[
  {
    "path": ".clang-format",
    "content": "---\nAllowShortBlocksOnASingleLine: 'true'\nAllowShortCaseLabelsOnASingleLine: 'true'\nAllowShortIfStatementsOnASingleLine: 'true'\nAllowShortLoopsOnASingleLine: 'true'\nAlwaysBreakAfterReturnType: TopLevel\nAccessModifierOffset: -8\nBreakBeforeBraces: Linux\nColumnLimit: 160\nIndentCaseLabels: 'false'\nIndentWidth: '8'\nLanguage: Cpp\nPointerAlignment: Right\nSpaceAfterCStyleCast: 'false'\nSpaceBeforeAssignmentOperators: 'true'\nSpaceBeforeCtorInitializerColon: 'true'\nSpaceBeforeInheritanceColon: 'true'\nSpaceBeforeParens: Never\nSpaceInEmptyParentheses: 'false'\nSpacesInAngles: 'false'\nSpacesInCStyleCastParentheses: 'false'\nSpacesInContainerLiterals: 'false'\nSpacesInParentheses: 'false'\nSpacesInSquareBrackets: 'false'\nTabWidth: '8'\nUseTab: ForIndentation\n\n...\n"
  },
  {
    "path": ".gitattributes",
    "content": "sdk/* linguist-vendored\nvendor/* linguist-vendored"
  },
  {
    "path": ".github/pull_request_template.md",
    "content": "As long as it's not linux/cross-platform skeleton/compatibility layer, all of the code on the repo that's not behind a preprocessor condition(like FIX_BUGS) are **completely** reversed code from original binaries.  \n\nWe **don't** accept custom codes, as long as it's not wrapped via preprocessor conditions, or it's linux/cross-platform skeleton/compatibility layer.\n\nWe accept only these kinds of PRs;\n\n- A new feature that exists in at least one of the GTAs (if it wasn't in III/VC then it doesn't have to be decompilation)  \n- Game, UI or UX bug fixes (if it's a fix to R* code, it should be behind FIX_BUGS)\n- Platform-specific and/or unused code that's not been reversed yet\n- Makes reversed code more understandable/accurate, as in \"which code would produce this assembly\".\n- A new cross-platform skeleton/compatibility layer, or improvements to them\n- Translation fixes, for languages R* supported/outsourced\n- Code that increase maintainability\n"
  },
  {
    "path": ".github/workflows/build-cmake-conan.yml",
    "content": "name: reLCS conan+cmake\non:\n  pull_request:\n  push:\n  release:\n    types: published\njobs:\n  build-cmake:\n    strategy:\n      matrix:\n        include:\n          - os: 'windows-latest'\n            platform: 'gl3'\n            gl3_gfxlib: 'glfw'\n            audio: 'openal'\n#          - os: 'windows-latest'\n#            platform: 'gl3'\n#            gl3_gfxlib: 'sdl2'\n#            audio: 'openal'\n          - os: 'windows-latest'\n            platform: 'd3d9'\n            audio: 'openal'\n#          - os: 'windows-latest'\n#            platform: 'd3d9'\n#            audio: 'miles'\n          - os: 'ubuntu-latest'\n            platform: 'gl3'\n            gl3_gfxlib: 'glfw'\n            audio: 'openal'\n#          - os: 'ubuntu-latest'\n#            platform: 'gl3'\n#            gl3_gfxlib: 'sdl2'\n#            audio: 'openal'\n          - os: 'macos-latest'\n            platform: 'gl3'\n            gl3_gfxlib: 'glfw'\n            audio: 'openal'\n#          - os: 'macos-latest'\n#            platform: 'gl3'\n#            gl3_gfxlib: 'sdl2'\n#            audio: 'openal'\n    runs-on: ${{ matrix.os }}\n    continue-on-error: ${{ matrix.platform == 'ps2' || matrix.gl3_gfxlib == 'sdl2' || matrix.audio == 'miles' }}\n    steps:\n      - uses: actions/checkout@v2\n        with:\n          submodules: true\n      - name: \"Checkout Miles SDK Import Library project\"\n        uses: actions/checkout@v2\n        if: ${{ matrix.audio == 'miles' }}\n        with:\n          repository: 'withmorten/re3mss'\n          path: 're3mss'\n      - uses: actions/setup-python@v2\n        with:\n          python-version: '3.x'\n      - name: \"Use XCode 11 as default (conan-center-index does not provide XCode 12 binaries at the moment)\"\n        if: startsWith(matrix.os, 'macos')\n        run: |\n          sudo xcode-select --switch /Applications/Xcode_11.7.app\n      - name: \"Setup conan\"\n        run: |\n          python -m pip install conan\n          conan config init\n          conan config set log.print_run_commands=True\n          conan remote add bincrafters https://api.bintray.com/conan/bincrafters/public-conan\n          conan remote add madebr_ps2dev https://api.bintray.com/conan/madebr/ps2dev\n      - name: \"Add os=playstation2 + gcc.version=3.2 to .conan/settings.yml\"\n        shell: python\n        run: |\n          import os, yaml\n          settings_path = os.path.expanduser(\"~/.conan/settings.yml\")\n          yml = yaml.safe_load(open(settings_path))\n          yml[\"os\"][\"playstation2\"] = None\n          yml[\"compiler\"][\"gcc\"][\"version\"].append(\"3.2\")\n          yml[\"compiler\"][\"gcc\"][\"version\"].sort()\n          yaml.safe_dump(yml, open(settings_path, \"w\"))\n      - name: \"Create host profile\"\n        shell: bash\n        run: |\n          if test \"${{ matrix.platform }}\" = \"ps2\"; then\n            cp vendor/librw/conan/playstation2 host_profile\n          else\n            cp ~/.conan/profiles/default host_profile\n          fi\n      - name: \"Export Playstation 2 CMake toolchain conan recipe\"\n        run: |\n          conan export vendor/librw/cmake/ps2toolchain ps2dev-cmaketoolchain/master@\n      - name: \"Export librw conan recipe\"\n        run: |\n          conan export vendor/librw librw/master@\n      - name: \"Export Miles SDK conan recipe\"\n        if: ${{ matrix.audio == 'miles' }}\n        run: |\n          conan export re3mss miles-sdk/master@\n      - name: \"Download/build dependencies (conan install)\"\n        run: |\n          conan install ${{ github.workspace }} reLCS/master@ -if build -o reLCS:audio=${{ matrix.audio }} -o librw:platform=${{ matrix.platform }} -o librw:gl3_gfxlib=${{ matrix.gl3_gfxlib || 'glfw' }} --build missing -pr:h ./host_profile -pr:b default -s reLCS:build_type=RelWithDebInfo -s librw:build_type=RelWithDebInfo\n        env:\n          CONAN_SYSREQUIRES_MODE: enabled\n      - name: \"Build reLCS (conan build)\"\n        run: |\n          conan build ${{ github.workspace }} -if build -bf build -pf package\n      - name: \"Package reLCS (conan package)\"\n        run: |\n          conan package ${{ github.workspace }} -if build -bf build -pf package\n      - name: \"Create binary package (cpack)\"\n        working-directory: ./build\n        run: |\n          cpack -C RelWithDebInfo\n      - name: \"Archive binary package (github artifacts)\"\n        uses: actions/upload-artifact@v2\n        with:\n          name: \"${{ matrix.os }}-${{ matrix.platform }}\"\n          path: build/*.tar.xz\n          if-no-files-found: error\n"
  },
  {
    "path": ".github/workflows/msbuildvc.yml",
    "content": "name: MSBuild_vc\n\non: [push]\n\nenv:\n  # Path to the solution file relative to the root of the project.\n  SOLUTION_FILE_PATH: .\n\n  # Configuration type to build.\n  # You can convert this to a build matrix if you need coverage of multiple configuration types.\n  # https://docs.github.com/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix\n  BUILD_CONFIGURATION: Release\n\njobs:\n  build:\n    runs-on: windows-latest\n\n    steps:\n    - uses: actions/checkout@v2\n\n    - name: Add MSBuild to PATH\n      uses: microsoft/setup-msbuild@v1\n\n    - name: Build\n      working-directory: ${{env.SOLUTION_FILE_PATH}}\n      # Add additional options to the MSBuild command line here (like platform or verbosity level).\n      # See https://docs.microsoft.com/visualstudio/msbuild/msbuild-command-line-reference\n      run: |\n        git submodule update --init --recursive\n        .\\premake-vs2019.cmd\n        msbuild /m /p:Configuration=Release build/reVC.sln\n"
  },
  {
    "path": ".github/workflows/msbuildvcAyml",
    "content": "name: MSBuild_vc\n\non: [push]\n\nenv:\n  # Path to the solution file relative to the root of the project.\n  SOLUTION_FILE_PATH: .\n\n  # Configuration type to build.\n  # You can convert this to a build matrix if you need coverage of multiple configuration types.\n  # https://docs.github.com/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix\n  BUILD_CONFIGURATION: Release\n\njobs:\n  build:\n    runs-on: windows-latest\n\n    steps:\n    - uses: actions/checkout@v2\n\n    - name: Add MSBuild to PATH\n      uses: microsoft/setup-msbuild@v1\n\n    - name: Build\n      working-directory: ${{env.SOLUTION_FILE_PATH}}\n      # Add additional options to the MSBuild command line here (like platform or verbosity level).\n      # See https://docs.microsoft.com/visualstudio/msbuild/msbuild-command-line-reference\n      run: |\n        .\\premake-vs2019.cmd\n        msbuild /m /p:Configuration=${{env.BUILD_CONFIGURATION}} .\\build\\reVC.sln\n"
  },
  {
    "path": ".github/workflows/reLCS_msvc_amd64.yml",
    "content": "name: reLCS premake amd64\n\non:\n  pull_request:\n  push:\n  release:\n    types: published\nenv:\n  GLFW_VER: \"3.3.2\"\n  GLFW_BASE: \"glfw-3.3.2.bin.WIN64\"\n  GLFW_FILE: \"glfw-3.3.2.bin.WIN64.zip\"\n  GLFW_URL: \"https://github.com/glfw/glfw/releases/download/3.3.2/glfw-3.3.2.bin.WIN64.zip\"\njobs:\n  build:\n    runs-on: windows-2019\n    strategy:\n      matrix:\n        platform: [win-amd64-librw_d3d9-oal, win-amd64-librw_gl3_glfw-oal]\n        buildtype: [Debug, Release]\n    steps:\n    - name: Add msbuild to PATH\n      uses: microsoft/setup-msbuild@v1.0.2\n    - uses: actions/checkout@v2\n      with:\n        submodules: 'true'\n    - if: ${{ matrix.platform }} == \"win-amd64-librw_gl3_glfw-mss\"\n      name: Download glfw\n      uses: carlosperate/download-file-action@v1.0.3\n      with:\n        file-url: ${{env.GLFW_URL}}\n    - if: ${{ matrix.platform }} == \"win-amd64-librw_gl3_glfw-mss\"\n      name: Unpack archives\n      run: |\n          7z x ${{env.GLFW_FILE}}\n    - name: Configure build\n      run: |\n        ./premake5 vs2019 --with-librw --glfwdir64=${{env.GLFW_BASE}}\n    - name: Build\n      run: |\n        msbuild -m build/reLCS.sln /property:Configuration=${{matrix.buildtype}} /property:Platform=${{matrix.platform}}\n    # - name: Pack artifacts\n      # run: |\n        # 7z a reLCS_${{matrix.buildtype}}_${{matrix.platform}}.zip ./bin/${{matrix.platform}}/${{matrix.buildtype}}/*\n    - name: Move binaries to gamefiles\n      run: |\n        mv ./bin/${{matrix.platform}}/${{matrix.buildtype}}/reLCS.exe ./gamefiles/\n        mv ./bin/${{matrix.platform}}/${{matrix.buildtype}}/reLCS.pdb ./gamefiles/\n    - name: Move dynamic dependencies to gamefiles\n      run: |\n        mv ./vendor/mpg123/dist/Win64/libmpg123-0.dll ./gamefiles/\n        mv ./vendor/openal-soft/dist/Win64/OpenAL32.dll ./gamefiles/\n    - name: Upload artifact to actions\n      uses: actions/upload-artifact@v2\n      with:\n        name: reLCS_${{matrix.buildtype}}_${{matrix.platform}}\n        path: ./gamefiles/*\n#    - name: Upload artifact to Bintray\n#      uses: hpcsc/upload-bintray-docker-action@v1\n#      with:\n#        repository: reLCS\n#        package: ${{matrix.buildtype}}_${{matrix.platform}}\n#        version:  1.0-$(echo ${GITHUB_SHA}\n#        sourcePath: ./bin/${{matrix.platform}}/${{matrix.buildtype}}\n#        username: gtamodding\n#        apiKey: ${{secrets.BINTRAY_API_KEY}}\n"
  },
  {
    "path": ".github/workflows/reLCS_msvc_x86.yml",
    "content": "name: reLCS premake x86\n\non:\n  pull_request:\n  push:\n  release:\n    types: published\nenv:\n  GLFW_VER: \"3.3.2\"\n  GLFW_BASE: \"glfw-3.3.2.bin.WIN32\"\n  GLFW_FILE: \"glfw-3.3.2.bin.WIN32.zip\"\n  GLFW_URL: \"https://github.com/glfw/glfw/releases/download/3.3.2/glfw-3.3.2.bin.WIN32.zip\"\njobs:\n  build:\n    runs-on: windows-2019\n    strategy:\n      matrix:\n        platform: [win-x86-librw_d3d9-mss, win-x86-librw_gl3_glfw-mss, win-x86-librw_d3d9-oal, win-x86-librw_gl3_glfw-oal]\n        buildtype: [Debug, Release]\n    steps:\n    - name: Add msbuild to PATH\n      uses: microsoft/setup-msbuild@v1.0.2\n    - uses: actions/checkout@v2\n      with:\n        submodules: 'true'\n    - if: ${{ matrix.platform }} == \"win-x86-librw_gl3_glfw-mss\"\n      name: Download glfw\n      uses: carlosperate/download-file-action@v1.0.3\n      with:\n        file-url: ${{env.GLFW_URL}}\n    - if: ${{ matrix.platform }} == \"win-x86-librw_gl3_glfw-mss\"\n      name: Unpack archives\n      run: |\n          7z x ${{env.GLFW_FILE}}\n    - name: Configure build\n      run: |\n        ./premake5 vs2019 --with-librw --glfwdir32=${{env.GLFW_BASE}}\n    - name: Build\n      run: |\n        msbuild -m build/reLCS.sln /property:Configuration=${{matrix.buildtype}} /property:Platform=${{matrix.platform}}\n    # - name: Pack artifacts\n      # run: |\n        # 7z a reLCS_${{matrix.buildtype}}_${{matrix.platform}}.zip ./bin/${{matrix.platform}}/${{matrix.buildtype}}/*\n    - name: Move binaries to gamefiles\n      run: |\n        mv ./bin/${{matrix.platform}}/${{matrix.buildtype}}/reLCS.exe ./gamefiles/\n        mv ./bin/${{matrix.platform}}/${{matrix.buildtype}}/reLCS.pdb ./gamefiles/\n    - if: contains(matrix.platform, 'oal')\n      name: Move dynamic dependencies to gamefiles\n      run: |\n        mv ./vendor/mpg123/dist/Win32/libmpg123-0.dll ./gamefiles/\n        mv ./vendor/openal-soft/dist/Win32/OpenAL32.dll ./gamefiles/\n    - name: Upload artifact to actions\n      uses: actions/upload-artifact@v2\n      with:\n        name: reLCS_${{matrix.buildtype}}_${{matrix.platform}}\n        path: ./gamefiles/*\n#    - name: Upload artifact to Bintray\n#      uses: hpcsc/upload-bintray-docker-action@v1\n#      with:\n#        repository: reLCS\n#        package: ${{matrix.buildtype}}_${{matrix.platform}}\n#        version:  1.0-$(echo ${GITHUB_SHA}\n#        sourcePath: ./bin/${{matrix.platform}}/${{matrix.buildtype}}\n#        username: gtamodding\n#        apiKey: ${{secrets.BINTRAY_API_KEY}}\n\n"
  },
  {
    "path": ".github/workflows/reVC_msvc_amd64.yml",
    "content": "name: reVC premake amd64\n\non:\n  pull_request:\n  push:\n  release:\n    types: published\nenv:\n  GLFW_VER: \"3.3.2\"\n  GLFW_BASE: \"glfw-3.3.2.bin.WIN64\"\n  GLFW_FILE: \"glfw-3.3.2.bin.WIN64.zip\"\n  GLFW_URL: \"https://github.com/glfw/glfw/releases/download/3.3.2/glfw-3.3.2.bin.WIN64.zip\"\njobs:\n  build:\n    runs-on: windows-2019\n    strategy:\n      matrix:\n        platform: [win-amd64-librw_d3d9-oal, win-amd64-librw_gl3_glfw-oal]\n        buildtype: [Debug, Release, Vanilla]\n    steps:\n    - name: Add msbuild to PATH\n      uses: microsoft/setup-msbuild@v1.0.2\n    - uses: actions/checkout@v2\n      with:\n        submodules: 'true'\n    - if: ${{ matrix.platform }} == \"win-amd64-librw_gl3_glfw-mss\"\n      name: Download glfw\n      uses: carlosperate/download-file-action@v1.0.3\n      with:\n        file-url: ${{env.GLFW_URL}}\n    - if: ${{ matrix.platform }} == \"win-amd64-librw_gl3_glfw-mss\"\n      name: Unpack archives\n      run: |\n          7z x ${{env.GLFW_FILE}}\n    - name: Configure build\n      run: |\n        ./premake5 vs2019 --with-librw --glfwdir64=${{env.GLFW_BASE}}\n    - name: Build\n      run: |\n        msbuild -m build/reVC.sln /property:Configuration=${{matrix.buildtype}} /property:Platform=${{matrix.platform}}\n    # - name: Pack artifacts\n      # run: |\n        # 7z a reVC_${{matrix.buildtype}}_${{matrix.platform}}.zip ./bin/${{matrix.platform}}/${{matrix.buildtype}}/*\n    - name: Move binaries to gamefiles\n      run: |\n        mv ./bin/${{matrix.platform}}/${{matrix.buildtype}}/reVC.exe ./gamefiles/\n        mv ./bin/${{matrix.platform}}/${{matrix.buildtype}}/reVC.pdb ./gamefiles/\n    - name: Move dynamic dependencies to gamefiles\n      run: |\n        mv ./vendor/mpg123/dist/Win64/libmpg123-0.dll ./gamefiles/\n        mv ./vendor/openal-soft/dist/Win64/OpenAL32.dll ./gamefiles/\n    - name: Upload artifact to actions\n      uses: actions/upload-artifact@v2\n      with:\n        name: reVC_${{matrix.buildtype}}_${{matrix.platform}}\n        path: ./gamefiles/*\n#    - name: Upload artifact to Bintray\n#      uses: hpcsc/upload-bintray-docker-action@v1\n#      with:\n#        repository: reVC\n#        package: ${{matrix.buildtype}}_${{matrix.platform}}\n#        version:  1.0-$(echo ${GITHUB_SHA}\n#        sourcePath: ./bin/${{matrix.platform}}/${{matrix.buildtype}}\n#        username: gtamodding\n#        apiKey: ${{secrets.BINTRAY_API_KEY}}\n"
  },
  {
    "path": ".github/workflows/reVC_msvc_x86.yml",
    "content": "name: reVC premake x86\n\non:\n  pull_request:\n  push:\n  release:\n    types: published\nenv:\n  GLFW_VER: \"3.3.2\"\n  GLFW_BASE: \"glfw-3.3.2.bin.WIN32\"\n  GLFW_FILE: \"glfw-3.3.2.bin.WIN32.zip\"\n  GLFW_URL: \"https://github.com/glfw/glfw/releases/download/3.3.2/glfw-3.3.2.bin.WIN32.zip\"\njobs:\n  build:\n    runs-on: windows-2019\n    strategy:\n      matrix:\n        platform: [win-x86-librw_d3d9-mss, win-x86-librw_gl3_glfw-mss, win-x86-librw_d3d9-oal, win-x86-librw_gl3_glfw-oal]\n        buildtype: [Debug, Release, Vanilla]\n    steps:\n    - name: Add msbuild to PATH\n      uses: microsoft/setup-msbuild@v1.0.2\n    - uses: actions/checkout@v2\n      with:\n        submodules: 'true'\n    - if: ${{ matrix.platform }} == \"win-x86-librw_gl3_glfw-mss\"\n      name: Download glfw\n      uses: carlosperate/download-file-action@v1.0.3\n      with:\n        file-url: ${{env.GLFW_URL}}\n    - if: ${{ matrix.platform }} == \"win-x86-librw_gl3_glfw-mss\"\n      name: Unpack archives\n      run: |\n          7z x ${{env.GLFW_FILE}}\n    - name: Configure build\n      run: |\n        ./premake5 vs2019 --with-librw --glfwdir32=${{env.GLFW_BASE}}\n    - name: Build\n      run: |\n        msbuild -m build/reVC.sln /property:Configuration=${{matrix.buildtype}} /property:Platform=${{matrix.platform}}\n    # - name: Pack artifacts\n      # run: |\n        # 7z a reVC_${{matrix.buildtype}}_${{matrix.platform}}.zip ./bin/${{matrix.platform}}/${{matrix.buildtype}}/*\n    - name: Move binaries to gamefiles\n      run: |\n        mv ./bin/${{matrix.platform}}/${{matrix.buildtype}}/reVC.exe ./gamefiles/\n        mv ./bin/${{matrix.platform}}/${{matrix.buildtype}}/reVC.pdb ./gamefiles/\n    - if: contains(matrix.platform, 'oal')\n      name: Move dynamic dependencies to gamefiles\n      run: |\n        mv ./vendor/mpg123/dist/Win32/libmpg123-0.dll ./gamefiles/\n        mv ./vendor/openal-soft/dist/Win32/OpenAL32.dll ./gamefiles/\n    - name: Upload artifact to actions\n      uses: actions/upload-artifact@v2\n      with:\n        name: reVC_${{matrix.buildtype}}_${{matrix.platform}}\n        path: ./gamefiles/*\n#    - name: Upload artifact to Bintray\n#      uses: hpcsc/upload-bintray-docker-action@v1\n#      with:\n#        repository: reVC\n#        package: ${{matrix.buildtype}}_${{matrix.platform}}\n#        version:  1.0-$(echo ${GITHUB_SHA}\n#        sourcePath: ./bin/${{matrix.platform}}/${{matrix.buildtype}}\n#        username: gtamodding\n#        apiKey: ${{secrets.BINTRAY_API_KEY}}\n\n"
  },
  {
    "path": ".gitignore",
    "content": "## 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# Mono auto generated files\nmono_crash.*\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[Bb]uild/\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\nnunit-*.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# NuGet Symbol Packages\n*.snupkg\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*.appxbundle\n*.appxupload\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\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*- [Bb]ackup.rdl\n*- [Bb]ackup ([0-9]).rdl\n*- [Bb]ackup ([0-9][0-9]).rdl\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# 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# Backup folder for Package Reference Convert tool in Visual Studio 2017\nMigrationBackup/\n\nvendor/glew-2.1.0/\nvendor/glfw-3.3.2.bin.WIN32/\nvendor/glfw-3.3.2.bin.WIN64/\n\nsdk/\n\ncodewarrior/reVC_Data/\ncodewarrior/Release/\ncodewarrior/Debug/\n\nsrc/extras/GitSHA1.cpp"
  },
  {
    "path": ".gitmodules",
    "content": "[submodule \"vendor/ogg\"]\n\tpath = vendor/ogg\n\turl = https://github.com/xiph/ogg.git\n\tbranch = master\n[submodule \"vendor/opus\"]\n\tpath = vendor/opus\n\turl = https://github.com/xiph/opus.git\n\tbranch = master\n[submodule \"vendor/opusfile\"]\n\tpath = vendor/opusfile\n\turl = https://github.com/xiph/opusfile.git\n\tbranch = master\n[submodule \"vendor/librw\"]\n\tpath = vendor/librw\n\turl = https://github.com/aap/librw.git\n\tbranch = master\n"
  },
  {
    "path": ".vscode/c_cpp_properties.json",
    "content": "{\n  \"configurations\": [\n    {\n      \"name\": \"Mac\",\n      \"includePath\": [\"${default}\"],\n      \"defines\": [],\n      \"macFrameworkPath\": [\n        \"/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks\"\n      ],\n      \"compilerPath\": \"/opt/local/bin/clang\",\n      \"compilerArgs\": [\"-g\"],\n      \"cStandard\": \"gnu11\",\n      \"cppStandard\": \"gnu++14\",\n      \"browse\": {\n        \"path\": [\n          \"/opt/local/include\",\n          \"/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include\"\n        ]\n      }\n    },\n    {\n      \"name\": \"Linux\",\n      \"includePath\": [\"${default}\"],\n      \"defines\": [\"XDG_ROOT\"],\n      \"compilerPath\": \"/usr/bin/gcc\",\n      \"compilerArgs\": [\"-ggdb\"],\n      \"cStandard\": \"gnu11\",\n      \"cppStandard\": \"gnu++14\"\n    }\n  ],\n  \"version\": 4\n}\n"
  },
  {
    "path": ".vscode/launch.json",
    "content": "{\n  \"configurations\": [\n    {\n      \"MIMode\": \"gdb\",\n      \"args\": [],\n      \"cwd\": \"${workspaceFolder}\",\n      \"environment\": [],\n      \"externalConsole\": false,\n      \"name\": \"(gdb) Launch (Linux Debug)\",\n      \"preLaunchTask\": \"Compile (Debug Linux x64)\",\n      \"program\": \"${workspaceFolder}/bin/linux-amd64-librw_gl3_glfw-oal/Debug/re3\",\n      \"request\": \"launch\",\n      \"setupCommands\": [\n        {\n          \"description\": \"Enable pretty-printing for gdb\",\n          \"ignoreFailures\": true,\n          \"text\": \"-enable-pretty-printing\"\n        }\n      ],\n      \"stopAtEntry\": false,\n      \"targetArchitecture\": \"x64\",\n      \"type\": \"cppdbg\"\n    },\n    {\n      \"MIMode\": \"gdb\",\n      \"args\": [],\n      \"cwd\": \"${workspaceFolder}\",\n      \"environment\": [],\n      \"externalConsole\": false,\n      \"name\": \"(gdb) Launch (Linux Release)\",\n      \"preLaunchTask\": \"Compile (Release Linux x64)\",\n      \"program\": \"${workspaceFolder}/bin/linux-amd64-librw_gl3_glfw-oal/Release/re3\",\n      \"request\": \"launch\",\n      \"setupCommands\": [\n        {\n          \"description\": \"Enable pretty-printing for gdb\",\n          \"ignoreFailures\": true,\n          \"text\": \"-enable-pretty-printing\"\n        }\n      ],\n      \"stopAtEntry\": false,\n      \"targetArchitecture\": \"x64\",\n      \"type\": \"cppdbg\"\n    },\n    {\n      \"MIMode\": \"lldb\",\n      \"args\": [],\n      \"cwd\": \"${workspaceFolder}\",\n      \"environment\": [],\n      \"externalConsole\": false,\n      \"name\": \"(lldb) Launch (macOS Debug)\",\n      \"preLaunchTask\": \"Compile (Debug macOS x64)\",\n      \"program\": \"${workspaceFolder}/bin/macosx-amd64-librw_gl3_glfw-oal/Debug/re3.app\",\n      \"request\": \"launch\",\n      \"setupCommands\": [\n        {\n          \"description\": \"Enable pretty-printing for lldb\",\n          \"ignoreFailures\": true,\n          \"text\": \"-enable-pretty-printing\"\n        }\n      ],\n      \"stopAtEntry\": false,\n      \"targetArchitecture\": \"x64\",\n      \"type\": \"cppdbg\"\n    },\n    {\n      \"MIMode\": \"lldb\",\n      \"args\": [],\n      \"cwd\": \"${workspaceFolder}\",\n      \"environment\": [],\n      \"externalConsole\": false,\n      \"name\": \"(lldb) Launch (macOS Release)\",\n      \"preLaunchTask\": \"Compile (Release macOS x64)\",\n      \"program\": \"${workspaceFolder}/bin/macosx-amd64-librw_gl3_glfw-oal/Release/re3.app\",\n      \"request\": \"launch\",\n      \"setupCommands\": [\n        {\n          \"description\": \"Enable pretty-printing for lldb\",\n          \"ignoreFailures\": true,\n          \"text\": \"-enable-pretty-printing\"\n        }\n      ],\n      \"stopAtEntry\": false,\n      \"targetArchitecture\": \"x64\",\n      \"type\": \"cppdbg\"\n    }\n  ],\n  \"version\": \"0.2.0\"\n}\n"
  },
  {
    "path": ".vscode/settings.json",
    "content": "{\n  \"C_Cpp.default.cStandard\": \"gnu11\",\n  \"C_Cpp.default.cppStandard\": \"gnu++14\",\n  \"C_Cpp.default.includePath\": [\n    \"src/animation\",\n    \"src/audio\",\n    \"src/control\",\n    \"src/core\",\n    \"src/entities\",\n    \"src/extras\",\n    \"src/fakerw\",\n    \"src/math\",\n    \"src/modelinfo\",\n    \"src/objects\",\n    \"src/peds\",\n    \"src/render\",\n    \"src/rw\",\n    \"src/save\",\n    \"src/skel\",\n    \"src/text\",\n    \"src/vehicles\",\n    \"src/weapons\",\n    \"vendor/librw\"\n  ],\n  \"C_Cpp.vcFormat.indent.gotoLabels\": \"leftmostColumn\",\n  \"C_Cpp.vcFormat.space.pointerReferenceAlignment\": \"right\",\n  \"cSpell.enabled\": false,\n  \"files.trimFinalNewlines\": false,\n  \"files.trimTrailingWhitespace\": false\n}\n"
  },
  {
    "path": ".vscode/tasks.json",
    "content": "{\n  \"tasks\": [\n    {\n      \"args\": [\"--with-librw\", \"gmake2\"],\n      \"command\": \"./premake5Linux\",\n      \"label\": \"Premake (Linux)\",\n      \"problemMatcher\": \"$gcc\",\n      \"type\": \"shell\"\n    },\n    {\n      \"args\": [\"--with-librw\", \"gmake2\"],\n      \"command\": \"premake5\",\n      \"label\": \"Premake (macOS)\",\n      \"problemMatcher\": \"$gcc\",\n      \"type\": \"shell\"\n    },\n    {\n      \"args\": [\n        \"-j5\",\n        \"config=debug_linux-amd64-librw_gl3_glfw-oal\",\n        \"verbose=1\"\n      ],\n      \"command\": \"make\",\n      \"dependsOn\": \"Premake (Linux)\",\n      \"group\": {\n        \"isDefault\": true,\n        \"kind\": \"build\"\n      },\n      \"label\": \"Compile (Debug Linux x64)\",\n      \"options\": {\n        \"cwd\": \"${workspaceFolder}/build\"\n      },\n      \"problemMatcher\": \"$gcc\",\n      \"type\": \"shell\"\n    },\n    {\n      \"args\": [\n        \"-j5\",\n        \"config=release_linux-amd64-librw_gl3_glfw-oal\",\n        \"verbose=1\"\n      ],\n      \"command\": \"make\",\n      \"dependsOn\": \"Premake (Linux)\",\n      \"group\": {\n        \"isDefault\": true,\n        \"kind\": \"build\"\n      },\n      \"label\": \"Compile (Release Linux x64)\",\n      \"options\": {\n        \"cwd\": \"${workspaceFolder}/build\"\n      },\n      \"problemMatcher\": \"$gcc\",\n      \"type\": \"shell\"\n    },\n    {\n      \"args\": [\n        \"-j5\",\n        \"config=debug_macosx-amd64-librw_gl3_glfw-oal\",\n        \"verbose=1\"\n      ],\n      \"command\": \"make\",\n      \"dependsOn\": \"Premake (macOS)\",\n      \"group\": {\n        \"isDefault\": true,\n        \"kind\": \"build\"\n      },\n      \"label\": \"Compile (Debug macOS x64)\",\n      \"options\": {\n        \"cwd\": \"${workspaceFolder}/build\"\n      },\n      \"problemMatcher\": \"$gcc\",\n      \"type\": \"shell\"\n    },\n    {\n      \"args\": [\n        \"-j5\",\n        \"config=release_macosx-amd64-librw_gl3_glfw-oal\",\n        \"verbose=1\"\n      ],\n      \"command\": \"make\",\n      \"dependsOn\": \"Premake (macOS)\",\n      \"group\": {\n        \"isDefault\": true,\n        \"kind\": \"build\"\n      },\n      \"label\": \"Compile (Release macOS x64)\",\n      \"options\": {\n        \"cwd\": \"${workspaceFolder}/build\"\n      },\n      \"problemMatcher\": \"$gcc\",\n      \"type\": \"shell\"\n    }\n  ],\n  \"version\": \"2.0.0\"\n}\n"
  },
  {
    "path": "CMakeLists.txt",
    "content": "cmake_minimum_required(VERSION 3.8)\n\nset(EXECUTABLE reVC)\nset(PROJECT REVC)\n\nproject(${EXECUTABLE} C CXX)\nlist(APPEND CMAKE_MODULE_PATH \"${PROJECT_SOURCE_DIR}/cmake\")\n\ninclude(GetGitRevisionDescription)\nget_git_head_revision(GIT_REFSPEC GIT_SHA1 \"ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR\")\nmessage(STATUS \"Building ${CMAKE_PROJECT_NAME} GIT SHA1: ${GIT_SHA1}\")\n\nif(WIN32)\n    set(${PROJECT}_AUDIOS \"OAL\" \"MSS\")\nelse()\n    set(${PROJECT}_AUDIOS \"OAL\")\nendif()\n\nset(${PROJECT}_AUDIO \"OAL\" CACHE STRING \"Audio\")\n\noption(${PROJECT}_WITH_OPUS \"Build ${EXECUTABLE} with opus support\" OFF)\noption(${PROJECT}_WITH_LIBSNDFILE \"Build ${EXECUTABLE} with libsndfile (instead of internal decoder)\" OFF)\n\nset_property(CACHE ${PROJECT}_AUDIO PROPERTY STRINGS ${${PROJECT}_AUDIOS})\nmessage(STATUS \"${PROJECT}_AUDIO = ${${PROJECT}_AUDIO} (choices=${${PROJECT}_AUDIOS})\")\nset(\"${PROJECT}_AUDIO_${${PROJECT}_AUDIO}\" ON)\nif(NOT ${PROJECT}_AUDIO IN_LIST ${PROJECT}_AUDIOS)\n    message(FATAL_ERROR \"Illegal ${PROJECT}_AUDIO=${${PROJECT}_AUDIO}\")\nendif()\n\noption(${PROJECT}_VENDORED_LIBRW \"Use vendored librw\" ON)\nif(${PROJECT}_VENDORED_LIBRW)\n    add_subdirectory(vendor/librw)\nelse()\n    find_package(librw REQUIRED)\nendif()\nadd_subdirectory(src)\n\nif(${PROJECT}_INSTALL)\n    install(DIRECTORY gamefiles/ DESTINATION \".\")\n    if(LIBRW_PLATFORM_NULL)\n        set(platform \"-null\")\n    elseif(LIBRW_PLATFORM_PS2)\n        set(platform \"-ps2\")\n    elseif(LIBRW_PLATFORM_GL3)\n        if(LIBRW_GL3_GFXLIB STREQUAL \"GLFW\")\n            set(platform \"-gl3-glfw\")\n        else()\n            set(platform \"-gl3-sdl2\")\n        endif()\n    elseif(LIBRW_PLATFORM_D3D9)\n        set(platform \"-d3d9\")\n    endif()\n    if(${PROJECT}_AUDIO_OAL)\n        set(audio \"-oal\")\n    elseif(${PROJECT}_AUDIO_MSS)\n        set(audio \"-mss\")\n    endif()\n    if(${PROJECT}_WITH_OPUS)\n        set(audio \"${audio}-opus\")\n    endif()\n    if(NOT LIBRW_PLATFORM_PS2)\n        if(WIN32)\n            set(os \"-win\")\n        elseif(APPLE)\n            set(os \"-apple\")\n        elseif(UNIX)\n            set(os \"-linux\")\n        else()\n            set(compiler \"-UNK\")\n            message(WARNING \"Unknown os. Created cpack package will be wrong. (override using cpack -P)\")\n        endif()\n    endif()\n\n    set(CPACK_PACKAGE_NAME \"${PROJECT_NAME}${platform}${audio}${os}${compiler}\")\n    set(CPACK_PACKAGE_DESCRIPTION_SUMMARY \"GTA III reversed\")\n    set(CPACK_PACKAGE_VENDOR \"GTAModding\")\n    # FIXME: missing license (https://github.com/GTAmodding/re3/issues/794)\n    # set(CPACK_PACKAGE_DESCRIPTION_FILE \"${PROJECT_SOURCE_DIR}/LICENSE\")\n    # set(CPACK_RESOURCE_FILE_LICENSE \"${PROJECT_SOURCE_DIR}/LICENSE\")\n    set(CPACK_PACKAGE_INSTALL_DIRECTORY \"${CPACK_PACKAGE_NAME}\")\n    set(CPACK_SOURCE_PACKAGE_FILE_NAME \"${CPACK_PACKAGE_NAME}\")\n    set(CPACK_PACKAGE_FILE_NAME \"${CPACK_PACKAGE_NAME}\")\n    set(CPACK_GENERATOR \"TXZ\")\n    include(CPack)\nendif()\n"
  },
  {
    "path": "CODING_STYLE.md",
    "content": "# Coding style\n\nI started writing in [Plan 9 style](http://man.cat-v.org/plan_9/6/style),\nbut realize that this is not the most popular style, so I'm willing to compromise.\nTry not to deviate too much so the code will look similar across the whole project.\n\nTo give examples, these two styles (or anything in between) are fine:\n\n```\ntype\nfunctionname(args)\n{\n\tif(a == b){\n\t\ts1;\n\t\ts2;\n\t}else{\n\t\ts3;\n\t\ts4;\n\t}\n\tif(x != y)\n\t\ts5;\n}\n\ntype functionname(args)\n{\n\tif (a == b) {\n\t\ts1;\n\t\ts2;\n\t} else {\n\t\ts3;\n\t\ts4;\n\t}\n\tif (x != y)\n\t\ts5;\n}\n```\n\nThis one (or anything more extreme) is heavily discouraged:\n\n```\ntype functionname ( args )\n{\n  if ( a == b )\n  {\n    s1;\n    s2;\n  }\n  else\n  {\n    s3;\n    s4;\n  }\n  if ( x != y )\n  {\n    s5;\n  }\n}\n```\n\ni.e. \n\n* Put the brace on the same line as control statements\n\n* Put the brace on the next line after function definitions and structs/classes\n\n* Put an `else` on the same line with the braces\n\n* Don't put braces around single statements\n\n* Put the function return type on a separate line\n\n* Indent with TABS\n\nAs for the less cosmetic choices, here are some guidelines how the code should look:\n\n* Don't use magic numbers where the original source code would have had an enum or similar.\nEven if you don't know the exact meaning it's better to call something `FOOBAR_TYPE_4` than just `4`,\nsince `4` will be used in other places and you can't easily see where else the enum value is used.\n\n* Don't just copy paste code from IDA, make it look nice\n\n* Use the right types. In particular:\n\n    * don't use types like `__int16`, we have `int16` for that\n\n    * don't use `unsigned`, we have typedefs for that\n\n    * don't use `char` for anything but actual characters, use `int8`, `uint8` or `bool`\n\n    * don't even think about using win32 types (`BYTE`, `WORD`, &c.) unless you're writing win32 specific code\n\n    * declare pointers like `int *ptr;`, not `int* ptr;`\n\n* As for variable names, the original gta source code was not written in a uniform style,\nbut here are some observations:\n\n    * many variables employ a form of hungarian notation, i.e.:\n\n    * `m_` may be used for class member variables (mostly those that are considered private)\n\n    * `ms_` for (mostly private) static members\n\n    * `f` is a float, `i` or `n` is an integer, `b` is a boolean, `a` is an array\n\n    * do *not* use `dw` for `DWORD` or so, we're not programming win32\n\n* Generally, try to make the code look as if R* could have written it\n"
  },
  {
    "path": "README.md",
    "content": "# Take Two, all of their employees, and anyone who supports them can go fuck themselves :). Sincerely, Starman. \n\n<img src=\"https://github.com/GTAmodding/re3/blob/miami/logo.png?raw=true\" alt=\"reVC logo\" width=\"200\">\n\n[![Build Status](https://img.shields.io/endpoint.svg?url=https%3A%2F%2Factions-badge.atrox.dev%2FGTAmodding%2Fre3%2Fbadge%3Fref%3Dmiami&style=flat)](https://actions-badge.atrox.dev/GTAmodding/re3/goto?ref=miami)\n<a href=\"https://discord.gg/ERYg58ttcE\"><img src=\"https://img.shields.io/badge/discord-join-7289DA.svg?logo=discord&longCache=true&style=flat\" /></a>\n\n## Intro\n\nIn this repository you'll find the fully reversed source code for GTA III ([master](https://github.com/GTAmodding/re3/tree/master/) branch) and GTA VC ([miami](https://github.com/GTAmodding/re3/tree/miami/) branch).\n\nIt has been tested and works on Windows, Linux and FreeBSD, on x86, amd64, arm and arm64.\\\nRendering is handled either by original RenderWare (D3D8)\nor the reimplementation [librw](https://github.com/aap/librw) (D3D9, OpenGL 2.1 or above, OpenGL ES 2.0 or above).\\\nAudio is done with MSS (using dlls from original GTA) or OpenAL.\n\nWe cannot build for PS2 or Xbox yet. If you're interested in doing so, get in touch with us.\n\n## How can I try it?\n\n- reVC requires game assets to work, so you **must** own [a copy of GTA Vice City](https://store.steampowered.com/app/12110/Grand_Theft_Auto_Vice_City/).\n- Build reVC or download the latest build:\n  - [Windows D3D9 MSS 32bit](https://nightly.link/GTAmodding/re3/workflows/reVC_msvc_x86/miami/reVC_Release_win-x86-librw_d3d9-mss.zip)\n  - [Windows D3D9 64bit](https://nightly.link/GTAmodding/re3/workflows/reVC_msvc_amd64/miami/reVC_Release_win-amd64-librw_d3d9-oal.zip)\n  - [Windows OpenGL 64bit](https://nightly.link/GTAmodding/re3/workflows/reVC_msvc_amd64/miami/reVC_Release_win-amd64-librw_gl3_glfw-oal.zip)\n  - [Linux 64bit](https://nightly.link/GTAmodding/re3/workflows/build-cmake-conan/miami/ubuntu-latest-gl3.zip)\n  - [MacOS 64bit](https://nightly.link/GTAmodding/re3/workflows/build-cmake-conan/miami/macos-latest-gl3.zip)\n- Extract the downloaded zip over your GTA VC directory and run reVC. The zip includes the gamefiles and in case of OpenAL the required dlls.\n\n## Screenshots\n\n![screen_ 1613087332](https://user-images.githubusercontent.com/1521437/107714111-f84f3200-6ccc-11eb-902e-d757481d579a.png)\n![screen_ 1613086852](https://user-images.githubusercontent.com/1521437/107714115-fa18f580-6ccc-11eb-9de5-eb4cd04865d3.png)\n![screen_ 1613086989](https://user-images.githubusercontent.com/1521437/107714103-f38a7e00-6ccc-11eb-88a3-c8c2033c51d6.png)\n![screen_ 1613087193](https://user-images.githubusercontent.com/1521437/107714106-f4bbab00-6ccc-11eb-96a9-13821d9b9684.png)\n\n## Improvements\n\nWe have implemented a number of changes and improvements to the original game.\nThey can be configured in `core/config.h`.\nSome of them can be toggled at runtime, some cannot.\n\n* Fixed a lot of smaller and bigger bugs\n* User files (saves and settings) stored in GTA root directory\n* Settings stored in reVC.ini file instead of gta_vc.set\n* Debug menu to do and change various things (Ctrl-M to open)\n* Debug camera (Ctrl-B to toggle)\n* Rotatable camera\n* XInput controller support (Windows)\n* No loading screens between islands (\"map memory usage\" in menu)\n* Rendering\n  * Widescreen support (properly scaled HUD, Menu and FOV)\n  * PS2 MatFX (vehicle reflections)\n  * PS2 alpha test (better rendering of transparency)\n  * Xbox vehicle rendering\n  * Xbox world lightmap rendering (needs Xbox map)\n  * Xbox ped rim light\n  * Xbox screen rain droplets\n  * More customizable colourfilter\n* Menu\n  * More options\n  * Controller configuration menu\n  * ...\n* Can load DFFs and TXDs from other platforms, possibly with a performance penalty\n* ...\n\n## To-Do\n\nThe following things would be nice to have/do:\n\n* Fix physics for high FPS\n* Improve performance on lower end devices, especially the OpenGL layer on the Raspberry Pi (if you have experience with this, please get in touch)\n* [PS2 port](https://github.com/GTAmodding/re3/wiki/PS2-port)\n* Xbox port (not quite as important)\n* reverse remaining unused/debug functions\n* compare CodeWarrior build with original binary for more accurate code (very tedious)\n\n## Modding\n\nAsset modifications (models, texture, handling, script, ...) should work the same way as with original GTA for the most part.\n\nMods that make changes to the code (dll/asi, CLEO, limit adjusters) will *not* work.\nSome things these mods do are already implemented in re3 (much of SkyGFX, GInput, SilentPatch, Widescreen fix),\nothers can easily be achieved (increasing limis, see `config.h`),\nothers will simply have to be rewritten and integrated into the code directly.\nSorry for the inconvenience.\n\n## Building from Source  \n\nWhen using premake, you may want to point GTA_VC_RE_DIR environment variable to GTA Vice City root folder if you want the executable to be moved there via post-build script.\n\nClone the repository with `git clone --recursive -b miami https://github.com/GTAmodding/re3.git reVC`. Then `cd reVC` into the cloned repository.\n\n<details><summary>Linux Premake</summary>\n\nFor Linux using premake, proceed: [Building on Linux](https://github.com/GTAmodding/re3/wiki/Building-on-Linux)\n\n</details>\n\n<details><summary>Linux Conan</summary>\n\nInstall python and conan, and then run build.\n```\nconan export vendor/librw librw/master@\nmkdir build\ncd build\nconan install .. reVC/master@ -if build -o reVC:audio=openal -o librw:platform=gl3 -o librw:gl3_gfxlib=glfw --build missing -s reVC:build_type=RelWithDebInfo -s librw:build_type=RelWithDebInfo\nconan build .. -if build -bf build -pf package\n```\n</details>\n\n<details><summary>FreeBSD</summary>\n\nFor FreeBSD using premake, proceed: [Building on FreeBSD](https://github.com/GTAmodding/re3/wiki/Building-on-FreeBSD)\n\n</details>\n\n<details><summary>Windows</summary>\n\nAssuming you have Visual Studio 2015/2017/2019:\n- Run one of the `premake-vsXXXX.cmd` variants on root folder.\n- Open build/reVC.sln with Visual Studio and compile the solution.\n    \nMicrosoft recently discontinued its downloads of the DX9 SDK. You can download an archived version here: https://archive.org/details/dxsdk_jun10\n\n**If you choose OpenAL on Windows** You must read [Running OpenAL build on Windows](https://github.com/GTAmodding/re3/wiki/Running-OpenAL-build-on-Windows).\n</details>\n\n> :information_source: premake has an `--lto` option if you want the project to be compiled with Link Time Optimization.\n\n> :information_source: There are various settings in [config.h](https://github.com/GTAmodding/re3/tree/miami/src/core/config.h), you may want to take a look there.\n\n> :information_source: reVC uses completely homebrew RenderWare-replacement rendering engine; [librw](https://github.com/aap/librw/). librw comes as submodule of re3, but you also can use LIBRW enviorenment variable to specify path to your own librw.\n\nIf you feel the need, you can also use CodeWarrior 7 to compile reVC using the supplied codewarrior/reVC.mcp project - this requires the original RW34 libraries, and the DX8 SDK. The build is unstable compared to the MSVC builds though, and is mostly meant to serve as a reference.\n\n## Contributing\nAs long as it's not linux/cross-platform skeleton/compatibility layer, all of the code on the repo that's not behind a preprocessor condition(like FIX_BUGS) are **completely** reversed code from original binaries.  \n\nWe **don't** accept custom codes, as long as it's not wrapped via preprocessor conditions, or it's linux/cross-platform skeleton/compatibility layer.\n\nWe accept only these kinds of PRs;\n\n- A new feature that exists in at least one of the GTAs (if it wasn't in III/VC then it doesn't have to be decompilation)  \n- Game, UI or UX bug fixes (if it's a fix to original code, it should be behind FIX_BUGS)\n- Platform-specific and/or unused code that's not been reversed yet\n- Makes reversed code more understandable/accurate, as in \"which code would produce this assembly\".\n- A new cross-platform skeleton/compatibility layer, or improvements to them\n- Translation fixes, for languages original game supported\n- Code that increase maintainability  \n\nWe have a [Coding Style](https://github.com/GTAmodding/re3/blob/master/CODING_STYLE.md) document that isn't followed or enforced very well.\n\nDo not use features from C++11 or later.\n\n\n## History\n\nre3 was started sometime in the spring of 2018,\ninitially as a way to test reversed collision and physics code\ninside the game.\nThis was done by replacing single functions of the game\nwith their reversed counterparts using a dll.\n\nAfter a bit of work the project lay dormant for about a year\nand was picked up again and pushed to github in May 2019.\nAt the time I (aap) had reversed around 10k lines of code and estimated\nthe final game to have around 200-250k.\nOthers quickly joined the effort (Fire_Head, shfil, erorcun and Nick007J\nin time order, and Serge a bit later) and we made very quick progress\nthroughout the summer of 2019\nafter which the pace slowed down a bit.\n\nDue to everyone staying home during the start of the Corona pandemic\neverybody had a lot of time to work on re3 again and\nwe finally got a standalone exe in April 2020 (around 180k lines by then).\n\nAfter the initial excitement and fixing and polishing the code further,\nreVC was started in early May 2020 by starting from re3 code,\nnot by starting from scratch replacing functions with a dll.\nAfter a few months of mostly steady progress we considered reVC\nfinished in December.\n\nSince then we have started reLCS, which is currently work in progress.\n\n\n## License\n\nWe don't feel like we're in a position to give this code a license.\\\nThe code should only be used for educational, documentation and modding purposes.\\\nWe do not encourage piracy or commercial use.\\\nPlease keep derivate work open source and give proper credit.\n"
  },
  {
    "path": "cmake/FindMilesSDK.cmake",
    "content": "# - Find Miles SDK\n# Find the Miles SDK header + import library\n#\n#  MilesSDK_INCLUDE_DIR - Where to find mss.h\n#  MilesSDK_LIBRARIES   - List of libraries when using MilesSDK.\n#  MilesSDK_FOUND       - True if Miles SDK found.\n#  MilesSDK::MilesSDK   - Imported library of Miles SDK\n\nfind_path(MilesSDK_INCLUDE_DIR mss.h\n    PATHS \"${MilesSDK_DIR}\"\n    PATH_SUFFIXES include\n)\n\nif(CMAKE_SIZEOF_VOID_P EQUAL 8)\n    set(_miles_sdk_libname mss64)\nelse()\n    set(_miles_sdk_libname mss32)\nendif()\n\nfind_library(MilesSDK_LIBRARIES NAMES ${_miles_sdk_libname}\n    PATHS \"${MilesSDK_DIR}\"\n    PATH_SUFFIXES lib\n)\n\ninclude(FindPackageHandleStandardArgs)\nfind_package_handle_standard_args(MilesSDK DEFAULT_MSG MilesSDK_LIBRARIES MilesSDK_INCLUDE_DIR)\n\nif(NOT TARGET MilesSDK::MilesSDK)\n    add_library(MilesSDK::MilesSDK UNKNOWN IMPORTED)\n    set_target_properties(MilesSDK::MilesSDK PROPERTIES\n        IMPORTED_LOCATION \"${MilesSDK_LIBRARIES}\n        INTERFACE_INCLUDE_DIRECTORIES \"${MilesSDK_INCLUDE_DIR}\"\n    )\nendif()\n"
  },
  {
    "path": "cmake/FindSndFile.cmake",
    "content": "# Found on http://hg.kvats.net\n#\n# - Try to find libsndfile\n# \n# Once done this will define\n#\n#  SNDFILE_FOUND        - system has libsndfile\n#  SNDFILE_INCLUDE_DIRS - the libsndfile include directory\n#  SNDFILE_LIBRARIES    - Link these to use libsndfile\n#  SNDFILE_CFLAGS       - Compile options to use libsndfile\n#  SndFile::SndFile     - Imported library of libsndfile\n#\n#  Copyright (C) 2006  Wengo\n#\n#  Redistribution and use is allowed according to the terms of the New\n#  BSD license.\n#  For details see the accompanying COPYING-CMAKE-SCRIPTS file.\n#\n\nfind_package(PkgConfig QUIET)\nif(PKG_CONFIG_FOUND)\n    pkg_search_module(PKG_SNDFILE \"sndfile\")\nendif()\n\nfind_path(SNDFILE_INCLUDE_DIR\n    NAMES\n        sndfile.h\n    HINTS\n        ${PKG_SNDFILE_INCLUDE_DIRS}\n    PATHS\n        /usr/include\n        /usr/local/include\n        /opt/local/include\n        /sw/include\n    )\n\nfind_library(SNDFILE_LIBRARY\n    NAMES\n        sndfile\n    HINTS\n        ${PKG_SNDFILE_LIBRARIES}\n    PATHS\n        /usr/lib\n        /usr/local/lib\n        /opt/local/lib\n        /sw/lib\n)\n\nset(SNDFILE_CFLAGS \"${PKG_SNDFILE_CFLAGS_OTHER}\" CACHE STRING \"CFLAGS of libsndfile\")\n\nset(SNDFILE_INCLUDE_DIRS \"${SNDFILE_INCLUDE_DIR}\")\nset(SNDFILE_LIBRARIES \"${SNDFILE_LIBRARY}\")\n\nif(SNDFILE_INCLUDE_DIRS AND SNDFILE_LIBRARIES)\n    set(SNDFILE_FOUND TRUE)\nendif()\n\ninclude(FindPackageHandleStandardArgs)\nfind_package_handle_standard_args(SndFile DEFAULT_MSG SNDFILE_INCLUDE_DIRS SNDFILE_LIBRARIES)\n\nif(NOT TARGET SndFile::SndFile)\n    add_library(__SndFile INTERFACE)\n    target_compile_options(__SndFile INTERFACE ${SNDFILE_CFLAGS})\n    target_include_directories(__SndFile INTERFACE ${SNDFILE_INCLUDE_DIRS})\n    target_link_libraries(__SndFile INTERFACE ${SNDFILE_LIBRARIES})\n    add_library(SndFile::SndFile ALIAS __SndFile)\nendif()\n"
  },
  {
    "path": "cmake/Findmpg123.cmake",
    "content": "# - Find mpg123\n# Find the native mpg123 includes and library\n#\n#  mpg123_INCLUDE_DIR - Where to find mpg123.h\n#  mpg123_LIBRARIES   - List of libraries when using mpg123.\n#  mpg123_CFLAGS      - Compile options to use mpg123\n#  mpg123_FOUND       - True if mpg123 found.\n#  MPG123::libmpg123  - Imported library of libmpg123\n\nfind_package(PkgConfig QUIET)\nif(PKG_CONFIG_FOUND)\n    pkg_search_module(PKG_MPG123 mpg123)\nendif()\n\nfind_path(mpg123_INCLUDE_DIR mpg123.h\n    HINTS ${PKG_MPG123_INCLUDE_DIRS}\n    PATHS \"${mpg123_DIR}\"\n    PATH_SUFFIXES include\n)\n\nfind_library(mpg123_LIBRARIES NAMES mpg123 mpg123-0\n    HINTS ${PKG_MPG123_LIBRARIES}\n    PATHS \"${mpg123_DIR}\"\n    PATH_SUFFIXES lib\n)\n\nset(mpg123_CFLAGS \"${PKG_MPG123_CFLAGS_OTHER}\" CACHE STRING \"CFLAGS of mpg123\")\n\ninclude(FindPackageHandleStandardArgs)\nfind_package_handle_standard_args(mpg123 DEFAULT_MSG mpg123_LIBRARIES mpg123_INCLUDE_DIR)\n\nif(NOT TARGET MPG123::libmpg123)\n    add_library(__libmpg123 INTERFACE)\n    target_compile_options(__libmpg123 INTERFACE ${mpg123_CFLAGS})\n    target_include_directories(__libmpg123 INTERFACE ${mpg123_INCLUDE_DIR})\n    target_link_libraries(__libmpg123 INTERFACE ${mpg123_LIBRARIES})\n    add_library(MPG123::libmpg123 ALIAS __libmpg123)\nendif()\n"
  },
  {
    "path": "cmake/Findopusfile.cmake",
    "content": "# - Try to find opusfile\n# \n# Once done this will define\n#\n#  OPUSFILE_FOUND        - system has opusfile\n#  OPUSFILE_INCLUDE_DIRS - the opusfile include directories\n#  OPUSFILE_LIBRARIES    - Link these to use opusfile\n#  OPUSFILE_CFLAGS       - Compile options to use opusfile\n#  opusfile::opusfile    - Imported library of opusfile\n#\n\n# FIXME: opusfile does not ship an official opusfile cmake script,\n# rename this file/variables/target when/if it has.\n\nfind_package(PkgConfig QUIET)\nif(PKG_CONFIG_FOUND)\n    pkg_search_module(PKG_OPUSFILE \"opusfile\")\nendif()\n\nfind_path(OPUSFILE_INCLUDE_DIR\n    NAMES\n        opusfile.h\n    PATH_SUFFIXES\n        opusfile\n    HINTS\n        ${PKG_OPUSFILE_INCLUDE_DIRS}\n    PATHS\n        /usr/include\n        /usr/local/include\n        /opt/local/include\n        /sw/include\n    )\n\nfind_library(OPUSFILE_LIBRARY\n    NAMES\n        opusfile\n    HINTS\n        ${PKG_OPUSFILE_LIBRARIES}\n    PATHS\n        /usr/lib\n        /usr/local/lib\n        /opt/local/lib\n        /sw/lib\n)\n\nset(OPUSFILE_CFLAGS \"${PKG_OPUSFILE_CFLAGS_OTHER}\" CACHE STRING \"CFLAGS of opusfile\")\n\nset(OPUSFILE_INCLUDE_DIRS \"${OPUSFILE_INCLUDE_DIR}\")\nset(OPUSFILE_LIBRARIES \"${OPUSFILE_LIBRARY}\")\n\nif (OPUSFILE_INCLUDE_DIRS AND OPUSFILE_LIBRARIES)\nset(OPUSFILE_FOUND TRUE)\nendif (OPUSFILE_INCLUDE_DIRS AND OPUSFILE_LIBRARIES)\n\ninclude(FindPackageHandleStandardArgs)\nfind_package_handle_standard_args(opusfile DEFAULT_MSG OPUSFILE_INCLUDE_DIRS OPUSFILE_LIBRARIES)\n\nif(NOT TARGET opusfile::opusfile)\n    add_library(__opusfile INTERFACE)\n    target_compile_options(__opusfile INTERFACE ${OPUSFILE_CFLAGS})\n    target_include_directories(__opusfile INTERFACE ${OPUSFILE_INCLUDE_DIRS})\n    target_link_libraries(__opusfile INTERFACE ${OPUSFILE_LIBRARIES})\n    add_library(opusfile::opusfile ALIAS __opusfile)\nendif()\n"
  },
  {
    "path": "cmake/GetGitRevisionDescription.cmake",
    "content": "# - Returns a version string from Git\n#\n# These functions force a re-configure on each git commit so that you can\n# trust the values of the variables in your build system.\n#\n#  get_git_head_revision(<refspecvar> <hashvar> [ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR])\n#\n# Returns the refspec and sha hash of the current head revision\n#\n#  git_describe(<var> [<additional arguments to git describe> ...])\n#\n# Returns the results of git describe on the source tree, and adjusting\n# the output so that it tests false if an error occurs.\n#\n#  git_describe_working_tree(<var> [<additional arguments to git describe> ...])\n#\n# Returns the results of git describe on the working tree (--dirty option),\n# and adjusting the output so that it tests false if an error occurs.\n#\n#  git_get_exact_tag(<var> [<additional arguments to git describe> ...])\n#\n# Returns the results of git describe --exact-match on the source tree,\n# and adjusting the output so that it tests false if there was no exact\n# matching tag.\n#\n#  git_local_changes(<var>)\n#\n# Returns either \"CLEAN\" or \"DIRTY\" with respect to uncommitted changes.\n# Uses the return code of \"git diff-index --quiet HEAD --\".\n# Does not regard untracked files.\n#\n# Requires CMake 2.6 or newer (uses the 'function' command)\n#\n# Original Author:\n# 2009-2020 Ryan Pavlik <ryan.pavlik@gmail.com> <abiryan@ryand.net>\n# http://academic.cleardefinition.com\n#\n# Copyright 2009-2013, Iowa State University.\n# Copyright 2013-2020, Ryan Pavlik\n# Copyright 2013-2020, Contributors\n# SPDX-License-Identifier: BSL-1.0\n# Distributed under the Boost Software License, Version 1.0.\n# (See accompanying file LICENSE_1_0.txt or copy at\n# http://www.boost.org/LICENSE_1_0.txt)\n\nif(__get_git_revision_description)\n    return()\nendif()\nset(__get_git_revision_description YES)\n\n# We must run the following at \"include\" time, not at function call time,\n# to find the path to this module rather than the path to a calling list file\nget_filename_component(_gitdescmoddir ${CMAKE_CURRENT_LIST_FILE} PATH)\n\n# Function _git_find_closest_git_dir finds the next closest .git directory\n# that is part of any directory in the path defined by _start_dir.\n# The result is returned in the parent scope variable whose name is passed\n# as variable _git_dir_var. If no .git directory can be found, the\n# function returns an empty string via _git_dir_var.\n#\n# Example: Given a path C:/bla/foo/bar and assuming C:/bla/.git exists and\n# neither foo nor bar contain a file/directory .git. This wil return\n# C:/bla/.git\n#\nfunction(_git_find_closest_git_dir _start_dir _git_dir_var)\n    set(cur_dir \"${_start_dir}\")\n    set(git_dir \"${_start_dir}/.git\")\n    while(NOT EXISTS \"${git_dir}\")\n        # .git dir not found, search parent directories\n        set(git_previous_parent \"${cur_dir}\")\n        get_filename_component(cur_dir ${cur_dir} DIRECTORY)\n        if(cur_dir STREQUAL git_previous_parent)\n            # We have reached the root directory, we are not in git\n            set(${_git_dir_var}\n                \"\"\n                PARENT_SCOPE)\n            return()\n        endif()\n        set(git_dir \"${cur_dir}/.git\")\n    endwhile()\n    set(${_git_dir_var}\n        \"${git_dir}\"\n        PARENT_SCOPE)\nendfunction()\n\nfunction(get_git_head_revision _refspecvar _hashvar)\n    _git_find_closest_git_dir(\"${CMAKE_CURRENT_SOURCE_DIR}\" GIT_DIR)\n\n    if(\"${ARGN}\" STREQUAL \"ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR\")\n        set(ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR TRUE)\n    else()\n        set(ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR FALSE)\n    endif()\n    if(NOT \"${GIT_DIR}\" STREQUAL \"\")\n        file(RELATIVE_PATH _relative_to_source_dir \"${CMAKE_SOURCE_DIR}\"\n             \"${GIT_DIR}\")\n        if(\"${_relative_to_source_dir}\" MATCHES \"[.][.]\" AND NOT ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR)\n            # We've gone above the CMake root dir.\n            set(GIT_DIR \"\")\n        endif()\n    endif()\n    if(\"${GIT_DIR}\" STREQUAL \"\")\n        set(${_refspecvar}\n            \"GITDIR-NOTFOUND\"\n            PARENT_SCOPE)\n        set(${_hashvar}\n            \"GITDIR-NOTFOUND\"\n            PARENT_SCOPE)\n        return()\n    endif()\n\n    # Check if the current source dir is a git submodule or a worktree.\n    # In both cases .git is a file instead of a directory.\n    #\n    if(NOT IS_DIRECTORY ${GIT_DIR})\n        # The following git command will return a non empty string that\n        # points to the super project working tree if the current\n        # source dir is inside a git submodule.\n        # Otherwise the command will return an empty string.\n        #\n        execute_process(\n            COMMAND \"${GIT_EXECUTABLE}\" rev-parse\n                    --show-superproject-working-tree\n            WORKING_DIRECTORY \"${CMAKE_CURRENT_SOURCE_DIR}\"\n            OUTPUT_VARIABLE out\n            ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)\n        if(NOT \"${out}\" STREQUAL \"\")\n            # If out is empty, GIT_DIR/CMAKE_CURRENT_SOURCE_DIR is in a submodule\n            file(READ ${GIT_DIR} submodule)\n            string(REGEX REPLACE \"gitdir: (.*)$\" \"\\\\1\" GIT_DIR_RELATIVE\n                                 ${submodule})\n            string(STRIP ${GIT_DIR_RELATIVE} GIT_DIR_RELATIVE)\n            get_filename_component(SUBMODULE_DIR ${GIT_DIR} PATH)\n            get_filename_component(GIT_DIR ${SUBMODULE_DIR}/${GIT_DIR_RELATIVE}\n                                   ABSOLUTE)\n            set(HEAD_SOURCE_FILE \"${GIT_DIR}/HEAD\")\n        else()\n            # GIT_DIR/CMAKE_CURRENT_SOURCE_DIR is in a worktree\n            file(READ ${GIT_DIR} worktree_ref)\n            # The .git directory contains a path to the worktree information directory\n            # inside the parent git repo of the worktree.\n            #\n            string(REGEX REPLACE \"gitdir: (.*)$\" \"\\\\1\" git_worktree_dir\n                                 ${worktree_ref})\n            string(STRIP ${git_worktree_dir} git_worktree_dir)\n            _git_find_closest_git_dir(\"${git_worktree_dir}\" GIT_DIR)\n            set(HEAD_SOURCE_FILE \"${git_worktree_dir}/HEAD\")\n        endif()\n    else()\n        set(HEAD_SOURCE_FILE \"${GIT_DIR}/HEAD\")\n    endif()\n    set(GIT_DATA \"${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/git-data\")\n    if(NOT EXISTS \"${GIT_DATA}\")\n        file(MAKE_DIRECTORY \"${GIT_DATA}\")\n    endif()\n\n    if(NOT EXISTS \"${HEAD_SOURCE_FILE}\")\n        return()\n    endif()\n    set(HEAD_FILE \"${GIT_DATA}/HEAD\")\n    configure_file(\"${HEAD_SOURCE_FILE}\" \"${HEAD_FILE}\" COPYONLY)\n\n    configure_file(\"${_gitdescmoddir}/GetGitRevisionDescription.cmake.in\"\n                   \"${GIT_DATA}/grabRef.cmake\" @ONLY)\n    include(\"${GIT_DATA}/grabRef.cmake\")\n\n    set(${_refspecvar}\n        \"${HEAD_REF}\"\n        PARENT_SCOPE)\n    set(${_hashvar}\n        \"${HEAD_HASH}\"\n        PARENT_SCOPE)\nendfunction()\n\nfunction(git_describe _var)\n    if(NOT GIT_FOUND)\n        find_package(Git QUIET)\n    endif()\n    get_git_head_revision(refspec hash)\n    if(NOT GIT_FOUND)\n        set(${_var}\n            \"GIT-NOTFOUND\"\n            PARENT_SCOPE)\n        return()\n    endif()\n    if(NOT hash)\n        set(${_var}\n            \"HEAD-HASH-NOTFOUND\"\n            PARENT_SCOPE)\n        return()\n    endif()\n\n    # TODO sanitize\n    #if((${ARGN}\" MATCHES \"&&\") OR\n    #\t(ARGN MATCHES \"||\") OR\n    #\t(ARGN MATCHES \"\\\\;\"))\n    #\tmessage(\"Please report the following error to the project!\")\n    #\tmessage(FATAL_ERROR \"Looks like someone's doing something nefarious with git_describe! Passed arguments ${ARGN}\")\n    #endif()\n\n    #message(STATUS \"Arguments to execute_process: ${ARGN}\")\n\n    execute_process(\n        COMMAND \"${GIT_EXECUTABLE}\" describe --tags --always ${hash} ${ARGN}\n        WORKING_DIRECTORY \"${CMAKE_CURRENT_SOURCE_DIR}\"\n        RESULT_VARIABLE res\n        OUTPUT_VARIABLE out\n        ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)\n    if(NOT res EQUAL 0)\n        set(out \"${out}-${res}-NOTFOUND\")\n    endif()\n\n    set(${_var}\n        \"${out}\"\n        PARENT_SCOPE)\nendfunction()\n\nfunction(git_describe_working_tree _var)\n    if(NOT GIT_FOUND)\n        find_package(Git QUIET)\n    endif()\n    if(NOT GIT_FOUND)\n        set(${_var}\n            \"GIT-NOTFOUND\"\n            PARENT_SCOPE)\n        return()\n    endif()\n\n    execute_process(\n        COMMAND \"${GIT_EXECUTABLE}\" describe --dirty ${ARGN}\n        WORKING_DIRECTORY \"${CMAKE_CURRENT_SOURCE_DIR}\"\n        RESULT_VARIABLE res\n        OUTPUT_VARIABLE out\n        ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)\n    if(NOT res EQUAL 0)\n        set(out \"${out}-${res}-NOTFOUND\")\n    endif()\n\n    set(${_var}\n        \"${out}\"\n        PARENT_SCOPE)\nendfunction()\n\nfunction(git_get_exact_tag _var)\n    git_describe(out --exact-match ${ARGN})\n    set(${_var}\n        \"${out}\"\n        PARENT_SCOPE)\nendfunction()\n\nfunction(git_local_changes _var)\n    if(NOT GIT_FOUND)\n        find_package(Git QUIET)\n    endif()\n    get_git_head_revision(refspec hash)\n    if(NOT GIT_FOUND)\n        set(${_var}\n            \"GIT-NOTFOUND\"\n            PARENT_SCOPE)\n        return()\n    endif()\n    if(NOT hash)\n        set(${_var}\n            \"HEAD-HASH-NOTFOUND\"\n            PARENT_SCOPE)\n        return()\n    endif()\n\n    execute_process(\n        COMMAND \"${GIT_EXECUTABLE}\" diff-index --quiet HEAD --\n        WORKING_DIRECTORY \"${CMAKE_CURRENT_SOURCE_DIR}\"\n        RESULT_VARIABLE res\n        OUTPUT_VARIABLE out\n        ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)\n    if(res EQUAL 0)\n        set(${_var}\n            \"CLEAN\"\n            PARENT_SCOPE)\n    else()\n        set(${_var}\n            \"DIRTY\"\n            PARENT_SCOPE)\n    endif()\nendfunction()\n"
  },
  {
    "path": "cmake/GetGitRevisionDescription.cmake.in",
    "content": "#\n# Internal file for GetGitRevisionDescription.cmake\n#\n# Requires CMake 2.6 or newer (uses the 'function' command)\n#\n# Original Author:\n# 2009-2010 Ryan Pavlik <rpavlik@iastate.edu> <abiryan@ryand.net>\n# http://academic.cleardefinition.com\n# Iowa State University HCI Graduate Program/VRAC\n#\n# Copyright 2009-2012, Iowa State University\n# Copyright 2011-2015, Contributors\n# Distributed under the Boost Software License, Version 1.0.\n# (See accompanying file LICENSE_1_0.txt or copy at\n# http://www.boost.org/LICENSE_1_0.txt)\n# SPDX-License-Identifier: BSL-1.0\n\nset(HEAD_HASH)\n\nfile(READ \"@HEAD_FILE@\" HEAD_CONTENTS LIMIT 1024)\n\nstring(STRIP \"${HEAD_CONTENTS}\" HEAD_CONTENTS)\nif(HEAD_CONTENTS MATCHES \"ref\")\n\t# named branch\n\tstring(REPLACE \"ref: \" \"\" HEAD_REF \"${HEAD_CONTENTS}\")\n\tif(EXISTS \"@GIT_DIR@/${HEAD_REF}\")\n\t\tconfigure_file(\"@GIT_DIR@/${HEAD_REF}\" \"@GIT_DATA@/head-ref\" COPYONLY)\n\telse()\n\t\tconfigure_file(\"@GIT_DIR@/packed-refs\" \"@GIT_DATA@/packed-refs\" COPYONLY)\n\t\tfile(READ \"@GIT_DATA@/packed-refs\" PACKED_REFS)\n\t\tif(${PACKED_REFS} MATCHES \"([0-9a-z]*) ${HEAD_REF}\")\n\t\t\tset(HEAD_HASH \"${CMAKE_MATCH_1}\")\n\t\tendif()\n\tendif()\nelse()\n\t# detached HEAD\n\tconfigure_file(\"@GIT_DIR@/HEAD\" \"@GIT_DATA@/head-ref\" COPYONLY)\nendif()\n\nif(NOT HEAD_HASH)\n\tfile(READ \"@GIT_DATA@/head-ref\" HEAD_HASH LIMIT 1024)\n\tstring(STRIP \"${HEAD_HASH}\" HEAD_HASH)\nendif()\n"
  },
  {
    "path": "conanfile.py",
    "content": "from conans import ConanFile, CMake, tools\nfrom conans.errors import ConanException, ConanInvalidConfiguration\nimport os\nimport shutil\nimport textwrap\n\n\nclass ReVCConan(ConanFile):\n    name = \"reVC\"\n    version = \"master\"\n    license = \"???\"  # FIXME: https://github.com/GTAmodding/re3/issues/794\n    settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n    generators = \"cmake\", \"cmake_find_package\"\n    options = {\n        \"audio\": [\"openal\", \"miles\"],\n        \"with_libsndfile\": [True, False],\n        \"with_opus\": [True, False],\n    }\n    default_options = {\n        \"audio\": \"openal\",\n        \"with_libsndfile\": False,\n        \"with_opus\": False,\n        # \"libsndfile:with_external_libs\": False,\n        # \"mpg123:flexible_resampling\": False,\n        # \"mpg123:network\": False,\n        # \"mpg123:icy\": False,\n        # \"mpg123:id3v2\": False,\n        # \"mpg123:ieeefloat\": False,\n        # \"mpg123:layer1\": False,\n        # \"mpg123:layer2\": False,\n        # \"mpg123:layer3\": False,\n        # \"mpg123:moreinfo\": False,\n        # \"sdl2:vulkan\": False,\n        # \"sdl2:opengl\": True,\n        # \"sdl2:sdl2main\": True,\n    }\n    no_copy_source = True\n\n    @property\n    def _os_is_playstation2(self):\n        try:\n            return self.settings.os == \"Playstation2\"\n        except ConanException:\n            return False\n\n    def configure(self):\n        if self.options.audio != \"openal\":\n            self.options.with_libsndfile = False\n\n    def requirements(self):\n        self.requires(\"librw/{}\".format(self.version))\n        self.requires(\"mpg123/1.26.4\")\n        if self.options.audio == \"openal\":\n            self.requires(\"openal/1.21.0\")\n        elif self.options.audio == \"miles\":\n            self.requires(\"miles-sdk/{}\".format(self.version))\n        if self.options.with_libsndfile:\n            self.requires(\"libsndfile/1.0.30\")\n        if self.options.with_opus:\n            self.requires(\"opusfile/0.12\")\n\n    def export_sources(self):\n        for d in (\"cmake\", \"src\"):\n            shutil.copytree(src=d, dst=os.path.join(self.export_sources_folder, d))\n        self.copy(\"CMakeLists.txt\")\n\n    def validate(self):\n        if self.options[\"librw\"].platform == \"gl3\" and self.options[\"librw\"].gl3_gfxlib != \"glfw\":\n            raise ConanInvalidConfiguration(\"Only `glfw` is supported as gl3_gfxlib.\")\n        #if not self.options.with_opus:\n        #    if not self.options[\"libsndfile\"].with_external_libs:\n        #        raise ConanInvalidConfiguration(\"reVC with opus support requires a libsndfile built with external libs (=ogg/flac/opus/vorbis)\")\n\n    @property\n    def _reVC_audio(self):\n        return {\n            \"miles\": \"MSS\",\n            \"openal\": \"OAL\",\n        }[str(self.options.audio)]\n\n    def build(self):\n        if self.source_folder == self.build_folder:\n            raise Exception(\"cannot build with source_folder == build_folder\")\n        try:\n            os.unlink(os.path.join(self.install_folder, \"Findlibrw.cmake\"))\n            tools.save(\"FindOpenAL.cmake\",\n                       textwrap.dedent(\n                           \"\"\"\n                           set(OPENAL_FOUND ON)\n                           set(OPENAL_INCLUDE_DIR ${OpenAL_INCLUDE_DIRS})\n                           set(OPENAL_LIBRARY ${OpenAL_LIBRARIES})\n                           set(OPENAL_DEFINITIONS ${OpenAL_DEFINITIONS})\n                           \"\"\"), append=True)\n            if self.options[\"librw\"].platform == \"gl3\" and self.options[\"librw\"].gl3_gfxlib == \"glfw\":\n                tools.save(\"Findglfw3.cmake\",\n                           textwrap.dedent(\n                               \"\"\"\n                               if(NOT TARGET glfw)\n                                 message(STATUS \"Creating glfw TARGET\")\n                                 add_library(glfw INTERFACE IMPORTED)\n                                 set_target_properties(glfw PROPERTIES\n                                    INTERFACE_LINK_LIBRARIES CONAN_PKG::glfw)\n                               endif()\n                               \"\"\"), append=True)\n            tools.save(\"CMakeLists.txt\",\n                       textwrap.dedent(\n                           \"\"\"\n                           cmake_minimum_required(VERSION 3.0)\n                           project(cmake_wrapper)\n    \n                           include(\"{}/conanbuildinfo.cmake\")\n                           conan_basic_setup(TARGETS NO_OUTPUT_DIRS)\n    \n                           add_subdirectory(\"{}\" reVC)\n                           \"\"\").format(self.install_folder.replace(\"\\\\\", \"/\"),\n                                       self.source_folder.replace(\"\\\\\", \"/\")))\n        except FileNotFoundError:\n            pass\n        cmake = CMake(self)\n        cmake.definitions[\"REVC_AUDIO\"] = self._reVC_audio\n        cmake.definitions[\"REVC_WITH_OPUS\"] = self.options.with_opus\n        cmake.definitions[\"REVC_INSTALL\"] = True\n        cmake.definitions[\"REVC_VENDORED_LIBRW\"] = False\n        env = {}\n        if self._os_is_playstation2:\n            cmake.definitions[\"CMAKE_TOOLCHAIN_FILE\"] = self.deps_user_info[\"ps2dev-cmaketoolchain\"].cmake_toolchain_file\n            env[\"PS2SDK\"] = self.deps_cpp_info[\"ps2dev-ps2sdk\"].rootpath\n\n        with tools.environment_append(env):\n            cmake.configure(source_folder=self.build_folder)\n        cmake.build()\n\n    def package(self):\n        cmake = CMake(self)\n        cmake.install()\n"
  },
  {
    "path": "gamefiles/gamecontrollerdb.txt",
    "content": "# Game Controller DB for SDL in 2.0.9 format\n# Source: https://github.com/gabomdq/SDL_GameControllerDB\n\n# Windows\n03000000fa2d00000100000000000000,3DRUDDER,leftx:a0,lefty:a1,rightx:a5,righty:a2,platform:Windows,\n03000000c82d00002038000000000000,8bitdo,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,\n03000000c82d000011ab000000000000,8BitDo F30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,\n03000000c82d00001038000000000000,8BitDo F30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows,\n03000000c82d00000090000000000000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,\n03000000c82d00000650000000000000,8BitDo M30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:a4,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,start:b11,x:b3,y:b4,platform:Windows,\n03000000c82d00005106000000000000,8BitDo M30 Gamepad,a:b1,b:b0,back:b10,guide:b2,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,start:b11,x:b4,y:b3,platform:Windows,\n03000000c82d00000310000000000000,8BitDo N30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Windows,\n03000000c82d00002028000000000000,8BitDo N30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows,\n03000000c82d00008010000000000000,8BitDo N30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Windows,\n03000000c82d00000190000000000000,8BitDo N30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,\n03000000c82d00001590000000000000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,\n03000000c82d00006528000000000000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,\n03000000c82d00015900000000000000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows,\n03000000c82d00065280000000000000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows,\n03000000022000000090000000000000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,\n03000000203800000900000000000000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,\n03000000c82d00000130000000000000,8BitDo SF30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows,\n03000000c82d00000060000000000000,8Bitdo SF30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows,\n03000000c82d00000061000000000000,8Bitdo SF30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows,\n03000000c82d000021ab000000000000,8BitDo SFC30,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows,\n03000000102800000900000000000000,8Bitdo SFC30 GamePad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows,\n03000000c82d00003028000000000000,8Bitdo SFC30 GamePad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows,\n03000000c82d00000030000000000000,8BitDo SN30,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows,\n03000000c82d00000351000000000000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows,\n03000000c82d00001290000000000000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows,\n03000000c82d000020ab000000000000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows,\n03000000c82d00004028000000000000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows,\n03000000c82d00006228000000000000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows,\n03000000c82d00000160000000000000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows,\n03000000c82d00000161000000000000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows,\n03000000c82d00000260000000000000,8BitDo SN30 Pro+,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows,\n03000000c82d00000261000000000000,8BitDo SN30 Pro+,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows,\n03000000c82d00000031000000000000,8BitDo Wireless Adapter,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,\n03000000c82d00001890000000000000,8BitDo Zero 2,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows,\n03000000c82d00003032000000000000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows,\n03000000a00500003232000000000000,8Bitdo Zero GamePad,a:b0,b:b1,back:b10,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Windows,\n030000008f0e00001200000000000000,Acme GA-02,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Windows,\n03000000fa190000f0ff000000000000,Acteck AGJ-3200,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,\n030000006f0e00001413000000000000,Afterglow,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n03000000341a00003608000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n030000006f0e00000263000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n030000006f0e00001101000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n030000006f0e00001401000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n030000006f0e00001402000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n030000006f0e00001901000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n030000006f0e00001a01000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n03000000d62000001d57000000000000,Airflo PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n03000000869800002400000000007801,Astro C40 TR,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,\n03000000d6200000e557000000000000,Batarang,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n03000000c01100001352000000000000,Battalife Joystick,a:b6,b:b7,back:b2,leftshoulder:b0,leftx:a0,lefty:a1,rightshoulder:b1,start:b3,x:b4,y:b5,platform:Windows,\n030000006f0e00003201000000000000,Battlefield 4 PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n03000000d62000002a79000000000000,BDA PS4 Fightpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,\n03000000bc2000006012000000000000,Betop 2126F,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,\n03000000bc2000000055000000000000,Betop BFM Gamepad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,\n03000000bc2000006312000000000000,Betop Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,\n03000000bc2000006321000000000000,BETOP CONTROLLER,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,\n03000000bc2000006412000000000000,Betop Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,\n03000000c01100000555000000000000,Betop Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,\n03000000c01100000655000000000000,Betop Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,\n03000000790000000700000000000000,Betop Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b3,y:b0,platform:Windows,\n03000000808300000300000000000000,Betop Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b3,y:b0,platform:Windows,\n030000006b1400000055000000000000,Bigben PS3 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,\n030000006b1400000103000000000000,Bigben PS3 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Windows,\n0300000066f700000500000000000000,BrutalLegendTest,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b3,platform:Windows,\n03000000d81d00000b00000000000000,BUFFALO BSGP1601 Series ,a:b5,b:b3,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b13,x:b4,y:b2,platform:Windows,\n03000000e82000006058000000000000,Cideko AK08b,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,\n03000000457500000401000000000000,Cobra,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,\n030000005e0400008e02000000000000,Controller (XBOX 360 For Windows),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,\n030000005e040000a102000000000000,Controller (Xbox 360 Wireless Receiver for Windows),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,\n030000005e040000ff02000000000000,Controller (Xbox One For Windows) - Wired,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,\n030000005e040000ea02000000000000,Controller (Xbox One For Windows) - Wireless,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,\n03000000260900008888000000000000,Cyber Gadget GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a4,rightx:a2,righty:a3~,start:b7,x:b2,y:b3,platform:Windows,\n03000000a306000022f6000000000000,Cyborg V.3 Rumble Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:-a3,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Windows,\n03000000451300000830000000000000,Defender Game Racer X7,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,\n030000007d0400000840000000000000,Destroyer Tiltpad,+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b1,b:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,x:b0,y:b3,platform:Windows,\n03000000791d00000103000000000000,Dual Box WII,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,\n03000000bd12000002e0000000000000,Dual USB Vibration Joystick,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a3,righty:a2,start:b11,x:b3,y:b0,platform:Windows,\n030000008f0e00000910000000000000,DualShock 2,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a3,righty:a2,start:b11,x:b3,y:b0,platform:Windows,\n030000006f0e00003001000000000000,EA SPORTS PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n03000000b80500000410000000000000,Elecom Gamepad,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,platform:Windows,\n03000000b80500000610000000000000,Elecom Gamepad,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,platform:Windows,\n03000000120c0000f61c000000000000,Elite,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,\n030000008f0e00000f31000000000000,EXEQ,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Windows,\n03000000341a00000108000000000000,EXEQ RF USB Gamepad 8206,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,\n030000006f0e00008401000000000000,Faceoff Deluxe+ Audio Wired Controller for Nintendo Switch,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n030000006f0e00008001000000000000,Faceoff Wired Pro Controller for Nintendo Switch,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n03000000852100000201000000000000,FF-GP1,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n030000000d0f00008500000000000000,Fighting Commander 2016 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n030000000d0f00008400000000000000,Fighting Commander 5,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,\n030000000d0f00008700000000000000,Fighting Stick mini 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,\n030000000d0f00008800000000000000,Fighting Stick mini 4,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b8,x:b0,y:b3,platform:Windows,\n030000000d0f00002700000000000000,FIGHTING STICK V3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,\n78696e70757403000000000000000000,Fightstick TES,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,start:b7,x:b2,y:b3,platform:Windows,\n03000000790000002201000000000000,Game Controller for PC,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,\n0300000066f700000100000000000000,Game VIB Joystick,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Windows,\n03000000260900002625000000000000,Gamecube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,lefttrigger:a4,leftx:a0,lefty:a1,righttrigger:a5,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Windows,\n03000000790000004618000000000000,GameCube Controller Adapter,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Windows,\n030000008f0e00000d31000000000000,GAMEPAD 3 TURBO,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n03000000280400000140000000000000,GamePad Pro USB,a:b1,b:b2,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,\n03000000ac0500003d03000000000000,GameSir,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,\n03000000ac0500004d04000000000000,GameSir,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,\n03000000ffff00000000000000000000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,\n03000000c01100000140000000000000,GameStop PS4 Fun Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,\n030000006f0e00000102000000007801,GameStop Xbox 360 Wired Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,\n030000009b2800003200000000000000,GC/N64 to USB v3.4,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:+a5,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:+a2,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Windows,\n030000009b2800006000000000000000,GC/N64 to USB v3.6,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:+a5,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:+a2,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Windows,\n030000008305000009a0000000000000,Genius,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,\n030000008305000031b0000000000000,Genius Maxfire Blaze 3,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,\n03000000451300000010000000000000,Genius Maxfire Grandias 12,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,\n030000005c1a00003330000000000000,Genius MaxFire Grandias 12V,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Windows,\n03000000300f00000b01000000000000,GGE909 Recoil Pad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows,\n03000000f0250000c283000000000000,Gioteck,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,\n03000000f025000021c1000000000000,Gioteck PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,\n03000000f0250000c383000000000000,Gioteck VX2 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,\n03000000f0250000c483000000000000,Gioteck VX2 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,\n030000007d0400000540000000000000,Gravis Eliminator GamePad Pro,a:b1,b:b2,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,\n03000000341a00000302000000000000,Hama Scorpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n030000000d0f00004900000000000000,Hatsune Miku Sho Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n030000001008000001e1000000000000,Havit HV-G60,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b3,y:b0,platform:Windows,\n03000000d81400000862000000000000,HitBox Edition Cthulhu+,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b4,rightshoulder:b7,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows,\n03000000632500002605000000000000,HJD-X,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,\n030000000d0f00002d00000000000000,Hori Fighting Commander 3 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n030000000d0f00005f00000000000000,Hori Fighting Commander 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n030000000d0f00005e00000000000000,Hori Fighting Commander 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,\n030000000d0f00004000000000000000,Hori Fighting Stick Mini 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b4,rightshoulder:b7,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows,\n030000000d0f00005400000000000000,Hori Pad 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n030000000d0f00000900000000000000,Hori Pad 3 Turbo,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n030000000d0f00004d00000000000000,Hori Pad A,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n030000000d0f00009200000000000000,Hori Pokken Tournament DX Pro Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,\n030000000d0f00001600000000007803,HORI Real Arcade Pro EX-SE (Xbox 360),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,start:b7,x:b2,y:b3,platform:Windows,\n030000000d0f00009c00000000000000,Hori TAC Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,\n030000000d0f0000c100000000000000,Horipad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n030000000d0f00006e00000000000000,HORIPAD 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n030000000d0f00006600000000000000,HORIPAD 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,\n030000000d0f00005500000000000000,Horipad 4 FPS,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,\n030000000d0f0000ee00000000000000,HORIPAD mini4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,\n03000000250900000017000000000000,HRAP2 on PS/SS/N64 Joypad to USB BOX,a:b2,b:b1,back:b9,leftshoulder:b5,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b6,start:b8,x:b3,y:b0,platform:Windows,\n030000008f0e00001330000000000000,HuiJia SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b9,x:b3,y:b0,platform:Windows,\n03000000d81d00000f00000000000000,iBUFFALO BSGP1204 Series,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,\n03000000d81d00001000000000000000,iBUFFALO BSGP1204P Series,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,\n03000000830500006020000000000000,iBuffalo SNES Controller,a:b1,b:b0,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Windows,\n03000000b50700001403000000000000,Impact Black,a:b2,b:b3,back:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows,\n030000006f0e00002401000000000000,INJUSTICE FightStick PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,\n03000000ac0500002c02000000000000,IPEGA,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b13,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b14,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,\n03000000491900000204000000000000,Ipega PG-9023,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,\n03000000491900000304000000000000,Ipega PG-9087 - Bluetooth Gamepad,+righty:+a5,-righty:-a4,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,start:b11,x:b3,y:b4,platform:Windows,\n030000006e0500000a20000000000000,JC-DUX60 ELECOM MMO Gamepad,a:b2,b:b3,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b14,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b15,righttrigger:b13,rightx:a3,righty:a4,start:b20,x:b0,y:b1,platform:Windows,\n030000006e0500000520000000000000,JC-P301U,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Windows,\n030000006e0500000320000000000000,JC-U3613M (DInput),a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Windows,\n030000006e0500000720000000000000,JC-W01U,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,platform:Windows,\n030000007e0500000620000000000000,Joy-Con (L),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b13,leftshoulder:b4,leftstick:b10,rightshoulder:b5,start:b8,x:b2,y:b3,platform:Windows,\n030000007e0500000620000001000000,Joy-Con (L),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b13,leftshoulder:b4,leftstick:b10,rightshoulder:b5,start:b8,x:b2,y:b3,platform:Windows,\n030000007e0500000720000000000000,Joy-Con (R),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b12,leftshoulder:b4,leftstick:b11,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Windows,\n030000007e0500000720000001000000,Joy-Con (R),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b12,leftshoulder:b4,leftstick:b11,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Windows,\n03000000bd12000003c0000000000000,JY-P70UR,a:b1,b:b0,back:b5,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b8,rightstick:b11,righttrigger:b9,rightx:a3,righty:a2,start:b4,x:b3,y:b2,platform:Windows,\n03000000242f00002d00000000000000,JYS Wireless Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,\n03000000242f00008a00000000000000,JYS Wireless Adapter,a:b1,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b0,y:b3,platform:Windows,\n03000000790000000200000000000000,King PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b3,y:b0,platform:Windows,\n030000006d040000d1ca000000000000,Logitech ChillStream,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n030000006d040000d2ca000000000000,Logitech Cordless Precision,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n030000006d04000011c2000000000000,Logitech Cordless Wingman,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b5,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b2,righttrigger:b7,rightx:a3,righty:a4,x:b4,platform:Windows,\n030000006d04000016c2000000000000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n030000006d04000018c2000000000000,Logitech F510 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n030000006d04000019c2000000000000,Logitech F710 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n030000006d0400001ac2000000000000,Logitech Precision Gamepad,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,\n030000006d0400000ac2000000000000,Logitech WingMan RumblePad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,rightx:a3,righty:a4,x:b3,y:b4,platform:Windows,\n03000000380700006652000000000000,Mad Catz C.T.R.L.R,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows,\n03000000380700005032000000000000,Mad Catz FightPad PRO (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n03000000380700005082000000000000,Mad Catz FightPad PRO (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,\n03000000380700008433000000000000,Mad Catz FightStick TE S+ (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n03000000380700008483000000000000,Mad Catz FightStick TE S+ (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,\n03000000380700008134000000000000,Mad Catz FightStick TE2+ PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b7,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b4,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n03000000380700008184000000000000,Mad Catz FightStick TE2+ PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,leftstick:b10,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,\n03000000380700006252000000000000,Mad Catz Micro C.T.R.L.R,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows,\n03000000380700008034000000000000,Mad Catz TE2 PS3 Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n03000000380700008084000000000000,Mad Catz TE2 PS4 Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,\n03000000380700008532000000000000,Madcatz Arcade Fightstick TE S PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n03000000380700003888000000000000,Madcatz Arcade Fightstick TE S+ PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n03000000380700001888000000000000,MadCatz SFIV FightStick PS3,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b4,righttrigger:b6,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,\n03000000380700008081000000000000,MADCATZ SFV Arcade FightStick Alpha PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,\n030000002a0600001024000000000000,Matricom,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:Windows,\n03000000250900000128000000000000,Mayflash Arcade Stick,a:b1,b:b2,back:b8,leftshoulder:b0,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b3,righttrigger:b7,start:b9,x:b5,y:b6,platform:Windows,\n03000000790000004418000000000000,Mayflash GameCube Controller,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Windows,\n03000000790000004318000000000000,Mayflash GameCube Controller Adapter,a:b1,b:b2,back:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b0,leftshoulder:b4,leftstick:b0,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b0,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Windows,\n03000000242f00007300000000000000,Mayflash Magic NS,a:b1,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b0,y:b3,platform:Windows,\n0300000079000000d218000000000000,Mayflash Magic NS,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,\n03000000d620000010a7000000000000,Mayflash Magic NS,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n030000008f0e00001030000000000000,Mayflash USB Adapter for original Sega Saturn controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b5,rightshoulder:b2,righttrigger:b7,start:b9,x:b3,y:b4,platform:Windows,\n0300000025090000e803000000000000,Mayflash Wii Classic Controller,a:b1,b:b0,back:b8,dpdown:b13,dpleft:b12,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Windows,\n03000000790000000018000000000000,Mayflash WiiU Pro Game Controller Adapter (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n03000000790000002418000000000000,Mega Drive,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,rightshoulder:b2,start:b9,x:b3,y:b4,platform:Windows,\n03000000380700006382000000000000,MLG GamePad PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n03000000c62400002a89000000000000,MOGA XP5-A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,\n03000000c62400002b89000000000000,MOGA XP5-A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,\n03000000c62400001a89000000000000,MOGA XP5-X Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,\n03000000c62400001b89000000000000,MOGA XP5-X Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,\n03000000efbe0000edfe000000000000,Monect Virtual Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b0,platform:Windows,\n03000000250900006688000000000000,MP-8866 Super Dual Box,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows,\n030000006b140000010c000000000000,NACON GC-400ES,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,\n030000001008000001e5000000000000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b6,start:b9,x:b3,y:b0,platform:Windows,\n03000000152000000182000000000000,NGDS,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b3,y:b0,platform:Windows,\n03000000bd12000015d0000000000000,Nintendo Retrolink USB Super SNES Classic Controller,a:b2,b:b1,back:b8,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Windows,\n030000007e0500000920000000000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,\n030000000d0500000308000000000000,Nostromo N45,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b12,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b10,x:b2,y:b3,platform:Windows,\n03000000550900001472000000000000,NVIDIA Controller v01.04,a:b11,b:b10,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b7,leftstick:b5,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b4,righttrigger:a5,rightx:a3,righty:a6,start:b3,x:b9,y:b8,platform:Windows,\n030000004b120000014d000000000000,NYKO AIRFLO,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:a3,leftstick:a0,lefttrigger:b6,rightshoulder:b5,rightstick:a2,righttrigger:b7,start:b9,x:b2,y:b3,platform:Windows,\n03000000782300000a10000000000000,Onlive Wireless Controller,a:b15,b:b14,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b11,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b13,y:b12,platform:Windows,\n03000000d62000006d57000000000000,OPP PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n030000006b14000001a1000000000000,Orange Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Windows,\n03000000362800000100000000000000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:b13,rightx:a3,righty:a4,x:b1,y:b2,platform:Windows,\n03000000120c0000f60e000000000000,P4 Wired Gamepad,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b5,lefttrigger:b7,rightshoulder:b4,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows,\n030000006f0e00000901000000000000,PDP Versus Fighting Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,\n030000008f0e00000300000000000000,Piranha xtreme,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows,\n030000004c050000da0c000000000000,PlayStation Classic Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows,\n03000000d62000006dca000000000000,PowerA Pro Ex,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n03000000d62000009557000000000000,Pro Elite PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n03000000d62000009f31000000000000,Pro Ex mini PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n03000000d6200000c757000000000000,Pro Ex mini PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n03000000632500002306000000000000,PS Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Windows,\n03000000e30500009605000000000000,PS to USB convert cable,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows,\n03000000100800000100000000000000,PS1 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows,\n030000008f0e00007530000000000000,PS1 Controller,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b1,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n03000000100800000300000000000000,PS2 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a4,righty:a2,start:b9,x:b3,y:b0,platform:Windows,\n03000000250900008888000000000000,PS2 Controller,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows,\n03000000666600006706000000000000,PS2 Controller,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,platform:Windows,\n030000006b1400000303000000000000,PS2 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,\n030000009d0d00001330000000000000,PS2 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,\n03000000250900000500000000000000,PS3 Controller,a:b2,b:b1,back:b9,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b0,y:b3,platform:Windows,\n030000004c0500006802000000000000,PS3 Controller,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b10,lefttrigger:a3~,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:a4~,rightx:a2,righty:a5,start:b8,x:b3,y:b0,platform:Windows,\n03000000632500007505000000000000,PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,\n03000000888800000803000000000000,PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b9,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b0,y:b3,platform:Windows,\n030000008f0e00001431000000000000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n030000003807000056a8000000000000,PS3 RF pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n03000000100000008200000000000000,PS360+ v1.66,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:h0.4,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,\n030000004c050000a00b000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,\n030000004c050000c405000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,\n030000004c050000cc09000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,\n030000004c050000e60c000000000000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,\n03000000300f00000011000000000000,QanBa Arcade JoyStick 1008,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b10,x:b0,y:b3,platform:Windows,\n03000000300f00001611000000000000,QanBa Arcade JoyStick 4018,a:b1,b:b2,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b8,x:b0,y:b3,platform:Windows,\n03000000222c00000020000000000000,QANBA DRONE ARCADE JOYSTICK,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,rightshoulder:b5,righttrigger:a4,start:b9,x:b0,y:b3,platform:Windows,\n03000000300f00001210000000000000,QanBa Joystick Plus,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Windows,\n03000000341a00000104000000000000,QanBa Joystick Q4RAF,a:b5,b:b6,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b0,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b3,righttrigger:b7,start:b9,x:b1,y:b2,platform:Windows,\n03000000222c00000223000000000000,Qanba Obsidian Arcade Joystick PS3 Mode,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n03000000222c00000023000000000000,Qanba Obsidian Arcade Joystick PS4 Mode,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,\n03000000321500000003000000000000,Razer Hydra,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,\n03000000321500000204000000000000,Razer Panthera (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n03000000321500000104000000000000,Razer Panthera (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,\n03000000321500000507000000000000,Razer Raiju Mobile,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,\n03000000321500000707000000000000,Razer Raiju Mobile,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,\n03000000321500000011000000000000,Razer Raion Fightpad for PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,\n03000000321500000009000000000000,Razer Serval,+lefty:+a2,-lefty:-a1,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,leftx:a0,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,\n030000000d0f00001100000000000000,REAL ARCADE PRO.3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,\n030000000d0f00006a00000000000000,Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,\n030000000d0f00006b00000000000000,Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n030000000d0f00008a00000000000000,Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,\n030000000d0f00008b00000000000000,Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n030000000d0f00007000000000000000,REAL ARCADE PRO.4 VLX,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,\n030000000d0f00002200000000000000,REAL ARCADE Pro.V3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n030000000d0f00005b00000000000000,Real Arcade Pro.V4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,\n030000000d0f00005c00000000000000,Real Arcade Pro.V4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n03000000790000001100000000000000,Retrolink SNES Controller,a:b2,b:b1,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Windows,\n03000000bd12000013d0000000000000,Retrolink USB SEGA Saturn Classic,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b5,lefttrigger:b6,rightshoulder:b2,righttrigger:b7,start:b8,x:b3,y:b4,platform:Windows,\n0300000000f000000300000000000000,RetroUSB.com RetroPad,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Windows,\n0300000000f00000f100000000000000,RetroUSB.com Super RetroPort,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Windows,\n030000006b140000010d000000000000,Revolution Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,\n030000006b140000020d000000000000,Revolution Pro Controller 2(1/2),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,\n030000006b140000130d000000000000,Revolution Pro Controller 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,\n030000006f0e00001e01000000000000,Rock Candy PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n030000006f0e00002801000000000000,Rock Candy PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n030000006f0e00002f01000000000000,Rock Candy PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n030000004f04000003d0000000000000,run'n'drive,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b7,leftshoulder:a3,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:a4,rightstick:b11,righttrigger:b5,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,\n03000000a30600001af5000000000000,Saitek Cyborg,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows,\n03000000a306000023f6000000000000,Saitek Cyborg V.1 Game pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Windows,\n03000000300f00001201000000000000,Saitek Dual Analog Pad,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows,\n03000000a30600000701000000000000,Saitek P220,a:b2,b:b3,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b4,righttrigger:b5,x:b0,y:b1,platform:Windows,\n03000000a30600000cff000000000000,Saitek P2500 Force Rumble Pad,a:b2,b:b3,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b0,y:b1,platform:Windows,\n03000000a30600000c04000000000000,Saitek P2900,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b3,platform:Windows,\n03000000300f00001001000000000000,Saitek P480 Rumble Pad,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows,\n03000000a30600000b04000000000000,Saitek P990,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b3,platform:Windows,\n03000000a30600000b04000000010000,Saitek P990 Dual Analog Pad,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b8,x:b0,y:b3,platform:Windows,\n03000000a30600002106000000000000,Saitek PS1000,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Windows,\n03000000a306000020f6000000000000,Saitek PS2700,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Windows,\n03000000300f00001101000000000000,Saitek Rumble Pad,a:b2,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows,\n03000000730700000401000000000000,Sanwa PlayOnline Mobile,a:b0,b:b1,back:b2,leftx:a0,lefty:a1,start:b3,platform:Windows,\n0300000000050000289b000000000000,Saturn_Adapter_2.0,a:b1,b:b2,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b0,y:b3,platform:Windows,\n030000009b2800000500000000000000,Saturn_Adapter_2.0,a:b1,b:b2,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b0,y:b3,platform:Windows,\n030000005e0400008e02000000007801,ShanWan PS3/PC Wired GamePad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,\n03000000341a00000208000000000000,SL-6555-SBK,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:-a4,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a4,rightx:a3,righty:a2,start:b7,x:b2,y:b3,platform:Windows,\n03000000341a00000908000000000000,SL-6566,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,\n030000008f0e00000800000000000000,SpeedLink Strike FX,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,\n03000000c01100000591000000000000,Speedlink Torid,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,\n03000000d11800000094000000000000,Stadia Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:b11,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:Windows,\n03000000110100001914000000000000,SteelSeries,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftstick:b13,lefttrigger:b6,leftx:a0,lefty:a1,rightstick:b14,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,\n03000000381000001214000000000000,SteelSeries Free,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Windows,\n03000000110100003114000000000000,SteelSeries Stratus Duo,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,\n03000000381000001814000000000000,SteelSeries Stratus XL,a:b0,b:b1,back:b18,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,guide:b19,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b2,y:b3,platform:Windows,\n03000000790000001c18000000000000,STK-7024X,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,\n03000000ff1100003133000000000000,SVEN X-PAD,a:b2,b:b3,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a4,start:b5,x:b0,y:b1,platform:Windows,\n03000000d620000011a7000000000000,Switch,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n03000000457500002211000000000000,SZMY-POWER PC Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n030000004f04000007d0000000000000,T Mini Wireless,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n030000004f0400000ab1000000000000,T.16000M,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b4,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,start:b10,x:b2,y:b3,platform:Windows,\n03000000fa1900000706000000000000,Team 5,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,\n03000000b50700001203000000000000,Techmobility X6-38V,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows,\n030000004f04000015b3000000000000,Thrustmaster Dual Analog 4,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows,\n030000004f04000023b3000000000000,Thrustmaster Dual Trigger 3-in-1,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,\n030000004f0400000ed0000000000000,ThrustMaster eSwap PRO Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,\n030000004f04000000b3000000000000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,platform:Windows,\n030000004f04000004b3000000000000,Thrustmaster Firestorm Dual Power 3,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows,\n03000000666600000488000000000000,TigerGame PS/PS2 Game Controller Adapter,a:b2,b:b1,back:b9,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows,\n03000000d62000006000000000000000,Tournament PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n030000005f140000c501000000000000,Trust Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,\n03000000b80500000210000000000000,Trust Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,\n030000004f04000087b6000000000000,TWCS Throttle,dpdown:b8,dpleft:b9,dpright:b7,dpup:b6,leftstick:b5,lefttrigger:-a5,leftx:a0,lefty:a1,righttrigger:+a5,platform:Windows,\n03000000d90400000200000000000000,TwinShock PS2,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows,\n030000006e0500001320000000000000,U4113,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n03000000101c0000171c000000000000,uRage Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,\n03000000300f00000701000000000000,USB 4-Axis 12-Button Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows,\n03000000341a00002308000000000000,USB gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,\n030000005509000000b4000000000000,USB gamepad,a:b10,b:b11,back:b5,dpdown:b1,dpleft:b2,dpright:b3,dpup:b0,guide:b14,leftshoulder:b8,leftstick:b6,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b7,righttrigger:a5,rightx:a2,righty:a3,start:b4,x:b12,y:b13,platform:Windows,\n030000006b1400000203000000000000,USB gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,\n03000000790000000a00000000000000,USB gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b3,y:b0,platform:Windows,\n03000000f0250000c183000000000000,USB gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n03000000ff1100004133000000000000,USB gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a4,righty:a2,start:b9,x:b3,y:b0,platform:Windows,\n03000000632500002305000000000000,USB Vibration Joystick (BM),a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,\n03000000790000001a18000000000000,Venom,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n03000000790000001b18000000000000,Venom Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,\n030000006f0e00000302000000000000,Victrix Pro Fight Stick for PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,\n030000006f0e00000702000000000000,Victrix Pro Fight Stick for PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,\n0300000034120000adbe000000000000,vJoy Device,a:b0,b:b1,back:b15,dpdown:b6,dpleft:b7,dpright:b8,dpup:b5,guide:b16,leftshoulder:b9,leftstick:b13,lefttrigger:b11,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b14,righttrigger:b12,rightx:+a3,righty:+a4,start:b4,x:b2,y:b3,platform:Windows,\n030000005e0400000a0b000000000000,Xbox Adaptive Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,\n030000005e040000ff02000000007801,Xbox One Elite Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,\n030000005e040000130b000000000000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,\n03000000341a00000608000000000000,Xeox,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,\n03000000450c00002043000000000000,XEOX Gamepad SL-6556-BK,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,\n03000000ac0500005b05000000000000,Xiaoji Gamesir-G3w,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,\n03000000172700004431000000000000,XiaoMi Game Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b20,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a7,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows,\n03000000786901006e70000000000000,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,\nxinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,\n03000000790000004f18000000000000,ZD-T Android,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,\n03000000120c0000101e000000000000,ZEROPLUS P4 Wired Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,\n\n# Mac OS X\n030000008f0e00000300000009010000,2In1 USB Joystick,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X,\n03000000c82d00000090000001000000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,\n03000000c82d00001038000000010000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,\n03000000c82d00000650000001000000,8BitDo M30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,start:b11,x:b3,y:b4,platform:Mac OS X,\n03000000c82d00005106000000010000,8BitDo M30 Gamepad,a:b1,b:b0,back:b10,guide:b2,leftshoulder:b6,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,start:b11,x:b4,y:b3,platform:Mac OS X,\n03000000c82d00001590000001000000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,\n03000000c82d00006528000000010000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,\n030000003512000012ab000001000000,8BitDo NES30 Gamepad,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X,\n03000000022000000090000001000000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,\n03000000203800000900000000010000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,\n03000000c82d00000190000001000000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,\n03000000102800000900000000000000,8Bitdo SFC30 GamePad Joystick,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X,\n03000000c82d00001290000001000000,8BitDo SN30 Gamepad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X,\n03000000c82d00000160000001000000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,\n03000000c82d00000161000000010000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Mac OS X,\n03000000c82d00000260000001000000,8BitDo SN30 Pro+,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,\n03000000c82d00000261000000010000,8BitDo SN30 Pro+,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,\n03000000c82d00000031000001000000,8BitDo Wireless Adapter,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,\n03000000c82d00001890000001000000,8BitDo Zero 2,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X,\n03000000c82d00003032000000010000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a31,start:b11,x:b4,y:b3,platform:Mac OS X,\n03000000a00500003232000008010000,8Bitdo Zero GamePad,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Mac OS X,\n03000000a00500003232000009010000,8Bitdo Zero GamePad,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Mac OS X,\n03000000050b00000045000031000000,ASUS Gamepad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X,\n03000000c62400001a89000000010000,BDA MOGA XP5-X Plus,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b14,leftshoulder:b6,leftstick:b15,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b16,righttrigger:a4,rightx:a2,righty:a3,start:b13,x:b3,y:b4,platform:Mac OS X,\n03000000c62400001b89000000010000,BDA MOGA XP5-X Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,\n03000000d62000002a79000000010000,BDA PS4 Fightpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,\n030000008305000031b0000000000000,Cideko AK08b,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,\n03000000260900008888000088020000,Cyber Gadget GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a5,rightx:a2,righty:a3~,start:b7,x:b2,y:b3,platform:Mac OS X,\n03000000a306000022f6000001030000,Cyborg V.3 Rumble Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:-a3,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Mac OS X,\n03000000ad1b000001f9000000000000,Gamestop BB-070 X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,\n0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X,\n03000000c01100000140000000010000,GameStop PS4 Fun Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,\n030000006f0e00000102000000000000,GameStop Xbox 360 Wired Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,\n030000007d0400000540000001010000,Gravis Eliminator GamePad Pro,a:b1,b:b2,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X,\n030000000d0f00002d00000000100000,Hori Fighting Commander 3 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,\n030000000d0f00005f00000000010000,Hori Fighting Commander 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,\n030000000d0f00005e00000000010000,Hori Fighting Commander 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,\n030000000d0f00005f00000000000000,HORI Fighting Commander 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,\n030000000d0f00005e00000000000000,HORI Fighting Commander 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,\n030000000d0f00004d00000000000000,HORI Gem Pad 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,\n030000000d0f00009200000000010000,Hori Pokken Tournament DX Pro Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X,\n030000000d0f00006e00000000010000,HORIPAD 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,\n030000000d0f00006600000000010000,HORIPAD 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,\n030000000d0f00006600000000000000,HORIPAD FPS PLUS 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,\n030000000d0f0000ee00000000010000,HORIPAD mini4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,\n030000008f0e00001330000011010000,HuiJia SNES Controller,a:b4,b:b2,back:b16,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,leftshoulder:b12,rightshoulder:b14,start:b18,x:b6,y:b0,platform:Mac OS X,\n03000000830500006020000000010000,iBuffalo SNES Controller,a:b1,b:b0,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Mac OS X,\n03000000830500006020000000000000,iBuffalo USB 2-axis 8-button Gamepad,a:b1,b:b0,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Mac OS X,\n030000007e0500000620000001000000,Joy-Con (L),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b13,leftshoulder:b4,leftstick:b10,rightshoulder:b5,start:b8,x:b2,y:b3,platform:Mac OS X,\n030000007e0500000720000001000000,Joy-Con (R),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b12,leftshoulder:b4,leftstick:b11,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Mac OS X,\n03000000242f00002d00000007010000,JYS Wireless Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X,\n030000006d04000016c2000000020000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,\n030000006d04000016c2000000030000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,\n030000006d04000016c2000014040000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,\n030000006d04000016c2000000000000,Logitech F310 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,\n030000006d04000018c2000000000000,Logitech F510 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,\n030000006d04000019c2000005030000,Logitech F710,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,\n030000006d0400001fc2000000000000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,\n030000006d04000018c2000000010000,Logitech RumblePad 2 USB,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3~,start:b9,x:b0,y:b3,platform:Mac OS X,\n030000006d04000019c2000000000000,Logitech Wireless Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,\n03000000380700005032000000010000,Mad Catz FightPad PRO (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,\n03000000380700005082000000010000,Mad Catz FightPad PRO (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,\n03000000380700008433000000010000,Mad Catz FightStick TE S+ (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,\n03000000380700008483000000010000,Mad Catz FightStick TE S+ (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,\n03000000790000004418000000010000,Mayflash GameCube Controller,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Mac OS X,\n03000000242f00007300000000020000,Mayflash Magic NS,a:b1,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b0,y:b3,platform:Mac OS X,\n0300000079000000d218000026010000,Mayflash Magic NS,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X,\n03000000d620000010a7000003010000,Mayflash Magic NS,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,\n0300000025090000e803000000000000,Mayflash Wii Classic Controller,a:b1,b:b0,back:b8,dpdown:b13,dpleft:b12,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Mac OS X,\n03000000790000000018000000000000,Mayflash WiiU Pro Game Controller Adapter (DInput),a:b4,b:b8,back:b32,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b16,leftstick:b40,lefttrigger:b24,leftx:a0,lefty:a4,rightshoulder:b20,rightstick:b44,righttrigger:b28,rightx:a8,righty:a12,start:b36,x:b0,y:b12,platform:Mac OS X,\n03000000d8140000cecf000000000000,MC Cthulhu,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X,\n030000005e0400002700000001010000,Microsoft SideWinder Plug & Play Game Pad,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,lefttrigger:b4,leftx:a0,lefty:a1,righttrigger:b5,x:b2,y:b3,platform:Mac OS X,\n03000000d62000007162000001000000,Moga Pro 2 HID,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Mac OS X,\n03000000c62400002a89000000010000,MOGA XP5-A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b21,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,\n03000000c62400002b89000000010000,MOGA XP5-A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,\n03000000632500007505000000020000,NEOGEO mini PAD Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b9,x:b2,y:b3,platform:Mac OS X,\n030000001008000001e5000006010000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b6,start:b9,x:b3,y:b0,platform:Mac OS X,\n03000000d620000011a7000000020000,Nintendo Switch Core (Plus) Wired Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,\n030000007e0500000920000000000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X,\n030000007e0500000920000001000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X,\n03000000550900001472000025050000,NVIDIA Controller v01.04,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b4,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Mac OS X,\n030000006f0e00000901000002010000,PDP Versus Fighting Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X,\n030000008f0e00000300000000000000,Piranha xtreme,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Mac OS X,\n030000004c050000da0c000000010000,Playstation Classic Controller,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Mac OS X,\n03000000d62000006dca000000010000,PowerA Pro Ex,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,\n030000004c0500006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Mac OS X,\n030000004c0500006802000000010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Mac OS X,\n030000004c050000a00b000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,\n030000004c050000c405000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,\n030000004c050000c405000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,\n030000004c050000cc09000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,\n050000004c050000e60c000000010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,\n030000008916000000fd000000000000,Razer Onza TE,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,\n03000000321500000204000000010000,Razer Panthera (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,\n03000000321500000104000000010000,Razer Panthera (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,\n03000000321500000010000000010000,Razer RAIJU,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,\n03000000321500000507000001010000,Razer Raiju Mobile,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b21,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,\n03000000321500000011000000010000,Razer Raion Fightpad for PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,\n03000000321500000009000000020000,Razer Serval,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Mac OS X,\n030000003215000000090000163a0000,Razer Serval,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Mac OS X,\n0300000032150000030a000000000000,Razer Wildcat,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,\n03000000790000001100000000000000,Retrolink Classic Controller,a:b2,b:b1,back:b8,leftshoulder:b4,leftx:a3,lefty:a4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X,\n03000000790000001100000006010000,Retrolink SNES Controller,a:b2,b:b1,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X,\n030000006b140000010d000000010000,Revolution Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,\n030000006b140000130d000000010000,Revolution Pro Controller 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,\n03000000c6240000fefa000000000000,Rock Candy Gamepad for PS3,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,\n03000000730700000401000000010000,Sanwa PlayOnline Mobile,a:b0,b:b1,back:b2,leftx:a0,lefty:a1,start:b3,platform:Mac OS X,\n03000000811700007e05000000000000,Sega Saturn,a:b2,b:b4,dpdown:b16,dpleft:b15,dpright:b14,dpup:b17,leftshoulder:b8,lefttrigger:a5,leftx:a0,lefty:a2,rightshoulder:b9,righttrigger:a4,start:b13,x:b0,y:b6,platform:Mac OS X,\n03000000b40400000a01000000000000,Sega Saturn USB Gamepad,a:b0,b:b1,back:b5,guide:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b8,x:b3,y:b4,platform:Mac OS X,\n030000003512000021ab000000000000,SFC30 Joystick,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X,\n0300000000f00000f100000000000000,SNES RetroPort,a:b2,b:b3,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b5,rightshoulder:b7,start:b6,x:b0,y:b1,platform:Mac OS X,\n030000004c050000e60c000000010000,Sony DualSense,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,\n030000004c050000cc09000000000000,Sony DualShock 4 V2,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,\n030000004c050000a00b000000000000,Sony DualShock 4 Wireless Adaptor,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,\n03000000d11800000094000000010000,Stadia Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Mac OS X,\n030000005e0400008e02000001000000,Steam Virtual Gamepad,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,\n03000000110100002014000000000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b12,x:b2,y:b3,platform:Mac OS X,\n03000000110100002014000001000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,x:b2,y:b3,platform:Mac OS X,\n03000000381000002014000001000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,x:b2,y:b3,platform:Mac OS X,\n03000000110100001714000000000000,SteelSeries Stratus XL,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,start:b12,x:b2,y:b3,platform:Mac OS X,\n03000000110100001714000020010000,SteelSeries Stratus XL,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,start:b12,x:b2,y:b3,platform:Mac OS X,\n03000000457500002211000000010000,SZMY-POWER PC Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,\n030000004f04000015b3000000000000,Thrustmaster Dual Analog 3.2,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Mac OS X,\n030000004f0400000ed0000000020000,ThrustMaster eSwap PRO Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,\n030000004f04000000b3000000000000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,platform:Mac OS X,\n03000000bd12000015d0000000000000,Tomee SNES USB Controller,a:b2,b:b1,back:b8,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X,\n03000000bd12000015d0000000010000,Tomee SNES USB Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X,\n03000000100800000100000000000000,Twin USB Joystick,a:b4,b:b2,back:b16,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b12,leftstick:b20,lefttrigger:b8,leftx:a0,lefty:a2,rightshoulder:b14,rightstick:b22,righttrigger:b10,rightx:a6,righty:a4,start:b18,x:b6,y:b0,platform:Mac OS X,\n030000006f0e00000302000025040000,Victrix Pro Fight Stick for PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X,\n030000006f0e00000702000003060000,Victrix Pro Fight Stick for PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X,\n03000000791d00000103000009010000,Wii Classic Controller,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b10,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X,\n050000005769696d6f74652028303000,Wii Remote,a:b4,b:b5,back:b7,dpdown:b3,dpleft:b0,dpright:b1,dpup:b2,guide:b8,leftshoulder:b11,lefttrigger:b12,leftx:a0,lefty:a1,start:b6,x:b10,y:b9,platform:Mac OS X,\n050000005769696d6f74652028313800,Wii U Pro Controller,a:b16,b:b15,back:b7,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b8,leftshoulder:b19,leftstick:b23,lefttrigger:b21,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b24,righttrigger:b22,rightx:a2,righty:a3,start:b6,x:b18,y:b17,platform:Mac OS X,\n030000005e0400008e02000000000000,X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,\n03000000c6240000045d000000000000,Xbox 360 Wired Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,\n030000005e0400000a0b000000000000,Xbox Adaptive Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,\n030000005e040000050b000003090000,Xbox Elite Wireless Controller Series 2,a:b0,b:b1,back:b31,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b53,leftshoulder:b6,leftstick:b13,lefttrigger:a6,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,\n030000005e040000d102000000000000,Xbox One Wired Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,\n030000005e040000dd02000000000000,Xbox One Wired Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,\n030000005e040000e302000000000000,Xbox One Wired Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,\n030000005e040000130b000001050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,\n030000005e040000130b000005050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,\n030000005e040000e002000000000000,Xbox Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Mac OS X,\n030000005e040000e002000003090000,Xbox Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Mac OS X,\n030000005e040000ea02000000000000,Xbox Wireless Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,\n030000005e040000fd02000003090000,Xbox Wireless Controller,a:b0,b:b1,back:b16,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,\n03000000172700004431000029010000,XiaoMi Game Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a6,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Mac OS X,\n03000000120c0000100e000000010000,ZEROPLUS P4 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,\n03000000120c0000101e000000010000,ZEROPLUS P4 Wired Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,\n\n# Linux\n03000000c82d00000090000011010000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,\n05000000c82d00001038000000010000,8Bitdo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,\n05000000c82d00005106000000010000,8BitDo M30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,start:b11,x:b3,y:b4,platform:Linux,\n03000000c82d00001590000011010000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,\n05000000c82d00006528000000010000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,\n03000000c82d00000310000011010000,8BitDo NES30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b7,lefttrigger:b6,rightshoulder:b9,righttrigger:b8,start:b11,x:b3,y:b4,platform:Linux,\n05000000c82d00008010000000010000,8BitDo NES30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b7,lefttrigger:b6,rightshoulder:b9,righttrigger:b8,start:b11,x:b3,y:b4,platform:Linux,\n03000000022000000090000011010000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,\n05000000203800000900000000010000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,\n05000000c82d00002038000000010000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,\n03000000c82d00000190000011010000,8Bitdo NES30 Pro 8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,\n05000000c82d00000060000000010000,8BitDo SF30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,\n05000000c82d00000061000000010000,8Bitdo SF30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,\n03000000c82d000021ab000010010000,8BitDo SFC30,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux,\n030000003512000012ab000010010000,8Bitdo SFC30 GamePad,a:b2,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b0,platform:Linux,\n05000000102800000900000000010000,8Bitdo SFC30 GamePad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux,\n05000000c82d00003028000000010000,8Bitdo SFC30 GamePad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux,\n03000000c82d00000160000000000000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Linux,\n03000000c82d00000160000011010000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,\n03000000c82d00000161000000000000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Linux,\n03000000c82d00001290000011010000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Linux,\n05000000c82d00000161000000010000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,\n05000000c82d00006228000000010000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,\n03000000c82d00000260000011010000,8BitDo SN30 Pro+,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,\n05000000c82d00000261000000010000,8BitDo SN30 Pro+,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,\n05000000202800000900000000010000,8BitDo SNES30 Gamepad,a:b1,b:b0,back:b10,dpdown:b122,dpleft:b119,dpright:b120,dpup:b117,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux,\n030000005e0400008e02000020010000,8BitDo Wireless Adapter (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n03000000c82d00000031000011010000,8BitDo Wireless Adapter (DInput),a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,\n03000000c82d00001890000011010000,8BitDo Zero 2,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux,\n05000000c82d00003032000000010000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,\n05000000a00500003232000001000000,8Bitdo Zero GamePad,a:b0,b:b1,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Linux,\n05000000a00500003232000008010000,8Bitdo Zero GamePad,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Linux,\n030000006f0e00001302000000010000,Afterglow,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n030000006f0e00003901000020060000,Afterglow Controller for Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n030000006f0e00003901000000430000,Afterglow Prismatic Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n030000006f0e00003901000013020000,Afterglow Prismatic Wired Controller 048-007-NA,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n03000000100000008200000011010000,Akishop Customs PS360+ v1.66,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,\n030000007c1800000006000010010000,Alienware Dual Compatible Game Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b3,platform:Linux,\n05000000491900000204000021000000,Amazon Fire Game Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b17,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b12,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,\n03000000790000003018000011010000,Arcade Fightstick F300,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,\n05000000050b00000045000031000000,ASUS Gamepad,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b10,x:b2,y:b3,platform:Linux,\n05000000050b00000045000040000000,ASUS Gamepad,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b10,x:b2,y:b3,platform:Linux,\n03000000120c00000500000010010000,AxisPad,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Linux,\n03000000c62400001b89000011010000,BDA MOGA XP5-X Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,\n03000000d62000002a79000011010000,BDA PS4 Fightpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,\n03000000c21100000791000011010000,Be1 GC101 Controller 1.03 mode,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,\n03000000c31100000791000011010000,Be1 GC101 GAMEPAD 1.03 mode,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,\n030000005e0400008e02000003030000,Be1 GC101 Xbox 360 Controller mode,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n03000000666600006706000000010000,boom PSX to PC Converter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,platform:Linux,\n03000000ffff0000ffff000000010000,Chinese-made Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux,\n03000000e82000006058000001010000,Cideko AK08b,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,\n030000000b0400003365000000010000,Competition Pro,a:b0,b:b1,back:b2,leftx:a0,lefty:a1,start:b3,platform:Linux,\n03000000260900008888000000010000,Cyber Gadget GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a5,rightx:a2,righty:a3~,start:b7,x:b2,y:b3,platform:Linux,\n03000000a306000022f6000011010000,Cyborg V.3 Rumble Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:-a3,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Linux,\n03000000b40400000a01000000010000,CYPRESS USB Gamepad,a:b0,b:b1,back:b5,guide:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b8,x:b3,y:b4,platform:Linux,\n03000000790000000600000010010000,DragonRise Inc. Generic USB Joystick,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b3,y:b0,platform:Linux,\n030000004f04000004b3000010010000,Dual Power 2,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux,\n030000006f0e00003001000001010000,EA Sports PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,\n03000000341a000005f7000010010000,GameCube {HuiJia USB box},a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Linux,\n03000000bc2000000055000011010000,GameSir G3w,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,\n0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,\n030000006f0e00000104000000010000,Gamestop Logic3 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n030000008f0e00000800000010010000,Gasia Co. Ltd PS(R) Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,\n030000006f0e00001304000000010000,Generic X-Box pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n03000000f0250000c183000010010000,Goodbetterbest Ltd USB Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,\n0300000079000000d418000000010000,GPD Win 2 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n030000007d0400000540000000010000,Gravis Eliminator GamePad Pro,a:b1,b:b2,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,\n03000000280400000140000000010000,Gravis GamePad Pro USB ,a:b1,b:b2,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,\n030000008f0e00000610000000010000,GreenAsia Electronics 4Axes 12Keys GamePad ,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a3,righty:a2,start:b11,x:b3,y:b0,platform:Linux,\n030000008f0e00001200000010010000,GreenAsia Inc. USB Joystick,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux,\n0500000047532067616d657061640000,GS gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,\n03000000f0250000c383000010010000,GT VX2,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,\n06000000adde0000efbe000002010000,Hidromancer Game Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n03000000d81400000862000011010000,HitBox (PS3/PC) Analog Mode,a:b1,b:b2,back:b8,guide:b9,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b12,x:b0,y:b3,platform:Linux,\n03000000c9110000f055000011010000,HJC Game GAMEPAD,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,\n03000000632500002605000010010000,HJD-X,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,\n030000000d0f00000d00000000010000,hori,a:b0,b:b6,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b3,leftx:b4,lefty:b5,rightshoulder:b7,start:b9,x:b1,y:b2,platform:Linux,\n030000000d0f00001000000011010000,HORI CO. LTD. FIGHTING STICK 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,\n030000000d0f0000c100000011010000,HORI CO. LTD. HORIPAD S,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b13,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,\n030000000d0f00006a00000011010000,HORI CO. LTD. Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,\n030000000d0f00006b00000011010000,HORI CO. LTD. Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,\n030000000d0f00002200000011010000,HORI CO. LTD. REAL ARCADE Pro.V3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,\n030000000d0f00008500000010010000,HORI Fighting Commander,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,\n030000000d0f00008600000002010000,Hori Fighting Commander,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,\n030000000d0f00005f00000011010000,Hori Fighting Commander 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,\n030000000d0f00005e00000011010000,Hori Fighting Commander 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,\n03000000ad1b000001f5000033050000,Hori Pad EX Turbo 2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n030000000d0f00009200000011010000,Hori Pokken Tournament DX Pro Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,\n030000000d0f0000aa00000011010000,HORI Real Arcade Pro,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,\n030000000d0f0000d800000072056800,HORI Real Arcade Pro S,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Linux,\n030000000d0f00001600000000010000,Hori Real Arcade Pro.EX-SE (Xbox 360),a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b2,y:b3,platform:Linux,\n030000000d0f00006e00000011010000,HORIPAD 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,\n030000000d0f00006600000011010000,HORIPAD 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,\n030000000d0f0000ee00000011010000,HORIPAD mini4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,\n030000000d0f00006700000001010000,HORIPAD ONE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n030000008f0e00001330000010010000,HuiJia SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b9,x:b3,y:b0,platform:Linux,\n03000000242e00008816000001010000,Hyperkin X91,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n03000000830500006020000010010000,iBuffalo SNES Controller,a:b1,b:b0,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Linux,\n050000006964726f69643a636f6e0000,idroid:con,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,\n03000000b50700001503000010010000,impact,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Linux,\n03000000d80400008200000003000000,IMS PCU#0 Gamepad Interface,a:b1,b:b0,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b5,x:b3,y:b2,platform:Linux,\n03000000fd0500000030000000010000,InterAct GoPad I-73000 (Fighting Game Layout),a:b3,b:b4,back:b6,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,start:b7,x:b0,y:b1,platform:Linux,\n0500000049190000020400001b010000,Ipega PG-9069 - Bluetooth Gamepad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b161,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,\n03000000632500007505000011010000,Ipega PG-9099 - Bluetooth Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,\n030000006e0500000320000010010000,JC-U3613M - DirectInput Mode,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Linux,\n03000000300f00001001000010010000,Jess Tech Dual Analog Rumble Pad,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Linux,\n03000000300f00000b01000010010000,Jess Tech GGE909 PC Recoil Pad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux,\n03000000ba2200002010000001010000,Jess Technology USB Game Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux,\n030000007e0500000620000001000000,Joy-Con (L),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b13,leftshoulder:b4,leftstick:b10,rightshoulder:b5,start:b8,x:b2,y:b3,platform:Linux,\n050000007e0500000620000001000000,Joy-Con (L),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b13,leftshoulder:b4,leftstick:b10,rightshoulder:b5,start:b8,x:b2,y:b3,platform:Linux,\n030000007e0500000720000001000000,Joy-Con (R),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b12,leftshoulder:b4,leftstick:b11,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Linux,\n050000007e0500000720000001000000,Joy-Con (R),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b12,leftshoulder:b4,leftstick:b11,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Linux,\n03000000242f00002d00000011010000,JYS Wireless Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,\n03000000242f00008a00000011010000,JYS Wireless Adapter,a:b1,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b0,y:b3,platform:Linux,\n030000006f0e00000103000000020000,Logic3 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n030000006d040000d1ca000000000000,Logitech ChillStream,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,\n030000006d04000019c2000010010000,Logitech Cordless RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,\n030000006d04000016c2000010010000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,\n030000006d04000016c2000011010000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,\n030000006d0400001dc2000014400000,Logitech F310 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n030000006d0400001ec2000019200000,Logitech F510 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n030000006d0400001ec2000020200000,Logitech F510 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n030000006d04000019c2000011010000,Logitech F710 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,\n030000006d0400001fc2000005030000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n030000006d0400000ac2000010010000,Logitech Inc. WingMan RumblePad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,rightx:a3,righty:a4,x:b3,y:b4,platform:Linux,\n030000006d04000018c2000010010000,Logitech RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,\n030000006d04000011c2000010010000,Logitech WingMan Cordless RumblePad,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b6,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b10,rightx:a3,righty:a4,start:b8,x:b3,y:b4,platform:Linux,\n050000004d4f435554452d3035305800,M54-PC,a:b0,b:b1,x:b3,y:b4,back:b10,start:b11,leftshoulder:b6,rightshoulder:b7,leftstick:b13,rightstick:b14,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a5,righttrigger:a4,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,platform:Linux,\n05000000380700006652000025010000,Mad Catz C.T.R.L.R ,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,\n03000000380700005032000011010000,Mad Catz FightPad PRO (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,\n03000000380700005082000011010000,Mad Catz FightPad PRO (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,\n03000000ad1b00002ef0000090040000,Mad Catz Fightpad SFxT,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,start:b7,x:b2,y:b3,platform:Linux,\n03000000380700008034000011010000,Mad Catz fightstick (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,\n03000000380700008084000011010000,Mad Catz fightstick (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,\n03000000380700008433000011010000,Mad Catz FightStick TE S+ (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,\n03000000380700008483000011010000,Mad Catz FightStick TE S+ (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,\n03000000380700001647000010040000,Mad Catz Wired Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n03000000380700003847000090040000,Mad Catz Wired Xbox 360 Controller (SFIV),a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,\n03000000ad1b000016f0000090040000,Mad Catz Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n03000000380700001888000010010000,MadCatz PC USB Wired Stick 8818,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,\n03000000380700003888000010010000,MadCatz PC USB Wired Stick 8838,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:a0,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,\n03000000120c00000500000000010000,Manta Dualshock 2,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux,\n03000000790000004418000010010000,Mayflash GameCube Controller,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Linux,\n03000000790000004318000010010000,Mayflash GameCube Controller Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Linux,\n03000000242f00007300000011010000,Mayflash Magic NS,a:b1,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b0,y:b3,platform:Linux,\n0300000079000000d218000011010000,Mayflash Magic NS,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,\n03000000d620000010a7000011010000,Mayflash Magic NS,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,\n0300000025090000e803000001010000,Mayflash Wii Classic Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:a4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:a5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Linux,\n03000000780000000600000010010000,Microntek USB Joystick,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux,\n030000005e0400000e00000000010000,Microsoft SideWinder,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,rightshoulder:b7,start:b8,x:b3,y:b4,platform:Linux,\n030000005e0400008e02000004010000,Microsoft X-Box 360 pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n030000005e0400008e02000062230000,Microsoft X-Box 360 pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n050000005e040000050b000003090000,Microsoft X-Box One Elite 2 pad,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a6,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,\n030000005e040000e302000003020000,Microsoft X-Box One Elite pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n030000005e040000d102000001010000,Microsoft X-Box One pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n030000005e040000dd02000003020000,Microsoft X-Box One pad (Firmware 2015),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n030000005e040000d102000003020000,Microsoft X-Box One pad v2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n030000005e0400008502000000010000,Microsoft X-Box pad (Japan),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux,\n030000005e0400008902000021010000,Microsoft X-Box pad v2 (US),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux,\n030000005e040000000b000008040000,Microsoft Xbox One Elite 2 pad - Wired,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n030000005e040000ea02000008040000,Microsoft Xbox One S pad - Wired,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n03000000c62400001a53000000010000,Mini PE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n03000000030000000300000002000000,Miroof,a:b1,b:b0,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Linux,\n05000000d6200000e589000001000000,Moga 2 HID,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Linux,\n05000000d6200000ad0d000001000000,Moga Pro,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Linux,\n05000000d62000007162000001000000,Moga Pro 2 HID,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Linux,\n03000000c62400002b89000011010000,MOGA XP5-A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,\n05000000c62400002a89000000010000,MOGA XP5-A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b22,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,\n05000000c62400001a89000000010000,MOGA XP5-X Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,\n03000000250900006688000000010000,MP-8866 Super Dual Box,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Linux,\n030000006b140000010c000010010000,NACON GC-400ES,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,\n030000000d0f00000900000010010000,Natec Genesis P44,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,\n030000001008000001e5000010010000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b6,start:b9,x:b3,y:b0,platform:Linux,\n060000007e0500000820000000000000,Nintendo Combined Joy-Cons (joycond),a:b0,b:b1,back:b9,dpdown:b15,dpleft:b16,dpright:b17,dpup:b14,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux,\n030000007e0500003703000000016800,Nintendo GameCube Controller,a:b0,b:b2,dpdown:b6,dpleft:b4,dpright:b5,dpup:b7,lefttrigger:a4,leftx:a0,lefty:a1~,rightshoulder:b9,righttrigger:a5,rightx:a2,righty:a3~,start:b8,x:b1,y:b3,platform:Linux,\n03000000790000004618000010010000,Nintendo GameCube Controller Adapter,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a5~,righty:a2~,start:b9,x:b0,y:b3,platform:Linux,\n050000007e0500000920000001000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,\n050000007e0500000920000001800000,Nintendo Switch Pro Controller (joycond),a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux,\n030000007e0500000920000011810000,Nintendo Switch Pro Controller Wired (joycond),a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux,\n050000007e0500003003000001000000,Nintendo Wii Remote Pro Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Linux,\n05000000010000000100000003000000,Nintendo Wiimote,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,\n030000000d0500000308000010010000,Nostromo n45 Dual Analog Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b12,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b10,x:b2,y:b3,platform:Linux,\n03000000550900001072000011010000,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b13,leftshoulder:b4,leftstick:b8,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux,\n03000000550900001472000011010000,NVIDIA Controller v01.04,a:b0,b:b1,back:b14,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b4,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Linux,\n05000000550900001472000001000000,NVIDIA Controller v01.04,a:b0,b:b1,back:b14,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b4,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Linux,\n03000000451300000830000010010000,NYKO CORE,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,\n19000000010000000100000001010000,odroidgo2_joypad,a:b1,b:b0,dpdown:b7,dpleft:b8,dpright:b9,dpup:b6,guide:b10,leftshoulder:b4,leftstick:b12,lefttrigger:b11,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b13,righttrigger:b14,start:b15,x:b2,y:b3,platform:Linux,\n19000000010000000200000011000000,odroidgo2_joypad_v11,a:b1,b:b0,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b12,leftshoulder:b4,leftstick:b14,lefttrigger:b13,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b15,righttrigger:b16,start:b17,x:b2,y:b3,platform:Linux,\n030000005e0400000202000000010000,Old Xbox pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux,\n05000000362800000100000002010000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,platform:Linux,\n05000000362800000100000003010000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,platform:Linux,\n03000000830500005020000010010000,Padix Co. Ltd. Rockfire PSX/USB Bridge,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b2,y:b3,platform:Linux,\n03000000790000001c18000011010000,PC Game Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,\n03000000ff1100003133000010010000,PC Game Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,\n030000006f0e0000b802000001010000,PDP AFTERGLOW Wired Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n030000006f0e0000b802000013020000,PDP AFTERGLOW Wired Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n030000006f0e00006401000001010000,PDP Battlefield One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n030000006f0e00008001000011010000,PDP CO. LTD. Faceoff Wired Pro Controller for Nintendo Switch,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,\n030000006f0e00003101000000010000,PDP EA Sports Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n030000006f0e0000c802000012010000,PDP Kingdom Hearts Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n030000006f0e00008701000011010000,PDP Rock Candy Wired Controller for Nintendo Switch,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b13,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,\n030000006f0e00000901000011010000,PDP Versus Fighting Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,\n030000006f0e0000a802000023020000,PDP Wired Controller for Xbox One,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,\n030000006f0e00008501000011010000,PDP Wired Fight Pad Pro for Nintendo Switch,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,\n05000000491900000204000000000000,PG-9118,x:b76,a:b73,b:b74,y:b77,back:b83,start:b84,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b79,lefttrigger:b81,rightshoulder:b80,righttrigger:b82,leftstick:b86,rightstick:b87,leftx:a0,lefty:a1,rightx:a2,righty:a3,platform:Linux,\n0500000049190000030400001b010000,PG-9099,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,\n030000004c050000da0c000011010000,Playstation Controller,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux,\n03000000c62400000053000000010000,PowerA,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n03000000c62400003a54000001010000,PowerA 1428124-01,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n03000000d62000006dca000011010000,PowerA Pro Ex,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,\n03000000c62400001a58000001010000,PowerA Xbox One Cabled,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n030000006d040000d2ca000011010000,Precision Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,\n03000000ff1100004133000010010000,PS2 Controller,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux,\n03000000341a00003608000011010000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,\n030000004c0500006802000010010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux,\n030000004c0500006802000010810000,PS3 Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,\n030000004c0500006802000011010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux,\n030000004c0500006802000011810000,PS3 Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,\n030000006f0e00001402000011010000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,\n030000008f0e00000300000010010000,PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,\n050000004c0500006802000000010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:a12,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:a13,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux,\n050000004c0500006802000000800000,PS3 Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,\n050000004c0500006802000000810000,PS3 Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,\n05000000504c415953544154494f4e00,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux,\n060000004c0500006802000000010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux,\n030000004c050000a00b000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,\n030000004c050000a00b000011810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,\n030000004c050000c405000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,\n030000004c050000c405000011810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,\n030000004c050000cc09000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,\n030000004c050000cc09000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,\n030000004c050000cc09000011810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,\n03000000c01100000140000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,\n050000004c050000c405000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,\n050000004c050000c405000000810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,\n050000004c050000c405000001800000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,\n050000004c050000cc09000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,\n050000004c050000cc09000000810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,\n050000004c050000cc09000001800000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,\n030000004c050000e60c000011010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,\n050000004c050000e60c000000010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,\n03000000300f00001211000011010000,QanBa Arcade JoyStick,a:b2,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b5,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b6,start:b9,x:b1,y:b3,platform:Linux,\n030000009b2800003200000001010000,Raphnet Technologies GC/N64 to USB v3.4,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Linux,\n030000009b2800006000000001010000,Raphnet Technologies GC/N64 to USB v3.6,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Linux,\n030000009b2800000300000001010000,raphnet.net 4nes4snes v1.5,a:b0,b:b4,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Linux,\n030000008916000001fd000024010000,Razer Onza Classic Edition,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n030000008916000000fd000024010000,Razer Onza Tournament Edition,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n03000000321500000204000011010000,Razer Panthera (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,\n03000000321500000104000011010000,Razer Panthera (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,\n03000000321500000810000011010000,Razer Panthera Evo Arcade Stick for PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b13,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,\n03000000321500000010000011010000,Razer RAIJU,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,\n03000000321500000507000000010000,Razer Raiju Mobile,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b21,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,\n03000000321500000011000011010000,Razer Raion Fightpad for PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,\n030000008916000000fe000024010000,Razer Sabertooth,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n03000000c6240000045d000024010000,Razer Sabertooth,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n03000000c6240000045d000025010000,Razer Sabertooth,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n03000000321500000009000011010000,Razer Serval,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux,\n050000003215000000090000163a0000,Razer Serval,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux,\n0300000032150000030a000001010000,Razer Wildcat,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n03000000790000001100000010010000,Retrolink SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Linux,\n0300000081170000990a000001010000,Retronic Adapter,a:b0,leftx:a0,lefty:a1,platform:Linux,\n0300000000f000000300000000010000,RetroPad,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Linux,\n030000006b140000010d000011010000,Revolution Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,\n030000006b140000130d000011010000,Revolution Pro Controller 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,\n030000006f0e00001f01000000010000,Rock Candy,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n030000006f0e00001e01000011010000,Rock Candy PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,\n030000006f0e00004601000001010000,Rock Candy Xbox One Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n03000000a306000023f6000011010000,Saitek Cyborg V.1 Game Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Linux,\n03000000a30600001005000000010000,Saitek P150,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b7,lefttrigger:b6,rightshoulder:b2,righttrigger:b5,x:b3,y:b4,platform:Linux,\n03000000a30600000701000000010000,Saitek P220,a:b2,b:b3,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b4,righttrigger:b5,x:b0,y:b1,platform:Linux,\n03000000a30600000cff000010010000,Saitek P2500 Force Rumble Pad,a:b2,b:b3,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b10,x:b0,y:b1,platform:Linux,\n03000000a30600000c04000011010000,Saitek P2900 Wireless Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b12,x:b0,y:b3,platform:Linux,\n03000000300f00001201000010010000,Saitek P380,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Linux,\n03000000a30600000901000000010000,Saitek P880,a:b2,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,x:b0,y:b1,platform:Linux,\n03000000a30600000b04000000010000,Saitek P990 Dual Analog Pad,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b8,x:b0,y:b3,platform:Linux,\n03000000a306000018f5000010010000,Saitek PLC Saitek P3200 Rumble Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Linux,\n03000000a306000020f6000011010000,Saitek PS2700 Rumble Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Linux,\n03000000d81d00000e00000010010000,Savior,a:b0,b:b1,back:b8,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b11,righttrigger:b3,start:b9,x:b4,y:b5,platform:Linux,\n03000000c01600008704000011010000,Serial/Keyboard/Mouse/Joystick,a:b12,b:b10,back:b4,dpdown:b2,dpleft:b3,dpright:b1,dpup:b0,leftshoulder:b9,leftstick:b14,lefttrigger:b6,leftx:a1,lefty:a0,rightshoulder:b8,rightstick:b15,righttrigger:b7,rightx:a2,righty:a3,start:b5,x:b13,y:b11,platform:Linux,\n03000000f025000021c1000010010000,ShanWan Gioteck PS3 Wired Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,\n03000000632500007505000010010000,SHANWAN PS3/PC Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,\n03000000bc2000000055000010010000,ShanWan PS3/PC Wired GamePad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,\n03000000632500002305000010010000,ShanWan USB Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,\n03000000341a00000908000010010000,SL-6566,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,\n03000000250900000500000000010000,Sony PS2 pad with SmartJoy adapter,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Linux,\n030000005e0400008e02000073050000,Speedlink TORID Wireless Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n030000005e0400008e02000020200000,SpeedLink XEOX Pro Analog Gamepad pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n03000000d11800000094000011010000,Stadia Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux,\n03000000de2800000112000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,\n03000000de2800000211000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,\n03000000de2800000211000011010000,Steam Controller,a:b2,b:b3,back:b10,dpdown:b18,dpleft:b19,dpright:b20,dpup:b17,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b5,platform:Linux,\n03000000de2800004211000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,\n03000000de2800004211000011010000,Steam Controller,a:b2,b:b3,back:b10,dpdown:b18,dpleft:b19,dpright:b20,dpup:b17,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b5,platform:Linux,\n03000000de280000fc11000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n05000000de2800000212000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,\n05000000de2800000511000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,\n05000000de2800000611000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,\n03000000de280000ff11000001000000,Steam Virtual Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n03000000381000003014000075010000,SteelSeries Stratus Duo,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n03000000381000003114000075010000,SteelSeries Stratus Duo,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n0500000011010000311400001b010000,SteelSeries Stratus Duo,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b32,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,\n05000000110100001914000009010000,SteelSeries Stratus XL,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,\n03000000ad1b000038f0000090040000,Street Fighter IV FightStick TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n030000003b07000004a1000000010000,Suncom SFX Plus for USB,a:b0,b:b2,back:b7,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b5,start:b8,x:b1,y:b3,platform:Linux,\n03000000666600000488000000010000,Super Joy Box 5 Pro,a:b2,b:b1,back:b9,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Linux,\n0300000000f00000f100000000010000,Super RetroPort,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Linux,\n03000000457500002211000010010000,SZMY-POWER CO. LTD. GAMEPAD,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,\n030000008f0e00000d31000010010000,SZMY-POWER CO. LTD. GAMEPAD 3 TURBO,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,\n030000008f0e00001431000010010000,SZMY-POWER CO.,LTD. PS3 gamepad,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Linux,\n030000004f04000020b3000010010000,Thrustmaster 2 in 1 DT,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux,\n030000004f04000015b3000010010000,Thrustmaster Dual Analog 4,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux,\n030000004f04000023b3000000010000,Thrustmaster Dual Trigger 3-in-1,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,\n030000004f0400000ed0000011010000,ThrustMaster eSwap PRO Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,\n03000000b50700000399000000010000,Thrustmaster Firestorm Digital 2,a:b2,b:b4,back:b11,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b8,rightstick:b0,righttrigger:b9,start:b1,x:b3,y:b5,platform:Linux,\n030000004f04000003b3000010010000,Thrustmaster Firestorm Dual Analog 2,a:b0,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b9,rightx:a2,righty:a3,x:b1,y:b3,platform:Linux,\n030000004f04000000b3000010010000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,platform:Linux,\n030000004f04000026b3000002040000,Thrustmaster Gamepad GP XID,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n03000000c6240000025b000002020000,Thrustmaster GPX Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n030000004f04000008d0000000010000,Thrustmaster Run N Drive Wireless,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,\n030000004f04000009d0000000010000,Thrustmaster Run N Drive Wireless PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,\n030000004f04000007d0000000010000,Thrustmaster T Mini Wireless,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,\n030000004f04000012b3000010010000,Thrustmaster vibrating gamepad,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux,\n03000000bd12000015d0000010010000,Tomee SNES USB Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Linux,\n03000000d814000007cd000011010000,Toodles 2008 Chimp PC/PS3,a:b0,b:b1,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b3,y:b2,platform:Linux,\n030000005e0400008e02000070050000,Torid,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n03000000c01100000591000011010000,Torid,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,\n03000000100800000100000010010000,Twin USB PS2 Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux,\n03000000100800000300000010010000,USB Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux,\n03000000790000000600000007010000,USB gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b3,y:b0,platform:Linux,\n03000000790000001100000000010000,USB Gamepad1,a:b2,b:b1,back:b8,dpdown:a0,dpleft:a1,dpright:a2,dpup:a4,start:b9,platform:Linux,\n030000006f0e00000302000011010000,Victrix Pro Fight Stick for PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,\n030000006f0e00000702000011010000,Victrix Pro Fight Stick for PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,\n05000000ac0500003232000001000000,VR-BOX,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux,\n03000000791d00000103000010010000,Wii Classic Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,\n050000000d0f0000f600000001000000,Wireless HORIPAD Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,\n030000005e0400008e02000010010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n030000005e0400008e02000014010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n030000005e0400001907000000010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n030000005e0400009102000007010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n030000005e040000a102000000010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n030000005e040000a102000007010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n0000000058626f782033363020576900,Xbox 360 Wireless Controller,a:b0,b:b1,back:b14,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,guide:b7,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Linux,\n030000005e040000a102000014010000,Xbox 360 Wireless Receiver (XBOX),a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n0000000058626f782047616d65706100,Xbox Gamepad (userspace driver),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux,\n030000005e040000d102000002010000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n050000005e040000fd02000030110000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n050000005e040000050b000002090000,Xbox One Elite Series 2,a:b0,b:b1,back:b136,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a6,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,\n030000005e040000ea02000000000000,Xbox One Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n050000005e040000e002000003090000,Xbox One Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n050000005e040000fd02000003090000,Xbox One Wireless Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,\n030000005e040000ea02000001030000,Xbox One Wireless Controller (Model 1708),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n030000005e040000120b000001050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n030000005e040000130b000005050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,\n050000005e040000130b000001050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,\n050000005e040000130b000005050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,\n030000005e0400008e02000000010000,xbox360 Wireless EasySMX,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n03000000450c00002043000010010000,XEOX Gamepad SL-6556-BK,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,\n03000000ac0500005b05000010010000,Xiaoji Gamesir-G3w,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,\n05000000172700004431000029010000,XiaoMi Game Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b20,leftshoulder:b6,leftstick:b13,lefttrigger:a7,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a6,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Linux,\n03000000c0160000e105000001010000,Xin-Mo Xin-Mo Dual Arcade,a:b4,b:b3,back:b6,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b9,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b1,y:b0,platform:Linux,\nxinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n03000000120c0000100e000011010000,ZEROPLUS P4 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,\n03000000120c0000101e000011010000,ZEROPLUS P4 Wired Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,\n03000000c0160000dc27000001010000,OnyxSoft Dual JoyDivision,platform:Linux,a:b0,b:b1,x:b2,y:b3,start:b6,leftshoulder:b4,rightshoulder:b5,dpup:-a1,dpdown:+a1,dpleft:-a0,dpright:+a0,\n\n# Android\n05000000c82d000006500000ffff3f00,8BitDo M30 Gamepad,a:b1,b:b0,back:b4,guide:b17,leftshoulder:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:a4,start:b6,x:b3,y:b2,platform:Android,\n05000000c82d000051060000ffff3f00,8BitDo M30 Gamepad,a:b1,b:b0,back:b4,guide:b17,leftshoulder:b9,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:a5,start:b6,x:b3,y:b2,platform:Android,\n05000000c82d000015900000ffff3f00,8BitDo N30 Pro 2,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,\n05000000c82d000065280000ffff3f00,8BitDo N30 Pro 2,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b17,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,\n050000000220000000900000ffff3f00,8BitDo NES30 Pro,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,\n050000002038000009000000ffff3f00,8BitDo NES30 Pro,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,\n05000000c82d000000600000ffff3f00,8BitDo SF30 Pro,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b15,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b16,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,\n05000000c82d000000610000ffff3f00,8BitDo SF30 Pro,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,\n05000000c82d000012900000ffff3f00,8BitDo SN30 Gamepad,a:b1,b:b0,back:b4,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android,\n05000000c82d000062280000ffff3f00,8BitDo SN30 Gamepad,a:b1,b:b0,back:b4,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android,\n05000000c82d000001600000ffff3f00,8BitDo SN30 Pro,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,\n05000000c82d000002600000ffff0f00,8BitDo SN30 Pro+,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b17,leftshoulder:b9,leftstick:b7,lefttrigger:b15,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b16,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,\n050000002028000009000000ffff3f00,8BitDo SNES30 Gamepad,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,\n050000003512000020ab000000780f00,8BitDo SNES30 Gamepad,a:b21,b:b20,back:b30,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b26,rightshoulder:b27,start:b31,x:b24,y:b23,platform:Android,\n05000000c82d000018900000ffff0f00,8BitDo Zero 2,a:b1,b:b0,back:b4,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android,\n05000000c82d000030320000ffff0f00,8BitDo Zero 2,a:b1,b:b0,back:b4,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android,\n05000000bc20000000550000ffff3f00,GameSir G3w,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,\n05000000d6020000e5890000dfff3f00,GPD XD Plus,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Android,\n0500000031366332860c44aadfff0f00,GS Gamepad,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b15,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b16,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,\n0500000083050000602000000ffe0000,iBuffalo SNES Controller,a:b1,b:b0,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b15,rightshoulder:b16,start:b10,x:b3,y:b2,platform:Android,\n64633436313965656664373634323364,Microsoft X-Box 360 pad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,x:b2,y:b3,platform:Android,\n7573622067616d657061642020202020,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b6,start:b9,x:b3,y:b0,platform:Android,\n050000007e05000009200000ffff0f00,Nintendo Switch Pro Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b16,x:b17,y:b2,platform:Android,\n37336435666338653565313731303834,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,\n4e564944494120436f72706f72617469,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,\n61363931656135336130663561616264,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,\n050000005509000003720000cf7f3f00,NVIDIA Controller v01.01,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,\n050000005509000010720000ffff3f00,NVIDIA Controller v01.03,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,\n050000005509000014720000df7f3f00,NVIDIA Controller v01.04,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Android,\n050000004c05000068020000dfff3f00,PS3 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,\n030000004c050000cc09000000006800,PS4 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,\n050000004c050000c4050000fffe3f00,PS4 Controller,a:b1,b:b17,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:+a4,rightx:a2,righty:a5,start:b16,x:b0,y:b2,platform:Android,\n050000004c050000c4050000ffff3f00,PS4 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,\n050000004c050000cc090000fffe3f00,PS4 Controller,a:b1,b:b17,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:a4,rightx:a2,righty:a5,start:b16,x:b0,y:b2,platform:Android,\n050000004c050000cc090000ffff3f00,PS4 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,\n35643031303033326130316330353564,PS4 Controller,a:b1,b:b17,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:+a4,rightx:a2,righty:a5,start:b16,x:b0,y:b2,platform:Android,\n050000004c050000e60c0000fffe3f00,PS5 Controller,a:b1,b:b17,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:a4,rightx:a2,righty:a5,start:b16,x:b0,y:b2,platform:Android,\n62653861643333663663383332396665,Razer Kishi,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,\n050000003215000005070000ffff3f00,Razer Raiju Mobile,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,\n050000003215000007070000ffff3f00,Razer Raiju Mobile,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,\n050000003215000000090000bf7f3f00,Razer Serval,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,x:b2,y:b3,platform:Android,\n32633532643734376632656664383733,Sony DualSense,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a5,start:b18,x:b0,y:b2,platform:Android,\n61303162353165316365336436343139,Sony DualSense,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a5,start:b18,x:b0,y:b2,platform:Android,\n05000000de2800000511000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Android,\n05000000de2800000611000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Android,\n050000004f0400000ed00000fffe3f00,ThrustMaster eSwap PRO Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,\n5477696e20555342204a6f7973746963,Twin USB Joystick,a:b22,b:b21,back:b28,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b26,leftstick:b30,lefttrigger:b24,leftx:a0,lefty:a1,rightshoulder:b27,rightstick:b31,righttrigger:b25,rightx:a3,righty:a2,start:b29,x:b23,y:b20,platform:Android,\n30306539356238653637313730656134,Wireless HORIPAD Switch Pro Controller,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b19,y:b2,platform:Android,\n050000005e040000fd020000ff7f3f00,Xbox One S Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,\n050000005e040000e00200000ffe3f00,Xbox One Wireless Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b16,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b17,y:b2,platform:Android,\n050000005e040000fd020000ffff3f00,Xbox One Wireless Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,\n050000005e040000130b0000ffff3f00,Xbox Series Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,\n65633038363832353634653836396239,Xbox Series Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,\n050000005e04000091020000ff073f00,Xbox Wireless Controller,a:b0,b:b1,back:b4,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Android,\n34356136633366613530316338376136,Xbox Wireless Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b3,leftstick:b15,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b16,righttrigger:a5,rightx:a3,righty:a4,x:b17,y:b2,platform:Android,\n050000001727000044310000ffff3f00,XiaoMi Game Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a7,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a6,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Android,\n\n# iOS\n05000000ac0500000100000000006d01,*,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a5,rightx:a3,righty:a4,x:b2,y:b3,platform:iOS,\n05000000ac050000010000004f066d01,*,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a5,rightx:a3,righty:a4,x:b2,y:b3,platform:iOS,\n05000000ac05000001000000cf076d01,*,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b2,y:b3,platform:iOS,\n05000000ac05000001000000df076d01,*,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:iOS,\n05000000ac05000001000000ff076d01,*,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,platform:iOS,\n05000000ac0500000200000000006d02,*,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,rightshoulder:b5,x:b2,y:b3,platform:iOS,\n05000000ac050000020000004f066d02,*,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,rightshoulder:b5,x:b2,y:b3,platform:iOS,\n4d466947616d65706164010000000000,MFi Extended Gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:iOS,\n4d466947616d65706164020000000000,MFi Gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,start:b6,x:b2,y:b3,platform:iOS,\n050000004c050000cc090000df070000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:iOS,\n050000004c050000cc090000ff070000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,platform:iOS,\n050000004c050000cc090000ff870001,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,touchpad:b11,x:b2,y:b3,platform:iOS,\n05000000ac0500000300000000006d03,Remote,a:b0,b:b2,leftx:a0,lefty:a1,platform:iOS,\n05000000ac0500000300000043006d03,Remote,a:b0,b:b2,leftx:a0,lefty:a1,platform:iOS,\n05000000de2800000511000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:iOS,\n05000000de2800000611000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:iOS,\n050000005e040000050b0000ff070001,Xbox Elite Wireless Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b13,paddle3:b12,paddle4:b14,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,platform:iOS,\n050000005e040000e0020000df070000,Xbox Wireless Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:iOS,\n050000005e040000e0020000ff070000,Xbox Wireless Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,platform:iOS,\n"
  },
  {
    "path": "premake-vs2015.cmd",
    "content": "premake5 vs2015 --with-librw\n"
  },
  {
    "path": "premake-vs2017.cmd",
    "content": "premake5 vs2017 --with-librw\n"
  },
  {
    "path": "premake-vs2019.cmd",
    "content": "premake5 vs2019 --with-librw\n"
  },
  {
    "path": "premake5.lua",
    "content": "newoption {\r\n\ttrigger     = \"glfwdir64\",\r\n\tvalue       = \"PATH\",\r\n\tdescription = \"Directory of glfw\",\r\n\tdefault     = \"vendor/glfw-3.3.2.bin.WIN64\",\r\n}\r\n\r\nnewoption {\r\n\ttrigger     = \"glfwdir32\",\r\n\tvalue       = \"PATH\",\r\n\tdescription = \"Directory of glfw\",\r\n\tdefault     = \"vendor/glfw-3.3.2.bin.WIN32\",\r\n}\r\n\r\nnewoption {\r\n\ttrigger     = \"with-asan\",\r\n\tdescription = \"Build with address sanitizer\"\r\n}\r\n\r\nnewoption {\r\n\ttrigger     = \"with-librw\",\r\n\tdescription = \"Build and use librw from this solution\"\r\n}\r\n\r\nnewoption {\r\n\ttrigger     = \"with-opus\",\r\n\tdescription = \"Build with opus\"\r\n}\r\n\r\nnewoption {\r\n\ttrigger     = \"lto\",\r\n\tdescription = \"Use link time optimization\"\r\n}\r\n\r\nif(_OPTIONS[\"with-librw\"]) then\r\n\tLibrw = \"vendor/librw\"\r\nelse\r\n\tLibrw = os.getenv(\"LIBRW\") or \"vendor/librw\"\r\nend\r\n\r\nfunction getsys(a)\r\n\tif a == 'windows' then\r\n\t\treturn 'win'\r\n\tend\r\n\treturn a\r\nend\r\n\r\nfunction getarch(a)\r\n\tif a == 'x86_64' then\r\n\t\treturn 'amd64'\r\n\telseif a == 'ARM' then\r\n\t\treturn 'arm'\r\n\telseif a == 'ARM64' then\r\n\t\treturn 'arm64'\r\n\tend\r\n\treturn a\r\nend\r\n\r\nworkspace \"reVC\"\r\n\tlanguage \"C++\"\r\n\tconfigurations { \"Debug\", \"Release\", \"Vanilla\" }\r\n\tstartproject \"reVC\"\r\n\tlocation \"build\"\r\n\tsymbols \"Full\"\r\n\tstaticruntime \"off\"\r\n\r\n\tif _OPTIONS[\"with-asan\"] then\r\n\t\tbuildoptions { \"-fsanitize=address -g3 -fno-omit-frame-pointer\" }\r\n\t\tlinkoptions { \"-fsanitize=address\" }\r\n\tend\r\n\r\n\tfilter { \"system:windows\" }\r\n\t\tplatforms {\r\n\t\t\t\"win-x86-RW34_d3d8-mss\",\r\n\t\t\t\"win-x86-librw_d3d9-mss\",\r\n\t\t\t\"win-x86-librw_gl3_glfw-mss\",\r\n\t\t\t\"win-x86-RW34_d3d8-oal\",\r\n\t\t\t\"win-x86-librw_d3d9-oal\",\r\n\t\t\t\"win-x86-librw_gl3_glfw-oal\",\r\n\t\t\t\"win-amd64-librw_d3d9-oal\",\r\n\t\t\t\"win-amd64-librw_gl3_glfw-oal\",\r\n\t\t}\r\n\r\n\tfilter { \"system:linux\" }\r\n\t\tplatforms {\r\n\t\t\t\"linux-x86-librw_gl3_glfw-oal\",\r\n\t\t\t\"linux-amd64-librw_gl3_glfw-oal\",\r\n\t\t\t\"linux-arm-librw_gl3_glfw-oal\",\r\n\t\t\t\"linux-arm64-librw_gl3_glfw-oal\",\r\n\t\t}\r\n\r\n\tfilter { \"system:bsd\" }\r\n\t\tplatforms {\r\n\t\t\t\"bsd-x86-librw_gl3_glfw-oal\",\r\n\t\t\t\"bsd-amd64-librw_gl3_glfw-oal\",\r\n\t\t\t\"bsd-arm-librw_gl3_glfw-oal\",\r\n\t\t\t\"bsd-arm64-librw_gl3_glfw-oal\"\r\n\t\t}\r\n\t\t\r\n\tfilter { \"system:macosx\" }\r\n\t\tplatforms {\r\n\t\t\t\"macosx-arm64-librw_gl3_glfw-oal\",\r\n\t\t\t\"macosx-amd64-librw_gl3_glfw-oal\",\r\n\t\t}\r\n\r\n\tfilter \"configurations:Debug\"\r\n\t\tdefines { \"DEBUG\" }\r\n\t\t\r\n\tfilter \"configurations:not Debug\"\r\n\t\tdefines { \"NDEBUG\" }\r\n\t\toptimize \"Speed\"\r\n\t\tif(_OPTIONS[\"lto\"]) then\r\n\t\t\tflags { \"LinkTimeOptimization\" }\r\n\t\tend\r\n\r\n\tfilter \"configurations:Vanilla\"\r\n\t\tdefines { \"VANILLA_DEFINES\" }\r\n\r\n\tfilter { \"platforms:win*\" }\r\n\t\tsystem \"windows\"\r\n\r\n\tfilter { \"platforms:linux*\" }\r\n\t\tsystem \"linux\"\r\n\t\t\r\n\tfilter { \"platforms:bsd*\" }\r\n\t\tsystem \"bsd\"\r\n\r\n\tfilter { \"platforms:macosx*\" }\r\n\t\tsystem \"macosx\"\r\n\t\r\n\tfilter { \"platforms:*x86*\" }\r\n\t\tarchitecture \"x86\"\r\n\t\t\r\n\tfilter { \"platforms:*amd64*\" }\r\n\t\tarchitecture \"amd64\"\r\n\r\n\tfilter { \"platforms:*arm*\" }\r\n\t\tarchitecture \"ARM\"\r\n\t\t\r\n\tfilter { \"platforms:macosx-arm64-*\" }\r\n\t\tbuildoptions { \"-target\", \"arm64-apple-macos11\", \"-std=gnu++14\" }\r\n\r\n\tfilter { \"platforms:macosx-amd64-*\" }\r\n\t\tbuildoptions { \"-target\", \"x86_64-apple-macos10.12\", \"-std=gnu++14\" }\r\n\r\n\tfilter { \"platforms:*librw_d3d9*\" }\r\n\t\tdefines { \"RW_D3D9\" }\r\n\t\tif(not _OPTIONS[\"with-librw\"]) then\r\n\t\t\tlibdirs { path.join(Librw, \"lib/win-%{getarch(cfg.architecture)}-d3d9/%{cfg.buildcfg}\") }\r\n\t\tend\r\n\t\t\r\n\tfilter \"platforms:*librw_gl3_glfw*\"\r\n\t\tdefines { \"RW_GL3\" }\r\n\t\tif(not _OPTIONS[\"with-librw\"]) then\r\n\t\t\tlibdirs { path.join(Librw, \"lib/%{getsys(cfg.system)}-%{getarch(cfg.architecture)}-gl3/%{cfg.buildcfg}\") }\r\n\t\tend\r\n\t\t\r\n\tfilter \"platforms:*x86-librw_gl3_glfw*\"\r\n\t\tincludedirs { path.join(_OPTIONS[\"glfwdir32\"], \"include\") }\r\n\t\t\r\n\tfilter \"platforms:*amd64-librw_gl3_glfw*\"\r\n\t\tincludedirs { path.join(_OPTIONS[\"glfwdir64\"], \"include\") }\r\n\r\n\tfilter  {}\r\n\t\t\r\n    function setpaths (gamepath, exepath)\r\n       if (gamepath) then\r\n          postbuildcommands {\r\n             '{COPYFILE} \"%{cfg.buildtarget.abspath}\" \"' .. gamepath .. '%{cfg.buildtarget.name}\"'\r\n          }\r\n          debugdir (gamepath)\r\n          if (exepath) then\r\n\t\t\t -- Used VS variable $(TargetFileName) because it doesn't accept premake tokens. Does debugcommand even work outside VS??\r\n             debugcommand (gamepath .. \"$(TargetFileName)\")\r\n             dir, file = exepath:match'(.*/)(.*)'\r\n             debugdir (gamepath .. (dir or \"\"))\r\n          end\r\n       end\r\n    end\r\n\r\nif(_OPTIONS[\"with-librw\"]) then\r\nproject \"librw\"\r\n\tkind \"StaticLib\"\r\n\ttargetname \"rw\"\r\n\ttargetdir(path.join(Librw, \"lib/%{cfg.platform}/%{cfg.buildcfg}\"))\r\n\tfiles { path.join(Librw, \"src/*.*\") }\r\n\tfiles { path.join(Librw, \"src/*/*.*\") }\r\n\tfiles { path.join(Librw, \"src/gl/*/*.*\") }\r\n\t\r\n\tfilter { \"platforms:*x86*\" }\r\n\t\tarchitecture \"x86\"\r\n\r\n\tfilter { \"platforms:*amd64*\" }\r\n\t\tarchitecture \"amd64\"\r\n\r\n\tfilter \"platforms:win*\"\r\n\t\tdefines { \"_CRT_SECURE_NO_WARNINGS\", \"_CRT_NONSTDC_NO_DEPRECATE\" }\r\n\t\tstaticruntime \"on\"\r\n\t\tbuildoptions { \"/Zc:sizedDealloc-\" }\r\n\r\n\tfilter \"platforms:bsd*\"\r\n\t\tincludedirs { \"/usr/local/include\" }\r\n\t\tlibdirs { \"/usr/local/lib\" }\r\n\r\n\tfilter \"platforms:macosx*\"\r\n\t\t-- Support MacPorts and Homebrew\r\n\t\tincludedirs { \"/opt/local/include\" }\r\n\t\tincludedirs {\"/usr/local/include\" }\r\n\t\tlibdirs { \"/opt/local/lib\" }\r\n\t\tlibdirs { \"/usr/local/lib\" }\r\n\r\n\tfilter \"platforms:*gl3_glfw*\"\r\n\t\tstaticruntime \"off\"\r\n\t\r\n\tfilter \"platforms:*RW34*\"\r\n\t\tflags { \"ExcludeFromBuild\" }\r\n\tfilter  {}\r\nend\r\n\r\nlocal function addSrcFiles( prefix )\r\n\treturn prefix .. \"/*cpp\", prefix .. \"/*.h\", prefix .. \"/*.c\", prefix .. \"/*.ico\", prefix .. \"/*.rc\"\r\nend\r\n\r\nproject \"reVC\"\r\n\tkind \"WindowedApp\"\r\n\ttargetname \"reVC\"\r\n\ttargetdir \"bin/%{cfg.platform}/%{cfg.buildcfg}\"\r\n\r\n\tif(_OPTIONS[\"with-librw\"]) then\r\n\t\tdependson \"librw\"\r\n\tend\r\n\r\n\tfiles { addSrcFiles(\"src\") }\r\n\tfiles { addSrcFiles(\"src/animation\") }\r\n\tfiles { addSrcFiles(\"src/audio\") }\r\n\tfiles { addSrcFiles(\"src/audio/eax\") }\r\n\tfiles { addSrcFiles(\"src/audio/oal\") }\r\n\tfiles { addSrcFiles(\"src/buildings\") }\r\n\tfiles { addSrcFiles(\"src/collision\") }\r\n\tfiles { addSrcFiles(\"src/control\") }\r\n\tfiles { addSrcFiles(\"src/core\") }\r\n\tfiles { addSrcFiles(\"src/entities\") }\r\n\tfiles { addSrcFiles(\"src/math\") }\r\n\tfiles { addSrcFiles(\"src/modelinfo\") }\r\n\tfiles { addSrcFiles(\"src/objects\") }\r\n\tfiles { addSrcFiles(\"src/peds\") }\r\n\tfiles { addSrcFiles(\"src/render\") }\r\n\tfiles { addSrcFiles(\"src/rw\") }\r\n\tfiles { addSrcFiles(\"src/save\") }\r\n\tfiles { addSrcFiles(\"src/skel\") }\r\n\tfiles { addSrcFiles(\"src/skel/glfw\") }\r\n\tfiles { addSrcFiles(\"src/text\") }\r\n\tfiles { addSrcFiles(\"src/vehicles\") }\r\n\tfiles { addSrcFiles(\"src/weapons\") }\r\n\tfiles { addSrcFiles(\"src/extras\") }\r\n\tfiles { \"src/extras/GitSHA1.cpp\" } -- this won't be in repo in first build\r\n\r\n\tincludedirs { \"src\" }\r\n\tincludedirs { \"src/animation\" }\r\n\tincludedirs { \"src/audio\" }\r\n\tincludedirs { \"src/audio/eax\" }\r\n\tincludedirs { \"src/audio/oal\" }\r\n\tincludedirs { \"src/buildings\" }\r\n\tincludedirs { \"src/collision\" }\r\n\tincludedirs { \"src/control\" }\r\n\tincludedirs { \"src/core\" }\r\n\tincludedirs { \"src/entities\" }\r\n\tincludedirs { \"src/math\" }\r\n\tincludedirs { \"src/modelinfo\" }\r\n\tincludedirs { \"src/objects\" }\r\n\tincludedirs { \"src/peds\" }\r\n\tincludedirs { \"src/render\" }\r\n\tincludedirs { \"src/rw\" }\r\n\tincludedirs { \"src/save/\" }\r\n\tincludedirs { \"src/skel/\" }\r\n\tincludedirs { \"src/skel/glfw\" }\r\n\tincludedirs { \"src/text\" }\r\n\tincludedirs { \"src/vehicles\" }\r\n\tincludedirs { \"src/weapons\" }\r\n\tincludedirs { \"src/extras\" }\r\n\t\r\n\tif _OPTIONS[\"with-opus\"] then\r\n\t\tincludedirs { \"vendor/ogg/include\" }\r\n\t\tincludedirs { \"vendor/opus/include\" }\r\n\t\tincludedirs { \"vendor/opusfile/include\" }\r\n\tend\r\n\r\n\tfilter \"platforms:*mss\"\r\n\t\tdefines { \"AUDIO_MSS\" }\r\n\t\tincludedirs { \"vendor/milessdk/include\" }\r\n\t\tlibdirs { \"vendor/milessdk/lib\" }\r\n\t\r\n\tif _OPTIONS[\"with-opus\"] then\r\n\t\tfilter \"platforms:win*\"\r\n\t\t\tlibdirs { \"vendor/ogg/win32/VS2015/Win32/%{cfg.buildcfg}\" }\r\n\t\t\tlibdirs { \"vendor/opus/win32/VS2015/Win32/%{cfg.buildcfg}\" }\r\n\t\t\tlibdirs { \"vendor/opusfile/win32/VS2015/Win32/Release-NoHTTP\" }\r\n\t\tfilter {}\r\n\t\tdefines { \"AUDIO_OPUS\" }\r\n\tend\r\n\t\t\r\n\tfilter \"platforms:*oal\"\r\n\t\tdefines { \"AUDIO_OAL\" }\r\n\r\n\tfilter {}\r\n\tif(os.getenv(\"GTA_VC_RE_DIR\")) then\r\n\t\tsetpaths(os.getenv(\"GTA_VC_RE_DIR\") .. \"/\", \"%(cfg.buildtarget.name)\")\r\n\tend\r\n\t\r\n\tfilter \"platforms:win*\"\r\n\t\tfiles { addSrcFiles(\"src/skel/win\") }\r\n\t\tincludedirs { \"src/skel/win\" }\r\n\t\tbuildoptions { \"/Zc:sizedDealloc-\" }\r\n\t\tlinkoptions \"/SAFESEH:NO\"\r\n\t\tcharacterset (\"MBCS\")\r\n\t\ttargetextension \".exe\"\r\n\t\tif(_OPTIONS[\"with-librw\"]) then\r\n\t\t\t-- external librw is dynamic\r\n\t\t\tstaticruntime \"on\"\r\n\t\tend\r\n\t\tprebuildcommands { '\"%{prj.location}..\\\\printHash.bat\" \"%{prj.location}..\\\\src\\\\extras\\\\GitSHA1.cpp\"' }\r\n\r\n\tfilter \"platforms:not win*\"\r\n\t\tprebuildcommands { '\"%{prj.location}/../printHash.sh\" \"%{prj.location}/../src/extras/GitSHA1.cpp\"' }\r\n\r\n\tfilter \"platforms:win*glfw*\"\r\n\t\tstaticruntime \"off\"\r\n\t\t\r\n\tfilter \"platforms:win*oal\"\r\n\t\tincludedirs { \"vendor/openal-soft/include\" }\r\n\t\tincludedirs { \"vendor/libsndfile/include\" }\r\n\t\tincludedirs { \"vendor/mpg123/include\" }\r\n\t\t\r\n\tfilter \"platforms:win-x86*oal\"\r\n\t\tlibdirs { \"vendor/mpg123/lib/Win32\" }\r\n\t\tlibdirs { \"vendor/libsndfile/lib/Win32\" }\r\n\t\tlibdirs { \"vendor/openal-soft/libs/Win32\" }\r\n\t\t\r\n\tfilter \"platforms:win-amd64*oal\"\r\n\t\tlibdirs { \"vendor/mpg123/lib/Win64\" }\r\n\t\tlibdirs { \"vendor/libsndfile/lib/Win64\" }\r\n\t\tlibdirs { \"vendor/openal-soft/libs/Win64\" }\r\n\r\n\tfilter \"platforms:linux*oal\"\r\n\t\tlinks { \"openal\", \"mpg123\", \"sndfile\", \"pthread\", \"X11\" }\r\n\t\t\r\n\tfilter \"platforms:bsd*oal\"\r\n\t\tlinks { \"openal\", \"mpg123\", \"sndfile\", \"pthread\", \"X11\" }\r\n\r\n\tfilter \"platforms:macosx*oal\"\r\n\t\tlinks { \"openal\", \"mpg123\", \"sndfile\", \"pthread\" }\r\n\t\tincludedirs { \"/usr/local/opt/openal-soft/include\" }\r\n\t\tlibdirs { \"/usr/local/opt/openal-soft/lib\" }\r\n\t\r\n\tif _OPTIONS[\"with-opus\"] then\r\n\t\tfilter {}\r\n\t\tlinks { \"libogg\" }\r\n\t\tlinks { \"opus\" }\r\n\t\tlinks { \"opusfile\" }\r\n\tend\r\n\r\n\tfilter \"platforms:*RW34*\"\r\n\t\tincludedirs { \"sdk/rwsdk/include/d3d8\" }\r\n\t\tlibdirs { \"sdk/rwsdk/lib/d3d8/release\" }\r\n\t\tlinks { \"rwcore\", \"rpworld\", \"rpmatfx\", \"rpskin\", \"rphanim\", \"rtbmp\", \"rtquat\", \"rtanim\", \"rtcharse\", \"rpanisot\" }\r\n\t\tdefines { \"RWLIBS\" }\r\n\t\tlinkoptions \"/SECTION:_rwcseg,ER!W /MERGE:_rwcseg=.text\"\r\n\t\r\n\tfilter \"platforms:*librw*\"\r\n\t\tdefines { \"LIBRW\" }\r\n\t\tfiles { addSrcFiles(\"src/fakerw\") }\r\n\t\tincludedirs { \"src/fakerw\" }\r\n\t\tincludedirs { Librw }\r\n\t\tif(_OPTIONS[\"with-librw\"]) then\r\n\t\t\tlibdirs { \"vendor/librw/lib/%{cfg.platform}/%{cfg.buildcfg}\" }\r\n\t\tend\r\n\t\tlinks { \"rw\" }\r\n\r\n\tfilter \"platforms:*d3d9*\"\r\n\t\tdefines { \"USE_D3D9\" }\r\n\t\tlinks { \"d3d9\" }\r\n\t\t\r\n\tfilter \"platforms:*x86*d3d*\"\r\n\t\tincludedirs { \"sdk/dx8sdk/include\" }\r\n\t\tlibdirs { \"sdk/dx8sdk/lib\" }\r\n\t\t\r\n\tfilter \"platforms:win-x86*gl3_glfw*\"\r\n\t\tlibdirs { path.join(_OPTIONS[\"glfwdir32\"], \"lib-\" .. string.gsub(_ACTION or '', \"vs\", \"vc\")) }\r\n\t\tlinks { \"opengl32\", \"glfw3\" }\r\n\t\t\r\n\tfilter \"platforms:win-amd64*gl3_glfw*\"\r\n\t\tlibdirs { path.join(_OPTIONS[\"glfwdir64\"], \"lib-\" .. string.gsub(_ACTION or '', \"vs\", \"vc\")) }\r\n\t\tlinks { \"opengl32\", \"glfw3\" }\r\n\r\n\tfilter \"platforms:linux*gl3_glfw*\"\r\n\t\tlinks { \"GL\", \"glfw\" }\r\n\t\t\r\n\tfilter \"platforms:bsd*gl3_glfw*\"\r\n\t\tlinks { \"GL\", \"glfw\", \"sysinfo\" }\r\n\t\tincludedirs { \"/usr/local/include\" }\r\n\t\tlibdirs { \"/usr/local/lib\" }\r\n\r\n\tfilter \"platforms:macosx*gl3_glfw*\"\r\n\t\tlinks { \"glfw\" }\r\n\t\tlinkoptions { \"-framework OpenGL\" }\r\n\t\tincludedirs { \"/opt/local/include\" }\r\n\t\tincludedirs { \"/usr/local/include\" }\r\n\t\tlibdirs { \"/opt/local/lib\" }\r\n\t\tlibdirs { \"/usr/local/lib\" }\r\n"
  },
  {
    "path": "printHash.bat",
    "content": "@echo off\n\nREM creates version.h with HEAD commit hash\nREM params: $1=full path to output file (usually points version.h)\n\nsetlocal enableextensions enabledelayedexpansion\n\ncd /d \"%~dp0\"\n\nbreak> %1\n\n<nul set /p=^\"#define GIT_SHA1 ^\"^\"> %1\n\nwhere git\nif \"%errorlevel%\" == \"0\" ( goto :havegit ) else ( goto :writeending )\n\n:havegit\nfor /f %%v in ('git rev-parse --short HEAD') do set version=%%v\n<nul set /p=\"%version%\" >> %1\n\n:writeending\n\necho ^\" >> %1\necho const char* g_GIT_SHA1 = GIT_SHA1; >> %1\n\nEXIT /B"
  },
  {
    "path": "printHash.sh",
    "content": "#!/usr/bin/env bash\n\n> $1\n\necho -n \"#define GIT_SHA1 \\\"\" > $1\n\nif (command -v \"git\" >/dev/null) then\ngit rev-parse --short HEAD | tr -d '\\n' >> $1\nfi\n\necho \"\\\"\" >> $1\necho \"const char* g_GIT_SHA1 = GIT_SHA1;\" >> $1"
  },
  {
    "path": "src/CMakeLists.txt",
    "content": "find_package(Threads REQUIRED)\nset(THREADS_PREFER_PTHREAD_FLAG ON)\n\nfile(GLOB_RECURSE ${PROJECT}_SOURCES \"*.cpp\" \"*.h\" \"*.rc\")\n\nfunction(header_directories RETURN_LIST)\n    file(GLOB_RECURSE ALL_SRCS *.h *.cpp *.c)\n    set(RELDIRS)\n    foreach(SRC ${ALL_SRCS})\n        file(RELATIVE_PATH RELSRC \"${CMAKE_CURRENT_SOURCE_DIR}\" \"${SRC}\")\n        get_filename_component(RELDIR \"${RELSRC}\" DIRECTORY)\n        list(APPEND RELDIRS ${RELDIR})\n    endforeach()\n    list(REMOVE_DUPLICATES RELDIRS)\n    set(${RETURN_LIST} ${RELDIRS} PARENT_SCOPE)\nendfunction()\n\nheader_directories(${PROJECT}_INCLUDES)\n\nconfigure_file(\"${CMAKE_CURRENT_SOURCE_DIR}/extras/GitSHA1.cpp.in\" \"${CMAKE_CURRENT_BINARY_DIR}/extras/GitSHA1.cpp\" @ONLY)\nlist(APPEND ${PROJECT}_SOURCES \"${CMAKE_CURRENT_BINARY_DIR}/extras/GitSHA1.cpp\")\n\nadd_executable(${EXECUTABLE} WIN32\n    ${${PROJECT}_SOURCES}\n)\n\ntarget_link_libraries(${EXECUTABLE} PRIVATE\n    librw::librw\n    Threads::Threads\n)\n\ntarget_include_directories(${EXECUTABLE}\n    PRIVATE\n        $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}>\n        $<BUILD_INTERFACE:${${PROJECT}_INCLUDES}>\n)\n\ntarget_compile_definitions(${EXECUTABLE}\n    PRIVATE\n        $<IF:$<CONFIG:DEBUG>,DEBUG,NDEBUG>\n        LIBRW\n        CMAKE_NO_AUTOLINK\n)\n\nif(LIBRW_PLATFORM_D3D9)\n    target_compile_definitions(${EXECUTABLE}\n        PUBLIC\n            USE_D3D9\n    )\nendif()\n\ntarget_compile_definitions(${EXECUTABLE} PRIVATE CMAKE_BUILD)\n\nif(${PROJECT}_AUDIO STREQUAL \"OAL\")\n    find_package(OpenAL REQUIRED)\n    target_include_directories(${EXECUTABLE} PRIVATE ${OPENAL_INCLUDE_DIR})\n    target_link_libraries(${EXECUTABLE} PRIVATE ${OPENAL_LIBRARY})\n    target_compile_definitions(${EXECUTABLE} PRIVATE ${OPENAL_DEFINITIONS})\n    target_compile_definitions(${EXECUTABLE} PRIVATE AUDIO_OAL)\nelseif(${PROJECT}_AUDIO STREQUAL \"MSS\")\n    find_package(MilesSDK REQUIRED)\n    target_compile_definitions(${EXECUTABLE} PRIVATE AUDIO_MSS)\n    target_link_libraries(${EXECUTABLE} PRIVATE MilesSDK::MilesSDK)\nendif()\n\nfind_package(mpg123 REQUIRED)\ntarget_link_libraries(${EXECUTABLE} PRIVATE\n    MPG123::libmpg123\n)\nif(${PROJECT}_WITH_OPUS)\n    find_package(opusfile REQUIRED)\n    target_link_libraries(${EXECUTABLE} PRIVATE\n        opusfile::opusfile\n    )\n    target_compile_definitions(${EXECUTABLE} PRIVATE AUDIO_OPUS)\nendif()\nif(${PROJECT}_WITH_LIBSNDFILE)\n    find_package(SndFile REQUIRED)\n    target_link_libraries(${EXECUTABLE} PRIVATE\n        SndFile::SndFile\n    )\n    target_compile_definitions(${EXECUTABLE} PRIVATE AUDIO_OAL_USE_SNDFILE)\nendif()\n\ntarget_compile_definitions(${EXECUTABLE} PRIVATE )\n\noption(${PROJECT}_WITH_SANITIZERS \"Use UB sanitizers (better crash log)\" OFF)\noption(${PROJECT}_WITH_ASAN \"Use Address sanitizer (better crash log)\" OFF)\n\nif(${PROJECT}_WITH_SANITIZERS)\n    target_compile_options(${EXECUTABLE} PUBLIC\n            -fsanitize=undefined,float-divide-by-zero,integer,implicit-conversion,implicit-integer-truncation,implicit-integer-arithmetic-value-change,local-bounds,nullability\n            -g3 -fno-omit-frame-pointer)\n    target_link_options(${EXECUTABLE} PUBLIC -fsanitize=undefined,float-divide-by-zero,integer,implicit-conversion,implicit-integer-truncation,implicit-integer-arithmetic-value-change,local-bounds,nullability)\nendif()\n\nif(${PROJECT}_WITH_ASAN)\n    target_compile_options(${EXECUTABLE} PUBLIC -fsanitize=address -g3 -fno-omit-frame-pointer)\n    target_link_options(${EXECUTABLE} PUBLIC -fsanitize=address)\nendif()\n\nif(CMAKE_CXX_COMPILER_ID STREQUAL \"GNU\" OR CMAKE_CXX_COMPILER_ID STREQUAL \"Clang\" OR CMAKE_CXX_COMPILER_ID STREQUAL \"AppleClang\")\n    target_compile_options(${EXECUTABLE}\n        PRIVATE\n            \"-Wall\"\n    )\n    if (NOT LIBRW_PLATFORM_PS2)\n        target_compile_options(${EXECUTABLE}\n            PRIVATE\n                -Wextra\n                -Wdouble-promotion\n                -Wpedantic\n        )\n    endif()\nelseif(CMAKE_CXX_COMPILER_ID STREQUAL \"MSVC\")\n    target_compile_options(${EXECUTABLE}\n        PUBLIC\n            /Zc:sizedDealloc-\n    )\nendif()\n\nset_target_properties(${EXECUTABLE}\n    PROPERTIES\n        C_STANDARD 11\n        C_EXTENSIONS OFF\n        C_STANDARD_REQUIRED ON\n        CXX_STANDARD 11\n        CXX_EXTENSIONS OFF\n        CXX_STANDARD_REQUIRED ON\n)\n\nif(${PROJECT}_INSTALL)\n    install(\n        TARGETS ${EXECUTABLE}\n        EXPORT ${EXECUTABLE}-targets\n        RUNTIME DESTINATION \".\"\n    )\n    if(MSVC)\n        install(FILES $<TARGET_PDB_FILE:${EXECUTABLE}> DESTINATION \".\" OPTIONAL)\n    endif()\nendif()\n"
  },
  {
    "path": "src/animation/AnimBlendAssocGroup.cpp",
    "content": "#include \"common.h\"\n\n#if defined _WIN32 && !defined __MINGW32__\n#if defined __MWERKS__\n#include <wctype.h>\n#else\n#include \"ctype.h\"\n#endif\n#else\n#include <cwctype>\n#endif\n\n#include \"General.h\"\n#include \"RwHelper.h\"\n#include \"ModelIndices.h\"\n#include \"ModelInfo.h\"\n#include \"AnimManager.h\"\n#include \"RpAnimBlend.h\"\n#include \"AnimBlendAssociation.h\"\n#include \"AnimBlendAssocGroup.h\"\n\nCAnimBlendAssocGroup::CAnimBlendAssocGroup(void)\n{\n\tanimBlock = nil;\n\tassocList = nil;\n\tnumAssociations = 0;\n\tfirstAnimId = 0;\n\tgroupId = -1;\n}\n\nCAnimBlendAssocGroup::~CAnimBlendAssocGroup(void)\n{\n\tDestroyAssociations();\n}\n\nvoid\nCAnimBlendAssocGroup::DestroyAssociations(void)\n{\n\tif(assocList){\n\t\tdelete[] assocList;\n\t\tassocList = nil;\n\t\tnumAssociations = 0;\n\t}\n}\n\nCAnimBlendAssociation*\nCAnimBlendAssocGroup::GetAnimation(uint32 id)\n{\n\treturn &assocList[id - firstAnimId];\n}\n\nCAnimBlendAssociation*\nCAnimBlendAssocGroup::GetAnimation(const char *name)\n{\n\tint i;\n\tfor(i = 0; i < numAssociations; i++)\n\t\tif(!CGeneral::faststricmp(assocList[i].hierarchy->name, name))\n\t\t\treturn &assocList[i];\n\tdebug(\"\\n\\nCan't find the fucking animation %s\\n\\n\\n\", name);\n\treturn nil;\n}\n\n\nCAnimBlendAssociation*\nCAnimBlendAssocGroup::CopyAnimation(uint32 id)\n{\n\tCAnimBlendAssociation *anim = GetAnimation(id);\n\tif(anim == nil)\n\t\treturn nil;\n\tCAnimManager::UncompressAnimation(anim->hierarchy);\n\treturn new CAnimBlendAssociation(*anim);\n}\n\nCAnimBlendAssociation*\nCAnimBlendAssocGroup::CopyAnimation(const char *name)\n{\n\tCAnimBlendAssociation *anim = GetAnimation(name);\n\tif(anim == nil)\n\t\treturn nil;\n\tCAnimManager::UncompressAnimation(anim->hierarchy);\n\treturn new CAnimBlendAssociation(*anim);\n}\n\nbool\nstrcmpIgnoringDigits(const char *s1, const char *s2)\n{\n\tchar c1, c2;\n\n\tfor(;;){\n\t\tc1 = *s1;\n\t\tc2 = *s2;\n\t\tif(c1) s1++;\n\t\tif(c2) s2++;\n\t\tif(c1 == '\\0' && c2 == '\\0') return true;\n#ifndef ASCII_STRCMP\n\t\tif(iswdigit(c1) && iswdigit(c2))\n#else\n\t\tif(__ascii_iswdigit(c1) && __ascii_iswdigit(c2))\n#endif\n\t\t\tcontinue;\n#ifndef ASCII_STRCMP\n\t\tc1 = toupper(c1);\n\t\tc2 = toupper(c2);\n#else\n\t\tc1 = __ascii_toupper(c1);\n\t\tc2 = __ascii_toupper(c2);\n#endif\n\n\t\tif(c1 && c2 && c1 != c2)\n\t\t\treturn false;\n\t}\n}\n\nCBaseModelInfo*\nGetModelFromName(const char *name)\n{\n\tint i;\n\tCBaseModelInfo *mi;\n\tchar playername[32];\n\n\tif(strncasecmp(name, \"CSplay\", 6) == 0 &&\n\t   strncasecmp(CModelInfo::GetModelInfo(MI_PLAYER)->GetModelName(), \"ig\", 2) == 0){\n\t\tstrcpy(playername, CModelInfo::GetModelInfo(MI_PLAYER)->GetModelName());\n\t\tplayername[0] = 'C';\n\t\tplayername[1] = 'S';\n\t\tname = playername;\n\t}\n\n\tfor(i = 0; i < MODELINFOSIZE; i++){\n\t\tmi = CModelInfo::GetModelInfo(i);\n\t\tif(mi && mi->GetRwObject() && RwObjectGetType(mi->GetRwObject()) == rpCLUMP &&\n\t\t   strcmpIgnoringDigits(mi->GetModelName(), name))\n\t\t\treturn mi;\n\t}\n\treturn nil;\n}\n\nvoid\nCAnimBlendAssocGroup::CreateAssociations(const char *name)\n{\n\tint i;\n\tCAnimBlock *animBlock;\n\n\tDestroyAssociations();\n\n\tanimBlock = CAnimManager::GetAnimationBlock(name);\n\tassocList = new CAnimBlendAssociation[animBlock->numAnims];\n\tnumAssociations = 0;\n\n\tfor(i = 0; i < animBlock->numAnims; i++){\n\t\tCAnimBlendHierarchy *anim = CAnimManager::GetAnimation(animBlock->firstIndex + i);\n\t\tCBaseModelInfo *model = GetModelFromName(anim->name);\n\t\tif(model){\n\t\t\tdebug(\"Associated anim %s with model %s\\n\", anim->name, model->GetModelName());\n\t\t\tRpClump *clump = (RpClump*)model->CreateInstance();\n\t\t\tRpAnimBlendClumpInit(clump);\n\t\t\tassocList[i].Init(clump, anim);\n\t\t\tif(IsClumpSkinned(clump))\n\t\t\t\tRpClumpForAllAtomics(clump, AtomicRemoveAnimFromSkinCB, nil);\n\t\t\tRpClumpDestroy(clump);\n\t\t\tassocList[i].animId = firstAnimId + i;\n\t\t\tassocList[i].groupId = groupId;\n\t\t}else\n\t\t\tdebug(\"\\n\\nCANNOT FIND MODELINFO WITH NAME %s\\n\\n\\n\", anim->name);\n\t}\n\tnumAssociations = animBlock->numAnims;\n}\n\n// Create associations from hierarchies for a given clump\nvoid\nCAnimBlendAssocGroup::CreateAssociations(const char *blockName, RpClump *clump, const char **animNames, int numAssocs)\n{\n\tint i;\n\n\tDestroyAssociations();\n\n\tanimBlock = CAnimManager::GetAnimationBlock(blockName);\n\tassocList = new CAnimBlendAssociation[numAssocs];\n\n\tnumAssociations = 0;\n\tfor(i = 0; i < numAssocs; i++){\n\t\tassocList[i].Init(clump, CAnimManager::GetAnimation(animNames[i], animBlock));\n\t\tassocList[i].animId = firstAnimId + i;\n\t\tassocList[i].groupId = groupId;\n\t}\n\tnumAssociations = numAssocs;\n}\n"
  },
  {
    "path": "src/animation/AnimBlendAssocGroup.h",
    "content": "#pragma once\n\nclass CAnimBlendAssociation;\nstruct CAnimBlock;\n\nclass CAnimBlendAssocGroup\n{\npublic:\n\tCAnimBlock *animBlock;\n\tCAnimBlendAssociation *assocList;\n\tint32 numAssociations;\n\tint32 firstAnimId;\n\tint32 groupId;\t// id of self in ms_aAnimAssocGroups\n\n\tCAnimBlendAssocGroup(void);\n\t~CAnimBlendAssocGroup(void);\n\tvoid DestroyAssociations(void);\n\tCAnimBlendAssociation *GetAnimation(uint32 id);\n\tCAnimBlendAssociation *GetAnimation(const char *name);\n\tCAnimBlendAssociation *CopyAnimation(uint32 id);\n\tCAnimBlendAssociation *CopyAnimation(const char *name);\n\tvoid CreateAssociations(const char *name);\n\tvoid CreateAssociations(const char *blockName, RpClump *clump, const char **animNames, int numAssocs);\n};\n"
  },
  {
    "path": "src/animation/AnimBlendAssociation.cpp",
    "content": "#include \"common.h\"\n\n#include \"AnimBlendHierarchy.h\"\n#include \"AnimBlendClumpData.h\"\n#include \"RpAnimBlend.h\"\n#include \"AnimManager.h\"\n#include \"AnimBlendAssociation.h\"\n#include \"MemoryMgr.h\"\n\nCAnimBlendAssociation::CAnimBlendAssociation(void)\n{\n\tgroupId = -1;\n\tnodes = nil;\n\tblendAmount = 1.0f;\n\tblendDelta = 0.0f;\n\tcurrentTime = 0.0f;\n\tspeed = 1.0f;\n\ttimeStep = 0.0f;\n\tanimId = -1;\n\tflags = 0;\n\tcallbackType = CB_NONE;\n\tlink.Init();\n}\n\nCAnimBlendAssociation::CAnimBlendAssociation(CAnimBlendAssociation &other)\n{\n\tnodes = nil;\n\tblendAmount = 1.0f;\n\tblendDelta = 0.0f;\n\tcurrentTime = 0.0f;\n\tspeed = 1.0f;\n\ttimeStep = 0.0f;\n\tcallbackType = CB_NONE;\n\tlink.Init();\n\tInit(other);\n}\n\nCAnimBlendAssociation::~CAnimBlendAssociation(void)\n{\n\tFreeAnimBlendNodeArray();\n\tlink.Remove();\n}\n\n\nvoid\nCAnimBlendAssociation::AllocateAnimBlendNodeArray(int n)\n{\n\tint i;\n\n\tnodes = (CAnimBlendNode*)RwMallocAlign(n*sizeof(CAnimBlendNode), 64);\n\tfor(i = 0; i < n; i++)\n\t\tnodes[i].Init();\n}\n\nvoid\nCAnimBlendAssociation::FreeAnimBlendNodeArray(void)\n{\n\tif(nodes)\n\t\tRwFreeAlign(nodes);\n}\n\nvoid\nCAnimBlendAssociation::Init(RpClump *clump, CAnimBlendHierarchy *hier)\n{\n\tint i;\n\tAnimBlendFrameData *frame;\n\n\tCAnimBlendClumpData *clumpData = *RPANIMBLENDCLUMPDATA(clump);\n\tnumNodes = clumpData->numFrames;\n\tAllocateAnimBlendNodeArray(numNodes);\n\tfor(i = 0; i < numNodes; i++)\n\t\tnodes[i].association = this;\n\thierarchy = hier;\n\n\t// Init every node from a sequence and a Clump frame\n\t// NB: This is where the order of nodes is defined\n\tfor(i = 0; i < hier->numSequences; i++){\n\t\tCAnimBlendSequence *seq = &hier->sequences[i];\n\t\tif(seq->boneTag == -1)\n\t\t\tframe = RpAnimBlendClumpFindFrame(clump, seq->name);\n\t\telse\n\t\t\tframe = RpAnimBlendClumpFindBone(clump, seq->boneTag);\n\t\tif(frame && seq->numFrames > 0)\n\t\t\tnodes[frame - clumpData->frames].sequence = seq;\n\t}\n}\n\nvoid\nCAnimBlendAssociation::Init(CAnimBlendAssociation &assoc)\n{\n\tint i;\n\n\thierarchy = assoc.hierarchy;\n\tnumNodes = assoc.numNodes;\n\tflags = assoc.flags;\n\tanimId = assoc.animId;\n\tgroupId = assoc.groupId;\n\tAllocateAnimBlendNodeArray(numNodes);\n\tfor(i = 0; i < numNodes; i++){\n\t\tnodes[i] = assoc.nodes[i];\n\t\tnodes[i].association = this;\n\t}\n}\n\nvoid\nCAnimBlendAssociation::SetBlend(float amount, float delta)\n{\n\tblendAmount = amount;\n\tblendDelta = delta;\n}\n\nvoid\nCAnimBlendAssociation::SetFinishCallback(void (*cb)(CAnimBlendAssociation*, void*), void *arg)\n{\n\tcallbackType = CB_FINISH;\n\tcallback = cb;\n\tcallbackArg = arg;\n}\n\nvoid\nCAnimBlendAssociation::SetDeleteCallback(void (*cb)(CAnimBlendAssociation*, void*), void *arg)\n{\n\tcallbackType = CB_DELETE;\n\tcallback = cb;\n\tcallbackArg = arg;\n}\n\nvoid\nCAnimBlendAssociation::SetCurrentTime(float time)\n{\n\tint i;\n\n\tfor(currentTime = time; currentTime >= hierarchy->totalLength; currentTime -= hierarchy->totalLength)\n\t\tif (!IsRepeating()) {\n\t\t\tcurrentTime = hierarchy->totalLength;\n\t\t\tbreak;\n\t\t}\n\n\tCAnimManager::UncompressAnimation(hierarchy);\n#ifdef ANIM_COMPRESSION\n\t// strangely PC has this but android doesn't\n\tif(hierarchy->keepCompressed){\n\t\tfor(i = 0; i < numNodes; i++)\n\t\t\tif(nodes[i].sequence)\n\t\t\t\tnodes[i].SetupKeyFrameCompressed();\n\t}else\n#endif\n\t{\n\t\tfor(i = 0; i < numNodes; i++)\n\t\t\tif(nodes[i].sequence)\n\t\t\t\tnodes[i].FindKeyFrame(currentTime);\n\t}\n}\n\nvoid\nCAnimBlendAssociation::SyncAnimation(CAnimBlendAssociation *other)\n{\n\tSetCurrentTime(other->currentTime/other->hierarchy->totalLength * hierarchy->totalLength);\n}\n\nvoid\nCAnimBlendAssociation::Start(float time)\n{\n\tflags |= ASSOC_RUNNING;\n\tSetCurrentTime(time);\n}\n\nvoid\nCAnimBlendAssociation::UpdateTimeStep(float timeDelta, float relSpeed)\n{\n\tif(IsRunning())\n\t\ttimeStep = (flags & ASSOC_MOVEMENT ? relSpeed*hierarchy->totalLength : speed) * timeDelta;\n}\n\nbool\nCAnimBlendAssociation::UpdateTime(float timeDelta, float relSpeed)\n{\n\tif(!IsRunning())\n\t\treturn true;\n\tif(currentTime >= hierarchy->totalLength){\n\t\tflags &= ~ASSOC_RUNNING;\n\t\treturn true;\n\t}\n\n\tcurrentTime += timeStep;\n\n\tif(currentTime >= hierarchy->totalLength){\n\t\t// Ran past end\n\n\t\tif(IsRepeating())\n\t\t\tcurrentTime -= hierarchy->totalLength;\n\t\telse{\n\t\t\tcurrentTime = hierarchy->totalLength;\n\t\t\tif(flags & ASSOC_FADEOUTWHENDONE){\n\t\t\t\tflags |= ASSOC_DELETEFADEDOUT;\n\t\t\t\tblendDelta = -4.0f;\n\t\t\t}\n\t\t\tif(callbackType == CB_FINISH){\n\t\t\t\tcallbackType = CB_NONE;\n\t\t\t\tcallback(this, callbackArg);\n\t\t\t}\n\t\t}\n\t}\n\treturn true;\n}\n\n// return whether we still exist after this function\nbool\nCAnimBlendAssociation::UpdateBlend(float timeDelta)\n{\n\tblendAmount += blendDelta * timeDelta;\n\n\tif(blendAmount <= 0.0f && blendDelta < 0.0f){\n\t\t// We're faded out and are not fading in\n\t\tblendAmount = 0.0f;\n\t\tblendDelta = Max(0.0f, blendDelta);\n\t\tif(flags & ASSOC_DELETEFADEDOUT){\n\t\t\tif(callbackType == CB_FINISH || callbackType == CB_DELETE)\n\t\t\t\tcallback(this, callbackArg);\n\t\t\tdelete this;\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tif(blendAmount > 1.0f){\n\t\t// Maximally faded in, clamp values\n\t\tblendAmount = 1.0f;\n\t\tblendDelta = Min(0.0f, blendDelta);\n\t}\n\n\treturn true;\n}\n"
  },
  {
    "path": "src/animation/AnimBlendAssociation.h",
    "content": "#pragma once\n\n#include \"AnimBlendList.h\"\n#include \"AnimBlendNode.h\"\n#include \"AnimBlendHierarchy.h\"\n\nenum {\n\tASSOC_RUNNING = 1,\n\tASSOC_REPEAT = 2,\n\tASSOC_DELETEFADEDOUT = 4,\n\tASSOC_FADEOUTWHENDONE = 8,\n\tASSOC_PARTIAL = 0x10,\n\tASSOC_MOVEMENT = 0x20,\t// ???\n\tASSOC_HAS_TRANSLATION = 0x40,\n\tASSOC_HAS_X_TRANSLATION = 0x80,\t// for 2d velocity extraction\n\tASSOC_WALK = 0x100,\t// for CPed::PlayFootSteps(void)\n\tASSOC_IDLE = 0x200,\t// only xpress scratch has it by default, but game adds it to player's idle animations later\n\tASSOC_NOWALK = 0x400,\t// see CPed::PlayFootSteps(void)\n\tASSOC_BLOCK = 0x800,\t// unused in assoc description, blocks other anims from being played\n\tASSOC_FRONTAL = 0x1000, // anims that we fall to front\n\tASSOC_DRIVING = 0x2000,\t// new in VC\n};\n\n// Anim hierarchy associated with a clump\n// Holds the interpolated state of all nodes.\n// Also used as template for other clumps.\nclass CAnimBlendAssociation\n{\npublic:\n\tenum {\n\t\t// callbackType\n\t\tCB_NONE,\n\t\tCB_FINISH,\n\t\tCB_DELETE\n\t};\n\n\tCAnimBlendLink link;\n\n\tint16 numNodes;\t\t\t// taken from CAnimBlendClumpData::numFrames\n\tint16 groupId;\t\t// ID of CAnimBlendAssocGroup this is in\n\t// NB: Order of these depends on order of nodes in Clump this was built from\n\tCAnimBlendNode *nodes;\n\tCAnimBlendHierarchy *hierarchy;\n\tfloat blendAmount;\n\tfloat blendDelta;\t// how much blendAmount changes over time\n\tfloat currentTime;\n\tfloat speed;\n\tfloat timeStep;\n\tint16 animId;\n\tint16 flags;\n\tint32 callbackType;\n\tvoid (*callback)(CAnimBlendAssociation*, void*);\n\tvoid *callbackArg;\n\n\tbool IsRunning(void) { return !!(flags & ASSOC_RUNNING); }\n\tbool IsRepeating(void) { return !!(flags & ASSOC_REPEAT); }\n\tbool IsPartial(void) { return !!(flags & ASSOC_PARTIAL); }\n\tbool IsMovement(void) { return !!(flags & ASSOC_MOVEMENT); }\n\tbool HasTranslation(void) { return !!(flags & ASSOC_HAS_TRANSLATION); }\n\tbool HasXTranslation(void) { return !!(flags & ASSOC_HAS_X_TRANSLATION); }\n\n\tfloat GetBlendAmount(float weight) { return IsPartial() ? blendAmount : blendAmount*weight; }\n\tCAnimBlendNode *GetNode(int i) { return &nodes[i]; }\n\n\tCAnimBlendAssociation(void);\n\tCAnimBlendAssociation(CAnimBlendAssociation &other);\n#ifndef FIX_BUGS\n\tvirtual\n#endif\n\t~CAnimBlendAssociation(void);\n\tvoid AllocateAnimBlendNodeArray(int n);\n\tvoid FreeAnimBlendNodeArray(void);\n\tvoid Init(RpClump *clump, CAnimBlendHierarchy *hier);\n\tvoid Init(CAnimBlendAssociation &assoc);\n\tvoid SetBlend(float amount, float delta);\n\tvoid SetFinishCallback(void (*callback)(CAnimBlendAssociation*, void*), void *arg);\n\tvoid SetDeleteCallback(void (*callback)(CAnimBlendAssociation*, void*), void *arg);\n\tvoid SetCurrentTime(float time);\n\tvoid SyncAnimation(CAnimBlendAssociation *other);\n\tvoid Start(float time);\n\tvoid UpdateTimeStep(float timeDelta, float relSpeed);\n\tbool UpdateTime(float timeDelta, float relSpeed);\n\tbool UpdateBlend(float timeDelta);\n\n\tvoid SetRun(void) { flags |= ASSOC_RUNNING; }\n\n\tfloat GetTimeLeft() { return hierarchy->totalLength - currentTime; }\n\tfloat GetProgress() { return currentTime / hierarchy->totalLength; }\n\n\tstatic CAnimBlendAssociation *FromLink(CAnimBlendLink *l) {\n\t\treturn (CAnimBlendAssociation*)((uint8*)l - offsetof(CAnimBlendAssociation, link));\n\t}\n};\n"
  },
  {
    "path": "src/animation/AnimBlendClumpData.cpp",
    "content": "#include \"common.h\"\n\n#include \"AnimBlendClumpData.h\"\n#include \"MemoryMgr.h\"\n\nCAnimBlendClumpData::CAnimBlendClumpData(void)\n{\n\tnumFrames = 0;\n\tvelocity2d = nil;\n\tframes = nil;\n\tlink.Init();\n}\n\nCAnimBlendClumpData::~CAnimBlendClumpData(void)\n{\n\tlink.Remove();\n\tif(frames)\n\t\tRwFreeAlign(frames);\n}\n\nvoid\nCAnimBlendClumpData::SetNumberOfFrames(int n)\n{\n\tif(frames)\n\t\tRwFreeAlign(frames);\n\tnumFrames = n;\n\tframes = (AnimBlendFrameData*)RwMallocAlign(numFrames * sizeof(AnimBlendFrameData), 64);\n}\n\nvoid\nCAnimBlendClumpData::ForAllFrames(void (*cb)(AnimBlendFrameData*, void*), void *arg)\n{\n\tint i;\n\tfor(i = 0; i < numFrames; i++)\n\t\tcb(&frames[i], arg);\n}\n"
  },
  {
    "path": "src/animation/AnimBlendClumpData.h",
    "content": "#pragma once\n\n#include \"AnimBlendList.h\"\n\n\nstruct AnimBlendFrameData\n{\n\tenum {\n\t\tIGNORE_ROTATION = 2,\n\t\tIGNORE_TRANSLATION = 4,\n\t\tVELOCITY_EXTRACTION = 8,\n\t\tVELOCITY_EXTRACTION_3D = 0x10,\n\t\tUPDATE_KEYFRAMES = 0x20,\n\t\tCOMPRESSED = 0x40\n\t};\n\n\tuint8 flag;\n\tRwV3d resetPos;\n\tunion {\n\t\tRwFrame *frame;\n\t\tRpHAnimStdInterpFrame *hanimFrame;\n\t};\n\tint32 nodeID;\n};\nVALIDATE_SIZE(AnimBlendFrameData, 0x18);\n\n\nclass CAnimBlendClumpData\n{\npublic:\n\tCAnimBlendLink link;\n\tint32 numFrames;\n\tunion {\n\t\tCVector2D *velocity2d;\n\t\tCVector *velocity3d;\n\t};\n\t// order of frames is determined by RW hierarchy\n\tAnimBlendFrameData *frames;\n\n\tCAnimBlendClumpData(void);\n\t~CAnimBlendClumpData(void);\n\tvoid SetNumberOfFrames(int n);\n\tvoid SetNumberOfBones(int n) { SetNumberOfFrames(n); }\n\tvoid ForAllFrames(void (*cb)(AnimBlendFrameData*, void*), void *arg);\n};\n"
  },
  {
    "path": "src/animation/AnimBlendHierarchy.cpp",
    "content": "#include \"common.h\"\n\n#include \"AnimBlendSequence.h\"\n#include \"AnimBlendHierarchy.h\"\n#include \"AnimManager.h\"\n\nCAnimBlendHierarchy::CAnimBlendHierarchy(void)\n{\n\tsequences = nil;\n\tnumSequences = 0;\n\tcompressed = 0;\n\ttotalLength = 0.0f;\n\tlinkPtr = nil;\n}\n\nvoid\nCAnimBlendHierarchy::Shutdown(void)\n{\n\tCAnimManager::RemoveFromUncompressedCache(this);\n\tRemoveAnimSequences();\n\ttotalLength = 0.0f;\n\tcompressed = 0;\n}\n\nvoid\nCAnimBlendHierarchy::SetName(char *name)\n{\n\tstrncpy(this->name, name, 24);\n}\n\nvoid\nCAnimBlendHierarchy::CalcTotalTime(void)\n{\n\tint i, j;\n\n\ttotalLength = 0.0f;\n\n\tfor(i = 0; i < numSequences; i++){\n#ifdef FIX_BUGS\n\t\tif(sequences[i].numFrames == 0)\n\t\t\tcontinue;\n#endif\n\n\t\ttotalLength = Max(totalLength, sequences[i].GetKeyFrame(sequences[i].numFrames-1)->deltaTime);\n\t\tfor(j = sequences[i].numFrames-1; j >= 1; j--){\n\t\t\tKeyFrame *kf1 = sequences[i].GetKeyFrame(j);\n\t\t\tKeyFrame *kf2 = sequences[i].GetKeyFrame(j-1);\n\t\t\tkf1->deltaTime -= kf2->deltaTime;\n\t\t}\n\t}\n}\n\nvoid\nCAnimBlendHierarchy::CalcTotalTimeCompressed(void)\n{\n\tint i, j;\n\n\ttotalLength = 0.0f;\n\n\tfor(i = 0; i < numSequences; i++){\n#ifdef FIX_BUGS\n\t\tif(sequences[i].numFrames == 0)\n\t\t\tcontinue;\n#endif\n\n\t\ttotalLength = Max(totalLength, sequences[i].GetKeyFrameCompressed(sequences[i].numFrames-1)->GetDeltaTime());\n\t\tfor(j = sequences[i].numFrames-1; j >= 1; j--){\n\t\t\tKeyFrameCompressed *kf1 = sequences[i].GetKeyFrameCompressed(j);\n\t\t\tKeyFrameCompressed *kf2 = sequences[i].GetKeyFrameCompressed(j-1);\n\t\t\tkf1->deltaTime -= kf2->deltaTime;\n\t\t}\n\t}\n}\n\nvoid\nCAnimBlendHierarchy::RemoveQuaternionFlips(void)\n{\n\tint i;\n\n\tfor(i = 0; i < numSequences; i++)\n\t\tsequences[i].RemoveQuaternionFlips();\n}\n\nvoid\nCAnimBlendHierarchy::RemoveAnimSequences(void)\n{\n\tdelete[] sequences;\n\tsequences = nil;\n\tnumSequences = 0;\n}\n\nvoid\nCAnimBlendHierarchy::Uncompress(void)\n{\n#ifdef ANIM_COMPRESSION\n\tint i;\n\tassert(compressed);\n\tfor(i = 0; i < numSequences; i++)\n\t\tsequences[i].Uncompress();\n#endif\n\tcompressed = 0;\n\tif(totalLength == 0.0f){\n\t\tRemoveQuaternionFlips();\n\t\tCalcTotalTime();\n\t}\n}\n\nvoid\nCAnimBlendHierarchy::RemoveUncompressedData(void)\n{\n#ifdef ANIM_COMPRESSION\n\tint i;\n\tassert(!compressed);\n\tfor(i = 0; i < numSequences; i++)\n\t\tsequences[i].RemoveUncompressedData();\n#endif\n\tcompressed = 1;\n}\n\n#ifdef USE_CUSTOM_ALLOCATOR\nvoid\nCAnimBlendHierarchy::MoveMemory(bool onlyone)\n{\n\tint i;\n\tfor(i = 0; i < numSequences; i++)\n\t\tif(sequences[i].MoveMemory() && onlyone)\n\t\t\treturn;\n}\n#endif\n"
  },
  {
    "path": "src/animation/AnimBlendHierarchy.h",
    "content": "#pragma once\n\n#include \"templates.h\"\n\n#ifdef MoveMemory\n#undef MoveMemory\t// windows shit\n#endif\n\nclass CAnimBlendSequence;\n\n// A collection of sequences\nclass CAnimBlendHierarchy\n{\npublic:\n\tchar name[24];\n\tCAnimBlendSequence *sequences;\n\tint16 numSequences;\n\tbool compressed;\n\tbool keepCompressed;\n\tfloat totalLength;\n\tCLink<CAnimBlendHierarchy*> *linkPtr;\n\n\tCAnimBlendHierarchy(void);\n\tvoid Shutdown(void);\n\tvoid SetName(char *name);\n\tvoid CalcTotalTime(void);\n\tvoid CalcTotalTimeCompressed(void);\n\tvoid RemoveQuaternionFlips(void);\n\tvoid RemoveAnimSequences(void);\n\tvoid Uncompress(void);\n\tvoid RemoveUncompressedData(void);\n\tvoid MoveMemory(bool onlyone = false);\n\tbool IsCompressed() { return !!compressed; };\n};\n\nVALIDATE_SIZE(CAnimBlendHierarchy, 0x28);"
  },
  {
    "path": "src/animation/AnimBlendList.h",
    "content": "#pragma once\n\n// name made up\nclass CAnimBlendLink\n{\npublic:\n\tCAnimBlendLink *next;\n\tCAnimBlendLink *prev;\n\n\tvoid Init(void){\n\t\tnext = nil;\n\t\tprev = nil;\n\t}\n\tvoid Prepend(CAnimBlendLink *link){\n\t\tif(next)\n\t\t        next->prev = link;\n\t\tlink->next = next;\n\t\tlink->prev = this;\n\t\tnext = link;\n\t}\n\tvoid Remove(void){\n\t\tif(prev)\n\t\t\tprev->next = next;\n\t\tif(next)\n\t\t\tnext->prev = prev;\n\t\tInit();\n\t}\n};\n"
  },
  {
    "path": "src/animation/AnimBlendNode.cpp",
    "content": "#include \"common.h\"\n\n#include \"AnimBlendAssociation.h\"\n#include \"AnimBlendNode.h\"\n\nvoid \nCAnimBlendNode::Init(void)\n{\n\tframeA = -1;\n\tframeB = -1;\n\tremainingTime = 0.0f;\n\tsequence = nil;\n\tassociation = nil;\n}\n\nbool\nCAnimBlendNode::Update(CVector &trans, CQuaternion &rot, float weight)\n{\n\tbool looped = false;\n\n\ttrans = CVector(0.0f, 0.0f, 0.0f);\n\trot = CQuaternion(0.0f, 0.0f, 0.0f, 0.0f);\n\n\tif(association->IsRunning()){\n\t\tremainingTime -= association->timeStep;\n\t\tif(remainingTime <= 0.0f)\n\t\t\tlooped = NextKeyFrame();\n\t}\n\n\tfloat blend = association->GetBlendAmount(weight);\n\tif(blend > 0.0f){\n\t\tKeyFrameTrans *kfA = (KeyFrameTrans*)sequence->GetKeyFrame(frameA);\n\t\tKeyFrameTrans *kfB = (KeyFrameTrans*)sequence->GetKeyFrame(frameB);\n\t\tfloat t = kfA->deltaTime == 0.0f ? 0.0f : (kfA->deltaTime - remainingTime)/kfA->deltaTime;\n\t\tif(sequence->type & CAnimBlendSequence::KF_TRANS){\n\t\t\ttrans = kfB->translation + t*(kfA->translation - kfB->translation);\n\t\t\ttrans *= blend;\n\t\t}\n\t\tif(sequence->type & CAnimBlendSequence::KF_ROT){\n\t\t\trot.Slerp(kfB->rotation, kfA->rotation, theta, invSin, t);\n\t\t\trot *= blend;\n\t\t}\n\t}\n\n\treturn looped;\n}\n\nbool\nCAnimBlendNode::UpdateCompressed(CVector &trans, CQuaternion &rot, float weight)\n{\n\tbool looped = false;\n\n\ttrans = CVector(0.0f, 0.0f, 0.0f);\n\trot = CQuaternion(0.0f, 0.0f, 0.0f, 0.0f);\n\n\tif(association->IsRunning()){\n\t\tremainingTime -= association->timeStep;\n\t\tif(remainingTime <= 0.0f)\n\t\t\tlooped = NextKeyFrameCompressed();\n\t}\n\n\tfloat blend = association->GetBlendAmount(weight);\n\tif(blend > 0.0f){\n\t\tKeyFrameTransCompressed *kfA = (KeyFrameTransCompressed*)sequence->GetKeyFrameCompressed(frameA);\n\t\tKeyFrameTransCompressed *kfB = (KeyFrameTransCompressed*)sequence->GetKeyFrameCompressed(frameB);\n\t\tfloat t = kfA->deltaTime == 0 ? 0.0f : (kfA->GetDeltaTime() - remainingTime)/kfA->GetDeltaTime();\n\t\tif(sequence->type & CAnimBlendSequence::KF_TRANS){\n\t\t\tCVector transA, transB;\n\t\t\tkfA->GetTranslation(&transA);\n\t\t\tkfB->GetTranslation(&transB);\n\t\t\ttrans = transB + t*(transA - transB);\n\t\t\ttrans *= blend;\n\t\t}\n\t\tif(sequence->type & CAnimBlendSequence::KF_ROT){\n\t\t\tCQuaternion rotA, rotB;\n\t\t\tkfA->GetRotation(&rotA);\n\t\t\tkfB->GetRotation(&rotB);\n\t\t\trot.Slerp(rotB, rotA, theta, invSin, t);\n\t\t\trot *= blend;\n\t\t}\n\t}\n\n\treturn looped;\n}\n\nbool\nCAnimBlendNode::NextKeyFrame(void)\n{\n\tbool looped;\n\n\tif(sequence->numFrames <= 1)\n\t\treturn false;\n\n\tlooped = false;\n\tframeB = frameA;\n\n\t// Advance as long as we have to\n\twhile(remainingTime <= 0.0f){\n\t\tframeA++;\n\n\t\tif(frameA >= sequence->numFrames){\n\t\t\t// reached end of animation\n\t\t\tif(!association->IsRepeating()){\n\t\t\t\tframeA--;\n\t\t\t\tremainingTime = 0.0f;\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tlooped = true;\n\t\t\tframeA = 0;\n\t\t}\n\n\t\tremainingTime += sequence->GetKeyFrame(frameA)->deltaTime;\n\t}\n\n\tframeB = frameA - 1;\n\tif(frameB < 0)\n\t\tframeB += sequence->numFrames;\n\n\tCalcDeltas();\n\treturn looped;\n}\n\nbool\nCAnimBlendNode::NextKeyFrameCompressed(void)\n{\n\tbool looped;\n\n\tif(sequence->numFrames <= 1)\n\t\treturn false;\n\n\tlooped = false;\n\tframeB = frameA;\n\n\t// Advance as long as we have to\n\twhile(remainingTime <= 0.0f){\n\t\tframeA++;\n\n\t\tif(frameA >= sequence->numFrames){\n\t\t\t// reached end of animation\n\t\t\tif(!association->IsRepeating()){\n\t\t\t\tframeA--;\n\t\t\t\tremainingTime = 0.0f;\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tlooped = true;\n\t\t\tframeA = 0;\n\t\t}\n\n\t\tremainingTime += sequence->GetKeyFrameCompressed(frameA)->GetDeltaTime();\n\t}\n\n\tframeB = frameA - 1;\n\tif(frameB < 0)\n\t\tframeB += sequence->numFrames;\n\n\tCalcDeltasCompressed();\n\treturn looped;\n}\n\n// Set animation to time t\nbool\nCAnimBlendNode::FindKeyFrame(float t)\n{\n\tif(sequence->numFrames < 1)\n\t\treturn false;\n\n\tframeA = 0;\n\tframeB = frameA;\n\n\tif(sequence->numFrames == 1){\n\t\tremainingTime = 0.0f;\n\t}else{\n\t\t// advance until t is between frameB and frameA\n\t\twhile (t > sequence->GetKeyFrame(++frameA)->deltaTime) {\n\t\t\tt -= sequence->GetKeyFrame(frameA)->deltaTime;\n\t\t\tif (frameA + 1 >= sequence->numFrames) {\n\t\t\t\t// reached end of animation\n\t\t\t\tif (!association->IsRepeating()) {\n\t\t\t\t\tCalcDeltas();\n\t\t\t\t\tremainingTime = 0.0f;\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tframeA = 0;\n\t\t\t}\n\t\t\tframeB = frameA;\n\t\t}\n\n\t\tremainingTime = sequence->GetKeyFrame(frameA)->deltaTime - t;\n\t}\n\n\tCalcDeltas();\n\treturn true;\n}\n\nbool\nCAnimBlendNode::SetupKeyFrameCompressed(void)\n{\n\tif(sequence->numFrames < 1)\n\t\treturn false;\n\n\tframeA = 1;\n\tframeB = 0;\n\n\tif(sequence->numFrames == 1){\n\t\tframeA = 0;\n\t\tremainingTime = 0.0f;\n\t}else\n\t\tremainingTime = sequence->GetKeyFrameCompressed(frameA)->GetDeltaTime();\n\n\tCalcDeltasCompressed();\n\treturn true;\n}\n\nvoid\nCAnimBlendNode::CalcDeltas(void)\n{\n\tif((sequence->type & CAnimBlendSequence::KF_ROT) == 0)\n\t\treturn;\n\tKeyFrame *kfA = sequence->GetKeyFrame(frameA);\n\tKeyFrame *kfB = sequence->GetKeyFrame(frameB);\n\tfloat cos = DotProduct(kfA->rotation, kfB->rotation);\n\tif(cos > 1.0f)\n\t\tcos = 1.0f;\n\ttheta = Acos(cos);\n\tinvSin = theta == 0.0f ?  0.0f : 1.0f/Sin(theta);\n}\n\nvoid\nCAnimBlendNode::CalcDeltasCompressed(void)\n{\n\tif((sequence->type & CAnimBlendSequence::KF_ROT) == 0)\n\t\treturn;\n\tKeyFrameCompressed *kfA = sequence->GetKeyFrameCompressed(frameA);\n\tKeyFrameCompressed *kfB = sequence->GetKeyFrameCompressed(frameB);\n\tCQuaternion rotA, rotB;\n\tkfA->GetRotation(&rotA);\n\tkfB->GetRotation(&rotB);\n\tfloat cos = DotProduct(rotA, rotB);\n\tif(cos < 0.0f){\n\t\trotB *= -1.0f;\n\t\tkfB->SetRotation(rotB);\n\t}\n\tcos = DotProduct(rotA, rotB);\n\tif(cos > 1.0f)\n\t\tcos = 1.0f;\n\ttheta = Acos(cos);\n\tinvSin = theta == 0.0f ?  0.0f : 1.0f/Sin(theta);\n}\n\nvoid\nCAnimBlendNode::GetCurrentTranslation(CVector &trans, float weight)\n{\n\ttrans = CVector(0.0f, 0.0f, 0.0f);\n\n\tfloat blend = association->GetBlendAmount(weight);\n\tif(blend > 0.0f){\n\t\tKeyFrameTrans *kfA = (KeyFrameTrans*)sequence->GetKeyFrame(frameA);\n\t\tKeyFrameTrans *kfB = (KeyFrameTrans*)sequence->GetKeyFrame(frameB);\n\t\tfloat t = kfA->deltaTime == 0.0f ? 0.0f : (kfA->deltaTime - remainingTime)/kfA->deltaTime;\n\t\tif(sequence->type & CAnimBlendSequence::KF_TRANS){\n\t\t\ttrans = kfB->translation + t*(kfA->translation - kfB->translation);\n\t\t\ttrans *= blend;\n\t\t}\n\t}\n}\n\nvoid\nCAnimBlendNode::GetCurrentTranslationCompressed(CVector &trans, float weight)\n{\n\ttrans = CVector(0.0f, 0.0f, 0.0f);\n\n\tfloat blend = association->GetBlendAmount(weight);\n\tif(blend > 0.0f){\n\t\tKeyFrameTransCompressed *kfA = (KeyFrameTransCompressed*)sequence->GetKeyFrameCompressed(frameA);\n\t\tKeyFrameTransCompressed *kfB = (KeyFrameTransCompressed*)sequence->GetKeyFrameCompressed(frameB);\n\t\tfloat t = kfA->deltaTime == 0 ? 0.0f : (kfA->GetDeltaTime() - remainingTime)/kfA->GetDeltaTime();\n\t\tif(sequence->type & CAnimBlendSequence::KF_TRANS){\n\t\t\tCVector transA, transB;\n\t\t\tkfA->GetTranslation(&transA);\n\t\t\tkfB->GetTranslation(&transB);\n\t\t\ttrans = transB + t*(transA - transB);\n\t\t\ttrans *= blend;\n\t\t}\n\t}\n}\n\nvoid\nCAnimBlendNode::GetEndTranslation(CVector &trans, float weight)\n{\n\ttrans = CVector(0.0f, 0.0f, 0.0f);\n\n\tfloat blend = association->GetBlendAmount(weight);\n\tif(blend > 0.0f){\n\t\tKeyFrameTrans *kf = (KeyFrameTrans*)sequence->GetKeyFrame(sequence->numFrames-1);\n\t\tif(sequence->type & CAnimBlendSequence::KF_TRANS)\n\t\t\ttrans = kf->translation * blend;\n\t}\n}\n\nvoid\nCAnimBlendNode::GetEndTranslationCompressed(CVector &trans, float weight)\n{\n\ttrans = CVector(0.0f, 0.0f, 0.0f);\n\n\tfloat blend = association->GetBlendAmount(weight);\n\tif(blend > 0.0f){\n\t\tKeyFrameTransCompressed *kf = (KeyFrameTransCompressed*)sequence->GetKeyFrameCompressed(sequence->numFrames-1);\n\t\tif(sequence->type & CAnimBlendSequence::KF_TRANS){\n\t\t\tCVector pos;\n\t\t\tkf->GetTranslation(&pos);\n\t\t\ttrans = pos * blend;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/animation/AnimBlendNode.h",
    "content": "#pragma once\n\n#include \"AnimBlendSequence.h\"\n\nclass CAnimBlendAssociation;\n\n// The interpolated state between two key frames in a sequence\nclass CAnimBlendNode\n{\npublic:\n\t// for slerp\n\tfloat theta;\t\t// angle between quaternions\n\tfloat invSin;\t\t// 1/Sin(theta)\n\t// indices into array in sequence\n\tint32 frameA;\t\t// next key frame\n\tint32 frameB;\t\t// previous key frame\n\tfloat remainingTime;\t// time until frames have to advance\n\tCAnimBlendSequence *sequence;\n\tCAnimBlendAssociation *association;\n\n\tvoid Init(void);\n\tbool Update(CVector &trans, CQuaternion &rot, float weight);\n\tbool UpdateCompressed(CVector &trans, CQuaternion &rot, float weight);\n\tbool NextKeyFrame(void);\n\tbool NextKeyFrameCompressed(void);\n\tbool FindKeyFrame(float t);\n\tbool SetupKeyFrameCompressed(void);\n\tvoid CalcDeltas(void);\n\tvoid CalcDeltasCompressed(void);\n\tvoid GetCurrentTranslation(CVector &trans, float weight);\n\tvoid GetCurrentTranslationCompressed(CVector &trans, float weight);\n\tvoid GetEndTranslation(CVector &trans, float weight);\n\tvoid GetEndTranslationCompressed(CVector &trans, float weight);\n};\n\n\nVALIDATE_SIZE(CAnimBlendNode, 0x1C);\n"
  },
  {
    "path": "src/animation/AnimBlendSequence.cpp",
    "content": "#include \"common.h\"\n\n#include \"AnimBlendSequence.h\"\n#include \"MemoryHeap.h\"\n\nCAnimBlendSequence::CAnimBlendSequence(void)\n{\n\ttype = 0;\n\tnumFrames = 0;\n\tkeyFrames = nil;\n\tkeyFramesCompressed = nil;\n\tboneTag = -1;\n}\n\nCAnimBlendSequence::~CAnimBlendSequence(void)\n{\n\tif(keyFrames)\n\t\tRwFree(keyFrames);\n\tif(keyFramesCompressed)\n\t\tRwFree(keyFramesCompressed);\n}\n\nvoid\nCAnimBlendSequence::SetName(char *name)\n{\n\tstrncpy(this->name, name, 24);\n}\n\nvoid\nCAnimBlendSequence::SetNumFrames(int numFrames, bool translation, bool compressed)\n{\n\tif(translation){\n\t\ttype |= KF_ROT | KF_TRANS;\n\t\tif(compressed)\n\t\t\tkeyFramesCompressed = RwMalloc(sizeof(KeyFrameTrans) * numFrames);\n\t\telse\n\t\t\tkeyFrames = RwMalloc(sizeof(KeyFrameTrans) * numFrames);\n\t}else{\n\t\ttype |= KF_ROT;\n\t\tif(compressed)\n\t\t\tkeyFramesCompressed = RwMalloc(sizeof(KeyFrame) * numFrames);\n\t\telse\n\t\t\tkeyFrames = RwMalloc(sizeof(KeyFrame) * numFrames);\n\t}\n\tthis->numFrames = numFrames;\n}\n\nvoid\nCAnimBlendSequence::RemoveQuaternionFlips(void)\n{\n\tint i;\n\tCQuaternion last;\n\tKeyFrame *frame;\n\n\tif(numFrames < 2)\n\t\treturn;\n\n\tframe = GetKeyFrame(0);\n\tlast = frame->rotation;\n\tfor(i = 1; i < numFrames; i++){\n\t\tframe = GetKeyFrame(i);\n\t\tif(DotProduct(last, frame->rotation) < 0.0f)\n\t\t\tframe->rotation = -frame->rotation;\n\t\tlast = frame->rotation;\n\t}\n}\n\nvoid\nCAnimBlendSequence::Uncompress(void)\n{\n\tint i;\n\n\tif(numFrames == 0)\n\t\treturn;\n\n\tPUSH_MEMID(MEMID_ANIMATION);\n\n\tfloat rotScale = 1.0f/4096.0f;\n\tfloat timeScale = 1.0f/60.0f;\n\tfloat transScale = 1.0f/1024.0f;\n\tif(type & KF_TRANS){\n\t\tvoid *newKfs = RwMalloc(numFrames * sizeof(KeyFrameTrans));\n\t\tKeyFrameTransCompressed *ckf = (KeyFrameTransCompressed*)keyFramesCompressed;\n\t\tKeyFrameTrans *kf = (KeyFrameTrans*)newKfs;\n\t\tfor(i = 0; i < numFrames; i++){\n\t\t\tkf->rotation.x = ckf->rot[0]*rotScale;\n\t\t\tkf->rotation.y = ckf->rot[1]*rotScale;\n\t\t\tkf->rotation.z = ckf->rot[2]*rotScale;\n\t\t\tkf->rotation.w = ckf->rot[3]*rotScale;\n\t\t\tkf->deltaTime = ckf->deltaTime*timeScale;\n\t\t\tkf->translation.x = ckf->trans[0]*transScale;\n\t\t\tkf->translation.y = ckf->trans[1]*transScale;\n\t\t\tkf->translation.z = ckf->trans[2]*transScale;\n\t\t\tkf++;\n\t\t\tckf++;\n\t\t}\n\t\tkeyFrames = newKfs;\n\t}else{\n\t\tvoid *newKfs = RwMalloc(numFrames * sizeof(KeyFrame));\n\t\tKeyFrameCompressed *ckf = (KeyFrameCompressed*)keyFramesCompressed;\n\t\tKeyFrame *kf = (KeyFrame*)newKfs;\n\t\tfor(i = 0; i < numFrames; i++){\n\t\t\tkf->rotation.x = ckf->rot[0]*rotScale;\n\t\t\tkf->rotation.y = ckf->rot[1]*rotScale;\n\t\t\tkf->rotation.z = ckf->rot[2]*rotScale;\n\t\t\tkf->rotation.w = ckf->rot[3]*rotScale;\n\t\t\tkf->deltaTime = ckf->deltaTime*timeScale;\n\t\t\tkf++;\n\t\t\tckf++;\n\t\t}\n\t\tkeyFrames = newKfs;\n\t}\n\tREGISTER_MEMPTR(&keyFrames);\n\n\tRwFree(keyFramesCompressed);\n\tkeyFramesCompressed = nil;\n\n\tPOP_MEMID();\n}\n\nvoid\nCAnimBlendSequence::CompressKeyframes(void)\n{\n\tint i;\n\n\tif(numFrames == 0)\n\t\treturn;\n\n\tPUSH_MEMID(MEMID_ANIMATION);\n\n\tfloat rotScale = 4096.0f;\n\tfloat timeScale = 60.0f;\n\tfloat transScale = 1024.0f;\n\tif(type & KF_TRANS){\n\t\tvoid *newKfs = RwMalloc(numFrames * sizeof(KeyFrameTransCompressed));\n\t\tKeyFrameTransCompressed *ckf = (KeyFrameTransCompressed*)newKfs;\n\t\tKeyFrameTrans *kf = (KeyFrameTrans*)keyFrames;\n\t\tfor(i = 0; i < numFrames; i++){\n\t\t\tckf->rot[0] = kf->rotation.x*rotScale;\n\t\t\tckf->rot[1] = kf->rotation.y*rotScale;\n\t\t\tckf->rot[2] = kf->rotation.z*rotScale;\n\t\t\tckf->rot[3] = kf->rotation.w*rotScale;\n\t\t\tckf->deltaTime = kf->deltaTime*timeScale + 0.5f;\n\t\t\tckf->trans[0] = kf->translation.x*transScale;\n\t\t\tckf->trans[1] = kf->translation.y*transScale;\n\t\t\tckf->trans[2] = kf->translation.z*transScale;\n\t\t\tkf++;\n\t\t\tckf++;\n\t\t}\n\t\tkeyFramesCompressed = newKfs;\n\t}else{\n\t\tvoid *newKfs = RwMalloc(numFrames * sizeof(KeyFrameCompressed));\n\t\tKeyFrameCompressed *ckf = (KeyFrameCompressed*)newKfs;\n\t\tKeyFrame *kf = (KeyFrame*)keyFrames;\n\t\tfor(i = 0; i < numFrames; i++){\n\t\t\tckf->rot[0] = kf->rotation.x*rotScale;\n\t\t\tckf->rot[1] = kf->rotation.y*rotScale;\n\t\t\tckf->rot[2] = kf->rotation.z*rotScale;\n\t\t\tckf->rot[3] = kf->rotation.w*rotScale;\n\t\t\tckf->deltaTime = kf->deltaTime*timeScale + 0.5f;\n\t\t\tkf++;\n\t\t\tckf++;\n\t\t}\n\t\tkeyFramesCompressed = newKfs;\n\t}\n\tREGISTER_MEMPTR(&keyFramesCompressed);\n\n\tPOP_MEMID();\n}\n\nvoid\nCAnimBlendSequence::RemoveUncompressedData(void)\n{\n\tif(numFrames == 0)\n\t\treturn;\n\tCompressKeyframes();\n\tRwFree(keyFrames);\n\tkeyFrames = nil;\n}\n\n#ifdef USE_CUSTOM_ALLOCATOR\nbool\nCAnimBlendSequence::MoveMemory(void)\n{\n\tif(keyFrames){\n\t\tvoid *newaddr = gMainHeap.MoveMemory(keyFrames);\n\t\tif(newaddr != keyFrames){\n\t\t\tkeyFrames = newaddr;\n\t\t\treturn true;\n\t\t}\n\t}else if(keyFramesCompressed){\n\t\tvoid *newaddr = gMainHeap.MoveMemory(keyFramesCompressed);\n\t\tif(newaddr != keyFramesCompressed){\n\t\t\tkeyFramesCompressed = newaddr;\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n#endif\n"
  },
  {
    "path": "src/animation/AnimBlendSequence.h",
    "content": "#pragma once\n\n#include \"Quaternion.h\"\n\n#ifdef MoveMemory\n#undef MoveMemory\t// windows shit\n#endif\n\n// TODO: put them somewhere else?\nstruct KeyFrame {\n\tCQuaternion rotation;\n\tfloat deltaTime;\t// relative to previous key frame\n};\n\nstruct KeyFrameTrans : KeyFrame {\n\tCVector translation;\n};\n\nstruct KeyFrameCompressed {\n\tint16 rot[4];\t\t// 4096\n\tint16 deltaTime;\t// 60\n\n\tvoid GetRotation(CQuaternion *quat){\n\t\tfloat scale = 1.0f/4096.0f;\n\t\tquat->x = rot[0]*scale;\n\t\tquat->y = rot[1]*scale;\n\t\tquat->z = rot[2]*scale;\n\t\tquat->w = rot[3]*scale;\n\t}\n\tvoid SetRotation(const CQuaternion &quat){\n\t\trot[0] = quat.x * 4096.0f;\n\t\trot[1] = quat.y * 4096.0f;\n\t\trot[2] = quat.z * 4096.0f;\n\t\trot[3] = quat.w * 4096.0f;\n\t}\n\tfloat GetDeltaTime(void) { return deltaTime/60.0f; }\n\tvoid SetTime(float t) { deltaTime = t*60.0f + 0.5f; }\n};\n\nstruct KeyFrameTransCompressed : KeyFrameCompressed {\n\tint16 trans[3];\t\t// 1024\n\n\tvoid GetTranslation(CVector *vec) {\n\t\tfloat scale = 1.0f/1024.0f;\n\t\tvec->x = trans[0]*scale;\n\t\tvec->y = trans[1]*scale;\n\t\tvec->z = trans[2]*scale;\n\t}\n\tvoid SetTranslation(const CVector &vec){\n\t\ttrans[0] = vec.x*1024.0f;\n\t\ttrans[1] = vec.y*1024.0f;\n\t\ttrans[2] = vec.z*1024.0f;\n\t}\n};\n\n\n// The sequence of key frames of one animated node\nclass CAnimBlendSequence\n{\npublic:\n\tenum {\n\t\tKF_ROT = 1,\n\t\tKF_TRANS = 2\n\t};\n\tint32 type;\n\tchar name[24];\n\tint32 numFrames;\n\tint16 boneTag;\n\tvoid *keyFrames;\n\tvoid *keyFramesCompressed;\n\n\tCAnimBlendSequence(void);\n\tvirtual ~CAnimBlendSequence(void);\n\tvoid SetName(char *name);\n\tvoid SetNumFrames(int numFrames, bool translation, bool compressed);\n\tvoid RemoveQuaternionFlips(void);\n\tKeyFrame *GetKeyFrame(int n) {\n\t\treturn type & KF_TRANS ?\n\t\t\t&((KeyFrameTrans*)keyFrames)[n] :\n\t\t\t&((KeyFrame*)keyFrames)[n];\n\t}\n\tKeyFrameCompressed *GetKeyFrameCompressed(int n) {\n\t\treturn type & KF_TRANS ?\n\t\t\t&((KeyFrameTransCompressed*)keyFramesCompressed)[n] :\n\t\t\t&((KeyFrameCompressed*)keyFramesCompressed)[n];\n\t}\n\tbool HasTranslation(void) { return !!(type & KF_TRANS); }\n\tvoid Uncompress(void);\n\tvoid CompressKeyframes(void);\n\tvoid RemoveUncompressedData(void);\n\tbool MoveMemory(void);\n\n\tvoid SetBoneTag(int tag) { boneTag = tag; }\n};\nVALIDATE_SIZE(CAnimBlendSequence, 0x30);\n"
  },
  {
    "path": "src/animation/AnimManager.cpp",
    "content": "#include \"common.h\"\n\n#include \"General.h\"\n#include \"RwHelper.h\"\n#include \"ModelInfo.h\"\n#include \"ModelIndices.h\"\n#include \"FileMgr.h\"\n#include \"RpAnimBlend.h\"\n#include \"AnimBlendClumpData.h\"\n#include \"AnimBlendAssociation.h\"\n#include \"AnimBlendAssocGroup.h\"\n#include \"AnimManager.h\"\n#include \"Streaming.h\"\n\nCAnimBlock CAnimManager::ms_aAnimBlocks[NUMANIMBLOCKS];\nCAnimBlendHierarchy CAnimManager::ms_aAnimations[NUMANIMATIONS];\nint32 CAnimManager::ms_numAnimBlocks;\nint32 CAnimManager::ms_numAnimations;\nCAnimBlendAssocGroup *CAnimManager::ms_aAnimAssocGroups;\nCLinkList<CAnimBlendHierarchy*> CAnimManager::ms_animCache;\n\nAnimAssocDesc aStdAnimDescs[] = {\n\t{ ANIM_STD_WALK, ASSOC_REPEAT | ASSOC_MOVEMENT | ASSOC_HAS_TRANSLATION | ASSOC_WALK },\n\t{ ANIM_STD_RUN, ASSOC_REPEAT | ASSOC_MOVEMENT | ASSOC_HAS_TRANSLATION | ASSOC_WALK },\n\t{ ANIM_STD_RUNFAST, ASSOC_REPEAT | ASSOC_MOVEMENT | ASSOC_HAS_TRANSLATION | ASSOC_WALK },\n\t{ ANIM_STD_IDLE, ASSOC_REPEAT },\n\t{ ANIM_STD_STARTWALK, ASSOC_HAS_TRANSLATION },\n\t{ ANIM_STD_RUNSTOP1, ASSOC_DELETEFADEDOUT | ASSOC_HAS_TRANSLATION },\n\t{ ANIM_STD_RUNSTOP2, ASSOC_DELETEFADEDOUT | ASSOC_HAS_TRANSLATION },\n\t{ ANIM_STD_IDLE_CAM, ASSOC_REPEAT | ASSOC_PARTIAL },\n\t{ ANIM_STD_IDLE_HBHB, ASSOC_REPEAT | ASSOC_PARTIAL },\n\t{ ANIM_STD_IDLE_TIRED, ASSOC_REPEAT },\n\t{ ANIM_STD_IDLE_BIGGUN, ASSOC_REPEAT | ASSOC_PARTIAL },\n\t{ ANIM_STD_CHAT, ASSOC_REPEAT | ASSOC_PARTIAL },\n\t{ ANIM_STD_HAILTAXI, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_KO_FRONT, ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION | ASSOC_FRONTAL },\n\t{ ANIM_STD_KO_LEFT, ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION | ASSOC_FRONTAL },\n\t{ ANIM_STD_KO_BACK, ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION | ASSOC_FRONTAL },\n\t{ ANIM_STD_KO_RIGHT, ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION | ASSOC_FRONTAL },\n\t{ ANIM_STD_KO_SHOT_FACE, ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION | ASSOC_FRONTAL },\n\t{ ANIM_STD_KO_SHOT_STOMACH, ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION },\n\t{ ANIM_STD_KO_SHOT_ARM_L, ASSOC_PARTIAL | ASSOC_FRONTAL },\n\t{ ANIM_STD_KO_SHOT_ARM_R, ASSOC_PARTIAL | ASSOC_FRONTAL },\n\t{ ANIM_STD_KO_SHOT_LEG_L, ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION },\n\t{ ANIM_STD_KO_SHOT_LEG_R, ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION },\n\t{ ANIM_STD_SPINFORWARD_LEFT, ASSOC_PARTIAL | ASSOC_FRONTAL },\n\t{ ANIM_STD_SPINFORWARD_RIGHT, ASSOC_PARTIAL | ASSOC_FRONTAL },\n\t{ ANIM_STD_HIGHIMPACT_FRONT, ASSOC_PARTIAL },\n\t{ ANIM_STD_HIGHIMPACT_LEFT, ASSOC_PARTIAL },\n\t{ ANIM_STD_HIGHIMPACT_BACK, ASSOC_PARTIAL | ASSOC_FRONTAL },\n\t{ ANIM_STD_HIGHIMPACT_RIGHT, ASSOC_PARTIAL },\n\t{ ANIM_STD_HITBYGUN_FRONT, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_NOWALK },\n\t{ ANIM_STD_HITBYGUN_LEFT, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_NOWALK },\n\t{ ANIM_STD_HITBYGUN_BACK, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_NOWALK },\n\t{ ANIM_STD_HITBYGUN_RIGHT, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_NOWALK },\n\t{ ANIM_STD_HIT_FRONT, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION },\n\t{ ANIM_STD_HIT_LEFT, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_HIT_BACK, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION },\n\t{ ANIM_STD_HIT_RIGHT, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_HIT_FLOOR, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL },\n\t{ ANIM_STD_HIT_BODYBLOW, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION },\n\t{ ANIM_STD_HIT_CHEST, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION },\n\t{ ANIM_STD_HIT_HEAD, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION },\n\t{ ANIM_STD_HIT_WALK, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION },\n\t{ ANIM_STD_HIT_WALL, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION },\n\t{ ANIM_STD_HIT_FLOOR_FRONT, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_FRONTAL },\n\t{ ANIM_STD_HIT_BEHIND, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_FIGHT_IDLE, ASSOC_REPEAT },\n\t{ ANIM_STD_FIGHT_2IDLE, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_FIGHT_SHUFFLE_F, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION },\n\t{ ANIM_STD_FIGHT_BODYBLOW, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_FIGHT_HEAD, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_FIGHT_KICK, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_FIGHT_KNEE, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_FIGHT_LHOOK, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_FIGHT_PUNCH, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_FIGHT_ROUNDHOUSE, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION },\n\t{ ANIM_STD_FIGHT_LONGKICK, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION },\n\t{ ANIM_STD_PARTIAL_PUNCH, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_NOWALK },\n\t{ ANIM_STD_FIGHT_JAB, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_FIGHT_ELBOW_L, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_FIGHT_ELBOW_R, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_FIGHT_BKICK_L, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_FIGHT_BKICK_R, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_DETONATE, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_PUNCH, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_PARTIALPUNCH, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_KICKGROUND, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_THROW_UNDER, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_FIGHT_SHUFFLE_B, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION },\n\t{ ANIM_STD_JACKEDCAR_RHS, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL },\n\t{ ANIM_STD_JACKEDCAR_LO_RHS, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL },\n\t{ ANIM_STD_JACKEDCAR_LHS, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL },\n\t{ ANIM_STD_JACKEDCAR_LO_LHS, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL },\n\t{ ANIM_STD_QUICKJACK, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_QUICKJACKED, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL },\n\t{ ANIM_STD_CAR_ALIGN_DOOR_LHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_CAR_ALIGNHI_DOOR_LHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_CAR_OPEN_DOOR_LHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_CARDOOR_LOCKED_LHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_CAR_PULL_OUT_PED_LHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_CAR_PULL_OUT_PED_LO_LHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_CAR_GET_IN_LHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_CAR_GET_IN_LO_LHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_CAR_CLOSE_DOOR_LHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_CAR_CLOSE_DOOR_LO_LHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_CAR_CLOSE_DOOR_ROLLING_LHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_CAR_CLOSE_DOOR_ROLLING_LO_LHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_CAR_JUMP_IN_LO_LHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_GETOUT_LHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_GETOUT_LO_LHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_CAR_CLOSE_LHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_CAR_ALIGN_DOOR_RHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_CAR_ALIGNHI_DOOR_RHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_CAR_OPEN_DOOR_RHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_CARDOOR_LOCKED_RHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_CAR_PULL_OUT_PED_RHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_CAR_PULL_OUT_PED_LO_RHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_CAR_GET_IN_RHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_CAR_GET_IN_LO_RHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_CAR_CLOSE_DOOR_RHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_CAR_CLOSE_DOOR_LO_RHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_CAR_SHUFFLE_RHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_CAR_SHUFFLE_LO_RHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_CAR_SIT, ASSOC_DELETEFADEDOUT},\n\t{ ANIM_STD_CAR_SIT_LO, ASSOC_DELETEFADEDOUT},\n\t{ ANIM_STD_CAR_SIT_P, ASSOC_DELETEFADEDOUT},\n\t{ ANIM_STD_CAR_SIT_P_LO, ASSOC_DELETEFADEDOUT},\n\t{ ANIM_STD_CAR_DRIVE_LEFT, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_DRIVING },\n\t{ ANIM_STD_CAR_DRIVE_RIGHT, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_DRIVING },\n\t{ ANIM_STD_CAR_DRIVE_LEFT_LO, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_DRIVING },\n\t{ ANIM_STD_CAR_DRIVE_RIGHT_LO, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_DRIVING },\n\t{ ANIM_STD_CAR_DRIVEBY_LEFT, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_DRIVING },\n\t{ ANIM_STD_CAR_DRIVEBY_RIGHT, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_DRIVING },\n\t{ ANIM_STD_CAR_DRIVEBY_LEFT_LO, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_DRIVING },\n\t{ ANIM_STD_CAR_DRIVEBY_RIGHT_LO, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_DRIVING },\n\t{ ANIM_STD_CAR_LOOKBEHIND, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_DRIVING },\n\t{ ANIM_STD_BOAT_DRIVE, ASSOC_DELETEFADEDOUT | ASSOC_DRIVING },\n\t{ ANIM_STD_BOAT_DRIVE_LEFT, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_DRIVING },\n\t{ ANIM_STD_BOAT_DRIVE_RIGHT, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_DRIVING },\n\t{ ANIM_STD_BOAT_LOOKBEHIND, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_DRIVING },\n\t{ ANIM_STD_BIKE_PICKUP_LHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_BIKE_PICKUP_RHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_BIKE_PULLUP_LHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_BIKE_PULLUP_RHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_BIKE_ELBOW_LHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_BIKE_ELBOW_RHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_BIKE_FALLOFF, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION },\n\t{ ANIM_STD_BIKE_FALLBACK, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION },\n\t{ ANIM_STD_GETOUT_RHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_GETOUT_LO_RHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_CAR_CLOSE_RHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_CAR_HOOKERTALK, ASSOC_REPEAT | ASSOC_PARTIAL },\n\t{ ANIM_STD_TRAIN_GETIN, ASSOC_PARTIAL },\n\t{ ANIM_STD_TRAIN_GETOUT, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_CRAWLOUT_LHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_CRAWLOUT_RHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_ROLLOUT_LHS, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION | ASSOC_HAS_X_TRANSLATION },\n\t{ ANIM_STD_ROLLOUT_RHS, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION | ASSOC_HAS_X_TRANSLATION },\n\t{ ANIM_STD_GET_UP, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION },\n\t{ ANIM_STD_GET_UP_LEFT, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION },\n\t{ ANIM_STD_GET_UP_RIGHT, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION },\n\t{ ANIM_STD_GET_UP_FRONT, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION },\n\t{ ANIM_STD_JUMP_LAUNCH, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_JUMP_GLIDE, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL },\n\t{ ANIM_STD_JUMP_LAND, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION },\n\t{ ANIM_STD_FALL, ASSOC_REPEAT | ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL },\n\t{ ANIM_STD_FALL_GLIDE, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL },\n\t{ ANIM_STD_FALL_LAND, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION },\n\t{ ANIM_STD_FALL_COLLAPSE, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION },\n\t{ ANIM_STD_FALL_ONBACK, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL },\n\t{ ANIM_STD_FALL_ONFRONT, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_FRONTAL },\n\t{ ANIM_STD_EVADE_STEP, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION },\n\t{ ANIM_STD_EVADE_DIVE, ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION | ASSOC_FRONTAL },\n\t{ ANIM_STD_XPRESS_SCRATCH, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_IDLE },\n\t{ ANIM_STD_ROADCROSS, ASSOC_REPEAT | ASSOC_PARTIAL },\n\t{ ANIM_STD_TURN180, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_ARREST, ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION },\n\t{ ANIM_STD_DROWN, ASSOC_PARTIAL },\n\t{ ANIM_STD_DUCK_DOWN, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL },\n\t{ ANIM_STD_DUCK_LOW, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL },\n\t{ ANIM_STD_DUCK_WEAPON, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL },\n\t{ ANIM_STD_RBLOCK_SHOOT, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL },\n\t{ ANIM_STD_HANDSUP, ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION },\n\t{ ANIM_STD_HANDSCOWER, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION },\n\t{ ANIM_STD_PARTIAL_FUCKU, ASSOC_DELETEFADEDOUT | ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_NOWALK },\n\t{ ANIM_STD_PHONE_IN, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_PHONE_OUT, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_PHONE_TALK, ASSOC_REPEAT | ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL },\n\t{ ANIM_STD_SEAT_DOWN, ASSOC_DELETEFADEDOUT | ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_SEAT_UP, ASSOC_DELETEFADEDOUT | ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_SEAT_IDLE, ASSOC_REPEAT | ASSOC_DELETEFADEDOUT | ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_SEAT_RVRS, ASSOC_DELETEFADEDOUT | ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_ATM, ASSOC_DELETEFADEDOUT | ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_ABSEIL, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL },\n};\nAnimAssocDesc aVanAnimDescs[] = {\n\t{ ANIM_STD_VAN_OPEN_DOOR_REAR_LHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_VAN_GET_IN_REAR_LHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_VAN_CLOSE_DOOR_REAR_LHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_VAN_GET_OUT_REAR_LHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_VAN_OPEN_DOOR_REAR_RHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_VAN_GET_IN_REAR_RHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_VAN_CLOSE_DOOR_REAR_RHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_VAN_GET_OUT_REAR_RHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n};\nAnimAssocDesc aCoachAnimDescs[] = {\n\t{ ANIM_STD_COACH_OPEN_LHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_COACH_OPEN_RHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_COACH_GET_IN_LHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_COACH_GET_IN_RHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STD_COACH_GET_OUT_LHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n};\nAnimAssocDesc aBikeAnimDescs[] = {\n\t{ ANIM_BIKE_RIDE, ASSOC_DELETEFADEDOUT},\n\t{ ANIM_BIKE_READY, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_DRIVING },\n\t{ ANIM_BIKE_LEFT, ASSOC_PARTIAL | ASSOC_DRIVING },\n\t{ ANIM_BIKE_RIGHT, ASSOC_PARTIAL | ASSOC_DRIVING },\n\t{ ANIM_BIKE_LEANB, ASSOC_PARTIAL | ASSOC_DRIVING },\n\t{ ANIM_BIKE_LEANF, ASSOC_PARTIAL | ASSOC_DRIVING },\n\t{ ANIM_BIKE_WALKBACK, ASSOC_REPEAT | ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_DRIVING },\n\t{ ANIM_BIKE_JUMPON_LHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_BIKE_JUMPON_RHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_BIKE_KICK, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_BIKE_HIT, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_BIKE_GETOFF_LHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_BIKE_GETOFF_RHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_BIKE_GETOFF_BACK, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION },\n\t{ ANIM_BIKE_DRIVEBY_LHS, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_DRIVING },\n\t{ ANIM_BIKE_DRIVEBY_RHS, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_DRIVING },\n\t{ ANIM_BIKE_DRIVEBY_FORWARD, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_DRIVING },\n\t{ ANIM_BIKE_RIDE_P, ASSOC_DELETEFADEDOUT | ASSOC_DRIVING },\n};\nAnimAssocDesc aMeleeAnimDescs[] = {\n\t{ ANIM_MELEE_ATTACK, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_MELEE_ATTACK_2ND, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_MELEE_ATTACK_START, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_NOWALK },\n\t{ ANIM_MELEE_IDLE_FIGHTMODE, ASSOC_REPEAT },\n\t{ ANIM_MELEE_ATTACK_FINISH, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION },\n};\nAnimAssocDesc aSwingAnimDescs[] = {\n\t{ ANIM_MELEE_ATTACK, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_MELEE_ATTACK_2ND, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_MELEE_ATTACK_START, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_MELEE_IDLE_FIGHTMODE, ASSOC_REPEAT },\n\t{ ANIM_MELEE_ATTACK_FINISH, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n};\nAnimAssocDesc aWeaponAnimDescs[] = {\n\t{ ANIM_WEAPON_FIRE, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_WEAPON_CROUCHFIRE, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_WEAPON_RELOAD, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_WEAPON_CROUCHRELOAD, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_WEAPON_FIRE_3RD, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n};\nAnimAssocDesc aMedicAnimDescs[] = {\n\t{ ANIM_MEDIC_CPR, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n};\nAnimAssocDesc aSunbatheAnimDescs[] = {\n\t{ ANIM_SUNBATHE_IDLE, ASSOC_REPEAT | ASSOC_PARTIAL },\n\t{ ANIM_SUNBATHE_DOWN, ASSOC_REPEAT | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION | ASSOC_HAS_X_TRANSLATION },\n\t{ ANIM_SUNBATHE_UP, ASSOC_REPEAT | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION | ASSOC_HAS_X_TRANSLATION },\n\t{ ANIM_SUNBATHE_ESCAPE, ASSOC_REPEAT | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION | ASSOC_HAS_X_TRANSLATION },\n};\nAnimAssocDesc aPlayerIdleAnimDescs[] = {\n\t{ ANIM_PLAYER_IDLE1, ASSOC_DELETEFADEDOUT | ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_PLAYER_IDLE2, ASSOC_DELETEFADEDOUT | ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_PLAYER_IDLE3, ASSOC_DELETEFADEDOUT | ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_PLAYER_IDLE4, ASSOC_DELETEFADEDOUT | ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n};\nAnimAssocDesc aRiotAnimDescs[] = {\n\t{ ANIM_RIOT_ANGRY, ASSOC_REPEAT | ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_RIOT_ANGRY_B, ASSOC_REPEAT | ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_RIOT_CHANT, ASSOC_REPEAT | ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_RIOT_PUNCHES, ASSOC_REPEAT | ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_RIOT_SHOUT, ASSOC_REPEAT | ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_RIOT_CHALLENGE, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_RIOT_FUCKYOU, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n};\nAnimAssocDesc aStripAnimDescs[] = {\n\t{ ANIM_STRIP_A, ASSOC_REPEAT | ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STRIP_B, ASSOC_REPEAT | ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STRIP_C, ASSOC_REPEAT | ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STRIP_D, ASSOC_REPEAT | ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STRIP_E, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STRIP_F, ASSOC_REPEAT | ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n\t{ ANIM_STRIP_G, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },\n};\n#ifdef PC_PLAYER_CONTROLS\nAnimAssocDesc aStdAnimDescsSide[] = {\n\t{ ANIM_STD_WALK, ASSOC_REPEAT | ASSOC_MOVEMENT | ASSOC_HAS_TRANSLATION | ASSOC_HAS_X_TRANSLATION | ASSOC_WALK },\n\t{ ANIM_STD_RUN, ASSOC_REPEAT | ASSOC_MOVEMENT | ASSOC_HAS_TRANSLATION | ASSOC_HAS_X_TRANSLATION | ASSOC_WALK },\n\t{ ANIM_STD_RUNFAST, ASSOC_REPEAT | ASSOC_MOVEMENT | ASSOC_HAS_TRANSLATION | ASSOC_HAS_X_TRANSLATION | ASSOC_WALK },\n\t{ ANIM_STD_IDLE, ASSOC_REPEAT },\n\t{ ANIM_STD_STARTWALK, ASSOC_HAS_TRANSLATION | ASSOC_HAS_X_TRANSLATION },\n};\n#endif\nchar const* aStdAnimations[] = {\n\t\"walk_civi\",\n\t\"run_civi\",\n\t\"sprint_panic\",\n\t\"idle_stance\",\n\t\"walk_start\",\n\t\"run_stop\",\n\t\"run_stopR\",\n\t\"idle_hbhb\",\n\t\"idle_hbhb\",\n\t\"idle_tired\",\n\t\"idle_armed\",\n\t\"idle_chat\",\n\t\"idle_taxi\",\n\t\"KO_shot_front\",\n\t\"KO_shot_front\",\n\t\"KO_shot_front\",\n\t\"KO_shot_front\",\n\t\"KO_shot_face\",\n\t\"KO_shot_stom\",\n\t\"KO_shot_arml\",\n\t\"KO_shot_armR\",\n\t\"KO_shot_legl\",\n\t\"KO_shot_legR\",\n\t\"KD_left\",\n\t\"KD_right\",\n\t\"KO_skid_front\",\n\t\"KO_spin_R\",\n\t\"KO_skid_back\",\n\t\"KO_spin_L\",\n\t\"SHOT_partial\",\n\t\"SHOT_leftP\",\n\t\"SHOT_partial\",\n\t\"SHOT_rightP\",\n\t\"HIT_front\",\n\t\"HIT_L\",\n\t\"HIT_back\",\n\t\"HIT_R\",\n\t\"FLOOR_hit\",\n\t\"HIT_bodyblow\",\n\t\"HIT_chest\",\n\t\"HIT_head\",\n\t\"HIT_walk\",\n\t\"HIT_wall\",\n\t\"FLOOR_hit_f\",\n\t\"HIT_behind\",\n\t\"FIGHTIDLE\",\n\t\"FIGHT2IDLE\",\n\t\"FIGHTsh_F\",\n\t\"FIGHTbodyblow\",\n\t\"FIGHThead\",\n\t\"FIGHTkick\",\n\t\"FIGHTknee\",\n\t\"FIGHTLhook\",\n\t\"FIGHTpunch\",\n\t\"FIGHTrndhse\",\n\t\"FIGHTlngkck\",\n\t\"FIGHTppunch\",\n\t\"FIGHTjab\",\n\t\"FIGHTelbowL\",\n\t\"FIGHTelbowR\",\n\t\"FIGHTbkickL\",\n\t\"FIGHTbkickR\",\n\t\"bomber\",\n\t\"punchR\",\n\t\"FIGHTppunch\",\n\t\"KICK_floor\",\n\t\"WEAPON_throwu\",\n\t\"FIGHTsh_back\",\n\t\"car_jackedRHS\",\n\t\"car_LjackedRHS\",\n\t\"car_jackedLHS\",\n\t\"car_LjackedLHS\",\n\t\"CAR_Qjack\",\n\t\"CAR_Qjacked\",\n\t\"CAR_align_LHS\",\n\t\"CAR_alignHI_LHS\",\n\t\"CAR_open_LHS\",\n\t\"CAR_doorlocked_LHS\",\n\t\"CAR_pullout_LHS\",\n\t\"CAR_pulloutL_LHS\",\n\t\"CAR_getin_LHS\",\n\t\"CAR_getinL_LHS\",\n\t\"CAR_closedoor_LHS\",\n\t\"CAR_closedoorL_LHS\",\n\t\"CAR_rolldoor\",\n\t\"CAR_rolldoorLO\",\n\t\"CAR_jumpin_LHS\",\n\t\"CAR_getout_LHS\",\n\t\"CAR_getoutL_LHS\",\n\t\"CAR_close_LHS\",\n\t\"CAR_align_RHS\",\n\t\"CAR_alignHI_RHS\",\n\t\"CAR_open_RHS\",\n\t\"CAR_doorlocked_RHS\",\n\t\"CAR_pullout_RHS\",\n\t\"CAR_pulloutL_RHS\",\n\t\"CAR_getin_RHS\",\n\t\"CAR_getinL_RHS\",\n\t\"CAR_closedoor_RHS\",\n\t\"CAR_closedoorL_RHS\",\n\t\"CAR_shuffle_RHS\",\n\t\"CAR_Lshuffle_RHS\",\n\t\"CAR_sit\",\n\t\"CAR_Lsit\",\n\t\"CAR_sitp\",\n\t\"CAR_sitpLO\",\n\t\"DRIVE_L\",\n\t\"Drive_R\",\n\t\"Drive_LO_l\",\n\t\"Drive_LO_R\",\n\t\"Driveby_L\",\n\t\"Driveby_R\",\n\t\"DrivebyL_L\",\n\t\"DrivebyL_R\",\n\t\"CAR_LB\",\n\t\"DRIVE_BOAT\",\n\t\"DRIVE_BOAT_L\",\n\t\"DRIVE_BOAT_R\",\n\t\"DRIVE_BOAT_back\",\n\t\"BIKE_pickupR\",\n\t\"BIKE_pickupL\",\n\t\"BIKE_pullupR\",\n\t\"BIKE_pullupL\",\n\t\"BIKE_elbowR\",\n\t\"BIKE_elbowL\",\n\t\"BIKE_fall_off\",\n\t\"BIKE_fallR\",\n\t\"CAR_getout_RHS\",\n\t\"CAR_getoutL_RHS\",\n\t\"CAR_close_RHS\",\n\t\"car_hookertalk\",\n\t\"idle_stance\",\n\t\"idle_stance\",\n\t\"CAR_crawloutRHS\",\n\t\"CAR_crawloutRHS\",\n\t\"CAR_rollout_LHS\",\n\t\"CAR_rollout_LHS\",\n\t\"Getup\",\n\t\"Getup\",\n\t\"Getup\",\n\t\"Getup_front\",\n\t\"JUMP_launch\",\n\t\"JUMP_glide\",\n\t\"JUMP_land\",\n\t\"FALL_fall\",\n\t\"FALL_glide\",\n\t\"FALL_land\",\n\t\"FALL_collapse\",\n\t\"FALL_back\",\n\t\"FALL_front\",\n\t\"EV_step\",\n\t\"EV_dive\",\n\t\"XPRESSscratch\",\n\t\"roadcross\",\n\t\"TURN_180\",\n\t\"ARRESTgun\",\n\t\"DROWN\",\n\t\"DUCK_down\",\n\t\"DUCK_low\",\n\t\"WEAPON_crouch\",\n\t\"RBLOCK_Cshoot\",\n\t\"handsup\",\n\t\"handsCOWER\",\n\t\"FUCKU\",\n\t\"PHONE_in\",\n\t\"PHONE_out\",\n\t\"PHONE_talk\",\n\t\"SEAT_down\",\n\t\"SEAT_up\",\n\t\"SEAT_idle\",\n\t\"SEAT_down\",\n\t\"ATM\",\n\t\"abseil\",\n};\nchar const* aVanAnimations[] = {\n\t\"VAN_openL\",\n\t\"VAN_getinL\",\n\t\"VAN_closeL\",\n\t\"VAN_getoutL\",\n\t\"VAN_open\",\n\t\"VAN_getin\",\n\t\"VAN_close\",\n\t\"VAN_getout\",\n};\nchar const* aCoachAnimations[] = {\n\t\"COACH_opnL\",\n\t\"COACH_opnL\",\n\t\"COACH_inL\",\n\t\"COACH_inL\",\n\t\"COACH_outL\",\n};\nchar const* aBikesAnimations[] = {\n\t\"BIKEs_Ride\",\n\t\"BIKEs_Still\",\n\t\"BIKEs_Left\",\n\t\"BIKEs_Right\",\n\t\"BIKEs_Back\",\n\t\"BIKEs_Fwd\",\n\t\"BIKEs_pushes\",\n\t\"BIKEs_jumponR\",\n\t\"BIKEs_jumponL\",\n\t\"BIKEs_kick\",\n\t\"BIKEs_hit\",\n\t\"BIKEs_getoffRHS\",\n\t\"BIKEs_getoffLHS\",\n\t\"BIKEs_getoffBACK\",\n\t\"BIKEs_drivebyLHS\",\n\t\"BIKEs_drivebyRHS\",\n\t\"BIKEs_drivebyFT\",\n\t\"BIKEs_passenger\",\n};\nchar const* aBikevAnimations[] = {\n\t\"BIKEv_Ride\",\n\t\"BIKEv_Still\",\n\t\"BIKEv_Left\",\n\t\"BIKEv_Right\",\n\t\"BIKEv_Back\",\n\t\"BIKEv_Fwd\",\n\t\"BIKEv_pushes\",\n\t\"BIKEv_jumponR\",\n\t\"BIKEv_jumponL\",\n\t\"BIKEv_kick\",\n\t\"BIKEv_hit\",\n\t\"BIKEv_getoffRHS\",\n\t\"BIKEv_getoffLHS\",\n\t\"BIKEv_getoffBACK\",\n\t\"BIKEv_drivebyLHS\",\n\t\"BIKEv_drivebyRHS\",\n\t\"BIKEv_drivebyFT\",\n\t\"BIKEv_passenger\",\n};\nchar const* aBikehAnimations[] = {\n\t\"BIKEh_Ride\",\n\t\"BIKEh_Still\",\n\t\"BIKEh_Left\",\n\t\"BIKEh_Right\",\n\t\"BIKEh_Back\",\n\t\"BIKEh_Fwd\",\n\t\"BIKEh_pushes\",\n\t\"BIKEh_jumponR\",\n\t\"BIKEh_jumponL\",\n\t\"BIKEh_kick\",\n\t\"BIKEh_hit\",\n\t\"BIKEh_getoffRHS\",\n\t\"BIKEh_getoffLHS\",\n\t\"BIKEh_getoffBACK\",\n\t\"BIKEh_drivebyLHS\",\n\t\"BIKEh_drivebyRHS\",\n\t\"BIKEh_drivebyFT\",\n\t\"BIKEh_passenger\",\n};\nchar const* aBikedAnimations[] = {\n\t\"BIKEd_Ride\",\n\t\"BIKEd_Still\",\n\t\"BIKEd_Left\",\n\t\"BIKEd_Right\",\n\t\"BIKEd_Back\",\n\t\"BIKEd_Fwd\",\n\t\"BIKEd_pushes\",\n\t\"BIKEd_jumponR\",\n\t\"BIKEd_jumponL\",\n\t\"BIKEd_kick\",\n\t\"BIKEd_hit\",\n\t\"BIKEd_getoffRHS\",\n\t\"BIKEd_getoffLHS\",\n\t\"BIKEd_getoffBACK\",\n\t\"BIKEd_drivebyLHS\",\n\t\"BIKEd_drivebyRHS\",\n\t\"BIKEd_drivebyFT\",\n\t\"BIKEd_passenger\",\n};\nchar const* aUnarmedAnimations[] = {\n\t\"punchR\",\n\t\"KICK_floor\",\n\t\"FIGHTppunch\",\n};\nchar const* aScrewdriverAnimations[] = {\n\t\"FIGHTbodyblow\",\n\t\"FIGHTbodyblow\",\n\t\"FIGHTppunch\",\n\t\"FIGHTIDLE\",\n\t\"FIGHTbodyblow\",\n};\nchar const* aKnifeAnimations[] = {\n\t\"WEAPON_knife_1\",\n\t\"WEAPON_knife_2\",\n\t\"knife_part\",\n\t\"WEAPON_knifeidle\",\n\t\"WEAPON_knife_3\",\n};\nchar const* aBaseballbatAnimations[] = {\n\t\"WEAPON_bat_h\",\n\t\"WEAPON_bat_v\",\n\t\"BAT_PART\",\n\t\"WEAPON_bat_h\",\n\t\"WEAPON_golfclub\",\n};\nchar const* aGolfclubAnimations[] = {\n\t\"WEAPON_bat_h\",\n\t\"WEAPON_golfclub\",\n\t\"BAT_PART\",\n\t\"WEAPON_bat_h\",\n\t\"WEAPON_bat_v\",\n};\nchar const* aChainsawAnimations[] = {\n\t\"WEAPON_csaw\",\n\t\"WEAPON_csawlo\",\n\t\"csaw_part\",\n};\nchar const* aPythonAnimations[] = {\n\t\"python_fire\",\n\t\"python_crouchfire\",\n\t\"python_reload\",\n\t\"python_crouchreload\",\n};\nchar const* aColtAnimations[] = {\n\t\"colt45_fire\",\n\t\"colt45_crouchfire\",\n\t\"colt45_reload\",\n\t\"colt45_crouchreload\",\n\t\"colt45_cop\",\n};\nchar const* aShotgunAnimations[] = {\n\t\"shotgun_fire\",\n\t\"shotgun_crouchfire\",\n};\nchar const* aBuddyAnimations[] = {\n\t\"buddy_fire\",\n\t\"buddy_crouchfire\",\n};\nchar const* aTecAnimations[] = {\n\t\"TEC_fire\",\n\t\"TEC_crouchfire\",\n\t\"TEC_reload\",\n\t\"TEC_crouchreload\",\n};\nchar const* aUziAnimations[] = {\n\t\"UZI_fire\",\n\t\"UZI_crouchfire\",\n\t\"UZI_reload\",\n\t\"UZI_crouchreload\",\n};\nchar const* aRifleAnimations[] = {\n\t\"RIFLE_fire\",\n\t\"RIFLE_crouchfire\",\n\t\"RIFLE_load\",\n\t\"RIFLE_crouchload\",\n};\nchar const* aM60Animations[] = {\n\t\"M60_fire\",\n\t\"M60_fire\",\n\t\"M60_reload\",\n};\nchar const* aSniperAnimations[] = {\n\t\"WEAPON_sniper\",\n};\nchar const* aThrowAnimations[] = {\n\t\"WEAPON_throw\",\n\t\"WEAPON_throwu\",\n\t\"WEAPON_start_throw\",\n};\nchar const* aFlamethrowerAnimations[] = {\n\t\"FLAME_fire\",\n};\nchar const* aMedicAnimations[] = {\n\t\"CPR\",\n};\nchar const* aSunbatheAnimations[] = {\n\t\"bather\",\n\t\"batherdown\",\n\t\"batherup\",\n\t\"batherscape\",\n};\nchar const* aPlayerIdleAnimations[] = {\n\t\"stretch\",\n\t\"time\",\n\t\"shldr\",\n\t\"strleg\",\n};\nchar const* aRiotAnimations[] = {\n\t\"riot_angry\",\n\t\"riot_angry_b\",\n\t\"riot_chant\",\n\t\"riot_punches\",\n\t\"riot_shout\",\n\t\"riot_challenge\",\n\t\"riot_fuku\",\n};\nchar const* aStripAnimations[] = {\n\t\"strip_A\",\n\t\"strip_B\",\n\t\"strip_C\",\n\t\"strip_D\",\n\t\"strip_E\",\n\t\"strip_F\",\n\t\"strip_G\",\n};\nchar const* aLanceAnimations[] = {\n\t\"lance\",\n};\nchar const* aPlayerAnimations[] = {\n\t\"walk_player\",\n\t\"run_player\",\n\t\"SPRINT_civi\",\n\t\"IDLE_STANCE\",\n\t\"walk_start\",\n};\nchar const* aPlayerWithRocketAnimations[] = {\n\t\"walk_rocket\",\n\t\"run_rocket\",\n\t\"run_rocket\",\n\t\"idle_rocket\",\n\t\"walk_start_rocket\",\n};\nchar const* aPlayer1ArmedAnimations[] = {\n\t\"walk_player\",\n\t\"run_1armed\",\n\t\"SPRINT_civi\",\n\t\"IDLE_STANCE\",\n\t\"walk_start\",\n};\nchar const* aPlayer2ArmedAnimations[] = {\n\t\"walk_armed\",\n\t\"run_armed\",\n\t\"run_armed\",\n\t\"idle_armed\",\n\t\"walk_start_armed\",\n};\nchar const* aPlayerBBBatAnimations[] = {\n\t\"walk_player\",\n\t\"run_player\",\n\t\"run_player\",\n\t\"IDLE_STANCE\",\n\t\"walk_start\",\n};\nchar const* aPlayerChainsawAnimations[] = {\n\t\"walk_csaw\",\n\t\"run_csaw\",\n\t\"run_csaw\",\n\t\"IDLE_csaw\",\n\t\"walk_start_csaw\",\n};\nchar const* aShuffleAnimations[] = {\n\t\"WALK_shuffle\",\n\t\"RUN_civi\",\n\t\"SPRINT_civi\",\n\t\"IDLE_STANCE\",\n};\nchar const* aOldAnimations[] = {\n\t\"walk_old\",\n\t\"run_civi\",\n\t\"sprint_civi\",\n\t\"idle_stance\",\n};\nchar const* aGang1Animations[] = {\n\t\"walk_gang1\",\n\t\"run_gang1\",\n\t\"sprint_civi\",\n\t\"idle_stance\",\n};\nchar const* aGang2Animations[] = {\n\t\"walk_gang2\",\n\t\"run_gang1\",\n\t\"sprint_civi\",\n\t\"idle_stance\",\n};\nchar const* aFatAnimations[] = {\n\t\"walk_fat\",\n\t\"run_civi\",\n\t\"woman_runpanic\",\n\t\"idle_stance\",\n};\nchar const* aOldFatAnimations[] = {\n\t\"walk_fatold\",\n\t\"run_fatold\",\n\t\"woman_runpanic\",\n\t\"idle_stance\",\n};\nchar const* aJoggerAnimations[] = {\n\t\"JOG_maleA\",\n\t\"run_civi\",\n\t\"sprint_civi\",\n\t\"idle_stance\",\n};\nchar const* aStdWomanAnimations[] = {\n\t\"woman_walknorm\",\n\t\"woman_run\",\n\t\"woman_runpanic\",\n\t\"woman_idlestance\",\n};\nchar const* aWomanShopAnimations[] = {\n\t\"woman_walkshop\",\n\t\"woman_run\",\n\t\"woman_run\",\n\t\"woman_idlestance\",\n};\nchar const* aBusyWomanAnimations[] = {\n\t\"woman_walkbusy\",\n\t\"woman_run\",\n\t\"woman_runpanic\",\n\t\"woman_idlestance\",\n};\nchar const* aSexyWomanAnimations[] = {\n\t\"woman_walksexy\",\n\t\"woman_run\",\n\t\"woman_runpanic\",\n\t\"woman_idlestance\",\n};\nchar const* aFatWomanAnimations[] = {\n\t\"walk_fat\",\n\t\"woman_run\",\n\t\"woman_runpanic\",\n\t\"woman_idlestance\",\n};\nchar const* aOldWomanAnimations[] = {\n\t\"woman_walkold\",\n\t\"woman_run\",\n\t\"woman_runpanic\",\n\t\"woman_idlestance\",\n};\nchar const* aJoggerWomanAnimations[] = {\n\t\"JOG_maleB\",\n\t\"woman_run\",\n\t\"woman_runpanic\",\n\t\"woman_idlestance\",\n};\nchar const* aPanicChunkyAnimations[] = {\n\t\"run_fatold\",\n\t\"woman_runpanic\",\n\t\"woman_runpanic\",\n\t\"idle_stance\",\n};\nchar const* aSkateAnimations[] = {\n\t\"skate_run\",\n\t\"skate_sprint\",\n\t\"skate_sprint\",\n\t\"skate_idle\",\n};\n#ifdef PC_PLAYER_CONTROLS\nchar const* aPlayerStrafeBackAnimations[] = {\n\t\"walk_back\",\n\t\"run_back\",\n\t\"run_back\",\n\t\"IDLE_STANCE\",\n\t\"walk_start_back\",\n};\nchar const* aPlayerStrafeLeftAnimations[] = {\n\t\"walk_left\",\n\t\"run_left\",\n\t\"run_left\",\n\t\"IDLE_STANCE\",\n\t\"walk_start_left\",\n};\nchar const* aPlayerStrafeRightAnimations[] = {\n\t\"walk_right\",\n\t\"run_right\",\n\t\"run_right\",\n\t\"IDLE_STANCE\",\n\t\"walk_start_right\",\n};\nchar const* aRocketStrafeBackAnimations[] = {\n\t\"walk_rocket_back\",\n\t\"run_rocket_back\",\n\t\"run_rocket_back\",\n\t\"idle_rocket\",\n\t\"walkst_rocket_back\",\n};\nchar const* aRocketStrafeLeftAnimations[] = {\n\t\"walk_rocket_left\",\n\t\"run_rocket_left\",\n\t\"run_rocket_left\",\n\t\"idle_rocket\",\n\t\"walkst_rocket_left\",\n};\nchar const* aRocketStrafeRightAnimations[] = {\n\t\"walk_rocket_right\",\n\t\"run_rocket_right\",\n\t\"run_rocket_right\",\n\t\"idle_rocket\",\n\t\"walkst_rocket_right\",\n};\nchar const* aChainsawStrafeBackAnimations[] = {\n\t\"walk_csaw_back\",\n\t\"run_csaw_back\",\n\t\"run_csaw_back\",\n\t\"idle_csaw\",\n\t\"walkst_csaw_back\",\n};\nchar const* aChainsawStrafeLeftAnimations[] = {\n\t\"walk_csaw_left\",\n\t\"run_csaw_left\",\n\t\"run_csaw_left\",\n\t\"idle_csaw\",\n\t\"walkst_csaw_left\",\n};\nchar const* aChainsawStrafeRightAnimations[] = {\n\t\"walk_csaw_right\",\n\t\"run_csaw_right\",\n\t\"run_csaw_right\",\n\t\"idle_csaw\",\n\t\"walkst_csaw_right\",\n};\n#endif\n\n#define awc(a) ARRAY_SIZE(a), a\nconst AnimAssocDefinition CAnimManager::ms_aAnimAssocDefinitions[NUM_ANIM_ASSOC_GROUPS] = {\n\t{ \"man\", \"ped\", MI_COP, awc(aStdAnimations), aStdAnimDescs },\n\t{ \"van\", \"van\", MI_COP, awc(aVanAnimations), aVanAnimDescs },\n\t{ \"coach\", \"coach\", MI_COP, awc(aCoachAnimations), aCoachAnimDescs },\n\t{ \"bikes\", \"bikes\", MI_COP, awc(aBikesAnimations), aBikeAnimDescs },\n\t{ \"bikev\", \"bikev\", MI_COP, awc(aBikevAnimations), aBikeAnimDescs },\n\t{ \"bikeh\", \"bikeh\", MI_COP, awc(aBikehAnimations), aBikeAnimDescs },\n\t{ \"biked\", \"biked\", MI_COP, awc(aBikedAnimations), aBikeAnimDescs },\n\t{ \"unarmed\", \"ped\", MI_COP, awc(aUnarmedAnimations), aMeleeAnimDescs },\n\t{ \"screwdrv\", \"ped\", MI_COP, awc(aScrewdriverAnimations), aMeleeAnimDescs },\n\t{ \"knife\", \"knife\", MI_COP, awc(aKnifeAnimations), aMeleeAnimDescs },\n\t{ \"baseball\", \"baseball\", MI_COP, awc(aBaseballbatAnimations), aSwingAnimDescs },\n\t{ \"golfclub\", \"baseball\", MI_COP, awc(aGolfclubAnimations), aSwingAnimDescs },\n\t{ \"chainsaw\", \"chainsaw\", MI_COP, awc(aChainsawAnimations), aMeleeAnimDescs },\n\t{ \"python\", \"python\", MI_COP, awc(aPythonAnimations), aWeaponAnimDescs },\n\t{ \"colt45\", \"colt45\", MI_COP, awc(aColtAnimations), aWeaponAnimDescs },\n\t{ \"shotgun\", \"shotgun\", MI_COP, awc(aShotgunAnimations), aWeaponAnimDescs },\n\t{ \"buddy\", \"buddy\", MI_COP, awc(aBuddyAnimations), aWeaponAnimDescs },\n\t{ \"tec\", \"tec\", MI_COP, awc(aTecAnimations), aWeaponAnimDescs },\n\t{ \"uzi\", \"uzi\", MI_COP, awc(aUziAnimations), aWeaponAnimDescs },\n\t{ \"rifle\", \"rifle\", MI_COP, awc(aRifleAnimations), aWeaponAnimDescs },\n\t{ \"m60\", \"m60\", MI_COP, awc(aM60Animations), aWeaponAnimDescs },\n\t{ \"sniper\", \"sniper\", MI_COP, awc(aSniperAnimations), aWeaponAnimDescs },\n\t{ \"grenade\", \"grenade\", MI_COP, awc(aThrowAnimations), aWeaponAnimDescs },\n\t{ \"flame\", \"flame\", MI_COP, awc(aFlamethrowerAnimations), aWeaponAnimDescs },\n\t{ \"medic\", \"medic\", MI_COP, awc(aMedicAnimations), aMedicAnimDescs },\n\t{ \"sunbathe\", \"sunbathe\", MI_COP, 1, aSunbatheAnimations, aSunbatheAnimDescs },\t// NB: not using awc here!\n\t{ \"playidles\", \"playidles\", MI_COP, awc(aPlayerIdleAnimations), aPlayerIdleAnimDescs },\n\t{ \"riot\", \"riot\", MI_COP, awc(aRiotAnimations), aRiotAnimDescs },\n\t{ \"strip\", \"strip\", MI_COP, awc(aStripAnimations), aStripAnimDescs },\n\t{ \"lance\", \"lance\", MI_COP, awc(aLanceAnimations), aSunbatheAnimDescs },\n\t{ \"player\", \"ped\", MI_COP, awc(aPlayerAnimations), aStdAnimDescs },\n\t{ \"playerrocket\", \"ped\", MI_COP, awc(aPlayerWithRocketAnimations), aStdAnimDescs },\n\t{ \"player1armed\", \"ped\", MI_COP, awc(aPlayer1ArmedAnimations), aStdAnimDescs },\n\t{ \"player2armed\", \"ped\", MI_COP, awc(aPlayer2ArmedAnimations), aStdAnimDescs },\n\t{ \"playerBBBat\", \"ped\", MI_COP, awc(aPlayerBBBatAnimations), aStdAnimDescs },\n\t{ \"playercsaw\", \"ped\", MI_COP, awc(aPlayerChainsawAnimations), aStdAnimDescs },\n\t{ \"shuffle\", \"ped\", MI_COP, awc(aShuffleAnimations), aStdAnimDescs },\n\t{ \"oldman\", \"ped\", MI_COP, awc(aOldAnimations), aStdAnimDescs },\n\t{ \"gang1\", \"ped\", MI_COP, awc(aGang1Animations), aStdAnimDescs },\n\t{ \"gang2\", \"ped\", MI_COP, awc(aGang2Animations), aStdAnimDescs },\n\t{ \"fatman\", \"ped\", MI_COP, awc(aFatAnimations), aStdAnimDescs },\n\t{ \"oldfatman\", \"ped\", MI_COP, awc(aOldFatAnimations), aStdAnimDescs },\n\t{ \"jogger\", \"ped\", MI_COP, awc(aJoggerAnimations), aStdAnimDescs },\n\t{ \"woman\", \"ped\", MI_COP, awc(aStdWomanAnimations), aStdAnimDescs },\n\t{ \"shopping\", \"ped\", MI_COP, awc(aWomanShopAnimations), aStdAnimDescs },\n\t{ \"busywoman\", \"ped\", MI_COP, awc(aBusyWomanAnimations), aStdAnimDescs },\n\t{ \"sexywoman\", \"ped\", MI_COP, awc(aSexyWomanAnimations), aStdAnimDescs },\n\t{ \"fatwoman\", \"ped\", MI_COP, awc(aFatWomanAnimations), aStdAnimDescs },\n\t{ \"oldwoman\", \"ped\", MI_COP, awc(aOldWomanAnimations), aStdAnimDescs },\n\t{ \"jogwoman\", \"ped\", MI_COP, awc(aJoggerWomanAnimations), aStdAnimDescs },\n\t{ \"panicchunky\", \"ped\", MI_COP, awc(aPanicChunkyAnimations), aStdAnimDescs },\n\t{ \"skate\", \"skate\", MI_COP, awc(aSkateAnimations), aStdAnimDescs },\n#ifdef PC_PLAYER_CONTROLS\n\t{ \"playerback\", \"ped\", MI_COP, awc(aPlayerStrafeBackAnimations), aStdAnimDescs },\n\t{ \"playerleft\", \"ped\", MI_COP, awc(aPlayerStrafeLeftAnimations), aStdAnimDescsSide },\n\t{ \"playerright\", \"ped\", MI_COP, awc(aPlayerStrafeRightAnimations), aStdAnimDescsSide },\n\t{ \"rocketback\", \"ped\", MI_COP, awc(aRocketStrafeBackAnimations), aStdAnimDescs },\n\t{ \"rocketleft\", \"ped\", MI_COP, awc(aRocketStrafeLeftAnimations), aStdAnimDescsSide },\n\t{ \"rocketright\", \"ped\", MI_COP, awc(aRocketStrafeRightAnimations), aStdAnimDescsSide },\n\t{ \"csawback\", \"ped\", MI_COP, awc(aChainsawStrafeBackAnimations), aStdAnimDescs },\n\t{ \"csawleft\", \"ped\", MI_COP, awc(aChainsawStrafeLeftAnimations), aStdAnimDescsSide },\n\t{ \"csawright\", \"ped\", MI_COP, awc(aChainsawStrafeRightAnimations), aStdAnimDescsSide },\n#endif\n};\n#undef awc\n\nvoid\nCAnimManager::Initialise(void)\n{\n\tms_numAnimations = 0;\n\tms_numAnimBlocks = 0;\n\tms_animCache.Init(25);\n}\n\nvoid\nCAnimManager::Shutdown(void)\n{\n\tint i;\n\n\tfor(i = 0; i < NUMANIMBLOCKS; i++)\n\t\tCStreaming::RemoveAnim(i);\n\n\tfor(i = 0; i < ms_numAnimations; i++)\n\t\tms_aAnimations[i].Shutdown();\n\n\tms_animCache.Shutdown();\n\n\tdelete[] ms_aAnimAssocGroups;\n}\n\nvoid\nCAnimManager::UncompressAnimation(CAnimBlendHierarchy *hier)\n{\n\tif(hier->keepCompressed){\n\t\tif(hier->totalLength == 0.0f)\n\t\t\thier->CalcTotalTimeCompressed();\n\t}else{\n\t\tif(!hier->compressed){\n\t\t\tif(hier->linkPtr){\n\t\t\t\thier->linkPtr->Remove();\n\t\t\t\tms_animCache.head.Insert(hier->linkPtr);\n\t\t\t}\n\t\t}else{\n\t\t\tCLink<CAnimBlendHierarchy*> *link = ms_animCache.Insert(hier);\n\t\t\tif(link == nil){\n\t\t\t\tCAnimBlendHierarchy *lastHier = ms_animCache.tail.prev->item;\n\t\t\t\tlastHier->RemoveUncompressedData();\n\t\t\t\tms_animCache.Remove(ms_animCache.tail.prev);\n\t\t\t\tlastHier->linkPtr = nil;\n\t\t\t\tlink = ms_animCache.Insert(hier);\n\t\t\t}\n\t\t\thier->linkPtr = link;\n\t\t\thier->Uncompress();\n\t\t}\n\t}\n}\n\nvoid\nCAnimManager::RemoveFromUncompressedCache(CAnimBlendHierarchy *hier)\n{\n\tif(hier->linkPtr){\n\t\tms_animCache.Remove(hier->linkPtr);\n\t\thier->linkPtr = nil;\n\t}\n}\n\nCAnimBlock*\nCAnimManager::GetAnimationBlock(const char *name)\n{\n\tint i;\n\n\tfor(i = 0; i < ms_numAnimBlocks; i++)\n\t\tif(strcasecmp(ms_aAnimBlocks[i].name, name) == 0)\n\t\t\treturn &ms_aAnimBlocks[i];\n\treturn nil;\n}\n\nint32\nCAnimManager::GetAnimationBlockIndex(const char *name)\n{\n\tint i;\n\n\tfor(i = 0; i < ms_numAnimBlocks; i++)\n\t\tif(strcasecmp(ms_aAnimBlocks[i].name, name) == 0)\n\t\t\treturn i;\n\treturn -1;\n}\n\nint32\nCAnimManager::RegisterAnimBlock(const char *name)\n{\n\tCAnimBlock *animBlock = GetAnimationBlock(name);\n\tif(animBlock == nil){\n\t\tanimBlock = &ms_aAnimBlocks[ms_numAnimBlocks++];\n\t\tstrncpy(animBlock->name, name, MAX_ANIMBLOCK_NAME);\n\t\tanimBlock->numAnims = 0;\n\t\tassert(animBlock->refCount == 0);\n\t}\n\treturn animBlock - ms_aAnimBlocks;\n}\n\nint32\nCAnimManager::GetNumRefsToAnimBlock(int32 block)\n{\n\treturn ms_aAnimBlocks[block].refCount;\n}\n\nvoid\nCAnimManager::AddAnimBlockRef(int32 block)\n{\n\tms_aAnimBlocks[block].refCount++;\n}\n\nvoid\nCAnimManager::RemoveAnimBlockRefWithoutDelete(int32 block)\n{\n\tms_aAnimBlocks[block].refCount--;\n}\n\nvoid\nCAnimManager::RemoveAnimBlockRef(int32 block)\n{\n\tms_aAnimBlocks[block].refCount--;\n\tif(ms_aAnimBlocks[block].refCount == 0)\n\t\tCStreaming::RemoveAnim(block);\n}\n\nvoid\nCAnimManager::RemoveAnimBlock(int32 block)\n{\n\tint i;\n\tCAnimBlock *animblock;\n\n\tanimblock = &ms_aAnimBlocks[block];\n\tdebug(\"Removing ANIMS %s\\n\", animblock->name);\n\tfor(i = 0; i < NUM_ANIM_ASSOC_GROUPS; i++)\n\t\tif(ms_aAnimAssocGroups[i].animBlock == animblock)\n\t\t\tms_aAnimAssocGroups[i].DestroyAssociations();\n\tfor(i = 0; i < animblock->numAnims; i++)\n\t\tms_aAnimations[animblock->firstIndex + i].Shutdown();\n\tanimblock->isLoaded = false;\n\tanimblock->refCount = 0;\n}\n\nCAnimBlendHierarchy*\nCAnimManager::GetAnimation(const char *name, CAnimBlock *animBlock)\n{\n\tint i;\n\tCAnimBlendHierarchy *hier = &ms_aAnimations[animBlock->firstIndex];\n\n\tfor(i = 0; i < animBlock->numAnims; i++){\n\t\tif(strcasecmp(hier->name, name) == 0)\n\t\t\treturn hier;\n\t\thier++;\n\t}\n\treturn nil;\n}\n\nconst char*\nCAnimManager::GetAnimGroupName(AssocGroupId groupId)\n{\n\treturn ms_aAnimAssocDefinitions[groupId].name;\n}\n\nCAnimBlendAssociation*\nCAnimManager::CreateAnimAssociation(AssocGroupId groupId, AnimationId animId)\n{\n\treturn ms_aAnimAssocGroups[groupId].CopyAnimation(animId);\n}\n\nCAnimBlendAssociation*\nCAnimManager::GetAnimAssociation(AssocGroupId groupId, AnimationId animId)\n{\n\treturn ms_aAnimAssocGroups[groupId].GetAnimation(animId);\n}\n\nCAnimBlendAssociation*\nCAnimManager::GetAnimAssociation(AssocGroupId groupId, const char *name)\n{\n\treturn ms_aAnimAssocGroups[groupId].GetAnimation(name);\n}\n\nCAnimBlendAssociation*\nCAnimManager::AddAnimation(RpClump *clump, AssocGroupId groupId, AnimationId animId)\n{\n\tCAnimBlendAssociation *anim = CreateAnimAssociation(groupId, animId);\n\tCAnimBlendClumpData *clumpData = *RPANIMBLENDCLUMPDATA(clump);\n\tif(anim->IsMovement()){\n\t\tCAnimBlendAssociation *syncanim = nil;\n\t\tCAnimBlendLink *link;\n\t\tfor(link = clumpData->link.next; link; link = link->next){\n\t\t\tsyncanim = CAnimBlendAssociation::FromLink(link);\n\t\t\tif(syncanim->IsMovement())\n\t\t\t\tbreak;\n\t\t}\n\t\tif(link){\n\t\t\tanim->SyncAnimation(syncanim);\n\t\t\tanim->flags |= ASSOC_RUNNING;\n\t\t}else\n\t\t\tanim->Start(0.0f);\n\t}else\n\t\tanim->Start(0.0f);\n\n\tclumpData->link.Prepend(&anim->link);\n\treturn anim;\n}\n\nCAnimBlendAssociation*\nCAnimManager::AddAnimationAndSync(RpClump *clump, CAnimBlendAssociation *syncanim, AssocGroupId groupId, AnimationId animId)\n{\n\tCAnimBlendAssociation *anim = CreateAnimAssociation(groupId, animId);\n\tCAnimBlendClumpData *clumpData = *RPANIMBLENDCLUMPDATA(clump);\n\tif (anim->IsMovement() && syncanim){\n\t\tanim->SyncAnimation(syncanim);\n\t\tanim->flags |= ASSOC_RUNNING;\n\t}else\n\t\tanim->Start(0.0f);\n\n\tclumpData->link.Prepend(&anim->link);\n\treturn anim;\n}\n\nCAnimBlendAssociation*\nCAnimManager::BlendAnimation(RpClump *clump, AssocGroupId groupId, AnimationId animId, float delta)\n{\n\tint removePrevAnim = 0;\n\tCAnimBlendClumpData *clumpData = *RPANIMBLENDCLUMPDATA(clump);\n\tCAnimBlendAssociation *anim = GetAnimAssociation(groupId, animId);\n\tbool isMovement = anim->IsMovement();\n\tbool isPartial = anim->IsPartial();\n\tCAnimBlendLink *link;\n\tCAnimBlendAssociation *found = nil, *movementAnim = nil;\n\tfor(link = clumpData->link.next; link; link = link->next){\n\t\tanim = CAnimBlendAssociation::FromLink(link);\n\t\tif(isMovement && anim->IsMovement())\n\t\t\tmovementAnim = anim;\n\t\tif(anim->animId == animId)\n\t\t\tfound = anim;\n\t\telse{\n\t\t\tif(isPartial == anim->IsPartial()){\n\t\t\t\tif(anim->blendAmount > 0.0f){\n\t\t\t\t\tfloat blendDelta = -delta*anim->blendAmount;\n\t\t\t\t\tif(blendDelta < anim->blendDelta || !isPartial)\n\t\t\t\t\t\tanim->blendDelta = blendDelta;\n\t\t\t\t}else{\n\t\t\t\t\tanim->blendDelta = -1.0f;\n\t\t\t\t}\n\t\t\t\tanim->flags |= ASSOC_DELETEFADEDOUT;\n\t\t\t\tremovePrevAnim = 1;\n\t\t\t}\n\t\t}\n\t}\n\tif(found){\n\t\tfound->blendDelta = (1.0f - found->blendAmount)*delta;\n\t\tif(!found->IsRunning() && found->currentTime == found->hierarchy->totalLength)\n\t\t\tfound->Start(0.0f);\n\t}else{\n\t\tfound = AddAnimationAndSync(clump, movementAnim, groupId, animId);\n\t\tif(!removePrevAnim && !isPartial){\n\t\t\tfound->blendAmount = 1.0f;\n\t\t\treturn found;\n\t\t}\n\t\tfound->blendAmount = 0.0f;\n\t\tfound->blendDelta = delta;\n\t}\n\tUncompressAnimation(found->hierarchy);\n\treturn found;\n}\n\nvoid\nCAnimManager::LoadAnimFiles(void)\n{\n\tLoadAnimFile(\"ANIM\\\\PED.IFP\");\n\tms_aAnimAssocGroups = new CAnimBlendAssocGroup[NUM_ANIM_ASSOC_GROUPS];\n\tCreateAnimAssocGroups();\n}\n\nvoid\nCAnimManager::CreateAnimAssocGroups(void)\n{\n\tint i, j;\n\n\tfor(i = 0; i < NUM_ANIM_ASSOC_GROUPS; i++){\n\t\tCAnimBlock *block = GetAnimationBlock(ms_aAnimAssocDefinitions[i].blockName);\n\t\tif(block == nil || !block->isLoaded || ms_aAnimAssocGroups[i].assocList)\n\t\t\tcontinue;\n\n\t\tCBaseModelInfo *mi = CModelInfo::GetModelInfo(ms_aAnimAssocDefinitions[i].modelIndex);\n\t\tRpClump *clump = (RpClump*)mi->CreateInstance();\n\t\tRpAnimBlendClumpInit(clump);\n\t\tCAnimBlendAssocGroup *group = &ms_aAnimAssocGroups[i];\n\t\tconst AnimAssocDefinition *def = &ms_aAnimAssocDefinitions[i];\n\t\tgroup->groupId = i;\n\t\tgroup->firstAnimId = def->animDescs[0].animId;\n\t\tgroup->CreateAssociations(def->blockName, clump, def->animNames, def->numAnims);\n\t\tfor(j = 0; j < group->numAssociations; j++)\n\t\t\t// GetAnimation(i) in III (but it's in LoadAnimFiles), GetAnimation(group->animDesc[j].animId) in VC\n\t\t\tgroup->GetAnimation(def->animDescs[j].animId)->flags |= def->animDescs[j].flags;\n\t\tif(IsClumpSkinned(clump))\n\t\t\tRpClumpForAllAtomics(clump, AtomicRemoveAnimFromSkinCB, nil);\n\t\tRpClumpDestroy(clump);\n\t}\n}\n\nvoid\nCAnimManager::LoadAnimFile(const char *filename)\n{\n\tRwStream *stream;\n\tstream = RwStreamOpen(rwSTREAMFILENAME, rwSTREAMREAD, filename);\n\tassert(stream);\n\tLoadAnimFile(stream, true);\n\tRwStreamClose(stream, nil);\n}\n\nvoid\nCAnimManager::LoadAnimFile(RwStream *stream, bool compress, char (*uncompressedAnims)[32])\n{\n\t#define ROUNDSIZE(x) if((x) & 3) (x) += 4 - ((x)&3)\n\tstruct IfpHeader {\n\t\tchar ident[4];\n\t\tuint32 size;\n\t};\n\tIfpHeader anpk, info, name, dgan, cpan, anim;\n\tchar buf[256];\n\tint j, k, l;\n\tfloat *fbuf = (float*)buf;\n\n\t// block name\n\tRwStreamRead(stream, &anpk, sizeof(IfpHeader));\n\tROUNDSIZE(anpk.size);\n\tRwStreamRead(stream, &info, sizeof(IfpHeader));\n\tROUNDSIZE(info.size);\n\tRwStreamRead(stream, buf, info.size);\n\tCAnimBlock *animBlock = GetAnimationBlock(buf+4);\n\tif(animBlock){\n\t\tif(animBlock->numAnims == 0){\n\t\t\tanimBlock->numAnims = *(int*)buf;\n\t\t\tanimBlock->firstIndex = ms_numAnimations;\n\t\t}\n\t}else{\n\t\tanimBlock = &ms_aAnimBlocks[ms_numAnimBlocks++];\n\t\tstrncpy(animBlock->name, buf+4, MAX_ANIMBLOCK_NAME);\n\t\tanimBlock->numAnims = *(int*)buf;\n\t\tanimBlock->firstIndex = ms_numAnimations;\n\t}\n\n\tdebug(\"Loading ANIMS %s\\n\", animBlock->name);\n\tanimBlock->isLoaded = true;\n\n\tint animIndex = animBlock->firstIndex;\n\tfor(j = 0; j < animBlock->numAnims; j++){\n\t\tassert(animIndex < ARRAY_SIZE(ms_aAnimations));\n\t\tCAnimBlendHierarchy *hier = &ms_aAnimations[animIndex++];\n\n\t\t// animation name\n\t\tRwStreamRead(stream, &name, sizeof(IfpHeader));\n\t\tROUNDSIZE(name.size);\n\t\tRwStreamRead(stream, buf, name.size);\n\t\thier->SetName(buf);\n\n#ifdef ANIM_COMPRESSION\n\t\tbool compressHier = compress;\n#else\n\t\tbool compressHier = false;\n#endif\n\t\tif (uncompressedAnims) {\n\t\t\tfor (int i = 0; uncompressedAnims[i][0]; i++) {\n\t\t\t\tif (!CGeneral::faststricmp(uncompressedAnims[i], hier->name)){\n\t\t\t\t\tdebug(\"Loading %s uncompressed\\n\", hier->name);\n\t\t\t\t\tcompressHier = false;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\thier->compressed = compressHier;\n\t\thier->keepCompressed = false;\n\n\t\t// DG info has number of nodes/sequences\n\t\tRwStreamRead(stream, (char*)&dgan, sizeof(IfpHeader));\n\t\tROUNDSIZE(dgan.size);\n\t\tRwStreamRead(stream, (char*)&info, sizeof(IfpHeader));\n\t\tROUNDSIZE(info.size);\n\t\tRwStreamRead(stream, buf, info.size);\n\t\thier->numSequences = *(int*)buf;\n\t\thier->sequences = new CAnimBlendSequence[hier->numSequences];\n\n\t\tCAnimBlendSequence *seq = hier->sequences;\n\t\tfor(k = 0; k < hier->numSequences; k++, seq++){\n\t\t\t// Each node has a name and key frames\n\t\t\tRwStreamRead(stream, &cpan, sizeof(IfpHeader));\n\t\t\tROUNDSIZE(dgan.size);\n\t\t\tRwStreamRead(stream, &anim, sizeof(IfpHeader));\n\t\t\tROUNDSIZE(anim.size);\n\t\t\tRwStreamRead(stream, buf, anim.size);\n\t\t\tint numFrames = *(int*)(buf+28);\n\t\t\tseq->SetName(buf);\n\t\t\tif(anim.size == 44)\n\t\t\t\tseq->SetBoneTag(*(int*)(buf+40));\n\t\t\tif(numFrames == 0)\n\t\t\t\tcontinue;\n\n\t\t\tbool hasScale = false;\n\t\t\tbool hasTranslation = false;\n\t\t\tRwStreamRead(stream, &info, sizeof(info));\n\t\t\tif(strncmp(info.ident, \"KRTS\", 4) == 0){\n\t\t\t\thasScale = true;\n\t\t\t\tseq->SetNumFrames(numFrames, true, compressHier);\n\t\t\t}else if(strncmp(info.ident, \"KRT0\", 4) == 0){\n\t\t\t\thasTranslation = true;\n\t\t\t\tseq->SetNumFrames(numFrames, true, compressHier);\n\t\t\t}else if(strncmp(info.ident, \"KR00\", 4) == 0){\n\t\t\t\tseq->SetNumFrames(numFrames, false, compressHier);\n\t\t\t}\n\t\t\tif(strstr(seq->name, \"L Toe\"))\n\t\t\t\tdebug(\"anim %s has toe keyframes\\n\", hier->name); // BUG: seq->name\n\n\t\t\tfor(l = 0; l < numFrames; l++){\n\t\t\t\tif(hasScale){\n\t\t\t\t\tRwStreamRead(stream, buf, 0x2C);\n\t\t\t\t\tCQuaternion rot(fbuf[0], fbuf[1], fbuf[2], fbuf[3]);\n\t\t\t\t\trot.Invert();\n\t\t\t\t\tCVector trans(fbuf[4], fbuf[5], fbuf[6]);\n\n\t\t\t\t\tif(compressHier){\n\t\t\t\t\t\tKeyFrameTransCompressed *kf = (KeyFrameTransCompressed*)seq->GetKeyFrameCompressed(l);\n\t\t\t\t\t\tkf->SetRotation(rot);\n\t\t\t\t\t\tkf->SetTranslation(trans);\n\t\t\t\t\t\t// scaling ignored\n\t\t\t\t\t\tkf->SetTime(fbuf[10]);\t// absolute time here\n\t\t\t\t\t}else{\n\t\t\t\t\t\tKeyFrameTrans *kf = (KeyFrameTrans*)seq->GetKeyFrame(l);\n\t\t\t\t\t\tkf->rotation = rot;\n\t\t\t\t\t\tkf->translation = trans;\n\t\t\t\t\t\t// scaling ignored\n\t\t\t\t\t\tkf->deltaTime = fbuf[10];\t// absolute time here\n\t\t\t\t\t}\n\t\t\t\t}else if(hasTranslation){\n\t\t\t\t\tRwStreamRead(stream, buf, 0x20);\n\t\t\t\t\tCQuaternion rot(fbuf[0], fbuf[1], fbuf[2], fbuf[3]);\n\t\t\t\t\trot.Invert();\n\t\t\t\t\tCVector trans(fbuf[4], fbuf[5], fbuf[6]);\n\n\t\t\t\t\tif(compressHier){\n\t\t\t\t\t\tKeyFrameTransCompressed *kf = (KeyFrameTransCompressed*)seq->GetKeyFrameCompressed(l);\n\t\t\t\t\t\tkf->SetRotation(rot);\n\t\t\t\t\t\tkf->SetTranslation(trans);\n\t\t\t\t\t\tkf->SetTime(fbuf[7]);\t// absolute time here\n\t\t\t\t\t}else{\n\t\t\t\t\t\tKeyFrameTrans *kf = (KeyFrameTrans*)seq->GetKeyFrame(l);\n\t\t\t\t\t\tkf->rotation = rot;\n\t\t\t\t\t\tkf->translation = trans;\n\t\t\t\t\t\tkf->deltaTime = fbuf[7];\t// absolute time here\n\t\t\t\t\t}\n\t\t\t\t}else{\n\t\t\t\t\tRwStreamRead(stream, buf, 0x14);\n\t\t\t\t\tCQuaternion rot(fbuf[0], fbuf[1], fbuf[2], fbuf[3]);\n\t\t\t\t\trot.Invert();\n\n\t\t\t\t\tif(compressHier){\n\t\t\t\t\t\tKeyFrameCompressed *kf = (KeyFrameCompressed*)seq->GetKeyFrameCompressed(l);\n\t\t\t\t\t\tkf->SetRotation(rot);\n\t\t\t\t\t\tkf->SetTime(fbuf[4]);\t// absolute time here\n\t\t\t\t\t}else{\n\t\t\t\t\t\tKeyFrame *kf = (KeyFrame*)seq->GetKeyFrame(l);\n\t\t\t\t\t\tkf->rotation = rot;\n\t\t\t\t\t\tkf->deltaTime = fbuf[4];\t// absolute time here\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif(!compressHier){\n\t\t\thier->RemoveQuaternionFlips();\n\t\t\thier->CalcTotalTime();\n\t\t}\n\t}\n\tif(animIndex > ms_numAnimations)\n\t\tms_numAnimations = animIndex;\n}\n\nvoid\nCAnimManager::RemoveLastAnimFile(void)\n{\n\tint i;\n\tms_numAnimBlocks--;\n\tms_numAnimations = ms_aAnimBlocks[ms_numAnimBlocks].firstIndex;\n\tfor(i = 0; i < ms_aAnimBlocks[ms_numAnimBlocks].numAnims; i++)\n\t\tms_aAnimations[ms_aAnimBlocks[ms_numAnimBlocks].firstIndex + i].Shutdown();\n\tms_aAnimBlocks[ms_numAnimBlocks].isLoaded = false;\n}\n"
  },
  {
    "path": "src/animation/AnimManager.h",
    "content": "#pragma once\n\n#include \"AnimBlendHierarchy.h\"\n#include \"AnimationId.h\"\n\nenum AssocGroupId\n{\n\tASSOCGRP_STD,\n\tASSOCGRP_VAN,\n\tASSOCGRP_COACH,\n\tASSOCGRP_BIKE_STANDARD,\n\tASSOCGRP_BIKE_VESPA,\n\tASSOCGRP_BIKE_HARLEY,\n\tASSOCGRP_BIKE_DIRT,\n\tASSOCGRP_UNARMED,\n\tASSOCGRP_SCREWDRIVER,\n\tASSOCGRP_KNIFE,\n\tASSOCGRP_BASEBALLBAT,\n\tASSOCGRP_GOLFCLUB,\n\tASSOCGRP_CHAINSAW,\n\tASSOCGRP_PYTHON,\n\tASSOCGRP_COLT,\n\tASSOCGRP_SHOTGUN,\n\tASSOCGRP_BUDDY,\n\tASSOCGRP_TEC,\n\tASSOCGRP_UZI,\n\tASSOCGRP_RIFLE,\n\tASSOCGRP_M60,\n\tASSOCGRP_SNIPER,\n\tASSOCGRP_THROW,\n\tASSOCGRP_FLAMETHROWER,\n\tASSOCGRP_MEDIC,\n\tASSOCGRP_SUNBATHE,\n\tASSOCGRP_PLAYER_IDLE,\n\tASSOCGRP_RIOT,\n\tASSOCGRP_STRIP,\n\tASSOCGRP_LANCE,\n\tASSOCGRP_PLAYER,\n\tASSOCGRP_PLAYERROCKET,\n\tASSOCGRP_PLAYER1ARMED,\n\tASSOCGRP_PLAYER2ARMED,\n\tASSOCGRP_PLAYERBBBAT,\n\tASSOCGRP_PLAYERCHAINSAW,\n\tASSOCGRP_SHUFFLE,\n\tASSOCGRP_OLD,\n\tASSOCGRP_GANG1,\n\tASSOCGRP_GANG2,\n\tASSOCGRP_FAT,\n\tASSOCGRP_OLDFAT,\n\tASSOCGRP_JOGGER,\n\tASSOCGRP_WOMAN,\n\tASSOCGRP_WOMANSHOP,\n\tASSOCGRP_BUSYWOMAN,\n\tASSOCGRP_SEXYWOMAN,\n\tASSOCGRP_FATWOMAN,\n\tASSOCGRP_OLDWOMAN,\n\tASSOCGRP_JOGWOMAN,\n\tASSOCGRP_PANICCHUNKY,\n\tASSOCGRP_SKATE,\n#ifdef PC_PLAYER_CONTROLS\n\tASSOCGRP_PLAYERBACK,\n\tASSOCGRP_PLAYERLEFT,\n\tASSOCGRP_PLAYERRIGHT,\n\tASSOCGRP_ROCKETBACK,\n\tASSOCGRP_ROCKETLEFT,\n\tASSOCGRP_ROCKETRIGHT,\n\tASSOCGRP_CHAINSAWBACK,\n\tASSOCGRP_CHAINSAWLEFT,\n\tASSOCGRP_CHAINSAWRIGHT,\n#endif\n\n\tNUM_ANIM_ASSOC_GROUPS\n};\n\nclass CAnimBlendAssociation;\nclass CAnimBlendAssocGroup;\n\n#define MAX_ANIMBLOCK_NAME 20\n\n// A block of hierarchies\nstruct CAnimBlock\n{\n\tchar name[MAX_ANIMBLOCK_NAME];\n\tbool isLoaded;\n\tint16 refCount;\n\tint32 firstIndex;\t// first animtion in ms_aAnimations\n\tint32 numAnims;\n};\n\nstruct AnimAssocDesc\n{\n\tint32 animId;\n\tint32 flags;\n};\n\nstruct AnimAssocDefinition\n{\n\tchar const *name;\n\tchar const *blockName;\n\tint32 modelIndex;\n\tint32 numAnims;\n\tchar const **animNames;\n\tAnimAssocDesc *animDescs;\n};\n\nclass CAnimManager\n{\n\tstatic const AnimAssocDefinition ms_aAnimAssocDefinitions[NUM_ANIM_ASSOC_GROUPS];\n\tstatic CAnimBlock ms_aAnimBlocks[NUMANIMBLOCKS];\n\tstatic CAnimBlendHierarchy ms_aAnimations[NUMANIMATIONS];\n\tstatic int32 ms_numAnimBlocks;\n\tstatic int32 ms_numAnimations;\n\tstatic CAnimBlendAssocGroup *ms_aAnimAssocGroups;\n\tstatic CLinkList<CAnimBlendHierarchy*> ms_animCache;\npublic:\n\n\tstatic void Initialise(void);\n\tstatic void Shutdown(void);\n\tstatic void UncompressAnimation(CAnimBlendHierarchy *anim);\n\tstatic void RemoveFromUncompressedCache(CAnimBlendHierarchy *hier);\n\tstatic CAnimBlock *GetAnimationBlock(int32 block) { return &ms_aAnimBlocks[block]; }\n\tstatic CAnimBlock *GetAnimationBlock(const char *name);\n\tstatic int32 GetAnimationBlockIndex(const char *name);\n\tstatic int32 RegisterAnimBlock(const char *name);\n\tstatic int32 GetNumRefsToAnimBlock(int32 block);\n\tstatic void AddAnimBlockRef(int32 block);\n\tstatic void RemoveAnimBlockRefWithoutDelete(int32 block);\n\tstatic void RemoveAnimBlockRef(int32 block);\n\tstatic void RemoveAnimBlock(int32 block);\n\tstatic CAnimBlendHierarchy *GetAnimation(const char *name, CAnimBlock *animBlock);\n\tstatic CAnimBlendHierarchy *GetAnimation(int32 n) { return &ms_aAnimations[n]; }\n\tstatic const char *GetAnimGroupName(AssocGroupId groupId);\n\tstatic CAnimBlendAssociation *CreateAnimAssociation(AssocGroupId groupId, AnimationId animId);\n\tstatic CAnimBlendAssociation *GetAnimAssociation(AssocGroupId groupId, AnimationId animId);\n\tstatic CAnimBlendAssociation *GetAnimAssociation(AssocGroupId groupId, const char *name);\n\tstatic CAnimBlendAssociation *AddAnimation(RpClump *clump, AssocGroupId groupId, AnimationId animId);\n\tstatic CAnimBlendAssociation *AddAnimationAndSync(RpClump *clump, CAnimBlendAssociation *syncanim, AssocGroupId groupId, AnimationId animId);\n\tstatic CAnimBlendAssociation *BlendAnimation(RpClump *clump, AssocGroupId groupId, AnimationId animId, float delta);\n\tstatic void LoadAnimFiles(void);\n\tstatic void LoadAnimFile(const char *filename);\n\tstatic void LoadAnimFile(RwStream *stream, bool compress, char (*uncompressedAnims)[32] = nil);\n\tstatic void CreateAnimAssocGroups(void);\n\tstatic void RemoveLastAnimFile(void);\n\tstatic CAnimBlendAssocGroup* GetAnimAssocGroups(void) { return ms_aAnimAssocGroups; }\n};\n"
  },
  {
    "path": "src/animation/AnimationId.h",
    "content": "#pragma once\n\nenum AnimationId\n{\n\tANIM_STD_WALK,\n\tANIM_STD_RUN,\n\tANIM_STD_RUNFAST,\n\tANIM_STD_IDLE,\n\tANIM_STD_STARTWALK,\n\tANIM_STD_RUNSTOP1,\n\tANIM_STD_RUNSTOP2,\n\tANIM_STD_IDLE_CAM,\n\tANIM_STD_IDLE_HBHB,\n\tANIM_STD_IDLE_TIRED,\n\tANIM_STD_IDLE_BIGGUN,\n\tANIM_STD_CHAT,\n\tANIM_STD_HAILTAXI,\n\tANIM_STD_KO_FRONT,\n\tANIM_STD_KO_LEFT,\n\tANIM_STD_KO_BACK,\n\tANIM_STD_KO_RIGHT,\n\tANIM_STD_KO_SHOT_FACE,\n\tANIM_STD_KO_SHOT_STOMACH,\n\tANIM_STD_KO_SHOT_ARM_L,\n\tANIM_STD_KO_SHOT_ARM_R,\n\tANIM_STD_KO_SHOT_LEG_L,\n\tANIM_STD_KO_SHOT_LEG_R,\n\tANIM_STD_SPINFORWARD_LEFT,\n\tANIM_STD_SPINFORWARD_RIGHT,\n\tANIM_STD_HIGHIMPACT_FRONT,\n\tANIM_STD_HIGHIMPACT_LEFT,\n\tANIM_STD_HIGHIMPACT_BACK,\n\tANIM_STD_HIGHIMPACT_RIGHT,\n\tANIM_STD_HITBYGUN_FRONT,\n\tANIM_STD_HITBYGUN_LEFT,\n\tANIM_STD_HITBYGUN_BACK,\n\tANIM_STD_HITBYGUN_RIGHT,\n\tANIM_STD_HIT_FRONT,\n\tANIM_STD_HIT_LEFT,\n\tANIM_STD_HIT_BACK,\n\tANIM_STD_HIT_RIGHT,\n\tANIM_STD_HIT_FLOOR,\n\n\t/* names made up */\n\tANIM_STD_HIT_BODYBLOW,\n\tANIM_STD_HIT_CHEST,\n\tANIM_STD_HIT_HEAD,\n\tANIM_STD_HIT_WALK,\n\t/**/\n\n\tANIM_STD_HIT_WALL,\n\tANIM_STD_HIT_FLOOR_FRONT,\n\tANIM_STD_HIT_BEHIND,\n\tANIM_STD_FIGHT_IDLE,\n\tANIM_STD_FIGHT_2IDLE,\n\tANIM_STD_FIGHT_SHUFFLE_F,\n\n\t/* names made up */\n\tANIM_STD_FIGHT_BODYBLOW,\n\tANIM_STD_FIGHT_HEAD,\n\tANIM_STD_FIGHT_KICK,\n\tANIM_STD_FIGHT_KNEE,\n\tANIM_STD_FIGHT_LHOOK,\n\tANIM_STD_FIGHT_PUNCH,\n\tANIM_STD_FIGHT_ROUNDHOUSE,\n\tANIM_STD_FIGHT_LONGKICK,\n\t/**/\n\n\tANIM_STD_PARTIAL_PUNCH,\n\n\t/* names made up */\n\tANIM_STD_FIGHT_JAB,\n\tANIM_STD_FIGHT_ELBOW_L,\n\tANIM_STD_FIGHT_ELBOW_R,\n\tANIM_STD_FIGHT_BKICK_L,\n\tANIM_STD_FIGHT_BKICK_R,\n\t/**/\n\n\tANIM_STD_DETONATE,\n\tANIM_STD_PUNCH,\n\tANIM_STD_PARTIALPUNCH,\n\tANIM_STD_KICKGROUND,\n\n\tANIM_STD_THROW_UNDER,\n\tANIM_STD_FIGHT_SHUFFLE_B,\n\n\tANIM_STD_JACKEDCAR_RHS,\n\tANIM_STD_JACKEDCAR_LO_RHS,\n\tANIM_STD_JACKEDCAR_LHS,\n\tANIM_STD_JACKEDCAR_LO_LHS,\n\tANIM_STD_QUICKJACK,\n\tANIM_STD_QUICKJACKED,\n\tANIM_STD_CAR_ALIGN_DOOR_LHS,\n\tANIM_STD_CAR_ALIGNHI_DOOR_LHS,\n\tANIM_STD_CAR_OPEN_DOOR_LHS,\n\tANIM_STD_CARDOOR_LOCKED_LHS,\n\tANIM_STD_CAR_PULL_OUT_PED_LHS,\n\tANIM_STD_CAR_PULL_OUT_PED_LO_LHS,\n\tANIM_STD_CAR_GET_IN_LHS,\n\tANIM_STD_CAR_GET_IN_LO_LHS,\n\tANIM_STD_CAR_CLOSE_DOOR_LHS,\n\tANIM_STD_CAR_CLOSE_DOOR_LO_LHS,\n\tANIM_STD_CAR_CLOSE_DOOR_ROLLING_LHS,\n\tANIM_STD_CAR_CLOSE_DOOR_ROLLING_LO_LHS,\n\tANIM_STD_CAR_JUMP_IN_LO_LHS,\n\tANIM_STD_GETOUT_LHS,\n\tANIM_STD_GETOUT_LO_LHS,\n\tANIM_STD_CAR_CLOSE_LHS,\n\tANIM_STD_CAR_ALIGN_DOOR_RHS,\n\tANIM_STD_CAR_ALIGNHI_DOOR_RHS,\n\tANIM_STD_CAR_OPEN_DOOR_RHS,\n\tANIM_STD_CARDOOR_LOCKED_RHS,\n\tANIM_STD_CAR_PULL_OUT_PED_RHS,\n\tANIM_STD_CAR_PULL_OUT_PED_LO_RHS,\n\tANIM_STD_CAR_GET_IN_RHS,\n\tANIM_STD_CAR_GET_IN_LO_RHS,\n\tANIM_STD_CAR_CLOSE_DOOR_RHS,\n\tANIM_STD_CAR_CLOSE_DOOR_LO_RHS,\n\tANIM_STD_CAR_SHUFFLE_RHS,\n\tANIM_STD_CAR_SHUFFLE_LO_RHS,\n\tANIM_STD_CAR_SIT,\n\tANIM_STD_CAR_SIT_LO,\n\tANIM_STD_CAR_SIT_P,\n\tANIM_STD_CAR_SIT_P_LO,\n\tANIM_STD_CAR_DRIVE_LEFT,\n\tANIM_STD_CAR_DRIVE_RIGHT,\n\tANIM_STD_CAR_DRIVE_LEFT_LO,\n\tANIM_STD_CAR_DRIVE_RIGHT_LO,\n\tANIM_STD_CAR_DRIVEBY_LEFT,\n\tANIM_STD_CAR_DRIVEBY_RIGHT,\n\tANIM_STD_CAR_DRIVEBY_LEFT_LO,\n\tANIM_STD_CAR_DRIVEBY_RIGHT_LO,\n\tANIM_STD_CAR_LOOKBEHIND,\n\tANIM_STD_BOAT_DRIVE,\n\tANIM_STD_BOAT_DRIVE_LEFT,\n\tANIM_STD_BOAT_DRIVE_RIGHT,\n\tANIM_STD_BOAT_LOOKBEHIND,\n\n\tANIM_STD_BIKE_PICKUP_LHS,\n\tANIM_STD_BIKE_PICKUP_RHS,\n\tANIM_STD_BIKE_PULLUP_LHS,\n\tANIM_STD_BIKE_PULLUP_RHS,\n\tANIM_STD_BIKE_ELBOW_LHS,\n\tANIM_STD_BIKE_ELBOW_RHS,\n\tANIM_STD_BIKE_FALLOFF,\n\tANIM_STD_BIKE_FALLBACK,\n\n\tANIM_STD_GETOUT_RHS,\n\tANIM_STD_GETOUT_LO_RHS,\n\tANIM_STD_CAR_CLOSE_RHS,\n\tANIM_STD_CAR_HOOKERTALK,\n\n\tANIM_STD_TRAIN_GETIN,\n\tANIM_STD_TRAIN_GETOUT,\n\n\tANIM_STD_CRAWLOUT_LHS,\n\tANIM_STD_CRAWLOUT_RHS,\n\tANIM_STD_ROLLOUT_LHS,\n\tANIM_STD_ROLLOUT_RHS,\n\n\tANIM_STD_GET_UP,\n\tANIM_STD_GET_UP_LEFT,\n\tANIM_STD_GET_UP_RIGHT,\n\tANIM_STD_GET_UP_FRONT,\n\tANIM_STD_JUMP_LAUNCH,\n\tANIM_STD_JUMP_GLIDE,\n\tANIM_STD_JUMP_LAND,\n\tANIM_STD_FALL,\n\tANIM_STD_FALL_GLIDE,\n\tANIM_STD_FALL_LAND,\n\tANIM_STD_FALL_COLLAPSE,\n\tANIM_STD_FALL_ONBACK,\n\tANIM_STD_FALL_ONFRONT,\n\n\tANIM_STD_EVADE_STEP,\n\tANIM_STD_EVADE_DIVE,\n\tANIM_STD_XPRESS_SCRATCH,\n\tANIM_STD_ROADCROSS,\n\tANIM_STD_TURN180,\n\tANIM_STD_ARREST,\n\tANIM_STD_DROWN,\n\tANIM_STD_DUCK_DOWN,\n\tANIM_STD_DUCK_LOW,\n\n\tANIM_STD_DUCK_WEAPON,\n\n\tANIM_STD_RBLOCK_SHOOT,\n\tANIM_STD_HANDSUP,\n\tANIM_STD_HANDSCOWER,\n\tANIM_STD_PARTIAL_FUCKU,\n\tANIM_STD_PHONE_IN,\n\tANIM_STD_PHONE_OUT,\n\tANIM_STD_PHONE_TALK,\n\n\tANIM_STD_SEAT_DOWN,\n\tANIM_STD_SEAT_UP,\n\tANIM_STD_SEAT_IDLE,\n\tANIM_STD_SEAT_RVRS,\n\tANIM_STD_ATM,\n\tANIM_STD_ABSEIL,\n\n\tANIM_STD_NUM,\n\n\tANIM_STD_VAN_OPEN_DOOR_REAR_LHS,\n\tANIM_STD_VAN_GET_IN_REAR_LHS,\n\tANIM_STD_VAN_CLOSE_DOOR_REAR_LHS,\n\tANIM_STD_VAN_GET_OUT_REAR_LHS,\n\tANIM_STD_VAN_OPEN_DOOR_REAR_RHS,\n\tANIM_STD_VAN_GET_IN_REAR_RHS,\n\tANIM_STD_VAN_CLOSE_DOOR_REAR_RHS,\n\tANIM_STD_VAN_GET_OUT_REAR_RHS,\n\n\tANIM_STD_COACH_OPEN_LHS,\n\tANIM_STD_COACH_OPEN_RHS,\n\tANIM_STD_COACH_GET_IN_LHS,\n\tANIM_STD_COACH_GET_IN_RHS,\n\tANIM_STD_COACH_GET_OUT_LHS,\n\n\tANIM_BIKE_RIDE,\n\tANIM_BIKE_READY,\n\tANIM_BIKE_LEFT,\n\tANIM_BIKE_RIGHT,\n\tANIM_BIKE_LEANB,\n\tANIM_BIKE_LEANF,\n\tANIM_BIKE_WALKBACK,\n\tANIM_BIKE_JUMPON_LHS,\n\tANIM_BIKE_JUMPON_RHS,\n\tANIM_BIKE_KICK,\n\tANIM_BIKE_HIT,\n\tANIM_BIKE_GETOFF_LHS,\n\tANIM_BIKE_GETOFF_RHS,\n\tANIM_BIKE_GETOFF_BACK,\n\tANIM_BIKE_DRIVEBY_LHS,\n\tANIM_BIKE_DRIVEBY_RHS,\n\tANIM_BIKE_DRIVEBY_FORWARD,\n\tANIM_BIKE_RIDE_P,\n\n\tANIM_ATTACK_1,\n\tANIM_ATTACK_2,\n\tANIM_ATTACK_EXTRA1,\n\tANIM_ATTACK_EXTRA2,\n\tANIM_ATTACK_3,\n\n\t// our synonyms... because originals are hard to understand\n\tANIM_WEAPON_FIRE = ANIM_ATTACK_1,\n\tANIM_WEAPON_CROUCHFIRE,\n\tANIM_WEAPON_FIRE_2ND = ANIM_WEAPON_CROUCHFIRE,\n\tANIM_WEAPON_RELOAD,\n\tANIM_WEAPON_CROUCHRELOAD,\n\tANIM_WEAPON_FIRE_3RD,\n\tANIM_THROWABLE_THROW = ANIM_ATTACK_1,\n\tANIM_THROWABLE_THROWU,\n\tANIM_THROWABLE_START_THROW,\n\tANIM_MELEE_ATTACK = ANIM_ATTACK_1,\n\tANIM_MELEE_ATTACK_2ND,\n\tANIM_MELEE_ATTACK_START,\n\tANIM_MELEE_IDLE_FIGHTMODE,\n\tANIM_MELEE_ATTACK_FINISH,\n\n\tANIM_SUNBATHE_IDLE,\n\tANIM_SUNBATHE_DOWN,\n\tANIM_SUNBATHE_UP,\n\tANIM_SUNBATHE_ESCAPE,\n\n\tANIM_MEDIC_CPR,\n\n\tANIM_PLAYER_IDLE1,\n\tANIM_PLAYER_IDLE2,\n\tANIM_PLAYER_IDLE3,\n\tANIM_PLAYER_IDLE4,\n\n\tANIM_RIOT_ANGRY,\n\tANIM_RIOT_ANGRY_B,\n\tANIM_RIOT_CHANT,\n\tANIM_RIOT_PUNCHES,\n\tANIM_RIOT_SHOUT,\n\tANIM_RIOT_CHALLENGE,\n\tANIM_RIOT_FUCKYOU,\n\n\tANIM_STRIP_A,\n\tANIM_STRIP_B,\n\tANIM_STRIP_C,\n\tANIM_STRIP_D,\n\tANIM_STRIP_E,\n\tANIM_STRIP_F,\n\tANIM_STRIP_G,\n};"
  },
  {
    "path": "src/animation/Bones.cpp",
    "content": "#include \"common.h\"\n#include \"PedModelInfo.h\"\n#include \"Bones.h\"\n\nint\nConvertPedNode2BoneTag(int node)\n{\n\tswitch(node){\n\tcase PED_MID:\treturn BONE_spine1;\n\tcase PED_HEAD:\treturn BONE_head;\n\tcase PED_UPPERARML:\treturn BONE_l_upperarm;\n\tcase PED_UPPERARMR:\treturn BONE_r_upperarm;\n\tcase PED_HANDL:\treturn BONE_l_hand;\n\tcase PED_HANDR:\treturn BONE_r_hand;\n\tcase PED_UPPERLEGL:\treturn BONE_l_thigh;\n\tcase PED_UPPERLEGR:\treturn BONE_r_thigh;\n\tcase PED_FOOTL:\treturn BONE_l_foot;\n\tcase PED_FOOTR:\treturn BONE_r_foot;\n\tcase PED_LOWERLEGR:\treturn BONE_r_calf;\n\tcase PED_LOWERLEGL:\treturn BONE_l_calf;\n\tcase PED_FOREARML:\treturn BONE_l_forearm;\n\tcase PED_FOREARMR:\treturn BONE_r_forearm;\n\tcase PED_CLAVICLEL:\treturn BONE_l_clavicle;\n\tcase PED_CLAVICLER:\treturn BONE_r_clavicle;\n\tcase PED_NECK:\treturn BONE_neck;\n\t}\n\tassert(0 && \"this node has no bone\");\n\treturn -1;\n}\n\nconst char*\nConvertBoneTag2BoneName(int tag)\n{\n\tswitch(tag){\n\tcase BONE_root:\treturn \"Root\";\n\tcase BONE_pelvis:\treturn \"Pelvis\";\n\tcase BONE_spine:\treturn \"Spine\";\n\tcase BONE_spine1:\treturn \"Spine1\";\n\tcase BONE_neck:\treturn \"Neck\";\n\tcase BONE_head:\treturn \"Head\";\n\tcase BONE_r_clavicle:\treturn \"Bip01 R Clavicle\";\n\tcase BONE_r_upperarm:\treturn \"R UpperArm\";\n\tcase BONE_r_forearm:\treturn \"R Forearm\";\n\tcase BONE_r_hand:\treturn \"R Hand\";\n\tcase BONE_r_finger:\treturn \"R Fingers\";\n\tcase BONE_l_clavicle:\treturn \"Bip01 L Clavicle\";\n\tcase BONE_l_upperarm:\treturn \"L UpperArm\";\n\tcase BONE_l_forearm:\treturn \"L Forearm\";\n\tcase BONE_l_hand:\treturn \"L Hand\";\n\tcase BONE_l_finger:\treturn \"L Fingers\";\n\tcase BONE_l_thigh:\treturn \"L Thigh\";\n\tcase BONE_l_calf:\treturn \"L Calf\";\n\tcase BONE_l_foot:\treturn \"L Foot\";\n\tcase BONE_r_thigh:\treturn \"R Thigh\";\n\tcase BONE_r_calf:\treturn \"R Calf\";\n\tcase BONE_r_foot:\treturn \"R Foot\";\n\t}\n\treturn nil;\n}\n"
  },
  {
    "path": "src/animation/Bones.h",
    "content": "#pragma once\n\nenum BoneTag\n{\n\tBONE_root = 0,\n\tBONE_pelvis = 1,\n\tBONE_spine = 2,\n\tBONE_spine1 = 3,\n\tBONE_neck = 4,\n\tBONE_head = 5,\n\tBONE_l_clavicle = 31,\n\tBONE_l_upperarm = 32,\n\tBONE_l_forearm = 33,\n\tBONE_l_hand = 34,\n\tBONE_l_finger = 35,\n\tBONE_r_clavicle = 21,\n\tBONE_r_upperarm = 22,\n\tBONE_r_forearm = 23,\n\tBONE_r_hand = 24,\n\tBONE_r_finger = 25,\n\tBONE_l_thigh = 41,\n\tBONE_l_calf = 42,\n\tBONE_l_foot = 43,\n\tBONE_r_thigh = 51,\n\tBONE_r_calf = 52,\n\tBONE_r_foot = 53,\n};\n\nint ConvertPedNode2BoneTag(int node);\nconst char *ConvertBoneTag2BoneName(int tag);\n"
  },
  {
    "path": "src/animation/CutsceneMgr.cpp",
    "content": "#include \"common.h\"\n\n#include \"General.h\"\n#include \"CutsceneMgr.h\"\n#include \"Directory.h\"\n#include \"Camera.h\"\n#include \"Streaming.h\"\n#include \"FileMgr.h\"\n#include \"main.h\"\n#include \"AnimManager.h\"\n#include \"AnimBlendAssociation.h\"\n#include \"AnimBlendAssocGroup.h\"\n#include \"AnimBlendClumpData.h\"\n#include \"Pad.h\"\n#include \"DMAudio.h\"\n#include \"World.h\"\n#include \"PlayerPed.h\"\n#include \"Wanted.h\"\n#include \"RpAnimBlend.h\"\n#include \"ModelIndices.h\"\n#include \"TempColModels.h\"\n#include \"ColStore.h\"\n#include \"Radar.h\"\n#include \"Pools.h\"\n\nconst struct {\n\tconst char *szTrackName;\n\tint iTrackId;\n} musicNameIdAssoc[] = {\n\t{ \"ASS_1\", STREAMED_SOUND_CUTSCENE_ASS_1 },\n\t{ \"ASS_2\", STREAMED_SOUND_CUTSCENE_ASS_2 },\n\t{ \"BANK_1\", STREAMED_SOUND_CUTSCENE_BANK_1 },\n\t{ \"BANK_2A\", STREAMED_SOUND_CUTSCENE_BANK_2A },\n\t{ \"BANK_2B\", STREAMED_SOUND_CUTSCENE_BANK_2B },\n\t{ \"BANK_3A\", STREAMED_SOUND_CUTSCENE_BANK_3A },\n\t{ \"BANK_3B\", STREAMED_SOUND_CUTSCENE_BANK_3B },\n\t{ \"BANK_4\", STREAMED_SOUND_CUTSCENE_BANK_4 },\n\t{ \"BIKE_1\", STREAMED_SOUND_CUTSCENE_BIKE_1 },\n\t{ \"BIKE_2\", STREAMED_SOUND_CUTSCENE_BIKE_2 },\n\t{ \"BIKE_3\", STREAMED_SOUND_CUTSCENE_BIKE_3 },\n\t{ \"BUD_1\", STREAMED_SOUND_CUTSCENE_BUD_1 },\n\t{ \"BUD_2\", STREAMED_SOUND_CUTSCENE_BUD_2 },\n\t{ \"BUD_3\", STREAMED_SOUND_CUTSCENE_BUD_3 },\n\t{ \"CAP_1\", STREAMED_SOUND_CUTSCENE_CAP_1 },\n\t{ \"CAR_1\", STREAMED_SOUND_CUTSCENE_CAR_1 },\n\t{ \"CNT_1A\", STREAMED_SOUND_CUTSCENE_CNT_1A },\n\t{ \"CNT_1B\", STREAMED_SOUND_CUTSCENE_CNT_1B },\n\t{ \"CNT_2\", STREAMED_SOUND_CUTSCENE_CNT_2 },\n\t{ \"COK_1\", STREAMED_SOUND_CUTSCENE_COK_1 },\n\t{ \"COK_2A\", STREAMED_SOUND_CUTSCENE_COK_2A },\n\t{ \"COK_2B\", STREAMED_SOUND_CUTSCENE_COK_2B },\n\t{ \"COK_3\", STREAMED_SOUND_CUTSCENE_COK_3 },\n\t{ \"COK_4A\", STREAMED_SOUND_CUTSCENE_COK_4A },\n\t{ \"COK_4A2\", STREAMED_SOUND_CUTSCENE_COK_4A2 },\n\t{ \"COK_4B\", STREAMED_SOUND_CUTSCENE_COK_4B },\n\t{ \"COL_1\", STREAMED_SOUND_CUTSCENE_COL_1 },\n\t{ \"COL_2\", STREAMED_SOUND_CUTSCENE_COL_2 },\n\t{ \"COL_3A\", STREAMED_SOUND_CUTSCENE_COL_3A },\n\t{ \"COL_4A\", STREAMED_SOUND_CUTSCENE_COL_4A },\n\t{ \"COL_5A\", STREAMED_SOUND_CUTSCENE_COL_5A },\n\t{ \"COL_5B\", STREAMED_SOUND_CUTSCENE_COL_5B },\n\t{ \"CUB_1\", STREAMED_SOUND_CUTSCENE_CUB_1 },\n\t{ \"CUB_2\", STREAMED_SOUND_CUTSCENE_CUB_2 },\n\t{ \"CUB_3\", STREAMED_SOUND_CUTSCENE_CUB_3 },\n\t{ \"CUB_4\", STREAMED_SOUND_CUTSCENE_CUB_4 },\n\t{ \"DRUG_1\", STREAMED_SOUND_CUTSCENE_DRUG_1 },\n\t{ \"FIN\", STREAMED_SOUND_CUTSCENE_FIN },\n\t{ \"FIN_2\", STREAMED_SOUND_CUTSCENE_FIN2 },\n\t{ \"FINALE\", STREAMED_SOUND_CUTSCENE_FINALE },\n\t{ \"HAT_1\", STREAMED_SOUND_CUTSCENE_HAT_1 },\n\t{ \"HAT_2\", STREAMED_SOUND_CUTSCENE_HAT_2 },\n\t{ \"HAT_3\", STREAMED_SOUND_CUTSCENE_HAT_3 },\n\t{ \"ICE_1\", STREAMED_SOUND_CUTSCENE_ICE_1 },\n\t{ \"INT_A\", STREAMED_SOUND_CUTSCENE_INT_A },\n\t{ \"INT_B\", STREAMED_SOUND_CUTSCENE_INT_B },\n\t{ \"INT_D\", STREAMED_SOUND_CUTSCENE_INT_D },\n\t{ \"INT_M\", STREAMED_SOUND_CUTSCENE_INT_M },\n\t{ \"LAW_1A\", STREAMED_SOUND_CUTSCENE_LAW_1A },\n\t{ \"LAW_1B\", STREAMED_SOUND_CUTSCENE_LAW_1B },\n\t{ \"LAW_2A\", STREAMED_SOUND_CUTSCENE_LAW_2A },\n\t{ \"LAW_2B\", STREAMED_SOUND_CUTSCENE_LAW_2B },\n\t{ \"LAW_2C\", STREAMED_SOUND_CUTSCENE_LAW_2C },\n\t{ \"LAW_3\", STREAMED_SOUND_CUTSCENE_LAW_3 },\n\t{ \"LAW_4\", STREAMED_SOUND_CUTSCENE_LAW_4 },\n\t{ \"PHIL_1\", STREAMED_SOUND_CUTSCENE_PHIL_1 },\n\t{ \"PHIL_2\", STREAMED_SOUND_CUTSCENE_PHIL_2 },\n\t{ \"PORN_1\", STREAMED_SOUND_CUTSCENE_PORN_1 },\n\t{ \"PORN_2\", STREAMED_SOUND_CUTSCENE_PORN_2 },\n\t{ \"PORN_3\", STREAMED_SOUND_CUTSCENE_PORN_3 },\n\t{ \"PORN_4\", STREAMED_SOUND_CUTSCENE_PORN_4 },\n\t{ \"RESC_1A\", STREAMED_SOUND_CUTSCENE_RESC_1A },\n\t{ \"ROK_1\", STREAMED_SOUND_CUTSCENE_ROK_1 },\n\t{ \"ROK_2\", STREAMED_SOUND_CUTSCENE_ROK_2 },\n\t{ \"ROK_3A\", STREAMED_SOUND_CUTSCENE_ROK_3A },\n\t{ \"STRIPA\", STREAMED_SOUND_CUTSCENE_STRIPA },\n\t{ \"TAX_1\", STREAMED_SOUND_CUTSCENE_TAX_1 },\n\t{ \"TEX_1\", STREAMED_SOUND_CUTSCENE_TEX_1 },\n\t{ \"TEX_2\", STREAMED_SOUND_CUTSCENE_TEX_2 },\n\t{ \"TEX_3\", STREAMED_SOUND_CUTSCENE_TEX_3 },\n\t{ \"GSPOT\", STREAMED_SOUND_CUTSCENE_GLIGHT },\n\t{ \"FIST\", STREAMED_SOUND_CUTSCENE_FIST },\n\t{ \"EL_PH1\", STREAMED_SOUND_CUTSCENE_ELBURRO1_PH1 },\n\t{ \"EL_PH2\", STREAMED_SOUND_CUTSCENE_ELBURRO2_PH2 },\n\t{ NULL, 0 }\n};\n\nint\nFindCutsceneAudioTrackId(const char *szCutsceneName)\n{\n\tfor (int i = 0; musicNameIdAssoc[i].szTrackName; i++) {\n\t\tif (!CGeneral::faststricmp(musicNameIdAssoc[i].szTrackName, szCutsceneName))\n\t\t\treturn musicNameIdAssoc[i].iTrackId;\n\t}\n\treturn -1;\n}\n\nbool CCutsceneMgr::ms_running;\nbool CCutsceneMgr::ms_cutsceneProcessing;\nCDirectory *CCutsceneMgr::ms_pCutsceneDir;\nCCutsceneObject *CCutsceneMgr::ms_pCutsceneObjects[NUMCUTSCENEOBJECTS];\nint32 CCutsceneMgr::ms_numCutsceneObjs;\nbool CCutsceneMgr::ms_loaded;\nbool CCutsceneMgr::ms_animLoaded;\nbool CCutsceneMgr::ms_useLodMultiplier;\nchar CCutsceneMgr::ms_cutsceneName[CUTSCENENAMESIZE];\nCAnimBlendAssocGroup CCutsceneMgr::ms_cutsceneAssociations;\nCVector CCutsceneMgr::ms_cutsceneOffset;\nfloat CCutsceneMgr::ms_cutsceneTimer;\nbool CCutsceneMgr::ms_wasCutsceneSkipped;\nuint32 CCutsceneMgr::ms_cutsceneLoadStatus;\nbool CCutsceneMgr::ms_useCutsceneShadows = true;\n\nbool bCamLoaded;\nbool bIsEverythingRemovedFromTheWorldForTheBiggestFuckoffCutsceneEver; // pls don't shrink the name :P\nint32 NumberOfSavedWeapons;\neWeaponType SavedWeaponIDs[TOTAL_WEAPON_SLOTS];\nint32 SavedWeaponAmmo[TOTAL_WEAPON_SLOTS];\nchar uncompressedAnims[8][32];\nuint32 numUncompressedAnims;\n\n\nRpAtomic *\nCalculateBoundingSphereRadiusCB(RpAtomic *atomic, void *data)\n{\n\tfloat radius = RpAtomicGetBoundingSphere(atomic)->radius;\n\tRwV3d center = RpAtomicGetBoundingSphere(atomic)->center;\n\n\tfor (RwFrame *frame = RpAtomicGetFrame(atomic); RwFrameGetParent(frame); frame = RwFrameGetParent(frame))\n\t\tRwV3dTransformPoints(&center, &center, 1, RwFrameGetMatrix(frame));\n\n\tfloat size = RwV3dLength(&center) + radius;\n\tif (size > *(float *)data)\n\t\t*(float *)data = size;\n\treturn atomic;\n}\n\nvoid\nCCutsceneMgr::Initialise(void)\n{\n\tms_numCutsceneObjs = 0;\n\tms_loaded = false;\n\tms_wasCutsceneSkipped = false;\n\tms_running = false;\n\tms_useLodMultiplier = false;\n\tms_animLoaded = false;\n\tms_cutsceneProcessing = false;\n\n\tms_pCutsceneDir = new CDirectory(CUTSCENEDIRSIZE);\n\tms_pCutsceneDir->ReadDirFile(\"ANIM\\\\CUTS.DIR\");\n\n\tnumUncompressedAnims = 0;\n\tuncompressedAnims[0][0] = '\\0';\n}\n\nvoid\nCCutsceneMgr::Shutdown(void)\n{\n\tdelete ms_pCutsceneDir;\n}\n\nvoid\nCCutsceneMgr::LoadCutsceneData(const char *szCutsceneName)\n{\n\tint file;\n\tuint32 size;\n\tuint32 offset;\n\tCPlayerPed *pPlayerPed;\n\n\tms_cutsceneProcessing = true;\n\tms_wasCutsceneSkipped = false;\n\tCTimer::Suspend();\n\tif (!bIsEverythingRemovedFromTheWorldForTheBiggestFuckoffCutsceneEver)\n\t\tCStreaming::RemoveCurrentZonesModels();\n\n\tms_pCutsceneDir->numEntries = 0;\n\tms_pCutsceneDir->ReadDirFile(\"ANIM\\\\CUTS.DIR\");\n\n\tCStreaming::RemoveUnusedModelsInLoadedList();\n\tCGame::DrasticTidyUpMemory(true);\n\n\tstrcpy(ms_cutsceneName, szCutsceneName);\n\n\tRwStream *stream;\n\tstream = RwStreamOpen(rwSTREAMFILENAME, rwSTREAMREAD, \"ANIM\\\\CUTS.IMG\");\n\tassert(stream);\n\n\t// Load animations\n\tsprintf(gString, \"%s.IFP\", szCutsceneName);\n\tif (ms_pCutsceneDir->FindItem(gString, offset, size)) {\n\t\tCStreaming::MakeSpaceFor(size << 11);\n\t\tCStreaming::ImGonnaUseStreamingMemory();\n\t\tRwStreamSkip(stream,  offset << 11);\n\t\tCAnimManager::LoadAnimFile(stream, true, uncompressedAnims);\n\t\tms_cutsceneAssociations.CreateAssociations(szCutsceneName);\n\t\tCStreaming::IHaveUsedStreamingMemory();\n\t\tms_animLoaded = true;\n\t} else {\n\t\tms_animLoaded = false;\n\t}\n\tRwStreamClose(stream, nil);\n\n\t// Load camera data\n\tfile = CFileMgr::OpenFile(\"ANIM\\\\CUTS.IMG\", \"rb\");\n\tsprintf(gString, \"%s.DAT\", szCutsceneName);\n\tif (ms_pCutsceneDir->FindItem(gString, offset, size)) {\n\t\tCStreaming::ImGonnaUseStreamingMemory();\n\t\tCFileMgr::Seek(file, offset << 11, SEEK_SET);\n\t\tTheCamera.LoadPathSplines(file);\n\t\tCStreaming::IHaveUsedStreamingMemory();\n\t\tbCamLoaded = true;\n\t} else {\n\t\tbCamLoaded = false;\n\t}\n\n\tCFileMgr::CloseFile(file);\n\n\tif (CGeneral::faststricmp(ms_cutsceneName, \"finale\")) {\n\t\tDMAudio.ChangeMusicMode(MUSICMODE_CUTSCENE);\n\t\tint trackId = FindCutsceneAudioTrackId(szCutsceneName);\n\t\tif (trackId != -1) {\n\t\t\tprintf(\"Start preload audio %s\\n\", szCutsceneName);\n\t\t\tDMAudio.PreloadCutSceneMusic(trackId);\n\t\t\tprintf(\"End preload audio %s\\n\", szCutsceneName);\n\t\t}\n\t}\n\n\tms_cutsceneTimer = 0.0f;\n\tms_loaded = true;\n\tms_cutsceneOffset = CVector(0.0f, 0.0f, 0.0f);\n\n\tpPlayerPed = FindPlayerPed();\n\tpPlayerPed->m_pWanted->ClearQdCrimes();\n\tpPlayerPed->bIsVisible = false;\n\tpPlayerPed->m_fCurrentStamina = pPlayerPed->m_fMaxStamina;\n\tCPad::GetPad(0)->SetDisablePlayerControls(PLAYERCONTROL_CUTSCENE);\n\tCWorld::Players[CWorld::PlayerInFocus].MakePlayerSafe(true);\n\n\tCTimer::Resume();\n}\n\nvoid\nCCutsceneMgr::FinishCutscene()\n{\n\tms_wasCutsceneSkipped = true;\n\tif (bCamLoaded) {\n\t\tCCutsceneMgr::ms_cutsceneTimer = TheCamera.GetCutSceneFinishTime() * 0.001f;\n\t\tTheCamera.FinishCutscene();\n\t}\n\n\tFindPlayerPed()->bIsVisible = true;\n\tCWorld::Players[CWorld::PlayerInFocus].MakePlayerSafe(false);\n}\n\nvoid\nCCutsceneMgr::SetupCutsceneToStart(void)\n{\n\tif (bCamLoaded) {\n\t\tTheCamera.SetCamCutSceneOffSet(ms_cutsceneOffset);\n\t\tTheCamera.TakeControlWithSpline(JUMP_CUT);\n\t\tTheCamera.SetWideScreenOn();\n\t}\n\n\tms_cutsceneOffset.z++;\n\n\tfor (int i = ms_numCutsceneObjs - 1; i >= 0; i--) {\n\t\tassert(RwObjectGetType(ms_pCutsceneObjects[i]->m_rwObject) == rpCLUMP);\n\t\tif (CAnimBlendAssociation *pAnimBlendAssoc = RpAnimBlendClumpGetFirstAssociation((RpClump*)ms_pCutsceneObjects[i]->m_rwObject)) {\n\t\t\tassert(pAnimBlendAssoc->hierarchy->sequences[0].HasTranslation());\n\t\t\tif (ms_pCutsceneObjects[i]->m_pAttachTo != nil) {\n\t\t\t\tpAnimBlendAssoc->flags &= (~ASSOC_HAS_TRANSLATION);\n\t\t\t} else {\n\t\t\t\tif (pAnimBlendAssoc->hierarchy->IsCompressed()){\n\t\t\t\t\tKeyFrameTransCompressed *keyFrames = ((KeyFrameTransCompressed*)pAnimBlendAssoc->hierarchy->sequences[0].GetKeyFrameCompressed(0));\n\t\t\t\t\tCVector trans;\n\t\t\t\t\tkeyFrames->GetTranslation(&trans);\n\t\t\t\t\tms_pCutsceneObjects[i]->SetPosition(ms_cutsceneOffset + trans);\n\t\t\t\t}else{\n\t\t\t\t\tKeyFrameTrans *keyFrames = ((KeyFrameTrans*)pAnimBlendAssoc->hierarchy->sequences[0].GetKeyFrame(0));\n\t\t\t\t\tms_pCutsceneObjects[i]->SetPosition(ms_cutsceneOffset + keyFrames->translation);\n\t\t\t\t}\n\t\t\t}\n\t\t\tpAnimBlendAssoc->SetRun();\n\t\t} else {\n\t\t\tms_pCutsceneObjects[i]->SetPosition(ms_cutsceneOffset);\n\t\t}\n\t\tCWorld::Add(ms_pCutsceneObjects[i]);\n\t\tif (RwObjectGetType(ms_pCutsceneObjects[i]->m_rwObject) == rpCLUMP) {\n\t\t\tms_pCutsceneObjects[i]->UpdateRpHAnim();\n\t\t}\n\t}\n\n\tCTimer::Update();\n\tCTimer::Update();\n\tms_running = true;\n\tms_cutsceneTimer = 0.0f;\n}\n\nvoid\nCCutsceneMgr::SetCutsceneAnim(const char *animName, CObject *pObject)\n{\n\tCAnimBlendAssociation *pNewAnim;\n\tCAnimBlendClumpData *pAnimBlendClumpData;\n\n\tassert(RwObjectGetType(pObject->m_rwObject) == rpCLUMP);\n\tdebug(\"Give cutscene anim %s\\n\", animName);\n\tRpAnimBlendClumpRemoveAllAssociations((RpClump*)pObject->m_rwObject);\n\n\tpNewAnim = ms_cutsceneAssociations.GetAnimation(animName);\n\tif (!pNewAnim) {\n\t\tdebug(\"\\n\\nHaven't I told you I can't find the fucking animation %s\\n\\n\\n\", animName);\n\t\treturn;\n\t}\n\n\tif (pNewAnim->hierarchy->IsCompressed())\n\t\tpNewAnim->hierarchy->keepCompressed = true;\n\n\tCStreaming::ImGonnaUseStreamingMemory();\n\tpNewAnim = ms_cutsceneAssociations.CopyAnimation(animName);\n\tCStreaming::IHaveUsedStreamingMemory();\n\n\tpNewAnim->SetCurrentTime(0.0f);\n\tpNewAnim->flags |= ASSOC_HAS_TRANSLATION;\n\tpNewAnim->flags &= ~ASSOC_RUNNING;\n\n\tpAnimBlendClumpData = *RPANIMBLENDCLUMPDATA(pObject->m_rwObject);\n\tpAnimBlendClumpData->link.Prepend(&pNewAnim->link);\n\n\tif (pNewAnim->hierarchy->keepCompressed)\n\t\tpAnimBlendClumpData->frames->flag |= AnimBlendFrameData::COMPRESSED;\n}\n\nvoid\nCCutsceneMgr::SetCutsceneAnimToLoop(const char* animName)\n{\n\tms_cutsceneAssociations.GetAnimation(animName)->flags |= ASSOC_REPEAT;\n}\n\nCCutsceneHead *\nCCutsceneMgr::AddCutsceneHead(CObject *pObject, int modelId)\n{\n\treturn nil;\n}\n\nvoid UpdateCutsceneObjectBoundingBox(RpClump* clump, int modelId)\n{\n\tif (modelId >= MI_CUTOBJ01 && modelId <= MI_CUTOBJ05) {\n\t\tCColModel* pColModel = &CTempColModels::ms_colModelCutObj[modelId - MI_CUTOBJ01];\n\t\tfloat radius = 0.0f;\n\t\tRpClumpForAllAtomics(clump, CalculateBoundingSphereRadiusCB, &radius);\n\t\tpColModel->boundingSphere.radius = radius;\n\t\tpColModel->boundingBox.min = CVector(-radius, -radius, -radius);\n\t\tpColModel->boundingBox.max = CVector(radius, radius, radius);\n\t}\n}\n\nCCutsceneObject *\nCCutsceneMgr::CreateCutsceneObject(int modelId)\n{\n\tCBaseModelInfo *pModelInfo;\n\tCColModel *pColModel;\n\tCCutsceneObject *pCutsceneObject;\n\n\tCStreaming::ImGonnaUseStreamingMemory();\n\tdebug(\"Created cutscene object %s\\n\", CModelInfo::GetModelInfo(modelId)->GetModelName());\n\tif (modelId >= MI_CUTOBJ01 && modelId <= MI_CUTOBJ05) {\n\t\tpModelInfo = CModelInfo::GetModelInfo(modelId);\n\t\tpColModel = &CTempColModels::ms_colModelCutObj[modelId - MI_CUTOBJ01];\n\t\tpModelInfo->SetColModel(pColModel);\n\t\tUpdateCutsceneObjectBoundingBox((RpClump*)pModelInfo->GetRwObject(), modelId);\n\t} else if (modelId >= MI_SPECIAL01 && modelId <= MI_SPECIAL21) {\n\t\tpModelInfo = CModelInfo::GetModelInfo(modelId);\n\t\tif (pModelInfo->GetColModel() == &CTempColModels::ms_colModelPed1) {\n\t\t\tCColModel *colModel = new CColModel();\n\t\t\tcolModel->boundingSphere.radius = 2.0f;\n\t\t\tcolModel->boundingSphere.center = CVector(0.0f, 0.0f, 0.0f);\n\t\t\tpModelInfo->SetColModel(colModel, true);\n\t\t}\n\t\tpColModel = pModelInfo->GetColModel();\n\t\tfloat radius = 2.0f;\n\t\tpColModel->boundingSphere.radius = radius;\n\t\tpColModel->boundingBox.min = CVector(-radius, -radius, -radius);\n\t\tpColModel->boundingBox.max = CVector(radius, radius, radius);\n\t}\n\n\tpCutsceneObject = new CCutsceneObject();\n\tpCutsceneObject->SetModelIndex(modelId);\n\tif (ms_useCutsceneShadows)\n\t\tpCutsceneObject->CreateShadow();\n\tms_pCutsceneObjects[ms_numCutsceneObjs++] = pCutsceneObject;\n\tCStreaming::IHaveUsedStreamingMemory();\n\treturn pCutsceneObject;\n}\n\nvoid\nCCutsceneMgr::DeleteCutsceneData(void)\n{\n\tif (!ms_loaded) return;\n\tCTimer::Suspend();\n\n\tms_cutsceneProcessing = false;\n\tms_useLodMultiplier = false;\n\tms_useCutsceneShadows = true;\n\n\tfor (--ms_numCutsceneObjs; ms_numCutsceneObjs >= 0; ms_numCutsceneObjs--) {\n\t\tCWorld::Remove(ms_pCutsceneObjects[ms_numCutsceneObjs]);\n\t\tms_pCutsceneObjects[ms_numCutsceneObjs]->DeleteRwObject();\n\t\tdelete ms_pCutsceneObjects[ms_numCutsceneObjs];\n\t\tms_pCutsceneObjects[ms_numCutsceneObjs] = nil;\n\t}\n\tms_numCutsceneObjs = 0;\n\n\tfor (int i = MI_SPECIAL01; i < MI_SPECIAL21; i++) {\n\t\tCBaseModelInfo *minfo = CModelInfo::GetModelInfo(i);\n\t\tCColModel *colModel = minfo->GetColModel();\n\t\tif (colModel != &CTempColModels::ms_colModelPed1) {\n\t\t\tdelete colModel;\n\t\t\tminfo->SetColModel(&CTempColModels::ms_colModelPed1);\n\t\t}\n\t}\n\n\tif (ms_animLoaded)\n\t\tCAnimManager::RemoveLastAnimFile();\n\n\tms_animLoaded = false;\n\tnumUncompressedAnims = 0;\n\tuncompressedAnims[0][0] = '\\0';\n\n\tif (bCamLoaded) {\n\t\tTheCamera.RestoreWithJumpCut();\n\t\tTheCamera.SetWideScreenOff();\n\t\tTheCamera.DeleteCutSceneCamDataMemory();\n\t}\n\tms_running = false;\n\tms_loaded = false;\n\n\tFindPlayerPed()->bIsVisible = true;\n\tCPad::GetPad(0)->SetEnablePlayerControls(PLAYERCONTROL_CUTSCENE);\n\tCWorld::Players[CWorld::PlayerInFocus].MakePlayerSafe(false);\n\n\tif (CGeneral::faststricmp(ms_cutsceneName, \"finale\")) {\n\t\tDMAudio.StopCutSceneMusic();\n\t\tDMAudio.ChangeMusicMode(MUSICMODE_GAME);\n\t}\n\n\tCStreaming::ms_disableStreaming = false;\n\tCWorld::bProcessCutsceneOnly = false;\n\n\tif(bCamLoaded)\n\t\tCGame::DrasticTidyUpMemory(TheCamera.GetScreenFadeStatus() == FADE_2);\n\t\n\tCPad::GetPad(0)->Clear(false);\n\tif (bIsEverythingRemovedFromTheWorldForTheBiggestFuckoffCutsceneEver) {\n\t\tCStreaming::LoadInitialPeds();\n\t\tCStreaming::LoadInitialWeapons();\n\t\tCStreaming::LoadInitialVehicles();\n\t\tbIsEverythingRemovedFromTheWorldForTheBiggestFuckoffCutsceneEver = false;\n\t\t\n\t\tCPlayerPed *pPlayerPed = FindPlayerPed();\n\t\tfor (int i = 0; i < NumberOfSavedWeapons; i++) {\n\t\t\tint32 weaponModelId = CWeaponInfo::GetWeaponInfo(SavedWeaponIDs[i])->m_nModelId;\n\t\t\tuint8 flags = CStreaming::ms_aInfoForModel[weaponModelId].m_flags;\n\t\t\tCStreaming::RequestModel(weaponModelId, STREAMFLAGS_DONT_REMOVE);\n\t\t\tCStreaming::LoadAllRequestedModels(false);\n\t\t\tif (CWeaponInfo::GetWeaponInfo(SavedWeaponIDs[i])->m_nModel2Id != -1) {\n\t\t\t\tCStreaming::RequestModel(CWeaponInfo::GetWeaponInfo(SavedWeaponIDs[i])->m_nModel2Id, 0);\n\t\t\t\tCStreaming::LoadAllRequestedModels(false);\n\t\t\t}\n\t\t\tif (!(flags & STREAMFLAGS_DONT_REMOVE))\n\t\t\t\tCStreaming::SetModelIsDeletable(weaponModelId);\n\t\t\tpPlayerPed->GiveWeapon(SavedWeaponIDs[i], SavedWeaponAmmo[i], true);\n\t\t}\n\t\tNumberOfSavedWeapons = 0;\n\t}\n\n\tCTimer::Resume();\n}\n\nvoid\nCCutsceneMgr::Update(void)\n{\n\tenum {\n\t\tCUTSCENE_LOADING_0 = 0,\n\t\tCUTSCENE_LOADING_AUDIO,\n\t\tCUTSCENE_LOADING_2,\n\t\tCUTSCENE_LOADING_3,\n\t\tCUTSCENE_LOADING_4\n\t};\n\n\tswitch (ms_cutsceneLoadStatus) {\n\tcase CUTSCENE_LOADING_AUDIO:\n\t\tSetupCutsceneToStart();\n\t\tif (CGeneral::faststricmp(ms_cutsceneName, \"finale\"))\n\t\t\tDMAudio.PlayPreloadedCutSceneMusic();\n\t\tms_cutsceneLoadStatus++;\n\t\tbreak;\n\tcase CUTSCENE_LOADING_2:\n\tcase CUTSCENE_LOADING_3:\n\t\tms_cutsceneLoadStatus++;\n\t\tbreak;\n\tcase CUTSCENE_LOADING_4:\n\t\tms_cutsceneLoadStatus = CUTSCENE_LOADING_0;\n\t\tbreak;\n\tdefault:\n\t\tbreak;\n\t}\n\n\tif (!ms_running) return;\n\n\tms_cutsceneTimer += CTimer::GetTimeStepNonClippedInSeconds();\n\n\tfor (int i = 0; i < ms_numCutsceneObjs; i++) {\n\t\tint modelId = ms_pCutsceneObjects[i]->GetModelIndex();\n\t\tif (modelId >= MI_CUTOBJ01 && modelId <= MI_CUTOBJ05)\n\t\t\tUpdateCutsceneObjectBoundingBox(ms_pCutsceneObjects[i]->GetClump(), modelId);\n\n\t\tif (ms_pCutsceneObjects[i]->m_pAttachTo != nil && modelId >= MI_SPECIAL01 && modelId <= MI_SPECIAL21)\n\t\t\tUpdateCutsceneObjectBoundingBox(ms_pCutsceneObjects[i]->GetClump(), modelId);\n\t}\n\n\tif (bCamLoaded)\n\t\tif (CGeneral::faststricmp(ms_cutsceneName, \"finale\") && TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_FLYBY && ms_cutsceneLoadStatus == CUTSCENE_LOADING_0) {\n\t\t\tif (CPad::GetPad(0)->GetCrossJustDown()\n\t\t\t\t|| (CGame::playingIntro && CPad::GetPad(0)->GetStartJustDown())\n\t\t\t\t|| CPad::GetPad(0)->GetLeftMouseJustDown()\n\t\t\t\t|| CPad::GetPad(0)->GetEnterJustDown()\n\t\t\t\t|| CPad::GetPad(0)->GetCharJustDown(' '))\n\t\t\t\t\tFinishCutscene();\n\t\t}\n}\n\nbool CCutsceneMgr::HasCutsceneFinished(void) { return !bCamLoaded || TheCamera.GetPositionAlongSpline() == 1.0f; }\n\nvoid\nCCutsceneMgr::LoadAnimationUncompressed(char const* name)\n{\n\tstrcpy(uncompressedAnims[numUncompressedAnims], name);\n\t\n\t// Because that's how CAnimManager knows the end of array\n\t++numUncompressedAnims;\n\tassert(numUncompressedAnims < ARRAY_SIZE(uncompressedAnims));\n\tuncompressedAnims[numUncompressedAnims][0] = '\\0';\n}\n\nvoid\nCCutsceneMgr::AttachObjectToParent(CObject *pObject, CEntity *pAttachTo)\n{\n\t((CCutsceneObject*)pObject)->m_pAttachmentObject = nil;\n\t((CCutsceneObject*)pObject)->m_pAttachTo = RpClumpGetFrame(pAttachTo->GetClump());\n\n\tdebug(\"Attach %s to %s\\n\", CModelInfo::GetModelInfo(pObject->GetModelIndex())->GetModelName(), CModelInfo::GetModelInfo(pAttachTo->GetModelIndex())->GetModelName());\n}\n\nvoid\nCCutsceneMgr::AttachObjectToFrame(CObject *pObject, CEntity *pAttachTo, const char *frame)\n{\n\t((CCutsceneObject*)pObject)->m_pAttachmentObject = nil;\n\t((CCutsceneObject*)pObject)->m_pAttachTo = RpAnimBlendClumpFindFrame(pAttachTo->GetClump(), frame)->frame;\n\tdebug(\"Attach %s to component %s of %s\\n\",\n\t\tCModelInfo::GetModelInfo(pObject->GetModelIndex())->GetModelName(),\n\t\tframe,\n\t\tCModelInfo::GetModelInfo(pAttachTo->GetModelIndex())->GetModelName());\n\tif (RwObjectGetType(pObject->m_rwObject) == rpCLUMP) {\n\t\tRpClump *clump = (RpClump*)pObject->m_rwObject;\n\t\tif (IsClumpSkinned(clump))\n\t\t\tRpAtomicGetBoundingSphere(GetFirstAtomic(clump))->radius *= 1.1f;\n\t}\n}\n\nvoid\nCCutsceneMgr::AttachObjectToBone(CObject *pObject, CObject *pAttachTo, int bone)\n{\n\tRpHAnimHierarchy *hanim = GetAnimHierarchyFromSkinClump(pAttachTo->GetClump());\n\tRwInt32 id = RpHAnimIDGetIndex(hanim, bone);\n\tRwMatrix *matrixArray = RpHAnimHierarchyGetMatrixArray(hanim);\n\t((CCutsceneObject*)pObject)->m_pAttachmentObject = pAttachTo;\n\t((CCutsceneObject*)pObject)->m_pAttachTo = &matrixArray[id];\n\tdebug(\"Attach %s to %s\\n\",\n\t\tCModelInfo::GetModelInfo(pObject->GetModelIndex())->GetModelName(),\n\t\tCModelInfo::GetModelInfo(pAttachTo->GetModelIndex())->GetModelName());\n}\n\nvoid\nCCutsceneMgr::RemoveEverythingFromTheWorldForTheBiggestFuckoffCutsceneEver()\n{\n\tCStreaming::ms_disableStreaming = true;\n\tCColStore::RemoveAllCollision();\n\tCWorld::bProcessCutsceneOnly = true;\n\tms_cutsceneProcessing = true;\n\n\tfor (int i = CPools::GetPedPool()->GetSize() - 1; i >= 0; i--) {\n\t\tCPed *pPed = CPools::GetPedPool()->GetSlot(i);\n\t\tif (pPed) {\n\t\t\tif (!pPed->IsPlayer() && pPed->CanBeDeleted()) {\n\t\t\t\tCWorld::Remove(pPed);\n\t\t\t\tdelete pPed;\n\t\t\t}\n\t\t}\n\t}\n\n\tfor (int i = CPools::GetVehiclePool()->GetSize() - 1; i >= 0; i--) {\n\t\tCVehicle *pVehicle = CPools::GetVehiclePool()->GetSlot(i);\n\t\tif (pVehicle) {\n\t\t\tif (pVehicle->CanBeDeleted()) {\n\t\t\t\tCWorld::Remove(pVehicle);\n\t\t\t\tdelete pVehicle;\n\t\t\t}\n\t\t}\n\t}\n\n\tbIsEverythingRemovedFromTheWorldForTheBiggestFuckoffCutsceneEver = true;\n\tCStreaming::RemoveCurrentZonesModels();\n\tCStreaming::SetModelIsDeletable(MI_MALE01);\n\tCStreaming::SetModelTxdIsDeletable(MI_MALE01);\n\tCStreaming::SetModelIsDeletable(MI_TAXI_D);\n\tCStreaming::SetModelTxdIsDeletable(MI_TAXI_D);\n\tCStreaming::SetModelIsDeletable(MI_NIGHTSTICK);\n\tCStreaming::SetModelTxdIsDeletable(MI_NIGHTSTICK);\n\tCStreaming::SetModelIsDeletable(MI_MISSILE);\n\tCStreaming::SetModelTxdIsDeletable(MI_MISSILE);\n\tCStreaming::SetModelIsDeletable(MI_POLICE);\n\tCStreaming::SetModelTxdIsDeletable(MI_POLICE);\n\n\twhile (CStreaming::RemoveLoadedVehicle()) ;\n\n\tCRadar::RemoveRadarSections();\n\n\tfor (int i = CPools::GetDummyPool()->GetSize() - 1; i >= 0; i--) {\n\t\tCDummy* pDummy = CPools::GetDummyPool()->GetSlot(i);\n\t\tif (pDummy)\n\t\t\tpDummy->DeleteRwObject();\n\t}\n\n\tfor (int i = CPools::GetObjectPool()->GetSize() - 1; i >= 0; i--) {\n\t\tCObject* pObject = CPools::GetObjectPool()->GetSlot(i);\n\t\tif (pObject)\n\t\t\tpObject->DeleteRwObject();\n\t}\n\n\tfor (int i = CPools::GetBuildingPool()->GetSize() - 1; i >= 0; i--) {\n\t\tCBuilding* pBuilding = CPools::GetBuildingPool()->GetSlot(i);\n\t\tif (pBuilding && pBuilding->m_rwObject != nil && pBuilding->bIsBIGBuilding && pBuilding->bStreamBIGBuilding) {\n\t\t\tif (pBuilding->bIsBIGBuilding)\n\t\t\t\tCStreaming::RequestModel(pBuilding->GetModelIndex(), 0);\n\t\t\tif (!pBuilding->bImBeingRendered)\n\t\t\t\tpBuilding->DeleteRwObject();\n\t\t}\n\t}\n\n\tCPlayerPed *pPlayerPed = FindPlayerPed();\n\tpPlayerPed->RemoveWeaponAnims(0, -1000.0f);\n\tNumberOfSavedWeapons = 0;\n\n\tfor (int i = 0; i < TOTAL_WEAPON_SLOTS; i++) {\n\t\tif (pPlayerPed->m_weapons[i].m_eWeaponType != WEAPONTYPE_UNARMED) {\n\t\t\tSavedWeaponIDs[NumberOfSavedWeapons] = pPlayerPed->m_weapons[i].m_eWeaponType;\n\t\t\tSavedWeaponAmmo[NumberOfSavedWeapons] = pPlayerPed->m_weapons[i].m_nAmmoTotal;\n\t\t\tNumberOfSavedWeapons++;\n\t\t}\n\t}\n\n\tpPlayerPed->ClearWeapons();\n\tCGame::DrasticTidyUpMemory(true);\n}"
  },
  {
    "path": "src/animation/CutsceneMgr.h",
    "content": "#pragma once\n#include \"CutsceneObject.h\"\n\n#define CUTSCENENAMESIZE 8\n\nclass CDirectory;\nclass CAnimBlendAssocGroup;\nclass CCutsceneHead;\n\nclass CCutsceneMgr\n{\n\tstatic bool ms_running;\n\tstatic CCutsceneObject *ms_pCutsceneObjects[NUMCUTSCENEOBJECTS];\n\t\n\tstatic int32 ms_numCutsceneObjs;\n\tstatic bool ms_loaded;\n\tstatic bool ms_animLoaded;\n\tstatic bool ms_useLodMultiplier;\n\n\tstatic char ms_cutsceneName[CUTSCENENAMESIZE];\n\tstatic CAnimBlendAssocGroup ms_cutsceneAssociations;\n\tstatic CVector ms_cutsceneOffset;\n\tstatic float ms_cutsceneTimer;\n\tstatic bool ms_wasCutsceneSkipped;\n\tstatic bool ms_cutsceneProcessing;\n\tstatic bool ms_useCutsceneShadows;\npublic:\n\tstatic CDirectory *ms_pCutsceneDir;\n\tstatic uint32 ms_cutsceneLoadStatus;\n\n\tstatic void StartCutsceneProcessing() { ms_cutsceneProcessing = true; }\n\tstatic bool IsRunning(void) { return ms_running; }\n\tstatic bool HasLoaded(void) { return ms_loaded; }\n\tstatic bool IsCutsceneProcessing(void) { return ms_cutsceneProcessing; }\n\tstatic bool WasCutsceneSkipped(void) { return ms_wasCutsceneSkipped; }\n\tstatic bool UseLodMultiplier(void) { return ms_useLodMultiplier; }\n\tstatic CCutsceneObject* GetCutsceneObject(int id) { return ms_pCutsceneObjects[id]; }\n\tstatic int GetCutsceneTimeInMilleseconds(void) { return 1000.0f * ms_cutsceneTimer; }\n\tstatic char *GetCutsceneName(void) { return ms_cutsceneName; }\n\tstatic void SetCutsceneOffset(const CVector& vec) { ms_cutsceneOffset = vec; }\n\tstatic bool HasCutsceneFinished(void);\n\n\tstatic void Initialise(void);\n\tstatic void Shutdown(void);\n\tstatic void LoadCutsceneData(const char *szCutsceneName);\n\tstatic void FinishCutscene(void);\n\tstatic void SetupCutsceneToStart(void);\n\tstatic void SetCutsceneAnim(const char *animName, CObject *pObject);\n\tstatic void SetCutsceneAnimToLoop(const char *animName);\n\tstatic CCutsceneHead *AddCutsceneHead(CObject *pObject, int modelId);\n\tstatic CCutsceneObject *CreateCutsceneObject(int modelId);\n\tstatic void DeleteCutsceneData(void);\n\tstatic void LoadAnimationUncompressed(char const*);\n\tstatic void Update(void);\n\n\tstatic void AttachObjectToParent(CObject *pObject, CEntity *pAttachTo);\n\tstatic void AttachObjectToFrame(CObject *pObject, CEntity *pAttachTo, const char *frame);\n\tstatic void AttachObjectToBone(CObject *pObject, CObject *pAttachTo, int frame);\n\tstatic void RemoveEverythingFromTheWorldForTheBiggestFuckoffCutsceneEver();\n\tstatic void DisableCutsceneShadows() { ms_useCutsceneShadows = false; }\n};\n"
  },
  {
    "path": "src/animation/FrameUpdate.cpp",
    "content": "#include \"common.h\"\n\n#include \"NodeName.h\"\n#include \"VisibilityPlugins.h\"\n#include \"AnimBlendClumpData.h\"\n#include \"AnimBlendAssociation.h\"\n#include \"RpAnimBlend.h\"\n\nCAnimBlendClumpData *gpAnimBlendClump;\n\n// PS2 names without \"NonSkinned\"\nvoid FrameUpdateCallBackNonSkinned(AnimBlendFrameData *frame, void *arg);\nvoid FrameUpdateCallBackWithVelocityExtractionNonSkinned(AnimBlendFrameData *frame, void *arg);\nvoid FrameUpdateCallBackWith3dVelocityExtractionNonSkinned(AnimBlendFrameData *frame, void *arg);\n\nvoid FrameUpdateCallBackSkinned(AnimBlendFrameData *frame, void *arg);\nvoid FrameUpdateCallBackWithVelocityExtractionSkinned(AnimBlendFrameData *frame, void *arg);\nvoid FrameUpdateCallBackWith3dVelocityExtractionSkinned(AnimBlendFrameData *frame, void *arg);\n\nvoid FrameUpdateCallBackNonSkinnedCompressed(AnimBlendFrameData *frame, void *arg);\nvoid FrameUpdateCallBackSkinnedCompressed(AnimBlendFrameData *frame, void *arg);\n\nvoid\nFrameUpdateCallBackNonSkinned(AnimBlendFrameData *frame, void *arg)\n{\n\tCVector vec, pos(0.0f, 0.0f, 0.0f);\n\tCQuaternion q, rot(0.0f, 0.0f, 0.0f, 0.0f);\n\tfloat totalBlendAmount = 0.0f;\n\tRwMatrix *mat = RwFrameGetMatrix(frame->frame);\n\tCAnimBlendNode **node;\n\tAnimBlendFrameUpdateData *updateData = (AnimBlendFrameUpdateData*)arg;\n\n\tif(frame->flag & AnimBlendFrameData::VELOCITY_EXTRACTION &&\n\t   gpAnimBlendClump->velocity2d){\n\t\tif(frame->flag & AnimBlendFrameData::VELOCITY_EXTRACTION_3D)\n\t\t\tFrameUpdateCallBackWith3dVelocityExtractionNonSkinned(frame, arg);\n\t\telse\n\t\t\tFrameUpdateCallBackWithVelocityExtractionNonSkinned(frame, arg);\n\t\treturn;\n\t}\n\n\tif(updateData->foobar)\n\t\tfor(node = updateData->nodes; *node; node++)\n\t\t\tif((*node)->sequence && (*node)->association->IsPartial())\n\t\t\t\ttotalBlendAmount += (*node)->association->blendAmount;\n\n\tfor(node = updateData->nodes; *node; node++){\n\t\tif((*node)->sequence){\n\t\t\t(*node)->Update(vec, q, 1.0f-totalBlendAmount);\n\t\t\tif((*node)->sequence->HasTranslation())\n\t\t\t\tpos += vec;\n#ifdef FIX_BUGS\n\t\t\tif(DotProduct(rot, q) < 0.0f)\n\t\t\t\trot -= q;\n\t\t\telse\n#endif\n\t\t\t\trot += q;\n\t\t}\n\t\t++*node;\n\t}\n\n\tif((frame->flag & AnimBlendFrameData::IGNORE_ROTATION) == 0){\n\t\tRwMatrixSetIdentity(mat);\n\t\trot.Normalise();\n\t\trot.Get(mat);\n\t}\n\n\tif((frame->flag & AnimBlendFrameData::IGNORE_TRANSLATION) == 0){\n\t\tmat->pos.x = pos.x;\n\t\tmat->pos.y = pos.y;\n\t\tmat->pos.z = pos.z;\n\t\tmat->pos.x += frame->resetPos.x;\n\t\tmat->pos.y += frame->resetPos.y;\n\t\tmat->pos.z += frame->resetPos.z;\n\t}\n\tRwMatrixUpdate(mat);\n}\n\nvoid\nFrameUpdateCallBackWithVelocityExtractionNonSkinned(AnimBlendFrameData *frame, void *arg)\n{\n\tCVector vec, pos(0.0f, 0.0f, 0.0f);\n\tCQuaternion q, rot(0.0f, 0.0f, 0.0f, 0.0f);\n\tfloat totalBlendAmount = 0.0f;\n\tfloat transx = 0.0f, transy = 0.0f;\n\tfloat curx = 0.0f, cury = 0.0f;\n\tfloat endx = 0.0f, endy = 0.0f;\n\tbool looped = false;\n\tRwMatrix *mat = RwFrameGetMatrix(frame->frame);\n\tCAnimBlendNode **node;\n\tAnimBlendFrameUpdateData *updateData = (AnimBlendFrameUpdateData*)arg;\n\n\tif(updateData->foobar)\n\t\tfor(node = updateData->nodes; *node; node++)\n\t\t\tif((*node)->sequence && (*node)->association->IsPartial())\n\t\t\t\ttotalBlendAmount += (*node)->association->blendAmount;\n\n\tfor(node = updateData->nodes; *node; node++)\n\t\tif((*node)->sequence && (*node)->sequence->HasTranslation()){\n\t\t\tif((*node)->association->HasTranslation()){\n\t\t\t\t(*node)->GetCurrentTranslation(vec, 1.0f-totalBlendAmount);\n\t\t\t\tcury += vec.y;\n\t\t\t\tif((*node)->association->HasXTranslation())\n\t\t\t\t\tcurx += vec.x;\n\t\t\t}\n\t\t}\n\n\tfor(node = updateData->nodes; *node; node++){\n\t\tif((*node)->sequence){\n\t\t\tbool nodelooped = (*node)->Update(vec, q, 1.0f-totalBlendAmount);\n#ifdef FIX_BUGS\n\t\t\tif(DotProduct(rot, q) < 0.0f)\n\t\t\t\trot -= q;\n\t\t\telse\n#endif\n\t\t\t\trot += q;\n\t\t\tif((*node)->sequence->HasTranslation()){\n\t\t\t\tpos += vec;\n\t\t\t\tif((*node)->association->HasTranslation()){\n\t\t\t\t\ttransy += vec.y;\n\t\t\t\t\tif((*node)->association->HasXTranslation())\n\t\t\t\t\t\ttransx += vec.x;\n\t\t\t\t\tlooped |= nodelooped;\n\t\t\t\t\tif(nodelooped){\n\t\t\t\t\t\t(*node)->GetEndTranslation(vec, 1.0f-totalBlendAmount);\n\t\t\t\t\t\tendy += vec.y;\n\t\t\t\t\t\tif((*node)->association->HasXTranslation())\n\t\t\t\t\t\t\tendx += vec.x;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t++*node;\n\t}\n\n\tif((frame->flag & AnimBlendFrameData::IGNORE_ROTATION) == 0){\n\t\tRwMatrixSetIdentity(mat);\n\t\trot.Normalise();\n\t\trot.Get(mat);\n\t}\n\n\tif((frame->flag & AnimBlendFrameData::IGNORE_TRANSLATION) == 0){\n\t\tgpAnimBlendClump->velocity2d->x = transx - curx;\n\t\tgpAnimBlendClump->velocity2d->y = transy - cury;\n\t\tif(looped){\n\t\t\tgpAnimBlendClump->velocity2d->x += endx;\n\t\t\tgpAnimBlendClump->velocity2d->y += endy;\n\t\t}\n\t\tmat->pos.x = pos.x - transx;\n\t\tmat->pos.y = pos.y - transy;\n\t\tmat->pos.z = pos.z;\n\t\tif(mat->pos.z >= -0.8f) {\n\t\t\tif(mat->pos.z < -0.4f)\n\t\t\t\tmat->pos.z += (2.5f * mat->pos.z + 2.0f) * frame->resetPos.z;\n\t\t\telse\n\t\t\t\tmat->pos.z += frame->resetPos.z;\n\t\t}\n\t\tmat->pos.x += frame->resetPos.x;\n\t\tmat->pos.y += frame->resetPos.y;\n\t}\n\tRwMatrixUpdate(mat);\n}\n\n// original code uses do loops?\nvoid\nFrameUpdateCallBackWith3dVelocityExtractionNonSkinned(AnimBlendFrameData *frame, void *arg)\n{\n\tCVector vec, pos(0.0f, 0.0f, 0.0f);\n\tCQuaternion q, rot(0.0f, 0.0f, 0.0f, 0.0f);\n\tfloat totalBlendAmount = 0.0f;\n\tCVector trans(0.0f, 0.0f, 0.0f);\n\tCVector cur(0.0f, 0.0f, 0.0f);\n\tCVector end(0.0f, 0.0f, 0.0f);\n\tbool looped = false;\n\tRwMatrix *mat = RwFrameGetMatrix(frame->frame);\n\tCAnimBlendNode **node;\n\tAnimBlendFrameUpdateData *updateData = (AnimBlendFrameUpdateData*)arg;\n\n\tif(updateData->foobar)\n\t\tfor(node = updateData->nodes; *node; node++)\n\t\t\tif((*node)->sequence && (*node)->association->IsPartial())\n\t\t\t\ttotalBlendAmount += (*node)->association->blendAmount;\n\n\tfor(node = updateData->nodes; *node; node++)\n\t\tif((*node)->sequence && (*node)->sequence->HasTranslation()){\n\t\t\tif((*node)->association->HasTranslation()){\n\t\t\t\t(*node)->GetCurrentTranslation(vec, 1.0f-totalBlendAmount);\n\t\t\t\tcur += vec;\n\t\t\t}\n\t\t}\n\n\tfor(node = updateData->nodes; *node; node++){\n\t\tif((*node)->sequence){\n\t\t\tbool nodelooped = (*node)->Update(vec, q, 1.0f-totalBlendAmount);\n#ifdef FIX_BUGS\n\t\t\tif(DotProduct(rot, q) < 0.0f)\n\t\t\t\trot -= q;\n\t\t\telse\n#endif\n\t\t\t\trot += q;\n\t\t\tif((*node)->sequence->HasTranslation()){\n\t\t\t\tpos += vec;\n\t\t\t\tif((*node)->association->HasTranslation()){\n\t\t\t\t\ttrans += vec;\n\t\t\t\t\tlooped |= nodelooped;\n\t\t\t\t\tif(nodelooped){\n\t\t\t\t\t\t(*node)->GetEndTranslation(vec, 1.0f-totalBlendAmount);\n\t\t\t\t\t\tend += vec;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t++*node;\n\t}\n\n\tif((frame->flag & AnimBlendFrameData::IGNORE_ROTATION) == 0){\n\t\tRwMatrixSetIdentity(mat);\n\t\trot.Normalise();\n\t\trot.Get(mat);\n\t}\n\n\tif((frame->flag & AnimBlendFrameData::IGNORE_TRANSLATION) == 0){\n\t\t*gpAnimBlendClump->velocity3d = trans - cur;\n\t\tif(looped)\n\t\t\t*gpAnimBlendClump->velocity3d += end;\n\t\tmat->pos.x = (pos - trans).x + frame->resetPos.x;\n\t\tmat->pos.y = (pos - trans).y + frame->resetPos.y;\n\t\tmat->pos.z = (pos - trans).z + frame->resetPos.z;\n\t}\n\tRwMatrixUpdate(mat);\n}\n\nvoid\nFrameUpdateCallBackSkinned(AnimBlendFrameData *frame, void *arg)\n{\n\tCVector vec, pos(0.0f, 0.0f, 0.0f);\n\tfloat transBlendAmount = 0.0f;\n\tCQuaternion q, rot(0.0f, 0.0f, 0.0f, 0.0f);\n\tfloat totalBlendAmount = 0.0f;\n\tRpHAnimStdInterpFrame *xform = frame->hanimFrame;\n\tCAnimBlendNode **node;\n\tAnimBlendFrameUpdateData *updateData = (AnimBlendFrameUpdateData*)arg;\n\n\tif(frame->flag & AnimBlendFrameData::VELOCITY_EXTRACTION &&\n\t   gpAnimBlendClump->velocity2d){\n\t\tif(frame->flag & AnimBlendFrameData::VELOCITY_EXTRACTION_3D)\n\t\t\tFrameUpdateCallBackWith3dVelocityExtractionSkinned(frame, arg);\n\t\telse\n\t\t\tFrameUpdateCallBackWithVelocityExtractionSkinned(frame, arg);\n\t\treturn;\n\t}\n\n\tif(updateData->foobar)\n\t\tfor(node = updateData->nodes; *node; node++)\n\t\t\tif((*node)->sequence && (*node)->association->IsPartial())\n\t\t\t\ttotalBlendAmount += (*node)->association->blendAmount;\n\n\tfor(node = updateData->nodes; *node; node++){\n\t\tif((*node)->sequence){\n\t\t\t(*node)->Update(vec, q, 1.0f-totalBlendAmount);\n\t\t\tif((*node)->sequence->HasTranslation()){\n\t\t\t\tpos += vec;\n\t\t\t\ttransBlendAmount += (*node)->association->blendAmount;\n\t\t\t}\n\t\t\tif(DotProduct(rot, q) < 0.0f)\n\t\t\t\trot -= q;\n\t\t\telse\n\t\t\t\trot += q;\n\t\t}\n\t\t++*node;\n\t}\n\n\tif((frame->flag & AnimBlendFrameData::IGNORE_ROTATION) == 0){\n\t\trot.Normalise();\n\t\txform->q.imag.x = rot.x;\n\t\txform->q.imag.y = rot.y;\n\t\txform->q.imag.z = rot.z;\n\t\txform->q.real = rot.w;\n\t}\n\n\tif((frame->flag & AnimBlendFrameData::IGNORE_TRANSLATION) == 0){\n\t\txform->t.x = transBlendAmount*pos.x;\n\t\txform->t.y = transBlendAmount*pos.y;\n\t\txform->t.z = transBlendAmount*pos.z;\n\t\txform->t.x += (1.0f-transBlendAmount)*frame->resetPos.x;\n\t\txform->t.y += (1.0f-transBlendAmount)*frame->resetPos.y;\n\t\txform->t.z += (1.0f-transBlendAmount)*frame->resetPos.z;\n\t}\n}\n\nvoid\nFrameUpdateCallBackWithVelocityExtractionSkinned(AnimBlendFrameData *frame, void *arg)\n{\n\tCVector vec, pos(0.0f, 0.0f, 0.0f);\n\tCQuaternion q, rot(0.0f, 0.0f, 0.0f, 0.0f);\n\tfloat totalBlendAmount = 0.0f;\n\tfloat transx = 0.0f, transy = 0.0f;\n\tfloat curx = 0.0f, cury = 0.0f;\n\tfloat endx = 0.0f, endy = 0.0f;\n\tbool looped = false;\n\tRpHAnimStdInterpFrame *xform = frame->hanimFrame;\n\tCAnimBlendNode **node;\n\tAnimBlendFrameUpdateData *updateData = (AnimBlendFrameUpdateData*)arg;\n\n\tif(updateData->foobar)\n\t\tfor(node = updateData->nodes; *node; node++)\n\t\t\tif((*node)->sequence && (*node)->association->IsPartial())\n\t\t\t\ttotalBlendAmount += (*node)->association->blendAmount;\n\n\tfor(node = updateData->nodes; *node; node++)\n\t\tif((*node)->sequence && (*node)->sequence->HasTranslation()){\n\t\t\tif((*node)->association->HasTranslation()){\n\t\t\t\t(*node)->GetCurrentTranslation(vec, 1.0f-totalBlendAmount);\n\t\t\t\tcury += vec.y;\n\t\t\t\tif((*node)->association->HasXTranslation())\n\t\t\t\t\tcurx += vec.x;\n\t\t\t}\n\t\t}\n\n\tfor(node = updateData->nodes; *node; node++){\n\t\tif((*node)->sequence){\n\t\t\tbool nodelooped = (*node)->Update(vec, q, 1.0f-totalBlendAmount);\n\t\t\tif(DotProduct(rot, q) < 0.0f)\n\t\t\t\trot -= q;\n\t\t\telse\n\t\t\t\trot += q;\n\t\t\tif((*node)->sequence->HasTranslation()){\n\t\t\t\tpos += vec;\n\t\t\t\tif((*node)->association->HasTranslation()){\n\t\t\t\t\ttransy += vec.y;\n\t\t\t\t\tif((*node)->association->HasXTranslation())\n\t\t\t\t\t\ttransx += vec.x;\n\t\t\t\t\tlooped |= nodelooped;\n\t\t\t\t\tif(nodelooped){\n\t\t\t\t\t\t(*node)->GetEndTranslation(vec, 1.0f-totalBlendAmount);\n\t\t\t\t\t\tendy += vec.y;\n\t\t\t\t\t\tif((*node)->association->HasXTranslation())\n\t\t\t\t\t\t\tendx += vec.x;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t++*node;\n\t}\n\n\tif((frame->flag & AnimBlendFrameData::IGNORE_ROTATION) == 0){\n\t\trot.Normalise();\n\t\txform->q.imag.x = rot.x;\n\t\txform->q.imag.y = rot.y;\n\t\txform->q.imag.z = rot.z;\n\t\txform->q.real = rot.w;\n\t}\n\n\tif((frame->flag & AnimBlendFrameData::IGNORE_TRANSLATION) == 0){\n\t\tgpAnimBlendClump->velocity2d->x = transx - curx;\n\t\tgpAnimBlendClump->velocity2d->y = transy - cury;\n\t\tif(looped){\n\t\t\tgpAnimBlendClump->velocity2d->x += endx;\n\t\t\tgpAnimBlendClump->velocity2d->y += endy;\n\t\t}\n\t\txform->t.x = pos.x - transx;\n\t\txform->t.y = pos.y - transy;\n\t\txform->t.z = pos.z;\n\t\tif(xform->t.z >= -0.8f) {\n\t\t\tif(xform->t.z < -0.4f)\n\t\t\t\txform->t.z += (2.5f * xform->t.z + 2.0f) * frame->resetPos.z;\n\t\t\telse\n\t\t\t\txform->t.z += frame->resetPos.z;\n\t\t}\n\t\txform->t.x += frame->resetPos.x;\n\t\txform->t.y += frame->resetPos.y;\n\t}\n}\n\nvoid\nFrameUpdateCallBackWith3dVelocityExtractionSkinned(AnimBlendFrameData *frame, void *arg)\n{\n\tCVector vec, pos(0.0f, 0.0f, 0.0f);\n\tCQuaternion q, rot(0.0f, 0.0f, 0.0f, 0.0f);\n\tfloat totalBlendAmount = 0.0f;\n\tCVector trans(0.0f, 0.0f, 0.0f);\n\tCVector cur(0.0f, 0.0f, 0.0f);\n\tCVector end(0.0f, 0.0f, 0.0f);\n\tbool looped = false;\n\tRpHAnimStdInterpFrame *xform = frame->hanimFrame;\n\tCAnimBlendNode **node;\n\tAnimBlendFrameUpdateData *updateData = (AnimBlendFrameUpdateData*)arg;\n\n\tif(updateData->foobar)\n\t\tfor(node = updateData->nodes; *node; node++)\n\t\t\tif((*node)->sequence && (*node)->association->IsPartial())\n\t\t\t\ttotalBlendAmount += (*node)->association->blendAmount;\n\n\tfor(node = updateData->nodes; *node; node++)\n\t\tif((*node)->sequence && (*node)->sequence->HasTranslation()){\n\t\t\tif((*node)->association->HasTranslation()){\n\t\t\t\t(*node)->GetCurrentTranslation(vec, 1.0f-totalBlendAmount);\n\t\t\t\tcur += vec;\n\t\t\t}\n\t\t}\n\n\tfor(node = updateData->nodes; *node; node++){\n\t\tif((*node)->sequence){\n\t\t\tbool nodelooped = (*node)->Update(vec, q, 1.0f-totalBlendAmount);\n#ifdef FIX_BUGS\n\t\t\tif(DotProduct(rot, q) < 0.0f)\n\t\t\t\trot -= q;\n\t\t\telse\n#endif\n\t\t\t\trot += q;\n\t\t\tif((*node)->sequence->HasTranslation()){\n\t\t\t\tpos += vec;\n\t\t\t\tif((*node)->association->HasTranslation()){\n\t\t\t\t\ttrans += vec;\n\t\t\t\t\tlooped |= nodelooped;\n\t\t\t\t\tif(nodelooped){\n\t\t\t\t\t\t(*node)->GetEndTranslation(vec, 1.0f-totalBlendAmount);\n\t\t\t\t\t\tend += vec;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t++*node;\n\t}\n\n\tif((frame->flag & AnimBlendFrameData::IGNORE_ROTATION) == 0){\n\t\trot.Normalise();\n\t\txform->q.imag.x = rot.x;\n\t\txform->q.imag.y = rot.y;\n\t\txform->q.imag.z = rot.z;\n\t\txform->q.real = rot.w;\n\t}\n\n\tif((frame->flag & AnimBlendFrameData::IGNORE_TRANSLATION) == 0){\n\t\t*gpAnimBlendClump->velocity3d = trans - cur;\n\t\tif(looped)\n\t\t\t*gpAnimBlendClump->velocity3d += end;\n\t\txform->t.x = (pos - trans).x + frame->resetPos.x;\n\t\txform->t.y = (pos - trans).y + frame->resetPos.y;\n\t\txform->t.z = (pos - trans).z + frame->resetPos.z;\n\t}\n}\n\nvoid\nFrameUpdateCallBackOffscreen(AnimBlendFrameData *frame, void *arg)\n{\n\tif(frame->flag & AnimBlendFrameData::VELOCITY_EXTRACTION && gpAnimBlendClump->velocity2d)\n\t\tFrameUpdateCallBackWithVelocityExtractionSkinned(frame, arg);\n}\n\n\nvoid\nFrameUpdateCallBackNonSkinnedCompressed(AnimBlendFrameData *frame, void *arg)\n{\n\tCVector vec, pos(0.0f, 0.0f, 0.0f);\n\tCQuaternion q, rot(0.0f, 0.0f, 0.0f, 0.0f);\n\tfloat totalBlendAmount = 0.0f;\n\tCVector trans(0.0f, 0.0f, 0.0f);\n\tCVector cur(0.0f, 0.0f, 0.0f);\n\tCVector end(0.0f, 0.0f, 0.0f);\n\tbool looped = false;\n\tRwMatrix *mat = RwFrameGetMatrix(frame->frame);\n\tCAnimBlendNode **node;\n\tAnimBlendFrameUpdateData *updateData = (AnimBlendFrameUpdateData*)arg;\n\n\tif(frame->flag & AnimBlendFrameData::VELOCITY_EXTRACTION &&\n\t   gpAnimBlendClump->velocity2d){\n\t\tif(updateData->foobar)\n\t\t\tfor(node = updateData->nodes; *node; node++)\n\t\t\t\tif((*node)->sequence && (*node)->association->IsPartial())\n\t\t\t\t\ttotalBlendAmount += (*node)->association->blendAmount;\n\n\t\tfor(node = updateData->nodes; *node; node++)\n\t\t\tif((*node)->sequence && (*node)->sequence->HasTranslation()){\n\t\t\t\tif((*node)->association->HasTranslation()){\n\t\t\t\t\t(*node)->GetCurrentTranslationCompressed(vec, 1.0f-totalBlendAmount);\n\t\t\t\t\tcur += vec;\n\t\t\t\t}\n\t\t\t}\n\n\t\tfor(node = updateData->nodes; *node; node++){\n\t\t\tif((*node)->sequence){\n\t\t\t\tbool nodelooped = (*node)->UpdateCompressed(vec, q, 1.0f-totalBlendAmount);\n#ifdef FIX_BUGS\n\t\t\t\tif(DotProduct(rot, q) < 0.0f)\n\t\t\t\t\trot -= q;\n\t\t\t\telse\n#endif\n\t\t\t\t\trot += q;\n\t\t\t\tif((*node)->sequence->HasTranslation()){\n\t\t\t\t\tpos += vec;\n\t\t\t\t\tif((*node)->association->HasTranslation()){\n\t\t\t\t\t\ttrans += vec;\n\t\t\t\t\t\tlooped |= nodelooped;\n\t\t\t\t\t\tif(nodelooped){\n\t\t\t\t\t\t\t(*node)->GetEndTranslationCompressed(vec, 1.0f-totalBlendAmount);\n\t\t\t\t\t\t\tend += vec;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t++*node;\n\t\t}\n\n\t\tif((frame->flag & AnimBlendFrameData::IGNORE_ROTATION) == 0){\n\t\t\tRwMatrixSetIdentity(mat);\n\t\t\trot.Normalise();\n\t\t\trot.Get(mat);\n\t\t}\n\n\t\tif((frame->flag & AnimBlendFrameData::IGNORE_TRANSLATION) == 0){\n\t\t\t*gpAnimBlendClump->velocity3d = trans - cur;\n\t\t\tif(looped)\n\t\t\t\t*gpAnimBlendClump->velocity3d += end;\n\t\t\tmat->pos.x = (pos - trans).x + frame->resetPos.x;\n\t\t\tmat->pos.y = (pos - trans).y + frame->resetPos.y;\n\t\t\tmat->pos.z = (pos - trans).z + frame->resetPos.z;\n\t\t}\n\t\tRwMatrixUpdate(mat);\n\t}else{\n\t\tif(updateData->foobar)\n\t\t\tfor(node = updateData->nodes; *node; node++)\n\t\t\t\tif((*node)->sequence && (*node)->association->IsPartial())\n\t\t\t\t\ttotalBlendAmount += (*node)->association->blendAmount;\n\n\t\tfor(node = updateData->nodes; *node; node++){\n\t\t\tif((*node)->sequence){\n\t\t\t\t(*node)->UpdateCompressed(vec, q, 1.0f-totalBlendAmount);\n\t\t\t\tif((*node)->sequence->HasTranslation())\n\t\t\t\t\tpos += vec;\n#ifdef FIX_BUGS\n\t\t\t\tif(DotProduct(rot, q) < 0.0f)\n\t\t\t\t\trot -= q;\n\t\t\t\telse\n#endif\n\t\t\t\t\trot += q;\n\t\t\t}\n\t\t\t++*node;\n\t\t}\n\n\t\tif((frame->flag & AnimBlendFrameData::IGNORE_ROTATION) == 0){\n\t\t\tRwMatrixSetIdentity(mat);\n\t\t\trot.Normalise();\n\t\t\trot.Get(mat);\n\t\t}\n\n\t\tif((frame->flag & AnimBlendFrameData::IGNORE_TRANSLATION) == 0){\n\t\t\tmat->pos.x = pos.x;\n\t\t\tmat->pos.y = pos.y;\n\t\t\tmat->pos.z = pos.z;\n\t\t\tmat->pos.x += frame->resetPos.x;\n\t\t\tmat->pos.y += frame->resetPos.y;\n\t\t\tmat->pos.z += frame->resetPos.z;\n\t\t}\n\t\tRwMatrixUpdate(mat);\n\t}\n}\n\nvoid\nFrameUpdateCallBackSkinnedCompressed(AnimBlendFrameData *frame, void *arg)\n{\n\tCVector vec, pos(0.0f, 0.0f, 0.0f);\n\tCQuaternion q, rot(0.0f, 0.0f, 0.0f, 0.0f);\n\tfloat totalBlendAmount = 0.0f;\n\tCVector trans(0.0f, 0.0f, 0.0f);\n\tCVector cur(0.0f, 0.0f, 0.0f);\n\tCVector end(0.0f, 0.0f, 0.0f);\n\tbool looped = false;\n\tRpHAnimStdInterpFrame *xform = frame->hanimFrame;\n\tCAnimBlendNode **node;\n\tAnimBlendFrameUpdateData *updateData = (AnimBlendFrameUpdateData*)arg;\n\n\tif(frame->flag & AnimBlendFrameData::VELOCITY_EXTRACTION &&\n\t   gpAnimBlendClump->velocity2d){\n\t\tif(updateData->foobar)\n\t\t\tfor(node = updateData->nodes; *node; node++)\n\t\t\t\tif((*node)->sequence && (*node)->association->IsPartial())\n\t\t\t\t\ttotalBlendAmount += (*node)->association->blendAmount;\n\n\t\tfor(node = updateData->nodes; *node; node++)\n\t\t\tif((*node)->sequence && (*node)->sequence->HasTranslation()){\n\t\t\t\tif((*node)->association->HasTranslation()){\n\t\t\t\t\t(*node)->GetCurrentTranslationCompressed(vec, 1.0f-totalBlendAmount);\n\t\t\t\t\tcur += vec;\n\t\t\t\t}\n\t\t\t}\n\n\t\tfor(node = updateData->nodes; *node; node++){\n\t\t\tif((*node)->sequence){\n\t\t\t\tbool nodelooped = (*node)->UpdateCompressed(vec, q, 1.0f-totalBlendAmount);\n#ifdef FIX_BUGS\n\t\t\t\tif(DotProduct(rot, q) < 0.0f)\n\t\t\t\t\trot -= q;\n\t\t\t\telse\n#endif\n\t\t\t\t\trot += q;\n\t\t\t\tif((*node)->sequence->HasTranslation()){\n\t\t\t\t\tpos += vec;\n\t\t\t\t\tif((*node)->association->HasTranslation()){\n\t\t\t\t\t\ttrans += vec;\n\t\t\t\t\t\tlooped |= nodelooped;\n\t\t\t\t\t\tif(nodelooped){\n\t\t\t\t\t\t\t(*node)->GetEndTranslationCompressed(vec, 1.0f-totalBlendAmount);\n\t\t\t\t\t\t\tend += vec;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t++*node;\n\t\t}\n\n\t\tif((frame->flag & AnimBlendFrameData::IGNORE_ROTATION) == 0){\n\t\t\trot.Normalise();\n\t\t\txform->q.imag.x = rot.x;\n\t\t\txform->q.imag.y = rot.y;\n\t\t\txform->q.imag.z = rot.z;\n\t\t\txform->q.real = rot.w;\n\t\t}\n\n\t\tif((frame->flag & AnimBlendFrameData::IGNORE_TRANSLATION) == 0){\n\t\t\t*gpAnimBlendClump->velocity3d = trans - cur;\n\t\t\tif(looped)\n\t\t\t\t*gpAnimBlendClump->velocity3d += end;\n\t\t\txform->t.x = (pos - trans).x + frame->resetPos.x;\n\t\t\txform->t.y = (pos - trans).y + frame->resetPos.y;\n\t\t\txform->t.z = (pos - trans).z + frame->resetPos.z;\n\t\t}\n\t}else{\n\t\tfloat transBlendAmount = 0.0f;\n\n\t\tif(updateData->foobar)\n\t\t\tfor(node = updateData->nodes; *node; node++)\n\t\t\t\tif((*node)->sequence && (*node)->association->IsPartial())\n\t\t\t\t\ttotalBlendAmount += (*node)->association->blendAmount;\n\n\t\tfor(node = updateData->nodes; *node; node++){\n\t\t\tif((*node)->sequence){\n\t\t\t\t(*node)->UpdateCompressed(vec, q, 1.0f-totalBlendAmount);\n\t\t\t\tif((*node)->sequence->HasTranslation()){\n\t\t\t\t\tpos += vec;\n\t\t\t\t\ttransBlendAmount += (*node)->association->blendAmount;\n\t\t\t\t}\n\t\t\t\tif(DotProduct(rot, q) < 0.0f)\n\t\t\t\t\trot -= q;\n\t\t\t\telse\n\t\t\t\t\trot += q;\n\t\t\t}\n\t\t\t++*node;\n\t\t}\n\n\t\tif((frame->flag & AnimBlendFrameData::IGNORE_ROTATION) == 0){\n\t\t\trot.Normalise();\n\t\t\txform->q.imag.x = rot.x;\n\t\t\txform->q.imag.y = rot.y;\n\t\t\txform->q.imag.z = rot.z;\n\t\t\txform->q.real = rot.w;\n\t\t}\n\n\t\tif((frame->flag & AnimBlendFrameData::IGNORE_TRANSLATION) == 0){\n\t\t\txform->t.x = transBlendAmount*pos.x;\n\t\t\txform->t.y = transBlendAmount*pos.y;\n\t\t\txform->t.z = transBlendAmount*pos.z;\n\t\t\txform->t.x += (1.0f-transBlendAmount)*frame->resetPos.x;\n\t\t\txform->t.y += (1.0f-transBlendAmount)*frame->resetPos.y;\n\t\t\txform->t.z += (1.0f-transBlendAmount)*frame->resetPos.z;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/animation/RpAnimBlend.cpp",
    "content": "#include \"common.h\"\n\n#include \"RwHelper.h\"\n#include \"General.h\"\n#include \"NodeName.h\"\n#include \"VisibilityPlugins.h\"\n#include \"Bones.h\"\n#include \"AnimBlendClumpData.h\"\n#include \"AnimBlendHierarchy.h\"\n#include \"AnimBlendAssociation.h\"\n#include \"AnimManager.h\"\n#include \"RpAnimBlend.h\"\n#include \"PedModelInfo.h\"\n\nRwInt32 ClumpOffset;\n\nenum\n{\n\tID_RPANIMBLEND = MAKECHUNKID(rwVENDORID_ROCKSTAR, 0xFD),\n};\n\nvoid*\nAnimBlendClumpCreate(void *object, RwInt32 offsetInObject, RwInt32 sizeInObject)\n{\n\t*RWPLUGINOFFSET(CAnimBlendClumpData*, object, offsetInObject) = nil;\n\treturn object;\n}\n\nvoid*\nAnimBlendClumpDestroy(void *object, RwInt32 offsetInObject, RwInt32 sizeInObject)\n{\n\tCAnimBlendClumpData *data;\n\tdata = *RPANIMBLENDCLUMPDATA(object);\n\tif(data){\n\t\tRpAnimBlendClumpRemoveAllAssociations((RpClump*)object);\n\t\tdelete data;\n\t\t*RPANIMBLENDCLUMPDATA(object) = nil;\n\t}\n\treturn object;\n}\n\nvoid *AnimBlendClumpCopy(void *dstObject, const void *srcObject, RwInt32 offsetInObject, RwInt32 sizeInObject) { return nil; }\n\nbool\nRpAnimBlendPluginAttach(void)\n{\n\tClumpOffset = RpClumpRegisterPlugin(sizeof(CAnimBlendClumpData*), ID_RPANIMBLEND,\n\t\tAnimBlendClumpCreate, AnimBlendClumpDestroy, AnimBlendClumpCopy);\n\treturn ClumpOffset >= 0;\n}\n\nCAnimBlendAssociation*\nRpAnimBlendGetNextAssociation(CAnimBlendAssociation *assoc)\n{\n\tif(assoc->link.next)\n\t\treturn CAnimBlendAssociation::FromLink(assoc->link.next);\n\treturn nil;\n}\n\nCAnimBlendAssociation*\nRpAnimBlendGetNextAssociation(CAnimBlendAssociation *assoc, uint32 mask)\n{\n\tCAnimBlendLink *link;\n\tfor(link = assoc->link.next; link; link = link->next){\n\t\tassoc = CAnimBlendAssociation::FromLink(link);\n\t\tif(assoc->flags & mask)\n\t\t\treturn assoc;\n\t}\n\treturn nil;\n}\n\nvoid\nRpAnimBlendAllocateData(RpClump *clump)\n{\n\t*RPANIMBLENDCLUMPDATA(clump) = new CAnimBlendClumpData;\n}\n\n\nvoid\nRpAnimBlendClumpSetBlendDeltas(RpClump *clump, uint32 mask, float delta)\n{\n\tCAnimBlendClumpData *clumpData = *RPANIMBLENDCLUMPDATA(clump);\n\tfor(CAnimBlendLink *link = clumpData->link.next; link; link = link->next){\n\t\tCAnimBlendAssociation *assoc = CAnimBlendAssociation::FromLink(link);\n\t\tif(mask == 0 || (assoc->flags & mask))\n\t\t\tassoc->blendDelta = delta;\n\t}\n}\n\nvoid\nRpAnimBlendClumpRemoveAllAssociations(RpClump *clump)\n{\n\tRpAnimBlendClumpRemoveAssociations(clump, 0);\n}\n\nvoid\nRpAnimBlendClumpRemoveAssociations(RpClump *clump, uint32 mask)\n{\n\tCAnimBlendClumpData *clumpData = *RPANIMBLENDCLUMPDATA(clump);\n\tCAnimBlendLink *next;\n\tfor(CAnimBlendLink *link = clumpData->link.next; link; link = next){\n\t\tnext = link->next;\n\t\tCAnimBlendAssociation *assoc = CAnimBlendAssociation::FromLink(link);\n\t\tif(mask == 0 || (assoc->flags & mask))\n\t\t\tif(assoc)\n\t\t\t\tdelete assoc;\n\t}\n}\n\nRwFrame*\nFrameForAllChildrenCountCallBack(RwFrame *frame, void *data)\n{\n\tint *numFrames = (int*)data;\n\t(*numFrames)++;\n\tRwFrameForAllChildren(frame, FrameForAllChildrenCountCallBack, data);\n\treturn frame;\n}\n\nRwFrame*\nFrameForAllChildrenFillFrameArrayCallBack(RwFrame *frame, void *data)\n{\n\tAnimBlendFrameData **frames = (AnimBlendFrameData**)data;\n\t(*frames)->frame = frame;\n\t(*frames)++;\n\tRwFrameForAllChildren(frame, FrameForAllChildrenFillFrameArrayCallBack, frames);\n\treturn frame;\n}\n\n// FrameInitCallBack on PS2\nvoid\nFrameInitCBnonskin(AnimBlendFrameData *frameData, void*)\n{\n\tframeData->flag = 0;\n\tframeData->resetPos = *RwMatrixGetPos(RwFrameGetMatrix(frameData->frame));\n}\n\nvoid\nFrameInitCBskin(AnimBlendFrameData *frameData, void*)\n{\n\tframeData->flag = 0;\n}\n\nvoid\nRpAnimBlendClumpInitSkinned(RpClump *clump)\n{\n\tint i;\n\tRwV3d boneTab[64];\n\tCAnimBlendClumpData *clumpData;\n\tRpAtomic *atomic;\n\tRpSkin *skin;\n\tRpHAnimHierarchy *hier;\n\tint numBones;\n\n\tRpAnimBlendAllocateData(clump);\n\tclumpData = *RPANIMBLENDCLUMPDATA(clump);\n\tatomic = GetFirstAtomic(clump);\n\tassert(atomic);\n\tskin = RpSkinGeometryGetSkin(RpAtomicGetGeometry(atomic));\n\tassert(skin);\n\tnumBones = RpSkinGetNumBones(skin);\n\tclumpData->SetNumberOfBones(numBones);\n\thier = GetAnimHierarchyFromSkinClump(clump);\n\tassert(hier);\n\tmemset(boneTab, 0, sizeof(boneTab));\n\tSkinGetBonePositionsToTable(clump, boneTab);\n\n\tAnimBlendFrameData *frames = clumpData->frames;\n\tfor(i = 0; i < numBones; i++){\n\t\tframes[i].nodeID = HIERNODEID(hier, i);\n\t\tframes[i].resetPos = boneTab[i];\n#ifdef LIBRW\n\t\tframes[i].hanimFrame = (RpHAnimStdInterpFrame*)rpHANIMHIERARCHYGETINTERPFRAME(hier, i);\n#else\n\t\tframes[i].hanimFrame = (RpHAnimStdInterpFrame*)rtANIMGETINTERPFRAME(hier->currentAnim, i);\n#endif\n\t}\n\tclumpData->ForAllFrames(FrameInitCBskin, nil);\n\tclumpData->frames[0].flag |= AnimBlendFrameData::VELOCITY_EXTRACTION;\n}\n\nvoid\nRpAnimBlendClumpInitNotSkinned(RpClump *clump)\n{\n\tint numFrames = 0;\n\tCAnimBlendClumpData *clumpData;\n\tRwFrame *root;\n\tAnimBlendFrameData *frames;\n\n\tRpAnimBlendAllocateData(clump);\n\tclumpData = *RPANIMBLENDCLUMPDATA(clump);\n\troot = RpClumpGetFrame(clump);\n\tRwFrameForAllChildren(root, FrameForAllChildrenCountCallBack, &numFrames);\n\tclumpData->SetNumberOfFrames(numFrames);\n\tframes = clumpData->frames;\n\tRwFrameForAllChildren(root, FrameForAllChildrenFillFrameArrayCallBack, &frames);\n\tclumpData->ForAllFrames(FrameInitCBnonskin, nil);\n\tclumpData->frames[0].flag |= AnimBlendFrameData::VELOCITY_EXTRACTION;\n}\n\nvoid\nRpAnimBlendClumpInit(RpClump *clump)\n{\n\tif(IsClumpSkinned(clump))\n\t\tRpAnimBlendClumpInitSkinned(clump);\n\telse\n\t\tRpAnimBlendClumpInitNotSkinned(clump);\n}\n\nbool\nRpAnimBlendClumpIsInitialized(RpClump *clump)\n{\n\tCAnimBlendClumpData *clumpData = *RPANIMBLENDCLUMPDATA(clump);\n\treturn clumpData && clumpData->numFrames != 0;\n}\n\nCAnimBlendAssociation*\nRpAnimBlendClumpGetAssociation(RpClump *clump, uint32 id)\n{\n\tCAnimBlendClumpData *clumpData = *RPANIMBLENDCLUMPDATA(clump);\n\n\tif(clumpData == nil) return nil;\n\n\tfor(CAnimBlendLink *link = clumpData->link.next; link; link = link->next){\n\t\tCAnimBlendAssociation *assoc = CAnimBlendAssociation::FromLink(link);\n\t\tif(assoc->animId == id)\n\t\t\treturn assoc;\n\t}\n\treturn nil;\n}\n\nCAnimBlendAssociation*\nRpAnimBlendClumpGetMainAssociation(RpClump *clump, CAnimBlendAssociation **assocRet, float *blendRet)\n{\n\tCAnimBlendClumpData *clumpData = *RPANIMBLENDCLUMPDATA(clump);\n\n\tif(clumpData == nil) return nil;\n\n\tCAnimBlendAssociation *mainAssoc = nil;\n\tCAnimBlendAssociation *secondAssoc = nil;\n\tfloat mainBlend = 0.0f;\n\tfloat secondBlend = 0.0f;\n\tfor(CAnimBlendLink *link = clumpData->link.next; link; link = link->next){\n\t\tCAnimBlendAssociation *assoc = CAnimBlendAssociation::FromLink(link);\n\n\t\tif(assoc->IsPartial())\n\t\t\tcontinue;\n\n\t\tif(assoc->blendAmount > mainBlend){\n\t\t\tsecondBlend = mainBlend;\n\t\t\tmainBlend = assoc->blendAmount;\n\n\t\t\tsecondAssoc = mainAssoc;\n\t\t\tmainAssoc = assoc;\n\t\t}else if(assoc->blendAmount > secondBlend){\n\t\t\tsecondBlend = assoc->blendAmount;\n\t\t\tsecondAssoc = assoc;\n\t\t}\n\t}\n\tif(assocRet) *assocRet = secondAssoc;\n\tif(blendRet) *blendRet = secondBlend;\n\treturn mainAssoc;\n}\n\nCAnimBlendAssociation*\nRpAnimBlendClumpGetMainPartialAssociation(RpClump *clump)\n{\n\tCAnimBlendClumpData *clumpData = *RPANIMBLENDCLUMPDATA(clump);\n\n\tif(clumpData == nil) return nil;\n\n\tCAnimBlendAssociation *mainAssoc = nil;\n\tfloat mainBlend = 0.0f;\n\tfor(CAnimBlendLink *link = clumpData->link.next; link; link = link->next){\n\t\tCAnimBlendAssociation *assoc = CAnimBlendAssociation::FromLink(link);\n\n\t\tif(!assoc->IsPartial())\n\t\t\tcontinue;\n\n\t\tif(assoc->blendAmount > mainBlend){\n\t\t\tmainBlend = assoc->blendAmount;\n\t\t\tmainAssoc = assoc;\n\t\t}\n\t}\n\treturn mainAssoc;\n}\n\nCAnimBlendAssociation*\nRpAnimBlendClumpGetMainAssociation_N(RpClump *clump, int n)\n{\n\tint i;\n\tCAnimBlendClumpData *clumpData = *RPANIMBLENDCLUMPDATA(clump);\n\n\tif(clumpData == nil) return nil;\n\n\ti = 0;\n\tfor(CAnimBlendLink *link = clumpData->link.next; link; link = link->next){\n\t\tCAnimBlendAssociation *assoc = CAnimBlendAssociation::FromLink(link);\n\n\t\tif(assoc->IsPartial())\n\t\t\tcontinue;\n\n\t\tif(i == n)\n\t\t\treturn assoc;\n\t\ti++;\n\t}\n\treturn nil;\n}\n\nCAnimBlendAssociation*\nRpAnimBlendClumpGetMainPartialAssociation_N(RpClump *clump, int n)\n{\n\tint i;\n\tCAnimBlendClumpData *clumpData = *RPANIMBLENDCLUMPDATA(clump);\n\n\tif(clumpData == nil) return nil;\n\n\ti = 0;\n\tfor(CAnimBlendLink *link = clumpData->link.next; link; link = link->next){\n\t\tCAnimBlendAssociation *assoc = CAnimBlendAssociation::FromLink(link);\n\n\t\tif(!assoc->IsPartial())\n\t\t\tcontinue;\n\n\t\tif(i == n)\n\t\t\treturn assoc;\n\t\ti++;\n\t}\n\treturn nil;\n}\n\nCAnimBlendAssociation*\nRpAnimBlendClumpGetFirstAssociation(RpClump *clump, uint32 mask)\n{\n\tCAnimBlendClumpData *clumpData = *RPANIMBLENDCLUMPDATA(clump);\n\n\tif(clumpData == nil) return nil;\n\n\tfor(CAnimBlendLink *link = clumpData->link.next; link; link = link->next){\n\t\tCAnimBlendAssociation *assoc = CAnimBlendAssociation::FromLink(link);\n\t\tif(assoc->flags & mask)\n\t\t\treturn assoc;\n\t}\n\treturn nil;\n}\n\nCAnimBlendAssociation*\nRpAnimBlendClumpGetFirstAssociation(RpClump *clump)\n{\n\tCAnimBlendClumpData *clumpData = *RPANIMBLENDCLUMPDATA(clump);\n\tif(!RpAnimBlendClumpIsInitialized(clump))\n\t\treturn nil;\n\tif(clumpData->link.next)\n\t\treturn CAnimBlendAssociation::FromLink(clumpData->link.next);\n\treturn nil;\n}\n\n// FillFrameArrayCallBack on PS2\nvoid\nFillFrameArrayCBnonskin(AnimBlendFrameData *frame, void *arg)\n{\n\tAnimBlendFrameData **frames = (AnimBlendFrameData**)arg;\n\tframes[CVisibilityPlugins::GetFrameHierarchyId(frame->frame)] = frame;\n}\n\nvoid\nRpAnimBlendClumpFillFrameArraySkin(RpClump *clump, AnimBlendFrameData **frames)\n{\n\tint i;\n\tCAnimBlendClumpData *clumpData = *RPANIMBLENDCLUMPDATA(clump);\n\tRpHAnimHierarchy *hier = GetAnimHierarchyFromSkinClump(clump);\n\tfor(i = PED_MID; i < PED_NODE_MAX; i++)\n\t\tframes[i] = &clumpData->frames[RpHAnimIDGetIndex(hier, ConvertPedNode2BoneTag(i))];\n}\n\nvoid\nRpAnimBlendClumpFillFrameArray(RpClump *clump, AnimBlendFrameData **frames)\n{\n\tif(IsClumpSkinned(clump))\n\t\tRpAnimBlendClumpFillFrameArraySkin(clump, frames);\n\telse\n\t\t(*RPANIMBLENDCLUMPDATA(clump))->ForAllFrames(FillFrameArrayCBnonskin, frames);\n}\n\nAnimBlendFrameData *pFrameDataFound;\n\nvoid\nFrameFindByNameCBnonskin(AnimBlendFrameData *frame, void *arg)\n{\n\tchar *nodename = GetFrameNodeName(frame->frame);\n\tif(!CGeneral::faststricmp(nodename, (char*)arg))\n\t\tpFrameDataFound = frame;\n}\n\nvoid\nFrameFindByNameCBskin(AnimBlendFrameData *frame, void *arg)\n{\n\tconst char *name = ConvertBoneTag2BoneName(frame->nodeID);\n\tif(name && CGeneral::faststricmp(name, (char*)arg) == 0)\n\t\tpFrameDataFound = frame;\n}\n\nvoid\nFrameFindByBoneCB(AnimBlendFrameData *frame, void *arg)\n{\n\tif(frame->nodeID == (int32)(uintptr)arg)\n\t\tpFrameDataFound = frame;\n}\n\nAnimBlendFrameData*\nRpAnimBlendClumpFindFrame(RpClump *clump, const char *name)\n{\n\tpFrameDataFound = nil;\n\tif(IsClumpSkinned(clump))\n\t\t(*RPANIMBLENDCLUMPDATA(clump))->ForAllFrames(FrameFindByNameCBskin, (void*)name);\n\telse\n\t\t(*RPANIMBLENDCLUMPDATA(clump))->ForAllFrames(FrameFindByNameCBnonskin, (void*)name);\n\treturn pFrameDataFound;\n}\n\nAnimBlendFrameData*\nRpAnimBlendClumpFindBone(RpClump *clump, uint32 boneTag)\n{\n\tpFrameDataFound = nil;\n\t(*RPANIMBLENDCLUMPDATA(clump))->ForAllFrames(FrameFindByBoneCB, (void*)boneTag);\n\treturn pFrameDataFound;\n}\n\nvoid\nRpAnimBlendNodeUpdateKeyframes(AnimBlendFrameData *frames, AnimBlendFrameUpdateData *updateData, int32 numNodes)\n{\n\tCAnimBlendNode **node;\n\tint i;\n\n\tfor(node = updateData->nodes; *node; node++){\n\t\tCAnimBlendAssociation *a = (*node)->association;\n\t\tfor(i = 0; i < numNodes; i++)\n\t\t\tif((frames[i].flag & AnimBlendFrameData::VELOCITY_EXTRACTION) == 0 ||\n\t\t\t   gpAnimBlendClump->velocity2d == nil){\n\t\t\t\tif((*node)[i].sequence)\n\t\t\t\t\t(*node)[i].FindKeyFrame(a->currentTime - a->timeStep);\n\t\t\t}\n\t}\n}\n\n// TODO:\n// CAnimBlendClumpData::LoadFramesIntoSPR\n// CAnimBlendClumpData::ForAllFramesInSPR\nvoid\nRpAnimBlendClumpUpdateAnimations(RpClump *clump, float timeDelta, bool doRender)\n{\n\tint i;\n\tCAnimBlendAssociation *assoc;\n\tAnimBlendFrameUpdateData updateData;\n\tfloat totalLength = 0.0f;\n\tfloat totalBlend = 0.0f;\n\tCAnimBlendLink *link, *next;\n\tCAnimBlendClumpData *clumpData = *RPANIMBLENDCLUMPDATA(clump);\n\tgpAnimBlendClump = clumpData;\n\n\tif(clumpData->link.next == nil)\n\t\treturn;\n\n\t// Update blend and get node array\n\ti = 0;\n\tupdateData.foobar = 0;\n\tfor(link = clumpData->link.next; link; link = next){\n\t\tnext = link->next;\n\t\tassoc = CAnimBlendAssociation::FromLink(link);\n\t\tif(assoc->UpdateBlend(timeDelta)){\n\t\t\tif(assoc->hierarchy->sequences){\n\t\t\t\tCAnimManager::UncompressAnimation(assoc->hierarchy);\n\t\t\t\tif(i < 11)\n\t\t\t\t\tupdateData.nodes[i++] = assoc->GetNode(0);\n\t\t\t\tif(assoc->flags & ASSOC_MOVEMENT){\n\t\t\t\t\ttotalLength += assoc->hierarchy->totalLength/assoc->speed * assoc->blendAmount;\n\t\t\t\t\ttotalBlend += assoc->blendAmount;\n\t\t\t\t}else\n\t\t\t\t\tupdateData.foobar = 1;\n\t\t\t}else\n\t\t\t\tdebug(\"anim %s is not loaded\\n\", assoc->hierarchy->name);\n\t\t}\n\t}\n\n\tfor(link = clumpData->link.next; link; link = link->next){\n\t\tassoc = CAnimBlendAssociation::FromLink(link);\n\t\tassoc->UpdateTimeStep(timeDelta, totalLength == 0.0f ? 1.0f : totalBlend/totalLength);\n\t}\n\n\tupdateData.nodes[i] = nil;\n\n#ifdef ANIM_COMPRESSION\n\tif(clumpData->frames[0].flag & AnimBlendFrameData::COMPRESSED){\n\t\tif(IsClumpSkinned(clump))\n\t\t\tclumpData->ForAllFrames(FrameUpdateCallBackSkinnedCompressed, &updateData);\n\t\telse\n\t\t\tclumpData->ForAllFrames(FrameUpdateCallBackNonSkinnedCompressed, &updateData);\n\t}else\n#endif\n\tif(doRender){\n\t\tif(clumpData->frames[0].flag & AnimBlendFrameData::UPDATE_KEYFRAMES)\n\t\t\tRpAnimBlendNodeUpdateKeyframes(clumpData->frames, &updateData, clumpData->numFrames);\n\t\tif(IsClumpSkinned(clump))\n\t\t\tclumpData->ForAllFrames(FrameUpdateCallBackSkinned, &updateData);\n\t\telse\n\t\t\tclumpData->ForAllFrames(FrameUpdateCallBackNonSkinned, &updateData);\n\t\tclumpData->frames[0].flag &= ~AnimBlendFrameData::UPDATE_KEYFRAMES;\n\t}else{\n\t\tclumpData->ForAllFrames(FrameUpdateCallBackOffscreen, &updateData);\n\t\tclumpData->frames[0].flag |= AnimBlendFrameData::UPDATE_KEYFRAMES;\n\t}\n\n\tfor(link = clumpData->link.next; link; link = link->next){\n\t\tassoc = CAnimBlendAssociation::FromLink(link);\n\t\tassoc->UpdateTime(timeDelta, totalLength == 0.0f ? 1.0f : totalBlend/totalLength);\n\t}\n\tRwFrameUpdateObjects(RpClumpGetFrame(clump));\n}\n"
  },
  {
    "path": "src/animation/RpAnimBlend.h",
    "content": "#pragma once\n\nclass CAnimBlendNode;\nclass CAnimBlendAssociation;\nclass CAnimBlendClumpData;\nstruct AnimBlendFrameData;\n\nstruct AnimBlendFrameUpdateData\n{\n\tint foobar;\t// TODO: figure out what this actually means\n\tCAnimBlendNode *nodes[16];\n};\n\nextern RwInt32 ClumpOffset;\n#define RPANIMBLENDCLUMPDATA(o) (RWPLUGINOFFSET(CAnimBlendClumpData*, o, ClumpOffset))\n\nbool RpAnimBlendPluginAttach(void);\nCAnimBlendAssociation *RpAnimBlendGetNextAssociation(CAnimBlendAssociation *assoc);\nCAnimBlendAssociation *RpAnimBlendGetNextAssociation(CAnimBlendAssociation *assoc, uint32 mask);\nvoid RpAnimBlendAllocateData(RpClump *clump);\n\nvoid RpAnimBlendClumpSetBlendDeltas(RpClump *clump, uint32 mask, float delta);\nvoid RpAnimBlendClumpRemoveAllAssociations(RpClump *clump);\nvoid RpAnimBlendClumpRemoveAssociations(RpClump *clump, uint32 mask);\nvoid RpAnimBlendClumpInit(RpClump *clump);\nbool RpAnimBlendClumpIsInitialized(RpClump *clump);\nvoid RpAnimBlendClumpFillFrameArray(RpClump* clump, AnimBlendFrameData** frames);\nAnimBlendFrameData *RpAnimBlendClumpFindFrame(RpClump *clump, const char *name);\nAnimBlendFrameData *RpAnimBlendClumpFindBone(RpClump *clump, uint32 boneTag);\nvoid FillFrameArrayCallBack(AnimBlendFrameData *frame, void *arg);\nCAnimBlendAssociation *RpAnimBlendClumpGetAssociation(RpClump *clump, uint32 id);\nCAnimBlendAssociation *RpAnimBlendClumpGetMainAssociation(RpClump *clump, CAnimBlendAssociation **assocRet, float *blendRet);\nCAnimBlendAssociation *RpAnimBlendClumpGetMainPartialAssociation(RpClump *clump);\nCAnimBlendAssociation *RpAnimBlendClumpGetMainAssociation_N(RpClump *clump, int n);\nCAnimBlendAssociation *RpAnimBlendClumpGetMainPartialAssociation_N(RpClump *clump, int n);\nCAnimBlendAssociation *RpAnimBlendClumpGetFirstAssociation(RpClump *clump, uint32 mask);\nCAnimBlendAssociation *RpAnimBlendClumpGetFirstAssociation(RpClump *clump);\nvoid RpAnimBlendNodeUpdateKeyframes(AnimBlendFrameData *frames, AnimBlendFrameUpdateData *updateData, int32 numNodes);\nvoid RpAnimBlendClumpUpdateAnimations(RpClump* clump, float timeDelta, bool doRender = true);\n\n\nextern CAnimBlendClumpData *gpAnimBlendClump;\nvoid FrameUpdateCallBackNonSkinned(AnimBlendFrameData *frame, void *arg);\nvoid FrameUpdateCallBackSkinned(AnimBlendFrameData *frame, void *arg);\nvoid FrameUpdateCallBackOffscreen(AnimBlendFrameData *frame, void *arg);\n\nvoid FrameUpdateCallBackNonSkinnedCompressed(AnimBlendFrameData *frame, void *arg);\nvoid FrameUpdateCallBackSkinnedCompressed(AnimBlendFrameData *frame, void *arg);\n"
  },
  {
    "path": "src/audio/AudioCollision.cpp",
    "content": "#include \"common.h\"\n\n#include \"DMAudio.h\"\n#include \"Entity.h\"\n#include \"AudioCollision.h\"\n#include \"AudioManager.h\"\n#include \"AudioSamples.h\"\n#include \"SurfaceTable.h\"\n#include \"sampman.h\"\n\nconst int CollisionSoundIntensity = 60;\n\ncAudioCollisionManager::cAudioCollisionManager()\n{\n\tm_sQueue.m_pEntity1 = nil;\n\tm_sQueue.m_pEntity2 = nil;\n\tm_sQueue.m_bSurface1 = SURFACE_DEFAULT;\n\tm_sQueue.m_bSurface2 = SURFACE_DEFAULT;\n\tm_sQueue.m_fIntensity2 = 0.0f;\n\tm_sQueue.m_fIntensity1 = 0.0f;\n\tm_sQueue.m_vecPosition = CVector(0.0f, 0.0f, 0.0f);\n\n\tfor (int i = 0; i < NUMAUDIOCOLLISIONS; i++)\n\t\tm_bIndicesTable[i] = NUMAUDIOCOLLISIONS;\n\n\tm_bCollisionsInQueue = 0;\n}\n\nvoid\ncAudioCollisionManager::AddCollisionToRequestedQueue()\n{\n\tint32 collisionsIndex;\n\tint32 i;\n\n\n\tif (m_bCollisionsInQueue < NUMAUDIOCOLLISIONS)\n\t\tcollisionsIndex = m_bCollisionsInQueue++;\n\telse {\n\t\tcollisionsIndex = m_bIndicesTable[NUMAUDIOCOLLISIONS - 1];\n\t\tif (m_sQueue.m_fDistance >= m_asCollisions1[collisionsIndex].m_fDistance) return;\n\t}\n\n\tm_asCollisions1[collisionsIndex] = m_sQueue;\n\n\ti = 0;\n\tif(collisionsIndex) {\n\t\twhile(m_asCollisions1[m_bIndicesTable[i]].m_fDistance <= m_asCollisions1[collisionsIndex].m_fDistance) {\n\t\t\tif(++i >= collisionsIndex) {\n\t\t\t\tm_bIndicesTable[i] = collisionsIndex;\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\tmemmove(&m_bIndicesTable[i + 1], &m_bIndicesTable[i], NUMAUDIOCOLLISIONS - 1 - i);\n\t}\n\tm_bIndicesTable[i] = collisionsIndex;\n}\n\nfloat\ncAudioManager::GetCollisionLoopingRatio(uint32 a, uint32 b, float c) const\n{\n\treturn GetCollisionRatio(c, 0.0f, 0.02f, 0.02f);\n}\n\nfloat\ncAudioManager::GetCollisionOneShotRatio(int32 a, float b) const\n{\n\tfloat result;\n\n\tswitch(a) {\n\tcase SURFACE_DEFAULT:\n\tcase SURFACE_TARMAC:\n\tcase SURFACE_PAVEMENT:\n\tcase SURFACE_STEEP_CLIFF:\n\tcase SURFACE_TRANSPARENT_STONE:\n\tcase SURFACE_CONCRETE_BEACH: result = GetCollisionRatio(b, 10.f, 60.f, 50.f); break;\n\tcase SURFACE_GRASS:\n\tcase SURFACE_GRAVEL:\n\tcase SURFACE_MUD_DRY:\n\tcase SURFACE_CARDBOARDBOX: result = GetCollisionRatio(b, 0.f, 2.f, 2.f); break;\n\tcase SURFACE_CAR: result = GetCollisionRatio(b, 6.f, 50.f, 44.f); break;\n\tcase SURFACE_GLASS:\n\tcase SURFACE_METAL_CHAIN_FENCE: result = GetCollisionRatio(b, 0.1f, 10.f, 9.9f); break;\n\tcase SURFACE_TRANSPARENT_CLOTH:\n\tcase SURFACE_THICK_METAL_PLATE: result = GetCollisionRatio(b, 30.f, 130.f, 100.f); break;\n\tcase SURFACE_GARAGE_DOOR: result = GetCollisionRatio(b, 20.f, 100.f, 80.f); break;\n\tcase SURFACE_CAR_PANEL: result = GetCollisionRatio(b, 0.f, 4.f, 4.f); break;\n\tcase SURFACE_SCAFFOLD_POLE:\n\tcase SURFACE_METAL_GATE: \n\tcase SURFACE_LAMP_POST: result = GetCollisionRatio(b, 1.f, 10.f, 9.f); break;\n\tcase SURFACE_FIRE_HYDRANT: result = GetCollisionRatio(b, 1.f, 15.f, 14.f); break;\n\tcase SURFACE_GIRDER: result = GetCollisionRatio(b, 8.f, 50.f, 42.f); break;\n\tcase SURFACE_PED: result = GetCollisionRatio(b, 0.f, 20.f, 20.f); break;\n\tcase SURFACE_SAND:\n\tcase SURFACE_WATER:\n\tcase SURFACE_RUBBER:\n\tcase SURFACE_WHEELBASE:\n\tcase SURFACE_SAND_BEACH: result = GetCollisionRatio(b, 0.f, 10.f, 10.f); break;\n\tcase SURFACE_WOOD_CRATES: result = GetCollisionRatio(b, 1.f, 4.f, 3.f); break;\n\tcase SURFACE_WOOD_BENCH: result = GetCollisionRatio(b, 0.1f, 5.f, 4.9f); break;\n\tcase SURFACE_WOOD_SOLID: result = GetCollisionRatio(b, 0.1f, 40.f, 39.9f); break;\n\tcase SURFACE_PLASTIC: result = GetCollisionRatio(b, 0.1f, 4.f, 3.9f); break;\n\tcase SURFACE_HEDGE: result = GetCollisionRatio(b, 0.f, 0.5f, 0.5f); break;\n\tcase SURFACE_CONTAINER: result = GetCollisionRatio(b, 4.f, 40.f, 36.f); break;\n\tcase SURFACE_NEWS_VENDOR: result = GetCollisionRatio(b, 0.f, 5.f, 5.f); break;\n\tdefault: result = 0.f; break;\n\t}\n\n\treturn result;\n}\n\nfloat\ncAudioManager::GetCollisionRatio(float a, float b, float c, float d) const\n{\n\tfloat e;\n\te = a;\n\tif(a <= b) return 0.0f;\n\tif(c <= a) e = c;\n\treturn (e - b) / d;\n}\n\nuint32\ncAudioManager::SetLoopingCollisionRequestedSfxFreqAndGetVol(const cAudioCollision &audioCollision)\n{\n\tuint8 surface1 = audioCollision.m_bSurface1;\n\tuint8 surface2 = audioCollision.m_bSurface2;\n\tint32 vol;\n\tfloat ratio;\n\n\tif(surface1 == SURFACE_GRASS || surface2 == SURFACE_GRASS || surface1 == SURFACE_HEDGE ||\n\t   surface2 == SURFACE_HEDGE) {\n\t\tratio = GetCollisionRatio(audioCollision.m_fIntensity2, 0.0001f, 0.09f, 0.0899f);\n\t\tm_sQueueSample.m_nSampleIndex = SFX_RAIN;\n\t\tm_sQueueSample.m_nFrequency = 13000.f * ratio + 35000;\n\t\tvol = 50.f * ratio;\n\t} else if(surface1 == SURFACE_WATER || surface2 == SURFACE_WATER) {\n\t\tratio = GetCollisionRatio(audioCollision.m_fIntensity2, 0.0001f, 0.09f, 0.0899f);\n\t\tm_sQueueSample.m_nSampleIndex = SFX_BOAT_WATER_LOOP;\n\t\tm_sQueueSample.m_nFrequency = 6050.f * ratio + 16000;\n\t\tvol = 30.f * ratio;\n\t} else if(surface1 == SURFACE_GRAVEL || surface2 == SURFACE_GRAVEL || surface1 == SURFACE_MUD_DRY || surface2 == SURFACE_MUD_DRY ||\n\t          surface1 == SURFACE_SAND || surface2 == SURFACE_SAND || surface1 == SURFACE_SAND_BEACH || surface2 == SURFACE_SAND_BEACH) {\n\t\tratio = GetCollisionRatio(audioCollision.m_fIntensity2, 0.0001f, 0.09f, 0.0899f);\n\t\tm_sQueueSample.m_nSampleIndex = SFX_GRAVEL_SKID;\n\t\tm_sQueueSample.m_nFrequency = 6000.f * ratio + 10000;\n\t\tvol = 50.f * ratio;\n\t} else if(surface1 == SURFACE_PED || surface2 == SURFACE_PED) {\n\t\treturn 0;\n\t} else {\n\t\tratio = GetCollisionRatio(audioCollision.m_fIntensity2, 0.0001f, 0.09f, 0.0899f);\n\t\tm_sQueueSample.m_nSampleIndex = SFX_SCRAPE_CAR_1;\n\t\tm_sQueueSample.m_nFrequency = 10000.f * ratio + 10000;\n\t\tvol = 40.f * ratio;\n\t}\n\tif(audioCollision.m_nBaseVolume < 2) vol = audioCollision.m_nBaseVolume * vol / 2;\n\treturn vol;\n}\n\nvoid\ncAudioManager::SetUpLoopingCollisionSound(const cAudioCollision &col, uint8 counter)\n{\n    bool distCalculated = false;\n\tif(col.m_fIntensity2 > 0.0016f) {\n\t\tuint8 emittingVol = SetLoopingCollisionRequestedSfxFreqAndGetVol(col);\n\t\tif(emittingVol) {\n\t\t\tCalculateDistance(distCalculated, m_sQueueSample.m_fDistance);\n\t\t\tm_sQueueSample.m_nVolume = ComputeVolume(emittingVol, CollisionSoundIntensity, m_sQueueSample.m_fDistance);\n\t\t\tif(m_sQueueSample.m_nVolume) {\n\t\t\t\tm_sQueueSample.m_nCounter = counter;\n\t\t\t\tm_sQueueSample.m_vecPos = col.m_vecPosition;\n\t\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\t\tm_sQueueSample.m_bIs2D = false;\n\t\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 7;\n\t\t\t\tm_sQueueSample.m_nLoopCount = 0;\n\t\t\t\tm_sQueueSample.m_nEmittingVolume = emittingVol;\n\t\t\t\tm_sQueueSample.m_nLoopStart =\n\t\t\t\t    SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex);\n\t\t\t\tm_sQueueSample.m_nLoopEnd =\n\t\t\t\t    SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex);\n\t\t\t\tm_sQueueSample.m_fSpeedMultiplier = 4.0f;\n\t\t\t\tm_sQueueSample.m_fSoundIntensity = CollisionSoundIntensity;\n\t\t\t\tm_sQueueSample.m_bReleasingSoundFlag = false;\n\t\t\t\tm_sQueueSample.m_nReleasingVolumeDivider = 5;\n\t\t\t\tm_sQueueSample.m_bReverbFlag = true;\n\t\t\t\tm_sQueueSample.m_bRequireReflection = false;\n\t\t\t\tAddSampleToRequestedQueue();\n\t\t\t}\n\t\t}\n\t}\n}\nstatic const int32 gOneShotCol[] = {SFX_COL_TARMAC_1,\n                                    SFX_COL_TARMAC_1,\n                                    SFX_COL_GRASS_1,\n                                    SFX_COL_GRAVEL_1,\n                                    SFX_COL_MUD_1,\n                                    SFX_COL_TARMAC_1,\n                                    SFX_COL_CAR_1,\n                                    SFX_COL_GRASS_1,\n                                    SFX_COL_SCAFFOLD_POLE_1,\n                                    SFX_COL_GARAGE_DOOR_1,\n                                    SFX_COL_CAR_PANEL_1,\n                                    SFX_COL_THICK_METAL_PLATE_1,\n                                    SFX_COL_SCAFFOLD_POLE_1,\n                                    SFX_COL_LAMP_POST_1,\n                                    SFX_COL_HYDRANT_1,\n                                    SFX_COL_HYDRANT_1,\n                                    SFX_COL_METAL_CHAIN_FENCE_1,\n                                    SFX_COL_PED_1,\n                                    SFX_COL_SAND_1,\n                                    SFX_SPLASH_1,\n                                    SFX_COL_WOOD_CRATES_1,\n                                    SFX_COL_WOOD_BENCH_1,\n                                    SFX_COL_WOOD_SOLID_1,\n                                    SFX_COL_GRASS_1,\n                                    SFX_COL_GRASS_1,\n                                    SFX_COL_VEG_1,\n                                    SFX_COL_TARMAC_1,\n                                    SFX_COL_CONTAINER_1,\n                                    SFX_COL_NEWS_VENDOR_1,\n                                    SFX_TYRE_BUMP,\n                                    SFX_COL_CARDBOARD_1,\n                                    SFX_COL_TARMAC_1,\n                                    SFX_COL_GATE,\n                                    SFX_COL_SAND_1,\n                                    SFX_COL_TARMAC_1 };\n\nvoid\ncAudioManager::SetUpOneShotCollisionSound(const cAudioCollision &col)\n{\n\n\tint16 s1;\n\tint16 s2;\n\n\tint32 emittingVol;\n\tfloat ratio;\n\n\tstatic uint16 counter = 28;\n\n\tfor(int32 i = 0; i < 2; i++) {\n\t\tif(i) {\n\t\t\ts1 = col.m_bSurface2;\n\t\t\ts2 = col.m_bSurface1;\n\t\t} else {\n\t\t\ts1 = col.m_bSurface1;\n\t\t\ts2 = col.m_bSurface2;\n\t\t}\n\t\tratio = GetCollisionOneShotRatio(s1, col.m_fIntensity1);\n\t\tif(s1 == SURFACE_CAR && s2 == SURFACE_PED) ratio /= 4.0f;\n\t\tif(s1 == SURFACE_CAR && ratio < 0.6f) {\n\t\t\ts1 = SURFACE_CAR_PANEL;\n\t\t\tratio = Min(1.f, 2.f * ratio);\n\t\t}\n\t\temittingVol = 40.f * ratio;\n\t\tif(emittingVol) {\n\t\t\tm_sQueueSample.m_fDistance = Sqrt(col.m_fDistance);\n\t\t\tm_sQueueSample.m_nVolume =\n\t\t\t    ComputeVolume(emittingVol, CollisionSoundIntensity, m_sQueueSample.m_fDistance);\n\t\t\tif(m_sQueueSample.m_nVolume) {\n\t\t\t\tm_sQueueSample.m_nSampleIndex = gOneShotCol[s1];\n\t\t\t\tswitch(m_sQueueSample.m_nSampleIndex) {\n\t\t\t\tcase SFX_COL_TARMAC_1:\n\t\t\t\t\tm_sQueueSample.m_nSampleIndex += m_anRandomTable[3] % 5;\n\t\t\t\t\tbreak;\n\t\t\t\tcase SFX_COL_CAR_PANEL_1:\n\t\t\t\t\tm_sQueueSample.m_nSampleIndex += m_anRandomTable[0] % 6;\n\t\t\t\t\tbreak;\n\t\t\t\tcase SFX_COL_LAMP_POST_1:\n\t\t\t\t\tm_sQueueSample.m_nSampleIndex += m_anRandomTable[1] % 2;\n\t\t\t\t\tbreak;\n\t\t\t\tcase SFX_COL_METAL_CHAIN_FENCE_1:\n\t\t\t\t\tm_sQueueSample.m_nSampleIndex += m_anRandomTable[3] % 4;\n\t\t\t\t\tbreak;\n\t\t\t\tcase SFX_COL_PED_1:\n\t\t\t\t\tm_sQueueSample.m_nSampleIndex += m_anRandomTable[4] % 2;\n\t\t\t\t\tbreak;\n\t\t\t\tcase SFX_COL_WOOD_CRATES_1:\n\t\t\t\t\tm_sQueueSample.m_nSampleIndex += m_anRandomTable[4] % 4;\n\t\t\t\t\tbreak;\n\t\t\t\tcase SFX_COL_WOOD_BENCH_1:\n\t\t\t\t\tm_sQueueSample.m_nSampleIndex += m_anRandomTable[1] % 4;\n\t\t\t\t\tbreak;\n\t\t\t\tcase SFX_COL_VEG_1:\n\t\t\t\t\tm_sQueueSample.m_nSampleIndex += m_anRandomTable[2] % 5;\n\t\t\t\t\tbreak;\n\t\t\t\tcase SFX_COL_NEWS_VENDOR_1:\n\t\t\t\t\tm_sQueueSample.m_nSampleIndex += m_anRandomTable[2] % 3;\n\t\t\t\t\tbreak;\n\t\t\t\tcase SFX_COL_CAR_1:\n\t\t\t\t\tm_sQueueSample.m_nSampleIndex += m_anRandomTable[1] % 5;\n\t\t\t\t\tbreak;\n\t\t\t\tcase SFX_COL_CARDBOARD_1:\n\t\t\t\t\tm_sQueueSample.m_nSampleIndex += m_anRandomTable[3] % 2;\n\t\t\t\t\tbreak;\n\t\t\t\tdefault: break;\n\t\t\t\t}\n\t\t\t\tswitch(s1) {\n\t\t\t\tcase SURFACE_GLASS: m_sQueueSample.m_nFrequency = 13500; break;\n\t\t\t\tcase SURFACE_GIRDER: m_sQueueSample.m_nFrequency = 8819; break;\n\t\t\t\tcase SURFACE_WATER:\n\t\t\t\t\tm_sQueueSample.m_nFrequency =\n\t\t\t\t\t    2 * SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex);\n\t\t\t\t\tbreak;\n\t\t\t\tcase SURFACE_RUBBER: m_sQueueSample.m_nFrequency = 6000; break;\n\t\t\t\tcase SURFACE_PLASTIC: m_sQueueSample.m_nFrequency = 8000; break;\n\t\t\t\tdefault:\n\t\t\t\t\tm_sQueueSample.m_nFrequency =\n\t\t\t\t\t    SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tm_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 16);\n\t\t\t\tm_sQueueSample.m_nCounter = counter++;\n\t\t\t\tif(counter >= 255) counter = 28;\n\t\t\t\tm_sQueueSample.m_vecPos = col.m_vecPosition;\n\t\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\t\tm_sQueueSample.m_bIs2D = false;\n\t\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 11;\n\t\t\t\tm_sQueueSample.m_nLoopCount = 1;\n\t\t\t\tm_sQueueSample.m_nEmittingVolume = emittingVol;\n\t\t\t\tm_sQueueSample.m_nLoopStart = 0;\n\t\t\t\tm_sQueueSample.m_nLoopEnd = -1;\n\t\t\t\tm_sQueueSample.m_fSpeedMultiplier = 4.0f;\n\t\t\t\tm_sQueueSample.m_fSoundIntensity = CollisionSoundIntensity;\n\t\t\t\tm_sQueueSample.m_bReleasingSoundFlag = true;\n\t\t\t\tm_sQueueSample.m_bReverbFlag = true;\n\t\t\t\tm_sQueueSample.m_bRequireReflection = false;\n\t\t\t\tAddSampleToRequestedQueue();\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\ncAudioManager::ServiceCollisions()\n{\n\tint i, j;\n\tbool abRepeatedCollision1[NUMAUDIOCOLLISIONS];\n\tbool abRepeatedCollision2[NUMAUDIOCOLLISIONS];\n\n\tm_sQueueSample.m_nEntityIndex = m_nCollisionEntity;\n\n\tfor (int i = 0; i < NUMAUDIOCOLLISIONS; i++)\n\t\tabRepeatedCollision1[i] = abRepeatedCollision2[i] = false;\n\n\tfor (i = 0; i < m_sCollisionManager.m_bCollisionsInQueue; i++) {\n\t\tfor (j = 0; j < NUMAUDIOCOLLISIONS; j++) {\n\t\t\tint index = m_sCollisionManager.m_bIndicesTable[i];\n\t\t\tif ((m_sCollisionManager.m_asCollisions1[index].m_pEntity1 == m_sCollisionManager.m_asCollisions2[j].m_pEntity1)\n\t\t\t\t&& (m_sCollisionManager.m_asCollisions1[index].m_pEntity2 == m_sCollisionManager.m_asCollisions2[j].m_pEntity2)\n\t\t\t\t&& (m_sCollisionManager.m_asCollisions1[index].m_bSurface1 == m_sCollisionManager.m_asCollisions2[j].m_bSurface1)\n\t\t\t\t&& (m_sCollisionManager.m_asCollisions1[index].m_bSurface2 == m_sCollisionManager.m_asCollisions2[j].m_bSurface2)\n\t\t\t\t) {\n\t\t\t\tabRepeatedCollision1[index] = true;\n\t\t\t\tabRepeatedCollision2[j] = true;\n\t\t\t\tm_sCollisionManager.m_asCollisions1[index].m_nBaseVolume = ++m_sCollisionManager.m_asCollisions2[j].m_nBaseVolume;\n\t\t\t\tSetUpLoopingCollisionSound(m_sCollisionManager.m_asCollisions1[index], j);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tfor (i = 0; i < NUMAUDIOCOLLISIONS; i++) {\n\t\tif (!abRepeatedCollision2[i]) {\n\t\t\tm_sCollisionManager.m_asCollisions2[i].m_pEntity1 = nil;\n\t\t\tm_sCollisionManager.m_asCollisions2[i].m_pEntity2 = nil;\n\t\t\tm_sCollisionManager.m_asCollisions2[i].m_bSurface1 = SURFACE_DEFAULT;\n\t\t\tm_sCollisionManager.m_asCollisions2[i].m_bSurface2 = SURFACE_DEFAULT;\n\t\t\tm_sCollisionManager.m_asCollisions2[i].m_fIntensity2 = 0.0f;\n\t\t\tm_sCollisionManager.m_asCollisions2[i].m_fIntensity1 = 0.0f;\n\t\t\tm_sCollisionManager.m_asCollisions2[i].m_vecPosition = CVector(0.0f, 0.0f, 0.0f);\n\t\t\tm_sCollisionManager.m_asCollisions2[i].m_fDistance = 0.0f;\n\t\t}\n\t}\n\n\tfor (i = 0; i < m_sCollisionManager.m_bCollisionsInQueue; i++) {\n\t\tint index = m_sCollisionManager.m_bIndicesTable[i];\n\t\tif (!abRepeatedCollision1[index]) {\n\t\t\tfor (j = 0; j < NUMAUDIOCOLLISIONS; j++) {\n\t\t\t\tif (!abRepeatedCollision2[j]) {\n\t\t\t\t\tm_sCollisionManager.m_asCollisions2[j].m_nBaseVolume = 1;\n\t\t\t\t\tm_sCollisionManager.m_asCollisions2[j].m_pEntity1 = m_sCollisionManager.m_asCollisions1[index].m_pEntity1;\n\t\t\t\t\tm_sCollisionManager.m_asCollisions2[j].m_pEntity2 = m_sCollisionManager.m_asCollisions1[index].m_pEntity2;\n\t\t\t\t\tm_sCollisionManager.m_asCollisions2[j].m_bSurface1 = m_sCollisionManager.m_asCollisions1[index].m_bSurface1;\n\t\t\t\t\tm_sCollisionManager.m_asCollisions2[j].m_bSurface2 = m_sCollisionManager.m_asCollisions1[index].m_bSurface2;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tSetUpOneShotCollisionSound(m_sCollisionManager.m_asCollisions1[index]);\n\t\t\tSetUpLoopingCollisionSound(m_sCollisionManager.m_asCollisions1[index], j);\n\t\t}\n\t}\n\n\tfor (int i = 0; i < NUMAUDIOCOLLISIONS; i++)\n\t\tm_sCollisionManager.m_bIndicesTable[i] = NUMAUDIOCOLLISIONS;\n\tm_sCollisionManager.m_bCollisionsInQueue = 0;\n}\n\nvoid\ncAudioManager::ReportCollision(CEntity *entity1, CEntity *entity2, uint8 surface1, uint8 surface2, float collisionPower,\n                               float velocity)\n{\n\tfloat distSquared;\n\tCVector v1;\n\tCVector v2;\n\n\tif(!m_bIsInitialised || m_nCollisionEntity < 0 || m_nUserPause ||\n\t   (velocity < 0.0016f && collisionPower < 0.01f))\n\t\treturn;\n\n\tif(entity1->IsBuilding()) {\n\t\tv1 = v2 = entity2->GetPosition();\n\t} else if(entity2->IsBuilding()) {\n\t\tv1 = v2 = entity1->GetPosition();\n\t} else {\n\t\tv1 = entity1->GetPosition();\n\t\tv2 = entity2->GetPosition();\n\t}\n\tCVector pos = (v1 + v2) * 0.5f;\n\tdistSquared = GetDistanceSquared(pos);\n\tif(distSquared < SQR(CollisionSoundIntensity)) {\n\t\tm_sCollisionManager.m_sQueue.m_pEntity1 = entity1;\n\t\tm_sCollisionManager.m_sQueue.m_pEntity2 = entity2;\n\t\tm_sCollisionManager.m_sQueue.m_bSurface1 = surface1;\n\t\tm_sCollisionManager.m_sQueue.m_bSurface2 = surface2;\n\t\tm_sCollisionManager.m_sQueue.m_fIntensity1 = collisionPower;\n\t\tm_sCollisionManager.m_sQueue.m_fIntensity2 = velocity;\n\t\tm_sCollisionManager.m_sQueue.m_vecPosition = pos;\n\t\tm_sCollisionManager.m_sQueue.m_fDistance = distSquared;\n\t\tm_sCollisionManager.AddCollisionToRequestedQueue();\n\t}\n}\n"
  },
  {
    "path": "src/audio/AudioCollision.h",
    "content": "#pragma once\n\n#define NUMAUDIOCOLLISIONS 10\n\nclass CEntity;\n\nclass cAudioCollision\n{\npublic:\n\tCEntity *m_pEntity1;\n\tCEntity *m_pEntity2;\n\tuint8 m_bSurface1;\n\tuint8 m_bSurface2;\n\tfloat m_fIntensity1;\n\tfloat m_fIntensity2;\n\tCVector m_vecPosition;\n\tfloat m_fDistance;\n\tint32 m_nBaseVolume;\n\n\t// no methods\n};\n\nVALIDATE_SIZE(cAudioCollision, 40);\n\nclass cAudioCollisionManager\n{\npublic:\n\tcAudioCollision m_asCollisions1[NUMAUDIOCOLLISIONS];\n\tcAudioCollision m_asCollisions2[NUMAUDIOCOLLISIONS];\n\tuint8 m_bIndicesTable[NUMAUDIOCOLLISIONS];\n\tuint8 m_bCollisionsInQueue;\n\tcAudioCollision m_sQueue;\n\n\tcAudioCollisionManager();\n\tvoid AddCollisionToRequestedQueue();\n};\n\nVALIDATE_SIZE(cAudioCollisionManager, 0x354);\n"
  },
  {
    "path": "src/audio/AudioLogic.cpp",
    "content": "#include \"common.h\"\n\n#include \"AudioManager.h\"\n#include \"audio_enums.h\"\n\n#include \"Automobile.h\"\n#include \"Boat.h\"\n#include \"Bridge.h\"\n#include \"Camera.h\"\n#include \"Cranes.h\"\n#include \"DMAudio.h\"\n#include \"Entity.h\"\n#include \"Explosion.h\"\n#include \"Fire.h\"\n#include \"Garages.h\"\n#include \"General.h\"\n#include \"HandlingMgr.h\"\n#include \"Heli.h\"\n#include \"ModelIndices.h\"\n#include \"MusicManager.h\"\n#include \"Pad.h\"\n#include \"Ped.h\"\n#include \"Physical.h\"\n#include \"Placeable.h\"\n#include \"Plane.h\"\n#include \"PlayerPed.h\"\n#include \"Pools.h\"\n#include \"Projectile.h\"\n#include \"ProjectileInfo.h\"\n#include \"Replay.h\"\n#include \"Stats.h\"\n#include \"SurfaceTable.h\"\n#include \"Train.h\"\n#include \"Transmission.h\"\n#include \"Vehicle.h\"\n#include \"WaterCannon.h\"\n#include \"Weather.h\"\n#include \"ZoneCull.h\"\n#include \"sampman.h\"\n#include \"Bike.h\"\n#include \"WindModifiers.h\"\n#include \"Fluff.h\"\n#include \"Script.h\"\n#include \"Wanted.h\"\n\nconst int channels = ARRAY_SIZE(AudioManager.m_asActiveSamples);\nconst int policeChannel = channels + 1;\nconst int allChannels = channels + 2;\n\nenum PLAY_STATUS { PLAY_STATUS_STOPPED = 0, PLAY_STATUS_PLAYING, PLAY_STATUS_FINISHED };\nenum LOADING_STATUS { LOADING_STATUS_NOT_LOADED = 0, LOADING_STATUS_LOADED, LOADING_STATUS_FAILED };\n\nvoid\ncAudioManager::PreInitialiseGameSpecificSetup() const\n{\n\tBankStartOffset[SFX_BANK_0] = SAMPLEBANK_START;\n#ifdef GTA_PS2\n\tBankStartOffset[SAMPLEBANK_CAR_PACARD] = SFX_CAR_ACCEL_1;\n\tBankStartOffset[SAMPLEBANK_CAR_PATHFINDER] = SFX_CAR_ACCEL_2;\n\tBankStartOffset[SAMPLEBANK_CAR_PORSCHE] = SFX_CAR_ACCEL_3;\n\tBankStartOffset[SAMPLEBANK_CAR_SPIDER] = SFX_CAR_ACCEL_4;\n\tBankStartOffset[SAMPLEBANK_CAR_MERC] = SFX_CAR_ACCEL_5;\n\tBankStartOffset[SAMPLEBANK_CAR_MACKTRUCK] = SFX_CAR_ACCEL_6;\n\tBankStartOffset[SAMPLEBANK_CAR_HOTROD] = SFX_CAR_ACCEL_7;\n\tBankStartOffset[SAMPLEBANK_CAR_COBRA] = SFX_CAR_ACCEL_8;\n\tBankStartOffset[SAMPLEBANK_CAR_NONE] = SFX_CAR_ACCEL_9;\n\tBankStartOffset[SAMPLEBANK_FRONTEND] = SFX_PAGE_CHANGE_AND_BACK_LEFT;\n\tBankStartOffset[SAMPLEBANK_TRAIN] = SFX_TRAIN_STATION_AMBIENCE_LOOP;\n\tBankStartOffset[SAMPLEBANK_BUILDING_CLUB_1] = SFX_CLUB_1;\n\tBankStartOffset[SAMPLEBANK_BUILDING_CLUB_2] = SFX_CLUB_2;\n\tBankStartOffset[SAMPLEBANK_BUILDING_CLUB_3] = SFX_CLUB_3;\n\tBankStartOffset[SAMPLEBANK_BUILDING_CLUB_4] = SFX_CLUB_4;\n\tBankStartOffset[SAMPLEBANK_BUILDING_CLUB_5] = SFX_CLUB_5;\n\tBankStartOffset[SAMPLEBANK_BUILDING_CLUB_6] = SFX_CLUB_6;\n\tBankStartOffset[SAMPLEBANK_BUILDING_CLUB_7] = SFX_CLUB_7;\n\tBankStartOffset[SAMPLEBANK_BUILDING_CLUB_8] = SFX_CLUB_8;\n\tBankStartOffset[SAMPLEBANK_BUILDING_CLUB_9] = SFX_CLUB_9;\n\tBankStartOffset[SAMPLEBANK_BUILDING_CLUB_10] = SFX_CLUB_10;\n\tBankStartOffset[SAMPLEBANK_BUILDING_CLUB_11] = SFX_CLUB_11;\n\tBankStartOffset[SAMPLEBANK_BUILDING_CLUB_12] = SFX_CLUB_12;\n\tBankStartOffset[SAMPLEBANK_BUILDING_CLUB_RAGGA] = SFX_CLUB_RAGGA;\n\tBankStartOffset[SAMPLEBANK_BUILDING_STRIP_CLUB_1] = SFX_STRIP_CLUB_1;\n\tBankStartOffset[SAMPLEBANK_BUILDING_STRIP_CLUB_2] = SFX_STRIP_CLUB_2;\n\tBankStartOffset[SAMPLEBANK_BUILDING_WORKSHOP] = SFX_WORKSHOP_1;\n\tBankStartOffset[SAMPLEBANK_BUILDING_PIANO_BAR] = SFX_PIANO_BAR_1;\n\tBankStartOffset[SAMPLEBANK_BUILDING_SAWMILL] = SFX_SAWMILL_LOOP;\n\tBankStartOffset[SAMPLEBANK_BUILDING_DOG_FOOD_FACTORY] = SFX_DOG_FOOD_FACTORY;\n\tBankStartOffset[SAMPLEBANK_BUILDING_LAUNDERETTE] = SFX_LAUNDERETTE_LOOP;\n\tBankStartOffset[SAMPLEBANK_BUILDING_RESTAURANT_CHINATOWN] = SFX_RESTAURANT_CHINATOWN;\n\tBankStartOffset[SAMPLEBANK_BUILDING_RESTAURANT_ITALY] = SFX_RESTAURANT_ITALY;\n\tBankStartOffset[SAMPLEBANK_BUILDING_RESTAURANT_GENERIC_1] = SFX_RESTAURANT_GENERIC_1;\n\tBankStartOffset[SAMPLEBANK_BUILDING_RESTAURANT_GENERIC_2] = SFX_RESTAURANT_GENERIC_2;\n\tBankStartOffset[SAMPLEBANK_BUILDING_AIRPORT] = SFX_AIRPORT_ANNOUNCEMENT_1;\n\tBankStartOffset[SAMPLEBANK_BUILDING_SHOP] = SFX_SHOP_LOOP;\n\tBankStartOffset[SAMPLEBANK_BUILDING_CINEMA] = SFX_CINEMA_BASS_1;\n\tBankStartOffset[SAMPLEBANK_BUILDING_DOCKS] = SFX_DOCKS_FOGHORN;\n\tBankStartOffset[SAMPLEBANK_BUILDING_HOME] = SFX_HOME_1;\n\tBankStartOffset[SAMPLEBANK_BUILDING_PORN_1] = SFX_PORN_1_LOOP;\n\tBankStartOffset[SAMPLEBANK_BUILDING_PORN_2] = SFX_PORN_2_LOOP;\n\tBankStartOffset[SAMPLEBANK_BUILDING_PORN_3] = SFX_PORN_3_LOOP;\n\tBankStartOffset[SAMPLEBANK_BUILDING_POLICE_BALL] = SFX_POLICE_BALL_1;\n\tBankStartOffset[SAMPLEBANK_BUILDING_BANK_ALARM] = SFX_BANK_ALARM_1;\n\tBankStartOffset[SAMPLEBANK_BUILDING_RAVE_INDUSTRIAL] = SFX_RAVE_INDUSTRIAL;\n\tBankStartOffset[SAMPLEBANK_BUILDING_RAVE_COMMERCIAL] = SFX_RAVE_COMMERCIAL;\n\tBankStartOffset[SAMPLEBANK_BUILDING_RAVE_SUBURBAN] = SFX_RAVE_SUBURBAN;\n\tBankStartOffset[SAMPLEBANK_BUILDING_RAVE_COMMERCIAL_2] = SFX_RAVE_COMMERCIAL_2;\n\tBankStartOffset[SAMPLEBANK_BUILDING_39] = SFX_CLUB_1_1;\n\tBankStartOffset[SAMPLEBANK_BUILDING_40] = SFX_CLUB_1_2;\n\tBankStartOffset[SAMPLEBANK_BUILDING_41] = SFX_CLUB_1_3;\n\tBankStartOffset[SAMPLEBANK_BUILDING_42] = SFX_CLUB_1_4;\n\tBankStartOffset[SAMPLEBANK_BUILDING_43] = SFX_CLUB_1_5;\n\tBankStartOffset[SAMPLEBANK_BUILDING_44] = SFX_CLUB_1_6;\n\tBankStartOffset[SAMPLEBANK_BUILDING_45] = SFX_CLUB_1_7;\n\tBankStartOffset[SAMPLEBANK_BUILDING_46] = SFX_CLUB_1_8;\n\tBankStartOffset[SAMPLEBANK_BUILDING_47] = SFX_CLUB_1_9;\n\tBankStartOffset[SAMPLEBANK_EXTRAS] = SFX_EXPLOSION_1;\n#endif // GTA_PS2\n\tBankStartOffset[SFX_BANK_PED_COMMENTS] = SAMPLEBANK_PED_START;\n}\n\nvoid\ncAudioManager::PostInitialiseGameSpecificSetup()\n{\n\tm_nFireAudioEntity = CreateEntity(AUDIOTYPE_FIRE, &gFireManager);\n\tif (m_nFireAudioEntity >= 0)\n\t\tSetEntityStatus(m_nFireAudioEntity, true);\n\n\tm_nCollisionEntity = CreateEntity(AUDIOTYPE_COLLISION, (void *)1);\n\tif (m_nCollisionEntity >= 0)\n\t\tSetEntityStatus(m_nCollisionEntity, true);\n\n\tm_nFrontEndEntity = CreateEntity(AUDIOTYPE_FRONTEND, (void *)1);\n\tif (m_nFrontEndEntity >= 0)\n\t\tSetEntityStatus(m_nFrontEndEntity, true);\n\n\tm_nProjectileEntity = CreateEntity(AUDIOTYPE_PROJECTILE, (void *)1);\n\tif (m_nProjectileEntity >= 0)\n\t\tSetEntityStatus(m_nProjectileEntity, true);\n\n\tm_nWaterCannonEntity = CreateEntity(AUDIOTYPE_WATERCANNON, (void *)1);\n\tif (m_nWaterCannonEntity >= 0)\n\t\tSetEntityStatus(m_nWaterCannonEntity, true);\n\n\tm_nPoliceChannelEntity = CreateEntity(AUDIOTYPE_POLICERADIO, (void *)1);\n\tif (m_nPoliceChannelEntity >= 0)\n\t\tSetEntityStatus(m_nPoliceChannelEntity, true);\n#ifdef GTA_BRIDGE\n\tm_nBridgeEntity = CreateEntity(AUDIOTYPE_BRIDGE, (void*)1);\n\tif (m_nBridgeEntity >= 0)\n\t\tSetEntityStatus(m_nBridgeEntity, true);\n#endif // GTA_BRIDGE\n\tm_nEscalatorEntity = CreateEntity(AUDIOTYPE_ESCALATOR, (void*)1);\n\tif (m_nEscalatorEntity >= 0)\n\t\tSetEntityStatus(m_nEscalatorEntity, true);\n\n\tm_nExtraSoundsEntity = CreateEntity(AUDIOTYPE_EXTRA_SOUNDS, (void*)1);\n\tif (m_nExtraSoundsEntity >= 0)\n\t\tSetEntityStatus(m_nExtraSoundsEntity, true);\n\n\n\tm_sMissionAudio.m_nSampleIndex[0] = NO_SAMPLE;\n\tm_sMissionAudio.m_nLoadingStatus[0] = LOADING_STATUS_NOT_LOADED;\n\tm_sMissionAudio.m_nPlayStatus[0] = PLAY_STATUS_STOPPED;\n\tm_sMissionAudio.m_bIsPlaying[0] = false;\n\tm_sMissionAudio.m_bIsPlayed[0] = false;\n\tm_sMissionAudio.m_bPredefinedProperties[0] = true;\n\tm_sMissionAudio.m_nMissionAudioCounter[0] = 0;\n\tm_sMissionAudio.m_bIsMobile[0] = false;\n\tfield_5538 = 127;\n\tm_sMissionAudio.m_nSampleIndex[1] = NO_SAMPLE;\n\tm_sMissionAudio.m_nLoadingStatus[1] = LOADING_STATUS_NOT_LOADED;\n\tm_sMissionAudio.m_nPlayStatus[1] = PLAY_STATUS_STOPPED;\n\tm_sMissionAudio.m_bIsPlaying[1] = false;\n\tm_sMissionAudio.m_bIsPlayed[1] = false;\n\tm_sMissionAudio.m_bPredefinedProperties[1] = true;\n\tm_sMissionAudio.m_nMissionAudioCounter[1] = 0;\n\tm_sMissionAudio.m_bIsMobile[1] = false;\n\tfield_5538 = 127;\n\n\tResetAudioLogicTimers(CTimer::GetTimeInMilliseconds());\n\tm_bIsPlayerShutUp = false;\n\tm_nPlayerMood = PLAYER_MOOD_CALM;\n\tm_nPlayerMoodTimer = 0;\n}\n\nvoid\ncAudioManager::PreTerminateGameSpecificShutdown()\n{\n#ifdef GTA_BRIDGE\n\tif (m_nBridgeEntity >= 0) {\n\t\tDestroyEntity(m_nBridgeEntity);\n\t\tm_nBridgeEntity = AEHANDLE_NONE;\n\t}\n#endif\n\tif (m_nEscalatorEntity >= 0) {\n\t\tDestroyEntity(m_nEscalatorEntity);\n\t\tm_nEscalatorEntity = AEHANDLE_NONE;\n\t}\n\tif (m_nExtraSoundsEntity >= 0) {\n\t\tDestroyEntity(m_nExtraSoundsEntity);\n\t\tm_nExtraSoundsEntity = AEHANDLE_NONE;\n\t}\n\tif (m_nPoliceChannelEntity >= 0) {\n\t\tDestroyEntity(m_nPoliceChannelEntity);\n\t\tm_nPoliceChannelEntity = AEHANDLE_NONE;\n\t}\n\tif (m_nWaterCannonEntity >= 0) {\n\t\tDestroyEntity(m_nWaterCannonEntity);\n\t\tm_nWaterCannonEntity = AEHANDLE_NONE;\n\t}\n\tif (m_nFireAudioEntity >= 0) {\n\t\tDestroyEntity(m_nFireAudioEntity);\n\t\tm_nFireAudioEntity = AEHANDLE_NONE;\n\t}\n\tif (m_nCollisionEntity >= 0) {\n\t\tDestroyEntity(m_nCollisionEntity);\n\t\tm_nCollisionEntity = AEHANDLE_NONE;\n\t}\n\tif (m_nFrontEndEntity >= 0) {\n\t\tDestroyEntity(m_nFrontEndEntity);\n\t\tm_nFrontEndEntity = AEHANDLE_NONE;\n\t}\n\tif (m_nProjectileEntity >= 0) {\n\t\tDestroyEntity(m_nProjectileEntity);\n\t\tm_nProjectileEntity = AEHANDLE_NONE;\n\t}\n}\n\nvoid\ncAudioManager::PostTerminateGameSpecificShutdown()\n{\n\t;\n}\n\nvoid\ncAudioManager::ResetAudioLogicTimers(uint32 timer)\n{\n\tfor (int32 i = 0; i < m_nAudioEntitiesTotal; i++) {\n\t\tif (m_asAudioEntities[m_anAudioEntityIndices[i]].m_nType == AUDIOTYPE_PHYSICAL) {\n\t\t\tCPed *ped = (CPed *)m_asAudioEntities[m_anAudioEntityIndices[i]].m_pEntity;\n\t\t\tif (ped->IsPed()) {\n\t\t\t\tped->m_lastSoundStart = timer;\n\t\t\t\tped->m_soundStart = timer + m_anRandomTable[0] % 3000;\n\t\t\t}\n\t\t}\n\t}\n\tClearMissionAudio(0);\n\tClearMissionAudio(1);\n\tSampleManager.StopChannel(policeChannel);\n}\n\nvoid\ncAudioManager::ProcessReverb() const\n{\n#ifdef FIX_BUGS\n\tconst uint32 numChannels = channels;\n#else\n\tconst uint32 numChannels = 28;\n#endif\n\n\tif (SampleManager.UpdateReverb() && m_bDynamicAcousticModelingStatus) {\n\t\tfor (uint32 i = 0; i < numChannels; i++) {\n\t\t\tif (m_asActiveSamples[i].m_bReverbFlag)\n\t\t\t\tSampleManager.SetChannelReverbFlag(i, true);\n\t\t}\n\t}\n}\n\nfloat\ncAudioManager::GetDistanceSquared(const CVector &v) const\n{\n\tconst CVector &c = TheCamera.GetPosition();\n\treturn sq(v.x - c.x) + sq(v.y - c.y) + sq((v.z - c.z) * 0.2f);\n}\n\nvoid\ncAudioManager::CalculateDistance(bool &distCalculated, float dist)\n{\n\tif (!distCalculated) {\n\t\tm_sQueueSample.m_fDistance = Sqrt(dist);\n\t\tdistCalculated = true;\n\t}\n}\n\nCVehicle *cAudioManager::FindVehicleOfPlayer()\n{\n\tCVehicle* vehicle = FindPlayerVehicle();\n\tCPlayerPed* ped = FindPlayerPed();\n\tif (vehicle == nil && ped != nil) {\n\t\tCEntity *attachedTo = ped->m_attachedTo;\n\t\tif (attachedTo && attachedTo->IsVehicle())\n\t\t\tvehicle = (CVehicle*)attachedTo;\n\t}\n\treturn vehicle;\n}\n\nvoid\ncAudioManager::ProcessPlayerMood()\n{\n\tCPlayerPed *playerPed;\n\tuint32& lastMissionPassedTime = CTheScripts::GetLastMissionPassedTime();\n\tuint32 curTime = CTimer::GetTimeInMilliseconds();\n\n\tif (m_nPlayerMoodTimer <= curTime) {\n\t\tplayerPed = FindPlayerPed();\n\t\tif (playerPed != nil) {\n\n\t\t\tif (playerPed->m_pWanted->GetWantedLevel() > 3) {\n\t\t\t\tm_nPlayerMood = PLAYER_MOOD_ANGRY;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (playerPed->m_pWanted->GetWantedLevel() > 1) {\n\t\t\t\tm_nPlayerMood = PLAYER_MOOD_PISSED_OFF;\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (lastMissionPassedTime != -1) {\n\t\t\t\tif (curTime < lastMissionPassedTime) {\n\t\t\t\t\tlastMissionPassedTime = curTime;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (curTime < lastMissionPassedTime + 180000) {\n\t\t\t\t\tm_nPlayerMood = PLAYER_MOOD_WISECRACKING;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t\tm_nPlayerMood = PLAYER_MOOD_CALM;\n\t\t}\n\t}\n}\n\nvoid\ncAudioManager::ProcessSpecial()\n{\n\tCPlayerPed *playerPed;\n\n\tif (m_nUserPause) {\n\t\tif (!m_nPreviousUserPause) {\n\t\t\tSampleManager.SetEffectsFadeVolume(MAX_VOLUME);\n\t\t\tSampleManager.SetMusicFadeVolume(MAX_VOLUME);\n\t\t}\n\t} else {\n\t\tif (!CReplay::IsPlayingBack())\n\t\t\tProcessPlayerMood();\n\t\tplayerPed = FindPlayerPed();\n\t\tif (playerPed != nil) {\n\t\t\tif (playerPed->m_audioEntityId >= 0 && m_asAudioEntities[playerPed->m_audioEntityId].m_bIsUsed) {\n\t\t\t\tif (playerPed->EnteringCar()) {\n\t\t\t\t\tif(!playerPed->bInVehicle && CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle == nil)\n\t\t\t\t\t\tSampleManager.StopChannel(m_nActiveSamples);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\ncAudioManager::ProcessEntity(int32 id)\n{\n\tif (m_asAudioEntities[id].m_bStatus) {\n\t\tm_sQueueSample.m_nEntityIndex = id;\n\t\tswitch (m_asAudioEntities[id].m_nType) {\n\t\tcase AUDIOTYPE_PHYSICAL:\n\t\t\tif (!m_nUserPause) {\n\t\t\t\tm_sQueueSample.m_bReverbFlag = true;\n\t\t\t\tProcessPhysical(id);\n\t\t\t}\n\t\t\tbreak;\n\t\tcase AUDIOTYPE_EXPLOSION:\n\t\t\tif (!m_nUserPause) {\n\t\t\t\tm_sQueueSample.m_bReverbFlag = true;\n\t\t\t\tProcessExplosions(id);\n\t\t\t}\n\t\t\tbreak;\n\t\tcase AUDIOTYPE_FIRE:\n\t\t\tif (!m_nUserPause) {\n\t\t\t\tm_sQueueSample.m_bReverbFlag = true;\n\t\t\t\tProcessFires(id);\n\t\t\t}\n\t\t\tbreak;\n\t\tcase AUDIOTYPE_WEATHER:\n\t\t\tif (!m_nUserPause) {\n\t\t\t\tm_sQueueSample.m_bReverbFlag = true;\n\t\t\t\tif(CGame::currArea == AREA_MAIN_MAP || CGame::currArea == AREA_EVERYWHERE)\n\t\t\t\t\tProcessWeather(id);\n\t\t\t}\n\t\t\tbreak;\n/*\t\tcase AUDIOTYPE_CRANE:\n\t\t\tif (!m_nUserPause) {\n\t\t\t\tm_sQueueSample.m_bReverbFlag = true;\n\t\t\t\tProcessCrane();\n\t\t\t}\n\t\t\tbreak;*/\n\t\tcase AUDIOTYPE_SCRIPTOBJECT:\n\t\t\tif (!m_nUserPause) {\n\t\t\t\tm_sQueueSample.m_bReverbFlag = true;\n\t\t\t\tProcessScriptObject(id);\n\t\t\t}\n\t\t\tbreak;\n#ifdef GTA_BRIDGE\n\t\tcase AUDIOTYPE_BRIDGE:\n\t\t\tif (!m_nUserPause) {\n\t\t\t\tm_sQueueSample.m_bReverbFlag = true;\n\t\t\t\tProcessBridge();\n\t\t\t}\n\t\t\tbreak;\n#endif\n\t\tcase AUDIOTYPE_FRONTEND:\n\t\t\tm_sQueueSample.m_bReverbFlag = false;\n\t\t\tProcessFrontEnd();\n\t\t\tbreak;\n\t\tcase AUDIOTYPE_PROJECTILE:\n\t\t\tif (!m_nUserPause) {\n\t\t\t\tm_sQueueSample.m_bReverbFlag = true;\n\t\t\t\tProcessProjectiles();\n\t\t\t}\n\t\t\tbreak;\n\t\tcase AUDIOTYPE_GARAGE:\n\t\t\tif (!m_nUserPause)\n\t\t\t\tProcessGarages();\n\t\t\tbreak;\n\t\tcase AUDIOTYPE_FIREHYDRANT:\n\t\t\tif (!m_nUserPause) {\n\t\t\t\tm_sQueueSample.m_bReverbFlag = true;\n\t\t\t\tProcessFireHydrant();\n\t\t\t}\n\t\t\tbreak;\n\t\tcase AUDIOTYPE_WATERCANNON:\n\t\t\tif (!m_nUserPause) {\n\t\t\t\tm_sQueueSample.m_bReverbFlag = true;\n\t\t\t\tProcessWaterCannon(id);\n\t\t\t}\n\t\t\tbreak;\n\t\tcase AUDIOTYPE_ESCALATOR:\n\t\t\tif (!m_nUserPause) {\n\t\t\t\tm_sQueueSample.m_bReverbFlag = true;\n\t\t\t\tProcessEscalators();\n\t\t\t}\n\t\t\tbreak;\n\t\tcase AUDIOTYPE_EXTRA_SOUNDS:\n\t\t\tif (!m_nUserPause) {\n\t\t\t\tm_sQueueSample.m_bReverbFlag = true;\n\t\t\t\tProcessExtraSounds();\n\t\t\t}\n\t\t\tbreak;\n\t\tdefault:\n\t\t\treturn;\n\t\t}\n\t}\n}\n\nvoid\ncAudioManager::ProcessPhysical(int32 id)\n{\n\tCPhysical *entity = (CPhysical *)m_asAudioEntities[id].m_pEntity;\n\tif (entity) {\n\t\tswitch (entity->GetType()) {\n\t\tcase ENTITY_TYPE_VEHICLE:\n\t\t\tProcessVehicle((CVehicle *)m_asAudioEntities[id].m_pEntity);\n\t\t\tbreak;\n\t\tcase ENTITY_TYPE_PED:\n\t\t\tProcessPed((CPhysical *)m_asAudioEntities[id].m_pEntity);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\treturn;\n\t\t}\n\t}\n}\n\n#pragma region VEHICLE AUDIO\nenum eVehicleModel {\n\tLANDSTAL,\n\tIDAHO,\n\tSTINGER,\n\tLINERUN,\n\tPEREN,\n\tSENTINEL,\n\tRIO,\n\tFIRETRUK,\n\tTRASH,\n\tSTRETCH,\n\tMANANA,\n\tINFERNUS,\n\tVOODOO,\n\tPONY,\n\tMULE,\n\tCHEETAH,\n\tAMBULAN,\n\tFBICAR,\n\tMOONBEAM,\n\tESPERANT,\n\tTAXI,\n\tWASHING,\n\tBOBCAT,\n\tMRWHOOP,\n\tBFINJECT,\n\tHUNTER,\n\tPOLICE,\n\tENFORCER,\n\tSECURICA,\n\tBANSHEE,\n\tPREDATOR,\n\tBUS,\n\tRHINO,\n\tBARRACKS,\n\tCUBAN,\n\tCHOPPER,\n\tANGEL,\n\tCOACH,\n\tCABBIE,\n\tSTALLION,\n\tRUMPO,\n\tRCBANDIT,\n\tROMERO,\n\tPACKER,\n\tSENTXS,\n\tADMIRAL,\n\tSQUALO,\n\tSEASPAR,\n\tPIZZABOY,\n\tGANGBUR,\n\tAIRTRAIN,\n\tDEADDODO,\n\tSPEEDER,\n\tREEFER,\n\tTROPIC,\n\tFLATBED,\n\tYANKEE,\n\tCADDY,\n\tZEBRA,\n\tTOPFUN,\n\tSKIMMER,\n\tPCJ600,\n\tFAGGIO,\n\tFREEWAY,\n\tRCBARON,\n\tRCRAIDER,\n\tGLENDALE,\n\tOCEANIC,\n\tSANCHEZ,\n\tSPARROW,\n\tPATRIOT,\n\tLOVEFIST,\n\tCOASTG,\n\tDINGHY,\n\tHERMES,\n\tSABRE,\n\tSABRETUR,\n\tPHEONIX,\n\tWALTON,\n\tREGINA,\n\tCOMET,\n\tDELUXO,\n\tBURRITO,\n\tSPAND,\n\tMARQUIS,\n\tBAGGAGE,\n\tKAUFMAN,\n\tMAVERICK,\n\tVCNMAV,\n\tRANCHER,\n\tFBIRANCH,\n\tVIRGO,\n\tGREENWOO,\n\tJETMAX,\n\tHOTRING,\n\tSANDKING,\n\tBLISTAC,\n\tPOLMAV,\n\tBOXVILLE,\n\tBENSON,\n\tMESA,\n\tRCGOBLIN,\n\tHOTRINA,\n\tHOTRINB,\n\tBLOODRA,\n\tBLOODRB,\n\tVICECHEE,\n\tCAR237,\n\tCAR238,\n\tCAR239,\n\tMAX_CARS,\n\n\t// HACK so this compiles\n\t// TODO(MIAMI): check it out\n\tDODO = -1\n};\n\nenum\n{\n\tOLD_DOOR = 0,\n\tNEW_DOOR,\n\tTRUCK_DOOR,\n\tBUS_DOOR,\n};\n\n\nstruct tVehicleSampleData {\n\teSfxSample m_nAccelerationSampleIndex;\n\tuint8 m_nBank;\n\teSfxSample m_nHornSample;\n\tint32 m_nHornFrequency;\n\tuint8 m_nSirenOrAlarmSample;\n\tint32 m_nSirenOrAlarmFrequency;\n\tuint8 m_bDoorType;\n};\n\nconst tVehicleSampleData aVehicleSettings[MAX_CARS] = {\n\t{SFX_CAR_REV_10, SFX_BANK_PATHFINDER, SFX_CAR_HORN_JEEP, 26513, SFX_CAR_HORN_JEEP, 9935, OLD_DOOR},\n\t{SFX_CAR_REV_11, SFX_BANK_PACARD, SFX_CAR_HORN_56CHEV, 11487, SFX_CAR_HORN_JEEP, 9900, OLD_DOOR},\n\t{SFX_CAR_REV_2, SFX_BANK_PORSCHE, SFX_CAR_HORN_PORSCHE, 11025, SFX_CAR_HORN_JEEP, 9890, NEW_DOOR},\n\t{SFX_CAR_REV_5, SFX_BANK_TRUCK, SFX_CAR_HORN_TRUCK, 29711, SFX_CAR_HORN_JEEP, 9960, TRUCK_DOOR},\n\t{SFX_CAR_REV_11, SFX_BANK_PACARD, SFX_CAR_HORN_56CHEV, 12893, SFX_CAR_HORN_JEEP, 9500, OLD_DOOR},\n\t{SFX_CAR_REV_4, SFX_BANK_MERC, SFX_CAR_HORN_BMW328, 10706, SFX_CAR_HORN_JEEP, 9600, NEW_DOOR},\n\t{SFX_CAR_REV_1, SFX_BANK_0, SFX_CAR_HORN_TRUCK, 29711, SFX_CAR_HORN_JEEP, 9700, NEW_DOOR},\n\t{SFX_CAR_REV_5, SFX_BANK_TRUCK, SFX_CAR_HORN_TRUCK, 29711, SFX_POLICE_SIREN_SLOW, 10588, TRUCK_DOOR},\n\t{SFX_CAR_REV_5, SFX_BANK_TRUCK, SFX_CAR_HORN_TRUCK, 31478, SFX_CAR_HORN_JEEP, 9800, TRUCK_DOOR},\n\t{SFX_CAR_REV_11, SFX_BANK_PACARD, SFX_CAR_HORN_BMW328, 9538, SFX_CAR_HORN_JEEP, 9900, NEW_DOOR},\n\t{SFX_CAR_REV_11, SFX_BANK_PACARD, SFX_CAR_HORN_56CHEV, 10842, SFX_CAR_HORN_JEEP, 10000, OLD_DOOR},\n\t{SFX_CAR_REV_7, SFX_BANK_COBRA, SFX_CAR_HORN_BMW328, 12017, SFX_CAR_HORN_JEEP, 9900, NEW_DOOR},\n\t{SFX_CAR_REV_9, SFX_BANK_CADILLAC, SFX_CAR_HORN_JEEP, 22293, SFX_CAR_HORN_JEEP, 9800, NEW_DOOR},\n\t{SFX_CAR_REV_3, SFX_BANK_SPIDER, SFX_CAR_HORN_BUS2, 18000, SFX_CAR_HORN_JEEP, 9700, OLD_DOOR},\n\t{SFX_CAR_REV_3, SFX_BANK_SPIDER, SFX_CAR_HORN_BUS, 18286, SFX_CAR_HORN_JEEP, 9600, OLD_DOOR},\n\t{SFX_CAR_REV_2, SFX_BANK_PORSCHE, SFX_CAR_HORN_PORSCHE, 11025, SFX_CAR_HORN_JEEP, 9500, NEW_DOOR},\n\t{SFX_CAR_REV_3, SFX_BANK_SPIDER, SFX_CAR_HORN_JEEP, 22295, SFX_AMBULANCE_SIREN_SLOW, 12688, OLD_DOOR},\n\t{SFX_CAR_REV_4, SFX_BANK_MERC, SFX_CAR_HORN_PORSCHE, 9271, SFX_POLICE_SIREN_SLOW, 11471, NEW_DOOR},\n\t{SFX_CAR_REV_11, SFX_BANK_PACARD, SFX_CAR_HORN_56CHEV, 12170, SFX_CAR_HORN_JEEP, 9400, OLD_DOOR},\n\t{SFX_CAR_REV_11, SFX_BANK_PACARD, SFX_CAR_HORN_BMW328, 11000, SFX_CAR_HORN_JEEP, 9300, OLD_DOOR},\n\t{SFX_CAR_REV_10, SFX_BANK_PATHFINDER, SFX_CAR_HORN_BMW328, 10796, SFX_CAR_HORN_JEEP, 9200, NEW_DOOR},\n\t{SFX_CAR_REV_4, SFX_BANK_MERC, SFX_CAR_HORN_BMW328, 10500, SFX_CAR_HORN_JEEP, 9100, NEW_DOOR},\n\t{SFX_CAR_REV_10, SFX_BANK_PATHFINDER, SFX_CAR_HORN_PICKUP, 10924, SFX_CAR_HORN_JEEP, 9000, OLD_DOOR},\n\t{SFX_CAR_REV_3, SFX_BANK_SPIDER, SFX_CAR_HORN_PICKUP, 11025, SFX_ICE_CREAM_TUNE, 11025, OLD_DOOR},\n\t{SFX_CAR_REV_6, SFX_BANK_HOTROD, SFX_CAR_HORN_JEEP, 26513, SFX_CAR_HORN_JEEP, 9100, OLD_DOOR},\n\t{SFX_HELI_APACHE_1, SFX_BANK_HELI_APACHE, SFX_CAR_HORN_JEEP, 26513, SFX_CAR_HORN_JEEP, 9200, NEW_DOOR},\n\t{SFX_CAR_REV_4, SFX_BANK_MERC, SFX_CAR_HORN_BMW328, 10706, SFX_POLICE_SIREN_SLOW, 10511, NEW_DOOR},\n\t{SFX_CAR_REV_3, SFX_BANK_SPIDER, SFX_CAR_HORN_BUS, 17260, SFX_POLICE_SIREN_SLOW, 11029, OLD_DOOR},\n\t{SFX_CAR_REV_3, SFX_BANK_SPIDER, SFX_CAR_HORN_PICKUP, 8670, SFX_CAR_HORN_JEEP, 9300, OLD_DOOR},\n\t{SFX_CAR_REV_7, SFX_BANK_COBRA, SFX_CAR_HORN_PORSCHE, 10400, SFX_CAR_HORN_JEEP, 9400, NEW_DOOR},\n\t{SFX_CAR_REV_1, SFX_BANK_0, SFX_CAR_HORN_JEEP, 26513, SFX_POLICE_SIREN_SLOW, 11912, NEW_DOOR},\n\t{SFX_CAR_REV_5, SFX_BANK_TRUCK, SFX_CAR_HORN_BUS2, 11652, SFX_CAR_HORN_JEEP, 9500, BUS_DOOR},\n\t{SFX_CAR_REV_5, SFX_BANK_TRUCK, SFX_CAR_HORN_TRUCK, 29711, SFX_CAR_HORN_JEEP, 9600, TRUCK_DOOR},\n\t{SFX_CAR_REV_5, SFX_BANK_TRUCK, SFX_CAR_HORN_TRUCK, 28043, SFX_CAR_HORN_JEEP, 9700, TRUCK_DOOR},\n\t{SFX_CAR_REV_6, SFX_BANK_HOTROD, SFX_CAR_HORN_JEEP, 25400, SFX_CAR_HORN_JEEP, 9800, OLD_DOOR},\n\t{SFX_CAR_REV_1, SFX_BANK_0, SFX_CAR_HORN_JEEP, 26513, SFX_CAR_HORN_JEEP, 9900, NEW_DOOR},\n\t{SFX_CAR_REV_17, SFX_BANK_VTWIN, SFX_CAR_HORN_JEEP, 26313, SFX_CAR_HORN_JEEP, 10000, NEW_DOOR},\n\t{SFX_CAR_REV_5, SFX_BANK_TRUCK, SFX_CAR_HORN_BUS, 16291, SFX_CAR_HORN_JEEP, 10100, BUS_DOOR},\n\t{SFX_CAR_REV_11, SFX_BANK_PACARD, SFX_CAR_HORN_56CHEV, 10842, SFX_CAR_HORN_JEEP, 9900, OLD_DOOR},\n\t{SFX_CAR_REV_11, SFX_BANK_PACARD, SFX_CAR_HORN_56CHEV, 10233, SFX_CAR_HORN_JEEP, 9800, NEW_DOOR},\n\t{SFX_CAR_REV_3, SFX_BANK_SPIDER, SFX_CAR_HORN_PICKUP, 8670, SFX_CAR_HORN_JEEP, 9700, OLD_DOOR},\n\t{SFX_RC_REV, SFX_BANK_RC, SFX_CAR_HORN_PICKUP, 20000, SFX_CAR_HORN_JEEP, 9600, NEW_DOOR},\n\t{SFX_CAR_REV_11, SFX_BANK_PACARD, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9500, NEW_DOOR},\n\t{SFX_CAR_REV_5, SFX_BANK_TRUCK, SFX_CAR_HORN_TRUCK, 29000, SFX_CAR_HORN_JEEP, 9400, TRUCK_DOOR},\n\t{SFX_CAR_REV_1, CAR_SFX_BANKS_OFFSET, SFX_CAR_HORN_BMW328, 9003, SFX_CAR_HORN_JEEP, 9300, NEW_DOOR},\n\t{SFX_CAR_REV_4, SFX_BANK_MERC, SFX_CAR_HORN_PORSCHE, 12375, SFX_CAR_HORN_JEEP, 9200, NEW_DOOR},\n\t{SFX_CAR_REV_1, SFX_BANK_0, SFX_CAR_HORN_BUS2, 15554, SFX_CAR_HORN_JEEP, 9100, NEW_DOOR},\n\t{SFX_CAR_REV_1, SFX_BANK_0, SFX_CAR_HORN_BUS2, 13857, SFX_CAR_HORN_JEEP, 9000, TRUCK_DOOR},\n\t{SFX_MOPED_REV, SFX_BANK_MOPED, SFX_CAR_HORN_JEEP, 30000, SFX_CAR_HORN_JEEP, 9100, NEW_DOOR},\n\t{SFX_CAR_REV_7, SFX_BANK_COBRA, SFX_CAR_HORN_JEEP, 22043, SFX_CAR_HORN_JEEP, 9200, OLD_DOOR},\n\t{SFX_CAR_REV_1, SFX_BANK_0, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9300, NEW_DOOR},\n\t{SFX_CAR_REV_1, SFX_BANK_0, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9400, NEW_DOOR},\n\t{SFX_CAR_REV_1, SFX_BANK_0, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9500, NEW_DOOR},\n\t{SFX_CAR_REV_1, SFX_BANK_0, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9600, NEW_DOOR},\n\t{SFX_CAR_REV_1, SFX_BANK_0, SFX_CAR_HORN_JEEP, 21043, SFX_CAR_HORN_JEEP, 9700, NEW_DOOR},\n\t{SFX_CAR_REV_5, SFX_BANK_TRUCK, SFX_CAR_HORN_TRUCK, 28043, SFX_CAR_HORN_JEEP, 9800, TRUCK_DOOR},\n\t{SFX_CAR_REV_3, SFX_BANK_SPIDER, SFX_CAR_HORN_BUS, 18286, SFX_CAR_HORN_JEEP, 9900, OLD_DOOR},\n\t{SFX_CAR_REV_12, SFX_BANK_GOLF_CART, SFX_CAR_HORN_JEEP, 28500, SFX_CAR_HORN_JEEP, 9800, NEW_DOOR},\n\t{SFX_CAR_REV_1, CAR_SFX_BANKS_OFFSET, SFX_CAR_HORN_56CHEV, 10842, SFX_CAR_HORN_JEEP, 9700, OLD_DOOR},\n\t{SFX_CAR_REV_8, SFX_BANK_PONTIAC_SLOW, SFX_CAR_HORN_BUS2, 18000, SFX_CAR_HORN_JEEP, 9700, OLD_DOOR},\n\t{SFX_SEAPLANE_PRO1, SFX_BANK_PLANE_SEAPLANE, SFX_CAR_HORN_JEEP, 26513, SFX_CAR_HORN_JEEP, 9700, NEW_DOOR},\n\t{SFX_CAR_REV_20, SFX_BANK_SPORTS_BIKE, SFX_CAR_HORN_JEEP, 27000, SFX_CAR_HORN_JEEP, 9600, NEW_DOOR},\n\t{SFX_MOPED_REV, SFX_BANK_MOPED, SFX_CAR_HORN_JEEP, 31000, SFX_CAR_HORN_JEEP, 9500, NEW_DOOR},\n\t{SFX_CAR_REV_17, SFX_BANK_VTWIN, SFX_CAR_HORN_PICKUP, 11000, SFX_CAR_HORN_JEEP, 9400, NEW_DOOR},\n\t{SFX_RC_REV, SFX_BANK_RC, SFX_CAR_HORN_JEEP, 30000, SFX_CAR_HORN_JEEP, 15000, NEW_DOOR},\n\t{SFX_CAR_RC_HELI, SFX_BANK_RC_HELI, SFX_CAR_HORN_JEEP, 30000, SFX_CAR_HORN_JEEP, 15000, NEW_DOOR},\n\t{SFX_CAR_REV_9, SFX_BANK_CADILLAC, SFX_CAR_HORN_56CHEV, 10300, SFX_CAR_HORN_JEEP, 9100, OLD_DOOR},\n\t{SFX_CAR_REV_9, SFX_BANK_CADILLAC, SFX_CAR_HORN_56CHEV, 10500, SFX_CAR_HORN_JEEP, 9000, OLD_DOOR},\n\t{SFX_CAR_REV_19, SFX_BANK_HONDA250, SFX_CAR_HORN_JEEP, 30000, SFX_CAR_HORN_JEEP, 9000, NEW_DOOR},\n\t{SFX_CAR_REV_1, SFX_BANK_0, SFX_CAR_HORN_JEEP, 26513, SFX_CAR_HORN_JEEP, 9100, TRUCK_DOOR},\n\t{SFX_CAR_REV_3, SFX_BANK_SPIDER, SFX_CAR_HORN_TRUCK, 28000, SFX_CAR_HORN_JEEP, 9200, TRUCK_DOOR},\n\t{SFX_CAR_REV_7, SFX_BANK_COBRA, SFX_CAR_HORN_PICKUP, 11200, SFX_CAR_HORN_JEEP, 9300, NEW_DOOR},\n\t{SFX_CAR_REV_1, SFX_BANK_0, SFX_CAR_HORN_JEEP, 26513, SFX_CAR_HORN_JEEP, 9400, NEW_DOOR},\n\t{SFX_CAR_REV_1, SFX_BANK_0, SFX_CAR_HORN_JEEP, 26513, SFX_CAR_HORN_JEEP, 9500, NEW_DOOR},\n\t{SFX_CAR_REV_9, SFX_BANK_CADILLAC, SFX_CAR_HORN_56CHEV, 10700, SFX_CAR_HORN_JEEP, 9600, OLD_DOOR},\n\t{SFX_CAR_REV_1, CAR_SFX_BANKS_OFFSET, SFX_CAR_HORN_BMW328, 9000, SFX_CAR_HORN_JEEP, 9700, OLD_DOOR},\n\t{SFX_CAR_REV_6, SFX_BANK_HOTROD, SFX_CAR_HORN_BMW328, 9200, SFX_CAR_HORN_JEEP, 9800, OLD_DOOR},\n\t{SFX_CAR_REV_7, SFX_BANK_COBRA, SFX_CAR_HORN_JEEP, 26513, SFX_CAR_HORN_JEEP, 9900, NEW_DOOR},\n\t{SFX_CAR_REV_11, SFX_BANK_PACARD, SFX_CAR_HORN_56CHEV, 10540, SFX_CAR_HORN_JEEP, 9935, TRUCK_DOOR},\n\t{SFX_CAR_REV_8, SFX_BANK_PONTIAC_SLOW, SFX_CAR_HORN_PICKUP, 11000, SFX_CAR_HORN_JEEP, 9700, NEW_DOOR},\n\t{SFX_CAR_REV_2, SFX_BANK_PORSCHE, SFX_CAR_HORN_BMW328, 9500, SFX_CAR_HORN_JEEP, 9800, NEW_DOOR},\n\t{SFX_CAR_REV_7, SFX_BANK_COBRA, SFX_CAR_HORN_BMW328, 9700, SFX_CAR_HORN_JEEP, 9700, NEW_DOOR},\n\t{SFX_CAR_REV_8, SFX_BANK_PONTIAC_SLOW, SFX_CAR_HORN_BUS2, 18000, SFX_CAR_HORN_JEEP, 9600, OLD_DOOR},\n\t{SFX_CAR_REV_3, SFX_BANK_SPIDER, SFX_CAR_HORN_BUS, 18000, SFX_CAR_HORN_JEEP, 9500, TRUCK_DOOR},\n\t{SFX_CAR_REV_1, SFX_BANK_0, SFX_CAR_HORN_JEEP, 26513, SFX_CAR_HORN_JEEP, 9400, NEW_DOOR},\n\t{SFX_CAR_REV_8, SFX_BANK_PONTIAC_SLOW, SFX_CAR_HORN_JEEP, 27513, SFX_CAR_HORN_JEEP, 9300, NEW_DOOR},\n\t{SFX_CAR_REV_8, SFX_BANK_PONTIAC_SLOW, SFX_CAR_HORN_56CHEV, 10700, SFX_CAR_HORN_JEEP, 9200, OLD_DOOR},\n\t{SFX_CAR_REV_1, SFX_BANK_0, SFX_CAR_HORN_JEEP, 26513, SFX_CAR_HORN_JEEP, 9100, TRUCK_DOOR},\n\t{SFX_CAR_REV_1, SFX_BANK_0, SFX_CAR_HORN_JEEP, 26513, SFX_CAR_HORN_JEEP, 9000, TRUCK_DOOR},\n\t{SFX_CAR_REV_10, SFX_BANK_PATHFINDER, SFX_CAR_HORN_BUS2, 18000, SFX_CAR_HORN_JEEP, 9100, TRUCK_DOOR},\n\t{SFX_CAR_REV_1, CAR_SFX_BANKS_OFFSET, SFX_CAR_HORN_BUS2, 17900, SFX_POLICE_SIREN_SLOW, 10511, TRUCK_DOOR},\n\t{SFX_CAR_REV_4, SFX_BANK_MERC, SFX_CAR_HORN_JEEP, 26513, SFX_CAR_HORN_JEEP, 9200, NEW_DOOR},\n\t{SFX_CAR_REV_8, SFX_BANK_PONTIAC_SLOW, SFX_CAR_HORN_BMW328, 9600, SFX_CAR_HORN_JEEP, 9300, NEW_DOOR},\n\t{SFX_CAR_REV_4, SFX_BANK_0, SFX_CAR_HORN_JEEP, 26513, SFX_CAR_HORN_JEEP, 9400, NEW_DOOR},\n\t{SFX_CAR_REV_7, SFX_BANK_COBRA, SFX_CAR_HORN_PORSCHE, 10000, SFX_CAR_HORN_JEEP, 9500, OLD_DOOR},\n\t{SFX_CAR_REV_6, SFX_BANK_HOTROD, SFX_CAR_HORN_PORSCHE, 10500, SFX_CAR_HORN_JEEP, 9600, OLD_DOOR},\n\t{SFX_CAR_REV_10, SFX_BANK_PATHFINDER, SFX_CAR_HORN_JEEP, 25513, SFX_CAR_HORN_JEEP, 9700, NEW_DOOR},\n\t{SFX_CAR_REV_1, SFX_BANK_0, SFX_CAR_HORN_JEEP, 26513, SFX_CAR_HORN_JEEP, 9800, NEW_DOOR},\n\t{SFX_CAR_REV_3, SFX_BANK_SPIDER, SFX_CAR_HORN_JEEP, 26513, SFX_CAR_HORN_JEEP, 9900, NEW_DOOR},\n\t{SFX_CAR_REV_10, SFX_BANK_PATHFINDER, SFX_CAR_HORN_JEEP, 26513, SFX_CAR_HORN_JEEP, 9800, NEW_DOOR},\n\t{SFX_CAR_REV_1, CAR_SFX_BANKS_OFFSET, SFX_CAR_HORN_JEEP, 26513, SFX_CAR_HORN_JEEP, 9700, NEW_DOOR},\n\t{SFX_CAR_RC_HELI, SFX_BANK_RC_HELI, SFX_CAR_HORN_JEEP, 26513, SFX_CAR_HORN_JEEP, 9600, NEW_DOOR},\n\t{SFX_CAR_REV_6, SFX_BANK_HOTROD, SFX_CAR_HORN_JEEP, 26513, SFX_CAR_HORN_JEEP, 9700, NEW_DOOR},\n\t{SFX_CAR_REV_7, SFX_BANK_COBRA, SFX_CAR_HORN_JEEP, 26513, SFX_CAR_HORN_JEEP, 9600, NEW_DOOR},\n\t{SFX_CAR_REV_1, CAR_SFX_BANKS_OFFSET, SFX_CAR_HORN_JEEP, 26513, SFX_CAR_HORN_JEEP, 9500, NEW_DOOR},\n\t{SFX_CAR_REV_9, SFX_BANK_CADILLAC, SFX_CAR_HORN_JEEP, 26513, SFX_CAR_HORN_JEEP, 9400, NEW_DOOR},\n\t{SFX_CAR_REV_2, SFX_BANK_PORSCHE, SFX_CAR_HORN_PORSCHE, 11025, SFX_POLICE_SIREN_SLOW, 11000, NEW_DOOR},\n\t{SFX_CAR_REV_1, CAR_SFX_BANKS_OFFSET, SFX_CAR_HORN_JEEP, 26513, SFX_CAR_HORN_JEEP, 9200, NEW_DOOR},\n\t{SFX_CAR_REV_1, CAR_SFX_BANKS_OFFSET, SFX_CAR_HORN_JEEP, 26513, SFX_CAR_HORN_JEEP, 9300, NEW_DOOR},\n\t{SFX_CAR_REV_1, CAR_SFX_BANKS_OFFSET, SFX_CAR_HORN_JEEP, 26513, SFX_CAR_HORN_JEEP, 9400, NEW_DOOR} };\n\n\n\nbool bPlayerJustEnteredCar;\n\nconst bool hornPatternsArray[8][44] = {\n    {false, false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, false, false, false, false,\n     false, true,  true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true,  false, false, false, false},\n    {false, false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true,  true,\n     true,  true,  true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, false},\n    {false, false, true, true, true, true, true, true, true, true, true, true, false, false, false, false, true, true, true, true, true, false,\n     false, false, true, true, true, true, true, true, true, true, true, true, true,  true,  true,  true,  true, true, true, true, true, false},\n    {false, false, true, true, true, true,  true,  false, false, true, true, true, true, true, false, false, false, true, true, true, true, true,\n     true,  true,  true, true, true, false, false, false, true,  true, true, true, true, true, true,  true,  true,  true, true, true, true, false},\n    {false, false, true,  true,  true,  true,  true,  true,  true,  true,  true,  false, false, false, false, false, false, false, false, false, false, false,\n     false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false},\n    {false, false, true,  true,  true,  false, false, false, true,  true,  true,  false, false, false, false, false, false, false, false, false, false, false,\n     false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false},\n    {false, false, true, true, true,  true,  false, false, false, false, true, true, true, false, false, true, true, true, false, false, true,  true,\n     true,  true,  true, true, false, false, false, false, false, true,  true, true, true, true,  true,  true, true, true, true,  true,  false, false},\n    {false, false, true,  true,  true, true, false, false, true, true, true, true, true, false, false, false, true, true,  true,  true,  true,  true,\n     false, false, false, false, true, true, true,  true,  true, true, true, true, true, true,  true,  true,  true, false, false, false, false, false},\n};\n\nvoid cAudioManager::ProcessVehicle(CVehicle* veh)\n{\n\tCVehicle* playerVeh;\n\tcVehicleParams params;\n\tCBike* bike;\n\tCAutomobile* automobile;\n\n\tplayerVeh = FindVehicleOfPlayer();\n\tif (playerVeh == veh\n\t\t|| CGame::currArea == AREA_OVALRING\n\t\t|| CGame::currArea == AREA_BLOOD\n\t\t|| CGame::currArea == AREA_DIRT\n\t\t|| CGame::currArea == AREA_EVERYWHERE\n\t\t|| CGame::currArea == AREA_MALL\n\t\t|| CGame::currArea == AREA_MAIN_MAP) {\n\t\tm_sQueueSample.m_vecPos = veh->GetPosition();\n\t\tparams.m_bDistanceCalculated = false;\n\t\tparams.m_pVehicle = veh;\n\t\tparams.m_fDistance = GetDistanceSquared(m_sQueueSample.m_vecPos);\n\t\tparams.m_pTransmission = veh->pHandling != nil ? &veh->pHandling->Transmission : nil;\n\t\tparams.m_nIndex = veh->m_modelIndex - MI_FIRST_VEHICLE;\n\t\tif (veh->GetStatus() == STATUS_SIMPLE)\n\t\t\tparams.m_fVelocityChange = veh->AutoPilot.m_fMaxTrafficSpeed * 0.02f;\n\t\telse\n\t\t\tparams.m_fVelocityChange = DotProduct(veh->m_vecMoveSpeed, veh->GetForward());\n\t\tparams.m_VehicleType = veh->m_vehType;\n\t\t\n\t\tif (CGame::currArea == AREA_MALL && playerVeh != veh) {\n\t\t\tProcessVehicleOneShots(params);\n\t\t\tProcessVehicleSirenOrAlarm(params);\n\t\t\tProcessEngineDamage(params);\n\t\t\treturn;\n\t\t}\n\t\tswitch (params.m_VehicleType) {\n\t\tcase VEHICLE_TYPE_CAR:\n\t\t\tautomobile = (CAutomobile*)veh;\n\t\t\tUpdateGasPedalAudio(veh, params.m_VehicleType);\n\t\t\tif (veh->m_modelIndex == MI_RCBANDIT || veh->m_modelIndex == MI_RCBARON) {\n\t\t\t\tProcessModelVehicle(params);\n\t\t\t\tProcessEngineDamage(params);\n\t\t\t} else if (veh->m_modelIndex == MI_RCRAIDER || veh->m_modelIndex == MI_RCGOBLIN) {\n\t\t\t\tProcessModelHeliVehicle(params);\n\t\t\t\tProcessEngineDamage(params);\n\t\t\t} else {\n\t\t\t\tswitch (veh->GetVehicleAppearance()) {\n\t\t\t\tcase VEHICLE_APPEARANCE_HELI:\n\t\t\t\t\tProcessCarHeli(params);\n\t\t\t\t\tProcessVehicleFlatTyre(params);\n\t\t\t\t\tProcessEngineDamage(params);\n\t\t\t\t\tbreak;\n\t\t\t\tcase VEHICLE_APPEARANCE_BOAT:\n\t\t\t\tcase VEHICLE_APPEARANCE_PLANE:\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tif (ProcessVehicleRoadNoise(params)) {\n\t\t\t\t\t\tProcessReverseGear(params);\n\t\t\t\t\t\tif (CWeather::WetRoads > 0.0f)\n\t\t\t\t\t\t\tProcessWetRoadNoise(params);\n\t\t\t\t\t\tProcessVehicleSkidding(params);\n\t\t\t\t\t\tProcessVehicleFlatTyre(params);\n\t\t\t\t\t\tProcessVehicleHorn(params);\n\t\t\t\t\t\tProcessVehicleSirenOrAlarm(params);\n\t\t\t\t\t\tif (UsesReverseWarning(params.m_nIndex))\n\t\t\t\t\t\t\tProcessVehicleReverseWarning(params);\n\t\t\t\t\t\tif(HasAirBrakes(params.m_nIndex))\n\t\t\t\t\t\t\tProcessAirBrakes(params);\n\t\t\t\t\t\tProcessCarBombTick(params);\n\t\t\t\t\t\tProcessVehicleEngine(params);\n\t\t\t\t\t\tProcessEngineDamage(params);\n\t\t\t\t\t\tProcessVehicleDoors(params);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tProcessVehicleOneShots(params);\n\t\t\tautomobile->m_fVelocityChangeForAudio = params.m_fVelocityChange;\n\t\t\tbreak;\n\t\tcase VEHICLE_TYPE_BOAT:\n\t\t\tif (veh->m_modelIndex == MI_SKIMMER)\n\t\t\t\tProcessCarHeli(params);\n\t\t\telse\n\t\t\t\tProcessBoatEngine(params);\n\t\t\tProcessBoatMovingOverWater(params);\n\t\t\tProcessVehicleOneShots(params);\n\t\t\tbreak;\n\t\tcase VEHICLE_TYPE_HELI: \n\t\t\tProcessCarHeli(params);\n\t\t\tProcessVehicleOneShots(params);\n\t\t\tbreak;\n\t\tcase VEHICLE_TYPE_PLANE:\n\t\t\tProcessPlane(params);\n\t\t\tProcessVehicleOneShots(params);\n\t\t\tProcessVehicleFlatTyre(params);\n\t\t\tbreak;\n\t\tcase VEHICLE_TYPE_BIKE:\n\t\t\tbike = (CBike*)veh;\n\t\t\tUpdateGasPedalAudio(veh, params.m_VehicleType);\n\t\t\tif (ProcessVehicleRoadNoise(params)) {\n\t\t\t\tif (CWeather::WetRoads > 0.0f)\n\t\t\t\t\tProcessWetRoadNoise(params);\n\t\t\t\tProcessVehicleSkidding(params);\n\t\t\t\tProcessVehicleHorn(params);\n\t\t\t\tProcessVehicleSirenOrAlarm(params);\n\t\t\t\tProcessCarBombTick(params);\n\t\t\t\tProcessEngineDamage(params);\n\t\t\t\tProcessVehicleEngine(params);\n\t\t\t\tProcessVehicleFlatTyre(params);\n\t\t\t}\n\t\t\tProcessVehicleOneShots(params);\n\t\t\tbike->m_fVelocityChangeForAudio = params.m_fVelocityChange;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\t\tProcessRainOnVehicle(params);\n\t}\n}\n\nvoid\ncAudioManager::ProcessRainOnVehicle(cVehicleParams& params)\n{\n\tconst int SOUND_INTENSITY = 22.0f;\n\n\tCVehicle *veh;\n\tuint8 emittingVol;\n\n\tif (params.m_fDistance >= SQR(SOUND_INTENSITY) || CWeather::Rain <= 0.01f || CCullZones::CamNoRain() && CCullZones::PlayerNoRain())\n\t\treturn;\n\n\tveh = params.m_pVehicle;\n\tveh->m_bRainAudioCounter++;\n\tif (veh->m_bRainAudioCounter >= 2) {\n\t\tveh->m_bRainAudioCounter = 0;\n\t\tCalculateDistance(params.m_bDistanceCalculated, params.m_fDistance);\n\t\temittingVol = 30.0f * CWeather::Rain;\n\t\tm_sQueueSample.m_nVolume = ComputeVolume(emittingVol, SOUND_INTENSITY, m_sQueueSample.m_fDistance);\n\t\tif (m_sQueueSample.m_nVolume != 0) {\n\t\t\tm_sQueueSample.m_nCounter = veh->m_bRainSamplesCounter++;\n\t\t\tif (veh->m_bRainSamplesCounter > 4)\n\t\t\t\tveh->m_bRainSamplesCounter = 68;\n\t\t\tm_sQueueSample.m_nSampleIndex = (m_anRandomTable[1] & 3) + SFX_CAR_RAIN_1;\n\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\tm_sQueueSample.m_bIs2D = false;\n\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 9;\n\t\t\tm_sQueueSample.m_nFrequency = m_anRandomTable[1] % 4000 + 28000;\n\t\t\tm_sQueueSample.m_nLoopCount = 1;\n\t\t\tm_sQueueSample.m_nEmittingVolume = emittingVol;\n\t\t\tm_sQueueSample.m_nLoopStart = 0;\n\t\t\tm_sQueueSample.m_nLoopEnd = -1;\n\t\t\tm_sQueueSample.m_fSpeedMultiplier = 0.0f;\n\t\t\tm_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY;\n\t\t\tm_sQueueSample.m_bReleasingSoundFlag = true;\n\t\t\tm_sQueueSample.m_bReverbFlag = false;\n\t\t\tm_sQueueSample.m_bRequireReflection = false;\n\t\t\tAddSampleToRequestedQueue();\n\t\t}\n\t}\n}\n\nbool\ncAudioManager::ProcessReverseGear(cVehicleParams& params)\n{\n\tconst int reverseGearIntensity = 30;\n\n\tCAutomobile* automobile;\n\tfloat modificator;\n\tuint8 emittingVolume;\n\n\tif (params.m_fDistance >= SQR(reverseGearIntensity))\n\t\treturn false;\n\tautomobile = (CAutomobile*)params.m_pVehicle;\n\tif (automobile->m_modelIndex == MI_CADDY)\n\t\treturn true;\n\tif (automobile->bEngineOn && (automobile->m_fGasPedal < 0.0f || automobile->m_nCurrentGear == 0)) {\n\t\tCalculateDistance(params.m_bDistanceCalculated, params.m_fDistance);\n\t\tif (automobile->m_nDriveWheelsOnGround != 0) {\n\t\t\tmodificator = params.m_fVelocityChange / params.m_pTransmission->fMaxReverseVelocity;\n\t\t} else {\n\t\t\tif (automobile->m_nDriveWheelsOnGroundPrev != 0)\n\t\t\t\tautomobile->m_fGasPedalAudio *= 0.4f;\n\t\t\tmodificator = automobile->m_fGasPedalAudio;\n\t\t}\n\t\tmodificator = Abs(modificator);\n\t\temittingVolume = modificator * 24.0f;\n\t\tm_sQueueSample.m_nVolume = ComputeVolume(emittingVolume, reverseGearIntensity, m_sQueueSample.m_fDistance);\n\n\t\tif (m_sQueueSample.m_nVolume != 0) {\n\t\t\tif (params.m_pVehicle->m_fGasPedal >= 0.0f) {\n\t\t\t\tm_sQueueSample.m_nCounter = 62;\n\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_REVERSE_GEAR_2;\n\t\t\t} else {\n\t\t\t\tm_sQueueSample.m_nCounter = 61;\n\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_REVERSE_GEAR;\n\t\t\t}\n\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\tm_sQueueSample.m_bIs2D = false;\n\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 3;\n\t\t\tm_sQueueSample.m_nFrequency = (6000.0f * modificator) + 7000;\n\t\t\tm_sQueueSample.m_nLoopCount = 0;\n\t\t\tm_sQueueSample.m_nEmittingVolume = emittingVolume;\n\t\t\tm_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex);\n\t\t\tm_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex);\n\t\t\tm_sQueueSample.m_fSpeedMultiplier = 3.0f;\n\t\t\tm_sQueueSample.m_fSoundIntensity = reverseGearIntensity;\n\t\t\tm_sQueueSample.m_bReleasingSoundFlag = false;\n\t\t\tm_sQueueSample.m_nReleasingVolumeDivider = 5;\n\t\t\tm_sQueueSample.m_bReverbFlag = true;\n\t\t\tm_sQueueSample.m_bRequireReflection = false;\n\t\t\tAddSampleToRequestedQueue();\n\t\t}\n\t}\n\treturn true;\n}\n\nvoid\ncAudioManager::ProcessModelVehicle(cVehicleParams& params)\n{\n\tconst float SOUND_INTENSITY = 35.0f;\n\n\tstatic uint32 prevFreq = 14000;\n\tstatic uint8 prevVolume = 0;\n\n\tuint32 freq;\n\tint16 acceletateState;\n\tint16 brakeState;\n\tuint8 volume;\n\tbool isPlayerVeh;\n\tbool vehSlowdown;\n\n\tif (params.m_fDistance >= SQR(SOUND_INTENSITY))\n\t\treturn;\n\n\tif (FindPlayerVehicle() == params.m_pVehicle)\n\t\tisPlayerVeh = true;\n\telse\n#ifdef FIX_BUGS\n\t\tisPlayerVeh = CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle == params.m_pVehicle;\n#else\n\t\tisPlayerVeh = CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle != nil;\n#endif\n\tif (params.m_pVehicle->m_modelIndex == MI_RCBANDIT) {\n\t\tif (((CAutomobile*)params.m_pVehicle)->m_nDriveWheelsOnGround != 0) {\n\t\t\tvolume = Min(127, 127.0f * Abs(params.m_fVelocityChange) * 3.0f);\n\t\t\tfreq = 8000.0f * Abs(params.m_fVelocityChange) + 14000;\n\t\t} else {\n\t\t\tvolume = 127;\n\t\t\tfreq = 25000;\n\t\t}\n\t\tif (isPlayerVeh) {\n\t\t\tvolume = clamp2(volume, prevVolume, 7);\n\t\t\tfreq = clamp2(freq, prevFreq, 800);\n\t\t}\n\t\tif (volume > 0) {\n\t\t\tCalculateDistance(params.m_bDistanceCalculated, params.m_fDistance);\n\t\t\tm_sQueueSample.m_nVolume = ComputeVolume(volume, SOUND_INTENSITY, m_sQueueSample.m_fDistance);\n\t\t\tif (m_sQueueSample.m_nVolume != 0) {\n\t\t\t\tm_sQueueSample.m_nCounter = 2;\n\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_RC_REV;\n\t\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\t\tm_sQueueSample.m_bIs2D = false;\n\t\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 1;\n\t\t\t\tm_sQueueSample.m_nFrequency = freq;\n\t\t\t\tm_sQueueSample.m_nLoopCount = 0;\n\t\t\t\tm_sQueueSample.m_nEmittingVolume = volume;\n\t\t\t\tm_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(SFX_RC_REV);\n\t\t\t\tm_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(SFX_RC_REV);\n\t\t\t\tm_sQueueSample.m_fSpeedMultiplier = 3.0f;\n\t\t\t\tm_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY;\n\t\t\t\tm_sQueueSample.m_bReleasingSoundFlag = false;\n\t\t\t\tm_sQueueSample.m_nReleasingVolumeDivider = 4;\n\t\t\t\tm_sQueueSample.m_bReverbFlag = true;\n\t\t\t\tm_sQueueSample.m_bRequireReflection = false;\n\t\t\t\tAddSampleToRequestedQueue();\n\t\t\t}\n\t\t}\n\t\tif (isPlayerVeh) {\n\t\t\tprevFreq = freq;\n\t\t\tprevVolume = volume;\n\t\t}\n\t} else if (params.m_pVehicle != nil) {\n\t\tif (isPlayerVeh) {\n\t\t\tacceletateState = Pads[0].GetAccelerate();\n\t\t\tbrakeState = Pads[0].GetBrake();\n\t\t} else {\n\t\t\tacceletateState = 255.0f * params.m_pVehicle->m_fGasPedal;\n\t\t\tbrakeState = 255.0f * params.m_pVehicle->m_fBrakePedal;\n\t\t}\n\t\tif (acceletateState < brakeState)\n\t\t\tacceletateState = brakeState;\n\t\tif (acceletateState <= 0) {\n\t\t\tvehSlowdown = true;\n\t\t\tvolume = 127;\n\t\t\tfreq = 18000;\n\t\t} else {\n\t\t\tvehSlowdown = false;\n\t\t\tvolume = Min(127, (127 * acceletateState / 255) * 3.0f * Abs(params.m_fVelocityChange));\n\t\t\tfreq = Min(22000, (8000 * acceletateState / 255 + 14000) * 3.0f * Abs(params.m_fVelocityChange));\n\t\t}\n\t\tif (isPlayerVeh && !vehSlowdown) {\n\t\t\tvolume = clamp2(volume, prevVolume, 7);\n\t\t\tfreq = clamp2(freq, prevFreq, 800);\n\t\t}\n\t\tif (!vehSlowdown)\n#ifdef THIS_IS_STUPID\n\t\t\tfreq += 8000.0f * Abs(DotProduct(params.m_pVehicle->GetUp(), CVector(0.0f, 1.0f, 0.0f)));\n#else\n\t\t\tfreq += 8000.0f * Abs(params.m_pVehicle->GetUp().y);\n#endif\n\t\tif (params.m_pVehicle->bIsDrowning)\n\t\t\tvolume /= 4;\n\t\tif (volume > 0) {\n\t\t\tCalculateDistance(params.m_bDistanceCalculated, params.m_fDistance);\n\t\t\tm_sQueueSample.m_nVolume = ComputeVolume(volume, SOUND_INTENSITY, m_sQueueSample.m_fDistance);\n\t\t\tif (m_sQueueSample.m_nVolume != 0) {\n\t\t\t\tif (vehSlowdown) {\n\t\t\t\t\tm_sQueueSample.m_nCounter = 0;\n\t\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_RC_IDLE;\n\t\t\t\t\tm_sQueueSample.m_nReleasingVolumeDivider = 6;\n\t\t\t\t} else {\n\t\t\t\t\tm_sQueueSample.m_nCounter = 2;\n\t\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_RC_REV;\n\t\t\t\t\tm_sQueueSample.m_nReleasingVolumeDivider = 4;\n\t\t\t\t}\n\t\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\t\tm_sQueueSample.m_bIs2D = false;\n\t\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 3;\n\t\t\t\tm_sQueueSample.m_nFrequency = freq;\n\t\t\t\tm_sQueueSample.m_nLoopCount = 0;\n\t\t\t\tm_sQueueSample.m_nEmittingVolume = volume;\n\t\t\t\tm_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex);\n\t\t\t\tm_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex);\n\t\t\t\tm_sQueueSample.m_fSpeedMultiplier = 3.0f;\n\t\t\t\tm_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY;\n\t\t\t\tm_sQueueSample.m_bReleasingSoundFlag = false;\n\t\t\t\tm_sQueueSample.m_bReverbFlag = true;\n\t\t\t\tm_sQueueSample.m_bRequireReflection = false;\n\t\t\t\tAddSampleToRequestedQueue();\n\t\t\t}\n\t\t}\n\t\tif (isPlayerVeh) {\n\t\t\tif (vehSlowdown) {\n\t\t\t\tprevFreq = freq;\n\t\t\t\tprevVolume = volume;\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\ncAudioManager::ProcessModelHeliVehicle(cVehicleParams& params)\n{\n\tconst float SOUND_INTENSITY = 35.0f;\n\n\tstatic uint32 prevFreq = 22050;\n\n\tuint32 freq;\n\tbool isPlayerVeh;\n\tint16 acceletateState;\n\tint16 brakeState;\n\n\tif (params.m_fDistance >= SQR(SOUND_INTENSITY))\n\t\treturn;\n\n\tif (FindPlayerVehicle() == params.m_pVehicle)\n\t\tisPlayerVeh = true;\n\telse\n#ifdef FIX_BUGS\n\t\tisPlayerVeh = CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle == params.m_pVehicle;\n#else\n\t\tisPlayerVeh = CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle != nil;\n#endif\n\tif (isPlayerVeh) {\n\t\tbrakeState = Pads[0].GetBrake();\n\t\tacceletateState = Max(Pads[0].GetAccelerate(), Abs(Pads[0].GetCarGunUpDown()) * 2);\n\t} else {\n\t\tacceletateState = 255.0f * params.m_pVehicle->m_fGasPedal;\n\t\tbrakeState = 255.0f * params.m_pVehicle->m_fBrakePedal;\n\t}\n\tif (acceletateState < brakeState)\n\t\tacceletateState = brakeState;\n\tfreq = clamp2(5 * acceletateState + 22050, prevFreq, 30);\n\tCalculateDistance(params.m_bDistanceCalculated, params.m_fDistance);\n\tm_sQueueSample.m_nVolume = ComputeVolume(70, SOUND_INTENSITY, m_sQueueSample.m_fDistance);\n\tif (m_sQueueSample.m_nVolume != 0) {\n\t\tm_sQueueSample.m_nCounter = 2;\n\t\tm_sQueueSample.m_nSampleIndex = SFX_CAR_RC_HELI;\n\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\tm_sQueueSample.m_bIs2D = false;\n\t\tm_sQueueSample.m_nReleasingVolumeModificator = 3;\n\t\tm_sQueueSample.m_nFrequency = freq;\n\t\tm_sQueueSample.m_nLoopCount = 0;\n\t\tm_sQueueSample.m_nEmittingVolume = 70;\n\t\tm_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(SFX_CAR_RC_HELI);\n\t\tm_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(SFX_CAR_RC_HELI);\n\t\tm_sQueueSample.m_fSpeedMultiplier = 3.0f;\n\t\tm_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY;\n\t\tm_sQueueSample.m_bReleasingSoundFlag = false;\n\t\tm_sQueueSample.m_nReleasingVolumeDivider = 4;\n\t\tm_sQueueSample.m_bReverbFlag = true;\n\t\tm_sQueueSample.m_bRequireReflection = false;\n\t\tAddSampleToRequestedQueue();\n\t}\n\tif (isPlayerVeh)\n\t\tprevFreq = freq;\n}\n\nbool\ncAudioManager::ProcessVehicleRoadNoise(cVehicleParams& params)\n{\n\tconst float SOUND_INTENSITY = 95.0f;\n\n\tint32 emittingVol;\n\tuint32 freq;\n\tfloat multiplier;\n\tint sampleFreq;\n\tfloat velocity;\n\tuint8 wheelsOnGround;\n\n\tif (params.m_fDistance >= SQR(SOUND_INTENSITY))\n\t\treturn false;\n\n\tif (params.m_fDistance >= SQR(SOUND_INTENSITY))\n\t\treturn false;\n\tswitch (params.m_VehicleType) {\n\tcase VEHICLE_TYPE_CAR:\n\t\twheelsOnGround = ((CAutomobile*)params.m_pVehicle)->m_nWheelsOnGround;\n\t\tbreak;\n\tcase VEHICLE_TYPE_BIKE:\n\t\twheelsOnGround = ((CBike*)params.m_pVehicle)->m_nWheelsOnGround;\n\t\tbreak;\n\tdefault:\n\t\twheelsOnGround = 4;\n\t\tbreak;\n\t}\n\tif (params.m_pTransmission == nil || wheelsOnGround == 0)\n\t\treturn true;\n\n\tvelocity = Abs(params.m_fVelocityChange);\n\tif (velocity > 0.0f) {\n\t\tCalculateDistance(params.m_bDistanceCalculated, params.m_fDistance);\n\t\temittingVol = 30.f * Min(1.f, velocity / (0.5f * params.m_pTransmission->fMaxVelocity));\n\t\tm_sQueueSample.m_nVolume = ComputeVolume(emittingVol, SOUND_INTENSITY, m_sQueueSample.m_fDistance);\n\t\tif (m_sQueueSample.m_nVolume != 0) {\n\t\t\tm_sQueueSample.m_nCounter = 0;\n\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\tm_sQueueSample.m_bIs2D = false;\n\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 3;\n\t\t\tif (params.m_pVehicle->m_nSurfaceTouched == SURFACE_WATER) {\n\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_BOAT_WATER_LOOP;\n\t\t\t\tfreq = 6050 * emittingVol / 30 + 16000;\n\t\t\t} else {\n\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_ROAD_NOISE;\n\t\t\t\tmultiplier = (m_sQueueSample.m_fDistance / SOUND_INTENSITY) * 0.5f;\n\t\t\t\tsampleFreq = SampleManager.GetSampleBaseFrequency(SFX_ROAD_NOISE);\n\t\t\t\tfreq = (sampleFreq * multiplier) + ((3 * sampleFreq) / 4);\n\t\t\t}\n\t\t\tm_sQueueSample.m_nFrequency = freq;\n\t\t\tm_sQueueSample.m_nLoopCount = 0;\n\t\t\tm_sQueueSample.m_nEmittingVolume = emittingVol;\n\t\t\tm_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex);\n\t\t\tm_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex);\n\t\t\tm_sQueueSample.m_fSpeedMultiplier = 6.0f;\n\t\t\tm_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY;\n\t\t\tm_sQueueSample.m_bReleasingSoundFlag = false;\n\t\t\tm_sQueueSample.m_nReleasingVolumeDivider = 4;\n\t\t\tm_sQueueSample.m_bReverbFlag = true;\n\t\t\tm_sQueueSample.m_bRequireReflection = false;\n\t\t\tAddSampleToRequestedQueue();\n\t\t}\n\t}\n\n\treturn true;\n}\n\nbool\ncAudioManager::ProcessWetRoadNoise(cVehicleParams& params)\n{\n\tconst float SOUND_INTENSITY = 30.0f;\n\n\tfloat relativeVelocity;\n\tint32 emittingVol;\n\tfloat multiplier;\n\tint freq;\n\tfloat velocity;\n\tuint8 wheelsOnGround;\n\n\tif (params.m_fDistance >= SQR(SOUND_INTENSITY))\n\t\treturn false;\n\tswitch (params.m_VehicleType) {\n\tcase VEHICLE_TYPE_CAR:\n\t\twheelsOnGround = ((CAutomobile*)params.m_pVehicle)->m_nWheelsOnGround;\n\t\tbreak;\n\tcase VEHICLE_TYPE_BIKE:\n\t\twheelsOnGround = ((CBike*)params.m_pVehicle)->m_nWheelsOnGround;\n\t\tbreak;\n\tdefault:\n\t\twheelsOnGround = 4;\n\t\tbreak;\n\t}\n\tif (params.m_pTransmission == nil || wheelsOnGround == 0)\n\t\treturn true;\n\n\tvelocity = Abs(params.m_fVelocityChange);\n\tif (velocity > 0.0f) {\n\t\tCalculateDistance(params.m_bDistanceCalculated, params.m_fDistance);\n\t\trelativeVelocity = Min(1.0f, velocity / (0.5f * params.m_pTransmission->fMaxVelocity));\n\t\temittingVol = 23.0f * relativeVelocity * CWeather::WetRoads;\n\t\tm_sQueueSample.m_nVolume = ComputeVolume(emittingVol, SOUND_INTENSITY, m_sQueueSample.m_fDistance);\n\t\tif (m_sQueueSample.m_nVolume != 0) {\n\t\t\tm_sQueueSample.m_nCounter = 1;\n\t\t\tm_sQueueSample.m_nSampleIndex = SFX_ROAD_NOISE;\n\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\tm_sQueueSample.m_bIs2D = false;\n\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 3;\n\t\t\tmultiplier = (m_sQueueSample.m_fDistance / SOUND_INTENSITY) * 0.5f;\n\t\t\tfreq = SampleManager.GetSampleBaseFrequency(SFX_ROAD_NOISE);\n\t\t\tm_sQueueSample.m_nFrequency = freq + freq * multiplier;\n\t\t\tm_sQueueSample.m_nLoopCount = 0;\n\t\t\tm_sQueueSample.m_nEmittingVolume = emittingVol;\n\t\t\tm_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex);\n\t\t\tm_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex);\n\t\t\tm_sQueueSample.m_fSpeedMultiplier = 6.0f;\n\t\t\tm_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY;\n\t\t\tm_sQueueSample.m_bReleasingSoundFlag = false;\n\t\t\tm_sQueueSample.m_nReleasingVolumeDivider = 4;\n\t\t\tm_sQueueSample.m_bReverbFlag = true;\n\t\t\tm_sQueueSample.m_bRequireReflection = false;\n\t\t\tAddSampleToRequestedQueue();\n\t\t}\n\t}\n\n\treturn true;\n}\n\nvoid\ncAudioManager::ProcessVehicleEngine(cVehicleParams& params)\n{\n\tconst float SOUND_INTENSITY = 50.0f;\n\n\tCVehicle* playerVeh;\n\tCVehicle* veh;\n\tCAutomobile* automobile;\n\tcTransmission* transmission;\n\tCBike* bike;\n\ttWheelState* wheelState;\n\tfloat* gasPedalAudioPtr;\n\n\tint32 freq = 0;\n\tuint8 currentGear;\n\tuint8 emittingVol;\n\tint8 wheelsOnGround;\n\tint8 wheelsOnGroundPrev;\n\tfloat relativeGearChange;\n\tfloat relativeChange;\n\tfloat modificator;\n\tfloat traction;\n\tbool isMoped;\n\tbool caddyBool;\n\n\tisMoped = false;\n\tcaddyBool = false;\n\ttraction = 0.0f;\n\tif (params.m_fDistance >= SQR(SOUND_INTENSITY))\n\t\treturn;\n\tplayerVeh = FindPlayerVehicle();\n\tveh = params.m_pVehicle;\n\tif (playerVeh == veh && veh->GetStatus() == STATUS_WRECKED) {\n\t\tSampleManager.StopChannel(m_nActiveSamples);\n\t\treturn;\n\t}\n\tif (!veh->bEngineOn)\n\t\treturn;\n\tCalculateDistance(params.m_bDistanceCalculated, params.m_fDistance);\n\tif (playerVeh == veh && veh->m_modelIndex != MI_CADDY) {\n\t\tProcessPlayersVehicleEngine(params, params.m_pVehicle);\n\t\treturn;\n\t}\n\ttransmission = params.m_pTransmission;\n\tif (transmission != nil) {\n\t\tswitch (veh->m_modelIndex) {\n\t\tcase MI_PIZZABOY:\n\t\tcase MI_FAGGIO:\n\t\t\tisMoped = true;\n\t\t\tcurrentGear = transmission->nNumberOfGears;\n\t\t\tbreak;\n\t\tcase MI_CADDY:\n\t\t\tcurrentGear = transmission->nNumberOfGears;\n\t\t\tcaddyBool = true;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tcurrentGear = veh->m_nCurrentGear;\n\t\t\tbreak;\n\t\t}\n\t\tswitch (params.m_VehicleType) {\n\t\tcase VEHICLE_TYPE_CAR:\n\t\t\tautomobile = (CAutomobile*)veh;\n\t\t\twheelsOnGround = automobile->m_nDriveWheelsOnGround;\n\t\t\twheelsOnGroundPrev = automobile->m_nDriveWheelsOnGroundPrev;\n\t\t\twheelState = automobile->m_aWheelState;\n\t\t\tgasPedalAudioPtr = &automobile->m_fGasPedalAudio;\n\t\t\tbreak;\n\t\tcase VEHICLE_TYPE_BIKE:\n\t\t\tbike = (CBike*)veh;\n\t\t\twheelsOnGround = bike->m_nDriveWheelsOnGround;\n\t\t\twheelsOnGroundPrev = bike->m_nDriveWheelsOnGroundPrev;\n\t\t\twheelState = bike->m_aWheelState;\n\t\t\tgasPedalAudioPtr = &bike->m_fGasPedalAudio;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tdebug(\" ** AUDIOLOG: Unrecognised vehicle type %d in ProcessVehicleEngine() * \\n\", params.m_VehicleType);\n\t\t\treturn;\n\t\t}\n\n\t\tif (wheelsOnGround != 0) {\n\t\t\tif (!veh->bIsHandbrakeOn || isMoped && caddyBool) { //mb bug, bcs it's can't be true together\n\t\t\t\tif (veh->GetStatus() == STATUS_SIMPLE || isMoped || caddyBool) {\n\t\t\t\t\ttraction = 0.0f;\n\t\t\t\t} else {\n\t\t\t\t\tswitch (transmission->nDriveType) {\n\t\t\t\t\tcase '4':\n\t\t\t\t\t\tif (params.m_VehicleType == VEHICLE_TYPE_BIKE) {\n\t\t\t\t\t\t\tfor (int i = 0; i < 2; i++)\n\t\t\t\t\t\t\t\tif (wheelState[i] == WHEEL_STATE_SPINNING)\n\t\t\t\t\t\t\t\t\ttraction += 0.1f;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tfor (int i = 0; i < 4; i++)\n\t\t\t\t\t\t\t\tif (wheelState[i] == WHEEL_STATE_SPINNING)\n\t\t\t\t\t\t\t\t\ttraction += 0.05f;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'F':\n\t\t\t\t\t\tif (params.m_VehicleType == VEHICLE_TYPE_BIKE) {\n\t\t\t\t\t\t\tif (wheelState[BIKEWHEEL_FRONT] == WHEEL_STATE_SPINNING)\n\t\t\t\t\t\t\t\ttraction += 0.2f;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (wheelState[CARWHEEL_FRONT_LEFT] == WHEEL_STATE_SPINNING)\n\t\t\t\t\t\t\t\ttraction += 0.1f;\n\t\t\t\t\t\t\tif (wheelState[CARWHEEL_FRONT_RIGHT] == WHEEL_STATE_SPINNING)\n\t\t\t\t\t\t\t\ttraction += 0.1f;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'R':\n\t\t\t\t\t\tif (params.m_VehicleType == VEHICLE_TYPE_BIKE) {\n\t\t\t\t\t\t\tif (wheelState[BIKEWHEEL_REAR] == WHEEL_STATE_SPINNING)\n\t\t\t\t\t\t\t\ttraction += 0.2f;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (wheelState[CARWHEEL_REAR_LEFT] == WHEEL_STATE_SPINNING)\n\t\t\t\t\t\t\t\ttraction += 0.1f;\n\t\t\t\t\t\t\tif (wheelState[CARWHEEL_REAR_RIGHT] == WHEEL_STATE_SPINNING)\n\t\t\t\t\t\t\t\ttraction += 0.1f;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if (params.m_fVelocityChange == 0.0f) {\n\t\t\t\ttraction = 0.9f;\n\t\t\t}\n\t\t\tif (transmission->fMaxVelocity <= 0.0f) {\n\t\t\t\trelativeChange = 0.0f;\n\t\t\t\tmodificator = 0.0f;\n\t\t\t} else {\n\t\t\t\tif (!isMoped && !caddyBool) {\n\t\t\t\t\tif (currentGear != 0) {\n\t\t\t\t\t\trelativeGearChange = Min(1.0f,\n\t\t\t\t\t\t\tparams.m_fVelocityChange - transmission->Gears[currentGear].fShiftDownVelocity) / transmission->fMaxVelocity * 2.5f;\n\t\t\t\t\t\tif (traction == 0.0f && veh->GetStatus() != STATUS_SIMPLE && \n\t\t\t\t\t\t\tparams.m_fVelocityChange < transmission->Gears[1].fShiftUpVelocity)\n\t\t\t\t\t\t\ttraction = 0.7f;\n\t\t\t\t\t\trelativeChange = traction * *gasPedalAudioPtr * 0.95f + (1.0f - traction) * relativeGearChange;\n\t\t\t\t\t} else {\n\t\t\t\t\t\trelativeChange = Min(1.0f,\n\t\t\t\t\t\t\t1.0f - Abs((params.m_fVelocityChange - transmission->Gears[0].fShiftDownVelocity) / transmission->fMaxReverseVelocity));\n\t\t\t\t\t}\n\t\t\t\t\tmodificator = relativeChange;\n\t\t\t\t} else {\n\t\t\t\t\tmodificator = Min(1.0f, Abs(params.m_fVelocityChange / transmission->fMaxVelocity > 1.0f));\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tif (wheelsOnGroundPrev != 0)\n\t\t\t\t*gasPedalAudioPtr *= 0.4f;\n\t\t\trelativeChange = *gasPedalAudioPtr;\n\t\t\tmodificator = relativeChange;\n\t\t}\n\t\tif (currentGear != 0 || wheelsOnGround == 0)\n\t\t\tfreq = 1200 * currentGear + 18000.0f * modificator + 14000;\n\t\telse if (params.m_VehicleType == VEHICLE_TYPE_BIKE)\n\t\t\tfreq = 22050;\n\t\telse\n\t\t\tfreq = 13000.0f * modificator + 14000;\n\t\tif (modificator >= 0.75f)\n\t\t\temittingVol = 90;\n\t\telse\n\t\t\temittingVol = modificator * (4.0f / 3.0f) * 15.0f + 75;\n\t} else {\n\t\tmodificator = 0.0f;\n\t\temittingVol = 75;\n\t}\n\tif (veh->bIsDrowning)\n\t\temittingVol /= 4;\n\tif (caddyBool) {\n\t\temittingVol = 100.0f * modificator;\n\t\tfreq = 2130.0f * modificator + 4270;\n\t\tm_sQueueSample.m_nCounter = 2;\n\t}\n\tm_sQueueSample.m_nVolume = ComputeVolume(emittingVol, SOUND_INTENSITY, m_sQueueSample.m_fDistance);\n\tif (m_sQueueSample.m_nVolume != 0) {\n\t\tif (!caddyBool) {\n\t\t\tif (veh->GetStatus() == STATUS_SIMPLE) {\n\t\t\t\tif (modificator < 0.02f) {\n\t\t\t\t\tm_sQueueSample.m_nSampleIndex = aVehicleSettings[params.m_nIndex].m_nBank - CAR_SFX_BANKS_OFFSET + SFX_CAR_IDLE_1;\n\t\t\t\t\tm_sQueueSample.m_nCounter = 52;\n\t\t\t\t\tfreq = 10000.0f * modificator + 22050;\n\t\t\t\t} else {\n\t\t\t\t\tm_sQueueSample.m_nSampleIndex = aVehicleSettings[params.m_nIndex].m_nAccelerationSampleIndex;\n\t\t\t\t\tm_sQueueSample.m_nCounter = 2;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (veh->m_fGasPedal < 0.02f) {\n\t\t\t\t\tm_sQueueSample.m_nSampleIndex = aVehicleSettings[params.m_nIndex].m_nBank - CAR_SFX_BANKS_OFFSET + SFX_CAR_IDLE_1;\n\t\t\t\t\tm_sQueueSample.m_nCounter = 52;\n\t\t\t\t\tfreq = 10000.0f * modificator + 22050;\n\t\t\t\t} else {\n\t\t\t\t\tm_sQueueSample.m_nSampleIndex = aVehicleSettings[params.m_nIndex].m_nAccelerationSampleIndex;\n\t\t\t\t\tm_sQueueSample.m_nCounter = 2;\n\t\t\t\t}\n\t\t\t}\n\t\t\tm_sQueueSample.m_nFrequency = freq + 100 * m_sQueueSample.m_nBankIndex % 1000;\n\t\t} else {\n\t\t\tif (FindVehicleOfPlayer() == params.m_pVehicle)\n\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_CAR_AFTER_ACCEL_12;\n\t\t\telse\n\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_CAR_REV_12;\n\t\t\tm_sQueueSample.m_nFrequency = freq + 20 * m_sQueueSample.m_nBankIndex % 100;\n\t\t}\n\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\tm_sQueueSample.m_bIs2D = false;\n\t\tm_sQueueSample.m_nReleasingVolumeModificator = 3;\n\t\tif (m_sQueueSample.m_nSampleIndex == SFX_CAR_IDLE_5 || m_sQueueSample.m_nSampleIndex == SFX_CAR_REV_5)\n\t\t\tm_sQueueSample.m_nFrequency /= 2;\n\t\tm_sQueueSample.m_nLoopCount = 0;\n\t\tm_sQueueSample.m_nEmittingVolume = emittingVol;\n\t\tm_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex);\n\t\tm_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex);\n\t\tm_sQueueSample.m_fSpeedMultiplier = 6.0f;\n\t\tm_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY;\n\t\tm_sQueueSample.m_bReleasingSoundFlag = false;\n\t\tm_sQueueSample.m_nReleasingVolumeDivider = 8;\n\t\tm_sQueueSample.m_bReverbFlag = true;\n\t\tm_sQueueSample.m_bRequireReflection = false;\n\t\tAddSampleToRequestedQueue();\n\t}\n}\n\nvoid\ncAudioManager::UpdateGasPedalAudio(CVehicle* veh, int vehType)\n{\n\tfloat gasPedal = Abs(veh->m_fGasPedal);\n\tfloat* gasPealAudioPtr;\n\n\tswitch(vehType) {\n\tcase VEHICLE_TYPE_CAR: gasPealAudioPtr = &((CAutomobile *)veh)->m_fGasPedalAudio; break;\n\tcase VEHICLE_TYPE_BIKE: gasPealAudioPtr = &((CBike *)veh)->m_fGasPedalAudio; break;\n\tdefault: return;\n\t}\n\tif (*gasPealAudioPtr < gasPedal)\n\t\t*gasPealAudioPtr = Min(*gasPealAudioPtr + 0.09f, gasPedal);\n\telse\n\t\t*gasPealAudioPtr = Max(*gasPealAudioPtr - 0.07f, gasPedal);\n}\n\nvoid\ncAudioManager::PlayerJustGotInCar() const\n{\n\tif (m_bIsInitialised)\n\t\tbPlayerJustEnteredCar = true;\n}\n\nvoid\ncAudioManager::PlayerJustLeftCar(void) const\n{\n\t// UNUSED: This is a perfectly empty function.\n}\n\nvoid\ncAudioManager::AddPlayerCarSample(uint8 emittingVolume, int32 freq, uint32 sample, uint8 bank, uint8 counter, bool notLooping)\n{\n\tm_sQueueSample.m_nVolume = ComputeVolume(emittingVolume, 50.f, m_sQueueSample.m_fDistance);\n\tif (m_sQueueSample.m_nVolume != 0) {\n\t\tm_sQueueSample.m_nCounter = counter;\n\t\tm_sQueueSample.m_nSampleIndex = sample;\n#ifdef GTA_PS2\n\t\tm_sQueueSample.m_nBankIndex = bank;\n#else\n\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n#endif // GTA_PS2\n\t\tm_sQueueSample.m_bIs2D = false;\n\t\tm_sQueueSample.m_nReleasingVolumeModificator = 0;\n\t\tm_sQueueSample.m_nFrequency = freq;\n\t\tif (notLooping) {\n\t\t\tm_sQueueSample.m_nLoopCount = 0;\n\t\t\tm_sQueueSample.m_nReleasingVolumeDivider = 8;\n\t\t} else {\n\t\t\tm_sQueueSample.m_nLoopCount = 1;\n\t\t}\n\t\tm_sQueueSample.m_nEmittingVolume = emittingVolume;\n\t\tm_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex);\n\t\tm_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex);\n\t\tm_sQueueSample.m_fSpeedMultiplier = 6.0f;\n\t\tm_sQueueSample.m_fSoundIntensity = 50.0f;\n\t\tm_sQueueSample.m_bReleasingSoundFlag = false;\n\t\tm_sQueueSample.m_bReverbFlag = true;\n\t\tm_sQueueSample.m_bRequireReflection = false;\n\t\tAddSampleToRequestedQueue();\n\t}\n}\n\nvoid\ncAudioManager::ProcessCesna(cVehicleParams &params)\n{\n\tif(params.m_fDistance < SQR(200)) {\n\t\tCalculateDistance(params.m_bDistanceCalculated, params.m_fDistance);\n\t\tm_sQueueSample.m_nVolume = ComputeVolume(80, 200.f, m_sQueueSample.m_fDistance);\n\t\tif(m_sQueueSample.m_nVolume != 0) {\n\t\t\tm_sQueueSample.m_nCounter = 52;\n\t\t\tm_sQueueSample.m_nSampleIndex = SFX_CESNA_IDLE;\n\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\tm_sQueueSample.m_bIs2D = false;\n\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 0;\n\t\t\tm_sQueueSample.m_nFrequency = 12500;\n\t\t\tm_sQueueSample.m_nLoopCount = 0;\n\t\t\tm_sQueueSample.m_nReleasingVolumeDivider = 8;\n\t\t\tm_sQueueSample.m_nEmittingVolume = 80;\n\t\t\tm_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex);\n\t\t\tm_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex);\n\t\t\tm_sQueueSample.m_fSpeedMultiplier = 4.0f;\n\t\t\tm_sQueueSample.m_fSoundIntensity = 200.0f;\n\t\t\tm_sQueueSample.m_bReleasingSoundFlag = false;\n\t\t\tm_sQueueSample.m_bReverbFlag = true;\n\t\t\tm_sQueueSample.m_bRequireReflection = false;\n\t\t\tAddSampleToRequestedQueue();\n\t\t}\n\t\tif(params.m_fDistance < SQR(90)) {\n\t\t\tm_sQueueSample.m_nVolume = ComputeVolume(80, 90.f, m_sQueueSample.m_fDistance);\n\t\t\tif(m_sQueueSample.m_nVolume != 0) {\n\t\t\t\tm_sQueueSample.m_nCounter = 2;\n\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_CESNA_REV;\n\t\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\t\tm_sQueueSample.m_bIs2D = false;\n\t\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 3;\n\t\t\t\tm_sQueueSample.m_nFrequency = 25000;\n\t\t\t\tm_sQueueSample.m_nLoopCount = 0;\n\t\t\t\tm_sQueueSample.m_nReleasingVolumeDivider = 4;\n\t\t\t\tm_sQueueSample.m_nEmittingVolume = 80;\n\t\t\t\tm_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex);\n\t\t\t\tm_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex);\n\t\t\t\tm_sQueueSample.m_fSpeedMultiplier = 4.0f;\n\t\t\t\tm_sQueueSample.m_fSoundIntensity = 90.0f;\n\t\t\t\tm_sQueueSample.m_bReleasingSoundFlag = false;\n\t\t\t\tm_sQueueSample.m_bReverbFlag = true;\n\t\t\t\tm_sQueueSample.m_bRequireReflection = false;\n\t\t\t\tAddSampleToRequestedQueue();\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\ncAudioManager::ProcessPlayersVehicleEngine(cVehicleParams& params, CVehicle* veh)\n{\n\tstatic int32 GearFreqAdj[] = { 6000, 6000, 3400, 1200, 0, -1000 };\n\n\ttWheelState* wheelState;\n\tCAutomobile* automobile;\n\tCBike* bike;\n\tCVector pos;\n\tfloat* gasPedalAudioPtr;\n\n\tint32 accelerateState;\n\tint32 brakeState;\n\tint32 freq;\n\tint32 baseFreq;\n\tint32 freqModifier;\n\tuint32 gearSoundLength;\n\tuint32 soundOffset;\n\tuint8 engineSoundType;\n\tuint8 wheelInUseCounter;\n\tuint8 wheelsOnGround;\n\tuint8 vol;\n\tuint8 currentGear;\n\tuint8 wheelsOnGroundPrev;\n\n\tfloat accelerationMultipler;\n\tfloat gasPedalAudio;\n\tfloat velocityChangeForAudio;\n\tfloat relativeVelocityChange;\n\tfloat time;\n\tbool channelUsed;\n\tbool lostTraction;\n\tbool noGearBox;\n\tbool stuckInSand;\n\tbool processedAccelSampleStopped;\n\tbool isMoped;\n\n\tstatic uint32 gearSoundStartTime = CTimer::GetTimeInMilliseconds();\n\tstatic int32 nCruising = 0;\n\tstatic int16 LastAccel = 0;\n\tstatic uint8 CurrentPretendGear = 1;\n\tstatic bool bLostTractionLastFrame = false;\n\tstatic bool bHandbrakeOnLastFrame = false;\n\tstatic bool bAccelSampleStopped = true;\n\n\tlostTraction = false;\n\tisMoped = params.m_pVehicle->m_modelIndex == MI_PIZZABOY || params.m_pVehicle->m_modelIndex == MI_FAGGIO;\n\tprocessedAccelSampleStopped = false;\n\tif (bPlayerJustEnteredCar) {\n\t\tbAccelSampleStopped = true;\n\t\tbPlayerJustEnteredCar = false;\n\t\tnCruising = 0;\n\t\tLastAccel = 0;\n\t\tbLostTractionLastFrame = false;\n\t\tCurrentPretendGear = 1;\n\t\tbHandbrakeOnLastFrame = false;\n\t}\n\tif (CReplay::IsPlayingBack()) {\n\t\taccelerateState = (255.0f * clamp(params.m_pVehicle->m_fGasPedal, 0.0f, 1.0f));\n\t\tbrakeState = (255.0f * clamp(params.m_pVehicle->m_fBrakePedal, 0.0f, 1.0f));\n\t} else {\n\t\taccelerateState = Pads[0].GetAccelerate();\n\t\tbrakeState = Pads[0].GetBrake();\n\t}\n\tchannelUsed = SampleManager.GetChannelUsedFlag(m_nActiveSamples);\n\tif (isMoped) {\n\t\tCurrentPretendGear = params.m_pTransmission->nNumberOfGears;\n\t\tcurrentGear = CurrentPretendGear;\n\t\tif (params.m_pVehicle->bIsHandbrakeOn) {\n\t\t\tbrakeState = 0;\n\t\t\tnCruising = 0;\n\t\t\tLastAccel = 0;\n\t\t\taccelerateState = 0;\n\t\t} else {\n\t\t\tnCruising = 1;\n\t\t}\n\t} else {\n\t\tcurrentGear = params.m_pVehicle->m_nCurrentGear;\n\t}\n\n\tswitch (params.m_VehicleType) {\n\tcase VEHICLE_TYPE_CAR:\n\t\tautomobile = (CAutomobile*)params.m_pVehicle;\n\t\twheelsOnGround = automobile->m_nDriveWheelsOnGround;\n\t\twheelsOnGroundPrev = automobile->m_nDriveWheelsOnGroundPrev;\n\t\tgasPedalAudioPtr = &automobile->m_fGasPedalAudio;\n\t\twheelState = automobile->m_aWheelState;\n\t\tvelocityChangeForAudio = automobile->m_fVelocityChangeForAudio;\n\t\tbreak;\n\tcase VEHICLE_TYPE_BIKE:\n\t\tbike = (CBike*)params.m_pVehicle;\n\t\twheelsOnGround = bike->m_nDriveWheelsOnGround;\n\t\twheelsOnGroundPrev = bike->m_nDriveWheelsOnGroundPrev;\n\t\tgasPedalAudioPtr = &bike->m_fGasPedalAudio;\n\t\twheelState = bike->m_aWheelState;\n\t\tvelocityChangeForAudio = bike->m_fVelocityChangeForAudio;\n\t\tbreak;\n\tdefault:\n\t\tdebug(\" ** AUDIOLOG: Unrecognised vehicle type %d in ProcessVehicleEngine() * \\n\", params.m_VehicleType);\n\t\treturn;\n\t}\n\tif (!isMoped) {\n\t\tswitch (params.m_pTransmission->nDriveType) {\n\t\tcase '4':\n\t\t\tif (params.m_VehicleType != VEHICLE_TYPE_BIKE) {\n\t\t\t\twheelInUseCounter = 0;\n\t\t\t\tfor (uint8 i = 0; i < 4; i++) {\n\t\t\t\t\tif (wheelState[i] != WHEEL_STATE_NORMAL)\n\t\t\t\t\t\t++wheelInUseCounter;\n\t\t\t\t}\n\t\t\t\tif (wheelInUseCounter > 2)\n\t\t\t\t\tlostTraction = true;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase 'F':\n\t\t\tif (params.m_VehicleType == VEHICLE_TYPE_BIKE) {\n\t\t\t\tif (wheelState[BIKEWHEEL_FRONT] != WHEEL_STATE_NORMAL)\n\t\t\t\t\tlostTraction = true;\n\t\t\t} else {\n\t\t\t\tif ((wheelState[CARWHEEL_FRONT_LEFT] != WHEEL_STATE_NORMAL || wheelState[CARWHEEL_FRONT_RIGHT] != WHEEL_STATE_NORMAL) &&\n\t\t\t\t\t(wheelState[CARWHEEL_REAR_LEFT] != WHEEL_STATE_NORMAL || wheelState[CARWHEEL_REAR_RIGHT] != WHEEL_STATE_NORMAL))\n\t\t\t\t\tlostTraction = true;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase 'R':\n\t\t\tif (params.m_VehicleType == VEHICLE_TYPE_BIKE) {\n\t\t\t\tif (wheelState[BIKEWHEEL_REAR] != WHEEL_STATE_NORMAL)\n\t\t\t\t\tlostTraction = true;\n\t\t\t} else {\n\t\t\t\tif (wheelState[CARWHEEL_REAR_LEFT] != WHEEL_STATE_NORMAL || wheelState[CARWHEEL_REAR_RIGHT] != WHEEL_STATE_NORMAL)\n\t\t\t\t\tlostTraction = true;\n\t\t\t}\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\t}\n\tif (params.m_fVelocityChange != 0.0f) {\n\t\ttime = params.m_pVehicle->m_vecMoveSpeed.z / params.m_fVelocityChange;\n\t\tif (time > 0.0f)\n\t\t\tfreqModifier = -(Min(0.2f, time) * 3000.0f * 5.0f);\n\t\telse\n\t\t\tfreqModifier = -(Max(-0.2f, time) * 3000.0f * 5.0f);\n\t\tif (params.m_fVelocityChange < -0.001f)\n\t\t\tfreqModifier = -freqModifier;\n\t} else\n\t\tfreqModifier = 0;\n\tif (params.m_VehicleType == VEHICLE_TYPE_BIKE && bike->bExtraSpeed)\n\t\tfreqModifier += 1400;\n\tgearSoundLength = 0;\n\tengineSoundType = aVehicleSettings[params.m_nIndex].m_nBank;\n\tsoundOffset = 3 * (engineSoundType - CAR_SFX_BANKS_OFFSET);\n\tnoGearBox = false;\n\tswitch (engineSoundType) {\n\tcase SFX_BANK_PONTIAC:\n\t\tgearSoundLength = 2526;\n\t\tbreak;\n\tcase SFX_BANK_PORSCHE:\n\t\tgearSoundLength = 3587;\n\t\tbreak;\n\tcase SFX_BANK_SPIDER:\n\t\tgearSoundLength = 4898;\n\t\tbreak;\n\tcase SFX_BANK_MERC:\n\t\tgearSoundLength = 4003;\n\t\tbreak;\n\tcase SFX_BANK_TRUCK:\n\t\tgearSoundLength = 6289;\n\t\tbreak;\n\tcase SFX_BANK_HOTROD:\n\t\tgearSoundLength = 2766;\n\t\tbreak;\n\tcase SFX_BANK_COBRA:\n\t\tgearSoundLength = 3523;\n\t\tbreak;\n\tcase SFX_BANK_PONTIAC_SLOW:\n\t\tgearSoundLength = 2773;\n\t\tbreak;\n\tcase SFX_BANK_CADILLAC:\n\t\tgearSoundLength = 2560;\n\t\tbreak;\n\tcase SFX_BANK_PATHFINDER:\n\t\tgearSoundLength = 4228;\n\t\tbreak;\n\tcase SFX_BANK_PACARD:\n\t\tgearSoundLength = 4648;\n\t\tbreak;\n\tcase SFX_BANK_VTWIN:\n\t\tgearSoundLength = 3480;\n\t\tbreak;\n\tcase SFX_BANK_HONDA250:\n\t\tgearSoundLength = 2380;\n\t\tbreak;\n\tcase SFX_BANK_SPORTS_BIKE:\n\t\tgearSoundLength = 2410;\n\t\tbreak;\n\tdefault:\n\t\tnoGearBox = true;\n\t\tbreak;\n\t}\n\tif (!channelUsed || nCruising || noGearBox) {\n\t\tgearSoundStartTime = CTimer::GetTimeInMilliseconds();\n\t} else {\n\t\tgearSoundLength -= 1000;\n\t\tif (CTimer::GetTimeInMilliseconds() - gearSoundStartTime > gearSoundLength) {\n\t\t\tchannelUsed = false;\n\t\t\tgearSoundStartTime = CTimer::GetTimeInMilliseconds();\n\t\t}\n\t}\n\trelativeVelocityChange = 2.0f * params.m_fVelocityChange / params.m_pTransmission->fMaxVelocity;\n\taccelerationMultipler = clamp(relativeVelocityChange, 0.0f, 1.0f);\n\tgasPedalAudio = accelerationMultipler;\n\tswitch (engineSoundType) {\n\tcase SFX_BANK_MOPED:\n\t\t++soundOffset;\n\t\tbreak;\n\tcase SFX_BANK_HONDA250:\n\t\tsoundOffset += 2;\n\t\tbreak;\n\tcase SFX_BANK_SPORTS_BIKE:\n\t\tsoundOffset += 3;\n\t\tbreak;\n\tdefault:\n\t\tbreak;\n\t}\n\tif (accelerateState <= 0) {\n\t\tif (params.m_fVelocityChange < -0.001f) {\n\t\t\tif (channelUsed) {\n\t\t\t\tSampleManager.StopChannel(m_nActiveSamples);\n\t\t\t\tbAccelSampleStopped = true;\n\t\t\t}\n\t\t\tif (wheelsOnGround == 0 || params.m_pVehicle->bIsHandbrakeOn || lostTraction)\n\t\t\t\tgasPedalAudio = *gasPedalAudioPtr;\n\t\t\telse if (params.m_VehicleType == VEHICLE_TYPE_BIKE)\n\t\t\t\tgasPedalAudio = 0.0f;\n\t\t\telse\n\t\t\t\tgasPedalAudio = Min(1.0f, params.m_fVelocityChange / params.m_pTransmission->fMaxReverseVelocity);\n\t\t\t*gasPedalAudioPtr = Max(0.0f, gasPedalAudio);\n\t\t} else if (LastAccel > 0) {\n\t\t\tif (channelUsed) {\n\t\t\t\tSampleManager.StopChannel(m_nActiveSamples);\n\t\t\t\tbAccelSampleStopped = true;\n\t\t\t}\n\t\t\tnCruising = 0;\n\t\t\tif (wheelsOnGround == 0\n\t\t\t\t|| params.m_pVehicle->bIsHandbrakeOn\n\t\t\t\t|| lostTraction\n\t\t\t\t|| params.m_fVelocityChange < 0.01f && *gasPedalAudioPtr > 0.2f) {\n\t\t\t\tif (isMoped) {\n\t\t\t\t\tgasPedalAudio = 0.0f;\n\t\t\t\t} else {\n\t\t\t\t\t*gasPedalAudioPtr *= 0.6f;\n\t\t\t\t\tgasPedalAudio = *gasPedalAudioPtr;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (gasPedalAudio > 0.05f) {\n\t\t\t\tfreq = (5000.f * (gasPedalAudio - 0.05f) * 20.f / 19) + 19000;\n\t\t\t\tvol = (25.0f * (gasPedalAudio - 0.05f) * 20.f / 19) + 40;\n\t\t\t\tif (params.m_pVehicle->bIsDrowning)\n\t\t\t\t\tvol /= 4;\n\t\t\t\tif (engineSoundType == SFX_BANK_TRUCK)\n\t\t\t\t\tfreq /= 2;\n\t\t\t\tAddPlayerCarSample(vol, freq, soundOffset + SFX_CAR_FINGER_OFF_ACCEL_1, engineSoundType, 63, false);\n\t\t\t}\n\t\t}\n\t\tfreq = (10000.f * gasPedalAudio) + 22050;\n\t\tvol = 110 - (40.0f * gasPedalAudio);\n\t\tif (engineSoundType == SFX_BANK_TRUCK)\n\t\t\tfreq /= 2;\n\t\tif (params.m_pVehicle->bIsDrowning)\n\t\t\tvol /= 4;\n\t\tAddPlayerCarSample(vol, freq, engineSoundType - CAR_SFX_BANKS_OFFSET + SFX_CAR_IDLE_1, SFX_BANK_0, 52, true);\n\n\t\tCurrentPretendGear = Max(1, currentGear);\n\t}\n\telse {\n\t\tif (nCruising == 0){\n\t\t\tstuckInSand = params.m_VehicleType == VEHICLE_TYPE_CAR && ((CAutomobile*)params.m_pVehicle)->bStuckInSand;\n\t\t\tif (accelerateState < 150 || wheelsOnGround == 0 || params.m_pVehicle->bIsHandbrakeOn || lostTraction\n\t\t\t\t|| (currentGear < 2 && params.m_fVelocityChange - velocityChangeForAudio < 0.01f) || brakeState > 0) {\n\n\t\t\t\tif (((wheelsOnGround && !params.m_pVehicle->bIsHandbrakeOn && !lostTraction ) || stuckInSand) && brakeState <= 0) {\n\t\t\t\t\tbaseFreq = (8000.0f * accelerationMultipler) + 16000;\n\t\t\t\t\tvol = (25.0f * accelerationMultipler) + 60;\n\t\t\t\t\t*gasPedalAudioPtr = accelerationMultipler;\n\t\t\t\t} else {\n\t\t\t\t\tif (wheelsOnGround == 0 && wheelsOnGroundPrev != 0 || (params.m_pVehicle->bIsHandbrakeOn && !bHandbrakeOnLastFrame || lostTraction && !bLostTractionLastFrame)\n\t\t\t\t\t\t&& wheelsOnGround != 0) {\n\t\t\t\t\t\t*gasPedalAudioPtr *= 0.6f;\n\t\t\t\t\t}\n\t\t\t\t\tfreqModifier = 0;\n\t\t\t\t\tif (engineSoundType != SFX_BANK_GOLF_CART && engineSoundType != SFX_BANK_CAR_CHAINSAW)\n\t\t\t\t\t\tbaseFreq = (25000.0f * *gasPedalAudioPtr) + 14000;\n\t\t\t\t\telse\n\t\t\t\t\t\tbaseFreq = (15000.0f * *gasPedalAudioPtr) + 14000;\n\t\t\t\t\tvol = (25.0f * *gasPedalAudioPtr) + 60;\n\t\t\t\t}\n\t\t\t\tfreq = freqModifier + baseFreq;\n\t\t\t\tif (engineSoundType == SFX_BANK_TRUCK)\n\t\t\t\t\tfreq /= 2;\n\t\t\t\tif (channelUsed) {\n\t\t\t\t\tSampleManager.StopChannel(m_nActiveSamples);\n\t\t\t\t\tbAccelSampleStopped = true;\n\t\t\t\t}\n\t\t\t\tif (params.m_pVehicle->bIsDrowning)\n\t\t\t\t\tvol /= 4;\n\t\t\t\tAddPlayerCarSample(vol, freq, engineSoundType - CAR_SFX_BANKS_OFFSET + SFX_CAR_REV_1, SFX_BANK_0, 2, true);\n\t\t\t} else {\n\t\t\t\tTranslateEntity(&m_sQueueSample.m_vecPos, &pos);\n\t\t\t\tif (bAccelSampleStopped) {\n\t\t\t\t\tif (CurrentPretendGear != 1 || currentGear != 2)\n\t\t\t\t\t\tCurrentPretendGear = Max(1, currentGear - 1);\n\t\t\t\t\tprocessedAccelSampleStopped = true;\n\t\t\t\t\tbAccelSampleStopped = false;\n\t\t\t\t}\n\t\t\t\tif (channelUsed) {\n\t\t\t\t\tSampleManager.SetChannelEmittingVolume(m_nActiveSamples, 120);\n\t\t\t\t\tSampleManager.SetChannel3DPosition(m_nActiveSamples, pos.x, pos.y, pos.z);\n\t\t\t\t\tSampleManager.SetChannel3DDistances(m_nActiveSamples, 50.0f, 12.5f);\n\t\t\t\t\tfreq = (GearFreqAdj[CurrentPretendGear] + freqModifier + 22050) ;\n\t\t\t\t\tif (engineSoundType == SFX_BANK_TRUCK)\n\t\t\t\t\t\tfreq /= 2;\n\t\t\t\t\tSampleManager.SetChannelFrequency(m_nActiveSamples, freq);\n\t\t\t\t\tif (!channelUsed) {\n\t\t\t\t\t\tSampleManager.SetChannelReverbFlag(m_nActiveSamples, m_bDynamicAcousticModelingStatus != false);\n\t\t\t\t\t\tSampleManager.StartChannel(m_nActiveSamples);\n\t\t\t\t\t}\n\t\t\t\t} else if (processedAccelSampleStopped) {\n\t\t\t\t\tgearSoundStartTime = CTimer::GetTimeInMilliseconds();\n\t\t\t\t\tparams.m_pVehicle->bAudioChangingGear = true;\n\t\t\t\t\tif (!SampleManager.InitialiseChannel(m_nActiveSamples, soundOffset + SFX_CAR_ACCEL_1, SFX_BANK_0))\n\t\t\t\t\t\treturn;\n\t\t\t\t\tSampleManager.SetChannelLoopCount(m_nActiveSamples, 1);\n\t\t\t\t\tSampleManager.SetChannelLoopPoints(m_nActiveSamples, 0, -1);\n\n\t\t\t\t\tSampleManager.SetChannelEmittingVolume(m_nActiveSamples, 120);\n\t\t\t\t\tSampleManager.SetChannel3DPosition(m_nActiveSamples, pos.x, pos.y, pos.z);\n\t\t\t\t\tSampleManager.SetChannel3DDistances(m_nActiveSamples, 50.0f, 12.5f);\n\t\t\t\t\tfreq = (GearFreqAdj[CurrentPretendGear] + freqModifier + 22050);\n\t\t\t\t\tif (engineSoundType == SFX_BANK_TRUCK)\n\t\t\t\t\t\tfreq /= 2;\n\t\t\t\t\tSampleManager.SetChannelFrequency(m_nActiveSamples, freq);\n\t\t\t\t\tif (!channelUsed) {\n\t\t\t\t\t\tSampleManager.SetChannelReverbFlag(m_nActiveSamples, m_bDynamicAcousticModelingStatus != false);\n\t\t\t\t\t\tSampleManager.StartChannel(m_nActiveSamples);\n\t\t\t\t\t}\n\t\t\t\t} else if (CurrentPretendGear < params.m_pTransmission->nNumberOfGears - 1) {\n\t\t\t\t\t++CurrentPretendGear;\n\t\t\t\t\tgearSoundStartTime = CTimer::GetTimeInMilliseconds();\n\t\t\t\t\tparams.m_pVehicle->bAudioChangingGear = true;\n\t\t\t\t\tif (!SampleManager.InitialiseChannel(m_nActiveSamples, soundOffset + SFX_CAR_ACCEL_1, SFX_BANK_0))\n\t\t\t\t\t\treturn;\n\t\t\t\t\tSampleManager.SetChannelLoopCount(m_nActiveSamples, 1);\n\t\t\t\t\tSampleManager.SetChannelLoopPoints(m_nActiveSamples, 0, -1);\n\n\t\t\t\t\tSampleManager.SetChannelEmittingVolume(m_nActiveSamples, 120);\n\t\t\t\t\tSampleManager.SetChannel3DPosition(m_nActiveSamples, pos.x, pos.y, pos.z);\n\t\t\t\t\tSampleManager.SetChannel3DDistances(m_nActiveSamples, 50.0f, 12.5f);\n\t\t\t\t\tfreq = (GearFreqAdj[CurrentPretendGear] + freqModifier + 22050);\n\t\t\t\t\tif (engineSoundType == SFX_BANK_TRUCK)\n\t\t\t\t\t\tfreq /= 2;\n\t\t\t\t\tSampleManager.SetChannelFrequency(m_nActiveSamples, freq);\n\t\t\t\t\tif (!channelUsed) {\n\t\t\t\t\t\tSampleManager.SetChannelReverbFlag(m_nActiveSamples, m_bDynamicAcousticModelingStatus != false);\n\t\t\t\t\t\tSampleManager.StartChannel(m_nActiveSamples);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tnCruising = 1;\n\t\t\t\t\tgoto PlayCruising;\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\nPlayCruising:\n\t\t\tbAccelSampleStopped = true;\n\t\t\tSampleManager.StopChannel(m_nActiveSamples);\n\t\t\tif (isMoped || accelerateState >= 150 && wheelsOnGround && brakeState <= 0 && !params.m_pVehicle->bIsHandbrakeOn\n\t\t\t\t&& !lostTraction && currentGear >= params.m_pTransmission->nNumberOfGears - 1) {\n\t\t\t\tif (accelerateState >= 220 && params.m_fVelocityChange + 0.001f >= velocityChangeForAudio) {\n\t\t\t\t\tif (nCruising < 800)\n\t\t\t\t\t\t++nCruising;\n\t\t\t\t} else if (nCruising > 3) {\n\t\t\t\t\t--nCruising;\n\t\t\t\t}\n\t\t\t\tfreq = 27 * nCruising + freqModifier + 22050;\n\t\t\t\tif (engineSoundType == SFX_BANK_TRUCK)\n\t\t\t\t\tfreq /= 2;\n\t\t\t\tAddPlayerCarSample(120, freq, soundOffset + SFX_CAR_AFTER_ACCEL_1, engineSoundType, 64, true);\n\t\t\t} else {\n\t\t\t\tnCruising = 0;\n\t\t\t}\n\t\t}\n\t}\n\tLastAccel = accelerateState;\n\tbHandbrakeOnLastFrame = params.m_pVehicle->bIsHandbrakeOn;\n\tbLostTractionLastFrame = lostTraction;\n\treturn;\n}\n\nbool\ncAudioManager::ProcessVehicleSkidding(cVehicleParams& params)\n{\n\tconst float SOUND_INTENSITY = 40.0f;\n\n\tCAutomobile *automobile;\n\tCBike *bike;\n\tuint8 numWheels;\n\tuint8 wheelsOnGround;\n\tfloat gasPedalAudio;\n\ttWheelState* wheelStateArr;\n\n\n\tcTransmission *transmission;\n\tint32 emittingVol;\n\tfloat newSkidVal = 0.0f;\n\tfloat skidVal = 0.0f;\n\n\tif (params.m_fDistance >= SQR(SOUND_INTENSITY))\n\t\treturn false;\n\tswitch (params.m_VehicleType) {\n\tcase VEHICLE_TYPE_CAR:\n\t\tautomobile = (CAutomobile*)params.m_pVehicle;\n\t\tnumWheels = 4;\n\t\twheelStateArr = automobile->m_aWheelState;\n\t\twheelsOnGround = automobile->m_nWheelsOnGround;\n\t\tgasPedalAudio = automobile->m_fGasPedalAudio;\n\t\tbreak;\n\tcase VEHICLE_TYPE_BIKE:\n\t\tbike = (CBike*)params.m_pVehicle;\n\t\tnumWheels = 2;\n\t\twheelStateArr = bike->m_aWheelState;\n\t\twheelsOnGround = bike->m_nWheelsOnGround;\n\t\tgasPedalAudio = bike->m_fGasPedalAudio;\n\t\tbreak;\n\tdefault:\n\t\tdebug(\"\\n * AUDIOLOG:  ProcessVehicleSkidding() Unsupported vehicle type %d * \\n\", params.m_VehicleType);\n\t\treturn true;\n\t}\n\tif (wheelsOnGround == 0)\n\t\treturn true;\n\tCalculateDistance(params.m_bDistanceCalculated, params.m_fDistance);\n\n\tfor (int32 i = 0; i < numWheels; i++) {\n\t\tif (wheelStateArr[i] == WHEEL_STATE_NORMAL)\n\t\t\tcontinue;\n\t\ttransmission = params.m_pTransmission;\n\t\tswitch (transmission->nDriveType) {\n\t\tcase '4':\n\t\t\tnewSkidVal = GetVehicleDriveWheelSkidValue(params.m_pVehicle, wheelStateArr[i], gasPedalAudio, transmission, params.m_fVelocityChange);\n\t\t\tbreak;\n\t\tcase 'F':\n\t\t\tif (i == CARWHEEL_FRONT_LEFT || i == CARWHEEL_FRONT_RIGHT)\n\t\t\t\tnewSkidVal = GetVehicleDriveWheelSkidValue(params.m_pVehicle, wheelStateArr[i], gasPedalAudio, transmission, params.m_fVelocityChange);\n\t\t\telse\n\t\t\t\tnewSkidVal = GetVehicleNonDriveWheelSkidValue(params.m_pVehicle, wheelStateArr[i], transmission, params.m_fVelocityChange);\n\t\t\tbreak;\n\t\tcase 'R':\n\t\t\tif (i == CARWHEEL_REAR_LEFT || i == CARWHEEL_REAR_RIGHT)\n\t\t\t\tnewSkidVal = GetVehicleDriveWheelSkidValue(params.m_pVehicle, wheelStateArr[i], gasPedalAudio, transmission, params.m_fVelocityChange);\n\t\t\telse\n\t\t\t\tnewSkidVal = GetVehicleNonDriveWheelSkidValue(params.m_pVehicle, wheelStateArr[i], transmission, params.m_fVelocityChange);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\t\tskidVal = Max(skidVal, newSkidVal);\n\t}\n\n\tif (skidVal > 0.0f) {\n\t\temittingVol = 50.f * skidVal;\n\t\tm_sQueueSample.m_nVolume = ComputeVolume(emittingVol, SOUND_INTENSITY, m_sQueueSample.m_fDistance);\n\t\tif (m_sQueueSample.m_nVolume != 0) {\n\t\t\tm_sQueueSample.m_nCounter = 3;\n\t\t\tswitch (params.m_pVehicle->m_nSurfaceTouched) {\n\t\t\tcase SURFACE_GRASS:\n\t\t\tcase SURFACE_HEDGE:\n\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_RAIN;\n\t\t\t\temittingVol /= 4;\n\t\t\t\tm_sQueueSample.m_nFrequency = 13000.f * skidVal + 35000.f;\n\t\t\t\tm_sQueueSample.m_nVolume /= 4;\n\t\t\t\tif (m_sQueueSample.m_nVolume == 0)\n\t\t\t\t\treturn true;\n\t\t\t\tbreak;\n\t\t\tcase SURFACE_GRAVEL:\n\t\t\tcase SURFACE_MUD_DRY:\n\t\t\tcase SURFACE_SAND:\n\t\t\tcase SURFACE_WATER:\n\t\t\tcase SURFACE_SAND_BEACH:\n\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_GRAVEL_SKID;\n\t\t\t\tm_sQueueSample.m_nFrequency = 6000.f * skidVal + 10000.f;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_SKID;\n\t\t\t\tm_sQueueSample.m_nFrequency = 5000.f * skidVal + 11000.f;\n\t\t\t\tif (params.m_VehicleType == VEHICLE_TYPE_BIKE)\n\t\t\t\t\tm_sQueueSample.m_nFrequency += 2000;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\tm_sQueueSample.m_bIs2D = false;\n\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 8;\n\t\t\tm_sQueueSample.m_nLoopCount = 0;\n\t\t\tm_sQueueSample.m_nEmittingVolume = emittingVol;\n\t\t\tm_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex);\n\t\t\tm_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex);\n\t\t\tm_sQueueSample.m_fSpeedMultiplier = 3.0f;\n\t\t\tm_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY;\n\t\t\tm_sQueueSample.m_bReleasingSoundFlag = false;\n\t\t\tm_sQueueSample.m_nReleasingVolumeDivider = 3;\n\t\t\tm_sQueueSample.m_bReverbFlag = true;\n\t\t\tm_sQueueSample.m_bRequireReflection = false;\n\t\t\tAddSampleToRequestedQueue();\n\t\t}\n\t}\n\treturn true;\n}\n\nfloat\ncAudioManager::GetVehicleDriveWheelSkidValue(CVehicle *veh, tWheelState wheelState, float gasPedalAudio, cTransmission *transmission, float velocityChange)\n{\n\tfloat relativeVelChange = 0.0f;\n\tfloat velChange;\n\tfloat relativeVel;\n\n\tswitch (wheelState)\n\t{\n\tcase WHEEL_STATE_SPINNING:\n\t\tif (gasPedalAudio > 0.4f)\n\t\t\trelativeVelChange = (gasPedalAudio - 0.4f) * (5.0f / 3.0f) * 0.75f;\n\t\tbreak;\n\tcase WHEEL_STATE_SKIDDING:\n\t\trelativeVelChange = Min(1.0f, Abs(velocityChange) / transmission->fMaxVelocity);\n\t\tbreak;\n\tcase WHEEL_STATE_FIXED:\n\t\trelativeVel = gasPedalAudio;\n\t\tif (relativeVel > 0.4f)\n\t\t\trelativeVel = (gasPedalAudio - 0.4f) * (5.0f / 3.0f);\n\n\t\tvelChange = Abs(velocityChange);\n\t\tif (velChange > 0.04f)\n\t\t\trelativeVelChange = Min(1.0f, velChange / transmission->fMaxVelocity);\n\t\tif (relativeVel > relativeVelChange)\n\t\t\trelativeVelChange = relativeVel;\n\n\t\tbreak;\n\tdefault:\n\t\tbreak;\n\t}\n\n\treturn Max(relativeVelChange, Min(1.0f, Abs(veh->m_vecTurnSpeed.z) * 20.0f));\n}\n\nfloat\ncAudioManager::GetVehicleNonDriveWheelSkidValue(CVehicle *veh, tWheelState wheelState, cTransmission *transmission, float velocityChange)\n{\n\tfloat relativeVelChange = 0.0f;\n\n\tif (wheelState == WHEEL_STATE_SKIDDING)\n\t\trelativeVelChange = Min(1.0f, Abs(velocityChange) / transmission->fMaxVelocity);\n\n\treturn Max(relativeVelChange, Min(1.0f, Abs(veh->m_vecTurnSpeed.z) * 20.0f));\n}\n\nbool\ncAudioManager::ProcessVehicleHorn(cVehicleParams& params)\n{\n\tconst float SOUND_INTENSITY = 40.0f;\n\n\tCVehicle *veh;\n\tuint8 volume;\n\n\tif (params.m_fDistance >= SQR(SOUND_INTENSITY))\n\t\treturn false;\n\n\tveh = params.m_pVehicle;\n\tif (veh->m_bSirenOrAlarm && UsesSirenSwitching(params))\n\t\treturn true;\n\n\tif (veh->m_modelIndex == MI_MRWHOOP)\n\t\treturn true;\n\n\tif (veh->IsAlarmOn())\n\t\treturn true;\n\n\tif (veh->m_nCarHornTimer != 0) {\n\t\tif (veh->GetStatus() != STATUS_PLAYER) {\n\t\t\tveh->m_nCarHornTimer = Min(44, veh->m_nCarHornTimer);\n\t\t\tif (veh->m_nCarHornTimer == 44)\n\t\t\t\tveh->m_nCarHornPattern = (m_FrameCounter + m_sQueueSample.m_nEntityIndex) & 7;\n\n\t\t\tif (!hornPatternsArray[veh->m_nCarHornPattern][44 - veh->m_nCarHornTimer])\n\t\t\t\treturn true;\n\t\t}\n\n\t\tCalculateDistance(params.m_bDistanceCalculated, params.m_fDistance);\n\t\tvolume = veh->bIsDrowning ? 20 : 80;\n\t\tm_sQueueSample.m_nVolume = ComputeVolume(volume, SOUND_INTENSITY, m_sQueueSample.m_fDistance);\n\t\tif (m_sQueueSample.m_nVolume != 0) {\n\t\t\tm_sQueueSample.m_nCounter = 4;\n\t\t\tm_sQueueSample.m_nSampleIndex = aVehicleSettings[params.m_nIndex].m_nHornSample;\n\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\tm_sQueueSample.m_bIs2D = false;\n\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 2;\n\t\t\tm_sQueueSample.m_nFrequency = aVehicleSettings[params.m_nIndex].m_nHornFrequency;\n\t\t\tm_sQueueSample.m_nLoopCount = 0;\n#ifdef FIX_BUGS\n\t\t\tm_sQueueSample.m_nEmittingVolume = volume;\n#else\n\t\t\tm_sQueueSample.m_nEmittingVolume = 80;\n#endif\n\t\t\tm_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex);\n\t\t\tm_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex);\n\t\t\tm_sQueueSample.m_fSpeedMultiplier = 5.0f;\n\t\t\tm_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY;\n\t\t\tm_sQueueSample.m_bReleasingSoundFlag = false;\n\t\t\tm_sQueueSample.m_nReleasingVolumeDivider = 4;\n\t\t\tm_sQueueSample.m_bReverbFlag = true;\n\t\t\tm_sQueueSample.m_bRequireReflection = false;\n\t\t\tAddSampleToRequestedQueue();\n\t\t}\n\t}\n\treturn true;\n}\n\nbool\ncAudioManager::UsesSiren(cVehicleParams& params) const\n{\n\treturn params.m_pVehicle->UsesSiren();\n}\n\nbool\ncAudioManager::UsesSirenSwitching(cVehicleParams& params) const\n{\n\tif (params.m_nIndex == FIRETRUK || params.m_nIndex == MRWHOOP)\n\t\treturn false;\n\treturn UsesSiren(params);\n}\n\nbool\ncAudioManager::ProcessVehicleSirenOrAlarm(cVehicleParams& params)\n{\n\tconst float SOUND_INTENSITY = 110.0f;\n\n\tCVehicle *veh;\n\tuint8 volume;\n\n\tif (params.m_fDistance >= SQR(SOUND_INTENSITY))\n\t\treturn false;\n\n\tveh = params.m_pVehicle;\n\tif (!veh->m_bSirenOrAlarm && !veh->IsAlarmOn())\n\t\treturn true;\n\n\tif (veh->IsAlarmOn()) {\n\t\tif (CTimer::GetTimeInMilliseconds() > veh->m_nCarHornTimer)\n\t\t\tveh->m_nCarHornTimer = CTimer::GetTimeInMilliseconds() + 750;\n\n\t\tif (veh->m_nCarHornTimer < CTimer::GetTimeInMilliseconds() + 375)\n\t\t\treturn true;\n\t}\n\n\tCalculateDistance(params.m_bDistanceCalculated, params.m_fDistance);\n\tvolume = veh->bIsDrowning ? 20 : 80;\n\tm_sQueueSample.m_nVolume = ComputeVolume(volume, SOUND_INTENSITY, m_sQueueSample.m_fDistance);\n\tif (m_sQueueSample.m_nVolume != 0) {\n\t\tm_sQueueSample.m_nCounter = 5;\n\t\tif (UsesSiren(params)) {\n\t\t\tif (params.m_pVehicle->GetStatus() == STATUS_ABANDONED)\n\t\t\t\treturn true;\n\t\t\tif (veh->m_nCarHornTimer != 0 && params.m_nIndex != FIRETRUK && params.m_nIndex != MRWHOOP) {\n\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_SIREN_FAST;\n\t\t\t\tif (params.m_nIndex == FBIRANCH)\n\t\t\t\t\tm_sQueueSample.m_nFrequency = 12668;\n\t\t\t\telse\n\t\t\t\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_SIREN_FAST);\n\t\t\t\tm_sQueueSample.m_nCounter = 60;\n\t\t\t} else if (params.m_nIndex == VICECHEE) {\n\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_POLICE_SIREN_SLOW;\n\t\t\t\tm_sQueueSample.m_nFrequency = 11440;\n\t\t\t} else {\n\t\t\t\tm_sQueueSample.m_nSampleIndex = aVehicleSettings[params.m_nIndex].m_nSirenOrAlarmSample;\n\t\t\t\tm_sQueueSample.m_nFrequency = aVehicleSettings[params.m_nIndex].m_nSirenOrAlarmFrequency;\n\t\t\t}\n\t\t} else {\n\t\t\tm_sQueueSample.m_nSampleIndex = aVehicleSettings[params.m_nIndex].m_nHornSample;\n\t\t\tm_sQueueSample.m_nFrequency = aVehicleSettings[params.m_nIndex].m_nHornFrequency;\n\t\t}\n\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\tm_sQueueSample.m_bIs2D = false;\n\t\tm_sQueueSample.m_nReleasingVolumeModificator = 1;\n\t\tm_sQueueSample.m_nLoopCount = 0;\n\t\tm_sQueueSample.m_nEmittingVolume = volume;\n\t\tm_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex);\n\t\tm_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex);\n\t\tm_sQueueSample.m_fSpeedMultiplier = 7.0f;\n\t\tm_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY;\n\t\tm_sQueueSample.m_bReleasingSoundFlag = false;\n\t\tm_sQueueSample.m_nReleasingVolumeDivider = 5;\n\t\tm_sQueueSample.m_bReverbFlag = true;\n\t\tm_sQueueSample.m_bRequireReflection = false;\n\t\tAddSampleToRequestedQueue();\n\t}\n\treturn true;\n}\n\nbool\ncAudioManager::UsesReverseWarning(int32 model) const\n{\n\treturn model == LINERUN || model == FIRETRUK || model == BUS || model == COACH || model == PACKER || model == FLATBED;\n}\n\nbool\ncAudioManager::ProcessVehicleReverseWarning(cVehicleParams& params)\n{\n\tconst float SOUND_INTENSITY = 50.0f;\n\n\tCVehicle *veh = params.m_pVehicle;\n\tuint8 volume;\n\n\tif (params.m_fDistance >= SQR(SOUND_INTENSITY))\n\t\treturn false;\n\n\tif (veh->bEngineOn && veh->m_fGasPedal < 0.0f) {\n\t\tCalculateDistance(params.m_bDistanceCalculated, params.m_fDistance);\n\t\tvolume = veh->bIsDrowning ? 15 : 60;\n\t\tm_sQueueSample.m_nVolume = ComputeVolume(volume, SOUND_INTENSITY, m_sQueueSample.m_fDistance);\n\t\tif (m_sQueueSample.m_nVolume != 0) {\n\t\t\tm_sQueueSample.m_nCounter = 12;\n\t\t\tm_sQueueSample.m_nSampleIndex = SFX_REVERSE_WARNING;\n\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\tm_sQueueSample.m_bIs2D = false;\n\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 2;\n\t\t\tm_sQueueSample.m_nFrequency = (100 * m_sQueueSample.m_nEntityIndex & 1023) + SampleManager.GetSampleBaseFrequency(SFX_REVERSE_WARNING);\n\t\t\tm_sQueueSample.m_nLoopCount = 0;\n#ifdef FIX_BUGS\n\t\t\tm_sQueueSample.m_nEmittingVolume = volume;\n#else\n\t\t\tm_sQueueSample.m_nEmittingVolume = 60;\n#endif\n\t\t\tm_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex);\n\t\t\tm_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex);\n\t\t\tm_sQueueSample.m_fSpeedMultiplier = 3.0f;\n\t\t\tm_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY;\n\t\t\tm_sQueueSample.m_bReleasingSoundFlag = false;\n\t\t\tm_sQueueSample.m_nReleasingVolumeDivider = 3;\n\t\t\tm_sQueueSample.m_bReverbFlag = true;\n\t\t\tm_sQueueSample.m_bRequireReflection = false;\n\t\t\tAddSampleToRequestedQueue();\n\t\t}\n\t}\n\treturn true;\n}\n\nbool\ncAudioManager::ProcessVehicleDoors(cVehicleParams& params)\n{\n\tconst float SOUND_INTENSITY = 40.0f;\n\n\tCAutomobile *automobile;\n\tint8 doorState;\n\tint32 emittingVol;\n\tfloat velocity;\n\n\tif (params.m_fDistance >= SQR(SOUND_INTENSITY))\n\t\treturn false;\n\n\tautomobile = (CAutomobile *)params.m_pVehicle;\n\tCalculateDistance(params.m_bDistanceCalculated, params.m_fDistance);\n\tfor (int32 i = 0; i < ARRAY_SIZE(automobile->Doors); i++) {\n\t\tif (automobile->Damage.GetDoorStatus(i) == DOOR_STATUS_SWINGING) {\n\t\t\tdoorState = automobile->Doors[i].m_nDoorState;\n\t\t\tif (doorState == DOORST_OPEN || doorState == DOORST_CLOSED) {\n\t\t\t\tvelocity = Min(0.3f, Abs(automobile->Doors[i].m_fAngVel));\n\t\t\t\tif (velocity > 0.0035f) {\n\t\t\t\t\temittingVol = (100.0f * velocity * 10.0f / 3.0f);\n\t\t\t\t\tm_sQueueSample.m_nVolume = ComputeVolume(emittingVol, SOUND_INTENSITY, m_sQueueSample.m_fDistance);\n\t\t\t\t\tif (m_sQueueSample.m_nVolume != 0) {\n\t\t\t\t\t\tm_sQueueSample.m_nCounter = i + 6;\n\t\t\t\t\t\tm_sQueueSample.m_nSampleIndex = m_anRandomTable[1] % 6 + SFX_COL_CAR_PANEL_1;\n\t\t\t\t\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex) + RandomDisplacement(1000);\n\t\t\t\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\t\t\t\tm_sQueueSample.m_bIs2D = false;\n\t\t\t\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 10;\n\t\t\t\t\t\tm_sQueueSample.m_nLoopCount = 1;\n\t\t\t\t\t\tm_sQueueSample.m_nEmittingVolume = emittingVol;\n\t\t\t\t\t\tm_sQueueSample.m_nLoopStart = 0;\n\t\t\t\t\t\tm_sQueueSample.m_nLoopEnd = -1;\n\t\t\t\t\t\tm_sQueueSample.m_fSpeedMultiplier = 1.0f;\n\t\t\t\t\t\tm_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY;\n\t\t\t\t\t\tm_sQueueSample.m_bReleasingSoundFlag = true;\n\t\t\t\t\t\tm_sQueueSample.m_bReverbFlag = true;\n\t\t\t\t\t\tm_sQueueSample.m_bRequireReflection = true;\n\t\t\t\t\t\tAddSampleToRequestedQueue();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn true;\n}\n\nbool\ncAudioManager::ProcessAirBrakes(cVehicleParams& params)\n{\n\tconst float SOUND_INTENSITY = 30.0f;\n\tCAutomobile *automobile;\n\tuint8 volume;\n\n\tif (params.m_fDistance > SQR(SOUND_INTENSITY))\n\t\treturn false;\n\tautomobile = (CAutomobile *)params.m_pVehicle;\n\tif (!automobile->bEngineOn)\n\t\treturn true;\n\n\tif ((automobile->m_fVelocityChangeForAudio < 0.025f || params.m_fVelocityChange >= 0.025f) &&\n\t    (automobile->m_fVelocityChangeForAudio > -0.025f || params.m_fVelocityChange <= 0.025f))\n\t\treturn true;\n\n\tCalculateDistance(params.m_bDistanceCalculated, params.m_fDistance);\n\tvolume = m_anRandomTable[0] % 10 + 70;\n\tm_sQueueSample.m_nVolume = ComputeVolume(volume, SOUND_INTENSITY, m_sQueueSample.m_fDistance);\n\tif (m_sQueueSample.m_nVolume != 0) {\n\t\tm_sQueueSample.m_nCounter = 13;\n\t\tm_sQueueSample.m_nSampleIndex = SFX_AIR_BRAKES;\n\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_AIR_BRAKES);\n\t\tm_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 16);\n\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\tm_sQueueSample.m_bIs2D = false;\n\t\tm_sQueueSample.m_nReleasingVolumeModificator = 10;\n\t\tm_sQueueSample.m_nLoopCount = 1;\n\t\tm_sQueueSample.m_nEmittingVolume = volume;\n\t\tm_sQueueSample.m_nLoopStart = 0;\n\t\tm_sQueueSample.m_nLoopEnd = -1;\n\t\tm_sQueueSample.m_fSpeedMultiplier = 0.0f;\n\t\tm_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY;\n\t\tm_sQueueSample.m_bReleasingSoundFlag = true;\n\t\tm_sQueueSample.m_bReverbFlag = true;\n\t\tm_sQueueSample.m_bRequireReflection = false;\n\t\tAddSampleToRequestedQueue();\n\t}\n\n\treturn true;\n}\n\nbool\ncAudioManager::HasAirBrakes(int32 model) const\n{\n\treturn model == LINERUN || model == FIRETRUK || model == TRASH || model == BUS || model == BARRACKS \n\t\t|| model == COACH || model == PACKER || model == FLATBED;\n}\n\nbool\ncAudioManager::ProcessEngineDamage(cVehicleParams& params)\n{\n\tconst float SOUND_INTENSITY = 40.0f;\n\n\tfloat health;\n\tuint8 emittingVolume;\n\n\tif (params.m_fDistance >= SQR(SOUND_INTENSITY))\n\t\treturn false;\n\tif (params.m_pVehicle->m_modelIndex == MI_CADDY)\n\t\treturn true;\n\tif (params.m_pVehicle->GetStatus() == STATUS_WRECKED)\n\t\treturn true;\n\thealth = params.m_pVehicle->m_fHealth;\n\tif (health < 390.0f) {\n\t\tif (health < 250.0f) {\n\t\t\temittingVolume = 60;\n\t\t\tm_sQueueSample.m_nSampleIndex = SFX_CAR_ON_FIRE;\n\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 7;\n\t\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CAR_ON_FIRE);\n\t\t} else {\n\t\t\temittingVolume = 30;\n\t\t\tm_sQueueSample.m_nSampleIndex = SFX_PALM_TREE_LO;\n\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 7;\n\t\t\tm_sQueueSample.m_nFrequency = 27000;\n\t\t}\n\t\tCalculateDistance(params.m_bDistanceCalculated, params.m_fDistance);\n\t\tif (params.m_pVehicle->bIsDrowning)\n\t\t\temittingVolume /= 2;\n\t\tm_sQueueSample.m_nVolume = ComputeVolume(emittingVolume, SOUND_INTENSITY, m_sQueueSample.m_fDistance);\n\t\tif (m_sQueueSample.m_nVolume != 0) {\n\t\t\tm_sQueueSample.m_nCounter = 28;\n\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\tm_sQueueSample.m_bIs2D = false;\n\t\t\tm_sQueueSample.m_nLoopCount = 0;\n\t\t\tm_sQueueSample.m_nEmittingVolume = emittingVolume;\n\t\t\tm_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex);\n\t\t\tm_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex);\n\t\t\tm_sQueueSample.m_fSpeedMultiplier = 2.0f;\n\t\t\tm_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY;\n\t\t\tm_sQueueSample.m_bReleasingSoundFlag = false;\n\t\t\tm_sQueueSample.m_nReleasingVolumeDivider = 3;\n\t\t\tm_sQueueSample.m_bReverbFlag = true;\n\t\t\tm_sQueueSample.m_bRequireReflection = false;\n\t\t\tAddSampleToRequestedQueue();\n\t\t}\n\t}\n\treturn true;\n}\n\nbool\ncAudioManager::ProcessCarBombTick(cVehicleParams& params)\n{\n\tconst float SOUND_INTENSITY = 40.0f;\n\tconst uint8 EMITTING_VOLUME = 60;\n\n\tuint8 bombType;\n\n\tif (params.m_fDistance >= SQR(SOUND_INTENSITY))\n\t\treturn false;\n\tif (params.m_pVehicle->bEngineOn) {\n\t\tswitch (params.m_VehicleType) {\n\t\tcase VEHICLE_TYPE_CAR:\n\t\t\tbombType = params.m_pVehicle->m_bombType;\n\t\t\tbreak;\n\t\tcase VEHICLE_TYPE_BIKE:\n\t\t\tbombType = params.m_pVehicle->m_bombType;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tdebug(\"\\n * AUDIOLOG:  ProcessCarBombTick()  Unsupported vehicle type %d * \\n\", params.m_VehicleType);\n\t\t\treturn true;\n\t\t\tbreak;\n\t\t}\n\t\tif (bombType == CARBOMB_TIMEDACTIVE) {\n\t\t\tCalculateDistance(params.m_bDistanceCalculated, params.m_fDistance);\n\t\t\tm_sQueueSample.m_nVolume = ComputeVolume(EMITTING_VOLUME, SOUND_INTENSITY, m_sQueueSample.m_fDistance);\n\t\t\tif (m_sQueueSample.m_nVolume != 0) {\n\t\t\t\tm_sQueueSample.m_nCounter = 35;\n\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_COUNTDOWN;\n\t\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\t\tm_sQueueSample.m_bIs2D = false;\n\t\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 0;\n\t\t\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_COUNTDOWN);\n\t\t\t\tm_sQueueSample.m_nLoopCount = 0;\n\t\t\t\tm_sQueueSample.m_nEmittingVolume = EMITTING_VOLUME;\n\t\t\t\tm_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex);\n\t\t\t\tm_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex);\n\t\t\t\tm_sQueueSample.m_fSpeedMultiplier = 2.0f;\n\t\t\t\tm_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY;\n\t\t\t\tm_sQueueSample.m_bReleasingSoundFlag = false;\n\t\t\t\tm_sQueueSample.m_nReleasingVolumeDivider = 3;\n\t\t\t\tm_sQueueSample.m_bReverbFlag = true;\n\t\t\t\tm_sQueueSample.m_bRequireReflection = false;\n\t\t\t\tAddSampleToRequestedQueue();\n\t\t\t}\n\t\t}\n\t}\n\treturn true;\n}\n\nvoid\ncAudioManager::ProcessVehicleOneShots(cVehicleParams& params)\n{\n\tint16 event;\n\tuint8 emittingVol;\n\tfloat relVol;\n\tfloat vol;\n\tbool noReflections;\n\tbool isHeli;\n\tfloat maxDist;\n\tstatic uint8 GunIndex = 53;\n\n\tfor (int i = 0; i < m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_AudioEvents; i++) {\n\t\tnoReflections = false;\n\t\tisHeli = false;\n\t\tm_sQueueSample.m_bRequireReflection = false;\n\t\tevent = m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_awAudioEvent[i];\n\t\tswitch (event) {\n\t\tcase SOUND_CAR_DOOR_CLOSE_BONNET:\n\t\tcase SOUND_CAR_DOOR_CLOSE_BUMPER:\n\t\tcase SOUND_CAR_DOOR_CLOSE_FRONT_LEFT:\n\t\tcase SOUND_CAR_DOOR_CLOSE_FRONT_RIGHT:\n\t\tcase SOUND_CAR_DOOR_CLOSE_BACK_LEFT:\n\t\tcase SOUND_CAR_DOOR_CLOSE_BACK_RIGHT: {\n\t\t\tconst float SOUND_INTENSITY = 50.0f;\n\t\t\tmaxDist = SQR(SOUND_INTENSITY);\n\t\t\temittingVol = m_anRandomTable[2] % 5 + 122;\n\t\t\tswitch (aVehicleSettings[params.m_nIndex].m_bDoorType) {\n\t\t\tcase OLD_DOOR:\n\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_OLD_CAR_DOOR_CLOSE;\n\t\t\t\tbreak;\n\t\t\tcase NEW_DOOR:\n\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_NEW_CAR_DOOR_CLOSE;\n\t\t\t\tbreak;\n\t\t\tcase TRUCK_DOOR:\n\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_TRUCK_DOOR_CLOSE;\n\t\t\t\tbreak;\n\t\t\tcase BUS_DOOR:\n\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_AIR_BRAKES;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_NEW_CAR_DOOR_CLOSE;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n#ifdef THIS_IS_STUPID\n\t\t\tm_sQueueSample.m_nCounter = m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_awAudioEvent[i] + 22;\n#else\n\t\t\tm_sQueueSample.m_nCounter = event + 22;\n#endif\n\t\t\tif (params.m_pVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_HELI)\n\t\t\t\tm_sQueueSample.m_nFrequency = 28062;\n\t\t\telse\n\t\t\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex);\n\t\t\tm_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 32);\n\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 3;\n\t\t\tm_sQueueSample.m_fSpeedMultiplier = 0.0f;\n\t\t\tm_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY;\n\t\t\tm_sQueueSample.m_bRequireReflection = true;\n\t\t\tbreak;\n\t\t}\n\t\tcase SOUND_CAR_DOOR_OPEN_BONNET:\n\t\tcase SOUND_CAR_DOOR_OPEN_BUMPER:\n\t\tcase SOUND_CAR_DOOR_OPEN_FRONT_LEFT:\n\t\tcase SOUND_CAR_DOOR_OPEN_FRONT_RIGHT:\n\t\tcase SOUND_CAR_DOOR_OPEN_BACK_LEFT:\n\t\tcase SOUND_CAR_DOOR_OPEN_BACK_RIGHT: {\n\t\t\tconst float SOUND_INTENSITY = 50.0f;\n\t\t\tmaxDist = SQR(SOUND_INTENSITY);\n\t\t\temittingVol = m_anRandomTable[1] % 10 + 117;\n\t\t\tswitch (aVehicleSettings[params.m_nIndex].m_bDoorType) {\n\t\t\tcase OLD_DOOR:\n\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_OLD_CAR_DOOR_OPEN;\n\t\t\t\tbreak;\n\t\t\tcase TRUCK_DOOR:\n\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_TRUCK_DOOR_OPEN;\n\t\t\t\tbreak;\n\t\t\tcase BUS_DOOR:\n\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_AIR_BRAKES;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_NEW_CAR_DOOR_OPEN;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n#ifdef THIS_IS_STUPID\n\t\t\tm_sQueueSample.m_nCounter = m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_awAudioEvent[i] + 10;\n#else\n\t\t\tm_sQueueSample.m_nCounter = event + 10;\n#endif\n\t\t\tif (params.m_pVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_HELI)\n\t\t\t\tm_sQueueSample.m_nFrequency = 23459;\n\t\t\telse\n\t\t\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex);\n\t\t\tm_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 32);\n\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 3;\n\t\t\tm_sQueueSample.m_fSpeedMultiplier = 0.0f;\n\t\t\tm_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY;\n\t\t\tm_sQueueSample.m_bRequireReflection = true;\n\t\t\tbreak;\n\t\t}\n\t\tcase SOUND_CAR_WINDSHIELD_CRACK: {\n\t\t\tconst float SOUND_INTENSITY = 40.0f;\n\t\t\tmaxDist = SQR(SOUND_INTENSITY);\n\t\t\tm_sQueueSample.m_nSampleIndex = SFX_GLASS_CRACK;\n\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\tm_sQueueSample.m_nCounter = 68;\n\t\t\temittingVol = m_anRandomTable[1] % 30 + 80; //GetRandomNumberInRange(1, 80, 109)\n\t\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_GLASS_CRACK);\n\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 5;\n\t\t\tm_sQueueSample.m_fSpeedMultiplier = 0.0f;\n\t\t\tm_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY;\n\t\t} break;\n\t\tcase SOUND_CAR_JUMP: \n\t\tcase SOUND_CAR_JUMP_2: {\n\t\t\tconst float SOUND_INTENSITY = 35.0f;\n\t\t\tstatic uint8 WheelIndex = 82;\n\t\t\tmaxDist = SQR(SOUND_INTENSITY);\n#ifdef THIS_IS_STUPID\n\t\t\tif (m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_awAudioEvent[i] == SOUND_CAR_JUMP_2) {\n#else\n\t\t\tif (event == SOUND_CAR_JUMP_2) {\n#endif\n\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_TYRE_BURST_B;\n\t\t\t\temittingVol = Max(50.0f, 2 * (60.0f * m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_afVolume[i]));\n\t\t\t} else {\n\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_TYRE_BUMP;\n\t\t\t\temittingVol = Max(80.f, 2 * (100.0f * m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_afVolume[i]));\n\t\t\t}\n\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\tm_sQueueSample.m_nCounter = WheelIndex++;\n\t\t\tif (WheelIndex > 85)\n\t\t\t\tWheelIndex = 82;\n\t\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_TYRE_BUMP);\n\t\t\tm_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 16);\n\t\t\tif (params.m_VehicleType == VEHICLE_TYPE_BIKE)\n\t\t\t\tm_sQueueSample.m_nFrequency *= 2;\n\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 6;\n\t\t\tm_sQueueSample.m_fSpeedMultiplier = 2.0f;\n\t\t\tm_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY;\n\t\t\tbreak;\n\t\t}\n\t\tcase SOUND_CAR_TYRE_POP: {\n\t\t\tconst float SOUND_INTENSITY = 60.0f;\n\t\t\tstatic uint8 WheelIndex = 91;\n\t\t\tm_sQueueSample.m_nSampleIndex = SFX_TYRE_BURST;\n\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\tm_sQueueSample.m_nCounter = WheelIndex++;\n\t\t\tif (WheelIndex > 94)\n\t\t\t\tWheelIndex = 91;\n\t\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_TYRE_BURST);\n\t\t\tm_sQueueSample.m_nFrequency += RandomDisplacement(2000);\n\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 2;\n\t\t\tm_sQueueSample.m_fSpeedMultiplier = 0.0f;\n\t\t\tm_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY;\n\t\t\tmaxDist = SQR(SOUND_INTENSITY);\n\t\t\temittingVol = m_anRandomTable[4] % 10 + 117;\n\t\t\tbreak;\n\t\t}\n\t\tcase SOUND_CAR_ENGINE_START: {\n\t\t\tconst float SOUND_INTENSITY = 40.0f;\n\t\t\tif (params.m_pVehicle->GetVehicleAppearance() != VEHICLE_APPEARANCE_CAR\n\t\t\t\t|| params.m_pVehicle->m_modelIndex == MI_CADDY)\n\t\t\t\tcontinue;\n\t\t\temittingVol = 60;\n\t\t\tmaxDist = SQR(SOUND_INTENSITY);\n\t\t\tm_sQueueSample.m_nSampleIndex = SFX_CAR_STARTER;\n\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\tm_sQueueSample.m_nCounter = 33;\n\t\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CAR_STARTER);\n\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 1;\n\t\t\tm_sQueueSample.m_fSpeedMultiplier = 2.0f;\n\t\t\tm_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY;\n\t\t\tm_sQueueSample.m_bRequireReflection = true;\n\t\t\tbreak;\n\t\t}\n\t\tcase SOUND_CAR_LIGHT_BREAK: {\n\t\t\tconst float SOUND_INTENSITY = 30.0f;\n\t\t\tm_sQueueSample.m_nSampleIndex = SFX_GLASS_SHARD_1;\n\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\tm_sQueueSample.m_nCounter = 37;\n\t\t\tm_sQueueSample.m_nFrequency = 9 * SampleManager.GetSampleBaseFrequency(SFX_GLASS_SHARD_1) / 10;\n\t\t\tm_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 8);\n\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 5;\n\t\t\tm_sQueueSample.m_fSpeedMultiplier = 0.0f;\n\t\t\tm_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY;\n\t\t\tmaxDist = SQR(SOUND_INTENSITY);\n\t\t\temittingVol = m_anRandomTable[4] % 10 + 30;\n\t\t\tbreak;\n\t\t}\n\t\tcase SOUND_CAR_HYDRAULIC_1:\n\t\tcase SOUND_CAR_HYDRAULIC_2: {\n\t\t\tconst float SOUND_INTENSITY = 35.0f;\n\t\t\tif (event == SOUND_CAR_HYDRAULIC_1)\n\t\t\t\tm_sQueueSample.m_nFrequency = 15600;\n\t\t\telse\n\t\t\t\tm_sQueueSample.m_nFrequency = 13118;\n\t\t\tm_sQueueSample.m_nSampleIndex = SFX_SUSPENSION_FAST_MOVE;\n\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\tm_sQueueSample.m_nCounter = 51;\n\t\t\tm_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 8);\n\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 5;\n\t\t\tm_sQueueSample.m_fSpeedMultiplier = 0.0f;\n\t\t\tm_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY;\n\t\t\tmaxDist = SQR(SOUND_INTENSITY);\n\t\t\temittingVol = m_anRandomTable[0] % 15 + 55;\n\t\t\tbreak;\n\t\t}\n\t\tcase SOUND_CAR_HYDRAULIC_3: {\n\t\t\tconst float SOUND_INTENSITY = 35.0f;\n\t\t\tm_sQueueSample.m_nSampleIndex = SFX_SUSPENSION_SLOW_MOVE_LOOP;\n\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\tm_sQueueSample.m_nCounter = 86;\n\t\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_SUSPENSION_SLOW_MOVE_LOOP);\n\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 5;\n\t\t\tm_sQueueSample.m_fSpeedMultiplier = 0.0f;\n\t\t\tm_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY;\n\t\t\tm_sQueueSample.m_nReleasingVolumeDivider = 7;\n\t\t\tnoReflections = true;\n\t\t\tmaxDist = SQR(SOUND_INTENSITY);\n\t\t\temittingVol = m_anRandomTable[0] % 15 + 55;\n\t\t\tbreak;\n\t\t}\n\t\tcase SOUND_CAR_JERK: {\n\t\t\tconst float SOUND_INTENSITY = 35.0f;\n\t\t\tm_sQueueSample.m_nSampleIndex = SFX_SHAG_SUSPENSION;\n\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\tm_sQueueSample.m_nCounter = 87;\n\t\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_SHAG_SUSPENSION);\n\t\t\tm_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 8);\n\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 5;\n\t\t\tm_sQueueSample.m_fSpeedMultiplier = 0.0f;\n\t\t\tm_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY;\n\t\t\tmaxDist = SQR(SOUND_INTENSITY);\n\t\t\temittingVol = m_anRandomTable[1] % 15 + 55;\n\t\t\tbreak;\n\t\t}\n\t\tcase SOUND_CAR_SPLASH: {\n\t\t\tconst float SOUND_INTENSITY = 60.0f;\n\t\t\tstatic uint8 WaveIndex = 41;\n\t\t\tvol = m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_afVolume[i];\n\t\t\tif (vol <= 150.0f)\n\t\t\t\tcontinue;\n\t\t\tif (vol > 800.0f)\n\t\t\t\tm_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_afVolume[i] = 800.0f;\n\t\t\trelVol = (m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_afVolume[i] - 150.0f) / 650.0f;\n\t\t\tm_sQueueSample.m_nSampleIndex = (m_anRandomTable[0] & 1) + SFX_BOAT_SPLASH_1;\n\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\tm_sQueueSample.m_nCounter = WaveIndex++;\n\t\t\tif (WaveIndex > 46)\n\t\t\t\tWaveIndex = 41;\n\t\t\tm_sQueueSample.m_nFrequency = (7000.0f * relVol) + 6000;\n\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 3;\n\t\t\tm_sQueueSample.m_fSpeedMultiplier = 2.0f;\n\t\t\tm_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY;\n\t\t\temittingVol = (35.0f * relVol);\n\t\t\tmaxDist = SQR(SOUND_INTENSITY);\n\t\t\tbreak;\n\t\t}\n\t\t/*case SOUND_17: {\n\t\t\tconst float SOUND_INTENSITY = 50.0f;\n\t\t\tm_sQueueSample.m_nSampleIndex = SFX_POLICE_BOAT_THUMB_OFF;\n\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\tm_sQueueSample.m_nCounter = 47;\n\t\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_POLICE_BOAT_THUMB_OFF) + RandomDisplacement(600);\n\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 2;\n\t\t\tm_sQueueSample.m_fSpeedMultiplier = 0.0f;\n\t\t\tm_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY;\n\t\t\temittingVol = m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_afVolume[i];\n\t\t\tmaxDist = SQR(SOUND_INTENSITY);\n\t\t\tbreak;\n\t\t}*/\n#ifdef GTA_TRAIN\n\t\tcase SOUND_TRAIN_DOOR_CLOSE:\n\t\tcase SOUND_TRAIN_DOOR_OPEN: {\n\t\t\tconst float SOUND_INTENSITY = 35.0f;\n\t\t\tm_sQueueSample.m_nSampleIndex = SFX_AIR_BRAKES;\n\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\tm_sQueueSample.m_nCounter = 59;\n\t\t\tm_sQueueSample.m_nFrequency = RandomDisplacement(1000) + 11025;\n\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 5;\n\t\t\tm_sQueueSample.m_fSpeedMultiplier = 5.0f;\n\t\t\tm_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY;\n\t\t\tmaxDist = SQR(SOUND_INTENSITY);\n\t\t\temittingVol = m_anRandomTable[1] % 20 + 70;\n\t\t\tbreak;\n\t\t}\n#endif\n\t\tcase SOUND_CAR_TANK_TURRET_ROTATE: {\n\t\t\tconst float SOUND_INTENSITY = 40.0f;\n\t\t\tvol = m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_afVolume[i];\n\t\t\tif (vol > 24.0f / 625.0f)\n\t\t\t\tvol = 24.0f / 625.0f;\n\t\t\tm_sQueueSample.m_nSampleIndex = SFX_TANK_TURRET;\n\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\tm_sQueueSample.m_nCounter = 79;\n\t\t\tm_sQueueSample.m_nFrequency = (3000.0f * vol * 625.0f / 24.0f) + 9000;\n\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 2;\n\t\t\tm_sQueueSample.m_fSpeedMultiplier = 2.0f;\n\t\t\tm_sQueueSample.m_nReleasingVolumeDivider = 3;\n\t\t\tm_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY;\n\t\t\temittingVol = (37.0f * vol * 625.0f / 24.0f) + 90;\n\t\t\tmaxDist = SQR(SOUND_INTENSITY);\n\t\t\tnoReflections = true;\n\t\t\tbreak;\n\t\t}\n\t\tcase SOUND_CAR_BOMB_TICK: {\n\t\t\tconst float SOUND_INTENSITY = 30.0f;\n\t\t\tm_sQueueSample.m_nSampleIndex = SFX_BOMB_BEEP;\n\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\tm_sQueueSample.m_nCounter = 80;\n\t\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_BOMB_BEEP);\n\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 3;\n\t\t\tm_sQueueSample.m_fSpeedMultiplier = 0.0f;\n\t\t\tm_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY;\n\t\t\tmaxDist = SQR(SOUND_INTENSITY);\n\t\t\tm_sQueueSample.m_bRequireReflection = true;\n\t\t\temittingVol = 60;\n\t\t\tbreak;\n\t\t}\n\t\tcase SOUND_PLANE_ON_GROUND: {\n\t\t\tconst float SOUND_INTENSITY = 180.0f;\n\t\t\tm_sQueueSample.m_nSampleIndex = SFX_JUMBO_LAND_WHEELS;\n\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\tm_sQueueSample.m_nCounter = 81;\n\t\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_JUMBO_LAND_WHEELS);\n\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 2;\n\t\t\tm_sQueueSample.m_fSpeedMultiplier = 0.0f;\n\t\t\tm_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY;\n\t\t\tmaxDist = SQR(SOUND_INTENSITY);\n\t\t\temittingVol = m_anRandomTable[4] % 25 + 75;\n\t\t\tbreak;\n\t\t}\n\t\tcase SOUND_HELI_BLADE:{\n\t\t\tconst float SOUND_INTENSITY = 35.0f;\n\t\t\tstatic uint8 HeliIndex = 89;\n\t\t\trelVol = ((CAutomobile*)params.m_pVehicle)->m_aWheelSpeed[1] * 50.0f / 11.0f;\n\t\t\tif (relVol < 0.2f || relVol == 1.0f)\n\t\t\t\tcontinue;\n\t\t\temittingVol = (1.0f - relVol) * 70.0f;\n\t\t\tmaxDist = SQR(SOUND_INTENSITY);\n\t\t\tm_sQueueSample.m_nSampleIndex = SFX_CAR_HELI_ROT;\n\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\tm_sQueueSample.m_nCounter = HeliIndex++;\n\t\t\tif (HeliIndex > 90)\n\t\t\t\tHeliIndex = 89;\n\t\t\tm_sQueueSample.m_nFrequency = (8000.0f * relVol) + 16000;\n\t\t\tm_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 32);\n\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 2;\n\t\t\tm_sQueueSample.m_fSpeedMultiplier = 0.0f;\n\t\t\tm_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY;\n\t\t\tbreak;\n\t\t}\n\t\tcase SOUND_WEAPON_SHOT_FIRED: {\n\t\t\tconst float SOUND_INTENSITY = 120.0f;\n\t\t\tCVehicle *playerVeh;\n\t\t\tCPlayerPed *playerPed;\n\n\t\t\tswitch (params.m_pVehicle->m_modelIndex) {\n\t\t\tcase MI_HUNTER:\n\t\t\tcase MI_CHOPPER:\n\t\t\tcase MI_SEASPAR:\n\t\t\tcase MI_SPARROW:\n\t\t\tcase MI_MAVERICK:\n\t\t\tcase MI_VCNMAV:\n\t\t\t\tif (params.m_pVehicle->m_modelIndex == MI_HUNTER) {\n\t\t\t\t\tif (Pads[0].GetHandBrake() == 0) {\n\t\t\t\t\t\tplayerVeh = FindPlayerVehicle();\n\t\t\t\t\t\tplayerPed = FindPlayerPed();\n\t\t\t\t\t\tif (playerVeh == nil && playerPed != nil) {\n\t\t\t\t\t\t\tif (playerPed->m_attachedTo != nil && playerPed->m_attachedTo->GetType() == ENTITY_TYPE_VEHICLE)\n\t\t\t\t\t\t\t\tplayerVeh = (CVehicle*)playerPed->m_attachedTo;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (playerVeh != params.m_pVehicle) {\n\t\t\t\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_M60_LEFT;\n\t\t\t\t\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_ROCKET_LEFT;\n\t\t\t\t\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_M60_LEFT;\n\t\t\t\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_M60_LEFT;\n\t\t\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\t\t}\n\t\t\t\tmaxDist = SQR(SOUND_INTENSITY);\n\t\t\t\tm_sQueueSample.m_nCounter = GunIndex++;\n\t\t\t\temittingVol = MAX_VOLUME;\n\t\t\t\tif (GunIndex > 58)\n\t\t\t\t\tGunIndex = 53;\n\t\t\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_M60_LEFT);\n\t\t\t\tm_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 16);\n\t\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 2;\n\t\t\t\tm_sQueueSample.m_fSpeedMultiplier = 0.0f;\n\t\t\t\tm_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY;\n\t\t\t\tm_sQueueSample.m_bRequireReflection = true;\n\t\t\t\tisHeli = true;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t{\n\t\t\t\tmaxDist = SQR(SOUND_INTENSITY);\n#ifdef FIX_BUGS\n\t\t\t\tint32 sampleIndex;\n\t\t\t\tint32 frequency;\n\t\t\t\tCPed *pPed = params.m_pVehicle->pDriver;\n\t\t\t\tif(!pPed)\n\t\t\t\t\tbreak;\n\t\t\t\tif(!pPed->HasWeaponSlot(WEAPONSLOT_SUBMACHINEGUN)) {\n\t\t\t\t\tsampleIndex = SFX_UZI_LEFT;\n\t\t\t\t\tfrequency = SampleManager.GetSampleBaseFrequency(sampleIndex);\n\t\t\t\t\tfrequency += RandomDisplacement(frequency / 32);\n\t\t\t\t} else\n\t\t\t\t\tswitch(pPed->GetWeapon(WEAPONSLOT_SUBMACHINEGUN).m_eWeaponType) {\n\t\t\t\t\tcase WEAPONTYPE_TEC9:\n\t\t\t\t\t\tsampleIndex = SFX_TEC_LEFT;\n\t\t\t\t\t\tfrequency = RandomDisplacement(500) + 17000;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase WEAPONTYPE_SILENCED_INGRAM:\n\t\t\t\t\t\tsampleIndex = SFX_TEC_LEFT;\n\t\t\t\t\t\tfrequency = RandomDisplacement(1000) + 34000;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase WEAPONTYPE_MP5:\n\t\t\t\t\t\tsampleIndex = SFX_MP5_LEFT;\n\t\t\t\t\t\tfrequency = SampleManager.GetSampleBaseFrequency(sampleIndex);\n\t\t\t\t\t\tfrequency += RandomDisplacement(frequency / 32);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tsampleIndex = SFX_UZI_LEFT;\n\t\t\t\t\t\tfrequency = SampleManager.GetSampleBaseFrequency(sampleIndex);\n\t\t\t\t\t\tfrequency += RandomDisplacement(frequency / 32);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\tm_sQueueSample.m_nSampleIndex = sampleIndex;\n#else\n\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_UZI_LEFT;\n#endif\n\t\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\t\tm_sQueueSample.m_nCounter = GunIndex++;\n\t\t\t\temittingVol = m_anRandomTable[2] % 15 + 65;\n\t\t\t\tif(GunIndex > 58) GunIndex = 53;\n#ifdef FIX_BUGS\n\t\t\t\tm_sQueueSample.m_nFrequency = frequency;\n#else\n\t\t\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_UZI_LEFT);\n\t\t\t\tm_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 16);\n#endif\n\t\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 3;\n\t\t\t\tm_sQueueSample.m_fSpeedMultiplier = 0.0f;\n\t\t\t\tm_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY;\n\t\t\t\tm_sQueueSample.m_bRequireReflection = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tcase SOUND_WEAPON_HIT_VEHICLE: {\n\t\t\tconst float SOUND_INTENSITY = 40.0f;\n\t\t\tm_sQueueSample.m_nSampleIndex = m_anRandomTable[m_sQueueSample.m_nEntityIndex % ARRAY_SIZE(m_anRandomTable)] % 6 + SFX_BULLET_CAR_1;\n\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\tm_sQueueSample.m_nCounter = 34;\n\t\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex);\n\t\t\tm_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 32);\n\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 7;\n\t\t\tm_sQueueSample.m_fSpeedMultiplier = 0.0f;\n\t\t\tm_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY;\n\t\t\tmaxDist = SQR(SOUND_INTENSITY);\n\t\t\temittingVol = m_anRandomTable[3] % 20 + 90;\n\t\t\tbreak;\n\t\t}\n\t\tcase SOUND_BOMB_TIMED_ACTIVATED:\n\t\tcase SOUND_91:\n\t\tcase SOUND_BOMB_ONIGNITION_ACTIVATED:\n\t\tcase SOUND_BOMB_TICK: {\n\t\t\tconst float SOUND_INTENSITY = 50.0f;\n\t\t\tm_sQueueSample.m_nSampleIndex = SFX_ARM_BOMB;\n\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\tm_sQueueSample.m_nCounter = 36;\n\t\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_ARM_BOMB);\n\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 0;\n\t\t\tm_sQueueSample.m_fSpeedMultiplier = 0.0f;\n\t\t\tm_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY;\n\t\t\tm_sQueueSample.m_bRequireReflection = true;\n\t\t\temittingVol = 50;\n\t\t\tmaxDist = SQR(SOUND_INTENSITY);\n\t\t\tbreak;\n\t\t}\n\t\tcase SOUND_PED_HELI_PLAYER_FOUND: {\n\t\t\tcPedParams pedParams;\n\t\t\tpedParams.m_bDistanceCalculated = params.m_bDistanceCalculated;\n\t\t\tpedParams.m_fDistance = params.m_fDistance;\n\t\t\tSetupPedComments(pedParams, SOUND_PED_HELI_PLAYER_FOUND);\n\t\t\tcontinue;\n\t\t}\n\t\t/* case SOUND_PED_BODYCAST_HIT:\n\t\t\tpedParams.m_pPed = nil;\n\t\t\tpedParams.m_bDistanceCalculated = false;\n\t\t\tpedParams.m_fDistance = 0.0f;\n\t\t\tpedParams.m_bDistanceCalculated = params.m_bDistanceCalculated;\n\t\t\tpedParams.m_fDistance = params.m_fDistance;\n\t\t\tSetupPedComments(&pedParams, SOUND_PED_BODYCAST_HIT);\n\t\t\tcontinue; */\n\t\tcase SOUND_PED_VCPA_PLAYER_FOUND: {\n\t\t\tcPedParams pedParams;\n\t\t\tpedParams.m_bDistanceCalculated = params.m_bDistanceCalculated;\n\t\t\tpedParams.m_fDistance = params.m_fDistance;\n\t\t\tSetupPedComments(pedParams, SOUND_PED_VCPA_PLAYER_FOUND);\n\t\t\tcontinue;\n\t\t}\n\t\tcase SOUND_WATER_FALL: {\n\t\t\tconst float SOUND_INTENSITY = 40.0f;\n\t\t\tstatic uint32 WaterFallFrame = 0;\n\t\t\tif (m_FrameCounter <= WaterFallFrame)\n\t\t\t\tcontinue;\n\t\t\tWaterFallFrame = m_FrameCounter + 6;\n\t\t\tm_sQueueSample.m_nSampleIndex = SFX_SPLASH_1;\n\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\tm_sQueueSample.m_nCounter = 15;\n\t\t\tm_sQueueSample.m_nFrequency = RandomDisplacement(1000) + 16000;\n\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 1;\n\t\t\tm_sQueueSample.m_fSpeedMultiplier = 0.0f;\n\t\t\tm_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY;\n\t\t\tmaxDist = SQR(SOUND_INTENSITY);\n\t\t\tm_sQueueSample.m_bRequireReflection = true;\n\t\t\temittingVol = m_anRandomTable[4] % 20 + 90;\n\t\t\tbreak;\n\t\t}\n\t\tcase SOUND_SPLATTER: {\n\t\t\tconst float SOUND_INTENSITY = 40.0f;\n\t\t\tstatic uint8 CrunchOffset = 0;\n\t\t\tm_sQueueSample.m_nSampleIndex = CrunchOffset + SFX_PED_CRUNCH_1;\n\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\tm_sQueueSample.m_nCounter = 48;\n\t\t\tm_sQueueSample.m_nFrequency = RandomDisplacement(6000) + 16000;\n\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 1;\n\t\t\tm_sQueueSample.m_fSpeedMultiplier = 0.0f;\n\t\t\tm_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY;\n\t\t\t++CrunchOffset;\n\t\t\tmaxDist = SQR(SOUND_INTENSITY);\n\t\t\temittingVol = m_anRandomTable[4] % 20 + 55;\n\t\t\tCrunchOffset %= 2;\n\t\t\tm_sQueueSample.m_bRequireReflection = true;\n\t\t\tbreak;\n\t\t}\n\t\tcase SOUND_CAR_PED_COLLISION: {\n\t\t\tconst float SOUND_INTENSITY = 40.0f;\n\t\t\tvol = Min(20.0f, m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_afVolume[i]);\n\t\t\temittingVol = Min(127, (3 * (vol / 20.0f * 127.f)) / 2);\n\t\t\tif (emittingVol == 0)\n\t\t\t\tcontinue;\n\n\t\t\tm_sQueueSample.m_nSampleIndex = SFX_FIGHT_1;\n\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\tm_sQueueSample.m_nCounter = 50;\n\t\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex);\n\t\t\tm_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 16);\n\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 1;\n\t\t\tm_sQueueSample.m_fSpeedMultiplier = 0.0f;\n\t\t\tm_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY;\n\t\t\tmaxDist = SQR(SOUND_INTENSITY);\n\t\t\tbreak;\n\t\t}\n\t\tdefault:\n\t\t\tcontinue;\n\t\t}\n\t\tif (params.m_fDistance < maxDist) {\n\t\t\tCalculateDistance(params.m_bDistanceCalculated, params.m_fDistance);\n\t\t\tm_sQueueSample.m_nVolume = ComputeVolume(emittingVol, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance);\n\t\t\tif (m_sQueueSample.m_nVolume != 0) {\n\t\t\t\tif (noReflections) {\n\t\t\t\t\tm_sQueueSample.m_nLoopCount = 0;\n\t\t\t\t\tm_sQueueSample.m_bReleasingSoundFlag = false;\n\t\t\t\t} else {\n\t\t\t\t\tm_sQueueSample.m_nLoopCount = 1;\n\t\t\t\t\tm_sQueueSample.m_bReleasingSoundFlag = true;\n\t\t\t\t}\n\t\t\t\tm_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex);\n\t\t\t\tm_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex);\n\t\t\t\tm_sQueueSample.m_nEmittingVolume = emittingVol;\n\t\t\t\tm_sQueueSample.m_bReverbFlag = true;\n\t\t\t\tif (isHeli) {\n\t\t\t\t\tif (0.2f * m_sQueueSample.m_fSoundIntensity > m_sQueueSample.m_fDistance) {\n\t\t\t\t\t\tm_sQueueSample.m_bIs2D = true;\n\t\t\t\t\t\tm_sQueueSample.m_nOffset = 0;\n#ifdef THIS_IS_STUPID\n\t\t\t\t\t\tgoto AddSample;\n#else\n\t\t\t\t\t\tAddSampleToRequestedQueue();\n\t\t\t\t\t\tm_sQueueSample.m_nOffset = 127;\n\t\t\t\t\t\tm_sQueueSample.m_nSampleIndex++;\n\t\t\t\t\t\tm_sQueueSample.m_nCounter = GunIndex++;\n\t\t\t\t\t\tif (GunIndex > 58)\n\t\t\t\t\t\t\tGunIndex = 53;\n\t\t\t\t\t\tm_sQueueSample.m_bRequireReflection = false;\n\t\t\t\t\t\tAddSampleToRequestedQueue();\n\t\t\t\t\t\tcontinue;\n#endif\n\t\t\t\t\t}\n\t\t\t\t\tisHeli = false;\n\t\t\t\t}\n\t\t\t\tm_sQueueSample.m_bIs2D = false;\n#ifdef THIS_IS_STUPID\nAddSample:\n\t\t\t\tAddSampleToRequestedQueue();\n\t\t\t\tif (isHeli) {\n\t\t\t\t\tm_sQueueSample.m_nOffset = 127;\n\t\t\t\t\tm_sQueueSample.m_nSampleIndex++;\n\t\t\t\t\tm_sQueueSample.m_nCounter = GunIndex++;\n\t\t\t\t\tif (GunIndex > 58)\n\t\t\t\t\t\tGunIndex = 53;\n\t\t\t\t\tm_sQueueSample.m_bRequireReflection = 0;\n\t\t\t\t\tAddSampleToRequestedQueue();\n\t\t\t\t}\n#else\n\t\t\t\tAddSampleToRequestedQueue();\n#endif\n\t\t\t\tcontinue;\n\n\t\t\t}\n\t\t}\n\t}\n}\n\n#ifdef GTA_TRAIN\nbool\ncAudioManager::ProcessTrainNoise(cVehicleParams& params)\n{\n\tconst float SOUND_INTENSITY = 300.0f;\n\n\tCTrain *train;\n\tuint8 emittingVol;\n\tfloat speedMultipler;\n\n\tif (params.m_fDistance >= SQR(SOUND_INTENSITY))\n\t\treturn false;\n\n\tif (params.m_fVelocityChange > 0.0f) {\n\t\tCalculateDistance(params.m_bDistanceCalculated, params.m_fDistance);\n\t\ttrain = (CTrain *)params.m_pVehicle;\n\t\tspeedMultipler = Min(1.0f, train->m_fSpeed * 250.f / 51.f);\n\t\temittingVol = (75.f * speedMultipler);\n\t\tif (train->m_fWagonPosition == 0.0f) {\n\t\t\tm_sQueueSample.m_nVolume = ComputeVolume(emittingVol, SOUND_INTENSITY, m_sQueueSample.m_fDistance);\n\t\t\tif (m_sQueueSample.m_nVolume != 0) {\n\t\t\t\tm_sQueueSample.m_nCounter = 32;\n\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_TRAIN_FAR;\n\t\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\t\tm_sQueueSample.m_bIs2D = false;\n\t\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 2;\n\t\t\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_TRAIN_FAR);\n\t\t\t\tm_sQueueSample.m_nLoopCount = 0;\n\t\t\t\tm_sQueueSample.m_nEmittingVolume = emittingVol;\n\t\t\t\tm_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex);\n\t\t\t\tm_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex);\n\t\t\t\tm_sQueueSample.m_fSpeedMultiplier = 3.0f;\n\t\t\t\tm_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY;\n\t\t\t\tm_sQueueSample.m_bReleasingSoundFlag = false;\n\t\t\t\tm_sQueueSample.m_nReleasingVolumeDivider = 3;\n\t\t\t\tm_sQueueSample.m_bReverbFlag = true;\n\t\t\t\tm_sQueueSample.m_bRequireReflection = false;\n\t\t\t\tAddSampleToRequestedQueue();\n\t\t\t}\n\t\t}\n\t\tconst float SOUND_INTENSITY = 70.0f;\n\t\tif (params.m_fDistance < SQR(SOUND_INTENSITY)) {\n\t\t\tm_sQueueSample.m_nVolume = ComputeVolume(emittingVol, SOUND_INTENSITY, m_sQueueSample.m_fDistance);\n\t\t\tif (m_sQueueSample.m_nVolume != 0) {\n\t\t\t\tm_sQueueSample.m_nCounter = 33;\n\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_TRAIN_NEAR;\n\t\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\t\tm_sQueueSample.m_bIs2D = false;\n\t\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 5;\n\t\t\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_TRAIN_NEAR) + 100 * m_sQueueSample.m_nEntityIndex % 987;\n\t\t\t\tm_sQueueSample.m_nLoopCount = 0;\n\t\t\t\tm_sQueueSample.m_nEmittingVolume = emittingVol;\n\t\t\t\tm_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex);\n\t\t\t\tm_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex);\n\t\t\t\tm_sQueueSample.m_fSpeedMultiplier = 6.0f;\n\t\t\t\tm_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY;\n\t\t\t\tm_sQueueSample.m_bReleasingSoundFlag = false;\n\t\t\t\tm_sQueueSample.m_nReleasingVolumeDivider = 3;\n\t\t\t\tm_sQueueSample.m_bReverbFlag = true;\n\t\t\t\tm_sQueueSample.m_bRequireReflection = false;\n\t\t\t\tAddSampleToRequestedQueue();\n\t\t\t}\n\t\t}\n\t}\n\treturn true;\n}\n#endif\nbool\ncAudioManager::ProcessBoatEngine(cVehicleParams& params)\n{\n\tCBoat *boat;\n\tfloat padRelativeAccerate;\n\n\tbool isV12 = false;\n\tstatic int32 LastFreq = 2000;\n\tstatic int8 LastVol = 0;\n\n\tstatic const float intensity = 90.0f;\n\n\tif (params.m_fDistance < SQR(intensity)) {\n\t\tboat = (CBoat *)params.m_pVehicle;\n\t\tif(boat->GetStatus() == STATUS_WRECKED)\n\t\t\treturn true;\n\n\t\tfloat freqModificator;\n\t\tfloat volModificator;\n\t\tint BaseVol;\n\t\tint BaseFreq;\n\n\t\tswitch(boat->GetModelIndex()) {\n\t\tcase MI_RIO:\n\t\t\tfreqModificator = 490.0f;\n\t\t\tvolModificator = 60.0f;\n\t\t\tBaseVol = 20;\n\t\t\tBaseFreq = 1888;\n\t\t\tbreak;\n\t\tcase MI_PREDATOR:\n\t\tcase MI_SQUALO:\n\t\tcase MI_SPEEDER:\n\t\tcase MI_COASTG:\n\t\tcase MI_DINGHY:\n\t\tcase MI_JETMAX:\n\t\t\tfreqModificator = 6000.0f;\n\t\t\tvolModificator = 60.0f;\n\t\t\tisV12 = true;\n\t\t\tBaseFreq = 9000;\n\t\t\tBaseVol = 20;\n\t\t\tbreak;\n\t\tcase MI_REEFER:\n\t\t\tfreqModificator = 715.0f;\n\t\t\tvolModificator = 80.0f;\n\t\t\tBaseVol = 0;\n\t\t\tBaseFreq = 3775;\n\t\t\tbreak;\n\t\tcase MI_TROPIC:\n\t\tcase MI_MARQUIS:\n\t\t\tfreqModificator = 463.0f;\n\t\t\tvolModificator = 60.0f;\n\t\t\tBaseVol = 20;\n\t\t\tBaseFreq = 1782;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\treturn true;\n\t\t}\n\n\t\tbool bIsPlayerVeh;\n\n\t\tif(FindPlayerVehicle() == params.m_pVehicle) {\n\t\t\tfloat padAccelerate = Max(Pads[0].GetAccelerate(), Pads[0].GetBrake());\n\t\t\tpadRelativeAccerate = padAccelerate / 255.0f;\n\t\t\tbIsPlayerVeh = true;\n\t\t} else {\n\t\t\tpadRelativeAccerate = Max(params.m_pVehicle->m_fGasPedal, params.m_pVehicle->m_fBrakePedal);\n\t\t\tbIsPlayerVeh = false;\n\t\t}\n\n\t\tint Freq = BaseFreq + (padRelativeAccerate * freqModificator);\n\t\tint Vol = BaseVol + (padRelativeAccerate * volModificator);\n\n\t\tif(!boat->bPropellerInWater)\n\t\t\tFreq = (9 * Freq) / 8;\n\n\t\tif(bIsPlayerVeh) {\n\t\t\tif(Freq > LastFreq) {\n\t\t\t\tif(isV12)\n\t\t\t\t\tFreq = Min(Freq, LastFreq + 100);\n\t\t\t\telse\n\t\t\t\t\tFreq = Min(Freq, LastFreq + 15);\n\t\t\t} else {\n\t\t\t\tif(isV12)\n\t\t\t\t\tFreq = Max(Freq, LastFreq - 100);\n\t\t\t\telse\n\t\t\t\t\tFreq = Max(Freq, LastFreq - 15);\n\t\t\t}\n\t\t\tif(Vol > LastVol)\n\t\t\t\tVol = Min(Vol, LastVol + 3);\n\t\t\telse\n\t\t\t\tVol = Max(Vol, LastVol - 3);\n\t\t}\n\n\t\tif (Vol > 0) {\n\t\t\tCalculateDistance(params.m_bDistanceCalculated, params.m_fDistance);\n\t\t\tm_sQueueSample.m_nVolume = ComputeVolume(Vol, intensity, m_sQueueSample.m_fDistance);\n\t\t\tif (m_sQueueSample.m_nVolume != 0) {\n\t\t\t\tm_sQueueSample.m_nFrequency = Freq;\n\t\t\t\tm_sQueueSample.m_nCounter = 40;\n\t\t\t\tif (isV12)\n\t\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_BOAT_V12_LOOP;\n\t\t\t\telse\n\t\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_BOAT_CRUISER_LOOP;\n\t\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\t\tm_sQueueSample.m_bIs2D = false;\n\t\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 3;\n\t\t\t\tm_sQueueSample.m_nLoopCount = 0;\n\t\t\t\tm_sQueueSample.m_nEmittingVolume = Vol;\n\t\t\t\tm_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex);\n\t\t\t\tm_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex);\n\t\t\t\tm_sQueueSample.m_fSpeedMultiplier = 2.0f;\n\t\t\t\tm_sQueueSample.m_fSoundIntensity = intensity;\n\t\t\t\tm_sQueueSample.m_bReleasingSoundFlag = false;\n\t\t\t\tm_sQueueSample.m_nReleasingVolumeDivider = 7;\n\t\t\t\tm_sQueueSample.m_bReverbFlag = true;\n\t\t\t\tm_sQueueSample.m_bRequireReflection = false;\n\t\t\t\tAddSampleToRequestedQueue();\n\t\t\t}\n\t\t}\n\n\t\tif(boat->GetModelIndex() == MI_REEFER) {\n\t\t\tCalculateDistance(params.m_bDistanceCalculated, params.m_fDistance);\n\t\t\tm_sQueueSample.m_nVolume = ComputeVolume(80, intensity, m_sQueueSample.m_fDistance);\n\t\t\tif (m_sQueueSample.m_nVolume != 0) {\n\t\t\t\tm_sQueueSample.m_nFrequency = 6000;\n\t\t\t\tm_sQueueSample.m_nCounter = 39;\n\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_FISHING_BOAT_IDLE;\n\t\t\t\tm_sQueueSample.m_nFrequency += (m_sQueueSample.m_nEntityIndex * 65536) % 1000;\n\t\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\t\tm_sQueueSample.m_bIs2D = false;\n\t\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 3;\n\t\t\t\tm_sQueueSample.m_nLoopCount = 0;\n\t\t\t\tm_sQueueSample.m_nEmittingVolume = 80;\n\t\t\t\tm_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex);\n\t\t\t\tm_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex);\n\t\t\t\tm_sQueueSample.m_fSpeedMultiplier = 2.0f;\n\t\t\t\tm_sQueueSample.m_fSoundIntensity = intensity;\n\t\t\t\tm_sQueueSample.m_bReleasingSoundFlag = false;\n\t\t\t\tm_sQueueSample.m_nReleasingVolumeDivider = 7;\n\t\t\t\tm_sQueueSample.m_bReverbFlag = true;\n\t\t\t\tm_sQueueSample.m_bRequireReflection = false;\n\t\t\t\tAddSampleToRequestedQueue();\n\t\t\t}\n\t\t}\n\t\tif(bIsPlayerVeh) {\n\t\t\tLastFreq = Freq;\n\t\t\tLastVol = Vol;\n\t\t}\n\t\treturn true;\n\t}\n\treturn false;\n}\n\nbool\ncAudioManager::ProcessBoatMovingOverWater(cVehicleParams& params)\n{\n\tfloat velocityChange;\n\tint32 vol;\n\tfloat multiplier;\n\n\tif (params.m_fDistance > SQR(50))\n\t\treturn false;\n\n\tvelocityChange = Abs(params.m_fVelocityChange);\n\tif (velocityChange <= 0.0005f && ((CBoat*)params.m_pVehicle)->bBoatInWater)\n\t\treturn true;\n\n\tvelocityChange = Min(0.75f, velocityChange);\n\tmultiplier = (velocityChange - 0.0005f) / (1499.0f / 2000.0f);\n\tCalculateDistance(params.m_bDistanceCalculated, params.m_fDistance);\n\tvol = (30.f * multiplier);\n\tm_sQueueSample.m_nVolume = ComputeVolume(vol, 50.f, m_sQueueSample.m_fDistance);\n\tif (m_sQueueSample.m_nVolume != 0) {\n\t\tm_sQueueSample.m_nCounter = 38;\n\t\tm_sQueueSample.m_nSampleIndex = SFX_BOAT_WATER_LOOP;\n\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\tm_sQueueSample.m_bIs2D = false;\n\t\tm_sQueueSample.m_nReleasingVolumeModificator = 3;\n\t\tm_sQueueSample.m_nFrequency = (6050.f * multiplier) + 16000;\n\t\tm_sQueueSample.m_nLoopCount = 0;\n\t\tm_sQueueSample.m_nEmittingVolume = vol;\n\t\tm_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex);\n\t\tm_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex);\n\t\tm_sQueueSample.m_fSpeedMultiplier = 2.0f;\n\t\tm_sQueueSample.m_fSoundIntensity = 50.0f;\n\t\tm_sQueueSample.m_bReleasingSoundFlag = false;\n\t\tm_sQueueSample.m_nReleasingVolumeDivider = 6;\n\t\tm_sQueueSample.m_bReverbFlag = true;\n\t\tm_sQueueSample.m_bRequireReflection = false;\n\t\tAddSampleToRequestedQueue();\n\t}\n\n\treturn true;\n}\n\nvoid\ncAudioManager::ProcessCarHeli(cVehicleParams& params)\n{\n\tconst float SOUND_INTENSITY = 250.0f;\n\n\tCVehicle* playerVeh;\n\tCVehicle* veh;\n\tCAutomobile* automobile;\n\tCBoat* boat;\n\n\tuint8 emittingVol;\n\tint16 brakeState;\n\tint16 accelerateState;\n\tuint32 freq;\n\tfloat propellerSpeed;\n\tfloat freqModifier; //may be relate to angle with horison\n\tfloat cameraAngle;\n\tbool distanceCalculatedOld;\n\tfloat distanceOld;\n\tCVector vecPosOld;\n\n\tfloat volumeModifier;//TODO find better name\n\tbool hunterBool;\n\t\n\tstatic uint32 freqFrontPrev = 14287;\n\tstatic uint32 freqPropellerPrev = 7143;\n\tstatic uint32 freqSkimmerPrev = 14287;\n\n\tboat = nil;\n\tautomobile = nil;\n\thunterBool = false;\n\n\tif (params.m_fDistance >= SQR(SOUND_INTENSITY))\n\t\treturn;\n\n\tplayerVeh = FindPlayerVehicle();\n\tveh = params.m_pVehicle;\n\tif (playerVeh == veh) {\n\t\taccelerateState = Pads[0].GetAccelerate();\n\t\tbrakeState = Pads[0].GetBrake();\n\t} else {\n\t\taccelerateState = veh->m_fGasPedal * 255.0f;\n\t\tbrakeState = veh->m_fBrakePedal * 255.0f;\n\t}\n\tfreqModifier = Abs(veh->GetUp().y);\n\tcameraAngle = (DotProduct(veh->m_matrix.GetForward(), TheCamera.GetForward()) + 1.0f) / 2.0f;\n\tif (veh->m_modelIndex == MI_SKIMMER) {\n\t\tboat = (CBoat*)veh;\n\t\tpropellerSpeed = boat->m_fMovingSpeed * 50.0f / 11.0f;\n\t} else if (params.m_VehicleType == VEHICLE_TYPE_HELI) {\n\t\tpropellerSpeed = 1.0f;\n\t} else {\n\t\tautomobile = (CAutomobile*)veh;\n\t\tpropellerSpeed = automobile->m_aWheelSpeed[1] * 50.0f / 11.0f;\n\t}\n\n\tif (propellerSpeed == 0.0f)\n\t\treturn;\n\n\tpropellerSpeed = Min(1.0f, propellerSpeed);\n\tCalculateDistance(params.m_bDistanceCalculated, params.m_fDistance);\n\n\n\t//sound on long distances\n\tif (m_sQueueSample.m_fDistance >= 40.0f)\n\t\temittingVol = propellerSpeed * 75.0f;\n\telse if (m_sQueueSample.m_fDistance >= 25.0f)\n\t\temittingVol = (m_sQueueSample.m_fDistance - 25.0f) * (75.0f * propellerSpeed) / 15.0f;\n\telse\n\t\temittingVol = 0;\n\tif (emittingVol != 0) {\n\t\tm_sQueueSample.m_nVolume = ComputeVolume(emittingVol, SOUND_INTENSITY, m_sQueueSample.m_fDistance);\n\t\tif (m_sQueueSample.m_nVolume != 0) {\n\t\t\tm_sQueueSample.m_nCounter = 88;\n\t\t\tif (boat != nil) {\n\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_SEAPLANE_PRO3;\n\t\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\t\tif (accelerateState > 0 || brakeState > 0)\n\t\t\t\t\tm_sQueueSample.m_nFrequency = 4600 + Min(1.0f, (Max(accelerateState, brakeState) / 255.0f) * freqModifier) * 563;\n\t\t\t\telse\n\t\t\t\t\tm_sQueueSample.m_nFrequency = 3651 + Min(1.0f, freqModifier) * 949;\n\t\t\t} else {\n\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_HELI_1;\n\t\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex);\n\t\t\t}\n\t\t\tm_sQueueSample.m_bIs2D = false;\n\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 2;\n\t\t\tm_sQueueSample.m_nLoopCount = 0;\n\t\t\tm_sQueueSample.m_nEmittingVolume = emittingVol;\n\t\t\tm_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex);\n\t\t\tm_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex);\n\t\t\tm_sQueueSample.m_fSpeedMultiplier = 6.0f;\n\t\t\tm_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY;\n\t\t\tm_sQueueSample.m_bReleasingSoundFlag = false;\n\t\t\tm_sQueueSample.m_nReleasingVolumeDivider = 5;\n\t\t\tm_sQueueSample.m_bReverbFlag = true;\n\t\t\tm_sQueueSample.m_bRequireReflection = false;\n\t\t\tAddSampleToRequestedQueue();\n\t\t}\n\t}\n\n\tif (params.m_fDistance >= SQR(140.0f))\n\t\treturn;\n\n\tif (propellerSpeed >= 0.4f)\n\t\tvolumeModifier = (propellerSpeed - 0.4f) * 5.0f / 3.0f;\n\telse\n\t\tvolumeModifier = 0.0f;\n\tif (!boat) {\n\t\tfreq = Min(1300, 7000.0f * freqModifier);\n\t\tif (playerVeh == veh && (accelerateState > 0 || brakeState > 0) && freq < 1300)//unnesesary freqModifier alredy <= 1300\n\t\t\tfreq = 1300;\n\t\tif (veh->m_modelIndex == MI_HUNTER)\n\t\t\thunterBool = true;\n\t}\n\n\n\t//sound from front of helicopter\n\temittingVol = (1.0f - cameraAngle) * volumeModifier * 127.0f;\n\tm_sQueueSample.m_nVolume = ComputeVolume(emittingVol, 140.0f, m_sQueueSample.m_fDistance);\n\tif (m_sQueueSample.m_nVolume != 0) {\n\t\tm_sQueueSample.m_nCounter = 3;\n\t\tif (hunterBool) {\n\t\t\tm_sQueueSample.m_nSampleIndex = SFX_HELI_APACHE_1;\n\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\tm_sQueueSample.m_nFrequency = (volumeModifier + 1.0f) * 16000 + freq;\n\t\t\tm_sQueueSample.m_bIs2D = false;\n\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 1;\n\t\t\tm_sQueueSample.m_nLoopCount = 0;\n\t\t\tm_sQueueSample.m_nEmittingVolume = emittingVol;\n\t\t\tm_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex);\n\t\t\tm_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex);\n\t\t\tm_sQueueSample.m_fSpeedMultiplier = 6.0f;\n\t\t\tm_sQueueSample.m_fSoundIntensity = 140.0f;\n\t\t\tm_sQueueSample.m_bReleasingSoundFlag = false;\n\t\t\tm_sQueueSample.m_nReleasingVolumeDivider = 5;\n\t\t\tm_sQueueSample.m_bReverbFlag = true;\n\t\t\tm_sQueueSample.m_bRequireReflection = false;\n\t\t\tAddSampleToRequestedQueue();\n\t\t} else if (boat != nil) {\n\t\t\tm_sQueueSample.m_nSampleIndex = SFX_SEAPLANE_PRO1;\n\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\n\t\t\tif (accelerateState > 0 || brakeState > 0)\n\t\t\t\tm_sQueueSample.m_nFrequency = 18000 + Min(1.0f, freqModifier * (Max(accelerateState, brakeState) / 255.0f)) * 2204;\n\t\t\telse\n\t\t\t\tm_sQueueSample.m_nFrequency = 14287 + Min(1.0f, freqModifier) * 3713;\n\t\t\tif (propellerSpeed < 1.0f)\n\t\t\t\tm_sQueueSample.m_nFrequency = (propellerSpeed + 1.0f) * (m_sQueueSample.m_nFrequency / 2.0f);\n\t\t\tm_sQueueSample.m_nFrequency = clamp2(m_sQueueSample.m_nFrequency, freqFrontPrev, 197);\n\t\t\tfreqFrontPrev = m_sQueueSample.m_nFrequency;\n\n\t\t\tm_sQueueSample.m_bIs2D = false;\n\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 1;\n\t\t\tm_sQueueSample.m_nLoopCount = 0;\n\t\t\tm_sQueueSample.m_nEmittingVolume = emittingVol;\n\t\t\tm_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex);\n\t\t\tm_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex);\n\t\t\tm_sQueueSample.m_fSpeedMultiplier = 6.0f;\n\t\t\tm_sQueueSample.m_fSoundIntensity = 140.0f;\n\t\t\tm_sQueueSample.m_bReleasingSoundFlag = false;\n\t\t\tm_sQueueSample.m_nReleasingVolumeDivider = 5;\n\t\t\tm_sQueueSample.m_bReverbFlag = true;\n\t\t\tm_sQueueSample.m_bRequireReflection = false;\n\t\t\tAddSampleToRequestedQueue();\n\t\t} else {\n\t\t\tm_sQueueSample.m_nSampleIndex = SFX_CAR_HELI_MAI;\n\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\tm_sQueueSample.m_nFrequency = (volumeModifier + 1) * 16000 + freq;\n\t\t\tm_sQueueSample.m_bIs2D = false;\n\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 1;\n\t\t\tm_sQueueSample.m_nLoopCount = 0;\n\t\t\tm_sQueueSample.m_nEmittingVolume = emittingVol;\n\t\t\tm_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex);\n\t\t\tm_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex);\n\t\t\tm_sQueueSample.m_fSpeedMultiplier = 6.0f;\n\t\t\tm_sQueueSample.m_fSoundIntensity = 140.0f;\n\t\t\tm_sQueueSample.m_bReleasingSoundFlag = false;\n\t\t\tm_sQueueSample.m_nReleasingVolumeDivider = 5;\n\t\t\tm_sQueueSample.m_bReverbFlag = true;\n\t\t\tm_sQueueSample.m_bRequireReflection = false;\n\t\t\tAddSampleToRequestedQueue();\n\t\t}\n\t}\n\n\n\t//after accel rotor sound\n\temittingVol = ((cameraAngle + 1.0f) * volumeModifier * 127.0f) / 2.0f;\n\tm_sQueueSample.m_nVolume = ComputeVolume(emittingVol, 140.0f, m_sQueueSample.m_fDistance);\n\tif (m_sQueueSample.m_nVolume != 0) {\n\t\tm_sQueueSample.m_nCounter = 1;\n\t\tif (hunterBool) {\n\t\t\tm_sQueueSample.m_nSampleIndex = SFX_HELI_APACHE_2;\n\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\tm_sQueueSample.m_nFrequency = (volumeModifier + 1) * 16000 + freq;\n\t\t} else if (boat) {\n\t\t\tm_sQueueSample.m_nSampleIndex = SFX_SEAPLANE_PRO2;\n\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\n\t\t\tif (accelerateState > 0 || brakeState > 0)\n\t\t\t\tm_sQueueSample.m_nFrequency = 9000 + Min(1.0f, (Max(accelerateState, brakeState) / 255) * freqModifier) * 1102;\n\t\t\telse\n\t\t\t\tm_sQueueSample.m_nFrequency = 7143 + Min(1.0f, freqModifier) * 1857;\n\n\t\t\tif (propellerSpeed < 1.0f)\n\t\t\t\tm_sQueueSample.m_nFrequency = (propellerSpeed + 1) * (m_sQueueSample.m_nFrequency / 2);\n\n\t\t\tm_sQueueSample.m_nFrequency = clamp2(m_sQueueSample.m_nFrequency, freqPropellerPrev, 98);\n\t\t\tfreqPropellerPrev = m_sQueueSample.m_nFrequency;\n\t\t} else {\n\t\t\tm_sQueueSample.m_nSampleIndex = SFX_CAR_HELI_MAI2;\n\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\tm_sQueueSample.m_nFrequency = (volumeModifier + 1) * 16000 + freq;\n\t\t}\n\t\tm_sQueueSample.m_bIs2D = false;\n\t\tm_sQueueSample.m_nReleasingVolumeModificator = 1;\n\t\tm_sQueueSample.m_nLoopCount = 0;\n\t\tm_sQueueSample.m_nEmittingVolume = emittingVol;\n\t\tm_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex);\n\t\tm_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex);\n\t\tm_sQueueSample.m_fSpeedMultiplier = 6.0f;\n\t\tm_sQueueSample.m_fSoundIntensity = 140.0f;\n\t\tm_sQueueSample.m_bReleasingSoundFlag = false;\n\t\tm_sQueueSample.m_nReleasingVolumeDivider = 5;\n\t\tm_sQueueSample.m_bReverbFlag = true;\n\t\tm_sQueueSample.m_bRequireReflection = false;\n\t\tAddSampleToRequestedQueue();\n\t}\n\n\n\t//engine starting sound \n\tif (boat == nil && params.m_VehicleType != VEHICLE_TYPE_HELI && m_sQueueSample.m_fDistance < 30.0f) { //strange way to check if automobile != nil\n\t\tif (automobile->bEngineOn) {\n\t\t\tif (propellerSpeed < 1.0f) {\n\t\t\t\temittingVol = (1.0f - propellerSpeed / 2.0f) * 70.0f;\n\t\t\t\tm_sQueueSample.m_nVolume = ComputeVolume(emittingVol, 30.0f, m_sQueueSample.m_fDistance);\n\t\t\t\tif (m_sQueueSample.m_nVolume) {\n\t\t\t\t\tif (hunterBool) {\n\t\t\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_HELI_APACHE_4;\n\t\t\t\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\t\t\t\tfreq = 3000.0f * propellerSpeed + 30000;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_CAR_HELI_STA;\n\t\t\t\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\t\t\t\tfreq = 3000.0f * propellerSpeed + 6000;\n\t\t\t\t\t}\n\t\t\t\t\tm_sQueueSample.m_nFrequency = freq;\n\t\t\t\t\tm_sQueueSample.m_nCounter = 12;\n\t\t\t\t\tm_sQueueSample.m_bIs2D = false;\n\t\t\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 1;\n\t\t\t\t\tm_sQueueSample.m_nLoopCount = 0;\n\t\t\t\t\tm_sQueueSample.m_nEmittingVolume = emittingVol;\n\t\t\t\t\tm_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex);\n\t\t\t\t\tm_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex);\n\t\t\t\t\tm_sQueueSample.m_fSpeedMultiplier = 6.0f;\n\t\t\t\t\tm_sQueueSample.m_fSoundIntensity = 30.0f;\n\t\t\t\t\tm_sQueueSample.m_bReleasingSoundFlag = false;\n\t\t\t\t\tm_sQueueSample.m_nReleasingVolumeDivider = 30;\n\t\t\t\t\tm_sQueueSample.m_bReverbFlag = true;\n\t\t\t\t\tm_sQueueSample.m_bRequireReflection = false;\n\t\t\t\t\tAddSampleToRequestedQueue();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\n\tif (boat) {\n\t\tif (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_FIXED && m_sQueueSample.m_fDistance < 20.0f && propellerSpeed > 0.0f) {\n\t\t\tm_sQueueSample.m_nVolume = ComputeVolume(propellerSpeed * 100.0f, 20.0f, m_sQueueSample.m_fDistance);\n\t\t\tif (m_sQueueSample.m_nVolume) {\n\n\t\t\t\tif (accelerateState > 0 || brakeState > 0)\n\t\t\t\t\tm_sQueueSample.m_nFrequency = 18000 + Min(1.0f, (Max(accelerateState, brakeState) / 255.0f) * freqModifier) * 2204;\n\t\t\t\telse\n\t\t\t\t\tm_sQueueSample.m_nFrequency = 14287 + Min(1.0f, freqModifier) * 3713;\n\t\t\t\tif (propellerSpeed < 1.0f)\n\t\t\t\t\tm_sQueueSample.m_nFrequency = (propellerSpeed + 1) * (m_sQueueSample.m_nFrequency / 2.0f);\n\t\t\t\tm_sQueueSample.m_nFrequency = clamp2(m_sQueueSample.m_nFrequency, freqSkimmerPrev, 197);\n\t\t\t\tfreqSkimmerPrev = m_sQueueSample.m_nFrequency;\n\n\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_SEAPLANE_PRO4;\n\t\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\t\tm_sQueueSample.m_nCounter = 12;\n\t\t\t\tm_sQueueSample.m_bIs2D = false;\n\t\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 3;\n\t\t\t\tm_sQueueSample.m_nLoopCount = 0;\n\t\t\t\tm_sQueueSample.m_nEmittingVolume = propellerSpeed * 100.0f;\n\t\t\t\tm_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(SFX_SEAPLANE_PRO4);\n\t\t\t\tm_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(SFX_SEAPLANE_PRO4);\n\t\t\t\tm_sQueueSample.m_fSpeedMultiplier = 5.0f;\n\t\t\t\tm_sQueueSample.m_fSoundIntensity = 20.0f;\n\t\t\t\tm_sQueueSample.m_bReleasingSoundFlag = false;\n\t\t\t\tm_sQueueSample.m_nReleasingVolumeDivider = 7;\n\t\t\t\tm_sQueueSample.m_bReverbFlag = true;\n\t\t\t\tm_sQueueSample.m_bRequireReflection = false;\n\t\t\t\tAddSampleToRequestedQueue();\n\t\t\t}\n\t\t}\n\t} else {\n\t\t//vacuum cleaner sound\n\t\tvecPosOld = m_sQueueSample.m_vecPos;\n\t\tdistanceCalculatedOld = params.m_bDistanceCalculated;\n\t\tdistanceOld = params.m_fDistance;\n\t\t\n\t\tif (automobile != nil)\n\t\t\tautomobile->GetComponentWorldPosition(CAR_BOOT, m_sQueueSample.m_vecPos);\n\t\telse if (params.m_VehicleType == VEHICLE_TYPE_HELI) \n\t\t\tm_sQueueSample.m_vecPos = CVector(0.0f, -10.0f, 0.0f); //this is from android, but for real it's not used\n\n\t\tparams.m_bDistanceCalculated = false;\n\t\tparams.m_fDistance = GetDistanceSquared(m_sQueueSample.m_vecPos);\n\t\tif (params.m_fDistance < SQR(27.0f)) {\n\t\t\tCalculateDistance(params.m_bDistanceCalculated, params.m_fDistance);\n\t\t\tm_sQueueSample.m_nVolume = ComputeVolume(volumeModifier * 25.0f, 27.0f, m_sQueueSample.m_fDistance);\n\t\t\tif (m_sQueueSample.m_nVolume) {\n\t\t\t\tm_sQueueSample.m_nCounter = 2;\n\t\t\t\tm_sQueueSample.m_nSampleIndex = hunterBool ? SFX_HELI_APACHE_3 : SFX_CAR_HELI_REA;\n\t\t\t\tm_sQueueSample.m_nBankIndex = 0;\n\t\t\t\tm_sQueueSample.m_bIs2D = false;\n\t\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 1;\n\t\t\t\tm_sQueueSample.m_nFrequency = (volumeModifier + 1.0f) * 16000;\n\t\t\t\tm_sQueueSample.m_nLoopCount = 0;\n\t\t\t\tm_sQueueSample.m_nEmittingVolume = volumeModifier * 25.0f;\n\t\t\t\tm_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex);\n\t\t\t\tm_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex);\n\t\t\t\tm_sQueueSample.m_fSpeedMultiplier = 6.0f;\n\t\t\t\tm_sQueueSample.m_fSoundIntensity = 27.0f;\n\t\t\t\tm_sQueueSample.m_bReleasingSoundFlag = false;\n\t\t\t\tm_sQueueSample.m_nReleasingVolumeDivider = 5;\n\t\t\t\tm_sQueueSample.m_bReverbFlag = true;\n\t\t\t\tm_sQueueSample.m_bRequireReflection = false;\n\t\t\t\tAddSampleToRequestedQueue();\n\t\t\t}\n\t\t}\n\t\t\n\t\tm_sQueueSample.m_vecPos = vecPosOld;\n\t\tparams.m_bDistanceCalculated = distanceCalculatedOld;\n\t\tparams.m_fDistance = distanceOld;\n\t}\n}\n\nvoid\ncAudioManager::ProcessVehicleFlatTyre(cVehicleParams& params)\n{\n\tconst float SOUND_INTENSITY = 60.0f;\n\n\tCAutomobile* automobile;\n\tCBike* bike;\n\tbool wheelBurst;\n\tuint8 emittingVol;\n\n\tfloat modifier;\n\n\tif (params.m_fDistance >= SQR(SOUND_INTENSITY))\n\t\treturn;\n\n\tswitch (params.m_VehicleType) {\n\tcase VEHICLE_TYPE_CAR:\n\t\tautomobile = (CAutomobile*)params.m_pVehicle;\n\t\twheelBurst = false;\n\t\tfor (int i = 0; i < 4; i++)\n\t\t\tif (automobile->Damage.GetWheelStatus(i) == WHEEL_STATUS_BURST && automobile->m_aWheelTimer[i] > 0.0f)\n\t\t\t\twheelBurst = true;\n\t\tif (!wheelBurst)\n\t\t\treturn;\n\t\tbreak;\n\tcase VEHICLE_TYPE_BIKE:\n\t\tbike = (CBike*)params.m_pVehicle;\n\t\twheelBurst = false;\n\t\tfor(int i = 0; i < 2; i++)\n\t\t\tif (bike->m_wheelStatus[i] == WHEEL_STATUS_BURST && bike->m_aWheelTimer[i] > 0.0f)\n\t\t\t\twheelBurst = true;\n\t\tif (!wheelBurst)\n\t\t\treturn;\n\t\tbreak;\n\tdefault:\n\t\treturn;\n\t}\n\tmodifier = Min(1.0f, Abs(params.m_fVelocityChange) / (0.3f * params.m_pTransmission->fMaxVelocity));\n\tif (modifier > 0.01f) { //mb can be replaced by (emittingVol > 1)\n\t\temittingVol = (100.0f * modifier);\n\t\tCalculateDistance(params.m_bDistanceCalculated, params.m_fDistance);\n\t\tm_sQueueSample.m_nVolume = ComputeVolume(emittingVol, SOUND_INTENSITY, m_sQueueSample.m_fDistance);\n\t\tif (m_sQueueSample.m_nVolume) {\n\t\t\tm_sQueueSample.m_nCounter = 95;\n\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\tm_sQueueSample.m_bIs2D = false;\n\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 5;\n\t\t\tm_sQueueSample.m_nSampleIndex = SFX_TYRE_BURST_L;\n\t\t\tm_sQueueSample.m_nFrequency = (5500.0f * modifier) + 8000;\n\t\t\tm_sQueueSample.m_nLoopCount = 0;\n\t\t\tm_sQueueSample.m_nEmittingVolume = emittingVol;\n\t\t\tm_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(SFX_TYRE_BURST_L);\n\t\t\tm_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(SFX_TYRE_BURST_L);\n\t\t\tm_sQueueSample.m_fSpeedMultiplier = 2.0f;\n\t\t\tm_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY;\n\t\t\tm_sQueueSample.m_bReleasingSoundFlag = false;\n\t\t\tm_sQueueSample.m_nReleasingVolumeDivider = 3;\n\t\t\tm_sQueueSample.m_bReverbFlag = true;\n\t\t\tm_sQueueSample.m_bRequireReflection = false;\n\t\t\tAddSampleToRequestedQueue();\n\t\t}\n\t}\n}\n\n//TODO use it in ProcessVehicle\nvoid\ncAudioManager::ProcessPlane(cVehicleParams& params)\n{\n\tswitch (params.m_nIndex) {\n\tcase AIRTRAIN:\n\t\tProcessJumbo(params);\n\t\tbreak;\n\tcase DEADDODO:\n\t\tProcessCesna(params);\n\t\tbreak;\n\tdefault:\n\t\tbreak;\n\t}\n}\n\n#pragma region JUMBO\nuint8 gJumboVolOffsetPercentage;\n\nvoid\nDoJumboVolOffset()\n{\n\tif (!(AudioManager.GetFrameCounter() % (AudioManager.GetRandomNumber(0) % 6 + 3)))\n\t\tgJumboVolOffsetPercentage = AudioManager.GetRandomNumber(1) % 60;\n}\n\nvoid\ncAudioManager::ProcessJumbo(cVehicleParams& params)\n{\n\tCPlane *plane;\n\tfloat position;\n\n\t if (params.m_fDistance >= SQR(440))\n\t\treturn;\n\n\tCalculateDistance(params.m_bDistanceCalculated, params.m_fDistance);\n\tplane = (CPlane*)params.m_pVehicle;\n\tDoJumboVolOffset();\n\tposition = PlanePathPosition[plane->m_nPlaneId];\n\tif (position <= TakeOffPoint) {\n\t\tif (plane->m_fSpeed > 0.103344f) {\n\t\t\tProcessJumboAccel(plane);\n\t\t} else {\n\t\t\tProcessJumboTaxi();\n\t\t}\n\t} else if (position <= TakeOffPoint + 300.0f) {\n\t\tProcessJumboTakeOff(plane);\n\t} else if (position <= LandingPoint - 350.0f) {\n\t\tProcessJumboFlying();\n\t} else if (position <= LandingPoint) {\n\t\tProcessJumboLanding(plane);\n\t} else if (plane->m_fSpeed > 0.103344f) {\n\t\tProcessJumboDecel(plane);\n\t} else {\n\t\tProcessJumboTaxi();\n\t}\n}\n\nvoid\ncAudioManager::ProcessJumboTaxi()\n{\n\tif (SetupJumboFlySound(20)) {\n\t\tif (SetupJumboTaxiSound(75))\n\t\t\tSetupJumboWhineSound(18, 29500);\n\t}\n}\n\nvoid\ncAudioManager::ProcessJumboAccel(CPlane *plane)\n{\n\tint32 engineFreq;\n\tint32 vol;\n\tfloat modificator;\n\tfloat freqModifier;\n\n\tif (SetupJumboFlySound(20)) {\n\t\tmodificator = Min(1.0f, (plane->m_fSpeed - 0.103344f) * 1.6760077f);\n\t\tif (SetupJumboRumbleSound(MAX_VOLUME * modificator) && SetupJumboTaxiSound((1.0f - modificator) * 75.f)) {\n\t\t\tif (modificator < 0.2f) {\n\t\t\t\tfreqModifier = modificator * 5.0f;\n\t\t\t\tvol = MAX_VOLUME * freqModifier;\n\t\t\t\tengineFreq = 6050.0f * freqModifier + 16000;\n\t\t\t} else {\n\t\t\t\tfreqModifier = 1.0f;\n\t\t\t\tengineFreq = 22050;\n\t\t\t\tvol = MAX_VOLUME;\n\t\t\t}\n\t\t\tSetupJumboEngineSound(vol, engineFreq);\n\t\t\tSetupJumboWhineSound(18, 14600.0f * freqModifier + 29500);\n\t\t}\n\t}\n}\n\nvoid\ncAudioManager::ProcessJumboTakeOff(CPlane *plane)\n{\n\tconst float modificator = (PlanePathPosition[plane->m_nPlaneId] - TakeOffPoint) / 300.f;\n\n\tif (SetupJumboFlySound((107.f * modificator) + 20) && SetupJumboRumbleSound(MAX_VOLUME * (1.f - modificator))) {\n\t\tif (SetupJumboEngineSound(MAX_VOLUME, 22050))\n\t\t\tSetupJumboWhineSound(18.f * (1.f - modificator), 44100);\n\t}\n}\n\nvoid\ncAudioManager::ProcessJumboFlying()\n{\n\tif (SetupJumboFlySound(MAX_VOLUME))\n\t\tSetupJumboEngineSound(63, 22050);\n}\n\nvoid\ncAudioManager::ProcessJumboLanding(CPlane *plane)\n{\n\tconst float modificator = (LandingPoint - PlanePathPosition[plane->m_nPlaneId]) / 350.f;\n\tif (SetupJumboFlySound(107.f * modificator + 20)) {\n\t\tif (SetupJumboTaxiSound(75.f * (1.f - modificator))) {\n\t\t\tSetupJumboEngineSound(MAX_VOLUME, 22050);\n\t\t\tSetupJumboWhineSound(18.f * (1.f - modificator), 14600.f * modificator + 29500);\n\t\t}\n\t}\n}\n\nvoid\ncAudioManager::ProcessJumboDecel(CPlane *plane)\n{\n\tif (SetupJumboFlySound(20) && SetupJumboTaxiSound(75)) {\n\t\tconst float modificator = Min(1.f, (plane->m_fSpeed - 0.103344f) * 1.6760077f);\n\t\tSetupJumboEngineSound(MAX_VOLUME * modificator, 6050.f * modificator + 16000);\n\t\tSetupJumboWhineSound(18, 29500);\n\t}\n}\n\nbool\ncAudioManager::SetupJumboTaxiSound(uint8 vol)\n{\n\tconst float SOUND_INTENSITY = 180.0f;\n\tif (m_sQueueSample.m_fDistance >= SOUND_INTENSITY)\n\t\treturn false;\n\n\tuint8 emittingVol = (vol / 2) + ((vol / 2) * m_sQueueSample.m_fDistance / SOUND_INTENSITY);\n\n\tif (m_sQueueSample.m_fDistance / SOUND_INTENSITY < 0.7f)\n\t\temittingVol -= emittingVol * gJumboVolOffsetPercentage / 100;\n\tm_sQueueSample.m_nVolume = ComputeVolume(emittingVol, SOUND_INTENSITY, m_sQueueSample.m_fDistance);\n\n\tif (m_sQueueSample.m_nVolume != 0) {\n\t\tm_sQueueSample.m_nCounter = 1;\n\t\tm_sQueueSample.m_nSampleIndex = SFX_JUMBO_TAXI;\n\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\tm_sQueueSample.m_bIs2D = false;\n\t\tm_sQueueSample.m_nReleasingVolumeModificator = 1;\n\t\tm_sQueueSample.m_nFrequency = GetJumboTaxiFreq();\n\t\tm_sQueueSample.m_nLoopCount = 0;\n\t\tm_sQueueSample.m_nEmittingVolume = emittingVol;\n\t\tm_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex);\n\t\tm_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex);\n\t\tm_sQueueSample.m_fSpeedMultiplier = 4.0f;\n\t\tm_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY;\n\t\tm_sQueueSample.m_bReleasingSoundFlag = false;\n\t\tm_sQueueSample.m_nReleasingVolumeDivider = 4;\n\t\tm_sQueueSample.m_bReverbFlag = true;\n\t\tm_sQueueSample.m_bRequireReflection = false;\n\t\tAddSampleToRequestedQueue();\n\t}\n\treturn true;\n}\n\nbool\ncAudioManager::SetupJumboWhineSound(uint8 emittingVol, uint32 freq)\n{\n\tconst float SOUND_INTENSITY = 170.0f;\n\n\tif (m_sQueueSample.m_fDistance >= SOUND_INTENSITY)\n\t\treturn false;\n\n\tm_sQueueSample.m_nVolume = ComputeVolume(emittingVol, SOUND_INTENSITY, m_sQueueSample.m_fDistance);\n\n\tif (m_sQueueSample.m_nVolume != 0) {\n\t\tm_sQueueSample.m_nCounter = 2;\n\t\tm_sQueueSample.m_nSampleIndex = SFX_JUMBO_WHINE;\n\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\tm_sQueueSample.m_bIs2D = false;\n\t\tm_sQueueSample.m_nReleasingVolumeModificator = 1;\n\t\tm_sQueueSample.m_nFrequency = freq;\n\t\tm_sQueueSample.m_nLoopCount = 0;\n\t\tm_sQueueSample.m_nEmittingVolume = emittingVol;\n\t\tm_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex);\n\t\tm_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex);\n\t\tm_sQueueSample.m_fSpeedMultiplier = 4.0f;\n\t\tm_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY;\n\t\tm_sQueueSample.m_bReleasingSoundFlag = false;\n\t\tm_sQueueSample.m_nReleasingVolumeDivider = 4;\n\t\tm_sQueueSample.m_bReverbFlag = true;\n\t\tm_sQueueSample.m_bRequireReflection = false;\n\t\tAddSampleToRequestedQueue();\n\t}\n\treturn true;\n}\n\nbool\ncAudioManager::SetupJumboEngineSound(uint8 vol, uint32 freq)\n{\n\tconst float SOUND_INTENSITY = 180.0f;\n\tif (m_sQueueSample.m_fDistance >= SOUND_INTENSITY)\n\t\treturn false;\n\n\tuint8 emittingVol = vol - gJumboVolOffsetPercentage / 100;\n\tm_sQueueSample.m_nVolume = ComputeVolume(emittingVol, SOUND_INTENSITY, m_sQueueSample.m_fDistance);\n\tif (m_sQueueSample.m_nVolume != 0) {\n\t\tm_sQueueSample.m_nCounter = 3;\n\t\tm_sQueueSample.m_nSampleIndex = SFX_JUMBO_ENGINE;\n\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\tm_sQueueSample.m_bIs2D = false;\n\t\tm_sQueueSample.m_nReleasingVolumeModificator = 1;\n\t\tm_sQueueSample.m_nFrequency = freq;\n\t\tm_sQueueSample.m_nLoopCount = 0;\n\t\tm_sQueueSample.m_nEmittingVolume = emittingVol;\n\t\tm_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex);\n\t\tm_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex);\n\t\tm_sQueueSample.m_fSpeedMultiplier = 4.0f;\n\t\tm_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY;\n\t\tm_sQueueSample.m_bReleasingSoundFlag = false;\n\t\tm_sQueueSample.m_nReleasingVolumeDivider = 4;\n\t\tm_sQueueSample.m_bReverbFlag = true;\n\t\tm_sQueueSample.m_bRequireReflection = false;\n\t\tAddSampleToRequestedQueue();\n\t}\n\treturn true;\n}\n\nbool\ncAudioManager::SetupJumboFlySound(uint8 emittingVol)\n{\n\tconst float SOUND_INTENSITY = 440.0f;\n\tif(m_sQueueSample.m_fDistance >= SOUND_INTENSITY) return false;\n\n\tint32 vol = ComputeVolume(emittingVol, SOUND_INTENSITY, m_sQueueSample.m_fDistance);\n\tm_sQueueSample.m_nVolume = vol;\n\tif(m_sQueueSample.m_nVolume != 0) {\n\t\tm_sQueueSample.m_nCounter = 0;\n\t\tm_sQueueSample.m_nSampleIndex = SFX_JUMBO_DIST_FLY;\n\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\tm_sQueueSample.m_bIs2D = false;\n\t\tm_sQueueSample.m_nReleasingVolumeModificator = 1;\n\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_JUMBO_DIST_FLY);\n\t\tm_sQueueSample.m_nLoopCount = 0;\n\t\tm_sQueueSample.m_nEmittingVolume = emittingVol;\n\t\tm_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex);\n\t\tm_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex);\n\t\tm_sQueueSample.m_fSpeedMultiplier = 4.0f;\n\t\tm_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY;\n\t\tm_sQueueSample.m_bReleasingSoundFlag = false;\n\t\tm_sQueueSample.m_nReleasingVolumeDivider = 5;\n\t\tm_sQueueSample.m_bReverbFlag = true;\n\t\tm_sQueueSample.m_bRequireReflection = false; // todo port fix to re3\n\t\tAddSampleToRequestedQueue();\n\t}\n\treturn true;\n}\n\nbool\ncAudioManager::SetupJumboRumbleSound(uint8 emittingVol)\n{\n\tconst float SOUND_INTENSITY = 240.0f;\n\tif (m_sQueueSample.m_fDistance >= SOUND_INTENSITY)\n\t\treturn false;\n\n\tm_sQueueSample.m_nVolume = ComputeVolume(emittingVol, SOUND_INTENSITY, m_sQueueSample.m_fDistance);\n\n\tif (m_sQueueSample.m_nVolume != 0) {\n\t\tm_sQueueSample.m_nCounter = 5;\n\t\tm_sQueueSample.m_nSampleIndex = SFX_JUMBO_RUMBLE;\n\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\tm_sQueueSample.m_bIs2D = true;\n\t\tm_sQueueSample.m_nReleasingVolumeModificator = 1;\n\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_JUMBO_RUMBLE);\n\t\tm_sQueueSample.m_nLoopCount = 0;\n\t\tm_sQueueSample.m_nEmittingVolume = emittingVol;\n\t\tm_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex);\n\t\tm_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex);\n\t\tm_sQueueSample.m_fSpeedMultiplier = 4.0f;\n\t\tm_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY;\n\t\tm_sQueueSample.m_bReleasingSoundFlag = false;\n\t\tm_sQueueSample.m_nReleasingVolumeDivider = 12;\n\t\tm_sQueueSample.m_nOffset = 0;\n\t\tm_sQueueSample.m_bReverbFlag = true;\n\t\tm_sQueueSample.m_bRequireReflection = false;\n\t\tAddSampleToRequestedQueue();\n\t\tm_sQueueSample.m_nCounter = 6;\n\t\tm_sQueueSample.m_nSampleIndex = SFX_JUMBO_RUMBLE;\n\t\tm_sQueueSample.m_nFrequency += 200;\n\t\tm_sQueueSample.m_nOffset = MAX_VOLUME;\n\t\tAddSampleToRequestedQueue();\n\t}\n\treturn true;\n}\n\nint32\ncAudioManager::GetJumboTaxiFreq() const\n{\n\treturn (1.f / 180 * 10950 * m_sQueueSample.m_fDistance) + 22050; // todo port fix to re3\n}\n\n#pragma endregion Some jumbo crap\n\n#pragma endregion All the vehicle audio code\n\n#pragma region PED AUDIO\nvoid\ncAudioManager::ProcessPed(CPhysical *ped)\n{\n\tcPedParams params;\n\n\tm_sQueueSample.m_vecPos = ped->GetPosition();\n\n\tparams.m_bDistanceCalculated = false;\n\tparams.m_pPed = (CPed *)ped;\n\tparams.m_fDistance = GetDistanceSquared(m_sQueueSample.m_vecPos);\n\tProcessPedOneShots(params);\n}\n\nvoid\ncAudioManager::ProcessPedOneShots(cPedParams &params)\n{\n\tuint8 emittingVol;\n\tint32 sampleIndex;\n\n\tCPed *ped = params.m_pPed;\n\n\tbool narrowSoundRange;\n\tint16 sound;\n\tbool stereo;\n\tCWeapon *weapon;\n\tfloat maxDist = 0.f; // uninitialized variable\n\n\tstatic uint8 iSound = 21;\n\tstatic uint32 iSplashFrame = 0;\n\n\tweapon = params.m_pPed->GetWeapon();\n\tfor (uint32 i = 0; i < m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_AudioEvents; i++) {\n\t\tstereo = false;\n\t\tnarrowSoundRange = false;\n\t\tm_sQueueSample.m_bRequireReflection = false;\n\t\tsound = m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_awAudioEvent[i];\n\t\tswitch (sound) {\n\t\tcase SOUND_STEP_START:\n\t\tcase SOUND_STEP_END:\n\t\t\tif (params.m_pPed->bIsInTheAir)\n\t\t\t\tcontinue;\n\t\t\temittingVol = m_anRandomTable[3] % 15 + 45;\n\t\t\tif (FindPlayerPed() != m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_pEntity)\n\t\t\t\temittingVol /= 2;\n\t\t\tmaxDist = 400.f;\n\t\t\tswitch (params.m_pPed->m_nSurfaceTouched) {\n\t\t\tcase SURFACE_GRASS:\n\t\t\t\tsampleIndex = m_anRandomTable[1] % 5 + SFX_FOOTSTEP_GRASS_1;\n\t\t\t\tbreak;\n\t\t\tcase SURFACE_GRAVEL:\n\t\t\tcase SURFACE_MUD_DRY:\n\t\t\t\tsampleIndex = m_anRandomTable[4] % 5 + SFX_FOOTSTEP_GRAVEL_1;\n\t\t\t\tbreak;\n\t\t\tcase SURFACE_CAR:\n\t\t\tcase SURFACE_GARAGE_DOOR:\n\t\t\tcase SURFACE_CAR_PANEL:\n\t\t\tcase SURFACE_THICK_METAL_PLATE:\n\t\t\tcase SURFACE_SCAFFOLD_POLE:\n\t\t\tcase SURFACE_LAMP_POST:\n\t\t\tcase SURFACE_FIRE_HYDRANT:\n\t\t\tcase SURFACE_GIRDER:\n\t\t\tcase SURFACE_METAL_CHAIN_FENCE:\n\t\t\tcase SURFACE_CONTAINER:\n\t\t\tcase SURFACE_NEWS_VENDOR:\n\t\t\t\tsampleIndex = m_anRandomTable[0] % 5 + SFX_FOOTSTEP_METAL_1;\n\t\t\t\tbreak;\n\t\t\tcase SURFACE_SAND:\n\t\t\t\tsampleIndex = (m_anRandomTable[4] & 3) + SFX_FOOTSTEP_SAND_1;\n\t\t\t\tbreak;\n\t\t\tcase SURFACE_WATER:\n\t\t\t\tsampleIndex = (m_anRandomTable[3] & 3) + SFX_FOOTSTEP_WATER_1;\n\t\t\t\tbreak;\n\t\t\tcase SURFACE_WOOD_CRATES:\n\t\t\tcase SURFACE_WOOD_BENCH:\n\t\t\tcase SURFACE_WOOD_SOLID:\n\t\t\t\tsampleIndex = m_anRandomTable[2] % 5 + SFX_FOOTSTEP_WOOD_1;\n\t\t\t\tbreak;\n\t\t\tcase SURFACE_HEDGE:\n\t\t\t\tsampleIndex = m_anRandomTable[2] % 5 + SFX_COL_VEG_1;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tsampleIndex = m_anRandomTable[2] % 5 + SFX_FOOTSTEP_CONCRETE_1;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tm_sQueueSample.m_nSampleIndex = sampleIndex;\n\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\tm_sQueueSample.m_nCounter = m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_awAudioEvent[i] - SOUND_STEP_START + 1;\n\t\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex);\n\t\t\tm_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 17);\n\t\t\tswitch (params.m_pPed->m_nMoveState) {\n\t\t\tcase PEDMOVE_WALK:\n\t\t\t\temittingVol /= 4;\n\t\t\t\tm_sQueueSample.m_nFrequency = 9 * m_sQueueSample.m_nFrequency / 10;\n\t\t\t\tbreak;\n\t\t\tcase PEDMOVE_RUN:\n\t\t\t\temittingVol /= 2;\n\t\t\t\tm_sQueueSample.m_nFrequency = 11 * m_sQueueSample.m_nFrequency / 10;\n\t\t\t\tbreak;\n\t\t\tcase PEDMOVE_SPRINT:\n\t\t\t\tm_sQueueSample.m_nFrequency = 12 * m_sQueueSample.m_nFrequency / 10;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 5;\n\t\t\tm_sQueueSample.m_fSpeedMultiplier = 0.0f;\n\t\t\tm_sQueueSample.m_fSoundIntensity = 20.0f;\n\t\t\tm_sQueueSample.m_nLoopCount = 1;\n\t\t\tm_sQueueSample.m_nLoopStart = 0;\n\t\t\tm_sQueueSample.m_nLoopEnd = -1;\n\t\t\tm_sQueueSample.m_nEmittingVolume = emittingVol;\n\t\t\tm_sQueueSample.m_bIs2D = false;\n\t\t\tm_sQueueSample.m_bReleasingSoundFlag = true;\n\t\t\tm_sQueueSample.m_bRequireReflection = true;\n\t\t\tbreak;\n\t\tcase SOUND_FALL_LAND:\n\t\tcase SOUND_FALL_COLLAPSE:\n\t\t\tif (ped->bIsInTheAir)\n\t\t\t\tcontinue;\n\t\t\tmaxDist = SQR(30);\n\t\t\temittingVol = m_anRandomTable[3] % 20 + 80;\n\t\t\tif (ped->m_nSurfaceTouched == SURFACE_WATER) {\n\t\t\t\tm_sQueueSample.m_nSampleIndex = (m_anRandomTable[3] & 3) + SFX_FOOTSTEP_WATER_1;\n\t\t\t} else if (sound == SOUND_FALL_LAND) {\n\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_BODY_LAND;\n\t\t\t} else {\n\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_BODY_LAND_AND_FALL;\n\t\t\t}\n\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\tm_sQueueSample.m_nCounter = 1;\n\t\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex);\n\t\t\tm_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 17);\n\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 2;\n\t\t\tm_sQueueSample.m_fSpeedMultiplier = 0.0f;\n\t\t\tm_sQueueSample.m_fSoundIntensity = 30.0f;\n\t\t\tm_sQueueSample.m_nLoopCount = 1;\n\t\t\tm_sQueueSample.m_nLoopStart = 0;\n\t\t\tm_sQueueSample.m_nLoopEnd = -1;\n\t\t\tm_sQueueSample.m_nEmittingVolume = emittingVol;\n\t\t\tm_sQueueSample.m_bIs2D = false;\n\t\t\tm_sQueueSample.m_bReleasingSoundFlag = true;\n\t\t\tm_sQueueSample.m_bRequireReflection = true;\n\t\t\tbreak;\n\t\tcase SOUND_FIGHT_37:\n\t\t\tm_sQueueSample.m_nSampleIndex = SFX_FIGHT_1;\n\t\t\tm_sQueueSample.m_nFrequency = 18000;\n\t\t\tgoto AddFightSound;\n\t\tcase SOUND_FIGHT_38:\n\t\t\tm_sQueueSample.m_nSampleIndex = SFX_FIGHT_1;\n\t\t\tm_sQueueSample.m_nFrequency = 16500;\n\t\t\tgoto AddFightSound;\n\t\tcase SOUND_FIGHT_39:\n\t\t\tm_sQueueSample.m_nSampleIndex = SFX_FIGHT_1;\n\t\t\tm_sQueueSample.m_nFrequency = 20000;\n\t\t\tgoto AddFightSound;\n\t\tcase SOUND_FIGHT_40:\n\t\t\tm_sQueueSample.m_nSampleIndex = SFX_FIGHT_2;\n\t\t\tm_sQueueSample.m_nFrequency = 18000;\n\t\t\tgoto AddFightSound;\n\t\tcase SOUND_FIGHT_41:\n\t\t\tm_sQueueSample.m_nSampleIndex = SFX_FIGHT_2;\n\t\t\tm_sQueueSample.m_nFrequency = 16500;\n\t\t\tgoto AddFightSound;\n\t\tcase SOUND_FIGHT_42:\n\t\t\tm_sQueueSample.m_nSampleIndex = SFX_FIGHT_2;\n\t\t\tm_sQueueSample.m_nFrequency = 20000;\n\t\t\tgoto AddFightSound;\n\t\tcase SOUND_FIGHT_43:\n\t\t\tm_sQueueSample.m_nSampleIndex = SFX_FIGHT_4;\n\t\t\tm_sQueueSample.m_nFrequency = 18000;\n\t\t\tgoto AddFightSound;\n\t\tcase SOUND_FIGHT_44:\n\t\t\tm_sQueueSample.m_nSampleIndex = SFX_FIGHT_4;\n\t\t\tm_sQueueSample.m_nFrequency = 16500;\n\t\t\tgoto AddFightSound;\n\t\tcase SOUND_FIGHT_45:\n\t\t\tm_sQueueSample.m_nSampleIndex = SFX_FIGHT_4;\n\t\t\tm_sQueueSample.m_nFrequency = 20000;\n\t\t\tgoto AddFightSound;\n\t\tcase SOUND_FIGHT_46:\n\t\tcase SOUND_187:\n\t\t\tm_sQueueSample.m_nSampleIndex = SFX_FIGHT_5;\n\t\t\tm_sQueueSample.m_nFrequency = 18000;\n\t\t\tgoto AddFightSound;\n\t\tcase SOUND_FIGHT_47:\n\t\t\tm_sQueueSample.m_nSampleIndex = SFX_FIGHT_5;\n\t\t\tm_sQueueSample.m_nFrequency = 16500;\n\t\t\tgoto AddFightSound;\n\t\tcase SOUND_FIGHT_48:\n\t\t\tm_sQueueSample.m_nSampleIndex = SFX_FIGHT_5;\n\t\t\tm_sQueueSample.m_nFrequency = 20000;\n\t\tAddFightSound:\n\t\t\t{\n\t\t\t\tuint32 soundParams = m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_afVolume[i]; // wtf? storing int as float\n\t\t\t\tuint8 damagerType = soundParams & 0xFF;\n\t\t\t\tuint32 weaponType = soundParams >> 8;\n\n\t\t\t\tif (damagerType == ENTITY_TYPE_PED) {\n\t\t\t\t\tif (weaponType == WEAPONTYPE_BRASSKNUCKLE) {\n\t\t\t\t\t\tCPed* ped = params.m_pPed;\n\t\t\t\t\t\tuint32 fightMove = ped->m_curFightMove;\n\t\t\t\t\t\tif (fightMove == FIGHTMOVE_BACKLEFT || fightMove == FIGHTMOVE_STDPUNCH || fightMove == FIGHTMOVE_PUNCH ||\n\t\t\t\t\t\t\tped->m_nPedState == PED_ATTACK) {\n\t\t\t\t\t\t\tCEntity* damageEntity = ped->m_pDamageEntity;\n\t\t\t\t\t\t\tif (!damageEntity)\n\t\t\t\t\t\t\t\tm_sQueueSample.m_nSampleIndex = m_anRandomTable[3] % 2 + SFX_HAMMER_HIT_1;\n\t\t\t\t\t\t\telse if (damageEntity->GetType() != ENTITY_TYPE_PED)\n\t\t\t\t\t\t\t\tm_sQueueSample.m_nSampleIndex = m_anRandomTable[3] % 2 + SFX_HAMMER_HIT_1;\n\t\t\t\t\t\t\telse if (((CPed*)damageEntity)->m_curFightMove != FIGHTMOVE_HITHEAD)\n\t\t\t\t\t\t\t\tm_sQueueSample.m_nSampleIndex = m_anRandomTable[3] % 2 + SFX_HAMMER_HIT_1;\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_HAMMER_HIT_1;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tm_sQueueSample.m_nSampleIndex = m_anRandomTable[4] % 6 + SFX_COL_CAR_PANEL_1;\n\t\t\t\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex);\n\t\t\t\t\tm_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 16);\n\t\t\t\t}\n\t\t\t}\n\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\tm_sQueueSample.m_nCounter = iSound;\n\t\t\tnarrowSoundRange = true;\n\t\t\t++iSound;\n\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 3;\n\t\t\tm_sQueueSample.m_fSpeedMultiplier = 0.0f;\n\t\t\tm_sQueueSample.m_fSoundIntensity = 30.0f;\n\t\t\tmaxDist = SQR(30);\n\t\t\tm_sQueueSample.m_nLoopCount = 1;\n\t\t\tm_sQueueSample.m_nLoopStart = 0;\n\t\t\temittingVol = m_anRandomTable[3] % 26 + 100;\n\t\t\tm_sQueueSample.m_nLoopEnd = -1;\n\t\t\tm_sQueueSample.m_nEmittingVolume = emittingVol;\n\t\t\tm_sQueueSample.m_bIs2D = false;\n\t\t\tm_sQueueSample.m_bReleasingSoundFlag = true;\n\t\t\tm_sQueueSample.m_bRequireReflection = true;\n\t\t\tbreak;\n\t\tcase SOUND_WEAPON_BAT_ATTACK:\n\t\tcase SOUND_WEAPON_KNIFE_ATTACK:\n\t\t{\n\t\t\tuint32 soundParams = m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_afVolume[i]; // wtf? storing int as float\n\t\t\tuint8 damagerType = soundParams & 0xFF;\n\t\t\tuint32 weaponType = soundParams >> 8;\n\t\t\tif (damagerType == ENTITY_TYPE_PED) {\n\t\t\t\tswitch (weaponType) {\n\t\t\t\tcase WEAPONTYPE_SCREWDRIVER:\n\t\t\t\tcase WEAPONTYPE_KNIFE:\n\t\t\t\tcase WEAPONTYPE_CLEAVER:\n\t\t\t\tcase WEAPONTYPE_MACHETE:\n\t\t\t\tcase WEAPONTYPE_KATANA:\n\t\t\t\t\tif (sound == SOUND_WEAPON_KNIFE_ATTACK)\n\t\t\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_KNIFE_SLASH;\n\t\t\t\t\telse\n\t\t\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_KNIFE_STAB;\n\t\t\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\t\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex);\n\t\t\t\t\tm_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 32);\n\t\t\t\t\tbreak;\n\t\t\t\tcase WEAPONTYPE_HAMMER:\n\t\t\t\t\tm_sQueueSample.m_nSampleIndex = m_anRandomTable[3] % 2 + SFX_HAMMER_HIT_1;\n\t\t\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\t\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex);\n\t\t\t\t\tm_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 32);\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_BAT_HIT_LEFT;\n\t\t\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\t\t\tm_sQueueSample.m_nFrequency = RandomDisplacement(2000) + 22000;\n\t\t\t\t\tstereo = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tm_sQueueSample.m_nSampleIndex = m_anRandomTable[4] % 6 + SFX_COL_CAR_PANEL_1;\n\t\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex);\n\t\t\t\tm_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 16);\n\t\t\t}\n\t\t\tm_sQueueSample.m_nCounter = iSound++;\n\t\t\tnarrowSoundRange = true;\n\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 3;\n\t\t\tm_sQueueSample.m_fSpeedMultiplier = 0.0f;\n\t\t\tm_sQueueSample.m_fSoundIntensity = 30.0f;\n\t\t\tmaxDist = SQR(30);\n\t\t\tm_sQueueSample.m_nLoopCount = 1;\n\t\t\tm_sQueueSample.m_nLoopStart = 0;\n\t\t\tm_sQueueSample.m_nLoopEnd = -1;\n\t\t\temittingVol = m_anRandomTable[2] % 20 + 100;\n\t\t\tm_sQueueSample.m_nEmittingVolume = emittingVol;\n\t\t\tm_sQueueSample.m_bIs2D = false;\n\t\t\tm_sQueueSample.m_bReleasingSoundFlag = true;\n\t\t\tm_sQueueSample.m_bRequireReflection = true;\n\t\t\tbreak;\n\t\t}\n\t\tcase SOUND_WEAPON_CHAINSAW_ATTACK:\n\t\t\tif (FindVehicleOfPlayer())\n\t\t\t\tcontinue;\n\t\t\tm_sQueueSample.m_nSampleIndex = SFX_CAR_ACCEL_13;\n\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0; // SFX_BANK_CAR_CHAINSAW\n\t\t\tm_sQueueSample.m_nCounter = 70;\n\t\t\tm_sQueueSample.m_nFrequency = 27000;\n\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 3;\n\t\t\tm_sQueueSample.m_fSpeedMultiplier = 3.0f;\n\t\t\tm_sQueueSample.m_fSoundIntensity = 50.0f;\n\t\t\tmaxDist = SQR(50);\n\t\t\tm_sQueueSample.m_nLoopCount = 0;\n\t\t\temittingVol = 100;\n\t\t\tm_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(SFX_CAR_ACCEL_13);\n\t\t\tm_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(SFX_CAR_ACCEL_13);\n\t\t\tm_sQueueSample.m_nEmittingVolume = 100;\n\t\t\tm_sQueueSample.m_bIs2D = false;\n\t\t\tm_sQueueSample.m_bReleasingSoundFlag = false;\n\t\t\tm_sQueueSample.m_nReleasingVolumeDivider = 5;\n\t\t\tbreak;\n\t\tcase SOUND_WEAPON_CHAINSAW_IDLE:\n\t\t\tif (FindVehicleOfPlayer())\n\t\t\t\tcontinue;\n\t\t\tm_sQueueSample.m_nSampleIndex = SFX_CAR_AFTER_ACCEL_13;\n\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0; // SFX_BANK_CAR_CHAINSAW\n\t\t\tm_sQueueSample.m_nCounter = 68;\n\t\t\tm_sQueueSample.m_nFrequency = 27000;\n\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 2;\n\t\t\tm_sQueueSample.m_fSpeedMultiplier = 3.0f;\n\t\t\tm_sQueueSample.m_fSoundIntensity = 60.0f;\n\t\t\tmaxDist = SQR(60);\n\t\t\tm_sQueueSample.m_nLoopCount = 0;\n\t\t\temittingVol = 100;\n\t\t\tm_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(SFX_CAR_AFTER_ACCEL_13);\n\t\t\tm_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(SFX_CAR_AFTER_ACCEL_13);\n\t\t\tm_sQueueSample.m_nEmittingVolume = 100;\n\t\t\tm_sQueueSample.m_bIs2D = false;\n\t\t\tm_sQueueSample.m_bReleasingSoundFlag = false;\n\t\t\tm_sQueueSample.m_nReleasingVolumeDivider = 5;\n\t\t\tbreak;\n\t\tcase SOUND_WEAPON_CHAINSAW_MADECONTACT:\n\t\t\tif (FindVehicleOfPlayer())\n\t\t\t\tcontinue;\n\t\t\tif ((int32)m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_afVolume[i] != ENTITY_TYPE_PED)\n\t\t\t\tReportCollision(params.m_pPed, params.m_pPed, SURFACE_CAR, SURFACE_TARMAC, 0.0f, 0.09f);\n\t\t\tm_sQueueSample.m_nSampleIndex = SFX_CAR_AFTER_ACCEL_13;\n\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0; // SFX_BANK_CAR_CHAINSAW\n\t\t\tm_sQueueSample.m_nCounter = 68;\n\t\t\tm_sQueueSample.m_nFrequency = RandomDisplacement(500) + 22000;\n\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 2;\n\t\t\tm_sQueueSample.m_fSpeedMultiplier = 3.0f;\n\t\t\tm_sQueueSample.m_fSoundIntensity = 60.0f;\n\t\t\tmaxDist = SQR(60);\n\t\t\tm_sQueueSample.m_nLoopCount = 0;\n\t\t\temittingVol = 100;\n\t\t\tm_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(SFX_CAR_AFTER_ACCEL_13);\n\t\t\tm_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(SFX_CAR_AFTER_ACCEL_13);\n\t\t\tm_sQueueSample.m_nEmittingVolume = 100;\n\t\t\tm_sQueueSample.m_bIs2D = false;\n\t\t\tm_sQueueSample.m_bReleasingSoundFlag = false;\n\t\t\tm_sQueueSample.m_nReleasingVolumeDivider = 5;\n\t\t\tbreak;\n\t\tcase SOUND_WEAPON_SHOT_FIRED:\n\t\t\tweapon = ped->GetWeapon();\n\t\t\tif (!weapon)\n\t\t\t\tcontinue;\n\t\t\tswitch (weapon->m_eWeaponType) {\n\t\t\tcase WEAPONTYPE_ROCKET:\n\t\t\tcase WEAPONTYPE_ROCKETLAUNCHER:\n\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_ROCKET_LEFT;\n\t\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\t\tm_sQueueSample.m_nCounter = iSound++;\n\t\t\t\tnarrowSoundRange = true;\n\t\t\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_ROCKET_LEFT);\n\t\t\t\tm_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 32);\n\t\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 1;\n\t\t\t\tm_sQueueSample.m_fSpeedMultiplier = 0.0f;\n\t\t\t\tm_sQueueSample.m_fSoundIntensity = 120.0f;\n\t\t\t\tmaxDist = SQR(120);\n\t\t\t\tm_sQueueSample.m_nLoopCount = 1;\n\t\t\t\tm_sQueueSample.m_nLoopStart = 0;\n\t\t\t\tm_sQueueSample.m_nLoopEnd = -1;\n\t\t\t\temittingVol = m_anRandomTable[0] % 20 + 80;\n\t\t\t\tm_sQueueSample.m_nEmittingVolume = emittingVol;\n\t\t\t\tm_sQueueSample.m_bIs2D = false;\n\t\t\t\tm_sQueueSample.m_bReleasingSoundFlag = true;\n\t\t\t\tm_sQueueSample.m_bRequireReflection = true;\n\t\t\t\tstereo = true;\n\t\t\t\tbreak;\n\t\t\tcase WEAPONTYPE_COLT45:\n\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_COLT45_LEFT;\n\t\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\t\tm_sQueueSample.m_nCounter = iSound++;\n\t\t\t\tnarrowSoundRange = true;\n\t\t\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_COLT45_LEFT);\n\t\t\t\tm_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 32);\n\t\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 3;\n\t\t\t\tm_sQueueSample.m_fSpeedMultiplier = 0.0f;\n\t\t\t\tm_sQueueSample.m_fSoundIntensity = 120.0f;\n\t\t\t\tmaxDist = SQR(120);\n\t\t\t\tm_sQueueSample.m_nLoopCount = 1;\n\t\t\t\tm_sQueueSample.m_nLoopStart = 0;\n\t\t\t\tm_sQueueSample.m_nLoopEnd = -1;\n\t\t\t\temittingVol = m_anRandomTable[1] % 10 + 90;\n\t\t\t\tm_sQueueSample.m_nEmittingVolume = emittingVol;\n\t\t\t\tm_sQueueSample.m_bIs2D = false;\n\t\t\t\tm_sQueueSample.m_bReleasingSoundFlag = true;\n\t\t\t\tm_sQueueSample.m_bRequireReflection = true;\n\t\t\t\tstereo = true;\n\t\t\t\tbreak;\n\t\t\tcase WEAPONTYPE_PYTHON:\n\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_PYTHON_LEFT;\n\t\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\t\tm_sQueueSample.m_nCounter = iSound++;\n\t\t\t\tnarrowSoundRange = true;\n\t\t\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_PYTHON_LEFT);\n\t\t\t\tm_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 32);\n\t\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 3;\n\t\t\t\tm_sQueueSample.m_fSpeedMultiplier = 0.0f;\n\t\t\t\tm_sQueueSample.m_fSoundIntensity = 120.0f;\n\t\t\t\tmaxDist = SQR(120);\n\t\t\t\tm_sQueueSample.m_nLoopCount = 1;\n\t\t\t\tm_sQueueSample.m_nLoopStart = 0;\n\t\t\t\tm_sQueueSample.m_nLoopEnd = -1;\n\t\t\t\temittingVol = 127;\n\t\t\t\tm_sQueueSample.m_nEmittingVolume = emittingVol;\n\t\t\t\tm_sQueueSample.m_bIs2D = false;\n\t\t\t\tm_sQueueSample.m_bReleasingSoundFlag = true;\n\t\t\t\tm_sQueueSample.m_bRequireReflection = true;\n\t\t\t\tstereo = true;\n\t\t\t\tbreak;\n\t\t\tcase WEAPONTYPE_SHOTGUN:\n\t\t\tcase WEAPONTYPE_STUBBY_SHOTGUN:\n\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_SHOTGUN_LEFT;\n\t\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\t\tm_sQueueSample.m_nCounter = iSound++;\n\t\t\t\tnarrowSoundRange = true;\n\t\t\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_SHOTGUN_LEFT);\n\t\t\t\tm_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 32);\n\t\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 3;\n\t\t\t\tm_sQueueSample.m_fSpeedMultiplier = 0.0f;\n\t\t\t\tm_sQueueSample.m_fSoundIntensity = 120.0f;\n\t\t\t\tmaxDist = SQR(120);\n\t\t\t\tm_sQueueSample.m_nLoopCount = 1;\n\t\t\t\tm_sQueueSample.m_nLoopStart = 0;\n\t\t\t\tm_sQueueSample.m_nLoopEnd = -1;\n\t\t\t\temittingVol = m_anRandomTable[2] % 10 + 100;\n\t\t\t\tm_sQueueSample.m_nEmittingVolume = emittingVol;\n\t\t\t\tm_sQueueSample.m_bIs2D = false;\n\t\t\t\tm_sQueueSample.m_bReleasingSoundFlag = true;\n\t\t\t\tm_sQueueSample.m_bRequireReflection = true;\n\t\t\t\tstereo = true;\n\t\t\t\tbreak;\n\t\t\tcase WEAPONTYPE_SPAS12_SHOTGUN:\n\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_SPAS12_LEFT;\n\t\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\t\tm_sQueueSample.m_nCounter = iSound++;\n\t\t\t\tnarrowSoundRange = true;\n\t\t\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_SPAS12_LEFT);\n\t\t\t\tm_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 32);\n\t\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 3;\n\t\t\t\tm_sQueueSample.m_fSpeedMultiplier = 0.0f;\n\t\t\t\tm_sQueueSample.m_fSoundIntensity = 120.0f;\n\t\t\t\tmaxDist = SQR(120);\n\t\t\t\tm_sQueueSample.m_nLoopCount = 1;\n\t\t\t\tm_sQueueSample.m_nLoopStart = 0;\n\t\t\t\tm_sQueueSample.m_nLoopEnd = -1;\n\t\t\t\temittingVol = m_anRandomTable[2] % 10 + 100;\n\t\t\t\tm_sQueueSample.m_nEmittingVolume = emittingVol;\n\t\t\t\tm_sQueueSample.m_bIs2D = false;\n\t\t\t\tm_sQueueSample.m_bReleasingSoundFlag = true;\n\t\t\t\tm_sQueueSample.m_bRequireReflection = true;\n\t\t\t\tstereo = true;\n\t\t\t\tbreak;\n\t\t\tcase WEAPONTYPE_TEC9:\n\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_TEC_LEFT;\n\t\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\t\tm_sQueueSample.m_nCounter = iSound++;\n\t\t\t\tnarrowSoundRange = true;\n\t\t\t\tm_sQueueSample.m_nFrequency = RandomDisplacement(500) + 17000;\n\t\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 3;\n\t\t\t\tm_sQueueSample.m_fSpeedMultiplier = 0.0f;\n\t\t\t\tm_sQueueSample.m_fSoundIntensity = 120.0f;\n\t\t\t\tmaxDist = SQR(120);\n\t\t\t\tm_sQueueSample.m_nLoopCount = 1;\n\t\t\t\tm_sQueueSample.m_nLoopStart = 0;\n\t\t\t\temittingVol = m_anRandomTable[3] % 15 + 70;\n\t\t\t\tm_sQueueSample.m_nLoopEnd = -1;\n\t\t\t\tm_sQueueSample.m_nEmittingVolume = emittingVol;\n\t\t\t\tm_sQueueSample.m_bIs2D = false;\n\t\t\t\tm_sQueueSample.m_bReleasingSoundFlag = true;\n\t\t\t\tstereo = true;\n\t\t\t\tbreak;\n\t\t\tcase WEAPONTYPE_UZI:\n\t\t\tcase WEAPONTYPE_MINIGUN:\n\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_UZI_LEFT;\n\t\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\t\tm_sQueueSample.m_nCounter = iSound++;\n\t\t\t\tnarrowSoundRange = true;\n\t\t\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_UZI_LEFT);\n\t\t\t\tm_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 32);\n\t\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 3;\n\t\t\t\tm_sQueueSample.m_fSpeedMultiplier = 0.0f;\n\t\t\t\tm_sQueueSample.m_fSoundIntensity = 120.0f;\n\t\t\t\tmaxDist = SQR(120);\n\t\t\t\tm_sQueueSample.m_nLoopCount = 1;\n\t\t\t\tm_sQueueSample.m_nLoopStart = 0;\n\t\t\t\temittingVol = m_anRandomTable[3] % 15 + 70;\n\t\t\t\tm_sQueueSample.m_nLoopEnd = -1;\n\t\t\t\tm_sQueueSample.m_nEmittingVolume = emittingVol;\n\t\t\t\tm_sQueueSample.m_bIs2D = false;\n\t\t\t\tm_sQueueSample.m_bReleasingSoundFlag = true;\n\t\t\t\tstereo = true;\n\t\t\t\tbreak;\n\t\t\tcase WEAPONTYPE_SILENCED_INGRAM:\n\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_TEC_LEFT;\n\t\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\t\tm_sQueueSample.m_nCounter = iSound++;\n\t\t\t\tnarrowSoundRange = true;\n\t\t\t\tm_sQueueSample.m_nFrequency = RandomDisplacement(1000) + 34000;\n\t\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 3;\n\t\t\t\tm_sQueueSample.m_fSpeedMultiplier = 0.0f;\n\t\t\t\tm_sQueueSample.m_fSoundIntensity = 120.0f;\n\t\t\t\tmaxDist = SQR(120);\n\t\t\t\tm_sQueueSample.m_nLoopCount = 1;\n\t\t\t\tm_sQueueSample.m_nLoopStart = 0;\n\t\t\t\temittingVol = m_anRandomTable[3] % 15 + 70;\n\t\t\t\tm_sQueueSample.m_nLoopEnd = -1;\n\t\t\t\tm_sQueueSample.m_nEmittingVolume = emittingVol;\n\t\t\t\tm_sQueueSample.m_bIs2D = false;\n\t\t\t\tm_sQueueSample.m_bReleasingSoundFlag = true;\n\t\t\t\tstereo = true;\n\t\t\t\tbreak;\n\t\t\tcase WEAPONTYPE_MP5:\n\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_MP5_LEFT;\n\t\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\t\tm_sQueueSample.m_nCounter = iSound++;\n\t\t\t\tnarrowSoundRange = true;\n\t\t\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_MP5_LEFT);\n\t\t\t\tm_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 32);\n\t\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 3;\n\t\t\t\tm_sQueueSample.m_fSpeedMultiplier = 0.0f;\n\t\t\t\tm_sQueueSample.m_fSoundIntensity = 120.0f;\n\t\t\t\tmaxDist = SQR(120);\n\t\t\t\tm_sQueueSample.m_nLoopCount = 1;\n\t\t\t\tm_sQueueSample.m_nLoopStart = 0;\n\t\t\t\temittingVol = m_anRandomTable[3] % 15 + 70;\n\t\t\t\tm_sQueueSample.m_nLoopEnd = -1;\n\t\t\t\tm_sQueueSample.m_nEmittingVolume = emittingVol;\n\t\t\t\tm_sQueueSample.m_bIs2D = false;\n\t\t\t\tm_sQueueSample.m_bReleasingSoundFlag = true;\n\t\t\t\tstereo = true;\n\t\t\t\tbreak;\n\t\t\tcase WEAPONTYPE_M4:\n\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_RUGER_LEFT;\n\t\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\t\tm_sQueueSample.m_nCounter = iSound++;\n\t\t\t\tnarrowSoundRange = true;\n\t\t\t\tm_sQueueSample.m_nFrequency = RandomDisplacement(1000) + 43150;\n\t\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 3;\n\t\t\t\tm_sQueueSample.m_fSpeedMultiplier = 0.0f;\n\t\t\t\tm_sQueueSample.m_fSoundIntensity = 120.0f;\n\t\t\t\tmaxDist = SQR(120);\n\t\t\t\tm_sQueueSample.m_nLoopCount = 1;\n\t\t\t\tm_sQueueSample.m_nLoopStart = 0;\n\t\t\t\temittingVol = m_anRandomTable[3] % 15 + 90;\n\t\t\t\tm_sQueueSample.m_nLoopEnd = -1;\n\t\t\t\tm_sQueueSample.m_nEmittingVolume = emittingVol;\n\t\t\t\tm_sQueueSample.m_bIs2D = false;\n\t\t\t\tm_sQueueSample.m_bReleasingSoundFlag = true;\n\t\t\t\tstereo = true;\n\t\t\t\tbreak;\n\t\t\tcase WEAPONTYPE_RUGER:\n\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_RUGER_LEFT;\n\t\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\t\tm_sQueueSample.m_nCounter = iSound++;\n\t\t\t\tnarrowSoundRange = true;\n\t\t\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_RUGER_LEFT);\n\t\t\t\tm_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 32);\n\t\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 3;\n\t\t\t\tm_sQueueSample.m_fSpeedMultiplier = 0.0f;\n\t\t\t\tm_sQueueSample.m_fSoundIntensity = 120.0f;\n\t\t\t\tmaxDist = SQR(120);\n\t\t\t\tm_sQueueSample.m_nLoopCount = 1;\n\t\t\t\tm_sQueueSample.m_nLoopStart = 0;\n\t\t\t\temittingVol = m_anRandomTable[3] % 15 + 90;\n\t\t\t\tm_sQueueSample.m_nLoopEnd = -1;\n\t\t\t\tm_sQueueSample.m_nEmittingVolume = emittingVol;\n\t\t\t\tm_sQueueSample.m_bIs2D = false;\n\t\t\t\tm_sQueueSample.m_bReleasingSoundFlag = true;\n\t\t\t\tstereo = true;\n\t\t\t\tbreak;\n\t\t\tcase WEAPONTYPE_SNIPERRIFLE:\n\t\t\tcase WEAPONTYPE_LASERSCOPE:\n\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_SNIPER_LEFT;\n\t\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\t\tm_sQueueSample.m_nCounter = iSound++;\n\t\t\t\tnarrowSoundRange = true;\n\t\t\t\tif (weapon->m_eWeaponType == WEAPONTYPE_SNIPERRIFLE)\n\t\t\t\t\tm_sQueueSample.m_nFrequency = 25472;\n\t\t\t\telse\n\t\t\t\t\tm_sQueueSample.m_nFrequency = 20182;\n\t\t\t\tm_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 32);\n\t\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 3;\n\t\t\t\tm_sQueueSample.m_fSpeedMultiplier = 0.0f;\n\t\t\t\tm_sQueueSample.m_fSoundIntensity = 120.0f;\n\t\t\t\tmaxDist = SQR(120);\n\t\t\t\tm_sQueueSample.m_nLoopCount = 1;\n\t\t\t\tm_sQueueSample.m_nLoopStart = 0;\n\t\t\t\tm_sQueueSample.m_nLoopEnd = -1;\n\t\t\t\temittingVol = m_anRandomTable[4] % 10 + 110;\n\t\t\t\tm_sQueueSample.m_nEmittingVolume = emittingVol;\n\t\t\t\tm_sQueueSample.m_bIs2D = false;\n\t\t\t\tm_sQueueSample.m_bReleasingSoundFlag = true;\n\t\t\t\tm_sQueueSample.m_bRequireReflection = true;\n\t\t\t\tstereo = true;\n\t\t\t\tbreak;\n\t\t\tcase WEAPONTYPE_FLAMETHROWER:\n\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_FLAMETHROWER_LEFT;\n\t\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\t\tm_sQueueSample.m_nCounter = 9;\n\t\t\t\temittingVol = 90;\n\t\t\t\tm_sQueueSample.m_nFrequency = (10 * m_sQueueSample.m_nEntityIndex & 2047) + SampleManager.GetSampleBaseFrequency(SFX_FLAMETHROWER_LEFT);\n\t\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 3;\n\t\t\t\tm_sQueueSample.m_fSpeedMultiplier = 4.0f;\n\t\t\t\tm_sQueueSample.m_fSoundIntensity = 60.0f;\n\t\t\t\tmaxDist = SQR(60);\n\t\t\t\tm_sQueueSample.m_nLoopCount = 0;\n\t\t\t\tm_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex);\n\t\t\t\tm_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex);\n\t\t\t\tm_sQueueSample.m_nEmittingVolume = 90;\n\t\t\t\tm_sQueueSample.m_bIs2D = false;\n\t\t\t\tm_sQueueSample.m_bReleasingSoundFlag = false;\n\t\t\t\tm_sQueueSample.m_nReleasingVolumeDivider = 6;\n\t\t\t\tstereo = true;\n\t\t\t\tbreak;\n\t\t\tcase WEAPONTYPE_M60:\n\t\t\tcase WEAPONTYPE_HELICANNON:\n\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_M60_LEFT;\n\t\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\t\tm_sQueueSample.m_nCounter = iSound++;\n\t\t\t\tnarrowSoundRange = true;\n\t\t\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_M60_LEFT);\n\t\t\t\tm_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 32);\n\t\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 3;\n\t\t\t\tm_sQueueSample.m_fSpeedMultiplier = 0.0f;\n\t\t\t\tm_sQueueSample.m_fSoundIntensity = 120.0f;\n\t\t\t\tmaxDist = SQR(120);\n\t\t\t\tm_sQueueSample.m_nLoopCount = 1;\n\t\t\t\tm_sQueueSample.m_nLoopStart = 0;\n\t\t\t\tm_sQueueSample.m_nLoopEnd = -1;\n\t\t\t\temittingVol = 127;\n\t\t\t\tm_sQueueSample.m_nEmittingVolume = 127;\n\t\t\t\tm_sQueueSample.m_bIs2D = false;\n\t\t\t\tm_sQueueSample.m_bReleasingSoundFlag = true;\n\t\t\t\tstereo = true;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase SOUND_WEAPON_RELOAD:\n\t\t\tswitch ((int32)m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_afVolume[i]) {\n\t\t\tcase WEAPONTYPE_ROCKET:\n\t\t\tcase WEAPONTYPE_ROCKETLAUNCHER:\n\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_ROCKET_RELOAD;\n\t\t\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_ROCKET_RELOAD);\n\t\t\t\tbreak;\n\t\t\tcase WEAPONTYPE_COLT45:\n\t\t\tcase WEAPONTYPE_PYTHON:\n\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_PISTOL_RELOAD;\n\t\t\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_PISTOL_RELOAD) + RandomDisplacement(300);\n\t\t\t\tbreak;\n\t\t\tcase WEAPONTYPE_SHOTGUN:\n\t\t\tcase WEAPONTYPE_SPAS12_SHOTGUN:\n\t\t\tcase WEAPONTYPE_STUBBY_SHOTGUN:\n\t\t\tcase WEAPONTYPE_RUGER:\n\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_AK47_RELOAD;\n\t\t\t\tm_sQueueSample.m_nFrequency = 30290;\n\t\t\t\tbreak;\n\t\t\tcase WEAPONTYPE_TEC9:\n\t\t\tcase WEAPONTYPE_UZI:\n\t\t\tcase WEAPONTYPE_SILENCED_INGRAM:\n\t\t\tcase WEAPONTYPE_MP5:\n\t\t\tcase WEAPONTYPE_M4:\n\t\t\tcase WEAPONTYPE_M60:\n\t\t\tcase WEAPONTYPE_HELICANNON:\n\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_AK47_RELOAD;\n\t\t\t\tm_sQueueSample.m_nFrequency = 39243;\n\t\t\t\tbreak;\n\t\t\tcase WEAPONTYPE_SNIPERRIFLE:\n\t\t\tcase WEAPONTYPE_LASERSCOPE:\n\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_RIFLE_RELOAD;\n\t\t\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_RIFLE_RELOAD);\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\temittingVol = 75;\n\t\t\tm_sQueueSample.m_nCounter = iSound++;\n\t\t\tnarrowSoundRange = true;\n\t\t\tm_sQueueSample.m_nFrequency += RandomDisplacement(300);\n\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 5;\n\t\t\tm_sQueueSample.m_fSpeedMultiplier = 0.0f;\n\t\t\tm_sQueueSample.m_fSoundIntensity = 30.0f;\n\t\t\tmaxDist = SQR(30);\n\t\t\tm_sQueueSample.m_nLoopCount = 1;\n\t\t\tm_sQueueSample.m_nLoopStart = 0;\n\t\t\tm_sQueueSample.m_nLoopEnd = -1;\n\t\t\tm_sQueueSample.m_nEmittingVolume = 75;\n\t\t\tm_sQueueSample.m_bIs2D = false;\n\t\t\tm_sQueueSample.m_bReleasingSoundFlag = true;\n\t\t\tm_sQueueSample.m_bRequireReflection = true;\n\t\t\tbreak;\n\t\tcase SOUND_WEAPON_AK47_BULLET_ECHO:\n\t\t{\n\t\t\tuint32 weaponType = m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_afVolume[i];\n\t\t\tswitch (weaponType) {\n\t\t\tcase WEAPONTYPE_SPAS12_SHOTGUN:\n\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_SPAS12_TAIL_LEFT;\n\t\t\t\tbreak;\n\t\t\tcase WEAPONTYPE_TEC9:\n\t\t\tcase WEAPONTYPE_SILENCED_INGRAM:\n\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_TEC_TAIL;\n\t\t\t\tbreak;\n\t\t\tcase WEAPONTYPE_UZI:\n\t\t\tcase WEAPONTYPE_MP5:\n\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_UZI_END_LEFT;\n\t\t\t\tbreak;\n\t\t\tcase WEAPONTYPE_M4:\n\t\t\tcase WEAPONTYPE_RUGER:\n\t\t\tcase WEAPONTYPE_SNIPERRIFLE:\n\t\t\tcase WEAPONTYPE_LASERSCOPE:\n\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_RUGER_TAIL;\n\t\t\t\tbreak;\n\t\t\tcase WEAPONTYPE_M60:\n\t\t\tcase WEAPONTYPE_HELICANNON:\n\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_M60_TAIL_LEFT;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\tm_sQueueSample.m_nCounter = iSound++;\n\t\t\tnarrowSoundRange = true;\n\t\t\tswitch (weaponType) {\n\t\t\tcase WEAPONTYPE_TEC9:\n\t\t\t\tm_sQueueSample.m_nFrequency = 13000;\n\t\t\t\tbreak;\n\t\t\tcase WEAPONTYPE_SILENCED_INGRAM:\n\t\t\t\tm_sQueueSample.m_nFrequency = 26000;\n\t\t\t\tbreak;\n\t\t\tcase WEAPONTYPE_M4:\n\t\t\t\tm_sQueueSample.m_nFrequency = 15600;\n\t\t\t\tbreak;\n\t\t\tcase WEAPONTYPE_SNIPERRIFLE:\n\t\t\t\tm_sQueueSample.m_nFrequency = 9959;\n\t\t\t\tbreak;\n\t\t\tcase WEAPONTYPE_LASERSCOPE:\n\t\t\t\tm_sQueueSample.m_nFrequency = 7904;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tm_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 16);\n\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 3;\n\t\t\tm_sQueueSample.m_fSpeedMultiplier = 0.0f;\n\t\t\tm_sQueueSample.m_fSoundIntensity = 120.0f;\n\t\t\tmaxDist = SQR(120);\n\t\t\tm_sQueueSample.m_nLoopCount = 1;\n\t\t\tm_sQueueSample.m_nLoopStart = 0;\n\t\t\tm_sQueueSample.m_nLoopEnd = -1;\n\t\t\temittingVol = m_anRandomTable[4] % 10 + 80;\n\t\t\tm_sQueueSample.m_nEmittingVolume = emittingVol;\n\t\t\tm_sQueueSample.m_bIs2D = false;\n\t\t\tm_sQueueSample.m_bReleasingSoundFlag = true;\n\t\t\tm_sQueueSample.m_bRequireReflection = true;\n\t\t\tbreak;\n\t\t}\n\t\tcase SOUND_WEAPON_FLAMETHROWER_FIRE:\n\t\t\tm_sQueueSample.m_nSampleIndex = SFX_FLAMETHROWER_START_LEFT;\n\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\tm_sQueueSample.m_nCounter = iSound++;\n\t\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_FLAMETHROWER_START_LEFT);\n\t\t\tm_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 16);\n\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 3;\n\t\t\tm_sQueueSample.m_fSpeedMultiplier = 4.0f;\n\t\t\tm_sQueueSample.m_fSoundIntensity = 60.0f;\n\t\t\tmaxDist = SQR(60);\n\t\t\tm_sQueueSample.m_nLoopCount = 1;\n\t\t\tm_sQueueSample.m_nLoopStart = 0;\n\t\t\tm_sQueueSample.m_nLoopEnd = -1;\n\t\t\temittingVol = 70;\n\t\t\tm_sQueueSample.m_nEmittingVolume = 70;\n\t\t\tm_sQueueSample.m_bIs2D = false;\n\t\t\tm_sQueueSample.m_bReleasingSoundFlag = true;\n\t\t\tbreak;\n\t\tcase SOUND_WEAPON_HIT_PED:\n\t\t\tm_sQueueSample.m_nSampleIndex = SFX_BULLET_PED;\n\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\tm_sQueueSample.m_nCounter = iSound++;\n\t\t\tnarrowSoundRange = true;\n\t\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_BULLET_PED);\n\t\t\tm_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 8);\n\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 7;\n\t\t\tm_sQueueSample.m_fSpeedMultiplier = 0.0f;\n\t\t\tm_sQueueSample.m_fSoundIntensity = 30.0f;\n\t\t\tmaxDist = SQR(30);\n\t\t\tm_sQueueSample.m_nLoopCount = 1;\n\t\t\tm_sQueueSample.m_nLoopStart = 0;\n\t\t\temittingVol = m_anRandomTable[0] % 20 + 90;\n\t\t\tm_sQueueSample.m_nLoopEnd = -1;\n\t\t\tm_sQueueSample.m_nEmittingVolume = emittingVol;\n\t\t\tm_sQueueSample.m_bIs2D = false;\n\t\t\tm_sQueueSample.m_bReleasingSoundFlag = true;\n\t\t\tbreak;\n\t\tcase SOUND_SPLASH:\n\t\t\tif (m_FrameCounter <= iSplashFrame)\n\t\t\t\tcontinue;\n\t\t\tiSplashFrame = m_FrameCounter + 6;\n\t\t\tm_sQueueSample.m_nSampleIndex = SFX_SPLASH_1;\n\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\tm_sQueueSample.m_nCounter = iSound++;\n\t\t\tnarrowSoundRange = true;\n\t\t\tm_sQueueSample.m_nFrequency = RandomDisplacement(1400) + 20000;\n\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 1;\n\t\t\tm_sQueueSample.m_fSpeedMultiplier = 0.0f;\n\t\t\tm_sQueueSample.m_fSoundIntensity = 40.0f;\n\t\t\tmaxDist = SQR(40);\n\t\t\tm_sQueueSample.m_nLoopCount = 1;\n\t\t\tm_sQueueSample.m_nLoopStart = 0;\n\t\t\temittingVol = m_anRandomTable[2] % 30 + 70;\n\t\t\tm_sQueueSample.m_nLoopEnd = -1;\n\t\t\tm_sQueueSample.m_nEmittingVolume = emittingVol;\n\t\t\tm_sQueueSample.m_bIs2D = false;\n\t\t\tm_sQueueSample.m_bReleasingSoundFlag = true;\n\t\t\tm_sQueueSample.m_bRequireReflection = true;\n\t\t\tbreak;\n\t\tcase SOUND_MELEE_ATTACK_START:\n\t\t{\n\t\t\tuint32 weaponType = ((uint32)m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_afVolume[i]) >> 8;\n\t\t\tswitch (weaponType)\n\t\t\t{\n\t\t\tcase WEAPONTYPE_SCREWDRIVER:\n\t\t\tcase WEAPONTYPE_KNIFE:\n\t\t\tcase WEAPONTYPE_CLEAVER:\n\t\t\tcase WEAPONTYPE_MACHETE:\n\t\t\tcase WEAPONTYPE_KATANA:\n\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_KNIFE_SWING;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_GOLF_CLUB_SWING;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\tm_sQueueSample.m_nCounter = iSound++;\n\t\t\tnarrowSoundRange = true;\n\t\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex);\n\t\t\tm_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 16);\n\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 3;\n\t\t\tm_sQueueSample.m_fSpeedMultiplier = 0.0f;\n\t\t\tm_sQueueSample.m_fSoundIntensity = 30.0f;\n\t\t\tif (weaponType == WEAPONTYPE_UNARMED || weaponType == WEAPONTYPE_BRASSKNUCKLE)\n\t\t\t\temittingVol = m_anRandomTable[1] % 10 + 35;\n\t\t\telse\n\t\t\t\temittingVol = m_anRandomTable[2] % 20 + 70;\n\t\t\tmaxDist = SQR(30);\n\t\t\tm_sQueueSample.m_nLoopCount = 1;\n\t\t\tm_sQueueSample.m_nLoopStart = 0;\n\t\t\tm_sQueueSample.m_nLoopEnd = -1;\n\t\t\tm_sQueueSample.m_nEmittingVolume = emittingVol;\n\t\t\tm_sQueueSample.m_bIs2D = false;\n\t\t\tm_sQueueSample.m_bReleasingSoundFlag = true;\n\t\t\tm_sQueueSample.m_bRequireReflection = true;\n\t\t\tbreak;\n\t\t}\n\t\tcase SOUND_SKATING:\n\t\t{\n\t\t\tuint32 soundParams = m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_afVolume[i];\n\t\t\tuint8 param1 = soundParams & 0xFF;\n\t\t\tuint32 param2 = soundParams >> 8;\n\t\t\tm_sQueueSample.m_nSampleIndex = (m_anRandomTable[3] & 1) + SFX_SKATE_1;\n\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\tm_sQueueSample.m_nCounter = iSound;\n\t\t\tstereo = true;\n\t\t\t++iSound;\n\t\t\tm_sQueueSample.m_nFrequency = m_anRandomTable[1] % 1000 + 17000;\n\t\t\tif (param2 == 0)\n\t\t\t\tm_sQueueSample.m_nFrequency = (3 * m_sQueueSample.m_nFrequency) / 4;\n\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 6;\n\t\t\tm_sQueueSample.m_fSpeedMultiplier = 3.0f;\n\t\t\tm_sQueueSample.m_fSoundIntensity = 20.0f;\n\t\t\tmaxDist = SQR(20);\n\t\t\tm_sQueueSample.m_nLoopCount = 1;\n\t\t\tm_sQueueSample.m_nLoopStart = 0;\n\t\t\tm_sQueueSample.m_nLoopEnd = -1;\n\t\t\temittingVol = (m_anRandomTable[2] % 20 + 70) * param1 / 127;\n\t\t\tm_sQueueSample.m_nEmittingVolume = emittingVol;\n\t\t\tm_sQueueSample.m_bIs2D = false;\n\t\t\tm_sQueueSample.m_bReleasingSoundFlag = true;\n\t\t\tm_sQueueSample.m_bRequireReflection = true;\n\t\t\tbreak;\n\t\t}\n\t\tcase SOUND_WEAPON_MINIGUN_ATTACK:\n\t\t\tm_sQueueSample.m_nSampleIndex = SFX_MINIGUN_FIRE_LEFT;\n\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\tm_sQueueSample.m_nCounter = 68;\n\t\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_MINIGUN_FIRE_LEFT);\n\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 2;\n\t\t\tm_sQueueSample.m_fSpeedMultiplier = 3.0f;\n\t\t\tm_sQueueSample.m_fSoundIntensity = 150.0f;\n\t\t\temittingVol = 127;\n\t\t\tmaxDist = SQR(150);\n\t\t\tm_sQueueSample.m_nLoopCount = 0;\n\t\t\tm_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(SFX_MINIGUN_FIRE_LEFT);\n\t\t\tm_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(SFX_MINIGUN_FIRE_LEFT);\n\t\t\tm_sQueueSample.m_nEmittingVolume = 127;\n\t\t\tm_sQueueSample.m_bIs2D = false;\n\t\t\tm_sQueueSample.m_bReleasingSoundFlag = false;\n\t\t\tm_sQueueSample.m_nReleasingVolumeDivider = 3;\n\t\t\tbreak;\n\t\tcase SOUND_WEAPON_MINIGUN_2:\n\t\t\tm_sQueueSample.m_nSampleIndex = SFX_MINIGUN_FIRE_RIGHT;\n\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\tm_sQueueSample.m_nCounter = 69;\n\t\t\tm_sQueueSample.m_nFrequency = 18569;\n\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 2;\n\t\t\tm_sQueueSample.m_fSpeedMultiplier = 3.0f;\n\t\t\tm_sQueueSample.m_fSoundIntensity = 150.0f;\n\t\t\temittingVol = 127.0f * m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_afVolume[i];\n\t\t\tmaxDist = SQR(150);\n\t\t\tm_sQueueSample.m_nLoopCount = 0;\n\t\t\tm_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(SFX_MINIGUN_FIRE_RIGHT);\n\t\t\tm_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(SFX_MINIGUN_FIRE_RIGHT);\n\t\t\tm_sQueueSample.m_nEmittingVolume = emittingVol;\n\t\t\tm_sQueueSample.m_bIs2D = false;\n\t\t\tm_sQueueSample.m_bReleasingSoundFlag = false;\n\t\t\tm_sQueueSample.m_nReleasingVolumeDivider = 3;\n\t\t\tbreak;\n\t\tcase SOUND_WEAPON_MINIGUN_3:\n\t\t\tm_sQueueSample.m_nSampleIndex = SFX_MINIGUN_STOP;\n\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\tm_sQueueSample.m_nCounter = 69;\n\t\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_MINIGUN_STOP);\n\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 4;\n\t\t\tm_sQueueSample.m_fSpeedMultiplier = 0.0f;\n\t\t\tm_sQueueSample.m_fSoundIntensity = 150.0f;\n\t\t\tmaxDist = SQR(150);\n\t\t\tm_sQueueSample.m_nLoopCount = 1;\n\t\t\tm_sQueueSample.m_nLoopStart = 0;\n\t\t\tm_sQueueSample.m_nLoopEnd = -1;\n\t\t\temittingVol = 127;\n\t\t\tm_sQueueSample.m_nEmittingVolume = 127;\n\t\t\tm_sQueueSample.m_bIs2D = false;\n\t\t\tm_sQueueSample.m_bReleasingSoundFlag = true;\n\t\t\tm_sQueueSample.m_bRequireReflection = true;\n\t\t\tbreak;\n\t\tcase SOUND_SHIRT_WIND_FLAP:\n\t\t\tif (params.m_pPed->IsPlayer() && params.m_pPed->m_pMyVehicle) {\n\t\t\t\tif (m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_afVolume[i] > 0.0f) {\n\t\t\t\t\tif (m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_afVolume[i] > 1.0f)\n\t\t\t\t\t\tm_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_afVolume[i] = 1.0f;\n\n\t\t\t\t\temittingVol = 90.0f * m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_afVolume[i];\n\n\t\t\t\t\tswitch (params.m_pPed->m_pMyVehicle->GetModelIndex())\n\t\t\t\t\t{\n\t\t\t\t\tcase MI_ANGEL:\n\t\t\t\t\tcase MI_FREEWAY:\n\t\t\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_CAR_WIND_17;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase MI_PIZZABOY:\n\t\t\t\t\tcase MI_FAGGIO:\n\t\t\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_CAR_WIND_18;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase MI_PCJ600:\n\t\t\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_CAR_WIND_20;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase MI_SANCHEZ:\n\t\t\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_CAR_WIND_19;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t};\n\n\t\t\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\t\t\tm_sQueueSample.m_nCounter = 71;\n\t\t\t\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex);\n\t\t\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 3;\n\t\t\t\t\tm_sQueueSample.m_fSpeedMultiplier = 3.0f;\n\t\t\t\t\tm_sQueueSample.m_fSoundIntensity = 15.0f;\n\t\t\t\t\tmaxDist = SQR(15);\n\t\t\t\t\tm_sQueueSample.m_nLoopCount = 0;\n\t\t\t\t\tm_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex);\n\t\t\t\t\tm_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex);\n\t\t\t\t\tm_sQueueSample.m_nEmittingVolume = emittingVol;\n\t\t\t\t\tm_sQueueSample.m_bIs2D = false;\n\t\t\t\t\tm_sQueueSample.m_bReleasingSoundFlag = false;\n\t\t\t\t\tm_sQueueSample.m_nReleasingVolumeDivider = 3;\n\t\t\t\t}\n\t\t\t}\n\t\t\tcontinue;\n\t\tdefault:\n\t\t\tSetupPedComments(params, sound);\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (narrowSoundRange && iSound > 60)\n\t\t\tiSound = 21;\n\t\tif (params.m_fDistance < maxDist) {\n\t\t\tCalculateDistance(params.m_bDistanceCalculated, params.m_fDistance);\n\t\t\tm_sQueueSample.m_nVolume = ComputeVolume(emittingVol, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance);\n\t\t\tif (m_sQueueSample.m_nVolume != 0) {\n\t\t\t\tif (stereo) {\n\t\t\t\t\tif (m_sQueueSample.m_fDistance < 0.2f * m_sQueueSample.m_fSoundIntensity) {\n\t\t\t\t\t\tm_sQueueSample.m_bIs2D = true;\n\t\t\t\t\t\tm_sQueueSample.m_nOffset = 0;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tstereo = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tm_sQueueSample.m_bReverbFlag = true;\n\t\t\t\tAddSampleToRequestedQueue();\n\t\t\t\tif (stereo) {\n\t\t\t\t\tm_sQueueSample.m_nOffset = 127;\n\t\t\t\t\t++m_sQueueSample.m_nSampleIndex;\n\t\t\t\t\tif (m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_awAudioEvent[i] != SOUND_WEAPON_SHOT_FIRED ||\n\t\t\t\t\t    weapon->m_eWeaponType != WEAPONTYPE_FLAMETHROWER) {\n\t\t\t\t\t\tm_sQueueSample.m_nCounter = iSound++;\n\t\t\t\t\t\tif (iSound > 60)\n\t\t\t\t\t\t\tiSound = 21;\n\t\t\t\t\t} else {\n\t\t\t\t\t\t++m_sQueueSample.m_nCounter;\n\t\t\t\t\t}\n\t\t\t\t\tAddSampleToRequestedQueue();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\ncAudioManager::SetPedTalkingStatus(CPed *ped, uint8 status)\n{\n\tif (ped != nil)\n\t\tped->m_canTalk = status;\n}\n\nvoid\ncAudioManager::SetPlayersMood(uint8 mood, uint32 time)\n{\n\tif (!m_bIsInitialised) return;\n\n\tif (mood < MAX_PLAYER_MOODS) {\n\t\tm_nPlayerMood = mood;\n\t\tm_nPlayerMoodTimer = CTimer::GetTimeInMilliseconds() + time;\n\t}\n\n}\n\nvoid\ncAudioManager::SetupPedComments(cPedParams &params, uint16 sound)\n{\n\tCPed *ped = params.m_pPed;\n\tuint8 emittingVol;\n\tfloat soundIntensity;\n\ttPedComment pedComment;\n\n\tif(ped != nil) {\n\t\tif(!ped->m_canTalk) return;\n\t\tm_bGenericSfx = false;\n\t\tpedComment.m_nSampleIndex = GetPedCommentSfx(ped, sound);\n\t\tif(pedComment.m_nSampleIndex == NO_SAMPLE) return;\n\t\tsoundIntensity = 40.0f;\n\t} else {\n\t\tm_bGenericSfx = true;\n\t\tswitch(sound) {\n\t\tcase SOUND_PED_HELI_PLAYER_FOUND:\n\t\t\tsoundIntensity = 400.0f;\n\t\t\tpedComment.m_nSampleIndex = GetRandomNumberInRange(m_sQueueSample.m_nEntityIndex % 4, SFX_POLICE_HELI_1, SFX_POLICE_HELI_20);\n\t\t\tbreak;\n\t\tcase SOUND_PED_VCPA_PLAYER_FOUND:\n\t\t\tsoundIntensity = 400.0f;\n#ifdef FIX_BUGS\n\t\t\tpedComment.m_nSampleIndex = m_anRandomTable[m_sQueueSample.m_nEntityIndex % 4] % 23 + SFX_POLICE_BOAT_1;\n#else\n\t\t\tpedComment.m_nSampleIndex = m_anRandomTable[m_sQueueSample.m_nEntityIndex % 4] % 29 + SFX_POLICE_BOAT_1;\n#endif\n\t\t\tbreak;\n\t\tcase SOUND_INJURED_PED_MALE_OUCH:\n\t\t\tsoundIntensity = 40.0f;\n\t\t\tpedComment.m_nSampleIndex = GetRandomNumberInRange(m_sQueueSample.m_nEntityIndex % 4, SFX_GENERIC_MALE_GRUNT_1, SFX_GENERIC_MALE_GRUNT_41);\n\t\t\tbreak;\n\t\tcase SOUND_INJURED_PED_FEMALE:\n\t\t\tsoundIntensity = 40.0f;\n\t\t\tpedComment.m_nSampleIndex = GetRandomNumberInRange(m_sQueueSample.m_nEntityIndex % 4, SFX_GENERIC_FEMALE_GRUNT_1, SFX_GENERIC_FEMALE_GRUNT_33);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\treturn;\n\t\t}\n\t}\n\n\tif(params.m_fDistance < SQR(soundIntensity)) {\n\t\tCalculateDistance(params.m_bDistanceCalculated, params.m_fDistance);\n\t\tif(CWorld::GetIsLineOfSightClear(TheCamera.GetPosition(), m_sQueueSample.m_vecPos, true, false, false, false, false, false))\n\t\t\temittingVol = MAX_VOLUME;\n\t\telse\n\t\t\temittingVol = 31;\n\t\tm_sQueueSample.m_nVolume = ComputeVolume(emittingVol, soundIntensity, m_sQueueSample.m_fDistance);\n\t\tpedComment.m_nProcess = 10;\n\t\tif(m_sQueueSample.m_nVolume != 0) {\n\t\t\tpedComment.m_nEntityIndex = m_sQueueSample.m_nEntityIndex;\n\t\t\tpedComment.m_vecPos = m_sQueueSample.m_vecPos;\n\t\t\tpedComment.m_fDistance = m_sQueueSample.m_fDistance;\n\t\t\tpedComment.m_bVolume = m_sQueueSample.m_nVolume;\n\t\t\tm_sPedComments.Add(&pedComment);\n\t\t}\n\t}\n}\n\nuint32\ncAudioManager::GetPedCommentSfx(CPed *ped, int32 sound)\n{\n\tif(ped->m_nPedState != PED_FALL || sound == MI_VICE8 || sound == MI_WFYG1 || sound == MI_WFYG2) {\n\t\tif(ped->m_getUpTimer == UINT32_MAX || ped->m_getUpTimer > CTimer::GetTimeInMilliseconds()) {\n\t\t\tif(sound != SOUND_PED_DAMAGE && sound != SOUND_PED_HIT && sound != SOUND_PED_LAND) return NO_SAMPLE;\n\t\t}\n\t\tif(ped->IsPlayer()) return GetPlayerTalkSfx(ped, sound);\n\t\tswitch(ped->GetModelIndex()) {\n\t\tcase MI_PLAYER: return GetPlayerTalkSfx(ped, sound);\n\t\tcase MI_COP: return GetCopTalkSfx(ped, sound);\n\t\tcase MI_SWAT: return GetSwatTalkSfx(ped, sound);\n\t\tcase MI_FBI: return GetFBITalkSfx(ped, sound);\n\t\tcase MI_ARMY: return GetGenericMaleTalkSfx(ped, sound);\n\t\tcase MI_MEDIC: return GetMedicTalkSfx(ped, sound);\n\t\tcase MI_FIREMAN: return GetFiremanTalkSfx(ped, sound);\n\t\tcase MI_MALE01: return GetDefaultTalkSfx(ped, sound);\n\t\tcase MI_HFYST: return GetHFYSTTalkSfx(ped, sound);\n\t\tcase MI_HFOST: return GetHFOSTTalkSfx(ped, sound);\n\t\tcase MI_HMYST: return GetHMYSTTalkSfx(ped, sound);\n\t\tcase MI_HMOST: return GetHMOSTTalkSfx(ped, sound);\n\t\tcase MI_HFYRI: return GetHFYRITalkSfx(ped, sound);\n\t\tcase MI_HFORI: return GetHFORITalkSfx(ped, sound);\n\t\tcase MI_HMYRI: return GetHMYRITalkSfx(ped, sound);\n\t\tcase MI_HMORI: return GetHMORITalkSfx(ped, sound);\n\t\tcase MI_HFYBE: return GetHFYBETalkSfx(ped, sound);\n\t\tcase MI_HFOBE: return GetHFOBETalkSfx(ped, sound);\n\t\tcase MI_HMYBE: return GetHMYBETalkSfx(ped, sound);\n\t\tcase MI_HMOBE: return GetHMOBETalkSfx(ped, sound);\n\t\tcase MI_HFYBU: return GetHFYBUTalkSfx(ped, sound);\n\t\tcase MI_HFYMD: return GetHFYMDTalkSfx(ped, sound);\n\t\tcase MI_HFYCG: return GetHFYCGTalkSfx(ped, sound);\n\t\tcase MI_HFYPR: return GetHFYPRTalkSfx(ped, sound);\n\t\tcase MI_HFOTR: return GetHFOTRTalkSfx(ped, sound);\n\t\tcase MI_HMOTR: return GetHMOTRTalkSfx(ped, sound);\n\t\tcase MI_HMYAP: return GetHMYAPTalkSfx(ped, sound);\n\t\tcase MI_HMOCA: return GetHMOCATalkSfx(ped, sound);\n\t\tcase MI_BMODK: return GetBMODKTalkSfx(ped, sound);\n\t\tcase MI_BMYKR: return GetBMYCRTalkSfx(ped, sound);\n\t\tcase MI_BFYST: return GetBFYSTTalkSfx(ped, sound);\n\t\tcase MI_BFOST: return GetBFOSTTalkSfx(ped, sound);\n\t\tcase MI_BMYST: return GetBMYSTTalkSfx(ped, sound);\n\t\tcase MI_BMOST: return GetBMOSTTalkSfx(ped, sound);\n\t\tcase MI_BFYRI: return GetBFYRITalkSfx(ped, sound);\n\t\tcase MI_BFORI: return GetBFORITalkSfx(ped, sound);\n\t\tcase MI_BMYRI: return GetBMYRITalkSfx(ped, sound);\n\t\tcase MI_BFYBE: return GetBFYBETalkSfx(ped, sound);\n\t\tcase MI_BMYBE: return GetBMYBETalkSfx(ped, sound);\n\t\tcase MI_BFOBE: return GetBFOBETalkSfx(ped, sound);\n\t\tcase MI_BMOBE: return GetBMOBETalkSfx(ped, sound);\n\t\tcase MI_BMYBU: return GetBMYBUTalkSfx(ped, sound);\n\t\tcase MI_BFYPR: return GetBFYPRTalkSfx(ped, sound);\n\t\tcase MI_BFOTR: return GetBFOTRTalkSfx(ped, sound);\n\t\tcase MI_BMOTR: return GetBMOTRTalkSfx(ped, sound);\n\t\tcase MI_BMYPI: return GetBMYPITalkSfx(ped, sound);\n\t\tcase MI_BMYBB: return GetBMYBBTalkSfx(ped, sound);\n\t\tcase MI_WMYCR: return GetWMYCRTalkSfx(ped, sound);\n\t\tcase MI_WFYST: return GetWFYSTTalkSfx(ped, sound);\n\t\tcase MI_WFOST: return GetWFOSTTalkSfx(ped, sound);\n\t\tcase MI_WMYST: return GetWMYSTTalkSfx(ped, sound);\n\t\tcase MI_WMOST: return GetWMOSTTalkSfx(ped, sound);\n\t\tcase MI_WFYRI: return GetWFYRITalkSfx(ped, sound);\n\t\tcase MI_WFORI: return GetWFORITalkSfx(ped, sound);\n\t\tcase MI_WMYRI: return GetWMYRITalkSfx(ped, sound);\n\t\tcase MI_WMORI: return GetWMORITalkSfx(ped, sound);\n\t\tcase MI_WFYBE: return GetWFYBETalkSfx(ped, sound);\n\t\tcase MI_WMYBE: return GetWMYBETalkSfx(ped, sound);\n\t\tcase MI_WFOBE: return GetWFOBETalkSfx(ped, sound);\n\t\tcase MI_WMOBE: return GetWMOBETalkSfx(ped, sound);\n\t\tcase MI_WMYCW: return GetWMYCWTalkSfx(ped, sound);\n\t\tcase MI_WMYGO: return GetWMYGOTalkSfx(ped, sound);\n\t\tcase MI_WFOGO: return GetWFOGOTalkSfx(ped, sound);\n\t\tcase MI_WMOGO: return GetWMOGOTalkSfx(ped, sound);\n\t\tcase MI_WFYLG: return GetWFYLGTalkSfx(ped, sound);\n\t\tcase MI_WMYLG: return GetWMYLGTalkSfx(ped, sound);\n\t\tcase MI_WFYBU: return GetWFYBUTalkSfx(ped, sound);\n\t\tcase MI_WMYBU: return GetWMYBUTalkSfx(ped, sound);\n\t\tcase MI_WMOBU: return GetWMOBUTalkSfx(ped, sound);\n\t\tcase MI_WFYPR: return GetWFYPRTalkSfx(ped, sound);\n\t\tcase MI_WFOTR: return GetWFOTRTalkSfx(ped, sound);\n\t\tcase MI_WMOTR: return GetWMOTRTalkSfx(ped, sound);\n\t\tcase MI_WMYPI: return GetWMYPITalkSfx(ped, sound);\n\t\tcase MI_WMOCA: return GetWMOCATalkSfx(ped, sound);\n\t\tcase MI_WFYJG: return GetWFYJGTalkSfx(ped, sound);\n\t\tcase MI_WMYJG: return GetWMYJGTalkSfx(ped, sound);\n\t\tcase MI_WFYSK: return GetWFYSKTalkSfx(ped, sound);\n\t\tcase MI_WMYSK: return GetWMYSKTalkSfx(ped, sound);\n\t\tcase MI_WFYSH: return GetWFYSHTalkSfx(ped, sound);\n\t\tcase MI_WFOSH: return GetWFOSHTalkSfx(ped, sound);\n\t\tcase MI_JFOTO: return GetJFOTOTalkSfx(ped, sound);\n\t\tcase MI_JMOTO: return GetJMOTOTalkSfx(ped, sound);\n\t\tcase MI_CBA:\n\t\tcase MI_CBB: return GetCBTalkSfx(ped, sound);\n\t\tcase MI_HNA:\n\t\tcase MI_HNB: return GetHNTalkSfx(ped, sound);\n\t\tcase MI_SGA:\n\t\tcase MI_SGB: return GetSGTalkSfx(ped, sound);\n\t\tcase MI_CLA:\n\t\tcase MI_CLB: return GetCLTalkSfx(ped, sound);\n\t\tcase MI_GDA:\n\t\tcase MI_GDB: return GetGDTalkSfx(ped, sound);\n\t\tcase MI_BKA:\n\t\tcase MI_BKB: return GetBKTalkSfx(ped, sound);\n\t\tcase MI_PGA:\n\t\tcase MI_PGB: return GetPGTalkSfx(ped, sound);\n\t\tcase MI_VICE1:\n\t\tcase MI_VICE2:\n\t\tcase MI_VICE3:\n\t\tcase MI_VICE4:\n\t\tcase MI_VICE5:\n\t\tcase MI_VICE6:\n\t\tcase MI_VICE7:\n\t\tcase MI_VICE8: return GetVICETalkSfx(ped, sound, ped->GetModelIndex());\n\t\tcase MI_WFYG1: return GetWFYG1TalkSfx(ped, sound);\n\t\tcase MI_WFYG2: return GetWFYG2TalkSfx(ped, sound);\n\t\tcase MI_SPECIAL01:\n\t\tcase MI_SPECIAL02:\n\t\tcase MI_SPECIAL03:\n\t\tcase MI_SPECIAL04:\n\t\tcase MI_SPECIAL05:\n\t\tcase MI_SPECIAL06:\n\t\tcase MI_SPECIAL07:\n\t\tcase MI_SPECIAL08:\n\t\tcase MI_SPECIAL09:\n\t\tcase MI_SPECIAL10:\n\t\tcase MI_SPECIAL11:\n\t\tcase MI_SPECIAL12:\n\t\tcase MI_SPECIAL13:\n\t\tcase MI_SPECIAL14:\n\t\tcase MI_SPECIAL15:\n\t\tcase MI_SPECIAL16:\n\t\tcase MI_SPECIAL17:\n\t\tcase MI_SPECIAL18:\n\t\tcase MI_SPECIAL19:\n\t\tcase MI_SPECIAL20:\n\t\tcase MI_SPECIAL21: return NO_SAMPLE;\n\t\tdefault: return GetGenericMaleTalkSfx(ped, sound);\n\t\t}\n\t}\n\n\treturn NO_SAMPLE;\n}\n\nvoid\ncAudioManager::GetPhrase(uint32 &phrase, uint32 &prevPhrase, uint32 sample, uint32 maxOffset) const\n{\n\tphrase = sample + m_anRandomTable[m_sQueueSample.m_nEntityIndex & 3] % maxOffset;\n\n\t// check if the same sfx like last time, if yes, then try use next one,\n\t// if exceeded range, then choose first available sample\n\tif (phrase == prevPhrase && ++phrase >= sample + maxOffset)\n\t\tphrase = sample;\n\tprevPhrase = phrase;\n}\n\n#pragma region PED_COMMENTS\n\n#define cooldown_phrase(count)\t\tstatic uint8 cooldown = 0;\\\nif (cooldown != 0) {\\\n\tif (++cooldown == count) cooldown = 0;\\\n\treturn NO_SAMPLE;\\\n}\\\ncooldown = 1;\n\nuint32\ncAudioManager::GetPlayerTalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tif(m_bIsPlayerShutUp) return NO_SAMPLE;\n\tswitch(sound) {\n\tcase SOUND_PED_DEATH: return 9796;\n\tcase SOUND_PED_DAMAGE:\n\tcase SOUND_PED_BULLET_HIT: GetPhrase(sfx, ped->m_lastComment, 9815, 33); break;\n\tcase SOUND_PED_HIT:\n\tcase SOUND_PED_DEFEND: GetPhrase(sfx, ped->m_lastComment, 9883, 42); break;\n\tcase SOUND_PED_LAND: GetPhrase(sfx, ped->m_lastComment, 9848, 35); break;\n\tcase SOUND_PED_BURNING: GetPhrase(sfx, ped->m_lastComment, 9925, 16); break;\n\tcase SOUND_PED_PLAYER_REACTTOCOP:\n\t\tswitch(m_nPlayerMood) {\n\t\tcase PLAYER_MOOD_ANGRY:\n\t\t\tGetPhrase(sfx, ped->m_lastComment, 8694, 38);\n\t\t\tbreak;\n\t\tcase PLAYER_MOOD_WISECRACKING:\n\t\t\tGetPhrase(sfx, ped->m_lastComment, 9615, 20);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tGetPhrase(sfx, ped->m_lastComment, 9046, 22);\n\t\t\tbreak;\n\t\t}\n\t\tbreak;\n\tcase SOUND_PED_ON_FIRE: {\n\t\tcooldown_phrase(8);\n\t\tswitch(m_nPlayerMood) {\n\t\tcase PLAYER_MOOD_PISSED_OFF:\n\t\t\tGetPhrase(sfx, ped->m_lastComment, 9586, 29);\n\t\t\tbreak;\n\t\tcase PLAYER_MOOD_ANGRY:\n\t\t\tGetPhrase(sfx, ped->m_lastComment, 9007, 39);\n\t\t\tbreak;\n\t\tcase PLAYER_MOOD_WISECRACKING:\n\t\t\tGetPhrase(sfx, ped->m_lastComment, 9787, 9);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tGetPhrase(sfx, ped->m_lastComment, 9322, 35);\n\t\t\tbreak;\n\t\t}\n\t\tbreak;\n\t}\n\tcase SOUND_PED_AIMING: {\n\t\tcooldown_phrase(8);\n\t\tswitch(m_nPlayerMood) {\n\t\tcase PLAYER_MOOD_PISSED_OFF:\n\t\t\tGetPhrase(sfx, ped->m_lastComment, 9561, 25);\n\t\t\tbreak;\n\t\tcase PLAYER_MOOD_ANGRY:\n\t\t\tGetPhrase(sfx, ped->m_lastComment, 8937, 52);\n\t\t\tbreak;\n\t\tcase PLAYER_MOOD_WISECRACKING:\n\t\t\tGetPhrase(sfx, ped->m_lastComment, 9758, 19);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tGetPhrase(sfx, ped->m_lastComment, 9275, 39);\n\t\t\tbreak;\n\t\t}\n\t\tbreak;\n\t}\n\tcase SOUND_PED_CAR_JACKING: {\n\t\tcooldown_phrase(4);\n\t\tswitch(m_nPlayerMood) {\n\t\tcase PLAYER_MOOD_PISSED_OFF:\n\t\t\tGetPhrase(sfx, ped->m_lastComment, 9483, 36);\n\t\t\tbreak;\n\t\tcase PLAYER_MOOD_ANGRY:\n\t\t\tGetPhrase(sfx, ped->m_lastComment, 8876, 43);\n\t\t\tbreak;\n\t\tcase PLAYER_MOOD_WISECRACKING:\n\t\t\tGetPhrase(sfx, ped->m_lastComment, 9706, 18);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tGetPhrase(sfx, ped->m_lastComment, 9202, 40);\n\t\t\tbreak;\n\t\t}\n\t\tbreak;\n\t}\n\tcase SOUND_PED_MUGGING: {\n\t\tcooldown_phrase(8);\n\t\tswitch(m_nPlayerMood) {\n\t\tcase PLAYER_MOOD_PISSED_OFF:\n\t\t\tGetPhrase(sfx, ped->m_lastComment, 9519, 25);\n\t\t\tbreak;\n\t\tcase PLAYER_MOOD_ANGRY:\n\t\t\tGetPhrase(sfx, ped->m_lastComment, 8919, 12);\n\t\t\tbreak;\n\t\tcase PLAYER_MOOD_WISECRACKING:\n\t\t\tGetPhrase(sfx, ped->m_lastComment, 9724, 23);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tGetPhrase(sfx, ped->m_lastComment, 9242, 11);\n\t\t\tbreak;\n\t\t}\n\t\tbreak;\n\t}\n\tcase SOUND_PED_CAR_JACKED: {\n\t\tcooldown_phrase(4);\n\t\tswitch(m_nPlayerMood) {\n\t\tcase PLAYER_MOOD_PISSED_OFF:\n\t\t\tGetPhrase(sfx, ped->m_lastComment, 9462, 21);\n\t\t\tbreak;\n\t\tcase PLAYER_MOOD_ANGRY:\n\t\t\tGetPhrase(sfx, ped->m_lastComment, 8843, 33);\n\t\t\tbreak;\n\t\tcase PLAYER_MOOD_WISECRACKING:\n\t\t\tGetPhrase(sfx, ped->m_lastComment, 9688, 18);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tGetPhrase(sfx, ped->m_lastComment, 9178, 24);\n\t\t\tbreak;\n\t\t}\n\t\tbreak;\n\t}\n\tcase SOUND_PED_PLAYER_AFTERSEX: GetPhrase(sfx, ped->m_lastComment, 9797, 18); break;\n\tcase SOUND_PED_PLAYER_BEFORESEX:\n\t\tswitch(m_nPlayerMood) {\n\t\tcase PLAYER_MOOD_ANGRY:\n\t\t\tGetPhrase(sfx, ped->m_lastComment, 8989, 18);\n\t\t\tbreak;\n\t\tcase PLAYER_MOOD_WISECRACKING:\n\t\t\tGetPhrase(sfx, ped->m_lastComment, 9777, 10);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tGetPhrase(sfx, ped->m_lastComment, 9314, 8);\n\t\t\tbreak;\n\t\t}\n\t\tbreak;\n\tcase SOUND_PED_PLAYER_FARFROMCOPS: {\n\t\tcooldown_phrase(4);\n\t\tswitch(m_nPlayerMood) {\n\t\tcase PLAYER_MOOD_ANGRY:\n\t\t\tGetPhrase(sfx, ped->m_lastComment, 8732, 9);\n\t\t\tbreak;\n\t\tcase PLAYER_MOOD_WISECRACKING:\n\t\t\tGetPhrase(sfx, ped->m_lastComment, 9635, 7);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tGetPhrase(sfx, ped->m_lastComment, 9068, 20);\n\t\t\tbreak;\n\t\t}\n\t\tbreak;\n\t}\n\tcase SOUND_PED_ATTACK: {\n\t\tcooldown_phrase(4);\n\t\tswitch(m_nPlayerMood) {\n\t\tcase PLAYER_MOOD_PISSED_OFF:\n\t\t\tGetPhrase(sfx, ped->m_lastComment, 9401, 61);\n\t\t\tbreak;\n\t\tcase PLAYER_MOOD_ANGRY:\n\t\t\tGetPhrase(sfx, ped->m_lastComment, 8782, 61);\n\t\t\tbreak;\n\t\tcase PLAYER_MOOD_WISECRACKING:\n\t\t\tGetPhrase(sfx, ped->m_lastComment, 9661, 27);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tGetPhrase(sfx, ped->m_lastComment, 9131, 47);\n\t\t\tbreak;\n\t\t}\n\t\tbreak;\n\t}\n\tcase SOUND_PED_CRASH_VEHICLE:\n\tcase SOUND_PED_CRASH_CAR:\n\tcase SOUND_PED_ANNOYED_DRIVER: {\n\t\tcooldown_phrase(4);\n\t\tswitch(m_nPlayerMood) {\n\t\tcase PLAYER_MOOD_PISSED_OFF:\n\t\t\tGetPhrase(sfx, ped->m_lastComment, 9357, 44);\n\t\t\tbreak;\n\t\tcase PLAYER_MOOD_ANGRY:\n\t\t\tGetPhrase(sfx, ped->m_lastComment, 8741, 41);\n\t\t\tbreak;\n\t\tcase PLAYER_MOOD_WISECRACKING:\n\t\t\tGetPhrase(sfx, ped->m_lastComment, 9642, 19);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tGetPhrase(sfx, ped->m_lastComment, 9088, 43);\n\t\t\tbreak;\n\t\t}\n\t\tbreak;\n\t}\n\tcase SOUND_PED_SOLICIT: {\n\t\tcooldown_phrase(4);\n\t\tswitch(m_nPlayerMood) {\n\t\tcase PLAYER_MOOD_PISSED_OFF:\n\t\t\tGetPhrase(sfx, ped->m_lastComment, 9544, 17);\n\t\t\tbreak;\n\t\tcase PLAYER_MOOD_ANGRY:\n\t\t\tGetPhrase(sfx, ped->m_lastComment, 8931, 6);\n\t\t\tbreak;\n\t\tcase PLAYER_MOOD_WISECRACKING:\n\t\t\tGetPhrase(sfx, ped->m_lastComment, 9747, 11);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tGetPhrase(sfx, ped->m_lastComment, 9253, 22);\n\t\t\tbreak;\n\t\t}\n\t\tbreak;\n\t}\n\tdefault: return GetGenericMaleTalkSfx(ped, sound);\n\t}\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetCopTalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\tPedState objective;\n\tswitch(sound) {\n\tcase SOUND_PED_ARREST_COP: GetPhrase(sfx, ped->m_lastComment, 8469, 4); break;\n\tcase SOUND_PED_PULLOUTWEAPON: GetPhrase(sfx, ped->m_lastComment, 8473, 3); break;\n\tcase SOUND_PED_ACCIDENTREACTION1: GetPhrase(sfx, ped->m_lastComment, 8500, 2); break;\n\tcase SOUND_PED_COP_UNK_129: GetPhrase(sfx, ped->m_lastComment, 8510, 4); break;\n\tcase SOUND_PED_COP_MANYCOPSAROUND: GetPhrase(sfx, ped->m_lastComment, 8508, 2); break;\n\tcase SOUND_PED_GUNAIMEDAT2: GetPhrase(sfx, ped->m_lastComment, 8498, 2); break;\n\tcase SOUND_PED_COP_ALONE: GetPhrase(sfx, ped->m_lastComment, 8504, 4); break;\n\tcase SOUND_PED_GUNAIMEDAT3: GetPhrase(sfx, ped->m_lastComment, 8485, 2); break;\n\tcase SOUND_PED_COP_REACTION: {\n\t\tcooldown_phrase(4);\n\t\tGetPhrase(sfx, ped->m_lastComment, 8502, 2);\n\t\tbreak;\n\t}\n\tcase SOUND_PED_COP_LITTLECOPSAROUND:\n\t\tobjective = FindPlayerPed()->m_nPedState;\n\t\tif(objective == PED_ARRESTED || objective == PED_DEAD || objective == PED_DIE) return NO_SAMPLE;\n\t\tGetPhrase(sfx, ped->m_lastComment, 8481, 4);\n\t\tbreak;\n\tcase SOUND_PED_ATTACK: GetPhrase(sfx, ped->m_lastComment, 8494, 4); break;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 8491, 3); break;\n\tcase SOUND_PED_PED_COLLISION:\n\t\tif(FindPlayerPed()->m_pWanted->GetWantedLevel() <= 0) return NO_SAMPLE;\n\t\tGetPhrase(sfx, ped->m_lastComment, 8476, 5);\n\t\tbreak;\n\tdefault: return GetGenericMaleTalkSfx(ped, sound);\n\t}\n\treturn 45 * (m_sQueueSample.m_nEntityIndex % 5) + sfx;\n}\n\nuint32\ncAudioManager::GetSwatTalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\tswitch(sound) {\n\tcase SOUND_PED_COP_HELIPILOTPHRASE: GetPhrase(sfx, ped->m_lastComment, 3285, 7); break;\n\tcase SOUND_PED_COP_UNK_129: GetPhrase(sfx, ped->m_lastComment, 3292, 4); break;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 3282, 3); break;\n\tdefault: return GetGenericMaleTalkSfx(ped, sound);\n\t}\n\tsfx += 14 * (m_sQueueSample.m_nEntityIndex % 3);\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetFBITalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\tswitch(sound) {\n\tcase SOUND_PED_COP_UNK_129: GetPhrase(sfx, ped->m_lastComment, 3240u, 4u); break;\n\tcase SOUND_PED_COP_MANYCOPSAROUND: GetPhrase(sfx, ped->m_lastComment, 3237u, 3u); break;\n\tcase SOUND_PED_GUNAIMEDAT2: sfx = 3236; break;\n\tcase SOUND_PED_GUNAIMEDAT3: GetPhrase(sfx, ped->m_lastComment, 3228u, 4u); break;\n\tcase SOUND_PED_CRASH_VEHICLE:\n\tcase SOUND_PED_CRASH_CAR: GetPhrase(sfx, ped->m_lastComment, 3232u, 4u); break;\n\tdefault: return GetGenericMaleTalkSfx(ped, sound);\n\t}\n\tsfx += 16 * (m_sQueueSample.m_nEntityIndex % 3);\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetArmyTalkSfx(CPed *ped, int16 sound)\n{\n\treturn GetGenericMaleTalkSfx(ped, sound);\n}\n\nuint32\ncAudioManager::GetMedicTalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\tswitch(sound) {\n\tcase SOUND_PED_ATTACK: GetPhrase(sfx, ped->m_lastComment, 3162, 6); break;\n\tcase SOUND_PED_HEALING: GetPhrase(sfx, ped->m_lastComment, 3178, 17); break;\n\tcase SOUND_PED_LEAVE_VEHICLE: GetPhrase(sfx, ped->m_lastComment, 3168, 10); break; // SFX_MEDIC_VOICE_1_GET_OUT_VAN_CHAT_1\n\tdefault: return GetGenericMaleTalkSfx(ped, sound);\n\t}\n\tsfx += 33 * (m_sQueueSample.m_nEntityIndex % 2);\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetFiremanTalkSfx(CPed *ped, int16 sound)\n{\n\treturn GetGenericMaleTalkSfx(ped, sound);\n}\n\nuint32\ncAudioManager::GetDefaultTalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_COWER: GetPhrase(sfx, ped->m_lastComment, 2033, 12); break;\n\tcase SOUND_PED_CAR_JACKED: GetPhrase(sfx, ped->m_lastComment, 2045, 12); break;\n\tcase SOUND_PED_ROBBED: GetPhrase(sfx, ped->m_lastComment, 2075, 4); break;\n\tcase SOUND_PED_ACCIDENTREACTION1: GetPhrase(sfx, ped->m_lastComment, 2098, 4); break;\n\tcase SOUND_PED_TAXI_WAIT: GetPhrase(sfx, ped->m_lastComment, 2108, 5); break;\n\tcase SOUND_PED_ATTACK: GetPhrase(sfx, ped->m_lastComment, 2004, 16); break;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 1979, 19); break;\n\tcase SOUND_PED_FLEE_RUN: GetPhrase(sfx, ped->m_lastComment, 2079, 19); break;\n\tcase SOUND_PED_CRASH_VEHICLE: GetPhrase(sfx, ped->m_lastComment, 2020, 13); break;\n\tcase SOUND_PED_CRASH_CAR: GetPhrase(sfx, ped->m_lastComment, 1939, 15); break;\n\tcase SOUND_PED_ANNOYED_DRIVER: GetPhrase(sfx, ped->m_lastComment, 1898, 16); break;\n\tcase SOUND_PED_WAIT_DOUBLEBACK: GetPhrase(sfx, ped->m_lastComment, 2070, 5); break;\n\tcase SOUND_153: GetPhrase(sfx, ped->m_lastComment, 1998, 6); break;\n\tcase SOUND_PED_CHAT_EVENT: GetPhrase(sfx, ped->m_lastComment, 2102, 6); break;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 1914, 25); break;\n\tcase SOUND_PED_CHAT: GetPhrase(sfx, ped->m_lastComment, 1954, 25); break;\n\tdefault: return GetGenericMaleTalkSfx(ped, sound);\n\t}\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetHFYSTTalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_UP: GetPhrase(sfx, ped->m_lastComment, 5736, 5); break;\n\tcase SOUND_PED_CAR_JACKING: GetPhrase(sfx, ped->m_lastComment, 5747, 4); break;\n\tcase SOUND_PED_MUGGING: GetPhrase(sfx, ped->m_lastComment, 5755, 4); break;\n\tcase SOUND_PED_CAR_JACKED: GetPhrase(sfx, ped->m_lastComment, 5741, 6); break;\n\tcase SOUND_PED_ROBBED: GetPhrase(sfx, ped->m_lastComment, 5753, 2); break;\n\tcase SOUND_PED_TAXI_WAIT: return 5759;\n\tcase SOUND_PED_ATTACK: GetPhrase(sfx, ped->m_lastComment, 5722, 7); break;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 5712, 10); break;\n\tcase SOUND_PED_CRASH_VEHICLE: GetPhrase(sfx, ped->m_lastComment, 5729, 7); break;\n\tcase SOUND_PED_CRASH_CAR: GetPhrase(sfx, ped->m_lastComment, 5695, 8); break;\n\tcase SOUND_PED_ANNOYED_DRIVER: GetPhrase(sfx, ped->m_lastComment, 5678, 7); break;\n\tcase SOUND_PED_WAIT_DOUBLEBACK: GetPhrase(sfx, ped->m_lastComment, 5751, 2); break;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 5685, 10); break;\n\tcase SOUND_PED_CHAT: GetPhrase(sfx, ped->m_lastComment, 5703, 9); break;\n\tdefault: return GetGenericFemaleTalkSfx(ped, sound);\n\t}\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetHFOSTTalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_UP: GetPhrase(sfx, ped->m_lastComment, 4382, 6); break;\n\tcase SOUND_PED_CAR_JACKED: GetPhrase(sfx, ped->m_lastComment, 4388, 8); break;\n\tcase SOUND_PED_ROBBED: GetPhrase(sfx, ped->m_lastComment, 4398, 3); break;\n\tcase SOUND_PED_TAXI_WAIT: GetPhrase(sfx, ped->m_lastComment, 4401, 2); break;\n\tcase SOUND_PED_ATTACK: GetPhrase(sfx, ped->m_lastComment, 4363, 8); break;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 4353, 10); break;\n\tcase SOUND_PED_CRASH_VEHICLE: GetPhrase(sfx, ped->m_lastComment, 4371, 11); break;\n\tcase SOUND_PED_CRASH_CAR: GetPhrase(sfx, ped->m_lastComment, 4334, 8); break;\n\tcase SOUND_PED_ANNOYED_DRIVER: GetPhrase(sfx, ped->m_lastComment, 4313, 9); break;\n\tcase SOUND_PED_WAIT_DOUBLEBACK: GetPhrase(sfx, ped->m_lastComment, 4396, 2); break;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 4322, 12); break;\n\tcase SOUND_PED_CHAT: GetPhrase(sfx, ped->m_lastComment, 4342, 11); break;\n\tdefault: return GetGenericFemaleTalkSfx(ped, sound);\n\t}\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetHMYSTTalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_COWER: GetPhrase(sfx, ped->m_lastComment, 7961, 6); break;\n\tcase SOUND_PED_ACCIDENTREACTION1: return 7971;\n\tcase SOUND_PED_TAXI_WAIT: return 7974;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 7946, 6); break;\n\tcase SOUND_PED_FLEE_RUN: GetPhrase(sfx, ped->m_lastComment, 7967, 4); break;\n\tcase SOUND_PED_CRASH_VEHICLE: GetPhrase(sfx, ped->m_lastComment, 7954, 7); break;\n\tcase SOUND_PED_CHAT_SEXY: GetPhrase(sfx, ped->m_lastComment, 7952, 2); break;\n\tcase SOUND_PED_CHAT_EVENT: GetPhrase(sfx, ped->m_lastComment, 7972, 2); break;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 7922, 13); break;\n\tcase SOUND_PED_CHAT: GetPhrase(sfx, ped->m_lastComment, 7935, 11); break;\n\tdefault: return GetGenericMaleTalkSfx(ped, sound);\n\t}\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetHMOSTTalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_UP: GetPhrase(sfx, ped->m_lastComment, 5820, 5); break;\n\tcase SOUND_PED_CAR_JACKING: GetPhrase(sfx, ped->m_lastComment, 5831, 3); break;\n\tcase SOUND_PED_CAR_JACKED: GetPhrase(sfx, ped->m_lastComment, 5825, 6); break;\n\tcase SOUND_PED_ROBBED: GetPhrase(sfx, ped->m_lastComment, 5836, 2); break;\n\tcase SOUND_PED_TAXI_WAIT: return 5838;\n\tcase SOUND_PED_ATTACK: GetPhrase(sfx, ped->m_lastComment, 5805, 8); break;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 5795, 9); break;\n\tcase SOUND_PED_CRASH_VEHICLE: GetPhrase(sfx, ped->m_lastComment, 5813, 7); break;\n\tcase SOUND_PED_CRASH_CAR: GetPhrase(sfx, ped->m_lastComment, 5777, 7); break;\n\tcase SOUND_PED_ANNOYED_DRIVER: GetPhrase(sfx, ped->m_lastComment, 5760, 7); break;\n\tcase SOUND_PED_WAIT_DOUBLEBACK: GetPhrase(sfx, ped->m_lastComment, 5834, 2); break;\n\tcase SOUND_PED_CHAT_SEXY: return 5804;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 5767, 10); break;\n\tcase SOUND_PED_CHAT: GetPhrase(sfx, ped->m_lastComment, 5784, 11); break;\n\tdefault: return GetGenericMaleTalkSfx(ped, sound);\n\t}\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetHFYRITalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_COWER: GetPhrase(sfx, ped->m_lastComment, 6965, 5); break;\n\tcase SOUND_PED_CAR_JACKED: GetPhrase(sfx, ped->m_lastComment, 6970, 6); break;\n\tcase SOUND_PED_ROBBED: GetPhrase(sfx, ped->m_lastComment, 6978, 4); break;\n\tcase SOUND_PED_ACCIDENTREACTION1: GetPhrase(sfx, ped->m_lastComment, 6986, 2); break;\n\tcase SOUND_PED_TAXI_WAIT: return 6991;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 6948, 10); break;\n\tcase SOUND_PED_FLEE_RUN: GetPhrase(sfx, ped->m_lastComment, 6982, 4); break;\n\tcase SOUND_PED_CRASH_VEHICLE: GetPhrase(sfx, ped->m_lastComment, 6958, 7); break;\n\tcase SOUND_PED_CRASH_CAR: GetPhrase(sfx, ped->m_lastComment, 6940, 8); break;\n\tcase SOUND_PED_ANNOYED_DRIVER: GetPhrase(sfx, ped->m_lastComment, 6923, 8); break;\n\tcase SOUND_PED_WAIT_DOUBLEBACK: GetPhrase(sfx, ped->m_lastComment, 6976, 2); break;\n\tcase SOUND_PED_CHAT_EVENT: GetPhrase(sfx, ped->m_lastComment, 6988, 3); break;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 6931, 9); break;\n\tdefault: return GetGenericFemaleTalkSfx(ped, sound);\n\t}\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetHFORITalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_COWER: GetPhrase(sfx, ped->m_lastComment, 7244, 6); break;\n\tcase SOUND_PED_CAR_JACKED: GetPhrase(sfx, ped->m_lastComment, 7250, 9); break;\n\tcase SOUND_PED_ROBBED: GetPhrase(sfx, ped->m_lastComment, 7261, 2); break;\n\tcase SOUND_PED_ACCIDENTREACTION1: return 7267;\n\tcase SOUND_PED_TAXI_WAIT: return 7270;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 7229, 6); break;\n\tcase SOUND_PED_FLEE_RUN: GetPhrase(sfx, ped->m_lastComment, 7263, 4); break;\n\tcase SOUND_PED_CRASH_VEHICLE: GetPhrase(sfx, ped->m_lastComment, 7237, 7); break;\n\tcase SOUND_PED_CRASH_CAR: GetPhrase(sfx, ped->m_lastComment, 7222, 7); break;\n\tcase SOUND_PED_ANNOYED_DRIVER: GetPhrase(sfx, ped->m_lastComment, 7206, 6); break;\n\tcase SOUND_PED_WAIT_DOUBLEBACK: GetPhrase(sfx, ped->m_lastComment, 7259, 2); break;\n\tcase SOUND_153: GetPhrase(sfx, ped->m_lastComment, 7235, 2); break;\n\tcase SOUND_PED_CHAT_EVENT: GetPhrase(sfx, ped->m_lastComment, 7268, 2); break;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 7212, 10); break;\n\tdefault: return GetGenericFemaleTalkSfx(ped, sound);\n\t}\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetHMYRITalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_COWER: GetPhrase(sfx, ped->m_lastComment, 5890, 7); break;\n\tcase SOUND_PED_CAR_JACKING: GetPhrase(sfx, ped->m_lastComment, 5905, 3); break;\n\tcase SOUND_PED_CAR_JACKED: GetPhrase(sfx, ped->m_lastComment, 5897, 8); break;\n\tcase SOUND_PED_ROBBED: return 5908;\n\tcase SOUND_PED_ATTACK: GetPhrase(sfx, ped->m_lastComment, 5873, 5); break;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 5864, 9); break;\n\tcase SOUND_PED_CRASH_VEHICLE: GetPhrase(sfx, ped->m_lastComment, 5878, 12); break;\n\tcase SOUND_PED_CRASH_CAR: GetPhrase(sfx, ped->m_lastComment, 5856, 8); break;\n\tcase SOUND_PED_ANNOYED_DRIVER: GetPhrase(sfx, ped->m_lastComment, 5839, 7); break;\n\tcase SOUND_PED_CHAT_EVENT: GetPhrase(sfx, ped->m_lastComment, 5909, 3); break;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 5846, 10); break;\n\tdefault: return GetGenericMaleTalkSfx(ped, sound);\n\t}\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetHMORITalkSfx(CPed *ped, int16 sound)\n{\n\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_COWER: GetPhrase(sfx, ped->m_lastComment, 4454, 5); break;\n\tcase SOUND_PED_CAR_JACKED: GetPhrase(sfx, ped->m_lastComment, 4459, 8); break;\n\tcase SOUND_PED_ROBBED: GetPhrase(sfx, ped->m_lastComment, 4469, 3); break;\n\tcase SOUND_PED_TAXI_WAIT: GetPhrase(sfx, ped->m_lastComment, 4478, 2); break;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 4436, 7); break;\n\tcase SOUND_PED_FLEE_RUN: GetPhrase(sfx, ped->m_lastComment, 4472, 6); break;\n\tcase SOUND_PED_CRASH_VEHICLE: GetPhrase(sfx, ped->m_lastComment, 4443, 11); break;\n\tcase SOUND_PED_CRASH_CAR: GetPhrase(sfx, ped->m_lastComment, 4422, 6); break;\n\tcase SOUND_PED_ANNOYED_DRIVER: GetPhrase(sfx, ped->m_lastComment, 4403, 8); break;\n\tcase SOUND_PED_WAIT_DOUBLEBACK: GetPhrase(sfx, ped->m_lastComment, 4467, 2); break;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 4411, 11); break;\n\tcase SOUND_PED_CHAT: GetPhrase(sfx, ped->m_lastComment, 4428, 8); break;\n\tdefault: return GetGenericMaleTalkSfx(ped, sound);\n\t}\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetHFYBETalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_COWER: GetPhrase(sfx, ped->m_lastComment, 6897, 7); break;\n\tcase SOUND_PED_CAR_JACKED: GetPhrase(sfx, ped->m_lastComment, 6904, 7); break;\n\tcase SOUND_PED_TAXI_WAIT: return 6922;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 6878, 11); break;\n\tcase SOUND_PED_CRASH_VEHICLE: GetPhrase(sfx, ped->m_lastComment, 6889, 8); break;\n\tcase SOUND_PED_CRASH_CAR: GetPhrase(sfx, ped->m_lastComment, 6862, 6); break;\n\tcase SOUND_PED_WAIT_DOUBLEBACK: GetPhrase(sfx, ped->m_lastComment, 6911, 2); break;\n\tcase SOUND_PED_CHAT_EVENT: GetPhrase(sfx, ped->m_lastComment, 6920, 2); break;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 6854, 8); break;\n\tcase SOUND_PED_CHAT: GetPhrase(sfx, ped->m_lastComment, 6868, 10); break;\n\tdefault: return GetGenericFemaleTalkSfx(ped, sound);\n\t}\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetHFOBETalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_COWER: GetPhrase(sfx, ped->m_lastComment, 1018, 5); break;\n\tcase SOUND_PED_CAR_JACKED: GetPhrase(sfx, ped->m_lastComment, 1023, 6); break;\n\tcase SOUND_PED_ACCIDENTREACTION1: return 1035;\n\tcase SOUND_PED_TAXI_WAIT: GetPhrase(sfx, ped->m_lastComment, 1038, 2); break;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 1006, 7); break;\n\tcase SOUND_PED_FLEE_RUN: GetPhrase(sfx, ped->m_lastComment, 1031, 4); break;\n\tcase SOUND_PED_CRASH_VEHICLE: GetPhrase(sfx, ped->m_lastComment, 1013, 5); break;\n\tcase SOUND_PED_CRASH_CAR: GetPhrase(sfx, ped->m_lastComment, 990, 6); break;\n\tcase SOUND_PED_ANNOYED_DRIVER: GetPhrase(sfx, ped->m_lastComment, 973, 6); break;\n\tcase SOUND_PED_WAIT_DOUBLEBACK: GetPhrase(sfx, ped->m_lastComment, 1029, 2); break;\n\tcase SOUND_PED_CHAT_EVENT: GetPhrase(sfx, ped->m_lastComment, 1036, 2); break;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 979, 11); break;\n\tcase SOUND_PED_CHAT: GetPhrase(sfx, ped->m_lastComment, 996, 10); break;\n\tdefault: return GetGenericFemaleTalkSfx(ped, sound);\n\t}\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetHMYBETalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_COWER: GetPhrase(sfx, ped->m_lastComment, 4892, 6); break;\n\tcase SOUND_PED_CAR_JACKED: GetPhrase(sfx, ped->m_lastComment, 4902, 12); break;\n\tcase SOUND_PED_ACCIDENTREACTION1: return 4917;\n\tcase SOUND_PED_UNK_126: GetPhrase(sfx, ped->m_lastComment, 4898, 4); break;\n\tcase SOUND_PED_TAXI_WAIT: return 4920;\n\tcase SOUND_PED_ATTACK: GetPhrase(sfx, ped->m_lastComment, 4874, 8); break;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 4862, 7); break;\n\tcase SOUND_PED_CRASH_VEHICLE: GetPhrase(sfx, ped->m_lastComment, 4882, 10); break;\n\tcase SOUND_PED_CRASH_CAR: GetPhrase(sfx, ped->m_lastComment, 4845, 7); break;\n\tcase SOUND_PED_WAIT_DOUBLEBACK: GetPhrase(sfx, ped->m_lastComment, 4914, 3); break;\n\tcase SOUND_PED_CHAT_SEXY: GetPhrase(sfx, ped->m_lastComment, 4869, 5); break;\n\tcase SOUND_PED_CHAT_EVENT: GetPhrase(sfx, ped->m_lastComment, 4918, 2); break;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 4835, 10); break;\n\tcase SOUND_PED_CHAT: GetPhrase(sfx, ped->m_lastComment, 4852, 10); break;\n\tdefault: return GetGenericMaleTalkSfx(ped, sound);\n\t}\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetHMOBETalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_COWER: GetPhrase(sfx, ped->m_lastComment, 4703, 3); break;\n\tcase SOUND_PED_CAR_JACKED: GetPhrase(sfx, ped->m_lastComment, 4709, 6); break;\n\tcase SOUND_PED_UNK_126: GetPhrase(sfx, ped->m_lastComment, 4706, 3); break;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 4690, 9); break;\n\tcase SOUND_PED_ANNOYED_DRIVER: GetPhrase(sfx, ped->m_lastComment, 4672, 10); break;\n\tcase SOUND_PED_CHAT_SEXY: GetPhrase(sfx, ped->m_lastComment, 4699, 4); break;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 4682, 8); break;\n\tdefault: return GetGenericMaleTalkSfx(ped, sound);\n\t}\n\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetHFYBUTalkSfx(CPed *ped, int16 sound)\n{\n\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_COWER: GetPhrase(sfx, ped->m_lastComment, 4771, 5); break;\n\tcase SOUND_PED_CAR_JACKING: GetPhrase(sfx, ped->m_lastComment, 4782, 3); break;\n\tcase SOUND_PED_CAR_JACKED: GetPhrase(sfx, ped->m_lastComment, 4776, 6); break;\n\tcase SOUND_PED_ROBBED: GetPhrase(sfx, ped->m_lastComment, 4787, 2); break;\n\tcase SOUND_PED_ACCIDENTREACTION1: return 4789;\n\tcase SOUND_PED_TAXI_WAIT: return 4790;\n\tcase SOUND_PED_ATTACK: GetPhrase(sfx, ped->m_lastComment, 4752, 7); break;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 4742, 10); break;\n\tcase SOUND_PED_CRASH_VEHICLE: GetPhrase(sfx, ped->m_lastComment, 4759, 12); break;\n\tcase SOUND_PED_CRASH_CAR: GetPhrase(sfx, ped->m_lastComment, 4734, 8); break;\n\tcase SOUND_PED_ANNOYED_DRIVER: GetPhrase(sfx, ped->m_lastComment, 4715, 8); break;\n\tcase SOUND_PED_WAIT_DOUBLEBACK: GetPhrase(sfx, ped->m_lastComment, 4785, 2); break;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 4723, 11); break;\n\tdefault: return GetGenericFemaleTalkSfx(ped, sound);\n\t}\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetHFYMDTalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_COWER: GetPhrase(sfx, ped->m_lastComment, 6014, 5); break;\n\tcase SOUND_PED_ROBBED: GetPhrase(sfx, ped->m_lastComment, 6019, 2); break;\n\tcase SOUND_PED_ACCIDENTREACTION1: GetPhrase(sfx, ped->m_lastComment, 6021, 3); break;\n\tcase SOUND_PED_TAXI_WAIT: return 8231;\n\tcase SOUND_PED_ATTACK: GetPhrase(sfx, ped->m_lastComment, 6005, 9); break;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 5997, 8); break;\n\tcase SOUND_PED_SOLICIT: GetPhrase(sfx, ped->m_lastComment, 6024, 15); break;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 5988, 9); break;\n\tdefault: return GetGenericFemaleTalkSfx(ped, sound);\n\t}\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetHFYCGTalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_COWER: GetPhrase(sfx, ped->m_lastComment, 4808, 5); break;\n\tcase SOUND_PED_ROBBED: GetPhrase(sfx, ped->m_lastComment, 4813, 2); break;\n\tcase SOUND_PED_ACCIDENTREACTION1: return 4819;\n\tcase SOUND_PED_TAXI_WAIT: return 8231;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 4800, 8); break;\n\tcase SOUND_PED_FLEE_RUN: GetPhrase(sfx, ped->m_lastComment, 4815, 4); break;\n\tcase SOUND_PED_SOLICIT: GetPhrase(sfx, ped->m_lastComment, 4820, 14); break;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 4791, 9); break;\n\tdefault: return GetGenericFemaleTalkSfx(ped, sound);\n\t}\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetHFYPRTalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_UP: GetPhrase(sfx, ped->m_lastComment, 5964, 6); break;\n\tcase SOUND_PED_ROBBED: GetPhrase(sfx, ped->m_lastComment, 5970, 2); break;\n\tcase SOUND_PED_ACCIDENTREACTION1: return 5972;\n\tcase SOUND_PED_PLAYER_BEFORESEX: GetPhrase(sfx, ped->m_lastComment, 5956, 8); break;\n\tcase SOUND_PED_TAXI_WAIT: return 5987;\n\tcase SOUND_PED_ATTACK: GetPhrase(sfx, ped->m_lastComment, 5946, 10); break;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 5934, 9); break;\n\tcase SOUND_PED_SOLICIT: GetPhrase(sfx, ped->m_lastComment, 5973, 14); break;\n\tcase SOUND_153: GetPhrase(sfx, ped->m_lastComment, 5943, 3); break;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 5912, 10); break;\n\tcase SOUND_PED_CHAT: GetPhrase(sfx, ped->m_lastComment, 5922, 12); break;\n\tdefault: return GetGenericFemaleTalkSfx(ped, sound);\n\t}\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetHFOTRTalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_UP: GetPhrase(sfx, ped->m_lastComment, 4660, 5); break;\n\tcase SOUND_PED_ROBBED: GetPhrase(sfx, ped->m_lastComment, 4665, 2); break;\n\tcase SOUND_PED_ACCIDENTREACTION1: return 4667;\n\tcase SOUND_PED_TAXI_WAIT: GetPhrase(sfx, ped->m_lastComment, 4670, 2); break;\n\tcase SOUND_PED_ATTACK: GetPhrase(sfx, ped->m_lastComment, 4654, 6); break;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 4646, 8); break;\n\tcase SOUND_PED_CHAT_EVENT: GetPhrase(sfx, ped->m_lastComment, 4668, 2); break;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 4623, 11); break;\n\tcase SOUND_PED_CHAT: GetPhrase(sfx, ped->m_lastComment, 4634, 12); break;\n\tdefault: return GetGenericFemaleTalkSfx(ped, sound);\n\t}\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetHMOTRTalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_UP: GetPhrase(sfx, ped->m_lastComment, 4515, 6); break;\n\tcase SOUND_PED_ACCIDENTREACTION1: GetPhrase(sfx, ped->m_lastComment, 4521, 2); break;\n\tcase SOUND_PED_TAXI_WAIT: return 4534;\n\tcase SOUND_PED_ATTACK: GetPhrase(sfx, ped->m_lastComment, 4508, 7); break;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 4497, 11); break;\n\tcase SOUND_PED_SOLICIT: GetPhrase(sfx, ped->m_lastComment, 4526, 8); break;\n\tcase SOUND_PED_CHAT_EVENT: GetPhrase(sfx, ped->m_lastComment, 4523, 3); break;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 4480, 8); break;\n\tcase SOUND_PED_CHAT: GetPhrase(sfx, ped->m_lastComment, 4488, 9); break;\n\tdefault: return GetGenericMaleTalkSfx(ped, sound);\n\t}\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetHMYAPTalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_COWER: GetPhrase(sfx, ped->m_lastComment, 4591, 7); break;\n\tcase SOUND_PED_CAR_JACKING: GetPhrase(sfx, ped->m_lastComment, 4605, 4); break;\n\tcase SOUND_PED_CAR_JACKED: GetPhrase(sfx, ped->m_lastComment, 4598, 7); break;\n\tcase SOUND_PED_ROBBED: GetPhrase(sfx, ped->m_lastComment, 4611, 2); break;\n\tcase SOUND_PED_ACCIDENTREACTION1: GetPhrase(sfx, ped->m_lastComment, 4619, 2); break;\n\tcase SOUND_PED_TAXI_WAIT: GetPhrase(sfx, ped->m_lastComment, 4621, 2); break;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 4573, 9); break;\n\tcase SOUND_PED_FLEE_RUN: GetPhrase(sfx, ped->m_lastComment, 4613, 6); break;\n\tcase SOUND_PED_CRASH_VEHICLE: GetPhrase(sfx, ped->m_lastComment, 4585, 6); break;\n\tcase SOUND_PED_CRASH_CAR: GetPhrase(sfx, ped->m_lastComment, 4555, 9); break;\n\tcase SOUND_PED_ANNOYED_DRIVER: GetPhrase(sfx, ped->m_lastComment, 4535, 9); break;\n\tcase SOUND_PED_WAIT_DOUBLEBACK: GetPhrase(sfx, ped->m_lastComment, 4609, 2); break;\n\tcase SOUND_PED_CHAT_SEXY: GetPhrase(sfx, ped->m_lastComment, 4582, 3); break;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 4544, 11); break;\n\tcase SOUND_PED_CHAT: GetPhrase(sfx, ped->m_lastComment, 4564, 9); break;\n\tdefault: return GetGenericMaleTalkSfx(ped, sound);\n\t}\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetHMOCATalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_COWER: GetPhrase(sfx, ped->m_lastComment, 3506, 5); break;\n\tcase SOUND_PED_CAR_JACKING: GetPhrase(sfx, ped->m_lastComment, 3521, 11); break;\n\tcase SOUND_PED_CAR_JACKED: GetPhrase(sfx, ped->m_lastComment, 3511, 10); break;\n\tcase SOUND_PED_ROBBED: GetPhrase(sfx, ped->m_lastComment, 3532, 7); break;\n\tcase SOUND_PED_TAXI_WAIT: return 3541;\n\tcase SOUND_PED_FLEE_RUN: GetPhrase(sfx, ped->m_lastComment, 3539, 2); break;\n\tcase SOUND_PED_CRASH_CAR: GetPhrase(sfx, ped->m_lastComment, 3486, 8); break;\n\tcase SOUND_PED_ANNOYED_DRIVER: GetPhrase(sfx, ped->m_lastComment, 3478, 8); break;\n\tcase SOUND_PED_CHAT_SEXY: GetPhrase(sfx, ped->m_lastComment, 3504, 2); break;\n\tcase SOUND_PED_CHAT: GetPhrase(sfx, ped->m_lastComment, 3494, 10); break;\n\tdefault: return GetGenericMaleTalkSfx(ped, sound);\n\t}\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetBMODKTalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_COWER: GetPhrase(sfx, ped->m_lastComment, 6831, 4); break;\n\tcase SOUND_PED_CAR_JACKED: GetPhrase(sfx, ped->m_lastComment, 6838, 9); break;\n\tcase SOUND_PED_ROBBED: GetPhrase(sfx, ped->m_lastComment, 6847, 2); break;\n\tcase SOUND_PED_UNK_126: GetPhrase(sfx, ped->m_lastComment, 6835, 3); break;\n\tcase SOUND_PED_TAXI_WAIT: return 6853;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 6817, 7); break;\n\tcase SOUND_PED_FLEE_RUN: GetPhrase(sfx, ped->m_lastComment, 6849, 4); break;\n\tcase SOUND_PED_CRASH_VEHICLE: GetPhrase(sfx, ped->m_lastComment, 6824, 7); break;\n\tcase SOUND_PED_CRASH_CAR: GetPhrase(sfx, ped->m_lastComment, 6794, 10); break;\n\tcase SOUND_PED_ANNOYED_DRIVER: GetPhrase(sfx, ped->m_lastComment, 6776, 8); break;\n\tcase SOUND_PED_147:\n\t\tGetPhrase(sfx, ped->m_lastComment, 6805, 11);\n\t\tswitch(sfx) {\n\t\tcase 6809:\n\t\tcase 6810:\n\t\tcase 6811: GetPhrase(sfx, ped->m_lastComment, 6805, 4); break;\n\t\tdefault: break;\n\t\t}\n\t\tbreak;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 6784, 10); break;\n\tdefault: return GetGenericMaleTalkSfx(ped, sound);\n\t}\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetBMYCRTalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_UP: GetPhrase(sfx, ped->m_lastComment, 6578, 6); break;\n\tcase SOUND_PED_CAR_JACKING: GetPhrase(sfx, ped->m_lastComment, 6594, 12); break;\n\tcase SOUND_PED_MUGGING: GetPhrase(sfx, ped->m_lastComment, 6609, 6); break;\n\tcase SOUND_PED_CAR_JACKED: GetPhrase(sfx, ped->m_lastComment, 6588, 6); break;\n\tcase SOUND_PED_ROBBED: GetPhrase(sfx, ped->m_lastComment, 6606, 3); break;\n\tcase SOUND_PED_ACCIDENTREACTION1: GetPhrase(sfx, ped->m_lastComment, 6615, 2); break;\n\tcase SOUND_PED_UNK_126: GetPhrase(sfx, ped->m_lastComment, 6584, 4); break;\n\tcase SOUND_PED_ATTACK: GetPhrase(sfx, ped->m_lastComment, 6563, 8); break;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 6553, 8); break;\n\tcase SOUND_PED_CRASH_VEHICLE: GetPhrase(sfx, ped->m_lastComment, 6571, 7); break;\n\tcase SOUND_PED_CRASH_CAR: GetPhrase(sfx, ped->m_lastComment, 6544, 9); break;\n\tcase SOUND_PED_ANNOYED_DRIVER: GetPhrase(sfx, ped->m_lastComment, 6521, 12); break;\n\tcase SOUND_PED_CHAT_SEXY: GetPhrase(sfx, ped->m_lastComment, 6561, 2); break;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 6533, 11); break;\n\tdefault: return GetGenericMaleTalkSfx(ped, sound);\n\t}\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetBFYSTTalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_COWER: GetPhrase(sfx, ped->m_lastComment, 7184, 4); break;\n\tcase SOUND_PED_CAR_JACKED: GetPhrase(sfx, ped->m_lastComment, 7188, 5); break;\n\tcase SOUND_PED_ROBBED: GetPhrase(sfx, ped->m_lastComment, 7195, 2); break;\n\tcase SOUND_PED_ACCIDENTREACTION1: GetPhrase(sfx, ped->m_lastComment, 7203, 2); break;\n\tcase SOUND_PED_TAXI_WAIT: return 7205;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 7167, 9); break;\n\tcase SOUND_PED_FLEE_RUN: GetPhrase(sfx, ped->m_lastComment, 7197, 6); break;\n\tcase SOUND_PED_CRASH_VEHICLE: GetPhrase(sfx, ped->m_lastComment, 7176, 8); break;\n\tcase SOUND_PED_CRASH_CAR: GetPhrase(sfx, ped->m_lastComment, 7149, 9); break;\n\tcase SOUND_PED_ANNOYED_DRIVER: GetPhrase(sfx, ped->m_lastComment, 7132, 8); break;\n\tcase SOUND_PED_WAIT_DOUBLEBACK: GetPhrase(sfx, ped->m_lastComment, 7193, 2); break;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 7140, 9); break;\n\tcase SOUND_PED_CHAT: GetPhrase(sfx, ped->m_lastComment, 7158, 9); break;\n\tdefault: return GetGenericFemaleTalkSfx(ped, sound);\n\t}\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetBFOSTTalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_COWER: GetPhrase(sfx, ped->m_lastComment, 7046, 5); break;\n\tcase SOUND_PED_CAR_JACKED: GetPhrase(sfx, ped->m_lastComment, 7051, 8); break;\n\tcase SOUND_PED_ROBBED: GetPhrase(sfx, ped->m_lastComment, 7061, 2); break;\n\tcase SOUND_PED_ACCIDENTREACTION1: GetPhrase(sfx, ped->m_lastComment, 7067, 2); break;\n\tcase SOUND_PED_TAXI_WAIT: return 7069;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 7027, 11); break;\n\tcase SOUND_PED_FLEE_RUN: GetPhrase(sfx, ped->m_lastComment, 7063, 4); break;\n\tcase SOUND_PED_CRASH_VEHICLE: GetPhrase(sfx, ped->m_lastComment, 7038, 8); break;\n\tcase SOUND_PED_CRASH_CAR: GetPhrase(sfx, ped->m_lastComment, 7009, 8); break;\n\tcase SOUND_PED_ANNOYED_DRIVER: GetPhrase(sfx, ped->m_lastComment, 6992, 7); break;\n\tcase SOUND_PED_WAIT_DOUBLEBACK: GetPhrase(sfx, ped->m_lastComment, 7059, 2); break;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 6999, 10); break;\n\tcase SOUND_PED_CHAT: GetPhrase(sfx, ped->m_lastComment, 7017, 10); break;\n\tdefault: return GetGenericFemaleTalkSfx(ped, sound);\n\t}\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetBMYSTTalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_UP: GetPhrase(sfx, ped->m_lastComment, 6413, 6); break;\n\tcase SOUND_PED_CAR_JACKING: GetPhrase(sfx, ped->m_lastComment, 6427, 4); break;\n\tcase SOUND_PED_MUGGING: GetPhrase(sfx, ped->m_lastComment, 6433, 4); break;\n\tcase SOUND_PED_CAR_JACKED: GetPhrase(sfx, ped->m_lastComment, 6419, 8); break;\n\tcase SOUND_PED_ROBBED: GetPhrase(sfx, ped->m_lastComment, 6431, 2); break;\n\tcase SOUND_PED_TAXI_WAIT: return 6437;\n\tcase SOUND_PED_ATTACK: GetPhrase(sfx, ped->m_lastComment, 6400, 6); break;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 6392, 8); break;\n\tcase SOUND_PED_CRASH_VEHICLE: GetPhrase(sfx, ped->m_lastComment, 6406, 7); break;\n\tcase SOUND_PED_CRASH_CAR: GetPhrase(sfx, ped->m_lastComment, 6371, 9); break;\n\tcase SOUND_PED_ANNOYED_DRIVER: GetPhrase(sfx, ped->m_lastComment, 6352, 8); break;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 6360, 11); break;\n\tcase SOUND_PED_CHAT: GetPhrase(sfx, ped->m_lastComment, 6380, 12); break;\n\tdefault: return GetGenericMaleTalkSfx(ped, sound);\n\t}\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetBMOSTTalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_COWER: GetPhrase(sfx, ped->m_lastComment, 4292, 9); break;\n\tcase SOUND_PED_ROBBED: GetPhrase(sfx, ped->m_lastComment, 4307, 4); break;\n\tcase SOUND_PED_ACCIDENTREACTION1: return 4311;\n\tcase SOUND_PED_TAXI_WAIT: return 4312;\n\tcase SOUND_PED_ATTACK: GetPhrase(sfx, ped->m_lastComment, 4272, 7); break;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 4258, 8); break;\n\tcase SOUND_PED_CRASH_VEHICLE: GetPhrase(sfx, ped->m_lastComment, 4279, 13); break;\n\tcase SOUND_PED_CRASH_CAR: GetPhrase(sfx, ped->m_lastComment, 4232, 8); break;\n\tcase SOUND_PED_WAIT_DOUBLEBACK: GetPhrase(sfx, ped->m_lastComment, 4301, 6); break;\n\tcase SOUND_PED_CHAT_SEXY: GetPhrase(sfx, ped->m_lastComment, 4266, 6); break;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 4215, 17); break;\n\tcase SOUND_PED_CHAT: GetPhrase(sfx, ped->m_lastComment, 4240, 18); break;\n\tdefault: return GetGenericMaleTalkSfx(ped, sound);\n\t}\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetBFYRITalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_COWER: GetPhrase(sfx, ped->m_lastComment, 6161, 4); break;\n\tcase SOUND_PED_CAR_JACKING: GetPhrase(sfx, ped->m_lastComment, 6173, 4); break;\n\tcase SOUND_PED_CAR_JACKED: GetPhrase(sfx, ped->m_lastComment, 6165, 8); break;\n\tcase SOUND_PED_ROBBED: GetPhrase(sfx, ped->m_lastComment, 6179, 3); break;\n\tcase SOUND_PED_ACCIDENTREACTION1: GetPhrase(sfx, ped->m_lastComment, 6188, 2); break;\n\tcase SOUND_PED_TAXI_WAIT: return 6194;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 6143, 8); break;\n\tcase SOUND_PED_FLEE_RUN: GetPhrase(sfx, ped->m_lastComment, 6182, 6); break;\n\tcase SOUND_PED_CRASH_VEHICLE: GetPhrase(sfx, ped->m_lastComment, 6154, 7); break;\n\tcase SOUND_PED_CRASH_CAR: GetPhrase(sfx, ped->m_lastComment, 6135, 8); break;\n\tcase SOUND_PED_ANNOYED_DRIVER: GetPhrase(sfx, ped->m_lastComment, 6117, 9); break;\n\tcase SOUND_PED_WAIT_DOUBLEBACK: GetPhrase(sfx, ped->m_lastComment, 6177, 2); break;\n\tcase SOUND_153: GetPhrase(sfx, ped->m_lastComment, 6151, 3); break;\n\tcase SOUND_PED_CHAT_EVENT: GetPhrase(sfx, ped->m_lastComment, 6190, 4); break;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 6126, 9); break;\n\tdefault: return GetGenericFemaleTalkSfx(ped, sound);\n\t}\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetBFORITalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_COWER: GetPhrase(sfx, ped->m_lastComment, 7110, 5); break;\n\tcase SOUND_PED_CAR_JACKED: GetPhrase(sfx, ped->m_lastComment, 7115, 4); break;\n\tcase SOUND_PED_ROBBED: GetPhrase(sfx, ped->m_lastComment, 7121, 2); break;\n\tcase SOUND_PED_ACCIDENTREACTION1: return 7127;\n\tcase SOUND_PED_TAXI_WAIT: GetPhrase(sfx, ped->m_lastComment, 7130, 2); break;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 7094, 9); break;\n\tcase SOUND_PED_FLEE_RUN: GetPhrase(sfx, ped->m_lastComment, 7123, 4); break;\n\tcase SOUND_PED_CRASH_VEHICLE: GetPhrase(sfx, ped->m_lastComment, 7103, 7); break;\n\tcase SOUND_PED_CRASH_CAR: GetPhrase(sfx, ped->m_lastComment, 7087, 7); break;\n\tcase SOUND_PED_ANNOYED_DRIVER: GetPhrase(sfx, ped->m_lastComment, 7070, 8); break;\n\tcase SOUND_PED_WAIT_DOUBLEBACK: GetPhrase(sfx, ped->m_lastComment, 7119, 2); break;\n\tcase SOUND_PED_CHAT_EVENT: GetPhrase(sfx, ped->m_lastComment, 7128, 2); break;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 7078, 9); break;\n\tdefault: return GetGenericFemaleTalkSfx(ped, sound);\n\t}\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetBMYRITalkSfx(CPed *ped, int16 sound)\n{\n\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_COWER: GetPhrase(sfx, ped->m_lastComment, 5430, 7); break;\n\tcase SOUND_PED_CAR_JACKED: GetPhrase(sfx, ped->m_lastComment, 5437, 4); break;\n\tcase SOUND_PED_ROBBED: GetPhrase(sfx, ped->m_lastComment, 5443, 2); break;\n\tcase SOUND_PED_ACCIDENTREACTION1: return 5449;\n\tcase SOUND_PED_TAXI_WAIT: return 5453;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 5414, 8); break;\n\tcase SOUND_PED_FLEE_RUN: GetPhrase(sfx, ped->m_lastComment, 5445, 4); break;\n\tcase SOUND_PED_CRASH_VEHICLE: GetPhrase(sfx, ped->m_lastComment, 5423, 7); break;\n\tcase SOUND_PED_CRASH_CAR: GetPhrase(sfx, ped->m_lastComment, 5407, 7); break;\n\tcase SOUND_PED_ANNOYED_DRIVER: GetPhrase(sfx, ped->m_lastComment, 5394, 6); break;\n\tcase SOUND_PED_WAIT_DOUBLEBACK: GetPhrase(sfx, ped->m_lastComment, 5441, 2); break;\n\tcase SOUND_PED_CHAT_SEXY: return 5422;\n\tcase SOUND_PED_CHAT_EVENT: GetPhrase(sfx, ped->m_lastComment, 5450, 3); break;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 5400, 7); break;\n\tdefault: return GetGenericMaleTalkSfx(ped, sound);\n\t}\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetBFYBETalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_UP: GetPhrase(sfx, ped->m_lastComment, 6255, 6); break;\n\tcase SOUND_PED_CAR_JACKED: GetPhrase(sfx, ped->m_lastComment, 6261, 8); break;\n\tcase SOUND_PED_ROBBED: GetPhrase(sfx, ped->m_lastComment, 6273, 5); break;\n\tcase SOUND_PED_ACCIDENTREACTION1: GetPhrase(sfx, ped->m_lastComment, 6284, 2); break;\n\tcase SOUND_PED_TAXI_WAIT: GetPhrase(sfx, ped->m_lastComment, 6290, 3); break;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 6233, 10); break;\n\tcase SOUND_PED_FLEE_RUN: GetPhrase(sfx, ped->m_lastComment, 6278, 6); break;\n\tcase SOUND_PED_CRASH_VEHICLE: GetPhrase(sfx, ped->m_lastComment, 6247, 8); break;\n\tcase SOUND_PED_CRASH_CAR: GetPhrase(sfx, ped->m_lastComment, 6207, 8); break;\n\tcase SOUND_PED_ANNOYED_DRIVER: GetPhrase(sfx, ped->m_lastComment, 6195, 12); break;\n\tcase SOUND_PED_WAIT_DOUBLEBACK: GetPhrase(sfx, ped->m_lastComment, 6269, 4); break;\n\tcase SOUND_PED_CHAT_SEXY: GetPhrase(sfx, ped->m_lastComment, 6243, 4); break;\n\tcase SOUND_PED_CHAT_EVENT: GetPhrase(sfx, ped->m_lastComment, 6286, 4); break;\n\tcase SOUND_PED_CHAT: GetPhrase(sfx, ped->m_lastComment, 6217, 16); break;\n\tdefault: return GetGenericFemaleTalkSfx(ped, sound);\n\t}\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetBMYBETalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_UP: GetPhrase(sfx, ped->m_lastComment, 956, 4); break;\n\tcase SOUND_PED_CAR_JACKING: GetPhrase(sfx, ped->m_lastComment, 966, 3); break;\n\tcase SOUND_PED_CAR_JACKED: GetPhrase(sfx, ped->m_lastComment, 960, 6); break;\n\tcase SOUND_PED_ROBBED: return 970;\n\tcase SOUND_PED_ACCIDENTREACTION1: return 971;\n\tcase SOUND_PED_TAXI_WAIT: return 972;\n\tcase SOUND_PED_ATTACK: GetPhrase(sfx, ped->m_lastComment, 940, 8); break;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 928, 10); break;\n\tcase SOUND_PED_CRASH_VEHICLE: GetPhrase(sfx, ped->m_lastComment, 948, 8); break;\n\tcase SOUND_PED_CRASH_CAR: GetPhrase(sfx, ped->m_lastComment, 910, 8); break;\n\tcase SOUND_PED_ANNOYED_DRIVER: GetPhrase(sfx, ped->m_lastComment, 892, 8); break;\n\tcase SOUND_PED_WAIT_DOUBLEBACK: return 969;\n\tcase SOUND_PED_CHAT_SEXY: GetPhrase(sfx, ped->m_lastComment, 938, 2); break;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 900, 10); break;\n\tcase SOUND_PED_CHAT: GetPhrase(sfx, ped->m_lastComment, 918, 10); break;\n\tdefault: return GetGenericMaleTalkSfx(ped, sound);\n\t}\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetBFOBETalkSfx(CPed *ped, int16 sound)\n{\n\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_COWER: GetPhrase(sfx, ped->m_lastComment, 8213, 5); break;\n\tcase SOUND_PED_CAR_JACKING: GetPhrase(sfx, ped->m_lastComment, 8223, 4); break;\n\tcase SOUND_PED_CAR_JACKED: GetPhrase(sfx, ped->m_lastComment, 8218, 5); break;\n\tcase SOUND_PED_ROBBED: GetPhrase(sfx, ped->m_lastComment, 8227, 2); break;\n\tcase SOUND_PED_TAXI_WAIT: return 8231;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 8197, 9); break;\n\tcase SOUND_PED_CRASH_VEHICLE: GetPhrase(sfx, ped->m_lastComment, 8206, 7); break;\n\tcase SOUND_PED_CRASH_CAR: GetPhrase(sfx, ped->m_lastComment, 8182, 7); break;\n\tcase SOUND_PED_ANNOYED_DRIVER: GetPhrase(sfx, ped->m_lastComment, 8166, 8); break;\n\tcase SOUND_PED_CHAT_EVENT: GetPhrase(sfx, ped->m_lastComment, 8229, 2); break;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 8174, 8); break;\n\tcase SOUND_PED_CHAT: GetPhrase(sfx, ped->m_lastComment, 8189, 8); break;\n\tdefault: return GetGenericFemaleTalkSfx(ped, sound);\n\t}\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetBMOBETalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_COWER: GetPhrase(sfx, ped->m_lastComment, 7611, 5); break;\n\tcase SOUND_PED_CAR_JACKED: GetPhrase(sfx, ped->m_lastComment, 7616, 6); break;\n\tcase SOUND_PED_ROBBED: GetPhrase(sfx, ped->m_lastComment, 7622, 4); break;\n\tcase SOUND_PED_ACCIDENTREACTION1: GetPhrase(sfx, ped->m_lastComment, 7626, 3); break;\n\tcase SOUND_PED_TAXI_WAIT: return 7632;\n\tcase SOUND_PED_ATTACK: GetPhrase(sfx, ped->m_lastComment, 7594, 10); break;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 7583, 11); break;\n\tcase SOUND_PED_CRASH_VEHICLE: GetPhrase(sfx, ped->m_lastComment, 7604, 7); break;\n\tcase SOUND_PED_CRASH_CAR: GetPhrase(sfx, ped->m_lastComment, 7564, 9); break;\n\tcase SOUND_PED_CHAT_EVENT: GetPhrase(sfx, ped->m_lastComment, 7629, 3); break;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 7559, 5); break;\n\tcase SOUND_PED_CHAT: GetPhrase(sfx, ped->m_lastComment, 7573, 10); break;\n\tdefault: return GetGenericMaleTalkSfx(ped, sound);\n\t}\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetBMYBUTalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_COWER: GetPhrase(sfx, ped->m_lastComment, 5500, 5); break;\n\tcase SOUND_PED_CAR_JACKED: GetPhrase(sfx, ped->m_lastComment, 5507, 6); break;\n\tcase SOUND_PED_ROBBED: GetPhrase(sfx, ped->m_lastComment, 5513, 2); break;\n\tcase SOUND_PED_ACCIDENTREACTION1: return 5515;\n\tcase SOUND_PED_UNK_126: GetPhrase(sfx, ped->m_lastComment, 5505, 2); break;\n\tcase SOUND_PED_TAXI_WAIT: return 5518;\n\tcase SOUND_PED_ATTACK: GetPhrase(sfx, ped->m_lastComment, 5488, 5); break;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 5476, 10); break;\n\tcase SOUND_PED_CRASH_VEHICLE: GetPhrase(sfx, ped->m_lastComment, 5493, 7); break;\n\tcase SOUND_PED_CRASH_CAR: GetPhrase(sfx, ped->m_lastComment, 5469, 7); break;\n\tcase SOUND_PED_ANNOYED_DRIVER: GetPhrase(sfx, ped->m_lastComment, 5454, 8); break;\n\tcase SOUND_PED_CHAT_SEXY: GetPhrase(sfx, ped->m_lastComment, 5486, 2); break;\n\tcase SOUND_PED_CHAT_EVENT: GetPhrase(sfx, ped->m_lastComment, 5516, 2); break;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 5462, 7); break;\n\tdefault: return GetGenericMaleTalkSfx(ped, sound);\n\t}\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetBFYPRTalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_UP: GetPhrase(sfx, ped->m_lastComment, 5369, 5); break;\n\tcase SOUND_PED_ROBBED: GetPhrase(sfx, ped->m_lastComment, 5374, 2); break;\n\tcase SOUND_PED_ACCIDENTREACTION1: return 5376;\n\tcase SOUND_PED_PLAYER_BEFORESEX: GetPhrase(sfx, ped->m_lastComment, 5362, 7); break;\n\tcase SOUND_PED_TAXI_WAIT: GetPhrase(sfx, ped->m_lastComment, 5392, 2); break;\n\tcase SOUND_PED_ATTACK: GetPhrase(sfx, ped->m_lastComment, 5355, 7); break;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 5348, 7); break;\n\tcase SOUND_PED_SOLICIT: GetPhrase(sfx, ped->m_lastComment, 5379, 13); break;\n\tcase SOUND_PED_CHAT_EVENT: GetPhrase(sfx, ped->m_lastComment, 5377, 2); break;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 5324, 11); break;\n\tcase SOUND_PED_CHAT: GetPhrase(sfx, ped->m_lastComment, 5335, 13); break;\n\tdefault: return GetGenericFemaleTalkSfx(ped, sound);\n\t}\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetBFOTRTalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_UP: GetPhrase(sfx, ped->m_lastComment, 5232, 6); break;\n\tcase SOUND_PED_MUGGING: GetPhrase(sfx, ped->m_lastComment, 5240, 3); break;\n\tcase SOUND_PED_ROBBED: GetPhrase(sfx, ped->m_lastComment, 5238, 2); break;\n\tcase SOUND_PED_ACCIDENTREACTION1: return 5243;\n\tcase SOUND_PED_TAXI_WAIT: return 5252;\n\tcase SOUND_PED_ATTACK: GetPhrase(sfx, ped->m_lastComment, 5226, 6); break;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 5217, 9); break;\n\tcase SOUND_PED_SOLICIT: GetPhrase(sfx, ped->m_lastComment, 5247, 5); break;\n\tcase SOUND_PED_CHAT_EVENT: GetPhrase(sfx, ped->m_lastComment, 5244, 3); break;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 5192, 10); break;\n\tcase SOUND_PED_CHAT: GetPhrase(sfx, ped->m_lastComment, 5202, 15); break;\n\tdefault: return GetGenericFemaleTalkSfx(ped, sound);\n\t}\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetBMOTRTalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_UP: GetPhrase(sfx, ped->m_lastComment, 6327, 5); break;\n\tcase SOUND_PED_ACCIDENTREACTION1: GetPhrase(sfx, ped->m_lastComment, 6343, 1); break;\n\tcase SOUND_PED_UNK_126: GetPhrase(sfx, ped->m_lastComment, 6332, 4); break;\n\tcase SOUND_PED_TAXI_WAIT: return 6351;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 6313, 11); break;\n\tcase SOUND_PED_FLEE_RUN: GetPhrase(sfx, ped->m_lastComment, 6336, 7); break;\n\tcase SOUND_PED_SOLICIT: GetPhrase(sfx, ped->m_lastComment, 6344, 7); break;\n\tcase SOUND_PED_CHAT_SEXY: GetPhrase(sfx, ped->m_lastComment, 6324, 3); break;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 6293, 10); break;\n\tcase SOUND_PED_CHAT: GetPhrase(sfx, ped->m_lastComment, 6303, 10); break;\n\tdefault: return GetGenericMaleTalkSfx(ped, sound);\n\t}\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetBMYPITalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_UP: GetPhrase(sfx, ped->m_lastComment, 4033, 5); break;\n\tcase SOUND_PED_CAR_JACKING: GetPhrase(sfx, ped->m_lastComment, 4044, 4); break;\n\tcase SOUND_PED_CAR_JACKED: GetPhrase(sfx, ped->m_lastComment, 4038, 6); break;\n\tcase SOUND_PED_ROBBED: return 4048;\n\tcase SOUND_PED_ACCIDENTREACTION1: return 4049;\n\tcase SOUND_PED_TAXI_WAIT: GetPhrase(sfx, ped->m_lastComment, 4050, 2); break;\n\tcase SOUND_PED_ATTACK: GetPhrase(sfx, ped->m_lastComment, 4012, 8); break;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 3998, 10); break;\n\tcase SOUND_PED_CRASH_VEHICLE: GetPhrase(sfx, ped->m_lastComment, 4020, 13); break;\n\tcase SOUND_PED_CRASH_CAR: GetPhrase(sfx, ped->m_lastComment, 3993, 5); break;\n\tcase SOUND_PED_ANNOYED_DRIVER: GetPhrase(sfx, ped->m_lastComment, 3978, 6); break;\n\tcase SOUND_PED_CHAT_SEXY: GetPhrase(sfx, ped->m_lastComment, 4008, 4); break;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 3984, 9); break;\n\tdefault: return GetGenericMaleTalkSfx(ped, sound);\n\t}\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetBMYBBTalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_UP: GetPhrase(sfx, ped->m_lastComment, 639, 5); break;\n\tcase SOUND_PED_CAR_JACKING: GetPhrase(sfx, ped->m_lastComment, 659, 9); break;\n\tcase SOUND_PED_MUGGING: GetPhrase(sfx, ped->m_lastComment, 691, 8); break;\n\tcase SOUND_PED_CAR_JACKED: GetPhrase(sfx, ped->m_lastComment, 648, 11); break;\n\tcase SOUND_PED_ROBBED: GetPhrase(sfx, ped->m_lastComment, 686, 5); break;\n\tcase SOUND_PED_ACCIDENTREACTION1: GetPhrase(sfx, ped->m_lastComment, 699, 6); break;\n\tcase SOUND_PED_UNK_126: GetPhrase(sfx, ped->m_lastComment, 644, 4); break;\n\tcase SOUND_PED_TAXI_WAIT: GetPhrase(sfx, ped->m_lastComment, 711, 3); break;\n\tcase SOUND_PED_ATTACK: GetPhrase(sfx, ped->m_lastComment, 618, 12); break;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 584, 18); break;\n\tcase SOUND_PED_CRASH_VEHICLE: GetPhrase(sfx, ped->m_lastComment, 630, 9); break;\n\tcase SOUND_PED_CRASH_CAR: GetPhrase(sfx, ped->m_lastComment, 554, 9); break;\n\tcase SOUND_PED_ANNOYED_DRIVER: GetPhrase(sfx, ped->m_lastComment, 524, 13); break;\n\tcase SOUND_PED_149: GetPhrase(sfx, ped->m_lastComment, 668, 16); break;\n\tcase SOUND_PED_WAIT_DOUBLEBACK: GetPhrase(sfx, ped->m_lastComment, 684, 2); break;\n\tcase SOUND_PED_CHAT_SEXY: GetPhrase(sfx, ped->m_lastComment, 602, 16); break;\n\tcase SOUND_PED_CHAT_EVENT: GetPhrase(sfx, ped->m_lastComment, 705, 6); break;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 537, 17); break;\n\tcase SOUND_PED_CHAT: GetPhrase(sfx, ped->m_lastComment, 563, 21); break;\n\tdefault: return GetGenericMaleTalkSfx(ped, sound);\n\t}\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetWMYCRTalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_UP: GetPhrase(sfx, ped->m_lastComment, 5056, 5); break;\n\tcase SOUND_PED_CAR_JACKING: GetPhrase(sfx, ped->m_lastComment, 5061, 6); break;\n\tcase SOUND_PED_MUGGING: GetPhrase(sfx, ped->m_lastComment, 5070, 5); break;\n\tcase SOUND_PED_ROBBED: GetPhrase(sfx, ped->m_lastComment, 5067, 3); break;\n\tcase SOUND_PED_TAXI_WAIT: return 5075;\n\tcase SOUND_PED_ATTACK: GetPhrase(sfx, ped->m_lastComment, 5040, 7); break;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 5030, 10); break;\n\tcase SOUND_PED_CRASH_VEHICLE: GetPhrase(sfx, ped->m_lastComment, 5047, 9); break;\n\tcase SOUND_PED_CRASH_CAR: GetPhrase(sfx, ped->m_lastComment, 5021, 9); break;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 5003, 18); break;\n\tdefault: return GetGenericMaleTalkSfx(ped, sound);\n\t}\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetWFYSTTalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_UP: GetPhrase(sfx, ped->m_lastComment, 8445, 5); break;\n\tcase SOUND_PED_CAR_JACKING: GetPhrase(sfx, ped->m_lastComment, 8456, 4); break;\n\tcase SOUND_PED_MUGGING: GetPhrase(sfx, ped->m_lastComment, 8463, 4); break;\n\tcase SOUND_PED_CAR_JACKED: GetPhrase(sfx, ped->m_lastComment, 8450, 6); break;\n\tcase SOUND_PED_ROBBED: GetPhrase(sfx, ped->m_lastComment, 8461, 2); break;\n\tcase SOUND_PED_ACCIDENTREACTION1: return 8467;\n\tcase SOUND_PED_TAXI_WAIT: return 8468;\n\tcase SOUND_PED_ATTACK: GetPhrase(sfx, ped->m_lastComment, 8430, 7); break;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 8420, 10); break;\n\tcase SOUND_PED_CRASH_VEHICLE: GetPhrase(sfx, ped->m_lastComment, 8437, 8); break;\n\tcase SOUND_PED_CRASH_CAR: GetPhrase(sfx, ped->m_lastComment, 8402, 8); break;\n\tcase SOUND_PED_ANNOYED_DRIVER: GetPhrase(sfx, ped->m_lastComment, 8386, 6); break;\n\tcase SOUND_PED_WAIT_DOUBLEBACK: return 8460;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 8392, 10); break;\n\tcase SOUND_PED_CHAT: GetPhrase(sfx, ped->m_lastComment, 8410, 10); break;\n\tdefault: return GetGenericFemaleTalkSfx(ped, sound);\n\t}\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetWFOSTTalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_COWER: GetPhrase(sfx, ped->m_lastComment, 8354, 4); break;\n\tcase SOUND_PED_CAR_JACKED: GetPhrase(sfx, ped->m_lastComment, 8358, 8); break;\n\tcase SOUND_PED_ROBBED: GetPhrase(sfx, ped->m_lastComment, 8369, 5); break;\n\tcase SOUND_PED_ACCIDENTREACTION1: GetPhrase(sfx, ped->m_lastComment, 8381, 4); break;\n\tcase SOUND_PED_TAXI_WAIT: return 8385;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 8332, 12); break;\n\tcase SOUND_PED_FLEE_RUN: GetPhrase(sfx, ped->m_lastComment, 8374, 7); break;\n\tcase SOUND_PED_CRASH_VEHICLE: GetPhrase(sfx, ped->m_lastComment, 8344, 10); break;\n\tcase SOUND_PED_CRASH_CAR: GetPhrase(sfx, ped->m_lastComment, 8305, 11); break;\n\tcase SOUND_PED_ANNOYED_DRIVER: GetPhrase(sfx, ped->m_lastComment, 8274, 12); break;\n\tcase SOUND_PED_WAIT_DOUBLEBACK: GetPhrase(sfx, ped->m_lastComment, 8366, 3); break;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 8286, 19); break;\n\tcase SOUND_PED_CHAT: GetPhrase(sfx, ped->m_lastComment, 8316, 16); break;\n\tdefault: return GetGenericFemaleTalkSfx(ped, sound);\n\t}\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetWMYSTTalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_COWER: GetPhrase(sfx, ped->m_lastComment, 3947, 5); break;\n\tcase SOUND_PED_MUGGING: GetPhrase(sfx, ped->m_lastComment, 3963, 5); break;\n\tcase SOUND_PED_CAR_JACKED: GetPhrase(sfx, ped->m_lastComment, 3955, 5); break;\n\tcase SOUND_PED_ROBBED: return 3962;\n\tcase SOUND_PED_ACCIDENTREACTION1: return 3975;\n\tcase SOUND_PED_UNK_126: GetPhrase(sfx, ped->m_lastComment, 3952, 3); break;\n\tcase SOUND_PED_TAXI_WAIT: GetPhrase(sfx, ped->m_lastComment, 3976, 2); break;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 3930, 10); break;\n\tcase SOUND_PED_FLEE_RUN: GetPhrase(sfx, ped->m_lastComment, 3968, 7); break;\n\tcase SOUND_PED_CRASH_VEHICLE: GetPhrase(sfx, ped->m_lastComment, 3942, 5); break;\n\tcase SOUND_PED_CRASH_CAR: GetPhrase(sfx, ped->m_lastComment, 3912, 8); break;\n\tcase SOUND_PED_ANNOYED_DRIVER: GetPhrase(sfx, ped->m_lastComment, 3893, 8); break;\n\tcase SOUND_PED_WAIT_DOUBLEBACK: GetPhrase(sfx, ped->m_lastComment, 3960, 2); break;\n\tcase SOUND_PED_CHAT_SEXY: GetPhrase(sfx, ped->m_lastComment, 3940, 2); break;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 3901, 11); break;\n\tcase SOUND_PED_CHAT: GetPhrase(sfx, ped->m_lastComment, 3920, 10); break;\n\tdefault: return GetGenericMaleTalkSfx(ped, sound);\n\t}\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetWMOSTTalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_UP: GetPhrase(sfx, ped->m_lastComment, 5170, 5); break;\n\tcase SOUND_PED_CAR_JACKED: GetPhrase(sfx, ped->m_lastComment, 5178, 4); break;\n\tcase SOUND_PED_ROBBED: GetPhrase(sfx, ped->m_lastComment, 5188, 2); break;\n\tcase SOUND_PED_ACCIDENTREACTION1: return 5190;\n\tcase SOUND_PED_UNK_126: GetPhrase(sfx, ped->m_lastComment, 5175, 3); break;\n\tcase SOUND_PED_TAXI_WAIT: return 5191;\n\tcase SOUND_PED_ATTACK: GetPhrase(sfx, ped->m_lastComment, 5155, 8); break;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 5145, 8); break;\n\tcase SOUND_PED_CRASH_VEHICLE: GetPhrase(sfx, ped->m_lastComment, 5163, 7); break;\n\tcase SOUND_PED_CRASH_CAR: GetPhrase(sfx, ped->m_lastComment, 5129, 7); break;\n\tcase SOUND_PED_ANNOYED_DRIVER: GetPhrase(sfx, ped->m_lastComment, 5111, 8); break;\n\tcase SOUND_PED_149: GetPhrase(sfx, ped->m_lastComment, 5182, 4); break;\n\tcase SOUND_PED_WAIT_DOUBLEBACK: GetPhrase(sfx, ped->m_lastComment, 5186, 2); break;\n\tcase SOUND_PED_CHAT_SEXY: GetPhrase(sfx, ped->m_lastComment, 5153, 2); break;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 5119, 10); break;\n\tcase SOUND_PED_CHAT: GetPhrase(sfx, ped->m_lastComment, 5136, 9); break;\n\tdefault: return GetGenericMaleTalkSfx(ped, sound);\n\t}\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetWFYRITalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_COWER: GetPhrase(sfx, ped->m_lastComment, 5299, 5); break;\n\tcase SOUND_PED_CAR_JACKED: GetPhrase(sfx, ped->m_lastComment, 5304, 7); break;\n\tcase SOUND_PED_ROBBED: GetPhrase(sfx, ped->m_lastComment, 5313, 2); break;\n\tcase SOUND_PED_ACCIDENTREACTION1: return 5320;\n\tcase SOUND_PED_TAXI_WAIT: return 5323;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 5280, 9); break;\n\tcase SOUND_PED_FLEE_RUN: GetPhrase(sfx, ped->m_lastComment, 5315, 5); break;\n\tcase SOUND_PED_CRASH_VEHICLE: GetPhrase(sfx, ped->m_lastComment, 5291, 8); break;\n\tcase SOUND_PED_CRASH_CAR: GetPhrase(sfx, ped->m_lastComment, 5271, 9); break;\n\tcase SOUND_PED_ANNOYED_DRIVER: GetPhrase(sfx, ped->m_lastComment, 5253, 8); break;\n\tcase SOUND_PED_WAIT_DOUBLEBACK: GetPhrase(sfx, ped->m_lastComment, 5311, 2); break;\n\tcase SOUND_153: GetPhrase(sfx, ped->m_lastComment, 5289, 2); break;\n\tcase SOUND_PED_CHAT_EVENT: GetPhrase(sfx, ped->m_lastComment, 5321, 2); break;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 5261, 10); break;\n\tdefault: return GetGenericFemaleTalkSfx(ped, sound);\n\t}\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetWFORITalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_COWER: GetPhrase(sfx, ped->m_lastComment, 7825, 6); break;\n\tcase SOUND_PED_CAR_JACKED: GetPhrase(sfx, ped->m_lastComment, 7831, 6); break;\n\tcase SOUND_PED_ROBBED: GetPhrase(sfx, ped->m_lastComment, 7839, 3); break;\n\tcase SOUND_PED_ACCIDENTREACTION1: return 7842;\n\tcase SOUND_PED_TAXI_WAIT: return 7846;\n\tcase SOUND_PED_ATTACK: GetPhrase(sfx, ped->m_lastComment, 7810, 7); break;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 7799, 11); break;\n\tcase SOUND_PED_CRASH_VEHICLE: GetPhrase(sfx, ped->m_lastComment, 7817, 8); break;\n\tcase SOUND_PED_CRASH_CAR: GetPhrase(sfx, ped->m_lastComment, 7789, 10); break;\n\tcase SOUND_PED_ANNOYED_DRIVER: GetPhrase(sfx, ped->m_lastComment, 7771, 7); break;\n\tcase SOUND_PED_WAIT_DOUBLEBACK: GetPhrase(sfx, ped->m_lastComment, 7837, 2); break;\n\tcase SOUND_PED_CHAT_EVENT: GetPhrase(sfx, ped->m_lastComment, 7843, 3); break;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 7778, 11); break;\n\tdefault: return GetGenericFemaleTalkSfx(ped, sound);\n\t}\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetWMYRITalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_COWER: GetPhrase(sfx, ped->m_lastComment, 4186, 8); break;\n\tcase SOUND_PED_CAR_JACKED: GetPhrase(sfx, ped->m_lastComment, 4194, 8); break;\n\tcase SOUND_PED_ACCIDENTREACTION1: return 4208;\n\tcase SOUND_PED_TAXI_WAIT: GetPhrase(sfx, ped->m_lastComment, 4213, 2); break;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 4163, 9); break;\n\tcase SOUND_PED_FLEE_RUN: GetPhrase(sfx, ped->m_lastComment, 4203, 5); break;\n\tcase SOUND_PED_CRASH_VEHICLE: GetPhrase(sfx, ped->m_lastComment, 4175, 11); break;\n\tcase SOUND_PED_CRASH_CAR: GetPhrase(sfx, ped->m_lastComment, 4144, 9); break;\n\tcase SOUND_PED_ANNOYED_DRIVER: GetPhrase(sfx, ped->m_lastComment, 4126, 10); break;\n\tcase SOUND_PED_WAIT_DOUBLEBACK: return 4202;\n\tcase SOUND_PED_CHAT_SEXY: GetPhrase(sfx, ped->m_lastComment, 4172, 3); break;\n\tcase SOUND_PED_CHAT_EVENT: GetPhrase(sfx, ped->m_lastComment, 4209, 4); break;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 4136, 8); break;\n\tdefault: return GetGenericMaleTalkSfx(ped, sound);\n\t}\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetWMORITalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_COWER: GetPhrase(sfx, ped->m_lastComment, 6668, 9); break;\n\tcase SOUND_PED_CAR_JACKED: GetPhrase(sfx, ped->m_lastComment, 6677, 6); break;\n\tcase SOUND_PED_ROBBED: GetPhrase(sfx, ped->m_lastComment, 6685, 4); break;\n\tcase SOUND_PED_ACCIDENTREACTION1: GetPhrase(sfx, ped->m_lastComment, 6701, 2); break;\n\tcase SOUND_PED_TAXI_WAIT: GetPhrase(sfx, ped->m_lastComment, 6707, 2); break;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 6647, 10); break;\n\tcase SOUND_PED_FLEE_RUN: GetPhrase(sfx, ped->m_lastComment, 6689, 12); break;\n\tcase SOUND_PED_CRASH_VEHICLE: GetPhrase(sfx, ped->m_lastComment, 6660, 8); break;\n\tcase SOUND_PED_CRASH_CAR: GetPhrase(sfx, ped->m_lastComment, 6641, 6); break;\n\tcase SOUND_PED_ANNOYED_DRIVER: GetPhrase(sfx, ped->m_lastComment, 6617, 10); break;\n\tcase SOUND_PED_WAIT_DOUBLEBACK: GetPhrase(sfx, ped->m_lastComment, 6683, 2); break;\n\tcase SOUND_PED_CHAT_SEXY: GetPhrase(sfx, ped->m_lastComment, 6657, 3); break;\n\tcase SOUND_PED_CHAT_EVENT: GetPhrase(sfx, ped->m_lastComment, 6703, 4); break;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 6627, 14); break;\n\tdefault: return GetGenericMaleTalkSfx(ped, sound);\n\t}\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetWFYBETalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_COWER: GetPhrase(sfx, ped->m_lastComment, 7752, 5); break;\n\tcase SOUND_PED_CAR_JACKED: GetPhrase(sfx, ped->m_lastComment, 7757, 4); break;\n\tcase SOUND_PED_ACCIDENTREACTION1: return 7766;\n\tcase SOUND_PED_TAXI_WAIT: return 7770;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 7738, 8); break;\n\tcase SOUND_PED_FLEE_RUN: GetPhrase(sfx, ped->m_lastComment, 7761, 5); break;\n\tcase SOUND_PED_CRASH_VEHICLE: GetPhrase(sfx, ped->m_lastComment, 7746, 6); break;\n\tcase SOUND_PED_CRASH_CAR: GetPhrase(sfx, ped->m_lastComment, 7722, 6); break;\n\tcase SOUND_PED_ANNOYED_DRIVER: GetPhrase(sfx, ped->m_lastComment, 7704, 7); break;\n\tcase SOUND_PED_CHAT_EVENT: GetPhrase(sfx, ped->m_lastComment, 7767, 3); break;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 7711, 11); break;\n\tcase SOUND_PED_CHAT: GetPhrase(sfx, ped->m_lastComment, 7728, 10); break;\n\tdefault: return GetGenericFemaleTalkSfx(ped, sound);\n\t}\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetWMYBETalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_COWER: GetPhrase(sfx, ped->m_lastComment, 8127, 8); break;\n\tcase SOUND_PED_CAR_JACKING: GetPhrase(sfx, ped->m_lastComment, 8142, 3); break;\n\tcase SOUND_PED_CAR_JACKED: GetPhrase(sfx, ped->m_lastComment, 8135, 7); break;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 8105, 12); break;\n\tcase SOUND_PED_FLEE_RUN: GetPhrase(sfx, ped->m_lastComment, 8155, 5); break;\n\tcase SOUND_PED_CRASH_VEHICLE: GetPhrase(sfx, ped->m_lastComment, 8119, 8); break;\n\tcase SOUND_PED_CRASH_CAR: GetPhrase(sfx, ped->m_lastComment, 8086, 8); break;\n\tcase SOUND_PED_ANNOYED_DRIVER: GetPhrase(sfx, ped->m_lastComment, 8063, 9); break;\n\tcase SOUND_PED_149: GetPhrase(sfx, ped->m_lastComment, 8145, 7); break;\n\tcase SOUND_PED_WAIT_DOUBLEBACK: GetPhrase(sfx, ped->m_lastComment, 8152, 3); break;\n\tcase SOUND_PED_CHAT_SEXY: GetPhrase(sfx, ped->m_lastComment, 8117, 2); break;\n\tcase SOUND_PED_CHAT_EVENT: GetPhrase(sfx, ped->m_lastComment, 8160, 6); break;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 8072, 14); break;\n\tcase SOUND_PED_CHAT: GetPhrase(sfx, ped->m_lastComment, 8094, 11); break;\n\tdefault: return GetGenericMaleTalkSfx(ped, sound);\n\t}\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetWFOBETalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_COWER: GetPhrase(sfx, ped->m_lastComment, 6093, 5); break;\n\tcase SOUND_PED_CAR_JACKED: GetPhrase(sfx, ped->m_lastComment, 6098, 4); break;\n\tcase SOUND_PED_ACCIDENTREACTION1: GetPhrase(sfx, ped->m_lastComment, 6109, 3); break;\n\tcase SOUND_PED_TAXI_WAIT: GetPhrase(sfx, ped->m_lastComment, 6115, 2); break;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 6075, 8); break;\n\tcase SOUND_PED_FLEE_RUN: GetPhrase(sfx, ped->m_lastComment, 6102, 7); break;\n\tcase SOUND_PED_CRASH_VEHICLE: GetPhrase(sfx, ped->m_lastComment, 6083, 10); break;\n\tcase SOUND_PED_CRASH_CAR: GetPhrase(sfx, ped->m_lastComment, 6058, 7); break;\n\tcase SOUND_PED_ANNOYED_DRIVER: GetPhrase(sfx, ped->m_lastComment, 6040, 8); break;\n\tcase SOUND_PED_CHAT_EVENT: GetPhrase(sfx, ped->m_lastComment, 6112, 3); break;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 6048, 10); break;\n\tcase SOUND_PED_CHAT: GetPhrase(sfx, ped->m_lastComment, 6065, 10); break;\n\tdefault: return GetGenericFemaleTalkSfx(ped, sound);\n\t}\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetWMOBETalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_COWER: GetPhrase(sfx, ped->m_lastComment, 3759, 5); break;\n\tcase SOUND_PED_CAR_JACKING: GetPhrase(sfx, ped->m_lastComment, 3772, 4); break;\n\tcase SOUND_PED_MUGGING: GetPhrase(sfx, ped->m_lastComment, 3792, 6); break;\n\tcase SOUND_PED_CAR_JACKED: GetPhrase(sfx, ped->m_lastComment, 3764, 8); break;\n\tcase SOUND_PED_ACCIDENTREACTION1: GetPhrase(sfx, ped->m_lastComment, 3802, 2); break;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 3742, 8); break;\n\tcase SOUND_PED_FLEE_RUN: GetPhrase(sfx, ped->m_lastComment, 3798, 4); break;\n\tcase SOUND_PED_CRASH_VEHICLE: GetPhrase(sfx, ped->m_lastComment, 3752, 7); break;\n\tcase SOUND_PED_CRASH_CAR: GetPhrase(sfx, ped->m_lastComment, 3724, 8); break;\n\tcase SOUND_PED_ANNOYED_DRIVER: GetPhrase(sfx, ped->m_lastComment, 3706, 6); break;\n\tcase SOUND_PED_149: GetPhrase(sfx, ped->m_lastComment, 3776, 16); break;\n\tcase SOUND_PED_CHAT_SEXY: GetPhrase(sfx, ped->m_lastComment, 3750, 2); break;\n\tcase SOUND_PED_CHAT_EVENT: GetPhrase(sfx, ped->m_lastComment, 3804, 2); break;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 3712, 12); break;\n\tcase SOUND_PED_CHAT: GetPhrase(sfx, ped->m_lastComment, 3732, 10); break;\n\tdefault: return GetGenericMaleTalkSfx(ped, sound);\n\t}\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetWMYCWTalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_COWER: GetPhrase(sfx, ped->m_lastComment, 5650, 6); break;\n\tcase SOUND_PED_CAR_JACKING: GetPhrase(sfx, ped->m_lastComment, 5670, 4); break;\n\tcase SOUND_PED_CAR_JACKED: GetPhrase(sfx, ped->m_lastComment, 5659, 6); break;\n\tcase SOUND_PED_ROBBED: return 5676;\n\tcase SOUND_PED_TAXI_WAIT: return 5677;\n\tcase SOUND_PED_ATTACK: GetPhrase(sfx, ped->m_lastComment, 5635, 8); break;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 5622, 10); break;\n\tcase SOUND_PED_CRASH_VEHICLE: GetPhrase(sfx, ped->m_lastComment, 5643, 7); break;\n\tcase SOUND_PED_CRASH_CAR: GetPhrase(sfx, ped->m_lastComment, 5598, 9); break;\n\tcase SOUND_PED_ANNOYED_DRIVER: GetPhrase(sfx, ped->m_lastComment, 5580, 9); break;\n\tcase SOUND_PED_149: GetPhrase(sfx, ped->m_lastComment, 5665, 5); break;\n\tcase SOUND_PED_WAIT_DOUBLEBACK: GetPhrase(sfx, ped->m_lastComment, 5674, 2); break;\n\tcase SOUND_PED_CHAT_SEXY: GetPhrase(sfx, ped->m_lastComment, 5632, 3); break;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 5589, 9); break;\n\tcase SOUND_PED_CHAT: GetPhrase(sfx, ped->m_lastComment, 5607, 15); break;\n\tdefault: return GetGenericMaleTalkSfx(ped, sound);\n\t}\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetWMYGOTalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_COWER: GetPhrase(sfx, ped->m_lastComment, 7679, 5); break;\n\tcase SOUND_PED_CAR_JACKED: GetPhrase(sfx, ped->m_lastComment, 7684, 6); break;\n\tcase SOUND_PED_ROBBED: GetPhrase(sfx, ped->m_lastComment, 7690, 2); break;\n\tcase SOUND_PED_ACCIDENTREACTION1: return 7698;\n\tcase SOUND_PED_TAXI_WAIT: GetPhrase(sfx, ped->m_lastComment, 7701, 3); break;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 7659, 11); break;\n\tcase SOUND_PED_FLEE_RUN: GetPhrase(sfx, ped->m_lastComment, 7692, 6); break;\n\tcase SOUND_PED_CRASH_VEHICLE: GetPhrase(sfx, ped->m_lastComment, 7672, 7); break;\n\tcase SOUND_PED_CRASH_CAR: GetPhrase(sfx, ped->m_lastComment, 7642, 7); break;\n\tcase SOUND_PED_CHAT_SEXY: GetPhrase(sfx, ped->m_lastComment, 7670, 2); break;\n\tcase SOUND_PED_CHAT_EVENT: GetPhrase(sfx, ped->m_lastComment, 7699, 2); break;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 7633, 9); break;\n\tcase SOUND_PED_CHAT: GetPhrase(sfx, ped->m_lastComment, 7649, 10); break;\n\tdefault: return GetGenericMaleTalkSfx(ped, sound);\n\t}\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetWFOGOTalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_COWER: GetPhrase(sfx, ped->m_lastComment, 7904, 5); break;\n\tcase SOUND_PED_CAR_JACKED: GetPhrase(sfx, ped->m_lastComment, 7909, 6); break;\n\tcase SOUND_PED_ROBBED: GetPhrase(sfx, ped->m_lastComment, 7915, 2); break;\n\tcase SOUND_PED_ACCIDENTREACTION1: return 7919;\n\tcase SOUND_PED_ATTACK: GetPhrase(sfx, ped->m_lastComment, 7883, 14); break;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 7874, 9); break;\n\tcase SOUND_PED_FLEE_RUN: GetPhrase(sfx, ped->m_lastComment, 7917, 2); break;\n\tcase SOUND_PED_CRASH_VEHICLE: GetPhrase(sfx, ped->m_lastComment, 7897, 7); break;\n\tcase SOUND_PED_CRASH_CAR: GetPhrase(sfx, ped->m_lastComment, 7855, 8); break;\n\tcase SOUND_PED_CHAT_EVENT: GetPhrase(sfx, ped->m_lastComment, 7920, 2); break;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 7847, 8); break;\n\tcase SOUND_PED_CHAT: GetPhrase(sfx, ped->m_lastComment, 7863, 11); break;\n\tdefault: return GetGenericFemaleTalkSfx(ped, sound);\n\t}\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetWMOGOTalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_COWER: GetPhrase(sfx, ped->m_lastComment, 4982, 5); break;\n\tcase SOUND_PED_CAR_JACKED: GetPhrase(sfx, ped->m_lastComment, 4987, 6); break;\n\tcase SOUND_PED_ACCIDENTREACTION1: return 4998;\n\tcase SOUND_PED_TAXI_WAIT: return 5002;\n\tcase SOUND_PED_ATTACK: GetPhrase(sfx, ped->m_lastComment, 4961, 13); break;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 4947, 12); break;\n\tcase SOUND_PED_FLEE_RUN: GetPhrase(sfx, ped->m_lastComment, 4993, 5); break;\n\tcase SOUND_PED_CRASH_VEHICLE: GetPhrase(sfx, ped->m_lastComment, 4974, 8); break;\n\tcase SOUND_PED_CRASH_CAR: GetPhrase(sfx, ped->m_lastComment, 4929, 9); break;\n\tcase SOUND_PED_CHAT_SEXY: GetPhrase(sfx, ped->m_lastComment, 4959, 2); break;\n\tcase SOUND_PED_CHAT_EVENT: GetPhrase(sfx, ped->m_lastComment, 4999, 3); break;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 4921, 8); break;\n\tcase SOUND_PED_CHAT: GetPhrase(sfx, ped->m_lastComment, 4938, 9); break;\n\tdefault: return GetGenericMaleTalkSfx(ped, sound);\n\t}\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetWFYLGTalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_UP: GetPhrase(sfx, ped->m_lastComment, 8267, 5); break;\n\tcase SOUND_PED_ACCIDENTREACTION1: return 8272;\n\tcase SOUND_PED_TAXI_WAIT: return 8273;\n\tcase SOUND_PED_ATTACK: GetPhrase(sfx, ped->m_lastComment, 8260, 7); break;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 8252, 8); break;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 8232, 10); break;\n\tcase SOUND_PED_CHAT: GetPhrase(sfx, ped->m_lastComment, 8242, 10); break;\n\tdefault: return GetGenericFemaleTalkSfx(ped, sound);\n\t}\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetWMYLGTalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_UP: GetPhrase(sfx, ped->m_lastComment, 3698, 6); break;\n\tcase SOUND_PED_ACCIDENTREACTION1: return 3704;\n\tcase SOUND_PED_TAXI_WAIT: return 3705;\n\tcase SOUND_PED_ATTACK: GetPhrase(sfx, ped->m_lastComment, 3691, 7); break;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 3682, 9); break;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 3662, 10); break;\n\tcase SOUND_PED_CHAT: GetPhrase(sfx, ped->m_lastComment, 3672, 10); break;\n\tdefault: return GetGenericMaleTalkSfx(ped, sound);\n\t}\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetWFYBUTalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_COWER: GetPhrase(sfx, ped->m_lastComment, 7309, 8); break;\n\tcase SOUND_PED_CAR_JACKED: GetPhrase(sfx, ped->m_lastComment, 7317, 8); break;\n\tcase SOUND_PED_ROBBED: GetPhrase(sfx, ped->m_lastComment, 7325, 4); break;\n\tcase SOUND_PED_TAXI_WAIT: GetPhrase(sfx, ped->m_lastComment, 7340, 2); break;\n\tcase SOUND_PED_FLEE_RUN: GetPhrase(sfx, ped->m_lastComment, 7329, 8); break;\n\tcase SOUND_PED_CRASH_VEHICLE: GetPhrase(sfx, ped->m_lastComment, 7301, 8); break;\n\tcase SOUND_PED_CRASH_CAR: GetPhrase(sfx, ped->m_lastComment, 7292, 9); break;\n\tcase SOUND_PED_CHAT_EVENT: GetPhrase(sfx, ped->m_lastComment, 7337, 3); break;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 7271, 21); break;\n\tdefault: return GetGenericFemaleTalkSfx(ped, sound);\n\t}\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetWMYBUTalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_COWER: GetPhrase(sfx, ped->m_lastComment, 3862, 6); break;\n\tcase SOUND_PED_CAR_JACKED: GetPhrase(sfx, ped->m_lastComment, 3870, 5); break;\n\tcase SOUND_PED_ROBBED: return 3880;\n\tcase SOUND_PED_ACCIDENTREACTION1: GetPhrase(sfx, ped->m_lastComment, 3884, 2); break;\n\tcase SOUND_PED_UNK_126: GetPhrase(sfx, ped->m_lastComment, 3868, 2); break;\n\tcase SOUND_PED_TAXI_WAIT: GetPhrase(sfx, ped->m_lastComment, 3891, 2); break;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 3845, 10); break;\n\tcase SOUND_PED_FLEE_RUN: GetPhrase(sfx, ped->m_lastComment, 3881, 3); break;\n\tcase SOUND_PED_CRASH_VEHICLE: GetPhrase(sfx, ped->m_lastComment, 3857, 5); break;\n\tcase SOUND_PED_CRASH_CAR: GetPhrase(sfx, ped->m_lastComment, 3826, 9); break;\n\tcase SOUND_PED_ANNOYED_DRIVER: GetPhrase(sfx, ped->m_lastComment, 3706, 6); break;\n\tcase SOUND_PED_WAIT_DOUBLEBACK: GetPhrase(sfx, ped->m_lastComment, 3875, 5); break;\n\tcase SOUND_PED_CHAT_SEXY: GetPhrase(sfx, ped->m_lastComment, 3855, 2); break;\n\tcase SOUND_PED_CHAT_EVENT: GetPhrase(sfx, ped->m_lastComment, 3886, 5); break;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 3815, 11); break;\n\tcase SOUND_PED_CHAT: GetPhrase(sfx, ped->m_lastComment, 3835, 10); break;\n\tdefault: return GetGenericMaleTalkSfx(ped, sound);\n\t}\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetWMOBUTalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_COWER: GetPhrase(sfx, ped->m_lastComment, 6753, 6); break;\n\tcase SOUND_PED_CAR_JACKED: GetPhrase(sfx, ped->m_lastComment, 6759, 7); break;\n\tcase SOUND_PED_ROBBED: GetPhrase(sfx, ped->m_lastComment, 6769, 2); break;\n\tcase SOUND_PED_ACCIDENTREACTION1: GetPhrase(sfx, ped->m_lastComment, 6771, 3); break;\n\tcase SOUND_PED_TAXI_WAIT: GetPhrase(sfx, ped->m_lastComment, 6774, 2); break;\n\tcase SOUND_PED_ATTACK: GetPhrase(sfx, ped->m_lastComment, 6743, 3); break;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 6733, 8); break;\n\tcase SOUND_PED_CRASH_VEHICLE: GetPhrase(sfx, ped->m_lastComment, 6746, 7); break;\n\tcase SOUND_PED_CRASH_CAR: GetPhrase(sfx, ped->m_lastComment, 6726, 7); break;\n\tcase SOUND_PED_ANNOYED_DRIVER: GetPhrase(sfx, ped->m_lastComment, 6709, 7); break;\n\tcase SOUND_PED_WAIT_DOUBLEBACK: GetPhrase(sfx, ped->m_lastComment, 6766, 3); break;\n\tcase SOUND_PED_CHAT_SEXY: GetPhrase(sfx, ped->m_lastComment, 6741, 2); break;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 6716, 10); break;\n\tdefault: return GetGenericMaleTalkSfx(ped, sound);\n\t}\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetWFYPRTalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_UP: GetPhrase(sfx, ped->m_lastComment, 4101, 6); break;\n\tcase SOUND_PED_ROBBED: GetPhrase(sfx, ped->m_lastComment, 4107, 2); break;\n\tcase SOUND_PED_ACCIDENTREACTION1: return 4109;\n\tcase SOUND_PED_PLAYER_BEFORESEX: GetPhrase(sfx, ped->m_lastComment, 4096, 5); break;\n\tcase SOUND_PED_TAXI_WAIT: return 4125;\n\tcase SOUND_PED_ATTACK: GetPhrase(sfx, ped->m_lastComment, 4087, 9); break;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 4077, 10); break;\n\tcase SOUND_PED_SOLICIT: GetPhrase(sfx, ped->m_lastComment, 4110, 15); break;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 4052, 11); break;\n\tcase SOUND_PED_CHAT: GetPhrase(sfx, ped->m_lastComment, 4063, 14); break;\n\tdefault: return GetGenericFemaleTalkSfx(ped, sound);\n\t}\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetWFOTRTalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_UP: GetPhrase(sfx, ped->m_lastComment, 7371, 6); break;\n\tcase SOUND_PED_ACCIDENTREACTION1: return 7383;\n\tcase SOUND_PED_TAXI_WAIT: return 7393;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 7362, 9); break;\n\tcase SOUND_PED_FLEE_RUN: GetPhrase(sfx, ped->m_lastComment, 7377, 6); break;\n\tcase SOUND_PED_SOLICIT: GetPhrase(sfx, ped->m_lastComment, 7384, 9); break;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 7342, 11); break;\n\tcase SOUND_PED_CHAT: GetPhrase(sfx, ped->m_lastComment, 7353, 9); break;\n\tdefault: return GetGenericFemaleTalkSfx(ped, sound);\n\t}\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetWMOTRTalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_UP: GetPhrase(sfx, ped->m_lastComment, 7542, 5); break;\n\tcase SOUND_PED_ACCIDENTREACTION1: return 7547;\n\tcase SOUND_PED_TAXI_WAIT: return 7558;\n\tcase SOUND_PED_ATTACK: GetPhrase(sfx, ped->m_lastComment, 7536, 6); break;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 7517, 17); break;\n\tcase SOUND_PED_SOLICIT: GetPhrase(sfx, ped->m_lastComment, 7551, 7); break;\n\tcase SOUND_PED_CHAT_SEXY: GetPhrase(sfx, ped->m_lastComment, 7534, 2); break;\n\tcase SOUND_PED_CHAT_EVENT: GetPhrase(sfx, ped->m_lastComment, 7548, 3); break;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 7494, 10); break;\n\tcase SOUND_PED_CHAT: GetPhrase(sfx, ped->m_lastComment, 7504, 13); break;\n\tdefault: return GetGenericMaleTalkSfx(ped, sound);\n\t}\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetWMYPITalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_UP: GetPhrase(sfx, ped->m_lastComment, 6496, 5); break;\n\tcase SOUND_PED_CAR_JACKING: GetPhrase(sfx, ped->m_lastComment, 6509, 4); break;\n\tcase SOUND_PED_CAR_JACKED: GetPhrase(sfx, ped->m_lastComment, 6503, 6); break;\n\tcase SOUND_PED_ROBBED: GetPhrase(sfx, ped->m_lastComment, 6513, 2); break;\n\tcase SOUND_PED_ACCIDENTREACTION1: GetPhrase(sfx, ped->m_lastComment, 6515, 2); break;\n\tcase SOUND_PED_UNK_126: GetPhrase(sfx, ped->m_lastComment, 6501, 2); break;\n\tcase SOUND_PED_TAXI_WAIT: GetPhrase(sfx, ped->m_lastComment, 6517, 4); break;\n\tcase SOUND_PED_ATTACK: GetPhrase(sfx, ped->m_lastComment, 6479, 7); break;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 6465, 8); break;\n\tcase SOUND_PED_CRASH_VEHICLE: GetPhrase(sfx, ped->m_lastComment, 6488, 8); break;\n\tcase SOUND_PED_CRASH_CAR: GetPhrase(sfx, ped->m_lastComment, 6457, 8); break;\n\tcase SOUND_PED_ANNOYED_DRIVER: GetPhrase(sfx, ped->m_lastComment, 6439, 8); break;\n\tcase SOUND_PED_CHAT_SEXY: GetPhrase(sfx, ped->m_lastComment, 6473, 6); break;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 6447, 10); break;\n\tdefault: return GetGenericMaleTalkSfx(ped, sound);\n\t}\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetWMOCATalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_COWER: GetPhrase(sfx, ped->m_lastComment, 8032, 6); break;\n\tcase SOUND_PED_CAR_JACKING: GetPhrase(sfx, ped->m_lastComment, 8048, 11); break;\n\tcase SOUND_PED_CAR_JACKED: GetPhrase(sfx, ped->m_lastComment, 8038, 10); break;\n\tcase SOUND_PED_ROBBED: GetPhrase(sfx, ped->m_lastComment, 8059, 2); break;\n\tcase SOUND_PED_ACCIDENTREACTION1: return 8061;\n\tcase SOUND_PED_TAXI_WAIT: return 8062;\n\tcase SOUND_PED_ATTACK: GetPhrase(sfx, ped->m_lastComment, 8015, 8); break;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 8003, 10); break;\n\tcase SOUND_PED_CRASH_VEHICLE: GetPhrase(sfx, ped->m_lastComment, 8023, 9); break;\n\tcase SOUND_PED_CRASH_CAR: GetPhrase(sfx, ped->m_lastComment, 7993, 10); break;\n\tcase SOUND_PED_ANNOYED_DRIVER: GetPhrase(sfx, ped->m_lastComment, 7975, 12); break;\n\tcase SOUND_PED_CHAT_SEXY: GetPhrase(sfx, ped->m_lastComment, 8013, 2); break;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 7987, 6); break;\n\tdefault: return GetGenericMaleTalkSfx(ped, sound);\n\t}\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetWFYJGTalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_COWER: GetPhrase(sfx, ped->m_lastComment, 7414, 4); break;\n\tcase SOUND_PED_ACCIDENTREACTION1: sfx = 7424; break;\n\tcase SOUND_PED_TAXI_WAIT: sfx = 7425; break;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 7406, 8); break;\n\tcase SOUND_PED_FLEE_RUN: GetPhrase(sfx, ped->m_lastComment, 7418, 6); break;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 7394, 12); break;\n\tdefault: return GetGenericFemaleTalkSfx(ped, sound);\n\t}\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetWMYJGTalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_COWER: GetPhrase(sfx, ped->m_lastComment, 5098, 4); break;\n\tcase SOUND_PED_ROBBED: GetPhrase(sfx, ped->m_lastComment, 5102, 2); break;\n\tcase SOUND_PED_ACCIDENTREACTION1: return 5109;\n\tcase SOUND_PED_TAXI_WAIT: return 5110;\n\tcase SOUND_PED_FLEE_RUN: GetPhrase(sfx, ped->m_lastComment, 5104, 5); break;\n\tcase SOUND_PED_ANNOYED_DRIVER: GetPhrase(sfx, ped->m_lastComment, 5076, 10); break;\n\tcase SOUND_PED_CHAT_SEXY: GetPhrase(sfx, ped->m_lastComment, 5096, 2); break;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 5086, 10); break;\n\tdefault: return GetGenericMaleTalkSfx(ped, sound);\n\t}\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetWFYSKTalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_COWER: GetPhrase(sfx, ped->m_lastComment, 3652, 5); break;\n\tcase SOUND_PED_ROBBED: GetPhrase(sfx, ped->m_lastComment, 3657, 2); break;\n\tcase SOUND_PED_ACCIDENTREACTION1: GetPhrase(sfx, ped->m_lastComment, 3659, 2); break;\n\tcase SOUND_PED_TAXI_WAIT: return 3661;\n\tcase SOUND_PED_ATTACK: GetPhrase(sfx, ped->m_lastComment, 3641, 11); break;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 3632, 9); break;\n\tcase SOUND_PED_ANNOYED_DRIVER: GetPhrase(sfx, ped->m_lastComment, 3603, 11); break;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 3614, 18); break;\n\tdefault: return GetGenericFemaleTalkSfx(ped, sound);\n\t}\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetWMYSKTalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_COWER: GetPhrase(sfx, ped->m_lastComment, 5563, 5); break;\n\tcase SOUND_PED_ROBBED: GetPhrase(sfx, ped->m_lastComment, 5573, 2); break;\n\tcase SOUND_PED_ACCIDENTREACTION1: GetPhrase(sfx, ped->m_lastComment, 5575, 2); break;\n\tcase SOUND_PED_UNK_126: GetPhrase(sfx, ped->m_lastComment, 5568, 3); break;\n\tcase SOUND_PED_TAXI_WAIT: return 5579;\n\tcase SOUND_PED_ATTACK: GetPhrase(sfx, ped->m_lastComment, 5558, 5); break;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 5546, 10); break;\n\tcase SOUND_PED_WAIT_DOUBLEBACK: GetPhrase(sfx, ped->m_lastComment, 5571, 2); break;\n\tcase SOUND_PED_CHAT_SEXY: GetPhrase(sfx, ped->m_lastComment, 5556, 2); break;\n\tcase SOUND_PED_CHAT_EVENT: GetPhrase(sfx, ped->m_lastComment, 5577, 2); break;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 5519, 14); break;\n\tcase SOUND_PED_CHAT: GetPhrase(sfx, ped->m_lastComment, 5533, 13); break;\n\tdefault: return GetGenericMaleTalkSfx(ped, sound);\n\t}\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetWFYSHTalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_UP: GetPhrase(sfx, ped->m_lastComment, 7459, 9); break;\n\tcase SOUND_PED_ROBBED: GetPhrase(sfx, ped->m_lastComment, 7470, 2); break;\n\tcase SOUND_PED_ACCIDENTREACTION1: GetPhrase(sfx, ped->m_lastComment, 7483, 4); break;\n\tcase SOUND_PED_TAXI_WAIT: GetPhrase(sfx, ped->m_lastComment, 7492, 2); break;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 7448, 11); break;\n\tcase SOUND_PED_FLEE_RUN: GetPhrase(sfx, ped->m_lastComment, 7472, 11); break;\n\tcase SOUND_PED_WAIT_DOUBLEBACK: GetPhrase(sfx, ped->m_lastComment, 7468, 2); break;\n\tcase SOUND_PED_CHAT_EVENT: GetPhrase(sfx, ped->m_lastComment, 7487, 5); break;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 7426, 12); break;\n\tcase SOUND_PED_CHAT: GetPhrase(sfx, ped->m_lastComment, 7438, 10); break;\n\tdefault: return GetGenericFemaleTalkSfx(ped, sound);\n\t}\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetWFOSHTalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_UP: GetPhrase(sfx, ped->m_lastComment, 3571, 10); break;\n\tcase SOUND_PED_ROBBED: GetPhrase(sfx, ped->m_lastComment, 3583, 2); break;\n\tcase SOUND_PED_ACCIDENTREACTION1: GetPhrase(sfx, ped->m_lastComment, 3594, 3); break;\n\tcase SOUND_PED_TAXI_WAIT: return 3602;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 3561, 10); break;\n\tcase SOUND_PED_FLEE_RUN: GetPhrase(sfx, ped->m_lastComment, 3585, 9); break;\n\tcase SOUND_PED_WAIT_DOUBLEBACK: GetPhrase(sfx, ped->m_lastComment, 3581, 2); break;\n\tcase SOUND_PED_CHAT_EVENT: GetPhrase(sfx, ped->m_lastComment, 3597, 5); break;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 3542, 10); break;\n\tcase SOUND_PED_CHAT: GetPhrase(sfx, ped->m_lastComment, 3552, 9); break;\n\tdefault: return GetGenericFemaleTalkSfx(ped, sound);\n\t}\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetJFOTOTalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_COWER: GetPhrase(sfx, ped->m_lastComment, 811, 4); break;\n\tcase SOUND_PED_CAR_JACKED: GetPhrase(sfx, ped->m_lastComment, 815, 5); break;\n\tcase SOUND_PED_ROBBED: GetPhrase(sfx, ped->m_lastComment, 821, 2); break;\n\tcase SOUND_PED_ACCIDENTREACTION1: GetPhrase(sfx, ped->m_lastComment, 828, 2); break;\n\tcase SOUND_PED_TAXI_WAIT: GetPhrase(sfx, ped->m_lastComment, 831, 2); break;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 796, 9); break;\n\tcase SOUND_PED_FLEE_RUN: GetPhrase(sfx, ped->m_lastComment, 823, 5); break;\n\tcase SOUND_PED_CRASH_VEHICLE: GetPhrase(sfx, ped->m_lastComment, 805, 6); break;\n\tcase SOUND_PED_CRASH_CAR: GetPhrase(sfx, ped->m_lastComment, 775, 8); break;\n\tcase SOUND_PED_ANNOYED_DRIVER: GetPhrase(sfx, ped->m_lastComment, 757, 8); break;\n\tcase SOUND_PED_WAIT_DOUBLEBACK: return 820;\n\tcase SOUND_PED_CHAT_EVENT: return 830;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 765, 10); break;\n\tcase SOUND_PED_CHAT: GetPhrase(sfx, ped->m_lastComment, 783, 13); break;\n\tdefault: return GetGenericFemaleTalkSfx(ped, sound);\n\t}\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetJMOTOTalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_COWER: GetPhrase(sfx, ped->m_lastComment, 874, 4); break;\n\tcase SOUND_PED_CAR_JACKED: GetPhrase(sfx, ped->m_lastComment, 878, 4); break;\n\tcase SOUND_PED_ROBBED: GetPhrase(sfx, ped->m_lastComment, 883, 2); break;\n\tcase SOUND_PED_ACCIDENTREACTION1: return 889;\n\tcase SOUND_PED_TAXI_WAIT: return 891;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 862, 6); break;\n\tcase SOUND_PED_FLEE_RUN: GetPhrase(sfx, ped->m_lastComment, 885, 4); break;\n\tcase SOUND_PED_CRASH_VEHICLE: GetPhrase(sfx, ped->m_lastComment, 868, 6); break;\n\tcase SOUND_PED_CRASH_CAR: GetPhrase(sfx, ped->m_lastComment, 849, 6); break;\n\tcase SOUND_PED_ANNOYED_DRIVER: GetPhrase(sfx, ped->m_lastComment, 833, 8); break;\n\tcase SOUND_PED_WAIT_DOUBLEBACK: return 882;\n\tcase SOUND_PED_CHAT_EVENT: return 890;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 841, 8); break;\n\tcase SOUND_PED_CHAT: GetPhrase(sfx, ped->m_lastComment, 855, 7); break;\n\tdefault: return GetGenericMaleTalkSfx(ped, sound);\n\t}\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetCBTalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_UP: GetPhrase(sfx, ped->m_lastComment, 2178, 5); break;\n\tcase SOUND_PED_CAR_JACKING: GetPhrase(sfx, ped->m_lastComment, 2187, 5); break;\n\tcase SOUND_PED_CAR_JACKED: GetPhrase(sfx, ped->m_lastComment, 2183, 4); break;\n\tcase SOUND_PED_ROBBED: GetPhrase(sfx, ped->m_lastComment, 2194, 2); break;\n\tcase SOUND_PED_ACCIDENTREACTION1: sfx = 2196; break;\n\tcase SOUND_PED_TAXI_WAIT: GetPhrase(sfx, ped->m_lastComment, 2197, 2); break;\n\tcase SOUND_PED_ATTACK: GetPhrase(sfx, ped->m_lastComment, 2161, 9); break;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 2150, 9); break;\n\tcase SOUND_PED_CRASH_VEHICLE: GetPhrase(sfx, ped->m_lastComment, 2170, 8); break;\n\tcase SOUND_PED_CRASH_CAR: GetPhrase(sfx, ped->m_lastComment, 2132, 8); break;\n\tcase SOUND_PED_ANNOYED_DRIVER: GetPhrase(sfx, ped->m_lastComment, 2113, 8); break;\n\tcase SOUND_PED_WAIT_DOUBLEBACK: GetPhrase(sfx, ped->m_lastComment, 2192, 2); break;\n\tcase SOUND_PED_CHAT_SEXY: GetPhrase(sfx, ped->m_lastComment, 2159, 2); break;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 2121, 11); break;\n\tcase SOUND_PED_CHAT: GetPhrase(sfx, ped->m_lastComment, 2140, 10); break;\n\tdefault: return GetGenericMaleTalkSfx(ped, sound);\n\t}\n\treturn 86 * (m_sQueueSample.m_nEntityIndex % 3) + sfx;\n}\n\nuint32\ncAudioManager::GetHNTalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_UP: GetPhrase(sfx, ped->m_lastComment, 2692, 5); break;\n\tcase SOUND_PED_CAR_JACKING: GetPhrase(sfx, ped->m_lastComment, 2703, 4); break;\n\tcase SOUND_PED_CAR_JACKED: GetPhrase(sfx, ped->m_lastComment, 2697, 6); break;\n\tcase SOUND_PED_ROBBED: GetPhrase(sfx, ped->m_lastComment, 2711, 3); break;\n\tcase SOUND_PED_ACCIDENTREACTION1: sfx = 2714; break;\n\tcase SOUND_PED_TAXI_WAIT: sfx = 2715; break;\n\tcase SOUND_PED_ATTACK: GetPhrase(sfx, ped->m_lastComment, 2673, 10); break;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 2661, 10); break;\n\tcase SOUND_PED_CRASH_VEHICLE: GetPhrase(sfx, ped->m_lastComment, 2683, 9); break;\n\tcase SOUND_PED_CRASH_CAR: GetPhrase(sfx, ped->m_lastComment, 2638, 9); break;\n\tcase SOUND_PED_ANNOYED_DRIVER: GetPhrase(sfx, ped->m_lastComment, 2617, 9); break;\n\tcase SOUND_PED_WAIT_DOUBLEBACK: GetPhrase(sfx, ped->m_lastComment, 2707, 4); break;\n\tcase SOUND_PED_CHAT_SEXY: GetPhrase(sfx, ped->m_lastComment, 2671, 2); break;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 2626, 12); break;\n\tcase SOUND_PED_CHAT: GetPhrase(sfx, ped->m_lastComment, 2647, 14); break;\n\tdefault: return GetGenericMaleTalkSfx(ped, sound);\n\t}\n\treturn 99 * (m_sQueueSample.m_nEntityIndex % 3) + sfx;\n}\n\nuint32\ncAudioManager::GetSGTalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_UP: GetPhrase(sfx, ped->m_lastComment, 1104, 5); break;\n\tcase SOUND_PED_CAR_JACKING: GetPhrase(sfx, ped->m_lastComment, 1114, 5); break;\n\tcase SOUND_PED_MUGGING: GetPhrase(sfx, ped->m_lastComment, 1124, 5); break;\n\tcase SOUND_PED_CAR_JACKED: GetPhrase(sfx, ped->m_lastComment, 1109, 5); break;\n\tcase SOUND_PED_ROBBED: GetPhrase(sfx, ped->m_lastComment, 1121, 3); break;\n\tcase SOUND_PED_ACCIDENTREACTION1: sfx = 1129; break;\n\tcase SOUND_PED_TAXI_WAIT: sfx = 1132; break;\n\tcase SOUND_PED_ATTACK: GetPhrase(sfx, ped->m_lastComment, 1088, 10); break;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 1076, 9); break;\n\tcase SOUND_PED_CRASH_VEHICLE: GetPhrase(sfx, ped->m_lastComment, 1098, 6); break;\n\tcase SOUND_PED_CRASH_CAR: GetPhrase(sfx, ped->m_lastComment, 1058, 6); break;\n\tcase SOUND_PED_ANNOYED_DRIVER: GetPhrase(sfx, ped->m_lastComment, 1040, 8); break;\n\tcase SOUND_PED_WAIT_DOUBLEBACK: GetPhrase(sfx, ped->m_lastComment, 1119, 2); break;\n\tcase SOUND_PED_CHAT_SEXY: GetPhrase(sfx, ped->m_lastComment, 1085, 3); break;\n\tcase SOUND_PED_CHAT_EVENT: GetPhrase(sfx, ped->m_lastComment, 1130, 2); break;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 1048, 10); break;\n\tcase SOUND_PED_CHAT: GetPhrase(sfx, ped->m_lastComment, 1064, 12); break;\n\tdefault: return GetGenericMaleTalkSfx(ped, sound);\n\t}\n\tif(ped->GetModelIndex() == MI_SGB) sfx += 93;\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetCLTalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_UP: GetPhrase(sfx, ped->m_lastComment, 1299, 5); break;\n\tcase SOUND_PED_CAR_JACKING: GetPhrase(sfx, ped->m_lastComment, 1310, 5); break;\n\tcase SOUND_PED_CAR_JACKED: GetPhrase(sfx, ped->m_lastComment, 1304, 6); break;\n\tcase SOUND_PED_ROBBED: GetPhrase(sfx, ped->m_lastComment, 1317, 2); break;\n\tcase SOUND_PED_ACCIDENTREACTION1: sfx = 1319; break;\n\tcase SOUND_PED_TAXI_WAIT: GetPhrase(sfx, ped->m_lastComment, 1320, 2); break;\n\tcase SOUND_PED_ATTACK: GetPhrase(sfx, ped->m_lastComment, 1281, 10); break;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 1266, 13); break;\n\tcase SOUND_PED_CRASH_VEHICLE: GetPhrase(sfx, ped->m_lastComment, 1291, 8); break;\n\tcase SOUND_PED_CRASH_CAR: GetPhrase(sfx, ped->m_lastComment, 1246, 10); break;\n\tcase SOUND_PED_ANNOYED_DRIVER: GetPhrase(sfx, ped->m_lastComment, 1226, 10); break;\n\tcase SOUND_PED_WAIT_DOUBLEBACK: GetPhrase(sfx, ped->m_lastComment, 1315, 2); break;\n\tcase SOUND_PED_CHAT_SEXY: GetPhrase(sfx, ped->m_lastComment, 1279, 2); break;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 1236, 10); break;\n\tcase SOUND_PED_CHAT: GetPhrase(sfx, ped->m_lastComment, 1256, 10); break;\n\tdefault: return GetGenericMaleTalkSfx(ped, sound);\n\t}\n\treturn 96 * (m_sQueueSample.m_nEntityIndex % 3) + sfx;\n}\n\nuint32\ncAudioManager::GetGDTalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_UP: GetPhrase(sfx, ped->m_lastComment, 1762, 6); break;\n\tcase SOUND_PED_ACCIDENTREACTION1: GetPhrase(sfx, ped->m_lastComment, 1770, 2); break;\n\tcase SOUND_PED_ATTACK: GetPhrase(sfx, ped->m_lastComment, 1755, 7); break;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 1744, 9); break;\n\tcase SOUND_PED_WAIT_DOUBLEBACK: GetPhrase(sfx, ped->m_lastComment, 1768, 2); break;\n\tcase SOUND_PED_CHAT_SEXY: GetPhrase(sfx, ped->m_lastComment, 1753, 2); break;\n\tcase SOUND_PED_CHAT_EVENT: GetPhrase(sfx, ped->m_lastComment, 1772, 2); break;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 1724, 10); break;\n\tcase SOUND_PED_CHAT: GetPhrase(sfx, ped->m_lastComment, 1734, 10); break;\n\tdefault: return GetGenericMaleTalkSfx(ped, sound);\n\t}\n\treturn 50 * (m_sQueueSample.m_nEntityIndex % 3) + sfx;\n}\n\nuint32\ncAudioManager::GetBKTalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_UP: GetPhrase(sfx, ped->m_lastComment, 2429, 5); break;\n\tcase SOUND_PED_CAR_JACKING: GetPhrase(sfx, ped->m_lastComment, 2442, 4); break;\n\tcase SOUND_PED_CAR_JACKED: GetPhrase(sfx, ped->m_lastComment, 2434, 8); break;\n\tcase SOUND_PED_ROBBED: GetPhrase(sfx, ped->m_lastComment, 2448, 2); break;\n\tcase SOUND_PED_ACCIDENTREACTION1: sfx = 2450; break;\n\tcase SOUND_PED_TAXI_WAIT: GetPhrase(sfx, ped->m_lastComment, 2451, 2); break;\n\tcase SOUND_PED_ATTACK: GetPhrase(sfx, ped->m_lastComment, 2412, 9); break;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 2403, 9); break;\n\tcase SOUND_PED_CRASH_VEHICLE: GetPhrase(sfx, ped->m_lastComment, 2421, 8); break;\n\tcase SOUND_PED_ANNOYED_DRIVER: GetPhrase(sfx, ped->m_lastComment, 2371, 10); break;\n\tcase SOUND_PED_WAIT_DOUBLEBACK: GetPhrase(sfx, ped->m_lastComment, 2446, 2); break;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 2381, 10); break;\n\tcase SOUND_PED_CHAT: GetPhrase(sfx, ped->m_lastComment, 2391, 12); break;\n\tdefault: return GetGenericMaleTalkSfx(ped, sound);\n\t}\n\treturn 82 * (m_sQueueSample.m_nEntityIndex % 3) + sfx;\n}\n\nuint32\ncAudioManager::GetPGTalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_UP: GetPhrase(sfx, ped->m_lastComment, 1561, 4); break;\n\tcase SOUND_PED_CAR_JACKING: GetPhrase(sfx, ped->m_lastComment, 1570, 5); break;\n\tcase SOUND_PED_CAR_JACKED: GetPhrase(sfx, ped->m_lastComment, 1565, 5); break;\n\tcase SOUND_PED_ROBBED: GetPhrase(sfx, ped->m_lastComment, 1577, 2); break;\n\tcase SOUND_PED_ACCIDENTREACTION1: sfx = 1579; break;\n\tcase SOUND_PED_TAXI_WAIT: GetPhrase(sfx, ped->m_lastComment, 1582, 2); break;\n\tcase SOUND_PED_ATTACK: GetPhrase(sfx, ped->m_lastComment, 1551, 5); break;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 1542, 7); break;\n\tcase SOUND_PED_CRASH_VEHICLE: GetPhrase(sfx, ped->m_lastComment, 1556, 5); break;\n\tcase SOUND_PED_CRASH_CAR: GetPhrase(sfx, ped->m_lastComment, 1529, 5); break;\n\tcase SOUND_PED_ANNOYED_DRIVER: GetPhrase(sfx, ped->m_lastComment, 1514, 10); break;\n\tcase SOUND_PED_WAIT_DOUBLEBACK: GetPhrase(sfx, ped->m_lastComment, 1575, 2); break;\n\tcase SOUND_PED_CHAT_SEXY: GetPhrase(sfx, ped->m_lastComment, 1549, 2); break;\n\tcase SOUND_PED_CHAT_EVENT: GetPhrase(sfx, ped->m_lastComment, 1580, 2); break;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 1524, 5); break;\n\tcase SOUND_PED_CHAT: GetPhrase(sfx, ped->m_lastComment, 1534, 8); break;\n\tdefault: return GetGenericMaleTalkSfx(ped, sound);\n\t}\n\treturn 70 * (m_sQueueSample.m_nEntityIndex % 3) + sfx;\n}\n\nuint32\ncAudioManager::GetVICETalkSfx(CPed *ped, int16 sound, int16 model)\n{\n\tuint32 sfx;\n\tif(model == MI_VICE6) {\n\n\t\tswitch(sound) {\n\t\tcase SOUND_PED_ARREST_COP: GetPhrase(sfx, ped->m_lastComment, 1894, 3); break;\n\t\tcase SOUND_PED_MIAMIVICE_EXITING_CAR: return 1897;\n\t\tdefault: return GetGenericMaleTalkSfx(ped, sound);\n\t\t}\n\t}\n\tswitch(sound) {\n\tcase SOUND_PED_ARREST_COP: GetPhrase(sfx, ped->m_lastComment, 1874, 3); break;\n\tcase SOUND_PED_MIAMIVICE_EXITING_CAR: sfx = 1877; break;\n\n\tdefault: return GetGenericMaleTalkSfx(ped, sound);\n\t}\n\tsfx += 4 * (m_sQueueSample.m_nEntityIndex % 5);\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetWFYG1TalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_UP: GetPhrase(sfx, ped->m_lastComment, 3383, 6); break;\n\tcase SOUND_PED_MUGGING: GetPhrase(sfx, ped->m_lastComment, 3399, 2); break;\n\tcase SOUND_PED_CAR_JACKED: GetPhrase(sfx, ped->m_lastComment, 3389, 5); break;\n\tcase SOUND_PED_ROBBED: GetPhrase(sfx, ped->m_lastComment, 3397, 2); break;\n\tcase SOUND_PED_ACCIDENTREACTION1: return 3403;\n\tcase SOUND_PED_TAXI_WAIT: return 3405;\n\tcase SOUND_PED_ATTACK: GetPhrase(sfx, ped->m_lastComment, 3372, 4); break;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 3361, 9); break;\n\tcase SOUND_PED_FLEE_RUN: GetPhrase(sfx, ped->m_lastComment, 3401, 2); break;\n\tcase SOUND_PED_CRASH_VEHICLE: GetPhrase(sfx, ped->m_lastComment, 3376, 7); break;\n\tcase SOUND_PED_CRASH_CAR: GetPhrase(sfx, ped->m_lastComment, 3342, 9); break;\n\tcase SOUND_PED_ANNOYED_DRIVER: GetPhrase(sfx, ped->m_lastComment, 3324, 7); break;\n\tcase SOUND_PED_WAIT_DOUBLEBACK: GetPhrase(sfx, ped->m_lastComment, 3394, 3); break;\n\tcase SOUND_153: GetPhrase(sfx, ped->m_lastComment, 3370, 2); break;\n\tcase SOUND_PED_CHAT_EVENT: return 3404;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 3331, 11); break;\n\tcase SOUND_PED_CHAT: GetPhrase(sfx, ped->m_lastComment, 3351, 10); break;\n\tdefault: return GetGenericFemaleTalkSfx(ped, sound);\n\t}\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetWFYG2TalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tswitch(sound) {\n\tcase SOUND_PED_HANDS_UP: GetPhrase(sfx, ped->m_lastComment, 3464, 3); break;\n\tcase SOUND_PED_CAR_JACKED: GetPhrase(sfx, ped->m_lastComment, 3467, 5); break;\n\tcase SOUND_PED_ROBBED: GetPhrase(sfx, ped->m_lastComment, 3473, 2); break;\n\tcase SOUND_PED_TAXI_WAIT: return 3476;\n\tcase SOUND_PED_ATTACK: GetPhrase(sfx, ped->m_lastComment, 3452, 5); break;\n\tcase SOUND_PED_EVADE: GetPhrase(sfx, ped->m_lastComment, 3440, 8); break;\n\tcase SOUND_PED_CRASH_VEHICLE: GetPhrase(sfx, ped->m_lastComment, 3457, 7); break;\n\tcase SOUND_PED_CRASH_CAR: GetPhrase(sfx, ped->m_lastComment, 3422, 9); break;\n\tcase SOUND_PED_ANNOYED_DRIVER: GetPhrase(sfx, ped->m_lastComment, 3406, 5); break;\n\tcase SOUND_PED_WAIT_DOUBLEBACK: return 3472;\n\tcase SOUND_153: GetPhrase(sfx, ped->m_lastComment, 3448, 4); break;\n\tcase SOUND_PED_CHAT_EVENT: return 3475;\n\tcase SOUND_PED_PED_COLLISION: GetPhrase(sfx, ped->m_lastComment, 3411, 11); break;\n\tcase SOUND_PED_CHAT: GetPhrase(sfx, ped->m_lastComment, 3431, 9); break;\n\tdefault: return GetGenericFemaleTalkSfx(ped, sound);\n\t}\n\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetGenericMaleTalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\n\tm_bGenericSfx = true;\n\tswitch(sound) {\n\tcase SOUND_PED_DEATH: GetPhrase(sfx, ped->m_lastComment, SFX_GENERIC_MALE_DEATH_1, 41); break;\n\tcase SOUND_PED_BULLET_HIT:\n\tcase SOUND_PED_DEFEND: GetPhrase(sfx, ped->m_lastComment, SFX_GENERIC_MALE_GRUNT_1, 41); break;\n\tcase SOUND_PED_BURNING: GetPhrase(sfx, ped->m_lastComment, SFX_GENERIC_MALE_FIRE_1, 32); break;\n\tcase SOUND_PED_FLEE_SPRINT: GetPhrase(sfx, ped->m_lastComment, SFX_GENERIC_MALE_PANIC_1, 35); break;\n\tdefault: return NO_SAMPLE;\n\t}\n\treturn sfx;\n}\n\nuint32\ncAudioManager::GetGenericFemaleTalkSfx(CPed *ped, int16 sound)\n{\n\tuint32 sfx;\n\tm_bGenericSfx = true;\n\tswitch(sound) {\n\tcase SOUND_PED_DEATH: GetPhrase(sfx, ped->m_lastComment, 2931, 22); break;\n\tcase SOUND_PED_BULLET_HIT:\n\tcase SOUND_PED_DEFEND: GetPhrase(sfx, ped->m_lastComment, 2953, 33); break;\n\tcase SOUND_PED_BURNING: GetPhrase(sfx, ped->m_lastComment, 2914, 17); break;\n\tcase SOUND_PED_FLEE_SPRINT: GetPhrase(sfx, ped->m_lastComment, 2986, 27); break;\n\tdefault: return NO_SAMPLE;\n\t}\n\treturn sfx;\n}\n\nvoid\ncPedComments::Add(tPedComment *com)\n{\n\tuint8 index;\n\n\tif (m_nCommentsInBank[m_nActiveBank] >= NUM_PED_COMMENTS_SLOTS) {\n\t\tindex = m_nIndexMap[m_nActiveBank][NUM_PED_COMMENTS_SLOTS - 1];\n\t\tif (m_asPedComments[m_nActiveBank][index].m_bVolume > com->m_bVolume)\n\t\t\treturn;\n\t} else {\n\t\tindex = m_nCommentsInBank[m_nActiveBank]++;\n\t}\n\n\tm_asPedComments[m_nActiveBank][index] = *com;\n\n\tuint32 i = 0;\n\tif (index != 0) {\n\t\tfor (i = 0; i < index; i++) {\n\t\t\tif (m_asPedComments[m_nActiveBank][m_nIndexMap[m_nActiveBank][i]].m_bVolume < m_asPedComments[m_nActiveBank][index].m_bVolume) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif (i < index)\n\t\t\tmemmove(&m_nIndexMap[m_nActiveBank][i + 1], &m_nIndexMap[m_nActiveBank][i], NUM_PED_COMMENTS_SLOTS - 1 - i);\n\t}\n\n\tm_nIndexMap[m_nActiveBank][i] = index;\n}\n\nvoid\ncPedComments::Process()\n{\n\tuint32 sampleIndex;\n\tuint8 actualUsedBank;\n\ttPedComment *comment;\n\tbool prevUsed = false;\n\tstatic uint8 counter = 0;\n\tstatic int32 prevSamples[10];\n\n\tif(AudioManager.m_nUserPause != 0) return;\n\n\tif(m_nCommentsInBank[m_nActiveBank]) {\n\t\tfor(int i = 0; i < ARRAY_SIZE(prevSamples); i++) {\n\t\t\tif(m_asPedComments[m_nActiveBank][m_nIndexMap[m_nActiveBank][0]].m_nSampleIndex ==\n\t\t\t   prevSamples[(counter + 1 + i) % ARRAY_SIZE(prevSamples)]) {\n\t\t\t\tm_asPedComments[m_nActiveBank][m_nIndexMap[m_nActiveBank][0]].m_nProcess = -1;\n\t\t\t\tprevUsed = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif(!prevUsed) {\n\t\t\tsampleIndex = m_asPedComments[m_nActiveBank][m_nIndexMap[m_nActiveBank][0]].m_nSampleIndex;\n\t\t\tif(!SampleManager.IsPedCommentLoaded(sampleIndex)) {\n#if defined(GTA_PC) && !defined(FIX_BUGS)\n\t\t\t\tif(!m_bDelay)\n#endif\n\t\t\t\t\tSampleManager.LoadPedComment(sampleIndex);\n\t\t\t} else {\n\t\t\t\tAudioManager.m_sQueueSample.m_nEntityIndex = m_asPedComments[m_nActiveBank][m_nIndexMap[m_nActiveBank][0]].m_nEntityIndex;\n\t\t\t\tAudioManager.m_sQueueSample.m_nCounter = 0;\n\t\t\t\tAudioManager.m_sQueueSample.m_nSampleIndex = sampleIndex;\n\t\t\t\tAudioManager.m_sQueueSample.m_nBankIndex = SFX_BANK_PED_COMMENTS;\n\t\t\t\tAudioManager.m_sQueueSample.m_nReleasingVolumeModificator = 3;\n\t\t\t\tAudioManager.m_sQueueSample.m_nVolume = m_asPedComments[m_nActiveBank][m_nIndexMap[m_nActiveBank][0]].m_bVolume;\n\t\t\t\tAudioManager.m_sQueueSample.m_fDistance = m_asPedComments[m_nActiveBank][m_nIndexMap[m_nActiveBank][0]].m_fDistance;\n\t\t\t\tAudioManager.m_sQueueSample.m_nLoopCount = 1;\n\t\t\t\tAudioManager.m_sQueueSample.m_nLoopStart = 0;\n\t\t\t\tAudioManager.m_sQueueSample.m_nLoopEnd = -1;\n\t\t\t\tAudioManager.m_sQueueSample.m_nEmittingVolume = MAX_VOLUME;\n\t\t\t\tAudioManager.m_sQueueSample.m_fSpeedMultiplier = 3.0f;\n\t\t\t\tAudioManager.m_sQueueSample.m_fSoundIntensity = 40.0f;\n\t\t\t\tAudioManager.m_sQueueSample.m_bReleasingSoundFlag = true;\n\t\t\t\tAudioManager.m_sQueueSample.m_vecPos = m_asPedComments[m_nActiveBank][m_nIndexMap[m_nActiveBank][0]].m_vecPos;\n\t\t\t\tAudioManager.m_sQueueSample.m_bReverbFlag = true;\n\t\t\t\tAudioManager.m_sQueueSample.m_bRequireReflection = true;\n\t\t\t\tAudioManager.m_sQueueSample.m_bIs2D = false;\n#ifdef FIX_BUGS\n\t\t\t\tif (sampleIndex >= 8694 && sampleIndex < TOTAL_AUDIO_SAMPLES) { // check if player sfx, TODO: enum\n\t\t\t\t\tAudioManager.m_sQueueSample.m_bIs2D = true;\n\t\t\t\t\tAudioManager.m_sQueueSample.m_nOffset = 63;\n\t\t\t\t}\n#endif // FIX_BUGS\n\t\t\t\tAudioManager.m_sQueueSample.m_nFrequency =\n\t\t\t\t    SampleManager.GetSampleBaseFrequency(AudioManager.m_sQueueSample.m_nSampleIndex) + AudioManager.RandomDisplacement(750);\n\t\t\t\tif(CTimer::GetIsSlowMotionActive()) AudioManager.m_sQueueSample.m_nFrequency /= 2;\n\t\t\t\tm_asPedComments[m_nActiveBank][m_nIndexMap[m_nActiveBank][0]].m_nProcess = -1;\n\t\t\t\tprevSamples[counter++] = sampleIndex;\n\t\t\t\tif(counter == 10) counter = 0;\n\t\t\t\tAudioManager.AddSampleToRequestedQueue();\n#if defined(GTA_PC) && !defined(FIX_BUGS)\n\t\t\t\tm_nDelayTimer = CTimer::GetTimeInMilliseconds();\n\t\t\t\tm_bDelay = true;\n#endif\n\t\t\t}\n\t\t}\n\t}\n\n\t// Switch bank\n\tif (m_nActiveBank) {\n\t\tactualUsedBank = SFX_BANK_PED_COMMENTS;\n\t\tm_nActiveBank = SFX_BANK_0;\n\t} else {\n\t\tactualUsedBank = SFX_BANK_0;\n\t\tm_nActiveBank = SFX_BANK_PED_COMMENTS;\n\t}\n\tcomment = m_asPedComments[actualUsedBank];\n\tfor (uint32 i = 0; i < m_nCommentsInBank[actualUsedBank]; i++) {\n\t\tif (m_asPedComments[actualUsedBank][m_nIndexMap[actualUsedBank][i]].m_nProcess > 0) {\n\t\t\t--m_asPedComments[actualUsedBank][m_nIndexMap[actualUsedBank][i]].m_nProcess;\n\t\t\tAdd(&comment[m_nIndexMap[actualUsedBank][i]]);\n\t\t}\n\t}\n\n\tfor (uint32 i = 0; i < NUM_PED_COMMENTS_SLOTS; i++) {\n\t\tm_nIndexMap[actualUsedBank][i] = NUM_PED_COMMENTS_SLOTS;\n\t}\n\tm_nCommentsInBank[actualUsedBank] = 0;\n#if defined(GTA_PC) && !defined(FIX_BUGS)\n\tif(m_bDelay)\n\t\tif(CTimer::GetTimeInMilliseconds() - m_nDelayTimer > 6000) m_bDelay = false;\n#endif\n}\n\n#undef cooldown_phrase\n\n#pragma endregion\n\n#pragma endregion All the ped audio code\n\nvoid\ncAudioManager::ProcessExplosions(int32 explosion)\n{\n\tuint8 type;\n\tfloat distSquared;\n\n\tfor (uint8 i = 0; i < ARRAY_SIZE(gaExplosion); i++) {\n\t\tif (CExplosion::DoesExplosionMakeSound(i) && CExplosion::GetExplosionActiveCounter(i) == 1) {\n\t\t\tCExplosion::ResetExplosionActiveCounter(i);\n\t\t\ttype = CExplosion::GetExplosionType(i);\n\t\t\tswitch (type) {\n\t\t\tcase EXPLOSION_GRENADE:\n\t\t\tcase EXPLOSION_ROCKET:\n\t\t\tcase EXPLOSION_BARREL:\n\t\t\tcase EXPLOSION_TANK_GRENADE:\n\t\t\t\tm_sQueueSample.m_fSoundIntensity = 200.0f;\n\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_EXPLOSION_2;\n\t\t\t\tm_sQueueSample.m_nFrequency = RandomDisplacement(1000) + 19000;\n\t\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 0;\n\t\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\t\tm_sQueueSample.m_bRequireReflection = true;\n\t\t\t\tbreak;\n\t\t\tcase EXPLOSION_MOLOTOV:\n\t\t\t\tm_sQueueSample.m_fSoundIntensity = 150.0f;\n\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_EXPLOSION_3;\n\t\t\t\tm_sQueueSample.m_nFrequency = RandomDisplacement(1000) + 19000;\n\t\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 0;\n\t\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\t\tm_sQueueSample.m_bRequireReflection = false;\n\t\t\t\tbreak;\n\t\t\tcase EXPLOSION_MINE:\n\t\t\tcase EXPLOSION_HELI_BOMB:\n\t\t\t\tm_sQueueSample.m_fSoundIntensity = 200.0f;\n\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_ROCKET_LEFT;\n\t\t\t\tm_sQueueSample.m_nFrequency = RandomDisplacement(1000) + 12347;\n\t\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 0;\n\t\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\t\tm_sQueueSample.m_bRequireReflection = true;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tm_sQueueSample.m_fSoundIntensity = 200.0f;\n\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_EXPLOSION_1;\n\t\t\t\tm_sQueueSample.m_nFrequency = RandomDisplacement(1000) + 19500;\n\t\t\t\tif (type == EXPLOSION_HELI)\n\t\t\t\t\tm_sQueueSample.m_nFrequency = 8 * m_sQueueSample.m_nFrequency / 10; //same *= 8 / 10;\n\t\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 0;\n\t\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_GENERIC_EXTRA;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tm_sQueueSample.m_vecPos = *CExplosion::GetExplosionPosition(i);\n\t\t\tdistSquared = GetDistanceSquared(m_sQueueSample.m_vecPos);\n\t\t\tif (distSquared < SQR(m_sQueueSample.m_fSoundIntensity)) {\n\t\t\t\tm_sQueueSample.m_fDistance = Sqrt(distSquared);\n\t\t\t\tm_sQueueSample.m_nVolume = ComputeVolume(MAX_VOLUME, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance);\n\t\t\t\tif (m_sQueueSample.m_nVolume != 0) {\n\t\t\t\t\tm_sQueueSample.m_nCounter = i;\n\t\t\t\t\tm_sQueueSample.m_fSpeedMultiplier = 2.0f;\n\t\t\t\t\tm_sQueueSample.m_bIs2D = false;\n\t\t\t\t\tm_sQueueSample.m_nLoopCount = 1;\n\t\t\t\t\tm_sQueueSample.m_bReleasingSoundFlag = true;\n\t\t\t\t\tm_sQueueSample.m_nEmittingVolume = MAX_VOLUME;\n\t\t\t\t\tm_sQueueSample.m_nLoopStart = 0;\n\t\t\t\t\tm_sQueueSample.m_nLoopEnd = -1;\n\t\t\t\t\tm_sQueueSample.m_bReverbFlag = true;\n\t\t\t\t\tAddSampleToRequestedQueue();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\ncAudioManager::ProcessFires(int32)\n{\n\tCEntity *entity;\n\tuint8 emittingVol;\n\tfloat distSquared;\n\n\tfor (uint8 i = 0; i < NUM_FIRES; i++) {\n\t\tif (gFireManager.m_aFires[i].m_bIsOngoing && gFireManager.m_aFires[i].m_bAudioSet) {\n\t\t\tentity = gFireManager.m_aFires[i].m_pEntity;\n\t\t\tif (entity) {\n\t\t\t\tswitch (entity->GetType()) {\n\t\t\t\tcase ENTITY_TYPE_BUILDING:\n\t\t\t\t\tm_sQueueSample.m_fSoundIntensity = 80.0f;\n\t\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_CAR_ON_FIRE;\n\t\t\t\t\temittingVol = 100;\n\t\t\t\t\tm_sQueueSample.m_nFrequency = 8 * SampleManager.GetSampleBaseFrequency(SFX_CAR_ON_FIRE) / 10;\n\t\t\t\t\tm_sQueueSample.m_nFrequency += i * (m_sQueueSample.m_nFrequency / 64);\n\t\t\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 6;\n\t\t\t\t\tbreak;\n\t\t\t\tcase ENTITY_TYPE_PED:\n\t\t\t\t\tm_sQueueSample.m_fSoundIntensity = 25.0f;\n\t\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_PED_ON_FIRE;\n\t\t\t\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_PED_ON_FIRE);\n\t\t\t\t\temittingVol = 60;\n\t\t\t\t\tm_sQueueSample.m_nFrequency += i * (m_sQueueSample.m_nFrequency / 64);\n\t\t\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 10;\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tm_sQueueSample.m_fSoundIntensity = 80.0f;\n\t\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_CAR_ON_FIRE;\n\t\t\t\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CAR_ON_FIRE);\n\t\t\t\t\tm_sQueueSample.m_nFrequency += i * (m_sQueueSample.m_nFrequency / 64);\n\t\t\t\t\temittingVol = 80;\n\t\t\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 8;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tm_sQueueSample.m_fSoundIntensity = 80.0f;\n\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_CAR_ON_FIRE;\n\t\t\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CAR_ON_FIRE);\n\t\t\t\temittingVol = 80;\n\t\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 8;\n\t\t\t}\n\t\t\tm_sQueueSample.m_vecPos = gFireManager.m_aFires[i].m_vecPos;\n\t\t\tdistSquared = GetDistanceSquared(m_sQueueSample.m_vecPos);\n\t\t\tif (distSquared < SQR(m_sQueueSample.m_fSoundIntensity)) {\n\t\t\t\tm_sQueueSample.m_fDistance = Sqrt(distSquared);\n\t\t\t\tm_sQueueSample.m_nVolume = ComputeVolume(emittingVol, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance);\n\t\t\t\tif (m_sQueueSample.m_nVolume != 0) {\n\t\t\t\t\tm_sQueueSample.m_nCounter = i;\n\t\t\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\t\t\tm_sQueueSample.m_fSpeedMultiplier = 2.0f;\n\t\t\t\t\tm_sQueueSample.m_nReleasingVolumeDivider = 10;\n\t\t\t\t\tm_sQueueSample.m_bIs2D = false;\n\t\t\t\t\tm_sQueueSample.m_nLoopCount = 0;\n\t\t\t\t\tm_sQueueSample.m_bReleasingSoundFlag = false;\n\t\t\t\t\tm_sQueueSample.m_nEmittingVolume = emittingVol;\n\t\t\t\t\tm_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex);\n\t\t\t\t\tm_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex);\n\t\t\t\t\tm_sQueueSample.m_bReverbFlag = true;\n\t\t\t\t\tm_sQueueSample.m_bRequireReflection = false;\n\t\t\t\t\tAddSampleToRequestedQueue();\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (gFireManager.m_aFires[i].m_bExtinguishedWithWater) {\n\t\t\t\tgFireManager.m_aFires[i].m_bExtinguishedWithWater = false;\n\t\t\t\temittingVol = 100.0f * gFireManager.m_aFires[i].m_fWaterExtinguishCountdown;\n\t\t\t\tm_sQueueSample.m_nVolume = ComputeVolume(emittingVol, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance);\n\t\t\t\tif (m_sQueueSample.m_nVolume != 0) {\n\t\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_JUMBO_TAXI;\n\t\t\t\t\tm_sQueueSample.m_nFrequency = 19591;\n\t\t\t\t\tm_sQueueSample.m_nFrequency += i * (m_sQueueSample.m_nFrequency / 64);\n\t\t\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 9;\n\t\t\t\t\tm_sQueueSample.m_nCounter = i + 40;\n\t\t\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\t\t\tm_sQueueSample.m_fSpeedMultiplier = 2.0f;\n\t\t\t\t\tm_sQueueSample.m_nReleasingVolumeDivider = 10;\n\t\t\t\t\tm_sQueueSample.m_bIs2D = false;\n\t\t\t\t\tm_sQueueSample.m_nLoopCount = 0;\n\t\t\t\t\tm_sQueueSample.m_bReleasingSoundFlag = false;\n\t\t\t\t\tm_sQueueSample.m_nEmittingVolume = emittingVol;\n\t\t\t\t\tm_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex);\n\t\t\t\t\tm_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex);\n\t\t\t\t\tm_sQueueSample.m_bReverbFlag = true;\n\t\t\t\t\tm_sQueueSample.m_bRequireReflection = false;\n\t\t\t\t\tAddSampleToRequestedQueue();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\ncAudioManager::ProcessWaterCannon(int32)\n{\n\tconst float SOUND_INTENSITY = 30.0f;\n\n\tfor (int32 i = 0; i < NUM_WATERCANNONS; i++) {\n\t\tif (CWaterCannons::aCannons[i].m_nId) {\n\t\t\tm_sQueueSample.m_vecPos = CWaterCannons::aCannons[0].m_avecPos[CWaterCannons::aCannons[i].m_nCur];\n\t\t\tfloat distSquared = GetDistanceSquared(m_sQueueSample.m_vecPos);\n\t\t\tif (distSquared < SQR(SOUND_INTENSITY)) {\n\t\t\t\tm_sQueueSample.m_fDistance = Sqrt(distSquared);\n\t\t\t\tm_sQueueSample.m_nVolume = ComputeVolume(50, SOUND_INTENSITY, m_sQueueSample.m_fDistance);\n\t\t\t\tif (m_sQueueSample.m_nVolume != 0) {\n\t\t\t\t\tm_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY;\n\t\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_JUMBO_TAXI;\n\t\t\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\t\t\tm_sQueueSample.m_nFrequency = 15591;\n\t\t\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 5;\n\t\t\t\t\tm_sQueueSample.m_nCounter = i;\n\t\t\t\t\tm_sQueueSample.m_fSpeedMultiplier = 2.0f;\n\t\t\t\t\tm_sQueueSample.m_nReleasingVolumeDivider = 8;\n\t\t\t\t\tm_sQueueSample.m_bIs2D = false;\n\t\t\t\t\tm_sQueueSample.m_nLoopCount = 0;\n\t\t\t\t\tm_sQueueSample.m_bReleasingSoundFlag = false;\n\t\t\t\t\tm_sQueueSample.m_nEmittingVolume = 50;\n\t\t\t\t\tm_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex);\n\t\t\t\t\tm_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex);\n\t\t\t\t\tm_sQueueSample.m_bReverbFlag = true;\n\t\t\t\t\tm_sQueueSample.m_bRequireReflection = false;\n\t\t\t\t\tAddSampleToRequestedQueue();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n//positon of arcade machines\nCVector aVecExtraSoundPosition[] = { CVector(-1042.546f, 88.794f, 11.324f), CVector(-1004.476f, 181.697f, 11.324f) };\n\nvoid \ncAudioManager::ProcessExtraSounds()\n{\n\tconst float SOUND_INTENSITY = 18.0f;\n\tconst uint8 EMITTING_VOLUME = 50;\n\n\tfloat distance;\n\n\tfor (int i = 0; i < ARRAY_SIZE(aVecExtraSoundPosition); i++) {\n\t\tm_sQueueSample.m_vecPos = aVecExtraSoundPosition[i];\n\t\tdistance = GetDistanceSquared(m_sQueueSample.m_vecPos);\n\t\tif (distance < SQR(SOUND_INTENSITY)) {\n\t\t\tm_sQueueSample.m_fDistance = Sqrt(distance);\n\t\t\tm_sQueueSample.m_nVolume = ComputeVolume(EMITTING_VOLUME, SOUND_INTENSITY, m_sQueueSample.m_fDistance);\n\t\t\tif (m_sQueueSample.m_nVolume != 0) {\n\t\t\t\tm_sQueueSample.m_nCounter = i;\n\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_ARCADE;\n\t\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_ARCADE);\n\t\t\t\tm_sQueueSample.m_bIs2D = false;\n\t\t\t\tm_sQueueSample.m_nLoopCount = 0;\n\t\t\t\tm_sQueueSample.m_bReleasingSoundFlag = false;\n\t\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 4;\n\t\t\t\tm_sQueueSample.m_fSpeedMultiplier = 3.0f;\n\t\t\t\tm_sQueueSample.m_nEmittingVolume = EMITTING_VOLUME;\n\t\t\t\tm_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(SFX_ARCADE);\n\t\t\t\tm_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(SFX_ARCADE);\n\t\t\t\tm_sQueueSample.m_bReverbFlag = true;\n\t\t\t\tm_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY;\n\t\t\t\tm_sQueueSample.m_bRequireReflection = false;\n\t\t\t\tm_sQueueSample.m_nReleasingVolumeDivider = 3;\n\t\t\t\tAddSampleToRequestedQueue();\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\ncAudioManager::ProcessEscalators()\n{\n\tconst float SOUND_INTENSITY = 30.0f;\n\tconst uint8 EMITTING_VOLUME = 26;\n\n\tfloat distance;\n\n\tfor (int i = 0; i < CEscalators::NumEscalators; i++) {\n\t\tif (!CEscalators::GetEscalator(i).IsActive())\n\t\t\tcontinue;\n\t\tm_sQueueSample.m_vecPos = CEscalators::GetEscalator(i).GetPosition();\n\t\tdistance = GetDistanceSquared(m_sQueueSample.m_vecPos);\n\t\tif (distance < SQR(SOUND_INTENSITY)) {\n\t\t\tm_sQueueSample.m_fDistance = Sqrt(distance);\n\t\t\tm_sQueueSample.m_nVolume = ComputeVolume(EMITTING_VOLUME, SOUND_INTENSITY, m_sQueueSample.m_fDistance);\n\t\t\tif (m_sQueueSample.m_nVolume != 0) {\n\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_BOAT_V12_LOOP;\n\t\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\t\tm_sQueueSample.m_nFrequency = i * 50 % 250 + 3973;\n\t\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 3;\n\t\t\t\tm_sQueueSample.m_fSpeedMultiplier = 3.0f;\n\t\t\t\tm_sQueueSample.m_nReleasingVolumeDivider = 5;\n\t\t\t\tm_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY;\n\t\t\t\tm_sQueueSample.m_nCounter = i;\n\t\t\t\tm_sQueueSample.m_bIs2D = false;\n\t\t\t\tm_sQueueSample.m_nLoopCount = 0;\n\t\t\t\tm_sQueueSample.m_nEmittingVolume = EMITTING_VOLUME;\n\t\t\t\tm_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(SFX_BOAT_V12_LOOP);\n\t\t\t\tm_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(SFX_BOAT_V12_LOOP);\n\t\t\t\tm_sQueueSample.m_bReverbFlag = true;\n\t\t\t\tm_sQueueSample.m_bReleasingSoundFlag = false;\n\t\t\t\tm_sQueueSample.m_bRequireReflection = false;\n\t\t\t\tAddSampleToRequestedQueue();\n\t\t\t}\n\t\t}\n\t}\n}\n\n#pragma region SCRIPT_OBJECTS\nconst int SCRIPT_OBJECT_INTENSITY_S = 30;\nconst int SCRIPT_OBJECT_INTENSITY_L = 80;\n\nvoid\ncAudioManager::ProcessScriptObject(int32 id)\n{\n\tif (MusicManager.m_nMusicMode == MUSICMODE_GAME) {\n\t\tcAudioScriptObject* entity = (cAudioScriptObject*)m_asAudioEntities[id].m_pEntity;\n\t\tif (entity != nil) {\n\t\t\tm_sQueueSample.m_vecPos = entity->Posn;\n\t\t\tif (m_asAudioEntities[id].m_AudioEvents == 1)\n\t\t\t\tProcessOneShotScriptObject(m_asAudioEntities[id].m_awAudioEvent[0]);\n\t\t\telse\n\t\t\t\tProcessLoopingScriptObject(entity->AudioId);\n\t\t}\n\t}\n}\n\nvoid\ncAudioManager::ProcessOneShotScriptObject(uint8 sound)\n{\n\tCPlayerPed *playerPed;\n\tuint8 emittingVolume;\n\tfloat distSquared;\n\n\tstatic uint8 iSound = 0;\n\n\tswitch (sound) {\n\tcase SCRIPT_SOUND_POLICE_CELL_DOOR_CLUNK:\n\t\tm_sQueueSample.m_fSoundIntensity = 40.0f;\n\t\tm_sQueueSample.m_nSampleIndex = SFX_COL_GATE;\n\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\tm_sQueueSample.m_nFrequency = 10600;\n\t\tm_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 32);\n\t\tm_sQueueSample.m_nReleasingVolumeModificator = 3;\n\t\temittingVolume = 60;\n\t\tm_sQueueSample.m_fSpeedMultiplier = 0.0f;\n\t\tm_sQueueSample.m_bIs2D = false;\n\t\tm_sQueueSample.m_bRequireReflection = true;\n\t\tbreak;\n\tcase SCRIPT_SOUND_GARAGE_DOOR_CLUNK:\n\t\tm_sQueueSample.m_fSoundIntensity = 80.0f;\n\t\tm_sQueueSample.m_nSampleIndex = SFX_COL_CAR_PANEL_2; // huh?\n\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\tm_sQueueSample.m_nFrequency = 22000;\n\t\tm_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 32);\n\t\tm_sQueueSample.m_nReleasingVolumeModificator = 4;\n\t\temittingVolume = 60;\n\t\tm_sQueueSample.m_fSpeedMultiplier = 0.0f;\n\t\tm_sQueueSample.m_bIs2D = false;\n\t\tm_sQueueSample.m_bRequireReflection = true;\n\t\tbreak;\n\tcase SCRIPT_SOUND_SHOOTING_RANGE_TARGET_HIT:\n\tcase SCRIPT_SOUND_BULLET_HIT_GROUND_1:\n\tcase SCRIPT_SOUND_BULLET_HIT_GROUND_2:\n\tcase SCRIPT_SOUND_BULLET_HIT_GROUND_3:\n\t\tm_sQueueSample.m_fSoundIntensity = 50.0f;\n\t\tm_sQueueSample.m_nSampleIndex = m_anRandomTable[iSound % 5] % 3 + SFX_BULLET_WALL_1;\n\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex);\n\t\tm_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 32);\n\t\tm_sQueueSample.m_nReleasingVolumeModificator = 9;\n\t\tm_sQueueSample.m_fSpeedMultiplier = 0.0f;\n\t\tm_sQueueSample.m_bIs2D = false;\n\t\temittingVolume = m_anRandomTable[2] % 20 + 90;\n\t\tbreak;\n\tcase SCRIPT_SOUND_WILLIE_CARD_SWIPE:\n\t\temittingVolume = 70;\n\t\tm_sQueueSample.m_fSoundIntensity = 40.0f;\n\t\tm_sQueueSample.m_nSampleIndex = SFX_BOMB_BEEP;\n\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\tm_sQueueSample.m_nFrequency = 20159;\n\t\tm_sQueueSample.m_nReleasingVolumeModificator = 1;\n\t\tm_sQueueSample.m_fSpeedMultiplier = 1.0f;\n\t\tm_sQueueSample.m_bIs2D = false;\n\t\tm_sQueueSample.m_bRequireReflection = false;\n\t\tbreak;\n\tcase SCRIPT_SOUND_MALE_AMBULANCE_OUCH:\n\t{\n\t\tcPedParams pedParams;\n\t\tpedParams.m_fDistance = GetDistanceSquared(m_sQueueSample.m_vecPos);\n\t\tSetupPedComments(pedParams, SOUND_INJURED_PED_MALE_OUCH);\n\t\treturn;\n\t}\n\tcase SCRIPT_SOUND_FEMALE_AMBULANCE_OUCH:\n\t{\n\t\tcPedParams pedParams;\n\t\tpedParams.m_fDistance = GetDistanceSquared(m_sQueueSample.m_vecPos);\n\t\tSetupPedComments(pedParams, SOUND_INJURED_PED_FEMALE);\n\t\treturn;\n\t}\n\tcase SCRIPT_SOUND_SEAPLANE_LOW_FUEL:\n\t\tm_sQueueSample.m_fSoundIntensity = 1000.0f;\n\t\tm_sQueueSample.m_nSampleIndex = SFX_SEAPLANE_LOW;\n\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\temittingVolume = 100;\n\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_CAR_HORN_JEEP); // BUG?\n\t\tm_sQueueSample.m_nReleasingVolumeModificator = 1;\n\t\tm_sQueueSample.m_fSpeedMultiplier = 0.0f;\n\t\tm_sQueueSample.m_bIs2D = true;\n\t\tm_sQueueSample.m_bRequireReflection = false;\n\t\tbreak;\n\tcase SCRIPT_SOUND_PAYPHONE_RINGING:\n\t\tm_sQueueSample.m_fSoundIntensity = 80.0f;\n\t\tm_sQueueSample.m_nSampleIndex = SFX_PHONE_RING;\n\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\temittingVolume = 80;\n\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_PHONE_RING);\n\t\tm_sQueueSample.m_nReleasingVolumeModificator = 1;\n\t\tm_sQueueSample.m_fSpeedMultiplier = 2.0f;\n\t\tm_sQueueSample.m_bIs2D = false;\n\t\tm_sQueueSample.m_bRequireReflection = false;\n\t\tbreak;\n\tcase SCRIPT_SOUND_GLASS_BREAK_L:\n\t\tm_sQueueSample.m_fSoundIntensity = 60.0f;\n\t\tm_sQueueSample.m_nSampleIndex = SFX_GLASS_SMASH;\n\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\temittingVolume = 70;\n\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_GLASS_SMASH);\n\t\tm_sQueueSample.m_nReleasingVolumeModificator = 3;\n\t\tm_sQueueSample.m_fSpeedMultiplier = 0.0f;\n\t\tm_sQueueSample.m_bIs2D = false;\n\t\tbreak;\n\tcase SCRIPT_SOUND_GLASS_BREAK_S:\n\t\tm_sQueueSample.m_fSoundIntensity = 60.0f;\n\t\tm_sQueueSample.m_nSampleIndex = SFX_GLASS_SMASH;\n\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\temittingVolume = 60;\n\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_GLASS_SMASH);\n\t\tm_sQueueSample.m_nReleasingVolumeModificator = 3;\n\t\tm_sQueueSample.m_fSpeedMultiplier = 0.0f;\n\t\tm_sQueueSample.m_bIs2D = false;\n\t\tbreak;\n\tcase SCRIPT_SOUND_GLASS_CRACK:\n\t\tm_sQueueSample.m_fSoundIntensity = 60.0f;\n\t\tm_sQueueSample.m_nSampleIndex = SFX_GLASS_CRACK;\n\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\temittingVolume = 70;\n\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_GLASS_CRACK);\n\t\tm_sQueueSample.m_nReleasingVolumeModificator = 3;\n\t\tm_sQueueSample.m_fSpeedMultiplier = 0.0f;\n\t\tm_sQueueSample.m_bIs2D = false;\n\t\tm_sQueueSample.m_bRequireReflection = true;\n\t\tbreak;\n\tcase SCRIPT_SOUND_GLASS_LIGHT_BREAK:\n\t\tm_sQueueSample.m_fSoundIntensity = 55.0f;\n\t\tm_sQueueSample.m_nSampleIndex = (m_anRandomTable[4] & 3) + SFX_GLASS_SHARD_1;\n\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\tm_sQueueSample.m_nFrequency = RandomDisplacement(2000) + 19000;\n\t\tm_sQueueSample.m_nReleasingVolumeModificator = 9;\n\t\tm_sQueueSample.m_fSpeedMultiplier = 0.0f;\n\t\tm_sQueueSample.m_bIs2D = false;\n\t\temittingVolume = RandomDisplacement(11) + 25;\n\t\tbreak;\n\tcase SCRIPT_SOUND_BOX_DESTROYED_1:\n\t\tm_sQueueSample.m_fSoundIntensity = 60.0f;\n\t\tm_sQueueSample.m_nSampleIndex = SFX_WOODEN_BOX_SMASH;\n\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\tm_sQueueSample.m_nFrequency = RandomDisplacement(1500) + 18600;\n\t\tm_sQueueSample.m_nReleasingVolumeModificator = 3;\n\t\tm_sQueueSample.m_fSpeedMultiplier = 0.0f;\n\t\tm_sQueueSample.m_bIs2D = false;\n\t\tm_sQueueSample.m_bRequireReflection = true;\n\t\temittingVolume = m_anRandomTable[2] % 20 + 80;\n\t\tbreak;\n\tcase SCRIPT_SOUND_BOX_DESTROYED_2:\n\t\tm_sQueueSample.m_fSoundIntensity = 60.0f;\n\t\tm_sQueueSample.m_nSampleIndex = SFX_CARDBOARD_BOX_SMASH;\n\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\tm_sQueueSample.m_nFrequency = RandomDisplacement(1500) + 18600;\n\t\tm_sQueueSample.m_nReleasingVolumeModificator = 3;\n\t\tm_sQueueSample.m_fSpeedMultiplier = 0.0f;\n\t\tm_sQueueSample.m_bIs2D = false;\n\t\tm_sQueueSample.m_bRequireReflection = true;\n\t\temittingVolume = m_anRandomTable[2] % 20 + 80;\n\t\tbreak;\n\tcase SCRIPT_SOUND_METAL_COLLISION:\n\t\tm_sQueueSample.m_fSoundIntensity = 60.0f;\n\t\tm_sQueueSample.m_nSampleIndex = m_anRandomTable[3] % 5 + SFX_COL_CAR_1;\n\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex);\n\t\tm_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 16);\n\t\tm_sQueueSample.m_nReleasingVolumeModificator = 3;\n\t\tm_sQueueSample.m_fSpeedMultiplier = 0.0f;\n\t\tm_sQueueSample.m_bIs2D = false;\n\t\tm_sQueueSample.m_bRequireReflection = true;\n\t\temittingVolume = m_anRandomTable[2] % 30 + 70;\n\t\tbreak;\n\tcase SCRIPT_SOUND_TIRE_COLLISION:\n\t\tm_sQueueSample.m_fSoundIntensity = 60.0f;\n\t\tm_sQueueSample.m_nSampleIndex = SFX_TYRE_BUMP;\n\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex);\n\t\tm_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 16);\n\t\tm_sQueueSample.m_nReleasingVolumeModificator = 3;\n\t\tm_sQueueSample.m_fSpeedMultiplier = 0.0f;\n\t\tm_sQueueSample.m_bIs2D = false;\n\t\tm_sQueueSample.m_bRequireReflection = true;\n\t\temittingVolume = m_anRandomTable[2] % 30 + 60;\n\t\tbreak;\n\tcase SCRIPT_SOUND_HIT_BALL:\n\t\tm_sQueueSample.m_fSoundIntensity = 60.0f;\n\t\tm_sQueueSample.m_nSampleIndex = SFX_HIT_BALL;\n\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex);\n\t\tm_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 16);\n\t\tm_sQueueSample.m_nReleasingVolumeModificator = 5;\n\t\tm_sQueueSample.m_fSpeedMultiplier = 0.0f;\n\t\tm_sQueueSample.m_bIs2D = false;\n\t\tm_sQueueSample.m_bRequireReflection = true;\n\t\temittingVolume = m_anRandomTable[2] % 30 + 60;\n\t\tbreak;\n\tcase SCRIPT_SOUND_GUNSHELL_DROP:\n\t\tplayerPed = FindPlayerPed();\n\t\tif (playerPed) {\n\t\t\tswitch (playerPed->m_nSurfaceTouched) {\n\t\t\tcase SURFACE_GRASS:\n\t\t\tcase SURFACE_GRAVEL:\n\t\t\tcase SURFACE_MUD_DRY:\n\t\t\tcase SURFACE_TRANSPARENT_CLOTH:\n\t\t\tcase SURFACE_PED:\n\t\t\tcase SURFACE_SAND:\n\t\t\tcase SURFACE_RUBBER:\n\t\t\tcase SURFACE_HEDGE:\n\t\t\tcase SURFACE_SAND_BEACH:\n\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_BULLET_SHELL_HIT_GROUND_2;\n\t\t\t\tm_sQueueSample.m_nFrequency = RandomDisplacement(600) + 10600;\n\t\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 18;\n\t\t\t\tbreak;\n\t\t\tcase SURFACE_WATER:\n\t\t\t\treturn;\n\t\t\tdefault:\n\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_BULLET_SHELL_HIT_GROUND_1;\n\t\t\t\tm_sQueueSample.m_nFrequency = RandomDisplacement(1500) + 30000;\n\t\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 15;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t} else {\n\t\t\tm_sQueueSample.m_nSampleIndex = SFX_BULLET_SHELL_HIT_GROUND_1;\n\t\t\tm_sQueueSample.m_nFrequency = RandomDisplacement(1500) + 30000;\n\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 15;\n\t\t}\n\t\tm_sQueueSample.m_fSoundIntensity = 20.0f;\n\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\tm_sQueueSample.m_fSpeedMultiplier = 0.0f;\n\t\tm_sQueueSample.m_bIs2D = false;\n\t\temittingVolume = m_anRandomTable[2] % 20 + 30;\n\t\tbreak;\n\tcase SCRIPT_SOUND_GUNSHELL_DROP_SOFT:\n\t\tm_sQueueSample.m_nSampleIndex = SFX_BULLET_SHELL_HIT_GROUND_2;\n\t\tm_sQueueSample.m_nFrequency = RandomDisplacement(500) + 11000;\n\t\tm_sQueueSample.m_nReleasingVolumeModificator = 18;\n\t\tm_sQueueSample.m_fSoundIntensity = 20.0f;\n\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\tm_sQueueSample.m_fSpeedMultiplier = 0.0f;\n\t\tm_sQueueSample.m_bIs2D = false;\n\t\temittingVolume = m_anRandomTable[2] % 20 + 30;\n\t\tbreak;\n\tdefault:\n\t\treturn;\n\t}\n\n\tdistSquared = GetDistanceSquared(m_sQueueSample.m_vecPos);\n\tif (distSquared < SQR(m_sQueueSample.m_fSoundIntensity)) {\n\t\tm_sQueueSample.m_fDistance = Sqrt(distSquared);\n\t\tm_sQueueSample.m_nVolume = ComputeVolume(emittingVolume, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance);\n\t\tif (m_sQueueSample.m_nVolume != 0) {\n\t\t\tm_sQueueSample.m_nCounter = iSound++;\n\t\t\tm_sQueueSample.m_nLoopCount = 1;\n\t\t\tm_sQueueSample.m_bReleasingSoundFlag = true;\n\t\t\tm_sQueueSample.m_nEmittingVolume = emittingVolume;\n\t\t\tm_sQueueSample.m_nLoopStart = 0;\n\t\t\tm_sQueueSample.m_nLoopEnd = -1;\n\t\t\tm_sQueueSample.m_bReverbFlag = true;\n\t\t\tAddSampleToRequestedQueue();\n\t\t}\n\t}\n}\n\nvoid\ncAudioManager::ProcessLoopingScriptObject(uint8 sound)\n{\n\tuint8 emittingVolume;\n\tfloat distSquared;\n\n\tswitch(sound) {\n\tcase SCRIPT_SOUND_BANK_ALARM_LOOP:\n\t\tm_sQueueSample.m_fSoundIntensity = 80.0f;\n\t\tm_sQueueSample.m_nSampleIndex = SFX_BUILDINGS_BANK_ALARM;\n\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_BUILDING_BANK_ALARM;\n\t\temittingVolume = 90;\n\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_BUILDINGS_BANK_ALARM);\n\t\tm_sQueueSample.m_nReleasingVolumeModificator = 2;\n\t\tm_sQueueSample.m_nReleasingVolumeDivider = 3;\n\t\tm_sQueueSample.m_fSpeedMultiplier = 2.0f;\n\t\tm_sQueueSample.m_bIs2D = false;\n\t\tbreak;\n\tcase SCRIPT_SOUND_POLICE_CELL_DOOR_SLIDING_LOOP:\n\tcase SCRIPT_SOUND_GARAGE_DOOR_SLIDING_LOOP:\n\t\tm_sQueueSample.m_fSoundIntensity = 80.0f;\n\t\tm_sQueueSample.m_nSampleIndex = SFX_GARAGE_DOOR_LOOP;\n\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\temittingVolume = 90;\n\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_GARAGE_DOOR_LOOP);\n\t\tm_sQueueSample.m_nReleasingVolumeModificator = 3;\n\t\tm_sQueueSample.m_nReleasingVolumeDivider = 3;\n\t\tm_sQueueSample.m_fSpeedMultiplier = 2.0f;\n\t\tm_sQueueSample.m_bIs2D = false;\n\t\tbreak;\n\tcase SCRIPT_SOUND_SNORING_LOOP:\n\t\tm_sQueueSample.m_fSoundIntensity = 6.0f;\n\t\tm_sQueueSample.m_nSampleIndex = SFX_BUILDING_SNORE;\n\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_BUILDING_SNORING;\n\t\temittingVolume = 25;\n\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_BUILDING_SNORE);\n\t\tm_sQueueSample.m_nReleasingVolumeModificator = 6;\n\t\tm_sQueueSample.m_nReleasingVolumeDivider = 3;\n\t\tm_sQueueSample.m_fSpeedMultiplier = 3.0f;\n\t\tm_sQueueSample.m_bIs2D = false;\n\t\tbreak;\n\tcase SCRIPT_SOUND_SHOOTING_RANGE_TARGET_MOVING_LOOP:\n\t\tm_sQueueSample.m_fSoundIntensity = 40.0f;\n\t\tm_sQueueSample.m_nSampleIndex = SFX_TANK_TURRET;\n\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\temittingVolume = 60;\n\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_TANK_TURRET);\n\t\tm_sQueueSample.m_nReleasingVolumeModificator = 4;\n\t\tm_sQueueSample.m_nReleasingVolumeDivider = 3;\n\t\tm_sQueueSample.m_fSpeedMultiplier = 2.0f;\n\t\tm_sQueueSample.m_bIs2D = false;\n\t\tbreak;\n\tcase SCRIPT_SOUND_NEW_BUILDING_BAR_1:\n\t\tm_sQueueSample.m_nSampleIndex = SFX_BUILDING_BAR_1;\n\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_BUILDING_BAR_1;\n\t\tm_sQueueSample.m_fSoundIntensity = 80.0f;\n\t\temittingVolume = 127;\n\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex);\n\t\tm_sQueueSample.m_nReleasingVolumeModificator = 3;\n\t\tm_sQueueSample.m_nReleasingVolumeDivider = 15;\n\t\tm_sQueueSample.m_fSpeedMultiplier = 4.0f;\n\t\tm_sQueueSample.m_bIs2D = false;\n\t\tbreak;\n\tcase SCRIPT_SOUND_NEW_BUILDING_BAR_2:\n\t\tm_sQueueSample.m_nSampleIndex = SFX_BUILDING_BAR_2;\n\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_BUILDING_BAR_2;\n\t\tm_sQueueSample.m_fSoundIntensity = 80.0f;\n\t\temittingVolume = 127;\n\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex);\n\t\tm_sQueueSample.m_nReleasingVolumeModificator = 3;\n\t\tm_sQueueSample.m_nReleasingVolumeDivider = 15;\n\t\tm_sQueueSample.m_fSpeedMultiplier = 4.0f;\n\t\tm_sQueueSample.m_bIs2D = false;\n\t\tbreak;\n\tcase SCRIPT_SOUND_NEW_BUILDING_BAR_3:\n\t\tm_sQueueSample.m_nSampleIndex = SFX_BUILDING_BAR_3;\n\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_BUILDING_BAR_3;\n\t\tm_sQueueSample.m_fSoundIntensity = 80.0f;\n\t\temittingVolume = 127;\n\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex);\n\t\tm_sQueueSample.m_nReleasingVolumeModificator = 3;\n\t\tm_sQueueSample.m_nReleasingVolumeDivider = 15;\n\t\tm_sQueueSample.m_fSpeedMultiplier = 4.0f;\n\t\tm_sQueueSample.m_bIs2D = false;\n\t\tbreak;\n\tcase SCRIPT_SOUND_NEW_BUILDING_BAR_4:\n\t\tm_sQueueSample.m_nSampleIndex = SFX_BUILDING_BAR_4;\n\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_BUILDING_BAR_4;\n\t\tm_sQueueSample.m_fSoundIntensity = 80.0f;\n\t\temittingVolume = 127;\n\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex);\n\t\tm_sQueueSample.m_nReleasingVolumeModificator = 3;\n\t\tm_sQueueSample.m_nReleasingVolumeDivider = 15;\n\t\tm_sQueueSample.m_fSpeedMultiplier = 4.0f;\n\t\tm_sQueueSample.m_bIs2D = false;\n\t\tbreak;\n\tcase SCRIPT_SOUND_NEW_BUILDING_MALIBU_1:\n\t\tif(MusicManager.m_nPlayingTrack == STREAMED_SOUND_MALIBU_AMBIENT) return;\n\t\tm_sQueueSample.m_nSampleIndex = SFX_BUILDING_MAL1;\n\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_BUILDING_MALIBU_1;\n\t\tMusicManager.SetMalibuClubTrackPos(SCRIPT_SOUND_NEW_BUILDING_MALIBU_1);\n\t\tm_sQueueSample.m_fSoundIntensity = 80.0f;\n\t\temittingVolume = 127;\n\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex);\n\t\tm_sQueueSample.m_nReleasingVolumeModificator = 3;\n\t\tm_sQueueSample.m_nReleasingVolumeDivider = 15;\n\t\tm_sQueueSample.m_fSpeedMultiplier = 4.0f;\n\t\tm_sQueueSample.m_bIs2D = false;\n\t\tbreak;\n\tcase SCRIPT_SOUND_NEW_BUILDING_MALIBU_2:\n\t\tif(MusicManager.m_nPlayingTrack == STREAMED_SOUND_MALIBU_AMBIENT) return;\n\t\tm_sQueueSample.m_nSampleIndex = SFX_BUILDING_MAL2;\n\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_BUILDING_MALIBU_2;\n\t\tMusicManager.SetMalibuClubTrackPos(SCRIPT_SOUND_NEW_BUILDING_MALIBU_2);\n\t\tm_sQueueSample.m_fSoundIntensity = 80.0f;\n\t\temittingVolume = 127;\n\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex);\n\t\tm_sQueueSample.m_nReleasingVolumeModificator = 3;\n\t\tm_sQueueSample.m_nReleasingVolumeDivider = 15;\n\t\tm_sQueueSample.m_fSpeedMultiplier = 4.0f;\n\t\tm_sQueueSample.m_bIs2D = false;\n\t\tbreak;\n\tcase SCRIPT_SOUND_NEW_BUILDING_MALIBU_3:\n\t\tif(MusicManager.m_nPlayingTrack == STREAMED_SOUND_MALIBU_AMBIENT) return;\n\t\tm_sQueueSample.m_nSampleIndex = SFX_BUILDING_MAL3;\n\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_BUILDING_MALIBU_3;\n\t\tMusicManager.SetMalibuClubTrackPos(SCRIPT_SOUND_NEW_BUILDING_MALIBU_3);\n\t\tm_sQueueSample.m_fSoundIntensity = 80.0f;\n\t\temittingVolume = 127;\n\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex);\n\t\tm_sQueueSample.m_nReleasingVolumeModificator = 3;\n\t\tm_sQueueSample.m_nReleasingVolumeDivider = 15;\n\t\tm_sQueueSample.m_fSpeedMultiplier = 4.0f;\n\t\tm_sQueueSample.m_bIs2D = false;\n\t\tbreak;\n\tcase SCRIPT_SOUND_NEW_BUILDING_STRIP_1:\n\t\tif(MusicManager.m_nPlayingTrack == STREAMED_SOUND_STRIPCLUB_AMBIENT) return;\n\t\tm_sQueueSample.m_nSampleIndex = SFX_BUILDING_STR1;\n\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_BUILDING_STRIP_1;\n\t\tMusicManager.SetStripClubTrackPos(SCRIPT_SOUND_NEW_BUILDING_STRIP_1);\n\t\tm_sQueueSample.m_fSoundIntensity = 80.0f;\n\t\temittingVolume = 127;\n\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex);\n\t\tm_sQueueSample.m_nReleasingVolumeModificator = 3;\n\t\tm_sQueueSample.m_nReleasingVolumeDivider = 15;\n\t\tm_sQueueSample.m_fSpeedMultiplier = 4.0f;\n\t\tm_sQueueSample.m_bIs2D = false;\n\t\tbreak;\n\tcase SCRIPT_SOUND_NEW_BUILDING_STRIP_2:\n\t\tif(MusicManager.m_nPlayingTrack == STREAMED_SOUND_STRIPCLUB_AMBIENT) return;\n\t\tm_sQueueSample.m_nSampleIndex = SFX_BUILDING_STR2;\n\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_BUILDING_STRIP_2;\n\t\tMusicManager.SetStripClubTrackPos(SCRIPT_SOUND_NEW_BUILDING_STRIP_2);\n\t\tm_sQueueSample.m_fSoundIntensity = 80.0f;\n\t\temittingVolume = 127;\n\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex);\n\t\tm_sQueueSample.m_nReleasingVolumeModificator = 3;\n\t\tm_sQueueSample.m_nReleasingVolumeDivider = 15;\n\t\tm_sQueueSample.m_fSpeedMultiplier = 4.0f;\n\t\tm_sQueueSample.m_bIs2D = false;\n\t\tbreak;\n\tcase SCRIPT_SOUND_NEW_BUILDING_STRIP_3:\n\t\tif(MusicManager.m_nPlayingTrack == STREAMED_SOUND_STRIPCLUB_AMBIENT) return;\n\t\tm_sQueueSample.m_nSampleIndex = SFX_BUILDING_STR3;\n\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_BUILDING_STRIP_3;\n\t\tMusicManager.SetStripClubTrackPos(SCRIPT_SOUND_NEW_BUILDING_STRIP_3);\n\t\tm_sQueueSample.m_fSoundIntensity = 80.0f;\n\t\temittingVolume = 127;\n\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex);\n\t\tm_sQueueSample.m_nReleasingVolumeModificator = 3;\n\t\tm_sQueueSample.m_nReleasingVolumeDivider = 15;\n\t\tm_sQueueSample.m_fSpeedMultiplier = 4.0f;\n\t\tm_sQueueSample.m_bIs2D = false;\n\t\tbreak;\n\tcase SCRIPT_SOUND_NEW_BUILDING_CHURCH:\n\t\tm_sQueueSample.m_nSampleIndex = SFX_BUILDING_CHURCH;\n\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_BUILDING_CHURCH;\n\t\tm_sQueueSample.m_fSoundIntensity = 80.0f;\n\t\temittingVolume = 127;\n\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex);\n\t\tm_sQueueSample.m_nReleasingVolumeModificator = 3;\n\t\tm_sQueueSample.m_nReleasingVolumeDivider = 15;\n\t\tm_sQueueSample.m_fSpeedMultiplier = 4.0f;\n\t\tm_sQueueSample.m_bIs2D = false;\n\t\tbreak;\n\tcase SCRIPT_SOUND_NEW_WATERFALL:\n\t\temittingVolume = 30;\n\t\tm_sQueueSample.m_fSoundIntensity = 80.0f;\n\t\tm_sQueueSample.m_nSampleIndex = SFX_BOAT_WATER_LOOP;\n\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\tm_sQueueSample.m_nFrequency = 20812;\n\t\tm_sQueueSample.m_nReleasingVolumeModificator = 4;\n\t\tm_sQueueSample.m_nReleasingVolumeDivider = 9;\n\t\tm_sQueueSample.m_fSpeedMultiplier = 2.0f;\n\t\tm_sQueueSample.m_bIs2D = false;\n\t\tbreak;\n\tdefault: return;\n\t}\n\n\tdistSquared = GetDistanceSquared(m_sQueueSample.m_vecPos);\n\tif(distSquared < SQR(m_sQueueSample.m_fSoundIntensity)) {\n\t\tm_sQueueSample.m_fDistance = Sqrt(distSquared);\n\t\tm_sQueueSample.m_nVolume = ComputeVolume(emittingVolume, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance);\n\t\tif(m_sQueueSample.m_nVolume != 0) {\n\t\t\tm_sQueueSample.m_nCounter = 0;\n\t\t\tm_sQueueSample.m_bIs2D = false;\n\t\t\tm_sQueueSample.m_nLoopCount = 0;\n\t\t\tm_sQueueSample.m_bReleasingSoundFlag = false;\n\t\t\tm_sQueueSample.m_bReverbFlag = true;\n\t\t\tm_sQueueSample.m_nEmittingVolume = emittingVolume;\n\t\t\tm_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex);\n\t\t\tm_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex);\n\t\t\tm_sQueueSample.m_bRequireReflection = false;\n\t\t\tAddSampleToRequestedQueue();\n\t\t}\n\t}\n}\n#pragma endregion All the code for script object audio on the map\n\nvoid\ncAudioManager::ProcessWeather(int32 id)\n{\n\tuint8 vol;\n\tfloat x;\n\tfloat y;\n\tfloat modifier;\n\tfloat wind;\n\n\tstatic uint8 iSound = 0;\n\n\tif (m_asAudioEntities[id].m_AudioEvents != 0 && m_asAudioEntities[id].m_awAudioEvent[0] == SOUND_LIGHTNING) {\n\t\tif (m_asAudioEntities[id].m_afVolume[0] >= 10.f) {\n\t\t\tm_sQueueSample.m_nSampleIndex = SFX_EXPLOSION_1;\n\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_GENERIC_EXTRA;\n\t\t\tm_sQueueSample.m_nFrequency = RandomDisplacement(500) + 4000;\n\t\t\tvol = (m_asAudioEntities[id].m_afVolume[0] - 10.0f) + 40;\n\t\t} else {\n\t\t\tm_sQueueSample.m_nSampleIndex = SFX_EXPLOSION_2;\n\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\tm_sQueueSample.m_nFrequency = RandomDisplacement(500) + 4000;\n\t\t\tvol = (m_asAudioEntities[id].m_afVolume[0]) + 35;\n\t\t}\n\t\tm_sQueueSample.m_nVolume = vol;\n\t\tif (TheCamera.SoundDistUp < 20.0f)\n\t\t\tm_sQueueSample.m_nVolume /= 2;\n\t\tif (iSound == 4)\n\t\t\tiSound = 0;\n\t\tm_sQueueSample.m_nCounter = iSound++;\n\t\tm_sQueueSample.m_nReleasingVolumeModificator = 0;\n\t\tm_sQueueSample.m_nOffset = (m_anRandomTable[2] & 15) + 55;\n\t\tm_sQueueSample.m_bIs2D = true;\n\t\tm_sQueueSample.m_nLoopCount = 1;\n\t\tm_sQueueSample.m_bReleasingSoundFlag = true;\n\t\tm_sQueueSample.m_nEmittingVolume = m_sQueueSample.m_nVolume;\n\t\tm_sQueueSample.m_nLoopStart = 0;\n\t\tm_sQueueSample.m_nLoopEnd = -1;\n\t\tm_sQueueSample.m_bReverbFlag = false;\n\t\tm_sQueueSample.m_bRequireReflection = false;\n\t\tAddSampleToRequestedQueue();\n\t}\n\tif (CWeather::Rain > 0.0f && (!CCullZones::CamNoRain() || !CCullZones::PlayerNoRain())) {\n\t\tm_sQueueSample.m_nSampleIndex = SFX_RAIN;\n\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_RAIN);\n\t\tm_sQueueSample.m_nVolume = (uint8)(25.0f * CWeather::Rain);\n\t\tm_sQueueSample.m_nCounter = 4;\n\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\tm_sQueueSample.m_nReleasingVolumeModificator = 0;\n\t\tm_sQueueSample.m_nOffset = 63;\n\t\tm_sQueueSample.m_bIs2D = true;\n\t\tm_sQueueSample.m_nLoopCount = 0;\n\t\tm_sQueueSample.m_bReleasingSoundFlag = false;\n\t\tm_sQueueSample.m_nReleasingVolumeDivider = 30;\n\t\tm_sQueueSample.m_bReverbFlag = false;\n\t\tm_sQueueSample.m_nEmittingVolume = m_sQueueSample.m_nVolume;\n\t\tm_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex);\n\t\tm_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex);\n\t\tm_sQueueSample.m_bRequireReflection = false;\n\t\tAddSampleToRequestedQueue();\n\t}\n\tx = 0.0f;\n\ty = 0.0f;\n\tCWindModifiers::FindWindModifier(TheCamera.GetPosition(), &x, &y);\n\tmodifier = Max(Abs(x), Abs(y)) * 10.0f;\n\tmodifier = Min(1.0f, modifier);\n\twind = Max(CWeather::Wind, modifier);\n\tif (wind > 0.0f && CObject::fDistToNearestTree < 75.0f) {\n\t\tm_sQueueSample.m_nSampleIndex = SFX_PALM_TREE_LO;\n\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_PALM_TREE_LO);\n\t\tm_sQueueSample.m_nVolume = (m_anRandomTable[1] % 10 + 45.0f) * (75.0f - CObject::fDistToNearestTree) * (4.0f / 300.0f) * wind;\n\t\tm_sQueueSample.m_nCounter = 5;\n\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\tm_sQueueSample.m_nReleasingVolumeModificator = 1;\n\t\tm_sQueueSample.m_nOffset = 63;\n\t\tm_sQueueSample.m_bIs2D = true;\n\t\tm_sQueueSample.m_nLoopCount = 0;\n\t\tm_sQueueSample.m_bReleasingSoundFlag = false;\n\t\tm_sQueueSample.m_nReleasingVolumeDivider = 7;\n\t\tm_sQueueSample.m_bReverbFlag = false;\n\t\tm_sQueueSample.m_nEmittingVolume = m_sQueueSample.m_nVolume;\n\t\tm_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex);\n\t\tm_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex);\n\t\tm_sQueueSample.m_bRequireReflection = false;\n\t\tAddSampleToRequestedQueue();\n\t\tCObject::fDistToNearestTree = 999999.9f;\n\t}\n}\n\nvoid\ncAudioManager::ProcessFrontEnd()\n{\n\tbool stereo;\n\tbool processedPickup;\n\tbool processedMission;\n\tbool staticFreq;\n\tbool center;\n\tint16 sample;\n\n\tstatic uint8 iSound = 0;\n\tstatic uint32 cPickupNextFrame = 0;\n\tstatic uint32 cPartMisComNextFrame = 0;\n\tstatic uint32 radioDial = SFX_RADIO_DIAL_1;\n\n\tfor (uint32 i = 0; i < m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_AudioEvents; i++) {\n\t\tstaticFreq = false;\n\t\tprocessedPickup = false;\n\t\tcenter = false;\n\t\tprocessedMission = false;\n\t\tstereo = false;\n\t\tswitch (m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_awAudioEvent[i]) {\n\t\tcase SOUND_WEAPON_SNIPER_SHOT_NO_ZOOM:\n\t\t\tm_sQueueSample.m_nSampleIndex = SFX_ERROR_FIRE_RIFLE;\n\t\t\tbreak;\n\t\tcase SOUND_WEAPON_ROCKET_SHOT_NO_ZOOM:\n\t\t\tm_sQueueSample.m_nSampleIndex = SFX_ERROR_FIRE_ROCKET_LAUNCHER;\n\t\t\tbreak;\n\t\tcase SOUND_GARAGE_NO_MONEY:\n\t\tcase SOUND_GARAGE_BAD_VEHICLE:\n\t\tcase SOUND_GARAGE_BOMB_ALREADY_SET:\n\t\t\tm_sQueueSample.m_nSampleIndex = SFX_WEAPON_LEFT;\n\t\t\tstereo = true;\n\t\t\tstaticFreq = true;\n\t\t\tcenter = true;\n\t\t\tbreak;\n\t\tcase SOUND_GARAGE_OPENING:\n\t\tcase SOUND_71: //case SOUND_41:\n\t\tcase SOUND_GARAGE_VEHICLE_DECLINED:\n\t\tcase SOUND_GARAGE_VEHICLE_ACCEPTED:\n\t\tcase SOUND_EVIDENCE_PICKUP:\n\t\tcase SOUND_UNLOAD_GOLD:\n\t\t\tstereo = true;\n\t\t\tprocessedPickup = true;\n\t\t\tm_sQueueSample.m_nSampleIndex = SFX_MONEY_LEFT;\n\t\t\tbreak;\n\t\tcase SOUND_GARAGE_BOMB1_SET:\n\t\tcase SOUND_GARAGE_BOMB2_SET:\n\t\tcase SOUND_GARAGE_BOMB3_SET:\n\t\tcase SOUND_PICKUP_WEAPON_BOUGHT:\n\t\tcase SOUND_PICKUP_WEAPON:\n\t\t\tcenter = true;\n\t\t\tprocessedPickup = true;\n\t\t\tm_sQueueSample.m_nSampleIndex = SFX_WEAPON_LEFT;\n\t\t\tstereo = true;\n\t\t\tbreak;\n\t\tcase SOUND_PICKUP_HEALTH:\n\t\tcase SOUND_81: //case SOUND_4B:\n\t\tcase SOUND_PICKUP_ADRENALINE:\n\t\tcase SOUND_PICKUP_ARMOUR:\n\t\t\tstereo = true;\n\t\t\tprocessedPickup = true;\n\t\t\tm_sQueueSample.m_nSampleIndex = SFX_MONEY_LEFT;\n\t\t\tbreak;\n\t\tcase SOUND_80:\n\t\t\tstereo = true;\n\t\t\tprocessedPickup = true;\n\t\t\tm_sQueueSample.m_nSampleIndex = SFX_WEAPON_LEFT;\n\t\t\tcenter = true;\n\t\t\tstaticFreq = true;\n\t\t\tbreak;\n\t\tcase SOUND_PICKUP_BONUS:\n\t\tcase SOUND_FRONTEND_MENU_STARTING:\n\t\tcase SOUND_HUD:\n\t\t\tstereo = true;\n\t\t\tm_sQueueSample.m_nSampleIndex = SFX_INFO_LEFT;\n\t\t\tcenter = true;\n\t\t\tbreak;\n\t\tcase SOUND_PICKUP_MONEY:\n\t\t\tstereo = true;\n\t\t\tprocessedPickup = true;\n\t\t\tm_sQueueSample.m_nSampleIndex = SFX_MONEY_LEFT;\n\t\t\tbreak;\n\t\tcase SOUND_PICKUP_HIDDEN_PACKAGE:\n\t\tcase SOUND_PICKUP_PACMAN_PILL:\n\t\tcase SOUND_PICKUP_PACMAN_PACKAGE:\n\t\tcase SOUND_PICKUP_FLOAT_PACKAGE:\n\t\t\tcenter = true;\n\t\t\tprocessedPickup = true;\n\t\t\tm_sQueueSample.m_nSampleIndex = SFX_PART_MISSION_COMPLETE_LEFT;\n\t\t\tstereo = true;\n\t\t\tbreak;\n\t\tcase SOUND_RACE_START_3:\n\t\tcase SOUND_RACE_START_2:\n\t\tcase SOUND_RACE_START_1:\n\t\tcase SOUND_PART_MISSION_COMPLETE:\n\t\t\tstereo = true;\n\t\t\tm_sQueueSample.m_nSampleIndex = SFX_PART_MISSION_COMPLETE_LEFT;\n\t\t\tprocessedMission = true;\n\t\t\tcenter = true;\n\t\t\tbreak;\n\t\tcase SOUND_RACE_START_GO:\n\t\t\tstereo = true;\n\t\t\tm_sQueueSample.m_nSampleIndex = SFX_GO_LEFT;\n\t\t\tcenter = true;\n\t\t\tbreak;\n\t\tcase SOUND_CLOCK_TICK:\n\t\t\tm_sQueueSample.m_nSampleIndex = SFX_TIMER;\n\t\t\tbreak;\n\t\tcase SOUND_FRONTEND_RADIO_TURN_OFF:\n\t\tcase SOUND_FRONTEND_RADIO_TURN_ON:\n\t\t\tm_sQueueSample.m_nSampleIndex = SFX_RADIO_CLICK;\n\t\t\tbreak;\n\t\tcase SOUND_FRONTEND_HURRICANE:\n\t\t\tm_sQueueSample.m_nSampleIndex = SFX_HURRICANE_MA;\n\t\t\tbreak;\n\t\tcase SOUND_BULLETTRACE_1:\n\t\tcase SOUND_BULLETTRACE_2:\n\t\t\tm_sQueueSample.m_nSampleIndex = (m_anRandomTable[0] % 2) + SFX_BULLET_PASS_1;\n\t\t\tbreak;\n\t\tcase SOUND_AMMUNATION_IMRAN_ARM_BOMB:\n\t\t\tm_sQueueSample.m_nSampleIndex = SFX_ARM_BOMB;\n\t\t\tbreak;\n\t\tcase SOUND_RADIO_CHANGE:\n\t\t\tm_sQueueSample.m_nSampleIndex = (m_anRandomTable[1] % 2) ? radioDial + 1 : radioDial + 2;\n\t\t\tif (m_sQueueSample.m_nSampleIndex > SFX_RADIO_DIAL_12)\n\t\t\t\tm_sQueueSample.m_nSampleIndex -= 12;\n\t\t\tradioDial = m_sQueueSample.m_nSampleIndex;\n\t\t\tbreak;\n\t\tcase SOUND_FRONTEND_HIGHLIGHT_OPTION:\n\t\t\tstereo = true;\n\t\t\tm_sQueueSample.m_nSampleIndex = SFX_FE_HIGHLIGHT_LEFT;\n\t\t\tbreak;\n\t\tcase SOUND_FRONTEND_ENTER_OR_ADJUST:\n\t\t\tstereo = true;\n\t\t\tm_sQueueSample.m_nSampleIndex = SFX_FE_SELECT_LEFT;\n\t\t\tbreak;\n\t\tcase SOUND_FRONTEND_BACK:\n\t\t\tstereo = true;\n\t\t\tm_sQueueSample.m_nSampleIndex = SFX_FE_BACK_LEFT;\n\t\t\tbreak;\n\t\tcase SOUND_FRONTEND_FAIL:\n\t\t\tstereo = true;\n\t\t\tm_sQueueSample.m_nSampleIndex = SFX_FE_ERROR_LEFT;\n\t\t\tbreak;\n\t\tcase SOUND_FRONTEND_AUDIO_TEST:\n\t\t\tm_sQueueSample.m_nSampleIndex = m_anRandomTable[0] % 3 + SFX_FE_NOISE_BURST_1;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (processedPickup) {\n\t\t\tif (m_FrameCounter <= cPickupNextFrame)\n\t\t\t\tcontinue;\n\t\t\tcPickupNextFrame = m_FrameCounter + 5;\n\t\t} else if (processedMission) {\n\t\t\tif (m_FrameCounter <= cPartMisComNextFrame)\n\t\t\t\tcontinue;\n\t\t\tcPartMisComNextFrame = m_FrameCounter + 5;\n\t\t}\n\n\t\tsample = m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_awAudioEvent[i];\n\n\t\tif (sample == SOUND_FRONTEND_RADIO_TURN_OFF)\n\t\t\tm_sQueueSample.m_nFrequency = 28509;\n\t\telse if (sample == SOUND_FRONTEND_RADIO_TURN_ON)\n\t\t\tm_sQueueSample.m_nFrequency = 32000;\n\t\telse if (sample == SOUND_BULLETTRACE_1 || sample == SOUND_BULLETTRACE_2) {\n\t\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex);\n\t\t\tm_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 32);\n\t\t} else if (staticFreq)\n\t\t\tm_sQueueSample.m_nFrequency = 5382;\n\t\telse\n\t\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex);\n\n\t\tm_sQueueSample.m_nVolume = 127;\n\t\tif (m_sQueueSample.m_nSampleIndex == SFX_HURRICANE_MA && CWeather::Wind > 1.0f)\n\t\t\tm_sQueueSample.m_nVolume = (CWeather::Wind - 1.0f) * m_sQueueSample.m_nVolume;\n\t\tm_sQueueSample.m_nCounter = iSound++;\n\t\tm_sQueueSample.m_nLoopCount = 1;\n\t\tm_sQueueSample.m_bReleasingSoundFlag = true;\n\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_FRONT_END_MENU;\n\t\tm_sQueueSample.m_nReleasingVolumeModificator = 0;\n\t\tm_sQueueSample.m_bIs2D = true;\n\t\tm_sQueueSample.m_nEmittingVolume = m_sQueueSample.m_nVolume;\n\t\tm_sQueueSample.m_nLoopStart = 0;\n\t\tm_sQueueSample.m_nLoopEnd = -1;\n\t\tm_sQueueSample.m_fDistance = 1.0f;\n\t\tif (stereo) \n\t\t\tm_sQueueSample.m_nOffset = 0;\n\t\telse {\n\t\t\tsample = m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_awAudioEvent[i];\n\t\t\tif (sample == SOUND_BULLETTRACE_1) {\n\t\t\t\tm_sQueueSample.m_nOffset = 20;\n\t\t\t\tm_sQueueSample.m_nVolume = m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_afVolume[i];\n\t\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 10;\n\t\t\t\tm_sQueueSample.m_fDistance = 100.0f;\n\t\t\t}\n\t\t\tif (sample == SOUND_BULLETTRACE_2) {\n\t\t\t\tm_sQueueSample.m_nOffset = 107;\n\t\t\t\tm_sQueueSample.m_nVolume = m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_afVolume[i];\n\t\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 10;\n\t\t\t\tm_sQueueSample.m_fDistance = 100.0f;\n\t\t\t}\n\t\t\tm_sQueueSample.m_nOffset = 63;\n\t\t}\n\t\tm_sQueueSample.m_bReverbFlag = false;\n\t\tm_sQueueSample.m_bRequireReflection = false;\n\t\tAddSampleToRequestedQueue();\n\t\tif (stereo) {\n\t\t\t++m_sQueueSample.m_nSampleIndex;\n\t\t\tm_sQueueSample.m_nCounter = iSound++;\n\t\t\tm_sQueueSample.m_nOffset = 127 - m_sQueueSample.m_nOffset;\n\t\t\tAddSampleToRequestedQueue();\n\t\t}\n\t\tif (center) {\n\t\t\t++m_sQueueSample.m_nSampleIndex;\n\t\t\tm_sQueueSample.m_nCounter = iSound++;\n\t\t\tm_sQueueSample.m_nOffset = 63;\n\t\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex);\n\t\t\tAddSampleToRequestedQueue();\n\t\t}\n\t}\n}\n\n/*void\ncAudioManager::ProcessCrane()\n{\n\tCCrane *crane = (CCrane *)m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_pEntity;\n\tfloat distSquared;\n\tbool distCalculated = false;\n\tstatic const int intensity = 80;\n\n\tif (crane) {\n\t\tif (crane->m_nCraneStatus == CCrane::ACTIVATED) {\n\t\t\tif (crane->m_nCraneState != CCrane::IDLE) {\n\t\t\t\tm_sQueueSample.m_vecPos = crane->m_pCraneEntity->GetPosition();\n\t\t\t\tdistSquared = GetDistanceSquared(m_sQueueSample.m_vecPos);\n\t\t\t\tif (distSquared < SQR(intensity)) {\n\t\t\t\t\tCalculateDistance(distCalculated, distSquared);\n\t\t\t\t\tm_sQueueSample.m_nVolume = ComputeVolume(100, 80.f, m_sQueueSample.m_fDistance);\n\t\t\t\t\tif (m_sQueueSample.m_nVolume != 0) {\n\t\t\t\t\t\tm_sQueueSample.m_nCounter = 0;\n\t\t\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_CRANE_MAGNET;\n\t\t\t\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\t\t\t\tm_sQueueSample.m_bIs2D = false;\n\t\t\t\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 2;\n\t\t\t\t\t\tm_sQueueSample.m_nFrequency = 6000;\n\t\t\t\t\t\tm_sQueueSample.m_nLoopCount = 0;\n\t\t\t\t\t\tm_sQueueSample.m_nEmittingVolume = 100;\n\t\t\t\t\t\tm_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex);\n\t\t\t\t\t\tm_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex);\n\t\t\t\t\t\tm_sQueueSample.m_fSpeedMultiplier = 4.0f;\n\t\t\t\t\t\tm_sQueueSample.m_fSoundIntensity = intensity;\n\t\t\t\t\t\tm_sQueueSample.m_bReleasingSoundFlag = false;\n\t\t\t\t\t\tm_sQueueSample.m_nReleasingVolumeDivider = 3;\n\t\t\t\t\t\tm_sQueueSample.m_bReverbFlag = true;\n\t\t\t\t\t\tm_sQueueSample.m_bRequireReflection = false;\n\t\t\t\t\t\tAddSampleToRequestedQueue();\n\t\t\t\t\t}\n\t\t\t\t\tif (m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_AudioEvents) {\n\t\t\t\t\t\tm_sQueueSample.m_nCounter = 1;\n\t\t\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_COL_CAR_2;\n\t\t\t\t\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_COL_CAR_2);\n\t\t\t\t\t\tm_sQueueSample.m_nLoopCount = 1;\n\t\t\t\t\t\tm_sQueueSample.m_bReleasingSoundFlag = true;\n\t\t\t\t\t\tm_sQueueSample.m_bReverbFlag = true;\n\t\t\t\t\t\tm_sQueueSample.m_bRequireReflection = true;\n\t\t\t\t\t\tAddSampleToRequestedQueue();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}*/\n\nvoid\ncAudioManager::ProcessProjectiles()\n{\n\tuint8 emittingVol;\n\tfloat distSquared;\n\n\tfor (int32 i = 0; i < NUM_PROJECTILES; i++) {\n\t\tif (CProjectileInfo::GetProjectileInfo(i)->m_bInUse) {\n\t\t\tswitch (CProjectileInfo::GetProjectileInfo(i)->m_eWeaponType) {\n\t\t\tcase WEAPONTYPE_TEARGAS:\n\t\t\t\temittingVol = 80;\n\t\t\t\tm_sQueueSample.m_fSoundIntensity = 40.0f;\n\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_PALM_TREE_LO;\n\t\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\t\tm_sQueueSample.m_nFrequency = 13879;\n\t\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 7;\n\t\t\t\tbreak;\n\t\t\tcase WEAPONTYPE_MOLOTOV:\n\t\t\t\temittingVol = 50;\n\t\t\t\tm_sQueueSample.m_fSoundIntensity = 30.0f;\n\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_PED_ON_FIRE;\n\t\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\t\tm_sQueueSample.m_nFrequency = 32 * SampleManager.GetSampleBaseFrequency(SFX_PED_ON_FIRE) / 25;\n\t\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 7;\n\t\t\t\tbreak;\n\t\t\tcase WEAPONTYPE_ROCKET:\n\t\t\t\temittingVol = 127;\n\t\t\t\tm_sQueueSample.m_fSoundIntensity = 90.0f;\n\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_ROCKET_FLY;\n\t\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_ROCKET_FLY);\n\t\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 3;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tm_sQueueSample.m_fSpeedMultiplier = 4.0f;\n\t\t\tm_sQueueSample.m_nReleasingVolumeDivider = 3;\n\t\t\tm_sQueueSample.m_vecPos = CProjectileInfo::ms_apProjectile[i]->GetPosition();\n\t\t\tdistSquared = GetDistanceSquared(m_sQueueSample.m_vecPos);\n\t\t\tif (distSquared < SQR(m_sQueueSample.m_fSoundIntensity)) {\n\t\t\t\tm_sQueueSample.m_fDistance = Sqrt(distSquared);\n\t\t\t\tm_sQueueSample.m_nVolume = ComputeVolume(emittingVol, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance);\n\t\t\t\tif (m_sQueueSample.m_nVolume != 0) {\n\t\t\t\t\tm_sQueueSample.m_nCounter = i;\n\t\t\t\t\tm_sQueueSample.m_bIs2D = false;\n\t\t\t\t\tm_sQueueSample.m_nLoopCount = 0;\n\t\t\t\t\tm_sQueueSample.m_nEmittingVolume = emittingVol;\n\t\t\t\t\tm_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex);\n\t\t\t\t\tm_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex);\n\t\t\t\t\tm_sQueueSample.m_bReleasingSoundFlag = false;\n\t\t\t\t\tm_sQueueSample.m_bReverbFlag = true;\n\t\t\t\t\tm_sQueueSample.m_bRequireReflection = false;\n\t\t\t\t\tAddSampleToRequestedQueue();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\ncAudioManager::ProcessGarages()\n{\n\tconst float SOUND_INTENSITY = 80.0f;\n\n\tCEntity *entity;\n\tuint8 state;\n\tuint32 sampleIndex;\n\tuint8 j;\n\tfloat distSquared;\n\tbool distCalculated;\n\n\tstatic uint8 iSound = 32;\n\n\tfor (uint32 i = 0; i < CGarages::NumGarages; ++i) {\n\t\tif (CGarages::aGarages[i].m_eGarageType == GARAGE_NONE)\n\t\t\tcontinue;\n\t\tentity = CGarages::aGarages[i].m_pDoor1;\n\t\tif (entity == nil)\n\t\t\tcontinue;\n\t\tm_sQueueSample.m_vecPos = entity->GetPosition();\n\t\tdistCalculated = false;\n\t\tdistSquared = GetDistanceSquared(m_sQueueSample.m_vecPos);\n\t\tif (distSquared < SQR(SOUND_INTENSITY)) {\n\t\t\tstate = CGarages::aGarages[i].m_eGarageState;\n\t\t\t// while is here just to exit prematurely and avoid goto\n\t\t\twhile (state == GS_OPENING || state == GS_CLOSING || state == GS_AFTERDROPOFF) {\n\t\t\t\tCalculateDistance(distCalculated, distSquared);\n\t\t\t\tm_sQueueSample.m_nVolume = ComputeVolume(90, SOUND_INTENSITY, m_sQueueSample.m_fDistance);\n\t\t\t\tif (m_sQueueSample.m_nVolume != 0) {\n\t\t\t\t\tif (CGarages::aGarages[i].m_eGarageType == GARAGE_CRUSHER) {\n\t\t\t\t\t\tif (CGarages::aGarages[i].m_eGarageState == GS_AFTERDROPOFF) {\n\t\t\t\t\t\t\tif (m_FrameCounter & 1) {\n\t\t\t\t\t\t\t\tif (m_anRandomTable[1] & 1)\n\t\t\t\t\t\t\t\t\tsampleIndex = m_anRandomTable[2] % 5 + SFX_COL_CAR_1;\n\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\tsampleIndex = m_anRandomTable[2] % 6 + SFX_COL_CAR_PANEL_1;\n\t\t\t\t\t\t\t\tm_sQueueSample.m_nSampleIndex = sampleIndex;\n\t\t\t\t\t\t\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex) / 2;\n\t\t\t\t\t\t\t\tm_sQueueSample.m_nFrequency += RandomDisplacement(m_sQueueSample.m_nFrequency / 16);\n\t\t\t\t\t\t\t\tm_sQueueSample.m_nLoopCount = 1;\n\t\t\t\t\t\t\t\tm_sQueueSample.m_bReleasingSoundFlag = true;\n\t\t\t\t\t\t\t\tm_sQueueSample.m_nCounter = iSound++;\n\t\t\t\t\t\t\t\tif (iSound < 32)\n\t\t\t\t\t\t\t\t\tiSound = 32;\n\t\t\t\t\t\t\t} else break; // premature exit to go straight to the for loop\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_FISHING_BOAT_IDLE;\n\t\t\t\t\t\t\tm_sQueueSample.m_nFrequency = 6543;\n\n\t\t\t\t\t\t\tm_sQueueSample.m_nCounter = i;\n\t\t\t\t\t\t\tm_sQueueSample.m_nLoopCount = 0;\n\t\t\t\t\t\t\tm_sQueueSample.m_nReleasingVolumeDivider = 3;\n\t\t\t\t\t\t\tm_sQueueSample.m_bReleasingSoundFlag = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_GARAGE_DOOR_LOOP;\n\t\t\t\t\t\tm_sQueueSample.m_nFrequency = 13961;\n\n\t\t\t\t\t\tm_sQueueSample.m_nCounter = i;\n\t\t\t\t\t\tm_sQueueSample.m_nLoopCount = 0;\n\t\t\t\t\t\tm_sQueueSample.m_nReleasingVolumeDivider = 3;\n\t\t\t\t\t\tm_sQueueSample.m_bReleasingSoundFlag = false;\n\t\t\t\t\t}\n\n\t\t\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\t\t\tm_sQueueSample.m_bIs2D = false;\n\t\t\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 3;\n\t\t\t\t\tm_sQueueSample.m_nEmittingVolume = 90;\n\t\t\t\t\tm_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex);\n\t\t\t\t\tm_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex);\n\t\t\t\t\tm_sQueueSample.m_fSpeedMultiplier = 2.0f;\n\t\t\t\t\tm_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY;\n\t\t\t\t\tm_sQueueSample.m_bReverbFlag = true;\n\t\t\t\t\tm_sQueueSample.m_bRequireReflection = false;\n\t\t\t\t\tAddSampleToRequestedQueue();\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tfor (j = 0; j < m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_AudioEvents; ++j) {\n\t\t\tswitch (m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_awAudioEvent[j]) {\n\t\t\tcase SOUND_GARAGE_DOOR_CLOSED:\n\t\t\tcase SOUND_GARAGE_DOOR_OPENED:\n\t\t\t\tif (distSquared < SQR(SOUND_INTENSITY)) {\n\t\t\t\t\tCalculateDistance(distCalculated, distSquared);\n\t\t\t\t\tm_sQueueSample.m_nVolume = ComputeVolume(60, SOUND_INTENSITY, m_sQueueSample.m_fDistance);\n\t\t\t\t\tif (m_sQueueSample.m_nVolume != 0) {\n\t\t\t\t\t\tif (CGarages::aGarages[i].m_eGarageType == GARAGE_CRUSHER) {\n\t\t\t\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_COL_CAR_PANEL_2;\n\t\t\t\t\t\t\tm_sQueueSample.m_nFrequency = 6735;\n\t\t\t\t\t\t} else if (m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_awAudioEvent[j] == SOUND_GARAGE_DOOR_OPENED) {\n\t\t\t\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_COL_CAR_PANEL_2;\n\t\t\t\t\t\t\tm_sQueueSample.m_nFrequency = 22000;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tm_sQueueSample.m_nSampleIndex = SFX_COL_GARAGE_DOOR_1;\n\t\t\t\t\t\t\tm_sQueueSample.m_nFrequency = 18000;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\t\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 4;\n\t\t\t\t\t\tm_sQueueSample.m_nEmittingVolume = 60;\n\t\t\t\t\t\tm_sQueueSample.m_fSpeedMultiplier = 0.0f;\n\t\t\t\t\t\tm_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY;\n\t\t\t\t\t\tm_sQueueSample.m_bReverbFlag = true; \n\t\t\t\t\t\tm_sQueueSample.m_bIs2D = false;\n\t\t\t\t\t\tm_sQueueSample.m_bReleasingSoundFlag = true;\n\t\t\t\t\t\tm_sQueueSample.m_nLoopCount = 1;\n\t\t\t\t\t\tm_sQueueSample.m_nLoopStart = 0;\n\t\t\t\t\t\tm_sQueueSample.m_nLoopEnd = -1;\n\t\t\t\t\t\tm_sQueueSample.m_nCounter = iSound++;\n\t\t\t\t\t\tif (iSound < 32)\n\t\t\t\t\t\t\tiSound = 32;\n\t\t\t\t\t\tm_sQueueSample.m_bRequireReflection = true;\n\t\t\t\t\t\tAddSampleToRequestedQueue();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\ncAudioManager::ProcessFireHydrant()\n{\n\tconst float SOUND_INTENSITY = 35;\n\n\tfloat distSquared;\n\tbool distCalculated = false;\n\n\tm_sQueueSample.m_vecPos = ((CEntity *)m_asAudioEntities[m_sQueueSample.m_nEntityIndex].m_pEntity)->GetPosition();\n\tdistSquared = GetDistanceSquared(m_sQueueSample.m_vecPos);\n\tif (distSquared < SQR(SOUND_INTENSITY)) {\n\t\tCalculateDistance(distCalculated, distSquared);\n\t\tm_sQueueSample.m_nVolume = ComputeVolume(40, 35.0f, m_sQueueSample.m_fDistance);\n\t\tif (m_sQueueSample.m_nVolume != 0) {\n\t\t\tm_sQueueSample.m_nSampleIndex = SFX_JUMBO_TAXI;\n\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 4;\n\t\t\tm_sQueueSample.m_nFrequency = 15591;\n\t\t\tm_sQueueSample.m_nCounter = 0;\n\t\t\tm_sQueueSample.m_nEmittingVolume = 40;\n\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\tm_sQueueSample.m_bIs2D = false;\n\t\t\tm_sQueueSample.m_nLoopCount = 0;\n\t\t\tm_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex);\n\t\t\tm_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex);\n\t\t\tm_sQueueSample.m_fSoundIntensity = SOUND_INTENSITY;\n\t\t\tm_sQueueSample.m_bReleasingSoundFlag = false;\n\t\t\tm_sQueueSample.m_bRequireReflection = false;\n\t\t\tm_sQueueSample.m_nReleasingVolumeDivider = 3;\n\t\t\tm_sQueueSample.m_fSpeedMultiplier = 2.0f;\n\t\t\tAddSampleToRequestedQueue();\n\t\t}\n\t}\n}\n#ifdef GTA_BRIDGE\n#pragma region BRIDGE\nconst int bridgeIntensity = 400;\n\nvoid\ncAudioManager::ProcessBridge()\n{\n\tfloat dist;\n\tbool distCalculated = false;\n\n\tif (CBridge::pLiftRoad) {\n\t\tm_sQueueSample.m_vecPos = CBridge::pLiftRoad->GetPosition();\n\t\tdist = GetDistanceSquared(m_sQueueSample.m_vecPos);\n\t\tif (dist < SQR(450.0f)) {\n\t\t\tCalculateDistance(distCalculated, dist);\n\t\t\tswitch (CBridge::State) {\n\t\t\tcase STATE_BRIDGE_LOCKED:\n\t\t\tcase STATE_LIFT_PART_IS_UP:\n\t\t\tcase STATE_LIFT_PART_ABOUT_TO_MOVE_UP:\n\t\t\t\tProcessBridgeWarning();\n\t\t\t\tbreak;\n\t\t\tcase STATE_LIFT_PART_MOVING_DOWN:\n\t\t\tcase STATE_LIFT_PART_MOVING_UP:\n\t\t\t\tProcessBridgeWarning();\n\t\t\t\tProcessBridgeMotor();\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tProcessBridgeOneShots();\n\t\t}\n\t}\n}\n\nvoid\ncAudioManager::ProcessBridgeWarning()\n{\n\tif (CStats::CommercialPassed && m_sQueueSample.m_fDistance < 450.f) {\n\t\tm_sQueueSample.m_nVolume = ComputeVolume(100, 450.f, m_sQueueSample.m_fDistance);\n\t\tif (m_sQueueSample.m_nVolume != 0) {\n\t\t\tm_sQueueSample.m_nCounter = 0;\n\t\t\tm_sQueueSample.m_nSampleIndex = SFX_BRIDGE_OPEN_WARNING;\n\t\t\tm_sQueueSample.m_nBankIndex = SAMPLEBANK_EXTRAS;\n\t\t\tm_sQueueSample.m_bIs2D = false;\n\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 1;\n\t\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_BRIDGE_OPEN_WARNING);\n\t\t\tm_sQueueSample.m_nLoopCount = 0;\n\t\t\tm_sQueueSample.m_nEmittingVolume = 100;\n\t\t\tm_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex);\n\t\t\tm_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex);\n\t\t\tm_sQueueSample.m_fSpeedMultiplier = 2.0f;\n\t\t\tm_sQueueSample.m_fSoundIntensity = 450.0f;\n\t\t\tm_sQueueSample.m_bReleasingSoundFlag = false;\n\t\t\tm_sQueueSample.m_nReleasingVolumeDivider = 8;\n\t\t\tm_sQueueSample.m_bReverbFlag = false;\n\t\t\tm_sQueueSample.m_bRequireReflection = false;\n\t\t\tAddSampleToRequestedQueue();\n\t\t}\n\t}\n}\n\nvoid\ncAudioManager::ProcessBridgeMotor()\n{\n\tif (m_sQueueSample.m_fDistance < bridgeIntensity) {\n\t\tm_sQueueSample.m_nVolume = ComputeVolume(MAX_VOLUME, bridgeIntensity, m_sQueueSample.m_fDistance);\n\t\tif (m_sQueueSample.m_nVolume != 0) {\n\t\t\tm_sQueueSample.m_nCounter = 1;\n\t\t\tm_sQueueSample.m_nSampleIndex = SFX_FISHING_BOAT_IDLE; // todo check sfx name\n\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\tm_sQueueSample.m_bIs2D = false;\n\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 1;\n\t\t\tm_sQueueSample.m_nFrequency = 5500;\n\t\t\tm_sQueueSample.m_nLoopCount = 0;\n\t\t\tm_sQueueSample.m_nEmittingVolume = MAX_VOLUME;\n\t\t\tm_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex);\n\t\t\tm_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex);\n\t\t\tm_sQueueSample.m_fSpeedMultiplier = 2.0f;\n\t\t\tm_sQueueSample.m_fSoundIntensity = bridgeIntensity;\n\t\t\tm_sQueueSample.m_bReleasingSoundFlag = false;\n\t\t\tm_sQueueSample.m_nReleasingVolumeDivider = 3;\n\t\t\tm_sQueueSample.m_bReverbFlag = false;\n\t\t\tAddSampleToRequestedQueue();\n\t\t}\n\t}\n}\n\nvoid\ncAudioManager::ProcessBridgeOneShots()\n{\n\tif (CBridge::State == STATE_LIFT_PART_IS_UP && CBridge::OldState == STATE_LIFT_PART_MOVING_UP)\n\t\tm_sQueueSample.m_nSampleIndex = SFX_COL_CONTAINER_1;\n\telse if (CBridge::State == STATE_LIFT_PART_IS_DOWN && CBridge::OldState == STATE_LIFT_PART_MOVING_DOWN)\n\t\tm_sQueueSample.m_nSampleIndex = SFX_COL_CONTAINER_1;\n\telse if (CBridge::State == STATE_LIFT_PART_MOVING_UP && CBridge::OldState == STATE_LIFT_PART_ABOUT_TO_MOVE_UP)\n\t\tm_sQueueSample.m_nSampleIndex = SFX_COL_CONTAINER_1;\n\telse if (CBridge::State == STATE_LIFT_PART_MOVING_DOWN && CBridge::OldState == STATE_LIFT_PART_IS_UP)\n\t\tm_sQueueSample.m_nSampleIndex = SFX_COL_CONTAINER_1;\n\telse return;\n\n\tif (m_sQueueSample.m_fDistance < bridgeIntensity) {\n\t\tm_sQueueSample.m_nVolume = ComputeVolume(MAX_VOLUME, bridgeIntensity, m_sQueueSample.m_fDistance);\n\t\tif (m_sQueueSample.m_nVolume != 0) {\n\t\t\tm_sQueueSample.m_nCounter = 2;\n\t\t\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\t\t\tm_sQueueSample.m_bIs2D = false;\n\t\t\tm_sQueueSample.m_nReleasingVolumeModificator = 1;\n\t\t\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(m_sQueueSample.m_nSampleIndex);\n\t\t\tm_sQueueSample.m_nLoopCount = 1;\n\t\t\tm_sQueueSample.m_nEmittingVolume = MAX_VOLUME;\n\t\t\tm_sQueueSample.m_nLoopStart = 0;\n\t\t\tm_sQueueSample.m_nLoopEnd = -1;\n\t\t\tm_sQueueSample.m_fSpeedMultiplier = 2.0f;\n\t\t\tm_sQueueSample.m_fSoundIntensity = bridgeIntensity;\n\t\t\tm_sQueueSample.m_bReleasingSoundFlag = true;\n\t\t\tm_sQueueSample.m_bReverbFlag = false;\n\t\t\tm_sQueueSample.m_bRequireReflection = false;\n\t\t\tAddSampleToRequestedQueue();\n\t\t}\n\t}\n}\n#pragma endregion\n#endif\n\n#pragma region MISSION_AUDIO\nbool g_bMissionAudioLoadFailed[MISSION_AUDIO_SLOTS];\n\nstruct MissionAudioData {\n\tconst char *m_pName;\n\tint32 m_nId;\n};\n\n\nconst MissionAudioData MissionAudioNameSfxAssoc[] = {\n\t{\"mobring\", STREAMED_SOUND_MISSION_MOBR1},    {\"pagring\", STREAMED_SOUND_MISSION_PAGER},    {\"carrev\", STREAMED_SOUND_MISSION_CARREV},\n\t{\"bikerev\", STREAMED_SOUND_MISSION_BIKEREV},  {\"liftop\", STREAMED_SOUND_MISSION_LIFTOP},    {\"liftcl\", STREAMED_SOUND_MISSION_LIFTCL},\n\t{\"liftrun\", STREAMED_SOUND_MISSION_LIFTRUN},  {\"liftbel\", STREAMED_SOUND_MISSION_LIFTBEL},  {\"inlift\", STREAMED_SOUND_MISSION_INLIFT},\n\t{\"caml\", STREAMED_SOUND_MISSION_CAMERAL},     {\"camr\", STREAMED_SOUND_MISSION_CAMERAR},     {\"cheer1\", STREAMED_SOUND_MISSION_CHEER1},\n\t{\"cheer2\", STREAMED_SOUND_MISSION_CHEER2},    {\"cheer3\", STREAMED_SOUND_MISSION_CHEER3},    {\"cheer4\", STREAMED_SOUND_MISSION_CHEER4},\n\t{\"ooh1\", STREAMED_SOUND_MISSION_OOH1},        {\"ooh2\", STREAMED_SOUND_MISSION_OOH2},        {\"race1\", STREAMED_SOUND_MISSION_RACE1},\n\t{\"race2\", STREAMED_SOUND_MISSION_RACE2},      {\"race3\", STREAMED_SOUND_MISSION_RACE3},      {\"race4\", STREAMED_SOUND_MISSION_RACE4},\n\t{\"race5\", STREAMED_SOUND_MISSION_RACE5},      {\"race6\", STREAMED_SOUND_MISSION_RACE6},      {\"race7\", STREAMED_SOUND_MISSION_RACE7},\n\t{\"race8\", STREAMED_SOUND_MISSION_RACE8},      {\"race9\", STREAMED_SOUND_MISSION_RACE9},      {\"race10\", STREAMED_SOUND_MISSION_RACE10},\n\t{\"race11\", STREAMED_SOUND_MISSION_RACE11},    {\"race12\", STREAMED_SOUND_MISSION_RACE12},    {\"race13\", STREAMED_SOUND_MISSION_RACE13},\n\t{\"race14\", STREAMED_SOUND_MISSION_RACE14},    {\"race15\", STREAMED_SOUND_MISSION_RACE15},    {\"hot1\", STREAMED_SOUND_MISSION_HOT1},\n\t{\"hot2\", STREAMED_SOUND_MISSION_HOT2},        {\"hot3\", STREAMED_SOUND_MISSION_HOT3},        {\"hot4\", STREAMED_SOUND_MISSION_HOT4},\n\t{\"hot5\", STREAMED_SOUND_MISSION_HOT5},        {\"hot6\", STREAMED_SOUND_MISSION_HOT6},        {\"hot7\", STREAMED_SOUND_MISSION_HOT7},\n\t{\"hot8\", STREAMED_SOUND_MISSION_HOT8},        {\"hot9\", STREAMED_SOUND_MISSION_HOT9},        {\"hot10\", STREAMED_SOUND_MISSION_HOT10},\n\t{\"hot11\", STREAMED_SOUND_MISSION_HOT11},      {\"hot12\", STREAMED_SOUND_MISSION_HOT12},      {\"hot13\", STREAMED_SOUND_MISSION_HOT13},\n\t{\"hot14\", STREAMED_SOUND_MISSION_HOT14},      {\"hot15\", STREAMED_SOUND_MISSION_HOT15},      {\"lanstp1\", STREAMED_SOUND_MISSION_LANSTP1},\n\t{\"lanstp2\", STREAMED_SOUND_MISSION_LANSTP2},  {\"lanamu1\", STREAMED_SOUND_MISSION_LANAMU1},  {\"lanamu2\", STREAMED_SOUND_MISSION_LANAMU2},\n\t{\"airhrnl\", STREAMED_SOUND_MISSION_AIRHORNL}, {\"airhrnr\", STREAMED_SOUND_MISSION_AIRHORNR}, {\"sniper\", STREAMED_SOUND_MISSION_SNIPSCRL},\n\t{\"snipsh\", STREAMED_SOUND_MISSION_SNIPSHORT}, {\"bloroof\", STREAMED_SOUND_MISSION_BLOWROOF}, {\"sfx_01\", STREAMED_SOUND_MISSION_SFX_01},\n\t{\"sfx_02\", STREAMED_SOUND_MISSION_SFX_02},    {\"LAW1_1\", STREAMED_SOUND_MISSION_LAW1_1},    {\"LAW1_2\", STREAMED_SOUND_MISSION_LAW1_2},\n\t{\"LAW1_3\", STREAMED_SOUND_MISSION_LAW1_3},    {\"LAW1_4\", STREAMED_SOUND_MISSION_LAW1_4},    {\"LAW1_5\", STREAMED_SOUND_MISSION_LAW1_5},\n\t{\"LAW1_6\", STREAMED_SOUND_MISSION_LAW1_6},    {\"LAW1_7\", STREAMED_SOUND_MISSION_LAW1_7},    {\"LAW1_8\", STREAMED_SOUND_MISSION_LAW1_8},\n\t{\"LAW1_9\", STREAMED_SOUND_MISSION_LAW1_9},    {\"LAW1_10\", STREAMED_SOUND_MISSION_LAW1_10},  {\"LAW2_1\", STREAMED_SOUND_MISSION_LAW2_1},\n\t{\"LAW2_2\", STREAMED_SOUND_MISSION_LAW2_2},    {\"LAW2_3\", STREAMED_SOUND_MISSION_LAW2_3},    {\"LAW2_4\", STREAMED_SOUND_MISSION_LAW2_4},\n\t{\"LAW2_5\", STREAMED_SOUND_MISSION_LAW2_5},    {\"LAW2_6\", STREAMED_SOUND_MISSION_LAW2_6},    {\"LAW2_7\", STREAMED_SOUND_MISSION_LAW2_7},\n\t{\"LAW2_8\", STREAMED_SOUND_MISSION_LAW2_8},    {\"LAW2_9\", STREAMED_SOUND_MISSION_LAW2_9},    {\"LAW2_10\", STREAMED_SOUND_MISSION_LAW2_10},\n\t{\"LAW3_1\", STREAMED_SOUND_MISSION_LAW3_1},    {\"LAW3_2\", STREAMED_SOUND_MISSION_LAW3_2},    {\"LAW3_3\", STREAMED_SOUND_MISSION_LAW3_3},\n\t{\"LAW3_4\", STREAMED_SOUND_MISSION_LAW3_4},    {\"LAW3_5\", STREAMED_SOUND_MISSION_LAW3_5},    {\"LAW3_6\", STREAMED_SOUND_MISSION_LAW3_6},\n\t{\"LAW3_10\", STREAMED_SOUND_MISSION_LAW3_10},  {\"LAW3_11\", STREAMED_SOUND_MISSION_LAW3_11},  {\"LAW3_12\", STREAMED_SOUND_MISSION_LAW3_12},\n\t{\"LAW3_13\", STREAMED_SOUND_MISSION_LAW3_13},  {\"LAW3_14\", STREAMED_SOUND_MISSION_LAW3_14},  {\"LAW3_16\", STREAMED_SOUND_MISSION_LAW3_16},\n\t{\"LAW3_17\", STREAMED_SOUND_MISSION_LAW3_17},  {\"LAW3_18\", STREAMED_SOUND_MISSION_LAW3_18},  {\"LAW3_19\", STREAMED_SOUND_MISSION_LAW3_19},\n\t{\"LAW3_20\", STREAMED_SOUND_MISSION_LAW3_20},  {\"LAW3_21\", STREAMED_SOUND_MISSION_LAW3_21},  {\"LAW3_22\", STREAMED_SOUND_MISSION_LAW3_22},\n\t{\"LAW3_23\", STREAMED_SOUND_MISSION_LAW3_23},  {\"LAW3_24\", STREAMED_SOUND_MISSION_LAW3_24},  {\"LAW3_25\", STREAMED_SOUND_MISSION_LAW3_25},\n\t{\"LAW4_1a\", STREAMED_SOUND_MISSION_LAW4_1A},  {\"LAW4_1b\", STREAMED_SOUND_MISSION_LAW4_1B},  {\"LAW4_1c\", STREAMED_SOUND_MISSION_LAW4_1C},\n\t{\"LAW4_1d\", STREAMED_SOUND_MISSION_LAW4_1D},  {\"LAW4_10\", STREAMED_SOUND_MISSION_LAW4_10},  {\"LAW4_3\", STREAMED_SOUND_MISSION_LAW4_3},\n\t{\"LAW4_4\", STREAMED_SOUND_MISSION_LAW4_4},    {\"LAW4_5\", STREAMED_SOUND_MISSION_LAW4_5},    {\"LAW4_6\", STREAMED_SOUND_MISSION_LAW4_6},\n\t{\"LAW4_7\", STREAMED_SOUND_MISSION_LAW4_7},    {\"LAW4_8\", STREAMED_SOUND_MISSION_LAW4_8},    {\"LAW4_9\", STREAMED_SOUND_MISSION_LAW4_9},\n\t{\"COL1_1\", STREAMED_SOUND_MISSION_COL1_1},    {\"COL1_2\", STREAMED_SOUND_MISSION_COL1_2},    {\"COL1_3\", STREAMED_SOUND_MISSION_COL1_3},\n\t{\"COL1_4\", STREAMED_SOUND_MISSION_COL1_4},    {\"COL1_5\", STREAMED_SOUND_MISSION_COL1_5},    {\"COL1_6\", STREAMED_SOUND_MISSION_COL1_6},\n\t{\"COL1_7\", STREAMED_SOUND_MISSION_COL1_7},    {\"COL1_8\", STREAMED_SOUND_MISSION_COL1_8},    {\"COL2_1\", STREAMED_SOUND_MISSION_COL2_1},\n\t{\"COL2_2\", STREAMED_SOUND_MISSION_COL2_2},    {\"COL2_3\", STREAMED_SOUND_MISSION_COL2_3},    {\"COL2_4\", STREAMED_SOUND_MISSION_COL2_4},\n\t{\"COL2_5\", STREAMED_SOUND_MISSION_COL2_5},    {\"COL2_6a\", STREAMED_SOUND_MISSION_COL2_6A},  {\"COL2_7\", STREAMED_SOUND_MISSION_COL2_7},\n\t{\"COL2_8\", STREAMED_SOUND_MISSION_COL2_8},    {\"COL2_9\", STREAMED_SOUND_MISSION_COL2_9},    {\"COL2_10\", STREAMED_SOUND_MISSION_COL2_10},\n\t{\"COL2_11\", STREAMED_SOUND_MISSION_COL2_11},  {\"COL2_12\", STREAMED_SOUND_MISSION_COL2_12},  {\"COL2_13\", STREAMED_SOUND_MISSION_COL2_13},\n\t{\"COL2_14\", STREAMED_SOUND_MISSION_COL2_14},  {\"COL2_15\", STREAMED_SOUND_MISSION_COL2_15},  {\"COL2_16\", STREAMED_SOUND_MISSION_COL2_16},\n\t{\"COL3_1\", STREAMED_SOUND_MISSION_COL3_1},    {\"COL3_2\", STREAMED_SOUND_MISSION_COL3_2},    {\"COL3_2a\", STREAMED_SOUND_MISSION_COL3_2A},\n\t{\"COL3_2b\", STREAMED_SOUND_MISSION_COL3_2B},  {\"COL3_3\", STREAMED_SOUND_MISSION_COL3_3},    {\"COL3_4\", STREAMED_SOUND_MISSION_COL3_4},\n\t{\"COL3_5\", STREAMED_SOUND_MISSION_COL3_5},    {\"COL3_6\", STREAMED_SOUND_MISSION_COL3_6},    {\"COL3_7\", STREAMED_SOUND_MISSION_COL3_7},\n\t{\"COL3_8\", STREAMED_SOUND_MISSION_COL3_8},    {\"COL3_9\", STREAMED_SOUND_MISSION_COL3_9},    {\"COL3_10\", STREAMED_SOUND_MISSION_COL3_10},\n\t{\"COL3_11\", STREAMED_SOUND_MISSION_COL3_11},  {\"COL3_12\", STREAMED_SOUND_MISSION_COL3_12},  {\"COL3_13\", STREAMED_SOUND_MISSION_COL3_13},\n\t{\"COL3_14\", STREAMED_SOUND_MISSION_COL3_14},  {\"COL3_15\", STREAMED_SOUND_MISSION_COL3_15},  {\"COL3_16\", STREAMED_SOUND_MISSION_COL3_16},\n\t{\"COL3_17\", STREAMED_SOUND_MISSION_COL3_17},  {\"COL3_18\", STREAMED_SOUND_MISSION_COL3_18},  {\"COL3_19\", STREAMED_SOUND_MISSION_COL3_19},\n\t{\"COL3_20\", STREAMED_SOUND_MISSION_COL3_20},  {\"COL3_21\", STREAMED_SOUND_MISSION_COL3_21},  {\"COL3_23\", STREAMED_SOUND_MISSION_COL3_23},\n\t{\"COL3_24\", STREAMED_SOUND_MISSION_COL3_24},  {\"COL3_25\", STREAMED_SOUND_MISSION_COL3_25},  {\"COL4_1\", STREAMED_SOUND_MISSION_COL4_1},\n\t{\"COL4_2\", STREAMED_SOUND_MISSION_COL4_2},    {\"COL4_3\", STREAMED_SOUND_MISSION_COL4_3},    {\"COL4_4\", STREAMED_SOUND_MISSION_COL4_4},\n\t{\"COL4_5\", STREAMED_SOUND_MISSION_COL4_5},    {\"COL4_6\", STREAMED_SOUND_MISSION_COL4_6},    {\"COL4_7\", STREAMED_SOUND_MISSION_COL4_7},\n\t{\"COL4_8\", STREAMED_SOUND_MISSION_COL4_8},    {\"COL4_9\", STREAMED_SOUND_MISSION_COL4_9},    {\"COL4_10\", STREAMED_SOUND_MISSION_COL4_10},\n\t{\"COL4_11\", STREAMED_SOUND_MISSION_COL4_11},  {\"COL4_12\", STREAMED_SOUND_MISSION_COL4_12},  {\"COL4_13\", STREAMED_SOUND_MISSION_COL4_13},\n\t{\"COL4_14\", STREAMED_SOUND_MISSION_COL4_14},  {\"COL4_15\", STREAMED_SOUND_MISSION_COL4_15},  {\"COL4_16\", STREAMED_SOUND_MISSION_COL4_16},\n\t{\"COL4_17\", STREAMED_SOUND_MISSION_COL4_17},  {\"COL4_18\", STREAMED_SOUND_MISSION_COL4_18},  {\"COL4_19\", STREAMED_SOUND_MISSION_COL4_19},\n\t{\"COL4_20\", STREAMED_SOUND_MISSION_COL4_20},  {\"COL4_21\", STREAMED_SOUND_MISSION_COL4_21},  {\"COL4_22\", STREAMED_SOUND_MISSION_COL4_22},\n\t{\"COL4_23\", STREAMED_SOUND_MISSION_COL4_23},  {\"COL4_24\", STREAMED_SOUND_MISSION_COL4_24},  {\"COL4_25\", STREAMED_SOUND_MISSION_COL4_25},\n\t{\"COL4_26\", STREAMED_SOUND_MISSION_COL4_26},  {\"COL5_1\", STREAMED_SOUND_MISSION_COL5_1},    {\"COL5_2\", STREAMED_SOUND_MISSION_COL5_2},\n\t{\"COL5_3\", STREAMED_SOUND_MISSION_COL5_3},    {\"COL5_4\", STREAMED_SOUND_MISSION_COL5_4},    {\"COL5_5\", STREAMED_SOUND_MISSION_COL5_5},\n\t{\"COL5_6\", STREAMED_SOUND_MISSION_COL5_6},    {\"COL5_7\", STREAMED_SOUND_MISSION_COL5_7},    {\"COL5_8\", STREAMED_SOUND_MISSION_COL5_8},\n\t{\"COL5_9\", STREAMED_SOUND_MISSION_COL5_9},    {\"COL5_10\", STREAMED_SOUND_MISSION_COL5_10},  {\"COL5_11\", STREAMED_SOUND_MISSION_COL5_11},\n\t{\"COL5_12\", STREAMED_SOUND_MISSION_COL5_12},  {\"COL5_13\", STREAMED_SOUND_MISSION_COL5_13},  {\"COL5_14\", STREAMED_SOUND_MISSION_COL5_14},\n\t{\"COL5_15\", STREAMED_SOUND_MISSION_COL5_15},  {\"COL5_16\", STREAMED_SOUND_MISSION_COL5_16},  {\"COL5_17\", STREAMED_SOUND_MISSION_COL5_17},\n\t{\"COL5_18\", STREAMED_SOUND_MISSION_COL5_18},  {\"COL5_19\", STREAMED_SOUND_MISSION_COL5_19},  {\"COL5_20\", STREAMED_SOUND_MISSION_COL5_20},\n\t{\"COL5_21\", STREAMED_SOUND_MISSION_COL5_21},  {\"COL5_22\", STREAMED_SOUND_MISSION_COL5_22},  {\"COK1_1\", STREAMED_SOUND_MISSION_COK1_1},\n\t{\"COK1_2\", STREAMED_SOUND_MISSION_COK1_2},    {\"COK1_3\", STREAMED_SOUND_MISSION_COK1_3},    {\"COK1_4\", STREAMED_SOUND_MISSION_COK1_4},\n\t{\"COK1_5\", STREAMED_SOUND_MISSION_COK1_5},    {\"COK1_6\", STREAMED_SOUND_MISSION_COK1_6},    {\"COK2_1\", STREAMED_SOUND_MISSION_COK2_1},\n\t{\"COK2_2\", STREAMED_SOUND_MISSION_COK2_2},    {\"COK2_3\", STREAMED_SOUND_MISSION_COK2_3},    {\"COK2_4\", STREAMED_SOUND_MISSION_COK2_4},\n\t{\"COK2_5\", STREAMED_SOUND_MISSION_COK2_5},    {\"COK2_6\", STREAMED_SOUND_MISSION_COK2_6},    {\"COK2_7a\", STREAMED_SOUND_MISSION_COK2_7A},\n\t{\"COK2_7b\", STREAMED_SOUND_MISSION_COK2_7B},  {\"COK2_7c\", STREAMED_SOUND_MISSION_COK2_7C},  {\"COK2_8a\", STREAMED_SOUND_MISSION_COK2_8A},\n\t{\"COK2_8b\", STREAMED_SOUND_MISSION_COK2_8B},  {\"COK2_8c\", STREAMED_SOUND_MISSION_COK2_8C},  {\"COK2_8d\", STREAMED_SOUND_MISSION_COK2_8D},\n\t{\"COK2_9\", STREAMED_SOUND_MISSION_COK2_9},    {\"COK210a\", STREAMED_SOUND_MISSION_COK210A},  {\"COK210b\", STREAMED_SOUND_MISSION_COK210B},\n\t{\"COK210c\", STREAMED_SOUND_MISSION_COK210C},  {\"COK212a\", STREAMED_SOUND_MISSION_COK212A},  {\"COK212b\", STREAMED_SOUND_MISSION_COK212B},\n\t{\"COK2_13\", STREAMED_SOUND_MISSION_COK2_13},  {\"COK2_14\", STREAMED_SOUND_MISSION_COK2_14},  {\"COK2_15\", STREAMED_SOUND_MISSION_COK2_15},\n\t{\"COK2_16\", STREAMED_SOUND_MISSION_COK2_16},  {\"COK2_20\", STREAMED_SOUND_MISSION_COK2_20},  {\"COK2_21\", STREAMED_SOUND_MISSION_COK2_21},\n\t{\"COK2_22\", STREAMED_SOUND_MISSION_COK2_22},  {\"COK3_1\", STREAMED_SOUND_MISSION_COK3_1},    {\"COK3_2\", STREAMED_SOUND_MISSION_COK3_2},\n\t{\"COK3_3\", STREAMED_SOUND_MISSION_COK3_3},    {\"COK3_4\", STREAMED_SOUND_MISSION_COK3_4},    {\"COK4_1\", STREAMED_SOUND_MISSION_COK4_1},\n\t{\"COK4_2\", STREAMED_SOUND_MISSION_COK4_2},    {\"COK4_3\", STREAMED_SOUND_MISSION_COK4_3},    {\"COK4_4\", STREAMED_SOUND_MISSION_COK4_4},\n\t{\"COK4_5\", STREAMED_SOUND_MISSION_COK4_5},    {\"COK4_6\", STREAMED_SOUND_MISSION_COK4_6},    {\"COK4_7\", STREAMED_SOUND_MISSION_COK4_7},\n\t{\"COK4_8\", STREAMED_SOUND_MISSION_COK4_8},    {\"COK4_9\", STREAMED_SOUND_MISSION_COK4_9},    {\"COK4_9A\", STREAMED_SOUND_MISSION_COK4_9A},\n\t{\"COK4_10\", STREAMED_SOUND_MISSION_COK4_10},  {\"COK4_11\", STREAMED_SOUND_MISSION_COK4_11},  {\"COK4_12\", STREAMED_SOUND_MISSION_COK4_12},\n\t{\"COK4_13\", STREAMED_SOUND_MISSION_COK4_13},  {\"COK4_14\", STREAMED_SOUND_MISSION_COK4_14},  {\"COK4_15\", STREAMED_SOUND_MISSION_COK4_15},\n\t{\"COK4_16\", STREAMED_SOUND_MISSION_COK4_16},  {\"COK4_17\", STREAMED_SOUND_MISSION_COK4_17},  {\"COK4_18\", STREAMED_SOUND_MISSION_COK4_18},\n\t{\"COK4_19\", STREAMED_SOUND_MISSION_COK4_19},  {\"COK4_20\", STREAMED_SOUND_MISSION_COK4_20},  {\"COK4_21\", STREAMED_SOUND_MISSION_COK4_21},\n\t{\"COK4_22\", STREAMED_SOUND_MISSION_COK4_22},  {\"COK4_23\", STREAMED_SOUND_MISSION_COK4_23},  {\"COK4_24\", STREAMED_SOUND_MISSION_COK4_24},\n\t{\"COK4_25\", STREAMED_SOUND_MISSION_COK4_25},  {\"COK4_26\", STREAMED_SOUND_MISSION_COK4_26},  {\"COK4_27\", STREAMED_SOUND_MISSION_COK4_27},\n\t{\"RESC_1\", STREAMED_SOUND_MISSION_RESC_1},    {\"RESC_2\", STREAMED_SOUND_MISSION_RESC_2},    {\"RESC_3\", STREAMED_SOUND_MISSION_RESC_3},\n\t{\"RESC_4\", STREAMED_SOUND_MISSION_RESC_4},    {\"RESC_5\", STREAMED_SOUND_MISSION_RESC_5},    {\"RESC_6\", STREAMED_SOUND_MISSION_RESC_6},\n\t{\"RESC_7\", STREAMED_SOUND_MISSION_RESC_7},    {\"RESC_8\", STREAMED_SOUND_MISSION_RESC_8},    {\"RESC_9\", STREAMED_SOUND_MISSION_RESC_9},\n\t{\"RESC_10\", STREAMED_SOUND_MISSION_RESC_10},  {\"ASS_1\", STREAMED_SOUND_MISSION_ASS_1},      {\"ASS_2\", STREAMED_SOUND_MISSION_ASS_2},\n\t{\"ASS_3\", STREAMED_SOUND_MISSION_ASS_3},      {\"ASS_4\", STREAMED_SOUND_MISSION_ASS_4},      {\"ASS_5\", STREAMED_SOUND_MISSION_ASS_5},\n\t{\"ASS_6\", STREAMED_SOUND_MISSION_ASS_6},      {\"ASS_7\", STREAMED_SOUND_MISSION_ASS_7},      {\"ASS_8\", STREAMED_SOUND_MISSION_ASS_8},\n\t{\"ASS_9\", STREAMED_SOUND_MISSION_ASS_9},      {\"ASS_10\", STREAMED_SOUND_MISSION_ASS_10},    {\"ASS_11\", STREAMED_SOUND_MISSION_ASS_11},\n\t{\"ASS_12\", STREAMED_SOUND_MISSION_ASS_12},    {\"ASS_13\", STREAMED_SOUND_MISSION_ASS_13},    {\"ASS_14\", STREAMED_SOUND_MISSION_ASS_14},\n\t{\"BUD1_1\", STREAMED_SOUND_MISSION_BUD1_1},    {\"BUD1_2\", STREAMED_SOUND_MISSION_BUD1_2},    {\"BUD1_3\", STREAMED_SOUND_MISSION_BUD1_3},\n\t{\"BUD1_4\", STREAMED_SOUND_MISSION_BUD1_4},    {\"BUD1_5\", STREAMED_SOUND_MISSION_BUD1_5},    {\"BUD1_9\", STREAMED_SOUND_MISSION_BUD1_9},\n\t{\"BUD1_10\", STREAMED_SOUND_MISSION_BUD1_10},  {\"BUD2_1\", STREAMED_SOUND_MISSION_BUD2_1},    {\"BUD2_2\", STREAMED_SOUND_MISSION_BUD2_2},\n\t{\"BUD2_3\", STREAMED_SOUND_MISSION_BUD2_3},    {\"BUD2_4\", STREAMED_SOUND_MISSION_BUD2_4},    {\"BUD2_5\", STREAMED_SOUND_MISSION_BUD2_5},\n\t{\"BUD2_6\", STREAMED_SOUND_MISSION_BUD2_6},    {\"BUD2_7\", STREAMED_SOUND_MISSION_BUD2_7},    {\"BUD3_1a\", STREAMED_SOUND_MISSION_BUD3_1A},\n\t{\"BUD3_1b\", STREAMED_SOUND_MISSION_BUD3_1B},  {\"BUD3_1\", STREAMED_SOUND_MISSION_BUD3_1},    {\"BUD3_2\", STREAMED_SOUND_MISSION_BUD3_2},\n\t{\"BUD3_3\", STREAMED_SOUND_MISSION_BUD3_3},    {\"BUD3_4\", STREAMED_SOUND_MISSION_BUD3_4},    {\"BUD3_1c\", STREAMED_SOUND_MISSION_BUD3_1C},\n\t{\"BUD3_5\", STREAMED_SOUND_MISSION_BUD3_5},    {\"BUD3_6\", STREAMED_SOUND_MISSION_BUD3_6},    {\"BUD3_7\", STREAMED_SOUND_MISSION_BUD3_7},\n\t{\"BUD3_8a\", STREAMED_SOUND_MISSION_BUD3_8A},  {\"BUD3_8b\", STREAMED_SOUND_MISSION_BUD3_8B},  {\"BUD3_8c\", STREAMED_SOUND_MISSION_BUD3_8C},\n\t{\"BUD3_9a\", STREAMED_SOUND_MISSION_BUD3_9A},  {\"BUD3_9b\", STREAMED_SOUND_MISSION_BUD3_9B},  {\"BUD3_9c\", STREAMED_SOUND_MISSION_BUD3_9C},\n\t{\"CAP1_2\", STREAMED_SOUND_MISSION_CAP1_2},    {\"CAP1_3\", STREAMED_SOUND_MISSION_CAP1_3},    {\"CAP1_4\", STREAMED_SOUND_MISSION_CAP1_4},\n\t{\"CAP1_5\", STREAMED_SOUND_MISSION_CAP1_5},    {\"CAP1_6\", STREAMED_SOUND_MISSION_CAP1_6},    {\"CAP1_7\", STREAMED_SOUND_MISSION_CAP1_7},\n\t{\"CAP1_8\", STREAMED_SOUND_MISSION_CAP1_8},    {\"CAP1_9\", STREAMED_SOUND_MISSION_CAP1_9},    {\"CAP1_10\", STREAMED_SOUND_MISSION_CAP1_10},\n\t{\"CAP1_11\", STREAMED_SOUND_MISSION_CAP1_11},  {\"CAP1_12\", STREAMED_SOUND_MISSION_CAP1_12},  {\"FINKILL\", STREAMED_SOUND_MISSION_FINKILL},\n\t{\"FIN_1a\", STREAMED_SOUND_MISSION_FIN_1A},    {\"FIN_1b\", STREAMED_SOUND_MISSION_FIN_1B},    {\"FIN_1c\", STREAMED_SOUND_MISSION_FIN_1C},\n\t{\"FIN_2b\", STREAMED_SOUND_MISSION_FIN_2B},    {\"FIN_2c\", STREAMED_SOUND_MISSION_FIN_2C},    {\"FIN_3\", STREAMED_SOUND_MISSION_FIN_3},\n\t{\"FIN_4\", STREAMED_SOUND_MISSION_FIN_4},      {\"FIN_5\", STREAMED_SOUND_MISSION_FIN_5},      {\"FIN_6\", STREAMED_SOUND_MISSION_FIN_6},\n\t{\"FIN_10\", STREAMED_SOUND_MISSION_FIN_10},    {\"FIN_11a\", STREAMED_SOUND_MISSION_FIN_11A},  {\"FIN_11b\", STREAMED_SOUND_MISSION_FIN_11B},\n\t{\"FIN_12a\", STREAMED_SOUND_MISSION_FIN_12A},  {\"FIN_12b\", STREAMED_SOUND_MISSION_FIN_12B},  {\"FIN_12c\", STREAMED_SOUND_MISSION_FIN_12C},\n\t{\"FIN_13\", STREAMED_SOUND_MISSION_FIN_13},    {\"BNK1_1\", STREAMED_SOUND_MISSION_BNK1_1},    {\"BNK1_2\", STREAMED_SOUND_MISSION_BNK1_2},\n\t{\"BNK1_3\", STREAMED_SOUND_MISSION_BNK1_3},    {\"BNK1_4\", STREAMED_SOUND_MISSION_BNK1_4},    {\"BNK1_5\", STREAMED_SOUND_MISSION_BNK1_5},\n\t{\"BNK1_6\", STREAMED_SOUND_MISSION_BNK1_6},    {\"BNK1_7\", STREAMED_SOUND_MISSION_BNK1_7},    {\"BNK1_8\", STREAMED_SOUND_MISSION_BNK1_8},\n\t{\"BNK1_10\", STREAMED_SOUND_MISSION_BNK1_10},  {\"BNK1_11\", STREAMED_SOUND_MISSION_BNK1_11},  {\"BNK1_12\", STREAMED_SOUND_MISSION_BNK1_12},\n\t{\"BNK1_13\", STREAMED_SOUND_MISSION_BNK1_13},  {\"BNK1_14\", STREAMED_SOUND_MISSION_BNK1_14},  {\"BNK2_1\", STREAMED_SOUND_MISSION_BNK2_1},\n\t{\"BNK2_2\", STREAMED_SOUND_MISSION_BNK2_2},    {\"BNK2_3\", STREAMED_SOUND_MISSION_BNK2_3},    {\"BNK2_4\", STREAMED_SOUND_MISSION_BNK2_4},\n\t{\"BNK2_5\", STREAMED_SOUND_MISSION_BNK2_5},    {\"BNK2_6\", STREAMED_SOUND_MISSION_BNK2_6},    {\"BNK2_7\", STREAMED_SOUND_MISSION_BNK2_7},\n\t{\"BNK2_8\", STREAMED_SOUND_MISSION_BNK2_8},    {\"BNK2_9\", STREAMED_SOUND_MISSION_BNK2_9},    {\"BNK3_1\", STREAMED_SOUND_MISSION_BNK3_1},\n\t{\"BNK3_2\", STREAMED_SOUND_MISSION_BNK3_2},    {\"BNK3_3a\", STREAMED_SOUND_MISSION_BNK3_3A},  {\"BNK3_3b\", STREAMED_SOUND_MISSION_BNK3_3B},\n\t{\"BNK3_3c\", STREAMED_SOUND_MISSION_BNK3_3C},  {\"BNK3_4a\", STREAMED_SOUND_MISSION_BNK3_4A},  {\"BNK3_4b\", STREAMED_SOUND_MISSION_BNK3_4B},\n\t{\"BNK3_4c\", STREAMED_SOUND_MISSION_BNK3_4C},  {\"BNK4_1\", STREAMED_SOUND_MISSION_BNK4_1},    {\"BNK4_2\", STREAMED_SOUND_MISSION_BNK4_2},\n\t{\"BNK4_3A\", STREAMED_SOUND_MISSION_BNK4_3A},  {\"BNK4_3B\", STREAMED_SOUND_MISSION_BNK4_3B},  {\"BNK4_3C\", STREAMED_SOUND_MISSION_BNK4_3C},\n\t{\"BNK4_3D\", STREAMED_SOUND_MISSION_BNK4_3D},  {\"BNK4_3E\", STREAMED_SOUND_MISSION_BNK4_3E},  {\"BNK4_3F\", STREAMED_SOUND_MISSION_BNK4_3F},\n\t{\"BNK4_3G\", STREAMED_SOUND_MISSION_BNK4_3G},  {\"BNK4_3H\", STREAMED_SOUND_MISSION_BNK4_3H},  {\"BNK4_3I\", STREAMED_SOUND_MISSION_BNK4_3I},\n\t{\"BNK4_3J\", STREAMED_SOUND_MISSION_BNK4_3J},  {\"BNK4_3K\", STREAMED_SOUND_MISSION_BNK4_3K},  {\"BNK4_3M\", STREAMED_SOUND_MISSION_BNK4_3M},\n\t{\"BNK4_3O\", STREAMED_SOUND_MISSION_BNK4_3O},  {\"BNK4_3P\", STREAMED_SOUND_MISSION_BNK4_3P},  {\"BNK4_3Q\", STREAMED_SOUND_MISSION_BNK4_3Q},\n\t{\"BNK4_3R\", STREAMED_SOUND_MISSION_BNK4_3R},  {\"BNK4_3S\", STREAMED_SOUND_MISSION_BNK4_3S},  {\"BNK4_3T\", STREAMED_SOUND_MISSION_BNK4_3T},\n\t{\"BNK4_3U\", STREAMED_SOUND_MISSION_BNK4_3U},  {\"BNK4_3V\", STREAMED_SOUND_MISSION_BNK4_3V},  {\"BNK4_4a\", STREAMED_SOUND_MISSION_BNK4_4A},\n\t{\"BNK4_4b\", STREAMED_SOUND_MISSION_BNK4_4B},  {\"BNK4_5\", STREAMED_SOUND_MISSION_BNK4_5},    {\"BNK4_6\", STREAMED_SOUND_MISSION_BNK4_6},\n\t{\"BNK4_7\", STREAMED_SOUND_MISSION_BNK4_7},    {\"BNK4_8\", STREAMED_SOUND_MISSION_BNK4_8},    {\"BNK4_9\", STREAMED_SOUND_MISSION_BNK4_9},\n\t{\"BNK4_10\", STREAMED_SOUND_MISSION_BNK4_10},  {\"BNK4_11\", STREAMED_SOUND_MISSION_BNK4_11},  {\"BK4_12a\", STREAMED_SOUND_MISSION_BK4_12A},\n\t{\"BK4_12b\", STREAMED_SOUND_MISSION_BK4_12B},  {\"BK4_12c\", STREAMED_SOUND_MISSION_BK4_12C},  {\"BNK4_13\", STREAMED_SOUND_MISSION_BNK4_13},\n\t{\"BK4_14a\", STREAMED_SOUND_MISSION_BK4_14A},  {\"BK4_14b\", STREAMED_SOUND_MISSION_BK4_14B},  {\"BNK4_15\", STREAMED_SOUND_MISSION_BNK4_15},\n\t{\"BNK4_16\", STREAMED_SOUND_MISSION_BNK4_16},  {\"BNK4_17\", STREAMED_SOUND_MISSION_BNK4_17},  {\"BNK4_18\", STREAMED_SOUND_MISSION_BNK4_18},\n\t{\"BK4_19a\", STREAMED_SOUND_MISSION_BK4_19A},  {\"BK4_19b\", STREAMED_SOUND_MISSION_BK4_19B},  {\"BK4_20a\", STREAMED_SOUND_MISSION_BK4_20A},\n\t{\"BK4_20b\", STREAMED_SOUND_MISSION_BK4_20B},  {\"BNK4_21\", STREAMED_SOUND_MISSION_BNK4_21},  {\"BNK422a\", STREAMED_SOUND_MISSION_BNK422A},\n\t{\"BNK422b\", STREAMED_SOUND_MISSION_BNK422B},  {\"BK4_23a\", STREAMED_SOUND_MISSION_BK4_23A},  {\"BK4_23b\", STREAMED_SOUND_MISSION_BK4_23B},\n\t{\"BK4_23c\", STREAMED_SOUND_MISSION_BK4_23C},  {\"BK4_23d\", STREAMED_SOUND_MISSION_BK4_23D},  {\"BK4_24a\", STREAMED_SOUND_MISSION_BK4_24A},\n\t{\"BK4_24b\", STREAMED_SOUND_MISSION_BK4_24B},  {\"BNK4_25\", STREAMED_SOUND_MISSION_BNK4_25},  {\"BNK4_26\", STREAMED_SOUND_MISSION_BNK4_26},\n\t{\"BNK4_27\", STREAMED_SOUND_MISSION_BNK4_27},  {\"BNK4_28\", STREAMED_SOUND_MISSION_BNK4_28},  {\"BNK4_29\", STREAMED_SOUND_MISSION_BNK4_29},\n\t{\"BNK4_30\", STREAMED_SOUND_MISSION_BNK4_30},  {\"BK4_31a\", STREAMED_SOUND_MISSION_BK4_31A},  {\"BK4_31b\", STREAMED_SOUND_MISSION_BK4_31B},\n\t{\"BNK4_32\", STREAMED_SOUND_MISSION_BNK4_32},  {\"BK4_34a\", STREAMED_SOUND_MISSION_BK4_34A},  {\"BK4_34b\", STREAMED_SOUND_MISSION_BK4_34B},\n\t{\"BK4_35a\", STREAMED_SOUND_MISSION_BK4_35A},  {\"BK4_35b\", STREAMED_SOUND_MISSION_BK4_35B},  {\"BNK4_36\", STREAMED_SOUND_MISSION_BNK4_36},\n\t{\"BNK4_37\", STREAMED_SOUND_MISSION_BNK4_37},  {\"BNK4_38\", STREAMED_SOUND_MISSION_BNK4_38},  {\"BNK_39\", STREAMED_SOUND_MISSION_BNK4_39},\n\t{\"BK4_40a\", STREAMED_SOUND_MISSION_BK4_40A},  {\"BK4_40b\", STREAMED_SOUND_MISSION_BK4_40B},  {\"BNK4_41\", STREAMED_SOUND_MISSION_BNK4_41},\n\t{\"BNK4_42\", STREAMED_SOUND_MISSION_BNK4_42},  {\"BNK4_43\", STREAMED_SOUND_MISSION_BNK4_43},  {\"BNK4_44\", STREAMED_SOUND_MISSION_BNK4_44},\n\t{\"BNK4_45\", STREAMED_SOUND_MISSION_BNK4_45},  {\"BNK4_46\", STREAMED_SOUND_MISSION_BNK4_46},  {\"BNK4_47\", STREAMED_SOUND_MISSION_BNK4_47},\n\t{\"BNK4_48\", STREAMED_SOUND_MISSION_BNK4_48},  {\"BNK4_49\", STREAMED_SOUND_MISSION_BNK4_49},  {\"BNK450A\", STREAMED_SOUND_MISSION_BNK450A},\n\t{\"BNK450B\", STREAMED_SOUND_MISSION_BNK450B},  {\"BNK4_51\", STREAMED_SOUND_MISSION_BNK4_51},  {\"BNK4_94\", STREAMED_SOUND_MISSION_BNK4_94},\n\t{\"BNK4_95\", STREAMED_SOUND_MISSION_BNK4_95},  {\"BNK4_96\", STREAMED_SOUND_MISSION_BNK4_96},  {\"BNK4_97\", STREAMED_SOUND_MISSION_BNK4_97},\n\t{\"BNK4_98\", STREAMED_SOUND_MISSION_BNK4_98},  {\"BNK4_99\", STREAMED_SOUND_MISSION_BNK4_99},  {\"CNT1_1\", STREAMED_SOUND_MISSION_CNT1_1},\n\t{\"CNT1_2\", STREAMED_SOUND_MISSION_CNT1_2},    {\"CNT1_3\", STREAMED_SOUND_MISSION_CNT1_3},    {\"CNT1_4\", STREAMED_SOUND_MISSION_CNT1_4},\n\t{\"CNT1_5\", STREAMED_SOUND_MISSION_CNT1_5},    {\"CNT2_1\", STREAMED_SOUND_MISSION_CNT2_1},    {\"CNT2_2\", STREAMED_SOUND_MISSION_CNT2_2},\n\t{\"CNT2_3\", STREAMED_SOUND_MISSION_CNT2_3},    {\"CNT2_4\", STREAMED_SOUND_MISSION_CNT2_4},    {\"PORN1_1\", STREAMED_SOUND_MISSION_PORN1_1},\n\t{\"PORN1_2\", STREAMED_SOUND_MISSION_PORN1_2},  {\"PORN1_3\", STREAMED_SOUND_MISSION_PORN1_3},  {\"PRN1_3A\", STREAMED_SOUND_MISSION_PRN1_3A},\n\t{\"PORN1_4\", STREAMED_SOUND_MISSION_PORN1_4},  {\"PORN1_5\", STREAMED_SOUND_MISSION_PORN1_5},  {\"PORN1_6\", STREAMED_SOUND_MISSION_PORN1_6},\n\t{\"PORN1_7\", STREAMED_SOUND_MISSION_PORN1_7},  {\"PORN1_8\", STREAMED_SOUND_MISSION_PORN1_8},  {\"PORN1_9\", STREAMED_SOUND_MISSION_PORN1_9},\n\t{\"PRN1_10\", STREAMED_SOUND_MISSION_PRN1_10},  {\"PRN1_11\", STREAMED_SOUND_MISSION_PRN1_11},  {\"PRN1_12\", STREAMED_SOUND_MISSION_PRN1_12},\n\t{\"PRN1_13\", STREAMED_SOUND_MISSION_PRN1_13},  {\"PRN1_14\", STREAMED_SOUND_MISSION_PRN1_14},  {\"PRN1_15\", STREAMED_SOUND_MISSION_PRN1_15},\n\t{\"PRN1_16\", STREAMED_SOUND_MISSION_PRN1_16},  {\"PRN1_17\", STREAMED_SOUND_MISSION_PRN1_17},  {\"PRN1_18\", STREAMED_SOUND_MISSION_PRN1_18},\n\t{\"PRN1_19\", STREAMED_SOUND_MISSION_PRN1_19},  {\"PRN1_20\", STREAMED_SOUND_MISSION_PRN1_20},  {\"PRN1_21\", STREAMED_SOUND_MISSION_PRN1_21},\n\t{\"PORN3_1\", STREAMED_SOUND_MISSION_PORN3_1},  {\"PORN3_2\", STREAMED_SOUND_MISSION_PORN3_2},  {\"PORN3_3\", STREAMED_SOUND_MISSION_PORN3_3},\n\t{\"PORN3_4\", STREAMED_SOUND_MISSION_PORN3_4},  {\"TAX1_1\", STREAMED_SOUND_MISSION_TAX1_1},    {\"TAX1_2\", STREAMED_SOUND_MISSION_TAX1_2},\n\t{\"TAX1_3\", STREAMED_SOUND_MISSION_TAX1_3},    {\"TAX1_4\", STREAMED_SOUND_MISSION_TAX1_4},    {\"TAX1_5\", STREAMED_SOUND_MISSION_TAX1_5},\n\t{\"TAX2_1\", STREAMED_SOUND_MISSION_TAX2_1},    {\"TAX2_2\", STREAMED_SOUND_MISSION_TAX2_2},    {\"TAX2_3\", STREAMED_SOUND_MISSION_TAX2_3},\n\t{\"TAX2_4\", STREAMED_SOUND_MISSION_TAX2_4},    {\"TAX2_5\", STREAMED_SOUND_MISSION_TAX2_5},    {\"TAX2_6\", STREAMED_SOUND_MISSION_TAX2_6},\n\t{\"TAX2_7\", STREAMED_SOUND_MISSION_TAX2_7},    {\"TAX3_1\", STREAMED_SOUND_MISSION_TAX3_1},    {\"TAX3_2\", STREAMED_SOUND_MISSION_TAX3_2},\n\t{\"TAX3_3\", STREAMED_SOUND_MISSION_TAX3_3},    {\"TAX3_4\", STREAMED_SOUND_MISSION_TAX3_4},    {\"TAX3_5\", STREAMED_SOUND_MISSION_TAX3_5},\n\t{\"TEX1_1\", STREAMED_SOUND_MISSION_TEX1_1},    {\"TEX1_2\", STREAMED_SOUND_MISSION_TEX1_2},    {\"TEX1_3\", STREAMED_SOUND_MISSION_TEX1_3},\n\t{\"TEX1_4\", STREAMED_SOUND_MISSION_TEX1_4},    {\"TEX1_5\", STREAMED_SOUND_MISSION_TEX1_5},    {\"TEX1_6\", STREAMED_SOUND_MISSION_TEX1_6},\n\t{\"TEX2_1\", STREAMED_SOUND_MISSION_TEX2_1},    {\"TEX3_1\", STREAMED_SOUND_MISSION_TEX3_1},    {\"TEX3_2\", STREAMED_SOUND_MISSION_TEX3_2},\n\t{\"TEX3_3\", STREAMED_SOUND_MISSION_TEX3_3},    {\"TEX3_4\", STREAMED_SOUND_MISSION_TEX3_4},    {\"TEX3_5\", STREAMED_SOUND_MISSION_TEX3_5},\n\t{\"TEX3_6\", STREAMED_SOUND_MISSION_TEX3_6},    {\"TEX3_7\", STREAMED_SOUND_MISSION_TEX3_7},    {\"TEX3_8\", STREAMED_SOUND_MISSION_TEX3_8},\n\t{\"PHIL1_2\", STREAMED_SOUND_MISSION_PHIL1_2},  {\"PHIL1_3\", STREAMED_SOUND_MISSION_PHIL1_3},  {\"PHIL2_1\", STREAMED_SOUND_MISSION_PHIL2_1},\n\t{\"PHIL2_2\", STREAMED_SOUND_MISSION_PHIL2_2},  {\"PHIL2_3\", STREAMED_SOUND_MISSION_PHIL2_3},  {\"PHIL2_4\", STREAMED_SOUND_MISSION_PHIL2_4},\n\t{\"PHIL2_5\", STREAMED_SOUND_MISSION_PHIL2_5},  {\"PHIL2_6\", STREAMED_SOUND_MISSION_PHIL2_6},  {\"PHIL2_7\", STREAMED_SOUND_MISSION_PHIL2_7},\n\t{\"PHIL2_8\", STREAMED_SOUND_MISSION_PHIL2_8},  {\"PHIL2_9\", STREAMED_SOUND_MISSION_PHIL2_9},  {\"PHIL210\", STREAMED_SOUND_MISSION_PHIL210},\n\t{\"PHIL211\", STREAMED_SOUND_MISSION_PHIL211},  {\"BIKE1_1\", STREAMED_SOUND_MISSION_BIKE1_1},  {\"BIKE1_2\", STREAMED_SOUND_MISSION_BIKE1_2},\n\t{\"BIKE1_3\", STREAMED_SOUND_MISSION_BIKE1_3},  {\"ROK1_1a\", STREAMED_SOUND_MISSION_ROK1_1A},  {\"ROK1_1b\", STREAMED_SOUND_MISSION_ROK1_1B},\n\t{\"ROK1_5\", STREAMED_SOUND_MISSION_ROK1_5},    {\"ROK1_6\", STREAMED_SOUND_MISSION_ROK1_6},    {\"ROK1_7\", STREAMED_SOUND_MISSION_ROK1_7},\n\t{\"ROK1_8\", STREAMED_SOUND_MISSION_ROK1_8},    {\"ROK1_9\", STREAMED_SOUND_MISSION_ROK1_9},    {\"PSYCH_1\", STREAMED_SOUND_MISSION_PSYCH_1},\n\t{\"PSYCH_2\", STREAMED_SOUND_MISSION_PSYCH_2},  {\"ROK2_01\", STREAMED_SOUND_MISSION_ROK2_01},  {\"ROK3_1\", STREAMED_SOUND_MISSION_ROK3_1},\n\t{\"ROK3_2\", STREAMED_SOUND_MISSION_ROK3_2},    {\"ROK3_3\", STREAMED_SOUND_MISSION_ROK3_3},    {\"ROK3_4\", STREAMED_SOUND_MISSION_ROK3_4},\n\t{\"ROK3_5\", STREAMED_SOUND_MISSION_ROK3_5},    {\"ROK3_6\", STREAMED_SOUND_MISSION_ROK3_6},    {\"ROK3_7\", STREAMED_SOUND_MISSION_ROK3_7},\n\t{\"ROK3_8\", STREAMED_SOUND_MISSION_ROK3_8},    {\"ROK3_9\", STREAMED_SOUND_MISSION_ROK3_9},    {\"ROK3_10\", STREAMED_SOUND_MISSION_ROK3_10},\n\t{\"ROK3_11\", STREAMED_SOUND_MISSION_ROK3_11},  {\"ROK3_12\", STREAMED_SOUND_MISSION_ROK3_12},  {\"ROK3_13\", STREAMED_SOUND_MISSION_ROK3_13},\n\t{\"ROK3_14\", STREAMED_SOUND_MISSION_ROK3_14},  {\"ROK3_15\", STREAMED_SOUND_MISSION_ROK3_15},  {\"ROK3_16\", STREAMED_SOUND_MISSION_ROK3_16},\n\t{\"ROK3_17\", STREAMED_SOUND_MISSION_ROK3_17},  {\"ROK3_18\", STREAMED_SOUND_MISSION_ROK3_18},  {\"ROK3_19\", STREAMED_SOUND_MISSION_ROK3_19},\n\t{\"ROK3_20\", STREAMED_SOUND_MISSION_ROK3_20},  {\"ROK3_21\", STREAMED_SOUND_MISSION_ROK3_21},  {\"ROK3_22\", STREAMED_SOUND_MISSION_ROK3_22},\n\t{\"ROK3_23\", STREAMED_SOUND_MISSION_ROK3_23},  {\"ROK3_24\", STREAMED_SOUND_MISSION_ROK3_24},  {\"ROK3_25\", STREAMED_SOUND_MISSION_ROK3_25},\n\t{\"ROK3_26\", STREAMED_SOUND_MISSION_ROK3_26},  {\"ROK3_27\", STREAMED_SOUND_MISSION_ROK3_27},  {\"ROK3_62\", STREAMED_SOUND_MISSION_ROK3_62},\n\t{\"ROK3_63\", STREAMED_SOUND_MISSION_ROK3_63},  {\"ROK3_64\", STREAMED_SOUND_MISSION_ROK3_64},  {\"ROK3_65\", STREAMED_SOUND_MISSION_ROK3_65},\n\t{\"ROK3_66\", STREAMED_SOUND_MISSION_ROK3_66},  {\"ROK3_67\", STREAMED_SOUND_MISSION_ROK3_67},  {\"ROK3_68\", STREAMED_SOUND_MISSION_ROK3_68},\n\t{\"ROK3_69\", STREAMED_SOUND_MISSION_ROK3_69},  {\"ROK3_70\", STREAMED_SOUND_MISSION_ROK3_70},  {\"ROK3_71\", STREAMED_SOUND_MISSION_ROK3_71},\n\t{\"ROK3_73\", STREAMED_SOUND_MISSION_ROK3_73},  {\"HAT_1a\", STREAMED_SOUND_MISSION_HAT_1A},    {\"intro1\", STREAMED_SOUND_MISSION_INTRO1},\n\t{\"intro2\", STREAMED_SOUND_MISSION_INTRO2},    {\"intro3\", STREAMED_SOUND_MISSION_INTRO3},    {\"intro4\", STREAMED_SOUND_MISSION_INTRO4},\n\t{\"CUB1_1\", STREAMED_SOUND_MISSION_CUB1_1},    {\"CUB1_2\", STREAMED_SOUND_MISSION_CUB1_2},    {\"CUB1_3\", STREAMED_SOUND_MISSION_CUB1_3},\n\t{\"CUB1_4\", STREAMED_SOUND_MISSION_CUB1_4},    {\"CUB1_5\", STREAMED_SOUND_MISSION_CUB1_5},    {\"CUB1_6\", STREAMED_SOUND_MISSION_CUB1_6},\n\t{\"CUB1_7\", STREAMED_SOUND_MISSION_CUB1_7},    {\"CUB1_8\", STREAMED_SOUND_MISSION_CUB1_8},    {\"CUB1_9\", STREAMED_SOUND_MISSION_CUB1_9},\n\t{\"CUB1_10\", STREAMED_SOUND_MISSION_CUB1_10},  {\"CUB2_1\", STREAMED_SOUND_MISSION_CUB2_1},    {\"CUB2_2\", STREAMED_SOUND_MISSION_CUB2_2},\n\t{\"CUB2_3a\", STREAMED_SOUND_MISSION_CUB2_3A},  {\"CUB2_3b\", STREAMED_SOUND_MISSION_CUB2_3B},  {\"CUB2_3c\", STREAMED_SOUND_MISSION_CUB2_3C},\n\t{\"CUB2_4a\", STREAMED_SOUND_MISSION_CUB2_4A},  {\"CUB2_5\", STREAMED_SOUND_MISSION_CUB2_5},    {\"CUB2_6\", STREAMED_SOUND_MISSION_CUB2_6},\n\t{\"CUB2_7\", STREAMED_SOUND_MISSION_CUB2_7},    {\"CUB2_8\", STREAMED_SOUND_MISSION_CUB2_8},    {\"CUB2_9\", STREAMED_SOUND_MISSION_CUB2_9},\n\t{\"CUB2_10\", STREAMED_SOUND_MISSION_CUB2_10},  {\"CUB2_11\", STREAMED_SOUND_MISSION_CUB2_11},  {\"CUB3_1\", STREAMED_SOUND_MISSION_CUB3_1},\n\t{\"CUB3_2\", STREAMED_SOUND_MISSION_CUB3_2},    {\"CUB3_3\", STREAMED_SOUND_MISSION_CUB3_3},    {\"CUB3_4\", STREAMED_SOUND_MISSION_CUB3_4},\n\t{\"CUB4_1\", STREAMED_SOUND_MISSION_CUB4_1},    {\"CUB4_2\", STREAMED_SOUND_MISSION_CUB4_2},    {\"CUB4_3\", STREAMED_SOUND_MISSION_CUB4_3},\n\t{\"CUB4_4\", STREAMED_SOUND_MISSION_CUB4_4},    {\"CUB4_5\", STREAMED_SOUND_MISSION_CUB4_5},    {\"CUB4_5A\", STREAMED_SOUND_MISSION_CUB4_5A},\n\t{\"CUB4_6\", STREAMED_SOUND_MISSION_CUB4_6},    {\"CUB4_7\", STREAMED_SOUND_MISSION_CUB4_7},    {\"CUB4_8\", STREAMED_SOUND_MISSION_CUB4_8},\n\t{\"CUB4_9\", STREAMED_SOUND_MISSION_CUB4_9},    {\"CUB4_10\", STREAMED_SOUND_MISSION_CUB4_10},  {\"CUB4_11\", STREAMED_SOUND_MISSION_CUB4_11},\n\t{\"CUB4_12\", STREAMED_SOUND_MISSION_CUB4_12},  {\"CUB4_13\", STREAMED_SOUND_MISSION_CUB4_13},  {\"CUB4_14\", STREAMED_SOUND_MISSION_CUB4_14},\n\t{\"CUB4_15\", STREAMED_SOUND_MISSION_CUB4_15},  {\"CUB4_16\", STREAMED_SOUND_MISSION_CUB4_16},  {\"golf_1\", STREAMED_SOUND_MISSION_GOLF_1},\n\t{\"golf_2\", STREAMED_SOUND_MISSION_GOLF_2},    {\"golf_3\", STREAMED_SOUND_MISSION_GOLF_3},    {\"bar_1\", STREAMED_SOUND_MISSION_BAR_1},\n\t{\"bar_2\", STREAMED_SOUND_MISSION_BAR_2},      {\"bar_3\", STREAMED_SOUND_MISSION_BAR_3},      {\"bar_4\", STREAMED_SOUND_MISSION_BAR_4},\n\t{\"bar_5\", STREAMED_SOUND_MISSION_BAR_5},      {\"bar_6\", STREAMED_SOUND_MISSION_BAR_6},      {\"bar_7\", STREAMED_SOUND_MISSION_BAR_7},\n\t{\"bar_8\", STREAMED_SOUND_MISSION_BAR_8},      {\"strip_1\", STREAMED_SOUND_MISSION_STRIP_1},  {\"strip_2\", STREAMED_SOUND_MISSION_STRIP_2},\n\t{\"strip_3\", STREAMED_SOUND_MISSION_STRIP_3},  {\"strip_4\", STREAMED_SOUND_MISSION_STRIP_4},  {\"strip_5\", STREAMED_SOUND_MISSION_STRIP_5},\n\t{\"strip_6\", STREAMED_SOUND_MISSION_STRIP_6},  {\"strip_7\", STREAMED_SOUND_MISSION_STRIP_7},  {\"strip_8\", STREAMED_SOUND_MISSION_STRIP_8},\n\t{\"strip_9\", STREAMED_SOUND_MISSION_STRIP_9},  {\"star_1\", STREAMED_SOUND_MISSION_STAR_1},    {\"star_2\", STREAMED_SOUND_MISSION_STAR_2},\n\t{\"star_3\", STREAMED_SOUND_MISSION_STAR_3},    {\"star_4\", STREAMED_SOUND_MISSION_STAR_4},    {\"mob_01a\", STREAMED_SOUND_MISSION_MOB_01A},\n\t{\"mob_01b\", STREAMED_SOUND_MISSION_MOB_01B},  {\"mob_01c\", STREAMED_SOUND_MISSION_MOB_01C},  {\"mob_02a\", STREAMED_SOUND_MISSION_MOB_02A},\n\t{\"mob_02b\", STREAMED_SOUND_MISSION_MOB_02B},  {\"mob_02c\", STREAMED_SOUND_MISSION_MOB_02C},  {\"mob_03a\", STREAMED_SOUND_MISSION_MOB_03A},\n\t{\"mob_03b\", STREAMED_SOUND_MISSION_MOB_03B},  {\"mob_03c\", STREAMED_SOUND_MISSION_MOB_03C},  {\"mob_03d\", STREAMED_SOUND_MISSION_MOB_03D},\n\t{\"mob_03e\", STREAMED_SOUND_MISSION_MOB_03E},  {\"shark_1\", STREAMED_SOUND_MISSION_SHARK_1},  {\"shark_2\", STREAMED_SOUND_MISSION_SHARK_2},\n\t{\"shark_3\", STREAMED_SOUND_MISSION_SHARK_3},  {\"shark_4\", STREAMED_SOUND_MISSION_SHARK_4},  {\"shark_5\", STREAMED_SOUND_MISSION_SHARK_5},\n\t{\"mob_04a\", STREAMED_SOUND_MISSION_MOB_04A},  {\"mob_04b\", STREAMED_SOUND_MISSION_MOB_04B},  {\"mob_04c\", STREAMED_SOUND_MISSION_MOB_04C},\n\t{\"mob_04d\", STREAMED_SOUND_MISSION_MOB_04D},  {\"mob_05a\", STREAMED_SOUND_MISSION_MOB_05A},  {\"mob_05b\", STREAMED_SOUND_MISSION_MOB_05B},\n\t{\"mob_05c\", STREAMED_SOUND_MISSION_MOB_05C},  {\"mob_05d\", STREAMED_SOUND_MISSION_MOB_05D},  {\"mob_06a\", STREAMED_SOUND_MISSION_MOB_06A},\n\t{\"mob_06b\", STREAMED_SOUND_MISSION_MOB_06B},  {\"mob_06c\", STREAMED_SOUND_MISSION_MOB_06C},  {\"mob_07a\", STREAMED_SOUND_MISSION_MOB_07A},\n\t{\"mob_07b\", STREAMED_SOUND_MISSION_MOB_07B},  {\"mob_08a\", STREAMED_SOUND_MISSION_MOB_08A},  {\"mob_08b\", STREAMED_SOUND_MISSION_MOB_08B},\n\t{\"mob_08c\", STREAMED_SOUND_MISSION_MOB_08C},  {\"mob_08d\", STREAMED_SOUND_MISSION_MOB_08D},  {\"mob_08e\", STREAMED_SOUND_MISSION_MOB_08E},\n\t{\"mob_08f\", STREAMED_SOUND_MISSION_MOB_08F},  {\"mob_08g\", STREAMED_SOUND_MISSION_MOB_08G},  {\"mob_09a\", STREAMED_SOUND_MISSION_MOB_09A},\n\t{\"mob_09b\", STREAMED_SOUND_MISSION_MOB_09B},  {\"mob_09c\", STREAMED_SOUND_MISSION_MOB_09C},  {\"mob_09d\", STREAMED_SOUND_MISSION_MOB_09D},\n\t{\"mob_09e\", STREAMED_SOUND_MISSION_MOB_09E},  {\"mob_09f\", STREAMED_SOUND_MISSION_MOB_09F},  {\"mob_10a\", STREAMED_SOUND_MISSION_MOB_10A},\n\t{\"mob_10b\", STREAMED_SOUND_MISSION_MOB_10B},  {\"mob_10c\", STREAMED_SOUND_MISSION_MOB_10C},  {\"mob_10d\", STREAMED_SOUND_MISSION_MOB_10D},\n\t{\"mob_10e\", STREAMED_SOUND_MISSION_MOB_10E},  {\"mob_11a\", STREAMED_SOUND_MISSION_MOB_11A},  {\"mob_11b\", STREAMED_SOUND_MISSION_MOB_11B},\n\t{\"mob_11c\", STREAMED_SOUND_MISSION_MOB_11C},  {\"mob_11d\", STREAMED_SOUND_MISSION_MOB_11D},  {\"mob_11e\", STREAMED_SOUND_MISSION_MOB_11E},\n\t{\"mob_11f\", STREAMED_SOUND_MISSION_MOB_11F},  {\"mob_14a\", STREAMED_SOUND_MISSION_MOB_14A},  {\"mob_14b\", STREAMED_SOUND_MISSION_MOB_14B},\n\t{\"mob_14c\", STREAMED_SOUND_MISSION_MOB_14C},  {\"mob_14d\", STREAMED_SOUND_MISSION_MOB_14D},  {\"mob_14e\", STREAMED_SOUND_MISSION_MOB_14E},\n\t{\"mob_14f\", STREAMED_SOUND_MISSION_MOB_14F},  {\"mob_14g\", STREAMED_SOUND_MISSION_MOB_14G},  {\"mob_14h\", STREAMED_SOUND_MISSION_MOB_14H},\n\t{\"mob_16a\", STREAMED_SOUND_MISSION_MOB_16A},  {\"mob_16b\", STREAMED_SOUND_MISSION_MOB_16B},  {\"mob_16c\", STREAMED_SOUND_MISSION_MOB_16C},\n\t{\"mob_16d\", STREAMED_SOUND_MISSION_MOB_16D},  {\"mob_16e\", STREAMED_SOUND_MISSION_MOB_16E},  {\"mob_16f\", STREAMED_SOUND_MISSION_MOB_16F},\n\t{\"mob_16g\", STREAMED_SOUND_MISSION_MOB_16G},  {\"mob_17a\", STREAMED_SOUND_MISSION_MOB_17A},  {\"mob_17b\", STREAMED_SOUND_MISSION_MOB_17B},\n\t{\"mob_17c\", STREAMED_SOUND_MISSION_MOB_17C},  {\"mob_17d\", STREAMED_SOUND_MISSION_MOB_17D},  {\"mob_17e\", STREAMED_SOUND_MISSION_MOB_17E},\n\t{\"mob_17g\", STREAMED_SOUND_MISSION_MOB_17G},  {\"mob_17h\", STREAMED_SOUND_MISSION_MOB_17H},  {\"mob_17i\", STREAMED_SOUND_MISSION_MOB_17I},\n\t{\"mob_17j\", STREAMED_SOUND_MISSION_MOB_17J},  {\"mob_17k\", STREAMED_SOUND_MISSION_MOB_17K},  {\"mob_17l\", STREAMED_SOUND_MISSION_MOB_17L},\n\t{\"mob_18a\", STREAMED_SOUND_MISSION_MOB_18A},  {\"mob_18b\", STREAMED_SOUND_MISSION_MOB_18B},  {\"mob_18c\", STREAMED_SOUND_MISSION_MOB_18C},\n\t{\"mob_18d\", STREAMED_SOUND_MISSION_MOB_18D},  {\"mob_18e\", STREAMED_SOUND_MISSION_MOB_18E},  {\"mob_18f\", STREAMED_SOUND_MISSION_MOB_18F},\n\t{\"mob_18g\", STREAMED_SOUND_MISSION_MOB_18G},  {\"mob_20a\", STREAMED_SOUND_MISSION_MOB_20A},  {\"mob_20b\", STREAMED_SOUND_MISSION_MOB_20B},\n\t{\"mob_20c\", STREAMED_SOUND_MISSION_MOB_20C},  {\"mob_20d\", STREAMED_SOUND_MISSION_MOB_20D},  {\"mob_20e\", STREAMED_SOUND_MISSION_MOB_20E},\n\t{\"mob_24a\", STREAMED_SOUND_MISSION_MOB_24A},  {\"mob_24b\", STREAMED_SOUND_MISSION_MOB_24B},  {\"mob_24c\", STREAMED_SOUND_MISSION_MOB_24C},\n\t{\"mob_24d\", STREAMED_SOUND_MISSION_MOB_24D},  {\"mob_24e\", STREAMED_SOUND_MISSION_MOB_24E},  {\"mob_24f\", STREAMED_SOUND_MISSION_MOB_24F},\n\t{\"mob_24g\", STREAMED_SOUND_MISSION_MOB_24G},  {\"mob_24h\", STREAMED_SOUND_MISSION_MOB_24H},  {\"mob_25a\", STREAMED_SOUND_MISSION_MOB_25A},\n\t{\"mob_25b\", STREAMED_SOUND_MISSION_MOB_25B},  {\"mob_25c\", STREAMED_SOUND_MISSION_MOB_25C},  {\"mob_25d\", STREAMED_SOUND_MISSION_MOB_25D},\n\t{\"mob_26a\", STREAMED_SOUND_MISSION_MOB_26A},  {\"mob_26b\", STREAMED_SOUND_MISSION_MOB_26B},  {\"mob_26c\", STREAMED_SOUND_MISSION_MOB_26C},\n\t{\"mob_26d\", STREAMED_SOUND_MISSION_MOB_26D},  {\"mob_26e\", STREAMED_SOUND_MISSION_MOB_26E},  {\"mob_29a\", STREAMED_SOUND_MISSION_MOB_29A},\n\t{\"mob_29b\", STREAMED_SOUND_MISSION_MOB_29B},  {\"mob_29c\", STREAMED_SOUND_MISSION_MOB_29C},  {\"mob_29d\", STREAMED_SOUND_MISSION_MOB_29D},\n\t{\"mob_29e\", STREAMED_SOUND_MISSION_MOB_29E},  {\"mob_29f\", STREAMED_SOUND_MISSION_MOB_29F},  {\"mob_29g\", STREAMED_SOUND_MISSION_MOB_29G},\n\t{\"mob_30a\", STREAMED_SOUND_MISSION_MOB_30A},  {\"mob_30b\", STREAMED_SOUND_MISSION_MOB_30B},  {\"mob_30c\", STREAMED_SOUND_MISSION_MOB_30C},\n\t{\"mob_30d\", STREAMED_SOUND_MISSION_MOB_30D},  {\"mob_30e\", STREAMED_SOUND_MISSION_MOB_30E},  {\"mob_30f\", STREAMED_SOUND_MISSION_MOB_30F},\n\t{\"mob_33a\", STREAMED_SOUND_MISSION_MOB_33A},  {\"mob_33b\", STREAMED_SOUND_MISSION_MOB_33B},  {\"mob_33c\", STREAMED_SOUND_MISSION_MOB_33C},\n\t{\"mob_33d\", STREAMED_SOUND_MISSION_MOB_33D},  {\"mob_34a\", STREAMED_SOUND_MISSION_MOB_34A},  {\"mob_34b\", STREAMED_SOUND_MISSION_MOB_34B},\n\t{\"mob_34c\", STREAMED_SOUND_MISSION_MOB_34C},  {\"mob_34d\", STREAMED_SOUND_MISSION_MOB_34D},  {\"mob_35a\", STREAMED_SOUND_MISSION_MOB_35A},\n\t{\"mob_35b\", STREAMED_SOUND_MISSION_MOB_35B},  {\"mob_35c\", STREAMED_SOUND_MISSION_MOB_35C},  {\"mob_35d\", STREAMED_SOUND_MISSION_MOB_35D},\n\t{\"mob_36a\", STREAMED_SOUND_MISSION_MOB_36A},  {\"mob_36b\", STREAMED_SOUND_MISSION_MOB_36B},  {\"mob_36c\", STREAMED_SOUND_MISSION_MOB_36C},\n\t{\"mob_40a\", STREAMED_SOUND_MISSION_MOB_40A},  {\"mob_40b\", STREAMED_SOUND_MISSION_MOB_40B},  {\"mob_40c\", STREAMED_SOUND_MISSION_MOB_40C},\n\t{\"mob_40d\", STREAMED_SOUND_MISSION_MOB_40D},  {\"mob_40e\", STREAMED_SOUND_MISSION_MOB_40E},  {\"mob_40f\", STREAMED_SOUND_MISSION_MOB_40F},\n\t{\"mob_40g\", STREAMED_SOUND_MISSION_MOB_40G},  {\"mob_40h\", STREAMED_SOUND_MISSION_MOB_40H},  {\"mob_40i\", STREAMED_SOUND_MISSION_MOB_40I},\n\t{\"mob_41a\", STREAMED_SOUND_MISSION_MOB_41A},  {\"mob_41b\", STREAMED_SOUND_MISSION_MOB_41B},  {\"mob_41c\", STREAMED_SOUND_MISSION_MOB_41C},\n\t{\"mob_41d\", STREAMED_SOUND_MISSION_MOB_41D},  {\"mob_41e\", STREAMED_SOUND_MISSION_MOB_41E},  {\"mob_41f\", STREAMED_SOUND_MISSION_MOB_41F},\n\t{\"mob_41g\", STREAMED_SOUND_MISSION_MOB_41G},  {\"mob_41h\", STREAMED_SOUND_MISSION_MOB_41H},  {\"mob_42a\", STREAMED_SOUND_MISSION_MOB_42A},\n\t{\"mob_42b\", STREAMED_SOUND_MISSION_MOB_42B},  {\"mob_42c\", STREAMED_SOUND_MISSION_MOB_42C},  {\"mob_42d\", STREAMED_SOUND_MISSION_MOB_42D},\n\t{\"mob_42e\", STREAMED_SOUND_MISSION_MOB_42E},  {\"mob_43a\", STREAMED_SOUND_MISSION_MOB_43A},  {\"mob_43b\", STREAMED_SOUND_MISSION_MOB_43B},\n\t{\"mob_43c\", STREAMED_SOUND_MISSION_MOB_43C},  {\"mob_43d\", STREAMED_SOUND_MISSION_MOB_43D},  {\"mob_43e\", STREAMED_SOUND_MISSION_MOB_43E},\n\t{\"mob_43f\", STREAMED_SOUND_MISSION_MOB_43F},  {\"mob_43g\", STREAMED_SOUND_MISSION_MOB_43G},  {\"mob_43h\", STREAMED_SOUND_MISSION_MOB_43H},\n\t{\"mob_45a\", STREAMED_SOUND_MISSION_MOB_45A},  {\"mob_45b\", STREAMED_SOUND_MISSION_MOB_45B},  {\"mob_45c\", STREAMED_SOUND_MISSION_MOB_45C},\n\t{\"mob_45d\", STREAMED_SOUND_MISSION_MOB_45D},  {\"mob_45e\", STREAMED_SOUND_MISSION_MOB_45E},  {\"mob_45f\", STREAMED_SOUND_MISSION_MOB_45F},\n\t{\"mob_45g\", STREAMED_SOUND_MISSION_MOB_45G},  {\"mob_45h\", STREAMED_SOUND_MISSION_MOB_45H},  {\"mob_45i\", STREAMED_SOUND_MISSION_MOB_45I},\n\t{\"mob_45j\", STREAMED_SOUND_MISSION_MOB_45J},  {\"mob_45k\", STREAMED_SOUND_MISSION_MOB_45K},  {\"mob_45l\", STREAMED_SOUND_MISSION_MOB_45L},\n\t{\"mob_45m\", STREAMED_SOUND_MISSION_MOB_45M},  {\"mob_45n\", STREAMED_SOUND_MISSION_MOB_45N},  {\"mob_46a\", STREAMED_SOUND_MISSION_MOB_46A},\n\t{\"mob_46b\", STREAMED_SOUND_MISSION_MOB_46B},  {\"mob_46c\", STREAMED_SOUND_MISSION_MOB_46C},  {\"mob_46d\", STREAMED_SOUND_MISSION_MOB_46D},\n\t{\"mob_46e\", STREAMED_SOUND_MISSION_MOB_46E},  {\"mob_46f\", STREAMED_SOUND_MISSION_MOB_46F},  {\"mob_46g\", STREAMED_SOUND_MISSION_MOB_46G},\n\t{\"mob_46h\", STREAMED_SOUND_MISSION_MOB_46H},  {\"mob_47a\", STREAMED_SOUND_MISSION_MOB_47A},  {\"mob_52a\", STREAMED_SOUND_MISSION_MOB_52A},\n\t{\"mob_52b\", STREAMED_SOUND_MISSION_MOB_52B},  {\"mob_52c\", STREAMED_SOUND_MISSION_MOB_52C},  {\"mob_52d\", STREAMED_SOUND_MISSION_MOB_52D},\n\t{\"mob_52e\", STREAMED_SOUND_MISSION_MOB_52E},  {\"mob_52f\", STREAMED_SOUND_MISSION_MOB_52F},  {\"mob_52g\", STREAMED_SOUND_MISSION_MOB_52G},\n\t{\"mob_52h\", STREAMED_SOUND_MISSION_MOB_52H},  {\"mob_54a\", STREAMED_SOUND_MISSION_MOB_54A},  {\"mob_54b\", STREAMED_SOUND_MISSION_MOB_54B},\n\t{\"mob_54c\", STREAMED_SOUND_MISSION_MOB_54C},  {\"mob_54d\", STREAMED_SOUND_MISSION_MOB_54D},  {\"mob_54e\", STREAMED_SOUND_MISSION_MOB_54E},\n\t{\"mob_55a\", STREAMED_SOUND_MISSION_MOB_55A},  {\"mob_55b\", STREAMED_SOUND_MISSION_MOB_55B},  {\"mob_55c\", STREAMED_SOUND_MISSION_MOB_55C},\n\t{\"mob_55d\", STREAMED_SOUND_MISSION_MOB_55D},  {\"mob_55e\", STREAMED_SOUND_MISSION_MOB_55E},  {\"mob_55f\", STREAMED_SOUND_MISSION_MOB_55F},\n\t{\"mob_56a\", STREAMED_SOUND_MISSION_MOB_56A},  {\"mob_56b\", STREAMED_SOUND_MISSION_MOB_56B},  {\"mob_56c\", STREAMED_SOUND_MISSION_MOB_56C},\n\t{\"mob_56d\", STREAMED_SOUND_MISSION_MOB_56D},  {\"mob_56e\", STREAMED_SOUND_MISSION_MOB_56E},  {\"mob_56f\", STREAMED_SOUND_MISSION_MOB_56F},\n\t{\"mob_57a\", STREAMED_SOUND_MISSION_MOB_57A},  {\"mob_57b\", STREAMED_SOUND_MISSION_MOB_57B},  {\"mob_57c\", STREAMED_SOUND_MISSION_MOB_57C},\n\t{\"mob_57d\", STREAMED_SOUND_MISSION_MOB_57D},  {\"mob_57e\", STREAMED_SOUND_MISSION_MOB_57E},  {\"mob_58a\", STREAMED_SOUND_MISSION_MOB_58A},\n\t{\"mob_58b\", STREAMED_SOUND_MISSION_MOB_58B},  {\"mob_58c\", STREAMED_SOUND_MISSION_MOB_58C},  {\"mob_58d\", STREAMED_SOUND_MISSION_MOB_58D},\n\t{\"mob_58e\", STREAMED_SOUND_MISSION_MOB_58E},  {\"mob_58f\", STREAMED_SOUND_MISSION_MOB_58F},  {\"mob_58g\", STREAMED_SOUND_MISSION_MOB_58G},\n\t{\"mob_61a\", STREAMED_SOUND_MISSION_MOB_61A},  {\"mob_61b\", STREAMED_SOUND_MISSION_MOB_61B},  {\"mob_62a\", STREAMED_SOUND_MISSION_MOB_62A},\n\t{\"mob_62b\", STREAMED_SOUND_MISSION_MOB_62B},  {\"mob_62c\", STREAMED_SOUND_MISSION_MOB_62C},  {\"mob_62d\", STREAMED_SOUND_MISSION_MOB_62D},\n\t{\"mob_63a\", STREAMED_SOUND_MISSION_MOB_63A},  {\"mob_63b\", STREAMED_SOUND_MISSION_MOB_63B},  {\"mob_63c\", STREAMED_SOUND_MISSION_MOB_63C},\n\t{\"mob_63d\", STREAMED_SOUND_MISSION_MOB_63D},  {\"mob_63e\", STREAMED_SOUND_MISSION_MOB_63E},  {\"mob_63f\", STREAMED_SOUND_MISSION_MOB_63F},\n\t{\"mob_63g\", STREAMED_SOUND_MISSION_MOB_63G},  {\"mob_63h\", STREAMED_SOUND_MISSION_MOB_63H},  {\"mob_63i\", STREAMED_SOUND_MISSION_MOB_63I},\n\t{\"mob_63j\", STREAMED_SOUND_MISSION_MOB_63J},  {\"mob_66a\", STREAMED_SOUND_MISSION_MOB_66A},  {\"mob_66b\", STREAMED_SOUND_MISSION_MOB_66B},\n\t{\"mob_68a\", STREAMED_SOUND_MISSION_MOB_68A},  {\"mob_68b\", STREAMED_SOUND_MISSION_MOB_68B},  {\"mob_68c\", STREAMED_SOUND_MISSION_MOB_68C},\n\t{\"mob_68d\", STREAMED_SOUND_MISSION_MOB_68D},  {\"mob_70a\", STREAMED_SOUND_MISSION_MOB_70A},  {\"mob_70b\", STREAMED_SOUND_MISSION_MOB_70B},\n\t{\"mob_71a\", STREAMED_SOUND_MISSION_MOB_71A},  {\"mob_71b\", STREAMED_SOUND_MISSION_MOB_71B},  {\"mob_71c\", STREAMED_SOUND_MISSION_MOB_71C},\n\t{\"mob_71d\", STREAMED_SOUND_MISSION_MOB_71D},  {\"mob_71e\", STREAMED_SOUND_MISSION_MOB_71E},  {\"mob_71f\", STREAMED_SOUND_MISSION_MOB_71F},\n\t{\"mob_71g\", STREAMED_SOUND_MISSION_MOB_71G},  {\"mob_71h\", STREAMED_SOUND_MISSION_MOB_71H},  {\"mob_71i\", STREAMED_SOUND_MISSION_MOB_71I},\n\t{\"mob_71j\", STREAMED_SOUND_MISSION_MOB_71J},  {\"mob_71k\", STREAMED_SOUND_MISSION_MOB_71K},  {\"mob_71l\", STREAMED_SOUND_MISSION_MOB_71L},\n\t{\"mob_71m\", STREAMED_SOUND_MISSION_MOB_71M},  {\"mob_71n\", STREAMED_SOUND_MISSION_MOB_71N},  {\"mob_72a\", STREAMED_SOUND_MISSION_MOB_72A},\n\t{\"mob_72b\", STREAMED_SOUND_MISSION_MOB_72B},  {\"mob_72c\", STREAMED_SOUND_MISSION_MOB_72C},  {\"mob_72d\", STREAMED_SOUND_MISSION_MOB_72D},\n\t{\"mob_72e\", STREAMED_SOUND_MISSION_MOB_72E},  {\"mob_72f\", STREAMED_SOUND_MISSION_MOB_72F},  {\"mob_72g\", STREAMED_SOUND_MISSION_MOB_72G},\n\t{\"mob_73a\", STREAMED_SOUND_MISSION_MOB_73A},  {\"mob_73c\", STREAMED_SOUND_MISSION_MOB_73C},  {\"mob_73d\", STREAMED_SOUND_MISSION_MOB_73D},\n\t{\"mob_73f\", STREAMED_SOUND_MISSION_MOB_73F},  {\"mob_73g\", STREAMED_SOUND_MISSION_MOB_73G},  {\"mob_73i\", STREAMED_SOUND_MISSION_MOB_73I},\n\t{\"mob_95a\", STREAMED_SOUND_MISSION_MOB_95A},  {\"mob_96a\", STREAMED_SOUND_MISSION_MOB_96A},  {\"mob_98a\", STREAMED_SOUND_MISSION_MOB_98A},\n\t{\"mob_99a\", STREAMED_SOUND_MISSION_MOB_99A},  {\"job1_1b\", STREAMED_SOUND_MISSION_JOB1_1B},  {\"job1_1c\", STREAMED_SOUND_MISSION_JOB1_1C},\n\t{\"job1_1d\", STREAMED_SOUND_MISSION_JOB1_1D},  {\"job2_1b\", STREAMED_SOUND_MISSION_JOB2_1B},  {\"job2_2\", STREAMED_SOUND_MISSION_JOB2_2},\n\t{\"job2_3\", STREAMED_SOUND_MISSION_JOB2_3},    {\"job2_4\", STREAMED_SOUND_MISSION_JOB2_4},    {\"job2_5\", STREAMED_SOUND_MISSION_JOB2_5},\n\t{\"job2_6\", STREAMED_SOUND_MISSION_JOB2_6},    {\"job2_7\", STREAMED_SOUND_MISSION_JOB2_7},    {\"job2_8\", STREAMED_SOUND_MISSION_JOB2_8},\n\t{\"job2_9\", STREAMED_SOUND_MISSION_JOB2_9},    {\"job3_1\", STREAMED_SOUND_MISSION_JOB3_1},    {\"job3_2\", STREAMED_SOUND_MISSION_JOB3_2},\n\t{\"job3_3\", STREAMED_SOUND_MISSION_JOB3_3},    {\"job4_1\", STREAMED_SOUND_MISSION_JOB4_1},    {\"job4_2\", STREAMED_SOUND_MISSION_JOB4_2},\n\t{\"job4_3\", STREAMED_SOUND_MISSION_JOB4_3},    {\"job5_1\", STREAMED_SOUND_MISSION_JOB5_1},    {\"job5_2\", STREAMED_SOUND_MISSION_JOB5_2},\n\t{\"job5_3\", STREAMED_SOUND_MISSION_JOB5_3},    {\"bjm1_20\", STREAMED_SOUND_MISSION_BJM1_20},  {\"bjm1_4\", STREAMED_SOUND_MISSION_BJM1_4},\n\t{\"bjm1_5\", STREAMED_SOUND_MISSION_BJM1_5},    {\"merc_39\", STREAMED_SOUND_MISSION_MERC_39},  {\"mono_1\", STREAMED_SOUND_MISSION_MONO_1},\n\t{\"mono_2\", STREAMED_SOUND_MISSION_MONO_2},    {\"mono_3\", STREAMED_SOUND_MISSION_MONO_3},    {\"mono_4\", STREAMED_SOUND_MISSION_MONO_4},\n\t{\"mono_5\", STREAMED_SOUND_MISSION_MONO_5},    {\"mono_6\", STREAMED_SOUND_MISSION_MONO_6},    {\"mono_7\", STREAMED_SOUND_MISSION_MONO_7},\n\t{\"mono_8\", STREAMED_SOUND_MISSION_MONO_8},    {\"mono_9\", STREAMED_SOUND_MISSION_MONO_9},    {\"mono10\", STREAMED_SOUND_MISSION_MONO10},\n\t{\"mono11\", STREAMED_SOUND_MISSION_MONO11},    {\"mono12\", STREAMED_SOUND_MISSION_MONO12},    {\"mono13\", STREAMED_SOUND_MISSION_MONO13},\n\t{\"mono14\", STREAMED_SOUND_MISSION_MONO14},    {\"mono15\", STREAMED_SOUND_MISSION_MONO15},    {\"mono16\", STREAMED_SOUND_MISSION_MONO16},\n\t{\"fud_01\", STREAMED_SOUND_MISSION_FUD_01},    {\"fud_02\", STREAMED_SOUND_MISSION_FUD_02},    {\"fud_03\", STREAMED_SOUND_MISSION_FUD_03},\n\t{\"fud_04\", STREAMED_SOUND_MISSION_FUD_04},    {\"fud_05\", STREAMED_SOUND_MISSION_FUD_05},    {\"fud_06\", STREAMED_SOUND_MISSION_FUD_06},\n\t{\"fud_07\", STREAMED_SOUND_MISSION_FUD_07},    {\"fud_08\", STREAMED_SOUND_MISSION_FUD_08},    {\"fud_09\", STREAMED_SOUND_MISSION_FUD_09},\n\t{\"fud_10\", STREAMED_SOUND_MISSION_FUD_10},    {\"fud_11\", STREAMED_SOUND_MISSION_FUD_11},    {\"fud_12\", STREAMED_SOUND_MISSION_FUD_12},\n\t{\"fud_13\", STREAMED_SOUND_MISSION_FUD_13},    {\"fud_14\", STREAMED_SOUND_MISSION_FUD_14},    {\"fud_15\", STREAMED_SOUND_MISSION_FUD_15},\n\t{\"fud_16\", STREAMED_SOUND_MISSION_FUD_16},    {\"fud_17\", STREAMED_SOUND_MISSION_FUD_17},    {\"fud_18\", STREAMED_SOUND_MISSION_FUD_18},\n\t{\"fud_19\", STREAMED_SOUND_MISSION_FUD_19},    {\"fud_20\", STREAMED_SOUND_MISSION_FUD_20},    {\"burg_01\", STREAMED_SOUND_MISSION_BURG_01},\n\t{\"burg_02\", STREAMED_SOUND_MISSION_BURG_02},  {\"burg_03\", STREAMED_SOUND_MISSION_BURG_03},  {\"burg_04\", STREAMED_SOUND_MISSION_BURG_04},\n\t{\"burg_05\", STREAMED_SOUND_MISSION_BURG_05},  {\"burg_06\", STREAMED_SOUND_MISSION_BURG_06},  {\"burg_07\", STREAMED_SOUND_MISSION_BURG_07},\n\t{\"burg_08\", STREAMED_SOUND_MISSION_BURG_08},  {\"burg_09\", STREAMED_SOUND_MISSION_BURG_09},  {\"burg_10\", STREAMED_SOUND_MISSION_BURG_10},\n\t{\"burg_11\", STREAMED_SOUND_MISSION_BURG_11},  {\"burg_12\", STREAMED_SOUND_MISSION_BURG_12},  {\"crust01\", STREAMED_SOUND_MISSION_CRUST01},\n\t{\"crust02\", STREAMED_SOUND_MISSION_CRUST02},  {\"crust03\", STREAMED_SOUND_MISSION_CRUST03},  {\"crust04\", STREAMED_SOUND_MISSION_CRUST04},\n\t{\"crust05\", STREAMED_SOUND_MISSION_CRUST05},  {\"crust06\", STREAMED_SOUND_MISSION_CRUST06},  {\"crust07\", STREAMED_SOUND_MISSION_CRUST07},\n\t{\"crust08\", STREAMED_SOUND_MISSION_CRUST08},  {\"crust09\", STREAMED_SOUND_MISSION_CRUST09},  {\"band_01\", STREAMED_SOUND_MISSION_BAND_01},\n\t{\"band_02\", STREAMED_SOUND_MISSION_BAND_02},  {\"band_03\", STREAMED_SOUND_MISSION_BAND_03},  {\"band_04\", STREAMED_SOUND_MISSION_BAND_04},\n\t{\"band_05\", STREAMED_SOUND_MISSION_BAND_05},  {\"band_06\", STREAMED_SOUND_MISSION_BAND_06},  {\"band_07\", STREAMED_SOUND_MISSION_BAND_07},\n\t{\"band_08\", STREAMED_SOUND_MISSION_BAND_08},  {\"shaft01\", STREAMED_SOUND_MISSION_SHAFT01},  {\"shaft02\", STREAMED_SOUND_MISSION_SHAFT02},\n\t{\"shaft03\", STREAMED_SOUND_MISSION_SHAFT03},  {\"shaft04\", STREAMED_SOUND_MISSION_SHAFT04},  {\"shaft05\", STREAMED_SOUND_MISSION_SHAFT05},\n\t{\"shaft06\", STREAMED_SOUND_MISSION_SHAFT06},  {\"shaft07\", STREAMED_SOUND_MISSION_SHAFT07},  {\"shaft08\", STREAMED_SOUND_MISSION_SHAFT08},\n\t{\"piss_01\", STREAMED_SOUND_MISSION_PISS_01},  {\"piss_02\", STREAMED_SOUND_MISSION_PISS_02},  {\"piss_03\", STREAMED_SOUND_MISSION_PISS_03},\n\t{\"piss_04\", STREAMED_SOUND_MISSION_PISS_04},  {\"piss_05\", STREAMED_SOUND_MISSION_PISS_05},  {\"piss_06\", STREAMED_SOUND_MISSION_PISS_06},\n\t{\"piss_07\", STREAMED_SOUND_MISSION_PISS_07},  {\"piss_08\", STREAMED_SOUND_MISSION_PISS_08},  {\"piss_09\", STREAMED_SOUND_MISSION_PISS_09},\n\t{\"piss_10\", STREAMED_SOUND_MISSION_PISS_10},  {\"piss_11\", STREAMED_SOUND_MISSION_PISS_11},  {\"piss_12\", STREAMED_SOUND_MISSION_PISS_12},\n\t{\"piss_13\", STREAMED_SOUND_MISSION_PISS_13},  {\"piss_14\", STREAMED_SOUND_MISSION_PISS_14},  {\"piss_15\", STREAMED_SOUND_MISSION_PISS_15},\n\t{\"piss_16\", STREAMED_SOUND_MISSION_PISS_16},  {\"piss_17\", STREAMED_SOUND_MISSION_PISS_17},  {\"piss_18\", STREAMED_SOUND_MISSION_PISS_18},\n\t{\"piss_19\", STREAMED_SOUND_MISSION_PISS_19},  {\"gimme01\", STREAMED_SOUND_MISSION_GIMME01},  {\"gimme02\", STREAMED_SOUND_MISSION_GIMME02},\n\t{\"gimme03\", STREAMED_SOUND_MISSION_GIMME03},  {\"gimme04\", STREAMED_SOUND_MISSION_GIMME04},  {\"gimme05\", STREAMED_SOUND_MISSION_GIMME05},\n\t{\"gimme06\", STREAMED_SOUND_MISSION_GIMME06},  {\"gimme07\", STREAMED_SOUND_MISSION_GIMME07},  {\"gimme08\", STREAMED_SOUND_MISSION_GIMME08},\n\t{\"gimme09\", STREAMED_SOUND_MISSION_GIMME09},  {\"gimme10\", STREAMED_SOUND_MISSION_GIMME10},  {\"gimme11\", STREAMED_SOUND_MISSION_GIMME11},\n\t{\"gimme12\", STREAMED_SOUND_MISSION_GIMME12},  {\"gimme13\", STREAMED_SOUND_MISSION_GIMME13},  {\"gimme14\", STREAMED_SOUND_MISSION_GIMME14},\n\t{\"gimme15\", STREAMED_SOUND_MISSION_GIMME15},  {\"bust_01\", STREAMED_SOUND_MISSION_BUST_01},  {\"bust_02\", STREAMED_SOUND_MISSION_BUST_02},\n\t{\"bust_03\", STREAMED_SOUND_MISSION_BUST_03},  {\"bust_04\", STREAMED_SOUND_MISSION_BUST_04},  {\"bust_05\", STREAMED_SOUND_MISSION_BUST_05},\n\t{\"bust_06\", STREAMED_SOUND_MISSION_BUST_06},  {\"bust_07\", STREAMED_SOUND_MISSION_BUST_07},  {\"bust_08\", STREAMED_SOUND_MISSION_BUST_08},\n\t{\"bust_09\", STREAMED_SOUND_MISSION_BUST_09},  {\"bust_10\", STREAMED_SOUND_MISSION_BUST_10},  {\"bust_11\", STREAMED_SOUND_MISSION_BUST_11},\n\t{\"bust_12\", STREAMED_SOUND_MISSION_BUST_12},  {\"bust_13\", STREAMED_SOUND_MISSION_BUST_13},  {\"bust_14\", STREAMED_SOUND_MISSION_BUST_14},\n\t{\"bust_15\", STREAMED_SOUND_MISSION_BUST_15},  {\"bust_16\", STREAMED_SOUND_MISSION_BUST_16},  {\"bust_17\", STREAMED_SOUND_MISSION_BUST_17},\n\t{\"bust_18\", STREAMED_SOUND_MISSION_BUST_18},  {\"bust_19\", STREAMED_SOUND_MISSION_BUST_19},  {\"bust_20\", STREAMED_SOUND_MISSION_BUST_20},\n\t{\"bust_21\", STREAMED_SOUND_MISSION_BUST_21},  {\"bust_22\", STREAMED_SOUND_MISSION_BUST_22},  {\"bust_23\", STREAMED_SOUND_MISSION_BUST_23},\n\t{\"bust_24\", STREAMED_SOUND_MISSION_BUST_24},  {\"bust_25\", STREAMED_SOUND_MISSION_BUST_25},  {\"bust_26\", STREAMED_SOUND_MISSION_BUST_26},\n\t{\"bust_27\", STREAMED_SOUND_MISSION_BUST_27},  {\"bust_28\", STREAMED_SOUND_MISSION_BUST_28},  {nil, 0} };\n\nint32\nFindMissionAudioSfx(const char *name)\n{\n\tfor (uint32 i = 0; MissionAudioNameSfxAssoc[i].m_pName != nil; ++i) {\n\t\tif (!CGeneral::faststricmp(MissionAudioNameSfxAssoc[i].m_pName, name))\n\t\t\treturn MissionAudioNameSfxAssoc[i].m_nId;\n\t}\n\tdebug(\"Can't find mission audio %s\", name);\n\treturn NO_SAMPLE;\n}\n\nbool\ncAudioManager::MissionScriptAudioUsesPoliceChannel(int32 soundMission) const\n{\n\treturn false;\n}\n\nvoid\ncAudioManager::PreloadMissionAudio(uint8 slot, Const char *name)\n{\n\tif (m_bIsInitialised && slot < MISSION_AUDIO_SLOTS) {\n\t\tint32 missionAudioSfx = FindMissionAudioSfx(name);\n\t\tif (missionAudioSfx != NO_SAMPLE) {\n\t\t\tm_sMissionAudio.m_nSampleIndex[slot] = missionAudioSfx;\n\t\t\tm_sMissionAudio.m_nLoadingStatus[slot] = LOADING_STATUS_NOT_LOADED;\n\t\t\tm_sMissionAudio.m_nPlayStatus[slot] = PLAY_STATUS_STOPPED;\n\t\t\tm_sMissionAudio.m_bIsPlaying[slot] = false;\n\t\t\tm_sMissionAudio.m_nMissionAudioCounter[slot] = m_nTimeSpent * SampleManager.GetStreamedFileLength(missionAudioSfx) / 1000;\n\t\t\tm_sMissionAudio.m_nMissionAudioCounter[slot] *= 4;\n\t\t\tm_sMissionAudio.m_bIsPlayed[slot] = false;\n\t\t\tm_sMissionAudio.m_bPredefinedProperties[slot] = true;\n\t\t\tg_bMissionAudioLoadFailed[slot] = false;\n\t\t}\n\t}\n}\n\nuint8\ncAudioManager::GetMissionAudioLoadingStatus(uint8 slot) const\n{\n\tif (m_bIsInitialised && slot < MISSION_AUDIO_SLOTS)\n\t\treturn m_sMissionAudio.m_nLoadingStatus[slot];\n\n\treturn LOADING_STATUS_LOADED;\n}\n\nvoid\ncAudioManager::SetMissionAudioLocation(uint8 slot, float x, float y, float z)\n{\n\tif (m_bIsInitialised && slot < MISSION_AUDIO_SLOTS) {\n\t\tm_sMissionAudio.m_bPredefinedProperties[slot] = false;\n\t\tm_sMissionAudio.m_vecPos[slot] = CVector(x, y, z);\n\t}\n}\n\nvoid\ncAudioManager::PlayLoadedMissionAudio(uint8 slot)\n{\n\tif (m_bIsInitialised && slot < MISSION_AUDIO_SLOTS && m_sMissionAudio.m_nSampleIndex[slot] != NO_SAMPLE && m_sMissionAudio.m_nLoadingStatus[slot] == LOADING_STATUS_LOADED &&\n\t    m_sMissionAudio.m_nPlayStatus[slot] == PLAY_STATUS_STOPPED)\n\t\tm_sMissionAudio.m_bIsPlayed[slot] = true;\n}\n\nbool\ncAudioManager::ShouldDuckMissionAudio(uint8 slot) const\n{\n\tif (IsMissionAudioSamplePlaying(slot))\n\t\treturn m_sMissionAudio.m_nSampleIndex[slot] != STREAMED_SOUND_MISSION_ROK2_01;\n\treturn false;\n}\n\nbool\ncAudioManager::IsMissionAudioSamplePlaying(uint8 slot) const\n{\n\tif (m_bIsInitialised) {\n\t\tif (slot < MISSION_AUDIO_SLOTS)\n\t\t\treturn m_sMissionAudio.m_nPlayStatus[slot] == PLAY_STATUS_PLAYING;\n\t\telse\n\t\t\treturn true;\n\t} else {\n\t\tstatic int32 cPretendFrame[MISSION_AUDIO_SLOTS] = { 1, 1 };\n\n\t\treturn (cPretendFrame[slot]++ % 64) != 0;\n\t}\n}\n\nbool\ncAudioManager::IsMissionAudioSampleFinished(uint8 slot)\n{\n\tif (m_bIsInitialised) {\n\t\tif (slot < MISSION_AUDIO_SLOTS)\n\t\t\treturn m_sMissionAudio.m_nPlayStatus[slot] == PLAY_STATUS_FINISHED;\n\t\telse\n\t\t\treturn true;\n\t}\n\n\tstatic int32 cPretendFrame[MISSION_AUDIO_SLOTS] = { 1, 1 };\n\n\treturn (cPretendFrame[slot]++ % 64) == 0;\n}\n\nvoid\ncAudioManager::ClearMissionAudio(uint8 slot)\n{\n\tif (m_bIsInitialised && slot < MISSION_AUDIO_SLOTS) {\n\t\tm_sMissionAudio.m_nSampleIndex[slot] = NO_SAMPLE;\n\t\tm_sMissionAudio.m_nLoadingStatus[slot] = LOADING_STATUS_NOT_LOADED;\n\t\tm_sMissionAudio.m_nPlayStatus[slot] = PLAY_STATUS_STOPPED;\n\t\tm_sMissionAudio.m_bIsPlaying[slot] = false;\n\t\tm_sMissionAudio.m_bIsPlayed[slot] = false;\n\t\tm_sMissionAudio.m_bPredefinedProperties[slot] = true;\n\t\tm_sMissionAudio.m_nMissionAudioCounter[slot] = 0;\n\t\tm_sMissionAudio.m_bIsMobile[slot] = false;\n\t\tSampleManager.StopStreamedFile(slot + 1);\n\t}\n}\n\nvoid\ncAudioManager::ProcessMissionAudioSlot(uint8 slot)\n{\n\tfloat dist;\n\tuint8 emittingVol;\n\tuint8 pan;\n\tfloat distSquared;\n\tCVector vec;\n\n\tstatic uint8 nCheckPlayingDelay[MISSION_AUDIO_SLOTS] = { 0, 0 };\n\tstatic uint8 nFramesUntilFailedLoad[MISSION_AUDIO_SLOTS] = { 0, 0 };\n\tstatic uint8 nFramesForPretendPlaying[MISSION_AUDIO_SLOTS] = { 0, 0 };\n\n\tif (m_sMissionAudio.m_nSampleIndex[slot] == NO_SAMPLE) return;\n\n\tswitch (m_sMissionAudio.m_nLoadingStatus[slot]) {\n\tcase LOADING_STATUS_NOT_LOADED:\n\t\tSampleManager.PreloadStreamedFile(m_sMissionAudio.m_nSampleIndex[slot], slot + 1);\n\t\tm_sMissionAudio.m_nLoadingStatus[slot] = LOADING_STATUS_LOADED;\n\t\tnFramesUntilFailedLoad[slot] = 0;\n\t\tbreak;\n\tcase LOADING_STATUS_LOADED:\n\t\tif (!m_sMissionAudio.m_bIsPlayed[slot])\n\t\t\treturn;\n\t\tif (g_bMissionAudioLoadFailed[slot]) {\n\t\t\tif (m_bTimerJustReset) {\n\t\t\t\tClearMissionAudio(slot);\n\t\t\t\tSampleManager.StopStreamedFile(slot + 1);\n\t\t\t\tnFramesForPretendPlaying[slot] = 0;\n\t\t\t\tnCheckPlayingDelay[slot] = 0;\n\t\t\t\tnFramesUntilFailedLoad[slot] = 0;\n\t\t\t} else if (!m_nUserPause) {\n\t\t\t\tif (++nFramesForPretendPlaying[slot] < 90) {\n\t\t\t\t\tm_sMissionAudio.m_nPlayStatus[slot] = PLAY_STATUS_PLAYING;\n\t\t\t\t} else {\n\t\t\t\t\tm_sMissionAudio.m_nPlayStatus[slot] = PLAY_STATUS_FINISHED;\n\t\t\t\t\tm_sMissionAudio.m_nSampleIndex[slot] = NO_SAMPLE;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tswitch (m_sMissionAudio.m_nPlayStatus[slot]) {\n\t\tcase PLAY_STATUS_STOPPED:\n\t\t\tif (MissionScriptAudioUsesPoliceChannel(m_sMissionAudio.m_nSampleIndex[slot])) {\n\t\t\t\tSetMissionScriptPoliceAudio(m_sMissionAudio.m_nSampleIndex[slot]);\n\t\t\t} else {\n\t\t\t\tif (m_nUserPause)\n\t\t\t\t\tSampleManager.PauseStream(1, slot + 1);\n\t\t\t\tif (m_sMissionAudio.m_bPredefinedProperties[slot]) {\n\t\t\t\t\tif (m_sMissionAudio.m_nSampleIndex[slot] == STREAMED_SOUND_MISSION_CAMERAL)\n\t\t\t\t\t\tSampleManager.SetStreamedVolumeAndPan(80, 0, 1, slot + 1);\n\t\t\t\t\telse if (m_sMissionAudio.m_nSampleIndex[slot] == STREAMED_SOUND_MISSION_CAMERAR)\n\t\t\t\t\t\tSampleManager.SetStreamedVolumeAndPan(80, 127, 1, slot + 1);\n\t\t\t\t\telse\n\t\t\t\t\t\tSampleManager.SetStreamedVolumeAndPan(80, 63, 1, slot + 1);\n\t\t\t\t} else {\n\t\t\t\t\tdistSquared = GetDistanceSquared(m_sMissionAudio.m_vecPos[slot]);\n\t\t\t\t\tif (distSquared >= SQR(80.0f)) {\n\t\t\t\t\t\temittingVol = 0;\n\t\t\t\t\t\tpan = 63;\n\t\t\t\t\t} else {\n\t\t\t\t\t\temittingVol = 80;\n\t\t\t\t\t\tif (distSquared > 0.0f) {\n\t\t\t\t\t\t\tdist = Sqrt(distSquared);\n\t\t\t\t\t\t\temittingVol = ComputeVolume(80, 80.0f, dist);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tTranslateEntity(&m_sMissionAudio.m_vecPos[slot], &vec);\n\t\t\t\t\t\tpan = ComputePan(80.f, &vec);\n\t\t\t\t\t}\n\t\t\t\t\tSampleManager.SetStreamedVolumeAndPan(emittingVol, pan, 1, slot + 1);\n\t\t\t\t}\n\t\t\t\tSampleManager.StartPreloadedStreamedFile(slot + 1);\n\t\t\t}\n\t\t\tm_sMissionAudio.m_nPlayStatus[slot] = PLAY_STATUS_PLAYING;\n\t\t\tnCheckPlayingDelay[slot] = 30;\n\t\t\tif (m_sMissionAudio.m_nSampleIndex[slot] >= STREAMED_SOUND_MISSION_MOB_01A && m_sMissionAudio.m_nSampleIndex[slot] <= STREAMED_SOUND_MISSION_MOB_99A)\n\t\t\t\tm_sMissionAudio.m_bIsMobile[slot] = true;\n\t\t\tbreak;\n\t\tcase PLAY_STATUS_PLAYING:\n\t\t\tif (m_bTimerJustReset) {\n\t\t\t\tClearMissionAudio(slot);\n\t\t\t\tSampleManager.StopStreamedFile(slot + 1);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (MissionScriptAudioUsesPoliceChannel(m_sMissionAudio.m_nSampleIndex[slot])) {\n\t\t\t\tif (!m_nUserPause) {\n\t\t\t\t\tif (nCheckPlayingDelay[slot]) {\n\t\t\t\t\t\t--nCheckPlayingDelay[slot];\n\t\t\t\t\t} else if (GetMissionScriptPoliceAudioPlayingStatus() == PLAY_STATUS_FINISHED || m_sMissionAudio.m_nMissionAudioCounter[slot]-- == 0) {\n\t\t\t\t\t\tm_sMissionAudio.m_nPlayStatus[slot] = PLAY_STATUS_FINISHED;\n\t\t\t\t\t\tm_sMissionAudio.m_nSampleIndex[slot] = NO_SAMPLE;\n\t\t\t\t\t\tSampleManager.StopStreamedFile(slot + 1);\n\t\t\t\t\t\tm_sMissionAudio.m_nMissionAudioCounter[slot] = 0;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if (m_sMissionAudio.m_bIsPlaying[slot]) {\n\t\t\t\tif (SampleManager.IsStreamPlaying(slot + 1) || m_nUserPause || m_nPreviousUserPause) {\n\t\t\t\t\tif (m_nUserPause)\n\t\t\t\t\t\tSampleManager.PauseStream(1, slot + 1);\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tSampleManager.PauseStream(0, slot + 1);\n\t\t\t\t\t\tif (!m_sMissionAudio.m_bPredefinedProperties[slot]) {\n\t\t\t\t\t\t\tdistSquared = GetDistanceSquared(m_sMissionAudio.m_vecPos[slot]);\n\t\t\t\t\t\t\tif (distSquared >= SQR(80.0f)) {\n\t\t\t\t\t\t\t\temittingVol = 0;\n\t\t\t\t\t\t\t\tpan = 63;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\temittingVol = 127;\n\t\t\t\t\t\t\t\tif (distSquared > 0.0f) {\n\t\t\t\t\t\t\t\t\tdist = Sqrt(distSquared);\n\t\t\t\t\t\t\t\t\temittingVol = ComputeVolume(127, 80.0f, dist);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tTranslateEntity(&m_sMissionAudio.m_vecPos[slot], &vec);\n\t\t\t\t\t\t\t\tpan = ComputePan(80.f, &vec);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tSampleManager.SetStreamedVolumeAndPan(emittingVol, pan, 1, slot + 1);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else if (m_sMissionAudio.m_nSampleIndex[slot] == STREAMED_SOUND_MISSION_ROK2_01) {\n\t\t\t\t\tm_sMissionAudio.m_nPlayStatus[slot] = PLAY_STATUS_STOPPED;\n\t\t\t\t} else {\n\t\t\t\t\tm_sMissionAudio.m_nPlayStatus[slot] = PLAY_STATUS_FINISHED;\n\t\t\t\t\tif (m_sMissionAudio.m_nSampleIndex[slot] >= STREAMED_SOUND_MISSION_MOB_01A && m_sMissionAudio.m_nSampleIndex[slot] <= STREAMED_SOUND_MISSION_MOB_99A)\n\t\t\t\t\t\tm_sMissionAudio.m_bIsMobile[slot] = false;\n\t\t\t\t\tm_sMissionAudio.m_nSampleIndex[slot] = NO_SAMPLE;\n\t\t\t\t\tSampleManager.StopStreamedFile(slot + 1);\n\t\t\t\t\tm_sMissionAudio.m_nMissionAudioCounter[slot] = 0;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (m_nUserPause)\n\t\t\t\t\tbreak;\n\t\t\t\tif (nCheckPlayingDelay[slot]--) {\n\t\t\t\t\tif (!SampleManager.IsStreamPlaying(slot + 1))\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tnCheckPlayingDelay[slot] = 0;\n\t\t\t\t}\n\t\t\t\tm_sMissionAudio.m_bIsPlaying[slot] = true;\n\t\t\t}\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\t\tbreak;\n\tcase LOADING_STATUS_FAILED:\n\t\tif (++nFramesUntilFailedLoad[slot] >= 120) {\n\t\t\tnFramesForPretendPlaying[slot] = 0;\n\t\t\tg_bMissionAudioLoadFailed[slot] = true;\n\t\t\tnFramesUntilFailedLoad[slot] = 0;\n\t\t\tm_sMissionAudio.m_nLoadingStatus[slot] = LOADING_STATUS_LOADED;\n\t\t}\n\t\tbreak;\n\tdefault:\n\t\tbreak;\n\t}\n}\n\nvoid\ncAudioManager::ProcessMissionAudio()\n{\n\tif (!m_bIsInitialised) return;\n\t\n\tfor (int i = 0; i < MISSION_AUDIO_SLOTS; i++)\n\t\tProcessMissionAudioSlot(i);\n\n\tif (m_sMissionAudio.m_bIsMobile[0] || m_sMissionAudio.m_bIsMobile[1])\n\t\tfield_5538 = 64;\n\telse if (field_5538 < 127) {\n\t\tfield_5538 += 5;\n\t\tif (field_5538 > 127)\n\t\t\tfield_5538 = 127;\n\t}\n}\n#pragma endregion All the mission audio stuff\n"
  },
  {
    "path": "src/audio/AudioManager.cpp",
    "content": "#include \"common.h\"\n\n#include \"AudioManager.h\"\n#include \"audio_enums.h\"\n\n#include \"AudioScriptObject.h\"\n#include \"MusicManager.h\"\n#include \"Timer.h\"\n#include \"DMAudio.h\"\n#include \"sampman.h\"\n#include \"Camera.h\"\n#include \"World.h\"\n#include \"ZoneCull.h\"\n\ncAudioManager AudioManager;\n\nconst int channels = ARRAY_SIZE(AudioManager.m_asActiveSamples);\nconst int policeChannel = channels + 1;\nconst int allChannels = channels + 2;\n\n#define SPEED_OF_SOUND 343.f\n#define TIME_SPENT 40\n\ncAudioManager::cAudioManager()\n{\n\tm_bIsInitialised = false;\n\tm_bReverb = true;\n\tfield_6 = 0;\n\tm_fSpeedOfSound = SPEED_OF_SOUND / TIME_SPENT;\n\tm_nTimeSpent = TIME_SPENT;\n\tm_nActiveSamples = NUM_SOUNDS_SAMPLES_SLOTS;\n\tm_nActiveSampleQueue = 1;\n\tClearRequestedQueue();\n\tm_nActiveSampleQueue = 0;\n\tClearRequestedQueue();\n\tClearActiveSamples();\n\tGenerateIntegerRandomNumberTable();\n\tfield_4 = 0;\n\tm_bDynamicAcousticModelingStatus = true;\n\n\tfor (int i = 0; i < NUM_AUDIOENTITIES; i++) {\n\t\tm_asAudioEntities[i].m_bIsUsed = false;\n\t\tm_anAudioEntityIndices[i] = NUM_AUDIOENTITIES;\n\t}\n\tm_nAudioEntitiesTotal = 0;\n\tm_FrameCounter = 0;\n\tm_bFifthFrameFlag = false;\n\tm_bTimerJustReset = false;\n\tm_nTimer = 0;\n}\n\ncAudioManager::~cAudioManager()\n{\n\tif (m_bIsInitialised)\n\t\tTerminate();\n}\n\nvoid\ncAudioManager::Initialise()\n{\n\tif (!m_bIsInitialised) {\n\t\tPreInitialiseGameSpecificSetup();\n\t\tm_bIsInitialised = SampleManager.Initialise();\n\t\tif (m_bIsInitialised) {\n\t\t\tm_nActiveSamples = SampleManager.GetMaximumSupportedChannels();\n\t\t\tif (m_nActiveSamples <= 1) {\n\t\t\t\tTerminate();\n\t\t\t} else {\n\t\t\t\t--m_nActiveSamples;\n\t\t\t\tPostInitialiseGameSpecificSetup();\n\t\t\t\tInitialisePoliceRadioZones();\n\t\t\t\tInitialisePoliceRadio();\n\t\t\t\tMusicManager.Initialise();\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\ncAudioManager::Terminate()\n{\n\tif (m_bIsInitialised) {\n\t\tMusicManager.Terminate();\n\n\t\tfor (uint32 i = 0; i < NUM_AUDIOENTITIES; i++) {\n\t\t\tm_asAudioEntities[i].m_bIsUsed = false;\n\t\t\tm_anAudioEntityIndices[i] = ARRAY_SIZE(m_anAudioEntityIndices);\n\t\t}\n\n\t\tm_nAudioEntitiesTotal = 0;\n\t\tm_sAudioScriptObjectManager.m_nScriptObjectEntityTotal = 0;\n\t\tPreTerminateGameSpecificShutdown();\n\n\t\tfor (uint32 i = 0; i < MAX_SFX_BANKS; i++) {\n\t\t\tif (SampleManager.IsSampleBankLoaded(i))\n\t\t\t\tSampleManager.UnloadSampleBank(i);\n\t\t}\n\n\t\tSampleManager.Terminate();\n\n\t\tm_bIsInitialised = false;\n\t\tPostTerminateGameSpecificShutdown();\n\t}\n}\n\nvoid\ncAudioManager::Service()\n{\n\tGenerateIntegerRandomNumberTable();\n\tif (m_bTimerJustReset) {\n\t\tResetAudioLogicTimers(m_nTimer);\n\t\tMusicManager.ResetTimers(m_nTimer);\n\t\tm_bTimerJustReset = false;\n\t}\n\tif (m_bIsInitialised) {\n\t\tm_nPreviousUserPause = m_nUserPause;\n\t\tm_nUserPause = CTimer::GetIsUserPaused();\n\t\tUpdateReflections();\n\t\tServiceSoundEffects();\n\t\tMusicManager.Service();\n\t}\n}\n\nint32\ncAudioManager::CreateEntity(eAudioType type, void *entity)\n{\n\tif (!m_bIsInitialised)\n\t\treturn AEHANDLE_ERROR_NOAUDIOSYS;\n\tif (!entity)\n\t\treturn AEHANDLE_ERROR_NOENTITY;\n\tif (type >= TOTAL_AUDIO_TYPES)\n\t\treturn AEHANDLE_ERROR_BADAUDIOTYPE;\n\tfor (uint32 i = 0; i < ARRAY_SIZE(m_asAudioEntities); i++) {\n\t\tif (!m_asAudioEntities[i].m_bIsUsed) {\n\t\t\tm_asAudioEntities[i].m_bIsUsed = true;\n\t\t\tm_asAudioEntities[i].m_bStatus = false;\n\t\t\tm_asAudioEntities[i].m_nType = type;\n\t\t\tm_asAudioEntities[i].m_pEntity = entity;\n\t\t\tm_asAudioEntities[i].m_awAudioEvent[0] = SOUND_NO_SOUND;\n\t\t\tm_asAudioEntities[i].m_awAudioEvent[1] = SOUND_NO_SOUND;\n\t\t\tm_asAudioEntities[i].m_awAudioEvent[2] = SOUND_NO_SOUND;\n\t\t\tm_asAudioEntities[i].m_awAudioEvent[3] = SOUND_NO_SOUND;\n\t\t\tm_asAudioEntities[i].m_AudioEvents = 0;\n\t\t\tm_anAudioEntityIndices[m_nAudioEntitiesTotal++] = i;\n\t\t\treturn i;\n\t\t}\n\t}\n\treturn AEHANDLE_ERROR_NOFREESLOT;\n}\n\nvoid\ncAudioManager::DestroyEntity(int32 id)\n{\n\tif (m_bIsInitialised && id >= 0 && id < NUM_AUDIOENTITIES && m_asAudioEntities[id].m_bIsUsed) {\n\t\tm_asAudioEntities[id].m_bIsUsed = false;\n\t\tfor (int32 i = 0; i < m_nAudioEntitiesTotal; ++i) {\n\t\t\tif (id == m_anAudioEntityIndices[i]) {\n\t\t\t\tif (i < NUM_AUDIOENTITIES - 1)\n\t\t\t\t\tmemmove(&m_anAudioEntityIndices[i], &m_anAudioEntityIndices[i + 1], NUM_AUDIOENTITY_EVENTS * (m_nAudioEntitiesTotal - (i + 1)));\n\t\t\t\tm_anAudioEntityIndices[--m_nAudioEntitiesTotal] = NUM_AUDIOENTITIES;\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\ncAudioManager::SetEntityStatus(int32 id, uint8 status)\n{\n\tif (m_bIsInitialised && id >= 0 && id < NUM_AUDIOENTITIES && m_asAudioEntities[id].m_bIsUsed)\n\t\tm_asAudioEntities[id].m_bStatus = status;\n}\n\nvoid\ncAudioManager::PlayOneShot(int32 index, uint16 sound, float vol)\n{\n\tstatic const uint8 OneShotPriority[] = { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 4, 2, 5, 5, 3, 5, 2, 2, 1, 1, 3, 1, 3, 3, 1, 1, 1, 1, 4, 4, 4, 3, 1, 1, 1, 1, 1,\n\t\t\t\t\t\t\t\t\t\t\t1, 1, 1, 1, 1, 1, 1, 1, 6, 1, 1, 1, 1, 1, 1, 3, 4, 2, 0, 0, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0,\n\t\t\t\t\t\t\t\t\t\t\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 3, 1, 1, 1, 9, 0, 0, 0, 1, 2, 2, 0, 0, 2, 3, 3, 3, 5, 1, 1,\n\t\t\t\t\t\t\t\t\t\t\t1, 1, 1, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 4, 7, 1, 4, 3, 4, 2, 2, 2, 3, 1, 2, 1, 3, 5, 3, 4, 6, 4, 6, 3, 0, 0, 0, 0, 0,\n\t\t\t\t\t\t\t\t\t\t\t0, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 3, 1, 1, 2, 1, 1, 0, 0, 0, 0, 0, 3, 3, 1, 0 };\n\n\tif (m_bIsInitialised) {\n\t\tif (index >= 0 && index < NUM_AUDIOENTITIES) {\n\t\t\ttAudioEntity &entity = m_asAudioEntities[index];\n\t\t\tif (entity.m_bIsUsed) {\n\t\t\t\tif (sound < SOUND_TOTAL_SOUNDS) {\n\t\t\t\t\tif (entity.m_nType == AUDIOTYPE_SCRIPTOBJECT) {\n\t\t\t\t\t\tif (m_sAudioScriptObjectManager.m_nScriptObjectEntityTotal < ARRAY_SIZE(m_sAudioScriptObjectManager.m_anScriptObjectEntityIndices)) {\n\t\t\t\t\t\t\tentity.m_awAudioEvent[0] = sound;\n\t\t\t\t\t\t\tentity.m_AudioEvents = 1;\n\t\t\t\t\t\t\tm_sAudioScriptObjectManager.m_anScriptObjectEntityIndices[m_sAudioScriptObjectManager.m_nScriptObjectEntityTotal++] = index;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tint32 i = 0;\n\t\t\t\t\t\twhile (true) {\n\t\t\t\t\t\t\tif (i >= entity.m_AudioEvents) {\n\t\t\t\t\t\t\t\tif (entity.m_AudioEvents < ARRAY_SIZE(entity.m_awAudioEvent)) {\n\t\t\t\t\t\t\t\t\tentity.m_awAudioEvent[i] = sound;\n\t\t\t\t\t\t\t\t\tentity.m_afVolume[i] = vol;\n\t\t\t\t\t\t\t\t\t++entity.m_AudioEvents;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (OneShotPriority[entity.m_awAudioEvent[i]] > OneShotPriority[sound])\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t++i;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (i < NUM_AUDIOENTITY_EVENTS - 1) {\n\t\t\t\t\t\t\tmemmove(&entity.m_awAudioEvent[i + 1], &entity.m_awAudioEvent[i], (NUM_AUDIOENTITY_EVENTS - 1 - i) * NUM_AUDIOENTITY_EVENTS / 2);\n\t\t\t\t\t\t\tmemmove(&entity.m_afVolume[i + 1], &entity.m_afVolume[i], (NUM_AUDIOENTITY_EVENTS - 1 - i) * NUM_AUDIOENTITY_EVENTS);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tentity.m_awAudioEvent[i] = sound;\n\t\t\t\t\t\tentity.m_afVolume[i] = vol;\n\t\t\t\t\t\tif (entity.m_AudioEvents < ARRAY_SIZE(entity.m_awAudioEvent))\n\t\t\t\t\t\t\t++entity.m_AudioEvents;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\ncAudioManager::SetMP3BoostVolume(uint8 volume) const\n{\n\tSampleManager.SetMP3BoostVolume(volume);\n}\n\nvoid\ncAudioManager::SetEffectsMasterVolume(uint8 volume) const\n{\n\tSampleManager.SetEffectsMasterVolume(volume);\n}\n\nvoid\ncAudioManager::SetMusicMasterVolume(uint8 volume) const\n{\n\tSampleManager.SetMusicMasterVolume(volume);\n}\n\nvoid\ncAudioManager::SetEffectsFadeVol(uint8 volume) const\n{\n\tSampleManager.SetEffectsFadeVolume(volume);\n}\n\nvoid\ncAudioManager::SetMonoMode(uint8 mono)\n{\n\tSampleManager.SetMonoMode(mono);\n}\n\nvoid\ncAudioManager::SetMusicFadeVol(uint8 volume) const\n{\n\tSampleManager.SetMusicFadeVolume(volume);\n}\n\nvoid\ncAudioManager::ResetTimers(uint32 time)\n{\n\tif (m_bIsInitialised) {\n\t\tm_bTimerJustReset = true;\n\t\tm_nTimer = time;\n\t\tClearRequestedQueue();\n\t\tif (m_nActiveSampleQueue) {\n\t\t\tm_nActiveSampleQueue = 0;\n\t\t\tClearRequestedQueue();\n\t\t\tm_nActiveSampleQueue = 1;\n\t\t} else {\n\t\t\tm_nActiveSampleQueue = 1;\n\t\t\tClearRequestedQueue();\n\t\t\tm_nActiveSampleQueue = 0;\n\t\t}\n\t\tClearActiveSamples();\n\t\tClearMissionAudio(0);\n\t\tClearMissionAudio(1);\n\t\tSampleManager.StopChannel(policeChannel);\n\t\tSampleManager.SetEffectsFadeVolume(0);\n\t\tSampleManager.SetMusicFadeVolume(0);\n\t\tMusicManager.ResetMusicAfterReload();\n\t\tm_bIsPlayerShutUp = false;\n#ifdef AUDIO_OAL\n\t\tSampleManager.Service();\n#endif\n\t}\n}\n\nvoid\ncAudioManager::DestroyAllGameCreatedEntities()\n{\n\tcAudioScriptObject *entity;\n\n\tif (m_bIsInitialised) {\n\t\tfor (uint32 i = 0; i < ARRAY_SIZE(m_asAudioEntities); i++) {\n\t\t\tif (m_asAudioEntities[i].m_bIsUsed) {\n\t\t\t\tswitch (m_asAudioEntities[i].m_nType) {\n\t\t\t\tcase AUDIOTYPE_PHYSICAL:\n\t\t\t\tcase AUDIOTYPE_EXPLOSION:\n\t\t\t\tcase AUDIOTYPE_WEATHER:\n\t\t\t\t//case AUDIOTYPE_CRANE:\n\t\t\t\tcase AUDIOTYPE_GARAGE:\n\t\t\t\tcase AUDIOTYPE_FIREHYDRANT:\n\t\t\t\t\tDestroyEntity(i);\n\t\t\t\t\tbreak;\n\t\t\t\tcase AUDIOTYPE_SCRIPTOBJECT:\n\t\t\t\t\tentity = (cAudioScriptObject *)m_asAudioEntities[i].m_pEntity;\n\t\t\t\t\tif (entity) {\n\t\t\t\t\t\tdelete entity;\n\t\t\t\t\t\tm_asAudioEntities[i].m_pEntity = nil;\n\t\t\t\t\t}\n\t\t\t\t\tDestroyEntity(i);\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tm_sAudioScriptObjectManager.m_nScriptObjectEntityTotal = 0;\n\t}\n}\n\nuint8\ncAudioManager::GetNum3DProvidersAvailable() const\n{\n\tif (m_bIsInitialised)\n\t\treturn SampleManager.GetNum3DProvidersAvailable();\n\treturn 0;\n}\n\nchar *\ncAudioManager::Get3DProviderName(uint8 id) const\n{\n\tif (!m_bIsInitialised)\n\t\treturn nil;\n#ifdef AUDIO_OAL\n\tid = clamp(id, 0, SampleManager.GetNum3DProvidersAvailable() - 1);\n#else\n\t// We don't want that either since it will crash the game, but skipping for now\n\tif (id >= SampleManager.GetNum3DProvidersAvailable())\n\t\treturn nil;\n#endif\n\treturn SampleManager.Get3DProviderName(id);\n}\n\nint8\ncAudioManager::GetCurrent3DProviderIndex() const\n{\n\tif (m_bIsInitialised)\n\t\treturn SampleManager.GetCurrent3DProviderIndex();\n\n\treturn -1;\n}\n\nint8\ncAudioManager::AutoDetect3DProviders() const\n{\n\tif (m_bIsInitialised)\n\t\treturn SampleManager.AutoDetect3DProviders();\n\n\treturn -1;\n}\n\nint8\ncAudioManager::SetCurrent3DProvider(uint8 which)\n{\n\tif (!m_bIsInitialised)\n\t\treturn -1;\n\tfor (uint8 i = 0; i < m_nActiveSamples + 1; ++i)\n\t\tSampleManager.StopChannel(i);\n\tClearRequestedQueue();\n\tif (m_nActiveSampleQueue == 0)\n\t\tm_nActiveSampleQueue = 1;\n\telse\n\t\tm_nActiveSampleQueue = 0;\n\tClearRequestedQueue();\n\tClearActiveSamples();\n\tint8 current = SampleManager.SetCurrent3DProvider(which);\n\tif (current > 0) {\n\t\tm_nActiveSamples = SampleManager.GetMaximumSupportedChannels();\n\t\tif (m_nActiveSamples > 1)\n\t\t\t--m_nActiveSamples;\n\t}\n\treturn current;\n}\n\nvoid\ncAudioManager::SetSpeakerConfig(int32 conf) const\n{\n\tSampleManager.SetSpeakerConfig(conf);\n}\n\nbool\ncAudioManager::IsMP3RadioChannelAvailable() const\n{\n\tif (m_bIsInitialised)\n\t\treturn SampleManager.IsMP3RadioChannelAvailable();\n\n\treturn false;\n}\n\nvoid\ncAudioManager::ReleaseDigitalHandle() const\n{\n\tif (m_bIsInitialised) {\n\t\tSampleManager.ReleaseDigitalHandle();\n\t}\n}\n\nvoid\ncAudioManager::ReacquireDigitalHandle() const\n{\n\tif (m_bIsInitialised) {\n\t\tSampleManager.ReacquireDigitalHandle();\n\t}\n}\n\nvoid\ncAudioManager::SetDynamicAcousticModelingStatus(uint8 status)\n{\n\tm_bDynamicAcousticModelingStatus = status!=0;\n}\n\nbool\ncAudioManager::CheckForAnAudioFileOnCD() const\n{\n\treturn SampleManager.CheckForAnAudioFileOnCD();\n}\n\nuint8\ncAudioManager::GetCDAudioDriveLetter() const\n{\n\tif(m_bIsInitialised) return SampleManager.GetCDAudioDriveLetter();\n\treturn 0;\n}\n\nbool\ncAudioManager::IsAudioInitialised() const\n{\n\treturn m_bIsInitialised;\n}\n\nvoid\ncAudioManager::ServiceSoundEffects()\n{\n\tm_bFifthFrameFlag = (m_FrameCounter++ % 5) == 0;\n\tif (m_nUserPause && !m_nPreviousUserPause) {\n\t\tfor (int32 i = 0; i < allChannels; i++)\n\t\t\tSampleManager.StopChannel(i);\n\n\t\tClearRequestedQueue();\n\t\tif (m_nActiveSampleQueue) {\n\t\t\tm_nActiveSampleQueue = 0;\n\t\t\tClearRequestedQueue();\n\t\t\tm_nActiveSampleQueue = 1;\n\t\t} else {\n\t\t\tm_nActiveSampleQueue = 1;\n\t\t\tClearRequestedQueue();\n\t\t\tm_nActiveSampleQueue = 0;\n\t\t}\n\t\tClearActiveSamples();\n\t}\n\tm_nActiveSampleQueue = m_nActiveSampleQueue == 1 ? 0 : 1;\n\tif(m_bReverb) ProcessReverb();\n\tProcessSpecial();\n\tClearRequestedQueue();\n\tInterrogateAudioEntities();\n\tm_sPedComments.Process();\n\tServicePoliceRadio();\n\tServiceCollisions();\n\tAddReleasingSounds();\n\tProcessMissionAudio();\n#ifdef GTA_PC\n\tAdjustSamplesVolume();\n#endif\n\tProcessActiveQueues();\n#ifdef AUDIO_OAL\n\tSampleManager.Service();\n#endif\n\tfor (int32 i = 0; i < m_sAudioScriptObjectManager.m_nScriptObjectEntityTotal; ++i) {\n\t\tcAudioScriptObject *object = (cAudioScriptObject *)m_asAudioEntities[m_sAudioScriptObjectManager.m_anScriptObjectEntityIndices[i]].m_pEntity;\n\t\tdelete object;\n\t\tm_asAudioEntities[m_sAudioScriptObjectManager.m_anScriptObjectEntityIndices[i]].m_pEntity = nil;\n\t\tDestroyEntity(m_sAudioScriptObjectManager.m_anScriptObjectEntityIndices[i]);\n\t}\n\tm_sAudioScriptObjectManager.m_nScriptObjectEntityTotal = 0;\n}\n\nuint8\ncAudioManager::ComputeVolume(uint8 emittingVolume, float soundIntensity, float distance) const\n{\n\tfloat newSoundIntensity;\n\tfloat newEmittingVolume;\n\n\tif (soundIntensity <= 0.0f)\n\t\treturn 0;\n\n\tnewSoundIntensity = soundIntensity / 5.0f;\n\tif (newSoundIntensity > distance)\n\t\treturn emittingVolume;\n\n\tnewEmittingVolume = emittingVolume * SQR((soundIntensity - newSoundIntensity - (distance - newSoundIntensity))\n\t\t/ (soundIntensity - newSoundIntensity));\n\treturn Min(127u, newEmittingVolume);\n}\n\nvoid\ncAudioManager::TranslateEntity(Const CVector *in, CVector *out) const\n{\n\t*out = MultiplyInverse(TheCamera.GetMatrix(), *in);\n}\n\nint32\ncAudioManager::ComputePan(float dist, CVector *vec)\n{\n\tconst uint8 PanTable[64] = { 0,  3,  8, 12, 16, 19, 22, 24, 26, 28, 30, 31, 33, 34, 36, 37, 39, 40, 41, 42, 44, 45, 46, 47, 48, 49, 49, 50, 51, 52, 53, 53,\n\t\t\t\t\t\t\t\t54, 55, 55, 56, 56, 57, 57, 58, 58, 58, 59, 59, 59, 60, 60, 61, 61, 61, 61, 62, 62, 62, 62, 62, 63, 63, 63, 63, 63, 63, 63, 63};\n\tint32 index = Min(63, Abs(int32(vec->x / (dist / 64.f))));\n\n\tif (vec->x > 0.f)\n\t\treturn Max(20, 63 - PanTable[index]);\n\treturn Min(107, PanTable[index] + 63);\n}\n\nuint32\ncAudioManager::ComputeDopplerEffectedFrequency(uint32 oldFreq, float position1, float position2, float speedMultiplier) const\n{\n\tuint32 newFreq = oldFreq;\n\tif (!TheCamera.Get_Just_Switched_Status() && speedMultiplier != 0.0f) {\n\t\tfloat dist = position2 - position1;\n\t\tif (dist != 0.0f) {\n\t\t\tfloat speedOfSource = (dist / m_nTimeSpent) * speedMultiplier;\n\t\t\tif (m_fSpeedOfSound > Abs(speedOfSource)) {\n\t\t\t\tspeedOfSource = clamp2(speedOfSource, 0.0f, 1.5f);\n\t\t\t\tnewFreq = (oldFreq * m_fSpeedOfSound) / (speedOfSource + m_fSpeedOfSound);\n\t\t\t}\n\t\t}\n\t}\n\treturn newFreq;\n}\n\nint32\ncAudioManager::RandomDisplacement(uint32 seed) const\n{\n\tint32 value;\n\n\tstatic bool bPos = true;\n\tstatic uint32 Adjustment = 0;\n\n\tif (!seed)\n\t\treturn 0;\n\n\tvalue = m_anRandomTable[(Adjustment + seed) % 5] % seed;\n\tAdjustment += value;\n\n\tif (value % 2) {\n\t\tbPos = !bPos;\n\t}\n\tif (!bPos)\n\t\tvalue = -value;\n\treturn value;\n}\n\nvoid\ncAudioManager::InterrogateAudioEntities()\n{\n\tfor (int32 i = 0; i < m_nAudioEntitiesTotal; i++) {\n\t\tProcessEntity(m_anAudioEntityIndices[i]);\n\t\tm_asAudioEntities[m_anAudioEntityIndices[i]].m_AudioEvents = 0;\n\t}\n}\n\nvoid\ncAudioManager::AddSampleToRequestedQueue()\n{\n\tint32 calculatedVolume;\n\tuint8 sampleIndex;\n\tbool bReflections;\n\n\tif (m_sQueueSample.m_nSampleIndex < TOTAL_AUDIO_SAMPLES) {\n\t\tcalculatedVolume = m_sQueueSample.m_nReleasingVolumeModificator * (MAX_VOLUME - m_sQueueSample.m_nVolume);\n\t\tsampleIndex = m_SampleRequestQueuesStatus[m_nActiveSampleQueue];\n\t\tif (sampleIndex >= m_nActiveSamples) {\n\t\t\tsampleIndex = m_abSampleQueueIndexTable[m_nActiveSampleQueue][m_nActiveSamples - 1];\n\t\t\tif (m_asSamples[m_nActiveSampleQueue][sampleIndex].m_nCalculatedVolume <= calculatedVolume)\n\t\t\t\treturn;\n\t\t} else {\n\t\t\t++m_SampleRequestQueuesStatus[m_nActiveSampleQueue];\n\t\t}\n\t\tm_sQueueSample.m_nCalculatedVolume = calculatedVolume;\n\t\tm_sQueueSample.m_bLoopEnded = false;\n\t\tif (m_sQueueSample.m_bIs2D || CCullZones::InRoomForAudio()) {\n\t\t\tm_sQueueSample.m_bRequireReflection = false;\n\t\t\tm_sQueueSample.m_nLoopsRemaining = 0;\n\t\t}\n\t\tif (m_bDynamicAcousticModelingStatus && m_sQueueSample.m_nLoopCount) {\n\t\t\tbReflections = m_sQueueSample.m_bRequireReflection;\n\t\t} else {\n\t\t\tbReflections = false;\n\t\t\tm_sQueueSample.m_nLoopsRemaining = 0;\n\t\t}\n\t\tm_sQueueSample.m_bRequireReflection = false;\n\n\t\tif ( m_bReverb && m_sQueueSample.m_bIs2D )\n\t\t\tm_sQueueSample.field_4C = 30;\n\n\t\tif (!m_bDynamicAcousticModelingStatus)\n\t\t\tm_sQueueSample.m_bReverbFlag = false;\n\n\t\tm_asSamples[m_nActiveSampleQueue][sampleIndex] = m_sQueueSample;\n\n\t\tAddDetailsToRequestedOrderList(sampleIndex);\n\t\tif (bReflections)\n\t\t\tAddReflectionsToRequestedQueue();\n\t}\n}\nvoid\ncAudioManager::AddDetailsToRequestedOrderList(uint8 sample)\n{\n\tuint32 i = 0;\n\tif (sample != 0) {\n\t\tfor (; i < sample; i++) {\n\t\t\tif (m_asSamples[m_nActiveSampleQueue][m_abSampleQueueIndexTable[m_nActiveSampleQueue][i]].m_nCalculatedVolume >\n\t\t\t    m_asSamples[m_nActiveSampleQueue][sample].m_nCalculatedVolume)\n\t\t\t\tbreak;\n\t\t}\n\t\tif (i < sample) {\n\t\t\tmemmove(&m_abSampleQueueIndexTable[m_nActiveSampleQueue][i + 1], &m_abSampleQueueIndexTable[m_nActiveSampleQueue][i], m_nActiveSamples - i - 1);\n\t\t}\n\t}\n\tm_abSampleQueueIndexTable[m_nActiveSampleQueue][i] = sample;\n}\n\nvoid\ncAudioManager::AddReflectionsToRequestedQueue()\n{\n#ifdef FIX_BUGS\n  \tuint32 oldFreq = 0;\n#else\n  \tuint32 oldFreq;\n#endif\n\tfloat reflectionDistance;\n\tint32 noise;\n\tuint8 emittingVolume;\n\n\tuint32 oldCounter = m_sQueueSample.m_nCounter;\n\tfloat oldDist = m_sQueueSample.m_fDistance;\n\tCVector oldPos = m_sQueueSample.m_vecPos;\n\tif ( CTimer::GetIsSlowMotionActive() ) {\n\t\temittingVolume = m_sQueueSample.m_nVolume;\n\t\toldFreq = m_sQueueSample.m_nFrequency;\n\t} else {\n\t\temittingVolume = (9 * m_sQueueSample.m_nVolume) / 16;\n\t}\n\tm_sQueueSample.m_fSoundIntensity /= 2.f;\n\n\tint halfOldFreq = oldFreq >> 1;\n\n\tfor (uint32 i = 0; i < ARRAY_SIZE(m_afReflectionsDistances); i++) {\n\t\tif ( CTimer::GetIsSlowMotionActive() )\n\t\t\tm_afReflectionsDistances[i] = GetRandomNumberInRange(i % 4, 0, 2) * 100.f / 8.f;\n\n\t\treflectionDistance = m_afReflectionsDistances[i];\n\t\tif (reflectionDistance > 0.0f && reflectionDistance < 100.f && reflectionDistance < m_sQueueSample.m_fSoundIntensity) {\n\t\t\tm_sQueueSample.m_nLoopsRemaining = CTimer::GetIsSlowMotionActive() ? (reflectionDistance * 800.f / 1029.f) : (reflectionDistance * 500.f / 1029.f);\n\t\t\tif (m_sQueueSample.m_nLoopsRemaining > 3) {\n\t\t\t\tm_sQueueSample.m_fDistance = m_afReflectionsDistances[i];\n\t\t\t\tm_sQueueSample.m_nEmittingVolume = emittingVolume;\n\t\t\t\tm_sQueueSample.m_nVolume = ComputeVolume(emittingVolume, m_sQueueSample.m_fSoundIntensity, m_sQueueSample.m_fDistance);\n\n\t\t\t\tif (m_sQueueSample.m_nVolume > emittingVolume / 16) {\n\t\t\t\t\tm_sQueueSample.m_nCounter = oldCounter + (i + 1) * 256;\n\t\t\t\t\tif (m_sQueueSample.m_nLoopCount) {\n\t\t\t\t\t\tif ( CTimer::GetIsSlowMotionActive() ) {\n\t\t\t\t\t\t\tm_sQueueSample.m_nFrequency = halfOldFreq + ((halfOldFreq * i) / ARRAY_SIZE(m_afReflectionsDistances));\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tnoise = RandomDisplacement(m_sQueueSample.m_nFrequency / 32);\n\t\t\t\t\t\t\tif (noise <= 0)\n\t\t\t\t\t\t\t\tm_sQueueSample.m_nFrequency += noise;\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\tm_sQueueSample.m_nFrequency -= noise;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tm_sQueueSample.m_nReleasingVolumeModificator += 20;\n\t\t\t\t\tm_sQueueSample.m_vecPos = m_avecReflectionsPos[i];\n\t\t\t\t\tAddSampleToRequestedQueue();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tm_sQueueSample.m_vecPos = oldPos;\n\tm_sQueueSample.m_fDistance = oldDist;\n}\n\nvoid\ncAudioManager::UpdateReflections()\n{\n\tCVector camPos = TheCamera.GetPosition();\n\tCColPoint colpoint;\n\tCEntity *ent;\n\n\tif (m_FrameCounter % 8 == 0) {\n\t\tm_avecReflectionsPos[0] = camPos;\n\t\tm_avecReflectionsPos[0].y += 100.f;\n\t\tif (CWorld::ProcessLineOfSight(camPos, m_avecReflectionsPos[0], colpoint, ent, true, false, false, true, false, true, true))\n\t\t\tm_afReflectionsDistances[0] = Distance(camPos, colpoint.point);\n\t\telse\n\t\t\tm_afReflectionsDistances[0] = 100.0f;\n\n\t} else if ((m_FrameCounter + 1) % 8 == 0) {\n\t\tm_avecReflectionsPos[1] = camPos;\n\t\tm_avecReflectionsPos[1].y -= 100.0f;\n\t\tif (CWorld::ProcessLineOfSight(camPos, m_avecReflectionsPos[1], colpoint, ent, true, false, false, true, false, true, true))\n\t\t\tm_afReflectionsDistances[1] = Distance(camPos, colpoint.point);\n\t\telse\n\t\t\tm_afReflectionsDistances[1] = 100.0f;\n\n\t} else if ((m_FrameCounter + 2) % 8 == 0) {\n\t\tm_avecReflectionsPos[2] = camPos;\n\t\tm_avecReflectionsPos[2].x -= 100.0f;\n\t\tif (CWorld::ProcessLineOfSight(camPos, m_avecReflectionsPos[2], colpoint, ent, true, false, false, true, false, true, true))\n\t\t\tm_afReflectionsDistances[2] = Distance(camPos, colpoint.point);\n\t\telse\n\t\t\tm_afReflectionsDistances[2] = 100.0f;\n\n\t} else if ((m_FrameCounter + 3) % 8 == 0) {\n\t\tm_avecReflectionsPos[3] = camPos;\n\t\tm_avecReflectionsPos[3].x += 100.0f;\n\t\tif (CWorld::ProcessLineOfSight(camPos, m_avecReflectionsPos[3], colpoint, ent, true, false, false, true, false, true, true))\n\t\t\tm_afReflectionsDistances[3] = Distance(camPos, colpoint.point);\n\t\telse\n\t\t\tm_afReflectionsDistances[3] = 100.0f;\n\n\t} else if ((m_FrameCounter + 4) % 8 == 0) {\n\t\tcamPos.y += 1.0f;\n\t\tm_avecReflectionsPos[4] = camPos;\n\t\tm_avecReflectionsPos[4].z += 100.0f;\n\t\tif (CWorld::ProcessVerticalLine(camPos, m_avecReflectionsPos[4].z, colpoint, ent, true, false, false, false, true, false, nil))\n\t\t\tm_afReflectionsDistances[4] = colpoint.point.z - camPos.z;\n\t\telse\n\t\t\tm_afReflectionsDistances[4] = 100.0f;\n\n\t} else if ((m_FrameCounter + 5) % 8 == 0) {\n\t\tcamPos.y -= 1.0f;\n\t\tm_avecReflectionsPos[5] = camPos;\n\t\tm_avecReflectionsPos[5].z += 100.0f;\n\t\tif (CWorld::ProcessVerticalLine(camPos, m_avecReflectionsPos[5].z, colpoint, ent, true, false, false, false, true, false, nil))\n\t\t\tm_afReflectionsDistances[5] = colpoint.point.z - camPos.z;\n\t\telse\n\t\t\tm_afReflectionsDistances[5] = 100.0f;\n\n\t} else if ((m_FrameCounter + 6) % 8 == 0) {\n\t\tcamPos.x -= 1.0f;\n\t\tm_avecReflectionsPos[6] = camPos;\n\t\tm_avecReflectionsPos[6].z += 100.0f;\n\t\tif (CWorld::ProcessVerticalLine(camPos, m_avecReflectionsPos[6].z, colpoint, ent, true, false, false, false, true, false, nil))\n\t\t\tm_afReflectionsDistances[6] = colpoint.point.z - camPos.z;\n\t\telse\n\t\t\tm_afReflectionsDistances[6] = 100.0f;\n\n\t} else if ((m_FrameCounter + 7) % 8 == 0) {\n\t\tcamPos.x += 1.0f;\n\t\tm_avecReflectionsPos[7] = camPos;\n\t\tm_avecReflectionsPos[7].z += 100.0f;\n\t\tif (CWorld::ProcessVerticalLine(camPos, m_avecReflectionsPos[7].z, colpoint, ent, true, false, false, false, true, false, nil))\n\t\t\tm_afReflectionsDistances[7] = colpoint.point.z - camPos.z;\n\t\telse\n\t\t\tm_afReflectionsDistances[7] = 100.0f;\n\t}\n}\n\nvoid\ncAudioManager::AddReleasingSounds()\n{\n\tbool toProcess[44]; // why not 27?\n\n\tint8 queue = m_nActiveSampleQueue == 0 ? 1 : 0;\n\n\tfor (int32 i = 0; i < m_SampleRequestQueuesStatus[queue]; i++) {\n\t\ttSound &sample = m_asSamples[queue][m_abSampleQueueIndexTable[queue][i]];\n\t\tif (sample.m_bLoopEnded)\n\t\t\tcontinue;\n\n\t\ttoProcess[i] = false;\n\t\tfor (int32 j = 0; j < m_SampleRequestQueuesStatus[m_nActiveSampleQueue]; j++) {\n\t\t\tif (sample.m_nEntityIndex == m_asSamples[m_nActiveSampleQueue][m_abSampleQueueIndexTable[m_nActiveSampleQueue][j]].m_nEntityIndex &&\n\t\t\t    sample.m_nCounter == m_asSamples[m_nActiveSampleQueue][m_abSampleQueueIndexTable[m_nActiveSampleQueue][j]].m_nCounter) {\n\t\t\t\ttoProcess[i] = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (!toProcess[i]) {\n\t\t\tif (sample.m_nCounter <= 255 || !sample.m_nLoopsRemaining) {\n\t\t\t\tif (!sample.m_nReleasingVolumeDivider)\n\t\t\t\t\tcontinue;\n\t\t\t\tif (!sample.m_nLoopCount) {\n\t\t\t\t\tif (sample.m_nVolumeChange == -1) {\n\t\t\t\t\t\tsample.m_nVolumeChange = sample.m_nVolume / sample.m_nReleasingVolumeDivider;\n\t\t\t\t\t\tif (sample.m_nVolumeChange <= 0)\n\t\t\t\t\t\t\tsample.m_nVolumeChange = 1;\n\t\t\t\t\t}\n\t\t\t\t\tif (sample.m_nVolume <= sample.m_nVolumeChange) {\n\t\t\t\t\t\tsample.m_nReleasingVolumeDivider = 0;\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tsample.m_nVolume -= sample.m_nVolumeChange;\n\t\t\t\t}\n\t\t\t\t--sample.m_nReleasingVolumeDivider;\n\t\t\t\tif (m_bFifthFrameFlag) {\n\t\t\t\t\tif (sample.m_nReleasingVolumeModificator < 20)\n\t\t\t\t\t\t++sample.m_nReleasingVolumeModificator;\n\t\t\t\t}\n\t\t\t\tsample.m_bReleasingSoundFlag = false;\n\t\t\t}\n\t\t\tmemcpy(&m_sQueueSample, &sample, sizeof(tSound));\n\t\t\tAddSampleToRequestedQueue();\n\t\t}\n\t}\n}\n\nvoid\ncAudioManager::ProcessActiveQueues()\n{\n\tCVector position;\n\tuint32 freqDivided;\n\tuint32 loopCount;\n\tuint8 emittingVol;\n\tuint8 vol;\n\tuint8 offset;\n\tfloat x;\n\tbool flag;\n\tbool missionState;\n\n\tfor (int32 i = 0; i < m_nActiveSamples; i++) {\n\t\tm_asSamples[m_nActiveSampleQueue][i].m_bIsProcessed = false;\n\t\tm_asActiveSamples[i].m_bIsProcessed = false;\n\t}\n\tfor (int32 i = 0; i < m_SampleRequestQueuesStatus[m_nActiveSampleQueue]; i++) {\n\t\ttSound& sample = m_asSamples[m_nActiveSampleQueue][m_abSampleQueueIndexTable[m_nActiveSampleQueue][i]];\n\t\tif (sample.m_nSampleIndex != NO_SAMPLE) {\n\t\t\tfor (int32 j = 0; j < m_nActiveSamples; j++) {\n\t\t\t\tif (sample.m_nEntityIndex == m_asActiveSamples[j].m_nEntityIndex && \n\t\t\t\t\tsample.m_nCounter == m_asActiveSamples[j].m_nCounter &&\n\t\t\t\t\tsample.m_nSampleIndex == m_asActiveSamples[j].m_nSampleIndex) {\n\t\t\t\t\tif (sample.m_nLoopCount) {\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (m_FrameCounter & 1) {\n\t\t\t\t\t\t\tif (!(j & 1)) {\n\t\t\t\t\t\t\t\tflag = false;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tflag = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if (j & 1) {\n\t\t\t\t\t\t\tflag = false;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tflag = true;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (flag && !SampleManager.GetChannelUsedFlag(j)) {\n\t\t\t\t\t\t\tsample.m_bLoopEnded = true;\n\t\t\t\t\t\t\tm_asActiveSamples[j].m_bLoopEnded = true;\n\t\t\t\t\t\t\tm_asActiveSamples[j].m_nSampleIndex = NO_SAMPLE;\n\t\t\t\t\t\t\tm_asActiveSamples[j].m_nEntityIndex = AEHANDLE_NONE;\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!sample.m_nReleasingVolumeDivider)\n\t\t\t\t\t\t\tsample.m_nReleasingVolumeDivider = 1;\n\t\t\t\t\t}\n\t\t\t\t\tsample.m_bIsProcessed = true;\n\t\t\t\t\tm_asActiveSamples[j].m_bIsProcessed = true;\n\t\t\t\t\tsample.m_nVolumeChange = -1;\n\t\t\t\t\tif (!sample.m_bReleasingSoundFlag) {\n\t\t\t\t\t\tif (sample.m_bIs2D) {\n\t\t\t\t\t\t\tif (field_4) {\n\t\t\t\t\t\t\t\temittingVol = 2 * Min(63, sample.m_nEmittingVolume);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\temittingVol = sample.m_nEmittingVolume;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tSampleManager.SetChannelFrequency(j, sample.m_nFrequency);\n\t\t\t\t\t\t\tSampleManager.SetChannelEmittingVolume(j, emittingVol);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tm_asActiveSamples[j].m_fDistance = sample.m_fDistance;\n\t\t\t\t\t\t\tsample.m_nFrequency = ComputeDopplerEffectedFrequency(\n\t\t\t\t\t\t\t\tsample.m_nFrequency,\n\t\t\t\t\t\t\t\tm_asActiveSamples[j].m_fDistance,\n\t\t\t\t\t\t\t\tsample.m_fDistance,\n\t\t\t\t\t\t\t\tsample.m_fSpeedMultiplier);\n\n\t\t\t\t\t\t\tif (sample.m_nFrequency != m_asActiveSamples[j].m_nFrequency) {\n\t\t\t\t\t\t\t\tm_asActiveSamples[j].m_nFrequency = clamp2((int32)sample.m_nFrequency, (int32)m_asActiveSamples[j].m_nFrequency, 6000);\n\t\t\t\t\t\t\t\tSampleManager.SetChannelFrequency(j, m_asActiveSamples[j].m_nFrequency);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (sample.m_nEmittingVolume != m_asActiveSamples[j].m_nEmittingVolume) {\n\t\t\t\t\t\t\t\tvol = clamp2((int8)sample.m_nEmittingVolume, (int8)m_asActiveSamples[j].m_nEmittingVolume, 10);\n\n\t\t\t\t\t\t\t\tif (field_4) {\n\t\t\t\t\t\t\t\t\temittingVol = 2 * Min(63, vol);\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\temittingVol = vol;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tmissionState = false;\n\t\t\t\t\t\t\t\tfor (int32 k = 0; k < ARRAY_SIZE(m_sMissionAudio.m_bIsMobile); k++) {\n\t\t\t\t\t\t\t\t\tif (m_sMissionAudio.m_bIsMobile[k]) {\n\t\t\t\t\t\t\t\t\t\tmissionState = true;\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (missionState) {\n\t\t\t\t\t\t\t\t\temittingVol = (emittingVol * field_5538) / 127;\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tif (field_5538 < 127)\n\t\t\t\t\t\t\t\t\t\temittingVol = (emittingVol * field_5538) / 127;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tSampleManager.SetChannelEmittingVolume(j, emittingVol);\n\t\t\t\t\t\t\t\tm_asActiveSamples[j].m_nEmittingVolume = vol;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tTranslateEntity(&sample.m_vecPos, &position);\n\t\t\t\t\t\t\tSampleManager.SetChannel3DPosition(j, position.x, position.y, position.z);\n\t\t\t\t\t\t\tSampleManager.SetChannel3DDistances(j, sample.m_fSoundIntensity, 0.25f * sample.m_fSoundIntensity);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tSampleManager.SetChannelReverbFlag(j, sample.m_bReverbFlag);\n\t\t\t\t\t\tbreak; //continue for i\n\t\t\t\t\t}\n\t\t\t\t\tsample.m_bIsProcessed = false;\n\t\t\t\t\tm_asActiveSamples[j].m_bIsProcessed = false;\n\t\t\t\t\t//continue for j\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tfor (int32 i = 0; i < m_nActiveSamples; i++) {\n\t\tif (m_asActiveSamples[i].m_nSampleIndex != NO_SAMPLE && !m_asActiveSamples[i].m_bIsProcessed) {\n\t\t\tSampleManager.StopChannel(i);\n\t\t\tm_asActiveSamples[i].m_nSampleIndex = NO_SAMPLE;\n\t\t\tm_asActiveSamples[i].m_nEntityIndex = AEHANDLE_NONE;\n\t\t}\n\t}\n\tfor (uint8 i = 0; i < m_SampleRequestQueuesStatus[m_nActiveSampleQueue]; i++) {\n\t\ttSound& sample = m_asSamples[m_nActiveSampleQueue][m_abSampleQueueIndexTable[m_nActiveSampleQueue][i]];\n\t\tif (!sample.m_bIsProcessed && !sample.m_bLoopEnded &&\n\t\t\tm_asAudioEntities[sample.m_nEntityIndex].m_bIsUsed && sample.m_nSampleIndex < NO_SAMPLE) {\n\t\t\tif (sample.m_nCounter > 255 && sample.m_nLoopCount && sample.m_nLoopsRemaining) {\n\t\t\t\tsample.m_nLoopsRemaining--;\n\t\t\t\tsample.m_nReleasingVolumeDivider = 1;\n\t\t\t} else {\n\t\t\t\tfor (uint8 j = 0; j < m_nActiveSamples; j++) {\n\t\t\t\t\tuint8 k = (j + field_6) % m_nActiveSamples;\n\t\t\t\t\tif (!m_asActiveSamples[k].m_bIsProcessed) {\n\t\t\t\t\t\tif (sample.m_nLoopCount != 0) {\n\t\t\t\t\t\t\tfreqDivided = sample.m_nFrequency / m_nTimeSpent;\n\t\t\t\t\t\t\tloopCount = sample.m_nLoopCount * SampleManager.GetSampleLength(sample.m_nSampleIndex);\n\t\t\t\t\t\t\tif (freqDivided == 0)\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\tsample.m_nReleasingVolumeDivider = loopCount / freqDivided + 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tmemcpy(&m_asActiveSamples[k], &sample, sizeof(tSound));\n\t\t\t\t\t\tif (!m_asActiveSamples[k].m_bIs2D)\n\t\t\t\t\t\t\tTranslateEntity(&m_asActiveSamples[k].m_vecPos, &position);\n\t\t\t\t\t\tif (field_4) {\n\t\t\t\t\t\t\temittingVol = 2 * Min(63, m_asActiveSamples[k].m_nEmittingVolume);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\temittingVol = m_asActiveSamples[k].m_nEmittingVolume;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (SampleManager.InitialiseChannel(k, m_asActiveSamples[k].m_nSampleIndex, m_asActiveSamples[k].m_nBankIndex)) {\n\t\t\t\t\t\t\tSampleManager.SetChannelFrequency(k, m_asActiveSamples[k].m_nFrequency);\n\t\t\t\t\t\t\tbool isMobile = false;\n\t\t\t\t\t\t\tfor (int32 l = 0; l < ARRAY_SIZE(m_sMissionAudio.m_bIsMobile); l++) {\n\t\t\t\t\t\t\t\tif (m_sMissionAudio.m_bIsMobile[l]) {\n\t\t\t\t\t\t\t\t\tisMobile = true;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (!isMobile || m_asActiveSamples[k].m_bIs2D) {\n\t\t\t\t\t\t\t\tif (field_5538 < 127)\n\t\t\t\t\t\t\t\t\temittingVol *= field_5538 / 127;\n\t\t\t\t\t\t\t\tvol = emittingVol;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tvol = (emittingVol * field_5538 / 127);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tSampleManager.SetChannelEmittingVolume(k, vol);\n\t\t\t\t\t\t\tSampleManager.SetChannelLoopPoints(k, m_asActiveSamples[k].m_nLoopStart, m_asActiveSamples[k].m_nLoopEnd);\n\t\t\t\t\t\t\tSampleManager.SetChannelLoopCount(k, m_asActiveSamples[k].m_nLoopCount);\n\t\t\t\t\t\t\tSampleManager.SetChannelReverbFlag(k, m_asActiveSamples[k].m_bReverbFlag);\n\t\t\t\t\t\t\tif (m_asActiveSamples[k].m_bIs2D) {\n\t\t\t\t\t\t\t\toffset = m_asActiveSamples[k].m_nOffset;\n\t\t\t\t\t\t\t\tif (offset == 63) {\n\t\t\t\t\t\t\t\t\tx = 0.0f;\n\t\t\t\t\t\t\t\t} else if (offset >= 63) {\n\t\t\t\t\t\t\t\t\tx = (offset - 63) * 1000.0f / 63;\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tx = -(63 - offset) * 1000.0f / 63; //same like line below\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tposition = CVector(x, 0.0f, 0.0f);\n\t\t\t\t\t\t\t\tm_asActiveSamples[k].m_fSoundIntensity = 100000.0f;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tSampleManager.SetChannel3DPosition(k, position.x, position.y, position.z);\n\t\t\t\t\t\t\tSampleManager.SetChannel3DDistances(k, m_asActiveSamples[k].m_fSoundIntensity, 0.25f * m_asActiveSamples[k].m_fSoundIntensity);\n\t\t\t\t\t\t\tSampleManager.StartChannel(k);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tm_asActiveSamples[k].m_bIsProcessed = true;\n\t\t\t\t\t\tsample.m_bIsProcessed = true;\n\t\t\t\t\t\tsample.m_nVolumeChange = -1;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tfield_6 %= m_nActiveSamples;\n}\n\nvoid\ncAudioManager::ClearRequestedQueue()\n{\n\tfor (int32 i = 0; i < m_nActiveSamples; i++) {\n\t\tm_abSampleQueueIndexTable[m_nActiveSampleQueue][i] = m_nActiveSamples;\n\t}\n\tm_SampleRequestQueuesStatus[m_nActiveSampleQueue] = 0;\n}\n\nvoid\ncAudioManager::ClearActiveSamples()\n{\n\tfor (uint8 i = 0; i < m_nActiveSamples; i++) {\n\t\tm_asActiveSamples[i].m_nEntityIndex = AEHANDLE_NONE;\n\t\tm_asActiveSamples[i].m_nCounter = 0;\n\t\tm_asActiveSamples[i].m_nSampleIndex = NO_SAMPLE;\n\t\tm_asActiveSamples[i].m_nBankIndex = INVALID_SFX_BANK;\n\t\tm_asActiveSamples[i].m_bIs2D = false;\n\t\tm_asActiveSamples[i].m_nReleasingVolumeModificator = 5;\n\t\tm_asActiveSamples[i].m_nFrequency = 0;\n\t\tm_asActiveSamples[i].m_nVolume = 0;\n\t\tm_asActiveSamples[i].m_nEmittingVolume = 0;\n\t\tm_asActiveSamples[i].m_fDistance = 0.0f;\n\t\tm_asActiveSamples[i].m_bIsProcessed = false;\n\t\tm_asActiveSamples[i].m_bLoopEnded = false;\n\t\tm_asActiveSamples[i].m_nLoopCount = 1;\n\t\tm_asActiveSamples[i].m_nLoopStart = 0;\n\t\tm_asActiveSamples[i].m_nLoopEnd = -1;\n\t\tm_asActiveSamples[i].m_fSpeedMultiplier = 0.0f;\n\t\tm_asActiveSamples[i].m_fSoundIntensity = 200.0f;\n\t\tm_asActiveSamples[i].m_nOffset = 63;\n\t\tm_asActiveSamples[i].m_bReleasingSoundFlag = false;\n\t\tm_asActiveSamples[i].m_nCalculatedVolume = 0;\n\t\tm_asActiveSamples[i].m_nReleasingVolumeDivider = 0;\n\t\tm_asActiveSamples[i].m_nVolumeChange = -1;\n\t\tm_asActiveSamples[i].m_vecPos = CVector(0.0f, 0.0f, 0.0f);\n\t\tm_asActiveSamples[i].m_bReverbFlag = false;\n\t\tm_asActiveSamples[i].m_nLoopsRemaining = 0;\n\t\tm_asActiveSamples[i].m_bRequireReflection = false;\n\t}\n}\n\nvoid\ncAudioManager::GenerateIntegerRandomNumberTable()\n{\n\tfor (int32 i = 0; i < ARRAY_SIZE(m_anRandomTable); i++) {\n\t\tm_anRandomTable[i] = myrand();\n\t}\n}\n\n#ifdef GTA_PC\nvoid\ncAudioManager::AdjustSamplesVolume()\n{\n\tfor (int i = 0; i < m_SampleRequestQueuesStatus[m_nActiveSampleQueue]; i++) {\n\t\ttSound *pSample = &m_asSamples[m_nActiveSampleQueue][m_abSampleQueueIndexTable[m_nActiveSampleQueue][i] + 1];\n\n\t\tif (!pSample->m_bIs2D)\n\t\t\tpSample->m_nEmittingVolume = ComputeEmittingVolume(pSample->m_nEmittingVolume, pSample->m_fSoundIntensity, pSample->m_fDistance);\n\t}\n}\n\nuint8\ncAudioManager::ComputeEmittingVolume(uint8 emittingVolume, float intensity, float dist)\n{\n\tfloat quatIntensity = intensity / 4.0f;\n\tfloat diffIntensity = intensity - quatIntensity;\n\tif (dist > diffIntensity)\n\t\treturn (quatIntensity - (dist - diffIntensity)) * (float)emittingVolume / quatIntensity;\n\treturn emittingVolume;\n}\n#endif\n"
  },
  {
    "path": "src/audio/AudioManager.h",
    "content": "#pragma once\n\n#include \"audio_enums.h\"\n#include \"AudioCollision.h\"\n#include \"PoliceRadio.h\"\n#include \"VehicleModelInfo.h\"\n#include \"Vehicle.h\"\n\nclass tSound\n{\npublic:\n\tint32 m_nEntityIndex;\n\tint32 m_nCounter;\n\tint32 m_nSampleIndex;\n\tuint8 m_nBankIndex;\n\tbool m_bIs2D;\n\tint32 m_nReleasingVolumeModificator;\n\tuint32 m_nFrequency;\n\tuint8 m_nVolume;\n\tfloat m_fDistance;\n\tint32 m_nLoopCount;\n\tint32 m_nLoopStart;\n\tint32 m_nLoopEnd;\n\tuint8 m_nEmittingVolume;\n\tfloat m_fSpeedMultiplier;\n\tfloat m_fSoundIntensity;\n\tbool m_bReleasingSoundFlag;\n\tCVector m_vecPos;\n\tbool m_bReverbFlag;\n\tuint8 m_nLoopsRemaining;\n\tbool m_bRequireReflection; // Used for oneshots\n\tuint8 m_nOffset;\n\tuint8 field_4C;\n\tint32 m_nReleasingVolumeDivider;\n\tbool m_bIsProcessed;\n\tbool m_bLoopEnded;\n\tint32 m_nCalculatedVolume;\n\tint8 m_nVolumeChange;\n};\n\nVALIDATE_SIZE(tSound, 96);\n\nclass CPhysical;\nclass CAutomobile;\n\nclass tAudioEntity\n{\npublic:\n\teAudioType m_nType;\n\tvoid *m_pEntity;\n\tbool m_bIsUsed;\n\tuint8 m_bStatus;\n\tint16 m_awAudioEvent[NUM_AUDIOENTITY_EVENTS];\n\tfloat m_afVolume[NUM_AUDIOENTITY_EVENTS];\n\tuint8 m_AudioEvents;\n};\n\nVALIDATE_SIZE(tAudioEntity, 40);\n\nclass tPedComment\n{\npublic:\n\tuint32 m_nSampleIndex;\n\tint32 m_nEntityIndex;\n\tCVector m_vecPos;\n\tfloat m_fDistance;\n\tuint8 m_bVolume;\n\tint8 m_nProcess;\n};\n\nVALIDATE_SIZE(tPedComment, 28);\n\nclass cPedComments\n{\npublic:\n\ttPedComment m_asPedComments[NUM_PED_COMMENTS_BANKS][NUM_PED_COMMENTS_SLOTS];\n\tuint8 m_nIndexMap[NUM_PED_COMMENTS_BANKS][NUM_PED_COMMENTS_SLOTS];\n\tuint8 m_nCommentsInBank[NUM_PED_COMMENTS_BANKS];\n\tuint8 m_nActiveBank;\n#ifdef GTA_PC\n\tbool m_bDelay;\n\tuint32 m_nDelayTimer;\n#endif\n\n\tcPedComments()\n\t{\n\t\tfor (int i = 0; i < NUM_PED_COMMENTS_SLOTS; i++)\n\t\t\tfor (int j = 0; j < NUM_PED_COMMENTS_BANKS; j++) {\n\t\t\t\tm_asPedComments[j][i].m_nProcess = -1;\n\t\t\t\tm_nIndexMap[j][i] = NUM_PED_COMMENTS_SLOTS;\n\t\t\t}\n\n\t\tfor (int i = 0; i < NUM_PED_COMMENTS_BANKS; i++)\n\t\t\tm_nCommentsInBank[i] = 0;\n\t\tm_nActiveBank = 0;\n\t}\n\tvoid Add(tPedComment *com); // done\n\tvoid Process();             // done\n};\n\nVALIDATE_SIZE(cPedComments, 0x490);\n\nclass CEntity;\n\n#define MISSION_AUDIO_SLOTS (2)\n\n// So instead of doing cMissionAudio [2] they've added [2] to every field of the struct...\n// Only someone with a VERY EXTRAORDINARY mind could have come up with that\nclass cMissionAudio\n{\npublic:\n\tCVector m_vecPos[MISSION_AUDIO_SLOTS];\n\tbool m_bPredefinedProperties[MISSION_AUDIO_SLOTS];\n\tint32 m_nSampleIndex[MISSION_AUDIO_SLOTS];\n\tuint8 m_nLoadingStatus[MISSION_AUDIO_SLOTS];\n\tuint8 m_nPlayStatus[MISSION_AUDIO_SLOTS];\n\tbool m_bIsPlaying[MISSION_AUDIO_SLOTS];\n\tint32 m_nMissionAudioCounter[MISSION_AUDIO_SLOTS];\n\tbool m_bIsPlayed[MISSION_AUDIO_SLOTS];\n\tbool m_bIsMobile[MISSION_AUDIO_SLOTS];\n};\nVALIDATE_SIZE(cMissionAudio, 0x38);\n\n// name made up\nclass cAudioScriptObjectManager\n{\npublic:\n\tint32 m_anScriptObjectEntityIndices[NUM_SCRIPT_MAX_ENTITIES];\n\tint32 m_nScriptObjectEntityTotal;\n\n\tcAudioScriptObjectManager() { m_nScriptObjectEntityTotal = 0; }\n\t~cAudioScriptObjectManager() { m_nScriptObjectEntityTotal = 0; }\n};\n\n\nclass cTransmission;\nclass CPlane;\nclass CVehicle;\nclass CPed;\n\nclass cPedParams\n{\npublic:\n\tbool m_bDistanceCalculated;\n\tfloat m_fDistance;\n\tCPed *m_pPed;\n\n\tcPedParams()\n\t{\n\t\tm_bDistanceCalculated = false;\n\t\tm_fDistance = 0.0f;\n\t\tm_pPed = nil;\n\t}\n};\n\nclass cVehicleParams\n{\npublic:\n\tint32 m_VehicleType;\n\tbool m_bDistanceCalculated;\n\tfloat m_fDistance;\n\tCVehicle *m_pVehicle;\n\tcTransmission *m_pTransmission;\n\tint32 m_nIndex;\n\tfloat m_fVelocityChange;\n\n\tcVehicleParams()\n\t{\n\t\tm_VehicleType = -1;\n\t\tm_bDistanceCalculated = false;\n\t\tm_fDistance = 0.0f;\n\t\tm_pVehicle = nil;\n\t\tm_pTransmission = nil;\n\t\tm_nIndex = 0;\n\t\tm_fVelocityChange = 0.0f;\n\t}\n};\n\nVALIDATE_SIZE(cVehicleParams, 0x1C);\n\nenum {\n\tREFLECTION_NORTH = 0,\n\tREFLECTION_SOUTH,\n\tREFLECTION_WEST,\n\tREFLECTION_EAST,\n\tREFLECTION_CEIL_NORTH,\n\tREFLECTION_CEIL_SOUTH,\n\tREFLECTION_CEIL_WEST,\n\tREFLECTION_CEIL_EAST,\n\tMAX_REFLECTIONS,\n};\n\nclass cAudioManager\n{\npublic:\n\tbool m_bIsInitialised;\n\tuint8 m_bReverb; // unused\n\tbool m_bFifthFrameFlag;\n\tuint8 m_nActiveSamples;\n\tuint8 field_4; // unused\n\tbool m_bDynamicAcousticModelingStatus;\n\tint8 field_6;\n\tfloat m_fSpeedOfSound;\n\tbool m_bTimerJustReset;\n\tint32 m_nTimer;\n\ttSound m_sQueueSample;\n\tuint8 m_nActiveSampleQueue;\n\ttSound m_asSamples[NUM_SOUNDS_SAMPLES_BANKS][NUM_SOUNDS_SAMPLES_SLOTS];\n\tuint8 m_abSampleQueueIndexTable[NUM_SOUNDS_SAMPLES_BANKS][NUM_SOUNDS_SAMPLES_SLOTS];\n\tuint8 m_SampleRequestQueuesStatus[NUM_SOUNDS_SAMPLES_BANKS];\n\ttSound m_asActiveSamples[NUM_SOUNDS_SAMPLES_SLOTS];\n\ttAudioEntity m_asAudioEntities[NUM_AUDIOENTITIES];\n\tint32 m_anAudioEntityIndices[NUM_AUDIOENTITIES];\n\tint32 m_nAudioEntitiesTotal;\n\tCVector m_avecReflectionsPos[NUM_AUDIO_REFLECTIONS];\n\tfloat m_afReflectionsDistances[NUM_AUDIO_REFLECTIONS];\n\tcAudioScriptObjectManager m_sAudioScriptObjectManager;\n\n\t// miami\n\tuint8 m_bIsPlayerShutUp;\n\tuint8 m_nPlayerMood;\n\tuint32 m_nPlayerMoodTimer;\n\tuint8 field_rest[4];\n\tbool m_bGenericSfx;\n\n\tcPedComments m_sPedComments;\n\tint32 m_nFireAudioEntity;\n\tint32 m_nWaterCannonEntity;\n\tint32 m_nPoliceChannelEntity;\n\tcPoliceRadioQueue m_sPoliceRadioQueue;\n\tint32 m_nFrontEndEntity;\n\tint32 m_nCollisionEntity;\n\tcAudioCollisionManager m_sCollisionManager;\n\tint32 m_nProjectileEntity;\n#ifdef GTA_BRIDGE\n\tint32 m_nBridgeEntity;\n#endif\n\tint32 m_nEscalatorEntity;\n\tint32 m_nExtraSoundsEntity;\n\tcMissionAudio m_sMissionAudio;\n\tuint8 field_5538; // something related to phone dialogues\n\tint32 m_anRandomTable[5];\n\tuint8 m_nTimeSpent;\n\tuint8 m_nUserPause;\n\tuint8 m_nPreviousUserPause;\n\tuint32 m_FrameCounter;\n\n\tcAudioManager();\n\t~cAudioManager();\n\n\t// getters\n\tuint32 GetFrameCounter() const { return m_FrameCounter; } // done\n\tfloat GetReflectionsDistance(int32 idx) const { return m_afReflectionsDistances[idx]; } // done\n\tint32 GetRandomNumber(int32 idx) const { return m_anRandomTable[idx]; }\n\tint32 GetRandomNumberInRange(int32 idx, int32 low, int32 high) const { return (m_anRandomTable[idx] % (high - low + 1)) + low; }\n\tbool IsMissionAudioSamplePlaying(uint8 slot) const; // { return m_sMissionAudio.m_nPlayStatus == 1; }\n\tbool ShouldDuckMissionAudio(uint8 slot) const;\n\n\t// \"Should\" be in alphabetic order, except \"getXTalkSfx\"\n\tvoid AddDetailsToRequestedOrderList(uint8 sample);                                                                    // done (inlined in vc)\n\tvoid AddPlayerCarSample(uint8 emittingVolume, int32 freq, uint32 sample, uint8 bank, uint8 counter, bool notLooping); // done\n\tvoid AddReflectionsToRequestedQueue();                                                                                // done\n\tvoid AddReleasingSounds();                                                                                            // done\n\tvoid AddSampleToRequestedQueue();                                                                                     // done\n\tvoid AgeCrimes();                                                                                                     // done (inlined in vc)\n\n\tvoid CalculateDistance(bool &condition, float dist);                                                                   // done\n\tbool CheckForAnAudioFileOnCD() const;                                                                                  // done\n\tvoid ClearActiveSamples();                                                                                             // done\n\tvoid ClearMissionAudio(uint8 slot);                                                                                    // done (inlined in vc)\n\tvoid ClearRequestedQueue();                                                                                            // done (inlined in vc)\n\tuint32 ComputeDopplerEffectedFrequency(uint32 oldFreq, float position1, float position2, float speedMultiplier) const; // done\n\tint32 ComputePan(float, CVector *);                                                                                    // done\n\tuint8 ComputeVolume(uint8 emittingVolume, float soundIntensity, float distance) const;                                 // done\n\tint32 CreateEntity(eAudioType type, void *entity);                                                                     // done\n\n\tvoid DestroyAllGameCreatedEntities();                                                                                  // done\n\tvoid DestroyEntity(int32 id);                                                                                          // done (inlined in vc)\n\tvoid DoPoliceRadioCrackle();                                                                                           // done\n\n\t// functions returning talk sfx,\n\t// order from GetPedCommentSfx\n\tuint32 GetPlayerTalkSfx(CPed *ped, int16 sound);\n\tuint32 GetCopTalkSfx(CPed *ped, int16 sound);\n\tuint32 GetSwatTalkSfx(CPed *ped, int16 sound);\n\tuint32 GetFBITalkSfx(CPed *ped, int16 sound);\n\tuint32 GetArmyTalkSfx(CPed *ped, int16 sound);\n\tuint32 GetMedicTalkSfx(CPed *ped, int16 sound);\n\tuint32 GetFiremanTalkSfx(CPed *ped, int16 sound);\n\tuint32 GetDefaultTalkSfx(CPed *ped, int16 sound);\n\tuint32 GetHFYSTTalkSfx(CPed *ped, int16 sound);\n\tuint32 GetHFOSTTalkSfx(CPed *ped, int16 sound);\n\tuint32 GetHMYSTTalkSfx(CPed *ped, int16 sound);\n\tuint32 GetHMOSTTalkSfx(CPed *ped, int16 sound);\n\tuint32 GetHFYRITalkSfx(CPed *ped, int16 sound);\n\tuint32 GetHFORITalkSfx(CPed *ped, int16 sound); \n\tuint32 GetHMYRITalkSfx(CPed *ped, int16 sound); \n\tuint32 GetHMORITalkSfx(CPed *ped, int16 sound);\n\tuint32 GetHFYBETalkSfx(CPed *ped, int16 sound);\n\tuint32 GetHFOBETalkSfx(CPed *ped, int16 sound);\n\tuint32 GetHMYBETalkSfx(CPed *ped, int16 sound);\n\tuint32 GetHMOBETalkSfx(CPed *ped, int16 sound);\n\tuint32 GetHFYBUTalkSfx(CPed *ped, int16 sound);\n\tuint32 GetHFYMDTalkSfx(CPed *ped, int16 sound);\n\tuint32 GetHFYCGTalkSfx(CPed *ped, int16 sound);\n\tuint32 GetHFYPRTalkSfx(CPed *ped, int16 sound);\n\tuint32 GetHFOTRTalkSfx(CPed *ped, int16 sound);\n\tuint32 GetHMOTRTalkSfx(CPed *ped, int16 sound);\n\tuint32 GetHMYAPTalkSfx(CPed *ped, int16 sound);\n\tuint32 GetHMOCATalkSfx(CPed *ped, int16 sound);\n\tuint32 GetBMODKTalkSfx(CPed *ped, int16 sound);\n\tuint32 GetBMYCRTalkSfx(CPed *ped, int16 sound);\n\tuint32 GetBFYSTTalkSfx(CPed *ped, int16 sound);\n\tuint32 GetBFOSTTalkSfx(CPed *ped, int16 sound);\n\tuint32 GetBMYSTTalkSfx(CPed *ped, int16 sound);\n\tuint32 GetBMOSTTalkSfx(CPed *ped, int16 sound);\n\tuint32 GetBFYRITalkSfx(CPed *ped, int16 sound);\n\tuint32 GetBFORITalkSfx(CPed *ped, int16 sound);\n\tuint32 GetBMYRITalkSfx(CPed *ped, int16 sound);\n\tuint32 GetBFYBETalkSfx(CPed *ped, int16 sound);\n\tuint32 GetBMYBETalkSfx(CPed *ped, int16 sound);\n\tuint32 GetBFOBETalkSfx(CPed *ped, int16 sound);\n\tuint32 GetBMOBETalkSfx(CPed *ped, int16 sound);\n\tuint32 GetBMYBUTalkSfx(CPed *ped, int16 sound);\n\tuint32 GetBFYPRTalkSfx(CPed *ped, int16 sound);\n\tuint32 GetBFOTRTalkSfx(CPed *ped, int16 sound);\n\tuint32 GetBMOTRTalkSfx(CPed *ped, int16 sound);\n\tuint32 GetBMYPITalkSfx(CPed *ped, int16 sound);\n\tuint32 GetBMYBBTalkSfx(CPed *ped, int16 sound);\n\tuint32 GetWMYCRTalkSfx(CPed *ped, int16 sound);\n\tuint32 GetWFYSTTalkSfx(CPed *ped, int16 sound);\n\tuint32 GetWFOSTTalkSfx(CPed *ped, int16 sound);\n\tuint32 GetWMYSTTalkSfx(CPed *ped, int16 sound);\n\tuint32 GetWMOSTTalkSfx(CPed *ped, int16 sound);\n\tuint32 GetWFYRITalkSfx(CPed *ped, int16 sound);\n\tuint32 GetWFORITalkSfx(CPed *ped, int16 sound);\n\tuint32 GetWMYRITalkSfx(CPed *ped, int16 sound);\n\tuint32 GetWMORITalkSfx(CPed *ped, int16 sound);\n\tuint32 GetWFYBETalkSfx(CPed *ped, int16 sound);\n\tuint32 GetWMYBETalkSfx(CPed *ped, int16 sound);\n\tuint32 GetWFOBETalkSfx(CPed *ped, int16 sound);\n\tuint32 GetWMOBETalkSfx(CPed *ped, int16 sound);\n\tuint32 GetWMYCWTalkSfx(CPed *ped, int16 sound);\n\tuint32 GetWMYGOTalkSfx(CPed *ped, int16 sound);\n\tuint32 GetWFOGOTalkSfx(CPed *ped, int16 sound);\n\tuint32 GetWMOGOTalkSfx(CPed *ped, int16 sound);\n\tuint32 GetWFYLGTalkSfx(CPed *ped, int16 sound);\n\tuint32 GetWMYLGTalkSfx(CPed *ped, int16 sound);\n\tuint32 GetWFYBUTalkSfx(CPed *ped, int16 sound);\n\tuint32 GetWMYBUTalkSfx(CPed *ped, int16 sound);\n\tuint32 GetWMOBUTalkSfx(CPed *ped, int16 sound);\n\tuint32 GetWFYPRTalkSfx(CPed *ped, int16 sound);\n\tuint32 GetWFOTRTalkSfx(CPed *ped, int16 sound);\n\tuint32 GetWMOTRTalkSfx(CPed *ped, int16 sound);\n\tuint32 GetWMYPITalkSfx(CPed *ped, int16 sound);\n\tuint32 GetWMOCATalkSfx(CPed *ped, int16 sound);\n\tuint32 GetWFYJGTalkSfx(CPed *ped, int16 sound);\n\tuint32 GetWMYJGTalkSfx(CPed *ped, int16 sound);\n\tuint32 GetWFYSKTalkSfx(CPed *ped, int16 sound);\n\tuint32 GetWMYSKTalkSfx(CPed *ped, int16 sound);\n\tuint32 GetWFYSHTalkSfx(CPed *ped, int16 sound);\n\tuint32 GetWFOSHTalkSfx(CPed *ped, int16 sound);\n\tuint32 GetJFOTOTalkSfx(CPed *ped, int16 sound);\n\tuint32 GetJMOTOTalkSfx(CPed *ped, int16 sound);\n\tuint32 GetCBTalkSfx(CPed *ped, int16 sound);\n\tuint32 GetHNTalkSfx(CPed *ped, int16 sound);\n\tuint32 GetSGTalkSfx(CPed *ped, int16 sound);\n\tuint32 GetCLTalkSfx(CPed *ped, int16 sound);\n\tuint32 GetGDTalkSfx(CPed *ped, int16 sound);\n\tuint32 GetBKTalkSfx(CPed *ped, int16 sound);\n\tuint32 GetPGTalkSfx(CPed *ped, int16 sound);\n\tuint32 GetVICETalkSfx(CPed *ped, int16 sound, int16 model);\n\tuint32 GetWFYG1TalkSfx(CPed *ped, int16 sound);\n\tuint32 GetWFYG2TalkSfx(CPed *ped, int16 sound);\n\n\tuint32 GetGenericMaleTalkSfx(CPed *ped, int16 sound);   // todo names (inlined in vc)\n\tuint32 GetGenericFemaleTalkSfx(CPed *ped, int16 sound); // todo names (inlined in vc)\n\t// end of functions returning talk sfx\n\n\tvoid GenerateIntegerRandomNumberTable();                                                   // done\n\tchar *Get3DProviderName(uint8 id) const;                                                   // done\n\tuint8 GetCDAudioDriveLetter() const;                                                       // done\n\tint8 GetCurrent3DProviderIndex() const;                                                    // done\n\tint8 AutoDetect3DProviders() const;                                                        // done\n\tfloat GetCollisionLoopingRatio(uint32 a, uint32 b, float c) const;                         // not used\n\tfloat GetCollisionOneShotRatio(int32 a, float b) const;                                    // done\n\tfloat GetCollisionRatio(float a, float b, float c, float d) const;                         // done (inlined in vc)\n\tfloat GetDistanceSquared(const CVector &v) const;                                          // done (inlined in vc)\n\tint32 GetJumboTaxiFreq() const;                                                            // done (inlined in vc)\n\tuint8 GetMissionAudioLoadingStatus(uint8 slot) const;                                      // done\n\tint8 GetMissionScriptPoliceAudioPlayingStatus() const;                                     // done\n\tuint8 GetNum3DProvidersAvailable() const;                                                  // done\n\tuint32 GetPedCommentSfx(CPed *ped, int32 sound);                                           // done\n\tvoid GetPhrase(uint32 &phrase, uint32 &prevPhrase, uint32 sample, uint32 maxOffset) const; // done\n\tfloat GetVehicleDriveWheelSkidValue(CVehicle *veh, tWheelState wheelState, float gasPedalAudio, cTransmission *transmission,\n\t                                    float velocityChange);                                                                        // done\n\tfloat GetVehicleNonDriveWheelSkidValue(CVehicle *veh, tWheelState wheelState, cTransmission *transmission, float velocityChange); // done\n\n\tbool HasAirBrakes(int32 model) const; // done\n\n\tvoid Initialise();                             // done\n\tvoid InitialisePoliceRadio();                  // done\n\tvoid InitialisePoliceRadioZones();             // done\n\tvoid InterrogateAudioEntities();               // done (inlined)\n\tbool IsAudioInitialised() const;               // done\n\tbool IsMissionAudioSampleFinished(uint8 slot); // done\n\tbool IsMP3RadioChannelAvailable() const;       // done\n\n\tbool MissionScriptAudioUsesPoliceChannel(int32 soundMission) const; //done\n\n\tvoid PlayLoadedMissionAudio(uint8 slot);                // done\n\tvoid PlayOneShot(int32 index, uint16 sound, float vol); // done\n\tvoid PlaySuspectLastSeen(float x, float y, float z);    // done\n\tvoid PlayerJustGotInCar() const;                        // done\n\tvoid PlayerJustLeftCar() const;                         // done\n\tvoid PostInitialiseGameSpecificSetup();                 // done\n\tvoid PostTerminateGameSpecificShutdown();               // done\n\tvoid PreInitialiseGameSpecificSetup() const;            // done\n\tvoid PreloadMissionAudio(uint8 slot, Const char *name); // done\n\tvoid PreTerminateGameSpecificShutdown();                // done\n\t/// processX - main logic of adding new sounds\n\tvoid ProcessActiveQueues();                              // done\n\tbool ProcessAirBrakes(cVehicleParams& params);           // done\n\tbool ProcessBoatEngine(cVehicleParams& params);          \n\tbool ProcessBoatMovingOverWater(cVehicleParams& params); //done \n#ifdef GTA_BRIDGE\n\tvoid ProcessBridge();         // done(bcs not exists in VC)\n\tvoid ProcessBridgeMotor();    // done(bcs not exists in VC)\n\tvoid ProcessBridgeOneShots(); // done(bcs not exists in VC)\n\tvoid ProcessBridgeWarning();  // done(bcs not exists in VC)\n#endif\n\tbool ProcessCarBombTick(cVehicleParams& params);                         // done\n\tvoid ProcessCarHeli(cVehicleParams& params);                             // done\n\tvoid ProcessCesna(cVehicleParams& params);                               // done\n\t//void ProcessCrane();                                                   // done(bcs not exists in VC)\n\tbool ProcessEngineDamage(cVehicleParams& params);                        // done\n\tvoid ProcessEntity(int32 sound);                                         // done\n\tvoid ProcessExplosions(int32 explosion);                                 // done\n\tvoid ProcessFireHydrant();                                               // done\n\tvoid ProcessFires(int32 entity);                                         // done\n\tvoid ProcessFrontEnd();                                                  // done\n\tvoid ProcessGarages();                                                   // done\n\tvoid ProcessJumbo(cVehicleParams& params);                               // done\n\tvoid ProcessJumboAccel(CPlane *plane);                                   // done\n\tvoid ProcessJumboDecel(CPlane *plane);                                   // done\n\tvoid ProcessJumboFlying();                                               // done\n\tvoid ProcessJumboLanding(CPlane *plane);                                 // done\n\tvoid ProcessJumboTakeOff(CPlane *plane);                               \t // done\n\tvoid ProcessJumboTaxi();                                                 // done\n\tvoid ProcessLoopingScriptObject(uint8 sound);                            // done\n\tvoid ProcessMissionAudio();                                              // done\n\tvoid ProcessMissionAudioSlot(uint8 slot);                                // done\n\tvoid ProcessModelHeliVehicle(cVehicleParams& params);                    // done\n\tvoid ProcessModelVehicle(cVehicleParams& params);                        // done\n\tvoid ProcessOneShotScriptObject(uint8 sound);                            // \n\tvoid ProcessPed(CPhysical *ped);                                         // done\n\tvoid ProcessPedOneShots(cPedParams &params);                             // \n\tvoid ProcessPhysical(int32 id);                                          // done\n\tvoid ProcessPlane(cVehicleParams& params);                               // done\n\tvoid ProcessPlayerMood();                                                // done\n\tvoid ProcessPlayersVehicleEngine(cVehicleParams& params, CVehicle* veh); // done\n\tvoid ProcessProjectiles();                                               // done\n\tvoid ProcessRainOnVehicle(cVehicleParams& params);                       // done\n\tvoid ProcessReverb() const;                                              // done\n\tbool ProcessReverseGear(cVehicleParams& params);                         // done\n\tvoid ProcessScriptObject(int32 id);                                      // done\n\tvoid ProcessSpecial();                                                   // done\n#ifdef GTA_TRAIN\n\tbool ProcessTrainNoise(cVehicleParams *params); //done(bcs not exists in VC)\n#endif\n\tvoid ProcessVehicle(CVehicle *vehicle);                    // done\n\tbool ProcessVehicleDoors(cVehicleParams &params);          // done\n\tvoid ProcessVehicleEngine(cVehicleParams &params);         // done\n\tvoid ProcessVehicleFlatTyre(cVehicleParams &params);       // done\n\tbool ProcessVehicleHorn(cVehicleParams &params);           // done\n\tvoid ProcessVehicleOneShots(cVehicleParams &params);       // done\n\tbool ProcessVehicleReverseWarning(cVehicleParams &params); // done\n\tbool ProcessVehicleRoadNoise(cVehicleParams &params);      // done\n\tbool ProcessVehicleSirenOrAlarm(cVehicleParams &params);   // done\n\tbool ProcessVehicleSkidding(cVehicleParams &params);       // done\n\tvoid ProcessWaterCannon(int32);                            // done\n\tvoid ProcessWeather(int32 id);                             // done\n\tbool ProcessWetRoadNoise(cVehicleParams& params);          // done\n\tvoid ProcessEscalators();                                  // done\n\tvoid ProcessExtraSounds();                                 // done\n\n\tint32 RandomDisplacement(uint32 seed) const;                                                                                      // done\n\tvoid ReacquireDigitalHandle() const;                                                                                              // done\n\tvoid ReleaseDigitalHandle() const;                                                                                                // done\n\tvoid ReportCollision(CEntity *entity1, CEntity *entity2, uint8 surface1, uint8 surface2, float collisionPower, float intensity2); // done\n\tvoid ReportCrime(eCrimeType crime, const CVector &pos);                                                                           // done\n\tvoid ResetAudioLogicTimers(uint32 timer);                                                                                         // done\n\tvoid ResetPoliceRadio();                                                                                                          // done\n\tvoid ResetTimers(uint32 time);                                                                                                    // done\n\n\tvoid Service();                                                                             // done\n\tvoid ServiceCollisions();                                                                   // done\n\tvoid ServicePoliceRadio();                                                                  // done\n\tvoid ServicePoliceRadioChannel(uint8 wantedLevel);                                          // done\n\tvoid ServiceSoundEffects();                                                                 // done\n\tint8 SetCurrent3DProvider(uint8 which);                                                     // done\n\tvoid SetDynamicAcousticModelingStatus(uint8 status);                                        // done\n\tvoid SetEffectsFadeVol(uint8 volume) const;                                                 // done\n\tvoid SetEffectsMasterVolume(uint8 volume) const;                                            // done\n\tvoid SetMP3BoostVolume(uint8 volume) const;                                                 // done\n\tvoid SetEntityStatus(int32 id, uint8 status);                                               // done\n\tuint32 SetLoopingCollisionRequestedSfxFreqAndGetVol(const cAudioCollision &audioCollision); // done\n\tvoid SetMissionAudioLocation(uint8 slot, float x, float y, float z);                        // done\n\tvoid SetMissionScriptPoliceAudio(int32 sfx) const;                                          // inlined and optimized\n\tvoid SetMonoMode(uint8 mono);                                                               // done\n\tvoid SetMusicFadeVol(uint8 volume) const;                                                   // done\n\tvoid SetMusicMasterVolume(uint8 volume) const;                                              // done\n\tvoid SetSpeakerConfig(int32 conf) const;                                                    // done\n\tvoid SetUpLoopingCollisionSound(const cAudioCollision &col, uint8 counter);                 // done\n\tvoid SetUpOneShotCollisionSound(const cAudioCollision &col);                                // done\n\tbool SetupCrimeReport();                                                                    // done\n\tbool SetupJumboEngineSound(uint8 vol, uint32 freq);                                         // done\n\tbool SetupJumboFlySound(uint8 emittingVol);                                                 // done\n\tbool SetupJumboRumbleSound(uint8 emittingVol);                                              // done\n\tbool SetupJumboTaxiSound(uint8 vol);                                                        // done\n\tbool SetupJumboWhineSound(uint8 emittingVol, uint32 freq);                                  // done\n\tvoid SetupPedComments(cPedParams &params, uint16 sound);                                    // done\n\tvoid SetupSuspectLastSeenReport();\n\n\tvoid Terminate();                                           // done\n\tvoid TranslateEntity(Const CVector *v1, CVector *v2) const; // done\n\n\tvoid UpdateGasPedalAudio(CVehicle *veh, int vehType);  // done\n\tvoid UpdateReflections();                              // done\n\tbool UsesReverseWarning(int32 model) const;            // done\n\tbool UsesSiren(cVehicleParams &params) const;          // done\n\tbool UsesSirenSwitching(cVehicleParams &params) const; // done\n\n\tCVehicle *FindVehicleOfPlayer();                   // done\n\tvoid SetPedTalkingStatus(CPed *ped, uint8 status); // done\n\tvoid SetPlayersMood(uint8 mood, uint32 time);      // done\n\n\tfloat Sqrt(float v) const { return v <= 0.0f ? 0.0f : ::Sqrt(v); }\n\n#ifdef GTA_PC\n\t// only used in pc\n\tvoid AdjustSamplesVolume();                                                     // done (inlined)\n\tuint8 ComputeEmittingVolume(uint8 emittingVolume, float intensity, float dist); // done (inlined)\n#endif\n};\n\n#ifdef AUDIO_MSS\nstatic_assert(sizeof(cAudioManager) == 0x5558, \"cAudioManager: error\");\n#endif\n\nextern cAudioManager AudioManager;\n"
  },
  {
    "path": "src/audio/AudioSamples.h",
    "content": "#pragma once\n\n#include \"common.h\"\n\nenum eSfxSample\n{\n\tSFX_CAR_HORN_JEEP = 0,\n\tSFX_CAR_HORN_BMW328,\n\tSFX_CAR_HORN_BUS,\n\tSFX_CAR_HORN_BUS2,\n\tSFX_CAR_HORN_56CHEV,\n\tSFX_CAR_HORN_PICKUP,\n\tSFX_CAR_HORN_PORSCHE,\n\tSFX_CAR_HORN_TRUCK,\n\n\tSFX_CAR_HELI_MAI,  // 8\n\tSFX_CAR_HELI_MAI2, // 9\n\tSFX_CAR_HELI_REA,  // 10\n\tSFX_CAR_HELI_STA,  // 11\n\tSFX_CAR_HELI_ROT,  // 12\n\tSFX_CAR_HELI_FAR,  // 13\n\tSFX_CAR_HELI_ROL,  // 14\n\n\tSFX_OLD_CAR_DOOR_OPEN,\n\tSFX_OLD_CAR_DOOR_CLOSE,\n\tSFX_NEW_CAR_DOOR_OPEN,\n\tSFX_NEW_CAR_DOOR_CLOSE,\n\tSFX_TRUCK_DOOR_OPEN,\n\tSFX_TRUCK_DOOR_CLOSE,\n\tSFX_REVERSE_GEAR,\n\tSFX_REVERSE_GEAR_2,\n\tSFX_CAR_STARTER, // 23\n\tSFX_ROAD_NOISE,  // 24\n\tSFX_SKID,        // 25\n\tSFX_GRAVEL_SKID, // 26\n\tSFX_POLICE_SIREN_SLOW,\n\tSFX_SIREN_FAST, // 28\n\tSFX_AMBULANCE_SIREN_SLOW,\n\tSFX_REVERSE_WARNING,\n\tSFX_ICE_CREAM_TUNE,\n\tSFX_AIR_BRAKES,    // 32\n\tSFX_TYRE_BUMP,     // 33\n\tSFX_TYRE_BURST_B,  // 34\n\tSFX_TYRE_BURST,    // 35\n\tSFX_TYRE_BURST_L,  // 36\n\tSFX_PALM_TREE_LO,  // 37\n\tSFX_BULLET_PASS_1, // 38\n\tSFX_BULLET_PASS_2, // 39\n\tSFX_SKATE_1,       // 40\n\tSFX_SKATE_2,       // 41\n\tSFX_FOOTSTEP_CONCRETE_1,\n\tSFX_FOOTSTEP_CONCRETE_2,\n\tSFX_FOOTSTEP_CONCRETE_3,\n\tSFX_FOOTSTEP_CONCRETE_4,\n\tSFX_FOOTSTEP_CONCRETE_5,\n\tSFX_EXPLOSION_1,              // 47\n\tSFX_EXPLOSION_2,              // 48\n\tSFX_EXPLOSION_3,              // 49\n\tSFX_COLT45_LEFT,              // 50\n\tSFX_COLT45_RIGHT,             // 51\n\tSFX_AK47_LEFT,                // 52\n\tSFX_AK47_RIGHT,               // 53\n\tSFX_UZI_LEFT,                 // 54\n\tSFX_UZI_RIGHT,                // 55\n\tSFX_UZI_END_LEFT,             // 56\n\tSFX_SNIPER_LEFT,              // 57\n\tSFX_SNIPER_RIGHT,             // 58\n\tSFX_ROCKET_LEFT,              // 59\n\tSFX_ROCKET_RIGHT,             // 60\n\tSFX_ROCKET_FLY,               // 61\n\tSFX_FLAMETHROWER_LEFT,        // 62\n\tSFX_FLAMETHROWER_RIGHT,       // 63\n\tSFX_FLAMETHROWER_START_LEFT,  // 64\n\tSFX_FLAMETHROWER_START_RIGHT, // 65\n\tSFX_SHOTGUN_LEFT,             // 66\n\tSFX_SHOTGUN_RIGH,             // 67\n\tSFX_M60_LEFT,                 // 68\n\tSFX_M60_RIGHT,                // 69\n\tSFX_M60_TAIL_LEFT,            // 70\n\tSFX_TEC_LEFT,                 // 71\n\tSFX_TEC_RIGHT,                // 72\n\tSFX_TEC_TAIL,                 // 73\n\tSFX_RUGER_LEFT,               // 74\n\tSFX_RUGER_RIGHT,              // 75\n\tSFX_RUGER_TAIL,               // 76\n\tSFX_PISTOL_RELOAD,            // 77\n\tSFX_AK47_RELOAD,              // 78\n\tSFX_ROCKET_RELOAD,            // 79\n\tSFX_RIFLE_RELOAD,             // 80\n\tSFX_GOLF_CLUB_SWING,          // 81\n\tSFX_MINIGUN_FIRE_LEFT,        // 82\n\tSFX_MINIGUN_FIRE_RIGHT,       // 83\n\tSFX_MINIGUN_STOP,             // 84\n\tSFX_SPAS12_LEFT,              // 85\n\tSFX_SPAS12_RIGHT,             // 86\n\tSFX_SPAS12_TAIL_LEFT,         // 87\n\tSFX_PYTHON_LEFT,              // 88\n\tSFX_PYTHON_RIGHT,             // 89\n\tSFX_MP5_LEFT,                 // 90\n\tSFX_MP5_RIGHT,                // 91\n\tSFX_COL_TARMAC_1,             // 92\n\tSFX_COL_TARMAC_2,             // 93\n\tSFX_COL_TARMAC_3,             // 94\n\tSFX_COL_TARMAC_4,             // 95\n\tSFX_COL_TARMAC_5,             // 96\n\tSFX_COL_GRASS_1,\n\tSFX_COL_GRAVEL_1,\n\tSFX_COL_MUD_1,\n\tSFX_COL_GARAGE_DOOR_1,\n\tSFX_COL_CAR_PANEL_1,\n\tSFX_COL_CAR_PANEL_2,\n\tSFX_COL_CAR_PANEL_3,\n\tSFX_COL_CAR_PANEL_4,\n\tSFX_COL_CAR_PANEL_5,\n\tSFX_COL_CAR_PANEL_6,\n\tSFX_COL_THICK_METAL_PLATE_1,\n\tSFX_COL_SCAFFOLD_POLE_1,\n\tSFX_COL_LAMP_POST_1,\n\tSFX_COL_HYDRANT_1,\n\tSFX_COL_METAL_CHAIN_FENCE_1,\n\tSFX_COL_METAL_CHAIN_FENCE_2,\n\tSFX_COL_METAL_CHAIN_FENCE_3,\n\tSFX_COL_METAL_CHAIN_FENCE_4,\n\tSFX_COL_PED_1, // 115\n\tSFX_COL_PED_2, // 116\n\tSFX_COL_SAND_1,\n\tSFX_COL_WOOD_CRATES_1,\n\tSFX_COL_WOOD_CRATES_2,\n\tSFX_COL_WOOD_CRATES_3,\n\tSFX_COL_WOOD_CRATES_4,\n\tSFX_COL_WOOD_BENCH_1,\n\tSFX_COL_WOOD_BENCH_2,\n\tSFX_COL_WOOD_BENCH_3,\n\tSFX_COL_WOOD_BENCH_4,\n\tSFX_COL_WOOD_SOLID_1,\n\tSFX_COL_VEG_1, // 127\n\tSFX_COL_VEG_2, // 128\n\tSFX_COL_VEG_3, // 129\n\tSFX_COL_VEG_4, // 130\n\tSFX_COL_VEG_5, // 131\n\tSFX_COL_CONTAINER_1,\n\tSFX_COL_NEWS_VENDOR_1,\n\tSFX_COL_NEWS_VENDOR_2,\n\tSFX_COL_NEWS_VENDOR_3,\n\tSFX_COL_CAR_1, // 136\n\tSFX_COL_CAR_2, // 137\n\tSFX_COL_CAR_3, // 138\n\tSFX_COL_CAR_4, // 139\n\tSFX_COL_CAR_5, // 140\n\tSFX_COL_CARDBOARD_1,\n\tSFX_COL_CARDBOARD_2,\n\tSFX_COL_GATE,     // 143\n\tSFX_SCRAPE_CAR_1, // 144\n\tSFX_CRATE_SMASH,\n\tSFX_GLASS_CRACK, // 146\n\tSFX_GLASS_SMASH, // 147\n\tSFX_GLASS_SHARD_1,\n\tSFX_GLASS_SHARD_2,\n\tSFX_GLASS_SHARD_3,\n\tSFX_GLASS_SHARD_4,\n\tSFX_PED_ON_FIRE,  // 152\n\tSFX_CAR_ON_FIRE,  // 153\n\tSFX_RAIN,         // 154\n\tSFX_HURRICANE_MA, // 155\n\tSFX_BULLET_SHELL_HIT_GROUND_1,\n\tSFX_BULLET_SHELL_HIT_GROUND_2,\n\tSFX_BULLET_PED,           // 158\n\tSFX_BULLET_CAR_1,         // 159\n\tSFX_BULLET_CAR_2,         // 160\n\tSFX_BULLET_CAR_3,         // 161\n\tSFX_BULLET_WALL_1,        // 162\n\tSFX_BULLET_WALL_2,        // 163\n\tSFX_BULLET_WALL_3,        // 164\n\tSFX_BAT_HIT_LEFT,         // 165\n\tSFX_BAT_HIT_RIGH,         // 166\n\tSFX_FIGHT_1,              // 167\n\tSFX_FIGHT_2,              // 168\n\tSFX_FIGHT_4,              // 169\n\tSFX_FIGHT_5,              // 170\n\tSFX_KNIFE_SWING,          // 171\n\tSFX_KNIFE_SLASH,          // 172\n\tSFX_KNIFE_STAB,           // 173\n\tSFX_HAMMER_HIT_1,         // 174\n\tSFX_HAMMER_HIT_2,         // 175\n\tSFX_GARAGE_DOOR_LOOP,     // 176\n\tSFX_COUNTDOWN,            // 177\n\tSFX_ARM_BOMB,             // 178\n\tSFX_POLICE_RADIO_CRACKLE, // 179\n\n\tSFX_WEVE_GOT,\n\tSFX_THERES,\n\tSFX_RESPOND_TO,\n\tSFX_A_10,\n\tSFX_IN,\n\tSFX_NORTH,\n\tSFX_EAST,\n\tSFX_SOUTH,\n\tSFX_WEST,\n\tSFX_CENTRAL,\n\tSFX_POLICE_RADIO_MESSAGE_NOISE_1,\n\tSFX_POLICE_RADIO_SUSPECT,\n\tSFX_POLICE_RADIO_LAST_SEEN,\n\tSFX_POLICE_RADIO_ON_FOOT,\n\tSFX_POLICE_RADIO_IN_A,\n\tSFX_POLICE_RADIO_DARK,\n\tSFX_POLICE_RADIO_LIGHT,\n\tSFX_POLICE_RADIO_BRIGHT,\n\n\tSFX_CRIME_1,\n\tSFX_CRIME_2,\n\tSFX_CRIME_3,\n\tSFX_CRIME_4,\n\tSFX_CRIME_5,\n\tSFX_CRIME_6,\n\tSFX_CRIME_7,\n\tSFX_CRIME_8,\n\tSFX_CRIME_9,\n\tSFX_CRIME_10,\n\tSFX_CRIME_11,\n\tSFX_CRIME_12,\n\tSFX_POLICE_RADIO_VICE_CITY,\n\tSFX_POLICE_RADIO_VICE_CITY_BEACH,\n\tSFX_POLICE_RADIO_VICE_CITY_MAINLAND,\n\tSFX_POLICE_RADIO_OCEAN_BEACH, //???\n\tSFX_POLICE_RADIO_WASHINGTON_BEACH,\n\tSFX_POLICE_RADIO_VICE_POINT,\n\tSFX_POLICE_RADIO_LEAF_LINKS,\n\tSFX_POLICE_RADIO_STRAFISH_ISLAND, //???????????\n\tSFX_POLICE_RADIO_VICE_PORT,\n\tSFX_POLICE_RADIO_LITTLE_HAVANA,\n\tSFX_POLICE_RADIO_LITTLE_HAITI,\n\tSFX_POLICE_RADIO_PRAWN_ISLAND, //??????????? IS THAT HOW SHE PRONOUNCES ISLAND?\n\tSFX_POLICE_RADIO_DOWNTOWN,\n\tSFX_POLICE_RADIO_ESCOBAR_INTERNATIONAL,\n\tSFX_POLICE_RADIO_BLACK,\n\tSFX_POLICE_RADIO_WHITE,\n\tSFX_POLICE_RADIO_BLUE,\n\tSFX_POLICE_RADIO_RED,\n\tSFX_POLICE_RADIO_PURPLE,\n\tSFX_POLICE_RADIO_YELLOW,\n\tSFX_POLICE_RADIO_GREY,\n\tSFX_POLICE_RADIO_ORANGE,\n\tSFX_POLICE_RADIO_GREEN,\n\tSFX_POLICE_RADIO_SILVER,\n\tSFX_POLICE_RADIO_AMBULANCE,\n\tSFX_POLICE_RADIO_2_DOOR,\n\tSFX_POLICE_RADIO_TRUCK,\n\tSFX_POLICE_RADIO_FIRE_TRUCK,\n\tSFX_POLICE_RADIO_PICKUP,\n\tSFX_POLICE_RADIO_POLICE_CAR,\n\tSFX_POLICE_RADIO_BOAT,\n\tSFX_POLICE_RADIO_BUGGY,\n\tSFX_POLICE_RADIO_BUS,\n\tSFX_POLICE_RADIO_COACH,\n\tSFX_POLICE_RADIO_CRUISER,\n\tSFX_POLICE_RADIO_DINGHY,\n\tSFX_POLICE_RADIO_GARBAGE_TRUCK,\n\tSFX_POLICE_RADIO_GOLF_CART,\n\tSFX_POLICE_RADIO_HEARSE,\n\tSFX_POLICE_RADIO_HELICOPTER,\n\tSFX_POLICE_RADIO_ICE_CREAM_VAN,\n\tSFX_POLICE_RADIO_LOWRIDER,\n\tSFX_POLICE_RADIO_MOPED,\n\tSFX_POLICE_RADIO_MOTOBIKE,\n\tSFX_POLICE_RADIO_OFFROAD,\n\tSFX_POLICE_RADIO_PLANE,\n\tSFX_POLICE_RADIO_RIG,\n\tSFX_POLICE_RADIO_SEDAN,\n\tSFX_POLICE_RADIO_SPEEDBOAT,\n\tSFX_POLICE_RADIO_SPORTS_CAR,\n\tSFX_POLICE_RADIO_STATION_WAGON,\n\tSFX_POLICE_RADIO_STRETCH,\n\tSFX_POLICE_RADIO_SWAT_VAN,\n\tSFX_POLICE_RADIO_TANK,\n\tSFX_POLICE_RADIO_TAXI,\n\tSFX_POLICE_RADIO_VAN,\n\n\tSFX_HELI_1,      // 198\n\tSFX_PHONE_RING,  // 199\n\tSFX_CAR_REV_1,   // PONT\n\tSFX_CAR_REV_2,   // PORSHE\n\tSFX_CAR_REV_3,   // SPIDER\n\tSFX_CAR_REV_4,   // MERC\n\tSFX_CAR_REV_5,   // TRUC\n\tSFX_CAR_REV_6,   // HOTROD\n\tSFX_CAR_REV_7,   // COBRA\n\tSFX_CAR_REV_8,   // PONT2\n\tSFX_CAR_REV_9,   // CADI\n\tSFX_CAR_REV_10,  // PATHFINDER\n\tSFX_CAR_REV_11,  // PACARD\n\tSFX_CAR_REV_12,  // GOLFCART\n\tSFX_CAR_REV_13,  // SFX_CAR_IDLE_GOL\n\tSFX_CAR_REV_14,  // SFX_CAR_IDLE_GOL\n\tSFX_CAR_REV_15,  // SFX_CAR_IDLE_GOL\n\tSFX_CAR_REV_16,  // SFX_CAR_IDLE_GOL\n\tSFX_CAR_REV_17,  // VTWI\n\tSFX_MOPED_REV,   // just moped\n\tSFX_CAR_REV_19,  // HOND(A)\n\tSFX_CAR_REV_20,  // SPOR(TCAR)\n\tSFX_CAR_IDLE_1,  // PONT\n\tSFX_CAR_IDLE_2,  // PORSHE\n\tSFX_CAR_IDLE_3,  // SPIDER\n\tSFX_CAR_IDLE_4,  // MERC\n\tSFX_CAR_IDLE_5,  // TRUC\n\tSFX_CAR_IDLE_6,  // HOTROD\n\tSFX_CAR_IDLE_7,  // COBRA\n\tSFX_CAR_IDLE_8,  // PONT2\n\tSFX_CAR_IDLE_9,  // CADI\n\tSFX_CAR_IDLE_10, // PATHFINDER\n\tSFX_CAR_IDLE_11, // PACARD\n\tSFX_CAR_IDLE_12, // GOLFCART\n\tSFX_CAR_IDLE_13, // SFX_CAR_IDLE_GOL\n\tSFX_CAR_IDLE_14, // SFX_CAR_IDLE_GOL\n\tSFX_CAR_IDLE_15, // SFX_CAR_IDLE_GOL\n\tSFX_CAR_IDLE_16, // SFX_CAR_IDLE_GOL\n\tSFX_CAR_IDLE_17, // VTWI\n\tSFX_MOPED_IDLE,  // 237\n\tSFX_CAR_IDLE_19, // HOND(A)\n\tSFX_CAR_IDLE_20, // SPOR(TCAR)\n\tSFX_JUMBO_DIST_FLY,\n\tSFX_JUMBO_TAXI,   // 241\n\tSFX_JUMBO_WHINE,  // 242\n\tSFX_JUMBO_ENGINE, // 243\n\tSFX_JUMBO_RUMBLE, // 244\n\tSFX_JUMBO_LAND_WHEELS,\n\tSFX_BOAT_CRUISER_LOOP, // 246\n\tSFX_BOAT_V12_LOOP,     // 247\n\tSFX_BOAT_WATER_LOOP,\n\tSFX_BOAT_SPLASH_1,\n\tSFX_BOAT_SPLASH_2,\n\tSFX_FISHING_BOAT_IDLE,\n\tSFX_CAR_RAIN_1,   // 252\n\tSFX_CAR_RAIN_2,   // 253\n\tSFX_CAR_RAIN_3,   // 254\n\tSFX_CAR_RAIN_4,   // 255\n\tSFX_SPLASH_1,     // 256\n\tSFX_PED_CRUNCH_1, // 257\n\tSFX_PED_CRUNCH_2, // 258\n\tSFX_WOODEN_BOX_SMASH,\n\tSFX_CARDBOARD_BOX_SMASH,\n\tSFX_ERROR_FIRE_ROCKET_LAUNCHER,\n\tSFX_ERROR_FIRE_RIFLE,\n\tSFX_TANK_TURRET, // 263\n\tSFX_BODY_LAND_AND_FALL,\n\tSFX_BODY_LAND,  // 265\n\tSFX_BOMB_BEEP,  // 266\n\tSFX_TIMER_BEEP, // 267\n\tSFX_SUSPENSION_FAST_MOVE,\n\tSFX_SUSPENSION_SLOW_MOVE_LOOP,\n\tSFX_SHAG_SUSPENSION,\n\tSFX_HIT_BALL,     // 271\n\tSFX_ARCADE,       // 272\n\tSFX_CESNA_IDLE,   // 273\n\tSFX_CESNA_REV,    // 274\n\tSFX_RADIO_CLICK,  // 275\n\tSFX_RADIO_DIAL_1, // 276\n\tSFX_RADIO_DIAL_2, // 277\n\tSFX_RADIO_DIAL_3, // 278\n\n\t// pc only\n\tSFX_RADIO_DIAL_4,\n\tSFX_RADIO_DIAL_5,\n\tSFX_RADIO_DIAL_6,\n\tSFX_RADIO_DIAL_7,\n\tSFX_RADIO_DIAL_8,\n\tSFX_RADIO_DIAL_9,\n\tSFX_RADIO_DIAL_10,\n\tSFX_RADIO_DIAL_11,\n\tSFX_RADIO_DIAL_12,\n\n\tSFX_INFO_LEFT,                    // 279\n\tSFX_INFO_RIGHT,                   // 280\n\tSFX_INFO_CENTRE,                  // 281\n\tSFX_MONEY_LEFT,                   // 282\n\tSFX_MONEY_RIGHT,                  // 283\n\tSFX_WEAPON_LEFT,                  // 284\n\tSFX_WEAPON_RIGHT,                 // 285\n\tSFX_WEAPON_CENTRE,                // 286\n\tSFX_PART_MISSION_COMPLETE_LEFT,   // 287\n\tSFX_PART_MISSION_COMPLETE_RIGHT,  // 288\n\tSFX_PART_MISSION_COMPLETE_CENTRE, // 289\n\tSFX_GO_LEFT,                      // 290\n\tSFX_GO_RIGHT,                     // 291\n\tSFX_GO_CENTRE,                    // 292\n\tSFX_TIMER,                        // 293\n\tSFX_EMPTY,                        // 294\n\n\tSFX_FE_HIGHLIGHT_LEFT,  //\n\tSFX_FE_HIGHLIGHT_RIGHT, //\n\tSFX_FE_SELECT_LEFT,     //\n\tSFX_FE_SELECT_RIGHT,    //\n\tSFX_FE_BACK_LEFT,       //\n\tSFX_FE_BACK_RIGHT,      //\n\tSFX_FE_ERROR_LEFT,      //\n\tSFX_FE_ERROR_RIGHT,     //\n\tSFX_FE_NOISE_BURST_1,\n\tSFX_FE_NOISE_BURST_2,\n\tSFX_FE_NOISE_BURST_3,\n\n\tSFX_CAR_ACCEL_1,\n\tSFX_CAR_AFTER_ACCEL_1,\n\tSFX_CAR_FINGER_OFF_ACCEL_1,\n\n\tSFX_CAR_ACCEL_2,\n\tSFX_CAR_AFTER_ACCEL_2,\n\tSFX_CAR_FINGER_OFF_ACCEL_2,\n\n\tSFX_CAR_ACCEL_3,\n\tSFX_CAR_AFTER_ACCEL_3,\n\tSFX_CAR_FINGER_OFF_ACCEL_3,\n\n\tSFX_CAR_ACCEL_4,\n\tSFX_CAR_AFTER_ACCEL_4,\n\tSFX_CAR_FINGER_OFF_ACCEL_4,\n\n\tSFX_CAR_ACCEL_5,\n\tSFX_CAR_AFTER_ACCEL_5,\n\tSFX_CAR_FINGER_OFF_ACCEL_5,\n\n\tSFX_CAR_ACCEL_6,\n\tSFX_CAR_AFTER_ACCEL_6,\n\tSFX_CAR_FINGER_OFF_ACCEL_6,\n\n\tSFX_CAR_ACCEL_7,\n\tSFX_CAR_AFTER_ACCEL_7,\n\tSFX_CAR_FINGER_OFF_ACCEL_7,\n\n\tSFX_CAR_ACCEL_8,\n\tSFX_CAR_AFTER_ACCEL_8,\n\tSFX_CAR_FINGER_OFF_ACCEL_8,\n\n\tSFX_CAR_ACCEL_9,\n\tSFX_CAR_AFTER_ACCEL_9,\n\tSFX_CAR_FINGER_OFF_ACCEL_9,\n\n\tSFX_CAR_ACCEL_10,\n\tSFX_CAR_AFTER_ACCEL_10,\n\tSFX_CAR_FINGER_OFF_ACCEL_10,\n\n\tSFX_CAR_ACCEL_11,\n\tSFX_CAR_AFTER_ACCEL_11,\n\tSFX_CAR_FINGER_OFF_ACCEL_11,\n\n\tSFX_CAR_ACCEL_12,\n\tSFX_CAR_AFTER_ACCEL_12,\n\tSFX_CAR_FINGER_OFF_ACCEL_12,\n\n\t// some CHAINSAW STUFF\n\t// SFX_CAR_CHAINSAW, //10973\n\t// SFX_CAR_CHAINSAW, //10974\n\t// SFX_CAR_CHAINSAW, //10975\n\tSFX_CAR_ACCEL_13,\n\tSFX_CAR_AFTER_ACCEL_13,\n\tSFX_CAR_FINGER_OFF_ACCEL_13,\n\n\tSFX_RC_IDLE,  // 10976\n\tSFX_RC_REV,   // 10977\n\tSFX_RC_EMPTY, // 10978\n\n\tSFX_CAR_RC_HELI,             // 10979\n\tSFX_CAR_AFTER_ACCEL_15,      // empty\n\tSFX_CAR_FINGER_OFF_ACCEL_15, // empty\n\n\tSFX_CAR_ACCEL_16,            // empty\n\tSFX_CAR_AFTER_ACCEL_16,      // empty\n\tSFX_CAR_FINGER_OFF_ACCEL_16, // empty\n\n\t// bike stuff apparently\n\tSFX_CAR_ACCEL_17,\n\tSFX_CAR_AFTER_ACCEL_17,\n\tSFX_CAR_FINGER_OFF_ACCEL_17,\n\tSFX_CAR_WIND_17,\n\n\tSFX_CAR_ACCEL_18,\n\tSFX_CAR_AFTER_ACCEL_18,\n\tSFX_CAR_FINGER_OFF_ACCEL_18,\n\tSFX_CAR_WIND_18,\n\n\tSFX_CAR_ACCEL_19,\n\tSFX_CAR_AFTER_ACCEL_19,\n\tSFX_CAR_FINGER_OFF_ACCEL_19,\n\tSFX_CAR_WIND_19,\n\n\tSFX_CAR_ACCEL_20,\n\tSFX_CAR_AFTER_ACCEL_20,\n\tSFX_CAR_FINGER_OFF_ACCEL_20,\n\tSFX_CAR_WIND_20,\n\n\t// some emptinnes here\n\tSFX_CAR_ACCEL_21,\n\tSFX_CAR_AFTER_ACCEL_21,\n\tSFX_CAR_FINGER_OFF_ACCEL_21,\n\tSFX_CAR_ACCEL_22,\n\tSFX_CAR_AFTER_ACCEL_22,\n\tSFX_CAR_FINGER_OFF_ACCEL_22,\n\n\tSFX_HELI_APACHE_1,\n\tSFX_HELI_APACHE_2,\n\tSFX_HELI_APACHE_3,\n\tSFX_HELI_APACHE_4,\n\n\t// something padded for more heli?\n\tSFX_HELI_UNUSED_1,\n\tSFX_HELI_UNUSED_2,\n\tSFX_HELI_UNUSED_3,\n\tSFX_HELI_UNUSED_4,\n\n\tSFX_SEAPLANE_PRO1, // 11018\n\tSFX_SEAPLANE_PRO2, // 11019\n\tSFX_SEAPLANE_PRO3, // 11020\n\tSFX_SEAPLANE_PRO4, // 11021\n\t// low fuel\n\tSFX_SEAPLANE_LOW, // 11022\n\n\t// something padded for more plane?\n\tSFX_PLANE_UNUSED_1,\n\tSFX_PLANE_UNUSED_2,\n\tSFX_PLANE_UNUSED_3,\n\tSFX_PLANE_UNUSED_4,\n\n\t// script objects\n\tSFX_BUILDINGS_BANK_ALARM, // 11027\n\tSFX_BUILDING_SNORE,       // 11028\n\tSFX_BUILDING_BAR_1,       // 11029\n\tSFX_BUILDING_BAR_2,       // 11030\n\tSFX_BUILDING_BAR_3,       // 11031\n\tSFX_BUILDING_BAR_4,       // 11032\n\tSFX_BUILDING_MAL1,        // 11033\n\tSFX_BUILDING_MAL2,        // 11034\n\tSFX_BUILDING_MAL3,        // 11035\n\tSFX_BUILDING_STR1,        // 11036\n\tSFX_BUILDING_STR2,        // 11037\n\tSFX_BUILDING_STR3,        // 11038\n\tSFX_BUILDING_CHURCH,      // 11039\n\tSFX_BUILDING_FAN_1,       // 11040\n\tSFX_BUILDING_FAN_2,       // 11041\n\tSFX_BUILDING_FAN_3,       // 11042\n\tSFX_BUILDING_FAN_4,       // 11043\n\tSFX_BUILDING_INSECTS_1,   // 11044\n\tSFX_BUILDING_INSECTS_2,   // 11045\n\tSFX_BUILDING_INSECTS_3,   // 11046\n\tSFX_BUILDING_INSECTS_4,   // 11047\n\tSFX_BUILDING_INSECTS_5,   // 11048\n\tSFX_CLUB_1,               // 11049\n\tSFX_CLUB_2,               // 11050\n\tSFX_CLUB_3,               // 11051\n\tSFX_CLUB_4,               // 11052\n\n\tSFX_FOOTSTEP_GRASS_1,\n\tSFX_FOOTSTEP_GRASS_2,\n\tSFX_FOOTSTEP_GRASS_3,\n\tSFX_FOOTSTEP_GRASS_4,\n\tSFX_FOOTSTEP_GRASS_5,\n\tSFX_FOOTSTEP_GRAVEL_1,\n\tSFX_FOOTSTEP_GRAVEL_2,\n\tSFX_FOOTSTEP_GRAVEL_3,\n\tSFX_FOOTSTEP_GRAVEL_4,\n\tSFX_FOOTSTEP_GRAVEL_5,\n\tSFX_FOOTSTEP_WOOD_1,\n\tSFX_FOOTSTEP_WOOD_2,\n\tSFX_FOOTSTEP_WOOD_3,\n\tSFX_FOOTSTEP_WOOD_4,\n\tSFX_FOOTSTEP_WOOD_5,\n\tSFX_FOOTSTEP_METAL_1,\n\tSFX_FOOTSTEP_METAL_2,\n\tSFX_FOOTSTEP_METAL_3,\n\tSFX_FOOTSTEP_METAL_4,\n\tSFX_FOOTSTEP_METAL_5,\n\tSFX_FOOTSTEP_WATER_1,\n\tSFX_FOOTSTEP_WATER_2,\n\tSFX_FOOTSTEP_WATER_3,\n\tSFX_FOOTSTEP_WATER_4,\n\tSFX_FOOTSTEP_SAND_1,\n\tSFX_FOOTSTEP_SAND_2,\n\tSFX_FOOTSTEP_SAND_3,\n\tSFX_FOOTSTEP_SAND_4,\n\n\t// TODO: miami ped comments... THERE'S OVER 9000\n\tSFX_POLICE_BOAT_1 = 714,\n\tSFX_POLICE_BOAT_2,\n\tSFX_POLICE_BOAT_3,\n\tSFX_POLICE_BOAT_4,\n\tSFX_POLICE_BOAT_5,\n\tSFX_POLICE_BOAT_6,\n\tSFX_POLICE_BOAT_7,\n\tSFX_POLICE_BOAT_8,\n\tSFX_POLICE_BOAT_9,\n\tSFX_POLICE_BOAT_10,\n\tSFX_POLICE_BOAT_11,\n\tSFX_POLICE_BOAT_12,\n\tSFX_POLICE_BOAT_13,\n\tSFX_POLICE_BOAT_14,\n\tSFX_POLICE_BOAT_15,\n\tSFX_POLICE_BOAT_16,\n\tSFX_POLICE_BOAT_17,\n\tSFX_POLICE_BOAT_18,\n\tSFX_POLICE_BOAT_19,\n\tSFX_POLICE_BOAT_20,\n\tSFX_POLICE_BOAT_21,\n\tSFX_POLICE_BOAT_22,\n\tSFX_POLICE_BOAT_23,\n\n\tSFX_POLICE_HELI_1,\n\tSFX_POLICE_HELI_2,\n\tSFX_POLICE_HELI_3,\n\tSFX_POLICE_HELI_4,\n\tSFX_POLICE_HELI_5,\n\tSFX_POLICE_HELI_6,\n\tSFX_POLICE_HELI_7,\n\tSFX_POLICE_HELI_8,\n\tSFX_POLICE_HELI_9,\n\tSFX_POLICE_HELI_10,\n\tSFX_POLICE_HELI_11,\n\tSFX_POLICE_HELI_12,\n\tSFX_POLICE_HELI_13,\n\tSFX_POLICE_HELI_14,\n\tSFX_POLICE_HELI_15,\n\tSFX_POLICE_HELI_16,\n\tSFX_POLICE_HELI_17,\n\tSFX_POLICE_HELI_18,\n\tSFX_POLICE_HELI_19,\n\tSFX_POLICE_HELI_20,\n\n\tSFX_GENERIC_FEMALE_GRUNT_1 = 2953,\n\tSFX_GENERIC_FEMALE_GRUNT_2 = 2954,\n\tSFX_GENERIC_FEMALE_GRUNT_3 = 2955,\n\tSFX_GENERIC_FEMALE_GRUNT_4 = 2956,\n\tSFX_GENERIC_FEMALE_GRUNT_5 = 2957,\n\tSFX_GENERIC_FEMALE_GRUNT_6 = 2958,\n\tSFX_GENERIC_FEMALE_GRUNT_7 = 2959,\n\tSFX_GENERIC_FEMALE_GRUNT_8 = 2960,\n\tSFX_GENERIC_FEMALE_GRUNT_9 = 2961,\n\tSFX_GENERIC_FEMALE_GRUNT_10 = 2962,\n\tSFX_GENERIC_FEMALE_GRUNT_11 = 2963,\n\tSFX_GENERIC_FEMALE_GRUNT_12 = 2964,\n\tSFX_GENERIC_FEMALE_GRUNT_13 = 2965,\n\tSFX_GENERIC_FEMALE_GRUNT_14 = 2966,\n\tSFX_GENERIC_FEMALE_GRUNT_15 = 2967,\n\tSFX_GENERIC_FEMALE_GRUNT_16 = 2968,\n\tSFX_GENERIC_FEMALE_GRUNT_17 = 2969,\n\tSFX_GENERIC_FEMALE_GRUNT_18 = 2970,\n\tSFX_GENERIC_FEMALE_GRUNT_19 = 2971,\n\tSFX_GENERIC_FEMALE_GRUNT_20 = 2972,\n\tSFX_GENERIC_FEMALE_GRUNT_21 = 2973,\n\tSFX_GENERIC_FEMALE_GRUNT_22 = 2974,\n\tSFX_GENERIC_FEMALE_GRUNT_23 = 2975,\n\tSFX_GENERIC_FEMALE_GRUNT_24 = 2976,\n\tSFX_GENERIC_FEMALE_GRUNT_25 = 2977,\n\tSFX_GENERIC_FEMALE_GRUNT_26 = 2978,\n\tSFX_GENERIC_FEMALE_GRUNT_27 = 2979,\n\tSFX_GENERIC_FEMALE_GRUNT_28 = 2980,\n\tSFX_GENERIC_FEMALE_GRUNT_29 = 2981,\n\tSFX_GENERIC_FEMALE_GRUNT_30 = 2982,\n\tSFX_GENERIC_FEMALE_GRUNT_31 = 2983,\n\tSFX_GENERIC_FEMALE_GRUNT_32 = 2984,\n\tSFX_GENERIC_FEMALE_GRUNT_33 = 2985,\n\tSFX_GENERIC_MALE_FIRE_1 = 3013,\n\tSFX_GENERIC_MALE_FIRE_2 = 3014,\n\tSFX_GENERIC_MALE_FIRE_3 = 3015,\n\tSFX_GENERIC_MALE_FIRE_4 = 3016,\n\tSFX_GENERIC_MALE_FIRE_5 = 3017,\n\tSFX_GENERIC_MALE_FIRE_6 = 3018,\n\tSFX_GENERIC_MALE_FIRE_7 = 3019,\n\tSFX_GENERIC_MALE_FIRE_8 = 3020,\n\tSFX_GENERIC_MALE_FIRE_9 = 3021,\n\tSFX_GENERIC_MALE_FIRE_10 = 3022,\n\tSFX_GENERIC_MALE_FIRE_11 = 3023,\n\tSFX_GENERIC_MALE_FIRE_12 = 3024,\n\tSFX_GENERIC_MALE_FIRE_13 = 3025,\n\tSFX_GENERIC_MALE_FIRE_14 = 3026,\n\tSFX_GENERIC_MALE_FIRE_15 = 3027,\n\tSFX_GENERIC_MALE_FIRE_16 = 3028,\n\tSFX_GENERIC_MALE_FIRE_17 = 3029,\n\tSFX_GENERIC_MALE_FIRE_18 = 3030,\n\tSFX_GENERIC_MALE_FIRE_19 = 3031,\n\tSFX_GENERIC_MALE_FIRE_20 = 3032,\n\tSFX_GENERIC_MALE_FIRE_21 = 3033,\n\tSFX_GENERIC_MALE_FIRE_22 = 3034,\n\tSFX_GENERIC_MALE_FIRE_23 = 3035,\n\tSFX_GENERIC_MALE_FIRE_24 = 3036,\n\tSFX_GENERIC_MALE_FIRE_25 = 3037,\n\tSFX_GENERIC_MALE_FIRE_26 = 3038,\n\tSFX_GENERIC_MALE_FIRE_27 = 3039,\n\tSFX_GENERIC_MALE_FIRE_28 = 3040,\n\tSFX_GENERIC_MALE_FIRE_29 = 3041,\n\tSFX_GENERIC_MALE_FIRE_30 = 3042,\n\tSFX_GENERIC_MALE_FIRE_31 = 3043,\n\tSFX_GENERIC_MALE_FIRE_32 = 3044,\n\tSFX_GENERIC_MALE_DEATH_1 = 3045,\n\tSFX_GENERIC_MALE_DEATH_2 = 3046,\n\tSFX_GENERIC_MALE_DEATH_3 = 3047,\n\tSFX_GENERIC_MALE_DEATH_4 = 3048,\n\tSFX_GENERIC_MALE_DEATH_5 = 3049,\n\tSFX_GENERIC_MALE_DEATH_6 = 3050,\n\tSFX_GENERIC_MALE_DEATH_7 = 3051,\n\tSFX_GENERIC_MALE_DEATH_8 = 3052,\n\tSFX_GENERIC_MALE_DEATH_9 = 3053,\n\tSFX_GENERIC_MALE_DEATH_10 = 3054,\n\tSFX_GENERIC_MALE_DEATH_11 = 3055,\n\tSFX_GENERIC_MALE_DEATH_12 = 3056,\n\tSFX_GENERIC_MALE_DEATH_13 = 3057,\n\tSFX_GENERIC_MALE_DEATH_14 = 3058,\n\tSFX_GENERIC_MALE_DEATH_15 = 3059,\n\tSFX_GENERIC_MALE_DEATH_16 = 3060,\n\tSFX_GENERIC_MALE_DEATH_17 = 3061,\n\tSFX_GENERIC_MALE_DEATH_18 = 3062,\n\tSFX_GENERIC_MALE_DEATH_19 = 3063,\n\tSFX_GENERIC_MALE_DEATH_20 = 3064,\n\tSFX_GENERIC_MALE_DEATH_21 = 3065,\n\tSFX_GENERIC_MALE_DEATH_22 = 3066,\n\tSFX_GENERIC_MALE_DEATH_23 = 3067,\n\tSFX_GENERIC_MALE_DEATH_24 = 3068,\n\tSFX_GENERIC_MALE_DEATH_25 = 3069,\n\tSFX_GENERIC_MALE_DEATH_26 = 3070,\n\tSFX_GENERIC_MALE_DEATH_27 = 3071,\n\tSFX_GENERIC_MALE_DEATH_28 = 3072,\n\tSFX_GENERIC_MALE_DEATH_29 = 3073,\n\tSFX_GENERIC_MALE_DEATH_30 = 3074,\n\tSFX_GENERIC_MALE_DEATH_31 = 3075,\n\tSFX_GENERIC_MALE_DEATH_32 = 3076,\n\tSFX_GENERIC_MALE_DEATH_33 = 3077,\n\tSFX_GENERIC_MALE_DEATH_34 = 3078,\n\tSFX_GENERIC_MALE_DEATH_35 = 3079,\n\tSFX_GENERIC_MALE_DEATH_36 = 3080,\n\tSFX_GENERIC_MALE_DEATH_37 = 3081,\n\tSFX_GENERIC_MALE_DEATH_38 = 3082,\n\tSFX_GENERIC_MALE_DEATH_39 = 3083,\n\tSFX_GENERIC_MALE_DEATH_40 = 3084,\n\tSFX_GENERIC_MALE_DEATH_41 = 3085,\n\tSFX_GENERIC_MALE_GRUNT_1 = 3086,\n\tSFX_GENERIC_MALE_GRUNT_2 = 3087,\n\tSFX_GENERIC_MALE_GRUNT_3 = 3088,\n\tSFX_GENERIC_MALE_GRUNT_4 = 3089,\n\tSFX_GENERIC_MALE_GRUNT_5 = 3090,\n\tSFX_GENERIC_MALE_GRUNT_6 = 3091,\n\tSFX_GENERIC_MALE_GRUNT_7 = 3092,\n\tSFX_GENERIC_MALE_GRUNT_8 = 3093,\n\tSFX_GENERIC_MALE_GRUNT_9 = 3094,\n\tSFX_GENERIC_MALE_GRUNT_10 = 3095,\n\tSFX_GENERIC_MALE_GRUNT_11 = 3096,\n\tSFX_GENERIC_MALE_GRUNT_12 = 3097,\n\tSFX_GENERIC_MALE_GRUNT_13 = 3098,\n\tSFX_GENERIC_MALE_GRUNT_14 = 3099,\n\tSFX_GENERIC_MALE_GRUNT_15 = 3100,\n\tSFX_GENERIC_MALE_GRUNT_16 = 3101,\n\tSFX_GENERIC_MALE_GRUNT_17 = 3102,\n\tSFX_GENERIC_MALE_GRUNT_18 = 3103,\n\tSFX_GENERIC_MALE_GRUNT_19 = 3104,\n\tSFX_GENERIC_MALE_GRUNT_20 = 3105,\n\tSFX_GENERIC_MALE_GRUNT_21 = 3106,\n\tSFX_GENERIC_MALE_GRUNT_22 = 3107,\n\tSFX_GENERIC_MALE_GRUNT_23 = 3108,\n\tSFX_GENERIC_MALE_GRUNT_24 = 3109,\n\tSFX_GENERIC_MALE_GRUNT_25 = 3110,\n\tSFX_GENERIC_MALE_GRUNT_26 = 3111,\n\tSFX_GENERIC_MALE_GRUNT_27 = 3112,\n\tSFX_GENERIC_MALE_GRUNT_28 = 3113,\n\tSFX_GENERIC_MALE_GRUNT_29 = 3114,\n\tSFX_GENERIC_MALE_GRUNT_30 = 3115,\n\tSFX_GENERIC_MALE_GRUNT_31 = 3116,\n\tSFX_GENERIC_MALE_GRUNT_32 = 3117,\n\tSFX_GENERIC_MALE_GRUNT_33 = 3118,\n\tSFX_GENERIC_MALE_GRUNT_34 = 3119,\n\tSFX_GENERIC_MALE_GRUNT_35 = 3120,\n\tSFX_GENERIC_MALE_GRUNT_36 = 3121,\n\tSFX_GENERIC_MALE_GRUNT_37 = 3122,\n\tSFX_GENERIC_MALE_GRUNT_38 = 3123,\n\tSFX_GENERIC_MALE_GRUNT_39 = 3124,\n\tSFX_GENERIC_MALE_GRUNT_40 = 3125,\n\tSFX_GENERIC_MALE_GRUNT_41 = 3126,\n\tSFX_GENERIC_MALE_PANIC_1 = 3127,\n\tSFX_GENERIC_MALE_PANIC_2 = 3128,\n\tSFX_GENERIC_MALE_PANIC_3 = 3129,\n\tSFX_GENERIC_MALE_PANIC_4 = 3130,\n\tSFX_GENERIC_MALE_PANIC_5 = 3131,\n\tSFX_GENERIC_MALE_PANIC_6 = 3132,\n\tSFX_GENERIC_MALE_PANIC_7 = 3133,\n\tSFX_GENERIC_MALE_PANIC_8 = 3134,\n\tSFX_GENERIC_MALE_PANIC_9 = 3135,\n\tSFX_GENERIC_MALE_PANIC_10 = 3136,\n\tSFX_GENERIC_MALE_PANIC_11 = 3137,\n\tSFX_GENERIC_MALE_PANIC_12 = 3138,\n\tSFX_GENERIC_MALE_PANIC_13 = 3139,\n\tSFX_GENERIC_MALE_PANIC_14 = 3140,\n\tSFX_GENERIC_MALE_PANIC_15 = 3141,\n\tSFX_GENERIC_MALE_PANIC_16 = 3142,\n\tSFX_GENERIC_MALE_PANIC_17 = 3143,\n\tSFX_GENERIC_MALE_PANIC_18 = 3144,\n\tSFX_GENERIC_MALE_PANIC_19 = 3145,\n\tSFX_GENERIC_MALE_PANIC_20 = 3146,\n\tSFX_GENERIC_MALE_PANIC_21 = 3147,\n\tSFX_GENERIC_MALE_PANIC_22 = 3148,\n\tSFX_GENERIC_MALE_PANIC_23 = 3149,\n\tSFX_GENERIC_MALE_PANIC_24 = 3150,\n\tSFX_GENERIC_MALE_PANIC_25 = 3151,\n\tSFX_GENERIC_MALE_PANIC_26 = 3152,\n\tSFX_GENERIC_MALE_PANIC_27 = 3153,\n\tSFX_GENERIC_MALE_PANIC_28 = 3154,\n\tSFX_GENERIC_MALE_PANIC_29 = 3155,\n\tSFX_GENERIC_MALE_PANIC_30 = 3156,\n\tSFX_GENERIC_MALE_PANIC_31 = 3157,\n\tSFX_GENERIC_MALE_PANIC_32 = 3158,\n\tSFX_GENERIC_MALE_PANIC_33 = 3159,\n\tSFX_GENERIC_MALE_PANIC_34 = 3160,\n\tSFX_GENERIC_MALE_PANIC_35 = 3161,\n\n\tTOTAL_AUDIO_SAMPLES = 9941,\n\tNO_SAMPLE,\n\n\t// shorthands\n\tSAMPLEBANK_START = SFX_CAR_HORN_JEEP,\n\tSAMPLEBANK_END = SFX_FOOTSTEP_SAND_4,\n\tSAMPLEBANK_MAX = SFX_FOOTSTEP_SAND_4 + 1,\n\tSAMPLEBANK_PED_START = SFX_FOOTSTEP_SAND_4 + 1,\n\tSAMPLEBANK_PED_END = 9940,\n\tSAMPLEBANK_PED_MAX = SAMPLEBANK_PED_END + 1,\n};\n"
  },
  {
    "path": "src/audio/AudioScriptObject.cpp",
    "content": "#include \"common.h\"\n\n#include \"AudioScriptObject.h\"\n#include \"Pools.h\"\n#include \"DMAudio.h\"\n\ncAudioScriptObject::cAudioScriptObject()\n{\n\tReset();\n};\n\ncAudioScriptObject::~cAudioScriptObject()\n{\n\tReset();\n};\n\nvoid\ncAudioScriptObject::Reset()\n{\n\tAudioId = SCRIPT_SOUND_INVALID;\n\tPosn = CVector(0.0f, 0.0f, 0.0f);\n\tAudioEntity = AEHANDLE_NONE;\n}\n\nvoid *\ncAudioScriptObject::operator new(size_t sz)\n{\n\treturn CPools::GetAudioScriptObjectPool()->New();\n}\n\nvoid *\ncAudioScriptObject::operator new(size_t sz, int handle)\n{\n\treturn CPools::GetAudioScriptObjectPool()->New(handle);\n}\n\nvoid\ncAudioScriptObject::operator delete(void *p, size_t sz)\n{\n\tCPools::GetAudioScriptObjectPool()->Delete((cAudioScriptObject *)p);\n}\n\nvoid\ncAudioScriptObject::operator delete(void *p, int handle)\n{\n\tCPools::GetAudioScriptObjectPool()->Delete((cAudioScriptObject *)p);\n}\n\nvoid\ncAudioScriptObject::LoadAllAudioScriptObjects(uint8 *buf, uint32 size)\n{\n\tINITSAVEBUF\n\n\tCheckSaveHeader(buf, 'A', 'U', 'D', '\\0', size - SAVE_HEADER_SIZE);\n\n\tint32 pool_size = ReadSaveBuf<int32>(buf);\n\tfor (int32 i = 0; i < pool_size; i++) {\n\t\tint handle = ReadSaveBuf<int32>(buf);\n\t\tcAudioScriptObject *p = new(handle) cAudioScriptObject;\n\t\tassert(p != nil);\n\t\t*p = ReadSaveBuf<cAudioScriptObject>(buf);\n\t\tp->AudioEntity = DMAudio.CreateLoopingScriptObject(p);\n\t}\n\n\tVALIDATESAVEBUF(size);\n}\n\nvoid\ncAudioScriptObject::SaveAllAudioScriptObjects(uint8 *buf, uint32 *size)\n{\n\tINITSAVEBUF\n\n\tint32 pool_size = CPools::GetAudioScriptObjectPool()->GetNoOfUsedSpaces();\n\t*size = SAVE_HEADER_SIZE + sizeof(int32) + pool_size * (sizeof(cAudioScriptObject) + sizeof(int32));\n\tWriteSaveHeader(buf, 'A', 'U', 'D', '\\0', *size - SAVE_HEADER_SIZE);\n\tWriteSaveBuf(buf, pool_size);\n\n\tint32 i = CPools::GetAudioScriptObjectPool()->GetSize();\n\twhile (i--) {\n\t\tcAudioScriptObject *p = CPools::GetAudioScriptObjectPool()->GetSlot(i);\n\t\tif (p != nil) {\n\t\t\tWriteSaveBuf(buf, CPools::GetAudioScriptObjectPool()->GetIndex(p));\n\t\t\tWriteSaveBuf(buf, *p);\n\t\t}\n\t}\n\n\tVALIDATESAVEBUF(*size);\n}\n\nvoid\nPlayOneShotScriptObject(uint8 id, CVector const &pos)\n{\n\tcAudioScriptObject *audioScriptObject = new cAudioScriptObject();\n\taudioScriptObject->Posn = pos;\n\taudioScriptObject->AudioId = id;\n\taudioScriptObject->AudioEntity = AEHANDLE_NONE;\n\tDMAudio.CreateOneShotScriptObject(audioScriptObject);\n}\n"
  },
  {
    "path": "src/audio/AudioScriptObject.h",
    "content": "#pragma once\n\nclass cAudioScriptObject\n{\npublic:\n\tint16 AudioId;\n\tCVector Posn;\n\tint32 AudioEntity;\n\n\tcAudioScriptObject();\n\t~cAudioScriptObject();\n\n\tvoid Reset(); /// ok\n\n\tstatic void* operator new(size_t);\n\tstatic void* operator new(size_t, int);\n\tstatic void operator delete(void*, size_t);\n\tstatic void operator delete(void*, int);\n\n\tstatic void LoadAllAudioScriptObjects(uint8 *buf, uint32 size);\n\tstatic void SaveAllAudioScriptObjects(uint8 *buf, uint32 *size);\n};\n\nVALIDATE_SIZE(cAudioScriptObject, 20);\n\nextern void PlayOneShotScriptObject(uint8 id, CVector const &pos);"
  },
  {
    "path": "src/audio/DMAudio.cpp",
    "content": "#include \"common.h\"\n\n#include \"DMAudio.h\"\n#include \"MusicManager.h\"\n#include \"AudioManager.h\"\n#include \"AudioScriptObject.h\"\n#include \"sampman.h\"\n\ncDMAudio DMAudio;\n\nvoid\ncDMAudio::Initialise(void)\n{\n\tAudioManager.Initialise();\n}\n\nvoid\ncDMAudio::Terminate(void)\n{\n\tAudioManager.Terminate();\n}\n\nvoid\ncDMAudio::Service(void)\n{\n\tAudioManager.Service();\n}\n\nint32\ncDMAudio::CreateEntity(eAudioType type, void *UID)\n{\n\treturn AudioManager.CreateEntity(type, (CPhysical *)UID);\n}\n\nvoid\ncDMAudio::DestroyEntity(int32 audioEntity)\n{\n\tAudioManager.DestroyEntity(audioEntity);\n}\n\nvoid\ncDMAudio::SetEntityStatus(int32 audioEntity, uint8 status)\n{\n\tAudioManager.SetEntityStatus(audioEntity, status);\n}\n\nvoid\ncDMAudio::PlayOneShot(int32 audioEntity, uint16 oneShot, float volume)\n{\n\tAudioManager.PlayOneShot(audioEntity, oneShot, volume);\n}\n\nvoid\ncDMAudio::DestroyAllGameCreatedEntities(void)\n{\n\tAudioManager.DestroyAllGameCreatedEntities();\n}\n\nvoid\ncDMAudio::SetMonoMode(uint8 mono)\n{\n\tAudioManager.SetMonoMode(mono);\n}\n\nvoid\ncDMAudio::SetMP3BoostVolume(uint8 volume)\n{\n\tuint8 vol = volume;\n\tif (vol > MAX_VOLUME) vol = MAX_VOLUME;\n\n\tAudioManager.SetMP3BoostVolume(vol);\n}\n\nvoid\ncDMAudio::SetEffectsMasterVolume(uint8 volume)\n{\n\tuint8 vol = volume;\n\tif ( vol > MAX_VOLUME ) vol = MAX_VOLUME;\n\t\n\tAudioManager.SetEffectsMasterVolume(vol);\n}\n\nvoid\ncDMAudio::SetMusicMasterVolume(uint8 volume)\n{\n\tuint8 vol = volume;\n\tif ( vol > MAX_VOLUME ) vol = MAX_VOLUME;\n\t\n\tAudioManager.SetMusicMasterVolume(vol);\n}\n\nvoid\ncDMAudio::SetEffectsFadeVol(uint8 volume)\n{\n\tuint8 vol = volume;\n\tif ( vol > MAX_VOLUME ) vol = MAX_VOLUME;\n\t\n\tAudioManager.SetEffectsFadeVol(vol);\n}\n\nvoid\ncDMAudio::SetMusicFadeVol(uint8 volume)\n{\n\tuint8 vol = volume;\n\tif ( vol > MAX_VOLUME ) vol = MAX_VOLUME;\n\t\n\tAudioManager.SetMusicFadeVol(vol);\n}\n\nuint8\ncDMAudio::GetNum3DProvidersAvailable(void)\n{\n\treturn AudioManager.GetNum3DProvidersAvailable();\n}\n\nchar *\ncDMAudio::Get3DProviderName(uint8 id)\n{\n\treturn AudioManager.Get3DProviderName(id);\n}\n\nint8 cDMAudio::AutoDetect3DProviders(void)\n{\n\treturn AudioManager.AutoDetect3DProviders();\n}\n\nint8\ncDMAudio::GetCurrent3DProviderIndex(void)\n{\n\treturn AudioManager.GetCurrent3DProviderIndex();\n}\n\nint8\ncDMAudio::SetCurrent3DProvider(uint8 which)\n{\n\treturn AudioManager.SetCurrent3DProvider(which);\n}\n\nvoid\ncDMAudio::SetSpeakerConfig(int32 config)\n{\n\tAudioManager.SetSpeakerConfig(config);\n}\n\nbool\ncDMAudio::IsMP3RadioChannelAvailable(void)\n{\n\treturn AudioManager.IsMP3RadioChannelAvailable();\n}\n\nvoid\ncDMAudio::ReleaseDigitalHandle(void)\n{\n\tAudioManager.ReleaseDigitalHandle();\n}\n\nvoid\ncDMAudio::ReacquireDigitalHandle(void)\n{\n\tAudioManager.ReacquireDigitalHandle();\n}\n\nvoid\ncDMAudio::SetDynamicAcousticModelingStatus(uint8 status)\n{\n\tAudioManager.SetDynamicAcousticModelingStatus(status);\n}\n\nbool\ncDMAudio::CheckForAnAudioFileOnCD(void)\n{\n\treturn AudioManager.CheckForAnAudioFileOnCD();\n}\n\nchar\ncDMAudio::GetCDAudioDriveLetter(void)\n{\n\treturn AudioManager.GetCDAudioDriveLetter();\n}\n\nbool\ncDMAudio::IsAudioInitialised(void)\n{\n\treturn AudioManager.IsAudioInitialised();\n}\n\nvoid\ncDMAudio::ReportCrime(eCrimeType crime, const CVector &pos)\n{\n\tAudioManager.ReportCrime(crime, pos);\n}\n\nint32\ncDMAudio::CreateLoopingScriptObject(cAudioScriptObject *scriptObject)\n{\n\tint32 audioEntity = AudioManager.CreateEntity(AUDIOTYPE_SCRIPTOBJECT, scriptObject);\n\n\tif ( AEHANDLE_IS_OK(audioEntity) )\n\t\tAudioManager.SetEntityStatus(audioEntity, true);\n\t\n\treturn audioEntity;\n}\n\nvoid\ncDMAudio::DestroyLoopingScriptObject(int32 audioEntity)\n{\n\tAudioManager.DestroyEntity(audioEntity);\n}\n\nvoid\ncDMAudio::CreateOneShotScriptObject(cAudioScriptObject *scriptObject)\n{\n\tint32 audioEntity = AudioManager.CreateEntity(AUDIOTYPE_SCRIPTOBJECT, scriptObject);\n\n\tif ( AEHANDLE_IS_OK(audioEntity) )\n\t{\n\t\tAudioManager.SetEntityStatus(audioEntity, true);\n\t\tAudioManager.PlayOneShot(audioEntity, scriptObject->AudioId, 0.0f);\n\t}\n}\n\nvoid\ncDMAudio::PlaySuspectLastSeen(float x, float y, float z)\n{\n\tAudioManager.PlaySuspectLastSeen(x, y, z);\n}\n\nvoid\ncDMAudio::ReportCollision(CEntity *entityA, CEntity *entityB, uint8 surfaceTypeA, uint8 surfaceTypeB, float collisionPower, float velocity)\n{\n\tAudioManager.ReportCollision(entityA, entityB, surfaceTypeA, surfaceTypeB, collisionPower, velocity);\n}\n\nvoid\ncDMAudio::PlayFrontEndSound(uint16 frontend, uint32 volume)\n{\n\tAudioManager.PlayOneShot(AudioManager.m_nFrontEndEntity, frontend, (float)volume);\n}\n\nvoid\ncDMAudio::PlayRadioAnnouncement(uint32 announcement)\n{\n\tMusicManager.PlayAnnouncement(announcement);\n}\n\nvoid\ncDMAudio::PlayFrontEndTrack(uint32 track, uint8 frontendFlag)\n{\n\tMusicManager.PlayFrontEndTrack(track, frontendFlag);\n}\n\nvoid\ncDMAudio::StopFrontEndTrack(void)\n{\n\tMusicManager.StopFrontEndTrack();\n}\n\nvoid\ncDMAudio::ResetTimers(uint32 time)\n{\n\tAudioManager.ResetTimers(time);\n}\n\nvoid\ncDMAudio::ChangeMusicMode(uint8 mode)\n{\n\tMusicManager.ChangeMusicMode(mode);\n}\n\nvoid\ncDMAudio::PreloadCutSceneMusic(uint32 track)\n{\n\tMusicManager.PreloadCutSceneMusic(track);\n}\n\nvoid\ncDMAudio::PlayPreloadedCutSceneMusic(void)\n{\n\tMusicManager.PlayPreloadedCutSceneMusic();\n}\n\nvoid\ncDMAudio::StopCutSceneMusic(void)\n{\n\tMusicManager.StopCutSceneMusic();\n}\n\nvoid\ncDMAudio::PreloadMissionAudio(uint8 slot, Const char *missionAudio)\n{\n\tAudioManager.PreloadMissionAudio(slot, missionAudio);\n}\n\nuint8\ncDMAudio::GetMissionAudioLoadingStatus(uint8 slot)\n{\n\treturn AudioManager.GetMissionAudioLoadingStatus(slot);\n}\n\nvoid\ncDMAudio::SetMissionAudioLocation(uint8 slot, float x, float y, float z)\n{\n\tAudioManager.SetMissionAudioLocation(slot, x, y, z);\n}\n\nvoid\ncDMAudio::PlayLoadedMissionAudio(uint8 slot)\n{\n\tAudioManager.PlayLoadedMissionAudio(slot);\n}\n\nbool\ncDMAudio::IsMissionAudioSampleFinished(uint8 slot)\n{\n\treturn AudioManager.IsMissionAudioSampleFinished(slot);\n}\n\nvoid\ncDMAudio::ClearMissionAudio(uint8 slot)\n{\n\tAudioManager.ClearMissionAudio(slot);\n}\n\nuint8\ncDMAudio::GetRadioInCar(void)\n{\n\treturn MusicManager.GetRadioInCar();\n}\n\nvoid\ncDMAudio::SetRadioInCar(uint32 radio)\n{\n\tMusicManager.SetRadioInCar(radio);\n}\n\nvoid\ncDMAudio::SetRadioChannel(uint32 radio, int32 pos)\n{\n\tMusicManager.SetRadioChannelByScript(radio, pos);\n}\n\nvoid\ncDMAudio::SetStartingTrackPositions(uint8 isStartGame)\n{\n\tMusicManager.SetStartingTrackPositions(isStartGame);\n}\n\nfloat *\ncDMAudio::GetListenTimeArray()\n{\n\treturn MusicManager.GetListenTimeArray();\n}\n\nuint32\ncDMAudio::GetFavouriteRadioStation()\n{\n\treturn MusicManager.GetFavouriteRadioStation();\n}\n\nint32\ncDMAudio::GetRadioPosition(uint32 station)\n{\n\treturn MusicManager.GetRadioPosition(station);\n}\n\nvoid\ncDMAudio::SetPedTalkingStatus(CPed *ped, uint8 status)\n{\n\treturn AudioManager.SetPedTalkingStatus(ped, status);\n}\n\nvoid\ncDMAudio::SetPlayersMood(uint8 mood, uint32 time)\n{\n\treturn AudioManager.SetPlayersMood(mood, time);\n}\n\nvoid\ncDMAudio::ShutUpPlayerTalking(uint8 state)\n{\n\tAudioManager.m_bIsPlayerShutUp = state;\n}"
  },
  {
    "path": "src/audio/DMAudio.h",
    "content": "#pragma once\n\n#include \"audio_enums.h\"\n#include \"soundlist.h\"\n#include \"Crime.h\"\n\n#define AEHANDLE_IS_FAILED(h) ((h)<0)\n#define AEHANDLE_IS_OK(h)     ((h)>=0)\n\n#define NO_AUDIO_PROVIDER -3\n#define AUDIO_PROVIDER_NOT_DETERMINED -99\n\nclass cAudioScriptObject;\nclass CEntity;\n\nclass cDMAudio\n{\npublic:\n\t~cDMAudio()\n\t{ }\n\n\tvoid Initialise(void);\n\tvoid Terminate(void);\n\tvoid Service(void);\n\t\n\tint32 CreateEntity(eAudioType type, void *UID);\n\tvoid DestroyEntity(int32 audioEntity);\n\tvoid SetEntityStatus(int32 audioEntity, uint8 status);\n\tvoid PlayOneShot(int32 audioEntity, uint16 oneShot, float volume);\n\tvoid DestroyAllGameCreatedEntities(void);\n\t\n\tvoid SetMonoMode(uint8 mono);\n\tvoid SetMP3BoostVolume(uint8 volume);\n\tvoid SetEffectsMasterVolume(uint8 volume);\n\tvoid SetMusicMasterVolume(uint8 volume);\n\tvoid SetEffectsFadeVol(uint8 volume);\n\tvoid SetMusicFadeVol(uint8 volume);\n\t\n\tuint8 GetNum3DProvidersAvailable(void);\n\tchar *Get3DProviderName(uint8 id);\n\t\n\tint8 AutoDetect3DProviders(void);\n\t\n\tint8 GetCurrent3DProviderIndex(void);\n\tint8 SetCurrent3DProvider(uint8 which);\n\t\n\tvoid SetSpeakerConfig(int32 config);\n\t\n\tbool IsMP3RadioChannelAvailable(void);\n\t\n\tvoid ReleaseDigitalHandle(void);\n\tvoid ReacquireDigitalHandle(void);\n\t\n\tvoid SetDynamicAcousticModelingStatus(uint8 status);\n\t\n\tbool CheckForAnAudioFileOnCD(void);\n\t\n\tchar GetCDAudioDriveLetter(void);\n\tbool IsAudioInitialised(void);\n\t\n\tvoid ReportCrime(eCrimeType crime, CVector const &pos);\n\t\n\tint32 CreateLoopingScriptObject(cAudioScriptObject *scriptObject);\n\tvoid DestroyLoopingScriptObject(int32 audioEntity);\n\tvoid CreateOneShotScriptObject(cAudioScriptObject *scriptObject);\n\t\n\tvoid PlaySuspectLastSeen(float x, float y, float z);\n\t\n\tvoid ReportCollision(CEntity *entityA, CEntity *entityB, uint8 surfaceTypeA, uint8 surfaceTypeB, float collisionPower, float velocity);\n\t\n\tvoid PlayFrontEndSound(uint16 frontend, uint32 volume);\n\tvoid PlayRadioAnnouncement(uint32 announcement);\n\tvoid PlayFrontEndTrack(uint32 track, uint8 frontendFlag);\n\tvoid StopFrontEndTrack(void);\n\t\n\tvoid ResetTimers(uint32 time);\n\t\n\tvoid ChangeMusicMode(uint8 mode);\n\t\n\tvoid PreloadCutSceneMusic(uint32 track);\n\tvoid PlayPreloadedCutSceneMusic(void);\n\tvoid StopCutSceneMusic(void);\n\t\n\tvoid PreloadMissionAudio(uint8 slot, Const char *missionAudio);\n\tuint8 GetMissionAudioLoadingStatus(uint8 slot);\n\tvoid SetMissionAudioLocation(uint8 slot, float x, float y, float z);\n\tvoid PlayLoadedMissionAudio(uint8 slot);\n\tbool IsMissionAudioSampleFinished(uint8 slot);\n\tvoid ClearMissionAudio(uint8 slot);\n\n\tuint8 GetRadioInCar(void);\n\tvoid SetRadioInCar(uint32 radio);\n\tvoid SetRadioChannel(uint32 radio, int32 pos);\n\n\tvoid SetStartingTrackPositions(uint8 isStartGame);\n\tfloat *GetListenTimeArray();\n\tuint32 GetFavouriteRadioStation();\n\tint32 GetRadioPosition(uint32 station);\n\tvoid SetPedTalkingStatus(class CPed *ped, uint8 status);\n\tvoid SetPlayersMood(uint8 mood, uint32 time);\n\tvoid ShutUpPlayerTalking(uint8 state);\n};\nextern cDMAudio DMAudio;\n"
  },
  {
    "path": "src/audio/MusicManager.cpp",
    "content": "#include \"common.h\"\n#include <time.h>\n#include \"soundlist.h\"\n#include \"MusicManager.h\"\n#include \"AudioManager.h\"\n#include \"ControllerConfig.h\"\n#include \"Camera.h\"\n#include \"Font.h\"\n#include \"Hud.h\"\n#include \"ModelIndices.h\"\n#include \"Replay.h\"\n#include \"Pad.h\"\n#include \"Text.h\"\n#include \"Timer.h\"\n#include \"World.h\"\n#include \"sampman.h\"\n#include \"Stats.h\"\n#include \"Script.h\"\n#include \"ZoneCull.h\"\n#include \"Weather.h\"\n#include \"DMAudio.h\"\n#include \"GenericGameStorage.h\"\n\n#if !defined FIX_BUGS && (defined RADIO_SCROLL_TO_PREV_STATION || defined RADIO_OFF_TEXT)\nstatic_assert(false, \"R*'s radio implementation is quite buggy, RADIO_SCROLL_TO_PREV_STATION and RADIO_OFF_TEXT won't work without FIX_BUGS\");\n#endif\n\ncMusicManager MusicManager;\nint32 gNumRetunePresses;\nint32 gRetuneCounter;\nbool g_bAnnouncementReadPosAlready;\nuint8 RadioStaticCounter = 5;\nuint32 RadioStaticTimer;\n\nCVector vecRiotPosition(300.7f, -322.0f, 12.0f);\n\nuint32 NewGameRadioTimers[10] =\n{\n\t948160,\n\t452150,\n\t2438150,\n\t3538230,\n\t3513100,\n\t4246050,\n\t1418050,\n\t3178240,\n\t471210,\n\t0\n};\n\ncMusicManager::cMusicManager()\n{\n\tm_bIsInitialised = false;\n\tm_bDisabled = false;\n\tm_nFrontendTrack = NO_TRACK;\n\tm_nPlayingTrack = NO_TRACK;\n\tm_nUpcomingMusicMode = MUSICMODE_DISABLED;\n\tm_nMusicMode = MUSICMODE_DISABLED;\n\tm_bSetNextStation = false;\n\n\tfor (int i = 0; i < NUM_RADIOS; i++)\n\t\taListenTimeArray[i] = 0.0f;\n\n\tm_nLastTrackServiceTime = 0.0f;\n\tm_nVolumeLatency = 0;\n\tm_nCurrentVolume = 0;\n\tm_nMaxVolume = 0;\n\tm_nAnnouncement = NO_TRACK;\n\tm_bAnnouncementInProgress = false;\n}\n\nvoid\ncMusicManager::ResetMusicAfterReload()\n{\n\tfloat afRadioTime[NUM_RADIOS];\n\n\tm_bRadioSetByScript = false;\n\tm_nRadioStationScript = WILDSTYLE;\n\tm_nRadioPosition = -1;\n\tm_nAnnouncement = NO_TRACK;\n\tm_bAnnouncementInProgress = false;\n\tm_bSetNextStation = false;\n\tRadioStaticTimer = 0;\n\tgNumRetunePresses = 0;\n\tgRetuneCounter = 0;\n\tm_nFrontendTrack = NO_TRACK;\n\tm_nPlayingTrack = NO_TRACK;\n\tm_FrontendLoopFlag = false;\n\tm_bTrackChangeStarted = false;\n\tm_nNextTrack = NO_TRACK;\n\tm_nNextLoopFlag = false;\n\tm_bVerifyNextTrackStartedToPlay = false;\n\tm_bGameplayAllowsRadio = false;\n\tm_bRadioStreamReady = false;\n\tnFramesSinceCutsceneEnded = -1;\n\tm_bUserResumedGame = false;\n\tm_bMusicModeChangeStarted = false;\n\tm_bEarlyFrontendTrack = false;\n\tm_nVolumeLatency = 0;\n\tm_nCurrentVolume = 0;\n\tm_nMaxVolume = 0;\n\n\tbool bRadioWasEverListened = false;\n\n\tfor (int i = 0; i < NUM_RADIOS; i++) {\n\t\tafRadioTime[i] = CStats::GetFavoriteRadioStationList(i);\n\t\tif (!bRadioWasEverListened && afRadioTime[i] != 0.0f)\n\t\t\tbRadioWasEverListened = true;\n\t}\n\n\tif (!bRadioWasEverListened) return;\n\n\tfor (int i = 0; i < NUM_RADIOS; i++) {\n\t\taListenTimeArray[i] = afRadioTime[i];\n\t\tint32 trackPos = GetSavedRadioStationPosition(i);\n\t\tif (trackPos != -1) {\n\t\t\tif (trackPos > m_aTracks[i].m_nLength) {\n\t\t\t\tdebug(\"Radio Track %d saved position is %d, Length is only %d\\n\", i, trackPos, m_aTracks[i].m_nLength);\n\t\t\t\ttrackPos %= m_aTracks[i].m_nLength;\n\t\t\t}\n\t\t\tm_aTracks[i].m_nPosition = trackPos;\n\t\t\tm_aTracks[i].m_nLastPosCheckTimer = CTimer::GetTimeInMillisecondsPauseMode();\n\t\t}\n\t}\n}\n\nvoid\ncMusicManager::SetStartingTrackPositions(uint8 isNewGameTimer)\n{\n\tint pos;\n\n\tif (IsInitialised()) {\n\t\ttime_t timevalue = time(0);\n\t\tif (timevalue == -1) {\n\t\t\tpos = AudioManager.GetRandomNumber(0);\n\t\t} else {\n\t\t\ttm* pTm = localtime(&timevalue);\n\t\t\tif (pTm->tm_sec == 0)\n\t\t\t\tpTm->tm_sec = AudioManager.GetRandomNumber(0);\n\t\t\tif (pTm->tm_min == 0)\n\t\t\t\tpTm->tm_min = AudioManager.GetRandomNumber(1);\n\t\t\tif (pTm->tm_hour == 0)\n\t\t\t\tpTm->tm_hour = AudioManager.GetRandomNumber(2);\n\t\t\tif (pTm->tm_mday == 0)\n\t\t\t\tpTm->tm_mday = AudioManager.GetRandomNumber(3);\n\t\t\tif (pTm->tm_mon == 0)\n\t\t\t\tpTm->tm_mon = AudioManager.GetRandomNumber(4);\n\t\t\tif (pTm->tm_year == 0)\n\t\t\t\tpTm->tm_year = AudioManager.GetRandomNumber(3);\n\t\t\tif (pTm->tm_wday == 0)\n\t\t\t\tpTm->tm_wday = AudioManager.GetRandomNumber(2);\n\t\t\tpos = pTm->tm_yday\n\t\t\t\t* pTm->tm_wday\n\t\t\t\t* pTm->tm_year\n\t\t\t\t* pTm->tm_mon\n\t\t\t\t* pTm->tm_mday\n\t\t\t\t* pTm->tm_hour * pTm->tm_hour\n\t\t\t\t* pTm->tm_min * pTm->tm_min\n\t\t\t\t* pTm->tm_sec * pTm->tm_sec * pTm->tm_sec * pTm->tm_sec;\n\t\t}\n\n\t\tfor (int i = 0; i < TOTAL_STREAMED_SOUNDS; i++) {\n\t\t\tm_aTracks[i].m_nLength = SampleManager.GetStreamedFileLength(i);\n\n\t\t\tif (i < STREAMED_SOUND_CITY_AMBIENT && isNewGameTimer)\n\t\t\t\tm_aTracks[i].m_nPosition = NewGameRadioTimers[i];\n\t\t\telse if (i < STREAMED_SOUND_ANNOUNCE_BRIDGE_CLOSED)\n\t\t\t\tm_aTracks[i].m_nPosition = (pos * AudioManager.GetRandomNumber(i % 5)) % m_aTracks[i].m_nLength;\n\t\t\telse\n\t\t\t\tm_aTracks[i].m_nPosition = 0;\n\t\t\t\n\t\t\tm_aTracks[i].m_nLastPosCheckTimer = CTimer::GetTimeInMillisecondsPauseMode();\n\t\t}\n\t}\n}\n\nbool\ncMusicManager::Initialise()\n{\n\tif (!IsInitialised()) {\n\t\tm_bIsInitialised = true;\n\t\tSetStartingTrackPositions(false);\n\t\tm_bResetTimers = false;\n\t\tm_nResetTime = 0;\n\t\tm_bRadioSetByScript = false;\n\t\tm_nRadioStationScript = WILDSTYLE;\n\t\tm_nRadioPosition = -1;\n\t\tm_nRadioInCar = NO_TRACK;\n\t\tgRetuneCounter = 0;\n\t\tgNumRetunePresses = 0;\n\t\tm_nFrontendTrack = NO_TRACK;\n\t\tm_nPlayingTrack = NO_TRACK;\n\t\tm_nUpcomingMusicMode = MUSICMODE_DISABLED;\n\t\tm_nMusicMode = MUSICMODE_DISABLED;\n\t\tm_FrontendLoopFlag = false;\n\t\tm_bTrackChangeStarted = false;\n\t\tm_nNextTrack = NO_TRACK;\n\t\tm_nNextLoopFlag = false;\n\t\tm_bVerifyNextTrackStartedToPlay = false;\n\t\tm_bGameplayAllowsRadio = false;\n\t\tm_bRadioStreamReady = false;\n\t\tnFramesSinceCutsceneEnded = -1;\n\t\tm_bUserResumedGame = false;\n\t\tm_bMusicModeChangeStarted = false;\n\t\tm_nMusicModeToBeSet = MUSICMODE_DISABLED;\n\t\tm_bEarlyFrontendTrack = false;\n\t\tm_nVolumeLatency = 0;\n\t\tm_nCurrentVolume = 0;\n\t\tm_nMaxVolume = 0;\n\t}\n\treturn m_bIsInitialised;\n}\n\nvoid\ncMusicManager::Terminate()\n{\n\tif (!IsInitialised()) return;\n\n\tif (SampleManager.IsStreamPlaying(0)) {\n\t\tSampleManager.StopStreamedFile(0);\n\t\tm_nPlayingTrack = NO_TRACK;\n\t}\n\tm_bIsInitialised = false;\n}\n\nvoid\ncMusicManager::SetRadioChannelByScript(uint32 station, int32 pos)\n{\n\tif (m_bIsInitialised) {\n\t\tif (station == STREAMED_SOUND_RADIO_MP3_PLAYER)\n\t\t\tstation = STREAMED_SOUND_CITY_AMBIENT;\n\t\tif (station <= STREAMED_SOUND_RADIO_POLICE) {\n\t\t\tm_bRadioSetByScript = true;\n\t\t\tm_nRadioStationScript = station;\n\t\t\tm_nRadioPosition = pos == -1 ? -1 : pos % m_aTracks[station].m_nLength;\n\t\t}\n\t}\n}\n\nbool\ncMusicManager::PlayerInCar()\n{\n\tCVehicle *vehicle = AudioManager.FindVehicleOfPlayer();\n\tif(!vehicle)\n\t\treturn false;\n\n\tint32 State = FindPlayerPed()->m_nPedState;\n\n\tif(State == PED_DRAG_FROM_CAR || State == PED_EXIT_CAR || State == PED_ARRESTED)\n\t\treturn false;\n\n\tif (vehicle->GetStatus() == STATUS_WRECKED)\n\t\treturn false;\n\n\treturn true;\n}\n\nuint32\ncMusicManager::GetRadioInCar(void)\n{\n\tif (!m_bIsInitialised) return WILDSTYLE;\n\tif (PlayerInCar()) {\n\t\tCVehicle* veh = AudioManager.FindVehicleOfPlayer();\n\t\tif (veh != nil) {\n\t\t\tif (UsesPoliceRadio(veh) || UsesTaxiRadio(veh)) {\n\t\t\t\tif (m_nRadioInCar == NO_TRACK || (CReplay::IsPlayingBack() && AudioManager.m_nUserPause == 0))\n\t\t\t\t\treturn STREAMED_SOUND_RADIO_POLICE;\n\t\t\t\treturn m_nRadioInCar;\n\t\t\t}\n\t\t\telse return veh->m_nRadioStation;\n\t\t}\n\t}\n\n\tif (m_nRadioInCar == NO_TRACK || (CReplay::IsPlayingBack() && AudioManager.m_nUserPause == 0))\n\t\treturn RADIO_OFF;\n\treturn m_nRadioInCar;\n}\n\nvoid\ncMusicManager::SetRadioInCar(uint32 station)\n{\n\tif (m_bIsInitialised) {\n\t\tif (!PlayerInCar()) {\n\t\t\tm_nRadioInCar = station;\n\t\t\treturn;\n\t\t}\n\t\tCVehicle* veh = AudioManager.FindVehicleOfPlayer();\n\t\tif (veh == nil) return;\n\t\tif (UsesPoliceRadio(veh) || UsesTaxiRadio(veh))\n\t\t\tm_nRadioInCar = station;\n\t\telse\n\t\t\tveh->m_nRadioStation = station;\n\t}\n}\n\nvoid\ncMusicManager::RecordRadioStats()\n{\n\tif (m_nPlayingTrack < NUM_RADIOS) {\n\t\tdouble time /*Rusty*/ = CTimer::GetTimeInMillisecondsPauseMode();\n\t\tif (time > m_nLastTrackServiceTime)\n\t\t\taListenTimeArray[m_nPlayingTrack] += time - m_nLastTrackServiceTime;\n\t}\n}\n\nvoid\ncMusicManager::ChangeMusicMode(uint8 mode)\n{\n\tif (!IsInitialised()) return;\n\n\tswitch (mode)\n\t{\n\tcase MUSICMODE_FRONTEND: m_nUpcomingMusicMode = MUSICMODE_FRONTEND; break;\n\tcase MUSICMODE_GAME: m_nUpcomingMusicMode = MUSICMODE_GAME; break;\n\tcase MUSICMODE_CUTSCENE:\n\t\tm_nUpcomingMusicMode = MUSICMODE_CUTSCENE;\n\t\tif (SampleManager.IsStreamPlaying(0)) {\n\t\t\tif (m_nPlayingTrack != NO_TRACK) {\n\t\t\t\tRecordRadioStats();\n\t\t\t\tm_aTracks[m_nPlayingTrack].m_nPosition = SampleManager.GetStreamedFilePosition(0);\n\t\t\t\tm_aTracks[m_nPlayingTrack].m_nLastPosCheckTimer = CTimer::GetTimeInMillisecondsPauseMode();\n\t\t\t}\n\t\t}\n\t\tSampleManager.StopStreamedFile(0);\n\t\twhile (SampleManager.IsStreamPlaying(0))\n\t\t\tSampleManager.StopStreamedFile(0);\n\t\tm_nMusicMode = m_nUpcomingMusicMode;\n\t\tm_bMusicModeChangeStarted = false;\n\t\tm_bTrackChangeStarted = false;\n\t\tm_nNextTrack = NO_TRACK;\n\t\tm_nNextLoopFlag = false;\n\t\tm_bVerifyNextTrackStartedToPlay = false;\n\t\tm_nPlayingTrack = NO_TRACK;\n\t\tm_nFrontendTrack = NO_TRACK;\n\t\tm_bAnnouncementInProgress = false;\n\t\tm_nAnnouncement = NO_TRACK;\n\t\tg_bAnnouncementReadPosAlready = false;\n\t\tbreak;\n\tcase MUSICMODE_DISABLE: m_nUpcomingMusicMode = MUSICMODE_DISABLED; break;\n\tdefault: return;\n\t}\n}\n\nvoid\ncMusicManager::ResetTimers(int32 time)\n{\n\tm_bResetTimers = true;\n\tm_nResetTime = time;\n}\n\nvoid\ncMusicManager::Service()\n{\n\tif (m_bResetTimers) {\n\t\tm_bResetTimers = false;\n\t\tm_nLastTrackServiceTime = m_nResetTime;\n\t}\n\n\tstatic bool bRadioStatsRecorded = false;\n\n\tif (!m_bIsInitialised || m_bDisabled) return;\n\n\tif (!m_bMusicModeChangeStarted)\n\t\tm_nMusicModeToBeSet = m_nUpcomingMusicMode;\n\tif (m_nMusicModeToBeSet == m_nMusicMode) {\n\t\tif (!AudioManager.m_nUserPause || AudioManager.m_nPreviousUserPause || m_nMusicMode != MUSICMODE_FRONTEND)\n\t\t{\n\t\t\tswitch (m_nMusicMode)\n\t\t\t{\n\t\t\tcase MUSICMODE_FRONTEND: ServiceFrontEndMode(); break;\n\t\t\tcase MUSICMODE_GAME: ServiceGameMode(); break;\n\t\t\tcase MUSICMODE_CUTSCENE: SampleManager.SetStreamedVolumeAndPan(MAX_VOLUME, 63, 1, 0); break;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t\tm_nMusicMode = MUSICMODE_DISABLED;\n\t} else {\n\t\tm_bMusicModeChangeStarted = true;\n\t\tif (!m_bUserResumedGame && !AudioManager.m_nUserPause && AudioManager.m_nPreviousUserPause)\n\t\t\tm_bUserResumedGame = true;\n\t\tif (AudioManager.m_FrameCounter % 4 == 0) {\n\t\t\tgNumRetunePresses = 0;\n\t\t\tgRetuneCounter = 0;\n\t\t\tm_bSetNextStation = false;\n\t\t\tif (SampleManager.IsStreamPlaying(0)) {\n\t\t\t\tif (m_nPlayingTrack != NO_TRACK && !bRadioStatsRecorded)\n\t\t\t\t{\n\t\t\t\t\tRecordRadioStats();\n\t\t\t\t\tm_aTracks[m_nPlayingTrack].m_nPosition = SampleManager.GetStreamedFilePosition(0);\n\t\t\t\t\tm_aTracks[m_nPlayingTrack].m_nLastPosCheckTimer = CTimer::GetTimeInMillisecondsPauseMode();\n\t\t\t\t\tbRadioStatsRecorded = true;\n\t\t\t\t}\n\t\t\t\tSampleManager.StopStreamedFile(0);\n\t\t\t} else {\n\t\t\t\tbRadioStatsRecorded = false;\n\t\t\t\tm_nMusicMode = m_nMusicModeToBeSet;\n\t\t\t\tm_bMusicModeChangeStarted = false;\n\t\t\t\tm_bTrackChangeStarted = false;\n\t\t\t\tm_nNextTrack = NO_TRACK;\n\t\t\t\tm_nNextLoopFlag = false;\n\t\t\t\tm_bVerifyNextTrackStartedToPlay = false;\n\t\t\t\tm_nPlayingTrack = NO_TRACK;\n\t\t\t\tif (m_bEarlyFrontendTrack)\n\t\t\t\t\tm_bEarlyFrontendTrack = false;\n\t\t\t\telse\n\t\t\t\t\tm_nFrontendTrack = NO_TRACK;\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\ncMusicManager::ServiceFrontEndMode()\n{\n\tstatic bool bRadioStatsRecorded = false;\n\n\tif (m_bAnnouncementInProgress) {\n\t\tSampleManager.StopStreamedFile(0);\n\t\tif (SampleManager.IsStreamPlaying(0))\n\t\t\treturn;\n\t\tg_bAnnouncementReadPosAlready = false;\n\t\tm_nAnnouncement = NO_TRACK;\n\t\tm_bAnnouncementInProgress = false;\n\t\tm_nNextTrack = NO_TRACK;\n\t\tm_nFrontendTrack = NO_TRACK;\n\t\tm_nPlayingTrack = NO_TRACK;\n\t}\n\n\tif (AudioManager.m_FrameCounter % 4 != 0) return;\n\n\tif (!m_bTrackChangeStarted && !m_bVerifyNextTrackStartedToPlay) {\n\t\tm_nNextTrack = m_nFrontendTrack;\n\t\tm_nNextLoopFlag = m_FrontendLoopFlag;\n\t}\n\n\tif (m_nNextTrack == m_nPlayingTrack) {\n\t\tif (SampleManager.IsStreamPlaying(0)) {\n\t\t\tif (m_nVolumeLatency > 0) m_nVolumeLatency--;\n\t\t\telse {\n\t\t\t\tif (m_nCurrentVolume < m_nMaxVolume)\n\t\t\t\t\tm_nCurrentVolume = Min(m_nMaxVolume, m_nCurrentVolume + 6);\n\t\t\t\tSampleManager.SetStreamedVolumeAndPan(m_nCurrentVolume, 63, 0, 0);\n\t\t\t}\n\t\t} else {\n\t\t\tif (m_nPlayingTrack == STREAMED_SOUND_RADIO_MP3_PLAYER)\n\t\t\t\tSampleManager.StartStreamedFile(STREAMED_SOUND_RADIO_MP3_PLAYER, 0, 0);\n\t\t\telse if (m_nPlayingTrack == STREAMED_SOUND_MISSION_COMPLETED && AudioManager.m_nUserPause == 0)\n\t\t\t\tChangeMusicMode(MUSICMODE_GAME);\n\t\t}\n\t} else {\n\t\tm_bTrackChangeStarted = true;\n\t\tif (m_bVerifyNextTrackStartedToPlay || !SampleManager.IsStreamPlaying(0)) {\n\t\t\tbRadioStatsRecorded = false;\n\t\t\tif (SampleManager.IsStreamPlaying(0) || m_nNextTrack == NO_TRACK) {\n\t\t\t\tm_nPlayingTrack = m_nNextTrack;\n\t\t\t\tm_bVerifyNextTrackStartedToPlay = false;\n\t\t\t\tm_bTrackChangeStarted = false;\n\t\t\t} else {\n\t\t\t\tuint32 trackStartPos = (m_nNextTrack > STREAMED_SOUND_RADIO_POLICE) ? 0 : GetTrackStartPos(m_nNextTrack);\n\t\t\t\tif (m_nNextTrack != NO_TRACK) {\n\t\t\t\t\tSampleManager.SetStreamedFileLoopFlag(m_nNextLoopFlag, 0);\n\t\t\t\t\tSampleManager.StartStreamedFile(m_nNextTrack, trackStartPos, 0);\n\t\t\t\t\tm_nVolumeLatency = 3;\n\t\t\t\t\tm_nCurrentVolume = 0;\n\t\t\t\t\tm_nMaxVolume = 100;\n\t\t\t\t\tSampleManager.SetStreamedVolumeAndPan(m_nCurrentVolume, 63, 0, 0);\n\t\t\t\t\tif (m_nNextTrack < STREAMED_SOUND_CITY_AMBIENT)\n\t\t\t\t\t\tm_nLastTrackServiceTime = CTimer::GetTimeInMillisecondsPauseMode();\n\t\t\t\t\tm_bVerifyNextTrackStartedToPlay = true;\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tif (m_nPlayingTrack != NO_TRACK && !bRadioStatsRecorded) {\n\t\t\t\tm_aTracks[m_nPlayingTrack].m_nPosition = SampleManager.GetStreamedFilePosition(0);\n\t\t\t\tm_aTracks[m_nPlayingTrack].m_nLastPosCheckTimer = CTimer::GetTimeInMillisecondsPauseMode();\n\t\t\t\tRecordRadioStats();\n\t\t\t\tbRadioStatsRecorded = true;\n\t\t\t}\n\t\t\tSampleManager.SetStreamedVolumeAndPan(0, 63, 0, 0);\n\t\t\tSampleManager.StopStreamedFile(0);\n\t\t}\n\t}\n}\n\nvoid\ncMusicManager::ServiceGameMode()\n{\n\tCPed *ped = FindPlayerPed();\n\tCVehicle *vehicle = AudioManager.FindVehicleOfPlayer();\n\tm_bRadioStreamReady = m_bGameplayAllowsRadio;\n\tm_bGameplayAllowsRadio = false;\n\n\tswitch (CGame::currArea)\n\t{\n\tcase AREA_HOTEL:\n\tcase AREA_MALL:\n\tcase AREA_STRIP_CLUB:\n\tcase AREA_DIRT:\n\tcase AREA_BLOOD:\n\tcase AREA_OVALRING:\n\tcase AREA_MALIBU_CLUB:\n\t\tm_bGameplayAllowsRadio = false;\n\t\tbreak;\n\tdefault:\n\t\tif (SampleManager.GetMusicVolume()) {\n\t\t\tif (PlayerInCar())\n\t\t\t\tm_bGameplayAllowsRadio = true;\n\t\t} else\n\t\t\tm_bGameplayAllowsRadio = false;\n\t\tbreak;\n\t}\n\n\tif (!m_bGameplayAllowsRadio) {\n\t\tnFramesSinceCutsceneEnded = -1;\n\t\tgNumRetunePresses = 0;\n\t\tgRetuneCounter = 0;\n\t\tm_bSetNextStation = false;\n\t} else if (ped) {\n\t\tif(!ped->DyingOrDead() && vehicle) {\n#ifdef GTA_PC\n\t\t\tif (SampleManager.IsMP3RadioChannelAvailable()\n\t\t\t\t&& vehicle->m_nRadioStation < USERTRACK\n\t\t\t\t&& ControlsManager.GetIsKeyboardKeyJustDown(rsF9))\n\t\t\t{\n\t\t\t\tif (!UsesPoliceRadio(vehicle) && !UsesTaxiRadio(vehicle)) {\n\t\t\t\t\tgNumRetunePresses = 0;\n\t\t\t\t\tgRetuneCounter = 20;\n\t\t\t\t\tRadioStaticCounter = 0;\n\t\t\t\t\tif (vehicle->m_nRadioStation < USERTRACK)\n\t\t\t\t\t{\n\t\t\t\t\t\tdo\n\t\t\t\t\t\t\t++gNumRetunePresses;\n\t\t\t\t\t\twhile (gNumRetunePresses + vehicle->m_nRadioStation < USERTRACK);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n#endif\n\t\t\tif (CPad::GetPad(0)->ChangeStationJustDown())\n\t\t\t{\n\t\t\t\tif (!UsesPoliceRadio(vehicle) && !UsesTaxiRadio(vehicle)) {\n\t\t\t\t\tgNumRetunePresses++;\n\t\t\t\t\tgRetuneCounter = 20;\n\t\t\t\t\tRadioStaticCounter = 0;\n\t\t\t\t}\n\t\t\t}\n#ifdef RADIO_SCROLL_TO_PREV_STATION\n\t\t\telse if(CPad::GetPad(0)->GetMouseWheelDownJustDown() || CPad::GetPad(0)->GetMouseWheelUpJustDown()) {\n\t\t\t\tif(!UsesPoliceRadio(vehicle) && !UsesTaxiRadio(vehicle)) {\n\t\t\t\t\tint scrollNext = ControlsManager.GetControllerKeyAssociatedWithAction(VEHICLE_CHANGE_RADIO_STATION, MOUSE);\n\t\t\t\t\tint scrollPrev = scrollNext == rsMOUSEWHEELUPBUTTON ? rsMOUSEWHEELDOWNBUTTON\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t: scrollNext == rsMOUSEWHEELDOWNBUTTON ? rsMOUSEWHEELUPBUTTON : -1;\n\n\t\t\t\t\tif(scrollPrev != -1 && !ControlsManager.IsAnyVehicleActionAssignedToMouseKey(scrollPrev)) {\n\t\t\t\t\t\tgNumRetunePresses--;\n\t\t\t\t\t\tgRetuneCounter = 20;\n\t\t\t\t\t\tRadioStaticCounter = 0;\n\t\t\t\t\t\tint track = gNumRetunePresses + vehicle->m_nRadioStation;\n\t\t\t\t\t\twhile(track < 0) track += NUM_RADIOS + 1;\n\t\t\t\t\t\twhile(track >= NUM_RADIOS + 1) track -= NUM_RADIOS + 1;\n\t\t\t\t\t\tif(!DMAudio.IsMP3RadioChannelAvailable() && track == USERTRACK) gNumRetunePresses--;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n#endif\n\t\t}\n\t}\n\n\tif (m_bUserResumedGame)\n\t{\n\t\tm_bRadioStreamReady = false;\n\t\tm_bUserResumedGame = false;\n\t}\n\tif (m_nPlayingTrack == NO_TRACK && m_nFrontendTrack == NO_TRACK)\n\t\tm_bRadioStreamReady = false;\n\n\tif (m_bGameplayAllowsRadio)\n\t{\n\t\tif (!m_bRadioStreamReady)\n\t\t{\n\t\t\tif(vehicle == nil) {\n\t\t\t\tm_nFrontendTrack = STREAMED_SOUND_RADIO_WAVE; // huh?\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif(m_bRadioSetByScript) {\n\t\t\t\tif(UsesPoliceRadio(vehicle))\n\t\t\t\t\tm_nFrontendTrack = STREAMED_SOUND_RADIO_POLICE;\n\t\t\t\telse if(UsesTaxiRadio(vehicle))\n\t\t\t\t\tm_nFrontendTrack = STREAMED_SOUND_RADIO_TAXI;\n\t\t\t\telse {\n\t\t\t\t\tm_nFrontendTrack = m_nRadioStationScript;\n\t\t\t\t\tvehicle->m_nRadioStation = m_nRadioStationScript;\n\t\t\t\t}\n\t\t\t\tif(m_nRadioPosition != -1) {\n\t\t\t\t\tm_aTracks[m_nFrontendTrack].m_nPosition = m_nRadioPosition;\n\t\t\t\t\tm_aTracks[m_nFrontendTrack].m_nLastPosCheckTimer = CTimer::GetTimeInMillisecondsPauseMode();\n\t\t\t\t}\n\t\t\t\tm_bRadioSetByScript = false;\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// This starts the radio when you enter the car.\n\t\t\tm_nFrontendTrack = GetCarTuning();\n\t\t\treturn;\n\t\t}\n\t\tif (m_nAnnouncement < NO_TRACK) {\n\t\t\tif ((m_bAnnouncementInProgress || m_nFrontendTrack == m_nPlayingTrack) && ServiceAnnouncement()) {\n\t\t\t\tif (m_bAnnouncementInProgress) {\n\t\t\t\t\tm_bSetNextStation = false;\n\t\t\t\t\tgNumRetunePresses = 0;\n\t\t\t\t\tgRetuneCounter = 0;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif(m_nAnnouncement == NO_TRACK) {\n\t\t\t\t\tm_nNextTrack = NO_TRACK;\n\t\t\t\t\tm_nFrontendTrack = GetCarTuning();\n\t\t\t\t\tm_bSetNextStation = false;\n\t\t\t\t\tgRetuneCounter = 0;\n\t\t\t\t\tgNumRetunePresses = 0;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (!m_bAnnouncementInProgress\n\t\t\t&& m_nAnnouncement == NO_TRACK\n\t\t\t&& m_nPlayingTrack == STREAMED_SOUND_RADIO_MP3_PLAYER\n\t\t\t&& !SampleManager.IsStreamPlaying(0))\n\t\t{\n\t\t\tSampleManager.StartStreamedFile(STREAMED_SOUND_RADIO_MP3_PLAYER, 0, 0);\n\t\t}\n\n\t\tif (!m_bRadioSetByScript)\n\t\t{\n\t\t\t// Because when you switch radio back and forth, gNumRetunePresses will be 0 but gRetuneCounter won't.\n#ifdef RADIO_SCROLL_TO_PREV_STATION\n\t\t\tif(gRetuneCounter != 0) {\n\t\t\t\tif(gRetuneCounter > 1)\n\t\t\t\t\tgRetuneCounter--;\n\t\t\t\telse if(gRetuneCounter == 1) {\n\t\t\t\t\tm_bSetNextStation = true;\n\t\t\t\t\tgRetuneCounter = 0;\n\t\t\t\t}\n\t\t\t}\n#else\n\t\t\tif (gNumRetunePresses != 0)\n\t\t\t{\n\t\t\t\tif (--gRetuneCounter == 0)\n\t\t\t\t{\n\t\t\t\t\tm_bSetNextStation = true;\n\t\t\t\t\tgRetuneCounter = 0;\n\t\t\t\t}\n\t\t\t}\n#endif\n\t\t\tif (gRetuneCounter)\n\t\t\t{\n\t\t\t\tint32 station = gNumRetunePresses + vehicle->m_nRadioStation;\n#ifdef RADIO_SCROLL_TO_PREV_STATION\n\t\t\t\twhile (station < 0) station += NUM_RADIOS + 1;\n#endif\n\t\t\t\twhile (station >= NUM_RADIOS + 1) station -= NUM_RADIOS + 1;\n\n\t\t\t\t// Scrolling back won't hit here, so increasing isn't problem\n\t\t\t\tif (!DMAudio.IsMP3RadioChannelAvailable() && station == USERTRACK)\n\t\t\t\t{\n\t\t\t\t\t++gNumRetunePresses;\n\t\t\t\t\tstation = RADIO_OFF;\n\t\t\t\t}\n\t\t\t\tif (station == RADIO_OFF)\n\t\t\t\t{\n\t\t\t\t\tif (gRetuneCounter == 19) // One less then what switching radio sets, so runs right after turning off radio\n\t\t\t\t\t{\n\t\t\t\t\t\tAudioManager.PlayOneShot(AudioManager.m_nFrontEndEntity, SOUND_FRONTEND_RADIO_TURN_OFF, 0.0f);\n\t\t\t\t\t\tRadioStaticCounter = 5;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n#ifdef RADIO_SCROLL_TO_PREV_STATION\n\t\t\t\t\tif (vehicle->m_nRadioStation == RADIO_OFF && gRetuneCounter == 19) // Right after turning on the radio\n#else\n\t\t\t\t\tif (station == 0 && gRetuneCounter == 19) // Right after turning on the radio\n#endif\n\t\t\t\t\t\tAudioManager.PlayOneShot(AudioManager.m_nFrontEndEntity, SOUND_FRONTEND_RADIO_TURN_ON, 0.0f);\n\t\t\t\t\tAudioManager.DoPoliceRadioCrackle();\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (RadioStaticCounter < 2 && CTimer::GetTimeInMilliseconds() > RadioStaticTimer + 800)\n\t\t\t{\n\t\t\t\tAudioManager.PlayOneShot(AudioManager.m_nFrontEndEntity, SOUND_RADIO_CHANGE, 0.0f);\n\t\t\t\tRadioStaticCounter++;\n\t\t\t\tRadioStaticTimer = CTimer::GetTimeInMilliseconds();\n\t\t\t}\n\t\t\tif (m_bSetNextStation)\n\t\t\t\tm_nFrontendTrack = GetNextCarTuning();\n\t\t\tif (m_nFrontendTrack >= STREAMED_SOUND_CITY_AMBIENT && m_nFrontendTrack <= STREAMED_SOUND_AMBSIL_AMBIENT)\n\t\t\t\tSetUpCorrectAmbienceTrack();\n\t\t\tServiceTrack(vehicle, ped);\n\t\t\tif (m_bSetNextStation)\n\t\t\t\tm_bSetNextStation = false;\n\t\t\treturn;\n\t\t}\n\t\tif (UsesPoliceRadio(vehicle))\n\t\t\tm_nFrontendTrack = STREAMED_SOUND_RADIO_POLICE;\n\t\telse if (UsesTaxiRadio(vehicle))\n\t\t\tm_nFrontendTrack = STREAMED_SOUND_RADIO_TAXI;\n\t\telse {\n\t\t\tm_nFrontendTrack = m_nRadioStationScript;\n\t\t\tvehicle->m_nRadioStation = m_nRadioStationScript;\n\t\t}\n\n\t\tif (m_nRadioPosition != -1) {\n\t\t\tm_aTracks[m_nFrontendTrack].m_nPosition = m_nRadioPosition;\n\t\t\tm_aTracks[m_nFrontendTrack].m_nLastPosCheckTimer = CTimer::GetTimeInMillisecondsPauseMode();\n\t\t}\n\n\t\tgRetuneCounter = 0;\n\t\tgNumRetunePresses = 0;\n\t\tm_bSetNextStation = false;\n\t\tm_bRadioSetByScript = false;\n\t\tif (m_nFrontendTrack >= STREAMED_SOUND_CITY_AMBIENT && m_nFrontendTrack <= STREAMED_SOUND_AMBSIL_AMBIENT)\n\t\t\tSetUpCorrectAmbienceTrack();\n\t\tServiceTrack(vehicle, ped);\n\t\tif (m_bSetNextStation)\n\t\t\tm_bSetNextStation = false;\n\t\treturn;\n\t}\n\n\tif (m_bAnnouncementInProgress)\n\t{\n\t\tSampleManager.StopStreamedFile(0);\n\t\tif (SampleManager.IsStreamPlaying(0))\n\t\t\treturn;\n\t\tg_bAnnouncementReadPosAlready = false;\n\t\tm_nAnnouncement = NO_TRACK;\n\t\tm_bAnnouncementInProgress = false;\n\t\tm_nNextTrack = NO_TRACK;\n\t\tm_nFrontendTrack = NO_TRACK;\n\t\tm_nPlayingTrack = NO_TRACK;\n\t}\n\tSetUpCorrectAmbienceTrack();\n\tServiceTrack(nil, ped);\n}\n\nvoid\ncMusicManager::SetUpCorrectAmbienceTrack()\n{\n\tswitch (CGame::currArea)\n\t{\n\tcase AREA_MAIN_MAP:\n\tcase AREA_EVERYWHERE:\n\t\tif (CTheScripts::RiotIntensity != 0 && ((TheCamera.GetPosition() - vecRiotPosition).MagnitudeSqr() < SQR(65.0f)))\n\t\t\tm_nFrontendTrack = STREAMED_SOUND_LAW4RIOT_AMBIENT;\n\t\telse if (TheCamera.DistanceToWater <= 90.0f) {\n\t\t\tif (CCullZones::bAtBeachForAudio) {\n\t\t\t\tif (CWeather::OldWeatherType != WEATHER_HURRICANE && CWeather::NewWeatherType != WEATHER_HURRICANE || CWeather::Wind <= 1.0f)\n\t\t\t\t\tm_nFrontendTrack = STREAMED_SOUND_BEACH_AMBIENT;\n\t\t\t\telse\n\t\t\t\t\tm_nFrontendTrack = STREAMED_SOUND_HAVANA_BEACH_AMBIENT;\n\t\t\t}\n\t\t\telse if (CWeather::OldWeatherType != WEATHER_HURRICANE && CWeather::NewWeatherType != WEATHER_HURRICANE || CWeather::Wind <= 1.0f)\n\t\t\t\tm_nFrontendTrack = STREAMED_SOUND_WATER_AMBIENT;\n\t\t\telse\n\t\t\t\tm_nFrontendTrack = STREAMED_SOUND_HAVANA_WATER_AMBIENT;\n\t\t}\n\t\telse if (CWeather::OldWeatherType != WEATHER_HURRICANE && CWeather::NewWeatherType != WEATHER_HURRICANE || CWeather::Wind <= 1.0f)\n\t\t\tm_nFrontendTrack = STREAMED_SOUND_CITY_AMBIENT;\n\t\telse\n\t\t\tm_nFrontendTrack = STREAMED_SOUND_HAVANA_CITY_AMBIENT;\n\t\tbreak;\n\tcase AREA_HOTEL:\n\t\tm_nFrontendTrack = STREAMED_SOUND_HOTEL_AMBIENT;\n\t\tbreak;\n\tcase AREA_MALL:\n\t\tm_nFrontendTrack = STREAMED_SOUND_MALL_AMBIENT;\n\t\tbreak;\n\tcase AREA_STRIP_CLUB:\n\t\tm_nFrontendTrack = STREAMED_SOUND_STRIPCLUB_AMBIENT;\n\t\tbreak;\n\tcase AREA_DIRT:\n\tcase AREA_BLOOD:\n\tcase AREA_OVALRING:\n\t\tm_nFrontendTrack = STREAMED_SOUND_DIRTRING_AMBIENT;\n\t\tbreak;\n\tcase AREA_MALIBU_CLUB:\n\t\tm_nFrontendTrack = STREAMED_SOUND_MALIBU_AMBIENT;\n\t\tbreak;\n\tcase AREA_MANSION:\n\tcase AREA_BANK:\n\tcase AREA_LAWYERS:\n\tcase AREA_COFFEE_SHOP:\n\tcase AREA_CONCERT_HALL:\n\tcase AREA_STUDIO:\n\tcase AREA_RIFLE_RANGE:\n\tcase AREA_BIKER_BAR:\n\tcase AREA_POLICE_STATION:\n\t\tm_nFrontendTrack = STREAMED_SOUND_AMBSIL_AMBIENT;\n\t\tbreak;\n\t}\n}\n\nfloat\nGetHeightScale()\n{\n\tif (TheCamera.GetPosition().z > 20.0f) {\n\t\tif (TheCamera.GetPosition().z < 50.0f)\n\t\t\treturn 1.0f - (TheCamera.GetPosition().z - 20.0f) / 30.0f;\n\t\treturn 0.0f;\n\t}\n\treturn 1.0f;\n}\n\nvoid\ncMusicManager::ComputeAmbienceVol(uint8 reset, uint8& outVolume)\n{\n\tstatic float fVol = 0.0f;\n\n\tfloat fHeightScale = GetHeightScale();\n\n\tif (CTheScripts::RiotIntensity > 0) {\n\t\tfloat distToRiotSq = (TheCamera.GetPosition() - vecRiotPosition).MagnitudeSqr();\n\t\tif (distToRiotSq < SQR(100.0f)) {\n\t\t\tif (distToRiotSq >= SQR(65.0f))\n\t\t\t\toutVolume = (Sqrt(distToRiotSq) - 65.0f) / 35.0f * (127.0f * fHeightScale);\n\t\t\telse if (distToRiotSq >= SQR(20.0f))\n\t\t\t\toutVolume = (CTheScripts::RiotIntensity * (1.0f - (Sqrt(distToRiotSq) - 20.0f) / 45.0f) * (127.0f * fHeightScale)) / MAX_VOLUME;\n\t\t\telse\n\t\t\t\toutVolume = (CTheScripts::RiotIntensity * (127.0f * fHeightScale)) / MAX_VOLUME;\n\t\t\treturn;\n\t\t}\n\t}\n\n\tif (reset)\n\t\tfVol = 0.0f;\n\telse if (fVol < 60.0f) {\n\t\tif ((m_nPlayingTrack >= STREAMED_SOUND_HAVANA_CITY_AMBIENT) && (m_nPlayingTrack <= STREAMED_SOUND_HAVANA_BEACH_AMBIENT))\n\t\t\tfVol += 20.0f;\n\t\telse\n\t\t\tfVol += 1.0f;\n\t\tfVol = Min(fVol, 60.0f);\n\t}\n\n\tif ((m_nPlayingTrack >= STREAMED_SOUND_MALL_AMBIENT) && (m_nPlayingTrack <= STREAMED_SOUND_AMBSIL_AMBIENT)) {\n\t\toutVolume = fVol;\n\t\treturn;\n\t}\n\n\tif (CWeather::OldWeatherType == WEATHER_HURRICANE || CWeather::NewWeatherType == WEATHER_HURRICANE) {\n\t\tif (CWeather::Wind > 1.0f) {\n\t\t\toutVolume = (CWeather::Wind - 1.0f) * fVol;\n\t\t\treturn;\n\t\t}\n\t\tfVol = (1.0f - CWeather::Wind) * fVol;\n\t}\n\t\n\tif (TheCamera.DistanceToWater > 140.0f) {\n\t\toutVolume = fVol;\n\t\treturn;\n\t}\n\n\tif (TheCamera.DistanceToWater > 90.0f) {\n\t\toutVolume = ((TheCamera.DistanceToWater - 90.0f) / 50.0f * fVol * fHeightScale);\n\t\treturn;\n\t}\n\n\tif (TheCamera.DistanceToWater > 40.0f) {\n\t\toutVolume = fVol;\n\t\treturn;\n\t}\n\n\toutVolume = (90.0f - fHeightScale) / 50.0f * fVol;\n}\n\nbool\ncMusicManager::ServiceAnnouncement()\n{\n\tif (m_bAnnouncementInProgress) {\n\t\tif (SampleManager.IsStreamPlaying(0))\n\t\t\tm_nPlayingTrack = m_nNextTrack;\n\t\telse if (m_nPlayingTrack != NO_TRACK) {\n\t\t\tm_nAnnouncement = NO_TRACK;\n\t\t\tm_bAnnouncementInProgress = false;\n\t\t\tm_nPlayingTrack = NO_TRACK;\n\t\t}\n\t\treturn true;\n\t} else if (SampleManager.IsStreamPlaying(0)) {\n\t\tif (m_nPlayingTrack != NO_TRACK && !g_bAnnouncementReadPosAlready) {\n\t\t\tRecordRadioStats();\n\t\t\tm_aTracks[m_nPlayingTrack].m_nPosition = SampleManager.GetStreamedFilePosition(0);\n\t\t\tg_bAnnouncementReadPosAlready = true;\n\t\t\tm_aTracks[m_nPlayingTrack].m_nLastPosCheckTimer = CTimer::GetTimeInMillisecondsPauseMode();\n\t\t}\n\t\tSampleManager.StopStreamedFile(0);\n\t} else {\n\t\tg_bAnnouncementReadPosAlready = false;\n\t\tm_nPlayingTrack = NO_TRACK;\n\t\tm_nNextTrack = m_nAnnouncement;\n\t\tSampleManager.SetStreamedFileLoopFlag(0, 0);\n\t\tSampleManager.StartStreamedFile(m_nNextTrack, 0, 0);\n\t\tSampleManager.SetStreamedVolumeAndPan(MAX_VOLUME, 63, 0, 0);\n\t\tm_bAnnouncementInProgress = true;\n\t}\n\n\treturn true;\n}\n\nvoid\ncMusicManager::ServiceTrack(CVehicle *veh, CPed *ped)\n{\n\tstatic bool bRadioStatsRecorded = false;\n\tstatic bool bRadioStatsRecorded2 = false;\n\tuint8 volume;\n\tif (!m_bTrackChangeStarted)\n\t\tm_nNextTrack = m_nFrontendTrack;\n\tif (gRetuneCounter != 0 || m_bSetNextStation) {\n\t\tif (SampleManager.IsStreamPlaying(0)) {\n\t\t\tif (m_nPlayingTrack != NO_TRACK && !bRadioStatsRecorded) {\n\t\t\t\tm_aTracks[m_nPlayingTrack].m_nPosition = SampleManager.GetStreamedFilePosition(0);\n\t\t\t\tm_aTracks[m_nPlayingTrack].m_nLastPosCheckTimer = CTimer::GetTimeInMillisecondsPauseMode();\n\t\t\t\tRecordRadioStats();\n\t\t\t\tbRadioStatsRecorded = true;\n\t\t\t}\n\t\t\tSampleManager.SetStreamedVolumeAndPan(0, 63, 0, 0);\n\t\t\tSampleManager.StopStreamedFile(0);\n\t\t}\n\t\treturn;\n\t}\n\n\tif (bRadioStatsRecorded) {\n\t\tbRadioStatsRecorded = false;\n\t\tm_nPlayingTrack = NO_TRACK;\n\t}\n\n\tif (m_nNextTrack != m_nPlayingTrack)\n\t{\n\t\tm_bTrackChangeStarted = true;\n\t\tSampleManager.SetStreamedVolumeAndPan(0, 63, 0, 0);\n\t\tif (!(AudioManager.m_FrameCounter & 1)) {\n\t\t\tif (m_bVerifyNextTrackStartedToPlay || !SampleManager.IsStreamPlaying(0)) {\n\t\t\t\tbRadioStatsRecorded2 = false;\n\t\t\t\tif (SampleManager.IsStreamPlaying(0)) {\n\t\t\t\t\tm_nPlayingTrack = m_nNextTrack;\n\t\t\t\t\tm_bVerifyNextTrackStartedToPlay = false;\n\t\t\t\t\tm_bTrackChangeStarted = false;\n\t\t\t\t\tif (veh) {\n#ifdef FIX_BUGS\n\t\t\t\t\t\tif (m_nPlayingTrack >= STREAMED_SOUND_CITY_AMBIENT && m_nPlayingTrack <= STREAMED_SOUND_AMBSIL_AMBIENT)\n\t\t\t\t\t\t\tveh->m_nRadioStation = RADIO_OFF;\n\t\t\t\t\t\telse if (m_nPlayingTrack < STREAMED_SOUND_CITY_AMBIENT)\n\t\t\t\t\t\t\tveh->m_nRadioStation = m_nPlayingTrack;\n#else\n\t\t\t\t\t\tif (veh->m_nRadioStation >= STREAMED_SOUND_CITY_AMBIENT && veh->m_nRadioStation <= STREAMED_SOUND_AMBSIL_AMBIENT)\n\t\t\t\t\t\t\tveh->m_nRadioStation = RADIO_OFF;\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tveh->m_nRadioStation = m_nPlayingTrack;\n#endif\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tuint32 pos = GetTrackStartPos(m_nNextTrack);\n\t\t\t\t\tif (m_nNextTrack != NO_TRACK) {\n\t\t\t\t\t\tSampleManager.SetStreamedFileLoopFlag(1, 0);\n\t\t\t\t\t\tSampleManager.StartStreamedFile(m_nNextTrack, pos, 0);\n\t\t\t\t\t\tif (m_nFrontendTrack < STREAMED_SOUND_CITY_AMBIENT || m_nFrontendTrack > STREAMED_SOUND_AMBSIL_AMBIENT)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tm_nVolumeLatency = 10;\n\t\t\t\t\t\t\tm_nCurrentVolume = 0;\n\t\t\t\t\t\t\tm_nMaxVolume = 100;\n\t\t\t\t\t\t\tSampleManager.SetStreamedVolumeAndPan(m_nCurrentVolume, 63, 0, 0);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tComputeAmbienceVol(true, volume);\n\t\t\t\t\t\t\tSampleManager.SetStreamedVolumeAndPan(volume, 63, 1, 0);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (m_nNextTrack < STREAMED_SOUND_CITY_AMBIENT)\n\t\t\t\t\t\t\tm_nLastTrackServiceTime = CTimer::GetTimeInMillisecondsPauseMode();\n\t\t\t\t\t\tm_bVerifyNextTrackStartedToPlay = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (m_nPlayingTrack == NO_TRACK)\n\t\t\t\t\tdebug(\"m_nPlayingTrack == NO_TRACK, yet track playing - tidying up\\n\");\n\t\t\t\telse if (!bRadioStatsRecorded2)\n\t\t\t\t{\n\t\t\t\t\tm_aTracks[m_nPlayingTrack].m_nPosition = SampleManager.GetStreamedFilePosition(0);\n\t\t\t\t\tm_aTracks[m_nPlayingTrack].m_nLastPosCheckTimer = CTimer::GetTimeInMillisecondsPauseMode();\n\t\t\t\t\tbRadioStatsRecorded2 = true;\n\t\t\t\t\tRecordRadioStats();\n\t\t\t\t\tif (m_nPlayingTrack >= STREAMED_SOUND_HAVANA_CITY_AMBIENT && m_nPlayingTrack <= STREAMED_SOUND_HAVANA_BEACH_AMBIENT)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (m_nNextTrack >= STREAMED_SOUND_HAVANA_CITY_AMBIENT && m_nNextTrack <= STREAMED_SOUND_HAVANA_BEACH_AMBIENT)\n\t\t\t\t\t\t\tAudioManager.PlayOneShot(AudioManager.m_nFrontEndEntity, SOUND_FRONTEND_HURRICANE, 0.0);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tSampleManager.SetStreamedVolumeAndPan(0, 63, 0, 0);\n\t\t\t\tSampleManager.StopStreamedFile(0);\n\t\t\t}\n\t\t}\n\t\treturn;\n\t}\n\n\tif (m_nPlayingTrack >= STREAMED_SOUND_CITY_AMBIENT && m_nPlayingTrack <= STREAMED_SOUND_AMBSIL_AMBIENT)\n\t{\n\t\tComputeAmbienceVol(false, volume);\n\t\tSampleManager.SetStreamedVolumeAndPan(volume, 63, 1, 0);\n\t\treturn;\n\t}\n\tif (CTimer::GetIsSlowMotionActive())\n\t{\n\t\tif (TheCamera.pTargetEntity)\n\t\t{\n\t\t\tfloat DistToTargetSq = (TheCamera.pTargetEntity->GetPosition() - TheCamera.GetPosition()).MagnitudeSqr();\n\t\t\tif (DistToTargetSq >= SQR(55.0f))\n\t\t\t{\n\t\t\t\tSampleManager.SetStreamedVolumeAndPan(0, 63, 0, 0);\n\t\t\t}\n\t\t\telse if (DistToTargetSq >= SQR(10.0f))\n\t\t\t{\n\t\t\t\tvolume = (45.0f - (Sqrt(DistToTargetSq) - 10.0f)) / 45.0f * m_nCurrentVolume;\n\t\t\t\tif (AudioManager.ShouldDuckMissionAudio(0) || AudioManager.ShouldDuckMissionAudio(1))\n\t\t\t\t\tvolume /= 4;\n\n\t\t\t\tuint8 pan = 0;\n\t\t\t\tif (volume > 0)\n\t\t\t\t{\n\t\t\t\t\tCVector panVec;\n\t\t\t\t\tAudioManager.TranslateEntity(&TheCamera.pTargetEntity->GetPosition(), &panVec);\n\t\t\t\t\tpan = AudioManager.ComputePan(55.0f, &panVec);\n\t\t\t\t}\n\t\t\t\tif (gRetuneCounter != 0)\n\t\t\t\t\tvolume = 0;\n\t\t\t\tSampleManager.SetStreamedVolumeAndPan(volume, pan, 0, 0);\n\t\t\t}\n\t\t\telse if (AudioManager.ShouldDuckMissionAudio(0) || AudioManager.ShouldDuckMissionAudio(1))\n\t\t\t\tSampleManager.SetStreamedVolumeAndPan(m_nCurrentVolume, 63, 0, 0);\n\t\t\telse if (gRetuneCounter != 0)\n\t\t\t\tSampleManager.SetStreamedVolumeAndPan(0, 63, 0, 0);\n\t\t\telse\n\t\t\t\tSampleManager.SetStreamedVolumeAndPan(m_nCurrentVolume, 63, 0, 0);\n\t\t}\n\t} else if (AudioManager.ShouldDuckMissionAudio(0) || AudioManager.ShouldDuckMissionAudio(1)) {\n\t\tSampleManager.SetStreamedVolumeAndPan(Min(m_nCurrentVolume, 25), 63, 0, 0);\n\t\tnFramesSinceCutsceneEnded = 0;\n\t} else {\n\t\tif (nFramesSinceCutsceneEnded == -1)\n\t\t\tvolume = m_nCurrentVolume;\n\t\telse if (nFramesSinceCutsceneEnded < 20)\n\t\t{\n\t\t\tvolume = Min(m_nCurrentVolume, 25);\n\t\t\tnFramesSinceCutsceneEnded++;\n\t\t}\n\t\telse if (nFramesSinceCutsceneEnded < 40)\n\t\t{\n\t\t\tvolume = Min(m_nCurrentVolume, 3 * (nFramesSinceCutsceneEnded - 20) + 25);\n\t\t\tnFramesSinceCutsceneEnded++;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tvolume = m_nCurrentVolume;\n\t\t\tnFramesSinceCutsceneEnded = -1;\n\t\t}\n\t\tif (gRetuneCounter != 0)\n\t\t\tvolume = 0;\n\t\tSampleManager.SetStreamedVolumeAndPan(volume, 63, 0, 0);\n\t}\n\tif (m_nVolumeLatency > 0)\n\t\tm_nVolumeLatency--;\n\telse if (m_nCurrentVolume < m_nMaxVolume)\n\t\tm_nCurrentVolume = Min(m_nMaxVolume, m_nCurrentVolume + 6);\n}\n\nvoid\ncMusicManager::PreloadCutSceneMusic(uint32 track)\n{\n\tif (IsInitialised() && !m_bDisabled && track < TOTAL_STREAMED_SOUNDS && m_nMusicMode == MUSICMODE_CUTSCENE) {\n\t\tAudioManager.ResetPoliceRadio();\n\t\twhile (SampleManager.IsStreamPlaying(0))\n\t\t\tSampleManager.StopStreamedFile(0);\n\t\tSampleManager.PreloadStreamedFile(track, 0);\n\t\tSampleManager.SetStreamedVolumeAndPan(MAX_VOLUME, 63, 1, 0);\n\t\tm_nPlayingTrack = track;\n\t}\n}\n\nvoid\ncMusicManager::PlayPreloadedCutSceneMusic(void)\n{\n\tif (IsInitialised() && !m_bDisabled && m_nMusicMode == MUSICMODE_CUTSCENE)\n\t\tSampleManager.StartPreloadedStreamedFile(0);\n}\n\nvoid\ncMusicManager::StopCutSceneMusic(void)\n{\n\tif (IsInitialised() && !m_bDisabled && m_nMusicMode == MUSICMODE_CUTSCENE) {\n\t\tSampleManager.StopStreamedFile(0);\n\t\tm_nPlayingTrack = NO_TRACK;\n\t}\n}\n\nvoid\ncMusicManager::PlayFrontEndTrack(uint32 track, uint8 loopFlag)\n{\n\tif (IsInitialised() && !m_bDisabled && track < TOTAL_STREAMED_SOUNDS && (m_nUpcomingMusicMode == MUSICMODE_FRONTEND || m_nMusicMode == MUSICMODE_FRONTEND))\n\t{\n\t\tm_nFrontendTrack = track;\n\t\tm_FrontendLoopFlag = loopFlag;\n\t\tif (m_nMusicMode != MUSICMODE_FRONTEND)\n\t\t\tm_bEarlyFrontendTrack = true;\n\t}\n}\n\nvoid\ncMusicManager::StopFrontEndTrack()\n{\n\tif (m_nUpcomingMusicMode == MUSICMODE_FRONTEND || m_nMusicMode == MUSICMODE_FRONTEND)\n\t\tm_nFrontendTrack = NO_TRACK;\n}\n\nvoid\ncMusicManager::PlayAnnouncement(uint32 announcement)\n{\n\tif (IsInitialised() && !m_bDisabled && !m_bAnnouncementInProgress)\n\t\tm_nAnnouncement = announcement;\n}\n\nuint32\ncMusicManager::GetNextCarTuning()\n{\n\tCVehicle *veh = AudioManager.FindVehicleOfPlayer();\n\tif (veh == nil) return STREAMED_SOUND_CITY_AMBIENT;\n\tif (UsesPoliceRadio(veh)) return STREAMED_SOUND_RADIO_POLICE;\n\tif (UsesTaxiRadio(veh)) return STREAMED_SOUND_RADIO_TAXI;\n\tif (gNumRetunePresses != 0) {\n#ifdef RADIO_SCROLL_TO_PREV_STATION\n\t\t// m_nRadioStation is unsigned, so...\n\t\tint station = veh->m_nRadioStation + gNumRetunePresses;\n\t\twhile(station < 0) station += NUM_RADIOS + 1;\n\t\twhile(station >= NUM_RADIOS + 1) station -= NUM_RADIOS + 1;\n\t\tveh->m_nRadioStation = station;\n#else\n\t\tveh->m_nRadioStation += gNumRetunePresses;\n\t\twhile(veh->m_nRadioStation >= NUM_RADIOS + 1)\n\t\t\tveh->m_nRadioStation -= NUM_RADIOS + 1;\n#endif\n\t\tDMAudio.IsMP3RadioChannelAvailable(); // woof, just call and do nothing =P they manipulate gNumRetunePresses on DisplayRadioStationName in this case\n\t\tgNumRetunePresses = 0;\n\t}\n\treturn veh->m_nRadioStation;\n}\n\nuint32\ncMusicManager::GetCarTuning()\n{\n\tCVehicle* veh = AudioManager.FindVehicleOfPlayer();\n\tif (veh == nil) return STREAMED_SOUND_CITY_AMBIENT;\n\tif (UsesPoliceRadio(veh)) return STREAMED_SOUND_RADIO_POLICE;\n\tif (UsesTaxiRadio(veh)) return STREAMED_SOUND_RADIO_TAXI;\n\tif (veh->m_nRadioStation == USERTRACK && !SampleManager.IsMP3RadioChannelAvailable())\n\t\tveh->m_nRadioStation = AudioManager.GetRandomNumber(2) % USERTRACK;\n\treturn veh->m_nRadioStation;\n}\n\nfloat*\ncMusicManager::GetListenTimeArray()\n{\n\treturn aListenTimeArray;\n}\n\nuint32\ncMusicManager::GetTrackStartPos(uint32 track)\n{\n\tif (!IsInitialised()) return 0;\n\n\tuint32 pos = m_aTracks[track].m_nPosition;\n\tif (CTimer::GetTimeInMillisecondsPauseMode() > m_aTracks[track].m_nLastPosCheckTimer)\n\t\tpos += Min(CTimer::GetTimeInMillisecondsPauseMode() - m_aTracks[track].m_nLastPosCheckTimer, 270000);\n\telse\n\t\tm_aTracks[track].m_nLastPosCheckTimer = CTimer::GetTimeInMillisecondsPauseMode();\n\n\tif (pos > m_aTracks[track].m_nLength)\n\t\tpos %= m_aTracks[track].m_nLength;\n\treturn pos;\n}\n\nuint32\ncMusicManager::GetRadioPosition(uint32 station)\n{\n\tif (station < NUM_RADIOS)\n\t\treturn GetTrackStartPos(station);\n\treturn 0;\n}\n\nuint32\ncMusicManager::GetFavouriteRadioStation()\n{\n\tuint32 favstation = 0;\n\n\tfor (int i = 1; i < NUM_RADIOS; i++) {\n\t\tif (aListenTimeArray[i] > aListenTimeArray[favstation])\n\t\t\tfavstation = i;\n\t}\n\n\treturn favstation;\n}\n\nbool\ncMusicManager::CheckForMusicInterruptions()\n{\n\treturn (m_nPlayingTrack == STREAMED_SOUND_MISSION_COMPLETED) || (m_nPlayingTrack == STREAMED_SOUND_CUTSCENE_FINALE);\n}\n\nvoid\ncMusicManager::SetMalibuClubTrackPos(uint8 scriptObject)\n{\n\tif (!IsInitialised())\n\t\tm_aTracks[STREAMED_SOUND_MALIBU_AMBIENT].m_nPosition = 8640;\n\tif (m_nNextTrack != STREAMED_SOUND_MALIBU_AMBIENT && m_nPlayingTrack != STREAMED_SOUND_MALIBU_AMBIENT) {\n\t\tswitch (scriptObject)\n\t\t{\n\t\tcase SCRIPT_SOUND_NEW_BUILDING_MALIBU_1:\n\t\t\tm_aTracks[STREAMED_SOUND_MALIBU_AMBIENT].m_nPosition = (AudioManager.m_anRandomTable[0] % 128) + 8640;\n\t\t\tbreak;\n\t\tcase SCRIPT_SOUND_NEW_BUILDING_MALIBU_2:\n\t\t\tm_aTracks[STREAMED_SOUND_MALIBU_AMBIENT].m_nPosition = (AudioManager.m_anRandomTable[0] % 128) + 286720;\n\t\t\tbreak;\n\t\tcase SCRIPT_SOUND_NEW_BUILDING_MALIBU_3:\n\t\t\tm_aTracks[STREAMED_SOUND_MALIBU_AMBIENT].m_nPosition = (AudioManager.m_anRandomTable[0] % 128) + 509120;\n\t\t\tbreak;\n\t\t}\n\t\tm_aTracks[STREAMED_SOUND_MALIBU_AMBIENT].m_nLastPosCheckTimer = CTimer::GetTimeInMillisecondsPauseMode();\n\t}\n}\n\nvoid\ncMusicManager::SetStripClubTrackPos(uint8 scriptObject)\n{\n\tif (!IsInitialised())\n\t\tm_aTracks[STREAMED_SOUND_STRIPCLUB_AMBIENT].m_nPosition = 0;\n\tif (m_nNextTrack != STREAMED_SOUND_STRIPCLUB_AMBIENT && m_nPlayingTrack != STREAMED_SOUND_STRIPCLUB_AMBIENT)\n\t{\n\t\tswitch (scriptObject)\n\t\t{\n\t\tcase SCRIPT_SOUND_NEW_BUILDING_STRIP_1:\n\t\t\tm_aTracks[STREAMED_SOUND_STRIPCLUB_AMBIENT].m_nPosition = AudioManager.m_anRandomTable[0] % 128;\n\t\t\tbreak;\n\t\tcase SCRIPT_SOUND_NEW_BUILDING_STRIP_2:\n\t\t\tm_aTracks[STREAMED_SOUND_STRIPCLUB_AMBIENT].m_nPosition = (AudioManager.m_anRandomTable[0] % 128) + 320200;\n\t\t\tbreak;\n\t\tcase SCRIPT_SOUND_NEW_BUILDING_STRIP_3:\n\t\t\tm_aTracks[STREAMED_SOUND_STRIPCLUB_AMBIENT].m_nPosition = (AudioManager.m_anRandomTable[0] % 128) + 672000;\n\t\t\tbreak;\n\t\t}\n\t\tm_aTracks[STREAMED_SOUND_STRIPCLUB_AMBIENT].m_nLastPosCheckTimer = CTimer::GetTimeInMillisecondsPauseMode();\n\t}\n}\n\nvoid\ncMusicManager::DisplayRadioStationName()\n{\n\tuint8 gStreamedSound;\n\tstatic wchar *pCurrentStation = nil;\n\tstatic uint8 cDisplay = 0;\n\n\tif(!CTimer::GetIsPaused() && !TheCamera.m_WideScreenOn && PlayerInCar() &&\n\t   !CReplay::IsPlayingBack()) {\n\t\tCVehicle *vehicle = AudioManager.FindVehicleOfPlayer();\n\n\t\tif (vehicle)\n\t\t{\n#if defined RADIO_SCROLL_TO_PREV_STATION || defined FIX_BUGS // Because m_nFrontendTrack can have NO_TRACK\n\t\t\tint track;\n#else\n\t\t\tuint8 track;\n#endif\n\t\t\tgStreamedSound = vehicle->m_nRadioStation;\n\t\t\tif (gStreamedSound >= STREAMED_SOUND_CITY_AMBIENT && gStreamedSound <= STREAMED_SOUND_AMBSIL_AMBIENT)\n\t\t\t\tgStreamedSound = RADIO_OFF;\n\t\t\tif (gNumRetunePresses != 0)\n\t\t\t{\n\t\t\t\ttrack = gNumRetunePresses + gStreamedSound;\n#ifdef RADIO_SCROLL_TO_PREV_STATION\n\t\t\t\twhile (track < 0) track += NUM_RADIOS + 1;\n#endif\n\t\t\t\twhile (track >= NUM_RADIOS + 1) track -= NUM_RADIOS + 1;\n\n\t\t\t\t// We already handle this condition while scrolling back, on key press. No need to change this.\n\t\t\t\tif (!DMAudio.IsMP3RadioChannelAvailable() && track == USERTRACK)\n\t\t\t\t\tgNumRetunePresses++;\n\t\t\t}\n\t\t\telse\n\t\t\t\ttrack = m_nFrontendTrack;\n\n\t\t\twchar* string = nil;\n\t\t\tswitch (track) {\n\t\t\tcase WILDSTYLE: string = TheText.Get(\"FEA_FM0\"); break;\n\t\t\tcase FLASH_FM: string = TheText.Get(\"FEA_FM1\"); break;\n\t\t\tcase KCHAT: string = TheText.Get(\"FEA_FM2\"); break;\n\t\t\tcase FEVER: string = TheText.Get(\"FEA_FM3\"); break;\n\t\t\tcase V_ROCK: string = TheText.Get(\"FEA_FM4\"); break;\n\t\t\tcase VCPR: string = TheText.Get(\"FEA_FM5\"); break;\n\t\t\tcase RADIO_ESPANTOSO: string = TheText.Get(\"FEA_FM6\"); break;\n\t\t\tcase EMOTION: string = TheText.Get(\"FEA_FM7\"); break;\n\t\t\tcase WAVE: string = TheText.Get(\"FEA_FM8\"); break;\n\t\t\tcase USERTRACK:\n\t\t\t\tif (!SampleManager.IsMP3RadioChannelAvailable())\n\t\t\t\t\treturn;\n\t\t\t\tstring = TheText.Get(\"FEA_MP3\"); break;\n#ifdef RADIO_OFF_TEXT\n\t\t\tcase STREAMED_SOUND_RADIO_POLICE:\n\t\t\tcase STREAMED_SOUND_RADIO_TAXI:\n\t\t\t\treturn;\n\t\t\tdefault: {\n\t\t\t\t// Otherwise pausing-resuming game will show RADIO OFF, since radio isn't set yet\n\t\t\t\tif (m_nPlayingTrack == NO_TRACK && m_nFrontendTrack == NO_TRACK)\n\t\t\t\t\treturn;\n\n\t\t\t\textern wchar WideErrorString[];\n\n\t\t\t\tstring = TheText.Get(\"FEA_NON\");\n\t\t\t\tif (string == WideErrorString) {\n\t\t\t\t\tpCurrentStation = nil;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n#else\n\t\t\tdefault: return;\n#endif\n\t\t\t};\n\n\t\t\tif (pCurrentStation != string) {\n\t\t\t\tpCurrentStation = string;\n\t\t\t\tcDisplay = 60;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tif (cDisplay == 0) return;\n\t\t\t\tcDisplay--;\n\t\t\t}\n\n\t\t\tCFont::SetJustifyOff();\n\t\t\tCFont::SetBackgroundOff();\n\t\t\tCFont::SetScale(SCREEN_SCALE_X(0.8f), SCREEN_SCALE_Y(1.35f));\n\t\t\tCFont::SetPropOn();\n\t\t\tCFont::SetFontStyle(FONT_STANDARD);\n\t\t\tCFont::SetCentreOn();\n\t\t\tCFont::SetCentreSize(SCREEN_STRETCH_X(DEFAULT_SCREEN_WIDTH));\n\t\t\tCFont::SetColor(CRGBA(0, 0, 0, 255));\n\t\t\tCFont::PrintString(SCREEN_WIDTH / 2 + SCREEN_SCALE_X(2.0f), SCREEN_SCALE_Y(22.0f) + SCREEN_SCALE_Y(2.0f), pCurrentStation);\n\n\t\t\tif (gNumRetunePresses)\n\t\t\t\tCFont::SetColor(CRGBA(102, 133, 143, 255));\n\t\t\telse\n\t\t\t\tCFont::SetColor(CRGBA(147, 196, 211, 255));\n\n\t\t\tCFont::PrintString(SCREEN_WIDTH / 2, SCREEN_SCALE_Y(22.0f), pCurrentStation);\n\t\t\tCFont::DrawFonts();\n\t\t}\n\t}\n\t// Always show station text after entering car. Same behaviour as III and SA.\n#ifdef FIX_BUGS\n\telse\n\t\tpCurrentStation = nil;\n#endif\n}\n\nbool\ncMusicManager::UsesPoliceRadio(CVehicle *veh)\n{\n\tswitch (veh->GetModelIndex())\n\t{\n\tcase MI_VCNMAV:\n\tcase MI_POLMAV:\n\tcase MI_COASTG:\n\tcase MI_RHINO:\n\tcase MI_BARRACKS:\n\t\treturn true;\n\tcase MI_MRWHOOP:\n\tcase MI_HUNTER:\n\t\treturn false;\n\t}\n\treturn veh->UsesSiren();\n}\n\nbool\ncMusicManager::UsesTaxiRadio(CVehicle *veh)\n{\n\tif (veh->GetModelIndex() != MI_KAUFMAN) return false;\n\treturn CTheScripts::bPlayerHasMetDebbieHarry;\n}\n\nvoid\ncMusicManager::ServiceAmbience()\n{\n}\n\nbool\ncMusicManager::ChangeRadioChannel()\n{\n\treturn true;\n}\n\n// these two are empty\nvoid cMusicManager::Enable() {}\nvoid cMusicManager::Disable() {}\n"
  },
  {
    "path": "src/audio/MusicManager.h",
    "content": "#pragma once\n\n#include \"audio_enums.h\"\n\nclass tStreamedSample\n{\npublic:\n\tuint32 m_nLength;\n\tuint32 m_nPosition;\n\tuint32 m_nLastPosCheckTimer;\n};\n\nclass CVehicle;\nclass CPed;\n\nclass cMusicManager\n{\npublic:\n\tbool m_bIsInitialised;\n\tbool m_bDisabled;\n\tbool m_bSetNextStation;\n\tuint8 m_nVolumeLatency;\n\tuint8 m_nCurrentVolume;\n\tuint8 m_nMaxVolume;\n\tuint32 m_nAnnouncement;\n\tbool m_bAnnouncementInProgress;\n\ttStreamedSample m_aTracks[TOTAL_STREAMED_SOUNDS];\n\tbool m_bResetTimers;\n\tuint32 m_nResetTime;\n\tbool m_bRadioSetByScript;\n\tuint8 m_nRadioStationScript;\n\tint32 m_nRadioPosition;\n\tuint32 m_nRadioInCar;\n\tuint32 m_nFrontendTrack;\n\tuint32 m_nPlayingTrack;\n\tuint8 m_nUpcomingMusicMode;\n\tuint8 m_nMusicMode;\n\tbool m_FrontendLoopFlag;\n\tbool m_bTrackChangeStarted;\n\tuint32 m_nNextTrack;\n\tbool m_nNextLoopFlag;\n\tbool m_bVerifyNextTrackStartedToPlay;\n\tbool m_bGameplayAllowsRadio;\n\tbool m_bRadioStreamReady;\n\tint8 nFramesSinceCutsceneEnded;\n\tbool m_bUserResumedGame;\n\tbool m_bMusicModeChangeStarted;\n\tuint8 m_nMusicModeToBeSet;\n\tbool m_bEarlyFrontendTrack;\n\tfloat aListenTimeArray[NUM_RADIOS];\n\tfloat m_nLastTrackServiceTime;\n\npublic:\n\tcMusicManager();\n\tbool IsInitialised() { return m_bIsInitialised; }\n\tuint8 GetMusicMode() { return m_nMusicMode; }\n\tuint32 GetCurrentTrack() { return m_nPlayingTrack; }\n\n\tvoid ResetMusicAfterReload();\n\tvoid SetStartingTrackPositions(uint8 isNewGameTimer);\n\tbool Initialise();\n\tvoid Terminate();\n\n\tvoid ChangeMusicMode(uint8 mode);\n\tvoid StopFrontEndTrack();\n\n\tbool PlayerInCar();\n\tvoid DisplayRadioStationName();\n\n\tvoid PlayAnnouncement(uint32);\n\tvoid PlayFrontEndTrack(uint32, uint8);\n\tvoid PreloadCutSceneMusic(uint32);\n\tvoid PlayPreloadedCutSceneMusic(void);\n\tvoid StopCutSceneMusic(void);\n\tuint32 GetRadioInCar(void);\n\tvoid SetRadioInCar(uint32);\n\tvoid SetRadioChannelByScript(uint32, int32);\n\n\tvoid ResetTimers(int32);\n\tvoid Service();\n\tvoid ServiceFrontEndMode();\n\tvoid ServiceGameMode();\n\tvoid ServiceAmbience();\n\tvoid ServiceTrack(CVehicle *veh, CPed *ped);\n\n\tbool UsesPoliceRadio(CVehicle *veh);\n\tbool UsesTaxiRadio(CVehicle *veh);\n\tuint32 GetTrackStartPos(uint32 track);\n\n\tvoid ComputeAmbienceVol(uint8 reset, uint8& outVolume);\n\tbool ServiceAnnouncement();\n\n\tuint32 GetCarTuning();\n\tuint32 GetNextCarTuning();\n\tbool ChangeRadioChannel();\n\tvoid RecordRadioStats();\n\tvoid SetUpCorrectAmbienceTrack();\n\tfloat *GetListenTimeArray();\n\tuint32 GetRadioPosition(uint32 station);\n\tuint32 GetFavouriteRadioStation();\n\tvoid SetMalibuClubTrackPos(uint8 pos);\n\tvoid SetStripClubTrackPos(uint8 pos);\n\tbool CheckForMusicInterruptions();\n\n\tvoid Enable();\n\tvoid Disable();\n};\n\nVALIDATE_SIZE(cMusicManager, 0x95C);\n\nextern cMusicManager MusicManager;\nextern bool g_bAnnouncementReadPosAlready; // we have a symbol of this so it was declared in .h\nfloat GetHeightScale();\n"
  },
  {
    "path": "src/audio/PoliceRadio.cpp",
    "content": "#include \"common.h\"\n\n#include \"DMAudio.h\"\n\n#include \"AudioManager.h\"\n\n#include \"AudioSamples.h\"\n#include \"MusicManager.h\"\n#include \"PlayerPed.h\"\n#include \"PoliceRadio.h\"\n#include \"Replay.h\"\n#include \"Vehicle.h\"\n#include \"World.h\"\n#include \"Zones.h\"\n#include \"sampman.h\"\n#include \"Wanted.h\"\n\nconst int channels = ARRAY_SIZE(AudioManager.m_asActiveSamples);\nconst int policeChannel = channels + 1;\n\nstruct tPoliceRadioZone {\n\tchar m_aName[8];\n\tuint32 m_nSampleIndex;\n\tint32 field_12;\n};\n\ntPoliceRadioZone ZoneSfx[NUMAUDIOZONES];\n\nint32 g_nMissionAudioSfx = TOTAL_AUDIO_SAMPLES;\nint8 g_nMissionAudioPlayingStatus = 2;\nuint8 gSpecialSuspectLastSeenReport;\nuint32 gMinTimeToNextReport[NUM_CRIME_TYPES];\n\nvoid\ncAudioManager::InitialisePoliceRadioZones()\n{\n\tfor (int32 i = 0; i < NUMAUDIOZONES; i++)\n\t\tmemset(ZoneSfx[i].m_aName, 0, 8);\n\n#define SETZONESFX(i, name, sample) \\\n\tstrcpy(ZoneSfx[i].m_aName, name); \\\n\tZoneSfx[i].m_nSampleIndex = sample;\n\n\tSETZONESFX(0, \"VICE_C\", SFX_POLICE_RADIO_VICE_CITY);\n\tSETZONESFX(1, \"IND_ZON\", SFX_POLICE_RADIO_VICE_CITY_BEACH);\n\tSETZONESFX(2, \"COM_ZON\", SFX_POLICE_RADIO_VICE_CITY_MAINLAND);\n\tSETZONESFX(3, \"BEACH1\", SFX_POLICE_RADIO_OCEAN_BEACH);\n\tSETZONESFX(4, \"BEACH2\", SFX_POLICE_RADIO_WASHINGTON_BEACH);\n\tSETZONESFX(5, \"BEACH3\", SFX_POLICE_RADIO_VICE_POINT);\n\tSETZONESFX(6, \"GOLFC\", SFX_POLICE_RADIO_LEAF_LINKS);\n\tSETZONESFX(7, \"STARI\", SFX_POLICE_RADIO_STRAFISH_ISLAND);\n\tSETZONESFX(8, \"DOCKS\", SFX_POLICE_RADIO_VICE_PORT);\n\tSETZONESFX(9, \"HAVANA\", SFX_POLICE_RADIO_LITTLE_HAVANA);\n\tSETZONESFX(10, \"HAITI\", SFX_POLICE_RADIO_LITTLE_HAITI);\n\tSETZONESFX(11, \"PORNI\", SFX_POLICE_RADIO_PRAWN_ISLAND);\n\tSETZONESFX(12, \"DTOWN\", SFX_POLICE_RADIO_DOWNTOWN);\n\tSETZONESFX(13, \"A_PORT\", SFX_POLICE_RADIO_ESCOBAR_INTERNATIONAL);\n\n#undef SETZONESFX\n}\n\nvoid\ncAudioManager::InitialisePoliceRadio()\n{\n\tm_sPoliceRadioQueue.policeChannelTimer = 0;\n\tm_sPoliceRadioQueue.policeChannelTimerSeconds = 0;\n\tm_sPoliceRadioQueue.policeChannelCounterSeconds = 0;\n\tfor (int32 i = 0; i < ARRAY_SIZE(m_sPoliceRadioQueue.crimes); i++)\n\t\tm_sPoliceRadioQueue.crimes[i].type = CRIME_NONE;\n\n\tSampleManager.SetChannelReverbFlag(policeChannel, false);\n\tgSpecialSuspectLastSeenReport = false;\n\tfor (int32 i = 0; i < ARRAY_SIZE(gMinTimeToNextReport); i++)\n\t\tgMinTimeToNextReport[i] = m_FrameCounter;\n}\n\nvoid\ncAudioManager::ResetPoliceRadio()\n{\n\tif (!m_bIsInitialised) return;\n\tif (SampleManager.GetChannelUsedFlag(policeChannel)) SampleManager.StopChannel(policeChannel);\n\tInitialisePoliceRadio();\n}\n\nvoid\ncAudioManager::SetMissionScriptPoliceAudio(int32 sfx) const\n{\n\tif (!m_bIsInitialised) return;\n\tif (g_nMissionAudioPlayingStatus != 1) {\n\t\tg_nMissionAudioPlayingStatus = 0;\n\t\tg_nMissionAudioSfx = sfx;\n\t}\n}\n\nint8\ncAudioManager::GetMissionScriptPoliceAudioPlayingStatus() const\n{\n\treturn g_nMissionAudioPlayingStatus;\n}\n\nvoid\ncAudioManager::DoPoliceRadioCrackle()\n{\n\tm_sQueueSample.m_nEntityIndex = m_nPoliceChannelEntity;\n\tm_sQueueSample.m_nCounter = 0;\n\tm_sQueueSample.m_nSampleIndex = SFX_POLICE_RADIO_CRACKLE;\n\tm_sQueueSample.m_nBankIndex = SFX_BANK_0;\n\tm_sQueueSample.m_bIs2D = true;\n\tm_sQueueSample.m_nReleasingVolumeModificator = 10;\n\tm_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_POLICE_RADIO_CRACKLE);\n\tm_sQueueSample.m_nVolume = m_anRandomTable[2] % 20 + 15;\n\tm_sQueueSample.m_nLoopCount = 0;\n\tm_sQueueSample.m_nEmittingVolume = m_sQueueSample.m_nVolume;\n\tm_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(SFX_POLICE_RADIO_CRACKLE);\n\tm_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(SFX_POLICE_RADIO_CRACKLE);\n\tm_sQueueSample.m_bReleasingSoundFlag = false;\n\tm_sQueueSample.m_bReverbFlag = false;\n\tm_sQueueSample.m_nOffset = 63;\n\tm_sQueueSample.m_nReleasingVolumeDivider = 3;\n\tm_sQueueSample.m_bRequireReflection = false;\n\tAddSampleToRequestedQueue();\n}\n\nvoid\ncAudioManager::ServicePoliceRadio()\n{\n\tint32 wantedLevel = 0; // uninitialized variable\n\tstatic uint32 nLastSeen = 300;\n\n\tif(!m_bIsInitialised) return;\n\n\tif(m_nUserPause == 0) {\n\t\tbool crimeReport = SetupCrimeReport();\n#ifdef FIX_BUGS // Crash at 0x5fe6ef\n\t\tif(CReplay::IsPlayingBack() || !FindPlayerPed() || !FindPlayerPed()->m_pWanted)\n\t\t\treturn;\n#endif\n\t\tCPlayerPed *playerPed = FindPlayerPed();\n\t\tif (playerPed) {\n\t\t\twantedLevel = playerPed->m_pWanted->GetWantedLevel();\n\t\t\tif (!crimeReport) {\n\t\t\t\tif (wantedLevel != 0) {\n\t\t\t\t\tif (nLastSeen != 0)\n\t\t\t\t\t\t--nLastSeen;\n\t\t\t\t\telse {\n\t\t\t\t\t\tnLastSeen = m_anRandomTable[1] % 1000 + 2000;\n\t\t\t\t\t\tSetupSuspectLastSeenReport();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tServicePoliceRadioChannel(wantedLevel);\n}\n\nvoid\ncAudioManager::ServicePoliceRadioChannel(uint8 wantedLevel)\n{\n\tbool processed = false;\n\tuint32 sample;\n\tint32 freq;\n\n\tstatic int cWait = 0;\n\tstatic bool bChannelOpen = false;\n\tstatic uint8 bMissionAudioPhysicalPlayingStatus = 0;\n\tstatic int32 PoliceChannelFreq = 22050;\n\n\tif (!m_bIsInitialised) return;\n\n\tif (m_nUserPause != 0) {\n\t\tif (SampleManager.GetChannelUsedFlag(policeChannel)) SampleManager.StopChannel(policeChannel);\n\t\tif (g_nMissionAudioSfx != NO_SAMPLE && bMissionAudioPhysicalPlayingStatus == 1 &&\n\t\t\tSampleManager.IsStreamPlaying(1)) {\n\t\t\tSampleManager.PauseStream(1, 1);\n\t\t}\n\t} else {\n\t\tif (m_nPreviousUserPause && g_nMissionAudioSfx != NO_SAMPLE &&\n\t\t\tbMissionAudioPhysicalPlayingStatus == 1) {\n\t\t\tSampleManager.PauseStream(0, 1);\n\t\t}\n\t\tif (m_sPoliceRadioQueue.policeChannelTimer == 0) bChannelOpen = false;\n\t\tif (cWait) {\n\t\t\t--cWait;\n\t\t\treturn;\n\t\t}\n\t\tif (g_nMissionAudioSfx != NO_SAMPLE && !bChannelOpen) {\n\t\t\tif (g_nMissionAudioPlayingStatus) {\n\t\t\t\tif (g_nMissionAudioPlayingStatus == 1 && !bMissionAudioPhysicalPlayingStatus &&\n\t\t\t\t\tSampleManager.IsStreamPlaying(1)) {\n\t\t\t\t\tbMissionAudioPhysicalPlayingStatus = 1;\n\t\t\t\t}\n\t\t\t\tif (bMissionAudioPhysicalPlayingStatus == 1) {\n\t\t\t\t\tif (SampleManager.IsStreamPlaying(1)) {\n\t\t\t\t\t\tDoPoliceRadioCrackle();\n\t\t\t\t\t} else {\n\t\t\t\t\t\tbMissionAudioPhysicalPlayingStatus = 2;\n\t\t\t\t\t\tg_nMissionAudioPlayingStatus = 2;\n\t\t\t\t\t\tg_nMissionAudioSfx = NO_SAMPLE;\n\t\t\t\t\t\tcWait = 30;\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t} else if (!SampleManager.GetChannelUsedFlag(policeChannel)) {\n\t\t\t\tSampleManager.PreloadStreamedFile(g_nMissionAudioSfx, 1);\n\t\t\t\tSampleManager.SetStreamedVolumeAndPan(MAX_VOLUME, 63, 1, 1);\n\t\t\t\tSampleManager.StartPreloadedStreamedFile(1);\n\t\t\t\tg_nMissionAudioPlayingStatus = 1;\n\t\t\t\tbMissionAudioPhysicalPlayingStatus = 0;\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\tif (bChannelOpen) DoPoliceRadioCrackle();\n\t\tif ((g_nMissionAudioSfx == NO_SAMPLE || g_nMissionAudioPlayingStatus != 1) &&\n\t\t\t!SampleManager.GetChannelUsedFlag(policeChannel) && m_sPoliceRadioQueue.policeChannelTimer) {\n\t\t\tif (m_sPoliceRadioQueue.policeChannelTimer) {\n\t\t\t\tsample = m_sPoliceRadioQueue.crimesSamples[m_sPoliceRadioQueue.policeChannelCounterSeconds];\n\t\t\t\tm_sPoliceRadioQueue.policeChannelTimer--;\n\t\t\t\tm_sPoliceRadioQueue.policeChannelCounterSeconds = (m_sPoliceRadioQueue.policeChannelCounterSeconds + 1) % 60;\n\t\t\t} else {\n\t\t\t\tsample = NO_SAMPLE;\n\t\t\t}\n\t\t\tif (wantedLevel == 0) {\n\t\t\t\tif (gSpecialSuspectLastSeenReport) {\n\t\t\t\t\tgSpecialSuspectLastSeenReport = 0;\n\t\t\t\t} else if (sample == SFX_POLICE_RADIO_MESSAGE_NOISE_1) {\n\t\t\t\t\tbChannelOpen = false;\n\t\t\t\t\tprocessed = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (sample == NO_SAMPLE) {\n\t\t\t\tif (!processed) cWait = 30;\n\t\t\t} else {\n\t\t\t\tSampleManager.InitialiseChannel(policeChannel, sample, 0);\n\t\t\t\tswitch (sample) {\n\t\t\t\tcase SFX_POLICE_RADIO_MESSAGE_NOISE_1:\n\t\t\t\t\tfreq = m_anRandomTable[4] % 2000 + 10025;\n\t\t\t\t\tbChannelOpen = bChannelOpen == false;\n\t\t\t\t\tbreak;\n\t\t\t\tdefault: freq = SampleManager.GetSampleBaseFrequency(sample); break;\n\t\t\t\t}\n\t\t\t\tPoliceChannelFreq = freq;\n\t\t\t\tSampleManager.SetChannelFrequency(policeChannel, freq);\n\t\t\t\tSampleManager.SetChannelVolume(policeChannel, 100);\n\t\t\t\tSampleManager.SetChannelPan(policeChannel, 63);\n\t\t\t\tSampleManager.SetChannelLoopCount(policeChannel, 1);\n\t\t\t\tSampleManager.SetChannelLoopPoints(policeChannel, 0, -1);\n\t\t\t\tSampleManager.StartChannel(policeChannel);\n\t\t\t}\n\t\t\tif (processed) ResetPoliceRadio();\n\t\t}\n\t}\n}\n\nbool\ncAudioManager::SetupCrimeReport()\n{\n\tint16 audioZoneId;\n\tCZone *zone;\n\tfloat rangeX;\n\tfloat rangeY;\n\tfloat halfX;\n\tfloat halfY;\n\tfloat quarterX;\n\tfloat quarterY;\n\tint i;\n\tint32 sampleIndex;\n\tbool processed = false;\n\n\tif (MusicManager.m_nMusicMode == MUSICMODE_CUTSCENE) return false;\n\n\tif (60 - m_sPoliceRadioQueue.policeChannelTimer <= 9) {\n\t\tAgeCrimes();\n\t\treturn true;\n\t}\n\n\tfor (i = 0; i < ARRAY_SIZE(m_sPoliceRadioQueue.crimes); i++) {\n\t\tif (m_sPoliceRadioQueue.crimes[i].type != CRIME_NONE)\n\t\t\tbreak;\n\t}\n\n\tif (i == ARRAY_SIZE(m_sPoliceRadioQueue.crimes)) return false;\n\taudioZoneId = CTheZones::FindAudioZone(&m_sPoliceRadioQueue.crimes[i].position);\n\tif (audioZoneId >= 0 && audioZoneId < NUMAUDIOZONES) {\n\t\tzone = CTheZones::GetAudioZone(audioZoneId);\n\t\tfor (int j = 0; j < NUMAUDIOZONES; j++) {\n\t\t\tif (strcmp(zone->name, ZoneSfx[j].m_aName) == 0) {\n\t\t\t\tsampleIndex = ZoneSfx[j].m_nSampleIndex;\n\t\t\t\tm_sPoliceRadioQueue.Add(SFX_POLICE_RADIO_MESSAGE_NOISE_1);\n\t\t\t\tm_sPoliceRadioQueue.Add(m_anRandomTable[0] % 3 + SFX_WEVE_GOT);\n\t\t\t\tm_sPoliceRadioQueue.Add(SFX_A_10);\n\t\t\t\tswitch (m_sPoliceRadioQueue.crimes[i].type) {\n\t\t\t\tcase CRIME_PED_BURNED:\n\t\t\t\tcase CRIME_HIT_PED_NASTYWEAPON:\n\t\t\t\t\tm_sPoliceRadioQueue.crimes[i].type = CRIME_HIT_PED;\n\t\t\t\t\tbreak;\n\t\t\t\tcase CRIME_COP_BURNED:\n\t\t\t\tcase CRIME_HIT_COP_NASTYWEAPON:\n\t\t\t\t\tm_sPoliceRadioQueue.crimes[i].type = CRIME_HIT_COP;\n\t\t\t\t\tbreak;\n\t\t\t\tcase CRIME_VEHICLE_BURNED: m_sPoliceRadioQueue.crimes[i].type = CRIME_STEAL_CAR; break;\n\t\t\t\tcase CRIME_DESTROYED_CESSNA: m_sPoliceRadioQueue.crimes[i].type = CRIME_SHOOT_HELI; break;\n\t\t\t\tcase CRIME_EXPLOSION: m_sPoliceRadioQueue.crimes[i].type = CRIME_STEAL_CAR; break; // huh?\n\t\t\t\tdefault: break;\n\t\t\t\t}\n#ifdef FIX_BUGS\n\t\t\t\tm_sPoliceRadioQueue.Add(m_sPoliceRadioQueue.crimes[i].type + SFX_CRIME_1 - 1);\n#else\n\t\t\t\tm_sPoliceRadioQueue.Add(m_sPoliceRadioQueue.crimes[i].type + SFX_CRIME_1);\n#endif\n\t\t\t\tm_sPoliceRadioQueue.Add(SFX_IN);\n\t\t\t\trangeX = zone->maxx - zone->minx;\n\t\t\t\trangeY = zone->maxy - zone->miny;\n\t\t\t\thalfX = 0.5f * rangeX + zone->minx;\n\t\t\t\thalfY = 0.5f * rangeY + zone->miny;\n\t\t\t\tquarterX = 0.25f * rangeX;\n\t\t\t\tquarterY = 0.25f * rangeY;\n\n\t\t\t\tif (m_sPoliceRadioQueue.crimes[i].position.y > halfY + quarterY) {\n\t\t\t\t\tm_sPoliceRadioQueue.Add(SFX_NORTH);\n\t\t\t\t\tprocessed = true;\n\t\t\t\t} else if (m_sPoliceRadioQueue.crimes[i].position.y < halfY - quarterY) {\n\t\t\t\t\tm_sPoliceRadioQueue.Add(SFX_SOUTH);\n\t\t\t\t\tprocessed = true;\n\t\t\t\t}\n\n\t\t\t\tif (m_sPoliceRadioQueue.crimes[i].position.x > halfX + quarterX)\n\t\t\t\t\tm_sPoliceRadioQueue.Add(SFX_EAST);\n\t\t\t\telse if (m_sPoliceRadioQueue.crimes[i].position.x < halfX - quarterX)\n\t\t\t\t\tm_sPoliceRadioQueue.Add(SFX_WEST);\n\t\t\t\telse if (!processed)\n\t\t\t\t\tm_sPoliceRadioQueue.Add(SFX_CENTRAL);\n\n\t\t\t\tm_sPoliceRadioQueue.Add(sampleIndex);\n\t\t\t\tm_sPoliceRadioQueue.Add(SFX_POLICE_RADIO_MESSAGE_NOISE_1);\n\t\t\t\tm_sPoliceRadioQueue.Add(NO_SAMPLE);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\tm_sPoliceRadioQueue.crimes[i].type = CRIME_NONE;\n\tAgeCrimes();\n\treturn true;\n}\n\nvoid\ncAudioManager::SetupSuspectLastSeenReport()\n{\n\tCVehicle *veh;\n\tuint8 color1;\n\tint32 main_color;\n\tint32 sample;\n\n\tint32 color_pre_modifier;\n\tint32 color_post_modifier;\n\n\tconst int32 gCarColourTable[][3] = {\n\t\t{NO_SAMPLE, SFX_POLICE_RADIO_BLACK, NO_SAMPLE},\n\t\t{NO_SAMPLE, SFX_POLICE_RADIO_WHITE, NO_SAMPLE},\n\t\t{NO_SAMPLE, SFX_POLICE_RADIO_BLUE, NO_SAMPLE},\n\t\t{NO_SAMPLE, SFX_POLICE_RADIO_RED, NO_SAMPLE},\n\t\t{SFX_POLICE_RADIO_DARK, SFX_POLICE_RADIO_BLUE, NO_SAMPLE},\n\t\t{NO_SAMPLE, SFX_POLICE_RADIO_PURPLE, NO_SAMPLE},\n\t\t{NO_SAMPLE, SFX_POLICE_RADIO_YELLOW, NO_SAMPLE},\n\t\t{SFX_POLICE_RADIO_BRIGHT, SFX_POLICE_RADIO_BLUE, NO_SAMPLE},\n\t\t{SFX_POLICE_RADIO_LIGHT, SFX_POLICE_RADIO_BLUE, SFX_POLICE_RADIO_GREY},\n\t\t{SFX_POLICE_RADIO_LIGHT, NO_SAMPLE, NO_SAMPLE},\n\t\t{SFX_POLICE_RADIO_DARK, NO_SAMPLE, NO_SAMPLE},\n\t\t{SFX_POLICE_RADIO_DARK, NO_SAMPLE, NO_SAMPLE},\n\t\t{SFX_POLICE_RADIO_DARK, SFX_POLICE_RADIO_RED, NO_SAMPLE},\n\t\t{NO_SAMPLE, SFX_POLICE_RADIO_RED, NO_SAMPLE},\n\t\t{NO_SAMPLE, SFX_POLICE_RADIO_RED, NO_SAMPLE},\n\t\t{NO_SAMPLE, SFX_POLICE_RADIO_RED, NO_SAMPLE},\n\t\t{NO_SAMPLE, SFX_POLICE_RADIO_RED, NO_SAMPLE},\n\t\t{NO_SAMPLE, SFX_POLICE_RADIO_RED, NO_SAMPLE},\n\t\t{NO_SAMPLE, SFX_POLICE_RADIO_RED, NO_SAMPLE},\n\t\t{SFX_POLICE_RADIO_LIGHT, NO_SAMPLE, NO_SAMPLE},\n\t\t{SFX_POLICE_RADIO_DARK, NO_SAMPLE, NO_SAMPLE},\n\t\t{SFX_POLICE_RADIO_DARK, NO_SAMPLE, NO_SAMPLE},\n\t\t{SFX_POLICE_RADIO_DARK, NO_SAMPLE, NO_SAMPLE},\n\t\t{NO_SAMPLE, SFX_POLICE_RADIO_ORANGE, NO_SAMPLE},\n\t\t{NO_SAMPLE, SFX_POLICE_RADIO_ORANGE, NO_SAMPLE},\n\t\t{NO_SAMPLE, SFX_POLICE_RADIO_ORANGE, NO_SAMPLE},\n\t\t{NO_SAMPLE, SFX_POLICE_RADIO_ORANGE, NO_SAMPLE},\n\t\t{NO_SAMPLE, SFX_POLICE_RADIO_ORANGE, NO_SAMPLE},\n\t\t{NO_SAMPLE, SFX_POLICE_RADIO_ORANGE, NO_SAMPLE},\n\t\t{SFX_POLICE_RADIO_LIGHT, NO_SAMPLE, NO_SAMPLE},\n\t\t{SFX_POLICE_RADIO_DARK, NO_SAMPLE, NO_SAMPLE},\n\t\t{SFX_POLICE_RADIO_DARK, NO_SAMPLE, NO_SAMPLE},\n\t\t{SFX_POLICE_RADIO_DARK, NO_SAMPLE, NO_SAMPLE},\n\t\t{NO_SAMPLE, SFX_POLICE_RADIO_YELLOW, NO_SAMPLE},\n\t\t{NO_SAMPLE, SFX_POLICE_RADIO_YELLOW, NO_SAMPLE},\n\t\t{NO_SAMPLE, SFX_POLICE_RADIO_YELLOW, NO_SAMPLE},\n\t\t{NO_SAMPLE, SFX_POLICE_RADIO_YELLOW, NO_SAMPLE},\n\t\t{NO_SAMPLE, SFX_POLICE_RADIO_YELLOW, NO_SAMPLE},\n\t\t{NO_SAMPLE, SFX_POLICE_RADIO_YELLOW, NO_SAMPLE},\n\t\t{SFX_POLICE_RADIO_LIGHT, NO_SAMPLE, NO_SAMPLE},\n\t\t{SFX_POLICE_RADIO_DARK, NO_SAMPLE, NO_SAMPLE},\n\t\t{SFX_POLICE_RADIO_DARK, NO_SAMPLE, NO_SAMPLE},\n\t\t{SFX_POLICE_RADIO_DARK, NO_SAMPLE, NO_SAMPLE},\n\t\t{NO_SAMPLE, SFX_POLICE_RADIO_GREEN, NO_SAMPLE},\n\t\t{NO_SAMPLE, SFX_POLICE_RADIO_GREEN, NO_SAMPLE},\n\t\t{NO_SAMPLE, SFX_POLICE_RADIO_GREEN, NO_SAMPLE},\n\t\t{NO_SAMPLE, SFX_POLICE_RADIO_GREEN, NO_SAMPLE},\n\t\t{NO_SAMPLE, SFX_POLICE_RADIO_GREEN, NO_SAMPLE},\n\t\t{NO_SAMPLE, SFX_POLICE_RADIO_GREEN, NO_SAMPLE},\n\t\t{SFX_POLICE_RADIO_LIGHT, NO_SAMPLE, NO_SAMPLE},\n\t\t{SFX_POLICE_RADIO_DARK, NO_SAMPLE, NO_SAMPLE},\n\t\t{SFX_POLICE_RADIO_DARK, NO_SAMPLE, NO_SAMPLE},\n\t\t{SFX_POLICE_RADIO_DARK, NO_SAMPLE, NO_SAMPLE},\n\t\t{NO_SAMPLE, SFX_POLICE_RADIO_BLUE, NO_SAMPLE},\n\t\t{NO_SAMPLE, SFX_POLICE_RADIO_BLUE, NO_SAMPLE},\n\t\t{NO_SAMPLE, SFX_POLICE_RADIO_BLUE, NO_SAMPLE},\n\t\t{NO_SAMPLE, SFX_POLICE_RADIO_BLUE, NO_SAMPLE},\n\t\t{NO_SAMPLE, SFX_POLICE_RADIO_BLUE, NO_SAMPLE},\n\t\t{NO_SAMPLE, SFX_POLICE_RADIO_BLUE, NO_SAMPLE},\n\t\t{SFX_POLICE_RADIO_LIGHT, NO_SAMPLE, NO_SAMPLE},\n\t\t{SFX_POLICE_RADIO_DARK, NO_SAMPLE, NO_SAMPLE},\n\t\t{SFX_POLICE_RADIO_DARK, NO_SAMPLE, NO_SAMPLE},\n\t\t{SFX_POLICE_RADIO_DARK, NO_SAMPLE, NO_SAMPLE},\n\t\t{NO_SAMPLE, SFX_POLICE_RADIO_PURPLE, NO_SAMPLE},\n\t\t{NO_SAMPLE, SFX_POLICE_RADIO_PURPLE, NO_SAMPLE},\n\t\t{NO_SAMPLE, SFX_POLICE_RADIO_PURPLE, NO_SAMPLE},\n\t\t{NO_SAMPLE, SFX_POLICE_RADIO_PURPLE, NO_SAMPLE},\n\t\t{NO_SAMPLE, SFX_POLICE_RADIO_PURPLE, NO_SAMPLE},\n\t\t{NO_SAMPLE, SFX_POLICE_RADIO_PURPLE, NO_SAMPLE},\n\t\t{SFX_POLICE_RADIO_LIGHT, NO_SAMPLE, NO_SAMPLE},\n\t\t{SFX_POLICE_RADIO_DARK, NO_SAMPLE, NO_SAMPLE},\n\t\t{SFX_POLICE_RADIO_DARK, NO_SAMPLE, NO_SAMPLE},\n\t\t{SFX_POLICE_RADIO_DARK, NO_SAMPLE, NO_SAMPLE},\n\t\t{NO_SAMPLE, SFX_POLICE_RADIO_SILVER, NO_SAMPLE},\n\t\t{NO_SAMPLE, SFX_POLICE_RADIO_SILVER, NO_SAMPLE},\n\t\t{NO_SAMPLE, SFX_POLICE_RADIO_SILVER, NO_SAMPLE},\n\t\t{NO_SAMPLE, SFX_POLICE_RADIO_SILVER, NO_SAMPLE},\n\t\t{NO_SAMPLE, SFX_POLICE_RADIO_SILVER, NO_SAMPLE},\n\t\t{NO_SAMPLE, SFX_POLICE_RADIO_SILVER, NO_SAMPLE},\n\t\t{SFX_POLICE_RADIO_LIGHT, NO_SAMPLE, NO_SAMPLE},\n\t\t{SFX_POLICE_RADIO_LIGHT, NO_SAMPLE, NO_SAMPLE},\n\t\t{SFX_POLICE_RADIO_LIGHT, NO_SAMPLE, NO_SAMPLE},\n\t\t{SFX_POLICE_RADIO_LIGHT, NO_SAMPLE, NO_SAMPLE},\n\t\t{SFX_POLICE_RADIO_LIGHT, NO_SAMPLE, NO_SAMPLE},\n\t\t{SFX_POLICE_RADIO_LIGHT, NO_SAMPLE, NO_SAMPLE},\n\t\t{SFX_POLICE_RADIO_LIGHT, NO_SAMPLE, NO_SAMPLE},\n\t\t{SFX_POLICE_RADIO_LIGHT, NO_SAMPLE, NO_SAMPLE},\n\t\t{SFX_POLICE_RADIO_LIGHT, NO_SAMPLE, NO_SAMPLE},\n\t\t{SFX_POLICE_RADIO_LIGHT, NO_SAMPLE, NO_SAMPLE},\n\t\t{SFX_POLICE_RADIO_LIGHT, NO_SAMPLE, NO_SAMPLE},\n\t\t{SFX_POLICE_RADIO_DARK, NO_SAMPLE, NO_SAMPLE},\n\t\t{SFX_POLICE_RADIO_DARK, NO_SAMPLE, NO_SAMPLE},\n\t\t{SFX_POLICE_RADIO_DARK, NO_SAMPLE, NO_SAMPLE},\n\t\t{SFX_POLICE_RADIO_DARK, NO_SAMPLE, NO_SAMPLE},\n\t\t{SFX_POLICE_RADIO_DARK, NO_SAMPLE, NO_SAMPLE}\n\t};\n\n\tif (MusicManager.m_nMusicMode != MUSICMODE_CUTSCENE) {\n\t\tveh = FindVehicleOfPlayer();\n\t\tif (veh != nil) {\n\t\t\tif (60 - m_sPoliceRadioQueue.policeChannelTimer > 9) {\n\t\t\t\tcolor1 = veh->m_currentColour1;\n\t\t\t\tif (color1 >= ARRAY_SIZE(gCarColourTable)) {\n\t\t\t\t\tdebug(\"\\n *** UNKNOWN CAR COLOUR %d *** \", color1);\n\t\t\t\t} else {\n\t\t\t\t\tmain_color = gCarColourTable[color1][1];\n\t\t\t\t\tcolor_pre_modifier = gCarColourTable[color1][0];\n\t\t\t\t\tcolor_post_modifier = gCarColourTable[color1][2];\n\t\t\t\t\tswitch (veh->GetModelIndex()) {\n\t\t\t\t\tcase MI_LANDSTAL:\n\t\t\t\t\tcase MI_PATRIOT:\n\t\t\t\t\tcase MI_RANCHER:\n\t\t\t\t\tcase MI_FBIRANCH:\n\t\t\t\t\tcase MI_SANDKING:\n\t\t\t\t\t\tsample = SFX_POLICE_RADIO_OFFROAD;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase MI_IDAHO:\n\t\t\t\t\tcase MI_MANANA:\n\t\t\t\t\tcase MI_ESPERANT:\n\t\t\t\t\tcase MI_CUBAN:\n\t\t\t\t\tcase MI_STALLION:\n\t\t\t\t\tcase MI_SABRE:\n\t\t\t\t\tcase MI_SABRETUR:\n\t\t\t\t\tcase MI_VIRGO:\n\t\t\t\t\tcase MI_BLISTAC:\n\t\t\t\t\t\t\tsample = SFX_POLICE_RADIO_2_DOOR;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase MI_STINGER:\n\t\t\t\t\tcase MI_INFERNUS:\n\t\t\t\t\tcase MI_CHEETAH:\n\t\t\t\t\tcase MI_BANSHEE:\n\t\t\t\t\tcase MI_PHEONIX:\n\t\t\t\t\tcase MI_COMET:\n\t\t\t\t\tcase MI_DELUXO:\n\t\t\t\t\tcase MI_HOTRING:\n\t\t\t\t\t\tsample = SFX_POLICE_RADIO_SPORTS_CAR;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase MI_LINERUN:\n\t\t\t\t\t\tsample = SFX_POLICE_RADIO_RIG;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase MI_PEREN:\n\t\t\t\t\tcase MI_REGINA:\n\t\t\t\t\t\tsample = SFX_POLICE_RADIO_STATION_WAGON;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase MI_SENTINEL:\n\t\t\t\t\tcase MI_FBICAR:\n\t\t\t\t\tcase MI_WASHING:\n\t\t\t\t\tcase MI_SENTXS:\n\t\t\t\t\tcase MI_ADMIRAL:\n\t\t\t\t\tcase MI_GLENDALE:\n\t\t\t\t\tcase MI_OCEANIC:\n\t\t\t\t\tcase MI_HERMES:\n\t\t\t\t\tcase MI_GREENWOO:\n\t\t\t\t\t\tsample = SFX_POLICE_RADIO_SEDAN;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase MI_RIO:\n\t\t\t\t\t\tsample = SFX_POLICE_RADIO_CRUISER;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase MI_FIRETRUCK:\n\t\t\t\t\t\tsample = SFX_POLICE_RADIO_FIRE_TRUCK;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase MI_TRASH:\n\t\t\t\t\t\tsample = SFX_POLICE_RADIO_GARBAGE_TRUCK;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase MI_STRETCH:\n\t\t\t\t\tcase MI_LOVEFIST:\n\t\t\t\t\t\tsample = SFX_POLICE_RADIO_STRETCH;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase MI_VOODOO:\n\t\t\t\t\t\tsample = SFX_POLICE_RADIO_LOWRIDER;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase MI_PONY:\n\t\t\t\t\tcase MI_MOONBEAM:\n\t\t\t\t\tcase MI_SECURICA:\n\t\t\t\t\tcase MI_RUMPO:\n\t\t\t\t\tcase MI_GANGBUR:\n\t\t\t\t\tcase MI_YANKEE:\n\t\t\t\t\tcase MI_TOPFUN:\n\t\t\t\t\tcase MI_BURRITO:\n\t\t\t\t\tcase MI_SPAND:\n\t\t\t\t\t\tsample = SFX_POLICE_RADIO_VAN;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase MI_MULE:\n\t\t\t\t\tcase MI_BARRACKS:\n\t\t\t\t\tcase MI_PACKER:\n\t\t\t\t\tcase MI_FLATBED:\n\t\t\t\t\t\tsample = SFX_POLICE_RADIO_TRUCK;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase MI_AMBULAN:\n\t\t\t\t\t\tsample = SFX_POLICE_RADIO_AMBULANCE;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase MI_TAXI:\n\t\t\t\t\tcase MI_CABBIE:\n\t\t\t\t\tcase MI_ZEBRA:\n\t\t\t\t\tcase MI_KAUFMAN:\n\t\t\t\t\t\tsample = SFX_POLICE_RADIO_TAXI;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase MI_BOBCAT:\n\t\t\t\t\tcase MI_WALTON:\n\t\t\t\t\t\tsample = SFX_POLICE_RADIO_PICKUP;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase MI_MRWHOOP:\n\t\t\t\t\t\tsample = SFX_POLICE_RADIO_ICE_CREAM_VAN;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase MI_BFINJECT:\n\t\t\t\t\t\tsample = SFX_POLICE_RADIO_BUGGY;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase MI_HUNTER:\n\t\t\t\t\tcase MI_CHOPPER:\n\t\t\t\t\tcase MI_SEASPAR:\n\t\t\t\t\tcase MI_SPARROW:\n\t\t\t\t\tcase MI_MAVERICK:\n\t\t\t\t\tcase MI_VCNMAV:\n\t\t\t\t\tcase MI_POLMAV:\n\t\t\t\t\t\tsample = SFX_POLICE_RADIO_HELICOPTER;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase MI_POLICE:\n\t\t\t\t\t\tsample = SFX_POLICE_RADIO_POLICE_CAR;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase MI_ENFORCER:\n\t\t\t\t\t\tsample = SFX_POLICE_RADIO_SWAT_VAN;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase MI_PREDATOR:\n\t\t\t\t\tcase MI_SQUALO:\n\t\t\t\t\tcase MI_SPEEDER:\n\t\t\t\t\t\tsample = SFX_POLICE_RADIO_SPEEDBOAT;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase MI_BUS:\n\t\t\t\t\t\tsample = SFX_POLICE_RADIO_BUS;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase MI_RHINO:\n\t\t\t\t\t\tsample = SFX_POLICE_RADIO_TANK;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase MI_ANGEL:\n\t\t\t\t\tcase MI_PCJ600:\n\t\t\t\t\tcase MI_FREEWAY:\n\t\t\t\t\tcase MI_SANCHEZ:\n\t\t\t\t\t\tsample = SFX_POLICE_RADIO_MOTOBIKE;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase MI_COACH:\n\t\t\t\t\t\tsample = SFX_POLICE_RADIO_COACH;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase MI_ROMERO:\n\t\t\t\t\t\tsample = SFX_POLICE_RADIO_HEARSE;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase MI_PIZZABOY:\n\t\t\t\t\tcase MI_FAGGIO:\n\t\t\t\t\t\tsample = SFX_POLICE_RADIO_MOPED;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase MI_DEADDODO:\n\t\t\t\t\tcase MI_SKIMMER:\n\t\t\t\t\t\tsample = SFX_POLICE_RADIO_PLANE;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase MI_REEFER:\n\t\t\t\t\tcase MI_TROPIC:\n\t\t\t\t\tcase MI_COASTG:\n\t\t\t\t\tcase MI_MARQUIS:\n\t\t\t\t\tcase MI_JETMAX:\n\t\t\t\t\t\tsample = SFX_POLICE_RADIO_BOAT;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase MI_CADDY:\n\t\t\t\t\t\tsample = SFX_POLICE_RADIO_GOLF_CART;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase MI_DINGHY:\n\t\t\t\t\t\tsample = SFX_POLICE_RADIO_DINGHY;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\t//debug(\"\\n *** UNKNOWN CAR MODEL INDEX %d *** \", veh->GetModelIndex());\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tm_sPoliceRadioQueue.Add(SFX_POLICE_RADIO_MESSAGE_NOISE_1);\n\t\t\t\t\tm_sPoliceRadioQueue.Add(SFX_POLICE_RADIO_SUSPECT);\n\t\t\t\t\tif (m_anRandomTable[3] % 2) \n\t\t\t\t\t\tm_sPoliceRadioQueue.Add(SFX_POLICE_RADIO_LAST_SEEN);\n\t\t\t\t\tm_sPoliceRadioQueue.Add(SFX_POLICE_RADIO_IN_A);\n\t\t\t\t\tif (color_pre_modifier != NO_SAMPLE)\n\t\t\t\t\t\tm_sPoliceRadioQueue.Add(color_pre_modifier);\n\t\t\t\t\tif (main_color != NO_SAMPLE)\n\t\t\t\t\t\tm_sPoliceRadioQueue.Add(main_color);\n\t\t\t\t\tif (color_post_modifier != NO_SAMPLE)\n\t\t\t\t\t\tm_sPoliceRadioQueue.Add(color_post_modifier);\n\t\t\t\t\tm_sPoliceRadioQueue.Add(sample);\n\t\t\t\t\tm_sPoliceRadioQueue.Add(SFX_POLICE_RADIO_MESSAGE_NOISE_1);\n\t\t\t\t\tm_sPoliceRadioQueue.Add(NO_SAMPLE);\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (60 - m_sPoliceRadioQueue.policeChannelTimer > 4) {\n\t\t\tm_sPoliceRadioQueue.Add(SFX_POLICE_RADIO_MESSAGE_NOISE_1);\n\t\t\tm_sPoliceRadioQueue.Add(SFX_POLICE_RADIO_SUSPECT);\n\t\t\tm_sPoliceRadioQueue.Add(SFX_POLICE_RADIO_ON_FOOT);\n\t\t\tm_sPoliceRadioQueue.Add(SFX_POLICE_RADIO_MESSAGE_NOISE_1);\n\t\t\tm_sPoliceRadioQueue.Add(NO_SAMPLE);\n\t\t}\n\t}\n}\n\nvoid\ncAudioManager::ReportCrime(eCrimeType type, const CVector &pos)\n{\n\tint32 lastCrime = ARRAY_SIZE(m_sPoliceRadioQueue.crimes);\n\tif (m_bIsInitialised && MusicManager.m_nMusicMode != MUSICMODE_CUTSCENE && FindPlayerPed()->m_pWanted->GetWantedLevel() > 0 &&\n\t\t(type > CRIME_NONE || type < NUM_CRIME_TYPES) && m_FrameCounter >= gMinTimeToNextReport[type]) {\n\t\tfor (int32 i = 0; i < ARRAY_SIZE(m_sPoliceRadioQueue.crimes); i++) {\n\t\t\tif (m_sPoliceRadioQueue.crimes[i].type != CRIME_NONE) {\n\t\t\t\tif (m_sPoliceRadioQueue.crimes[i].type == type) {\n\t\t\t\t\tm_sPoliceRadioQueue.crimes[i].position = pos;\n\t\t\t\t\tm_sPoliceRadioQueue.crimes[i].timer = 0;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t} else\n\t\t\t\tlastCrime = i;\n\t\t}\n\n\t\tif (lastCrime < ARRAY_SIZE(m_sPoliceRadioQueue.crimes)) {\n\t\t\tm_sPoliceRadioQueue.crimes[lastCrime].type = type;\n\t\t\tm_sPoliceRadioQueue.crimes[lastCrime].position = pos;\n\t\t\tm_sPoliceRadioQueue.crimes[lastCrime].timer = 0;\n\t\t\tgMinTimeToNextReport[type] = m_FrameCounter + 500;\n\t\t}\n\t}\n}\n\nvoid\ncAudioManager::PlaySuspectLastSeen(float x, float y, float z)\n{\n\tint16 audioZone;\n\tCZone *zone;\n\tfloat rangeX;\n\tfloat rangeY;\n\tfloat halfX;\n\tfloat halfY;\n\tfloat quarterX;\n\tfloat quarterY;\n\tint32 sample;\n\tbool processed = false;\n\tCVector vec = CVector(x, y, z);\n\n\tif (!m_bIsInitialised) return;\n\n\tif (MusicManager.m_nMusicMode != MUSICMODE_CUTSCENE && 60 - m_sPoliceRadioQueue.policeChannelTimer > 9) {\n\t\taudioZone = CTheZones::FindAudioZone(&vec);\n\t\tif (audioZone >= 0 && audioZone < NUMAUDIOZONES) {\n\t\t\tzone = CTheZones::GetAudioZone(audioZone);\n\t\t\tfor (int i = 0; i < NUMAUDIOZONES; i++) {\n\t\t\t\tif (strcmp(zone->name, ZoneSfx[i].m_aName) == 0) {\n\t\t\t\t\tsample = ZoneSfx[i].m_nSampleIndex;\n\t\t\t\t\tm_sPoliceRadioQueue.Add(SFX_POLICE_RADIO_MESSAGE_NOISE_1);\n\t\t\t\t\tm_sPoliceRadioQueue.Add(SFX_POLICE_RADIO_SUSPECT);\n\t\t\t\t\tm_sPoliceRadioQueue.Add(SFX_POLICE_RADIO_LAST_SEEN);\n\t\t\t\t\tm_sPoliceRadioQueue.Add(SFX_IN);\n\t\t\t\t\trangeX = zone->maxx - zone->minx;\n\t\t\t\t\trangeY = zone->maxy - zone->miny;\n\t\t\t\t\thalfX = 0.5f * rangeX + zone->minx;\n\t\t\t\t\thalfY = 0.5f * rangeY + zone->miny;\n\t\t\t\t\tquarterX = 0.25f * rangeX;\n\t\t\t\t\tquarterY = 0.25f * rangeY;\n\n\t\t\t\t\tif (vec.y > halfY + quarterY) {\n\t\t\t\t\t\tm_sPoliceRadioQueue.Add(SFX_NORTH);\n\t\t\t\t\t\tprocessed = true;\n\t\t\t\t\t} else if (vec.y < halfY - quarterY) {\n\t\t\t\t\t\tm_sPoliceRadioQueue.Add(SFX_SOUTH);\n\t\t\t\t\t\tprocessed = true;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (vec.x > halfX + quarterX)\n\t\t\t\t\t\tm_sPoliceRadioQueue.Add(SFX_EAST);\n\t\t\t\t\telse if (vec.x < halfX - quarterX)\n\t\t\t\t\t\tm_sPoliceRadioQueue.Add(SFX_WEST);\n\t\t\t\t\telse if (!processed)\n\t\t\t\t\t\tm_sPoliceRadioQueue.Add(SFX_CENTRAL);\n\t\t\t\t\tm_sPoliceRadioQueue.Add(sample);\n\t\t\t\t\tm_sPoliceRadioQueue.Add(SFX_POLICE_RADIO_MESSAGE_NOISE_1);\n\t\t\t\t\tm_sPoliceRadioQueue.Add(NO_SAMPLE);\n\t\t\t\t\tgSpecialSuspectLastSeenReport = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\ncAudioManager::AgeCrimes()\n{\n\tfor (uint8 i = 0; i < ARRAY_SIZE(m_sPoliceRadioQueue.crimes); i++) {\n\t\tif (m_sPoliceRadioQueue.crimes[i].type != CRIME_NONE) {\n\t\t\tif (++m_sPoliceRadioQueue.crimes[i].timer > 1200) m_sPoliceRadioQueue.crimes[i].type = CRIME_NONE;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/audio/PoliceRadio.h",
    "content": "#pragma once\n\n#include \"Crime.h\"\n\nstruct cAMCrime {\n\tint32 type;\n\tCVector position;\n\tuint16 timer;\n\n\tcAMCrime()\n\t{\n\t\ttype = CRIME_NONE;\n\t\tposition = CVector(0.0f, 0.0f, 0.0f);\n\t\ttimer = 0;\n\t}\n};\n\nVALIDATE_SIZE(cAMCrime, 20);\n\nclass cPoliceRadioQueue\n{\npublic:\n\tint32 crimesSamples[60];\n\tuint8 policeChannelTimer;\n\tuint8 policeChannelTimerSeconds;\n\tuint8 policeChannelCounterSeconds;\n\tcAMCrime crimes[10];\n\n\tcPoliceRadioQueue()\n\t{\n\t\tpoliceChannelTimerSeconds = 0;\n\t\tpoliceChannelCounterSeconds = 0;\n\t\tpoliceChannelTimer = 0;\n\t}\n\n\tvoid Add(uint32 sample)\n\t{\n\t\tif (policeChannelTimer != 60) {\n\t\t\tcrimesSamples[policeChannelTimerSeconds] = sample;\n\t\t\tpoliceChannelTimer++;\n\t\t\tpoliceChannelTimerSeconds = (policeChannelTimerSeconds + 1) % 60;\n\t\t}\n\t}\n};\n\nVALIDATE_SIZE(cPoliceRadioQueue, 0x1BC);\n"
  },
  {
    "path": "src/audio/audio_enums.h",
    "content": "#pragma once\n\nenum eRadioStation\n{\n\tWILDSTYLE,\n\tFLASH_FM,\n\tKCHAT,\n\tFEVER,\n\tV_ROCK,\n\tVCPR,\n\tRADIO_ESPANTOSO,\n\tEMOTION,\n\tWAVE,\n\tUSERTRACK,\n\tNUM_RADIOS = 10,\n\tPOLICE_RADIO = 10,\n\tRADIO_OFF = 10,\n\t//TAXI_RADIO,\n};\n\nenum eMusicMode\n{\n\tMUSICMODE_FRONTEND = 0,\n\tMUSICMODE_GAME,\n\tMUSICMODE_CUTSCENE,\n\tMUSICMODE_DISABLE,\n\tMUSICMODE_DISABLED,\n};\n\nenum ePlayerMood\n{\n\tPLAYER_MOOD_CALM = 0,\n\tPLAYER_MOOD_PISSED_OFF,\n\tPLAYER_MOOD_ANGRY,\n\tPLAYER_MOOD_WISECRACKING,\n\tMAX_PLAYER_MOODS,\n};\n\nenum eStreamedSounds\n{\n\tSTREAMED_SOUND_RADIO_WILD,\n\tSTREAMED_SOUND_RADIO_FLASH,\n\tSTREAMED_SOUND_RADIO_KCHAT,\n\tSTREAMED_SOUND_RADIO_FEVER,\n\tSTREAMED_SOUND_RADIO_VROCK,\n\tSTREAMED_SOUND_RADIO_VCPR,\n\tSTREAMED_SOUND_RADIO_ESPANTOSO,\n\tSTREAMED_SOUND_RADIO_EMOTION,\n\tSTREAMED_SOUND_RADIO_WAVE,\n\tSTREAMED_SOUND_RADIO_MP3_PLAYER,\n\tSTREAMED_SOUND_CITY_AMBIENT,\n\tSTREAMED_SOUND_WATER_AMBIENT,\n\tSTREAMED_SOUND_BEACH_AMBIENT,\n\tSTREAMED_SOUND_HAVANA_CITY_AMBIENT,\n\tSTREAMED_SOUND_HAVANA_WATER_AMBIENT,\n\tSTREAMED_SOUND_HAVANA_BEACH_AMBIENT,\n\tSTREAMED_SOUND_MALL_AMBIENT,\n\tSTREAMED_SOUND_STRIPCLUB_AMBIENT,\n\tSTREAMED_SOUND_MALIBU_AMBIENT,\n\tSTREAMED_SOUND_HOTEL_AMBIENT,\n\tSTREAMED_SOUND_DIRTRING_AMBIENT,\n\tSTREAMED_SOUND_LAW4RIOT_AMBIENT,\n\tSTREAMED_SOUND_AMBSIL_AMBIENT,\n\tSTREAMED_SOUND_RADIO_POLICE,\n\tSTREAMED_SOUND_RADIO_TAXI,\n\tSTREAMED_SOUND_ANNOUNCE_BRIDGE_CLOSED,\n\tSTREAMED_SOUND_ANNOUNCE_BRIDGE_OPEN,\n\tSTREAMED_SOUND_CUTSCENE_ASS_1,\n\tSTREAMED_SOUND_CUTSCENE_ASS_2,\n\tSTREAMED_SOUND_CUTSCENE_BANK_1,\n\tSTREAMED_SOUND_CUTSCENE_BANK_2A,\n\tSTREAMED_SOUND_CUTSCENE_BANK_2B,\n\tSTREAMED_SOUND_CUTSCENE_BANK_3A,\n\tSTREAMED_SOUND_CUTSCENE_BANK_3B,\n\tSTREAMED_SOUND_CUTSCENE_BANK_4,\n\tSTREAMED_SOUND_CUTSCENE_BIKE_1,\n\tSTREAMED_SOUND_CUTSCENE_BIKE_2,\n\tSTREAMED_SOUND_CUTSCENE_BIKE_3,\n\tSTREAMED_SOUND_CUTSCENE_BUD_1,\n\tSTREAMED_SOUND_CUTSCENE_BUD_2,\n\tSTREAMED_SOUND_CUTSCENE_BUD_3,\n\tSTREAMED_SOUND_CUTSCENE_CAP_1,\n\tSTREAMED_SOUND_CUTSCENE_CAR_1,\n\tSTREAMED_SOUND_CUTSCENE_CNT_1A,\n\tSTREAMED_SOUND_CUTSCENE_CNT_1B,\n\tSTREAMED_SOUND_CUTSCENE_CNT_2,\n\tSTREAMED_SOUND_CUTSCENE_COK_1,\n\tSTREAMED_SOUND_CUTSCENE_COK_2A,\n\tSTREAMED_SOUND_CUTSCENE_COK_2B,\n\tSTREAMED_SOUND_CUTSCENE_COK_3,\n\tSTREAMED_SOUND_CUTSCENE_COK_4A,\n\tSTREAMED_SOUND_CUTSCENE_COK_4A2,\n\tSTREAMED_SOUND_CUTSCENE_COK_4B,\n\tSTREAMED_SOUND_CUTSCENE_COL_1,\n\tSTREAMED_SOUND_CUTSCENE_COL_2,\n\tSTREAMED_SOUND_CUTSCENE_COL_3A,\n\tSTREAMED_SOUND_CUTSCENE_COL_4A,\n\tSTREAMED_SOUND_CUTSCENE_COL_5A,\n\tSTREAMED_SOUND_CUTSCENE_COL_5B,\n\tSTREAMED_SOUND_CUTSCENE_CUB_1,\n\tSTREAMED_SOUND_CUTSCENE_CUB_2,\n\tSTREAMED_SOUND_CUTSCENE_CUB_3,\n\tSTREAMED_SOUND_CUTSCENE_CUB_4,\n\tSTREAMED_SOUND_CUTSCENE_DRUG_1,\n\tSTREAMED_SOUND_CUTSCENE_FIN,\n\tSTREAMED_SOUND_CUTSCENE_FIN2,\n\tSTREAMED_SOUND_CUTSCENE_FINALE,\n\tSTREAMED_SOUND_CUTSCENE_HAT_1,\n\tSTREAMED_SOUND_CUTSCENE_HAT_2,\n\tSTREAMED_SOUND_CUTSCENE_HAT_3,\n\tSTREAMED_SOUND_CUTSCENE_ICE_1,\n\tSTREAMED_SOUND_CUTSCENE_INT_A,\n\tSTREAMED_SOUND_CUTSCENE_INT_B,\n\tSTREAMED_SOUND_CUTSCENE_INT_D,\n\tSTREAMED_SOUND_CUTSCENE_INT_M,\n\tSTREAMED_SOUND_CUTSCENE_LAW_1A,\n\tSTREAMED_SOUND_CUTSCENE_LAW_1B,\n\tSTREAMED_SOUND_CUTSCENE_LAW_2A,\n\tSTREAMED_SOUND_CUTSCENE_LAW_2B,\n\tSTREAMED_SOUND_CUTSCENE_LAW_2C,\n\tSTREAMED_SOUND_CUTSCENE_LAW_3,\n\tSTREAMED_SOUND_CUTSCENE_LAW_4,\n\tSTREAMED_SOUND_CUTSCENE_PHIL_1,\n\tSTREAMED_SOUND_CUTSCENE_PHIL_2,\n\tSTREAMED_SOUND_CUTSCENE_PORN_1,\n\tSTREAMED_SOUND_CUTSCENE_PORN_2,\n\tSTREAMED_SOUND_CUTSCENE_PORN_3,\n\tSTREAMED_SOUND_CUTSCENE_PORN_4,\n\tSTREAMED_SOUND_CUTSCENE_RESC_1A,\n\tSTREAMED_SOUND_CUTSCENE_ROK_1,\n\tSTREAMED_SOUND_CUTSCENE_ROK_2,\n\tSTREAMED_SOUND_CUTSCENE_ROK_3A,\n\tSTREAMED_SOUND_CUTSCENE_STRIPA,\n\tSTREAMED_SOUND_CUTSCENE_TAX_1,\n\tSTREAMED_SOUND_CUTSCENE_TEX_1,\n\tSTREAMED_SOUND_CUTSCENE_TEX_2,\n\tSTREAMED_SOUND_CUTSCENE_TEX_3,\n\tSTREAMED_SOUND_CUTSCENE_GLIGHT,\n\tSTREAMED_SOUND_CUTSCENE_FIST,\n\tSTREAMED_SOUND_CUTSCENE_ELBURRO1_PH1,\n\tSTREAMED_SOUND_CUTSCENE_ELBURRO2_PH2,\n\tSTREAMED_SOUND_MISSION_COMPLETED,\n\tSTREAMED_SOUND_MISSION_COMPLETED4,\n\tSTREAMED_SOUND_MISSION_MOBR1,\n\tSTREAMED_SOUND_MISSION_PAGER,\n\tSTREAMED_SOUND_MISSION_CARREV,\n\tSTREAMED_SOUND_MISSION_BIKEREV,\n\tSTREAMED_SOUND_MISSION_LIFTOP,\n\tSTREAMED_SOUND_MISSION_LIFTCL,\n\tSTREAMED_SOUND_MISSION_LIFTRUN,\n\tSTREAMED_SOUND_MISSION_LIFTBEL,\n\tSTREAMED_SOUND_MISSION_INLIFT,\n\tSTREAMED_SOUND_MISSION_SFX_01,\n\tSTREAMED_SOUND_MISSION_SFX_02,\n\tSTREAMED_SOUND_MISSION_CAMERAL,\n\tSTREAMED_SOUND_MISSION_CAMERAR,\n\tSTREAMED_SOUND_MISSION_CHEER1,\n\tSTREAMED_SOUND_MISSION_CHEER2,\n\tSTREAMED_SOUND_MISSION_CHEER3,\n\tSTREAMED_SOUND_MISSION_CHEER4,\n\tSTREAMED_SOUND_MISSION_OOH1,\n\tSTREAMED_SOUND_MISSION_OOH2,\n\tSTREAMED_SOUND_MISSION_RACE1,\n\tSTREAMED_SOUND_MISSION_RACE2,\n\tSTREAMED_SOUND_MISSION_RACE3,\n\tSTREAMED_SOUND_MISSION_RACE4,\n\tSTREAMED_SOUND_MISSION_RACE5,\n\tSTREAMED_SOUND_MISSION_RACE6,\n\tSTREAMED_SOUND_MISSION_RACE7,\n\tSTREAMED_SOUND_MISSION_RACE8,\n\tSTREAMED_SOUND_MISSION_RACE9,\n\tSTREAMED_SOUND_MISSION_RACE10,\n\tSTREAMED_SOUND_MISSION_RACE11,\n\tSTREAMED_SOUND_MISSION_RACE12,\n\tSTREAMED_SOUND_MISSION_RACE13,\n\tSTREAMED_SOUND_MISSION_RACE14,\n\tSTREAMED_SOUND_MISSION_RACE15,\n\tSTREAMED_SOUND_MISSION_HOT1,\n\tSTREAMED_SOUND_MISSION_HOT2,\n\tSTREAMED_SOUND_MISSION_HOT3,\n\tSTREAMED_SOUND_MISSION_HOT4,\n\tSTREAMED_SOUND_MISSION_HOT5,\n\tSTREAMED_SOUND_MISSION_HOT6,\n\tSTREAMED_SOUND_MISSION_HOT7,\n\tSTREAMED_SOUND_MISSION_HOT8,\n\tSTREAMED_SOUND_MISSION_HOT9,\n\tSTREAMED_SOUND_MISSION_HOT10,\n\tSTREAMED_SOUND_MISSION_HOT11,\n\tSTREAMED_SOUND_MISSION_HOT12,\n\tSTREAMED_SOUND_MISSION_HOT13,\n\tSTREAMED_SOUND_MISSION_HOT14,\n\tSTREAMED_SOUND_MISSION_HOT15,\n\tSTREAMED_SOUND_MISSION_LANSTP1,\n\tSTREAMED_SOUND_MISSION_LANSTP2,\n\tSTREAMED_SOUND_MISSION_LANAMU1,\n\tSTREAMED_SOUND_MISSION_LANAMU2,\n\tSTREAMED_SOUND_MISSION_AIRHORNL,\n\tSTREAMED_SOUND_MISSION_AIRHORNR,\n\tSTREAMED_SOUND_MISSION_SNIPSCRL,\n\tSTREAMED_SOUND_MISSION_SNIPSHORT,\n\tSTREAMED_SOUND_MISSION_BLOWROOF,\n\tSTREAMED_SOUND_MISSION_ASS_1,\n\tSTREAMED_SOUND_MISSION_ASS_2,\n\tSTREAMED_SOUND_MISSION_ASS_3,\n\tSTREAMED_SOUND_MISSION_ASS_4,\n\tSTREAMED_SOUND_MISSION_ASS_5,\n\tSTREAMED_SOUND_MISSION_ASS_6,\n\tSTREAMED_SOUND_MISSION_ASS_7,\n\tSTREAMED_SOUND_MISSION_ASS_8,\n\tSTREAMED_SOUND_MISSION_ASS_9,\n\tSTREAMED_SOUND_MISSION_ASS_10,\n\tSTREAMED_SOUND_MISSION_ASS_11,\n\tSTREAMED_SOUND_MISSION_ASS_12,\n\tSTREAMED_SOUND_MISSION_ASS_13,\n\tSTREAMED_SOUND_MISSION_ASS_14,\n\tSTREAMED_SOUND_MISSION_BIKE1_1,\n\tSTREAMED_SOUND_MISSION_BIKE1_2,\n\tSTREAMED_SOUND_MISSION_BIKE1_3,\n\tSTREAMED_SOUND_MISSION_BNK1_1,\n\tSTREAMED_SOUND_MISSION_BNK1_2,\n\tSTREAMED_SOUND_MISSION_BNK1_3,\n\tSTREAMED_SOUND_MISSION_BNK1_4,\n\tSTREAMED_SOUND_MISSION_BNK1_5,\n\tSTREAMED_SOUND_MISSION_BNK1_6,\n\tSTREAMED_SOUND_MISSION_BNK1_7,\n\tSTREAMED_SOUND_MISSION_BNK1_8,\n\tSTREAMED_SOUND_MISSION_BNK1_10,\n\tSTREAMED_SOUND_MISSION_BNK1_11,\n\tSTREAMED_SOUND_MISSION_BNK1_12,\n\tSTREAMED_SOUND_MISSION_BNK1_13,\n\tSTREAMED_SOUND_MISSION_BNK1_14,\n\tSTREAMED_SOUND_MISSION_BNK2_1,\n\tSTREAMED_SOUND_MISSION_BNK2_2,\n\tSTREAMED_SOUND_MISSION_BNK2_3,\n\tSTREAMED_SOUND_MISSION_BNK2_4,\n\tSTREAMED_SOUND_MISSION_BNK2_5,\n\tSTREAMED_SOUND_MISSION_BNK2_6,\n\tSTREAMED_SOUND_MISSION_BNK2_7,\n\tSTREAMED_SOUND_MISSION_BNK2_8,\n\tSTREAMED_SOUND_MISSION_BNK2_9,\n\tSTREAMED_SOUND_MISSION_BNK3_1,\n\tSTREAMED_SOUND_MISSION_BNK3_2,\n\tSTREAMED_SOUND_MISSION_BNK3_3A,\n\tSTREAMED_SOUND_MISSION_BNK3_3B,\n\tSTREAMED_SOUND_MISSION_BNK3_3C,\n\tSTREAMED_SOUND_MISSION_BNK3_4A,\n\tSTREAMED_SOUND_MISSION_BNK3_4B,\n\tSTREAMED_SOUND_MISSION_BNK3_4C,\n\tSTREAMED_SOUND_MISSION_BNK4_1,\n\tSTREAMED_SOUND_MISSION_BNK4_2,\n\tSTREAMED_SOUND_MISSION_BNK4_3A,\n\tSTREAMED_SOUND_MISSION_BNK4_3B,\n\tSTREAMED_SOUND_MISSION_BNK4_3C,\n\tSTREAMED_SOUND_MISSION_BNK4_3D,\n\tSTREAMED_SOUND_MISSION_BNK4_3E,\n\tSTREAMED_SOUND_MISSION_BNK4_3F,\n\tSTREAMED_SOUND_MISSION_BNK4_3G,\n\tSTREAMED_SOUND_MISSION_BNK4_3H,\n\tSTREAMED_SOUND_MISSION_BNK4_3I,\n\tSTREAMED_SOUND_MISSION_BNK4_3J,\n\tSTREAMED_SOUND_MISSION_BNK4_3K,\n\tSTREAMED_SOUND_MISSION_BNK4_3M,\n\tSTREAMED_SOUND_MISSION_BNK4_3O,\n\tSTREAMED_SOUND_MISSION_BNK4_3P,\n\tSTREAMED_SOUND_MISSION_BNK4_3Q,\n\tSTREAMED_SOUND_MISSION_BNK4_3R,\n\tSTREAMED_SOUND_MISSION_BNK4_3S,\n\tSTREAMED_SOUND_MISSION_BNK4_3T,\n\tSTREAMED_SOUND_MISSION_BNK4_3U,\n\tSTREAMED_SOUND_MISSION_BNK4_3V,\n\tSTREAMED_SOUND_MISSION_BNK4_4A,\n\tSTREAMED_SOUND_MISSION_BNK4_4B,\n\tSTREAMED_SOUND_MISSION_BNK4_5,\n\tSTREAMED_SOUND_MISSION_BNK4_6,\n\tSTREAMED_SOUND_MISSION_BNK4_7,\n\tSTREAMED_SOUND_MISSION_BNK4_8,\n\tSTREAMED_SOUND_MISSION_BNK4_9,\n\tSTREAMED_SOUND_MISSION_BNK4_10,\n\tSTREAMED_SOUND_MISSION_BNK4_11,\n\tSTREAMED_SOUND_MISSION_BK4_12A,\n\tSTREAMED_SOUND_MISSION_BK4_12B,\n\tSTREAMED_SOUND_MISSION_BK4_12C,\n\tSTREAMED_SOUND_MISSION_BNK4_13,\n\tSTREAMED_SOUND_MISSION_BK4_14A,\n\tSTREAMED_SOUND_MISSION_BK4_14B,\n\tSTREAMED_SOUND_MISSION_BNK4_15,\n\tSTREAMED_SOUND_MISSION_BNK4_16,\n\tSTREAMED_SOUND_MISSION_BNK4_17,\n\tSTREAMED_SOUND_MISSION_BNK4_18,\n\tSTREAMED_SOUND_MISSION_BK4_19A,\n\tSTREAMED_SOUND_MISSION_BK4_19B,\n\tSTREAMED_SOUND_MISSION_BK4_20A,\n\tSTREAMED_SOUND_MISSION_BK4_20B,\n\tSTREAMED_SOUND_MISSION_BNK4_21,\n\tSTREAMED_SOUND_MISSION_BNK422A,\n\tSTREAMED_SOUND_MISSION_BNK422B,\n\tSTREAMED_SOUND_MISSION_BK4_23A,\n\tSTREAMED_SOUND_MISSION_BK4_23B,\n\tSTREAMED_SOUND_MISSION_BK4_23C,\n\tSTREAMED_SOUND_MISSION_BK4_23D,\n\tSTREAMED_SOUND_MISSION_BK4_24A,\n\tSTREAMED_SOUND_MISSION_BK4_24B,\n\tSTREAMED_SOUND_MISSION_BNK4_25,\n\tSTREAMED_SOUND_MISSION_BNK4_26,\n\tSTREAMED_SOUND_MISSION_BNK4_27,\n\tSTREAMED_SOUND_MISSION_BNK4_28,\n\tSTREAMED_SOUND_MISSION_BNK4_29,\n\tSTREAMED_SOUND_MISSION_BNK4_30,\n\tSTREAMED_SOUND_MISSION_BK4_31A,\n\tSTREAMED_SOUND_MISSION_BK4_31B,\n\tSTREAMED_SOUND_MISSION_BNK4_32,\n\tSTREAMED_SOUND_MISSION_BK4_34A,\n\tSTREAMED_SOUND_MISSION_BK4_34B,\n\tSTREAMED_SOUND_MISSION_BK4_35A,\n\tSTREAMED_SOUND_MISSION_BK4_35B,\n\tSTREAMED_SOUND_MISSION_BNK4_36,\n\tSTREAMED_SOUND_MISSION_BNK4_37,\n\tSTREAMED_SOUND_MISSION_BNK4_38,\n\tSTREAMED_SOUND_MISSION_BNK4_39,\n\tSTREAMED_SOUND_MISSION_BK4_40A,\n\tSTREAMED_SOUND_MISSION_BK4_40B,\n\tSTREAMED_SOUND_MISSION_BNK4_41,\n\tSTREAMED_SOUND_MISSION_BNK4_42,\n\tSTREAMED_SOUND_MISSION_BNK4_43,\n\tSTREAMED_SOUND_MISSION_BNK4_44,\n\tSTREAMED_SOUND_MISSION_BNK4_45,\n\tSTREAMED_SOUND_MISSION_BNK4_46,\n\tSTREAMED_SOUND_MISSION_BNK4_47,\n\tSTREAMED_SOUND_MISSION_BNK4_48,\n\tSTREAMED_SOUND_MISSION_BNK4_49,\n\tSTREAMED_SOUND_MISSION_BNK450A,\n\tSTREAMED_SOUND_MISSION_BNK450B,\n\tSTREAMED_SOUND_MISSION_BNK4_51,\n\tSTREAMED_SOUND_MISSION_BNK4_94,\n\tSTREAMED_SOUND_MISSION_BNK4_95,\n\tSTREAMED_SOUND_MISSION_BNK4_96,\n\tSTREAMED_SOUND_MISSION_BNK4_97,\n\tSTREAMED_SOUND_MISSION_BNK4_98,\n\tSTREAMED_SOUND_MISSION_BNK4_99,\n\tSTREAMED_SOUND_MISSION_BUD1_1,\n\tSTREAMED_SOUND_MISSION_BUD1_2,\n\tSTREAMED_SOUND_MISSION_BUD1_3,\n\tSTREAMED_SOUND_MISSION_BUD1_4,\n\tSTREAMED_SOUND_MISSION_BUD1_5,\n\tSTREAMED_SOUND_MISSION_BUD1_9,\n\tSTREAMED_SOUND_MISSION_BUD1_10,\n\tSTREAMED_SOUND_MISSION_BUD2_1,\n\tSTREAMED_SOUND_MISSION_BUD2_2,\n\tSTREAMED_SOUND_MISSION_BUD2_3,\n\tSTREAMED_SOUND_MISSION_BUD2_4,\n\tSTREAMED_SOUND_MISSION_BUD2_5,\n\tSTREAMED_SOUND_MISSION_BUD2_6,\n\tSTREAMED_SOUND_MISSION_BUD2_7,\n\tSTREAMED_SOUND_MISSION_BUD3_1,\n\tSTREAMED_SOUND_MISSION_BUD3_1A,\n\tSTREAMED_SOUND_MISSION_BUD3_1B,\n\tSTREAMED_SOUND_MISSION_BUD3_1C,\n\tSTREAMED_SOUND_MISSION_BUD3_2,\n\tSTREAMED_SOUND_MISSION_BUD3_3,\n\tSTREAMED_SOUND_MISSION_BUD3_4,\n\tSTREAMED_SOUND_MISSION_BUD3_5,\n\tSTREAMED_SOUND_MISSION_BUD3_6,\n\tSTREAMED_SOUND_MISSION_BUD3_7,\n\tSTREAMED_SOUND_MISSION_BUD3_8A,\n\tSTREAMED_SOUND_MISSION_BUD3_8B,\n\tSTREAMED_SOUND_MISSION_BUD3_8C,\n\tSTREAMED_SOUND_MISSION_BUD3_9A,\n\tSTREAMED_SOUND_MISSION_BUD3_9B,\n\tSTREAMED_SOUND_MISSION_BUD3_9C,\n\tSTREAMED_SOUND_MISSION_CAP1_2,\n\tSTREAMED_SOUND_MISSION_CAP1_3,\n\tSTREAMED_SOUND_MISSION_CAP1_4,\n\tSTREAMED_SOUND_MISSION_CAP1_5,\n\tSTREAMED_SOUND_MISSION_CAP1_6,\n\tSTREAMED_SOUND_MISSION_CAP1_7,\n\tSTREAMED_SOUND_MISSION_CAP1_8,\n\tSTREAMED_SOUND_MISSION_CAP1_9,\n\tSTREAMED_SOUND_MISSION_CAP1_10,\n\tSTREAMED_SOUND_MISSION_CAP1_11,\n\tSTREAMED_SOUND_MISSION_CAP1_12,\n\tSTREAMED_SOUND_MISSION_CNT1_1,\n\tSTREAMED_SOUND_MISSION_CNT1_2,\n\tSTREAMED_SOUND_MISSION_CNT1_3,\n\tSTREAMED_SOUND_MISSION_CNT1_4,\n\tSTREAMED_SOUND_MISSION_CNT1_5,\n\tSTREAMED_SOUND_MISSION_CNT2_1,\n\tSTREAMED_SOUND_MISSION_CNT2_2,\n\tSTREAMED_SOUND_MISSION_CNT2_3,\n\tSTREAMED_SOUND_MISSION_CNT2_4,\n\tSTREAMED_SOUND_MISSION_COK1_1,\n\tSTREAMED_SOUND_MISSION_COK1_2,\n\tSTREAMED_SOUND_MISSION_COK1_3,\n\tSTREAMED_SOUND_MISSION_COK1_4,\n\tSTREAMED_SOUND_MISSION_COK1_5,\n\tSTREAMED_SOUND_MISSION_COK1_6,\n\tSTREAMED_SOUND_MISSION_COK2_1,\n\tSTREAMED_SOUND_MISSION_COK2_2,\n\tSTREAMED_SOUND_MISSION_COK2_3,\n\tSTREAMED_SOUND_MISSION_COK2_4,\n\tSTREAMED_SOUND_MISSION_COK2_5,\n\tSTREAMED_SOUND_MISSION_COK2_6,\n\tSTREAMED_SOUND_MISSION_COK2_7A,\n\tSTREAMED_SOUND_MISSION_COK2_7B,\n\tSTREAMED_SOUND_MISSION_COK2_7C,\n\tSTREAMED_SOUND_MISSION_COK2_8A,\n\tSTREAMED_SOUND_MISSION_COK2_8B,\n\tSTREAMED_SOUND_MISSION_COK2_8C,\n\tSTREAMED_SOUND_MISSION_COK2_8D,\n\tSTREAMED_SOUND_MISSION_COK2_9,\n\tSTREAMED_SOUND_MISSION_COK210A,\n\tSTREAMED_SOUND_MISSION_COK210B,\n\tSTREAMED_SOUND_MISSION_COK210C,\n\tSTREAMED_SOUND_MISSION_COK212A,\n\tSTREAMED_SOUND_MISSION_COK212B,\n\tSTREAMED_SOUND_MISSION_COK2_13,\n\tSTREAMED_SOUND_MISSION_COK2_14,\n\tSTREAMED_SOUND_MISSION_COK2_15,\n\tSTREAMED_SOUND_MISSION_COK2_16,\n\tSTREAMED_SOUND_MISSION_COK2_20,\n\tSTREAMED_SOUND_MISSION_COK2_21,\n\tSTREAMED_SOUND_MISSION_COK2_22,\n\tSTREAMED_SOUND_MISSION_COK3_1,\n\tSTREAMED_SOUND_MISSION_COK3_2,\n\tSTREAMED_SOUND_MISSION_COK3_3,\n\tSTREAMED_SOUND_MISSION_COK3_4,\n\tSTREAMED_SOUND_MISSION_COK4_1,\n\tSTREAMED_SOUND_MISSION_COK4_2,\n\tSTREAMED_SOUND_MISSION_COK4_3,\n\tSTREAMED_SOUND_MISSION_COK4_4,\n\tSTREAMED_SOUND_MISSION_COK4_5,\n\tSTREAMED_SOUND_MISSION_COK4_6,\n\tSTREAMED_SOUND_MISSION_COK4_7,\n\tSTREAMED_SOUND_MISSION_COK4_8,\n\tSTREAMED_SOUND_MISSION_COK4_9,\n\tSTREAMED_SOUND_MISSION_COK4_9A,\n\tSTREAMED_SOUND_MISSION_COK4_10,\n\tSTREAMED_SOUND_MISSION_COK4_11,\n\tSTREAMED_SOUND_MISSION_COK4_12,\n\tSTREAMED_SOUND_MISSION_COK4_13,\n\tSTREAMED_SOUND_MISSION_COK4_14,\n\tSTREAMED_SOUND_MISSION_COK4_15,\n\tSTREAMED_SOUND_MISSION_COK4_16,\n\tSTREAMED_SOUND_MISSION_COK4_17,\n\tSTREAMED_SOUND_MISSION_COK4_18,\n\tSTREAMED_SOUND_MISSION_COK4_19,\n\tSTREAMED_SOUND_MISSION_COK4_20,\n\tSTREAMED_SOUND_MISSION_COK4_21,\n\tSTREAMED_SOUND_MISSION_COK4_22,\n\tSTREAMED_SOUND_MISSION_COK4_23,\n\tSTREAMED_SOUND_MISSION_COK4_24,\n\tSTREAMED_SOUND_MISSION_COK4_25,\n\tSTREAMED_SOUND_MISSION_COK4_26,\n\tSTREAMED_SOUND_MISSION_COK4_27,\n\tSTREAMED_SOUND_MISSION_COL1_1,\n\tSTREAMED_SOUND_MISSION_COL1_2,\n\tSTREAMED_SOUND_MISSION_COL1_3,\n\tSTREAMED_SOUND_MISSION_COL1_4,\n\tSTREAMED_SOUND_MISSION_COL1_5,\n\tSTREAMED_SOUND_MISSION_COL1_6,\n\tSTREAMED_SOUND_MISSION_COL1_7,\n\tSTREAMED_SOUND_MISSION_COL1_8,\n\tSTREAMED_SOUND_MISSION_COL2_1,\n\tSTREAMED_SOUND_MISSION_COL2_2,\n\tSTREAMED_SOUND_MISSION_COL2_3,\n\tSTREAMED_SOUND_MISSION_COL2_4,\n\tSTREAMED_SOUND_MISSION_COL2_5,\n\tSTREAMED_SOUND_MISSION_COL2_6A,\n\tSTREAMED_SOUND_MISSION_COL2_7,\n\tSTREAMED_SOUND_MISSION_COL2_8,\n\tSTREAMED_SOUND_MISSION_COL2_9,\n\tSTREAMED_SOUND_MISSION_COL2_10,\n\tSTREAMED_SOUND_MISSION_COL2_11,\n\tSTREAMED_SOUND_MISSION_COL2_12,\n\tSTREAMED_SOUND_MISSION_COL2_13,\n\tSTREAMED_SOUND_MISSION_COL2_14,\n\tSTREAMED_SOUND_MISSION_COL2_15,\n\tSTREAMED_SOUND_MISSION_COL2_16,\n\tSTREAMED_SOUND_MISSION_COL3_1,\n\tSTREAMED_SOUND_MISSION_COL3_2,\n\tSTREAMED_SOUND_MISSION_COL3_2A,\n\tSTREAMED_SOUND_MISSION_COL3_2B,\n\tSTREAMED_SOUND_MISSION_COL3_3,\n\tSTREAMED_SOUND_MISSION_COL3_4,\n\tSTREAMED_SOUND_MISSION_COL3_5,\n\tSTREAMED_SOUND_MISSION_COL3_6,\n\tSTREAMED_SOUND_MISSION_COL3_7,\n\tSTREAMED_SOUND_MISSION_COL3_8,\n\tSTREAMED_SOUND_MISSION_COL3_9,\n\tSTREAMED_SOUND_MISSION_COL3_10,\n\tSTREAMED_SOUND_MISSION_COL3_11,\n\tSTREAMED_SOUND_MISSION_COL3_12,\n\tSTREAMED_SOUND_MISSION_COL3_13,\n\tSTREAMED_SOUND_MISSION_COL3_14,\n\tSTREAMED_SOUND_MISSION_COL3_15,\n\tSTREAMED_SOUND_MISSION_COL3_16,\n\tSTREAMED_SOUND_MISSION_COL3_17,\n\tSTREAMED_SOUND_MISSION_COL3_18,\n\tSTREAMED_SOUND_MISSION_COL3_19,\n\tSTREAMED_SOUND_MISSION_COL3_20,\n\tSTREAMED_SOUND_MISSION_COL3_21,\n\tSTREAMED_SOUND_MISSION_COL3_23,\n\tSTREAMED_SOUND_MISSION_COL3_24,\n\tSTREAMED_SOUND_MISSION_COL3_25,\n\tSTREAMED_SOUND_MISSION_COL4_1,\n\tSTREAMED_SOUND_MISSION_COL4_2,\n\tSTREAMED_SOUND_MISSION_COL4_3,\n\tSTREAMED_SOUND_MISSION_COL4_4,\n\tSTREAMED_SOUND_MISSION_COL4_5,\n\tSTREAMED_SOUND_MISSION_COL4_6,\n\tSTREAMED_SOUND_MISSION_COL4_7,\n\tSTREAMED_SOUND_MISSION_COL4_8,\n\tSTREAMED_SOUND_MISSION_COL4_9,\n\tSTREAMED_SOUND_MISSION_COL4_10,\n\tSTREAMED_SOUND_MISSION_COL4_11,\n\tSTREAMED_SOUND_MISSION_COL4_12,\n\tSTREAMED_SOUND_MISSION_COL4_13,\n\tSTREAMED_SOUND_MISSION_COL4_14,\n\tSTREAMED_SOUND_MISSION_COL4_15,\n\tSTREAMED_SOUND_MISSION_COL4_16,\n\tSTREAMED_SOUND_MISSION_COL4_17,\n\tSTREAMED_SOUND_MISSION_COL4_18,\n\tSTREAMED_SOUND_MISSION_COL4_19,\n\tSTREAMED_SOUND_MISSION_COL4_20,\n\tSTREAMED_SOUND_MISSION_COL4_21,\n\tSTREAMED_SOUND_MISSION_COL4_22,\n\tSTREAMED_SOUND_MISSION_COL4_23,\n\tSTREAMED_SOUND_MISSION_COL4_24,\n\tSTREAMED_SOUND_MISSION_COL4_25,\n\tSTREAMED_SOUND_MISSION_COL4_26,\n\tSTREAMED_SOUND_MISSION_COL5_1,\n\tSTREAMED_SOUND_MISSION_COL5_2,\n\tSTREAMED_SOUND_MISSION_COL5_3,\n\tSTREAMED_SOUND_MISSION_COL5_4,\n\tSTREAMED_SOUND_MISSION_COL5_5,\n\tSTREAMED_SOUND_MISSION_COL5_6,\n\tSTREAMED_SOUND_MISSION_COL5_7,\n\tSTREAMED_SOUND_MISSION_COL5_8,\n\tSTREAMED_SOUND_MISSION_COL5_9,\n\tSTREAMED_SOUND_MISSION_COL5_10,\n\tSTREAMED_SOUND_MISSION_COL5_11,\n\tSTREAMED_SOUND_MISSION_COL5_12,\n\tSTREAMED_SOUND_MISSION_COL5_13,\n\tSTREAMED_SOUND_MISSION_COL5_14,\n\tSTREAMED_SOUND_MISSION_COL5_15,\n\tSTREAMED_SOUND_MISSION_COL5_16,\n\tSTREAMED_SOUND_MISSION_COL5_17,\n\tSTREAMED_SOUND_MISSION_COL5_18,\n\tSTREAMED_SOUND_MISSION_COL5_19,\n\tSTREAMED_SOUND_MISSION_COL5_20,\n\tSTREAMED_SOUND_MISSION_COL5_21,\n\tSTREAMED_SOUND_MISSION_COL5_22,\n\tSTREAMED_SOUND_MISSION_CUB1_1,\n\tSTREAMED_SOUND_MISSION_CUB1_2,\n\tSTREAMED_SOUND_MISSION_CUB1_3,\n\tSTREAMED_SOUND_MISSION_CUB1_4,\n\tSTREAMED_SOUND_MISSION_CUB1_5,\n\tSTREAMED_SOUND_MISSION_CUB1_6,\n\tSTREAMED_SOUND_MISSION_CUB1_7,\n\tSTREAMED_SOUND_MISSION_CUB1_8,\n\tSTREAMED_SOUND_MISSION_CUB1_9,\n\tSTREAMED_SOUND_MISSION_CUB1_10,\n\tSTREAMED_SOUND_MISSION_CUB2_1,\n\tSTREAMED_SOUND_MISSION_CUB2_2,\n\tSTREAMED_SOUND_MISSION_CUB2_3A,\n\tSTREAMED_SOUND_MISSION_CUB2_3B,\n\tSTREAMED_SOUND_MISSION_CUB2_3C,\n\tSTREAMED_SOUND_MISSION_CUB2_4A,\n\tSTREAMED_SOUND_MISSION_CUB2_5,\n\tSTREAMED_SOUND_MISSION_CUB2_6,\n\tSTREAMED_SOUND_MISSION_CUB2_7,\n\tSTREAMED_SOUND_MISSION_CUB2_8,\n\tSTREAMED_SOUND_MISSION_CUB2_9,\n\tSTREAMED_SOUND_MISSION_CUB2_10,\n\tSTREAMED_SOUND_MISSION_CUB2_11,\n\tSTREAMED_SOUND_MISSION_CUB3_1,\n\tSTREAMED_SOUND_MISSION_CUB3_2,\n\tSTREAMED_SOUND_MISSION_CUB3_3,\n\tSTREAMED_SOUND_MISSION_CUB3_4,\n\tSTREAMED_SOUND_MISSION_CUB4_1,\n\tSTREAMED_SOUND_MISSION_CUB4_2,\n\tSTREAMED_SOUND_MISSION_CUB4_3,\n\tSTREAMED_SOUND_MISSION_CUB4_4,\n\tSTREAMED_SOUND_MISSION_CUB4_5,\n\tSTREAMED_SOUND_MISSION_CUB4_5A,\n\tSTREAMED_SOUND_MISSION_CUB4_6,\n\tSTREAMED_SOUND_MISSION_CUB4_7,\n\tSTREAMED_SOUND_MISSION_CUB4_8,\n\tSTREAMED_SOUND_MISSION_CUB4_9,\n\tSTREAMED_SOUND_MISSION_CUB4_10,\n\tSTREAMED_SOUND_MISSION_CUB4_11,\n\tSTREAMED_SOUND_MISSION_CUB4_12,\n\tSTREAMED_SOUND_MISSION_CUB4_13,\n\tSTREAMED_SOUND_MISSION_CUB4_14,\n\tSTREAMED_SOUND_MISSION_CUB4_15,\n\tSTREAMED_SOUND_MISSION_CUB4_16,\n\tSTREAMED_SOUND_MISSION_GOLF_1,\n\tSTREAMED_SOUND_MISSION_GOLF_2,\n\tSTREAMED_SOUND_MISSION_GOLF_3,\n\tSTREAMED_SOUND_MISSION_BAR_1,\n\tSTREAMED_SOUND_MISSION_BAR_2,\n\tSTREAMED_SOUND_MISSION_BAR_3,\n\tSTREAMED_SOUND_MISSION_BAR_4,\n\tSTREAMED_SOUND_MISSION_BAR_5,\n\tSTREAMED_SOUND_MISSION_BAR_6,\n\tSTREAMED_SOUND_MISSION_BAR_7,\n\tSTREAMED_SOUND_MISSION_BAR_8,\n\tSTREAMED_SOUND_MISSION_STRIP_1,\n\tSTREAMED_SOUND_MISSION_STRIP_2,\n\tSTREAMED_SOUND_MISSION_STRIP_3,\n\tSTREAMED_SOUND_MISSION_STRIP_4,\n\tSTREAMED_SOUND_MISSION_STRIP_5,\n\tSTREAMED_SOUND_MISSION_STRIP_6,\n\tSTREAMED_SOUND_MISSION_STRIP_7,\n\tSTREAMED_SOUND_MISSION_STRIP_8,\n\tSTREAMED_SOUND_MISSION_STRIP_9,\n\tSTREAMED_SOUND_MISSION_STAR_1,\n\tSTREAMED_SOUND_MISSION_STAR_2,\n\tSTREAMED_SOUND_MISSION_STAR_3,\n\tSTREAMED_SOUND_MISSION_STAR_4,\n\tSTREAMED_SOUND_MISSION_FIN_1A,\n\tSTREAMED_SOUND_MISSION_FIN_1B,\n\tSTREAMED_SOUND_MISSION_FIN_1C,\n\tSTREAMED_SOUND_MISSION_FIN_2B,\n\tSTREAMED_SOUND_MISSION_FIN_2C,\n\tSTREAMED_SOUND_MISSION_FIN_3,\n\tSTREAMED_SOUND_MISSION_FIN_4,\n\tSTREAMED_SOUND_MISSION_FIN_5,\n\tSTREAMED_SOUND_MISSION_FIN_6,\n\tSTREAMED_SOUND_MISSION_FIN_10,\n\tSTREAMED_SOUND_MISSION_FIN_11A,\n\tSTREAMED_SOUND_MISSION_FIN_11B,\n\tSTREAMED_SOUND_MISSION_FIN_12A,\n\tSTREAMED_SOUND_MISSION_FIN_12B,\n\tSTREAMED_SOUND_MISSION_FIN_12C,\n\tSTREAMED_SOUND_MISSION_FIN_13,\n\tSTREAMED_SOUND_MISSION_FINKILL,\n\tSTREAMED_SOUND_MISSION_LAW1_1,\n\tSTREAMED_SOUND_MISSION_LAW1_2,\n\tSTREAMED_SOUND_MISSION_LAW1_3,\n\tSTREAMED_SOUND_MISSION_LAW1_4,\n\tSTREAMED_SOUND_MISSION_LAW1_5,\n\tSTREAMED_SOUND_MISSION_LAW1_6,\n\tSTREAMED_SOUND_MISSION_LAW1_7,\n\tSTREAMED_SOUND_MISSION_LAW1_8,\n\tSTREAMED_SOUND_MISSION_LAW1_9,\n\tSTREAMED_SOUND_MISSION_LAW1_10,\n\tSTREAMED_SOUND_MISSION_LAW2_1,\n\tSTREAMED_SOUND_MISSION_LAW2_2,\n\tSTREAMED_SOUND_MISSION_LAW2_3,\n\tSTREAMED_SOUND_MISSION_LAW2_4,\n\tSTREAMED_SOUND_MISSION_LAW2_5,\n\tSTREAMED_SOUND_MISSION_LAW2_6,\n\tSTREAMED_SOUND_MISSION_LAW2_7,\n\tSTREAMED_SOUND_MISSION_LAW2_8,\n\tSTREAMED_SOUND_MISSION_LAW2_9,\n\tSTREAMED_SOUND_MISSION_LAW2_10,\n\tSTREAMED_SOUND_MISSION_LAW3_1,\n\tSTREAMED_SOUND_MISSION_LAW3_2,\n\tSTREAMED_SOUND_MISSION_LAW3_3,\n\tSTREAMED_SOUND_MISSION_LAW3_4,\n\tSTREAMED_SOUND_MISSION_LAW3_5,\n\tSTREAMED_SOUND_MISSION_LAW3_6,\n\tSTREAMED_SOUND_MISSION_LAW3_10,\n\tSTREAMED_SOUND_MISSION_LAW3_11,\n\tSTREAMED_SOUND_MISSION_LAW3_12,\n\tSTREAMED_SOUND_MISSION_LAW3_13,\n\tSTREAMED_SOUND_MISSION_LAW3_14,\n\tSTREAMED_SOUND_MISSION_LAW3_16,\n\tSTREAMED_SOUND_MISSION_LAW3_17,\n\tSTREAMED_SOUND_MISSION_LAW3_18,\n\tSTREAMED_SOUND_MISSION_LAW3_19,\n\tSTREAMED_SOUND_MISSION_LAW3_20,\n\tSTREAMED_SOUND_MISSION_LAW3_21,\n\tSTREAMED_SOUND_MISSION_LAW3_22,\n\tSTREAMED_SOUND_MISSION_LAW3_23,\n\tSTREAMED_SOUND_MISSION_LAW3_24,\n\tSTREAMED_SOUND_MISSION_LAW3_25,\n\tSTREAMED_SOUND_MISSION_LAW4_1A,\n\tSTREAMED_SOUND_MISSION_LAW4_1B,\n\tSTREAMED_SOUND_MISSION_LAW4_1C,\n\tSTREAMED_SOUND_MISSION_LAW4_1D,\n\tSTREAMED_SOUND_MISSION_LAW4_10,\n\tSTREAMED_SOUND_MISSION_LAW4_3,\n\tSTREAMED_SOUND_MISSION_LAW4_4,\n\tSTREAMED_SOUND_MISSION_LAW4_5,\n\tSTREAMED_SOUND_MISSION_LAW4_6,\n\tSTREAMED_SOUND_MISSION_LAW4_7,\n\tSTREAMED_SOUND_MISSION_LAW4_8,\n\tSTREAMED_SOUND_MISSION_LAW4_9,\n\tSTREAMED_SOUND_MISSION_PHIL1_2,\n\tSTREAMED_SOUND_MISSION_PHIL1_3,\n\tSTREAMED_SOUND_MISSION_PHIL2_1,\n\tSTREAMED_SOUND_MISSION_PHIL2_2,\n\tSTREAMED_SOUND_MISSION_PHIL2_3,\n\tSTREAMED_SOUND_MISSION_PHIL2_4,\n\tSTREAMED_SOUND_MISSION_PHIL2_5,\n\tSTREAMED_SOUND_MISSION_PHIL2_6,\n\tSTREAMED_SOUND_MISSION_PHIL2_7,\n\tSTREAMED_SOUND_MISSION_PHIL2_8,\n\tSTREAMED_SOUND_MISSION_PHIL2_9,\n\tSTREAMED_SOUND_MISSION_PHIL210,\n\tSTREAMED_SOUND_MISSION_PHIL211,\n\tSTREAMED_SOUND_MISSION_PORN1_1,\n\tSTREAMED_SOUND_MISSION_PORN1_2,\n\tSTREAMED_SOUND_MISSION_PORN1_3,\n\tSTREAMED_SOUND_MISSION_PRN1_3A,\n\tSTREAMED_SOUND_MISSION_PORN1_4,\n\tSTREAMED_SOUND_MISSION_PORN1_5,\n\tSTREAMED_SOUND_MISSION_PORN1_6,\n\tSTREAMED_SOUND_MISSION_PORN1_7,\n\tSTREAMED_SOUND_MISSION_PORN1_8,\n\tSTREAMED_SOUND_MISSION_PORN1_9,\n\tSTREAMED_SOUND_MISSION_PRN1_10,\n\tSTREAMED_SOUND_MISSION_PRN1_11,\n\tSTREAMED_SOUND_MISSION_PRN1_12,\n\tSTREAMED_SOUND_MISSION_PRN1_13,\n\tSTREAMED_SOUND_MISSION_PRN1_14,\n\tSTREAMED_SOUND_MISSION_PRN1_15,\n\tSTREAMED_SOUND_MISSION_PRN1_16,\n\tSTREAMED_SOUND_MISSION_PRN1_17,\n\tSTREAMED_SOUND_MISSION_PRN1_18,\n\tSTREAMED_SOUND_MISSION_PRN1_19,\n\tSTREAMED_SOUND_MISSION_PRN1_20,\n\tSTREAMED_SOUND_MISSION_PRN1_21,\n\tSTREAMED_SOUND_MISSION_PORN3_1,\n\tSTREAMED_SOUND_MISSION_PORN3_2,\n\tSTREAMED_SOUND_MISSION_PORN3_3,\n\tSTREAMED_SOUND_MISSION_PORN3_4,\n\tSTREAMED_SOUND_MISSION_PSYCH_1,\n\tSTREAMED_SOUND_MISSION_PSYCH_2,\n\tSTREAMED_SOUND_MISSION_ROK2_01,\n\tSTREAMED_SOUND_MISSION_ROK3_1,\n\tSTREAMED_SOUND_MISSION_ROK3_2,\n\tSTREAMED_SOUND_MISSION_ROK3_3,\n\tSTREAMED_SOUND_MISSION_ROK3_4,\n\tSTREAMED_SOUND_MISSION_ROK3_5,\n\tSTREAMED_SOUND_MISSION_ROK3_6,\n\tSTREAMED_SOUND_MISSION_ROK3_7,\n\tSTREAMED_SOUND_MISSION_ROK3_8,\n\tSTREAMED_SOUND_MISSION_ROK3_9,\n\tSTREAMED_SOUND_MISSION_ROK3_10,\n\tSTREAMED_SOUND_MISSION_ROK3_11,\n\tSTREAMED_SOUND_MISSION_ROK3_12,\n\tSTREAMED_SOUND_MISSION_ROK3_13,\n\tSTREAMED_SOUND_MISSION_ROK3_14,\n\tSTREAMED_SOUND_MISSION_ROK3_15,\n\tSTREAMED_SOUND_MISSION_ROK3_16,\n\tSTREAMED_SOUND_MISSION_ROK3_17,\n\tSTREAMED_SOUND_MISSION_ROK3_18,\n\tSTREAMED_SOUND_MISSION_ROK3_19,\n\tSTREAMED_SOUND_MISSION_ROK3_20,\n\tSTREAMED_SOUND_MISSION_ROK3_21,\n\tSTREAMED_SOUND_MISSION_ROK3_22,\n\tSTREAMED_SOUND_MISSION_ROK3_23,\n\tSTREAMED_SOUND_MISSION_ROK3_24,\n\tSTREAMED_SOUND_MISSION_ROK3_25,\n\tSTREAMED_SOUND_MISSION_ROK3_26,\n\tSTREAMED_SOUND_MISSION_ROK3_27,\n\tSTREAMED_SOUND_MISSION_ROK3_62,\n\tSTREAMED_SOUND_MISSION_ROK3_63,\n\tSTREAMED_SOUND_MISSION_ROK3_64,\n\tSTREAMED_SOUND_MISSION_ROK3_65,\n\tSTREAMED_SOUND_MISSION_ROK3_66,\n\tSTREAMED_SOUND_MISSION_ROK3_67,\n\tSTREAMED_SOUND_MISSION_ROK3_68,\n\tSTREAMED_SOUND_MISSION_ROK3_69,\n\tSTREAMED_SOUND_MISSION_ROK3_70,\n\tSTREAMED_SOUND_MISSION_ROK3_71,\n\tSTREAMED_SOUND_MISSION_ROK3_73,\n\tSTREAMED_SOUND_MISSION_RESC_1,\n\tSTREAMED_SOUND_MISSION_RESC_2,\n\tSTREAMED_SOUND_MISSION_RESC_3,\n\tSTREAMED_SOUND_MISSION_RESC_4,\n\tSTREAMED_SOUND_MISSION_RESC_5,\n\tSTREAMED_SOUND_MISSION_RESC_6,\n\tSTREAMED_SOUND_MISSION_RESC_7,\n\tSTREAMED_SOUND_MISSION_RESC_8,\n\tSTREAMED_SOUND_MISSION_RESC_9,\n\tSTREAMED_SOUND_MISSION_RESC_10,\n\tSTREAMED_SOUND_MISSION_ROK1_1A,\n\tSTREAMED_SOUND_MISSION_ROK1_1B,\n\tSTREAMED_SOUND_MISSION_ROK1_5,\n\tSTREAMED_SOUND_MISSION_ROK1_6,\n\tSTREAMED_SOUND_MISSION_ROK1_7,\n\tSTREAMED_SOUND_MISSION_ROK1_8,\n\tSTREAMED_SOUND_MISSION_ROK1_9,\n\tSTREAMED_SOUND_MISSION_TAX1_1,\n\tSTREAMED_SOUND_MISSION_TAX1_2,\n\tSTREAMED_SOUND_MISSION_TAX1_3,\n\tSTREAMED_SOUND_MISSION_TAX1_4,\n\tSTREAMED_SOUND_MISSION_TAX1_5,\n\tSTREAMED_SOUND_MISSION_TAX2_1,\n\tSTREAMED_SOUND_MISSION_TAX2_2,\n\tSTREAMED_SOUND_MISSION_TAX2_3,\n\tSTREAMED_SOUND_MISSION_TAX2_4,\n\tSTREAMED_SOUND_MISSION_TAX2_5,\n\tSTREAMED_SOUND_MISSION_TAX2_6,\n\tSTREAMED_SOUND_MISSION_TAX2_7,\n\tSTREAMED_SOUND_MISSION_TAX3_1,\n\tSTREAMED_SOUND_MISSION_TAX3_2,\n\tSTREAMED_SOUND_MISSION_TAX3_3,\n\tSTREAMED_SOUND_MISSION_TAX3_4,\n\tSTREAMED_SOUND_MISSION_TAX3_5,\n\tSTREAMED_SOUND_MISSION_TEX1_1,\n\tSTREAMED_SOUND_MISSION_TEX1_2,\n\tSTREAMED_SOUND_MISSION_TEX1_3,\n\tSTREAMED_SOUND_MISSION_TEX1_4,\n\tSTREAMED_SOUND_MISSION_TEX1_5,\n\tSTREAMED_SOUND_MISSION_TEX1_6,\n\tSTREAMED_SOUND_MISSION_TEX2_1,\n\tSTREAMED_SOUND_MISSION_TEX3_1,\n\tSTREAMED_SOUND_MISSION_TEX3_2,\n\tSTREAMED_SOUND_MISSION_TEX3_3,\n\tSTREAMED_SOUND_MISSION_TEX3_4,\n\tSTREAMED_SOUND_MISSION_TEX3_5,\n\tSTREAMED_SOUND_MISSION_TEX3_6,\n\tSTREAMED_SOUND_MISSION_TEX3_7,\n\tSTREAMED_SOUND_MISSION_TEX3_8,\n\tSTREAMED_SOUND_MISSION_HAT_1A,\n\tSTREAMED_SOUND_MISSION_INTRO1,\n\tSTREAMED_SOUND_MISSION_INTRO2,\n\tSTREAMED_SOUND_MISSION_INTRO3,\n\tSTREAMED_SOUND_MISSION_INTRO4,\n\tSTREAMED_SOUND_MISSION_MOB_01A,\n\tSTREAMED_SOUND_MISSION_MOB_01B,\n\tSTREAMED_SOUND_MISSION_MOB_01C,\n\tSTREAMED_SOUND_MISSION_MOB_02A,\n\tSTREAMED_SOUND_MISSION_MOB_02B,\n\tSTREAMED_SOUND_MISSION_MOB_02C,\n\tSTREAMED_SOUND_MISSION_MOB_03A,\n\tSTREAMED_SOUND_MISSION_MOB_03B,\n\tSTREAMED_SOUND_MISSION_MOB_03C,\n\tSTREAMED_SOUND_MISSION_MOB_03D,\n\tSTREAMED_SOUND_MISSION_MOB_03E,\n\tSTREAMED_SOUND_MISSION_SHARK_1,\n\tSTREAMED_SOUND_MISSION_SHARK_2,\n\tSTREAMED_SOUND_MISSION_SHARK_3,\n\tSTREAMED_SOUND_MISSION_SHARK_4,\n\tSTREAMED_SOUND_MISSION_SHARK_5,\n\tSTREAMED_SOUND_MISSION_MOB_04A,\n\tSTREAMED_SOUND_MISSION_MOB_04B,\n\tSTREAMED_SOUND_MISSION_MOB_04C,\n\tSTREAMED_SOUND_MISSION_MOB_04D,\n\tSTREAMED_SOUND_MISSION_MOB_05A,\n\tSTREAMED_SOUND_MISSION_MOB_05B,\n\tSTREAMED_SOUND_MISSION_MOB_05C,\n\tSTREAMED_SOUND_MISSION_MOB_05D,\n\tSTREAMED_SOUND_MISSION_MOB_06A,\n\tSTREAMED_SOUND_MISSION_MOB_06B,\n\tSTREAMED_SOUND_MISSION_MOB_06C,\n\tSTREAMED_SOUND_MISSION_MOB_07A,\n\tSTREAMED_SOUND_MISSION_MOB_07B,\n\tSTREAMED_SOUND_MISSION_MOB_08A,\n\tSTREAMED_SOUND_MISSION_MOB_08B,\n\tSTREAMED_SOUND_MISSION_MOB_08C,\n\tSTREAMED_SOUND_MISSION_MOB_08D,\n\tSTREAMED_SOUND_MISSION_MOB_08E,\n\tSTREAMED_SOUND_MISSION_MOB_08F,\n\tSTREAMED_SOUND_MISSION_MOB_08G,\n\tSTREAMED_SOUND_MISSION_MOB_09A,\n\tSTREAMED_SOUND_MISSION_MOB_09B,\n\tSTREAMED_SOUND_MISSION_MOB_09C,\n\tSTREAMED_SOUND_MISSION_MOB_09D,\n\tSTREAMED_SOUND_MISSION_MOB_09E,\n\tSTREAMED_SOUND_MISSION_MOB_09F,\n\tSTREAMED_SOUND_MISSION_MOB_10A,\n\tSTREAMED_SOUND_MISSION_MOB_10B,\n\tSTREAMED_SOUND_MISSION_MOB_10C,\n\tSTREAMED_SOUND_MISSION_MOB_10D,\n\tSTREAMED_SOUND_MISSION_MOB_10E,\n\tSTREAMED_SOUND_MISSION_MOB_11A,\n\tSTREAMED_SOUND_MISSION_MOB_11B,\n\tSTREAMED_SOUND_MISSION_MOB_11C,\n\tSTREAMED_SOUND_MISSION_MOB_11D,\n\tSTREAMED_SOUND_MISSION_MOB_11E,\n\tSTREAMED_SOUND_MISSION_MOB_11F,\n\tSTREAMED_SOUND_MISSION_MOB_14A,\n\tSTREAMED_SOUND_MISSION_MOB_14B,\n\tSTREAMED_SOUND_MISSION_MOB_14C,\n\tSTREAMED_SOUND_MISSION_MOB_14D,\n\tSTREAMED_SOUND_MISSION_MOB_14E,\n\tSTREAMED_SOUND_MISSION_MOB_14F,\n\tSTREAMED_SOUND_MISSION_MOB_14G,\n\tSTREAMED_SOUND_MISSION_MOB_14H,\n\tSTREAMED_SOUND_MISSION_MOB_16A,\n\tSTREAMED_SOUND_MISSION_MOB_16B,\n\tSTREAMED_SOUND_MISSION_MOB_16C,\n\tSTREAMED_SOUND_MISSION_MOB_16D,\n\tSTREAMED_SOUND_MISSION_MOB_16E,\n\tSTREAMED_SOUND_MISSION_MOB_16F,\n\tSTREAMED_SOUND_MISSION_MOB_16G,\n\tSTREAMED_SOUND_MISSION_MOB_17A,\n\tSTREAMED_SOUND_MISSION_MOB_17B,\n\tSTREAMED_SOUND_MISSION_MOB_17C,\n\tSTREAMED_SOUND_MISSION_MOB_17D,\n\tSTREAMED_SOUND_MISSION_MOB_17E,\n\tSTREAMED_SOUND_MISSION_MOB_17G,\n\tSTREAMED_SOUND_MISSION_MOB_17H,\n\tSTREAMED_SOUND_MISSION_MOB_17I,\n\tSTREAMED_SOUND_MISSION_MOB_17J,\n\tSTREAMED_SOUND_MISSION_MOB_17K,\n\tSTREAMED_SOUND_MISSION_MOB_17L,\n\tSTREAMED_SOUND_MISSION_MOB_18A,\n\tSTREAMED_SOUND_MISSION_MOB_18B,\n\tSTREAMED_SOUND_MISSION_MOB_18C,\n\tSTREAMED_SOUND_MISSION_MOB_18D,\n\tSTREAMED_SOUND_MISSION_MOB_18E,\n\tSTREAMED_SOUND_MISSION_MOB_18F,\n\tSTREAMED_SOUND_MISSION_MOB_18G,\n\tSTREAMED_SOUND_MISSION_MOB_20A,\n\tSTREAMED_SOUND_MISSION_MOB_20B,\n\tSTREAMED_SOUND_MISSION_MOB_20C,\n\tSTREAMED_SOUND_MISSION_MOB_20D,\n\tSTREAMED_SOUND_MISSION_MOB_20E,\n\tSTREAMED_SOUND_MISSION_MOB_24A,\n\tSTREAMED_SOUND_MISSION_MOB_24B,\n\tSTREAMED_SOUND_MISSION_MOB_24C,\n\tSTREAMED_SOUND_MISSION_MOB_24D,\n\tSTREAMED_SOUND_MISSION_MOB_24E,\n\tSTREAMED_SOUND_MISSION_MOB_24F,\n\tSTREAMED_SOUND_MISSION_MOB_24G,\n\tSTREAMED_SOUND_MISSION_MOB_24H,\n\tSTREAMED_SOUND_MISSION_MOB_25A,\n\tSTREAMED_SOUND_MISSION_MOB_25B,\n\tSTREAMED_SOUND_MISSION_MOB_25C,\n\tSTREAMED_SOUND_MISSION_MOB_25D,\n\tSTREAMED_SOUND_MISSION_MOB_26A,\n\tSTREAMED_SOUND_MISSION_MOB_26B,\n\tSTREAMED_SOUND_MISSION_MOB_26C,\n\tSTREAMED_SOUND_MISSION_MOB_26D,\n\tSTREAMED_SOUND_MISSION_MOB_26E,\n\tSTREAMED_SOUND_MISSION_MOB_29A,\n\tSTREAMED_SOUND_MISSION_MOB_29B,\n\tSTREAMED_SOUND_MISSION_MOB_29C,\n\tSTREAMED_SOUND_MISSION_MOB_29D,\n\tSTREAMED_SOUND_MISSION_MOB_29E,\n\tSTREAMED_SOUND_MISSION_MOB_29F,\n\tSTREAMED_SOUND_MISSION_MOB_29G,\n\tSTREAMED_SOUND_MISSION_MOB_30A,\n\tSTREAMED_SOUND_MISSION_MOB_30B,\n\tSTREAMED_SOUND_MISSION_MOB_30C,\n\tSTREAMED_SOUND_MISSION_MOB_30D,\n\tSTREAMED_SOUND_MISSION_MOB_30E,\n\tSTREAMED_SOUND_MISSION_MOB_30F,\n\tSTREAMED_SOUND_MISSION_MOB_33A,\n\tSTREAMED_SOUND_MISSION_MOB_33B,\n\tSTREAMED_SOUND_MISSION_MOB_33C,\n\tSTREAMED_SOUND_MISSION_MOB_33D,\n\tSTREAMED_SOUND_MISSION_MOB_34A,\n\tSTREAMED_SOUND_MISSION_MOB_34B,\n\tSTREAMED_SOUND_MISSION_MOB_34C,\n\tSTREAMED_SOUND_MISSION_MOB_34D,\n\tSTREAMED_SOUND_MISSION_MOB_35A,\n\tSTREAMED_SOUND_MISSION_MOB_35B,\n\tSTREAMED_SOUND_MISSION_MOB_35C,\n\tSTREAMED_SOUND_MISSION_MOB_35D,\n\tSTREAMED_SOUND_MISSION_MOB_36A,\n\tSTREAMED_SOUND_MISSION_MOB_36B,\n\tSTREAMED_SOUND_MISSION_MOB_36C,\n\tSTREAMED_SOUND_MISSION_MOB_40A,\n\tSTREAMED_SOUND_MISSION_MOB_40B,\n\tSTREAMED_SOUND_MISSION_MOB_40C,\n\tSTREAMED_SOUND_MISSION_MOB_40D,\n\tSTREAMED_SOUND_MISSION_MOB_40E,\n\tSTREAMED_SOUND_MISSION_MOB_40F,\n\tSTREAMED_SOUND_MISSION_MOB_40G,\n\tSTREAMED_SOUND_MISSION_MOB_40H,\n\tSTREAMED_SOUND_MISSION_MOB_40I,\n\tSTREAMED_SOUND_MISSION_MOB_41A,\n\tSTREAMED_SOUND_MISSION_MOB_41B,\n\tSTREAMED_SOUND_MISSION_MOB_41C,\n\tSTREAMED_SOUND_MISSION_MOB_41D,\n\tSTREAMED_SOUND_MISSION_MOB_41E,\n\tSTREAMED_SOUND_MISSION_MOB_41F,\n\tSTREAMED_SOUND_MISSION_MOB_41G,\n\tSTREAMED_SOUND_MISSION_MOB_41H,\n\tSTREAMED_SOUND_MISSION_MOB_42A,\n\tSTREAMED_SOUND_MISSION_MOB_42B,\n\tSTREAMED_SOUND_MISSION_MOB_42C,\n\tSTREAMED_SOUND_MISSION_MOB_42D,\n\tSTREAMED_SOUND_MISSION_MOB_42E,\n\tSTREAMED_SOUND_MISSION_MOB_43A,\n\tSTREAMED_SOUND_MISSION_MOB_43B,\n\tSTREAMED_SOUND_MISSION_MOB_43C,\n\tSTREAMED_SOUND_MISSION_MOB_43D,\n\tSTREAMED_SOUND_MISSION_MOB_43E,\n\tSTREAMED_SOUND_MISSION_MOB_43F,\n\tSTREAMED_SOUND_MISSION_MOB_43G,\n\tSTREAMED_SOUND_MISSION_MOB_43H,\n\tSTREAMED_SOUND_MISSION_MOB_45A,\n\tSTREAMED_SOUND_MISSION_MOB_45B,\n\tSTREAMED_SOUND_MISSION_MOB_45C,\n\tSTREAMED_SOUND_MISSION_MOB_45D,\n\tSTREAMED_SOUND_MISSION_MOB_45E,\n\tSTREAMED_SOUND_MISSION_MOB_45F,\n\tSTREAMED_SOUND_MISSION_MOB_45G,\n\tSTREAMED_SOUND_MISSION_MOB_45H,\n\tSTREAMED_SOUND_MISSION_MOB_45I,\n\tSTREAMED_SOUND_MISSION_MOB_45J,\n\tSTREAMED_SOUND_MISSION_MOB_45K,\n\tSTREAMED_SOUND_MISSION_MOB_45L,\n\tSTREAMED_SOUND_MISSION_MOB_45M,\n\tSTREAMED_SOUND_MISSION_MOB_45N,\n\tSTREAMED_SOUND_MISSION_MOB_46A,\n\tSTREAMED_SOUND_MISSION_MOB_46B,\n\tSTREAMED_SOUND_MISSION_MOB_46C,\n\tSTREAMED_SOUND_MISSION_MOB_46D,\n\tSTREAMED_SOUND_MISSION_MOB_46E,\n\tSTREAMED_SOUND_MISSION_MOB_46F,\n\tSTREAMED_SOUND_MISSION_MOB_46G,\n\tSTREAMED_SOUND_MISSION_MOB_46H,\n\tSTREAMED_SOUND_MISSION_MOB_47A,\n\tSTREAMED_SOUND_MISSION_MOB_52A,\n\tSTREAMED_SOUND_MISSION_MOB_52B,\n\tSTREAMED_SOUND_MISSION_MOB_52C,\n\tSTREAMED_SOUND_MISSION_MOB_52D,\n\tSTREAMED_SOUND_MISSION_MOB_52E,\n\tSTREAMED_SOUND_MISSION_MOB_52F,\n\tSTREAMED_SOUND_MISSION_MOB_52G,\n\tSTREAMED_SOUND_MISSION_MOB_52H,\n\tSTREAMED_SOUND_MISSION_MOB_54A,\n\tSTREAMED_SOUND_MISSION_MOB_54B,\n\tSTREAMED_SOUND_MISSION_MOB_54C,\n\tSTREAMED_SOUND_MISSION_MOB_54D,\n\tSTREAMED_SOUND_MISSION_MOB_54E,\n\tSTREAMED_SOUND_MISSION_MOB_55A,\n\tSTREAMED_SOUND_MISSION_MOB_55B,\n\tSTREAMED_SOUND_MISSION_MOB_55C,\n\tSTREAMED_SOUND_MISSION_MOB_55D,\n\tSTREAMED_SOUND_MISSION_MOB_55E,\n\tSTREAMED_SOUND_MISSION_MOB_55F,\n\tSTREAMED_SOUND_MISSION_MOB_56A,\n\tSTREAMED_SOUND_MISSION_MOB_56B,\n\tSTREAMED_SOUND_MISSION_MOB_56C,\n\tSTREAMED_SOUND_MISSION_MOB_56D,\n\tSTREAMED_SOUND_MISSION_MOB_56E,\n\tSTREAMED_SOUND_MISSION_MOB_56F,\n\tSTREAMED_SOUND_MISSION_MOB_57A,\n\tSTREAMED_SOUND_MISSION_MOB_57B,\n\tSTREAMED_SOUND_MISSION_MOB_57C,\n\tSTREAMED_SOUND_MISSION_MOB_57D,\n\tSTREAMED_SOUND_MISSION_MOB_57E,\n\tSTREAMED_SOUND_MISSION_MOB_58A,\n\tSTREAMED_SOUND_MISSION_MOB_58B,\n\tSTREAMED_SOUND_MISSION_MOB_58C,\n\tSTREAMED_SOUND_MISSION_MOB_58D,\n\tSTREAMED_SOUND_MISSION_MOB_58E,\n\tSTREAMED_SOUND_MISSION_MOB_58F,\n\tSTREAMED_SOUND_MISSION_MOB_58G,\n\tSTREAMED_SOUND_MISSION_MOB_61A,\n\tSTREAMED_SOUND_MISSION_MOB_61B,\n\tSTREAMED_SOUND_MISSION_MOB_62A,\n\tSTREAMED_SOUND_MISSION_MOB_62B,\n\tSTREAMED_SOUND_MISSION_MOB_62C,\n\tSTREAMED_SOUND_MISSION_MOB_62D,\n\tSTREAMED_SOUND_MISSION_MOB_63A,\n\tSTREAMED_SOUND_MISSION_MOB_63B,\n\tSTREAMED_SOUND_MISSION_MOB_63C,\n\tSTREAMED_SOUND_MISSION_MOB_63D,\n\tSTREAMED_SOUND_MISSION_MOB_63E,\n\tSTREAMED_SOUND_MISSION_MOB_63F,\n\tSTREAMED_SOUND_MISSION_MOB_63G,\n\tSTREAMED_SOUND_MISSION_MOB_63H,\n\tSTREAMED_SOUND_MISSION_MOB_63I,\n\tSTREAMED_SOUND_MISSION_MOB_63J,\n\tSTREAMED_SOUND_MISSION_MOB_66A,\n\tSTREAMED_SOUND_MISSION_MOB_66B,\n\tSTREAMED_SOUND_MISSION_MOB_68A,\n\tSTREAMED_SOUND_MISSION_MOB_68B,\n\tSTREAMED_SOUND_MISSION_MOB_68C,\n\tSTREAMED_SOUND_MISSION_MOB_68D,\n\tSTREAMED_SOUND_MISSION_MOB_70A,\n\tSTREAMED_SOUND_MISSION_MOB_70B,\n\tSTREAMED_SOUND_MISSION_MOB_71A,\n\tSTREAMED_SOUND_MISSION_MOB_71B,\n\tSTREAMED_SOUND_MISSION_MOB_71C,\n\tSTREAMED_SOUND_MISSION_MOB_71D,\n\tSTREAMED_SOUND_MISSION_MOB_71E,\n\tSTREAMED_SOUND_MISSION_MOB_71F,\n\tSTREAMED_SOUND_MISSION_MOB_71G,\n\tSTREAMED_SOUND_MISSION_MOB_71H,\n\tSTREAMED_SOUND_MISSION_MOB_71I,\n\tSTREAMED_SOUND_MISSION_MOB_71J,\n\tSTREAMED_SOUND_MISSION_MOB_71K,\n\tSTREAMED_SOUND_MISSION_MOB_71L,\n\tSTREAMED_SOUND_MISSION_MOB_71M,\n\tSTREAMED_SOUND_MISSION_MOB_71N,\n\tSTREAMED_SOUND_MISSION_MOB_72A,\n\tSTREAMED_SOUND_MISSION_MOB_72B,\n\tSTREAMED_SOUND_MISSION_MOB_72C,\n\tSTREAMED_SOUND_MISSION_MOB_72D,\n\tSTREAMED_SOUND_MISSION_MOB_72E,\n\tSTREAMED_SOUND_MISSION_MOB_72F,\n\tSTREAMED_SOUND_MISSION_MOB_72G,\n\tSTREAMED_SOUND_MISSION_MOB_73A,\n\tSTREAMED_SOUND_MISSION_MOB_73C,\n\tSTREAMED_SOUND_MISSION_MOB_73D,\n\tSTREAMED_SOUND_MISSION_MOB_73F,\n\tSTREAMED_SOUND_MISSION_MOB_73G,\n\tSTREAMED_SOUND_MISSION_MOB_73I,\n\tSTREAMED_SOUND_MISSION_MOB_95A,\n\tSTREAMED_SOUND_MISSION_MOB_96A,\n\tSTREAMED_SOUND_MISSION_MOB_98A,\n\tSTREAMED_SOUND_MISSION_MOB_99A,\n\tSTREAMED_SOUND_MISSION_JOB1_1B,\n\tSTREAMED_SOUND_MISSION_JOB1_1C,\n\tSTREAMED_SOUND_MISSION_JOB1_1D,\n\tSTREAMED_SOUND_MISSION_JOB2_1B,\n\tSTREAMED_SOUND_MISSION_JOB2_2,\n\tSTREAMED_SOUND_MISSION_JOB2_3,\n\tSTREAMED_SOUND_MISSION_JOB2_4,\n\tSTREAMED_SOUND_MISSION_JOB2_5,\n\tSTREAMED_SOUND_MISSION_JOB2_6,\n\tSTREAMED_SOUND_MISSION_JOB2_7,\n\tSTREAMED_SOUND_MISSION_JOB2_8,\n\tSTREAMED_SOUND_MISSION_JOB2_9,\n\tSTREAMED_SOUND_MISSION_JOB3_1,\n\tSTREAMED_SOUND_MISSION_JOB3_2,\n\tSTREAMED_SOUND_MISSION_JOB3_3,\n\tSTREAMED_SOUND_MISSION_JOB4_1,\n\tSTREAMED_SOUND_MISSION_JOB4_2,\n\tSTREAMED_SOUND_MISSION_JOB4_3,\n\tSTREAMED_SOUND_MISSION_JOB5_1,\n\tSTREAMED_SOUND_MISSION_JOB5_2,\n\tSTREAMED_SOUND_MISSION_JOB5_3,\n\tSTREAMED_SOUND_MISSION_BJM1_20,\n\tSTREAMED_SOUND_MISSION_BJM1_4,\n\tSTREAMED_SOUND_MISSION_BJM1_5,\n\tSTREAMED_SOUND_MISSION_MERC_39,\n\tSTREAMED_SOUND_MISSION_MONO_1,\n\tSTREAMED_SOUND_MISSION_MONO_2,\n\tSTREAMED_SOUND_MISSION_MONO_3,\n\tSTREAMED_SOUND_MISSION_MONO_4,\n\tSTREAMED_SOUND_MISSION_MONO_5,\n\tSTREAMED_SOUND_MISSION_MONO_6,\n\tSTREAMED_SOUND_MISSION_MONO_7,\n\tSTREAMED_SOUND_MISSION_MONO_8,\n\tSTREAMED_SOUND_MISSION_MONO_9,\n\tSTREAMED_SOUND_MISSION_MONO10,\n\tSTREAMED_SOUND_MISSION_MONO11,\n\tSTREAMED_SOUND_MISSION_MONO12,\n\tSTREAMED_SOUND_MISSION_MONO13,\n\tSTREAMED_SOUND_MISSION_MONO14,\n\tSTREAMED_SOUND_MISSION_MONO15,\n\tSTREAMED_SOUND_MISSION_MONO16,\n\tSTREAMED_SOUND_MISSION_FUD_01,\n\tSTREAMED_SOUND_MISSION_FUD_02,\n\tSTREAMED_SOUND_MISSION_FUD_03,\n\tSTREAMED_SOUND_MISSION_FUD_04,\n\tSTREAMED_SOUND_MISSION_FUD_05,\n\tSTREAMED_SOUND_MISSION_FUD_06,\n\tSTREAMED_SOUND_MISSION_FUD_07,\n\tSTREAMED_SOUND_MISSION_FUD_08,\n\tSTREAMED_SOUND_MISSION_FUD_09,\n\tSTREAMED_SOUND_MISSION_FUD_10,\n\tSTREAMED_SOUND_MISSION_FUD_11,\n\tSTREAMED_SOUND_MISSION_FUD_12,\n\tSTREAMED_SOUND_MISSION_FUD_13,\n\tSTREAMED_SOUND_MISSION_FUD_14,\n\tSTREAMED_SOUND_MISSION_FUD_15,\n\tSTREAMED_SOUND_MISSION_FUD_16,\n\tSTREAMED_SOUND_MISSION_FUD_17,\n\tSTREAMED_SOUND_MISSION_FUD_18,\n\tSTREAMED_SOUND_MISSION_FUD_19,\n\tSTREAMED_SOUND_MISSION_FUD_20,\n\tSTREAMED_SOUND_MISSION_BURG_01,\n\tSTREAMED_SOUND_MISSION_BURG_02,\n\tSTREAMED_SOUND_MISSION_BURG_03,\n\tSTREAMED_SOUND_MISSION_BURG_04,\n\tSTREAMED_SOUND_MISSION_BURG_05,\n\tSTREAMED_SOUND_MISSION_BURG_06,\n\tSTREAMED_SOUND_MISSION_BURG_07,\n\tSTREAMED_SOUND_MISSION_BURG_08,\n\tSTREAMED_SOUND_MISSION_BURG_09,\n\tSTREAMED_SOUND_MISSION_BURG_10,\n\tSTREAMED_SOUND_MISSION_BURG_11,\n\tSTREAMED_SOUND_MISSION_BURG_12,\n\tSTREAMED_SOUND_MISSION_CRUST01,\n\tSTREAMED_SOUND_MISSION_CRUST02,\n\tSTREAMED_SOUND_MISSION_CRUST03,\n\tSTREAMED_SOUND_MISSION_CRUST04,\n\tSTREAMED_SOUND_MISSION_CRUST05,\n\tSTREAMED_SOUND_MISSION_CRUST06,\n\tSTREAMED_SOUND_MISSION_CRUST07,\n\tSTREAMED_SOUND_MISSION_CRUST08,\n\tSTREAMED_SOUND_MISSION_CRUST09,\n\tSTREAMED_SOUND_MISSION_BAND_01,\n\tSTREAMED_SOUND_MISSION_BAND_02,\n\tSTREAMED_SOUND_MISSION_BAND_03,\n\tSTREAMED_SOUND_MISSION_BAND_04,\n\tSTREAMED_SOUND_MISSION_BAND_05,\n\tSTREAMED_SOUND_MISSION_BAND_06,\n\tSTREAMED_SOUND_MISSION_BAND_07,\n\tSTREAMED_SOUND_MISSION_BAND_08,\n\tSTREAMED_SOUND_MISSION_SHAFT01,\n\tSTREAMED_SOUND_MISSION_SHAFT02,\n\tSTREAMED_SOUND_MISSION_SHAFT03,\n\tSTREAMED_SOUND_MISSION_SHAFT04,\n\tSTREAMED_SOUND_MISSION_SHAFT05,\n\tSTREAMED_SOUND_MISSION_SHAFT06,\n\tSTREAMED_SOUND_MISSION_SHAFT07,\n\tSTREAMED_SOUND_MISSION_SHAFT08,\n\tSTREAMED_SOUND_MISSION_PISS_01,\n\tSTREAMED_SOUND_MISSION_PISS_02,\n\tSTREAMED_SOUND_MISSION_PISS_03,\n\tSTREAMED_SOUND_MISSION_PISS_04,\n\tSTREAMED_SOUND_MISSION_PISS_05,\n\tSTREAMED_SOUND_MISSION_PISS_06,\n\tSTREAMED_SOUND_MISSION_PISS_07,\n\tSTREAMED_SOUND_MISSION_PISS_08,\n\tSTREAMED_SOUND_MISSION_PISS_09,\n\tSTREAMED_SOUND_MISSION_PISS_10,\n\tSTREAMED_SOUND_MISSION_PISS_11,\n\tSTREAMED_SOUND_MISSION_PISS_12,\n\tSTREAMED_SOUND_MISSION_PISS_13,\n\tSTREAMED_SOUND_MISSION_PISS_14,\n\tSTREAMED_SOUND_MISSION_PISS_15,\n\tSTREAMED_SOUND_MISSION_PISS_16,\n\tSTREAMED_SOUND_MISSION_PISS_17,\n\tSTREAMED_SOUND_MISSION_PISS_18,\n\tSTREAMED_SOUND_MISSION_PISS_19,\n\tSTREAMED_SOUND_MISSION_GIMME01,\n\tSTREAMED_SOUND_MISSION_GIMME02,\n\tSTREAMED_SOUND_MISSION_GIMME03,\n\tSTREAMED_SOUND_MISSION_GIMME04,\n\tSTREAMED_SOUND_MISSION_GIMME05,\n\tSTREAMED_SOUND_MISSION_GIMME06,\n\tSTREAMED_SOUND_MISSION_GIMME07,\n\tSTREAMED_SOUND_MISSION_GIMME08,\n\tSTREAMED_SOUND_MISSION_GIMME09,\n\tSTREAMED_SOUND_MISSION_GIMME10,\n\tSTREAMED_SOUND_MISSION_GIMME11,\n\tSTREAMED_SOUND_MISSION_GIMME12,\n\tSTREAMED_SOUND_MISSION_GIMME13,\n\tSTREAMED_SOUND_MISSION_GIMME14,\n\tSTREAMED_SOUND_MISSION_GIMME15,\n\tSTREAMED_SOUND_MISSION_BUST_01,\n\tSTREAMED_SOUND_MISSION_BUST_02,\n\tSTREAMED_SOUND_MISSION_BUST_03,\n\tSTREAMED_SOUND_MISSION_BUST_04,\n\tSTREAMED_SOUND_MISSION_BUST_05,\n\tSTREAMED_SOUND_MISSION_BUST_06,\n\tSTREAMED_SOUND_MISSION_BUST_07,\n\tSTREAMED_SOUND_MISSION_BUST_08,\n\tSTREAMED_SOUND_MISSION_BUST_09,\n\tSTREAMED_SOUND_MISSION_BUST_10,\n\tSTREAMED_SOUND_MISSION_BUST_11,\n\tSTREAMED_SOUND_MISSION_BUST_12,\n\tSTREAMED_SOUND_MISSION_BUST_13,\n\tSTREAMED_SOUND_MISSION_BUST_14,\n\tSTREAMED_SOUND_MISSION_BUST_15,\n\tSTREAMED_SOUND_MISSION_BUST_16,\n\tSTREAMED_SOUND_MISSION_BUST_17,\n\tSTREAMED_SOUND_MISSION_BUST_18,\n\tSTREAMED_SOUND_MISSION_BUST_19,\n\tSTREAMED_SOUND_MISSION_BUST_20,\n\tSTREAMED_SOUND_MISSION_BUST_21,\n\tSTREAMED_SOUND_MISSION_BUST_22,\n\tSTREAMED_SOUND_MISSION_BUST_23,\n\tSTREAMED_SOUND_MISSION_BUST_24,\n\tSTREAMED_SOUND_MISSION_BUST_25,\n\tSTREAMED_SOUND_MISSION_BUST_26,\n\tSTREAMED_SOUND_MISSION_BUST_27,\n\tSTREAMED_SOUND_MISSION_BUST_28,\n\tTOTAL_STREAMED_SOUNDS,\n\tNO_TRACK,\n};\n\nenum AudioEntityHandle {\n\tAEHANDLE_NONE = -5,\n\tAEHANDLE_ERROR_NOAUDIOSYS = -4,\n\tAEHANDLE_ERROR_NOFREESLOT = -3,\n\tAEHANDLE_ERROR_NOENTITY = -2,\n\tAEHANDLE_ERROR_BADAUDIOTYPE = -1,\n};\n\nenum eAudioType\n{\n\tAUDIOTYPE_PHYSICAL = 0,\n\tAUDIOTYPE_EXPLOSION,\n\tAUDIOTYPE_FIRE,\n\tAUDIOTYPE_WEATHER,\n\tAUDIOTYPE_SCRIPTOBJECT,\n#ifdef GTA_BRIDGE\n\tAUDIOTYPE_BRIDGE,\n#endif\n\tAUDIOTYPE_COLLISION,\n\tAUDIOTYPE_FRONTEND,\n\tAUDIOTYPE_PROJECTILE,\n\tAUDIOTYPE_GARAGE,\n\tAUDIOTYPE_FIREHYDRANT,\n\tAUDIOTYPE_WATERCANNON,\n\tAUDIOTYPE_ESCALATOR,\n\tAUDIOTYPE_EXTRA_SOUNDS,\n\tAUDIOTYPE_POLICERADIO,\n\tTOTAL_AUDIO_TYPES,\n};\n"
  },
  {
    "path": "src/audio/eax/eax-util.cpp",
    "content": "/***********************************************************************************************\\\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*  EAX-UTIL.CPP -\tutilities for EAX 3.0\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tFunction declaration for EAX Morphing\t\t\t\t\t\t\t\t\t\t*\n*\t\t\t\t\tString names of the all the presets defined in eax-util.h\t\t\t\t\t*\n*\t\t\t\t\tArrays grouping together all the EAX presets in a scenario\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n************************************************************************************************/\n\n#include \"eax-util.h\"\n#include <math.h>\n\n// Function prototypes used by EAX3ListenerInterpolate\nvoid Clamp(EAXVECTOR *eaxVector);\nbool CheckEAX3LP(LPEAXLISTENERPROPERTIES lpEAX3LP);\n\n\n/***********************************************************************************************\\\n*\n* Definition of the EAXMorph function - EAX3ListenerInterpolate\n*\n\\***********************************************************************************************/\n\n/*\n\tEAX3ListenerInterpolate\n\tlpStart\t\t\t- Initial EAX 3 Listener parameters\n\tlpFinish\t\t- Final EAX 3 Listener parameters\n\tflRatio\t\t\t- Ratio Destination : Source (0.0 == Source, 1.0 == Destination)\n\tlpResult\t\t- Interpolated EAX 3 Listener parameters\n\tbCheckValues\t- Check EAX 3.0 parameters are in range, default = false (no checking)\n*/\nbool EAX3ListenerInterpolate(LPEAXLISTENERPROPERTIES lpStart, LPEAXLISTENERPROPERTIES lpFinish,\n\t\t\t\t\t\tfloat flRatio, LPEAXLISTENERPROPERTIES lpResult, bool bCheckValues)\n{\n\tEAXVECTOR StartVector, FinalVector;\n\n\tfloat flInvRatio;\n\n\tif (bCheckValues)\n\t{\n\t\tif (!CheckEAX3LP(lpStart))\n\t\t\treturn false;\n\n\t\tif (!CheckEAX3LP(lpFinish))\n\t\t\treturn false;\n\t}\n\n\tif (flRatio >= 1.0f)\n\t{\n\t\tmemcpy(lpResult, lpFinish, sizeof(EAXLISTENERPROPERTIES));\n\t\treturn true;\n\t}\n\telse if (flRatio <= 0.0f)\n\t{\n\t\tmemcpy(lpResult, lpStart, sizeof(EAXLISTENERPROPERTIES));\n\t\treturn true;\n\t}\n\n\tflInvRatio = (1.0f - flRatio);\n\n\t// Environment\n\tlpResult->ulEnvironment = 26;\t// (UNDEFINED environment)\n\n\t// Environment Size\n\tif (lpStart->flEnvironmentSize == lpFinish->flEnvironmentSize)\n\t\tlpResult->flEnvironmentSize = lpStart->flEnvironmentSize;\n\telse\n\t\tlpResult->flEnvironmentSize = (float)exp( (log(lpStart->flEnvironmentSize) * flInvRatio) + (log(lpFinish->flEnvironmentSize) * flRatio) );\n\t\n\t// Environment Diffusion\n\tif (lpStart->flEnvironmentDiffusion == lpFinish->flEnvironmentDiffusion)\n\t\tlpResult->flEnvironmentDiffusion = lpStart->flEnvironmentDiffusion;\n\telse\n\t\tlpResult->flEnvironmentDiffusion = (lpStart->flEnvironmentDiffusion * flInvRatio) + (lpFinish->flEnvironmentDiffusion * flRatio);\n\t\n\t// Room\n\tif (lpStart->lRoom == lpFinish->lRoom)\n\t\tlpResult->lRoom = lpStart->lRoom;\n\telse\n\t\tlpResult->lRoom = (int)( ((float)lpStart->lRoom * flInvRatio) + ((float)lpFinish->lRoom * flRatio) );\n\t\n\t// Room HF\n\tif (lpStart->lRoomHF == lpFinish->lRoomHF)\n\t\tlpResult->lRoomHF = lpStart->lRoomHF;\n\telse\n\t\tlpResult->lRoomHF = (int)( ((float)lpStart->lRoomHF * flInvRatio) + ((float)lpFinish->lRoomHF * flRatio) );\n\t\n\t// Room LF\n\tif (lpStart->lRoomLF == lpFinish->lRoomLF)\n\t\tlpResult->lRoomLF = lpStart->lRoomLF;\n\telse\n\t\tlpResult->lRoomLF = (int)( ((float)lpStart->lRoomLF * flInvRatio) + ((float)lpFinish->lRoomLF * flRatio) );\n\t\n\t// Decay Time\n\tif (lpStart->flDecayTime == lpFinish->flDecayTime)\n\t\tlpResult->flDecayTime = lpStart->flDecayTime;\n\telse\n\t\tlpResult->flDecayTime = (float)exp( (log(lpStart->flDecayTime) * flInvRatio) + (log(lpFinish->flDecayTime) * flRatio) );\n\t\n\t// Decay HF Ratio\n\tif (lpStart->flDecayHFRatio == lpFinish->flDecayHFRatio)\n\t\tlpResult->flDecayHFRatio = lpStart->flDecayHFRatio;\n\telse\n\t\tlpResult->flDecayHFRatio = (float)exp( (log(lpStart->flDecayHFRatio) * flInvRatio) + (log(lpFinish->flDecayHFRatio) * flRatio) );\n\t\n\t// Decay LF Ratio\n\tif (lpStart->flDecayLFRatio == lpFinish->flDecayLFRatio)\n\t\tlpResult->flDecayLFRatio = lpStart->flDecayLFRatio;\n\telse\n\t\tlpResult->flDecayLFRatio = (float)exp( (log(lpStart->flDecayLFRatio) * flInvRatio) + (log(lpFinish->flDecayLFRatio) * flRatio) );\n\t\n\t// Reflections\n\tif (lpStart->lReflections == lpFinish->lReflections)\n\t\tlpResult->lReflections = lpStart->lReflections;\n\telse\n\t\tlpResult->lReflections = (int)( ((float)lpStart->lReflections * flInvRatio) + ((float)lpFinish->lReflections * flRatio) );\n\t\n\t// Reflections Delay\n\tif (lpStart->flReflectionsDelay == lpFinish->flReflectionsDelay)\n\t\tlpResult->flReflectionsDelay = lpStart->flReflectionsDelay;\n\telse\n\t\tlpResult->flReflectionsDelay = (float)exp( (log(lpStart->flReflectionsDelay+0.0001f) * flInvRatio) + (log(lpFinish->flReflectionsDelay+0.0001f) * flRatio) );\n\n\t// Reflections Pan\n\n\t// To interpolate the vector correctly we need to ensure that both the initial and final vectors vectors are clamped to a length of 1.0f\n\tStartVector = lpStart->vReflectionsPan;\n\tFinalVector = lpFinish->vReflectionsPan;\n\n\tClamp(&StartVector);\n\tClamp(&FinalVector);\n\n\tif (lpStart->vReflectionsPan.x == lpFinish->vReflectionsPan.x)\n\t\tlpResult->vReflectionsPan.x = lpStart->vReflectionsPan.x;\n\telse\n\t\tlpResult->vReflectionsPan.x = FinalVector.x + (flInvRatio * (StartVector.x - FinalVector.x));\n\t\n\tif (lpStart->vReflectionsPan.y == lpFinish->vReflectionsPan.y)\n\t\tlpResult->vReflectionsPan.y = lpStart->vReflectionsPan.y;\n\telse\n\t\tlpResult->vReflectionsPan.y = FinalVector.y + (flInvRatio * (StartVector.y - FinalVector.y));\n\t\n\tif (lpStart->vReflectionsPan.z == lpFinish->vReflectionsPan.z)\n\t\tlpResult->vReflectionsPan.z = lpStart->vReflectionsPan.z;\n\telse\n\t\tlpResult->vReflectionsPan.z = FinalVector.z + (flInvRatio * (StartVector.z - FinalVector.z));\n\t\n\t// Reverb\n\tif (lpStart->lReverb == lpFinish->lReverb)\n\t\tlpResult->lReverb = lpStart->lReverb;\n\telse\n\t\tlpResult->lReverb = (int)( ((float)lpStart->lReverb * flInvRatio) + ((float)lpFinish->lReverb * flRatio) );\n\t\n\t// Reverb Delay\n\tif (lpStart->flReverbDelay == lpFinish->flReverbDelay)\n\t\tlpResult->flReverbDelay = lpStart->flReverbDelay;\n\telse\n\t\tlpResult->flReverbDelay = (float)exp( (log(lpStart->flReverbDelay+0.0001f) * flInvRatio) + (log(lpFinish->flReverbDelay+0.0001f) * flRatio) );\n\t\n\t// Reverb Pan\n\n\t// To interpolate the vector correctly we need to ensure that both the initial and final vectors are clamped to a length of 1.0f\t\n\tStartVector = lpStart->vReverbPan;\n\tFinalVector = lpFinish->vReverbPan;\n\n\tClamp(&StartVector);\n\tClamp(&FinalVector);\n\n\tif (lpStart->vReverbPan.x == lpFinish->vReverbPan.x)\n\t\tlpResult->vReverbPan.x = lpStart->vReverbPan.x;\n\telse\n\t\tlpResult->vReverbPan.x = FinalVector.x + (flInvRatio * (StartVector.x - FinalVector.x));\n\t\n\tif (lpStart->vReverbPan.y == lpFinish->vReverbPan.y)\n\t\tlpResult->vReverbPan.y = lpStart->vReverbPan.y;\n\telse\n\t\tlpResult->vReverbPan.y = FinalVector.y + (flInvRatio * (StartVector.y - FinalVector.y));\n\t\n\tif (lpStart->vReverbPan.z == lpFinish->vReverbPan.z)\n\t\tlpResult->vReverbPan.z = lpStart->vReverbPan.z;\n\telse\n\t\tlpResult->vReverbPan.z = FinalVector.z + (flInvRatio * (StartVector.z - FinalVector.z));\n\t\n\t// Echo Time\n\tif (lpStart->flEchoTime == lpFinish->flEchoTime)\n\t\tlpResult->flEchoTime = lpStart->flEchoTime;\n\telse\n\t\tlpResult->flEchoTime = (float)exp( (log(lpStart->flEchoTime) * flInvRatio) + (log(lpFinish->flEchoTime) * flRatio) );\n\t\n\t// Echo Depth\n\tif (lpStart->flEchoDepth == lpFinish->flEchoDepth)\n\t\tlpResult->flEchoDepth = lpStart->flEchoDepth;\n\telse\n\t\tlpResult->flEchoDepth = (lpStart->flEchoDepth * flInvRatio) + (lpFinish->flEchoDepth * flRatio);\n\n\t// Modulation Time\n\tif (lpStart->flModulationTime == lpFinish->flModulationTime)\n\t\tlpResult->flModulationTime = lpStart->flModulationTime;\n\telse\n\t\tlpResult->flModulationTime = (float)exp( (log(lpStart->flModulationTime) * flInvRatio) + (log(lpFinish->flModulationTime) * flRatio) );\n\t\n\t// Modulation Depth\n\tif (lpStart->flModulationDepth == lpFinish->flModulationDepth)\n\t\tlpResult->flModulationDepth = lpStart->flModulationDepth;\n\telse\n\t\tlpResult->flModulationDepth = (lpStart->flModulationDepth * flInvRatio) + (lpFinish->flModulationDepth * flRatio);\n\t\n\t// Air Absorption HF\n\tif (lpStart->flAirAbsorptionHF == lpFinish->flAirAbsorptionHF)\n\t\tlpResult->flAirAbsorptionHF = lpStart->flAirAbsorptionHF;\n\telse\n\t\tlpResult->flAirAbsorptionHF = (lpStart->flAirAbsorptionHF * flInvRatio) + (lpFinish->flAirAbsorptionHF * flRatio);\n\t\n\t// HF Reference\n\tif (lpStart->flHFReference == lpFinish->flHFReference)\n\t\tlpResult->flHFReference = lpStart->flHFReference;\n\telse\n\t\tlpResult->flHFReference = (float)exp( (log(lpStart->flHFReference) * flInvRatio) + (log(lpFinish->flHFReference) * flRatio) );\n\t\n\t// LF Reference\n\tif (lpStart->flLFReference == lpFinish->flLFReference)\n\t\tlpResult->flLFReference = lpStart->flLFReference;\n\telse\n\t\tlpResult->flLFReference = (float)exp( (log(lpStart->flLFReference) * flInvRatio) + (log(lpFinish->flLFReference) * flRatio) );\n\t\n\t// Room Rolloff Factor\n\tif (lpStart->flRoomRolloffFactor == lpFinish->flRoomRolloffFactor)\n\t\tlpResult->flRoomRolloffFactor = lpStart->flRoomRolloffFactor;\n\telse\n\t\tlpResult->flRoomRolloffFactor = (lpStart->flRoomRolloffFactor * flInvRatio) + (lpFinish->flRoomRolloffFactor * flRatio);\n\t\n\t// Flags\n\tlpResult->ulFlags = (lpStart->ulFlags & lpFinish->ulFlags);\n\n\t// Clamp Delays\n\tif (lpResult->flReflectionsDelay > EAXLISTENER_MAXREFLECTIONSDELAY)\n\t\tlpResult->flReflectionsDelay = EAXLISTENER_MAXREFLECTIONSDELAY;\n\n\tif (lpResult->flReverbDelay > EAXLISTENER_MAXREVERBDELAY)\n\t\tlpResult->flReverbDelay = EAXLISTENER_MAXREVERBDELAY;\n\n\treturn true;\n}\n\n\n/*\n\tCheckEAX3LP\n\tChecks that the parameters in the EAX 3 Listener Properties structure are in-range\n*/\nbool CheckEAX3LP(LPEAXLISTENERPROPERTIES lpEAX3LP)\n{\n\tif ( (lpEAX3LP->lRoom < EAXLISTENER_MINROOM) || (lpEAX3LP->lRoom > EAXLISTENER_MAXROOM) )\n\t\treturn false;\n\n\tif ( (lpEAX3LP->lRoomHF < EAXLISTENER_MINROOMHF) || (lpEAX3LP->lRoomHF > EAXLISTENER_MAXROOMHF) )\n\t\treturn false;\n\n\tif ( (lpEAX3LP->lRoomLF < EAXLISTENER_MINROOMLF) || (lpEAX3LP->lRoomLF > EAXLISTENER_MAXROOMLF) )\n\t\treturn false;\n\n\tif ( (lpEAX3LP->ulEnvironment < EAXLISTENER_MINENVIRONMENT) || (lpEAX3LP->ulEnvironment > EAXLISTENER_MAXENVIRONMENT) )\n\t\treturn false;\n\n\tif ( (lpEAX3LP->flEnvironmentSize < EAXLISTENER_MINENVIRONMENTSIZE) || (lpEAX3LP->flEnvironmentSize > EAXLISTENER_MAXENVIRONMENTSIZE) )\n\t\treturn false;\n\n\tif ( (lpEAX3LP->flEnvironmentDiffusion < EAXLISTENER_MINENVIRONMENTDIFFUSION) || (lpEAX3LP->flEnvironmentDiffusion > EAXLISTENER_MAXENVIRONMENTDIFFUSION) )\n\t\treturn false;\n\n\tif ( (lpEAX3LP->flDecayTime < EAXLISTENER_MINDECAYTIME) || (lpEAX3LP->flDecayTime > EAXLISTENER_MAXDECAYTIME) )\n\t\treturn false;\n\n\tif ( (lpEAX3LP->flDecayHFRatio < EAXLISTENER_MINDECAYHFRATIO) || (lpEAX3LP->flDecayHFRatio > EAXLISTENER_MAXDECAYHFRATIO) )\n\t\treturn false;\n\n\tif ( (lpEAX3LP->flDecayLFRatio < EAXLISTENER_MINDECAYLFRATIO) || (lpEAX3LP->flDecayLFRatio > EAXLISTENER_MAXDECAYLFRATIO) )\n\t\treturn false;\n\n\tif ( (lpEAX3LP->lReflections < EAXLISTENER_MINREFLECTIONS) || (lpEAX3LP->lReflections > EAXLISTENER_MAXREFLECTIONS) )\n\t\treturn false;\n\n\tif ( (lpEAX3LP->flReflectionsDelay < EAXLISTENER_MINREFLECTIONSDELAY) || (lpEAX3LP->flReflectionsDelay > EAXLISTENER_MAXREFLECTIONSDELAY) )\n\t\treturn false;\n\n\tif ( (lpEAX3LP->lReverb < EAXLISTENER_MINREVERB) || (lpEAX3LP->lReverb > EAXLISTENER_MAXREVERB) )\n\t\treturn false;\n\n\tif ( (lpEAX3LP->flReverbDelay < EAXLISTENER_MINREVERBDELAY) || (lpEAX3LP->flReverbDelay > EAXLISTENER_MAXREVERBDELAY) )\n\t\treturn false;\n\n\tif ( (lpEAX3LP->flEchoTime < EAXLISTENER_MINECHOTIME) || (lpEAX3LP->flEchoTime > EAXLISTENER_MAXECHOTIME) )\n\t\treturn false;\n\n\tif ( (lpEAX3LP->flEchoDepth < EAXLISTENER_MINECHODEPTH) || (lpEAX3LP->flEchoDepth > EAXLISTENER_MAXECHODEPTH) )\n\t\treturn false;\n\n\tif ( (lpEAX3LP->flModulationTime < EAXLISTENER_MINMODULATIONTIME) || (lpEAX3LP->flModulationTime > EAXLISTENER_MAXMODULATIONTIME) )\n\t\treturn false;\n\n\tif ( (lpEAX3LP->flModulationDepth < EAXLISTENER_MINMODULATIONDEPTH) || (lpEAX3LP->flModulationDepth > EAXLISTENER_MAXMODULATIONDEPTH) )\n\t\treturn false;\n\n\tif ( (lpEAX3LP->flAirAbsorptionHF < EAXLISTENER_MINAIRABSORPTIONHF) || (lpEAX3LP->flAirAbsorptionHF > EAXLISTENER_MAXAIRABSORPTIONHF) )\n\t\treturn false;\n\n\tif ( (lpEAX3LP->flHFReference < EAXLISTENER_MINHFREFERENCE) || (lpEAX3LP->flHFReference > EAXLISTENER_MAXHFREFERENCE) )\n\t\treturn false;\n\n\tif ( (lpEAX3LP->flLFReference < EAXLISTENER_MINLFREFERENCE) || (lpEAX3LP->flLFReference > EAXLISTENER_MAXLFREFERENCE) )\n\t\treturn false;\n\n\tif ( (lpEAX3LP->flRoomRolloffFactor < EAXLISTENER_MINROOMROLLOFFFACTOR) || (lpEAX3LP->flRoomRolloffFactor > EAXLISTENER_MAXROOMROLLOFFFACTOR) )\n\t\treturn false;\n\n\tif (lpEAX3LP->ulFlags & EAXLISTENERFLAGS_RESERVED)\n\t\treturn false;\n\n\treturn true;\n}\n\n/*\n\tClamp\n\tClamps the length of the vector to 1.0f\n*/\nvoid Clamp(EAXVECTOR *eaxVector)\n{\n\tfloat flMagnitude;\n\tfloat flInvMagnitude;\n\n\tflMagnitude = (float)sqrt((eaxVector->x*eaxVector->x) + (eaxVector->y*eaxVector->y) + (eaxVector->z*eaxVector->z));\n\n\tif (flMagnitude <= 1.0f)\n\t\treturn;\n\n\tflInvMagnitude = 1.0f / flMagnitude;\n\n\teaxVector->x *= flInvMagnitude;\n\teaxVector->y *= flInvMagnitude;\n\teaxVector->z *= flInvMagnitude;\n}\n\n\n/***********************************************************************************************\\\n*\n* To assist those developers wishing to add EAX effects to their level editors, each of the \n\n* List of string names of the various EAX 3.0 presets defined in eax-util.h\n* Arrays to group together presets of the same scenario\n*\n\\***********************************************************************************************/\n\n\n//////////////////////////////////////////////////////\n// Array of scenario names\t\t\t\t\t\t\t//\n//////////////////////////////////////////////////////\n\nconst char* EAX30_SCENARIO_NAMES[] =\t\t\t\t\n{\t\n\t\"Castle\", \n\t\"Factory\", \n\t\"IcePalace\", \n\t\"SpaceStation\", \n\t\"WoodenShip\",\n\t\"Sports\",\n\t\"Prefab\",\n\t\"Domes and Pipes\",\n\t\"Outdoors\",\n\t\"Mood\",\n\t\"Driving\",\n\t\"City\",\n\t\"Miscellaneous\",\n\t\"Original\"\n};\n\n//////////////////////////////////////////////////////\n// Array of standardised location names\t\t\t\t//\n//////////////////////////////////////////////////////\n\nconst char* EAX30_LOCATION_NAMES[] =\t\t\t\t\n{\t\n\t\"Hall\", \n\t\"Large Room\", \n\t\"Medium Room\", \n\t\"Small Room\", \n\t\"Cupboard\", \n\t\"Alcove\", \n\t\"Long Passage\", \n\t\"Short Passage\", \n\t\"Courtyard\"\n};\n\n//////////////////////////////////////////////////////\n// Standardised Location effects can be accessed\t//\n// from a matrix\t\t\t\t\t\t\t\t\t//\n//////////////////////////////////////////////////////\n\nEAXLISTENERPROPERTIES EAX30_STANDARD_PRESETS[EAX30_NUM_STANDARD_SCENARIOS][EAX30_NUM_LOCATIONS]=\n{\n\t{EAX30_PRESET_CASTLE_HALL,\t\tEAX30_PRESET_CASTLE_LARGEROOM,\t\tEAX30_PRESET_CASTLE_MEDIUMROOM,\t\t\tEAX30_PRESET_CASTLE_SMALLROOM,\t\tEAX30_PRESET_CASTLE_CUPBOARD,\t\tEAX30_PRESET_CASTLE_ALCOVE,\t\t\tEAX30_PRESET_CASTLE_LONGPASSAGE,\t\tEAX30_PRESET_CASTLE_SHORTPASSAGE,\t\tEAX30_PRESET_CASTLE_COURTYARD},\n\t{EAX30_PRESET_FACTORY_HALL,\t\tEAX30_PRESET_FACTORY_LARGEROOM,\t\tEAX30_PRESET_FACTORY_MEDIUMROOM,\t\tEAX30_PRESET_FACTORY_SMALLROOM,\t\tEAX30_PRESET_FACTORY_CUPBOARD,\t\tEAX30_PRESET_FACTORY_ALCOVE,\t\tEAX30_PRESET_FACTORY_LONGPASSAGE,\t\tEAX30_PRESET_FACTORY_SHORTPASSAGE,\t\tEAX30_PRESET_FACTORY_COURTYARD},\n\t{EAX30_PRESET_ICEPALACE_HALL,\tEAX30_PRESET_ICEPALACE_LARGEROOM,\tEAX30_PRESET_ICEPALACE_MEDIUMROOM,\t\tEAX30_PRESET_ICEPALACE_SMALLROOM,\tEAX30_PRESET_ICEPALACE_CUPBOARD,\tEAX30_PRESET_ICEPALACE_ALCOVE,\t\tEAX30_PRESET_ICEPALACE_LONGPASSAGE,\t\tEAX30_PRESET_ICEPALACE_SHORTPASSAGE,\tEAX30_PRESET_ICEPALACE_COURTYARD},\n\t{EAX30_PRESET_SPACESTATION_HALL,EAX30_PRESET_SPACESTATION_LARGEROOM,EAX30_PRESET_SPACESTATION_MEDIUMROOM,\tEAX30_PRESET_SPACESTATION_SMALLROOM,EAX30_PRESET_SPACESTATION_CUPBOARD,\tEAX30_PRESET_SPACESTATION_ALCOVE,\tEAX30_PRESET_SPACESTATION_LONGPASSAGE,\tEAX30_PRESET_SPACESTATION_SHORTPASSAGE, EAX30_PRESET_SPACESTATION_HALL},\n\t{EAX30_PRESET_WOODEN_HALL,\t\tEAX30_PRESET_WOODEN_LARGEROOM,\t\tEAX30_PRESET_WOODEN_MEDIUMROOM,\t\t\tEAX30_PRESET_WOODEN_SMALLROOM,\t\tEAX30_PRESET_WOODEN_CUPBOARD,\t\tEAX30_PRESET_WOODEN_ALCOVE,\t\t\tEAX30_PRESET_WOODEN_LONGPASSAGE,\t\tEAX30_PRESET_WOODEN_SHORTPASSAGE,\t\tEAX30_PRESET_WOODEN_COURTYARD},\n};\n\n\n/********************************************************************************************************/\n\n//////////////////////////////////////////////////////\n// Array of original environment names\t\t\t\t//\n//////////////////////////////////////////////////////\n\nconst char* EAX30_ORIGINAL_PRESET_NAMES[] =\n{\n\t\"Generic\",\n\t\"Padded Cell\",\n\t\"Room\",\n\t\"Bathroom\",\n\t\"Living Room\",\n\t\"Stone Room\",\n\t\"Auditorium\",\n\t\"Concert Hall\",\n\t\"Cave\",\n\t\"Arena\",\n\t\"Hangar\",\n\t\"Carpetted Hallway\",\n\t\"Hallway\",\n\t\"Stone Corridor\",\n\t\"Alley\",\n\t\"Forest\",\n\t\"City\",\n\t\"Mountains\",\n\t\"Quarry\",\n\t\"Plain\",\n\t\"Parking Lot\",\n\t\"Sewer Pipe\",\n\t\"Underwater\",\n\t\"Drugged\",\n\t\"Dizzy\",\n\t\"Psychotic\"\n};\n\n//////////////////////////////////////////////////////\n// Sports effects matrix\t\t\t\t\t\t\t//\n//////////////////////////////////////////////////////\n\nEAXLISTENERPROPERTIES\t\tEAX30_ORIGINAL_PRESETS[] =\n{\n\tEAX30_PRESET_GENERIC,\n\tEAX30_PRESET_PADDEDCELL,\n\tEAX30_PRESET_ROOM,\n\tEAX30_PRESET_BATHROOM,\n\tEAX30_PRESET_LIVINGROOM,\n\tEAX30_PRESET_STONEROOM,\n\tEAX30_PRESET_AUDITORIUM,\n\tEAX30_PRESET_CONCERTHALL,\n\tEAX30_PRESET_CAVE,\n\tEAX30_PRESET_ARENA,\n\tEAX30_PRESET_HANGAR,\n\tEAX30_PRESET_CARPETTEDHALLWAY,\n\tEAX30_PRESET_HALLWAY,\n\tEAX30_PRESET_STONECORRIDOR,\n\tEAX30_PRESET_ALLEY,\n\tEAX30_PRESET_FOREST,\n\tEAX30_PRESET_CITY,\n\tEAX30_PRESET_MOUNTAINS,\n\tEAX30_PRESET_QUARRY,\n\tEAX30_PRESET_PLAIN,\n\tEAX30_PRESET_PARKINGLOT,\n\tEAX30_PRESET_SEWERPIPE,\n\tEAX30_PRESET_UNDERWATER,\n\tEAX30_PRESET_DRUGGED,\n\tEAX30_PRESET_DIZZY,\n\tEAX30_PRESET_PSYCHOTIC\n};\n\n/********************************************************************************************************/\n\n//////////////////////////////////////////////////////\n// Array of sport environment names\t\t\t\t\t//\n//////////////////////////////////////////////////////\n\nconst char* EAX30_SPORTS_PRESET_NAMES[] =\n{\n\t\"Empty Stadium\",\n\t\"Full Stadium\", \n\t\"Stadium Tannoy\",\n\t\"Squash Court\",\n\t\"Small Swimming Pool\", \n\t\"Large Swimming Pool\",\n\t\"Gymnasium\"\n};\n\n//////////////////////////////////////////////////////\n// Sports effects matrix\t\t\t\t\t\t\t//\n//////////////////////////////////////////////////////\n\nEAXLISTENERPROPERTIES\t\tEAX30_SPORTS_PRESETS[] =\n{\n\tEAX30_PRESET_SPORT_EMPTYSTADIUM,\n\tEAX30_PRESET_SPORT_FULLSTADIUM,\n\tEAX30_PRESET_SPORT_STADIUMTANNOY,\n\tEAX30_PRESET_SPORT_SQUASHCOURT,\n\tEAX30_PRESET_SPORT_SMALLSWIMMINGPOOL,\n\tEAX30_PRESET_SPORT_LARGESWIMMINGPOOL,\n\tEAX30_PRESET_SPORT_GYMNASIUM\n};\n\n/********************************************************************************************************/\n\n//////////////////////////////////////////////////////\n// Array of prefab environment names\t\t\t\t//\n//////////////////////////////////////////////////////\n\nconst char* EAX30_PREFAB_PRESET_NAMES[] =\n{\n\t\"Workshop\",\n\t\"School Room\",\n\t\"Practise Room\",\n\t\"Outhouse\",\n\t\"Caravan\"\n};\n\n//////////////////////////////////////////////////////\n// Prefab effects matrix\t\t\t\t\t\t\t//\n//////////////////////////////////////////////////////\n\nEAXLISTENERPROPERTIES EAX30_PREFAB_PRESETS[] =\n{\n\tEAX30_PRESET_PREFAB_WORKSHOP,\n\tEAX30_PRESET_PREFAB_SCHOOLROOM,\n\tEAX30_PRESET_PREFAB_PRACTISEROOM,\n\tEAX30_PRESET_PREFAB_OUTHOUSE,\n\tEAX30_PRESET_PREFAB_CARAVAN\n};\n\n/********************************************************************************************************/\n\n//////////////////////////////////////////////////////\n// Array of Domes & Pipes environment names\t\t\t//\n//////////////////////////////////////////////////////\n\nconst char* EAX30_DOMESNPIPES_PRESET_NAMES[] =\n{\n\t\"Domed Tomb\",\n\t\"Saint Paul's Dome\",\n\t\"Small Pipe\",\n\t\"Long Thin Pipe\", \n\t\"Large Pipe\",\n\t\"Resonant Pipe\"\n};\n\n//////////////////////////////////////////////////////\n// Domes & Pipes effects matrix\t\t\t\t\t\t//\n//////////////////////////////////////////////////////\n\nEAXLISTENERPROPERTIES EAX30_DOMESNPIPES_PRESETS[] =\n{\n\tEAX30_PRESET_DOME_TOMB,\n\tEAX30_PRESET_DOME_SAINTPAULS,\n\tEAX30_PRESET_PIPE_SMALL,\n\tEAX30_PRESET_PIPE_LONGTHIN,\n\tEAX30_PRESET_PIPE_LARGE,\n\tEAX30_PRESET_PIPE_RESONANT\n};\n\n/********************************************************************************************************/\n\n//////////////////////////////////////////////////////\n// Array of Outdoors environment names\t\t\t\t//\n//////////////////////////////////////////////////////\n\nconst char* EAX30_OUTDOORS_PRESET_NAMES[] =\n{\n\t\"Backyard\", \n\t\"Rolling Plains\",\n\t\"Deep Canyon\",\n\t\"Creek\",\n\t\"Valley\"\n};\n\n//////////////////////////////////////////////////////\n// Outdoors effects matrix\t\t\t\t\t\t\t//\n//////////////////////////////////////////////////////\n\nEAXLISTENERPROPERTIES EAX30_OUTDOORS_PRESETS[] =\n{\n\tEAX30_PRESET_OUTDOORS_BACKYARD,\n\tEAX30_PRESET_OUTDOORS_ROLLINGPLAINS,\n\tEAX30_PRESET_OUTDOORS_DEEPCANYON,\n\tEAX30_PRESET_OUTDOORS_CREEK,\n\tEAX30_PRESET_OUTDOORS_VALLEY\n};\n\n/********************************************************************************************************/\n\n//////////////////////////////////////////////////////\n// Array of Mood environment names\t\t\t\t\t//\n//////////////////////////////////////////////////////\n\nconst char* EAX30_MOOD_PRESET_NAMES[] =\n{\n\t\"Heaven\",\n\t\"Hell\",\n\t\"Memory\"\n};\n\n//////////////////////////////////////////////////////\n// Mood effects matrix\t\t\t\t\t\t\t\t//\n//////////////////////////////////////////////////////\n\nEAXLISTENERPROPERTIES EAX30_MOOD_PRESETS[] =\n{\n\tEAX30_PRESET_MOOD_HEAVEN,\n\tEAX30_PRESET_MOOD_HELL,\n\tEAX30_PRESET_MOOD_MEMORY\n};\n\n/********************************************************************************************************/\n\n//////////////////////////////////////////////////////\n// Array of driving environment names\t\t\t\t//\n//////////////////////////////////////////////////////\n\nconst char* EAX30_DRIVING_PRESET_NAMES[] =\n{\n\t\"Race Commentator\",\n\t\"Pit Garage\",\n\t\"In-car (Stripped out racer)\",\n\t\"In-car (Sportscar)\",\n\t\"In-car (Luxury)\",\n\t\"Full Grandstand\",\n\t\"Empty Grandstand\",\n\t\"Tunnel\"\n};\n\n//////////////////////////////////////////////////////\n// Driving effects matrix\t\t\t\t\t\t\t//\n//////////////////////////////////////////////////////\n\nEAXLISTENERPROPERTIES EAX30_DRIVING_PRESETS[] =\n{\n\tEAX30_PRESET_DRIVING_COMMENTATOR,\n\tEAX30_PRESET_DRIVING_PITGARAGE,\n\tEAX30_PRESET_DRIVING_INCAR_RACER,\n\tEAX30_PRESET_DRIVING_INCAR_SPORTS,\n\tEAX30_PRESET_DRIVING_INCAR_LUXURY,\n\tEAX30_PRESET_DRIVING_FULLGRANDSTAND,\n\tEAX30_PRESET_DRIVING_EMPTYGRANDSTAND,\n\tEAX30_PRESET_DRIVING_TUNNEL\n};\n\n/********************************************************************************************************/\n\n//////////////////////////////////////////////////////\n// Array of City environment names\t\t\t\t\t//\n//////////////////////////////////////////////////////\n\nconst char* EAX30_CITY_PRESET_NAMES[] =\n{\n\t\"City Streets\",\n\t\"Subway\",\n\t\"Museum\",\n\t\"Library\",\n\t\"Underpass\",\n\t\"Abandoned City\"\n};\n\n//////////////////////////////////////////////////////\n// City effects matrix\t\t\t\t\t\t\t\t//\n//////////////////////////////////////////////////////\n\nEAXLISTENERPROPERTIES EAX30_CITY_PRESETS[] =\n{\n\tEAX30_PRESET_CITY_STREETS,\n\tEAX30_PRESET_CITY_SUBWAY,\n\tEAX30_PRESET_CITY_MUSEUM,\n\tEAX30_PRESET_CITY_LIBRARY,\n\tEAX30_PRESET_CITY_UNDERPASS,\n\tEAX30_PRESET_CITY_ABANDONED\n};\n\n/********************************************************************************************************/\n\n//////////////////////////////////////////////////////\n// Array of Misc environment names\t\t\t\t\t//\n//////////////////////////////////////////////////////\n\nconst char* EAX30_MISC_PRESET_NAMES[] =\n{\n\t\"Dusty Box Room\",\n\t\"Chapel\",\n\t\"Small Water Room\"\n};\n\n//////////////////////////////////////////////////////\n// Misc effects matrix\t\t\t\t\t\t\t\t//\n//////////////////////////////////////////////////////\n\nEAXLISTENERPROPERTIES EAX30_MISC_PRESETS[] =\n{\n\tEAX30_PRESET_DUSTYROOM,\n\tEAX30_PRESET_CHAPEL,\n\tEAX30_PRESET_SMALLWATERROOM\n};\n\n"
  },
  {
    "path": "src/audio/eax/eax-util.h",
    "content": "/*******************************************************************\\\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*  EAX-UTIL.H - utilities for Environmental Audio Extensions v. 3.0\t*\n*\t\t\t\tDefinitions of the Original 26 EAX Presets\t\t\t*\n*\t\t\t\tDefinitions for some new EAX Presets\t\t\t\t*\n*\t\t\t\tDefinitions of some Material Presets\t\t\t\t*\n*\t\t\t\tFunction declaration for EAX Morphing\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n\\*******************************************************************/\n\n#ifndef EAXUTIL_INCLUDED\n#define EAXUTIL_INCLUDED\n\n#include <eax.h>\n\n/***********************************************************************************************\n* Function\t:\tEAX3ListenerInterpolate\n* Params\t:\tlpStart\t\t\t- Initial EAX 3 Listener parameters\n*\t\t\t:\tlpFinish\t\t- Final EAX 3 Listener parameters\n*\t\t\t:\tflRatio\t\t\t- Ratio Destination : Source (0.0 == Source, 1.0 == Destination)\n*\t\t\t:\tlpResult\t\t- Interpolated EAX 3 Listener parameters\n*\t\t\t:\tbCheckValues\t- Check EAX 3.0 parameters are in range,\n\t\t\t\t\t\t\t\t- default == false (no checking)\n************************************************************************************************/\nbool EAX3ListenerInterpolate(EAXLISTENERPROPERTIES *lpStartEAX3LP, EAXLISTENERPROPERTIES *lpFinishEAX3LP,\n\t\t\tfloat flRatio, EAXLISTENERPROPERTIES *lpResultEAX3LP, bool bCheckValues = false);\n\n\n/***********************************************************************************************\\\n*\n* Legacy environment presets for use with DSPROPERTY_EAXLISTENER_ALLPARAMETERS.\n* Each array conforms to the DSPROPSETID_EAX30_ListenerProperties structure defined in EAX.H.\n*\n************************************************************************************************/\n\n//\tEnv\t\tSize\tDiffus\tRoom\tRoomHF\tRoomLF\tDecTm\tDcHF\tDcLF\tRefl\tRefDel\tRef Pan\t\t\t\tRevb\tRevDel\t\tRev Pan\t\t\t\tEchTm\tEchDp\tModTm\tModDp\tAirAbs\tHFRef\t\tLFRef\tRRlOff\tFLAGS\n#define EAX30_PRESET_GENERIC \\\n\t{0,\t\t7.5f,\t1.000f,\t-1000,\t-100,\t0,\t\t1.49f,\t0.83f,\t1.00f,\t-2602,\t0.007f,\t0.00f,0.00f,0.00f,\t200,\t0.011f,\t\t0.00f,0.00f,0.00f,\t0.250f,\t0.000f,\t0.250f,\t0.000f,\t-5.0f,\t5000.0f,\t250.0f,\t0.00f,\t0x3f }\n#define EAX30_PRESET_PADDEDCELL \\\n\t{1,\t\t1.4f,\t1.000f,\t-1000,\t-6000,\t0,\t\t0.17f,\t0.10f,\t1.00f,\t-1204,\t0.001f, 0.00f,0.00f,0.00f,  207,\t0.002f,\t\t0.00f,0.00f,0.00f,\t0.250f, 0.000f, 0.250f, 0.000f,\t-5.0f,\t5000.0f,\t250.0f,\t0.00f,\t0x3f }\n#define EAX30_PRESET_ROOM \\\n\t{2,\t\t1.9f,\t1.000f,\t-1000,\t-454,\t0,\t\t0.40f,\t0.83f,\t1.00f,  -1646,\t0.002f, 0.00f,0.00f,0.00f,\t53,\t\t0.003f,\t\t0.00f,0.00f,0.00f,\t0.250f, 0.000f, 0.250f, 0.000f,\t-5.0f,  5000.0f,\t250.0f,\t0.00f,\t0x3f }\n#define EAX30_PRESET_BATHROOM \\\n\t{3,\t\t1.4f,\t1.000f,\t-1000,  -1200,\t0,\t\t1.49f,\t0.54f,\t1.00f,  -370,\t0.007f, 0.00f,0.00f,0.00f,\t1030,\t0.011f,\t\t0.00f,0.00f,0.00f,\t0.250f, 0.000f, 0.250f, 0.000f,\t-5.0f,  5000.0f,\t250.0f,\t0.00f,\t0x3f }\n#define EAX30_PRESET_LIVINGROOM \\\n\t{4,\t\t2.5f,\t1.000f,\t-1000,  -6000,\t0,\t\t0.50f,\t0.10f,\t1.00f,  -1376,\t0.003f, 0.00f,0.00f,0.00f,\t-1104,\t0.004f,\t\t0.00f,0.00f,0.00f,\t0.250f, 0.000f, 0.250f, 0.000f,\t-5.0f,  5000.0f,\t250.0f,\t0.00f,\t0x3f }\n#define EAX30_PRESET_STONEROOM \\\n\t{5,\t\t11.6f,\t1.000f,  -1000, -300,\t0,\t\t2.31f,\t0.64f,\t1.00f,\t-711,\t0.012f, 0.00f,0.00f,0.00f,\t83,\t\t0.017f,\t\t0.00f,0.00f,0.00f,\t0.250f, 0.000f, 0.250f, 0.000f,\t-5.0f,  5000.0f,\t250.0f,\t0.00f,\t0x3f }\n#define EAX30_PRESET_AUDITORIUM \\\n\t{6,\t\t21.6f,\t1.000f,  -1000,\t-476,\t0,\t\t4.32f,\t0.59f,\t1.00f,\t-789,\t0.020f, 0.00f,0.00f,0.00f,\t-289,\t0.030f,\t\t0.00f,0.00f,0.00f,\t0.250f, 0.000f, 0.250f, 0.000f,\t-5.0f,  5000.0f,\t250.0f,\t0.00f,\t0x3f }\n#define EAX30_PRESET_CONCERTHALL \\\n\t{7,\t\t19.6f,\t1.000f,  -1000,\t-500,\t0,\t\t3.92f,\t0.70f,\t1.00f,  -1230,\t0.020f, 0.00f,0.00f,0.00f,  -02,\t0.029f,\t\t0.00f,0.00f,0.00f,\t0.250f, 0.000f, 0.250f, 0.000f, -5.0f,  5000.0f,\t250.0f, 0.00f,\t0x3f }\n#define EAX30_PRESET_CAVE \\\n\t{8,\t\t14.6f,\t1.000f,  -1000,\t0,\t\t0,\t\t2.91f,\t1.30f,\t1.00f,  -602,\t0.015f, 0.00f,0.00f,0.00f,\t-302,\t0.022f,\t\t0.00f,0.00f,0.00f,\t0.250f, 0.000f, 0.250f, 0.000f, -5.0f,  5000.0f,\t250.0f,\t0.00f,\t0x1f }\n#define EAX30_PRESET_ARENA \\\n\t{9,\t\t36.2f,\t1.000f,  -1000,\t-698,\t0,\t\t7.24f,\t0.33f,\t1.00f,  -1166,\t0.020f, 0.00f,0.00f,0.00f,  16,\t\t0.030f,\t\t0.00f,0.00f,0.00f,\t0.250f, 0.000f, 0.250f, 0.000f, -5.0f,  5000.0f,\t250.0f,\t0.00f,\t0x3f }\n#define EAX30_PRESET_HANGAR \\\n\t{10,\t50.3f,\t1.000f,  -1000,\t-1000,\t0,\t\t10.05f, 0.23f,\t1.00f,  -602,\t0.020f, 0.00f,0.00f,0.00f,  198,\t0.030f,\t\t0.00f,0.00f,0.00f,\t0.250f, 0.000f, 0.250f, 0.000f, -5.0f,  5000.0f,\t250.0f, 0.00f,\t0x3f }\n#define EAX30_PRESET_CARPETTEDHALLWAY \\\n\t{11,\t1.9f,\t1.000f,\t-1000,\t-4000,\t0,\t\t0.30f,\t0.10f,\t1.00f,  -1831,\t0.002f, 0.00f,0.00f,0.00f,\t-1630,\t0.030f,\t\t0.00f,0.00f,0.00f,\t0.250f, 0.000f, 0.250f, 0.000f, -5.0f,  5000.0f,\t250.0f, 0.00f,\t0x3f }\n#define EAX30_PRESET_HALLWAY \\\n\t{12,\t1.8f,\t1.000f,\t-1000,\t-300,\t0,\t\t1.49f,\t0.59f,\t1.00f,  -1219,\t0.007f, 0.00f,0.00f,0.00f,  441,\t0.011f,\t\t0.00f,0.00f,0.00f,\t0.250f, 0.000f, 0.250f, 0.000f, -5.0f,  5000.0f,\t250.0f, 0.00f,\t0x3f }\n#define EAX30_PRESET_STONECORRIDOR \\\n\t{13,\t13.5f,\t1.000f,\t-1000,\t-237,\t0,\t\t2.70f,\t0.79f,\t1.00f,  -1214,\t0.013f, 0.00f,0.00f,0.00f,  395,\t0.020f,\t\t0.00f,0.00f,0.00f,\t0.250f, 0.000f, 0.250f, 0.000f, -5.0f,  5000.0f,\t250.0f, 0.00f,\t0x3f }\n#define EAX30_PRESET_ALLEY \\\n\t{14,\t7.5f,\t0.300f,\t-1000,\t-270,\t0,\t\t1.49f,\t0.86f,\t1.00f,  -1204,\t0.007f, 0.00f,0.00f,0.00f,  -4,\t\t0.011f,\t\t0.00f,0.00f,0.00f,\t0.125f, 0.950f, 0.250f, 0.000f, -5.0f,  5000.0f,\t250.0f, 0.00f,\t0x3f }\n#define EAX30_PRESET_FOREST \\\n\t{15,\t38.0f,\t0.300f,\t-1000,\t-3300,\t0,\t\t1.49f,\t0.54f,\t1.00f,  -2560,\t0.162f, 0.00f,0.00f,0.00f,\t-229,\t0.088f,\t\t0.00f,0.00f,0.00f,\t0.125f, 1.000f, 0.250f, 0.000f, -5.0f,  5000.0f,\t250.0f, 0.00f,\t0x3f }\n#define EAX30_PRESET_CITY \\\n\t{16,\t7.5f,\t0.500f,\t-1000,\t-800,\t0,\t\t1.49f,\t0.67f,\t1.00f,  -2273,\t0.007f, 0.00f,0.00f,0.00f,\t-1691,\t0.011f,\t\t0.00f,0.00f,0.00f,\t0.250f, 0.000f, 0.250f, 0.000f, -5.0f,  5000.0f,\t250.0f, 0.00f,\t0x3f }\n#define EAX30_PRESET_MOUNTAINS \\\n\t{17,\t100.0f, 0.270f,\t-1000,\t-2500,\t0,\t\t1.49f,\t0.21f,\t1.00f,  -2780,\t0.300f, 0.00f,0.00f,0.00f,\t-1434,\t0.100f,\t\t0.00f,0.00f,0.00f,\t0.250f, 1.000f, 0.250f, 0.000f, -5.0f,  5000.0f,\t250.0f, 0.00f,\t0x1f }\n#define EAX30_PRESET_QUARRY \\\n\t{18,\t17.5f,\t1.000f,\t-1000,\t-1000,\t0,\t\t1.49f,\t0.83f,\t1.00f,\t-10000, 0.061f, 0.00f,0.00f,0.00f,  500,\t0.025f,\t\t0.00f,0.00f,0.00f,\t0.125f, 0.700f, 0.250f, 0.000f, -5.0f,  5000.0f,\t250.0f, 0.00f,\t0x3f }\n#define EAX30_PRESET_PLAIN \\\n\t{19,\t42.5f,\t0.210f,\t-1000,\t-2000,\t0,\t\t1.49f,\t0.50f,\t1.00f,  -2466,\t0.179f, 0.00f,0.00f,0.00f,\t-1926,\t0.100f,\t\t0.00f,0.00f,0.00f,\t0.250f, 1.000f, 0.250f, 0.000f, -5.0f,  5000.0f,\t250.0f, 0.00f,\t0x3f }\n#define EAX30_PRESET_PARKINGLOT \\\n\t{20,\t8.3f,\t1.000f,\t-1000,\t0,\t\t0,\t\t1.65f,\t1.50f,\t1.00f,  -1363,\t0.008f, 0.00f,0.00f,0.00f,\t-1153,\t0.012f,\t\t0.00f,0.00f,0.00f,\t0.250f, 0.000f, 0.250f, 0.000f, -5.0f,  5000.0f,\t250.0f, 0.00f,\t0x1f }\n#define EAX30_PRESET_SEWERPIPE \\\n\t{21,\t1.7f,\t0.800f,\t-1000,\t-1000,\t0,\t\t2.81f,\t0.14f,\t1.00f,\t429,\t0.014f, 0.00f,0.00f,0.00f,\t1023,\t0.021f,\t\t0.00f,0.00f,0.00f,\t0.250f, 0.000f, 0.250f, 0.000f, -5.0f,  5000.0f,\t250.0f, 0.00f,\t0x3f }\n#define EAX30_PRESET_UNDERWATER \\\n\t{22,\t1.8f,\t1.000f,\t-1000,  -4000,\t0,\t\t1.49f,\t0.10f,\t1.00f,  -449,\t0.007f, 0.00f,0.00f,0.00f,\t1700,\t0.011f,\t\t0.00f,0.00f,0.00f,\t0.250f, 0.000f, 1.180f, 0.348f, -5.0f,  5000.0f,\t250.0f, 0.00f,\t0x3f }\n#define EAX30_PRESET_DRUGGED \\\n\t{23,\t1.9f,\t0.500f,\t-1000,\t0,\t\t0,\t\t8.39f,\t1.39f,\t1.00f,  -115,\t0.002f, 0.00f,0.00f,0.00f,  985,\t0.030f,\t\t0.00f,0.00f,0.00f,\t0.250f, 0.000f, 0.250f, 1.000f, -5.0f,  5000.0f,\t250.0f, 0.00f,\t0x1f }\n#define EAX30_PRESET_DIZZY \\\n\t{24,\t1.8f,\t0.600f,\t-1000,\t-400,\t0,\t\t17.23f, 0.56f,\t1.00f,  -1713,\t0.020f, 0.00f,0.00f,0.00f,\t-613,\t0.030f,\t\t0.00f,0.00f,0.00f,\t0.250f, 1.000f, 0.810f, 0.310f, -5.0f,  5000.0f,\t250.0f, 0.00f,\t0x1f }\n#define EAX30_PRESET_PSYCHOTIC \\\n\t{25,\t1.0f,\t0.500f,\t-1000,\t-151,\t0,\t\t7.56f,\t0.91f,\t1.00f,  -626,\t0.020f, 0.00f,0.00f,0.00f,  774,\t0.030f,\t\t0.00f,0.00f,0.00f,\t0.250f, 0.000f, 4.000f, 1.000f, -5.0f,  5000.0f,\t250.0f, 0.00f,\t0x1f }\n\n\n/***********************************************************************************************\\\n*\n* New environment presets for use with DSPROPERTY_EAXLISTENER_ALLPARAMETERS.\n* Each array conforms to the DSPROPSETID_EAX30_ListenerProperties structure defined in EAX.H.\n*\n************************************************************************************************/\n\n// STANDARDISED-LOCATION SCENARIOS\n\n// CASTLE PRESETS\n\n//\tEnv\t\tSize\tDiffus\tRoom\tRoomHF\tRoomLF\tDecTm\tDcHF\tDcLF\tRefl\tRefDel\tRef Pan\t\t\t\tRevb\tRevDel\t\tRev Pan\t\t\t\tEchTm\tEchDp\tModTm\tModDp\tAirAbs\tHFRef\t\tLFRef\tRRlOff\tFLAGS\n#define EAX30_PRESET_CASTLE_SMALLROOM \\\n\t{ 26,   8.3f,\t0.890f,\t-1100,\t-800,\t-2000,\t1.22f,\t0.83f,\t0.31f,\t-100,\t0.022f,\t0.00f,0.00f,0.00f,\t0,\t\t0.011f,\t\t0.00f,0.00f,0.00f,\t0.138f,\t0.080f,\t0.250f,\t0.000f,\t-5.0f,\t5168.6f,\t139.5f,  0.00f, 0x20 }\n#define EAX30_PRESET_CASTLE_SHORTPASSAGE \\\n\t{ 26,   8.3f,\t0.890f, -1000,  -1000,  -2000,  2.32f,\t0.83f,\t0.31f,\t-100,\t0.007f, 0.00f,0.00f,0.00f,  -500,\t0.023f,\t\t0.00f,0.00f,0.00f,\t0.138f, 0.080f, 0.250f, 0.000f, -5.0f,  5168.6f,\t139.5f,  0.00f, 0x20 }\n#define EAX30_PRESET_CASTLE_MEDIUMROOM \\\n\t{ 26,   8.3f,\t0.930f, -1000,  -1100,  -2000,  2.04f,\t0.83f,\t0.46f,  -300,\t0.022f, 0.00f,0.00f,0.00f,\t-200,\t0.011f,\t\t0.00f,0.00f,0.00f,\t0.155f, 0.030f, 0.250f, 0.000f, -5.0f,  5168.6f,\t139.5f,  0.00f, 0x20 }\n#define EAX30_PRESET_CASTLE_LONGPASSAGE \\\n\t{ 26,   8.3f,\t0.890f, -1000,  -800,\t-2000,  3.42f,\t0.83f,\t0.31f,  -200,\t0.007f, 0.00f,0.00f,0.00f,\t-600,\t0.023f,\t\t0.00f,0.00f,0.00f,\t0.138f, 0.080f, 0.250f, 0.000f, -5.0f,  5168.6f,\t139.5f,  0.00f, 0x20 }\n#define EAX30_PRESET_CASTLE_LARGEROOM \\\n\t{ 26,   8.3f,\t0.820f, -1000,  -1100,  -1800,  2.53f,\t0.83f,\t0.50f,  -900,\t0.034f, 0.00f,0.00f,0.00f,\t-400,\t0.016f,\t\t0.00f,0.00f,0.00f,\t0.185f, 0.070f, 0.250f, 0.000f, -5.0f,  5168.6f,\t139.5f,  0.00f, 0x20 }\n#define EAX30_PRESET_CASTLE_HALL \\\n\t{ 26,   8.3f,\t0.810f, -1000,  -1100,  -1500,  3.14f,\t0.79f,\t0.62f,  -1300,\t0.056f, 0.00f,0.00f,0.00f,\t-500,\t0.024f,\t\t0.00f,0.00f,0.00f,\t0.250f, 0.000f, 0.250f, 0.000f, -5.0f,  5168.6f,\t139.5f,  0.00f, 0x20 }\n#define EAX30_PRESET_CASTLE_CUPBOARD \\\n\t{ 26,   8.3f,\t0.890f, -1000,  -1100,  -2000,  0.67f,\t0.87f,\t0.31f,  300,\t0.010f,\t0.00f,0.00f,0.00f,\t300,\t0.007f,\t\t0.00f,0.00f,0.00f,\t0.138f, 0.080f, 0.250f, 0.000f, -5.0f,  5168.6f,\t139.5f,  0.00f, 0x20 }\n#define EAX30_PRESET_CASTLE_COURTYARD \\\n\t{ 26,   8.3f,\t0.420f, -1100,  -700,   -900,\t2.13f,\t0.61f,\t0.23f,  -2300,\t0.112f, 0.00f,0.00f,0.00f,\t-1500,\t0.036f,\t\t0.00f,0.00f,0.00f,\t0.250f, 0.370f, 0.250f, 0.000f, -0.0f,  5000.0f,\t250.0f,  0.00f, 0x1f }\n#define EAX30_PRESET_CASTLE_ALCOVE \\\n\t{ 26,   8.3f,\t0.890f,\t-1000,  -600,\t-2000,  1.64f,\t0.87f,\t0.31f,  -100,\t0.007f, 0.00f,0.00f,0.00f,\t-500,\t0.034f,\t\t0.00f,0.00f,0.00f,\t0.138f, 0.080f, 0.250f, 0.000f, -5.0f,\t5168.6f,\t139.5f,  0.00f, 0x20 }\n\n\n// FACTORY PRESETS\n\n//\tEnv\t\tSize\tDiffus\tRoom\tRoomHF\tRoomLF\tDecTm\tDcHF\tDcLF\tRefl\tRefDel\tRef Pan\t\t\t\tRevb\tRevDel\t\tRev Pan\t\t\t\tEchTm\tEchDp\tModTm\tModDp\tAirAbs\tHFRef\t\tLFRef\tRRlOff\tFLAGS\n#define EAX30_PRESET_FACTORY_ALCOVE \\\n\t{ 26,   1.8f,\t0.590f,  -1200, -200,   -600,\t3.14f,\t0.65f,\t1.31f,  300,\t0.010f, 0.00f,0.00f,0.00f,\t-1200,\t0.038f,\t\t0.00f,0.00f,0.00f,\t0.114f, 0.100f, 0.250f, 0.000f, -0.0f,  3762.6f,\t362.5f,  0.00f, 0x20 }\n#define EAX30_PRESET_FACTORY_SHORTPASSAGE \\\n\t{ 26,   1.8f,\t0.640f,  -1200, -200,   -600,\t2.53f,\t0.65f,\t1.31f,  0,\t\t0.010f, 0.00f,0.00f,0.00f,\t-600,\t0.038f,\t\t0.00f,0.00f,0.00f,\t0.135f, 0.230f, 0.250f, 0.000f, -0.0f,  3762.6f,\t362.5f,  0.00f, 0x20 }\n#define EAX30_PRESET_FACTORY_MEDIUMROOM \\\n\t{ 26,   1.9f,\t0.820f,  -1200, -200,   -600,\t2.76f,\t0.65f,\t1.31f,  -1100,\t0.022f, 0.00f,0.00f,0.00f,\t-400,\t0.023f,\t\t0.00f,0.00f,0.00f,\t0.174f, 0.070f, 0.250f, 0.000f, -0.0f,  3762.6f,\t362.5f,  0.00f, 0x20 }\n#define EAX30_PRESET_FACTORY_LONGPASSAGE \\\n\t{ 26,   1.8f,\t0.640f,  -1200, -200,   -600,\t4.06f,\t0.65f,\t1.31f,  0,\t\t0.020f, 0.00f,0.00f,0.00f,\t-900,\t0.037f,\t\t0.00f,0.00f,0.00f,\t0.135f, 0.230f, 0.250f, 0.000f, -0.0f,  3762.6f,\t362.5f,  0.00f, 0x20 }\n#define EAX30_PRESET_FACTORY_LARGEROOM \\\n\t{ 26,   1.9f,\t0.750f,  -1200, -300,   -400,\t4.24f,\t0.51f,\t1.31f,  -1500,\t0.039f, 0.00f,0.00f,0.00f,\t-600,\t0.023f,\t\t0.00f,0.00f,0.00f,\t0.231f, 0.070f, 0.250f, 0.000f, -0.0f,  3762.6f,\t362.5f,  0.00f, 0x20 }\n#define EAX30_PRESET_FACTORY_HALL \\\n\t{ 26,   1.9f,\t0.750f,  -1000, -300,   -400,\t7.43f,\t0.51f,\t1.31f,  -2400,\t0.073f, 0.00f,0.00f,0.00f,\t-500,\t0.027f,\t\t0.00f,0.00f,0.00f,\t0.250f, 0.070f, 0.250f, 0.000f, -0.0f,  3762.6f,\t362.5f,  0.00f, 0x20 }\n#define EAX30_PRESET_FACTORY_CUPBOARD \\\n\t{ 26,   1.7f,\t0.630f,  -1200, -200,   -600,\t0.49f,\t0.65f,\t1.31f,  200,\t0.010f, 0.00f,0.00f,0.00f,\t200,\t0.032f,\t\t0.00f,0.00f,0.00f,\t0.107f, 0.070f, 0.250f, 0.000f, -0.0f,  3762.6f,\t362.5f,  0.00f, 0x20 }\n#define EAX30_PRESET_FACTORY_COURTYARD \\\n\t{ 26,   1.7f,\t0.570f,  -1000, -1000,  -400,\t2.32f,\t0.29f,\t0.56f,  -2400,\t0.090f, 0.00f,0.00f,0.00f,\t-2000,\t0.039f,\t\t0.00f,0.00f,0.00f,\t0.250f, 0.290f, 0.250f, 0.000f, -0.0f,  3762.6f,\t362.5f,  0.00f, 0x20 }\n#define EAX30_PRESET_FACTORY_SMALLROOM \\\n\t{ 26,   1.8f,\t0.820f,  -1200,\t-200,   -600,\t1.72f,\t0.65f,\t1.31f,  -300,\t0.010f, 0.00f,0.00f,0.00f,\t-200,\t0.024f,\t\t0.00f,0.00f,0.00f,\t0.119f, 0.070f, 0.250f, 0.000f, -0.0f,\t3762.6f,\t362.5f,  0.00f, 0x20 }\n\n// ICE PALACE PRESETS\n\n//\tEnv\t\tSize\tDiffus\tRoom\tRoomHF\tRoomLF\tDecTm\tDcHF\tDcLF\tRefl\tRefDel\tRef Pan\t\t\t\tRevb\tRevDel\t\tRev Pan\t\t\t\tEchTm\tEchDp\tModTm\tModDp\tAirAbs\tHFRef\t\tLFRef\tRRlOff\tFLAGS\n#define EAX30_PRESET_ICEPALACE_ALCOVE \\\n\t{ 26,   2.7f,\t0.840f, -1000,  -500,\t-1100,  2.76f,\t1.46f,\t0.28f,  100,\t0.010f, 0.00f,0.00f,0.00f,\t-1200,\t0.030f,\t\t0.00f,0.00f,0.00f,\t0.161f, 0.090f, 0.250f, 0.000f,\t-0.0f,\t12428.5f,\t99.6f,  0.00f,\t0x20 }\n#define EAX30_PRESET_ICEPALACE_SHORTPASSAGE \\\n\t{ 26,   2.7f,\t0.750f, -1000,  -500,\t-1100,  1.79f,\t1.46f,\t0.28f,  -600,\t0.010f, 0.00f,0.00f,0.00f,\t-700,\t0.019f,\t\t0.00f,0.00f,0.00f,\t0.177f, 0.090f, 0.250f, 0.000f, -0.0f,\t12428.5f,\t99.6f,  0.00f,\t0x20 }\n#define EAX30_PRESET_ICEPALACE_MEDIUMROOM \\\n\t{ 26,   2.7f,\t0.870f, -1000,  -500,   -700,\t2.22f,\t1.53f,\t0.32f,  -800,\t0.039f, 0.00f,0.00f,0.00f,\t-1200,\t0.027f,\t\t0.00f,0.00f,0.00f,\t0.186f, 0.120f, 0.250f, 0.000f, -0.0f,\t12428.5f,\t99.6f,  0.00f,\t0x20 }\n#define EAX30_PRESET_ICEPALACE_LONGPASSAGE \\\n\t{ 26,   2.7f,\t0.770f, -1000,  -500,   -800,\t3.01f,\t1.46f,\t0.28f,  -200,\t0.012f, 0.00f,0.00f,0.00f,\t-800,\t0.025f,\t\t0.00f,0.00f,0.00f,\t0.186f, 0.040f, 0.250f, 0.000f, -0.0f,\t12428.5f,\t99.6f,  0.00f,\t0x20 }\n#define EAX30_PRESET_ICEPALACE_LARGEROOM \\\n\t{ 26,   2.9f,\t0.810f, -1000,  -500,   -700,\t3.14f,\t1.53f,\t0.32f,  -1200,\t0.039f, 0.00f,0.00f,0.00f,\t-1300,\t0.027f,\t\t0.00f,0.00f,0.00f,\t0.214f, 0.110f, 0.250f, 0.000f, -0.0f,\t12428.5f,\t99.6f,  0.00f,\t0x20 }\n#define EAX30_PRESET_ICEPALACE_HALL \\\n\t{ 26,   2.9f,\t0.760f, -1000,  -700,   -500,\t5.49f,\t1.53f,\t0.38f,  -1900,\t0.054f, 0.00f,0.00f,0.00f,\t-1400,\t0.052f,\t\t0.00f,0.00f,0.00f,\t0.226f, 0.110f, 0.250f, 0.000f, -0.0f,\t12428.5f,\t99.6f,  0.00f,\t0x20 }\n#define EAX30_PRESET_ICEPALACE_CUPBOARD \\\n\t{ 26,   2.7f,\t0.830f, -1000,  -600,\t-1300,  0.76f,\t1.53f,\t0.26f,  100,\t0.012f, 0.00f,0.00f,0.00f,\t100,\t0.016f,\t\t0.00f,0.00f,0.00f,\t0.143f, 0.080f, 0.250f, 0.000f, -0.0f,\t12428.5f,\t99.6f,  0.00f,\t0x20 }\n#define EAX30_PRESET_ICEPALACE_COURTYARD \\\n\t{ 26,   2.9f,\t0.590f, -1000,  -1100,  -1000,  2.04f,\t1.20f,\t0.38f,  -2000,\t0.073f, 0.00f,0.00f,0.00f,\t-2200,\t0.043f,\t\t0.00f,0.00f,0.00f,\t0.235f, 0.480f, 0.250f, 0.000f, -0.0f,\t12428.5f,\t99.6f,  0.00f,\t0x20 }\n#define EAX30_PRESET_ICEPALACE_SMALLROOM \\\n\t{ 26,   2.7f,\t0.840f, -1000,  -500,\t-1100,  1.51f,\t1.53f,\t0.27f,\t-100,\t0.010f, 0.00f,0.00f,0.00f,\t-900,\t0.011f,\t\t0.00f,0.00f,0.00f,\t0.164f, 0.140f, 0.250f, 0.000f, -0.0f,\t12428.5f,\t99.6f,  0.00f,\t0x20 }\n\n// SPACE STATION PRESETS\n\n//\tEnv\t\tSize\tDiffus\tRoom\tRoomHF\tRoomLF\tDecTm\tDcHF\tDcLF\tRefl\tRefDel\tRef Pan\t\t\t\tRevb\tRevDel\t\tRev Pan\t\t\t\tEchTm\tEchDp\tModTm\tModDp\tAirAbs\tHFRef\t\tLFRef\tRRlOff\tFLAGS\n#define EAX30_PRESET_SPACESTATION_ALCOVE \\\n\t{ 26,   1.5f,\t0.780f, -1100,  -300,   -100,\t1.16f,\t0.81f,\t0.55f,  300,\t0.007f, 0.00f,0.00f,0.00f,\t-500,\t0.018f,\t\t0.00f,0.00f,0.00f,\t0.192f, 0.210f, 0.250f, 0.000f,\t-5.0f,  3316.1f,\t458.2f,  0.00f, 0x20 }\n#define EAX30_PRESET_SPACESTATION_MEDIUMROOM \\\n\t{ 26,   1.5f,\t0.750f, -1000,  -400,   -100,\t3.01f,\t0.50f,\t0.55f,  -1000,\t0.034f, 0.00f,0.00f,0.00f,\t-700,\t0.035f,\t\t0.00f,0.00f,0.00f,\t0.209f, 0.310f, 0.250f, 0.000f,\t-5.0f,  3316.1f,\t458.2f,  0.00f, 0x20 }\n#define EAX30_PRESET_SPACESTATION_SHORTPASSAGE \\\n\t{ 26,   1.5f,\t0.870f, -1000,  -400,   -100,\t3.57f,\t0.50f,\t0.55f,  0,\t\t0.012f, 0.00f,0.00f,0.00f,\t-600,\t0.016f,\t\t0.00f,0.00f,0.00f,\t0.172f, 0.200f, 0.250f, 0.000f, -5.0f,  3316.1f,\t458.2f,  0.00f, 0x20 }\n#define EAX30_PRESET_SPACESTATION_LONGPASSAGE \\\n\t{ 26,   1.9f,\t0.820f, -1000,  -400,   -100,\t4.62f,\t0.62f,\t0.55f,  0,\t\t0.012f, 0.00f,0.00f,0.00f,\t-800,\t0.031f,\t\t0.00f,0.00f,0.00f,\t0.250f, 0.230f, 0.250f, 0.000f, -5.0f,  3316.1f,\t458.2f,  0.00f, 0x20 }\n#define EAX30_PRESET_SPACESTATION_LARGEROOM \\\n\t{ 26,   1.8f,\t0.810f, -1000,  -400,   -100,\t3.89f,\t0.38f,\t0.61f,  -1200,\t0.056f, 0.00f,0.00f,0.00f,\t-800,\t0.035f,\t\t0.00f,0.00f,0.00f,\t0.233f, 0.280f, 0.250f, 0.000f, -5.0f,  3316.1f,\t458.2f,  0.00f, 0x20 }\n#define EAX30_PRESET_SPACESTATION_HALL \\\n\t{ 26,   1.9f,\t0.870f, -1000,  -400,   -100,\t7.11f,\t0.38f,\t0.61f,  -1500,\t0.100f, 0.00f,0.00f,0.00f,\t-1000,\t0.047f,\t\t0.00f,0.00f,0.00f,\t0.250f, 0.250f, 0.250f, 0.000f, -5.0f,  3316.1f,\t458.2f,  0.00f, 0x20 }\n#define EAX30_PRESET_SPACESTATION_CUPBOARD \\\n\t{ 26,   1.4f,\t0.560f, -1000,  -300,   -100,\t0.79f,\t0.81f,\t0.55f,  200,\t0.007f, 0.00f,0.00f,0.00f,\t400,\t0.018f,\t\t0.00f,0.00f,0.00f,\t0.181f, 0.310f, 0.250f, 0.000f, -5.0f,  3316.1f,\t458.2f,  0.00f, 0x20 }\n#define EAX30_PRESET_SPACESTATION_SMALLROOM \\\n\t{ 26,   1.5f,\t0.700f, -1000,  -300,   -100,\t1.72f,\t0.82f,\t0.55f,\t-400,\t0.007f, 0.00f,0.00f,0.00f,\t-500,\t0.013f,\t\t0.00f,0.00f,0.00f,\t0.188f, 0.260f, 0.250f, 0.000f, -5.0f,  3316.1f,\t458.2f,  0.00f, 0x20 }\n\n// WOODEN GALLEON PRESETS\n\n//\tEnv\t\tSize\tDiffus\tRoom\tRoomHF\tRoomLF\tDecTm\tDcHF\tDcLF\tRefl\tRefDel\tRef Pan\t\t\t\tRevb\tRevDel\t\tRev Pan\t\t\t\tEchTm\tEchDp\tModTm\tModDp\tAirAbs\tHFRef\t\tLFRef\tRRlOff\tFLAGS\n#define EAX30_PRESET_WOODEN_ALCOVE \\\n\t{ 26,   7.5f,\t1.000f, -1100,  -1800,  -1000,  1.22f,\t0.62f,\t0.91f,\t-100,\t0.012f, 0.00f,0.00f,0.00f,\t-600,\t0.024f,\t\t0.00f,0.00f,0.00f,\t0.250f, 0.000f, 0.250f, 0.000f, -5.0f,  4705.0f,\t99.6f,  0.00f,\t0x3f }\n#define EAX30_PRESET_WOODEN_SHORTPASSAGE \\\n\t{ 26,   7.5f,\t1.000f, -1100,  -1800,  -1000,  1.45f,\t0.50f,\t0.87f,\t-300,\t0.012f, 0.00f,0.00f,0.00f,\t-700,\t0.024f,\t\t0.00f,0.00f,0.00f,\t0.250f, 0.000f, 0.250f, 0.000f, -5.0f,  4705.0f,\t99.6f,  0.00f,\t0x3f }\n#define EAX30_PRESET_WOODEN_MEDIUMROOM \\\n\t{ 26,   7.5f,\t1.000f, -1200,  -2000,  -1100,  1.07f,\t0.42f,\t0.82f,\t-300,\t0.039f, 0.00f,0.00f,0.00f,\t-400,\t0.029f,\t\t0.00f,0.00f,0.00f,\t0.250f, 0.000f, 0.250f, 0.000f, -5.0f,  4705.0f,\t99.6f,  0.00f,\t0x3f }\n#define EAX30_PRESET_WOODEN_LONGPASSAGE \\\n\t{ 26,   7.5f,\t1.000f, -1100,  -2000,  -1000,  1.79f,\t0.40f,\t0.79f,\t-200,\t0.020f, 0.00f,0.00f,0.00f,\t-1000,\t0.036f,\t\t0.00f,0.00f,0.00f,\t0.250f, 0.000f, 0.250f, 0.000f, -5.0f,  4705.0f,\t99.6f,  0.00f,\t0x3f }\n#define EAX30_PRESET_WOODEN_LARGEROOM \\\n\t{ 26,   7.5f,\t1.000f, -1200,  -2100,  -1100,  1.45f,\t0.33f,\t0.82f,\t-300,\t0.056f, 0.00f,0.00f,0.00f,\t-500,\t0.049f,\t\t0.00f,0.00f,0.00f,\t0.250f, 0.000f, 0.250f, 0.000f, -5.0f,  4705.0f,\t99.6f,  0.00f,\t0x3f }\n#define EAX30_PRESET_WOODEN_HALL \\\n\t{ 26,   7.5f,\t1.000f, -1200,  -2200,  -1100,  1.95f,\t0.30f,\t0.82f,\t-300,\t0.068f, 0.00f,0.00f,0.00f,\t-500,\t0.063f,\t\t0.00f,0.00f,0.00f,\t0.250f, 0.000f, 0.250f, 0.000f, -5.0f,  4705.0f,\t99.6f,  0.00f,\t0x3f }\n#define EAX30_PRESET_WOODEN_CUPBOARD \\\n\t{ 26,   7.5f,\t1.000f, -1000,  -1700,  -1000,  0.56f,\t0.46f,\t0.91f,\t-100,\t0.012f, 0.00f,0.00f,0.00f,\t-100,\t0.028f,\t\t0.00f,0.00f,0.00f,\t0.250f, 0.000f, 0.250f, 0.000f, -5.0f,  4705.0f,\t99.6f,  0.00f,\t0x3f }\n#define EAX30_PRESET_WOODEN_SMALLROOM \\\n\t{ 26,   7.5f,\t1.000f, -1200,  -1900,  -1000,  0.79f,\t0.32f,\t0.87f,\t-200,\t0.032f, 0.00f,0.00f,0.00f,\t-300,\t0.029f,\t\t0.00f,0.00f,0.00f,\t0.250f, 0.000f, 0.250f, 0.000f, -5.0f,  4705.0f,\t99.6f,  0.00f,\t0x3f }\n#define EAX30_PRESET_WOODEN_COURTYARD \\\n\t{ 26,   7.5f,\t0.650f, -1700,  -2200,  -1000,  1.79f,\t0.35f,\t0.79f,\t-700,\t0.063f, 0.00f,0.00f,0.00f,\t-2300,\t0.032f,\t\t0.00f,0.00f,0.00f,\t0.250f, 0.000f, 0.250f, 0.000f, -5.0f,  4705.0f,\t99.6f,  0.00f,\t0x3f }\n\n\n// OTHER SCENARIOS\n\n// SPORTS PRESETS\n\n//\tEnv\t\tSize\tDiffus\tRoom\tRoomHF\tRoomLF\tDecTm\tDcHF\tDcLF\tRefl\tRefDel\tRef Pan\t\t\t\tRevb\tRevDel\t\tRev Pan\t\t\t\tEchTm\tEchDp\tModTm\tModDp\tAirAbs\tHFRef\t\tLFRef\tRRlOff\tFLAGS\n#define EAX30_PRESET_SPORT_EMPTYSTADIUM \\\n\t{ 26,   7.2f,\t1.000f, -1300,  -700,   -200,\t6.26f,\t0.51f,\t1.10f,  -2400,\t0.183f, 0.00f,0.00f,0.00f,\t-1100,\t0.038f,\t\t0.00f,0.00f,0.00f,\t0.250f, 0.000f, 0.250f, 0.000f, -5.0f,  5000.0f,\t250.0f,  0.00f, 0x20 }\n#define EAX30_PRESET_SPORT_SQUASHCOURT \\\n\t{ 26,   7.5f,\t0.750f, -1100,  -1000,  -200,\t2.22f,\t0.91f,\t1.16f,  -700,\t0.007f, 0.00f,0.00f,0.00f,\t-300,\t0.011f,\t\t0.00f,0.00f,0.00f,\t0.126f, 0.190f, 0.250f, 0.000f, -0.0f,  7176.9f,\t211.2f,  0.00f, 0x20 }\n#define EAX30_PRESET_SPORT_SMALLSWIMMINGPOOL \\\n\t{ 26,  36.2f,\t0.700f, -1400,  -200,   -100,\t2.76f,\t1.25f,\t1.14f,  -400,\t0.020f, 0.00f,0.00f,0.00f,\t-300,\t0.030f,\t\t0.00f,0.00f,0.00f,\t0.179f, 0.150f, 0.895f, 0.190f, -5.0f,  5000.0f,\t250.0f,  0.00f, 0x0 }\n#define EAX30_PRESET_SPORT_LARGESWIMMINGPOOL\\\n\t{ 26,  36.2f,\t0.820f, -1200,  -200,   0,\t\t5.49f,\t1.31f,\t1.14f,  -700,\t0.039f, 0.00f,0.00f,0.00f,\t-800,\t0.049f,\t\t0.00f,0.00f,0.00f,\t0.222f, 0.550f, 1.159f, 0.210f, -5.0f,  5000.0f,\t250.0f,  0.00f, 0x0 }\n#define EAX30_PRESET_SPORT_GYMNASIUM \\\n\t{ 26,   7.5f,\t0.810f, -1200,  -700,   -100,\t3.14f,\t1.06f,\t1.35f,  -800,\t0.029f, 0.00f,0.00f,0.00f,\t-700,\t0.045f,\t\t0.00f,0.00f,0.00f,\t0.146f, 0.140f, 0.250f, 0.000f, -0.0f,  7176.9f,\t211.2f,  0.00f, 0x20 }\n#define EAX30_PRESET_SPORT_FULLSTADIUM \\\n\t{ 26,   7.2f,\t1.000f, -1300,  -2300,  -200,\t5.25f,\t0.17f,\t0.80f,  -2000,\t0.188f, 0.00f,0.00f,0.00f,\t-1300,\t0.038f,\t\t0.00f,0.00f,0.00f,\t0.250f, 0.000f, 0.250f, 0.000f, -5.0f,  5000.0f,\t250.0f,  0.00f, 0x20 }\n#define EAX30_PRESET_SPORT_STADIUMTANNOY \\\n\t{ 26,   3.0f,\t0.780f, -900,   -500,   -600,\t2.53f,\t0.88f,\t0.68f,  -1100,\t0.230f, 0.00f,0.00f,0.00f,\t-600,\t0.063f,\t\t0.00f,0.00f,0.00f,\t0.250f, 0.200f, 0.250f, 0.000f, -0.0f,  5000.0f,\t250.0f,  0.00f, 0x20 }\n\n// PREFAB PRESETS\n\n//\tEnv\t\tSize\tDiffus\tRoom\tRoomHF\tRoomLF\tDecTm\tDcHF\tDcLF\tRefl\tRefDel\tRef Pan\t\t\t\tRevb\tRevDel\t\tRev Pan\t\t\t\tEchTm\tEchDp\tModTm\tModDp\tAirAbs\tHFRef\t\tLFRef\tRRlOff\tFLAGS\n#define EAX30_PRESET_PREFAB_WORKSHOP \\\n\t{ 26,   1.9f,\t1.000f, -1000,  -1700,  -800,\t0.76f,\t1.00f,\t1.00f,\t0,\t\t0.012f, 0.00f,0.00f,0.00f,\t-200,\t0.012f,\t\t0.00f,0.00f,0.00f,\t0.250f, 0.000f, 0.250f, 0.000f, -5.0f,  5000.0f,\t250.0f,  0.00f, 0x0 }\n#define EAX30_PRESET_PREFAB_SCHOOLROOM \\\n\t{ 26,   1.86f,\t0.690f, -1100,  -400,   -600,\t0.98f,\t0.45f,\t0.18f,  300,\t0.017f, 0.00f,0.00f,0.00f,  0,\t\t0.015f,\t\t0.00f,0.00f,0.00f,\t0.095f, 0.140f, 0.250f, 0.000f, -0.0f,  7176.9f,\t211.2f,  0.00f, 0x20 }\n#define EAX30_PRESET_PREFAB_PRACTISEROOM \\\n\t{ 26,   1.86f,\t0.870f, -1000,  -800,   -600,\t1.12f,\t0.56f,\t0.18f,  200,\t0.010f, 0.00f,0.00f,0.00f,\t-200,\t0.011f,\t\t0.00f,0.00f,0.00f,\t0.095f, 0.140f, 0.250f, 0.000f, -0.0f,  7176.9f,\t211.2f,  0.00f, 0x20 }\n#define EAX30_PRESET_PREFAB_OUTHOUSE \\\n\t{ 26,  80.3f,\t0.820f, -1100,  -1900,  -1600,  1.38f,\t0.38f,\t0.35f,\t-100,\t0.024f, 0.00f,0.00f,-0.00f,\t-800,\t0.044f,\t\t0.00f,0.00f,0.00f,\t0.121f, 0.170f, 0.250f, 0.000f, -0.0f,  2854.4f,\t107.5f,  0.00f, 0x0 }\n#define EAX30_PRESET_PREFAB_CARAVAN \\\n\t{ 26,   8.3f,\t1.000f, -1000,  -2100,  -1800,  0.43f,\t1.50f,\t1.00f,  0,\t\t0.012f, 0.00f,0.00f,0.00f,\t400,\t0.012f,\t\t0.00f,0.00f,0.00f,\t0.250f, 0.000f, 0.250f, 0.000f, -5.0f,  5000.0f,\t250.0f,  0.00f, 0x1f }\n\t\t\t// for US developers, a caravan is the same as a trailer =o)\n\n\n// DOME AND PIPE PRESETS\n\n//\tEnv\t\tSize\tDiffus\tRoom\tRoomHF\tRoomLF\tDecTm\tDcHF\tDcLF\tRefl\tRefDel\tRef Pan\t\t\t\tRevb\tRevDel\t\tRev Pan\t\t\t\tEchTm\tEchDp\tModTm\tModDp\tAirAbs\tHFRef\t\tLFRef\tRRlOff\tFLAGS\n#define EAX30_PRESET_DOME_TOMB \\\n\t{ 26,  51.8f,\t0.790f, -1000,  -900,\t-1300,  4.18f,\t0.21f,\t0.10f,  -825,\t0.030f, 0.00f,0.00f,0.00f,\t-125,\t0.022f,\t\t0.00f,0.00f,0.00f,\t0.177f, 0.190f, 0.250f, 0.000f,\t-5.0f,  2854.4f,\t20.0f,  0.00f,\t0x0 }\n#define EAX30_PRESET_PIPE_SMALL \\\n\t{ 26,  50.3f,\t1.000f, -1000,  -900,\t-1300,  5.04f,\t0.10f,\t0.10f,  -600,\t0.032f, 0.00f,0.00f,0.00f,\t400,\t0.015f,\t\t0.00f,0.00f,0.00f,\t0.250f, 0.000f, 0.250f, 0.000f, -5.0f,  2854.4f,\t20.0f,  0.00f,\t0x3f }\n#define EAX30_PRESET_DOME_SAINTPAULS \\\n\t{ 26,  50.3f,\t0.870f, -1000,  -900,\t-1300,  10.48f,\t0.19f,\t0.10f,  -1500,\t0.090f, 0.00f,0.00f,0.00f,\t-500,\t0.042f,\t\t0.00f,0.00f,0.00f,\t0.250f, 0.120f, 0.250f, 0.000f, -5.0f,  2854.4f,\t20.0f,  0.00f,\t0x3f }\n#define EAX30_PRESET_PIPE_LONGTHIN \\\n\t{ 26,   1.6f,\t0.910f, -1200,  -700,\t-1100,  9.21f,\t0.18f,\t0.10f,  -300,\t0.010f, 0.00f,0.00f,0.00f,\t-1000,\t0.022f,\t\t0.00f,0.00f,0.00f,\t0.250f, 0.000f, 0.250f, 0.000f, -5.0f,  2854.4f,\t20.0f,  0.00f,\t0x0 }\n#define EAX30_PRESET_PIPE_LARGE \\\n\t{ 26,  50.3f,\t1.000f, -1000,  -900,\t-1300,  8.45f,\t0.10f,\t0.10f,  -800,\t0.046f, 0.00f,0.00f,0.00f,  0,\t\t0.032f,\t\t0.00f,0.00f,0.00f,\t0.250f, 0.000f, 0.250f, 0.000f, -5.0f,  2854.4f,\t20.0f,  0.00f,\t0x3f }\n#define EAX30_PRESET_PIPE_RESONANT \\\n\t{ 26,   1.3f,\t0.910f, -1200,  -700,\t-1100,  6.81f,\t0.18f,\t0.10f,  -300,\t0.010f, 0.00f,0.00f,0.00f,\t-700,\t0.022f,\t\t0.00f,0.00f,0.00f,\t0.250f, 0.000f, 0.250f, 0.000f, -5.0f,  2854.4f,\t20.0f,  0.00f,\t0x0 }\n\n// OUTDOORS PRESETS\n\n//\tEnv\t\tSize\tDiffus\tRoom\tRoomHF\tRoomLF\tDecTm\tDcHF\tDcLF\tRefl\tRefDel\tRef Pan\t\t\t\tRevb\tRevDel\t\tRev Pan\t\t\t\tEchTm\tEchDp\tModTm\tModDp\tAirAbs\tHFRef\t\tLFRef\tRRlOff\tFLAGS\n#define EAX30_PRESET_OUTDOORS_BACKYARD \\\n\t{ 26,  80.3f,\t0.450f,\t-1100,  -1200,  -600,\t1.12f,\t0.34f,\t0.46f,  -1100,\t0.049f, 0.00f,0.00f,-0.00f,\t-1300,\t0.023f,\t\t0.00f,0.00f,0.00f,\t0.218f, 0.340f, 0.250f, 0.000f,\t-5.0f,  4399.1f,\t242.9f,  0.00f, 0x0 }\n#define EAX30_PRESET_OUTDOORS_ROLLINGPLAINS \\\n\t{ 26,  80.3f,\t0.000f,\t-1100,  -3900,  -400,\t2.13f,\t0.21f,\t0.46f,  -2000,\t0.300f, 0.00f,0.00f,-0.00f,\t-1500,\t0.019f,\t\t0.00f,0.00f,0.00f,\t0.250f, 1.000f, 0.250f, 0.000f, -5.0f,  4399.1f,\t242.9f,  0.00f, 0x0 }\n#define EAX30_PRESET_OUTDOORS_DEEPCANYON \\\n\t{ 26,  80.3f,\t0.740f,\t-1100,  -1500,  -400,\t3.89f,\t0.21f,\t0.46f,  -2000,\t0.193f, 0.00f,0.00f,-0.00f,\t-1100,\t0.019f,\t\t0.00f,0.00f,0.00f,\t0.250f, 1.000f, 0.250f, 0.000f, -5.0f,  4399.1f,\t242.9f,  0.00f, 0x0 }\n#define EAX30_PRESET_OUTDOORS_CREEK \\\n\t{ 26,  80.3f,\t0.350f,\t-1100,  -1500,  -600,\t2.13f,\t0.21f,\t0.46f,  -1700,\t0.115f, 0.00f,0.00f,-0.00f,\t-1100,\t0.031f,\t\t0.00f,0.00f,0.00f,\t0.218f, 0.340f, 0.250f, 0.000f, -5.0f,  4399.1f,\t242.9f,  0.00f, 0x0 }\n#define EAX30_PRESET_OUTDOORS_VALLEY \\\n\t{ 26,  80.3f,\t0.280f,\t-1100,  -3100,\t-1600,  2.88f,\t0.26f,\t0.35f,  -3200,\t0.163f, 0.00f,0.00f,-0.00f,\t-1000,\t0.100f,\t\t0.00f,0.00f,0.00f,\t0.250f, 0.340f, 0.250f, 0.000f, -0.0f,  2854.4f,\t107.5f,  0.00f, 0x0 }\n\n\n// MOOD PRESETS\n\n//\tEnv\t\tSize\tDiffus\tRoom\tRoomHF\tRoomLF\tDecTm\tDcHF\tDcLF\tRefl\tRefDel\tRef Pan\t\t\t\tRevb\tRevDel\t\tRev Pan\t\t\t\tEchTm\tEchDp\tModTm\tModDp\tAirAbs\tHFRef\t\tLFRef\tRRlOff\tFLAGS\n#define EAX30_PRESET_MOOD_HEAVEN \\\n\t{ 26,  19.6f,\t0.940f,  -1000, -200,   -700,\t5.04f,\t1.12f,\t0.56f,  -1230,\t0.020f, 0.00f,0.00f,0.00f,\t-200,\t0.029f,\t\t0.00f,0.00f,0.00f,\t0.250f, 0.080f, 2.742f, 0.050f, -2.0f,  5000.0f,\t250.0f,  0.00f, 0x3f }\n#define EAX30_PRESET_MOOD_HELL \\\n\t{ 26, 100.0f,\t0.570f,  -1000, -900,   -700,\t3.57f,\t0.49f,\t2.00f,\t-10000, 0.020f, 0.00f,0.00f,0.00f,\t100,\t0.030f,\t\t0.00f,0.00f,0.00f,\t0.110f, 0.040f, 2.109f, 0.520f, -5.0f,  5000.0f,\t139.5f,  0.00f, 0x40 }\n#define EAX30_PRESET_MOOD_MEMORY \\\n\t{ 26,   8.0f,\t0.850f,  -1000, -400,   -900,\t4.06f,\t0.82f,\t0.56f,  -2800,\t0.000f, 0.00f,0.00f,0.00f,\t-500,\t0.000f,\t\t0.00f,0.00f,0.00f,\t0.250f, 0.000f, 0.474f, 0.450f, -2.0f,  5000.0f,\t250.0f,  0.00f, 0x0 }\n\n// DRIVING SIMULATION PRESETS\n\n//\tEnv\t\tSize\tDiffus\tRoom\tRoomHF\tRoomLF\tDecTm\tDcHF\tDcLF\tRefl\tRefDel\tRef Pan\t\t\t\tRevb\tRevDel\t\tRev Pan\t\t\t\tEchTm\tEchDp\tModTm\tModDp\tAirAbs\tHFRef\t\tLFRef\tRRlOff\tFLAGS\n#define EAX30_PRESET_DRIVING_COMMENTATOR \\\n\t{ 26,   3.0f,\t0.000f, -900,   -500,   -600,\t2.42f,\t0.88f,\t0.68f,  -1400,\t0.093f, 0.00f,0.00f,0.00f,\t-1200,\t0.017f,\t\t0.00f,0.00f,0.00f,\t0.250f, 1.000f, 0.250f, 0.000f, -0.0f,  5000.0f,\t250.0f,  0.00f, 0x20 }\n#define EAX30_PRESET_DRIVING_PITGARAGE \\\n\t{ 26,   1.9f,\t0.590f, -1400,  -300,   -500,\t1.72f,\t0.93f,\t0.87f,  -500,\t0.000f, 0.00f,0.00f,0.00f,\t0,\t\t0.016f,\t\t0.00f,0.00f,0.00f,\t0.250f, 0.110f, 0.250f, 0.000f, -5.0f,  5000.0f,\t250.0f,  0.00f, 0x0 }\n#define EAX30_PRESET_DRIVING_INCAR_RACER \\\n\t{ 26,   1.1f,\t0.800f, -700,   0,\t\t-200,\t0.17f,\t2.00f,\t0.41f,  500,\t0.007f, 0.00f,0.00f,0.00f,\t-500,\t0.015f,\t\t0.00f,0.00f,0.00f,\t0.250f, 0.000f, 0.250f, 0.000f, -0.0f,\t10268.2f,\t251.0f,  0.00f, 0x20 }\n#define EAX30_PRESET_DRIVING_INCAR_SPORTS \\\n\t{ 26,   1.1f,\t0.800f, -900,\t-400,   0,\t\t0.17f,\t0.75f,\t0.41f,  0,\t\t0.010f, 0.00f,0.00f,0.00f,\t-600,\t0.000f,\t\t0.00f,0.00f,0.00f,\t0.250f, 0.000f, 0.250f, 0.000f, -0.0f,\t10268.2f,\t251.0f,  0.00f, 0x20 }\n#define EAX30_PRESET_DRIVING_INCAR_LUXURY \\\n\t{ 26,   1.6f,\t1.000f, -800,\t-2000,  -600,\t0.13f,\t0.41f,\t0.46f,  -200,\t0.010f, 0.00f,0.00f,0.00f,\t300,\t0.010f,\t\t0.00f,0.00f,0.00f,\t0.250f, 0.000f, 0.250f, 0.000f, -0.0f,\t10268.2f,\t251.0f,  0.00f, 0x20 }\n#define EAX30_PRESET_DRIVING_FULLGRANDSTAND \\\n\t{ 26,   8.3f,\t1.000f, -1100,  -1100,  -400,\t3.01f,\t1.37f,\t1.28f,  -900,\t0.090f, 0.00f,0.00f,0.00f,\t-1700,\t0.049f,\t\t0.00f,0.00f,0.00f,\t0.250f, 0.000f, 0.250f, 0.000f, -5.0f,\t10420.2f,\t250.0f,  0.00f, 0x1f }\n#define EAX30_PRESET_DRIVING_EMPTYGRANDSTAND \\\n\t{ 26,   8.3f,\t1.000f, -700,   0,\t\t-200,\t4.62f,\t1.75f,\t1.40f,  -1363,\t0.090f, 0.00f,0.00f,0.00f,\t-1900,\t0.049f,\t\t0.00f,0.00f,0.00f,\t0.250f, 0.000f, 0.250f, 0.000f, -5.0f,\t10420.2f,\t250.0f,  0.00f, 0x1f }\n#define EAX30_PRESET_DRIVING_TUNNEL \\\n\t{ 26,   3.1f,\t0.810f, -900,   -800,\t-100,\t3.42f,\t0.94f,\t1.31f,  -300,\t0.051f, 0.00f,0.00f,0.00f,  -500,\t0.047f,\t\t0.00f,0.00f,0.00f,\t0.214f, 0.050f, 0.250f, 0.000f, -0.0f,  5000.0f,\t155.3f,  0.00f, 0x20 }\n\n// CITY PRESETS\n\n//\tEnv\t\tSize\tDiffus\tRoom\tRoomHF\tRoomLF\tDecTm\tDcHF\tDcLF\tRefl\tRefDel\tRef Pan\t\t\t\tRevb\tRevDel\t\tRev Pan\t\t\t\tEchTm\tEchDp\tModTm\tModDp\tAirAbs\tHFRef\t\tLFRef\tRRlOff\tFLAGS\n#define EAX30_PRESET_CITY_STREETS \\\n\t{ 26,   3.0f,\t0.780f, -1100,  -300,   -100,\t1.79f,\t1.12f,\t0.91f,  -1700,\t0.046f, 0.00f,0.00f,0.00f,\t-2800,\t0.028f,\t\t0.00f,0.00f,0.00f,\t0.250f, 0.200f, 0.250f, 0.000f, -0.0f,  5000.0f,\t250.0f,  0.00f, 0x20 }\n#define EAX30_PRESET_CITY_SUBWAY \\\n\t{ 26,   3.0f,\t0.740f, -1100,  -300,   -100,\t3.01f,\t1.23f,\t0.91f,   -700,\t0.046f, 0.00f,0.00f,0.00f,\t-1000,\t0.028f,\t\t0.00f,0.00f,0.00f,\t0.125f, 0.210f, 0.250f, 0.000f, -0.0f,  5000.0f,\t250.0f,  0.00f, 0x20 }\n#define EAX30_PRESET_CITY_MUSEUM \\\n\t{ 26,  80.3f,\t0.820f, -1100,  -1500,  -1500,  3.28f,\t1.40f,\t0.57f,  -1600,\t0.039f, 0.00f,0.00f,-0.00f, -600,\t0.034f,\t\t0.00f,0.00f,0.00f,\t0.130f, 0.170f, 0.250f, 0.000f, -0.0f,  2854.4f,\t107.5f,  0.00f, 0x0 }\n#define EAX30_PRESET_CITY_LIBRARY \\\n\t{ 26,  80.3f,\t0.820f, -1100,  -1100,  -2100,  2.76f,\t0.89f,\t0.41f,  -1100,\t0.029f, 0.00f,0.00f,-0.00f, -500,\t0.020f,\t\t0.00f,0.00f,0.00f,\t0.130f, 0.170f, 0.250f, 0.000f, -0.0f,  2854.4f,\t107.5f,  0.00f, 0x0 }\n#define EAX30_PRESET_CITY_UNDERPASS \\\n\t{ 26,   3.0f,\t0.820f, -1500,  -700,   -100,\t3.57f,\t1.12f,\t0.91f,  -1500,\t0.059f, 0.00f,0.00f,0.00f,\t-1100,\t0.037f,\t\t0.00f,0.00f,0.00f,\t0.250f, 0.140f, 0.250f, 0.000f, -0.0f,  5000.0f,\t250.0f,  0.00f, 0x20 }\n#define EAX30_PRESET_CITY_ABANDONED \\\n\t{ 26,   3.0f,\t0.690f, -1100,  -200,   -100,\t3.28f,\t1.17f,\t0.91f,  -1400,\t0.044f, 0.00f,0.00f,0.00f,\t-2400,\t0.024f,\t\t0.00f,0.00f,0.00f,\t0.250f, 0.200f, 0.250f, 0.000f, -0.0f,  5000.0f,\t250.0f,  0.00f, 0x20 }\n\n// MISC ROOMS\n\n//\tEnv\t\tSize\tDiffus\tRoom\tRoomHF\tRoomLF\tDecTm\tDcHF\tDcLF\tRefl\tRefDel\tRef Pan\t\t\t\tRevb\tRevDel\t\tRev Pan\t\t\t\tEchTm\tEchDp\tModTm\tModDp\tAirAbs\tHFRef\t\tLFRef\tRRlOff\tFLAGS\n#define EAX30_PRESET_DUSTYROOM  \\\n\t{ 26,   1.8f,\t0.560f,\t-1100,\t-200,\t-300,\t1.79f,\t0.38f,\t0.21f,\t-600,\t0.002f,\t0.00f,0.00f,0.00f,\t200,\t0.006f,\t\t0.00f,0.00f,0.00f,\t0.202f, 0.050f, 0.250f, 0.000f, -3.0f,  13046.0f,\t163.3f,\t0.00f,\t0x20 }\n#define EAX30_PRESET_CHAPEL \\\n\t{ 26,  19.6f,\t0.840f,\t-1000,  -500,\t0,\t\t4.62f,\t0.64f,\t1.23f,  -700,\t0.032f,\t0.00f,0.00f,0.00f,\t-800,\t0.049f,\t\t0.00f,0.00f,0.00f,\t0.250f, 0.000f, 0.250f, 0.110f, -5.0f,  5000.0f,\t250.0f, 0.00f,\t0x3f }\n#define EAX30_PRESET_SMALLWATERROOM \\\n\t{ 26,  36.2f,\t0.700f, -1200,  -698,   0,\t\t1.51f,\t1.25f,\t1.14f,  -100,\t0.020f, 0.00f,0.00f,0.00f,\t200,\t0.030f,\t\t0.00f,0.00f,0.00f,\t0.179f, 0.150f, 0.895f, 0.190f, -5.0f,  5000.0f,\t250.0f, 0.00f, 0x0 }\n\n/********************************************************************************************************/\n\n//////////////////////////////////////////////////////\n// Effect Scenarios enumerated\t\t\t\t\t\t//\n//////////////////////////////////////////////////////\n\ntypedef enum\n{\n\tEAX30_SCENARIO_CASTLE = 0,\n\tEAX30_SCENARIO_FACTORY,\n\tEAX30_SCENARIO_ICEPALACE,\n\tEAX30_SCENARIO_SPACESTATION,\n\tEAX30_SCENARIO_WOODGALLEON,\n\tEAX30_SCENARIO_SPORTS,\n\tEAX30_SCENARIO_PREFAB,\n\tEAX30_SCENARIO_DOMESNPIPES,\n\tEAX30_SCENARIO_OUTDOORS,\n\tEAX30_SCENARIO_MOOD,\n\tEAX30_SCENARIO_DRIVING,\n\tEAX30_SCENARIO_CITY,\n\tEAX30_SCENARIO_MISC,\n\tEAX30_SCENARIO_ORIGINAL\n}\nEAX30_SCENARIO;\n\n//////////////////////////////////////////////////////\n// Number of Effect Scenarios\t\t\t\t\t\t//\n//////////////////////////////////////////////////////\n\n#define EAX30_NUM_SCENARIOS\t\t\t\t\t14\n\n//////////////////////////////////////////////////////\n// Number of Effect Scenarios with standardised\t\t//\n// locations\t\t\t\t\t\t\t\t\t\t//\n//////////////////////////////////////////////////////\n\n#define EAX30_NUM_STANDARD_SCENARIOS\t\t5\n\n//////////////////////////////////////////////////////\n// Array of scenario names\t\t\t\t\t\t\t//\n//////////////////////////////////////////////////////\n\nextern const char* EAX30_SCENARIO_NAMES[];\n\n//////////////////////////////////////////////////////\n// Standardised Locations enumerated\t\t\t\t//\n//////////////////////////////////////////////////////\n\ntypedef enum \n{\n\tEAX30_LOCATION_HALL = 0,\n\tEAX30_LOCATION_LARGEROOM,\n\tEAX30_LOCATION_MEDIUMROOM,\n\tEAX30_LOCATION_SMALLROOM,\n\tEAX30_LOCATION_CUPBOARD,\n\tEAX30_LOCATION_ALCOVE,\n\tEAX30_LOCATION_LONGPASSAGE,\n\tEAX30_LOCATION_SHORTPASSAGE,\n\tEAX30_LOCATION_COURTYARD\n}\nEAX30_LOCATION;\n\n//////////////////////////////////////////////////////\n// Number of Standardised Locations\t\t\t\t\t//\n//////////////////////////////////////////////////////\n\n#define EAX30_NUM_LOCATIONS\t\t\t\t\t\t9\n\n//////////////////////////////////////////////////////\n// Array of standardised location names\t\t\t\t//\n//////////////////////////////////////////////////////\n\nextern const char* EAX30_LOCATION_NAMES[];\n\n//////////////////////////////////////////////////////\n// Number of effects in each scenario\t\t\t\t//\n//////////////////////////////////////////////////////\n\n#define EAX30_NUM_ORIGINAL_PRESETS\t\t26\n#define EAX30_NUM_CASTLE_PRESETS\t\tEAX30_NUM_LOCATIONS\n#define EAX30_NUM_FACTORY_PRESETS\t\tEAX30_NUM_LOCATIONS\n#define EAX30_NUM_ICEPALACE_PRESETS\t\tEAX30_NUM_LOCATIONS\n#define EAX30_NUM_SPACESTATION_PRESETS\tEAX30_NUM_LOCATIONS\n#define EAX30_NUM_WOODGALLEON_PRESETS\tEAX30_NUM_LOCATIONS\n#define EAX30_NUM_SPORTS_PRESETS\t\t7\n#define EAX30_NUM_PREFAB_PRESETS\t\t5\n#define EAX30_NUM_DOMESNPIPES_PRESETS\t6\n#define EAX30_NUM_OUTDOORS_PRESETS\t\t5\n#define EAX30_NUM_MOOD_PRESETS\t\t\t3\n#define EAX30_NUM_DRIVING_PRESETS\t\t8\n#define EAX30_NUM_CITY_PRESETS\t\t\t6\n#define EAX30_NUM_MISC_PRESETS\t\t\t3\n\n//////////////////////////////////////////////////////\n// Standardised Location effects can be accessed\t//\n// from a matrix\t\t\t\t\t\t\t\t\t//\n//////////////////////////////////////////////////////\n\nextern EAXLISTENERPROPERTIES EAX30_STANDARD_PRESETS[EAX30_NUM_STANDARD_SCENARIOS][EAX30_NUM_LOCATIONS];\n\n/********************************************************************************************************/\n\n//////////////////////////////////////////////////////\n// Original Preset effects enumerated\t\t\t\t//\n//////////////////////////////////////////////////////\n\ntypedef enum\n{\n\tORIGINAL_GENERIC = 0,\n\tORIGINAL_PADDEDCELL,\n\tORIGINAL_ROOM,\n\tORIGINAL_BATHROOM,\n\tORIGINAL_LIVINGROOM,\n\tORIGINAL_STONEROOM,\n\tORIGINAL_AUDITORIUM,\n\tORIGINAL_CONCERTHALL,\n\tORIGINAL_CAVE,\n\tORIGINAL_ARENA,\n\tORIGINAL_HANGAR,\n\tORIGINAL_CARPETTEDHALLWAY,\n\tORIGINAL_HALLWAY,\n\tORIGINAL_STONECORRIDOR,\n\tORIGINAL_ALLEY,\n\tORIGINAL_FOREST,\n\tORIGINAL_CITY,\n\tORIGINAL_MOUNTAINS,\n\tORIGINAL_QUARRY,\n\tORIGINAL_PLAIN,\n\tORIGINAL_PARKINGLOT,\n\tORIGINAL_SEWERPIPE,\n\tORIGINAL_UNDERWATER,\n\tORIGINAL_DRUGGED,\n\tORIGINAL_DIZZY,\n\tORIGINAL_PSYCHOTIC\n}\nEAX30_ORIGINAL_PRESET_ENUMS;\n\n//////////////////////////////////////////////////////\n// Array of original environment names\t\t\t\t//\n//////////////////////////////////////////////////////\n\nextern const char* EAX30_ORIGINAL_PRESET_NAMES[];\n\n//////////////////////////////////////////////////////\n// Original effects matrix\t\t\t\t\t\t\t//\n//////////////////////////////////////////////////////\n\nextern EAXLISTENERPROPERTIES EAX30_ORIGINAL_PRESETS[];\n\n/********************************************************************************************************/\n\n//////////////////////////////////////////////////////\n// Sports scenario effects enumerated\t\t\t\t//\n//////////////////////////////////////////////////////\n\ntypedef enum\n{\n\tSPORT_EMPTYSTADIUM=0,\n\tSPORT_FULLSTADIUM,\n\tSPORT_STADIUMTANNOY,\n\tSPORT_SQUASHCOURT,\n\tSPORT_SMALLSWIMMINGPOOL,\n\tSPORT_LARGESWIMMINGPOOL,\n\tSPORT_GYMNASIUM\n}\nEAX30_SPORTS_PRESET_ENUMS;\n\n//////////////////////////////////////////////////////\n// Array of sport environment names\t\t\t\t\t//\n//////////////////////////////////////////////////////\n\nextern const char* EAX30_SPORTS_PRESET_NAMES[];\n\n//////////////////////////////////////////////////////\n// Sports effects matrix\t\t\t\t\t\t\t//\n//////////////////////////////////////////////////////\n\nextern EAXLISTENERPROPERTIES EAX30_SPORTS_PRESETS[];\n\n/********************************************************************************************************/\n\n//////////////////////////////////////////////////////\n// Prefab scenario effects enumerated\t\t\t\t//\n//////////////////////////////////////////////////////\n\ntypedef enum\n{\n\tPREFAB_WORKSHOP,\n\tPREFAB_SCHOOLROOM,\n\tPREFAB_PRACTISEROOM,\n\tPREFAB_OUTHOUSE,\n\tPREFAB_CARAVAN\n}\nEAX30_PREFAB_PRESET_ENUMS;\n\n//////////////////////////////////////////////////////\n// Array of prefab environment names\t\t\t\t//\n//////////////////////////////////////////////////////\n\nextern const char* EAX30_PREFAB_PRESET_NAMES[];\n\n//////////////////////////////////////////////////////\n// Prefab effects matrix\t\t\t\t\t\t\t//\n//////////////////////////////////////////////////////\n\nextern EAXLISTENERPROPERTIES EAX30_PREFAB_PRESETS[];\n\n/********************************************************************************************************/\n\n//////////////////////////////////////////////////////\n// Domes & Pipes effects enumerated\t\t\t\t\t//\n//////////////////////////////////////////////////////\n\ntypedef enum\n{\n\tDOME_TOMB,\n\tDOME_SAINTPAULS,\n\tPIPE_SMALL,\n\tPIPE_LONGTHIN,\n\tPIPE_LARGE,\n\tPIPE_RESONANT\n}\nEAX30_DOMESNPIPES_PRESET_ENUMS;\n\n//////////////////////////////////////////////////////\n// Array of Domes & Pipes environment names\t\t\t//\n//////////////////////////////////////////////////////\n\nextern const char* EAX30_DOMESNPIPES_PRESET_NAMES[];\n\n//////////////////////////////////////////////////////\n// Domes & Pipes effects matrix\t\t\t\t\t\t//\n//////////////////////////////////////////////////////\n\nextern EAXLISTENERPROPERTIES EAX30_DOMESNPIPES_PRESETS[];\n\n/********************************************************************************************************/\n\n//////////////////////////////////////////////////////\n// Outdoors scenario effects enumerated\t\t\t\t//\n//////////////////////////////////////////////////////\n\ntypedef enum\n{\n\tOUTDOORS_BACKYARD,\n\tOUTDOORS_ROLLINGPLAINS,\n\tOUTDOORS_DEEPCANYON,\n\tOUTDOORS_CREEK,\n\tOUTDOORS_VALLEY\n}\nEAX30_OUTDOORS_PRESET_ENUMS;\n\n//////////////////////////////////////////////////////\n// Array of Outdoors environment names\t\t\t\t//\n//////////////////////////////////////////////////////\n\nextern const char* EAX30_OUTDOORS_PRESET_NAMES[];\n\n//////////////////////////////////////////////////////\n// Outdoors effects matrix\t\t\t\t\t\t\t//\n//////////////////////////////////////////////////////\n\nextern EAXLISTENERPROPERTIES EAX30_OUTDOORS_PRESETS[];\n\n/********************************************************************************************************/\n\n//////////////////////////////////////////////////////\n// Mood scenario effects enumerated\t\t\t\t\t//\n//////////////////////////////////////////////////////\n\ntypedef enum\n{\n\tMOOD_HEAVEN,\n\tMOOD_HELL,\n\tMOOD_MEMORY\n}\nEAX30_MOOD_PRESET_ENUMS;\n\n//////////////////////////////////////////////////////\n// Array of Mood environment names\t\t\t\t\t//\n//////////////////////////////////////////////////////\n\nextern const char* EAX30_MOOD_PRESET_NAMES[];\n\n//////////////////////////////////////////////////////\n// Mood effects matrix\t\t\t\t\t\t\t\t//\n//////////////////////////////////////////////////////\n\nextern EAXLISTENERPROPERTIES EAX30_MOOD_PRESETS[];\n\n/********************************************************************************************************/\n\n//////////////////////////////////////////////////////\n// Driving scenario effects enumerated\t\t\t\t//\n//////////////////////////////////////////////////////\n\ntypedef enum\n{\n\tDRIVING_COMMENTATOR,\n\tDRIVING_PITGARAGE,\n\tDRIVING_INCAR_RACER,\n\tDRIVING_INCAR_SPORTS,\n\tDRIVING_INCAR_LUXURY,\n\tDRIVING_FULLGRANDSTAND,\n\tDRIVING_EMPTYGRANDSTAND,\n\tDRIVING_TUNNEL\n}\nEAX30_DRIVING_PRESET_ENUMS;\n\n//////////////////////////////////////////////////////\n// Array of driving environment names\t\t\t\t//\n//////////////////////////////////////////////////////\n\nextern const char* EAX30_DRIVING_PRESET_NAMES[];\n\n//////////////////////////////////////////////////////\n// Driving effects matrix\t\t\t\t\t\t\t//\n//////////////////////////////////////////////////////\n\nextern EAXLISTENERPROPERTIES EAX30_DRIVING_PRESETS[];\n\n/********************************************************************************************************/\n\n//////////////////////////////////////////////////////\n// City scenario effects enumerated\t\t\t\t\t//\n//////////////////////////////////////////////////////\n\ntypedef enum\n{\n\tCITY_STREETS,\n\tCITY_SUBWAY,\n\tCITY_MUSEUM,\n\tCITY_LIBRARY,\n\tCITY_UNDERPASS,\n\tCITY_ABANDONED\n}\nEAX30_CITY_PRESET_ENUMS;\n\n//////////////////////////////////////////////////////\n// Array of City environment names\t\t\t\t\t//\n//////////////////////////////////////////////////////\n\nextern const char* EAX30_CITY_PRESET_NAMES[];\n\n//////////////////////////////////////////////////////\n// City effects matrix\t\t\t\t\t\t\t\t//\n//////////////////////////////////////////////////////\n\nextern EAXLISTENERPROPERTIES EAX30_CITY_PRESETS[];\n\n/********************************************************************************************************/\n\n//////////////////////////////////////////////////////\n// Misc scenario effects enumerated\t\t\t\t\t//\n//////////////////////////////////////////////////////\n\ntypedef enum\n{\n\tDUSTYROOM,\n\tCHAPEL,\n\tSMALLWATERROOM\n}\nEAX30_MISC_PRESET_ENUMS;\n\n\n//////////////////////////////////////////////////////\n// Array of Misc environment names\t\t\t\t\t//\n//////////////////////////////////////////////////////\n\nextern const char* EAX30_MISC_PRESET_NAMES[];\n\n//////////////////////////////////////////////////////\n// Misc effects matrix\t\t\t\t\t\t\t\t//\n//////////////////////////////////////////////////////\n\nextern EAXLISTENERPROPERTIES EAX30_MISC_PRESETS[];\n\n\n/***********************************************************************************************\\\n*\n* Material transmission presets\n*\n* Three values in this order :-\n*\n*\t1. Occlusion (or Obstruction)\n*\t2. Occlusion LF Ratio (or Obstruction LF Ratio)\n*\t3. Occlusion Room Ratio\n*\n************************************************************************************************/\n\n\n// Single window material preset\n#define EAX_MATERIAL_SINGLEWINDOW          (-2800)\n#define EAX_MATERIAL_SINGLEWINDOWLF        0.71f\n#define EAX_MATERIAL_SINGLEWINDOWROOMRATIO 0.43f\n\n// Double window material preset\n#define EAX_MATERIAL_DOUBLEWINDOW          (-5000)\n#define EAX_MATERIAL_DOUBLEWINDOWLF        0.40f\n#define EAX_MATERIAL_DOUBLEWINDOWROOMRATIO 0.24f\n\n// Thin door material preset\n#define EAX_MATERIAL_THINDOOR              (-1800)\n#define EAX_MATERIAL_THINDOORLF            0.66f\n#define EAX_MATERIAL_THINDOORROOMRATIO     0.66f\n\n// Thick door material preset\n#define EAX_MATERIAL_THICKDOOR             (-4400)\n#define EAX_MATERIAL_THICKDOORLF           0.64f\n#define EAX_MATERIAL_THICKDOORROOMRATIO\t   0.27f\n\n// Wood wall material preset\n#define EAX_MATERIAL_WOODWALL              (-4000)\n#define EAX_MATERIAL_WOODWALLLF            0.50f\n#define EAX_MATERIAL_WOODWALLROOMRATIO     0.30f\n\n// Brick wall material preset\n#define EAX_MATERIAL_BRICKWALL             (-5000)\n#define EAX_MATERIAL_BRICKWALLLF           0.60f\n#define EAX_MATERIAL_BRICKWALLROOMRATIO    0.24f\n\n// Stone wall material preset\n#define EAX_MATERIAL_STONEWALL             (-6000)\n#define EAX_MATERIAL_STONEWALLLF           0.68f\n#define EAX_MATERIAL_STONEWALLROOMRATIO    0.20f\n\n// Curtain material preset\n#define EAX_MATERIAL_CURTAIN               (-1200)\n#define EAX_MATERIAL_CURTAINLF             0.15f\n#define EAX_MATERIAL_CURTAINROOMRATIO      1.00f\n\n\n#endif // EAXUTIL_INCLUDED\n"
  },
  {
    "path": "src/audio/eax/eax.h",
    "content": "/*******************************************************************\\\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n*  EAX.H - Environmental Audio Extensions version 3.0\t\t\t\t*\n*          for OpenAL and DirectSound3D\t\t\t\t\t\t\t\t*\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\n********************************************************************/\n\n#ifndef EAX_H_INCLUDED\n#define EAX_H_INCLUDED\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif // __cplusplus\n\n#ifndef AUDIO_OAL\n\t#include <dsound.h>\n\n\t/*\n\t * EAX Wrapper Interface (using Direct X 7) {4FF53B81-1CE0-11d3-AAB8-00A0C95949D5}\n\t */\n\tDEFINE_GUID(CLSID_EAXDirectSound, \n    \t0x4ff53b81, \n    \t0x1ce0, \n    \t0x11d3,\n    \t0xaa, 0xb8, 0x0, 0xa0, 0xc9, 0x59, 0x49, 0xd5);\n    \t\n   /*\n\t* EAX Wrapper Interface (using Direct X 8) {CA503B60-B176-11d4-A094-D0C0BF3A560C}\n\t*/\n\tDEFINE_GUID(CLSID_EAXDirectSound8, \n\t\t0xca503b60,\n\t\t0xb176,\n\t\t0x11d4,\n\t\t0xa0, 0x94, 0xd0, 0xc0, 0xbf, 0x3a, 0x56, 0xc);\n\n\t\n\n#ifdef DIRECTSOUND_VERSION\t\t\n#if DIRECTSOUND_VERSION >= 0x0800\n\t__declspec(dllimport) HRESULT WINAPI EAXDirectSoundCreate8(GUID*, LPDIRECTSOUND8*, IUnknown FAR *);\n\ttypedef HRESULT (FAR PASCAL *LPEAXDIRECTSOUNDCREATE8)(GUID*, LPDIRECTSOUND8*, IUnknown FAR*);\n#endif\n#endif\n\t\n\t__declspec(dllimport) HRESULT WINAPI EAXDirectSoundCreate(GUID*, LPDIRECTSOUND*, IUnknown FAR *);\n\ttypedef HRESULT (FAR PASCAL *LPEAXDIRECTSOUNDCREATE)(GUID*, LPDIRECTSOUND*, IUnknown FAR*);\n\n\t__declspec(dllimport) void CDECL GetCurrentVersion(LPDWORD major, LPDWORD minor);\n    typedef void (CDECL *LPGETCURRENTVERSION)(LPDWORD major, LPDWORD minor);\n\n\n#else // AUDIO_OAL\n\t#include <AL/al.h>\n\t#include <string.h>\n\n\t#ifndef GUID_DEFINED\n\t\t#define GUID_DEFINED\n\t\ttypedef struct _GUID\n\t\t{\n\t\t\tunsigned long Data1;\n\t\t\tunsigned short Data2;\n\t\t\tunsigned short Data3;\n\t\t\tunsigned char Data4[8];\n\t\t} GUID;\n\t#endif // !GUID_DEFINED\n\n\t#ifndef DEFINE_GUID\n\t\t#ifndef INITGUID\n\t\t\t#define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \\\n\t\t\t\t\textern const GUID /*FAR*/ name\n\t\t#else\n\t\t\t#define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \\\n\t\t\t\t\textern const GUID name = { l, w1, w2, { b1, b2,  b3,  b4,  b5,  b6,  b7,  b8 } }\n\t\t#endif // INITGUID\n\t#endif // DEFINE_GUID\n\t\n\n\t/*\n\t * EAX OpenAL Extension\n\t */\n\ttypedef ALenum (*EAXSet)(const GUID*, ALuint, ALuint, ALvoid*, ALuint);\n\ttypedef ALenum (*EAXGet)(const GUID*, ALuint, ALuint, ALvoid*, ALuint);\n#endif\n\n#pragma pack(push, 4)\n\n/*\n * EAX 3.0 listener property set {A8FA6880-B476-11d3-BDB9-00C0F02DDF87}\n */\nDEFINE_GUID(DSPROPSETID_EAX30_ListenerProperties, \n\t0xa8fa6882, \n\t0xb476, \n\t0x11d3, \n\t0xbd, 0xb9, 0x00, 0xc0, 0xf0, 0x2d, 0xdf, 0x87);\n\n// For compatibility with future EAX versions:\n#define DSPROPSETID_EAX_ListenerProperties DSPROPSETID_EAX30_ListenerProperties\n\ntypedef enum\n{\n    DSPROPERTY_EAXLISTENER_NONE,\n    DSPROPERTY_EAXLISTENER_ALLPARAMETERS,\n    DSPROPERTY_EAXLISTENER_ENVIRONMENT,\n    DSPROPERTY_EAXLISTENER_ENVIRONMENTSIZE,\n    DSPROPERTY_EAXLISTENER_ENVIRONMENTDIFFUSION,\n    DSPROPERTY_EAXLISTENER_ROOM,\n    DSPROPERTY_EAXLISTENER_ROOMHF,\n    DSPROPERTY_EAXLISTENER_ROOMLF,\n    DSPROPERTY_EAXLISTENER_DECAYTIME,\n    DSPROPERTY_EAXLISTENER_DECAYHFRATIO,\n    DSPROPERTY_EAXLISTENER_DECAYLFRATIO,\n    DSPROPERTY_EAXLISTENER_REFLECTIONS,\n    DSPROPERTY_EAXLISTENER_REFLECTIONSDELAY,\n    DSPROPERTY_EAXLISTENER_REFLECTIONSPAN,\n    DSPROPERTY_EAXLISTENER_REVERB,\n    DSPROPERTY_EAXLISTENER_REVERBDELAY,\n    DSPROPERTY_EAXLISTENER_REVERBPAN,\n    DSPROPERTY_EAXLISTENER_ECHOTIME,\n    DSPROPERTY_EAXLISTENER_ECHODEPTH,\n    DSPROPERTY_EAXLISTENER_MODULATIONTIME,\n    DSPROPERTY_EAXLISTENER_MODULATIONDEPTH,\n    DSPROPERTY_EAXLISTENER_AIRABSORPTIONHF,\n    DSPROPERTY_EAXLISTENER_HFREFERENCE,\n    DSPROPERTY_EAXLISTENER_LFREFERENCE,\n    DSPROPERTY_EAXLISTENER_ROOMROLLOFFFACTOR,\n    DSPROPERTY_EAXLISTENER_FLAGS\n} DSPROPERTY_EAX_LISTENERPROPERTY;\n\n// OR these flags with property id\n#define DSPROPERTY_EAXLISTENER_IMMEDIATE 0x00000000 // changes take effect immediately\n#define DSPROPERTY_EAXLISTENER_DEFERRED  0x80000000 // changes take effect later\n#define DSPROPERTY_EAXLISTENER_COMMITDEFERREDSETTINGS (DSPROPERTY_EAXLISTENER_NONE | \\\n                                                       DSPROPERTY_EAXLISTENER_IMMEDIATE)\n\ntypedef struct _EAXVECTOR {\n\tfloat x;\n\tfloat y;\n\tfloat z;\n} EAXVECTOR;\n\n// Use this structure for DSPROPERTY_EAXLISTENER_ALLPARAMETERS\n// - all levels are hundredths of decibels\n// - all times and delays are in seconds\n//\n// NOTE: This structure may change in future EAX versions.\n//       It is recommended to initialize fields by name:\n//              myListener.lRoom = -1000;\n//              myListener.lRoomHF = -100;\n//              ...\n//              myListener.dwFlags = myFlags /* see EAXLISTENERFLAGS below */ ;\n//       instead of:\n//              myListener = { -1000, -100, ... , 0x00000009 };\n//       If you want to save and load presets in binary form, you \n//       should define your own structure to insure future compatibility.\n//\ntypedef struct _EAXLISTENERPROPERTIES\n{\n    unsigned long ulEnvironment;   // sets all listener properties\n    float flEnvironmentSize;       // environment size in meters\n    float flEnvironmentDiffusion;  // environment diffusion\n    long lRoom;                    // room effect level (at mid frequencies)\n    long lRoomHF;                  // relative room effect level at high frequencies\n    long lRoomLF;                  // relative room effect level at low frequencies  \n    float flDecayTime;             // reverberation decay time at mid frequencies\n    float flDecayHFRatio;          // high-frequency to mid-frequency decay time ratio\n    float flDecayLFRatio;          // low-frequency to mid-frequency decay time ratio   \n    long lReflections;             // early reflections level relative to room effect\n    float flReflectionsDelay;      // initial reflection delay time\n    EAXVECTOR vReflectionsPan;     // early reflections panning vector\n    long lReverb;                  // late reverberation level relative to room effect\n    float flReverbDelay;           // late reverberation delay time relative to initial reflection\n    EAXVECTOR vReverbPan;          // late reverberation panning vector\n    float flEchoTime;              // echo time\n    float flEchoDepth;             // echo depth\n    float flModulationTime;        // modulation time\n    float flModulationDepth;       // modulation depth\n    float flAirAbsorptionHF;       // change in level per meter at high frequencies\n    float flHFReference;           // reference high frequency\n    float flLFReference;           // reference low frequency \n    float flRoomRolloffFactor;     // like DS3D flRolloffFactor but for room effect\n    unsigned long ulFlags;         // modifies the behavior of properties\n} EAXLISTENERPROPERTIES, *LPEAXLISTENERPROPERTIES;\n\n// used by DSPROPERTY_EAXLISTENER_ENVIRONMENT\nenum\n{\n    EAX_ENVIRONMENT_GENERIC,\n    EAX_ENVIRONMENT_PADDEDCELL,\n    EAX_ENVIRONMENT_ROOM,\n    EAX_ENVIRONMENT_BATHROOM,\n    EAX_ENVIRONMENT_LIVINGROOM,\n    EAX_ENVIRONMENT_STONEROOM,\n    EAX_ENVIRONMENT_AUDITORIUM,\n    EAX_ENVIRONMENT_CONCERTHALL,\n    EAX_ENVIRONMENT_CAVE,\n    EAX_ENVIRONMENT_ARENA,\n    EAX_ENVIRONMENT_HANGAR,\n    EAX_ENVIRONMENT_CARPETEDHALLWAY,\n    EAX_ENVIRONMENT_HALLWAY,\n    EAX_ENVIRONMENT_STONECORRIDOR,\n    EAX_ENVIRONMENT_ALLEY,\n    EAX_ENVIRONMENT_FOREST,\n    EAX_ENVIRONMENT_CITY,\n    EAX_ENVIRONMENT_MOUNTAINS,\n    EAX_ENVIRONMENT_QUARRY,\n    EAX_ENVIRONMENT_PLAIN,\n    EAX_ENVIRONMENT_PARKINGLOT,\n    EAX_ENVIRONMENT_SEWERPIPE,\n    EAX_ENVIRONMENT_UNDERWATER,\n    EAX_ENVIRONMENT_DRUGGED,\n    EAX_ENVIRONMENT_DIZZY,\n    EAX_ENVIRONMENT_PSYCHOTIC,\n\n    EAX_ENVIRONMENT_UNDEFINED,\n\n    EAX_ENVIRONMENT_COUNT\n};\n\n// Used by DSPROPERTY_EAXLISTENER_FLAGS\n//\n// Note: The number and order of flags may change in future EAX versions.\n//       It is recommended to use the flag defines as follows:\n//              myFlags = EAXLISTENERFLAGS_DECAYTIMESCALE | EAXLISTENERFLAGS_REVERBSCALE;\n//       instead of:\n//              myFlags = 0x00000009;\n//\n// These flags determine what properties are affected by environment size.\n#define EAXLISTENERFLAGS_DECAYTIMESCALE        0x00000001 // reverberation decay time\n#define EAXLISTENERFLAGS_REFLECTIONSSCALE      0x00000002 // reflection level\n#define EAXLISTENERFLAGS_REFLECTIONSDELAYSCALE 0x00000004 // initial reflection delay time\n#define EAXLISTENERFLAGS_REVERBSCALE           0x00000008 // reflections level\n#define EAXLISTENERFLAGS_REVERBDELAYSCALE      0x00000010 // late reverberation delay time\n#define EAXLISTENERFLAGS_ECHOTIMESCALE         0x00000040 // echo time\n#define EAXLISTENERFLAGS_MODULATIONTIMESCALE   0x00000080 // modulation time\n\n// This flag limits high-frequency decay time according to air absorption.\n#define EAXLISTENERFLAGS_DECAYHFLIMIT          0x00000020\n \n#define EAXLISTENERFLAGS_RESERVED              0xFFFFFF00 // reserved future use\n\n// Property ranges and defaults:\n\n#define EAXLISTENER_MINENVIRONMENT                0\n#define EAXLISTENER_MAXENVIRONMENT                (EAX_ENVIRONMENT_COUNT-1)\n#define EAXLISTENER_DEFAULTENVIRONMENT            EAX_ENVIRONMENT_GENERIC\n\n#define EAXLISTENER_MINENVIRONMENTSIZE            1.0f\n#define EAXLISTENER_MAXENVIRONMENTSIZE            100.0f\n#define EAXLISTENER_DEFAULTENVIRONMENTSIZE        7.5f\n\n#define EAXLISTENER_MINENVIRONMENTDIFFUSION       0.0f\n#define EAXLISTENER_MAXENVIRONMENTDIFFUSION       1.0f\n#define EAXLISTENER_DEFAULTENVIRONMENTDIFFUSION   1.0f\n\n#define EAXLISTENER_MINROOM                       (-10000)\n#define EAXLISTENER_MAXROOM                       0\n#define EAXLISTENER_DEFAULTROOM                   (-1000)\n\n#define EAXLISTENER_MINROOMHF                     (-10000)\n#define EAXLISTENER_MAXROOMHF                     0\n#define EAXLISTENER_DEFAULTROOMHF                 (-100)\n\n#define EAXLISTENER_MINROOMLF                     (-10000)\n#define EAXLISTENER_MAXROOMLF                     0\n#define EAXLISTENER_DEFAULTROOMLF                 0\n\n#define EAXLISTENER_MINDECAYTIME                  0.1f\n#define EAXLISTENER_MAXDECAYTIME                  20.0f\n#define EAXLISTENER_DEFAULTDECAYTIME              1.49f\n\n#define EAXLISTENER_MINDECAYHFRATIO               0.1f\n#define EAXLISTENER_MAXDECAYHFRATIO               2.0f\n#define EAXLISTENER_DEFAULTDECAYHFRATIO           0.83f\n\n#define EAXLISTENER_MINDECAYLFRATIO               0.1f\n#define EAXLISTENER_MAXDECAYLFRATIO               2.0f\n#define EAXLISTENER_DEFAULTDECAYLFRATIO           1.00f\n\n#define EAXLISTENER_MINREFLECTIONS                (-10000)\n#define EAXLISTENER_MAXREFLECTIONS                1000\n#define EAXLISTENER_DEFAULTREFLECTIONS            (-2602)\n\n#define EAXLISTENER_MINREFLECTIONSDELAY           0.0f\n#define EAXLISTENER_MAXREFLECTIONSDELAY           0.3f\n#define EAXLISTENER_DEFAULTREFLECTIONSDELAY       0.007f\n\n#define EAXLISTENER_MINREVERB                     (-10000)\n#define EAXLISTENER_MAXREVERB                     2000\n#define EAXLISTENER_DEFAULTREVERB                 200\n\n#define EAXLISTENER_MINREVERBDELAY                0.0f\n#define EAXLISTENER_MAXREVERBDELAY                0.1f\n#define EAXLISTENER_DEFAULTREVERBDELAY            0.011f\n\n#define EAXLISTENER_MINECHOTIME                   0.075f\n#define EAXLISTENER_MAXECHOTIME\t                  0.25f\n#define EAXLISTENER_DEFAULTECHOTIME               0.25f\n\n#define EAXLISTENER_MINECHODEPTH                  0.0f\n#define EAXLISTENER_MAXECHODEPTH                  1.0f\n#define EAXLISTENER_DEFAULTECHODEPTH              0.0f\n\n#define EAXLISTENER_MINMODULATIONTIME             0.04f\n#define EAXLISTENER_MAXMODULATIONTIME             4.0f\n#define EAXLISTENER_DEFAULTMODULATIONTIME         0.25f\n\n#define EAXLISTENER_MINMODULATIONDEPTH            0.0f\n#define EAXLISTENER_MAXMODULATIONDEPTH            1.0f\n#define EAXLISTENER_DEFAULTMODULATIONDEPTH        0.0f\n\n#define EAXLISTENER_MINAIRABSORPTIONHF            (-100.0f)\n#define EAXLISTENER_MAXAIRABSORPTIONHF            0.0f\n#define EAXLISTENER_DEFAULTAIRABSORPTIONHF        (-5.0f)\n\n#define EAXLISTENER_MINHFREFERENCE                1000.0f\n#define EAXLISTENER_MAXHFREFERENCE                20000.0f\n#define EAXLISTENER_DEFAULTHFREFERENCE            5000.0f\n\n#define EAXLISTENER_MINLFREFERENCE                20.0f\n#define EAXLISTENER_MAXLFREFERENCE                1000.0f\n#define EAXLISTENER_DEFAULTLFREFERENCE            250.0f\n\n#define EAXLISTENER_MINROOMROLLOFFFACTOR          0.0f\n#define EAXLISTENER_MAXROOMROLLOFFFACTOR          10.0f\n#define EAXLISTENER_DEFAULTROOMROLLOFFFACTOR      0.0f\n\n#define EAXLISTENER_DEFAULTFLAGS                  (EAXLISTENERFLAGS_DECAYTIMESCALE |        \\\n                                                   EAXLISTENERFLAGS_REFLECTIONSSCALE |      \\\n                                                   EAXLISTENERFLAGS_REFLECTIONSDELAYSCALE | \\\n                                                   EAXLISTENERFLAGS_REVERBSCALE |           \\\n                                                   EAXLISTENERFLAGS_REVERBDELAYSCALE |      \\\n                                                   EAXLISTENERFLAGS_DECAYHFLIMIT)\n\n\n\n/*\n* EAX 3.0 buffer property set {A8FA6881-B476-11d3-BDB9-00C0F02DDF87}\n*/\nDEFINE_GUID(DSPROPSETID_EAX30_BufferProperties, \n\t0xa8fa6881, \n\t0xb476, \n\t0x11d3, \n\t0xbd, 0xb9, 0x0, 0xc0, 0xf0, 0x2d, 0xdf, 0x87);\n\n// For compatibility with future EAX versions:\n#define DSPROPSETID_EAX_BufferProperties DSPROPSETID_EAX30_BufferProperties\n#define DSPROPSETID_EAX_SourceProperties DSPROPSETID_EAX30_BufferProperties\n\ntypedef enum\n{\n    DSPROPERTY_EAXBUFFER_NONE,\n    DSPROPERTY_EAXBUFFER_ALLPARAMETERS,\n    DSPROPERTY_EAXBUFFER_OBSTRUCTIONPARAMETERS,\n    DSPROPERTY_EAXBUFFER_OCCLUSIONPARAMETERS,\n    DSPROPERTY_EAXBUFFER_EXCLUSIONPARAMETERS,\n    DSPROPERTY_EAXBUFFER_DIRECT,\n    DSPROPERTY_EAXBUFFER_DIRECTHF,\n    DSPROPERTY_EAXBUFFER_ROOM,\n    DSPROPERTY_EAXBUFFER_ROOMHF,\n    DSPROPERTY_EAXBUFFER_OBSTRUCTION,\n    DSPROPERTY_EAXBUFFER_OBSTRUCTIONLFRATIO,\n    DSPROPERTY_EAXBUFFER_OCCLUSION, \n    DSPROPERTY_EAXBUFFER_OCCLUSIONLFRATIO,\n    DSPROPERTY_EAXBUFFER_OCCLUSIONROOMRATIO,\n    DSPROPERTY_EAXBUFFER_OCCLUSIONDIRECTRATIO,\n    DSPROPERTY_EAXBUFFER_EXCLUSION, \n    DSPROPERTY_EAXBUFFER_EXCLUSIONLFRATIO,\n    DSPROPERTY_EAXBUFFER_OUTSIDEVOLUMEHF, \n    DSPROPERTY_EAXBUFFER_DOPPLERFACTOR, \n    DSPROPERTY_EAXBUFFER_ROLLOFFFACTOR, \n    DSPROPERTY_EAXBUFFER_ROOMROLLOFFFACTOR,\n    DSPROPERTY_EAXBUFFER_AIRABSORPTIONFACTOR,\n    DSPROPERTY_EAXBUFFER_FLAGS\n} DSPROPERTY_EAX_BUFFERPROPERTY;    \n\n// OR these flags with property id\n#define DSPROPERTY_EAXBUFFER_IMMEDIATE 0x00000000 // changes take effect immediately\n#define DSPROPERTY_EAXBUFFER_DEFERRED  0x80000000 // changes take effect later\n#define DSPROPERTY_EAXBUFFER_COMMITDEFERREDSETTINGS (DSPROPERTY_EAXBUFFER_NONE | \\\n                                                     DSPROPERTY_EAXBUFFER_IMMEDIATE)\n\n// Use this structure for DSPROPERTY_EAXBUFFER_ALLPARAMETERS\n// - all levels are hundredths of decibels\n// - all delays are in seconds\n//\n// NOTE: This structure may change in future EAX versions.\n//       It is recommended to initialize fields by name:\n//              myBuffer.lDirect = 0;\n//              myBuffer.lDirectHF = -200;\n//              ...\n//              myBuffer.dwFlags = myFlags /* see EAXBUFFERFLAGS below */ ;\n//       instead of:\n//              myBuffer = { 0, -200, ... , 0x00000003 };\n//\ntypedef struct _EAXBUFFERPROPERTIES\n{\n    long lDirect;                 // direct path level (at low and mid frequencies)\n    long lDirectHF;               // relative direct path level at high frequencies\n    long lRoom;                   // room effect level (at low and mid frequencies)\n    long lRoomHF;                 // relative room effect level at high frequencies\n    long lObstruction;            // main obstruction control (attenuation at high frequencies) \n    float flObstructionLFRatio;   // obstruction low-frequency level re. main control\n    long lOcclusion;              // main occlusion control (attenuation at high frequencies)\n    float flOcclusionLFRatio;     // occlusion low-frequency level re. main control\n    float flOcclusionRoomRatio;   // relative occlusion control for room effect\n    float flOcclusionDirectRatio; // relative occlusion control for direct path\n    long lExclusion;              // main exlusion control (attenuation at high frequencies)\n    float flExclusionLFRatio;     // exclusion low-frequency level re. main control\n    long lOutsideVolumeHF;        // outside sound cone level at high frequencies\n    float flDopplerFactor;        // like DS3D flDopplerFactor but per source\n    float flRolloffFactor;        // like DS3D flRolloffFactor but per source\n    float flRoomRolloffFactor;    // like DS3D flRolloffFactor but for room effect\n    float flAirAbsorptionFactor;  // multiplies DSPROPERTY_EAXLISTENER_AIRABSORPTIONHF\n    unsigned long ulFlags;        // modifies the behavior of properties\n} EAXBUFFERPROPERTIES, *LPEAXBUFFERPROPERTIES;\n\n// Use this structure for DSPROPERTY_EAXBUFFER_OBSTRUCTION,\ntypedef struct _EAXOBSTRUCTIONPROPERTIES\n{\n    long lObstruction;\n    float flObstructionLFRatio;\n} EAXOBSTRUCTIONPROPERTIES, *LPEAXOBSTRUCTIONPROPERTIES;\n\n// Use this structure for DSPROPERTY_EAXBUFFER_OCCLUSION\ntypedef struct _EAXOCCLUSIONPROPERTIES\n{\n    long lOcclusion;\n    float flOcclusionLFRatio;\n    float flOcclusionRoomRatio;\n    float flOcclusionDirectRatio;\n} EAXOCCLUSIONPROPERTIES, *LPEAXOCCLUSIONPROPERTIES;\n\n// Use this structure for DSPROPERTY_EAXBUFFER_EXCLUSION\ntypedef struct _EAXEXCLUSIONPROPERTIES\n{\n    long lExclusion;\n    float flExclusionLFRatio;\n} EAXEXCLUSIONPROPERTIES, *LPEAXEXCLUSIONPROPERTIES;\n\n// Used by DSPROPERTY_EAXBUFFER_FLAGS\n//    TRUE:    value is computed automatically - property is an offset\n//    FALSE:   value is used directly\n//\n// Note: The number and order of flags may change in future EAX versions.\n//       To insure future compatibility, use flag defines as follows:\n//              myFlags = EAXBUFFERFLAGS_DIRECTHFAUTO | EAXBUFFERFLAGS_ROOMAUTO;\n//       instead of:\n//              myFlags = 0x00000003;\n//\n#define EAXBUFFERFLAGS_DIRECTHFAUTO          0x00000001 // affects DSPROPERTY_EAXBUFFER_DIRECTHF\n#define EAXBUFFERFLAGS_ROOMAUTO              0x00000002 // affects DSPROPERTY_EAXBUFFER_ROOM\n#define EAXBUFFERFLAGS_ROOMHFAUTO            0x00000004 // affects DSPROPERTY_EAXBUFFER_ROOMHF\n\n#define EAXBUFFERFLAGS_RESERVED              0xFFFFFFF8 // reserved future use\n\n// Property ranges and defaults:\n\n#define EAXBUFFER_MINDIRECT                    (-10000)\n#define EAXBUFFER_MAXDIRECT                    1000\n#define EAXBUFFER_DEFAULTDIRECT                0\n\n#define EAXBUFFER_MINDIRECTHF                  (-10000)\n#define EAXBUFFER_MAXDIRECTHF                  0\n#define EAXBUFFER_DEFAULTDIRECTHF              0\n\n#define EAXBUFFER_MINROOM                      (-10000)\n#define EAXBUFFER_MAXROOM                      1000\n#define EAXBUFFER_DEFAULTROOM                  0\n\n#define EAXBUFFER_MINROOMHF                    (-10000)\n#define EAXBUFFER_MAXROOMHF                    0\n#define EAXBUFFER_DEFAULTROOMHF                0\n\n#define EAXBUFFER_MINOBSTRUCTION               (-10000)\n#define EAXBUFFER_MAXOBSTRUCTION               0\n#define EAXBUFFER_DEFAULTOBSTRUCTION           0\n\n#define EAXBUFFER_MINOBSTRUCTIONLFRATIO        0.0f\n#define EAXBUFFER_MAXOBSTRUCTIONLFRATIO        1.0f\n#define EAXBUFFER_DEFAULTOBSTRUCTIONLFRATIO    0.0f\n\n#define EAXBUFFER_MINOCCLUSION                 (-10000)\n#define EAXBUFFER_MAXOCCLUSION                 0\n#define EAXBUFFER_DEFAULTOCCLUSION             0\n\n#define EAXBUFFER_MINOCCLUSIONLFRATIO          0.0f\n#define EAXBUFFER_MAXOCCLUSIONLFRATIO          1.0f\n#define EAXBUFFER_DEFAULTOCCLUSIONLFRATIO      0.25f\n\n#define EAXBUFFER_MINOCCLUSIONROOMRATIO        0.0f\n#define EAXBUFFER_MAXOCCLUSIONROOMRATIO        10.0f\n#define EAXBUFFER_DEFAULTOCCLUSIONROOMRATIO    1.5f\n\n#define EAXBUFFER_MINOCCLUSIONDIRECTRATIO      0.0f\n#define EAXBUFFER_MAXOCCLUSIONDIRECTRATIO      10.0f\n#define EAXBUFFER_DEFAULTOCCLUSIONDIRECTRATIO  1.0f\n\n#define EAXBUFFER_MINEXCLUSION                 (-10000)\n#define EAXBUFFER_MAXEXCLUSION                 0\n#define EAXBUFFER_DEFAULTEXCLUSION             0\n\n#define EAXBUFFER_MINEXCLUSIONLFRATIO          0.0f\n#define EAXBUFFER_MAXEXCLUSIONLFRATIO          1.0f\n#define EAXBUFFER_DEFAULTEXCLUSIONLFRATIO      1.0f\n\n#define EAXBUFFER_MINOUTSIDEVOLUMEHF           (-10000)\n#define EAXBUFFER_MAXOUTSIDEVOLUMEHF           0\n#define EAXBUFFER_DEFAULTOUTSIDEVOLUMEHF       0\n\n#define EAXBUFFER_MINDOPPLERFACTOR             0.0f\n#define EAXBUFFER_MAXDOPPLERFACTOR             10.f\n#define EAXBUFFER_DEFAULTDOPPLERFACTOR         0.0f\n\n#define EAXBUFFER_MINROLLOFFFACTOR             0.0f\n#define EAXBUFFER_MAXROLLOFFFACTOR             10.f\n#define EAXBUFFER_DEFAULTROLLOFFFACTOR         0.0f\n\n#define EAXBUFFER_MINROOMROLLOFFFACTOR         0.0f\n#define EAXBUFFER_MAXROOMROLLOFFFACTOR         10.f\n#define EAXBUFFER_DEFAULTROOMROLLOFFFACTOR     0.0f\n\n#define EAXBUFFER_MINAIRABSORPTIONFACTOR       0.0f\n#define EAXBUFFER_MAXAIRABSORPTIONFACTOR       10.0f\n#define EAXBUFFER_DEFAULTAIRABSORPTIONFACTOR   1.0f\n\n#define EAXBUFFER_DEFAULTFLAGS                 (EAXBUFFERFLAGS_DIRECTHFAUTO |       \\\n                                                EAXBUFFERFLAGS_ROOMAUTO |           \\\n                                                EAXBUFFERFLAGS_ROOMHFAUTO )\n\n#pragma pack(pop)\n\n#ifdef __cplusplus\n}\n#endif // __cplusplus\n\n#endif\n"
  },
  {
    "path": "src/audio/oal/aldlist.cpp",
    "content": "/*\n * Copyright (c) 2006, Creative Labs Inc.\n * All rights reserved.\n * \n * Redistribution and use in source and binary forms, with or without modification, are permitted provided\n * that the following conditions are met:\n * \n *     * Redistributions of source code must retain the above copyright notice, this list of conditions and\n * \t     the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright notice, this list of conditions\n * \t     and the following disclaimer in the documentation and/or other materials provided with the distribution.\n *     * Neither the name of Creative Labs Inc. nor the names of its contributors may be used to endorse or\n * \t     promote products derived from this software without specific prior written permission.\n * \n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED\n * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A\n * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR\n * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED\n * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\n * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"aldlist.h\"\n\n#ifndef _WIN32\n#define _stricmp strcasecmp\n#define _strnicmp strncasecmp\n#define _strdup strdup\n#endif\n\n#ifdef AUDIO_OAL\n/* \n * Init call\n */\nALDeviceList::ALDeviceList()\n{\n\tchar *devices;\n\tint index;\n\tconst char *defaultDeviceName;\n\tconst char *actualDeviceName;\n\n\t// DeviceInfo vector stores, for each enumerated device, it's device name, selection status, spec version #, and extension support\n\tnNumOfDevices = 0;\n\n\tdefaultDeviceIndex = 0;\n\n\tif (alcIsExtensionPresent(NULL, \"ALC_ENUMERATION_EXT\")) {\n\t\tdevices = (char *)alcGetString(NULL, ALC_DEVICE_SPECIFIER);\n\t\tdefaultDeviceName = (char *)alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER);\n\t\t\n\t\tindex = 0;\n\t\t// go through device list (each device terminated with a single NULL, list terminated with double NULL)\n\t\twhile (*devices != '\\0') {\n\t\t\tif (strcmp(defaultDeviceName, devices) == 0) {\n\t\t\t\tdefaultDeviceIndex = index;\n\t\t\t}\n\t\t\tALCdevice *device = alcOpenDevice(devices);\n\t\t\tif (device) {\n\t\t\t\tALCcontext *context = alcCreateContext(device, NULL);\n\t\t\t\tif (context) {\n\t\t\t\t\talcMakeContextCurrent(context);\n\t\t\t\t\t// if new actual device name isn't already in the list, then add it...\n\t\t\t\t\tactualDeviceName = alcGetString(device, ALC_DEVICE_SPECIFIER);\n\t\t\t\t\tbool bNewName = true;\n\t\t\t\t\tfor (unsigned int i = 0; i < GetNumDevices(); i++) {\n\t\t\t\t\t\tif (strcmp(GetDeviceName(i), actualDeviceName) == 0) {\n\t\t\t\t\t\t\tbNewName = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif ((bNewName) && (actualDeviceName != NULL) && (strlen(actualDeviceName) > 0)) {\n\t\t\t\t\t\tALDEVICEINFO ALDeviceInfo;\n\t\t\t\t\t\tALDeviceInfo.bSelected = true;\n\t\t\t\t\t\tALDeviceInfo.strDeviceName = _strdup(actualDeviceName);\n\t\t\t\t\t\talcGetIntegerv(device, ALC_MAJOR_VERSION, sizeof(int), &ALDeviceInfo.iMajorVersion);\n\t\t\t\t\t\talcGetIntegerv(device, ALC_MINOR_VERSION, sizeof(int), &ALDeviceInfo.iMinorVersion);\n\n\t\t\t\t\t\t// Check for ALC Extensions\n\t\t\t\t\t\tif (alcIsExtensionPresent(device, \"ALC_EXT_CAPTURE\") == AL_TRUE)\n\t\t\t\t\t\t\tALDeviceInfo.Extensions |= ADEXT_EXT_CAPTURE;\n\t\t\t\t\t\tif (alcIsExtensionPresent(device, \"ALC_EXT_EFX\") == AL_TRUE)\n\t\t\t\t\t\t\tALDeviceInfo.Extensions |= ADEXT_EXT_EFX;\n\n\t\t\t\t\t\t// Check for AL Extensions\n\t\t\t\t\t\tif (alIsExtensionPresent(\"AL_EXT_OFFSET\") == AL_TRUE)\n\t\t\t\t\t\t\tALDeviceInfo.Extensions |= ADEXT_EXT_OFFSET;\n\n\t\t\t\t\t\tif (alIsExtensionPresent(\"AL_EXT_LINEAR_DISTANCE\") == AL_TRUE)\n\t\t\t\t\t\t\tALDeviceInfo.Extensions |= ADEXT_EXT_LINEAR_DISTANCE;\n\t\t\t\t\t\tif (alIsExtensionPresent(\"AL_EXT_EXPONENT_DISTANCE\") == AL_TRUE)\n\t\t\t\t\t\t\tALDeviceInfo.Extensions |= ADEXT_EXT_EXPONENT_DISTANCE;\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (alIsExtensionPresent(\"EAX2.0\") == AL_TRUE)\n\t\t\t\t\t\t\tALDeviceInfo.Extensions |= ADEXT_EAX2;\n\t\t\t\t\t\tif (alIsExtensionPresent(\"EAX3.0\") == AL_TRUE)\n\t\t\t\t\t\t\tALDeviceInfo.Extensions |= ADEXT_EAX3;\n\t\t\t\t\t\tif (alIsExtensionPresent(\"EAX4.0\") == AL_TRUE)\n\t\t\t\t\t\t\tALDeviceInfo.Extensions |= ADEXT_EAX4;\n\t\t\t\t\t\tif (alIsExtensionPresent(\"EAX5.0\") == AL_TRUE)\n\t\t\t\t\t\t\tALDeviceInfo.Extensions |= ADEXT_EAX5;\n\n\t\t\t\t\t\tif (alIsExtensionPresent(\"EAX-RAM\") == AL_TRUE)\n\t\t\t\t\t\t\tALDeviceInfo.Extensions |= ADEXT_EAX_RAM;\n\n\t\t\t\t\t\t// Get Source Count\n\t\t\t\t\t\tALDeviceInfo.uiSourceCount = GetMaxNumSources();\n\n\t\t\t\t\t\taDeviceInfo[nNumOfDevices++] = ALDeviceInfo;\n\t\t\t\t\t}\n\t\t\t\t\talcMakeContextCurrent(NULL);\n\t\t\t\t\talcDestroyContext(context);\n\t\t\t\t}\n\t\t\t\talcCloseDevice(device);\n\t\t\t}\n\t\t\tdevices += strlen(devices) + 1;\n\t\t\tindex += 1;\n\t\t}\n\t}\n\n\tResetFilters();\n}\n\n/* \n * Exit call\n */\nALDeviceList::~ALDeviceList()\n{\n}\n\n/*\n * Returns the number of devices in the complete device list\n */\nunsigned int ALDeviceList::GetNumDevices()\n{\n\treturn nNumOfDevices;\n}\n\n/* \n * Returns the device name at an index in the complete device list\n */\nconst char * ALDeviceList::GetDeviceName(unsigned int index)\n{\n\tif (index < GetNumDevices())\n\t\treturn aDeviceInfo[index].strDeviceName;\n\telse\n\t\treturn NULL;\n}\n\n/*\n * Returns the major and minor version numbers for a device at a specified index in the complete list\n */\nvoid ALDeviceList::GetDeviceVersion(unsigned int index, int *major, int *minor)\n{\n\tif (index < GetNumDevices()) {\n\t\tif (major)\n\t\t\t*major = aDeviceInfo[index].iMajorVersion;\n\t\tif (minor)\n\t\t\t*minor = aDeviceInfo[index].iMinorVersion;\n\t}\n\treturn;\n}\n\n/*\n * Returns the maximum number of Sources that can be generate on the given device\n */\nunsigned int ALDeviceList::GetMaxNumSources(unsigned int index)\n{\n\tif (index < GetNumDevices())\n\t\treturn aDeviceInfo[index].uiSourceCount;\n\telse\n\t\treturn 0;\n}\n\n/*\n * Checks if the extension is supported on the given device\n */\nbool ALDeviceList::IsExtensionSupported(int index, unsigned short ext)\n{\n\treturn !!(aDeviceInfo[index].Extensions & ext);\n}\n\n/*\n * returns the index of the default device in the complete device list\n */\nint ALDeviceList::GetDefaultDevice()\n{\n\treturn defaultDeviceIndex;\n}\n\n/* \n * Deselects devices which don't have the specified minimum version\n */\nvoid ALDeviceList::FilterDevicesMinVer(int major, int minor)\n{\n\tint dMajor, dMinor;\n\tfor (unsigned int i = 0; i < nNumOfDevices; i++) {\n\t\tGetDeviceVersion(i, &dMajor, &dMinor);\n\t\tif ((dMajor < major) || ((dMajor == major) && (dMinor < minor))) {\n\t\t\taDeviceInfo[i].bSelected = false;\n\t\t}\n\t}\n}\n\n/* \n * Deselects devices which don't have the specified maximum version\n */\nvoid ALDeviceList::FilterDevicesMaxVer(int major, int minor)\n{\n\tint dMajor, dMinor;\n\tfor (unsigned int i = 0; i < nNumOfDevices; i++) {\n\t\tGetDeviceVersion(i, &dMajor, &dMinor);\n\t\tif ((dMajor > major) || ((dMajor == major) && (dMinor > minor))) {\n\t\t\taDeviceInfo[i].bSelected = false;\n\t\t}\n\t}\n}\n\n/*\n * Deselects device which don't support the given extension name\n */\nvoid\nALDeviceList::FilterDevicesExtension(unsigned short ext)\n{\n\tfor (unsigned int i = 0; i < nNumOfDevices; i++) {\n\t\tif (!IsExtensionSupported(i, ext))\n\t\t\taDeviceInfo[i].bSelected = false;\n\t}\n}\n\n/*\n * Resets all filtering, such that all devices are in the list\n */\nvoid ALDeviceList::ResetFilters()\n{\n\tfor (unsigned int i = 0; i < GetNumDevices(); i++) {\n\t\taDeviceInfo[i].bSelected = true;\n\t}\n\tfilterIndex = 0;\n}\n\n/*\n * Gets index of first filtered device\n */\nint ALDeviceList::GetFirstFilteredDevice()\n{\n\tunsigned int i;\n\n\tfor (i = 0; i < GetNumDevices(); i++) {\n\t\tif (aDeviceInfo[i].bSelected == true) {\n\t\t\tbreak;\n\t\t}\n\t}\n\tfilterIndex = i + 1;\n\treturn i;\n}\n\n/*\n * Gets index of next filtered device\n */\nint ALDeviceList::GetNextFilteredDevice()\n{\n\tunsigned int i;\n\n\tfor (i = filterIndex; i < GetNumDevices(); i++) {\n\t\tif (aDeviceInfo[i].bSelected == true) {\n\t\t\tbreak;\n\t\t}\n\t}\n\tfilterIndex = i + 1;\n\treturn i;\n}\n\n/*\n * Internal function to detemine max number of Sources that can be generated\n */\nunsigned int ALDeviceList::GetMaxNumSources()\n{\n\tALuint uiSources[256];\n\tunsigned int iSourceCount = 0;\n\n\t// Clear AL Error Code\n\talGetError();\n\n\t// Generate up to 256 Sources, checking for any errors\n\tfor (iSourceCount = 0; iSourceCount < 256; iSourceCount++)\n\t{\n\t\talGenSources(1, &uiSources[iSourceCount]);\n\t\tif (alGetError() != AL_NO_ERROR)\n\t\t\tbreak;\n\t}\n\n\t// Release the Sources\n\talDeleteSources(iSourceCount, uiSources);\n\tif (alGetError() != AL_NO_ERROR)\n\t{\n\t\tfor (unsigned int i = 0; i < 256; i++)\n\t\t{\n\t\t\talDeleteSources(1, &uiSources[i]);\n\t\t}\n\t}\n\n\treturn iSourceCount;\n}\n#endif\n"
  },
  {
    "path": "src/audio/oal/aldlist.h",
    "content": "#ifndef ALDEVICELIST_H\n#define ALDEVICELIST_H\n\n#include \"oal_utils.h\"\n\n#ifdef AUDIO_OAL\n#pragma warning(disable: 4786)  //disable warning \"identifier was truncated to '255' characters in the browser information\"\n\nenum\n{\n\tADEXT_EXT_CAPTURE = (1 << 0),\n\tADEXT_EXT_EFX = (1 << 1),\n\tADEXT_EXT_OFFSET = (1 << 2),\n\tADEXT_EXT_LINEAR_DISTANCE = (1 << 3),\n\tADEXT_EXT_EXPONENT_DISTANCE = (1 << 4),\n\tADEXT_EAX2 = (1 << 5),\n\tADEXT_EAX3 = (1 << 6),\n\tADEXT_EAX4 = (1 << 7),\n\tADEXT_EAX5 = (1 << 8),\n\tADEXT_EAX_RAM = (1 << 9),\n};\n\nstruct ALDEVICEINFO {\n\tconst char\t\t*strDeviceName;\n\tint\t\t\t\tiMajorVersion;\n\tint\t\t\t\tiMinorVersion;\n\tunsigned int\tuiSourceCount;\n\tunsigned short  Extensions;\n\tbool\t\t\tbSelected;\n\n\tALDEVICEINFO() : iMajorVersion(0), iMinorVersion(0), uiSourceCount(0), bSelected(false)\n\t{\n\t\tstrDeviceName = NULL;\n\t\tExtensions = 0;\n\t}\n};\n\ntypedef ALDEVICEINFO *LPALDEVICEINFO;\n\nclass ALDeviceList\n{\nprivate:\n\tALDEVICEINFO aDeviceInfo[64];\n\tunsigned int nNumOfDevices;\n\tint defaultDeviceIndex;\n\tint filterIndex;\n\npublic:\n\tALDeviceList ();\n\t~ALDeviceList ();\n\tunsigned int GetNumDevices();\n\tconst char *GetDeviceName(unsigned int index);\n\tvoid GetDeviceVersion(unsigned int index, int *major, int *minor);\n\tunsigned int GetMaxNumSources(unsigned int index);\n\tbool IsExtensionSupported(int index, unsigned short ext);\n\tint GetDefaultDevice();\n\tvoid FilterDevicesMinVer(int major, int minor);\n\tvoid FilterDevicesMaxVer(int major, int minor);\n\tvoid FilterDevicesExtension(unsigned short ext);\n\tvoid ResetFilters();\n\tint GetFirstFilteredDevice();\n\tint GetNextFilteredDevice();\n\nprivate:\n\tunsigned int GetMaxNumSources();\n};\n#endif\n\n#endif // ALDEVICELIST_H\n"
  },
  {
    "path": "src/audio/oal/channel.cpp",
    "content": "#include \"common.h\"\n\n#ifdef AUDIO_OAL\n#include \"channel.h\"\n#include \"sampman.h\"\n\n#ifndef _WIN32\n#include <float.h>\n#endif\n\nextern bool IsFXSupported();\n\nALuint alSources[MAXCHANNELS+MAX2DCHANNELS];\nALuint alFilters[MAXCHANNELS+MAX2DCHANNELS];\nALuint alBuffers[MAXCHANNELS+MAX2DCHANNELS];\nbool bChannelsCreated = false;\n\nint32 CChannel::channelsThatNeedService = 0;\n\nvoid\nCChannel::InitChannels()\n{\n\talGenSources(MAXCHANNELS+MAX2DCHANNELS, alSources);\n\talGenBuffers(MAXCHANNELS+MAX2DCHANNELS, alBuffers);\n\tif (IsFXSupported())\n\t\talGenFilters(MAXCHANNELS + MAX2DCHANNELS, alFilters);\n\tbChannelsCreated = true;\n}\n\nvoid\nCChannel::DestroyChannels()\n{\n\tif (bChannelsCreated) \n\t{\n\t\talDeleteSources(MAXCHANNELS + MAX2DCHANNELS, alSources);\n\t\tmemset(alSources, 0, sizeof(alSources));\n\t\talDeleteBuffers(MAXCHANNELS + MAX2DCHANNELS, alBuffers);\n\t\tmemset(alBuffers, 0, sizeof(alBuffers));\n\t\tif (IsFXSupported())\n\t\t{\n\t\t\talDeleteFilters(MAXCHANNELS + MAX2DCHANNELS, alFilters);\n\t\t\tmemset(alFilters, 0, sizeof(alFilters));\n\t\t}\n\t\tbChannelsCreated = false;\n\t}\n}\n\n\nCChannel::CChannel()\n{\n\tData = nil;\n\tDataSize = 0;\n\tSetDefault();\n}\n\nvoid CChannel::SetDefault()\n{\n\tPitch = 1.0f;\n\tGain = 1.0f;\n\tMix = 0.0f;\n\t\t\n\tPosition[0] = 0.0f; Position[1] = 0.0f; Position[2] = 0.0f;\n\tDistances[0] = 0.0f; Distances[1] = FLT_MAX;\n\n\tLoopCount = 1;\n\tLastProcessedOffset = UINT32_MAX;\n\tLoopPoints[0] = 0; LoopPoints[1] = -1;\n\t\n\tFrequency = MAX_FREQ;\n}\n\nvoid CChannel::Reset()\n{\n\t// Here is safe because ctor don't call this\n\tif (LoopCount > 1)\n\t\tchannelsThatNeedService--;\n\n\tClearBuffer();\n\tSetDefault();\n}\n\nvoid CChannel::Init(uint32 _id, bool Is2D)\n{\n\tid = _id;\n\tif ( HasSource() )\n\t{\n\t\talSourcei(alSources[id], AL_SOURCE_RELATIVE, AL_TRUE);\n\t\tif ( IsFXSupported() )\n\t\t\talSource3i(alSources[id], AL_AUXILIARY_SEND_FILTER, AL_EFFECTSLOT_NULL, 0, AL_FILTER_NULL);\n\t\t\n\t\tif ( Is2D )\n\t\t{\n\t\t\talSource3f(alSources[id], AL_POSITION, 0.0f, 0.0f, 0.0f);\n\t\t\talSourcef(alSources[id], AL_GAIN, 1.0f);\n\t\t}\n\t}\n}\n\nvoid CChannel::Term()\n{\n\tStop();\n\tif ( HasSource() )\n\t{\n\t\tif ( IsFXSupported() )\n\t\t{\n\t\t\talSource3i(alSources[id], AL_AUXILIARY_SEND_FILTER, AL_EFFECTSLOT_NULL, 0, AL_FILTER_NULL);\n\t\t}\n\t}\n}\n\nvoid CChannel::Start()\n{\n\tif ( !HasSource() ) return;\n\tif ( !Data ) return;\n\n\talBufferData(alBuffers[id], AL_FORMAT_MONO16, Data, DataSize, Frequency);\n\tif ( LoopPoints[0] != 0 && LoopPoints[0] != -1 )\n\t\talBufferiv(alBuffers[id], AL_LOOP_POINTS_SOFT, LoopPoints);\n\talSourcei(alSources[id], AL_BUFFER, alBuffers[id]);\n\talSourcePlay(alSources[id]);\n}\n\nvoid CChannel::Stop()\n{\n\tif ( HasSource() )\n\t\talSourceStop(alSources[id]);\n\t\n\tReset();\n}\n\nbool CChannel::HasSource()\n{\n\treturn alSources[id] != AL_NONE;\n}\n\t\nbool CChannel::IsUsed()\n{\n\tif ( HasSource() )\n\t{\n\t\tALint sourceState;\n\t\talGetSourcei(alSources[id], AL_SOURCE_STATE, &sourceState);\n\t\treturn sourceState == AL_PLAYING;\n\t}\n\treturn false;\n}\n\nvoid CChannel::SetPitch(float pitch)\n{\n\tif ( !HasSource() ) return;\n\talSourcef(alSources[id], AL_PITCH, pitch);\n}\n\nvoid CChannel::SetGain(float gain)\n{\n\tif ( !HasSource() ) return;\n\talSourcef(alSources[id], AL_GAIN, gain);\n}\n\t\nvoid CChannel::SetVolume(int32 vol)\n{\n\tSetGain(ALfloat(vol) / MAX_VOLUME);\n}\n\nvoid CChannel::SetSampleData(void *_data, size_t _DataSize, int32 freq)\n{\n\tData = _data;\n\tDataSize = _DataSize;\n\tFrequency = freq;\n}\n\t\nvoid CChannel::SetCurrentFreq(uint32 freq)\n{\n\tSetPitch(ALfloat(freq) / Frequency);\n}\n\nvoid CChannel::SetLoopCount(int32 count)\n{\n\tif ( !HasSource() ) return;\n\n\t// 0: loop indefinitely, 1: play one time, 2: play two times etc...\n\t// only > 1 needs manual processing\n\n\tif (LoopCount > 1 && count < 2)\n\t\tchannelsThatNeedService--;\n\telse if (LoopCount < 2 && count > 1)\n\t\tchannelsThatNeedService++;\n\n\talSourcei(alSources[id], AL_LOOPING, count == 1 ? AL_FALSE : AL_TRUE);\n\tLoopCount = count;\n}\n\nbool CChannel::Update()\n{\n\tif (!HasSource()) return false;\n\tif (LoopCount < 2) return false;\n\n\tALint state;\n\talGetSourcei(alSources[id], AL_SOURCE_STATE, &state);\n\tif (state == AL_STOPPED) {\n\t\tdebug(\"Looping channels(%d in this case) shouldn't report AL_STOPPED, but nvm\\n\", id);\n\t\tSetLoopCount(1);\n\t\treturn true;\n\t}\n\n\tassert(channelsThatNeedService > 0 && \"Ref counting is broken\");\n\n\tALint offset;\n\talGetSourcei(alSources[id], AL_SAMPLE_OFFSET, &offset);\n\n\t// Rewound\n\tif (offset < LastProcessedOffset) {\n\t\tLoopCount--;\n\t\tif (LoopCount == 1) {\n\t\t\t// Playing last tune...\n\t\t\tchannelsThatNeedService--;\n\t\t\talSourcei(alSources[id], AL_LOOPING, AL_FALSE);\n\t\t}\n\t}\n\tLastProcessedOffset = offset;\n\treturn true;\n}\n\nvoid CChannel::SetLoopPoints(ALint start, ALint end)\n{\n\tLoopPoints[0] = start;\n\tLoopPoints[1] = end;\n}\n\t\nvoid CChannel::SetPosition(float x, float y, float z)\n{\n\tif ( !HasSource() ) return;\n\talSource3f(alSources[id], AL_POSITION, x, y, z);\n}\n\t\nvoid CChannel::SetDistances(float max, float min)\n{\n\tif ( !HasSource() ) return;\n\talSourcef   (alSources[id], AL_MAX_DISTANCE,       max);\n\talSourcef   (alSources[id], AL_REFERENCE_DISTANCE, min);\n\talSourcef   (alSources[id], AL_MAX_GAIN, 1.0f);\n\talSourcef   (alSources[id], AL_ROLLOFF_FACTOR, 1.0f);\n}\n\t\nvoid CChannel::SetPan(int32 pan)\n{\n\tSetPosition((pan-63)/64.0f, 0.0f, Sqrt(1.0f-SQR((pan-63)/64.0f)));\n}\n\nvoid CChannel::ClearBuffer()\n{\n\tif ( !HasSource() ) return;\n\talSourcei(alSources[id], AL_LOOPING, AL_FALSE);\n\talSourcei(alSources[id], AL_BUFFER, AL_NONE);\n\tData = nil;\n\tDataSize = 0;\n}\n\nvoid CChannel::SetReverbMix(ALuint slot, float mix)\n{\n\tif ( !IsFXSupported() ) return;\n\tif ( !HasSource() ) return;\n\tif ( alFilters[id] == AL_FILTER_NULL ) return;\n\t\n\tMix = mix;\n\tEAX3_SetReverbMix(alFilters[id], mix);\n\talSource3i(alSources[id], AL_AUXILIARY_SEND_FILTER, slot, 0, alFilters[id]);\n}\n\nvoid CChannel::UpdateReverb(ALuint slot)\n{\n\tif ( !IsFXSupported() ) return;\n\tif ( !HasSource() ) return;\n\tif ( alFilters[id] == AL_FILTER_NULL ) return;\n\tEAX3_SetReverbMix(alFilters[id], Mix);\n\talSource3i(alSources[id], AL_AUXILIARY_SEND_FILTER, slot, 0, alFilters[id]);\n}\n\n#endif\n"
  },
  {
    "path": "src/audio/oal/channel.h",
    "content": "#pragma once\n\n#ifdef AUDIO_OAL\n#include \"oal/oal_utils.h\"\n#include <AL/al.h>\n#include <AL/alext.h>\n#include <AL/efx.h>\n\n\nclass CChannel\n{\n\tuint32 id;\n\tfloat  Pitch, Gain;\n\tfloat  Mix;\n\tvoid  *Data;\n\tsize_t DataSize;\n\tint32  Frequency;\n\tfloat  Position[3];\n\tfloat  Distances[2];\n\tint32  LoopCount;\n\tALint  LoopPoints[2];\n\tALint  LastProcessedOffset;\npublic:\n\tstatic int32 channelsThatNeedService;\n\n\tstatic void InitChannels();\n\tstatic void DestroyChannels();\n\n\tCChannel();\n\tvoid SetDefault();\n\tvoid Reset();\n\tvoid Init(uint32 _id, bool Is2D = false);\n\tvoid Term();\n\tvoid Start();\n\tvoid Stop();\n\tbool HasSource();\n\tbool IsUsed();\n\tvoid SetPitch(float pitch);\n\tvoid SetGain(float gain);\n\tvoid SetVolume(int32 vol);\n\tvoid SetSampleData(void *_data, size_t _DataSize, int32 freq);\n\tvoid SetCurrentFreq(uint32 freq);\n\tvoid SetLoopCount(int32 count);\n\tvoid SetLoopPoints(ALint start, ALint end);\n\tvoid SetPosition(float x, float y, float z);\n\tvoid SetDistances(float max, float min);\n\tvoid SetPan(int32 pan);\n\tvoid ClearBuffer();\n\tvoid SetReverbMix(ALuint slot, float mix);\n\tvoid UpdateReverb(ALuint slot);\n\tbool Update();\n};\n\n#endif"
  },
  {
    "path": "src/audio/oal/oal_utils.cpp",
    "content": "#include \"common.h\"\n#include \"oal_utils.h\"\n\n#ifdef AUDIO_OAL\n\n/*\n * When linking to a static openal-soft library,\n * the extension function inside the openal library conflict with the variables here.\n * Therefore declare these re3 owned symbols in a private namespace.\n */\n\nnamespace re3_openal {\n\nLPALGENEFFECTS alGenEffects;\nLPALDELETEEFFECTS alDeleteEffects;\nLPALISEFFECT alIsEffect;\nLPALEFFECTI alEffecti;\nLPALEFFECTIV alEffectiv;\nLPALEFFECTF alEffectf;\nLPALEFFECTFV alEffectfv;\nLPALGETEFFECTI alGetEffecti;\nLPALGETEFFECTIV alGetEffectiv;\nLPALGETEFFECTF alGetEffectf;\nLPALGETEFFECTFV alGetEffectfv;\nLPALGENAUXILIARYEFFECTSLOTS alGenAuxiliaryEffectSlots;\nLPALDELETEAUXILIARYEFFECTSLOTS alDeleteAuxiliaryEffectSlots;\nLPALISAUXILIARYEFFECTSLOT alIsAuxiliaryEffectSlot;\nLPALAUXILIARYEFFECTSLOTI alAuxiliaryEffectSloti;\nLPALAUXILIARYEFFECTSLOTIV alAuxiliaryEffectSlotiv;\nLPALAUXILIARYEFFECTSLOTF alAuxiliaryEffectSlotf;\nLPALAUXILIARYEFFECTSLOTFV alAuxiliaryEffectSlotfv;\nLPALGETAUXILIARYEFFECTSLOTI alGetAuxiliaryEffectSloti;\nLPALGETAUXILIARYEFFECTSLOTIV alGetAuxiliaryEffectSlotiv;\nLPALGETAUXILIARYEFFECTSLOTF alGetAuxiliaryEffectSlotf;\nLPALGETAUXILIARYEFFECTSLOTFV alGetAuxiliaryEffectSlotfv;\nLPALGENFILTERS alGenFilters;\nLPALDELETEFILTERS alDeleteFilters;\nLPALISFILTER alIsFilter;\nLPALFILTERI alFilteri;\nLPALFILTERIV alFilteriv;\nLPALFILTERF alFilterf;\nLPALFILTERFV alFilterfv;\nLPALGETFILTERI alGetFilteri;\nLPALGETFILTERIV alGetFilteriv;\nLPALGETFILTERF alGetFilterf;\nLPALGETFILTERFV alGetFilterfv;\n\n}\n\nusing namespace re3_openal;\n\nvoid EFXInit()\n{\n\t/* Define a macro to help load the function pointers. */\n#define LOAD_PROC(T, x)  ((x) = (T)alGetProcAddress(#x))\n\tLOAD_PROC(LPALGENEFFECTS, alGenEffects);\n\tLOAD_PROC(LPALDELETEEFFECTS, alDeleteEffects);\n\tLOAD_PROC(LPALISEFFECT, alIsEffect);\n\tLOAD_PROC(LPALEFFECTI, alEffecti);\n\tLOAD_PROC(LPALEFFECTIV, alEffectiv);\n\tLOAD_PROC(LPALEFFECTF, alEffectf);\n\tLOAD_PROC(LPALEFFECTFV, alEffectfv);\n\tLOAD_PROC(LPALGETEFFECTI, alGetEffecti);\n\tLOAD_PROC(LPALGETEFFECTIV, alGetEffectiv);\n\tLOAD_PROC(LPALGETEFFECTF, alGetEffectf);\n\tLOAD_PROC(LPALGETEFFECTFV, alGetEffectfv);\n\t\n\tLOAD_PROC(LPALGENFILTERS, alGenFilters);\n\tLOAD_PROC(LPALDELETEFILTERS, alDeleteFilters);\n\tLOAD_PROC(LPALISFILTER, alIsFilter);\n\tLOAD_PROC(LPALFILTERI, alFilteri);\n\tLOAD_PROC(LPALFILTERIV, alFilteriv);\n\tLOAD_PROC(LPALFILTERF, alFilterf);\n\tLOAD_PROC(LPALFILTERFV, alFilterfv);\n\tLOAD_PROC(LPALGETFILTERI, alGetFilteri);\n\tLOAD_PROC(LPALGETFILTERIV, alGetFilteriv);\n\tLOAD_PROC(LPALGETFILTERF, alGetFilterf);\n\tLOAD_PROC(LPALGETFILTERFV, alGetFilterfv);\n\t\n\tLOAD_PROC(LPALGENAUXILIARYEFFECTSLOTS, alGenAuxiliaryEffectSlots);\n\tLOAD_PROC(LPALDELETEAUXILIARYEFFECTSLOTS, alDeleteAuxiliaryEffectSlots);\n\tLOAD_PROC(LPALISAUXILIARYEFFECTSLOT, alIsAuxiliaryEffectSlot);\n\tLOAD_PROC(LPALAUXILIARYEFFECTSLOTI, alAuxiliaryEffectSloti);\n\tLOAD_PROC(LPALAUXILIARYEFFECTSLOTIV, alAuxiliaryEffectSlotiv);\n\tLOAD_PROC(LPALAUXILIARYEFFECTSLOTF, alAuxiliaryEffectSlotf);\n\tLOAD_PROC(LPALAUXILIARYEFFECTSLOTFV, alAuxiliaryEffectSlotfv);\n\tLOAD_PROC(LPALGETAUXILIARYEFFECTSLOTI, alGetAuxiliaryEffectSloti);\n\tLOAD_PROC(LPALGETAUXILIARYEFFECTSLOTIV, alGetAuxiliaryEffectSlotiv);\n\tLOAD_PROC(LPALGETAUXILIARYEFFECTSLOTF, alGetAuxiliaryEffectSlotf);\n\tLOAD_PROC(LPALGETAUXILIARYEFFECTSLOTFV, alGetAuxiliaryEffectSlotfv);\n#undef LOAD_PROC\n}\n\nvoid SetEffectsLevel(ALuint uiFilter, float level)\n{\n\talFilteri(uiFilter, AL_FILTER_TYPE, AL_FILTER_LOWPASS);\n\talFilterf(uiFilter, AL_LOWPASS_GAIN, 1.0f);\n\talFilterf(uiFilter, AL_LOWPASS_GAINHF, level);\n}\n\nstatic inline float gain_to_mB(float gain)\n{\n    return (gain > 1e-5f) ? (float)(log10f(gain) * 2000.0f) : -10000l;\n}\n\nstatic inline float mB_to_gain(float millibels)\n{\n    return (millibels > -10000.0f) ? powf(10.0f, millibels/2000.0f) : 0.0f;\n}\n\nstatic inline float clampF(float val, float minval, float maxval)\n{\n    if(val >= maxval) return maxval;\n    if(val <= minval) return minval;\n    return val;\n}\n\nvoid EAX3_Set(ALuint effect, const EAXLISTENERPROPERTIES *props)\n{\n\talEffecti (effect, AL_EFFECT_TYPE,                     AL_EFFECT_EAXREVERB);\n\talEffectf (effect, AL_EAXREVERB_DENSITY,               clampF(powf(props->flEnvironmentSize, 3.0f) / 16.0f, 0.0f, 1.0f));\n\talEffectf (effect, AL_EAXREVERB_DIFFUSION,             props->flEnvironmentDiffusion);\n\talEffectf (effect, AL_EAXREVERB_GAIN,                  mB_to_gain((float)props->lRoom));\n\talEffectf (effect, AL_EAXREVERB_GAINHF,                mB_to_gain((float)props->lRoomHF));\n\talEffectf (effect, AL_EAXREVERB_GAINLF,                mB_to_gain((float)props->lRoomLF));\n\talEffectf (effect, AL_EAXREVERB_DECAY_TIME,            props->flDecayTime);\n\talEffectf (effect, AL_EAXREVERB_DECAY_HFRATIO,         props->flDecayHFRatio);\n\talEffectf (effect, AL_EAXREVERB_DECAY_LFRATIO,         props->flDecayLFRatio);\n\talEffectf (effect, AL_EAXREVERB_REFLECTIONS_GAIN,      clampF(mB_to_gain((float)props->lReflections), AL_EAXREVERB_MIN_REFLECTIONS_GAIN, AL_EAXREVERB_MAX_REFLECTIONS_GAIN));\n\talEffectf (effect, AL_EAXREVERB_REFLECTIONS_DELAY,     props->flReflectionsDelay);\n\talEffectfv(effect, AL_EAXREVERB_REFLECTIONS_PAN,       &props->vReflectionsPan.x);\n\talEffectf (effect, AL_EAXREVERB_LATE_REVERB_GAIN,      clampF(mB_to_gain((float)props->lReverb), AL_EAXREVERB_MIN_LATE_REVERB_GAIN, AL_EAXREVERB_MAX_LATE_REVERB_GAIN));\n\talEffectf (effect, AL_EAXREVERB_LATE_REVERB_DELAY,     props->flReverbDelay);\n\talEffectfv(effect, AL_EAXREVERB_LATE_REVERB_PAN,       &props->vReverbPan.x);\n\talEffectf (effect, AL_EAXREVERB_ECHO_TIME,             props->flEchoTime);\n\talEffectf (effect, AL_EAXREVERB_ECHO_DEPTH,            props->flEchoDepth);\n\talEffectf (effect, AL_EAXREVERB_MODULATION_TIME,       props->flModulationTime);\n\talEffectf (effect, AL_EAXREVERB_MODULATION_DEPTH,      props->flModulationDepth);\n\talEffectf (effect, AL_EAXREVERB_AIR_ABSORPTION_GAINHF, clampF(mB_to_gain(props->flAirAbsorptionHF), AL_EAXREVERB_MIN_AIR_ABSORPTION_GAINHF, AL_EAXREVERB_MAX_AIR_ABSORPTION_GAINHF));\n\talEffectf (effect, AL_EAXREVERB_HFREFERENCE,           props->flHFReference);\n\talEffectf (effect, AL_EAXREVERB_LFREFERENCE,           props->flLFReference);\n\talEffectf (effect, AL_EAXREVERB_ROOM_ROLLOFF_FACTOR,   props->flRoomRolloffFactor);\n\talEffecti (effect, AL_EAXREVERB_DECAY_HFLIMIT,         (props->ulFlags&EAXLISTENERFLAGS_DECAYHFLIMIT) ? AL_TRUE : AL_FALSE);\n}\n\nvoid EFX_Set(ALuint effect, const EAXLISTENERPROPERTIES *props)\n{\n\talEffecti(effect, AL_EFFECT_TYPE, AL_EFFECT_REVERB);\n\t\n\talEffectf(effect, AL_REVERB_DENSITY,               clampF(powf(props->flEnvironmentSize, 3.0f) / 16.0f, 0.0f, 1.0f));\n\talEffectf(effect, AL_REVERB_DIFFUSION,             props->flEnvironmentDiffusion);\n\talEffectf(effect, AL_REVERB_GAIN,                  mB_to_gain((float)props->lRoom));\n\talEffectf(effect, AL_REVERB_GAINHF,                mB_to_gain((float)props->lRoomHF));\n\talEffectf(effect, AL_REVERB_DECAY_TIME,            props->flDecayTime);\n\talEffectf(effect, AL_REVERB_DECAY_HFRATIO,         props->flDecayHFRatio);\n\talEffectf(effect, AL_REVERB_REFLECTIONS_GAIN,      clampF(mB_to_gain((float)props->lReflections), AL_EAXREVERB_MIN_REFLECTIONS_GAIN, AL_EAXREVERB_MAX_REFLECTIONS_GAIN));\n\talEffectf(effect, AL_REVERB_REFLECTIONS_DELAY,     props->flReflectionsDelay);\n\talEffectf(effect, AL_REVERB_LATE_REVERB_GAIN,      clampF(mB_to_gain((float)props->lReverb), AL_EAXREVERB_MIN_LATE_REVERB_GAIN, AL_EAXREVERB_MAX_LATE_REVERB_GAIN));\n\talEffectf(effect, AL_REVERB_LATE_REVERB_DELAY,     props->flReverbDelay);\n\talEffectf(effect, AL_REVERB_AIR_ABSORPTION_GAINHF, clampF(mB_to_gain(props->flAirAbsorptionHF), AL_EAXREVERB_MIN_AIR_ABSORPTION_GAINHF, AL_EAXREVERB_MAX_AIR_ABSORPTION_GAINHF));\n\talEffectf(effect, AL_REVERB_ROOM_ROLLOFF_FACTOR,   props->flRoomRolloffFactor);\n\talEffecti(effect, AL_REVERB_DECAY_HFLIMIT,         (props->ulFlags&EAXLISTENERFLAGS_DECAYHFLIMIT) ? AL_TRUE : AL_FALSE);\n}\n\nvoid EAX3_SetReverbMix(ALuint filter, float mix)\n{\n\t//long vol=(long)linear_to_dB(mix);\n\t//DSPROPERTY_EAXBUFFER_ROOMHF,\n\t//DSPROPERTY_EAXBUFFER_ROOM,\n\t//DSPROPERTY_EAXBUFFER_REVERBMIX,\n\t\n\tlong mbvol = gain_to_mB(mix);\n\tfloat mb   = mbvol;\n\tfloat mbhf = mbvol;\n\t\n\talFilteri(filter, AL_FILTER_TYPE, AL_FILTER_LOWPASS);\n\talFilterf(filter, AL_LOWPASS_GAIN,   mB_to_gain(Min(mb, 0.0f)));\n\talFilterf(filter, AL_LOWPASS_GAINHF, mB_to_gain(mbhf));\n}\n\n#endif"
  },
  {
    "path": "src/audio/oal/oal_utils.h",
    "content": "#pragma once\n\n#ifdef AUDIO_OAL\n#include \"eax.h\"\n#include \"AL/efx.h\"\n\n\nvoid EFXInit();\nvoid EAX3_Set(ALuint effect, const EAXLISTENERPROPERTIES *props);\nvoid EFX_Set(ALuint effect, const EAXLISTENERPROPERTIES *props);\nvoid EAX3_SetReverbMix(ALuint filter, float mix);\nvoid SetEffectsLevel(ALuint uiFilter, float level);\n\nnamespace re3_openal {\n\nextern LPALGENEFFECTS alGenEffects;\nextern LPALDELETEEFFECTS alDeleteEffects;\nextern LPALISEFFECT alIsEffect;\nextern LPALEFFECTI alEffecti;\nextern LPALEFFECTIV alEffectiv;\nextern LPALEFFECTF alEffectf;\nextern LPALEFFECTFV alEffectfv;\nextern LPALGETEFFECTI alGetEffecti;\nextern LPALGETEFFECTIV alGetEffectiv;\nextern LPALGETEFFECTF alGetEffectf;\nextern LPALGETEFFECTFV alGetEffectfv;\nextern LPALGENAUXILIARYEFFECTSLOTS alGenAuxiliaryEffectSlots;\nextern LPALDELETEAUXILIARYEFFECTSLOTS alDeleteAuxiliaryEffectSlots;\nextern LPALISAUXILIARYEFFECTSLOT alIsAuxiliaryEffectSlot;\nextern LPALAUXILIARYEFFECTSLOTI alAuxiliaryEffectSloti;\nextern LPALAUXILIARYEFFECTSLOTIV alAuxiliaryEffectSlotiv;\nextern LPALAUXILIARYEFFECTSLOTF alAuxiliaryEffectSlotf;\nextern LPALAUXILIARYEFFECTSLOTFV alAuxiliaryEffectSlotfv;\nextern LPALGETAUXILIARYEFFECTSLOTI alGetAuxiliaryEffectSloti;\nextern LPALGETAUXILIARYEFFECTSLOTIV alGetAuxiliaryEffectSlotiv;\nextern LPALGETAUXILIARYEFFECTSLOTF alGetAuxiliaryEffectSlotf;\nextern LPALGETAUXILIARYEFFECTSLOTFV alGetAuxiliaryEffectSlotfv;\nextern LPALGENFILTERS alGenFilters;\nextern LPALDELETEFILTERS alDeleteFilters;\nextern LPALISFILTER alIsFilter;\nextern LPALFILTERI alFilteri;\nextern LPALFILTERIV alFilteriv;\nextern LPALFILTERF alFilterf;\nextern LPALFILTERFV alFilterfv;\nextern LPALGETFILTERI alGetFilteri;\nextern LPALGETFILTERIV alGetFilteriv;\nextern LPALGETFILTERF alGetFilterf;\nextern LPALGETFILTERFV alGetFilterfv;\n\n}\n\nusing namespace re3_openal;\n\n#endif\n"
  },
  {
    "path": "src/audio/oal/stream.cpp",
    "content": "#include \"common.h\"\n\n#ifdef AUDIO_OAL\n#include \"stream.h\"\n#include \"sampman.h\"\n\n#if defined _MSC_VER && !defined CMAKE_NO_AUTOLINK\n#ifdef AUDIO_OAL_USE_SNDFILE\n#pragma comment( lib, \"libsndfile-1.lib\" )\n#endif\n#ifdef AUDIO_OAL_USE_MPG123\n#pragma comment( lib, \"libmpg123-0.lib\" )\n#endif\n#endif\n#ifdef AUDIO_OAL_USE_SNDFILE\n#include <sndfile.h>\n#endif\n#ifdef AUDIO_OAL_USE_MPG123\n#include <mpg123.h>\n#endif\n#ifdef AUDIO_OAL_USE_OPUS\n#include <opusfile.h>\n#endif\n\n#ifndef _WIN32\n#include \"crossplatform.h\"\n#endif\n\n/*\nAs we ran onto an issue of having different volume levels for mono streams\nand stereo streams we are now handling all the stereo panning ourselves.\nEach stream now has two sources - one panned to the left and one to the right,\nand uses two separate buffers to store data for each individual channel.\nFor that we also have to reshuffle all decoded PCM stereo data from LRLRLRLR to\nLLLLRRRR (handled by CSortStereoBuffer).\n*/\n\nclass CSortStereoBuffer\n{\n\tuint16* PcmBuf;\n\tsize_t BufSize;\npublic:\n\tCSortStereoBuffer() : PcmBuf(nil), BufSize(0) {}\n\t~CSortStereoBuffer()\n\t{\n\t\tif (PcmBuf)\n\t\t\tfree(PcmBuf);\n\t}\n\n\tuint16* GetBuffer(size_t size)\n\t{\n\t\tif (size == 0) return nil;\n\t\tif (!PcmBuf)\n\t\t{\n\t\t\tBufSize = size;\n\t\t\tPcmBuf = (uint16*)malloc(BufSize);\n\t\t}\n\t\telse if (BufSize < size)\n\t\t{\n\t\t\tBufSize = size;\n\t\t\tPcmBuf = (uint16*)realloc(PcmBuf, size);\n\t\t}\n\t\treturn PcmBuf;\n\t}\n\n\tvoid SortStereo(void* buf, size_t size)\n\t{\n\t\tuint16* InBuf = (uint16*)buf;\n\t\tuint16* OutBuf = GetBuffer(size);\n\n\t\tif (!OutBuf) return;\n\n\t\tsize_t rightStart = size / 4;\n\t\tfor (size_t i = 0; i < size / 4; i++)\n\t\t{\n\t\t\tOutBuf[i] = InBuf[i*2];\n\t\t\tOutBuf[i+rightStart] = InBuf[i*2+1];\n\t\t}\n\n\t\tmemcpy(InBuf, OutBuf, size);\n\t}\n\n};\n\nCSortStereoBuffer SortStereoBuffer;\n\nclass CImaADPCMDecoder\n{\n\tconst uint16 StepTable[89] = {\n\t\t7, 8, 9, 10, 11, 12, 13, 14,\n\t\t16, 17, 19, 21, 23, 25, 28, 31,\n\t\t34, 37, 41, 45, 50, 55, 60, 66,\n\t\t73, 80, 88, 97, 107, 118, 130, 143,\n\t\t157, 173, 190, 209, 230, 253, 279, 307,\n\t\t337, 371, 408, 449, 494, 544, 598, 658,\n\t\t724, 796, 876, 963, 1060, 1166, 1282, 1411,\n\t\t1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024,\n\t\t3327, 3660, 4026, 4428, 4871, 5358, 5894, 6484,\n\t\t7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,\n\t\t15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794,\n\t\t32767\n\t};\n\n\tint16 Sample, StepIndex;\n\npublic:\n\tCImaADPCMDecoder()\n\t{\n\t\tInit(0, 0);\n\t}\n\n\tvoid Init(int16 _Sample, int16 _StepIndex)\n\t{\n\t\tSample = _Sample;\n\t\tStepIndex = _StepIndex;\n\t}\n\n\tvoid Decode(uint8 *inbuf, int16 *_outbuf, size_t size)\n\t{\n\t\tint16* outbuf = _outbuf;\n\t\tfor (size_t i = 0; i < size; i++)\n\t\t{\n\t\t\t*(outbuf++) = DecodeSample(inbuf[i] & 0xF);\n\t\t\t*(outbuf++) = DecodeSample(inbuf[i] >> 4);\n\t\t}\n\t}\n\n\tint16 DecodeSample(uint8 adpcm)\n\t{\n\t\tuint16 step = StepTable[StepIndex];\n\n\t\tif (adpcm & 4)\n\t\t\tStepIndex += ((adpcm & 3) + 1) * 2;\n\t\telse\n\t\t\tStepIndex--;\n\n\t\tStepIndex = clamp(StepIndex, 0, 88);\n\n\t\tint delta = step >> 3;\n\t\tif (adpcm & 1) delta += step >> 2;\n\t\tif (adpcm & 2) delta += step >> 1;\n\t\tif (adpcm & 4) delta += step;\n\t\tif (adpcm & 8) delta = -delta;\n\n\t\tint newSample = Sample + delta;\n\t\tSample = clamp(newSample, -32768, 32767);\n\t\treturn Sample;\n\t}\n};\n\nclass CWavFile : public IDecoder\n{\n\tenum\n\t{\n\t\tWAVEFMT_PCM = 1,\n\t\tWAVEFMT_IMA_ADPCM = 0x11,\n\t\tWAVEFMT_XBOX_ADPCM = 0x69,\n\t};\n\n\tstruct tDataHeader\n\t{\n\t\tuint32 ID;\n\t\tuint32 Size;\n\t};\n\n\tstruct tFormatHeader\n\t{\n\t\tuint16 AudioFormat;\n\t\tuint16 NumChannels;\n\t\tuint32 SampleRate;\n\t\tuint32 ByteRate;\n\t\tuint16 BlockAlign;\n\t\tuint16 BitsPerSample;\n\t\tuint16 extra[2]; // adpcm only\n\n\t\ttFormatHeader() { memset(this, 0, sizeof(*this)); }\n\t};\n\n\tFILE *m_pFile;\n\tbool  m_bIsOpen;\n\n\ttFormatHeader m_FormatHeader;\n\n\tuint32 m_DataStartOffset; // TODO: 64 bit?\n\tuint32 m_nSampleCount;\n\tuint32 m_nSamplesPerBlock;\n\n\t// ADPCM things\n\tuint8            *m_pAdpcmBuffer;\n\tint16           **m_ppPcmBuffers;\n\tCImaADPCMDecoder *m_pAdpcmDecoders;\n\n\tvoid Close()\n\t{\n\t\tif (m_pFile) {\n\t\t\tfclose(m_pFile);\n\t\t\tm_pFile = nil;\n\t\t}\n\t\tdelete[] m_pAdpcmBuffer;\n\t\tdelete[] m_ppPcmBuffers;\n\t\tdelete[] m_pAdpcmDecoders;\n\t}\n\n\tuint32 GetCurrentSample() const\n\t{\n\t\t// TODO: 64 bit?\n\t\tuint32 FilePos = ftell(m_pFile);\n\t\tif (FilePos <= m_DataStartOffset)\n\t\t\treturn 0;\n\t\treturn (FilePos - m_DataStartOffset) / m_FormatHeader.BlockAlign * m_nSamplesPerBlock;\n\t}\n\npublic:\n\tCWavFile(const char* path) : m_bIsOpen(false), m_DataStartOffset(0), m_nSampleCount(0), m_nSamplesPerBlock(0), m_pAdpcmBuffer(nil), m_ppPcmBuffers(nil), m_pAdpcmDecoders(nil)\n\t{\n\t\tm_pFile = fopen(path, \"rb\");\n\t\tif (!m_pFile) return;\n\n#define CLOSE_ON_ERROR(op)\\\n\t\t\tif (op) { \\\n\t\t\t\tClose(); \\\n\t\t\t\treturn; \\\n\t\t\t}\n\n\t\ttDataHeader DataHeader;\n\n\t\tCLOSE_ON_ERROR(fread(&DataHeader, sizeof(DataHeader), 1, m_pFile) == 0);\n\t\tCLOSE_ON_ERROR(DataHeader.ID != 'FFIR');\n\n\t\t// TODO? validate filesizes\n\n\t\tint WAVE;\n\t\tCLOSE_ON_ERROR(fread(&WAVE, 4, 1, m_pFile) == 0);\n\t\tCLOSE_ON_ERROR(WAVE != 'EVAW')\n\t\tCLOSE_ON_ERROR(fread(&DataHeader, sizeof(DataHeader), 1, m_pFile) == 0);\n\t\tCLOSE_ON_ERROR(DataHeader.ID != ' tmf');\n\n\t\tCLOSE_ON_ERROR(fread(&m_FormatHeader, Min(DataHeader.Size, sizeof(tFormatHeader)), 1, m_pFile) == 0);\n\t\tCLOSE_ON_ERROR(DataHeader.Size > sizeof(tFormatHeader));\n\n\t\tswitch (m_FormatHeader.AudioFormat)\n\t\t{\n\t\tcase WAVEFMT_XBOX_ADPCM:\n\t\t\tm_FormatHeader.AudioFormat = WAVEFMT_IMA_ADPCM;\n\t\tcase WAVEFMT_IMA_ADPCM:\n\t\t\tm_nSamplesPerBlock = (m_FormatHeader.BlockAlign / m_FormatHeader.NumChannels - 4) * 2 + 1;\n\t\t\tm_pAdpcmBuffer = new uint8[m_FormatHeader.BlockAlign];\n\t\t\tm_ppPcmBuffers = new int16*[m_FormatHeader.NumChannels];\n\t\t\tm_pAdpcmDecoders = new CImaADPCMDecoder[m_FormatHeader.NumChannels];\n\t\t\tbreak;\n\t\tcase WAVEFMT_PCM:\n\t\t\tm_nSamplesPerBlock = 1;\n\t\t\tif (m_FormatHeader.BitsPerSample != 16)\n\t\t\t{\n\t\t\t\tdebug(\"Unsupported PCM (%d bits), only signed 16-bit is supported (%s)\\n\", m_FormatHeader.BitsPerSample, path);\n\t\t\t\tClose();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tdebug(\"Unsupported wav format 0x%x (%s)\\n\", m_FormatHeader.AudioFormat, path);\n\t\t\tClose();\n\t\t\treturn;\n\t\t}\n\n\t\twhile (true) {\n\t\t\tCLOSE_ON_ERROR(fread(&DataHeader, sizeof(DataHeader), 1, m_pFile) == 0);\n\t\t\tif (DataHeader.ID == 'atad')\n\t\t\t\tbreak;\n\t\t\tfseek(m_pFile, DataHeader.Size, SEEK_CUR);\n\t\t\t// TODO? validate data size\n\t\t\t// maybe check if there no extreme custom headers that might break this\n\t\t}\n\t\t\n\t\tm_DataStartOffset = ftell(m_pFile);\n\t\tm_nSampleCount = DataHeader.Size / m_FormatHeader.BlockAlign * m_nSamplesPerBlock;\n\n\t\tm_bIsOpen = true;\n#undef CLOSE_ON_ERROR\n\t}\n\n\t~CWavFile()\n\t{\n\t\tClose();\n\t}\n\n\tbool IsOpened()\n\t{\n\t\treturn m_bIsOpen;\n\t}\n\n\tuint32 GetSampleSize()\n\t{\n\t\treturn sizeof(uint16);\n\t}\n\n\tuint32 GetSampleCount()\n\t{\n\t\treturn m_nSampleCount;\n\t}\n\n\tuint32 GetSampleRate()\n\t{\n\t\treturn m_FormatHeader.SampleRate;\n\t}\n\n\tuint32 GetChannels()\n\t{\n\t\treturn m_FormatHeader.NumChannels;\n\t}\n\n\tvoid Seek(uint32 milliseconds)\n\t{\n\t\tif (!IsOpened()) return;\n\t\tfseek(m_pFile, m_DataStartOffset + ms2samples(milliseconds) / m_nSamplesPerBlock * m_FormatHeader.BlockAlign, SEEK_SET);\n\t}\n\n\tuint32 Tell()\n\t{\n\t\tif (!IsOpened()) return 0;\n\t\treturn samples2ms(GetCurrentSample());\n\t}\n\n#define SAMPLES_IN_LINE (8)\n\n\tuint32 Decode(void* buffer)\n\t{\n\t\tif (!IsOpened()) return 0;\n\t\t\n\t\tif (m_FormatHeader.AudioFormat == WAVEFMT_PCM)\n\t\t{\n\t\t\t// just read the file and sort the samples\n\t\t\tuint32 size = fread(buffer, 1, GetBufferSize(), m_pFile);\n\t\t\tif (m_FormatHeader.NumChannels == 2)\n\t\t\t\tSortStereoBuffer.SortStereo(buffer, size);\n\t\t\treturn size;\n\t\t}\n\t\telse if (m_FormatHeader.AudioFormat == WAVEFMT_IMA_ADPCM)\n\t\t{\n\t\t\t// trim the buffer size if we're at the end of our file\n\t\t\tuint32 nMaxSamples = GetBufferSamples() / m_FormatHeader.NumChannels;\n\t\t\tuint32 nSamplesLeft = m_nSampleCount - GetCurrentSample();\n\t\t\tnMaxSamples = Min(nMaxSamples, nSamplesLeft);\n\n\t\t\t// align sample count to our block\n\t\t\tnMaxSamples = nMaxSamples / m_nSamplesPerBlock * m_nSamplesPerBlock;\n\n\t\t\t// count the size of output buffer\n\t\t\tuint32 OutBufSizePerChannel = nMaxSamples * GetSampleSize();\n\t\t\tuint32 OutBufSize = OutBufSizePerChannel * m_FormatHeader.NumChannels;\n\n\t\t\t// calculate the pointers to individual channel buffers\n\t\t\tfor (uint32 i = 0; i < m_FormatHeader.NumChannels; i++)\n\t\t\t\tm_ppPcmBuffers[i] = (int16*)((int8*)buffer + OutBufSizePerChannel * i);\n\n\t\t\tuint32 samplesRead = 0;\n\t\t\twhile (samplesRead < nMaxSamples)\n\t\t\t{\n\t\t\t\t// read the file\n\t\t\t\tuint8 *pAdpcmBuf = m_pAdpcmBuffer;\n\t\t\t\tif (fread(m_pAdpcmBuffer, 1, m_FormatHeader.BlockAlign, m_pFile) == 0)\n\t\t\t\t\treturn 0;\n\n\t\t\t\t// get the first sample in adpcm block and initialise the decoder(s)\n\t\t\t\tfor (uint32 i = 0; i < m_FormatHeader.NumChannels; i++)\n\t\t\t\t{\n\t\t\t\t\tint16 Sample = *(int16*)pAdpcmBuf;\n\t\t\t\t\tpAdpcmBuf += sizeof(int16);\n\t\t\t\t\tint16 Step = *(int16*)pAdpcmBuf;\n\t\t\t\t\tpAdpcmBuf += sizeof(int16);\n\t\t\t\t\tm_pAdpcmDecoders[i].Init(Sample, Step);\n\t\t\t\t\t*(m_ppPcmBuffers[i]) = Sample;\n\t\t\t\t\tm_ppPcmBuffers[i]++;\n\t\t\t\t}\n\t\t\t\tsamplesRead++;\n\n\t\t\t\t// decode the rest of the block\n\t\t\t\tfor (uint32 s = 1; s < m_nSamplesPerBlock; s += SAMPLES_IN_LINE)\n\t\t\t\t{\n\t\t\t\t\tfor (uint32 i = 0; i < m_FormatHeader.NumChannels; i++)\n\t\t\t\t\t{\n\t\t\t\t\t\tm_pAdpcmDecoders[i].Decode(pAdpcmBuf, m_ppPcmBuffers[i], SAMPLES_IN_LINE / 2);\n\t\t\t\t\t\tpAdpcmBuf += SAMPLES_IN_LINE / 2;\n\t\t\t\t\t\tm_ppPcmBuffers[i] += SAMPLES_IN_LINE;\n\t\t\t\t\t}\n\t\t\t\t\tsamplesRead += SAMPLES_IN_LINE;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn OutBufSize;\n\t\t}\n\t\treturn 0;\n\t}\n};\n\n#ifdef AUDIO_OAL_USE_SNDFILE\nclass CSndFile : public IDecoder\n{\n\tSNDFILE *m_pfSound;\n\tSF_INFO m_soundInfo;\npublic:\n\tCSndFile(const char *path) :\n\t\tm_pfSound(nil)\n\t{\n\t\tmemset(&m_soundInfo, 0, sizeof(m_soundInfo));\n\t\tm_pfSound = sf_open(path, SFM_READ, &m_soundInfo);\n\t}\n\t\n\t~CSndFile()\n\t{\n\t\tif ( m_pfSound )\n\t\t{\n\t\t\tsf_close(m_pfSound);\n\t\t\tm_pfSound = nil;\n\t\t}\n\t}\n\t\n\tbool IsOpened()\n\t{\n\t\treturn m_pfSound != nil;\n\t}\n\t\n\tuint32 GetSampleSize()\n\t{\n\t\treturn sizeof(uint16);\n\t}\n\t\n\tuint32 GetSampleCount()\n\t{\n\t\treturn m_soundInfo.frames;\n\t}\n\t\n\tuint32 GetSampleRate()\n\t{\n\t\treturn m_soundInfo.samplerate;\n\t}\n\t\n\tuint32 GetChannels()\n\t{\n\t\treturn m_soundInfo.channels;\n\t}\n\t\n\tvoid Seek(uint32 milliseconds)\n\t{\n\t\tif ( !IsOpened() ) return;\n\t\tsf_seek(m_pfSound, ms2samples(milliseconds), SF_SEEK_SET);\n\t}\n\t\n\tuint32 Tell()\n\t{\n\t\tif ( !IsOpened() ) return 0;\n\t\treturn samples2ms(sf_seek(m_pfSound, 0, SF_SEEK_CUR));\n\t}\n\t\n\tuint32 Decode(void *buffer)\n\t{\n\t\tif ( !IsOpened() ) return 0;\n\n\t\tsize_t size = sf_read_short(m_pfSound, (short*)buffer, GetBufferSamples()) * GetSampleSize();\n\t\tif (GetChannels()==2)\n\t\t\tSortStereoBuffer.SortStereo(buffer, size);\n\t\treturn size;\n\t}\n};\n#endif\n\n#ifdef AUDIO_OAL_USE_MPG123\n// fuzzy seek eliminates stutter when playing ADF but spams errors a lot (and breaks radio sometimes)\n//#define MP3_USE_FUZZY_SEEK\n\nclass CMP3File : public IDecoder\n{\nprotected:\n\tmpg123_handle *m_pMH;\n\tbool m_bOpened;\n\tuint32 m_nRate;\n\tuint32 m_nChannels;\n\t\n\tCMP3File() :\n\t\tm_pMH(nil),\n\t\tm_bOpened(false),\n\t\tm_nRate(0),\n\t\tm_nChannels(0) {}\npublic:\n\tCMP3File(const char *path) :\n\t\tm_pMH(nil),\n\t\tm_bOpened(false),\n\t\tm_nRate(0),\n\t\tm_nChannels(0)\n\t{\n\t\tm_pMH = mpg123_new(nil, nil);\n\t\tif ( m_pMH )\n\t\t{\n#ifdef MP3_USE_FUZZY_SEEK\n\t\t\tmpg123_param(m_pMH, MPG123_FLAGS, MPG123_FUZZY | MPG123_SEEKBUFFER | MPG123_GAPLESS | MPG123_QUIET, 0.0);\n#else\n\t\t\tmpg123_param(m_pMH, MPG123_FLAGS, MPG123_SEEKBUFFER | MPG123_GAPLESS, 0.0);\n#endif\n\t\t\tlong rate = 0;\n\t\t\tint channels = 0;\n\t\t\tint encoding = 0;\n\t\t\t\n\t\t\tm_bOpened = mpg123_open(m_pMH, path) == MPG123_OK\n\t\t\t\t&& mpg123_getformat(m_pMH, &rate, &channels, &encoding) == MPG123_OK;\n\n\t\t\tm_nRate = rate;\n\t\t\tm_nChannels = channels;\n\t\t\t\n\t\t\tif ( IsOpened() )\n\t\t\t{\n\t\t\t\tmpg123_format_none(m_pMH);\n\t\t\t\tmpg123_format(m_pMH, rate, channels, encoding);\n\t\t\t}\n\t\t}\n\t}\n\t\n\t~CMP3File()\n\t{\n\t\tif ( m_pMH )\n\t\t{\n\t\t\tmpg123_close(m_pMH);\n\t\t\tmpg123_delete(m_pMH);\n\t\t\tm_pMH = nil;\n\t\t}\n\t}\n\t\n\tbool IsOpened()\n\t{\n\t\treturn m_bOpened;\n\t}\n\t\n\tuint32 GetSampleSize()\n\t{\n\t\treturn sizeof(uint16);\n\t}\n\t\n\tuint32 GetSampleCount()\n\t{\n\t\tif ( !IsOpened() ) return 0;\n\t\treturn mpg123_length(m_pMH);\n\t}\n\t\n\tuint32 GetSampleRate()\n\t{\n\t\treturn m_nRate;\n\t}\n\t\n\tuint32 GetChannels()\n\t{\n\t\treturn m_nChannels;\n\t}\n\t\n\tvoid Seek(uint32 milliseconds)\n\t{\n\t\tif ( !IsOpened() ) return;\n\t\tmpg123_seek(m_pMH, ms2samples(milliseconds), SEEK_SET);\n\t}\n\t\n\tuint32 Tell()\n\t{\n\t\tif ( !IsOpened() ) return 0;\n\t\treturn samples2ms(mpg123_tell(m_pMH));\n\t}\n\t\n\tuint32 Decode(void *buffer)\n\t{\n\t\tif ( !IsOpened() ) return 0;\n\t\t\n\t\tsize_t size;\n\t\tint err = mpg123_read(m_pMH, (unsigned char *)buffer, GetBufferSize(), &size);\n#if defined(__LP64__) || defined(_WIN64)\n\t\tassert(\"We can't handle audio files more then 2 GB yet :shrug:\" && (size < UINT32_MAX));\n#endif\n\t\tif (err != MPG123_OK && err != MPG123_DONE) return 0;\n\t\tif (GetChannels() == 2)\n\t\t\tSortStereoBuffer.SortStereo(buffer, size);\n\t\treturn (uint32)size;\n\t}\n};\n\nclass CADFFile : public CMP3File\n{\n\tstatic ssize_t r_read(void* fh, void* buf, size_t size)\n\t{\n\t\tsize_t bytesRead = fread(buf, 1, size, (FILE*)fh);\n\t\tuint8* _buf = (uint8*)buf;\n\t\tfor (size_t i = 0; i < size; i++)\n\t\t\t_buf[i] ^= 0x22;\n\t\treturn bytesRead;\n\t}\n\tstatic off_t r_seek(void* fh, off_t pos, int seekType)\n\t{\n\t\tfseek((FILE*)fh, pos, seekType);\n\t\treturn ftell((FILE*)fh);\n\t}\n\tstatic void r_close(void* fh)\n\t{\n\t\tfclose((FILE*)fh);\n\t}\npublic:\n\tCADFFile(const char* path)\n\t{\n\t\tm_pMH = mpg123_new(nil, nil);\n\t\tif (m_pMH)\n\t\t{\n#ifdef MP3_USE_FUZZY_SEEK\n\t\t\tmpg123_param(m_pMH, MPG123_FLAGS, MPG123_FUZZY | MPG123_SEEKBUFFER | MPG123_GAPLESS | MPG123_QUIET, 0.0);\n#else\n\t\t\tmpg123_param(m_pMH, MPG123_FLAGS, MPG123_SEEKBUFFER | MPG123_GAPLESS, 0.0);\n#endif\n\t\t\tlong rate = 0;\n\t\t\tint channels = 0;\n\t\t\tint encoding = 0;\n\n\t\t\tFILE* f = fopen(path, \"rb\");\n\n\t\t\tm_bOpened = mpg123_replace_reader_handle(m_pMH, r_read, r_seek, r_close) == MPG123_OK\n\t\t\t\t&& mpg123_open_handle(m_pMH, f) == MPG123_OK &&  mpg123_getformat(m_pMH, &rate, &channels, &encoding) == MPG123_OK;\n\t\t\tm_nRate = rate;\n\t\t\tm_nChannels = channels;\n\n\t\t\tif (IsOpened())\n\t\t\t{\n\t\t\t\tmpg123_format_none(m_pMH);\n\t\t\t\tmpg123_format(m_pMH, rate, channels, encoding);\n\t\t\t}\n\t\t}\n\t}\n};\n\n#endif\n#define VAG_LINE_SIZE (0x10)\n#define VAG_SAMPLES_IN_LINE (28)\n\nclass CVagDecoder\n{\n\tconst double f[5][2] = { { 0.0, 0.0 },\n\t\t\t\t\t{  60.0 / 64.0,  0.0 },\n\t\t\t\t\t{  115.0 / 64.0, -52.0 / 64.0 },\n\t\t\t\t\t{  98.0 / 64.0, -55.0 / 64.0 },\n\t\t\t\t\t{  122.0 / 64.0, -60.0 / 64.0 } };\n\n\tdouble s_1;\n\tdouble s_2;\npublic:\n\tCVagDecoder()\n\t{\n\t\tResetState();\n\t}\n\n\tvoid ResetState()\n\t{\n\t\ts_1 = s_2 = 0.0;\n\t}\n\n\tstatic short quantize(double sample)\n\t{\n\t\tint a = int(sample + 0.5);\n\t\treturn short(clamp(a, -32768, 32767));\n\t}\n\n\tvoid Decode(void* _inbuf, int16* _outbuf, size_t size)\n\t{\n\t\tuint8* inbuf = (uint8*)_inbuf;\n\t\tint16* outbuf = _outbuf;\n\t\tsize &= ~(VAG_LINE_SIZE - 1);\n\n\t\twhile (size > 0) {\n\t\t\tdouble samples[VAG_SAMPLES_IN_LINE];\n\n\t\t\tint predict_nr, shift_factor, flags;\n\t\t\tpredict_nr = *(inbuf++);\n\t\t\tshift_factor = predict_nr & 0xf;\n\t\t\tpredict_nr >>= 4;\n\t\t\tflags = *(inbuf++);\n\t\t\tif (flags == 7) // TODO: ignore?\n\t\t\t\tbreak;\n\t\t\tfor (int i = 0; i < VAG_SAMPLES_IN_LINE; i += 2) {\n\t\t\t\tint d = *(inbuf++);\n\t\t\t\tint16 s = int16((d & 0xf) << 12);\n\t\t\t\tsamples[i] = (double)(s >> shift_factor);\n\t\t\t\ts = int16((d & 0xf0) << 8);\n\t\t\t\tsamples[i + 1] = (double)(s >> shift_factor);\n\t\t\t}\n\n\t\t\tfor (int i = 0; i < VAG_SAMPLES_IN_LINE; i++) {\n\t\t\t\tsamples[i] = samples[i] + s_1 * f[predict_nr][0] + s_2 * f[predict_nr][1];\n\t\t\t\ts_2 = s_1;\n\t\t\t\ts_1 = samples[i];\n\t\t\t\t*(outbuf++) = quantize(samples[i] + 0.5);\n\t\t\t}\n\t\t\tsize -= VAG_LINE_SIZE;\n\t\t}\n\t}\n};\n\n#define VB_BLOCK_SIZE (0x2000)\n#define NUM_VAG_LINES_IN_BLOCK (VB_BLOCK_SIZE / VAG_LINE_SIZE)\n#define NUM_VAG_SAMPLES_IN_BLOCK (NUM_VAG_LINES_IN_BLOCK * VAG_SAMPLES_IN_LINE)\n\nclass CVbFile : public IDecoder\n{\n\tFILE        *m_pFile;\n\tCVagDecoder *m_pVagDecoders;\n\n\tsize_t  m_FileSize;\n\tsize_t  m_nNumberOfBlocks;\n\n\tuint32  m_nSampleRate;\n\tuint8   m_nChannels;\n\tbool    m_bBlockRead;\n\tuint16  m_LineInBlock;\n\tsize_t  m_CurrentBlock;\n\n\tuint8 **m_ppVagBuffers; // buffers that cache actual ADPCM file data\n\tint16 **m_ppPcmBuffers;\n\n\tvoid ReadBlock(int32 block = -1)\n\t{\n\t\t// just read next block if -1\n\t\tif (block != -1)\n\t\t\tfseek(m_pFile, block * m_nChannels * VB_BLOCK_SIZE, SEEK_SET);\n\n\t\tfor (int i = 0; i < m_nChannels; i++)\n\t\t\tfread(m_ppVagBuffers[i], VB_BLOCK_SIZE, 1, m_pFile);\n\t\tm_bBlockRead = true;\n\t}\n\npublic:\n\tCVbFile(const char* path, uint32 nSampleRate = 32000, uint8 nChannels = 2) : m_nSampleRate(nSampleRate), m_nChannels(nChannels), m_pVagDecoders(nil), m_ppVagBuffers(nil), m_ppPcmBuffers(nil),\n\t\tm_FileSize(0), m_nNumberOfBlocks(0), m_bBlockRead(false), m_LineInBlock(0), m_CurrentBlock(0)\n\t{\n\t\tm_pFile = fopen(path, \"rb\");\n\t\tif (!m_pFile) return;\n\n\t\tfseek(m_pFile, 0, SEEK_END);\n\t\tm_FileSize = ftell(m_pFile);\n\t\tfseek(m_pFile, 0, SEEK_SET);\n\n\t\tm_nNumberOfBlocks = m_FileSize / (nChannels * VB_BLOCK_SIZE);\n\t\tm_pVagDecoders = new CVagDecoder[nChannels];\n\t\tm_ppVagBuffers = new uint8*[nChannels];\n\t\tm_ppPcmBuffers = new int16*[nChannels];\n\t\tfor (uint8 i = 0; i < nChannels; i++)\n\t\t\tm_ppVagBuffers[i] = new uint8[VB_BLOCK_SIZE];\n\t}\n\n\t~CVbFile()\n\t{\n\t\tif (m_pFile)\n\t\t{\n\t\t\tfclose(m_pFile);\n\n\t\t\tdelete[] m_pVagDecoders;\n\t\t\tfor (int i = 0; i < m_nChannels; i++)\n\t\t\t\tdelete[] m_ppVagBuffers[i];\n\t\t\tdelete[] m_ppVagBuffers;\n\t\t\tdelete[] m_ppPcmBuffers;\n\t\t}\n\t}\n\n\tbool IsOpened()\n\t{\n\t\treturn m_pFile != nil;\n\t}\n\n\tuint32 GetSampleSize()\n\t{\n\t\treturn sizeof(uint16);\n\t}\n\n\tuint32 GetSampleCount()\n\t{\n\t\tif (!IsOpened()) return 0;\n\t\treturn m_nNumberOfBlocks * NUM_VAG_LINES_IN_BLOCK * VAG_SAMPLES_IN_LINE;\n\t}\n\n\tuint32 GetSampleRate()\n\t{\n\t\treturn m_nSampleRate;\n\t}\n\n\tuint32 GetChannels()\n\t{\n\t\treturn m_nChannels;\n\t}\n\n\tvoid Seek(uint32 milliseconds)\n\t{\n\t\tif (!IsOpened()) return;\n\t\tuint32 samples = ms2samples(milliseconds);\n\n\t\t// find the block of our sample\n\t\tuint32 block = samples / NUM_VAG_SAMPLES_IN_BLOCK;\n\t\tif (block > m_nNumberOfBlocks)\n\t\t{\n\t\t\tsamples = 0;\n\t\t\tblock = 0;\n\t\t}\n\t\tif (block != m_CurrentBlock)\n\t\t\tm_bBlockRead = false;\n\n\t\t// find a line of our sample within our block\n\t\tuint32 remainingSamples = samples - block * NUM_VAG_SAMPLES_IN_BLOCK;\n\t\tuint32 newLine = remainingSamples / VAG_SAMPLES_IN_LINE / VAG_LINE_SIZE;\n\n\t\tif (m_CurrentBlock != block || m_LineInBlock != newLine)\n\t\t{\n\t\t\tm_CurrentBlock = block;\n\t\t\tm_LineInBlock = newLine;\n\t\t\tfor (uint32 i = 0; i < GetChannels(); i++)\n\t\t\t\tm_pVagDecoders[i].ResetState();\n\t\t}\n\n\t}\n\n\tuint32 Tell()\n\t{\n\t\tif (!IsOpened()) return 0;\n\t\tuint32 pos = (m_CurrentBlock * NUM_VAG_LINES_IN_BLOCK + m_LineInBlock) * VAG_SAMPLES_IN_LINE;\n\t\treturn samples2ms(pos);\n\t}\n\n\tuint32 Decode(void* buffer)\n\t{\n\t\tif (!IsOpened()) return 0;\n\n\t\tif (m_CurrentBlock >= m_nNumberOfBlocks) return 0;\n\n\t\t// cache current ADPCM block\n\t\tif (!m_bBlockRead)\n\t\t\tReadBlock(m_CurrentBlock);\n\n\t\t// trim the buffer size if we're at the end of our file\n\t\tint numberOfRequiredLines = GetBufferSamples() / m_nChannels / VAG_SAMPLES_IN_LINE;\n\t\tint numberOfRemainingLines = (m_nNumberOfBlocks - m_CurrentBlock) * NUM_VAG_LINES_IN_BLOCK - m_LineInBlock;\n\t\tint bufSizePerChannel = Min(numberOfRequiredLines, numberOfRemainingLines) * VAG_SAMPLES_IN_LINE * GetSampleSize();\n\n\t\t// calculate the pointers to individual channel buffers\n\t\tfor (uint32 i = 0; i < m_nChannels; i++)\n\t\t\tm_ppPcmBuffers[i] = (int16*)((int8*)buffer + bufSizePerChannel * i);\n\n\t\tint size = 0;\n\t\twhile (size < bufSizePerChannel)\n\t\t{\n\t\t\t// decode the VAG lines\n\t\t\tfor (uint32 i = 0; i < m_nChannels; i++)\n\t\t\t{\n\t\t\t\tm_pVagDecoders[i].Decode(m_ppVagBuffers[i] + m_LineInBlock * VAG_LINE_SIZE, m_ppPcmBuffers[i], VAG_LINE_SIZE);\n\t\t\t\tm_ppPcmBuffers[i] += VAG_SAMPLES_IN_LINE;\n\t\t\t}\n\t\t\tsize += VAG_SAMPLES_IN_LINE * GetSampleSize();\n\t\t\tm_LineInBlock++;\n\n\t\t\t// block is over, read the next block\n\t\t\tif (m_LineInBlock >= NUM_VAG_LINES_IN_BLOCK)\n\t\t\t{\n\t\t\t\tm_CurrentBlock++;\n\t\t\t\tif (m_CurrentBlock >= m_nNumberOfBlocks) // end of file\n\t\t\t\t\tbreak;\n\t\t\t\tm_LineInBlock = 0;\n\t\t\t\tReadBlock();\n\t\t\t}\n\t\t}\n\n\t\treturn bufSizePerChannel * m_nChannels;\n\t}\n};\n#ifdef AUDIO_OAL_USE_OPUS\nclass COpusFile : public IDecoder\n{\n\tOggOpusFile *m_FileH;\n\tbool m_bOpened;\n\tuint32 m_nRate;\n\tuint32 m_nChannels;\npublic:\n\tCOpusFile(const char *path) : m_FileH(nil),\n\t\tm_bOpened(false),\n\t\tm_nRate(0),\n\t\tm_nChannels(0)\n\t{\n\t\tint ret;\n\t\tm_FileH = op_open_file(path, &ret);\n\n\t\tif (m_FileH) {\n\t\t\tm_nChannels = op_head(m_FileH, 0)->channel_count;\n\t\t\tm_nRate = 48000;\n\t\t\tconst OpusTags *tags = op_tags(m_FileH, 0);\n\t\t\tfor (int i = 0; i < tags->comments; i++) {\n\t\t\t\tif (strncmp(tags->user_comments[i], \"SAMPLERATE\", sizeof(\"SAMPLERATE\")-1) == 0)\n\t\t\t\t{\n\t\t\t\t\tsscanf(tags->user_comments[i], \"SAMPLERATE=%i\", &m_nRate);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tm_bOpened = true;\n\t\t}\n\t}\n\t\n\t~COpusFile()\n\t{\n\t\tif (m_FileH)\n\t\t{\n\t\t\top_free(m_FileH);\n\t\t\tm_FileH = nil;\n\t\t}\n\t}\n\t\n\tbool IsOpened()\n\t{\n\t\treturn m_bOpened;\n\t}\n\t\n\tuint32 GetSampleSize()\n\t{\n\t\treturn sizeof(uint16);\n\t}\n\t\n\tuint32 GetSampleCount()\n\t{\n\t\tif ( !IsOpened() ) return 0;\n\t\treturn op_pcm_total(m_FileH, 0);\n\t}\n\t\n\tuint32 GetSampleRate()\n\t{\n\t\treturn m_nRate;\n\t}\n\t\n\tuint32 GetChannels()\n\t{\n\t\treturn m_nChannels;\n\t}\n\t\n\tvoid Seek(uint32 milliseconds)\n\t{\n\t\tif ( !IsOpened() ) return;\n\t\top_pcm_seek(m_FileH, ms2samples(milliseconds) / GetChannels());\n\t}\n\t\n\tuint32 Tell()\n\t{\n\t\tif ( !IsOpened() ) return 0;\n\t\treturn samples2ms(op_pcm_tell(m_FileH) * GetChannels());\n\t}\n\t\n\tuint32 Decode(void *buffer)\n\t{\n\t\tif ( !IsOpened() ) return 0;\n\n\t\tint size = op_read(m_FileH, (opus_int16 *)buffer, GetBufferSamples(), NULL);\n\n\t\tif (size < 0)\n\t\t\treturn 0;\n\n\t\tif (GetChannels() == 2)\n\t\t\tSortStereoBuffer.SortStereo(buffer, size * m_nChannels * GetSampleSize());\n\n\t\treturn size * m_nChannels * GetSampleSize();\n\t}\n};\n#endif\n\nvoid CStream::Initialise()\n{\n#ifdef AUDIO_OAL_USE_MPG123\n\tmpg123_init();\n#endif\n}\n\nvoid CStream::Terminate()\n{\n#ifdef AUDIO_OAL_USE_MPG123\n\tmpg123_exit();\n#endif\n}\n\nCStream::CStream(char *filename, ALuint *sources, ALuint (&buffers)[NUM_STREAMBUFFERS], uint32 overrideSampleRate) :\n\tm_pAlSources(sources),\n\tm_alBuffers(buffers),\n\tm_pBuffer(nil),\n\tm_bPaused(false),\n\tm_bActive(false),\n\tm_pSoundFile(nil),\n\tm_bReset(false),\n\tm_nVolume(0),\n\tm_nPan(0),\n\tm_nPosBeforeReset(0),\n\tm_nLoopCount(1)\n\t\n{\n// Be case-insensitive on linux (from https://github.com/OneSadCookie/fcaseopen/)\n#if !defined(_WIN32)\n\tchar *real = casepath(filename);\n\tif (real) {\n\t\tstrcpy(m_aFilename, real);\n\t\tfree(real);\n\t} else {\n#else\n\t{\n#endif\n\t\tstrcpy(m_aFilename, filename);\n\t}\n\t\t\n\tDEV(\"Stream %s\\n\", m_aFilename);\n\n\tif (!strcasecmp(&m_aFilename[strlen(m_aFilename) - strlen(\".wav\")], \".wav\"))\n#ifdef AUDIO_OAL_USE_SNDFILE\n\t\tm_pSoundFile = new CSndFile(m_aFilename);\n#else\n\t\tm_pSoundFile = new CWavFile(m_aFilename);\n#endif\n#ifdef AUDIO_OAL_USE_MPG123\n\telse if (!strcasecmp(&m_aFilename[strlen(m_aFilename) - strlen(\".mp3\")], \".mp3\"))\n\t\tm_pSoundFile = new CMP3File(m_aFilename);\n\telse if (!strcasecmp(&m_aFilename[strlen(m_aFilename) - strlen(\".adf\")], \".adf\"))\n\t\tm_pSoundFile = new CADFFile(m_aFilename);\n#endif\n\telse if (!strcasecmp(&m_aFilename[strlen(m_aFilename) - strlen(\".vb\")], \".VB\"))\n\t\tm_pSoundFile = new CVbFile(m_aFilename, overrideSampleRate);\n#ifdef AUDIO_OAL_USE_OPUS\n\telse if (!strcasecmp(&m_aFilename[strlen(m_aFilename) - strlen(\".opus\")], \".opus\"))\n\t\tm_pSoundFile = new COpusFile(m_aFilename);\n#endif\n\telse \n\t\tm_pSoundFile = nil;\n\n\tif ( IsOpened() )\n\t{\n\t\tm_pBuffer            = malloc(m_pSoundFile->GetBufferSize());\n\t\tASSERT(m_pBuffer!=nil);\n\t\t\n\t\tDEV(\"AvgSamplesPerSec: %d\\n\", m_pSoundFile->GetAvgSamplesPerSec());\n\t\tDEV(\"SampleCount: %d\\n\",      m_pSoundFile->GetSampleCount());\n\t\tDEV(\"SampleRate: %d\\n\",       m_pSoundFile->GetSampleRate());\n\t\tDEV(\"Channels: %d\\n\",         m_pSoundFile->GetChannels());\n\t\tDEV(\"Buffer Samples: %d\\n\",   m_pSoundFile->GetBufferSamples());\n\t\tDEV(\"Buffer sec: %f\\n\",       (float(m_pSoundFile->GetBufferSamples()) / float(m_pSoundFile->GetChannels())/ float(m_pSoundFile->GetSampleRate())));\n\t\tDEV(\"Length MS: %02d:%02d\\n\", (m_pSoundFile->GetLength() / 1000) / 60, (m_pSoundFile->GetLength() / 1000) % 60);\n\t\t\n\t\treturn;\n\t}\n}\n\nCStream::~CStream()\n{\n\tDelete();\n}\n\nvoid CStream::Delete()\n{\n\tStop();\n\tClearBuffers();\n\t\n\tif ( m_pSoundFile )\n\t{\n\t\tdelete m_pSoundFile;\n\t\tm_pSoundFile = nil;\n\t}\n\t\n\tif ( m_pBuffer )\n\t{\n\t\tfree(m_pBuffer);\n\t\tm_pBuffer = nil;\n\t}\n}\n\nbool CStream::HasSource()\n{\n\treturn (m_pAlSources[0] != AL_NONE) && (m_pAlSources[1] != AL_NONE);\n}\n\nbool CStream::IsOpened()\n{\n\treturn m_pSoundFile && m_pSoundFile->IsOpened();\n}\n\nbool CStream::IsPlaying()\n{\n\tif ( !HasSource() || !IsOpened() ) return false;\n\t\n\tif ( !m_bPaused )\n\t{\n\t\tALint sourceState[2];\n\t\talGetSourcei(m_pAlSources[0], AL_SOURCE_STATE, &sourceState[0]);\n\t\talGetSourcei(m_pAlSources[1], AL_SOURCE_STATE, &sourceState[1]);\n\t\tif (sourceState[0] == AL_PLAYING || sourceState[1] == AL_PLAYING)\n\t\t\treturn true;\n\t}\n\t\n\treturn false;\n}\n\nvoid CStream::Pause()\n{\n\tif ( !HasSource() ) return;\n\tALint sourceState = AL_PAUSED;\n\talGetSourcei(m_pAlSources[0], AL_SOURCE_STATE, &sourceState);\n\tif (sourceState != AL_PAUSED)\n\t\talSourcePause(m_pAlSources[0]);\n\talGetSourcei(m_pAlSources[1], AL_SOURCE_STATE, &sourceState);\n\tif (sourceState != AL_PAUSED)\n\t\talSourcePause(m_pAlSources[1]);\n}\n\nvoid CStream::SetPause(bool bPause)\n{\n\tif ( !HasSource() ) return;\n\tif ( bPause )\n\t{\n\t\tPause();\n\t\tm_bPaused = true;\n\t}\n\telse\n\t{\n\t\tif (m_bPaused)\n\t\t\tSetPlay(true);\n\t\tm_bPaused = false;\n\t}\n}\n\nvoid CStream::SetPitch(float pitch)\n{\n\tif ( !HasSource() ) return;\n\talSourcef(m_pAlSources[0], AL_PITCH, pitch);\n\talSourcef(m_pAlSources[1], AL_PITCH, pitch);\n}\n\nvoid CStream::SetGain(float gain)\n{\n\tif ( !HasSource() ) return;\n\talSourcef(m_pAlSources[0], AL_GAIN, gain);\n\talSourcef(m_pAlSources[1], AL_GAIN, gain);\n}\n\nvoid CStream::SetPosition(int i, float x, float y, float z)\n{\n\tif ( !HasSource() ) return;\n\talSource3f(m_pAlSources[i], AL_POSITION, x, y, z);\n}\n\nvoid CStream::SetVolume(uint32 nVol)\n{\n\tm_nVolume = nVol;\n\tSetGain(ALfloat(nVol) / MAX_VOLUME);\n}\n\nvoid CStream::SetPan(uint8 nPan)\n{\n\tm_nPan = clamp((int8)nPan - 63, 0, 63);\n\tSetPosition(0, (m_nPan - 63) / 64.0f, 0.0f, Sqrt(1.0f - SQR((m_nPan - 63) / 64.0f)));\n\n\tm_nPan = clamp((int8)nPan + 64, 64, 127);\n\tSetPosition(1, (m_nPan - 63) / 64.0f, 0.0f, Sqrt(1.0f - SQR((m_nPan - 63) / 64.0f)));\n\n\tm_nPan = nPan;\n}\n\n// Should only be called if source is stopped\nvoid CStream::SetPosMS(uint32 nPos)\n{\n\tif ( !IsOpened() ) return;\n\tm_pSoundFile->Seek(nPos);\n\tClearBuffers();\n}\n\nuint32 CStream::GetPosMS()\n{\n\tif ( !HasSource() ) return 0;\n\tif ( !IsOpened() ) return 0;\n\t\n\tALint offset;\n\t//alGetSourcei(m_alSource, AL_SAMPLE_OFFSET, &offset);\n\talGetSourcei(m_pAlSources[0], AL_BYTE_OFFSET, &offset);\n\n\treturn m_pSoundFile->Tell()\n\t\t- m_pSoundFile->samples2ms(m_pSoundFile->GetBufferSamples() * (NUM_STREAMBUFFERS/2-1)) / m_pSoundFile->GetChannels()\n\t\t+ m_pSoundFile->samples2ms(offset/m_pSoundFile->GetSampleSize()) / m_pSoundFile->GetChannels();\n}\n\nuint32 CStream::GetLengthMS()\n{\n\tif ( !IsOpened() ) return 0;\n\treturn m_pSoundFile->GetLength();\n}\n\nbool CStream::FillBuffer(ALuint *alBuffer)\n{\n\tif ( !HasSource() )\n\t\treturn false;\n\tif ( !IsOpened() )\n\t\treturn false;\n\tif ( !(alBuffer[0] != AL_NONE && alIsBuffer(alBuffer[0])) )\n\t\treturn false;\n\tif ( !(alBuffer[1] != AL_NONE && alIsBuffer(alBuffer[1])) )\n\t\treturn false;\n\t\n\tuint32 size = m_pSoundFile->Decode(m_pBuffer);\n\tif( size == 0 )\n\t\treturn false;\n\t\n\tuint32 channelSize = size / m_pSoundFile->GetChannels();\n\n\talBufferData(alBuffer[0], AL_FORMAT_MONO16, m_pBuffer, channelSize, m_pSoundFile->GetSampleRate());\n\t// TODO: use just one buffer if we play mono\n\tif (m_pSoundFile->GetChannels() == 1)\n\t\talBufferData(alBuffer[1], AL_FORMAT_MONO16, m_pBuffer, channelSize, m_pSoundFile->GetSampleRate());\n\telse\n\t\talBufferData(alBuffer[1], AL_FORMAT_MONO16, (uint8*)m_pBuffer + channelSize, channelSize, m_pSoundFile->GetSampleRate());\n\treturn true;\n}\n\nint32 CStream::FillBuffers()\n{\n\tint32 i = 0;\n\tfor ( i = 0; i < NUM_STREAMBUFFERS/2; i++ )\n\t{\n\t\tif ( !FillBuffer(&m_alBuffers[i*2]) )\n\t\t\tbreak;\n\t\talSourceQueueBuffers(m_pAlSources[0], 1, &m_alBuffers[i*2]);\n\t\talSourceQueueBuffers(m_pAlSources[1], 1, &m_alBuffers[i*2+1]);\n\t}\n\t\n\treturn i;\n}\n\nvoid CStream::ClearBuffers()\n{\n\tif ( !HasSource() ) return;\n\t\n\tALint buffersQueued[2];\n\talGetSourcei(m_pAlSources[0], AL_BUFFERS_QUEUED, &buffersQueued[0]);\n\talGetSourcei(m_pAlSources[1], AL_BUFFERS_QUEUED, &buffersQueued[1]);\n\n\tALuint value;\n\twhile (buffersQueued[0]--)\n\t\talSourceUnqueueBuffers(m_pAlSources[0], 1, &value);\n\twhile (buffersQueued[1]--)\n\t\talSourceUnqueueBuffers(m_pAlSources[1], 1, &value);\n}\n\nbool CStream::Setup(bool imSureQueueIsEmpty)\n{\n\tif ( IsOpened() )\n\t{\n\t\talSourcei(m_pAlSources[0], AL_LOOPING, AL_FALSE);\n\t\talSourcei(m_pAlSources[1], AL_LOOPING, AL_FALSE);\n\t\tif (!imSureQueueIsEmpty) {\n\t\t\tSetPlay(false);\n\t\t\tClearBuffers();\n\t\t}\n\t\tm_pSoundFile->Seek(0);\n\t\t//SetPosition(0.0f, 0.0f, 0.0f);\n\t\tSetPitch(1.0f);\n\t\t//SetPan(m_nPan);\n\t\t//SetVolume(100);\n\t}\n\t\n\treturn IsOpened();\n}\n\nvoid CStream::SetLoopCount(int32 count)\n{\n\tif ( !HasSource() ) return;\n\n\tm_nLoopCount = count;\n}\n\nvoid CStream::SetPlay(bool state)\n{\n\tif ( !HasSource() ) return;\n\tif ( state )\n\t{\n\t\tALint sourceState = AL_PLAYING;\n\t\talGetSourcei(m_pAlSources[0], AL_SOURCE_STATE, &sourceState);\n\t\tif (sourceState != AL_PLAYING )\n\t\t\talSourcePlay(m_pAlSources[0]);\n\n\t\tsourceState = AL_PLAYING;\n\t\talGetSourcei(m_pAlSources[1], AL_SOURCE_STATE, &sourceState);\n\t\tif (sourceState != AL_PLAYING)\n\t\t\talSourcePlay(m_pAlSources[1]);\n\n\t\tm_bActive = true;\n\t}\n\telse\n\t{\n\t\tALint sourceState = AL_STOPPED;\n\t\talGetSourcei(m_pAlSources[0], AL_SOURCE_STATE, &sourceState);\n\t\tif (sourceState != AL_STOPPED )\n\t\t\talSourceStop(m_pAlSources[0]);\n\n\t\tsourceState = AL_STOPPED;\n\t\talGetSourcei(m_pAlSources[1], AL_SOURCE_STATE, &sourceState);\n\t\tif (sourceState != AL_STOPPED)\n\t\t\talSourceStop(m_pAlSources[1]);\n\n\t\tm_bActive = false;\n\t}\n}\n\nvoid CStream::Start()\n{\n\tif ( !HasSource() ) return;\n\tif ( FillBuffers() != 0 )\n\t\tSetPlay(true);\n}\n\nvoid CStream::Stop()\n{\n\tif ( !HasSource() ) return;\n\tSetPlay(false);\n}\n\nvoid CStream::Update()\n{\n\tif ( !IsOpened() )\n\t\treturn;\n\t\n\tif ( !HasSource() )\n\t\treturn;\n\t\n\tif ( m_bReset )\n\t\treturn;\n\t\n\tif ( !m_bPaused )\n\t{\n\t\tALint totalBuffers[2] = { 0, 0 };\n\t\tALint buffersProcessed[2] = { 0, 0 };\n\t\t\n\t\t// Relying a lot on left buffer states in here\n\n\t\tdo\n\t\t{\n\t\t\t//alSourcef(m_pAlSources[0], AL_ROLLOFF_FACTOR, 0.0f);\n\t\t\talGetSourcei(m_pAlSources[0], AL_BUFFERS_QUEUED, &totalBuffers[0]);\n\t\t\talGetSourcei(m_pAlSources[0], AL_BUFFERS_PROCESSED, &buffersProcessed[0]);\n\t\t\t//alSourcef(m_pAlSources[1], AL_ROLLOFF_FACTOR, 0.0f);\n\t\t\talGetSourcei(m_pAlSources[1], AL_BUFFERS_QUEUED, &totalBuffers[1]);\n\t\t\talGetSourcei(m_pAlSources[1], AL_BUFFERS_PROCESSED, &buffersProcessed[1]);\n\t\t} while (buffersProcessed[0] != buffersProcessed[1]);\n\t\t\n\t\tassert(buffersProcessed[0] == buffersProcessed[1]);\n\n\t\t// Correcting OpenAL concepts here:\n\t\t// AL_BUFFERS_QUEUED = Number of *all* buffers in queue, including processed, processing and pending\n\t\t// AL_BUFFERS_PROCESSED = Index of the buffer being processing right now. Buffers coming after that(have greater index) are pending buffers.\n\t\t// which means: totalBuffers[0] - buffersProcessed[0] = pending buffers\n\n\t\tbool buffersRefilled = false;\n\n\t\t// We should wait queue to be cleared to loop track, because position calculation relies on queue.\n\t\tif (m_nLoopCount != 1 && m_bActive && totalBuffers[0] == 0)\n\t\t{\n\t\t\tSetup(true);\n\t\t\tbuffersRefilled = FillBuffers() != 0;\n\t\t\tif (m_nLoopCount != 0)\n\t\t\t\tm_nLoopCount--;\n\t\t}\n\t\telse\n\t\t{\n\t\t\twhile( buffersProcessed[0]-- )\n\t\t\t{\n\t\t\t\tALuint buffer[2];\n\t\t\t\t\n\t\t\t\talSourceUnqueueBuffers(m_pAlSources[0], 1, &buffer[0]);\n\t\t\t\talSourceUnqueueBuffers(m_pAlSources[1], 1, &buffer[1]);\n\t\t\t\t\n\t\t\t\tif (m_bActive && FillBuffer(buffer))\n\t\t\t\t{\n\t\t\t\t\tbuffersRefilled = true;\n\t\t\t\t\talSourceQueueBuffers(m_pAlSources[0], 1, &buffer[0]);\n\t\t\t\t\talSourceQueueBuffers(m_pAlSources[1], 1, &buffer[1]);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Two reasons: 1-Source may be starved to audio and stopped itself, 2- We're already waiting it to starve and die for looping track!\n\t\tif (m_bActive && (buffersRefilled || (totalBuffers[1] - buffersProcessed[1] != 0)))\n\t\t\tSetPlay(true);\n\t}\n}\n\nvoid CStream::ProviderInit()\n{\n\tif ( m_bReset )\n\t{\n\t\tif ( Setup(true) )\n\t\t{\n\t\t\tSetPan(m_nPan);\n\t\t\tSetVolume(m_nVolume);\n\t\t\tSetLoopCount(m_nLoopCount);\n\t\t\tSetPosMS(m_nPosBeforeReset);\n\t\t\tif (m_bActive)\n\t\t\t\tFillBuffers();\n\t\t\tSetPlay(m_bActive);\n\t\t\tif ( m_bPaused )\n\t\t\t\tPause();\n\t\t}\n\t\n\t\tm_bReset = false;\n\t}\n}\n\nvoid CStream::ProviderTerm()\n{\n\tm_bReset = true;\n\tm_nPosBeforeReset = GetPosMS();\n\t\n\tClearBuffers();\n}\n\t\n#endif\n"
  },
  {
    "path": "src/audio/oal/stream.h",
    "content": "#pragma once\n\n#ifdef AUDIO_OAL\n#include <AL/al.h>\n\n#define NUM_STREAMBUFFERS 8\n\nclass IDecoder\n{\npublic:\n\tvirtual ~IDecoder() { }\n\t\n\tvirtual bool   IsOpened() = 0;\n\t\n\tvirtual uint32 GetSampleSize() = 0;\n\tvirtual uint32 GetSampleCount() = 0;\n\tvirtual uint32 GetSampleRate() = 0;\n\tvirtual uint32 GetChannels() = 0;\n\t\n\tuint32 GetAvgSamplesPerSec()\n\t{\n\t\treturn GetChannels() * GetSampleRate();\n\t}\n\t\n\tuint32 ms2samples(uint32 ms)\n\t{\n\t\treturn float(ms) / 1000.0f * float(GetSampleRate());\n\t}\n\t\n\tuint32 samples2ms(uint32 sm)\n\t{\n\t\treturn float(sm) * 1000.0f / float(GetSampleRate());\n\t}\n\t\n\tuint32 GetBufferSamples()\n\t{\n\t\t//return (GetAvgSamplesPerSec() >> 2) - (GetSampleCount() % GetChannels());\n\t\treturn (GetAvgSamplesPerSec() / 4); // 250ms\n\t}\n\t\n\tuint32 GetBufferSize()\n\t{\n\t\treturn GetBufferSamples() * GetSampleSize();\n\t}\n\t\n\tvirtual void   Seek(uint32 milliseconds) = 0;\n\tvirtual uint32 Tell() = 0;\n\t\n\tuint32 GetLength()\n\t{\n\t\treturn float(GetSampleCount()) * 1000.0f / float(GetSampleRate());\n\t}\n\t\n\tvirtual uint32 Decode(void *buffer) = 0;\n};\n\nclass CStream\n{\n\tchar     m_aFilename[128];\n\tALuint  *m_pAlSources;\n\tALuint (&m_alBuffers)[NUM_STREAMBUFFERS];\n\t\n\tbool     m_bPaused;\n\tbool     m_bActive;\n\t\n\tvoid    *m_pBuffer;\n\t\n\tbool     m_bReset;\n\tuint32   m_nVolume;\n\tuint8    m_nPan;\n\tuint32   m_nPosBeforeReset;\n\tint32   m_nLoopCount;\n\t\n\tIDecoder *m_pSoundFile;\n\t\n\tbool HasSource();\n\tvoid SetPosition(int i, float x, float y, float z);\n\tvoid SetPitch(float pitch);\n\tvoid SetGain(float gain);\n\tvoid   Pause();\n\tvoid   SetPlay(bool state);\n\t\n\tbool   FillBuffer(ALuint *alBuffer);\n\tint32  FillBuffers();\n\tvoid   ClearBuffers();\npublic:\n\tstatic void Initialise();\n\tstatic void Terminate();\n\t\n\tCStream(char *filename, ALuint *sources, ALuint (&buffers)[NUM_STREAMBUFFERS], uint32 overrideSampleRate = 32000);\n\t~CStream();\n\tvoid   Delete();\n\t\n\tbool   IsOpened();\n\tbool   IsPlaying();\n\tvoid   SetPause (bool bPause);\n\tvoid   SetVolume(uint32 nVol);\n\tvoid   SetPan   (uint8 nPan);\n\tvoid   SetPosMS (uint32 nPos); \n\tuint32 GetPosMS();\n\tuint32 GetLengthMS();\n\t\n\tbool Setup(bool imSureQueueIsEmpty = false);\n\tvoid Start();\n\tvoid Stop();\n\tvoid Update(void);\n\tvoid SetLoopCount(int32);\n\n\t\n\tvoid ProviderInit();\n\tvoid ProviderTerm();\n};\n\n#endif\n"
  },
  {
    "path": "src/audio/sampman.h",
    "content": "#pragma once\n#include \"AudioSamples.h\"\n\n#define MAX_VOLUME 127\n#define MAX_FREQ DIGITALRATE\n\nstruct tSample {\n\tint32 nOffset;\n\tuint32 nSize;\n\tint32 nFrequency;\n\tint32 nLoopStart;\n\tint32 nLoopEnd;\n};\n\n#ifdef GTA_PS2\n#define PS2BANK(e) e\n#else\n#define PS2BANK(e) e = SFX_BANK_0\n#endif // GTA_PS2\n\n\nenum\n{\n\tSFX_BANK_0,\n#ifdef GTA_PS2\n\tSFX_BANK_GENERIC_EXTRA,\n\tSFX_BANK_PED_COMMENTS,\n\tSFX_BANK_FRONT_END_MENU,\n#else\n\tSFX_BANK_GENERIC_EXTRA = SFX_BANK_0,\n\tSFX_BANK_FRONT_END_MENU = SFX_BANK_0,\n\n\tSFX_BANK_PED_COMMENTS,\n\tMAX_SFX_BANKS,\n\tINVALID_SFX_BANK,\n#endif\n\n\tCAR_SFX_BANKS_OFFSET,\n\tSFX_BANK_PONTIAC = CAR_SFX_BANKS_OFFSET,\n\tSFX_BANK_PORSCHE,\n\tSFX_BANK_SPIDER,\n\tSFX_BANK_MERC,\n\tSFX_BANK_TRUCK,\n\tSFX_BANK_HOTROD,\n\tSFX_BANK_COBRA,\n\tSFX_BANK_PONTIAC_SLOW,\n\tSFX_BANK_CADILLAC,\n\tSFX_BANK_PATHFINDER,\n\tSFX_BANK_PACARD,\n\tSFX_BANK_GOLF_CART,\n\tSFX_BANK_CAR_CHAINSAW,\n\tSFX_BANK_RC,\n\tSFX_BANK_RC_HELI,\n\tSFX_BANK_CAR_UNUSED_4,\n\n\t// bikes\n\tSFX_BANK_VTWIN,\n\tSFX_BANK_MOPED,\n\tSFX_BANK_HONDA250,\n\tSFX_BANK_SPORTS_BIKE,\n\tSFX_BANK_BIKE_UNUSED_1,\n\tSFX_BANK_BIKE_UNUSED_2,\n\tSFX_BANK_BIKE_UNUSED_3,\n\tSFX_BANK_BIKE_UNUSED_4,\n\tSFX_BANK_BIKE_UNUSED_5,\n\tSFX_BANK_BIKE_UNUSED_6,\n\n\t// heli\n\tSFX_BANK_HELI_APACHE,\n\tSFX_BANK_HELI_UNUSED_1,\n\tSFX_BANK_HELI_UNUSED_2,\n\tSFX_BANK_HELI_UNUSED_3,\n\tSFX_BANK_HELI_UNUSED_4,\n\n\t// plane\n\tSFX_BANK_PLANE_SEAPLANE,\n\tSFX_BANK_PLANE_UNUSED_1,\n\tSFX_BANK_PLANE_UNUSED_2,\n\tSFX_BANK_PLANE_UNUSED_3,\n\tSFX_BANK_PLANE_UNUSED_4,\n\tPS2BANK(SFX_BANK_BUILDING_BANK_ALARM),\n\tPS2BANK(SFX_BANK_BUILDING_SNORING),\n\tPS2BANK(SFX_BANK_BUILDING_BAR_1),\n\tPS2BANK(SFX_BANK_BUILDING_BAR_2),\n\tPS2BANK(SFX_BANK_BUILDING_BAR_3),\n\tPS2BANK(SFX_BANK_BUILDING_BAR_4),\n\tPS2BANK(SFX_BANK_BUILDING_MALIBU_1),\n\tPS2BANK(SFX_BANK_BUILDING_MALIBU_2),\n\tPS2BANK(SFX_BANK_BUILDING_MALIBU_3),\n\tPS2BANK(SFX_BANK_BUILDING_STRIP_1),\n\tPS2BANK(SFX_BANK_BUILDING_STRIP_2),\n\tPS2BANK(SFX_BANK_BUILDING_STRIP_3),\n\tPS2BANK(SFX_BANK_BUILDING_CHURCH),\n\tPS2BANK(SFX_BANK_BUILDING_FAN_1),\n\tPS2BANK(SFX_BANK_BUILDING_FAN_2),\n\tPS2BANK(SFX_BANK_BUILDING_INSECT_1),\n\tPS2BANK(SFX_BANK_BUILDING_INSECT_2),\n\tPS2BANK(SFX_BANK_BUILDING_18),\n\tPS2BANK(SFX_BANK_BUILDING_19),\n\tPS2BANK(SFX_BANK_BUILDING_20),\n\tPS2BANK(SFX_BANK_BUILDING_21),\n\tPS2BANK(SFX_BANK_FOOTSTEPS_GRASS),\n\tPS2BANK(SFX_BANK_FOOTSTEPS_GRAVEL),\n\tPS2BANK(SFX_BANK_FOOTSTEPS_WOOD),\n\tPS2BANK(SFX_BANK_FOOTSTEPS_METAL),\n\tPS2BANK(SFX_BANK_FOOTSTEPS_WATER),\n\tPS2BANK(SFX_BANK_FOOTSTEPS_SAND),\n#ifdef GTA_PS2\n\tMAX_SFX_BANKS,\n\tINVALID_SFX_BANK\n#endif\n};\n#define MAX_PEDSFX                 7\n#define PED_BLOCKSIZE              79000\n\n#define MAXPROVIDERS               64\n\n#define MAXCHANNELS                28\n#define MAXCHANNELS_SURROUND       24\n#define MAX2DCHANNELS              1\n#define CHANNEL2D                  MAXCHANNELS\n\n#define MAX_STREAMS                3\n\n#define DIGITALRATE                32000\n#define DIGITALBITS                16\n#define DIGITALCHANNELS            2\n\n#define MAX_DIGITAL_MIXER_CHANNELS 32\n\nclass cSampleManager\n{\n\tuint8   m_nEffectsVolume;\n\tuint8   m_nMusicVolume;\n\tuint8   m_nMP3BoostVolume;\n\tuint8   m_nEffectsFadeVolume;\n\tuint8   m_nMusicFadeVolume;\n\tuint8   m_nMonoMode;\n\tchar    m_szCDRomRootPath[80];\n\tbool    m_bInitialised;\n\tuint8   m_nNumberOfProviders;\n\tchar   *m_aAudioProviders[MAXPROVIDERS];\n\ttSample m_aSamples[TOTAL_AUDIO_SAMPLES];\n\tchar    m_MiscomPath[260];\n\tchar    m_WavFilesPath[260];\n\tchar    m_MP3FilesPath[188];\n\tvoid   *m_aChannels[18];\n\npublic:\n\t\n\t\n\n\tcSampleManager(void);\n\t~cSampleManager(void);\n\t\n\tvoid SetSpeakerConfig(int32 nConfig);\n\tuint32 GetMaximumSupportedChannels(void);\n\t\n\tuint32 GetNum3DProvidersAvailable(void);\n\tvoid SetNum3DProvidersAvailable(uint32 num);\n\t\n\tchar *Get3DProviderName(uint8 id);\n\tvoid Set3DProviderName(uint8 id, char *name);\n\t\n\tint8 GetCurrent3DProviderIndex(void);\n\tint8 SetCurrent3DProvider(uint8 which);\n\n\tint8 AutoDetect3DProviders();\n\t\n\tbool IsMP3RadioChannelAvailable(void);\n\t\n\tvoid ReleaseDigitalHandle  (void);\n\tvoid ReacquireDigitalHandle(void);\n\t\n\tbool Initialise(void);\n\tvoid Terminate (void);\n\t\t\n\tbool CheckForAnAudioFileOnCD(void);\n\tchar GetCDAudioDriveLetter  (void);\n\t\n\tvoid UpdateEffectsVolume(void);\n\n\tvoid SetEffectsMasterVolume(uint8 nVolume);\n\tvoid SetMusicMasterVolume  (uint8 nVolume);\n\tvoid SetMP3BoostVolume     (uint8 nVolume);\n\tvoid SetEffectsFadeVolume  (uint8 nVolume);\n\tvoid SetMusicFadeVolume    (uint8 nVolume);\n\tvoid SetMonoMode           (uint8 nMode);\n\t\n\tbool LoadSampleBank    (uint8 nBank);\n\tvoid UnloadSampleBank  (uint8 nBank);\n\tbool IsSampleBankLoaded(uint8 nBank);\n\t\n\tbool IsPedCommentLoaded(uint32 nComment);\n\tbool LoadPedComment    (uint32 nComment);\n\tint32 GetBankContainingSound(uint32 offset);\n\n\tint32 _GetPedCommentSlot(uint32 nComment);\n\t\n\tint32  GetSampleBaseFrequency  (uint32 nSample);\n\tint32  GetSampleLoopStartOffset(uint32 nSample);\n\tint32  GetSampleLoopEndOffset  (uint32 nSample);\n\tuint32 GetSampleLength         (uint32 nSample);\n\t\n\tbool  UpdateReverb(void);\n\t\n\tvoid  SetChannelReverbFlag    (uint32 nChannel, uint8 nReverbFlag);\n\tbool  InitialiseChannel       (uint32 nChannel, uint32 nSfx, uint8 nBank);\n\tvoid  SetChannelEmittingVolume(uint32 nChannel, uint32 nVolume);\n\tvoid  SetChannel3DPosition    (uint32 nChannel, float fX, float fY, float fZ);\n\tvoid  SetChannel3DDistances   (uint32 nChannel, float fMax, float fMin);\n\tvoid  SetChannelVolume        (uint32 nChannel, uint32 nVolume);\n\tvoid  SetChannelPan           (uint32 nChannel, uint32 nPan);\n\tvoid  SetChannelFrequency     (uint32 nChannel, uint32 nFreq);\n\tvoid  SetChannelLoopPoints    (uint32 nChannel, uint32 nLoopStart, int32 nLoopEnd);\n\tvoid  SetChannelLoopCount     (uint32 nChannel, uint32 nLoopCount);\n\tbool  GetChannelUsedFlag      (uint32 nChannel);\n\tvoid  StartChannel            (uint32 nChannel);\n\tvoid  StopChannel             (uint32 nChannel);\n\t\n\tvoid  PreloadStreamedFile                                    (uint32 nFile, uint8 nStream);\n\tvoid  PauseStream                                        (uint8 nPauseFlag, uint8 nStream);\n\tvoid  StartPreloadedStreamedFile                                           (uint8 nStream);\n\tbool  StartStreamedFile                         (uint32 nFile, uint32 nPos, uint8 nStream);\n\tvoid  StopStreamedFile                                                     (uint8 nStream);\n\tint32 GetStreamedFilePosition                                              (uint8 nStream);\n\tvoid  SetStreamedVolumeAndPan(uint8 nVolume, uint8 nPan, uint8 nEffectFlag, uint8 nStream);\n\tint32 GetStreamedFileLength                                                (uint8 nStream);\n\tbool  IsStreamPlaying                                                      (uint8 nStream);\n#ifdef AUDIO_OAL\n\tvoid  Service(void);\n#endif\n\tbool  InitialiseSampleBanks(void);\n\n\tuint8 GetMusicVolume() const { return m_nMusicVolume;  }\n\tvoid SetStreamedFileLoopFlag(uint8 nLoopFlag, uint8 nStream);\n};\n\nextern cSampleManager SampleManager;\nextern uint32 BankStartOffset[MAX_SFX_BANKS];\n\n#if defined(OPUS_AUDIO_PATHS)\nstatic char StreamedNameTable[][25] = {\n    \"AUDIO\\\\HEAD.OPUS\",    \"AUDIO\\\\CLASS.OPUS\",   \"AUDIO\\\\KJAH.OPUS\",    \"AUDIO\\\\RISE.OPUS\",    \"AUDIO\\\\LIPS.OPUS\",    \"AUDIO\\\\GAME.OPUS\",\n    \"AUDIO\\\\MSX.OPUS\",     \"AUDIO\\\\FLASH.OPUS\",   \"AUDIO\\\\CHAT.OPUS\",    \"AUDIO\\\\HEAD.OPUS\",    \"AUDIO\\\\POLICE.OPUS\",  \"AUDIO\\\\CITY.OPUS\",\n    \"AUDIO\\\\WATER.OPUS\",   \"AUDIO\\\\COMOPEN.OPUS\", \"AUDIO\\\\SUBOPEN.OPUS\", \"AUDIO\\\\JB.OPUS\",      \"AUDIO\\\\BET.OPUS\",     \"AUDIO\\\\L1_LG.OPUS\",\n    \"AUDIO\\\\L2_DSB.OPUS\",  \"AUDIO\\\\L3_DM.OPUS\",   \"AUDIO\\\\L4_PAP.OPUS\",  \"AUDIO\\\\L5_TFB.OPUS\",  \"AUDIO\\\\J0_DM2.OPUS\",  \"AUDIO\\\\J1_LFL.OPUS\",\n    \"AUDIO\\\\J2_KCL.OPUS\",  \"AUDIO\\\\J3_VH.OPUS\",   \"AUDIO\\\\J4_ETH.OPUS\",  \"AUDIO\\\\J5_DST.OPUS\",  \"AUDIO\\\\J6_TBJ.OPUS\",  \"AUDIO\\\\T1_TOL.OPUS\",\n    \"AUDIO\\\\T2_TPU.OPUS\",  \"AUDIO\\\\T3_MAS.OPUS\",  \"AUDIO\\\\T4_TAT.OPUS\",  \"AUDIO\\\\T5_BF.OPUS\",   \"AUDIO\\\\S0_MAS.OPUS\",  \"AUDIO\\\\S1_PF.OPUS\",\n    \"AUDIO\\\\S2_CTG.OPUS\",  \"AUDIO\\\\S3_RTC.OPUS\",  \"AUDIO\\\\S5_LRQ.OPUS\",  \"AUDIO\\\\S4_BDBA.OPUS\", \"AUDIO\\\\S4_BDBB.OPUS\", \"AUDIO\\\\S2_CTG2.OPUS\",\n    \"AUDIO\\\\S4_BDBD.OPUS\", \"AUDIO\\\\S5_LRQB.OPUS\", \"AUDIO\\\\S5_LRQC.OPUS\", \"AUDIO\\\\A1_SSO.OPUS\",  \"AUDIO\\\\A2_PP.OPUS\",   \"AUDIO\\\\A3_SS.OPUS\",\n    \"AUDIO\\\\A4_PDR.OPUS\",  \"AUDIO\\\\A5_K2FT.OPUS\", \"AUDIO\\\\K1_KBO.OPUS\",  \"AUDIO\\\\K2_GIS.OPUS\",  \"AUDIO\\\\K3_DS.OPUS\",   \"AUDIO\\\\K4_SHI.OPUS\",\n    \"AUDIO\\\\K5_SD.OPUS\",   \"AUDIO\\\\R0_PDR2.OPUS\", \"AUDIO\\\\R1_SW.OPUS\",   \"AUDIO\\\\R2_AP.OPUS\",   \"AUDIO\\\\R3_ED.OPUS\",   \"AUDIO\\\\R4_GF.OPUS\",\n    \"AUDIO\\\\R5_PB.OPUS\",   \"AUDIO\\\\R6_MM.OPUS\",   \"AUDIO\\\\D1_STOG.OPUS\", \"AUDIO\\\\D2_KK.OPUS\",   \"AUDIO\\\\D3_ADO.OPUS\",  \"AUDIO\\\\D5_ES.OPUS\",\n    \"AUDIO\\\\D7_MLD.OPUS\",  \"AUDIO\\\\D4_GTA.OPUS\",  \"AUDIO\\\\D4_GTA2.OPUS\", \"AUDIO\\\\D6_STS.OPUS\",  \"AUDIO\\\\A6_BAIT.OPUS\", \"AUDIO\\\\A7_ETG.OPUS\",\n    \"AUDIO\\\\A8_PS.OPUS\",   \"AUDIO\\\\A9_ASD.OPUS\",  \"AUDIO\\\\K4_SHI2.OPUS\", \"AUDIO\\\\C1_TEX.OPUS\",  \"AUDIO\\\\EL_PH1.OPUS\",  \"AUDIO\\\\EL_PH2.OPUS\",\n    \"AUDIO\\\\EL_PH3.OPUS\",  \"AUDIO\\\\EL_PH4.OPUS\",  \"AUDIO\\\\YD_PH1.OPUS\",  \"AUDIO\\\\YD_PH2.OPUS\",  \"AUDIO\\\\YD_PH3.OPUS\",  \"AUDIO\\\\YD_PH4.OPUS\",\n    \"AUDIO\\\\HD_PH1.OPUS\",  \"AUDIO\\\\HD_PH2.OPUS\",  \"AUDIO\\\\HD_PH3.OPUS\",  \"AUDIO\\\\HD_PH4.OPUS\",  \"AUDIO\\\\HD_PH5.OPUS\",  \"AUDIO\\\\MT_PH1.OPUS\",\n    \"AUDIO\\\\MT_PH2.OPUS\",  \"AUDIO\\\\MT_PH3.OPUS\",  \"AUDIO\\\\MT_PH4.OPUS\",  \"AUDIO\\\\MISCOM.OPUS\",  \"AUDIO\\\\END.OPUS\",     \"AUDIO\\\\lib_a1.OPUS\",\n    \"AUDIO\\\\lib_a2.OPUS\",  \"AUDIO\\\\lib_a.OPUS\",   \"AUDIO\\\\lib_b.OPUS\",   \"AUDIO\\\\lib_c.OPUS\",   \"AUDIO\\\\lib_d.OPUS\",   \"AUDIO\\\\l2_a.OPUS\",\n    \"AUDIO\\\\j4t_1.OPUS\",   \"AUDIO\\\\j4t_2.OPUS\",   \"AUDIO\\\\j4t_3.OPUS\",   \"AUDIO\\\\j4t_4.OPUS\",   \"AUDIO\\\\j4_a.OPUS\",    \"AUDIO\\\\j4_b.OPUS\",\n    \"AUDIO\\\\j4_c.OPUS\",    \"AUDIO\\\\j4_d.OPUS\",    \"AUDIO\\\\j4_e.OPUS\",    \"AUDIO\\\\j4_f.OPUS\",    \"AUDIO\\\\j6_1.OPUS\",    \"AUDIO\\\\j6_a.OPUS\",\n    \"AUDIO\\\\j6_b.OPUS\",    \"AUDIO\\\\j6_c.OPUS\",    \"AUDIO\\\\j6_d.OPUS\",    \"AUDIO\\\\t4_a.OPUS\",    \"AUDIO\\\\s1_a.OPUS\",    \"AUDIO\\\\s1_a1.OPUS\",\n    \"AUDIO\\\\s1_b.OPUS\",    \"AUDIO\\\\s1_c.OPUS\",    \"AUDIO\\\\s1_c1.OPUS\",   \"AUDIO\\\\s1_d.OPUS\",    \"AUDIO\\\\s1_e.OPUS\",    \"AUDIO\\\\s1_f.OPUS\",\n    \"AUDIO\\\\s1_g.OPUS\",    \"AUDIO\\\\s1_h.OPUS\",    \"AUDIO\\\\s1_i.OPUS\",    \"AUDIO\\\\s1_j.OPUS\",    \"AUDIO\\\\s1_k.OPUS\",    \"AUDIO\\\\s1_l.OPUS\",\n    \"AUDIO\\\\s3_a.OPUS\",    \"AUDIO\\\\s3_b.OPUS\",    \"AUDIO\\\\el3_a.OPUS\",   \"AUDIO\\\\mf1_a.OPUS\",   \"AUDIO\\\\mf2_a.OPUS\",   \"AUDIO\\\\mf3_a.OPUS\",\n    \"AUDIO\\\\mf3_b.OPUS\",   \"AUDIO\\\\mf3_b1.OPUS\",  \"AUDIO\\\\mf3_c.OPUS\",   \"AUDIO\\\\mf4_a.OPUS\",   \"AUDIO\\\\mf4_b.OPUS\",   \"AUDIO\\\\mf4_c.OPUS\",\n    \"AUDIO\\\\a1_a.OPUS\",    \"AUDIO\\\\a3_a.OPUS\",    \"AUDIO\\\\a5_a.OPUS\",    \"AUDIO\\\\a4_a.OPUS\",    \"AUDIO\\\\a4_b.OPUS\",    \"AUDIO\\\\a4_c.OPUS\",\n    \"AUDIO\\\\a4_d.OPUS\",    \"AUDIO\\\\k1_a.OPUS\",    \"AUDIO\\\\k3_a.OPUS\",    \"AUDIO\\\\r1_a.OPUS\",    \"AUDIO\\\\r2_a.OPUS\",    \"AUDIO\\\\r2_b.OPUS\",\n    \"AUDIO\\\\r2_c.OPUS\",    \"AUDIO\\\\r2_d.OPUS\",    \"AUDIO\\\\r2_e.OPUS\",    \"AUDIO\\\\r2_f.OPUS\",    \"AUDIO\\\\r2_g.OPUS\",    \"AUDIO\\\\r2_h.OPUS\",\n    \"AUDIO\\\\r5_a.OPUS\",    \"AUDIO\\\\r6_a.OPUS\",    \"AUDIO\\\\r6_a1.OPUS\",   \"AUDIO\\\\r6_b.OPUS\",    \"AUDIO\\\\lo2_a.OPUS\",   \"AUDIO\\\\lo6_a.OPUS\",\n    \"AUDIO\\\\yd2_a.OPUS\",   \"AUDIO\\\\yd2_b.OPUS\",   \"AUDIO\\\\yd2_c.OPUS\",   \"AUDIO\\\\yd2_c1.OPUS\",  \"AUDIO\\\\yd2_d.OPUS\",   \"AUDIO\\\\yd2_e.OPUS\",\n    \"AUDIO\\\\yd2_f.OPUS\",   \"AUDIO\\\\yd2_g.OPUS\",   \"AUDIO\\\\yd2_h.OPUS\",   \"AUDIO\\\\yd2_ass.OPUS\", \"AUDIO\\\\yd2_ok.OPUS\",  \"AUDIO\\\\h5_a.OPUS\",\n    \"AUDIO\\\\h5_b.OPUS\",    \"AUDIO\\\\h5_c.OPUS\",    \"AUDIO\\\\ammu_a.OPUS\",  \"AUDIO\\\\ammu_b.OPUS\",  \"AUDIO\\\\ammu_c.OPUS\",  \"AUDIO\\\\door_1.OPUS\",\n    \"AUDIO\\\\door_2.OPUS\",  \"AUDIO\\\\door_3.OPUS\",  \"AUDIO\\\\door_4.OPUS\",  \"AUDIO\\\\door_5.OPUS\",  \"AUDIO\\\\door_6.OPUS\",  \"AUDIO\\\\t3_a.OPUS\",\n    \"AUDIO\\\\t3_b.OPUS\",    \"AUDIO\\\\t3_c.OPUS\",    \"AUDIO\\\\k1_b.OPUS\",    \"AUDIO\\\\cat1.OPUS\"};\n#elif defined(PS2_AUDIO_PATHS)\nstatic char StreamedNameTable[][40] =\n{\n\t\"AUDIO\\\\MUSIC\\\\WILD.VB\",\n\t\"AUDIO\\\\MUSIC\\\\FLASH.VB\",\n\t\"AUDIO\\\\MUSIC\\\\KCHAT.VB\", // 16 khz\n\t\"AUDIO\\\\MUSIC\\\\FEVER.VB\",\n\t\"AUDIO\\\\MUSIC\\\\VROCK.VB\",\n\t\"AUDIO\\\\MUSIC\\\\VCPR.VB\", // 16 khz\n\t\"AUDIO\\\\MUSIC\\\\ESPANT.VB\",\n\t\"AUDIO\\\\MUSIC\\\\EMOTION.VB\",\n\t\"AUDIO\\\\MUSIC\\\\WAVE.VB\",\n\t\"AUDIO\\\\MUSIC\\\\MISCOM.VB\",\n\t\"AUDIO\\\\MUSIC\\\\CITY.VB\",\n\t\"AUDIO\\\\MUSIC\\\\WATER.VB\",\n\t\"AUDIO\\\\MUSIC\\\\BEACHAMB.VB\",\n\t\"AUDIO\\\\MUSIC\\\\HCITY.VB\",\n\t\"AUDIO\\\\MUSIC\\\\HWATER.VB\",\n\t\"AUDIO\\\\MUSIC\\\\HBEACH.VB\",\n\t\"AUDIO\\\\MUSIC\\\\MALLAMB.VB\",\n\t\"AUDIO\\\\MUSIC\\\\STRIP.VB\",\n\t\"AUDIO\\\\MUSIC\\\\MALIBU.VB\",\n\t\"AUDIO\\\\MUSIC\\\\HOTEL.VB\",\n\t\"AUDIO\\\\MUSIC\\\\DIRTRING.VB\",\n\t\"AUDIO\\\\MUSIC\\\\LAW4RIOT.VB\",\n\t\"AUDIO\\\\MUSIC\\\\AMBSIL.VB\",\n\t\"AUDIO\\\\MUSIC\\\\POLICE.VB\", // 16 khz\n\t\"AUDIO\\\\MUSIC\\\\TAXI.VB\",\n\t\"AUDIO\\\\MUSIC\\\\BCLOSED.VB\",\n\t\"AUDIO\\\\MUSIC\\\\BOPEN.VB\",\n\t\"AUDIO\\\\CUTSCENE\\\\ASS\\\\ASS_1.VB\",\n\t\"AUDIO\\\\CUTSCENE\\\\ASS\\\\ASS_2.VB\",\n\t\"AUDIO\\\\CUTSCENE\\\\BANK\\\\BANK_1.VB\",\n\t\"AUDIO\\\\CUTSCENE\\\\BANK\\\\BANK_2A.VB\",\n\t\"AUDIO\\\\CUTSCENE\\\\BANK\\\\BANK_2B.VB\",\n\t\"AUDIO\\\\CUTSCENE\\\\BANK\\\\BANK_3A.VB\",\n\t\"AUDIO\\\\CUTSCENE\\\\BANK\\\\BANK_3B.VB\",\n\t\"AUDIO\\\\CUTSCENE\\\\BANK\\\\BANK_4.VB\",\n\t\"AUDIO\\\\CUTSCENE\\\\BIKE\\\\BIKE_1.VB\",\n\t\"AUDIO\\\\CUTSCENE\\\\BIKE\\\\BIKE_2.VB\",\n\t\"AUDIO\\\\CUTSCENE\\\\BIKE\\\\BIKE_3.VB\",\n\t\"AUDIO\\\\CUTSCENE\\\\BUD\\\\BUD_1.VB\",\n\t\"AUDIO\\\\CUTSCENE\\\\BUD\\\\BUD_2.VB\",\n\t\"AUDIO\\\\CUTSCENE\\\\BUD\\\\BUD_3.VB\",\n\t\"AUDIO\\\\CUTSCENE\\\\CAP\\\\CAP_1.VB\",\n\t\"AUDIO\\\\CUTSCENE\\\\CAR\\\\CAR_1.VB\",\n\t\"AUDIO\\\\CUTSCENE\\\\CNT\\\\CNT_1A.VB\",\n\t\"AUDIO\\\\CUTSCENE\\\\CNT\\\\CNT_1B.VB\",\n\t\"AUDIO\\\\CUTSCENE\\\\CNT\\\\CNT_2.VB\",\n\t\"AUDIO\\\\CUTSCENE\\\\COK\\\\COK_1.VB\",\n\t\"AUDIO\\\\CUTSCENE\\\\COK\\\\COK_2A.VB\",\n\t\"AUDIO\\\\CUTSCENE\\\\COK\\\\COK_2B.VB\",\n\t\"AUDIO\\\\CUTSCENE\\\\COK\\\\COK_3.VB\",\n\t\"AUDIO\\\\CUTSCENE\\\\COK\\\\COK_4A.VB\",\n\t\"AUDIO\\\\CUTSCENE\\\\COK\\\\COK_4A2.VB\",\n\t\"AUDIO\\\\CUTSCENE\\\\COK\\\\COK_4B.VB\",\n\t\"AUDIO\\\\CUTSCENE\\\\COL\\\\COL_1.VB\",\n\t\"AUDIO\\\\CUTSCENE\\\\COL\\\\COL_2.VB\",\n\t\"AUDIO\\\\CUTSCENE\\\\COL\\\\COL_3A.VB\",\n\t\"AUDIO\\\\CUTSCENE\\\\COL\\\\COL_4A.VB\",\n\t\"AUDIO\\\\CUTSCENE\\\\COL\\\\COL_5A.VB\",\n\t\"AUDIO\\\\CUTSCENE\\\\COL\\\\COL_5B.VB\",\n\t\"AUDIO\\\\CUTSCENE\\\\CUB\\\\CUB_1.VB\",\n\t\"AUDIO\\\\CUTSCENE\\\\CUB\\\\CUB_2.VB\",\n\t\"AUDIO\\\\CUTSCENE\\\\CUB\\\\CUB_3.VB\",\n\t\"AUDIO\\\\CUTSCENE\\\\CUB\\\\CUB_4.VB\",\n\t\"AUDIO\\\\CUTSCENE\\\\DRUG\\\\DRUG_1.VB\",\n\t\"AUDIO\\\\CUTSCENE\\\\FIN\\\\FIN.VB\",\n\t\"AUDIO\\\\CUTSCENE\\\\FIN\\\\FIN2.VB\",\n\t\"AUDIO\\\\CUTSCENE\\\\FINALE\\\\FINALE.VB\",\n\t\"AUDIO\\\\CUTSCENE\\\\HAT\\\\HAT_1.VB\",\n\t\"AUDIO\\\\CUTSCENE\\\\HAT\\\\HAT_2.VB\",\n\t\"AUDIO\\\\CUTSCENE\\\\HAT\\\\HAT_3.VB\",\n\t\"AUDIO\\\\CUTSCENE\\\\ICE\\\\ICE_1.VB\",\n\t\"AUDIO\\\\CUTSCENE\\\\INT\\\\INT_A.VB\",\n\t\"AUDIO\\\\CUTSCENE\\\\INT\\\\INT_B.VB\",\n\t\"AUDIO\\\\CUTSCENE\\\\INT\\\\INT_D.VB\",\n\t\"AUDIO\\\\CUTSCENE\\\\INT\\\\INT_M.VB\",\n\t\"AUDIO\\\\CUTSCENE\\\\LAW\\\\LAW_1A.VB\",\n\t\"AUDIO\\\\CUTSCENE\\\\LAW\\\\LAW_1B.VB\",\n\t\"AUDIO\\\\CUTSCENE\\\\LAW\\\\LAW_2A.VB\",\n\t\"AUDIO\\\\CUTSCENE\\\\LAW\\\\LAW_2B.VB\",\n\t\"AUDIO\\\\CUTSCENE\\\\LAW\\\\LAW_2C.VB\",\n\t\"AUDIO\\\\CUTSCENE\\\\LAW\\\\LAW_3.VB\",\n\t\"AUDIO\\\\CUTSCENE\\\\LAW\\\\LAW_4.VB\",\n\t\"AUDIO\\\\CUTSCENE\\\\PHIL\\\\PHIL_1.VB\",\n\t\"AUDIO\\\\CUTSCENE\\\\PHIL\\\\PHIL_2.VB\",\n\t\"AUDIO\\\\CUTSCENE\\\\PORN\\\\PORN_1.VB\",\n\t\"AUDIO\\\\CUTSCENE\\\\PORN\\\\PORN_2.VB\",\n\t\"AUDIO\\\\CUTSCENE\\\\PORN\\\\PORN_3.VB\",\n\t\"AUDIO\\\\CUTSCENE\\\\PORN\\\\PORN_4.VB\",\n\t\"AUDIO\\\\CUTSCENE\\\\RESC\\\\RESC_1A.VB\",\n\t\"AUDIO\\\\CUTSCENE\\\\ROK\\\\ROK_1.VB\",\n\t\"AUDIO\\\\CUTSCENE\\\\ROK\\\\ROK_2.VB\",\n\t\"AUDIO\\\\CUTSCENE\\\\ROK\\\\ROK_3A.VB\",\n\t\"AUDIO\\\\CUTSCENE\\\\STRIPA\\\\STRIPA.VB\",\n\t\"AUDIO\\\\CUTSCENE\\\\TAX\\\\TAX_1.VB\",\n\t\"AUDIO\\\\CUTSCENE\\\\TEX\\\\TEX_1.VB\",\n\t\"AUDIO\\\\CUTSCENE\\\\TEX\\\\TEX_2.VB\",\n\t\"AUDIO\\\\CUTSCENE\\\\TEX\\\\TEX_3.VB\",\n\t\"AUDIO\\\\MUSIC\\\\GLIGHT.VB\",\n\t\"AUDIO\\\\MUSIC\\\\FIST.VB\",\n\t\"AUDIO\\\\MUSIC\\\\MISCOM.VB\",\n\t\"AUDIO\\\\MUSIC\\\\MISCOM.VB\",\n\t\"AUDIO\\\\MUSIC\\\\MISCOM.VB\",\n\t\"AUDIO\\\\MUSIC\\\\MISCOM.VB\",\n#else\nstatic char StreamedNameTable[][25] =\n{\n\t\"AUDIO\\\\WILD.ADF\",\n\t\"AUDIO\\\\FLASH.ADF\",\n\t\"AUDIO\\\\KCHAT.ADF\",\n\t\"AUDIO\\\\FEVER.ADF\",\n\t\"AUDIO\\\\VROCK.ADF\",\n\t\"AUDIO\\\\VCPR.ADF\",\n\t\"AUDIO\\\\ESPANT.ADF\",\n\t\"AUDIO\\\\EMOTION.ADF\",\n\t\"AUDIO\\\\WAVE.ADF\",\n\t\"AUDIO\\\\MISCOM.MP3\",\n\t\"AUDIO\\\\CITY.MP3\",\n\t\"AUDIO\\\\WATER.MP3\",\n\t\"AUDIO\\\\BEACHAMB.MP3\",\n\t\"AUDIO\\\\HCITY.MP3\",\n\t\"AUDIO\\\\HWATER.MP3\",\n\t\"AUDIO\\\\HBEACH.MP3\",\n\t\"AUDIO\\\\MALLAMB.MP3\",\n\t\"AUDIO\\\\STRIP.MP3\",\n\t\"AUDIO\\\\MALIBU.MP3\",\n\t\"AUDIO\\\\HOTEL.MP3\",\n\t\"AUDIO\\\\DIRTRING.MP3\",\n\t\"AUDIO\\\\LAW4RIOT.MP3\",\n\t\"AUDIO\\\\AMBSIL.MP3\",\n\t\"AUDIO\\\\POLICE.MP3\",\n\t\"AUDIO\\\\TAXI.MP3\",\n\t\"AUDIO\\\\BCLOSED.MP3\",\n\t\"AUDIO\\\\BOPEN.MP3\",\n\t\"AUDIO\\\\ASS_1.MP3\",\n\t\"AUDIO\\\\ASS_2.MP3\",\n\t\"AUDIO\\\\BANK_1.MP3\",\n\t\"AUDIO\\\\BANK_2A.MP3\",\n\t\"AUDIO\\\\BANK_2B.MP3\",\n\t\"AUDIO\\\\BANK_3A.MP3\",\n\t\"AUDIO\\\\BANK_3B.MP3\",\n\t\"AUDIO\\\\BANK_4.MP3\",\n\t\"AUDIO\\\\BIKE_1.MP3\",\n\t\"AUDIO\\\\BIKE_2.MP3\",\n\t\"AUDIO\\\\BIKE_3.MP3\",\n\t\"AUDIO\\\\BUD_1.MP3\",\n\t\"AUDIO\\\\BUD_2.MP3\",\n\t\"AUDIO\\\\BUD_3.MP3\",\n\t\"AUDIO\\\\CAP_1.MP3\",\n\t\"AUDIO\\\\CAR_1.MP3\",\n\t\"AUDIO\\\\CNT_1A.MP3\",\n\t\"AUDIO\\\\CNT_1B.MP3\",\n\t\"AUDIO\\\\CNT_2.MP3\",\n\t\"AUDIO\\\\COK_1.MP3\",\n\t\"AUDIO\\\\COK_2A.MP3\",\n\t\"AUDIO\\\\COK_2B.MP3\",\n\t\"AUDIO\\\\COK_3.MP3\",\n\t\"AUDIO\\\\COK_4A.MP3\",\n\t\"AUDIO\\\\COK_4A2.MP3\",\n\t\"AUDIO\\\\COK_4B.MP3\",\n\t\"AUDIO\\\\COL_1.MP3\",\n\t\"AUDIO\\\\COL_2.MP3\",\n\t\"AUDIO\\\\COL_3A.MP3\",\n\t\"AUDIO\\\\COL_4A.MP3\",\n\t\"AUDIO\\\\COL_5A.MP3\",\n\t\"AUDIO\\\\COL_5B.MP3\",\n\t\"AUDIO\\\\CUB_1.MP3\",\n\t\"AUDIO\\\\CUB_2.MP3\",\n\t\"AUDIO\\\\CUB_3.MP3\",\n\t\"AUDIO\\\\CUB_4.MP3\",\n\t\"AUDIO\\\\DRUG_1.MP3\",\n\t\"AUDIO\\\\FIN.MP3\",\n\t\"AUDIO\\\\FIN2.MP3\",\n\t\"AUDIO\\\\FINALE.MP3\",\n\t\"AUDIO\\\\HAT_1.MP3\",\n\t\"AUDIO\\\\HAT_2.MP3\",\n\t\"AUDIO\\\\HAT_3.MP3\",\n\t\"AUDIO\\\\ICE_1.MP3\",\n\t\"AUDIO\\\\INT_A.MP3\",\n\t\"AUDIO\\\\INT_B.MP3\",\n\t\"AUDIO\\\\INT_D.MP3\",\n\t\"AUDIO\\\\INT_M.MP3\",\n\t\"AUDIO\\\\LAW_1A.MP3\",\n\t\"AUDIO\\\\LAW_1B.MP3\",\n\t\"AUDIO\\\\LAW_2A.MP3\",\n\t\"AUDIO\\\\LAW_2B.MP3\",\n\t\"AUDIO\\\\LAW_2C.MP3\",\n\t\"AUDIO\\\\LAW_3.MP3\",\n\t\"AUDIO\\\\LAW_4.MP3\",\n\t\"AUDIO\\\\PHIL_1.MP3\",\n\t\"AUDIO\\\\PHIL_2.MP3\",\n\t\"AUDIO\\\\PORN_1.MP3\",\n\t\"AUDIO\\\\PORN_2.MP3\",\n\t\"AUDIO\\\\PORN_3.MP3\",\n\t\"AUDIO\\\\PORN_4.MP3\",\n\t\"AUDIO\\\\RESC_1A.MP3\",\n\t\"AUDIO\\\\ROK_1.MP3\",\n\t\"AUDIO\\\\ROK_2.MP3\",\n\t\"AUDIO\\\\ROK_3A.MP3\",\n\t\"AUDIO\\\\STRIPA.MP3\",\n\t\"AUDIO\\\\TAX_1.MP3\",\n\t\"AUDIO\\\\TEX_1.MP3\",\n\t\"AUDIO\\\\TEX_2.MP3\",\n\t\"AUDIO\\\\TEX_3.MP3\",\n\t\"AUDIO\\\\GLIGHT.MP3\",\n\t\"AUDIO\\\\FIST.MP3\",\n\t\"AUDIO\\\\MISCOM.MP3\",\n\t\"AUDIO\\\\MISCOM.MP3\",\n\t\"AUDIO\\\\MISCOM.MP3\",\n\t\"AUDIO\\\\MISCOM.MP3\",\n#endif\n\t\"AUDIO\\\\MOBR1.WAV\",\n\t\"AUDIO\\\\PAGER.WAV\",\n\t\"AUDIO\\\\CARREV.WAV\",\n\t\"AUDIO\\\\BIKEREV.WAV\",\n\t\"AUDIO\\\\LIFTOP.WAV\",\n\t\"AUDIO\\\\LIFTCL.WAV\",\n\t\"AUDIO\\\\LIFTRUN.WAV\",\n\t\"AUDIO\\\\LIFTBEL.WAV\",\n\t\"AUDIO\\\\INLIFT.WAV\",\n\t\"AUDIO\\\\SFX_01.WAV\",\n\t\"AUDIO\\\\SFX_02.WAV\",\n\t\"AUDIO\\\\CAMERAL.WAV\",\n\t\"AUDIO\\\\CAMERAR.WAV\",\n\t\"AUDIO\\\\CHEER1.WAV\",\n\t\"AUDIO\\\\CHEER2.WAV\",\n\t\"AUDIO\\\\CHEER3.WAV\",\n\t\"AUDIO\\\\CHEER4.WAV\",\n\t\"AUDIO\\\\OOH1.WAV\",\n\t\"AUDIO\\\\OOH2.WAV\",\n\t\"AUDIO\\\\RACE1.WAV\",\n\t\"AUDIO\\\\RACE2.WAV\",\n\t\"AUDIO\\\\RACE3.WAV\",\n\t\"AUDIO\\\\RACE4.WAV\",\n\t\"AUDIO\\\\RACE5.WAV\",\n\t\"AUDIO\\\\RACE6.WAV\",\n\t\"AUDIO\\\\RACE7.WAV\",\n\t\"AUDIO\\\\RACE8.WAV\",\n\t\"AUDIO\\\\RACE9.WAV\",\n\t\"AUDIO\\\\RACE10.WAV\",\n\t\"AUDIO\\\\RACE11.WAV\",\n\t\"AUDIO\\\\RACE12.WAV\",\n\t\"AUDIO\\\\RACE13.WAV\",\n\t\"AUDIO\\\\RACE14.WAV\",\n\t\"AUDIO\\\\RACE15.WAV\",\n\t\"AUDIO\\\\HOT1.WAV\",\n\t\"AUDIO\\\\HOT2.WAV\",\n\t\"AUDIO\\\\HOT3.WAV\",\n\t\"AUDIO\\\\HOT4.WAV\",\n\t\"AUDIO\\\\HOT5.WAV\",\n\t\"AUDIO\\\\HOT6.WAV\",\n\t\"AUDIO\\\\HOT7.WAV\",\n\t\"AUDIO\\\\HOT8.WAV\",\n\t\"AUDIO\\\\HOT9.WAV\",\n\t\"AUDIO\\\\HOT10.WAV\",\n\t\"AUDIO\\\\HOT11.WAV\",\n\t\"AUDIO\\\\HOT12.WAV\",\n\t\"AUDIO\\\\HOT13.WAV\",\n\t\"AUDIO\\\\HOT14.WAV\",\n\t\"AUDIO\\\\HOT15.WAV\",\n\t\"AUDIO\\\\LANSTP1.WAV\",\n\t\"AUDIO\\\\LANSTP2.WAV\",\n\t\"AUDIO\\\\LANAMU1.WAV\",\n\t\"AUDIO\\\\LANAMU2.WAV\",\n\t\"AUDIO\\\\AIRHORNL.WAV\",\n\t\"AUDIO\\\\AIRHORNR.WAV\",\n\t\"AUDIO\\\\SNIPSCRL.WAV\",\n\t\"AUDIO\\\\SNIPSHORT.WAV\",\n\t\"AUDIO\\\\BLOWROOF.WAV\",\n\t\"AUDIO\\\\ASS_1.WAV\",\n\t\"AUDIO\\\\ASS_2.WAV\",\n\t\"AUDIO\\\\ASS_3.WAV\",\n\t\"AUDIO\\\\ASS_4.WAV\",\n\t\"AUDIO\\\\ASS_5.WAV\",\n\t\"AUDIO\\\\ASS_6.WAV\",\n\t\"AUDIO\\\\ASS_7.WAV\",\n\t\"AUDIO\\\\ASS_8.WAV\",\n\t\"AUDIO\\\\ASS_9.WAV\",\n\t\"AUDIO\\\\ASS_10.WAV\",\n\t\"AUDIO\\\\ASS_11.WAV\",\n\t\"AUDIO\\\\ASS_12.WAV\",\n\t\"AUDIO\\\\ASS_13.WAV\",\n\t\"AUDIO\\\\ASS_14.WAV\",\n\t\"AUDIO\\\\BIKE1_1.WAV\",\n\t\"AUDIO\\\\BIKE1_2.WAV\",\n\t\"AUDIO\\\\BIKE1_3.WAV\",\n\t\"AUDIO\\\\BNK1_1.WAV\",\n\t\"AUDIO\\\\BNK1_2.WAV\",\n\t\"AUDIO\\\\BNK1_3.WAV\",\n\t\"AUDIO\\\\BNK1_4.WAV\",\n\t\"AUDIO\\\\BNK1_5.WAV\",\n\t\"AUDIO\\\\BNK1_6.WAV\",\n\t\"AUDIO\\\\BNK1_7.WAV\",\n\t\"AUDIO\\\\BNK1_8.WAV\",\n\t\"AUDIO\\\\BNK1_10.WAV\",\n\t\"AUDIO\\\\BNK1_11.WAV\",\n\t\"AUDIO\\\\BNK1_12.WAV\",\n\t\"AUDIO\\\\BNK1_13.WAV\",\n\t\"AUDIO\\\\BNK1_14.WAV\",\n\t\"AUDIO\\\\BNK2_1.WAV\",\n\t\"AUDIO\\\\BNK2_2.WAV\",\n\t\"AUDIO\\\\BNK2_3.WAV\",\n\t\"AUDIO\\\\BNK2_4.WAV\",\n\t\"AUDIO\\\\BNK2_5.WAV\",\n\t\"AUDIO\\\\BNK2_6.WAV\",\n\t\"AUDIO\\\\BNK2_7.WAV\",\n\t\"AUDIO\\\\BNK2_8.WAV\",\n\t\"AUDIO\\\\BNK2_9.WAV\",\n\t\"AUDIO\\\\BNK3_1.WAV\",\n\t\"AUDIO\\\\BNK3_2.WAV\",\n\t\"AUDIO\\\\BNK3_3A.WAV\",\n\t\"AUDIO\\\\BNK3_3B.WAV\",\n\t\"AUDIO\\\\BNK3_3C.WAV\",\n\t\"AUDIO\\\\BNK3_4A.WAV\",\n\t\"AUDIO\\\\BNK3_4B.WAV\",\n\t\"AUDIO\\\\BNK3_4C.WAV\",\n\t\"AUDIO\\\\BNK4_1.WAV\",\n\t\"AUDIO\\\\BNK4_2.WAV\",\n\t\"AUDIO\\\\BNK4_3A.WAV\",\n\t\"AUDIO\\\\BNK4_3B.WAV\",\n\t\"AUDIO\\\\BNK4_3C.WAV\",\n\t\"AUDIO\\\\BNK4_3D.WAV\",\n\t\"AUDIO\\\\BNK4_3E.WAV\",\n\t\"AUDIO\\\\BNK4_3F.WAV\",\n\t\"AUDIO\\\\BNK4_3G.WAV\",\n\t\"AUDIO\\\\BNK4_3H.WAV\",\n\t\"AUDIO\\\\BNK4_3I.WAV\",\n\t\"AUDIO\\\\BNK4_3J.WAV\",\n\t\"AUDIO\\\\BNK4_3K.WAV\",\n\t\"AUDIO\\\\BNK4_3M.WAV\",\n\t\"AUDIO\\\\BNK4_3O.WAV\",\n\t\"AUDIO\\\\BNK4_3P.WAV\",\n\t\"AUDIO\\\\BNK4_3Q.WAV\",\n\t\"AUDIO\\\\BNK4_3R.WAV\",\n\t\"AUDIO\\\\BNK4_3S.WAV\",\n\t\"AUDIO\\\\BNK4_3T.WAV\",\n\t\"AUDIO\\\\BNK4_3U.WAV\",\n\t\"AUDIO\\\\BNK4_3V.WAV\",\n\t\"AUDIO\\\\BNK4_4A.WAV\",\n\t\"AUDIO\\\\BNK4_4B.WAV\",\n\t\"AUDIO\\\\BNK4_5.WAV\",\n\t\"AUDIO\\\\BNK4_6.WAV\",\n\t\"AUDIO\\\\BNK4_7.WAV\",\n\t\"AUDIO\\\\BNK4_8.WAV\",\n\t\"AUDIO\\\\BNK4_9.WAV\",\n\t\"AUDIO\\\\BNK4_10.WAV\",\n\t\"AUDIO\\\\BNK4_11.WAV\",\n\t\"AUDIO\\\\BK4_12A.WAV\",\n\t\"AUDIO\\\\BK4_12B.WAV\",\n\t\"AUDIO\\\\BK4_12C.WAV\",\n\t\"AUDIO\\\\BNK4_13.WAV\",\n\t\"AUDIO\\\\BK4_14A.WAV\",\n\t\"AUDIO\\\\BK4_14B.WAV\",\n\t\"AUDIO\\\\BNK4_15.WAV\",\n\t\"AUDIO\\\\BNK4_16.WAV\",\n\t\"AUDIO\\\\BNK4_17.WAV\",\n\t\"AUDIO\\\\BNK4_18.WAV\",\n\t\"AUDIO\\\\BK4_19A.WAV\",\n\t\"AUDIO\\\\BK4_19B.WAV\",\n\t\"AUDIO\\\\BK4_20A.WAV\",\n\t\"AUDIO\\\\BK4_20B.WAV\",\n\t\"AUDIO\\\\BNK4_21.WAV\",\n\t\"AUDIO\\\\BNK422A.WAV\",\n\t\"AUDIO\\\\BNK422B.WAV\",\n\t\"AUDIO\\\\BK4_23A.WAV\",\n\t\"AUDIO\\\\BK4_23B.WAV\",\n\t\"AUDIO\\\\BK4_23C.WAV\",\n\t\"AUDIO\\\\BK4_23D.WAV\",\n\t\"AUDIO\\\\BK4_24A.WAV\",\n\t\"AUDIO\\\\BK4_24B.WAV\",\n\t\"AUDIO\\\\BNK4_25.WAV\",\n\t\"AUDIO\\\\BNK4_26.WAV\",\n\t\"AUDIO\\\\BNK4_27.WAV\",\n\t\"AUDIO\\\\BNK4_28.WAV\",\n\t\"AUDIO\\\\BNK4_29.WAV\",\n\t\"AUDIO\\\\BNK4_30.WAV\",\n\t\"AUDIO\\\\BK4_31A.WAV\",\n\t\"AUDIO\\\\BK4_31B.WAV\",\n\t\"AUDIO\\\\BNK4_32.WAV\",\n\t\"AUDIO\\\\BK4_34A.WAV\",\n\t\"AUDIO\\\\BK4_34B.WAV\",\n\t\"AUDIO\\\\BK4_35A.WAV\",\n\t\"AUDIO\\\\BK4_35B.WAV\",\n\t\"AUDIO\\\\BNK4_36.WAV\",\n\t\"AUDIO\\\\BNK4_37.WAV\",\n\t\"AUDIO\\\\BNK4_38.WAV\",\n\t\"AUDIO\\\\BNK4_39.WAV\",\n\t\"AUDIO\\\\BK4_40A.WAV\",\n\t\"AUDIO\\\\BK4_40B.WAV\",\n\t\"AUDIO\\\\BNK4_41.WAV\",\n\t\"AUDIO\\\\BNK4_42.WAV\",\n\t\"AUDIO\\\\BNK4_43.WAV\",\n\t\"AUDIO\\\\BNK4_44.WAV\",\n\t\"AUDIO\\\\BNK4_45.WAV\",\n\t\"AUDIO\\\\BNK4_46.WAV\",\n\t\"AUDIO\\\\BNK4_47.WAV\",\n\t\"AUDIO\\\\BNK4_48.WAV\",\n\t\"AUDIO\\\\BNK4_49.WAV\",\n\t\"AUDIO\\\\BNK450A.WAV\",\n\t\"AUDIO\\\\BNK450B.WAV\",\n\t\"AUDIO\\\\BNK4_51.WAV\",\n\t\"AUDIO\\\\BNK4_94.WAV\",\n\t\"AUDIO\\\\BNK4_95.WAV\",\n\t\"AUDIO\\\\BNK4_96.WAV\",\n\t\"AUDIO\\\\BNK4_97.WAV\",\n\t\"AUDIO\\\\BNK4_98.WAV\",\n\t\"AUDIO\\\\BNK4_99.WAV\",\n\t\"AUDIO\\\\BUD1_1.WAV\",\n\t\"AUDIO\\\\BUD1_2.WAV\",\n\t\"AUDIO\\\\BUD1_3.WAV\",\n\t\"AUDIO\\\\BUD1_4.WAV\",\n\t\"AUDIO\\\\BUD1_5.WAV\",\n\t\"AUDIO\\\\BUD1_9.WAV\",\n\t\"AUDIO\\\\BUD1_10.WAV\",\n\t\"AUDIO\\\\BUD2_1.WAV\",\n\t\"AUDIO\\\\BUD2_2.WAV\",\n\t\"AUDIO\\\\BUD2_3.WAV\",\n\t\"AUDIO\\\\BUD2_4.WAV\",\n\t\"AUDIO\\\\BUD2_5.WAV\",\n\t\"AUDIO\\\\BUD2_6.WAV\",\n\t\"AUDIO\\\\BUD2_7.WAV\",\n\t\"AUDIO\\\\BUD3_1.WAV\",\n\t\"AUDIO\\\\BUD3_1A.WAV\",\n\t\"AUDIO\\\\BUD3_1B.WAV\",\n\t\"AUDIO\\\\BUD3_1C.WAV\",\n\t\"AUDIO\\\\BUD3_2.WAV\",\n\t\"AUDIO\\\\BUD3_3.WAV\",\n\t\"AUDIO\\\\BUD3_4.WAV\",\n\t\"AUDIO\\\\BUD3_5.WAV\",\n\t\"AUDIO\\\\BUD3_6.WAV\",\n\t\"AUDIO\\\\BUD3_7.WAV\",\n\t\"AUDIO\\\\BUD3_8A.WAV\",\n\t\"AUDIO\\\\BUD3_8B.WAV\",\n\t\"AUDIO\\\\BUD3_8C.WAV\",\n\t\"AUDIO\\\\BUD3_9A.WAV\",\n\t\"AUDIO\\\\BUD3_9B.WAV\",\n\t\"AUDIO\\\\BUD3_9C.WAV\",\n\t\"AUDIO\\\\CAP1_2.WAV\",\n\t\"AUDIO\\\\CAP1_3.WAV\",\n\t\"AUDIO\\\\CAP1_4.WAV\",\n\t\"AUDIO\\\\CAP1_5.WAV\",\n\t\"AUDIO\\\\CAP1_6.WAV\",\n\t\"AUDIO\\\\CAP1_7.WAV\",\n\t\"AUDIO\\\\CAP1_8.WAV\",\n\t\"AUDIO\\\\CAP1_9.WAV\",\n\t\"AUDIO\\\\CAP1_10.WAV\",\n\t\"AUDIO\\\\CAP1_11.WAV\",\n\t\"AUDIO\\\\CAP1_12.WAV\",\n\t\"AUDIO\\\\CNT1_1.WAV\",\n\t\"AUDIO\\\\CNT1_2.WAV\",\n\t\"AUDIO\\\\CNT1_3.WAV\",\n\t\"AUDIO\\\\CNT1_4.WAV\",\n\t\"AUDIO\\\\CNT1_5.WAV\",\n\t\"AUDIO\\\\CNT2_1.WAV\",\n\t\"AUDIO\\\\CNT2_2.WAV\",\n\t\"AUDIO\\\\CNT2_3.WAV\",\n\t\"AUDIO\\\\CNT2_4.WAV\",\n\t\"AUDIO\\\\COK1_1.WAV\",\n\t\"AUDIO\\\\COK1_2.WAV\",\n\t\"AUDIO\\\\COK1_3.WAV\",\n\t\"AUDIO\\\\COK1_4.WAV\",\n\t\"AUDIO\\\\COK1_5.WAV\",\n\t\"AUDIO\\\\COK1_6.WAV\",\n\t\"AUDIO\\\\COK2_1.WAV\",\n\t\"AUDIO\\\\COK2_2.WAV\",\n\t\"AUDIO\\\\COK2_3.WAV\",\n\t\"AUDIO\\\\COK2_4.WAV\",\n\t\"AUDIO\\\\COK2_5.WAV\",\n\t\"AUDIO\\\\COK2_6.WAV\",\n\t\"AUDIO\\\\COK2_7A.WAV\",\n\t\"AUDIO\\\\COK2_7B.WAV\",\n\t\"AUDIO\\\\COK2_7C.WAV\",\n\t\"AUDIO\\\\COK2_8A.WAV\",\n\t\"AUDIO\\\\COK2_8B.WAV\",\n\t\"AUDIO\\\\COK2_8C.WAV\",\n\t\"AUDIO\\\\COK2_8D.WAV\",\n\t\"AUDIO\\\\COK2_9.WAV\",\n\t\"AUDIO\\\\COK210A.WAV\",\n\t\"AUDIO\\\\COK210B.WAV\",\n\t\"AUDIO\\\\COK210C.WAV\",\n\t\"AUDIO\\\\COK212A.WAV\",\n\t\"AUDIO\\\\COK212B.WAV\",\n\t\"AUDIO\\\\COK2_13.WAV\",\n\t\"AUDIO\\\\COK2_14.WAV\",\n\t\"AUDIO\\\\COK2_15.WAV\",\n\t\"AUDIO\\\\COK2_16.WAV\",\n\t\"AUDIO\\\\COK2_20.WAV\",\n\t\"AUDIO\\\\COK2_21.WAV\",\n\t\"AUDIO\\\\COK2_2.WAV\", // this is probably a typo of COK2_22\n\t\"AUDIO\\\\COK3_1.WAV\",\n\t\"AUDIO\\\\COK3_2.WAV\",\n\t\"AUDIO\\\\COK3_3.WAV\",\n\t\"AUDIO\\\\COK3_4.WAV\",\n\t\"AUDIO\\\\COK4_1.WAV\",\n\t\"AUDIO\\\\COK4_2.WAV\",\n\t\"AUDIO\\\\COK4_3.WAV\",\n\t\"AUDIO\\\\COK4_4.WAV\",\n\t\"AUDIO\\\\COK4_5.WAV\",\n\t\"AUDIO\\\\COK4_6.WAV\",\n\t\"AUDIO\\\\COK4_7.WAV\",\n\t\"AUDIO\\\\COK4_8.WAV\",\n\t\"AUDIO\\\\COK4_9.WAV\",\n\t\"AUDIO\\\\COK4_9A.WAV\",\n\t\"AUDIO\\\\COK4_10.WAV\",\n\t\"AUDIO\\\\COK4_11.WAV\",\n\t\"AUDIO\\\\COK4_12.WAV\",\n\t\"AUDIO\\\\COK4_13.WAV\",\n\t\"AUDIO\\\\COK4_14.WAV\",\n\t\"AUDIO\\\\COK4_15.WAV\",\n\t\"AUDIO\\\\COK4_16.WAV\",\n\t\"AUDIO\\\\COK4_17.WAV\",\n\t\"AUDIO\\\\COK4_18.WAV\",\n\t\"AUDIO\\\\COK4_19.WAV\",\n\t\"AUDIO\\\\COK4_20.WAV\",\n\t\"AUDIO\\\\COK4_21.WAV\",\n\t\"AUDIO\\\\COK4_22.WAV\",\n\t\"AUDIO\\\\COK4_23.WAV\",\n\t\"AUDIO\\\\COK4_24.WAV\",\n\t\"AUDIO\\\\COK4_25.WAV\",\n\t\"AUDIO\\\\COK4_26.WAV\",\n\t\"AUDIO\\\\COK4_27.WAV\",\n\t\"AUDIO\\\\COL1_1.WAV\",\n\t\"AUDIO\\\\COL1_2.WAV\",\n\t\"AUDIO\\\\COL1_3.WAV\",\n\t\"AUDIO\\\\COL1_4.WAV\",\n\t\"AUDIO\\\\COL1_5.WAV\",\n\t\"AUDIO\\\\COL1_6.WAV\",\n\t\"AUDIO\\\\COL1_7.WAV\",\n\t\"AUDIO\\\\COL1_8.WAV\",\n\t\"AUDIO\\\\COL2_1.WAV\",\n\t\"AUDIO\\\\COL2_2.WAV\",\n\t\"AUDIO\\\\COL2_3.WAV\",\n\t\"AUDIO\\\\COL2_4.WAV\",\n\t\"AUDIO\\\\COL2_5.WAV\",\n\t\"AUDIO\\\\COL2_6A.WAV\",\n\t\"AUDIO\\\\COL2_7.WAV\",\n\t\"AUDIO\\\\COL2_8.WAV\",\n\t\"AUDIO\\\\COL2_9.WAV\",\n\t\"AUDIO\\\\COL2_10.WAV\",\n\t\"AUDIO\\\\COL2_11.WAV\",\n\t\"AUDIO\\\\COL2_12.WAV\",\n\t\"AUDIO\\\\COL2_13.WAV\",\n\t\"AUDIO\\\\COL2_14.WAV\",\n\t\"AUDIO\\\\COL2_15.WAV\",\n\t\"AUDIO\\\\COL2_16.WAV\",\n\t\"AUDIO\\\\COL3_1.WAV\",\n\t\"AUDIO\\\\COL3_2.WAV\",\n\t\"AUDIO\\\\COL3_2A.WAV\",\n\t\"AUDIO\\\\COL3_2B.WAV\",\n\t\"AUDIO\\\\COL3_3.WAV\",\n\t\"AUDIO\\\\COL3_4.WAV\",\n\t\"AUDIO\\\\COL3_5.WAV\",\n\t\"AUDIO\\\\COL3_6.WAV\",\n\t\"AUDIO\\\\COL3_7.WAV\",\n\t\"AUDIO\\\\COL3_8.WAV\",\n\t\"AUDIO\\\\COL3_9.WAV\",\n\t\"AUDIO\\\\COL3_10.WAV\",\n\t\"AUDIO\\\\COL3_11.WAV\",\n\t\"AUDIO\\\\COL3_12.WAV\",\n\t\"AUDIO\\\\COL3_13.WAV\",\n\t\"AUDIO\\\\COL3_14.WAV\",\n\t\"AUDIO\\\\COL3_15.WAV\",\n\t\"AUDIO\\\\COL3_16.WAV\",\n\t\"AUDIO\\\\COL3_17.WAV\",\n\t\"AUDIO\\\\COL3_18.WAV\",\n\t\"AUDIO\\\\COL3_19.WAV\",\n\t\"AUDIO\\\\COL3_20.WAV\",\n\t\"AUDIO\\\\COL3_21.WAV\",\n\t\"AUDIO\\\\COL3_23.WAV\",\n\t\"AUDIO\\\\COL3_24.WAV\",\n\t\"AUDIO\\\\COL3_25.WAV\",\n\t\"AUDIO\\\\COL4_1.WAV\",\n\t\"AUDIO\\\\COL4_2.WAV\",\n\t\"AUDIO\\\\COL4_3.WAV\",\n\t\"AUDIO\\\\COL4_4.WAV\",\n\t\"AUDIO\\\\COL4_5.WAV\",\n\t\"AUDIO\\\\COL4_6.WAV\",\n\t\"AUDIO\\\\COL4_7.WAV\",\n\t\"AUDIO\\\\COL4_8.WAV\",\n\t\"AUDIO\\\\COL4_9.WAV\",\n\t\"AUDIO\\\\COL4_10.WAV\",\n\t\"AUDIO\\\\COL4_11.WAV\",\n\t\"AUDIO\\\\COL4_12.WAV\",\n\t\"AUDIO\\\\COL4_13.WAV\",\n\t\"AUDIO\\\\COL4_14.WAV\",\n\t\"AUDIO\\\\COL4_15.WAV\",\n\t\"AUDIO\\\\COL4_16.WAV\",\n\t\"AUDIO\\\\COL4_17.WAV\",\n\t\"AUDIO\\\\COL4_18.WAV\",\n\t\"AUDIO\\\\COL4_19.WAV\",\n\t\"AUDIO\\\\COL4_20.WAV\",\n\t\"AUDIO\\\\COL4_21.WAV\",\n\t\"AUDIO\\\\COL4_22.WAV\",\n\t\"AUDIO\\\\COL4_23.WAV\",\n\t\"AUDIO\\\\COL4_24.WAV\",\n\t\"AUDIO\\\\COL4_25.WAV\",\n\t\"AUDIO\\\\COL4_26.WAV\",\n\t\"AUDIO\\\\COL5_1.WAV\",\n\t\"AUDIO\\\\COL5_2.WAV\",\n\t\"AUDIO\\\\COL5_3.WAV\",\n\t\"AUDIO\\\\COL5_4.WAV\",\n\t\"AUDIO\\\\COL5_5.WAV\",\n\t\"AUDIO\\\\COL5_6.WAV\",\n\t\"AUDIO\\\\COL5_7.WAV\",\n\t\"AUDIO\\\\COL5_8.WAV\",\n\t\"AUDIO\\\\COL5_9.WAV\",\n\t\"AUDIO\\\\COL5_10.WAV\",\n\t\"AUDIO\\\\COL5_11.WAV\",\n\t\"AUDIO\\\\COL5_12.WAV\",\n\t\"AUDIO\\\\COL5_13.WAV\",\n\t\"AUDIO\\\\COL5_14.WAV\",\n\t\"AUDIO\\\\COL5_15.WAV\",\n\t\"AUDIO\\\\COL5_16.WAV\",\n\t\"AUDIO\\\\COL5_17.WAV\",\n\t\"AUDIO\\\\COL5_18.WAV\",\n\t\"AUDIO\\\\COL5_19.WAV\",\n\t\"AUDIO\\\\COL5_20.WAV\",\n\t\"AUDIO\\\\COL5_21.WAV\",\n\t\"AUDIO\\\\COL5_22.WAV\",\n\t\"AUDIO\\\\CUB1_1.WAV\",\n\t\"AUDIO\\\\CUB1_2.WAV\",\n\t\"AUDIO\\\\CUB1_3.WAV\",\n\t\"AUDIO\\\\CUB1_4.WAV\",\n\t\"AUDIO\\\\CUB1_5.WAV\",\n\t\"AUDIO\\\\CUB1_6.WAV\",\n\t\"AUDIO\\\\CUB1_7.WAV\",\n\t\"AUDIO\\\\CUB1_8.WAV\",\n\t\"AUDIO\\\\CUB1_9.WAV\",\n\t\"AUDIO\\\\CUB1_10.WAV\",\n\t\"AUDIO\\\\CUB2_1.WAV\",\n\t\"AUDIO\\\\CUB2_2.WAV\",\n\t\"AUDIO\\\\CUB2_3A.WAV\",\n\t\"AUDIO\\\\CUB2_3B.WAV\",\n\t\"AUDIO\\\\CUB2_3C.WAV\",\n\t\"AUDIO\\\\CUB2_4A.WAV\",\n\t\"AUDIO\\\\CUB2_5.WAV\",\n\t\"AUDIO\\\\CUB2_6.WAV\",\n\t\"AUDIO\\\\CUB2_7.WAV\",\n\t\"AUDIO\\\\CUB2_8.WAV\",\n\t\"AUDIO\\\\CUB2_9.WAV\",\n\t\"AUDIO\\\\CUB2_10.WAV\",\n\t\"AUDIO\\\\CUB2_11.WAV\",\n\t\"AUDIO\\\\CUB3_1.WAV\",\n\t\"AUDIO\\\\CUB3_2.WAV\",\n\t\"AUDIO\\\\CUB3_3.WAV\",\n\t\"AUDIO\\\\CUB3_4.WAV\",\n\t\"AUDIO\\\\CUB4_1.WAV\",\n\t\"AUDIO\\\\CUB4_2.WAV\",\n\t\"AUDIO\\\\CUB4_3.WAV\",\n\t\"AUDIO\\\\CUB4_4.WAV\",\n\t\"AUDIO\\\\CUB4_5.WAV\",\n\t\"AUDIO\\\\CUB4_5A.WAV\",\n\t\"AUDIO\\\\CUB4_6.WAV\",\n\t\"AUDIO\\\\CUB4_7.WAV\",\n\t\"AUDIO\\\\CUB4_8.WAV\",\n\t\"AUDIO\\\\CUB4_9.WAV\",\n\t\"AUDIO\\\\CUB4_10.WAV\",\n\t\"AUDIO\\\\CUB4_11.WAV\",\n\t\"AUDIO\\\\CUB4_12.WAV\",\n\t\"AUDIO\\\\CUB4_13.WAV\",\n\t\"AUDIO\\\\CUB4_14.WAV\",\n\t\"AUDIO\\\\CUB4_15.WAV\",\n\t\"AUDIO\\\\CUB4_16.WAV\",\n\t\"AUDIO\\\\GOLF_1.WAV\",\n\t\"AUDIO\\\\GOLF_2.WAV\",\n\t\"AUDIO\\\\GOLF_3.WAV\",\n\t\"AUDIO\\\\BAR_1.WAV\",\n\t\"AUDIO\\\\BAR_2.WAV\",\n\t\"AUDIO\\\\BAR_3.WAV\",\n\t\"AUDIO\\\\BAR_4.WAV\",\n\t\"AUDIO\\\\BAR_5.WAV\",\n\t\"AUDIO\\\\BAR_6.WAV\",\n\t\"AUDIO\\\\BAR_7.WAV\",\n\t\"AUDIO\\\\BAR_8.WAV\",\n\t\"AUDIO\\\\STRIP_1.WAV\",\n\t\"AUDIO\\\\STRIP_2.WAV\",\n\t\"AUDIO\\\\STRIP_3.WAV\",\n\t\"AUDIO\\\\STRIP_4.WAV\",\n\t\"AUDIO\\\\STRIP_5.WAV\",\n\t\"AUDIO\\\\STRIP_6.WAV\",\n\t\"AUDIO\\\\STRIP_7.WAV\",\n\t\"AUDIO\\\\STRIP_8.WAV\",\n\t\"AUDIO\\\\STRIP_9.WAV\",\n\t\"AUDIO\\\\STAR_1.WAV\",\n\t\"AUDIO\\\\STAR_2.WAV\",\n\t\"AUDIO\\\\STAR_3.WAV\",\n\t\"AUDIO\\\\STAR_4.WAV\",\n\t\"AUDIO\\\\FIN_1A.WAV\",\n\t\"AUDIO\\\\FIN_1B.WAV\",\n\t\"AUDIO\\\\FIN_1C.WAV\",\n\t\"AUDIO\\\\FIN_2B.WAV\",\n\t\"AUDIO\\\\FIN_2C.WAV\",\n\t\"AUDIO\\\\FIN_3.WAV\",\n\t\"AUDIO\\\\FIN_4.WAV\",\n\t\"AUDIO\\\\FIN_5.WAV\",\n\t\"AUDIO\\\\FIN_6.WAV\",\n\t\"AUDIO\\\\FIN_10.WAV\",\n\t\"AUDIO\\\\FIN_11A.WAV\",\n\t\"AUDIO\\\\FIN_11B.WAV\",\n\t\"AUDIO\\\\FIN_12A.WAV\",\n\t\"AUDIO\\\\FIN_12B.WAV\",\n\t\"AUDIO\\\\FIN_12C.WAV\",\n\t\"AUDIO\\\\FIN_13.WAV\",\n\t\"AUDIO\\\\FINKILL.WAV\",\n\t\"AUDIO\\\\LAW1_1.WAV\",\n\t\"AUDIO\\\\LAW1_2.WAV\",\n\t\"AUDIO\\\\LAW1_3.WAV\",\n\t\"AUDIO\\\\LAW1_4.WAV\",\n\t\"AUDIO\\\\LAW1_5.WAV\",\n\t\"AUDIO\\\\LAW1_6.WAV\",\n\t\"AUDIO\\\\LAW1_7.WAV\",\n\t\"AUDIO\\\\LAW1_8.WAV\",\n\t\"AUDIO\\\\LAW1_9.WAV\",\n\t\"AUDIO\\\\LAW1_10.WAV\",\n\t\"AUDIO\\\\LAW2_1.WAV\",\n\t\"AUDIO\\\\LAW2_2.WAV\",\n\t\"AUDIO\\\\LAW2_3.WAV\",\n\t\"AUDIO\\\\LAW2_4.WAV\",\n\t\"AUDIO\\\\LAW2_5.WAV\",\n\t\"AUDIO\\\\LAW2_6.WAV\",\n\t\"AUDIO\\\\LAW2_7.WAV\",\n\t\"AUDIO\\\\LAW2_8.WAV\",\n\t\"AUDIO\\\\LAW2_9.WAV\",\n\t\"AUDIO\\\\LAW2_10.WAV\",\n\t\"AUDIO\\\\LAW3_1.WAV\",\n\t\"AUDIO\\\\LAW3_2.WAV\",\n\t\"AUDIO\\\\LAW3_3.WAV\",\n\t\"AUDIO\\\\LAW3_4.WAV\",\n\t\"AUDIO\\\\LAW3_5.WAV\",\n\t\"AUDIO\\\\LAW3_6.WAV\",\n\t\"AUDIO\\\\LAW3_10.WAV\",\n\t\"AUDIO\\\\LAW3_11.WAV\",\n\t\"AUDIO\\\\LAW3_12.WAV\",\n\t\"AUDIO\\\\LAW3_13.WAV\",\n\t\"AUDIO\\\\LAW3_14.WAV\",\n\t\"AUDIO\\\\LAW3_16.WAV\",\n\t\"AUDIO\\\\LAW3_17.WAV\",\n\t\"AUDIO\\\\LAW3_18.WAV\",\n\t\"AUDIO\\\\LAW3_19.WAV\",\n\t\"AUDIO\\\\LAW3_20.WAV\",\n\t\"AUDIO\\\\LAW3_21.WAV\",\n\t\"AUDIO\\\\LAW3_22.WAV\",\n\t\"AUDIO\\\\LAW3_23.WAV\",\n\t\"AUDIO\\\\LAW3_24.WAV\",\n\t\"AUDIO\\\\LAW3_25.WAV\",\n\t\"AUDIO\\\\LAW4_1A.WAV\",\n\t\"AUDIO\\\\LAW4_1B.WAV\",\n\t\"AUDIO\\\\LAW4_1C.WAV\",\n\t\"AUDIO\\\\LAW4_1D.WAV\",\n\t\"AUDIO\\\\LAW4_10.WAV\",\n\t\"AUDIO\\\\LAW4_3.WAV\",\n\t\"AUDIO\\\\LAW4_4.WAV\",\n\t\"AUDIO\\\\LAW4_5.WAV\",\n\t\"AUDIO\\\\LAW4_6.WAV\",\n\t\"AUDIO\\\\LAW4_7.WAV\",\n\t\"AUDIO\\\\LAW4_8.WAV\",\n\t\"AUDIO\\\\LAW4_9.WAV\",\n\t\"AUDIO\\\\PHIL1_2.WAV\",\n\t\"AUDIO\\\\PHIL1_3.WAV\",\n\t\"AUDIO\\\\PHIL2_1.WAV\",\n\t\"AUDIO\\\\PHIL2_2.WAV\",\n\t\"AUDIO\\\\PHIL2_3.WAV\",\n\t\"AUDIO\\\\PHIL2_4.WAV\",\n\t\"AUDIO\\\\PHIL2_5.WAV\",\n\t\"AUDIO\\\\PHIL2_6.WAV\",\n\t\"AUDIO\\\\PHIL2_7.WAV\",\n\t\"AUDIO\\\\PHIL2_8.WAV\",\n\t\"AUDIO\\\\PHIL2_9.WAV\",\n\t\"AUDIO\\\\PHIL210.WAV\",\n\t\"AUDIO\\\\PHIL211.WAV\",\n\t\"AUDIO\\\\PORN1_1.WAV\",\n\t\"AUDIO\\\\PORN1_2.WAV\",\n\t\"AUDIO\\\\PORN1_3.WAV\",\n\t\"AUDIO\\\\PRN1_3A.WAV\",\n\t\"AUDIO\\\\PORN1_4.WAV\",\n\t\"AUDIO\\\\PORN1_5.WAV\",\n\t\"AUDIO\\\\PORN1_6.WAV\",\n\t\"AUDIO\\\\PORN1_7.WAV\",\n\t\"AUDIO\\\\PORN1_8.WAV\",\n\t\"AUDIO\\\\PORN1_9.WAV\",\n\t\"AUDIO\\\\PRN1_10.WAV\",\n\t\"AUDIO\\\\PRN1_11.WAV\",\n\t\"AUDIO\\\\PRN1_12.WAV\",\n\t\"AUDIO\\\\PRN1_13.WAV\",\n\t\"AUDIO\\\\PRN1_14.WAV\",\n\t\"AUDIO\\\\PRN1_15.WAV\",\n\t\"AUDIO\\\\PRN1_16.WAV\",\n\t\"AUDIO\\\\PRN1_17.WAV\",\n\t\"AUDIO\\\\PRN1_18.WAV\",\n\t\"AUDIO\\\\PRN1_19.WAV\",\n\t\"AUDIO\\\\PRN1_20.WAV\",\n\t\"AUDIO\\\\PRN1_21.WAV\",\n\t\"AUDIO\\\\PORN3_1.WAV\",\n\t\"AUDIO\\\\PORN3_2.WAV\",\n\t\"AUDIO\\\\PORN3_3.WAV\",\n\t\"AUDIO\\\\PORN3_4.WAV\",\n\t\"AUDIO\\\\PSYCH_1.WAV\",\n\t\"AUDIO\\\\PSYCH_2.WAV\",\n\t\"AUDIO\\\\ROK2_01.WAV\",\n\t\"AUDIO\\\\ROK3_1.WAV\",\n\t\"AUDIO\\\\ROK3_2.WAV\",\n\t\"AUDIO\\\\ROK3_3.WAV\",\n\t\"AUDIO\\\\ROK3_4.WAV\",\n\t\"AUDIO\\\\ROK3_5.WAV\",\n\t\"AUDIO\\\\ROK3_6.WAV\",\n\t\"AUDIO\\\\ROK3_7.WAV\",\n\t\"AUDIO\\\\ROK3_8.WAV\",\n\t\"AUDIO\\\\ROK3_9.WAV\",\n\t\"AUDIO\\\\ROK3_10.WAV\",\n\t\"AUDIO\\\\ROK3_11.WAV\",\n\t\"AUDIO\\\\ROK3_12.WAV\",\n\t\"AUDIO\\\\ROK3_13.WAV\",\n\t\"AUDIO\\\\ROK3_14.WAV\",\n\t\"AUDIO\\\\ROK3_15.WAV\",\n\t\"AUDIO\\\\ROK3_16.WAV\",\n\t\"AUDIO\\\\ROK3_17.WAV\",\n\t\"AUDIO\\\\ROK3_18.WAV\",\n\t\"AUDIO\\\\ROK3_19.WAV\",\n\t\"AUDIO\\\\ROK3_20.WAV\",\n\t\"AUDIO\\\\ROK3_21.WAV\",\n\t\"AUDIO\\\\ROK3_22.WAV\",\n\t\"AUDIO\\\\ROK3_23.WAV\",\n\t\"AUDIO\\\\ROK3_24.WAV\",\n\t\"AUDIO\\\\ROK3_25.WAV\",\n\t\"AUDIO\\\\ROK3_26.WAV\",\n\t\"AUDIO\\\\ROK3_27.WAV\",\n\t\"AUDIO\\\\ROK3_62.WAV\",\n\t\"AUDIO\\\\ROK3_63.WAV\",\n\t\"AUDIO\\\\ROK3_64.WAV\",\n\t\"AUDIO\\\\ROK3_65.WAV\",\n\t\"AUDIO\\\\ROK3_66.WAV\",\n\t\"AUDIO\\\\ROK3_67.WAV\",\n\t\"AUDIO\\\\ROK3_68.WAV\",\n\t\"AUDIO\\\\ROK3_69.WAV\",\n\t\"AUDIO\\\\ROK3_70.WAV\",\n\t\"AUDIO\\\\ROK3_71.WAV\",\n\t\"AUDIO\\\\ROK3_73.WAV\",\n\t\"AUDIO\\\\RESC_1.WAV\",\n\t\"AUDIO\\\\RESC_2.WAV\",\n\t\"AUDIO\\\\RESC_3.WAV\",\n\t\"AUDIO\\\\RESC_4.WAV\",\n\t\"AUDIO\\\\RESC_5.WAV\",\n\t\"AUDIO\\\\RESC_6.WAV\",\n\t\"AUDIO\\\\RESC_7.WAV\",\n\t\"AUDIO\\\\RESC_8.WAV\",\n\t\"AUDIO\\\\RESC_9.WAV\",\n\t\"AUDIO\\\\RESC_10.WAV\",\n\t\"AUDIO\\\\ROK1_1A.WAV\",\n\t\"AUDIO\\\\ROK1_1B.WAV\",\n\t\"AUDIO\\\\ROK1_5.WAV\",\n\t\"AUDIO\\\\ROK1_6.WAV\",\n\t\"AUDIO\\\\ROK1_7.WAV\",\n\t\"AUDIO\\\\ROK1_8.WAV\",\n\t\"AUDIO\\\\ROK1_9.WAV\",\n\t\"AUDIO\\\\TAX1_1.WAV\",\n\t\"AUDIO\\\\TAX1_2.WAV\",\n\t\"AUDIO\\\\TAX1_3.WAV\",\n\t\"AUDIO\\\\TAX1_4.WAV\",\n\t\"AUDIO\\\\TAX1_5.WAV\",\n\t\"AUDIO\\\\TAX2_1.WAV\",\n\t\"AUDIO\\\\TAX2_2.WAV\",\n\t\"AUDIO\\\\TAX2_3.WAV\",\n\t\"AUDIO\\\\TAX2_4.WAV\",\n\t\"AUDIO\\\\TAX2_5.WAV\",\n\t\"AUDIO\\\\TAX2_6.WAV\",\n\t\"AUDIO\\\\TAX2_7.WAV\",\n\t\"AUDIO\\\\TAX3_1.WAV\",\n\t\"AUDIO\\\\TAX3_2.WAV\",\n\t\"AUDIO\\\\TAX3_3.WAV\",\n\t\"AUDIO\\\\TAX3_4.WAV\",\n\t\"AUDIO\\\\TAX3_5.WAV\",\n\t\"AUDIO\\\\TEX1_1.WAV\",\n\t\"AUDIO\\\\TEX1_2.WAV\",\n\t\"AUDIO\\\\TEX1_3.WAV\",\n\t\"AUDIO\\\\TEX1_4.WAV\",\n\t\"AUDIO\\\\TEX1_5.WAV\",\n\t\"AUDIO\\\\TEX1_6.WAV\",\n\t\"AUDIO\\\\TEX2_1.WAV\",\n\t\"AUDIO\\\\TEX3_1.WAV\",\n\t\"AUDIO\\\\TEX3_2.WAV\",\n\t\"AUDIO\\\\TEX3_3.WAV\",\n\t\"AUDIO\\\\TEX3_4.WAV\",\n\t\"AUDIO\\\\TEX3_5.WAV\",\n\t\"AUDIO\\\\TEX3_6.WAV\",\n\t\"AUDIO\\\\TEX3_7.WAV\",\n\t\"AUDIO\\\\TEX3_8.WAV\",\n\t\"AUDIO\\\\HAT_1A.WAV\",\n\t\"AUDIO\\\\INTRO1.WAV\",\n\t\"AUDIO\\\\INTRO2.WAV\",\n\t\"AUDIO\\\\INTRO3.WAV\",\n\t\"AUDIO\\\\INTRO4.WAV\",\n\t\"AUDIO\\\\MOB_01A.WAV\",\n\t\"AUDIO\\\\MOB_01B.WAV\",\n\t\"AUDIO\\\\MOB_01C.WAV\",\n\t\"AUDIO\\\\MOB_02A.WAV\",\n\t\"AUDIO\\\\MOB_02B.WAV\",\n\t\"AUDIO\\\\MOB_02C.WAV\",\n\t\"AUDIO\\\\MOB_03A.WAV\",\n\t\"AUDIO\\\\MOB_03B.WAV\",\n\t\"AUDIO\\\\MOB_03C.WAV\",\n\t\"AUDIO\\\\MOB_03D.WAV\",\n\t\"AUDIO\\\\MOB_03E.WAV\",\n\t\"AUDIO\\\\SHARK_1.WAV\",\n\t\"AUDIO\\\\SHARK_2.WAV\",\n\t\"AUDIO\\\\SHARK_3.WAV\",\n\t\"AUDIO\\\\SHARK_4.WAV\",\n\t\"AUDIO\\\\SHARK_5.WAV\",\n\t\"AUDIO\\\\MOB_04A.WAV\",\n\t\"AUDIO\\\\MOB_04B.WAV\",\n\t\"AUDIO\\\\MOB_04C.WAV\",\n\t\"AUDIO\\\\MOB_04D.WAV\",\n\t\"AUDIO\\\\MOB_05A.WAV\",\n\t\"AUDIO\\\\MOB_05B.WAV\",\n\t\"AUDIO\\\\MOB_05C.WAV\",\n\t\"AUDIO\\\\MOB_05D.WAV\",\n\t\"AUDIO\\\\MOB_06A.WAV\",\n\t\"AUDIO\\\\MOB_06B.WAV\",\n\t\"AUDIO\\\\MOB_06C.WAV\",\n\t\"AUDIO\\\\MOB_07A.WAV\",\n\t\"AUDIO\\\\MOB_07B.WAV\",\n\t\"AUDIO\\\\MOB_08A.WAV\",\n\t\"AUDIO\\\\MOB_08B.WAV\",\n\t\"AUDIO\\\\MOB_08C.WAV\",\n\t\"AUDIO\\\\MOB_08D.WAV\",\n\t\"AUDIO\\\\MOB_08E.WAV\",\n\t\"AUDIO\\\\MOB_08F.WAV\",\n\t\"AUDIO\\\\MOB_08G.WAV\",\n\t\"AUDIO\\\\MOB_09A.WAV\",\n\t\"AUDIO\\\\MOB_09B.WAV\",\n\t\"AUDIO\\\\MOB_09C.WAV\",\n\t\"AUDIO\\\\MOB_09D.WAV\",\n\t\"AUDIO\\\\MOB_09E.WAV\",\n\t\"AUDIO\\\\MOB_09F.WAV\",\n\t\"AUDIO\\\\MOB_10A.WAV\",\n\t\"AUDIO\\\\MOB_10B.WAV\",\n\t\"AUDIO\\\\MOB_10C.WAV\",\n\t\"AUDIO\\\\MOB_10D.WAV\",\n\t\"AUDIO\\\\MOB_10E.WAV\",\n\t\"AUDIO\\\\MOB_11A.WAV\",\n\t\"AUDIO\\\\MOB_11B.WAV\",\n\t\"AUDIO\\\\MOB_11C.WAV\",\n\t\"AUDIO\\\\MOB_11D.WAV\",\n\t\"AUDIO\\\\MOB_11E.WAV\",\n\t\"AUDIO\\\\MOB_11F.WAV\",\n\t\"AUDIO\\\\MOB_14A.WAV\",\n\t\"AUDIO\\\\MOB_14B.WAV\",\n\t\"AUDIO\\\\MOB_14C.WAV\",\n\t\"AUDIO\\\\MOB_14D.WAV\",\n\t\"AUDIO\\\\MOB_14E.WAV\",\n\t\"AUDIO\\\\MOB_14F.WAV\",\n\t\"AUDIO\\\\MOB_14G.WAV\",\n\t\"AUDIO\\\\MOB_14H.WAV\",\n\t\"AUDIO\\\\MOB_16A.WAV\",\n\t\"AUDIO\\\\MOB_16B.WAV\",\n\t\"AUDIO\\\\MOB_16C.WAV\",\n\t\"AUDIO\\\\MOB_16D.WAV\",\n\t\"AUDIO\\\\MOB_16E.WAV\",\n\t\"AUDIO\\\\MOB_16F.WAV\",\n\t\"AUDIO\\\\MOB_16G.WAV\",\n\t\"AUDIO\\\\MOB_17A.WAV\",\n\t\"AUDIO\\\\MOB_17B.WAV\",\n\t\"AUDIO\\\\MOB_17C.WAV\",\n\t\"AUDIO\\\\MOB_17D.WAV\",\n\t\"AUDIO\\\\MOB_17E.WAV\",\n\t\"AUDIO\\\\MOB_17G.WAV\",\n\t\"AUDIO\\\\MOB_17H.WAV\",\n\t\"AUDIO\\\\MOB_17I.WAV\",\n\t\"AUDIO\\\\MOB_17J.WAV\",\n\t\"AUDIO\\\\MOB_17K.WAV\",\n\t\"AUDIO\\\\MOB_17L.WAV\",\n\t\"AUDIO\\\\MOB_18A.WAV\",\n\t\"AUDIO\\\\MOB_18B.WAV\",\n\t\"AUDIO\\\\MOB_18C.WAV\",\n\t\"AUDIO\\\\MOB_18D.WAV\",\n\t\"AUDIO\\\\MOB_18E.WAV\",\n\t\"AUDIO\\\\MOB_18F.WAV\",\n\t\"AUDIO\\\\MOB_18G.WAV\",\n\t\"AUDIO\\\\MOB_20A.WAV\",\n\t\"AUDIO\\\\MOB_20B.WAV\",\n\t\"AUDIO\\\\MOB_20C.WAV\",\n\t\"AUDIO\\\\MOB_20D.WAV\",\n\t\"AUDIO\\\\MOB_20E.WAV\",\n\t\"AUDIO\\\\MOB_24A.WAV\",\n\t\"AUDIO\\\\MOB_24B.WAV\",\n\t\"AUDIO\\\\MOB_24C.WAV\",\n\t\"AUDIO\\\\MOB_24D.WAV\",\n\t\"AUDIO\\\\MOB_24E.WAV\",\n\t\"AUDIO\\\\MOB_24F.WAV\",\n\t\"AUDIO\\\\MOB_24G.WAV\",\n\t\"AUDIO\\\\MOB_24H.WAV\",\n\t\"AUDIO\\\\MOB_25A.WAV\",\n\t\"AUDIO\\\\MOB_25B.WAV\",\n\t\"AUDIO\\\\MOB_25C.WAV\",\n\t\"AUDIO\\\\MOB_25D.WAV\",\n\t\"AUDIO\\\\MOB_26A.WAV\",\n\t\"AUDIO\\\\MOB_26B.WAV\",\n\t\"AUDIO\\\\MOB_26C.WAV\",\n\t\"AUDIO\\\\MOB_26D.WAV\",\n\t\"AUDIO\\\\MOB_26E.WAV\",\n\t\"AUDIO\\\\MOB_29A.WAV\",\n\t\"AUDIO\\\\MOB_29B.WAV\",\n\t\"AUDIO\\\\MOB_29C.WAV\",\n\t\"AUDIO\\\\MOB_29D.WAV\",\n\t\"AUDIO\\\\MOB_29E.WAV\",\n\t\"AUDIO\\\\MOB_29F.WAV\",\n\t\"AUDIO\\\\MOB_29G.WAV\",\n\t\"AUDIO\\\\MOB_30A.WAV\",\n\t\"AUDIO\\\\MOB_30B.WAV\",\n\t\"AUDIO\\\\MOB_30C.WAV\",\n\t\"AUDIO\\\\MOB_30D.WAV\",\n\t\"AUDIO\\\\MOB_30E.WAV\",\n\t\"AUDIO\\\\MOB_30F.WAV\",\n\t\"AUDIO\\\\MOB_33A.WAV\",\n\t\"AUDIO\\\\MOB_33B.WAV\",\n\t\"AUDIO\\\\MOB_33C.WAV\",\n\t\"AUDIO\\\\MOB_33D.WAV\",\n\t\"AUDIO\\\\MOB_34A.WAV\",\n\t\"AUDIO\\\\MOB_34B.WAV\",\n\t\"AUDIO\\\\MOB_34C.WAV\",\n\t\"AUDIO\\\\MOB_34D.WAV\",\n\t\"AUDIO\\\\MOB_35A.WAV\",\n\t\"AUDIO\\\\MOB_35B.WAV\",\n\t\"AUDIO\\\\MOB_35C.WAV\",\n\t\"AUDIO\\\\MOB_35D.WAV\",\n\t\"AUDIO\\\\MOB_36A.WAV\",\n\t\"AUDIO\\\\MOB_36B.WAV\",\n\t\"AUDIO\\\\MOB_36C.WAV\",\n\t\"AUDIO\\\\MOB_40A.WAV\",\n\t\"AUDIO\\\\MOB_40B.WAV\",\n\t\"AUDIO\\\\MOB_40C.WAV\",\n\t\"AUDIO\\\\MOB_40D.WAV\",\n\t\"AUDIO\\\\MOB_40E.WAV\",\n\t\"AUDIO\\\\MOB_40F.WAV\",\n\t\"AUDIO\\\\MOB_40G.WAV\",\n\t\"AUDIO\\\\MOB_40H.WAV\",\n\t\"AUDIO\\\\MOB_40I.WAV\",\n\t\"AUDIO\\\\MOB_41A.WAV\",\n\t\"AUDIO\\\\MOB_41B.WAV\",\n\t\"AUDIO\\\\MOB_41C.WAV\",\n\t\"AUDIO\\\\MOB_41D.WAV\",\n\t\"AUDIO\\\\MOB_41E.WAV\",\n\t\"AUDIO\\\\MOB_41F.WAV\",\n\t\"AUDIO\\\\MOB_41G.WAV\",\n\t\"AUDIO\\\\MOB_41H.WAV\",\n\t\"AUDIO\\\\MOB_42A.WAV\",\n\t\"AUDIO\\\\MOB_42B.WAV\",\n\t\"AUDIO\\\\MOB_42C.WAV\",\n\t\"AUDIO\\\\MOB_42D.WAV\",\n\t\"AUDIO\\\\MOB_42E.WAV\",\n\t\"AUDIO\\\\MOB_43A.WAV\",\n\t\"AUDIO\\\\MOB_43B.WAV\",\n\t\"AUDIO\\\\MOB_43C.WAV\",\n\t\"AUDIO\\\\MOB_43D.WAV\",\n\t\"AUDIO\\\\MOB_43E.WAV\",\n\t\"AUDIO\\\\MOB_43F.WAV\",\n\t\"AUDIO\\\\MOB_43G.WAV\",\n\t\"AUDIO\\\\MOB_43H.WAV\",\n\t\"AUDIO\\\\MOB_45A.WAV\",\n\t\"AUDIO\\\\MOB_45B.WAV\",\n\t\"AUDIO\\\\MOB_45C.WAV\",\n\t\"AUDIO\\\\MOB_45D.WAV\",\n\t\"AUDIO\\\\MOB_45E.WAV\",\n\t\"AUDIO\\\\MOB_45F.WAV\",\n\t\"AUDIO\\\\MOB_45G.WAV\",\n\t\"AUDIO\\\\MOB_45H.WAV\",\n\t\"AUDIO\\\\MOB_45I.WAV\",\n\t\"AUDIO\\\\MOB_45J.WAV\",\n\t\"AUDIO\\\\MOB_45K.WAV\",\n\t\"AUDIO\\\\MOB_45L.WAV\",\n\t\"AUDIO\\\\MOB_45M.WAV\",\n\t\"AUDIO\\\\MOB_45N.WAV\",\n\t\"AUDIO\\\\MOB_46A.WAV\",\n\t\"AUDIO\\\\MOB_46B.WAV\",\n\t\"AUDIO\\\\MOB_46C.WAV\",\n\t\"AUDIO\\\\MOB_46D.WAV\",\n\t\"AUDIO\\\\MOB_46E.WAV\",\n\t\"AUDIO\\\\MOB_46F.WAV\",\n\t\"AUDIO\\\\MOB_46G.WAV\",\n\t\"AUDIO\\\\MOB_46H.WAV\",\n\t\"AUDIO\\\\MOB_47A.WAV\",\n\t\"AUDIO\\\\MOB_52A.WAV\",\n\t\"AUDIO\\\\MOB_52B.WAV\",\n\t\"AUDIO\\\\MOB_52C.WAV\",\n\t\"AUDIO\\\\MOB_52D.WAV\",\n\t\"AUDIO\\\\MOB_52E.WAV\",\n\t\"AUDIO\\\\MOB_52F.WAV\",\n\t\"AUDIO\\\\MOB_52G.WAV\",\n\t\"AUDIO\\\\MOB_52H.WAV\",\n\t\"AUDIO\\\\MOB_54A.WAV\",\n\t\"AUDIO\\\\MOB_54B.WAV\",\n\t\"AUDIO\\\\MOB_54C.WAV\",\n\t\"AUDIO\\\\MOB_54D.WAV\",\n\t\"AUDIO\\\\MOB_54E.WAV\",\n\t\"AUDIO\\\\MOB_55A.WAV\",\n\t\"AUDIO\\\\MOB_55B.WAV\",\n\t\"AUDIO\\\\MOB_55C.WAV\",\n\t\"AUDIO\\\\MOB_55D.WAV\",\n\t\"AUDIO\\\\MOB_55E.WAV\",\n\t\"AUDIO\\\\MOB_55F.WAV\",\n\t\"AUDIO\\\\MOB_56A.WAV\",\n\t\"AUDIO\\\\MOB_56B.WAV\",\n\t\"AUDIO\\\\MOB_56C.WAV\",\n\t\"AUDIO\\\\MOB_56D.WAV\",\n\t\"AUDIO\\\\MOB_56E.WAV\",\n\t\"AUDIO\\\\MOB_56F.WAV\",\n\t\"AUDIO\\\\MOB_57A.WAV\",\n\t\"AUDIO\\\\MOB_57B.WAV\",\n\t\"AUDIO\\\\MOB_57C.WAV\",\n\t\"AUDIO\\\\MOB_57D.WAV\",\n\t\"AUDIO\\\\MOB_57E.WAV\",\n\t\"AUDIO\\\\MOB_58A.WAV\",\n\t\"AUDIO\\\\MOB_58B.WAV\",\n\t\"AUDIO\\\\MOB_58C.WAV\",\n\t\"AUDIO\\\\MOB_58D.WAV\",\n\t\"AUDIO\\\\MOB_58E.WAV\",\n\t\"AUDIO\\\\MOB_58F.WAV\",\n\t\"AUDIO\\\\MOB_58G.WAV\",\n\t\"AUDIO\\\\MOB_61A.WAV\",\n\t\"AUDIO\\\\MOB_61B.WAV\",\n\t\"AUDIO\\\\MOB_62A.WAV\",\n\t\"AUDIO\\\\MOB_62B.WAV\",\n\t\"AUDIO\\\\MOB_62C.WAV\",\n\t\"AUDIO\\\\MOB_62D.WAV\",\n\t\"AUDIO\\\\MOB_63A.WAV\",\n\t\"AUDIO\\\\MOB_63B.WAV\",\n\t\"AUDIO\\\\MOB_63C.WAV\",\n\t\"AUDIO\\\\MOB_63D.WAV\",\n\t\"AUDIO\\\\MOB_63E.WAV\",\n\t\"AUDIO\\\\MOB_63F.WAV\",\n\t\"AUDIO\\\\MOB_63G.WAV\",\n\t\"AUDIO\\\\MOB_63H.WAV\",\n\t\"AUDIO\\\\MOB_63I.WAV\",\n\t\"AUDIO\\\\MOB_63J.WAV\",\n\t\"AUDIO\\\\MOB_66A.WAV\",\n\t\"AUDIO\\\\MOB_66B.WAV\",\n\t\"AUDIO\\\\MOB_68A.WAV\",\n\t\"AUDIO\\\\MOB_68B.WAV\",\n\t\"AUDIO\\\\MOB_68C.WAV\",\n\t\"AUDIO\\\\MOB_68D.WAV\",\n\t\"AUDIO\\\\MOB_70A.WAV\",\n\t\"AUDIO\\\\MOB_70B.WAV\",\n\t\"AUDIO\\\\MOB_71A.WAV\",\n\t\"AUDIO\\\\MOB_71B.WAV\",\n\t\"AUDIO\\\\MOB_71C.WAV\",\n\t\"AUDIO\\\\MOB_71D.WAV\",\n\t\"AUDIO\\\\MOB_71E.WAV\",\n\t\"AUDIO\\\\MOB_71F.WAV\",\n\t\"AUDIO\\\\MOB_71G.WAV\",\n\t\"AUDIO\\\\MOB_71H.WAV\",\n\t\"AUDIO\\\\MOB_71I.WAV\",\n\t\"AUDIO\\\\MOB_71J.WAV\",\n\t\"AUDIO\\\\MOB_71K.WAV\",\n\t\"AUDIO\\\\MOB_71L.WAV\",\n\t\"AUDIO\\\\MOB_71M.WAV\",\n\t\"AUDIO\\\\MOB_71N.WAV\",\n\t\"AUDIO\\\\MOB_72A.WAV\",\n\t\"AUDIO\\\\MOB_72B.WAV\",\n\t\"AUDIO\\\\MOB_72C.WAV\",\n\t\"AUDIO\\\\MOB_72D.WAV\",\n\t\"AUDIO\\\\MOB_72E.WAV\",\n\t\"AUDIO\\\\MOB_72F.WAV\",\n\t\"AUDIO\\\\MOB_72G.WAV\",\n\t\"AUDIO\\\\MOB_73A.WAV\",\n\t\"AUDIO\\\\MOB_73C.WAV\",\n\t\"AUDIO\\\\MOB_73D.WAV\",\n\t\"AUDIO\\\\MOB_73F.WAV\",\n\t\"AUDIO\\\\MOB_73G.WAV\",\n\t\"AUDIO\\\\MOB_73I.WAV\",\n\t\"AUDIO\\\\MOB_95A.WAV\",\n\t\"AUDIO\\\\MOB_96A.WAV\",\n\t\"AUDIO\\\\MOB_98A.WAV\",\n\t\"AUDIO\\\\MOB_99A.WAV\",\n\t\"AUDIO\\\\JOB1_1B.WAV\",\n\t\"AUDIO\\\\JOB1_1C.WAV\",\n\t\"AUDIO\\\\JOB1_1D.WAV\",\n\t\"AUDIO\\\\JOB2_1B.WAV\",\n\t\"AUDIO\\\\JOB2_2.WAV\",\n\t\"AUDIO\\\\JOB2_3.WAV\",\n\t\"AUDIO\\\\JOB2_4.WAV\",\n\t\"AUDIO\\\\JOB2_5.WAV\",\n\t\"AUDIO\\\\JOB2_6.WAV\",\n\t\"AUDIO\\\\JOB2_7.WAV\",\n\t\"AUDIO\\\\JOB2_8.WAV\",\n\t\"AUDIO\\\\JOB2_9.WAV\",\n\t\"AUDIO\\\\JOB3_1.WAV\",\n\t\"AUDIO\\\\JOB3_2.WAV\",\n\t\"AUDIO\\\\JOB3_3.WAV\",\n\t\"AUDIO\\\\JOB4_1.WAV\",\n\t\"AUDIO\\\\JOB4_2.WAV\",\n\t\"AUDIO\\\\JOB4_3.WAV\",\n\t\"AUDIO\\\\JOB5_1.WAV\",\n\t\"AUDIO\\\\JOB5_2.WAV\",\n\t\"AUDIO\\\\JOB5_3.WAV\",\n\t\"AUDIO\\\\BJM1_20.WAV\",\n\t\"AUDIO\\\\BJM1_4.WAV\",\n\t\"AUDIO\\\\BJM1_5.WAV\",\n\t\"AUDIO\\\\MERC_39.WAV\",\n\t\"AUDIO\\\\MONO_1.WAV\",\n\t\"AUDIO\\\\MONO_2.WAV\",\n\t\"AUDIO\\\\MONO_3.WAV\",\n\t\"AUDIO\\\\MONO_4.WAV\",\n\t\"AUDIO\\\\MONO_5.WAV\",\n\t\"AUDIO\\\\MONO_6.WAV\",\n\t\"AUDIO\\\\MONO_7.WAV\",\n\t\"AUDIO\\\\MONO_8.WAV\",\n\t\"AUDIO\\\\MONO_9.WAV\",\n\t\"AUDIO\\\\MONO10.WAV\",\n\t\"AUDIO\\\\MONO11.WAV\",\n\t\"AUDIO\\\\MONO12.WAV\",\n\t\"AUDIO\\\\MONO13.WAV\",\n\t\"AUDIO\\\\MONO14.WAV\",\n\t\"AUDIO\\\\MONO15.WAV\",\n\t\"AUDIO\\\\MONO16.WAV\",\n\t\"AUDIO\\\\FUD_01.WAV\",\n\t\"AUDIO\\\\FUD_02.WAV\",\n\t\"AUDIO\\\\FUD_03.WAV\",\n\t\"AUDIO\\\\FUD_04.WAV\",\n\t\"AUDIO\\\\FUD_05.WAV\",\n\t\"AUDIO\\\\FUD_06.WAV\",\n\t\"AUDIO\\\\FUD_07.WAV\",\n\t\"AUDIO\\\\FUD_08.WAV\",\n\t\"AUDIO\\\\FUD_09.WAV\",\n\t\"AUDIO\\\\FUD_10.WAV\",\n\t\"AUDIO\\\\FUD_11.WAV\",\n\t\"AUDIO\\\\FUD_12.WAV\",\n\t\"AUDIO\\\\FUD_13.WAV\",\n\t\"AUDIO\\\\FUD_14.WAV\",\n\t\"AUDIO\\\\FUD_15.WAV\",\n\t\"AUDIO\\\\FUD_16.WAV\",\n\t\"AUDIO\\\\FUD_17.WAV\",\n\t\"AUDIO\\\\FUD_18.WAV\",\n\t\"AUDIO\\\\FUD_19.WAV\",\n\t\"AUDIO\\\\FUD_20.WAV\",\n\t\"AUDIO\\\\BURG_01.WAV\",\n\t\"AUDIO\\\\BURG_02.WAV\",\n\t\"AUDIO\\\\BURG_03.WAV\",\n\t\"AUDIO\\\\BURG_04.WAV\",\n\t\"AUDIO\\\\BURG_05.WAV\",\n\t\"AUDIO\\\\BURG_06.WAV\",\n\t\"AUDIO\\\\BURG_07.WAV\",\n\t\"AUDIO\\\\BURG_08.WAV\",\n\t\"AUDIO\\\\BURG_09.WAV\",\n\t\"AUDIO\\\\BURG_10.WAV\",\n\t\"AUDIO\\\\BURG_11.WAV\",\n\t\"AUDIO\\\\BURG_12.WAV\",\n\t\"AUDIO\\\\CRUST01.WAV\",\n\t\"AUDIO\\\\CRUST02.WAV\",\n\t\"AUDIO\\\\CRUST03.WAV\",\n\t\"AUDIO\\\\CRUST04.WAV\",\n\t\"AUDIO\\\\CRUST05.WAV\",\n\t\"AUDIO\\\\CRUST06.WAV\",\n\t\"AUDIO\\\\CRUST07.WAV\",\n\t\"AUDIO\\\\CRUST08.WAV\",\n\t\"AUDIO\\\\CRUST09.WAV\",\n\t\"AUDIO\\\\BAND_01.WAV\",\n\t\"AUDIO\\\\BAND_02.WAV\",\n\t\"AUDIO\\\\BAND_03.WAV\",\n\t\"AUDIO\\\\BAND_04.WAV\",\n\t\"AUDIO\\\\BAND_05.WAV\",\n\t\"AUDIO\\\\BAND_06.WAV\",\n\t\"AUDIO\\\\BAND_07.WAV\",\n\t\"AUDIO\\\\BAND_08.WAV\",\n\t\"AUDIO\\\\SHAFT01.WAV\",\n\t\"AUDIO\\\\SHAFT02.WAV\",\n\t\"AUDIO\\\\SHAFT03.WAV\",\n\t\"AUDIO\\\\SHAFT04.WAV\",\n\t\"AUDIO\\\\SHAFT05.WAV\",\n\t\"AUDIO\\\\SHAFT06.WAV\",\n\t\"AUDIO\\\\SHAFT07.WAV\",\n\t\"AUDIO\\\\SHAFT08.WAV\",\n\t\"AUDIO\\\\PISS_01.WAV\",\n\t\"AUDIO\\\\PISS_02.WAV\",\n\t\"AUDIO\\\\PISS_03.WAV\",\n\t\"AUDIO\\\\PISS_04.WAV\",\n\t\"AUDIO\\\\PISS_05.WAV\",\n\t\"AUDIO\\\\PISS_06.WAV\",\n\t\"AUDIO\\\\PISS_07.WAV\",\n\t\"AUDIO\\\\PISS_08.WAV\",\n\t\"AUDIO\\\\PISS_09.WAV\",\n\t\"AUDIO\\\\PISS_10.WAV\",\n\t\"AUDIO\\\\PISS_11.WAV\",\n\t\"AUDIO\\\\PISS_12.WAV\",\n\t\"AUDIO\\\\PISS_13.WAV\",\n\t\"AUDIO\\\\PISS_14.WAV\",\n\t\"AUDIO\\\\PISS_15.WAV\",\n\t\"AUDIO\\\\PISS_16.WAV\",\n\t\"AUDIO\\\\PISS_17.WAV\",\n\t\"AUDIO\\\\PISS_18.WAV\",\n\t\"AUDIO\\\\PISS_19.WAV\",\n\t\"AUDIO\\\\GIMME01.WAV\",\n\t\"AUDIO\\\\GIMME02.WAV\",\n\t\"AUDIO\\\\GIMME03.WAV\",\n\t\"AUDIO\\\\GIMME04.WAV\",\n\t\"AUDIO\\\\GIMME05.WAV\",\n\t\"AUDIO\\\\GIMME06.WAV\",\n\t\"AUDIO\\\\GIMME07.WAV\",\n\t\"AUDIO\\\\GIMME08.WAV\",\n\t\"AUDIO\\\\GIMME09.WAV\",\n\t\"AUDIO\\\\GIMME10.WAV\",\n\t\"AUDIO\\\\GIMME11.WAV\",\n\t\"AUDIO\\\\GIMME12.WAV\",\n\t\"AUDIO\\\\GIMME13.WAV\",\n\t\"AUDIO\\\\GIMME14.WAV\",\n\t\"AUDIO\\\\GIMME15.WAV\",\n\t\"AUDIO\\\\BUST_01.WAV\",\n\t\"AUDIO\\\\BUST_02.WAV\",\n\t\"AUDIO\\\\BUST_03.WAV\",\n\t\"AUDIO\\\\BUST_04.WAV\",\n\t\"AUDIO\\\\BUST_05.WAV\",\n\t\"AUDIO\\\\BUST_06.WAV\",\n\t\"AUDIO\\\\BUST_07.WAV\",\n\t\"AUDIO\\\\BUST_08.WAV\",\n\t\"AUDIO\\\\BUST_09.WAV\",\n\t\"AUDIO\\\\BUST_10.WAV\",\n\t\"AUDIO\\\\BUST_11.WAV\",\n\t\"AUDIO\\\\BUST_12.WAV\",\n\t\"AUDIO\\\\BUST_13.WAV\",\n\t\"AUDIO\\\\BUST_14.WAV\",\n\t\"AUDIO\\\\BUST_15.WAV\",\n\t\"AUDIO\\\\BUST_16.WAV\",\n\t\"AUDIO\\\\BUST_17.WAV\",\n\t\"AUDIO\\\\BUST_18.WAV\",\n\t\"AUDIO\\\\BUST_19.WAV\",\n\t\"AUDIO\\\\BUST_20.WAV\",\n\t\"AUDIO\\\\BUST_21.WAV\",\n\t\"AUDIO\\\\BUST_22.WAV\",\n\t\"AUDIO\\\\BUST_23.WAV\",\n\t\"AUDIO\\\\BUST_24.WAV\",\n\t\"AUDIO\\\\BUST_25.WAV\",\n\t\"AUDIO\\\\BUST_26.WAV\",\n\t\"AUDIO\\\\BUST_27.WAV\",\n\t\"AUDIO\\\\BUST_28.WAV\",\n};"
  },
  {
    "path": "src/audio/sampman_miles.cpp",
    "content": "#include \"common.h\"\n\n#ifdef AUDIO_MSS\n#include <shlobj.h>\n#include <shlguid.h>\n\n#include <time.h>\n\n#include \"eax.h\"\n#include \"eax-util.h\"\n#include \"mss.h\"\n\n#include \"sampman.h\"\n#include \"AudioManager.h\"\n#include \"MusicManager.h\"\n#include \"Frontend.h\"\n#include \"Timer.h\"\n#include \"crossplatform.h\"\n\n#pragma comment( lib, \"mss32.lib\" )\n\ncSampleManager SampleManager;\nuint32 BankStartOffset[MAX_SFX_BANKS];\n///////////////////////////////////////////////////////////////\n\nchar SampleBankDescFilename[] = \"AUDIO\\\\SFX.SDT\";\nchar SampleBankDataFilename[] = \"AUDIO\\\\SFX.RAW\";\n\nFILE *fpSampleDescHandle;\nFILE *fpSampleDataHandle;\nbool  bSampleBankLoaded            [MAX_SFX_BANKS];\nint32 nSampleBankDiscStartOffset   [MAX_SFX_BANKS];\nint32 nSampleBankSize              [MAX_SFX_BANKS];\nint32 nSampleBankMemoryStartAddress[MAX_SFX_BANKS];\nint32 _nSampleDataEndOffset;\n\nint32 nPedSlotSfx    [MAX_PEDSFX];\nint32 nPedSlotSfxAddr[MAX_PEDSFX];\nuint8 nCurrentPedSlot;\n\nuint8 nChannelVolume[MAXCHANNELS+MAX2DCHANNELS];\n\nuint32 nStreamLength[TOTAL_STREAMED_SOUNDS];\n\n///////////////////////////////////////////////////////////////\nstruct tMP3Entry\n{\n\tchar aFilename[MAX_PATH];\n\t\n\tuint32 nTrackLength;\n\tuint32 nTrackStreamPos;\n\t\n\ttMP3Entry *pNext;\n\tchar *pLinkPath;\n};\n\nuint32 nNumMP3s;\ntMP3Entry *_pMP3List;\nchar _mp3DirectoryPath[MAX_PATH];\nHSTREAM mp3Stream [MAX_STREAMS];\nint8 nStreamPan   [MAX_STREAMS];\nint8 nStreamVolume[MAX_STREAMS];\nuint8 nStreamLoopedFlag[MAX_STREAMS];\nuint32 _CurMP3Index;\nint32 _CurMP3Pos;\nbool _bIsMp3Active;\n///////////////////////////////////////////////////////////////\n\n\nbool _bSampmanInitialised = false;\n\n//\n// Miscellaneous globals / defines\n\n//\tEnv\t\tSize\tDiffus\tRoom\tRoomHF\tRoomLF\tDecTm\tDcHF\tDcLF\tRefl\tRefDel\tRef Pan\t\t\t\tRevb\tRevDel\t\tRev Pan\t\t\t\tEchTm\tEchDp\tModTm\tModDp\tAirAbs\tHFRef\t\tLFRef\tRRlOff\tFLAGS\n\nEAXLISTENERPROPERTIES StartEAX3 =\n\t{26,\t1.7f,\t0.8f,\t-1000,\t-1000,\t-100,\t4.42f,\t0.14f,\t1.00f,\t429,\t0.014f,\t0.00f,0.00f,0.00f,\t1023,\t0.021f,\t\t0.00f,0.00f,0.00f,\t0.250f,\t0.000f,\t0.250f,\t0.000f,\t-5.0f,\t2727.1f,\t250.0f,\t0.00f,\t0x3f };\n\nEAXLISTENERPROPERTIES FinishEAX3 =\n\t{26,\t100.0f,\t1.0f,\t0,\t\t-1000,\t-2200,\t20.0f,\t1.39f,\t1.00f,\t1000,\t0.069f,\t0.00f,0.00f,0.00f,\t400,\t0.100f,\t\t0.00f,0.00f,0.00f,\t0.250f,\t1.000f,\t3.982f,\t0.000f,\t-18.0f,\t3530.8f,\t417.9f,\t6.70f,\t0x3f };\n\nEAXLISTENERPROPERTIES EAX3Params;\n\nS32         prevprovider=-1;\nS32         curprovider=-1;\nS32         usingEAX=0;\nS32         usingEAX3=0;\nHPROVIDER   opened_provider=0;\nH3DSAMPLE   opened_samples[MAXCHANNELS] = {0};\nHSAMPLE     opened_2dsamples[MAX2DCHANNELS] = {0};\nHDIGDRIVER  DIG;\nS32         speaker_type=0;\n\nU32 _maxSamples;\nfloat _fPrevEaxRatioDestination;\nbool _usingMilesFast2D;\nfloat _fEffectsLevel;\n\n\nstruct\n{\n\tHPROVIDER id;\n\tchar name[80];\n}providers[MAXPROVIDERS];\n\ntypedef struct provider_stuff\n{\n  char* name;\n  HPROVIDER id;\n} provider_stuff;\n\n\nstatic int __cdecl comp(const provider_stuff*s1,const provider_stuff*s2)\n{\n  return( _stricmp(s1->name,s2->name) );\n}\n\nstatic void\nadd_providers()\n{\n\tprovider_stuff pi[MAXPROVIDERS];\n\tU32   n,i,j;\n\t\n\tSampleManager.SetNum3DProvidersAvailable(0);\n\t\n\tHPROENUM next = HPROENUM_FIRST;\n\t\n\tn=0;\n\twhile (AIL_enumerate_3D_providers(&next, &pi[n].id, &pi[n].name) && (n<MAXPROVIDERS))\n\t{\n\t\t++n;\n\t}\n\t\n\tqsort(pi,n,sizeof(pi[0]), (int(__cdecl*)(void const*, void const*))comp);\n\t\n\tfor(i=0;i<n;i++)\n\t{\n\t\tproviders[i].id=pi[i].id;\n\t\tstrcpy(providers[i].name, pi[i].name);\n\t\tSampleManager.Set3DProviderName(i, providers[i].name);\n\t}\n\t\n\tSampleManager.SetNum3DProvidersAvailable(n);\n\t\n\tfor(j=n;j<MAXPROVIDERS;j++)\n\t\tSampleManager.Set3DProviderName(j, NULL);\n}\n\nstatic void\nrelease_existing()\n{\n\tfor ( U32 i = 0; i < _maxSamples; i++ )\n\t{\n\t\tif ( opened_samples[i] )\n\t\t{\n\t\t\tAIL_release_3D_sample_handle(opened_samples[i]);\n\t\t\topened_samples[i] = NULL;\n\t\t}\n\t}\n\n\tif ( opened_provider )\n\t{\n\t\tAIL_close_3D_provider(opened_provider);\n\t\topened_provider = NULL;\n\t}\n\n\t_fPrevEaxRatioDestination = 0.0f;\n\t_usingMilesFast2D = false;\n\t_fEffectsLevel = 0.0f;\n}\n\nstatic bool\nset_new_provider(S32 index)\n{\n\tDWORD result;\n\t\n\tif ( curprovider == index )\n\t\treturn true;\n\n\t//close the already opened provider\n\tcurprovider = index;\n\t\n\trelease_existing();\n\t\n\tif ( curprovider != -1 )\n\t{\n\t\tif ( !strcmp(providers[index].name, \"Dolby Surround\") )\n\t\t\t_maxSamples = MAXCHANNELS_SURROUND;\n\t\telse\n\t\t\t_maxSamples = MAXCHANNELS;\n\t\t\n\t\tAIL_set_3D_provider_preference(providers[index].id, \"Maximum supported samples\", &_maxSamples);\n\t\t\n\t\t//load the new provider\n\t\tresult = AIL_open_3D_provider(providers[index].id);\n\t\t\n\t\tif (result != M3D_NOERR) \n\t\t{\n\t\t\tcurprovider=-1;\n\t\t\t\n\t\t\tOutputDebugStringA(AIL_last_error());\n\t\t\t\n\t\t\trelease_existing();\n\t\t\t\n\t\t\treturn false;\n\t\t}\n\t\telse\n\t\t{\n\t\t\topened_provider=providers[index].id;\n\t\t\t\n\t\t\t//see if we're running under an EAX compatible provider\n\t\t\t\n\t\t\tif ( !strcmp(providers[index].name, \"Creative Labs EAX 3 (TM)\") )\n\t\t\t{\n\t\t\t\tusingEAX = 1;\n\t\t\t\tusingEAX3 = 1;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tusingEAX3 = 0;\n\n\t\t\t\tresult=AIL_3D_room_type(opened_provider);\n\t\t\t\tusingEAX=(((S32)result)!=-1)?1:0; // will be something other than -1 on EAX\t\t\t\t\n\t\t\t}\n\t\t\t\n\t\t\tif ( usingEAX3 )\n\t\t\t{\n\t\t\t\tOutputDebugString(\"DOING SPECIAL EAX 3 STUFF!\");\n\t\t\t\tAIL_set_3D_provider_preference(opened_provider, \"EAX all parameters\", &FinishEAX3);\n\t\t\t}\n\t\t\telse if ( usingEAX )\n\t\t\t{\n\t\t\t\tAIL_set_3D_room_type(opened_provider, ENVIRONMENT_CAVE);\n\t\t\t\t\n\t\t\t\tif ( !strcmp(providers[index].name, \"Miles Fast 2D Positional Audio\") )\n\t\t\t\t\t_usingMilesFast2D = true;\n\t\t\t}\n\t\t\t\n\t\t\tAIL_3D_provider_attribute(opened_provider, \"Maximum supported samples\", &_maxSamples);\n\t\t\t\n\t\t\tif ( _maxSamples > MAXCHANNELS )\n\t\t\t\t_maxSamples = MAXCHANNELS;\n\t\t\t\n\t\t\tSampleManager.SetSpeakerConfig(speaker_type);\n\t\t\t\n\t\t\t//obtain a 3D sample handles\n\t\t\tfor ( U32 i = 0; i < _maxSamples; ++i )\n\t\t\t{\n\t\t\t\topened_samples[i] = AIL_allocate_3D_sample_handle(opened_provider);\n\t\t\t\tif ( opened_samples[i] != NULL )\n\t\t\t\t\tAIL_set_3D_sample_effects_level(opened_samples[i], 0.0f);\n\t\t\t}\n\t\t\t\n\t\t\treturn true;\n\t\t}\t\n\t}\n\t\n\treturn false;\n}\n\nU32 RadioHandlers[9];\n\nU32 WINAPI vfs_open_callback(char const* Filename, U32* FileHandle)\n{\n\t*FileHandle = (U32)fopen(Filename, \"rb\");\n\n\t// couldn't they just use stricmp once? and strlen? this is very inefficient\n\tif ((strcmp(Filename + strlen(Filename) - 4, \".adf\") == 0) || (strcmp(Filename + strlen(Filename) - 4, \".ADF\") == 0)) {\n\t\tfor (int i = 0; i < ARRAY_SIZE(RadioHandlers); i++) {\n\t\t\tif (RadioHandlers[i] == NULL) {\n\t\t\t\tRadioHandlers[i] = *FileHandle;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tstrcpy((char*)Filename + strlen(Filename) - 4, \".mp3\");\n\t}\n\treturn *FileHandle;\n}\n\nvoid WINAPI vfs_close_callback(U32 FileHandle)\n{\n\tfor (int i = 0; i < ARRAY_SIZE(RadioHandlers); i++) {\n\t\tif (RadioHandlers[i] == FileHandle) {\n\t\t\tRadioHandlers[i] = NULL;\n\t\t\tbreak;\n\t\t}\n\t}\n\tfclose((FILE*)FileHandle);\n}\n\nS32 WINAPI vfs_seek_callback(U32 FileHandle, S32 Offset, U32 Type)\n{\n\tfseek((FILE*)FileHandle, Offset, Type);\n\treturn ftell((FILE*)FileHandle);\n}\n\nU32 WINAPI vfs_read_callback(U32 FileHandle, void* Buffer, U32 Bytes)\n{\n\tfread(Buffer, Bytes, 1, (FILE*)FileHandle);\n\tuint8* _Buffer = (uint8*)Buffer;\n\n\tfor (int i = 0; i < ARRAY_SIZE(RadioHandlers); i++) {\n\t\tif (FileHandle == RadioHandlers[i]) {\n\t\t\tfor (U32 k = 0; k < Bytes; k++)\n\t\t\t\t_Buffer[k] ^= 0x22;\n\t\t\tbreak;\n\t\t}\n\t}\n\treturn Bytes;\n}\n\ncSampleManager::cSampleManager(void) : \n\tm_nNumberOfProviders(0)\n{\n\t;\n\n\tAIL_set_file_callbacks(vfs_open_callback, vfs_close_callback, vfs_seek_callback, vfs_read_callback);\n}\n\ncSampleManager::~cSampleManager(void)\n{\n\t\n}\n\nvoid\ncSampleManager::SetSpeakerConfig(int32 which)\n{\n\tswitch ( which )\n\t{\n\t\tcase 1:\n\t\t\tspeaker_type=AIL_3D_2_SPEAKER;\n\t\t\tbreak;\n\t\t\n\t\tcase 2:\n\t\t\tspeaker_type=AIL_3D_HEADPHONE;\n\t\t\tbreak;\n\t\t\n\t\tcase 3:\n\t\t\tspeaker_type=AIL_3D_4_SPEAKER;\n\t\t\tbreak;\n\t\t\t\n\t\tdefault:\n\t\t\treturn;\n\t\t\tbreak;\n\t}\n\t\n\tif (opened_provider)\n\t\tAIL_set_3D_speaker_type(opened_provider, speaker_type);\n}\n\nuint32\ncSampleManager::GetMaximumSupportedChannels(void)\n{\n\tif ( _maxSamples > MAXCHANNELS )\n\t\treturn MAXCHANNELS;\n\t\n\treturn _maxSamples;\n}\n\nuint32 cSampleManager::GetNum3DProvidersAvailable()\n{\n\treturn m_nNumberOfProviders;\n}\n\nvoid cSampleManager::SetNum3DProvidersAvailable(uint32 num)\n{\n\tm_nNumberOfProviders = num;\n}\n\t\nchar *cSampleManager::Get3DProviderName(uint8 id)\n{\n\treturn m_aAudioProviders[id];\n}\n\nvoid cSampleManager::Set3DProviderName(uint8 id, char *name)\n{\n\tm_aAudioProviders[id] = name;\n}\n\nint8\ncSampleManager::GetCurrent3DProviderIndex(void)\n{\n\treturn curprovider;\n}\n\nint8\ncSampleManager::SetCurrent3DProvider(uint8 nProvider)\n{\n\tS32 savedprovider = curprovider;\n\t\n\tif ( nProvider < m_nNumberOfProviders )\n\t{\n\t\tif ( set_new_provider(nProvider) )\n\t\t\treturn curprovider;\n\t\telse if ( savedprovider != -1 && savedprovider < m_nNumberOfProviders && set_new_provider(savedprovider) )\n\t\t\treturn curprovider;\n\t\telse\n\t\t\treturn -1;\n\t}\n\telse\n\t\treturn curprovider;\n}\n\nint8\ncSampleManager::AutoDetect3DProviders()\n{\n\tif (!AudioManager.IsAudioInitialised())\n\t\treturn -1;\n\n\tint eax = -1, eax2 = -1, eax3 = -1, ds3dh = -1, ds3ds = -1;\n\n\tfor (uint32 i = 0; i < GetNum3DProvidersAvailable(); i++)\n\t{\n\t\tchar* providername = Get3DProviderName(i);\n\n\t\tif (!strcasecmp(providername, \"CREATIVE LABS EAX (TM)\")) {\n\t\t\tAudioManager.SetCurrent3DProvider(i);\n\t\t\tif (GetCurrent3DProviderIndex() == i)\n\t\t\t\teax = i;\n\t\t}\n\n\t\tif (!strcasecmp(providername, \"CREATIVE LABS EAX 2 (TM)\")) {\n\t\t\tAudioManager.SetCurrent3DProvider(i);\n\t\t\tif (GetCurrent3DProviderIndex() == i)\n\t\t\t\teax2 = i;\n\t\t}\n\n\t\tif (!strcasecmp(providername, \"CREATIVE LABS EAX 3 (TM)\")) {\n\t\t\tAudioManager.SetCurrent3DProvider(i);\n\t\t\tif (GetCurrent3DProviderIndex() == i) {\n\t\t\t\teax3 = i;\n\t\t\t}\n\t\t}\n\n\t\tif (!strcasecmp(providername, \"DIRECTSOUND3D HARDWARE SUPPORT\")) {\n\t\t\tAudioManager.SetCurrent3DProvider(i);\n\t\t\tif (GetCurrent3DProviderIndex() == i)\n\t\t\t\tds3dh = i;\n\t\t}\n\n\t\tif (!strcasecmp(providername, \"DIRECTSOUND3D SOFTWARE EMULATION\")) {\n\t\t\tAudioManager.SetCurrent3DProvider(i);\n\t\t\tif (GetCurrent3DProviderIndex() == i)\n\t\t\t\tds3ds = i;\n\t\t}\n\t}\n\n\tif (eax3 != -1)\n\t\treturn eax3;\n\tif (eax2 != -1)\n\t\treturn eax2;\n\tif (eax != -1)\n\t\treturn eax;\n\tif (ds3dh != -1)\n\t\treturn ds3dh;\n\tif (ds3ds != -1)\n\t\treturn ds3ds;\n\treturn -1;\n}\n\nstatic bool\n_ResolveLink(char const *path, char *out)\n{\n\tIShellLink* psl;\n\tWIN32_FIND_DATA fd;\n\tchar filepath[MAX_PATH];\n\t\n\tCoInitialize(NULL);\n\t\t\t\t\t\t\t\t\t   \n\tif (SUCCEEDED( CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID*)&psl ) ))\n\t{\n\t\tIPersistFile *ppf;\n\n\t\tif (SUCCEEDED(psl->QueryInterface(IID_IPersistFile, (LPVOID*)&ppf)))\n\t\t{\n\t\t\tWCHAR wpath[MAX_PATH];\n\t\t\t\n\t\t\tMultiByteToWideChar(CP_ACP, 0, path, -1, wpath, MAX_PATH);\n\t\t\t\n\t\t\tif (SUCCEEDED(ppf->Load(wpath, STGM_READ)))\n\t\t\t{\n\t\t\t\t/* Resolve the link */\n\t\t\t\tif (SUCCEEDED(psl->Resolve(NULL, SLR_ANY_MATCH|SLR_NO_UI|SLR_NOSEARCH)))\n\t\t\t\t{\n\t\t\t\t\tstrcpy(filepath, path);\n\t\t\t\t\t\n\t\t\t\t\tif (SUCCEEDED(psl->GetPath(filepath, MAX_PATH, &fd, SLGP_UNCPRIORITY)))\n\t\t\t\t\t{\n\t\t\t\t\t\tOutputDebugString(fd.cFileName);\n\t\t\t\t\t\t\n\t\t\t\t\t\tstrcpy(out, filepath);\n\t\t\t\t\t\t// FIX: Release the objects. Taken from SA.\n#ifdef FIX_BUGS\n\t\t\t\t\t\tppf->Release();\n\t\t\t\t\t\tpsl->Release();\n#endif\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tppf->Release();\n\t\t}\n\t\tpsl->Release();\n\t}\n\t\n\treturn false;\n}\n\nstatic void\n_FindMP3s(void)\n{\n\ttMP3Entry *pList;\n\tbool bShortcut;\t\n\tbool bInitFirstEntry;\t\n\tHANDLE hFind;\n\tchar path[MAX_PATH];\n\tchar filepath[MAX_PATH*2];\n\tS32 total_ms;\n\tWIN32_FIND_DATA fd;\n\t\n\t\n\tif ( GetCurrentDirectory(MAX_PATH, _mp3DirectoryPath) == 0 )\n\t{\n\t\tGetLastError();\n\t\treturn;\n\t}\n\t\n\tOutputDebugString(\"Finding MP3s...\");\n\tstrcpy(path, _mp3DirectoryPath);\n\tstrcat(path, \"\\\\MP3\\\\\");\n\t\n\tstrcpy(_mp3DirectoryPath, path);\n\tOutputDebugString(_mp3DirectoryPath);\n\t\n\tstrcat(path, \"*\");\n\t\n\thFind = FindFirstFile(path, &fd);\n\t\n\tif ( hFind == INVALID_HANDLE_VALUE ) \n\t{\n\t\tGetLastError();\n\t\treturn;\n\t}\n\t\n\tstrcpy(filepath, _mp3DirectoryPath);\n\tstrcat(filepath, fd.cFileName);\n\t\n\tint32 filepathlen = strlen(filepath);\n\t\n\tif ( filepathlen <= 0)\n\t{\n\t\tFindClose(hFind);\n\t\treturn;\n\t}\n\n\tif ( filepathlen > 4 )\n\t{\n\t\tif ( !strcmp(&filepath[filepathlen - 4], \".lnk\") )\n\t\t{\n\t\t\tif ( _ResolveLink(filepath, filepath) )\n\t\t\t{\n\t\t\t\tOutputDebugString(\"Resolving Link\");\n\t\t\t\tOutputDebugString(filepath);\n\t\t\t}\n\t\t\t\n\t\t\tbShortcut = true;\n\t\t}\n\t\telse\n\t\t\tbShortcut = false;\n\t}\n\t\n\tmp3Stream[0] = AIL_open_stream(DIG, filepath, 0);\n\tif ( mp3Stream[0] )\n\t{\n\t\tAIL_stream_ms_position(mp3Stream[0], &total_ms, NULL);\n\t\t\n\t\tAIL_close_stream(mp3Stream[0]);\n\t\tmp3Stream[0] = NULL;\n\t\t\n\t\tOutputDebugString(fd.cFileName);\n\t\t\n\t\t_pMP3List = new tMP3Entry;\n\t\t\n\t\tif ( _pMP3List == NULL )\n\t\t{\n\t\t\tFindClose(hFind);\n\t\t\treturn;\n\t\t}\n\t\t\n\t\tnNumMP3s = 1;\n\t\t\n\t\tstrcpy(_pMP3List->aFilename, fd.cFileName);\n\t\t\n\t\t_pMP3List->nTrackLength = total_ms;\n\t\t\n\t\t_pMP3List->pNext = NULL;\n\t\t\n\t\tpList = _pMP3List;\n\t\t\n\t\tif ( bShortcut )\n\t\t{\n\t\t\t_pMP3List->pLinkPath = new char[MAX_PATH*2];\n\t\t\tstrcpy(_pMP3List->pLinkPath, filepath);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_pMP3List->pLinkPath = NULL;\n\t\t}\n\t\tbInitFirstEntry = false;\n\t}\n\telse\n\t{\n\t\tstrcat(filepath, \" - NOT A VALID MP3\");\n\t\t\n\t\tOutputDebugString(filepath);\n\n\t\tbInitFirstEntry = true;\n\t}\n\t\n\twhile ( true )\n\t{\n\t\tif ( !FindNextFile(hFind, &fd) )\n\t\t\tbreak;\n\t\t\n\t\tif ( bInitFirstEntry )\n\t\t{\n\t\t\tstrcpy(filepath, _mp3DirectoryPath);\n\t\t\tstrcat(filepath, fd.cFileName);\n\t\t\t\n\t\t\tint32 filepathlen = strlen(filepath);\n\t\t\t\n\t\t\tif ( filepathlen > 0 )\n\t\t\t{\n\t\t\t\tif ( filepathlen > 4 )\n\t\t\t\t{\n\t\t\t\t\tif ( !strcmp(&filepath[filepathlen - 4], \".lnk\") )\n\t\t\t\t\t{\n\t\t\t\t\t\tif ( _ResolveLink(filepath, filepath) )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tOutputDebugString(\"Resolving Link\");\n\t\t\t\t\t\t\tOutputDebugString(filepath);\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\tbShortcut = true;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tbShortcut = false;\n\t\t\t\t\t\t\n\t\t\t\t\t\tif ( filepathlen > MAX_PATH )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tmp3Stream[0] = AIL_open_stream(DIG, filepath, 0);\n\t\t\t\tif ( mp3Stream[0] )\n\t\t\t\t{\n\t\t\t\t\tAIL_stream_ms_position(mp3Stream[0], &total_ms, NULL);\n\t\t\t\t\t\n\t\t\t\t\tAIL_close_stream(mp3Stream[0]);\n\t\t\t\t\tmp3Stream[0] = NULL;\n\t\t\t\t\t\n\t\t\t\t\tOutputDebugString(fd.cFileName);\n\t\t\t\t\t\n\t\t\t\t\t_pMP3List = new tMP3Entry;\n\t\t\t\t\t\n\t\t\t\t\tif ( _pMP3List  == NULL)\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t\n\t\t\t\t\tnNumMP3s = 1;\n\t\t\t\t\t\n\t\t\t\t\tstrcpy(_pMP3List->aFilename, fd.cFileName);\n\t\t\t\t\t\n\t\t\t\t\t_pMP3List->nTrackLength = total_ms;\n\t\t\t\t\t_pMP3List->pNext = NULL;\n\t\t\t\t\t\n\t\t\t\t\tif ( bShortcut )\n\t\t\t\t\t{\n\t\t\t\t\t\t_pMP3List->pLinkPath = new char [MAX_PATH*2];\n\t\t\t\t\t\tstrcpy(_pMP3List->pLinkPath, filepath);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t_pMP3List->pLinkPath = NULL;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tpList = _pMP3List;\n\n\t\t\t\t\tbInitFirstEntry = false;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tstrcat(filepath, \" - NOT A VALID MP3\");\n\t\t\t\t\tOutputDebugString(filepath);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tstrcpy(filepath, _mp3DirectoryPath);\n\t\t\tstrcat(filepath, fd.cFileName);\n\t\t\t\n\t\t\tint32 filepathlen = strlen(filepath);\n\t\t\t\n\t\t\tif ( filepathlen > 0 )\n\t\t\t{\n\t\t\t\tif ( filepathlen > 4 )\n\t\t\t\t{\n\t\t\t\t\tif ( !strcmp(&filepath[filepathlen - 4], \".lnk\") )\n\t\t\t\t\t{\n\t\t\t\t\t\tif ( _ResolveLink(filepath, filepath) )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tOutputDebugString(\"Resolving Link\");\n\t\t\t\t\t\t\tOutputDebugString(filepath);\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\tbShortcut = true;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tbShortcut = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tmp3Stream[0] = AIL_open_stream(DIG, filepath, 0);\n\t\t\t\tif ( mp3Stream[0] )\n\t\t\t\t{\n\t\t\t\t\tAIL_stream_ms_position(mp3Stream[0], &total_ms, NULL);\n\t\t\t\t\t\n\t\t\t\t\tAIL_close_stream(mp3Stream[0]);\n\t\t\t\t\tmp3Stream[0] = NULL;\n\t\t\t\t\t\n\t\t\t\t\tpList->pNext = new tMP3Entry;\n\t\t\t\t\t\n\t\t\t\t\ttMP3Entry *e = pList->pNext;\n\t\t\t\t\t\n\t\t\t\t\tif ( e == NULL )\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t\n\t\t\t\t\tpList = pList->pNext;\n\t\t\t\t\t\n\t\t\t\t\tstrcpy(e->aFilename, fd.cFileName);\n\t\t\t\t\te->nTrackLength = total_ms;\n\t\t\t\t\te->pNext = NULL;\n\t\t\t\t\t\n\t\t\t\t\tif ( bShortcut )\n\t\t\t\t\t{\n\t\t\t\t\t\te->pLinkPath = new char [MAX_PATH*2];\n\t\t\t\t\t\tstrcpy(e->pLinkPath, filepath);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\te->pLinkPath = NULL;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tnNumMP3s++;\n\t\t\t\t\t\n\t\t\t\t\tOutputDebugString(fd.cFileName);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tstrcat(filepath, \" - NOT A VALID MP3\");\n\t\t\t\t\tOutputDebugString(filepath);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tFindClose(hFind);\n}\n\nstatic void\n_DeleteMP3Entries(void)\n{\n\ttMP3Entry *e = _pMP3List;\n\n\twhile ( e != NULL )\n\t{\n\t\ttMP3Entry *next = e->pNext;\n\t\t\n\t\tif ( next == NULL )\n\t\t\tnext = NULL;\n\t\t\n\t\tif ( e->pLinkPath != NULL )\n\t\t{\n#ifndef FIX_BUGS\n\t\t\tdelete   e->pLinkPath; // BUG: should be delete []\n#else\n\t\t\tdelete[] e->pLinkPath;\n#endif\n\t\t\te->pLinkPath = NULL;\n\t\t}\n\t\t\n\t\tdelete e;\n\t\t\n\t\tif ( next )\n\t\t\te = next;\n\t\telse\n\t\t\te = NULL;\n\t\t\n\t\tnNumMP3s--;\n\t}\n\t\n\t\n\tif ( nNumMP3s != 0 )\n\t{\n\t\tOutputDebugString(\"Not all MP3 entries were deleted\");\n\t\tnNumMP3s = 0;\n\t}\n\t\n\t_pMP3List = NULL;\n}\n\nstatic tMP3Entry *\n_GetMP3EntryByIndex(uint32 idx)\n{\n\tuint32 n = ( idx < nNumMP3s ) ? idx : 0;\n\t\n\tif ( _pMP3List != NULL )\n\t{\n\t\ttMP3Entry *e = _pMP3List;\n\t\t\n\t\tfor ( uint32 i = 0; i < n; i++ )\n\t\t\te = e->pNext;\n\t\t\n\t\treturn e;\n\t\t\t\n\t}\n\t\n\treturn NULL;\n}\n\nstatic inline bool\n_GetMP3PosFromStreamPos(uint32 *pPosition, tMP3Entry **pEntry)\n{\n\t_CurMP3Index = 0;\n\t\n\tfor ( *pEntry = _pMP3List; *pEntry != NULL; *pEntry = (*pEntry)->pNext )\n\t{\n\t\tif (   *pPosition >= (*pEntry)->nTrackStreamPos\n\t\t\t&& *pPosition <  (*pEntry)->nTrackLength + (*pEntry)->nTrackStreamPos )\n\t\t{\n\t\t\t*pPosition -= (*pEntry)->nTrackStreamPos;\n\t\t\t_CurMP3Pos = *pPosition;\n\t\t\t\n\t\t\treturn true;\n\t\t}\n\t\t\n\t\t_CurMP3Index++;\n\t}\n\t\t\t\t\n\t*pPosition = 0;\n\t*pEntry = _pMP3List;\n\t_CurMP3Pos = 0;\n\t_CurMP3Index = 0;\n\t\n\treturn false;\n}\n\nbool\ncSampleManager::IsMP3RadioChannelAvailable(void)\n{\n\treturn nNumMP3s != 0;\n}\n\nvoid\ncSampleManager::ReleaseDigitalHandle(void)\n{\n\tif ( DIG )\n\t{\n\t\tprevprovider = curprovider;\n\t\trelease_existing();\n\t\tcurprovider = -1;\n\t\tAIL_digital_handle_release(DIG);\n\t}\n}\n\nvoid\ncSampleManager::ReacquireDigitalHandle(void)\n{\n\tif ( DIG )\n\t{\n\t\tAIL_digital_handle_reacquire(DIG);\n\t\tif ( prevprovider != -1 )\n\t\t\tset_new_provider(prevprovider);\n\t}\n}\n\nbool\ncSampleManager::Initialise(void)\n{\n\tTRACE(\"start\");\n\t\n\tif ( _bSampmanInitialised )\n\t\treturn true;\n\n\t{\n\t\tfor ( int32 i = 0; i < TOTAL_AUDIO_SAMPLES; i++ )\n\t\t{\n\t\t\tm_aSamples[i].nOffset    = 0;\n\t\t\tm_aSamples[i].nSize      = 0;\n\t\t\tm_aSamples[i].nFrequency = 22050;\n\t\t\tm_aSamples[i].nLoopStart = 0;\n\t\t\tm_aSamples[i].nLoopEnd   = -1;\n\t\t}\n\t\t\n\t\tm_nEffectsVolume     = MAX_VOLUME;\n\t\tm_nMusicVolume       = MAX_VOLUME;\n\t\tm_nEffectsFadeVolume = MAX_VOLUME;\n\t\tm_nMusicFadeVolume   = MAX_VOLUME;\n\t\t\n\t\tm_nMonoMode = 0;\n\t}\n\t\n\t// miles \n\tTRACE(\"MILES\");\n\t{\n\t\tcurprovider = -1;\n\t\tprevprovider = -1;\n\t\t\n\t\t_usingMilesFast2D = false;\n\t\tusingEAX=0;\n\t\tusingEAX3=0;\n\t\t\n\t\t_fEffectsLevel = 0.0f;\n\t\t\n\t\t_maxSamples = 0;\n\t\n\t\topened_provider = NULL;\n\t\tDIG = NULL;\n\t\t\n\t\tfor ( int32 i = 0; i < MAXCHANNELS; i++ )\n\t\t\topened_samples[i] = NULL;\n\t}\n\t\n\t// banks\n\tTRACE(\"banks\");\n\t{\n\t\tfpSampleDescHandle = NULL;\n\t\tfpSampleDataHandle = NULL;\n\t\t\n\t\t_nSampleDataEndOffset = 0;\n\t\t\n\t\tfor ( int32 i = 0; i < MAX_SFX_BANKS; i++ )\n\t\t{\n\t\t\tbSampleBankLoaded[i]             = false;\n\t\t\tnSampleBankDiscStartOffset[i]    = 0;\n\t\t\tnSampleBankSize[i]               = 0;\n\t\t\tnSampleBankMemoryStartAddress[i] = 0;\n\t\t}\n\t}\n\t\n\t// pedsfx\n\tTRACE(\"pedsfx\");\n\t{\n\t\tfor ( int32 i = 0; i < MAX_PEDSFX; i++ )\n\t\t{\n\t\t\tnPedSlotSfx[i]     = NO_SAMPLE;\n\t\t\tnPedSlotSfxAddr[i] = 0;\n\t\t}\n\t\t\n\t\tnCurrentPedSlot = 0;\n\t}\n\t\n\t// channel volume\n\tTRACE(\"vol\");\n\t{\n\t\tfor ( int32 i = 0; i < MAXCHANNELS+MAX2DCHANNELS; i++ )\n\t\t\tnChannelVolume[i] = 0;\n\t}\n\t\n\tTRACE(\"mss\");\n\t{\n\t\tAIL_set_redist_directory( \"mss\" );\n\t\t\n\t\tAIL_startup();\n\t\t\n\t\tAIL_set_preference(DIG_MIXER_CHANNELS, MAX_DIGITAL_MIXER_CHANNELS);\n\t\t\n\t\tDIG = AIL_open_digital_driver(DIGITALRATE, DIGITALBITS, DIGITALCHANNELS, 0);\t\t\n\t\t\n\t}\n\t\n#ifdef AUDIO_CACHE\n\tTRACE(\"cache\");\n\tFILE *cacheFile = fcaseopen(\"audio\\\\sound.cache\", \"rb\");\n\tbool CreateCache = false;\n\tif (cacheFile) {\n\t\tfread(nStreamLength, sizeof(uint32), TOTAL_STREAMED_SOUNDS, cacheFile);\n\t\tfclose(cacheFile);\n\t}else\n\t\tCreateCache = true;\n#endif\n\t\n\tchar filepath[MAX_PATH];\n\tbool bFileNotFound;\n\tS32 tatalms;\n\n\tTRACE(\"cdrom\");\n\t{\n\t\tm_bInitialised = false;\n\n\t\t\n\t\twhile (true)\n\t\t{\n\n\t\t\t// Find path of WAVs (originally in HDD)\n\t\t\tint32 drive = 'C';\n\t\t\t\n#ifndef NO_CDCHECK\n\t\t\tdo\n\t\t\t{\n\t\t\t\tchar latter[2];\n\t\t\t\t\n\t\t\t\tlatter[0] = drive;\n\t\t\t\tlatter[1] = '\\0';\n\t\t\t\t\n\t\t\t\tstrcpy(m_szCDRomRootPath, latter);\n\t\t\t\tstrcat(m_szCDRomRootPath, \":\\\\\");\n\t\t\t\t\n\t\t\t\tif ( GetDriveType(m_szCDRomRootPath) == DRIVE_CDROM )\n\t\t\t\t{\n\t\t\t\t\tstrcpy(filepath, m_szCDRomRootPath);\n\t\t\t\t\tstrcat(filepath, StreamedNameTable[0]);\n\t\t\t\t\t\n\t\t\t\t\tFILE *f = fopen(filepath, \"rb\");\n\t\t\t\t\t\n\t\t\t\t\tif ( f )\n\t\t\t\t\t{\n\t\t\t\t\t\tfclose(f);\n\t\t\t\t\t\tstrcpy(m_MiscomPath, m_szCDRomRootPath);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t} while ( ++drive <= 'Z' );\n#else\n\t\t\tm_MiscomPath[0] = '\\0';\n#endif\n\n\t\t\tif ( DIG == NULL )\n\t\t\t{\n\t\t\t\tOutputDebugString(AIL_last_error());\n\t\t\t\tTerminate();\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\t\n\t\t\tadd_providers();\n\n\t\t\tm_szCDRomRootPath[0] = '\\0';\n\n\t\t\tstrcpy(m_WavFilesPath, m_szCDRomRootPath);\n\n#ifdef AUDIO_CACHE\n\t\t\tif ( CreateCache )\n#endif\n\t\t\tfor ( int32 i = STREAMED_SOUND_MISSION_MOBR1; i < TOTAL_STREAMED_SOUNDS; i++ )\n\t\t\t{\n\t\t\t\tstrcpy(filepath, m_szCDRomRootPath);\n\t\t\t\tstrcat(filepath, StreamedNameTable[i]);\n\t\t\t\t\n\t\t\t\tmp3Stream[0] = AIL_open_stream(DIG, filepath, 0);\n\t\t\t\t\n\t\t\t\tif ( mp3Stream[0] )\n\t\t\t\t{\n\t\t\t\t\tAIL_stream_ms_position(mp3Stream[0], &tatalms, NULL);\n\t\t\t\t\t\n\t\t\t\t\tAIL_close_stream(mp3Stream[0]);\n\t\t\t\t\tmp3Stream[0] = NULL;\n\t\t\t\t\t\n\t\t\t\t\tnStreamLength[i] = tatalms;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tm_bInitialised = false;\n\t\t\t\t\tTerminate();\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Find path of MP3s (originally in CD-Rom)\n\t\t\t// if NO_CDCHECK is NOT defined but AUDIO_CACHE is defined, we still need to find MP3s' path, but will exit after the first file\n#ifndef NO_CDCHECK\n\t\t\tint32 drive = 'C';\n\t\t\tdo\n\t\t\t{\n\t\t\t\tlatter[0] = drive;\n\t\t\t\tlatter[1] = '\\0';\n\t\t\t\t\n\t\t\t\tstrcpy(m_szCDRomRootPath, latter);\n\t\t\t\tstrcat(m_szCDRomRootPath, \":\");\n\t\t\t\tstrcat(m_MP3FilesPath, m_szCDRomRootPath);\n#else\n\t\t\tm_MP3FilesPath[0] = '\\0';\n\t\t\t{\n#endif\n\n\t\t\t\tfor (int32 i = 0; i < STREAMED_SOUND_MISSION_MOBR1; i++)\n\t\t\t\t{\n\t\t\t\t\tstrcpy(filepath, m_MP3FilesPath);\n\t\t\t\t\tstrcat(filepath, StreamedNameTable[i]);\n\n\t\t\t\t\tmp3Stream[0] = AIL_open_stream(DIG, filepath, 0);\n\n\t\t\t\t\tif (mp3Stream[0])\n\t\t\t\t\t{\n\t\t\t\t\t\tAIL_stream_ms_position(mp3Stream[0], &tatalms, NULL);\n\n\t\t\t\t\t\tAIL_close_stream(mp3Stream[0]);\n\t\t\t\t\t\tmp3Stream[0] = NULL;\n\n\t\t\t\t\t\tbFileNotFound = false;\n#ifdef AUDIO_CACHE\n\t\t\t\t\t\tif (!CreateCache)\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\telse\n#endif\n\t\t\t\t\t\t\tnStreamLength[i] = tatalms;\n\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tbFileNotFound = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n#ifndef NO_CDCHECK\n\t\t\t\tif (!bFileNotFound) // otherwise try next drive\n\t\t\t\t\tbreak;\n\n\t\t\t}\n\t\t\twhile (++drive <= 'Z');\n#else\n\t\t\t}\n#endif\n\n\t\t\tif ( !bFileNotFound ) {\n\n#ifdef AUDIO_CACHE\n\t\t\tif ( CreateCache )\n#endif\n\t\t\t\tfor ( int32 i = STREAMED_SOUND_MISSION_COMPLETED4; i < STREAMED_SOUND_MISSION_PAGER; i++ )\n\t\t\t\t{\n\t\t\t\t\tstrcpy(filepath, m_MiscomPath);\n\t\t\t\t\tstrcat(filepath, StreamedNameTable[i]);\n\t\t\t\t\t\n\t\t\t\t\tmp3Stream[0] = AIL_open_stream(DIG, filepath, 0);\n\t\t\t\t\t\n\t\t\t\t\tif ( mp3Stream[0] )\n\t\t\t\t\t{\n\t\t\t\t\t\tAIL_stream_ms_position(mp3Stream[0], &tatalms, NULL);\n\t\t\t\t\t\t\n\t\t\t\t\t\tAIL_close_stream(mp3Stream[0]);\n\t\t\t\t\t\tmp3Stream[0] = NULL;\n\t\t\t\t\t\t\n\t\t\t\t\t\tnStreamLength[i] = tatalms;\n\t\t\t\t\t\tbFileNotFound = false;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tbFileNotFound = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tm_bInitialised = !bFileNotFound;\n\n\t\t\tif ( !m_bInitialised )\n\t\t\t{\n#if !defined(GTA3_STEAM_PATCH) && !defined(NO_CDCHECK)\n\t\t\t\tFrontEndMenuManager.WaitForUserCD();\n\t\t\t\tif ( FrontEndMenuManager.m_bQuitGameNoCD )\n\t\t\t\t{\n\t\t\t\t\tTerminate();\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tcontinue;\n#else\n\t\t\t\tm_bInitialised = true;\n#endif\n\t\t\t}\n\t\t\t\n\t\t\tbreak;\n\t\t}\n\t}\n\n#ifdef AUDIO_CACHE\n\tif (CreateCache) {\n\t\tcacheFile = fcaseopen(\"audio\\\\sound.cache\", \"wb\");\n\t\tfwrite(nStreamLength, sizeof(uint32), TOTAL_STREAMED_SOUNDS, cacheFile);\n\t\tfclose(cacheFile);\n\t}\n#endif\n\n\tif ( !InitialiseSampleBanks() )\n\t{\n\t\tTerminate();\n\t\treturn false;\n\t}\n\t\n\tnSampleBankMemoryStartAddress[SFX_BANK_0] = (int32)AIL_mem_alloc_lock(nSampleBankSize[SFX_BANK_0]);\n\tif ( !nSampleBankMemoryStartAddress[SFX_BANK_0] )\n\t{\n\t\tTerminate();\n\t\treturn false;\n\t}\n\n\tnSampleBankMemoryStartAddress[SFX_BANK_PED_COMMENTS] = (int32)AIL_mem_alloc_lock(PED_BLOCKSIZE*MAX_PEDSFX);\n\n\tLoadSampleBank(SFX_BANK_0);\n\n\tTRACE(\"stream\");\n\t{\n\t\tfor ( int32 i = 0; i < MAX_STREAMS; i++ )\n\t\t{\n\t\t\tmp3Stream    [i] = NULL;\n\t\t\tnStreamPan   [i] = 63;\n\t\t\tnStreamVolume[i] = 100;\n\t\t}\n\t}\n\t\n\tfor ( int32 i = 0; i < MAX2DCHANNELS; i++ )\n\t{\n\t\topened_2dsamples[i] = AIL_allocate_sample_handle(DIG);\n\t\tif ( opened_2dsamples[i] )\n\t\t{\n\t\t\tAIL_init_sample(opened_2dsamples[i]);\n\t\t\tAIL_set_sample_type(opened_2dsamples[i], DIG_F_MONO_16, DIG_PCM_SIGN);\n\t\t}\n\t}\n\t\n\tTRACE(\"providerset\");\n\t{\n\t\t_bSampmanInitialised = true;\n\t\t\n\t\tU32 n = 0;\n\t\t\n\t\twhile ( n < m_nNumberOfProviders )\n\t\t{\n\t\t\tif ( !strcmp(strupr(providers[n].name), \"DIRECTSOUND3D SOFTWARE EMULATION\") )\n\t\t\t{\n\t\t\t\tset_new_provider(n);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tn++;\n\t\t}\n\t\t\n\t\tif ( n == m_nNumberOfProviders )\n\t\t{\n\t\t\tTerminate();\n\t\t\treturn false;\n\t\t}\n\t}\n\t\n\t// mp3\n\tTRACE(\"mp3\");\n\t{\n\t\tnNumMP3s = 0;\n\t\t\n\t\t_pMP3List = NULL;\n\t\t\n\t\t_FindMP3s();\n\t\t\n\t\tif ( nNumMP3s != 0 )\n\t\t{\n\t\t\tnStreamLength[STREAMED_SOUND_RADIO_MP3_PLAYER] = 0;\n\t\t\t\n\t\t\tfor ( tMP3Entry *e = _pMP3List; e != NULL; e = e->pNext )\n\t\t\t{\n\t\t\t\te->nTrackStreamPos = nStreamLength[STREAMED_SOUND_RADIO_MP3_PLAYER];\n\t\t\t\tnStreamLength[STREAMED_SOUND_RADIO_MP3_PLAYER] += e->nTrackLength;\n\t\t\t}\n\t\t\t\n\t\t\ttime_t t = time(NULL);\n\t\t\ttm *localtm;\n\t\t\tbool bUseRandomTable;\n\t\t\t\n\t\t\tif ( t == -1 )\n\t\t\t\tbUseRandomTable = true;\n\t\t\telse\n\t\t\t{\n\t\t\t\tbUseRandomTable = false;\n\t\t\t\tlocaltm = localtime(&t);\n\t\t\t}\n\t\t\t\n\t\t\tint32 randval;\n\t\t\tif ( bUseRandomTable )\n\t\t\t\trandval = AudioManager.GetRandomNumber(1);\n\t\t\telse\n\t\t\t\trandval = localtm->tm_sec * localtm->tm_min;\n\t\t\t\n\t\t\t_CurMP3Index = randval % nNumMP3s;\n\t\t\t\n\t\t\ttMP3Entry *randmp3 = _pMP3List;\n\t\t\tfor ( int32 i = randval % nNumMP3s; i > 0; --i)\n\t\t\t\trandmp3 = randmp3->pNext;\n\t\t\t\n\t\t\tif ( bUseRandomTable )\n\t\t\t\t_CurMP3Pos = AudioManager.GetRandomNumber(0)     % randmp3->nTrackLength;\n\t\t\telse\n\t\t\t{\n\t\t\t\tif ( localtm->tm_sec > 0 )\n\t\t\t\t{\n\t\t\t\t\tint32 s = localtm->tm_sec;\n\t\t\t\t\t_CurMP3Pos = s*s*s*s*s*s*s*s                 % randmp3->nTrackLength;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\t_CurMP3Pos = AudioManager.GetRandomNumber(0) % randmp3->nTrackLength;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t\t_CurMP3Pos = 0;\n\t\t\n\t\t_bIsMp3Active = false;\n\t}\n\t\n\tTRACE(\"end\");\n\t\n\treturn true;\n}\n\nvoid\ncSampleManager::Terminate(void)\n{\n\tfor ( int32 i = 0; i < MAX_STREAMS; i++ )\n\t{\n\t\tif ( mp3Stream[i] )\n\t\t{\n\t\t\tAIL_pause_stream(mp3Stream[i], 1);\n\t\t\tAIL_close_stream(mp3Stream[i]);\n\t\t\tmp3Stream[i] = NULL;\n\t\t}\n\t}\n\t\n\tfor ( int32 i = 0; i < MAX2DCHANNELS; i++ )\n\t{\n\t\tif ( opened_2dsamples[i] )\n\t\t{\n\t\t\tAIL_release_sample_handle(opened_2dsamples[i]);\n\t\t\topened_2dsamples[i] = NULL;\n\t\t}\n\t}\n\t\n\trelease_existing();\n\t\n\t_DeleteMP3Entries();\n\t\n\tif ( nSampleBankMemoryStartAddress[SFX_BANK_0] != 0 )\n\t{\n\t\tAIL_mem_free_lock((void *)nSampleBankMemoryStartAddress[SFX_BANK_0]);\n\t\tnSampleBankMemoryStartAddress[SFX_BANK_0] = 0;\n\t}\n\n\tif ( nSampleBankMemoryStartAddress[SFX_BANK_PED_COMMENTS] != 0 )\n\t{\n\t\tAIL_mem_free_lock((void *)nSampleBankMemoryStartAddress[SFX_BANK_PED_COMMENTS]);\n\t\tnSampleBankMemoryStartAddress[SFX_BANK_PED_COMMENTS] = 0;\n\t}\n\t\n\tif ( DIG )\n\t{\n\t\tAIL_close_digital_driver(DIG);\n\t\tDIG = NULL;\n\t}\n\t\n\tAIL_shutdown();\n\t\n\t_bSampmanInitialised = false;\n}\n\nbool\ncSampleManager::CheckForAnAudioFileOnCD(void)\n{\n#if !defined(NO_CDCHECK) // TODO: check steam, probably GTAVC_STEAM_PATCH needs to be added\n\tchar filepath[MAX_PATH];\n\t\n\tstrcpy(filepath, m_MiscomPath);\n\tstrcat(filepath, StreamedNameTable[STREAMED_SOUND_MISSION_COMPLETED4]);\n\n\tFILE *f = fopen(filepath, \"rb\");\n\n\tif ( f )\n\t{\n\t\tfclose(f);\n\t\tDMAudio.SetMusicMasterVolume(FrontEndMenuManager.m_PrefsMusicVolume);\n\t\tDMAudio.SetEffectsMasterVolume(FrontEndMenuManager.m_PrefsSfxVolume);\n\t\tDMAudio.Service();\n\n\t\treturn true;\n\t}\n\n\tDMAudio.SetMusicMasterVolume(0);\n\tDMAudio.SetEffectsMasterVolume(0);\n\tDMAudio.Service();\n\n\treturn false;\n\t\n#else\n\treturn true;\n#endif // #if !defined(NO_CDCHECK)\n}\n\nchar\ncSampleManager::GetCDAudioDriveLetter(void)\n{\n\tif ( strlen(m_MiscomPath) != 0 )\n\t\treturn m_MiscomPath[0];\n\telse\n\t\treturn '\\0';\n}\n\nvoid\ncSampleManager::UpdateEffectsVolume(void) //[Y], cSampleManager::UpdateSoundBuffers ?\n{\n\tif ( _bSampmanInitialised )\n\t{\n\t\tfor ( int32 i = 0; i < MAXCHANNELS+MAX2DCHANNELS; i++ )\n\t\t{\n\t\t\tif ( i < MAXCHANNELS )\n\t\t\t{\n\t\t\t\tif ( opened_samples[i] && GetChannelUsedFlag(i) )\n\t\t\t\t{\n\t\t\t\t\tif ( nChannelVolume[i] )\n\t\t\t\t\t{\n\t\t\t\t\t\tAIL_set_3D_sample_volume(opened_samples[i],\n\t\t\t\t\t\t\t\tm_nEffectsFadeVolume * nChannelVolume[i] * m_nEffectsVolume >> 14);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif ( opened_2dsamples[i - MAXCHANNELS] )\n\t\t\t\t{\n\t\t\t\t\tif ( GetChannelUsedFlag(i - MAXCHANNELS) )\n\t\t\t\t\t{\n\t\t\t\t\t\tif ( nChannelVolume[i - MAXCHANNELS] )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tAIL_set_sample_volume(opened_2dsamples[i - MAXCHANNELS],\n\t\t\t\t\t\t\t\t\tm_nEffectsFadeVolume * nChannelVolume[i - MAXCHANNELS] * m_nEffectsVolume >> 14);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\ncSampleManager::SetEffectsMasterVolume(uint8 nVolume)\n{\n\tm_nEffectsVolume = nVolume;\n\tUpdateEffectsVolume();\n}\n\nvoid\ncSampleManager::SetMusicMasterVolume(uint8 nVolume)\n{\n\tm_nMusicVolume = nVolume;\n}\n\nvoid\ncSampleManager::SetMP3BoostVolume(uint8 nVolume)\n{\n\tm_nMP3BoostVolume = nVolume;\n}\n\nvoid\ncSampleManager::SetEffectsFadeVolume(uint8 nVolume)\n{\n\tm_nEffectsFadeVolume = nVolume;\n\tUpdateEffectsVolume();\n}\n\nvoid\ncSampleManager::SetMusicFadeVolume(uint8 nVolume)\n{\n\tm_nMusicFadeVolume = nVolume;\n}\n\nvoid\ncSampleManager::SetMonoMode(uint8 nMode)\n{\n\tm_nMonoMode = nMode;\n}\n\nbool\ncSampleManager::LoadSampleBank(uint8 nBank)\n{\n\tif ( CTimer::GetIsCodePaused() )\n\t\treturn false;\n\t\n\tif ( MusicManager.IsInitialised()\n\t\t&& MusicManager.GetMusicMode() == MUSICMODE_CUTSCENE\n\t\t&& nBank != SFX_BANK_0 )\n\t{\n\t\treturn false;\n\t}\n\t\n\tif ( fseek(fpSampleDataHandle, nSampleBankDiscStartOffset[nBank], SEEK_SET) != 0 )\n\t\treturn false;\n\t\n\tif ( fread((void *)nSampleBankMemoryStartAddress[nBank], 1, nSampleBankSize[nBank],fpSampleDataHandle) != nSampleBankSize[nBank] )\n\t\treturn false;\n\t\n\tbSampleBankLoaded[nBank] = true;\n\t\n\treturn true;\n}\n\nvoid\ncSampleManager::UnloadSampleBank(uint8 nBank)\n{\n\tbSampleBankLoaded[nBank] = false;\n}\n\nbool\ncSampleManager::IsSampleBankLoaded(uint8 nBank)\n{\n\treturn bSampleBankLoaded[nBank];\n}\n\nbool\ncSampleManager::IsPedCommentLoaded(uint32 nComment)\n{\n\tint8 slot;\n\n\tfor ( int32 i = 0; i < _TODOCONST(3); i++ )\n\t{\n\t\tslot = nCurrentPedSlot - i - 1;\n#ifdef FIX_BUGS\n\t\tif (slot < 0)\n\t\t\tslot += ARRAY_SIZE(nPedSlotSfx);\n#endif\n\t\tif ( nComment == nPedSlotSfx[slot] )\n\t\t\treturn true;\n\t}\n\t\n\treturn false;\n}\n\nint32\ncSampleManager::_GetPedCommentSlot(uint32 nComment)\n{\n\tint8 slot;\n\n\tfor ( int32 i = 0; i < _TODOCONST(3); i++ )\n\t{\n\t\tslot = nCurrentPedSlot - i - 1;\n#ifdef FIX_BUGS\n\t\tif (slot < 0)\n\t\t\tslot += ARRAY_SIZE(nPedSlotSfx);\n#endif\n\t\tif ( nComment == nPedSlotSfx[slot] )\n\t\t\treturn slot;\n\t}\n\t\n\treturn -1;\n}\n\nbool\ncSampleManager::LoadPedComment(uint32 nComment)\n{\n\tif ( CTimer::GetIsCodePaused() )\n\t\treturn false;\n\t\n\t// no talking peds during cutsenes or the game end\n\tif ( MusicManager.IsInitialised() )\n\t{\n\t\tswitch ( MusicManager.GetMusicMode() )\n\t\t{\n\t\t\tcase MUSICMODE_CUTSCENE:\n\t\t\t{\n\t\t\t\treturn false;\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\t\n\tif ( fseek(fpSampleDataHandle, m_aSamples[nComment].nOffset, SEEK_SET) != 0 )\n\t\treturn false;\n\t\n\tif ( fread((void *)(nSampleBankMemoryStartAddress[SFX_BANK_PED_COMMENTS] + PED_BLOCKSIZE*nCurrentPedSlot), 1, m_aSamples[nComment].nSize, fpSampleDataHandle) != m_aSamples[nComment].nSize )\n\t\treturn false;\n\t\n\tnPedSlotSfxAddr[nCurrentPedSlot] = nSampleBankMemoryStartAddress[SFX_BANK_PED_COMMENTS] + PED_BLOCKSIZE*nCurrentPedSlot;\n\tnPedSlotSfx    [nCurrentPedSlot] = nComment;\n\t\n\tif ( ++nCurrentPedSlot >= MAX_PEDSFX )\n\t\tnCurrentPedSlot = 0;\n\t\n\treturn true;\n}\n\nint32\ncSampleManager::GetBankContainingSound(uint32 offset)\n{\n\tif ( offset >= BankStartOffset[SFX_BANK_PED_COMMENTS] )\n\t\treturn SFX_BANK_PED_COMMENTS;\n\t\n\tif ( offset >= BankStartOffset[SFX_BANK_0] )\n\t\treturn SFX_BANK_0;\n\t\n\treturn INVALID_SFX_BANK;\n}\n\nint32\ncSampleManager::GetSampleBaseFrequency(uint32 nSample)\n{\n\treturn m_aSamples[nSample].nFrequency;\n}\n\nint32\ncSampleManager::GetSampleLoopStartOffset(uint32 nSample)\n{\n\treturn m_aSamples[nSample].nLoopStart;\n}\n\nint32\ncSampleManager::GetSampleLoopEndOffset(uint32 nSample)\n{\n\treturn m_aSamples[nSample].nLoopEnd;\n}\n\nuint32\ncSampleManager::GetSampleLength(uint32 nSample)\n{\n\treturn m_aSamples[nSample].nSize >> 1;\n}\n\nbool\ncSampleManager::UpdateReverb(void)\n{\n\tif ( !usingEAX )\n\t\treturn false;\n\t\n\tif ( AudioManager.GetFrameCounter() & 15 )\n\t\treturn false;\n\n\tfloat fRatio = 0.0f;\n\n#define MIN_DIST 0.5f\n#define CALCULATE_RATIO(value, maxDist, maxRatio) (value > MIN_DIST && value < maxDist ? value / maxDist * maxRatio : 0)\n\n\tfRatio += CALCULATE_RATIO(AudioManager.GetReflectionsDistance(REFLECTION_CEIL_NORTH), 10.0f, 1/2.f);\n\tfRatio += CALCULATE_RATIO(AudioManager.GetReflectionsDistance(REFLECTION_CEIL_SOUTH), 10.0f, 1/2.f);\n\tfRatio += CALCULATE_RATIO(AudioManager.GetReflectionsDistance(REFLECTION_CEIL_WEST), 10.0f, 1/2.f);\n\tfRatio += CALCULATE_RATIO(AudioManager.GetReflectionsDistance(REFLECTION_CEIL_EAST), 10.0f, 1/2.f);\n\n\tfRatio += CALCULATE_RATIO((AudioManager.GetReflectionsDistance(REFLECTION_NORTH) + AudioManager.GetReflectionsDistance(REFLECTION_SOUTH)) / 2.f, 4.0f, 1/3.f);\n\tfRatio += CALCULATE_RATIO((AudioManager.GetReflectionsDistance(REFLECTION_WEST) + AudioManager.GetReflectionsDistance(REFLECTION_EAST)) / 2.f, 4.0f, 1/3.f);\n\n#undef CALCULATE_RATIO\n#undef MIN_DIST\n\t\n\tfRatio = clamp(fRatio, 0.0f, 0.6f);\n\t\n\tif ( fRatio == _fPrevEaxRatioDestination )\n\t\treturn false;\n\t\n\tif ( usingEAX3 )\n\t{\n\t\tfRatio = Min(fRatio * 1.67f, 1.0f);\n\t\tif ( EAX3ListenerInterpolate(&StartEAX3, &FinishEAX3, fRatio, &EAX3Params, false) )\n\t\t{\n\t\t\tAIL_set_3D_provider_preference(opened_provider, \"EAX all parameters\", &EAX3Params);\n\t\t\t_fEffectsLevel = fRatio * 0.75f;\n\t\t}\n\t}\n\telse\n\t{\n\t\tif ( _usingMilesFast2D )\n\t\t\t_fEffectsLevel = fRatio * 0.8f;\n\t\telse\n\t\t\t_fEffectsLevel = fRatio * 0.22f;\n\t}\n\t_fEffectsLevel = Min(_fEffectsLevel, 1.0f);\n\n\t_fPrevEaxRatioDestination = fRatio;\n\t\n\treturn true;\n}\n\nvoid\ncSampleManager::SetChannelReverbFlag(uint32 nChannel, uint8 nReverbFlag)\n{\n\tbool b2d = false;\n\t\n\tswitch ( nChannel )\n\t{\n\t\tcase CHANNEL2D:\n\t\t{\n\t\t\tb2d = true;\n\t\t\tbreak;\n\t\t}\n\t}\n\t\n\tif ( usingEAX )\n\t{\n\t\tif ( nReverbFlag != 0 )\n\t\t{\n\t\t\tif ( !b2d )\n\t\t\t\tAIL_set_3D_sample_effects_level(opened_samples[nChannel], _fEffectsLevel);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif ( !b2d )\n\t\t\t\tAIL_set_3D_sample_effects_level(opened_samples[nChannel], 0.0f);\n\t\t}\n\t}\n}\n\nbool\ncSampleManager::InitialiseChannel(uint32 nChannel, uint32 nSfx, uint8 nBank)\n{\n\tbool b2d = false;\n\n\tswitch ( nChannel )\n\t{\n\t\tcase CHANNEL2D:\n\t\t{\n\t\t\tb2d = true;\n\t\t\tbreak;\n\t\t}\n\t}\n\t\n\tint32 addr;\n\t\n\tif ( nSfx < SAMPLEBANK_MAX )\n\t{\n\t\tif ( !IsSampleBankLoaded(nBank) )\n\t\t\treturn false;\n\t\t\n\t\taddr = nSampleBankMemoryStartAddress[nBank] + m_aSamples[nSfx].nOffset - m_aSamples[BankStartOffset[nBank]].nOffset;\n\t}\n\telse\n\t{\t\n\t\tif ( !IsPedCommentLoaded(nSfx) )\n\t\t\treturn false;\n\t\t\n\t\tint32 slot = _GetPedCommentSlot(nSfx);\n\t\t\n\t\taddr = nPedSlotSfxAddr[slot];\n\t}\n\t\n\tif ( b2d )\n\t{\n\t\tif ( opened_2dsamples[nChannel - MAXCHANNELS] )\n\t\t{\n\t\t\tAIL_set_sample_address(opened_2dsamples[nChannel - MAXCHANNELS], (void *)addr, m_aSamples[nSfx].nSize);\n\t\t\treturn true;\n\t\t}\n\t\telse\n\t\t\treturn false;\n\t}\n\telse\n\t{\n\t\tAILSOUNDINFO info;\n\t\t\n\t\tinfo.format   = WAVE_FORMAT_PCM;\n\t\tinfo.data_ptr = (void *)addr;\n\t\tinfo.channels = 1;\n\t\tinfo.data_len = m_aSamples[nSfx].nSize;\n\t\tinfo.rate     = m_aSamples[nSfx].nFrequency;\n\t\tinfo.bits     = 16;\n\t\n\t\tif ( AIL_set_3D_sample_info(opened_samples[nChannel], &info) == 0 )\n\t\t{\n\t\t\tOutputDebugString(AIL_last_error());\n\t\t\treturn false;\n\t\t}\n\t\t\n\t\treturn true;\n\t}\n}\n\nvoid\ncSampleManager::SetChannelEmittingVolume(uint32 nChannel, uint32 nVolume)\n{\n\tuint32 vol = nVolume;\n\tif ( vol > MAX_VOLUME ) vol = MAX_VOLUME;\n\t\n\tnChannelVolume[nChannel] = vol;\n\t\n\t// increase the volume for JB.MP3 and S4_BDBD.MP3\n\tif (MusicManager.GetMusicMode() == MUSICMODE_CUTSCENE ) {\n\t\tif (MusicManager.GetCurrentTrack() == STREAMED_SOUND_CUTSCENE_FINALE)\n\t\t\tnChannelVolume[nChannel] = 0;\n\t\telse\n\t\t\tnChannelVolume[nChannel] >>= 2;\n\t}\n\n\tif ( opened_samples[nChannel] )\n\t\tAIL_set_3D_sample_volume(opened_samples[nChannel], m_nEffectsFadeVolume*nChannelVolume[nChannel]*m_nEffectsVolume >> 14);\n\n}\n\nvoid\ncSampleManager::SetChannel3DPosition(uint32 nChannel, float fX, float fY, float fZ)\n{\n\tif ( opened_samples[nChannel] )\n\t\tAIL_set_3D_position(opened_samples[nChannel], -fX, fY, fZ);\n}\n\nvoid\ncSampleManager::SetChannel3DDistances(uint32 nChannel, float fMax, float fMin)\n{\n\tif ( opened_samples[nChannel] )\n\t\tAIL_set_3D_sample_distances(opened_samples[nChannel], fMax, fMin);\n}\n\nvoid\ncSampleManager::SetChannelVolume(uint32 nChannel, uint32 nVolume)\n{\n\tuint32 vol = nVolume;\n\tif ( vol > MAX_VOLUME ) vol = MAX_VOLUME;\n\t\n\tswitch ( nChannel )\n\t{\n\t\tcase CHANNEL2D:\n\t\t{\n\t\t\tnChannelVolume[nChannel] = vol;\n\t\t\t\n\t\t\t// increase the volume for JB.MP3 and S4_BDBD.MP3\n\t\t\tif (   MusicManager.GetMusicMode()    == MUSICMODE_CUTSCENE\n\t\t\t\t&& MusicManager.GetCurrentTrack() != STREAMED_SOUND_CUTSCENE_FINALE )\n\t\t\t{\n\t\t\t\tnChannelVolume[nChannel] >>= 2;\n\t\t\t}\n\n\t\t\tif ( opened_2dsamples[nChannel - MAXCHANNELS] )\n\t\t\t{\n\t\t\t\tAIL_set_sample_volume(opened_2dsamples[nChannel - MAXCHANNELS],\n\t\t\t\t\t\tm_nEffectsFadeVolume*vol*m_nEffectsVolume >> 14);\n\t\t\t}\n\t\t\t\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\nvoid\ncSampleManager::SetChannelPan(uint32 nChannel, uint32 nPan)\n{\n\tswitch ( nChannel )\n\t{\n\t\tcase CHANNEL2D:\n\t\t{\n#ifndef FIX_BUGS\n\t\t\tif ( opened_samples[nChannel - MAXCHANNELS] ) // BUG\n#else\n\t\t\tif ( opened_2dsamples[nChannel - MAXCHANNELS] )\n#endif\n\t\t\t\tAIL_set_sample_pan(opened_2dsamples[nChannel - MAXCHANNELS], nPan);\n\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\nvoid\ncSampleManager::SetChannelFrequency(uint32 nChannel, uint32 nFreq)\n{\n\tbool b2d = false;\n\n\tswitch ( nChannel )\n\t{\n\t\tcase CHANNEL2D:\n\t\t{\n\t\t\tb2d = true;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tif ( b2d )\n\t{\n\t\tif ( opened_2dsamples[nChannel - MAXCHANNELS] )\n\t\t\tAIL_set_sample_playback_rate(opened_2dsamples[nChannel - MAXCHANNELS], nFreq);\n\t}\n\telse\n\t{\n\t\tif ( opened_samples[nChannel] )\n\t\t\tAIL_set_3D_sample_playback_rate(opened_samples[nChannel], nFreq);\n\t}\n}\n\nvoid\ncSampleManager::SetChannelLoopPoints(uint32 nChannel, uint32 nLoopStart, int32 nLoopEnd)\n{\n\tbool b2d = false;\n\n\tswitch ( nChannel )\n\t{\n\t\tcase CHANNEL2D:\n\t\t{\n\t\t\tb2d = true;\n\t\t\tbreak;\n\t\t}\n\t}\n\t\n\tif ( b2d )\n\t{\n\t\tif ( opened_2dsamples[nChannel - MAXCHANNELS] )\n\t\t\tAIL_set_sample_loop_block(opened_2dsamples[nChannel - MAXCHANNELS], nLoopStart, nLoopEnd);\n\t}\n\telse\n\t{\n\t\tif ( opened_samples[nChannel] )\n\t\t\tAIL_set_3D_sample_loop_block(opened_samples[nChannel], nLoopStart, nLoopEnd);\n\t}\n}\n\nvoid\ncSampleManager::SetChannelLoopCount(uint32 nChannel, uint32 nLoopCount)\n{\n\tbool b2d = false;\n\n\tswitch ( nChannel )\n\t{\n\t\tcase CHANNEL2D:\n\t\t{\n\t\t\tb2d = true;\n\t\t\tbreak;\n\t\t}\n\t}\n\t\n\tif ( b2d )\n\t{\n\t\tif ( opened_2dsamples[nChannel - MAXCHANNELS] )\n\t\t\tAIL_set_sample_loop_count(opened_2dsamples[nChannel - MAXCHANNELS], nLoopCount);\n\t}\n\telse\n\t{\n\t\tif ( opened_samples[nChannel] )\n\t\t\tAIL_set_3D_sample_loop_count(opened_samples[nChannel], nLoopCount);\n\t}\n}\n\nbool\ncSampleManager::GetChannelUsedFlag(uint32 nChannel)\n{\n\tbool b2d = false;\n\n\tswitch ( nChannel )\n\t{\n\t\tcase CHANNEL2D:\n\t\t{\n\t\t\tb2d = true;\n\t\t\tbreak;\n\t\t}\n\t}\n\t\n\tif ( b2d )\n\t{\n\t\tif ( opened_2dsamples[nChannel - MAXCHANNELS] )\n\t\t\treturn AIL_sample_status(opened_2dsamples[nChannel - MAXCHANNELS]) == SMP_PLAYING;\n\t\telse\n\t\t\treturn false;\n\t}\n\telse\n\t{\n\t\tif ( opened_samples[nChannel] )\n\t\t\treturn AIL_3D_sample_status(opened_samples[nChannel]) == SMP_PLAYING;\n\t\telse\n\t\t\treturn false;\n\t}\n\t\n}\n\nvoid\ncSampleManager::StartChannel(uint32 nChannel)\n{\n\tbool b2d = false;\n\n\tswitch ( nChannel )\n\t{\n\t\tcase CHANNEL2D:\n\t\t{\n\t\t\tb2d = true;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tif ( b2d )\n\t{\n\t\tif ( opened_2dsamples[nChannel - MAXCHANNELS] )\n\t\t\tAIL_start_sample(opened_2dsamples[nChannel - MAXCHANNELS]);\n\t}\n\telse\n\t{\n\t\tif ( opened_samples[nChannel] )\n\t\t\tAIL_start_3D_sample(opened_samples[nChannel]);\n\t}\n}\n\nvoid\ncSampleManager::StopChannel(uint32 nChannel)\n{\n\tbool b2d = false;\n\n\tswitch ( nChannel )\n\t{\n\t\tcase CHANNEL2D:\n\t\t{\n\t\t\tb2d = true;\n\t\t\tbreak;\n\t\t}\n\t}\n\t\n\tif ( b2d )\n\t{\n\t\tif ( opened_2dsamples[nChannel - MAXCHANNELS] )\n\t\t\tAIL_end_sample(opened_2dsamples[nChannel - MAXCHANNELS]);\n\t}\n\telse\n\t{\n\t\tif ( opened_samples[nChannel] )\n\t\t{\n\t\t\tif ( AIL_3D_sample_status(opened_samples[nChannel]) == SMP_PLAYING )\n\t\t\t\tAIL_end_3D_sample(opened_samples[nChannel]);\n\t\t}\n\t}\n}\n\nvoid\ncSampleManager::PreloadStreamedFile(uint32 nFile, uint8 nStream)\n{\n\tif ( m_bInitialised  )\n\t{\n\t\tif ( nFile < TOTAL_STREAMED_SOUNDS )\n\t\t{\n\t\t\tif ( mp3Stream[nStream] )\n\t\t\t{\n\t\t\t\tAIL_pause_stream(mp3Stream[nStream], 1);\n\t\t\t\tAIL_close_stream(mp3Stream[nStream]);\n\t\t\t}\n\t\t\t\n\t\t\tchar filepath[MAX_PATH];\n\t\t\t\n\t\t\tstrcpy(filepath, nFile < STREAMED_SOUND_MISSION_COMPLETED4 ? m_MP3FilesPath : (nFile < STREAMED_SOUND_MISSION_MOBR1 ? m_MiscomPath : m_WavFilesPath));\n\t\t\tstrcat(filepath, StreamedNameTable[nFile]);\n\t\t\t\n\t\t\tmp3Stream[nStream] = AIL_open_stream(DIG, filepath, 0);\n\t\n\t\t\tif ( mp3Stream[nStream] )\n\t\t\t{\n\t\t\t\tAIL_set_stream_loop_count(mp3Stream[nStream], 1);\n\t\t\t\tAIL_service_stream(mp3Stream[nStream], 1);\n\t\t\t}\n\t\t\telse\n\t\t\t\tOutputDebugString(AIL_last_error());\n\t\t}\n\t}\n}\n\nvoid\ncSampleManager::PauseStream(uint8 nPauseFlag, uint8 nStream)\n{\n\tif ( m_bInitialised )\n\t{\n\t\tif ( mp3Stream[nStream] )\n\t\t\tAIL_pause_stream(mp3Stream[nStream], nPauseFlag != 0);\n\t}\n}\n\nvoid\ncSampleManager::StartPreloadedStreamedFile(uint8 nStream)\n{\n\tif ( m_bInitialised )\n\t{\n\t\tif ( mp3Stream[nStream] )\n\t\t\tAIL_start_stream(mp3Stream[nStream]);\n\t}\n}\n\nbool\ncSampleManager::StartStreamedFile(uint32 nFile, uint32 nPos, uint8 nStream)\n{\n\tint i = 0;\n\tuint32 position = nPos;\n\tchar filename[MAX_PATH];\n\t\n\tif ( !m_bInitialised || nFile >= TOTAL_STREAMED_SOUNDS )\n\t\treturn false;\n\n\tif ( mp3Stream[nStream] )\n\t{\n\t\tAIL_pause_stream(mp3Stream[nStream], 1);\n\t\tAIL_close_stream(mp3Stream[nStream]);\n\t}\n\tif ( nFile == STREAMED_SOUND_RADIO_MP3_PLAYER )\n\t{\n\t\tdo\n\t\t{\n\t\t\t// Just switched to MP3 player\n\t\t\tif ( !_bIsMp3Active && i == 0 )\n\t\t\t{\n\t\t\t\tif ( nPos > nStreamLength[STREAMED_SOUND_RADIO_MP3_PLAYER] )\n\t\t\t\t\tposition = 0;\n\t\t\t\ttMP3Entry *e = _pMP3List;\n\n\t\t\t\t// Try to continue from previous song, if already started\n\t\t\t\tif(!_GetMP3PosFromStreamPos(&position, &e) && !e) {\n\t\t\t\t\tnFile = 0;\n\t\t\t\t\tstrcpy(filename, m_MiscomPath);\n\t\t\t\t\tstrcat(filename, StreamedNameTable[nFile]);\n\t\t\t\t\tmp3Stream[nStream] =\n\t\t\t\t\t    AIL_open_stream(DIG, filename, 0);\n\t\t\t\t\tif(mp3Stream[nStream]) {\n\t\t\t\t\t\tAIL_set_stream_loop_count(mp3Stream[nStream], nStreamLoopedFlag[nStream] ? 0 : 1);\n\t\t\t\t\t\tnStreamLoopedFlag[nStream] = true;\n\t\t\t\t\t\tAIL_set_stream_ms_position(mp3Stream[nStream], position);\n\t\t\t\t\t\tAIL_pause_stream(mp3Stream[nStream], 0);\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t\treturn false;\n\n\t\t\t\t} else {\n\t\t\t\t\tif ( e->pLinkPath != NULL )\n\t\t\t\t\t\tmp3Stream[nStream] = AIL_open_stream(DIG, e->pLinkPath, 0);\n\t\t\t\t\telse {\n\t\t\t\t\t\tstrcpy(filename, _mp3DirectoryPath);\n\t\t\t\t\t\tstrcat(filename, e->aFilename);\n\t\t\t\t\t\n\t\t\t\t\t\tmp3Stream[nStream] = AIL_open_stream(DIG, filename, 0);\n\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\tif ( mp3Stream[nStream] ) {\n\t\t\t\t\t\tAIL_set_stream_loop_count(mp3Stream[nStream], 1);\n\t\t\t\t\t\tAIL_set_stream_ms_position(mp3Stream[nStream], position);\n\t\t\t\t\t\tAIL_pause_stream(mp3Stream[nStream], 0);\n\t\t\t\t\t\t\n\t\t\t\t\t\t_bIsMp3Active = true;\n\t\t\t\t\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t\t// fall through, start playing from another song\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif(++_CurMP3Index >= nNumMP3s) _CurMP3Index = 0;\n\n\t\t\t\t_CurMP3Pos = 0;\n\n\t\t\t\ttMP3Entry *mp3 = _GetMP3EntryByIndex(_CurMP3Index);\n\t\t\t\tif ( !mp3 )\n\t\t\t\t{\n\t\t\t\t\tmp3 = _pMP3List;\n\t\t\t\t\tif ( !_pMP3List )\n\t\t\t\t\t{\n\t\t\t\t\t\tnFile = 0;\n\t\t\t\t\t\t_bIsMp3Active = 0;\n\t\t\t\t\t\tstrcpy(filename, m_MiscomPath);\n\t\t\t\t\t\tstrcat(filename, StreamedNameTable[nFile]);\n\n\t\t\t\t\t\tmp3Stream[nStream] =\n\t\t\t\t\t\t    AIL_open_stream(DIG, filename, 0);\n\t\t\t\t\t\tif(mp3Stream[nStream]) {\n\t\t\t\t\t\t\tAIL_set_stream_loop_count(\n\t\t\t\t\t\t\t    mp3Stream[nStream], nStreamLoopedFlag[nStream] ? 0 : 1);\n\t\t\t\t\t\t\tnStreamLoopedFlag[nStream] = true;\n\t\t\t\t\t\t\tAIL_set_stream_ms_position(\n\t\t\t\t\t\t\t    mp3Stream[nStream], position);\n\t\t\t\t\t\t\tAIL_pause_stream(mp3Stream[nStream],\n\t\t\t\t\t\t\t                 0);\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif(mp3->pLinkPath != NULL)\n\t\t\t\t\tmp3Stream[nStream] = AIL_open_stream(DIG, mp3->pLinkPath, 0);\n\t\t\t\telse {\n\t\t\t\t\tstrcpy(filename, _mp3DirectoryPath);\n\t\t\t\t\tstrcat(filename, mp3->aFilename);\n\n\t\t\t\t\tmp3Stream[nStream] =\n\t\t\t\t\t    AIL_open_stream(DIG, filename, 0);\n\t\t\t\t}\n\n\t\t\t\tif(mp3Stream[nStream]) {\n\t\t\t\t\tAIL_set_stream_loop_count(mp3Stream[nStream], 1);\n\t\t\t\t\tAIL_set_stream_ms_position(mp3Stream[nStream], 0);\n\t\t\t\t\tAIL_pause_stream(mp3Stream[nStream], 0);\n#ifdef FIX_BUGS\n\t\t\t\t\t_bIsMp3Active = true;\n#endif\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t}\n\t\t\t_bIsMp3Active = 0;\n\t\t}\n\t\twhile ( ++i < nNumMP3s );\n\t\tposition = 0;\n\t\tnFile = 0;\n\t}\n\tstrcpy(filename, m_MiscomPath);\n\tstrcat(filename, StreamedNameTable[nFile]);\n\t\n\tmp3Stream[nStream] = AIL_open_stream(DIG, filename, 0);\n\tif ( mp3Stream[nStream] )\n\t{\n\t\tAIL_set_stream_loop_count(mp3Stream[nStream], nStreamLoopedFlag[nStream] ? 0 : 1);\n\t\tnStreamLoopedFlag[nStream] = true;\n\t\tAIL_set_stream_ms_position(mp3Stream[nStream], position);\n\t\tAIL_pause_stream(mp3Stream[nStream], 0);\n\t\treturn true;\n\t}\n\treturn false;\n}\n\nvoid\ncSampleManager::StopStreamedFile(uint8 nStream)\n{\n\tif ( m_bInitialised )\n\t{\n\t\tif ( mp3Stream[nStream] )\n\t\t{\n\t\t\tAIL_pause_stream(mp3Stream[nStream], 1);\n\t\t\t\n\t\t\tAIL_close_stream(mp3Stream[nStream]);\n\t\t\tmp3Stream[nStream] = NULL;\n\t\t\t\n\t\t\tif ( nStream == 0 )\n\t\t\t\t_bIsMp3Active = false;\n\t\t}\n\t}\n}\n\nint32\ncSampleManager::GetStreamedFilePosition(uint8 nStream)\n{\n\tS32 currentms;\n\t\n\tif ( m_bInitialised )\n\t{\n\t\tif ( mp3Stream[nStream] )\n\t\t{\n\t\t\tif ( _bIsMp3Active )\n\t\t\t{\n\t\t\t\ttMP3Entry *mp3 = _GetMP3EntryByIndex(_CurMP3Index);\n\t\t\t\t\n\t\t\t\tif ( mp3 != NULL )\n\t\t\t\t{\n\t\t\t\t\tAIL_stream_ms_position(mp3Stream[nStream], NULL, &currentms);\n\t\t\t\t\treturn currentms + mp3->nTrackStreamPos;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\treturn 0;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tAIL_stream_ms_position(mp3Stream[nStream], NULL, &currentms);\n\t\t\t\treturn currentms;\n\t\t\t}\n\t\t}\n\t}\n\t\n\treturn 0;\n}\n\nvoid\ncSampleManager::SetStreamedVolumeAndPan(uint8 nVolume, uint8 nPan, uint8 nEffectFlag, uint8 nStream)\n{\n\tuint8 vol = nVolume;\n\tfloat boostMult = 0.0f;\n\t\n\tif ( m_bInitialised )\n\t{\n\t\tif ( vol > MAX_VOLUME ) vol = MAX_VOLUME;\n\t\t\n\t\tif ( MusicManager.GetRadioInCar() == USERTRACK && !MusicManager.CheckForMusicInterruptions() )\n\t\t\tboostMult = m_nMP3BoostVolume / 64.f;\n\t\t\n\t\tnStreamVolume[nStream] = vol;\n\t\tnStreamPan[nStream]    = nPan;\n\t\t\n\t\tif ( mp3Stream[nStream] )\n\t\t{\n\t\t\tif ( nEffectFlag )\n\t\t\t{\n\t\t\t\tif ( nStream == 1 || nStream == 2 )\n\t\t\t\t\tAIL_set_stream_volume(mp3Stream[nStream], 128*vol*m_nEffectsVolume >> 14);\n\t\t\t\telse\n\t\t\t\t\tAIL_set_stream_volume(mp3Stream[nStream], m_nEffectsFadeVolume*vol*m_nEffectsVolume >> 14);\n\t\t\t}\n\t\t\telse\n\t\t\t\tAIL_set_stream_volume(mp3Stream[nStream], (m_nMusicFadeVolume*vol*(uint32)(m_nMusicVolume * boostMult + m_nMusicVolume)) >> 14);\n\t\t\t\n\t\t\tAIL_set_stream_pan(mp3Stream[nStream], nPan);\n\t\t}\n\t}\n}\n\nint32\ncSampleManager::GetStreamedFileLength(uint8 nStream)\n{\n\tif ( m_bInitialised )\n\t\treturn nStreamLength[nStream];\n\t\n\treturn 0;\n}\n\nbool\ncSampleManager::IsStreamPlaying(uint8 nStream)\n{\n\tif ( m_bInitialised )\n\t{\n\t\tif ( mp3Stream[nStream] )\n\t\t{\n\t\t\tif ( AIL_stream_status(mp3Stream[nStream]) == SMP_PLAYING )\n\t\t\t\treturn true;\n\t\t\telse\n\t\t\t\treturn false;\n\t\t}\n\t}\n\t\n\treturn false;\n}\n\nbool\ncSampleManager::InitialiseSampleBanks(void)\n{\n\tint32 nBank = SFX_BANK_0;\n\t\n\tfpSampleDescHandle = fopen(SampleBankDescFilename, \"rb\");\n\tif ( fpSampleDescHandle == NULL )\n\t\treturn false;\n\t\n\tfpSampleDataHandle = fopen(SampleBankDataFilename, \"rb\");\n\tif ( fpSampleDataHandle == NULL )\n\t{\n\t\tfclose(fpSampleDescHandle);\n\t\tfpSampleDescHandle = NULL;\n\t\t\n\t\treturn false;\n\t}\n\t\n\tfseek(fpSampleDataHandle, 0, SEEK_END);\n\t_nSampleDataEndOffset = ftell(fpSampleDataHandle);\n\trewind(fpSampleDataHandle);\n\t\n\tfread(m_aSamples, sizeof(tSample), TOTAL_AUDIO_SAMPLES, fpSampleDescHandle);\n\t\n\tfclose(fpSampleDescHandle);\n\tfpSampleDescHandle = NULL;\n\t\n\tfor ( int32 i = 0; i < TOTAL_AUDIO_SAMPLES; i++ )\n\t{\n#ifdef FIX_BUGS\n\t\tif (nBank >= MAX_SFX_BANKS) break;\n#endif\n\t\tif ( BankStartOffset[nBank] == BankStartOffset[SFX_BANK_0] + i )\n\t\t{\n\t\t\tnSampleBankDiscStartOffset[nBank] = m_aSamples[i].nOffset;\n\t\t\tnBank++;\n\t\t}\n\t}\n\n\tnSampleBankSize[SFX_BANK_0] = nSampleBankDiscStartOffset[SFX_BANK_PED_COMMENTS] - nSampleBankDiscStartOffset[SFX_BANK_0];\n\tnSampleBankSize[SFX_BANK_PED_COMMENTS] = _nSampleDataEndOffset                       - nSampleBankDiscStartOffset[SFX_BANK_PED_COMMENTS];\n\t\n\treturn true;\n}\n\n\nvoid\ncSampleManager::SetStreamedFileLoopFlag(uint8 nLoopFlag, uint8 nChannel)\n{\n\tif (m_bInitialised)\n\t\tnStreamLoopedFlag[nChannel] = nLoopFlag;\n}\n\n#endif\n"
  },
  {
    "path": "src/audio/sampman_null.cpp",
    "content": "#include \"common.h\"\n#if !defined(AUDIO_OAL) &&  !defined(AUDIO_MSS)\n#include \"sampman.h\"\n#include \"AudioManager.h\"\n\ncSampleManager SampleManager;\nbool _bSampmanInitialised = false;\n\nuint32 BankStartOffset[MAX_SFX_BANKS];\nuint32     nNumMP3s;\n\ncSampleManager::cSampleManager(void)\n{\n\t;\n}\n\ncSampleManager::~cSampleManager(void)\n{\n\t\n}\n\nvoid cSampleManager::SetSpeakerConfig(int32 nConfig)\n{\n\n}\n\nuint32 cSampleManager::GetMaximumSupportedChannels(void)\n{\t\n\treturn MAXCHANNELS;\n}\n\nuint32 cSampleManager::GetNum3DProvidersAvailable()\n{\n\treturn 1;\n}\n\nvoid cSampleManager::SetNum3DProvidersAvailable(uint32 num)\n{\n\t\n}\n\nchar *cSampleManager::Get3DProviderName(uint8 id)\n{\n\tstatic char name[64] = \"NULL\";\n\treturn name;\n}\n\nvoid cSampleManager::Set3DProviderName(uint8 id, char *name)\n{\n\t\n}\n\nint8 cSampleManager::GetCurrent3DProviderIndex(void)\n{\n\treturn 0;\n}\n\nint8 cSampleManager::SetCurrent3DProvider(uint8 nProvider)\n{\n\treturn 0;\n}\n\nbool\ncSampleManager::IsMP3RadioChannelAvailable(void)\n{\n\treturn nNumMP3s != 0;\n}\n\n\nvoid cSampleManager::ReleaseDigitalHandle(void)\n{\n}\n\nvoid cSampleManager::ReacquireDigitalHandle(void)\n{\n}\n\nbool\ncSampleManager::Initialise(void)\n{\n\treturn true;\n}\n\nvoid\ncSampleManager::Terminate(void)\n{\n\n}\n\nbool cSampleManager::CheckForAnAudioFileOnCD(void)\n{\n\treturn true;\n}\n\nchar cSampleManager::GetCDAudioDriveLetter(void)\n{\n\treturn '\\0';\n}\n\nvoid\ncSampleManager::UpdateEffectsVolume(void)\n{\n\t\n}\n\nvoid\ncSampleManager::SetEffectsMasterVolume(uint8 nVolume)\n{\n}\n\nvoid\ncSampleManager::SetMusicMasterVolume(uint8 nVolume)\n{\n}\n\nvoid\ncSampleManager::SetMusicMasterVolume(uint8 nVolume)\n{\n}\n\nvoid\ncSampleManager::SetEffectsFadeVolume(uint8 nVolume)\n{\n}\n\nvoid\ncSampleManager::SetMusicFadeVolume(uint8 nVolume)\n{\n}\n\nvoid\ncSampleManager::SetMonoMode(uint8 nMode)\n{\n}\n\nbool\ncSampleManager::LoadSampleBank(uint8 nBank)\n{\n\tASSERT( nBank < MAX_SFX_BANKS );\n\treturn false;\n}\n\nvoid\ncSampleManager::UnloadSampleBank(uint8 nBank)\n{\n\tASSERT( nBank < MAX_SFX_BANKS );\n}\n\nbool\ncSampleManager::IsSampleBankLoaded(uint8 nBank)\n{\n\tASSERT( nBank < MAX_SFX_BANKS );\n\t\n\treturn false;\n}\n\nbool\ncSampleManager::IsPedCommentLoaded(uint32 nComment)\n{\n\tASSERT( nComment < TOTAL_AUDIO_SAMPLES );\n\n\treturn false;\n}\n\n\nint32\ncSampleManager::_GetPedCommentSlot(uint32 nComment)\n{\n\treturn -1;\n}\n\nbool\ncSampleManager::LoadPedComment(uint32 nComment)\n{\n\tASSERT( nComment < TOTAL_AUDIO_SAMPLES );\n\treturn false;\n}\n\nint32\ncSampleManager::GetBankContainingSound(uint32 offset)\n{\n\treturn INVALID_SFX_BANK;\n}\n\nint32\ncSampleManager::GetSampleBaseFrequency(uint32 nSample)\n{\n\tASSERT( nSample < TOTAL_AUDIO_SAMPLES );\n\treturn 0;\n}\n\nint32\ncSampleManager::GetSampleLoopStartOffset(uint32 nSample)\n{\n\tASSERT( nSample < TOTAL_AUDIO_SAMPLES );\n\treturn 0;\n}\n\nint32\ncSampleManager::GetSampleLoopEndOffset(uint32 nSample)\n{\n\tASSERT( nSample < TOTAL_AUDIO_SAMPLES );\n\treturn 0;\n}\n\nuint32\ncSampleManager::GetSampleLength(uint32 nSample)\n{\n\tASSERT( nSample < TOTAL_AUDIO_SAMPLES );\n\treturn 0;\n}\n\nbool cSampleManager::UpdateReverb(void)\n{\n\treturn false;\n}\n\nvoid\ncSampleManager::SetChannelReverbFlag(uint32 nChannel, uint8 nReverbFlag)\n{\n\tASSERT( nChannel < MAXCHANNELS+MAX2DCHANNELS );\n}\n\nbool\ncSampleManager::InitialiseChannel(uint32 nChannel, uint32 nSfx, uint8 nBank)\n{\n\tASSERT( nChannel < MAXCHANNELS+MAX2DCHANNELS );\n\treturn false;\n}\n\nvoid\ncSampleManager::SetChannelEmittingVolume(uint32 nChannel, uint32 nVolume)\n{\n\tASSERT( nChannel != CHANNEL2D );\n\tASSERT( nChannel < MAXCHANNELS+MAX2DCHANNELS );\n}\n\nvoid\ncSampleManager::SetChannel3DPosition(uint32 nChannel, float fX, float fY, float fZ)\n{\n\tASSERT( nChannel != CHANNEL2D );\n\tASSERT( nChannel < MAXCHANNELS+MAX2DCHANNELS );\n}\n\nvoid\ncSampleManager::SetChannel3DDistances(uint32 nChannel, float fMax, float fMin)\n{\n\tASSERT( nChannel != CHANNEL2D );\n\tASSERT( nChannel < MAXCHANNELS+MAX2DCHANNELS );\n}\n\nvoid\ncSampleManager::SetChannelVolume(uint32 nChannel, uint32 nVolume)\n{\n\tASSERT( nChannel == CHANNEL2D );\n\tASSERT( nChannel < MAXCHANNELS+MAX2DCHANNELS );\n}\n\nvoid\ncSampleManager::SetChannelPan(uint32 nChannel, uint32 nPan)\n{\n\tASSERT(nChannel == CHANNEL2D);\n\tASSERT( nChannel < MAXCHANNELS+MAX2DCHANNELS );\n}\n\nvoid\ncSampleManager::SetChannelFrequency(uint32 nChannel, uint32 nFreq)\n{\n\tASSERT( nChannel < MAXCHANNELS+MAX2DCHANNELS );\n}\n\nvoid\ncSampleManager::SetChannelLoopPoints(uint32 nChannel, uint32 nLoopStart, int32 nLoopEnd)\n{\n\tASSERT( nChannel < MAXCHANNELS+MAX2DCHANNELS );\n}\n\nvoid\ncSampleManager::SetChannelLoopCount(uint32 nChannel, uint32 nLoopCount)\n{\n\tASSERT( nChannel < MAXCHANNELS+MAX2DCHANNELS );\n}\n\nbool\ncSampleManager::GetChannelUsedFlag(uint32 nChannel)\n{\n\tASSERT( nChannel < MAXCHANNELS+MAX2DCHANNELS );\n\n\treturn false;\n}\n\nvoid\ncSampleManager::StartChannel(uint32 nChannel)\n{\n\tASSERT( nChannel < MAXCHANNELS+MAX2DCHANNELS );\n}\n\nvoid\ncSampleManager::StopChannel(uint32 nChannel)\n{\n\tASSERT( nChannel < MAXCHANNELS+MAX2DCHANNELS );\n}\n\nvoid\ncSampleManager::PreloadStreamedFile(uint32 nFile, uint8 nStream)\n{\n\tASSERT( nStream < MAX_STREAMS );\n}\n\nvoid\ncSampleManager::PauseStream(uint8 nPauseFlag, uint8 nStream)\n{\n\tASSERT( nStream < MAX_STREAMS );\n}\n\nvoid\ncSampleManager::StartPreloadedStreamedFile(uint8 nStream)\n{\n\tASSERT( nStream < MAX_STREAMS );\n}\n\nbool\ncSampleManager::StartStreamedFile(uint32 nFile, uint32 nPos, uint8 nStream)\n{\t\n\tASSERT( nStream < MAX_STREAMS );\n\t\n\treturn false;\n}\n\nvoid\ncSampleManager::StopStreamedFile(uint8 nStream)\n{\n\tASSERT( nStream < MAX_STREAMS );\n}\n\nint32\ncSampleManager::GetStreamedFilePosition(uint8 nStream)\n{\n\tASSERT( nStream < MAX_STREAMS );\n\t\n\treturn 0;\n}\n\nvoid\ncSampleManager::SetStreamedVolumeAndPan(uint8 nVolume, uint8 nPan, uint8 nEffectFlag, uint8 nStream)\n{\n\tASSERT( nStream < MAX_STREAMS );\n}\n\nint32\ncSampleManager::GetStreamedFileLength(uint8 nStream)\n{\n\tASSERT( nStream < TOTAL_STREAMED_SOUNDS );\n\n\treturn 1;\n}\n\nbool\ncSampleManager::IsStreamPlaying(uint8 nStream)\n{\n\tASSERT( nStream < MAX_STREAMS );\n\n\treturn false;\n}\n\nbool\ncSampleManager::InitialiseSampleBanks(void)\n{\n\t\n\treturn true;\n}\n\nvoid\ncSampleManager::SetStreamedFileLoopFlag(uint8 nLoopFlag, uint8 nChannel)\n{\n}\n\nint8 cSampleManager::AutoDetect3DProviders()\n{\n\treturn -1;\n}\n\n#endif\n"
  },
  {
    "path": "src/audio/sampman_oal.cpp",
    "content": "//#define JUICY_OAL\n\n#ifdef AUDIO_OAL\n#include <time.h>\n\n#include \"eax.h\"\n#include \"eax-util.h\"\n\n#ifdef _WIN32\n#include <io.h>\n#include <AL/al.h>\n#include <AL/alc.h>\n#include <AL/alext.h>\n#include <AL/efx.h>\n#include <AL/efx-presets.h>\n\n// for user MP3s\n#include <direct.h>\n#include <shlobj.h>\n#include <shlguid.h>\n#else\n#define _getcwd getcwd\n#endif\n\n#if defined _MSC_VER && !defined CMAKE_NO_AUTOLINK\n#pragma comment( lib, \"OpenAL32.lib\" )\n#endif\n\n#include \"common.h\"\n#include \"crossplatform.h\"\n\n#include \"sampman.h\"\n\n#include \"oal/oal_utils.h\"\n#include \"oal/aldlist.h\"\n#include \"oal/channel.h\"\n#include \"oal/stream.h\"\n\n#include \"AudioManager.h\"\n#include \"MusicManager.h\"\n#include \"Frontend.h\"\n#include \"Timer.h\"\n#ifdef AUDIO_OAL_USE_OPUS\n#include <opusfile.h>\n#endif\n\n//TODO: fix eax3 reverb\n//TODO: max channels\n\ncSampleManager SampleManager;\nbool _bSampmanInitialised = false;\n\nuint32 BankStartOffset[MAX_SFX_BANKS];\n\nint           prevprovider=-1;\nint           curprovider=-1;\nint           usingEAX=0;\nint           usingEAX3=0;\n//int         speaker_type=0;\nALCdevice    *ALDevice = NULL;\nALCcontext   *ALContext = NULL;\nunsigned int _maxSamples;\nfloat        _fPrevEaxRatioDestination;\nbool         _usingEFX;\nfloat        _fEffectsLevel;\nALuint       ALEffect = AL_EFFECT_NULL;\nALuint       ALEffectSlot = AL_EFFECTSLOT_NULL;\nstruct\n{\n\tchar id[256];\n\tchar name[256];\n\tint sources;\n}providers[MAXPROVIDERS];\n\nint defaultProvider;\n\n\nchar SampleBankDescFilename[] = \"audio/sfx.SDT\";\nchar SampleBankDataFilename[] = \"audio/sfx.RAW\";\n\nFILE *fpSampleDescHandle;\n#ifdef OPUS_SFX\nOggOpusFile *fpSampleDataHandle;\n#else\nFILE *fpSampleDataHandle;\n#endif\nbool  bSampleBankLoaded            [MAX_SFX_BANKS];\nint32 nSampleBankDiscStartOffset   [MAX_SFX_BANKS];\nint32 nSampleBankSize              [MAX_SFX_BANKS];\nuintptr nSampleBankMemoryStartAddress[MAX_SFX_BANKS];\nint32 _nSampleDataEndOffset;\n\nint32 nPedSlotSfx    [MAX_PEDSFX];\nint32 nPedSlotSfxAddr[MAX_PEDSFX];\nuint8 nCurrentPedSlot;\n\nCChannel aChannel[MAXCHANNELS+MAX2DCHANNELS];\nuint8 nChannelVolume[MAXCHANNELS+MAX2DCHANNELS];\n\nuint32 nStreamLength[TOTAL_STREAMED_SOUNDS];\nALuint ALStreamSources[MAX_STREAMS][2];\nALuint ALStreamBuffers[MAX_STREAMS][NUM_STREAMBUFFERS];\n\nstruct tMP3Entry\n{\n\tchar aFilename[MAX_PATH];\n\n\tuint32 nTrackLength;\n\tuint32 nTrackStreamPos;\n\n\ttMP3Entry* pNext;\n\tchar* pLinkPath;\n};\n\nuint32 nNumMP3s;\ntMP3Entry* _pMP3List;\nchar _mp3DirectoryPath[MAX_PATH]; \nCStream    *aStream[MAX_STREAMS];\nuint8      nStreamPan   [MAX_STREAMS];\nuint8      nStreamVolume[MAX_STREAMS];\nuint8      nStreamLoopedFlag[MAX_STREAMS];\nuint32 _CurMP3Index;\nint32 _CurMP3Pos;\nbool _bIsMp3Active;\n///////////////////////////////////////////////////////////////\n//\tEnv\t\tSize\tDiffus\tRoom\tRoomHF\tRoomLF\tDecTm\tDcHF\tDcLF\tRefl\tRefDel\tRef Pan\t\t\t\tRevb\tRevDel\t\tRev Pan\t\t\t\tEchTm\tEchDp\tModTm\tModDp\tAirAbs\tHFRef\t\tLFRef\tRRlOff\tFLAGS\nEAXLISTENERPROPERTIES StartEAX3 =\n\t{26,\t1.7f,\t0.8f,\t-1000,\t-1000,\t-100,\t4.42f,\t0.14f,\t1.00f,\t429,\t0.014f,\t0.00f,0.00f,0.00f,\t1023,\t0.021f,\t\t0.00f,0.00f,0.00f,\t0.250f,\t0.000f,\t0.250f,\t0.000f,\t-5.0f,\t2727.1f,\t250.0f,\t0.00f,\t0x3f };\n\nEAXLISTENERPROPERTIES FinishEAX3 =\n\t{26,\t100.0f,\t1.0f,\t0,\t\t-1000,\t-2200,\t20.0f,\t1.39f,\t1.00f,\t1000,\t0.069f,\t0.00f,0.00f,0.00f,\t400,\t0.100f,\t\t0.00f,0.00f,0.00f,\t0.250f,\t1.000f,\t3.982f,\t0.000f,\t-18.0f,\t3530.8f,\t417.9f,\t6.70f,\t0x3f };\n\nEAXLISTENERPROPERTIES EAX3Params;\n\n\nbool IsFXSupported()\n{\n\treturn usingEAX || usingEAX3 || _usingEFX;\n}\n\nvoid EAX_SetAll(const EAXLISTENERPROPERTIES *allparameters)\n{\n\tif ( usingEAX || usingEAX3 )\n\t\tEAX3_Set(ALEffect, allparameters);\n\telse\n\t\tEFX_Set(ALEffect, allparameters);\n}\n\nstatic void\nadd_providers()\n{\n\tSampleManager.SetNum3DProvidersAvailable(0);\n\t\n\tALDeviceList *pDeviceList = NULL;\n\tpDeviceList = new ALDeviceList();\n\n\tif ((pDeviceList) && (pDeviceList->GetNumDevices()))\n\t{\n\t\tconst int devNumber = Min(pDeviceList->GetNumDevices(), MAXPROVIDERS);\n\t\tint n = 0;\n\t\t\n\t\tfor (int i = 0; i < devNumber; i++) \n\t\t{\n\t\t\tif ( n < MAXPROVIDERS )\n\t\t\t{\n\t\t\t\tstrcpy(providers[n].id, pDeviceList->GetDeviceName(i));\n\t\t\t\tstrncpy(providers[n].name, pDeviceList->GetDeviceName(i), sizeof(providers[n].name));\n\t\t\t\tproviders[n].sources = pDeviceList->GetMaxNumSources(i);\n\t\t\t\tSampleManager.Set3DProviderName(n, providers[n].name);\n\t\t\t\tn++;\n\t\t\t}\n\t\t\t\n\t\t\tif ( alGetEnumValue(\"AL_EFFECT_EAXREVERB\") != 0\n\t\t\t\t|| pDeviceList->IsExtensionSupported(i, ADEXT_EAX2)\n\t\t\t\t|| pDeviceList->IsExtensionSupported(i, ADEXT_EAX3) \n\t\t\t\t|| pDeviceList->IsExtensionSupported(i, ADEXT_EAX4)\n\t\t\t\t|| pDeviceList->IsExtensionSupported(i, ADEXT_EAX5) )\n\t\t\t{\n\t\t\t\tif ( n < MAXPROVIDERS )\n\t\t\t\t{\n\t\t\t\t\tstrcpy(providers[n].id, pDeviceList->GetDeviceName(i));\n\t\t\t\t\tstrncpy(providers[n].name, pDeviceList->GetDeviceName(i), sizeof(providers[n].name));\n\t\t\t\t\tstrcat(providers[n].name, \" EAX\");\n\t\t\t\t\tproviders[n].sources = pDeviceList->GetMaxNumSources(i);\n\t\t\t\t\tSampleManager.Set3DProviderName(n, providers[n].name);\n\t\t\t\t\tn++;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif ( n < MAXPROVIDERS )\n\t\t\t\t{\n\t\t\t\t\tstrcpy(providers[n].id, pDeviceList->GetDeviceName(i));\n\t\t\t\t\tstrncpy(providers[n].name, pDeviceList->GetDeviceName(i), sizeof(providers[n].name));\n\t\t\t\t\tstrcat(providers[n].name, \" EAX3\");\n\t\t\t\t\tproviders[n].sources = pDeviceList->GetMaxNumSources(i);\n\t\t\t\t\tSampleManager.Set3DProviderName(n, providers[n].name);\n\t\t\t\t\tn++;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tSampleManager.SetNum3DProvidersAvailable(n);\n\t\n\t\tfor(int j=n;j<MAXPROVIDERS;j++)\n\t\t\tSampleManager.Set3DProviderName(j, NULL);\n\t\t\n\t\tdefaultProvider = pDeviceList->GetDefaultDevice();\n\t\tif ( defaultProvider > MAXPROVIDERS )\n\t\t\tdefaultProvider = 0;\n\t}\n\t\n\tdelete pDeviceList;\n}\n\nstatic void\nrelease_existing()\n{\n\tfor ( int32 i = 0; i < MAXCHANNELS; i++ )\n\t\taChannel[i].Term();\n\taChannel[CHANNEL2D].Term();\n\t\n\tif ( IsFXSupported() )\n\t{\n\t\tif ( alIsEffect(ALEffect) )\n\t\t{\n\t\t\talEffecti(ALEffect, AL_EFFECT_TYPE, AL_EFFECT_NULL);\n\t\t\talDeleteEffects(1, &ALEffect);\n\t\t\tALEffect = AL_EFFECT_NULL;\n\t\t}\n\t\t\n\t\tif (alIsAuxiliaryEffectSlot(ALEffectSlot))\n\t\t{\n\t\t\talAuxiliaryEffectSloti(ALEffectSlot, AL_EFFECTSLOT_EFFECT, AL_EFFECT_NULL);\n\t\t\t\n\t\t\talDeleteAuxiliaryEffectSlots(1, &ALEffectSlot);\n\t\t\tALEffectSlot = AL_EFFECTSLOT_NULL;\n\t\t}\n\t}\n\t\n\tfor ( int32 i = 0; i < MAX_STREAMS; i++ )\n\t{\n\t\tCStream *stream = aStream[i];\n\t\tif (stream)\n\t\t\tstream->ProviderTerm();\n\t\t\n\t\talDeleteBuffers(NUM_STREAMBUFFERS, ALStreamBuffers[i]);\n\t}\n\talDeleteSources(MAX_STREAMS*2, ALStreamSources[0]);\n\t\n\tCChannel::DestroyChannels();\n\t\n\tif ( ALContext )\n\t{\n\t\talcMakeContextCurrent(NULL);\n\t\talcSuspendContext(ALContext);\n\t\talcDestroyContext(ALContext);\n\t}\n\tif ( ALDevice )\n\t\talcCloseDevice(ALDevice);\n\t\n\tALDevice = NULL;\n\tALContext = NULL;\n\t\n\t_fPrevEaxRatioDestination = 0.0f;\n\t_usingEFX                 = false;\n\t_fEffectsLevel            = 0.0f;\n\t\n\tDEV(\"release_existing()\\n\");\n}\n\nstatic bool\nset_new_provider(int index)\n{\n\tif ( curprovider == index )\n\t\treturn true;\n\t\n\tcurprovider = index;\n\t\n\trelease_existing();\n\t\n\tif ( curprovider != -1 )\n\t{\n\t\tDEV(\"set_new_provider()\\n\");\n\t\t\n\t\t//TODO:\n\t\t_maxSamples = MAXCHANNELS;\n\t\t\n\t\tALCint attr[] = {ALC_FREQUENCY,MAX_FREQ,\n\t\t\t\t\t\tALC_MONO_SOURCES, MAX_STREAMS * 2 + MAXCHANNELS,\n\t\t\t\t\t\t0,\n\t\t\t\t\t\t};\n\t\t\n\t\tALDevice  = alcOpenDevice(providers[index].id);\n\t\tASSERT(ALDevice != NULL);\n\t\t\n\t\tALContext = alcCreateContext(ALDevice, attr);\n\t\tASSERT(ALContext != NULL);\n\t\t\n\t\talcMakeContextCurrent(ALContext);\n\t\n\t\tconst char* ext=(const char*)alGetString(AL_EXTENSIONS);\n\t\tASSERT(strstr(ext,\"AL_SOFT_loop_points\")!=NULL);\n\t\tif ( strstr(ext,\"AL_SOFT_loop_points\")==NULL )\n\t\t{\n\t\t\tcurprovider=-1;\n\t\t\trelease_existing();\n\t\t\treturn false;\n\t\t}\n\t\t\n\t\talListenerf (AL_GAIN,     1.0f);\n\t\talListener3f(AL_POSITION, 0.0f, 0.0f, 0.0f);\n\t\talListener3f(AL_VELOCITY, 0.0f, 0.0f, 0.0f);\n\t\tALfloat orientation[6] = { 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f };\n\t\talListenerfv(AL_ORIENTATION, orientation);\n\t\t\n\t\talDistanceModel(AL_INVERSE_DISTANCE_CLAMPED);\n\t\t\n\t\tif ( alcIsExtensionPresent(ALDevice, (ALCchar*)ALC_EXT_EFX_NAME) )\n\t\t{\n\t\t\talGenAuxiliaryEffectSlots(1, &ALEffectSlot);\n\t\t\talGenEffects(1, &ALEffect);\n\t\t}\n\n\t\talGenSources(MAX_STREAMS*2, ALStreamSources[0]);\n\t\tfor ( int32 i = 0; i < MAX_STREAMS; i++ )\n\t\t{\n\t\t\talGenBuffers(NUM_STREAMBUFFERS, ALStreamBuffers[i]);\n\t\t\talSourcei(ALStreamSources[i][0], AL_SOURCE_RELATIVE, AL_TRUE);\n\t\t\talSource3f(ALStreamSources[i][0], AL_POSITION, 0.0f, 0.0f, 0.0f);\n\t\t\talSourcef(ALStreamSources[i][0], AL_GAIN, 1.0f);\n\t\t\talSourcei(ALStreamSources[i][1], AL_SOURCE_RELATIVE, AL_TRUE);\n\t\t\talSource3f(ALStreamSources[i][1], AL_POSITION, 0.0f, 0.0f, 0.0f);\n\t\t\talSourcef(ALStreamSources[i][1], AL_GAIN, 1.0f);\n\t\t\t\n\t\t\tCStream *stream = aStream[i];\n\t\t\tif (stream)\n\t\t\t\tstream->ProviderInit();\n\t\t}\n\t\t\n\t\tusingEAX = 0;\n\t\tusingEAX3 = 0;\n\t\t_usingEFX = false;\n\t\t\n\t\tif ( !strcmp(&providers[index].name[strlen(providers[index].name) - strlen(\" EAX3\")], \" EAX3\") \n\t\t\t\t&& alcIsExtensionPresent(ALDevice, (ALCchar*)ALC_EXT_EFX_NAME) )\n\t\t{\n\t\t\tEAX_SetAll(&FinishEAX3);\n\t\t\t\n\t\t\tusingEAX = 1;\n\t\t\tusingEAX3 = 1;\n\n\t\t\tDEV(\"EAX3\\n\");\n\t\t}\n\t\telse if ( alcIsExtensionPresent(ALDevice, (ALCchar*)ALC_EXT_EFX_NAME) )\n\t\t{\n\t\t\tEAX_SetAll(&EAX30_ORIGINAL_PRESETS[EAX_ENVIRONMENT_CAVE]);\n\t\t\t\n\t\t\tif ( !strcmp(&providers[index].name[strlen(providers[index].name) - strlen(\" EAX\")], \" EAX\"))\n\t\t\t{\n\t\t\t\tusingEAX = 1;\n\t\t\t\tDEV(\"EAX1\\n\");\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t_usingEFX = true;\n\t\t\t\tDEV(\"EFX\\n\");\n\t\t\t}\n\t\t}\n\t\t\n\t\t//SampleManager.SetSpeakerConfig(speaker_type);\n\t\t\n\t\tCChannel::InitChannels();\n\n\t\tfor ( int32 i = 0; i < MAXCHANNELS; i++ )\n\t\t\taChannel[i].Init(i);\n\t\taChannel[CHANNEL2D].Init(CHANNEL2D, true);\n\t\t\n\t\tif ( IsFXSupported() )\n\t\t{\n\t\t\t/**/\n\t\t\talAuxiliaryEffectSloti(ALEffectSlot, AL_EFFECTSLOT_EFFECT, ALEffect);\n\t\t\t/**/\n\t\t\t\n\t\t\tfor ( int32 i = 0; i < MAXCHANNELS; i++ )\n\t\t\t\taChannel[i].SetReverbMix(ALEffectSlot, 0.0f);\n\t\t}\n\t\t\n\t\treturn true;\n\t}\n\t\n\treturn false;\n}\n\nstatic bool\nIsThisTrackAt16KHz(uint32 track)\n{\n\treturn track == STREAMED_SOUND_RADIO_KCHAT || track == STREAMED_SOUND_RADIO_VCPR || track == STREAMED_SOUND_RADIO_POLICE;\n}\n\ncSampleManager::cSampleManager(void)\n{\n\t;\n}\n\ncSampleManager::~cSampleManager(void)\n{\n\t\n}\n\nvoid cSampleManager::SetSpeakerConfig(int32 nConfig)\n{\n\n}\n\nuint32 cSampleManager::GetMaximumSupportedChannels(void)\n{\n\tif ( _maxSamples > MAXCHANNELS )\n\t\treturn MAXCHANNELS;\n\t\n\treturn _maxSamples;\n}\n\nuint32 cSampleManager::GetNum3DProvidersAvailable()\n{\n\treturn m_nNumberOfProviders;\n}\n\nvoid cSampleManager::SetNum3DProvidersAvailable(uint32 num)\n{\n\tm_nNumberOfProviders = num;\n}\n\nchar *cSampleManager::Get3DProviderName(uint8 id)\n{\n\treturn m_aAudioProviders[id];\n}\n\nvoid cSampleManager::Set3DProviderName(uint8 id, char *name)\n{\n\tm_aAudioProviders[id] = name;\n}\n\nint8 cSampleManager::GetCurrent3DProviderIndex(void)\n{\n\treturn curprovider;\n}\n\nint8 cSampleManager::SetCurrent3DProvider(uint8 nProvider)\n{\n\tint savedprovider = curprovider;\n\n\tnProvider = clamp(nProvider, 0, m_nNumberOfProviders - 1);\n\n\tif ( set_new_provider(nProvider) )\n\t\treturn curprovider;\n\telse if ( savedprovider != -1 && savedprovider < m_nNumberOfProviders && set_new_provider(savedprovider) )\n\t\treturn curprovider;\n\telse\n\t\treturn curprovider;\n}\n\nint8\ncSampleManager::AutoDetect3DProviders()\n{\n\tif (!AudioManager.IsAudioInitialised())\n\t\treturn -1;\n\n\tif (defaultProvider >= 0 && defaultProvider < m_nNumberOfProviders) {\n\t\tif (set_new_provider(defaultProvider))\n\t\t\treturn defaultProvider;\n\t}\n\n\tfor (uint32 i = 0; i < GetNum3DProvidersAvailable(); i++)\n\t{\n\t\tchar* providername = Get3DProviderName(i);\n\n\t\tif (!strcasecmp(providername, \"OPENAL SOFT\")) {\n\t\t\tSetCurrent3DProvider(i);\n\t\t\tif (GetCurrent3DProviderIndex() == i)\n\t\t\t\treturn i;\n\t\t}\n\t}\n\n\treturn -1;\n}\n\nstatic bool\n_ResolveLink(char const *path, char *out)\n{\n#ifdef _WIN32\n\tsize_t len = strlen(path);\n\tif (len < 4 || strcmp(&path[len - 4], \".lnk\") != 0)\n\t\treturn false;\n\t\t\n\tIShellLink* psl;\n\tWIN32_FIND_DATA fd;\n\tchar filepath[MAX_PATH];\n\t\n\tCoInitialize(NULL);\n\t\t\t\t\t\t\t\t\t   \n\tif (SUCCEEDED( CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID*)&psl ) ))\n\t{\n\t\tIPersistFile *ppf;\n\n\t\tif (SUCCEEDED(psl->QueryInterface(IID_IPersistFile, (LPVOID*)&ppf)))\n\t\t{\n\t\t\tWCHAR wpath[MAX_PATH];\n\t\t\t\n\t\t\tMultiByteToWideChar(CP_ACP, 0, path, -1, wpath, MAX_PATH);\n\t\t\t\n\t\t\tif (SUCCEEDED(ppf->Load(wpath, STGM_READ)))\n\t\t\t{\n\t\t\t\t/* Resolve the link */\n\t\t\t\tif (SUCCEEDED(psl->Resolve(NULL, SLR_ANY_MATCH|SLR_NO_UI|SLR_NOSEARCH)))\n\t\t\t\t{\n\t\t\t\t\tstrcpy(filepath, path);\n\t\t\t\t\t\n\t\t\t\t\tif (SUCCEEDED(psl->GetPath(filepath, MAX_PATH, &fd, SLGP_UNCPRIORITY)))\n\t\t\t\t\t{\n\t\t\t\t\t\tOutputDebugString(fd.cFileName);\n\t\t\t\t\t\t\n\t\t\t\t\t\tstrcpy(out, filepath);\n\t\t\t\t\t\t// FIX: Release the objects. Taken from SA.\n#ifdef FIX_BUGS\n\t\t\t\t\t\tppf->Release();\n\t\t\t\t\t\tpsl->Release();\n#endif\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tppf->Release();\n\t\t}\n\t\tpsl->Release();\n\t}\n\t\n\treturn false;\n#else\n\tstruct stat sb;\n\n\tif (lstat(path, &sb) == -1) {\n\t\tperror(\"lstat: \");\n\t\treturn false;\n\t}\n\n\tif (S_ISLNK(sb.st_mode)) {\n\t\tchar* linkname = (char*)alloca(sb.st_size + 1);\n\t\tif (linkname == NULL) {\n\t\t\tfprintf(stderr, \"insufficient memory\\n\");\n\t\t\treturn false;\n\t\t}\n\n\t\tif (readlink(path, linkname, sb.st_size + 1) < 0) {\n\t\t\tperror(\"readlink: \");\n\t\t\treturn false;\n\t\t}\n\t\tlinkname[sb.st_size] = '\\0';\n\t\tstrcpy(out, linkname);\n\t\treturn true;\n\t} else {\n\t\treturn false;\n\t}\n#endif\n}\n\nstatic void\n_FindMP3s(void)\n{\n\ttMP3Entry *pList;\n\tbool bShortcut;\t\n\tbool bInitFirstEntry;\t\n\tHANDLE hFind;\n\tchar path[MAX_PATH];\n\tchar filepath[MAX_PATH*2];\n\tint total_ms;\n\tWIN32_FIND_DATA fd;\n\t\n\tif (getcwd(_mp3DirectoryPath, MAX_PATH) == NULL) {\n\t\tperror(\"getcwd: \");\n\t\treturn;\n\t}\n\t\n\tOutputDebugString(\"Finding MP3s...\");\n\tstrcpy(path, _mp3DirectoryPath);\n\tstrcat(path, \"\\\\MP3\\\\\");\n\t\n\tstrcpy(_mp3DirectoryPath, path);\n\tOutputDebugString(_mp3DirectoryPath);\n\t\n\tstrcat(path, \"*\");\n\t\n\thFind = FindFirstFile(path, &fd);\n\t\n\tif ( hFind == INVALID_HANDLE_VALUE ) \n\t{\n\t\treturn;\n\t}\n\t\n\tstrcpy(filepath, _mp3DirectoryPath);\n\tstrcat(filepath, fd.cFileName);\n\t\n\tsize_t filepathlen = strlen(filepath);\n\t\n\tif ( filepathlen <= 0)\n\t{\n\t\tFindClose(hFind);\n\t\treturn;\n\t}\n\n\tif ( _ResolveLink(filepath, filepath) )\n\t{\n\t\tOutputDebugString(\"Resolving Link\");\n\t\tOutputDebugString(filepath);\n\t\tbShortcut = true;\n\t} else\n\t\tbShortcut = false;\n\t\n\taStream[0] = new CStream(filepath, ALStreamSources[0], ALStreamBuffers[0]);\n\n\tif (aStream[0] && aStream[0]->IsOpened())\n\t{\n\t\ttotal_ms = aStream[0]->GetLengthMS();\n\t\tdelete aStream[0];\n\t\taStream[0] = NULL;\n\n\t\tOutputDebugString(fd.cFileName);\n\t\t\n\t\t_pMP3List = new tMP3Entry;\n\t\t\n\t\tif ( _pMP3List == NULL )\n\t\t{\n\t\t\tFindClose(hFind);\n\t\t\treturn;\n\t\t}\n\t\t\n\t\tnNumMP3s = 1;\n\t\t\n\t\tstrcpy(_pMP3List->aFilename, fd.cFileName);\n\t\t\n\t\t_pMP3List->nTrackLength = total_ms;\n\t\t\n\t\t_pMP3List->pNext = NULL;\n\t\t\n\t\tpList = _pMP3List;\n\t\t\n\t\tif ( bShortcut )\n\t\t{\n\t\t\t_pMP3List->pLinkPath = new char[MAX_PATH*2];\n\t\t\tstrcpy(_pMP3List->pLinkPath, filepath);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t_pMP3List->pLinkPath = NULL;\n\t\t}\n\n\t\tbInitFirstEntry = false;\n\t}\n\telse\n\t{\n\t\tstrcat(filepath, \" - NOT A VALID MP3\");\n\t\t\n\t\tOutputDebugString(filepath);\n\n\t\tbInitFirstEntry = true;\n\t}\n\t\n\twhile ( true )\n\t{\n\t\tif ( !FindNextFile(hFind, &fd) )\n\t\t\tbreak;\n\t\t\n\t\tif ( bInitFirstEntry )\n\t\t{\n\t\t\tstrcpy(filepath, _mp3DirectoryPath);\n\t\t\tstrcat(filepath, fd.cFileName);\n\t\t\t\n\t\t\tsize_t filepathlen = strlen(filepath);\n\n\t\t\tif ( filepathlen > 0 )\n\t\t\t{\n\t\t\t\tif ( _ResolveLink(filepath, filepath) )\n\t\t\t\t{\n\t\t\t\t\tOutputDebugString(\"Resolving Link\");\n\t\t\t\t\tOutputDebugString(filepath);\n\t\t\t\t\tbShortcut = true;\n\t\t\t\t} else {\n\t\t\t\t\tbShortcut = false;\n\t\t\t\t\tif (filepathlen > MAX_PATH) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\taStream[0] = new CStream(filepath, ALStreamSources[0], ALStreamBuffers[0]);\n\n\t\t\t\tif (aStream[0] && aStream[0]->IsOpened())\n\t\t\t\t{\n\t\t\t\t\ttotal_ms = aStream[0]->GetLengthMS();\n\t\t\t\t\tdelete aStream[0];\n\t\t\t\t\taStream[0] = NULL;\n\t\t\t\t\t\n\t\t\t\t\tOutputDebugString(fd.cFileName);\n\t\t\t\t\t\n\t\t\t\t\t_pMP3List = new tMP3Entry;\n\t\t\t\t\t\n\t\t\t\t\tif ( _pMP3List  == NULL)\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t\n\t\t\t\t\tnNumMP3s = 1;\n\t\t\t\t\t\n\t\t\t\t\tstrcpy(_pMP3List->aFilename, fd.cFileName);\n\t\t\t\t\t\n\t\t\t\t\t_pMP3List->nTrackLength = total_ms;\n\t\t\t\t\t_pMP3List->pNext = NULL;\n\t\t\t\t\t\n\t\t\t\t\tif ( bShortcut )\n\t\t\t\t\t{\n\t\t\t\t\t\t_pMP3List->pLinkPath = new char [MAX_PATH*2];\n\t\t\t\t\t\tstrcpy(_pMP3List->pLinkPath, filepath);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t_pMP3List->pLinkPath = NULL;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tpList = _pMP3List;\n\n\t\t\t\t\tbInitFirstEntry = false;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tstrcat(filepath, \" - NOT A VALID MP3\");\n\t\t\t\t\tOutputDebugString(filepath);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tstrcpy(filepath, _mp3DirectoryPath);\n\t\t\tstrcat(filepath, fd.cFileName);\n\t\t\t\n\t\t\tsize_t filepathlen = strlen(filepath);\n\t\t\t\n\t\t\tif ( filepathlen > 0 )\n\t\t\t{\n\t\t\t\tif ( _ResolveLink(filepath, filepath) )\n\t\t\t\t{\n\t\t\t\t\tOutputDebugString(\"Resolving Link\");\n\t\t\t\t\tOutputDebugString(filepath);\n\t\t\t\t\tbShortcut = true;\n\t\t\t\t} else\n\t\t\t\t\tbShortcut = false;\n\t\t\t\t\n\t\t\t\taStream[0] = new CStream(filepath, ALStreamSources[0], ALStreamBuffers[0]);\n\n\t\t\t\tif (aStream[0] && aStream[0]->IsOpened())\n\t\t\t\t{\n\t\t\t\t\ttotal_ms = aStream[0]->GetLengthMS();\n\t\t\t\t\tdelete aStream[0];\n\t\t\t\t\taStream[0] = NULL;\n\n\t\t\t\t\tOutputDebugString(fd.cFileName);\n\t\t\t\t\t\n\t\t\t\t\tpList->pNext = new tMP3Entry;\n\t\t\t\t\t\n\t\t\t\t\ttMP3Entry *e = pList->pNext;\n\t\t\t\t\t\n\t\t\t\t\tif ( e == NULL )\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t\n\t\t\t\t\tpList = pList->pNext;\n\t\t\t\t\t\n\t\t\t\t\tstrcpy(e->aFilename, fd.cFileName);\n\t\t\t\t\te->nTrackLength = total_ms;\n\t\t\t\t\te->pNext = NULL;\n\t\t\t\t\t\n\t\t\t\t\tif ( bShortcut )\n\t\t\t\t\t{\n\t\t\t\t\t\te->pLinkPath = new char [MAX_PATH*2];\n\t\t\t\t\t\tstrcpy(e->pLinkPath, filepath);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\te->pLinkPath = NULL;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tnNumMP3s++;\n\t\t\t\t\t\n\t\t\t\t\tOutputDebugString(fd.cFileName);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tstrcat(filepath, \" - NOT A VALID MP3\");\n\t\t\t\t\tOutputDebugString(filepath);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tFindClose(hFind);\n}\n\nstatic void\n_DeleteMP3Entries(void)\n{\n\ttMP3Entry *e = _pMP3List;\n\n\twhile ( e != NULL )\n\t{\n\t\ttMP3Entry *next = e->pNext;\n\t\t\n\t\tif ( next == NULL )\n\t\t\tnext = NULL;\n\t\t\n\t\tif ( e->pLinkPath != NULL )\n\t\t{\n#ifndef FIX_BUGS\n\t\t\tdelete   e->pLinkPath; // BUG: should be delete []\n#else\n\t\t\tdelete[] e->pLinkPath;\n#endif\n\t\t\te->pLinkPath = NULL;\n\t\t}\n\t\t\n\t\tdelete e;\n\t\t\n\t\tif ( next )\n\t\t\te = next;\n\t\telse\n\t\t\te = NULL;\n\t\t\n\t\tnNumMP3s--;\n\t}\n\t\n\t\n\tif ( nNumMP3s != 0 )\n\t{\n\t\tOutputDebugString(\"Not all MP3 entries were deleted\");\n\t\tnNumMP3s = 0;\n\t}\n\t\n\t_pMP3List = NULL;\n}\n\nstatic tMP3Entry *\n_GetMP3EntryByIndex(uint32 idx)\n{\n\tuint32 n = ( idx < nNumMP3s ) ? idx : 0;\n\t\n\tif ( _pMP3List != NULL )\n\t{\n\t\ttMP3Entry *e = _pMP3List;\n\t\t\n\t\tfor ( uint32 i = 0; i < n; i++ )\n\t\t\te = e->pNext;\n\t\t\n\t\treturn e;\n\t\t\t\n\t}\n\t\n\treturn NULL;\n}\n\nstatic inline bool\n_GetMP3PosFromStreamPos(uint32 *pPosition, tMP3Entry **pEntry)\n{\n\t_CurMP3Index = 0;\n\t\n\tfor ( *pEntry = _pMP3List; *pEntry != NULL; *pEntry = (*pEntry)->pNext )\n\t{\n\t\tif (   *pPosition >= (*pEntry)->nTrackStreamPos\n\t\t\t&& *pPosition <  (*pEntry)->nTrackLength + (*pEntry)->nTrackStreamPos )\n\t\t{\n\t\t\t*pPosition -= (*pEntry)->nTrackStreamPos;\n\t\t\t_CurMP3Pos = *pPosition;\n\t\t\t\n\t\t\treturn true;\n\t\t}\n\t\t\n\t\t_CurMP3Index++;\n\t}\n\t\t\t\t\n\t*pPosition = 0;\n\t*pEntry = _pMP3List;\n\t_CurMP3Pos = 0;\n\t_CurMP3Index = 0;\n\t\n\treturn false;\n}\n\nbool\ncSampleManager::IsMP3RadioChannelAvailable(void)\n{\n\treturn nNumMP3s != 0;\n}\n\n\nvoid cSampleManager::ReleaseDigitalHandle(void)\n{\n\tif ( ALDevice )\n\t{\n\t\tprevprovider = curprovider;\n\t\trelease_existing();\n\t\tcurprovider = -1;\n\t}\n}\n\nvoid cSampleManager::ReacquireDigitalHandle(void)\n{\n\tif ( ALDevice )\n\t{\n\t\tif ( prevprovider != -1 )\n\t\t\tset_new_provider(prevprovider);\n\t}\n}\n\nbool\ncSampleManager::Initialise(void)\n{\n\tif ( _bSampmanInitialised )\n\t\treturn true;\n\n\tEFXInit();\n\tCStream::Initialise();\n\n\t{\n\t\tfor ( int32 i = 0; i < TOTAL_AUDIO_SAMPLES; i++ )\n\t\t{\n\t\t\tm_aSamples[i].nOffset    = 0;\n\t\t\tm_aSamples[i].nSize      = 0;\n\t\t\tm_aSamples[i].nFrequency = MAX_FREQ;\n\t\t\tm_aSamples[i].nLoopStart = 0;\n\t\t\tm_aSamples[i].nLoopEnd   = -1;\n\t\t}\n\t\t\n\t\tm_nEffectsVolume     = MAX_VOLUME;\n\t\tm_nMusicVolume       = MAX_VOLUME;\n\t\tm_nEffectsFadeVolume = MAX_VOLUME;\n\t\tm_nMusicFadeVolume   = MAX_VOLUME;\n\t\n\t\tm_nMonoMode = 0;\n\t}\n\t\n\t{\n\t\tcurprovider = -1;\n\t\tprevprovider = -1;\n\t\t\t\n\t\t_usingEFX = false;\n\t\tusingEAX =0;\n\t\tusingEAX3=0;\n\t\t\t\n\t\t_fEffectsLevel = 0.0f;\n\t\t\t\n\t\t_maxSamples = 0;\n\t\t\n\t\tALDevice = NULL;\n\t\tALContext = NULL;\n\t}\n\t\n\t{\n\t\tfpSampleDescHandle = NULL;\n\t\tfpSampleDataHandle = NULL;\n\t\t\n\t\tfor ( int32 i = 0; i < MAX_SFX_BANKS; i++ )\n\t\t{\n\t\t\tbSampleBankLoaded[i]             = false;\n\t\t\tnSampleBankDiscStartOffset[i]    = 0;\n\t\t\tnSampleBankSize[i]               = 0;\n\t\t\tnSampleBankMemoryStartAddress[i] = 0;\n\t\t}\n\t}\n\t\n\t{\n\t\tfor ( int32 i = 0; i < MAX_PEDSFX; i++ )\n\t\t{\n\t\t\tnPedSlotSfx[i]     = NO_SAMPLE;\n\t\t\tnPedSlotSfxAddr[i] = 0;\n\t\t}\n\t\t\n\t\tnCurrentPedSlot = 0;\n\t}\n\t\n\t{\n\t\tfor ( int32 i = 0; i < MAXCHANNELS+MAX2DCHANNELS; i++ )\n\t\t\tnChannelVolume[i] = 0;\n\t}\n\t\n\t{\t\n\t\tfor ( int32 i = 0; i < TOTAL_STREAMED_SOUNDS; i++ )\n\t\t\tnStreamLength[i] = 0;\n\t}\n\t\n\t\tadd_providers();\n\n#ifdef AUDIO_CACHE\n\tFILE *cacheFile = fcaseopen(\"audio\\\\sound.cache\", \"rb\");\n\tif (cacheFile) {\n\t\tdebug(\"Loadind audio cache (If game crashes around here, then your cache is corrupted, remove audio/sound.cache)\\n\");\n\t\tfread(nStreamLength, sizeof(uint32), TOTAL_STREAMED_SOUNDS, cacheFile);\n\t\tfclose(cacheFile);\n\t} else\n\t{\n\t\tdebug(\"Cannot load audio cache\\n\");\n#endif\n\n\t\tfor ( int32 i = 0; i < TOTAL_STREAMED_SOUNDS; i++ )\n\t\t{\t\n\t\t\taStream[0] = new CStream(StreamedNameTable[i], ALStreamSources[0], ALStreamBuffers[0], IsThisTrackAt16KHz(i) ? 16000 : 32000);\n\t\t\t\n\t\t\tif ( aStream[0] && aStream[0]->IsOpened() )\n\t\t\t{\n\t\t\t\tuint32 tatalms = aStream[0]->GetLengthMS();\n\t\t\t\tdelete aStream[0];\n\t\t\t\taStream[0] = NULL;\n\t\t\t\t\n\t\t\t\tnStreamLength[i] = tatalms;\n\t\t\t}\n\t\t\telse\n\t\t\t\tUSERERROR(\"Can't open '%s'\\n\", StreamedNameTable[i]);\n\t\t}\n#ifdef AUDIO_CACHE\n\t\tcacheFile = fcaseopen(\"audio\\\\sound.cache\", \"wb\");\n\t\tif(cacheFile) {\n\t\t\tdebug(\"Saving audio cache\\n\");\n\t\t\tfwrite(nStreamLength, sizeof(uint32), TOTAL_STREAMED_SOUNDS, cacheFile);\n\t\t\tfclose(cacheFile);\n\t\t} else {\n\t\t\tdebug(\"Cannot save audio cache\\n\");\n\t\t}\n\t}\n#endif\n\n\t{\n\t\tif ( !InitialiseSampleBanks() )\n\t\t{\n\t\t\tTerminate();\n\t\t\treturn false;\n\t\t}\n\t\t\n\t\tnSampleBankMemoryStartAddress[SFX_BANK_0] = (uintptr)malloc(nSampleBankSize[SFX_BANK_0]);\n\t\tASSERT(nSampleBankMemoryStartAddress[SFX_BANK_0] != 0);\n\t\t\n\t\tif ( nSampleBankMemoryStartAddress[SFX_BANK_0] == 0 )\n\t\t{\n\t\t\tTerminate();\n\t\t\treturn false;\n\t\t}\n\t\t\n\t\tnSampleBankMemoryStartAddress[SFX_BANK_PED_COMMENTS] = (uintptr)malloc(PED_BLOCKSIZE*MAX_PEDSFX);\n\t\tASSERT(nSampleBankMemoryStartAddress[SFX_BANK_PED_COMMENTS] != 0);\n\t\n\t\tLoadSampleBank(SFX_BANK_0);\n\t}\n\t\n\t{\n\t\tfor ( int32 i = 0; i < MAX_STREAMS; i++ )\n\t\t{\n\t\t\taStream[i]       = NULL;\n\t\t\tnStreamVolume[i] = 100;\n\t\t\tnStreamPan[i]    = 63;\n\t\t}\n\t}\n\t\n\t{\n\t\t_bSampmanInitialised = true;\n\t\t\n\t\tif ( defaultProvider >= 0 && defaultProvider < m_nNumberOfProviders )\n\t\t{\n\t\t\tset_new_provider(defaultProvider);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tTerminate();\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t{\n\t\tnNumMP3s = 0;\n\t\t\n\t\t_pMP3List = NULL;\n\t\t\n\t\t_FindMP3s();\n\t\t\n\t\tif ( nNumMP3s != 0 )\n\t\t{\n\t\t\tnStreamLength[STREAMED_SOUND_RADIO_MP3_PLAYER] = 0;\n\t\t\t\n\t\t\tfor ( tMP3Entry *e = _pMP3List; e != NULL; e = e->pNext )\n\t\t\t{\n\t\t\t\te->nTrackStreamPos = nStreamLength[STREAMED_SOUND_RADIO_MP3_PLAYER];\n\t\t\t\tnStreamLength[STREAMED_SOUND_RADIO_MP3_PLAYER] += e->nTrackLength;\n\t\t\t}\n\t\t\t\n\t\t\ttime_t t = time(NULL);\n\t\t\ttm *localtm;\n\t\t\tbool bUseRandomTable;\n\t\t\t\n\t\t\tif ( t == -1 )\n\t\t\t\tbUseRandomTable = true;\n\t\t\telse\n\t\t\t{\n\t\t\t\tbUseRandomTable = false;\n\t\t\t\tlocaltm = localtime(&t);\n\t\t\t}\n\t\t\t\n\t\t\tint32 randval;\n\t\t\tif ( bUseRandomTable )\n\t\t\t\trandval = AudioManager.GetRandomNumber(1);\n\t\t\telse\n\t\t\t\trandval = localtm->tm_sec * localtm->tm_min;\n\t\t\t\n\t\t\t_CurMP3Index = randval % nNumMP3s;\n\t\t\t\n\t\t\ttMP3Entry *randmp3 = _pMP3List;\n\t\t\tfor ( int32 i = randval % nNumMP3s; i > 0; --i)\n\t\t\t\trandmp3 = randmp3->pNext;\n\t\t\t\n\t\t\tif ( bUseRandomTable )\n\t\t\t\t_CurMP3Pos = AudioManager.GetRandomNumber(0)     % randmp3->nTrackLength;\n\t\t\telse\n\t\t\t{\n\t\t\t\tif ( localtm->tm_sec > 0 )\n\t\t\t\t{\n\t\t\t\t\tint32 s = localtm->tm_sec;\n\t\t\t\t\t_CurMP3Pos = s*s*s*s*s*s*s*s                 % randmp3->nTrackLength;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\t_CurMP3Pos = AudioManager.GetRandomNumber(0) % randmp3->nTrackLength;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t\t_CurMP3Pos = 0;\n\t\t\n\t\t_bIsMp3Active = false;\n\t}\n\t\n\treturn true;\n}\n\nvoid\ncSampleManager::Terminate(void)\n{\n\tfor (int32 i = 0; i < MAX_STREAMS; i++)\n\t{\n\t\tCStream *stream = aStream[i];\n\t\tif (stream)\n\t\t{\n\t\t\tdelete stream;\n\t\t\taStream[i] = NULL;\n\t\t}\n\t}\n\n\trelease_existing();\n\n\t_DeleteMP3Entries();\n\n\tCStream::Terminate();\n\n\tif ( nSampleBankMemoryStartAddress[SFX_BANK_0] != 0 )\n\t{\n\t\tfree((void *)nSampleBankMemoryStartAddress[SFX_BANK_0]);\n\t\tnSampleBankMemoryStartAddress[SFX_BANK_0] = 0;\n\t}\n\n\tif ( nSampleBankMemoryStartAddress[SFX_BANK_PED_COMMENTS] != 0 )\n\t{\n\t\tfree((void *)nSampleBankMemoryStartAddress[SFX_BANK_PED_COMMENTS]);\n\t\tnSampleBankMemoryStartAddress[SFX_BANK_PED_COMMENTS] = 0;\n\t}\n\t\n\t_bSampmanInitialised = false;\n}\n\nbool cSampleManager::CheckForAnAudioFileOnCD(void)\n{\n\treturn true;\n}\n\nchar cSampleManager::GetCDAudioDriveLetter(void)\n{\n\treturn '\\0';\n}\n\nvoid\ncSampleManager::UpdateEffectsVolume(void)\n{\n\tif ( _bSampmanInitialised )\n\t{\n\t\tfor ( int32 i = 0; i < MAXCHANNELS+MAX2DCHANNELS; i++ )\n\t\t{\n\t\t\tif ( GetChannelUsedFlag(i) )\n\t\t\t{\n\t\t\t\tif ( nChannelVolume[i] != 0 )\n\t\t\t\t\taChannel[i].SetVolume(m_nEffectsFadeVolume*nChannelVolume[i]*m_nEffectsVolume >> 14);\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\ncSampleManager::SetEffectsMasterVolume(uint8 nVolume)\n{\n\tm_nEffectsVolume = nVolume;\n\tUpdateEffectsVolume();\n}\n\nvoid\ncSampleManager::SetMusicMasterVolume(uint8 nVolume)\n{\n\tm_nMusicVolume = nVolume;\n}\n\nvoid\ncSampleManager::SetMP3BoostVolume(uint8 nVolume)\n{\n\tm_nMP3BoostVolume = nVolume;\n}\n\nvoid\ncSampleManager::SetEffectsFadeVolume(uint8 nVolume)\n{\n\tm_nEffectsFadeVolume = nVolume;\n\tUpdateEffectsVolume();\n}\n\nvoid\ncSampleManager::SetMusicFadeVolume(uint8 nVolume)\n{\n\tm_nMusicFadeVolume = nVolume;\n}\n\nvoid\ncSampleManager::SetMonoMode(uint8 nMode)\n{\n\tm_nMonoMode = nMode;\n}\n\nbool\ncSampleManager::LoadSampleBank(uint8 nBank)\n{\n\tASSERT( nBank < MAX_SFX_BANKS);\n\t\n\tif ( CTimer::GetIsCodePaused() )\n\t\treturn false;\n\t\n\tif ( MusicManager.IsInitialised()\n\t\t&& MusicManager.GetMusicMode() == MUSICMODE_CUTSCENE\n\t\t&& nBank != SFX_BANK_0 )\n\t{\n\t\treturn false;\n\t}\n\t\n#ifdef OPUS_SFX\n\tint samplesRead = 0;\n\tint samplesSize = nSampleBankSize[nBank] / 2;\n\top_pcm_seek(fpSampleDataHandle, 0);\n\twhile (samplesSize > 0) {\n\t\tint size = op_read(fpSampleDataHandle, (opus_int16 *)(nSampleBankMemoryStartAddress[nBank] + samplesRead), samplesSize, NULL);\n\t\tif (size <= 0) {\n\t\t\t// huh?\n\t\t\t//assert(0);\n\t\t\tbreak;\n\t\t}\n\t\tsamplesRead += size*2;\n\t\tsamplesSize -= size;\n\t}\n#else\n\tif ( fseek(fpSampleDataHandle, nSampleBankDiscStartOffset[nBank], SEEK_SET) != 0 )\n\t\treturn false;\n\t\n\tif ( fread((void *)nSampleBankMemoryStartAddress[nBank], 1, nSampleBankSize[nBank], fpSampleDataHandle) != nSampleBankSize[nBank] )\n\t\treturn false;\n#endif\n\tbSampleBankLoaded[nBank] = true;\n\t\n\treturn true;\n}\n\nvoid\ncSampleManager::UnloadSampleBank(uint8 nBank)\n{\n\tASSERT( nBank < MAX_SFX_BANKS);\n\t\n\tbSampleBankLoaded[nBank] = false;\n}\n\nbool\ncSampleManager::IsSampleBankLoaded(uint8 nBank)\n{\n\tASSERT( nBank < MAX_SFX_BANKS);\n\t\n\treturn bSampleBankLoaded[nBank];\n}\n\nbool\ncSampleManager::IsPedCommentLoaded(uint32 nComment)\n{\n\tASSERT( nComment < TOTAL_AUDIO_SAMPLES );\n\t\n\tint8 slot;\n\n\tfor ( int32 i = 0; i < _TODOCONST(3); i++ )\n\t{\n\t\tslot = nCurrentPedSlot - i - 1;\n#ifdef FIX_BUGS\n\t\tif (slot < 0)\n\t\t\tslot += ARRAY_SIZE(nPedSlotSfx);\n#endif\n\t\tif ( nComment == nPedSlotSfx[slot] )\n\t\t\treturn true;\n\t}\n\t\n\treturn false;\n}\n\n\nint32\ncSampleManager::_GetPedCommentSlot(uint32 nComment)\n{\n\tint8 slot;\n\n\tfor (int32 i = 0; i < _TODOCONST(3); i++)\n\t{\n\t\tslot = nCurrentPedSlot - i - 1;\n#ifdef FIX_BUGS\n\t\tif (slot < 0)\n\t\t\tslot += ARRAY_SIZE(nPedSlotSfx);\n#endif\n\t\tif (nComment == nPedSlotSfx[slot])\n\t\t\treturn slot;\n\t}\n\n\treturn -1;\n}\n\nbool\ncSampleManager::LoadPedComment(uint32 nComment)\n{\n\tASSERT( nComment < TOTAL_AUDIO_SAMPLES );\n\t\n\tif ( CTimer::GetIsCodePaused() )\n\t\treturn false;\n\t\n\t// no talking peds during cutsenes or the game end\n\tif ( MusicManager.IsInitialised() )\n\t{\n\t\tswitch ( MusicManager.GetMusicMode() )\n\t\t{\n\t\t\tcase MUSICMODE_CUTSCENE:\n\t\t\t{\n\t\t\t\treturn false;\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n#ifdef OPUS_SFX\n\tint samplesRead = 0;\n\tint samplesSize = m_aSamples[nComment].nSize / 2;\n\top_pcm_seek(fpSampleDataHandle, m_aSamples[nComment].nOffset / 2);\n\twhile (samplesSize > 0) {\n\t\tint size = op_read(fpSampleDataHandle, (opus_int16 *)(nSampleBankMemoryStartAddress[SAMPLEBANK_PED] + PED_BLOCKSIZE * nCurrentPedSlot + samplesRead),\n\t\t                   samplesSize, NULL);\n\t\tif (size <= 0) {\n\t\t\treturn false;\n\t\t}\n\t\tsamplesRead += size * 2;\n\t\tsamplesSize -= size;\n\t}\n#else\n\tif ( fseek(fpSampleDataHandle, m_aSamples[nComment].nOffset, SEEK_SET) != 0 )\n\t\treturn false;\n\t\n\tif ( fread((void *)(nSampleBankMemoryStartAddress[SFX_BANK_PED_COMMENTS] + PED_BLOCKSIZE*nCurrentPedSlot), 1, m_aSamples[nComment].nSize, fpSampleDataHandle) != m_aSamples[nComment].nSize )\n\t\treturn false;\n\n#endif\n\tnPedSlotSfx[nCurrentPedSlot] = nComment;\n\t\t\n\tif ( ++nCurrentPedSlot >= MAX_PEDSFX )\n\t\tnCurrentPedSlot = 0;\n\t\n\treturn true;\n}\n\nint32\ncSampleManager::GetBankContainingSound(uint32 offset)\n{\n\tif ( offset >= BankStartOffset[SFX_BANK_PED_COMMENTS] )\n\t\treturn SFX_BANK_PED_COMMENTS;\n\t\n\tif ( offset >= BankStartOffset[SFX_BANK_0] )\n\t\treturn SFX_BANK_0;\n\t\n\treturn INVALID_SFX_BANK;\n}\n\nint32\ncSampleManager::GetSampleBaseFrequency(uint32 nSample)\n{\n\tASSERT( nSample < TOTAL_AUDIO_SAMPLES );\n\treturn m_aSamples[nSample].nFrequency;\n}\n\nint32\ncSampleManager::GetSampleLoopStartOffset(uint32 nSample)\n{\n\tASSERT( nSample < TOTAL_AUDIO_SAMPLES );\n\treturn m_aSamples[nSample].nLoopStart;\n}\n\nint32\ncSampleManager::GetSampleLoopEndOffset(uint32 nSample)\n{\n\tASSERT( nSample < TOTAL_AUDIO_SAMPLES );\n\treturn m_aSamples[nSample].nLoopEnd;\n}\n\nuint32\ncSampleManager::GetSampleLength(uint32 nSample)\n{\n\tASSERT( nSample < TOTAL_AUDIO_SAMPLES );\n\treturn m_aSamples[nSample].nSize / sizeof(uint16);\n}\n\nbool cSampleManager::UpdateReverb(void)\n{\n\tif ( !usingEAX && !_usingEFX )\n\t\treturn false;\n\n\tif ( AudioManager.GetFrameCounter() & 15 )\n\t\treturn false;\n\n\tfloat fRatio = 0.0f;\n\n#define MIN_DIST 0.5f\n#define CALCULATE_RATIO(value, maxDist, maxRatio) (value > MIN_DIST && value < maxDist ? value / maxDist * maxRatio : 0)\n\n\tfRatio += CALCULATE_RATIO(AudioManager.GetReflectionsDistance(REFLECTION_CEIL_NORTH), 10.0f, 1/2.f);\n\tfRatio += CALCULATE_RATIO(AudioManager.GetReflectionsDistance(REFLECTION_CEIL_SOUTH), 10.0f, 1/2.f);\n\tfRatio += CALCULATE_RATIO(AudioManager.GetReflectionsDistance(REFLECTION_CEIL_WEST), 10.0f, 1/2.f);\n\tfRatio += CALCULATE_RATIO(AudioManager.GetReflectionsDistance(REFLECTION_CEIL_EAST), 10.0f, 1/2.f);\n\n\tfRatio += CALCULATE_RATIO((AudioManager.GetReflectionsDistance(REFLECTION_NORTH) + AudioManager.GetReflectionsDistance(REFLECTION_SOUTH)) / 2.f, 4.0f, 1/3.f);\n\tfRatio += CALCULATE_RATIO((AudioManager.GetReflectionsDistance(REFLECTION_WEST) + AudioManager.GetReflectionsDistance(REFLECTION_EAST)) / 2.f, 4.0f, 1/3.f);\n\n#undef CALCULATE_RATIO\n#undef MIN_DIST\n\t\n\tfRatio = clamp(fRatio, 0.0f, 0.6f);\n\t\n\tif ( fRatio == _fPrevEaxRatioDestination )\n\t\treturn false;\n\t\n#ifdef JUICY_OAL\n\tif ( usingEAX3 || _usingEFX )\n#else\n\tif ( usingEAX3 )\n#endif\n\t{\n\t\tfRatio = Min(fRatio * 1.67f, 1.0f);\n\t\tif ( EAX3ListenerInterpolate(&StartEAX3, &FinishEAX3, fRatio, &EAX3Params, false) )\n\t\t{\n\t\t\tEAX_SetAll(&EAX3Params);\n\t\t\t\n\t\t\t/*\n\t\t\tif ( IsFXSupported() )\n\t\t\t{\n\t\t\t\talAuxiliaryEffectSloti(ALEffectSlot, AL_EFFECTSLOT_EFFECT, ALEffect);\n\t\t\t\n\t\t\t\tfor ( int32 i = 0; i < MAXCHANNELS; i++ )\n\t\t\t\t\taChannel[i].UpdateReverb(ALEffectSlot);\n\t\t\t}\n\t\t\t*/\n\t\t\t\n\t\t\t_fEffectsLevel = fRatio * 0.75f;\n\t\t}\n\t}\n\telse\n\t{\n\t\tif ( _usingEFX )\n\t\t\t_fEffectsLevel = fRatio * 0.8f;\n\t\telse\n\t\t\t_fEffectsLevel = fRatio * 0.22f;\n\t}\n\t_fEffectsLevel = Min(_fEffectsLevel, 1.0f);\n\n\t_fPrevEaxRatioDestination = fRatio;\n\t\n\treturn true;\n}\n\nvoid\ncSampleManager::SetChannelReverbFlag(uint32 nChannel, uint8 nReverbFlag)\n{\n\tASSERT( nChannel < MAXCHANNELS+MAX2DCHANNELS );\n\t\n\tif ( usingEAX || _usingEFX )\n\t{\n\t\tif ( IsFXSupported() )\n\t\t{\n\t\t\talAuxiliaryEffectSloti(ALEffectSlot, AL_EFFECTSLOT_EFFECT, ALEffect);\n\t\t\t\n\t\t\tif ( nReverbFlag != 0 )\n\t\t\t\taChannel[nChannel].SetReverbMix(ALEffectSlot, _fEffectsLevel);\n\t\t\telse\n\t\t\t\taChannel[nChannel].SetReverbMix(ALEffectSlot, 0.0f);\n\t\t}\n\t}\n}\n\nbool\ncSampleManager::InitialiseChannel(uint32 nChannel, uint32 nSfx, uint8 nBank)\n{\n\tASSERT( nChannel < MAXCHANNELS+MAX2DCHANNELS );\n\t\n\tuintptr addr;\n\t\n\tif ( nSfx < SAMPLEBANK_MAX )\n\t{\n\t\tif ( !IsSampleBankLoaded(nBank) )\n\t\t\treturn false;\n\t\t\n\t\taddr = nSampleBankMemoryStartAddress[nBank] + m_aSamples[nSfx].nOffset - m_aSamples[BankStartOffset[nBank]].nOffset;\n\t}\n\telse\n\t{\n\t\tif ( !IsPedCommentLoaded(nSfx) )\n\t\t\treturn false;\n\t\t\n\t\tint32 slot = _GetPedCommentSlot(nSfx);\n\t\taddr = (nSampleBankMemoryStartAddress[SFX_BANK_PED_COMMENTS] + PED_BLOCKSIZE * slot);\n\t}\n\t\n\tif ( GetChannelUsedFlag(nChannel) )\n\t{\n\t\tTRACE(\"Stopping channel %d - really!!!\", nChannel);\n\t\tStopChannel(nChannel);\n\t}\n\t\n\taChannel[nChannel].Reset();\n\tif ( aChannel[nChannel].HasSource() )\n\t{\t\n\t\taChannel[nChannel].SetSampleData   ((void*)addr, m_aSamples[nSfx].nSize, m_aSamples[nSfx].nFrequency);\n\t\taChannel[nChannel].SetLoopPoints   (0, -1);\n\t\taChannel[nChannel].SetPitch        (1.0f);\n\t\treturn true;\n\t}\n\t\n\treturn false;\n}\n\nvoid\ncSampleManager::SetChannelEmittingVolume(uint32 nChannel, uint32 nVolume)\n{\n\tASSERT( nChannel != CHANNEL2D );\n\tASSERT( nChannel < MAXCHANNELS+MAX2DCHANNELS );\n\t\n\tuint32 vol = nVolume;\n\tif ( vol > MAX_VOLUME ) vol = MAX_VOLUME;\n\t\n\tnChannelVolume[nChannel] = vol;\n\t\n\tif (MusicManager.GetMusicMode() == MUSICMODE_CUTSCENE ) {\n\t\tif (MusicManager.GetCurrentTrack() == STREAMED_SOUND_CUTSCENE_FINALE)\n\t\t\tnChannelVolume[nChannel] = 0;\n\t\telse\n\t\t\tnChannelVolume[nChannel] >>= 2;\n\t}\n\n\t// no idea, does this one looks like a bug or it's SetChannelVolume ?\n\taChannel[nChannel].SetVolume(m_nEffectsFadeVolume*nChannelVolume[nChannel]*m_nEffectsVolume >> 14);\n}\n\nvoid\ncSampleManager::SetChannel3DPosition(uint32 nChannel, float fX, float fY, float fZ)\n{\n\tASSERT( nChannel != CHANNEL2D );\n\tASSERT( nChannel < MAXCHANNELS+MAX2DCHANNELS );\n\t\n\taChannel[nChannel].SetPosition(-fX, fY, fZ);\n}\n\nvoid\ncSampleManager::SetChannel3DDistances(uint32 nChannel, float fMax, float fMin)\n{\n\tASSERT( nChannel != CHANNEL2D );\n\tASSERT( nChannel < MAXCHANNELS+MAX2DCHANNELS );\n\taChannel[nChannel].SetDistances(fMax, fMin);\n}\n\nvoid\ncSampleManager::SetChannelVolume(uint32 nChannel, uint32 nVolume)\n{\n\tASSERT( nChannel == CHANNEL2D );\n\tASSERT( nChannel < MAXCHANNELS+MAX2DCHANNELS );\n\t\n\tif ( nChannel == CHANNEL2D )\n\t{\n\t\tuint32 vol = nVolume;\n\t\tif ( vol > MAX_VOLUME ) vol = MAX_VOLUME;\n\t\t\n\t\tnChannelVolume[nChannel] = vol;\n\t\t\n\t\t// increase the volume for JB.MP3 and S4_BDBD.MP3\n\t\tif (MusicManager.GetMusicMode() == MUSICMODE_CUTSCENE ) {\n\t\t\tif (MusicManager.GetCurrentTrack() == STREAMED_SOUND_CUTSCENE_FINALE)\n\t\t\t\tnChannelVolume[nChannel] = 0;\n\t\t\telse\n\t\t\t\tnChannelVolume[nChannel] >>= 2;\n\t\t}\n\n\t\taChannel[nChannel].SetVolume(m_nEffectsFadeVolume*vol*m_nEffectsVolume >> 14);\n\t}\n}\n\nvoid\ncSampleManager::SetChannelPan(uint32 nChannel, uint32 nPan)\n{\n\tASSERT(nChannel == CHANNEL2D);\n\tASSERT( nChannel < MAXCHANNELS+MAX2DCHANNELS );\n\t\n\tif ( nChannel == CHANNEL2D )\n\t{\n\t\taChannel[nChannel].SetPan(nPan);\n\t}\n}\n\nvoid\ncSampleManager::SetChannelFrequency(uint32 nChannel, uint32 nFreq)\n{\n\tASSERT( nChannel < MAXCHANNELS+MAX2DCHANNELS );\n\t\n\taChannel[nChannel].SetCurrentFreq(nFreq);\n}\n\nvoid\ncSampleManager::SetChannelLoopPoints(uint32 nChannel, uint32 nLoopStart, int32 nLoopEnd)\n{\n\tASSERT( nChannel < MAXCHANNELS+MAX2DCHANNELS );\n\t\n\taChannel[nChannel].SetLoopPoints(nLoopStart / (DIGITALBITS / 8), nLoopEnd / (DIGITALBITS / 8));\n}\n\nvoid\ncSampleManager::SetChannelLoopCount(uint32 nChannel, uint32 nLoopCount)\n{\n\tASSERT( nChannel < MAXCHANNELS+MAX2DCHANNELS );\n\t\n\taChannel[nChannel].SetLoopCount(nLoopCount);\n}\n\nbool\ncSampleManager::GetChannelUsedFlag(uint32 nChannel)\n{\n\tASSERT( nChannel < MAXCHANNELS+MAX2DCHANNELS );\n\t\n\treturn aChannel[nChannel].IsUsed();\n}\n\nvoid\ncSampleManager::StartChannel(uint32 nChannel)\n{\n\tASSERT( nChannel < MAXCHANNELS+MAX2DCHANNELS );\n\t\n\taChannel[nChannel].Start();\n}\n\nvoid\ncSampleManager::StopChannel(uint32 nChannel)\n{\n\tASSERT( nChannel < MAXCHANNELS+MAX2DCHANNELS );\n\t\n\taChannel[nChannel].Stop();\n}\n\nvoid\ncSampleManager::PreloadStreamedFile(uint32 nFile, uint8 nStream)\n{\n\tchar filename[MAX_PATH];\n\t\n\tASSERT( nStream < MAX_STREAMS );\n\n\tif ( nFile < TOTAL_STREAMED_SOUNDS )\n\t{\n\t\tif ( aStream[nStream] )\n\t\t{\n\t\t\tdelete aStream[nStream];\n\t\t\taStream[nStream] = NULL;\n\t\t}\n\t\t\n\t\tstrcpy(filename, StreamedNameTable[nFile]);\n\t\t\n\t\tCStream *stream = new CStream(filename, ALStreamSources[nStream], ALStreamBuffers[nStream], IsThisTrackAt16KHz(nFile) ? 16000 : 32000);\n\t\tASSERT(stream != NULL);\n\t\t\n\t\taStream[nStream] = stream;\n\t\tif ( !stream->Setup() )\n\t\t{\n\t\t\tdelete stream;\n\t\t\taStream[nStream] = NULL;\n\t\t}\n\t}\n}\n\nvoid\ncSampleManager::PauseStream(uint8 nPauseFlag, uint8 nStream)\n{\n\tASSERT( nStream < MAX_STREAMS );\n\t\n\tCStream *stream = aStream[nStream];\n\t\n\tif ( stream )\n\t{\n\t\tstream->SetPause(nPauseFlag != 0);\n\t}\n}\n\nvoid\ncSampleManager::StartPreloadedStreamedFile(uint8 nStream)\n{\n\tASSERT( nStream < MAX_STREAMS );\n\t\n\tCStream *stream = aStream[nStream];\n\t\n\tif ( stream )\n\t{\n\t\tif ( stream->IsOpened() )\n\t\t{\n\t\t\tstream->Start();\n\t\t}\n\t}\n}\n\nbool\ncSampleManager::StartStreamedFile(uint32 nFile, uint32 nPos, uint8 nStream)\n{\n\tint i = 0;\n\tuint32 position = nPos;\n\tchar filename[MAX_PATH];\n\t\n\tif ( nFile >= TOTAL_STREAMED_SOUNDS )\n\t\treturn false;\n\n\tif ( aStream[nStream] )\n\t{\n\t\tdelete aStream[nStream];\n\t\taStream[nStream] = NULL;\n\t}\n\tif ( nFile == STREAMED_SOUND_RADIO_MP3_PLAYER )\n\t{\n\t\tdo\n\t\t{\n\t\t\t// Just switched to MP3 player\n\t\t\tif ( !_bIsMp3Active && i == 0 )\n\t\t\t{\n\t\t\t\tif ( nPos > nStreamLength[STREAMED_SOUND_RADIO_MP3_PLAYER] )\n\t\t\t\t\tposition = 0;\n\t\t\t\ttMP3Entry *e = _pMP3List;\n\n\t\t\t\t// Try to continue from previous song, if already started\n\t\t\t\tif(!_GetMP3PosFromStreamPos(&position, &e) && !e) {\n\t\t\t\t\tnFile = 0;\n\n\t\t\t\t\tstrcpy(filename, StreamedNameTable[nFile]);\n\t\t\t\t\tCStream* stream = new CStream(filename, ALStreamSources[nStream], ALStreamBuffers[nStream], IsThisTrackAt16KHz(nFile) ? 16000 : 32000);\n\n\t\t\t\t\taStream[nStream] = stream;\n\n\t\t\t\t\tif (stream->Setup()) {\n\t\t\t\t\t\tstream->SetLoopCount(nStreamLoopedFlag[nStream] ? 0 : 1);\n\t\t\t\t\t\tnStreamLoopedFlag[nStream] = true;\n\t\t\t\t\t\tif (position != 0)\n\t\t\t\t\t\t\tstream->SetPosMS(position);\n\n\t\t\t\t\t\tstream->Start();\n\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tdelete stream;\n\t\t\t\t\t\taStream[nStream] = NULL;\n\t\t\t\t\t}\n\t\t\t\t\treturn false;\n\n\t\t\t\t} else {\n\n\t\t\t\t\tif (e->pLinkPath != NULL)\n\t\t\t\t\t\taStream[nStream] = new CStream(e->pLinkPath, ALStreamSources[nStream], ALStreamBuffers[nStream], IsThisTrackAt16KHz(nFile) ? 16000 : 32000);\n\t\t\t\t\telse {\n\t\t\t\t\t\tstrcpy(filename, _mp3DirectoryPath);\n\t\t\t\t\t\tstrcat(filename, e->aFilename);\n\n\t\t\t\t\t\taStream[nStream] = new CStream(filename, ALStreamSources[nStream], ALStreamBuffers[nStream]);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (aStream[nStream]->Setup()) {\n\t\t\t\t\t\tif (position != 0)\n\t\t\t\t\t\t\taStream[nStream]->SetPosMS(position);\n\n\t\t\t\t\t\taStream[nStream]->Start();\n\n\t\t\t\t\t\t_bIsMp3Active = true;\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tdelete aStream[nStream];\n\t\t\t\t\t\taStream[nStream] = NULL;\n\t\t\t\t\t}\n\t\t\t\t\t// fall through, start playing from another song\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif(++_CurMP3Index >= nNumMP3s) _CurMP3Index = 0;\n\n\t\t\t\t_CurMP3Pos = 0;\n\n\t\t\t\ttMP3Entry *mp3 = _GetMP3EntryByIndex(_CurMP3Index);\n\t\t\t\tif ( !mp3 )\n\t\t\t\t{\n\t\t\t\t\tmp3 = _pMP3List;\n\t\t\t\t\tif ( !_pMP3List )\n\t\t\t\t\t{\n\t\t\t\t\t\tnFile = 0;\n\t\t\t\t\t\t_bIsMp3Active = 0;\n\t\t\t\t\t\tstrcpy(filename, StreamedNameTable[nFile]);\n\n\t\t\t\t\t\tCStream* stream = new CStream(filename, ALStreamSources[nStream], ALStreamBuffers[nStream], IsThisTrackAt16KHz(nFile) ? 16000 : 32000);\n\n\t\t\t\t\t\taStream[nStream] = stream;\n\n\t\t\t\t\t\tif (stream->Setup()) {\n\t\t\t\t\t\t\tstream->SetLoopCount(nStreamLoopedFlag[nStream] ? 0 : 1);\n\t\t\t\t\t\t\tnStreamLoopedFlag[nStream] = true;\n\t\t\t\t\t\t\tif (position != 0)\n\t\t\t\t\t\t\t\tstream->SetPosMS(position);\n\n\t\t\t\t\t\t\tstream->Start();\n\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tdelete stream;\n\t\t\t\t\t\t\taStream[nStream] = NULL;\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (mp3->pLinkPath != NULL)\n\t\t\t\t\taStream[nStream] = new CStream(mp3->pLinkPath, ALStreamSources[nStream], ALStreamBuffers[nStream], IsThisTrackAt16KHz(nFile) ? 16000 : 32000);\n\t\t\t\telse {\n\t\t\t\t\tstrcpy(filename, _mp3DirectoryPath);\n\t\t\t\t\tstrcat(filename, mp3->aFilename);\n\n\t\t\t\t\taStream[nStream] = new CStream(filename, ALStreamSources[nStream], ALStreamBuffers[nStream], IsThisTrackAt16KHz(nFile) ? 16000 : 32000);\n\t\t\t\t}\n\n\t\t\t\tif (aStream[nStream]->Setup()) {\n\t\t\t\t\taStream[nStream]->Start();\n#ifdef FIX_BUGS\n\t\t\t\t\t_bIsMp3Active = true;\n#endif\n\t\t\t\t\treturn true;\n\t\t\t\t} else {\n\t\t\t\t\tdelete aStream[nStream];\n\t\t\t\t\taStream[nStream] = NULL;\n\t\t\t\t}\n\n\t\t\t}\n\t\t\t_bIsMp3Active = 0;\n\t\t}\n\t\twhile ( ++i < nNumMP3s );\n\t\tposition = 0;\n\t\tnFile = 0;\n\t}\n\tstrcpy(filename, StreamedNameTable[nFile]);\n\t\n\tCStream *stream = new CStream(filename, ALStreamSources[nStream], ALStreamBuffers[nStream], IsThisTrackAt16KHz(nFile) ? 16000 : 32000);\n\n\taStream[nStream] = stream;\n\t\n\tif ( stream->Setup() ) {\n\t\tstream->SetLoopCount(nStreamLoopedFlag[nStream] ? 0 : 1);\n\t\tnStreamLoopedFlag[nStream] = true;\n\t\tif (position != 0)\n\t\t\tstream->SetPosMS(position);\t\n\n\t\tstream->Start();\n\t\t\n\t\treturn true;\n\t} else {\n\t\tdelete stream;\n\t\taStream[nStream] = NULL;\n\t}\n\treturn false;\n}\n\nvoid\ncSampleManager::StopStreamedFile(uint8 nStream)\n{\n\tASSERT( nStream < MAX_STREAMS );\n\n\tCStream *stream = aStream[nStream];\n\t\n\tif ( stream )\n\t{\n\t\tdelete stream;\n\t\taStream[nStream] = NULL;\n\n\t\tif ( nStream == 0 )\n\t\t\t_bIsMp3Active = false;\n\t}\n}\n\nint32\ncSampleManager::GetStreamedFilePosition(uint8 nStream)\n{\n\tASSERT( nStream < MAX_STREAMS );\n\t\n\tCStream *stream = aStream[nStream];\n\t\n\tif ( stream )\n\t{\n\t\tif ( _bIsMp3Active )\n\t\t{\n\t\t\ttMP3Entry *mp3 = _GetMP3EntryByIndex(_CurMP3Index);\n\t\t\t\n\t\t\tif ( mp3 != NULL )\n\t\t\t{\n\t\t\t\treturn stream->GetPosMS() + mp3->nTrackStreamPos;\n\t\t\t}\n\t\t\telse\n\t\t\t\treturn 0;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn stream->GetPosMS();\n\t\t}\n\t}\n\t\n\treturn 0;\n}\n\nvoid\ncSampleManager::SetStreamedVolumeAndPan(uint8 nVolume, uint8 nPan, uint8 nEffectFlag, uint8 nStream)\n{\n\tASSERT( nStream < MAX_STREAMS );\n\t\n\tfloat boostMult = 0.0f;\n\n\tif ( nVolume > MAX_VOLUME )\n\t\tnVolume = MAX_VOLUME;\n\t\n\tif ( nPan > MAX_VOLUME )\n\t\tnPan = MAX_VOLUME;\n\n\tif ( MusicManager.GetRadioInCar() == USERTRACK && !MusicManager.CheckForMusicInterruptions() )\n\t\t\tboostMult = m_nMP3BoostVolume / 64.f;\n\t\t\n\tnStreamVolume[nStream] = nVolume;\n\tnStreamPan   [nStream] = nPan;\n\t\n\tCStream *stream = aStream[nStream];\n\t\n\tif ( stream )\n\t{\n\t\tif ( nEffectFlag ) {\n\t\t\tif ( nStream == 1 || nStream == 2 )\n\t\t\t\tstream->SetVolume(128*nVolume*m_nEffectsVolume >> 14);\n\t\t\telse\n\t\t\t\tstream->SetVolume(m_nEffectsFadeVolume*nVolume*m_nEffectsVolume >> 14);\n\t\t}\n\t\telse\n\t\t\tstream->SetVolume((m_nMusicFadeVolume*nVolume*(uint32)(m_nMusicVolume * boostMult + m_nMusicVolume)) >> 14);\n\t\t\n\t\tstream->SetPan(nPan);\n\t}\n}\n\nint32\ncSampleManager::GetStreamedFileLength(uint8 nStream)\n{\n\tASSERT( nStream < TOTAL_STREAMED_SOUNDS );\n\n\treturn nStreamLength[nStream];\n}\n\nbool\ncSampleManager::IsStreamPlaying(uint8 nStream)\n{\n\tASSERT( nStream < MAX_STREAMS );\n\t\n\tCStream *stream = aStream[nStream];\n\t\n\tif ( stream )\n\t{\n\t\tif ( stream->IsPlaying() )\n\t\t\treturn true;\n\t}\n\t\n\treturn false;\n}\n\nvoid\ncSampleManager::Service(void)\n{\n\tfor ( int32 i = 0; i < MAX_STREAMS; i++ )\n\t{\n\t\tCStream *stream = aStream[i];\n\t\t\n\t\tif ( stream )\n\t\t\tstream->Update();\n\t}\n\tint refCount = CChannel::channelsThatNeedService;\n\tfor ( int32 i = 0; refCount && i < MAXCHANNELS+MAX2DCHANNELS; i++ )\n\t{\n\t\tif ( aChannel[i].Update() )\n\t\t\trefCount--;\n\t}\n}\n\nbool\ncSampleManager::InitialiseSampleBanks(void)\n{\n\tint32 nBank = SFX_BANK_0;\n\t\n\tfpSampleDescHandle = fcaseopen(SampleBankDescFilename, \"rb\");\n\tif ( fpSampleDescHandle == NULL )\n\t\treturn false;\n#ifndef OPUS_SFX\n\tfpSampleDataHandle = fcaseopen(SampleBankDataFilename, \"rb\");\n\tif ( fpSampleDataHandle == NULL )\n\t{\n\t\tfclose(fpSampleDescHandle);\n\t\tfpSampleDescHandle = NULL;\n\t\t\n\t\treturn false;\n\t}\n\t\n\tfseek(fpSampleDataHandle, 0, SEEK_END);\n\tint32 _nSampleDataEndOffset = ftell(fpSampleDataHandle);\n\trewind(fpSampleDataHandle);\n#else\n\tint e;\n\tfpSampleDataHandle = op_open_file(SampleBankDataFilename, &e);\n#endif\n\tfread(m_aSamples, sizeof(tSample), TOTAL_AUDIO_SAMPLES, fpSampleDescHandle);\n#ifdef OPUS_SFX\n\tint32 _nSampleDataEndOffset = m_aSamples[TOTAL_AUDIO_SAMPLES - 1].nOffset + m_aSamples[TOTAL_AUDIO_SAMPLES - 1].nSize;\n#endif\n\tfclose(fpSampleDescHandle);\n\tfpSampleDescHandle = NULL;\n\t\n\tfor ( int32 i = 0; i < TOTAL_AUDIO_SAMPLES; i++ )\n\t{\n#ifdef FIX_BUGS\n\t\tif (nBank >= MAX_SFX_BANKS) break;\n#endif\n\t\tif ( BankStartOffset[nBank] == BankStartOffset[SFX_BANK_0] + i )\n\t\t{\n\t\t\tnSampleBankDiscStartOffset[nBank] = m_aSamples[i].nOffset;\n\t\t\tnBank++;\n\t\t}\n\t}\n\n\tnSampleBankSize[SFX_BANK_0] = nSampleBankDiscStartOffset[SFX_BANK_PED_COMMENTS] - nSampleBankDiscStartOffset[SFX_BANK_0];\n\tnSampleBankSize[SFX_BANK_PED_COMMENTS]  = _nSampleDataEndOffset                      - nSampleBankDiscStartOffset[SFX_BANK_PED_COMMENTS];\n\n\treturn true;\n}\n\nvoid\ncSampleManager::SetStreamedFileLoopFlag(uint8 nLoopFlag, uint8 nChannel)\n{\n\tnStreamLoopedFlag[nChannel] = nLoopFlag;\n}\n\n#endif\n"
  },
  {
    "path": "src/audio/soundlist.h",
    "content": "#pragma once\n\nenum eSound\n{\n\tSOUND_CAR_DOOR_CLOSE_BONNET = 0,\n\tSOUND_CAR_DOOR_CLOSE_BUMPER,\n\tSOUND_CAR_DOOR_CLOSE_FRONT_LEFT,\n\tSOUND_CAR_DOOR_CLOSE_FRONT_RIGHT,\n\tSOUND_CAR_DOOR_CLOSE_BACK_LEFT,\n\tSOUND_CAR_DOOR_CLOSE_BACK_RIGHT,\n\tSOUND_CAR_DOOR_OPEN_BONNET,\n\tSOUND_CAR_DOOR_OPEN_BUMPER,\n\tSOUND_CAR_DOOR_OPEN_FRONT_LEFT,\n\tSOUND_CAR_DOOR_OPEN_FRONT_RIGHT,\n\tSOUND_CAR_DOOR_OPEN_BACK_LEFT,\n\tSOUND_CAR_DOOR_OPEN_BACK_RIGHT,\n\tSOUND_CAR_WINDSHIELD_CRACK,\n\tSOUND_CAR_JUMP,\n\tSOUND_CAR_JUMP_2,\n\tSOUND_CAR_TYRE_POP,\n\tSOUND_16,\n\tSOUND_17,\n\tSOUND_CAR_ENGINE_START,\n\tSOUND_CAR_LIGHT_BREAK,\n\tSOUND_CAR_HYDRAULIC_1,\n\tSOUND_CAR_HYDRAULIC_2,\n\tSOUND_CAR_HYDRAULIC_3,\n\tSOUND_CAR_JERK,\n\tSOUND_CAR_SPLASH,\n\tSOUND_BOAT_SLOWDOWN,\n\tSOUND_TRAIN_DOOR_CLOSE,\n\tSOUND_TRAIN_DOOR_OPEN,\n\tSOUND_CAR_TANK_TURRET_ROTATE,\n\tSOUND_CAR_BOMB_TICK,\n\tSOUND_PLANE_ON_GROUND,\n\tSOUND_HELI_BLADE,\n\tSOUND_32,\n\tSOUND_STEP_START,\n\tSOUND_STEP_END,\n\tSOUND_FALL_LAND,\n\tSOUND_FALL_COLLAPSE,\n\tSOUND_FIGHT_37,\n\tSOUND_FIGHT_38,\n\tSOUND_FIGHT_39,\n\tSOUND_FIGHT_40,\n\tSOUND_FIGHT_41,\n\tSOUND_FIGHT_42,\n\tSOUND_FIGHT_43,\n\tSOUND_FIGHT_44,\n\tSOUND_FIGHT_45,\n\tSOUND_FIGHT_46,\n\tSOUND_FIGHT_47,\n\tSOUND_FIGHT_48,\n\tSOUND_49,\n\tSOUND_WEAPON_BAT_ATTACK,\n\tSOUND_WEAPON_KNIFE_ATTACK,\n\tSOUND_WEAPON_CHAINSAW_ATTACK,\n\tSOUND_WEAPON_CHAINSAW_IDLE,\n\tSOUND_WEAPON_CHAINSAW_MADECONTACT,\n\tSOUND_WEAPON_SHOT_FIRED,\n\tSOUND_WEAPON_RELOAD,\n\tSOUND_WEAPON_AK47_BULLET_ECHO,\n\tSOUND_WEAPON_FLAMETHROWER_FIRE,\n\tSOUND_WEAPON_SNIPER_SHOT_NO_ZOOM,\n\tSOUND_WEAPON_ROCKET_SHOT_NO_ZOOM,\n\tSOUND_WEAPON_HIT_PED,\n\tSOUND_WEAPON_HIT_VEHICLE,\n\tSOUND_GARAGE_NO_MONEY,\n\tSOUND_GARAGE_BAD_VEHICLE,\n\tSOUND_GARAGE_OPENING,\n\tSOUND_GARAGE_BOMB_ALREADY_SET,\n\tSOUND_GARAGE_BOMB1_SET,\n\tSOUND_GARAGE_BOMB2_SET,\n\tSOUND_GARAGE_BOMB3_SET,\n\tSOUND_70,\n\tSOUND_71,\n\tSOUND_GARAGE_VEHICLE_DECLINED,\n\tSOUND_GARAGE_VEHICLE_ACCEPTED,\n\tSOUND_GARAGE_DOOR_CLOSED,\n\tSOUND_GARAGE_DOOR_OPENED,\n\tSOUND_CRANE_PICKUP,\n\tSOUND_PICKUP_WEAPON_BOUGHT,\n\tSOUND_PICKUP_WEAPON,\n\tSOUND_PICKUP_HEALTH,\n\tSOUND_80,\n\tSOUND_81,\n\tSOUND_PICKUP_ADRENALINE,\n\tSOUND_PICKUP_ARMOUR,\n\tSOUND_PICKUP_BONUS,\n\tSOUND_PICKUP_MONEY,\n\tSOUND_PICKUP_HIDDEN_PACKAGE,\n\tSOUND_PICKUP_PACMAN_PILL,\n\tSOUND_PICKUP_PACMAN_PACKAGE,\n\tSOUND_PICKUP_FLOAT_PACKAGE,\n\tSOUND_BOMB_TIMED_ACTIVATED,\n\tSOUND_91,\n\tSOUND_BOMB_ONIGNITION_ACTIVATED,\n\tSOUND_BOMB_TICK,\n\tSOUND_RAMPAGE_START,\n\tSOUND_RAMPAGE_ONGOING,\n\tSOUND_RAMPAGE_PASSED,\n\tSOUND_RAMPAGE_FAILED,\n\tSOUND_RAMPAGE_KILL,\n\tSOUND_RAMPAGE_CAR_BLOWN,\n\tSOUND_EVIDENCE_PICKUP,\n\tSOUND_UNLOAD_GOLD,\n\tSOUND_PAGER,\n\tSOUND_PED_DEATH,\n\tSOUND_PED_DAMAGE,\n\tSOUND_PED_HIT,\n\tSOUND_PED_LAND,\n\tSOUND_PED_BULLET_HIT,\n\tSOUND_PED_BURNING,\n\tSOUND_PED_PLAYER_REACTTOCOP,\n\tSOUND_PED_ARREST_COP,\n\tSOUND_PED_MIAMIVICE_EXITING_CAR,\n\tSOUND_PED_COP_HELIPILOTPHRASE,\n\tSOUND_PED_PULLOUTWEAPON,\n\tSOUND_PED_HELI_PLAYER_FOUND = 114,\n\tSOUND_PED_VCPA_PLAYER_FOUND = 115,\n\tSOUND_PED_ON_FIRE,\n\tSOUND_PED_AIMING,\n\tSOUND_PED_HANDS_UP,\n\tSOUND_PED_HANDS_COWER,\n\tSOUND_PED_FLEE_SPRINT,\n\tSOUND_PED_CAR_JACKING,\n\tSOUND_PED_MUGGING,\n\tSOUND_PED_CAR_JACKED,\n\tSOUND_PED_ROBBED,\n\tSOUND_PED_ACCIDENTREACTION1,\n\tSOUND_PED_UNK_126,\n\tSOUND_PED_PLAYER_AFTERSEX,\n\tSOUND_PED_PLAYER_BEFORESEX,\n\tSOUND_PED_COP_UNK_129, // also used for medics\n\tSOUND_PED_COP_MANYCOPSAROUND, // also used for medics\n\tSOUND_PED_GUNAIMEDAT2,\n\tSOUND_PED_COP_ALONE, // also used for medics\n\tSOUND_PED_GUNAIMEDAT3,\n\tSOUND_PED_COP_REACTION,\n\tSOUND_PED_COP_LITTLECOPSAROUND, // also used for medics\n\tSOUND_PED_PLAYER_FARFROMCOPS, // also used for medics\n\tSOUND_PED_TAXI_WAIT,\n\tSOUND_PED_ATTACK,\n\tSOUND_PED_DEFEND,\n\tSOUND_PED_HEALING,\n\tSOUND_PED_LEAVE_VEHICLE,\n\tSOUND_PED_EVADE,\n\tSOUND_PED_FLEE_RUN,\n\tSOUND_PED_CRASH_VEHICLE,\n\tSOUND_PED_CRASH_CAR,\n\tSOUND_PED_ANNOYED_DRIVER,\n\tSOUND_PED_147,\n\tSOUND_PED_SOLICIT,\n\tSOUND_PED_149,\n\tSOUND_PED_150,\n\tSOUND_PED_EXTINGUISHING_FIRE,\n\tSOUND_PED_WAIT_DOUBLEBACK,\n\tSOUND_153,\n\tSOUND_PED_CHAT_SEXY,\n\tSOUND_PED_CHAT_EVENT,\n\tSOUND_PED_PED_COLLISION,\n\tSOUND_PED_CHAT,\n\tSOUND_PED_TAXI_CALL,\n\tSOUND_RACE_START_3,\n\tSOUND_RACE_START_2,\n\tSOUND_RACE_START_1,\n\tSOUND_RACE_START_GO,\n\tSOUND_SPLASH,\n\tSOUND_WATER_FALL,\n\tSOUND_SPLATTER,\n\tSOUND_CAR_PED_COLLISION,\n\tSOUND_CLOCK_TICK,\n\tSOUND_PART_MISSION_COMPLETE,\n\tSOUND_FRONTEND_MENU_STARTING, // same sound as SOUND_HUD\n\n\t// TODO(Miami): What are 170-175??\n\t\n\tSOUND_FRONTEND_RADIO_TURN_OFF = 176, // those 2 are same sound\n\tSOUND_FRONTEND_RADIO_TURN_ON,\n\tSOUND_FRONTEND_HURRICANE, // yes, frontend\n\tSOUND_HUD,\n\tSOUND_180,\n\tSOUND_181,\n\tSOUND_182,\n\tSOUND_LIGHTNING,\n\tSOUND_BULLETTRACE_1,\n\tSOUND_BULLETTRACE_2,\n\tSOUND_186, // makes same sound as 40\n\tSOUND_187, // makes same sound as 46\n\tSOUND_MELEE_ATTACK_START,\n\tSOUND_SKATING,\n\tSOUND_WEAPON_MINIGUN_ATTACK,\n\tSOUND_WEAPON_MINIGUN_2,\n\tSOUND_WEAPON_MINIGUN_3,\n\tSOUND_AMMUNATION_IMRAN_ARM_BOMB,\n\tSOUND_RADIO_CHANGE,\n\tSOUND_FRONTEND_HIGHLIGHT_OPTION,\n\tSOUND_FRONTEND_ENTER_OR_ADJUST,\n\tSOUND_FRONTEND_BACK,\n\tSOUND_FRONTEND_FAIL,\n\tSOUND_FRONTEND_AUDIO_TEST,\n\tSOUND_INJURED_PED_MALE_OUCH,\n\tSOUND_INJURED_PED_FEMALE,\n\tSOUND_SHIRT_WIND_FLAP,\n\tSOUND_SET_203,\n\tSOUND_TOTAL_SOUNDS = 204,\n\tSOUND_NO_SOUND = 205,\n};\n\n\nenum eScriptSounds {\n\tSCRIPT_SOUND_BANK_ALARM_LOOP = 0,\n\tSCRIPT_SOUND_PART_MISSION_COMPLETE,\n\tSCRIPT_SOUND_POLICE_CELL_DOOR_SLIDING_LOOP,\n\tSCRIPT_SOUND_POLICE_CELL_DOOR_CLUNK,\n\tSCRIPT_SOUND_GARAGE_DOOR_SLIDING_LOOP,\n\tSCRIPT_SOUND_GARAGE_DOOR_CLUNK,\n\tSCRIPT_SOUND_SNORING_LOOP,\n\tSCRIPT_SOUND_RACE_START_3,\n\tSCRIPT_SOUND_RACE_START_2,\n\tSCRIPT_SOUND_RACE_START_1,\n\tSCRIPT_SOUND_RACE_START_GO,\n\tSCRIPT_SOUND_SHOOTING_RANGE_TARGET_MOVING_LOOP,\n\tSCRIPT_SOUND_SHOOTING_RANGE_TARGET_HIT,\n\tSCRIPT_SOUND_AMMUNATION_BUY_WEAPON,\n\tSCRIPT_SOUND_AMMUNATION_BUY_WEAPON_DENIED,\n\tSCRIPT_SOUND_WMYCW_TICKET_SPEECH,\n\tSCRIPT_SOUND_IMRAN_ARM_BOMB,\n\tSCRIPT_SOUND_ANDY_SNIPER_SHOT,\n\tSCRIPT_SOUND_WILLIE_CARD_SWIPE,\n\tSCRIPT_SOUND_MALE_AMBULANCE_OUCH,\n\tSCRIPT_SOUND_FEMALE_AMBULANCE_OUCH,\n\tSCRIPT_SOUND_BUILDING_BAR_1,\n\tSCRIPT_SOUND_BUILDING_BAR_2,\n\tSCRIPT_SOUND_BUILDING_BAR_3,\n\tSCRIPT_SOUND_BUILDING_BAR_4,\n\tSCRIPT_SOUND_BUILDING_BIKER_BAR,\n\tSCRIPT_SOUND_BUILDING_CHURCH,\n\tSCRIPT_SOUND_BUILDING_CLUB,\n\tSCRIPT_SOUND_BUILDING_CUBA_1,\n\tSCRIPT_SOUND_BUILDING_CUBA_2,\n\tSCRIPT_SOUND_BUILDING_VOODOO,\n\tSCRIPT_SOUND_BUILDING_MUSIC_SHOP,\n\tSCRIPT_SOUND_BUILDING_STRIPCLUB_1,\n\tSCRIPT_SOUND_BUILDING_STRIPCLUB_2,\n\tSCRIPT_SOUND_BUILDING_SUPERSWEEP,\n\tSCRIPT_SOUND_SEAPLANE_LOW_FUEL,\n\tSCRIPT_SOUND_NEW_BUILDING_BAR_1,\n\tSCRIPT_SOUND_NEW_BUILDING_BAR_2,\n\tSCRIPT_SOUND_NEW_BUILDING_BAR_3,\n\tSCRIPT_SOUND_NEW_BUILDING_BAR_4,\n\tSCRIPT_SOUND_NEW_BUILDING_MALIBU_1,\n\tSCRIPT_SOUND_NEW_BUILDING_MALIBU_2,\n\tSCRIPT_SOUND_NEW_BUILDING_MALIBU_3,\n\tSCRIPT_SOUND_NEW_BUILDING_STRIP_1,\n\tSCRIPT_SOUND_NEW_BUILDING_STRIP_2,\n\tSCRIPT_SOUND_NEW_BUILDING_STRIP_3,\n\tSCRIPT_SOUND_NEW_BUILDING_CHURCH,\n\tSCRIPT_SOUND_NEW_BUILDING_FAN_1,\n\tSCRIPT_SOUND_NEW_BUILDING_FAN_2,\n\tSCRIPT_SOUND_NEW_BUILDING_INSECT_1,\n\tSCRIPT_SOUND_NEW_BUILDING_INSECT_2,\n\tSCRIPT_SOUND_NEW_WATERFALL,\n\tSCRIPT_SOUND_BULLET_HIT_GROUND_1,\n\tSCRIPT_SOUND_BULLET_HIT_GROUND_2,\n\tSCRIPT_SOUND_BULLET_HIT_GROUND_3,\n\tSCRIPT_SOUND_BULLET_HIT_WATER, // no sound\n\tSCRIPT_SOUND_PAYPHONE_RINGING,\n\tSCRIPT_SOUND_GLASS_BREAK_L,\n\tSCRIPT_SOUND_GLASS_BREAK_S,\n\tSCRIPT_SOUND_GLASS_CRACK,\n\tSCRIPT_SOUND_GLASS_LIGHT_BREAK,\n\tSCRIPT_SOUND_BOX_DESTROYED_1,\n\tSCRIPT_SOUND_BOX_DESTROYED_2,\n\tSCRIPT_SOUND_METAL_COLLISION,\n\tSCRIPT_SOUND_TIRE_COLLISION,\n\tSCRIPT_SOUND_HIT_BALL,\n\tSCRIPT_SOUND_GUNSHELL_DROP,\n\tSCRIPT_SOUND_GUNSHELL_DROP_SOFT,\n\tSCRIPT_SOUND_TOTAL,\n\tSCRIPT_SOUND_INVALID,\n};\n"
  },
  {
    "path": "src/buildings/Building.cpp",
    "content": "#include \"common.h\"\n\n#include \"Building.h\"\n#include \"Streaming.h\"\n#include \"Pools.h\"\n\nvoid *CBuilding::operator new(size_t sz) { return CPools::GetBuildingPool()->New();  }\nvoid CBuilding::operator delete(void *p, size_t sz) { CPools::GetBuildingPool()->Delete((CBuilding*)p); }\n\nvoid\nCBuilding::ReplaceWithNewModel(int32 id)\n{\n\tDeleteRwObject();\n\n\tif (CModelInfo::GetModelInfo(m_modelIndex)->GetNumRefs() == 0)\n\t\tCStreaming::RemoveModel(m_modelIndex);\n\tm_modelIndex = id;\n\n\tif(bIsBIGBuilding)\n\t\tif(m_level == LEVEL_GENERIC || m_level == CGame::currLevel)\n\t\t\tCStreaming::RequestModel(id, STREAMFLAGS_DONT_REMOVE);\n}\n\nbool\nIsBuildingPointerValid(CBuilding* pBuilding)\n{\n\tif (!pBuilding)\n\t\treturn false;\n\tif (pBuilding->GetIsATreadable()) {\n\t\tint index = CPools::GetTreadablePool()->GetJustIndex_NoFreeAssert((CTreadable*)pBuilding);\n#ifdef FIX_BUGS\n\t\treturn index >= 0 && index < CPools::GetTreadablePool()->GetSize();\n#else\n\t\treturn index >= 0 && index <= CPools::GetTreadablePool()->GetSize();\n#endif\n\t} else {\n\t\tint index = CPools::GetBuildingPool()->GetJustIndex_NoFreeAssert(pBuilding);\n#ifdef FIX_BUGS\n\t\treturn index >= 0 && index < CPools::GetBuildingPool()->GetSize();\n#else\n\t\treturn index >= 0 && index <= CPools::GetBuildingPool()->GetSize();\n#endif\n\t}\n}\n"
  },
  {
    "path": "src/buildings/Building.h",
    "content": "#pragma once\n\n#include \"Entity.h\"\n\nclass CBuilding : public CEntity\n{\npublic:\n\tCBuilding(void) {\n\t\tm_type = ENTITY_TYPE_BUILDING;\n\t\tbUsesCollision = true;\n\t}\n\tstatic void *operator new(size_t);\n\tstatic void operator delete(void*, size_t);\n\n\tvoid ReplaceWithNewModel(int32 id);\n\n\tvirtual bool GetIsATreadable(void) { return false; }\n};\n\nbool IsBuildingPointerValid(CBuilding*);\n"
  },
  {
    "path": "src/buildings/Solid.h",
    "content": "#pragma once\n\n#include \"Entity.h\"\n\nclass CSolid : public CEntity\n{\npublic:\n\tCSolid(void) {\n\t\tm_type = ENTITY_TYPE_BUILDING;\n\t\tbUsesCollision = true;\n\t}\n};"
  },
  {
    "path": "src/buildings/Treadable.cpp",
    "content": "#include \"common.h\"\n\n#include \"rpworld.h\"\n#include \"Treadable.h\"\n#include \"Pools.h\"\n\nvoid *CTreadable::operator new(size_t sz) { return CPools::GetTreadablePool()->New();  }\nvoid CTreadable::operator delete(void *p, size_t sz) { CPools::GetTreadablePool()->Delete((CTreadable*)p); }\n"
  },
  {
    "path": "src/buildings/Treadable.h",
    "content": "#pragma once\n\n#include \"Building.h\"\n\nclass CTreadable : public CBuilding\n{\npublic:\n\tstatic void *operator new(size_t);\n\tstatic void operator delete(void*, size_t);\n\n\tbool GetIsATreadable(void) { return true; }\n};\n"
  },
  {
    "path": "src/collision/ColBox.cpp",
    "content": "#include \"common.h\"\n#include \"ColBox.h\"\n\nvoid\nCColBox::Set(const CVector &min, const CVector &max, uint8 surf, uint8 piece)\n{\n\tthis->min = min;\n\tthis->max = max;\n\tthis->surface = surf;\n\tthis->piece = piece;\n}\n\nCColBox&\nCColBox::operator=(const CColBox& other)\n{\n\tmin = other.min;\n\tmax = other.max;\n\tsurface = other.surface;\n\tpiece = other.piece;\n\treturn *this;\n}"
  },
  {
    "path": "src/collision/ColBox.h",
    "content": "#pragma once\n\n#include \"SurfaceTable.h\"\n\nstruct CBox\n{\n\tCVector min;\n\tCVector max;\n\tCVector GetSize(void) { return max - min; }\n\tvoid Set(const CVector &min, const CVector &max) {  this->min = min; this->max = max; }\n};\n\nstruct CColBox : public CBox\n{\n\tuint8 surface;\n\tuint8 piece;\n\n\tvoid Set(const CVector &min, const CVector &max, uint8 surf, uint8 piece);\n\tusing CBox::Set;\n\n\tCColBox& operator=(const CColBox &other);\n};"
  },
  {
    "path": "src/collision/ColLine.cpp",
    "content": "#include \"common.h\"\n#include \"ColLine.h\"\n\nvoid\nCColLine::Set(const CVector &p0, const CVector &p1)\n{\n\tthis->p0 = p0;\n\tthis->p1 = p1;\n}"
  },
  {
    "path": "src/collision/ColLine.h",
    "content": "#pragma once\n\nstruct CColLine\n{\n\t// NB: this has to be compatible with two CVuVectors\n\tCVector p0;\n\tint pad0;\n\tCVector p1;\n\tint pad1;\n\n\tCColLine(void) { };\n\tCColLine(const CVector &p0, const CVector &p1) { this->p0 = p0; this->p1 = p1; };\n\tvoid Set(const CVector &p0, const CVector &p1);\n};"
  },
  {
    "path": "src/collision/ColModel.cpp",
    "content": "#include \"common.h\"\n#include \"ColModel.h\"\n#include \"Collision.h\"\n#include \"Game.h\"\n#include \"MemoryHeap.h\"\n#include \"Pools.h\"\n\nCColModel::CColModel(void)\n{\n\tnumSpheres = 0;\n\tspheres = nil;\n\tnumLines = 0;\n\tlines = nil;\n\tnumBoxes = 0;\n\tboxes = nil;\n\tnumTriangles = 0;\n\tvertices = nil;\n\ttriangles = nil;\n\ttrianglePlanes = nil;\n\tlevel = LEVEL_GENERIC;\t// generic col slot\n\townsCollisionVolumes = true;\n}\n\nCColModel::~CColModel(void)\n{\n\tRemoveCollisionVolumes();\n}\n\nvoid*\nCColModel::operator new(size_t)\n{\n\tCColModel* node = CPools::GetColModelPool()->New();\n\tassert(node);\n\treturn node;\n}\n\nvoid\nCColModel::operator delete(void *p, size_t)\n{\n\tCPools::GetColModelPool()->Delete((CColModel*)p);\n}\n\nvoid\nCColModel::RemoveCollisionVolumes(void)\n{\n\tif(ownsCollisionVolumes){\n\t\tRwFree(spheres);\n\t\tRwFree(lines);\n\t\tRwFree(boxes);\n\t\tRwFree(vertices);\n\t\tRwFree(triangles);\n\t\tCCollision::RemoveTrianglePlanes(this);\n\t}\n\tnumSpheres = 0;\n\tnumLines = 0;\n\tnumBoxes = 0;\n\tnumTriangles = 0;\n\tspheres = nil;\n\tlines = nil;\n\tboxes = nil;\n\tvertices = nil;\n\ttriangles = nil;\n}\n\nvoid\nCColModel::CalculateTrianglePlanes(void)\n{\n\tPUSH_MEMID(MEMID_COLLISION);\n\n\t// HACK: allocate space for one more element to stuff the link pointer into\n\ttrianglePlanes = (CColTrianglePlane*)RwMalloc(sizeof(CColTrianglePlane) * (numTriangles+1));\n\tREGISTER_MEMPTR(&trianglePlanes);\n\tfor(int i = 0; i < numTriangles; i++)\n\t\ttrianglePlanes[i].Set(vertices, triangles[i]);\n\n\tPOP_MEMID();\n}\n\nvoid\nCColModel::RemoveTrianglePlanes(void)\n{\n\tRwFree(trianglePlanes);\n\ttrianglePlanes = nil;\n}\n\nvoid\nCColModel::SetLinkPtr(CLink<CColModel*> *lptr)\n{\n\tassert(trianglePlanes);\n\t*(CLink<CColModel*>**)ALIGNPTR(&trianglePlanes[numTriangles]) = lptr;\n}\n\nCLink<CColModel*>*\nCColModel::GetLinkPtr(void)\n{\n\tassert(trianglePlanes);\n\treturn *(CLink<CColModel*>**)ALIGNPTR(&trianglePlanes[numTriangles]);\n}\n\nvoid\nCColModel::GetTrianglePoint(CVector &v, int i) const\n{\n\tv = vertices[i].Get();\n}\n\nCColModel&\nCColModel::operator=(const CColModel &other)\n{\n\tint i;\n\tint numVerts;\n\n\tboundingSphere = other.boundingSphere;\n\tboundingBox = other.boundingBox;\n\n\t// copy spheres\n\tif(other.numSpheres){\n\t\tif(numSpheres != other.numSpheres){\n\t\t\tnumSpheres = other.numSpheres;\n\t\t\tif(spheres)\n\t\t\t\tRwFree(spheres);\n\t\t\tspheres = (CColSphere*)RwMalloc(numSpheres*sizeof(CColSphere));\n\t\t}\n\t\tfor(i = 0; i < numSpheres; i++)\n\t\t\tspheres[i] = other.spheres[i];\n\t}else{\n\t\tnumSpheres = 0;\n\t\tif(spheres)\n\t\t\tRwFree(spheres);\n\t\tspheres = nil;\n\t}\n\n\t// copy lines\n\tif(other.numLines){\n\t\tif(numLines != other.numLines){\n\t\t\tnumLines = other.numLines;\n\t\t\tif(lines)\n\t\t\t\tRwFree(lines);\n\t\t\tlines = (CColLine*)RwMalloc(numLines*sizeof(CColLine));\n\t\t}\n\t\tfor(i = 0; i < numLines; i++)\n\t\t\tlines[i] = other.lines[i];\n\t}else{\n\t\tnumLines = 0;\n\t\tif(lines)\n\t\t\tRwFree(lines);\n\t\tlines = nil;\n\t}\n\n\t// copy boxes\n\tif(other.numBoxes){\n\t\tif(numBoxes != other.numBoxes){\n\t\t\tnumBoxes = other.numBoxes;\n\t\t\tif(boxes)\n\t\t\t\tRwFree(boxes);\n\t\t\tboxes = (CColBox*)RwMalloc(numBoxes*sizeof(CColBox));\n\t\t}\n\t\tfor(i = 0; i < numBoxes; i++)\n\t\t\tboxes[i] = other.boxes[i];\n\t}else{\n\t\tnumBoxes = 0;\n\t\tif(boxes)\n\t\t\tRwFree(boxes);\n\t\tboxes = nil;\n\t}\n\n\t// copy mesh\n\tif(other.numTriangles){\n\t\t// copy vertices\n\t\tnumVerts = 0;\n\t\tfor(i = 0; i < other.numTriangles; i++){\n\t\t\tif(other.triangles[i].a > numVerts)\n\t\t\t\tnumVerts = other.triangles[i].a;\n\t\t\tif(other.triangles[i].b > numVerts)\n\t\t\t\tnumVerts = other.triangles[i].b;\n\t\t\tif(other.triangles[i].c > numVerts)\n\t\t\t\tnumVerts = other.triangles[i].c;\n\t\t}\n\t\tnumVerts++;\n\t\tif(vertices)\n\t\t\tRwFree(vertices);\n\t\tif(numVerts){\n\t\t\tvertices = (CompressedVector*)RwMalloc(numVerts*sizeof(CompressedVector));\n\t\t\tfor(i = 0; i < numVerts; i++)\n\t\t\t\tvertices[i] = other.vertices[i];\n\t\t}\n\n\t\t// copy triangles\n\t\tif(numTriangles != other.numTriangles){\n\t\t\tnumTriangles = other.numTriangles;\n\t\t\tif(triangles)\n\t\t\t\tRwFree(triangles);\n\t\t\ttriangles = (CColTriangle*)RwMalloc(numTriangles*sizeof(CColTriangle));\n\t\t}\n\t\tfor(i = 0; i < numTriangles; i++)\n\t\t\ttriangles[i] = other.triangles[i];\n\t}else{\n\t\tnumTriangles = 0;\n\t\tif(triangles)\n\t\t\tRwFree(triangles);\n\t\ttriangles = nil;\n\t\tif(vertices)\n\t\t\tRwFree(vertices);\n\t\tvertices = nil;\n\t}\n\treturn *this;\n}\n"
  },
  {
    "path": "src/collision/ColModel.h",
    "content": "#pragma once\n\n#include \"templates.h\"\n#include \"ColBox.h\"\n#include \"ColSphere.h\"\n#include \"ColLine.h\"\n#include \"ColPoint.h\"\n#include \"ColTriangle.h\"\n\nstruct CColModel\n{\n\tCSphere boundingSphere;\n\tCBox boundingBox;\n\tint16 numSpheres;\n\tint16 numBoxes;\n\tint16 numTriangles;\n\tint8 numLines;\n\tuint8 level;\t// colstore slot but probably still named level\n\tbool ownsCollisionVolumes;\n\tCColSphere *spheres;\n\tCColLine *lines;\n\tCColBox *boxes;\n\tCompressedVector *vertices;\n\tCColTriangle *triangles;\n\tCColTrianglePlane *trianglePlanes;\n\n\tCColModel(void);\n\t~CColModel(void);\n\tvoid RemoveCollisionVolumes(void);\n\tvoid CalculateTrianglePlanes(void);\n\tvoid RemoveTrianglePlanes(void);\n\tCLink<CColModel*> *GetLinkPtr(void);\n\tvoid SetLinkPtr(CLink<CColModel*>*);\n\tvoid GetTrianglePoint(CVector &v, int i) const;\n\n\tvoid *operator new(size_t);\n\tvoid operator delete(void *p, size_t);\n\tCColModel& operator=(const CColModel& other);\n};"
  },
  {
    "path": "src/collision/ColPoint.cpp",
    "content": "#include \"common.h\"\n#include \"ColPoint.h\"\n\nCColPoint&\nCColPoint::operator=(const CColPoint &other)\n{\n\tpoint = other.point;\n\tnormal = other.normal;\n\tsurfaceA = other.surfaceA;\n\tpieceA = other.pieceA;\n\tsurfaceB = other.surfaceB;\n\tpieceB = other.pieceB;\n\n\t// no depth?\n\treturn *this;\n}\n"
  },
  {
    "path": "src/collision/ColPoint.h",
    "content": "#pragma once\n\nstruct CColPoint\n{\n\tCVector point;\n\tint pad1;\n\t// the surface normal on the surface of point\n\tCVector normal;\n\tint pad2;\n\tuint8 surfaceA;\n\tuint8 pieceA;\n\tuint8 surfaceB;\n\tuint8 pieceB;\n\tfloat depth;\n\n\tconst CVector &GetNormal() { return normal; }\n\tfloat GetDepth() { return depth; }\n\tvoid Set(float depth, uint8 surfA, uint8 pieceA, uint8 surfB, uint8 pieceB) {\n\t\tthis->depth = depth;\n\t\tthis->surfaceA = surfA;\n\t\tthis->pieceA = pieceA;\n\t\tthis->surfaceB = surfB;\n\t\tthis->pieceB = pieceB;\n\t}\n\tvoid Set(uint8 surfA, uint8 pieceA, uint8 surfB, uint8 pieceB) {\n\t\tthis->surfaceA = surfA;\n\t\tthis->pieceA = pieceA;\n\t\tthis->surfaceB = surfB;\n\t\tthis->pieceB = pieceB;\n\t}\n\n\tCColPoint &operator=(const CColPoint &other);\n};\n\n"
  },
  {
    "path": "src/collision/ColSphere.cpp",
    "content": "#include \"common.h\"\n#include \"ColSphere.h\"\n#include \"General.h\"\n\nvoid\nCColSphere::Set(float radius, const CVector &center, uint8 surf, uint8 piece)\n{\n\tthis->radius = radius;\n\tthis->center = center;\n\tthis->surface = surf;\n\tthis->piece = piece;\n}\n\nbool\nCColSphere::IntersectRay(CVector const& from, CVector const& dir, CVector &entry, CVector &exit)\n{\n\tCVector distToCenter = from - center;\n\tfloat distToTouchSqr = distToCenter.MagnitudeSqr() - sq(radius);\n\tfloat root1, root2;\n\n\tif (!CGeneral::SolveQuadratic(1.0f, DotProduct(distToCenter, dir) * 2.f, distToTouchSqr, root1, root2))\n\t\treturn false;\n\n\tentry = from + dir * root1;\n\texit = from + dir * root2;\n\treturn true;\n}"
  },
  {
    "path": "src/collision/ColSphere.h",
    "content": "#pragma once\n\n#include \"SurfaceTable.h\"\n\nstruct CSphere\n{\n\t// NB: this has to be compatible with a CVuVector\n\tCVector center;\n\tfloat radius;\n\tvoid Set(float radius, const CVector &center) { this->center = center; this->radius = radius; }\n};\n\nstruct CColSphere : public CSphere\n{\n\tuint8 surface;\n\tuint8 piece;\n\n\tvoid Set(float radius, const CVector &center, uint8 surf, uint8 piece);\n\tbool IntersectRay(CVector const &from, CVector const &dir, CVector &entry, CVector &exit);\n\tusing CSphere::Set;\n};"
  },
  {
    "path": "src/collision/ColStore.cpp",
    "content": "#include \"common.h\"\n\n#include \"templates.h\"\n#include \"General.h\"\n#include \"ModelInfo.h\"\n#include \"Streaming.h\"\n#include \"FileLoader.h\"\n#include \"Script.h\"\n#include \"Timer.h\"\n#include \"Camera.h\"\n#include \"Frontend.h\"\n#include \"Physical.h\"\n#include \"ColStore.h\"\n#include \"VarConsole.h\"\n#include \"Pools.h\"\n\nCPool<ColDef,ColDef> *CColStore::ms_pColPool;\n#ifndef MASTER\nbool bDispColInMem;\n#endif\n\nvoid\nCColStore::Initialise(void)\n{\n\tif(ms_pColPool == nil)\n\t\tms_pColPool = new CPool<ColDef,ColDef>(COLSTORESIZE, \"CollisionFiles\");\n\tAddColSlot(\"generic\");\t// slot 0. not streamed\n#ifndef MASTER\n\tVarConsole.Add(\"Display collision in memory\", &bDispColInMem, true);\n#endif\n}\n\nvoid\nCColStore::Shutdown(void)\n{\n\tint i;\n\tfor(i = 0; i < COLSTORESIZE; i++)\n\t\tRemoveColSlot(i);\n\tif(ms_pColPool)\n\t\tdelete ms_pColPool;\n\tms_pColPool = nil;\n}\n\nint\nCColStore::AddColSlot(const char *name)\n{\n\tColDef *def = ms_pColPool->New();\n\tassert(def);\n\tdef->isLoaded = false;\n\tdef->unused = 0;\n\tdef->bounds.left = 1000000.0f;\n\tdef->bounds.top = 1000000.0f;\n\tdef->bounds.right = -1000000.0f;\n\tdef->bounds.bottom = -1000000.0f;\n\tdef->minIndex = INT16_MAX;\n\tdef->maxIndex = INT16_MIN;\n\tstrcpy(def->name, name);\n\treturn ms_pColPool->GetJustIndex(def);\n}\n\nvoid\nCColStore::RemoveColSlot(int slot)\n{\n\tif(GetSlot(slot)){\n\t\tif(GetSlot(slot)->isLoaded)\n\t\t\tRemoveCol(slot);\n\t\tms_pColPool->Delete(GetSlot(slot));\n\t}\n}\n\nint\nCColStore::FindColSlot(const char *name)\n{\n\tColDef *def;\n\tint size = ms_pColPool->GetSize();\n\tfor(int i = 0; i < size; i++){\n\t\tdef = GetSlot(i);\n\t\tif(def && !CGeneral::faststricmp(def->name, name))\n\t\t\treturn i;\n\t}\n\treturn -1;\n}\n\nchar*\nCColStore::GetColName(int32 slot)\n{\n\treturn GetSlot(slot)->name;\n}\n\nCRect&\nCColStore::GetBoundingBox(int32 slot)\n{\n\treturn GetSlot(slot)->bounds;\n}\n\nvoid\nCColStore::IncludeModelIndex(int32 slot, int32 modelIndex)\n{\n\tColDef *def = GetSlot(slot);\n\tif(modelIndex < def->minIndex)\n\t\tdef->minIndex = modelIndex;\n\tif(modelIndex > def->maxIndex)\n\t\tdef->maxIndex = modelIndex;\n}\n\nbool\nCColStore::LoadCol(int32 slot, uint8 *buffer, int32 bufsize)\n{\n\tbool success;\n\tColDef *def = GetSlot(slot);\n\tif(def->minIndex > def->maxIndex)\n\t\tsuccess = CFileLoader::LoadCollisionFileFirstTime(buffer, bufsize, slot);\n\telse\n\t\tsuccess = CFileLoader::LoadCollisionFile(buffer, bufsize, slot);\n\tif(success)\n\t\tdef->isLoaded = true;\n\telse\n\t\tdebug(\"Failed to load Collision\\n\");\n\treturn success;\n}\n\nvoid\nCColStore::RemoveCol(int32 slot)\n{\n\tint id;\n\tGetSlot(slot)->isLoaded = false;\n\tfor(id = 0; id < MODELINFOSIZE; id++){\n\t\tCBaseModelInfo *mi = CModelInfo::GetModelInfo(id);\n\t\tif(mi){\n\t\t\tCColModel *col = mi->GetColModel();\n\t\t\tif(col && col->level == slot)\n\t\t\t\tcol->RemoveCollisionVolumes();\n\t\t}\n\t}\n}\n\nvoid\nCColStore::LoadAllCollision(void)\n{\n\tint i;\n\tfor(i = 1; i < COLSTORESIZE; i++)\n\t\tif(GetSlot(i))\n\t\t\tCStreaming::RequestCol(i, 0);\n\n\tCStreaming::LoadAllRequestedModels(false);\n}\n\nvoid\nCColStore::RemoveAllCollision(void)\n{\n\tint i;\n\tfor(i = 1; i < COLSTORESIZE; i++)\n\t\tif(GetSlot(i))\n\t\t\tif(CStreaming::CanRemoveCol(i))\n\t\t\t\tCStreaming::RemoveCol(i);\n}\n\nstatic bool bLoadAtSecondPosition;\nstatic CVector2D secondPosition;\n\nvoid\nCColStore::AddCollisionNeededAtPosn(const CVector2D &pos)\n{\n\tbLoadAtSecondPosition = true;\n\tsecondPosition = pos;\n}\n\nvoid\nCColStore::LoadCollision(const CVector2D &pos)\n{\n\tint i;\n\n\tif(CStreaming::ms_disableStreaming)\n\t\treturn;\n\n\tfor(i = 1; i < COLSTORESIZE; i++){\n\t\tif(GetSlot(i) == nil)\n\t\t\tcontinue;\n\n\t\tbool wantThisOne = false;\n\n\t\tif(GetBoundingBox(i).IsPointInside(pos) ||\n\t\t   bLoadAtSecondPosition && GetBoundingBox(i).IsPointInside(secondPosition, -119.0f) ||\n\t\t   strcmp(GetColName(i), \"yacht\") == 0){\n\t\t\twantThisOne = true;\n\t\t}else{\n\t\t\tfor (int j = 0; j < MAX_CLEANUP; j++) {\n\t\t\t\tCPhysical* pEntity = nil;\n\t\t\t\tcleanup_entity_struct* pCleanup = &CTheScripts::MissionCleanUp.m_sEntities[i];\n\t\t\t\tif (pCleanup->type == CLEANUP_CAR) {\n\t\t\t\t\tpEntity = CPools::GetVehiclePool()->GetAt(pCleanup->id);\n\t\t\t\t\tif (!pEntity || pEntity->GetStatus() == STATUS_WRECKED)\n\t\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\telse if (pCleanup->type == CLEANUP_CHAR) {\n\t\t\t\t\tpEntity = CPools::GetPedPool()->GetAt(pCleanup->id);\n\t\t\t\t\tif (!pEntity || ((CPed*)pEntity)->DyingOrDead())\n\t\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (pEntity && !pEntity->bDontLoadCollision && !pEntity->bIsFrozen) {\n\t\t\t\t\tif (GetBoundingBox(i).IsPointInside(pEntity->GetPosition(), -80.0f))\n\t\t\t\t\t\twantThisOne = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif(wantThisOne)\n\t\t\tCStreaming::RequestCol(i, STREAMFLAGS_PRIORITY);\n\t\telse\n\t\t\tCStreaming::RemoveCol(i);\n\t}\n\tbLoadAtSecondPosition = false;\n}\n\nvoid\nCColStore::RequestCollision(const CVector2D &pos)\n{\n\tint i;\n\n\tfor(i = 1; i < COLSTORESIZE; i++)\n\t\tif(GetSlot(i) && GetBoundingBox(i).IsPointInside(pos, -115.0f))\n\t\t\tCStreaming::RequestCol(i, STREAMFLAGS_PRIORITY);\n}\n\nvoid\nCColStore::EnsureCollisionIsInMemory(const CVector2D &pos)\n{\n\tint i;\n\n\tif(CStreaming::ms_disableStreaming)\n\t\treturn;\n\n\tfor(i = 1; i < COLSTORESIZE; i++)\n\t\tif(GetSlot(i) && GetBoundingBox(i).IsPointInside(pos, -110.0f) &&\n\t\t   !CStreaming::HasColLoaded(i)){\n\t\t\tCStreaming::RequestCol(i, 0);\n\t\t\tif(TheCamera.GetScreenFadeStatus() == FADE_0)\n\t\t\t\tFrontEndMenuManager.MessageScreen(\"LOADCOL\", false);\n\t\t\tCTimer::Suspend();\n\t\t\tCStreaming::LoadAllRequestedModels(false);\n\t\t\tCTimer::Resume();\n\t\t}\n}\n\nbool\nCColStore::HasCollisionLoaded(const CVector2D &pos)\n{\n\tint i;\n\n\tfor(i = 1; i < COLSTORESIZE; i++)\n\t\tif(GetSlot(i) && GetBoundingBox(i).IsPointInside(pos, -115.0f) &&\n\t\t   !GetSlot(i)->isLoaded)\n\t\t\treturn false;\n\treturn true;\n}\n"
  },
  {
    "path": "src/collision/ColStore.h",
    "content": "#pragma once\n\n#include \"templates.h\"\n\nstruct ColDef {\t// made up name\n\tint32 unused;\n\tbool isLoaded;\n\tCRect bounds;\n\tchar name[20];\n\tint16 minIndex;\n\tint16 maxIndex;\n};\n\nclass CColStore\n{\n\tstatic CPool<ColDef,ColDef> *ms_pColPool;\n\npublic:\n\tstatic void Initialise(void);\n\tstatic void Shutdown(void);\n\tstatic int AddColSlot(const char *name);\n\tstatic void RemoveColSlot(int32 slot);\n\tstatic int FindColSlot(const char *name);\n\tstatic char *GetColName(int32 slot);\n\tstatic CRect &GetBoundingBox(int32 slot);\n\tstatic void IncludeModelIndex(int32 slot, int32 modelIndex);\n\tstatic bool LoadCol(int32 storeID, uint8 *buffer, int32 bufsize);\n\tstatic void RemoveCol(int32 slot);\n\tstatic void AddCollisionNeededAtPosn(const CVector2D &pos);\n\tstatic void LoadAllCollision(void);\n\tstatic void RemoveAllCollision(void);\n\tstatic void LoadCollision(const CVector2D &pos);\n\tstatic void RequestCollision(const CVector2D &pos);\n\tstatic void EnsureCollisionIsInMemory(const CVector2D &pos);\n\tstatic bool HasCollisionLoaded(const CVector2D &pos);\n\n\tstatic ColDef *GetSlot(int slot) {\n\t\tassert(slot >= 0);\n\t\tassert(ms_pColPool);\n\t\tassert(slot < ms_pColPool->GetSize());\n\t\treturn ms_pColPool->GetSlot(slot);\n\t}\n};\n"
  },
  {
    "path": "src/collision/ColTriangle.cpp",
    "content": "#include \"common.h\"\n#include \"ColTriangle.h\"\n\n#ifdef VU_COLLISION\nvoid\nCColTrianglePlane::Set(const CVector &va, const CVector &vb, const CVector &vc)\n{\n\tCVector norm = CrossProduct(vc-va, vb-va);\n\tnorm.Normalise();\n\tfloat d = DotProduct(norm, va);\n\tnormal.x = norm.x*4096.0f;\n\tnormal.y = norm.y*4096.0f;\n\tnormal.z = norm.z*4096.0f;\n\tdist = d*128.0f;\n}\n#else\nvoid\nCColTrianglePlane::Set(const CVector &va, const CVector &vb, const CVector &vc)\n{\n\tnormal = CrossProduct(vc-va, vb-va);\n\tnormal.Normalise();\n\tdist = DotProduct(normal, va);\n\tCVector an(Abs(normal.x), Abs(normal.y), Abs(normal.z));\n\t// find out largest component and its direction\n\tif(an.x > an.y && an.x > an.z)\n\t\tdir = normal.x < 0.0f ? DIR_X_NEG : DIR_X_POS;\n\telse if(an.y > an.z)\n\t\tdir = normal.y < 0.0f ? DIR_Y_NEG : DIR_Y_POS;\n\telse\n\t\tdir = normal.z < 0.0f ? DIR_Z_NEG : DIR_Z_POS;\n}\n#endif"
  },
  {
    "path": "src/collision/ColTriangle.h",
    "content": "#pragma once\n\n#include \"CompressedVector.h\"\n\nenum Direction {\n\tDIR_X_POS,\n\tDIR_X_NEG,\n\tDIR_Y_POS,\n\tDIR_Y_NEG,\n\tDIR_Z_POS,\n\tDIR_Z_NEG,\n};\n\nstruct CColTriangle\n{\n\tuint16 a;\n\tuint16 b;\n\tuint16 c;\n\tuint8 surface;\n\n\tvoid Set(int a, int b, int c, uint8 surf)\n\t{\n\t\tthis->a = a;\n\t\tthis->b = b;\n\t\tthis->c = c;\n\t\tthis->surface = surf;\n\t}\n};\n\nstruct CColTrianglePlane\n{\n#ifdef VU_COLLISION\n\tCompressedVector normal;\n\tint16 dist;\n\n\tvoid Set(const CVector &va, const CVector &vb, const CVector &vc);\n\tvoid Set(const CompressedVector *v, CColTriangle &tri) { Set(v[tri.a].Get(), v[tri.b].Get(), v[tri.c].Get()); }\n\tvoid GetNormal(CVector &n) const { n.x = normal.x/4096.0f; n.y = normal.y/4096.0f; n.z = normal.z/4096.0f; }\n\tfloat CalcPoint(const CVector &v) const { CVector n; GetNormal(n); return DotProduct(n, v) - dist/128.0f; };\n#ifdef GTA_PS2\n\tvoid Unpack(uint128 &qword) const {\n\t\t__asm__ volatile (\n\t\t\t\"lh      $8, 0(%1)\\n\"\n\t\t\t\"lh      $9, 2(%1)\\n\"\n\t\t\t\"lh      $10, 4(%1)\\n\"\n\t\t\t\"lh      $11, 6(%1)\\n\"\n\t\t\t\"pextlw  $10, $8\\n\"\n\t\t\t\"pextlw  $11, $9\\n\"\n\t\t\t\"pextlw  $2, $11, $10\\n\"\n\t\t\t\"sq      $2, %0\\n\"\n\t\t\t: \"=m\" (qword)\n\t\t\t: \"r\" (this)\n\t\t\t: \"$8\", \"$9\", \"$10\", \"$11\", \"$2\"\n\t\t);\n\t}\n#else\n\tvoid Unpack(int32 *qword) const {\n\t\tqword[0] = normal.x;\n\t\tqword[1] = normal.y;\n\t\tqword[2] = normal.z;\n\t\tqword[3] = dist;\n\t}\n#endif\n#else\n\tCVector normal;\n\tfloat dist;\n\tuint8 dir;\n\n\tvoid Set(const CVector &va, const CVector &vb, const CVector &vc);\n\tvoid Set(const CompressedVector *v, CColTriangle &tri) { Set(v[tri.a].Get(), v[tri.b].Get(), v[tri.c].Get()); }\n\tvoid GetNormal(CVector &n) const { n = normal; }\n\tfloat GetNormalX() const { return normal.x; }\n\tfloat GetNormalY() const { return normal.y; }\n\tfloat GetNormalZ() const { return normal.z; }\n\tfloat CalcPoint(const CVector &v) const { return DotProduct(normal, v) - dist; };\n#endif\n};"
  },
  {
    "path": "src/collision/Collision.cpp",
    "content": "#include \"common.h\"\n\n#include \"VuVector.h\"\n#include \"main.h\"\n#include \"Lists.h\"\n#include \"Game.h\"\n#include \"Zones.h\"\n#include \"General.h\"\n#include \"ZoneCull.h\"\n#include \"World.h\"\n#include \"Entity.h\"\n#include \"Train.h\"\n#include \"Streaming.h\"\n#include \"Pad.h\"\n#include \"DMAudio.h\"\n#include \"Population.h\"\n#include \"FileLoader.h\"\n#include \"Replay.h\"\n#include \"CutsceneMgr.h\"\n#include \"RenderBuffer.h\"\n#include \"SurfaceTable.h\"\n#include \"Lines.h\"\n#include \"Collision.h\"\n#include \"Camera.h\"\n#include \"ColStore.h\"\n\n#ifdef VU_COLLISION\n#include \"VuCollision.h\"\n\ninline int\nGetVUresult(void)\n{\n#ifdef GTA_PS2\n\tint ret;\n\t__asm__ volatile (\n\t\t\"cfc2.i\t%0,vi01\\n\"\t// .i important! wait for VU0 to finish\n\t\t: \"=r\" (ret)\n\t);\n\treturn ret;\n#else\n\treturn vi01;\n#endif\n}\n\ninline int\nGetVUresult(CVuVector &point, CVuVector &normal, float &dist)\n{\n#ifdef GTA_PS2\n\tint ret;\n\t__asm__ volatile (\n\t\t\"cfc2.i\t%0,vi01\\n\"\t// .i important! wait for VU0 to finish\n\t\t\"sqc2\tvf01,(%1)\\n\"\n\t\t\"sqc2\tvf02,(%2)\\n\"\n\t\t\"qmfc2\t$12,vf03\\n\"\n\t\t\"sw\t$12,(%3)\\n\"\n\t\t: \"=r\" (ret)\n\t\t: \"r\" (&point), \"r\" (&normal), \"r\" (&dist)\n\t\t: \"$12\"\n\t);\n\treturn ret;\n#else\n\tpoint = vf01;\n\tnormal = vf02;\n\tdist = vf03.x;\n\treturn vi01;\n#endif\n}\n\n#endif\n\neLevelName CCollision::ms_collisionInMemory;\nCLinkList<CColModel*> CCollision::ms_colModelCache;\n\nvoid\nCCollision::Init(void)\n{\n\tms_colModelCache.Init(NUMCOLCACHELINKS);\n\tms_collisionInMemory = LEVEL_GENERIC;\n\tCColStore::Initialise();\n}\n\nvoid\nCCollision::Shutdown(void)\n{\n\tms_colModelCache.Shutdown();\n\tCColStore::Shutdown();\n}\n\nvoid\nCCollision::Update(void)\n{\n}\n\n// unused\neLevelName\nGetCollisionInSectorList(CPtrList &list)\n{\n\tCPtrNode *node;\n\tCEntity *e;\n\tint level;\n\n\tfor(node = list.first; node; node = node->next){\n\t\te = (CEntity*)node->item;\n\t\tlevel = CModelInfo::GetModelInfo(e->GetModelIndex())->GetColModel()->level;\n\t\tif(level != LEVEL_GENERIC)\n\t\t\treturn (eLevelName)level;\n\t}\n\treturn LEVEL_GENERIC;\n}\n\n// unused\n// Get a level this sector is in based on collision models\neLevelName\nGetCollisionInSector(CSector &sect)\n{\n\tint level;\n\n\tlevel = GetCollisionInSectorList(sect.m_lists[ENTITYLIST_BUILDINGS]);\n\tif(level == LEVEL_GENERIC)\n\t\tlevel = GetCollisionInSectorList(sect.m_lists[ENTITYLIST_BUILDINGS_OVERLAP]);\n\tif(level == LEVEL_GENERIC)\n\t\tlevel = GetCollisionInSectorList(sect.m_lists[ENTITYLIST_OBJECTS]);\n\tif(level == LEVEL_GENERIC)\n\t\tlevel = GetCollisionInSectorList(sect.m_lists[ENTITYLIST_OBJECTS_OVERLAP]);\n\tif(level == LEVEL_GENERIC)\n\t\tlevel = GetCollisionInSectorList(sect.m_lists[ENTITYLIST_DUMMIES]);\n\tif(level == LEVEL_GENERIC)\n\t\tlevel = GetCollisionInSectorList(sect.m_lists[ENTITYLIST_DUMMIES_OVERLAP]);\n\treturn (eLevelName)level;\n}\n\nvoid\nCCollision::LoadCollisionWhenINeedIt(bool forceChange)\n{\n}\n\nvoid\nCCollision::SortOutCollisionAfterLoad(void)\n{\n\tCColStore::LoadCollision(TheCamera.GetPosition());\n\tCStreaming::LoadAllRequestedModels(false);\n}\n\nvoid\nCCollision::LoadCollisionScreen(eLevelName level)\n{\n\tstatic Const char *levelNames[4] = {\n\t\t\"\",\n\t\t\"IND_ZON\",\n\t\t\"COM_ZON\",\n\t\t\"SUB_ZON\"\n\t};\n\n\t// Why twice?\n\tLoadingIslandScreen(levelNames[level]);\n\tLoadingIslandScreen(levelNames[level]);\n}\n\n//\n// Test\n//\n\n\nbool\nCCollision::TestSphereSphere(const CSphere &s1, const CSphere &s2)\n{\n\tfloat d = s1.radius + s2.radius;\n\treturn (s1.center - s2.center).MagnitudeSqr() < d*d;\n}\n\nbool\nCCollision::TestSphereBox(const CSphere &sph, const CBox &box)\n{\n\tif(sph.center.x + sph.radius < box.min.x) return false;\n\tif(sph.center.x - sph.radius > box.max.x) return false;\n\tif(sph.center.y + sph.radius < box.min.y) return false;\n\tif(sph.center.y - sph.radius > box.max.y) return false;\n\tif(sph.center.z + sph.radius < box.min.z) return false;\n\tif(sph.center.z - sph.radius > box.max.z) return false;\n\treturn true;\n}\n\nbool\nCCollision::TestLineBox(const CColLine &line, const CBox &box)\n{\n\tfloat t, x, y, z;\n\t// If either line point is in the box, we have a collision\n\tif(line.p0.x > box.min.x && line.p0.x < box.max.x &&\n\t   line.p0.y > box.min.y && line.p0.y < box.max.y &&\n\t   line.p0.z > box.min.z && line.p0.z < box.max.z)\n\t\treturn true;\n\tif(line.p1.x > box.min.x && line.p1.x < box.max.x &&\n\t   line.p1.y > box.min.y && line.p1.y < box.max.y &&\n\t   line.p1.z > box.min.z && line.p1.z < box.max.z)\n\t\treturn true;\n\n\t// check if points are on opposite sides of min x plane\n\tif((box.min.x - line.p1.x) * (box.min.x - line.p0.x) < 0.0f){\n\t\t// parameter along line where we intersect\n\t\tt = (box.min.x - line.p0.x) / (line.p1.x - line.p0.x);\n\t\t// y of intersection\n\t\ty = line.p0.y + (line.p1.y - line.p0.y)*t;\n\t\tif(y > box.min.y && y < box.max.y){\n\t\t\t// z of intersection\n\t\t\tz = line.p0.z + (line.p1.z - line.p0.z)*t;\n\t\t\tif(z > box.min.z && z < box.max.z)\n\t\t\t\treturn true;\n\t\t}\n\t}\n\n\t// same test with max x plane\n\tif((line.p1.x - box.max.x) * (line.p0.x - box.max.x) < 0.0f){\n\t\tt = (line.p0.x - box.max.x) / (line.p0.x - line.p1.x);\n\t\ty = line.p0.y + (line.p1.y - line.p0.y)*t;\n\t\tif(y > box.min.y && y < box.max.y){\n\t\t\tz = line.p0.z + (line.p1.z - line.p0.z)*t;\n\t\t\tif(z > box.min.z && z < box.max.z)\n\t\t\t\treturn true;\n\t\t}\n\t}\n\n\t// min y plne\n\tif((box.min.y - line.p0.y) * (box.min.y - line.p1.y) < 0.0f){\n\t\tt = (box.min.y - line.p0.y) / (line.p1.y - line.p0.y);\n\t\tx = line.p0.x + (line.p1.x - line.p0.x)*t;\n\t\tif(x > box.min.x && x < box.max.x){\n\t\t\tz = line.p0.z + (line.p1.z - line.p0.z)*t;\n\t\t\tif(z > box.min.z && z < box.max.z)\n\t\t\t\treturn true;\n\t\t}\n\t}\n\n\t// max y plane\n\tif((line.p0.y - box.max.y) * (line.p1.y - box.max.y) < 0.0f){\n\t\tt = (line.p0.y - box.max.y) / (line.p0.y - line.p1.y);\n\t\tx = line.p0.x + (line.p1.x - line.p0.x)*t;\n\t\tif(x > box.min.x && x < box.max.x){\n\t\t\tz = line.p0.z + (line.p1.z - line.p0.z)*t;\n\t\t\tif(z > box.min.z && z < box.max.z)\n\t\t\t\treturn true;\n\t\t}\n\t}\n\n\t// min z plne\n\tif((box.min.z - line.p0.z) * (box.min.z - line.p1.z) < 0.0f){\n\t\tt = (box.min.z - line.p0.z) / (line.p1.z - line.p0.z);\n\t\tx = line.p0.x + (line.p1.x - line.p0.x)*t;\n\t\tif(x > box.min.x && x < box.max.x){\n\t\t\ty = line.p0.y + (line.p1.y - line.p0.y)*t;\n\t\t\tif(y > box.min.y && y < box.max.y)\n\t\t\t\treturn true;\n\t\t}\n\t}\n\n\t// max z plane\n\tif((line.p0.z - box.max.z) * (line.p1.z - box.max.z) < 0.0f){\n\t\tt = (line.p0.z - box.max.z) / (line.p0.z - line.p1.z);\n\t\tx = line.p0.x + (line.p1.x - line.p0.x)*t;\n\t\tif(x > box.min.x && x < box.max.x){\n\t\t\ty = line.p0.y + (line.p1.y - line.p0.y)*t;\n\t\t\tif(y > box.min.y && y < box.max.y)\n\t\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n\nbool\nCCollision::TestVerticalLineBox(const CColLine &line, const CBox &box)\n{\n\tif(line.p0.x <= box.min.x) return false;\n\tif(line.p0.y <= box.min.y) return false;\n\tif(line.p0.x >= box.max.x) return false;\n\tif(line.p0.y >= box.max.y) return false;\n\tif(line.p0.z < line.p1.z){\n\t\tif(line.p0.z > box.max.z) return false;\n\t\tif(line.p1.z < box.min.z) return false;\n\t}else{\n\t\tif(line.p1.z > box.max.z) return false;\n\t\tif(line.p0.z < box.min.z) return false;\n\t}\n\treturn true;\n}\n\nbool\nCCollision::TestLineTriangle(const CColLine &line, const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane)\n{\n#ifdef VU_COLLISION\n\t// not used in favour of optimized loops\n\tVuTriangle vutri;\n\tverts[tri.a].Unpack(vutri.v0);\n\tverts[tri.b].Unpack(vutri.v1);\n\tverts[tri.c].Unpack(vutri.v2);\n\tplane.Unpack(vutri.plane);\n\n\tLineToTriangleCollisionCompressed(*(CVuVector*)&line.p0, *(CVuVector*)&line.p1, vutri);\n\n\tif(GetVUresult())\n\t\treturn true;\n\treturn false;\n#else\n\tfloat t;\n\tCVector normal;\n\tplane.GetNormal(normal);\n\n\t// if points are on the same side, no collision\n\tif(plane.CalcPoint(line.p0) * plane.CalcPoint(line.p1) > 0.0f)\n\t\treturn false;\n\n\tfloat p0dist = DotProduct(line.p1 - line.p0, normal);\n\n#ifdef FIX_BUGS\n\t// line lines in the plane, assume no collision\n\tif (p0dist == 0.0f)\n\t\treturn false;\n#endif\n\n\t// intersection parameter on line\n\tt = -plane.CalcPoint(line.p0) / p0dist;\n\t// find point of intersection\n\tCVector p = line.p0 + (line.p1-line.p0)*t;\n\n\tconst CVector &va = verts[tri.a].Get();\n\tconst CVector &vb = verts[tri.b].Get();\n\tconst CVector &vc = verts[tri.c].Get();\n\tCVector2D vec1, vec2, vec3, vect;\n\n\t// We do the test in 2D. With the plane direction we\n\t// can figure out how to project the vectors.\n\t// normal = (c-a) x (b-a)\n\tswitch(plane.dir){\n\tcase DIR_X_POS:\n\t\tvec1.x = va.y; vec1.y = va.z;\n\t\tvec2.x = vc.y; vec2.y = vc.z;\n\t\tvec3.x = vb.y; vec3.y = vb.z;\n\t\tvect.x = p.y; vect.y = p.z;\n\t\tbreak;\n\tcase DIR_X_NEG:\n\t\tvec1.x = va.y; vec1.y = va.z;\n\t\tvec2.x = vb.y; vec2.y = vb.z;\n\t\tvec3.x = vc.y; vec3.y = vc.z;\n\t\tvect.x = p.y; vect.y = p.z;\n\t\tbreak;\n\tcase DIR_Y_POS:\n\t\tvec1.x = va.z; vec1.y = va.x;\n\t\tvec2.x = vc.z; vec2.y = vc.x;\n\t\tvec3.x = vb.z; vec3.y = vb.x;\n\t\tvect.x = p.z; vect.y = p.x;\n\t\tbreak;\n\tcase DIR_Y_NEG:\n\t\tvec1.x = va.z; vec1.y = va.x;\n\t\tvec2.x = vb.z; vec2.y = vb.x;\n\t\tvec3.x = vc.z; vec3.y = vc.x;\n\t\tvect.x = p.z; vect.y = p.x;\n\t\tbreak;\n\tcase DIR_Z_POS:\n\t\tvec1.x = va.x; vec1.y = va.y;\n\t\tvec2.x = vc.x; vec2.y = vc.y;\n\t\tvec3.x = vb.x; vec3.y = vb.y;\n\t\tvect.x = p.x; vect.y = p.y;\n\t\tbreak;\n\tcase DIR_Z_NEG:\n\t\tvec1.x = va.x; vec1.y = va.y;\n\t\tvec2.x = vb.x; vec2.y = vb.y;\n\t\tvec3.x = vc.x; vec3.y = vc.y;\n\t\tvect.x = p.x; vect.y = p.y;\n\t\tbreak;\n\tdefault:\n\t\tassert(0);\n\t}\n\t// This is our triangle:\n\t// 3-------2\n\t//  \\  P  /\n\t//   \\   /\n\t//    \\ /\n\t//     1\n\t// We can use the \"2d cross product\" to check on which side\n\t// a vector is of another. Test is true if point is inside of all edges.\n\tif(CrossProduct2D(vec2-vec1, vect-vec1) < 0.0f) return false;\n\tif(CrossProduct2D(vec3-vec1, vect-vec1) > 0.0f) return false;\n\tif(CrossProduct2D(vec3-vec2, vect-vec2) < 0.0f) return false;\n\treturn true;\n#endif\n}\n\n// Test if line segment intersects with sphere.\n// If the first point is inside the sphere this test does not register a collision!\n// The code is reversed from the original code and rather ugly, see Process for a clear version.\n// TODO: actually rewrite this mess\nbool\nCCollision::TestLineSphere(const CColLine &line, const CColSphere &sph)\n{\n\tCVector v01 = line.p1 - line.p0;\t// vector from p0 to p1\n\tCVector v0c = sph.center - line.p0;\t// vector from p0 to center\n\tfloat linesq = v01.MagnitudeSqr();\n\t// I leave in the strange -2 factors even though they serve no real purpose\n\tfloat projline = -2.0f * DotProduct(v01, v0c);\t// project v0c onto line\n\t// Square of tangent from p0 multiplied by line length so we can compare with projline.\n\t// The length of the tangent would be this: Sqrt((c-p0)^2 - r^2).\n\t// Negative if p0 is inside the sphere! This breaks the test!\n\tfloat tansq = 4.0f * linesq *\n\t\t(sph.center.MagnitudeSqr() - 2.0f*DotProduct(sph.center, line.p0) + line.p0.MagnitudeSqr() - sph.radius*sph.radius);\n\tfloat diffsq = projline*projline - tansq;\n\t// if diffsq < 0 that means the line is a passant, so no intersection\n\tif(diffsq < 0.0f)\n\t\treturn false;\n\t// projline (negative in GTA for some reason) is the point on the line\n\t// in the middle of the two intersection points (startin from p0).\n\t// Sqrt(diffsq) somehow works out to be the distance from that\n\t// midpoint to the intersection points.\n\t// So subtract that and get rid of the awkward scaling:\n\tfloat f = (-projline - Sqrt(diffsq)) / (2.0f*linesq);\n\t// f should now be in range [0, 1] for [p0, p1]\n\treturn f >= 0.0f && f <= 1.0f;\n}\n\nbool\nCCollision::TestSphereTriangle(const CColSphere &sphere,\n\tconst CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane)\n{\n#ifdef VU_COLLISION\n\t// not used in favour of optimized loops\n\tVuTriangle vutri;\n\tverts[tri.a].Unpack(vutri.v0);\n\tverts[tri.b].Unpack(vutri.v1);\n\tverts[tri.c].Unpack(vutri.v2);\n\tplane.Unpack(vutri.plane);\n\n\tSphereToTriangleCollisionCompressed(*(CVuVector*)&sphere, vutri);\n\n\tif(GetVUresult())\n\t\treturn true;\n\treturn false;\n#else\n\t// If sphere and plane don't intersect, no collision\n\tfloat planedist = plane.CalcPoint(sphere.center);\n\tif(Abs(planedist) > sphere.radius)\n\t\treturn false;\n\n\tconst CVector &va = verts[tri.a].Get();\n\tconst CVector &vb = verts[tri.b].Get();\n\tconst CVector &vc = verts[tri.c].Get();\n\n\t// calculate two orthogonal basis vectors for the triangle\n\tCVector vec2 = vb - va;\n\tfloat len = vec2.Magnitude();\n\tvec2 = vec2 * (1.0f/len);\n\tCVector normal;\n\tplane.GetNormal(normal);\n\tCVector vec1 = CrossProduct(vec2, normal);\n\n\t// We know A has local coordinate [0,0] and B has [0,len].\n\t// Now calculate coordinates on triangle for these two vectors:\n\tCVector vac = vc - va;\n\tCVector vas = sphere.center - va;\n\tCVector2D b(0.0f, len);\n\tCVector2D c(DotProduct(vec1, vac), DotProduct(vec2, vac));\n\tCVector2D s(DotProduct(vec1, vas), DotProduct(vec2, vas));\n\n\t// The three triangle lines partition the space into 6 sectors,\n\t// find out in which the center lies.\n\tint insideAB = CrossProduct2D(s, b) >= 0.0f;\n\tint insideAC = CrossProduct2D(c, s) >= 0.0f;\n\tint insideBC = CrossProduct2D(s-b, c-b) >= 0.0f;\n\n\tint testcase = insideAB + insideAC + insideBC;\n\tfloat dist = 0.0f;\n\tswitch(testcase){\n\tcase 0:\n\t\treturn false;\t// shouldn't happen\n\tcase 1:\n\t\t// closest to a vertex\n\t\tif(insideAB) dist = (sphere.center - vc).Magnitude();\n\t\telse if(insideAC) dist = (sphere.center - vb).Magnitude();\n\t\telse if(insideBC) dist = (sphere.center - va).Magnitude();\n\t\telse assert(0);\n\t\tbreak;\n\tcase 2:\n\t\t// closest to an edge\n\t\t// looks like original game as DistToLine manually inlined\n\t\tif(!insideAB) dist = DistToLine(&va, &vb, &sphere.center);\n\t\telse if(!insideAC) dist = DistToLine(&va, &vc, &sphere.center);\n\t\telse if(!insideBC) dist = DistToLine(&vb, &vc, &sphere.center);\n\t\telse assert(0);\n\t\tbreak;\n\tcase 3:\n\t\t// center is in triangle\n\t\tdist = Abs(planedist);\n\t\tbreak;\n\tdefault:\n\t\tassert(0);\n\t}\n\n\treturn dist < sphere.radius;\n#endif\n}\n\nbool\nCCollision::TestLineOfSight(const CColLine &line, const CMatrix &matrix, CColModel &model, bool ignoreSeeThrough, bool ignoreShootThrough)\n{\n#ifdef VU_COLLISION\n\tCMatrix matTransform;\n\tint i;\n\n\t// transform line to model space\n\tInvert(matrix, matTransform);\n\tCVuVector newline[2];\n\tTransformPoints(newline, 2, matTransform, &line.p0, sizeof(CColLine)/2);\n\n\t// If we don't intersect with the bounding box, no chance on the rest\n\tif(!TestLineBox(*(CColLine*)newline, model.boundingBox))\n\t\treturn false;\n\n\tfor(i = 0; i < model.numSpheres; i++){\n\t\tif(ignoreSeeThrough && IsSeeThrough(model.spheres[i].surface)) continue;\n\t\tif(ignoreShootThrough && IsShootThrough(model.spheres[i].surface)) continue;\n\t\tif(TestLineSphere(*(CColLine*)newline, model.spheres[i]))\n\t\t\treturn true;\n\t}\n\n\tfor(i = 0; i < model.numBoxes; i++){\n\t\tif(ignoreSeeThrough && IsSeeThrough(model.boxes[i].surface)) continue;\n\t\tif(ignoreShootThrough && IsShootThrough(model.boxes[i].surface)) continue;\n\t\tif(TestLineBox(*(CColLine*)newline, model.boxes[i]))\n\t\t\treturn true;\n\t}\n\n\tCalculateTrianglePlanes(&model);\n\tint lastTest = -1;\n\tVuTriangle vutri;\n\tfor(i = 0; i < model.numTriangles; i++){\n\t\tif(ignoreSeeThrough && IsSeeThrough(model.triangles[i].surface)) continue;\n\t\tif(ignoreShootThrough && IsShootThrough(model.triangles[i].surface)) continue;\n\n\t\tCColTriangle *tri = &model.triangles[i];\n\t\tmodel.vertices[tri->a].Unpack(vutri.v0);\n\t\tmodel.vertices[tri->b].Unpack(vutri.v1);\n\t\tmodel.vertices[tri->c].Unpack(vutri.v2);\n\t\tmodel.trianglePlanes[i].Unpack(vutri.plane);\n\n\t\tLineToTriangleCollisionCompressed(newline[0], newline[1], vutri);\n\t\tlastTest = i;\n\t\tbreak;\n\t}\n#ifdef FIX_BUGS\n\t// no need to check first again\n\ti++;\n#endif\n\tfor(; i < model.numTriangles; i++){\n\t\tif(ignoreSeeThrough && IsSeeThrough(model.triangles[i].surface)) continue;\n\t\tif(ignoreShootThrough && IsShootThrough(model.triangles[i].surface)) continue;\n\n\t\tCColTriangle *tri = &model.triangles[i];\n\t\tmodel.vertices[tri->a].Unpack(vutri.v0);\n\t\tmodel.vertices[tri->b].Unpack(vutri.v1);\n\t\tmodel.vertices[tri->c].Unpack(vutri.v2);\n\t\tmodel.trianglePlanes[i].Unpack(vutri.plane);\n\n\t\tif(GetVUresult())\n\t\t\treturn true;\n\n\t\tLineToTriangleCollisionCompressed(newline[0], newline[1], vutri);\n\t\tlastTest = i;\n\n\t}\n\tif(lastTest != -1 && GetVUresult())\n\t\treturn true;\n\n\treturn false;\n#else\n\tstatic CMatrix matTransform;\n\tint i;\n\n\t// transform line to model space\n\tInvert(matrix, matTransform);\n\tCColLine newline(matTransform * line.p0, matTransform * line.p1);\n\n\t// If we don't intersect with the bounding box, no chance on the rest\n\tif(!TestLineBox(newline, model.boundingBox))\n\t\treturn false;\n\n\tfor(i = 0; i < model.numSpheres; i++){\n\t\tif(ignoreSeeThrough && IsSeeThrough(model.spheres[i].surface)) continue;\n\t\tif(ignoreShootThrough && IsShootThrough(model.spheres[i].surface)) continue;\n\t\tif(TestLineSphere(newline, model.spheres[i]))\n\t\t\treturn true;\n\t}\n\n\tfor(i = 0; i < model.numBoxes; i++){\n\t\tif(ignoreSeeThrough && IsSeeThrough(model.boxes[i].surface)) continue;\n\t\tif(ignoreShootThrough && IsShootThrough(model.boxes[i].surface)) continue;\n\t\tif(TestLineBox(newline, model.boxes[i]))\n\t\t\treturn true;\n\t}\n\n\tCalculateTrianglePlanes(&model);\n\tfor(i = 0; i < model.numTriangles; i++){\n\t\tif(ignoreSeeThrough && IsSeeThrough(model.triangles[i].surface)) continue;\n\t\tif(ignoreShootThrough && IsShootThrough(model.triangles[i].surface)) continue;\n\t\tif(TestLineTriangle(newline, model.vertices, model.triangles[i], model.trianglePlanes[i]))\n\t\t\treturn true;\n\t}\n\n\treturn false;\n#endif\n}\n\n// TODO: TestPillWithSpheresInColModel, but only called from overloaded CWeapon::FireMelee which isn't used\n\n//\n// Process\n//\n\n// For Spheres mindist is the squared distance to its center\n// For Lines mindist is between [0,1]\n\nbool\nCCollision::ProcessSphereSphere(const CColSphere &s1, const CColSphere &s2, CColPoint &point, float &mindistsq)\n{\n\tCVector dist = s1.center - s2.center;\n\tfloat d = dist.Magnitude() - s2.radius;\t// distance from s1's center to s2\n\tfloat depth = s1.radius - d;\t// sphere overlap\n\tif(d < 0.0f) d = 0.0f;\t\t// clamp to zero, i.e. if s1's center is inside s2\n\t// no collision if sphere is not close enough\n\tif(d*d < mindistsq && d < s1.radius){\n\t\tdist.Normalise();\n\t\tpoint.point = s1.center - dist*d;\n\t\tpoint.normal = dist;\n#ifndef VU_COLLISION\n\t\tpoint.surfaceA = s1.surface;\n\t\tpoint.pieceA = s1.piece;\n\t\tpoint.surfaceB = s2.surface;\n\t\tpoint.pieceB = s2.piece;\n#endif\n\t\tpoint.depth = depth;\t\n\t\tmindistsq = d*d;\t\t// collision radius\n\t\treturn true;\n\t}\n\treturn false;\n}\n\nbool\nCCollision::ProcessSphereBox(const CColSphere &sph, const CColBox &box, CColPoint &point, float &mindistsq)\n{\n\tCVector p;\n\tCVector dist;\n\n\t// GTA's code is too complicated, uses a huge 3x3x3 if statement\n\t// we can simplify the structure a lot\n\n\t// first make sure we have a collision at all\n\tif(sph.center.x + sph.radius < box.min.x) return false;\n\tif(sph.center.x - sph.radius > box.max.x) return false;\n\tif(sph.center.y + sph.radius < box.min.y) return false;\n\tif(sph.center.y - sph.radius > box.max.y) return false;\n\tif(sph.center.z + sph.radius < box.min.z) return false;\n\tif(sph.center.z - sph.radius > box.max.z) return false;\n\n\t// Now find out where the sphere center lies in relation to all the sides\n\tint xpos = sph.center.x < box.min.x ? 1 :\n\t           sph.center.x > box.max.x ? 2 :\n\t           0;\n\tint ypos = sph.center.y < box.min.y ? 1 :\n\t           sph.center.y > box.max.y ? 2 :\n\t           0;\n\tint zpos = sph.center.z < box.min.z ? 1 :\n\t           sph.center.z > box.max.z ? 2 :\n\t           0;\n\n\tif(xpos == 0 && ypos == 0 && zpos == 0){\n\t\t// sphere is inside the box\n\t\tp = (box.min + box.max)*0.5f;\n\n\t\tdist = sph.center - p;\n\t\tfloat lensq = dist.MagnitudeSqr();\n\t\tif(lensq < mindistsq){\n\t\t\tpoint.normal = dist * (1.0f/Sqrt(lensq));\n\t\t\tpoint.point = sph.center - point.normal;\n#ifndef VU_COLLISION\n\t\t\tpoint.surfaceA = sph.surface;\n\t\t\tpoint.pieceA = sph.piece;\n\t\t\tpoint.surfaceB = box.surface;\n\t\t\tpoint.pieceB = box.piece;\n#endif\n\n\t\t\t// find absolute distance to the closer side in each dimension\n\t\t\tfloat dx = dist.x > 0.0f ?\n\t\t\t\tbox.max.x - sph.center.x :\n\t\t\t\tsph.center.x - box.min.x;\n\t\t\tfloat dy = dist.y > 0.0f ?\n\t\t\t\tbox.max.y - sph.center.y :\n\t\t\t\tsph.center.y - box.min.y;\n\t\t\tfloat dz = dist.z > 0.0f ?\n\t\t\t\tbox.max.z - sph.center.z :\n\t\t\t\tsph.center.z - box.min.z;\n\t\t\t// collision depth is maximum of that:\n\t\t\tif(dx > dy && dx > dz)\n\t\t\t\tpoint.depth = dx;\n\t\t\telse if(dy > dz)\n\t\t\t\tpoint.depth = dy;\n\t\t\telse\n\t\t\t\tpoint.depth = dz;\n\t\t\treturn true;\n\t\t}\n\t}else{\n\t\t// sphere is outside.\n\t\t// closest point on box:\n\t\tp.x = xpos == 1 ? box.min.x :\n\t\t      xpos == 2 ? box.max.x :\n\t\t      sph.center.x;\n\t\tp.y = ypos == 1 ? box.min.y :\n\t\t      ypos == 2 ? box.max.y :\n\t\t      sph.center.y;\n\t\tp.z = zpos == 1 ? box.min.z :\n\t\t      zpos == 2 ? box.max.z :\n\t\t      sph.center.z;\n\n\t\tdist = sph.center - p;\n\t\tfloat lensq = dist.MagnitudeSqr();\n\t\tif(lensq < mindistsq){\n\t\t\tfloat len = Sqrt(lensq);\n\t\t\tpoint.point = p;\n\t\t\tpoint.normal = dist * (1.0f/len);\n#ifndef VU_COLLISION\n\t\t\tpoint.surfaceA = sph.surface;\n\t\t\tpoint.pieceA = sph.piece;\n\t\t\tpoint.surfaceB = box.surface;\n\t\t\tpoint.pieceB = box.piece;\n#endif\n\t\t\tpoint.depth = sph.radius - len;\n\t\t\tmindistsq = lensq;\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n\nbool\nCCollision::ProcessLineBox(const CColLine &line, const CColBox &box, CColPoint &point, float &mindist)\n{\n\tfloat mint, t, x, y, z;\n\tCVector normal;\n\tCVector p;\n\n\tmint = 1.0f;\n\t// check if points are on opposite sides of min x plane\n\tif((box.min.x - line.p1.x) * (box.min.x - line.p0.x) < 0.0f){\n\t\t// parameter along line where we intersect\n\t\tt = (box.min.x - line.p0.x) / (line.p1.x - line.p0.x);\n\t\t// y of intersection\n\t\ty = line.p0.y + (line.p1.y - line.p0.y)*t;\n\t\tif(y > box.min.y && y < box.max.y){\n\t\t\t// z of intersection\n\t\t\tz = line.p0.z + (line.p1.z - line.p0.z)*t;\n\t\t\tif(z > box.min.z && z < box.max.z)\n\t\t\t\tif(t < mint){\n\t\t\t\t\tmint = t;\n\t\t\t\t\tp = CVector(box.min.x, y, z);\n\t\t\t\t\tnormal = CVector(-1.0f, 0.0f, 0.0f);\n\t\t\t\t}\n\t\t}\n\t}\n\n\t// max x plane\n\tif((line.p1.x - box.max.x) * (line.p0.x - box.max.x) < 0.0f){\n\t\tt = (line.p0.x - box.max.x) / (line.p0.x - line.p1.x);\n\t\ty = line.p0.y + (line.p1.y - line.p0.y)*t;\n\t\tif(y > box.min.y && y < box.max.y){\n\t\t\tz = line.p0.z + (line.p1.z - line.p0.z)*t;\n\t\t\tif(z > box.min.z && z < box.max.z)\n\t\t\t\tif(t < mint){\n\t\t\t\t\tmint = t;\n\t\t\t\t\tp = CVector(box.max.x, y, z);\n\t\t\t\t\tnormal = CVector(1.0f, 0.0f, 0.0f);\n\t\t\t\t}\n\t\t}\n\t}\n\n\t// min y plne\n\tif((box.min.y - line.p0.y) * (box.min.y - line.p1.y) < 0.0f){\n\t\tt = (box.min.y - line.p0.y) / (line.p1.y - line.p0.y);\n\t\tx = line.p0.x + (line.p1.x - line.p0.x)*t;\n\t\tif(x > box.min.x && x < box.max.x){\n\t\t\tz = line.p0.z + (line.p1.z - line.p0.z)*t;\n\t\t\tif(z > box.min.z && z < box.max.z)\n\t\t\t\tif(t < mint){\n\t\t\t\t\tmint = t;\n\t\t\t\t\tp = CVector(x, box.min.y, z);\n\t\t\t\t\tnormal = CVector(0.0f, -1.0f, 0.0f);\n\t\t\t\t}\n\t\t}\n\t}\n\n\t// max y plane\n\tif((line.p0.y - box.max.y) * (line.p1.y - box.max.y) < 0.0f){\n\t\tt = (line.p0.y - box.max.y) / (line.p0.y - line.p1.y);\n\t\tx = line.p0.x + (line.p1.x - line.p0.x)*t;\n\t\tif(x > box.min.x && x < box.max.x){\n\t\t\tz = line.p0.z + (line.p1.z - line.p0.z)*t;\n\t\t\tif(z > box.min.z && z < box.max.z)\n\t\t\t\tif(t < mint){\n\t\t\t\t\tmint = t;\n\t\t\t\t\tp = CVector(x, box.max.y, z);\n\t\t\t\t\tnormal = CVector(0.0f, 1.0f, 0.0f);\n\t\t\t\t}\n\t\t}\n\t}\n\n\t// min z plne\n\tif((box.min.z - line.p0.z) * (box.min.z - line.p1.z) < 0.0f){\n\t\tt = (box.min.z - line.p0.z) / (line.p1.z - line.p0.z);\n\t\tx = line.p0.x + (line.p1.x - line.p0.x)*t;\n\t\tif(x > box.min.x && x < box.max.x){\n\t\t\ty = line.p0.y + (line.p1.y - line.p0.y)*t;\n\t\t\tif(y > box.min.y && y < box.max.y)\n\t\t\t\tif(t < mint){\n\t\t\t\t\tmint = t;\n\t\t\t\t\tp = CVector(x, y, box.min.z);\n\t\t\t\t\tnormal = CVector(0.0f, 0.0f, -1.0f);\n\t\t\t\t}\n\t\t}\n\t}\n\n\t// max z plane\n\tif((line.p0.z - box.max.z) * (line.p1.z - box.max.z) < 0.0f){\n\t\tt = (line.p0.z - box.max.z) / (line.p0.z - line.p1.z);\n\t\tx = line.p0.x + (line.p1.x - line.p0.x)*t;\n\t\tif(x > box.min.x && x < box.max.x){\n\t\t\ty = line.p0.y + (line.p1.y - line.p0.y)*t;\n\t\t\tif(y > box.min.y && y < box.max.y)\n\t\t\t\tif(t < mint){\n\t\t\t\t\tmint = t;\n\t\t\t\t\tp = CVector(x, y, box.max.z);\n\t\t\t\t\tnormal = CVector(0.0f, 0.0f, 1.0f);\n\t\t\t\t}\n\t\t}\n\t}\n\n\tif(mint >= mindist)\n\t\treturn false;\n\n\tpoint.point = p;\n\tpoint.normal = normal;\n#ifndef VU_COLLISION\n\tpoint.surfaceA = 0;\n\tpoint.pieceA = 0;\n\tpoint.surfaceB = box.surface;\n\tpoint.pieceB = box.piece;\n#endif\n\tmindist = mint;\n\n\treturn true;\n}\n\n// If line.p0 lies inside sphere, no collision is registered.\nbool\nCCollision::ProcessLineSphere(const CColLine &line, const CColSphere &sphere, CColPoint &point, float &mindist)\n{\n\tCVector v01 = line.p1 - line.p0;\n\tCVector v0c = sphere.center - line.p0;\n\tfloat linesq = v01.MagnitudeSqr();\n\t// project v0c onto v01, scaled by |v01| this is the midpoint of the two intersections\n\tfloat projline = DotProduct(v01, v0c);\n\t// tangent of p0 to sphere, scaled by linesq just like projline^2\n\tfloat tansq = (v0c.MagnitudeSqr() - sphere.radius*sphere.radius) * linesq;\n\t// this works out to be the square of the distance between the midpoint and the intersections\n\tfloat diffsq = projline*projline - tansq;\n\t// no intersection\n\tif(diffsq < 0.0f)\n\t\treturn false;\n\t// point of first intersection, in range [0,1] between p0 and p1\n\tfloat t = (projline - Sqrt(diffsq)) / linesq;\n\t// if not on line or beyond mindist, no intersection\n\tif(t < 0.0f || t > 1.0f || t >= mindist)\n\t\treturn false;\n\tpoint.point = line.p0 + v01*t;\n\tpoint.normal = point.point - sphere.center;\n\tpoint.normal.Normalise();\n#ifndef VU_COLLISION\n\tpoint.surfaceA = 0;\n\tpoint.pieceA = 0;\n\tpoint.surfaceB = sphere.surface;\n\tpoint.pieceB = sphere.piece;\n#endif\n\tmindist = t;\n\treturn true;\n}\n\n// unused\nbool\nCCollision::ProcessVerticalLineTriangle(const CColLine &line,\n\tconst CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane,\n\tCColPoint &point, float &mindist, CStoredCollPoly *poly)\n{\n#ifdef VU_COLLISION\n\t// not used in favour of optimized loops\n\tbool res = ProcessLineTriangle(line, verts, tri, plane, point, mindist);\n\tif(res && poly){\n\t\tpoly->verts[0] = verts[tri.a].Get();\n\t\tpoly->verts[1] = verts[tri.b].Get();\n\t\tpoly->verts[2] = verts[tri.c].Get();\n\t\tpoly->valid = true;\n\t}\n\treturn res;\n#else\n\tfloat t;\n\tCVector normal;\n\n\tconst CVector &p0 = line.p0;\n\tconst CVector &va = verts[tri.a].Get();\n\tconst CVector &vb = verts[tri.b].Get();\n\tconst CVector &vc = verts[tri.c].Get();\n\n\t// early out bound rect test\n\tif(p0.x < va.x && p0.x < vb.x && p0.x < vc.x) return false;\n\tif(p0.x > va.x && p0.x > vb.x && p0.x > vc.x) return false;\n\tif(p0.y < va.y && p0.y < vb.y && p0.y < vc.y) return false;\n\tif(p0.y > va.y && p0.y > vb.y && p0.y > vc.y) return false;\n\n\tplane.GetNormal(normal);\n\t// if points are on the same side, no collision\n\tif(plane.CalcPoint(p0) * plane.CalcPoint(line.p1) > 0.0f)\n\t\treturn false;\n\n\t// intersection parameter on line\n\tfloat h = (line.p1 - p0).z;\n\tt = -plane.CalcPoint(p0) / (h * normal.z);\n\t// early out if we're beyond the mindist\n\tif(t >= mindist)\n\t\treturn false;\n\tCVector p(p0.x, p0.y, p0.z + h*t);\n\n\tCVector2D vec1, vec2, vec3, vect;\n\tswitch(plane.dir){\n\tcase DIR_X_POS:\n\t\tvec1.x = va.y; vec1.y = va.z;\n\t\tvec2.x = vc.y; vec2.y = vc.z;\n\t\tvec3.x = vb.y; vec3.y = vb.z;\n\t\tvect.x = p.y; vect.y = p.z;\n\t\tbreak;\n\tcase DIR_X_NEG:\n\t\tvec1.x = va.y; vec1.y = va.z;\n\t\tvec2.x = vb.y; vec2.y = vb.z;\n\t\tvec3.x = vc.y; vec3.y = vc.z;\n\t\tvect.x = p.y; vect.y = p.z;\n\t\tbreak;\n\tcase DIR_Y_POS:\n\t\tvec1.x = va.z; vec1.y = va.x;\n\t\tvec2.x = vc.z; vec2.y = vc.x;\n\t\tvec3.x = vb.z; vec3.y = vb.x;\n\t\tvect.x = p.z; vect.y = p.x;\n\t\tbreak;\n\tcase DIR_Y_NEG:\n\t\tvec1.x = va.z; vec1.y = va.x;\n\t\tvec2.x = vb.z; vec2.y = vb.x;\n\t\tvec3.x = vc.z; vec3.y = vc.x;\n\t\tvect.x = p.z; vect.y = p.x;\n\t\tbreak;\n\tcase DIR_Z_POS:\n\t\tvec1.x = va.x; vec1.y = va.y;\n\t\tvec2.x = vc.x; vec2.y = vc.y;\n\t\tvec3.x = vb.x; vec3.y = vb.y;\n\t\tvect.x = p.x; vect.y = p.y;\n\t\tbreak;\n\tcase DIR_Z_NEG:\n\t\tvec1.x = va.x; vec1.y = va.y;\n\t\tvec2.x = vb.x; vec2.y = vb.y;\n\t\tvec3.x = vc.x; vec3.y = vc.y;\n\t\tvect.x = p.x; vect.y = p.y;\n\t\tbreak;\n\tdefault:\n\t\tassert(0);\n\t}\n\tif(CrossProduct2D(vec2-vec1, vect-vec1) < 0.0f) return false;\n\tif(CrossProduct2D(vec3-vec1, vect-vec1) > 0.0f) return false;\n\tif(CrossProduct2D(vec3-vec2, vect-vec2) < 0.0f) return false;\n\tif(t >= mindist) return false;\n\tpoint.point = p;\n\tpoint.normal = normal;\n\tpoint.surfaceA = 0;\n\tpoint.pieceA = 0;\n\tpoint.surfaceB = tri.surface;\n\tpoint.pieceB = 0;\n\tif(poly){\n\t\tpoly->verts[0] = va;\n\t\tpoly->verts[1] = vb;\n\t\tpoly->verts[2] = vc;\n\t\tpoly->valid = true;\n\t}\n\tmindist = t;\n\treturn true;\n#endif\n}\n\nbool\nCCollision::IsStoredPolyStillValidVerticalLine(const CVector &pos, float z, CColPoint &point, CStoredCollPoly *poly)\n{\n#ifdef VU_COLLISION\n\tif(!poly->valid)\n\t\treturn false;\n\n\tCVuVector p0 = pos;\n\tCVuVector p1 = pos;\n\tp1.z = z;\n\n\tCVector v01 = poly->verts[1] - poly->verts[0];\n\tCVector v02 = poly->verts[2] - poly->verts[0];\n\tCVuVector plane = CrossProduct(v02, v01);\n\tplane.Normalise();\n\tplane.w = DotProduct(plane, poly->verts[0]);\n\n\tLineToTriangleCollision(p0, p1, poly->verts[0], poly->verts[1], poly->verts[2], plane);\n\n\tCVuVector pnt;\n\tfloat dist;\n\tif(!GetVUresult(pnt, plane, dist))\n#ifdef FIX_BUGS\n\t\t// perhaps not needed but be safe\n\t\treturn poly->valid = false;\n#else\n\t\treturn false;\n#endif\n\tpoint.point = pnt;\n\treturn true;\n#else\n\tfloat t;\n\n\tif(!poly->valid)\n\t\treturn false;\n\n\t// maybe inlined?\n\tCColTrianglePlane plane;\n\tplane.Set(poly->verts[0], poly->verts[1], poly->verts[2]);\n\n\tconst CVector &va = poly->verts[0];\n\tconst CVector &vb = poly->verts[1];\n\tconst CVector &vc = poly->verts[2];\n\tCVector p0 = pos;\n\tCVector p1(pos.x, pos.y, z);\n\n\t// The rest is pretty much CCollision::ProcessLineTriangle\n\n\t// if points are on the same side, no collision\n\tif(plane.CalcPoint(p0) * plane.CalcPoint(p1) > 0.0f)\n\t\treturn poly->valid = false;\n\n\t// intersection parameter on line\n\tCVector normal;\n\tplane.GetNormal(normal);\n\tt = -plane.CalcPoint(p0) / DotProduct(p1 - p0, normal);\n\t// find point of intersection\n\tCVector p = p0 + (p1-p0)*t;\n\n\tCVector2D vec1, vec2, vec3, vect;\n\tswitch(plane.dir){\n\tcase DIR_X_POS:\n\t\tvec1.x = va.y; vec1.y = va.z;\n\t\tvec2.x = vc.y; vec2.y = vc.z;\n\t\tvec3.x = vb.y; vec3.y = vb.z;\n\t\tvect.x = p.y; vect.y = p.z;\n\t\tbreak;\n\tcase DIR_X_NEG:\n\t\tvec1.x = va.y; vec1.y = va.z;\n\t\tvec2.x = vb.y; vec2.y = vb.z;\n\t\tvec3.x = vc.y; vec3.y = vc.z;\n\t\tvect.x = p.y; vect.y = p.z;\n\t\tbreak;\n\tcase DIR_Y_POS:\n\t\tvec1.x = va.z; vec1.y = va.x;\n\t\tvec2.x = vc.z; vec2.y = vc.x;\n\t\tvec3.x = vb.z; vec3.y = vb.x;\n\t\tvect.x = p.z; vect.y = p.x;\n\t\tbreak;\n\tcase DIR_Y_NEG:\n\t\tvec1.x = va.z; vec1.y = va.x;\n\t\tvec2.x = vb.z; vec2.y = vb.x;\n\t\tvec3.x = vc.z; vec3.y = vc.x;\n\t\tvect.x = p.z; vect.y = p.x;\n\t\tbreak;\n\tcase DIR_Z_POS:\n\t\tvec1.x = va.x; vec1.y = va.y;\n\t\tvec2.x = vc.x; vec2.y = vc.y;\n\t\tvec3.x = vb.x; vec3.y = vb.y;\n\t\tvect.x = p.x; vect.y = p.y;\n\t\tbreak;\n\tcase DIR_Z_NEG:\n\t\tvec1.x = va.x; vec1.y = va.y;\n\t\tvec2.x = vb.x; vec2.y = vb.y;\n\t\tvec3.x = vc.x; vec3.y = vc.y;\n\t\tvect.x = p.x; vect.y = p.y;\n\t\tbreak;\n\tdefault:\n\t\tassert(0);\n\t}\n\tif(CrossProduct2D(vec2-vec1, vect-vec1) < 0.0f) return poly->valid = false;\n\tif(CrossProduct2D(vec3-vec1, vect-vec1) > 0.0f) return poly->valid = false;\n\tif(CrossProduct2D(vec3-vec2, vect-vec2) < 0.0f) return poly->valid = false;\n\tpoint.point = p;\n\treturn poly->valid = true;\n#endif\n}\n\nbool\nCCollision::ProcessLineTriangle(const CColLine &line,\n\tconst CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane,\n\tCColPoint &point, float &mindist, CStoredCollPoly *poly)\n{\n#ifdef VU_COLLISION\n\t// not used in favour of optimized loops\n\tVuTriangle vutri;\n\tverts[tri.a].Unpack(vutri.v0);\n\tverts[tri.b].Unpack(vutri.v1);\n\tverts[tri.c].Unpack(vutri.v2);\n\tplane.Unpack(vutri.plane);\n\n\tLineToTriangleCollisionCompressed(*(CVuVector*)&line.p0, *(CVuVector*)&line.p1, vutri);\n\n\tCVuVector pnt, normal;\n\tfloat dist;\n\tif(GetVUresult(pnt, normal, dist)){\n\t\tif(dist < mindist){\n\t\t\tpoint.point = pnt;\n\t\t\tpoint.normal = normal;\n\t\t\tmindist = dist;\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n#else\n\tfloat t;\n\tCVector normal;\n\tplane.GetNormal(normal);\n\n\t// if points are on the same side, no collision\n\tif(plane.CalcPoint(line.p0) * plane.CalcPoint(line.p1) > 0.0f)\n\t\treturn false;\n\n\tfloat p0dist = DotProduct(line.p1 - line.p0, normal);\n\n#ifdef FIX_BUGS\n\t// line lines in the plane, assume no collision\n\tif (p0dist == 0.0f)\n\t\treturn false;\n#endif\n\n\t// intersection parameter on line\n\tt = -plane.CalcPoint(line.p0) / p0dist;\n\n\t// early out if we're beyond the mindist\n\tif(t >= mindist)\n\t\treturn false;\n\t// find point of intersection\n\tCVector p = line.p0 + (line.p1-line.p0)*t;\n\n\tconst CVector &va = verts[tri.a].Get();\n\tconst CVector &vb = verts[tri.b].Get();\n\tconst CVector &vc = verts[tri.c].Get();\n\tCVector2D vec1, vec2, vec3, vect;\n\n\tswitch(plane.dir){\n\tcase DIR_X_POS:\n\t\tvec1.x = va.y; vec1.y = va.z;\n\t\tvec2.x = vc.y; vec2.y = vc.z;\n\t\tvec3.x = vb.y; vec3.y = vb.z;\n\t\tvect.x = p.y; vect.y = p.z;\n\t\tbreak;\n\tcase DIR_X_NEG:\n\t\tvec1.x = va.y; vec1.y = va.z;\n\t\tvec2.x = vb.y; vec2.y = vb.z;\n\t\tvec3.x = vc.y; vec3.y = vc.z;\n\t\tvect.x = p.y; vect.y = p.z;\n\t\tbreak;\n\tcase DIR_Y_POS:\n\t\tvec1.x = va.z; vec1.y = va.x;\n\t\tvec2.x = vc.z; vec2.y = vc.x;\n\t\tvec3.x = vb.z; vec3.y = vb.x;\n\t\tvect.x = p.z; vect.y = p.x;\n\t\tbreak;\n\tcase DIR_Y_NEG:\n\t\tvec1.x = va.z; vec1.y = va.x;\n\t\tvec2.x = vb.z; vec2.y = vb.x;\n\t\tvec3.x = vc.z; vec3.y = vc.x;\n\t\tvect.x = p.z; vect.y = p.x;\n\t\tbreak;\n\tcase DIR_Z_POS:\n\t\tvec1.x = va.x; vec1.y = va.y;\n\t\tvec2.x = vc.x; vec2.y = vc.y;\n\t\tvec3.x = vb.x; vec3.y = vb.y;\n\t\tvect.x = p.x; vect.y = p.y;\n\t\tbreak;\n\tcase DIR_Z_NEG:\n\t\tvec1.x = va.x; vec1.y = va.y;\n\t\tvec2.x = vb.x; vec2.y = vb.y;\n\t\tvec3.x = vc.x; vec3.y = vc.y;\n\t\tvect.x = p.x; vect.y = p.y;\n\t\tbreak;\n\tdefault:\n\t\tassert(0);\n\t}\n\tif(CrossProduct2D(vec2-vec1, vect-vec1) < 0.0f) return false;\n\tif(CrossProduct2D(vec3-vec1, vect-vec1) > 0.0f) return false;\n\tif(CrossProduct2D(vec3-vec2, vect-vec2) < 0.0f) return false;\n\tif(t >= mindist) return false;\n\tpoint.point = p;\n\tpoint.normal = normal;\n\tpoint.surfaceA = 0;\n\tpoint.pieceA = 0;\n\tpoint.surfaceB = tri.surface;\n\tpoint.pieceB = 0;\n\tif(poly){\n\t\tpoly->verts[0] = va;\n\t\tpoly->verts[1] = vb;\n\t\tpoly->verts[2] = vc;\n\t\tpoly->valid = true;\n\t}\n\tmindist = t;\n\treturn true;\n#endif\n}\n\nbool\nCCollision::ProcessSphereTriangle(const CColSphere &sphere,\n\tconst CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane,\n\tCColPoint &point, float &mindistsq)\n{\n#ifdef VU_COLLISION\n\t// not used in favour of optimized loops\n\tVuTriangle vutri;\n\tverts[tri.a].Unpack(vutri.v0);\n\tverts[tri.b].Unpack(vutri.v1);\n\tverts[tri.c].Unpack(vutri.v2);\n\tplane.Unpack(vutri.plane);\n\n\tSphereToTriangleCollisionCompressed(*(CVuVector*)&sphere, vutri);\n\n\tCVuVector pnt, normal;\n\tfloat dist;\n\tif(GetVUresult(pnt, normal, dist) && dist*dist < mindistsq){\n\t\tfloat depth = sphere.radius - dist;\n\t\tif(depth > point.depth){\n\t\t\tpoint.point = pnt;\n\t\t\tpoint.normal = normal;\n\t\t\tpoint.depth = depth;\n\t\t\tmindistsq = dist*dist;\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n#else\n\t// If sphere and plane don't intersect, no collision\n\tfloat planedist = plane.CalcPoint(sphere.center);\n\tfloat distsq = planedist*planedist;\n\tif(Abs(planedist) > sphere.radius || distsq > mindistsq)\n\t\treturn false;\n\n\tconst CVector &va = verts[tri.a].Get();\n\tconst CVector &vb = verts[tri.b].Get();\n\tconst CVector &vc = verts[tri.c].Get();\n\n\t// calculate two orthogonal basis vectors for the triangle\n\tCVector normal;\n\tplane.GetNormal(normal);\n\tCVector vec2 = vb - va;\n\tfloat len = vec2.Magnitude();\n\tvec2 = vec2 * (1.0f/len);\n\tCVector vec1 = CrossProduct(vec2, normal);\n\n\t// We know A has local coordinate [0,0] and B has [0,len].\n\t// Now calculate coordinates on triangle for these two vectors:\n\tCVector vac = vc - va;\n\tCVector vas = sphere.center - va;\n\tCVector2D b(0.0f, len);\n\tCVector2D c(DotProduct(vec1, vac), DotProduct(vec2, vac));\n\tCVector2D s(DotProduct(vec1, vas), DotProduct(vec2, vas));\n\n\t// The three triangle lines partition the space into 6 sectors,\n\t// find out in which the center lies.\n\tint insideAB = CrossProduct2D(s, b) >= 0.0f;\n\tint insideAC = CrossProduct2D(c, s) >= 0.0f;\n\tint insideBC = CrossProduct2D(s-b, c-b) >= 0.0f;\n\n\tint testcase = insideAB + insideAC + insideBC;\n\tfloat dist = 0.0f;\n\tCVector p;\n\tswitch(testcase){\n\tcase 0:\n\t\treturn false;\t// shouldn't happen\n\tcase 1:\n\t\t// closest to a vertex\n\t\tif(insideAB) p = vc;\n\t\telse if(insideAC) p = vb;\n\t\telse if(insideBC) p = va;\n\t\telse assert(0);\n\t\tdist = (sphere.center - p).Magnitude();\n\t\tbreak;\n\tcase 2:\n\t\t// closest to an edge\n\t\t// looks like original game as DistToLine manually inlined\n\t\tif(!insideAB) dist = DistToLine(&va, &vb, &sphere.center, p);\n\t\telse if(!insideAC) dist = DistToLine(&va, &vc, &sphere.center, p);\n\t\telse if(!insideBC) dist = DistToLine(&vb, &vc, &sphere.center, p);\n\t\telse assert(0);\n\t\tbreak;\n\tcase 3:\n\t\t// center is in triangle\n\t\tdist = Abs(planedist);\n\t\tp = sphere.center - normal*planedist;\n\t\tbreak;\n\tdefault:\n\t\tassert(0);\n\t}\n\n\tif(dist >= sphere.radius || dist*dist >= mindistsq)\n\t\treturn false;\n\n\tpoint.point = p;\n\tpoint.normal = sphere.center - p;\n\tpoint.normal.Normalise();\n#ifndef VU_COLLISION\n\tpoint.surfaceA = sphere.surface;\n\tpoint.pieceA = sphere.piece;\n\tpoint.surfaceB = tri.surface;\n\tpoint.pieceB = 0;\n#endif\n\tpoint.depth = sphere.radius - dist;\n\tmindistsq = dist*dist;\n\treturn true;\n#endif\n}\n\nbool\nCCollision::ProcessLineOfSight(const CColLine &line,\n\tconst CMatrix &matrix, CColModel &model,\n\tCColPoint &point, float &mindist, bool ignoreSeeThrough, bool ignoreShootThrough)\n{\n#ifdef VU_COLLISION\n\tCMatrix matTransform;\n\tint i;\n\n\t// transform line to model space\n\tInvert(matrix, matTransform);\n\tCVuVector newline[2];\n\tTransformPoints(newline, 2, matTransform, &line.p0, sizeof(CColLine)/2);\n\n\tif(mindist < 1.0f)\n\t\tnewline[1] = newline[0] + (newline[1] - newline[0])*mindist;\n\n\t// If we don't intersect with the bounding box, no chance on the rest\n\tif(!TestLineBox(*(CColLine*)newline, model.boundingBox))\n\t\treturn false;\n\n\tfloat coldist = 1.0f;\n\tfor(i = 0; i < model.numSpheres; i++){\n\t\tif(ignoreSeeThrough && IsSeeThrough(model.spheres[i].surface)) continue;\n\t\tif(ignoreShootThrough && IsShootThrough(model.spheres[i].surface)) continue;\n\t\tif(ProcessLineSphere(*(CColLine*)newline, model.spheres[i], point, coldist))\n\t\t\tpoint.Set(0, 0, model.spheres[i].surface, model.spheres[i].piece);\n\t}\n\n\tfor(i = 0; i < model.numBoxes; i++){\n\t\tif(ignoreSeeThrough && IsSeeThrough(model.boxes[i].surface)) continue;\n\t\tif(ProcessLineBox(*(CColLine*)newline, model.boxes[i], point, coldist))\n\t\t\tpoint.Set(0, 0, model.boxes[i].surface, model.boxes[i].piece);\n\t}\n\n\tCalculateTrianglePlanes(&model);\n\tVuTriangle vutri;\n\tCColTriangle *lasttri = nil;\n\tfor(i = 0; i < model.numTriangles; i++){\n\t\tif(ignoreSeeThrough && IsSeeThrough(model.triangles[i].surface)) continue;\n\t\tif(ignoreShootThrough && IsShootThrough(model.triangles[i].surface)) continue;\n\n\t\tCColTriangle *tri = &model.triangles[i];\n\t\tmodel.vertices[tri->a].Unpack(vutri.v0);\n\t\tmodel.vertices[tri->b].Unpack(vutri.v1);\n\t\tmodel.vertices[tri->c].Unpack(vutri.v2);\n\t\tmodel.trianglePlanes[i].Unpack(vutri.plane);\n\n\t\tLineToTriangleCollisionCompressed(newline[0], newline[1], vutri);\n\t\tlasttri = tri;\n\t\tbreak;\n\t}\n#ifdef FIX_BUGS\n\t// no need to check first again\n\ti++;\n#endif\n\tCVuVector pnt, normal;\n\tfloat dist;\n\tfor(; i < model.numTriangles; i++){\n\t\tif(ignoreSeeThrough && IsSeeThrough(model.triangles[i].surface)) continue;\n\t\tif(ignoreShootThrough && IsShootThrough(model.triangles[i].surface)) continue;\n\n\t\tCColTriangle *tri = &model.triangles[i];\n\t\tmodel.vertices[tri->a].Unpack(vutri.v0);\n\t\tmodel.vertices[tri->b].Unpack(vutri.v1);\n\t\tmodel.vertices[tri->c].Unpack(vutri.v2);\n\t\tmodel.trianglePlanes[i].Unpack(vutri.plane);\n\n\t\tif(GetVUresult(pnt, normal, dist))\n\t\t\tif(dist < coldist){\n\t\t\t\tpoint.point = pnt;\n\t\t\t\tpoint.normal = normal;\n\t\t\t\tpoint.Set(0, 0, lasttri->surface, 0);\n\t\t\t\tcoldist = dist;\n\t\t\t}\n\n\t\tLineToTriangleCollisionCompressed(newline[0], newline[1], vutri);\n\t\tlasttri = tri;\n\t}\n\tif(lasttri && GetVUresult(pnt, normal, dist))\n\t\tif(dist < coldist){\n\t\t\tpoint.point = pnt;\n\t\t\tpoint.normal = normal;\n\t\t\tpoint.Set(0, 0, lasttri->surface, 0);\n\t\t\tcoldist = dist;\n\t\t}\n\n\n\tif(coldist < 1.0f){\n\t\tpoint.point = matrix * point.point;\n\t\tpoint.normal = Multiply3x3(matrix, point.normal);\n\t\tmindist *= coldist;\n\t\treturn true;\n\t}\n\treturn false;\n#else\n\tstatic CMatrix matTransform;\n\tint i;\n\n\t// transform line to model space\n\tInvert(matrix, matTransform);\n\tCColLine newline(matTransform * line.p0, matTransform * line.p1);\n\n\t// If we don't intersect with the bounding box, no chance on the rest\n\tif(!TestLineBox(newline, model.boundingBox))\n\t\treturn false;\n\n\tfloat coldist = mindist;\n\tfor(i = 0; i < model.numSpheres; i++){\n\t\tif(ignoreSeeThrough && IsSeeThrough(model.spheres[i].surface)) continue;\n\t\tif(ignoreShootThrough && IsShootThrough(model.spheres[i].surface)) continue;\n\t\tProcessLineSphere(newline, model.spheres[i], point, coldist);\n\t}\n\n\tfor(i = 0; i < model.numBoxes; i++){\n\t\tif(ignoreSeeThrough && IsSeeThrough(model.boxes[i].surface)) continue;\n\t\tif(ignoreShootThrough && IsShootThrough(model.boxes[i].surface)) continue;\n\t\tProcessLineBox(newline, model.boxes[i], point, coldist);\n\t}\n\n\tCalculateTrianglePlanes(&model);\n\tfor(i = 0; i < model.numTriangles; i++){\n\t\tif(ignoreSeeThrough && IsSeeThrough(model.triangles[i].surface)) continue;\n\t\tif(ignoreShootThrough && IsShootThrough(model.triangles[i].surface)) continue;\n\t\tProcessLineTriangle(newline, model.vertices, model.triangles[i], model.trianglePlanes[i], point, coldist);\n\t}\n\n\tif(coldist < mindist){\n\t\tpoint.point = matrix * point.point;\n\t\tpoint.normal = Multiply3x3(matrix, point.normal);\n\t\tmindist = coldist;\n\t\treturn true;\n\t}\n\treturn false;\n#endif\n}\n\nbool\nCCollision::ProcessVerticalLine(const CColLine &line,\n\tconst CMatrix &matrix, CColModel &model,\n\tCColPoint &point, float &mindist, bool ignoreSeeThrough, bool ignoreShootThrough, CStoredCollPoly *poly)\n{\n#ifdef VU_COLLISION\n\tstatic CStoredCollPoly TempStoredPoly;\n\tCMatrix matTransform;\n\tint i;\n\n\t// transform line to model space\n\tInvert(matrix, matTransform);\n\tCVuVector newline[2];\n\tTransformPoints(newline, 2, matTransform, &line.p0, sizeof(CColLine)/2);\n\n\tif(mindist < 1.0f)\n\t\tnewline[1] = newline[0] + (newline[1] - newline[0])*mindist;\n\n\tif(!TestLineBox(*(CColLine*)newline, model.boundingBox))\n\t\treturn false;\n\n\tfloat coldist = 1.0f;\n\tfor(i = 0; i < model.numSpheres; i++){\n\t\tif(ignoreSeeThrough && IsSeeThroughVertical(model.spheres[i].surface)) continue;\n\t\tif(ProcessLineSphere(*(CColLine*)newline, model.spheres[i], point, coldist))\n\t\t\tpoint.Set(0, 0, model.spheres[i].surface, model.spheres[i].piece);\n\t}\n\n\tfor(i = 0; i < model.numBoxes; i++){\n\t\tif(ignoreSeeThrough && IsSeeThroughVertical(model.boxes[i].surface)) continue;\n\t\tif(ProcessLineBox(*(CColLine*)newline, model.boxes[i], point, coldist))\n\t\t\tpoint.Set(0, 0, model.boxes[i].surface, model.boxes[i].piece);\n\t}\n\n\tCalculateTrianglePlanes(&model);\n\tTempStoredPoly.valid = false;\n\tif(model.numTriangles){\n\t\tbool registeredCol;\n\t\tCColTriangle *lasttri = nil;\n\t\tVuTriangle vutri;\n\t\tfor(i = 0; i < model.numTriangles; i++){\n\t\t\tif(ignoreSeeThrough && IsSeeThroughVertical(model.triangles[i].surface)) continue;\n\n\t\t\tCColTriangle *tri = &model.triangles[i];\n\t\t\tmodel.vertices[tri->a].Unpack(vutri.v0);\n\t\t\tmodel.vertices[tri->b].Unpack(vutri.v1);\n\t\t\tmodel.vertices[tri->c].Unpack(vutri.v2);\n\t\t\tmodel.trianglePlanes[i].Unpack(vutri.plane);\n\n\t\t\tLineToTriangleCollisionCompressed(newline[0], newline[1], vutri);\n\t\t\tlasttri = tri;\n\t\t\tbreak;\n\t\t}\n#ifdef FIX_BUGS\n\t\t// no need to check first again\n\t\ti++;\n#endif\n\t\tCVuVector pnt, normal;\n\t\tfloat dist;\n\t\tfor(; i < model.numTriangles; i++){\n\t\t\tif(ignoreSeeThrough && IsSeeThroughVertical(model.triangles[i].surface)) continue;\n\n\t\t\tCColTriangle *tri = &model.triangles[i];\n\t\t\tmodel.vertices[tri->a].Unpack(vutri.v0);\n\t\t\tmodel.vertices[tri->b].Unpack(vutri.v1);\n\t\t\tmodel.vertices[tri->c].Unpack(vutri.v2);\n\t\t\tmodel.trianglePlanes[i].Unpack(vutri.plane);\n\n\t\t\tif(GetVUresult(pnt, normal, dist)){\n\t\t\t\tif(dist < coldist){\n\t\t\t\t\tpoint.point = pnt;\n\t\t\t\t\tpoint.normal = normal;\n\t\t\t\t\tpoint.Set(0, 0, lasttri->surface, 0);\n\t\t\t\t\tcoldist = dist;\n\t\t\t\t\tregisteredCol = true;\n\t\t\t\t}else\n\t\t\t\t\tregisteredCol = false;\n\t\t\t}else\n\t\t\t\tregisteredCol = false;\n\n\t\t\tif(registeredCol){\n\t\t\t\tTempStoredPoly.verts[0] = model.vertices[lasttri->a].Get();\n\t\t\t\tTempStoredPoly.verts[1] = model.vertices[lasttri->b].Get();\n\t\t\t\tTempStoredPoly.verts[2] = model.vertices[lasttri->c].Get();\n\t\t\t\tTempStoredPoly.valid = true;\n\t\t\t}\n\n\t\t\tLineToTriangleCollisionCompressed(newline[0], newline[1], vutri);\n\t\t\tlasttri = tri;\n\t\t}\n\t\tif(lasttri && GetVUresult(pnt, normal, dist)){\n\t\t\tif(dist < coldist){\n\t\t\t\tpoint.point = pnt;\n\t\t\t\tpoint.normal = normal;\n\t\t\t\tpoint.Set(0, 0, lasttri->surface, 0);\n\t\t\t\tcoldist = dist;\n\t\t\t\tregisteredCol = true;\n\t\t\t}else\n\t\t\t\tregisteredCol = false;\n\t\t}else\n\t\t\tregisteredCol = false;\n\n\t\tif(registeredCol){\n\t\t\tTempStoredPoly.verts[0] = model.vertices[lasttri->a].Get();\n\t\t\tTempStoredPoly.verts[1] = model.vertices[lasttri->b].Get();\n\t\t\tTempStoredPoly.verts[2] = model.vertices[lasttri->c].Get();\n\t\t\tTempStoredPoly.valid = true;\n\t\t}\n\t}\n\n\tif(coldist < 1.0f){\n\t\tpoint.point = matrix * point.point;\n\t\tpoint.normal = Multiply3x3(matrix, point.normal);\n\t\tif(TempStoredPoly.valid && poly){\n\t\t\t*poly = TempStoredPoly;\n\t\t\tpoly->verts[0] = matrix * CVector(poly->verts[0]);\n\t\t\tpoly->verts[1] = matrix * CVector(poly->verts[1]);\n\t\t\tpoly->verts[2] = matrix * CVector(poly->verts[2]);\n\t\t}\n\t\tmindist *= coldist;\n\t\treturn true;\n\t}\n\treturn false;\n#else\n\tstatic CStoredCollPoly TempStoredPoly;\n\tint i;\n\n\t// transform line to model space\n\t// Why does the game seem to do this differently than above?\n\tCColLine newline(MultiplyInverse(matrix, line.p0), MultiplyInverse(matrix, line.p1));\n\n\tif(!TestLineBox(newline, model.boundingBox))\n\t\treturn false;\n\n\t// BUG? is IsSeeThroughVertical really the right thing? also not checking shoot through\n\tfloat coldist = mindist;\n\tfor(i = 0; i < model.numSpheres; i++){\n\t\tif(ignoreSeeThrough && IsSeeThroughVertical(model.spheres[i].surface)) continue;\n\t\tProcessLineSphere(newline, model.spheres[i], point, coldist);\n\t}\n\n\tfor(i = 0; i < model.numBoxes; i++){\n\t\tif(ignoreSeeThrough && IsSeeThroughVertical(model.boxes[i].surface)) continue;\n\t\tProcessLineBox(newline, model.boxes[i], point, coldist);\n\t}\n\n\tCalculateTrianglePlanes(&model);\n\tTempStoredPoly.valid = false;\n\tfor(i = 0; i < model.numTriangles; i++){\n\t\tif(ignoreSeeThrough && IsSeeThroughVertical(model.triangles[i].surface)) continue;\n\t\tProcessLineTriangle(newline, model.vertices, model.triangles[i], model.trianglePlanes[i], point, coldist, &TempStoredPoly);\n\t}\n\n\tif(coldist < mindist){\n\t\tpoint.point = matrix * point.point;\n\t\tpoint.normal = Multiply3x3(matrix, point.normal);\n\t\tif(TempStoredPoly.valid && poly){\n\t\t\t*poly = TempStoredPoly;\n\t\t\tpoly->verts[0] = matrix * poly->verts[0];\n\t\t\tpoly->verts[1] = matrix * poly->verts[1];\n\t\t\tpoly->verts[2] = matrix * poly->verts[2];\n\t\t}\n\t\tmindist = coldist;\n\t\treturn true;\n\t}\n\treturn false;\n#endif\n}\n\nenum {\n\tMAXNUMSPHERES = 128,\n\tMAXNUMBOXES = 32,\n\tMAXNUMLINES = 16,\n\tMAXNUMTRIS = 600\n};\n\n#ifdef VU_COLLISION\n#ifdef GTA_PS2\n#define SPR(off) ((uint8*)(0x70000000 + (off)))\n#else\nstatic uint8 fakeSPR[16*1024];\n#define SPR(off) ((uint8*)(fakeSPR + (off)))\n#endif\n#endif\n\n// This checks model A's spheres and lines against model B's spheres, boxes and triangles.\n// Returns the number of A's spheres that collide.\n// Returned ColPoints are in world space.\n// NB: only vehicles can have col models with lines, exactly 4, one for each wheel\nint32\nCCollision::ProcessColModels(const CMatrix &matrixA, CColModel &modelA,\n\tconst CMatrix &matrixB, CColModel &modelB,\n\tCColPoint *spherepoints, CColPoint *linepoints, float *linedists)\n{\n#ifdef VU_COLLISION\n\tCVuVector *aSpheresA = (CVuVector*)SPR(0x0000);\n\tCVuVector *aSpheresB = (CVuVector*)SPR(0x0800);\n\tCVuVector *aLinesA = (CVuVector*)SPR(0x1000);\n\tint32 *aSphereIndicesA = (int32*)SPR(0x1200);\n\tint32 *aSphereIndicesB = (int32*)SPR(0x1400);\n\tint32 *aBoxIndicesB = (int32*)SPR(0x1600);\n\tint32 *aTriangleIndicesB = (int32*)SPR(0x1680);\n\tbool *aCollided = (bool*)SPR(0x1FE0);\n\tCMatrix &matAB = *(CMatrix*)SPR(0x1FF0);\n\tCMatrix &matBA = *(CMatrix*)SPR(0x2040);\n\tint i, j, k;\n\n\t// From model A space to model B space\n\tInvert(matrixB, matAB);\n\tmatAB *= matrixA;\n\n\tCVuVector bsphereAB;\t// bounding sphere of A in B space\n\tTransformPoint(bsphereAB, matAB, modelA.boundingSphere.center);\t// inlined\n\tbsphereAB.w = modelA.boundingSphere.radius;\n\tif(!TestSphereBox(*(CColSphere*)&bsphereAB, modelB.boundingBox))\n\t\treturn 0;\n\n\t// transform modelA's spheres and lines to B space\n\tTransformPoints(aSpheresA, modelA.numSpheres, matAB, &modelA.spheres->center, sizeof(CColSphere));\n\tfor(i = 0; i < modelA.numSpheres; i++)\n\t\taSpheresA[i].w = modelA.spheres[i].radius;\n\tTransformPoints(aLinesA, modelA.numLines*2, matAB, &modelA.lines->p0, sizeof(CColLine)/2);\n\n\t// Test them against model B's bounding volumes\n\tint numSpheresA = 0;\n\tfor(i = 0; i < modelA.numSpheres; i++)\n\t\tif(TestSphereBox(*(CColSphere*)&aSpheresA[i], modelB.boundingBox))\n\t\t\taSphereIndicesA[numSpheresA++] = i;\n\t// No collision\n\tif(numSpheresA == 0 && modelA.numLines == 0)\n\t\treturn 0;\n\n\n\t// B to A space\n\tInvert(matrixA, matBA);\n\tmatBA *= matrixB;\n\n\t// transform modelB's spheres to A space\n\tTransformPoints(aSpheresB, modelB.numSpheres, matBA, &modelB.spheres->center, sizeof(CColSphere));\n\tfor(i = 0; i < modelB.numSpheres; i++)\n\t\taSpheresB[i].w = modelB.spheres[i].radius;\n\n\t// Check model B against A's bounding volumes\n\tint numSpheresB = 0;\n\tint numBoxesB = 0;\n\tint numTrianglesB = 0;\n\tfor(i = 0; i < modelB.numSpheres; i++)\n\t\tif(TestSphereBox(*(CColSphere*)&aSpheresB[i], modelA.boundingBox))\n\t\t\taSphereIndicesB[numSpheresB++] = i;\n\tfor(i = 0; i < modelB.numBoxes; i++)\n\t\tif(TestSphereBox(*(CColSphere*)&bsphereAB, modelB.boxes[i]))\n\t\t\taBoxIndicesB[numBoxesB++] = i;\n\tCalculateTrianglePlanes(&modelB);\n\tif(modelB.numTriangles){\n\t\tVuTriangle vutri;\n\t\t// process the first triangle\n\t\tCColTriangle *tri = &modelB.triangles[0];\n\t\tmodelB.vertices[tri->a].Unpack(vutri.v0);\n\t\tmodelB.vertices[tri->b].Unpack(vutri.v1);\n\t\tmodelB.vertices[tri->c].Unpack(vutri.v2);\n\t\tmodelB.trianglePlanes[0].Unpack(vutri.plane);\n\n\t\tSphereToTriangleCollisionCompressed(bsphereAB, vutri);\n\n\t\tfor(i = 1; i < modelB.numTriangles; i++){\n\t\t\t// set up the next triangle while VU0 is running\n\t\t\ttri = &modelB.triangles[i];\n\t\t\tmodelB.vertices[tri->a].Unpack(vutri.v0);\n\t\t\tmodelB.vertices[tri->b].Unpack(vutri.v1);\n\t\t\tmodelB.vertices[tri->c].Unpack(vutri.v2);\n\t\t\tmodelB.trianglePlanes[i].Unpack(vutri.plane);\n\n\t\t\t// check previous result\n\t\t\tif(GetVUresult())\n\t\t\t\taTriangleIndicesB[numTrianglesB++] = i-1;\n\n\t\t\t// kick off this one\n\t\t\tSphereToTriangleCollisionCompressed(bsphereAB, vutri);\n\t\t}\n\n\t\t// check last result\n\t\tif(GetVUresult())\n\t\t\taTriangleIndicesB[numTrianglesB++] = i-1;\n\t}\n\t// No collision\n\tif(numSpheresB == 0 && numBoxesB == 0 && numTrianglesB == 0)\n\t\treturn 0;\n\n\t// We now have the collision volumes in A and B that are worth processing.\n\n\t// Process A's spheres against B's collision volumes\n\tint numCollisions = 0;\n\tspherepoints[numCollisions].depth = -1.0f;\n\tfor(i = 0; i < numSpheresA; i++){\n\t\tfloat coldist = 1.0e24f;\n\t\tbool hasCollided = false;\n\t\tCColSphere *sphA = &modelA.spheres[aSphereIndicesA[i]];\n\t\tCVuVector *vusphA = &aSpheresA[aSphereIndicesA[i]];\n\n\t\tfor(j = 0; j < numSpheresB; j++)\n\t\t\t// This actually looks like something was inlined here\n\t\t\tif(ProcessSphereSphere(*(CColSphere*)vusphA, modelB.spheres[aSphereIndicesB[j]],\n\t\t\t\t\tspherepoints[numCollisions], coldist)){\n\t\t\t\tspherepoints[numCollisions].Set(\n\t\t\t\t\tsphA->surface, sphA->piece,\n\t\t\t\t\tmodelB.spheres[aSphereIndicesB[j]].surface, modelB.spheres[aSphereIndicesB[j]].piece);\n\t\t\t\thasCollided = true;\n\t\t\t}\n\t\tfor(j = 0; j < numBoxesB; j++)\n\t\t\tif(ProcessSphereBox(*(CColSphere*)vusphA, modelB.boxes[aBoxIndicesB[j]],\n\t\t\t\t\tspherepoints[numCollisions], coldist)){\n\t\t\t\tspherepoints[numCollisions].Set(\n\t\t\t\t\tsphA->surface, sphA->piece,\n\t\t\t\t\tmodelB.boxes[aBoxIndicesB[j]].surface, modelB.boxes[aBoxIndicesB[j]].piece);\n\t\t\t\thasCollided = true;\n\t\t\t}\n\t\tif(numTrianglesB){\n\t\t\tCVuVector point, normal;\n\t\t\tfloat depth;\n\t\t\tbool registeredCol;\n\t\t\tCColTriangle *lasttri;\n\n\t\t\tVuTriangle vutri;\n\t\t\t// process the first triangle\n\t\t\tk = aTriangleIndicesB[0];\n\t\t\tCColTriangle *tri = &modelB.triangles[k];\n\t\t\tmodelB.vertices[tri->a].Unpack(vutri.v0);\n\t\t\tmodelB.vertices[tri->b].Unpack(vutri.v1);\n\t\t\tmodelB.vertices[tri->c].Unpack(vutri.v2);\n\t\t\tmodelB.trianglePlanes[k].Unpack(vutri.plane);\n\n\t\t\tSphereToTriangleCollisionCompressed(*vusphA, vutri);\n\t\t\tlasttri = tri;\n\n\t\t\tfor(j = 1; j < numTrianglesB; j++){\n\t\t\t\tk = aTriangleIndicesB[j];\n\t\t\t\t// set up the next triangle while VU0 is running\n\t\t\t\ttri = &modelB.triangles[k];\n\t\t\t\tmodelB.vertices[tri->a].Unpack(vutri.v0);\n\t\t\t\tmodelB.vertices[tri->b].Unpack(vutri.v1);\n\t\t\t\tmodelB.vertices[tri->c].Unpack(vutri.v2);\n\t\t\t\tmodelB.trianglePlanes[k].Unpack(vutri.plane);\n\n\t\t\t\t// check previous result\n\t\t\t\t// TODO: this looks inlined but spherepoints[numCollisions] does not...\n\t\t\t\tif(GetVUresult(point, normal, depth)){\n\t\t\t\t\tdepth = sphA->radius - depth;\n\t\t\t\t\tif(depth > spherepoints[numCollisions].depth){\n\t\t\t\t\t\tspherepoints[numCollisions].point = point;\n\t\t\t\t\t\tspherepoints[numCollisions].normal = normal;\n\t\t\t\t\t\tspherepoints[numCollisions].Set(depth,\n\t\t\t\t\t\t\tsphA->surface, sphA->piece, lasttri->surface, 0);\n\t\t\t\t\t\tregisteredCol = true;\n\t\t\t\t\t}else\n\t\t\t\t\t\tregisteredCol = false;\n\t\t\t\t}else\n\t\t\t\t\tregisteredCol = false;\n\n\t\t\t\tif(registeredCol)\n\t\t\t\t\thasCollided = true;\n\n\t\t\t\t// kick off this one\n\t\t\t\tSphereToTriangleCollisionCompressed(*vusphA, vutri);\n\t\t\t\tlasttri = tri;\n\t\t\t}\n\n\t\t\t// check last result\n\t\t\t// TODO: this looks inlined but spherepoints[numCollisions] does not...\n\t\t\tif(GetVUresult(point, normal, depth)){\n\t\t\t\tdepth = sphA->radius - depth;\n\t\t\t\tif(depth > spherepoints[numCollisions].depth){\n\t\t\t\t\tspherepoints[numCollisions].point = point;\n\t\t\t\t\tspherepoints[numCollisions].normal = normal;\n\t\t\t\t\tspherepoints[numCollisions].Set(depth,\n\t\t\t\t\t\tsphA->surface, sphA->piece, lasttri->surface, 0);\n\t\t\t\t\tregisteredCol = true;\n\t\t\t\t}else\n\t\t\t\t\tregisteredCol = false;\n\t\t\t}else\n\t\t\t\tregisteredCol = false;\n\n\t\t\tif(registeredCol)\n\t\t\t\thasCollided = true;\n\t\t}\n\n\t\tif(hasCollided){\n\t\t\tnumCollisions++;\n\t\t\tif(numCollisions == MAX_COLLISION_POINTS)\n\t\t\t\tbreak;\n\t\t\tspherepoints[numCollisions].depth = -1.0f;\n\t\t}\n\t}\n\tfor(i = 0; i < numCollisions; i++){\n\t\t// TODO: both VU0 macros\n\t\tspherepoints[i].point = matrixB * spherepoints[i].point;\n\t\tspherepoints[i].normal = Multiply3x3(matrixB, spherepoints[i].normal);\n\t}\n\n\t// And the same thing for the lines in A\n\tfor(i = 0; i < modelA.numLines; i++){\n\t\taCollided[i] = false;\n\t\tCVuVector *lineA = &aLinesA[i*2];\n\n\t\tfor(j = 0; j < numSpheresB; j++)\n\t\t\tif(ProcessLineSphere(*(CColLine*)lineA, modelB.spheres[aSphereIndicesB[j]],\n\t\t\t\t\tlinepoints[i], linedists[i])){\n\t\t\t\tlinepoints[i].Set(0, 0,\n#ifdef FIX_BUGS\n\t\t\t\t\tmodelB.spheres[aSphereIndicesB[j]].surface, modelB.spheres[aSphereIndicesB[j]].piece);\n#else\n\t\t\t\t\tmodelB.spheres[j].surface, modelB.spheres[j].piece);\n#endif\n\t\t\t\taCollided[i] = true;\n\t\t\t}\n\t\tfor(j = 0; j < numBoxesB; j++)\n\t\t\tif(ProcessLineBox(*(CColLine*)lineA, modelB.boxes[aBoxIndicesB[j]],\n\t\t\t\t\tlinepoints[i], linedists[i])){\n\t\t\t\tlinepoints[i].Set(0, 0,\n\t\t\t\t\tmodelB.boxes[aBoxIndicesB[j]].surface, modelB.boxes[aBoxIndicesB[j]].piece);\n\t\t\t\taCollided[i] = true;\n\t\t\t}\n\t\tif(numTrianglesB){\n\t\t\tCVuVector point, normal;\n\t\t\tfloat dist;\n\t\t\tbool registeredCol;\n\t\t\tCColTriangle *lasttri;\n\n\t\t\tVuTriangle vutri;\n\t\t\t// process the first triangle\n\t\t\tk = aTriangleIndicesB[0];\n\t\t\tCColTriangle *tri = &modelB.triangles[k];\n\t\t\tmodelB.vertices[tri->a].Unpack(vutri.v0);\n\t\t\tmodelB.vertices[tri->b].Unpack(vutri.v1);\n\t\t\tmodelB.vertices[tri->c].Unpack(vutri.v2);\n\t\t\tmodelB.trianglePlanes[k].Unpack(vutri.plane);\n\n\t\t\tLineToTriangleCollisionCompressed(lineA[0], lineA[1], vutri);\n\t\t\tlasttri = tri;\n\n\t\t\tfor(j = 1; j < numTrianglesB; j++){\n\t\t\t\tk = aTriangleIndicesB[j];\n\t\t\t\t// set up the next triangle while VU0 is running\n\t\t\t\tCColTriangle *tri = &modelB.triangles[k];\n\t\t\t\tmodelB.vertices[tri->a].Unpack(vutri.v0);\n\t\t\t\tmodelB.vertices[tri->b].Unpack(vutri.v1);\n\t\t\t\tmodelB.vertices[tri->c].Unpack(vutri.v2);\n\t\t\t\tmodelB.trianglePlanes[k].Unpack(vutri.plane);\n\n\t\t\t\t// check previous result\n\t\t\t\t// TODO: this again somewhat looks inlined\n\t\t\t\tif(GetVUresult(point, normal, dist)){\n\t\t\t\t\tif(dist < linedists[i]){\n\t\t\t\t\t\tlinepoints[i].point = point;\n\t\t\t\t\t\tlinepoints[i].normal = normal;\n\t\t\t\t\t\tlinedists[i] = dist;\n\t\t\t\t\t\tlinepoints[i].Set(0, 0, lasttri->surface, 0);\n\t\t\t\t\t\tregisteredCol = true;\n\t\t\t\t\t}else\n\t\t\t\t\t\tregisteredCol = false;\n\t\t\t\t}else\n\t\t\t\t\tregisteredCol = false;\n\n\t\t\t\tif(registeredCol)\n\t\t\t\t\taCollided[i] = true;\n\n\t\t\t\t// kick of this one\n\t\t\t\tLineToTriangleCollisionCompressed(lineA[0], lineA[1], vutri);\n\t\t\t\tlasttri = tri;\n\t\t\t}\n\n\t\t\t// check last result\n\t\t\tif(GetVUresult(point, normal, dist)){\n\t\t\t\tif(dist < linedists[i]){\n\t\t\t\t\tlinepoints[i].point = point;\n\t\t\t\t\tlinepoints[i].normal = normal;\n\t\t\t\t\tlinedists[i] = dist;\n\t\t\t\t\tlinepoints[i].Set(0, 0, lasttri->surface, 0);\n\t\t\t\t\tregisteredCol = true;\n\t\t\t\t}else\n\t\t\t\t\tregisteredCol = false;\n\t\t\t}else\n\t\t\t\tregisteredCol = false;\n\n\t\t\tif(registeredCol)\n\t\t\t\taCollided[i] = true;\n\t\t}\n\n\t\tif(aCollided[i]){\n\t\t\t// TODO: both VU0 macros\n\t\t\tlinepoints[i].point = matrixB * linepoints[i].point;\n\t\t\tlinepoints[i].normal = Multiply3x3(matrixB, linepoints[i].normal);\n\t\t}\n\t}\n\n\treturn numCollisions;\t// sphere collisions\n#else\n\tstatic int aSphereIndicesA[MAXNUMSPHERES];\n\tstatic int aLineIndicesA[MAXNUMLINES];\n\tstatic int aSphereIndicesB[MAXNUMSPHERES];\n\tstatic int aBoxIndicesB[MAXNUMBOXES];\n\tstatic int aTriangleIndicesB[MAXNUMTRIS];\n\tstatic bool aCollided[MAXNUMLINES];\n\tstatic CColSphere aSpheresA[MAXNUMSPHERES];\n\tstatic CColLine aLinesA[MAXNUMLINES];\n\tstatic CMatrix matAB, matBA;\n\tCColSphere s;\n\tint i, j;\n\n\tassert(modelA.numSpheres <= MAXNUMSPHERES);\n\tassert(modelA.numLines <= MAXNUMLINES);\n\n\t// From model A space to model B space\n\tmatAB = Invert(matrixB, matAB);\n\tmatAB *= matrixA;\n\n\tCColSphere bsphereAB;\t// bounding sphere of A in B space\n\tbsphereAB.radius = modelA.boundingSphere.radius;\n\tbsphereAB.center = matAB * modelA.boundingSphere.center;\n\tif(!TestSphereBox(bsphereAB, modelB.boundingBox))\n\t\treturn 0;\n\t// B to A space\n\tmatBA = Invert(matrixA, matBA);\n\tmatBA *= matrixB;\n\n\t// transform modelA's spheres and lines to B space\n\tfor(i = 0; i < modelA.numSpheres; i++){\n\t\tCColSphere &s = modelA.spheres[i];\n\t\taSpheresA[i].Set(s.radius, matAB * s.center, s.surface, s.piece);\n\t}\n\tfor(i = 0; i < modelA.numLines; i++)\n\t\taLinesA[i].Set(matAB * modelA.lines[i].p0, matAB * modelA.lines[i].p1);\n\n\t// Test them against model B's bounding volumes\n\tint numSpheresA = 0;\n\tint numLinesA = 0;\n\tfor(i = 0; i < modelA.numSpheres; i++)\n\t\tif(TestSphereBox(aSpheresA[i], modelB.boundingBox))\n\t\t\taSphereIndicesA[numSpheresA++] = i;\n\t// no actual check???\n\tfor(i = 0; i < modelA.numLines; i++)\n\t\taLineIndicesA[numLinesA++] = i;\n\t// No collision\n\tif(numSpheresA == 0 && numLinesA == 0)\n\t\treturn 0;\n\n\t// Check model B against A's bounding volumes\n\tint numSpheresB = 0;\n\tint numBoxesB = 0;\n\tint numTrianglesB = 0;\n\tfor(i = 0; i < modelB.numSpheres; i++){\n\t\ts.radius = modelB.spheres[i].radius;\n\t\ts.center = matBA * modelB.spheres[i].center;\n\t\tif(TestSphereBox(s, modelA.boundingBox))\n\t\t\taSphereIndicesB[numSpheresB++] = i;\n\t}\n\tfor(i = 0; i < modelB.numBoxes; i++)\n\t\tif(TestSphereBox(bsphereAB, modelB.boxes[i]))\n\t\t\taBoxIndicesB[numBoxesB++] = i;\n\tCalculateTrianglePlanes(&modelB);\n\tfor(i = 0; i < modelB.numTriangles; i++)\n\t\tif(TestSphereTriangle(bsphereAB, modelB.vertices, modelB.triangles[i], modelB.trianglePlanes[i]))\n\t\t\taTriangleIndicesB[numTrianglesB++] = i;\n\tassert(numSpheresB <= MAXNUMSPHERES);\n\tassert(numBoxesB <= MAXNUMBOXES);\n\tassert(numTrianglesB <= MAXNUMTRIS);\n\t// No collision\n\tif(numSpheresB == 0 && numBoxesB == 0 && numTrianglesB == 0)\n\t\treturn 0;\n\n\t// We now have the collision volumes in A and B that are worth processing.\n\n\t// Process A's spheres against B's collision volumes\n\tint numCollisions = 0;\n\tfor(i = 0; i < numSpheresA; i++){\n\t\tfloat coldist = 1.0e24f;\n\t\tbool hasCollided = false;\n\n\t\tfor(j = 0; j < numSpheresB; j++)\n\t\t\thasCollided |= ProcessSphereSphere(\n\t\t\t\taSpheresA[aSphereIndicesA[i]],\n\t\t\t\tmodelB.spheres[aSphereIndicesB[j]],\n\t\t\t\tspherepoints[numCollisions], coldist);\n\t\tfor(j = 0; j < numBoxesB; j++)\n\t\t\thasCollided |= ProcessSphereBox(\n\t\t\t\taSpheresA[aSphereIndicesA[i]],\n\t\t\t\tmodelB.boxes[aBoxIndicesB[j]],\n\t\t\t\tspherepoints[numCollisions], coldist);\n\t\tfor(j = 0; j < numTrianglesB; j++)\n\t\t\thasCollided |= ProcessSphereTriangle(\n\t\t\t\taSpheresA[aSphereIndicesA[i]],\n\t\t\t\tmodelB.vertices,\n\t\t\t\tmodelB.triangles[aTriangleIndicesB[j]],\n\t\t\t\tmodelB.trianglePlanes[aTriangleIndicesB[j]],\n\t\t\t\tspherepoints[numCollisions], coldist);\n\n\t\tif(hasCollided)\n\t\t\tnumCollisions++;\n\t}\n\tfor(i = 0; i < numCollisions; i++){\n\t\tspherepoints[i].point = matrixB * spherepoints[i].point;\n\t\tspherepoints[i].normal = Multiply3x3(matrixB, spherepoints[i].normal);\n\t}\n\n\t// And the same thing for the lines in A\n\tfor(i = 0; i < numLinesA; i++){\n\t\taCollided[i] = false;\n\n\t\tfor(j = 0; j < numSpheresB; j++)\n\t\t\taCollided[i] |= ProcessLineSphere(\n\t\t\t\taLinesA[aLineIndicesA[i]],\n\t\t\t\tmodelB.spheres[aSphereIndicesB[j]],\n\t\t\t\tlinepoints[aLineIndicesA[i]],\n\t\t\t\tlinedists[aLineIndicesA[i]]);\n\t\tfor(j = 0; j < numBoxesB; j++)\n\t\t\taCollided[i] |= ProcessLineBox(\n\t\t\t\taLinesA[aLineIndicesA[i]],\n\t\t\t\tmodelB.boxes[aBoxIndicesB[j]],\n\t\t\t\tlinepoints[aLineIndicesA[i]],\n\t\t\t\tlinedists[aLineIndicesA[i]]);\n\t\tfor(j = 0; j < numTrianglesB; j++)\n\t\t\taCollided[i] |= ProcessLineTriangle(\n\t\t\t\taLinesA[aLineIndicesA[i]],\n\t\t\t\tmodelB.vertices,\n\t\t\t\tmodelB.triangles[aTriangleIndicesB[j]],\n\t\t\t\tmodelB.trianglePlanes[aTriangleIndicesB[j]],\n\t\t\t\tlinepoints[aLineIndicesA[i]],\n\t\t\t\tlinedists[aLineIndicesA[i]]);\n\t}\n\tfor(i = 0; i < numLinesA; i++)\n\t\tif(aCollided[i]){\n\t\t\tj = aLineIndicesA[i];\n\t\t\tlinepoints[j].point = matrixB * linepoints[j].point;\n\t\t\tlinepoints[j].normal = Multiply3x3(matrixB, linepoints[j].normal);\n\t\t}\n\n\treturn numCollisions;\t// sphere collisions\n#endif\n}\n\n\n//\n// Misc\n//\n\nfloat\nCCollision::DistToLine(const CVector *l0, const CVector *l1, const CVector *point)\n{\n\tfloat lensq = (*l1 - *l0).MagnitudeSqr();\n\tfloat dot = DotProduct(*point - *l0, *l1 - *l0);\n\t// Between 0 and len we're above the line.\n\t// if not, calculate distance to endpoint\n\tif(dot <= 0.0f) return (*point - *l0).Magnitude();\n\tif(dot >= lensq) return (*point - *l1).Magnitude();\n\t// distance to line\n\tfloat distSqr = (*point - *l0).MagnitudeSqr() - dot * dot / lensq;\n\tif(distSqr <= 0.f) return 0.f;\n\treturn Sqrt(distSqr);\n}\n\n// same as above but also return the point on the line\nfloat\nCCollision::DistToLine(const CVector *l0, const CVector *l1, const CVector *point, CVector &closest)\n{\n\tfloat lensq = (*l1 - *l0).MagnitudeSqr();\n\tfloat dot = DotProduct(*point - *l0, *l1 - *l0);\n\t// find out which point we're closest to\n\tif(dot <= 0.0f)\n\t\tclosest = *l0;\n\telse if(dot >= lensq)\n\t\tclosest = *l1;\n\telse\n\t\tclosest = *l0 + (*l1 - *l0)*(dot/lensq);\n\t// this is the distance\n\treturn (*point - closest).Magnitude();\n}\n\nvoid\nCCollision::CalculateTrianglePlanes(CColModel *model)\n{\n\tassert(model);\n\tif(model->numTriangles == 0)\n\t\treturn;\n\n\tCLink<CColModel*> *lptr;\n\tif(model->trianglePlanes){\n\t\t// re-insert at front so it's not removed again soon\n\t\tlptr = model->GetLinkPtr();\n\t\tlptr->Remove();\n\t\tms_colModelCache.head.Insert(lptr);\n\t}else{\n\t\tlptr = ms_colModelCache.Insert(model);\n\t\tif(lptr == nil){\n\t\t\t// make room if we have to, remove last in list\n\t\t\tlptr = ms_colModelCache.tail.prev;\n\t\t\tassert(lptr);\n\t\t\tassert(lptr->item);\n\t\t\tlptr->item->RemoveTrianglePlanes();\n\t\t\tms_colModelCache.Remove(lptr);\n\t\t\t// now this cannot fail\n\t\t\tlptr = ms_colModelCache.Insert(model);\n\t\t\tassert(lptr);\n\t\t}\n\t\tmodel->CalculateTrianglePlanes();\n\t\tmodel->SetLinkPtr(lptr);\n\t}\n}\n\nvoid\nCCollision::RemoveTrianglePlanes(CColModel *model)\n{\n\tif(model->trianglePlanes){\n\t\tms_colModelCache.Remove(model->GetLinkPtr());\n\t\tmodel->RemoveTrianglePlanes();\n\t}\n}\n\nvoid\nCCollision::DrawColModel(const CMatrix &mat, const CColModel &colModel)\n{\n\tint i;\n\tCVector min, max;\n\tCVector verts[8];\n\tCVector c;\n\tfloat r;\n\n\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);\n\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);\n\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);\n\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);\n\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil);\n\n\tmin = colModel.boundingBox.min;\n\tmax = colModel.boundingBox.max;\n\n\tverts[0] = mat * CVector(min.x, min.y, min.z);\n\tverts[1] = mat * CVector(min.x, min.y, max.z);\n\tverts[2] = mat * CVector(min.x, max.y, min.z);\n\tverts[3] = mat * CVector(min.x, max.y, max.z);\n\tverts[4] = mat * CVector(max.x, min.y, min.z);\n\tverts[5] = mat * CVector(max.x, min.y, max.z);\n\tverts[6] = mat * CVector(max.x, max.y, min.z);\n\tverts[7] = mat * CVector(max.x, max.y, max.z);\n\n\tCLines::RenderLineWithClipping(\n\t\tverts[0].x, verts[0].y, verts[0].z,\n\t\tverts[1].x, verts[1].y, verts[1].z,\n\t\t0xFF0000FF, 0xFF0000FF);\n\tCLines::RenderLineWithClipping(\n\t\tverts[1].x, verts[1].y, verts[1].z,\n\t\tverts[3].x, verts[3].y, verts[3].z,\n\t\t0xFF0000FF, 0xFF0000FF);\n\tCLines::RenderLineWithClipping(\n\t\tverts[3].x, verts[3].y, verts[3].z,\n\t\tverts[2].x, verts[2].y, verts[2].z,\n\t\t0xFF0000FF, 0xFF0000FF);\n\tCLines::RenderLineWithClipping(\n\t\tverts[2].x, verts[2].y, verts[2].z,\n\t\tverts[0].x, verts[0].y, verts[0].z,\n\t\t0xFF0000FF, 0xFF0000FF);\n\n\tCLines::RenderLineWithClipping(\n\t\tverts[4].x, verts[4].y, verts[4].z,\n\t\tverts[5].x, verts[5].y, verts[5].z,\n\t\t0xFF0000FF, 0xFF0000FF);\n\tCLines::RenderLineWithClipping(\n\t\tverts[5].x, verts[5].y, verts[5].z,\n\t\tverts[7].x, verts[7].y, verts[7].z,\n\t\t0xFF0000FF, 0xFF0000FF);\n\tCLines::RenderLineWithClipping(\n\t\tverts[7].x, verts[7].y, verts[7].z,\n\t\tverts[6].x, verts[6].y, verts[6].z,\n\t\t0xFF0000FF, 0xFF0000FF);\n\tCLines::RenderLineWithClipping(\n\t\tverts[6].x, verts[6].y, verts[6].z,\n\t\tverts[4].x, verts[4].y, verts[4].z,\n\t\t0xFF0000FF, 0xFF0000FF);\n\n\tCLines::RenderLineWithClipping(\n\t\tverts[0].x, verts[0].y, verts[0].z,\n\t\tverts[4].x, verts[4].y, verts[4].z,\n\t\t0xFF0000FF, 0xFF0000FF);\n\tCLines::RenderLineWithClipping(\n\t\tverts[1].x, verts[1].y, verts[1].z,\n\t\tverts[5].x, verts[5].y, verts[5].z,\n\t\t0xFF0000FF, 0xFF0000FF);\n\tCLines::RenderLineWithClipping(\n\t\tverts[2].x, verts[2].y, verts[2].z,\n\t\tverts[6].x, verts[6].y, verts[6].z,\n\t\t0xFF0000FF, 0xFF0000FF);\n\tCLines::RenderLineWithClipping(\n\t\tverts[3].x, verts[3].y, verts[3].z,\n\t\tverts[7].x, verts[7].y, verts[7].z,\n\t\t0xFF0000FF, 0xFF0000FF);\n\n\tfor(i = 0; i < colModel.numSpheres; i++){\n\t\tc = mat * colModel.spheres[i].center;\n\t\tr = colModel.spheres[i].radius;\n\n\t\tCLines::RenderLineWithClipping(\n\t\t\tc.x,   c.y,   c.z-r,\n\t\t\tc.x-r, c.y-r, c.z,\n\t\t\t0xFF00FFFF, 0xFF00FFFF);\n\t\tCLines::RenderLineWithClipping(\n\t\t\tc.x,   c.y,   c.z-r,\n\t\t\tc.x-r, c.y+r, c.z,\n\t\t\t0xFF00FFFF, 0xFF00FFFF);\n\t\tCLines::RenderLineWithClipping(\n\t\t\tc.x,   c.y,   c.z-r,\n\t\t\tc.x+r, c.y-r, c.z,\n\t\t\t0xFF00FFFF, 0xFF00FFFF);\n\t\tCLines::RenderLineWithClipping(\n\t\t\tc.x,   c.y,   c.z-r,\n\t\t\tc.x+r, c.y+r, c.z,\n\t\t\t0xFF00FFFF, 0xFF00FFFF);\n\t\tCLines::RenderLineWithClipping(\n\t\t\tc.x-r, c.y-r, c.z,\n\t\t\tc.x,   c.y,   c.z+r,\n\t\t\t0xFF00FFFF, 0xFF00FFFF);\n\t\tCLines::RenderLineWithClipping(\n\t\t\tc.x-r, c.y+r, c.z,\n\t\t\tc.x,   c.y,   c.z+r,\n\t\t\t0xFF00FFFF, 0xFF00FFFF);\n\t\tCLines::RenderLineWithClipping(\n\t\t\tc.x+r, c.y-r, c.z,\n\t\t\tc.x,   c.y,   c.z+r,\n\t\t\t0xFF00FFFF, 0xFF00FFFF);\n\t\tCLines::RenderLineWithClipping(\n\t\t\tc.x+r, c.y+r, c.z,\n\t\t\tc.x,   c.y,   c.z+r,\n\t\t\t0xFF00FFFF, 0xFF00FFFF);\n\t}\n\n\tfor(i = 0; i < colModel.numLines; i++){\n\t\tverts[0] = colModel.lines[i].p0;\n\t\tverts[1] = colModel.lines[i].p1;\n\n\t\tverts[0] = mat * verts[0];\n\t\tverts[1] = mat * verts[1];\n\n\t\tCLines::RenderLineWithClipping(\n\t\t\tverts[0].x, verts[0].y, verts[0].z,\n\t\t\tverts[1].x, verts[1].y, verts[1].z,\n\t\t\t0x00FFFFFF, 0x00FFFFFF);\n\t}\n\n\tfor(i = 0; i < colModel.numBoxes; i++){\n\t\tmin = colModel.boxes[i].min;\n\t\tmax = colModel.boxes[i].max;\n\n\t\tverts[0] = mat * CVector(min.x, min.y, min.z);\n\t\tverts[1] = mat * CVector(min.x, min.y, max.z);\n\t\tverts[2] = mat * CVector(min.x, max.y, min.z);\n\t\tverts[3] = mat * CVector(min.x, max.y, max.z);\n\t\tverts[4] = mat * CVector(max.x, min.y, min.z);\n\t\tverts[5] = mat * CVector(max.x, min.y, max.z);\n\t\tverts[6] = mat * CVector(max.x, max.y, min.z);\n\t\tverts[7] = mat * CVector(max.x, max.y, max.z);\n\n\t\tCLines::RenderLineWithClipping(\n\t\t\tverts[0].x, verts[0].y, verts[0].z,\n\t\t\tverts[1].x, verts[1].y, verts[1].z,\n\t\t\t0xFFFFFFFF, 0xFFFFFFFF);\n\t\tCLines::RenderLineWithClipping(\n\t\t\tverts[1].x, verts[1].y, verts[1].z,\n\t\t\tverts[3].x, verts[3].y, verts[3].z,\n\t\t\t0xFFFFFFFF, 0xFFFFFFFF);\n\t\tCLines::RenderLineWithClipping(\n\t\t\tverts[3].x, verts[3].y, verts[3].z,\n\t\t\tverts[2].x, verts[2].y, verts[2].z,\n\t\t\t0xFFFFFFFF, 0xFFFFFFFF);\n\t\tCLines::RenderLineWithClipping(\n\t\t\tverts[2].x, verts[2].y, verts[2].z,\n\t\t\tverts[0].x, verts[0].y, verts[0].z,\n\t\t\t0xFFFFFFFF, 0xFFFFFFFF);\n\n\t\tCLines::RenderLineWithClipping(\n\t\t\tverts[4].x, verts[4].y, verts[4].z,\n\t\t\tverts[5].x, verts[5].y, verts[5].z,\n\t\t\t0xFFFFFFFF, 0xFFFFFFFF);\n\t\tCLines::RenderLineWithClipping(\n\t\t\tverts[5].x, verts[5].y, verts[5].z,\n\t\t\tverts[7].x, verts[7].y, verts[7].z,\n\t\t\t0xFFFFFFFF, 0xFFFFFFFF);\n\t\tCLines::RenderLineWithClipping(\n\t\t\tverts[7].x, verts[7].y, verts[7].z,\n\t\t\tverts[6].x, verts[6].y, verts[6].z,\n\t\t\t0xFFFFFFFF, 0xFFFFFFFF);\n\t\tCLines::RenderLineWithClipping(\n\t\t\tverts[6].x, verts[6].y, verts[6].z,\n\t\t\tverts[4].x, verts[4].y, verts[4].z,\n\t\t\t0xFFFFFFFF, 0xFFFFFFFF);\n\n\t\tCLines::RenderLineWithClipping(\n\t\t\tverts[0].x, verts[0].y, verts[0].z,\n\t\t\tverts[4].x, verts[4].y, verts[4].z,\n\t\t\t0xFFFFFFFF, 0xFFFFFFFF);\n\t\tCLines::RenderLineWithClipping(\n\t\t\tverts[1].x, verts[1].y, verts[1].z,\n\t\t\tverts[5].x, verts[5].y, verts[5].z,\n\t\t\t0xFFFFFFFF, 0xFFFFFFFF);\n\t\tCLines::RenderLineWithClipping(\n\t\t\tverts[2].x, verts[2].y, verts[2].z,\n\t\t\tverts[6].x, verts[6].y, verts[6].z,\n\t\t\t0xFFFFFFFF, 0xFFFFFFFF);\n\t\tCLines::RenderLineWithClipping(\n\t\t\tverts[3].x, verts[3].y, verts[3].z,\n\t\t\tverts[7].x, verts[7].y, verts[7].z,\n\t\t\t0xFFFFFFFF, 0xFFFFFFFF);\n\t}\n\n\tfor(i = 0; i < colModel.numTriangles; i++){\n\t\tcolModel.GetTrianglePoint(verts[0], colModel.triangles[i].a);\n\t\tcolModel.GetTrianglePoint(verts[1], colModel.triangles[i].b);\n\t\tcolModel.GetTrianglePoint(verts[2], colModel.triangles[i].c);\n\t\tverts[0] = mat * verts[0];\n\t\tverts[1] = mat * verts[1];\n\t\tverts[2] = mat * verts[2];\n\t\tCLines::RenderLineWithClipping(\n\t\t\tverts[0].x, verts[0].y, verts[0].z,\n\t\t\tverts[1].x, verts[1].y, verts[1].z,\n\t\t\t0x00FF00FF, 0x00FF00FF);\n\t\tCLines::RenderLineWithClipping(\n\t\t\tverts[0].x, verts[0].y, verts[0].z,\n\t\t\tverts[2].x, verts[2].y, verts[2].z,\n\t\t\t0x00FF00FF, 0x00FF00FF);\n\t\tCLines::RenderLineWithClipping(\n\t\t\tverts[1].x, verts[1].y, verts[1].z,\n\t\t\tverts[2].x, verts[2].y, verts[2].z,\n\t\t\t0x00FF00FF, 0x00FF00FF);\n\t}\n\n\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);\n\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);\n\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);\n\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);\n\tRwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);\n}\n\nstatic void\nGetSurfaceColor(uint8 surf, uint8 &r, uint8 &g, uint8 &b)\n{\n\t// game doesn't do this\n\tr = 255;\n\tg = 128;\n\tb = 0;\n\n\tswitch(CSurfaceTable::GetAdhesionGroup(surf)){\n\tcase ADHESIVE_RUBBER:\n\t\tr = 255;\n\t\tg = 0;\n\t\tb = 0;\n\t\tbreak;\n\tcase ADHESIVE_HARD:\n\t\tr = 255;\n\t\tg = 255;\n\t\tb = 128;\n\t\tbreak;\n\tcase ADHESIVE_ROAD:\n\t\tr = 128;\n\t\tg = 128;\n\t\tb = 128;\n\t\tbreak;\n\tcase ADHESIVE_LOOSE:\n\t\tr = 0;\n\t\tg = 255;\n\t\tb = 0;\n\t\tbreak;\n\tcase ADHESIVE_SAND:\n\t\tr = 255;\n\t\tg = 128;\n\t\tb = 128;\n\t\tbreak;\n\tcase ADHESIVE_WET:\n\t\tr = 0;\n\t\tg = 0;\n\t\tb = 255;\n\t\tbreak;\n\t}\n\n\tif(surf == SURFACE_SAND || surf == SURFACE_SAND_BEACH){\n\t\tr = 255;\n\t\tg = 255;\n\t\tb = 0;\n\t}\n\n\tfloat f = (surf & 0xF)/32.0f + 0.5f;\n\tr *= f;\n\tg *= f;\n\tb *= f;\n\n\tif(surf == SURFACE_TRANSPARENT_CLOTH || surf == SURFACE_METAL_CHAIN_FENCE ||\n\t   surf == SURFACE_TRANSPARENT_STONE || surf == SURFACE_SCAFFOLD_POLE)\n\t\tif(CTimer::GetFrameCounter() & 1){\n\t\t\tr = 0;\n\t\t\tg = 0;\n\t\t\tb = 0;\n\t\t}\n}\n\nvoid\nCCollision::DrawColModel_Coloured(const CMatrix &mat, const CColModel &colModel, int32 id)\n{\n\tint i;\n\tint s;\n\tCVector verts[8];\n\tCVector min, max;\n\tuint8 r, g, b;\n\tRwImVertexIndex *iptr;\n\tRwIm3DVertex *vptr;\n\n\tRenderBuffer::ClearRenderBuffer();\n\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);\n\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);\n\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);\n\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);\n\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil);\n\n\tfor(i = 0; i < colModel.numTriangles; i++){\n\t\tcolModel.GetTrianglePoint(verts[0], colModel.triangles[i].a);\n\t\tcolModel.GetTrianglePoint(verts[1], colModel.triangles[i].b);\n\t\tcolModel.GetTrianglePoint(verts[2], colModel.triangles[i].c);\n\t\tverts[0] = mat * verts[0];\n\t\tverts[1] = mat * verts[1];\n\t\tverts[2] = mat * verts[2];\n\n\t\ts = colModel.triangles[i].surface;\n\t\tGetSurfaceColor(s, r, g, b);\n\n\t\tif(s > SURFACE_METAL_GATE){\n\t\t\tr = CGeneral::GetRandomNumber();\n\t\t\tg = CGeneral::GetRandomNumber();\n\t\t\tb = CGeneral::GetRandomNumber();\n\t\t\tprintf(\"Illegal surfacetype:%d on MI:%d\\n\", s, id);\n\t\t}\n\n\t\tRenderBuffer::StartStoring(6, 3, &iptr, &vptr);\n\t\tRwIm3DVertexSetRGBA(&vptr[0], r, g, b, 255);\n\t\tRwIm3DVertexSetRGBA(&vptr[1], r, g, b, 255);\n\t\tRwIm3DVertexSetRGBA(&vptr[2], r, g, b, 255);\n\t\tRwIm3DVertexSetU(&vptr[0], 0.0f);\n\t\tRwIm3DVertexSetV(&vptr[0], 0.0f);\n\t\tRwIm3DVertexSetU(&vptr[1], 0.0f);\n\t\tRwIm3DVertexSetV(&vptr[1], 1.0f);\n\t\tRwIm3DVertexSetU(&vptr[2], 1.0f);\n\t\tRwIm3DVertexSetV(&vptr[2], 1.0f);\n\t\tRwIm3DVertexSetPos(&vptr[0], verts[0].x, verts[0].y, verts[0].z);\n\t\tRwIm3DVertexSetPos(&vptr[1], verts[1].x, verts[1].y, verts[1].z);\n\t\tRwIm3DVertexSetPos(&vptr[2], verts[2].x, verts[2].y, verts[2].z);\n\t\tiptr[0] = 0; iptr[1] = 1; iptr[2] = 2;\n\t\tiptr[3] = 0; iptr[4] = 2; iptr[5] = 1;\n\t\tRenderBuffer::StopStoring();\n\t}\n\n\tfor(i = 0; i < colModel.numBoxes; i++){\n\t\tmin = colModel.boxes[i].min;\n\t\tmax = colModel.boxes[i].max;\n\n\t\tverts[0] = mat * CVector(min.x, min.y, min.z);\n\t\tverts[1] = mat * CVector(min.x, min.y, max.z);\n\t\tverts[2] = mat * CVector(min.x, max.y, min.z);\n\t\tverts[3] = mat * CVector(min.x, max.y, max.z);\n\t\tverts[4] = mat * CVector(max.x, min.y, min.z);\n\t\tverts[5] = mat * CVector(max.x, min.y, max.z);\n\t\tverts[6] = mat * CVector(max.x, max.y, min.z);\n\t\tverts[7] = mat * CVector(max.x, max.y, max.z);\n\n\t\ts = colModel.boxes[i].surface;\n\t\tGetSurfaceColor(s, r, g, b);\n\n\t\tRenderBuffer::StartStoring(36, 8, &iptr, &vptr);\n\t\tRwIm3DVertexSetRGBA(&vptr[0], r, g, b, 255);\n\t\tRwIm3DVertexSetRGBA(&vptr[1], r, g, b, 255);\n\t\tRwIm3DVertexSetRGBA(&vptr[2], r, g, b, 255);\n\t\tRwIm3DVertexSetRGBA(&vptr[3], r, g, b, 255);\n\t\tRwIm3DVertexSetRGBA(&vptr[4], r, g, b, 255);\n\t\tRwIm3DVertexSetRGBA(&vptr[5], r, g, b, 255);\n\t\tRwIm3DVertexSetRGBA(&vptr[6], r, g, b, 255);\n\t\tRwIm3DVertexSetRGBA(&vptr[7], r, g, b, 255);\n\t\tRwIm3DVertexSetU(&vptr[0], 0.0f);\n\t\tRwIm3DVertexSetV(&vptr[0], 0.0f);\n\t\tRwIm3DVertexSetU(&vptr[1], 0.0f);\n\t\tRwIm3DVertexSetV(&vptr[1], 1.0f);\n\t\tRwIm3DVertexSetU(&vptr[2], 1.0f);\n\t\tRwIm3DVertexSetV(&vptr[2], 1.0f);\n\t\tRwIm3DVertexSetU(&vptr[3], 0.0f);\n\t\tRwIm3DVertexSetV(&vptr[3], 0.0f);\n\t\tRwIm3DVertexSetU(&vptr[4], 0.0f);\n\t\tRwIm3DVertexSetV(&vptr[4], 1.0f);\n\t\tRwIm3DVertexSetU(&vptr[5], 1.0f);\n\t\tRwIm3DVertexSetV(&vptr[5], 1.0f);\n\t\tRwIm3DVertexSetU(&vptr[6], 0.0f);\n\t\tRwIm3DVertexSetV(&vptr[6], 1.0f);\n\t\tRwIm3DVertexSetU(&vptr[7], 1.0f);\n\t\tRwIm3DVertexSetV(&vptr[7], 1.0f);\n\t\tRwIm3DVertexSetPos(&vptr[0], verts[0].x, verts[0].y, verts[0].z);\n\t\tRwIm3DVertexSetPos(&vptr[1], verts[1].x, verts[1].y, verts[1].z);\n\t\tRwIm3DVertexSetPos(&vptr[2], verts[2].x, verts[2].y, verts[2].z);\n\t\tRwIm3DVertexSetPos(&vptr[3], verts[3].x, verts[3].y, verts[3].z);\n\t\tRwIm3DVertexSetPos(&vptr[4], verts[4].x, verts[4].y, verts[4].z);\n\t\tRwIm3DVertexSetPos(&vptr[5], verts[5].x, verts[5].y, verts[5].z);\n\t\tRwIm3DVertexSetPos(&vptr[6], verts[6].x, verts[6].y, verts[6].z);\n\t\tRwIm3DVertexSetPos(&vptr[7], verts[7].x, verts[7].y, verts[7].z);\n\t\tiptr[0] = 0; iptr[1] = 1; iptr[2] = 2;\n\t\tiptr[3] = 1; iptr[4] = 3; iptr[5] = 2;\n\t\tiptr[6] = 1; iptr[7] = 5; iptr[8] = 7;\n\t\tiptr[9] = 1; iptr[10] = 7; iptr[11] = 3;\n\t\tiptr[12] = 2; iptr[13] = 3; iptr[14] = 7;\n\t\tiptr[15] = 2; iptr[16] = 7; iptr[17] = 6;\n\t\tiptr[18] = 0; iptr[19] = 5; iptr[20] = 1;\n\t\tiptr[21] = 0; iptr[22] = 4; iptr[23] = 5;\n\t\tiptr[24] = 0; iptr[25] = 2; iptr[26] = 4;\n\t\tiptr[27] = 2; iptr[28] = 6; iptr[29] = 4;\n\t\tiptr[30] = 4; iptr[31] = 6; iptr[32] = 7;\n\t\tiptr[33] = 4; iptr[34] = 7; iptr[35] = 5;\n\t\tRenderBuffer::StopStoring();\n\t}\n \n\tRenderBuffer::RenderStuffInBuffer();\n\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);\n\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);\n\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);\n\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);\n\tRwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);\n}\n"
  },
  {
    "path": "src/collision/Collision.h",
    "content": "#pragma once\n\n#include \"ColModel.h\"\n#include \"Game.h\"\t// for eLevelName\n#ifdef VU_COLLISION\n#include \"VuVector.h\"\n#endif\n\nstruct CStoredCollPoly\n{\n#ifdef VU_COLLISION\n\tCVuVector verts[3];\n#else\n\tCVector verts[3];\n#endif\n\tbool valid;\n};\n\n// If you spawn many tanks at once, you will see that collisions of two entity exceeds 32.\n#if defined(FIX_BUGS) && !defined(SQUEEZE_PERFORMANCE)\n#define MAX_COLLISION_POINTS 64\n#else\n#define MAX_COLLISION_POINTS 32\n#endif\n\nclass CCollision\n{\npublic:\n\tstatic eLevelName ms_collisionInMemory;\n\tstatic CLinkList<CColModel*> ms_colModelCache;\n\n\tstatic void Init(void);\n\tstatic void Shutdown(void);\n\tstatic void Update(void);\n\tstatic void LoadCollisionWhenINeedIt(bool changeLevel);\n\tstatic void SortOutCollisionAfterLoad(void);\n\tstatic void LoadCollisionScreen(eLevelName level);\n\tstatic void DrawColModel(const CMatrix &mat, const CColModel &colModel);\n\tstatic void DrawColModel_Coloured(const CMatrix &mat, const CColModel &colModel, int32 id);\n\n\tstatic void CalculateTrianglePlanes(CColModel *model);\n\tstatic void RemoveTrianglePlanes(CColModel *model);\n\n\t// all these return true if there's a collision\n\tstatic bool TestSphereSphere(const CSphere &s1, const CSphere &s2);\n\tstatic bool TestSphereBox(const CSphere &sph, const CBox &box);\n\tstatic bool TestLineBox(const CColLine &line, const CBox &box);\n\tstatic bool TestVerticalLineBox(const CColLine &line, const CBox &box);\n\tstatic bool TestLineTriangle(const CColLine &line, const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane);\n\tstatic bool TestLineSphere(const CColLine &line, const CColSphere &sph);\n\tstatic bool TestSphereTriangle(const CColSphere &sphere, const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane);\n\tstatic bool TestLineOfSight(const CColLine &line, const CMatrix &matrix, CColModel &model, bool ignoreSeeThrough, bool ignoreShootThrough);\n\n\tstatic bool ProcessSphereSphere(const CColSphere &s1, const CColSphere &s2, CColPoint &point, float &mindistsq);\n\tstatic bool ProcessSphereBox(const CColSphere &sph, const CColBox &box, CColPoint &point, float &mindistsq);\n\tstatic bool ProcessLineBox(const CColLine &line, const CColBox &box, CColPoint &point, float &mindist);\n\tstatic bool ProcessVerticalLineTriangle(const CColLine &line, const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane, CColPoint &point, float &mindist, CStoredCollPoly *poly);\n\tstatic bool ProcessLineTriangle(const CColLine &line , const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane, CColPoint &point, float &mindist, CStoredCollPoly *poly = nil);\n\tstatic bool ProcessLineSphere(const CColLine &line, const CColSphere &sphere, CColPoint &point, float &mindist);\n\tstatic bool ProcessSphereTriangle(const CColSphere &sph, const CompressedVector *verts, const CColTriangle &tri, const CColTrianglePlane &plane, CColPoint &point, float &mindistsq);\n\tstatic bool ProcessLineOfSight(const CColLine &line, const CMatrix &matrix, CColModel &model, CColPoint &point, float &mindist, bool ignoreSeeThrough, bool ignoreShootThrough);\n\tstatic bool ProcessVerticalLine(const CColLine &line, const CMatrix &matrix, CColModel &model, CColPoint &point, float &mindist, bool ignoreSeeThrough, bool ignoreShootThrough, CStoredCollPoly *poly);\n\tstatic int32 ProcessColModels(const CMatrix &matrixA, CColModel &modelA, const CMatrix &matrixB, CColModel &modelB, CColPoint *spherepoints, CColPoint *linepoints, float *linedists);\n\tstatic bool IsStoredPolyStillValidVerticalLine(const CVector &pos, float z, CColPoint &point, CStoredCollPoly *poly);\n\n\tstatic float DistToLine(const CVector *l0, const CVector *l1, const CVector *point);\n\tstatic float DistToLine(const CVector *l0, const CVector *l1, const CVector *point, CVector &closest);\n};\n"
  },
  {
    "path": "src/collision/CompressedVector.h",
    "content": "#pragma once\n\nstruct CompressedVector\n{\n#ifdef COMPRESSED_COL_VECTORS\n\tint16 x, y, z;\n\tCVector Get(void) const { return CVector(x, y, z)/128.0f; };\n\tvoid Set(float x, float y, float z) { this->x = x*128.0f; this->y = y*128.0f; this->z = z*128.0f; };\n#ifdef GTA_PS2\n\tvoid Unpack(uint128 &qword) const {\n\t\t__asm__ volatile (\n\t\t\t\"lh      $8, 0(%1)\\n\"\n\t\t\t\"lh      $9, 2(%1)\\n\"\n\t\t\t\"lh      $10, 4(%1)\\n\"\n\t\t\t\"pextlw  $10, $8\\n\"\n\t\t\t\"pextlw  $2, $9, $10\\n\"\n\t\t\t\"sq      $2, %0\\n\"\n\t\t\t: \"=m\" (qword)\n\t\t\t: \"r\" (this)\n\t\t\t: \"$8\", \"$9\", \"$10\", \"$2\"\n\t\t);\n\t}\n#else\n\tvoid Unpack(int32 *qword) const {\n\t\tqword[0] = x;\n\t\tqword[1] = y;\n\t\tqword[2] = z;\n\t\tqword[3] = 0;\t// junk\n\t}\n#endif\n#else\n\tfloat x, y, z;\n\tCVector Get(void) const { return CVector(x, y, z); };\n\tvoid Set(float x, float y, float z) { this->x = x; this->y = y; this->z = z; };\n#endif\n};"
  },
  {
    "path": "src/collision/TempColModels.cpp",
    "content": "#include \"common.h\"\n\n#include \"TempColModels.h\"\n#include \"Game.h\"\n\nCColModel CTempColModels::ms_colModelPed1;\nCColModel CTempColModels::ms_colModelPed2;\nCColModel CTempColModels::ms_colModelBBox;\nCColModel CTempColModels::ms_colModelBumper1;\nCColModel CTempColModels::ms_colModelWheel1;\nCColModel CTempColModels::ms_colModelPanel1;\nCColModel CTempColModels::ms_colModelBodyPart2;\nCColModel CTempColModels::ms_colModelBodyPart1;\nCColModel CTempColModels::ms_colModelCutObj[5];\nCColModel CTempColModels::ms_colModelPedGroundHit;\nCColModel CTempColModels::ms_colModelBoot1;\nCColModel CTempColModels::ms_colModelDoor1;\nCColModel CTempColModels::ms_colModelBonnet1;\nCColModel CTempColModels::ms_colModelWeapon;\n\n\nCColSphere s_aPedSpheres[3];\nCColSphere s_aPed2Spheres[3];\nCColSphere s_aPedGSpheres[4];\n#ifdef FIX_BUGS\nCColSphere s_aDoorSpheres[3];\n#else\nCColSphere s_aDoorSpheres[4];\n#endif\nCColSphere s_aBumperSpheres[4];\nCColSphere s_aPanelSpheres[4];\nCColSphere s_aBonnetSpheres[4];\nCColSphere s_aBootSpheres[4];\nCColSphere s_aWheelSpheres[2];\nCColSphere s_aBodyPartSpheres1[2];\nCColSphere s_aBodyPartSpheres2[2];\n\nvoid\nCTempColModels::Initialise(void)\n{\n#define SET_COLMODEL_SPHERES(colmodel, sphrs)\\\n\tcolmodel.numSpheres = ARRAY_SIZE(sphrs);\\\n\tcolmodel.spheres = sphrs;\\\n\tcolmodel.level = LEVEL_GENERIC;\\\n\tcolmodel.ownsCollisionVolumes = false;\n\n\tint i;\n\n\tms_colModelBBox.boundingSphere.Set(2.0f, CVector(0.0f, 0.0f, 0.0f));\n\tms_colModelBBox.boundingBox.Set(CVector(-2.0f, -2.0f, -2.0f), CVector(2.0f, 2.0f, 2.0f));\n\tms_colModelBBox.level = LEVEL_GENERIC;\n\n\tfor (i = 0; i < ARRAY_SIZE(ms_colModelCutObj); i++) {\n\t\tms_colModelCutObj[i].boundingSphere.Set(2.0f, CVector(0.0f, 0.0f, 0.0f));\n\t\tms_colModelCutObj[i].boundingBox.Set(CVector(-2.0f, -2.0f, -2.0f), CVector(2.0f, 2.0f, 2.0f));\n\t\tms_colModelCutObj[i].level = LEVEL_GENERIC;\n\t}\n\n\t// Ped Spheres\n\n\tfor (i = 0; i < ARRAY_SIZE(s_aPedSpheres); i++)\n\t\ts_aPedSpheres[i].radius = 0.35f;\n\n\ts_aPedSpheres[0].center = CVector(0.0f, 0.0f, -0.25f);\n\ts_aPedSpheres[1].center = CVector(0.0f, 0.0f, 0.15f);\n\ts_aPedSpheres[2].center = CVector(0.0f, 0.0f, 0.55f);\n\n#ifdef FIX_BUGS\n\tfor (i = 0; i < ARRAY_SIZE(s_aPedSpheres); i++) {\n#else\n\tfor (i = 0; i < ARRAY_SIZE(s_aPedGSpheres); i++) {\n#endif\n\t\ts_aPedSpheres[i].surface = SURFACE_PED;\n\t\ts_aPedSpheres[i].piece = 0;\n\t}\n\n\tms_colModelPed1.boundingSphere.Set(1.25f, CVector(0.0f, 0.0f, 0.0f));\n\tms_colModelPed1.boundingBox.Set(CVector(-0.35f, -0.35f, -1.0f), CVector(0.35f, 0.35f, 0.9f));\n\tSET_COLMODEL_SPHERES(ms_colModelPed1, s_aPedSpheres);\n\n\t// Ped 2 Spheres\n\n\ts_aPed2Spheres[0].radius = 0.3f;\n\ts_aPed2Spheres[1].radius = 0.4f;\n\ts_aPed2Spheres[2].radius = 0.3f;\n\n\ts_aPed2Spheres[0].center = CVector(0.0f, 0.35f, -0.9f);\n\ts_aPed2Spheres[1].center = CVector(0.0f, 0.0f, -0.9f);\n\ts_aPed2Spheres[2].center = CVector(0.0f, -0.35f, -0.9f);\n\n\tfor (i = 0; i < ARRAY_SIZE(s_aPed2Spheres); i++) {\n\t\ts_aPed2Spheres[i].surface = SURFACE_PED;\n\t\ts_aPed2Spheres[i].piece = 0;\n\t}\n\n\tms_colModelPed2.boundingSphere.Set(2.0f, CVector(0.0f, 0.0f, 0.0f));\n\tms_colModelPed2.boundingBox.Set(CVector(-0.7f, -0.7f, -1.2f), CVector(0.7f, 0.7f, 0.0f));\n\n\tSET_COLMODEL_SPHERES(ms_colModelPed2, s_aPed2Spheres);\n\n\t// Ped ground collision\n\t\n\ts_aPedGSpheres[0].radius = 0.35f;\n\ts_aPedGSpheres[1].radius = 0.35f;\n\ts_aPedGSpheres[2].radius = 0.35f;\n\ts_aPedGSpheres[3].radius = 0.3f;\n\n\ts_aPedGSpheres[0].center = CVector(0.0f, -0.4f, -0.9f);\n\ts_aPedGSpheres[1].center = CVector(0.0f, -0.1f, -0.9f);\n\ts_aPedGSpheres[2].center = CVector(0.0f, 0.25f, -0.9f);\n\ts_aPedGSpheres[3].center = CVector(0.0f, 0.65f, -0.9f);\n\n\ts_aPedGSpheres[0].surface = SURFACE_PED;\n\ts_aPedGSpheres[1].surface = SURFACE_PED;\n\ts_aPedGSpheres[2].surface = SURFACE_PED;\n\ts_aPedGSpheres[3].surface = SURFACE_PED;\n\ts_aPedGSpheres[0].piece = 4;\n\ts_aPedGSpheres[1].piece = 1;\n\ts_aPedGSpheres[2].piece = 0;\n\ts_aPedGSpheres[3].piece = 6;\n\n\tms_colModelPedGroundHit.boundingSphere.Set(2.0f, CVector(0.0f, 0.0f, 0.0f));\n\tms_colModelPedGroundHit.boundingBox.Set(CVector(-0.4f, -1.0f, -1.25f), CVector(0.4f, 1.2f, -0.5f));\n\n\tSET_COLMODEL_SPHERES(ms_colModelPedGroundHit, s_aPedGSpheres);\n\n\t// Door Spheres\n\n\ts_aDoorSpheres[0].radius = 0.15f;\n\ts_aDoorSpheres[1].radius = 0.15f;\n\ts_aDoorSpheres[2].radius = 0.25f;\n\n\ts_aDoorSpheres[0].center = CVector(0.0f, -0.25f, -0.35f);\n\ts_aDoorSpheres[1].center = CVector(0.0f, -0.95f, -0.35f);\n\ts_aDoorSpheres[2].center = CVector(0.0f, -0.6f, 0.25f);\n\n#ifdef FIX_BUGS\n\tfor (i = 0; i < ARRAY_SIZE(s_aDoorSpheres); i++) {\n#else\n\tfor (i = 0; i < ARRAY_SIZE(s_aPed2Spheres); i++) {\n#endif\n\t\ts_aDoorSpheres[i].surface = SURFACE_CAR_PANEL;\n\t\ts_aDoorSpheres[i].piece = 0;\n\t}\n\n\tms_colModelDoor1.boundingSphere.Set(1.5f, CVector(0.0f, -0.6f, 0.0f));\n\tms_colModelDoor1.boundingBox.Set(CVector(-0.3f, 0.0f, -0.6f), CVector(0.3f, -1.2f, 0.6f));\n\n\tSET_COLMODEL_SPHERES(ms_colModelDoor1, s_aDoorSpheres);\n\n\t// Bumper Spheres\n\n\tfor (i = 0; i < ARRAY_SIZE(s_aBumperSpheres); i++)\n\t\ts_aBumperSpheres[i].radius = 0.15f;\n\n\ts_aBumperSpheres[0].center = CVector(0.85f, -0.05f, 0.0f);\n\ts_aBumperSpheres[1].center = CVector(0.4f, 0.05f, 0.0f);\n\ts_aBumperSpheres[2].center = CVector(-0.4f, 0.05f, 0.0f);\n\ts_aBumperSpheres[3].center = CVector(-0.85f, -0.05f, 0.0f);\n\n\tfor (i = 0; i < ARRAY_SIZE(s_aBumperSpheres); i++) {\n\t\ts_aBumperSpheres[i].surface = SURFACE_CAR_PANEL;\n\t\ts_aBumperSpheres[i].piece = 0;\n\t}\n\n\tms_colModelBumper1.boundingSphere.Set(2.2f, CVector(0.0f, -0.6f, 0.0f));\n\tms_colModelBumper1.boundingBox.Set(CVector(-1.2f, -0.3f, -0.2f), CVector(1.2f, 0.3f, 0.2f));\n\n\tSET_COLMODEL_SPHERES(ms_colModelBumper1, s_aBumperSpheres);\n\n\t// Panel Spheres\n\n\tfor (i = 0; i < ARRAY_SIZE(s_aPanelSpheres); i++)\n\t\ts_aPanelSpheres[i].radius = 0.15f;\n\n\ts_aPanelSpheres[0].center = CVector(0.15f, 0.45f, 0.0f);\n\ts_aPanelSpheres[1].center = CVector(0.15f, -0.45f, 0.0f);\n\ts_aPanelSpheres[2].center = CVector(-0.15f, -0.45f, 0.0f);\n\ts_aPanelSpheres[3].center = CVector(-0.15f, 0.45f, 0.0f);\n\n\tfor (i = 0; i < ARRAY_SIZE(s_aPanelSpheres); i++) {\n\t\ts_aPanelSpheres[i].surface = SURFACE_CAR_PANEL;\n\t\ts_aPanelSpheres[i].piece = 0;\n\t}\n\n\tms_colModelPanel1.boundingSphere.Set(1.4f, CVector(0.0f, 0.0f, 0.0f));\n\tms_colModelPanel1.boundingBox.Set(CVector(-0.3f, -0.6f, -0.15f), CVector(0.3f, 0.6f, 0.15f));\n\n\tSET_COLMODEL_SPHERES(ms_colModelPanel1, s_aPanelSpheres);\n\n\t// Bonnet Spheres\n\n\tfor (i = 0; i < ARRAY_SIZE(s_aBonnetSpheres); i++)\n\t\ts_aBonnetSpheres[i].radius = 0.2f;\n\n\ts_aBonnetSpheres[0].center = CVector(-0.4f, 0.1f, 0.0f);\n\ts_aBonnetSpheres[1].center = CVector(-0.4f, 0.9f, 0.0f);\n\ts_aBonnetSpheres[2].center = CVector(0.4f, 0.1f, 0.0f);\n\ts_aBonnetSpheres[3].center = CVector(0.4f, 0.9f, 0.0f);\n\n\tfor (i = 0; i < ARRAY_SIZE(s_aBonnetSpheres); i++) {\n\t\ts_aBonnetSpheres[i].surface = SURFACE_CAR_PANEL;\n\t\ts_aBonnetSpheres[i].piece = 0;\n\t}\n\n\tms_colModelBonnet1.boundingSphere.Set(1.7f, CVector(0.0f, 0.5f, 0.0f));\n\tms_colModelBonnet1.boundingBox.Set(CVector(-0.7f, -0.2f, -0.3f), CVector(0.7f, 1.2f, 0.3f));\n\n\tSET_COLMODEL_SPHERES(ms_colModelBonnet1, s_aBonnetSpheres);\n\n\t// Boot Spheres\n\n\tfor (i = 0; i < ARRAY_SIZE(s_aBootSpheres); i++)\n\t\ts_aBootSpheres[i].radius = 0.2f;\n\n\ts_aBootSpheres[0].center = CVector(-0.4f, -0.1f, 0.0f);\n\ts_aBootSpheres[1].center = CVector(-0.4f, -0.6f, 0.0f);\n\ts_aBootSpheres[2].center = CVector(0.4f, -0.1f, 0.0f);\n\ts_aBootSpheres[3].center = CVector(0.4f, -0.6f, 0.0f);\n\n\tfor (i = 0; i < ARRAY_SIZE(s_aBootSpheres); i++) {\n\t\ts_aBootSpheres[i].surface = SURFACE_CAR_PANEL;\n\t\ts_aBootSpheres[i].piece = 0;\n\t}\n\n\tms_colModelBoot1.boundingSphere.Set(1.4f, CVector(0.0f, -0.4f, 0.0f));\n\tms_colModelBoot1.boundingBox.Set(CVector(-0.7f, -0.9f, -0.3f), CVector(0.7f, 0.2f, 0.3f));\n\n\tSET_COLMODEL_SPHERES(ms_colModelBoot1, s_aBootSpheres);\n\n\t// Wheel Spheres\n\n\ts_aWheelSpheres[0].radius = 0.35f;\n\ts_aWheelSpheres[1].radius = 0.35f;\n\n\ts_aWheelSpheres[0].center = CVector(-0.3f, 0.0f, 0.0f);\n\ts_aWheelSpheres[1].center = CVector(0.3f, 0.0f, 0.0f);\n\n#ifdef FIX_BUGS\n\tfor (i = 0; i < ARRAY_SIZE(s_aWheelSpheres); i++) {\n#else\n\tfor (i = 0; i < ARRAY_SIZE(s_aBootSpheres); i++) {\n#endif\n\t\ts_aWheelSpheres[i].surface = SURFACE_WHEELBASE;\n\t\ts_aWheelSpheres[i].piece = 0;\n\t}\n\n\tms_colModelWheel1.boundingSphere.Set(1.4f, CVector(0.0f, 0.0f, 0.0f));\n\tms_colModelWheel1.boundingBox.Set(CVector(-0.7f, -0.4f, -0.4f), CVector(0.7f, 0.4f, 0.4f));\n\n\tSET_COLMODEL_SPHERES(ms_colModelWheel1, s_aWheelSpheres);\n\n\t// Body Part Spheres 1\n\n\ts_aBodyPartSpheres1[0].radius = 0.2f;\n\ts_aBodyPartSpheres1[1].radius = 0.2f;\n\n\ts_aBodyPartSpheres1[0].center = CVector(0.0f, 0.0f, 0.0f);\n\ts_aBodyPartSpheres1[1].center = CVector(0.8f, 0.0f, 0.0f);\n\n#ifdef FIX_BUGS\n\tfor (i = 0; i < ARRAY_SIZE(s_aBodyPartSpheres1); i++) {\n#else\n\tfor (i = 0; i < ARRAY_SIZE(s_aBootSpheres); i++) {\n#endif\n\t\ts_aBodyPartSpheres1[i].surface = SURFACE_PED;\n\t\ts_aBodyPartSpheres1[i].piece = 0;\n\t}\n\n\tms_colModelBodyPart1.boundingSphere.Set(0.7f, CVector(0.4f, 0.0f, 0.0f));\n\tms_colModelBodyPart1.boundingBox.Set(CVector(-0.3f, -0.3f, -0.3f), CVector(1.1f, 0.3f, 0.3f));\n\n\tSET_COLMODEL_SPHERES(ms_colModelBodyPart1, s_aBodyPartSpheres1);\n\n\t// Body Part Spheres 2\n\n\ts_aBodyPartSpheres2[0].radius = 0.15f;\n\ts_aBodyPartSpheres2[1].radius = 0.15f;\n\n\ts_aBodyPartSpheres2[0].center = CVector(0.0f, 0.0f, 0.0f);\n\ts_aBodyPartSpheres2[1].center = CVector(0.5f, 0.0f, 0.0f);\n\n#ifdef FIX_BUGS\n\tfor (i = 0; i < ARRAY_SIZE(s_aBodyPartSpheres2); i++) {\n#else\n\tfor (i = 0; i < ARRAY_SIZE(s_aBootSpheres); i++) {\n#endif\n\t\ts_aBodyPartSpheres2[i].surface = SURFACE_PED;\n\t\ts_aBodyPartSpheres2[i].piece = 0;\n\t}\n\n\tms_colModelBodyPart2.boundingSphere.Set(0.5f, CVector(0.25f, 0.0f, 0.0f));\n\tms_colModelBodyPart2.boundingBox.Set(CVector(-0.2f, -0.2f, -0.2f), CVector(0.7f, 0.2f, 0.2f));\n\n\tSET_COLMODEL_SPHERES(ms_colModelBodyPart2, s_aBodyPartSpheres2);\n\n\tms_colModelWeapon.boundingSphere.radius = 0.25f;\n\tms_colModelWeapon.boundingBox.min.x = -0.25f;\n\tms_colModelWeapon.boundingBox.min.y = -0.25f;\n\tms_colModelWeapon.boundingBox.min.z = -0.25f;\n\tms_colModelWeapon.boundingBox.max.x = 0.25f;\n\tms_colModelWeapon.boundingBox.max.y = 0.25f;\n\tms_colModelWeapon.boundingBox.max.z = 0.25f;\n\n#undef SET_COLMODEL_SPHERES\n}\n"
  },
  {
    "path": "src/collision/TempColModels.h",
    "content": "#pragma once\n\n#include \"ColModel.h\"\n\nclass CTempColModels\n{\npublic:\n\tstatic CColModel ms_colModelPed1;\n\tstatic CColModel ms_colModelPed2;\n\tstatic CColModel ms_colModelBBox;\n\tstatic CColModel ms_colModelBumper1;\n\tstatic CColModel ms_colModelWheel1;\t\n\tstatic CColModel ms_colModelPanel1;\n\tstatic CColModel ms_colModelBodyPart2;\n\tstatic CColModel ms_colModelBodyPart1;\n\tstatic CColModel ms_colModelCutObj[5];\n\tstatic CColModel ms_colModelPedGroundHit;\n\tstatic CColModel ms_colModelBoot1;\n\tstatic CColModel ms_colModelDoor1;\n\tstatic CColModel ms_colModelBonnet1;\n\tstatic CColModel ms_colModelWeapon;\n\n\tstatic void Initialise(void);\n};\n"
  },
  {
    "path": "src/collision/VuCollision.cpp",
    "content": "#include \"common.h\"\n#ifdef VU_COLLISION\n#include \"VuVector.h\"\n#include \"VuCollision.h\"\n\n#ifndef GTA_PS2\nint16 vi01;\nCVuVector vf01;\nCVuVector vf02;\nCVuVector vf03;\n\nCVuVector\nDistanceBetweenSphereAndLine(const CVuVector &center, const CVuVector &p0, const CVuVector &line)\n{\n\t// center  VF12\n\t// p0      VF14\n\t// line    VF15\n\tCVuVector ret;\t// VF16\n\tCVuVector p1 = p0+line;\n\tCVuVector dist0 = center - p0;\t// VF20\n\tCVuVector dist1 = center - p1;\t// VF25\n\tfloat lenSq = line.MagnitudeSqr();\t// VF21\n\tfloat distSq0 = dist0.MagnitudeSqr();\t// VF22\n\tfloat distSq1 = dist1.MagnitudeSqr();\n\tfloat dot = DotProduct(dist0, line);\t// VF23\n\tif(dot < 0.0f){\n\t\t// not above line, closest to p0\n\t\tret = p0;\n\t\tret.w = distSq0;\n\t\treturn ret;\n\t}\n\tfloat t = dot/lenSq;\t// param of nearest point on infinite line\n\tif(t > 1.0f){\n\t\t// not above line, closest to p1\n\t\tret = p1;\n\t\tret.w = distSq1;\n\t\treturn ret;\n\t}\n\t// closest to line\n\tret = p0 + line*t;\n\tret.w = (ret - center).MagnitudeSqr();\n\treturn ret;\n}\ninline int SignFlags(const CVector &v)\n{\n\tint f = 0;\n\tif(v.x < 0.0f) f |= 1;\n\tif(v.y < 0.0f) f |= 2;\n\tif(v.z < 0.0f) f |= 4;\n\treturn f;\n}\n#endif\n\nextern \"C\" void\nLineToTriangleCollision(const CVuVector &p0, const CVuVector &p1,\n\tconst CVuVector &v0, const CVuVector &v1, const CVuVector &v2,\n\tconst CVuVector &plane)\n{\n#ifdef GTA_PS2\n\t__asm__ volatile (\n\t\t\".set noreorder\\n\"\n\t\t\"lqc2\tvf12, 0x0(%0)\\n\"\n\t\t\"lqc2\tvf13, 0x0(%1)\\n\"\n\t\t\"lqc2\tvf14, 0x0(%2)\\n\"\n\t\t\"lqc2\tvf15, 0x0(%3)\\n\"\n\t\t\"lqc2\tvf16, 0x0(%4)\\n\"\n\t\t\"lqc2\tvf17, 0x0(%5)\\n\"\n\t\t\"vcallms\tVu0LineToTriangleCollisionStart\\n\"\n\t\t\".set reorder\\n\"\n\t\t:\n\t\t: \"r\" (&p0), \"r\" (&p1), \"r\" (&v0), \"r\" (&v1), \"r\" (&v2), \"r\" (&plane)\n\t);\n#else\n\tfloat dot0 = DotProduct(plane, p0);\n\tfloat dot1 = DotProduct(plane, p1);\n\tfloat dist0 = plane.w - dot0;\n\tfloat dist1 = plane.w - dot1;\n\n\t// if points are on the same side, no collision\n\tif(dist0 * dist1 > 0.0f){\n\t\tvi01 = 0;\n\t\treturn;\n\t}\n\n\tCVuVector diff = p1 - p0;\n\tfloat t = dist0/(dot1 - dot0);\n\tCVuVector p = p0 + diff*t;\n\tp.w = 0.0f;\n\tvf01 = p;\n\tvf03.x = t;\n\n\t// Check if point is inside\n\tCVector cross1 = CrossProduct(p-v0, v1-v0);\n\tCVector cross2 = CrossProduct(p-v1, v2-v1);\n\tCVector cross3 = CrossProduct(p-v2, v0-v2);\n\t// Only check relevant directions\n\tint flagmask = 0;\n\tif(Abs(plane.x) > 0.5f) flagmask |= 1;\n\tif(Abs(plane.y) > 0.5f) flagmask |= 2;\n\tif(Abs(plane.z) > 0.5f) flagmask |= 4;\n\tint flags1 = SignFlags(cross1) & flagmask;\n\tint flags2 = SignFlags(cross2) & flagmask;\n\tint flags3 = SignFlags(cross3) & flagmask;\n\t// inside if on the same side of all edges\n\tif(flags1 != flags2 || flags1 != flags3){\n\t\tvi01 = 0;\n\t\treturn;\n\t}\n\tvi01 = 1;\n\tvf02 = plane;\n\treturn;\n#endif\n}\n\nextern \"C\" void\nLineToTriangleCollisionCompressed(const CVuVector &p0, const CVuVector &p1, VuTriangle &tri)\n{\n#ifdef GTA_PS2\n\t__asm__ volatile (\n\t\t\".set noreorder\\n\"\n\t\t\"lqc2\tvf12, 0x0(%0)\\n\"\n\t\t\"lqc2\tvf13, 0x0(%1)\\n\"\n\t\t\"lqc2\tvf14, 0x0(%2)\\n\"\n\t\t\"lqc2\tvf15, 0x10(%2)\\n\"\n\t\t\"lqc2\tvf16, 0x20(%2)\\n\"\n\t\t\"lqc2\tvf17, 0x30(%2)\\n\"\n\t\t\"vcallms\tVu0LineToTriangleCollisionCompressedStart\\n\"\n\t\t\".set reorder\\n\"\n\t\t:\n\t\t: \"r\" (&p0), \"r\" (&p1), \"r\" (&tri)\n\t);\n#else\n\tCVuVector v0, v1, v2, plane;\n\tv0.x = tri.v0[0]/128.0f;\n\tv0.y = tri.v0[1]/128.0f;\n\tv0.z = tri.v0[2]/128.0f;\n\tv0.w = tri.v0[3]/128.0f;\n\tv1.x = tri.v1[0]/128.0f;\n\tv1.y = tri.v1[1]/128.0f;\n\tv1.z = tri.v1[2]/128.0f;\n\tv1.w = tri.v1[3]/128.0f;\n\tv2.x = tri.v2[0]/128.0f;\n\tv2.y = tri.v2[1]/128.0f;\n\tv2.z = tri.v2[2]/128.0f;\n\tv2.w = tri.v2[3]/128.0f;\n\tplane.x = tri.plane[0]/4096.0f;\n\tplane.y = tri.plane[1]/4096.0f;\n\tplane.z = tri.plane[2]/4096.0f;\n\tplane.w = tri.plane[3]/128.0f;\n\tLineToTriangleCollision(p0, p1, v0, v1, v2, plane);\n#endif\n}\n\nextern \"C\" void\nSphereToTriangleCollision(const CVuVector &sph,\n\tconst CVuVector &v0, const CVuVector &v1, const CVuVector &v2,\n\tconst CVuVector &plane)\n{\n#ifdef GTA_PS2\n\t__asm__ volatile (\n\t\t\".set noreorder\\n\"\n\t\t\"lqc2\tvf12, 0x0(%0)\\n\"\n\t\t\"lqc2\tvf14, 0x0(%1)\\n\"\n\t\t\"lqc2\tvf15, 0x0(%2)\\n\"\n\t\t\"lqc2\tvf16, 0x0(%3)\\n\"\n\t\t\"lqc2\tvf17, 0x0(%4)\\n\"\n\t\t\"vcallms\tVu0SphereToTriangleCollisionStart\\n\"\n\t\t\".set reorder\\n\"\n\t\t:\n\t\t: \"r\" (&sph), \"r\" (&v0), \"r\" (&v1), \"r\" (&v2), \"r\" (&plane)\n\t);\n#else\n\tfloat planedist = DotProduct(plane, sph) - plane.w;\t// VF02\n\tif(Abs(planedist) > sph.w){\n\t\tvi01 = 0;\n\t\treturn;\n\t}\n\t// point on plane\n\tCVuVector p = sph - planedist*plane;\n\tp.w = 0.0f;\n\tvf01 = p;\n\tplanedist = Abs(planedist);\n\t// edges\n\tCVuVector v01 = v1 - v0;\n\tCVuVector v12 = v2 - v1;\n\tCVuVector v20 = v0 - v2;\n\t// VU code calculates normal again for some weird reason...\n\t// Check sides of point\n\tCVector cross1 = CrossProduct(p-v0, v01);\n\tCVector cross2 = CrossProduct(p-v1, v12);\n\tCVector cross3 = CrossProduct(p-v2, v20);\n\t// Only check relevant directions\n\tint flagmask = 0;\n\tif(Abs(plane.x) > 0.1f) flagmask |= 1;\n\tif(Abs(plane.y) > 0.1f) flagmask |= 2;\n\tif(Abs(plane.z) > 0.1f) flagmask |= 4;\n\tint nflags = SignFlags(plane) & flagmask;\n\tint flags1 = SignFlags(cross1) & flagmask;\n\tint flags2 = SignFlags(cross2) & flagmask;\n\tint flags3 = SignFlags(cross3) & flagmask;\n\tint testcase = 0;\n\tCVuVector closest(0.0f, 0.0f, 0.0f);\t// VF04\n\tif(flags1 == nflags){\n\t\tclosest += v2;\n\t\ttestcase++;\n\t}\n\tif(flags2 == nflags){\n\t\tclosest += v0;\n\t\ttestcase++;\n\t}\n\tif(flags3 == nflags){\n\t\tclosest += v1;\n\t\ttestcase++;\n\t}\n\tif(testcase == 3){\n\t\t// inside triangle - dist to plane already checked\n\t\tvf02 = plane;\n\t\tvf02.w = vf03.x = planedist;\n\t\tvi01 = 1;\n\t}else if(testcase == 1){\n\t\t// outside two sides - closest to point opposide inside edge\n\t\tvf01 = closest;\n\t\tvf02 = sph - closest;\n\t\tfloat distSq = vf02.MagnitudeSqr();\n\t\tvi01 = sph.w*sph.w > distSq;\n\t\tvf03.x = Sqrt(distSq);\n\t\tvf02 *= 1.0f/vf03.x;\n\t}else{\n\t\t// inside two sides - closest to third edge\n\t\tif(flags1 != nflags)\n\t\t\tclosest = DistanceBetweenSphereAndLine(sph, v0, v01);\n\t\telse if(flags2 != nflags)\n\t\t\tclosest = DistanceBetweenSphereAndLine(sph, v1, v12);\n\t\telse\n\t\t\tclosest = DistanceBetweenSphereAndLine(sph, v2, v20);\n\t\tvi01 = sph.w*sph.w > closest.w;\n\t\tvf01 = closest;\n\t\tvf02 = sph - closest;\n\t\tvf03.x = Sqrt(closest.w);\n\t\tvf02 *= 1.0f/vf03.x;\n\t}\n#endif\n}\n\nextern \"C\" void\nSphereToTriangleCollisionCompressed(const CVuVector &sph, VuTriangle &tri)\n{\n#ifdef GTA_PS2\n\t__asm__ volatile (\n\t\t\".set noreorder\\n\"\n\t\t\"lqc2\tvf12, 0x0(%0)\\n\"\n\t\t\"lqc2\tvf14, 0x0(%1)\\n\"\n\t\t\"lqc2\tvf15, 0x10(%1)\\n\"\n\t\t\"lqc2\tvf16, 0x20(%1)\\n\"\n\t\t\"lqc2\tvf17, 0x30(%1)\\n\"\n\t\t\"vcallms\tVu0SphereToTriangleCollisionCompressedStart\\n\"\n\t\t\".set reorder\\n\"\n\t\t:\n\t\t: \"r\" (&sph), \"r\" (&tri)\n\t);\n#else\n\tCVuVector v0, v1, v2, plane;\n\tv0.x = tri.v0[0]/128.0f;\n\tv0.y = tri.v0[1]/128.0f;\n\tv0.z = tri.v0[2]/128.0f;\n\tv0.w = tri.v0[3]/128.0f;\n\tv1.x = tri.v1[0]/128.0f;\n\tv1.y = tri.v1[1]/128.0f;\n\tv1.z = tri.v1[2]/128.0f;\n\tv1.w = tri.v1[3]/128.0f;\n\tv2.x = tri.v2[0]/128.0f;\n\tv2.y = tri.v2[1]/128.0f;\n\tv2.z = tri.v2[2]/128.0f;\n\tv2.w = tri.v2[3]/128.0f;\n\tplane.x = tri.plane[0]/4096.0f;\n\tplane.y = tri.plane[1]/4096.0f;\n\tplane.z = tri.plane[2]/4096.0f;\n\tplane.w = tri.plane[3]/128.0f;\n\tSphereToTriangleCollision(sph, v0, v1, v2, plane);\n#endif\n}\n#endif"
  },
  {
    "path": "src/collision/VuCollision.h",
    "content": "#pragma once\n\n\nstruct VuTriangle\n{\n\t// Compressed int16 but unpacked\n#ifdef GTA_PS2\n\tuint128 v0;\n\tuint128 v1;\n\tuint128 v2;\n\tuint128 plane;\n#else\n\tint32 v0[4];\n\tint32 v1[4];\n\tint32 v2[4];\n\tint32 plane[4];\n#endif\n};\n\n#ifndef GTA_PS2\nextern int16 vi01;\nextern CVuVector vf01;\nextern CVuVector vf02;\nextern CVuVector vf03;\n#endif\n\nextern \"C\" {\nvoid LineToTriangleCollision(const CVuVector &p0, const CVuVector &p1, const CVuVector &v0, const CVuVector &v1, const CVuVector &v2, const CVuVector &plane);\nvoid LineToTriangleCollisionCompressed(const CVuVector &p0, const CVuVector &p1, VuTriangle &tri);\nvoid SphereToTriangleCollision(const CVuVector &sph, const CVuVector &v0, const CVuVector &v1, const CVuVector &v2, const CVuVector &plane);\nvoid SphereToTriangleCollisionCompressed(const CVuVector &sph, VuTriangle &tri);\n}\n"
  },
  {
    "path": "src/collision/vu0Collision.dsm",
    "content": ".align 4\n.global Vu0CollisionDmaTag\nVu0CollisionDmaTag:\nDMAcnt *\nMPG 0, *\n.vu\n.include \"vu0Collision_1.s\"\n.EndMPG\n.EndDmaData\nDMAend\n\n.global Vu0Collision2DmaTag\nVu0Collision2DmaTag:\nDMAcnt *\nMPG 0, *\n.vu\n.include \"vu0Collision_2.s\"\n.EndMPG\n.EndDmaData\nDMAend\n.end\n"
  },
  {
    "path": "src/collision/vu0Collision_1.s",
    "content": "QuitAndFail:\n\tNOP[E]                                   IADDIU VI01, VI00, 0\n\tNOP                                      NOP\n\n\nQuitAndSucceed:\n\tNOP[E]                                   IADDIU VI01, VI00, 1\n\tNOP                                      NOP\n\n\n; 20 -- unused\n; VF12, VF13 xyz: sphere centers\n; VF14, VF15 x: sphere radii\n; out:\n;  VI01: set when collision\n;  VF01: supposed to be intersection point?\n;  VF02: normal (pointing towards s1, not normalized)\n.globl Vu0SphereToSphereCollision\nVu0SphereToSphereCollision:\n\tSUB.xyz VF02, VF13, VF12                 NOP                     ; dist of centers\n\tADD.x VF04, VF14, VF15                   NOP                     ; s = sum of radii\n\tMUL.xyzw VF03, VF02, VF02                NOP                     ;\n\tMUL.x VF04, VF04, VF04                   DIV Q, VF14x, VF04x     ; square s\n\tNOP                                      NOP                     ;\n\tNOP                                      NOP                     ;\n\tMULAx.w ACC, VF00, VF03                  NOP                     ;\n\tMADDAy.w ACC, VF00, VF03                 NOP                     ;\n\tMADDz.w VF03, VF00, VF03                 NOP                     ; d = DistSq of centers\n\tNOP                                      NOP                     ;\n\tMULAw.xyz ACC, VF12, VF00                NOP                     ;\n\tMADDq.xyz VF01, VF02, Q                  NOP                     ; intersection, but wrong\n\tCLIPw.xyz VF04, VF03                     NOP                     ; compare s and d\n\tSUB.xyz VF02, VF00, VF02                 NOP                     ; compute normal\n\tNOP                                      NOP                     ;\n\tNOP                                      NOP                     ;\n\tNOP                                      FCAND VI01, 0x3         ; 0x2 cannot be set here\n\tNOP[E]                                   NOP                     ;\n\tNOP                                      NOP                     ;\n\n\n; B8 -- unused\n; VF12:\n; VF13: radius\n; VF14:\n; VF15: box dimensions (?)\n.globl Vu0SphereToAABBCollision\nVu0SphereToAABBCollision:\n\tSUB.xyz VF03, VF12, VF14                 LOI 0.5\n\tMULi.xyz VF15, VF15, I                   NOP\n\tMUL.x VF13, VF13, VF13                   NOP\n\tSUB.xyz VF04, VF03, VF15                 NOP\n\tADD.xyz VF05, VF03, VF15                 MR32.xyzw VF16, VF15\n\tCLIPw.xyz VF03, VF16                     MR32.xyzw VF17, VF16\n\tMUL.xyz VF04, VF04, VF04                 NOP\n\tMUL.xyz VF05, VF05, VF05                 NOP\n\tCLIPw.xyz VF03, VF17                     MR32.xyzw VF16, VF17\n\tNOP                                      FCAND VI01, 0x1\n\tMINI.xyz VF04, VF04, VF05                MFIR.x VF09, VI01\n\tNOP                                      NOP\n\tCLIPw.xyz VF03, VF16                     FCAND VI01, 0x4\n\tNOP                                      MFIR.y VF09, VI01\n\tNOP                                      NOP\n\tMULAx.w ACC, VF00, VF00                  NOP\n\tADD.xyz VF01, VF00, VF03                 FCAND VI01, 0x10\n\tNOP                                      MFIR.z VF09, VI01\n\tNOP                                      LOI 2\n\tNOP                                      FCAND VI01, 0x30\n\tSUBAw.xyz ACC, VF00, VF00                IADD VI04, VI00, VI01\n\tITOF0.xyz VF09, VF09                     FCAND VI01, 0x300\n\tNOP                                      IADD VI03, VI00, VI01\n\tNOP                                      FCAND VI01, 0x3000\n\tNOP                                      IADD VI02, VI00, VI01\n\tMADDi.xyzw VF09, VF09, I                 NOP\n\tNOP                                      IBEQ VI04, VI00, IgnoreZValue\n\tNOP                                      NOP\n\tMADDAz.w ACC, VF00, VF04                 NOP\n\tMUL.z VF01, VF09, VF15                   NOP\nIgnoreZValue:\n\tNOP                                      IBEQ VI03, VI00, IgnoreYValue\n\tNOP                                      NOP\n\tMADDAy.w ACC, VF00, VF04                 NOP\n\tMUL.y VF01, VF09, VF15                   NOP\nIgnoreYValue:\n\tNOP                                      IBEQ VI02, VI00, IgnoreXValue\n\tNOP                                      NOP\n\tMADDAx.w ACC, VF00, VF04                 NOP\n\tMUL.x VF01, VF09, VF15                   NOP\nIgnoreXValue:\n\tMADDx.w VF06, VF00, VF00                 NOP\n\tSUB.xyz VF02, VF03, VF01                 NOP\n\tADD.xyz VF01, VF01, VF14                 NOP\n\tMULx.w VF01, VF00, VF00                  NOP\n\tCLIPw.xyz VF13, VF06                     NOP\n\tNOP                                      NOP\n\tNOP                                      NOP\n\tNOP                                      NOP\n\tNOP                                      FCAND VI01, 0x1\nQuitMicrocode:\n\tNOP[E]                                   NOP\n\tNOP                                      NOP\n\n\n; 240\n.globl Vu0LineToSphereCollision\nVu0LineToSphereCollision:\n\tSUB.xyzw VF01, VF13, VF12                NOP\n\tSUB.xyzw VF02, VF14, VF12                NOP\n\tMUL.xyz VF03, VF01, VF02                 NOP\n\tMUL.xyz VF04, VF01, VF01                 NOP\n\tMUL.x VF15, VF15, VF15                   NOP\n\tMUL.xyz VF02, VF02, VF02                 NOP\n\tMULAx.w ACC, VF00, VF03                  NOP\n\tMADDAy.w ACC, VF00, VF03                 NOP\n\tMADDz.w VF03, VF00, VF03                 NOP\n\tMULAx.w ACC, VF00, VF04                  NOP\n\tMADDAy.w ACC, VF00, VF04                 NOP\n\tMADDz.w VF01, VF00, VF04                 NOP\n\tMULAx.w ACC, VF00, VF02                  NOP\n\tMADDAy.w ACC, VF00, VF02                 NOP\n\tMADDz.w VF02, VF00, VF02                 NOP\n\tMULA.w ACC, VF03, VF03                   NOP\n\tMADDAx.w ACC, VF01, VF15                 NOP\n\tMSUB.w VF05, VF01, VF02                  NOP\n\tNOP                                      NOP\n\tNOP                                      NOP\n\tNOP                                      IADDIU VI02, VI00, 0x10\n\tNOP                                      FMAND VI01, VI02\n\tNOP                                      IBNE VI01, VI00, QuitAndFail\n\tNOP                                      NOP\n\tCLIPw.xyz VF15, VF02                     SQRT Q, VF05w\n\tNOP                                      NOP\n\tNOP                                      NOP\n\tNOP                                      NOP\n\tNOP                                      FCAND VI01, 0x1\n\tNOP                                      IBNE VI00, VI01, LineStartInsideSphere\n\tNOP                                      NOP\n\tSUBq.w VF05, VF03, Q                     NOP\n\tSUB.w VF05, VF05, VF01                   DIV Q, VF05w, VF01w\n\tNOP                                      FMAND VI01, VI02\n\tNOP                                      IBNE VI01, VI00, QuitAndFail\n\tNOP                                      NOP\n\tNOP                                      FMAND VI01, VI02\n\tNOP                                      IBEQ VI01, VI00, QuitAndFail\n\tNOP                                      NOP\n\tADDA.xyz ACC, VF12, VF00                 NOP\n\tMADDq.xyz VF01, VF01, Q                  NOP\n\tMULx.w VF01, VF00, VF00                  NOP\n\tSUB.xyz VF02, VF01, VF14                 NOP\n\tNOP[E]                                   NOP\n\tNOP                                      NOP\nLineStartInsideSphere:\n\tNOP                                      MOVE.xyzw VF01, VF12\n\tNOP[E]                                   IADDIU VI01, VI00, 0x1\n\tNOP                                      NOP\n\n\n; 3C0\n.globl Vu0LineToAABBCollision\nVu0LineToAABBCollision:\n\tSUB.xyzw VF08, VF13, VF12                LOI 0.5\n\tMULi.xyz VF15, VF15, I                   IADDIU VI08, VI00, 0x0\n\tSUB.xyzw VF12, VF12, VF14                NOP\n\tSUB.xyzw VF13, VF13, VF14                NOP\n\tNOP                                      DIV Q, VF00w, VF08x\n\tNOP                                      MR32.xyzw VF03, VF15\n\tSUB.xyz VF06, VF15, VF12                 NOP\n\tADD.xyz VF07, VF15, VF12                 NOP\n\tNOP                                      NOP\n\tCLIPw.xyz VF12, VF03                     MR32.xyzw VF04, VF03\n\tNOP                                      NOP\n\tADDq.x VF09, VF00, Q                     DIV Q, VF00w, VF08y\n\tNOP                                      NOP\n\tCLIPw.xyz VF12, VF04                     MR32.xyzw VF05, VF04\n\tSUB.xyz VF07, VF00, VF07                 IADDIU VI06, VI00, 0xCC\n\tNOP                                      IADDIU VI07, VI00, 0x30\n\tNOP                                      NOP\n\tCLIPw.xyz VF12, VF05                     FCGET VI02\n\tNOP                                      IAND VI02, VI02, VI06\n\tADDq.y VF09, VF00, Q                     DIV Q, VF00w, VF08z\n\tSUB.xyz VF10, VF00, VF10                 NOP\n\tCLIPw.xyz VF13, VF03                     FCGET VI03\n\tCLIPw.xyz VF13, VF04                     IAND VI03, VI03, VI07\n\tCLIPw.xyz VF13, VF05                     FCAND VI01, 0x3330\n\tNOP                                      IBEQ VI01, VI00, StartPointInsideAABB\n\tNOP                                      NOP\n\tADDq.z VF09, VF00, Q                     FCGET VI04\n\tNOP                                      FCGET VI05\n\tNOP                                      IAND VI04, VI04, VI06\n\tNOP                                      IAND VI05, VI05, VI07\n\tMULx.xyz VF17, VF08, VF09                NOP\n\tMULy.xyz VF18, VF08, VF09                IADDIU VI07, VI00, 0x80\n\tMULz.xyz VF19, VF08, VF09                IAND VI06, VI02, VI07\n\tMUL.w VF10, VF00, VF00                   IAND VI07, VI04, VI07\n\tNOP                                      NOP\n\tNOP                                      IBEQ VI06, VI07, CheckMaxXSide\n\tNOP                                      NOP\n\tMULAx.xyz ACC, VF17, VF07                NOP\n\tMADDw.xyz VF16, VF12, VF00               NOP\n\tMUL.x VF10, VF07, VF09                   NOP\n\tCLIPw.xyz VF16, VF04                     NOP\n\tCLIPw.xyz VF16, VF05                     NOP\n\tNOP                                      NOP\n\tNOP                                      NOP\n\tNOP                                      NOP\n\tNOP                                      FCAND VI01, 0x330\n\tNOP                                      IBNE VI01, VI00, CheckMaxXSide\n\tNOP                                      NOP\n\tMULx.w VF10, VF00, VF10                  IADDIU VI08, VI00, 0x1\n\tADD.yz VF02, VF00, VF00                  MOVE.xyzw VF01, VF16\n\tSUBw.x VF02, VF00, VF00                  NOP\nCheckMaxXSide:\n\tMULAx.xyz ACC, VF17, VF06                IADDIU VI07, VI00, 0x40\n\tMADDw.xyz VF16, VF12, VF00               IAND VI06, VI02, VI07\n\tMUL.x VF10, VF06, VF09                   IAND VI07, VI04, VI07\n\tNOP                                      NOP\n\tNOP                                      IBEQ VI06, VI07, CheckMinYSide\n\tNOP                                      NOP\n\tCLIPw.xyz VF16, VF04                     NOP\n\tCLIPw.xyz VF16, VF05                     NOP\n\tCLIPw.xyz VF10, VF10                     NOP\n\tNOP                                      NOP\n\tNOP                                      NOP\n\tNOP                                      NOP\n\tNOP                                      FCAND VI01, 0xCC03\n\tNOP                                      IBNE VI01, VI00, CheckMinYSide\n\tNOP                                      NOP\n\tMULx.w VF10, VF00, VF10                  IADDIU VI08, VI00, 0x1\n\tADD.yz VF02, VF00, VF00                  MOVE.xyzw VF01, VF16\n\tADDw.x VF02, VF00, VF00                  NOP\nCheckMinYSide:\n\tMULAy.xyz ACC, VF18, VF07                IADDIU VI07, VI00, 0x8\n\tMADDw.xyz VF16, VF12, VF00               IAND VI06, VI02, VI07\n\tMUL.y VF10, VF07, VF09                   IAND VI07, VI04, VI07\n\tNOP                                      NOP\n\tNOP                                      IBEQ VI06, VI07, CheckMaxYSide\n\tNOP                                      NOP\n\tCLIPw.xyz VF16, VF03                     NOP\n\tCLIPw.xyz VF16, VF05                     NOP\n\tCLIPw.xyz VF10, VF10                     NOP\n\tNOP                                      NOP\n\tNOP                                      NOP\n\tNOP                                      NOP\n\tNOP                                      FCAND VI01, 0x3C0C\n\tNOP                                      IBNE VI01, VI00, CheckMaxYSide\n\tNOP                                      NOP\n\tMULy.w VF10, VF00, VF10                  IADDIU VI08, VI00, 0x1\n\tADD.xz VF02, VF00, VF00                  MOVE.xyzw VF01, VF16\n\tSUBw.y VF02, VF00, VF00                  NOP\nCheckMaxYSide:\n\tMULAy.xyz ACC, VF18, VF06                IADDIU VI07, VI00, 0x4\n\tMADDw.xyz VF16, VF12, VF00               IAND VI06, VI02, VI07\n\tMUL.y VF10, VF06, VF09                   IAND VI07, VI04, VI07\n\tNOP                                      NOP\n\tNOP                                      IBEQ VI06, VI07, CheckMinZSide\n\tNOP                                      NOP\n\tCLIPw.xyz VF16, VF03                     NOP\n\tCLIPw.xyz VF16, VF05                     NOP\n\tCLIPw.xyz VF10, VF10                     NOP\n\tNOP                                      NOP\n\tNOP                                      NOP\n\tNOP                                      NOP\n\tNOP                                      FCAND VI01, 0x3C0C\n\tNOP                                      IBNE VI01, VI00, CheckMinZSide\n\tNOP                                      NOP\n\tMULy.w VF10, VF00, VF10                  IADDIU VI08, VI00, 0x1\n\tADD.xz VF02, VF00, VF00                  MOVE.xyzw VF01, VF16\n\tADDw.y VF02, VF00, VF00                  NOP\nCheckMinZSide:\n\tMULAz.xyz ACC, VF19, VF07                IADDIU VI07, VI00, 0x20\n\tMADDw.xyz VF16, VF12, VF00               IAND VI06, VI03, VI07\n\tMUL.z VF10, VF07, VF09                   IAND VI07, VI05, VI07\n\tNOP                                      NOP\n\tNOP                                      IBEQ VI06, VI07, CheckMaxZSide\n\tNOP                                      NOP\n\tCLIPw.xyz VF16, VF03                     NOP\n\tCLIPw.xyz VF16, VF04                     NOP\n\tCLIPw.xyz VF10, VF10                     NOP\n\tNOP                                      NOP\n\tNOP                                      NOP\n\tNOP                                      NOP\n\tNOP                                      FCAND VI01, 0x3330\n\tNOP                                      IBNE VI01, VI00, CheckMaxZSide\n\tNOP                                      NOP\n\tMULz.w VF10, VF00, VF10                  IADDIU VI08, VI00, 0x1\n\tADD.xy VF02, VF00, VF00                  MOVE.xyzw VF01, VF16\n\tSUBw.z VF02, VF00, VF00                  NOP\nCheckMaxZSide:\n\tMULAz.xyz ACC, VF19, VF06                IADDIU VI07, VI00, 0x10\n\tMADDw.xyz VF16, VF12, VF00               IAND VI06, VI03, VI07\n\tMUL.z VF10, VF06, VF09                   IAND VI07, VI05, VI07\n\tNOP                                      NOP\n\tNOP                                      IBEQ VI06, VI07, DoneAllChecks\n\tNOP                                      NOP\n\tCLIPw.xyz VF16, VF03                     NOP\n\tCLIPw.xyz VF16, VF04                     NOP\n\tCLIPw.xyz VF10, VF10                     NOP\n\tNOP                                      NOP\n\tNOP                                      NOP\n\tNOP                                      NOP\n\tNOP                                      FCAND VI01, 0x3330\n\tNOP                                      IBNE VI01, VI00, DoneAllChecks\n\tNOP                                      NOP\n\tMULz.w VF10, VF00, VF10                  IADDIU VI08, VI00, 0x1\n\tADD.xy VF02, VF00, VF00                  MOVE.xyzw VF01, VF16\n\tADDw.z VF02, VF00, VF00                  NOP\nDoneAllChecks:\n\tADD.xyz VF01, VF01, VF14                 IADD VI01, VI00, VI08\n\tNOP[E]                                   NOP\n\tNOP                                      NOP\nStartPointInsideAABB:\n\tADD.xyz VF01, VF12, VF14                 WAITQ\n\tNOP                                      IADDIU VI01, VI00, 0x1\n\tNOP[E]                                   NOP\n\tNOP                                      NOP\n\n\n; 860\n.globl Vu0LineToTriangleCollisionCompressedStart\nVu0LineToTriangleCollisionCompressedStart:\n\tITOF0.xyzw VF17, VF17                    LOI 0.000244140625\t; 1.0/4096.0\n\tITOF0.xyzw VF14, VF14                    NOP\n\tITOF0.xyzw VF15, VF15                    NOP\n\tITOF0.xyzw VF16, VF16                    NOP\n\tMULi.xyz VF17, VF17, I                   LOI 0.0078125\t\t; 1.0/128.0\n\tMULi.w VF17, VF17, I                     NOP\n\tMULi.xyzw VF14, VF14, I                  NOP\n\tMULi.xyzw VF15, VF15, I                  NOP\n\tMULi.xyzw VF16, VF16, I                  NOP\n; fall through\n\n; 8A8\n; VF12: point0\n; VF13: point1\n; VF14-16: verts\n; VF17: plane\n; out:\n;  VF01: intersection point\n;  VF02: triangle normal\n;  VF03 x: intersection parameter\n.globl Vu0LineToTriangleCollisionStart\nVu0LineToTriangleCollisionStart:\n\tMUL.xyz VF10, VF17, VF12                 LOI 0.5\n\tMUL.xyz VF11, VF17, VF13                 NOP\n\tSUB.xyz VF02, VF13, VF12                 NOP                            ; line dist\n\tADD.xyz VF17, VF17, VF00                 NOP\n\tMULi.w VF03, VF00, I                     NOP\n\tMULAx.w ACC, VF00, VF10                  NOP\n\tMADDAy.w ACC, VF00, VF10                 IADDIU VI06, VI00, 0xE0\n\tMADDz.w VF10, VF00, VF10                 FMAND VI05, VI06               ; -- normal sign flags, unused\n\tMULAx.w ACC, VF00, VF11                  NOP\n\tMADDAy.w ACC, VF00, VF11                 NOP\n\tMADDz.w VF11, VF00, VF11                 NOP\n\tSUB.w VF09, VF17, VF10                   NOP                            ; plane-pos 0\n\tCLIPw.xyz VF17, VF03                     NOP                            ; compare normal against 0.5 to figure out which in which dimension to compare\n\tNOP                                      IADDIU VI02, VI00, 0x10        ; Sw flag\n\tSUBA.w ACC, VF17, VF11                   NOP                            ; plane-pos 1\n\tSUB.w VF08, VF11, VF10                   FMAND VI01, VI02\n\tNOP                                      NOP\n\tNOP                                      NOP\n\tNOP                                      FMAND VI02, VI02\n\tNOP                                      IBEQ VI01, VI02, QuitAndFail   ; if on same side, no collision\n\tNOP                                      NOP\n\tNOP                                      DIV Q, VF09w, VF08w            ; parameter of intersection\n\tNOP                                      FCAND VI01, 0x3                ; check x direction\n\tNOP                                      IADDIU VI02, VI01, 0x7F\n\tNOP                                      IADDIU VI06, VI00, 0x80\n\tNOP                                      IAND VI02, VI02, VI06          ; Sx flag\n\tNOP                                      FCAND VI01, 0xC                ; check y direction\n\tNOP                                      IADDIU VI03, VI01, 0x3F\n\tMULAw.xyz ACC, VF12, VF00                IADDIU VI06, VI00, 0x40\n\tMADDq.xyz VF01, VF02, Q                  IAND VI03, VI03, VI06          ; point of intersection -- Sy flag\n\tMULx.w VF01, VF00, VF00                  FCAND VI01, 0x30               ; -- check z direction\n\tADDq.x VF03, VF00, Q                     IADDIU VI04, VI01, 0x1F        ; output parameter\n\tSUB.xyz VF05, VF15, VF14                 IADDIU VI06, VI00, 0x20        ; edge vectors\n\tSUB.xyz VF08, VF01, VF14                 IAND VI04, VI04, VI06          ; edge vectors -- Sz flag\n\tSUB.xyz VF06, VF16, VF15                 IADD VI06, VI02, VI03          ; edge vectors\n\tSUB.xyz VF09, VF01, VF15                 IADD VI06, VI06, VI04          ; edge vectors -- combine flags\n\tSUB.xyz VF07, VF14, VF16                 NOP                            ; edge vectors\n\tSUB.xyz VF10, VF01, VF16                 NOP                            ; edge vectors\n\tOPMULA.xyz ACC, VF08, VF05               NOP\n\tOPMSUB.xyz VF18, VF05, VF08              NOP                            ; cross1\n\tOPMULA.xyz ACC, VF09, VF06               NOP\n\tOPMSUB.xyz VF19, VF06, VF09              NOP                            ; cross2\n\tOPMULA.xyz ACC, VF10, VF07               NOP\n\tOPMSUB.xyz VF20, VF07, VF10              FMAND VI02, VI06               ; cross3\n\tNOP                                      NOP\n\tNOP                                      FMAND VI03, VI06\n\tNOP                                      NOP\n\tNOP                                      FMAND VI04, VI06\n\tNOP                                      NOP\n\tNOP                                      IBNE VI03, VI02, QuitAndFail   ; point has to lie on the same side of all edges (i.e. inside)\n\tNOP                                      NOP\n\tNOP                                      IBNE VI04, VI02, QuitAndFail\n\tNOP                                      NOP\n\tMULw.xyz VF02, VF17, VF00                IADDIU VI01, VI00, 0x1         ; success\n\tNOP[E]                                   NOP\n\tNOP                                      NOP\n\n\n; A68\n; VF12: center\n; VF14: line origin\n; VF15: line vector to other point\n; out: VF16 xyz: nearest point on line; w: distance to that point\nDistanceBetweenSphereAndLine:\n\tSUB.xyz VF20, VF12, VF14                 NOP\n\tMUL.xyz VF21, VF15, VF15                 NOP\n\tADDA.xyz ACC, VF14, VF15                 NOP\n\tMSUBw.xyz VF25, VF12, VF00               NOP                                        ; VF25 = VF12 - (VF14+VF15)\n\tMUL.xyz VF22, VF20, VF20                 NOP\n\tMUL.xyz VF23, VF20, VF15                 NOP\n\tMULAx.w ACC, VF00, VF21                  NOP\n\tMADDAy.w ACC, VF00, VF21                 NOP\n\tMADDz.w VF21, VF00, VF21                 NOP\t                                    ; MagSq VF15 (line length)\n\tMULAx.w ACC, VF00, VF23                  NOP\n\tMADDAy.w ACC, VF00, VF23                 NOP\n\tMADDz.w VF23, VF00, VF23                 NOP                                        ; dot(VF12-VF14, VF15)\n\tMULAx.w ACC, VF00, VF22                  NOP\n\tMADDAy.w ACC, VF00, VF22                 NOP\n\tMADDz.w VF22, VF00, VF22                 IADDIU VI08, VI00, 0x10                    ; MagSq VF12-VF14 -- Sw bit\n\tMUL.xyz VF25, VF25, VF25                 FMAND VI08, VI08\n\tNOP                                      DIV Q, VF23w, VF21w\n\tNOP                                      IBNE VI00, VI08, NegativeRatio\n\tNOP                                      NOP\n\tADDA.xyz ACC, VF00, VF14                 NOP\n\tMADDq.xyz VF16, VF15, Q                  WAITQ                                     ; nearest point on infinte line\n\tADDq.x VF24, VF00, Q                     NOP                                       ; ratio\n\tNOP                                      NOP\n\tNOP                                      NOP\n\tSUB.xyz VF26, VF16, VF12                 NOP\n\tCLIPw.xyz VF24, VF00                     NOP                                       ; compare ratio to 1.0\n\tNOP                                      NOP\n\tNOP                                      NOP\n\tMUL.xyz VF26, VF26, VF26                 NOP\n\tNOP                                      FCAND VI01, 0x1\n\tNOP                                      IBNE VI00, VI01, RatioGreaterThanOne\n\tNOP                                      NOP\n\tMULAx.w ACC, VF00, VF26                  NOP\n\tMADDAy.w ACC, VF00, VF26                 NOP\n\tMADDz.w VF16, VF00, VF26                 NOP                                      ; distance\n\tNOP                                      JR VI15\n\tNOP                                      NOP\nNegativeRatio:\n\tADD.xyz VF16, VF00, VF14                 NOP                 ; return line origin\n\tMUL.w VF16, VF00, VF22                   NOP                 ; and DistSq to it\n\tNOP                                      JR VI15\n\tNOP                                      NOP\nRatioGreaterThanOne:\n\tMULAx.w ACC, VF00, VF25                  NOP\n\tMADDAy.w ACC, VF00, VF25                 NOP\n\tMADDz.w VF16, VF00, VF25                 NOP\n\tADD.xyz VF16, VF14, VF15                 NOP                ; return toerh line point\n\tNOP                                      JR VI15\n\tNOP                                      NOP\n\n\n; BE0\n.globl Vu0SphereToTriangleCollisionCompressedStart\nVu0SphereToTriangleCollisionCompressedStart:\n\tITOF0.xyzw VF17, VF17                    LOI 0.000244140625\t; 1.0/4096.0\n\tITOF0.xyzw VF14, VF14                    NOP\n\tITOF0.xyzw VF15, VF15                    NOP\n\tITOF0.xyzw VF16, VF16                    NOP\n\tMULi.xyz VF17, VF17, I                   LOI 0.0078125\t\t; 1.0/128.0\n\tMULi.w VF17, VF17, I                     NOP\n\tMULi.xyzw VF14, VF14, I                  NOP\n\tMULi.xyzw VF15, VF15, I                  NOP\n\tMULi.xyzw VF16, VF16, I                  NOP\n; fall through\n\n; C28\n; VF12: sphere\n; VF14-16: verts\n; VF17: plane\n; out:\n;  VF01: intersection point\n;  VF02: triangle normal\n;  VF03 x: intersection parameter\n.globl Vu0SphereToTriangleCollisionStart\nVu0SphereToTriangleCollisionStart:\n\tMUL.xyz VF02, VF12, VF17                 LOI 0.1\n\tADD.xyz VF17, VF17, VF00                 NOP\n\tADDw.x VF13, VF00, VF12                  NOP\n\tNOP                                      NOP\n\tMULAx.w ACC, VF00, VF02                  IADDIU VI06, VI00, 0xE0\n\tMADDAy.w ACC, VF00, VF02                 FMAND VI05, VI06                  ; normal sign flags\n\tMADDAz.w ACC, VF00, VF02                 NOP\n\tMSUB.w VF02, VF00, VF17                  NOP                               ; center plane pos\n\tMULi.w VF03, VF00, I                     MOVE.xyzw VF04, VF03\n\tNOP                                      NOP\n\tNOP                                      NOP\n\tCLIPw.xyz VF13, VF02                     NOP                               ; compare dist and radius\n\tCLIPw.xyz VF17, VF03                     NOP\n\tMULAw.xyz ACC, VF12, VF00                IADDIU VI07, VI00, 0x0            ; -- clear test case\n\tMSUBw.xyz VF01, VF17, VF02               NOP\n\tMULx.w VF01, VF00, VF00                  FCAND VI01, 0x3                   ; projected center on plane\n\tABS.w VF02, VF02                         IBEQ VI00, VI01, QuitAndFail      ; no intersection\n\tNOP                                      NOP\n\tNOP                                      FCAND VI01, 0x3                   ; -- check x direction\n\tSUB.xyz VF02, VF12, VF01                 IADDIU VI02, VI01, 0x7F\n\tNOP                                      IADDIU VI06, VI00, 0x80\n\tSUB.xyz VF05, VF15, VF14                 IAND VI02, VI02, VI06\n\tSUB.xyz VF08, VF01, VF14                 FCAND VI01, 0xC                   ; -- check y direction\n\tSUB.xyz VF06, VF16, VF15                 IADDIU VI03, VI01, 0x3F\n\tSUB.xyz VF09, VF01, VF15                 IADDIU VI06, VI00, 0x40\n\tSUB.xyz VF07, VF14, VF16                 IAND VI03, VI03, VI06\n\tSUB.xyz VF10, VF01, VF16                 FCAND VI01, 0x30                  ; -- check z direction\n\tMUL.xyz VF03, VF02, VF02                 IADDIU VI04, VI01, 0x1F\n\tOPMULA.xyz ACC, VF08, VF05               IADDIU VI06, VI00, 0x20\n\tOPMSUB.xyz VF18, VF05, VF08              IAND VI04, VI04, VI06\n\tOPMULA.xyz ACC, VF09, VF06               NOP\n\tOPMSUB.xyz VF19, VF06, VF09              IADD VI06, VI02, VI03\n\tOPMULA.xyz ACC, VF10, VF07               IADD VI06, VI06, VI04             ; -- combine flags\n\tOPMSUB.xyz VF20, VF07, VF10              FMAND VI02, VI06                  ; -- cross 1 flags\n\tMULAx.w ACC, VF00, VF03                  IAND VI05, VI05, VI06\n\tMADDAy.w ACC, VF00, VF03                 FMAND VI03, VI06                  ; -- cross 2 flags\n\tMADDz.w VF03, VF00, VF03                 IADDIU VI08, VI00, 0x3\n\tNOP                                      FMAND VI04, VI06                  ; -- cross 3 flags\n\tNOP                                      NOP\n\tNOP                                      IBNE VI02, VI05, CheckSide2\n\tNOP                                      RSQRT Q, VF00w, VF03w\n\tADD.xyz VF04, VF00, VF16                 IADDIU VI07, VI07, 0x1                          ; inside side 1\nCheckSide2:\n\tNOP                                      IBNE VI03, VI05, CheckSide3\n\tNOP                                      NOP\n\tADD.xyz VF04, VF00, VF14                 IADDIU VI07, VI07, 0x1                          ; inside side 2\nCheckSide3:\n\tNOP                                      IBNE VI04, VI05, FinishCheckingSides\n\tNOP                                      NOP\n\tADD.xyz VF04, VF00, VF15                 IADDIU VI07, VI07, 0x1                          ; inside side 3\n\tNOP                                      NOP\n\tNOP                                      IBEQ VI07, VI08, TotallyInsideTriangle\n\tNOP                                      NOP\nFinishCheckingSides:\n\tMUL.x VF13, VF13, VF13                   IADDIU VI08, VI00, 0x2\n\tMULq.xyz VF02, VF02, Q                   WAITQ\n\tNOP                                      IBNE VI07, VI08, IntersectionOutsideTwoSides\n\tNOP                                      NOP\n\tNOP                                      IBEQ VI02, VI05, CheckDistanceSide2\n\tNOP                                      NOP\n\tNOP                                      MOVE.xyzw VF15, VF05\n\tNOP                                      BAL VI15, DistanceBetweenSphereAndLine\n\tNOP                                      NOP\n\tNOP                                      B ProcessLineResult\n\tNOP                                      NOP\nCheckDistanceSide2:\n\tNOP                                      IBEQ VI03, VI05, CheckDistanceSide3\n\tNOP                                      NOP\n\tNOP                                      MOVE.xyzw VF14, VF15\n\tNOP                                      MOVE.xyzw VF15, VF06\n\tNOP                                      BAL VI15, DistanceBetweenSphereAndLine\n\tNOP                                      NOP\n\tNOP                                      B ProcessLineResult\n\tNOP                                      NOP\nCheckDistanceSide3:\n\tNOP                                      MOVE.xyzw VF14, VF16\n\tNOP                                      MOVE.xyzw VF15, VF07\n\tNOP                                      BAL VI15, DistanceBetweenSphereAndLine\n\tNOP                                      NOP\n\tNOP                                      B ProcessLineResult\n\tNOP                                      NOP\nIntersectionOutsideTwoSides:\n\tSUB.xyz VF05, VF04, VF12                 NOP\n\tADD.xyz VF01, VF00, VF04                 NOP                                ; col point\n\tSUB.xyz VF02, VF12, VF04                 NOP\n\tNOP                                      NOP\n\tMUL.xyz VF05, VF05, VF05                 NOP\n\tNOP                                      NOP\n\tNOP                                      NOP\n\tNOP                                      NOP\n\tMULAx.w ACC, VF00, VF05                  NOP\n\tMADDAy.w ACC, VF00, VF05                 NOP\n\tMADDz.w VF05, VF00, VF05                 NOP                                ; distSq to vertex\n\tNOP                                      NOP\n\tNOP                                      NOP\n\tNOP                                      NOP\n\tCLIPw.xyz VF13, VF05                     SQRT Q, VF05w                      ; compare radiusSq and distSq\n\tNOP                                      NOP\n\tNOP                                      NOP\n\tNOP                                      NOP\n\tNOP                                      FCAND VI01, 0x1\n\tADDq.x VF03, VF00, Q                     WAITQ                              ; dist to vertex\n\tNOP                                      IBEQ VI00, VI01, QuitAndFail       ; too far\n\tNOP                                      NOP\n\tNOP                                      NOP\n\tNOP                                      DIV Q, VF00w, VF03x\n\tMULq.xyz VF02, VF02, Q                   WAITQ                              ; col normal\n\tNOP[E]                                   NOP\n\tNOP                                      NOP\nTotallyInsideTriangle:\n\tADDw.x VF03, VF00, VF02                  WAITQ\n\tMULq.xyz VF02, VF02, Q                   NOP\n\tNOP[E]                                   IADDIU VI01, VI00, 0x1\n\tNOP                                      NOP\nProcessLineResult:\n\tCLIPw.xyz VF13, VF16                     SQRT Q, VF16w\n\tADD.xyz VF01, VF00, VF16                 NOP\n\tSUB.xyz VF02, VF12, VF16                 NOP\n\tNOP                                      NOP\n\tNOP                                      FCAND VI01, 0x1\n\tADDq.x VF03, VF00, Q                     WAITQ\n\tNOP                                      IBEQ VI00, VI01, QuitAndFail\n\tNOP                                      NOP\n\tNOP                                      NOP\n\tNOP                                      DIV Q, VF00w, VF03x\n\tMULq.xyz VF02, VF02, Q                   WAITQ\n\tNOP[E]                                   NOP\n\tNOP                                      NOP\n\nEndOfMicrocode:\n"
  },
  {
    "path": "src/collision/vu0Collision_2.s",
    "content": "QuitAndFail2:\n\tNOP[E]                                   IADDIU VI01, VI00, 0x0\n\tNOP                                      NOP\n\n\nQuitAndSucceed2:\n\tNOP[E]                                   IADDIU VI01, VI00, 0x1\n\tNOP                                      NOP\n\n\n; 20\nGetBBVertices:\n\tMULw.xy VF02, VF01, VF00                 NOP\n\tMUL.z VF02, VF01, VF11                   NOP\n\tMULw.xz VF03, VF01, VF00                 NOP\n\tMUL.y VF03, VF01, VF11                   NOP\n\tMULw.x VF04, VF01, VF00                  NOP\n\tMUL.yz VF04, VF01, VF11                  NOP\n\tNOP                                      JR VI15\n\tNOP                                      NOP\n\n\n; 60\nVu0OBBToOBBCollision:\n\tSUBw.xyz VF11, VF00, VF00                LOI 0.5\n\tMULi.xyz VF12, VF12, I                   NOP\n\tMULi.xyz VF13, VF13, I                   NOP\n\tNOP                                      NOP\n\tNOP                                      NOP\n\tNOP                                      MOVE.xyz VF01, VF12\n\tNOP                                      BAL VI15, GetBBVertices\n\tNOP                                      NOP\n\tMULAx.xyz ACC, VF14, VF01                NOP\n\tMADDAy.xyz ACC, VF15, VF01               NOP\n\tMADDz.xyz VF01, VF16, VF01               NOP\n\tMULAx.xyz ACC, VF14, VF02                NOP\n\tMADDAy.xyz ACC, VF15, VF02               NOP\n\tMADDz.xyz VF02, VF16, VF02               NOP\n\tMULAx.xyz ACC, VF14, VF03                NOP\n\tMADDAy.xyz ACC, VF15, VF03               NOP\n\tMADDz.xyz VF03, VF16, VF03               NOP\n\tMULAx.xyz ACC, VF14, VF04                NOP\n\tMADDAy.xyz ACC, VF15, VF04               NOP\n\tMADDz.xyz VF04, VF16, VF04               NOP\n\tABS.xyz VF05, VF01                       NOP\n\tABS.xyz VF06, VF02                       NOP\n\tABS.xyz VF07, VF03                       NOP\n\tABS.xyz VF08, VF04                       NOP\n\tNOP                                      NOP\n\tMAX.xyz VF05, VF05, VF06                 NOP\n\tNOP                                      NOP\n\tMAX.xyz VF07, VF07, VF08                 NOP\n\tNOP                                      NOP\n\tNOP                                      NOP\n\tNOP                                      NOP\n\tMAX.xyz VF05, VF05, VF07                 NOP\n\tNOP                                      NOP\n\tNOP                                      NOP\n\tNOP                                      NOP\n\tADD.xyz VF09, VF05, VF13                 NOP\n\tNOP                                      NOP\n\tNOP                                      NOP\n\tNOP                                      NOP\n\tMULx.w VF05, VF00, VF09                  NOP\n\tMULy.w VF06, VF00, VF09                  NOP\n\tMULz.w VF07, VF00, VF09                  NOP\n\tCLIPw.xyz VF17, VF05                     NOP\n\tCLIPw.xyz VF17, VF06                     NOP\n\tCLIPw.xyz VF17, VF07                     MOVE.xyz VF01, VF13\n\tNOP                                      NOP\n\tNOP                                      NOP\n\tNOP                                      NOP\n\tNOP                                      FCAND VI01, 0x3330\n\tNOP                                      IBNE VI01, VI00, QuitAndFail2\n\tNOP                                      NOP\n\tNOP                                      BAL VI15, GetBBVertices\n\tNOP                                      NOP\n\tMULAx.xyz ACC, VF18, VF01                NOP\n\tMADDAy.xyz ACC, VF19, VF01               NOP\n\tMADDz.xyz VF01, VF20, VF01               NOP\n\tMULAx.xyz ACC, VF18, VF02                NOP\n\tMADDAy.xyz ACC, VF19, VF02               NOP\n\tMADDz.xyz VF02, VF20, VF02               NOP\n\tMULAx.xyz ACC, VF18, VF03                NOP\n\tMADDAy.xyz ACC, VF19, VF03               NOP\n\tMADDz.xyz VF03, VF20, VF03               NOP\n\tMULAx.xyz ACC, VF18, VF04                NOP\n\tMADDAy.xyz ACC, VF19, VF04               NOP\n\tMADDz.xyz VF04, VF20, VF04               NOP\n\tABS.xyz VF05, VF01                       NOP\n\tABS.xyz VF06, VF02                       NOP\n\tABS.xyz VF07, VF03                       NOP\n\tABS.xyz VF08, VF04                       NOP\n\tNOP                                      NOP\n\tMAX.xyz VF05, VF05, VF06                 NOP\n\tNOP                                      NOP\n\tMAX.xyz VF07, VF07, VF08                 NOP\n\tNOP                                      NOP\n\tNOP                                      NOP\n\tNOP                                      NOP\n\tMAX.xyz VF05, VF05, VF07                 NOP\n\tNOP                                      NOP\n\tNOP                                      NOP\n\tNOP                                      NOP\n\tADD.xyz VF09, VF05, VF12                 NOP\n\tNOP                                      NOP\n\tNOP                                      NOP\n\tNOP                                      NOP\n\tMULx.w VF05, VF00, VF09                  NOP\n\tMULy.w VF06, VF00, VF09                  NOP\n\tMULz.w VF07, VF00, VF09                  NOP\n\tCLIPw.xyz VF21, VF05                     NOP\n\tCLIPw.xyz VF21, VF06                     NOP\n\tCLIPw.xyz VF21, VF07                     NOP\n\tNOP                                      NOP\n\tNOP                                      NOP\n\tNOP                                      NOP\n\tNOP                                      FCAND VI01, 0x3330\n\tNOP                                      IBNE VI01, VI00, QuitAndFail2\n\tNOP                                      NOP\n\tSUB.xyz VF06, VF02, VF01                 NOP\n\tSUB.xyz VF07, VF03, VF01                 NOP\n\tADD.xyz VF08, VF04, VF01                 NOP\n\tADD.x VF09, VF00, VF12                   NOP\n\tADD.yz VF09, VF00, VF00                  NOP\n\tADD.y VF10, VF00, VF12                   NOP\n\tADD.xz VF10, VF00, VF00                  NOP\n\tADD.z VF11, VF00, VF12                   IADDI VI04, VI00, 0x0\n\tADD.xy VF11, VF00, VF00                  IADD VI02, VI00, VI00\n\tOPMULA.xyz ACC, VF06, VF09               NOP\n\tOPMSUB.xyz VF01, VF09, VF06              NOP\n\tOPMULA.xyz ACC, VF06, VF10               NOP\n\tOPMSUB.xyz VF02, VF10, VF06              NOP\n\tOPMULA.xyz ACC, VF06, VF11               NOP\n\tOPMSUB.xyz VF03, VF11, VF06              SQI.xyzw VF01, (VI02++)\n\tOPMULA.xyz ACC, VF07, VF09               NOP\n\tOPMSUB.xyz VF01, VF09, VF07              SQI.xyzw VF02, (VI02++)\n\tOPMULA.xyz ACC, VF07, VF10               NOP\n\tOPMSUB.xyz VF02, VF10, VF07              SQI.xyzw VF03, (VI02++)\n\tOPMULA.xyz ACC, VF07, VF11               NOP\n\tOPMSUB.xyz VF03, VF11, VF07              SQI.xyzw VF01, (VI02++)\n\tOPMULA.xyz ACC, VF08, VF09               NOP\n\tOPMSUB.xyz VF01, VF09, VF08              SQI.xyzw VF02, (VI02++)\n\tOPMULA.xyz ACC, VF08, VF10               NOP\n\tOPMSUB.xyz VF02, VF10, VF08              SQI.xyzw VF03, (VI02++)\n\tOPMULA.xyz ACC, VF08, VF11               LOI 0.5\n\tOPMSUB.xyz VF01, VF11, VF08              SQI.xyzw VF01, (VI02++)\n\tMULi.xyz VF06, VF06, I                   NOP\n\tMULi.xyz VF07, VF07, I                   SQI.xyzw VF02, (VI02++)\n\tMULi.xyz VF08, VF08, I                   NOP\n\tMUL.xyz VF02, VF21, VF01                 NOP\n\tMUL.xyz VF03, VF12, VF01                 NOP\n\tMUL.xyz VF09, VF06, VF01                 NOP\n\tMUL.xyz VF10, VF07, VF01                 NOP\n\tMUL.xyz VF11, VF08, VF01                 NOP\n\tABS.xyz VF03, VF03                       NOP\n\tADDy.x VF05, VF09, VF09                  NOP\n\tADDx.y VF05, VF10, VF10                  NOP\n\tADDx.z VF05, VF11, VF11                  NOP\n\tNOP                                      NOP\nEdgePairLoop:\n\tADDz.x VF05, VF05, VF09                  NOP\n\tADDz.y VF05, VF05, VF10                  NOP\n\tADDy.z VF05, VF05, VF11                  NOP\n\tMULAx.w ACC, VF00, VF02                  IADD VI03, VI02, VI00\n\tMADDAy.w ACC, VF00, VF02                 LQD.xyzw VF01, (--VI02)\n\tMADDz.w VF02, VF00, VF02                 NOP\n\tABS.xyz VF05, VF05                       NOP\n\tMULAx.w ACC, VF00, VF03                  NOP\n\tMADDAy.w ACC, VF00, VF03                 NOP\n\tMADDAz.w ACC, VF00, VF03                 NOP\n\tMADDAx.w ACC, VF00, VF05                 NOP\n\tMADDAy.w ACC, VF00, VF05                 NOP\n\tMADDz.w VF03, VF00, VF05                 NOP\n\tADDw.x VF04, VF00, VF02                  NOP\n\tMUL.xyz VF02, VF21, VF01                 NOP\n\tMUL.xyz VF03, VF12, VF01                 NOP\n\tMUL.xyz VF09, VF06, VF01                 NOP\n\tCLIPw.xyz VF04, VF03                     NOP\n\tMUL.xyz VF10, VF07, VF01                 NOP\n\tMUL.xyz VF11, VF08, VF01                 NOP\n\tABS.xyz VF03, VF03                       NOP\n\tADDy.x VF05, VF09, VF09                  FCAND VI01, 0x3\n\tADDx.y VF05, VF10, VF10                  IBNE VI01, VI00, QuitAndFail2\n\tADDx.z VF05, VF11, VF11                  NOP\n\tNOP                                      IBNE VI03, VI00, EdgePairLoop\n\tNOP                                      NOP\n\tNOP[E]                                   IADDIU VI01, VI00, 0x1\n\tNOP                                      NOP\n\nEndOfMicrocode2:\n"
  },
  {
    "path": "src/control/AutoPilot.cpp",
    "content": "#include \"common.h\"\n\n#include \"AutoPilot.h\"\n\n#include \"CarCtrl.h\"\n#include \"Curves.h\"\n#include \"PathFind.h\"\n\nvoid CAutoPilot::ModifySpeed(float speed)\n{\n\tm_fMaxTrafficSpeed = Max(0.01f, speed);\n\tfloat positionBetweenNodes = (float)(CTimer::GetTimeInMilliseconds() - m_nTimeEnteredCurve) / m_nTimeToSpendOnCurrentCurve;\n\tCCarPathLink* pCurrentLink = &ThePaths.m_carPathLinks[m_nCurrentPathNodeInfo];\n\tCCarPathLink* pNextLink = &ThePaths.m_carPathLinks[m_nNextPathNodeInfo];\n\tfloat currentPathLinkForwardX = m_nCurrentDirection * ThePaths.m_carPathLinks[m_nCurrentPathNodeInfo].GetDirX();\n\tfloat currentPathLinkForwardY = m_nCurrentDirection * ThePaths.m_carPathLinks[m_nCurrentPathNodeInfo].GetDirY();\n\tfloat nextPathLinkForwardX = m_nNextDirection * ThePaths.m_carPathLinks[m_nNextPathNodeInfo].GetDirX();\n\tfloat nextPathLinkForwardY = m_nNextDirection * ThePaths.m_carPathLinks[m_nNextPathNodeInfo].GetDirY();\n\tCVector positionOnCurrentLinkIncludingLane(\n\t\tpCurrentLink->GetX() + ((m_nCurrentLane + 0.5f) * LANE_WIDTH) * currentPathLinkForwardY,\n\t\tpCurrentLink->GetY() - ((m_nCurrentLane + 0.5f) * LANE_WIDTH) * currentPathLinkForwardX,\n\t\t0.0f);\n\tCVector positionOnNextLinkIncludingLane(\n\t\tpNextLink->GetX() + ((m_nNextLane + 0.5f) * LANE_WIDTH) * nextPathLinkForwardY,\n\t\tpNextLink->GetY() - ((m_nNextLane + 0.5f) * LANE_WIDTH) * nextPathLinkForwardX,\n\t\t0.0f);\n\tm_nTimeToSpendOnCurrentCurve = CCurves::CalcSpeedScaleFactor(\n\t\t&positionOnCurrentLinkIncludingLane,\n\t\t&positionOnNextLinkIncludingLane,\n\t\tcurrentPathLinkForwardX, currentPathLinkForwardY,\n\t\tnextPathLinkForwardX, nextPathLinkForwardY\n\t) * (1000.0f / m_fMaxTrafficSpeed);\n#ifdef FIX_BUGS\n\t/* Casting timer to float is very unwanted, and in this case even causes crashes. */\n\tm_nTimeEnteredCurve = CTimer::GetTimeInMilliseconds() -\n\t\t(uint32)(positionBetweenNodes * m_nTimeToSpendOnCurrentCurve);\n#else\n\tm_nTimeEnteredCurve = CTimer::GetTimeInMilliseconds() - positionBetweenNodes * m_nTimeToSpendOnCurrentCurve;\n#endif\n}\n\nvoid CAutoPilot::RemoveOnePathNode()\n{\n\t--m_nPathFindNodesCount;\n\tfor (int i = 0; i < m_nPathFindNodesCount; i++)\n\t\tm_aPathFindNodesInfo[i] = m_aPathFindNodesInfo[i + 1];\n}\n\n#ifdef COMPATIBLE_SAVES\nvoid CAutoPilot::Save(uint8*& buf)\n{\n\tWriteSaveBuf<int32>(buf, m_nCurrentRouteNode);\n\tWriteSaveBuf<int32>(buf, m_nNextRouteNode);\n\tWriteSaveBuf<int32>(buf, m_nPrevRouteNode);\n\tWriteSaveBuf<int32>(buf, m_nTimeEnteredCurve);\n\tWriteSaveBuf<int32>(buf, m_nTimeToSpendOnCurrentCurve);\n\tWriteSaveBuf<uint32>(buf, m_nCurrentPathNodeInfo);\n\tWriteSaveBuf<uint32>(buf, m_nNextPathNodeInfo);\n\tWriteSaveBuf<uint32>(buf, m_nPreviousPathNodeInfo);\n\tWriteSaveBuf<uint32>(buf, m_nAntiReverseTimer);\n\tWriteSaveBuf<uint32>(buf, m_nTimeToStartMission);\n\tWriteSaveBuf<int8>(buf, m_nPreviousDirection);\n\tWriteSaveBuf<int8>(buf, m_nCurrentDirection);\n\tWriteSaveBuf<int8>(buf, m_nNextDirection);\n\tWriteSaveBuf<int8>(buf, m_nCurrentLane);\n\tWriteSaveBuf<int8>(buf, m_nNextLane);\n\tWriteSaveBuf<uint8>(buf, m_nDrivingStyle);\n\tWriteSaveBuf<uint8>(buf, m_nCarMission);\n\tWriteSaveBuf<uint8>(buf, m_nTempAction);\n\tWriteSaveBuf<uint32>(buf, m_nTimeTempAction);\n\tWriteSaveBuf<float>(buf, m_fMaxTrafficSpeed);\n\tWriteSaveBuf<uint8>(buf, m_nCruiseSpeed);\n\tWriteSaveBuf<uint8>(buf, m_nCruiseSpeedMultiplierType);\n\tSkipSaveBuf(buf, 2);\n\tWriteSaveBuf<float>(buf, m_fCruiseSpeedMultiplier);\n\tuint8 flags = 0;\n\tif (m_bSlowedDownBecauseOfCars) flags |= BIT(0);\n\tif (m_bSlowedDownBecauseOfPeds) flags |= BIT(1);\n\tif (m_bStayInCurrentLevel) flags |= BIT(2);\n\tif (m_bStayInFastLane) flags |= BIT(3);\n\tif (m_bIgnorePathfinding) flags |= BIT(4);\n\tWriteSaveBuf<uint8>(buf, flags);\n\tWriteSaveBuf<uint8>(buf, m_nSwitchDistance);\n\tSkipSaveBuf(buf, 2);\n\tWriteSaveBuf<float>(buf, m_vecDestinationCoors.x);\n\tWriteSaveBuf<float>(buf, m_vecDestinationCoors.y);\n\tWriteSaveBuf<float>(buf, m_vecDestinationCoors.z);\n\tSkipSaveBuf(buf, 32);\n\tWriteSaveBuf<int16>(buf, m_nPathFindNodesCount);\n\tSkipSaveBuf(buf, 6);\n}\n\nvoid CAutoPilot::Load(uint8*& buf)\n{\n\tm_nCurrentRouteNode = ReadSaveBuf<int32>(buf);\n\tm_nNextRouteNode = ReadSaveBuf<int32>(buf);\n\tm_nPrevRouteNode = ReadSaveBuf<int32>(buf);\n\tm_nTimeEnteredCurve = ReadSaveBuf<int32>(buf);\n\tm_nTimeToSpendOnCurrentCurve = ReadSaveBuf<int32>(buf);\n\tm_nCurrentPathNodeInfo = ReadSaveBuf<uint32>(buf);\n\tm_nNextPathNodeInfo = ReadSaveBuf<uint32>(buf);\n\tm_nPreviousPathNodeInfo = ReadSaveBuf<uint32>(buf);\n\tm_nAntiReverseTimer = ReadSaveBuf<uint32>(buf);\n\tm_nTimeToStartMission = ReadSaveBuf<uint32>(buf);\n\tm_nPreviousDirection = ReadSaveBuf<int8>(buf);\n\tm_nCurrentDirection = ReadSaveBuf<int8>(buf);\n\tm_nNextDirection = ReadSaveBuf<int8>(buf);\n\tm_nCurrentLane = ReadSaveBuf<int8>(buf);\n\tm_nNextLane = ReadSaveBuf<int8>(buf);\n\tm_nDrivingStyle = ReadSaveBuf<uint8>(buf);\n\tm_nCarMission = ReadSaveBuf<uint8>(buf);\n\tm_nTempAction = ReadSaveBuf<uint8>(buf);\n\tm_nTimeTempAction = ReadSaveBuf<uint32>(buf);\n\tm_fMaxTrafficSpeed = ReadSaveBuf<float>(buf);\n\tm_nCruiseSpeed = ReadSaveBuf<uint8>(buf);\n\tm_nCruiseSpeedMultiplierType = ReadSaveBuf<uint8>(buf);\n\tSkipSaveBuf(buf, 2);\n\tm_fCruiseSpeedMultiplier = ReadSaveBuf<float>(buf);\n\tuint8 flags = ReadSaveBuf<uint8>(buf);\n\tm_bSlowedDownBecauseOfCars = !!(flags & BIT(0));\n\tm_bSlowedDownBecauseOfPeds = !!(flags & BIT(1));\n\tm_bStayInCurrentLevel = !!(flags & BIT(2));\n\tm_bStayInFastLane = !!(flags & BIT(3));\n\tm_bIgnorePathfinding = !!(flags & BIT(4));\n\tm_nSwitchDistance = ReadSaveBuf<uint8>(buf);\n\tSkipSaveBuf(buf, 2);\n\tm_vecDestinationCoors.x = ReadSaveBuf<float>(buf);\n\tm_vecDestinationCoors.y = ReadSaveBuf<float>(buf);\n\tm_vecDestinationCoors.z = ReadSaveBuf<float>(buf);\n\tSkipSaveBuf(buf, 32);\n\tm_nPathFindNodesCount = ReadSaveBuf<int16>(buf);\n\tSkipSaveBuf(buf, 6);\n}\n#endif"
  },
  {
    "path": "src/control/AutoPilot.h",
    "content": "#pragma once\n#include \"Timer.h\"\n\nclass CVehicle;\nstruct CPathNode;\n\nenum eCarMission\n{\n\tMISSION_NONE,\n\tMISSION_CRUISE,\n\tMISSION_RAMPLAYER_FARAWAY,\n\tMISSION_RAMPLAYER_CLOSE,\n\tMISSION_BLOCKPLAYER_FARAWAY,\n\tMISSION_BLOCKPLAYER_CLOSE,\n\tMISSION_BLOCKPLAYER_HANDBRAKESTOP,\n\tMISSION_WAITFORDELETION,\n\tMISSION_GOTOCOORDS,\n\tMISSION_GOTOCOORDS_STRAIGHT,\n\tMISSION_EMERGENCYVEHICLE_STOP,\n\tMISSION_STOP_FOREVER,\n\tMISSION_GOTOCOORDS_ACCURATE,\n\tMISSION_GOTO_COORDS_STRAIGHT_ACCURATE,\n\tMISSION_GOTOCOORDS_ASTHECROWSWIMS,\n\tMISSION_RAMCAR_FARAWAY,\n\tMISSION_RAMCAR_CLOSE,\n\tMISSION_BLOCKCAR_FARAWAY,\n\tMISSION_BLOCKCAR_CLOSE,\n\tMISSION_BLOCKCAR_HANDBRAKESTOP,\n\tMISSION_HELI_FLYTOCOORS,\n\tMISSION_ATTACKPLAYER,\n\tMISSION_PLANE_FLYTOCOORS,\n\tMISSION_HELI_LAND,\n\tMISSION_SLOWLY_DRIVE_TOWARDS_PLAYER_1,\n\tMISSION_SLOWLY_DRIVE_TOWARDS_PLAYER_2,\n\tMISSION_BLOCKPLAYER_FORWARDANDBACK\n};\n\nenum eCarTempAction\n{\n\tTEMPACT_NONE,\n\tTEMPACT_WAIT,\n\tTEMPACT_REVERSE,\n\tTEMPACT_HANDBRAKETURNLEFT,\n\tTEMPACT_HANDBRAKETURNRIGHT,\n\tTEMPACT_HANDBRAKESTRAIGHT,\n\tTEMPACT_TURNLEFT,\n\tTEMPACT_TURNRIGHT,\n\tTEMPACT_GOFORWARD,\n\tTEMPACT_SWERVELEFT,\n\tTEMPACT_SWERVERIGHT\n};\n\nenum eCarDrivingStyle\n{\n\tDRIVINGSTYLE_STOP_FOR_CARS,\n\tDRIVINGSTYLE_SLOW_DOWN_FOR_CARS,\n\tDRIVINGSTYLE_AVOID_CARS,\n\tDRIVINGSTYLE_PLOUGH_THROUGH,\n\tDRIVINGSTYLE_STOP_FOR_CARS_IGNORE_LIGHTS\n};\n\nclass CAutoPilot {\npublic:\n\tint32 m_nCurrentRouteNode;\n\tint32 m_nNextRouteNode;\n\tint32 m_nPrevRouteNode;\n\tint32 m_nTimeEnteredCurve;\n\tint32 m_nTimeToSpendOnCurrentCurve;\n\tuint32 m_nCurrentPathNodeInfo;\n\tuint32 m_nNextPathNodeInfo;\n\tuint32 m_nPreviousPathNodeInfo;\n\tuint32 m_nAntiReverseTimer;\n\tuint32 m_nTimeToStartMission;\n\tint8 m_nPreviousDirection;\n\tint8 m_nCurrentDirection;\n\tint8 m_nNextDirection;\n\tint8 m_nCurrentLane;\n\tint8 m_nNextLane;\n\tuint8 m_nDrivingStyle;\n\tuint8 m_nCarMission;\n\tuint8 m_nTempAction;\n\tuint32 m_nTimeTempAction;\n\tfloat m_fMaxTrafficSpeed;\n\tuint8 m_nCruiseSpeed;\n\tuint8 m_nCruiseSpeedMultiplierType;\n\tfloat m_fCruiseSpeedMultiplier;\n\tuint8 m_bSlowedDownBecauseOfCars : 1;\n\tuint8 m_bSlowedDownBecauseOfPeds : 1;\n\tuint8 m_bStayInCurrentLevel : 1;\n\tuint8 m_bStayInFastLane : 1;\n\tuint8 m_bIgnorePathfinding : 1;\n\tuint8 m_nSwitchDistance;\n\tCVector m_vecDestinationCoors;\n\tCPathNode *m_aPathFindNodesInfo[NUM_PATH_NODES_IN_AUTOPILOT];\n\tint16 m_nPathFindNodesCount;\n\tCVehicle *m_pTargetCar;\n\n\tCAutoPilot(void) {\n\t\tm_nPrevRouteNode = 0;\n\t\tm_nNextRouteNode = m_nPrevRouteNode;\n\t\tm_nCurrentRouteNode = m_nNextRouteNode;\n\t\tm_nTimeEnteredCurve = 0;\n\t\tm_nTimeToSpendOnCurrentCurve = 1000;\n\t\tm_nPreviousPathNodeInfo = 0;\n\t\tm_nNextPathNodeInfo = m_nPreviousPathNodeInfo;\n\t\tm_nCurrentPathNodeInfo = m_nNextPathNodeInfo;\n\t\tm_nNextDirection = 1;\n\t\tm_nCurrentDirection = m_nNextDirection;\n\t\tm_nCurrentLane = m_nNextLane = 0;\n\t\tm_nDrivingStyle = DRIVINGSTYLE_STOP_FOR_CARS;\n\t\tm_nCarMission = MISSION_NONE;\n\t\tm_nTempAction = TEMPACT_NONE;\n\t\tm_nCruiseSpeed = 10;\n\t\tm_fMaxTrafficSpeed = 10.0f;\n\t\tm_bSlowedDownBecauseOfPeds = false;\n\t\tm_bSlowedDownBecauseOfCars = false;\n\t\tm_nPathFindNodesCount = 0;\n\t\tm_pTargetCar = 0;\n\t\tm_nTimeToStartMission = CTimer::GetTimeInMilliseconds();\n\t\tm_nAntiReverseTimer = m_nTimeToStartMission;\n\t\tm_bStayInFastLane = false;\n\t\tm_nCruiseSpeedMultiplierType = 0;\n\t\tm_fCruiseSpeedMultiplier = 1.0f;\n\t}\n\n\tvoid ModifySpeed(float);\n\tvoid RemoveOnePathNode();\n#ifdef COMPATIBLE_SAVES\n\tvoid Save(uint8*& buf);\n\tvoid Load(uint8*& buf);\n#endif\n\n\tfloat GetCruiseSpeed(void) { return m_nCruiseSpeed * m_fCruiseSpeedMultiplier; }\n\n};\n\nVALIDATE_SIZE(CAutoPilot, 0x70);\n"
  },
  {
    "path": "src/control/Bridge.cpp",
    "content": "#include \"common.h\"\n\n#include \"Bridge.h\"\n#include \"Pools.h\"\n#include \"ModelIndices.h\"\n#include \"PathFind.h\"\n#include \"Stats.h\"\n\nCEntity *CBridge::pLiftRoad;\nCEntity *CBridge::pLiftPart;\nCEntity *CBridge::pWeight;\n\nint CBridge::State;\nint CBridge::OldState;\n\nfloat CBridge::DefaultZLiftPart;\nfloat CBridge::DefaultZLiftRoad;\nfloat CBridge::DefaultZLiftWeight;\n\nfloat CBridge::OldLift;\n\nuint32 CBridge::TimeOfBridgeBecomingOperational;\n\nvoid CBridge::Init()\n{\n#ifdef GTA_BRIDGE\n\tFindBridgeEntities();\n\tOldLift = -1.0f;\n\tif (pLiftPart && pWeight)\n\t{\n\t\tDefaultZLiftPart   = pLiftPart->GetPosition().z;\n\t\tDefaultZLiftWeight = pWeight->GetPosition().z;\n\n\t\tif (pLiftRoad)\n\t\t\tDefaultZLiftRoad = pLiftRoad->GetPosition().z;\n\n\t\tThePaths.SetLinksBridgeLights(-330.0, -230.0, -700.0, -588.0, true);\n\t}\n#endif\n}\n\nvoid CBridge::Update()\n{\n#ifdef GTA_BRIDGE\n\tif (!pLiftPart || !pWeight)\n\t\treturn;\n\n\tOldState = State;\n\n\tfloat liftHeight;\n\n\t// Set bridge height and state\n\tif (CStats::CommercialPassed)\n\t{\n\t\tif (TimeOfBridgeBecomingOperational == 0)\n\t\t\tTimeOfBridgeBecomingOperational = CTimer::GetTimeInMilliseconds();\n\n\t\t// Time remaining for bridge to become operational\n\t\t// uint16, so after about a minute it overflows to 0 and the cycle repeats\n\t\tuint16 timeElapsed = CTimer::GetTimeInMilliseconds() - TimeOfBridgeBecomingOperational;\n\n\t\t// Calculate lift part height and bridge state\n\t\tif (timeElapsed < 10000)\n\t\t{\n\t\t\tState = STATE_LIFT_PART_MOVING_DOWN;\n\t\t\tliftHeight = 25.0f - timeElapsed / 10000.0f * 25.0f;\n\t\t}\n\t\telse if (timeElapsed < 40000)\n\t\t{\n\t\t\tliftHeight = 0.0f;\n\t\t\tState = STATE_LIFT_PART_IS_DOWN;\n\t\t}\n\t\telse if (timeElapsed < 50000)\n\t\t{\n\t\t\tliftHeight = 0.0f;\n\t\t\tState = STATE_LIFT_PART_ABOUT_TO_MOVE_UP;\n\t\t}\n\t\telse if (timeElapsed < 60000)\n\t\t{\n\t\t\tState = STATE_LIFT_PART_MOVING_UP;\n\t\t\tliftHeight = (timeElapsed - 50000) / 10000.0f * 25.0f;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tliftHeight = 25.0f;\n\t\t\tState = STATE_LIFT_PART_IS_UP;\n\t\t}\n\t}\n\telse\n\t{\n\t\tliftHeight = 25.0f;\n\t\tTimeOfBridgeBecomingOperational = 0;\n\t\tState = STATE_BRIDGE_LOCKED;\n\t}\n\n\t// Move bridge part\n\tif (liftHeight != OldLift)\n\t{\n\t\tpLiftPart->GetMatrix().GetPosition().z = DefaultZLiftPart + liftHeight;\n\t\tpLiftPart->GetMatrix().UpdateRW();\n\t\tpLiftPart->UpdateRwFrame();\n\t\tif (pLiftRoad)\n\t\t{\n\t\t\tpLiftRoad->GetMatrix().GetPosition().z = DefaultZLiftRoad + liftHeight;\n\t\t\tpLiftRoad->GetMatrix().UpdateRW();\n\t\t\tpLiftRoad->UpdateRwFrame();\n\t\t}\n\t\tpWeight->GetMatrix().GetPosition().z = DefaultZLiftWeight - liftHeight;\n\t\tpWeight->GetMatrix().UpdateRW();\n\t\tpWeight->UpdateRwFrame();\n\n\t\tOldLift = liftHeight;\n\t}\n\n\tif (State == STATE_LIFT_PART_ABOUT_TO_MOVE_UP && OldState == STATE_LIFT_PART_IS_DOWN)\n\t\tThePaths.SetLinksBridgeLights(-330.0, -230.0, -700.0, -588.0, true);\n\telse if (State == STATE_LIFT_PART_IS_DOWN && OldState == STATE_LIFT_PART_MOVING_DOWN)\n\t\tThePaths.SetLinksBridgeLights(-330.0, -230.0, -700.0, -588.0, false);\n#endif\n}\n\nbool CBridge::ShouldLightsBeFlashing()\n{\n#ifdef GTA_BRIDGE\n\treturn State != STATE_LIFT_PART_IS_DOWN;\n#else\n\treturn false;\n#endif\n}\n\nvoid CBridge::FindBridgeEntities()\n{\n#ifdef GTA_BRIDGE\n\tpWeight   = nil;\n\tpLiftRoad = nil;\n\tpLiftPart = nil;\n\n\tfor (int i = CPools::GetBuildingPool()->GetSize()-1; i >= 0; i--) {\n\t\tCBuilding* entry = CPools::GetBuildingPool()->GetSlot(i);\n\t\tif (entry)\n\t\t{\n\t\t\tif (entry->GetModelIndex() == MI_BRIDGELIFT)\n\t\t\t\tpLiftPart = entry;\n\t\t\telse if (entry->GetModelIndex() == MI_BRIDGEROADSEGMENT)\n\t\t\t\tpLiftRoad = entry;\n\t\t\telse if (entry->GetModelIndex() == MI_BRIDGEWEIGHT)\n\t\t\t\tpWeight = entry;\n\t\t}\n\t}\n#endif\n}\n\nbool CBridge::ThisIsABridgeObjectMovingUp(int index)\n{\n#ifdef GTA_BRIDGE\n\tif (index != MI_BRIDGEROADSEGMENT && index != MI_BRIDGELIFT)\n\t\treturn false;\n\n\treturn State == STATE_LIFT_PART_ABOUT_TO_MOVE_UP || State == STATE_LIFT_PART_MOVING_UP;\n#else\n\treturn false;\n#endif\n}\n"
  },
  {
    "path": "src/control/Bridge.h",
    "content": "#pragma once\n\nclass CEntity;\n\nenum bridgeStates {\n    STATE_BRIDGE_LOCKED,\n    STATE_LIFT_PART_IS_UP,\n    STATE_LIFT_PART_MOVING_DOWN,\n    STATE_LIFT_PART_IS_DOWN,\n    STATE_LIFT_PART_ABOUT_TO_MOVE_UP,\n    STATE_LIFT_PART_MOVING_UP\n};\n\nclass CBridge\n{\npublic:\n\tstatic CEntity *pLiftRoad, *pLiftPart, *pWeight;\n\tstatic int State, OldState;\n\tstatic float DefaultZLiftPart, DefaultZLiftRoad, DefaultZLiftWeight;\n\tstatic float OldLift;\n\tstatic uint32 TimeOfBridgeBecomingOperational;\n\n\tstatic void Init();\n\tstatic void Update();\n\tstatic bool ShouldLightsBeFlashing();\n\tstatic void FindBridgeEntities();\n\tstatic bool ThisIsABridgeObjectMovingUp(int);\n};\n"
  },
  {
    "path": "src/control/CarAI.cpp",
    "content": "#include \"common.h\"\n\n#include \"CarAI.h\"\n\n#include \"Accident.h\"\n#include \"AutoPilot.h\"\n#include \"CarCtrl.h\"\n#include \"General.h\"\n#include \"HandlingMgr.h\"\n#include \"ModelIndices.h\"\n#include \"PlayerPed.h\"\n#include \"Wanted.h\"\n#include \"DMAudio.h\"\n#include \"Fire.h\"\n#include \"Pools.h\"\n#include \"Population.h\"\n#include \"Timer.h\"\n#include \"TrafficLights.h\"\n#include \"Vehicle.h\"\n#include \"World.h\"\n#include \"ZoneCull.h\"\n\n#define DISTANCE_TO_SWITCH_DISTANCE_GOTO 20.0f\n\nfloat CCarAI::FindSwitchDistanceClose(CVehicle* pVehicle)\n{\n\treturn pVehicle->AutoPilot.m_nSwitchDistance;\n}\n\nfloat CCarAI::FindSwitchDistanceFarNormalVehicle(CVehicle* pVehicle)\n{\n\treturn FindSwitchDistanceClose(pVehicle) + 5.0f;\n}\n\nfloat CCarAI::FindSwitchDistanceFar(CVehicle* pVehicle)\n{\n\tif (pVehicle->bIsLawEnforcer)\n\t\treturn 50.0f;\n\treturn FindSwitchDistanceFarNormalVehicle(pVehicle);\n}\n\nvoid CCarAI::BackToCruisingIfNoWantedLevel(CVehicle* pVehicle)\n{\n\tif (FindPlayerPed()->m_pWanted->m_bIgnoredByEveryone || pVehicle->bIsLawEnforcer &&\n\t\t(FindPlayerPed()->m_pWanted->GetWantedLevel() == 0 || FindPlayerPed()->m_pWanted->m_bIgnoredByCops || CCullZones::NoPolice())) {\n\t\tCCarCtrl::JoinCarWithRoadSystem(pVehicle);\n\t\tpVehicle->AutoPilot.m_nCarMission = MISSION_CRUISE;\n\t\tpVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_STOP_FOR_CARS;\n\t\tpVehicle->m_bSirenOrAlarm = false;\n\t\tif (CCullZones::NoPolice())\n\t\t\tpVehicle->AutoPilot.m_nCarMission = MISSION_NONE;\n\t}\n}\n\nvoid CCarAI::UpdateCarAI(CVehicle* pVehicle)\n{\n\tif (pVehicle->bIsLawEnforcer){\n\t\tif (pVehicle->AutoPilot.m_nCarMission == MISSION_BLOCKCAR_FARAWAY ||\n\t\t\tpVehicle->AutoPilot.m_nCarMission == MISSION_RAMPLAYER_FARAWAY ||\n\t\t\tpVehicle->AutoPilot.m_nCarMission == MISSION_BLOCKPLAYER_CLOSE ||\n\t\t\tpVehicle->AutoPilot.m_nCarMission == MISSION_RAMPLAYER_CLOSE)\n\t\t\tpVehicle->AutoPilot.m_nCruiseSpeed = FindPoliceCarSpeedForWantedLevel(pVehicle);\n\t}\n\tswitch (pVehicle->GetStatus()){\n\tcase STATUS_PLAYER:\n\tcase STATUS_PLAYER_PLAYBACKFROMBUFFER:\n\tcase STATUS_TRAIN_MOVING:\n\tcase STATUS_TRAIN_NOT_MOVING:\n\tcase STATUS_HELI:\n\tcase STATUS_PLANE:\n\tcase STATUS_PLAYER_REMOTE:\n\tcase STATUS_PLAYER_DISABLED:\n\t\tbreak;\n\tcase STATUS_SIMPLE:\n\tcase STATUS_PHYSICS:\n\t\tswitch (pVehicle->AutoPilot.m_nCarMission) {\n\t\tcase MISSION_RAMPLAYER_FARAWAY:\n\t\t\tif (FindSwitchDistanceClose(pVehicle) > (FindPlayerCoors() - pVehicle->GetPosition()).Magnitude2D() ||\n\t\t\t\tpVehicle->AutoPilot.m_bIgnorePathfinding) {\n\t\t\t\tpVehicle->AutoPilot.m_nCarMission = MISSION_RAMPLAYER_CLOSE;\n\t\t\t\tif (pVehicle->UsesSiren())\n\t\t\t\t\tpVehicle->m_bSirenOrAlarm = true;\n\t\t\t}\n\t\t\tBackToCruisingIfNoWantedLevel(pVehicle);\n\t\t\tbreak;\n\t\tcase MISSION_RAMPLAYER_CLOSE:\n\t\t\tif (FindSwitchDistanceFar(pVehicle) >= (FindPlayerCoors() - pVehicle->GetPosition()).Magnitude2D() ||\n\t\t\t\tpVehicle->AutoPilot.m_bIgnorePathfinding) {\n\t\t\t\tif (FindPlayerVehicle()) {\n\t\t\t\t\tif (pVehicle->GetHasCollidedWith(FindPlayerVehicle())) {\n\t\t\t\t\t\tif (pVehicle->AutoPilot.m_nTempAction != TEMPACT_TURNLEFT && pVehicle->AutoPilot.m_nTempAction != TEMPACT_TURNRIGHT) {\n\t\t\t\t\t\t\tif (FindPlayerVehicle()->GetMoveSpeed().Magnitude() < 0.05f) {\n\t\t\t\t\t\t\t\tpVehicle->AutoPilot.m_nTempAction = TEMPACT_REVERSE;\n\t\t\t\t\t\t\t\tpVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 800;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tpVehicle->AutoPilot.m_nTempAction = TEMPACT_REVERSE;\n\t\t\t\t\t\t\t\tpVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 50;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (FindPlayerVehicle() && FindPlayerVehicle()->GetMoveSpeed().Magnitude() < 0.05f)\n#ifdef FIX_BUGS\n\t\t\t\t\tpVehicle->m_nTimeBlocked += CTimer::GetTimeStepInMilliseconds();\n#else\n\t\t\t\t\tpVehicle->m_nTimeBlocked += 1000.0f / 60.0f * CTimer::GetTimeStep();\n#endif\n\t\t\t\telse\n\t\t\t\t\tpVehicle->m_nTimeBlocked = 0;\n\t\t\t\tif (!FindPlayerVehicle() || FindPlayerVehicle()->IsUpsideDown() ||\n\t\t\t\t\tFindPlayerVehicle()->GetMoveSpeed().Magnitude() < 0.05f && pVehicle->m_nTimeBlocked > TIME_COPS_WAIT_TO_EXIT_AFTER_STOPPING) {\n\t\t\t\t\tif (pVehicle->bIsLawEnforcer &&\n\t\t\t\t\t\t(pVehicle->GetModelIndex() != MI_RHINO || pVehicle->m_randomSeed > 10000) &&\n\t\t\t\t\t\t(FindPlayerCoors() - pVehicle->GetPosition()).Magnitude2D() < 10.0f) {\n\t\t\t\t\t\tTellOccupantsToLeaveCar(pVehicle);\n\t\t\t\t\t\tpVehicle->AutoPilot.m_nCruiseSpeed = 0;\n\t\t\t\t\t\tpVehicle->AutoPilot.m_nCarMission = MISSION_NONE;\n\t\t\t\t\t\tif (FindPlayerPed()->m_pWanted->GetWantedLevel() <= 1)\n\t\t\t\t\t\t\tpVehicle->m_bSirenOrAlarm = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (!CCarCtrl::JoinCarWithRoadSystemGotoCoors(pVehicle, FindPlayerCoors(), true)){\n\t\t\t\tpVehicle->AutoPilot.m_nCarMission = MISSION_RAMPLAYER_FARAWAY;\n\t\t\t\tpVehicle->m_bSirenOrAlarm = false;\n\t\t\t\tpVehicle->m_nCarHornTimer = 0;\n\t\t\t}\n\t\t\tif (pVehicle->bIsLawEnforcer)\n\t\t\t\tMellowOutChaseSpeed(pVehicle);\n\t\t\tBackToCruisingIfNoWantedLevel(pVehicle);\n\t\t\tbreak;\n\t\tcase MISSION_BLOCKPLAYER_FARAWAY:\n\t\t\tif (FindSwitchDistanceClose(pVehicle) > (FindPlayerCoors() - pVehicle->GetPosition()).Magnitude2D() ||\n\t\t\t\tpVehicle->AutoPilot.m_bIgnorePathfinding) {\n\t\t\t\tpVehicle->AutoPilot.m_nCarMission = MISSION_BLOCKPLAYER_CLOSE;\n\t\t\t\tif (pVehicle->UsesSiren())\n\t\t\t\t\tpVehicle->m_bSirenOrAlarm = true;\n\t\t\t}\n\t\t\tBackToCruisingIfNoWantedLevel(pVehicle);\n\t\t\tbreak;\n\t\tcase MISSION_BLOCKPLAYER_CLOSE:\n\t\t\tif (FindSwitchDistanceFar(pVehicle) >= (FindPlayerCoors() - pVehicle->GetPosition()).Magnitude2D() ||\n\t\t\t\tpVehicle->AutoPilot.m_bIgnorePathfinding) {\n\t\t\t\tif (FindPlayerVehicle() && FindPlayerVehicle()->GetMoveSpeed().Magnitude() < 0.04f)\n#ifdef FIX_BUGS\n\t\t\t\t\tpVehicle->m_nTimeBlocked += CTimer::GetTimeStepInMilliseconds();\n#else\n\t\t\t\t\tpVehicle->m_nTimeBlocked += 1000.0f / 60.0f * CTimer::GetTimeStep();\n#endif\n\t\t\t\telse\n\t\t\t\t\tpVehicle->m_nTimeBlocked = 0;\n\t\t\t\tif (!FindPlayerVehicle() || FindPlayerVehicle()->IsUpsideDown() ||\n\t\t\t\t\tFindPlayerVehicle()->GetMoveSpeed().Magnitude() < 0.04f && pVehicle->m_nTimeBlocked > TIME_COPS_WAIT_TO_EXIT_AFTER_STOPPING) {\n\t\t\t\t\tif (pVehicle->bIsLawEnforcer &&\n\t\t\t\t\t\t(pVehicle->GetModelIndex() != MI_RHINO || pVehicle->m_randomSeed > 10000) &&\n\t\t\t\t\t\t(FindPlayerCoors() - pVehicle->GetPosition()).Magnitude2D() < 10.0f) {\n\t\t\t\t\t\tTellOccupantsToLeaveCar(pVehicle);\n\t\t\t\t\t\tpVehicle->AutoPilot.m_nCruiseSpeed = 0;\n\t\t\t\t\t\tpVehicle->AutoPilot.m_nCarMission = MISSION_NONE;\n\t\t\t\t\t\tif (FindPlayerPed()->m_pWanted->GetWantedLevel() <= 1)\n\t\t\t\t\t\t\tpVehicle->m_bSirenOrAlarm = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}else if (!CCarCtrl::JoinCarWithRoadSystemGotoCoors(pVehicle, FindPlayerCoors(), true)) {\n\t\t\t\tpVehicle->AutoPilot.m_nCarMission = MISSION_BLOCKPLAYER_FARAWAY;\n\t\t\t\tpVehicle->m_bSirenOrAlarm = false;\n\t\t\t\tpVehicle->m_nCarHornTimer = 0;\n\t\t\t}\n\t\t\tif (pVehicle->bIsLawEnforcer)\n\t\t\t\tMellowOutChaseSpeed(pVehicle);\n\t\t\tBackToCruisingIfNoWantedLevel(pVehicle);\n\t\t\tbreak;\n\t\tcase MISSION_GOTOCOORDS:\n\t\t\tif ((pVehicle->AutoPilot.m_vecDestinationCoors - pVehicle->GetPosition()).Magnitude2D() < FindSwitchDistanceClose(pVehicle) ||\n\t\t\t  pVehicle->AutoPilot.m_bIgnorePathfinding)\n\t\t\t\tpVehicle->AutoPilot.m_nCarMission = MISSION_GOTOCOORDS_STRAIGHT;\n\t\t\tbreak;\n\t\tcase MISSION_GOTOCOORDS_STRAIGHT:\n\t\t{\n\t\t\tfloat distance = (pVehicle->AutoPilot.m_vecDestinationCoors - pVehicle->GetPosition()).Magnitude2D();\n\t\t\tif ((pVehicle->bIsAmbulanceOnDuty || pVehicle->bIsFireTruckOnDuty) && distance < 20.0f)\n\t\t\t\tpVehicle->AutoPilot.m_nCarMission = MISSION_EMERGENCYVEHICLE_STOP;\n\t\t\tif (distance < 3.0f){\n\t\t\t\tpVehicle->AutoPilot.m_nCarMission = MISSION_NONE;\n\t\t\t\tpVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE;\n\t\t\t\tif (pVehicle->bParking) {\n\t\t\t\t\tTellOccupantsToLeaveCar(pVehicle);\n\t\t\t\t\tpVehicle->bParking = false;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (distance > FindSwitchDistanceFarNormalVehicle(pVehicle) && !pVehicle->AutoPilot.m_bIgnorePathfinding && (CTimer::GetFrameCounter() & 7) == 0){\n\t\t\t\tpVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE;\n\t\t\t\tpVehicle->AutoPilot.m_nCarMission = (CCarCtrl::JoinCarWithRoadSystemGotoCoors(pVehicle, pVehicle->AutoPilot.m_vecDestinationCoors, true)) ?\n\t\t\t\t\tMISSION_GOTOCOORDS_STRAIGHT : MISSION_GOTOCOORDS;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tcase MISSION_EMERGENCYVEHICLE_STOP:\n\t\t\tif (pVehicle->GetMoveSpeed().Magnitude2D() < 0.01f){\n\t\t\t\tif (pVehicle->bIsAmbulanceOnDuty){\n\t\t\t\t\tfloat distance = 30.0f;\n\t\t\t\t\tif (gAccidentManager.FindNearestAccident(pVehicle->AutoPilot.m_vecDestinationCoors, &distance)){\n\t\t\t\t\t\tTellOccupantsToLeaveCar(pVehicle);\n\t\t\t\t\t\tpVehicle->AutoPilot.m_nCarMission = MISSION_STOP_FOREVER;\n\t\t\t\t\t}else{\n\t\t\t\t\t\tCCarCtrl::JoinCarWithRoadSystem(pVehicle);\n\t\t\t\t\t\tpVehicle->AutoPilot.m_nCarMission = MISSION_CRUISE;\n\t\t\t\t\t\tpVehicle->m_bSirenOrAlarm = false;\n\t\t\t\t\t\tpVehicle->AutoPilot.m_nCruiseSpeed = 17;\n\t\t\t\t\t\tif (pVehicle->bIsAmbulanceOnDuty){\n\t\t\t\t\t\t\tpVehicle->bIsAmbulanceOnDuty = false;\n\t\t\t\t\t\t\t--CCarCtrl::NumAmbulancesOnDuty;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (pVehicle->bIsFireTruckOnDuty) {\n\t\t\t\t\tfloat distance = 30.0f;\n\t\t\t\t\tif (gFireManager.FindNearestFire(pVehicle->AutoPilot.m_vecDestinationCoors, &distance)) {\n\t\t\t\t\t\tTellOccupantsToLeaveCar(pVehicle);\n\t\t\t\t\t\tpVehicle->AutoPilot.m_nCarMission = MISSION_STOP_FOREVER;\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tCCarCtrl::JoinCarWithRoadSystem(pVehicle);\n\t\t\t\t\t\tpVehicle->AutoPilot.m_nCarMission = MISSION_CRUISE;\n\t\t\t\t\t\tpVehicle->m_bSirenOrAlarm = false;\n\t\t\t\t\t\tpVehicle->AutoPilot.m_nCruiseSpeed = 17;\n\t\t\t\t\t\tif (pVehicle->bIsFireTruckOnDuty) {\n\t\t\t\t\t\t\tpVehicle->bIsFireTruckOnDuty = false;\n\t\t\t\t\t\t\t--CCarCtrl::NumFiretrucksOnDuty;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\tcase MISSION_GOTOCOORDS_ACCURATE:\n\t\t\tif ((pVehicle->AutoPilot.m_vecDestinationCoors - pVehicle->GetPosition()).Magnitude2D() < FindSwitchDistanceClose(pVehicle) ||\n\t\t\t\tpVehicle->AutoPilot.m_bIgnorePathfinding)\n\t\t\t\tpVehicle->AutoPilot.m_nCarMission = MISSION_GOTO_COORDS_STRAIGHT_ACCURATE;\n\t\t\tbreak;\n\t\tcase MISSION_GOTO_COORDS_STRAIGHT_ACCURATE:\n\t\t{\n\t\t\tfloat distance = (pVehicle->AutoPilot.m_vecDestinationCoors - pVehicle->GetPosition()).Magnitude2D();\n\t\t\tif (distance < 1.0f) {\n\t\t\t\tpVehicle->AutoPilot.m_nCarMission = MISSION_NONE;\n\t\t\t\tpVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE;\n\t\t\t\tif (pVehicle->bParking) {\n\t\t\t\t\tTellOccupantsToLeaveCar(pVehicle);\n\t\t\t\t\tpVehicle->bParking = false;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (distance > FindSwitchDistanceFarNormalVehicle(pVehicle) && !pVehicle->AutoPilot.m_bIgnorePathfinding && (CTimer::GetFrameCounter() & 7) == 0) {\n\t\t\t\tpVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE;\n\t\t\t\tpVehicle->AutoPilot.m_nCarMission = (CCarCtrl::JoinCarWithRoadSystemGotoCoors(pVehicle, pVehicle->AutoPilot.m_vecDestinationCoors, true)) ?\n\t\t\t\t\tMISSION_GOTO_COORDS_STRAIGHT_ACCURATE : MISSION_GOTOCOORDS_ACCURATE;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tcase MISSION_RAMCAR_FARAWAY:\n\t\t\tif (pVehicle->AutoPilot.m_pTargetCar){\n\t\t\t\tif ((pVehicle->GetPosition() - pVehicle->AutoPilot.m_pTargetCar->GetPosition()).Magnitude2D() < FindSwitchDistanceClose(pVehicle) ||\n\t\t\t\t  pVehicle->AutoPilot.m_bIgnorePathfinding)\n\t\t\t\t\tpVehicle->AutoPilot.m_nCarMission = MISSION_RAMCAR_CLOSE;\n\t\t\t}else{\n\t\t\t\tpVehicle->AutoPilot.m_nCarMission = MISSION_NONE;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase MISSION_RAMCAR_CLOSE:\n\t\t\tif (pVehicle->AutoPilot.m_pTargetCar){\n#ifdef FIX_BUGS // btw fixed in SA\n\t\t\t\tif (FindPlayerVehicle() == pVehicle->AutoPilot.m_pTargetCar)\n#endif\n\t\t\t\t\tBackToCruisingIfNoWantedLevel(pVehicle);\n\t\t\t\tif ((pVehicle->AutoPilot.m_pTargetCar->GetPosition() - pVehicle->GetPosition()).Magnitude2D() <= FindSwitchDistanceFar(pVehicle) ||\n\t\t\t\t  pVehicle->AutoPilot.m_bIgnorePathfinding){\n\t\t\t\t\tif (pVehicle->GetHasCollidedWith(pVehicle->AutoPilot.m_pTargetCar)){\n\t\t\t\t\t\tif (pVehicle->GetMoveSpeed().Magnitude() < 0.04f){\n\t\t\t\t\t\t\tpVehicle->AutoPilot.m_nTempAction = TEMPACT_REVERSE;\n\t\t\t\t\t\t\tpVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 800;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}else{\n\t\t\t\t\tpVehicle->AutoPilot.m_nCarMission = MISSION_RAMCAR_FARAWAY;\n\t\t\t\t\tCCarCtrl::JoinCarWithRoadSystem(pVehicle);\n\t\t\t\t}\n\t\t\t}else{\n\t\t\t\tpVehicle->AutoPilot.m_nCarMission = MISSION_NONE;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase MISSION_BLOCKCAR_FARAWAY:\n\t\t\tif (pVehicle->AutoPilot.m_pTargetCar){\n\t\t\t\tif ((pVehicle->AutoPilot.m_pTargetCar->GetPosition() - pVehicle->GetPosition()).Magnitude2D() < FindSwitchDistanceClose(pVehicle) ||\n\t\t\t\t  pVehicle->AutoPilot.m_bIgnorePathfinding){\n\t\t\t\t\tpVehicle->AutoPilot.m_nCarMission = MISSION_BLOCKCAR_CLOSE;\n\t\t\t\t\tif (pVehicle->UsesSiren())\n\t\t\t\t\t\tpVehicle->m_bSirenOrAlarm = true;\n\t\t\t\t}\n\t\t\t}else{\n\t\t\t\tpVehicle->AutoPilot.m_nCarMission = MISSION_NONE;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase MISSION_BLOCKCAR_CLOSE:\n\t\t\tif (pVehicle->AutoPilot.m_pTargetCar){\n\t\t\t\tif ((pVehicle->AutoPilot.m_pTargetCar->GetPosition() - pVehicle->GetPosition()).Magnitude2D() > FindSwitchDistanceFar(pVehicle) &&\n\t\t\t\t  !pVehicle->AutoPilot.m_bIgnorePathfinding){\n\t\t\t\t\tpVehicle->AutoPilot.m_nCarMission = MISSION_BLOCKCAR_FARAWAY;\n\t\t\t\t\tpVehicle->m_bSirenOrAlarm = false;\n\t\t\t\t\tpVehicle->m_nCarHornTimer = 0;\n\t\t\t\t\tCCarCtrl::JoinCarWithRoadSystem(pVehicle);\n\t\t\t\t}\n\t\t\t}else{\n\t\t\t\tpVehicle->AutoPilot.m_nCarMission = MISSION_NONE;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase MISSION_ATTACKPLAYER:\n\t\t\tif (pVehicle->bIsLawEnforcer)\n\t\t\t\tMellowOutChaseSpeedBoat(pVehicle);\n\t\t\tBackToCruisingIfNoWantedLevel(pVehicle);\n\t\t\tbreak;\n\t\tcase MISSION_SLOWLY_DRIVE_TOWARDS_PLAYER_1:\n\t\t\tif (((CVector2D)(pVehicle->AutoPilot.m_vecDestinationCoors) - pVehicle->GetPosition()).Magnitude() < 1.5f)\n\t\t\t\tpVehicle->AutoPilot.m_nCarMission = MISSION_SLOWLY_DRIVE_TOWARDS_PLAYER_2;\n\t\t\tBackToCruisingIfNoWantedLevel(pVehicle);\n\t\t\tbreak;\n\t\tcase MISSION_SLOWLY_DRIVE_TOWARDS_PLAYER_2:\n\t\t{\n\t\t\tfloat distance = ((CVector2D)FindPlayerCoors() - pVehicle->GetPosition()).Magnitude();\n\t\t\tif (distance < 13.0f) {\n\t\t\t\tTellOccupantsToLeaveCar(pVehicle);\n\t\t\t\tpVehicle->AutoPilot.m_nCruiseSpeed = 0;\n\t\t\t\tpVehicle->AutoPilot.m_nCarMission = MISSION_STOP_FOREVER;\n\t\t\t}\n\t\t\tif (distance > 70.0f || FindPlayerPed()->m_pWanted->m_bIgnoredByEveryone ||\n\t\t\t\t(FindPlayerPed()->m_pWanted->GetWantedLevel() == 0 || FindPlayerPed()->m_pWanted->m_bIgnoredByCops || CCullZones::NoPolice())) {\n\t\t\t\tTellOccupantsToLeaveCar(pVehicle);\n\t\t\t\tpVehicle->AutoPilot.m_nCruiseSpeed = 0;\n\t\t\t\tpVehicle->AutoPilot.m_nCarMission = MISSION_STOP_FOREVER;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tcase MISSION_BLOCKPLAYER_FORWARDANDBACK:\n\t\t{\n\t\t\tCVector2D diff = (CVector2D)FindPlayerCoors() - pVehicle->GetPosition();\n\t\t\tfloat distance = Max(0.001f, diff.Magnitude());\n\t\t\tif (!FindPlayerVehicle() || DotProduct2D(CVector2D(diff.x / distance, diff.y / distance), FindPlayerSpeed()) > 0.05f)\n\t\t\t\tpVehicle->AutoPilot.m_nCarMission = MISSION_BLOCKPLAYER_CLOSE;\n\t\t\tBackToCruisingIfNoWantedLevel(pVehicle);\n\t\t\tbreak;\n\t\t}\n\t\tdefault:\n\t\t\tif (pVehicle->bIsLawEnforcer && FindPlayerPed()->m_pWanted->GetWantedLevel() > 0 && !CCullZones::NoPolice()){\n\t\t\t\tif (ABS(FindPlayerCoors().x - pVehicle->GetPosition().x) > 10.0f ||\n\t\t\t\t  ABS(FindPlayerCoors().y - pVehicle->GetPosition().y) > 10.0f){\n\t\t\t\t\tpVehicle->AutoPilot.m_nCruiseSpeed = FindPoliceCarSpeedForWantedLevel(pVehicle);\n\t\t\t\t\tpVehicle->SetStatus(STATUS_PHYSICS);\n\t\t\t\t\tpVehicle->AutoPilot.m_nCarMission = \n\t\t\t\t\t\tpVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_BOAT ? FindPoliceBoatMissionForWantedLevel() : FindPoliceCarMissionForWantedLevel();\n\t\t\t\t\tpVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE;\n\t\t\t\t\tpVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS;\n\t\t\t\t}else if (pVehicle->AutoPilot.m_nCarMission == MISSION_CRUISE){\n\t\t\t\t\tpVehicle->SetStatus(STATUS_PHYSICS);\n\t\t\t\t\tTellOccupantsToLeaveCar(pVehicle);\n\t\t\t\t\tpVehicle->AutoPilot.m_nCruiseSpeed = 0;\n\t\t\t\t\tpVehicle->AutoPilot.m_nCarMission = MISSION_NONE;\n\t\t\t\t\tif (FindPlayerPed()->m_pWanted->GetWantedLevel() <= 1)\n\t\t\t\t\t\tpVehicle->m_bSirenOrAlarm = false;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tbreak;\n\tcase STATUS_ABANDONED:\n\tcase STATUS_WRECKED:\n\t\tpVehicle->AutoPilot.m_nCarMission = MISSION_NONE;\n\t\tpVehicle->AutoPilot.m_nCruiseSpeed = 0;\n\t\tbreak;\n\t}\n\tif (pVehicle->bIsLawEnforcer && FindPlayerPed()->m_pWanted->GetWantedLevel() >= 1 && CCullZones::PoliceAbandonCars()) {\n\t\tTellOccupantsToLeaveCar(pVehicle);\n\t\tpVehicle->AutoPilot.m_nCruiseSpeed = 0;\n\t\tpVehicle->AutoPilot.m_nCarMission = MISSION_NONE;\n\t}\n\tfloat flatSpeed = pVehicle->GetMoveSpeed().MagnitudeSqr2D();\n\tif (flatSpeed > SQR(0.018f)){\n\t\tpVehicle->AutoPilot.m_nTimeToStartMission = CTimer::GetTimeInMilliseconds();\n\t\tpVehicle->AutoPilot.m_nAntiReverseTimer = CTimer::GetTimeInMilliseconds();\n\t}\n\tif (pVehicle->GetStatus() == STATUS_PHYSICS && pVehicle->AutoPilot.m_nTempAction == TEMPACT_NONE){\n\t\tif (pVehicle->AutoPilot.m_nCarMission != MISSION_NONE){\n\t\t\tif (pVehicle->AutoPilot.m_nCarMission != MISSION_STOP_FOREVER &&\n\t\t\t\tpVehicle->AutoPilot.m_nCarMission != MISSION_BLOCKPLAYER_HANDBRAKESTOP &&\n\t\t\t  pVehicle->AutoPilot.m_nCruiseSpeed != 0 &&\n\t\t\t  (pVehicle->VehicleCreatedBy != RANDOM_VEHICLE || pVehicle->AutoPilot.m_nCarMission != MISSION_CRUISE)){\n\t\t\t\tif (pVehicle->AutoPilot.m_nDrivingStyle != DRIVINGSTYLE_STOP_FOR_CARS\n\t\t\t\t\t&& pVehicle->AutoPilot.m_nDrivingStyle != DRIVINGSTYLE_STOP_FOR_CARS_IGNORE_LIGHTS ||\n\t\t\t\t\tpVehicle->VehicleCreatedBy == MISSION_VEHICLE\n\t\t\t\t\t) {\n\t\t\t\t\tif (CTimer::GetTimeInMilliseconds() - pVehicle->m_nLastTimeCollided > 500)\n\t\t\t\t\t\tpVehicle->AutoPilot.m_nAntiReverseTimer = CTimer::GetTimeInMilliseconds();\n\t\t\t\t\tif (flatSpeed < SQR(0.018f) && CTimer::GetTimeInMilliseconds() - pVehicle->AutoPilot.m_nAntiReverseTimer > 2000){\n\t\t\t\t\t\tpVehicle->AutoPilot.m_nTempAction = TEMPACT_REVERSE;\n\t\t\t\t\t\tif (pVehicle->AutoPilot.m_nCarMission != MISSION_NONE &&\n\t\t\t\t\t\t  pVehicle->AutoPilot.m_nCarMission != MISSION_CRUISE || pVehicle->VehicleCreatedBy == MISSION_VEHICLE)\n\t\t\t\t\t\t\tpVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 1500;\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tpVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 750;\n\t\t\t\t\t\tpVehicle->AutoPilot.m_nAntiReverseTimer = CTimer::GetTimeInMilliseconds();\n\t\t\t\t\t\tif (pVehicle->VehicleCreatedBy == RANDOM_VEHICLE)\n\t\t\t\t\t\t\tpVehicle->AutoPilot.m_nDrivingStyle = Max(DRIVINGSTYLE_AVOID_CARS, pVehicle->AutoPilot.m_nDrivingStyle);\n\t\t\t\t\t\tpVehicle->PlayCarHorn();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tif ((pVehicle->m_randomSeed & 7) == 0){\n\t\tif (CTimer::GetTimeInMilliseconds() - pVehicle->AutoPilot.m_nTimeToStartMission > 30000 &&\n\t\t  CTimer::GetPreviousTimeInMilliseconds() - pVehicle->AutoPilot.m_nTimeToStartMission <= 30000 &&\n\t\t  pVehicle->AutoPilot.m_nCarMission == MISSION_CRUISE &&\n\t\t  !CTrafficLights::ShouldCarStopForBridge(pVehicle)){\n\t\t\tpVehicle->SetStatus(STATUS_PHYSICS);\n\t\t\tCCarCtrl::SwitchVehicleToRealPhysics(pVehicle);\n\t\t\tpVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS;\n\t\t\tpVehicle->AutoPilot.m_nTempAction = TEMPACT_REVERSE;\n\t\t\tpVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 400;\n\t\t}\n\t}\n\tif (pVehicle->bIsLawEnforcer) {\n\t\tif (pVehicle->AutoPilot.m_nCarMission == MISSION_RAMPLAYER_FARAWAY ||\n\t\t\tpVehicle->AutoPilot.m_nCarMission == MISSION_RAMPLAYER_CLOSE) {\n\t\t\tif (FindPlayerVehicle() && FindPlayerVehicle()->GetVehicleAppearance() == VEHICLE_APPEARANCE_BIKE)\n\t\t\t\tpVehicle->AutoPilot.m_nCarMission = MISSION_BLOCKPLAYER_FARAWAY;\n\t\t}\n\t}\n\tif (pVehicle->GetUp().z < -0.7f){\n\t\tpVehicle->AutoPilot.m_nTempAction = TEMPACT_WAIT;\n\t\tpVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 1000;\n\t}\n\tif (pVehicle->AutoPilot.m_nTempAction == TEMPACT_NONE){\n\t\tswitch (pVehicle->AutoPilot.m_nCarMission){\n\t\tcase MISSION_RAMPLAYER_FARAWAY:\n\t\tcase MISSION_RAMPLAYER_CLOSE:\n\t\tcase MISSION_BLOCKPLAYER_FARAWAY:\n\t\tcase MISSION_BLOCKPLAYER_CLOSE:\n\t\t\tif (FindPlayerVehicle() && FindPlayerSpeed().Magnitude() > pVehicle->GetMoveSpeed().Magnitude()){\n\t\t\t\tif (FindPlayerSpeed().Magnitude() > 0.1f){\n\t\t\t\t\tif (DotProduct2D(FindPlayerVehicle()->GetForward(), pVehicle->GetForward()) > 0.0f){\n\t\t\t\t\t\tCVector2D dist = pVehicle->GetPosition() - FindPlayerCoors();\n\t\t\t\t\t\tCVector2D speed = FindPlayerSpeed();\n\t\t\t\t\t\tif (0.5f * dist.Magnitude() * speed.Magnitude() < DotProduct2D(dist, speed)){\n\t\t\t\t\t\t\tif ((FindPlayerCoors() - pVehicle->GetPosition()).Magnitude() > 12.0f){\n\t\t\t\t\t\t\t\tpVehicle->AutoPilot.m_nTempAction = TEMPACT_WAIT;\n\t\t\t\t\t\t\t\tpVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 500;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\tdefault: break;\n\t\t}\n\t}\n\tif (pVehicle->pDriver && pVehicle->pDriver->m_objective == OBJECTIVE_KILL_CHAR_ANY_MEANS){\n\t\tif ((pVehicle->GetPosition() - FindPlayerCoors()).Magnitude() < 15.0f){\n\t\t\tif (!FindPlayerVehicle() || pVehicle->GetHasCollidedWith(FindPlayerVehicle())){\n\t\t\t\tpVehicle->AutoPilot.m_nTempAction = TEMPACT_WAIT;\n\t\t\t\tpVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 3000;\n\t\t\t}\n\t\t}\n\t}\n\tif (pVehicle->m_bSirenOrAlarm){\n\t\tif ((uint8)(pVehicle->m_randomSeed ^ CGeneral::GetRandomNumber()) == 0xAD)\n\t\t\tpVehicle->m_nCarHornTimer = 45;\n\t}\n\tfloat target = 1.0f;\n\tif (pVehicle->AutoPilot.m_nCarMission == MISSION_CRUISE)\n\t\ttarget = CCarCtrl::FindSpeedMultiplierWithSpeedFromNodes(pVehicle->AutoPilot.m_nCruiseSpeedMultiplierType);\n\tfloat change = CTimer::GetTimeStep() * 0.01f;\n\tif (Abs(pVehicle->AutoPilot.m_fCruiseSpeedMultiplier - target) < change)\n\t\tpVehicle->AutoPilot.m_fCruiseSpeedMultiplier = target;\n\telse if (pVehicle->AutoPilot.m_fCruiseSpeedMultiplier > target)\n\t\tpVehicle->AutoPilot.m_fCruiseSpeedMultiplier -= change;\n\telse\n\t\tpVehicle->AutoPilot.m_fCruiseSpeedMultiplier += change;\n\n\tif (pVehicle->bIsLawEnforcer && FindPlayerPed()->m_pWanted->GetWantedLevel() > 0) {\n\t\tif (!FindPlayerVehicle() ||\n\t\t\tFindPlayerVehicle()->GetVehicleAppearance() == VEHICLE_APPEARANCE_CAR ||\n\t\t\tFindPlayerVehicle()->GetVehicleAppearance() == VEHICLE_APPEARANCE_BIKE) {\n\t\t\tif (pVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_BOAT) {\n\t\t\t\tpVehicle->AutoPilot.m_nTempAction = TEMPACT_WAIT;\n\t\t\t\tpVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 1000;\n\t\t\t}\n\t\t}\n\t\telse if (FindPlayerVehicle()->GetVehicleAppearance() == VEHICLE_APPEARANCE_BOAT) {\n\t\t\tif (pVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_CAR ||\n\t\t\t\tpVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_BIKE) {\n\t\t\t\tpVehicle->AutoPilot.m_nTempAction = TEMPACT_WAIT;\n\t\t\t\tpVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 1000;\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid CCarAI::CarHasReasonToStop(CVehicle* pVehicle)\n{\n\tpVehicle->AutoPilot.m_nAntiReverseTimer = CTimer::GetTimeInMilliseconds();\n}\n\nfloat CCarAI::GetCarToGoToCoors(CVehicle* pVehicle, CVector* pTarget)\n{\n\tif (pVehicle->AutoPilot.m_nCarMission != MISSION_GOTOCOORDS && pVehicle->AutoPilot.m_nCarMission != MISSION_GOTOCOORDS_STRAIGHT){\n\t\tpVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS;\n\t\tpVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE;\n\t\tpVehicle->AutoPilot.m_nCruiseSpeed = 20;\n\t\tpVehicle->AutoPilot.m_nAntiReverseTimer = CTimer::GetTimeInMilliseconds();\n\t\tpVehicle->SetStatus(STATUS_PHYSICS);\n\t\tpVehicle->AutoPilot.m_nCarMission = (CCarCtrl::JoinCarWithRoadSystemGotoCoors(pVehicle, *pTarget, false)) ?\n\t\t\tMISSION_GOTOCOORDS_STRAIGHT : MISSION_GOTOCOORDS;\n\t}else if (Abs(pTarget->x - pVehicle->AutoPilot.m_vecDestinationCoors.x) > 2.0f ||\n\t  Abs(pTarget->y - pVehicle->AutoPilot.m_vecDestinationCoors.y) > 2.0f){\n\t\tpVehicle->AutoPilot.m_vecDestinationCoors = *pTarget;\n\t}\n\treturn (pVehicle->GetPosition() - *pTarget).Magnitude2D();\n}\n\nfloat CCarAI::GetCarToParkAtCoors(CVehicle* pVehicle, CVector* pTarget)\n{\n\tGetCarToGoToCoors(pVehicle, pTarget);\n\tpVehicle->bParking = true;\n\tpVehicle->AutoPilot.m_nCruiseSpeed = 10;\n\treturn (pVehicle->GetPosition() - *pTarget).Magnitude2D();\n}\n\nvoid CCarAI::AddPoliceCarOccupants(CVehicle* pVehicle)\n{\n\tif (pVehicle->bOccupantsHaveBeenGenerated)\n\t\treturn;\n\tpVehicle->bOccupantsHaveBeenGenerated = true;\n\tswitch (pVehicle->GetModelIndex()){\n\tcase MI_FBIRANCH:\n\tcase MI_ENFORCER:\n\t\tpVehicle->SetUpDriver();\n\t\tfor (int i = 0; i < 3; i++)\n\t\t\tpVehicle->SetupPassenger(i);\n\t\treturn;\n\tcase MI_POLICE:\n\tcase MI_RHINO:\n\tcase MI_BARRACKS:\n\t\tpVehicle->SetUpDriver();\n\t\tif (FindPlayerPed()->m_pWanted->GetWantedLevel() > 1)\n\t\t\tpVehicle->SetupPassenger(0);\n\t\treturn;\n\tcase MI_PREDATOR:\n\t\tpVehicle->SetUpDriver();\n\t\treturn;\n\tcase MI_VICECHEE:\n\t{\n\t\tpVehicle->SetUpDriver()->bMiamiViceCop = true;\n\t\tpVehicle->SetupPassenger(0)->bMiamiViceCop = true;\n\t\tCPopulation::NumMiamiViceCops += 2;\n\t\tCCarCtrl::MiamiViceCycle = (CCarCtrl::MiamiViceCycle + 1) % 4;\n\t\tCCarCtrl::LastTimeMiamiViceGenerated = CTimer::GetTimeInMilliseconds();\n\t\treturn;\n\t}\n\tdefault:\n\t\treturn;\n\t}\n}\n\nvoid CCarAI::AddAmbulanceOccupants(CVehicle* pVehicle)\n{\n\tpVehicle->SetUpDriver();\n\tpVehicle->SetupPassenger(1);\n}\n\nvoid CCarAI::AddFiretruckOccupants(CVehicle* pVehicle)\n{\n\tpVehicle->SetUpDriver();\n\tpVehicle->SetupPassenger(0);\n}\n\nvoid CCarAI::TellOccupantsToLeaveCar(CVehicle* pVehicle)\n{\n\tif (pVehicle->pDriver){\n\t\tpVehicle->pDriver->SetObjective(OBJECTIVE_LEAVE_CAR, pVehicle);\n\t\tif (pVehicle->GetModelIndex() == MI_AMBULAN)\n\t\t\tpVehicle->pDriver->Say(SOUND_PED_LEAVE_VEHICLE);\n\t}\n\tint timer = 100;\n\tfor (int i = 0; i < pVehicle->m_nNumMaxPassengers; i++){\n\t\tif (pVehicle->pPassengers[i]) {\n\t\t\tpVehicle->pPassengers[i]->m_leaveCarTimer = timer;\n\t\t\tpVehicle->pPassengers[i]->SetObjective(OBJECTIVE_LEAVE_CAR, pVehicle);\n\t\t\ttimer += CGeneral::GetRandomNumberInRange(200, 400);\n\t\t}\n\t}\n}\n\nvoid CCarAI::TellOccupantsToFleeCar(CVehicle* pVehicle)\n{\n\tif (pVehicle->pDriver && !pVehicle->pDriver->IsPlayer()) {\n\t\tpVehicle->pDriver->SetObjective(OBJECTIVE_FLEE_ON_FOOT_TILL_SAFE);\n\t\tif (pVehicle->GetModelIndex() != MI_FIRETRUCK && pVehicle->GetModelIndex() == MI_AMBULAN)\n\t\t\tpVehicle->pDriver->Say(SOUND_PED_LEAVE_VEHICLE);\n\t}\n\tint timer = 100;\n\tfor (int i = 0; i < pVehicle->m_nNumMaxPassengers; i++) {\n\t\tif (pVehicle->pPassengers[i]) {\n\t\t\tpVehicle->pPassengers[i]->m_leaveCarTimer = timer;\n\t\t\tpVehicle->pPassengers[i]->SetObjective(OBJECTIVE_FLEE_ON_FOOT_TILL_SAFE);\n\t\t\ttimer += CGeneral::GetRandomNumberInRange(200, 400);\n\t\t}\n\t}\n}\n\nvoid CCarAI::TellCarToRamOtherCar(CVehicle* pVehicle, CVehicle* pTarget)\n{\n\tpVehicle->AutoPilot.m_pTargetCar = pTarget;\n\tpTarget->RegisterReference((CEntity**)&pVehicle->AutoPilot.m_pTargetCar);\n\tpVehicle->AutoPilot.m_nCarMission = MISSION_RAMCAR_FARAWAY;\n\tpVehicle->bEngineOn = true;\n\tpVehicle->AutoPilot.m_nCruiseSpeed = Max(6, pVehicle->AutoPilot.m_nCruiseSpeed);\n}\n\nvoid CCarAI::TellCarToBlockOtherCar(CVehicle* pVehicle, CVehicle* pTarget)\n{\n\tpVehicle->AutoPilot.m_pTargetCar = pTarget;\n\tpTarget->RegisterReference((CEntity**)&pVehicle->AutoPilot.m_pTargetCar);\n\tpVehicle->AutoPilot.m_nCarMission = MISSION_BLOCKCAR_FARAWAY;\n\tpVehicle->bEngineOn = true;\n\tpVehicle->AutoPilot.m_nCruiseSpeed = Max(6, pVehicle->AutoPilot.m_nCruiseSpeed);\n}\n\nuint8 CCarAI::FindPoliceCarMissionForWantedLevel()\n{\n\tswitch (CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_pWanted->GetWantedLevel()){\n\tcase 0:\n\tcase 1: return MISSION_BLOCKPLAYER_FARAWAY;\n\tcase 2: return (CGeneral::GetRandomNumber() & 3) >= 3 ? MISSION_RAMPLAYER_FARAWAY : MISSION_BLOCKPLAYER_FARAWAY;\n\tcase 3: return (CGeneral::GetRandomNumber() & 3) >= 2 ? MISSION_RAMPLAYER_FARAWAY : MISSION_BLOCKPLAYER_FARAWAY;\n\tcase 4: \n\tcase 5:\n\tcase 6: return (CGeneral::GetRandomNumber() & 3) >= 1 ? MISSION_RAMPLAYER_FARAWAY : MISSION_BLOCKPLAYER_FARAWAY;\n\tdefault: return MISSION_BLOCKPLAYER_FARAWAY;\n\t}\n}\n\nuint8 CCarAI::FindPoliceBoatMissionForWantedLevel()\n{\n\tswitch (CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_pWanted->GetWantedLevel()) {\n\tcase 0:\n\tcase 1: return MISSION_BLOCKPLAYER_FARAWAY;\n\tcase 2:\n\tcase 3:\n\tcase 4:\n\tcase 5:\n\tcase 6: return MISSION_ATTACKPLAYER;\n\tdefault: return MISSION_BLOCKPLAYER_FARAWAY;\n\t}\n}\n\nint32 CCarAI::FindPoliceCarSpeedForWantedLevel(CVehicle* pVehicle)\n{\n\tswitch (CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_pWanted->GetWantedLevel()) {\n\tcase 0: return CGeneral::GetRandomNumberInRange(12, 16);\n\tcase 1: return 25;\n\tcase 2: return 34;\n\tcase 3: return GAME_SPEED_TO_CARAI_SPEED * pVehicle->pHandling->Transmission.fMaxVelocity * 0.9f;\n\tcase 4: return GAME_SPEED_TO_CARAI_SPEED * pVehicle->pHandling->Transmission.fMaxVelocity * 1.2f;\n\tcase 5: return GAME_SPEED_TO_CARAI_SPEED * pVehicle->pHandling->Transmission.fMaxVelocity * 1.25f;\n\tcase 6: return GAME_SPEED_TO_CARAI_SPEED * pVehicle->pHandling->Transmission.fMaxVelocity * 1.3f;\n\tdefault: return 0;\n\t}\n}\n\nvoid CCarAI::MellowOutChaseSpeed(CVehicle* pVehicle)\n{\n\tif (CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_pWanted->GetWantedLevel() == 1){\n\t\tfloat distanceToPlayer = (pVehicle->GetPosition() - FindPlayerCoors()).Magnitude();\n\t\tif (FindPlayerVehicle()){\n\t\t\tif (distanceToPlayer < 10.0f)\n\t\t\t\tpVehicle->AutoPilot.m_nCruiseSpeed = 15;\n\t\t\telse if (distanceToPlayer < 20.0f)\n\t\t\t\tpVehicle->AutoPilot.m_nCruiseSpeed = 22;\n\t\t\telse\n\t\t\t\tpVehicle->AutoPilot.m_nCruiseSpeed = 25;\n\t\t}else{\n\t\t\tif (distanceToPlayer < 20.0f)\n\t\t\t\tpVehicle->AutoPilot.m_nCruiseSpeed = 5;\n\t\t\telse if (distanceToPlayer < 40.0f)\n\t\t\t\tpVehicle->AutoPilot.m_nCruiseSpeed = 13;\n\t\t\telse\n\t\t\t\tpVehicle->AutoPilot.m_nCruiseSpeed = 25;\n\t\t}\n\t}else if (CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_pWanted->GetWantedLevel() == 2){\n\t\tfloat distanceToPlayer = (pVehicle->GetPosition() - FindPlayerCoors()).Magnitude();\n\t\tif (FindPlayerVehicle()) {\n\t\t\tif (distanceToPlayer < 10.0f)\n\t\t\t\tpVehicle->AutoPilot.m_nCruiseSpeed = 27;\n\t\t\telse if (distanceToPlayer < 20.0f)\n\t\t\t\tpVehicle->AutoPilot.m_nCruiseSpeed = 30;\n\t\t\telse\n\t\t\t\tpVehicle->AutoPilot.m_nCruiseSpeed = 34;\n\t\t}\n\t\telse {\n\t\t\tif (distanceToPlayer < 20.0f)\n\t\t\t\tpVehicle->AutoPilot.m_nCruiseSpeed = 5;\n\t\t\telse if (distanceToPlayer < 40.0f)\n\t\t\t\tpVehicle->AutoPilot.m_nCruiseSpeed = 18;\n\t\t\telse\n\t\t\t\tpVehicle->AutoPilot.m_nCruiseSpeed = 34;\n\t\t}\n\t}\n\tif (!FindPlayerVehicle() && FindPlayerPed()->GetMoveSpeed().Magnitude() < 0.07f) {\n\t\tif ((FindPlayerCoors() - pVehicle->GetPosition()).Magnitude() < 30.0f)\n\t\t\tpVehicle->AutoPilot.m_nCruiseSpeed = Min(10, pVehicle->AutoPilot.m_nCruiseSpeed);\n\t}\n}\n\nvoid CCarAI::MellowOutChaseSpeedBoat(CVehicle* pVehicle)\n{\n\tswitch (CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_pWanted->GetWantedLevel()) {\n\tcase 0: pVehicle->AutoPilot.m_nCruiseSpeed = 8; break;\n\tcase 1: pVehicle->AutoPilot.m_nCruiseSpeed = 10; break;\n\tcase 2: pVehicle->AutoPilot.m_nCruiseSpeed = 15; break;\n\tcase 3: pVehicle->AutoPilot.m_nCruiseSpeed = 20; break;\n\tcase 4: pVehicle->AutoPilot.m_nCruiseSpeed = 25; break;\n\tcase 5: pVehicle->AutoPilot.m_nCruiseSpeed = 30; break;\n\tcase 6: pVehicle->AutoPilot.m_nCruiseSpeed = 40; break;\n\t}\n}\n\nvoid CCarAI::MakeWayForCarWithSiren(CVehicle *pVehicle)\n{\n\tfloat flatSpeed = pVehicle->GetMoveSpeed().Magnitude2D();\n\tif (flatSpeed < 0.1f)\n\t\treturn;\n\tCVector2D forward = pVehicle->GetMoveSpeed() / flatSpeed;\n\tfloat projection = flatSpeed * 45 + 20;\n\tint i = CPools::GetVehiclePool()->GetSize();\n\twhile (--i >= 0) {\n\t\tCVehicle* vehicle = CPools::GetVehiclePool()->GetSlot(i);\n\t\tif (!vehicle)\n\t\t\tcontinue;\n\t\tif (!vehicle->IsCar() && !vehicle->IsBike())\n\t\t\tcontinue;\n\t\tif (vehicle->GetStatus() != STATUS_SIMPLE && vehicle->GetStatus() != STATUS_PHYSICS)\n\t\t\tcontinue;\n\t\tif (vehicle->VehicleCreatedBy != RANDOM_VEHICLE)\n\t\t\tcontinue;\n\t\tif (vehicle->bIsLawEnforcer || vehicle->bIsAmbulanceOnDuty || vehicle->bIsFireTruckOnDuty)\n\t\t\tcontinue;\n\t\tif (vehicle == pVehicle)\n\t\t\tcontinue;\n\t\tif (vehicle->AutoPilot.m_nDrivingStyle == DRIVINGSTYLE_AVOID_CARS)\n\t\t\treturn;\n\t\tif (Abs(pVehicle->GetPosition().z - vehicle->GetPosition().z) >= 5.0f)\n\t\t\tcontinue;\n\t\tCVector2D distance = vehicle->GetPosition() - pVehicle->GetPosition();\n\t\tif (distance.Magnitude() >= projection)\n\t\t\tcontinue;\n\t\tif (vehicle->GetMoveSpeed().Magnitude2D() <= 0.05f)\n\t\t\tcontinue;\n\t\tfloat correlation = DotProduct2D(forward, distance) / distance.Magnitude();\n\t\tif (correlation <= 0.0f)\n\t\t\tcontinue;\n\t\tif (correlation > 0.8f && DotProduct2D(forward, vehicle->GetForward()) > 0.7f){\n\t\t\tif (vehicle->AutoPilot.m_nTempAction != TEMPACT_SWERVELEFT && vehicle->AutoPilot.m_nTempAction != TEMPACT_SWERVERIGHT){\n\t\t\t\tvehicle->AutoPilot.m_nTempAction = (distance.x * forward.y - distance.y * forward.x > 0.0f) ?\n\t\t\t\t\tTEMPACT_SWERVELEFT : TEMPACT_SWERVERIGHT;\n\t\t\t\tvehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 2000;\n\t\t\t}\n\t\t\tvehicle->SetStatus(STATUS_PHYSICS);\n\t\t}else{\n\t\t\tif (DotProduct2D(vehicle->GetMoveSpeed(), distance) < 0.0f && vehicle->AutoPilot.m_nTempAction != TEMPACT_WAIT){\n\t\t\t\tvehicle->AutoPilot.m_nTempAction = TEMPACT_WAIT;\n\t\t\t\tvehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 2000;\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/control/CarAI.h",
    "content": "#pragma once\n\n#include \"AutoPilot.h\"\n\nclass CVehicle;\n\nclass CCarAI\n{\npublic:\n\tstatic float FindSwitchDistanceClose(CVehicle*);\n\tstatic float FindSwitchDistanceFarNormalVehicle(CVehicle*);\n\tstatic float FindSwitchDistanceFar(CVehicle*);\n\tstatic void BackToCruisingIfNoWantedLevel(CVehicle*);\n\tstatic void UpdateCarAI(CVehicle*);\n\tstatic void CarHasReasonToStop(CVehicle*);\n\tstatic float GetCarToGoToCoors(CVehicle*, CVector*);\n\tstatic float GetCarToParkAtCoors(CVehicle*, CVector*);\n\tstatic void AddPoliceCarOccupants(CVehicle*);\n\tstatic void AddAmbulanceOccupants(CVehicle*);\n\tstatic void AddFiretruckOccupants(CVehicle*);\n\tstatic void TellOccupantsToLeaveCar(CVehicle*);\n\tstatic void TellOccupantsToFleeCar(CVehicle*);\n\tstatic void TellCarToRamOtherCar(CVehicle*, CVehicle*);\n\tstatic void TellCarToBlockOtherCar(CVehicle*, CVehicle*);\n\tstatic uint8 FindPoliceCarMissionForWantedLevel();\n\tstatic uint8 FindPoliceBoatMissionForWantedLevel();\n\tstatic int32 FindPoliceCarSpeedForWantedLevel(CVehicle*);\n\tstatic void MellowOutChaseSpeed(CVehicle*);\n\tstatic void MellowOutChaseSpeedBoat(CVehicle*);\n\tstatic void MakeWayForCarWithSiren(CVehicle *veh);\n};\n"
  },
  {
    "path": "src/control/CarCtrl.cpp",
    "content": "#include \"common.h\"\n\n#include \"CarCtrl.h\"\n\n#include \"Accident.h\"\n#include \"Automobile.h\"\n#include \"Bike.h\"\n#include \"Camera.h\"\n#include \"CarAI.h\"\n#include \"CarGen.h\"\n#include \"Cranes.h\"\n#include \"Curves.h\"\n#include \"CutsceneMgr.h\"\n#include \"Gangs.h\"\n#include \"Game.h\"\n#include \"Garages.h\"\n#include \"General.h\"\n#include \"IniFile.h\"\n#include \"ModelIndices.h\"\n#include \"PathFind.h\"\n#include \"Ped.h\"\n#include \"PlayerInfo.h\"\n#include \"PlayerPed.h\"\n#include \"Population.h\"\n#include \"Wanted.h\"\n#include \"Pools.h\"\n#include \"Renderer.h\"\n#include \"RoadBlocks.h\"\n#include \"Timer.h\"\n#include \"TrafficLights.h\"\n#include \"Streaming.h\"\n#include \"VisibilityPlugins.h\"\n#include \"Vehicle.h\"\n#include \"Fire.h\"\n#include \"WaterLevel.h\"\n#include \"World.h\"\n#include \"Zones.h\"\n#include \"Pickups.h\"\n\n#define DISTANCE_TO_SPAWN_ROADBLOCK_PEDS (51.0f)\n#define DISTANCE_TO_SCAN_FOR_DANGER (14.0f)\n#define DISTANCE_TO_SCAN_FOR_PED_DANGER (11.0f)\n#define SAFE_DISTANCE_TO_PED (3.0f)\n#define INFINITE_Z (1000000000.0f)\n\n#define VEHICLE_HEIGHT_DIFF_TO_CONSIDER_WEAVING (4.0f)\n#define PED_HEIGHT_DIFF_TO_CONSIDER_WEAVING (4.0f)\n#define OBJECT_HEIGHT_DIFF_TO_CONSIDER_WEAVING (8.0f)\n#define WIDTH_COEF_TO_WEAVE_SAFELY (1.2f)\n#define OBJECT_WIDTH_TO_WEAVE (0.3f)\n#define PED_WIDTH_TO_WEAVE (0.8f)\n\n#define PATH_DIRECTION_NONE (0)\n#define PATH_DIRECTION_STRAIGHT (1)\n#define PATH_DIRECTION_RIGHT (2)\n#define PATH_DIRECTION_LEFT (4)\n\n#define ATTEMPTS_TO_FIND_NEXT_NODE (15)\n\n#define DISTANCE_TO_SWITCH_FROM_BLOCK_TO_STOP (5.0f)\n#define DISTANCE_TO_SWITCH_FROM_STOP_TO_BLOCK (10.0f)\n#define MAX_SPEED_TO_ACCOUNT_IN_INTERCEPTING (0.13f)\n#define DISTANCE_TO_NEXT_NODE_TO_CONSIDER_SLOWING_DOWN (40.0f)\n#define MAX_ANGLE_TO_STEER_AT_HIGH_SPEED (0.2f)\n#define MIN_SPEED_TO_START_LIMITING_STEER (0.45f)\n#define DISTANCE_TO_NEXT_NODE_TO_SELECT_NEW (5.0f)\n#define DISTANCE_TO_FACING_NEXT_NODE_TO_SELECT_NEW (8.0f)\n#define DEFAULT_MAX_STEER_ANGLE (0.5f)\n#define MIN_LOWERING_SPEED_COEFFICIENT (0.4f)\n#define MAX_ANGLE_FOR_SPEED_LIMITING (1.2f)\n#define MIN_ANGLE_FOR_SPEED_LIMITING (0.4f)\n#define MIN_ANGLE_FOR_SPEED_LIMITING_BETWEEN_NODES (0.1f)\n#define MIN_ANGLE_TO_APPLY_HANDBRAKE (0.7f)\n#define MIN_SPEED_TO_APPLY_HANDBRAKE (0.3f)\n\n#define PROBABILITY_OF_DEAD_PED_ACCIDENT (0.005f)\n#define DISTANCE_BETWEEN_CAR_AND_DEAD_PED (6.0f)\n#define PROBABILITY_OF_PASSENGER_IN_VEHICLE (0.125f)\n\n#define ONSCREEN_DESPAWN_RANGE (120.0f)\n#define MINIMAL_DISTANCE_TO_SPAWN_ONSCREEN (100.0f)\n#define REQUEST_ONSCREEN_DISTANCE ((ONSCREEN_DESPAWN_RANGE + MINIMAL_DISTANCE_TO_SPAWN_ONSCREEN) / 2)\n#define OFFSCREEN_DESPAWN_RANGE (40.0f)\n#define EXTENDED_RANGE_DESPAWN_MULTIPLIER (1.5f)\n\nbool CCarCtrl::bMadDriversCheat;\nint CCarCtrl::NumLawEnforcerCars;\nint CCarCtrl::NumAmbulancesOnDuty;\nint CCarCtrl::NumFiretrucksOnDuty;\nbool CCarCtrl::bCarsGeneratedAroundCamera;\nfloat CCarCtrl::CarDensityMultiplier = 1.0f;\nint32 CCarCtrl::NumMissionCars;\nint32 CCarCtrl::NumRandomCars;\nint32 CCarCtrl::NumParkedCars;\nint32 CCarCtrl::NumPermanentCars;\nint8 CCarCtrl::CountDownToCarsAtStart;\nint32 CCarCtrl::MaxNumberOfCarsInUse = 12;\nuint32 CCarCtrl::LastTimeLawEnforcerCreated;\nuint32 CCarCtrl::LastTimeFireTruckCreated;\nuint32 CCarCtrl::LastTimeAmbulanceCreated;\nint32 CCarCtrl::MiamiViceCycle;\nuint32 CCarCtrl::LastTimeMiamiViceGenerated;\nint32 CCarCtrl::TotalNumOfCarsOfRating[TOTAL_CUSTOM_CLASSES];\nint32 CCarCtrl::CarArrays[TOTAL_CUSTOM_CLASSES][MAX_CAR_MODELS_IN_ARRAY];\nint32 CCarCtrl::NumRequestsOfCarRating[TOTAL_CUSTOM_CLASSES];\nint32 CCarCtrl::NumOfLoadedCarsOfRating[TOTAL_CUSTOM_CLASSES];\nint32 CCarCtrl::CarFreqArrays[TOTAL_CUSTOM_CLASSES][MAX_CAR_MODELS_IN_ARRAY];\nint32 CCarCtrl::LoadedCarsArray[TOTAL_CUSTOM_CLASSES][MAX_CAR_MODELS_IN_ARRAY];\nCVehicle* apCarsToKeep[MAX_CARS_TO_KEEP];\nuint32 aCarsToKeepTime[MAX_CARS_TO_KEEP];\n\nvoid\nCCarCtrl::GenerateRandomCars()\n{\n\tif (CCutsceneMgr::IsRunning()) {\n\t\tCountDownToCarsAtStart = 2;\n\t\treturn;\n\t}\n\tif (NumRandomCars < 30){\n\t\tif (CountDownToCarsAtStart == 0)\n\t\t\tGenerateOneRandomCar();\n\t\telse if (--CountDownToCarsAtStart == 0) {\n\t\t\tfor (int i = 0; i < 100; i++)\n\t\t\t\tGenerateOneRandomCar();\n\t\t\tCTheCarGenerators::GenerateEvenIfPlayerIsCloseCounter = 20;\n\t\t}\n\t}\n\t/* Approximately once per 4 seconds. */\n\tif ((CTimer::GetTimeInMilliseconds() & 0xFFFFF000) != (CTimer::GetPreviousTimeInMilliseconds() & 0xFFFFF000))\n\t\tGenerateEmergencyServicesCar();\n}\n\nvoid\nCCarCtrl::GenerateOneRandomCar()\n{\n\tstatic int32 unk = 0;\n\tbool bTopDownCamera = false;\n\tCPlayerInfo* pPlayer = &CWorld::Players[CWorld::PlayerInFocus];\n\tCVector vecTargetPos = FindPlayerCentreOfWorld(CWorld::PlayerInFocus);\n\tCVector2D vecPlayerSpeed = FindPlayerSpeed();\n\tCZoneInfo zone;\n\tCTheZones::GetZoneInfoForTimeOfDay(&vecTargetPos, &zone);\n\tpPlayer->m_nTrafficMultiplier = pPlayer->m_fRoadDensity * zone.carDensity;\n\tif (NumRandomCars >= pPlayer->m_nTrafficMultiplier * CarDensityMultiplier * CIniFile::CarNumberMultiplier)\n\t\treturn;\n\tif (NumFiretrucksOnDuty + NumAmbulancesOnDuty + NumParkedCars + NumMissionCars + NumLawEnforcerCars + NumRandomCars >= MaxNumberOfCarsInUse)\n\t\treturn;\n\tCWanted* pWanted = pPlayer->m_pPed->m_pWanted;\n\tint carClass;\n\tint carModel;\n\tif (pWanted->GetWantedLevel() > 1 && NumLawEnforcerCars < pWanted->m_MaximumLawEnforcerVehicles &&\n\t\tpWanted->m_CurrentCops < pWanted->m_MaxCops && !CGame::IsInInterior() && (\n\t\t\tpWanted->GetWantedLevel() > 3 ||\n\t\t\tpWanted->GetWantedLevel() > 2 && CTimer::GetTimeInMilliseconds() > LastTimeLawEnforcerCreated + 5000 ||\n\t\t\tpWanted->GetWantedLevel() > 1 && CTimer::GetTimeInMilliseconds() > LastTimeLawEnforcerCreated + 8000)) {\n\t\t/* Last pWanted->GetWantedLevel() > 1 is unnecessary but I added it for better readability. */\n\t\t/* Wouldn't be surprised it was there originally but was optimized out. */\n\t\tcarClass = COPS;\n\t\tcarModel = ChoosePoliceCarModel();\n\t}else{\n\t\tcarModel = ChooseModel(&zone, &carClass);\n\t\tif (carModel == -1 || (carClass == COPS && pWanted->GetWantedLevel() >= 1))\n\t\t\t/* All cop spawns with wanted level are handled by condition above. */\n\t\t\t/* In particular it means that cop cars never spawn if player has wanted level of 1. */\n\t\t\treturn;\n\t}\n\tfloat frontX, frontY;\n\tfloat preferredDistance, angleLimit;\n\tbool invertAngleLimitTest;\n\tCVector spawnPosition;\n\tint32 curNodeId, nextNodeId;\n\tfloat positionBetweenNodes;\n\tbool testForCollision;\n\tCVehicle* pPlayerVehicle = FindPlayerVehicle();\n\tCVector2D vecPlayerVehicleSpeed;\n\tfloat fPlayerVehicleSpeed;\n\tif (pPlayerVehicle) {\n\t\tvecPlayerVehicleSpeed = FindPlayerVehicle()->GetMoveSpeed();\n\t\tfPlayerVehicleSpeed = vecPlayerVehicleSpeed.Magnitude();\n\t}\n\tif (TheCamera.GetForward().z < -0.9f){\n\t\t/* Player uses topdown camera. */\n\t\t/* Spawn essentially anywhere. */\n\t\tfrontX = frontY = 0.707f; /* 45 degrees */\n\t\tangleLimit = -1.0f;\n\t\tbTopDownCamera = true;\n\t\tinvertAngleLimitTest = true;\n\t\tpreferredDistance = OFFSCREEN_DESPAWN_RANGE + 15.0f;\n\t\t/* BUG: testForCollision not initialized in original game. */\n\t\ttestForCollision = false;\n\t}else if (!pPlayerVehicle){\n\t\t/* Player is not in vehicle. */\n\t\ttestForCollision = true;\n\t\tfrontX = TheCamera.CamFrontXNorm;\n\t\tfrontY = TheCamera.CamFrontYNorm;\n\t\tswitch (CTimer::GetFrameCounter() & 1) {\n\t\tcase 0:\n\t\t\t/* Spawn a vehicle relatively far away from player. */\n\t\t\t/* Forward to his current direction (camera direction). */\n\t\t\tangleLimit = 0.707f; /* 45 degrees */\n\t\t\tinvertAngleLimitTest = true;\n\t\t\tpreferredDistance = REQUEST_ONSCREEN_DISTANCE * TheCamera.GenerationDistMultiplier;\n\t\t\tbreak;\n\t\tcase 1:\n\t\t\t/* Spawn a vehicle close to player to his side. */\n\t\t\t/* Kinda not within camera angle. */\n\t\t\tangleLimit = 0.707f; /* 45 degrees */\n\t\t\tinvertAngleLimitTest = false;\n\t\t\tpreferredDistance = OFFSCREEN_DESPAWN_RANGE;\n\t\t\tbreak;\n\t\t}\n\t}else if (fPlayerVehicleSpeed > 0.4f){ /* 72 km/h */\n\t\t/* Player is moving fast in vehicle */\n\t\t/* Prefer spawning vehicles very far away from him. */\n\t\tfrontX = vecPlayerVehicleSpeed.x / fPlayerVehicleSpeed;\n\t\tfrontY = vecPlayerVehicleSpeed.y / fPlayerVehicleSpeed;\n\t\ttestForCollision = false;\n\t\tswitch (CTimer::GetFrameCounter() & 3) {\n\t\tcase 0:\n\t\tcase 1:\n\t\t\t/* Spawn a vehicle in a very narrow gap in front of a player */\n\t\t\tangleLimit = 0.85f; /* approx 30 degrees */\n\t\t\tinvertAngleLimitTest = true;\n\t\t\tpreferredDistance = REQUEST_ONSCREEN_DISTANCE * TheCamera.GenerationDistMultiplier;\n\t\t\tbreak;\n\t\tcase 2:\n\t\t\t/* Spawn a vehicle relatively far away from player. */\n\t\t\t/* Forward to his current direction (camera direction). */\n\t\t\tangleLimit = 0.707f; /* 45 degrees */\n\t\t\tinvertAngleLimitTest = true;\n\t\t\tpreferredDistance = REQUEST_ONSCREEN_DISTANCE * TheCamera.GenerationDistMultiplier;\n\t\t\tbreak;\n\t\tcase 3:\n\t\t\t/* Spawn a vehicle close to player to his side. */\n\t\t\t/* Kinda not within camera angle. */\n\t\t\tangleLimit = 0.707f; /* 45 degrees */\n\t\t\tinvertAngleLimitTest = false;\n\t\t\tpreferredDistance = OFFSCREEN_DESPAWN_RANGE;\n\t\t\tbreak;\n\t\t}\n\t}else if (fPlayerVehicleSpeed > 0.1f){ /* 18 km/h */\n\t\t/* Player is moving moderately fast in vehicle */\n\t\t/* Spawn more vehicles to player's side. */\n\t\tfrontX = vecPlayerVehicleSpeed.x / fPlayerVehicleSpeed;\n\t\tfrontY = vecPlayerVehicleSpeed.y / fPlayerVehicleSpeed;\n\t\ttestForCollision = false;\n\t\tswitch (CTimer::GetFrameCounter() & 3) {\n\t\tcase 0:\n\t\t\t/* Spawn a vehicle in a very narrow gap in front of a player */\n\t\t\tangleLimit = 0.85f; /* approx 30 degrees */\n\t\t\tinvertAngleLimitTest = true;\n\t\t\tpreferredDistance = REQUEST_ONSCREEN_DISTANCE * TheCamera.GenerationDistMultiplier;\n\t\t\tbreak;\n\t\tcase 1:\n\t\t\t/* Spawn a vehicle relatively far away from player. */\n\t\t\t/* Forward to his current direction (camera direction). */\n\t\t\tangleLimit = 0.707f; /* 45 degrees */\n\t\t\tinvertAngleLimitTest = true;\n\t\t\tpreferredDistance = REQUEST_ONSCREEN_DISTANCE * TheCamera.GenerationDistMultiplier;\n\t\t\tbreak;\n\t\tcase 2:\n\t\tcase 3:\n\t\t\t/* Spawn a vehicle close to player to his side. */\n\t\t\t/* Kinda not within camera angle. */\n\t\t\tangleLimit = 0.707f; /* 45 degrees */\n\t\t\tinvertAngleLimitTest = false;\n\t\t\tpreferredDistance = OFFSCREEN_DESPAWN_RANGE;\n\t\t\tbreak;\n\t\t}\n\t}else{\n\t\t/* Player is in vehicle but moving very slow. */\n\t\t/* Then use camera direction instead of vehicle direction. */\n\t\ttestForCollision = true;\n\t\tfrontX = TheCamera.CamFrontXNorm;\n\t\tfrontY = TheCamera.CamFrontYNorm;\n\t\tswitch (CTimer::GetFrameCounter() & 1) {\n\t\tcase 0:\n\t\t\t/* Spawn a vehicle relatively far away from player. */\n\t\t\t/* Forward to his current direction (camera direction). */\n\t\t\tangleLimit = 0.707f; /* 45 degrees */\n\t\t\tinvertAngleLimitTest = true;\n\t\t\tpreferredDistance = REQUEST_ONSCREEN_DISTANCE * TheCamera.GenerationDistMultiplier;\n\t\t\tbreak;\n\t\tcase 1:\n\t\t\t/* Spawn a vehicle close to player to his side. */\n\t\t\t/* Kinda not within camera angle. */\n\t\t\tangleLimit = 0.707f; /* 45 degrees */\n\t\t\tinvertAngleLimitTest = false;\n\t\t\tpreferredDistance = OFFSCREEN_DESPAWN_RANGE;\n\t\t\tbreak;\n\t\t}\n\t}\n\tif (!ThePaths.GenerateCarCreationCoors(vecTargetPos.x, vecTargetPos.y, frontX, frontY,\n\t\tpreferredDistance, angleLimit, invertAngleLimitTest, &spawnPosition, &curNodeId, &nextNodeId,\n\t\t&positionBetweenNodes, carClass == COPS && pWanted->GetWantedLevel() >= 1))\n\t\treturn;\n\tCPathNode* pCurNode = &ThePaths.m_pathNodes[curNodeId];\n\tCPathNode* pNextNode = &ThePaths.m_pathNodes[nextNodeId];\n\tbool bBoatGenerated = false;\n\tif ((CGeneral::GetRandomNumber() & 0xF) > Min(pCurNode->spawnRate, pNextNode->spawnRate))\n\t\treturn;\n\tif (pCurNode->bWaterPath) {\n\t\tbBoatGenerated = true;\n\t\tif (carClass == COPS) {\n\t\t\tcarModel = MI_PREDATOR;\n\t\t\tcarClass = COPS_BOAT;\n\t\t\tif (!CStreaming::HasModelLoaded(MI_PREDATOR)) {\n\t\t\t\tCStreaming::RequestModel(MI_PREDATOR, STREAMFLAGS_DEPENDENCY);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tint i;\n\t\t\tcarModel = -1;\n\t\t\tfor (i = 10; i > 0 && (carModel == -1 || !CStreaming::HasModelLoaded(carModel)); i--) {\n\t\t\t\tcarModel = ChooseBoatModel(ChooseBoatRating(&zone));\n\t\t\t}\n\t\t\tif (i == 0)\n\t\t\t\treturn;\n\t\t}\n\t\tif (pCurNode->bOnlySmallBoats || pNextNode->bOnlySmallBoats) {\n\t\t\tif (BoatWithTallMast(carModel))\n\t\t\t\treturn;\n\t\t}\n\t}\n\tint16 colliding;\n\tCWorld::FindObjectsKindaColliding(spawnPosition, bBoatGenerated ? 40.0f : 10.0f, true, &colliding, 2, nil, false, true, true, false, false);\n\tif (colliding)\n\t\t/* If something is already present in spawn position, do not create vehicle*/\n\t\treturn;\n\tif (!bBoatGenerated && !ThePaths.TestCoorsCloseness(vecTargetPos, false, spawnPosition))\n\t\t/* Testing if spawn position can reach target position via valid path. */\n\t\treturn;\n\tint16 idInNode = 0;\n\n\twhile (idInNode < pCurNode->numLinks &&\n\t\tThePaths.ConnectedNode(idInNode + pCurNode->firstLink) != nextNodeId)\n\t\tidInNode++;\n\tint16 connectionId = ThePaths.m_carPathConnections[idInNode + pCurNode->firstLink];\n\tCCarPathLink* pPathLink = &ThePaths.m_carPathLinks[connectionId];\n\tint16 lanesOnCurrentRoad = pPathLink->pathNodeIndex == nextNodeId ? pPathLink->numLeftLanes : pPathLink->numRightLanes;\n\tCVehicleModelInfo* pModelInfo = (CVehicleModelInfo*)CModelInfo::GetModelInfo(carModel);\n\tif (lanesOnCurrentRoad == 0)\n\t\t/* Not spawning vehicle if road is one way and intended direction is opposide to that way. */\n\t\treturn;\n\tCVehicle* pVehicle;\n\tif (CModelInfo::IsBoatModel(carModel))\n\t\tpVehicle = new CBoat(carModel, RANDOM_VEHICLE);\n\telse if (CModelInfo::IsBikeModel(carModel))\n\t\tpVehicle = new CBike(carModel, RANDOM_VEHICLE);\n\telse\n\t\tpVehicle = new CAutomobile(carModel, RANDOM_VEHICLE);\n\tpVehicle->AutoPilot.m_nPrevRouteNode = 0;\n\tpVehicle->AutoPilot.m_nCurrentRouteNode = curNodeId;\n\tpVehicle->AutoPilot.m_nNextRouteNode = nextNodeId;\n\tswitch (carClass) {\n\tcase COPS:\n\t\tpVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE;\n\t\tif (CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_pWanted->GetWantedLevel() != 0){\n\t\t\tpVehicle->AutoPilot.m_nCruiseSpeed = CCarAI::FindPoliceCarSpeedForWantedLevel(pVehicle);\n\t\t\tpVehicle->AutoPilot.m_fMaxTrafficSpeed = pVehicle->AutoPilot.m_nCruiseSpeed / 2;\n\t\t\tpVehicle->AutoPilot.m_nCarMission = CCarAI::FindPoliceCarMissionForWantedLevel();\n\t\t\tpVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS;\n\t\t}else{\n\t\t\tpVehicle->AutoPilot.m_nCruiseSpeed = CGeneral::GetRandomNumberInRange(12, 16);\n\t\t\tpVehicle->AutoPilot.m_fMaxTrafficSpeed = pVehicle->AutoPilot.m_nCruiseSpeed;\n\t\t\tpVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_STOP_FOR_CARS;\n\t\t\tpVehicle->AutoPilot.m_nCarMission = MISSION_CRUISE;\n\t\t}\n\t\tif (carModel == MI_FBIRANCH){\n\t\t\tpVehicle->m_currentColour1 = 0;\n\t\t\tpVehicle->m_currentColour2 = 0;\n\t\t}\n\t\tpVehicle->bCreatedAsPoliceVehicle = true;\n\t\tbreak;\n\tcase COPS_BOAT:\n\t\tpVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE;\n\t\tpVehicle->AutoPilot.m_nCruiseSpeed = CGeneral::GetRandomNumberInRange(4, 16);\n\t\tpVehicle->AutoPilot.m_fMaxTrafficSpeed = pVehicle->AutoPilot.m_nCruiseSpeed;\n\t\tpVehicle->AutoPilot.m_nCarMission = CCarAI::FindPoliceBoatMissionForWantedLevel();\n\t\tpVehicle->bCreatedAsPoliceVehicle = true;\n\t\tbreak;\n\tdefault:\n\t\tpVehicle->AutoPilot.m_nCruiseSpeed = CGeneral::GetRandomNumberInRange(9, 14);\n\t\tif (carClass == EXEC)\n\t\t\tpVehicle->AutoPilot.m_nCruiseSpeed = CGeneral::GetRandomNumberInRange(12, 18);\n\t\telse if (carClass == POOR)\n\t\t\tpVehicle->AutoPilot.m_nCruiseSpeed = CGeneral::GetRandomNumberInRange(7, 10);\n\t\tif (pVehicle->GetColModel()->boundingBox.max.y - pVehicle->GetColModel()->boundingBox.min.y > 10.0f || carClass == BIG) {\n\t\t\tpVehicle->AutoPilot.m_nCruiseSpeed *= 3;\n\t\t\tpVehicle->AutoPilot.m_nCruiseSpeed /= 4;\n\t\t}\n\t\tpVehicle->AutoPilot.m_fMaxTrafficSpeed = pVehicle->AutoPilot.m_nCruiseSpeed;\n\t\tpVehicle->AutoPilot.m_nCarMission = MISSION_CRUISE;\n\t\tpVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE;\n\t\tpVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_STOP_FOR_CARS;\n\t\tbreak;\n\t}\n\tif (pVehicle && pVehicle->GetModelIndex() == MI_MRWHOOP)\n\t\tpVehicle->m_bSirenOrAlarm = true;\n\tpVehicle->AutoPilot.m_nNextPathNodeInfo = connectionId;\n\tpVehicle->AutoPilot.m_nNextLane = pVehicle->AutoPilot.m_nCurrentLane = CGeneral::GetRandomNumber() % lanesOnCurrentRoad;\n\tCBox* boundingBox = &CModelInfo::GetModelInfo(pVehicle->GetModelIndex())->GetColModel()->boundingBox;\n\tfloat carLength = 1.0f + (boundingBox->max.y - boundingBox->min.y) / 2;\n\tfloat distanceBetweenNodes = (pCurNode->GetPosition() - pNextNode->GetPosition()).Magnitude2D();\n\t/* If car is so long that it doesn't fit between two car nodes, place it directly in the middle. */\n\t/* Otherwise put it at least in a way that full vehicle length fits between two nodes. */\n\tif (distanceBetweenNodes / 2 < carLength)\n\t\tpositionBetweenNodes = 0.5f;\n\telse\n\t\tpositionBetweenNodes = Min(1.0f - carLength / distanceBetweenNodes, Max(carLength / distanceBetweenNodes, positionBetweenNodes));\n\tpVehicle->AutoPilot.m_nNextDirection = (curNodeId >= nextNodeId) ? 1 : -1;\n\tif (pCurNode->numLinks == 1){\n\t\t/* Do not create vehicle if there is nowhere to go. */\n\t\tdelete pVehicle;\n\t\treturn;\n\t}\n\tint16 nextConnection = pVehicle->AutoPilot.m_nNextPathNodeInfo;\n\tint16 newLink;\n\twhile (nextConnection == pVehicle->AutoPilot.m_nNextPathNodeInfo){\n\t\tnewLink = CGeneral::GetRandomNumber() % pCurNode->numLinks;\n\t\tnextConnection = ThePaths.m_carPathConnections[newLink + pCurNode->firstLink];\n\t}\n\tpVehicle->AutoPilot.m_nCurrentPathNodeInfo = nextConnection;\n\tpVehicle->AutoPilot.m_nCurrentDirection = (ThePaths.ConnectedNode(newLink + pCurNode->firstLink) >= curNodeId) ? 1 : -1;\n\tCVector2D vecBetweenNodes = pNextNode->GetPosition() - pCurNode->GetPosition();\n\tfloat forwardX, forwardY;\n\tfloat distBetweenNodes = vecBetweenNodes.Magnitude();\n\tif (distanceBetweenNodes == 0.0f){\n\t\tforwardX = 1.0f;\n\t\tforwardY = 0.0f;\n\t}else{\n\t\tforwardX = vecBetweenNodes.x / distBetweenNodes;\n\t\tforwardY = vecBetweenNodes.y / distBetweenNodes;\n\t}\n\t/* I think the following might be some form of SetRotateZOnly. */\n\t/* Setting up direction between two car nodes. */\n\tpVehicle->GetForward() = CVector(forwardX, forwardY, 0.0f);\n\tpVehicle->GetRight() = CVector(forwardY, -forwardX, 0.0f);\n\tpVehicle->GetUp() = CVector(0.0f, 0.0f, 1.0f);\n\n\tfloat currentPathLinkForwardX = pVehicle->AutoPilot.m_nCurrentDirection * ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nCurrentPathNodeInfo].GetDirX();\n\tfloat currentPathLinkForwardY = pVehicle->AutoPilot.m_nCurrentDirection * ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nCurrentPathNodeInfo].GetDirY();\n\tfloat nextPathLinkForwardX = pVehicle->AutoPilot.m_nNextDirection * ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo].GetDirX();\n\tfloat nextPathLinkForwardY = pVehicle->AutoPilot.m_nNextDirection * ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo].GetDirY();\n\n#ifdef FIX_BUGS\n\tCCarPathLink* pCurrentLink;\n\tCCarPathLink* pNextLink;\n\tCVector positionOnCurrentLinkIncludingLane;\n\tCVector positionOnNextLinkIncludingLane;\n\tfloat directionCurrentLinkX;\n\tfloat directionCurrentLinkY;\n\tfloat directionNextLinkX;\n\tfloat directionNextLinkY;\n\tif (positionBetweenNodes < 0.5f) {\n\t\tpCurrentLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nCurrentPathNodeInfo];\n\t\tpNextLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo];\n\t\tpositionOnCurrentLinkIncludingLane = CVector(\n\t\t\tpCurrentLink->GetX() + ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardY,\n\t\t\tpCurrentLink->GetY() - ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX,\n\t\t\t0.0f);\n\t\tpositionOnNextLinkIncludingLane = CVector(\n\t\t\tpNextLink->GetX() + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY,\n\t\t\tpNextLink->GetY() - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX,\n\t\t\t0.0f);\n\t\tdirectionCurrentLinkX = pCurrentLink->GetDirX() * pVehicle->AutoPilot.m_nCurrentDirection;\n\t\tdirectionCurrentLinkY = pCurrentLink->GetDirY() * pVehicle->AutoPilot.m_nCurrentDirection;\n\t\tdirectionNextLinkX = pNextLink->GetDirX() * pVehicle->AutoPilot.m_nNextDirection;\n\t\tdirectionNextLinkY = pNextLink->GetDirY() * pVehicle->AutoPilot.m_nNextDirection;\n\t\t/* We want to make a path between two links that may not have the same forward directions a curve. */\n\t\tpVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve = CCurves::CalcSpeedScaleFactor(\n\t\t\t&positionOnCurrentLinkIncludingLane,\n\t\t\t&positionOnNextLinkIncludingLane,\n\t\t\tdirectionCurrentLinkX, directionCurrentLinkY,\n\t\t\tdirectionNextLinkX, directionNextLinkY\n\t\t) * (1000.0f / pVehicle->AutoPilot.m_fMaxTrafficSpeed);\n\t\tpVehicle->AutoPilot.m_nTimeEnteredCurve = CTimer::GetTimeInMilliseconds() -\n\t\t\t(uint32)((0.5f + positionBetweenNodes) * pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve);\n\t}\n\telse {\n\t\tPickNextNodeRandomly(pVehicle);\n\t\tpVehicle->AutoPilot.m_nTimeEnteredCurve = CTimer::GetTimeInMilliseconds() -\n\t\t\t(uint32)((positionBetweenNodes - 0.5f) * pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve);\n\n\t\tpCurrentLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nCurrentPathNodeInfo];\n\t\tpNextLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo];\n\t\tpositionOnCurrentLinkIncludingLane = CVector(\n\t\t\tpCurrentLink->GetX() + ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardY,\n\t\t\tpCurrentLink->GetY() - ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX,\n\t\t\t0.0f);\n\t\tpositionOnNextLinkIncludingLane = CVector(\n\t\t\tpNextLink->GetX() + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY,\n\t\t\tpNextLink->GetY() - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX,\n\t\t\t0.0f);\n\t\tdirectionCurrentLinkX = pCurrentLink->GetDirX() * pVehicle->AutoPilot.m_nCurrentDirection;\n\t\tdirectionCurrentLinkY = pCurrentLink->GetDirY() * pVehicle->AutoPilot.m_nCurrentDirection;\n\t\tdirectionNextLinkX = pNextLink->GetDirX() * pVehicle->AutoPilot.m_nNextDirection;\n\t\tdirectionNextLinkY = pNextLink->GetDirY() * pVehicle->AutoPilot.m_nNextDirection;\n\t}\n#else\n\n\tCCarPathLink* pCurrentLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nCurrentPathNodeInfo];\n\tCCarPathLink* pNextLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo];\n\tCVector positionOnCurrentLinkIncludingLane(\n\t\tpCurrentLink->GetX() + ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardY,\n\t\tpCurrentLink->GetY() - ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX,\n\t\t0.0f);\n\tCVector positionOnNextLinkIncludingLane(\n\t\tpNextLink->GetX() + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY,\n\t\tpNextLink->GetY() - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX,\n\t\t0.0f);\n\tfloat directionCurrentLinkX = pCurrentLink->GetDirX() * pVehicle->AutoPilot.m_nCurrentDirection;\n\tfloat directionCurrentLinkY = pCurrentLink->GetDirY() * pVehicle->AutoPilot.m_nCurrentDirection;\n\tfloat directionNextLinkX = pNextLink->GetDirX() * pVehicle->AutoPilot.m_nNextDirection;\n\tfloat directionNextLinkY = pNextLink->GetDirY() * pVehicle->AutoPilot.m_nNextDirection;\n\t/* We want to make a path between two links that may not have the same forward directions a curve. */\n\tpVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve = CCurves::CalcSpeedScaleFactor(\n\t\t&positionOnCurrentLinkIncludingLane,\n\t\t&positionOnNextLinkIncludingLane,\n\t\tdirectionCurrentLinkX, directionCurrentLinkY,\n\t\tdirectionNextLinkX, directionNextLinkY\n\t) * (1000.0f / pVehicle->AutoPilot.m_fMaxTrafficSpeed);\n\tpVehicle->AutoPilot.m_nTimeEnteredCurve = CTimer::GetTimeInMilliseconds() -\n\t\t(0.5f + positionBetweenNodes) * pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve;\n#endif\n\n\tCVector directionCurrentLink(directionCurrentLinkX, directionCurrentLinkY, 0.0f);\n\tCVector directionNextLink(directionNextLinkX, directionNextLinkY, 0.0f);\n\tCVector positionIncludingCurve;\n\tCVector directionIncludingCurve;\n\tCCurves::CalcCurvePoint(\n\t\t&positionOnCurrentLinkIncludingLane,\n\t\t&positionOnNextLinkIncludingLane,\n\t\t&directionCurrentLink,\n\t\t&directionNextLink,\n\t\tGetPositionAlongCurrentCurve(pVehicle),\n\t\tpVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve,\n\t\t&positionIncludingCurve,\n\t\t&directionIncludingCurve\n\t);\n\tCVector vectorBetweenNodes = pCurNode->GetPosition() - pNextNode->GetPosition();\n\tCVector finalPosition = positionIncludingCurve + vectorBetweenNodes * 2.0f / vectorBetweenNodes.Magnitude();\n\tfinalPosition.z = positionBetweenNodes * pNextNode->GetZ() +\n\t\t(1.0f - positionBetweenNodes) * pCurNode->GetZ();\n\tfloat groundZ = INFINITE_Z;\n\tCColPoint colPoint;\n\tCEntity* pEntity;\n\tif (bBoatGenerated) {\n\t\tif (!CWaterLevel::GetWaterLevel(finalPosition, &groundZ, true)) {\n\t\t\tdelete pVehicle;\n\t\t\treturn;\n\t\t}\n\t}\n\telse {\n\t\tif (CWorld::ProcessVerticalLine(finalPosition, 1000.0f, colPoint, pEntity, true, false, false, false, true, false, nil))\n\t\t\tgroundZ = colPoint.point.z;\n\t\tif (CWorld::ProcessVerticalLine(finalPosition, -1000.0f, colPoint, pEntity, true, false, false, false, true, false, nil)) {\n\t\t\tif (ABS(colPoint.point.z - finalPosition.z) < ABS(groundZ - finalPosition.z))\n\t\t\t\tgroundZ = colPoint.point.z;\n\t\t}\n\t}\n\tif (groundZ == INFINITE_Z || ABS(groundZ - finalPosition.z) > 7.0f) {\n\t\t/* Failed to find ground or too far from expected position. */\n\t\tdelete pVehicle;\n\t\treturn;\n\t}\n\tif (CModelInfo::IsBoatModel(carModel)) {\n\t\tfinalPosition.z = groundZ;\n\t\tpVehicle->bExtendedRange = true;\n\t}\n\telse\n\t\tfinalPosition.z = groundZ + pVehicle->GetHeightAboveRoad();\n\tpVehicle->SetPosition(finalPosition);\n\tpVehicle->SetMoveSpeed(directionIncludingCurve / GAME_SPEED_TO_CARAI_SPEED);\n\tCVector2D speedDifferenceWithTarget = (CVector2D)pVehicle->GetMoveSpeed() - vecPlayerSpeed;\n\tCVector2D distanceToTarget = positionIncludingCurve - vecTargetPos;\n\tswitch (carClass) {\n\tcase COPS:\n\t\tpVehicle->SetStatus((pVehicle->AutoPilot.m_nCarMission == MISSION_CRUISE) ? STATUS_SIMPLE : STATUS_PHYSICS);\n\t\tpVehicle->ChangeLawEnforcerState(1);\n\t\tbreak;\n\tcase COPS_BOAT:\n\t\tpVehicle->ChangeLawEnforcerState(1);\n\t\tpVehicle->SetStatus(STATUS_PHYSICS);\n\t\tbreak;\n\tdefault:\n\t\tbBoatGenerated ? pVehicle->SetStatus(STATUS_PHYSICS) : pVehicle->SetStatus(STATUS_SIMPLE);\n\t\tbreak;\n\t}\n\tCVisibilityPlugins::SetClumpAlpha(pVehicle->GetClump(), 0);\n\tif (!pVehicle->GetIsOnScreen()){\n\t\tif ((vecTargetPos - pVehicle->GetPosition()).Magnitude2D() > OFFSCREEN_DESPAWN_RANGE * (pVehicle->bExtendedRange ? EXTENDED_RANGE_DESPAWN_MULTIPLIER : 1.0f)) {\n\t\t\t/* Too far away cars that are not visible aren't needed. */\n\t\t\tdelete pVehicle;\n\t\t\treturn;\n\t\t}\n\t}else{\n\t\tif ((vecTargetPos - pVehicle->GetPosition()).Magnitude2D() > TheCamera.GenerationDistMultiplier * (pVehicle->bExtendedRange ? EXTENDED_RANGE_DESPAWN_MULTIPLIER : 1.0f) * ONSCREEN_DESPAWN_RANGE ||\n\t\t\t(vecTargetPos - pVehicle->GetPosition()).Magnitude2D() < TheCamera.GenerationDistMultiplier * MINIMAL_DISTANCE_TO_SPAWN_ONSCREEN) {\n\t\t\tdelete pVehicle;\n\t\t\treturn;\n\t\t}\n\t\tif ((TheCamera.GetPosition() - pVehicle->GetPosition()).Magnitude2D() < 82.5f * TheCamera.GenerationDistMultiplier || bTopDownCamera) {\n\t\t\tdelete pVehicle;\n\t\t\treturn;\n\t\t}\n\t\tif (pVehicle->GetModelIndex() == MI_MARQUIS) { // so marquis can only spawn if player doesn't see it?\n\t\t\tdelete pVehicle;\n\t\t\treturn;\n\t\t}\n\t}\n\tCVehicleModelInfo* pVehicleModel = pVehicle->GetModelInfo();\n\tfloat radiusToTest = pVehicleModel->GetColModel()->boundingSphere.radius;\n\tif (testForCollision){\n\t\tCWorld::FindObjectsKindaColliding(pVehicle->GetPosition(), radiusToTest + 20.0f, true, &colliding, 2, nil, false, true, false, false, false);\n\t\tif (colliding){\n\t\t\tdelete pVehicle;\n\t\t\treturn;\n\t\t}\n\t}\n\tCWorld::FindObjectsKindaColliding(pVehicle->GetPosition(), radiusToTest, true, &colliding, 2, nil, false, true, false, false, false);\n\tif (colliding){\n\t\tdelete pVehicle;\n\t\treturn;\n\t}\n\tif (speedDifferenceWithTarget.x * distanceToTarget.x +\n\t\tspeedDifferenceWithTarget.y * distanceToTarget.y >= 0.0f){\n\t\tdelete pVehicle;\n\t\treturn;\n\t}\n\tpVehicleModel->AvoidSameVehicleColour(&pVehicle->m_currentColour1, &pVehicle->m_currentColour2);\n\tCWorld::Add(pVehicle);\n\tif (carClass == COPS || carClass == COPS_BOAT)\n\t\tCCarAI::AddPoliceCarOccupants(pVehicle);\n\telse {\n\t\tpVehicle->SetUpDriver();\n\t\tint32 passengers = 0;\n\t\tfor (int i = 0; i < pVehicle->m_nNumMaxPassengers; i++)\n\t\t\tpassengers += (CGeneral::GetRandomNumberInRange(0.0f, 1.0f) < PROBABILITY_OF_PASSENGER_IN_VEHICLE) ? 1 : 0;\n\t\tif (CModelInfo::IsCarModel(carModel) && (CModelInfo::GetModelInfo(carModel)->GetAnimFileIndex() == CAnimManager::GetAnimationBlockIndex(\"van\") && passengers >= 1))\n\t\t\tpassengers = 1;\n\t\tfor (int i = 0; i < passengers; i++) {\n\t\t\tCPed* pPassenger = pVehicle->SetupPassenger(i);\n\t\t\tif (pPassenger) {\n\t\t\t\t++CPopulation::ms_nTotalCarPassengerPeds;\n\t\t\t\tpPassenger->bCarPassenger = true;\n\t\t\t}\n\t\t}\n\t}\n\tint nMadDrivers;\n\tswitch (pVehicle->GetVehicleAppearance()) {\n\tcase VEHICLE_APPEARANCE_BIKE:\n\t\tnMadDrivers = 30;\n\t\tbreak;\n\tcase VEHICLE_APPEARANCE_BOAT:\n\t\tnMadDrivers = 40;\n\t\tbreak;\n\tdefault:\n\t\tnMadDrivers = 6;\n\t\tbreak;\n\t}\n\tif ((CGeneral::GetRandomNumber() & 0x7F) < nMadDrivers || bMadDriversCheat) {\n\t\tpVehicle->SetStatus(STATUS_PHYSICS);\n\t\tpVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS;\n\t\tpVehicle->AutoPilot.m_nCruiseSpeed += 10;\n\t}\n\tif (carClass == COPS)\n\t\tLastTimeLawEnforcerCreated = CTimer::GetTimeInMilliseconds();\n\tif (pVehicle->GetModelIndex() == MI_CADDY) {\n\t\tpVehicle->SetStatus(STATUS_PHYSICS);\n\t\tpVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS;\n\t}\n\tif (carClass == COPS && pVehicle->GetModelIndex() == MI_VICECHEE) {\n\t\tCVehicleModelInfo* pVehicleModel = (CVehicleModelInfo*)CModelInfo::GetModelInfo(MI_VICECHEE);\n\t\tswitch (MiamiViceCycle) {\n\t\tcase 0:\n\t\t\tpVehicleModel->SetVehicleColour(53, 77);\n\t\t\tbreak;\n\t\tcase 1:\n\t\t\tpVehicleModel->SetVehicleColour(15, 77);\n\t\t\tbreak;\n\t\tcase 2:\n\t\t\tpVehicleModel->SetVehicleColour(41, 77);\n\t\t\tbreak;\n\t\tcase 3:\n\t\t\tpVehicleModel->SetVehicleColour(61, 77);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\t}\n\tif (CGeneral::GetRandomNumberInRange(0.0f, 1.0f) >= (1 - PROBABILITY_OF_DEAD_PED_ACCIDENT)) {\n\t\tif (CModelInfo::IsCarModel(pVehicle->GetModelIndex()) && !pVehicle->bIsLawEnforcer) {\n\t\t\tif (CPopulation::AddDeadPedInFrontOfCar(pVehicle->GetPosition() + pVehicle->GetForward() * DISTANCE_BETWEEN_CAR_AND_DEAD_PED, pVehicle)) {\n\t\t\t\tpVehicle->AutoPilot.m_nCruiseSpeed = 0;\n\t\t\t\tpVehicle->SetMoveSpeed(0.0f, 0.0f, 0.0f);\n\t\t\t\tfor (int i = 0; i < pVehicle->m_nNumPassengers; i++) {\n\t\t\t\t\tif (pVehicle->pPassengers[i]) {\n\t\t\t\t\t\tpVehicle->pPassengers[i]->SetObjective(OBJECTIVE_LEAVE_CAR, pVehicle);\n\t\t\t\t\t\tpVehicle->pPassengers[i]->m_nLastPedState = PED_WANDER_PATH;\n\t\t\t\t\t\tpVehicle->pPassengers[i]->m_vehicleInAccident = pVehicle;\n\t\t\t\t\t\tpVehicle->pPassengers[i]->bDeadPedInFrontOfCar = true;\n\t\t\t\t\t\tpVehicle->RegisterReference((CEntity**)&pVehicle->pPassengers[i]->m_vehicleInAccident);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (pVehicle->pDriver) {\n\t\t\t\t\tpVehicle->pDriver->SetObjective(OBJECTIVE_LEAVE_CAR, pVehicle);\n\t\t\t\t\tpVehicle->pDriver->m_nLastPedState = PED_WANDER_PATH;\n\t\t\t\t\tpVehicle->pDriver->m_vehicleInAccident = pVehicle;\n\t\t\t\t\tpVehicle->pDriver->bDeadPedInFrontOfCar = true;\n\t\t\t\t\tpVehicle->RegisterReference((CEntity**)&pVehicle->pDriver->m_vehicleInAccident);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nbool\nCCarCtrl::BoatWithTallMast(int32 mi)\n{\n\treturn mi == MI_RIO || mi == MI_TROPIC || mi == MI_MARQUIS;\n}\n\nint32\nCCarCtrl::ChooseBoatModel(int32 rating)\n{\n\t++NumRequestsOfCarRating[rating];\n\treturn ChooseCarModel(rating);\n}\n\nint32\nCCarCtrl::ChooseBoatRating(CZoneInfo* pZoneInfo)\n{\n\tint rnd = CGeneral::GetRandomNumberInRange(0, 1000);\n\tfor (int i = 0; i < NUM_BOAT_CLASSES - 1; i++) {\n\t\tif (rnd < pZoneInfo->boatThreshold[i])\n\t\t\treturn FIRST_BOAT_RATING + i;\n\t}\n\treturn FIRST_BOAT_RATING + NUM_BOAT_CLASSES - 1;\n}\n\nint32\nCCarCtrl::ChooseCarRating(CZoneInfo* pZoneInfo)\n{\n\tint rnd = CGeneral::GetRandomNumberInRange(0, 1000);\n\tfor (int i = 0; i < NUM_CAR_CLASSES - 1; i++) {\n\t\tif (rnd < pZoneInfo->carThreshold[i])\n\t\t\treturn i;\n\t}\n\treturn FIRST_CAR_RATING + NUM_CAR_CLASSES - 1;\n}\n\nint32\nCCarCtrl::ChooseModel(CZoneInfo* pZone, int* pClass) {\n\tint32 model = -1;\n\tint32 i;\n\tfor (i = 10; i > 0 && (model == -1 || !CStreaming::HasModelLoaded(model)); i--) {\n\t\tint rnd = CGeneral::GetRandomNumberInRange(0, 1000);\n\n\t\tif (rnd < pZone->copThreshold) {\n\t\t\t*pClass = COPS; \n\t\t\tmodel = ChoosePoliceCarModel();\n\t\t\tcontinue;\n\t\t}\n\n\t\tint32 j;\n\t\tfor (j = 0; j < NUM_GANG_CAR_CLASSES; j++) {\n\t\t\tif (rnd < pZone->gangThreshold[j]) {\n\t\t\t\t*pClass = j + FIRST_GANG_CAR_RATING;\n\t\t\t\tmodel = ChooseGangCarModel(j);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif (j != NUM_GANG_CAR_CLASSES)\n\t\t\tcontinue;\n\n\t\t*pClass = ChooseCarRating(pZone);\n\t\tmodel = ChooseCarModel(*pClass);\n\t}\n\tif (i == 0)\n\t\treturn -1;\n\treturn model;\n}\n\nint32\nCCarCtrl::ChooseCarModel(int32 vehclass)\n{\n\tint32 model = -1;\n\t++NumRequestsOfCarRating[vehclass];\n\tif (NumOfLoadedCarsOfRating[vehclass] == 0)\n\t\treturn -1;\n\tint32 rnd = CGeneral::GetRandomNumberInRange(0, CarFreqArrays[vehclass][NumOfLoadedCarsOfRating[vehclass] - 1]);\n\tint32 index = 0;\n\twhile (rnd > CarFreqArrays[vehclass][index])\n\t\tindex++;\n\tassert(LoadedCarsArray[vehclass][index]);\n\treturn LoadedCarsArray[vehclass][index];\n}\n\nvoid\nCCarCtrl::AddToLoadedVehicleArray(int32 mi, int32 rating, int32 freq)\n{\n\tLoadedCarsArray[rating][NumOfLoadedCarsOfRating[rating]] = mi;\n\tassert(mi >= 130);\n\tCarFreqArrays[rating][NumOfLoadedCarsOfRating[rating]] = freq;\n\tif (NumOfLoadedCarsOfRating[rating])\n\t\tCarFreqArrays[rating][NumOfLoadedCarsOfRating[rating]] += CarFreqArrays[rating][NumOfLoadedCarsOfRating[rating] - 1];\n\tNumOfLoadedCarsOfRating[rating]++;\n}\n\nvoid\nCCarCtrl::RemoveFromLoadedVehicleArray(int mi, int32 rating)\n{\n\tint index = 0;\n\twhile (LoadedCarsArray[rating][index] != -1) {\n\t\tif (LoadedCarsArray[rating][index] == mi)\n\t\t\tbreak;\n\t\tindex++;\n\t}\n\tassert(LoadedCarsArray[rating][index] == mi);\n\tint32 freq = CarFreqArrays[rating][index];\n\tif (index > 0)\n\t\tfreq -= CarFreqArrays[rating][index - 1];\n\twhile (LoadedCarsArray[rating][index + 1] != -1) {\n\t\tLoadedCarsArray[rating][index] = LoadedCarsArray[rating][index + 1];\n\t\tCarFreqArrays[rating][index] = CarFreqArrays[rating][index + 1] - freq;\n\t\tindex++;\n\t}\n\t--NumOfLoadedCarsOfRating[rating];\n}\n\nint32\nCCarCtrl::ChooseCarModelToLoad(int rating)\n{\n\treturn CarArrays[rating][CGeneral::GetRandomNumberInRange(0, TotalNumOfCarsOfRating[rating])];\n}\n\nint32\nCCarCtrl::ChoosePoliceCarModel(void)\n{\n\tif (FindPlayerPed()->m_pWanted->AreMiamiViceRequired() &&\n#ifdef FIX_BUGS\n\t\t(CTimer::GetTimeInMilliseconds() > LastTimeMiamiViceGenerated + 120000 || LastTimeMiamiViceGenerated == 0) &&\n#else\n\t\tCTimer::GetTimeInMilliseconds() > LastTimeMiamiViceGenerated + 120000 &&\n#endif\n\t\tCStreaming::HasModelLoaded(MI_VICECHEE)) {\n\t\tswitch (MiamiViceCycle) {\n\t\tcase 0:\n\t\t\tif (CStreaming::HasModelLoaded(MI_VICE1) && CStreaming::HasModelLoaded(MI_VICE2))\n\t\t\t\treturn MI_VICECHEE;\n\t\t\tbreak;\n\t\tcase 1:\n\t\t\tif (CStreaming::HasModelLoaded(MI_VICE3) && CStreaming::HasModelLoaded(MI_VICE4))\n\t\t\t\treturn MI_VICECHEE;\n\t\t\tbreak;\n\t\tcase 2:\n\t\t\tif (CStreaming::HasModelLoaded(MI_VICE5) && CStreaming::HasModelLoaded(MI_VICE6))\n\t\t\t\treturn MI_VICECHEE;\n\t\t\tbreak;\n\t\tcase 3:\n\t\t\tif (CStreaming::HasModelLoaded(MI_VICE7) && CStreaming::HasModelLoaded(MI_VICE8))\n\t\t\t\treturn MI_VICECHEE;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\t}\n\tif (FindPlayerPed()->m_pWanted->AreSwatRequired() &&\n\t\tCStreaming::HasModelLoaded(MI_ENFORCER) &&\n\t\tCStreaming::HasModelLoaded(MI_POLICE))\n\t\treturn ((CGeneral::GetRandomNumber() & 0xF) == 0) ? MI_ENFORCER : MI_POLICE;\n\tif (FindPlayerPed()->m_pWanted->AreFbiRequired() &&\n\t\tCStreaming::HasModelLoaded(MI_FBIRANCH) &&\n\t\tCStreaming::HasModelLoaded(MI_FBI))\n\t\treturn MI_FBIRANCH;\n\tif (FindPlayerPed()->m_pWanted->AreArmyRequired() &&\n\t\tCStreaming::HasModelLoaded(MI_RHINO) &&\n\t\tCStreaming::HasModelLoaded(MI_BARRACKS) &&\n\t\tCStreaming::HasModelLoaded(MI_ARMY))\n\t\treturn CGeneral::GetRandomTrueFalse() ? MI_BARRACKS : MI_RHINO;\n\treturn MI_POLICE;\n}\n\nint32\nCCarCtrl::ChooseGangCarModel(int32 gang)\n{\n\tif (CGangs::HaveGangModelsLoaded(gang))\n\t\treturn CGangs::GetGangVehicleModel(gang);\n\treturn -1;\n}\n\nvoid\nCCarCtrl::AddToCarArray(int32 id, int32 vehclass)\n{\n\tassert(TotalNumOfCarsOfRating[vehclass] < MAX_CAR_MODELS_IN_ARRAY);\n\tCarArrays[vehclass][TotalNumOfCarsOfRating[vehclass]++] = id;\n}\n\nvoid\nCCarCtrl::RemoveDistantCars()\n{\n\tfor (int i = CPools::GetVehiclePool()->GetSize()-1; i >= 0; i--) {\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetSlot(i);\n\t\tif (!pVehicle)\n\t\t\tcontinue;\n\t\tPossiblyRemoveVehicle(pVehicle);\n\t\tif (pVehicle->bCreateRoadBlockPeds){\n\t\t\tif ((pVehicle->GetPosition() - FindPlayerCentreOfWorld(CWorld::PlayerInFocus)).Magnitude2D() < DISTANCE_TO_SPAWN_ROADBLOCK_PEDS) {\n\t\t\t\tCRoadBlocks::GenerateRoadBlockCopsForCar(pVehicle, pVehicle->m_nRoadblockType);\n\t\t\t\tpVehicle->bCreateRoadBlockPeds = false;\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nCCarCtrl::RemoveCarsIfThePoolGetsFull(void)\n{\n\tif ((CTimer::GetFrameCounter() & 7) != 3)\n\t\treturn;\n\tif (CPools::GetVehiclePool()->GetNoOfFreeSpaces() >= 8)\n\t\treturn;\n\tint i = CPools::GetVehiclePool()->GetSize();\n\tfloat md = 10000000.f;\n\tCVehicle* pClosestVehicle = nil;\n\twhile (i--) {\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetSlot(i);\n\t\tif (!pVehicle)\n\t\t\tcontinue;\n\t\tif (IsThisVehicleInteresting(pVehicle) || pVehicle->bIsLocked)\n\t\t\tcontinue;\n\t\tif (!pVehicle->CanBeDeleted() || CCranes::IsThisCarBeingTargettedByAnyCrane(pVehicle))\n\t\t\tcontinue;\n\t\tfloat distance = (TheCamera.GetPosition() - pVehicle->GetPosition()).Magnitude();\n\t\tif (distance < md) {\n\t\t\tmd = distance;\n\t\t\tpClosestVehicle = pVehicle;\n\t\t}\n\t}\n\tif (pClosestVehicle) {\n\t\tCWorld::Remove(pClosestVehicle);\n\t\tdelete pClosestVehicle;\n\t}\n}\n\nvoid\nCCarCtrl::PossiblyRemoveVehicle(CVehicle* pVehicle)\n{\n#ifdef FIX_BUGS\n\tif (pVehicle->bIsLocked)\n\t\treturn;\n#endif\n\tCVector vecPlayerPos = FindPlayerCentreOfWorld(CWorld::PlayerInFocus);\n\t/* BUG: this variable is initialized only in if-block below but can be used outside of it. */\n\tif (!IsThisVehicleInteresting(pVehicle) && !pVehicle->bIsLocked &&\n\t\tpVehicle->CanBeDeleted() && !CCranes::IsThisCarBeingTargettedByAnyCrane(pVehicle)){\n\t\tif (pVehicle->bFadeOut && CVisibilityPlugins::GetClumpAlpha(pVehicle->GetClump()) == 0){\n\t\t\tCWorld::Remove(pVehicle);\n\t\t\tdelete pVehicle;\n\t\t\treturn;\n\t\t}\n\t\tfloat distanceToPlayer = (pVehicle->GetPosition() - vecPlayerPos).Magnitude2D();\n\t\tfloat threshold = OFFSCREEN_DESPAWN_RANGE;\n\t\tif (pVehicle->GetIsOnScreen() ||\n\t\t\tTheCamera.Cams[TheCamera.ActiveCam].LookingLeft ||\n\t\t\tTheCamera.Cams[TheCamera.ActiveCam].LookingRight ||\n\t\t\tTheCamera.Cams[TheCamera.ActiveCam].LookingBehind ||\n\t\t\tTheCamera.GetLookDirection() == 0 ||\n\t\t\tpVehicle->VehicleCreatedBy == PARKED_VEHICLE ||\n\t\t\tpVehicle->GetModelIndex() == MI_AMBULAN ||\n\t\t\tpVehicle->GetModelIndex() == MI_FIRETRUCK ||\n\t\t\tpVehicle->bIsLawEnforcer ||\n\t\t\tpVehicle->bIsCarParkVehicle ||\n\t\t\tCTimer::GetTimeInMilliseconds() < pVehicle->m_nSetPieceExtendedRangeTime\n\t\t\t){\n\t\t\tthreshold = ONSCREEN_DESPAWN_RANGE * TheCamera.GenerationDistMultiplier;\n\t\t}\n\t\tif (TheCamera.GetForward().z < -0.9f)\n\t\t\tthreshold = 70.0f;\n\t\tif (pVehicle->bExtendedRange)\n\t\t\tthreshold *= EXTENDED_RANGE_DESPAWN_MULTIPLIER;\n\t\tif (distanceToPlayer > threshold && !CGarages::IsPointWithinHideOutGarage(pVehicle->GetPosition())){\n\t\t\tif (pVehicle->GetIsOnScreen()){\n\t\t\t\tpVehicle->bFadeOut = true;\n\t\t\t}else{\n\t\t\t\tCWorld::Remove(pVehicle);\n\t\t\t\tdelete pVehicle;\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t}\n\tif ((pVehicle->GetStatus() == STATUS_SIMPLE || pVehicle->GetStatus() == STATUS_PHYSICS &&\n\t\t(pVehicle->AutoPilot.m_nDrivingStyle == DRIVINGSTYLE_STOP_FOR_CARS || pVehicle->AutoPilot.m_nDrivingStyle == DRIVINGSTYLE_STOP_FOR_CARS_IGNORE_LIGHTS)) &&\n\t\tCTimer::GetTimeInMilliseconds() - pVehicle->AutoPilot.m_nTimeToStartMission > 5000 &&\n\t\t!pVehicle->GetIsOnScreen() &&\n\t\t(pVehicle->GetPosition() - vecPlayerPos).Magnitude2D() > 22.0f &&\n\t\t!IsThisVehicleInteresting(pVehicle) &&\n\t\t!pVehicle->bIsLocked &&\n\t\tpVehicle->CanBeDeleted() &&\n\t\t!CTrafficLights::ShouldCarStopForLight(pVehicle, true) &&\n\t\t!CTrafficLights::ShouldCarStopForBridge(pVehicle) &&\n\t\t!CGarages::IsPointWithinHideOutGarage(pVehicle->GetPosition())){\n\t\tCWorld::Remove(pVehicle);\n\t\tdelete pVehicle;\n\t\treturn;\n\t}\n\tif (pVehicle->GetStatus() != STATUS_WRECKED || pVehicle->m_nTimeOfDeath == 0)\n\t\treturn;\n\tif (CTimer::GetTimeInMilliseconds() > pVehicle->m_nTimeOfDeath + 60000 &&\n\t\t!pVehicle->GetIsOnScreen()){\n\t\tif ((pVehicle->GetPosition() - vecPlayerPos).MagnitudeSqr() > SQR(7.5f)){\n\t\t\tif (!CGarages::IsPointWithinHideOutGarage(pVehicle->GetPosition())){\n\t\t\t\tCWorld::Remove(pVehicle);\n\t\t\t\tdelete pVehicle;\n\t\t\t}\n\t\t}\n\t}\n}\n\nint32\nCCarCtrl::CountCarsOfType(int32 mi)\n{\n\tint32 total = 0;\n\tfor (int i = CPools::GetVehiclePool()->GetSize()-1; i >= 0; i--) {\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetSlot(i);\n\t\tif (!pVehicle)\n\t\t\tcontinue;\n\t\tif (pVehicle->GetModelIndex() == mi)\n\t\t\ttotal++;\n\t}\n\treturn total;\n}\n\nstatic CVector GetRandomOffsetForVehicle(CVehicle* pVehicle, bool bNext)\n{\n\tCVector offset;\n\tint32 seed = ((bNext ? pVehicle->AutoPilot.m_nNextPathNodeInfo : pVehicle->AutoPilot.m_nCurrentPathNodeInfo) + pVehicle->m_randomSeed) & 7;\n\toffset.x = (seed - 3) * 0.009f;\n\toffset.y = ((seed >> 3) - 3) * 0.009f;\n\toffset.z = 0.0f;\n\treturn offset;\n}\n\nvoid\nCCarCtrl::UpdateCarOnRails(CVehicle* pVehicle)\n{\n\tif (pVehicle->AutoPilot.m_nTempAction == TEMPACT_WAIT){\n\t\tpVehicle->SetMoveSpeed(0.0f, 0.0f, 0.0f);\n\t\tpVehicle->AutoPilot.ModifySpeed(0.0f);\n\t\tif (CTimer::GetTimeInMilliseconds() > pVehicle->AutoPilot.m_nTempAction){\n\t\t\tpVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE;\n\t\t\tpVehicle->AutoPilot.m_nAntiReverseTimer = 0;\n\t\t\tpVehicle->AutoPilot.m_nTimeToStartMission = 0;\n\t\t}\n\t\treturn;\n\t}\n\tSlowCarOnRailsDownForTrafficAndLights(pVehicle);\n\tif (pVehicle->AutoPilot.m_nTimeEnteredCurve + pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve <= CTimer::GetTimeInMilliseconds())\n\t\tPickNextNodeAccordingStrategy(pVehicle);\n\tif (pVehicle->GetStatus() == STATUS_PHYSICS)\n\t\treturn;\n\tCCarPathLink* pCurrentLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nCurrentPathNodeInfo];\n\tCCarPathLink* pNextLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo];\n\tfloat currentPathLinkForwardX = pCurrentLink->GetDirX() * pVehicle->AutoPilot.m_nCurrentDirection;\n\tfloat currentPathLinkForwardY = pCurrentLink->GetDirY() * pVehicle->AutoPilot.m_nCurrentDirection;\n\tfloat nextPathLinkForwardX = pNextLink->GetDirX() * pVehicle->AutoPilot.m_nNextDirection;\n\tfloat nextPathLinkForwardY = pNextLink->GetDirY() * pVehicle->AutoPilot.m_nNextDirection;\n\tCVector positionOnCurrentLinkIncludingLane(\n\t\tpCurrentLink->GetX() + ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardY,\n\t\tpCurrentLink->GetY() - ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX,\n\t\t0.0f);\n\tCVector positionOnNextLinkIncludingLane(\n\t\tpNextLink->GetX() + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY,\n\t\tpNextLink->GetY() - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX,\n\t\t0.0f);\n\tCVector directionCurrentLink = GetRandomOffsetForVehicle(pVehicle, false);\n\tdirectionCurrentLink += CVector(currentPathLinkForwardX, currentPathLinkForwardY, 0.0f);\n\tdirectionCurrentLink.Normalise();\n\tCVector directionNextLink = GetRandomOffsetForVehicle(pVehicle, true);\n\tdirectionNextLink += CVector(nextPathLinkForwardX, nextPathLinkForwardY, 0.0f);\n\tdirectionNextLink.Normalise();\n\tCVector positionIncludingCurve;\n\tCVector directionIncludingCurve;\n\tCCurves::CalcCurvePoint(\n\t\t&positionOnCurrentLinkIncludingLane,\n\t\t&positionOnNextLinkIncludingLane,\n\t\t&directionCurrentLink,\n\t\t&directionNextLink,\n\t\tGetPositionAlongCurrentCurve(pVehicle),\n\t\tpVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve,\n\t\t&positionIncludingCurve,\n\t\t&directionIncludingCurve\n\t);\n\tpositionIncludingCurve.z = 15.0f;\n\tDragCarToPoint(pVehicle, &positionIncludingCurve);\n\tpVehicle->SetMoveSpeed(directionIncludingCurve / GAME_SPEED_TO_CARAI_SPEED);\n}\n\nfloat\nCCarCtrl::FindMaximumSpeedForThisCarInTraffic(CVehicle* pVehicle)\n{\n\tif (pVehicle->AutoPilot.m_nDrivingStyle == DRIVINGSTYLE_AVOID_CARS ||\n\t\tpVehicle->AutoPilot.m_nDrivingStyle == DRIVINGSTYLE_PLOUGH_THROUGH)\n\t\treturn pVehicle->AutoPilot.GetCruiseSpeed();\n\tfloat left = pVehicle->GetPosition().x - DISTANCE_TO_SCAN_FOR_DANGER;\n\tfloat right = pVehicle->GetPosition().x + DISTANCE_TO_SCAN_FOR_DANGER;\n\tfloat top = pVehicle->GetPosition().y - DISTANCE_TO_SCAN_FOR_DANGER;\n\tfloat bottom = pVehicle->GetPosition().y + DISTANCE_TO_SCAN_FOR_DANGER;\n\tint xstart = Max(0, CWorld::GetSectorIndexX(left));\n\tint xend = Min(NUMSECTORS_X - 1, CWorld::GetSectorIndexX(right));\n\tint ystart = Max(0, CWorld::GetSectorIndexY(top));\n\tint yend = Min(NUMSECTORS_Y - 1, CWorld::GetSectorIndexY(bottom));\n\tassert(xstart <= xend);\n\tassert(ystart <= yend);\n\n\tfloat maxSpeed = pVehicle->AutoPilot.GetCruiseSpeed();\n\n\tCWorld::AdvanceCurrentScanCode();\n\n\tfor (int y = ystart; y <= yend; y++){\n\t\tfor (int x = xstart; x <= xend; x++){\n\t\t\tCSector* s = CWorld::GetSector(x, y);\n\t\t\tSlowCarDownForCarsSectorList(s->m_lists[ENTITYLIST_VEHICLES], pVehicle, left, top, right, bottom, &maxSpeed, pVehicle->AutoPilot.GetCruiseSpeed());\n\t\t\tSlowCarDownForCarsSectorList(s->m_lists[ENTITYLIST_VEHICLES_OVERLAP], pVehicle, left, top, right, bottom, &maxSpeed, pVehicle->AutoPilot.GetCruiseSpeed());\n\t\t\tSlowCarDownForPedsSectorList(s->m_lists[ENTITYLIST_PEDS], pVehicle, left, top, right, bottom, &maxSpeed, pVehicle->AutoPilot.GetCruiseSpeed());\n\t\t\tSlowCarDownForPedsSectorList(s->m_lists[ENTITYLIST_PEDS_OVERLAP], pVehicle, left, top, right, bottom, &maxSpeed, pVehicle->AutoPilot.GetCruiseSpeed());\n\t\t}\n\t}\n\tpVehicle->bWarnedPeds = true;\n\tif (pVehicle->AutoPilot.m_nDrivingStyle == DRIVINGSTYLE_STOP_FOR_CARS || pVehicle->AutoPilot.m_nDrivingStyle == DRIVINGSTYLE_STOP_FOR_CARS_IGNORE_LIGHTS)\n\t\treturn maxSpeed;\n\treturn (maxSpeed + pVehicle->AutoPilot.GetCruiseSpeed()) / 2;\n}\n\nvoid\nCCarCtrl::ScanForPedDanger(CVehicle* pVehicle)\n{\n\tbool storedSlowDownFlag = pVehicle->AutoPilot.m_bSlowedDownBecauseOfPeds;\n\tfloat left = pVehicle->GetPosition().x - DISTANCE_TO_SCAN_FOR_PED_DANGER;\n\tfloat right = pVehicle->GetPosition().x + DISTANCE_TO_SCAN_FOR_PED_DANGER;\n\tfloat top = pVehicle->GetPosition().y - DISTANCE_TO_SCAN_FOR_PED_DANGER;\n\tfloat bottom = pVehicle->GetPosition().y + DISTANCE_TO_SCAN_FOR_PED_DANGER;\n\tint xstart = Max(0, CWorld::GetSectorIndexX(left));\n\tint xend = Min(NUMSECTORS_X - 1, CWorld::GetSectorIndexX(right));\n\tint ystart = Max(0, CWorld::GetSectorIndexY(top));\n\tint yend = Min(NUMSECTORS_Y - 1, CWorld::GetSectorIndexY(bottom));\n\tassert(xstart <= xend);\n\tassert(ystart <= yend);\n\n\tfloat maxSpeed = pVehicle->AutoPilot.m_nCruiseSpeed;\n\n\tCWorld::AdvanceCurrentScanCode();\n\n\tfor (int y = ystart; y <= yend; y++) {\n\t\tfor (int x = xstart; x <= xend; x++) {\n\t\t\tCSector* s = CWorld::GetSector(x, y);\n\t\t\tSlowCarDownForPedsSectorList(s->m_lists[ENTITYLIST_PEDS], pVehicle, left, top, right, bottom, &maxSpeed, pVehicle->AutoPilot.m_nCruiseSpeed);\n\t\t\tSlowCarDownForPedsSectorList(s->m_lists[ENTITYLIST_PEDS_OVERLAP], pVehicle, left, top, right, bottom, &maxSpeed, pVehicle->AutoPilot.m_nCruiseSpeed);\n\t\t}\n\t}\n\tpVehicle->bWarnedPeds = true;\n\tpVehicle->AutoPilot.m_bSlowedDownBecauseOfPeds = storedSlowDownFlag;\n}\n\nvoid\nCCarCtrl::SlowCarOnRailsDownForTrafficAndLights(CVehicle* pVehicle)\n{\n\tfloat maxSpeed;\n\tif (CTrafficLights::ShouldCarStopForLight(pVehicle, false) || CTrafficLights::ShouldCarStopForBridge(pVehicle)){\n\t\tCCarAI::CarHasReasonToStop(pVehicle);\n\t\tmaxSpeed = 0.0f;\n\t}else{\n\t\tmaxSpeed = FindMaximumSpeedForThisCarInTraffic(pVehicle);\n\t}\n\tfloat curSpeed = pVehicle->AutoPilot.m_fMaxTrafficSpeed;\n\tif (maxSpeed >= curSpeed){\n\t\tif (maxSpeed > curSpeed)\n\t\t\tpVehicle->AutoPilot.ModifySpeed(Min(maxSpeed, curSpeed + 0.05f * CTimer::GetTimeStep()));\n\t}else if (curSpeed != 0.0f) {\n\t\tif (curSpeed < 0.1f)\n\t\t\tpVehicle->AutoPilot.ModifySpeed(0.0f);\n\t\telse\n\t\t\tpVehicle->AutoPilot.ModifySpeed(Max(maxSpeed, curSpeed - 0.7f * CTimer::GetTimeStep()));\n\t}\n}\n\nvoid CCarCtrl::SlowCarDownForPedsSectorList(CPtrList& lst, CVehicle* pVehicle, float x_inf, float y_inf, float x_sup, float y_sup, float* pSpeed, float curSpeed)\n{\n\tfloat frontOffset = pVehicle->GetModelInfo()->GetColModel()->boundingBox.max.y;\n\tfloat frontSafe = frontOffset + SAFE_DISTANCE_TO_PED;\n\tfor (CPtrNode* pNode = lst.first; pNode != nil; pNode = pNode->next){\n\t\tCPed* pPed = (CPed*)pNode->item;\n\t\tif (pPed->m_scanCode == CWorld::GetCurrentScanCode())\n\t\t\tcontinue;\n\t\tif (!pPed->bUsesCollision)\n\t\t\tcontinue;\n\t\tpPed->m_scanCode = CWorld::GetCurrentScanCode();\n\t\tCVector vecPedPos = pPed->GetPosition();\n\t\tif (vecPedPos.x < x_inf || vecPedPos.x > x_sup)\n\t\t\tcontinue;\n\t\tif (vecPedPos.y < y_inf || vecPedPos.y > y_sup)\n\t\t\tcontinue;\n\t\tif (ABS(vecPedPos.z - pVehicle->GetPosition().z) >= 4.0f)\n\t\t\tcontinue;\n\t\tCVector vecToPed = vecPedPos - pVehicle->GetPosition();\n\t\tfloat dotDirection = DotProduct(pVehicle->GetForward(), vecToPed);\n\t\tfloat dotVelocity = DotProduct(pVehicle->GetForward(), pVehicle->GetMoveSpeed());\n\t\tif (dotDirection <= frontOffset) /* If already run him over, don't care */\n\t\t\tcontinue;\n\t\tfloat distanceUntilHit = dotDirection - frontOffset;\n\t\tfloat movementTowardsPedPerSecond = GAME_SPEED_TO_METERS_PER_SECOND * dotVelocity;\n\t\tif (4 * movementTowardsPedPerSecond <= distanceUntilHit)\n\t\t\t/* If car isn't projected to hit a ped in 4 seconds, don't care */\n\t\t\tcontinue;\n\t\tfloat sidewaysDistance = ABS(DotProduct(pVehicle->GetRight(), vecToPed));\n\t\tfloat sideLength = pVehicle->GetModelInfo()->GetColModel()->boundingBox.max.x;\n\t\tif (pVehicle->m_vehType == VEHICLE_TYPE_BIKE)\n\t\t\tsideLength *= 1.6f;\n\t\tif (sideLength + 0.5f < sidewaysDistance)\n\t\t\t/* If car is far enough taking side into account, don't care */\n\t\t\tcontinue;\n\t\tif (pPed->IsPed()){ /* ...how can it not be? */\n\t\t\tif (pPed->GetPedState() != PED_STEP_AWAY && pPed->GetPedState() != PED_DIVE_AWAY){\n\t\t\t\tif (distanceUntilHit < movementTowardsPedPerSecond){\n\t\t\t\t\t/* Very close. Time to evade. */\n\t\t\t\t\tif (pVehicle->GetModelIndex() == MI_RCBANDIT){\n\t\t\t\t\t\tif (dotVelocity * GAME_SPEED_TO_METERS_PER_SECOND / 2 > distanceUntilHit)\n\t\t\t\t\t\t\tpPed->SetEvasiveStep(pVehicle, 0);\n\t\t\t\t\t}else if (dotVelocity > 0.3f) {\n\t\t\t\t\t\tif (sideLength + 0.1f < sidewaysDistance)\n\t\t\t\t\t\t\tpPed->SetEvasiveStep(pVehicle, 0);\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tpPed->SetEvasiveDive(pVehicle, 0);\n\t\t\t\t\t}else if (dotVelocity > 0.1f) {\n\t\t\t\t\t\tif (sideLength - 0.5f < sidewaysDistance)\n\t\t\t\t\t\t\tpPed->SetEvasiveStep(pVehicle, 0);\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tpPed->SetEvasiveDive(pVehicle, 0);\n\t\t\t\t\t}\n\t\t\t\t}else{\n\t\t\t\t\t/* Relatively safe but annoying. */\n\t\t\t\t\tif (pVehicle->GetStatus() == STATUS_PLAYER &&\n\t\t\t\t\t  pPed->GetPedState() != PED_FLEE_ENTITY &&\n\t\t\t\t\t  pPed->CharCreatedBy == RANDOM_CHAR){\n\t\t\t\t\t\tfloat angleCarToPed = CGeneral::GetRadianAngleBetweenPoints(\n\t\t\t\t\t\t\tpVehicle->GetPosition().x, pVehicle->GetPosition().y,\n\t\t\t\t\t\t\tpPed->GetPosition().x, pPed->GetPosition().y\n\t\t\t\t\t\t);\n\t\t\t\t\t\tangleCarToPed = CGeneral::LimitRadianAngle(angleCarToPed);\n\t\t\t\t\t\tpPed->m_headingRate = CGeneral::LimitRadianAngle(pPed->m_headingRate);\n\t\t\t\t\t\tfloat visibilityAngle = ABS(angleCarToPed - pPed->m_headingRate);\n\t\t\t\t\t\tif (visibilityAngle > PI)\n\t\t\t\t\t\t\tvisibilityAngle = TWOPI - visibilityAngle;\n\t\t\t\t\t\tif (visibilityAngle < HALFPI || pVehicle->m_nCarHornTimer){\n\t\t\t\t\t\t\t/* if ped sees the danger or if car horn is on */\n\t\t\t\t\t\t\tpPed->SetFlee(pVehicle, 2000);\n\t\t\t\t\t\t\tpPed->bUsePedNodeSeek = false;\n\t\t\t\t\t\t\tpPed->SetMoveState(PEDMOVE_RUN);\n\t\t\t\t\t\t}\n\t\t\t\t\t}else{\n\t\t\t\t\t\tCPlayerPed* pPlayerPed = (CPlayerPed*)pPed;\n\t\t\t\t\t\tif (pPlayerPed->IsPlayer() && dotDirection < frontSafe &&\n\t\t\t\t\t\t  pPlayerPed->IsPedInControl() &&\n\t\t\t\t\t\t  pPlayerPed->m_fMoveSpeed < 1.0f && !pPlayerPed->bIsLooking &&\n\t\t\t\t\t\t  CTimer::GetTimeInMilliseconds() > pPlayerPed->m_lookTimer) {\n\t\t\t\t\t\t\tpPlayerPed->AnnoyPlayerPed(false);\n\t\t\t\t\t\t\tpPlayerPed->SetLookFlag(pVehicle, true);\n\t\t\t\t\t\t\tpPlayerPed->SetLookTimer(1500);\n\t\t\t\t\t\t\tif (pPlayerPed->GetWeapon()->m_eWeaponType == WEAPONTYPE_UNARMED ||\n\t\t\t\t\t\t\t\tpPlayerPed->GetWeapon()->m_eWeaponType == WEAPONTYPE_BASEBALLBAT ||\n\t\t\t\t\t\t\t\tpPlayerPed->GetWeapon()->m_eWeaponType == WEAPONTYPE_COLT45 ||\n\t\t\t\t\t\t\t\tpPlayerPed->GetWeapon()->m_eWeaponType == WEAPONTYPE_UZI) {\n\t\t\t\t\t\t\t\tpPlayerPed->bShakeFist = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t/* Ped stuff done. Now vehicle stuff. */\n\t\tif (distanceUntilHit < 10.0f){\n\t\t\tif (pVehicle->AutoPilot.m_nDrivingStyle == DRIVINGSTYLE_STOP_FOR_CARS ||\n\t\t\t  pVehicle->AutoPilot.m_nDrivingStyle == DRIVINGSTYLE_SLOW_DOWN_FOR_CARS){\n\t\t\t\t*pSpeed = Min(*pSpeed, ABS(distanceUntilHit - 1.0f) / 10.0f * curSpeed);\n\t\t\t\tpVehicle->AutoPilot.m_bSlowedDownBecauseOfPeds = true;\n\t\t\t\tif (distanceUntilHit < 2.0f){\n\t\t\t\t\tpVehicle->AutoPilot.m_nTempAction = TEMPACT_WAIT;\n\t\t\t\t\tpVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 3000;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid CCarCtrl::SlowCarDownForCarsSectorList(CPtrList& lst, CVehicle* pVehicle, float x_inf, float y_inf, float x_sup, float y_sup, float* pSpeed, float curSpeed)\n{\n\tfor (CPtrNode* pNode = lst.first; pNode != nil; pNode = pNode->next){\n\t\tCVehicle* pTestVehicle = (CVehicle*)pNode->item;\n\t\tif (pVehicle == pTestVehicle)\n\t\t\tcontinue;\n\t\tif (pTestVehicle->m_scanCode == CWorld::GetCurrentScanCode())\n\t\t\tcontinue;\n\t\tif (!pTestVehicle->bUsesCollision)\n\t\t\tcontinue;\n\t\tpTestVehicle->m_scanCode = CWorld::GetCurrentScanCode();\n\t\tCVector boundCenter = pTestVehicle->GetBoundCentre();\n\t\tif (boundCenter.x < x_inf || boundCenter.x > x_sup)\n\t\t\tcontinue;\n\t\tif (boundCenter.y < y_inf || boundCenter.y > y_sup)\n\t\t\tcontinue;\n\t\tif (Abs(boundCenter.z - pVehicle->GetPosition().z) < 5.0f)\n\t\t\tSlowCarDownForOtherCar(pTestVehicle, pVehicle, pSpeed, curSpeed);\n\t}\n}\n\nvoid CCarCtrl::SlowCarDownForOtherCar(CEntity* pOtherEntity, CVehicle* pVehicle, float* pSpeed, float curSpeed)\n{\n\tCVector forwardA = pVehicle->GetForward();\n\t((CVector2D)forwardA).Normalise();\n\tif (DotProduct2D(pOtherEntity->GetPosition() - pVehicle->GetPosition(), forwardA) < 0.0f)\n\t\treturn;\n\tCVector forwardB = pOtherEntity->GetForward();\n\t((CVector2D)forwardB).Normalise();\n\tforwardA.z = forwardB.z = 0.0f;\n\tCVehicle* pOtherVehicle = (CVehicle*)pOtherEntity;\n\t/* why is the argument CEntity if it's always CVehicle anyway and is casted? */\n\tfloat speedOtherX = GAME_SPEED_TO_CARAI_SPEED * pOtherVehicle->GetMoveSpeed().x;\n\tfloat speedOtherY = GAME_SPEED_TO_CARAI_SPEED * pOtherVehicle->GetMoveSpeed().y;\n\tfloat projectionX = speedOtherX - forwardA.x * curSpeed;\n\tfloat projectionY = speedOtherY - forwardA.y * curSpeed;\n\tfloat proximityA = TestCollisionBetween2MovingRects(pOtherVehicle, pVehicle, projectionX, projectionY, &forwardA, &forwardB, 0);\n\tfloat proximityB = TestCollisionBetween2MovingRects(pVehicle, pOtherVehicle, -projectionX, -projectionY, &forwardB, &forwardA, 1);\n\tfloat minProximity = Min(proximityA, proximityB);\n\tif (minProximity >= 0.0f && minProximity < 1.5f){\n\t\tminProximity = Max(0.0f, (minProximity - 0.2f) / 1.3f);\n\t\tpVehicle->AutoPilot.m_bSlowedDownBecauseOfCars = true;\n\t\t*pSpeed = Min(*pSpeed, minProximity * curSpeed);\n\t}\n\tif (minProximity >= 0.0f && minProximity < 0.5f && pOtherEntity->IsVehicle() &&\n\t  CTimer::GetTimeInMilliseconds() - pVehicle->AutoPilot.m_nTimeToStartMission > 15000 &&\n\t  CTimer::GetTimeInMilliseconds() - pOtherVehicle->AutoPilot.m_nTimeToStartMission > 15000){\n\t\t/* If cars are standing for 15 seconds, annoy one of them and make avoid cars. */\n\t\tif (pOtherEntity != FindPlayerVehicle() &&\n\t\t  DotProduct2D(pVehicle->GetForward(), pOtherVehicle->GetForward()) < -0.5f &&\n\t\t  pVehicle < pOtherVehicle){ /* that comparasion though... */\n\t\t\t*pSpeed = Max(curSpeed / 5, *pSpeed);\n\t\t\tif (pVehicle->GetStatus() == STATUS_SIMPLE){\n\t\t\t\tpVehicle->SetStatus(STATUS_PHYSICS);\n\t\t\t\tSwitchVehicleToRealPhysics(pVehicle);\n\t\t\t}\n\t\t\tpVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS;\n\t\t\tpVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 1000;\n\t\t}\n\t}\n}\n\nfloat CCarCtrl::TestCollisionBetween2MovingRects(CVehicle* pVehicleA, CVehicle* pVehicleB, float projectionX, float projectionY, CVector* pForwardA, CVector* pForwardB, uint8 id)\n{\n\tCVector2D vecBToA = pVehicleA->GetPosition() - pVehicleB->GetPosition();\n\tfloat lenB = pVehicleB->GetModelInfo()->GetColModel()->boundingBox.max.y;\n\tfloat widthB = pVehicleB->GetModelInfo()->GetColModel()->boundingBox.max.x;\n\tfloat backLenB = -pVehicleB->GetModelInfo()->GetColModel()->boundingBox.min.y;\n\tfloat lenA = pVehicleA->GetModelInfo()->GetColModel()->boundingBox.max.y;\n\tfloat widthA = pVehicleA->GetModelInfo()->GetColModel()->boundingBox.max.x;\n\tfloat backLenA = -pVehicleA->GetModelInfo()->GetColModel()->boundingBox.min.y;\n\tfloat proximity = 1.0f;\n\tfloat fullWidthB = 2.0f * widthB;\n\tfloat fullLenB = lenB + backLenB;\n\tfor (int i = 0; i < 4; i++){\n\t\tfloat testedOffsetX;\n\t\tfloat testedOffsetY;\n\t\tswitch (i) {\n\t\tcase 0: /* Front right corner */\n\t\t\ttestedOffsetX = vecBToA.x + widthA * pForwardB->y + lenA * pForwardB->x;\n\t\t\ttestedOffsetY = vecBToA.y + lenA * pForwardB->y - widthA * pForwardB->x;\n\t\t\tbreak;\n\t\tcase 1: /* Front left corner */\n\t\t\ttestedOffsetX = vecBToA.x + -widthA * pForwardB->x + lenA * pForwardB->x;\n\t\t\ttestedOffsetY = vecBToA.y + lenA * pForwardB->y + widthA * pForwardB->x;\n\t\t\tbreak;\n\t\tcase 2: /* Rear right corner */\n\t\t\ttestedOffsetX = vecBToA.x + widthA * pForwardB->y - backLenA * pForwardB->x;\n\t\t\ttestedOffsetY = vecBToA.y - backLenA * pForwardB->y - widthA * pForwardB->x;\n\t\t\tbreak;\n\t\tcase 3: /* Rear left corner */\n\t\t\ttestedOffsetX = vecBToA.x - widthA * pForwardB->y - backLenA * pForwardB->x;\n\t\t\ttestedOffsetY = vecBToA.y - backLenA * pForwardB->y + widthA * pForwardB->x;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\t\t/* Testing width collision */\n\t\tfloat baseWidthProximity = 0.0f;\n\t\tfloat fullWidthProximity = 1.0f;\n\t\tfloat widthDistance = testedOffsetX * pForwardA->y - testedOffsetY * pForwardA->x;\n\t\tfloat widthProjection = projectionX * pForwardA->y - projectionY * pForwardA->x;\n\t\tif (widthDistance > widthB){\n\t\t\tif (widthProjection < 0.0f){\n\t\t\t\tfloat proximityWidth = -(widthDistance - widthB) / widthProjection;\n\t\t\t\tif (proximityWidth < 1.0f){\n\t\t\t\t\tbaseWidthProximity = proximityWidth;\n\t\t\t\t\tfullWidthProximity = Min(1.0f, proximityWidth - fullWidthB / widthProjection);\n\t\t\t\t}else{\n\t\t\t\t\tbaseWidthProximity = 1.0f;\n\t\t\t\t}\n\t\t\t}else{\n\t\t\t\tbaseWidthProximity = 1.0f;\n\t\t\t\tfullWidthProximity = 1.0f;\n\t\t\t}\n\t\t}else if (widthDistance < -widthB){\n\t\t\tif (widthProjection > 0.0f) {\n\t\t\t\tfloat proximityWidth = -(widthDistance + widthB) / widthProjection;\n\t\t\t\tif (proximityWidth < 1.0f) {\n\t\t\t\t\tbaseWidthProximity = proximityWidth;\n\t\t\t\t\tfullWidthProximity = Min(1.0f, proximityWidth + fullWidthB / widthProjection);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tbaseWidthProximity = 1.0f;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tbaseWidthProximity = 1.0f;\n\t\t\t\tfullWidthProximity = 1.0f;\n\t\t\t}\n\t\t}else if (widthProjection > 0.0f){\n\t\t\tfullWidthProximity = (widthB - widthDistance) / widthProjection;\n\t\t}else if (widthProjection < 0.0f){\n\t\t\tfullWidthProximity = -(widthB + widthDistance) / widthProjection;\n\t\t}\n\t\t/* Testing length collision */\n\t\tfloat baseLengthProximity = 0.0f;\n\t\tfloat fullLengthProximity = 1.0f;\n\t\tfloat lenDistance = testedOffsetX * pForwardA->x + testedOffsetY * pForwardA->y;\n\t\tfloat lenProjection = projectionX * pForwardA->x + projectionY * pForwardA->y;\n\t\tif (lenDistance > lenB) {\n\t\t\tif (lenProjection < 0.0f) {\n\t\t\t\tfloat proximityLength = -(lenDistance - lenB) / lenProjection;\n\t\t\t\tif (proximityLength < 1.0f) {\n\t\t\t\t\tbaseLengthProximity = proximityLength;\n\t\t\t\t\tfullLengthProximity = Min(1.0f, proximityLength - fullLenB / lenProjection);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tbaseLengthProximity = 1.0f;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tbaseLengthProximity = 1.0f;\n\t\t\t\tfullLengthProximity = 1.0f;\n\t\t\t}\n\t\t}\n\t\telse if (lenDistance < -backLenB) {\n\t\t\tif (lenProjection > 0.0f) {\n\t\t\t\tfloat proximityLength = -(lenDistance + backLenB) / lenProjection;\n\t\t\t\tif (proximityLength < 1.0f) {\n\t\t\t\t\tbaseLengthProximity = proximityLength;\n\t\t\t\t\tfullLengthProximity = Min(1.0f, proximityLength + fullLenB / lenProjection);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tbaseLengthProximity = 1.0f;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tbaseLengthProximity = 1.0f;\n\t\t\t\tfullLengthProximity = 1.0f;\n\t\t\t}\n\t\t}\n\t\telse if (lenProjection > 0.0f) {\n\t\t\tfullLengthProximity = (lenB - lenDistance) / lenProjection;\n\t\t}\n\t\telse if (lenProjection < 0.0f) {\n\t\t\tfullLengthProximity = -(backLenB + lenDistance) / lenProjection;\n\t\t}\n\t\tfloat baseProximity = Max(baseWidthProximity, baseLengthProximity);\n\t\tif (baseProximity < fullWidthProximity && baseProximity < fullLengthProximity)\n\t\t\tproximity = Min(proximity, baseProximity);\n\t}\n\treturn proximity;\n}\n\nfloat CCarCtrl::FindAngleToWeaveThroughTraffic(CVehicle* pVehicle, CPhysical* pTarget, float angleToTarget, float angleForward)\n{\n\tfloat distanceToTest = Min(2.0f, pVehicle->GetMoveSpeed().Magnitude2D() / 0.4f + 1.0f) * 12.0f;\n\tfloat left = pVehicle->GetPosition().x - distanceToTest;\n\tfloat right = pVehicle->GetPosition().x + distanceToTest;\n\tfloat top = pVehicle->GetPosition().y - distanceToTest;\n\tfloat bottom = pVehicle->GetPosition().y + distanceToTest;\n\tint xstart = Max(0, CWorld::GetSectorIndexX(left));\n\tint xend = Min(NUMSECTORS_X - 1, CWorld::GetSectorIndexX(right));\n\tint ystart = Max(0, CWorld::GetSectorIndexY(top));\n\tint yend = Min(NUMSECTORS_Y - 1, CWorld::GetSectorIndexY(bottom));\n\tassert(xstart <= xend);\n\tassert(ystart <= yend);\n\n\tfloat angleToWeaveLeft = angleToTarget;\n\tfloat angleToWeaveRight = angleToTarget;\n\n\tCWorld::AdvanceCurrentScanCode();\n\n\tfloat angleToWeaveLeftLastIteration = -9999.9f;\n\tfloat angleToWeaveRightLastIteration = -9999.9f;\n\n\twhile (angleToWeaveLeft != angleToWeaveLeftLastIteration ||\n\t\t   angleToWeaveRight != angleToWeaveRightLastIteration){\n\t\tangleToWeaveLeftLastIteration = angleToWeaveLeft;\n\t\tangleToWeaveRightLastIteration = angleToWeaveRight;\n\t\tfor (int y = ystart; y <= yend; y++) {\n\t\t\tfor (int x = xstart; x <= xend; x++) {\n\t\t\t\tCSector* s = CWorld::GetSector(x, y);\n\t\t\t\tWeaveThroughCarsSectorList(s->m_lists[ENTITYLIST_VEHICLES], pVehicle, pTarget,\n\t\t\t\t\tleft, top, right, bottom, &angleToWeaveLeft, &angleToWeaveRight);\n\t\t\t\tWeaveThroughCarsSectorList(s->m_lists[ENTITYLIST_VEHICLES_OVERLAP], pVehicle, pTarget,\n\t\t\t\t\tleft, top, right, bottom, &angleToWeaveLeft, &angleToWeaveRight);\n\t\t\t\tWeaveThroughPedsSectorList(s->m_lists[ENTITYLIST_PEDS], pVehicle, pTarget,\n\t\t\t\t\tleft, top, right, bottom, &angleToWeaveLeft, &angleToWeaveRight);\n\t\t\t\tWeaveThroughPedsSectorList(s->m_lists[ENTITYLIST_PEDS_OVERLAP], pVehicle, pTarget,\n\t\t\t\t\tleft, top, right, bottom, &angleToWeaveLeft, &angleToWeaveRight);\n\t\t\t\tWeaveThroughObjectsSectorList(s->m_lists[ENTITYLIST_OBJECTS], pVehicle,\n\t\t\t\t\tleft, top, right, bottom, &angleToWeaveLeft, &angleToWeaveRight);\n\t\t\t\tWeaveThroughObjectsSectorList(s->m_lists[ENTITYLIST_OBJECTS_OVERLAP], pVehicle,\n\t\t\t\t\tleft, top, right, bottom, &angleToWeaveLeft, &angleToWeaveRight);\n\t\t\t}\n\t\t}\n\t}\n\tfloat angleDiffFromActualToTarget = LimitRadianAngle(angleForward - angleToTarget);\n\tfloat angleToBisectActualToTarget = LimitRadianAngle(angleToTarget + angleDiffFromActualToTarget / 2);\n\tfloat angleDiffLeft = LimitRadianAngle(angleToWeaveLeft - angleToBisectActualToTarget);\n\tangleDiffLeft = ABS(angleDiffLeft);\n\tfloat angleDiffRight = LimitRadianAngle(angleToWeaveRight - angleToBisectActualToTarget);\n\tangleDiffRight = ABS(angleDiffRight);\n\tif (angleDiffLeft > HALFPI && angleDiffRight > HALFPI)\n\t\treturn angleToBisectActualToTarget;\n\tif (ABS(angleDiffLeft - angleDiffRight) < 0.08f)\n\t\treturn angleToWeaveRight;\n\treturn angleDiffLeft < angleDiffRight ? angleToWeaveLeft : angleToWeaveRight;\n}\n\nvoid CCarCtrl::WeaveThroughCarsSectorList(CPtrList& lst, CVehicle* pVehicle, CPhysical* pTarget, float x_inf, float y_inf, float x_sup, float y_sup, float* pAngleToWeaveLeft, float* pAngleToWeaveRight)\n{\n\tfor (CPtrNode* pNode = lst.first; pNode != nil; pNode = pNode->next) {\n\t\tCVehicle* pTestVehicle = (CVehicle*)pNode->item;\n\t\tif (pTestVehicle->m_scanCode == CWorld::GetCurrentScanCode())\n\t\t\tcontinue;\n\t\tif (!pTestVehicle->bUsesCollision)\n\t\t\tcontinue;\n\t\tif (pTestVehicle == pTarget)\n\t\t\tcontinue;\n\t\tpTestVehicle->m_scanCode = CWorld::GetCurrentScanCode();\n\t\tif (pTestVehicle->GetBoundCentre().x < x_inf || pTestVehicle->GetBoundCentre().x > x_sup)\n\t\t\tcontinue;\n\t\tif (pTestVehicle->GetBoundCentre().y < y_inf || pTestVehicle->GetBoundCentre().y > y_sup)\n\t\t\tcontinue;\n\t\tif (Abs(pTestVehicle->GetPosition().z - pVehicle->GetPosition().z) >= VEHICLE_HEIGHT_DIFF_TO_CONSIDER_WEAVING)\n\t\t\tcontinue;\n\t\tif (pTestVehicle != pVehicle)\n\t\t\tWeaveForOtherCar(pTestVehicle, pVehicle, pAngleToWeaveLeft, pAngleToWeaveRight);\n\t}\n}\n\nvoid CCarCtrl::WeaveForOtherCar(CEntity* pOtherEntity, CVehicle* pVehicle, float* pAngleToWeaveLeft, float* pAngleToWeaveRight)\n{\n\tCVehicle* pOtherCar = (CVehicle*)pOtherEntity;\n\tif (pVehicle->bPartOfConvoy && pOtherCar->bPartOfConvoy)\n\t\treturn;\n\tif (pVehicle->AutoPilot.m_nCarMission == MISSION_RAMPLAYER_CLOSE && pOtherEntity == FindPlayerVehicle())\n\t\treturn;\n\tif (pVehicle->AutoPilot.m_nCarMission == MISSION_RAMCAR_CLOSE && pOtherEntity == pVehicle->AutoPilot.m_pTargetCar)\n\t\treturn;\n\tCVector2D vecDiff = pOtherCar->GetPosition() - pVehicle->GetPosition();\n\tfloat angleBetweenVehicles = CGeneral::GetATanOfXY(vecDiff.x, vecDiff.y);\n\tfloat distance = vecDiff.Magnitude();\n\tif (distance < 1.0f)\n\t\treturn;\n\tif (DotProduct2D(pVehicle->GetMoveSpeed() - pOtherCar->GetMoveSpeed(), vecDiff) * 110.0f -\n\t  pOtherCar->GetColModel()->boundingSphere.radius -\n\t  pVehicle->GetColModel()->boundingSphere.radius < distance)\n\t\treturn;\n\tCVector2D forward = pVehicle->GetForward();\n\tforward.Normalise();\n\tfloat forwardAngle = CGeneral::GetATanOfXY(forward.x, forward.y);\n\tfloat angleDiff = angleBetweenVehicles - forwardAngle;\n\tfloat lenProjection = ABS(pOtherCar->GetColModel()->boundingBox.max.y * sin(angleDiff));\n\tfloat widthProjection = ABS(pOtherCar->GetColModel()->boundingBox.max.x * cos(angleDiff));\n\tfloat lengthToEvade = (2 * (lenProjection + widthProjection) + WIDTH_COEF_TO_WEAVE_SAFELY * 2 * pVehicle->GetColModel()->boundingBox.max.x) / distance;\n\tfloat diffToLeftAngle = LimitRadianAngle(angleBetweenVehicles - *pAngleToWeaveLeft);\n\tdiffToLeftAngle = ABS(diffToLeftAngle);\n\tfloat angleToWeave = lengthToEvade / 2;\n\tif (diffToLeftAngle < angleToWeave){\n\t\t*pAngleToWeaveLeft = angleBetweenVehicles - angleToWeave;\n\t\twhile (*pAngleToWeaveLeft < -PI)\n\t\t\t*pAngleToWeaveLeft += TWOPI;\n\t}\n\tfloat diffToRightAngle = LimitRadianAngle(angleBetweenVehicles - *pAngleToWeaveRight);\n\tdiffToRightAngle = ABS(diffToRightAngle);\n\tif (diffToRightAngle < angleToWeave){\n\t\t*pAngleToWeaveRight = angleBetweenVehicles + angleToWeave;\n\t\twhile (*pAngleToWeaveRight > PI)\n\t\t\t*pAngleToWeaveRight -= TWOPI;\n\t}\n}\n\nvoid CCarCtrl::WeaveThroughPedsSectorList(CPtrList& lst, CVehicle* pVehicle, CPhysical* pTarget, float x_inf, float y_inf, float x_sup, float y_sup, float* pAngleToWeaveLeft, float* pAngleToWeaveRight)\n{\n\tfor (CPtrNode* pNode = lst.first; pNode != nil; pNode = pNode->next) {\n\t\tCPed* pPed = (CPed*)pNode->item;\n\t\tif (pPed->m_scanCode == CWorld::GetCurrentScanCode())\n\t\t\tcontinue;\n\t\tif (!pPed->bUsesCollision)\n\t\t\tcontinue;\n\t\tif (pPed == pTarget)\n\t\t\tcontinue;\n\t\tpPed->m_scanCode = CWorld::GetCurrentScanCode();\n\t\tif (pPed->GetPosition().x < x_inf || pPed->GetPosition().x > x_sup)\n\t\t\tcontinue;\n\t\tif (pPed->GetPosition().y < y_inf || pPed->GetPosition().y > y_sup)\n\t\t\tcontinue;\n\t\tif (Abs(pPed->GetPosition().z - pVehicle->GetPosition().z) >= PED_HEIGHT_DIFF_TO_CONSIDER_WEAVING)\n\t\t\tcontinue;\n\t\tif (pPed->m_pCurSurface != pVehicle && pPed->m_attachedTo != pVehicle)\n\t\t\tWeaveForPed(pPed, pVehicle, pAngleToWeaveLeft, pAngleToWeaveRight);\n\t}\n\n}\nvoid CCarCtrl::WeaveForPed(CEntity* pOtherEntity, CVehicle* pVehicle, float* pAngleToWeaveLeft, float* pAngleToWeaveRight)\n{\n\tif (pVehicle->AutoPilot.m_nCarMission == MISSION_RAMPLAYER_CLOSE && pOtherEntity == FindPlayerPed())\n\t\treturn;\n\tCPed* pPed = (CPed*)pOtherEntity;\n\tCVector2D vecDiff = pPed->GetPosition() - pVehicle->GetPosition();\n\tfloat angleBetweenVehicleAndPed = CGeneral::GetATanOfXY(vecDiff.x, vecDiff.y);\n\tfloat distance = vecDiff.Magnitude();\n\tfloat lengthToEvade = (WIDTH_COEF_TO_WEAVE_SAFELY * 2 * pVehicle->GetColModel()->boundingBox.max.x + PED_WIDTH_TO_WEAVE) / distance;\n\tfloat diffToLeftAngle = LimitRadianAngle(angleBetweenVehicleAndPed - *pAngleToWeaveLeft);\n\tdiffToLeftAngle = ABS(diffToLeftAngle);\n\tfloat angleToWeave = lengthToEvade / 2;\n\tif (diffToLeftAngle < angleToWeave) {\n\t\t*pAngleToWeaveLeft = angleBetweenVehicleAndPed - angleToWeave;\n\t\twhile (*pAngleToWeaveLeft < -PI)\n\t\t\t*pAngleToWeaveLeft += TWOPI;\n\t}\n\tfloat diffToRightAngle = LimitRadianAngle(angleBetweenVehicleAndPed - *pAngleToWeaveRight);\n\tdiffToRightAngle = ABS(diffToRightAngle);\n\tif (diffToRightAngle < angleToWeave) {\n\t\t*pAngleToWeaveRight = angleBetweenVehicleAndPed + angleToWeave;\n\t\twhile (*pAngleToWeaveRight > PI)\n\t\t\t*pAngleToWeaveRight -= TWOPI;\n\t}\n}\n\nvoid CCarCtrl::WeaveThroughObjectsSectorList(CPtrList& lst, CVehicle* pVehicle, float x_inf, float y_inf, float x_sup, float y_sup, float* pAngleToWeaveLeft, float* pAngleToWeaveRight)\n{\n\tfor (CPtrNode* pNode = lst.first; pNode != nil; pNode = pNode->next) {\n\t\tCObject* pObject = (CObject*)pNode->item;\n\t\tif (pObject->m_scanCode == CWorld::GetCurrentScanCode())\n\t\t\tcontinue;\n\t\tif (!pObject->bUsesCollision)\n\t\t\tcontinue;\n\t\tpObject->m_scanCode = CWorld::GetCurrentScanCode();\n\t\tif (pObject->GetPosition().x < x_inf || pObject->GetPosition().x > x_sup)\n\t\t\tcontinue;\n\t\tif (pObject->GetPosition().y < y_inf || pObject->GetPosition().y > y_sup)\n\t\t\tcontinue;\n\t\tif (Abs(pObject->GetPosition().z - pVehicle->GetPosition().z) >= OBJECT_HEIGHT_DIFF_TO_CONSIDER_WEAVING)\n\t\t\tcontinue;\n\t\tif (pObject->GetUp().z > 0.9f)\n\t\t\tWeaveForObject(pObject, pVehicle, pAngleToWeaveLeft, pAngleToWeaveRight);\n\t}\n}\n\nvoid CCarCtrl::WeaveForObject(CEntity* pOtherEntity, CVehicle* pVehicle, float* pAngleToWeaveLeft, float* pAngleToWeaveRight)\n{\n\tfloat rightCoef;\n\tfloat forwardCoef;\n\tif (pOtherEntity->GetModelIndex() == MI_TRAFFICLIGHTS){\n\t\trightCoef = 2.957f;\n\t\tforwardCoef = 0.147f;\n\t}else if (pOtherEntity->GetModelIndex() == MI_SINGLESTREETLIGHTS1){\n\t\trightCoef = 0.744f;\n\t\tforwardCoef = 0.0f;\n\t}else if (pOtherEntity->GetModelIndex() == MI_SINGLESTREETLIGHTS2){\n\t\trightCoef = 0.043f;\n\t\tforwardCoef = 0.0f;\n\t}else if (pOtherEntity->GetModelIndex() == MI_SINGLESTREETLIGHTS3){\n\t\trightCoef = 1.143f;\n\t\tforwardCoef = 0.145f;\n\t}else if (pOtherEntity->GetModelIndex() == MI_DOUBLESTREETLIGHTS){\n\t\trightCoef = 0.0f;\n\t\tforwardCoef = -0.048f;\n\t}else if (IsTreeModel(pOtherEntity->GetModelIndex())){\n\t\trightCoef = 0.0f;\n\t\tforwardCoef = 0.0f;\n\t}else if (pOtherEntity->GetModelIndex() == MI_STREETLAMP1 || pOtherEntity->GetModelIndex() == MI_STREETLAMP2){\n\t\trightCoef = 0.0f;\n\t\tforwardCoef = 0.0f;\n\t}else\n\t\treturn;\n\tCObject* pObject = (CObject*)pOtherEntity;\n\tCVector2D vecDiff = pObject->GetPosition() +\n\t\trightCoef * pObject->GetRight() +\n\t\tforwardCoef * pObject->GetForward() -\n\t\tpVehicle->GetPosition();\n\tfloat angleBetweenVehicleAndObject = CGeneral::GetATanOfXY(vecDiff.x, vecDiff.y);\n\tfloat distance = vecDiff.Magnitude();\n\tfloat lengthToEvade = (WIDTH_COEF_TO_WEAVE_SAFELY * 2 * pVehicle->GetColModel()->boundingBox.max.x + OBJECT_WIDTH_TO_WEAVE) / distance;\n\tfloat diffToLeftAngle = LimitRadianAngle(angleBetweenVehicleAndObject - *pAngleToWeaveLeft);\n\tdiffToLeftAngle = ABS(diffToLeftAngle);\n\tfloat angleToWeave = lengthToEvade / 2;\n\tif (diffToLeftAngle < angleToWeave) {\n\t\t*pAngleToWeaveLeft = angleBetweenVehicleAndObject - angleToWeave;\n\t\twhile (*pAngleToWeaveLeft < -PI)\n\t\t\t*pAngleToWeaveLeft += TWOPI;\n\t}\n\tfloat diffToRightAngle = LimitRadianAngle(angleBetweenVehicleAndObject - *pAngleToWeaveRight);\n\tdiffToRightAngle = ABS(diffToRightAngle);\n\tif (diffToRightAngle < angleToWeave) {\n\t\t*pAngleToWeaveRight = angleBetweenVehicleAndObject + angleToWeave;\n\t\twhile (*pAngleToWeaveRight > PI)\n\t\t\t*pAngleToWeaveRight -= TWOPI;\n\t}\n}\n\nbool CCarCtrl::PickNextNodeAccordingStrategy(CVehicle* pVehicle)\n{\n\tpVehicle->AutoPilot.m_nCruiseSpeedMultiplierType = ThePaths.m_pathNodes[pVehicle->AutoPilot.m_nNextRouteNode].speedLimit;\n\tswitch (pVehicle->AutoPilot.m_nCarMission){\n\tcase MISSION_RAMPLAYER_FARAWAY:\n\tcase MISSION_BLOCKPLAYER_FARAWAY:\n\t\tPickNextNodeToChaseCar(pVehicle,\n\t\t\tFindPlayerCoors().x,\n\t\t\tFindPlayerCoors().y,\n#ifdef FIX_PATHFIND_BUG\n\t\t\tFindPlayerCoors().z,\n#endif\n\t\t\tFindPlayerVehicle());\n\t\treturn false;\n\tcase MISSION_GOTOCOORDS:\n\tcase MISSION_GOTOCOORDS_ACCURATE:\n\t\treturn PickNextNodeToFollowPath(pVehicle);\n\tcase MISSION_RAMCAR_FARAWAY:\n\tcase MISSION_BLOCKCAR_FARAWAY:\n\t\tPickNextNodeToChaseCar(pVehicle,\n\t\t\tpVehicle->AutoPilot.m_pTargetCar->GetPosition().x,\n\t\t\tpVehicle->AutoPilot.m_pTargetCar->GetPosition().y,\n#ifdef FIX_PATHFIND_BUG\n\t\t\tpVehicle->AutoPilot.m_pTargetCar->GetPosition().z,\n#endif\n\t\t\tpVehicle->AutoPilot.m_pTargetCar);\n\t\treturn false;\n\tdefault:\n\t\tPickNextNodeRandomly(pVehicle);\n\t\tif (ThePaths.GetNode(pVehicle->AutoPilot.m_nNextRouteNode)->bOnlySmallBoats && BoatWithTallMast(pVehicle->GetModelIndex()))\n\t\t\tpVehicle->AutoPilot.m_nCruiseSpeed = 0;\n\t\treturn false;\n\t}\n}\n\nvoid CCarCtrl::PickNextNodeRandomly(CVehicle* pVehicle)\n{\n\tif (pVehicle->m_nRouteSeed)\n\t\tCGeneral::SetRandomSeed(pVehicle->m_nRouteSeed);\n\tint32 prevNode = pVehicle->AutoPilot.m_nCurrentRouteNode;\n\tint32 curNode = pVehicle->AutoPilot.m_nNextRouteNode;\n\tuint8 totalLinks = ThePaths.m_pathNodes[curNode].numLinks;\n\tCCarPathLink* pCurLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo];\n\tuint8 lanesOnCurrentPath;\n\tbool isOnOneWayRoad;\n\tif (pCurLink->pathNodeIndex == curNode) {\n\t\tlanesOnCurrentPath = pCurLink->numLeftLanes;\n\t\tisOnOneWayRoad = pCurLink->numRightLanes == 0;\n\t}\n\telse {\n\t\tlanesOnCurrentPath = pCurLink->numRightLanes;\n\t\tisOnOneWayRoad = pCurLink->numLeftLanes == 0;\n\t}\n\tuint8 allowedDirections = PATH_DIRECTION_NONE;\n\tuint8 nextLane = pVehicle->AutoPilot.m_nNextLane;\n\tif (nextLane == 0)\n\t\t/* We are always allowed to turn left from  leftmost lane */\n\t\tallowedDirections |= PATH_DIRECTION_LEFT;\n\tif (nextLane == lanesOnCurrentPath - 1)\n\t\t/* We are always allowed to turn right from rightmost lane */\n\t\tallowedDirections |= PATH_DIRECTION_RIGHT;\n\tif (lanesOnCurrentPath < 3 || allowedDirections == PATH_DIRECTION_NONE)\n\t\t/* We are always allowed to go straight on one/two-laned road */\n\t\t/* or if we are in one of middle lanes of the road */\n\t\tallowedDirections |= PATH_DIRECTION_STRAIGHT;\n\tint attempt;\n\tpVehicle->AutoPilot.m_nPrevRouteNode = pVehicle->AutoPilot.m_nCurrentRouteNode;\n\tpVehicle->AutoPilot.m_nCurrentRouteNode = pVehicle->AutoPilot.m_nNextRouteNode;\n\tCPathNode* pPrevPathNode = &ThePaths.m_pathNodes[prevNode];\n\tCPathNode* pCurPathNode = &ThePaths.m_pathNodes[curNode];\n\tint16 nextLink;\n\tCCarPathLink* pNextLink;\n\tCPathNode* pNextPathNode;\n\tbool goingAgainstOneWayRoad;\n\tbool nextNodeIsOneWayRoad;\n\tuint8 direction;\n\tfor(attempt = 0; attempt < ATTEMPTS_TO_FIND_NEXT_NODE; attempt++){\n\t\tif (attempt != 0){\n\t\t\tif (pVehicle->AutoPilot.m_nNextRouteNode != prevNode){\n\t\t\t\tif (direction & allowedDirections){\n\t\t\t\t\tpNextPathNode = &ThePaths.m_pathNodes[pVehicle->AutoPilot.m_nNextRouteNode];\n\t\t\t\t\tif ((!pNextPathNode->bDeadEnd || pPrevPathNode->bDeadEnd) &&\n\t\t\t\t\t\t(!pNextPathNode->bDisabled || pPrevPathNode->bDisabled) &&\n\t\t\t\t\t\t(!pNextPathNode->bBetweenLevels || pPrevPathNode->bBetweenLevels || !pVehicle->AutoPilot.m_bStayInCurrentLevel) &&\n\t\t\t\t\t\t!goingAgainstOneWayRoad && (!isOnOneWayRoad || !nextNodeIsOneWayRoad))\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tnextLink = CGeneral::GetRandomNumber() % totalLinks;\n\t\tpVehicle->AutoPilot.m_nNextRouteNode = ThePaths.ConnectedNode(nextLink + pCurPathNode->firstLink);\n\t\tdirection = FindPathDirection(prevNode, curNode, pVehicle->AutoPilot.m_nNextRouteNode);\n\t\tpNextLink = &ThePaths.m_carPathLinks[ThePaths.m_carPathConnections[nextLink + pCurPathNode->firstLink]];\n\t\tgoingAgainstOneWayRoad = pNextLink->pathNodeIndex == curNode ? pNextLink->numRightLanes == 0 : pNextLink->numLeftLanes == 0;\n\t\tnextNodeIsOneWayRoad = pNextLink->pathNodeIndex == curNode ? pNextLink->numLeftLanes == 0 : pNextLink->numRightLanes == 0;\n\t}\n\tif (attempt >= ATTEMPTS_TO_FIND_NEXT_NODE) {\n\t\t/* If we failed 15 times, then remove dead end, one way road and current lane limitations */\n\t\tfor (attempt = 0; attempt < ATTEMPTS_TO_FIND_NEXT_NODE; attempt++) {\n\t\t\tif (attempt != 0) {\n\t\t\t\tif (pVehicle->AutoPilot.m_nNextRouteNode != prevNode) {\n\t\t\t\t\tpNextPathNode = &ThePaths.m_pathNodes[pVehicle->AutoPilot.m_nNextRouteNode];\n\t\t\t\t\tif ((!pNextPathNode->bDisabled || pPrevPathNode->bDisabled) &&\n\t\t\t\t\t\t(!pNextPathNode->bBetweenLevels || pPrevPathNode->bBetweenLevels || !pVehicle->AutoPilot.m_bStayInCurrentLevel) &&\n\t\t\t\t\t\t!goingAgainstOneWayRoad)\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tnextLink = CGeneral::GetRandomNumber() % totalLinks;\n\t\t\tpVehicle->AutoPilot.m_nNextRouteNode = ThePaths.ConnectedNode(nextLink + pCurPathNode->firstLink);\n\t\t\tpNextLink = &ThePaths.m_carPathLinks[ThePaths.m_carPathConnections[nextLink + pCurPathNode->firstLink]];\n\t\t\tgoingAgainstOneWayRoad = pNextLink->pathNodeIndex == curNode ? pNextLink->numRightLanes == 0 : pNextLink->numLeftLanes == 0;\n\t\t}\n\t}\n\tif (attempt >= ATTEMPTS_TO_FIND_NEXT_NODE) {\n\t\t/* If we failed again, remove no U-turn limitation and remove randomness */\n\t\tfor (nextLink = 0; nextLink < totalLinks; nextLink++) {\n\t\t\tpVehicle->AutoPilot.m_nNextRouteNode = ThePaths.ConnectedNode(nextLink + pCurPathNode->firstLink);\n\t\t\tpNextLink = &ThePaths.m_carPathLinks[ThePaths.m_carPathConnections[nextLink + pCurPathNode->firstLink]];\n\t\t\tgoingAgainstOneWayRoad = pNextLink->pathNodeIndex == curNode ? pNextLink->numRightLanes == 0 : pNextLink->numLeftLanes == 0;\n\t\t\tif (!goingAgainstOneWayRoad) {\n\t\t\t\tpNextPathNode = &ThePaths.m_pathNodes[pVehicle->AutoPilot.m_nNextRouteNode];\n\t\t\t\tif ((!pNextPathNode->bDisabled || pPrevPathNode->bDisabled) &&\n\t\t\t\t\t(!pNextPathNode->bBetweenLevels || pPrevPathNode->bBetweenLevels || !pVehicle->AutoPilot.m_bStayInCurrentLevel))\n\t\t\t\t\t/* Nice way to exit loop but this will fail because this is used for indexing! */\n\t\t\t\t\tnextLink = 1000;\n\t\t\t}\n\t\t}\n\t\tif (nextLink < 999)\n\t\t\t/* If everything else failed, turn vehicle around */\n\t\t\tpVehicle->AutoPilot.m_nNextRouteNode = prevNode;\n\t}\n\tpNextPathNode = &ThePaths.m_pathNodes[pVehicle->AutoPilot.m_nNextRouteNode];\n\tpNextLink = &ThePaths.m_carPathLinks[ThePaths.m_carPathConnections[nextLink + pCurPathNode->firstLink]];\n\tif (prevNode == pVehicle->AutoPilot.m_nNextRouteNode){\n\t\t/* We can no longer shift vehicle without physics if we have to turn it around. */\n\t\tpVehicle->SetStatus(STATUS_PHYSICS);\n\t\tSwitchVehicleToRealPhysics(pVehicle);\n\t}\n\tpVehicle->AutoPilot.m_nTimeEnteredCurve += pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve;\n\tpVehicle->AutoPilot.m_nPreviousPathNodeInfo = pVehicle->AutoPilot.m_nCurrentPathNodeInfo;\n\tpVehicle->AutoPilot.m_nCurrentPathNodeInfo = pVehicle->AutoPilot.m_nNextPathNodeInfo;\n\tpVehicle->AutoPilot.m_nPreviousDirection = pVehicle->AutoPilot.m_nCurrentDirection;\n\tpVehicle->AutoPilot.m_nCurrentDirection = pVehicle->AutoPilot.m_nNextDirection;\n\tpVehicle->AutoPilot.m_nCurrentLane = pVehicle->AutoPilot.m_nNextLane;\n\tpVehicle->AutoPilot.m_nNextPathNodeInfo = ThePaths.m_carPathConnections[nextLink + pCurPathNode->firstLink];\n\tint8 lanesOnNextNode;\n\tif (curNode >= pVehicle->AutoPilot.m_nNextRouteNode){\n\t\tpVehicle->AutoPilot.m_nNextDirection = 1;\n\t\tlanesOnNextNode = pNextLink->numLeftLanes;\n\t}else{\n\t\tpVehicle->AutoPilot.m_nNextDirection = -1;\n\t\tlanesOnNextNode = pNextLink->numRightLanes;\n\t}\n\tfloat currentPathLinkForwardX = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->GetDirX();\n\tfloat nextPathLinkForwardX = pVehicle->AutoPilot.m_nNextDirection * pNextLink->GetDirX();\n#ifdef FIX_BUGS\n\tfloat currentPathLinkForwardY = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->GetDirY();\n\tfloat nextPathLinkForwardY = pVehicle->AutoPilot.m_nNextDirection * pNextLink->GetDirY();\n#endif\n\tif (lanesOnNextNode >= 0){\n\t\tif ((CGeneral::GetRandomNumber() & 0x600) == 0){\n\t\t\t/* 25% chance vehicle will try to switch lane */\n\t\t\tCVector2D dist = pNextPathNode->GetPosition() - pCurPathNode->GetPosition();\n\t\t\tif (dist.MagnitudeSqr() >= SQR(14.0f)){\n\t\t\t\tif (CGeneral::GetRandomTrueFalse())\n\t\t\t\t\tpVehicle->AutoPilot.m_nNextLane += 1;\n\t\t\t\telse\n\t\t\t\t\tpVehicle->AutoPilot.m_nNextLane -= 1;\n\t\t\t}\n\t\t}\n\t\tpVehicle->AutoPilot.m_nNextLane = Min(lanesOnNextNode - 1, pVehicle->AutoPilot.m_nNextLane);\n\t\tpVehicle->AutoPilot.m_nNextLane = Max(0, pVehicle->AutoPilot.m_nNextLane);\n\t}else{\n\t\tpVehicle->AutoPilot.m_nNextLane = pVehicle->AutoPilot.m_nCurrentLane;\n\t}\n\tif (pVehicle->AutoPilot.m_bStayInFastLane)\n\t\tpVehicle->AutoPilot.m_nNextLane = 0;\n\tCVector positionOnCurrentLinkIncludingLane(\n\t\tpCurLink->GetX() + ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH)\n#ifdef FIX_BUGS\n\t\t* currentPathLinkForwardY\n#endif\n\t\t,pCurLink->GetY() - ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX,\n\t\t0.0f);\n\tCVector positionOnNextLinkIncludingLane(\n\t\tpNextLink->GetX() + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH)\n#ifdef FIX_BUGS\n\t\t* nextPathLinkForwardY\n#endif\n\t\t,pNextLink->GetY() - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX,\n\t\t0.0f);\n\tfloat directionCurrentLinkX = pCurLink->GetDirX() * pVehicle->AutoPilot.m_nCurrentDirection;\n\tfloat directionCurrentLinkY = pCurLink->GetDirY() * pVehicle->AutoPilot.m_nCurrentDirection;\n\tfloat directionNextLinkX = pNextLink->GetDirX() * pVehicle->AutoPilot.m_nNextDirection;\n\tfloat directionNextLinkY = pNextLink->GetDirY() * pVehicle->AutoPilot.m_nNextDirection;\n\t/* We want to make a path between two links that may not have the same forward directions a curve. */\n\tpVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve = CCurves::CalcSpeedScaleFactor(\n\t\t&positionOnCurrentLinkIncludingLane,\n\t\t&positionOnNextLinkIncludingLane,\n\t\tdirectionCurrentLinkX, directionCurrentLinkY,\n\t\tdirectionNextLinkX, directionNextLinkY\n\t) * (1000.0f / pVehicle->AutoPilot.m_fMaxTrafficSpeed);\n\tif (pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve < 10)\n\t\t/* Oh hey there Obbe */\n\t\tprintf(\"fout\\n\");\n\tpVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve = Max(10, pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve);\n}\n\nuint8 CCarCtrl::FindPathDirection(int32 prevNode, int32 curNode, int32 nextNode)\n{\n\tCVector2D prevToCur = ThePaths.m_pathNodes[curNode].GetPosition() - ThePaths.m_pathNodes[prevNode].GetPosition();\n\tCVector2D curToNext = ThePaths.m_pathNodes[nextNode].GetPosition() - ThePaths.m_pathNodes[curNode].GetPosition();\n\tfloat distPrevToCur = prevToCur.Magnitude();\n\tif (distPrevToCur == 0.0f)\n\t\treturn PATH_DIRECTION_NONE;\n\t/* We are trying to determine angle between prevToCur and curToNext. */\n\t/* To find it, we consider a to be an angle between y axis and prevToCur */\n\t/* and b to be an angle between x axis and curToNext */\n\t/* Then the angle we are looking for is (pi/2 + a + b). */\n\tfloat sin_a = prevToCur.x / distPrevToCur;\n\tfloat cos_a = prevToCur.y / distPrevToCur;\n\tfloat distCurToNext = curToNext.Magnitude();\n\tif (distCurToNext == 0.0f)\n\t\treturn PATH_DIRECTION_NONE;\n\tfloat sin_b = curToNext.y / distCurToNext;\n\tfloat cos_b = curToNext.x / distCurToNext;\n\t/* sin(a) * sin(b) - cos(a) * cos(b) = -cos(a+b) = sin(pi/2+a+b) */\n\tfloat sin_direction = sin_a * sin_b - cos_a * cos_b;\n\tif (sin_direction > 0.77f) /* Roughly between -50 and -130 degrees */\n\t\treturn PATH_DIRECTION_LEFT;\n\tif (sin_direction < -0.77f) /* Roughly between 50 and 130 degrees */\n\t\treturn PATH_DIRECTION_RIGHT;\n\treturn PATH_DIRECTION_STRAIGHT;\n}\n\n#ifdef FIX_PATHFIND_BUG\nvoid CCarCtrl::PickNextNodeToChaseCar(CVehicle* pVehicle, float targetX, float targetY, float targetZ, CVehicle* pTarget)\n#else\nvoid CCarCtrl::PickNextNodeToChaseCar(CVehicle* pVehicle, float targetX, float targetY, CVehicle* pTarget)\n#endif\n{\n\tif (pVehicle->m_nRouteSeed)\n\t\tCGeneral::SetRandomSeed(pVehicle->m_nRouteSeed);\n\tint prevNode = pVehicle->AutoPilot.m_nCurrentRouteNode;\n\tint curNode = pVehicle->AutoPilot.m_nNextRouteNode;\n\tCPathNode* pPrevNode = &ThePaths.m_pathNodes[prevNode];\n\tCPathNode* pCurNode = &ThePaths.m_pathNodes[curNode];\n\tCPathNode* pTargetNode[2];\n\tint16 numNodes;\n\tfloat distanceToTargetNode;\n\tThePaths.DoPathSearch(0, pCurNode->GetPosition(), curNode,\n#ifdef FIX_PATHFIND_BUG\n\t\tCVector(targetX, targetY, targetZ),\n#else\n\t\tCVector(targetX, targetY, 0.0f),\n#endif\n\t\tpTargetNode, &numNodes, 2, pVehicle, &distanceToTargetNode, 999999.9f, -1);\n\n\tint newNextNode;\n\tint nextLink;\n\tif (numNodes != 1 && numNodes != 2 || pTargetNode[0] == pCurNode){\n\t\tif (numNodes != 2 || pTargetNode[1] == pCurNode) {\n\t\t\tfloat currentAngle = CGeneral::GetATanOfXY(targetX - pVehicle->GetPosition().x, targetY - pVehicle->GetPosition().y);\n\t\t\tnextLink = 0;\n\t\t\tfloat lowestAngleChange = 10.0f;\n\t\t\tint numLinks = pCurNode->numLinks;\n\t\t\tnewNextNode = 0;\n\t\t\tfor (int i = 0; i < numLinks; i++) {\n\t\t\t\tint conNode = ThePaths.ConnectedNode(i + pCurNode->firstLink);\n\t\t\t\tif (conNode == prevNode && i > 1)\n\t\t\t\t\tcontinue;\n\t\t\t\tCPathNode* pTestNode = &ThePaths.m_pathNodes[conNode];\n\t\t\t\tfloat angle = CGeneral::GetATanOfXY(pTestNode->GetX() - pCurNode->GetX(), pTestNode->GetY() - pCurNode->GetY());\n\t\t\t\tangle = LimitRadianAngle(angle - currentAngle);\n\t\t\t\tangle = ABS(angle);\n\t\t\t\tif (angle < lowestAngleChange) {\n\t\t\t\t\tlowestAngleChange = angle;\n\t\t\t\t\tnewNextNode = conNode;\n\t\t\t\t\tnextLink = i;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tnextLink = 0;\n\t\t\tnewNextNode = pTargetNode[1] - ThePaths.m_pathNodes;\n\t\t\tfor (int i = pCurNode->firstLink; ThePaths.ConnectedNode(i) != newNextNode; i++, nextLink++)\n\t\t\t\t;\n\t\t}\n\t}\n\telse {\n\t\tnextLink = 0;\n\t\tnewNextNode = pTargetNode[0] - ThePaths.m_pathNodes;\n\t\tfor (int i = pCurNode->firstLink; ThePaths.ConnectedNode(i) != newNextNode; i++, nextLink++)\n\t\t\t;\n\t}\n\tCPathNode* pNextPathNode = &ThePaths.m_pathNodes[pVehicle->AutoPilot.m_nNextRouteNode];\n\tCCarPathLink* pNextLink = &ThePaths.m_carPathLinks[ThePaths.m_carPathConnections[nextLink + pCurNode->firstLink]];\n\tCCarPathLink* pCurLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo];\n\tpVehicle->AutoPilot.m_nPrevRouteNode = pVehicle->AutoPilot.m_nCurrentRouteNode;\n\tpVehicle->AutoPilot.m_nCurrentRouteNode = pVehicle->AutoPilot.m_nNextRouteNode;\n\tpVehicle->AutoPilot.m_nNextRouteNode = newNextNode;\n\tpVehicle->AutoPilot.m_nTimeEnteredCurve += pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve;\n\tpVehicle->AutoPilot.m_nPreviousPathNodeInfo = pVehicle->AutoPilot.m_nCurrentPathNodeInfo;\n\tpVehicle->AutoPilot.m_nCurrentPathNodeInfo = pVehicle->AutoPilot.m_nNextPathNodeInfo;\n\tpVehicle->AutoPilot.m_nPreviousDirection = pVehicle->AutoPilot.m_nCurrentDirection;\n\tpVehicle->AutoPilot.m_nCurrentDirection = pVehicle->AutoPilot.m_nNextDirection;\n\tpVehicle->AutoPilot.m_nCurrentLane = pVehicle->AutoPilot.m_nNextLane;\n\tpVehicle->AutoPilot.m_nNextPathNodeInfo = ThePaths.m_carPathConnections[nextLink + pCurNode->firstLink];\n\tint8 lanesOnNextNode;\n\tif (curNode >= pVehicle->AutoPilot.m_nNextRouteNode) {\n\t\tpVehicle->AutoPilot.m_nNextDirection = 1;\n\t\tlanesOnNextNode = pNextLink->numRightLanes;\n\t}\n\telse {\n\t\tpVehicle->AutoPilot.m_nNextDirection = -1;\n\t\tlanesOnNextNode = pNextLink->numLeftLanes;\n\t}\n\tfloat currentPathLinkForwardX = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->GetDirX();\n\tfloat currentPathLinkForwardY = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->GetDirY();\n\tfloat nextPathLinkForwardX = pVehicle->AutoPilot.m_nNextDirection * pNextLink->GetDirX();\n\tfloat nextPathLinkForwardY = pVehicle->AutoPilot.m_nNextDirection * pNextLink->GetDirY();\n\tif (lanesOnNextNode >= 0) {\n\t\tCVector2D dist = pNextPathNode->GetPosition() - pCurNode->GetPosition();\n\t\tif (dist.MagnitudeSqr() >= SQR(7.0f)){\n\t\t\t/* 25% chance vehicle will try to switch lane */\n\t\t\t/* No lane switching if following car from far away */\n\t\t\t/* ...although it's always one of those. */\n\t\t\tif ((CGeneral::GetRandomNumber() & 0x600) == 0 &&\n\t\t\t  pVehicle->AutoPilot.m_nCarMission != MISSION_RAMPLAYER_FARAWAY &&\n\t\t\t  pVehicle->AutoPilot.m_nCarMission != MISSION_BLOCKPLAYER_FARAWAY &&\n\t\t\t  pVehicle->AutoPilot.m_nCarMission != MISSION_RAMCAR_FARAWAY &&\n\t\t\t  pVehicle->AutoPilot.m_nCarMission != MISSION_BLOCKCAR_FARAWAY){\n\t\t\t\tif (CGeneral::GetRandomTrueFalse())\n\t\t\t\t\tpVehicle->AutoPilot.m_nNextLane += 1;\n\t\t\t\telse\n\t\t\t\t\tpVehicle->AutoPilot.m_nNextLane -= 1;\n\t\t\t}\n\t\t}\n\t\tpVehicle->AutoPilot.m_nNextLane = Min(lanesOnNextNode - 1, pVehicle->AutoPilot.m_nNextLane);\n\t\tpVehicle->AutoPilot.m_nNextLane = Max(0, pVehicle->AutoPilot.m_nNextLane);\n\t}\n\telse {\n\t\tpVehicle->AutoPilot.m_nNextLane = pVehicle->AutoPilot.m_nCurrentLane;\n\t}\n\tif (pVehicle->AutoPilot.m_bStayInFastLane)\n\t\tpVehicle->AutoPilot.m_nNextLane = 0;\n\tCVector positionOnCurrentLinkIncludingLane(\n\t\tpCurLink->GetX() + ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardY,\n\t\tpCurLink->GetY() - ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX,\n\t\t0.0f);\n\tCVector positionOnNextLinkIncludingLane(\n\t\tpNextLink->GetX() + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY,\n\t\tpNextLink->GetY() - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX,\n\t\t0.0f);\n\tfloat directionCurrentLinkX = pCurLink->GetDirX() * pVehicle->AutoPilot.m_nCurrentDirection;\n\tfloat directionCurrentLinkY = pCurLink->GetDirY() * pVehicle->AutoPilot.m_nCurrentDirection;\n\tfloat directionNextLinkX = pNextLink->GetDirX() * pVehicle->AutoPilot.m_nNextDirection;\n\tfloat directionNextLinkY = pNextLink->GetDirY() * pVehicle->AutoPilot.m_nNextDirection;\n\t/* We want to make a path between two links that may not have the same forward directions a curve. */\n\tpVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve = CCurves::CalcSpeedScaleFactor(\n\t\t&positionOnCurrentLinkIncludingLane,\n\t\t&positionOnNextLinkIncludingLane,\n\t\tdirectionCurrentLinkX, directionCurrentLinkY,\n\t\tdirectionNextLinkX, directionNextLinkY\n\t) * (1000.0f / pVehicle->AutoPilot.m_fMaxTrafficSpeed);\n\tpVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve = Max(10, pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve);\n}\n\nbool CCarCtrl::PickNextNodeToFollowPath(CVehicle* pVehicle)\n{\n\tif (pVehicle->m_nRouteSeed)\n\t\tCGeneral::SetRandomSeed(pVehicle->m_nRouteSeed);\n\tint curNode = pVehicle->AutoPilot.m_nNextRouteNode;\n\tCPathNode* pCurNode = &ThePaths.m_pathNodes[curNode];\n\tif (pVehicle->AutoPilot.m_nPathFindNodesCount == 0){\n\t\tThePaths.DoPathSearch(0, pVehicle->GetPosition(), curNode,\n\t\t\tpVehicle->AutoPilot.m_vecDestinationCoors, pVehicle->AutoPilot.m_aPathFindNodesInfo,\n\t\t\t&pVehicle->AutoPilot.m_nPathFindNodesCount, NUM_PATH_NODES_IN_AUTOPILOT,\n\t\t\tpVehicle, nil, 999999.9f, -1);\n\t\tif (pVehicle->AutoPilot.m_nPathFindNodesCount < 2)\n\t\t\treturn true;\n\t\tpVehicle->AutoPilot.RemoveOnePathNode();\n\t}\n\tCPathNode* pNextPathNode = &ThePaths.m_pathNodes[pVehicle->AutoPilot.m_nNextRouteNode];\n\tCCarPathLink* pCurLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo];\n\tpVehicle->AutoPilot.m_nPrevRouteNode = pVehicle->AutoPilot.m_nCurrentRouteNode;\n\tpVehicle->AutoPilot.m_nCurrentRouteNode = pVehicle->AutoPilot.m_nNextRouteNode;\n\tpVehicle->AutoPilot.m_nNextRouteNode = pVehicle->AutoPilot.m_aPathFindNodesInfo[0] - ThePaths.m_pathNodes;\n\tpVehicle->AutoPilot.RemoveOnePathNode();\n\tpVehicle->AutoPilot.m_nTimeEnteredCurve += pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve;\n\tpVehicle->AutoPilot.m_nPreviousPathNodeInfo = pVehicle->AutoPilot.m_nCurrentPathNodeInfo;\n\tpVehicle->AutoPilot.m_nCurrentPathNodeInfo = pVehicle->AutoPilot.m_nNextPathNodeInfo;\n\tpVehicle->AutoPilot.m_nPreviousDirection = pVehicle->AutoPilot.m_nCurrentDirection;\n\tpVehicle->AutoPilot.m_nCurrentDirection = pVehicle->AutoPilot.m_nNextDirection;\n\tpVehicle->AutoPilot.m_nCurrentLane = pVehicle->AutoPilot.m_nNextLane;\n\tint nextLink = 0;\n\tfor (int i = pCurNode->firstLink; ThePaths.ConnectedNode(i) != pVehicle->AutoPilot.m_nNextRouteNode; i++, nextLink++)\n\t\t;\n\tCCarPathLink* pNextLink = &ThePaths.m_carPathLinks[ThePaths.m_carPathConnections[nextLink + pCurNode->firstLink]];\n\tpVehicle->AutoPilot.m_nNextPathNodeInfo = ThePaths.m_carPathConnections[nextLink + pCurNode->firstLink];\n\tint8 lanesOnNextNode;\n\tif (curNode >= pVehicle->AutoPilot.m_nNextRouteNode) {\n\t\tpVehicle->AutoPilot.m_nNextDirection = 1;\n\t\tlanesOnNextNode = pNextLink->numLeftLanes;\n\t}\n\telse {\n\t\tpVehicle->AutoPilot.m_nNextDirection = -1;\n\t\tlanesOnNextNode = pNextLink->numRightLanes;\n\t}\n\tfloat currentPathLinkForwardX = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->GetDirX();\n\tfloat currentPathLinkForwardY = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->GetDirY();\n\tfloat nextPathLinkForwardX = pVehicle->AutoPilot.m_nNextDirection * pNextLink->GetDirX();\n\tfloat nextPathLinkForwardY = pVehicle->AutoPilot.m_nNextDirection * pNextLink->GetDirY();\n\tif (lanesOnNextNode >= 0) {\n\t\tCVector2D dist = pNextPathNode->GetPosition() - pCurNode->GetPosition();\n\t\tif (dist.MagnitudeSqr() >= SQR(7.0f) && (CGeneral::GetRandomNumber() & 0x600) == 0) {\n\t\t\tif (CGeneral::GetRandomTrueFalse())\n\t\t\t\tpVehicle->AutoPilot.m_nNextLane += 1;\n\t\t\telse\n\t\t\t\tpVehicle->AutoPilot.m_nNextLane -= 1;\n\t\t}\n\t\tpVehicle->AutoPilot.m_nNextLane = Min(lanesOnNextNode - 1, pVehicle->AutoPilot.m_nNextLane);\n\t\tpVehicle->AutoPilot.m_nNextLane = Max(0, pVehicle->AutoPilot.m_nNextLane);\n\t}\n\telse {\n\t\tpVehicle->AutoPilot.m_nNextLane = pVehicle->AutoPilot.m_nCurrentLane;\n\t}\n\tif (pVehicle->AutoPilot.m_bStayInFastLane)\n\t\tpVehicle->AutoPilot.m_nNextLane = 0;\n\tCVector positionOnCurrentLinkIncludingLane(\n\t\tpCurLink->GetX() + ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardY,\n\t\tpCurLink->GetY() - ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX,\n\t\t0.0f);\n\tCVector positionOnNextLinkIncludingLane(\n\t\tpNextLink->GetX() + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY,\n\t\tpNextLink->GetY() - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX,\n\t\t0.0f);\n\tfloat directionCurrentLinkX = pCurLink->GetDirX() * pVehicle->AutoPilot.m_nCurrentDirection;\n\tfloat directionCurrentLinkY = pCurLink->GetDirY() * pVehicle->AutoPilot.m_nCurrentDirection;\n\tfloat directionNextLinkX = pNextLink->GetDirX() * pVehicle->AutoPilot.m_nNextDirection;\n\tfloat directionNextLinkY = pNextLink->GetDirY() * pVehicle->AutoPilot.m_nNextDirection;\n\t/* We want to make a path between two links that may not have the same forward directions a curve. */\n\tpVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve = CCurves::CalcSpeedScaleFactor(\n\t\t&positionOnCurrentLinkIncludingLane,\n\t\t&positionOnNextLinkIncludingLane,\n\t\tdirectionCurrentLinkX, directionCurrentLinkY,\n\t\tdirectionNextLinkX, directionNextLinkY\n\t) * (1000.0f / pVehicle->AutoPilot.m_fMaxTrafficSpeed);\n\tpVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve = Max(10, pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve);\n\treturn false;\n}\n\nvoid CCarCtrl::Init(void)\n{\n\tNumRandomCars = 0;\n\tNumLawEnforcerCars = 0;\n\tNumMissionCars = 0;\n\tNumParkedCars = 0;\n\tNumPermanentCars = 0;\n\tNumAmbulancesOnDuty = 0;\n\tNumFiretrucksOnDuty = 0;\n\tLastTimeFireTruckCreated = 0;\n\tLastTimeAmbulanceCreated = 0;\n#ifdef FIX_BUGS\n\tLastTimeLawEnforcerCreated = 0;\n\tLastTimeMiamiViceGenerated = 0;\n#endif\n\tbCarsGeneratedAroundCamera = false;\n\tCountDownToCarsAtStart = 2;\n\tCarDensityMultiplier = 1.0f;\n\tfor (int i = 0; i < MAX_CARS_TO_KEEP; i++)\n\t\tapCarsToKeep[i] = nil;\n\tfor (int i = 0; i < TOTAL_CUSTOM_CLASSES; i++){\n\t\tfor (int j = 0; j < MAX_CAR_MODELS_IN_ARRAY; j++) {\n\t\t\tLoadedCarsArray[i][j] = -1;\n\t\t}\n\t\tNumOfLoadedCarsOfRating[i] = 0;\n\t\tNumRequestsOfCarRating[i] = 0;\n\t\tTotalNumOfCarsOfRating[i] = 0;\n\t}\n}\n\nvoid CCarCtrl::ReInit(void)\n{\n\tNumRandomCars = 0;\n\tNumLawEnforcerCars = 0;\n\tNumMissionCars = 0;\n\tNumParkedCars = 0;\n\tNumPermanentCars = 0;\n\tNumAmbulancesOnDuty = 0;\n\tNumFiretrucksOnDuty = 0;\n#ifdef FIX_BUGS\n\tLastTimeFireTruckCreated = 0;\n\tLastTimeAmbulanceCreated = 0;\n\tLastTimeLawEnforcerCreated = 0;\n\tLastTimeMiamiViceGenerated = 0;\n#endif\n\tCountDownToCarsAtStart = 2;\n\tCarDensityMultiplier = 1.0f;\n\tfor (int i = 0; i < MAX_CARS_TO_KEEP; i++)\n\t\tapCarsToKeep[i] = nil;\n\tfor (int i = 0; i < TOTAL_CUSTOM_CLASSES; i++)\n\t\tNumRequestsOfCarRating[i] = 0;\n}\n\nvoid CCarCtrl::DragCarToPoint(CVehicle* pVehicle, CVector* pPoint)\n{\n\tCVector2D posBehind = (CVector2D)pVehicle->GetPosition() - 3 * pVehicle->GetForward() / 2;\n\tCVector2D posTarget = *pPoint;\n\tCVector2D direction = posBehind - posTarget;\n\tCVector2D midPos = posTarget + direction * 3 / direction.Magnitude();\n\tfloat actualAheadZ;\n\tfloat actualBehindZ;\n\tCColPoint point;\n\tCEntity* pRoadObject;\n\tif (CCollision::IsStoredPolyStillValidVerticalLine(CVector(posTarget.x, posTarget.y, pVehicle->GetPosition().z - 3.0f),\n\t  pVehicle->GetPosition().z - 3.0f, point, &pVehicle->m_aCollPolys[0])){\n\t\tactualAheadZ = point.point.z;\n\t}else if (CWorld::ProcessVerticalLine(CVector(posTarget.x, posTarget.y, pVehicle->GetPosition().z + 1.5f),\n\t  pVehicle->GetPosition().z - 2.0f, point,\n\t  pRoadObject, true, false, false, false, false, false, &pVehicle->m_aCollPolys[0])){\n\t\tactualAheadZ = point.point.z;\n\t\tpVehicle->m_pCurGroundEntity = pRoadObject;\n\t\tif (ThisRoadObjectCouldMove(pRoadObject->GetModelIndex()))\n\t\t\tpVehicle->m_aCollPolys[0].valid = false;\n\t}else if (CWorld::ProcessVerticalLine(CVector(posTarget.x, posTarget.y, pVehicle->GetPosition().z + 3.0f),\n\t  pVehicle->GetPosition().z - 3.0f, point,\n\t  pRoadObject, true, false, false, false, false, false, &pVehicle->m_aCollPolys[0])) {\n\t\tactualAheadZ = point.point.z;\n\t\tpVehicle->m_pCurGroundEntity = pRoadObject;\n\t\tif (ThisRoadObjectCouldMove(pRoadObject->GetModelIndex()))\n\t\t\tpVehicle->m_aCollPolys[0].valid = false;\n\t}else{\n\t\tactualAheadZ = pVehicle->m_fMapObjectHeightAhead;\n\t}\n\tpVehicle->m_fMapObjectHeightAhead = actualAheadZ;\n\tif (CCollision::IsStoredPolyStillValidVerticalLine(CVector(midPos.x, midPos.y, pVehicle->GetPosition().z - 3.0f),\n\t  pVehicle->GetPosition().z - 3.0f, point, &pVehicle->m_aCollPolys[1])){\n\t\tactualBehindZ = point.point.z;\n\t}else if (CWorld::ProcessVerticalLine(CVector(midPos.x, midPos.y, pVehicle->GetPosition().z + 1.5f),\n\t  pVehicle->GetPosition().z - 2.0f, point,\n\t  pRoadObject, true, false, false, false, false, false, &pVehicle->m_aCollPolys[1])){\n\t\tactualBehindZ = point.point.z;\n\t\tpVehicle->m_pCurGroundEntity = pRoadObject;\n\t\tif (ThisRoadObjectCouldMove(pRoadObject->GetModelIndex()))\n\t\t\tpVehicle->m_aCollPolys[1].valid = false;\n\t}else if (CWorld::ProcessVerticalLine(CVector(midPos.x, midPos.y, pVehicle->GetPosition().z + 3.0f),\n\t  pVehicle->GetPosition().z - 3.0f, point,\n\t  pRoadObject, true, false, false, false, false, false, &pVehicle->m_aCollPolys[1])){\n\t\tactualBehindZ = point.point.z;\n\t\tpVehicle->m_pCurGroundEntity = pRoadObject;\n\t\tif (ThisRoadObjectCouldMove(pRoadObject->GetModelIndex()))\n\t\t\tpVehicle->m_aCollPolys[1].valid = false;\n\t}else{\n\t\tactualBehindZ = pVehicle->m_fMapObjectHeightBehind;\n\t}\n\tpVehicle->m_fMapObjectHeightBehind = actualBehindZ;\n\tfloat angleZ = Atan2((actualAheadZ - actualBehindZ) / 3, 1.0f);\n\tfloat cosZ = Cos(angleZ);\n\tfloat sinZ = Sin(angleZ);\n\tpVehicle->GetRight() = CVector(posTarget.y - midPos.y, -(posTarget.x - midPos.x), 0.0f) / 3;\n\tpVehicle->GetForward() = CVector(-cosZ * pVehicle->GetRight().y, cosZ * pVehicle->GetRight().x, sinZ);\n\tpVehicle->GetUp() = CrossProduct(pVehicle->GetRight(), pVehicle->GetForward());\n\tpVehicle->SetPosition((CVector(midPos.x, midPos.y, actualBehindZ) + CVector(posTarget.x, posTarget.y, actualAheadZ)) / 2);\n\tpVehicle->GetMatrix().GetPosition().z += pVehicle->GetHeightAboveRoad();\n}\n\nfloat CCarCtrl::FindSpeedMultiplier(float angleChange, float minAngle, float maxAngle, float coef)\n{\n\tfloat angle = Abs(LimitRadianAngle(angleChange));\n\tfloat n = angle - minAngle;\n\tn = Max(0.0f, n);\n\tfloat d = maxAngle - minAngle;\n\tfloat mult = 1.0f - n / d * (1.0f - coef);\n\tif (n > d)\n\t\treturn coef;\n\treturn mult;\n}\n\nvoid CCarCtrl::SteerAICarWithPhysics(CVehicle* pVehicle)\n{\n\tfloat swerve;\n\tfloat accel;\n\tfloat brake;\n\tbool handbrake;\n\tswitch (pVehicle->AutoPilot.m_nTempAction){\n\tcase TEMPACT_WAIT:\n\t\tswerve = 0.0f;\n\t\taccel = 0.0f;\n\t\tbrake = 0.2f;\n\t\thandbrake = false;\n\t\tif (CTimer::GetTimeInMilliseconds() > pVehicle->AutoPilot.m_nTimeTempAction){\n\t\t\tpVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE;\n\t\t\tpVehicle->AutoPilot.m_nAntiReverseTimer = CTimer::GetTimeInMilliseconds();\n\t\t\tpVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds();\n\t\t}\n\t\tbreak;\n\tcase TEMPACT_REVERSE:\n\t\tSteerAICarWithPhysics_OnlyMission(pVehicle, &swerve, &accel, &brake, &handbrake);\n\t\thandbrake = false;\n\t\tswerve = -swerve;\n\t\tif (DotProduct(pVehicle->GetMoveSpeed(), pVehicle->GetForward()) > 0.04f){\n\t\t\taccel = 0.0f;\n\t\t\tbrake = 0.5f;\n\t\t}else{\n\t\t\taccel = -0.5f;\n\t\t\tbrake = 0.0f;\n\t\t}\n\t\tif (CTimer::GetTimeInMilliseconds() > pVehicle->AutoPilot.m_nTimeTempAction)\n\t\t\tpVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE;\n\t\tbreak;\n\tcase TEMPACT_HANDBRAKETURNLEFT:\n\t\tswerve = 1.0f;\n\t\taccel = 0.0f;\n\t\tbrake = 0.0f;\n\t\thandbrake = true;\n\t\tif (CTimer::GetTimeInMilliseconds() > pVehicle->AutoPilot.m_nTimeTempAction)\n\t\t\tpVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE;\n\t\tbreak;\n\tcase TEMPACT_HANDBRAKETURNRIGHT:\n\t\tswerve = -1.0f;\n\t\taccel = 0.0f;\n\t\tbrake = 0.0f;\n\t\thandbrake = true;\n\t\tif (CTimer::GetTimeInMilliseconds() > pVehicle->AutoPilot.m_nTimeTempAction)\n\t\t\tpVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE;\n\t\tbreak;\n\tcase TEMPACT_HANDBRAKESTRAIGHT:\n\t\tswerve = 0.0f;\n\t\taccel = 0.0f;\n\t\tbrake = 0.0f;\n\t\thandbrake = true;\n\t\tif (CTimer::GetTimeInMilliseconds() > pVehicle->AutoPilot.m_nTimeTempAction)\n\t\t\tpVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE;\n\t\tbreak;\n\tcase TEMPACT_TURNLEFT:\n\t\tswerve = 1.0f;\n\t\taccel = 1.0f;\n\t\tbrake = 0.0f;\n\t\thandbrake = false;\n\t\tif (CTimer::GetTimeInMilliseconds() > pVehicle->AutoPilot.m_nTimeTempAction)\n\t\t\tpVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE;\n\t\tbreak;\n\tcase TEMPACT_TURNRIGHT:\n\t\tswerve = -1.0f;\n\t\taccel = 1.0f;\n\t\tbrake = 0.0f;\n\t\thandbrake = false;\n\t\tif (CTimer::GetTimeInMilliseconds() > pVehicle->AutoPilot.m_nTimeTempAction)\n\t\t\tpVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE;\n\t\tbreak;\n\tcase TEMPACT_GOFORWARD:\n\t\tswerve = 0.0f;\n\t\taccel = 0.5f;\n\t\tbrake = 0.0f;\n\t\thandbrake = false;\n\t\tif (CTimer::GetTimeInMilliseconds() > pVehicle->AutoPilot.m_nTimeTempAction)\n\t\t\tpVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE;\n\t\tbreak;\n\tcase TEMPACT_SWERVELEFT:\n\tcase TEMPACT_SWERVERIGHT:\n\t\tswerve = (pVehicle->AutoPilot.m_nTempAction == TEMPACT_SWERVERIGHT) ? 0.15f : -0.15f;\n\t\taccel = 0.0f;\n\t\tbrake = 0.001f;\n\t\thandbrake = false;\n\t\tif (CTimer::GetTimeInMilliseconds() > pVehicle->AutoPilot.m_nTimeTempAction - 1000)\n\t\t\tswerve = -swerve;\n\t\tif (CTimer::GetTimeInMilliseconds() > pVehicle->AutoPilot.m_nTimeTempAction)\n\t\t\tpVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE;\n\t\tbreak;\n\tdefault:\n\t\tSteerAICarWithPhysics_OnlyMission(pVehicle, &swerve, &accel, &brake, &handbrake);\n\t\tbreak;\n\t}\n\tpVehicle->m_fSteerAngle = swerve;\n\tpVehicle->bIsHandbrakeOn = handbrake;\n\tpVehicle->m_fGasPedal = accel;\n\tpVehicle->m_fBrakePedal = brake;\n}\n\nvoid CCarCtrl::SteerAICarWithPhysics_OnlyMission(CVehicle* pVehicle, float* pSwerve, float* pAccel, float* pBrake, bool* pHandbrake)\n{\n\tswitch (pVehicle->AutoPilot.m_nCarMission) {\n\tcase MISSION_NONE:\n\t\t*pSwerve = 0.0f;\n\t\t*pAccel = 0.0f;\n\t\t*pBrake = 0.5f;\n\t\t*pHandbrake = true;\n\t\treturn;\n\tcase MISSION_CRUISE:\n\tcase MISSION_RAMPLAYER_FARAWAY:\n\tcase MISSION_BLOCKPLAYER_FARAWAY:\n\tcase MISSION_GOTOCOORDS:\n\tcase MISSION_GOTOCOORDS_ACCURATE:\n\tcase MISSION_RAMCAR_FARAWAY:\n\tcase MISSION_BLOCKCAR_FARAWAY:\n\t\tif (pVehicle->AutoPilot.m_bIgnorePathfinding) {\n\t\t\t*pSwerve = 0.0f;\n\t\t\t*pAccel = 1.0f;\n\t\t\t*pBrake = 0.0f;\n\t\t\t*pHandbrake = false;\n\t\t}else\n\t\t\tSteerAICarWithPhysicsFollowPath(pVehicle, pSwerve, pAccel, pBrake, pHandbrake);\n\t\treturn;\n\tcase MISSION_RAMPLAYER_CLOSE:\n\t{\n\t\tCVector2D targetPos = FindPlayerCoors();\n\t\tif (FindPlayerVehicle()){\n\t\t\tif (pVehicle->m_randomSeed & 1 && DotProduct(FindPlayerVehicle()->GetForward(), pVehicle->GetForward()) > 0.5f){\n\t\t\t\tfloat targetWidth = FindPlayerVehicle()->GetColModel()->boundingBox.max.x;\n\t\t\t\tfloat ownWidth = pVehicle->GetColModel()->boundingBox.max.x;\n\t\t\t\tif (pVehicle->m_randomSeed & 2){\n\t\t\t\t\ttargetPos += (targetWidth + ownWidth - 0.2f) * FindPlayerVehicle()->GetRight();\n\t\t\t\t}else{\n\t\t\t\t\ttargetPos -= (targetWidth + ownWidth - 0.2f) * FindPlayerVehicle()->GetRight();\n\t\t\t\t}\n\t\t\t\tfloat targetSpeed = FindPlayerVehicle()->GetMoveSpeed().Magnitude();\n\t\t\t\tfloat distanceToTarget = ((CVector2D)pVehicle->GetPosition() - targetPos).Magnitude();\n\t\t\t\tif (12.0f * targetSpeed + 2.0f > distanceToTarget && pVehicle->AutoPilot.m_nTempAction == TEMPACT_NONE){\n\t\t\t\t\tpVehicle->AutoPilot.m_nTempAction = (pVehicle->m_randomSeed & 2) ? TEMPACT_TURNLEFT : TEMPACT_TURNRIGHT;\n\t\t\t\t\tpVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 250;\n\t\t\t\t}\n\t\t\t}else{\n\t\t\t\ttargetPos += FindPlayerVehicle()->GetRight() / 160 * ((pVehicle->m_randomSeed & 0xFF) - 128);\n\t\t\t}\n\t\t}\n\t\tSteerAICarWithPhysicsHeadingForTarget(pVehicle, FindPlayerVehicle(), targetPos.x, targetPos.y, pSwerve, pAccel, pBrake, pHandbrake);\n\t\treturn;\n\t}\n\tcase MISSION_BLOCKPLAYER_CLOSE:\n\t\tSteerAICarWithPhysicsTryingToBlockTarget(pVehicle, FindPlayerCoors().x, FindPlayerCoors().y,\n\t\t\tFindPlayerSpeed().x, FindPlayerSpeed().y, pSwerve, pAccel, pBrake, pHandbrake);\n\t\treturn;\n\tcase MISSION_BLOCKPLAYER_HANDBRAKESTOP:\n\t\tSteerAICarWithPhysicsTryingToBlockTarget_Stop(pVehicle, FindPlayerCoors().x, FindPlayerCoors().y,\n\t\t\tFindPlayerSpeed().x, FindPlayerSpeed().y, pSwerve, pAccel, pBrake, pHandbrake);\n\t\treturn;\n\tcase MISSION_WAITFORDELETION:\n\tcase MISSION_HELI_LAND:\n\t\treturn;\n\tcase MISSION_GOTOCOORDS_STRAIGHT:\n\tcase MISSION_GOTO_COORDS_STRAIGHT_ACCURATE:\n\t\tSteerAICarWithPhysicsHeadingForTarget(pVehicle, nil,\n\t\t\tpVehicle->AutoPilot.m_vecDestinationCoors.x, pVehicle->AutoPilot.m_vecDestinationCoors.y,\n\t\t\tpSwerve, pAccel, pBrake, pHandbrake);\n\t\treturn;\n\tcase MISSION_EMERGENCYVEHICLE_STOP:\n\tcase MISSION_STOP_FOREVER:\n\t\t*pSwerve = 0.0f;\n\t\t*pAccel = 0.0f;\n\t\t*pHandbrake = true;\n\t\t*pBrake = 0.5f;\n\t\treturn;\n\tcase MISSION_GOTOCOORDS_ASTHECROWSWIMS:\n\t\tSteerAIBoatWithPhysicsHeadingForTarget(pVehicle,\n\t\t\tpVehicle->AutoPilot.m_vecDestinationCoors.x, pVehicle->AutoPilot.m_vecDestinationCoors.y,\n\t\t\tpSwerve, pAccel, pBrake);\n\t\t*pHandbrake = false;\n\t\treturn;\n\tcase MISSION_RAMCAR_CLOSE:\n\t\tSteerAICarWithPhysicsHeadingForTarget(pVehicle, pVehicle->AutoPilot.m_pTargetCar,\n\t\t\tpVehicle->AutoPilot.m_pTargetCar->GetPosition().x, pVehicle->AutoPilot.m_pTargetCar->GetPosition().y,\n\t\t\tpSwerve, pAccel, pBrake, pHandbrake);\n\t\treturn;\n\tcase MISSION_BLOCKCAR_CLOSE:\n\t\tSteerAICarWithPhysicsTryingToBlockTarget(pVehicle,\n\t\t\tpVehicle->AutoPilot.m_pTargetCar->GetPosition().x,\n\t\t\tpVehicle->AutoPilot.m_pTargetCar->GetPosition().y,\n\t\t\tpVehicle->AutoPilot.m_pTargetCar->GetMoveSpeed().x,\n\t\t\tpVehicle->AutoPilot.m_pTargetCar->GetMoveSpeed().y,\n\t\t\tpSwerve, pAccel, pBrake, pHandbrake);\n\t\treturn;\n\tcase MISSION_BLOCKCAR_HANDBRAKESTOP:\n\t\tSteerAICarWithPhysicsTryingToBlockTarget_Stop(pVehicle,\n\t\t\tpVehicle->AutoPilot.m_pTargetCar->GetPosition().x,\n\t\t\tpVehicle->AutoPilot.m_pTargetCar->GetPosition().y,\n\t\t\tpVehicle->AutoPilot.m_pTargetCar->GetMoveSpeed().x,\n\t\t\tpVehicle->AutoPilot.m_pTargetCar->GetMoveSpeed().y,\n\t\t\tpSwerve, pAccel, pBrake, pHandbrake);\n\t\treturn;\n\tcase MISSION_HELI_FLYTOCOORS:\n\t\tSteerAIHeliTowardsTargetCoors((CAutomobile*)pVehicle);\n\t\treturn;\n\tcase MISSION_ATTACKPLAYER:\n\t\tSteerAIBoatWithPhysicsAttackingPlayer(pVehicle, pSwerve, pAccel, pBrake, pHandbrake);\n\t\treturn;\n\tcase MISSION_PLANE_FLYTOCOORS:\n\t\tSteerAIPlaneTowardsTargetCoors((CAutomobile*)pVehicle);\n\t\treturn;\n\tcase MISSION_SLOWLY_DRIVE_TOWARDS_PLAYER_1:\n\t\tSteerAICarWithPhysicsHeadingForTarget(pVehicle, nil,\n\t\t\tpVehicle->AutoPilot.m_vecDestinationCoors.x, pVehicle->AutoPilot.m_vecDestinationCoors.y,\n\t\t\tpSwerve, pAccel, pBrake, pHandbrake);\n\t\treturn;\n\tcase MISSION_SLOWLY_DRIVE_TOWARDS_PLAYER_2:\n\t\tSteerAICarWithPhysicsHeadingForTarget(pVehicle, nil, FindPlayerCoors().x, FindPlayerCoors().y,\n\t\t\tpSwerve, pAccel, pBrake, pHandbrake);\n\t\treturn;\n\tcase MISSION_BLOCKPLAYER_FORWARDANDBACK:\n\t\tSteerAICarBlockingPlayerForwardAndBack(pVehicle, pSwerve, pAccel, pBrake, pHandbrake);\n\t\treturn;\n\tdefault:\n\t\tassert(0);\n\t\treturn;\n\t}\n}\n\nvoid CCarCtrl::SteerAICarBlockingPlayerForwardAndBack(CVehicle* pVehicle, float* pSwerve, float* pAccel, float* pBrake, bool* pHandbrake)\n{\n\t*pSwerve = 0.0f;\n\t*pHandbrake = false;\n\tCVector player = FindPlayerSpeed() + 0.1f * FindPlayerEntity()->GetForward();\n\tplayer.z = 0.0f;\n\tCVector right(pVehicle->GetRight().x, pVehicle->GetRight().y, 0.0f);\n\tright.Normalise();\n\tCVector forward(pVehicle->GetForward().x, pVehicle->GetForward().y, 0.0f);\n\tforward.Normalise();\n\tfloat dpPlayerAndRight = DotProduct(player, right);\n\tif (dpPlayerAndRight == 0.0f)\n\t\tdpPlayerAndRight = 0.01f;\n\tfloat dpDiffAndRight = -DotProduct((FindPlayerCoors() - pVehicle->GetPosition()), right) / dpPlayerAndRight;\n\tif (dpDiffAndRight < 0.0f) {\n\t\t*pAccel = 0.0f;\n\t\t*pBrake = 0.0f;\n\t\treturn;\n\t}\n\tfloat dpSpeedAndForward = DotProduct(pVehicle->GetMoveSpeed(), forward);\n\tfloat dpPlayerAndForward = DotProduct(player, forward);\n\tfloat dpDiffAndForward = DotProduct((FindPlayerCoors() - pVehicle->GetPosition()), forward);\n\tfloat multiplier = dpPlayerAndForward * dpDiffAndRight + dpDiffAndForward - dpSpeedAndForward * dpDiffAndRight;\n\tif (multiplier > 0) {\n\t\t*pAccel = Min(1.0f, 0.1f * multiplier);\n\t\t*pBrake = 0.0f;\n\t}\n\telse if (dpSpeedAndForward > 0) {\n\t\t*pAccel = 0.0f;\n\t\t*pBrake = Min(1.0f, -0.1f * multiplier);\n\t\tif (*pBrake > 0.95f)\n\t\t\t*pHandbrake = true;\n\t}\n\telse {\n\t\t*pAccel = Max(-1.0f, 0.1f * multiplier);\n\t\t*pBrake = 0.0f;\n\t}\n}\n\nvoid CCarCtrl::SteerAIBoatWithPhysicsHeadingForTarget(CVehicle* pVehicle, float targetX, float targetY, float* pSwerve, float* pAccel, float* pBrake)\n{\n\tCVector2D forward = pVehicle->GetForward();\n\tforward.Normalise();\n\tfloat angleToTarget = CGeneral::GetATanOfXY(targetX - pVehicle->GetPosition().x, targetY - pVehicle->GetPosition().y);\n\tfloat angleForward = CGeneral::GetATanOfXY(forward.x, forward.y);\n\tfloat steerAngle = LimitRadianAngle(angleToTarget - angleForward);\n\tsteerAngle = clamp(steerAngle, -DEFAULT_MAX_STEER_ANGLE, DEFAULT_MAX_STEER_ANGLE);\n#ifdef FIX_BUGS\n\tfloat speedTarget = pVehicle->AutoPilot.GetCruiseSpeed();\n#else\n\tfloat speedTarget = pVehicle->AutoPilot.m_nCruiseSpeed;\n#endif\n\tfloat currentSpeed = pVehicle->GetMoveSpeed().Magnitude() * GAME_SPEED_TO_CARAI_SPEED;\n\tfloat speedDiff = speedTarget - currentSpeed;\n\tif (speedDiff <= 0.0f) {\n\t\tspeedDiff < -5.0f ? *pAccel = -0.2f : *pAccel = -0.1f;\n\t\tsteerAngle *= -1;\n\t}\n\telse if (speedDiff / currentSpeed > 0.25f) {\n\t\t*pAccel = 1.0f;\n\t}\n\telse {\n\t\t*pAccel = 1.0f - (0.25f - speedDiff / currentSpeed) * 4.0f;\n\t}\n\t*pBrake = 0.0f;\n\t*pSwerve = steerAngle;\n}\n\nvoid CCarCtrl::SteerAIBoatWithPhysicsAttackingPlayer(CVehicle* pVehicle, float* pSwerve, float* pAccel, float* pBrake, bool* pHandbrake)\n{\n\tfloat distanceToPlayer = (FindPlayerCoors() - pVehicle->GetPosition()).Magnitude();\n\tfloat projection = Min(distanceToPlayer / 20.0f, 2.0f);\n\tCVector2D forward = pVehicle->GetForward();\n\tforward.Normalise();\n\tCVector2D vecToProjection = FindPlayerCoors() + FindPlayerSpeed() * projection * GAME_SPEED_TO_CARAI_SPEED;\n\tfloat angleToTarget = CGeneral::GetATanOfXY(vecToProjection.x - pVehicle->GetPosition().x, vecToProjection.y - pVehicle->GetPosition().y);\n\tfloat angleForward = CGeneral::GetATanOfXY(forward.x, forward.y);\n\tfloat steerAngle = LimitRadianAngle(angleToTarget - angleForward);\n#ifdef FIX_BUGS\n\tfloat speedTarget = pVehicle->AutoPilot.GetCruiseSpeed();\n#else\n\tfloat speedTarget = pVehicle->AutoPilot.m_nCruiseSpeed;\n#endif\n\tfloat currentSpeed = pVehicle->GetMoveSpeed().Magnitude() * GAME_SPEED_TO_CARAI_SPEED;\n\tfloat speedDiff = speedTarget - currentSpeed;\n\tif (speedDiff <= 0.0f) {\n\t\tspeedDiff < -5.0f ? *pAccel = -0.2f : *pAccel = -0.1f;\n\t}\n\telse if (speedDiff / currentSpeed > 0.25f) {\n\t\t*pAccel = 1.0f;\n\t}\n\telse {\n\t\t*pAccel = 1.0f - (0.25f - speedDiff / currentSpeed) * 4.0f;\n\t}\n\t*pBrake = 0.0f;\n\t*pSwerve = steerAngle;\n\t*pHandbrake = false;\n\tif (pVehicle->GetModelIndex() == MI_PREDATOR && distanceToPlayer < 40.0f && steerAngle < 0.15f)\n\t\tpVehicle->FireFixedMachineGuns();\n}\n\nfloat CCarCtrl::FindMaxSteerAngle(CVehicle* pVehicle)\n{\n\treturn pVehicle->GetModelIndex() == MI_ENFORCER ? 0.7f : DEFAULT_MAX_STEER_ANGLE;\n}\n\nvoid CCarCtrl::SteerAIHeliTowardsTargetCoors(CAutomobile* pHeli)\n{\n\tif (pHeli->m_aWheelSpeed[1] < 0.22f)\n\t\tpHeli->m_aWheelSpeed[1] += 0.001f;\n\tif (pHeli->m_aWheelSpeed[1] < 0.15f)\n\t\treturn;\n\tCVector2D vecToTarget = pHeli->AutoPilot.m_vecDestinationCoors - pHeli->GetPosition();\n\tfloat distanceToTarget = vecToTarget.Magnitude();\n#ifdef FIX_BUGS\n\tfloat speed = pHeli->AutoPilot.GetCruiseSpeed() * 0.01f;\n#else\n\tfloat speed = pHeli->AutoPilot.m_nCruiseSpeed * 0.01f;\n#endif\n\tif (distanceToTarget <= 100.0f)\n\t{\n\t\tif (distanceToTarget > 75.0f)\n\t\t\tspeed *= 0.7f;\n\t\telse if (distanceToTarget > 10.0f)\n\t\t\tspeed *= 0.4f;\n\t\telse\n\t\t\tspeed *= 0.2f;\n\t}\n\tvecToTarget.Normalise();\n\tCVector2D vecAdvanceThisFrame(vecToTarget * speed);\n\tfloat resistance = Pow(0.997f, CTimer::GetTimeStep());\n\tpHeli->m_vecMoveSpeed.x *= resistance;\n\tpHeli->m_vecMoveSpeed.y *= resistance;\n\tCVector2D vecSpeedDirection = vecAdvanceThisFrame - pHeli->m_vecMoveSpeed;\n\tfloat vecSpeedChangeLength = vecSpeedDirection.Magnitude();\n\tvecSpeedDirection.Normalise();\n\tfloat changeMultiplier = 0.002f * CTimer::GetTimeStep();\n\tif (distanceToTarget < 5.0f)\n\t\tchangeMultiplier /= 5.0f;\n\tif (vecSpeedChangeLength < changeMultiplier)\n\t\tpHeli->SetMoveSpeed(vecAdvanceThisFrame.x, vecAdvanceThisFrame.y, pHeli->GetMoveSpeed().z);\n\telse\n\t\tpHeli->AddToMoveSpeed(vecSpeedDirection * changeMultiplier);\n\tpHeli->GetMatrix().Translate(CTimer::GetTimeStep() * pHeli->GetMoveSpeed().x, CTimer::GetTimeStep() * pHeli->GetMoveSpeed().y, 0.0f);\n\tfloat ZTarget = pHeli->AutoPilot.m_vecDestinationCoors.z;\n\tif (CTimer::GetTimeInMilliseconds() & 0x800) // switch every ~2 seconds\n\t\tZTarget += 2.0f;\n\tfloat ZSpeedTarget = (ZTarget - pHeli->GetPosition().z) * 0.01f;\n\tfloat ZSpeedChangeTarget = ZSpeedTarget - pHeli->GetMoveSpeed().z;\n\tfloat ZSpeedChangeMax = 0.001f * CTimer::GetTimeStep();\n\tif (!pHeli->bHeliDestroyed) {\n\t\tif (Abs(ZSpeedChangeTarget) < ZSpeedChangeMax)\n\t\t\tpHeli->SetMoveSpeed(pHeli->GetMoveSpeed().x, pHeli->GetMoveSpeed().y, ZSpeedTarget);\n\t\telse if (ZSpeedChangeTarget < 0.0f)\n\t\t\tpHeli->AddToMoveSpeed(0.0f, 0.0f, -ZSpeedChangeMax);\n\t\telse\n\t\t\tpHeli->AddToMoveSpeed(0.0f, 0.0f, 1.5f * ZSpeedChangeMax);\n\t}\n\tpHeli->GetMatrix().Translate(0.0f, 0.0f, CTimer::GetTimeStep() * pHeli->GetMoveSpeed().z);\n\tpHeli->m_vecTurnSpeed.z *= Pow(0.99f, CTimer::GetTimeStep());\n\tfloat ZTurnSpeedTarget;\n\tif (distanceToTarget < 8.0f && pHeli->m_fHeliOrientation < 0.0f)\n\t\tZTurnSpeedTarget = 0.0f;\n\telse {\n\t\tfloat fAngleTarget = CGeneral::GetATanOfXY(vecToTarget.x, vecToTarget.y) + PI;\n\t\tif (pHeli->m_fHeliOrientation >= 0.0f)\n\t\t\tfAngleTarget = pHeli->m_fHeliOrientation;\n\t\tfAngleTarget -= pHeli->m_fOrientation;\n\t\twhile (fAngleTarget < -PI)\n\t\t\tfAngleTarget += TWOPI;\n\t\twhile (fAngleTarget > PI)\n\t\t\tfAngleTarget -= TWOPI;\n\t\tif (Abs(fAngleTarget) <= 0.4f)\n\t\t\tZTurnSpeedTarget = 0.0f;\n\t\telse if (fAngleTarget < 0.0f)\n\t\t\tZTurnSpeedTarget = -0.03f;\n\t\telse\n\t\t\tZTurnSpeedTarget = 0.03f;\n\t}\n\tfloat ZTurnSpeedChangeTarget = ZTurnSpeedTarget - pHeli->GetTurnSpeed().z;\n\tfloat ZTurnSpeedLimit = 0.0002f * CTimer::GetTimeStep();\n\tif (Abs(ZTurnSpeedChangeTarget) < ZTurnSpeedLimit)\n\t\tpHeli->m_vecTurnSpeed.z = ZTurnSpeedTarget;\n\telse if (ZTurnSpeedChangeTarget < 0.0f)\n\t\tpHeli->m_vecTurnSpeed.z -= ZTurnSpeedLimit;\n\telse\n\t\tpHeli->m_vecTurnSpeed.z += ZTurnSpeedLimit;\n\tpHeli->m_fOrientation += pHeli->GetTurnSpeed().z * CTimer::GetTimeStep();\n\tCVector up;\n\tif (pHeli->bHeliMinimumTilt)\n\t\tup = CVector(0.5f * pHeli->GetMoveSpeed().x, 0.5f * pHeli->GetMoveSpeed().y, 1.0f);\n\telse\n\t\tup = CVector(3.0f * pHeli->GetMoveSpeed().x, 3.0f * pHeli->GetMoveSpeed().y, 1.0f);\n\tup.Normalise();\n\tCVector forward(Cos(pHeli->m_fOrientation), Sin(pHeli->m_fOrientation), 0.0f);\n\tCVector right = CrossProduct(up, forward);\n\tforward = CrossProduct(up, right);\n\tpHeli->GetMatrix().GetRight() = right;\n\tpHeli->GetMatrix().GetForward() = forward;\n\tpHeli->GetMatrix().GetUp() = up;\n}\n\nvoid CCarCtrl::SteerAIPlaneTowardsTargetCoors(CAutomobile* pPlane)\n{\n\tCVector2D vecToTarget = pPlane->AutoPilot.m_vecDestinationCoors - pPlane->GetPosition();\n\tfloat fForwardZ = (pPlane->AutoPilot.m_vecDestinationCoors.z - pPlane->GetPosition().z) / vecToTarget.Magnitude();\n\tfForwardZ = clamp(fForwardZ, -0.3f, 0.3f);\n\tfloat angle = CGeneral::GetATanOfXY(vecToTarget.x, vecToTarget.y);\n\twhile (angle > TWOPI)\n\t\tangle -= TWOPI;\n\tfloat difference = LimitRadianAngle(angle - pPlane->m_fOrientation);\n\tfloat steer = difference > 0.0f ? 0.04f : -0.04f;\n\tif (Abs(difference) < 0.2f)\n\t\tsteer *= 5.0f * Abs(difference);\n\tpPlane->m_fPlaneSteer *= Pow(0.96f, CTimer::GetTimeStep());\n\tfloat steerChange = steer - pPlane->m_fPlaneSteer;\n\tfloat maxChange = 0.003f * CTimer::GetTimeStep();\n\tif (Abs(steerChange) < maxChange)\n\t\tpPlane->m_fPlaneSteer = steer;\n\telse if (steerChange < 0.0f)\n\t\tpPlane->m_fPlaneSteer -= maxChange;\n\telse\n\t\tpPlane->m_fPlaneSteer += maxChange;\n\tpPlane->m_fOrientation += pPlane->m_fPlaneSteer * CTimer::GetTimeStep();\n\tCVector up(0.0f, 0.0f, 1.0f);\n\tup.Normalise();\n\tCVector forward(Cos(pPlane->m_fOrientation), Sin(pPlane->m_fOrientation), fForwardZ);\n\tforward.Normalise();\n\tCVector right = CrossProduct(up, forward);\n\tright.z -= 5.0f * pPlane->m_fPlaneSteer;\n\tright.Normalise();\n\tup = CrossProduct(forward, right);\n\tup.Normalise();\n\tright = CrossProduct(forward, up);\n\tpPlane->GetMatrix().GetRight() = right;\n\tpPlane->GetMatrix().GetForward() = forward;\n\tpPlane->GetMatrix().GetUp() = up;\n\tfloat newSplit = 1.0f - Pow(0.95f, CTimer::GetTimeStep());\n\tfloat oldSplit = 1.0f - newSplit;\n#ifdef FIX_BUGS\n\tpPlane->m_vecMoveSpeed = pPlane->m_vecMoveSpeed * oldSplit + pPlane->AutoPilot.GetCruiseSpeed() * 0.01f * forward * newSplit;\n#else\n\tpPlane->m_vecMoveSpeed = pPlane->m_vecMoveSpeed * oldSplit + pPlane->AutoPilot.m_nCruiseSpeed * 0.01f * forward * newSplit;\n#endif\n\tpPlane->m_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f);\n}\n\nvoid CCarCtrl::SteerAICarWithPhysicsFollowPath(CVehicle* pVehicle, float* pSwerve, float* pAccel, float* pBrake, bool* pHandbrake)\n{\n\tCVector2D forward = pVehicle->GetForward();\n\tforward.Normalise();\n\tCCarPathLink* pCurrentLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nCurrentPathNodeInfo];\n\tCCarPathLink* pNextLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo];\n\tCVector2D currentPathLinkForward(pCurrentLink->GetDirX() * pVehicle->AutoPilot.m_nCurrentDirection,\n\t\tpCurrentLink->GetDirY() * pVehicle->AutoPilot.m_nCurrentDirection);\n\tfloat nextPathLinkForwardX = pNextLink->GetDirX() * pVehicle->AutoPilot.m_nNextDirection;\n\tfloat nextPathLinkForwardY = pNextLink->GetDirY() * pVehicle->AutoPilot.m_nNextDirection;\n\tCVector2D positionOnCurrentLinkIncludingLane(\n\t\tpCurrentLink->GetX() + ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.y,\n\t\tpCurrentLink->GetY() - ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.x);\n\tCVector2D positionOnNextLinkIncludingLane(\n\t\tpNextLink->GetX() + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY,\n\t\tpNextLink->GetY() - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX);\n\tCVector2D distanceToNextNode = (CVector2D)pVehicle->GetPosition() - positionOnCurrentLinkIncludingLane;\n\tfloat scalarDistanceToNextNode = distanceToNextNode.Magnitude();\n\tCVector2D distanceBetweenNodes = positionOnNextLinkIncludingLane - positionOnCurrentLinkIncludingLane;\n\tfloat dp = DotProduct2D(distanceBetweenNodes, distanceToNextNode);\n\tif (scalarDistanceToNextNode < DISTANCE_TO_NEXT_NODE_TO_SELECT_NEW ||\n\t  dp > 0.0f && scalarDistanceToNextNode < DISTANCE_TO_FACING_NEXT_NODE_TO_SELECT_NEW ||\n\t  dp / (scalarDistanceToNextNode * distanceBetweenNodes.Magnitude()) > 0.7f ||\n\t  pVehicle->AutoPilot.m_nNextPathNodeInfo == pVehicle->AutoPilot.m_nCurrentPathNodeInfo){\n\t\tif (PickNextNodeAccordingStrategy(pVehicle)) {\n\t\t\tswitch (pVehicle->AutoPilot.m_nCarMission){\n\t\t\tcase MISSION_GOTOCOORDS:\n\t\t\t\tpVehicle->AutoPilot.m_nCarMission = MISSION_GOTOCOORDS_STRAIGHT;\n\t\t\t\tSteerAICarWithPhysicsHeadingForTarget(pVehicle, nil, pVehicle->AutoPilot.m_vecDestinationCoors.x,\n\t\t\t\t\tpVehicle->AutoPilot.m_vecDestinationCoors.y, pSwerve, pAccel, pBrake, pHandbrake);\n\t\t\t\treturn;\n\t\t\tcase MISSION_GOTOCOORDS_ACCURATE:\n\t\t\t\tpVehicle->AutoPilot.m_nCarMission = MISSION_GOTO_COORDS_STRAIGHT_ACCURATE;\n\t\t\t\tSteerAICarWithPhysicsHeadingForTarget(pVehicle, nil, pVehicle->AutoPilot.m_vecDestinationCoors.x,\n\t\t\t\t\tpVehicle->AutoPilot.m_vecDestinationCoors.y, pSwerve, pAccel, pBrake, pHandbrake);\n\t\t\t\treturn;\n\t\t\tdefault: break;\n\t\t\t}\n\t\t}\n\t\tpCurrentLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nCurrentPathNodeInfo];\n\t\tscalarDistanceToNextNode = CVector2D(\n\t\t\tpCurrentLink->GetX() + ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.y - pVehicle->GetPosition().x,\n\t\t\tpCurrentLink->GetY() - ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.x - pVehicle->GetPosition().y).Magnitude();\t\t\n\t\tpNextLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo];\n\t\tcurrentPathLinkForward.x = pCurrentLink->GetDirX() * pVehicle->AutoPilot.m_nCurrentDirection;\n\t\tcurrentPathLinkForward.y = pCurrentLink->GetDirY() * pVehicle->AutoPilot.m_nCurrentDirection;\n\t\tnextPathLinkForwardX = pNextLink->GetDirX() * pVehicle->AutoPilot.m_nNextDirection;\n\t\tnextPathLinkForwardY = pNextLink->GetDirY() * pVehicle->AutoPilot.m_nNextDirection;\n\t}\n\tpositionOnCurrentLinkIncludingLane.x = pCurrentLink->GetX() + ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.y;\n\tpositionOnCurrentLinkIncludingLane.y = pCurrentLink->GetY() - ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.x;\n\tCVector2D projectedPosition = positionOnCurrentLinkIncludingLane - currentPathLinkForward * scalarDistanceToNextNode * 0.4f;\n\tif (scalarDistanceToNextNode > DISTANCE_TO_NEXT_NODE_TO_CONSIDER_SLOWING_DOWN){\n\t\tprojectedPosition.x = positionOnCurrentLinkIncludingLane.x;\n\t\tprojectedPosition.y = positionOnCurrentLinkIncludingLane.y;\n\t}\n\tCVector2D distanceToProjectedPosition = projectedPosition - pVehicle->GetPosition();\n\tfloat angleCurrentLink = CGeneral::GetATanOfXY(distanceToProjectedPosition.x, distanceToProjectedPosition.y);\n\tfloat angleForward = CGeneral::GetATanOfXY(forward.x, forward.y);\n\tif (pVehicle->AutoPilot.m_nDrivingStyle == DRIVINGSTYLE_AVOID_CARS)\n\t\tangleCurrentLink = FindAngleToWeaveThroughTraffic(pVehicle, nil, angleCurrentLink, angleForward);\n\tfloat steerAngle = LimitRadianAngle(angleCurrentLink - angleForward);\n\tfloat maxAngle = FindMaxSteerAngle(pVehicle);\n\tsteerAngle = Min(maxAngle, Max(-maxAngle, steerAngle));\n\tif (pVehicle->GetMoveSpeed().Magnitude() > MIN_SPEED_TO_START_LIMITING_STEER)\n\t\tsteerAngle = Min(MAX_ANGLE_TO_STEER_AT_HIGH_SPEED, Max(-MAX_ANGLE_TO_STEER_AT_HIGH_SPEED, steerAngle));\n\tfloat currentForwardSpeed = DotProduct(pVehicle->GetMoveSpeed(), pVehicle->GetForward()) * GAME_SPEED_TO_CARAI_SPEED;\n\tfloat speedStyleMultiplier;\n\tswitch (pVehicle->AutoPilot.m_nDrivingStyle) {\n\tcase DRIVINGSTYLE_STOP_FOR_CARS:\n\tcase DRIVINGSTYLE_SLOW_DOWN_FOR_CARS:\n\tcase DRIVINGSTYLE_STOP_FOR_CARS_IGNORE_LIGHTS:\n\t\tspeedStyleMultiplier = FindMaximumSpeedForThisCarInTraffic(pVehicle);\n#ifdef FIX_BUGS\n\t\tif (pVehicle->AutoPilot.GetCruiseSpeed() != 0)\n\t\t\tspeedStyleMultiplier /= pVehicle->AutoPilot.GetCruiseSpeed();\n#else\n\t\tspeedStyleMultiplier /= pVehicle->AutoPilot.m_nCruiseSpeed;\n#endif\n\t\tbreak;\n\tdefault:\n\t\tspeedStyleMultiplier = 1.0f;\n\t\tbreak;\n\t}\n\tswitch (pVehicle->AutoPilot.m_nDrivingStyle) {\n\tcase DRIVINGSTYLE_STOP_FOR_CARS:\n\tcase DRIVINGSTYLE_SLOW_DOWN_FOR_CARS:\n\t\tif (CTrafficLights::ShouldCarStopForLight(pVehicle, false)){\n\t\t\tCCarAI::CarHasReasonToStop(pVehicle);\n\t\t\tspeedStyleMultiplier = 0.0f;\n\t\t}\n\t\tbreak;\n\tdefault:\n\t\tbreak;\n\t}\n\tif (CTrafficLights::ShouldCarStopForBridge(pVehicle)){\n\t\tCCarAI::CarHasReasonToStop(pVehicle);\n\t\tspeedStyleMultiplier = 0.0f;\n\t}\n\tCVector2D trajectory(pCurrentLink->GetX() + ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.y,\n\t\tpCurrentLink->GetY() - ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.x);\n\ttrajectory -= pVehicle->GetPosition();\n\tfloat speedAngleMultiplier = FindSpeedMultiplier(\n\t\tCGeneral::GetATanOfXY(trajectory.x, trajectory.y) - angleForward,\n\t\tMIN_ANGLE_FOR_SPEED_LIMITING, MAX_ANGLE_FOR_SPEED_LIMITING, MIN_LOWERING_SPEED_COEFFICIENT);\n\tfloat tmpWideMultiplier = FindSpeedMultiplier(\n\t\tCGeneral::GetATanOfXY(currentPathLinkForward.x, currentPathLinkForward.y) -\n\t\tCGeneral::GetATanOfXY(nextPathLinkForwardX, nextPathLinkForwardY),\n\t\tMIN_ANGLE_FOR_SPEED_LIMITING_BETWEEN_NODES, MAX_ANGLE_FOR_SPEED_LIMITING, MIN_LOWERING_SPEED_COEFFICIENT);\n\tfloat speedNodesMultiplier;\n\tif (scalarDistanceToNextNode > DISTANCE_TO_NEXT_NODE_TO_CONSIDER_SLOWING_DOWN || pVehicle->AutoPilot.m_nCruiseSpeed < 12)\n\t\tspeedNodesMultiplier = 1.0f;\n\telse\n\t\tspeedNodesMultiplier = 1.0f -\n\t\t\t(1.0f - scalarDistanceToNextNode / DISTANCE_TO_NEXT_NODE_TO_CONSIDER_SLOWING_DOWN) *\n\t\t\t(1.0f - tmpWideMultiplier);\n\tfloat speedMultiplier = Min(speedStyleMultiplier, Min(speedAngleMultiplier, speedNodesMultiplier));\n\tfloat speed = pVehicle->AutoPilot.m_nCruiseSpeed * speedMultiplier;\n\tfloat speedDifference = speed - currentForwardSpeed;\n\tif (speed < 0.05f && speedDifference < 0.03f){\n\t\t*pBrake = 1.0f;\n\t\t*pAccel = 0.0f;\n\t}else if (speedDifference <= 0.0f){\n\t\t*pBrake = Min(0.5f, -speedDifference * 0.05f);\n\t\t*pAccel = 0.0f;\n\t}else if (currentForwardSpeed < 2.0f){\n\t\t*pBrake = 0.0f;\n\t\t*pAccel = Min(1.0f, speedDifference * 0.25f);\n\t}else{\n\t\t*pBrake = 0.0f;\n\t\t*pAccel = Min(1.0f, speedDifference * 0.125f);\n\t}\n\t*pSwerve = steerAngle;\n\t*pHandbrake = false;\n}\n\nvoid CCarCtrl::SteerAICarWithPhysicsHeadingForTarget(CVehicle* pVehicle, CPhysical* pTarget, float targetX, float targetY, float* pSwerve, float* pAccel, float* pBrake, bool* pHandbrake)\n{\n\t*pHandbrake = false;\n\tCVector2D forward = pVehicle->GetForward();\n\tforward.Normalise();\n\tfloat angleToTarget = CGeneral::GetATanOfXY(targetX - pVehicle->GetPosition().x, targetY - pVehicle->GetPosition().y);\n\tfloat angleForward = CGeneral::GetATanOfXY(forward.x, forward.y);\n\tif (pVehicle->AutoPilot.m_nDrivingStyle == DRIVINGSTYLE_AVOID_CARS)\n\t\tangleToTarget = FindAngleToWeaveThroughTraffic(pVehicle, pTarget, angleToTarget, angleForward);\n\tfloat steerAngle = LimitRadianAngle(angleToTarget - angleForward);\n\tif (pVehicle->GetMoveSpeed().Magnitude() > MIN_SPEED_TO_APPLY_HANDBRAKE)\n\t\tif (ABS(steerAngle) > MIN_ANGLE_TO_APPLY_HANDBRAKE)\n\t\t\t*pHandbrake = true;\n\tfloat maxAngle = FindMaxSteerAngle(pVehicle);\n\tsteerAngle = Min(maxAngle, Max(-maxAngle, steerAngle));\n\tfloat speedMultiplier = FindSpeedMultiplier(CGeneral::GetATanOfXY(targetX - pVehicle->GetPosition().x, targetY - pVehicle->GetPosition().y) - angleForward,\n\t\tMIN_ANGLE_FOR_SPEED_LIMITING, MAX_ANGLE_FOR_SPEED_LIMITING, MIN_LOWERING_SPEED_COEFFICIENT);\n\tfloat speedTarget = pVehicle->AutoPilot.m_nCruiseSpeed * speedMultiplier;\n\tfloat currentSpeed = pVehicle->GetMoveSpeed().Magnitude() * GAME_SPEED_TO_CARAI_SPEED;\n\tfloat speedDiff = speedTarget - currentSpeed;\n\tif (speedDiff <= 0.0f){\n\t\t*pAccel = 0.0f;\n\t\t*pBrake = Min(0.5f, -speedDiff / 20.0f);\n\t}else if (currentSpeed < 25.0f){\n\t\t*pAccel = Min(1.0f, speedDiff * 0.1f);\n\t\t*pBrake = 0.0f;\n\t}else{\n\t\t*pAccel = 1.0f;\n\t\t*pBrake = 0.0f;\n\t}\n\t*pSwerve = steerAngle;\n}\n\nvoid CCarCtrl::SteerAICarWithPhysicsTryingToBlockTarget(CVehicle* pVehicle, float targetX, float targetY, float targetSpeedX, float targetSpeedY, float* pSwerve, float* pAccel, float* pBrake, bool* pHandbrake)\n{\n\tCVector2D targetPos(targetX, targetY);\n\tCVector2D offset(targetSpeedX, targetSpeedY);\n\tfloat trajectoryLen = offset.Magnitude();\n\tif (trajectoryLen > MAX_SPEED_TO_ACCOUNT_IN_INTERCEPTING)\n\t\toffset *= MAX_SPEED_TO_ACCOUNT_IN_INTERCEPTING / trajectoryLen;\n\ttargetPos += offset * GAME_SPEED_TO_CARAI_SPEED;\n\tpVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS;\n\tSteerAICarWithPhysicsHeadingForTarget(pVehicle, nil, targetPos.x, targetPos.y, pSwerve, pAccel, pBrake, pHandbrake);\n\tif ((targetPos - pVehicle->GetPosition()).MagnitudeSqr() < SQR(DISTANCE_TO_SWITCH_FROM_BLOCK_TO_STOP))\n\t\tpVehicle->AutoPilot.m_nCarMission = (pVehicle->AutoPilot.m_nCarMission == MISSION_BLOCKCAR_CLOSE) ?\n\t\t\tMISSION_BLOCKCAR_HANDBRAKESTOP : MISSION_BLOCKPLAYER_HANDBRAKESTOP;\n}\n\nvoid CCarCtrl::SteerAICarWithPhysicsTryingToBlockTarget_Stop(CVehicle* pVehicle, float targetX, float targetY, float targetSpeedX, float targetSpeedY, float* pSwerve, float* pAccel, float* pBrake, bool* pHandbrake)\n{\n\t*pSwerve = 0.0f;\n\t*pAccel = 0.0f;\n\t*pBrake = 1.0f;\n\t*pHandbrake = true;\n\tfloat distanceToTargetSqr = (CVector2D(targetX, targetY) - pVehicle->GetPosition()).MagnitudeSqr();\n\tif (distanceToTargetSqr > SQR(DISTANCE_TO_SWITCH_FROM_STOP_TO_BLOCK)){\n\t\tpVehicle->AutoPilot.m_nCarMission = (pVehicle->AutoPilot.m_nCarMission == MISSION_BLOCKCAR_HANDBRAKESTOP) ?\n\t\t\tMISSION_BLOCKCAR_CLOSE : MISSION_BLOCKPLAYER_CLOSE;\n\t\treturn;\n\t}\n\tif (pVehicle->AutoPilot.m_nCarMission == MISSION_BLOCKCAR_HANDBRAKESTOP){\n\t\tif (((CVector2D)pVehicle->GetMoveSpeed()).MagnitudeSqr() < SQR(0.01f) &&\n\t\t  CVector2D(targetSpeedX, targetSpeedY).MagnitudeSqr() < SQR(0.02f) &&\n\t\t  pVehicle->bIsLawEnforcer){\n\t\t\tCCarAI::TellOccupantsToLeaveCar(pVehicle);\n\t\t\tpVehicle->AutoPilot.m_nCruiseSpeed = 0;\n\t\t\tpVehicle->AutoPilot.m_nCarMission = MISSION_NONE;\n\t\t}\n\t}else{\n\t\tif (FindPlayerVehicle() && FindPlayerVehicle()->GetMoveSpeed().Magnitude() < 0.05f)\n#ifdef FIX_BUGS\n\t\t\tpVehicle->m_nTimeBlocked += CTimer::GetTimeStepInMilliseconds();\n#else\n\t\t\tpVehicle->m_nTimeBlocked += 1000.0f / 60.0f * CTimer::GetTimeStep(); // very doubtful constant\n#endif\n\t\telse\n\t\t\tpVehicle->m_nTimeBlocked = 0;\n\t\tif (FindPlayerVehicle() == nil || FindPlayerVehicle()->IsUpsideDown() ||\n\t\t  FindPlayerVehicle()->GetMoveSpeed().Magnitude() < 0.05f &&\n\t\t  pVehicle->m_nTimeBlocked > TIME_COPS_WAIT_TO_EXIT_AFTER_STOPPING){\n\t\t\tif (pVehicle->bIsLawEnforcer && distanceToTargetSqr < SQR(DISTANCE_TO_SWITCH_FROM_STOP_TO_BLOCK)){\n\t\t\t\tCCarAI::TellOccupantsToLeaveCar(pVehicle);\n\t\t\t\tpVehicle->AutoPilot.m_nCruiseSpeed = 0;\n\t\t\t\tpVehicle->AutoPilot.m_nCarMission = MISSION_NONE;\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nCCarCtrl::RegisterVehicleOfInterest(CVehicle* pVehicle)\n{\n\tfor (int i = 0; i < MAX_CARS_TO_KEEP; i++) {\n\t\tif (apCarsToKeep[i] == pVehicle) {\n\t\t\taCarsToKeepTime[i] = CTimer::GetTimeInMilliseconds();\n\t\t\treturn;\n\t\t}\n\t}\n\tfor (int i = 0; i < MAX_CARS_TO_KEEP; i++) {\n\t\tif (!apCarsToKeep[i]) {\n\t\t\tapCarsToKeep[i] = pVehicle;\n\t\t\taCarsToKeepTime[i] = CTimer::GetTimeInMilliseconds();\n\t\t\treturn;\n\t\t}\n\t}\n\tuint32 oldestCarWeKeepTime = UINT32_MAX;\n\tint oldestCarWeKeepIndex = 0;\n\tfor (int i = 0; i < MAX_CARS_TO_KEEP; i++) {\n\t\tif (apCarsToKeep[i] && aCarsToKeepTime[i] < oldestCarWeKeepTime) {\n\t\t\toldestCarWeKeepTime = aCarsToKeepTime[i];\n\t\t\toldestCarWeKeepIndex = i;\n\t\t}\n\t}\n\tapCarsToKeep[oldestCarWeKeepIndex] = pVehicle;\n\taCarsToKeepTime[oldestCarWeKeepIndex] = CTimer::GetTimeInMilliseconds();\n}\n\nbool\nCCarCtrl::IsThisVehicleInteresting(CVehicle* pVehicle)\n{\n\tfor (int i = 0; i < MAX_CARS_TO_KEEP; i++) {\n\t\tif (apCarsToKeep[i] == pVehicle)\n\t\t\treturn true;\n\t}\n\treturn false;\n}\n\nvoid CCarCtrl::RemoveFromInterestingVehicleList(CVehicle* pVehicle)\n{\n\tfor (int i = 0; i < MAX_CARS_TO_KEEP; i++) {\n\t\tif (apCarsToKeep[i] == pVehicle)\n\t\t\tapCarsToKeep[i] = nil;\n\t}\n}\n\nvoid CCarCtrl::ClearInterestingVehicleList()\n{\n\tfor (int i = 0; i < MAX_CARS_TO_KEEP; i++) {\n\t\tapCarsToKeep[i] = nil;\n\t}\n}\n\nvoid CCarCtrl::SwitchVehicleToRealPhysics(CVehicle* pVehicle)\n{\n\tpVehicle->AutoPilot.m_nCarMission = MISSION_CRUISE;\n\tpVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE;\n\tpVehicle->AutoPilot.m_nAntiReverseTimer = CTimer::GetTimeInMilliseconds();\n\tpVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds();\n}\n\nvoid CCarCtrl::JoinCarWithRoadSystem(CVehicle* pVehicle)\n{\n\tpVehicle->AutoPilot.m_nPrevRouteNode = pVehicle->AutoPilot.m_nCurrentRouteNode = pVehicle->AutoPilot.m_nNextRouteNode = 0;\n\tpVehicle->AutoPilot.m_nCurrentPathNodeInfo = pVehicle->AutoPilot.m_nPreviousPathNodeInfo = pVehicle->AutoPilot.m_nNextPathNodeInfo = 0;\n\tint nodeId = ThePaths.FindNodeClosestToCoorsFavourDirection(pVehicle->GetPosition(), 0, pVehicle->GetForward().x, pVehicle->GetForward().y);\n\tCPathNode* pNode = &ThePaths.m_pathNodes[nodeId];\n\tint prevNodeId = -1;\n\tfloat minDistance = 999999.9f;\n\tfor (int i = 0; i < pNode->numLinks; i++){\n\t\tint candidateId = ThePaths.ConnectedNode(i + pNode->firstLink);\n\t\tCPathNode* pCandidateNode = &ThePaths.m_pathNodes[candidateId];\n\t\tfloat distance = (pCandidateNode->GetPosition() - pNode->GetPosition()).Magnitude2D();\n\t\tif (distance < minDistance){\n\t\t\tminDistance = distance;\n\t\t\tprevNodeId = candidateId;\n\t\t}\n\t}\n\tif (prevNodeId < 0)\n\t\treturn;\n\tCVector2D forward = pVehicle->GetForward();\n\tCPathNode* pPrevNode = &ThePaths.m_pathNodes[prevNodeId];\n\tif (forward.x == 0.0f && forward.y == 0.0f)\n\t\tforward.x = 1.0f;\n\tif (DotProduct2D(pNode->GetPosition() - pPrevNode->GetPosition(), forward) < 0.0f){\n\t\tint tmp;\n\t\ttmp = prevNodeId;\n\t\tprevNodeId = nodeId;\n\t\tnodeId = tmp;\n\t}\n\tpVehicle->AutoPilot.m_nPrevRouteNode = 0;\n\tpVehicle->AutoPilot.m_nCurrentRouteNode = prevNodeId;\n\tpVehicle->AutoPilot.m_nNextRouteNode = nodeId;\n\tpVehicle->AutoPilot.m_nPathFindNodesCount = 0;\n\tFindLinksToGoWithTheseNodes(pVehicle);\n\tpVehicle->AutoPilot.m_nNextLane = pVehicle->AutoPilot.m_nCurrentLane = 0;\n}\n\nbool CCarCtrl::JoinCarWithRoadSystemGotoCoors(CVehicle* pVehicle, CVector vecTarget, bool isProperNow)\n{\n\tpVehicle->AutoPilot.m_vecDestinationCoors = vecTarget;\n\tThePaths.DoPathSearch(0, pVehicle->GetPosition(), -1, vecTarget, pVehicle->AutoPilot.m_aPathFindNodesInfo,\n\t\t&pVehicle->AutoPilot.m_nPathFindNodesCount, NUM_PATH_NODES_IN_AUTOPILOT, pVehicle, nil, 999999.9f, -1);\n\tThePaths.RemoveBadStartNode(pVehicle->GetPosition(),\n\t\tpVehicle->AutoPilot.m_aPathFindNodesInfo, &pVehicle->AutoPilot.m_nPathFindNodesCount);\n\tif (pVehicle->AutoPilot.m_nPathFindNodesCount < 2){\n\t\tpVehicle->AutoPilot.m_nPrevRouteNode = pVehicle->AutoPilot.m_nCurrentRouteNode = pVehicle->AutoPilot.m_nNextRouteNode = 0;\n\t\tpVehicle->AutoPilot.m_nPathFindNodesCount = 0;\n\t\treturn true;\n\t}\n\tpVehicle->AutoPilot.m_nPrevRouteNode = 0;\n\tpVehicle->AutoPilot.m_nCurrentRouteNode = pVehicle->AutoPilot.m_aPathFindNodesInfo[0] - ThePaths.m_pathNodes;\n\tpVehicle->AutoPilot.RemoveOnePathNode();\n\tpVehicle->AutoPilot.m_nNextRouteNode = pVehicle->AutoPilot.m_aPathFindNodesInfo[0] - ThePaths.m_pathNodes;\n\tpVehicle->AutoPilot.RemoveOnePathNode();\n\tFindLinksToGoWithTheseNodes(pVehicle);\n\tpVehicle->AutoPilot.m_nNextLane = pVehicle->AutoPilot.m_nCurrentLane = 0;\n\treturn false;\n}\n\nvoid CCarCtrl::FindLinksToGoWithTheseNodes(CVehicle* pVehicle)\n{\n\tif (pVehicle->m_nRouteSeed)\n\t\tCGeneral::SetRandomSeed(pVehicle->m_nRouteSeed);\n\tint nextLink;\n\tCPathNode* pCurNode = &ThePaths.m_pathNodes[pVehicle->AutoPilot.m_nCurrentRouteNode];\n\tfor (nextLink = 0; nextLink < 12; nextLink++)\n\t\tif (ThePaths.ConnectedNode(nextLink + pCurNode->firstLink) == pVehicle->AutoPilot.m_nNextRouteNode)\n\t\t\tbreak;\n\tpVehicle->AutoPilot.m_nNextPathNodeInfo = ThePaths.m_carPathConnections[nextLink + pCurNode->firstLink];\n\tpVehicle->AutoPilot.m_nNextDirection = (pVehicle->AutoPilot.m_nCurrentRouteNode >= pVehicle->AutoPilot.m_nNextRouteNode) ? 1 : -1;\n\tint curLink;\n\tint curConnection;\n\tif (pCurNode->numLinks == 1) {\n\t\tcurLink = 0;\n\t\tcurConnection = ThePaths.m_carPathConnections[pCurNode->firstLink];\n\t}else{\n\t\tint closestLink = -1;\n\t\tfloat md = 999999.9f;\n\n\t\tfor (curLink = 0; curLink < pCurNode->numLinks; curLink++) {\n\t\t\tint node = ThePaths.ConnectedNode(curLink + pCurNode->firstLink);\n\t\t\tCPathNode* pNode = &ThePaths.m_pathNodes[node];\n\t\t\tif (node == pVehicle->AutoPilot.m_nNextRouteNode)\n\t\t\t\tcontinue;\n\t\t\tCVector vCurPos = pCurNode->GetPosition();\n\t\t\tCVector vNextPos = pNode->GetPosition();\n\t\t\tfloat dist = CCollision::DistToLine(&vCurPos, &vNextPos, &pVehicle->GetPosition());\n\t\t\tif (dist < md) {\n\t\t\t\tmd = dist;\n\t\t\t\tclosestLink = curLink;\n\t\t\t}\n\t\t}\n\t\tcurConnection = ThePaths.m_carPathConnections[closestLink + pCurNode->firstLink];\n\t}\n\tpVehicle->AutoPilot.m_nCurrentPathNodeInfo = curConnection;\n\tpVehicle->AutoPilot.m_nCurrentDirection = (ThePaths.ConnectedNode(curLink + pCurNode->firstLink) >= pVehicle->AutoPilot.m_nCurrentRouteNode) ? 1 : -1;\n}\n\nvoid CCarCtrl::GenerateEmergencyServicesCar(void)\n{\n\tif (FindPlayerPed()->m_pWanted->GetWantedLevel() > 3)\n\t\treturn;\n\tif (CGame::IsInInterior())\n\t\treturn;\n\tif (NumFiretrucksOnDuty + NumAmbulancesOnDuty + NumParkedCars + NumMissionCars +\n\t\tNumLawEnforcerCars + NumRandomCars > MaxNumberOfCarsInUse)\n\t\treturn;\n\tif (NumAmbulancesOnDuty == 0){\n\t\tif (gAccidentManager.CountActiveAccidents() < 2){\n\t\t\tif (CStreaming::HasModelLoaded(MI_AMBULAN))\n\t\t\t\tCStreaming::SetModelIsDeletable(MI_MEDIC);\n\t\t}else{\n\t\t\tfloat distance = 30.0f;\n\t\t\tCAccident* pNearestAccident = gAccidentManager.FindNearestAccident(FindPlayerCoors(), &distance);\n\t\t\tif (pNearestAccident){\n\t\t\t\tif (CountCarsOfType(MI_AMBULAN) < 2 && CTimer::GetTimeInMilliseconds() > LastTimeAmbulanceCreated + 30000){\n\t\t\t\t\tCStreaming::RequestModel(MI_AMBULAN, STREAMFLAGS_DEPENDENCY);\n\t\t\t\t\tCStreaming::RequestModel(MI_MEDIC, STREAMFLAGS_DONT_REMOVE);\n\t\t\t\t\tif (CStreaming::HasModelLoaded(MI_AMBULAN) && CStreaming::HasModelLoaded(MI_MEDIC)){\n\t\t\t\t\t\tif (GenerateOneEmergencyServicesCar(MI_AMBULAN, pNearestAccident->m_pVictim->GetPosition())){\n\t\t\t\t\t\t\tLastTimeAmbulanceCreated = CTimer::GetTimeInMilliseconds();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tif (NumFiretrucksOnDuty == 0){\n\t\tif (gFireManager.GetTotalActiveFires() < 3){\n\t\t\tif (CStreaming::HasModelLoaded(MI_FIRETRUCK))\n\t\t\t\tCStreaming::SetModelIsDeletable(MI_FIREMAN);\n\t\t}else{\n\t\t\tfloat distance = 30.0f;\n\t\t\tCFire* pNearestFire = gFireManager.FindNearestFire(FindPlayerCoors(), &distance);\n\t\t\tif (pNearestFire) {\n\t\t\t\tif (CountCarsOfType(MI_FIRETRUCK) < 2 && CTimer::GetTimeInMilliseconds() > LastTimeFireTruckCreated + 35000){\n\t\t\t\t\tCStreaming::RequestModel(MI_FIRETRUCK, STREAMFLAGS_DEPENDENCY);\n\t\t\t\t\tCStreaming::RequestModel(MI_FIREMAN, STREAMFLAGS_DONT_REMOVE);\n\t\t\t\t\tif (CStreaming::HasModelLoaded(MI_FIRETRUCK) && CStreaming::HasModelLoaded(MI_FIREMAN)){\n\t\t\t\t\t\tif (GenerateOneEmergencyServicesCar(MI_FIRETRUCK, pNearestFire->m_vecPos)){\n\t\t\t\t\t\t\tLastTimeFireTruckCreated = CTimer::GetTimeInMilliseconds();\n#ifdef SECUROM\n\t\t\t\t\t\t\tif ((myrand() & 7) == 5){\n\t\t\t\t\t\t\t\t// if pirated game\n\t\t\t\t\t\t\t\tCPickups::Init();\n\t\t\t\t\t\t\t}\n#endif\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nbool CCarCtrl::GenerateOneEmergencyServicesCar(uint32 mi, CVector vecPos)\n{\n\tCVector pPlayerPos = FindPlayerCentreOfWorld(CWorld::PlayerInFocus);\n\tbool created = false;\n\tint attempts = 0;\n\tCVector spawnPos;\n\tint curNode, nextNode;\n\tfloat posBetweenNodes;\n\twhile (!created && attempts < 5){\n\t\tif (ThePaths.GenerateCarCreationCoors(pPlayerPos.x, pPlayerPos.y, 0.707f, 0.707f,\n\t\t\tREQUEST_ONSCREEN_DISTANCE, -1.0f, true, &spawnPos, &curNode, &nextNode, &posBetweenNodes, false)){\n\t\t\tint16 colliding[2];\n\t\t\tif (!ThePaths.GetNode(curNode)->bWaterPath) {\n\t\t\t\tCWorld::FindObjectsKindaColliding(spawnPos, 10.0f, true, colliding, 2, nil, false, true, true, false, false);\n\t\t\t\tif (colliding[0] == 0)\n\t\t\t\t\tcreated = true;\n\t\t\t}\n\t\t}\n\t\tattempts += 1;\n\t}\n\tif (attempts >= 5)\n\t\treturn false;\n\tCAutomobile* pVehicle = new CAutomobile(mi, RANDOM_VEHICLE);\n\tpVehicle->AutoPilot.m_vecDestinationCoors = vecPos;\n\tpVehicle->SetPosition(spawnPos);\n\tpVehicle->AutoPilot.m_nCarMission = (JoinCarWithRoadSystemGotoCoors(pVehicle, vecPos, false)) ? MISSION_GOTOCOORDS_STRAIGHT : MISSION_GOTOCOORDS;\n\tpVehicle->AutoPilot.m_fMaxTrafficSpeed = pVehicle->AutoPilot.m_nCruiseSpeed = 25;\n\tpVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE;\n\tpVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS;\n\tCVector2D direction = vecPos - spawnPos;\n\tdirection.Normalise();\n\tpVehicle->GetForward() = CVector(direction.x, direction.y, 0.0f);\n\tpVehicle->GetRight() = CVector(direction.y, -direction.x, 0.0f);\n\tpVehicle->GetUp() = CVector(0.0f, 0.0f, 1.0f);\n\tspawnPos.z = posBetweenNodes * ThePaths.m_pathNodes[curNode].GetZ() + (1.0f - posBetweenNodes) * ThePaths.m_pathNodes[nextNode].GetZ();\n\tfloat groundZ = INFINITE_Z;\n\tCColPoint colPoint;\n\tCEntity* pEntity;\n\tif (CWorld::ProcessVerticalLine(spawnPos, 1000.0f, colPoint, pEntity, true, false, false, false, true, false, nil))\n\t\tgroundZ = colPoint.point.z;\n\tif (CWorld::ProcessVerticalLine(spawnPos, -1000.0f, colPoint, pEntity, true, false, false, false, true, false, nil)) {\n\t\tif (ABS(colPoint.point.z - spawnPos.z) < ABS(groundZ - spawnPos.z))\n\t\t\tgroundZ = colPoint.point.z;\n\t}\n\tif (groundZ == INFINITE_Z) {\n\t\tdelete pVehicle;\n\t\treturn false;\n\t}\n\tspawnPos.z = groundZ + pVehicle->GetDistanceFromCentreOfMassToBaseOfModel();\n\tpVehicle->SetPosition(spawnPos);\n\tpVehicle->SetMoveSpeed(CVector(0.0f, 0.0f, 0.0f));\n\tpVehicle->SetStatus(STATUS_PHYSICS);\n\tswitch (mi){\n\tcase MI_FIRETRUCK:\n\t\tpVehicle->bIsFireTruckOnDuty = true;\n\t\t++NumFiretrucksOnDuty;\n\t\tCCarAI::AddFiretruckOccupants(pVehicle);\n\t\tbreak;\n\tcase MI_AMBULAN:\n\t\tpVehicle->bIsAmbulanceOnDuty = true;\n\t\t++NumAmbulancesOnDuty;\n\t\tCCarAI::AddAmbulanceOccupants(pVehicle);\n\t\tbreak;\n\t}\n\tpVehicle->m_bSirenOrAlarm = true;\n\tCWorld::Add(pVehicle);\n\tprintf(\"CREATED EMERGENCY VEHICLE\\n\");\n\treturn true;\n}\n\nvoid CCarCtrl::UpdateCarCount(CVehicle* pVehicle, bool remove)\n{\n\tif (remove){\n\t\tswitch (pVehicle->VehicleCreatedBy){\n\t\tcase RANDOM_VEHICLE:\n\t\t\tif (pVehicle->bIsLawEnforcer) {\n\t\t\t\tif (--NumLawEnforcerCars < 0)\n\t\t\t\t\tNumLawEnforcerCars = 0;\n\t\t\t}\n\t\t\tif (--NumRandomCars < 0)\n\t\t\t\tNumRandomCars = 0;\n\t\t\treturn;\n\t\tcase MISSION_VEHICLE:\n\t\t\tif (--NumMissionCars < 0)\n\t\t\t\tNumMissionCars = 0;\n\t\t\treturn;\n\t\tcase PARKED_VEHICLE:\n\t\t\tif (--NumParkedCars < 0)\n\t\t\t\tNumParkedCars = 0;\n\t\t\treturn;\n\t\tcase PERMANENT_VEHICLE:\n\t\t\tif (--NumPermanentCars < 0)\n\t\t\t\tNumPermanentCars = 0;\n\t\t\treturn;\n\t\t}\n\t}\n\telse{\n\t\tswitch (pVehicle->VehicleCreatedBy){\n\t\tcase RANDOM_VEHICLE:\n\t\t\tif (pVehicle->bIsLawEnforcer)\n\t\t\t\t++NumLawEnforcerCars;\n\t\t\t++NumRandomCars;\n\t\t\treturn;\n\t\tcase MISSION_VEHICLE:\n\t\t\t++NumMissionCars;\n\t\t\treturn;\n\t\tcase PARKED_VEHICLE:\n\t\t\t++NumParkedCars;\n\t\t\treturn;\n\t\tcase PERMANENT_VEHICLE:\n\t\t\t++NumPermanentCars;\n\t\t\treturn;\n\t\t}\n\t}\n}\n\nbool CCarCtrl::ThisRoadObjectCouldMove(int16 mi)\n{\n#ifdef GTA_BRIDGE\n\treturn mi == MI_BRIDGELIFT || mi == MI_BRIDGEROADSEGMENT;\n#else\n\treturn false;\n#endif\n}\n\nbool CCarCtrl::MapCouldMoveInThisArea(float x, float y)\n{\n#ifdef GTA_BRIDGE\t// actually they forgot that in VC...\n\t// bridge moves up and down\n\treturn x > -342.0f && x < -219.0f &&\n\t\ty > -677.0f && y < -580.0f;\n#else\n\treturn false;\n#endif\n}\n\nfloat CCarCtrl::FindSpeedMultiplierWithSpeedFromNodes(int8 type)\n{\n\tswitch (type)\n\t{\n\tcase 1: return 1.5f;\n\tcase 2: return 2.0f;\n\t}\n\treturn 1.0f;\n}\n"
  },
  {
    "path": "src/control/CarCtrl.h",
    "content": "#pragma once\n#include \"PathFind.h\"\n#include \"Boat.h\"\n#include \"Vehicle.h\"\n\n#define GAME_SPEED_TO_METERS_PER_SECOND 50.0f\n#define METERS_PER_SECOND_TO_GAME_SPEED (1.0f / GAME_SPEED_TO_METERS_PER_SECOND)\n#define GAME_SPEED_TO_CARAI_SPEED 60.0f\n#define TIME_COPS_WAIT_TO_EXIT_AFTER_STOPPING 2500\n\nclass CZoneInfo;\nclass CAutomobile;\n\nenum{\n\tMAX_CARS_TO_KEEP = 2,\n\tMAX_CAR_MODELS_IN_ARRAY = 25,\n};\n\n#ifdef FIX_BUGS\n#define FIX_PATHFIND_BUG\n#endif\n\nclass CCarCtrl\n{\npublic:\n\tenum eCarClass {\n\t\tNORMAL = 0,\n\t\tPOOR,\n\t\tRICH,\n\t\tEXEC,\n\t\tWORKER,\n\t\tBIG,\n\t\tTAXI,\n\t\tMOPED,\n\t\tMOTORBIKE,\n\n\t\tLEISUREBOAT,\n\t\tWORKERBOAT,\n\n\t\tCOPS,\n\t\tCUBAN,\n\t\tHAITIAN,\n\t\tSTREET,\n\t\tDIAZ,\n\t\tBIKER,\n\t\tSECURITY,\n\t\tPLAYER,\n\t\tGOLFERS,\n\t\tGANG9,\n\t\tCOPS_BOAT,\n\t\tFIRST_CAR_RATING = NORMAL,\n\t\tFIRST_BOAT_RATING = LEISUREBOAT,\n\t\tFIRST_GANG_CAR_RATING = CUBAN,\n\t\tNUM_CAR_CLASSES = MOTORBIKE - FIRST_CAR_RATING + 1,\n\t\tNUM_BOAT_CLASSES = WORKERBOAT - FIRST_BOAT_RATING + 1,\n\t\tNUM_GANG_CAR_CLASSES = GANG9 - FIRST_GANG_CAR_RATING + 1,\n\t\tTOTAL_CUSTOM_CLASSES = NUM_CAR_CLASSES + NUM_BOAT_CLASSES\n\t};\n\n\tstatic void SwitchVehicleToRealPhysics(CVehicle*);\n\tstatic void AddToCarArray(int32 id, int32 vehclass);\n\tstatic void UpdateCarCount(CVehicle*, bool);\n\tstatic int32 ChooseCarModel(int32 vehclass);\n\tstatic bool JoinCarWithRoadSystemGotoCoors(CVehicle*, CVector, bool);\n\tstatic void JoinCarWithRoadSystem(CVehicle*);\n\tstatic void UpdateCarOnRails(CVehicle*);\n\tstatic bool MapCouldMoveInThisArea(float x, float y);\n\tstatic void ScanForPedDanger(CVehicle *veh);\n\tstatic void RemoveFromInterestingVehicleList(CVehicle*);\n\tstatic void GenerateRandomCars(void);\n\tstatic void GenerateOneRandomCar(void);\n\tstatic void GenerateEmergencyServicesCar(void);\n\tstatic int32 ChooseModel(CZoneInfo*, int*);\n\tstatic int32 ChoosePoliceCarModel(void);\n\tstatic int32 ChooseGangCarModel(int32 gang);\n\tstatic void RemoveDistantCars(void);\n\tstatic void PossiblyRemoveVehicle(CVehicle*);\n\tstatic bool IsThisVehicleInteresting(CVehicle*);\n\tstatic void RegisterVehicleOfInterest(CVehicle*);\n\tstatic int32 CountCarsOfType(int32 mi);\n\tstatic void SlowCarOnRailsDownForTrafficAndLights(CVehicle*);\n\tstatic bool PickNextNodeAccordingStrategy(CVehicle*);\n\tstatic void DragCarToPoint(CVehicle*, CVector*);\n\tstatic float FindMaximumSpeedForThisCarInTraffic(CVehicle*);\n\tstatic void SlowCarDownForCarsSectorList(CPtrList&, CVehicle*, float, float, float, float, float*, float);\n\tstatic void SlowCarDownForPedsSectorList(CPtrList&, CVehicle*, float, float, float, float, float*, float);\n\tstatic void SlowCarDownForOtherCar(CEntity*, CVehicle*, float*, float);\n\tstatic float TestCollisionBetween2MovingRects(CVehicle*, CVehicle*, float, float, CVector*, CVector*, uint8);\n\tstatic float FindAngleToWeaveThroughTraffic(CVehicle*, CPhysical*, float, float);\n\tstatic void WeaveThroughCarsSectorList(CPtrList&, CVehicle*, CPhysical*, float, float, float, float, float*, float*);\n\tstatic void WeaveForOtherCar(CEntity*, CVehicle*, float*, float*);\n\tstatic void WeaveThroughPedsSectorList(CPtrList&, CVehicle*, CPhysical*, float, float, float, float, float*, float*);\n\tstatic void WeaveForPed(CEntity*, CVehicle*, float*, float*);\n\tstatic void WeaveThroughObjectsSectorList(CPtrList&, CVehicle*, float, float, float, float, float*, float*);\n\tstatic void WeaveForObject(CEntity*, CVehicle*, float*, float*);\n#ifdef FIX_PATHFIND_BUG\n\tstatic void PickNextNodeToChaseCar(CVehicle*, float, float, float, CVehicle*);\n#else\n\tstatic void PickNextNodeToChaseCar(CVehicle*, float, float, CVehicle*);\n#endif\n\tstatic bool PickNextNodeToFollowPath(CVehicle*);\n\tstatic void PickNextNodeRandomly(CVehicle*);\n\tstatic uint8 FindPathDirection(int32, int32, int32);\n\tstatic void Init(void);\n\tstatic void ReInit(void);\n\tstatic float FindSpeedMultiplier(float, float, float, float);\n\tstatic void SteerAICarWithPhysics(CVehicle*);\n\tstatic void SteerAICarWithPhysics_OnlyMission(CVehicle*, float*, float*, float*, bool*);\n\tstatic float FindMaxSteerAngle(CVehicle*);\n\tstatic void SteerAICarWithPhysicsFollowPath(CVehicle*, float*, float*, float*, bool*);\n\tstatic void SteerAICarWithPhysicsHeadingForTarget(CVehicle*, CPhysical*, float, float, float*, float*, float*, bool*);\n\tstatic void SteerAICarWithPhysicsTryingToBlockTarget(CVehicle*, float, float, float, float, float*, float*, float*, bool*);\n\tstatic void SteerAICarWithPhysicsTryingToBlockTarget_Stop(CVehicle*, float, float, float, float, float*, float*, float*, bool*);\n\tstatic bool ThisRoadObjectCouldMove(int16);\n\tstatic void ClearInterestingVehicleList();\n\tstatic void FindLinksToGoWithTheseNodes(CVehicle*);\n\tstatic bool GenerateOneEmergencyServicesCar(uint32, CVector);\n\tstatic float FindSpeedMultiplierWithSpeedFromNodes(int8);\n\tstatic int32 ChooseBoatModel(int32);\n\tstatic int32 ChooseBoatRating(CZoneInfo* pZoneInfo);\n\tstatic int32 ChooseCarRating(CZoneInfo* pZoneInfo);\n\tstatic void AddToLoadedVehicleArray(int32 mi, int32 rating, int32 freq);\n\tstatic void RemoveFromLoadedVehicleArray(int32 mi, int32 rating);\n\tstatic int32 ChooseCarModelToLoad(int32 rating);\n\tstatic bool BoatWithTallMast(int32 mi);\n\tstatic void RemoveCarsIfThePoolGetsFull(void);\n\tstatic void SteerAIBoatWithPhysicsHeadingForTarget(CVehicle*, float, float, float*, float*, float*);\n\tstatic void SteerAIHeliTowardsTargetCoors(CAutomobile*);\n\tstatic void SteerAIPlaneTowardsTargetCoors(CAutomobile*);\n\tstatic void SteerAIBoatWithPhysicsAttackingPlayer(CVehicle*, float*, float*, float*, bool*);\n\tstatic void SteerAICarBlockingPlayerForwardAndBack(CVehicle*, float*, float*, float*, bool*);\n\n\tstatic float GetPositionAlongCurrentCurve(CVehicle* pVehicle)\n\t{\n\t\tuint32 timeInCurve = CTimer::GetTimeInMilliseconds() - pVehicle->AutoPilot.m_nTimeEnteredCurve;\n\t\treturn (float)timeInCurve / pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve;\n\t}\n\n\tstatic float LimitRadianAngle(float angle)\n\t{\n\t\twhile (angle < -PI)\n\t\t\tangle += TWOPI;\n\t\twhile (angle > PI)\n\t\t\tangle -= TWOPI;\n\t\treturn angle;\n\t}\n\n\tstatic bool bMadDriversCheat;\n\tstatic int32 NumLawEnforcerCars;\n\tstatic int32 NumAmbulancesOnDuty;\n\tstatic int32 NumFiretrucksOnDuty;\n\tstatic int32 NumRandomCars;\n\tstatic int32 NumMissionCars;\n\tstatic int32 NumParkedCars;\n\tstatic int32 NumPermanentCars;\n\tstatic bool bCarsGeneratedAroundCamera;\n\tstatic float CarDensityMultiplier;\n\tstatic int8 CountDownToCarsAtStart;\n\tstatic int32 MaxNumberOfCarsInUse;\n\tstatic uint32 LastTimeLawEnforcerCreated;\n\tstatic uint32 LastTimeFireTruckCreated;\n\tstatic uint32 LastTimeAmbulanceCreated;\n\tstatic int32 TotalNumOfCarsOfRating[TOTAL_CUSTOM_CLASSES];\n\tstatic int32 CarArrays[TOTAL_CUSTOM_CLASSES][MAX_CAR_MODELS_IN_ARRAY];\n\n\tstatic int32 MiamiViceCycle;\n\tstatic uint32 LastTimeMiamiViceGenerated;\n\tstatic int32 NumRequestsOfCarRating[TOTAL_CUSTOM_CLASSES];\n\tstatic int32 NumOfLoadedCarsOfRating[TOTAL_CUSTOM_CLASSES];\n\tstatic int32 CarFreqArrays[TOTAL_CUSTOM_CLASSES][MAX_CAR_MODELS_IN_ARRAY];\n\tstatic int32 LoadedCarsArray[TOTAL_CUSTOM_CLASSES][MAX_CAR_MODELS_IN_ARRAY];\n};\n\nextern CVehicle* apCarsToKeep[MAX_CARS_TO_KEEP];"
  },
  {
    "path": "src/control/Curves.cpp",
    "content": "#include \"common.h\"\n\n#include \"Curves.h\"\n\nfloat CCurves::CalcSpeedScaleFactor(CVector* pPoint1, CVector* pPoint2, float dir1X, float dir1Y, float dir2X, float dir2Y)\n{\n\tCVector2D dir1(dir1X, dir1Y);\n\tCVector2D dir2(dir2X, dir2Y);\n\tfloat distance = (*pPoint1 - *pPoint2).Magnitude2D();\n\tfloat dp = DotProduct2D(dir1, dir2);\n\tif (dp > 0.9f)\n\t\treturn distance + Abs((pPoint1->x * dir1Y - pPoint1->y * dir1X) - (pPoint2->x * dir1Y - pPoint2->y * dir1X));\n\telse\n\t\treturn ((1.0f - dp) * 0.25f + 1.0f) * distance;\n}\n\nvoid CCurves::CalcCurvePoint(CVector* pPos1, CVector* pPos2, CVector* pDir1, CVector* pDir2, float between, int32 timeOnCurve, CVector* pOutPos, CVector* pOutDir)\n{\n\tfloat actualFactor = CalcSpeedScaleFactor(pPos1, pPos2, pDir1->x, pDir1->y, pDir2->x, pDir2->y);\n\tCVector2D dir1 = *pDir1 * actualFactor;\n\tCVector2D dir2 = *pDir2 * actualFactor;\n\tfloat t1 = Abs(DotProduct2D(*pPos1 - *pPos2, *pDir1));\n\tfloat t2 = Abs(DotProduct2D(*pPos2 - *pPos1, *pDir2));\n\tfloat curveCoef;\n\tif (t1 > t2) {\n\t\tif (between < (t1 - t2) / (t1 + t2))\n\t\t\tcurveCoef = 0.0f;\n\t\telse\n\t\t\tcurveCoef = 0.5f - 0.5f * Cos(3.1415f * (t1 + t2) / (2 * t2) * (between - (t1 - t2) / (t1 + t2)));\n\t}\n\telse {\n\t\tif (2 * t1 / (t1 + t2) < between)\n\t\t\tcurveCoef = 1.0f;\n\t\telse\n\t\t\tcurveCoef = 0.5f - 0.5f * Cos(3.1415f * between * (t1 + t2) / (2 * t1));\n\t}\n\t*pOutPos = CVector(\n\t\t(pPos1->x + between * dir1.x) * (1.0f - curveCoef) + (pPos2->x - (1 - between) * dir2.x) * curveCoef,\n\t\t(pPos1->y + between * dir1.y) * (1.0f - curveCoef) + (pPos2->y - (1 - between) * dir2.y) * curveCoef,\n\t\t0.0f);\n\t*pOutDir = CVector(\n\t\t(dir1.x * (1.0f - curveCoef) + dir2.x * curveCoef) / (timeOnCurve * 0.001f),\n\t\t(dir1.y * (1.0f - curveCoef) + dir2.y * curveCoef) / (timeOnCurve * 0.001f),\n\t\t0.0f);\n}"
  },
  {
    "path": "src/control/Curves.h",
    "content": "#pragma once\nclass CVector;\n\nclass CCurves\n{\npublic:\n\tstatic float CalcSpeedScaleFactor(CVector*, CVector*, float, float, float, float);\n\tstatic void CalcCurvePoint(CVector*, CVector*, CVector*, CVector*, float, int32, CVector*, CVector*);\n};\n"
  },
  {
    "path": "src/control/Darkel.cpp",
    "content": "#include \"common.h\"\n\n#include \"main.h\"\n#include \"Darkel.h\"\n#include \"PlayerPed.h\"\n#include \"Wanted.h\"\n#include \"Timer.h\"\n#include \"DMAudio.h\"\n#include \"Population.h\"\n#include \"Replay.h\"\n#include \"Weapon.h\"\n#include \"World.h\"\n#include \"Stats.h\"\n#include \"Font.h\"\n#include \"Text.h\"\n#include \"Vehicle.h\"\n#include \"GameLogic.h\"\n\n#define FRENZY_ANY_PED -1\n#define FRENZY_ANY_CAR -2\n\nint32 CDarkel::TimeLimit;\nint32 CDarkel::PreviousTime;\nint32 CDarkel::TimeOfFrenzyStart;\nint32 CDarkel::WeaponType;\nint32 CDarkel::AmmoInterruptedWeapon;\nint32 CDarkel::KillsNeeded;\nint32 CDarkel::InterruptedWeaponType;\nint32 CDarkel::InterruptedWeaponSelected;\n\n/*\n * TODO: Collect timer/kill counter RGBA colors on top like in Hud/Frontend.\n * bStandardSoundAndMessages is a completely beta thing,\n * makes game handle sounds & messages instead of SCM (just like in GTA2)\n * but it's never been used in the game. Has unused sliding text when frenzy completed etc.\n */\nbool CDarkel::bStandardSoundAndMessages;\nbool CDarkel::bNeedHeadShot;\nbool CDarkel::bProperKillFrenzy;\nuint16 CDarkel::Status;\nuint16 CDarkel::RegisteredKills[NUM_DEFAULT_MODELS];\nint32 CDarkel::ModelToKill;\nint32 CDarkel::ModelToKill2;\nint32 CDarkel::ModelToKill3;\nint32 CDarkel::ModelToKill4;\nwchar *CDarkel::pStartMessage;\n\nuint8\nCDarkel::CalcFade(uint32 time, uint32 start, uint32 end)\n{\n\tif (time >= start && time <= end) {\n\t\tif (time >= start + 500) {\n\t\t\tif (time <= end - 500)\n\t\t\t\treturn 255;\n\t\t\telse\n\t\t\t\treturn 255 * (end - time) / 500;\n\t\t} else\n\t\t\treturn 255 * (time - start) / 500;\n\t} else\n\t\treturn 0;\n}\n\nvoid\nCDarkel::DrawMessages()\n{\n\tif (CReplay::IsPlayingBack())\n\t\treturn;\n\n\tswitch (Status) {\n\t\tcase KILLFRENZY_ONGOING:\n\t\t{\n\t\t\tCFont::SetJustifyOff();\n\t\t\tCFont::SetBackgroundOff();\n#ifdef FIX_BUGS\n\t\t\tCFont::SetCentreSize(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH - 30));\n#else\n\t\t\tCFont::SetCentreSize(SCREEN_WIDTH - 30);\n#endif\n\t\t\tCFont::SetCentreOn();\n\t\t\tCFont::SetPropOn();\n\t\t\tuint32 timePassedSinceStart = CTimer::GetTimeInMilliseconds() - TimeOfFrenzyStart;\n\t\t\tif (bStandardSoundAndMessages) {\n\t\t\t\tif (timePassedSinceStart >= 3000 && timePassedSinceStart < 11000) {\n#ifdef FIX_BUGS\n\t\t\t\t\tCFont::SetScale(SCREEN_SCALE_X(1.3f), SCREEN_SCALE_Y(1.3f));\n#else\n\t\t\t\t\tCFont::SetScale(1.3f, 1.3f);\n#endif\n\t\t\t\t\tCFont::SetJustifyOff();\n\t\t\t\t\tCFont::SetColor(CRGBA(255, 255, 128, CalcFade(timePassedSinceStart, 3000, 11000)));\n\t\t\t\t\tCFont::SetFontStyle(FONT_STANDARD);\n\t\t\t\t\tif (pStartMessage) {\n\t\t\t\t\t\tCFont::PrintString(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, pStartMessage);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (timePassedSinceStart < 8000) {\n#ifdef FIX_BUGS\n\t\t\t\t\tCFont::SetScale(SCREEN_SCALE_X(1.3f), SCREEN_SCALE_Y(1.3f));\n#else\n\t\t\t\t\tCFont::SetScale(1.3f, 1.3f);\n#endif\n\t\t\t\t\tCFont::SetJustifyOff();\n\t\t\t\t\tCFont::SetColor(CRGBA(255, 255, 128, CalcFade(timePassedSinceStart, 0, 8000)));\n\t\t\t\t\tCFont::SetFontStyle(FONT_STANDARD);\n\t\t\t\t\tif (pStartMessage) {\n\t\t\t\t\t\tCFont::PrintString(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, pStartMessage);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n#ifdef FIX_BUGS\n\t\t\tCFont::SetScale(SCREEN_SCALE_X(0.75f), SCREEN_SCALE_Y(1.5f));\n#else\n\t\t\tCFont::SetScale(0.75f, 1.5f);\n#endif\n\t\t\tCFont::SetCentreOff();\n\t\t\tCFont::SetRightJustifyOn();\n\t\t\tCFont::SetFontStyle(FONT_HEADING);\n\t\t\tif (TimeLimit >= 0) {\n\t\t\t\tuint32 timeLeft = TimeLimit - (CTimer::GetTimeInMilliseconds() - TimeOfFrenzyStart);\n\t\t\t\tsprintf(gString, \"%d:%02d\", timeLeft / 60000, timeLeft % 60000 / 1000);\n\t\t\t\tAsciiToUnicode(gString, gUString);\n\t\t\t\tif (timeLeft > 4000 || CTimer::GetFrameCounter() & 1) {\n\t\t\t\t\tCFont::SetColor(CRGBA(0, 0, 0, 255));\n\t\t\t\t\tCFont::PrintString(SCREEN_SCALE_FROM_RIGHT(35.0f), SCREEN_SCALE_Y(109.0f), gUString);\n\t\t\t\t\tCFont::SetColor(CRGBA(0, 207, 133, 255));\n\t\t\t\t\tCFont::PrintString(SCREEN_SCALE_FROM_RIGHT(34.0f), SCREEN_SCALE_Y(108.0f), gUString);\n\t\t\t\t}\n\t\t\t}\n\t\t\tsprintf(gString, \"%d\", (KillsNeeded >= 0 ? KillsNeeded : 0));\n\t\t\tAsciiToUnicode(gString, gUString);\n\t\t\tCFont::SetColor(CRGBA(0, 0, 0, 255));\n\t\t\tCFont::PrintString(SCREEN_SCALE_FROM_RIGHT(35.0f), SCREEN_SCALE_Y(144.0f), gUString);\n\t\t\tCFont::SetColor(CRGBA(156, 91, 40, 255));\n\t\t\tCFont::PrintString(SCREEN_SCALE_FROM_RIGHT(34.0f), SCREEN_SCALE_Y(143.0f), gUString);\n\t\t\tbreak;\n\t\t}\n\t\tcase KILLFRENZY_PASSED:\n\t\t{\n\t\t\tif (bStandardSoundAndMessages) {\n\t\t\t\tuint32 timePassedSinceStart = CTimer::GetTimeInMilliseconds() - TimeOfFrenzyStart;\n\t\t\t\tif (CTimer::GetTimeInMilliseconds() - TimeOfFrenzyStart < 5000) {\n\t\t\t\t\tCFont::SetBackgroundOff();\n#ifdef FIX_BUGS\n\t\t\t\t\tCFont::SetCentreSize(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH - 20));\n#else\n\t\t\t\t\tCFont::SetCentreSize(SCREEN_WIDTH - 20);\n#endif\n\t\t\t\t\tCFont::SetCentreOn();\n#ifdef FIX_BUGS\n\t\t\t\t\tCFont::SetScale(SCREEN_SCALE_X(1.5f), SCREEN_SCALE_Y(1.5f));\n#else\n\t\t\t\t\tCFont::SetScale(1.5f, 1.5f);\n#endif\n\t\t\t\t\tCFont::SetJustifyOff();\n\t\t\t\t\tCFont::SetColor(CRGBA(128, 255, 128, CalcFade(timePassedSinceStart, 0, 5000)));\n\t\t\t\t\tCFont::SetFontStyle(FONT_STANDARD);\n#ifdef FIX_BUGS\n\t\t\t\t\tint y = SCREEN_HEIGHT / 2 + SCREEN_SCALE_Y(25.0f - timePassedSinceStart * 0.01f);\n#else\n\t\t\t\t\tint y = (SCREEN_HEIGHT / 2 + 25) - (timePassedSinceStart * 0.01f);\n#endif\n\t\t\t\t\tCFont::PrintString(SCREEN_WIDTH / 2, y, TheText.Get(\"KF_3\"));\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tdefault:\n\t\t\tbreak;\n\t}\n}\n\nvoid\nCDarkel::Init()\n{\n\tStatus = KILLFRENZY_NONE;\n}\n\nuint16\nCDarkel::QueryModelsKilledByPlayer(int32 modelId)\n{\n\treturn RegisteredKills[modelId];\n}\n\n\nbool\nCDarkel::FrenzyOnGoing()\n{\n\treturn Status == KILLFRENZY_ONGOING;\n}\n\n\nuint16\nCDarkel::ReadStatus()\n{\n\treturn Status;\n}\n\nvoid\nCDarkel::RegisterCarBlownUpByPlayer(CVehicle *vehicle)\n{\n#ifdef FIX_BUGS\n\tif (CReplay::IsPlayingBack())\n\t\treturn;\n#endif\n\tif (FrenzyOnGoing()) {\n\t\tint32 model = vehicle->GetModelIndex();\n\t\tif (ModelToKill == FRENZY_ANY_CAR || ModelToKill == model || ModelToKill2 == model || ModelToKill3 == model || ModelToKill4 == model) {\n\t\t\tKillsNeeded--;\n\t\t\tDMAudio.PlayFrontEndSound(SOUND_RAMPAGE_CAR_BLOWN, 0);\n\t\t}\n\t}\n\tRegisteredKills[vehicle->GetModelIndex()]++;\n\tswitch (vehicle->GetVehicleAppearance()) {\n\tcase VEHICLE_APPEARANCE_CAR:\n\tcase VEHICLE_APPEARANCE_BIKE:\n\t\tCStats::CarsExploded++;;\n\t\tbreak;\n\tcase VEHICLE_APPEARANCE_HELI:\n\tcase VEHICLE_APPEARANCE_PLANE:\n\t\tCStats::HelisDestroyed++;\n\t\tbreak;\n\tcase VEHICLE_APPEARANCE_BOAT:\n\t\tCStats::BoatsExploded++;\n\t\tbreak;\n\t}\n\t\n}\n\nvoid\nCDarkel::RegisterKillByPlayer(CPed *victim, eWeaponType weapon, bool headshot)\n{\n#ifdef FIX_BUGS\n\tif (CReplay::IsPlayingBack())\n\t\treturn;\n#endif\n\tif (FrenzyOnGoing() && (weapon == WeaponType\n\t\t\t|| weapon == WEAPONTYPE_EXPLOSION\n\t\t\t|| weapon == WEAPONTYPE_UZI_DRIVEBY && WeaponType == WEAPONTYPE_UZI\n\t\t\t|| weapon == WEAPONTYPE_RAMMEDBYCAR && WeaponType == WEAPONTYPE_RUNOVERBYCAR\n\t\t\t|| weapon == WEAPONTYPE_RUNOVERBYCAR && WeaponType == WEAPONTYPE_RAMMEDBYCAR\n\t\t\t|| weapon == WEAPONTYPE_FLAMETHROWER && WeaponType == WEAPONTYPE_MOLOTOV)) {\n\t\tint32 model = victim->GetModelIndex();\n\t\tif (ModelToKill == FRENZY_ANY_PED || ModelToKill == model || ModelToKill2 == model || ModelToKill3 == model || ModelToKill4 == model) {\n\t\t\tif (!bNeedHeadShot || headshot) {\n\t\t\t\tKillsNeeded--;\n\t\t\t\tDMAudio.PlayFrontEndSound(SOUND_RAMPAGE_KILL, 0);\n\t\t\t}\n\t\t}\n\t}\n\tCStats::PeopleKilledByPlayer++;\n\tRegisteredKills[victim->GetModelIndex()]++;\n\tCStats::PedsKilledOfThisType[victim->bChrisCriminal ? PEDTYPE_CRIMINAL : victim->m_nPedType]++;\n\tif (headshot)\n\t\tCStats::HeadsPopped++;\n\tCStats::KillsSinceLastCheckpoint++;\n}\n\nvoid\nCDarkel::RegisterKillNotByPlayer(CPed* victim, eWeaponType weapontype)\n{\n#ifdef FIX_BUGS\n\tif (CReplay::IsPlayingBack())\n\t\treturn;\n#endif\n\tCStats::PeopleKilledByOthers++;\n}\n\nvoid\nCDarkel::ResetModelsKilledByPlayer()\n{\n\tfor (int i = 0; i < NUM_DEFAULT_MODELS; i++)\n\t\tRegisteredKills[i] = 0;\n}\n\nvoid\nCDarkel::ResetOnPlayerDeath()\n{\n\tif (Status != KILLFRENZY_ONGOING)\n\t\treturn;\n\n\tCPopulation::m_AllRandomPedsThisType = -1;\n\tStatus = KILLFRENZY_FAILED;\n\tTimeOfFrenzyStart = CTimer::GetTimeInMilliseconds();\n\n\tDealWithWeaponChangeAtEndOfFrenzy();\n}\n\nvoid\nCDarkel::StartFrenzy(eWeaponType weaponType, int32 time, uint16 kill, int32 modelId0, wchar *text, int32 modelId2, int32 modelId3, int32 modelId4, bool standardSound, bool needHeadShot)\n{\n\tCGameLogic::ClearShortCut();\n\tCGameLogic::RemoveShortCutDropOffPointForMission();\n\teWeaponType fixedWeapon;\n\tif (weaponType == WEAPONTYPE_UZI_DRIVEBY)\n\t\tfixedWeapon = WEAPONTYPE_UZI;\n\telse\n\t\tfixedWeapon = weaponType;\n\n\tWeaponType = weaponType;\n\tStatus = KILLFRENZY_ONGOING;\n\tKillsNeeded = kill;\n\tModelToKill = modelId0;\n\tModelToKill2 = modelId2;\n\tModelToKill3 = modelId3;\n\tModelToKill4 = modelId4;\n\tpStartMessage = text;\n\n\tif (text == TheText.Get(\"PAGE_00\")) {\n\t\tCDarkel::bProperKillFrenzy = true;\n\t\tCDarkel::pStartMessage = nil;\n\t} else\n\t\tbProperKillFrenzy = false;\n\t\n\tbStandardSoundAndMessages = standardSound;\n\tbNeedHeadShot = needHeadShot;\n\tTimeOfFrenzyStart = CTimer::GetTimeInMilliseconds();\n\tTimeLimit = time;\n\tPreviousTime = time / 1000;\n\n\tCPlayerPed *player = FindPlayerPed();\n\tif (fixedWeapon < WEAPONTYPE_TOTALWEAPONS) {\n\t\tInterruptedWeaponSelected = player->GetWeapon()->m_eWeaponType;\n#if (defined FIX_BUGS || !defined GTA_PS2)\n\t\tplayer->RemoveWeaponAnims(InterruptedWeaponSelected, -1000.0f);\n#endif\n\t\tInterruptedWeaponType = player->GetWeapon(player->GetWeaponSlot(fixedWeapon)).m_eWeaponType;\n\t\tAmmoInterruptedWeapon = player->GetWeapon(player->GetWeaponSlot(fixedWeapon)).m_nAmmoTotal;\n\t\tif (InterruptedWeaponType)\n\t\t\tCModelInfo::GetModelInfo(CWeaponInfo::GetWeaponInfo((eWeaponType)InterruptedWeaponType)->m_nModelId)->AddRef();\n#if (!defined FIX_BUGS && defined GTA_PS2)\n\t\tplayer->RemoveWeaponAnims(InterruptedWeaponSelected, -1000.0f);\n#endif\n\t\tplayer->GiveWeapon(fixedWeapon, 30000);\n\t\tplayer->SetCurrentWeapon(fixedWeapon);\n\t\tplayer->MakeChangesForNewWeapon(player->m_nSelectedWepSlot);\n\n\t\tif (FindPlayerVehicle()) {\n\t\t\tplayer->SetCurrentWeapon(FindPlayerPed()->m_nSelectedWepSlot);\n\t\t\tplayer->SetAmmo(fixedWeapon, Min(player->GetWeapon()->m_nAmmoTotal, CWeaponInfo::GetWeaponInfo(player->GetWeapon()->m_eWeaponType)->m_nAmountofAmmunition));\n\t\t\tplayer->ClearWeaponTarget();\n\t\t}\n\t}\n\tif (CDarkel::bStandardSoundAndMessages)\n\t\tDMAudio.PlayFrontEndSound(SOUND_RAMPAGE_START, 0);\n}\n\nvoid\nCDarkel::Update()\n{\n#ifdef FIX_BUGS\n\tif (CReplay::IsPlayingBack())\n\t\treturn;\n#endif\n\n\tif (Status != KILLFRENZY_ONGOING)\n\t\treturn;\n\n\tint32 FrameTime = TimeLimit - (CTimer::GetTimeInMilliseconds() - TimeOfFrenzyStart);\n\tif (FrameTime > 0 || TimeLimit < 0) {\n\n\t\tDMAudio.PlayFrontEndSound(SOUND_RAMPAGE_ONGOING, FrameTime);\n\n\t\tint32 PrevTime = FrameTime / 1000;\n\n\t\tif (PrevTime != PreviousTime) {\n\t\t\tif (PreviousTime < 12)\n\t\t\t\tDMAudio.PlayFrontEndSound(SOUND_CLOCK_TICK, PrevTime);\n\t\t\tPreviousTime = PrevTime;\n\t\t}\n\n\t} else {\n\t\tCPopulation::m_AllRandomPedsThisType = -1;\n\t\tStatus = KILLFRENZY_FAILED;\n\t\tTimeOfFrenzyStart = CTimer::GetTimeInMilliseconds();\n\t\tDealWithWeaponChangeAtEndOfFrenzy();\n\n\t\tif (bStandardSoundAndMessages)\n\t\t\tDMAudio.PlayFrontEndSound(SOUND_RAMPAGE_FAILED, 0);\n\t}\n\n\tif (KillsNeeded <= 0) {\n\t\tCPopulation::m_AllRandomPedsThisType = -1;\n\t\tStatus = KILLFRENZY_PASSED;\n\n\t\tif (bProperKillFrenzy)\n\t\t\tCStats::AnotherKillFrenzyPassed();\n\n\t\tTimeOfFrenzyStart = CTimer::GetTimeInMilliseconds();\n\n\t\tFindPlayerPed()->m_pWanted->SetWantedLevel(0);\n\n\t\tDealWithWeaponChangeAtEndOfFrenzy();\n\n\t\tif (bStandardSoundAndMessages)\n\t\t\tDMAudio.PlayFrontEndSound(SOUND_RAMPAGE_PASSED, 0);\n\t}\n}\n\nvoid\nCDarkel::DealWithWeaponChangeAtEndOfFrenzy()\n{\n\teWeaponType fixedWeapon;\n\tif (WeaponType == WEAPONTYPE_UZI_DRIVEBY)\n\t\tfixedWeapon = WEAPONTYPE_UZI;\n\telse\n\t\tfixedWeapon = (eWeaponType)WeaponType;\n\n\tif (fixedWeapon < WEAPONTYPE_TOTALWEAPONS && InterruptedWeaponType)\n\t\tCModelInfo::GetModelInfo(CWeaponInfo::GetWeaponInfo((eWeaponType)InterruptedWeaponType)->m_nModelId)->RemoveRef();\n\n\tif (fixedWeapon < WEAPONTYPE_TOTALWEAPONS) {\n\t\tint slot = CWeaponInfo::GetWeaponInfo(fixedWeapon)->m_nWeaponSlot;\n\t\tFindPlayerPed()->RemoveWeaponModel(FindPlayerPed()->GetWeapon(slot).GetInfo()->m_nModelId);\n\t\tFindPlayerPed()->GetWeapon(slot).m_eWeaponType = WEAPONTYPE_UNARMED;\n\t\tFindPlayerPed()->GetWeapon(slot).m_nAmmoTotal = 0;\n\t\tFindPlayerPed()->GetWeapon(slot).m_nAmmoInClip = 0;\n\t\tFindPlayerPed()->GetWeapon(slot).m_eWeaponState = WEAPONSTATE_READY;\n\t\tFindPlayerPed()->RemoveWeaponAnims(fixedWeapon, -1000.0f);\n\t\tCModelInfo::GetModelInfo(CWeaponInfo::GetWeaponInfo(fixedWeapon)->m_nModelId)->RemoveRef();\n\t}\n\n\tCPlayerPed* player = FindPlayerPed();\n\tif (fixedWeapon < WEAPONTYPE_TOTALWEAPONS) {\n\t\tplayer->m_nSelectedWepSlot = CWeaponInfo::GetWeaponInfo((eWeaponType)InterruptedWeaponSelected)->m_nWeaponSlot;\n\t\tplayer->GiveWeapon((eWeaponType)InterruptedWeaponType, AmmoInterruptedWeapon, true);\n\t}\n\n\tif (FindPlayerVehicle()) {\n\t\tplayer->RemoveWeaponModel(CWeaponInfo::GetWeaponInfo(player->GetWeapon()->m_eWeaponType)->m_nModelId);\n\t\tif (FindPlayerPed()->GetWeapon(WEAPONSLOT_SUBMACHINEGUN).m_eWeaponType)\n\t\t\tFindPlayerPed()->m_nSelectedWepSlot = WEAPONSLOT_SUBMACHINEGUN;\n\t\telse\n\t\t\tFindPlayerPed()->m_nSelectedWepSlot = WEAPONSLOT_UNARMED;\n\t\tplayer->SetCurrentWeapon(FindPlayerPed()->m_nSelectedWepSlot);\n\t\tplayer->MakeChangesForNewWeapon(player->m_currentWeapon);\n\t\tplayer->RemoveDrivebyAnims();\n\t}\n}\n"
  },
  {
    "path": "src/control/Darkel.h",
    "content": "#pragma once\n\n#include \"ModelIndices.h\"\n#include \"WeaponType.h\"\n\nclass CVehicle;\nclass CPed;\n\nenum\n{\n\tKILLFRENZY_NONE,\n\tKILLFRENZY_ONGOING,\n\tKILLFRENZY_PASSED,\n\tKILLFRENZY_FAILED,\n};\n\nclass CDarkel\n{\nprivate:\n\tstatic int32 TimeLimit;\n\tstatic int32 PreviousTime;\n\tstatic int32 TimeOfFrenzyStart;\n\tstatic int32 WeaponType;\n\tstatic int32 AmmoInterruptedWeapon;\n\tstatic int32 KillsNeeded;\n\tstatic int32 InterruptedWeaponType;\n\tstatic int32 InterruptedWeaponSelected;\n\tstatic bool bStandardSoundAndMessages;\n\tstatic bool bNeedHeadShot;\n\tstatic bool bProperKillFrenzy;\n\tstatic uint16 Status;\n\tstatic uint16 RegisteredKills[NUM_DEFAULT_MODELS];\n\tstatic int32 ModelToKill;\n\tstatic int32 ModelToKill2;\n\tstatic int32 ModelToKill3;\n\tstatic int32 ModelToKill4;\n\tstatic wchar *pStartMessage;\n\npublic:\n\tstatic uint8 CalcFade(uint32 time, uint32 min, uint32 max);\n\tstatic void DrawMessages(void);\n\tstatic bool FrenzyOnGoing();\n\tstatic void Init();\n\tstatic uint16 QueryModelsKilledByPlayer(int32 modelId);\n\tstatic uint16 ReadStatus();\n\tstatic void RegisterCarBlownUpByPlayer(CVehicle *vehicle);\n\tstatic void RegisterKillByPlayer(CPed *victim, eWeaponType weapontype, bool headshot = false);\n\tstatic void RegisterKillNotByPlayer(CPed* victim, eWeaponType weapontype);\n\tstatic void ResetModelsKilledByPlayer();\n\tstatic void ResetOnPlayerDeath();\n\tstatic void StartFrenzy(eWeaponType weaponType, int32 time, uint16 kill, int32 modelId0, wchar *text, int32 modelId2, int32 modelId3, int32 modelId4, bool standardSound, bool needHeadShot);\n\tstatic void Update();\n\tstatic void DealWithWeaponChangeAtEndOfFrenzy();\n\n};\n"
  },
  {
    "path": "src/control/GameLogic.cpp",
    "content": "#include \"common.h\"\n\n#include \"GameLogic.h\"\n#include \"Clock.h\"\n#include \"Stats.h\"\n#include \"Pickups.h\"\n#include \"Timer.h\"\n#include \"Streaming.h\"\n#include \"CutsceneMgr.h\"\n#include \"World.h\"\n#include \"PlayerPed.h\"\n#include \"Wanted.h\"\n#include \"Camera.h\"\n#include \"Messages.h\"\n#include \"CarCtrl.h\"\n#include \"Restart.h\"\n#include \"Pad.h\"\n#include \"References.h\"\n#include \"Fire.h\"\n#include \"Script.h\"\n#include \"Garages.h\"\n#include \"Population.h\"\n#include \"General.h\"\n#include \"DMAudio.h\"\n#include \"Radar.h\"\n#include \"Pools.h\"\n#include \"Hud.h\"\n#include \"Particle.h\"\n#include \"ColStore.h\"\n#include \"Automobile.h\"\n#include \"MBlur.h\"\n#include \"screendroplets.h\"\n\nuint8 CGameLogic::ActivePlayers;\nuint8 CGameLogic::ShortCutState;\nCAutomobile* CGameLogic::pShortCutTaxi;\nuint32 CGameLogic::NumAfterDeathStartPoints;\nCVector CGameLogic::ShortCutStart;\nfloat CGameLogic::ShortCutStartOrientation;\nCVector CGameLogic::ShortCutDestination;\nfloat CGameLogic::ShortCutDestinationOrientation;\nuint32 CGameLogic::ShortCutTimer;\nCVector CGameLogic::AfterDeathStartPoints[NUM_SHORTCUT_START_POINTS];\nfloat CGameLogic::AfterDeathStartPointOrientation[NUM_SHORTCUT_START_POINTS];\nCVector CGameLogic::ShortCutDropOffForMission;\nfloat CGameLogic::ShortCutDropOffOrientationForMission;\nbool CGameLogic::MissionDropOffReadyToBeUsed;\n\n#define SHORTCUT_TAXI_COST (9)\n#define TOTAL_BUSTED_AUDIO (28)\n\nvoid\nCGameLogic::InitAtStartOfGame()\n{\n\tActivePlayers = 1;\n\tShortCutState = SHORTCUT_NONE;\n\tpShortCutTaxi = nil;\n\tNumAfterDeathStartPoints = 0;\n}\n\nvoid\nCGameLogic::PassTime(uint32 time)\n{\n\tint32 minutes, hours, days;\n\n\tminutes = time + CClock::GetMinutes();\n\thours = CClock::GetHours();\n\n\tfor (; minutes >= 60; minutes -= 60)\n\t\thours++;\n\n\tif (hours > 23) {\n\t\tdays = CStats::DaysPassed;\n\t\tfor (; hours >= 24; hours -= 24)\n\t\t\tdays++;\n\t\tCStats::DaysPassed = days;\n\t}\n\n\tCClock::SetGameClock(hours, minutes);\n\tCPickups::PassTime(time * 1000);\n}\n\nvoid \nCGameLogic::SortOutStreamingAndMemory(const CVector &pos)\n{\n\tCTimer::Stop();\n\tCStreaming::FlushRequestList();\n\tCStreaming::DeleteRwObjectsAfterDeath(pos);\n\tCStreaming::RemoveUnusedModelsInLoadedList();\n\tCGame::DrasticTidyUpMemory(true);\n\tCWorld::Players[CWorld::PlayerInFocus].m_pPed->Undress(\"player\");\n\tCStreaming::LoadSceneCollision(pos);\n\tCStreaming::LoadScene(pos);\n\tCWorld::Players[CWorld::PlayerInFocus].m_pPed->Dress();\n\tCTimer::Update();\n}\n\nvoid\nCGameLogic::Update()\n{\n\tCVector vecRestartPos;\n\tfloat fRestartFloat;\n\n\tif (CCutsceneMgr::IsCutsceneProcessing()) return;\n\n\tUpdateShortCut();\n\tCPlayerInfo &pPlayerInfo = CWorld::Players[CWorld::PlayerInFocus];\n\n\tswitch (pPlayerInfo.m_WBState) {\n\tcase WBSTATE_PLAYING:\n\t\tif (pPlayerInfo.m_pPed->m_nPedState == PED_DEAD) {\n\t\t\tpPlayerInfo.m_pPed->ClearAdrenaline();\n\t\t\tpPlayerInfo.KillPlayer();\n\t\t}\n\t\tif (pPlayerInfo.m_pPed->m_nPedState == PED_ARRESTED) {\n\t\t\tpPlayerInfo.m_pPed->ClearAdrenaline();\n\t\t\tpPlayerInfo.ArrestPlayer();\n\t\t}\n\t\tbreak;\n\tcase WBSTATE_WASTED:\n#ifdef MISSION_REPLAY\n\t\tif ((CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime > AddExtraDeathDelay() + 0x800) && (CTimer::GetPreviousTimeInMilliseconds() - pPlayerInfo.m_nWBTime <= AddExtraDeathDelay() + 0x800)) {\n#else\n\t\tif ((CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime > 0x800) && (CTimer::GetPreviousTimeInMilliseconds() - pPlayerInfo.m_nWBTime <= 0x800)) {\n#endif\n\t\t\tTheCamera.SetFadeColour(200, 200, 200);\n\t\t\tTheCamera.Fade(2.0f, FADE_OUT);\n\t\t}\n\n#ifdef MISSION_REPLAY\n\t\tif (CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime >= AddExtraDeathDelay() + 0x1000) {\n#else\n\t\tif (CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime >= 0x1000) {\n#endif\n\t\t\tpPlayerInfo.m_WBState = WBSTATE_PLAYING;\n\t\t\tif (pPlayerInfo.m_bGetOutOfHospitalFree) {\n\t\t\t\tpPlayerInfo.m_bGetOutOfHospitalFree = false;\n\t\t\t} else {\n\t\t\t\tpPlayerInfo.m_nMoney = Max(0, pPlayerInfo.m_nMoney - 100);\n\t\t\t\tpPlayerInfo.m_pPed->ClearWeapons();\n\t\t\t}\n\n\t\t\tif (pPlayerInfo.m_pPed->bInVehicle) {\n\t\t\t\tCVehicle *pVehicle = pPlayerInfo.m_pPed->m_pMyVehicle;\n\t\t\t\tif (pVehicle != nil) {\n\t\t\t\t\tif (pVehicle->pDriver == pPlayerInfo.m_pPed) {\n\t\t\t\t\t\tpVehicle->pDriver = nil;\n\t\t\t\t\t\tif (pVehicle->GetStatus() != STATUS_WRECKED)\n\t\t\t\t\t\t\tpVehicle->SetStatus(STATUS_ABANDONED);\n\t\t\t\t\t} else\n\t\t\t\t\t\tpVehicle->RemovePassenger(pPlayerInfo.m_pPed);\n\t\t\t\t}\n\t\t\t}\n\t\t\tCEventList::Initialise();\n#ifdef SCREEN_DROPLETS\n\t\t\tScreenDroplets::Initialise();\n#endif\n\t\t\tCMessages::ClearMessages();\n\t\t\tCCarCtrl::ClearInterestingVehicleList();\n\t\t\tCWorld::ClearExcitingStuffFromArea(pPlayerInfo.GetPos(), 4000.0f, 1);\n\t\t\tCRestart::FindClosestHospitalRestartPoint(pPlayerInfo.GetPos(), &vecRestartPos, &fRestartFloat);\n\t\t\tCRestart::OverrideHospitalLevel = LEVEL_GENERIC;\n\t\t\tCRestart::OverridePoliceStationLevel = LEVEL_GENERIC;\n\t\t\tPassTime(720);\n\t\t\tRestorePlayerStuffDuringResurrection(pPlayerInfo.m_pPed, vecRestartPos, fRestartFloat);\n\t\t\tAfterDeathArrestSetUpShortCutTaxi();\n\t\t\tSortOutStreamingAndMemory(pPlayerInfo.GetPos());\n\t\t\tTheCamera.m_fCamShakeForce = 0.0f;\n\t\t\tTheCamera.SetMotionBlur(0, 0, 0, 0, MOTION_BLUR_NONE);\n\t\t\tCPad::GetPad(0)->StopShaking(0);\n\t\t\tCReferences::RemoveReferencesToPlayer();\n\t\t\tCPopulation::m_CountDownToPedsAtStart = 10;\n\t\t\tCCarCtrl::CountDownToCarsAtStart = 10;\n\t\t\tCPad::GetPad(CWorld::PlayerInFocus)->DisablePlayerControls = PLAYERCONTROL_ENABLED;\n\t\t\tif (CRestart::bFadeInAfterNextDeath) { \n\t\t\t\tTheCamera.SetFadeColour(200, 200, 200);\n\t\t\t\tTheCamera.Fade(4.0f, FADE_IN);\n\t\t\t} else\n\t\t\t\tCRestart::bFadeInAfterNextDeath = true;\n\t\t}\n\t\tbreak;\n\tcase WBSTATE_BUSTED:\n#ifdef MISSION_REPLAY\n\t\tif ((CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime > AddExtraDeathDelay() + 0x800) && (CTimer::GetPreviousTimeInMilliseconds() - pPlayerInfo.m_nWBTime <= AddExtraDeathDelay() + 0x800)) {\n#else\n\t\tif ((CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime > 0x800) && (CTimer::GetPreviousTimeInMilliseconds() - pPlayerInfo.m_nWBTime <= 0x800)) {\n#endif\n\t\t\tTheCamera.SetFadeColour(0, 0, 0);\n\t\t\tTheCamera.Fade(2.0f, FADE_OUT);\n\t\t}\n\n\n\t\tif (!CTheScripts::IsPlayerOnAMission() && pPlayerInfo.m_nBustedAudioStatus == 0) {\n\t\t\tif (CGeneral::GetRandomNumberInRange(0, 4) == 0)\n\t\t\t\tpPlayerInfo.m_nBustedAudioStatus = BUSTEDAUDIO_DONE;\n\t\t\telse {\n\t\t\t\tpPlayerInfo.m_nBustedAudioStatus = BUSTEDAUDIO_LOADING;\n\t\t\t\tchar name[12];\n\t\t\t\tsprintf(name, pPlayerInfo.m_nCurrentBustedAudio >= 10 ? \"bust_%d\" : \"bust_0%d\", pPlayerInfo.m_nCurrentBustedAudio);\n\t\t\t\tDMAudio.ClearMissionAudio(0);\n\t\t\t\tDMAudio.PreloadMissionAudio(0, name);\n\t\t\t\tpPlayerInfo.m_nCurrentBustedAudio = pPlayerInfo.m_nCurrentBustedAudio % TOTAL_BUSTED_AUDIO + 1;\n\t\t\t}\n\t\t}\n\t\tif (CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime > 4000 &&\n\t\t\tpPlayerInfo.m_nBustedAudioStatus == BUSTEDAUDIO_LOADING &&\n\t\t\tDMAudio.GetMissionAudioLoadingStatus(0) == 1) {\n\t\t\tDMAudio.PlayLoadedMissionAudio(0);\n\t\t\tpPlayerInfo.m_nBustedAudioStatus = BUSTEDAUDIO_DONE;\n\t\t}\n\t\t\n#ifdef MISSION_REPLAY\n\t\tif (CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime >= AddExtraDeathDelay() + 0x1000) {\n#else\n\t\tif (CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime >= 0x1000) {\n#endif\n#ifdef FIX_BUGS\n\t\t\tpPlayerInfo.m_nBustedAudioStatus = BUSTEDAUDIO_NONE;\n#endif\n\t\t\tpPlayerInfo.m_WBState = WBSTATE_PLAYING;\n\t\t\tint takeMoney;\n\n\t\t\tswitch (pPlayerInfo.m_pPed->m_pWanted->GetWantedLevel()) {\n\t\t\tcase 0:\n\t\t\tcase 1:\n\t\t\t\ttakeMoney = 100;\n\t\t\t\tbreak;\n\t\t\tcase 2:\n\t\t\t\ttakeMoney = 200;\n\t\t\t\tbreak;\n\t\t\tcase 3:\n\t\t\t\ttakeMoney = 400;\n\t\t\t\tbreak;\n\t\t\tcase 4:\n\t\t\t\ttakeMoney = 600;\n\t\t\t\tbreak;\n\t\t\tcase 5:\n\t\t\t\ttakeMoney = 900;\n\t\t\t\tbreak;\n\t\t\tcase 6:\n\t\t\t\ttakeMoney = 1500;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (pPlayerInfo.m_bGetOutOfJailFree) {\n\t\t\t\tpPlayerInfo.m_bGetOutOfJailFree = false;\n\t\t\t} else {\n\t\t\t\tpPlayerInfo.m_nMoney = Max(0, pPlayerInfo.m_nMoney - takeMoney);\n\t\t\t\tpPlayerInfo.m_pPed->ClearWeapons();\n\t\t\t}\n\n\t\t\tif (pPlayerInfo.m_pPed->bInVehicle) {\n\t\t\t\tCVehicle *pVehicle = pPlayerInfo.m_pPed->m_pMyVehicle;\n\t\t\t\tif (pVehicle != nil) {\n\t\t\t\t\tif (pVehicle->pDriver == pPlayerInfo.m_pPed) {\n\t\t\t\t\t\tpVehicle->pDriver = nil;\n\t\t\t\t\t\tif (pVehicle->GetStatus() != STATUS_WRECKED)\n\t\t\t\t\t\t\tpVehicle->SetStatus(STATUS_ABANDONED);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t\tpVehicle->RemovePassenger(pPlayerInfo.m_pPed);\n\t\t\t\t}\n\t\t\t}\n\t\t\tCEventList::Initialise();\n#ifdef SCREEN_DROPLETS\n\t\t\tScreenDroplets::Initialise();\n#endif\n\t\t\tCMessages::ClearMessages();\n\t\t\tCCarCtrl::ClearInterestingVehicleList();\n\t\t\tCWorld::ClearExcitingStuffFromArea(pPlayerInfo.GetPos(), 4000.0f, 1);\n\t\t\tCRestart::FindClosestPoliceRestartPoint(pPlayerInfo.GetPos(), &vecRestartPos, &fRestartFloat);\n\t\t\tCRestart::OverrideHospitalLevel = LEVEL_GENERIC;\n\t\t\tCRestart::OverridePoliceStationLevel = LEVEL_GENERIC;\n\t\t\tPassTime(720);\n\t\t\tRestorePlayerStuffDuringResurrection(pPlayerInfo.m_pPed, vecRestartPos, fRestartFloat);\n\t\t\tAfterDeathArrestSetUpShortCutTaxi();\n\t\t\tpPlayerInfo.m_pPed->ClearWeapons();\n\t\t\tSortOutStreamingAndMemory(pPlayerInfo.GetPos());\n\t\t\tTheCamera.m_fCamShakeForce = 0.0f;\n\t\t\tTheCamera.SetMotionBlur(0, 0, 0, 0, MOTION_BLUR_NONE);\n\t\t\tCPad::GetPad(0)->StopShaking(0);\n\t\t\tCReferences::RemoveReferencesToPlayer();\n\t\t\tCPopulation::m_CountDownToPedsAtStart = 10;\n\t\t\tCCarCtrl::CountDownToCarsAtStart = 10;\n\t\t\tCPad::GetPad(CWorld::PlayerInFocus)->DisablePlayerControls = PLAYERCONTROL_ENABLED;\n\t\t\tif (CRestart::bFadeInAfterNextArrest) {\n\t\t\t\tTheCamera.SetFadeColour(0, 0, 0);\n\t\t\t\tTheCamera.Fade(4.0f, FADE_IN);\n\t\t\t} else\n\t\t\t\tCRestart::bFadeInAfterNextArrest = true;\n\t\t}\n\t\tbreak;\n\tcase WBSTATE_FAILED_CRITICAL_MISSION:\n#ifdef MISSION_REPLAY\n\t\tif ((CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime > AddExtraDeathDelay() + 0x800) && (CTimer::GetPreviousTimeInMilliseconds() - pPlayerInfo.m_nWBTime <= AddExtraDeathDelay() + 0x800)) {\n#else\n\t\tif ((CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime > 0x800) && (CTimer::GetPreviousTimeInMilliseconds() - pPlayerInfo.m_nWBTime <= 0x800)) {\n#endif\n\t\t\tTheCamera.SetFadeColour(0, 0, 0);\n\t\t\tTheCamera.Fade(2.0f, FADE_OUT);\n\t\t}\n#ifdef MISSION_REPLAY\n\t\tif (CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime >= AddExtraDeathDelay() + 0x1000) {\n#else\n\t\tif (CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime >= 0x1000) {\n#endif\n\t\t\tpPlayerInfo.m_WBState = WBSTATE_PLAYING;\n\t\t\tif (pPlayerInfo.m_pPed->bInVehicle) {\n\t\t\t\tCVehicle *pVehicle = pPlayerInfo.m_pPed->m_pMyVehicle;\n\t\t\t\tif (pVehicle != nil) {\n\t\t\t\t\tif (pVehicle->pDriver == pPlayerInfo.m_pPed) {\n\t\t\t\t\t\tpVehicle->pDriver = nil;\n\t\t\t\t\t\tif (pVehicle->GetStatus() != STATUS_WRECKED)\n\t\t\t\t\t\t\tpVehicle->SetStatus(STATUS_ABANDONED);\n\t\t\t\t\t} else\n\t\t\t\t\t\tpVehicle->RemovePassenger(pPlayerInfo.m_pPed);\n\t\t\t\t}\n\t\t\t}\n\t\t\tCEventList::Initialise();\n#ifdef SCREEN_DROPLETS\n\t\t\tScreenDroplets::Initialise();\n#endif\n\t\t\tCMessages::ClearMessages();\n\t\t\tCCarCtrl::ClearInterestingVehicleList();\n\t\t\tCWorld::ClearExcitingStuffFromArea(pPlayerInfo.GetPos(), 4000.0f, 1);\n\t\t\tCRestart::FindClosestPoliceRestartPoint(pPlayerInfo.GetPos(), &vecRestartPos, &fRestartFloat);\n\t\t\tCRestart::OverridePoliceStationLevel = LEVEL_GENERIC;\n\t\t\tCRestart::OverrideHospitalLevel = LEVEL_GENERIC;\n\t\t\tRestorePlayerStuffDuringResurrection(pPlayerInfo.m_pPed, vecRestartPos, fRestartFloat);\n\t\t\tSortOutStreamingAndMemory(pPlayerInfo.GetPos());\n\t\t\tTheCamera.m_fCamShakeForce = 0.0f;\n\t\t\tTheCamera.SetMotionBlur(0, 0, 0, 0, MOTION_BLUR_NONE);\n\t\t\tCPad::GetPad(0)->StopShaking(0);\n\t\t\tCReferences::RemoveReferencesToPlayer();\n\t\t\tCPopulation::m_CountDownToPedsAtStart = 10;\n\t\t\tCCarCtrl::CountDownToCarsAtStart = 10;\n\t\t\tCPad::GetPad(CWorld::PlayerInFocus)->DisablePlayerControls = PLAYERCONTROL_ENABLED;\n\t\t\tTheCamera.SetFadeColour(0, 0, 0);\n\t\t\tTheCamera.Fade(4.0f, FADE_IN);\n\t\t}\n\t\tbreak;\n\tcase 4:\n\t\treturn;\n\t}\n}\n\nvoid\nCGameLogic::RestorePlayerStuffDuringResurrection(CPlayerPed *pPlayerPed, CVector pos, float angle)\n{\n\tClearShortCut();\n\tCPlayerInfo* pPlayerInfo = pPlayerPed->GetPlayerInfoForThisPlayerPed();\n\tpPlayerPed->m_fHealth = pPlayerInfo->m_nMaxHealth;\n\tpPlayerPed->m_fArmour = 0.0f;\n\tpPlayerPed->bIsVisible = true;\n\tpPlayerPed->m_bloodyFootprintCountOrDeathTime = 0;\n\tpPlayerPed->bDoBloodyFootprints = false;\n\tpPlayerPed->m_nDrunkenness = 0;\n\tpPlayerPed->m_nFadeDrunkenness = 0;\n\tCMBlur::ClearDrunkBlur();\n\tpPlayerPed->m_nDrunkCountdown = 0;\n\tpPlayerPed->ClearAdrenaline();\n\tpPlayerPed->m_fCurrentStamina = pPlayerPed->m_fMaxStamina;\n\tif (pPlayerPed->m_pFire)\n\t\tpPlayerPed->m_pFire->Extinguish();\n\tpPlayerPed->bInVehicle = false;\n\tpPlayerPed->m_pMyVehicle = nil;\n\tpPlayerPed->m_pVehicleAnim = nil;\n\tpPlayerPed->m_pWanted->Reset();\n\tpPlayerPed->bCancelEnteringCar = false;\n\tpPlayerPed->RestartNonPartialAnims();\n\tpPlayerInfo->MakePlayerSafe(false);\n\tpPlayerPed->bRemoveFromWorld = false;\n\tpPlayerPed->ClearWeaponTarget();\n\tpPlayerPed->SetInitialState();\n\tCCarCtrl::ClearInterestingVehicleList();\n\tpPlayerPed->Teleport(pos + CVector(0.0f, 0.0f, 1.0f));\n\tpPlayerPed->SetMoveSpeed(0.0f, 0.0f, 0.0f);\n\tpPlayerPed->m_fRotationCur = DEGTORAD(angle);\n\tpPlayerPed->m_fRotationDest = pPlayerPed->m_fRotationCur;\n\tpPlayerPed->SetHeading(pPlayerPed->m_fRotationCur);\n\tCTheScripts::ClearSpaceForMissionEntity(pos, pPlayerPed);\n\tCWorld::ClearExcitingStuffFromArea(pos, 4000.0, 1);\n\tpPlayerPed->RestoreHeadingRate();\n\tCGame::currArea = AREA_MAIN_MAP;\n\tCStreaming::RemoveBuildingsNotInArea(0);\n\tTheCamera.SetCameraDirectlyInFrontForFollowPed_CamOnAString();\n\tTheCamera.Restore();\n\tCReferences::RemoveReferencesToPlayer();\n\tCGarages::PlayerArrestedOrDied();\n\tCStats::CheckPointReachedUnsuccessfully();\n\tCWorld::Remove(pPlayerPed);\n\tCWorld::Add(pPlayerPed);\n\tCHud::ResetWastedText();\n\tCStreaming::StreamZoneModels(pos);\n\tclearWaterDrop = true;\n}\n\nvoid\nCGameLogic::ClearShortCut()\n{\n\tif (pShortCutTaxi) {\n\t\tif (pShortCutTaxi->VehicleCreatedBy == MISSION_VEHICLE) {\n\t\t\tpShortCutTaxi->VehicleCreatedBy = RANDOM_VEHICLE;\n\t\t\t--CCarCtrl::NumMissionCars;\n\t\t\t++CCarCtrl::NumRandomCars;\n\t\t}\n\t\tCRadar::ClearBlipForEntity(BLIP_CAR, CPools::GetVehiclePool()->GetIndex(pShortCutTaxi));\n\t\tpShortCutTaxi = nil;\n\t}\n\tCPad::GetPad(0)->SetEnablePlayerControls(PLAYERCONTROL_SHORTCUT_TAXI);\n}\n\nvoid\nCGameLogic::SetUpShortCut(CVector vStartPos, float fStartAngle, CVector vEndPos, float fEndAngle)\n{\n\tClearShortCut();\n\tShortCutState = SHORTCUT_INIT;\n\tShortCutStart = vStartPos;\n\tShortCutStartOrientation = fStartAngle;\n\tShortCutDestination = vEndPos;\n\tShortCutDestinationOrientation = fEndAngle;\n\tCStreaming::RequestModel(MI_KAUFMAN, 0);\n}\n\nvoid\nCGameLogic::AbandonShortCutIfTaxiHasBeenMessedWith()\n{\n\tif (!pShortCutTaxi)\n\t\treturn;\n\tif (pShortCutTaxi->pDriver == nil ||\n\t\tpShortCutTaxi->pDriver->DyingOrDead() ||\n\t\tpShortCutTaxi->pDriver->GetPedState() == PED_DRAG_FROM_CAR ||\n\t\tpShortCutTaxi->pDriver->GetPedState() == PED_ON_FIRE ||\n\t\tpShortCutTaxi->pDriver->m_objective == OBJECTIVE_LEAVE_CAR_AND_DIE ||\n\t\tpShortCutTaxi->m_fHealth < 250.0f ||\n\t\tpShortCutTaxi->bRenderScorched)\n\t\tClearShortCut();\n}\n\nvoid\nCGameLogic::AbandonShortCutIfPlayerMilesAway()\n{\n\tif (!pShortCutTaxi)\n\t\treturn;\n\tif ((FindPlayerCoors() - pShortCutTaxi->GetPosition()).Magnitude() > 120.0f)\n\t\tClearShortCut();\n}\n\nvoid\nCGameLogic::UpdateShortCut()\n{\n\tswitch (ShortCutState) {\n\tcase SHORTCUT_INIT:\n\t\tif (!CStreaming::HasModelLoaded(MI_KAUFMAN)) {\n\t\t\tCStreaming::RequestModel(MI_KAUFMAN, 0);\n\t\t\treturn;\n\t\t}\n\t\tpShortCutTaxi = new CAutomobile(MI_KAUFMAN, RANDOM_VEHICLE);\n\t\tif (!pShortCutTaxi)\n\t\t\treturn;\n\t\tpShortCutTaxi->SetPosition(ShortCutStart);\n\t\tpShortCutTaxi->SetHeading(DEGTORAD(ShortCutStartOrientation));\n\t\tpShortCutTaxi->PlaceOnRoadProperly();\n\t\tpShortCutTaxi->SetStatus(STATUS_PHYSICS);\n\t\tpShortCutTaxi->AutoPilot.m_nCarMission = MISSION_STOP_FOREVER;\n\t\tpShortCutTaxi->AutoPilot.m_nCruiseSpeed = 0;\n\t\tpShortCutTaxi->SetUpDriver();\n\t\tpShortCutTaxi->VehicleCreatedBy = MISSION_VEHICLE;\n\t\t++CCarCtrl::NumMissionCars;\n\t\t--CCarCtrl::NumRandomCars;\n\t\tCTheScripts::ClearSpaceForMissionEntity(ShortCutStart, pShortCutTaxi);\n\t\tCWorld::Add(pShortCutTaxi);\n\t\tCRadar::SetEntityBlip(BLIP_CAR, CPools::GetVehiclePool()->GetIndex(pShortCutTaxi), 0, BLIP_DISPLAY_MARKER_ONLY);\n\t\tShortCutState = SHORTCUT_IDLE;\n\t\tbreak;\n\tcase SHORTCUT_IDLE:\n\t\tif (FindPlayerPed()->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER && FindPlayerPed()->m_carInObjective == pShortCutTaxi) {\n\t\t\tCPad::GetPad(0)->SetDisablePlayerControls(PLAYERCONTROL_SHORTCUT_TAXI);\n\t\t\tFindPlayerPed()->SetObjective(OBJECTIVE_ENTER_CAR_AS_PASSENGER, pShortCutTaxi);\n\t\t\tShortCutState = SHORTCUT_GETTING_IN;\n\t\t}\n\t\tAbandonShortCutIfTaxiHasBeenMessedWith();\n\t\tAbandonShortCutIfPlayerMilesAway();\n\t\tbreak;\n\tcase SHORTCUT_GETTING_IN:\n\t\tif (pShortCutTaxi->pPassengers[0] == FindPlayerPed() ||\n\t\t\tpShortCutTaxi->pPassengers[1] == FindPlayerPed() ||\n\t\t\tpShortCutTaxi->pPassengers[2] == FindPlayerPed()) {\n\t\t\tpShortCutTaxi->AutoPilot.m_nTempAction = TEMPACT_GOFORWARD;\n\t\t\tpShortCutTaxi->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 2500;\n\t\t\tTheCamera.SetFadeColour(0, 0, 0);\n\t\t\tTheCamera.Fade(2.5f, 0);\n\t\t\tShortCutState = SHORTCUT_TRANSITION;\n\t\t\tShortCutTimer = CTimer::GetTimeInMilliseconds() + 3000;\n\t\t\tCMessages::AddBigMessage(TheText.Get(\"TAXI\"), 4500, 1);\n\t\t}\n\t\tAbandonShortCutIfTaxiHasBeenMessedWith();\n\t\tbreak;\n\tcase SHORTCUT_TRANSITION:\n\t\tif (CTimer::GetTimeInMilliseconds() > ShortCutTimer) {\n\t\t\tCTimer::Suspend();\n\t\t\tCColStore::RequestCollision(ShortCutDestination);\n\t\t\tCStreaming::LoadSceneCollision(ShortCutDestination);\n\t\t\tCStreaming::LoadScene(ShortCutDestination);\n\t\t\tCTheScripts::ClearSpaceForMissionEntity(ShortCutDestination, pShortCutTaxi);\n\t\t\tpShortCutTaxi->Teleport(ShortCutDestination);\n\t\t\tpShortCutTaxi->SetHeading(DEGTORAD(ShortCutDestinationOrientation));\n\t\t\tpShortCutTaxi->PlaceOnRoadProperly();\n\t\t\tpShortCutTaxi->SetMoveSpeed(pShortCutTaxi->GetForward() * 0.4f);\n\t\t\tShortCutTimer = CTimer::GetTimeInMilliseconds() + 1500;\n\t\t\tTheCamera.SetFadeColour(0, 0, 0);\n\t\t\tTheCamera.Fade(1.0f, 1);\n\t\t\tShortCutState = SHORTCUT_ARRIVING;\n\t\t\tCTimer::Resume();\n\t\t}\n\t\tbreak;\n\tcase SHORTCUT_ARRIVING:\n\t\tif (CTimer::GetTimeInMilliseconds() > ShortCutTimer) {\n\t\t\tCWorld::Players[CWorld::PlayerInFocus].m_nMoney = Max(0, CWorld::Players[CWorld::PlayerInFocus].m_nMoney - SHORTCUT_TAXI_COST);\n\t\t\tFindPlayerPed()->SetObjective(OBJECTIVE_LEAVE_CAR, pShortCutTaxi);\n\t\t\tFindPlayerPed()->m_carInObjective = pShortCutTaxi;\n\t\t\tShortCutState = SHORTCUT_GETTING_OUT;\n\t\t}\n\t\tAbandonShortCutIfTaxiHasBeenMessedWith();\n\t\tbreak;\n\tcase SHORTCUT_GETTING_OUT:\n\t\tif (pShortCutTaxi->pPassengers[0] != FindPlayerPed() &&\n\t\t\tpShortCutTaxi->pPassengers[1] != FindPlayerPed() &&\n\t\t\tpShortCutTaxi->pPassengers[2] != FindPlayerPed()) {\n\t\t\tCPad::GetPad(0)->SetEnablePlayerControls(PLAYERCONTROL_SHORTCUT_TAXI);\n\t\t\tpShortCutTaxi->AutoPilot.m_nCarMission = MISSION_CRUISE;\n\t\t\tpShortCutTaxi->AutoPilot.m_nCruiseSpeed = 18;\n\t\t\tCCarCtrl::JoinCarWithRoadSystem(pShortCutTaxi);\n\t\t\tpShortCutTaxi->VehicleCreatedBy = RANDOM_VEHICLE;\n\t\t\t++CCarCtrl::NumRandomCars;\n\t\t\t--CCarCtrl::NumMissionCars;\n\t\t\tCRadar::ClearBlipForEntity(BLIP_CAR, CPools::GetVehiclePool()->GetIndex(pShortCutTaxi));\n\t\t\tShortCutState = SHORTCUT_NONE;\n\t\t\tpShortCutTaxi = nil;\n\t\t}\n\t\tAbandonShortCutIfTaxiHasBeenMessedWith();\n\t\tbreak;\n\t}\n}\n\nvoid\nCGameLogic::AddShortCutPointAfterDeath(CVector point, float angle)\n{\n\tif (NumAfterDeathStartPoints >= NUM_SHORTCUT_START_POINTS)\n\t\treturn;\n\tAfterDeathStartPoints[NumAfterDeathStartPoints] = point;\n\tAfterDeathStartPointOrientation[NumAfterDeathStartPoints] = angle;\n\tNumAfterDeathStartPoints++;\n}\n\nvoid\nCGameLogic::AddShortCutDropOffPointForMission(CVector point, float angle)\n{\n\tShortCutDropOffForMission = point;\n\tShortCutDropOffOrientationForMission = angle;\n\tMissionDropOffReadyToBeUsed = true;\n}\n\nvoid\nCGameLogic::RemoveShortCutDropOffPointForMission()\n{\n\tMissionDropOffReadyToBeUsed = false;\n}\n\nvoid\nCGameLogic::AfterDeathArrestSetUpShortCutTaxi()\n{\n\tif (!MissionDropOffReadyToBeUsed)\n\t\treturn;\n\tint nClosestPoint = -1;\n\tfloat fDistanceToPoint = 999999.9f;\n\tfor (int i = 0; i < NUM_SHORTCUT_START_POINTS; i++) {\n\t\tfloat dist = (AfterDeathStartPoints[i] - FindPlayerCoors()).Magnitude();\n\t\tif (dist < fDistanceToPoint) {\n\t\t\tfDistanceToPoint = dist;\n\t\t\tnClosestPoint = i;\n\t\t}\n\t}\n\tif (fDistanceToPoint < 100.0f)\n\t\tSetUpShortCut(AfterDeathStartPoints[nClosestPoint],\n\t\t\tAfterDeathStartPointOrientation[nClosestPoint],\n\t\t\tShortCutDropOffForMission,\n\t\t\tShortCutDropOffOrientationForMission);\n\tMissionDropOffReadyToBeUsed = false;\n}\n\nvoid\nCGameLogic::Save(uint8* buf, uint32* size)\n{\nINITSAVEBUF\n\tWriteSaveBuf(buf, NumAfterDeathStartPoints);\n\t*size += sizeof(NumAfterDeathStartPoints);\n\tfor (int i = 0; i < NUM_SHORTCUT_START_POINTS; i++) {\n\t\tWriteSaveBuf(buf, AfterDeathStartPoints[i].x);\n\t\t*size += sizeof(AfterDeathStartPoints[i].x);\n\t\tWriteSaveBuf(buf, AfterDeathStartPoints[i].y);\n\t\t*size += sizeof(AfterDeathStartPoints[i].y);\n\t\tWriteSaveBuf(buf, AfterDeathStartPoints[i].z);\n\t\t*size += sizeof(AfterDeathStartPoints[i].z);\n\t\tWriteSaveBuf(buf, AfterDeathStartPointOrientation[i]);\n\t\t*size += sizeof(AfterDeathStartPointOrientation[i]);\n\t}\nVALIDATESAVEBUF(*size)\n}\n\nvoid\nCGameLogic::Load(uint8* buf, uint32 size)\n{\nINITSAVEBUF\n\tNumAfterDeathStartPoints = ReadSaveBuf<uint32>(buf);\n\tfor (int i = 0; i < NUM_SHORTCUT_START_POINTS; i++) {\n\t\tAfterDeathStartPoints[i].x = ReadSaveBuf<float>(buf);\n\t\tAfterDeathStartPoints[i].y = ReadSaveBuf<float>(buf);\n\t\tAfterDeathStartPoints[i].z = ReadSaveBuf<float>(buf);\n\t\tAfterDeathStartPointOrientation[i] = ReadSaveBuf<float>(buf);\n\t}\nVALIDATESAVEBUF(size)\n}\n"
  },
  {
    "path": "src/control/GameLogic.h",
    "content": "#pragma once\n\nclass CAutomobile;\n\nclass CGameLogic\n{\npublic:\n\tenum {\n\t\tSHORTCUT_NONE = 0,\n\t\tSHORTCUT_INIT,\n\t\tSHORTCUT_IDLE,\n\t\tSHORTCUT_GETTING_IN,\n\t\tSHORTCUT_TRANSITION,\n\t\tSHORTCUT_ARRIVING,\n\t\tSHORTCUT_GETTING_OUT\n\t};\n\n\tstatic void InitAtStartOfGame();\n\tstatic void PassTime(uint32 time);\n\tstatic void SortOutStreamingAndMemory(const CVector &pos);\n\tstatic void Update();\n\tstatic void RestorePlayerStuffDuringResurrection(class CPlayerPed *pPlayerPed, CVector pos, float angle);\n\n\tstatic void ClearShortCut();\n\tstatic void SetUpShortCut(CVector, float, CVector, float);\n\tstatic void AbandonShortCutIfTaxiHasBeenMessedWith();\n\tstatic void AbandonShortCutIfPlayerMilesAway();\n\tstatic void UpdateShortCut();\n\tstatic void AddShortCutPointAfterDeath(CVector, float);\n\tstatic void AddShortCutDropOffPointForMission(CVector, float);\n\tstatic void RemoveShortCutDropOffPointForMission();\n\tstatic void AfterDeathArrestSetUpShortCutTaxi();\n\n\tstatic void Save(uint8*, uint32*);\n\tstatic void Load(uint8*, uint32);\n\n\tstatic uint8 ActivePlayers;\n\tstatic uint8 ShortCutState;\n\tstatic CAutomobile* pShortCutTaxi;\n\tstatic uint32 NumAfterDeathStartPoints;\n\tstatic CVector ShortCutStart;\n\tstatic float ShortCutStartOrientation;\n\tstatic CVector ShortCutDestination;\n\tstatic float ShortCutDestinationOrientation;\n\tstatic uint32 ShortCutTimer;\n\tstatic CVector AfterDeathStartPoints[NUM_SHORTCUT_START_POINTS];\n\tstatic float AfterDeathStartPointOrientation[NUM_SHORTCUT_START_POINTS];\n\tstatic CVector ShortCutDropOffForMission;\n\tstatic float ShortCutDropOffOrientationForMission;\n\tstatic bool MissionDropOffReadyToBeUsed;\n};"
  },
  {
    "path": "src/control/Garages.cpp",
    "content": "#include \"common.h\"\n\n#include \"Garages.h\"\n#include \"main.h\"\n\n#include \"Bike.h\"\n#include \"Boat.h\"\n#include \"DMAudio.h\"\n#include \"General.h\"\n#include \"Font.h\"\n#include \"HandlingMgr.h\"\n#include \"Hud.h\"\n#include \"Messages.h\"\n#include \"ModelIndices.h\"\n#include \"Pad.h\"\n#include \"Particle.h\"\n#include \"PlayerPed.h\"\n#include \"Replay.h\"\n#include \"Stats.h\"\n#include \"Streaming.h\"\n#include \"Text.h\"\n#include \"Timer.h\"\n#include \"Vehicle.h\"\n#include \"Wanted.h\"\n#include \"World.h\"\n#include \"VarConsole.h\"\n\n#define CRUSHER_GARAGE_X1 (1135.5f)\n#define CRUSHER_GARAGE_Y1 (57.0f)\n#define CRUSHER_GARAGE_Z1 (-1.0f)\n#define CRUSHER_GARAGE_X2 (1149.5f)\n#define CRUSHER_GARAGE_Y2 (63.7f)\n#define CRUSHER_GARAGE_Z2 (3.5f)\n\n#define ROTATED_DOOR_OPEN_SPEED (0.015f)\n#define ROTATED_DOOR_CLOSE_SPEED (0.02f)\n#define DEFAULT_DOOR_OPEN_SPEED (0.035f)\n#define DEFAULT_DOOR_CLOSE_SPEED (0.04f)\n#define CRUSHER_CRANE_SPEED (0.005f)\n\n// Prices\n#define BOMB_PRICE (500)\n#define RESPRAY_PRICE (100)\n\n// Distances\n#define DISTANCE_TO_CALL_OFF_CHASE (10.0f)\n#define DISTANCE_FOR_MRWHOOP_HACK (0.5f)\n#define DISTANCE_TO_ACTIVATE_GARAGE (8.0f)\n#define DISTANCE_TO_ACTIVATE_KEEPCAR_GARAGE (17.0f)\n#define DISTANCE_TO_CLOSE_MISSION_GARAGE (30.0f)\n#define DISTANCE_TO_CLOSE_COLLECTSPECIFICCARS_GARAGE (25.0f)\n#define DISTANCE_TO_CLOSE_COLLECTCARS_GARAGE (40.0f)\n#define DISTANCE_TO_CLOSE_HIDEOUT_GARAGE_ON_FOOT (3.2f)\n#define DISTANCE_TO_CLOSE_HIDEOUT_GARAGE_IN_CAR (15.0f)\n#define DISTANCE_TO_FORCE_CLOSE_HIDEOUT_GARAGE (70.0f)\n#define DISTANCE_TO_OPEN_HIDEOUT_GARAGE_ON_FOOT (2.8f)\n#define DISTANCE_TO_OPEN_HIDEOUT_GARAGE_IN_CAR (10.0f)\n#define DISTANCE_TO_SHOW_HIDEOUT_MESSAGE (5.0f)\n\n#define DISTANCE_TO_CONSIDER_DOOR_FOR_GARAGE (20.0f)\n\n// Time\n#define TIME_TO_RESPRAY (2000)\n#define TIME_TO_SETUP_BOMB (2000)\n#define TIME_TO_CRUSH_CAR (3000)\n#define TIME_TO_PROCESS_KEEPCAR_GARAGE (2000)\n\n// Respray stuff\n#define FREE_RESPRAY_HEALTH_THRESHOLD (970.0f)\n#define NUM_PARTICLES_IN_RESPRAY (200)\n#define RESPRAY_CENTERING_COEFFICIENT (0.4f)\n\n// Bomb stuff\n#define KGS_OF_EXPLOSIVES_IN_BOMB (10)\n\n// Collect specific cars stuff\n#define REWARD_FOR_FIRST_POLICE_CAR (5000)\n#define REWARD_FOR_FIRST_BANK_VAN (5000)\n#define MAX_POLICE_CARS_TO_COLLECT (10)\n#define MAX_BANK_VANS_TO_COLLECT (10)\n\n// Collect cars stuff\n#define MAX_SPEED_TO_SHOW_COLLECTED_MESSAGE (0.03f)\n#define IMPORT_REWARD (500)\n#define IMPORT_ALLCARS_REWARD (20500)\n\n// Crusher stuff\n#define CRUSHER_VEHICLE_TEST_SPAN (8)\n#define CRUSHER_MIN_REWARD (25)\n#define CRUSHER_MAX_REWARD (125)\n#define CRUSHER_REWARD_COEFFICIENT (1.0f/500000)\n\n// Hideout stuff\n#define HIDEOUT_DOOR_SPEED_COEFFICIENT (1.7f)\n#define TIME_BETWEEN_HIDEOUT_MESSAGES (18000)\n\n// Camera stuff\n#define MARGIN_FOR_CAMERA_COLLECTCARS (0.5f)\n#define MARGIN_FOR_CAMERA_DEFAULT (0.5f)\n\nconst int32 gaCarsToCollectInCraigsGarages[TOTAL_COLLECTCARS_GARAGES][TOTAL_COLLECTCARS_CARS] =\n{\n\t{ MI_LANDSTAL, MI_IDAHO,    MI_ESPERANT, MI_STALLION, MI_RANCHER, MI_BLISTAC  },\n\t{ MI_SABRE,    MI_VIRGO,    MI_SENTINEL, MI_STRETCH,  MI_WASHING, MI_ADMIRAL  },\n\t{ MI_CHEETAH,  MI_INFERNUS, MI_BANSHEE,  MI_PHEONIX,  MI_COMET,   MI_STINGER  },\n\t{ MI_VOODOO,   MI_CUBAN,    MI_CADDY,    MI_BAGGAGE,  MI_MRWHOOP, MI_PIZZABOY }\n};\n\nconst int32 gaCarsToCollectIn60Seconds[] = { MI_CHEETAH, MI_TAXI, MI_ESPERANT, MI_SENTINEL, MI_IDAHO };\n\nint32 CGarages::BankVansCollected;\nbool CGarages::BombsAreFree;\nbool CGarages::RespraysAreFree;\nint32 CGarages::CarsCollected;\nint32 CGarages::CarTypesCollected[TOTAL_COLLECTCARS_GARAGES];\nint32 CGarages::CrushedCarId;\nuint32 CGarages::LastTimeHelpMessage;\nint32 CGarages::MessageNumberInString;\nchar CGarages::MessageIDString[MESSAGE_LENGTH];\nint32 CGarages::MessageNumberInString2;\nuint32 CGarages::MessageStartTime;\nuint32 CGarages::MessageEndTime;\nuint32 CGarages::NumGarages;\nbool CGarages::PlayerInGarage;\nint32 CGarages::PoliceCarsCollected;\nCStoredCar CGarages::aCarsInSafeHouses[TOTAL_HIDEOUT_GARAGES][NUM_GARAGE_STORED_CARS];\nint32 hGarages = AEHANDLE_NONE;\nCGarage CGarages::aGarages[NUM_GARAGES];\nbool CGarages::bCamShouldBeOutisde;\n\n#ifndef MASTER\nbool bPrintNearestObject;\n#endif\n\nvoid CGarages::Init(void)\n{\n#ifndef MASTER\n\tVarConsole.Add(\"Print nearest object\", &bPrintNearestObject, true);\n#endif\n\tCrushedCarId = -1;\n\tNumGarages = 0;\n\tMessageEndTime = 0;\n\tMessageStartTime = 0;\n\tPlayerInGarage = false;\n\tBombsAreFree = false;\n#ifdef FIX_BUGS\n\tRespraysAreFree = false;\n#endif\n\tCarsCollected = 0;\n\tBankVansCollected = 0;\n\tPoliceCarsCollected = 0;\n\tfor (int i = 0; i < TOTAL_COLLECTCARS_GARAGES; i++)\n\t\tCarTypesCollected[i] = 0;\n\tLastTimeHelpMessage = 0;\n\tfor (int i = 0; i < NUM_GARAGE_STORED_CARS; i++) {\n\t\tfor (int j = 0; j < TOTAL_HIDEOUT_GARAGES; j++)\n\t\t\taCarsInSafeHouses[j][i].Init();\n\t}\n\thGarages = DMAudio.CreateEntity(AUDIOTYPE_GARAGE, (void*)1);\n\tif (hGarages >= 0)\n\t\tDMAudio.SetEntityStatus(hGarages, true);\n}\n\nvoid CGarages::Shutdown(void)\n{\n\tNumGarages = 0;\n\tif (hGarages < 0)\n\t\treturn;\n\tDMAudio.DestroyEntity(hGarages);\n\thGarages = AEHANDLE_NONE;\n}\n\nvoid CGarages::Update(void)\n{\n\tstatic uint32 GarageToBeTidied = 0;\n\tif (CReplay::IsPlayingBack())\n\t\treturn;\n#ifdef SECUROM\n\textern uint8 gameProcessPirateCheck;\n\tif (gameProcessPirateCheck == 2) return;\n#endif\n\tbCamShouldBeOutisde = false;\n\tTheCamera.pToGarageWeAreIn = nil;\n\tTheCamera.pToGarageWeAreInForHackAvoidFirstPerson = nil;\n#ifdef FIX_BUGS\n\tfor (uint32 i = 0; i < NumGarages; i++) {\n#else\n\tfor (int i = 0; i < NUM_GARAGES; i++) {\n#endif\n\t\tif (aGarages[i].IsUsed())\n\t\t\taGarages[i].Update();\n\t}\n\tif ((CTimer::GetFrameCounter() & 0xF) != 0xC)\n\t\treturn;\n#ifdef FIX_BUGS\n\tif (++GarageToBeTidied >= NumGarages)\n#else\n\tif (++GarageToBeTidied >= NUM_GARAGES)\n#endif\n\t\tGarageToBeTidied = 0;\n\tif (!aGarages[GarageToBeTidied].IsUsed())\n\t\treturn;\n\tif (!aGarages[GarageToBeTidied].IsFar())\n\t\taGarages[GarageToBeTidied].TidyUpGarageClose();\n\telse\n\t\taGarages[GarageToBeTidied].TidyUpGarage();\n}\n\nint16 CGarages::AddOne(float X1, float Y1, float Z1, float X2, float Y2, float X3, float Y3, float Z2, uint8 type, int32 targetId)\n{\n\tif (NumGarages >= NUM_GARAGES) {\n\t\tassert(0);\n\t\treturn NumGarages++;\n\t}\n\tCGarage* pGarage = &aGarages[NumGarages];\n\tpGarage->m_fInfX = Min(Min(Min(X1, X2), X3), X2 + X3 - X1);\n\tpGarage->m_fSupX = Max(Max(X1, X2), X3);\n\tpGarage->m_fInfY = Min(Min(Min(Y1, Y2), Y3), Y2 + Y3 - Y1);\n\tpGarage->m_fSupY = Max(Max(Y1, Y2), Y3);\n\tpGarage->m_vecCorner1 = CVector(X1, Y1, Z1);\n\tpGarage->m_fInfZ = Z1;\n\tpGarage->m_vDir1 = CVector2D(X2 - X1, Y2 - Y1);\n\tpGarage->m_vDir2 = CVector2D(X3 - X1, Y3 - Y1);\n\tpGarage->m_fSupZ = Z2;\n\tpGarage->m_nMaxStoredCars = NUM_GARAGE_STORED_CARS;\n\tpGarage->m_fDir1Len = pGarage->m_vDir1.Magnitude();\n\tpGarage->m_fDir2Len = pGarage->m_vDir2.Magnitude();\n\tpGarage->m_vDir1 /= pGarage->m_fDir1Len;\n\tpGarage->m_vDir2 /= pGarage->m_fDir2Len;\n\tpGarage->m_pDoor1 = nil;\n\tpGarage->m_pDoor2 = nil;\n\tpGarage->m_fDoor1Z = Z1;\n\tpGarage->m_fDoor2Z = Z1;\n\tpGarage->m_eGarageType = type;\n\tpGarage->m_bRecreateDoorOnNextRefresh = false;\n\tpGarage->m_bRotatedDoor = false;\n\tpGarage->m_bCameraFollowsPlayer = false;\n\tpGarage->RefreshDoorPointers(true);\n\tif (pGarage->m_pDoor1) {\n\t\tpGarage->m_fDoor1Z = pGarage->m_pDoor1->GetPosition().z;\n\t\tpGarage->m_fDoor1X = pGarage->m_pDoor1->GetPosition().x;\n\t\tpGarage->m_fDoor1Y = pGarage->m_pDoor1->GetPosition().y;\n\t}\n\tif (pGarage->m_pDoor2) {\n\t\tpGarage->m_fDoor2Z = pGarage->m_pDoor2->GetPosition().z;\n\t\tpGarage->m_fDoor2X = pGarage->m_pDoor2->GetPosition().x;\n\t\tpGarage->m_fDoor2Y = pGarage->m_pDoor2->GetPosition().y;\n\t}\n\tpGarage->m_fDoorHeight = pGarage->m_pDoor1 ? FindDoorHeightForMI(pGarage->m_pDoor1->GetModelIndex()) : 4.0f;\n\tpGarage->m_fDoorPos = 0.0f;\n\tpGarage->m_eGarageState = GS_FULLYCLOSED;\n\tpGarage->m_nTimeToStartAction = 0;\n\tpGarage->field_2 = false;\n\tpGarage->m_nTargetModelIndex = targetId;\n\tpGarage->m_bCollectedCarsState = 0;\n\tpGarage->m_bDeactivated = false;\n\tpGarage->m_bResprayHappened = false;\n\tswitch (type) {\n\tcase GARAGE_MISSION:\n\tcase GARAGE_COLLECTORSITEMS:\n\tcase GARAGE_COLLECTSPECIFICCARS:\n\tcase GARAGE_COLLECTCARS_1:\n\tcase GARAGE_COLLECTCARS_2:\n\tcase GARAGE_COLLECTCARS_3:\n\tcase GARAGE_FORCARTOCOMEOUTOF:\n\tcase GARAGE_60SECONDS:\n\tcase GARAGE_MISSION_KEEPCAR:\n\tcase GARAGE_FOR_SCRIPT_TO_OPEN:\n\tcase GARAGE_HIDEOUT_ONE:\n\tcase GARAGE_HIDEOUT_TWO:\n\tcase GARAGE_HIDEOUT_THREE:\n\tcase GARAGE_FOR_SCRIPT_TO_OPEN_AND_CLOSE:\n\tcase GARAGE_KEEPS_OPENING_FOR_SPECIFIC_CAR:\n\tcase GARAGE_MISSION_KEEPCAR_REMAINCLOSED:\n\tcase GARAGE_COLLECTCARS_4:\n\tcase GARAGE_FOR_SCRIPT_TO_OPEN_FOR_CAR:\n\tcase GARAGE_HIDEOUT_FOUR:\n\tcase GARAGE_HIDEOUT_FIVE:\n\tcase GARAGE_HIDEOUT_SIX:\n\tcase GARAGE_HIDEOUT_SEVEN:\n\tcase GARAGE_HIDEOUT_EIGHT:\n\tcase GARAGE_HIDEOUT_NINE:\n\tcase GARAGE_HIDEOUT_TEN:\n\tcase GARAGE_HIDEOUT_ELEVEN:\n\tcase GARAGE_HIDEOUT_TWELVE:\n\t\tpGarage->m_eGarageState = GS_FULLYCLOSED;\n\t\tpGarage->m_fDoorPos = 0.0f;\n\t\tbreak;\n\tcase GARAGE_BOMBSHOP1:\n\tcase GARAGE_BOMBSHOP2:\n\tcase GARAGE_BOMBSHOP3:\n\tcase GARAGE_RESPRAY:\n\t\tpGarage->m_eGarageState = GS_OPENED;\n\t\tpGarage->m_fDoorPos = pGarage->m_fDoorHeight;\n\t\tbreak;\n\tcase GARAGE_CRUSHER:\n\t\tpGarage->m_eGarageState = GS_OPENED;\n\t\tpGarage->m_fDoorPos = HALFPI;\n\t\tbreak;\n\tdefault:\n\t\tassert(false);\n\t}\n\tif (type == GARAGE_CRUSHER)\n\t\tpGarage->UpdateCrusherAngle();\n\telse\n\t\tpGarage->UpdateDoorsHeight();\n\treturn NumGarages++;\n}\n\nvoid CGarages::ChangeGarageType(int16 garage, uint8 type, int32 mi)\n{\n\tCGarage* pGarage = &aGarages[garage];\n\tpGarage->m_eGarageType = type;\n\tpGarage->m_nTargetModelIndex = mi;\n\tpGarage->m_eGarageState = GS_FULLYCLOSED;\n}\n\nvoid CGarage::Update()\n{\n\tif (m_eGarageType != GARAGE_CRUSHER) {\n\t\tswitch (m_eGarageState) {\n\t\tcase GS_FULLYCLOSED:\n\t\tcase GS_OPENED:\n\t\tcase GS_CLOSING:\n\t\tcase GS_OPENING:\n\t\tcase GS_OPENEDCONTAINSCAR:\n\t\tcase GS_CLOSEDCONTAINSCAR:\n\t\t\tif (FindPlayerPed() && !m_bCameraFollowsPlayer) {\n\t\t\t\tCVehicle* pVehicle = FindPlayerVehicle();\n\t\t\t\tif (IsEntityEntirelyInside3D(FindPlayerPed(), 0.25f)) {\n\t\t\t\t\tTheCamera.pToGarageWeAreIn = this;\n\t\t\t\t\tCGarages::bCamShouldBeOutisde = true;\n\t\t\t\t}\n\t\t\t\tif (pVehicle) {\n\t\t\t\t\tif (!IsEntityEntirelyOutside(pVehicle, 0.0f))\n\t\t\t\t\t\tTheCamera.pToGarageWeAreInForHackAvoidFirstPerson = this;\n\t\t\t\t\tif (pVehicle->GetModelIndex() == MI_MRWHOOP) {\n\t\t\t\t\t\tif (pVehicle->IsWithinArea(\n\t\t\t\t\t\t\tm_fInfX - DISTANCE_FOR_MRWHOOP_HACK,\n\t\t\t\t\t\t\tm_fInfY - DISTANCE_FOR_MRWHOOP_HACK,\n\t\t\t\t\t\t\tm_fSupX + DISTANCE_FOR_MRWHOOP_HACK,\n\t\t\t\t\t\t\tm_fSupY + DISTANCE_FOR_MRWHOOP_HACK)) {\n\t\t\t\t\t\t\tTheCamera.pToGarageWeAreIn = this;\n\t\t\t\t\t\t\tCGarages::bCamShouldBeOutisde = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\t}\n\tif (m_bDeactivated && m_eGarageState == GS_FULLYCLOSED)\n\t\treturn;\n\tif (m_bRotatedDoor) {\n#ifdef GTA_PS2\n\t\tif (m_eGarageState == GS_OPENING) {\n\t\t\tif (m_pDoor1) {\n\t\t\t\tif (FindPlayerPed()->m_pCurrentPhysSurface == m_pDoor1)\n\t\t\t\t\tm_pDoor1->bUsesCollision = false;\n\t\t\t}\n\t\t\tif (m_pDoor2) {\n\t\t\t\tif (FindPlayerPed()->m_pCurrentPhysSurface == m_pDoor2)\n\t\t\t\t\tm_pDoor2->bUsesCollision = false;\n\t\t\t}\n\t\t}\n\t\telse if (m_eGarageState == GS_OPENED) {\n\t\t\tif (m_pDoor1)\n\t\t\t\tm_pDoor1->bUsesCollision = true;\n\t\t\tif (m_pDoor2)\n\t\t\t\tm_pDoor2->bUsesCollision = true;\n\t\t}\n#else\n\t\tif (m_eGarageState == GS_OPENING || m_eGarageState == GS_OPENED) {\n\t\t\tif (m_pDoor1) {\n\t\t\t\tif (FindPlayerPed()->m_pCurrentPhysSurface == m_pDoor1 || FindPlayerPed()->GetPedState() == PED_JUMP || FindPlayerPed()->GetPedState() == PED_FALL || !FindPlayerPed()->bIsStanding)\n\t\t\t\t\tm_pDoor1->bUsesCollision = false;\n\t\t\t}\n\t\t\tif (m_pDoor2) {\n\t\t\t\tif (FindPlayerPed()->m_pCurrentPhysSurface == m_pDoor2 || FindPlayerPed()->GetPedState() == PED_JUMP || FindPlayerPed()->GetPedState() == PED_FALL || !FindPlayerPed()->bIsStanding)\n\t\t\t\t\tm_pDoor2->bUsesCollision = false;\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tif (m_pDoor1)\n\t\t\t\tm_pDoor1->bUsesCollision = true;\n\t\t\tif (m_pDoor2)\n\t\t\t\tm_pDoor2->bUsesCollision = true;\n\t\t}\n#endif\n\t}\n\tswitch (m_eGarageType) {\n\tcase GARAGE_RESPRAY:\n\t\tswitch (m_eGarageState) {\n\t\tcase GS_OPENED:\n\t\t\tif (IsStaticPlayerCarEntirelyInside()) {\n\t\t\t\tif (CGarages::IsCarSprayable(FindPlayerVehicle())) {\n\t\t\t\t\tif (CWorld::Players[CWorld::PlayerInFocus].m_nMoney >= RESPRAY_PRICE || CGarages::RespraysAreFree) {\n\t\t\t\t\t\tm_eGarageState = GS_CLOSING;\n\t\t\t\t\t\tCPad::GetPad(0)->SetDisablePlayerControls(PLAYERCONTROL_GARAGE);\n\t\t\t\t\t\tFindPlayerPed()->m_pWanted->m_bIgnoredByCops = true;\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tCGarages::TriggerMessage(\"GA_3\", -1, 4000, -1); // No more freebies. $100 to respray!\n\t\t\t\t\t\tm_eGarageState = GS_OPENEDCONTAINSCAR;\n\t\t\t\t\t\tDMAudio.PlayFrontEndSound(SOUND_GARAGE_NO_MONEY, 1);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tCGarages::TriggerMessage(\"GA_1\", -1, 4000, -1); // Whoa! I don't touch nothing THAT hot!\n\t\t\t\t\tm_eGarageState = GS_OPENEDCONTAINSCAR;\n\t\t\t\t\tDMAudio.PlayFrontEndSound(SOUND_GARAGE_BAD_VEHICLE, 1);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (FindPlayerVehicle()) {\n\t\t\t\tif (CalcDistToGarageRectangleSquared(FindPlayerVehicle()->GetPosition().x, FindPlayerVehicle()->GetPosition().y) < SQR(DISTANCE_TO_ACTIVATE_GARAGE))\n\t\t\t\t\tCWorld::CallOffChaseForArea(\n\t\t\t\t\t\tm_fInfX - DISTANCE_TO_CALL_OFF_CHASE,\n\t\t\t\t\t\tm_fInfY - DISTANCE_TO_CALL_OFF_CHASE,\n\t\t\t\t\t\tm_fSupX + DISTANCE_TO_CALL_OFF_CHASE,\n\t\t\t\t\t\tm_fSupY + DISTANCE_TO_CALL_OFF_CHASE);\n\t\t\t}\n\t\t\tbreak;\n\t\tcase GS_CLOSING:\n\t\t\tif (FindPlayerVehicle())\n\t\t\t\tThrowCarsNearDoorOutOfGarage(FindPlayerVehicle());\n\t\t\tm_fDoorPos = Max(0.0f, m_fDoorPos - (m_bRotatedDoor ? ROTATED_DOOR_CLOSE_SPEED : DEFAULT_DOOR_CLOSE_SPEED) * CTimer::GetTimeStep());\n\t\t\tif (m_fDoorPos == 0.0f) {\n\t\t\t\tm_eGarageState = GS_FULLYCLOSED;\n\t\t\t\tm_nTimeToStartAction = CTimer::GetTimeInMilliseconds() + TIME_TO_RESPRAY;\n\t\t\t\tDMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_CLOSED, 1.0f);\n\t\t\t\tCStats::CheckPointReachedSuccessfully();\n\t\t\t}\n\t\t\tUpdateDoorsHeight();\n#ifdef FIX_BUGS\n\t\t\tif (FindPlayerVehicle() && FindPlayerVehicle()->IsCar())\n#else\n\t\t\tif (FindPlayerVehicle())\n#endif\n\t\t\t\t((CAutomobile*)(FindPlayerVehicle()))->m_fFireBlowUpTimer = 0.0f;\n\t\t\tCWorld::CallOffChaseForArea(\n\t\t\t\tm_fInfX - DISTANCE_TO_CALL_OFF_CHASE,\n\t\t\t\tm_fInfY - DISTANCE_TO_CALL_OFF_CHASE,\n\t\t\t\tm_fSupX + DISTANCE_TO_CALL_OFF_CHASE,\n\t\t\t\tm_fSupY + DISTANCE_TO_CALL_OFF_CHASE);\n\t\t\tbreak;\n\t\tcase GS_FULLYCLOSED:\n\t\t\tif (CTimer::GetTimeInMilliseconds() > m_nTimeToStartAction) {\n\t\t\t\tm_eGarageState = GS_OPENING;\n\t\t\t\tDMAudio.PlayFrontEndSound(SOUND_GARAGE_OPENING, 1);\n\t\t\t\tbool bTakeMoney = false;\n\t\t\t\tif (FindPlayerPed()->m_pWanted->GetWantedLevel() != 0) {\n\t\t\t\t\tbTakeMoney = true;\n\t\t\t\t\tFindPlayerPed()->m_pWanted->Suspend();\n\t\t\t\t}\n\t\t\t\tCPad::GetPad(0)->SetEnablePlayerControls(PLAYERCONTROL_GARAGE);\n\t\t\t\tFindPlayerPed()->m_pWanted->m_bIgnoredByCops = false;\n#ifdef FIX_BUGS\n\t\t\t\tbool bChangedColour = false;\n#else\n\t\t\t\tbool bChangedColour;\n#endif\n\t\t\t\tif (FindPlayerVehicle() && (FindPlayerVehicle()->IsCar() || FindPlayerVehicle()->IsBike())) {\n\t\t\t\t\tif (FindPlayerVehicle()->m_fHealth < FREE_RESPRAY_HEALTH_THRESHOLD)\n\t\t\t\t\t\tbTakeMoney = true;\n\t\t\t\t\tFindPlayerVehicle()->m_fHealth = 1000.0f;\n\t\t\t\t\tif (FindPlayerVehicle()->IsCar()) {\n\t\t\t\t\t\t((CAutomobile*)(FindPlayerVehicle()))->m_fFireBlowUpTimer = 0.0f;\n\t\t\t\t\t\t((CAutomobile*)(FindPlayerVehicle()))->Fix();\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\t((CBike*)(FindPlayerVehicle()))->m_fFireBlowUpTimer = 0.0f;\n\t\t\t\t\t\t((CBike*)(FindPlayerVehicle()))->Fix();\n\t\t\t\t\t}\n\t\t\t\t\tFindPlayerVehicle()->m_nDoorLock = CARLOCK_UNLOCKED;\n\t\t\t\t\t++CStats::Sprayings;\n\t\t\t\t\tif (FindPlayerVehicle()->GetUp().z < 0.0f) {\n\t\t\t\t\t\tFindPlayerVehicle()->GetUp() = -FindPlayerVehicle()->GetUp();\n\t\t\t\t\t\tFindPlayerVehicle()->GetRight() = -FindPlayerVehicle()->GetRight();\n\t\t\t\t\t}\n\t\t\t\t\tbChangedColour = false;\n#ifdef FIX_BUGS\n\t\t\t\t\tif (!FindPlayerVehicle()->IsCar() || !((CAutomobile*)(FindPlayerVehicle()))->bFixedColour) {\n#else\n\t\t\t\t\tif (!((CAutomobile*)(FindPlayerVehicle()))->bFixedColour) {\n#endif\n\t\t\t\t\t\tuint8 colour1, colour2;\n\t\t\t\t\t\tuint16 attempt;\n\t\t\t\t\t\tFindPlayerVehicle()->GetModelInfo()->ChooseVehicleColour(colour1, colour2);\n\t\t\t\t\t\tfor (attempt = 0; attempt < 10; attempt++) {\n\t\t\t\t\t\t\tif (colour1 != FindPlayerVehicle()->m_currentColour1 || colour2 != FindPlayerVehicle()->m_currentColour2)\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tFindPlayerVehicle()->GetModelInfo()->ChooseVehicleColour(colour1, colour2);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbChangedColour = (attempt < 10);\n\t\t\t\t\t\tFindPlayerVehicle()->m_currentColour1 = colour1;\n\t\t\t\t\t\tFindPlayerVehicle()->m_currentColour2 = colour2;\n\t\t\t\t\t\tif (bChangedColour) {\n\t\t\t\t\t\t\tfor (int i = 0; i < NUM_PARTICLES_IN_RESPRAY; i++) {\n\t\t\t\t\t\t\t\tCVector pos;\n\t\t\t\t\t\t\t\tpos.x = CGeneral::GetRandomNumberInRange(m_fInfX + 0.5f, m_fSupX - 0.5f);\n\t\t\t\t\t\t\t\tpos.y = CGeneral::GetRandomNumberInRange(m_fInfY + 0.5f, m_fSupY - 0.5f);\n\t\t\t\t\t\t\t\tpos.z = CGeneral::GetRandomNumberInRange(m_fDoor1Z - 3.0f, m_fDoor1Z + 1.0f);\n\t\t\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_GARAGEPAINT_SPRAY, pos, CVector(0.0f, 0.0f, 0.0f), nil, 0.0f, CVehicleModelInfo::ms_vehicleColourTable[colour1]);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tCenterCarInGarage(FindPlayerVehicle());\n\t\t\t\t}\n\t\t\t\tif (bTakeMoney) {\n\t\t\t\t\tif (!CGarages::RespraysAreFree) {\n\t\t\t\t\t\tCWorld::Players[CWorld::PlayerInFocus].m_nMoney = Max(0, CWorld::Players[CWorld::PlayerInFocus].m_nMoney - RESPRAY_PRICE);\n\t\t\t\t\t\tCStats::AutoPaintingBudget += RESPRAY_PRICE;\n\t\t\t\t\t}\n\t\t\t\t\tCGarages::TriggerMessage(\"GA_2\", -1, 4000, -1); // New engine and paint job. The cops won't recognize you!\n\t\t\t\t}\n\t\t\t\telse if (bChangedColour) {\n\t\t\t\t\tif (CGeneral::GetRandomTrueFalse())\n\t\t\t\t\t\tCGarages::TriggerMessage(\"GA_15\", -1, 4000, -1); // Hope you like the new color.\n\t\t\t\t\telse\n\t\t\t\t\t\tCGarages::TriggerMessage(\"GA_16\", -1, 4000, -1); // Respray is complementary.\n\t\t\t\t}\n\t\t\t\tm_bResprayHappened = true;\n\t\t\t}\n\t\t\tCWorld::CallOffChaseForArea(\n\t\t\t\tm_fInfX - DISTANCE_TO_CALL_OFF_CHASE,\n\t\t\t\tm_fInfY - DISTANCE_TO_CALL_OFF_CHASE,\n\t\t\t\tm_fSupX + DISTANCE_TO_CALL_OFF_CHASE,\n\t\t\t\tm_fSupY + DISTANCE_TO_CALL_OFF_CHASE);\n\t\t\tbreak;\n\t\tcase GS_OPENING:\n\t\t\tm_fDoorPos = Min(m_fDoorHeight, m_fDoorPos + (m_bRotatedDoor ? ROTATED_DOOR_OPEN_SPEED : DEFAULT_DOOR_OPEN_SPEED) * CTimer::GetTimeStep());\n\t\t\tif (m_fDoorPos == m_fDoorHeight) {\n\t\t\t\tm_eGarageState = GS_OPENEDCONTAINSCAR;\n\t\t\t\tDMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_OPENED, 1.0f);\n\t\t\t}\n\t\t\tUpdateDoorsHeight();\n\t\t\tbreak;\n\t\tcase GS_OPENEDCONTAINSCAR:\n\t\t\tif (IsPlayerOutsideGarage())\n\t\t\t\tm_eGarageState = GS_OPENED;\n\t\t\tbreak;\n\t\t//case GS_CLOSEDCONTAINSCAR:\n\t\t//case GS_AFTERDROPOFF:\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\t\tbreak;\n\tcase GARAGE_BOMBSHOP1:\n\tcase GARAGE_BOMBSHOP2:\n\tcase GARAGE_BOMBSHOP3:\n\t\tswitch (m_eGarageState) {\n\t\tcase GS_OPENED:\n\t\t\tif (IsStaticPlayerCarEntirelyInside()) {\n\t\t\t\tif (!FindPlayerVehicle() || FindPlayerVehicle()->m_bombType) {\n\t\t\t\t\tCGarages::TriggerMessage(\"GA_5\", -1, 4000, -1); //\"Your car is already fitted with a bomb\"\n\t\t\t\t\tm_eGarageState = GS_OPENEDCONTAINSCAR;\n\t\t\t\t\tDMAudio.PlayFrontEndSound(SOUND_GARAGE_BOMB_ALREADY_SET, 1);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif (!CGarages::BombsAreFree && CWorld::Players[CWorld::PlayerInFocus].m_nMoney < BOMB_PRICE) {\n\t\t\t\t\tCGarages::TriggerMessage(\"GA_4\", -1, 4000, -1); // \"Car bombs are $1000 each\" - weird that the price is hardcoded in message\n\t\t\t\t\tm_eGarageState = GS_OPENEDCONTAINSCAR;\n\t\t\t\t\tDMAudio.PlayFrontEndSound(SOUND_GARAGE_NO_MONEY, 1);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tm_eGarageState = GS_CLOSING;\n\t\t\t\tCPad::GetPad(0)->SetDisablePlayerControls(PLAYERCONTROL_GARAGE);\n\t\t\t\tFindPlayerPed()->m_pWanted->m_bIgnoredByCops = true;\n\t\t\t\t}\n\t\t\tbreak;\n\t\tcase GS_CLOSING:\n\t\t\tif (FindPlayerVehicle())\n\t\t\t\tThrowCarsNearDoorOutOfGarage(FindPlayerVehicle());\n\t\t\tm_fDoorPos = Max(0.0f, m_fDoorPos - (m_bRotatedDoor ? ROTATED_DOOR_CLOSE_SPEED : DEFAULT_DOOR_CLOSE_SPEED) * CTimer::GetTimeStep());\n\t\t\tif (m_fDoorPos == 0.0f) {\n\t\t\t\tm_eGarageState = GS_FULLYCLOSED;\n\t\t\t\tm_nTimeToStartAction = CTimer::GetTimeInMilliseconds() + TIME_TO_SETUP_BOMB;\n\t\t\t\tDMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_CLOSED, 1.0f);\n\t\t\t}\n\t\t\tUpdateDoorsHeight();\n\t\t\tif (m_eGarageType == GARAGE_BOMBSHOP3)\n\t\t\t\tCStreaming::RequestModel(MI_BOMB, STREAMFLAGS_DONT_REMOVE);\n\t\t\tbreak;\n\t\tcase GS_FULLYCLOSED:\n\t\t\tif (CTimer::GetTimeInMilliseconds() > m_nTimeToStartAction) {\n\t\t\t\tif (m_eGarageType != GARAGE_BOMBSHOP3 || CStreaming::HasModelLoaded(MI_BOMB)) {\n\t\t\t\t\tswitch (m_eGarageType) {\n\t\t\t\t\tcase GARAGE_BOMBSHOP1: DMAudio.PlayFrontEndSound(SOUND_GARAGE_BOMB1_SET, 1); break;\n\t\t\t\t\tcase GARAGE_BOMBSHOP2: DMAudio.PlayFrontEndSound(SOUND_GARAGE_BOMB2_SET, 1); break;\n\t\t\t\t\tcase GARAGE_BOMBSHOP3: DMAudio.PlayFrontEndSound(SOUND_GARAGE_BOMB3_SET, 1); break;\n\t\t\t\t\t}\n\t\t\t\t\tm_eGarageState = GS_OPENING;\n\t\t\t\t\tif (!CGarages::BombsAreFree)\n\t\t\t\t\t\tCWorld::Players[CWorld::PlayerInFocus].m_nMoney = Max(0, CWorld::Players[CWorld::PlayerInFocus].m_nMoney - BOMB_PRICE);\n\t\t\t\t\tif (FindPlayerVehicle() && (FindPlayerVehicle()->IsCar() || FindPlayerVehicle()->IsBike())) {\n#if (!defined GTA_PS2 || defined FIX_BUGS)\n\t\t\t\t\t\tFindPlayerVehicle()->m_bombType = CGarages::GetBombTypeForGarageType(m_eGarageType);\n\t\t\t\t\t\tFindPlayerVehicle()->m_pBombRigger = FindPlayerPed();\n#else // PS2 version contained a bug: CBike was casted to CAutomobile, but due to coincidence it didn't corrupt memory\n\t\t\t\t\t\t((CAutomobile*)(FindPlayerVehicle()))->m_bombType = CGarages::GetBombTypeForGarageType(m_eGarageType);\n\t\t\t\t\t\t((CAutomobile*)(FindPlayerVehicle()))->m_pBombRigger = FindPlayerPed();\n#endif\n\t\t\t\t\t\tif (m_eGarageType == GARAGE_BOMBSHOP3)\n\t\t\t\t\t\t\tCGarages::GivePlayerDetonator();\n\t\t\t\t\t\tCStats::KgsOfExplosivesUsed += KGS_OF_EXPLOSIVES_IN_BOMB;\n\t\t\t\t\t}\n#ifdef DETECT_PAD_INPUT_SWITCH\n\t\t\t\t\tint16 Mode = CPad::IsAffectedByController ? CPad::GetPad(0)->Mode : 0;\n#else\n\t\t\t\t\tint16 Mode = CPad::GetPad(0)->Mode;\n#endif\n\t\t\t\t\tswitch (m_eGarageType) {\n\t\t\t\t\tcase GARAGE_BOMBSHOP1:\n\t\t\t\t\t\tswitch (Mode) {\n\t\t\t\t\t\tcase 0:\n\t\t\t\t\t\tcase 1:\n\t\t\t\t\t\tcase 2:\n\t\t\t\t\t\t\tCHud::SetHelpMessage(TheText.Get(\"GA_6\"), false); // Arm with ~h~~k~~PED_FIREWEAPON~ button~w~. Bomb will go off when engine is started.\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 3:\n\t\t\t\t\t\t\tCHud::SetHelpMessage(TheText.Get(\"GA_6B\"), false); // Arm with ~h~~k~~PED_FIREWEAPON~ button~w~. Bomb will go off when engine is started.\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase GARAGE_BOMBSHOP2:\n\t\t\t\t\t\tswitch (Mode) {\n\t\t\t\t\t\tcase 0:\n\t\t\t\t\t\tcase 1:\n\t\t\t\t\t\tcase 2:\n\t\t\t\t\t\t\tCHud::SetHelpMessage(TheText.Get(\"GA_7\"), false); // Park it, prime it by pressing the ~h~~k~~PED_FIREWEAPON~ button~w~ and LEG IT!\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 3:\n\t\t\t\t\t\t\tCHud::SetHelpMessage(TheText.Get(\"GA_7B\"), false); // Park it, prime it by pressing the ~h~~k~~PED_FIREWEAPON~ button~w~ and LEG IT!\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase GARAGE_BOMBSHOP3:\n\t\t\t\t\t\tCHud::SetHelpMessage(TheText.Get(\"GA_8\"), false); // Use the detonator to activate the bomb.\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tCPad::GetPad(0)->SetEnablePlayerControls(PLAYERCONTROL_GARAGE);\n\t\t\t\t\tFindPlayerPed()->m_pWanted->m_bIgnoredByCops = false;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tCStreaming::RequestModel(MI_BOMB, STREAMFLAGS_DONT_REMOVE);\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\tcase GS_OPENING:\n\t\t\tm_fDoorPos = Min(m_fDoorHeight, m_fDoorPos + (m_bRotatedDoor ? ROTATED_DOOR_OPEN_SPEED : DEFAULT_DOOR_OPEN_SPEED) * CTimer::GetTimeStep());\n\t\t\tif (m_fDoorPos == m_fDoorHeight) {\n\t\t\t\tm_eGarageState = GS_OPENEDCONTAINSCAR;\n\t\t\t\tDMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_OPENED, 1.0f);\n\t\t\t}\n\t\t\tUpdateDoorsHeight();\n\t\t\tbreak;\n\t\tcase GS_OPENEDCONTAINSCAR:\n\t\t\tif (IsPlayerOutsideGarage())\n\t\t\t\tm_eGarageState = GS_OPENED;\n\t\t\tbreak;\n\t\t//case GS_CLOSEDCONTAINSCAR:\n\t\t//case GS_AFTERDROPOFF:\n\t\tdefault:\n\t\t\tbreak;\n\t\t\t}\n\t\tbreak;\n\tcase GARAGE_MISSION:\n\t\tswitch (m_eGarageState) {\n\t\tcase GS_OPENED:\n\t\t\tif (((CVector2D)FindPlayerCoors() - CVector2D(GetGarageCenterX(), GetGarageCenterY())).MagnitudeSqr() > SQR(DISTANCE_TO_CLOSE_MISSION_GARAGE)) {\n\t\t\t\tif ((CTimer::GetFrameCounter() & 0x1F) == 0 \n#ifndef GTA_PS2\n\t\t\t\t\t&& (!m_pTarget || IsEntityTouching3D(m_pTarget))\n#endif\n\t\t\t\t\t) {\n\t\t\t\t\tm_eGarageState = GS_CLOSING;\n\t\t\t\t\tm_bClosingWithoutTargetCar = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (!FindPlayerVehicle() && m_pTarget && IsEntityEntirelyInside3D(m_pTarget, 0.0f) &&\n\t\t\t\tIsEntityEntirelyOutside(FindPlayerVehicle() ? (CEntity*)FindPlayerVehicle() : (CEntity*)FindPlayerPed(), 2.0f)) {\n\t\t\t\tCPad::GetPad(0)->SetDisablePlayerControls(PLAYERCONTROL_GARAGE);\n\t\t\t\tFindPlayerPed()->m_pWanted->m_bIgnoredByCops = true;\n\t\t\t\tm_eGarageState = GS_CLOSING;\n\t\t\t\tm_bClosingWithoutTargetCar = false;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase GS_CLOSING:\n\t\t\tif (m_pTarget)\n\t\t\t\tThrowCarsNearDoorOutOfGarage(m_pTarget);\n\t\t\tm_fDoorPos = Max(0.0f, m_fDoorPos - (m_bRotatedDoor ? ROTATED_DOOR_CLOSE_SPEED : DEFAULT_DOOR_CLOSE_SPEED) * CTimer::GetTimeStep());\n\t\t\tif (m_fDoorPos == 0.0f) {\n\t\t\t\tDMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_CLOSED, 1.0f);\n\t\t\t\tif (m_bClosingWithoutTargetCar)\n\t\t\t\t\tm_eGarageState = GS_FULLYCLOSED;\n\t\t\t\telse {\n\t\t\t\t\tif (m_pTarget) {\n\t\t\t\t\t\tm_eGarageState = GS_CLOSEDCONTAINSCAR;\n\t\t\t\t\t\tDestroyVehicleAndDriverAndPassengers(m_pTarget);\n\t\t\t\t\t\tm_pTarget = nil;\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tm_eGarageState = GS_FULLYCLOSED;\n\t\t\t\t\t}\n\t\t\t\t\tCPad::GetPad(0)->SetEnablePlayerControls(PLAYERCONTROL_GARAGE);\n\t\t\t\t\tFindPlayerPed()->m_pWanted->m_bIgnoredByCops = false;\n\t\t\t\t}\n\t\t\t}\n\t\t\tUpdateDoorsHeight();\n\t\t\tbreak;\n\t\tcase GS_FULLYCLOSED:\n\t\t\tif (FindPlayerVehicle() == m_pTarget && m_pTarget) {\n\t\t\t\tif (CalcDistToGarageRectangleSquared(\n\t\t\t\t\tFindPlayerVehicle()->GetPosition().x,\n\t\t\t\t\tFindPlayerVehicle()->GetPosition().y) < SQR(DISTANCE_TO_ACTIVATE_GARAGE))\n\t\t\t\t\tm_eGarageState = GS_OPENING;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase GS_OPENING:\n\t\t\tm_fDoorPos = Min(m_fDoorHeight, m_fDoorPos + (m_bRotatedDoor ? ROTATED_DOOR_OPEN_SPEED : DEFAULT_DOOR_OPEN_SPEED) * CTimer::GetTimeStep());\n\t\t\tif (m_fDoorPos == m_fDoorHeight) {\n\t\t\t\tm_eGarageState = GS_OPENED;\n\t\t\t\tDMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_OPENED, 1.0f);\n\t\t\t}\n\t\t\tUpdateDoorsHeight();\n\t\t\tbreak;\n\t\t//case GS_OPENEDCONTAINSCAR:\n\t\t//case GS_CLOSEDCONTAINSCAR:\n\t\t//case GS_AFTERDROPOFF:\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\t\tbreak;\n\tcase GARAGE_COLLECTSPECIFICCARS:\n\tcase GARAGE_COLLECTCARS_1:\n\tcase GARAGE_COLLECTCARS_2:\n\tcase GARAGE_COLLECTCARS_3:\n\tcase GARAGE_COLLECTCARS_4:\n\t\tswitch (m_eGarageState) {\n\t\tcase GS_OPENED:\n\t\t\tif (FindPlayerVehicle() && DoesCraigNeedThisCar(FindPlayerVehicle()->GetModelIndex())) {\n\t\t\t\tm_pTarget = FindPlayerVehicle();\n\t\t\t\tm_pTarget->RegisterReference((CEntity**)&m_pTarget);\n\t\t\t}\n\t\t\tif (Abs(FindPlayerCoors().x - GetGarageCenterX()) > DISTANCE_TO_CLOSE_COLLECTCARS_GARAGE ||\n\t\t\t\tAbs(FindPlayerCoors().y - GetGarageCenterY()) > DISTANCE_TO_CLOSE_COLLECTCARS_GARAGE) {\n\t\t\t\tm_eGarageState = GS_CLOSING;\n\t\t\t\tm_pTarget = nil;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (m_pTarget && !FindPlayerVehicle() && IsEntityEntirelyInside3D(m_pTarget, 0.0f) &&\n\t\t\t\t!IsAnyOtherCarTouchingGarage(m_pTarget) && IsEntityEntirelyOutside(FindPlayerPed(), 2.0f)) {\n#ifdef FIX_BUGS\n\t\t\t\tif (!m_pTarget->IsCar() ||\n\t\t\t\t\t((CAutomobile*)(m_pTarget))->Damage.GetEngineStatus() <= ENGINE_STATUS_ON_FIRE &&\n\t\t\t\t\t((CAutomobile*)(m_pTarget))->m_fFireBlowUpTimer == 0.0f) {\n#else\n\t\t\t\tif (((CAutomobile*)(m_pTarget))->Damage.GetEngineStatus() <= ENGINE_STATUS_ON_FIRE &&\n\t\t\t\t\t((CAutomobile*)(m_pTarget))->m_fFireBlowUpTimer == 0.0f) {\n#endif\n\t\t\t\t\tif (m_pTarget->GetStatus() != STATUS_WRECKED) {\n\t\t\t\t\t\tCPad::GetPad(0)->SetDisablePlayerControls(PLAYERCONTROL_GARAGE);\n\t\t\t\t\t\tFindPlayerPed()->m_pWanted->m_bIgnoredByCops = true;\n\t\t\t\t\t\tm_eGarageState = GS_CLOSING;\n\t\t\t\t\t\tTheCamera.SetCameraDirectlyBehindForFollowPed_CamOnAString();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\tcase GS_CLOSING:\n\t\t\tif (m_pTarget)\n\t\t\t\tThrowCarsNearDoorOutOfGarage(m_pTarget);\n\t\t\tm_fDoorPos = Max(0.0f, m_fDoorPos - (m_bRotatedDoor ? ROTATED_DOOR_CLOSE_SPEED : DEFAULT_DOOR_CLOSE_SPEED) * CTimer::GetTimeStep());\n\t\t\tif (m_fDoorPos == 0.0f) {\n\t\t\t\tm_eGarageState = GS_FULLYCLOSED;\n\t\t\t\tDMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_CLOSED, 1.0f);\n\t\t\t\tif (m_pTarget) {\n\t\t\t\t\tMarkThisCarAsCollectedForCraig(m_pTarget->GetModelIndex());\n\t\t\t\t\tDestroyVehicleAndDriverAndPassengers(m_pTarget);\n\t\t\t\t\tm_pTarget = nil;\n\t\t\t\t\tCPad::GetPad(0)->SetEnablePlayerControls(PLAYERCONTROL_GARAGE);\n\t\t\t\t\tFindPlayerPed()->m_pWanted->m_bIgnoredByCops = false;\n\t\t\t\t}\n\t\t\t}\n\t\t\tUpdateDoorsHeight();\n\t\t\tbreak;\n\t\tcase GS_FULLYCLOSED:\n\t\t\tif (FindPlayerVehicle() &&\n\t\t\t\tCalcSmallestDistToGarageDoorSquared(\n\t\t\t\t\tFindPlayerVehicle()->GetPosition().x,\n\t\t\t\t\tFindPlayerVehicle()->GetPosition().y\n\t\t\t\t\t) < SQR(DISTANCE_TO_ACTIVATE_GARAGE)) {\n\t\t\t\tif (DoesCraigNeedThisCar(FindPlayerVehicle()->GetModelIndex())) {\n\t\t\t\t\tif (FindPlayerVehicle()->VehicleCreatedBy == MISSION_VEHICLE)\n\t\t\t\t\t\tCGarages::TriggerMessage(\"GA_1A\", -1, 5000, -1); // Come back when you're not so busy...\n\t\t\t\t\telse\n\t\t\t\t\t\tm_eGarageState = GS_OPENING;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tif (HasCraigCollectedThisCar(FindPlayerVehicle()->GetModelIndex()))\n\t\t\t\t\t\tCGarages::TriggerMessage(\"GA_20\", -1, 5000, -1); // We got more of these than we can shift. Sorry man, no deal.\n\t\t\t\t\telse if (FindPlayerSpeed().Magnitude() < MAX_SPEED_TO_SHOW_COLLECTED_MESSAGE)\n\t\t\t\t\t\tCGarages::TriggerMessage(\"GA_19\", -1, 5000, -1); // We're not interested in that model.\n\t\t\t\t}\n\t\t\t}\n\t\t\tm_pTarget = nil;\n\t\t\tbreak;\n\t\tcase GS_OPENING:\n\t\t\tif (FindPlayerVehicle() && DoesCraigNeedThisCar(FindPlayerVehicle()->GetModelIndex())) {\n\t\t\t\tm_pTarget = FindPlayerVehicle();\n\t\t\t\tm_pTarget->RegisterReference((CEntity**)&m_pTarget);\n\t\t\t}\n\t\t\tm_fDoorPos = Min(m_fDoorHeight, m_fDoorPos + (m_bRotatedDoor ? ROTATED_DOOR_OPEN_SPEED : DEFAULT_DOOR_OPEN_SPEED) * CTimer::GetTimeStep());\n\t\t\tif (m_fDoorPos == m_fDoorHeight) {\n\t\t\t\tm_eGarageState = GS_OPENED;\n\t\t\t\tDMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_OPENED, 1.0f);\n\t\t\t}\n\t\t\tUpdateDoorsHeight();\n\t\t\tbreak;\n\t\t//case GS_OPENEDCONTAINSCAR:\n\t\t//case GS_CLOSEDCONTAINSCAR:\n\t\t//case GS_AFTERDROPOFF:\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\t\tbreak;\n\tcase GARAGE_FORCARTOCOMEOUTOF:\n\t\tswitch (m_eGarageState) {\n\t\tcase GS_OPENED:\n\t\t\tif (IsGarageEmpty())\n\t\t\t\tm_eGarageState = GS_CLOSING;\n\t\t\tbreak;\n\t\tcase GS_CLOSING:\n\t\t\tm_fDoorPos = Max(0.0f, m_fDoorPos - (m_bRotatedDoor ? ROTATED_DOOR_CLOSE_SPEED : DEFAULT_DOOR_CLOSE_SPEED) * CTimer::GetTimeStep());\n\t\t\tif (m_fDoorPos == 0.0f) {\n\t\t\t\tm_eGarageState = GS_FULLYCLOSED;\n\t\t\t\tDMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_CLOSED, 1.0f);\n\t\t\t}\n\t\t\tif (!IsGarageEmpty())\n\t\t\t\tm_eGarageState = GS_OPENING;\n\t\t\tbreak;\n\t\tcase GS_FULLYCLOSED:\n\t\t\tbreak;\n\t\tcase GS_OPENING:\n\t\t\tm_fDoorPos = Min(m_fDoorHeight, m_fDoorPos + (m_bRotatedDoor ? ROTATED_DOOR_OPEN_SPEED : DEFAULT_DOOR_OPEN_SPEED) * CTimer::GetTimeStep());\n\t\t\tif (m_fDoorPos == m_fDoorHeight) {\n\t\t\t\tm_eGarageState = GS_OPENED;\n\t\t\t\tDMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_OPENED, 1.0f);\n\t\t\t}\n\t\t\tUpdateDoorsHeight();\n\t\t\tbreak;\n\t\t//case GS_OPENEDCONTAINSCAR:\n\t\t//case GS_CLOSEDCONTAINSCAR:\n\t\t//case GS_AFTERDROPOFF:\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\t\tbreak;\n\tcase GARAGE_CRUSHER:\n\t\tbreak;\n\tcase GARAGE_MISSION_KEEPCAR:\n\tcase GARAGE_MISSION_KEEPCAR_REMAINCLOSED:\n\t\tswitch (m_eGarageState) {\n\t\tcase GS_OPENED:\n\t\t\tif (((CVector2D)FindPlayerCoors() - CVector2D(GetGarageCenterX(), GetGarageCenterY())).MagnitudeSqr() > SQR(DISTANCE_TO_CLOSE_MISSION_GARAGE) &&\n\t\t\t\t!IsAnyOtherCarTouchingGarage(nil)) {\n\t\t\t\tm_eGarageState = GS_CLOSING;\n\t\t\t\tm_bClosingWithoutTargetCar = true;\n\t\t\t}\n\t\t\telse if (m_pTarget && m_pTarget == FindPlayerVehicle() && IsStaticPlayerCarEntirelyInside() && !IsAnyCarBlockingDoor()) {\n\t\t\t\tCPad::GetPad(0)->SetDisablePlayerControls(PLAYERCONTROL_GARAGE);\n\t\t\t\tFindPlayerPed()->m_pWanted->m_bIgnoredByCops = true;\n\t\t\t\tm_eGarageState = GS_CLOSING;\n\t\t\t\tm_bClosingWithoutTargetCar = false;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase GS_CLOSING:\n\t\t\tif (m_pTarget)\n\t\t\t\tThrowCarsNearDoorOutOfGarage(m_pTarget);\n\t\t\tm_fDoorPos = Max(0.0f, m_fDoorPos - (m_bRotatedDoor ? ROTATED_DOOR_CLOSE_SPEED : DEFAULT_DOOR_CLOSE_SPEED) * CTimer::GetTimeStep());\n\t\t\tif (m_fDoorPos == 0.0f) {\n\t\t\t\tDMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_CLOSED, 1.0f);\n\t\t\t\tif (m_bClosingWithoutTargetCar)\n\t\t\t\t\tm_eGarageState = GS_FULLYCLOSED;\n\t\t\t\telse {\n\t\t\t\t\tif (m_pTarget) {\n\t\t\t\t\t\tm_eGarageState = GS_CLOSEDCONTAINSCAR;\n\t\t\t\t\t\tm_nTimeToStartAction = CTimer::GetTimeInMilliseconds() + TIME_TO_PROCESS_KEEPCAR_GARAGE;\n\t\t\t\t\t\tm_pTarget = nil;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t\tm_eGarageState = GS_FULLYCLOSED;\n\t\t\t\t\tCPad::GetPad(0)->SetEnablePlayerControls(PLAYERCONTROL_GARAGE);\n\t\t\t\t\tFindPlayerPed()->m_pWanted->m_bIgnoredByCops = false;\n\t\t\t\t}\n\t\t\t}\n\t\t\tUpdateDoorsHeight();\n\t\t\tbreak;\n\t\tcase GS_FULLYCLOSED:\n\t\t\tif (FindPlayerVehicle() == m_pTarget && m_pTarget &&\n\t\t\t\tCalcDistToGarageRectangleSquared(\n\t\t\t\t\tFindPlayerVehicle()->GetPosition().x,\n\t\t\t\t\tFindPlayerVehicle()->GetPosition().y\n\t\t\t\t\t) < SQR(DISTANCE_TO_ACTIVATE_KEEPCAR_GARAGE))\n\t\t\t\tm_eGarageState = GS_OPENING;\n\t\t\tbreak;\n\t\tcase GS_OPENING:\n\t\t\tm_fDoorPos = Min(m_fDoorHeight, m_fDoorPos + (m_bRotatedDoor ? ROTATED_DOOR_OPEN_SPEED : DEFAULT_DOOR_OPEN_SPEED) * CTimer::GetTimeStep());\n\t\t\tif (m_fDoorPos == m_fDoorHeight) {\n\t\t\t\tm_eGarageState = GS_OPENED;\n\t\t\t\tDMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_OPENED, 1.0f);\n\t\t\t}\n\t\t\tUpdateDoorsHeight();\n\t\t\tbreak;\n\t\tcase GS_CLOSEDCONTAINSCAR:\n\t\t\tif (m_eGarageType == GARAGE_MISSION_KEEPCAR && CTimer::GetTimeInMilliseconds() > m_nTimeToStartAction)\n\t\t\t\tm_eGarageState = GS_OPENING;\n\t\t\tbreak;\n\t\t//case GS_OPENEDCONTAINSCAR:\n\t\t//case GS_AFTERDROPOFF:\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\t\tbreak;\n\tcase GARAGE_FOR_SCRIPT_TO_OPEN:\n\t\tswitch (m_eGarageState) {\n\t\tcase GS_OPENING:\n\t\t\tm_fDoorPos = Min(m_fDoorHeight, m_fDoorPos + (m_bRotatedDoor ? ROTATED_DOOR_OPEN_SPEED : DEFAULT_DOOR_OPEN_SPEED) * CTimer::GetTimeStep());\n\t\t\tif (m_fDoorPos == m_fDoorHeight) {\n\t\t\t\tm_eGarageState = GS_OPENED;\n\t\t\t\tDMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_OPENED, 1.0f);\n\t\t\t}\n\t\t\tUpdateDoorsHeight();\n\t\t\tbreak;\n\t\t//case GS_OPENED:\n\t\t//case GS_CLOSING:\n\t\t//case GS_FULLYCLOSED:\n\t\t//case GS_OPENEDCONTAINSCAR:\n\t\t//case GS_CLOSEDCONTAINSCAR:\n\t\t//case GS_AFTERDROPOFF:\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\t\tbreak;\n\tcase GARAGE_FOR_SCRIPT_TO_OPEN_AND_CLOSE:\n\t\tswitch (m_eGarageState) {\n\t\tcase GS_CLOSING:\n\t\t\tm_fDoorPos = Max(0.0f, m_fDoorPos - (m_bRotatedDoor ? ROTATED_DOOR_CLOSE_SPEED : DEFAULT_DOOR_CLOSE_SPEED) * CTimer::GetTimeStep());\n\t\t\tif (m_fDoorPos == 0.0f) {\n\t\t\t\tm_eGarageState = GS_FULLYCLOSED;\n\t\t\t\tDMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_CLOSED, 1.0f);\n\t\t\t}\n\t\t\tUpdateDoorsHeight();\n\t\t\tbreak;\n\t\tcase GS_OPENING:\n\t\t\tm_fDoorPos = Min(m_fDoorHeight, m_fDoorPos + (m_bRotatedDoor ? ROTATED_DOOR_OPEN_SPEED : DEFAULT_DOOR_OPEN_SPEED) * CTimer::GetTimeStep());\n\t\t\tif (m_fDoorPos == m_fDoorHeight) {\n\t\t\t\tm_eGarageState = GS_OPENED;\n\t\t\t\tDMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_OPENED, 1.0f);\n\t\t\t}\n\t\t\tUpdateDoorsHeight();\n\t\t\tbreak;\n\t\t//case GS_OPENED:\n\t\t//case GS_FULLYCLOSED:\n\t\t//case GS_OPENEDCONTAINSCAR:\n\t\t//case GS_CLOSEDCONTAINSCAR:\n\t\t//case GS_AFTERDROPOFF:\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\t\tbreak;\n\tcase GARAGE_HIDEOUT_ONE:\n\tcase GARAGE_HIDEOUT_TWO:\n\tcase GARAGE_HIDEOUT_THREE:\n\tcase GARAGE_HIDEOUT_FOUR:\n\tcase GARAGE_HIDEOUT_FIVE:\n\tcase GARAGE_HIDEOUT_SIX:\n\tcase GARAGE_HIDEOUT_SEVEN:\n\tcase GARAGE_HIDEOUT_EIGHT:\n\tcase GARAGE_HIDEOUT_NINE:\n\tcase GARAGE_HIDEOUT_TEN:\n\tcase GARAGE_HIDEOUT_ELEVEN:\n\tcase GARAGE_HIDEOUT_TWELVE:\n\t\tswitch (m_eGarageState) {\n\t\tcase GS_OPENED:\n\t\t{\n\t\t\tfloat distance = CalcDistToGarageRectangleSquared(FindPlayerCoors().x, FindPlayerCoors().y);\n\t\t\t// Close car doors either if player is far, or if he is in vehicle and garage is full,\n\t\t\t// or if player is very very far so that we can remove whatever is blocking garage door without him noticing\n\t\t\tif ((distance > SQR(DISTANCE_TO_CLOSE_HIDEOUT_GARAGE_IN_CAR) ||\n\t\t\t\t!FindPlayerVehicle() && distance > SQR(DISTANCE_TO_CLOSE_HIDEOUT_GARAGE_ON_FOOT)) &&\n\t\t\t\t!IsAnyCarBlockingDoor())\n\t\t\t\tm_eGarageState = GS_CLOSING;\n\t\t\telse if (FindPlayerVehicle() &&\n\t\t\t\tCountCarsWithCenterPointWithinGarage(FindPlayerVehicle()) >=\n\t\t\t\tFindMaxNumStoredCarsForGarage()) {\n\t\t\t\tm_eGarageState = GS_CLOSING;\n\t\t\t}\n\t\t\telse if (distance > SQR(DISTANCE_TO_FORCE_CLOSE_HIDEOUT_GARAGE)) {\n\t\t\t\tm_eGarageState = GS_CLOSING;\n\t\t\t\tRemoveCarsBlockingDoorNotInside();\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tcase GS_CLOSING:\n\t\t\tm_fDoorPos = Max(0.0f, m_fDoorPos - HIDEOUT_DOOR_SPEED_COEFFICIENT * (m_bRotatedDoor ? ROTATED_DOOR_CLOSE_SPEED : DEFAULT_DOOR_CLOSE_SPEED) * CTimer::GetTimeStep());\n\t\t\tif (!IsPlayerOutsideGarage())\n\t\t\t\tm_eGarageState = GS_OPENING;\n\t\t\telse if (m_fDoorPos == 0.0f) {\n\t\t\t\tDMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_CLOSED, 1.0f);\n\t\t\t\tm_eGarageState = GS_FULLYCLOSED;\n\t\t\t\tStoreAndRemoveCarsForThisHideout(CGarages::aCarsInSafeHouses[CGarages::FindSafeHouseIndexForGarageType(m_eGarageType)], NUM_GARAGE_STORED_CARS);\n\t\t\t}\n\t\t\tUpdateDoorsHeight();\n\t\t\tbreak;\n\t\tcase GS_FULLYCLOSED:\n\t\t{\n\t\t\tfloat distance = CalcDistToGarageRectangleSquared(FindPlayerCoors().x, FindPlayerCoors().y);\n\t\t\tif (distance < SQR(DISTANCE_TO_OPEN_HIDEOUT_GARAGE_ON_FOOT) ||\n\t\t\t\tdistance < SQR(DISTANCE_TO_OPEN_HIDEOUT_GARAGE_IN_CAR) && FindPlayerVehicle()) {\n\t\t\t\tif (FindPlayerVehicle() && CGarages::CountCarsInHideoutGarage(m_eGarageType) >= FindMaxNumStoredCarsForGarage()) {\n\t\t\t\t\tif (m_pDoor1) {\n\t\t\t\t\t\tif (((CVector2D)FindPlayerVehicle()->GetPosition() - (CVector2D)m_pDoor1->GetPosition()).MagnitudeSqr() < SQR(DISTANCE_TO_SHOW_HIDEOUT_MESSAGE) &&\n\t\t\t\t\t\t\tCTimer::GetTimeInMilliseconds() - CGarages::LastTimeHelpMessage > TIME_BETWEEN_HIDEOUT_MESSAGES) {\n\t\t\t\t\t\t\tif (FindPlayerVehicle()->GetVehicleAppearance() != VEHICLE_APPEARANCE_HELI && FindPlayerVehicle()->GetVehicleAppearance() != VEHICLE_APPEARANCE_PLANE) {\n\t\t\t\t\t\t\t\tCHud::SetHelpMessage(TheText.Get(\"GA_21\"), false); // You cannot store any more cars in this garage.\n\t\t\t\t\t\t\t\tCGarages::LastTimeHelpMessage = CTimer::GetTimeInMilliseconds();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if (RestoreCarsForThisHideout(CGarages::aCarsInSafeHouses[CGarages::FindSafeHouseIndexForGarageType(m_eGarageType)]))\n\t\t\t\t\tm_eGarageState = GS_OPENING;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tcase GS_OPENING:\n\t\t\tm_fDoorPos = Min(m_fDoorHeight, m_fDoorPos + HIDEOUT_DOOR_SPEED_COEFFICIENT * (m_bRotatedDoor ? ROTATED_DOOR_OPEN_SPEED : DEFAULT_DOOR_OPEN_SPEED) * CTimer::GetTimeStep());\n\t\t\tif (m_fDoorPos == m_fDoorHeight) {\n\t\t\t\tm_eGarageState = GS_OPENED;\n\t\t\t\tDMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_OPENED, 1.0f);\n\t\t\t}\n\t\t\tUpdateDoorsHeight();\n\t\t\tbreak;\n\t\t//case GS_OPENEDCONTAINSCAR:\n\t\t//case GS_CLOSEDCONTAINSCAR:\n\t\t//case GS_AFTERDROPOFF:\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\t\tbreak;\n\tcase GARAGE_KEEPS_OPENING_FOR_SPECIFIC_CAR:\n\t\tswitch (m_eGarageState) {\n\t\tcase GS_OPENED:\n\t\t\tif (((CVector2D)FindPlayerCoors() - CVector2D(GetGarageCenterX(), GetGarageCenterY())).MagnitudeSqr() > SQR(DISTANCE_TO_CLOSE_MISSION_GARAGE)) {\n\t\t\t\tif (m_pTarget && IsEntityEntirelyOutside(m_pTarget, 0.0f) && !IsAnyOtherCarTouchingGarage(nil)) {\n\t\t\t\t\tm_eGarageState = GS_CLOSING;\n\t\t\t\t\tm_bClosingWithoutTargetCar = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\tcase GS_CLOSING:\n\t\t\tif (m_pTarget)\n\t\t\t\tThrowCarsNearDoorOutOfGarage(m_pTarget);\n\t\t\tm_fDoorPos = Max(0.0f, m_fDoorPos - (m_bRotatedDoor ? ROTATED_DOOR_CLOSE_SPEED : DEFAULT_DOOR_CLOSE_SPEED) * CTimer::GetTimeStep());\n\t\t\tif (m_fDoorPos == 0.0f) {\n\t\t\t\tm_eGarageState = GS_FULLYCLOSED;\n\t\t\t\tDMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_CLOSED, 1.0f);\n\t\t\t}\n\t\t\tUpdateDoorsHeight();\n\t\t\tbreak;\n\t\tcase GS_FULLYCLOSED:\n\t\t\tif (FindPlayerVehicle() == m_pTarget && m_pTarget &&\n\t\t\t\tCalcDistToGarageRectangleSquared(\n\t\t\t\t\tFindPlayerVehicle()->GetPosition().x,\n\t\t\t\t\tFindPlayerVehicle()->GetPosition().y\n\t\t\t\t\t) < SQR(DISTANCE_TO_ACTIVATE_GARAGE))\n\t\t\t\tm_eGarageState = GS_OPENING;\n\t\t\tbreak;\n\t\tcase GS_OPENING:\n\t\t\tm_fDoorPos = Min(m_fDoorHeight, m_fDoorPos + (m_bRotatedDoor ? ROTATED_DOOR_OPEN_SPEED : DEFAULT_DOOR_OPEN_SPEED) * CTimer::GetTimeStep());\n\t\t\tif (m_fDoorPos == m_fDoorHeight) {\n\t\t\t\tm_eGarageState = GS_OPENED;\n\t\t\t\tDMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_OPENED, 1.0f);\n\t\t\t}\n\t\t\tUpdateDoorsHeight();\n\t\t\tbreak;\n\t\t//case GS_OPENEDCONTAINSCAR:\n\t\t//case GS_CLOSEDCONTAINSCAR:\n\t\t//case GS_AFTERDROPOFF:\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\t\tbreak;\n\t//case GARAGE_COLLECTORSITEMS:\n\t//case GARAGE_60SECONDS:\n\tcase GARAGE_FOR_SCRIPT_TO_OPEN_FOR_CAR:\n\t\tswitch (m_eGarageState) {\n\t\tcase GS_OPENED:\n\t\t\tif (m_pTarget && IsEntityEntirelyInside3D(m_pTarget, 0.0f) && !IsAnyCarBlockingDoor() && IsPlayerOutsideGarage()) {\n\t\t\t\tCPad::GetPad(0)->SetDisablePlayerControls(PLAYERCONTROL_GARAGE);\n\t\t\t\tm_eGarageState = GS_CLOSING;\n\t\t\t\tm_bClosingWithoutTargetCar = false;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase GS_CLOSING:\n\t\t\tm_fDoorPos = Max(0.0f, m_fDoorPos - (m_bRotatedDoor ? ROTATED_DOOR_CLOSE_SPEED : DEFAULT_DOOR_CLOSE_SPEED) * CTimer::GetTimeStep());\n\t\t\tif (m_fDoorPos == 0.0f) {\n\t\t\t\tm_eGarageState = GS_FULLYCLOSED;\n\t\t\t\tDMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_CLOSED, 1.0f);\n\t\t\t\tCPad::GetPad(0)->SetEnablePlayerControls(PLAYERCONTROL_GARAGE);\n\t\t\t}\n\t\t\tUpdateDoorsHeight();\n\t\t\tbreak;\n\t\tcase GS_FULLYCLOSED:\n\t\t\tbreak;\n\t\tcase GS_OPENING:\n\t\t\tm_fDoorPos = Min(m_fDoorHeight, m_fDoorPos + (m_bRotatedDoor ? ROTATED_DOOR_OPEN_SPEED : DEFAULT_DOOR_OPEN_SPEED) * CTimer::GetTimeStep());\n\t\t\tif (m_fDoorPos == m_fDoorHeight) {\n\t\t\t\tm_eGarageState = GS_OPENED;\n\t\t\t\tDMAudio.PlayOneShot(hGarages, SOUND_GARAGE_DOOR_OPENED, 1.0f);\n\t\t\t}\n\t\t\tUpdateDoorsHeight();\n\t\t\tbreak;\n\t\t\t//case GS_OPENEDCONTAINSCAR:\n\t\t\t//case GS_CLOSEDCONTAINSCAR:\n\t\t\t//case GS_AFTERDROPOFF:\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\tdefault:\n\t\tbreak;\n\t}\n}\n\nbool CGarage::IsStaticPlayerCarEntirelyInside()\n{\n\tif (!FindPlayerVehicle())\n\t\treturn false;\n\tif (!FindPlayerVehicle()->IsCar() && !FindPlayerVehicle()->IsBike())\n\t\treturn false;\n\tif (FindPlayerPed()->GetPedState() != PED_DRIVING)\n\t\treturn false;\n\tif (FindPlayerPed()->m_objective == OBJECTIVE_LEAVE_CAR)\n\t\treturn false;\n\tCVehicle* pVehicle = FindPlayerVehicle();\n\tif (pVehicle->GetPosition().x < m_fInfX || pVehicle->GetPosition().x > m_fSupX ||\n\t\tpVehicle->GetPosition().y < m_fInfY || pVehicle->GetPosition().y > m_fSupY)\n\t\treturn false;\n\tif (Abs(pVehicle->GetSpeed().x) > 0.01f ||\n\t\tAbs(pVehicle->GetSpeed().y) > 0.01f ||\n\t\tAbs(pVehicle->GetSpeed().z) > 0.01f)\n\t\treturn false;\n\tif (pVehicle->GetSpeed().MagnitudeSqr() > SQR(0.01f))\n\t\treturn false;\n\treturn IsEntityEntirelyInside3D(pVehicle, 0.0f);\n}\n\nbool CGarage::IsPointInsideGarage(CVector pos)\n{\n\t// is it IsPointInsideGarage(pos, 0.0f)?\n\tif (pos.z < m_fInfZ)\n\t\treturn false;\n\tif (pos.z > m_fSupZ)\n\t\treturn false;\n\tCVector2D vecToTarget((CVector2D)pos - m_vecCorner1);\n\tfloat dp = DotProduct2D(m_vDir1, vecToTarget);\n\tif (dp < 0.0f)\n\t\treturn false;\n\tif (m_fDir1Len < dp)\n\t\treturn false;\n\tdp = DotProduct2D(m_vDir2, vecToTarget);\n\tif (dp < 0.0f)\n\t\treturn false;\n\tif (m_fDir2Len < dp)\n\t\treturn false;\n\treturn true;\n}\n\nbool CGarage::IsPointInsideGarage(CVector pos, float m_fMargin)\n{\n\tif (pos.z < m_fInfZ - m_fMargin)\n\t\treturn false;\n\tif (pos.z > m_fSupZ + m_fMargin)\n\t\treturn false;\n\tCVector2D vecToTarget((CVector2D)pos - m_vecCorner1);\n\tfloat dp = DotProduct2D(m_vDir1, vecToTarget);\n\tif (dp < -m_fMargin)\n\t\treturn false;\n\tif (m_fDir1Len + m_fMargin < dp)\n\t\treturn false;\n\tdp = DotProduct2D(m_vDir2, vecToTarget);\n\tif (dp < -m_fMargin)\n\t\treturn false;\n\tif (m_fDir2Len + m_fMargin < dp)\n\t\treturn false;\n\treturn true;\n}\n\nbool CGarage::IsEntityEntirelyInside3D(CEntity* pEntity, float fMargin)\n{\n\tif (pEntity->GetPosition().x < m_fInfX - fMargin || pEntity->GetPosition().x > m_fSupX + fMargin ||\n\t\tpEntity->GetPosition().y < m_fInfY - fMargin || pEntity->GetPosition().y > m_fSupY + fMargin ||\n\t\tpEntity->GetPosition().z < m_fInfZ - fMargin || pEntity->GetPosition().z > m_fSupZ + fMargin)\n\t\treturn false;\n\tCColModel* pColModel = pEntity->GetColModel();\n\tfor (int i = 0; i < pColModel->numSpheres; i++) {\n\t\tCVector pos = pEntity->GetMatrix() * pColModel->spheres[i].center;\n\t\tfloat radius = pColModel->spheres[i].radius;\n\t\tif (!IsPointInsideGarage(pos, fMargin - radius))\n\t\t\treturn false;\n\t}\n\treturn true;\n}\n\nbool CGarage::IsEntityEntirelyOutside(CEntity * pEntity, float fMargin)\n{\n\tif (pEntity->GetPosition().x > m_fInfX - fMargin && pEntity->GetPosition().x < m_fSupX + fMargin &&\n\t\tpEntity->GetPosition().y > m_fInfY - fMargin && pEntity->GetPosition().y < m_fSupY + fMargin)\n\t\treturn false;\n\tCColModel* pColModel = pEntity->GetColModel();\n\tfor (int i = 0; i < pColModel->numSpheres; i++) {\n\t\tCVector pos = pEntity->GetMatrix() * pColModel->spheres[i].center;\n\t\tfloat radius = pColModel->spheres[i].radius;\n\t\tif (IsPointInsideGarage(pos, fMargin + radius))\n\t\t\treturn false;\n\t}\n\treturn true;\n}\n\nbool CGarage::IsGarageEmpty()\n{\n\tint16 num;\n\tCEntity* pEntities[16];\n\tCWorld::FindObjectsIntersectingCube(CVector(m_fInfX, m_fInfY, m_fInfZ), CVector(m_fSupX, m_fSupY, m_fSupZ), &num, 16, pEntities, false, true, true, false, false);\n\tif (num <= 0)\n\t\treturn true;\n\tfor (int i = 0; i < 16; i++) {\n\t\tif (IsEntityTouching3D(pEntities[i]))\n\t\t\treturn false;\n\t}\n\treturn true;\n}\n\nbool CGarage::IsPlayerOutsideGarage()\n{\n\tif (FindPlayerVehicle())\n\t\treturn IsEntityEntirelyOutside(FindPlayerVehicle(), 0.0f);\n\treturn IsEntityEntirelyOutside(FindPlayerPed(), 0.0f);\n}\n\nbool CGarage::IsEntityTouching3D(CEntity* pEntity)\n{\n\tfloat radius = pEntity->GetBoundRadius();\n\tif (m_fInfX - radius > pEntity->GetPosition().x || m_fSupX + radius < pEntity->GetPosition().x ||\n\t\tm_fInfY - radius > pEntity->GetPosition().y || m_fSupY + radius < pEntity->GetPosition().y ||\n\t\tm_fInfZ - radius > pEntity->GetPosition().z || m_fSupZ + radius < pEntity->GetPosition().z)\n\t\treturn false;\n\tCColModel* pColModel = pEntity->GetColModel();\n\tfor (int i = 0; i < pColModel->numSpheres; i++) {\n\t\tCVector pos = pEntity->GetMatrix() * pColModel->spheres[i].center;\n\t\tradius = pColModel->spheres[i].radius;\n\t\tif (IsPointInsideGarage(pos, radius))\n\t\t\treturn true;\n\t}\n\treturn false;\n}\n\nbool CGarage::EntityHasASphereWayOutsideGarage(CEntity * pEntity, float fMargin)\n{\n\tCColModel* pColModel = pEntity->GetColModel();\n\tfor (int i = 0; i < pColModel->numSpheres; i++) {\n\t\tCVector pos = pEntity->GetMatrix() * pColModel->spheres[i].center;\n\t\tfloat radius = pColModel->spheres[i].radius;\n\t\tif (!IsPointInsideGarage(pos, fMargin + radius))\n\t\t\treturn true;\n\t}\n\treturn false;\n}\n\nbool CGarage::IsAnyOtherCarTouchingGarage(CVehicle * pException)\n{\n\tuint32 i = CPools::GetVehiclePool()->GetSize();\n\twhile (i--) {\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetSlot(i);\n\t\tif (!pVehicle || pVehicle == pException || pVehicle->GetStatus() == STATUS_WRECKED)\n\t\t\tcontinue;\n\t\tif (!IsEntityTouching3D(pVehicle))\n\t\t\tcontinue;\n\t\tCColModel* pColModel = pVehicle->GetColModel();\n\t\tfor (int i = 0; i < pColModel->numSpheres; i++) {\n\t\t\tCVector pos = pVehicle->GetMatrix() * pColModel->spheres[i].center;\n\t\t\tfloat radius = pColModel->spheres[i].radius;\n\t\t\tif (IsPointInsideGarage(pos, radius))\n\t\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n\nvoid CGarage::ThrowCarsNearDoorOutOfGarage(CVehicle* pException)\n{\n\tuint32 i = CPools::GetVehiclePool()->GetSize();\n\twhile (i--) {\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetSlot(i);\n\t\tif (!pVehicle || pVehicle == pException)\n\t\t\tcontinue;\n\t\tif (!IsEntityTouching3D(pVehicle))\n\t\t\tcontinue;\n\t\tCColModel* pColModel = pVehicle->GetColModel();\n\t\tfor (int i = 0; i < pColModel->numSpheres; i++) {\n\t\t\tCVector pos = pVehicle->GetMatrix() * pColModel->spheres[i].center;\n\t\t\tfloat radius = pColModel->spheres[i].radius;\n\t\t\tif (!IsPointInsideGarage(pos, 0.0f)) {\n\t\t\t\tCVector vecDirectionAway(pVehicle->GetPosition().x - GetGarageCenterX(), pVehicle->GetPosition().y - GetGarageCenterY(), 0.0f);\n\t\t\t\tvecDirectionAway.Normalise();\n\t\t\t\tpVehicle->AddToMoveSpeed(vecDirectionAway * CTimer::GetTimeStepInSeconds());\n\t\t\t}\n\t\t}\n\t}\n}\n\nbool CGarage::IsAnyOtherPedTouchingGarage(CPed * pException)\n{\n\tuint32 i = CPools::GetPedPool()->GetSize();\n\twhile (i--) {\n\t\tCPed* pPed = CPools::GetPedPool()->GetSlot(i);\n\t\tif (!pPed || pPed == pException)\n\t\t\tcontinue;\n\t\tif (!IsEntityTouching3D(pPed))\n\t\t\tcontinue;\n\t\tCColModel* pColModel = pException->GetColModel();\n\t\tfor (int i = 0; i < pColModel->numSpheres; i++) {\n\t\t\tCVector pos = pPed->GetMatrix() * pColModel->spheres[i].center;\n\t\t\tfloat radius = pColModel->spheres[i].radius;\n\t\t\tif (IsPointInsideGarage(pos, radius))\n\t\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n\nbool CGarage::IsAnyCarBlockingDoor()\n{\n\tuint32 i = CPools::GetVehiclePool()->GetSize();\n\twhile (i--) {\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetSlot(i);\n\t\tif (!pVehicle)\n\t\t\tcontinue;\n\t\tif (!IsEntityTouching3D(pVehicle))\n\t\t\tcontinue;\n\t\tCColModel* pColModel = pVehicle->GetColModel();\n\t\tfor (int i = 0; i < pColModel->numSpheres; i++) {\n\t\t\tCVector pos = pVehicle->GetMatrix() * pColModel->spheres[i].center;\n\t\t\tfloat radius = pColModel->spheres[i].radius;\n\t\t\tif (!IsPointInsideGarage(pos, radius))\n\t\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n\nint32 CGarage::CountCarsWithCenterPointWithinGarage(CEntity * pException)\n{\n\tint32 total = 0;\n\tuint32 i = CPools::GetVehiclePool()->GetSize();\n\twhile (i--) {\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetSlot(i);\n\t\tif (!pVehicle || pVehicle == pException)\n\t\t\tcontinue;\n\t\tif (IsPointInsideGarage(pVehicle->GetPosition()))\n\t\t\ttotal++;\n\t}\n\treturn total;\n}\n\nvoid CGarage::RemoveCarsBlockingDoorNotInside()\n{\n\tuint32 i = CPools::GetVehiclePool()->GetSize();\n\twhile (i--) {\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetSlot(i);\n\t\tif (!pVehicle)\n\t\t\tcontinue;\n\t\tif (!IsEntityTouching3D(pVehicle))\n\t\t\tcontinue;\n\t\tif (!IsPointInsideGarage(pVehicle->GetPosition())) {\n\t\t\tif (!pVehicle->bIsLocked && pVehicle->CanBeDeleted()) {\n\t\t\t\tCWorld::Remove(pVehicle);\n\t\t\t\tdelete pVehicle;\n#ifndef FIX_BUGS\n\t\t\t\treturn;\n#endif\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid CGarages::PrintMessages()\n{\n\tif (CTimer::GetTimeInMilliseconds() > MessageStartTime && CTimer::GetTimeInMilliseconds() < MessageEndTime) {\n\t\tCFont::DrawFonts();\n\t\tCFont::SetScale(SCREEN_SCALE_X(1.2f), SCREEN_SCALE_Y(1.5f));\n\t\tCFont::SetPropOn();\n\t\tCFont::SetJustifyOff();\n\t\tCFont::SetBackgroundOff();\n#ifdef FIX_BUGS\n\t\tCFont::SetCentreSize(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH - 50));\n#else\n\t\tCFont::SetCentreSize(SCREEN_WIDTH - 50);\n#endif\n\t\tCFont::SetCentreOn();\n\t\tCFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD));\n\t\tCFont::SetColor(CRGBA(27, 89, 130, 255));\n\t\tCFont::SetDropShadowPosition(2);\n\t\tCFont::SetDropColor(CRGBA(0, 0, 0, 255));\n\n\t\tfloat y_offset = SCREEN_SCALE_Y(140.0f);\n\n\t\tif (MessageNumberInString2 >= 0) {\n\t\t\tCMessages::InsertNumberInString(TheText.Get(MessageIDString), MessageNumberInString, MessageNumberInString2, -1, -1, -1, -1, gUString);\n\t\t\tCFont::PrintString(SCREEN_WIDTH / 2, y_offset - SCREEN_SCALE_Y(30.0f), gUString);\n\t\t}\n\t\telse if (MessageNumberInString >= 0) {\n\t\t\tCMessages::InsertNumberInString(TheText.Get(MessageIDString), MessageNumberInString, -1, -1, -1, -1, -1, gUString);\n\t\t\tCFont::PrintString(SCREEN_WIDTH / 2, y_offset - SCREEN_SCALE_Y(30.0f), gUString);\n\t\t}\n\t\telse {\n\t\t\tCFont::PrintString(SCREEN_WIDTH / 2, y_offset, TheText.Get(MessageIDString));\n\t\t}\n\t}\n}\n\nbool CGarages::IsCarSprayable(CVehicle * pVehicle)\n{\n\tswitch (pVehicle->GetModelIndex()) {\n\tcase MI_FIRETRUCK:\n\tcase MI_AMBULAN:\n\tcase MI_POLICE:\n\tcase MI_ENFORCER:\n\tcase MI_BUS:\n\tcase MI_RHINO:\n\tcase MI_BARRACKS:\n\tcase MI_DODO:\n\tcase MI_COACH:\n#ifndef GTA_PS2\n\tcase MI_FBIRANCH:\n#endif\n\t\treturn false;\n\tdefault:\n\t\tbreak;\n\t}\n\treturn true;\n}\n\nvoid CGarage::UpdateDoorsHeight()\n{\n\tRefreshDoorPointers(false);\n\tif (m_pDoor1) {\n\t\tm_pDoor1->GetMatrix().GetPosition().z = m_fDoorPos + m_fDoor1Z;\n\t\tif (m_bRotatedDoor) {\n\t\t\tCVector pos;\n\t\t\tpos.x = m_fDoor1X + m_fDoorPos * m_pDoor1->GetForward().y * 5.0f / 6.0f;\n\t\t\tpos.y = m_fDoor1Y - m_fDoorPos * m_pDoor1->GetForward().x * 5.0f / 6.0f;\n\t\t\tpos.z = m_pDoor1->GetPosition().z;\n\t\t\tm_pDoor1->SetPosition(pos);\n\t\t\tBuildRotatedDoorMatrix(m_pDoor1, m_fDoorPos / m_fDoorHeight);\n\t\t}\n\t\tm_pDoor1->GetMatrix().UpdateRW();\n\t\tm_pDoor1->UpdateRwFrame();\n\t}\n\tif (m_pDoor2) {\n\t\tm_pDoor2->GetMatrix().GetPosition().z = m_fDoorPos + m_fDoor2Z;\n\t\tif (m_bRotatedDoor) {\n\t\t\tCVector pos;\n\t\t\tpos.x = m_fDoor2X + m_fDoorPos * m_pDoor2->GetForward().y * 5.0f / 6.0f;\n\t\t\tpos.y = m_fDoor2Y - m_fDoorPos * m_pDoor2->GetForward().x * 5.0f / 6.0f;\n\t\t\tpos.z = m_pDoor2->GetPosition().z;\n\t\t\tm_pDoor2->SetPosition(pos);\n\t\t\tBuildRotatedDoorMatrix(m_pDoor2, m_fDoorPos / m_fDoorHeight);\n\t\t}\n\t\tm_pDoor2->GetMatrix().UpdateRW();\n\t\tm_pDoor2->UpdateRwFrame();\n\t}\n}\n\nvoid CGarage::BuildRotatedDoorMatrix(CEntity * pDoor, float fPosition)\n{\n\tfloat fAngle = -fPosition * HALFPI;\n\tCVector up(-Sin(fAngle) * pDoor->GetForward().y, Sin(fAngle) * pDoor->GetForward().x, Cos(fAngle));\n\tpDoor->GetRight() = CrossProduct(up, pDoor->GetForward());\n\tpDoor->GetUp() = up;\n}\n\nvoid CGarage::UpdateCrusherAngle()\n{\n\tRefreshDoorPointers(false);\n\tm_pDoor2->GetMatrix().SetRotateXOnly(TWOPI - m_fDoorPos);\n\tm_pDoor2->GetMatrix().UpdateRW();\n\tm_pDoor2->UpdateRwFrame();\n}\n\nvoid CGarage::UpdateCrusherShake(float X, float Y)\n{\n\tRefreshDoorPointers(false);\n\tm_pDoor1->GetMatrix().GetPosition().x += X;\n\tm_pDoor1->GetMatrix().GetPosition().y += Y;\n\tm_pDoor1->GetMatrix().UpdateRW();\n\tm_pDoor1->UpdateRwFrame();\n\tm_pDoor1->GetMatrix().GetPosition().x -= X;\n\tm_pDoor1->GetMatrix().GetPosition().y -= Y;\n\tm_pDoor2->GetMatrix().GetPosition().x += X;\n\tm_pDoor2->GetMatrix().GetPosition().y += Y;\n\tm_pDoor2->GetMatrix().UpdateRW();\n\tm_pDoor2->UpdateRwFrame();\n\tm_pDoor2->GetMatrix().GetPosition().x -= X;\n\tm_pDoor2->GetMatrix().GetPosition().y -= Y;\n}\n\nvoid CGarage::RefreshDoorPointers(bool bCreate)\n{\n\tbool bNeedToFindDoorEntities = bCreate || m_bRecreateDoorOnNextRefresh;\n\tm_bRecreateDoorOnNextRefresh = false;\n\tif (m_pDoor1) {\n\t\tif (m_bDoor1IsDummy) {\n\t\t\tif (CPools::GetDummyPool()->GetIsFree(CPools::GetDummyPool()->GetJustIndex_NoFreeAssert((CDummy*)m_pDoor1)))\n\t\t\t\tbNeedToFindDoorEntities = true;\n\t\t\telse {\n\t\t\t\tif (m_bDoor1PoolIndex != (CPools::GetDummyPool()->GetIndex((CDummy*)m_pDoor1) & 0x7F))\n\t\t\t\t\tbNeedToFindDoorEntities = true;\n\t\t\t\tif (!CGarages::IsModelIndexADoor(m_pDoor1->GetModelIndex()))\n\t\t\t\t\tbNeedToFindDoorEntities = true;\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tif (CPools::GetObjectPool()->GetIsFree(CPools::GetObjectPool()->GetJustIndex_NoFreeAssert((CObject*)m_pDoor1)))\n\t\t\t\tbNeedToFindDoorEntities = true;\n\t\t\telse {\n\t\t\t\tif (m_bDoor1PoolIndex != (CPools::GetObjectPool()->GetIndex((CObject*)m_pDoor1) & 0x7F))\n\t\t\t\t\tbNeedToFindDoorEntities = true;\n\t\t\t\tif (!CGarages::IsModelIndexADoor(m_pDoor1->GetModelIndex()))\n\t\t\t\t\tbNeedToFindDoorEntities = true;\n\t\t\t}\n\t\t}\n\t}\n\tif (m_pDoor2) {\n\t\tif (m_bDoor2IsDummy) {\n\t\t\tif (CPools::GetDummyPool()->GetIsFree(CPools::GetDummyPool()->GetJustIndex_NoFreeAssert((CDummy*)m_pDoor2)))\n\t\t\t\tbNeedToFindDoorEntities = true;\n\t\t\telse {\n\t\t\t\tif (m_bDoor2PoolIndex != (CPools::GetDummyPool()->GetIndex((CDummy*)m_pDoor2) & 0x7F))\n\t\t\t\t\tbNeedToFindDoorEntities = true;\n\t\t\t\tif (!CGarages::IsModelIndexADoor(m_pDoor2->GetModelIndex()))\n\t\t\t\t\tbNeedToFindDoorEntities = true;\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tif (CPools::GetObjectPool()->GetIsFree(CPools::GetObjectPool()->GetJustIndex_NoFreeAssert((CObject*)m_pDoor2)))\n\t\t\t\tbNeedToFindDoorEntities = true;\n\t\t\telse {\n\t\t\t\tif (m_bDoor2PoolIndex != (CPools::GetObjectPool()->GetIndex((CObject*)m_pDoor2) & 0x7F))\n\t\t\t\t\tbNeedToFindDoorEntities = true;\n\t\t\t\tif (!CGarages::IsModelIndexADoor(m_pDoor2->GetModelIndex()))\n\t\t\t\t\tbNeedToFindDoorEntities = true;\n\t\t\t}\n\t\t}\n\t}\n\tif (bNeedToFindDoorEntities)\n\t\tFindDoorsEntities();\n}\n\nvoid CGarages::TriggerMessage(const char* text, int16 num1, uint16 time, int16 num2)\n{\n\tif (strcmp(text, MessageIDString) == 0 &&\n\t\tCTimer::GetTimeInMilliseconds() >= MessageStartTime &&\n\t\tCTimer::GetTimeInMilliseconds() <= MessageEndTime) {\n\t\tif (CTimer::GetTimeInMilliseconds() - MessageStartTime <= 500)\n\t\t\treturn;\n\t\tMessageStartTime = CTimer::GetTimeInMilliseconds() - 500;\n\t\tMessageEndTime = CTimer::GetTimeInMilliseconds() - 500 + time;\n\t}\n\telse {\n\t\tstrcpy(MessageIDString, text);\n\t\tMessageStartTime = CTimer::GetTimeInMilliseconds();\n\t\tMessageEndTime = CTimer::GetTimeInMilliseconds() + time;\n\t}\n\tMessageNumberInString = num1;\n\tMessageNumberInString2 = num2;\n}\n\nvoid CGarages::SetTargetCarForMissonGarage(int16 garage, CVehicle* pVehicle)\n{\n\tassert(garage >= 0 && garage < NUM_GARAGES);\n\tif (pVehicle) {\n\t\taGarages[garage].m_pTarget = pVehicle;\n\t\taGarages[garage].m_pTarget->RegisterReference((CEntity**)&aGarages[garage].m_pTarget);\n\t\tif (aGarages[garage].m_eGarageState == GS_CLOSEDCONTAINSCAR)\n\t\t\taGarages[garage].m_eGarageState = GS_FULLYCLOSED;\n\t}\n\telse\n\t\taGarages[garage].m_pTarget = nil;\n}\n\nbool CGarages::HasCarBeenDroppedOffYet(int16 garage)\n{\n\treturn aGarages[garage].m_eGarageState == GS_CLOSEDCONTAINSCAR;\n}\n\nvoid CGarages::DeActivateGarage(int16 garage)\n{\n\taGarages[garage].m_bDeactivated = true;\n}\n\nvoid CGarages::ActivateGarage(int16 garage)\n{\n\taGarages[garage].m_bDeactivated = false;\n\tif (aGarages[garage].m_eGarageType == GARAGE_FORCARTOCOMEOUTOF && aGarages[garage].m_eGarageState == GS_FULLYCLOSED)\n\t\taGarages[garage].m_eGarageState = GS_OPENING;\n}\n\nint32 CGarages::QueryCarsCollected(int16 garage)\n{\n\treturn 0;\n}\n\nbool CGarages::HasImportExportGarageCollectedThisCar(int16 garage, int8 car)\n{\n\treturn CarTypesCollected[GetCarsCollectedIndexForGarageType(aGarages[garage].m_eGarageType)] & (BIT(car));\n}\n\nbool CGarages::IsGarageOpen(int16 garage)\n{\n\treturn aGarages[garage].IsOpen();\n}\n\nbool CGarages::IsGarageClosed(int16 garage)\n{\n\treturn aGarages[garage].IsClosed();\n}\n\nbool CGarages::HasThisCarBeenCollected(int16 garage, uint8 id)\n{\n\treturn aGarages[garage].m_bCollectedCarsState & BIT(id);\n}\n\nbool CGarage::DoesCraigNeedThisCar(int32 mi)\n{\n\tint ct = CGarages::GetCarsCollectedIndexForGarageType(m_eGarageType);\n\tfor (int i = 0; i < TOTAL_COLLECTCARS_CARS; i++) {\n\t\tif (mi == gaCarsToCollectInCraigsGarages[ct][i] || (gaCarsToCollectInCraigsGarages[ct][i] == MI_CHEETAH && mi == MI_VICECHEE))\n\t\t\treturn (CGarages::CarTypesCollected[ct] & BIT(i)) == 0;\n\t}\n\treturn false;\n}\n\nbool CGarage::HasCraigCollectedThisCar(int32 mi)\n{\n\tint ct = CGarages::GetCarsCollectedIndexForGarageType(m_eGarageType);\n\tfor (int i = 0; i < TOTAL_COLLECTCARS_CARS; i++) {\n\t\tif (mi == gaCarsToCollectInCraigsGarages[ct][i] || (gaCarsToCollectInCraigsGarages[ct][i] == MI_CHEETAH && mi == MI_VICECHEE))\n\t\t\treturn CGarages::CarTypesCollected[ct] & BIT(i);\n\t}\n\treturn false;\n}\n\nbool CGarage::MarkThisCarAsCollectedForCraig(int32 mi)\n{\n\tint ct = CGarages::GetCarsCollectedIndexForGarageType(m_eGarageType);\n\tint index;\n\tfor (index = 0; index < TOTAL_COLLECTCARS_CARS; index++) {\n\t\tif (mi == gaCarsToCollectInCraigsGarages[ct][index] || (gaCarsToCollectInCraigsGarages[ct][index] == MI_CHEETAH && mi == MI_VICECHEE))\n\t\t\tbreak;\n\t}\n\tif (index >= TOTAL_COLLECTCARS_CARS)\n\t\treturn false;\n\tCGarages::CarTypesCollected[ct] |= BIT(index);\n\tCWorld::Players[CWorld::PlayerInFocus].m_nMoney += IMPORT_REWARD;\n\tfor (int i = 0; i < TOTAL_COLLECTCARS_CARS; i++) {\n\t\tif ((CGarages::CarTypesCollected[ct] & BIT(i)) == 0) {\n\t\t\tCGarages::TriggerMessage(\"GA_13\", -1, 5000, -1); // Delivered like a pro. Complete the list and there'll be a bonus for you.\n\t\t\treturn false;\n\t\t}\n\t}\n\tCWorld::Players[CWorld::PlayerInFocus].m_nMoney += IMPORT_ALLCARS_REWARD;\n\tCGarages::TriggerMessage(\"GA_14\", -1, 5000, -1); // All the cars. NICE! Here's a little something.\n\treturn true;\n}\n\nvoid CGarage::OpenThisGarage()\n{\n\tif (m_eGarageState == GS_FULLYCLOSED || m_eGarageState == GS_CLOSING || m_eGarageState == GS_CLOSEDCONTAINSCAR)\n\t\tm_eGarageState = GS_OPENING;\n}\n\nvoid CGarage::CloseThisGarage()\n{\n\tif (m_eGarageState == GS_OPENED || m_eGarageState == GS_OPENING)\n\t\tm_eGarageState = GS_CLOSING;\n}\n\nfloat CGarage::CalcDistToGarageRectangleSquared(float X, float Y)\n{\n\tfloat distX, distY;\n\tif (X < m_fInfX)\n\t\tdistX = m_fInfX - X;\n\telse if (X > m_fSupX)\n\t\tdistX = X - m_fSupX;\n\telse\n\t\tdistX = 0.0f;\n\tif (Y < m_fInfY)\n\t\tdistY = m_fInfY - Y;\n\telse if (Y > m_fSupY)\n\t\tdistY = Y - m_fSupY;\n\telse\n\t\tdistY = 0.0f;\n\treturn SQR(distX) + SQR(distY);\n}\n\nfloat CGarage::CalcSmallestDistToGarageDoorSquared(float X, float Y)\n{\n\tfloat dist1 = 10000000.0f;\n\tfloat dist2 = 10000000.0f;\n\tif (m_pDoor1)\n\t\tdist1 = SQR(m_fDoor1X - X) + SQR(m_fDoor1Y - Y);\n\tif (m_pDoor2)\n\t\tdist2 = SQR(m_fDoor2X - X) + SQR(m_fDoor2Y - Y);\n\treturn Min(dist1, dist2);\n}\n\nvoid CGarage::FindDoorsEntities()\n{\n\tm_pDoor1 = nil;\n\tm_pDoor2 = nil;\n\tint xstart = Max(0, CWorld::GetSectorIndexX(GetGarageCenterX() - 100.0f));\n\tint xend = Min(NUMSECTORS_X - 1, CWorld::GetSectorIndexX(GetGarageCenterX() + 100.0f));\n\tint ystart = Max(0, CWorld::GetSectorIndexY(GetGarageCenterY() - 100.0f));\n\tint yend = Min(NUMSECTORS_Y - 1, CWorld::GetSectorIndexY(GetGarageCenterY() + 100.0f));\n\tassert(xstart <= xend);\n\tassert(ystart <= yend);\n\n\tCWorld::AdvanceCurrentScanCode();\n\n\tfor (int y = ystart; y <= yend; y++) {\n\t\tfor (int x = xstart; x <= xend; x++) {\n\t\t\tCSector* s = CWorld::GetSector(x, y);\n\t\t\tFindDoorsEntitiesSectorList(s->m_lists[ENTITYLIST_OBJECTS], false);\n\t\t\tFindDoorsEntitiesSectorList(s->m_lists[ENTITYLIST_OBJECTS_OVERLAP], false);\n\t\t\tFindDoorsEntitiesSectorList(s->m_lists[ENTITYLIST_DUMMIES], true);\n\t\t\tFindDoorsEntitiesSectorList(s->m_lists[ENTITYLIST_DUMMIES_OVERLAP], true);\n\t\t}\n\t}\n\tif (m_pDoor1 && m_pDoor2) {\n\t\tCVector2D vecDoor1ToGarage(m_pDoor1->GetPosition().x - GetGarageCenterX(), m_pDoor1->GetPosition().y - GetGarageCenterY());\n\t\tCVector2D vecDoor2ToGarage(m_pDoor2->GetPosition().x - GetGarageCenterX(), m_pDoor2->GetPosition().y - GetGarageCenterY());\n\t\tif (DotProduct2D(vecDoor1ToGarage, vecDoor2ToGarage) > 0.0f) {\n\t\t\tif (vecDoor1ToGarage.MagnitudeSqr() >= vecDoor2ToGarage.MagnitudeSqr()) {\n\t\t\t\tm_pDoor1 = m_pDoor2;\n\t\t\t\tm_bDoor1IsDummy = m_bDoor2IsDummy;\n\t\t\t}\n\t\t\tm_pDoor2 = nil;\n\t\t\tm_bDoor2IsDummy = false;\n\t\t}\n\t}\n\tif (m_pDoor1)\n\t\tm_pDoor1->bUsesCollision = true;\n\tif (m_pDoor2)\n\t\tm_pDoor2->bUsesCollision = true;\n}\n\nvoid CGarage::FindDoorsEntitiesSectorList(CPtrList& list, bool dummy)\n{\n\tCPtrNode* node;\n\tfor (node = list.first; node; node = node->next) {\n\t\tCEntity* pEntity = (CEntity*)node->item;\n\t\tif (pEntity->m_scanCode == CWorld::GetCurrentScanCode())\n\t\t\tcontinue;\n\t\tpEntity->m_scanCode = CWorld::GetCurrentScanCode();\n\t\tif (!pEntity || !CGarages::IsModelIndexADoor(pEntity->GetModelIndex()))\n\t\t\tcontinue;\n\t\tif (!IsPointInsideGarage(pEntity->GetPosition(), 2.0f))\n\t\t\tcontinue;\n\t\tif (!m_pDoor1) {\n\t\t\tm_pDoor1 = pEntity;\n\t\t\tm_bDoor1IsDummy = dummy;\n\t\t\tif (dummy)\n\t\t\t\tm_bDoor1PoolIndex = (CPools::GetDummyPool()->GetIndex((CDummy*)pEntity)) & 0x7F;\n\t\t\telse\n\t\t\t\tm_bDoor1PoolIndex = (CPools::GetObjectPool()->GetIndex((CObject*)pEntity)) & 0x7F;\n\t\t\tcontinue;\n\t\t}\n\t\telse {\n\t\t\tm_pDoor2 = pEntity;\n\t\t\tm_bDoor2IsDummy = dummy;\n\t\t\tif (dummy)\n\t\t\t\tm_bDoor2PoolIndex = (CPools::GetDummyPool()->GetIndex((CDummy*)pEntity)) & 0x7F;\n\t\t\telse\n\t\t\t\tm_bDoor2PoolIndex = (CPools::GetObjectPool()->GetIndex((CObject*)pEntity)) & 0x7F;\n\t\t}\n\t}\n}\n\nbool CGarages::HasResprayHappened(int16 garage)\n{\n\tbool result = aGarages[garage].m_bResprayHappened;\n\taGarages[garage].m_bResprayHappened = false;\n\treturn result;\n}\n\nvoid CGarages::SetGarageDoorToRotate(int16 garage)\n{\n\tif (aGarages[garage].m_bRotatedDoor)\n\t\treturn;\n\taGarages[garage].m_bRotatedDoor = true;\n\taGarages[garage].m_fDoorHeight /= 2.0f;\n\taGarages[garage].m_fDoorHeight -= 0.1f;\n\taGarages[garage].m_fDoorPos = Min(aGarages[garage].m_fDoorHeight, aGarages[garage].m_fDoorPos);\n\taGarages[garage].UpdateDoorsHeight();\n}\n\nvoid CGarages::SetLeaveCameraForThisGarage(int16 garage)\n{\n\taGarages[garage].m_bCameraFollowsPlayer = true;\n}\n\nbool CGarages::IsThisCarWithinGarageArea(int16 garage, CEntity * pCar)\n{\n\treturn aGarages[garage].IsEntityEntirelyInside3D(pCar, 0.0f);\n}\n\nbool CGarages::HasCarBeenCrushed(int32 handle)\n{\n\treturn CrushedCarId == handle;\n}\n\nvoid CStoredCar::StoreCar(CVehicle* pVehicle)\n{\n\tm_nModelIndex = pVehicle->GetModelIndex();\n\tm_vecPos = pVehicle->GetPosition();\n\tm_vecAngle = pVehicle->GetForward();\n\tm_nPrimaryColor = pVehicle->m_currentColour1;\n\tm_nSecondaryColor = pVehicle->m_currentColour2;\n\tm_nRadioStation = pVehicle->m_nRadioStation;\n\tm_nVariationA = pVehicle->m_aExtras[0];\n\tm_nVariationB = pVehicle->m_aExtras[1];\n\tm_bBulletproof = pVehicle->bBulletProof;\n\tm_bFireproof = pVehicle->bFireProof;\n\tm_bExplosionproof = pVehicle->bExplosionProof;\n\tm_bCollisionproof = pVehicle->bCollisionProof;\n\tm_bMeleeproof = pVehicle->bMeleeProof;\n\tif (pVehicle->IsCar() || pVehicle->IsBike())\n\t\tm_nCarBombType = ((CAutomobile*)pVehicle)->m_bombType; // NB: cast to CAutomobile is original behaviour\n}\n\nCVehicle* CStoredCar::RestoreCar()\n{\n\tCStreaming::RequestModel(m_nModelIndex, STREAMFLAGS_DEPENDENCY);\n\tif (!CStreaming::HasModelLoaded(m_nModelIndex))\n\t\treturn nil;\n#ifdef FIX_BUGS\n\tCVehicleModelInfo* pModelInfo = (CVehicleModelInfo*)CModelInfo::GetModelInfo(m_nModelIndex);\n\tassert(pModelInfo);\n\tif (pModelInfo->m_numComps != 0)\n#endif\n\t{\n\t\tCVehicleModelInfo::SetComponentsToUse(m_nVariationA, m_nVariationB);\n\t}\n\tCVehicle* pVehicle;\n\tif (CModelInfo::IsBoatModel(m_nModelIndex))\n\t\tpVehicle = new CBoat(m_nModelIndex, RANDOM_VEHICLE);\n\telse if (CModelInfo::IsBikeModel(m_nModelIndex))\n\t{\n\t\tCBike* pBike = new CBike(m_nModelIndex, RANDOM_VEHICLE);\n\t\tpBike->bIsStanding = true;\n\t\tpVehicle = pBike;\n\t}\n\telse\n\t\tpVehicle = new CAutomobile(m_nModelIndex, RANDOM_VEHICLE);\n\tpVehicle->SetPosition(m_vecPos);\n\tpVehicle->SetStatus(STATUS_ABANDONED);\n\tpVehicle->GetForward() = m_vecAngle;\n\tpVehicle->GetRight() = CVector(m_vecAngle.y, -m_vecAngle.x, 0.0f);\n\tpVehicle->GetUp() = CVector(0.0f, 0.0f, 1.0f);\n\tpVehicle->pDriver = nil;\n\tpVehicle->m_currentColour1 = m_nPrimaryColor;\n\tpVehicle->m_currentColour2 = m_nSecondaryColor;\n\tpVehicle->m_nRadioStation = m_nRadioStation;\n\tpVehicle->bFreebies = false;\n\tif (pVehicle->IsCar())\n\t{\n\t\t((CAutomobile*)pVehicle)->m_bombType = m_nCarBombType;\n#ifdef FIX_BUGS\n\t\tif (m_nCarBombType != CARBOMB_NONE)\n\t\t\t((CAutomobile*)pVehicle)->m_pBombRigger = FindPlayerPed();\n#endif\n\t}\n\tpVehicle->bHasBeenOwnedByPlayer = true;\n\tpVehicle->m_nDoorLock = CARLOCK_UNLOCKED;\n\tpVehicle->bBulletProof = m_bBulletproof;\n\tpVehicle->bFireProof = m_bFireproof;\n\tpVehicle->bExplosionProof = m_bExplosionproof;\n\tpVehicle->bCollisionProof = m_bCollisionproof;\n\tpVehicle->bMeleeProof = m_bMeleeproof;\n\treturn pVehicle;\n}\n\nvoid CGarage::StoreAndRemoveCarsForThisHideout(CStoredCar* aCars, int32 nMax)\n{\n\tfor (int i = 0; i < NUM_GARAGE_STORED_CARS; i++)\n\t\taCars[i].Clear();\n\tint i = CPools::GetVehiclePool()->GetSize();\n\tint index = 0;\n\twhile (i--) {\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetSlot(i);\n\t\tif (!pVehicle)\n\t\t\tcontinue;\n\t\tif (IsPointInsideGarage(pVehicle->GetPosition())) {\n\t\t\tif (pVehicle->VehicleCreatedBy != MISSION_VEHICLE) {\n\t\t\t\tif (index < Max(NUM_GARAGE_STORED_CARS, nMax) && !EntityHasASphereWayOutsideGarage(pVehicle, 1.0f))\n\t\t\t\t\taCars[index++].StoreCar(pVehicle);\n\t\t\t\tCWorld::Players[CWorld::PlayerInFocus].CancelPlayerEnteringCars(pVehicle);\n\t\t\t\tCWorld::Remove(pVehicle);\n\t\t\t\tdelete pVehicle;\n\t\t\t}\n\t\t}\n\t}\n\t// why?\n\tfor (i = index; i < NUM_GARAGE_STORED_CARS; i++)\n\t\taCars[i].Clear();\n}\n\nbool CGarage::RestoreCarsForThisHideout(CStoredCar* aCars)\n{\n\tfor (int i = 0; i < NUM_GARAGE_STORED_CARS; i++) {\n\t\tif (aCars[i].HasCar()) {\n\t\t\tCVehicle* pVehicle = aCars[i].RestoreCar();\n\t\t\tif (pVehicle) {\n\t\t\t\tCWorld::Add(pVehicle);\n\t\t\t\taCars[i].Clear();\n\t\t\t}\n\t\t}\n\t}\n\tfor (int i = 0; i < NUM_GARAGE_STORED_CARS; i++) {\n\t\tif (aCars[i].HasCar())\n\t\t\treturn false;\n\t}\n\treturn true;\n}\n\nbool CGarages::IsPointInAGarageCameraZone(CVector point)\n{\n#ifdef FIX_BUGS\n\tfor (uint32 i = 0; i < NumGarages; i++) {\n#else\n\tfor (int i = 0; i < NUM_GARAGES; i++) {\n#endif\n\t\tswitch (aGarages[i].m_eGarageType) {\n\t\tcase GARAGE_NONE:\n\t\t\tbreak;\n\t\tcase GARAGE_COLLECTCARS_1:\n\t\tcase GARAGE_COLLECTCARS_2:\n\t\tcase GARAGE_COLLECTCARS_3:\n\t\tcase GARAGE_COLLECTCARS_4:\n\t\t\tif (aGarages[i].IsPointInsideGarage(point, MARGIN_FOR_CAMERA_COLLECTCARS))\n\t\t\t\treturn true;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tif (aGarages[i].IsPointInsideGarage(point, MARGIN_FOR_CAMERA_DEFAULT))\n\t\t\t\treturn true;\n\t\t\tbreak;\n\t\t}\n\t}\n\treturn false;\n}\n\nbool CGarages::CameraShouldBeOutside()\n{\n\treturn bCamShouldBeOutisde;\n}\n\nvoid CGarages::GivePlayerDetonator()\n{\n\tCPlayerPed* pPed = FindPlayerPed();\n\tint slot = CWeaponInfo::GetWeaponInfo(WEAPONTYPE_DETONATOR)->m_nWeaponSlot;\n\tpPed->GiveWeapon(WEAPONTYPE_DETONATOR, 1);\n\tpPed->GetWeapon(pPed->GetWeaponSlot(WEAPONTYPE_DETONATOR)).m_eWeaponState = WEAPONSTATE_READY;\n\tpPed->m_nSelectedWepSlot = slot;\n\tif (pPed->m_storedWeapon != WEAPONTYPE_UNIDENTIFIED)\n\t\tpPed->m_storedWeapon = WEAPONTYPE_DETONATOR;\n}\n\nfloat CGarages::FindDoorHeightForMI(int32 mi)\n{\n\treturn CModelInfo::GetModelInfo(mi)->GetColModel()->boundingBox.max.z - CModelInfo::GetModelInfo(mi)->GetColModel()->boundingBox.min.z - 0.1f;\n}\n\nvoid CGarage::TidyUpGarage()\n{\n\tuint32 i = CPools::GetVehiclePool()->GetSize();\n#ifdef FIX_BUGS\n\twhile (i--) {\n#else\n\twhile (--i) {\n#endif\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetSlot(i);\n\t\tif (pVehicle && (pVehicle->IsCar() || pVehicle->IsBike())) {\n\t\t\tif (IsPointInsideGarage(pVehicle->GetPosition())) {\n\t\t\t\tif (pVehicle->GetStatus() == STATUS_WRECKED || pVehicle->GetUp().z < 0.5f) {\n\t\t\t\t\tCWorld::Remove(pVehicle);\n\t\t\t\t\tdelete pVehicle;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid CGarage::TidyUpGarageClose()\n{\n\tuint32 i = CPools::GetVehiclePool()->GetSize();\n#ifdef FIX_BUGS\n\twhile (i--) {\n#else\n\twhile (--i) {\n#endif\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetSlot(i);\n\t\tif (!pVehicle)\n\t\t\tcontinue;\n\t\tif ((!pVehicle->IsCar() && !pVehicle->IsBike()) || pVehicle->GetStatus() != STATUS_WRECKED || !IsEntityTouching3D(pVehicle))\n\t\t\tcontinue;\n\t\tbool bRemove = false;\n\t\tif (m_eGarageState != GS_FULLYCLOSED) {\n\t\t\tCColModel* pColModel = pVehicle->GetColModel();\n\t\t\tfor (int i = 0; i < pColModel->numSpheres; i++) {\n\t\t\t\tCVector pos = pVehicle->GetMatrix() * pColModel->spheres[i].center;\n\t\t\t\tfloat radius = pColModel->spheres[i].radius;\n\t\t\t\tif (!IsPointInsideGarage(pos, radius))\n\t\t\t\t\tbRemove = true;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t\tbRemove = true;\n\t\tif (bRemove) {\n\t\t\t// no MISSION_VEHICLE check???\n\t\t\tCWorld::Remove(pVehicle);\n\t\t\tdelete pVehicle;\n\t\t}\n\t}\n}\n\nvoid CGarages::PlayerArrestedOrDied()\n{\n\tstatic int GarageToBeTidied = 0; // lol\n#ifdef FIX_BUGS\n\tfor (uint32 i = 0; i < NumGarages; i++) {\n#else\n\tfor (int i = 0; i < NUM_GARAGES; i++) {\n#endif\n\t\tif (aGarages[i].m_eGarageType != GARAGE_NONE)\n\t\t\taGarages[i].PlayerArrestedOrDied();\n\t}\n\tMessageEndTime = 0;\n\tMessageStartTime = 0;\n}\n\nvoid CGarage::PlayerArrestedOrDied()\n{\n\tswitch (m_eGarageType) {\n\tcase GARAGE_MISSION:\n\tcase GARAGE_COLLECTORSITEMS:\n\tcase GARAGE_COLLECTSPECIFICCARS:\n\tcase GARAGE_COLLECTCARS_1:\n\tcase GARAGE_COLLECTCARS_2:\n\tcase GARAGE_COLLECTCARS_3:\n\tcase GARAGE_FORCARTOCOMEOUTOF:\n\tcase GARAGE_60SECONDS:\n\tcase GARAGE_MISSION_KEEPCAR:\n\tcase GARAGE_FOR_SCRIPT_TO_OPEN:\n\tcase GARAGE_HIDEOUT_ONE:\n\tcase GARAGE_HIDEOUT_TWO:\n\tcase GARAGE_HIDEOUT_THREE:\n\tcase GARAGE_FOR_SCRIPT_TO_OPEN_AND_CLOSE:\n\tcase GARAGE_KEEPS_OPENING_FOR_SPECIFIC_CAR:\n\tcase GARAGE_MISSION_KEEPCAR_REMAINCLOSED:\n\tcase GARAGE_COLLECTCARS_4:\n\tcase GARAGE_FOR_SCRIPT_TO_OPEN_FOR_CAR:\n\tcase GARAGE_HIDEOUT_FOUR:\n\tcase GARAGE_HIDEOUT_FIVE:\n\tcase GARAGE_HIDEOUT_SIX:\n\tcase GARAGE_HIDEOUT_SEVEN:\n\tcase GARAGE_HIDEOUT_EIGHT:\n\tcase GARAGE_HIDEOUT_NINE:\n\tcase GARAGE_HIDEOUT_TEN:\n\tcase GARAGE_HIDEOUT_ELEVEN:\n\tcase GARAGE_HIDEOUT_TWELVE:\n\t\tswitch (m_eGarageState) {\n\t\tcase GS_OPENED:\n\t\tcase GS_CLOSING:\n\t\tcase GS_OPENING:\n\t\t\tm_eGarageState = GS_CLOSING;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\t\tbreak;\n\tcase GARAGE_BOMBSHOP1:\n\tcase GARAGE_BOMBSHOP2:\n\tcase GARAGE_BOMBSHOP3:\n\tcase GARAGE_RESPRAY:\n\tcase GARAGE_CRUSHER:\n\t\tswitch (m_eGarageState) {\n\t\tcase GS_FULLYCLOSED:\n\t\tcase GS_CLOSING:\n\t\tcase GS_OPENING:\n\t\t\tm_eGarageState = GS_OPENING;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\t\tbreak;\n\tdefault:\n\t\tbreak;\n\t}\n}\n\nvoid CGarage::CenterCarInGarage(CVehicle* pVehicle)\n{\n\tif (IsAnyOtherCarTouchingGarage(FindPlayerVehicle()))\n\t\treturn;\n\tif (IsAnyOtherPedTouchingGarage(FindPlayerPed()))\n\t\treturn;\n\tCVector pos = pVehicle->GetPosition();\n\tfloat garageX = GetGarageCenterX();\n\tfloat garageY = GetGarageCenterY();\n\tfloat offsetX = garageX - pos.x;\n\tfloat offsetY = garageY - pos.y;\n\tfloat offsetZ = pos.z - pos.z;\n\tfloat distance = CVector(offsetX, offsetY, offsetZ).Magnitude();\n\tif (distance < RESPRAY_CENTERING_COEFFICIENT) {\n\t\tpVehicle->GetMatrix().GetPosition().x = GetGarageCenterX();\n\t\tpVehicle->GetMatrix().GetPosition().y = GetGarageCenterY();\n\t}\n\telse {\n\t\tpVehicle->GetMatrix().GetPosition().x += offsetX * RESPRAY_CENTERING_COEFFICIENT / distance;\n\t\tpVehicle->GetMatrix().GetPosition().y += offsetY * RESPRAY_CENTERING_COEFFICIENT / distance;\n\t}\n\tif (!IsEntityEntirelyInside3D(pVehicle, 0.3f))\n\t\tpVehicle->SetPosition(pos);\n}\n\nvoid CGarages::CloseHideOutGaragesBeforeSave()\n{\n#ifdef FIX_BUGS\n\tfor (uint32 i = 0; i < NumGarages; i++) {\n#else\n\tfor (int i = 0; i < NUM_GARAGES; i++) {\n#endif\n\t\tif (!IsThisGarageTypeSafehouse(aGarages[i].m_eGarageType))\n\t\t\tcontinue;\n\t\tif (aGarages[i].m_eGarageState != GS_FULLYCLOSED) {\n\t\t\taGarages[i].m_eGarageState = GS_FULLYCLOSED;\n\t\t\taGarages[i].StoreAndRemoveCarsForThisHideout(aCarsInSafeHouses[FindSafeHouseIndexForGarageType(aGarages[i].m_eGarageType)], NUM_GARAGE_STORED_CARS);\n\t\t\taGarages[i].RemoveCarsBlockingDoorNotInside();\n\t\t\taGarages[i].m_fDoorPos = 0.0f;\n\t\t\taGarages[i].UpdateDoorsHeight();\n\t\t}\n\t}\n}\n\nint32 CGarages::CountCarsInHideoutGarage(uint8 type)\n{\n\tint32 total = 0;\n\tfor (int i = 0; i < NUM_GARAGE_STORED_CARS; i++) {\n\t\ttotal += aCarsInSafeHouses[FindSafeHouseIndexForGarageType(type)][i].HasCar();\n\t}\n\treturn total;\n}\n\nbool CGarages::IsPointWithinHideOutGarage(Const CVector& point)\n{\n#ifdef FIX_BUGS\n\tfor (uint32 i = 0; i < NumGarages; i++) {\n#else\n\tfor (int i = 0; i < NUM_GARAGES; i++) {\n#endif\n\t\tswitch (aGarages[i].m_eGarageType) {\n\t\tcase GARAGE_HIDEOUT_ONE:\n\t\tcase GARAGE_HIDEOUT_TWO:\n\t\tcase GARAGE_HIDEOUT_THREE:\n\t\tcase GARAGE_HIDEOUT_FOUR:\n\t\tcase GARAGE_HIDEOUT_FIVE:\n\t\tcase GARAGE_HIDEOUT_SIX:\n\t\tcase GARAGE_HIDEOUT_SEVEN:\n\t\tcase GARAGE_HIDEOUT_EIGHT:\n\t\tcase GARAGE_HIDEOUT_NINE:\n\t\tcase GARAGE_HIDEOUT_TEN:\n\t\tcase GARAGE_HIDEOUT_ELEVEN:\n\t\tcase GARAGE_HIDEOUT_TWELVE:\n\t\t\tif (aGarages[i].IsPointInsideGarage(point))\n\t\t\t\treturn true;\n\t\tdefault: break;\n\t\t}\n\t}\n\treturn false;\n}\n\nbool CGarages::IsPointWithinAnyGarage(Const CVector& point)\n{\n#ifdef FIX_BUGS\n\tfor (uint32 i = 0; i < NumGarages; i++) {\n#else\n\tfor (int i = 0; i < NUM_GARAGES; i++) {\n#endif\n\t\tswitch (aGarages[i].m_eGarageType) {\n\t\tcase GARAGE_NONE:\n\t\t\tcontinue;\n\t\tdefault:\n\t\t\tif (aGarages[i].IsPointInsideGarage(point))\n\t\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n\nvoid CGarages::SetAllDoorsBackToOriginalHeight()\n{\n#ifdef FIX_BUGS\n\tfor (uint32 i = 0; i < NumGarages; i++) {\n#else\n\tfor (int i = 0; i < NUM_GARAGES; i++) {\n#endif\n\t\tswitch (aGarages[i].m_eGarageType) {\n\t\tcase GARAGE_NONE:\n\t\t\tcontinue;\n\t\tdefault:\n\t\t\taGarages[i].RefreshDoorPointers(true);\n\t\t\tif (aGarages[i].m_pDoor1) {\n\t\t\t\taGarages[i].m_pDoor1->GetMatrix().GetPosition().x = aGarages[i].m_fDoor1X;\n\t\t\t\taGarages[i].m_pDoor1->GetMatrix().GetPosition().y = aGarages[i].m_fDoor1Y;\n\t\t\t\taGarages[i].m_pDoor1->GetMatrix().GetPosition().z = aGarages[i].m_fDoor1Z;\n\t\t\t\tif (aGarages[i].m_pDoor1->IsObject())\n\t\t\t\t\t((CObject*)aGarages[i].m_pDoor1)->m_objectMatrix.GetPosition().z = aGarages[i].m_fDoor1Z;\n\t\t\t\tif (aGarages[i].m_bRotatedDoor)\n\t\t\t\t\taGarages[i].BuildRotatedDoorMatrix(aGarages[i].m_pDoor1, 0.0f);\n\t\t\t\taGarages[i].m_pDoor1->GetMatrix().UpdateRW();\n\t\t\t\taGarages[i].m_pDoor1->UpdateRwFrame();\n\t\t\t}\n\t\t\tif (aGarages[i].m_pDoor2) {\n\t\t\t\taGarages[i].m_pDoor2->GetMatrix().GetPosition().x = aGarages[i].m_fDoor2X;\n\t\t\t\taGarages[i].m_pDoor2->GetMatrix().GetPosition().y = aGarages[i].m_fDoor2Y;\n\t\t\t\taGarages[i].m_pDoor2->GetMatrix().GetPosition().z = aGarages[i].m_fDoor2Z;\n\t\t\t\tif (aGarages[i].m_pDoor2->IsObject())\n\t\t\t\t\t((CObject*)aGarages[i].m_pDoor2)->m_objectMatrix.GetPosition().z = aGarages[i].m_fDoor2Z;\n\t\t\t\tif (aGarages[i].m_bRotatedDoor)\n\t\t\t\t\taGarages[i].BuildRotatedDoorMatrix(aGarages[i].m_pDoor2, 0.0f);\n\t\t\t\taGarages[i].m_pDoor2->GetMatrix().UpdateRW();\n\t\t\t\taGarages[i].m_pDoor2->UpdateRwFrame();\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid CGarages::Save(uint8 * buf, uint32 * size)\n{\n//INITSAVEBUF\n\t*size = 7876; // for some reason it's not actual size again\n\t//*size = (6 * sizeof(uint32) + TOTAL_COLLECTCARS_GARAGES * sizeof(*CarTypesCollected) + sizeof(uint32) + TOTAL_HIDEOUT_GARAGES * NUM_GARAGE_STORED_CARS * sizeof(CStoredCar) + NUM_GARAGES * sizeof(CGarage));\n\tCloseHideOutGaragesBeforeSave();\n\tWriteSaveBuf(buf, NumGarages);\n\tWriteSaveBuf(buf, (uint32)BombsAreFree);\n\tWriteSaveBuf(buf, (uint32)RespraysAreFree);\n\tWriteSaveBuf(buf, CarsCollected);\n\tWriteSaveBuf(buf, BankVansCollected);\n\tWriteSaveBuf(buf, PoliceCarsCollected);\n\tfor (int i = 0; i < TOTAL_COLLECTCARS_GARAGES; i++)\n\t\tWriteSaveBuf(buf, CarTypesCollected[i]);\n\tWriteSaveBuf(buf, LastTimeHelpMessage);\n\tfor (int i = 0; i < NUM_GARAGE_STORED_CARS; i++) {\n\t\tfor (int j = 0; j < TOTAL_HIDEOUT_GARAGES; j++) {\n\t\t\tWriteSaveBuf(buf, aCarsInSafeHouses[j][i]);\n\t\t}\n\t}\n\tfor (int i = 0; i < NUM_GARAGES; i++)\n\t\tWriteSaveBuf(buf, aGarages[i]);\n//VALIDATESAVEBUF(*size);\n}\n\nconst CStoredCar &CStoredCar::operator=(const CStoredCar & other)\n{\n\tm_nModelIndex = other.m_nModelIndex;\n\tm_vecPos = other.m_vecPos;\n\tm_vecAngle = other.m_vecAngle;\n\tm_bBulletproof = other.m_bBulletproof;\n\tm_bFireproof = other.m_bFireproof;\n\tm_bExplosionproof = other.m_bExplosionproof;\n\tm_bCollisionproof = other.m_bCollisionproof;\n\tm_bMeleeproof = other.m_bMeleeproof;\n\tm_nPrimaryColor = other.m_nPrimaryColor;\n\tm_nSecondaryColor = other.m_nSecondaryColor;\n\tm_nRadioStation = other.m_nRadioStation;\n\tm_nVariationA = other.m_nVariationA;\n\tm_nVariationB = other.m_nVariationB;\n\tm_nCarBombType = other.m_nCarBombType;\n\treturn *this;\n}\n\nvoid CGarages::Load(uint8* buf, uint32 size)\n{\n//INITSAVEBUF\n\tassert(size = 7876);\n\t//assert(size == (6 * sizeof(uint32) + TOTAL_COLLECTCARS_GARAGES * sizeof(*CarTypesCollected) + sizeof(uint32) + TOTAL_HIDEOUT_GARAGES * NUM_GARAGE_STORED_CARS * sizeof(CStoredCar) + NUM_GARAGES * sizeof(CGarage)));\n\tCloseHideOutGaragesBeforeSave();\n\tNumGarages = ReadSaveBuf<uint32>(buf);\n\tBombsAreFree = ReadSaveBuf<uint32>(buf);\n\tRespraysAreFree = ReadSaveBuf<uint32>(buf);\n\tCarsCollected = ReadSaveBuf<int32>(buf);\n\tBankVansCollected = ReadSaveBuf<int32>(buf);\n\tPoliceCarsCollected = ReadSaveBuf<int32>(buf);\n\tfor (int i = 0; i < TOTAL_COLLECTCARS_GARAGES; i++)\n\t\tCarTypesCollected[i] = ReadSaveBuf<uint32>(buf);\n\tLastTimeHelpMessage = ReadSaveBuf<uint32>(buf);\n\tfor (int i = 0; i < NUM_GARAGE_STORED_CARS; i++) {\n\t\tfor (int j = 0; j < TOTAL_HIDEOUT_GARAGES; j++) {\n\t\t\taCarsInSafeHouses[j][i] = ReadSaveBuf<CStoredCar>(buf);\n\t\t}\n\t}\n\tfor (int i = 0; i < NUM_GARAGES; i++) {\n\t\taGarages[i] = ReadSaveBuf<CGarage>(buf);\n\t\taGarages[i].m_pDoor1 = nil;\n\t\taGarages[i].m_pDoor2 = nil;\n\t\taGarages[i].m_pTarget = nil;\n\t\taGarages[i].m_bRecreateDoorOnNextRefresh = true;\n\t\taGarages[i].RefreshDoorPointers(true);\n\t\tif (aGarages[i].m_eGarageType == GARAGE_CRUSHER)\n\t\t\taGarages[i].UpdateCrusherAngle();\n\t\telse\n\t\t\taGarages[i].UpdateDoorsHeight();\n\t}\n//VALIDATESAVEBUF(size);\n\n\tMessageEndTime = 0;\n\tbCamShouldBeOutisde = false;\n\tMessageStartTime = 0;\n}\n\nbool\nCGarages::IsModelIndexADoor(uint32 id)\n{\n\treturn id == MI_GARAGEDOOR2 ||\n\t\tid == MI_GARAGEDOOR3 ||\n\t\tid == MI_GARAGEDOOR4 ||\n\t\tid == MI_GARAGEDOOR5 ||\n\t\tid == MI_GARAGEDOOR6 ||\n\t\tid == MI_GARAGEDOOR7 ||\n\t\tid == MI_GARAGEDOOR9 ||\n\t\tid == MI_GARAGEDOOR10 ||\n\t\tid == MI_GARAGEDOOR11 ||\n\t\tid == MI_GARAGEDOOR12 ||\n\t\tid == MI_GARAGEDOOR13 ||\n\t\tid == MI_GARAGEDOOR14 ||\n\t\tid == MI_GARAGEDOOR15 ||\n\t\tid == MI_GARAGEDOOR16 ||\n\t\tid == MI_GARAGEDOOR18 ||\n\t\tid == MI_GARAGEDOOR19 ||\n\t\tid == MI_GARAGEDOOR20 ||\n\t\tid == MI_GARAGEDOOR21 ||\n\t\tid == MI_GARAGEDOOR22 ||\n\t\tid == MI_GARAGEDOOR23 ||\n\t\tid == MI_GARAGEDOOR24 ||\n\t\tid == MI_GARAGEDOOR25 ||\n\t\tid == MI_GARAGEDOOR26;\n}\n\nvoid CGarages::StopCarFromBlowingUp(CAutomobile* pCar)\n{\n\tpCar->m_fFireBlowUpTimer = 0.0f;\n\tpCar->m_fHealth = Max(pCar->m_fHealth, 300.0f);\n\tpCar->Damage.SetEngineStatus(Max(pCar->Damage.GetEngineStatus(), 275));\n}\n\nbool CGarage::Does60SecondsNeedThisCarAtAll(int mi)\n{\n\tfor (int i = 0; i < ARRAY_SIZE(gaCarsToCollectIn60Seconds); i++) {\n\t\tif (gaCarsToCollectIn60Seconds[i] == mi)\n\t\t\treturn true;\n\t}\n\treturn false;\n}\n\nbool CGarage::Does60SecondsNeedThisCar(int mi)\n{\n\tfor (int i = 0; i < ARRAY_SIZE(gaCarsToCollectIn60Seconds); i++) {\n\t\tif (gaCarsToCollectIn60Seconds[i] == mi)\n\t\t\treturn m_bCollectedCarsState & BIT(i);\n\t}\n\treturn false;\n}\n\nvoid CGarage::MarkThisCarAsCollectedFor60Seconds(int mi)\n{\n\tfor (int i = 0; i < ARRAY_SIZE(gaCarsToCollectIn60Seconds); i++) {\n\t\tif (gaCarsToCollectIn60Seconds[i] == mi)\n\t\t\tm_bCollectedCarsState |= BIT(i);\n\t}\n}\n\nbool CGarage::IsPlayerEntirelyInsideGarage()\n{\n\treturn IsEntityEntirelyInside3D(FindPlayerVehicle() ? (CEntity*)FindPlayerVehicle() : (CEntity*)FindPlayerPed(), 0.0f);\n}\n"
  },
  {
    "path": "src/control/Garages.h",
    "content": "#pragma once\n#include \"audio_enums.h\"\n#include \"Camera.h\"\n#include \"config.h\"\n#include \"Lists.h\"\n\nclass CVehicle;\n\nenum eGarageState\n{\n\tGS_FULLYCLOSED,\n\tGS_OPENED,\n\tGS_CLOSING,\n\tGS_OPENING,\n\tGS_OPENEDCONTAINSCAR,\n\tGS_CLOSEDCONTAINSCAR,\n\tGS_AFTERDROPOFF,\n};\n\nenum eGarageType\n{\n\tGARAGE_NONE,\n\tGARAGE_MISSION,\n\tGARAGE_BOMBSHOP1,\n\tGARAGE_BOMBSHOP2,\n\tGARAGE_BOMBSHOP3,\n\tGARAGE_RESPRAY,\n\tGARAGE_COLLECTORSITEMS,\n\tGARAGE_COLLECTSPECIFICCARS,\n\tGARAGE_COLLECTCARS_1,\n\tGARAGE_COLLECTCARS_2,\n\tGARAGE_COLLECTCARS_3,\n\tGARAGE_FORCARTOCOMEOUTOF,\n\tGARAGE_60SECONDS,\n\tGARAGE_CRUSHER,\n\tGARAGE_MISSION_KEEPCAR,\n\tGARAGE_FOR_SCRIPT_TO_OPEN,\n\tGARAGE_HIDEOUT_ONE,\n\tGARAGE_HIDEOUT_TWO,\n\tGARAGE_HIDEOUT_THREE,\n\tGARAGE_FOR_SCRIPT_TO_OPEN_AND_CLOSE,\n\tGARAGE_KEEPS_OPENING_FOR_SPECIFIC_CAR,\n\tGARAGE_MISSION_KEEPCAR_REMAINCLOSED,\n\tGARAGE_COLLECTCARS_4,\n\tGARAGE_FOR_SCRIPT_TO_OPEN_FOR_CAR,\n\tGARAGE_HIDEOUT_FOUR,\n\tGARAGE_HIDEOUT_FIVE,\n\tGARAGE_HIDEOUT_SIX,\n\tGARAGE_HIDEOUT_SEVEN,\n\tGARAGE_HIDEOUT_EIGHT,\n\tGARAGE_HIDEOUT_NINE,\n\tGARAGE_HIDEOUT_TEN,\n\tGARAGE_HIDEOUT_ELEVEN,\n\tGARAGE_HIDEOUT_TWELVE\n};\n\nenum\n{\n\tTOTAL_COLLECTCARS_GARAGES = 4,\n\tTOTAL_HIDEOUT_GARAGES = 12,\n\tTOTAL_COLLECTCARS_CARS = 6\n};\n\nclass CStoredCar\n{\n\tint32 m_nModelIndex;\n\tCVector m_vecPos;\n\tCVector m_vecAngle;\n\tint32 m_bBulletproof : 1;\n\tint32 m_bFireproof : 1;\n\tint32 m_bExplosionproof : 1;\n\tint32 m_bCollisionproof : 1;\n\tint32 m_bMeleeproof : 1;\n\tint8 m_nPrimaryColor;\n\tint8 m_nSecondaryColor;\n\tint8 m_nRadioStation;\n\tint8 m_nVariationA;\n\tint8 m_nVariationB;\n\tint8 m_nCarBombType;\npublic:\n\tvoid Init() { m_nModelIndex = 0; }\n\tvoid Clear() { m_nModelIndex = 0; }\n\tbool HasCar() { return m_nModelIndex != 0; }\n\tconst CStoredCar &operator=(const CStoredCar& other);\n\tvoid StoreCar(CVehicle*);\n\tCVehicle* RestoreCar();\n};\n\nVALIDATE_SIZE(CStoredCar, 0x28);\n\n#define SWITCH_GARAGE_DISTANCE_CLOSE 40.0f\n\nclass CGarage\n{\npublic:\n\tuint8 m_eGarageType;\n\tuint8 m_eGarageState;\n\tuint8 m_nMaxStoredCars;\n\tbool field_2; // unused\n\tbool m_bClosingWithoutTargetCar;\n\tbool m_bDeactivated;\n\tbool m_bResprayHappened;\n\tint m_nTargetModelIndex;\n\tCEntity *m_pDoor1;\n\tCEntity *m_pDoor2;\n\tuint8 m_bDoor1PoolIndex;\n\tuint8 m_bDoor2PoolIndex;\n\tbool m_bDoor1IsDummy;\n\tbool m_bDoor2IsDummy;\n\tbool m_bRecreateDoorOnNextRefresh;\n\tbool m_bRotatedDoor;\n\tbool m_bCameraFollowsPlayer;\n\tCVector2D m_vecCorner1;\n\tfloat m_fInfZ;\n\tCVector2D m_vDir1;\n\tCVector2D m_vDir2;\n\tfloat m_fSupZ;\n\tfloat m_fDir1Len;\n\tfloat m_fDir2Len;\n\tfloat m_fInfX;\n\tfloat m_fSupX;\n\tfloat m_fInfY;\n\tfloat m_fSupY;\n\tfloat m_fDoorPos;\n\tfloat m_fDoorHeight;\n\tfloat m_fDoor1X;\n\tfloat m_fDoor1Y;\n\tfloat m_fDoor2X;\n\tfloat m_fDoor2Y;\n\tfloat m_fDoor1Z;\n\tfloat m_fDoor2Z;\n\tuint32 m_nTimeToStartAction;\n\tuint8 m_bCollectedCarsState;\n\tCVehicle *m_pTarget;\n\tCStoredCar m_sStoredCar; // not needed\n\n\tvoid OpenThisGarage();\n\tvoid CloseThisGarage();\n\tbool IsOpen() { return m_eGarageState == GS_OPENED || m_eGarageState == GS_OPENEDCONTAINSCAR; }\n\tbool IsClosed() { return m_eGarageState == GS_FULLYCLOSED; }\n\tbool IsUsed() { return m_eGarageType != GARAGE_NONE; }\n\tvoid Update();\n\tfloat GetGarageCenterX() { return (m_fInfX + m_fSupX) / 2; }\n\tfloat GetGarageCenterY() { return (m_fInfY + m_fSupY) / 2; }\n\tbool IsFar()\n\t{ \n#ifdef FIX_BUGS\n\t\treturn Abs(TheCamera.GetPosition().x - GetGarageCenterX()) > SWITCH_GARAGE_DISTANCE_CLOSE ||\n\t\t\tAbs(TheCamera.GetPosition().y - GetGarageCenterY()) > SWITCH_GARAGE_DISTANCE_CLOSE;\n#else\n\t\treturn Abs(TheCamera.GetPosition().x - m_fInfX) > SWITCH_GARAGE_DISTANCE_CLOSE ||\n\t\t\tAbs(TheCamera.GetPosition().y - m_fInfY) > SWITCH_GARAGE_DISTANCE_CLOSE;\n#endif\n\t}\n\tvoid TidyUpGarageClose();\n\tvoid TidyUpGarage();\n\tvoid RefreshDoorPointers(bool);\n\tvoid UpdateCrusherAngle();\n\tvoid UpdateDoorsHeight();\n\tbool IsEntityEntirelyInside3D(CEntity*, float);\n\tbool IsEntityEntirelyOutside(CEntity*, float);\n\tfloat CalcDistToGarageRectangleSquared(float, float);\n\tfloat CalcSmallestDistToGarageDoorSquared(float, float);\n\tbool IsAnyOtherCarTouchingGarage(CVehicle* pException);\n\tbool IsStaticPlayerCarEntirelyInside();\n\tbool IsPlayerOutsideGarage();\n\tbool IsAnyCarBlockingDoor();\n\tvoid CenterCarInGarage(CVehicle*);\n\tbool DoesCraigNeedThisCar(int32);\n\tbool MarkThisCarAsCollectedForCraig(int32);\n\tbool HasCraigCollectedThisCar(int32);\n\tbool IsGarageEmpty();\n\tvoid UpdateCrusherShake(float, float);\n\tint32 CountCarsWithCenterPointWithinGarage(CEntity* pException);\n\tvoid RemoveCarsBlockingDoorNotInside();\n\tvoid StoreAndRemoveCarsForThisHideout(CStoredCar*, int32);\n\tbool RestoreCarsForThisHideout(CStoredCar*);\n\tbool IsEntityTouching3D(CEntity*);\n\tbool EntityHasASphereWayOutsideGarage(CEntity*, float);\n\tbool IsAnyOtherPedTouchingGarage(CPed* pException);\n\tvoid BuildRotatedDoorMatrix(CEntity*, float);\n\tvoid FindDoorsEntities();\n\tvoid FindDoorsEntitiesSectorList(CPtrList&, bool);\n\tvoid PlayerArrestedOrDied();\n\tbool Does60SecondsNeedThisCarAtAll(int mi);\n\tbool Does60SecondsNeedThisCar(int mi);\n\tvoid MarkThisCarAsCollectedFor60Seconds(int mi);\n\tbool IsPlayerEntirelyInsideGarage();\n\n\tbool IsPointInsideGarage(CVector);\n\tbool IsPointInsideGarage(CVector, float);\n\tvoid ThrowCarsNearDoorOutOfGarage(CVehicle*);\n\n\tint32 FindMaxNumStoredCarsForGarage() { return Min(NUM_GARAGE_STORED_CARS, m_nMaxStoredCars); }\n\n};\n\nclass CGarages\n{\n\tenum {\n\t\tMESSAGE_LENGTH = 8,\n\t};\npublic:\n\tstatic int32 BankVansCollected;\n\tstatic bool BombsAreFree;\n\tstatic bool RespraysAreFree;\n\tstatic int32 CarsCollected;\n\tstatic int32 CarTypesCollected[TOTAL_COLLECTCARS_GARAGES];\n\tstatic int32 CrushedCarId;\n\tstatic uint32 LastTimeHelpMessage;\n\tstatic int32 MessageNumberInString;\n\tstatic char MessageIDString[MESSAGE_LENGTH];\n\tstatic int32 MessageNumberInString2;\n\tstatic uint32 MessageStartTime;\n\tstatic uint32 MessageEndTime;\n\tstatic uint32 NumGarages;\n\tstatic bool PlayerInGarage;\n\tstatic int32 PoliceCarsCollected;\n\tstatic CGarage aGarages[NUM_GARAGES];\n\tstatic CStoredCar aCarsInSafeHouses[TOTAL_HIDEOUT_GARAGES][NUM_GARAGE_STORED_CARS];\n\tstatic bool bCamShouldBeOutisde;\n\n\tstatic void Init(void);\n#ifndef PS2\n\tstatic void Shutdown(void);\n#endif\n\tstatic void Update(void);\n\n\tstatic int16 AddOne(float X1, float Y1, float Z1, float X2, float Y2, float X3, float Y3, float Z2, uint8 type, int32 targetId);\n\tstatic void ChangeGarageType(int16, uint8, int32);\n\tstatic void PrintMessages(void);\n\tstatic void TriggerMessage(const char* text, int16, uint16 time, int16);\n\tstatic void SetTargetCarForMissonGarage(int16, CVehicle*);\n\tstatic bool HasCarBeenDroppedOffYet(int16);\n\tstatic void DeActivateGarage(int16);\n\tstatic void ActivateGarage(int16);\n\tstatic int32 QueryCarsCollected(int16);\n\tstatic bool HasImportExportGarageCollectedThisCar(int16, int8);\n\tstatic bool IsGarageOpen(int16);\n\tstatic bool IsGarageClosed(int16);\n\tstatic bool HasThisCarBeenCollected(int16, uint8);\n\tstatic void OpenGarage(int16 garage) { aGarages[garage].OpenThisGarage(); }\n\tstatic void CloseGarage(int16 garage) { aGarages[garage].CloseThisGarage(); }\n\tstatic bool HasResprayHappened(int16);\n\tstatic void SetGarageDoorToRotate(int16);\n\tstatic void SetLeaveCameraForThisGarage(int16);\n\tstatic bool IsThisCarWithinGarageArea(int16, CEntity*);\n\tstatic bool HasCarBeenCrushed(int32);\n\tstatic bool IsPointInAGarageCameraZone(CVector);\n\tstatic bool CameraShouldBeOutside(void);\n\tstatic void GivePlayerDetonator(void);\n\tstatic void PlayerArrestedOrDied(void);\n\tstatic bool IsPointWithinHideOutGarage(Const CVector&);\n\tstatic bool IsPointWithinAnyGarage(Const CVector&);\n\tstatic void SetAllDoorsBackToOriginalHeight(void);\n\tstatic void Save(uint8* buf, uint32* size);\n\tstatic void Load(uint8* buf, uint32 size);\n\tstatic bool IsModelIndexADoor(uint32 id);\n\tstatic void SetFreeBombs(bool bValue) { BombsAreFree = bValue; }\n\tstatic void SetFreeResprays(bool bValue) { RespraysAreFree = bValue; }\n\tstatic void StopCarFromBlowingUp(CAutomobile*);\n\tstatic void SetMaxNumStoredCarsForGarage(int16 garage, uint8 num) { aGarages[garage].m_nMaxStoredCars = num; }\n\n\tstatic bool IsCarSprayable(CVehicle*);\n\tstatic float FindDoorHeightForMI(int32);\n\tstatic void CloseHideOutGaragesBeforeSave(void);\n\tstatic int32 CountCarsInHideoutGarage(uint8);\n\tstatic int32 GetBombTypeForGarageType(uint8 type) { return type - GARAGE_BOMBSHOP1 + 1; }\n\tstatic int32 GetCarsCollectedIndexForGarageType(uint8 type)\n\t{\n\t\tswitch (type) {\n\t\tcase GARAGE_COLLECTCARS_1: return 0;\n\t\tcase GARAGE_COLLECTCARS_2: return 1;\n\t\tcase GARAGE_COLLECTCARS_3: return 2;\n\t\tcase GARAGE_COLLECTCARS_4: return 3;\n\t\tdefault: assert(0);\n\t\t}\n\t\treturn 0;\n\t}\n\tstatic int32 FindSafeHouseIndexForGarageType(uint8 type)\n\t{\n\t\tswitch (type) {\n\t\tcase GARAGE_HIDEOUT_ONE: return 0;\n\t\tcase GARAGE_HIDEOUT_TWO: return 1;\n\t\tcase GARAGE_HIDEOUT_THREE: return 2;\n\t\tcase GARAGE_HIDEOUT_FOUR: return 3;\n\t\tcase GARAGE_HIDEOUT_FIVE: return 4;\n\t\tcase GARAGE_HIDEOUT_SIX: return 5;\n\t\tcase GARAGE_HIDEOUT_SEVEN: return 6;\n\t\tcase GARAGE_HIDEOUT_EIGHT: return 7;\n\t\tcase GARAGE_HIDEOUT_NINE: return 8;\n\t\tcase GARAGE_HIDEOUT_TEN: return 9;\n\t\tcase GARAGE_HIDEOUT_ELEVEN: return 10;\n\t\tcase GARAGE_HIDEOUT_TWELVE: return 11;\n\t\t}\n\t\treturn -1;\n\t}\n\tstatic bool IsThisGarageTypeSafehouse(uint8 type) { return FindSafeHouseIndexForGarageType(type) >= 0; }\n\n};\n"
  },
  {
    "path": "src/control/NameGrid.cpp",
    "content": "#include \"common.h\"\n#include \"NameGrid.h\"\n\n// TODO: reverse mobile code\n\nCPlayerName::CPlayerName()\n{\n\t// TODO\n}\n\nvoid\nCPlayerName::DisplayName(int)\n{\n\t// TODO\n}\n\nCRow::CRow()\n{\n\t// TODO\n}\n\nvoid\nCRow::SetLetter(int, wchar *)\n{\n\t// TODO\n}\n\nCGrid::CGrid()\n{\n\t// TODO\n}\n\nvoid\nCGrid::ProcessAnyLeftJustDown()\n{\n\tunk_int2--;\n}\n\nvoid\nCGrid::ProcessAnyRightJustDown()\n{\n\tunk_int2++;\n}\n\nvoid\nCGrid::ProcessAnyUpJustDown()\n{\n\tunk_int1--;\n}\n\nvoid\nCGrid::ProcessAnyDownJustDown()\n{\n\tunk_int1++;\n}\n\nvoid\nCGrid::AllDoneMakePlayerName()\n{\n\t// TODO\n}\n\nvoid\nCGrid::ProcessDPadCrossJustDown()\n{\n\t// TODO\n}\n\nvoid\nCGrid::DisplayGrid()\n{\n\t// TODO\n}\n\nvoid\nCGrid::ProcessControllerInput()\n{\n\t// TODO\n}\n\nvoid\nCGrid::Process()\n{\n\tProcessControllerInput();\n\tDisplayGrid();\n\tplayerName.DisplayName(2 * playerName.unk_4c);\n}"
  },
  {
    "path": "src/control/NameGrid.h",
    "content": "#pragma once\n\n// TODO: reverse mobile code\n\nclass CPlayerName\n{\n\tfriend class CGrid;\n\n\tfloat x;\n\tfloat y;\n\twchar unk_8[34];\n\tint unk_4c;\npublic:\n\tCPlayerName();\n\tvoid DisplayName(int);\n};\n\nclass CRow\n{\n\tfriend class CGrid;\n\n\tint unk_0;\n\tint unk_4;\n\twchar unk_8[20];\n\tint unk_30;\npublic:\n\tCRow();\n\tvoid SetLetter(int, wchar *);\n};\n\nclass CGrid\n{\n\tCRow rows[5];\n\tint unk_int1;\n\tint unk_int2;\n\tint unk_int3;\n\tfloat unk_float1;\n\tfloat unk_float2;\n\tCPlayerName playerName;\n\tchar unk2[4];\n\tchar unk3[4];\npublic:\n\tCGrid();\n\tvoid ProcessAnyLeftJustDown();\n\tvoid ProcessAnyRightJustDown();\n\tvoid ProcessAnyUpJustDown();\n\tvoid ProcessAnyDownJustDown();\n\tvoid AllDoneMakePlayerName();\n\tvoid ProcessDPadCrossJustDown();\n\tvoid DisplayGrid();\n\tvoid ProcessControllerInput();\n\tvoid Process();\n};"
  },
  {
    "path": "src/control/OnscreenTimer.cpp",
    "content": "#include \"common.h\"\n\n\n#include \"DMAudio.h\"\n#include \"Hud.h\"\n#include \"Replay.h\"\n#include \"Timer.h\"\n#include \"Script.h\"\n#include \"OnscreenTimer.h\"\n#include \"Camera.h\"\n\nvoid COnscreenTimer::Init() {\n\tm_bDisabled = false;\n\tfor(uint32 i = 0; i < NUMONSCREENCOUNTERS; i++) {\n\t\tm_sCounters[i].m_nCounterOffset = 0;\n\n\t\tfor(uint32 j = 0; j < ARRAY_SIZE(m_sCounters[0].m_aCounterText); j++) {\n\t\t\tm_sCounters[i].m_aCounterText[j] = 0;\n\t\t}\n\n\t\tm_sCounters[i].m_nType = COUNTER_DISPLAY_NUMBER;\n\t\tm_sCounters[i].m_bCounterProcessed = false;\n\t}\n\tfor(uint32 i = 0; i < NUMONSCREENCLOCKS; i++) {\n\t\tm_sClocks[i].m_nClockOffset = 0;\n\n\t\tfor(uint32 j = 0; j < ARRAY_SIZE(m_sClocks[0].m_aClockText); j++) {\n\t\t\tm_sClocks[i].m_aClockText[j] = 0;\n\t\t}\n\n\t\tm_sClocks[i].m_bClockProcessed = false;\n\t\tm_sClocks[i].m_bClockGoingDown = true;\n\t}\n}\n\nvoid COnscreenTimer::Process() {\n\tif(!CReplay::IsPlayingBack() && !m_bDisabled) {\n\t\tfor(uint32 i = 0; i < NUMONSCREENCLOCKS; i++) {\n\t\t\tm_sClocks[i].Process();\n\t\t}\n\t}\n}\n\nvoid COnscreenTimer::ProcessForDisplay() {\n\tif(CHud::m_Wants_To_Draw_Hud) {\n\t\tm_bProcessed = false;\n\t\tfor(uint32 i = 0; i < NUMONSCREENCLOCKS; i++) {\n\t\t\tm_sClocks[i].m_bClockProcessed = false;\n\t\t\tif (m_sClocks[i].m_nClockOffset != 0) {\n\t\t\t\tm_sClocks[i].ProcessForDisplayClock();\n\t\t\t\tm_sClocks[i].m_bClockProcessed = true;\n\t\t\t\tm_bProcessed = true;\n\t\t\t}\n\t\t}\n\t\tfor(uint32 i = 0; i < NUMONSCREENCOUNTERS; i++) {\n\t\t\tm_sCounters[i].m_bCounterProcessed = false;\n\t\t\tif (m_sCounters[i].m_nCounterOffset != 0) {\n\t\t\t\tm_sCounters[i].ProcessForDisplayCounter();\n\t\t\t\tm_sCounters[i].m_bCounterProcessed = true;\n\t\t\t\tm_bProcessed = true;\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid COnscreenTimer::ClearCounter(uint32 offset) {\n\tfor(uint32 i = 0; i < NUMONSCREENCOUNTERS; i++) {\n\t\tif(offset == m_sCounters[i].m_nCounterOffset) {\n\t\t\tm_sCounters[i].m_nCounterOffset = 0;\n\t\t\tm_sCounters[i].m_aCounterText[0] = 0;\n\t\t\tm_sCounters[i].m_nType = COUNTER_DISPLAY_NUMBER;\n\t\t\tm_sCounters[i].m_bCounterProcessed = 0;\n\t\t}\n\t}\n}\n\nvoid COnscreenTimer::ClearClock(uint32 offset) {\n\tfor(uint32 i = 0; i < NUMONSCREENCLOCKS; i++) {\n\t\tif(offset == m_sClocks[i].m_nClockOffset) {\n\t\t\tm_sClocks[i].m_nClockOffset = 0;\n\t\t\tm_sClocks[i].m_aClockText[0] = 0;\n\t\t\tm_sClocks[i].m_bClockProcessed = 0;\n\t\t\tm_sClocks[i].m_bClockGoingDown = true;\n\t\t}\n\t}\n}\n\nvoid COnscreenTimer::AddCounter(uint32 offset, uint16 type, char* text, uint16 pos) {\n\n\tif (m_sCounters[pos].m_aCounterText[0] != '\\0')\n\t\treturn;\n\n\tm_sCounters[pos].m_nCounterOffset = offset;\n\tif(text) {\n\t\tstrncpy(m_sCounters[pos].m_aCounterText, text, ARRAY_SIZE(m_sCounters[0].m_aCounterText));\n\t} else {\n\t\tm_sCounters[pos].m_aCounterText[0] = 0;\n\t}\n\n\tm_sCounters[pos].m_nType = type;\n}\n\nvoid COnscreenTimer::AddClock(uint32 offset, char* text, bool bGoingDown) {\n\n\t// dead code in here\n\tuint32 i;\n\tfor(i = 0; i < NUMONSCREENCLOCKS; i++) {\n\t\tif(m_sClocks[i].m_nClockOffset == 0) {\n\t\t\tbreak;\n\t\t}\n\t\treturn;\n\t}\n\n\tm_sClocks[i].m_nClockOffset = offset;\n\tm_sClocks[i].m_bClockGoingDown = bGoingDown;\n\tif(text) {\n\t\tstrncpy(m_sClocks[i].m_aClockText, text, ARRAY_SIZE(m_sClocks[0].m_aClockText));\n\t} else {\n\t\tm_sClocks[i].m_aClockText[0] = 0;\n\t}\n}\n\nvoid COnscreenTimerEntry::Process() {\n\tif(m_nClockOffset == 0) {\n\t\treturn;\n\t}\n\n\tint32* timerPtr = CTheScripts::GetPointerToScriptVariable(m_nClockOffset);\n\tint32 oldTime = *timerPtr;\n\tif (m_bClockGoingDown) {\n\t\tint32 newTime = oldTime - int32(CTimer::GetTimeStepInMilliseconds());\n\t\t*timerPtr = newTime;\n\t\tif (newTime < 0) {\n\t\t\t*timerPtr = 0;\n\t\t\tm_bClockProcessed = 0;\n\t\t\tm_nClockOffset = 0;\n\t\t\tm_aClockText[0] = 0;\n\t\t}\n\t\telse {\n\t\t\tint32 oldTimeSeconds = oldTime / 1000;\n\t\t\tif (oldTimeSeconds < 12 && newTime / 1000 != oldTimeSeconds && !TheCamera.m_WideScreenOn) {\n\t\t\t\tDMAudio.PlayFrontEndSound(SOUND_CLOCK_TICK, newTime / 1000);\n\t\t\t}\n\t\t}\n\t}\n\telse\n\t\t*timerPtr = oldTime + int32(CTimer::GetTimeStepInMilliseconds());\n}\n\nvoid COnscreenTimerEntry::ProcessForDisplayClock() {\n\tuint32 time = *CTheScripts::GetPointerToScriptVariable(m_nClockOffset);\n\tsprintf(m_aClockBuffer, \"%02d:%02d\", time / 1000 / 60 % 100,\n\t\t\t\t   time / 1000 % 60);\n}\n\nvoid COnscreenCounterEntry::ProcessForDisplayCounter() {\n\tuint32 counter = *CTheScripts::GetPointerToScriptVariable(m_nCounterOffset);\n\tsprintf(m_aCounterBuffer, \"%d\", counter);\n}\n"
  },
  {
    "path": "src/control/OnscreenTimer.h",
    "content": "#pragma once\n\nenum\n{\n\tCOUNTER_DISPLAY_NUMBER,\n\tCOUNTER_DISPLAY_BAR,\n};\n\nclass COnscreenTimerEntry\n{\npublic:\n\tuint32 m_nClockOffset;\n\tchar m_aClockText[10];\n\tchar m_aClockBuffer[40];\n\tbool m_bClockProcessed;\n\tbool m_bClockGoingDown;\n\n\tvoid Process();\n\tvoid ProcessForDisplayClock();\n};\n\nVALIDATE_SIZE(COnscreenTimerEntry, 0x3C);\n\nclass COnscreenCounterEntry\n{\npublic:\n\tuint32 m_nCounterOffset;\n\tchar m_aCounterText[10];\n\tuint16 m_nType;\n\tchar m_aCounterBuffer[40];\n\tbool m_bCounterProcessed;\n\n\tvoid ProcessForDisplayCounter();\n};\n\nVALIDATE_SIZE(COnscreenCounterEntry, 0x3C);\n\nclass COnscreenTimer\n{\npublic:\n\tCOnscreenTimerEntry m_sClocks[NUMONSCREENCLOCKS];\n\tCOnscreenCounterEntry m_sCounters[NUMONSCREENCOUNTERS];\n\tbool m_bProcessed;\n\tbool m_bDisabled;\n\n\tvoid Init();\n\tvoid Process();\n\tvoid ProcessForDisplay();\n\n\tvoid ClearCounter(uint32 offset);\n\tvoid ClearClock(uint32 offset);\n\n\tvoid AddCounter(uint32 offset, uint16 type, char* text, uint16 pos);\n\tvoid AddClock(uint32 offset, char* text, bool bGoingDown);\n};\n\nVALIDATE_SIZE(COnscreenTimer, 0xF4);\n"
  },
  {
    "path": "src/control/PathFind.cpp",
    "content": "#include \"common.h\"\n\n#include \"General.h\"\n#include \"FileMgr.h\"\t// only needed for empty function\n#include \"Camera.h\"\n#include \"Vehicle.h\"\n#include \"World.h\"\n#include \"Lines.h\"\t// for debug\n#include \"PathFind.h\"\n\nbool gbShowPedPaths;\nbool gbShowCarPaths;\nbool gbShowCarPathsLinks;\n\nCPathFind ThePaths;\n\n#define MAX_DIST INT16_MAX-1\n#define MIN_PED_ROUTE_DISTANCE 23.8f\n\n\n#define NUMTEMPNODES 5000\n#define NUMDETACHED_CARS 1024\n#define NUMDETACHED_PEDS 1214\n#define NUMTEMPEXTERNALNODES 4600\n\nCPathInfoForObject *InfoForTileCars;\nCPathInfoForObject *InfoForTilePeds;\n\nCPathInfoForObject *DetachedInfoForTileCars;\nCPathInfoForObject *DetachedInfoForTilePeds;\nCTempNodeExternal *TempExternalNodes;\nint32 NumTempExternalNodes;\nint32 NumDetachedPedNodeGroups;\nint32 NumDetachedCarNodeGroups;\n\nbool \nCPedPath::CalcPedRoute(int8 pathType, CVector position, CVector destination, CVector *pointPoses, int16 *pointsFound, int16 maxPoints)\n{\n\t*pointsFound = 0;\n\tCVector vecDistance = destination - position;\n\tif (Abs(vecDistance.x) > MIN_PED_ROUTE_DISTANCE || Abs(vecDistance.y) > MIN_PED_ROUTE_DISTANCE || Abs(vecDistance.z) > MIN_PED_ROUTE_DISTANCE)\n\t\treturn false;\n\tCVector vecPos = (position + destination) * 0.5f;\n\tCVector vecSectorStartPos (vecPos.x - 14.0f, vecPos.y - 14.0f, vecPos.z);\n\tCVector2D vecSectorEndPos (vecPos.x + 28.0f, vecPos.x + 28.0f);\n\tconst int16 nodeStartX = (position.x - vecSectorStartPos.x) / 0.7f;\n\tconst int16 nodeStartY = (position.y - vecSectorStartPos.y) / 0.7f;\n\tconst int16 nodeEndX = (destination.x - vecSectorStartPos.x) / 0.7f;\n\tconst int16 nodeEndY = (destination.y - vecSectorStartPos.y) / 0.7f;\n\tif (nodeStartX == nodeEndX && nodeStartY == nodeEndY)\n\t\treturn false;\n\tCPedPathNode pathNodes[40][40]; \n\tCPedPathNode pathNodesList[416];\n\tfor (int32 x = 0; x < 40; x++) {\n\t\tfor (int32 y = 0; y < 40; y++) {\n\t\t\tpathNodes[x][y].bBlockade = false;\n\t\t\tpathNodes[x][y].id = INT16_MAX;\n\t\t\tpathNodes[x][y].nodeIdX = x;\n\t\t\tpathNodes[x][y].nodeIdY = y;\n\t\t}\n\t}\n\tCWorld::AdvanceCurrentScanCode();\n\tif (pathType != ROUTE_NO_BLOCKADE) {\n\t\tconst int32 nStartX = Max(CWorld::GetSectorIndexX(vecSectorStartPos.x), 0);\n\t\tconst int32 nStartY = Max(CWorld::GetSectorIndexY(vecSectorStartPos.y), 0);\n\t\tconst int32 nEndX = Min(CWorld::GetSectorIndexX(vecSectorEndPos.x), NUMSECTORS_X - 1);\n\t\tconst int32 nEndY = Min(CWorld::GetSectorIndexY(vecSectorEndPos.y), NUMSECTORS_Y - 1);\n\t\tfor (int32 y = nStartY; y <= nEndY; y++) {\n\t\t\tfor (int32 x = nStartX; x <= nEndX; x++) {\n\t\t\t\tCSector *pSector = CWorld::GetSector(x, y);\n\t\t\t\tAddBlockadeSectorList(pSector->m_lists[ENTITYLIST_VEHICLES], pathNodes, &vecSectorStartPos);\n\t\t\t\tAddBlockadeSectorList(pSector->m_lists[ENTITYLIST_VEHICLES_OVERLAP], pathNodes, &vecSectorStartPos);\n\t\t\t\tAddBlockadeSectorList(pSector->m_lists[ENTITYLIST_OBJECTS], pathNodes, &vecSectorStartPos);\n\t\t\t\tAddBlockadeSectorList(pSector->m_lists[ENTITYLIST_OBJECTS_OVERLAP], pathNodes, &vecSectorStartPos);\n\t\t\t}\n\t\t}\n\t}\n\tfor (int32 i = 0; i < 416; i++) {\n\t\tpathNodesList[i].prev = nil;\n\t\tpathNodesList[i].next = nil;\n\t}\n\tCPedPathNode *pStartPathNode = &pathNodes[nodeStartX][nodeStartY];\n\tCPedPathNode *pEndPathNode = &pathNodes[nodeEndX][nodeEndY];\n\tpEndPathNode->bBlockade = false;\n\tpEndPathNode->id = 0;\n\tpEndPathNode->prev = nil;\n\tpEndPathNode->next = pathNodesList;\n\tpathNodesList[0].prev = pEndPathNode;\n\tint32 pathNodeIndex = 0;\n\tCPedPathNode *pPreviousNode = nil;\n\tfor (; pathNodeIndex < 414; pathNodeIndex++)\n\t{\n\t\tpPreviousNode = pathNodesList[pathNodeIndex].prev;\n\t\twhile (pPreviousNode && pPreviousNode != pStartPathNode) {\n\t\t\tconst uint8 nodeIdX = pPreviousNode->nodeIdX;\n\t\t\tconst uint8 nodeIdY = pPreviousNode->nodeIdY;\n\t\t\tif (nodeIdX > 0) {\n\t\t\t\tAddNodeToPathList(&pathNodes[nodeIdX - 1][nodeIdY], pathNodeIndex + 5, pathNodesList);\n\t\t\t\tif (nodeIdY > 0)\n\t\t\t\t\tAddNodeToPathList(&pathNodes[nodeIdX - 1][nodeIdY - 1], pathNodeIndex + 7, pathNodesList);\n\t\t\t\tif (nodeIdY < 39)\n\t\t\t\t\tAddNodeToPathList(&pathNodes[nodeIdX - 1][nodeIdY + 1], pathNodeIndex + 7, pathNodesList);\n\t\t\t}\n\t\t\tif (nodeIdX < 39) {\n\t\t\t\tAddNodeToPathList(&pathNodes[nodeIdX + 1][nodeIdY], pathNodeIndex + 5, pathNodesList);\n\t\t\t\tif (nodeIdY > 0)\n\t\t\t\t\tAddNodeToPathList(&pathNodes[nodeIdX + 1][nodeIdY - 1], pathNodeIndex + 7, pathNodesList);\n\t\t\t\tif (nodeIdY < 39)\n\t\t\t\t\tAddNodeToPathList(&pathNodes[nodeIdX + 1][nodeIdY + 1], pathNodeIndex + 7, pathNodesList);\n\t\t\t}\n\t\t\tif (nodeIdY > 0)\n\t\t\t\tAddNodeToPathList(&pathNodes[nodeIdX][nodeIdY - 1], pathNodeIndex + 5, pathNodesList);\n\t\t\tif (nodeIdY < 39)\n\t\t\t\tAddNodeToPathList(&pathNodes[nodeIdX][nodeIdY + 1], pathNodeIndex + 5, pathNodesList);\n\t\t\tpPreviousNode = pPreviousNode->prev;\n\t\t\tif (!pPreviousNode)\n\t\t\t\tbreak;\n\t\t}\n\n\t\tif (pPreviousNode && pPreviousNode == pStartPathNode)\n\t\t\tbreak;\n\t}\n\tif (pathNodeIndex == 414)\n\t\treturn false;\n\tCPedPathNode *pPathNode = pStartPathNode;\n\tfor (*pointsFound = 0; pPathNode != pEndPathNode && *pointsFound < maxPoints; ++ *pointsFound) {\n\t\tconst uint8 nodeIdX = pPathNode->nodeIdX;\n\t\tconst uint8 nodeIdY = pPathNode->nodeIdY;\n\t\tif (nodeIdX > 0 && pathNodes[nodeIdX - 1][nodeIdY].id + 5 == pPathNode->id) \n\t\t\tpPathNode = &pathNodes[nodeIdX - 1][nodeIdY];\n\t\telse if (nodeIdX > 39 && pathNodes[nodeIdX + 1][nodeIdY].id + 5 == pPathNode->id)\n\t\t\tpPathNode = &pathNodes[nodeIdX + 1][nodeIdY];\n\t\telse if (nodeIdY > 0 && pathNodes[nodeIdX][nodeIdY - 1].id + 5 == pPathNode->id) \n\t\t\tpPathNode = &pathNodes[nodeIdX][nodeIdY - 1];\n\t\telse if (nodeIdY > 39 && pathNodes[nodeIdX][nodeIdY + 1].id + 5 == pPathNode->id) \n\t\t\tpPathNode = &pathNodes[nodeIdX][nodeIdY + 1];\n\t\telse if (nodeIdX > 0 && nodeIdY > 0 && pathNodes[nodeIdX - 1][nodeIdY - 1].id + 7 == pPathNode->id)\n\t\t\tpPathNode = &pathNodes[nodeIdX - 1][nodeIdY - 1];\n\t\telse if (nodeIdX > 0 && nodeIdY < 39 && pathNodes[nodeIdX - 1][nodeIdY + 1].id + 7 == pPathNode->id)\n\t\t\tpPathNode = &pathNodes[nodeIdX - 1][nodeIdY + 1];\n\t\telse if (nodeIdX < 39 && nodeIdY > 0 && pathNodes[nodeIdX + 1][nodeIdY - 1].id + 7 == pPathNode->id)\n\t\t\tpPathNode = &pathNodes[nodeIdX + 1][nodeIdY - 1];\n\t\telse if (nodeIdX < 39 && nodeIdY < 39 && pathNodes[nodeIdX + 1][nodeIdY + 1].id + 7 == pPathNode->id)\n\t\t\tpPathNode = &pathNodes[nodeIdX + 1][nodeIdY + 1];\n\t\tpointPoses[*pointsFound] = vecSectorStartPos;\n\t\tpointPoses[*pointsFound].x += pPathNode->nodeIdX * 0.7f;\n\t\tpointPoses[*pointsFound].y += pPathNode->nodeIdY * 0.7f;\n\t}\n\treturn true;\n}\n\n\nvoid \nCPedPath::AddNodeToPathList(CPedPathNode *pNodeToAdd, int16 id, CPedPathNode *pNodeList) \n{\n\tif (!pNodeToAdd->bBlockade && id < pNodeToAdd->id) {\n\t\tif (pNodeToAdd->id != INT16_MAX)\n\t\t\tRemoveNodeFromList(pNodeToAdd);\n\t\tAddNodeToList(pNodeToAdd, id, pNodeList);\n\t}\n}\n\nvoid \nCPedPath::RemoveNodeFromList(CPedPathNode *pNode)\n{\n\tpNode->next->prev = pNode->prev;\n\tif (pNode->prev)\n\t\tpNode->prev->next = pNode->next;\n}\n\nvoid \nCPedPath::AddNodeToList(CPedPathNode *pNode, int16 index, CPedPathNode *pList)\n{\n\tpNode->prev = pList[index].prev;\n\tpNode->next = &pList[index];\n\tif (pList[index].prev)\n\t\tpList[index].prev->next = pNode;\n\tpList[index].prev = pNode;\n\tpNode->id = index;\n}\n\nvoid\nCPedPath::AddBlockadeSectorList(CPtrList& list, CPedPathNode(*pathNodes)[40], CVector *pPosition)\n{\n\tCPtrNode* listNode = list.first;\n\twhile (listNode) {\n\t\tCEntity* pEntity = (CEntity*)listNode->item;\n\t\tif (pEntity->m_scanCode != CWorld::GetCurrentScanCode() && pEntity->bUsesCollision) {\n\t\t\tpEntity->m_scanCode = CWorld::GetCurrentScanCode();\n\t\t\tAddBlockade(pEntity, pathNodes, pPosition);\n\t\t}\n\t\tlistNode = listNode->next;\n\t}\n}\n\nvoid \nCPedPath::AddBlockade(CEntity *pEntity, CPedPathNode(*pathNodes)[40], CVector *pPosition)\n{\n\tconst CBox& boundingBox = pEntity->GetColModel()->boundingBox;\n\tconst float fBoundMaxY = boundingBox.max.y + 0.3f;\n\tconst float fBoundMinY = boundingBox.min.y - 0.3f;\n\tconst float fBoundMaxX = boundingBox.max.x + 0.3f;\n\tconst float fDistanceX = pPosition->x - pEntity->m_matrix.GetPosition().x;\n\tconst float fDistanceY = pPosition->y - pEntity->m_matrix.GetPosition().y;\n\tconst float fBoundRadius = pEntity->GetBoundRadius();\n\tCVector vecBoundCentre;\n\tpEntity->GetBoundCentre(vecBoundCentre);\n\tif (vecBoundCentre.x + fBoundRadius >= pPosition->x && \n\t\tvecBoundCentre.y + fBoundRadius >= pPosition->y &&\n\t\tvecBoundCentre.x - fBoundRadius <= pPosition->x + 28.0f &&\n\t\tvecBoundCentre.y - fBoundRadius <= pPosition->y + 28.0f) {\n\t\tfor (int16 x = 0; x < 40; x++) {\n\t\t\tconst float pointX = x * 0.7f + fDistanceX;\n\t\t\tfor (int16 y = 0; y < 40; y++) {\n\t\t\t\tif (!pathNodes[x][y].bBlockade) {\n\t\t\t\t\tconst float pointY = y * 0.7f + fDistanceY;\n\t\t\t\t\tCVector2D point(pointX, pointY);\n\t\t\t\t\tif (fBoundMaxX > Abs(DotProduct2D(point, pEntity->m_matrix.GetRight()))) {\n\t\t\t\t\t\tfloat fDotProduct = DotProduct2D(point, pEntity->m_matrix.GetForward());\n\t\t\t\t\t\tif (fBoundMaxY > fDotProduct && fBoundMinY < fDotProduct)\n\t\t\t\t\t\t\tpathNodes[x][y].bBlockade = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n// Make sure all externals link TO an internal\nvoid\nCPathInfoForObject::SwapConnectionsToBeRightWayRound(void)\n{\n\tint e, i;\n\tCPathInfoForObject *tile = this;\n\n\tfor(e = 0; e < 12; e++)\n\tif(tile[e].type == NodeTypeExtern && tile[e].next < 0)\n\t\tfor(i = 0; i < 12; i++)\n\t\tif(tile[i].type == NodeTypeIntern && tile[i].next == e){\n\t\t\ttile[e].next = i;\n\t\t\ttile[i].next = -1;\n\t\t\tbool tmp = !!tile[e].crossing;\n\t\t\ttile[e].crossing = tile[i].crossing;\n\t\t\ttile[i].crossing = tmp;\n\t\t}\n}\n\nvoid\nCPathFind::Init(void)\n{\n\tint i;\n\n\tm_numPathNodes = 0;\n\tm_numMapObjects = 0;\n\tm_numConnections = 0;\n\tm_numCarPathLinks = 0;\n\tunk = 0;\n\tNumTempExternalNodes = 0;\n\n\tfor(i = 0; i < NUM_PATHNODES; i++)\n\t\tm_pathNodes[i].distance = MAX_DIST;\n}\n\nvoid\nCPathFind::AllocatePathFindInfoMem(int16 numPathGroups)\n{\n\tdelete[] InfoForTileCars;\n\tInfoForTileCars = nil;\n\tdelete[] InfoForTilePeds;\n\tInfoForTilePeds = nil;\n\n\t// NB: MIAMI doesn't use numPathGroups here but hardcodes PATHNODESIZE\n\tInfoForTileCars = new CPathInfoForObject[12*PATHNODESIZE];\n\tmemset(InfoForTileCars, 0, 12*PATHNODESIZE*sizeof(CPathInfoForObject));\n\tInfoForTilePeds = new CPathInfoForObject[12*PATHNODESIZE];\n\tmemset(InfoForTilePeds, 0, 12*PATHNODESIZE*sizeof(CPathInfoForObject));\n\n\tdelete[] DetachedInfoForTileCars;\n\tDetachedInfoForTileCars = nil;\n\tdelete[] DetachedInfoForTilePeds;\n\tDetachedInfoForTilePeds = nil;\n\tDetachedInfoForTileCars = new CPathInfoForObject[12*NUMDETACHED_CARS];\n\tmemset(DetachedInfoForTileCars, 0, 12*NUMDETACHED_CARS*sizeof(CPathInfoForObject));\n\tDetachedInfoForTilePeds = new CPathInfoForObject[12*NUMDETACHED_PEDS];\n\tmemset(DetachedInfoForTilePeds, 0, 12*NUMDETACHED_PEDS*sizeof(CPathInfoForObject));\n\n\tdelete[] TempExternalNodes;\n\tTempExternalNodes = nil;\n\tTempExternalNodes = new CTempNodeExternal[NUMTEMPEXTERNALNODES];\n\tmemset(TempExternalNodes, 0, NUMTEMPEXTERNALNODES*sizeof(CTempNodeExternal));\n\tNumTempExternalNodes = 0;\n\tNumDetachedPedNodeGroups = 0;\n\tNumDetachedCarNodeGroups = 0;\n}\n\nvoid\nCPathFind::RegisterMapObject(CTreadable *mapObject)\n{\n\tm_mapObjects[m_numMapObjects++] = mapObject;\n}\n\nvoid\nCPathFind::StoreNodeInfoPed(int16 id, int16 node, int8 type, int8 next, int16 x, int16 y, int16 z, float width, bool crossing, uint8 spawnRate)\n{\n\tint i;\n\n\ti = id*12 + node;\n\tInfoForTilePeds[i].type = type;\n\tInfoForTilePeds[i].next = next;\n\tInfoForTilePeds[i].x = x/16.0f;\n\tInfoForTilePeds[i].y = y/16.0f;\n\tInfoForTilePeds[i].z = z/16.0f;\n\tInfoForTilePeds[i].width = 8.0f*Min(width, 15.0f);\n\tInfoForTilePeds[i].numLeftLanes = 0;\n\tInfoForTilePeds[i].numRightLanes = 0;\n\tInfoForTilePeds[i].crossing = crossing;\n\tInfoForTilePeds[i].speedLimit = 0;\n\tInfoForTilePeds[i].roadBlock = false;\n\tInfoForTilePeds[i].disabled = false;\n\tInfoForTilePeds[i].waterPath = false;\n\tInfoForTilePeds[i].onlySmallBoats = false;\n\tInfoForTilePeds[i].betweenLevels = false;\n\tInfoForTilePeds[i].spawnRate = Min(spawnRate, 15);\n\n\tif(node == 11)\n\t\tInfoForTilePeds[id*12].SwapConnectionsToBeRightWayRound();\n}\n\nvoid\nCPathFind::StoreNodeInfoCar(int16 id, int16 node, int8 type, int8 next, int16 x, int16 y, int16 z, float width, int8 numLeft, int8 numRight,\n\tbool disabled, bool betweenLevels, uint8 speedLimit, bool roadBlock, bool waterPath, uint8 spawnRate)\n{\n\tint i;\n\n\ti = id*12 + node;\n\tInfoForTileCars[i].type = type;\n\tInfoForTileCars[i].next = next;\n\tInfoForTileCars[i].x = x/16.0f;\n\tInfoForTileCars[i].y = y/16.0f;\n\tInfoForTileCars[i].z = z/16.0f;\n\tInfoForTileCars[i].width = 8.0f*Min(width, 15.0f);\n\tInfoForTileCars[i].numLeftLanes = numLeft;\n\tInfoForTileCars[i].numRightLanes = numRight;\n\tInfoForTileCars[i].crossing = false;\n\tInfoForTileCars[i].speedLimit = 0;\n\tInfoForTileCars[i].roadBlock = false;\n\tInfoForTileCars[i].disabled = false;\n\tInfoForTileCars[i].waterPath = false;\n\tInfoForTileCars[i].onlySmallBoats = false;\n\tInfoForTileCars[i].betweenLevels = false;\n\tInfoForTileCars[i].spawnRate = Min(spawnRate, 15);\n\n\tif(node == 11)\n\t\tInfoForTileCars[id*12].SwapConnectionsToBeRightWayRound();\n}\n\nvoid\nCPathFind::StoreDetachedNodeInfoPed(int32 node, int8 type, int32 next, float x, float y, float z, float width, bool crossing,\n\tbool disabled, bool betweenLevels, uint8 spawnRate)\n{\n\tint i;\n\n\tif(NumDetachedPedNodeGroups >= NUMDETACHED_PEDS)\n\t\treturn;\n\n\ti = NumDetachedPedNodeGroups*12 + node;\n\tDetachedInfoForTilePeds[i].type = type;\n\tDetachedInfoForTilePeds[i].next = next;\n\tDetachedInfoForTilePeds[i].x = x/16.0f;\n\tDetachedInfoForTilePeds[i].y = y/16.0f;\n\tDetachedInfoForTilePeds[i].z = z/16.0f;\n\tDetachedInfoForTilePeds[i].width = 8.0f*Min(width, 31.0f);\n\tDetachedInfoForTilePeds[i].numLeftLanes = 0;\n\tDetachedInfoForTilePeds[i].numRightLanes = 0;\n\tDetachedInfoForTilePeds[i].crossing = crossing;\n\tDetachedInfoForTilePeds[i].speedLimit = 0;\n\tDetachedInfoForTilePeds[i].roadBlock = false;\n\tDetachedInfoForTilePeds[i].disabled = disabled;\n\tDetachedInfoForTilePeds[i].waterPath = false;\n\tDetachedInfoForTilePeds[i].onlySmallBoats = false;\n\tDetachedInfoForTilePeds[i].betweenLevels = betweenLevels;\n\tDetachedInfoForTilePeds[i].spawnRate = Min(spawnRate, 15);\n\n\tif(node == 11){\n\t\tDetachedInfoForTilePeds[NumDetachedPedNodeGroups*12].SwapConnectionsToBeRightWayRound();\n\t\tNumDetachedPedNodeGroups++;\n\t}\n}\n\nvoid\nCPathFind::StoreDetachedNodeInfoCar(int32 node, int8 type, int32 next, float x, float y, float z, float width, int8 numLeft, int8 numRight,\n\tbool disabled, bool betweenLevels, uint8 speedLimit, bool roadBlock, bool waterPath, uint8 spawnRate, bool onlySmallBoats)\n{\n\tint i;\n\n\tif(NumDetachedCarNodeGroups >= NUMDETACHED_CARS)\n\t\treturn;\n\n\ti = NumDetachedCarNodeGroups*12 + node;\n\tDetachedInfoForTileCars[i].type = type;\n\tDetachedInfoForTileCars[i].next = next;\n\tDetachedInfoForTileCars[i].x = x/16.0f;\n\tDetachedInfoForTileCars[i].y = y/16.0f;\n\tDetachedInfoForTileCars[i].z = z/16.0f;\n\tDetachedInfoForTileCars[i].width = 8.0f*Min(width, 15.0f);\n\tDetachedInfoForTileCars[i].numLeftLanes = numLeft;\n\tDetachedInfoForTileCars[i].numRightLanes = numRight;\n\tDetachedInfoForTileCars[i].crossing = false;\n\tDetachedInfoForTileCars[i].speedLimit = speedLimit;\n\tDetachedInfoForTileCars[i].roadBlock = roadBlock;\n\tDetachedInfoForTileCars[i].disabled = disabled;\n\tDetachedInfoForTileCars[i].waterPath = waterPath;\n\tDetachedInfoForTileCars[i].onlySmallBoats = onlySmallBoats;\n\tDetachedInfoForTileCars[i].betweenLevels = betweenLevels;\n\tDetachedInfoForTileCars[i].spawnRate = Min(spawnRate, 15);\n\n\tif(node == 11){\n\t\tDetachedInfoForTileCars[NumDetachedCarNodeGroups*12].SwapConnectionsToBeRightWayRound();\n\t\tNumDetachedCarNodeGroups++;\n\t}\n}\n\nvoid\nCPathFind::CalcNodeCoors(float x, float y, float z, int id, CVector *out)\n{\n\tCVector pos;\n\tpos.x = x;\n\tpos.y = y;\n\tpos.z = z;\n\t*out = m_mapObjects[id]->GetMatrix() * pos;\n}\n\nbool\nCPathFind::LoadPathFindData(void)\n{\n\tCFileMgr::SetDir(\"\");\n\treturn false;\n}\n\nvoid\nCPathFind::PreparePathData(void)\n{\n\tint i, j;\n\tint numExtern, numIntern;\n\tCTempNode *tempNodes;\n\n\tprintf(\"PreparePathData\\n\");\n\tif(!CPathFind::LoadPathFindData() &&\t// empty\n\t   InfoForTileCars && InfoForTilePeds &&\n\t   DetachedInfoForTileCars && DetachedInfoForTilePeds && TempExternalNodes){\n\t\ttempNodes = new CTempNode[NUMTEMPNODES];\n\n\t\tm_numConnections = 0;\n\n\t\tfor(i = 0; i < PATHNODESIZE; i++){\n\t\t\tnumExtern = 0;\n\t\t\tnumIntern = 0;\n\t\t\tfor(j = 0; j < 12; j++){\n\t\t\t\tif(InfoForTileCars[i*12 + j].type == NodeTypeExtern)\n\t\t\t\t\tnumExtern++;\n\t\t\t\tif(InfoForTileCars[i*12 + j].type == NodeTypeIntern)\n\t\t\t\t\tnumIntern++;\n\t\t\t}\n\t\t\tif(numIntern > 1 && numExtern != 2)\n\t\t\t\tprintf(\"ILLEGAL BLOCK. MORE THAN 1 INTERNALS AND NOT 2 EXTERNALS (Modelindex:%d)\\n\", i);\n\t\t}\n\n\t\tint numExternDetached, numInternDetached;\n\t\tfor(i = 0; i < NUMDETACHED_CARS; i++){\n\t\t\tnumExternDetached = 0;\n\t\t\tnumInternDetached = 0;\n\t\t\tfor(j = 0; j < 12; j++){\n\t\t\t\tif(DetachedInfoForTileCars[i*12 + j].type == NodeTypeExtern)\n\t\t\t\t\tnumExternDetached++;\n\t\t\t\tif(DetachedInfoForTilePeds[i*12 + j].type == NodeTypeIntern)\n\t\t\t\t\tnumInternDetached++;\n\t\t\t}\n\t\t\t// no diagnostic here\n\t\t}\n\n\t\tfor(i = 0; i < PATHNODESIZE; i++)\n\t\t\tfor(j = 0; j < 12; j++)\n\t\t\t\tif(InfoForTileCars[i*12 + j].type == NodeTypeExtern){\n\t\t\t\t\t// MIAMI has MI:%d here but no argument for it\n\t\t\t\t\tif(InfoForTileCars[i*12 + j].numLeftLanes < 0)\n\t\t\t\t\t\tprintf(\"ILLEGAL BLOCK. NEGATIVE NUMBER OF LANES (Obj:%d)\\n\", i);\n\t\t\t\t\tif(InfoForTileCars[i*12 + j].numRightLanes < 0)\n\t\t\t\t\t\tprintf(\"ILLEGAL BLOCK. NEGATIVE NUMBER OF LANES (Obj:%d)\\n\", i);\n\t\t\t\t\tif(InfoForTileCars[i*12 + j].numLeftLanes + InfoForTileCars[i*12 + j].numRightLanes <= 0)\n\t\t\t\t\t\tprintf(\"ILLEGAL BLOCK. NO LANES IN NODE (Obj:%d)\\n\", i);\n\t\t\t\t}\n\t\tfor(i = 0; i < NUMDETACHED_CARS; i++)\n\t\t\tfor(j = 0; j < 12; j++)\n\t\t\t\tif(DetachedInfoForTileCars[i*12 + j].type == NodeTypeExtern){\n\t\t\t\t\t// MI:%d here but no argument for it\n\t\t\t\t\tif(DetachedInfoForTileCars[i*12 + j].numLeftLanes < 0)\n\t\t\t\t\t\tprintf(\"ILLEGAL BLOCK. NEGATIVE NUMBER OF LANES (Obj:%d)\\n\", i);\n\t\t\t\t\tif(DetachedInfoForTileCars[i*12 + j].numRightLanes < 0)\n\t\t\t\t\t\tprintf(\"ILLEGAL BLOCK. NEGATIVE NUMBER OF LANES (Obj:%d)\\n\", i);\n\t\t\t\t\tif(DetachedInfoForTileCars[i*12 + j].numLeftLanes + DetachedInfoForTileCars[i*12 + j].numRightLanes <= 0)\n\t\t\t\t\t\tprintf(\"ILLEGAL BLOCK. NO LANES IN NODE (Obj:%d)\\n\", i);\n\t\t\t\t}\n\n\t\tm_numPathNodes = 0;\n\t\tPreparePathDataForType(PATH_CAR, tempNodes, InfoForTileCars, 1.0f, DetachedInfoForTileCars, NumDetachedCarNodeGroups);\n\t\tm_numCarPathNodes = m_numPathNodes;\n\t\tPreparePathDataForType(PATH_PED, tempNodes, InfoForTilePeds, 1.0f, DetachedInfoForTilePeds, NumDetachedPedNodeGroups);\n\t\tm_numPedPathNodes = m_numPathNodes - m_numCarPathNodes;\n\n\t\tdelete[] tempNodes;\n\n\t\tCountFloodFillGroups(PATH_CAR);\n\t\tCountFloodFillGroups(PATH_PED);\n\n\t\tdelete[] InfoForTileCars;\n\t\tInfoForTileCars = nil;\n\t\tdelete[] InfoForTilePeds;\n\t\tInfoForTilePeds = nil;\n\n\t\tdelete[] DetachedInfoForTileCars;\n\t\tDetachedInfoForTileCars = nil;\n\t\tdelete[] DetachedInfoForTilePeds;\n\t\tDetachedInfoForTilePeds = nil;\n\t\tdelete[] TempExternalNodes;\n\t\tTempExternalNodes = nil;\n\t}\n\tprintf(\"Done with PreparePathData\\n\");\n}\n\n/* String together connected nodes in a list by a flood fill algorithm */\nvoid\nCPathFind::CountFloodFillGroups(uint8 type)\n{\n\tint start, end;\n\tint i, l;\n\tuint16 n;\n\tCPathNode *node, *prev;\n\n\tswitch(type){\n\tcase PATH_CAR:\n\t\tstart = 0;\n\t\tend = m_numCarPathNodes;\n\t\tbreak;\n\tcase PATH_PED:\n\t\tstart = m_numCarPathNodes;\n\t\tend = start + m_numPedPathNodes;\n\t\tbreak;\n\t}\n\n\tfor(i = start; i < end; i++)\n\t\tm_pathNodes[i].group = 0;\n\n\tn = 0;\n\tfor(;;){\n\t\tn++;\n\t\tif(n > 1500){\n\t\t\tfor(i = start; m_pathNodes[i].group && i < end; i++);\n\t\t\tprintf(\"NumNodes:%d Accounted for:%d\\n\", end - start, i - start);\n\t\t}\n\n\t\t// Look for unvisited node\n\t\tfor(i = start; m_pathNodes[i].group && i < end; i++);\n\t\tif(i == end)\n\t\t\tbreak;\n\n\t\tnode = &m_pathNodes[i];\n\t\tnode->SetNext(nil);\n\t\tnode->group = n;\n\n\t\tif(node->numLinks == 0){\n\t\t\tif(type == PATH_CAR)\n\t\t\t\tprintf(\"Single car node: %f %f %f\\n\",\n\t\t\t\t\tnode->GetX(), node->GetY(), node->GetZ());\n\t\t\telse\n\t\t\t\tprintf(\"Single ped node: %f %f %f\\n\",\n\t\t\t\t\tnode->GetX(), node->GetY(), node->GetZ());\n\t\t}\n\n\t\twhile(node){\n\t\t\tprev = node;\n\t\t\tnode = node->GetNext();\n\t\t\tfor(i = 0; i < prev->numLinks; i++){\n\t\t\t\tl = ConnectedNode(prev->firstLink + i);\n\t\t\t\tif(m_pathNodes[l].group == 0){\n\t\t\t\t\tm_pathNodes[l].group = n;\n\t\t\t\t\tif(m_pathNodes[l].group == 0)\n\t\t\t\t\t\tm_pathNodes[l].group = INT8_MIN;\n\t\t\t\t\tm_pathNodes[l].SetNext(node);\n\t\t\t\t\tnode = &m_pathNodes[l];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tm_numGroups[type] = n-1;\n\tprintf(\"GraphType:%d. FloodFill groups:%d\\n\", type, n);\n}\n\nint32 TempListLength;\n\nvoid\nCPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoForObject *objectpathinfo,\n\tfloat maxdist, CPathInfoForObject *detachednodes, int numDetached)\n{\n\tstatic CVector CoorsXFormed;\n\tint i, j, k;\n\tint l1, l2;\n\tint start;\n\tfloat posx, posy;\n\tfloat dx, dy, mag;\n\tfloat nearestDist;\n\tint nearestId;\n\tint oldNumPathNodes, oldNumLinks;\n\tfloat dist;\n\tint iseg, jseg;\n\tint done, cont;\n\tint tileStart;\n\n\toldNumPathNodes = m_numPathNodes;\n\toldNumLinks = m_numConnections;\n\n#define OBJECTINDEX(n) (mapObjIndices[(n)])\n\tint16 *mapObjIndices = new int16[NUM_PATHNODES];\n\tNumTempExternalNodes = 0;\n\n\t// Calculate internal nodes, store them and connect them to defining object\n\tfor(i = 0; i < m_numMapObjects; i++){\n\t\ttileStart = m_numPathNodes;\n\t\tstart = 12 * m_mapObjects[i]->GetModelIndex();\n\t\tfor(j = 0; j < 12; j++){\n\t\t\tif(objectpathinfo[start + j].type == NodeTypeIntern){\n\t\t\t\tCalcNodeCoors(\n\t\t\t\t\tobjectpathinfo[start + j].x,\n\t\t\t\t\tobjectpathinfo[start + j].y,\n\t\t\t\t\tobjectpathinfo[start + j].z,\n\t\t\t\t\ti,\n\t\t\t\t\t&CoorsXFormed);\n\t\t\t\tm_pathNodes[m_numPathNodes].SetPosition(CoorsXFormed);\n\t\t\t\tOBJECTINDEX(m_numPathNodes) = i;\n\t\t\t\tm_pathNodes[m_numPathNodes].width = objectpathinfo[start + j].width;\n\t\t\t\tm_pathNodes[m_numPathNodes].speedLimit = objectpathinfo[start + j].speedLimit;\n\t\t\t\tm_pathNodes[m_numPathNodes].spawnRate = objectpathinfo[start + j].spawnRate;\n\t\t\t\tm_pathNodes[m_numPathNodes].bUseInRoadBlock = objectpathinfo[start + j].roadBlock;\n\t\t\t\tm_pathNodes[m_numPathNodes].bDisabled = objectpathinfo[start + j].disabled;\n\t\t\t\tm_pathNodes[m_numPathNodes].bWaterPath = objectpathinfo[start + j].waterPath;\n\t\t\t\tm_pathNodes[m_numPathNodes].bOnlySmallBoats = objectpathinfo[start + j].onlySmallBoats;\n\t\t\t\tm_pathNodes[m_numPathNodes].bBetweenLevels = objectpathinfo[start + j].betweenLevels;\n\t\t\t\tm_numPathNodes++;\n\t\t\t}\n\t\t\telse if(objectpathinfo[start + j].type == NodeTypeExtern){\n\t\t\t\tCalcNodeCoors(\n\t\t\t\t\tobjectpathinfo[start + j].x,\n\t\t\t\t\tobjectpathinfo[start + j].y,\n\t\t\t\t\tobjectpathinfo[start + j].z,\n\t\t\t\t\ti,\n\t\t\t\t\t&CoorsXFormed);\n\t\t\t\tTempExternalNodes[NumTempExternalNodes].pos = CoorsXFormed;\n\t\t\t\tassert(objectpathinfo[start + j].next >= 0);\n\t\t\t\tTempExternalNodes[NumTempExternalNodes].next = tileStart + objectpathinfo[start + j].next;\n\t\t\t\tTempExternalNodes[NumTempExternalNodes].numLeftLanes = objectpathinfo[start + j].numLeftLanes;\n\t\t\t\tTempExternalNodes[NumTempExternalNodes].numRightLanes = objectpathinfo[start + j].numRightLanes;\n\t\t\t\tTempExternalNodes[NumTempExternalNodes].width = objectpathinfo[start + j].width;\n\t\t\t\tTempExternalNodes[NumTempExternalNodes].isCross = !!objectpathinfo[start + j].crossing;\n\t\t\t\tNumTempExternalNodes++;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Same thing for detached nodes\n\tfor(i = 0; i < numDetached; i++){\n\t\ttileStart = m_numPathNodes;\n\t\tstart = 12*i;\n\t\tfor(j = 0; j < 12; j++){\n\t\t\tif(detachednodes[start + j].type == NodeTypeIntern){\n\t\t\t\tCVector pos;\n\t\t\t\tpos.x = detachednodes[start + j].x;\n\t\t\t\tpos.y = detachednodes[start + j].y;\n\t\t\t\tpos.z = detachednodes[start + j].z;\n\t\t\t\tm_pathNodes[m_numPathNodes].SetPosition(pos);\n\t\t\t\tmapObjIndices[m_numPathNodes] = -(i+1);\n\t\t\t\tm_pathNodes[m_numPathNodes].width = detachednodes[start + j].width;\n\t\t\t\tm_pathNodes[m_numPathNodes].speedLimit = detachednodes[start + j].speedLimit;\n\t\t\t\tm_pathNodes[m_numPathNodes].spawnRate = detachednodes[start + j].spawnRate;\n\t\t\t\tm_pathNodes[m_numPathNodes].bUseInRoadBlock = detachednodes[start + j].roadBlock;\n\t\t\t\tm_pathNodes[m_numPathNodes].bDisabled = detachednodes[start + j].disabled;\n\t\t\t\tm_pathNodes[m_numPathNodes].bWaterPath = detachednodes[start + j].waterPath;\n\t\t\t\tm_pathNodes[m_numPathNodes].bOnlySmallBoats = detachednodes[start + j].onlySmallBoats;\n\t\t\t\tm_pathNodes[m_numPathNodes].bBetweenLevels = detachednodes[start + j].betweenLevels;\n\t\t\t\tm_numPathNodes++;\n\t\t\t}else if(detachednodes[start + j].type == NodeTypeExtern){\n\t\t\t\tTempExternalNodes[NumTempExternalNodes].pos.x = detachednodes[start + j].x;\n\t\t\t\tTempExternalNodes[NumTempExternalNodes].pos.y = detachednodes[start + j].y;\n\t\t\t\tTempExternalNodes[NumTempExternalNodes].pos.z = detachednodes[start + j].z;\n\t\t\t\tassert(detachednodes[start + j].next >= 0);\n\t\t\t\tTempExternalNodes[NumTempExternalNodes].next = tileStart + detachednodes[start + j].next;\n\t\t\t\tTempExternalNodes[NumTempExternalNodes].numLeftLanes = detachednodes[start + j].numLeftLanes;\n\t\t\t\tTempExternalNodes[NumTempExternalNodes].numRightLanes = detachednodes[start + j].numRightLanes;\n\t\t\t\tTempExternalNodes[NumTempExternalNodes].width = detachednodes[start + j].width;\n\t\t\t\tTempExternalNodes[NumTempExternalNodes].isCross = !!detachednodes[start + j].crossing;\n\t\t\t\tNumTempExternalNodes++;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Insert external nodes into TempList\n\tTempListLength = 0;\n\tfor(i = 0; i < NumTempExternalNodes; i++){\n\t\t// find closest unconnected node\n\t\tnearestId = -1;\n\t\tnearestDist = maxdist;\n\t\tfor(k = 0; k < TempListLength; k++){\n\t\t\tif(tempnodes[k].linkState != 1)\n\t\t\t\tcontinue;\n\t\t\tdx = tempnodes[k].pos.x - TempExternalNodes[i].pos.x;\n\t\t\tif(Abs(dx) < nearestDist){\n\t\t\t\tdy = tempnodes[k].pos.y - TempExternalNodes[i].pos.y;\n\t\t\t\tif(Abs(dy) < nearestDist){\n\t\t\t\t\tnearestDist = Max(Abs(dx), Abs(dy));\n\t\t\t\t\tnearestId = k;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif(nearestId < 0){\n\t\t\t// None found, add this one to temp list\n\t\t\ttempnodes[TempListLength].pos = TempExternalNodes[i].pos;\n\t\t\t// link to connecting internal node\n\t\t\ttempnodes[TempListLength].link1 = TempExternalNodes[i].next;\n\t\t\tif(type == PATH_CAR){\n\t\t\t\ttempnodes[TempListLength].numLeftLanes = TempExternalNodes[i].numLeftLanes;\n\t\t\t\ttempnodes[TempListLength].numRightLanes = TempExternalNodes[i].numRightLanes;\n\t\t\t}\n\t\t\ttempnodes[TempListLength].width = TempExternalNodes[i].width;\n\t\t\ttempnodes[TempListLength].isCross = TempExternalNodes[i].isCross;\n\t\t\ttempnodes[TempListLength++].linkState = 1;\n\t\t}else{\n\t\t\t// Found nearest, connect it to our neighbour\n\t\t\ttempnodes[nearestId].link2 = TempExternalNodes[i].next;\n\t\t\ttempnodes[nearestId].linkState = 2;\n\n\t\t\t// collapse this node with nearest we found\n\t\t\tdx = m_pathNodes[tempnodes[nearestId].link1].GetX() - m_pathNodes[tempnodes[nearestId].link2].GetX();\n\t\t\tdy = m_pathNodes[tempnodes[nearestId].link1].GetY() - m_pathNodes[tempnodes[nearestId].link2].GetY();\n\t\t\ttempnodes[nearestId].pos = (tempnodes[nearestId].pos + TempExternalNodes[i].pos)*0.5f;\n\t\t\tmag = Sqrt(dx*dx + dy*dy);\n\t\t\ttempnodes[nearestId].dirX = dx/mag * 100;\n\t\t\ttempnodes[nearestId].dirY = dy/mag * 100;\n\t\t\ttempnodes[nearestId].width = Max(tempnodes[nearestId].width, TempExternalNodes[i].width);\n\t\t\tif(TempExternalNodes[i].isCross)\n\t\t\t\ttempnodes[nearestId].isCross = true;\t// TODO: is this guaranteed to be false otherwise?\n\t\t\t// do something when number of lanes doesn't agree\n\t\t\tif(type == PATH_CAR)\n\t\t\t\tif(tempnodes[nearestId].numLeftLanes != 0 && tempnodes[nearestId].numRightLanes != 0 &&\n\t\t\t\t   (TempExternalNodes[i].numLeftLanes == 0 || TempExternalNodes[i].numRightLanes == 0)){\n\t\t\t\t\t// why switch left and right here?\n\t\t\t\t\ttempnodes[nearestId].numLeftLanes = TempExternalNodes[i].numRightLanes;\n\t\t\t\t\ttempnodes[nearestId].numRightLanes = TempExternalNodes[i].numLeftLanes;\n\t\t\t\t}\n\t\t}\n\t}\n\n\t// Loop through previously added internal nodes and link them\n\tfor(i = oldNumPathNodes; i < m_numPathNodes; i++){\n\t\t// Init link\n\t\tm_pathNodes[i].numLinks = 0;\n\t\tm_pathNodes[i].firstLink = m_numConnections;\n\n\t\t// See if node connects to external nodes\n\t\tfor(j = 0; j < TempListLength; j++){\n\t\t\tif(tempnodes[j].linkState != 2)\n\t\t\t\tcontinue;\n\n\t\t\t// Add link to other side of the external\n\t\t\t// NB this clears the flags in MIAMI\n\t\t\tif(tempnodes[j].link1 == i)\n\t\t\t\tm_connections[m_numConnections] = tempnodes[j].link2;\n\t\t\telse if(tempnodes[j].link2 == i)\n\t\t\t\tm_connections[m_numConnections] = tempnodes[j].link1;\n\t\t\telse\n\t\t\t\tcontinue;\n\n\t\t\tdist = (m_pathNodes[i].GetPosition() - m_pathNodes[ConnectedNode(m_numConnections)].GetPosition()).Magnitude();\n\t\t\tm_distances[m_numConnections] = Min(dist, 255);\n\t\t\tif(tempnodes[j].isCross)\n\t\t\t\tm_connections[j] |= 0x8000;\t// crosses road flag\n\n\t\t\tif(type == PATH_CAR){\n\t\t\t\t// IMPROVE: use a goto here\n\t\t\t\t// Find existing car path link\n\t\t\t\tfor(k = 0; k < m_numCarPathLinks; k++){\n\t\t\t\t\tif(m_carPathLinks[k].dirX == tempnodes[j].dirX &&\n\t\t\t\t\t   m_carPathLinks[k].dirY == tempnodes[j].dirY &&\n\t\t\t\t\t   m_carPathLinks[k].x == (int)(tempnodes[j].pos.x*8.0f) &&\n\t\t\t\t\t   m_carPathLinks[k].y == (int)(tempnodes[j].pos.y*8.0f)){\n\t\t\t\t\t\tm_carPathConnections[m_numConnections] = k;\n\t\t\t\t\t\tk = m_numCarPathLinks;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// k is m_numCarPathLinks+1 if we found one\n\t\t\t\tif(k == m_numCarPathLinks){\n\t\t\t\t\tm_carPathLinks[m_numCarPathLinks].dirX = tempnodes[j].dirX;\n\t\t\t\t\tm_carPathLinks[m_numCarPathLinks].dirY = tempnodes[j].dirY;\n\t\t\t\t\tm_carPathLinks[m_numCarPathLinks].x = tempnodes[j].pos.x*8.0f;\n\t\t\t\t\tm_carPathLinks[m_numCarPathLinks].y = tempnodes[j].pos.y*8.0f;\n\t\t\t\t\tm_carPathLinks[m_numCarPathLinks].trafficLightDirection = false;\n\t\t\t\t\tm_carPathLinks[m_numCarPathLinks].width = tempnodes[j].width;\n\t\t\t\t\tm_carPathLinks[m_numCarPathLinks].pathNodeIndex = i;\n\t\t\t\t\tm_carPathLinks[m_numCarPathLinks].numLeftLanes = tempnodes[j].numLeftLanes;\n\t\t\t\t\tm_carPathLinks[m_numCarPathLinks].numRightLanes = tempnodes[j].numRightLanes;\n\t\t\t\t\tm_carPathLinks[m_numCarPathLinks].trafficLightType = 0;\n\t\t\t\t\tassert(m_numCarPathLinks <= NUM_CARPATHLINKS);\n\t\t\t\t\tm_carPathConnections[m_numConnections] = m_numCarPathLinks++;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tm_pathNodes[i].numLinks++;\n\t\t\tm_numConnections++;\n\t\t}\n\n\t\tCPathInfoForObject *tile;\n\t\tif(mapObjIndices[i] < 0){\n\t\t\tif(type == PATH_CAR)\n\t\t\t\ttile = &DetachedInfoForTileCars[12 * (-1 - mapObjIndices[i])];\n\t\t\telse\n\t\t\t\ttile = &DetachedInfoForTilePeds[12 * (-1 - mapObjIndices[i])];\n\t\t}else{\n\t\t\tif(type == PATH_CAR)\n\t\t\t\ttile = &InfoForTileCars[12 * m_mapObjects[mapObjIndices[i]]->GetModelIndex()];\n\t\t\telse\n\t\t\t\ttile = &InfoForTilePeds[12 * m_mapObjects[mapObjIndices[i]]->GetModelIndex()];\n\t\t}\n\n\t\t// Find i inside path segment\n\t\tiseg = 0;\n\t\tfor(j = Max(oldNumPathNodes, i-12); j < i; j++)\n\t\t\tif(OBJECTINDEX(j) == OBJECTINDEX(i))\n\t\t\t\tiseg++;\n\n\t\t// Add links to other internal nodes\n\t\tfor(j = Max(oldNumPathNodes, i-12); j < Min(m_numPathNodes, i+12); j++){\n\t\t\tif(OBJECTINDEX(i) != OBJECTINDEX(j) || i == j)\n\t\t\t\tcontinue;\n\t\t\t// N.B.: in every path segment, the externals have to be at the end\n\t\t\tjseg = j-i + iseg;\n\n\t\t\tif(tile[iseg].next == jseg ||\n\t\t\t   tile[jseg].next == iseg){\n\t\t\t\t// Found a link between i and jConnectionSetCrossesRoad\n\t\t\t\t// NB this clears the flags in MIAMI\n\t\t\t\tm_connections[m_numConnections] = j;\n\t\t\t\tdist = (m_pathNodes[i].GetPosition() - m_pathNodes[j].GetPosition()).Magnitude();\n\t\t\t\tm_distances[m_numConnections] = Min(dist, 255);\n\n\t\t\t\tif(type == PATH_CAR){\n\t\t\t\t\tposx = (m_pathNodes[i].GetX() + m_pathNodes[j].GetX())*0.5f;\n\t\t\t\t\tposy = (m_pathNodes[i].GetY() + m_pathNodes[j].GetY())*0.5f;\n\t\t\t\t\tdx = m_pathNodes[j].GetX() - m_pathNodes[i].GetX();\n\t\t\t\t\tdy = m_pathNodes[j].GetY() - m_pathNodes[i].GetY();\n\t\t\t\t\tmag = Sqrt(dx*dx + dy*dy);\n\t\t\t\t\tdx /= mag;\n\t\t\t\t\tdy /= mag;\n\t\t\t\t\tuint8 width = Max(m_pathNodes[i].width, m_pathNodes[j].width);\n\t\t\t\t\tif(i < j){\n\t\t\t\t\t\tdx = -dx;\n\t\t\t\t\t\tdy = -dy;\n\t\t\t\t\t}\n\t\t\t\t\t// IMPROVE: use a goto here\n\t\t\t\t\t// Find existing car path link\n\t\t\t\t\tfor(k = 0; k < m_numCarPathLinks; k++){\n\t\t\t\t\t\tif(m_carPathLinks[k].dirX == (int)(dx*100.0f) &&\n\t\t\t\t\t\t   m_carPathLinks[k].dirY == (int)(dy*100.0f) &&\n\t\t\t\t\t\t   m_carPathLinks[k].x == (int)(posx*8.0f) &&\n\t\t\t\t\t\t   m_carPathLinks[k].y == (int)(posy*8.0f)){\n\t\t\t\t\t\t\tm_carPathConnections[m_numConnections] = k;\n\t\t\t\t\t\t\tk = m_numCarPathLinks;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t// k is m_numCarPathLinks+1 if we found one\n\t\t\t\t\tif(k == m_numCarPathLinks){\n\t\t\t\t\t\tm_carPathLinks[m_numCarPathLinks].dirX = dx*100.0f;\n\t\t\t\t\t\tm_carPathLinks[m_numCarPathLinks].dirY = dy*100.0f;\n\t\t\t\t\t\tm_carPathLinks[m_numCarPathLinks].x = posx*8.0f;\n\t\t\t\t\t\tm_carPathLinks[m_numCarPathLinks].y = posy*8.0f;\n\t\t\t\t\t\tm_carPathLinks[m_numCarPathLinks].trafficLightDirection = false;\n\t\t\t\t\t\tm_carPathLinks[m_numCarPathLinks].width = width;\n\t\t\t\t\t\tm_carPathLinks[m_numCarPathLinks].pathNodeIndex = i;\n\t\t\t\t\t\tm_carPathLinks[m_numCarPathLinks].numLeftLanes = -1;\n\t\t\t\t\t\tm_carPathLinks[m_numCarPathLinks].numRightLanes = -1;\n\t\t\t\t\t\tm_carPathLinks[m_numCarPathLinks].trafficLightType = 0;\n\t\t\t\t\t\tassert(m_numCarPathLinks <= NUM_CARPATHLINKS);\n\t\t\t\t\t\tm_carPathConnections[m_numConnections] = m_numCarPathLinks++;\n\t\t\t\t\t}\n\t\t\t\t}else{\n\t\t\t\t\t// Crosses road\n\t\t\t\t\tif(tile[iseg].next == jseg && tile[iseg].crossing ||\n\t\t\t\t\t   tile[jseg].next == iseg && tile[jseg].crossing)\n\t\t\t\t\t\tm_connections[m_numConnections] |= 0x8000;\t// crosses road flag\n\t\t\t\t}\n\n\t\t\t\tm_pathNodes[i].numLinks++;\n\t\t\t\tm_numConnections++;\n\t\t\t}\n\t\t}\n\t}\n\n\tif(type == PATH_CAR){\n\t\tdone = 0;\n\t\t// Set number of lanes for all nodes somehow\n\t\t// very strange code\n\t\tfor(k = 0; !done && k < 12; k++){\n\t\t\tdone = 1;\n\t\t\tfor(i = 0; i < m_numPathNodes; i++){\n\t\t\t\tif(m_pathNodes[i].numLinks != 2)\n\t\t\t\t\tcontinue;\n\t\t\t\tl1 = m_carPathConnections[m_pathNodes[i].firstLink];\n\t\t\t\tl2 = m_carPathConnections[m_pathNodes[i].firstLink+1];\n\n\t\t\t\tint8 l1Left = m_carPathLinks[l1].numLeftLanes;\n\t\t\t\tint8 l1Right = m_carPathLinks[l1].numRightLanes;\n\t\t\t\tint8 l2Left = m_carPathLinks[l2].numLeftLanes;\n\t\t\t\tint8 l2Right = m_carPathLinks[l2].numRightLanes;\n\t\t\t\tint8 *l1Leftp, *l1Rightp;\n\t\t\t\tint8 *l2Leftp, *l2Rightp;\n\t\t\t\tif(m_carPathLinks[l1].pathNodeIndex == i){\n\t\t\t\t\tl1Leftp = &l1Left;\n\t\t\t\t\tl1Rightp = &l1Right;\n\t\t\t\t}else{\n\t\t\t\t\tl1Leftp = &l1Right;\n\t\t\t\t\tl1Rightp = &l1Left;\n\t\t\t\t}\n\t\t\t\tif(m_carPathLinks[l2].pathNodeIndex == i){\n\t\t\t\t\tl2Leftp = &l2Left;\n\t\t\t\t\tl2Rightp = &l2Right;\n\t\t\t\t}else{\n\t\t\t\t\tl2Leftp = &l2Right;\n\t\t\t\t\tl2Rightp = &l2Left;\n\t\t\t\t}\n\t\t\t\tif(*l1Leftp == -1 && *l2Rightp != -1){\n\t\t\t\t\t*l1Leftp = *l2Rightp;\n\t\t\t\t\tdone = 0;\n\t\t\t\t}\n\t\t\t\tif(*l1Rightp == -1 && *l2Leftp != -1){\n\t\t\t\t\t*l1Rightp = *l2Leftp;\n\t\t\t\t\tdone = 0;\n\t\t\t\t}\n\t\t\t\tif(*l2Leftp == -1 && *l1Rightp != -1){\n\t\t\t\t\t*l2Leftp = *l1Rightp;\n\t\t\t\t\tdone = 0;\n\t\t\t\t}\n\t\t\t\tif(*l2Rightp == -1 && *l1Leftp != -1){\n\t\t\t\t\t*l2Rightp = *l1Leftp;\n\t\t\t\t\tdone = 0;\n\t\t\t\t}\n\t\t\t\tif(*l1Leftp == -1 && *l2Rightp == -1)\n\t\t\t\t\tdone = 0;\n\t\t\t\tif(*l2Leftp == -1 && *l1Rightp == -1)\n\t\t\t\t\tdone = 0;\n\t\t\t\tm_carPathLinks[l1].numLeftLanes = l1Left;\n\t\t\t\tm_carPathLinks[l1].numRightLanes = l1Right;\n\t\t\t\tm_carPathLinks[l2].numLeftLanes = l2Left;\n\t\t\t\tm_carPathLinks[l2].numRightLanes = l2Right;\n\t\t\t}\n\t\t}\n\n\t\t// Fall back to default values for number of lanes\n\t\tfor(i = 0; i < m_numPathNodes; i++)\n\t\t\tfor(j = 0; j < m_pathNodes[i].numLinks; j++){\n\t\t\t\tk = m_carPathConnections[m_pathNodes[i].firstLink + j];\n\t\t\t\tif(m_carPathLinks[k].numLeftLanes == -1)\n\t\t\t\t\tm_carPathLinks[k].numLeftLanes = 0;\n\t\t\t\tif(m_carPathLinks[k].numRightLanes == -1)\n\t\t\t\t\tm_carPathLinks[k].numRightLanes = 0;\n\t\t\t}\n\t}\n\n\t// Set flags for car nodes\n\tif(type == PATH_CAR){\n\t\tdo{\n\t\t\tcont = 0;\n\t\t\tfor(i = 0; i < m_numPathNodes; i++){\n\t\t\t\t// See if node is a dead end, if so, we're not done yet\n\t\t\t\tif(!m_pathNodes[i].bDeadEnd){\n\t\t\t\t\tk = 0;\n\t\t\t\t\tfor(j = 0; j < m_pathNodes[i].numLinks; j++)\n\t\t\t\t\t\tif(!m_pathNodes[ConnectedNode(m_pathNodes[i].firstLink + j)].bDeadEnd)\n\t\t\t\t\t\t\tk++;\n\t\t\t\t\tif(k < 2){\n\t\t\t\t\t\tm_pathNodes[i].bDeadEnd = true;\n\t\t\t\t\t\tcont = 1;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}while(cont);\n\t}\n\n\t// Remove isolated ped nodes\n\tif(type == PATH_PED)\n\t\tfor(i = oldNumPathNodes; i < m_numPathNodes; i++){\n\t\t\tif(m_pathNodes[i].numLinks != 0)\n\t\t\t\tcontinue;\n\n\t\t\t// Remove node\n\t\t\tfor(j = i; j < m_numPathNodes-1; j++)\n\t\t\t\tm_pathNodes[j] = m_pathNodes[j+1];\n\n\t\t\t// Fix links\n\t\t\tfor(j = oldNumLinks; j < m_numConnections; j++){\n\t\t\t\tint node = ConnectedNode(j);\n\t\t\t\tif(node >= i)\n\t\t\t\t\tm_connections[j] = node-1;\n\t\t\t}\n\n\t\t\ti--;\n\t\t\tm_numPathNodes--;\n\t\t}\n\n\tdelete[] mapObjIndices;\n}\n\nfloat\nCPathFind::CalcRoadDensity(float x, float y)\n{\n\tint i, j;\n\tfloat density = 0.0f;\n\n\tfor(i = 0; i < m_numCarPathNodes; i++){\n\t\tif(Abs(m_pathNodes[i].GetX() - x) < 80.0f &&\n\t\t   Abs(m_pathNodes[i].GetY() - y) < 80.0f &&\n\t\t   m_pathNodes[i].numLinks > 0){\n\t\t\tfor(j = 0; j < m_pathNodes[i].numLinks; j++){\n\t\t\t\tint next = ConnectedNode(m_pathNodes[i].firstLink + j);\n\t\t\t\tfloat dist = (m_pathNodes[i].GetPosition() - m_pathNodes[next].GetPosition()).Magnitude2D();\n\t\t\t\tnext = m_carPathConnections[m_pathNodes[i].firstLink + j];\n\t\t\t\tdensity += m_carPathLinks[next].numLeftLanes * dist;\n\t\t\t\tdensity += m_carPathLinks[next].numRightLanes * dist;\n\t\t\t}\n\t\t}\n\t}\n\treturn density/2500.0f;\n}\n\nbool\nCPathFind::TestForPedTrafficLight(CPathNode *n1, CPathNode *n2)\n{\n\tint i;\n\tfor(i = 0; i < n1->numLinks; i++)\n\t\tif(&m_pathNodes[ConnectedNode(n1->firstLink + i)] == n2)\n\t\t\treturn ConnectionHasTrafficLight(n1->firstLink + i);\n\treturn false;\n}\n\nbool\nCPathFind::TestCrossesRoad(CPathNode *n1, CPathNode *n2)\n{\n\tint i;\n\tfor(i = 0; i < n1->numLinks; i++)\n\t\tif(&m_pathNodes[ConnectedNode(n1->firstLink + i)] == n2)\n\t\t\treturn ConnectionCrossesRoad(n1->firstLink + i);\n\treturn false;\n}\n\nvoid\nCPathFind::AddNodeToList(CPathNode *node, int32 listId)\n{\n\tint i = listId & 0x1FF;\n\tnode->SetNext(m_searchNodes[i].GetNext());\n\tnode->SetPrev(&m_searchNodes[i]);\n\tif(m_searchNodes[i].GetNext())\n\t\tm_searchNodes[i].GetNext()->SetPrev(node);\n\tm_searchNodes[i].SetNext(node);\n\tnode->distance = listId;\n}\n\nvoid\nCPathFind::RemoveNodeFromList(CPathNode *node)\n{\n\tnode->GetPrev()->SetNext(node->GetNext());\n\tif(node->GetNext())\n\t\tnode->GetNext()->SetPrev(node->GetPrev());\n}\n\nvoid\nCPathFind::RemoveBadStartNode(CVector pos, CPathNode **nodes, int16 *n)\n{\n\tint i;\n\tif(*n < 2)\n\t\treturn;\n\tif(DotProduct2D(nodes[1]->GetPosition() - pos, nodes[0]->GetPosition() - pos) < 0.0f){\n\t\t(*n)--;\n\t\tfor(i = 0; i < *n; i++)\n\t\t\tnodes[i] = nodes[i+1];\n\t}\n}\n\n#ifdef GTA_BRIDGE\nvoid\nCPathFind::SetLinksBridgeLights(float x1, float x2, float y1, float y2, bool enable)\n{\n\tint i;\n\tfor(i = 0; i < m_numCarPathLinks; i++){\n\t\tCVector2D pos = m_carPathLinks[i].GetPosition();\n\t\tif(x1 < pos.x && pos.x < x2 &&\n\t\t   y1 < pos.y && pos.y < y2)\n\t\t\tm_carPathLinks[i].bBridgeLights = enable;\n\t}\n}\n#endif\n\nvoid\nCPathFind::SwitchOffNodeAndNeighbours(int32 nodeId, bool disable)\n{\n\tint i, next;\n\n\tm_pathNodes[nodeId].bDisabled = disable;\n\tif(m_pathNodes[nodeId].numLinks < 3)\n\t\tfor(i = 0; i < m_pathNodes[nodeId].numLinks; i++){\n\t\t\tnext = ConnectedNode(m_pathNodes[nodeId].firstLink + i);\n\t\t\tif(m_pathNodes[next].bDisabled != disable &&\n\t\t\t   m_pathNodes[next].numLinks < 3)\n\t\t\t\tSwitchOffNodeAndNeighbours(next, disable);\n\t\t}\n}\n\nvoid\nCPathFind::SwitchRoadsOffInArea(float x1, float x2, float y1, float y2, float z1, float z2, bool disable)\n{\n\tint i;\n\n\tfor(i = 0; i < m_numCarPathNodes; i++){\n\t\tCVector pos = m_pathNodes[i].GetPosition();\n\t\tif(x1 <= pos.x && pos.x <= x2 &&\n\t\t   y1 <= pos.y && pos.y <= y2 &&\n\t\t   z1 <= pos.z && pos.z <= z2 &&\n\t\t\tdisable != m_pathNodes[i].bDisabled)\n\t\t\tSwitchOffNodeAndNeighbours(i, disable);\n\t}\n}\n\nvoid\nCPathFind::SwitchPedRoadsOffInArea(float x1, float x2, float y1, float y2, float z1, float z2, bool disable)\n{\n\tint i;\n\n\tfor(i = m_numCarPathNodes; i < m_numPathNodes; i++){\n\t\tCVector pos = m_pathNodes[i].GetPosition();\n\t\tif(x1 <= pos.x && pos.x <= x2 &&\n\t\t   y1 <= pos.y && pos.y <= y2 &&\n\t\t   z1 <= pos.z && pos.z <= z2 &&\n\t\t\tdisable != m_pathNodes[i].bDisabled)\n\t\t\tSwitchOffNodeAndNeighbours(i, disable);\n\t}\n}\n\nvoid\nCPathFind::SwitchRoadsInAngledArea(float x1, float y1, float z1, float x2, float y2, float z2, float length, uint8 type, uint8 mode)\n{\n\tint i;\n\tint firstNode, lastNode;\n\n\t// this is NOT PATH_CAR\n\tif(type != 0){\n\t\tfirstNode = 0;\n\t\tlastNode = m_numCarPathNodes;\n\t}else{\n\t\tfirstNode = m_numCarPathNodes;\n\t\tlastNode = m_numPathNodes;\n\t}\n\n\tif(z1 > z2){\n\t\tfloat tmp = z2;\n\t\tz2 = z1;\n\t\tz1 = tmp;\n\t}\n\n\t// angle of vector from p2 to p1\n\tfloat angle = CGeneral::GetRadianAngleBetweenPoints(x1, y1, x2, y2) + HALFPI;\n\twhile(angle < 0.0f) angle += TWOPI;\n\twhile(angle > TWOPI) angle -= TWOPI;\n\t// vector from p1 to p2\n\tCVector2D v12(x2 - x1, y2 - y1);\n\tfloat len12 = v12.Magnitude();\n\tv12 /= len12;\n\n\t// vector from p2 to new point p3\n\tCVector2D v23(Sin(angle)*length, -(Cos(angle)*length));\n\tv23 /= v23.Magnitude();\t// obivously just 'length' but whatever\n\n\tbool disable = mode == SWITCH_OFF;\n\tfor(i = firstNode; i < lastNode; i++){\n\t\tCVector pos = m_pathNodes[i].GetPosition();\n\t\tif(pos.z < z1 || pos.z > z2)\n\t\t\tcontinue;\n\t\tCVector2D d(pos.x - x1, pos.y - y1);\n\t\tfloat dot = DotProduct2D(d, v12);\n\t\tif(dot < 0.0f || dot > len12)\n\t\t\tcontinue;\n\t\tdot = DotProduct2D(d, v23);\n\t\tif(dot < 0.0f || dot > length)\n\t\t\tcontinue;\n\t\tif(m_pathNodes[i].bDisabled != disable)\n\t\t\tSwitchOffNodeAndNeighbours(i, disable);\n\t}\n}\n\nvoid\nCPathFind::MarkRoadsBetweenLevelsNodeAndNeighbours(int32 nodeId)\n{\n\tint i, next;\n\n\tm_pathNodes[nodeId].bBetweenLevels = true;\n\tif(m_pathNodes[nodeId].numLinks < 3)\n\t\tfor(i = 0; i < m_pathNodes[nodeId].numLinks; i++){\n\t\t\tnext = ConnectedNode(m_pathNodes[nodeId].firstLink + i);\n\t\t\tif(!m_pathNodes[next].bBetweenLevels &&\n\t\t\t   m_pathNodes[next].numLinks < 3)\n\t\t\t\tMarkRoadsBetweenLevelsNodeAndNeighbours(next);\n\t\t}\n}\n\nvoid\nCPathFind::MarkRoadsBetweenLevelsInArea(float x1, float x2, float y1, float y2, float z1, float z2)\n{\n\tint i;\n\n\tfor(i = 0; i < m_numPathNodes; i++){\n\t\tCVector pos = m_pathNodes[i].GetPosition();\n\t\tif(x1 < pos.x && pos.x < x2 &&\n\t\t   y1 < pos.y && pos.y < y2 &&\n\t\t   z1 < pos.z && pos.z < z2)\n\t\t\tMarkRoadsBetweenLevelsNodeAndNeighbours(i);\n\t}\n}\n\nvoid\nCPathFind::PedMarkRoadsBetweenLevelsInArea(float x1, float x2, float y1, float y2, float z1, float z2)\n{\n\tint i;\n\n\tfor(i = m_numCarPathNodes; i < m_numPathNodes; i++){\n\t\tCVector pos = m_pathNodes[i].GetPosition();\n\t\tif(x1 < pos.x && pos.x < x2 &&\n\t\t   y1 < pos.y && pos.y < y2 &&\n\t\t   z1 < pos.z && pos.z < z2)\n\t\t\tMarkRoadsBetweenLevelsNodeAndNeighbours(i);\n\t}\n}\n\nint32\nCPathFind::FindNodeClosestToCoors(CVector coors, uint8 type, float distLimit, bool ignoreDisabled, bool ignoreBetweenLevels, bool ignoreSelected, bool bWaterPath)\n{\n\tint i;\n\tint firstNode, lastNode;\n\tfloat dist;\n\tfloat closestDist = 10000.0f;\n\tint closestNode = 0;\n\n\tswitch(type){\n\tcase PATH_CAR:\n\t\tfirstNode = 0;\n\t\tlastNode = m_numCarPathNodes;\n\t\tbreak;\n\tcase PATH_PED:\n\t\tfirstNode = m_numCarPathNodes;\n\t\tlastNode = m_numPathNodes;\n\t\tbreak;\n\t}\n\n\tfor(i = firstNode; i < lastNode; i++){\n\t\tif(ignoreDisabled && m_pathNodes[i].bDisabled) continue;\n\t\tif(ignoreBetweenLevels && m_pathNodes[i].bBetweenLevels) continue;\n\t\tif(ignoreSelected && m_pathNodes[i].bSelected) continue;\n\t\tif(bWaterPath != m_pathNodes[i].bWaterPath) continue;\n\t\tdist = Abs(m_pathNodes[i].GetX() - coors.x) +\n\t\t       Abs(m_pathNodes[i].GetY() - coors.y) +\n\t\t       3.0f*Abs(m_pathNodes[i].GetZ() - coors.z);\n\t\tif(dist < closestDist){\n\t\t\tclosestDist = dist;\n\t\t\tclosestNode = i;\n\t\t}\n\t}\n\treturn closestDist < distLimit ? closestNode : -1;\n}\n\nint32\nCPathFind::FindNodeClosestToCoorsFavourDirection(CVector coors, uint8 type, float dirX, float dirY)\n{\n\tint i;\n\tint firstNode, lastNode;\n\tfloat dist, dX, dY;\n\tNormalizeXY(dirX, dirY);\n\tfloat closestDist = 10000.0f;\n\tint closestNode = 0;\n\n\tswitch(type){\n\tcase PATH_CAR:\n\t\tfirstNode = 0;\n\t\tlastNode = m_numCarPathNodes;\n\t\tbreak;\n\tcase PATH_PED:\n\t\tfirstNode = m_numCarPathNodes;\n\t\tlastNode = m_numPathNodes;\n\t\tbreak;\n\t}\n\n\tfor(i = firstNode; i < lastNode; i++){\n\t\tdX = m_pathNodes[i].GetX() - coors.x;\n\t\tdY = m_pathNodes[i].GetY() - coors.y;\n\t\tdist = Abs(dX) + Abs(dY) +\n\t\t       3.0f*Abs(m_pathNodes[i].GetZ() - coors.z);\n\t\tif(dist < closestDist){\n\t\t\tNormalizeXY(dX, dY);\n\t\t\tdist -= (dX*dirX + dY*dirY - 1.0f)*20.0f;\n\t\t\tif(dist < closestDist){\n\t\t\t\tclosestDist = dist;\n\t\t\t\tclosestNode = i;\n\t\t\t}\n\t\t}\n\t}\n\treturn closestNode;\n}\n\nvoid\nCPathFind::FindNodePairClosestToCoors(CVector coors, uint8 type, int* node1, int* node2, float* angle, float minDist, float maxDist, bool ignoreDisabled, bool ignoreBetweenLevels, bool bWaterPath)\n{\n\tint i, j;\n\tint firstNode, lastNode, connectedNode;\n\tfloat dist;\n\tfloat closestDist = 10000.0f;\n\tint closestNode = 0, closestConnectedNode = 0;\n\n\tswitch (type) {\n\tcase PATH_CAR:\n\t\tfirstNode = 0;\n\t\tlastNode = m_numCarPathNodes;\n\t\tbreak;\n\tcase PATH_PED:\n\t\tfirstNode = m_numCarPathNodes;\n\t\tlastNode = m_numPathNodes;\n\t\tbreak;\n\t}\n\n\tfor (i = firstNode; i < lastNode; i++) {\n\t\tif (ignoreDisabled && m_pathNodes[i].bDisabled) continue;\n\t\tif (ignoreBetweenLevels && m_pathNodes[i].bBetweenLevels) continue;\n\t\tif (bWaterPath != m_pathNodes[i].bWaterPath) continue;\n\t\tdist = Abs(m_pathNodes[i].GetX() - coors.x) +\n\t\t\tAbs(m_pathNodes[i].GetY() - coors.y) +\n\t\t\t3.0f * Abs(m_pathNodes[i].GetZ() - coors.z);\n\t\tif (dist < closestDist) {\n\t\t\tfor (j = 0; j < m_pathNodes[i].numLinks; j++) {\n\t\t\t\tconnectedNode = ConnectedNode(m_pathNodes[i].firstLink + j);\n\t\t\t\tif (ignoreDisabled && m_pathNodes[connectedNode].bDisabled) continue;\n\t\t\t\tif (ignoreBetweenLevels && m_pathNodes[connectedNode].bBetweenLevels) continue;\n\t\t\t\tif (bWaterPath != m_pathNodes[connectedNode].bWaterPath) continue;\n\t\t\t\tif ((m_pathNodes[connectedNode].GetPosition() - m_pathNodes[i].GetPosition()).Magnitude() > minDist) {\n\t\t\t\t\tclosestDist = dist;\n\t\t\t\t\tclosestNode = i;\n\t\t\t\t\tclosestConnectedNode = connectedNode;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tif (closestDist < maxDist) {\n\t\t*node1 = closestNode;\n\t\t*node2 = closestConnectedNode;\n\t\tCVector dir(m_pathNodes[*node2].GetX() - m_pathNodes[*node1].GetX(), m_pathNodes[*node2].GetY() - m_pathNodes[*node1].GetY(), 0.0f);\n\t\tdir.Normalise();\n\t\t*angle = RADTODEG(Atan2(-dir.x, dir.y));\n\t}\n\telse {\n\t\t*node1 = -1;\n\t\t*node2 = -1;\n\t\t*angle = 0.0f;\n\t}\n}\n\nint32\nCPathFind::FindNthNodeClosestToCoors(CVector coors, uint8 type, float distLimit, bool ignoreDisabled, bool ignoreBetweenLevels, int N, bool bWaterPath)\n{\n\tint i;\n\tint firstNode, lastNode;\n\tswitch (type) {\n\tcase PATH_CAR:\n\t\tfirstNode = 0;\n\t\tlastNode = m_numCarPathNodes;\n\t\tbreak;\n\tcase PATH_PED:\n\t\tfirstNode = m_numCarPathNodes;\n\t\tlastNode = m_numPathNodes;\n\t\tbreak;\n\t}\n\tfor (i = firstNode; i < lastNode; i++)\n\t\tm_pathNodes[i].bSelected = false;\n\t\n\tfor (; N > 0; N--) {\n\t\ti = FindNodeClosestToCoors(coors, type, distLimit, ignoreDisabled, ignoreBetweenLevels, true, bWaterPath);\n\t\tif (i < 0)\n\t\t\treturn -1;\n\t\tm_pathNodes[i].bSelected = true;\n\t}\n\treturn FindNodeClosestToCoors(coors, type, distLimit, ignoreDisabled, ignoreBetweenLevels, true, bWaterPath);\n}\n\nCVector\nCPathFind::FindNodeCoorsForScript(int32 id)\n{\n\t// the point is to return valid position in case there is a divider in the middle of the road\n\tif (!m_pathNodes[id].HasDivider() || m_pathNodes[id].numLinks == 0)\n\t\treturn m_pathNodes[id].GetPosition();\n\tCVector2D dir(m_pathNodes[ConnectedNode(m_pathNodes[id].firstLink)].GetX() - m_pathNodes[id].GetX(), \n\t\tm_pathNodes[ConnectedNode(m_pathNodes[id].firstLink)].GetY() - m_pathNodes[id].GetY());\n\tdir.Normalise();\n\tif (dir.x < 0)\n\t\tdir = -dir;\n\treturn m_pathNodes[id].GetPosition() + CVector(-dir.y, dir.x, 0.0f) * (LANE_WIDTH / 2 + m_pathNodes[id].GetDividerWidth());\n}\n\nfloat\nCPathFind::FindNodeOrientationForCarPlacement(int32 nodeId)\n{\n\tif(m_pathNodes[nodeId].numLinks == 0)\n\t\treturn 0.0f;\n\tCVector dir = m_pathNodes[ConnectedNode(m_pathNodes[nodeId].firstLink)].GetPosition() - m_pathNodes[nodeId].GetPosition();\n\tdir.z = 0.0f;\n\tdir.Normalise();\n\treturn RADTODEG(dir.Heading());\n}\n\nfloat\nCPathFind::FindNodeOrientationForCarPlacementFacingDestination(int32 nodeId, float x, float y, bool towards)\n{\n\tint i;\n\n\tCVector targetDir(x - m_pathNodes[nodeId].GetX(), y - m_pathNodes[nodeId].GetY(), 0.0f);\n\ttargetDir.Normalise();\n\tCVector dir;\n\n\tif(m_pathNodes[nodeId].numLinks == 0)\n\t\treturn 0.0f;\n\n\tint bestNode = ConnectedNode(m_pathNodes[nodeId].firstLink);\n#ifdef FIX_BUGS\n\tfloat bestDot = towards ? -2.0f : 2.0f;\n#else\n\tint bestDot = towards ? -2 : 2;\t// why int?\n#endif\n\n\tfor(i = 0; i < m_pathNodes[nodeId].numLinks; i++){\n\t\tdir = m_pathNodes[ConnectedNode(m_pathNodes[nodeId].firstLink + i)].GetPosition() - m_pathNodes[nodeId].GetPosition();\n\t\tdir.z = 0.0f;\n\t\tdir.Normalise();\n\t\tfloat angle = DotProduct2D(dir, targetDir);\n\t\tif(towards){\n\t\t\tif(angle > bestDot){\n\t\t\t\tbestDot = angle;\n\t\t\t\tbestNode = ConnectedNode(m_pathNodes[nodeId].firstLink + i);\n\t\t\t}\n\t\t}else{\n\t\t\tif(angle < bestDot){\n\t\t\t\tbestDot = angle;\n\t\t\t\tbestNode = ConnectedNode(m_pathNodes[nodeId].firstLink + i);\n\t\t\t}\n\t\t}\n\t}\n\n\tdir = m_pathNodes[bestNode].GetPosition() - m_pathNodes[nodeId].GetPosition();\n\tdir.z = 0.0f;\n\tdir.Normalise();\n\treturn RADTODEG(dir.Heading());\n}\n\nbool\nCPathFind::GenerateCarCreationCoors(float x, float y, float dirX, float dirY, float spawnDist, float angleLimit, bool forward, CVector *pPosition, int32 *pNode1, int32 *pNode2, float *pPositionBetweenNodes, bool ignoreDisabled)\n{\n\tint i, j;\n\tint node1, node2;\n\tfloat dist1, dist2, d1, d2;\n\n\tif(m_numCarPathNodes == 0)\n\t\treturn false;\n\n\tfor(i = 0; i < 500; i++){\n\t\tnode1 = (CGeneral::GetRandomNumber()>>3) % m_numCarPathNodes;\n\t\tif(m_pathNodes[node1].bDisabled && !ignoreDisabled)\n\t\t\tcontinue;\n\t\tdist1 = Distance2D(m_pathNodes[node1].GetPosition(), x, y);\n\t\tif(dist1 < Max(spawnDist + 70.0f, spawnDist * 1.7f)){\n\t\t\td1 = m_pathNodes[node1].bWaterPath ? (dist1 - spawnDist * 1.5f) : (dist1 - spawnDist);\n\t\t\tfor(j = 0; j < m_pathNodes[node1].numLinks; j++){\n\t\t\t\tnode2 = ConnectedNode(m_pathNodes[node1].firstLink + j);\n\t\t\t\tif(m_pathNodes[node2].bDisabled && !ignoreDisabled)\n\t\t\t\t\tcontinue;\n\t\t\t\tdist2 = Distance2D(m_pathNodes[node2].GetPosition(), x, y);\n\t\t\t\td2 = m_pathNodes[node2].bWaterPath ? (dist2 - spawnDist * 1.5f) : (dist2 - spawnDist);\n\t\t\t\tif(d1*d2 < 0.0f){\n\t\t\t\t\t// nodes are on different sides of spawn distance\n\t\t\t\t\tfloat f2 = Abs(d1)/(Abs(d1) + Abs(d2));\n\t\t\t\t\tfloat f1 = 1.0f - f2;\n\t\t\t\t\t*pPositionBetweenNodes = f2;\n\t\t\t\t\tCVector pos = m_pathNodes[node1].GetPosition()*f1 + m_pathNodes[node2].GetPosition()*f2;\n\t\t\t\t\tCVector2D dist2d(pos.x - x, pos.y - y);\n\t\t\t\t\tdist2d.Normalise();\t// done manually in the game\n\t\t\t\t\tfloat dot = DotProduct2D(dist2d, CVector2D(dirX, dirY));\n\t\t\t\t\tif(forward){\n\t\t\t\t\t\tif(dot > angleLimit){\n\t\t\t\t\t\t\t*pNode1 = node1;\n\t\t\t\t\t\t\t*pNode2 = node2;\n\t\t\t\t\t\t\t*pPosition = pos;\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}else{\n\t\t\t\t\t\tif(dot <= angleLimit){\n\t\t\t\t\t\t\t*pNode1 = node1;\n\t\t\t\t\t\t\t*pNode2 = node2;\n\t\t\t\t\t\t\t*pPosition = pos;\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn false;\n}\n\nbool\nCPathFind::GeneratePedCreationCoors(float x, float y, float minDist, float maxDist, float minDistOffScreen, float maxDistOffScreen, CVector *pPosition, int32 *pNode1, int32 *pNode2, float *pPositionBetweenNodes, CMatrix *camMatrix)\n{\n\tint i;\n\tint node1, node2;\n\tfloat node1_dist, node2_dist;\n\tstatic int32 node_cnt;\n\n\tif(m_numPedPathNodes == 0)\n\t\treturn false;\n\n\tfor(i = 0; i < 230; i++){\n\t\tif (node_cnt++ >= m_numPedPathNodes)\n\t\t\tnode_cnt = 0;\n\t\tnode1 = node_cnt + m_numCarPathNodes;\n\t\tnode1_dist = Distance2D(m_pathNodes[node1].GetPosition(), x, y);\n\t\tif(node1_dist < maxDist+30.0f){\n\t\t\tif(m_pathNodes[node1].numLinks != 0)\n\t\t\t\tbreak;\n\t\t}\n\t}\n\tif (i >= 230)\n\t\treturn false;\n\n\tfor(i = 0; i < m_pathNodes[node1].numLinks; i++){\n\t\tint link = m_pathNodes[node1].firstLink + i;\n\t\tif(ConnectionCrossesRoad(link))\n\t\t\tcontinue;\n\t\tnode2 = ConnectedNode(link);\n\t\tif(m_pathNodes[node1].bDisabled || m_pathNodes[node2].bDisabled)\n\t\t\tcontinue;\n\t\tnode2_dist = Distance2D(m_pathNodes[node2].GetPosition(), x, y);\n\t\tif ((node1_dist < maxDist || node2_dist < maxDist) && (node1_dist > minDistOffScreen || node2_dist > minDistOffScreen))\n\t\t\tbreak;\n\t}\n\tif(i >= m_pathNodes[node1].numLinks)\n\t\treturn false;\n\n\tfor(i = 0; i < 5; i++){\n\t\tfloat f2 = (CGeneral::GetRandomNumber()&0xFF)/256.0f;\n\t\tfloat f1 = 1.0f - f2;\n\t\t*pPositionBetweenNodes = f2;\n\t\tCVector pos = m_pathNodes[node1].GetPosition()*f1 + m_pathNodes[node2].GetPosition()*f2;\n\t\tif(Distance2D(pos, x, y) < maxDist+20.0f){\n\t\t\tpos.x += ((CGeneral::GetRandomNumber()&0xFF)-128)*0.01f;\n\t\t\tpos.y += ((CGeneral::GetRandomNumber()&0xFF)-128)*0.01f;\n\t\t\tfloat dist = Distance2D(pos, x, y);\n\n\t\t\tbool visible;\n\t\t\tif(camMatrix)\n\t\t\t\tvisible = TheCamera.IsSphereVisible(pos, 2.0f, camMatrix);\n\t\t\telse\n\t\t\t\tvisible = TheCamera.IsSphereVisible(pos, 2.0f);\n\t\t\tif(!visible){\n\t\t\t\tminDist = minDistOffScreen;\n\t\t\t\tmaxDist = maxDistOffScreen;\n\t\t\t}\n\t\t\tif(visible && (minDist < dist && dist < maxDist) ||\n\t\t\t\t!visible && (minDistOffScreen < dist && dist < maxDistOffScreen)){\n\t\t\t\t*pNode1 = node1;\n\t\t\t\t*pNode2 = node2;\n\t\t\t\t*pPosition = pos;\n\n\t\t\t\tbool found;\n\t\t\t\tfloat groundZ = CWorld::FindGroundZFor3DCoord(pos.x, pos.y, pos.z+2.0f, &found);\n\t\t\t\tif(!found)\n\t\t\t\t\treturn false;\n\t\t\t\tif(Abs(groundZ - pos.z) > 3.0f)\n\t\t\t\t\treturn false;\n\t\t\t\tpPosition->z = groundZ;\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t}\n\treturn false;\n}\n\nvoid\nCPathFind::FindNextNodeWandering(uint8 type, CVector coors, CPathNode **lastNode, CPathNode **nextNode, uint8 curDir, uint8 *nextDir)\n{\n\tint i;\n\tCPathNode *node;\n\n\tif(lastNode == nil || (node = *lastNode) == nil || (coors - (*lastNode)->GetPosition()).MagnitudeSqr() > 7.0f){\n\t\tint32 nodeIdx = FindNodeClosestToCoors(coors, type, 999999.88f);\n\t\tnode = &m_pathNodes[nodeIdx];\n\t}\n\n\tCVector2D vCurDir(Sin(curDir*PI/4.0f), Cos(curDir * PI / 4.0f));\n\t*nextNode = 0;\n\tfloat bestDot = -999999.0f;\n\tfor(i = 0; i < node->numLinks; i++){\n\t\tint next = ConnectedNode(node->firstLink+i);\n\t\tif(!node->bDisabled && m_pathNodes[next].bDisabled)\n\t\t\tcontinue;\n\t\tCVector pedCoors = coors;\n\t\tpedCoors.z += 1.0f;\n\t\tCVector nodeCoors = m_pathNodes[next].GetPosition();\n\t\tnodeCoors.z += 1.0f;\n\t\tif(!CWorld::GetIsLineOfSightClear(pedCoors, nodeCoors, true, false, false, false, false, false))\n\t\t\tcontinue;\n\t\tCVector2D nodeDir = m_pathNodes[next].GetPosition() - node->GetPosition();\n\t\tnodeDir.Normalise();\n\t\tfloat dot = DotProduct2D(nodeDir, vCurDir);\n\t\tif(dot >= bestDot){\n\t\t\t*nextNode = &m_pathNodes[next];\n\t\t\tbestDot = dot;\n\n\t\t\t// direction is 0, 2, 4, 6 for north, east, south, west\n\t\t\t// this could be done simpler...\n\t\t\tif(nodeDir.x < 0.0f){\n\t\t\t\tif(2.0f*Abs(nodeDir.y) < -nodeDir.x)\n\t\t\t\t\t*nextDir = 6;\t// west\n\t\t\t\telse if(-2.0f*nodeDir.x < nodeDir.y)\n\t\t\t\t\t*nextDir = 0;\t// north\n\t\t\t\telse if(2.0f*nodeDir.x > nodeDir.y)\n\t\t\t\t\t*nextDir = 4;\t// south\n\t\t\t\telse if(nodeDir.y > 0.0f)\n\t\t\t\t\t*nextDir = 7;\t// north west\n\t\t\t\telse\n\t\t\t\t\t*nextDir = 5;\t// south west`\n\t\t\t}else{\n\t\t\t\tif(2.0f*Abs(nodeDir.y) < nodeDir.x)\n\t\t\t\t\t*nextDir = 2;\t// east\n\t\t\t\telse if(2.0f*nodeDir.x < nodeDir.y)\n\t\t\t\t\t*nextDir = 0;\t// north\n\t\t\t\telse if(-2.0f*nodeDir.x > nodeDir.y)\n\t\t\t\t\t*nextDir = 4;\t// south\n\t\t\t\telse if(nodeDir.y > 0.0f)\n\t\t\t\t\t*nextDir = 1;\t// north east\n\t\t\t\telse\n\t\t\t\t\t*nextDir = 3;\t// south east`\n\t\t\t}\n\t\t}\n\t}\n\tif(*nextNode == nil){\n\t\t*nextDir = 0;\n\t\t*nextNode = node;\n\t}\n}\n\nstatic CPathNode *apNodesToBeCleared[6525];\n\nvoid\nCPathFind::DoPathSearch(uint8 type, CVector start, int32 startNodeId, CVector target, CPathNode **nodes, int16 *pNumNodes, int16 maxNumNodes, CVehicle *vehicle, float *pDist, float distLimit, int32 targetNodeId)\n{\n\tint i, j;\n\n\t// Find target\n\tif(targetNodeId < 0)\n\t\ttargetNodeId = FindNodeClosestToCoors(target, type, distLimit);\n\tif(targetNodeId < 0) {\n\t\t*pNumNodes = 0;\n\t\tif(pDist) *pDist = 100000.0f;\n\t\treturn;\n\t}\n\n\t// Find start\n\tif(startNodeId < 0)\n\t\tstartNodeId = FindNodeClosestToCoors(start, type, 999999.88f);\n\tif(startNodeId < 0) {\n\t\t*pNumNodes = 0;\n\t\tif(pDist) *pDist = 100000.0f;\n\t\treturn;\n\t}\n\tif(startNodeId == targetNodeId){\n\t\t*pNumNodes = 0;\n\t\tif(pDist) *pDist = 0.0f;\n\t\treturn;\n\t}\n\tif(m_pathNodes[startNodeId].group != m_pathNodes[targetNodeId].group) {\n\t\t*pNumNodes = 0;\n\t\tif(pDist) *pDist = 100000.0f;\n\t\treturn;\n\t}\n\n\tfor(i = 0; i < ARRAY_SIZE(m_searchNodes); i++)\n\t\tm_searchNodes[i].SetNext(nil);\n\tAddNodeToList(&m_pathNodes[targetNodeId], 0);\n\tint numNodesToBeCleared = 0;\n\tapNodesToBeCleared[numNodesToBeCleared++] = &m_pathNodes[targetNodeId];\n\n\t// Dijkstra's algorithm\n\t// Find distances\n\tint numPathsFound = 0;\n\tfor(i = 0; numPathsFound == 0; i = (i+1) & 0x1FF){\n\t\tCPathNode *node;\n\t\tfor(node = m_searchNodes[i].GetNext(); node; node = node->GetNext()){\n\t\t\tif(node == &m_pathNodes[startNodeId])\n\t\t\t\tnumPathsFound = 1;\n\n\t\t\tfor(j = 0; j < node->numLinks; j++){\n\t\t\t\tint next = ConnectedNode(node->firstLink + j);\n\t\t\t\tint dist = node->distance + m_distances[node->firstLink + j];\n\t\t\t\tif(dist < m_pathNodes[next].distance){\n\t\t\t\t\tif(m_pathNodes[next].distance != MAX_DIST)\n\t\t\t\t\t\tRemoveNodeFromList(&m_pathNodes[next]);\n\t\t\t\t\tif(m_pathNodes[next].distance == MAX_DIST)\n\t\t\t\t\t\tapNodesToBeCleared[numNodesToBeCleared++] = &m_pathNodes[next];\n\t\t\t\t\tAddNodeToList(&m_pathNodes[next], dist);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tRemoveNodeFromList(node);\n\t\t}\n\t}\n\n\t// Find out whence to start tracing back\n\tCPathNode *curNode;\n\tcurNode = &m_pathNodes[startNodeId];\n\t*pNumNodes = 0;\n\tif(pDist)\n\t\t*pDist = m_pathNodes[startNodeId].distance;\n\n\tnodes[(*pNumNodes)++] = curNode;\n\t// Trace back to target and update list of nodes\n\twhile(*pNumNodes < maxNumNodes && curNode != &m_pathNodes[targetNodeId])\n\t\tfor(i = 0; i < curNode->numLinks; i++){\n\t\t\tint next = ConnectedNode(curNode->firstLink + i);\n\t\t\tif(curNode->distance - m_distances[curNode->firstLink + i] == m_pathNodes[next].distance){\n\t\t\t\tcurNode = &m_pathNodes[next];\n\t\t\t\tnodes[(*pNumNodes)++] = curNode;\n\t\t\t\ti = 29030;\t// could have used a break...\n\t\t\t}\n\t\t}\n\n\tfor(i = 0; i < numNodesToBeCleared; i++)\n\t\tapNodesToBeCleared[i]->distance = MAX_DIST;\n}\n\nstatic CPathNode *pNodeList[32];\nstatic int16 DummyResult;\nstatic int16 DummyResult2;\n\nbool\nCPathFind::TestCoorsCloseness(CVector target, uint8 type, CVector start)\n{\n\tfloat dist;\n\n\tif(type == PATH_CAR)\n\t\tDoPathSearch(type, start, -1, target, pNodeList, &DummyResult, 32, nil, &dist, 999999.88f, -1);\n\telse\n\t\tDoPathSearch(type, start, -1, target, nil, &DummyResult2, 0, nil, &dist, 50.0f, -1);\n#ifdef FIX_BUGS\n\t// dist has GenerationDistMultiplier as a factor, so our reference dist should have it too\n\tif(type == PATH_CAR)\n\t\treturn dist < 150.0f*TheCamera.GenerationDistMultiplier;\n\telse\n\t\treturn dist < 100.0f*TheCamera.GenerationDistMultiplier;\n#else\n\tif(type == PATH_CAR)\n\t\treturn dist < 150.0f;\n\telse\n\t\treturn dist < 100.0f;\n#endif\n}\n\nvoid\nCPathFind::Save(uint8 *buf, uint32 *size)\n{\n\tint i;\n\tint n = m_numPathNodes/8 + 1;\n\n\t*size = 2*n;\n\n\tfor(i = 0; i < m_numPathNodes; i++)\n\t\tif(m_pathNodes[i].bDisabled)\n\t\t\tbuf[i/8] |= 1 << i%8;\n\t\telse\n\t\t\tbuf[i/8] &= ~(1 << i%8);\n\n\tfor(i = 0; i < m_numPathNodes; i++)\n\t\tif(m_pathNodes[i].bBetweenLevels)\n\t\t\tbuf[i/8 + n] |= 1 << i%8;\n\t\telse\n\t\t\tbuf[i/8 + n] &= ~(1 << i%8);\n}\n\nvoid\nCPathFind::Load(uint8 *buf, uint32 size)\n{\n\tint i;\n\tint n = m_numPathNodes/8 + 1;\n\n\tfor(i = 0; i < m_numPathNodes; i++)\n\t\tif(buf[i/8] & (1 << i%8))\n\t\t\tm_pathNodes[i].bDisabled = true;\n\t\telse\n\t\t\tm_pathNodes[i].bDisabled = false;\n\n\tfor(i = 0; i < m_numPathNodes; i++)\n\t\tif(buf[i/8 + n] & (1 << i%8))\n\t\t\tm_pathNodes[i].bBetweenLevels = true;\n\t\telse\n\t\t\tm_pathNodes[i].bBetweenLevels = false;\n\n#ifdef SECUROM\n\t// if pirated game\n\tfor(i = 0; i < m_numPathNodes; i++)\n\t\tm_pathNodes[i].bDisabled = true;\n#endif\n}\n\nvoid\nCPathFind::DisplayPathData(void)\n{\n\t// Not the function from mobile but my own!\n\n\tint i, j, k;\n\t// Draw 50 units around camera\n\tCVector pos = TheCamera.GetPosition();\n\tconst float maxDist = 50.0f;\n\n\t// Render car path nodes\n\tif(gbShowCarPaths)\n\tfor(i = 0; i < m_numCarPathNodes; i++){\n\t\tif((m_pathNodes[i].GetPosition() - pos).MagnitudeSqr() > SQR(maxDist))\n\t\t\tcontinue;\n\n\t\tCVector n1 = m_pathNodes[i].GetPosition();\n\t\tn1.z += 0.3f;\n\n\t\t// Draw node itself\n\t\tCLines::RenderLineWithClipping(n1.x, n1.y, n1.z,\n\t\t\tn1.x, n1.y, n1.z + 1.0f,\n\t\t\t0xFFFFFFFF, 0xFFFFFFFF);\n\n\t\tfor(j = 0; j < m_pathNodes[i].numLinks; j++){\n\t\t\tk = ConnectedNode(m_pathNodes[i].firstLink + j);\n\t\t\tCVector n2 = m_pathNodes[k].GetPosition();\n\t\t\tn2.z += 0.3f;\n\t\t\t// Draw links to neighbours\n\t\t\tCLines::RenderLineWithClipping(n1.x, n1.y, n1.z,\n\t\t\t\tn2.x, n2.y, n2.z,\n\t\t\t\t0xFFFFFFFF, 0xFFFFFFFF);\n\t\t}\n\t}\n\n\t// Render car path nodes\n\tif(gbShowCarPathsLinks)\n\tfor(i = 0; i < m_numCarPathLinks; i++){\n\t\tCVector2D n1_2d = m_carPathLinks[i].GetPosition();\n\t\tif((n1_2d - pos).MagnitudeSqr() > SQR(maxDist))\n\t\t\tcontinue;\n\n\t\tint ni = m_carPathLinks[i].pathNodeIndex;\n\t\tCVector pn1 = m_pathNodes[ni].GetPosition();\n\t\tpn1.z += 0.3f;\n\t\tCVector n1(n1_2d.x, n1_2d.y, pn1.z);\n\t\tn1.z += 0.3f;\n\n\t\t// Draw car node itself\n\t\tCLines::RenderLineWithClipping(n1.x, n1.y, n1.z,\n\t\t\tn1.x, n1.y, n1.z + 1.0f,\n\t\t\t0xFFFFFFFF, 0xFFFFFFFF);\n\t\tCLines::RenderLineWithClipping(n1.x, n1.y, n1.z + 0.5f,\n\t\t\tn1.x+m_carPathLinks[i].GetDirX(), n1.y+m_carPathLinks[i].GetDirY(), n1.z + 0.5f,\n\t\t\t0xFFFFFFFF, 0xFFFFFFFF);\n\n\t\t// Draw connection to car path node\n\t\tCLines::RenderLineWithClipping(n1.x, n1.y, n1.z,\n\t\t\tpn1.x, pn1.y, pn1.z,\n\t\t\t0xFF0000FF, 0xFFFFFFFF);\n\n\t\t// traffic light type\n\t\tuint32 col = 0xFF;\n\t\tif((m_carPathLinks[i].trafficLightType&0x7F) == 1)\n\t\t\tcol += 0xFF000000;\n\t\tif((m_carPathLinks[i].trafficLightType&0x7F) == 2)\n\t\t\tcol += 0x00FF0000;\n\t\tif(m_carPathLinks[i].trafficLightType & 0x80)\n\t\t\tcol += 0x0000FF00;\n\t\tCLines::RenderLineWithClipping(n1.x+0.2f, n1.y, n1.z,\n\t\t\tn1.x+0.2f, n1.y, n1.z + 1.0f,\n\t\t\tcol, col);\n\n\t\tfor(j = 0; j < m_pathNodes[ni].numLinks; j++){\n\t\t\tk = m_carPathConnections[m_pathNodes[ni].firstLink + j];\n\t\t\tCVector2D n2_2d = m_carPathLinks[k].GetPosition();\n\t\t\tint nk = m_carPathLinks[k].pathNodeIndex;\n\t\t\tCVector pn2 = m_pathNodes[nk].GetPosition();\n\t\t\tpn2.z += 0.3f;\n\t\t\tCVector n2(n2_2d.x, n2_2d.y, pn2.z);\n\t\t\tn2.z += 0.3f;\n\n\t\t\t// Draw links to neighbours\n\t\t\tCLines::RenderLineWithClipping(n1.x, n1.y, n1.z,\n\t\t\t\tn2.x, n2.y, n2.z,\n\t\t\t\t0xFF00FFFF, 0xFF00FFFF);\n\t\t}\n\t}\n\n\t// Render ped path nodes\n\tif(gbShowPedPaths)\n\tfor(i = m_numCarPathNodes; i < m_numPathNodes; i++){\n\t\tif((m_pathNodes[i].GetPosition() - pos).MagnitudeSqr() > SQR(maxDist))\n\t\t\tcontinue;\n\n\t\tCVector n1 = m_pathNodes[i].GetPosition();\n\t\tn1.z += 0.3f;\n\n\t\t// Draw node itself\n\t\tCLines::RenderLineWithClipping(n1.x, n1.y, n1.z,\n\t\t\tn1.x, n1.y, n1.z + 1.0f,\n\t\t\t0xFFFFFFFF, 0xFFFFFFFF);\n\n\t\tfor(j = 0; j < m_pathNodes[i].numLinks; j++){\n\t\t\tk = ConnectedNode(m_pathNodes[i].firstLink + j);\n\t\t\tCVector n2 = m_pathNodes[k].GetPosition();\n\t\t\tn2.z += 0.3f;\n\t\t\t// Draw links to neighbours\n\t\t\tCLines::RenderLineWithClipping(n1.x, n1.y, n1.z,\n\t\t\t\tn2.x, n2.y, n2.z,\n\t\t\t\t0xFFFFFFFF, 0xFFFFFFFF);\n\n\t\t\t// Draw connection flags\n\t\t\tCVector mid = (n1+n2)/2.0f;\n\t\t\tuint32 col = 0xFF;\n\t\t\tif(ConnectionCrossesRoad(m_pathNodes[i].firstLink + j))\n\t\t\t\tcol += 0x00FF0000;\n\t\t\tif(ConnectionHasTrafficLight(m_pathNodes[i].firstLink + j))\n\t\t\t\tcol += 0xFF000000;\n\t\t\tCLines::RenderLineWithClipping(mid.x, mid.y, mid.z,\n\t\t\t\tmid.x, mid.y, mid.z + 1.0f,\n\t\t\t\tcol, col);\n\t\t}\n\t}\n}\n\nCVector\nCPathFind::TakeWidthIntoAccountForWandering(CPathNode* nextNode, uint16 random)\n{\n\tCVector pos = nextNode->GetPosition();\n\tfloat newX = (nextNode->GetPedNodeWidth() * ((random % 16) - 7)) + pos.x;\n\tfloat newY = (nextNode->GetPedNodeWidth() * (((random / 16) % 16) - 7)) + pos.y;\n\treturn CVector(newX, newY, pos.z);\n}\n\nvoid\nCPathFind::TakeWidthIntoAccountForCoors(CPathNode* node1, CPathNode* node2, uint16 random, float* x, float* y)\n{\n\t*x += (Min(node1->width, node2->width) * WIDTH_TO_PED_NODE_WIDTH * ((random % 16) - 7));\n\t*y += (Min(node1->width, node2->width) * WIDTH_TO_PED_NODE_WIDTH * (((random / 16) % 16) - 7));\n}\n\nCPathNode*\nCPathFind::GetNode(int16 index)\n{\n\tif(index < 0)\n\t\treturn nil;\n\tif(index < ARRAY_SIZE(ThePaths.m_searchNodes))\n\t\treturn &ThePaths.m_searchNodes[index];\n\treturn &ThePaths.m_pathNodes[index - ARRAY_SIZE(ThePaths.m_searchNodes)];\n}\nint16\nCPathFind::GetIndex(CPathNode *node)\n{\n\tif(node == nil)\n\t\treturn -1;\n\tif(node >= &ThePaths.m_searchNodes[0] && node < &ThePaths.m_searchNodes[ARRAY_SIZE(ThePaths.m_searchNodes)])\n\t\treturn node - ThePaths.m_searchNodes;\n\telse\n\t\treturn (node - ThePaths.m_pathNodes) + ARRAY_SIZE(ThePaths.m_searchNodes);\n}\n"
  },
  {
    "path": "src/control/PathFind.h",
    "content": "#pragma once\n\n#include \"Treadable.h\"\n\nclass CVehicle;\nclass CPtrList;\n\n#define LANE_WIDTH 5.0f\n#define WIDTH_TO_PED_NODE_WIDTH (31.f/(500.f * 8.f))\n\nenum\n{\n\tNodeTypeExtern = 1,\n\tNodeTypeIntern = 2,\n};\n\nenum\n{\n\tPATH_CAR = 0,\n\tPATH_PED = 1,\n};\n\nenum\n{\n\tSWITCH_OFF = 0,\n\tSWITCH_ON = 1,\n};\n\nenum \n{\n\tROUTE_ADD_BLOCKADE = 0,\n\tROUTE_NO_BLOCKADE = 1\n};\n\nstruct CPedPathNode\n{\n\tbool bBlockade;\n\tuint8 nodeIdX;\n\tuint8 nodeIdY;\n\tint16 id;\n\tCPedPathNode* prev;\n\tCPedPathNode* next;\n};\n\nVALIDATE_SIZE(CPedPathNode, 0x10);\n\nclass CPedPath {\npublic:\n\tstatic bool CalcPedRoute(int8 pathType, CVector position, CVector destination, CVector *pointPoses, int16 *pointsFound, int16 maxPoints);\n\tstatic void AddNodeToPathList(CPedPathNode *pNodeToAdd, int16 id, CPedPathNode *pNodeList);\n\tstatic void RemoveNodeFromList(CPedPathNode *pNode);\n\tstatic void AddNodeToList(CPedPathNode *pNode, int16 index, CPedPathNode *pList);\n\tstatic void AddBlockade(CEntity *pEntity, CPedPathNode(*pathNodes)[40], CVector *pPosition);\n\tstatic void AddBlockadeSectorList(CPtrList& list, CPedPathNode(*pathNodes)[40], CVector *pPosition);\n\tstatic void AddBuildingBlockade(CEntity*, CPedPathNode(*)[40], CVector*);\n\tstatic void AddBuildingBlockadeSectorList(CPtrList&, CPedPathNode(*)[40], CVector*);\n};\n\nstruct CPathNode\n{\n\tint16 prevIndex;\n\tint16 nextIndex;\n\tint16 x;\n\tint16 y;\n\tint16 z;\n\tint16 distance;\t\t// in path search\n\tint16 firstLink;\n\tuint8 width;\n\tint8 group;\n\n\tuint8 numLinks : 4;\n\tuint8 bDeadEnd : 1;\n\tuint8 bDisabled : 1;\n\tuint8 bBetweenLevels : 1;\n\tuint8 bUseInRoadBlock : 1;\n\n\tuint8 bWaterPath : 1;\n\tuint8 bOnlySmallBoats : 1;\n\tuint8 bSelected : 1;\n\tuint8 speedLimit : 2;\n\t//uint8 flagB20 : 1;\n\t//uint8 flagB40 : 1;\n\t//uint8 flagB80 : 1;\n\n\tuint8 spawnRate : 4;\n\tuint8 flagsC : 4;\n\n\tCVector GetPosition(void) { return CVector(x/8.0f, y/8.0f, z/8.0f); }\n\tvoid SetPosition(const CVector &p) { x = p.x*8.0f; y = p.y*8.0f; z = p.z*8.0f; }\n\tfloat GetX(void) { return x/8.0f; }\n\tfloat GetY(void) { return y/8.0f; }\n\tfloat GetZ(void) { return z/8.0f; }\n\tbool HasDivider(void) { return width != 0; }\n\tfloat GetDividerWidth(void) { return width/(2*8.0f); }\n\tfloat GetPedNodeWidth(void) { return width*WIDTH_TO_PED_NODE_WIDTH; }\n\tCPathNode *GetPrev(void);\n\tCPathNode *GetNext(void);\n\tvoid SetPrev(CPathNode *node);\n\tvoid SetNext(CPathNode *node);\n};\n\nunion CConnectionFlags\n{\n\tuint8 flags;\n\tstruct {\n\t\tuint8 bCrossesRoad : 1;\n\t\tuint8 bTrafficLight : 1;\n\t};\n};\n\nstruct CCarPathLink\n{\n\tint16 x;\n\tint16 y;\n\tint16 pathNodeIndex;\n\tint8 dirX;\n\tint8 dirY;\n\tint8 numLeftLanes : 3;\n\tint8 numRightLanes : 3;\n\tuint8 trafficLightDirection : 1;\n\tuint8 trafficLightType : 2;\n\tuint8 bBridgeLights : 1;\t// at least in LCS...\n\tuint8 width;\n\n\tCVector2D GetPosition(void) { return CVector2D(x/8.0f, y/8.0f); }\n\tCVector2D GetDirection(void) { return CVector2D(dirX/100.0f, dirY/100.0f); }\n\tfloat GetX(void) { return x/8.0f; }\n\tfloat GetY(void) { return y/8.0f; }\n\tfloat GetDirX(void) { return dirX/100.0f; }\n\tfloat GetDirY(void) { return dirY/100.0f; }\n\tfloat GetLaneOffset(void) { return width/(2*8.0f*LANE_WIDTH); }\n\n\tfloat OneWayLaneOffset()\n\t{\n\t\tif (numLeftLanes == 0)\n\t\t\treturn 0.5f - 0.5f * numRightLanes;\n\t\tif (numRightLanes == 0)\n\t\t\treturn 0.5f - 0.5f * numLeftLanes;\n\t\treturn 0.5f + GetLaneOffset();\n\t}\n};\n\n// This is what we're reading from the files, only temporary\nstruct CPathInfoForObject\n{\n\tfloat x;\n\tfloat y;\n\tfloat z;\n\tint8 type;\n\tint8 next;\n\tint8 numLeftLanes;\n\tint8 numRightLanes;\n\tint8 speedLimit;\n\tuint8 width;\n\n\tuint8 crossing : 1;\n\tuint8 onlySmallBoats : 1;\n\tuint8 roadBlock : 1;\n\tuint8 disabled : 1;\n\tuint8 waterPath : 1;\n\tuint8 betweenLevels : 1;\n\n\tuint8 spawnRate : 4;\n\n\tvoid CheckIntegrity(void);\n\tvoid SwapConnectionsToBeRightWayRound(void);\n};\nextern CPathInfoForObject *InfoForTileCars;\nextern CPathInfoForObject *InfoForTilePeds;\n\nstruct CTempNode\n{\n\tCVector pos;\n\tint8 dirX;\t// *100\n\tint8 dirY;\n\tint16 link1;\n\tint16 link2;\n\tint8 numLeftLanes;\n\tint8 numRightLanes;\n\tuint8 width;\n\tbool isCross;\n\tint8 linkState;\n};\n\nstruct CTempNodeExternal\t// made up name\n{\n\tCVector pos;\n\tint16 next;\n\tint8 numLeftLanes;\n\tint8 numRightLanes;\n\tuint8 width;\n\tbool isCross;\n};\n\n// from mobile\ntemplate<typename T>\nclass CRoute\n{\n\tT m_node[8];\n};\n\n\nclass CPathFind\n{\npublic:\n\tCPathNode m_pathNodes[NUM_PATHNODES];\n\tCCarPathLink m_carPathLinks[NUM_CARPATHLINKS];\n\tCTreadable *m_mapObjects[NUM_MAPOBJECTS];\n\tuint16 m_connections[NUM_PATHCONNECTIONS];\t// and flags\n\tuint8 m_distances[NUM_PATHCONNECTIONS];\n\tint16 m_carPathConnections[NUM_PATHCONNECTIONS];\n\n\tint32 m_numPathNodes;\n\tint32 m_numCarPathNodes;\n\tint32 m_numPedPathNodes;\n\tint16 m_numMapObjects;\n\tint16 m_numConnections;\n\tint32 m_numCarPathLinks;\n\tint32 unk;\n\tuint8 m_numGroups[2];\n\tCPathNode m_searchNodes[512];\n\n\tvoid Init(void);\n\tvoid AllocatePathFindInfoMem(int16 numPathGroups);\n\tvoid RegisterMapObject(CTreadable *mapObject);\n\tvoid StoreNodeInfoPed(int16 id, int16 node, int8 type, int8 next, int16 x, int16 y, int16 z, float width, bool crossing, uint8 spawnRate);\n\tvoid StoreNodeInfoCar(int16 id, int16 node, int8 type, int8 next, int16 x, int16 y, int16 z, float width, int8 numLeft, int8 numRight,\n\t\tbool disabled, bool betweenLevels, uint8 speedLimit, bool roadBlock, bool waterPath, uint8 spawnRate);\n\tvoid StoreDetachedNodeInfoPed(int32 node, int8 type, int32 next, float x, float y, float z, float width, bool crossing,\n\t\tbool disabled, bool betweenLevels, uint8 spawnRate);\n\tvoid StoreDetachedNodeInfoCar(int32 node, int8 type, int32 next, float x, float y, float z, float width, int8 numLeft, int8 numRight,\n\t\tbool disabled, bool betweenLevels, uint8 speedLimit, bool roadBlock, bool waterPath, uint8 spawnRate, bool unk);\n\tvoid CalcNodeCoors(float x, float y, float z, int32 id, CVector *out);\n\tbool LoadPathFindData(void);\n\tvoid PreparePathData(void);\n\tvoid CountFloodFillGroups(uint8 type);\n\tvoid PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoForObject *objectpathinfo,\n\t\tfloat maxdist, CPathInfoForObject *detachednodes, int32 numDetached);\n\n\tbool IsPathObject(int id) { return id < PATHNODESIZE && (InfoForTileCars[id*12].type != 0 || InfoForTilePeds[id*12].type != 0); }\n\n\tfloat CalcRoadDensity(float x, float y);\n\tbool TestForPedTrafficLight(CPathNode *n1, CPathNode *n2);\n\tbool TestCrossesRoad(CPathNode *n1, CPathNode *n2);\n\tvoid AddNodeToList(CPathNode *node, int32 listId);\n\tvoid RemoveNodeFromList(CPathNode *node);\n\tvoid RemoveBadStartNode(CVector pos, CPathNode **nodes, int16 *n);\n\tvoid SetLinksBridgeLights(float, float, float, float, bool);\n\tvoid SwitchOffNodeAndNeighbours(int32 nodeId, bool disable);\n\tvoid SwitchRoadsOffInArea(float x1, float x2, float y1, float y2, float z1, float z2, bool disable);\n\tvoid SwitchPedRoadsOffInArea(float x1, float x2, float y1, float y2, float z1, float z2, bool disable);\n\tvoid SwitchRoadsInAngledArea(float x1, float y1, float z1, float x2, float y2, float z2, float length, uint8 type, uint8 enable);\n\tvoid MarkRoadsBetweenLevelsNodeAndNeighbours(int32 nodeId);\n\tvoid MarkRoadsBetweenLevelsInArea(float x1, float x2, float y1, float y2, float z1, float z2);\n\tvoid PedMarkRoadsBetweenLevelsInArea(float x1, float x2, float y1, float y2, float z1, float z2);\n\tint32 FindNodeClosestToCoors(CVector coors, uint8 type, float distLimit, bool ignoreDisabled = false, bool ignoreBetweenLevels = false, bool ignoreSelected = false, bool bWaterPath = false);\n\tint32 FindNodeClosestToCoorsFavourDirection(CVector coors, uint8 type, float dirX, float dirY);\n\tvoid FindNodePairClosestToCoors(CVector coors, uint8 type, int* node1, int* node2, float* angle, float minDist, float maxDist, bool ignoreDisabled = false, bool ignoreBetweenLevels = false, bool bWaterPath = false);\n\tint32 FindNthNodeClosestToCoors(CVector coors, uint8 type, float distLimit, bool ignoreDisabled, bool ignoreBetweenLevels, int N, bool bWaterPath = false);\n\tCVector FindNodeCoorsForScript(int32 id);\n\tfloat FindNodeOrientationForCarPlacement(int32 nodeId);\n\tfloat FindNodeOrientationForCarPlacementFacingDestination(int32 nodeId, float x, float y, bool towards);\n\tbool GenerateCarCreationCoors(float x, float y, float dirX, float dirY, float spawnDist, float angleLimit, bool forward, CVector *pPosition, int32 *pNode1, int32 *pNode2, float *pPositionBetweenNodes, bool ignoreDisabled = false);\n\tbool GeneratePedCreationCoors(float x, float y, float minDist, float maxDist, float minDistOffScreen, float maxDistOffScreen, CVector *pPosition, int32 *pNode1, int32 *pNode2, float *pPositionBetweenNodes, CMatrix *camMatrix);\n\tvoid FindNextNodeWandering(uint8, CVector, CPathNode**, CPathNode**, uint8, uint8*);\n\tvoid DoPathSearch(uint8 type, CVector start, int32 startNodeId, CVector target, CPathNode **nodes, int16 *numNodes, int16 maxNumNodes, CVehicle *vehicle, float *dist, float distLimit, int32 forcedTargetNode);\n\tbool TestCoorsCloseness(CVector target, uint8 type, CVector start);\n\tvoid Save(uint8 *buf, uint32 *size);\n\tvoid Load(uint8 *buf, uint32 size);\n\n\tstatic CVector TakeWidthIntoAccountForWandering(CPathNode*, uint16);\n\tstatic void TakeWidthIntoAccountForCoors(CPathNode*, CPathNode*, uint16, float*, float*);\n\n\tCPathNode *GetNode(int16 index);\n\tint16 GetIndex(CPathNode *node);\n\n\tuint16 ConnectedNode(int id) { return m_connections[id] & 0x3FFF; }\n\tbool ConnectionCrossesRoad(int id) { return !!(m_connections[id] & 0x8000); }\n\tbool ConnectionHasTrafficLight(int id) { return !!(m_connections[id] & 0x4000); }\n\tvoid ConnectionSetTrafficLight(int id) { m_connections[id] |= 0x4000; }\n\n\tvoid DisplayPathData(void);\n\n\t// Following methods are present on mobile but are unused. TODO: implement them\n\tvoid SavePathFindData(void);\n\tvoid ComputeRoute(uint8, const CVector&, const CVector&, CRoute<CPathNode*>&);\n\tvoid RecordNodesClosestToCoors(CVector, uint8, int, CPathNode**, float, bool, bool, bool);\n\tvoid RecordNodesInCircle(const CVector&, float, uint8, int, CPathNode**, bool, bool, bool, bool);\n\tvoid ArrangeOneNodeList(CPathInfoForObject*, int16);\n\tvoid ArrangeNodes(int16);\n\tvoid RegisterMarker(CVector*);\n\tvoid Shutdown(void);\n};\n\nextern CPathFind ThePaths;\n\ninline CPathNode *CPathNode::GetPrev(void) { return ThePaths.GetNode(prevIndex); }\ninline CPathNode *CPathNode::GetNext(void) { return ThePaths.GetNode(nextIndex); }\ninline void CPathNode::SetPrev(CPathNode *node) { prevIndex = ThePaths.GetIndex(node); }\ninline void CPathNode::SetNext(CPathNode *node) { nextIndex = ThePaths.GetIndex(node); }\n\nextern bool gbShowPedPaths;\nextern bool gbShowCarPaths;\nextern bool gbShowCarPathsLinks;\n"
  },
  {
    "path": "src/control/Phones.cpp",
    "content": "#include \"common.h\"\n\n#include \"Phones.h\"\n#include \"Pools.h\"\n#include \"ModelIndices.h\"\n#include \"Ped.h\"\n#include \"Pad.h\"\n#include \"Messages.h\"\n#include \"Camera.h\"\n#include \"World.h\"\n#include \"General.h\"\n#include \"AudioScriptObject.h\"\n#include \"RpAnimBlend.h\"\n#include \"AnimBlendAssociation.h\"\n#include \"soundlist.h\"\n#ifdef FIX_BUGS\n#include \"Replay.h\"\n#endif\n\nCPhoneInfo gPhoneInfo;\n\nbool CPhoneInfo::bDisplayingPhoneMessage;  // is phone picked up\nuint32 CPhoneInfo::PhoneEnableControlsTimer;\nCPhone *CPhoneInfo::pPhoneDisplayingMessages;\nbool CPhoneInfo::bPickingUpPhone;\nCPed *CPhoneInfo::pCallBackPed; // ped who picking up the phone (reset after pickup cb)\n\n/*\n\tEntering phonebooth cutscene, showing messages and triggering these things\n\tby checking coordinates happens in here - blue mission marker is cosmetic.\n\n\tRepeated message means after the script set the messages for a particular phone,\n\tplayer can pick the phone again with the same messages appearing,\n\tafter 60 seconds of last phone pick-up.\n*/\n\nvoid\nCPhoneInfo::Update(void)\n{\n#ifdef FIX_BUGS\n\tif (CReplay::IsPlayingBack())\n\t\treturn;\n#endif\n\tCPlayerPed *player = FindPlayerPed();\n\tCPlayerInfo *playerInfo = &CWorld::Players[CWorld::PlayerInFocus];\n\tif (bDisplayingPhoneMessage && CTimer::GetTimeInMilliseconds() > PhoneEnableControlsTimer) {\n\t\tplayerInfo->MakePlayerSafe(false);\n\t\tTheCamera.SetWideScreenOff();\n\t\tpPhoneDisplayingMessages = nil;\n\t\tbDisplayingPhoneMessage = false;\n\t\tCAnimBlendAssociation *talkAssoc = RpAnimBlendClumpGetAssociation(player->GetClump(), ANIM_STD_PHONE_TALK);\n\t\tif (talkAssoc && talkAssoc->blendAmount > 0.5f) {\n\t\t\tCAnimBlendAssociation *endAssoc = CAnimManager::BlendAnimation(player->GetClump(), ASSOCGRP_STD, ANIM_STD_PHONE_OUT, 8.0f);\n\t\t\tendAssoc->flags &= ~ASSOC_DELETEFADEDOUT;\n\t\t\tendAssoc->SetFinishCallback(PhonePutDownCB, player);\n\t\t} else {\n\t\t\tCPad::GetPad(0)->SetEnablePlayerControls(PLAYERCONTROL_PHONE);\n\t\t\tif (player->m_nPedState == PED_MAKE_CALL)\n\t\t\t\tplayer->SetPedState(PED_IDLE);\n\t\t}\n\t}\n\tbool notInCar;\n\tCVector playerPos;\n\tif (FindPlayerVehicle()) {\n\t\tnotInCar = false;\n\t\tplayerPos = FindPlayerVehicle()->GetPosition();\n\t} else {\n\t\tnotInCar = true;\n\t\tplayerPos = player->GetPosition();\n\t}\n\tbool phoneRings = false;\n\tbool scratchTheCabinet;\n\tfor(int phoneId = 0; phoneId < m_nScriptPhonesMax; phoneId++) {\n\t\tif (m_aPhones[phoneId].m_visibleToCam) {\n\t\t\tswitch (m_aPhones[phoneId].m_nState) {\n\t\t\t\tcase PHONE_STATE_ONETIME_MESSAGE_SET:\n\t\t\t\tcase PHONE_STATE_REPEATED_MESSAGE_SET:\n\t\t\t\tcase PHONE_STATE_REPEATED_MESSAGE_SHOWN_ONCE:\n\t\t\t\t\tif (bPickingUpPhone) {\n\t\t\t\t\t\tscratchTheCabinet = false;\n\t\t\t\t\t\tphoneRings = false;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tscratchTheCabinet = (CTimer::GetTimeInMilliseconds() / 1880) % 2 == 1;\n\t\t\t\t\t\tphoneRings = (CTimer::GetPreviousTimeInMilliseconds() / 1880) % 2 == 1;\n\t\t\t\t\t}\n\t\t\t\t\tif (scratchTheCabinet) {\n\t\t\t\t\t\tm_aPhones[phoneId].m_pEntity->GetUp().z = (CGeneral::GetRandomNumber() % 1024) / 16000.0f + 1.0f;\n\t\t\t\t\t\tif (!phoneRings)\n\t\t\t\t\t\t    PlayOneShotScriptObject(SCRIPT_SOUND_PAYPHONE_RINGING, m_aPhones[phoneId].m_pEntity->GetPosition());\n\t\t\t\t\t} else {\n\t\t\t\t\t\tm_aPhones[phoneId].m_pEntity->GetUp().z = 1.0f;\n\t\t\t\t\t}\n\t\t\t\t\tm_aPhones[phoneId].m_pEntity->GetMatrix().UpdateRW();\n\t\t\t\t\tm_aPhones[phoneId].m_pEntity->UpdateRwFrame();\n\t\t\t\t\tif (notInCar && !bPickingUpPhone && player->IsPedInControl()) {\n\t\t\t\t\t\tCVector2D distToPhone = playerPos - m_aPhones[phoneId].m_vecPos;\n\t\t\t\t\t\tif (Abs(distToPhone.x) < 1.0f && Abs(distToPhone.y) < 1.0f) {\n\t\t\t\t\t\t\tif (DotProduct2D(distToPhone, m_aPhones[phoneId].m_pEntity->GetForward()) / distToPhone.Magnitude() < -0.85f) {\n\t\t\t\t\t\t\t\tCVector2D distToPhoneObj = playerPos - m_aPhones[phoneId].m_pEntity->GetPosition();\n\t\t\t\t\t\t\t\tfloat angleToFace = CGeneral::GetATanOfXY(distToPhoneObj.x, distToPhoneObj.y) + HALFPI;\n\t\t\t\t\t\t\t\tif (angleToFace > TWOPI)\n\t\t\t\t\t\t\t\t\tangleToFace = angleToFace - TWOPI;\n\t\t\t\t\t\t\t\tplayer->m_fRotationCur = angleToFace;\n\t\t\t\t\t\t\t\tplayer->m_fRotationDest = angleToFace;\n\t\t\t\t\t\t\t\tplayer->SetHeading(angleToFace);\n\t\t\t\t\t\t\t\tplayer->SetPedState(PED_MAKE_CALL);\n\t\t\t\t\t\t\t\tCPad::GetPad(0)->SetDisablePlayerControls(PLAYERCONTROL_PHONE);\n\t\t\t\t\t\t\t\tTheCamera.SetWideScreenOn();\n\t\t\t\t\t\t\t\tplayerInfo->MakePlayerSafe(true);\n\t\t\t\t\t\t\t\tCAnimBlendAssociation *phonePickAssoc = CAnimManager::BlendAnimation(player->GetClump(), ASSOCGRP_STD, ANIM_STD_PHONE_IN, 4.0f);\n\t\t\t\t\t\t\t\tphonePickAssoc->SetFinishCallback(PhonePickUpCB, &m_aPhones[phoneId]);\n\t\t\t\t\t\t\t\tbPickingUpPhone = true;\n\t\t\t\t\t\t\t\tpCallBackPed = player;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase PHONE_STATE_REPEATED_MESSAGE_STARTED:\n\t\t\t\t\tif (CTimer::GetTimeInMilliseconds() - m_aPhones[phoneId].m_repeatedMessagePickupStart > 60000)\n\t\t\t\t\t\tm_aPhones[phoneId].m_nState = PHONE_STATE_REPEATED_MESSAGE_SHOWN_ONCE;\n\t\t\t\t\tbreak;\n\t\t\t\tcase PHONE_STATE_9:\n\t\t\t\t\tscratchTheCabinet = (CTimer::GetTimeInMilliseconds() / 1880) % 2 == 1;\n\t\t\t\t\tphoneRings = (CTimer::GetPreviousTimeInMilliseconds() / 1880) % 2 == 1;\n\t\t\t\t\tif (scratchTheCabinet) {\n\t\t\t\t\t\tm_aPhones[phoneId].m_pEntity->GetUp().z = (CGeneral::GetRandomNumber() % 1024) / 16000.0f + 1.0f;\n\t\t\t\t\t\tif (!phoneRings)\n\t\t\t\t\t\t    PlayOneShotScriptObject(SCRIPT_SOUND_PAYPHONE_RINGING, m_aPhones[phoneId].m_pEntity->GetPosition());\n\t\t\t\t\t} else {\n\t\t\t\t\t\tm_aPhones[phoneId].m_pEntity->GetUp().z = 1.0f;\n\t\t\t\t\t}\n\t\t\t\t\tm_aPhones[phoneId].m_pEntity->GetMatrix().UpdateRW();\n\t\t\t\t\tm_aPhones[phoneId].m_pEntity->UpdateRwFrame();\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (CVector2D(TheCamera.GetPosition() - m_aPhones[phoneId].m_vecPos).MagnitudeSqr() > sq(100.0f))\n\t\t\t\tm_aPhones[phoneId].m_visibleToCam = false;\n\t\t} else if (!((CTimer::GetFrameCounter() + m_aPhones[phoneId].m_pEntity->m_randomSeed) % 16)) {\n\t\t\tif (CVector2D(TheCamera.GetPosition() - m_aPhones[phoneId].m_vecPos).MagnitudeSqr() < sq(60.0f))\n\t\t\t\tm_aPhones[phoneId].m_visibleToCam = true;\n\t\t}\n\t}\n}\n\nint\nCPhoneInfo::FindNearestFreePhone(CVector *pos)\n{\n\tint nearestPhoneId = -1;\n\tfloat nearestPhoneDist = 60.0f;\n\n\tfor (int phoneId = 0; phoneId < m_nMax; phoneId++) {\n\n\t\tif (gPhoneInfo.m_aPhones[phoneId].m_nState == PHONE_STATE_FREE) {\n\t\t\tfloat phoneDist = (m_aPhones[phoneId].m_vecPos - *pos).Magnitude2D();\n\n\t\t\tif (phoneDist < nearestPhoneDist) {\n\t\t\t\tnearestPhoneDist = phoneDist;\n\t\t\t\tnearestPhoneId = phoneId;\n\t\t\t}\n\t\t}\n\t}\n\treturn nearestPhoneId;\n}\n\nbool\nCPhoneInfo::PhoneAtThisPosition(CVector pos)\n{\n\tfor (int phoneId = 0; phoneId < m_nMax; phoneId++) {\n\t\tif (pos.x == m_aPhones[phoneId].m_vecPos.x && pos.y == m_aPhones[phoneId].m_vecPos.y)\n\t\t\treturn true;\n\t}\n\treturn false;\n}\n\nbool\nCPhoneInfo::HasMessageBeenDisplayed(int phoneId)\n{\n\tif (bDisplayingPhoneMessage)\n\t\treturn false;\n\n\tint state = m_aPhones[phoneId].m_nState;\n\n\treturn state == PHONE_STATE_REPEATED_MESSAGE_SHOWN_ONCE ||\n\t\tstate == PHONE_STATE_ONETIME_MESSAGE_STARTED ||\n\t\tstate == PHONE_STATE_REPEATED_MESSAGE_STARTED;\n}\n\nbool\nCPhoneInfo::IsMessageBeingDisplayed(int phoneId)\n{\n\treturn pPhoneDisplayingMessages == &m_aPhones[phoneId];\n}\n\nvoid\nCPhoneInfo::Load(uint8 *buf, uint32 size)\n{\nINITSAVEBUF\n\tm_nMax = ReadSaveBuf<int32>(buf);\n\tm_nScriptPhonesMax = ReadSaveBuf<int32>(buf);\n\tfor (int i = 0; i < NUMPHONES; i++) {\n\t\tm_aPhones[i] = ReadSaveBuf<CPhone>(buf);\n\t\t// It's saved as building pool index in save file, convert it to true entity\n\t\tif (m_aPhones[i].m_pEntity) {\n\t\t\tm_aPhones[i].m_pEntity = CPools::GetBuildingPool()->GetSlot((uintptr)m_aPhones[i].m_pEntity - 1);\n\t\t}\n\t}\nVALIDATESAVEBUF(size)\n}\n\nvoid\nCPhoneInfo::SetPhoneMessage_JustOnce(int phoneId, wchar *msg1, wchar *msg2, wchar *msg3, wchar *msg4, wchar *msg5, wchar *msg6)\n{\n\t// If there is at least one message, it should be msg1.\n\tif (msg1) {\n\t\tm_aPhones[phoneId].m_apMessages[0] = msg1;\n\t\tm_aPhones[phoneId].m_apMessages[1] = msg2;\n\t\tm_aPhones[phoneId].m_apMessages[2] = msg3;\n\t\tm_aPhones[phoneId].m_apMessages[3] = msg4;\n\t\tm_aPhones[phoneId].m_apMessages[4] = msg5;\n\t\tm_aPhones[phoneId].m_apMessages[5] = msg6;\n\t\tm_aPhones[phoneId].m_nState = PHONE_STATE_ONETIME_MESSAGE_SET;\n\t} else {\n\t\tm_aPhones[phoneId].m_nState = PHONE_STATE_MESSAGE_REMOVED;\n\t}\n}\n\nvoid\nCPhoneInfo::SetPhoneMessage_Repeatedly(int phoneId, wchar *msg1, wchar *msg2, wchar *msg3, wchar *msg4, wchar *msg5, wchar *msg6)\n{\n\t// If there is at least one message, it should be msg1.\n\tif (msg1) {\n\t\tm_aPhones[phoneId].m_apMessages[0] = msg1;\n\t\tm_aPhones[phoneId].m_apMessages[1] = msg2;\n\t\tm_aPhones[phoneId].m_apMessages[2] = msg3;\n\t\tm_aPhones[phoneId].m_apMessages[3] = msg4;\n\t\tm_aPhones[phoneId].m_apMessages[4] = msg5;\n\t\tm_aPhones[phoneId].m_apMessages[5] = msg6;\n\t\tm_aPhones[phoneId].m_nState = PHONE_STATE_REPEATED_MESSAGE_SET;\n\t} else {\n\t\tm_aPhones[phoneId].m_nState = PHONE_STATE_MESSAGE_REMOVED;\n\t}\n}\n\nint\nCPhoneInfo::GrabPhone(float xPos, float yPos)\n{\n\t// \"Grab\" doesn't mean picking up the phone, it means allocating some particular phone to\n\t// whoever called the 024A opcode first with the position parameters closest to phone.\n\t// Same phone won't be available on next run of this function.\n\n\tint nearestPhoneId = -1;\n\tCVector pos(xPos, yPos, 0.0f);\n\tfloat nearestPhoneDist = 100.0f;\n\n\tfor (int phoneId = m_nScriptPhonesMax; phoneId < m_nMax; phoneId++) {\n\t\tfloat phoneDistance = (m_aPhones[phoneId].m_vecPos - pos).Magnitude2D();\n\t\tif (phoneDistance < nearestPhoneDist) {\n\t\t\tnearestPhoneDist = phoneDistance;\n\t\t\tnearestPhoneId = phoneId;\n\t\t}\n\t}\n\tm_aPhones[nearestPhoneId].m_nState = PHONE_STATE_MESSAGE_REMOVED;\n\n\tCPhone oldFirstPhone = m_aPhones[m_nScriptPhonesMax];\n\tm_aPhones[m_nScriptPhonesMax] = m_aPhones[nearestPhoneId];\n\tm_aPhones[nearestPhoneId] = oldFirstPhone;\n\tm_nScriptPhonesMax++;\n\treturn m_nScriptPhonesMax - 1;\n}\n\nvoid\nCPhoneInfo::Initialise(void)\n{\n\tCBuildingPool *pool = CPools::GetBuildingPool();\n\tpCallBackPed = nil;\n\tbDisplayingPhoneMessage = false;\n\tbPickingUpPhone = false;\n\tpPhoneDisplayingMessages = nil;\n\tm_nMax = 0;\n\tm_nScriptPhonesMax = 0;\n\tfor (int i = pool->GetSize() - 1; i >= 0; i--) {\n\t\tCBuilding *building = pool->GetSlot(i);\n\t\tif (building) {\n\t\t\tif (building->GetModelIndex() == MI_PHONEBOOTH1) {\n\t\t\t\tassert(m_nMax < ARRAY_SIZE(m_aPhones) && \"NUMPHONES should be increased\");\n\t\t\t\tCPhone *maxPhone = &m_aPhones[m_nMax];\n\t\t\t\tmaxPhone->m_nState = PHONE_STATE_FREE;\n\t\t\t\tmaxPhone->m_vecPos = building->GetPosition();\n\t\t\t\tmaxPhone->m_pEntity = building;\n\t\t\t\tm_nMax++;\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nCPhoneInfo::Save(uint8 *buf, uint32 *size)\n{\n\t*size = sizeof(CPhoneInfo);\nINITSAVEBUF\n\tWriteSaveBuf(buf, m_nMax);\n\tWriteSaveBuf(buf, m_nScriptPhonesMax);\n\tfor(int phoneId = 0; phoneId < NUMPHONES; phoneId++) {\n\t\tCPhone* phone = WriteSaveBuf(buf, m_aPhones[phoneId]);\n\n\t\t// Convert entity pointer to building pool index while saving\n\t\tif (phone->m_pEntity) {\n\t\t\tphone->m_pEntity = (CEntity*) (CPools::GetBuildingPool()->GetJustIndex_NoFreeAssert((CBuilding*)phone->m_pEntity) + 1);\n\t\t}\n\t}\nVALIDATESAVEBUF(*size)\n}\n\nvoid\nCPhoneInfo::Shutdown(void)\n{\n\tm_nMax = 0;\n\tm_nScriptPhonesMax = 0;\n}\n\nvoid\nPhonePutDownCB(CAnimBlendAssociation *assoc, void *arg)\n{\n\tassoc->flags |= ASSOC_DELETEFADEDOUT;\n\tassoc->blendDelta = -1000.0f;\n\tCPad::GetPad(0)->SetEnablePlayerControls(PLAYERCONTROL_PHONE);\n\tCPed *ped = (CPed*)arg;\n\n\tif (assoc->blendAmount > 0.5f)\n\t\tped->bUpdateAnimHeading = true;\n\n\tif (ped->m_nPedState == PED_MAKE_CALL)\n\t\tped->SetPedState(PED_IDLE);\n}\n\nvoid\nPhonePickUpCB(CAnimBlendAssociation *assoc, void *arg)\n{\n\tCPhone *phone = (CPhone*)arg;\n\tint messagesDisplayTime = 0;\n\n\tfor(int i=0; i < 6; i++) {\n\t\twchar *msg = phone->m_apMessages[i];\n\t\tif (msg) {\n\t\t\tCMessages::AddMessage(msg, 3000, 0);\n\t\t\tmessagesDisplayTime += 3000;\n\t\t}\n\t}\n\n\tCPhoneInfo::bPickingUpPhone = false;\n\tCPhoneInfo::bDisplayingPhoneMessage = true;\n\tCPhoneInfo::pPhoneDisplayingMessages = phone;\n\tCPhoneInfo::PhoneEnableControlsTimer = CTimer::GetTimeInMilliseconds() + messagesDisplayTime;\n\n\tif (phone->m_nState == PHONE_STATE_ONETIME_MESSAGE_SET) {\n\t\tphone->m_nState = PHONE_STATE_ONETIME_MESSAGE_STARTED;\n\t} else {\n\t\tphone->m_nState = PHONE_STATE_REPEATED_MESSAGE_STARTED;\n\t\tphone->m_repeatedMessagePickupStart = CTimer::GetTimeInMilliseconds();\n\t}\n\n\tCPed *ped = CPhoneInfo::pCallBackPed;\n\tped->m_nMoveState = PEDMOVE_STILL;\n\tCAnimManager::BlendAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_IDLE, 8.0f);\n\n\tif (assoc->blendAmount > 0.5f && ped)\n\t\tCAnimManager::BlendAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_PHONE_TALK, 8.0f);\n\n\tCPhoneInfo::pCallBackPed = nil;\n}\n"
  },
  {
    "path": "src/control/Phones.h",
    "content": "#pragma once\n\n#include \"Physical.h\"\n\nclass CPed;\nclass CAnimBlendAssociation;\n\nenum PhoneState {\n\tPHONE_STATE_FREE,\n\tPHONE_STATE_REPORTING_CRIME, // CCivilianPed::ProcessControl sets it but unused\n\tPHONE_STATE_2,\n\tPHONE_STATE_MESSAGE_REMOVED,\n\tPHONE_STATE_ONETIME_MESSAGE_SET,\n\tPHONE_STATE_REPEATED_MESSAGE_SET,\n\tPHONE_STATE_REPEATED_MESSAGE_SHOWN_ONCE,\n\tPHONE_STATE_ONETIME_MESSAGE_STARTED,\n\tPHONE_STATE_REPEATED_MESSAGE_STARTED,\n\tPHONE_STATE_9 // just rings, picking being handled via script. most of the time game uses this\n};\n\nclass CPhone\n{\npublic:\n\tCVector m_vecPos;\n\twchar *m_apMessages[6];\n\tuint32 m_repeatedMessagePickupStart;\n\tCEntity *m_pEntity; // stored as building pool index in save files\n\tPhoneState m_nState;\n\tbool m_visibleToCam;\n\n\tCPhone() { }\n\t~CPhone() { }\n};\n\nVALIDATE_SIZE(CPhone, 0x34);\n\nclass CPhoneInfo {\npublic:\n\tstatic bool bDisplayingPhoneMessage;\n\tstatic uint32 PhoneEnableControlsTimer;\n\tstatic CPhone *pPhoneDisplayingMessages;\n\tstatic bool bPickingUpPhone;\n\tstatic CPed *pCallBackPed;\n\n\tint32 m_nMax;\n\tint32 m_nScriptPhonesMax;\n\tCPhone m_aPhones[NUMPHONES];\n\n\tCPhoneInfo() { }\n\t~CPhoneInfo() { }\n\n\tint FindNearestFreePhone(CVector*);\n\tbool PhoneAtThisPosition(CVector);\n\tbool HasMessageBeenDisplayed(int);\n\tbool IsMessageBeingDisplayed(int);\n\tvoid Load(uint8 *buf, uint32 size);\n\tvoid Save(uint8 *buf, uint32 *size);\n\tvoid SetPhoneMessage_JustOnce(int phoneId, wchar *msg1, wchar *msg2, wchar *msg3, wchar *msg4, wchar *msg5, wchar *msg6);\n\tvoid SetPhoneMessage_Repeatedly(int phoneId, wchar *msg1, wchar *msg2, wchar *msg3, wchar *msg4, wchar *msg5, wchar *msg6);\n\tint GrabPhone(float, float);\n\tvoid Initialise(void);\n\tvoid Shutdown(void);\n\tvoid Update(void);\n};\n\nextern CPhoneInfo gPhoneInfo;\n\nvoid PhonePutDownCB(CAnimBlendAssociation *assoc, void *arg);\nvoid PhonePickUpCB(CAnimBlendAssociation *assoc, void *arg);"
  },
  {
    "path": "src/control/Pickups.cpp",
    "content": "#include \"common.h\"\n\n#include \"main.h\"\n\n#include \"Camera.h\"\n#include \"Coronas.h\"\n#include \"Darkel.h\"\n#include \"Entity.h\"\n#include \"Explosion.h\"\n#include \"Font.h\"\n#include \"Garages.h\"\n#include \"General.h\"\n#include \"ModelIndices.h\"\n#include \"Object.h\"\n#include \"Pad.h\"\n#include \"Pickups.h\"\n#include \"PlayerPed.h\"\n#include \"Wanted.h\"\n#include \"DMAudio.h\"\n#include \"Fire.h\"\n#include \"PointLights.h\"\n#include \"Pools.h\"\n#ifdef FIX_BUGS\n#include \"Replay.h\"\n#endif\n#include \"Script.h\"\n#include \"Shadows.h\"\n#include \"SpecialFX.h\"\n#include \"Sprite.h\"\n#include \"Timer.h\"\n#include \"WaterLevel.h\"\n#include \"World.h\"\n#include \"Hud.h\"\n#include \"Messages.h\"\n#include \"Streaming.h\"\n\nCPickup CPickups::aPickUps[NUMPICKUPS];\nint16 CPickups::NumMessages;\nint32 CPickups::aPickUpsCollected[NUMCOLLECTEDPICKUPS];\nint16 CPickups::CollectedPickUpIndex;\n\nint32 CPickups::PlayerOnWeaponPickup;\nint32 CollectPickupBuffer;\n\n// unused\nbool CPickups::bPickUpcamActivated;\nCVehicle *CPickups::pPlayerVehicle;\nCVector CPickups::StaticCamCoors;\nuint32 CPickups::StaticCamStartTime;\n\ntPickupMessage CPickups::aMessages[NUMPICKUPMESSAGES];\n\nuint16 AmmoForWeapon[WEAPONTYPE_TOTALWEAPONS + 1] = { 0,  1,  1,  1,   1,   1,   1,   1,   1,   1,  1,  1, 8,   8,   8,    8, 8,   68, 24,\n\t\t\t\t\t\t\t\t\t\t\t\t\t 32, 28, 20, 200, 120, 120, 120, 120, 120, 40, 28, 8, 300, 200, 1000, 1, 400, 36, 0 };\n\nuint16 AmmoForWeapon_OnStreet[WEAPONTYPE_TOTALWEAPONS + 1] = { 0,  1,  1,  1,   1,  1,  1,  1,  1,  1,  1,  1, 4,   4,   4,   4, 4,   34, 12,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  16, 14, 10, 100, 60, 60, 60, 60, 60, 20, 14, 4, 150, 100, 500, 1, 400, 36, 0 };\n\nuint16 CostOfWeapon[WEAPONTYPE_TOTALWEAPONS + 3] = { 0,     10,    10,   10,   10,   10,    10,   10,    10,  10,  10,  10,   1000, 1000,\n\t\t\t\t\t\t\t\t\t\t\t\t\t1000,  500,   8000, 250,  400,  1200,  1250, 1250,  800, 800, 650, 1200, 5000, 400,\n\t\t\t\t\t\t\t\t\t\t\t\t\t10000, 10000, 8000, 8000, 8000, 10000, 1000, 11000, 500, 20,  10,  0 };\n\nstruct\n{\n\tuint8 r,g,b;\n\tfloat unk;\n} aPickupColors[] = {\n\t{ 128, 128, 128, 1.0f },\n\t{ 128, 128, 128, 1.0f },\n\t{ 97, 194, 247, 1.0f },\n\t{ 97, 194, 247, 1.0f },\n\t{ 97, 194, 247, 1.0f },\n\t{ 97, 194, 247, 1.0f },\n\t{ 97, 194, 247, 1.0f },\n\t{ 97, 194, 247, 1.0f },\n\t{ 97, 194, 247, 1.0f },\n\t{ 97, 194, 247, 1.0f },\n\t{ 97, 194, 247, 1.0f },\n\t{ 97, 194, 247, 1.0f },\n\t{ 27, 89, 130, 1.0f },\n\t{ 27, 89, 130, 1.0f },\n\t{ 27, 89, 130, 1.0f },\n\t{ 27, 89, 130, 1.0f },\n\t{ 27, 89, 130, 1.0f },\n\t{ 149, 194, 24, 1.0f },\n\t{ 149, 194, 24, 1.0f },\n\t{ 45, 155, 90, 1.0f },\n\t{ 45, 155, 90, 1.0f },\n\t{ 45, 155, 90, 1.0f },\n\t{ 255, 227, 79, 1.0f },\n\t{ 255, 227, 79, 1.0f },\n\t{ 255, 227, 79, 1.0f },\n\t{ 255, 227, 79, 1.0f },\n\t{ 254, 137, 0, 1.0f },\n\t{ 254, 137, 0, 1.0f },\n\t{ 249, 131, 215, 1.0f },\n\t{ 249, 131, 215, 1.0f },\n\t{ 164, 40, 178, 1.0f },\n\t{ 164, 40, 178, 1.0f },\n\t{ 164, 40, 178, 1.0f },\n\t{ 164, 40, 178, 1.0f },\n\t{ 69, 69, 69, 1.0f },\n\t{ 69, 69, 69, 1.0f },\n\t{ 69, 69, 69, 1.0f },\n\t{ 255, 100, 100, 1.0f },\n\t{ 128, 255, 128, 1.0f },\n\t{ 100, 100, 255, 1.0f },\n\t{ 255, 255, 100, 1.0f },\n\t{ 255, 100, 100, 1.0f },\n\t{ 100, 255, 100, 1.0f },\n\t{ 255, 255, 255, 1.0f }\n};\n\n\nvoid\nModifyStringLabelForControlSetting(char *str)\n{\n\tint len = (int)strlen(str);\n\tif (len <= 2)\n\t\treturn;\n\n\tif (str[len - 2] != '_')\n\t\treturn;\n\n\tswitch (CPad::GetPad(0)->Mode) {\n\t\tcase 0:\n\t\tcase 1:\n\t\t\tstr[len - 1] = 'L';\n\t\t\tbreak;\n\t\tcase 2:\n\t\t\tstr[len - 1] = 'T';\n\t\t\tbreak;\n\t\tcase 3:\n\t\t\tstr[len - 1] = 'C';\n\t\t\tbreak;\n\t\tdefault:\n\t\t\treturn;\n\t}\n}\n\nvoid\nCPickup::ExtractAmmoFromPickup(CPlayerPed *player)\n{\n\teWeaponType weaponType = CPickups::WeaponForModel(m_pObject->GetModelIndex());\n\t\n\tif (m_eType == PICKUP_IN_SHOP || !CWeaponInfo::IsWeaponSlotAmmoMergeable(CWeaponInfo::GetWeaponInfo(weaponType)->m_nWeaponSlot))\n\t\treturn;\n\n\tuint32 ammo = m_nQuantity;\n\tif (ammo == 0) {\n\t\tif (!m_bWasAmmoCollected)\n\t\t\tammo = AmmoForWeapon_OnStreet[weaponType];\n\t\telse\n\t\t\tgoto removeAmmo;\n\t}\n\tplayer->GrantAmmo(weaponType, ammo);\n\tDMAudio.PlayOneShot(player->m_audioEntityId, SOUND_WEAPON_RELOAD, weaponType); // BUG? weapon type as volume, wtf?\nremoveAmmo:\n\tm_nQuantity = 0;\n\tm_bWasAmmoCollected = true;\n}\n\nvoid\nCPickup::Remove()\n{\n\tGetRidOfObjects();\n\tm_bRemoved = true;\n\tm_eType = PICKUP_NONE;\n}\n\nCObject *\nCPickup::GiveUsAPickUpObject(CObject **ppObject, CObject **ppExtraObject, int32 handle, int32 extraHandle)\n{\n\tCObject *&object = *ppObject;\n\tCObject *&extraObject = *ppExtraObject;\n\n\tobject = extraObject = nil;\n\n\tint32 modelId = -1;\n\tif (CModelInfo::GetModelInfo(m_eModelIndex)->GetModelType() == MITYPE_WEAPON) {\n\t\tCWeaponInfo *weaponInfo = CWeaponInfo::GetWeaponInfo(((CWeaponModelInfo*)CModelInfo::GetModelInfo(m_eModelIndex))->GetWeaponInfo());\n\t\tmodelId = weaponInfo->m_nModelId;\n\t\tif (modelId == m_eModelIndex)\n\t\t\tmodelId = weaponInfo->m_nModel2Id;\n\t}\n\n\tif (handle >= 0) {\n\t\tCPools::MakeSureSlotInObjectPoolIsEmpty(handle);\n\t\tif (extraHandle >= 0)\n\t\t\tCPools::MakeSureSlotInObjectPoolIsEmpty(extraHandle);\n\t\tif (object == nil)\n\t\t\tobject = new(handle) CObject(m_eModelIndex, false);\n\n\t\tif (extraHandle >= 0 && modelId != -1 && extraObject == nil)\n\t\t\textraObject = new(extraHandle) CObject(modelId, false);\n\t} else {\n\t\tobject = new CObject(m_eModelIndex, false);\n\t\tif (modelId != -1)\n\t\t\textraObject = new CObject(modelId, false);\n\t}\n\n\tif (object == nil) return nil;\n\tobject->ObjectCreatedBy = MISSION_OBJECT;\n\tobject->SetPosition(m_vecPos);\n\tobject->SetOrientation(0.0f, 0.0f, -HALFPI);\n\tobject->GetMatrix().UpdateRW();\n\tobject->UpdateRwFrame();\n\n\tobject->bAffectedByGravity = false;\n\tobject->bExplosionProof = true;\n\tobject->bUsesCollision = false;\n\tobject->bIsPickup = true;\n\tobject->bAmmoCollected = m_bWasAmmoCollected;\n\tobject->bHasPreRenderEffects = true;\n\n\tif (extraObject) {\n\t\textraObject->ObjectCreatedBy = MISSION_OBJECT;\n\t\textraObject->SetPosition(m_vecPos);\n\t\textraObject->SetOrientation(0.0f, 0.0f, -HALFPI);\n\t\textraObject->GetMatrix().UpdateRW();\n\t\textraObject->UpdateRwFrame();\n\n\t\textraObject->bAffectedByGravity = false;\n\t\textraObject->bExplosionProof = true;\n\t\textraObject->bUsesCollision = false;\n\t\textraObject->bIsPickup = true;\n\t\textraObject->bAmmoCollected = true;\n\t\textraObject->bHasPreRenderEffects = true;\n\t\textraObject->m_nBonusValue = 0;\n\t\textraObject->bPickupObjWithMessage = false;\n\t\textraObject->bOutOfStock = false;\n\t}\n\n\tobject->m_nBonusValue = (m_eModelIndex == MI_PICKUP_BONUS || m_eModelIndex == MI_PICKUP_CLOTHES) ? m_nQuantity : 0;\n\n\tswitch (m_eType)\n\t{\n\tcase PICKUP_IN_SHOP:\n\t\tobject->bPickupObjWithMessage = true;\n\t\tobject->bOutOfStock = false;\n\t\tif (m_eModelIndex == MI_PICKUP_HEALTH || m_eModelIndex == MI_PICKUP_ADRENALINE)\n\t\t\tobject->m_nCostValue = 0;\n\t\telse\n\t\t\tobject->m_nCostValue = CostOfWeapon[CPickups::WeaponForModel(m_eModelIndex)];\n\t\tbreak;\n\tcase PICKUP_ON_STREET:\n\tcase PICKUP_ONCE:\n\tcase PICKUP_ONCE_TIMEOUT:\n\tcase PICKUP_COLLECTABLE1:\n\tcase PICKUP_MONEY:\n\tcase PICKUP_MINE_INACTIVE:\n\tcase PICKUP_MINE_ARMED:\n\tcase PICKUP_NAUTICAL_MINE_INACTIVE:\n\tcase PICKUP_NAUTICAL_MINE_ARMED:\n\tcase PICKUP_FLOATINGPACKAGE:\n\tcase PICKUP_ON_STREET_SLOW:\n\t\tobject->bPickupObjWithMessage = false;\n\t\tobject->bOutOfStock = false;\n\t\tbreak;\n\tcase PICKUP_IN_SHOP_OUT_OF_STOCK:\n\t\tobject->bPickupObjWithMessage = false;\n\t\tobject->bOutOfStock = true;\n\t\tobject->bRenderScorched = true;\n\t\tbreak;\n\tcase PICKUP_FLOATINGPACKAGE_FLOATING:\n\tdefault:\n\t\tbreak;\n\t}\n\treturn object;\n}\n\nbool\nCPickup::CanBePickedUp(CPlayerPed *player, int playerId)\n{\n\tassert(m_pObject != nil);\n\tbool cannotBePickedUp =\n\t\t(m_pObject->GetModelIndex() == MI_PICKUP_BODYARMOUR && player->m_fArmour > CWorld::Players[playerId].m_nMaxArmour - 0.2f)\n\t\t|| (m_pObject->GetModelIndex() == MI_PICKUP_HEALTH && player->m_fHealth > CWorld::Players[playerId].m_nMaxHealth - 0.2f)\n\t\t|| (m_pObject->GetModelIndex() == MI_PICKUP_BRIBE && player->m_pWanted->GetWantedLevel() == 0)\n\t\t|| (m_pObject->GetModelIndex() == MI_PICKUP_KILLFRENZY && (CTheScripts::IsPlayerOnAMission() || CDarkel::FrenzyOnGoing() || !CGame::nastyGame))\n\t\t|| (m_eType == PICKUP_ASSET_REVENUE && m_fRevenue < 10.0f);\n\treturn !cannotBePickedUp;\n}\n\nbool\nCPickup::Update(CPlayerPed *player, CVehicle *vehicle, int playerId)\n{\n\tbool result = false;\n\tfloat waterLevel;\n\n\tif (m_pObject) {\n\t\tm_pObject->GetMatrix().GetPosition() = m_vecPos;\n\t\tif (m_pExtraObject)\n\t\t\tm_pExtraObject->GetMatrix().GetPosition() = m_vecPos;\n\t}\n\tif (m_eType == PICKUP_ASSET_REVENUE) {\n\t\tuint32 timePassed = CTimer::GetTimeInMilliseconds() - m_nTimer;\n\t\tm_nTimer = CTimer::GetTimeInMilliseconds();\n\n\t\tif (Distance(FindPlayerCoors(), m_vecPos) > 10.0f)\n\t\t\tm_fRevenue += float(timePassed * m_nMoneySpeed) / SQR(1200.0f);\n\n\t\tm_fRevenue = Min(m_fRevenue, m_nQuantity);\n\n\t\tm_pObject->m_nCostValue = m_fRevenue < 10 ? 0 : m_fRevenue;\n\t}\n\n\tif (m_bRemoved) {\n\t\tif (CTimer::GetTimeInMilliseconds() > m_nTimer) {\n\t\t\t// respawn pickup if we're far enough\n\t\t\tfloat dist = (FindPlayerCoors().x - m_vecPos.x) * (FindPlayerCoors().x - m_vecPos.x) + (FindPlayerCoors().y - m_vecPos.y) * (FindPlayerCoors().y - m_vecPos.y);\n\t\t\tif (dist > 100.0f || m_eType == PICKUP_IN_SHOP && dist > 2.4f) {\n\t\t\t\tm_pObject = GiveUsAPickUpObject(&m_pObject, &m_pExtraObject, -1, -1);\n\t\t\t\tif (m_pObject) {\n\t\t\t\t\tCWorld::Add(m_pObject);\n\t\t\t\t\tm_bRemoved = false;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\tif (!m_pObject) {\n\t\tGiveUsAPickUpObject(&m_pObject, &m_pExtraObject, -1, -1);\n\t\tif (m_pObject)\n\t\t\tCWorld::Add(m_pObject);\n\t\tif (m_pExtraObject)\n\t\t\tCWorld::Add(m_pExtraObject);\n\t}\n\n\tif (!m_pObject) return false;\n\n\tif (!IsMine()) {\n\t\t// let's check if we touched the pickup\n\t\tbool isPickupTouched = false;\n\t\tif (m_pObject->GetModelIndex() == MI_PICKUP_BRIBE) {\n\t\t\tif (vehicle != nil) {\n\t\t\t\tif (vehicle->IsSphereTouchingVehicle(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z, 2.0f))\n\t\t\t\t\tisPickupTouched = true;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tif (Abs(player->GetPosition().z - m_pObject->GetPosition().z) < 2.0f) {\n\t\t\t\t\tif ((player->GetPosition().x - m_pObject->GetPosition().x) * (player->GetPosition().x - m_pObject->GetPosition().x) +\n\t\t\t\t\t\t(player->GetPosition().y - m_pObject->GetPosition().y) * (player->GetPosition().y - m_pObject->GetPosition().y) < 1.8f)\n\t\t\t\t\t\tisPickupTouched = true;\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (m_pObject->GetModelIndex() == MI_PICKUP_CAMERA) {\n\t\t\tif (vehicle != nil && vehicle->IsSphereTouchingVehicle(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z, 2.0f)) {\n\t\t\t\tisPickupTouched = true;\n\t\t\t}\n\t\t} else if (vehicle == nil) {\n\t\t\tif (Abs(player->GetPosition().z - m_pObject->GetPosition().z) < 2.0f) {\n\t\t\t\tif ((player->GetPosition().x - m_pObject->GetPosition().x) * (player->GetPosition().x - m_pObject->GetPosition().x) +\n\t\t\t\t\t(player->GetPosition().y - m_pObject->GetPosition().y) * (player->GetPosition().y - m_pObject->GetPosition().y) < 1.8f)\n\t\t\t\t\tisPickupTouched = true;\n\t\t\t}\n\t\t}\n\n\t\tif (isPickupTouched) {\n\t\t\teWeaponType weaponType = CPickups::WeaponForModel(m_pObject->GetModelIndex());\n\t\t\tif (weaponType < WEAPONTYPE_TOTALWEAPONS && CDarkel::FrenzyOnGoing()) {\n\t\t\t\tisPickupTouched = false;\n\t\t\t\tm_bWasControlMessageShown = false;\n\t\t\t} else if (weaponType < WEAPONTYPE_TOTALWEAPONS && weaponType != WEAPONTYPE_UNARMED) {\n\t\t\t\tuint32 slot = CWeaponInfo::GetWeaponInfo(weaponType)->m_nWeaponSlot;\n\t\t\t\teWeaponType plrWeaponSlot = FindPlayerPed()->GetWeapon(slot).m_eWeaponType;\n\t\t\t\tif (plrWeaponSlot != weaponType) {\n\t\t\t\t\tif (CStreaming::ms_aInfoForModel[m_pObject->GetModelIndex()].m_loadState == STREAMSTATE_LOADED) {\n\t\t\t\t\t\tif (plrWeaponSlot == WEAPONTYPE_UNARMED || (FindPlayerPed()->GetWeapon(slot).m_nAmmoTotal == 0 && !CWeaponInfo::IsWeaponSlotAmmoMergeable(slot))) {\n\t\t\t\t\t\t\tif (CTimer::GetTimeInMilliseconds() - FindPlayerPed()->m_nPadDownPressedInMilliseconds < 1500) {\n\t\t\t\t\t\t\t\tCPickups::PlayerOnWeaponPickup = 6;\n\t\t\t\t\t\t\t\tisPickupTouched = false;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tCPickups::PlayerOnWeaponPickup = 6;\n\t\t\t\t\t\t\tif (CWeaponInfo::IsWeaponSlotAmmoMergeable(slot)) {\n\t\t\t\t\t\t\t\tif (m_eType == PICKUP_ONCE_TIMEOUT || m_eType == PICKUP_ONCE || m_eType == PICKUP_ON_STREET) {\n\t\t\t\t\t\t\t\t\tExtractAmmoFromPickup(player);\n\t\t\t\t\t\t\t\t\tFindPlayerPed()->GetWeapon(slot).Reload();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (!m_bWasControlMessageShown) {\n\t\t\t\t\t\t\t\tswitch (CPad::GetPad(0)->Mode)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tcase 0:\n\t\t\t\t\t\t\t\tcase 1:\n\t\t\t\t\t\t\t\t\tCHud::SetHelpMessage(TheText.Get(\"PU_CF1\"), false);\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase 2:\n\t\t\t\t\t\t\t\t\tCHud::SetHelpMessage(TheText.Get(\"PU_CF3\"), false);\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase 3:\n\t\t\t\t\t\t\t\t\tCHud::SetHelpMessage(TheText.Get(\"PU_CF4\"), false);\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tm_bWasControlMessageShown = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (CollectPickupBuffer == 0)\n\t\t\t\t\t\t\t\tisPickupTouched = false;\n\t\t\t\t\t\t\tif (CTimer::GetTimeInMilliseconds() - FindPlayerPed()->m_nPadDownPressedInMilliseconds < 1500)\n\t\t\t\t\t\t\t\tisPickupTouched = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else\n\t\t\t\t\t\tisPickupTouched = false;\n\t\t\t\t}\n\t\t\t}\n\t\t} else\n\t\t\tm_bWasControlMessageShown = false;\n\n\t\t// if we didn't then we've got nothing to do\n\t\tif (isPickupTouched && CanBePickedUp(player, playerId)) {\n\t\t\tif (m_pObject->GetModelIndex() != MI_PICKUP_PROPERTY && m_pObject->GetModelIndex() != MI_PICKUP_PROPERTY_FORSALE)\n\t\t\t\tCPad::GetPad(0)->StartShake(120, 100);\n\n\t\t\teWeaponType weaponType = CPickups::WeaponForModel(m_pObject->GetModelIndex());\n\t\t\tswitch (m_eType)\n\t\t\t{\n\t\t\tcase PICKUP_IN_SHOP:\n\t\t\t\tif (CWorld::Players[playerId].m_nMoney < CostOfWeapon[weaponType])\n\t\t\t\t\tCGarages::TriggerMessage(\"PU_MONY\", -1, 6000, -1);\n\t\t\t\telse {\n\t\t\t\t\tCWorld::Players[playerId].m_nMoney -= CostOfWeapon[weaponType];\n\t\t\t\t\tif (!CPickups::GivePlayerGoodiesWithPickUpMI(m_pObject->GetModelIndex(), playerId)) {\n\t\t\t\t\t\tif (!player->DoesPlayerWantNewWeapon(weaponType, false))\n\t\t\t\t\t\t\tbreak; \n\t\t\t\t\t\tplayer->GiveWeapon(weaponType, AmmoForWeapon[weaponType]);\n\t\t\t\t\t\tplayer->m_nSelectedWepSlot = player->GetWeaponSlot(weaponType);\n\t\t\t\t\t\tDMAudio.PlayFrontEndSound(SOUND_PICKUP_WEAPON_BOUGHT, m_pObject->GetModelIndex() - MI_GRENADE);\n\t\t\t\t\t}\n\t\t\t\t\tresult = true;\n\t\t\t\t\tRemove();\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase PICKUP_ON_STREET:\n\t\t\tcase PICKUP_ON_STREET_SLOW:\n\t\t\t\tif (!CPickups::GivePlayerGoodiesWithPickUpMI(m_pObject->GetModelIndex(), playerId)) {\n\t\t\t\t\tif (!player->DoesPlayerWantNewWeapon(weaponType, false))\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tif (weaponType != WEAPONTYPE_UNARMED) {\n\t\t\t\t\t\tplayer->GiveWeapon(weaponType, m_nQuantity != 0 ? m_nQuantity : (m_bWasAmmoCollected ? 0 : AmmoForWeapon_OnStreet[weaponType]), true);\n\n\t\t\t\t\t\tif (player->m_nSelectedWepSlot == player->GetWeaponSlot(WEAPONTYPE_UNARMED)) \n\t\t\t\t\t\t\tplayer->m_nSelectedWepSlot = player->GetWeaponSlot(weaponType);\n\n\t\t\t\t\t\tDMAudio.PlayFrontEndSound(SOUND_PICKUP_WEAPON, m_pObject->GetModelIndex() - MI_GRENADE);\n\t\t\t\t\t} else if (m_pObject->GetModelIndex() == MI_PICKUP_CAMERA && vehicle != nil) {\n\t\t\t\t\t\tDMAudio.PlayFrontEndSound(SOUND_PICKUP_BONUS, 0);\n\t\t\t\t\t\tCPickups::bPickUpcamActivated = true;\n\t\t\t\t\t\tCPickups::pPlayerVehicle = FindPlayerVehicle();\n\t\t\t\t\t\tCPickups::StaticCamCoors = m_pObject->GetPosition();\n\t\t\t\t\t\tCPickups::StaticCamStartTime = CTimer::GetTimeInMilliseconds();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (m_eType == PICKUP_ON_STREET)\n\t\t\t\t\tm_nTimer = CTimer::GetTimeInMilliseconds() + 30000;\n\t\t\t\telse if (m_eType == PICKUP_ON_STREET_SLOW) {\n\t\t\t\t\tif (MI_PICKUP_BRIBE == m_pObject->GetModelIndex())\n\t\t\t\t\t\tm_nTimer = CTimer::GetTimeInMilliseconds() + 300000;\n\t\t\t\t\telse\n\t\t\t\t\t\tm_nTimer = CTimer::GetTimeInMilliseconds() + 720000;\n\t\t\t\t}\n\n\t\t\t\tresult = true;\n\t\t\t\tGetRidOfObjects();\n\t\t\t\tm_bRemoved = true;\n\t\t\t\tbreak;\n\t\t\tcase PICKUP_ONCE:\n\t\t\tcase PICKUP_ONCE_TIMEOUT:\n\t\t\tcase PICKUP_ONCE_TIMEOUT_SLOW:\n\t\t\t\tif (!CPickups::GivePlayerGoodiesWithPickUpMI(m_pObject->GetModelIndex(), playerId)) {\n\t\t\t\t\tif (!player->DoesPlayerWantNewWeapon(weaponType, false)) {\n\t\t\t\t\t\tExtractAmmoFromPickup(player);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (weaponType != WEAPONTYPE_UNARMED) {\n\t\t\t\t\t\tplayer->GiveWeapon(weaponType, m_nQuantity != 0 ? m_nQuantity : (m_bWasAmmoCollected ? 0 : AmmoForWeapon[weaponType]), true);\n\t\t\t\t\t\tif (player->m_nSelectedWepSlot == player->GetWeaponSlot(WEAPONTYPE_UNARMED))\n\t\t\t\t\t\t\tplayer->m_nSelectedWepSlot = player->GetWeaponSlot(weaponType);\n\t\t\t\t\t}\n\t\t\t\t\tif (MI_PICKUP_SAVEGAME != m_pObject->GetModelIndex())\n\t\t\t\t\t\tDMAudio.PlayFrontEndSound(SOUND_PICKUP_WEAPON, m_pObject->GetModelIndex() - MI_GRENADE);\n\t\t\t\t}\n\t\t\t\tresult = true;\n\t\t\t\tRemove();\n\t\t\t\tbreak;\n\t\t\tcase PICKUP_COLLECTABLE1:\n\t\t\t\tCWorld::Players[playerId].m_nCollectedPackages++;\n\t\t\t\tCWorld::Players[playerId].m_nMoney += 100;\n\n\t\t\t\tif (CWorld::Players[playerId].m_nCollectedPackages == CWorld::Players[playerId].m_nTotalPackages) {\n\t\t\t\t\tprintf(\"All collectables have been picked up\\n\");\n\t\t\t\t\tCGarages::TriggerMessage(\"CO_ALL\", -1, 5000, -1);\n\t\t\t\t\tCWorld::Players[CWorld::PlayerInFocus].m_nMoney += 100000;\n\t\t\t\t} else\n\t\t\t\t\tCGarages::TriggerMessage(\"CO_ONE\", CWorld::Players[CWorld::PlayerInFocus].m_nCollectedPackages, 5000, CWorld::Players[CWorld::PlayerInFocus].m_nTotalPackages);\n\n\t\t\t\tresult = true;\n\t\t\t\tRemove();\n\t\t\t\tDMAudio.PlayFrontEndSound(SOUND_PICKUP_HIDDEN_PACKAGE, 0);\n\t\t\t\tbreak;\n\t\t\tcase PICKUP_MONEY:\n\t\t\t\tCWorld::Players[playerId].m_nMoney += m_nQuantity;\n\t\t\t\tsprintf(gString, \"$%d\", m_nQuantity);\n#ifdef MONEY_MESSAGES\n\t\t\t\tCMoneyMessages::RegisterOne(m_vecPos + CVector(0.0f, 0.0f, 1.0f), gString, 0, 255, 0, 0.5f, 0.5f);\n#endif\n\t\t\t\tresult = true;\n\t\t\t\tRemove();\n\t\t\t\tDMAudio.PlayFrontEndSound(SOUND_PICKUP_MONEY, 0);\n\t\t\t\tplayer->Say(SOUND_PED_MUGGING);\n\t\t\t\tbreak;\n\t\t\tcase PICKUP_ASSET_REVENUE:\n\t\t\t\tCWorld::Players[CWorld::PlayerInFocus].m_nMoney += m_fRevenue;\n\t\t\t\tm_fRevenue = 0.0f;\n\t\t\t\tDMAudio.PlayFrontEndSound(SOUND_PICKUP_MONEY, 0);\n\t\t\t\tbreak;\n\t\t\tcase PICKUP_PROPERTY_LOCKED:\n\t\t\t\tif (!m_bWasControlMessageShown) {\n\t\t\t\t\tm_bWasControlMessageShown = true;\n\t\t\t\t\tCHud::SetHelpMessage(TheText.Get(m_sTextKey), false);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase PICKUP_PROPERTY_FORSALE:\n\t\t\t\tModifyStringLabelForControlSetting(m_sTextKey);\n\t\t\t\tCMessages::InsertNumberInString(TheText.Get(m_sTextKey), m_nQuantity,\n\t\t\t\t\t0, 0, 0, 0, 0, gUString);\n\t\t\t\tif (!CHud::IsHelpMessageBeingDisplayed())\n\t\t\t\t\tCHud::SetHelpMessage(gUString, false);\n\t\t\t\tif (CollectPickupBuffer == 0)\n\t\t\t\t\tbreak;\n\t\t\t\tif (CTheScripts::IsPlayerOnAMission())\n\t\t\t\t\tCHud::SetHelpMessage(TheText.Get(\"PROP_2\"), true);\n\t\t\t\telse {\n\t\t\t\t\tif (CWorld::Players[CWorld::PlayerInFocus].m_nMoney >= m_nQuantity) {\n\t\t\t\t\t\tCWorld::Players[CWorld::PlayerInFocus].m_nMoney -= m_nQuantity;\n\t\t\t\t\t\tCHud::SetHelpMessage(nil, true);\n\t\t\t\t\t\tresult = true;\n\t\t\t\t\t\tRemove();\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tCHud::SetHelpMessage(TheText.Get(\"PROP_1\"), true);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t} else {\n\t\tswitch (m_eType)\n\t\t{\n\t\tcase PICKUP_MINE_INACTIVE:\n\t\t\tif (vehicle != nil && !vehicle->IsSphereTouchingVehicle(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z, 2.0f)) {\n\t\t\t\tm_eType = PICKUP_MINE_ARMED;\n\t\t\t\tm_nTimer = CTimer::GetTimeInMilliseconds() + 10000;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase PICKUP_NAUTICAL_MINE_INACTIVE:\n\t\t{\n\t\t\tif (CWaterLevel::GetWaterLevel(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z + 5.0f, &waterLevel, false))\n\t\t\t\tm_pObject->GetMatrix().GetPosition().z = waterLevel + 0.6f;\n\n\t\t\tm_pObject->GetMatrix().UpdateRW();\n\t\t\tm_pObject->UpdateRwFrame();\n\n\t\t\tbool touched = false;\n\t\t\tfor (int32 i = CPools::GetVehiclePool()->GetSize()-1; i >= 0; i--) {\n\t\t\t\tCVehicle *vehicle = CPools::GetVehiclePool()->GetSlot(i);\n\t\t\t\tif (vehicle != nil && vehicle->IsSphereTouchingVehicle(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z, 1.5f)) {\n\t\t\t\t\ttouched = true;\n#ifdef FIX_BUGS\n\t\t\t\t\tbreak; // added break here\n#endif\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!touched) {\n\t\t\t\tm_eType = PICKUP_NAUTICAL_MINE_ARMED;\n\t\t\t\tm_nTimer = CTimer::GetTimeInMilliseconds() + 10000;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tcase PICKUP_NAUTICAL_MINE_ARMED:\n\t\t\tif (CWaterLevel::GetWaterLevel(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z + 5.0f, &waterLevel, false))\n\t\t\t\tm_pObject->GetMatrix().GetPosition().z = waterLevel + 0.6f;\n\n\t\t\tm_pObject->GetMatrix().UpdateRW();\n\t\t\tm_pObject->UpdateRwFrame();\n\t\t\t// no break here\n\t\tcase PICKUP_MINE_ARMED:\n\t\t{\n\t\t\tbool explode = false;\n\t\t\tif (CTimer::GetTimeInMilliseconds() > m_nTimer)\n\t\t\t\texplode = true;\n#ifdef FIX_BUGS\n\t\t\telse// added else here since vehicle lookup is useless\n#endif\n\t\t\t{\n\t\t\t\tfor (int32 i = CPools::GetVehiclePool()->GetSize()-1; i >= 0; i--) {\n\t\t\t\t\tCVehicle *vehicle = CPools::GetVehiclePool()->GetSlot(i);\n\t\t\t\t\tif (vehicle != nil && vehicle->IsSphereTouchingVehicle(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z, 1.5f)) {\n\t\t\t\t\t\texplode = true;\n#ifdef FIX_BUGS\n\t\t\t\t\t\tbreak; // added break here\n#endif\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (explode) {\n\t\t\t\tCExplosion::AddExplosion(nil, nil, EXPLOSION_MINE, m_pObject->GetPosition(), 0);\n\t\t\t\tRemove();\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tcase PICKUP_FLOATINGPACKAGE:\n\t\t\tm_pObject->m_vecMoveSpeed.z -= 0.01f * CTimer::GetTimeStep();\n\t\t\tm_pObject->GetMatrix().GetPosition() += m_pObject->GetMoveSpeed() * CTimer::GetTimeStep();\n\n\t\t\tm_pObject->GetMatrix().UpdateRW();\n\t\t\tm_pObject->UpdateRwFrame();\n\t\t\tif (CWaterLevel::GetWaterLevel(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z + 5.0f, &waterLevel, false) && waterLevel >= m_pObject->GetPosition().z)\n\t\t\t\tm_eType = PICKUP_FLOATINGPACKAGE_FLOATING;\n\t\t\tbreak;\n\t\tcase PICKUP_FLOATINGPACKAGE_FLOATING:\n\t\t\tif (CWaterLevel::GetWaterLevel(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z + 5.0f, &waterLevel, false))\n\t\t\t\tm_pObject->GetMatrix().GetPosition().z = waterLevel;\n\n\t\t\tm_pObject->GetMatrix().UpdateRW();\n\t\t\tm_pObject->UpdateRwFrame();\n\t\t\tif (vehicle != nil && vehicle->IsSphereTouchingVehicle(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z, 2.0f)) {\n\t\t\t\tRemove();\n\t\t\t\tresult = true;\n\t\t\t\tDMAudio.PlayFrontEndSound(SOUND_PICKUP_FLOAT_PACKAGE, 0);\n\t\t\t}\n\t\t\tbreak;\n\t\tdefault: break;\n\t\t}\n\t}\n\n\tif (!m_bRemoved && (m_eType == PICKUP_ONCE_TIMEOUT || m_eType == PICKUP_ONCE_TIMEOUT_SLOW || m_eType == PICKUP_MONEY) && CTimer::GetTimeInMilliseconds() > m_nTimer)\n\t\tRemove();\n\t\n\treturn result;\n}\n\nvoid\nCPickup::ProcessGunShot(CVector *vec1, CVector *vec2)\n{\n\tCColLine line(*vec1, *vec2);\n\tif (m_pObject) {\n\t\tCColSphere sphere;\n\t\tsphere.radius = 4.0f;\n\t\tsphere.center = m_pObject->GetPosition();\n\t\tif (CCollision::TestLineSphere(line, sphere)) {\n\t\t\tCExplosion::AddExplosion(nil, nil, EXPLOSION_MINE, m_pObject->GetPosition(), 0);\n\t\t\tCWorld::Remove(m_pObject);\n\t\t\tdelete m_pObject;\n\t\t\tm_pObject = nil;\n\t\t\tm_bRemoved = true;\n\t\t\tm_eType = PICKUP_NONE;\n\t\t}\n\t}\n}\n\nvoid\nCPickup::GetRidOfObjects()\n{\n\tif (m_pObject) {\n\t\tCWorld::Remove(m_pObject);\n\t\tdelete m_pObject;\n\t\tm_pObject = nil;\n\t}\n\tif (m_pExtraObject) {\n\t\tCWorld::Remove(m_pExtraObject);\n\t\tdelete m_pExtraObject;\n\t\tm_pExtraObject = nil;\n\t}\n}\n\nvoid\nCPickups::Init(void)\n{\n\tNumMessages = 0;\n\tfor (int i = 0; i < NUMPICKUPS; i++) {\n\t\taPickUps[i].m_eType = PICKUP_NONE;\n\t\taPickUps[i].m_nIndex = 1;\n\t\taPickUps[i].m_pObject = nil;\n\t\taPickUps[i].m_pExtraObject = nil;\n\t}\n\n\tfor (int i = 0; i < NUMCOLLECTEDPICKUPS; i++)\n\t\taPickUpsCollected[i] = 0;\n\n\tCollectedPickUpIndex = 0;\n}\n\nbool\nCPickups::TestForPickupsInBubble(CVector pos, float range)\n{\n\tfor (int i = 0; i < NUMPICKUPS; i++) {\n\t\tif ((aPickUps[i].m_vecPos - pos).Magnitude() < range)\n\t\t\treturn true;\n\t}\n\treturn false;\n}\n\nbool\nCPickups::TryToMerge_WeaponType(CVector pos, eWeaponType weapon, uint8 type, uint32 quantity, bool unused) {\n\tfor (int i = 0; i < NUMPICKUPS; i++) {\n\t\tif (aPickUps[i].m_eType == type && aPickUps[i].m_eModelIndex == ModelForWeapon(weapon))\n\t\t\tif ((aPickUps[i].m_vecPos - pos).Magnitude() < 7.5f) {\n\t\t\t\taPickUps[i].m_nQuantity += quantity;\n\t\t\t\treturn true;\n\t\t\t}\n\t}\n\treturn false;\n}\n\nbool\nCPickups::IsPickUpPickedUp(int32 pickupId)\n{\n\tfor (int i = 0; i < NUMCOLLECTEDPICKUPS; i++) {\n\t\tif (pickupId == aPickUpsCollected[i]) {\n\t\t\taPickUpsCollected[i] = 0;\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n\nvoid\nCPickups::PassTime(uint32 time)\n{\n\tfor (int i = 0; i < NUMPICKUPS; i++) {\n\t\tif (aPickUps[i].m_eType != PICKUP_NONE && aPickUps[i].m_eType != PICKUP_ASSET_REVENUE) {\n\t\t\tif (aPickUps[i].m_nTimer <= time)\n\t\t\t\taPickUps[i].m_nTimer = 0;\n\t\t\telse\n\t\t\t\taPickUps[i].m_nTimer -= time;\n\t\t}\n\t}\n}\n\nint32\nCPickups::GetActualPickupIndex(int32 index)\n{\n\tif (index == -1) return -1;\n\n\t// doesn't look nice\n\tif ((uint16)((index & 0xFFFF0000) >> 16) != aPickUps[(uint16)index].m_nIndex) return -1;\n\treturn (uint16)index;\n}\n\nbool\nCPickups::GivePlayerGoodiesWithPickUpMI(int16 modelIndex, int playerIndex)\n{\n\tCPlayerPed *player;\n\n\tif (playerIndex <= 0) player = CWorld::Players[CWorld::PlayerInFocus].m_pPed;\n\telse player = CWorld::Players[playerIndex].m_pPed;\n\n\tif (modelIndex == MI_PICKUP_ADRENALINE) {\n\t\tplayer->m_bAdrenalineActive = true;\n\t\tplayer->m_nAdrenalineTime = CTimer::GetTimeInMilliseconds() + 20000;\n\t\tplayer->m_fCurrentStamina = player->m_fMaxStamina;\n\t\tDMAudio.PlayFrontEndSound(SOUND_PICKUP_ADRENALINE, 0);\n\t\treturn true;\n\t} else if (modelIndex == MI_PICKUP_BODYARMOUR) {\n\t\tplayer->m_fArmour = CWorld::Players[playerIndex].m_nMaxArmour;\n\t\tDMAudio.PlayFrontEndSound(SOUND_PICKUP_ARMOUR, 0);\n\t\treturn true;\n\t} else if (modelIndex == MI_PICKUP_INFO) {\n\t\tDMAudio.PlayFrontEndSound(SOUND_PICKUP_BONUS, 0);\n\t\treturn true;\n\t} else if (modelIndex == MI_PICKUP_HEALTH) {\n\t\tplayer->m_fHealth = CWorld::Players[playerIndex].m_nMaxHealth;\n\t\tDMAudio.PlayFrontEndSound(SOUND_PICKUP_HEALTH, 0);\n\t\treturn true;\n\t} else if (modelIndex == MI_PICKUP_BONUS) {\n\t\tDMAudio.PlayFrontEndSound(SOUND_PICKUP_BONUS, 0);\n\t\treturn true;\n\t} else if (modelIndex == MI_PICKUP_BRIBE) {\n\t\tint32 level = Max(FindPlayerPed()->m_pWanted->GetWantedLevel() - 1, 0);\n\t\tplayer->SetWantedLevel(level);\n\t\tDMAudio.PlayFrontEndSound(SOUND_PICKUP_BONUS, 0);\n\t\treturn true;\n\t} else if (modelIndex == MI_PICKUP_KILLFRENZY) {\n\t\tDMAudio.PlayFrontEndSound(SOUND_PICKUP_BONUS, 0);\n\t\treturn true;\n\t}\n\treturn false;\n}\n\nvoid\nCPickups::RemovePickUp(int32 pickupIndex)\n{\n\tint32 index = GetActualPickupIndex(pickupIndex);\n\tif (index == -1) return;\n\n\tif (aPickUps[index].m_pObject) {\n\t\tCWorld::Remove(aPickUps[index].m_pObject);\n\t\tdelete aPickUps[index].m_pObject;\n\t\taPickUps[index].m_pObject = nil;\n\t}\n\tif (aPickUps[index].m_pExtraObject) {\n\t\tCWorld::Remove(aPickUps[index].m_pExtraObject);\n\t\tdelete aPickUps[index].m_pExtraObject;\n\t\taPickUps[index].m_pExtraObject = nil;\n\t}\n\taPickUps[index].m_eType = PICKUP_NONE;\n\taPickUps[index].m_bRemoved = true;\n}\n\nint32\nCPickups::GenerateNewOne(CVector pos, uint32 modelIndex, uint8 type, uint32 quantity, uint32 rate, bool highPriority, char* pText)\n{\n\tbool bFreeFound = false;\n\tint32 slot = 0;\n\n\tif (type == PICKUP_FLOATINGPACKAGE || type == PICKUP_NAUTICAL_MINE_INACTIVE || highPriority) {\n\t\tfor (slot = NUMPICKUPS-1; slot >= 0; slot--) {\n\t\t\tif (aPickUps[slot].m_eType == PICKUP_NONE) {\n\t\t\t\tbFreeFound = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\tif (!bFreeFound) {\n\t\tfor (slot = 0; slot < NUMGENERALPICKUPS; slot++) {\n\t\t\tif (aPickUps[slot].m_eType == PICKUP_NONE) {\n\t\t\t\tbFreeFound = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (!bFreeFound) {\n\t\tfor (slot = 0; slot < NUMGENERALPICKUPS; slot++) {\n\t\t\tif (aPickUps[slot].m_eType == PICKUP_MONEY) break;\n\t\t}\n\n\t\tif (slot >= NUMGENERALPICKUPS) {\n\t\t\tfor (slot = 0; slot < NUMGENERALPICKUPS; slot++) {\n\t\t\t\tif (aPickUps[slot].m_eType == PICKUP_ONCE_TIMEOUT || aPickUps[slot].m_eType == PICKUP_ONCE_TIMEOUT_SLOW) break;\n\t\t\t}\n\n\t\t\tif (slot >= NUMGENERALPICKUPS) return -1;\n\t\t\taPickUps[slot].GetRidOfObjects();\n\t\t}\n\t}\n\n\tif (slot >= NUMPICKUPS) return -1;\n\n\taPickUps[slot].m_eType = type;\n\taPickUps[slot].m_bRemoved = false;\n\taPickUps[slot].m_nQuantity = quantity;\n\taPickUps[slot].m_nMoneySpeed = rate;\n\taPickUps[slot].m_fRevenue = 0.0f;\n\taPickUps[slot].m_nTimer = CTimer::GetTimeInMilliseconds();\n\taPickUps[slot].m_bWasAmmoCollected = highPriority;\n\taPickUps[slot].m_bWasControlMessageShown = false;\n\tif (type == PICKUP_ONCE_TIMEOUT)\n\t\taPickUps[slot].m_nTimer = CTimer::GetTimeInMilliseconds() + 20000;\n\telse if (type == PICKUP_ONCE_TIMEOUT_SLOW)\n\t\taPickUps[slot].m_nTimer = CTimer::GetTimeInMilliseconds() + 120000;\n\telse if (type == PICKUP_MONEY)\n\t\taPickUps[slot].m_nTimer = CTimer::GetTimeInMilliseconds() + 30000;\n\telse if (type == PICKUP_MINE_INACTIVE || type == PICKUP_MINE_ARMED) {\n\t\taPickUps[slot].m_eType = PICKUP_MINE_INACTIVE;\n\t\taPickUps[slot].m_nTimer = CTimer::GetTimeInMilliseconds() + 1500;\n\t} else if (type == PICKUP_NAUTICAL_MINE_INACTIVE || type == PICKUP_NAUTICAL_MINE_ARMED) {\n\t\taPickUps[slot].m_eType = PICKUP_NAUTICAL_MINE_INACTIVE;\n\t\taPickUps[slot].m_nTimer = CTimer::GetTimeInMilliseconds() + 1500;\n\t}\n\taPickUps[slot].m_eModelIndex = modelIndex;\n\tif (pText)\n\t\tstrncpy(aPickUps[slot].m_sTextKey, pText, 8);\n\telse\n\t\taPickUps[slot].m_sTextKey[0] = '\\0';\n\n\taPickUps[slot].m_vecPos = pos;\n\taPickUps[slot].m_pObject = aPickUps[slot].GiveUsAPickUpObject(&aPickUps[slot].m_pObject, &aPickUps[slot].m_pExtraObject, -1, -1);\n\tif (aPickUps[slot].m_pObject)\n\t\tCWorld::Add(aPickUps[slot].m_pObject);\n\tif (aPickUps[slot].m_pExtraObject)\n\t\tCWorld::Add(aPickUps[slot].m_pExtraObject);\n\treturn GetNewUniquePickupIndex(slot);\n}\n\nint32\nCPickups::GenerateNewOne_WeaponType(CVector pos, eWeaponType weaponType, uint8 type, uint32 quantity)\n{\n\treturn GenerateNewOne(pos, ModelForWeapon(weaponType), type, quantity);\n}\n\nint32\nCPickups::GetNewUniquePickupIndex(int32 slot)\n{\n\tif (aPickUps[slot].m_nIndex >= 0xFFFE)\n\t\taPickUps[slot].m_nIndex = 1;\n\telse\n\t\taPickUps[slot].m_nIndex++;\n\treturn slot | (aPickUps[slot].m_nIndex << 16);\n}\n\nint32\nCPickups::ModelForWeapon(eWeaponType weaponType)\n{\n\treturn CWeaponInfo::GetWeaponInfo(weaponType)->m_nModelId;\n}\n\neWeaponType\nCPickups::WeaponForModel(int32 model)\n{\n\tif (model == MI_PICKUP_BODYARMOUR) return WEAPONTYPE_ARMOUR;\n\tif (model == MI_PICKUP_HEALTH) return WEAPONTYPE_HEALTH;\n\tif (model == MI_PICKUP_ADRENALINE) return WEAPONTYPE_ARMOUR;\n\tif (model == -1) return WEAPONTYPE_UNARMED;\n\treturn ((CWeaponModelInfo*)CModelInfo::GetModelInfo(model))->GetWeaponInfo();\n}\n\nvoid\nCPickups::AddToCollectedPickupsArray(int32 index)\n{\n\taPickUpsCollected[CollectedPickUpIndex++] = index | (aPickUps[index].m_nIndex << 16);\n\tif (CollectedPickUpIndex >= NUMCOLLECTEDPICKUPS)\n\t\tCollectedPickUpIndex = 0;\n}\n\nvoid\nCPickups::Update()\n{\n#ifdef FIX_BUGS // RIP speedrunning (solution from SA)\n\tif (CReplay::IsPlayingBack())\n\t\treturn;\n#endif\n#ifdef CAMERA_PICKUP\n\tif ( bPickUpcamActivated ) // taken from PS2\n\t{\n\t\tfloat dist = Distance2D(StaticCamCoors, FindPlayerCoors());\n\t\tfloat mult;\n\t\tif ( dist < 10.0f )\n\t\t\tmult = 1.0f - (dist / 10.0f );\n\t\telse\n\t\t\tmult = 0.0f;\n\n\t\tCVector pos = StaticCamCoors;\n\t\tpos.z += (pPlayerVehicle->GetColModel()->boundingBox.GetSize().z + 2.0f) * mult;\n\n\t\tif ( (CTimer::GetTimeInMilliseconds() - StaticCamStartTime) > 750 )\n\t\t{\n\t\t\tTheCamera.SetCamPositionForFixedMode(pos, CVector(0.0f, 0.0f, 0.0f));\n\t\t\tTheCamera.TakeControl(FindPlayerVehicle(), CCam::MODE_FIXED, JUMP_CUT, CAMCONTROL_SCRIPT);\n\t\t}\n\n\t\tif ( FindPlayerVehicle() != pPlayerVehicle || Distance(StaticCamCoors, FindPlayerCoors()) > 40.0f\n\t\t\t|| ((CTimer::GetTimeInMilliseconds() - StaticCamStartTime) > 60000) )\n\t\t{\n\t\t\tTheCamera.RestoreWithJumpCut();\n\t\t\tbPickUpcamActivated = false;\n\t\t}\n\t}\n#endif\n\tif (CPad::GetPad(0)->CollectPickupJustDown())\n\t\tCollectPickupBuffer = 6;\n\telse\n\t\tCollectPickupBuffer = Max(0, CollectPickupBuffer - 1);\n\n\tif (PlayerOnWeaponPickup)\n\t\tPlayerOnWeaponPickup = Max(0, PlayerOnWeaponPickup - 1);\n\n#define PICKUPS_FRAME_SPAN (6)\n#ifdef FIX_BUGS\n\tfor (uint32 i = NUMGENERALPICKUPS * (CTimer::GetFrameCounter() % PICKUPS_FRAME_SPAN) / PICKUPS_FRAME_SPAN; i < NUMGENERALPICKUPS * (CTimer::GetFrameCounter() % PICKUPS_FRAME_SPAN + 1) / PICKUPS_FRAME_SPAN; i++) {\n#else // BUG: this code can only reach 318 out of 320 pickups\n\tfor (uint32 i = NUMGENERALPICKUPS / PICKUPS_FRAME_SPAN * (CTimer::GetFrameCounter() % PICKUPS_FRAME_SPAN); i < NUMGENERALPICKUPS / PICKUPS_FRAME_SPAN * (CTimer::GetFrameCounter() % PICKUPS_FRAME_SPAN + 1); i++) {\n#endif\n\t\tif (aPickUps[i].m_eType != PICKUP_NONE && aPickUps[i].Update(FindPlayerPed(), FindPlayerVehicle(), CWorld::PlayerInFocus))\n\t\t\tAddToCollectedPickupsArray(i);\n\t}\n#undef PICKUPS_FRAME_SPAN\n\tfor (uint32 i = NUMGENERALPICKUPS; i < NUMPICKUPS; i++) {\n\t\tif (aPickUps[i].m_eType != PICKUP_NONE && aPickUps[i].Update(FindPlayerPed(), FindPlayerVehicle(), CWorld::PlayerInFocus))\n\t\t\tAddToCollectedPickupsArray(i);\n\t}\n}\n\nCPickup*\nCPickups::FindPickUpForThisObject(CEntity *object)\n{\n\tfor (uint32 i = 0; i < NUMPICKUPS; i++) {\n\t\tif (aPickUps[i].m_eType != PICKUP_NONE && (aPickUps[i].m_pObject == object || aPickUps[i].m_pExtraObject == object)) {\n\t\t\treturn &aPickUps[i];\n\t\t}\n\t}\n\treturn &aPickUps[0];\n}\n\nvoid\nCPickups::DoPickUpEffects(CEntity *entity)\n{\n\tCPickup *pickup = FindPickUpForThisObject(entity);\n\n\tif (entity->GetModelIndex() == MI_PICKUP_KILLFRENZY)\n\t\tentity->bDoNotRender = CTheScripts::IsPlayerOnAMission() || CDarkel::FrenzyOnGoing() || !CGame::nastyGame;\n\n\tif (!entity->bDoNotRender) {\n\t\tfloat s = Sin((float)((CTimer::GetTimeInMilliseconds() + (uintptr)entity) & 0x7FF) * DEGTORAD(360.0f / 0x800));\n\t\tfloat modifiedSin = 0.3f * (s + 1.0f);\n\n#ifdef FIX_BUGS\n\t\tint16 colorId = 0;\n#else\n\t\tint16 colorId;\n#endif\n\t\tbool doInnerGlow = false;\n\t\tbool doOuterGlow = true;\n\n\t\tif (entity->GetModelIndex() == MI_PICKUP_ADRENALINE || entity->GetModelIndex() == MI_PICKUP_CAMERA) {\n\t\t\tcolorId = WEAPONTYPE_TOTALWEAPONS;\n\t\t\tdoInnerGlow = true;\n\t\t\tdoOuterGlow = false;\n\t\t} else if (entity->GetModelIndex() == MI_PICKUP_BODYARMOUR) {\n\t\t\tcolorId = WEAPONTYPE_ARMOUR;\n\t\t} else if (entity->GetModelIndex() == MI_PICKUP_BRIBE) {\n\t\t\tdoInnerGlow = true;\n\t\t\tdoOuterGlow = false;\n\t\t} else if (entity->GetModelIndex() == MI_PICKUP_INFO || entity->GetModelIndex() == MI_PICKUP_KILLFRENZY) {\n\t\t\tdoInnerGlow = true;\n\t\t\tdoOuterGlow = false;\n\t\t} else if (entity->GetModelIndex() == MI_PICKUP_HEALTH || entity->GetModelIndex() == MI_PICKUP_BONUS) {\n\t\t\tcolorId = WEAPONTYPE_HEALTH;\n\t\t\tdoInnerGlow = true;\n\t\t\tdoOuterGlow = false;\n\t\t} else if (entity->GetModelIndex() == MI_PICKUP_PROPERTY) {\n\t\t\tdoInnerGlow = true;\n\t\t\tdoOuterGlow = false;\n\t\t} else if (entity->GetModelIndex() == MI_PICKUP_PROPERTY_FORSALE) {\n\t\t\tdoInnerGlow = true;\n\t\t\tdoOuterGlow = false;\n\t\t} else if (entity->GetModelIndex() == MI_PICKUP_REVENUE) {\n\t\t\tdoInnerGlow = true;\n\t\t\tdoOuterGlow = false;\n\t\t} else if (entity->GetModelIndex() == MI_PICKUP_SAVEGAME) {\n\t\t\tdoInnerGlow = true;\n\t\t\tdoOuterGlow = false;\n\t\t} else if (entity->GetModelIndex() == MI_PICKUP_CLOTHES) {\n\t\t\tcolorId = WEAPONTYPE_TOTALWEAPONS;\n\t\t\tdoOuterGlow = false;\n\t\t\tdoInnerGlow = true;\n\t\t} else\n\t\t\tcolorId = WeaponForModel(entity->GetModelIndex());\n\n\t\tconst CVector& pos = pickup->m_vecPos;\n\t\tif (doOuterGlow) {\n\t\t\tbool corona1 = false;\n\t\t\tbool corona2 = false;\n\t\t\tint timerVal = (CTimer::GetTimeInMilliseconds() >> 9) & 7;\n\n\t\t\tif (timerVal < 3)\n\t\t\t\tcorona1 = false;\n\t\t\telse if (timerVal == 3)\n\t\t\t\tcorona1 = (CGeneral::GetRandomNumber() & 3) != 0;\n\t\t\telse\n\t\t\t\tcorona1 = true;\n\n\t\t\ttimerVal = (timerVal - 1) & 7;\n\t\t\tif (timerVal < 3)\n\t\t\t\tcorona2 = false;\n\t\t\telse if (timerVal == 3)\n\t\t\t\tcorona2 = (CGeneral::GetRandomNumber() & 3) != 0;\n\t\t\telse\n\t\t\t\tcorona2 = true;\n\n\t\t\tif (((CObject*)entity)->bAmmoCollected) {\n\t\t\t\tcorona2 = false;\n\t\t\t\tcorona1 = false;\n\t\t\t}\n\n\t\t\tif (corona1) {\n\t\t\t\tCCoronas::RegisterCorona((uintptr)entity,\n\t\t\t\t\taPickupColors[colorId].r * 0.45f, aPickupColors[colorId].g * 0.45f, aPickupColors[colorId].b * 0.45f,\n\t\t\t\t\t255, pos, 0.76f, 65.0f,\n\t\t\t\t\tCCoronas::TYPE_RING, CCoronas::FLARE_NONE, CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF,\n\t\t\t\t\t0.0f, false, -0.4f);\n\t\t\t\tCShadows::StoreStaticShadow((uintptr)entity,\n\t\t\t\t\tSHADOWTYPE_ADDITIVE, gpShadowExplosionTex, &pos, 2.0f, 0.0f, 0.0f, -2.0f, 0,\n\t\t\t\t\taPickupColors[colorId].r * 0.3f, aPickupColors[colorId].g * 0.3f, aPickupColors[colorId].b * 0.3f,\n\t\t\t\t\t4.0f, 1.0f, 40.0f, false, 0.0f);\n\t\t\t\tfloat radius = (CGeneral::GetRandomNumber() & 0xF) * 0.1f + 3.0f;\n\t\t\t\tCPointLights::AddLight(CPointLights::LIGHT_POINT, pos, CVector(0.0f, 0.0f, 0.0f), radius, aPickupColors[colorId].r / 256.0f, aPickupColors[colorId].g / 256.0f, aPickupColors[colorId].b / 256.0f, CPointLights::FOG_NONE, true);\n\t\t\t} else\n\t\t\t\tCCoronas::RegisterCorona((uintptr)entity, 0, 0, 0, 255, pos, 0.57f, 65.0f, CCoronas::TYPE_RING, CCoronas::FLARE_NONE, CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);\n\n\t\t\tif (corona2) {\n\t\t\t\tCCoronas::RegisterCorona(\n\t\t\t\t\t(uintptr)entity + 1,\n\t\t\t\t\taPickupColors[colorId].r * 0.55f, aPickupColors[colorId].g * 0.55f, aPickupColors[colorId].b * 0.55f,\n\t\t\t\t\t255,\n\t\t\t\t\tpos,\n\t\t\t\t\t0.6f,\n\t\t\t\t\t65.0f,\n\t\t\t\t\tCCoronas::TYPE_RING, CCoronas::FLARE_NONE, CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF,\n\t\t\t\t\t0.0f, false, -0.4f);\n\t\t\t\tif (!corona1)\n\t\t\t\t\tCShadows::StoreStaticShadow((uintptr)entity, SHADOWTYPE_ADDITIVE, gpShadowExplosionTex, &pos, 2.0f, 0.0f, 0.0f, -2.0f, 0,\n\t\t\t\t\t\taPickupColors[colorId].r * 0.25f, aPickupColors[colorId].g * 0.25f, aPickupColors[colorId].b * 0.25f,\n\t\t\t\t\t\t4.0f, 1.0f, 40.0f, false, 0.0f);\n\t\t\t} else\n\t\t\t\tCCoronas::RegisterCorona((uintptr)entity + 1, 0, 0, 0, 255, pos, 0.45f, 65.0f, CCoronas::TYPE_RING, CCoronas::FLARE_NONE, CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);\n\t\t}\n\n\t\tCObject *object = (CObject*)entity;\n\t\tif (object->bPickupObjWithMessage || object->bOutOfStock || object->m_nBonusValue || object->m_nCostValue) {\n\t\t\t\n\t\t\tfloat dist = Distance2D(pos, TheCamera.GetPosition());\n\t\t\tconst float MAXDIST = 14.0f;\n\n\t\t\tif (dist < MAXDIST && NumMessages < NUMPICKUPMESSAGES) {\n\t\t\t\tRwV3d vecOut;\n\t\t\t\tfloat fDistX, fDistY;\n\t\t\t\tif (CSprite::CalcScreenCoors(entity->GetPosition() + CVector(0.0f, 0.0f, 0.7f), &vecOut, &fDistX, &fDistY, true)) {\n\t\t\t\t\taMessages[NumMessages].m_pos.x = vecOut.x;\n\t\t\t\t\taMessages[NumMessages].m_pos.y = vecOut.y;\n\t\t\t\t\taMessages[NumMessages].m_dist.x = fDistX;\n\t\t\t\t\taMessages[NumMessages].m_dist.y = fDistY;\n\t\t\t\t\taMessages[NumMessages].m_weaponType = WeaponForModel(entity->GetModelIndex());\n\t\t\t\t\taMessages[NumMessages].m_color.red = aPickupColors[colorId].r;\n\t\t\t\t\taMessages[NumMessages].m_color.green = aPickupColors[colorId].g;\n\t\t\t\t\taMessages[NumMessages].m_color.blue = aPickupColors[colorId].b;\n\t\t\t\t\taMessages[NumMessages].m_color.alpha = (1.0f - dist / MAXDIST) * 128.0f;\n\t\t\t\t\taMessages[NumMessages].m_bOutOfStock = object->bOutOfStock;\n\t\t\t\t\taMessages[NumMessages].m_quantity = object->m_nBonusValue;\n\t\t\t\t\taMessages[NumMessages].money = object->m_nCostValue;\n\t\t\t\t\tNumMessages++;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tuint32 model = entity->GetModelIndex();\n\t\tCColModel *colModel = entity->GetColModel();\n\t\tCVector colLength = colModel->boundingBox.max - colModel->boundingBox.min;\n\t\tfloat maxDimension = Max(colLength.x, Max(colLength.y, colLength.z));\n\n\t\tfloat scale = (Max(1.f, 1.2f / maxDimension) - 1.0f) * 0.6f + 1.0f;\n\t\tif (model == MI_MINIGUN || model == MI_MINIGUN2)\n\t\t\tscale = 1.2f;\n\n\t\tentity->GetMatrix().SetRotateZOnlyScaled((float)(CTimer::GetTimeInMilliseconds() & 0x7FF) * DEGTORAD(360.0f / 0x800), scale);\n\n\t\tif (entity->GetModelIndex() == MI_MINIGUN2) {\n\t\t\tCMatrix matrix1;\n\t\t\tCMatrix matrix2; // unused\n\t\t\tentity->SetPosition(pickup->m_vecPos);\n\t\t\tmatrix1.SetRotateX(0.0f);\n\t\t\tmatrix1.Rotate(DEGTORAD(4.477f), DEGTORAD(-29.731f), DEGTORAD(-1.064f));\n\t\t\tmatrix1.Translate(CVector(0.829f, -0.001f, 0.226f));\n\t\t\tentity->GetMatrix() *= matrix1;\n\t\t}\n\n\t\tif (doOuterGlow) {\n\t\t\tCVector scale(0.0f, 0.0f, 0.0f);\n\t\t\tif (colLength.x == maxDimension)\n\t\t\t\tscale.x = colLength.x;\n\t\t\telse if (colLength.y == maxDimension)\n\t\t\t\tscale.y = colLength.y;\n\t\t\telse\n\t\t\t\tscale.z = colLength.z;\n\n\t\t\tfor (int i = 0; i < 4; i++) {\n\t\t\t\tCVector pos = entity->GetMatrix() * (scale * ((float)i / 3.0f));\n\t\t\t\tCCoronas::RegisterCorona(\n\t\t\t\t\t(uintptr)entity + 8 + i,\n\t\t\t\t\taPickupColors[colorId].r * 0.15f,\n\t\t\t\t\taPickupColors[colorId].g * 0.15f,\n\t\t\t\t\taPickupColors[colorId].b * 0.15f,\n\t\t\t\t\t255,\n\t\t\t\t\tpos,\n\t\t\t\t\t1.0f,\n\t\t\t\t\t65.0f,\n\t\t\t\t\tCCoronas::TYPE_STAR, CCoronas::FLARE_NONE,\n\t\t\t\t\tCCoronas::REFLECTION_OFF,\n\t\t\t\t\tCCoronas::LOSCHECK_OFF,\n\t\t\t\t\tCCoronas::STREAK_OFF,\n\t\t\t\t\t0.0f,\n\t\t\t\t\tfalse,\n\t\t\t\t\t-0.5f);\n\t\t\t}\n\t\t}\n\n\t\tif (doInnerGlow)\n\t\t\tCCoronas::RegisterCorona(\n#ifdef FIX_BUGS\n\t\t\t\t(uintptr)entity + 8 + 4,\n#else\n\t\t\t\t(uintptr)entity + 9,\n#endif\n\t\t\t\t126, 69, 121, 255, entity->GetPosition(), 1.2f, 50.0f,\n\t\t\t\tCCoronas::TYPE_STAR, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_ON, 0.0f);\n\t}\n}\n\nvoid\nCPickups::DoMineEffects(CEntity *entity)\n{\n\tconst CVector &pos = entity->GetPosition();\n\tfloat dist = Distance(pos, TheCamera.GetPosition());\n\tconst float MAXDIST = 20.0f;\n\n\tif (dist < MAXDIST) {\n\t\tfloat s = Sin((float)((CTimer::GetTimeInMilliseconds() + (uintptr)entity) & 0x1FF) * DEGTORAD(360.0f / 0x200));\n\n\t\tint32 red = (MAXDIST - dist) * (0.5f * s + 0.5f) / MAXDIST * 64.0f;\n\t\tCShadows::StoreStaticShadow((uintptr)entity, SHADOWTYPE_ADDITIVE, gpShadowExplosionTex, &pos, 2.0f, 0.0f, 0.0f, -2.0f, 0, red, 0, 0, 4.0f, 1.0f, 40.0f,\n\t\t                            false, 0.0f);\n\t\tCCoronas::RegisterCorona((uintptr)entity, red, 0, 0, 255, pos, 0.6f, 60.0f, CCoronas::TYPE_RING, CCoronas::FLARE_NONE, CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);\n\t}\n\n\tentity->GetMatrix().SetRotateZOnly((float)(CTimer::GetTimeInMilliseconds() & 0x3FF) * DEGTORAD(360.0f / 0x400));\n}\n\nvoid\nCPickups::DoMoneyEffects(CEntity *entity)\n{\n\tconst CVector &pos = entity->GetPosition();\n\tfloat dist = Distance(pos, TheCamera.GetPosition());\n\tconst float MAXDIST = 20.0f;\n\n\tif (dist < MAXDIST) {\n\t\tfloat s = Sin((float)((CTimer::GetTimeInMilliseconds() + (uintptr)entity) & 0x3FF) * DEGTORAD(360.0f / 0x400));\n\n\t\tint32 green = (MAXDIST - dist) * (0.2f * s + 0.3f) / MAXDIST * 64.0f;\n\t\tCShadows::StoreStaticShadow((uintptr)entity, SHADOWTYPE_ADDITIVE, gpShadowExplosionTex, &pos, 2.0f, 0.0f, 0.0f, -2.0f, 0, 0, green, 0, 4.0f, 1.0f,\n\t\t                            40.0f, false, 0.0f);\n\t\tCCoronas::RegisterCorona((uintptr)entity, 0, green, 0, 255, pos, 0.4f, 40.0f, CCoronas::TYPE_RING, CCoronas::FLARE_NONE, CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);\n\t}\n\n\tentity->GetMatrix().SetRotateZOnly((float)(CTimer::GetTimeInMilliseconds() & 0x7FF) * DEGTORAD(360.0f / 0x800));\n}\n\nvoid\nCPickups::DoCollectableEffects(CEntity *entity)\n{\n\tconst CVector &pos = entity->GetPosition();\n\tfloat dist = Distance(pos, TheCamera.GetPosition());\n\tconst float MAXDIST = 14.0f;\n\n\tif (dist < MAXDIST) {\n\t\tfloat s = Sin((float)((CTimer::GetTimeInMilliseconds() + (uintptr)entity) & 0x7FF) * DEGTORAD(360.0f / 0x800));\n\n\t\tint32 color = (MAXDIST - dist) * (0.5f * s + 0.5f) / MAXDIST * 255.0f;\n\t\tCShadows::StoreStaticShadow((uintptr)entity, SHADOWTYPE_ADDITIVE, gpShadowExplosionTex, &pos, 2.0f, 0.0f, 0.0f, -2.0f, 0, color, color, color, 4.0f,\n\t\t                            1.0f, 40.0f, false, 0.0f);\n\t\tCCoronas::RegisterCorona((uintptr)entity, color, color, color, 255, pos, 0.6f, 40.0f, CCoronas::TYPE_HEX, CCoronas::FLARE_NONE, CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);\n\t}\n\n\tentity->GetMatrix().SetRotateZOnly((float)(CTimer::GetTimeInMilliseconds() & 0xFFF) * DEGTORAD(360.0f / 0x1000));\n}\n\nvoid\nCPickups::RenderPickUpText()\n{\n\twchar *strToPrint;\n\tfor (int32 i = 0; i < NumMessages; i++) {\n\n\t\tif (aMessages[i].money != 0) {\n\t\t\tsprintf(gString, \"$%d\", aMessages[i].money);\n\t\t\tAsciiToUnicode(gString, gUString);\n\t\t\tstrToPrint = gUString;\n\t\t} else {\n\t\t\tswitch (aMessages[i].m_quantity) // could use some enum maybe\n\t\t\t{\n\t\t\tcase 0:\n\t\t\t\tif (aMessages[i].m_weaponType == WEAPONTYPE_HEALTH || aMessages[i].m_weaponType == WEAPONTYPE_ARMOUR) {\n\t\t\t\t\tstrToPrint = nil;\n\t\t\t\t} else {\n\t\t\t\t\tif (aMessages[i].m_bOutOfStock)\n\t\t\t\t\t\tstrToPrint = TheText.Get(\"STOCK\");\n\t\t\t\t\telse {\n\t\t\t\t\t\tsprintf(gString, \"$%d\", CostOfWeapon[aMessages[i].m_weaponType]);\n\t\t\t\t\t\tAsciiToUnicode(gString, gUString);\n\t\t\t\t\t\tstrToPrint = gUString;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 1:\n\t\t\t\tstrToPrint = TheText.Get(\"OUTFT1\");\n\t\t\t\tbreak;\n\t\t\tcase 2:\n\t\t\t\tstrToPrint = TheText.Get(\"OUTFT2\");\n\t\t\t\tbreak;\n\t\t\tcase 3:\n\t\t\t\tstrToPrint = TheText.Get(\"OUTFT3\");\n\t\t\t\tbreak;\n\t\t\tcase 4:\n\t\t\t\tstrToPrint = TheText.Get(\"OUTFT4\");\n\t\t\t\tbreak;\n\t\t\tcase 5:\n\t\t\t\tstrToPrint = TheText.Get(\"OUTFT5\");\n\t\t\t\tbreak;\n\t\t\tcase 6:\n\t\t\t\tstrToPrint = TheText.Get(\"OUTFT6\");\n\t\t\t\tbreak;\n\t\t\tcase 7:\n\t\t\t\tstrToPrint = TheText.Get(\"OUTFT7\");\n\t\t\t\tbreak;\n\t\t\tcase 8:\n\t\t\t\tstrToPrint = TheText.Get(\"OUTFT8\");\n\t\t\t\tbreak;\n\t\t\tcase 9:\n\t\t\t\tstrToPrint = TheText.Get(\"OUTFT9\");\n\t\t\t\tbreak;\n\t\t\tcase 10:\n\t\t\t\tstrToPrint = TheText.Get(\"OUTFT10\");\n\t\t\t\tbreak;\n\t\t\tcase 11:\n\t\t\t\tstrToPrint = TheText.Get(\"OUTFT11\");\n\t\t\t\tbreak;\n\t\t\tcase 12:\n\t\t\t\tstrToPrint = TheText.Get(\"OUTFT12\");\n\t\t\t\tbreak;\n\t\t\tcase 13:\n\t\t\t\tstrToPrint = TheText.Get(\"OUTFT13\");\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (strToPrint == nil)\n\t\t\tcontinue;\n\t\tCFont::SetPropOn();\n\t\tCFont::SetBackgroundOff();\n\n#ifdef FIX_BUGS\n\t\tconst float MAX_SCALE = SCREEN_WIDTH / DEFAULT_SCREEN_WIDTH;\n#else\n\t\tfloat MAX_SCALE = RsGlobal.width / DEFAULT_SCREEN_WIDTH;\n#endif\n\n\t\tfloat fScaleY = aMessages[i].m_dist.y / 30.0f;\n\t\tif (fScaleY > MAX_SCALE) fScaleY = MAX_SCALE;\n\n\t\tfloat fScaleX = aMessages[i].m_dist.x / 30.0f;\n\t\tif (fScaleX > MAX_SCALE) fScaleX = MAX_SCALE;\n\n\t\tCFont::SetScale(fScaleX, fScaleY); // this shouldn't be scaled\n\t\tCFont::SetCentreOn();\n\t\tCFont::SetCentreSize(SCREEN_WIDTH);\n\t\tCFont::SetJustifyOff();\n\n\t\tCFont::SetColor(CRGBA(aMessages[i].m_color.red, aMessages[i].m_color.green, aMessages[i].m_color.blue, aMessages[i].m_color.alpha));\n\t\tCFont::SetBackGroundOnlyTextOff();\n\t\tCFont::SetFontStyle(FONT_STANDARD);\n\t\tCFont::PrintString(aMessages[i].m_pos.x, aMessages[i].m_pos.y, strToPrint);\n\t}\n\tNumMessages = 0;\n}\n\nvoid\nCPickups::CreateSomeMoney(CVector pos, int money)\n{\n\tbool found;\n\n\tint pickupCount = Min(money / 20 + 1, 7);\n\tint moneyPerPickup = money / pickupCount;\n\n\tfor (int i = 0; i < pickupCount; i++) {\n\t\t// (CGeneral::GetRandomNumber() % 256) * PI / 128 gives a float up to something TWOPI-ish.\n\t\tpos.x += 1.5f * Sin((CGeneral::GetRandomNumber() % 256) * PI / 128);\n\t\tpos.y += 1.5f * Cos((CGeneral::GetRandomNumber() % 256) * PI / 128);\n\t\tpos.z = CWorld::FindGroundZFor3DCoord(pos.x, pos.y, pos.z, &found) + 0.5f;\n\t\tif (found) {\n\t\t\tCPickups::GenerateNewOne(CVector(pos.x, pos.y, pos.z), MI_MONEY, PICKUP_MONEY, moneyPerPickup + (CGeneral::GetRandomNumber() & 3));\n\t\t}\n\t}\n}\n\nvoid\nCPickups::RemoveAllPickupsOfACertainWeaponGroupWithNoAmmo(eWeaponType weaponType)\n{\n\tuint32 weaponSlot = CWeaponInfo::GetWeaponInfo(weaponType)->m_nWeaponSlot;\n\tif (CWeaponInfo::IsWeaponSlotAmmoMergeable(weaponSlot)) {\n\t\tfor (int slot = 0; slot < NUMPICKUPS; slot++) {\n\t\t\tif (aPickUps[slot].m_eType == PICKUP_ONCE || aPickUps[slot].m_eType == PICKUP_ONCE_TIMEOUT || aPickUps[slot].m_eType == PICKUP_ONCE_TIMEOUT_SLOW) {\n\t\t\t\tif (aPickUps[slot].m_pObject) {\n\t\t\t\t\tif (CWeaponInfo::GetWeaponInfo(WeaponForModel(aPickUps[slot].m_pObject->GetModelIndex()))->m_nWeaponSlot == weaponSlot &&\n\t\t\t\t\t\taPickUps[slot].m_nQuantity == 0) {\n\t\t\t\t\t\tCWorld::Remove(aPickUps[slot].m_pObject);\n\t\t\t\t\t\tdelete aPickUps[slot].m_pObject;\n\t\t\t\t\t\taPickUps[slot].m_bRemoved = true;\n\t\t\t\t\t\taPickUps[slot].m_pObject = nil;\n\t\t\t\t\t\taPickUps[slot].m_eType = PICKUP_NONE;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nCPickups::DetonateMinesHitByGunShot(CVector *vec1, CVector *vec2)\n{\n\tfor (int i = 0; i < NUMGENERALPICKUPS; i++) {\n\t\tif (aPickUps[i].m_eType == PICKUP_NAUTICAL_MINE_ARMED)\n\t\t\taPickUps[i].ProcessGunShot(vec1, vec2);\n\t}\n}\n\nvoid\nCPickups::RemoveUnnecessaryPickups(const CVector& center, float radius)\n{\n\tfor (int i = 0; i < NUMPICKUPS; i++) {\n\t\tif (aPickUps[i].m_eType == PICKUP_ONCE_TIMEOUT || aPickUps[i].m_eType == PICKUP_MONEY) {\n\t\t\tif (Distance(center, aPickUps[i].m_vecPos) < radius) {\n\t\t\t\taPickUps[i].GetRidOfObjects();\n\t\t\t\taPickUps[i].m_bRemoved = true;\n\t\t\t\taPickUps[i].m_eType = PICKUP_NONE;\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nCPickups::Load(uint8 *buf, uint32 size)\n{\nINITSAVEBUF\n\n\tfor (int32 i = 0; i < NUMPICKUPS; i++) {\n\t\taPickUps[i] = ReadSaveBuf<CPickup>(buf);\n\n\t\tif (aPickUps[i].m_eType != PICKUP_NONE) {\n\t\t\tif (aPickUps[i].m_pObject != nil)\n\t\t\t\taPickUps[i].m_pObject = CPools::GetObjectPool()->GetSlot((uintptr)aPickUps[i].m_pObject - 1);\n\t\t\tif (aPickUps[i].m_pExtraObject != nil)\n\t\t\t\taPickUps[i].m_pExtraObject = CPools::GetObjectPool()->GetSlot((uintptr)aPickUps[i].m_pExtraObject - 1);\n\t\t}\n\t\t\t\n\t}\n\n\tCollectedPickUpIndex = ReadSaveBuf<uint16>(buf);\n\tReadSaveBuf<uint16>(buf);\n\tNumMessages = 0;\n\n\tfor (uint16 i = 0; i < NUMCOLLECTEDPICKUPS; i++)\n\t\taPickUpsCollected[i] = ReadSaveBuf<int32>(buf);\n\nVALIDATESAVEBUF(size)\n}\n\nvoid\nCPickups::Save(uint8 *buf, uint32 *size)\n{\n\t*size = sizeof(aPickUps);\n\t*size += sizeof(uint16) + sizeof(uint16) + sizeof(aPickUpsCollected);\n\nINITSAVEBUF\n\n\tfor (int32 i = 0; i < NUMPICKUPS; i++) {\n\t\tCPickup *buf_pickup = WriteSaveBuf(buf, aPickUps[i]);\n\t\tif (buf_pickup->m_eType != PICKUP_NONE) {\n\t\t\tif (buf_pickup->m_pObject != nil)\n\t\t\t\tbuf_pickup->m_pObject = (CObject*)(CPools::GetObjectPool()->GetJustIndex_NoFreeAssert(buf_pickup->m_pObject) + 1);\n\t\t\tif (buf_pickup->m_pExtraObject != nil)\n\t\t\t\tbuf_pickup->m_pExtraObject = (CObject*)(CPools::GetObjectPool()->GetJustIndex_NoFreeAssert(buf_pickup->m_pExtraObject) + 1);\n\t\t}\n\t}\n\n\tWriteSaveBuf(buf, CollectedPickUpIndex);\n\tWriteSaveBuf(buf, (uint16)0); // possibly was NumMessages\n\n\tfor (uint16 i = 0; i < NUMCOLLECTEDPICKUPS; i++)\n\t\tWriteSaveBuf(buf, aPickUpsCollected[i]);\n\nVALIDATESAVEBUF(*size)\n}\n\nvoid\nCPacManPickup::Update()\n{\n}\n\nint32 CollectGameState;\nint16 ThingsToCollect;\n\nCPacManPickup CPacManPickups::aPMPickUps[NUMPACMANPICKUPS];\nCVector CPacManPickups::LastPickUpCoors;\nint32 CPacManPickups::PillsEatenInRace;\nbool CPacManPickups::bPMActive;\n\nvoid\nCPacManPickups::Init()\n{\n}\n\nvoid\nCPacManPickups::Update()\n{\n}\n\nvoid\nCPacManPickups::GeneratePMPickUps(CVector pos, float scrambleMult, int16 count, uint8 type)\n{\n}\n\n// diablo porn mission pickups\nstatic const CVector aRacePoints1[] = {\n\tCVector(913.62219f, -155.13692f, 4.9699469f),\n\tCVector(913.92401f, -124.12943f, 4.9692569f),\n\tCVector(913.27899f, -93.524231f, 7.4325991f),\n\tCVector(912.60852f, -63.15905f, 7.4533591f),\n\tCVector(934.22144f, -42.049122f, 7.4511471f),\n\tCVector(0.0f, 0.0f, 0.0f),\n};\n\nvoid\nCPacManPickups::GeneratePMPickUpsForRace(int32 race)\n{\n}\n\nvoid\nCPacManPickups::GenerateOnePMPickUp(CVector pos)\n{\n}\n\nvoid\nCPacManPickups::Render()\n{\n}\n\nvoid\nCPacManPickups::ClearPMPickUps()\n{\n}\n\nvoid\nCPacManPickups::StartPacManRace(int32 race)\n{\n}\n\nvoid\nCPacManPickups::StartPacManRecord()\n{\n}\n\nuint32\nCPacManPickups::QueryPowerPillsEatenInRace()\n{\n\treturn 0;\n}\n\nvoid\nCPacManPickups::ResetPowerPillsEatenInRace()\n{\n}\n\nvoid\nCPacManPickups::CleanUpPacManStuff()\n{\n}\n\nvoid\nCPacManPickups::StartPacManScramble(CVector pos, float scrambleMult, int16 count)\n{\n}\n\nuint32\nCPacManPickups::QueryPowerPillsCarriedByPlayer()\n{\n\treturn 0;\n}\n\nvoid\nCPacManPickups::ResetPowerPillsCarriedByPlayer()\n{\n}\n\nvoid\nCPed::CreateDeadPedMoney(void)\n{\n\tif (!CGame::nastyGame)\n\t\treturn;\n\n\tint mi = GetModelIndex();\n\n\tif ((mi >= MI_COP && mi <= MI_FIREMAN) || (CharCreatedBy == MISSION_CHAR && !bMoneyHasBeenGivenByScript) || bInVehicle)\n\t\treturn;\n\n\tint money = m_nPedMoney;\n\tif (money < 10)\n\t\treturn;\n\n\tCVector pickupPos = GetPosition();\n\tCPickups::CreateSomeMoney(pickupPos, money);\n\tm_nPedMoney = 0;\n}\n\nvoid\nCPed::CreateDeadPedWeaponPickups(void)\n{\n\tCVector pickupPos;\n\n\tif (bInVehicle)\n\t\treturn;\n\n\tfor(int i = 0; i < TOTAL_WEAPON_SLOTS; i++) {\n\n\t\teWeaponType weapon = GetWeapon(i).m_eWeaponType;\n\t\tint weaponAmmo = GetWeapon(i).m_nAmmoTotal;\n\t\tif (weapon == WEAPONTYPE_UNARMED || weapon == WEAPONTYPE_DETONATOR || (weaponAmmo == 0 && !GetWeapon(i).IsTypeMelee()))\n\t\t\tcontinue;\n\n\t\tint quantity = Min(weaponAmmo, AmmoForWeapon_OnStreet[weapon] / 2);\n\t\tCreateDeadPedPickupCoors(&pickupPos.x, &pickupPos.y, &pickupPos.z);\n\t\tpickupPos.z += 0.3f;\n\t\tif (!CPickups::TryToMerge_WeaponType(pickupPos, weapon, PICKUP_ONCE_TIMEOUT, quantity, false)) {\n\t\t\tCPickups::GenerateNewOne_WeaponType(pickupPos, weapon, PICKUP_ONCE_TIMEOUT, Min(weaponAmmo, quantity));\n\t\t}\n\t}\n\tClearWeapons();\n}\n\nvoid\nCPed::CreateDeadPedPickupCoors(float *x, float *y, float *z)\n{\n\tbool found = false;\n\tCVector pickupPos;\n\n#define NUMBER_OF_ATTEMPTS 32\n\tfor (int i = 0; i < NUMBER_OF_ATTEMPTS; i++) {\n\n\t\tpickupPos = GetPosition();\n\t\tpickupPos.x = 1.5f * Sin((CGeneral::GetRandomNumber() % 256)/256.0f * TWOPI) + GetPosition().x;\n\t\tpickupPos.y = 1.5f * Cos((CGeneral::GetRandomNumber() % 256)/256.0f * TWOPI) + GetPosition().y;\n\t\tpickupPos.z = CWorld::FindGroundZFor3DCoord(pickupPos.x, pickupPos.y, pickupPos.z, &found) + 0.5f;\n\n\t\tif (!found)\n\t\t\tcontinue;\n\n\t\tCVector pedPos = GetPosition();\n\t\tpedPos.z += 0.3f;\n\n\t\tCVector pedToPickup = pickupPos - pedPos;\n\t\tfloat distance = pedToPickup.Magnitude();\n\n\t\t// outer edge of pickup\n\t\tdistance = (distance + 0.4f) / distance;\n\t\tCVector pickupPos2 = pedPos;\n\t\tpickupPos2 += distance * pedToPickup;\n\n\t\tif ((pickupPos - FindPlayerCoors()).Magnitude2D() > 2.0f || i > NUMBER_OF_ATTEMPTS / 2) {\n\n\t\t\tif (i > NUMBER_OF_ATTEMPTS / 2 || !CPickups::TestForPickupsInBubble(pickupPos, 1.3f)) {\n\n\t\t\t\tif (CWorld::GetIsLineOfSightClear(pickupPos2, pedPos,\n\t\t\t\t\ttrue, i < NUMBER_OF_ATTEMPTS / 2, false, i < NUMBER_OF_ATTEMPTS / 2, false, false, false)) {\n\n\t\t\t\t\tif (i > NUMBER_OF_ATTEMPTS / 2 || !CWorld::TestSphereAgainstWorld(pickupPos, 1.2f, nil, false, true, false, false, false, false)) {\n\t\t\t\t\t\t*x = pickupPos.x;\n\t\t\t\t\t\t*y = pickupPos.y;\n\t\t\t\t\t\t*z = pickupPos.z;\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\t*x = GetPosition().x;\n\t*y = GetPosition().y;\n\t*z = GetPosition().z + 0.4f;\n#undef NUMBER_OF_ATTEMPTS\n}"
  },
  {
    "path": "src/control/Pickups.h",
    "content": "#pragma once\n#include \"Weapon.h\"\n\nenum ePickupType\n{\n\tPICKUP_NONE = 0,\n\tPICKUP_IN_SHOP,\n\tPICKUP_ON_STREET,\n\tPICKUP_ONCE,\n\tPICKUP_ONCE_TIMEOUT,\n\tPICKUP_ONCE_TIMEOUT_SLOW,\n\tPICKUP_COLLECTABLE1,\n\tPICKUP_IN_SHOP_OUT_OF_STOCK,\n\tPICKUP_MONEY,\n\tPICKUP_MINE_INACTIVE,\n\tPICKUP_MINE_ARMED,\n\tPICKUP_NAUTICAL_MINE_INACTIVE,\n\tPICKUP_NAUTICAL_MINE_ARMED,\n\tPICKUP_FLOATINGPACKAGE,\n\tPICKUP_FLOATINGPACKAGE_FLOATING,\n\tPICKUP_ON_STREET_SLOW,\n\tPICKUP_ASSET_REVENUE,\n\tPICKUP_PROPERTY_LOCKED,\n\tPICKUP_PROPERTY_FORSALE,\n\tPICKUP_NUMOFTYPES\n};\n\nclass CEntity;\nclass CObject;\nclass CVehicle;\nclass CPlayerPed;\n\nclass CPickup\n{\npublic:\n\tCVector m_vecPos;\n\tfloat m_fRevenue;\n\tCObject *m_pObject;\n\tCObject *m_pExtraObject;\n\tuint32 m_nQuantity;\n\tuint32 m_nTimer;\n\tuint16 m_nMoneySpeed;\n\tint16 m_eModelIndex;\n\tuint16 m_nIndex;\n\tchar m_sTextKey[8];\n\tuint8 m_eType;\n\tbool m_bRemoved;\n\tuint8 m_bWasAmmoCollected:1;\n\tuint8 m_bWasControlMessageShown:1;\n\n\tCObject *GiveUsAPickUpObject(CObject **object, CObject **extraObject, int32 handle, int32 extraHandle);\n\tbool Update(CPlayerPed *player, CVehicle *vehicle, int playerId);\n\tvoid GetRidOfObjects();\n\tvoid ExtractAmmoFromPickup(CPlayerPed *player);\n\tvoid ProcessGunShot(CVector *vec1, CVector *vec2);\nprivate:\n\tinline bool IsMine() { return m_eType >= PICKUP_MINE_INACTIVE && m_eType <= PICKUP_FLOATINGPACKAGE_FLOATING; }\n\tinline bool CanBePickedUp(CPlayerPed *player, int playerId);\n\tinline void Remove();\n};\n\nVALIDATE_SIZE(CPickup, 0x1C);\n\nstruct tPickupMessage\n{\n\tCVector2D m_pos;\n\teWeaponType m_weaponType;\n\tCVector2D m_dist;\n\tCRGBA m_color;\n\tuint8 m_bOutOfStock;\n\tuint8 m_quantity;\n\tuint16 money;\n};\n\nclass CPickups\n{\n\tstatic int32 aPickUpsCollected[NUMCOLLECTEDPICKUPS];\n\tstatic int16 CollectedPickUpIndex;\n\tstatic int16 NumMessages;\n\tstatic tPickupMessage aMessages[NUMPICKUPMESSAGES];\npublic:\n\tstatic int32 PlayerOnWeaponPickup;\n\n\tstatic void Init();\n\tstatic void Update();\n\tstatic void RenderPickUpText();\n\tstatic void DoCollectableEffects(CEntity *ent);\n\tstatic void DoMoneyEffects(CEntity *ent);\n\tstatic void DoMineEffects(CEntity *ent);\n\tstatic void DoPickUpEffects(CEntity *ent);\n\tstatic int32 GenerateNewOne(CVector pos, uint32 modelIndex, uint8 type, uint32 quantity, uint32 rate = 0, bool highPriority = false, char* pText = nil);\n\tstatic int32 GenerateNewOne_WeaponType(CVector pos, eWeaponType weaponType, uint8 type, uint32 quantity);\n\tstatic void RemovePickUp(int32 pickupIndex);\n\tstatic void AddToCollectedPickupsArray(int32 index);\n\tstatic bool IsPickUpPickedUp(int32 pickupId);\n\tstatic int32 ModelForWeapon(eWeaponType weaponType);\n\tstatic enum eWeaponType WeaponForModel(int32 model);\n\tstatic int32 GetActualPickupIndex(int32 index);\n\tstatic int32 GetNewUniquePickupIndex(int32 slot);\n\tstatic void PassTime(uint32 time);\n\tstatic bool GivePlayerGoodiesWithPickUpMI(int16 modelIndex, int playerIndex);\n\tstatic bool TestForPickupsInBubble(CVector pos, float range);\n\tstatic bool TryToMerge_WeaponType(CVector pos, eWeaponType weapon, uint8 type, uint32 quantity, bool unused);\n\tstatic void CreateSomeMoney(CVector, int);\n\tstatic void DetonateMinesHitByGunShot(CVector *vec1, CVector *vec2);\n\tstatic void RemoveUnnecessaryPickups(const CVector& center, float radius);\n\tstatic void Load(uint8 *buf, uint32 size);\n\tstatic void Save(uint8 *buf, uint32 *size);\n\n\tstatic CPickup aPickUps[NUMPICKUPS];\n\n\t// unused\n\tstatic bool bPickUpcamActivated;\n\tstatic CVehicle *pPlayerVehicle;\n\tstatic CVector StaticCamCoors;\n\tstatic uint32 StaticCamStartTime;\n\t\n\tstatic void RemoveAllPickupsOfACertainWeaponGroupWithNoAmmo(eWeaponType);\n\tstatic CPickup *FindPickUpForThisObject(CEntity*);\n};\n\nextern uint16 AmmoForWeapon[WEAPONTYPE_TOTALWEAPONS + 1];\nextern uint16 AmmoForWeapon_OnStreet[WEAPONTYPE_TOTALWEAPONS + 1];\nextern uint16 CostOfWeapon[WEAPONTYPE_TOTALWEAPONS + 3];\n\nextern int32 CollectPickupBuffer;\n\nenum ePacmanPickupType\n{\n\tPACMAN_NONE,\n\tPACMAN_SCRAMBLE,\n\tPACMAN_RACE,\n};\n\nclass CPacManPickup\n{\npublic:\n\tCVector m_vecPosn;\n\tCObject *m_pObject;\n\tuint8 m_eType;\n\n\tvoid Update();\n};\n\nclass CPacManPickups\n{\n\tfriend class CPacManPickup;\n\n\tstatic CPacManPickup aPMPickUps[NUMPACMANPICKUPS];\n\tstatic CVector LastPickUpCoors;\n\tstatic int PillsEatenInRace;\n\tstatic bool bPMActive;\npublic:\n\tstatic void Init(void);\n\tstatic void Update(void);\n\tstatic void GeneratePMPickUps(CVector, float, int16, uint8);\n\tstatic void GeneratePMPickUpsForRace(int32);\n\tstatic void GenerateOnePMPickUp(CVector);\n\tstatic void Render(void);\n\tstatic void StartPacManRace(int32);\n\tstatic void StartPacManRecord(void);\n\tstatic uint32 QueryPowerPillsEatenInRace(void);\n\tstatic void ResetPowerPillsEatenInRace(void);\n\tstatic void ClearPMPickUps(void);\n\tstatic void CleanUpPacManStuff(void);\n\tstatic void StartPacManScramble(CVector, float, int16);\n\tstatic uint32 QueryPowerPillsCarriedByPlayer(void);\n\tstatic void ResetPowerPillsCarriedByPlayer(void);\n\n};\n"
  },
  {
    "path": "src/control/PowerPoints.cpp",
    "content": "#include \"common.h\"\n#include \"PowerPoints.h\"\n\n// Some cut beta feature\n\nvoid CPowerPoint::Update()\n{}\n\nvoid CPowerPoints::Init()\n{}\n\nvoid CPowerPoints::Update()\n{}\n\nvoid CPowerPoints::GenerateNewOne(float, float, float, float, float, float, uint8)\n{}\n\nvoid CPowerPoints::Save(uint8**, uint32*)\n{}\n\nvoid CPowerPoints::Load(uint8*, uint32)\n{}"
  },
  {
    "path": "src/control/PowerPoints.h",
    "content": "#pragma once\n\nenum\n{\n\tPOWERPOINT_NONE = 0,\n\tPOWERPOINT_HEALTH,\n\tPOWERPOINT_HIDEOUT_INDUSTRIAL,\n\tPOWERPOINT_HIDEOUT_COMMERCIAL,\n\tPOWERPOINT_HIDEOUT_SUBURBAN\n};\n\nclass CPowerPoint\n{\npublic:\n\tvoid Update();\n};\n\nclass CPowerPoints\n{\npublic:\n\tstatic void Init();\n\tstatic void Update();\n\tstatic void GenerateNewOne(float, float, float, float, float, float, uint8);\n\tstatic void Save(uint8**, uint32*);\n\tstatic void Load(uint8*, uint32);\n};"
  },
  {
    "path": "src/control/Record.cpp",
    "content": "#include \"common.h\"\n\n#include \"Record.h\"\n\n#include \"FileMgr.h\"\n#include \"Pad.h\"\n#include \"Pools.h\"\n#include \"Streaming.h\"\n#include \"Timer.h\"\n#include \"VehicleModelInfo.h\"\n#include \"World.h\"\n\nuint16 CRecordDataForGame::RecordingState;\n\nvoid CRecordDataForGame::Init(void)\n{\n\tRecordingState = STATE_NONE;\n}\n\nvoid CRecordDataForGame::SaveOrRetrieveDataForThisFrame(void)\n{\n}\n\nuint8* CRecordDataForGame::PackCurrentPadValues(uint8* buf, CControllerState* os, CControllerState* ns)\n{\n\treturn nil;\n}\n\nuint8* CRecordDataForGame::UnPackCurrentPadValues(uint8* buf, uint8 total, CControllerState* state)\n{\n\treturn nil;\n}\n\nuint16 CRecordDataForGame::CalcGameChecksum(void)\n{\n\treturn 0;\n}\n\nuint8 CRecordDataForChase::Status;\n\nvoid CRecordDataForChase::Init(void)\n{\n\tStatus = STATE_NONE;\n}\n\nvoid CRecordDataForChase::SaveOrRetrieveDataForThisFrame(void)\n{\n}\n\nvoid CRecordDataForChase::SaveOrRetrieveCarPositions(void)\n{\n}\n\nvoid CRecordDataForChase::StoreInfoForCar(CAutomobile* pCar, CCarStateEachFrame* pState)\n{\n}\n\nvoid CRecordDataForChase::RestoreInfoForMatrix(CMatrix& matrix, CCarStateEachFrame* pState)\n{\n}\n\nvoid CRecordDataForChase::RestoreInfoForCar(CAutomobile* pCar, CCarStateEachFrame* pState, bool stop)\n{\n}\n\nvoid CRecordDataForChase::ProcessControlCars(void)\n{\n}\n\nbool CRecordDataForChase::ShouldThisPadBeLeftAlone(uint8 pad)\n{\n\treturn false;\n}\n\nvoid CRecordDataForChase::GiveUsACar(int32 mi, CVector pos, float angle, CAutomobile** ppCar, uint8 colour1, uint8 colour2)\n{\n}\n\nvoid RemoveUnusedCollision(void)\n{\n}\n\nvoid CRecordDataForChase::StartChaseScene(float startTime)\n{\n}\n\nvoid CRecordDataForChase::CleanUpChaseScene(void)\n{\n}\n\nvoid CRecordDataForChase::SetUpCarsForChaseScene(void)\n{\n}\n\nvoid CRecordDataForChase::CleanUpCarsForChaseScene(void)\n{\n}\n\nvoid CRecordDataForChase::RemoveCarFromChase(int32 i)\n{\n}\n\nCVehicle* CRecordDataForChase::TurnChaseCarIntoScriptCar(int32 i)\n{\n\treturn nil;\n}\n\n"
  },
  {
    "path": "src/control/Record.h",
    "content": "#pragma once\n\nclass CAutomobile;\nclass CVehicle;\nclass CControllerState;\n\nclass CCarStateEachFrame\n{\npublic:\n\tint16 velX;\n\tint16 velY;\n\tint16 velZ;\n\tint8 rightX;\n\tint8 rightY;\n\tint8 rightZ;\n\tint8 forwardX;\n\tint8 forwardY;\n\tint8 forwardZ;\n\tint8 wheel;\n\tint8 gas;\n\tint8 brake;\n\tbool handbrake;\n\tCVector pos;\n};\n\nextern char gString[256];\n\nclass CRecordDataForChase\n{\n\tenum {\n\t\tNUM_CHASE_CARS = 20\n\t};\n\tenum {\n\t\tSTATE_NONE = 0,\n\t\tSTATE_RECORD = 1,\n\t\tSTATE_PLAYBACK_INIT = 2,\n\t\tSTATE_PLAYBACK = 3,\n\t\tSTATE_PLAYBACK_BEFORE_RECORDING = 4\n\t};\n\tstatic uint8 Status;\n\tstatic int PositionChanges;\n\tstatic uint8 CurrentCar;\n\tstatic CAutomobile*pChaseCars[NUM_CHASE_CARS];\n\tstatic float AnimTime;\n\tstatic uint32 AnimStartTime;\n\tstatic CCarStateEachFrame* pBaseMemForCar[NUM_CHASE_CARS];\n\tstatic float TimeMultiplier;\n\tstatic int FId2;\npublic:\n\n\tstatic bool IsRecording(void) { return Status == STATE_RECORD; }\n\n\tstatic void Init(void);\n\tstatic void SaveOrRetrieveDataForThisFrame(void);\n\tstatic void SaveOrRetrieveCarPositions(void);\n\tstatic void StoreInfoForCar(CAutomobile*, CCarStateEachFrame*);\n\tstatic void RestoreInfoForMatrix(CMatrix&, CCarStateEachFrame*);\n\tstatic void RestoreInfoForCar(CAutomobile*, CCarStateEachFrame*, bool);\n\tstatic void ProcessControlCars(void);\n\tstatic bool ShouldThisPadBeLeftAlone(uint8 pad);\n\tstatic void GiveUsACar(int32, CVector, float, CAutomobile**, uint8, uint8);\n\tstatic void StartChaseScene(float);\n\tstatic void CleanUpChaseScene(void);\n\tstatic void SetUpCarsForChaseScene(void);\n\tstatic void CleanUpCarsForChaseScene(void);\n\tstatic void RemoveCarFromChase(int32);\n\tstatic CVehicle* TurnChaseCarIntoScriptCar(int32);\n\n};\n\nstruct tGameBuffer\n{\n\tfloat m_fTimeStep;\n\tuint32 m_nTimeInMilliseconds;\n\tuint8 m_nSizeOfPads[2];\n\tuint16 m_nChecksum;\n\tuint8 m_ControllerBuffer[116];\n};\n\nclass CRecordDataForGame\n{\n\tenum {\n\t\tSTATE_NONE = 0,\n\t\tSTATE_RECORD = 1,\n\t\tSTATE_PLAYBACK = 2,\n\t};\n\tstatic uint16 RecordingState;\n\tstatic uint8* pDataBuffer;\n\tstatic uint8* pDataBufferPointer;\n\tstatic int FId;\n\tstatic tGameBuffer pDataBufferForFrame;\n\npublic:\n\tstatic bool IsRecording() { return RecordingState == STATE_RECORD; }\n\tstatic bool IsPlayingBack() { return RecordingState == STATE_PLAYBACK; }\n\n\tstatic void SaveOrRetrieveDataForThisFrame(void);\n\tstatic void Init(void);\n\nprivate:\n\tstatic uint16 CalcGameChecksum(void);\n\tstatic uint8* PackCurrentPadValues(uint8*, CControllerState*, CControllerState*);\n\tstatic uint8* UnPackCurrentPadValues(uint8*, uint8, CControllerState*);\n};\n"
  },
  {
    "path": "src/control/Remote.cpp",
    "content": "#include \"common.h\"\n\n#include \"Automobile.h\"\n#include \"CarCtrl.h\"\n#include \"Camera.h\"\n#include \"Remote.h\"\n#include \"Timer.h\"\n#include \"World.h\"\n#include \"PlayerInfo.h\"\n#include \"Vehicle.h\"\n\nvoid\nCRemote::GivePlayerRemoteControlledCar(float x, float y, float z, float rot, uint16 model)\n{\n\tCAutomobile *car = new CAutomobile(model, MISSION_VEHICLE);\n\tbool found;\n\n\tz = car->GetDistanceFromCentreOfMassToBaseOfModel() + CWorld::FindGroundZFor3DCoord(x, y, z + 2.0f, &found);\n\n\tcar->GetMatrix().SetRotateZOnly(rot);\n\tcar->SetPosition(x, y, z);\n\tcar->SetStatus(STATUS_PLAYER_REMOTE);\n\tcar->bIsLocked = true;\n\n\tCCarCtrl::JoinCarWithRoadSystem(car);\n\tcar->AutoPilot.m_nCarMission = MISSION_NONE;\n\tcar->AutoPilot.m_nTempAction = TEMPACT_NONE;\n\tcar->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_STOP_FOR_CARS;\n\tcar->AutoPilot.m_nCruiseSpeed = car->AutoPilot.m_fMaxTrafficSpeed = 9.0f;\n\tcar->AutoPilot.m_nNextLane = car->AutoPilot.m_nCurrentLane = 0;\n\tcar->bEngineOn = true;\n\tCWorld::Add(car);\n\tif (FindPlayerVehicle() != nil) \n\t\tFindPlayerVehicle()->SetStatus(STATUS_PLAYER_DISABLED);\n\n\tCWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle = car;\n\tCWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle->RegisterReference((CEntity**)&CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle);\n\tif (car->GetVehicleAppearance() == VEHICLE_APPEARANCE_PLANE || car->GetVehicleAppearance() == VEHICLE_APPEARANCE_HELI) {\n\t\tTheCamera.TakeControl(car, CCam::MODE_CAM_ON_A_STRING, INTERPOLATION, CAMCONTROL_SCRIPT);\n\t\tTheCamera.SetZoomValueCamStringScript(0);\n\t} else\n\t\tTheCamera.TakeControl(car, CCam::MODE_BEHINDCAR, INTERPOLATION, CAMCONTROL_SCRIPT);\n}\n\nvoid\nCRemote::TakeRemoteControlledCarFromPlayer(bool blowUp)\n{\n\tif (CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle->VehicleCreatedBy == MISSION_VEHICLE) {\n\t\tCWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle->VehicleCreatedBy = RANDOM_VEHICLE;\n\t\tCCarCtrl::NumMissionCars--;\n\t\tCCarCtrl::NumRandomCars++;\n\t}\n\tCWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle->bIsLocked = false;\n\tCWorld::Players[CWorld::PlayerInFocus].m_nTimeLostRemoteCar = CTimer::GetTimeInMilliseconds();\n\tCWorld::Players[CWorld::PlayerInFocus].m_bInRemoteMode = true;\n\tCWorld::Players[CWorld::PlayerInFocus].field_D5 = blowUp;\n\tCWorld::Players[CWorld::PlayerInFocus].field_D6 = true;\n}\n"
  },
  {
    "path": "src/control/Remote.h",
    "content": "#pragma once\n\nclass CRemote\n{\npublic:\n\tstatic void GivePlayerRemoteControlledCar(float, float, float, float, uint16);\n\tstatic void TakeRemoteControlledCarFromPlayer(bool blowUp = true);\n};\n"
  },
  {
    "path": "src/control/Replay.cpp",
    "content": "#include \"common.h\"\n#ifdef GTA_REPLAY\n#include \"AnimBlendAssocGroup.h\"\n#include \"AnimBlendAssociation.h\"\n#include \"Bike.h\"\n#include \"Boat.h\"\n#include \"SpecialFX.h\"\n#include \"CarCtrl.h\"\n#include \"CivilianPed.h\"\n#include \"CopPed.h\"\n#include \"Wanted.h\"\n#include \"Clock.h\"\n#include \"DMAudio.h\"\n#include \"Draw.h\"\n#include \"Explosion.h\"\n#include \"FileMgr.h\"\n#include \"Fire.h\"\n#include \"Frontend.h\"\n#include \"Garages.h\"\n#include \"Heli.h\"\n#include \"main.h\"\n#include \"Matrix.h\"\n#include \"ModelIndices.h\"\n#include \"ModelInfo.h\"\n#include \"Object.h\"\n#include \"Pad.h\"\n#include \"Particle.h\"\n#include \"PedAttractor.h\"\n#include \"Phones.h\"\n#include \"Pickups.h\"\n#include \"Plane.h\"\n#include \"Pools.h\"\n#include \"Population.h\"\n#include \"Projectile.h\"\n#include \"ProjectileInfo.h\"\n#include \"Replay.h\"\n#include \"References.h\"\n#include \"Pools.h\"\n#include \"RpAnimBlend.h\"\n#include \"RwHelper.h\"\n#include \"CutsceneMgr.h\"\n#include \"Skidmarks.h\"\n#include \"Stinger.h\"\n#include \"Streaming.h\"\n#include \"Timer.h\"\n#include \"Train.h\"\n#include \"Weather.h\"\n#include \"Zones.h\"\n#include \"Font.h\"\n#include \"Text.h\"\n#include \"Camera.h\"\n#include \"Radar.h\"\n#include \"Fluff.h\"\n#include \"WaterCreatures.h\"\n\nuint8 CReplay::Mode;\nCAddressInReplayBuffer CReplay::Record;\nCAddressInReplayBuffer CReplay::Playback;\nuint8 *CReplay::pBuf0;\nCAutomobile *CReplay::pBuf1;\nuint8 *CReplay::pBuf2;\nCPlayerPed *CReplay::pBuf3;\nuint8 *CReplay::pBuf4;\nCCutsceneObject *CReplay::pBuf5;\nuint8 *CReplay::pBuf6;\nCPtrNode *CReplay::pBuf7;\nuint8 *CReplay::pBuf8;\nCEntryInfoNode *CReplay::pBuf9;\nuint8 *CReplay::pBuf10;\nCDummyPed *CReplay::pBuf11;\nuint8 *CReplay::pRadarBlips;\nuint8 *CReplay::pStoredCam;\nuint8 *CReplay::pWorld1;\nCReference *CReplay::pEmptyReferences;\nCStoredDetailedAnimationState *CReplay::pPedAnims;\nuint8 *CReplay::pPickups;\nuint8 *CReplay::pReferences;\nuint8 CReplay::BufferStatus[NUM_REPLAYBUFFERS];\nuint8 CReplay::Buffers[NUM_REPLAYBUFFERS][REPLAYBUFFERSIZE];\nbool CReplay::bPlayingBackFromFile;\nbool CReplay::bReplayEnabled = true;\nuint32 CReplay::SlowMotion;\nuint32 CReplay::FramesActiveLookAroundCam;\nbool CReplay::bDoLoadSceneWhenDone;\nCPtrNode* CReplay::WorldPtrList;\nCPtrNode* CReplay::BigBuildingPtrList;\nCWanted CReplay::PlayerWanted;\nCPlayerInfo CReplay::PlayerInfo;\nuint32 CReplay::Time1;\nuint32 CReplay::Time2;\nuint32 CReplay::Time3;\nuint32 CReplay::Time4;\nuint32 CReplay::Frame;\nuint8 CReplay::ClockHours;\nuint8 CReplay::ClockMinutes;\nuint16 CReplay::OldWeatherType;\nuint16 CReplay::NewWeatherType;\nfloat CReplay::WeatherInterpolationValue;\nfloat CReplay::TimeStepNonClipped;\nfloat CReplay::TimeStep;\nfloat CReplay::TimeScale;\nfloat CReplay::CameraFixedX;\nfloat CReplay::CameraFixedY;\nfloat CReplay::CameraFixedZ;\nint32 CReplay::OldRadioStation;\nint8 CReplay::CameraMode;\nbool CReplay::bAllowLookAroundCam;\nfloat CReplay::LoadSceneX;\nfloat CReplay::LoadSceneY;\nfloat CReplay::LoadSceneZ;\nfloat CReplay::CameraFocusX;\nfloat CReplay::CameraFocusY;\nfloat CReplay::CameraFocusZ;\nbool CReplay::bPlayerInRCBuggy;\nfloat CReplay::fDistanceLookAroundCam;\nfloat CReplay::fBetaAngleLookAroundCam;\nfloat CReplay::fAlphaAngleLookAroundCam;\nint CReplay::ms_nNumCivMale_Stored;\nint CReplay::ms_nNumCivFemale_Stored;\nint CReplay::ms_nNumCop_Stored;\nint CReplay::ms_nNumEmergency_Stored;\nint CReplay::ms_nNumGang1_Stored;\nint CReplay::ms_nNumGang2_Stored;\nint CReplay::ms_nNumGang3_Stored;\nint CReplay::ms_nNumGang4_Stored;\nint CReplay::ms_nNumGang5_Stored;\nint CReplay::ms_nNumGang6_Stored;\nint CReplay::ms_nNumGang7_Stored;\nint CReplay::ms_nNumGang8_Stored;\nint CReplay::ms_nNumGang9_Stored;\nint CReplay::ms_nNumDummy_Stored;\nint CReplay::ms_nTotalCarPassengerPeds_Stored;\nint CReplay::ms_nTotalCivPeds_Stored;\nint CReplay::ms_nTotalGangPeds_Stored;\nint CReplay::ms_nTotalPeds_Stored;\nint CReplay::ms_nTotalMissionPeds_Stored;\nuint8* CReplay::pGarages;\nCFire* CReplay::FireArray;\nuint32 CReplay::NumOfFires;\nuint8* CReplay::paProjectileInfo;\nuint8* CReplay::paProjectiles;\nuint8 CReplay::CurrArea;\n#ifdef FIX_BUGS\nint CReplay::nHandleOfPlayerPed[NUMPLAYERS];\n#endif\n\nstatic void(*CBArray[])(CAnimBlendAssociation*, void*) =\n{\n\tnil, &CPed::PedGetupCB, &CPed::PedStaggerCB, &CPed::PedEvadeCB, &CPed::FinishDieAnimCB,\n\t&CPed::FinishedWaitCB, &CPed::FinishLaunchCB, &CPed::FinishHitHeadCB, &CPed::PedAnimGetInCB, &CPed::PedAnimDoorOpenCB,\n\t&CPed::PedAnimPullPedOutCB, &CPed::PedAnimDoorCloseCB, &CPed::PedSetInCarCB, &CPed::PedSetOutCarCB, &CPed::PedAnimAlignCB,\n\t&CPed::PedSetDraggedOutCarCB, &CPed::PedAnimStepOutCarCB, &CPed::PedSetInTrainCB,\n#ifdef GTA_TRAIN\n\t&CPed::PedSetOutTrainCB,\n#endif\n\t&CPed::FinishedAttackCB,\n\t&CPed::FinishFightMoveCB, &PhonePutDownCB, &PhonePickUpCB, &CPed::PedAnimDoorCloseRollingCB, &CPed::FinishJumpCB,\n\t&CPed::PedLandCB, &CPed::RestoreHeadingRateCB, &CPed::PedSetQuickDraggedOutCarPositionCB, &CPed::PedSetDraggedOutCarPositionCB,\n\t&CPed::PedSetPreviousStateCB, &CPed::FinishedReloadCB, &CPed::PedSetGetInCarPositionCB,\n\t&CPed::PedAnimShuffleCB, &CPed::DeleteSunbatheIdleAnimCB, &StartTalkingOnMobileCB, &FinishTalkingOnMobileCB\n};\n\nstatic uint8 FindCBFunctionID(void(*f)(CAnimBlendAssociation*, void*))\n{\n\tfor (int i = 0; i < sizeof(CBArray) / sizeof(*CBArray); i++){\n\t\tif (CBArray[i] == f)\n\t\t\treturn i;\n\t}\n\n\treturn 0;\n}\n\nstatic void(*FindCBFunction(uint8 id))(CAnimBlendAssociation*, void*)\n{\n\treturn CBArray[id];\n}\n\nstatic void ApplyPanelDamageToCar(uint32 panels, CAutomobile* vehicle, bool flying)\n{\n\tif(vehicle->Damage.GetPanelStatus(VEHPANEL_FRONT_LEFT) != CDamageManager::GetPanelStatus(panels, VEHPANEL_FRONT_LEFT)){\n\t\tvehicle->Damage.SetPanelStatus(VEHPANEL_FRONT_LEFT, CDamageManager::GetPanelStatus(panels, VEHPANEL_FRONT_LEFT));\n\t\tvehicle->SetPanelDamage(CAR_WING_LF, VEHPANEL_FRONT_LEFT, flying);\n\t}\n\tif(vehicle->Damage.GetPanelStatus(VEHPANEL_FRONT_RIGHT) != CDamageManager::GetPanelStatus(panels, VEHPANEL_FRONT_RIGHT)){\n\t\tvehicle->Damage.SetPanelStatus(VEHPANEL_FRONT_RIGHT, CDamageManager::GetPanelStatus(panels, VEHPANEL_FRONT_RIGHT));\n\t\tvehicle->SetPanelDamage(CAR_WING_RF, VEHPANEL_FRONT_RIGHT, flying);\n\t}\n\tif(vehicle->Damage.GetPanelStatus(VEHPANEL_REAR_LEFT) != CDamageManager::GetPanelStatus(panels, VEHPANEL_REAR_LEFT)){\n\t\tvehicle->Damage.SetPanelStatus(VEHPANEL_REAR_LEFT, CDamageManager::GetPanelStatus(panels, VEHPANEL_REAR_LEFT));\n\t\tvehicle->SetPanelDamage(CAR_WING_LR, VEHPANEL_REAR_LEFT, flying);\n\t}\n\tif(vehicle->Damage.GetPanelStatus(VEHPANEL_REAR_RIGHT) != CDamageManager::GetPanelStatus(panels, VEHPANEL_REAR_RIGHT)){\n\t\tvehicle->Damage.SetPanelStatus(VEHPANEL_REAR_RIGHT, CDamageManager::GetPanelStatus(panels, VEHPANEL_REAR_RIGHT));\n\t\tvehicle->SetPanelDamage(CAR_WING_RR, VEHPANEL_REAR_RIGHT, flying);\n\t}\n\tif(vehicle->Damage.GetPanelStatus(VEHPANEL_WINDSCREEN) != CDamageManager::GetPanelStatus(panels, VEHPANEL_WINDSCREEN)){\n\t\tvehicle->Damage.SetPanelStatus(VEHPANEL_WINDSCREEN, CDamageManager::GetPanelStatus(panels, VEHPANEL_WINDSCREEN));\n\t\tvehicle->SetPanelDamage(CAR_WINDSCREEN, VEHPANEL_WINDSCREEN, flying);\n\t}\n\tif(vehicle->Damage.GetPanelStatus(VEHBUMPER_FRONT) != CDamageManager::GetPanelStatus(panels, VEHBUMPER_FRONT)){\n\t\tvehicle->Damage.SetPanelStatus(VEHBUMPER_FRONT, CDamageManager::GetPanelStatus(panels, VEHBUMPER_FRONT));\n\t\tvehicle->SetPanelDamage(CAR_BUMP_FRONT, VEHBUMPER_FRONT, flying);\n\t}\n\tif(vehicle->Damage.GetPanelStatus(VEHBUMPER_REAR) != CDamageManager::GetPanelStatus(panels, VEHBUMPER_REAR)){\n\t\tvehicle->Damage.SetPanelStatus(VEHBUMPER_REAR, CDamageManager::GetPanelStatus(panels, VEHBUMPER_REAR));\n\t\tvehicle->SetPanelDamage(CAR_BUMP_REAR, VEHBUMPER_REAR, flying);\n\t}\n}\n\nvoid PrintElementsInPtrList(void) \n{\n\tfor (CPtrNode* node = CWorld::GetBigBuildingList(LEVEL_GENERIC).first; node; node = node->next) {\n\t\t/* Most likely debug print was present here */\n\t}\n}\n\nvoid CReplay::Init(void)\n{\n\tpBuf0 = nil;\n\tpBuf1 = nil;\n\tpBuf2 = nil;\n\tpBuf3 = nil;\n\tpBuf4 = nil;\n\tpBuf5 = nil;\n\tpBuf6 = nil;\n\tpBuf7 = nil;\n\tpBuf8 = nil;\n\tpBuf9 = nil;\n\tpBuf10 = nil;\n\tpBuf11 = nil;\n\tpRadarBlips = nil;\n\tpStoredCam = nil;\n\tpWorld1 = nil;\n\tpEmptyReferences = nil;\n\tpPedAnims = nil;\n\tpPickups = nil;\n\tpReferences = nil;\n\tMode = MODE_RECORD;\n\tPlayback.m_nOffset = 0;\n\tPlayback.m_pBase = nil;\n\tPlayback.m_bSlot = 0;\n\tRecord.m_nOffset = 0;\n\tRecord.m_pBase = nil;\n\tRecord.m_bSlot = 0;\n\tfor (int i = 0; i < NUM_REPLAYBUFFERS; i++)\n\t\tBufferStatus[i] = REPLAYBUFFER_UNUSED;\n\tRecord.m_bSlot = 0;\n\tRecord.m_pBase = Buffers[0];\n\tBufferStatus[0] = REPLAYBUFFER_RECORD;\n\tBuffers[0][Record.m_nOffset] = REPLAYPACKET_END;\n\tbPlayingBackFromFile = false;\n\tbReplayEnabled = true;\n\tSlowMotion = 1;\n\tFramesActiveLookAroundCam = 0;\n\tbDoLoadSceneWhenDone = false;\n\tMarkEverythingAsNew();\n}\n\nvoid CReplay::DisableReplays(void)\n{\n\tbReplayEnabled = false;\n}\n\nvoid CReplay::EnableReplays(void)\n{\n\tbReplayEnabled = true;\n}\n\nvoid PlayReplayFromHD(void);\nvoid CReplay::Update(void)\n{\n\tif (CCutsceneMgr::IsCutsceneProcessing() || CPad::GetPad(0)->ArePlayerControlsDisabled() || CScriptPaths::IsOneActive() || FrontEndMenuManager.GetIsMenuActive()) {\n\t\tInit();\n\t\treturn;\n\t}\n\tswitch (Mode){\n\tcase MODE_RECORD:\n\t\tRecordThisFrame();\n\t\tbreak;\n\tcase MODE_PLAYBACK:\n\t\tPlaybackThisFrame();\n\t\tbreak;\n\t}\n\tif (CDraw::FadeValue || !bReplayEnabled)\n\t\treturn;\n\tif (Mode == MODE_PLAYBACK){\n\t\tif (CPad::GetPad(0)->GetFJustDown(0))\n\t\t\tFinishPlayback();\n\t}\n\telse if (Mode == MODE_RECORD){\n\t\tif (CPad::GetPad(0)->GetFJustDown(0))\n\t\t\tTriggerPlayback(REPLAYCAMMODE_ASSTORED, 0.0f, 0.0f, 0.0f, false);\n\t\tif (CPad::GetPad(0)->GetFJustDown(1))\n\t\t\tSaveReplayToHD();\n\t\tif (CPad::GetPad(0)->GetFJustDown(2))\n\t\t\tPlayReplayFromHD();\n#ifdef USE_BETA_REPLAY_MODE\n\t\tif (CPad::GetPad(0)->GetFJustDown(3))\n\t\t\tTriggerPlaybackLastCoupleOfSeconds(5000, REPLAYCAMMODE_TOPDOWN, 0.0f, 0.0f, 0.0f, 4);\n#endif\n\t}\n}\n\nvoid CReplay::RecordThisFrame(void)\n{\n\tuint32 memory_required = sizeof(tGeneralPacket) + sizeof(tClockPacket) + sizeof(tWeatherPacket) + sizeof(tTimerPacket) + sizeof(tMiscPacket);\n\tCVehiclePool* vehiclesT = CPools::GetVehiclePool();\n\tfor (int i = 0; i < vehiclesT->GetSize(); i++) {\n\t\tCVehicle* v = vehiclesT->GetSlot(i);\n\t\tif (v && v->m_rwObject && v->GetModelIndex() != MI_AIRTRAIN && v->GetModelIndex() != MI_TRAIN) {\n\t\t\tif (v->IsBike())\n\t\t\t\tmemory_required += sizeof(tBikeUpdatePacket);\n\t\t\telse\n\t\t\t\tmemory_required += sizeof(tVehicleUpdatePacket);\n\t\t}\n\t}\n\tCPedPool* pedsT = CPools::GetPedPool();\n\tfor (int i = 0; i < pedsT->GetSize(); i++) {\n\t\tCPed* p = pedsT->GetSlot(i);\n\t\tif (!p || !p->m_rwObject)\n\t\t\tcontinue;\n\t\tif (!p->bHasAlreadyBeenRecorded) {\n\t\t\tmemory_required += sizeof(tPedHeaderPacket);\n\t\t}\n\t\tmemory_required += sizeof(tPedUpdatePacket);\n\t}\n\tfor (uint8 i = 0; i < NUMBULLETTRACES; i++) {\n\t\tif (!CBulletTraces::aTraces[i].m_bInUse)\n\t\t\tcontinue;\n\t\tmemory_required += sizeof(tBulletTracePacket);\n\t}\n\tmemory_required += sizeof(tEndOfFramePacket) + 1; // 1 for Record.m_pBase[Record.m_nOffset] = REPLAYPACKET_END;\n\tif (Record.m_nOffset + memory_required > REPLAYBUFFERSIZE - 16)\n\t\tGoToNextBlock();\n\ttGeneralPacket* general = (tGeneralPacket*)&Record.m_pBase[Record.m_nOffset];\n\tgeneral->type = REPLAYPACKET_GENERAL;\n\tgeneral->camera_pos.CopyOnlyMatrix(TheCamera.GetMatrix());\n\tgeneral->player_pos = FindPlayerCoors();\n\tgeneral->in_rcvehicle = CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle ? true : false;\n\tRecord.m_nOffset += sizeof(*general);\n\ttClockPacket* clock = (tClockPacket*)&Record.m_pBase[Record.m_nOffset];\n\tclock->type = REPLAYPACKET_CLOCK;\n\tclock->hours = CClock::GetHours();\n\tclock->minutes = CClock::GetMinutes();\n\tRecord.m_nOffset += sizeof(*clock);\n\ttWeatherPacket* weather = (tWeatherPacket*)&Record.m_pBase[Record.m_nOffset];\n\tweather->type = REPLAYPACKET_WEATHER;\n\tweather->old_weather = CWeather::OldWeatherType;\n\tweather->new_weather = CWeather::NewWeatherType;\n\tweather->interpolation = CWeather::InterpolationValue;\n\tRecord.m_nOffset += sizeof(*weather);\n\ttTimerPacket* timer = (tTimerPacket*)&Record.m_pBase[Record.m_nOffset];\n\ttimer->type = REPLAYPACKET_TIMER;\n\ttimer->timer = CTimer::GetTimeInMilliseconds();\n\tRecord.m_nOffset += sizeof(*timer);\n\tCVehiclePool* vehicles = CPools::GetVehiclePool();\n\tfor (int i = 0; i < vehicles->GetSize(); i++){\n\t\tCVehicle* v = vehicles->GetSlot(i);\n\t\tif (v && v->m_rwObject && v->GetModelIndex() != MI_AIRTRAIN && v->GetModelIndex() != MI_TRAIN) {\n\t\t\tif (v->IsBike())\n\t\t\t\tStoreBikeUpdate(v, i);\n\t\t\telse\n\t\t\t\tStoreCarUpdate(v, i);\n\t\t}\n\t}\n\tCPedPool* peds = CPools::GetPedPool();\n\tfor (int i = 0; i < peds->GetSize(); i++) {\n\t\tCPed* p = peds->GetSlot(i);\n\t\tif (!p || !p->m_rwObject)\n\t\t\tcontinue;\n\t\tif (!p->bHasAlreadyBeenRecorded){\n\t\t\ttPedHeaderPacket* ph = (tPedHeaderPacket*)&Record.m_pBase[Record.m_nOffset];\n\t\t\tph->type = REPLAYPACKET_PED_HEADER;\n\t\t\tph->index = i;\n\t\t\tph->mi = p->GetModelIndex();\n\t\t\tph->pedtype = p->m_nPedType;\n\t\t\tRecord.m_nOffset += sizeof(*ph);\n\t\t\tp->bHasAlreadyBeenRecorded = true;\n\t\t}\n\t\tStorePedUpdate(p, i);\n\t}\n\tfor (uint8 i = 0; i < NUMBULLETTRACES; i++){\n\t\tif (!CBulletTraces::aTraces[i].m_bInUse)\n\t\t\tcontinue;\n\t\ttBulletTracePacket* bt = (tBulletTracePacket*)&Record.m_pBase[Record.m_nOffset];\n\t\tbt->type = REPLAYPACKET_BULLET_TRACES;\n\t\tbt->index = i;\n\t\tbt->inf = CBulletTraces::aTraces[i].m_vecStartPos;\n\t\tbt->sup = CBulletTraces::aTraces[i].m_vecEndPos;\n\t\tRecord.m_nOffset += sizeof(*bt);\n\t}\n\ttMiscPacket* misc = (tMiscPacket*)&Record.m_pBase[Record.m_nOffset];\n\tmisc->type = REPLAYPACKET_MISC;\n\tmisc->cam_shake_start = TheCamera.m_uiCamShakeStart;\n\tmisc->cam_shake_strength = TheCamera.m_fCamShakeForce;\n\tmisc->cur_area = CGame::currArea;\n\tmisc->video_cam = CSpecialFX::bVideoCam;\n\tmisc->lift_cam = CSpecialFX::bLiftCam;\n\tRecord.m_nOffset += sizeof(*misc);\n\ttEndOfFramePacket* eof = (tEndOfFramePacket*)&Record.m_pBase[Record.m_nOffset];\n\teof->type = REPLAYPACKET_ENDOFFRAME;\n\tRecord.m_nOffset += sizeof(*eof);\n\tRecord.m_pBase[Record.m_nOffset] = REPLAYPACKET_END;\n}\n\nvoid CReplay::GoToNextBlock(void)\n{\n\tRecord.m_pBase[Record.m_nOffset] = REPLAYPACKET_END;\n\tBufferStatus[Record.m_bSlot] = REPLAYBUFFER_PLAYBACK;\n\tRecord.m_bSlot = (Record.m_bSlot + 1) % NUM_REPLAYBUFFERS;\n\tBufferStatus[Record.m_bSlot] = REPLAYBUFFER_RECORD;\n\tRecord.m_pBase = Buffers[Record.m_bSlot];\n\tRecord.m_nOffset = 0;\n\t*Record.m_pBase = REPLAYPACKET_END;\n\tMarkEverythingAsNew();\n}\n\nvoid CReplay::RecordParticle(tParticleType type, const CVector& vecPos, const CVector& vecDir, float fSize, const RwRGBA& color)\n{\n\tif (Record.m_nOffset > REPLAYBUFFERSIZE - 16 - sizeof(tParticlePacket))\n\t\tGoToNextBlock();\n\ttParticlePacket* pp = (tParticlePacket*)&Record.m_pBase[Record.m_nOffset];\n\tpp->type = REPLAYPACKET_PARTICLE;\n\tpp->particle_type = type;\n\tpp->pos_x = 4.0f * vecPos.x;\n\tpp->pos_y = 4.0f * vecPos.y;\n\tpp->pos_z = 4.0f * vecPos.z;\n\tpp->dir_x = 120.0f * clamp(vecDir.x, -1.0f, 1.0f);\n\tpp->dir_y = 120.0f * clamp(vecDir.y, -1.0f, 1.0f);\n\tpp->dir_z = 120.0f * clamp(vecDir.z, -1.0f, 1.0f);\n\tpp->size = fSize;\n\tpp->r = color.red;\n\tpp->g = color.green;\n\tpp->b = color.blue;\n\tpp->a = color.alpha;\n\tRecord.m_nOffset += sizeof(tParticlePacket);\n\tRecord.m_pBase[Record.m_nOffset] = REPLAYPACKET_END;\n}\n\nvoid CReplay::StorePedUpdate(CPed *ped, int id)\n{\n\ttPedUpdatePacket* pp = (tPedUpdatePacket*)&Record.m_pBase[Record.m_nOffset];\n\tpp->type = REPLAYPACKET_PED_UPDATE;\n\tpp->index = id;\n\tpp->heading = 128.0f / PI * ped->m_fRotationCur;\n\tpp->matrix.CompressFromFullMatrix(ped->GetMatrix());\n\tpp->assoc_group_id = ped->m_animGroup;\n\tpp->is_visible = ped->bIsVisible;\n\t/* \tWould be more sane to use GetJustIndex(ped->m_pMyVehicle) in following assignment */\n\tif (ped->InVehicle())\n\t\tpp->vehicle_index = (CPools::GetVehiclePool()->GetIndex(ped->m_pMyVehicle) >> 8) + 1;\n\telse\n\t\tpp->vehicle_index = 0;\n\tpp->weapon_model = ped->m_wepModelID;\n\tStorePedAnimation(ped, &pp->anim_state);\n\tRecord.m_nOffset += sizeof(tPedUpdatePacket);\n}\n\nvoid CReplay::StorePedAnimation(CPed *ped, CStoredAnimationState *state)\n{\n\tCAnimBlendAssociation* second;\n\tfloat blend_amount;\n\tCAnimBlendAssociation* main = RpAnimBlendClumpGetMainAssociation((RpClump*)ped->m_rwObject, &second, &blend_amount);\n\tif (main){\n\t\tstate->animId = main->animId;\n\t\tstate->time = 255.0f / 4.0f * clamp(main->currentTime, 0.0f, 4.0f);\n\t\tstate->speed = 255.0f / 3.0f * clamp(main->speed, 0.0f, 3.0f);\n\t\tstate->groupId = main->groupId;\n\t}else{\n\t\tstate->animId = 3;\n\t\tstate->time = 0;\n\t\tstate->speed = 85;\n\t\tstate->groupId = 0;\n\t}\n\tif (second) {\n\t\tstate->secAnimId = second->animId;\n\t\tstate->secTime = 255.0f / 4.0f * clamp(second->currentTime, 0.0f, 4.0f);\n\t\tstate->secSpeed = 255.0f / 3.0f * clamp(second->speed, 0.0f, 3.0f);\n\t\tstate->blendAmount = 255.0f / 2.0f * clamp(blend_amount, 0.0f, 2.0f);\n\t\tstate->secGroupId = second->groupId;\n\t}else{\n\t\tstate->secAnimId = 0;\n\t\tstate->secTime = 0;\n\t\tstate->secSpeed = 0;\n\t\tstate->blendAmount = 0;\n\t\tstate->secGroupId = 0;\n\t}\n\tCAnimBlendAssociation* partial = RpAnimBlendClumpGetMainPartialAssociation((RpClump*)ped->m_rwObject);\n\tif (partial) {\n\t\tstate->partAnimId = partial->animId;\n\t\tstate->partAnimTime = 255.0f / 4.0f * clamp(partial->currentTime, 0.0f, 4.0f);\n\t\tstate->partAnimSpeed = 255.0f / 3.0f * clamp(partial->speed, 0.0f, 3.0f);\n\t\tstate->partBlendAmount = 255.0f / 2.0f * clamp(partial->blendAmount, 0.0f, 2.0f);\n\t\tstate->partGroupId = partial->groupId;\n\t}else{\n\t\tstate->partAnimId = 0;\n\t\tstate->partAnimTime = 0;\n\t\tstate->partAnimSpeed = 0;\n\t\tstate->partBlendAmount = 0;\n\t\tstate->partGroupId = 0;\n\t}\n}\n\nvoid CReplay::StoreDetailedPedAnimation(CPed *ped, CStoredDetailedAnimationState *state)\n{\n\tfor (int i = 0; i < NUM_MAIN_ANIMS_IN_REPLAY; i++){\n\t\tCAnimBlendAssociation* assoc = RpAnimBlendClumpGetMainAssociation_N((RpClump*)ped->m_rwObject, i);\n\t\tif (assoc){\n\t\t\tstate->aAnimId[i] = assoc->animId;\n\t\t\tstate->aCurTime[i] = 255.0f / 4.0f * clamp(assoc->currentTime, 0.0f, 4.0f);\n\t\t\tstate->aSpeed[i] = 255.0f / 3.0f * clamp(assoc->speed, 0.0f, 3.0f);\n\t\t\tstate->aBlendAmount[i] = 255.0f / 2.0f * clamp(assoc->blendAmount, 0.0f, 2.0f);\n\t\t\tstate->aBlendDelta[i] = 127.0f / 32.0f * clamp(assoc->blendDelta, -16.0f, 16.0f);\n\t\t\tstate->aFlags[i] = assoc->flags;\n\t\t\tstate->aGroupId[i] = assoc->groupId;\n\t\t\tif (assoc->callbackType == CAnimBlendAssociation::CB_FINISH || assoc->callbackType == CAnimBlendAssociation::CB_DELETE) {\n\t\t\t\tstate->aFunctionCallbackID[i] = FindCBFunctionID(assoc->callback);\n\t\t\t\tif (assoc->callbackType == CAnimBlendAssociation::CB_FINISH)\n\t\t\t\t\tstate->aFunctionCallbackID[i] |= 0x80;\n\t\t\t}else{\n\t\t\t\tstate->aFunctionCallbackID[i] = 0;\n\t\t\t}\n\t\t}else{\n\t\t\tstate->aAnimId[i] = ANIM_STD_NUM;\n\t\t\tstate->aCurTime[i] = 0;\n\t\t\tstate->aSpeed[i] = 85;\n\t\t\tstate->aFunctionCallbackID[i] = 0;\n\t\t\tstate->aFlags[i] = 0;\n\t\t\tstate->aGroupId[i] = 0;\n\t\t}\n\t}\n\tfor (int i = 0; i < NUM_PARTIAL_ANIMS_IN_REPLAY; i++) {\n\t\tCAnimBlendAssociation* assoc = RpAnimBlendClumpGetMainPartialAssociation_N((RpClump*)ped->m_rwObject, i);\n\t\tif (assoc) {\n\t\t\tstate->aAnimId2[i] = assoc->animId;\n\t\t\tstate->aCurTime2[i] = 255.0f / 4.0f * clamp(assoc->currentTime, 0.0f, 4.0f);\n\t\t\tstate->aSpeed2[i] = 255.0f / 3.0f * clamp(assoc->speed, 0.0f, 3.0f);\n\t\t\tstate->aBlendAmount2[i] = 255.0f / 2.0f * clamp(assoc->blendAmount, 0.0f, 2.0f);\n\t\t\tstate->aBlendDelta2[i] = 127.0f / 16.0f * clamp(assoc->blendDelta, -16.0f, 16.0f);\n\t\t\tstate->aFlags2[i] = assoc->flags;\n\t\t\tstate->aGroupId2[i] = assoc->groupId;\n\t\t\tif (assoc->callbackType == CAnimBlendAssociation::CB_FINISH || assoc->callbackType == CAnimBlendAssociation::CB_DELETE) {\n\t\t\t\tstate->aFunctionCallbackID2[i] = FindCBFunctionID(assoc->callback);\n\t\t\t\tif (assoc->callbackType == CAnimBlendAssociation::CB_FINISH)\n\t\t\t\t\tstate->aFunctionCallbackID2[i] |= 0x80;\n\t\t\t}else{\n\t\t\t\tstate->aFunctionCallbackID2[i] = 0;\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tstate->aAnimId2[i] = ANIM_STD_NUM;\n\t\t\tstate->aCurTime2[i] = 0;\n\t\t\tstate->aSpeed2[i] = 85;\n\t\t\tstate->aFunctionCallbackID2[i] = 0;\n\t\t\tstate->aFlags2[i] = 0;\n\t\t\tstate->aGroupId2[i] = 0;\n\t\t}\n\t}\n}\n\nvoid CReplay::ProcessPedUpdate(CPed *ped, float interpolation, CAddressInReplayBuffer *buffer)\n{\n\ttPedUpdatePacket *pp = (tPedUpdatePacket*)&buffer->m_pBase[buffer->m_nOffset];\n\tif (!ped){\n\t\tprintf(\"Replay:Ped wasn't there\\n\");\n\t\tbuffer->m_nOffset += sizeof(tPedUpdatePacket);\n\t\treturn;\n\t}\n\tped->m_fRotationCur = pp->heading * PI / 128.0f;\n\tped->m_fRotationDest = pp->heading * PI / 128.0f;\n\tCMatrix ped_matrix;\n\tpp->matrix.DecompressIntoFullMatrix(ped_matrix);\n\tped->GetMatrix() = ped->GetMatrix() * CMatrix(1.0f - interpolation);\n\tped->GetMatrix().GetPosition() *= (1.0f - interpolation);\n\tped->GetMatrix() += CMatrix(interpolation) * ped_matrix;\n\tif (pp->vehicle_index) {\n\t\tped->m_pMyVehicle = CPools::GetVehiclePool()->GetSlot(pp->vehicle_index - 1);\n\t\tped->bInVehicle = true;\n\t}\n\telse {\n\t\tped->m_pMyVehicle = nil;\n\t\tped->bInVehicle = false;\n\t}\n\tif (pp->assoc_group_id != ped->m_animGroup) {\n\t\tped->m_animGroup = (AssocGroupId)pp->assoc_group_id;\n\t\tif (ped == FindPlayerPed())\n\t\t\t((CPlayerPed*)ped)->ReApplyMoveAnims();\n\t}\n\tped->bIsVisible = pp->is_visible;\n\tif (FramesActiveLookAroundCam && ped->m_nPedType == PEDTYPE_PLAYER1)\n\t\tped->bIsVisible = true;\n\tRetrievePedAnimation(ped, &pp->anim_state);\n\tped->RemoveWeaponModel(-1);\n\tif (pp->weapon_model != (uint16)-1) {\n\t\tif (CStreaming::HasModelLoaded(pp->weapon_model))\n\t\t\tped->AddWeaponModel(pp->weapon_model);\n\t\telse\n\t\t\tCStreaming::RequestModel(pp->weapon_model, 0);\n\t}\n\tCWorld::Remove(ped);\n\tCWorld::Add(ped);\n\tbuffer->m_nOffset += sizeof(tPedUpdatePacket);\n}\n\nbool HasAnimGroupLoaded(uint8 group)\n{\n\tCAnimBlendAssocGroup* pGroup = &CAnimManager::GetAnimAssocGroups()[group];\n\treturn pGroup->animBlock && pGroup->animBlock->isLoaded;\n}\n\nvoid CReplay::RetrievePedAnimation(CPed *ped, CStoredAnimationState *state)\n{\n\tCAnimBlendAssociation* anim1;\n\tif (state->animId <= ANIM_STD_IDLE)\n\t\tanim1 = CAnimManager::BlendAnimation(\n\t\t\t(RpClump*)ped->m_rwObject, ped->m_animGroup, (AnimationId)state->animId, 100.0f);\n\telse if (HasAnimGroupLoaded(state->groupId))\n\t\tanim1 = CAnimManager::BlendAnimation((RpClump*)ped->m_rwObject, (AssocGroupId)state->groupId, (AnimationId)state->animId, 100.0f);\n\telse\n\t\tanim1 = CAnimManager::BlendAnimation((RpClump*)ped->m_rwObject, ASSOCGRP_STD, ANIM_STD_WALK, 100.0f);\n\n\tanim1->SetCurrentTime(state->time * 4.0f / 255.0f);\n\tanim1->speed = state->speed * 3.0f / 255.0f;\n\tanim1->SetBlend(1.0f, 1.0f);\n\tanim1->callbackType = CAnimBlendAssociation::CB_NONE;\n\tif (state->blendAmount && state->secAnimId){\n\t\tfloat time = state->secTime * 4.0f / 255.0f;\n\t\tfloat speed = state->secSpeed * 3.0f / 255.0f;\n\t\tfloat blend = state->blendAmount * 2.0f / 255.0f;\n\t\tCAnimBlendAssociation* anim2 = CAnimManager::BlendAnimation(\n\t\t\t(RpClump*)ped->m_rwObject,\n\t\t\t(state->secAnimId > ANIM_STD_IDLE) ? (AssocGroupId)state->secGroupId : ped->m_animGroup,\n\t\t\t(AnimationId)state->secAnimId, 100.0f);\n\t\tanim2->SetCurrentTime(time);\n\t\tanim2->speed = speed;\n\t\tanim2->SetBlend(blend, 1.0f);\n\t\tanim2->callbackType = CAnimBlendAssociation::CB_NONE;\n\t}\n\tRpAnimBlendClumpRemoveAssociations((RpClump*)ped->m_rwObject, 0x10);\n\tif (state->partAnimId){\n\t\tfloat time = state->partAnimTime * 4.0f / 255.0f;\n\t\tfloat speed = state->partAnimSpeed * 3.0f / 255.0f;\n\t\tfloat blend = state->partBlendAmount * 2.0f / 255.0f;\n\t\tif (blend > 0.0f && state->partAnimId != ANIM_STD_IDLE && HasAnimGroupLoaded(state->partGroupId)){\n\t\t\tCAnimBlendAssociation* anim3 = CAnimManager::BlendAnimation(\n\t\t\t\t(RpClump*)ped->m_rwObject, (AssocGroupId)state->partGroupId, (AnimationId)state->partAnimId, 1000.0f);\n\t\t\tanim3->SetCurrentTime(time);\n\t\t\tanim3->speed = speed;\n\t\t\tanim3->SetBlend(blend, 0.0f);\n\t\t}\n\t}\n}\n\nvoid CReplay::RetrieveDetailedPedAnimation(CPed *ped, CStoredDetailedAnimationState *state)\n{\n\tCAnimBlendAssociation* assoc;\n\tfor (int i = 0; ((assoc = RpAnimBlendClumpGetMainAssociation_N(ped->GetClump(), i))); i++)\n\t\tassoc->SetBlend(0.0f, -1.0f);\n\tfor (int i = 0; ((assoc = RpAnimBlendClumpGetMainPartialAssociation_N(ped->GetClump(), i))); i++)\n\t\tassoc->SetBlend(0.0f, -1.0f);\n\tfor (int i = 0; i < NUM_MAIN_ANIMS_IN_REPLAY; i++) {\n\t\tif (state->aAnimId[i] == ANIM_STD_NUM)\n\t\t\tcontinue;\n\t\tCAnimBlendAssociation* anim = CAnimManager::AddAnimation(ped->GetClump(),\n\t\t\tstate->aAnimId[i] > ANIM_STD_IDLE ? (AssocGroupId)state->aGroupId[i] : ped->m_animGroup,\n\t\t\t(AnimationId)state->aAnimId[i]);\n\t\tanim->SetCurrentTime(state->aCurTime[i] * 4.0f / 255.0f);\n\t\tanim->speed = state->aSpeed[i] * 3.0f / 255.0f;\n\t\tanim->SetBlend(state->aBlendAmount[i] * 2.0f / 255.0f, state->aBlendDelta[i] * 16.0f / 127.0f);\n\t\tanim->flags = state->aFlags[i];\n\t\tuint8 callback = state->aFunctionCallbackID[i];\n\t\tif (!callback)\n\t\t\tanim->callbackType = CAnimBlendAssociation::CB_NONE;\n\t\telse if (callback & 0x80)\n\t\t\tanim->SetFinishCallback(FindCBFunction(callback & 0x7F), ped);\n\t\telse\n\t\t\tanim->SetDeleteCallback(FindCBFunction(callback & 0x7F), ped);\n\t}\n\tfor (int i = 0; i < NUM_PARTIAL_ANIMS_IN_REPLAY; i++) {\n\t\tif (state->aAnimId2[i] == ANIM_STD_NUM)\n\t\t\tcontinue;\n\t\tCAnimBlendAssociation* anim = CAnimManager::AddAnimation(ped->GetClump(),\n\t\t\tstate->aAnimId2[i] > ANIM_STD_IDLE ? (AssocGroupId)state->aGroupId2[i] : ped->m_animGroup,\n\t\t\t(AnimationId)state->aAnimId2[i]);\n\t\tanim->SetCurrentTime(state->aCurTime2[i] * 4.0f / 255.0f);\n\t\tanim->speed = state->aSpeed2[i] * 3.0f / 255.0f;\n\t\tanim->SetBlend(state->aBlendAmount2[i] * 2.0f / 255.0f, state->aBlendDelta2[i] * 16.0f / 127.0f);\n\t\tanim->flags = state->aFlags2[i];\n\t\tuint8 callback = state->aFunctionCallbackID2[i];\n\t\tif (!callback)\n\t\t\tanim->callbackType = CAnimBlendAssociation::CB_NONE;\n\t\telse if (callback & 0x80)\n\t\t\tanim->SetFinishCallback(FindCBFunction(callback & 0x7F), ped);\n\t\telse\n\t\t\tanim->SetDeleteCallback(FindCBFunction(callback & 0x7F), ped);\n\t}\n}\n\nvoid CReplay::PlaybackThisFrame(void)\n{\n\tstatic int FrameSloMo = 0;\n\tCAddressInReplayBuffer buf = Playback;\n\tif (PlayBackThisFrameInterpolation(&buf, 1.0f, nil)){\n\t\tDMAudio.SetEffectsFadeVol(127);\n\t\tDMAudio.SetMusicFadeVol(127);\n\t\treturn;\n\t}\n\tif (FrameSloMo){\n\t\tCAddressInReplayBuffer buf_sm = buf;\n\t\tif (PlayBackThisFrameInterpolation(&buf_sm, FrameSloMo * 1.0f / SlowMotion, nil)){\n\t\t\tDMAudio.SetEffectsFadeVol(127);\n\t\t\tDMAudio.SetMusicFadeVol(127);\n\t\t\treturn;\n\t\t}\n\t}\n\tFrameSloMo = (FrameSloMo + 1) % SlowMotion;\n\tif (FrameSloMo == 0)\n\t\tPlayback = buf;\n\tProcessLookAroundCam();\n\tDMAudio.SetEffectsFadeVol(0);\n\tDMAudio.SetMusicFadeVol(0);\n}\n\n// next two functions are only found in mobile version\n// most likely they were optimized out for being unused\nvoid CReplay::TriggerPlaybackLastCoupleOfSeconds(uint32 start, uint8 cam_mode, float cam_x, float cam_y, float cam_z, uint32 slomo)\n{\n\tif (Mode != MODE_RECORD)\n\t\treturn;\n\tTriggerPlayback(cam_mode, cam_x, cam_y, cam_z, true);\n\tSlowMotion = slomo;\n\tbAllowLookAroundCam = false;\n\tif (!FastForwardToTime(CTimer::GetTimeInMilliseconds() - start))\n\t\tMode = MODE_RECORD;\n}\n\nbool CReplay::FastForwardToTime(uint32 start)\n{\n\tuint32 timer = 0;\n\twhile (start > timer)\n\t\tif (PlayBackThisFrameInterpolation(&Playback, 1.0f, &timer))\n\t\t\treturn false;\n\treturn true;\n}\n\nvoid CReplay::StoreCarUpdate(CVehicle *vehicle, int id)\n{\n\ttVehicleUpdatePacket* vp = (tVehicleUpdatePacket*)&Record.m_pBase[Record.m_nOffset];\n\tvp->type = REPLAYPACKET_VEHICLE;\n\tvp->index = id;\n\tvp->matrix.CompressFromFullMatrix(vehicle->GetMatrix());\n\tvp->health = vehicle->m_fHealth / 4.0f; /* Not anticipated that health can be > 1000. */\n\tvp->acceleration = vehicle->m_fGasPedal * 100.0f;\n\tvp->panels = vehicle->IsCar() ? ((CAutomobile*)vehicle)->Damage.m_panelStatus : 0;\n\tvp->velocityX = 8000.0f * Max(-4.0f, Min(4.0f, vehicle->GetMoveSpeed().x)); /* 8000!? */\n\tvp->velocityY = 8000.0f * Max(-4.0f, Min(4.0f, vehicle->GetMoveSpeed().y));\n\tvp->velocityZ = 8000.0f * Max(-4.0f, Min(4.0f, vehicle->GetMoveSpeed().z));\n\tvp->mi = vehicle->GetModelIndex();\n\tvp->primary_color = vehicle->m_currentColour1;\n\tvp->secondary_color = vehicle->m_currentColour2;\n\tif (vehicle->GetModelIndex() == MI_RHINO)\n\t\tvp->car_gun = 128.0f / PI * ((CAutomobile*)vehicle)->m_fCarGunLR;\n\telse\n\t\tvp->wheel_state = 50.0f * vehicle->m_fSteerAngle;\n\tif (vehicle->IsCar()){\n\t\tCAutomobile* car = (CAutomobile*)vehicle;\n\t\tfor (int i = 0; i < 4; i++){\n\t\t\tvp->wheel_susp_dist[i] = 50.0f * car->m_aSuspensionSpringRatio[i];\n\t\t\tvp->wheel_rotation[i] = 128.0f / PI * car->m_aWheelRotation[i];\n\t\t}\n\t\tvp->door_angles[0] = 127.0f / PI * car->Doors[2].m_fAngle;\n\t\tvp->door_angles[1] = 127.0f / PI * car->Doors[3].m_fAngle;\n\t\tvp->door_status = 0;\n\t\tfor (int i = 0; i < 6; i++){\n\t\t\tif (car->Damage.GetDoorStatus(i) == DOOR_STATUS_MISSING)\n\t\t\t\tvp->door_status |= BIT(i);\n\t\t}\n\t}\n\tif (vehicle->GetModelIndex() == MI_SKIMMER)\n\t\tvp->skimmer_speed = 50.0f * ((CBoat*)vehicle)->m_fMovingSpeed;\n\tvp->render_scorched = vehicle->bRenderScorched;\n\tvp->vehicle_type = vehicle->m_vehType;\n\tRecord.m_nOffset += sizeof(tVehicleUpdatePacket);\n}\n\nvoid CReplay::StoreBikeUpdate(CVehicle* vehicle, int id)\n{\n\tCBike* bike = (CBike*)vehicle;\n\ttBikeUpdatePacket* vp = (tBikeUpdatePacket*)&Record.m_pBase[Record.m_nOffset];\n\tvp->type = REPLAYPACKET_BIKE;\n\tvp->index = id;\n\tvp->matrix.CompressFromFullMatrix(vehicle->GetMatrix());\n\tvp->health = vehicle->m_fHealth / 4.0f; /* Not anticipated that health can be > 1000. */\n\tvp->acceleration = vehicle->m_fGasPedal * 100.0f;\n#ifdef FIX_BUGS // originally it's undefined behaviour - different fields are copied on PC and mobile\n\tfor (int i = 0; i < 2; i++)\n\t\tvp->wheel_rotation[i] = 128.0f / PI * bike->m_aWheelRotation[i];\n\tfor (int i = 0; i < 2; i++)\n\t\tvp->wheel_rotation[i + 2] = 128.0f / PI * bike->m_aWheelSpeed[i];\n\tfor (int i = 0; i < 4; i++)\n\t\tvp->wheel_susp_dist[i] = 50.0f * bike->m_aSuspensionSpringRatio[i];\n#else\n\tfor (int i = 0; i < 4; i++) {\n\t\tvp->wheel_susp_dist[i] = 50.0f * bike->m_aSuspensionSpringRatio[i];\n\t\tvp->wheel_rotation[i] = 128.0f / PI * bike->m_aWheelRotation[i];\n\t}\n#endif\n\tvp->velocityX = 8000.0f * Max(-4.0f, Min(4.0f, vehicle->GetMoveSpeed().x)); /* 8000!? */\n\tvp->velocityY = 8000.0f * Max(-4.0f, Min(4.0f, vehicle->GetMoveSpeed().y));\n\tvp->velocityZ = 8000.0f * Max(-4.0f, Min(4.0f, vehicle->GetMoveSpeed().z));\n\tvp->mi = vehicle->GetModelIndex();\n\tvp->primary_color = vehicle->m_currentColour1;\n\tvp->secondary_color = vehicle->m_currentColour2;\n\tvp->wheel_state = 50.0f * vehicle->m_fSteerAngle;\n\tvp->lean_angle = 50.0f * bike->m_fLeanLRAngle;\n\tvp->wheel_angle = 50.0f * bike->m_fWheelAngle;\n\tRecord.m_nOffset += sizeof(tBikeUpdatePacket);\n}\n\nvoid CReplay::ProcessCarUpdate(CVehicle *vehicle, float interpolation, CAddressInReplayBuffer *buffer)\n{\n\ttVehicleUpdatePacket* vp = (tVehicleUpdatePacket*)&buffer->m_pBase[buffer->m_nOffset];\n\tif (!vehicle){\n\t\tprintf(\"Replay:Car wasn't there\");\n\t\treturn;\n\t}\n\tCMatrix vehicle_matrix;\n\tvp->matrix.DecompressIntoFullMatrix(vehicle_matrix);\n\tvehicle->GetMatrix() = vehicle->GetMatrix() * CMatrix(1.0f - interpolation);\n\tvehicle->GetMatrix().GetPosition() *= (1.0f - interpolation);\n\tvehicle->GetMatrix() += CMatrix(interpolation) * vehicle_matrix;\n\tvehicle->m_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f);\n\tvehicle->m_fHealth = 4 * vp->health;\n\tvehicle->m_fGasPedal = vp->acceleration / 100.0f;\n\tif (vehicle->IsCar())\n\t\tApplyPanelDamageToCar(vp->panels, (CAutomobile*)vehicle, true);\n\tvehicle->m_vecMoveSpeed = CVector(vp->velocityX / 8000.0f, vp->velocityY / 8000.0f, vp->velocityZ / 8000.0f);\n\tif (vehicle->GetModelIndex() == MI_RHINO) {\n\t\t((CAutomobile*)vehicle)->m_fCarGunLR = vp->car_gun * PI / 128.0f;\n\t\tvehicle->m_fSteerAngle = 0.0f;\n\t}else{\n\t\tvehicle->m_fSteerAngle = vp->wheel_state / 50.0f;\n\t}\n\tif (vehicle->IsCar()) {\n\t\tCAutomobile* car = (CAutomobile*)vehicle;\n\t\tfor (int i = 0; i < 4; i++) {\n\t\t\tcar->m_aSuspensionSpringRatio[i] = vp->wheel_susp_dist[i] / 50.0f;\n\t\t\tcar->m_aWheelRotation[i] = vp->wheel_rotation[i] * PI / 128.0f;\n\t\t}\n\t\tcar->Doors[DOOR_FRONT_LEFT].m_fAngle = car->Doors[DOOR_FRONT_LEFT].m_fPrevAngle = vp->door_angles[0] * PI / 127.0f;\n\t\tcar->Doors[DOOR_FRONT_RIGHT].m_fAngle = car->Doors[DOOR_FRONT_RIGHT].m_fPrevAngle = vp->door_angles[1] * PI / 127.0f;\n\t\tif (vp->door_angles[0])\n\t\t\tcar->Damage.SetDoorStatus(DOOR_FRONT_LEFT, DOOR_STATUS_SWINGING);\n\t\tif (vp->door_angles[1])\n\t\t\tcar->Damage.SetDoorStatus(DOOR_FRONT_RIGHT, DOOR_STATUS_SWINGING);\n\t\tif (vp->door_status & 1 && car->Damage.GetDoorStatus(DOOR_BONNET) != DOOR_STATUS_MISSING) {\n\t\t\tcar->Damage.SetDoorStatus(DOOR_BONNET, DOOR_STATUS_MISSING);\n\t\t\tcar->SetDoorDamage(CAR_BONNET, DOOR_BONNET, true);\n\t\t}\n\t\tif (vp->door_status & 2 && car->Damage.GetDoorStatus(DOOR_BOOT) != DOOR_STATUS_MISSING) {\n\t\t\tcar->Damage.SetDoorStatus(DOOR_BOOT, DOOR_STATUS_MISSING);\n\t\t\tcar->SetDoorDamage(CAR_BOOT, DOOR_BOOT, true);\n\t\t}\n\t\tif (vp->door_status & 4 && car->Damage.GetDoorStatus(DOOR_FRONT_LEFT) != DOOR_STATUS_MISSING) {\n\t\t\tcar->Damage.SetDoorStatus(DOOR_FRONT_LEFT, DOOR_STATUS_MISSING);\n\t\t\tcar->SetDoorDamage(CAR_DOOR_LF, DOOR_FRONT_LEFT, true);\n\t\t}\n\t\tif (vp->door_status & 8 && car->Damage.GetDoorStatus(DOOR_FRONT_RIGHT) != DOOR_STATUS_MISSING) {\n\t\t\tcar->Damage.SetDoorStatus(DOOR_FRONT_RIGHT, DOOR_STATUS_MISSING);\n\t\t\tcar->SetDoorDamage(CAR_DOOR_RF, DOOR_FRONT_RIGHT, true);\n\t\t}\n\t\tif (vp->door_status & 0x10 && car->Damage.GetDoorStatus(DOOR_REAR_LEFT) != DOOR_STATUS_MISSING) {\n\t\t\tcar->Damage.SetDoorStatus(DOOR_REAR_LEFT, DOOR_STATUS_MISSING);\n\t\t\tcar->SetDoorDamage(CAR_DOOR_LR, DOOR_REAR_LEFT, true);\n\t\t}\n\t\tif (vp->door_status & 0x20 && car->Damage.GetDoorStatus(DOOR_REAR_RIGHT) != DOOR_STATUS_MISSING) {\n\t\t\tcar->Damage.SetDoorStatus(DOOR_REAR_RIGHT, DOOR_STATUS_MISSING);\n\t\t\tcar->SetDoorDamage(CAR_DOOR_RR, DOOR_REAR_RIGHT, true);\n\t\t}\n\t}\n\tvehicle->bEngineOn = true;\n\tif (vehicle->IsCar())\n\t\t((CAutomobile*)vehicle)->m_nDriveWheelsOnGround = 4;\n\tCWorld::Remove(vehicle);\n\tCWorld::Add(vehicle);\n\tif (vehicle->IsBoat())\n\t\t((CBoat*)vehicle)->m_bIsAnchored = false;\n\tvehicle->bRenderScorched = vp->render_scorched;\n\tif (vehicle->GetModelIndex() == MI_SKIMMER)\n\t\t((CBoat*)vehicle)->m_fMovingSpeed = vp->skimmer_speed / 50.0f;\n}\n\nvoid CReplay::ProcessBikeUpdate(CVehicle* vehicle, float interpolation, CAddressInReplayBuffer* buffer)\n{\n\tCBike* bike = (CBike*)vehicle;\n\ttBikeUpdatePacket* vp = (tBikeUpdatePacket*)&buffer->m_pBase[buffer->m_nOffset];\n\tif (!vehicle) {\n\t\tprintf(\"Replay:Car wasn't there\");\n\t\treturn;\n\t}\n\tCMatrix vehicle_matrix;\n\tvp->matrix.DecompressIntoFullMatrix(vehicle_matrix);\n\tvehicle->GetMatrix() = vehicle->GetMatrix() * CMatrix(1.0f - interpolation);\n\tvehicle->GetMatrix().GetPosition() *= (1.0f - interpolation);\n\tvehicle->GetMatrix() += CMatrix(interpolation) * vehicle_matrix;\n\tvehicle->m_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f);\n\tvehicle->m_fHealth = 4 * vp->health;\n\tvehicle->m_fGasPedal = vp->acceleration / 100.0f;\n\tvehicle->m_vecMoveSpeed = CVector(vp->velocityX / 8000.0f, vp->velocityY / 8000.0f, vp->velocityZ / 8000.0f);\n\tvehicle->m_fSteerAngle = vp->wheel_state / 50.0f;\n\tvehicle->bEngineOn = true;\n#ifdef FIX_BUGS\n\tfor (int i = 0; i < 2; i++)\n\t\tbike->m_aWheelRotation[i] = vp->wheel_rotation[i] / (128.0f / PI);\n\tfor (int i = 0; i < 2; i++)\n\t\tbike->m_aWheelSpeed[i] = vp->wheel_rotation[i + 2] / (128.0f / PI);\n\tfor (int i = 0; i < 4; i++)\n\t\tbike->m_aSuspensionSpringRatio[i] = vp->wheel_susp_dist[i] / 50.0f;\n#else\n\tfor (int i = 0; i < 4; i++) {\n\t\tbike->m_aSuspensionSpringRatio[i] = vp->wheel_susp_dist[i] / 50.0f;\n\t\tbike->m_aWheelRotation[i] = vp->wheel_rotation[i] / (128.0f / PI);\n\t}\n#endif\n\tbike->m_fLeanLRAngle = vp->lean_angle / 50.0f;\n\tbike->m_fWheelAngle = vp->wheel_angle / 50.0f;\n\tbike->bLeanMatrixClean = false;\n\tbike->CalculateLeanMatrix();\n\tCWorld::Remove(vehicle);\n\tCWorld::Add(vehicle);\n}\n\nbool CReplay::PlayBackThisFrameInterpolation(CAddressInReplayBuffer *buffer, float interpolation, uint32 *pTimer)\n{\n\tCBulletTraces::Init();\n\tfloat split = 1.0f - interpolation;\n\tint ped_min_index = 0; /* Optimization due to peds and vehicles placed in buffer sequentially. */\n\tint vehicle_min_index = 0; /* So next ped can't have pool index less than current. */\n\tfor(;;){\n\t\tuint8* ptr = buffer->m_pBase;\n\t\tuint32 offset = buffer->m_nOffset;\n\t\tuint8 type = ptr[offset];\n\t\tif (type == REPLAYPACKET_ENDOFFRAME)\n\t\t\tbreak;\n\t\tswitch (type) {\n\t\tcase REPLAYPACKET_END:\n\t\t{\n\t\t\tint slot = buffer->m_bSlot;\n\t\t\tif (BufferStatus[slot] == REPLAYBUFFER_RECORD) {\n\t\t\t\tFinishPlayback();\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tbuffer->m_bSlot = (slot + 1) % NUM_REPLAYBUFFERS;\n\t\t\tbuffer->m_nOffset = 0;\n\t\t\tbuffer->m_pBase = Buffers[buffer->m_bSlot];\n\t\t\tped_min_index = 0;\n\t\t\tvehicle_min_index = 0;\n\t\t\tbreak;\n\t\t}\n\t\tcase REPLAYPACKET_VEHICLE:\n\t\t{\n\t\t\ttVehicleUpdatePacket* vp = (tVehicleUpdatePacket*)&ptr[offset];\n\t\t\tfor (int i = vehicle_min_index; i < vp->index; i++) {\n\t\t\t\tCVehicle* v = CPools::GetVehiclePool()->GetSlot(i);\n\t\t\t\tif (!v)\n\t\t\t\t\tcontinue;\n\t\t\t\t/* Removing vehicles not present in this frame. */\n\t\t\t\tCWorld::Remove(v);\n\t\t\t\tdelete v;\n\t\t\t}\n\t\t\tvehicle_min_index = vp->index + 1;\n\t\t\tCVehicle* v = CPools::GetVehiclePool()->GetSlot(vp->index);\n\t\t\tCVehicle* new_v;\n\t\t\tif (!v) {\n\t\t\t\tint mi = vp->mi;\n\t\t\t\tif (CStreaming::ms_aInfoForModel[mi].m_loadState != 1) {\n\t\t\t\t\tCStreaming::RequestModel(mi, 0);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tswitch (vp->vehicle_type) {\n\t\t\t\t\tcase VEHICLE_TYPE_CAR:\n\t\t\t\t\t\tnew_v = new(vp->index << 8) CAutomobile(mi, 2);\t\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase VEHICLE_TYPE_BOAT:\n\t\t\t\t\t\tnew_v = new(vp->index << 8) CBoat(mi, 2);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase VEHICLE_TYPE_TRAIN:\n\t\t\t\t\t\tnew_v = new(vp->index << 8) CTrain(mi, 2);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase VEHICLE_TYPE_HELI:\n\t\t\t\t\t\tnew_v = new(vp->index << 8) CHeli(mi, 2);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase VEHICLE_TYPE_PLANE:\n\t\t\t\t\t\tnew_v = new(vp->index << 8) CPlane(mi, 2);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase VEHICLE_TYPE_BIKE: // not possible\n\t\t\t\t\t\tnew_v = new(vp->index << 8) CBike(mi, 2);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tnew_v->SetStatus(STATUS_PLAYER_PLAYBACKFROMBUFFER);\n\t\t\t\t\tvp->matrix.DecompressIntoFullMatrix(new_v->GetMatrix());\n\t\t\t\t\tnew_v->m_currentColour1 = vp->primary_color;\n\t\t\t\t\tnew_v->m_currentColour2 = vp->secondary_color;\n\t\t\t\t\tCWorld::Add(new_v);\n\t\t\t\t}\n\t\t\t}\n\t\t\tProcessCarUpdate(CPools::GetVehiclePool()->GetSlot(vp->index), interpolation, buffer);\n\t\t\tbuffer->m_nOffset += sizeof(tVehicleUpdatePacket);\n\t\t\tbreak;\n\t\t}\n\t\tcase REPLAYPACKET_BIKE:\n\t\t{\n\t\t\ttBikeUpdatePacket* vp = (tBikeUpdatePacket*)&ptr[offset];\n\t\t\tfor (int i = vehicle_min_index; i < vp->index; i++) {\n\t\t\t\tCVehicle* v = CPools::GetVehiclePool()->GetSlot(i);\n\t\t\t\tif (!v)\n\t\t\t\t\tcontinue;\n\t\t\t\t/* Removing vehicles not present in this frame. */\n\t\t\t\tCWorld::Remove(v);\n\t\t\t\tdelete v;\n\t\t\t}\n\t\t\tvehicle_min_index = vp->index + 1;\n\t\t\tCVehicle* v = CPools::GetVehiclePool()->GetSlot(vp->index);\n\t\t\tCVehicle* new_v;\n\t\t\tif (!v) {\n\t\t\t\tint mi = vp->mi;\n\t\t\t\tif (CStreaming::ms_aInfoForModel[mi].m_loadState != 1) {\n\t\t\t\t\tCStreaming::RequestModel(mi, 0);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tnew_v = new(vp->index << 8) CBike(mi, 2);\n\t\t\t\t\tnew_v->SetStatus(STATUS_PLAYER_PLAYBACKFROMBUFFER);\n\t\t\t\t\tvp->matrix.DecompressIntoFullMatrix(new_v->GetMatrix());\n\t\t\t\t\tnew_v->m_currentColour1 = vp->primary_color;\n\t\t\t\t\tnew_v->m_currentColour2 = vp->secondary_color;\n\t\t\t\t\tCWorld::Add(new_v);\n\t\t\t\t}\n\t\t\t}\n\t\t\tProcessBikeUpdate(CPools::GetVehiclePool()->GetSlot(vp->index), interpolation, buffer);\n\t\t\tbuffer->m_nOffset += sizeof(tBikeUpdatePacket);\n\t\t\tbreak;\n\t\t}\n\t\tcase REPLAYPACKET_PED_HEADER:\n\t\t{\n\t\t\ttPedHeaderPacket* ph = (tPedHeaderPacket*)&ptr[offset];\n\t\t\tif (!CPools::GetPedPool()->GetSlot(ph->index)) {\n\t\t\t\tif (!CStreaming::HasModelLoaded(ph->mi) || (ph->mi >= MI_SPECIAL01 && ph->mi < MI_LAST_PED)) {\n\t\t\t\t\tCStreaming::RequestModel(ph->mi, 0);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tCPed* new_p;\n\t\t\t\t\tif (ph->pedtype != PEDTYPE_PLAYER1)\n\t\t\t\t\t\tnew_p = new(ph->index << 8) CCivilianPed((ePedType)ph->pedtype, ph->mi);\n\t\t\t\t\telse\n\t\t\t\t\t\tnew_p = new(ph->index << 8) CPlayerPed();\n\t\t\t\t\tnew_p->SetStatus(STATUS_PLAYER_PLAYBACKFROMBUFFER);\n\t\t\t\t\tnew_p->GetMatrix().SetUnity();\n\t\t\t\t\tCWorld::Add(new_p);\n\t\t\t\t}\n\t\t\t}\n\t\t\tbuffer->m_nOffset += sizeof(tPedHeaderPacket);\n\t\t\tbreak;\n\t\t}\n\t\tcase REPLAYPACKET_PED_UPDATE:\n\t\t{\n\t\t\ttPedUpdatePacket* pu = (tPedUpdatePacket*)&ptr[offset];\n\t\t\tfor (int i = ped_min_index; i < pu->index; i++) {\n\t\t\t\tCPed* p = CPools::GetPedPool()->GetSlot(i);\n\t\t\t\tif (!p)\n\t\t\t\t\tcontinue;\n\t\t\t\t/* Removing peds not present in this frame. */\n\t\t\t\tCWorld::Remove(p);\n\t\t\t\tdelete p;\n\t\t\t}\n\t\t\tped_min_index = pu->index + 1;\n\t\t\tProcessPedUpdate(CPools::GetPedPool()->GetSlot(pu->index), interpolation, buffer);\n\t\t\tbreak;\n\t\t}\n\t\tcase REPLAYPACKET_GENERAL:\n\t\t{\n\t\t\ttGeneralPacket* pg = (tGeneralPacket*)&ptr[offset];\n\t\t\tTheCamera.GetMatrix() = TheCamera.GetMatrix() * CMatrix(split);\n\t\t\tTheCamera.GetMatrix().GetPosition() *= split;\n\t\t\tTheCamera.GetMatrix() += CMatrix(interpolation) * pg->camera_pos;\n\t\t\tRwMatrix* pm = RwFrameGetMatrix(RwCameraGetFrame(TheCamera.m_pRwCamera));\n\t\t\tpm->pos = TheCamera.GetPosition();\n\t\t\tpm->at = TheCamera.GetForward();\n\t\t\tpm->up = TheCamera.GetUp();\n\t\t\tpm->right = TheCamera.GetRight();\n\t\t\tCameraFocusX = split * CameraFocusX + interpolation * pg->player_pos.x;\n\t\t\tCameraFocusY = split * CameraFocusY + interpolation * pg->player_pos.y;\n\t\t\tCameraFocusZ = split * CameraFocusZ + interpolation * pg->player_pos.z;\n\t\t\tbPlayerInRCBuggy = pg->in_rcvehicle;\n\t\t\tbuffer->m_nOffset += sizeof(tGeneralPacket);\n\t\t\tbreak;\n\t\t}\n\t\tcase REPLAYPACKET_CLOCK:\n\t\t{\n\t\t\ttClockPacket* pc = (tClockPacket*)&ptr[offset];\n\t\t\tCClock::SetGameClock(pc->hours, pc->minutes);\n\t\t\tbuffer->m_nOffset += sizeof(tClockPacket);\n\t\t\tbreak;\n\t\t}\n\t\tcase REPLAYPACKET_WEATHER:\n\t\t{\n\t\t\ttWeatherPacket* pw = (tWeatherPacket*)&ptr[offset];\n\t\t\tCWeather::OldWeatherType = pw->old_weather;\n\t\t\tCWeather::NewWeatherType = pw->new_weather;\n\t\t\tCWeather::InterpolationValue = pw->interpolation;\n\t\t\tbuffer->m_nOffset += sizeof(tWeatherPacket);\n\t\t\tbreak;\n\t\t}\n\t\tcase REPLAYPACKET_ENDOFFRAME:\n\t\t{\n\t\t\t/* Not supposed to be here. */\n\t\t\tassert(false);\n\t\t\tbuffer->m_nOffset++;\n\t\t\tbreak;\n\t\t}\n\t\tcase REPLAYPACKET_TIMER:\n\t\t{\n\t\t\ttTimerPacket* pt = (tTimerPacket*)&ptr[offset];\n\t\t\tif (pTimer)\n\t\t\t\t*pTimer = pt->timer;\n\t\t\tCTimer::SetTimeInMilliseconds(pt->timer);\n\t\t\tbuffer->m_nOffset += sizeof(tTimerPacket);\n\t\t\tbreak;\n\t\t}\n\t\tcase REPLAYPACKET_BULLET_TRACES:\n\t\t{\n\t\t\ttBulletTracePacket* pb = (tBulletTracePacket*)&ptr[offset];\n\t\t\tCBulletTraces::aTraces[pb->index].m_bInUse = true;\n\t\t\tCBulletTraces::aTraces[pb->index].m_vecStartPos = pb->inf;\n\t\t\tCBulletTraces::aTraces[pb->index].m_vecEndPos = pb->sup;\n\t\t\tbuffer->m_nOffset += sizeof(tBulletTracePacket);\n\t\t\tbreak;\n\t\t}\n\t\tcase REPLAYPACKET_PARTICLE:\n\t\t{\n\t\t\ttParticlePacket* pp = (tParticlePacket*)&ptr[offset];\n\t\t\tCVector pos(pp->pos_x / 4.0f, pp->pos_y / 4.0f, pp->pos_z / 4.0f);\n\t\t\tCVector dir(pp->dir_x / 120.0f, pp->dir_y / 120.0f, pp->dir_z / 120.0f);\n\t\t\tRwRGBA color;\n\t\t\tcolor.red = pp->r;\n\t\t\tcolor.green = pp->g;\n\t\t\tcolor.blue = pp->b;\n\t\t\tcolor.alpha = pp->a;\n\t\t\tCParticle::AddParticle((tParticleType)pp->particle_type, pos, dir, nil, pp->size, color);\n\t\t\tbuffer->m_nOffset += sizeof(tParticlePacket);\n\t\t\tbreak;\n\t\t}\n\t\tcase REPLAYPACKET_MISC:\n\t\t{\n\t\t\ttMiscPacket* pm = (tMiscPacket*)&ptr[offset];\n\t\t\tTheCamera.m_uiCamShakeStart = pm->cam_shake_start;\n\t\t\tTheCamera.m_fCamShakeForce = pm->cam_shake_strength;\n\t\t\tCSpecialFX::bVideoCam = pm->video_cam;\n\t\t\tCSpecialFX::bLiftCam = pm->lift_cam;\n\t\t\tCGame::currArea = pm->cur_area;\n\t\t\tbuffer->m_nOffset += sizeof(tMiscPacket);\n\t\t\tbreak;\n\t\t}\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\t}\n\tbuffer->m_nOffset += 4;\n\tfor (int i = vehicle_min_index; i < CPools::GetVehiclePool()->GetSize(); i++) {\n\t\tCVehicle* v = CPools::GetVehiclePool()->GetSlot(i);\n\t\tif (!v)\n\t\t\tcontinue;\n\t\t/* Removing vehicles not present in this frame. */\n\t\tCWorld::Remove(v);\n\t\tdelete v;\n\t}\n\tfor (int i = ped_min_index; i < CPools::GetPedPool()->GetSize(); i++) {\n\t\tCPed* p = CPools::GetPedPool()->GetSlot(i);\n\t\tif (!p)\n\t\t\tcontinue;\n\t\t/* Removing peds not present in this frame. */\n\t\tCWorld::Remove(p);\n\t\tdelete p;\n\t}\n\tProcessReplayCamera();\n\treturn false;\n}\n\nvoid CReplay::FinishPlayback(void)\n{\n\tif (Mode != MODE_PLAYBACK)\n\t\treturn;\n\tEmptyAllPools();\n\tRestoreStuffFromMem();\n\tMode = MODE_RECORD;\n\tif (bDoLoadSceneWhenDone){\n\t\tCVector v_ls(LoadSceneX, LoadSceneY, LoadSceneZ);\n\t\tCGame::currLevel = CTheZones::GetLevelFromPosition(&v_ls);\n\t\tCCollision::SortOutCollisionAfterLoad();\n\t\tCStreaming::LoadScene(v_ls);\n\t}\n\tbDoLoadSceneWhenDone = false;\n\tif (bPlayingBackFromFile){\n\t\tInit();\n\t\tMarkEverythingAsNew();\n\t}\n\tDMAudio.SetEffectsFadeVol(127);\n\tDMAudio.SetMusicFadeVol(127);\n}\n\nvoid CReplay::EmptyReplayBuffer(void)\n{\n\tif (Mode == MODE_PLAYBACK)\n\t\treturn;\n\tRecord.m_nOffset = 0;\n\tfor (int i = 0; i < NUM_REPLAYBUFFERS; i++){\n\t\tBufferStatus[i] = REPLAYBUFFER_UNUSED;\n\t}\n\tRecord.m_bSlot = 0;\n\tRecord.m_pBase = Buffers[0];\n\tBufferStatus[0] = REPLAYBUFFER_RECORD;\n\tRecord.m_pBase[Record.m_nOffset] = 0;\n\tMarkEverythingAsNew();\n}\n\nvoid CReplay::ProcessReplayCamera(void)\n{\n\tswitch (CameraMode) {\n\tcase REPLAYCAMMODE_TOPDOWN:\n\t{\n\t\tTheCamera.SetPosition(CameraFocusX, CameraFocusY, CameraFocusZ + 15.0f);\n\t\tTheCamera.GetForward() = CVector(0.0f, 0.0f, -1.0f);\n\t\tTheCamera.GetUp() = CVector(0.0f, 1.0f, 0.0f);\n\t\tTheCamera.GetRight() = CVector(1.0f, 0.0f, 0.0f);\n\t\tRwMatrix* pm = RwFrameGetMatrix(RwCameraGetFrame(TheCamera.m_pRwCamera));\n\t\tpm->pos = TheCamera.GetPosition();\n\t\tpm->at = TheCamera.GetForward();\n\t\tpm->up = TheCamera.GetUp();\n\t\tpm->right = TheCamera.GetRight();\n\t\tbreak;\n\t}\n\tcase REPLAYCAMMODE_FIXED:\n\t{\n\t\tTheCamera.GetMatrix().GetPosition() = CVector(CameraFixedX, CameraFixedY, CameraFixedZ);\n\t\tCVector forward(CameraFocusX - CameraFixedX, CameraFocusY - CameraFixedY, CameraFocusZ - CameraFixedZ);\n\t\tforward.Normalise();\n\t\tCVector right = CrossProduct(CVector(0.0f, 0.0f, 1.0f), forward);\n\t\tright.Normalise();\n\t\tCVector up = CrossProduct(forward, right);\n\t\tup.Normalise();\n\t\tTheCamera.GetMatrix().GetForward() = forward;\n\t\tTheCamera.GetMatrix().GetUp() = up;\n\t\tTheCamera.GetMatrix().GetRight() = right;\n\t\tRwMatrix* pm = RwFrameGetMatrix(RwCameraGetFrame(TheCamera.m_pRwCamera));\n\t\tpm->pos = TheCamera.GetMatrix().GetPosition();\n\t\tpm->at = TheCamera.GetMatrix().GetForward();\n\t\tpm->up = TheCamera.GetMatrix().GetUp();\n\t\tpm->right = TheCamera.GetMatrix().GetRight();\n\t\tbreak;\n\t}\n\tdefault:\n\t\tbreak;\n\t}\n\tTheCamera.m_vecGameCamPos = TheCamera.GetMatrix().GetPosition();\n\tTheCamera.CalculateDerivedValues();\n\tRwMatrixUpdate(RwFrameGetMatrix(RwCameraGetFrame(TheCamera.m_pRwCamera)));\n\tRwFrameUpdateObjects(RwCameraGetFrame(TheCamera.m_pRwCamera));\n}\n\nextern CWeaponEffects gCrossHair;\n\nvoid CReplay::TriggerPlayback(uint8 cam_mode, float cam_x, float cam_y, float cam_z, bool load_scene)\n{\n\tif (Mode != MODE_RECORD)\n\t\treturn;\n\tCameraFixedX = cam_x;\n\tCameraFixedY = cam_y;\n\tCameraFixedZ = cam_z;\n\tMode = MODE_PLAYBACK;\n\tFramesActiveLookAroundCam = 0;\n\tCameraMode = cam_mode;\n\tbAllowLookAroundCam = true;\n\tbPlayingBackFromFile = false;\n\tOldRadioStation = DMAudio.GetRadioInCar();\n\tDMAudio.ChangeMusicMode(MUSICMODE_FRONTEND);\n\tDMAudio.SetEffectsFadeVol(0);\n\tDMAudio.SetMusicFadeVol(0);\n\tCEscalators::Shutdown();\n\tCWaterCreatures::RemoveAll();\n\tint current;\n\tfor (current = 0; current < NUM_REPLAYBUFFERS; current++)\n\t\tif (BufferStatus[current] == REPLAYBUFFER_RECORD)\n\t\t\tbreak;\n\tint first;\n\tfor (first = (current + 1) % NUM_REPLAYBUFFERS; ; first = (first + 1) % NUM_REPLAYBUFFERS)\n\t\tif (BufferStatus[first] == REPLAYBUFFER_RECORD || BufferStatus[first] == REPLAYBUFFER_PLAYBACK)\n\t\t\tbreak;\n\tPlayback.m_bSlot = first;\n\tPlayback.m_nOffset = 0;\n\tPlayback.m_pBase = Buffers[first];\n\tCObject::DeleteAllTempObjectsInArea(CVector(0.0f, 0.0f, 0.0f), 1000000.0f);\n\tStoreStuffInMem();\n\tEmptyPedsAndVehiclePools();\n\tSlowMotion = 1;\n\tCSkidmarks::Clear();\n\tStreamAllNecessaryCarsAndPeds();\n\tif (load_scene)\n\t\tbDoLoadSceneWhenDone = false;\n\telse{\n\t\tbDoLoadSceneWhenDone = true;\n\t\tLoadSceneX = TheCamera.GetPosition().x;\n\t\tLoadSceneY = TheCamera.GetPosition().y;\n\t\tLoadSceneZ = TheCamera.GetPosition().z;\n\t\tCVector ff_coord;\n\t\tFindFirstFocusCoordinate(&ff_coord);\n\t\tCGame::currLevel = CTheZones::GetLevelFromPosition(&ff_coord);\n\t\tCCollision::SortOutCollisionAfterLoad();\n\t\tCStreaming::LoadScene(ff_coord);\n\t}\n\tif (cam_mode == REPLAYCAMMODE_ASSTORED)\n\t\tTheCamera.CarZoomIndicator = CAM_ZOOM_CINEMATIC;\n\tgCrossHair.m_bActive = false;\n\tCExplosion::ClearAllExplosions();\n\tCPlaneBanners::Init();\n#ifndef FIX_BUGS // this doesn't do anything useful and accesses destroyed player ped\n\tTheCamera.Restore();\n#endif\n\tCDraw::SetFOV(70.0f);\n}\n\nvoid CReplay::StoreStuffInMem(void)\n{\n#ifdef FIX_BUGS\n\tfor (int i = 0; i < NUMPLAYERS; i++)\n\t\tnHandleOfPlayerPed[i] = CPools::GetPedPool()->GetIndex(CWorld::Players[i].m_pPed);\n#endif\n\tint i = CPools::GetPedPool()->GetSize();\n\twhile (--i >= 0) {\n\t\tCPed* ped = CPools::GetPedPool()->GetSlot(i);\n\t\tif (!ped)\n\t\t\tcontinue;\n\t\tif (ped->m_attractor)\n\t\t\tGetPedAttractorManager()->DeRegisterPed(ped, ped->m_attractor);\n\t}\n\tCPools::GetVehiclePool()->Store(pBuf0, pBuf1);\n\tCPools::GetPedPool()->Store(pBuf2, pBuf3);\n\tCPools::GetObjectPool()->Store(pBuf4, pBuf5);\n\tCPools::GetPtrNodePool()->Store(pBuf6, pBuf7);\n\tCPools::GetEntryInfoNodePool()->Store(pBuf8, pBuf9);\n\tCPools::GetDummyPool()->Store(pBuf10, pBuf11);\n\tpWorld1 = new uint8[sizeof(CSector) * NUMSECTORS_X * NUMSECTORS_Y];\n\tmemcpy(pWorld1, CWorld::GetSector(0, 0), NUMSECTORS_X * NUMSECTORS_Y * sizeof(CSector));\n\tWorldPtrList = CWorld::GetMovingEntityList().first; // why\n\tBigBuildingPtrList = CWorld::GetBigBuildingList(LEVEL_GENERIC).first;\n\tpPickups = new uint8[sizeof(CPickup) * NUMPICKUPS];\n\tmemcpy(pPickups, CPickups::aPickUps, NUMPICKUPS * sizeof(CPickup));\n\tpReferences = new uint8[(sizeof(CReference) * NUMREFERENCES)];\n\tmemcpy(pReferences, CReferences::aRefs, NUMREFERENCES * sizeof(CReference));\n\tpEmptyReferences = CReferences::pEmptyList;\n\tpStoredCam = new uint8[sizeof(CCamera)];\n\tmemcpy(pStoredCam, &TheCamera, sizeof(CCamera));\n\tpRadarBlips = new uint8[sizeof(sRadarTrace) * NUMRADARBLIPS];\n\tmemcpy(pRadarBlips, CRadar::ms_RadarTrace, NUMRADARBLIPS * sizeof(sRadarTrace));\n\tPlayerWanted = *FindPlayerPed()->m_pWanted;\n\tPlayerInfo = CWorld::Players[0];\n\tTime1 = CTimer::GetTimeInMilliseconds();\n\tTime2 = CTimer::GetTimeInMillisecondsNonClipped();\n\tTime3 = CTimer::GetPreviousTimeInMilliseconds();\n\tTime4 = CTimer::GetTimeInMillisecondsPauseMode();\n\tFrame = CTimer::GetFrameCounter();\n\tClockHours = CClock::GetHours();\n\tClockMinutes = CClock::GetMinutes();\n\tOldWeatherType = CWeather::OldWeatherType;\n\tNewWeatherType = CWeather::NewWeatherType;\n\tWeatherInterpolationValue = CWeather::InterpolationValue;\n\tCurrArea = CGame::currArea;\n\tTimeStepNonClipped = CTimer::GetTimeStepNonClipped();\n\tTimeStep = CTimer::GetTimeStep();\n\tTimeScale = CTimer::GetTimeScale();\n\tms_nNumCivMale_Stored = CPopulation::ms_nNumCivMale;\n\tms_nNumCivFemale_Stored = CPopulation::ms_nNumCivFemale;\n\tms_nNumCop_Stored = CPopulation::ms_nNumCop;\n\tms_nNumEmergency_Stored = CPopulation::ms_nNumEmergency;\n\tms_nNumGang1_Stored = CPopulation::ms_nNumGang1;\n\tms_nNumGang2_Stored = CPopulation::ms_nNumGang2;\n\tms_nNumGang3_Stored = CPopulation::ms_nNumGang3;\n\tms_nNumGang4_Stored = CPopulation::ms_nNumGang4;\n\tms_nNumGang5_Stored = CPopulation::ms_nNumGang5;\n\tms_nNumGang6_Stored = CPopulation::ms_nNumGang6;\n\tms_nNumGang7_Stored = CPopulation::ms_nNumGang7;\n\tms_nNumGang8_Stored = CPopulation::ms_nNumGang8;\n\tms_nNumGang9_Stored = CPopulation::ms_nNumGang9;\n\tms_nNumDummy_Stored = CPopulation::ms_nNumDummy;\n\tms_nTotalCivPeds_Stored = CPopulation::ms_nTotalCivPeds;\n\tms_nTotalGangPeds_Stored = CPopulation::ms_nTotalGangPeds;\n\tms_nTotalPeds_Stored = CPopulation::ms_nTotalPeds;\n\tms_nTotalMissionPeds_Stored = CPopulation::ms_nTotalMissionPeds;\n\tint size = CPools::GetPedPool()->GetSize();\n\tpPedAnims = new CStoredDetailedAnimationState[size];\n\tfor (int i = 0; i < size; i++) {\n\t\tCPed* ped = CPools::GetPedPool()->GetSlot(i);\n\t\tif (ped)\n\t\t\tStoreDetailedPedAnimation(ped, &pPedAnims[i]);\n\t}\n\tpGarages = new uint8[sizeof(CGarages::aGarages)];\n\tmemcpy(pGarages, CGarages::aGarages, sizeof(CGarages::aGarages));\n\tFireArray = new CFire[NUM_FIRES];\n\tmemcpy(FireArray, gFireManager.m_aFires, sizeof(gFireManager.m_aFires));\n\tNumOfFires = gFireManager.m_nTotalFires;\n\tpaProjectileInfo = new uint8[sizeof(gaProjectileInfo)];\n\tmemcpy(paProjectileInfo, gaProjectileInfo, sizeof(gaProjectileInfo));\n\tpaProjectiles = new uint8[sizeof(CProjectileInfo::ms_apProjectile)];\n\tmemcpy(paProjectiles, CProjectileInfo::ms_apProjectile, sizeof(CProjectileInfo::ms_apProjectile));\n\tCScriptPaths::Save_ForReplay();\n}\n\nvoid CReplay::RestoreStuffFromMem(void)\n{\n\tCPools::GetVehiclePool()->CopyBack(pBuf0, pBuf1);\n\tCPools::GetPedPool()->CopyBack(pBuf2, pBuf3);\n\tCPools::GetObjectPool()->CopyBack(pBuf4, pBuf5);\n\tCPools::GetPtrNodePool()->CopyBack(pBuf6, pBuf7);\n\tCPools::GetEntryInfoNodePool()->CopyBack(pBuf8, pBuf9);\n\tCPools::GetDummyPool()->CopyBack(pBuf10, pBuf11);\n\tmemcpy(CWorld::GetSector(0, 0), pWorld1, sizeof(CSector) * NUMSECTORS_X * NUMSECTORS_Y);\n\tdelete[] pWorld1;\n\tpWorld1 = nil;\n\tCWorld::GetMovingEntityList().first = WorldPtrList;\n\tCWorld::GetBigBuildingList(LEVEL_GENERIC).first = BigBuildingPtrList;\n\tmemcpy(CPickups::aPickUps, pPickups, sizeof(CPickup) * NUMPICKUPS);\n\tdelete[] pPickups;\n\tpPickups = nil;\n\tmemcpy(CReferences::aRefs, pReferences, sizeof(CReference) * NUMREFERENCES);\n\tdelete[] pReferences;\n\tpReferences = nil;\n\tCReferences::pEmptyList = pEmptyReferences;\n\tpEmptyReferences = nil;\n\tmemcpy(&TheCamera, pStoredCam, sizeof(CCamera));\n\tdelete[] pStoredCam;\n\tpStoredCam = nil;\n\tmemcpy(CRadar::ms_RadarTrace, pRadarBlips, sizeof(sRadarTrace) * NUMRADARBLIPS);\n\tdelete[] pRadarBlips;\n\tpRadarBlips = nil;\n#ifdef FIX_BUGS\n\tfor (int i = 0; i < NUMPLAYERS; i++) {\n\t\tCPlayerPed* pPlayerPed = (CPlayerPed*)CPools::GetPedPool()->GetAt(nHandleOfPlayerPed[i]);\n\t\tassert(pPlayerPed);\n\t\tCWorld::Players[i].m_pPed = pPlayerPed;\n\t\tpPlayerPed->RegisterReference((CEntity**)&CWorld::Players[i].m_pPed);\n\t}\n#endif\n\tFindPlayerPed()->m_pWanted = new CWanted(PlayerWanted);\n\tCWorld::Players[0] = PlayerInfo;\n\tint i = CPools::GetPedPool()->GetSize();\n\twhile (--i >= 0) {\n\t\tCPed* ped = CPools::GetPedPool()->GetSlot(i);\n\t\tif (!ped)\n\t\t\tcontinue;\n\t\tint mi = ped->GetModelIndex();\n\t\tCStreaming::RequestModel(mi, 0);\n\t\tCStreaming::LoadAllRequestedModels(false);\n\t\tped->m_rwObject = nil;\n\t\tped->m_modelIndex = -1;\n\t\tped->SetModelIndex(mi);\n\t\tped->m_pVehicleAnim = nil;\n\t\tped->m_audioEntityId = DMAudio.CreateEntity(AUDIOTYPE_PHYSICAL, ped);\n\t\tDMAudio.SetEntityStatus(ped->m_audioEntityId, true);\n\t\tCPopulation::UpdatePedCount((ePedType)ped->m_nPedType, false);\n\t\tfor (int j = 0; j < TOTAL_WEAPON_SLOTS; j++) {\n\t\t\tint mi1 = CWeaponInfo::GetWeaponInfo(ped->m_weapons[j].m_eWeaponType)->m_nModelId;\n\t\t\tif (mi1 != -1)\n\t\t\t\tCStreaming::RequestModel(mi1, STREAMFLAGS_DEPENDENCY);\n\t\t\tint mi2 = CWeaponInfo::GetWeaponInfo(ped->m_weapons[j].m_eWeaponType)->m_nModel2Id;\n\t\t\tif (mi2 != -1)\n\t\t\t\tCStreaming::RequestModel(mi2, STREAMFLAGS_DEPENDENCY);\n\t\t\tCStreaming::LoadAllRequestedModels(false);\n\t\t\tped->m_weapons[j].Initialise(ped->m_weapons[j].m_eWeaponType, ped->m_weapons[j].m_nAmmoTotal);\n\t\t}\n\t\tif (ped->m_wepModelID >= 0) {\n\t\t\tped->m_pWeaponModel = nil;\n\t\t\tif (ped->IsPlayer())\n\t\t\t\t((CPlayerPed*)ped)->m_pMinigunTopAtomic = nil;\n\t\t\tped->AddWeaponModel(ped->m_wepModelID);\n\t\t}\n\t\tif (ped->m_nPedType == PEDTYPE_COP)\n\t\t\t((CCopPed*)ped)->m_pStinger = new CStinger;\n\t}\n\ti = CPools::GetVehiclePool()->GetSize();\n\twhile (--i >= 0) {\n\t\tCVehicle* vehicle = CPools::GetVehiclePool()->GetSlot(i);\n\t\tif (!vehicle)\n\t\t\tcontinue;\n\t\tint mi = vehicle->GetModelIndex();\n\t\tCStreaming::RequestModel(mi, 0);\n\t\tCStreaming::LoadAllRequestedModels(false);\n\t\tvehicle->m_rwObject = nil;\n\t\tvehicle->m_modelIndex = -1;\n\t\tvehicle->SetModelIndex(mi);\n\t\tif (vehicle->IsCar()) {\n\t\t\tCAutomobile* car = (CAutomobile*)vehicle;\n\t\t\tif (mi == MI_DODO) {\n\t\t\t\tRpAtomicSetFlags((RpAtomic*)GetFirstObject(car->m_aCarNodes[CAR_WHEEL_LF]), 0);\n\t\t\t\tCMatrix tmp1;\n\t\t\t\ttmp1.Attach(RwFrameGetMatrix(car->m_aCarNodes[CAR_WHEEL_RF]), false);\n\t\t\t\tCMatrix tmp2(RwFrameGetMatrix(car->m_aCarNodes[CAR_WHEEL_LF]), false);\n\t\t\t\ttmp1.GetPosition() += CVector(tmp2.GetPosition().x + 0.1f, 0.0f, tmp2.GetPosition().z);\n\t\t\t\ttmp1.UpdateRW();\n\t\t\t}\n\t\t\telse if (mi == MI_HUNTER) {\n\t\t\t\tRpAtomicSetFlags((RpAtomic*)GetFirstObject(car->m_aCarNodes[CAR_WHEEL_LB]), 0);\n\t\t\t\tRpAtomicSetFlags((RpAtomic*)GetFirstObject(car->m_aCarNodes[CAR_WHEEL_RB]), 0);\n\t\t\t}\n\t\t\telse if (vehicle->IsRealHeli()) {\n\t\t\t\tRpAtomicSetFlags((RpAtomic*)GetFirstObject(car->m_aCarNodes[CAR_WHEEL_LF]), 0);\n\t\t\t\tRpAtomicSetFlags((RpAtomic*)GetFirstObject(car->m_aCarNodes[CAR_WHEEL_RF]), 0);\n\t\t\t\tRpAtomicSetFlags((RpAtomic*)GetFirstObject(car->m_aCarNodes[CAR_WHEEL_LB]), 0);\n\t\t\t\tRpAtomicSetFlags((RpAtomic*)GetFirstObject(car->m_aCarNodes[CAR_WHEEL_RB]), 0);\n\t\t\t}\n\t\t}\n\t\tif (vehicle->IsCar()){\n\t\t\tCAutomobile* car = (CAutomobile*)vehicle;\n\t\t\tint32 panels = car->Damage.m_panelStatus;\n\t\t\tcar->Damage.m_panelStatus = 0;\n\t\t\tApplyPanelDamageToCar(panels, car, true);\n\t\t\tcar->SetDoorDamage(CAR_BONNET, DOOR_BONNET, true);\n\t\t\tcar->SetDoorDamage(CAR_BOOT, DOOR_BOOT, true);\n\t\t\tcar->SetDoorDamage(CAR_DOOR_LF, DOOR_FRONT_LEFT, true);\n\t\t\tcar->SetDoorDamage(CAR_DOOR_RF, DOOR_FRONT_RIGHT, true);\n\t\t\tcar->SetDoorDamage(CAR_DOOR_LR, DOOR_REAR_LEFT, true);\n\t\t\tcar->SetDoorDamage(CAR_DOOR_RR, DOOR_REAR_RIGHT, true);\n\t\t}\n\t\tvehicle->m_audioEntityId = DMAudio.CreateEntity(AUDIOTYPE_PHYSICAL, vehicle);\n\t\tDMAudio.SetEntityStatus(vehicle->m_audioEntityId, true);\n\t\tCCarCtrl::UpdateCarCount(vehicle, false);\n\t\tif ((mi == MI_AIRTRAIN || mi == MI_DEADDODO) && vehicle->m_rwObject){\n\t\t\tCVehicleModelInfo* info = (CVehicleModelInfo*)CModelInfo::GetModelInfo(mi);\n\t\t\tif (RwObjectGetType(vehicle->m_rwObject) == rpATOMIC){\n\t\t\t\tvehicle->GetMatrix().Detach();\n\t\t\t\tif (vehicle->m_rwObject){\n\t\t\t\t\tif (RwObjectGetType(vehicle->m_rwObject) == rpATOMIC){\n\t\t\t\t\t\tRwFrame* frame = RpAtomicGetFrame((RpAtomic*)vehicle->m_rwObject);\n\t\t\t\t\t\tRpAtomicDestroy((RpAtomic*)vehicle->m_rwObject);\n\t\t\t\t\t\tRwFrameDestroy(frame);\n\t\t\t\t\t}\n\t\t\t\t\tvehicle->m_rwObject = nil;\n\t\t\t\t}\n\t\t\t}else{\n\t\t\t\tvehicle->DeleteRwObject();\n\t\t\t\tint model_id = info->m_wheelId;\n\t\t\t\tif (model_id != -1){\n\t\t\t\t\tif ((vehicle->m_rwObject = CModelInfo::GetModelInfo(model_id)->CreateInstance())){\n\t\t\t\t\t\tvehicle->GetMatrix().AttachRW(RwFrameGetMatrix(RpClumpGetFrame((RpClump*)vehicle->m_rwObject)), false);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tPrintElementsInPtrList();\n\ti = CPools::GetObjectPool()->GetSize();\n\twhile (--i >= 0) {\n\t\tCObject* object = CPools::GetObjectPool()->GetSlot(i);\n\t\tif (!object)\n\t\t\tcontinue;\n\t\tint mi = object->GetModelIndex();\n\t\tobject->m_rwObject = nil;\n\t\tobject->m_modelIndex = -1;\n\t\tobject->SetModelIndexNoCreate(mi);\n\t\tobject->GetMatrix().m_attachment = nil;\n\t}\n\ti = CPools::GetDummyPool()->GetSize();\n\twhile (--i >= 0) {\n\t\tCDummy* dummy = CPools::GetDummyPool()->GetSlot(i);\n\t\tif (!dummy)\n\t\t\tcontinue;\n\t\tint mi = dummy->GetModelIndex();\n\t\tdummy->m_rwObject = nil;\n\t\tdummy->m_modelIndex = -1;\n\t\tdummy->SetModelIndexNoCreate(mi);\n\t\tdummy->GetMatrix().m_attachment = nil;\n\t}\n\t++ClockMinutes;\n\tCTimer::SetTimeInMilliseconds(Time1);\n\tCTimer::SetTimeInMillisecondsNonClipped(Time2);\n\tCTimer::SetPreviousTimeInMilliseconds(Time3);\n\tCTimer::SetTimeInMillisecondsPauseMode(Time4);\n\tCTimer::SetTimeScale(TimeScale);\n\tCTimer::SetFrameCounter(Frame);\n\tCTimer::SetTimeStep(TimeStep);\n\tCTimer::SetTimeStepNonClipped(TimeStepNonClipped);\n\tCClock::SetGameClock(ClockHours, ClockMinutes);\n\tCWeather::OldWeatherType = OldWeatherType;\n\tCWeather::NewWeatherType = NewWeatherType;\n\tCWeather::InterpolationValue = WeatherInterpolationValue;\n\tCGame::currArea = CurrArea;\n\tCPopulation::ms_nNumCivMale = ms_nNumCivMale_Stored;\n\tCPopulation::ms_nNumCivFemale = ms_nNumCivFemale_Stored;\n\tCPopulation::ms_nNumCop = ms_nNumCop_Stored;\n\tCPopulation::ms_nNumEmergency = ms_nNumEmergency_Stored;\n\tCPopulation::ms_nNumGang1 = ms_nNumGang1_Stored;\n\tCPopulation::ms_nNumGang2 = ms_nNumGang2_Stored;\n\tCPopulation::ms_nNumGang3 = ms_nNumGang3_Stored;\n\tCPopulation::ms_nNumGang4 = ms_nNumGang4_Stored;\n\tCPopulation::ms_nNumGang5 = ms_nNumGang5_Stored;\n\tCPopulation::ms_nNumGang6 = ms_nNumGang6_Stored;\n\tCPopulation::ms_nNumGang7 = ms_nNumGang7_Stored;\n\tCPopulation::ms_nNumGang8 = ms_nNumGang8_Stored;\n\tCPopulation::ms_nNumGang9 = ms_nNumGang9_Stored;\n\tCPopulation::ms_nNumDummy = ms_nNumDummy_Stored;\n\tCPopulation::ms_nTotalCivPeds = ms_nTotalCivPeds_Stored;\n\tCPopulation::ms_nTotalGangPeds = ms_nTotalGangPeds_Stored;\n\tCPopulation::ms_nTotalPeds = ms_nTotalPeds_Stored;\n\tCPopulation::ms_nTotalMissionPeds = ms_nTotalMissionPeds_Stored;\n\tfor (int i = 0; i < CPools::GetPedPool()->GetSize(); i++) {\n\t\tCPed* ped = CPools::GetPedPool()->GetSlot(i);\n\t\tif (!ped)\n\t\t\tcontinue;\n\t\tRetrieveDetailedPedAnimation(ped, &pPedAnims[i]);\n\t}\n\tdelete[] pPedAnims;\n\tpPedAnims = nil;\n\tmemcpy(CGarages::aGarages, pGarages, sizeof(CGarages::aGarages));\n\tdelete[] pGarages;\n\tpGarages = nil;\n\tmemcpy(gFireManager.m_aFires, FireArray, sizeof(gFireManager.m_aFires));\n\tdelete[] FireArray;\n\tFireArray = nil;\n\tgFireManager.m_nTotalFires = NumOfFires;\n\tmemcpy(gaProjectileInfo, paProjectileInfo, sizeof(gaProjectileInfo));\n\tdelete[] paProjectileInfo;\n\tpaProjectileInfo = nil;\n\tmemcpy(CProjectileInfo::ms_apProjectile, paProjectiles, sizeof(CProjectileInfo::ms_apProjectile));\n\tdelete[] paProjectiles;\n\tpaProjectiles = nil;\n\tCScriptPaths::Load_ForReplay();\n\tCExplosion::ClearAllExplosions();\n\tDMAudio.ChangeMusicMode(MUSICMODE_FRONTEND);\n\tDMAudio.SetRadioInCar(OldRadioStation);\n\tDMAudio.ChangeMusicMode(MUSICMODE_GAME);\n}\n\nvoid CReplay::EmptyPedsAndVehiclePools(void)\n{\n\tint i = CPools::GetVehiclePool()->GetSize();\n\twhile (--i >= 0) {\n\t\tCVehicle* v = CPools::GetVehiclePool()->GetSlot(i);\n\t\tif (!v)\n\t\t\tcontinue;\n\t\tCWorld::Remove(v);\n\t\tdelete v;\n\t}\n\ti = CPools::GetPedPool()->GetSize();\n\twhile (--i >= 0) {\n\t\tCPed* p = CPools::GetPedPool()->GetSlot(i);\n\t\tif (!p)\n\t\t\tcontinue;\n\t\tCWorld::Remove(p);\n\t\tdelete p;\n\t}\n}\n\nvoid CReplay::EmptyAllPools(void)\n{\n\tEmptyPedsAndVehiclePools();\n\tint i = CPools::GetObjectPool()->GetSize();\n\twhile (--i >= 0) {\n\t\tCObject* o = CPools::GetObjectPool()->GetSlot(i);\n\t\tif (!o)\n\t\t\tcontinue;\n\t\tCWorld::Remove(o);\n\t\tdelete o;\n\t}\n\ti = CPools::GetDummyPool()->GetSize();\n\twhile (--i >= 0) {\n\t\tCDummy* d = CPools::GetDummyPool()->GetSlot(i);\n\t\tif (!d)\n\t\t\tcontinue;\n\t\tCWorld::Remove(d);\n\t\tdelete d;\n\t}\n}\n\nvoid CReplay::MarkEverythingAsNew(void)\n{\n\tint i = CPools::GetVehiclePool()->GetSize();\n\twhile (--i >= 0) {\n\t\tCVehicle* v = CPools::GetVehiclePool()->GetSlot(i);\n\t\tif (!v)\n\t\t\tcontinue;\n\t\tv->bHasAlreadyBeenRecorded = false;\n\t}\n\ti = CPools::GetPedPool()->GetSize();\n\twhile (--i >= 0) {\n\t\tCPed* p = CPools::GetPedPool()->GetSlot(i);\n\t\tif (!p)\n\t\t\tcontinue;\n\t\tp->bHasAlreadyBeenRecorded = false;\n\t}\n}\n\nvoid CReplay::SaveReplayToHD(void)\n{\n\tCFileMgr::SetDirMyDocuments();\n\tint fw = CFileMgr::OpenFileForWriting(\"replay.rep\");\n#ifdef FIX_REPLAY_BUGS\n\tif (fw == 0) {\n#else\n\tif (fw < 0){ // BUG?\n#endif\n\t\tprintf(\"Couldn't open replay.rep for writing\");\n\t\tCFileMgr::SetDir(\"\");\n\t\treturn;\n\t}\n\tCFileMgr::Write(fw, \"gta3_7f\", sizeof(\"gta3_7f\"));\n\tint current;\n\tfor (current = 0; current < NUM_REPLAYBUFFERS; current++)\n\t\tif (BufferStatus[current] == REPLAYBUFFER_RECORD)\n\t\t\tbreak;\n\tint first;\n\tfor (first = (current + 1) % NUM_REPLAYBUFFERS; ; first = (first + 1) % NUM_REPLAYBUFFERS)\n\t\tif (BufferStatus[first] == REPLAYBUFFER_RECORD || BufferStatus[first] == REPLAYBUFFER_PLAYBACK)\n\t\t\tbreak;\n\tfor(int i = first; ; i = (i + 1) % NUM_REPLAYBUFFERS){\n\t\tCFileMgr::Write(fw, (char*)Buffers[i], sizeof(Buffers[i]));\n\t\tif (BufferStatus[i] == REPLAYBUFFER_RECORD)\n\t\t\tbreak;\n\t}\n\tCFileMgr::CloseFile(fw);\n\tCFileMgr::SetDir(\"\");\n}\n\nvoid CReplay::PlayReplayFromHD(void)\n{\n\tCFileMgr::SetDirMyDocuments();\n\tint fr = CFileMgr::OpenFile(\"replay.rep\", \"rb\");\n\tif (fr == 0) {\n\t\tprintf(\"Couldn't open replay.rep for reading\");\n#ifdef FIX_REPLAY_BUGS\n\tCFileMgr::SetDir(\"\");\n#endif\n\t\treturn;\n\t}\n\tCFileMgr::Read(fr, gString, 8);\n\tif (strncmp(gString, \"gta3_7f\", sizeof(\"gta3_7f\"))){\n\t\tCFileMgr::CloseFile(fr);\n\t\tprintf(\"Wrong file type for replay\");\n\t\tCFileMgr::SetDir(\"\");\n\t\treturn;\n\t}\n\tint slot;\n\tfor (slot = 0; CFileMgr::Read(fr, (char*)Buffers[slot], sizeof(Buffers[slot])); slot++)\n\t\tBufferStatus[slot] = REPLAYBUFFER_PLAYBACK;\n\tBufferStatus[slot - 1] = REPLAYBUFFER_RECORD;\n\twhile (slot < NUM_REPLAYBUFFERS)\n\t\tBufferStatus[slot++] = REPLAYBUFFER_UNUSED;\n\tCFileMgr::CloseFile(fr);\n\tCFileMgr::SetDir(\"\");\n\tTriggerPlayback(REPLAYCAMMODE_ASSTORED, 0.0f, 0.0f, 0.0f, false);\n\tbPlayingBackFromFile = true;\n\tbAllowLookAroundCam = true;\n\tStreamAllNecessaryCarsAndPeds();\n}\n\nvoid CReplay::StreamAllNecessaryCarsAndPeds(void)\n{\n\tfor (int slot = 0; slot < NUM_REPLAYBUFFERS; slot++) {\n\t\tif (BufferStatus[slot] == REPLAYBUFFER_UNUSED)\n\t\t\tcontinue;\n\t\tfor (size_t offset = 0; Buffers[slot][offset] != REPLAYPACKET_END; offset += FindSizeOfPacket(Buffers[slot][offset])) {\n\t\t\tswitch (Buffers[slot][offset]) {\n\t\t\tcase REPLAYPACKET_VEHICLE:\n\t\t\t\tCStreaming::RequestModel(((tVehicleUpdatePacket*)&Buffers[slot][offset])->mi, 0);\n\t\t\t\tbreak;\n\t\t\tcase REPLAYPACKET_BIKE:\n\t\t\t\tCStreaming::RequestModel(((tBikeUpdatePacket*)&Buffers[slot][offset])->mi, 0);\n\t\t\t\tbreak;\n\t\t\tcase REPLAYPACKET_PED_HEADER:\n\t\t\t\tCStreaming::RequestModel(((tPedHeaderPacket*)&Buffers[slot][offset])->mi, 0);\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\tCStreaming::LoadAllRequestedModels(false);\n}\n\nvoid CReplay::FindFirstFocusCoordinate(CVector *coord)\n{\n\t*coord = CVector(0.0f, 0.0f, 0.0f);\n\tfor (int slot = 0; slot < NUM_REPLAYBUFFERS; slot++) {\n\t\tif (BufferStatus[slot] == REPLAYBUFFER_UNUSED)\n\t\t\tcontinue;\n\t\tfor (size_t offset = 0; Buffers[slot][offset] != REPLAYPACKET_END; offset += FindSizeOfPacket(Buffers[slot][offset])) {\n\t\t\tif (Buffers[slot][offset] == REPLAYPACKET_GENERAL) {\n\t\t\t\t*coord = ((tGeneralPacket*)&Buffers[slot][offset])->player_pos;\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t}\n}\n\nbool CReplay::ShouldStandardCameraBeProcessed(void)\n{\n\tif (Mode != MODE_PLAYBACK)\n\t\treturn true;\n\tif (FramesActiveLookAroundCam || bPlayerInRCBuggy)\n\t\treturn false;\n\treturn FindPlayerVehicle() != nil;\n}\n\nvoid CReplay::ProcessLookAroundCam(void)\n{\n\tif (!bAllowLookAroundCam)\n\t\treturn;\n\tfloat x_moved = CPad::NewMouseControllerState.x / 200.0f;\n\tfloat y_moved = CPad::NewMouseControllerState.y / 200.0f;\n\tif (x_moved > 0.01f || y_moved > 0.01f) {\n\t\tif (FramesActiveLookAroundCam == 0)\n\t\t\tfDistanceLookAroundCam = 9.0f;\n\t\tFramesActiveLookAroundCam = 60;\n\t}\n\tif (bPlayerInRCBuggy)\n\t\tFramesActiveLookAroundCam = 0;\n\tif (!FramesActiveLookAroundCam)\n\t\treturn;\n\t--FramesActiveLookAroundCam;\n\tfBetaAngleLookAroundCam += x_moved;\n\tif (CPad::NewMouseControllerState.LMB && CPad::NewMouseControllerState.RMB)\n\t\tfDistanceLookAroundCam = Max(3.0f, Min(15.0f, fDistanceLookAroundCam + 2.0f * y_moved));\n\telse\n\t\tfAlphaAngleLookAroundCam = Max(0.1f, Min(1.5f, fAlphaAngleLookAroundCam + y_moved));\n\tCVector camera_pt(\n\t\tfDistanceLookAroundCam * Sin(fBetaAngleLookAroundCam) * Cos(fAlphaAngleLookAroundCam),\n\t\tfDistanceLookAroundCam * Cos(fBetaAngleLookAroundCam) * Cos(fAlphaAngleLookAroundCam),\n\t\tfDistanceLookAroundCam * Sin(fAlphaAngleLookAroundCam)\n\t);\n\tCVector focus = CVector(CameraFocusX, CameraFocusY, CameraFocusZ);\n\tcamera_pt += focus;\n\tCColPoint cp;\n\tCEntity* pe = nil;\n\tif (CWorld::ProcessLineOfSight(focus, camera_pt, cp, pe, true, false, false, false, false, true, true)){\n\t\tcamera_pt = cp.point;\n\t\tCVector direction = focus - cp.point;\n\t\tdirection.Normalise();\n\t\tcamera_pt += direction / 4.0f;\n\t}\n\tCVector forward = focus - camera_pt;\n\tforward.Normalise();\n\tCVector right = CrossProduct(CVector(0.0f, 0.0f, 1.0f), forward);\n\tright.Normalise();\n\tCVector up = CrossProduct(forward, right);\n\tup.Normalise();\n\tTheCamera.GetForward() = forward;\n\tTheCamera.GetUp() = up;\n\tTheCamera.GetRight() = right;\n\tTheCamera.SetPosition(camera_pt);\n\tRwMatrix* pm = RwFrameGetMatrix(RwCameraGetFrame(TheCamera.m_pRwCamera));\n\tpm->pos = TheCamera.GetPosition();\n\tpm->at = TheCamera.GetForward();\n\tpm->up = TheCamera.GetUp();\n\tpm->right = TheCamera.GetRight();\n\tTheCamera.CalculateDerivedValues();\n\tRwMatrixUpdate(RwFrameGetMatrix(RwCameraGetFrame(TheCamera.m_pRwCamera)));\n\tRwFrameUpdateObjects(RwCameraGetFrame(TheCamera.m_pRwCamera));\n}\n\nsize_t CReplay::FindSizeOfPacket(uint8 type)\n{\n\tswitch (type) {\n\tcase REPLAYPACKET_END:\t\t\treturn 4;\n\tcase REPLAYPACKET_VEHICLE:\t\treturn sizeof(tVehicleUpdatePacket);\n\tcase REPLAYPACKET_BIKE:\t\t\treturn sizeof(tBikeUpdatePacket);\n\tcase REPLAYPACKET_PED_HEADER:\treturn sizeof(tPedHeaderPacket);\n\tcase REPLAYPACKET_PED_UPDATE:\treturn sizeof(tPedUpdatePacket);\n\tcase REPLAYPACKET_GENERAL:\t\treturn sizeof(tGeneralPacket);\n\tcase REPLAYPACKET_CLOCK:\t\treturn sizeof(tClockPacket);\n\tcase REPLAYPACKET_WEATHER:\t\treturn sizeof(tWeatherPacket);\n\tcase REPLAYPACKET_ENDOFFRAME:\treturn 4;\n\tcase REPLAYPACKET_TIMER:\t\treturn sizeof(tTimerPacket);\n\tcase REPLAYPACKET_BULLET_TRACES:return sizeof(tBulletTracePacket);\n\tcase REPLAYPACKET_PARTICLE:\t\treturn sizeof(tParticlePacket);\n\tcase REPLAYPACKET_MISC:\t\t\treturn sizeof(tMiscPacket);\n\tdefault: assert(false); break;\n\t}\n\treturn 0;\n}\n\nvoid CReplay::Display()\n{\n\tstatic int TimeCount = 0;\n\tif (Mode == MODE_RECORD)\n\t\treturn;\n\tTimeCount = (TimeCount + 1) % UINT16_MAX;\n\tif ((TimeCount & 0x20) == 0)\n\t\treturn;\n\t\n\tCFont::SetScale(SCREEN_SCALE_X(1.5f), SCREEN_SCALE_Y(1.5f));\n\tCFont::SetJustifyOff();\n\tCFont::SetBackgroundOff();\n#ifdef FIX_BUGS\n\tCFont::SetCentreSize(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH-20));\n#else\n\tCFont::SetCentreSize(SCREEN_WIDTH-20);\n#endif\n\tCFont::SetCentreOff();\n\tCFont::SetPropOn();\n\tCFont::SetColor(CRGBA(255, 255, 200, 200));\n\tCFont::SetFontStyle(FONT_STANDARD);\n\tif (Mode == MODE_PLAYBACK)\n\t\tCFont::PrintString(SCREEN_WIDTH/15, SCREEN_HEIGHT/10, TheText.Get(\"REPLAY\"));\n}\n#endif\n"
  },
  {
    "path": "src/control/Replay.h",
    "content": "#pragma once\n\n#include \"Pools.h\"\n#include \"World.h\"\n#include \"WeaponEffects.h\"\n#include \"ParticleType.h\"\n\n#ifdef FIX_BUGS\n#ifndef DONT_FIX_REPLAY_BUGS\n#define FIX_REPLAY_BUGS\n#endif\n#endif\n\nclass CVehicle;\nstruct CReference;\n\nstruct CAddressInReplayBuffer\n{\n\tuint32 m_nOffset;\n\tuint8 *m_pBase;\n\tuint8 m_bSlot;\n};\n\nstruct CStoredAnimationState\n{\n\tuint8 animId;\n\tuint8 time;\n\tuint8 speed;\n\tuint8 groupId;\n\tuint8 secAnimId;\n\tuint8 secTime;\n\tuint8 secSpeed;\n\tuint8 secGroupId;\n\tuint8 blendAmount;\n\tuint8 partAnimId;\n\tuint8 partAnimTime;\n\tuint8 partAnimSpeed;\n\tuint8 partBlendAmount;\n\tuint8 partGroupId;\n};\n\nenum {\n\tNUM_MAIN_ANIMS_IN_REPLAY = 3,\n\tNUM_PARTIAL_ANIMS_IN_REPLAY = 6\n};\n\nstruct CStoredDetailedAnimationState\n{\n\tuint8 aAnimId[NUM_MAIN_ANIMS_IN_REPLAY];\n\tuint8 aCurTime[NUM_MAIN_ANIMS_IN_REPLAY];\n\tuint8 aSpeed[NUM_MAIN_ANIMS_IN_REPLAY];\n\tuint8 aBlendAmount[NUM_MAIN_ANIMS_IN_REPLAY];\n\tint8 aBlendDelta[NUM_MAIN_ANIMS_IN_REPLAY];\n\tuint8 aFunctionCallbackID[NUM_MAIN_ANIMS_IN_REPLAY];\n\tuint16 aFlags[NUM_MAIN_ANIMS_IN_REPLAY];\n\tuint8 aGroupId[NUM_MAIN_ANIMS_IN_REPLAY];\n\tuint8 aAnimId2[NUM_PARTIAL_ANIMS_IN_REPLAY];\n\tuint8 aCurTime2[NUM_PARTIAL_ANIMS_IN_REPLAY];\n\tuint8 aSpeed2[NUM_PARTIAL_ANIMS_IN_REPLAY];\n\tuint8 aBlendAmount2[NUM_PARTIAL_ANIMS_IN_REPLAY];\n\tint8 aBlendDelta2[NUM_PARTIAL_ANIMS_IN_REPLAY];\n\tuint8 aFunctionCallbackID2[NUM_PARTIAL_ANIMS_IN_REPLAY];\n\tuint16 aFlags2[NUM_PARTIAL_ANIMS_IN_REPLAY];\n\tuint8 aGroupId2[NUM_PARTIAL_ANIMS_IN_REPLAY];\n};\n\n#ifdef GTA_REPLAY\n#define REPLAY_STUB\n#else\n#define REPLAY_STUB {}\n#endif\n\nclass CReplay\n{\n\tenum {\n\t\tMODE_RECORD = 0,\n\t\tMODE_PLAYBACK = 1\n\t};\n\n\tenum {\n\t\tREPLAYCAMMODE_ASSTORED = 0,\n\t\tREPLAYCAMMODE_TOPDOWN,\n\t\tREPLAYCAMMODE_FIXED\n\t};\n\n\tenum {\n\t\tREPLAYPACKET_END = 0,\n\t\tREPLAYPACKET_VEHICLE,\n\t\tREPLAYPACKET_BIKE,\n\t\tREPLAYPACKET_PED_HEADER,\n\t\tREPLAYPACKET_PED_UPDATE,\n\t\tREPLAYPACKET_GENERAL,\n\t\tREPLAYPACKET_CLOCK,\n\t\tREPLAYPACKET_WEATHER,\n\t\tREPLAYPACKET_ENDOFFRAME,\n\t\tREPLAYPACKET_TIMER,\n\t\tREPLAYPACKET_BULLET_TRACES,\n\t\tREPLAYPACKET_PARTICLE,\n\t\tREPLAYPACKET_MISC\n\t};\n\n\tenum {\n\t\tREPLAYBUFFER_UNUSED = 0,\n\t\tREPLAYBUFFER_PLAYBACK = 1,\n\t\tREPLAYBUFFER_RECORD = 2\n\t};\n\n\tenum {\n\t\tNUM_REPLAYBUFFERS = 8,\n\t\tREPLAYBUFFERSIZE = 100000\n\t};\n\n\n\tstruct tGeneralPacket\n\t{\n\t\tuint8 type;\n\t\tbool in_rcvehicle;\n\t\tCMatrix camera_pos;\n\t\tCVector player_pos;\n\t};\n\n\tVALIDATE_SIZE(tGeneralPacket, 88);\n\n\tstruct tClockPacket\n\t{\n\t\tuint8 type;\n\t\tuint8 hours;\n\t\tuint8 minutes;\n\tprivate:\n\t\tuint8 __align;\n\t};\n\tVALIDATE_SIZE(tClockPacket, 4);\n\n\tstruct tWeatherPacket\n\t{\n\t\tuint8 type;\n\t\tuint8 old_weather;\n\t\tuint8 new_weather;\n\t\tfloat interpolation;\n\t};\n\tVALIDATE_SIZE(tWeatherPacket, 8);\n\n\tstruct tTimerPacket\n\t{\n\t\tuint8 type;\n\t\tuint32 timer;\n\t};\n\tVALIDATE_SIZE(tTimerPacket, 8);\n\n\tstruct tPedHeaderPacket\n\t{\n\t\tuint8 type;\n\t\tuint8 index;\n\t\tuint16 mi;\n\t\tuint8 pedtype;\n\tprivate:\n\t\tuint8 __align[3];\n\t};\n\tVALIDATE_SIZE(tPedHeaderPacket, 8);\n\n\tstruct tBulletTracePacket\n\t{\n\t\tuint8 type;\n\t\tuint8 frames;\n\t\tuint8 lifetime;\n\t\tuint8 index;\n\t\tCVector inf;\n\t\tCVector sup;\n\t};\n\tVALIDATE_SIZE(tBulletTracePacket, 28);\n\n\tstruct tEndOfFramePacket\n\t{\n\t\tuint8 type;\n\tprivate:\n\t\tuint8 __align[3];\n\t};\n\tVALIDATE_SIZE(tEndOfFramePacket, 4);\n\n\tstruct tPedUpdatePacket\n\t{\n\t\tuint8 type;\n\t\tuint8 index;\n\t\tint8 heading;\n\t\tint8 vehicle_index;\n\t\tCStoredAnimationState anim_state;\n\t\tCCompressedMatrixNotAligned matrix;\n\t\tuint16 weapon_model;\n\t\tint8 assoc_group_id;\n\t\tbool is_visible;\n\t};\n\tVALIDATE_SIZE(tPedUpdatePacket, 40);\n\n\tstruct tVehicleUpdatePacket\n\t{\n\t\tuint8 type;\n\t\tuint8 index;\n\t\tuint8 health;\n\t\tuint8 acceleration;\n\t\tCCompressedMatrixNotAligned matrix;\n\t\tint8 door_angles[2];\n\t\tuint16 mi;\n\t\tuint32 panels;\n\t\tint8 velocityX;\n\t\tint8 velocityY;\n\t\tint8 velocityZ;\n\t\tunion {\n\t\t\tint8 car_gun;\n\t\t\tint8 wheel_state;\n\t\t};\n\t\tuint8 wheel_susp_dist[4];\n\t\tuint8 wheel_rotation[4];\n\t\tuint8 door_status;\n\t\tuint8 primary_color;\n\t\tuint8 secondary_color;\n\t\tbool render_scorched;\n\t\tint8 skimmer_speed;\n\t\tint8 vehicle_type;\n\n\t};\n\tVALIDATE_SIZE(tVehicleUpdatePacket, 52);\n\n\tstruct tBikeUpdatePacket\n\t{\n\t\tuint8 type;\n\t\tuint8 index;\n\t\tuint8 health;\n\t\tuint8 acceleration;\n\t\tCCompressedMatrixNotAligned matrix;\n\t\tint8 door_angles[2];\n\t\tuint16 mi;\n\t\tint8 velocityX;\n\t\tint8 velocityY;\n\t\tint8 velocityZ;\n\t\tint8 wheel_state;\n\t\tuint8 wheel_susp_dist[4];\n\t\tuint8 wheel_rotation[4];\n\t\tuint8 primary_color;\n\t\tuint8 secondary_color;\n\t\tint8 lean_angle;\n\t\tint8 wheel_angle;\n\n\t};\n\tVALIDATE_SIZE(tBikeUpdatePacket, 44);\n\n\tstruct tParticlePacket\n\t{\n\t\tuint8 type;\n\t\tuint8 particle_type;\n\t\tint8 dir_x;\n\t\tint8 dir_y;\n\t\tint8 dir_z;\n\t\tuint8 r;\n\t\tuint8 g;\n\t\tuint8 b;\n\t\tuint8 a;\n\t\tint16 pos_x;\n\t\tint16 pos_y;\n\t\tint16 pos_z;\n\t\tfloat size;\n\t};\n\tVALIDATE_SIZE(tParticlePacket, 20);\n\n\tstruct tMiscPacket\n\t{\n\t\tuint8 type;\n\t\tuint32 cam_shake_start;\n\t\tfloat cam_shake_strength;\n\t\tuint8 cur_area;\n\t\tuint8 video_cam : 1;\n\t\tuint8 lift_cam : 1;\n\t};\n\n\tVALIDATE_SIZE(tMiscPacket, 16);\n\nprivate:\n\tstatic uint8 Mode;\n\tstatic CAddressInReplayBuffer Record;\n\tstatic CAddressInReplayBuffer Playback;\n\tstatic uint8* pBuf0;\n\tstatic CAutomobile* pBuf1;\n\tstatic uint8* pBuf2;\n\tstatic CPlayerPed* pBuf3;\n\tstatic uint8* pBuf4;\n\tstatic CCutsceneObject* pBuf5;\n\tstatic uint8* pBuf6;\n\tstatic CPtrNode* pBuf7;\n\tstatic uint8* pBuf8;\n\tstatic CEntryInfoNode* pBuf9;\n\tstatic uint8* pBuf10;\n\tstatic CDummyPed* pBuf11;\n\tstatic uint8* pRadarBlips;\n\tstatic uint8* pStoredCam;\n\tstatic uint8* pWorld1;\n\tstatic CReference* pEmptyReferences;\n\tstatic CStoredDetailedAnimationState* pPedAnims;\n\tstatic uint8* pPickups;\n\tstatic uint8* pReferences;\n\tstatic uint8 BufferStatus[NUM_REPLAYBUFFERS];\n\tstatic uint8 Buffers[NUM_REPLAYBUFFERS][REPLAYBUFFERSIZE];\n\tstatic bool bPlayingBackFromFile;\n\tstatic bool bReplayEnabled;\n\tstatic uint32 SlowMotion;\n\tstatic uint32 FramesActiveLookAroundCam;\n\tstatic bool bDoLoadSceneWhenDone;\n\tstatic CPtrNode* WorldPtrList;\n\tstatic CPtrNode* BigBuildingPtrList;\n\tstatic CWanted PlayerWanted;\n\tstatic CPlayerInfo PlayerInfo;\n\tstatic uint32 Time1;\n\tstatic uint32 Time2;\n\tstatic uint32 Time3;\n\tstatic uint32 Time4;\n\tstatic uint32 Frame;\n\tstatic uint8 ClockHours;\n\tstatic uint8 ClockMinutes;\n\tstatic uint16 OldWeatherType;\n\tstatic uint16 NewWeatherType;\n\tstatic float WeatherInterpolationValue;\n\tstatic float TimeStepNonClipped;\n\tstatic float TimeStep;\n\tstatic float TimeScale;\n\tstatic float CameraFixedX;\n\tstatic float CameraFixedY;\n\tstatic float CameraFixedZ;\n\tstatic int32 OldRadioStation;\n\tstatic int8 CameraMode;\n\tstatic bool bAllowLookAroundCam;\n\tstatic float LoadSceneX;\n\tstatic float LoadSceneY;\n\tstatic float LoadSceneZ;\n\tstatic float CameraFocusX;\n\tstatic float CameraFocusY;\n\tstatic float CameraFocusZ;\n\tstatic bool bPlayerInRCBuggy;\n\tstatic float fDistanceLookAroundCam;\n\tstatic float fAlphaAngleLookAroundCam;\n\tstatic float fBetaAngleLookAroundCam;\n\tstatic int ms_nNumCivMale_Stored;\n\tstatic int ms_nNumCivFemale_Stored;\n\tstatic int ms_nNumCop_Stored;\n\tstatic int ms_nNumEmergency_Stored;\n\tstatic int ms_nNumGang1_Stored;\n\tstatic int ms_nNumGang2_Stored;\n\tstatic int ms_nNumGang3_Stored;\n\tstatic int ms_nNumGang4_Stored;\n\tstatic int ms_nNumGang5_Stored;\n\tstatic int ms_nNumGang6_Stored;\n\tstatic int ms_nNumGang7_Stored;\n\tstatic int ms_nNumGang8_Stored;\n\tstatic int ms_nNumGang9_Stored;\n\tstatic int ms_nNumDummy_Stored;\n\tstatic int ms_nTotalCarPassengerPeds_Stored;\n\tstatic int ms_nTotalCivPeds_Stored;\n\tstatic int ms_nTotalGangPeds_Stored;\n\tstatic int ms_nTotalPeds_Stored;\n\tstatic int ms_nTotalMissionPeds_Stored;\n\tstatic uint8* pGarages;\n\tstatic CFire* FireArray;\n\tstatic uint32 NumOfFires;\n\tstatic uint8* paProjectileInfo;\n\tstatic uint8* paProjectiles;\n\tstatic uint8 CurrArea;\n#ifdef FIX_BUGS\n\tstatic int nHandleOfPlayerPed[NUMPLAYERS];\n#endif\n\npublic:\n\tstatic void Init(void) REPLAY_STUB;\n\tstatic void DisableReplays(void) REPLAY_STUB;\n\tstatic void EnableReplays(void) REPLAY_STUB;\n\tstatic void Update(void) REPLAY_STUB;\n\tstatic void FinishPlayback(void) REPLAY_STUB;\n\tstatic void EmptyReplayBuffer(void) REPLAY_STUB;\n\tstatic void Display(void) REPLAY_STUB;\n\tstatic void TriggerPlayback(uint8 cam_mode, float cam_x, float cam_y, float cam_z, bool load_scene) REPLAY_STUB;\n\tstatic void StreamAllNecessaryCarsAndPeds(void) REPLAY_STUB;\n\tstatic void RecordParticle(tParticleType type, CVector const& vecPos, CVector const& vecDir, float fSize, RwRGBA const& color) REPLAY_STUB;\n\n#ifndef GTA_REPLAY\n\tstatic bool ShouldStandardCameraBeProcessed(void) { return true; }\n\tstatic bool IsPlayingBack() { return false; }\n\tstatic bool IsPlayingBackFromFile() { return false; }\n#else\n\tstatic bool ShouldStandardCameraBeProcessed(void);\n\tstatic bool IsPlayingBack() { return Mode == MODE_PLAYBACK; }\n\tstatic bool IsPlayingBackFromFile() { return bPlayingBackFromFile; }\nprivate:\n\tstatic void RecordThisFrame(void);\n\tstatic void StorePedUpdate(CPed *ped, int id);\n\tstatic void StorePedAnimation(CPed *ped, CStoredAnimationState *state);\n\tstatic void StoreDetailedPedAnimation(CPed *ped, CStoredDetailedAnimationState *state);\n\tstatic void ProcessPedUpdate(CPed *ped, float interpolation, CAddressInReplayBuffer *buffer);\n\tstatic void RetrievePedAnimation(CPed *ped, CStoredAnimationState *state);\n\tstatic void RetrieveDetailedPedAnimation(CPed *ped, CStoredDetailedAnimationState *state);\n\tstatic void PlaybackThisFrame(void);\n\tstatic void TriggerPlaybackLastCoupleOfSeconds(uint32, uint8, float, float, float, uint32);\n\tstatic bool FastForwardToTime(uint32);\n\tstatic void StoreCarUpdate(CVehicle *vehicle, int id);\n\tstatic void StoreBikeUpdate(CVehicle* vehicle, int id);\n\tstatic void ProcessCarUpdate(CVehicle *vehicle, float interpolation, CAddressInReplayBuffer *buffer);\n\tstatic void ProcessBikeUpdate(CVehicle* vehicle, float interpolation, CAddressInReplayBuffer* buffer);\n\tstatic bool PlayBackThisFrameInterpolation(CAddressInReplayBuffer *buffer, float interpolation, uint32 *pTimer);\n\tstatic void ProcessReplayCamera(void);\n\tstatic void StoreStuffInMem(void);\n\tstatic void RestoreStuffFromMem(void);\n\tstatic void EmptyPedsAndVehiclePools(void);\n\tstatic void EmptyAllPools(void);\n\tstatic void MarkEverythingAsNew(void);\n\tstatic void SaveReplayToHD(void);\n\tstatic void PlayReplayFromHD(void); // out of class in III PC and later because of SecuROM\n\tstatic void FindFirstFocusCoordinate(CVector *coord);\n\tstatic void ProcessLookAroundCam(void);\n\tstatic size_t FindSizeOfPacket(uint8);\n\tstatic void GoToNextBlock(void);\n#endif\n};\n"
  },
  {
    "path": "src/control/Restart.cpp",
    "content": "#include \"common.h\"\n\n#include \"Restart.h\"\n#include \"Zones.h\"\n#include \"PathFind.h\"\n\nuint8 CRestart::OverrideHospitalLevel;\nuint8 CRestart::OverridePoliceStationLevel;\nbool CRestart::bFadeInAfterNextArrest;\nbool CRestart::bFadeInAfterNextDeath;\n\nbool CRestart::bOverrideRestart;\nCVector CRestart::OverridePosition;\nfloat CRestart::OverrideHeading;\n\nCVector CRestart::HospitalRestartPoints[NUM_RESTART_POINTS];\nfloat CRestart::HospitalRestartHeadings[NUM_RESTART_POINTS];\nuint16 CRestart::NumberOfHospitalRestarts;\n\nCVector CRestart::PoliceRestartPoints[NUM_RESTART_POINTS];\nfloat CRestart::PoliceRestartHeadings[NUM_RESTART_POINTS];\nuint16 CRestart::NumberOfPoliceRestarts;\n\nvoid\nCRestart::Initialise()\n{\n\tOverridePoliceStationLevel = LEVEL_GENERIC;\n\tOverrideHospitalLevel = LEVEL_GENERIC;\n\tbFadeInAfterNextArrest = true;\n\tbFadeInAfterNextDeath = true;\n\tOverrideHeading = 0.0f;\n\tOverridePosition = CVector(0.0f, 0.0f, 0.0f);\n\tbOverrideRestart = false;\n\tNumberOfPoliceRestarts = 0;\n\tNumberOfHospitalRestarts = 0;\n\n\tfor (int i = 0; i < NUM_RESTART_POINTS; i++) {\n\t\tHospitalRestartPoints[i] = CVector(0.0f, 0.0f, 0.0f);\n\t\tHospitalRestartHeadings[i] = 0.0f;\n\t\tPoliceRestartPoints[i] = CVector(0.0f, 0.0f, 0.0f);\n\t\tPoliceRestartHeadings[i] = 0.0f;\n\t}\n}\n\nvoid\nCRestart::AddHospitalRestartPoint(const CVector &pos, float heading)\n{\n\tHospitalRestartPoints[NumberOfHospitalRestarts] = pos;\n\tHospitalRestartHeadings[NumberOfHospitalRestarts++] = heading;\n}\n\nvoid\nCRestart::AddPoliceRestartPoint(const CVector &pos, float heading)\n{\n\tPoliceRestartPoints[NumberOfPoliceRestarts] = pos;\n\tPoliceRestartHeadings[NumberOfPoliceRestarts++] = heading;\n}\n\nvoid\nCRestart::OverrideNextRestart(const CVector &pos, float heading)\n{\n\tbOverrideRestart = true;\n\tOverridePosition = pos;\n\tOverrideHeading = heading;\n}\n\nvoid\nCRestart::CancelOverrideRestart()\n{\n\tbOverrideRestart = false;\n}\n\nvoid\nCRestart::FindClosestHospitalRestartPoint(const CVector &pos, CVector *outPos, float *outHeading)\n{\n\tif (bOverrideRestart) {\n\t\t*outPos = OverridePosition;\n\t\t*outHeading = OverrideHeading;\n\t\tCancelOverrideRestart();\n\t\treturn;\n\t}\n\n\teLevelName curlevel = CTheZones::GetLevelFromPosition(&pos);\n\tfloat fMinDist = SQR(4000.0f);\n\tint closestPoint = NUM_RESTART_POINTS;\n\n\t// find closest point on this level\n\tfor (int i = 0; i < NumberOfHospitalRestarts; i++) {\n\t\tif (CTheZones::GetLevelFromPosition(&HospitalRestartPoints[i]) == (OverrideHospitalLevel != LEVEL_GENERIC ? OverrideHospitalLevel : curlevel)) {\n\t\t\tfloat dist = (pos - HospitalRestartPoints[i]).MagnitudeSqr();\n\t\t\tif (fMinDist >= dist) {\n\t\t\t\tfMinDist = dist;\n\t\t\t\tclosestPoint = i;\n\t\t\t}\n\t\t}\n\t}\n\n\t// if we didn't find anything, find closest point on any level\n\tif (closestPoint == NUM_RESTART_POINTS) {\n\t\tfor (int i = 0; i < NumberOfHospitalRestarts; i++) {\n\t\t\tfloat dist = (pos - HospitalRestartPoints[i]).MagnitudeSqr();\n\t\t\tif (fMinDist >= dist) {\n\t\t\t\tfMinDist = dist;\n\t\t\t\tclosestPoint = i;\n\t\t\t}\n\t\t}\n\t}\n\n\t// if we still didn't find anything, find closest path node\n\tif (closestPoint == NUM_RESTART_POINTS) {\n\t\t*outPos = ThePaths.m_pathNodes[ThePaths.FindNodeClosestToCoors(pos, PATH_PED, 999999.9f)].GetPosition();\n\t\t*outHeading = 0.0f;\n\t\tprintf(\"Couldn't find a hospital restart zone near the player %f %f %f->%f %f %f\\n\", pos.x, pos.y, pos.z, outPos->x, outPos->y, outPos->z);\n\t} else {\n\t\t*outPos = HospitalRestartPoints[closestPoint];\n\t\t*outHeading = HospitalRestartHeadings[closestPoint];\n\t}\n}\n\nvoid\nCRestart::FindClosestPoliceRestartPoint(const CVector &pos, CVector *outPos, float *outHeading)\n{\n\tif (bOverrideRestart) {\n\t\t*outPos = OverridePosition;\n\t\t*outHeading = OverrideHeading;\n\t\tCancelOverrideRestart();\n\t\treturn;\n\t}\n\n\teLevelName curlevel = CTheZones::GetLevelFromPosition(&pos);\n\tfloat fMinDist = SQR(4000.0f);\n\tint closestPoint = NUM_RESTART_POINTS;\n\n\t// find closest point on this level\n\tfor (int i = 0; i < NumberOfPoliceRestarts; i++) {\n\t\tif (CTheZones::GetLevelFromPosition(&PoliceRestartPoints[i]) == (OverridePoliceStationLevel != LEVEL_GENERIC ? OverridePoliceStationLevel : curlevel)) {\n\t\t\tfloat dist = (pos - PoliceRestartPoints[i]).MagnitudeSqr();\n\t\t\tif (fMinDist >= dist) {\n\t\t\t\tfMinDist = dist;\n\t\t\t\tclosestPoint = i;\n\t\t\t}\n\t\t}\n\t}\n\n\t// if we didn't find anything, find closest point on any level\n\tif (closestPoint == NUM_RESTART_POINTS) {\n\t\tfor (int i = 0; i < NumberOfPoliceRestarts; i++) {\n\t\t\tfloat dist = (pos - PoliceRestartPoints[i]).MagnitudeSqr();\n\t\t\tif (fMinDist >= dist) {\n\t\t\t\tfMinDist = dist;\n\t\t\t\tclosestPoint = i;\n\t\t\t}\n\t\t}\n\t}\n\n\t// if we still didn't find anything, find closest path node\n\tif (closestPoint == NUM_RESTART_POINTS) {\n\t\tprintf(\"Couldn't find a police restart zone near the player\\n\");\n\t\t*outPos = ThePaths.m_pathNodes[ThePaths.FindNodeClosestToCoors(pos, PATH_PED, 999999.9f)].GetPosition();\n\t\t*outHeading = 0.0f;\n\t} else {\n\t\t*outPos = PoliceRestartPoints[closestPoint];\n\t\t*outHeading = PoliceRestartHeadings[closestPoint];\n\t}\n}\n\nvoid\nCRestart::LoadAllRestartPoints(uint8 *buf, uint32 size)\n{\n\tInitialise();\n\nINITSAVEBUF\n\tCheckSaveHeader(buf, 'R','S','T','\\0', size - SAVE_HEADER_SIZE);\n\n\tfor (int i = 0; i < NUM_RESTART_POINTS; i++) {\n\t\tHospitalRestartPoints[i] = ReadSaveBuf<CVector>(buf);\n\t\tHospitalRestartHeadings[i] = ReadSaveBuf<float>(buf);\n\t}\n\n\tfor (int i = 0; i < NUM_RESTART_POINTS; i++) {\n\t\tPoliceRestartPoints[i] = ReadSaveBuf<CVector>(buf);\n\t\tPoliceRestartHeadings[i] = ReadSaveBuf<float>(buf);\n\t}\n\n\tNumberOfHospitalRestarts = ReadSaveBuf<uint16>(buf);\n\tNumberOfPoliceRestarts = ReadSaveBuf<uint16>(buf);\n\tbOverrideRestart = ReadSaveBuf<bool>(buf);\n\n\t// skip something unused\n\tReadSaveBuf<uint8>(buf);\n\tReadSaveBuf<uint16>(buf);\n\n\tOverridePosition = ReadSaveBuf<CVector>(buf);\n\tOverrideHeading = ReadSaveBuf<float>(buf);\n\tbFadeInAfterNextDeath = ReadSaveBuf<bool>(buf);\n\tbFadeInAfterNextArrest = ReadSaveBuf<bool>(buf);\n\tOverrideHospitalLevel = ReadSaveBuf<uint8>(buf);\n\tOverridePoliceStationLevel = ReadSaveBuf<uint8>(buf);\nVALIDATESAVEBUF(size);\n}\n\nvoid\nCRestart::SaveAllRestartPoints(uint8 *buf, uint32 *size)\n{\n\t*size = SAVE_HEADER_SIZE\n\t\t+ sizeof(HospitalRestartPoints)\n\t\t+ sizeof(HospitalRestartHeadings)\n\t\t+ sizeof(PoliceRestartPoints)\n\t\t+ sizeof(PoliceRestartHeadings)\n\t\t+ sizeof(NumberOfHospitalRestarts)\n\t\t+ sizeof(NumberOfPoliceRestarts)\n\t\t+ sizeof(bOverrideRestart)\n\t\t+ sizeof(uint8)\n\t\t+ sizeof(uint16)\n\t\t+ sizeof(OverridePosition)\n\t\t+ sizeof(OverrideHeading)\n\t\t+ sizeof(bFadeInAfterNextDeath)\n\t\t+ sizeof(bFadeInAfterNextArrest)\n\t\t+ sizeof(OverrideHospitalLevel)\n\t\t+ sizeof(OverridePoliceStationLevel); // == 292\n\nINITSAVEBUF\n\tWriteSaveHeader(buf, 'R','S','T','\\0', *size - SAVE_HEADER_SIZE);\n\n\tfor (int i = 0; i < NUM_RESTART_POINTS; i++) {\n\t\tWriteSaveBuf(buf, HospitalRestartPoints[i]);\n\t\tWriteSaveBuf(buf, HospitalRestartHeadings[i]);\n\t}\n\n\tfor (int i = 0; i < NUM_RESTART_POINTS; i++) {\n\t\tWriteSaveBuf(buf, PoliceRestartPoints[i]);\n\t\tWriteSaveBuf(buf, PoliceRestartHeadings[i]);\n\t}\n\n\tWriteSaveBuf(buf, NumberOfHospitalRestarts);\n\tWriteSaveBuf(buf, NumberOfPoliceRestarts);\n\tWriteSaveBuf(buf, bOverrideRestart);\n\n\tWriteSaveBuf(buf, (uint8)0);\n\tWriteSaveBuf(buf, (uint16)0);\n\n\tWriteSaveBuf(buf, OverridePosition);\n\tWriteSaveBuf(buf, OverrideHeading);\n\tWriteSaveBuf(buf, bFadeInAfterNextDeath);\n\tWriteSaveBuf(buf, bFadeInAfterNextArrest);\n\tWriteSaveBuf(buf, OverrideHospitalLevel);\n\tWriteSaveBuf(buf, OverridePoliceStationLevel);\nVALIDATESAVEBUF(*size);\n}\n"
  },
  {
    "path": "src/control/Restart.h",
    "content": "#pragma once\n\n#define NUM_RESTART_POINTS 8\n\nclass CRestart\n{\npublic:\n\tstatic void AddPoliceRestartPoint(const CVector&, float);\n\tstatic void AddHospitalRestartPoint(const CVector&, float);\n\tstatic void OverrideNextRestart(const CVector&, float);\n\n\tstatic void FindClosestHospitalRestartPoint(const CVector &, CVector *, float *);\n\tstatic void FindClosestPoliceRestartPoint(const CVector &, CVector *, float *);\n\tstatic void Initialise();\n\tstatic void CancelOverrideRestart();\n\n\tstatic void LoadAllRestartPoints(uint8 *buf, uint32 size);\n\tstatic void SaveAllRestartPoints(uint8 *buf, uint32 *size);\n\n\tstatic uint8 OverrideHospitalLevel;\n\tstatic uint8 OverridePoliceStationLevel;\n\tstatic bool bFadeInAfterNextArrest;\n\tstatic bool bFadeInAfterNextDeath;\n\n\tstatic bool bOverrideRestart;\n\tstatic CVector OverridePosition;\n\tstatic float OverrideHeading;\n\n\tstatic CVector HospitalRestartPoints[NUM_RESTART_POINTS];\n\tstatic float HospitalRestartHeadings[NUM_RESTART_POINTS];\n\tstatic uint16 NumberOfHospitalRestarts;\n\n\tstatic CVector PoliceRestartPoints[NUM_RESTART_POINTS];\n\tstatic float PoliceRestartHeadings[NUM_RESTART_POINTS];\n\tstatic uint16 NumberOfPoliceRestarts;\n};\n"
  },
  {
    "path": "src/control/RoadBlocks.cpp",
    "content": "#include \"common.h\"\n\n#include \"RoadBlocks.h\"\n#include \"PathFind.h\"\n#include \"ModelIndices.h\"\n#include \"Streaming.h\"\n#include \"World.h\"\n#include \"PedPlacement.h\"\n#include \"Automobile.h\"\n#include \"CopPed.h\"\n#include \"VisibilityPlugins.h\"\n#include \"PlayerPed.h\"\n#include \"Wanted.h\"\n#include \"Camera.h\"\n#include \"CarCtrl.h\"\n#include \"General.h\"\n#include \"Object.h\"\n\n#define ROADBLOCKDIST (90.0f)\n#define ROADBLOCK_OBJECT_WIDTH (4.0f)\n\nint16 CRoadBlocks::NumRoadBlocks;\nint16 CRoadBlocks::RoadBlockNodes[NUMROADBLOCKS];\nbool CRoadBlocks::InOrOut[NUMROADBLOCKS];\nCScriptRoadblock CRoadBlocks::aScriptRoadBlocks[NUM_SCRIPT_ROADBLOCKS];\n\n#ifdef SECUROM\nuint8 roadBlocksPirateCheck = 0;\n#endif\n\nvoid\nCRoadBlocks::Init(void)\n{\n\tint i;\n\tNumRoadBlocks = 0;\n\tfor(i = 0; i < ThePaths.m_numCarPathNodes; i++){\n\t\tif(ThePaths.m_pathNodes[i].bUseInRoadBlock && ThePaths.m_pathNodes[i].numLinks == 2){\n\t\t\tif (NumRoadBlocks < NUMROADBLOCKS) {\n\t\t\t\tInOrOut[NumRoadBlocks] = true;\n\t\t\t\tRoadBlockNodes[NumRoadBlocks] = i;\n\t\t\t\tNumRoadBlocks++;\n\t\t\t} else {\n#ifndef MASTER\n\t\t\t\tprintf(\"Not enough room for the potential roadblocks\\n\");\n#endif\n\t\t\t\t// FIX: Don't iterate loop after NUMROADBLOCKS\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t}\n\n\tClearScriptRoadBlocks();\n}\n\nvoid\nCRoadBlocks::GenerateRoadBlockCopsForCar(CVehicle* pVehicle, int32 roadBlockType)\n{\n\tstatic const CVector vecRoadBlockOffets[6] = { CVector(-1.5, 1.8f, 0.0f), CVector(-1.5f, -1.8f, 0.0f), CVector(1.5f, 1.8f, 0.0f),\n\tCVector(1.5f, -1.8f, 0.0f), CVector(-1.5f, 0.0f, 0.0f), CVector(1.5, 0.0, 0.0) };\n\tCEntity* pEntityToAttack = (CEntity*)FindPlayerVehicle();\n\tif (!pEntityToAttack)\n\t\tpEntityToAttack = (CEntity*)FindPlayerPed();\n\tCColModel* pPoliceColModel = CModelInfo::GetModelInfo(MI_POLICE)->GetColModel();\n\tfloat fRadius = pVehicle->GetBoundRadius() / pPoliceColModel->boundingSphere.radius;\n\tfor (int32 i = 0; i < 2; i++) {\n\t\tconst int32 roadBlockIndex = i + 2 * roadBlockType;\n\t\tCVector posForZ = pVehicle->m_matrix * (fRadius * vecRoadBlockOffets[roadBlockIndex]);\n\t\tint32 modelInfoId = MI_COP;\n\t\teCopType copType = COP_STREET;\n\t\tswitch (pVehicle->GetModelIndex())\n\t\t{\n\t\tcase MI_FBIRANCH:\n\t\t\tmodelInfoId = MI_FBI;\n\t\t\tcopType = COP_FBI;\n\t\t\tbreak;\n\t\tcase MI_ENFORCER:\n\t\t\tmodelInfoId = MI_SWAT;\n\t\t\tcopType = COP_SWAT;\n\t\t\tbreak;\n\t\tcase MI_BARRACKS:\n\t\t\tmodelInfoId = MI_ARMY;\n\t\t\tcopType = COP_ARMY;\n\t\t\tbreak;\n\t\t}\n\t\tif (!CStreaming::HasModelLoaded(modelInfoId))\n\t\t\tcopType = COP_STREET;\n\t\tCCopPed* pCopPed = new CCopPed(copType);\n\t\tif (copType == COP_STREET)\n\t\t\tpCopPed->SetCurrentWeapon(WEAPONTYPE_COLT45);\n\t\tCPedPlacement::FindZCoorForPed(&posForZ);\n\t\tpCopPed->SetPosition(posForZ);\n\t\tpCopPed->SetOrientation(0.0f, 0.0f, -HALFPI);\n\t\tpCopPed->m_bIsDisabledCop = true;\n\t\tpCopPed->SetIdle();\n\t\tpCopPed->bKindaStayInSamePlace = true;\n\t\tpCopPed->bNotAllowedToDuck = false;\n\t\tpCopPed->m_nExtendedRangeTimer = CTimer::GetTimeInMilliseconds() + 10000;\n\t\tpCopPed->m_nRoadblockVeh = pVehicle;\n\t\tpCopPed->m_nRoadblockVeh->RegisterReference((CEntity**)&pCopPed->m_nRoadblockVeh);\n\t\tpCopPed->bCrouchWhenShooting = roadBlockType == 2 ? false : true;\n\t\tif (pEntityToAttack) {\n\t\t\tpCopPed->SetWeaponLockOnTarget(pEntityToAttack);\n\t\t\tpCopPed->SetAttack(pEntityToAttack);\n\t\t}\n\t\tpCopPed->m_pMyVehicle = pVehicle;\n\t\tpVehicle->RegisterReference((CEntity**)&pCopPed->m_pMyVehicle);\n\t\tpCopPed->bCullExtraFarAway = true;\n\t\tCVisibilityPlugins::SetClumpAlpha(pCopPed->GetClump(), 0);\n\t\tCWorld::Add(pCopPed);\n\t}\n}\n\nvoid \nCRoadBlocks::GenerateRoadBlocks(void) \n{ \n\tCMatrix tmp1, tmp2;\n\tstatic int16 unk;\n#ifdef SQUEEZE_PERFORMANCE\n\tif (FindPlayerPed()->m_pWanted->m_RoadblockDensity == 0)\n\t\treturn;\n#endif\n\tuint32 frame = CTimer::GetFrameCounter() & 0xF;\n\tint16 nRoadblockNode = (int16)(NUMROADBLOCKS * frame) / 16;\n\tconst int16 maxRoadBlocks = (int16)(NUMROADBLOCKS * (frame + 1)) / 16;\n\tfor (; nRoadblockNode < Min(NumRoadBlocks, maxRoadBlocks); nRoadblockNode++) {\n\t\tint16 node = RoadBlockNodes[nRoadblockNode];\n\t\tCVector2D vecDistance = FindPlayerCoors() - ThePaths.m_pathNodes[node].GetPosition();\n\t\tif (vecDistance.x > -ROADBLOCKDIST && vecDistance.x < ROADBLOCKDIST &&\n\t\t\tvecDistance.y > -ROADBLOCKDIST && vecDistance.y < ROADBLOCKDIST &&\n\t\t\tvecDistance.Magnitude() < ROADBLOCKDIST) {\n\t\t\tif (!InOrOut[nRoadblockNode]) {\n\t\t\t\tInOrOut[nRoadblockNode] = true;\n\t\t\t\tif (FindPlayerVehicle() && (CGeneral::GetRandomNumber() & 0x7F) < FindPlayerPed()->m_pWanted->m_RoadblockDensity) {\n\t\t\t\t\tCCarPathLink* pLink1 = &ThePaths.m_carPathLinks[ThePaths.m_carPathConnections[ThePaths.m_pathNodes[node].firstLink]];\n\t\t\t\t\tCCarPathLink* pLink2 = &ThePaths.m_carPathLinks[ThePaths.m_carPathConnections[ThePaths.m_pathNodes[node].firstLink + 1]];\n\t\t\t\t\tint lanes = Min(pLink1->numRightLanes + pLink1->numLeftLanes, pLink2->numLeftLanes + pLink2->numRightLanes);\n\t\t\t\t\tfloat length = LANE_WIDTH * (lanes + 1);\n\t\t\t\t\tCVector forward(pLink2->GetY() - pLink1->GetY(), -(pLink2->GetX() - pLink1->GetX()), 0.0f);\n\t\t\t\t\tforward.Normalise();\n\t\t\t\t\tif (ThePaths.m_pathNodes[node].HasDivider()) {\n\t\t\t\t\t\tCreateRoadBlockBetween2Points(\n\t\t\t\t\t\t\tThePaths.m_pathNodes[node].GetPosition() + (length * 0.5f + ThePaths.m_pathNodes[node].GetDividerWidth()) * forward,\n\t\t\t\t\t\t\tThePaths.m_pathNodes[node].GetPosition() + ThePaths.m_pathNodes[node].GetDividerWidth() * forward);\n\t\t\t\t\t\tCreateRoadBlockBetween2Points(\n\t\t\t\t\t\t\tThePaths.m_pathNodes[node].GetPosition() - ThePaths.m_pathNodes[node].GetDividerWidth() * forward,\n\t\t\t\t\t\t\tThePaths.m_pathNodes[node].GetPosition() - (length * 0.5f + ThePaths.m_pathNodes[node].GetDividerWidth()) * forward);\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tCreateRoadBlockBetween2Points(\n\t\t\t\t\t\t\tThePaths.m_pathNodes[node].GetPosition() + (length * 0.5f) * forward,\n\t\t\t\t\t\t\tThePaths.m_pathNodes[node].GetPosition() - (length * 0.5f) * forward);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tInOrOut[nRoadblockNode] = false;\n\t\t}\n\t}\n\tint i = CTimer::GetFrameCounter() & 0xF;\n\tif (!aScriptRoadBlocks[i].m_bInUse)\n\t\treturn;\n\tif ((aScriptRoadBlocks[i].GetPosition() - FindPlayerCoors()).Magnitude() < 100.0f) {\n\t\tCreateRoadBlockBetween2Points(aScriptRoadBlocks[i].m_vInf, aScriptRoadBlocks[i].m_vSup);\n\t\taScriptRoadBlocks[i].m_bInUse = false;\n\t}\n}\n\nvoid\nCRoadBlocks::ClearScriptRoadBlocks(void)\n{\n\tfor (int i = 0; i < NUM_SCRIPT_ROADBLOCKS; i++)\n\t\taScriptRoadBlocks[i].m_bInUse = false;\n}\n\nvoid\nCRoadBlocks::RegisterScriptRoadBlock(CVector vInf, CVector vSup)\n{\n\tint32 i;\n\tfor (i = 0; i < NUM_SCRIPT_ROADBLOCKS; i++) {\n\t\tif (!aScriptRoadBlocks[i].m_bInUse)\n\t\t\tbreak;\n\t}\n\tif (i == NUM_SCRIPT_ROADBLOCKS)\n\t\treturn;\n\taScriptRoadBlocks[i].m_bInUse = true;\n\taScriptRoadBlocks[i].m_vInf = vInf;\n\taScriptRoadBlocks[i].m_vSup = vSup;\n}\n\nvoid \nCRoadBlocks::CreateRoadBlockBetween2Points(CVector point1, CVector point2)\n{\n#ifdef SECUROM\n\tif (roadBlocksPirateCheck == 0)\n\t\t// if not pirated game\n\t\t// roadBlocksPirateCheck = 1;\n\t\t// else\n\t\troadBlocksPirateCheck = 2;\n#endif\n\tCMatrix tmp;\n\tCVector forward = (point2 - point1);\n\tfloat distBetween = forward.Magnitude();\n\tCVector pos = (point1 + point2) / 2;\n\tCVector right(forward.y, -forward.x, 0.0f);\n\tforward.Normalise();\n\tright.Normalise();\n\tif (DotProduct(FindPlayerCoors() - pos, right) < 0.0f) {\n\t\tright *= -1.0f;\n\t}\n\tint32 vehicleId = MI_POLICE;\n\tif (FindPlayerPed()->m_pWanted->AreArmyRequired())\n\t\tvehicleId = MI_BARRACKS;\n\telse if (FindPlayerPed()->m_pWanted->AreFbiRequired())\n\t\tvehicleId = MI_FBICAR;\n\telse if (FindPlayerPed()->m_pWanted->AreSwatRequired())\n\t\tvehicleId = MI_ENFORCER;\n\tif (!CStreaming::HasModelLoaded(vehicleId))\n\t\tvehicleId = MI_POLICE;\n\tCColModel* pVehicleColModel = CModelInfo::GetModelInfo(vehicleId)->GetColModel();\n\tfloat fModelRadius = 2.0f * pVehicleColModel->boundingSphere.radius + 0.25f;\n\tint16 numRoadblockVehicles = Min(6, (int16)(distBetween / fModelRadius));\n\tfor (int16 i = 0; i < numRoadblockVehicles; i++) {\n\t\tfloat offset = fModelRadius * (i - numRoadblockVehicles / 2);\n\t\ttmp.SetTranslate(0.0f, 0.0f, 0.0f);\n\t\ttmp.GetRight() = CVector(forward.y, -forward.x, 0.0f);\n\t\ttmp.GetForward() = forward;\n\t\ttmp.GetUp() = CVector(0.0f, 0.0f, 1.0f);\n\t\ttmp.RotateZ(((CGeneral::GetRandomNumber() & 0xFF) - 128.0f) * 0.003f);\n\t\tif (CGeneral::GetRandomNumber() & 1)\n\t\t\ttmp.RotateZ(((CGeneral::GetRandomNumber() & 0xFF) - 128.0f) * 0.003f + 3.1416f);\n\t\ttmp.SetTranslateOnly(offset * forward + pos);\n\t\ttmp.GetPosition().z += 0.6f;\n\t\tfloat fModelRadius = CModelInfo::GetModelInfo(vehicleId)->GetColModel()->boundingSphere.radius - 0.25f;\n\t\tint16 colliding = 0;\n\t\tCWorld::FindObjectsKindaColliding(tmp.GetPosition(), fModelRadius, 0, &colliding, 2, nil, false, true, true, false, false);\n\t\tif (!colliding) {\n\t\t\tCAutomobile* pVehicle = new CAutomobile(vehicleId, RANDOM_VEHICLE);\n\t\t\tpVehicle->SetStatus(STATUS_ABANDONED);\n\t\t\t// pVehicle->GetHeightAboveRoad(); // called but return value is ignored?\n\t\t\ttmp.GetPosition().z += fModelRadius - 0.6f;\n\t\t\tpVehicle->m_matrix = tmp;\n\t\t\tpVehicle->PlaceOnRoadProperly();\n\t\t\tpVehicle->SetIsStatic(false);\n\t\t\tpVehicle->m_matrix.UpdateRW();\n\t\t\tpVehicle->m_nDoorLock = CARLOCK_UNLOCKED;\n\t\t\tCCarCtrl::JoinCarWithRoadSystem(pVehicle);\n\t\t\tpVehicle->bIsLocked = false;\n\t\t\tpVehicle->AutoPilot.m_nCarMission = MISSION_NONE;\n\t\t\tpVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE;\n\t\t\tpVehicle->AutoPilot.m_nNextLane = pVehicle->AutoPilot.m_nCurrentLane = 0;\n\t\t\tpVehicle->AutoPilot.m_nCruiseSpeed = pVehicle->AutoPilot.m_fMaxTrafficSpeed = 0;\n\t\t\tpVehicle->bExtendedRange = true;\n\t\t\tif (pVehicle->UsesSiren() && CGeneral::GetRandomNumber() & 1)\n\t\t\t\tpVehicle->m_bSirenOrAlarm = true;\n\t\t\tif (pVehicle->GetUp().z > 0.94f) {\n\t\t\t\tCVisibilityPlugins::SetClumpAlpha(pVehicle->GetClump(), 0);\n\t\t\t\tCWorld::Add(pVehicle);\n\t\t\t\tpVehicle->bCreateRoadBlockPeds = true;\n\t\t\t\tpVehicle->m_nRoadblockType = DotProduct(pVehicle->GetRight(), pVehicle->GetPosition() - FindPlayerCoors()) >= 0.0f;\n\t\t\t\tpVehicle->m_nSetPieceExtendedRangeTime = CTimer::GetTimeInMilliseconds() + 7000;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tdelete pVehicle;\n\t\t\t}\n\t\t}\n\t}\n\tint numBarriers = distBetween / ROADBLOCK_OBJECT_WIDTH;\n\tCStreaming::RequestModel(MI_ROADWORKBARRIER1, STREAMFLAGS_DONT_REMOVE);\n\tif (!CStreaming::HasModelLoaded(MI_ROADWORKBARRIER1))\n\t\treturn;\n\tfor (int i = 0; i < numBarriers; i++) {\n\t\tfloat offset = ROADBLOCK_OBJECT_WIDTH * (i - numBarriers / 2);\n\t\ttmp.SetTranslate(0.0f, 0.0f, 0.0f);\n\t\ttmp.GetRight() = CVector(forward.y, -forward.x, 0.0f);\n\t\ttmp.GetForward() = forward;\n\t\ttmp.GetUp() = CVector(0.0f, 0.0f, 1.0f);\n\t\ttmp.RotateZ(((CGeneral::GetRandomNumber() & 0xFF) - 128.0f) * 0.003f);\n\t\ttmp.SetTranslateOnly(5.0f * right + offset * forward + pos);\n\t\ttmp.GetPosition().x += (CGeneral::GetRandomNumber() & 0xF) * 0.1f;\n\t\ttmp.GetPosition().y += (CGeneral::GetRandomNumber() & 0xF) * 0.1f;\n\t\tbool found;\n\t\ttmp.GetPosition().z = CWorld::FindGroundZFor3DCoord(tmp.GetPosition().x, tmp.GetPosition().y, tmp.GetPosition().z + 2.0f, &found);\n\t\tif (!found)\n\t\t\tcontinue;\n\t\tint16 colliding = 0;\n\t\tCBaseModelInfo* pMI = CModelInfo::GetModelInfo(MI_ROADWORKBARRIER1);\n\t\ttmp.GetPosition().z -= pMI->GetColModel()->boundingBox.min.z;\n\t\tCWorld::FindObjectsKindaColliding(tmp.GetPosition(), pMI->GetColModel()->boundingSphere.radius, 0, &colliding, 2, nil, false, true, true, false, false);\n\t\tif (colliding == 0) {\n\t\t\tCObject* pObject = new CObject(MI_ROADWORKBARRIER1, true);\n\t\t\tpObject->GetMatrix() = tmp;\n\t\t\tpObject->ObjectCreatedBy = TEMP_OBJECT;\n\t\t\tpObject->m_nEndOfLifeTime = CTimer::GetTimeInMilliseconds() + 600000;\n\t\t\tCWorld::Add(pObject);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/control/RoadBlocks.h",
    "content": "#pragma once\n#include \"common.h\"\n\nclass CVehicle;\n\nclass CScriptRoadblock\n{\npublic:\n\tCVector m_vInf;\n\tCVector m_vSup;\n\tbool m_bInUse;\n\tCVector GetPosition() { return (m_vInf + m_vSup) / 2; }\n};\n\nclass CRoadBlocks\n{\npublic:\n\tstatic int16 NumRoadBlocks;\n\tstatic int16 RoadBlockNodes[NUMROADBLOCKS];\n\tstatic bool InOrOut[NUMROADBLOCKS];\n\tstatic CScriptRoadblock aScriptRoadBlocks[NUM_SCRIPT_ROADBLOCKS];\n\n\tstatic void Init(void);\n\tstatic void GenerateRoadBlockCopsForCar(CVehicle* pVehicle, int32 roadBlockType);\n\tstatic void GenerateRoadBlocks(void);\n\n\tstatic void CreateRoadBlockBetween2Points(CVector, CVector);\n\tstatic void RegisterScriptRoadBlock(CVector, CVector);\n\tstatic void ClearScriptRoadBlocks();\n};\n"
  },
  {
    "path": "src/control/SceneEdit.cpp",
    "content": "#include \"common.h\"\n\n#include \"SceneEdit.h\"\n#ifdef GTA_SCENE_EDIT\n#include \"Automobile.h\"\n#include \"Camera.h\"\n#include \"CarCtrl.h\"\n#include \"CivilianPed.h\"\n#include \"FileMgr.h\"\n#include \"Font.h\"\n#include \"ModelIndices.h\"\n#include \"ModelInfo.h\"\n#include \"Pad.h\"\n#include \"Ped.h\"\n#include \"Population.h\"\n#include \"Text.h\"\n#include \"Timecycle.h\"\n#include \"Streaming.h\"\n#include \"Vehicle.h\"\n#include \"WeaponInfo.h\"\n#include \"World.h\"\n\nbool CSceneEdit::m_bEditOn;\nint32 CSceneEdit::m_bCameraFollowActor;\nbool CSceneEdit::m_bRecording;\nCVector CSceneEdit::m_vecCurrentPosition;\nCVector CSceneEdit::m_vecCamHeading;\nCVector CSceneEdit::m_vecGotoPosition;\nint32 CSceneEdit::m_nVehicle;\nint32 CSceneEdit::m_nVehicle2;\nint32 CSceneEdit::m_nActor;\nint32 CSceneEdit::m_nActor2;\nint32 CSceneEdit::m_nVehiclemodelId;\nint32 CSceneEdit::m_nPedmodelId;\nint16 CSceneEdit::m_nCurrentMovieCommand;\nint16 CSceneEdit::m_nNumActors;\nint16 CSceneEdit::m_nNumMovieCommands;\nint16 CSceneEdit::m_nCurrentCommand;\nint16 CSceneEdit::m_nCurrentVehicle;\nint16 CSceneEdit::m_nCurrentActor;\nint16 CSceneEdit::m_nWeaponType;\nbool CSceneEdit::m_bCommandActive;\nbool CSceneEdit::m_bActorSelected;\nbool CSceneEdit::m_bActor2Selected;\nbool CSceneEdit::m_bVehicleSelected;\nint16 CSceneEdit::m_nNumVehicles;\nCPed* CSceneEdit::pActors[NUM_ACTORS_IN_MOVIE];\nCVehicle* CSceneEdit::pVehicles[NUM_VEHICLES_IN_MOVIE];\nbool CSceneEdit::m_bDrawGotoArrow;\nCMovieCommand CSceneEdit::Movie[NUM_COMMANDS_IN_MOVIE];\n\n#define SHADOW_OFFSET (2.0f)\n#define ACTION_MESSAGE_X_RIGHT (60.0f)\n#define ACTION_MESSAGE_Y (8.0f)\n#define SELECTED_MESSAGE_X_RIGHT (60.0f)\n#define SELECTED_MESSAGE_Y (248.0f)\n#define COMMAND_NAME_X_RIGHT (60.0f)\n#define COMMAND_NAME_Y (38.0f)\n#define COMMAND_NAME_HEIGHT (16.0f)\n\n#define NUM_COMMANDS_TO_DRAW (9)\n\nstatic const char* pCommandStrings[] = {\n\t\"do-nothing\", \"New Actor\", \"Move Actor\", \"Select Actor\", \"Delete Actor\",\n\t\"New Vehicle\", \"Move Vehicle\", \"Select Vehicle\", \"Delete Vehicle\", \"Give Weapon\",\n\t\"Goto\", \"Goto (wait)\", \"Get In Car\", \"Get Out Car\", \"Kill\",\n\t\"Flee\", \"Wait\", \"Position Camera\", \"Set Camera Target\", \"Select Camera Mode\",\n\t\"Save Movie\", \"Load Movie\", \"Play Movie\", \"END\"\n};\n\n#ifdef CHECK_STRUCT_SIZES\nstatic_assert(ARRAY_SIZE(pCommandStrings) == CSceneEdit::MOVIE_TOTAL_COMMANDS, \"Scene edit: not all commands have names\");\n#endif\n\nstatic int32 NextValidModelId(int32 mi, int32 step)\n{\n\tint32 result = -1;\n\tint32 i = mi;\n\twhile (result == -1) {\n\t\ti += step;\n\t\tif (i < 0 || i > MODELINFOSIZE) {\n\t\t\tstep = -step;\n\t\t\tcontinue;\n\t\t}\n\t\tCBaseModelInfo* pInfo = CModelInfo::GetModelInfo(i);\n\t\tCVehicleModelInfo* pVehicleInfo = (CVehicleModelInfo*)pInfo;\n\t\tif (!pInfo)\n\t\t\tcontinue;\n\t\tif (pInfo->GetModelType() == MITYPE_PED\n#ifdef FIX_BUGS\n\t\t\t&& !(i >= MI_SPECIAL01 && i <= MI_SPECIAL21)\n#endif\n\t\t\t|| pInfo->GetModelType() == MITYPE_VEHICLE &&\n#ifdef FIX_BUGS\n\t\t\t(pVehicleInfo->m_vehicleType == VEHICLE_TYPE_CAR || pVehicleInfo->m_vehicleType == VEHICLE_TYPE_BOAT))\n#else // && and || priority failure it seems, also crashes on special models\n\t\t\tpVehicleInfo->m_vehicleType == VEHICLE_TYPE_CAR || pVehicleInfo->m_vehicleType == VEHICLE_TYPE_BOAT)\n#endif\n\t\t\tresult = i;\n\t}\n\treturn result;\n}\n\nvoid CSceneEdit::LoadMovie(void)\n{\n\tReInitialise();\n\tCFileMgr::SetDir(\"DATA\");\n\tint fid = CFileMgr::OpenFile(\"movie.dat\", \"r\");\n#ifdef FIX_BUGS\n\tif (fid >= 0)\n#endif\n\t{\n\t\tCFileMgr::Read(fid, (char*)&Movie, sizeof(Movie));\n\t\tCFileMgr::Read(fid, (char*)&m_nNumMovieCommands, sizeof(m_nNumMovieCommands));\n\t\tCFileMgr::CloseFile(fid);\n\t}\n\tCFileMgr::SetDir(\"\");\n\tm_bCommandActive = false;\n}\n\nvoid CSceneEdit::SaveMovie(void)\n{\n\tCFileMgr::SetDir(\"DATA\");\n\tint fid = CFileMgr::OpenFileForWriting(\"movie.dat\");\n\tif (fid >= 0) {\n\t\tCFileMgr::Write(fid, (char*)&Movie, sizeof(Movie));\n\t\tCFileMgr::Write(fid, (char*)&m_nNumMovieCommands, sizeof(m_nNumMovieCommands));\n\t\tCFileMgr::CloseFile(fid);\n\t}\n\tCFileMgr::SetDir(\"\");\n\tm_bCommandActive = false;\n}\n\nvoid CSceneEdit::Initialise(void)\n{\n\tm_nActor = -1;\n\tm_nActor2 = -1;\n\tm_nVehicle = -1;\n\tm_nVehicle2 = -1;\n\tm_nCurrentCommand = MOVIE_NEW_ACTOR;\n\tm_nVehiclemodelId = MI_INFERNUS;\n\tm_nPedmodelId = MI_MALE01;\n\tm_nNumVehicles = 0;\n\tm_nNumActors = 0;\n\tm_nNumMovieCommands = 0;\n\tm_bCommandActive = false;\n\tm_bRecording = true;\n\tm_bEditOn = false;\n\tfor (int i = 0; i < NUM_ACTORS_IN_MOVIE; i++)\n\t\tpActors[i] = nil;\n\tfor (int i = 0; i < NUM_VEHICLES_IN_MOVIE; i++)\n\t\tpVehicles[i] = nil;\n\tm_vecCamHeading = TheCamera.Cams[TheCamera.ActiveCam].Front;\n\tm_vecGotoPosition = CVector(0.0f, 0.0f, 0.0f);\n\tm_bCameraFollowActor = false;\n\tTheCamera.Cams[TheCamera.ActiveCam].ResetStatics = true;\n\tm_bDrawGotoArrow = false;\n}\n\nvoid CSceneEdit::InitPlayback(void)\n{\n\tm_nVehiclemodelId = MI_INFERNUS;\n\tm_nPedmodelId = MI_MALE01;\n\tm_bCommandActive = false;\n\tm_nNumActors = 0;\n\tm_nNumVehicles = 0;\n\tm_nActor = -1;\n\tm_nActor2 = -1;\n\tm_nVehicle = -1;\n\tm_nVehicle2 = -1;\n\tTheCamera.Cams[TheCamera.ActiveCam].ResetStatics = true;\n\tm_vecCamHeading = TheCamera.Cams[TheCamera.ActiveCam].Front;\n\tfor (int i = 0; i < NUM_ACTORS_IN_MOVIE; i++) {\n\t\tif (pActors[i]) {\n\t\t\tCPopulation::RemovePed(pActors[i]);\n\t\t\tpActors[i] = nil;\n\t\t}\n\t}\n\tm_nCurrentActor = 0;\n\tfor (int i = 0; i < NUM_VEHICLES_IN_MOVIE; i++) {\n\t\tif (pVehicles[i]) {\n\t\t\tCWorld::Remove(pVehicles[i]);\n\t\t\tdelete pVehicles[i];\n\t\t\tpVehicles[i] = nil;\n\t\t}\n\t}\n\tm_nCurrentVehicle = 0;\n\tm_vecGotoPosition = CVector(0.0f, 0.0f, 0.0f);\n\tm_nCurrentMovieCommand = MOVIE_DO_NOTHING;\n\tm_bDrawGotoArrow = false;\n}\n\nvoid CSceneEdit::ReInitialise(void)\n{\n\tm_nVehiclemodelId = MI_INFERNUS;\n\tm_nPedmodelId = MI_MALE01;\n\tm_nCurrentCommand = MOVIE_NEW_ACTOR;\n\tm_bEditOn = true;\n\tm_bRecording = true;\n\tm_bCommandActive = false;\n#ifdef FIX_BUGS\n\tm_bCameraFollowActor = false;\n\tTheCamera.Cams[TheCamera.ActiveCam].ResetStatics = true; // not enough...\n#endif\n\tm_nActor = -1;\n\tm_nActor2 = -1;\n\tm_nVehicle = -1;\n\tm_nVehicle2 = -1;\n\tm_nNumMovieCommands = 0;\n\tm_nCurrentMovieCommand = MOVIE_DO_NOTHING;\n\tm_nNumActors = 0;\n\tm_nNumVehicles = 0;\n\tfor (int i = 0; i < NUM_ACTORS_IN_MOVIE; i++) {\n\t\tif (pActors[i]) {\n\t\t\tCPopulation::RemovePed(pActors[i]);\n\t\t\tpActors[i] = nil;\n\t\t}\n\t}\n\tfor (int i = 0; i < NUM_VEHICLES_IN_MOVIE; i++) {\n\t\tif (pVehicles[i]) {\n\t\t\tCWorld::Remove(pVehicles[i]);\n\t\t\tdelete pVehicles[i];\n\t\t\tpVehicles[i] = nil;\n\t\t}\n\t}\n\tfor (int i = 0; i < NUM_COMMANDS_IN_MOVIE; i++) {\n\t\tMovie[i].m_nCommandId = MOVIE_DO_NOTHING;\n\t\tMovie[i].m_vecPosition = CVector(0.0f, 0.0f, 0.0f);\n\t\tMovie[i].m_vecCamera = CVector(0.0f, 0.0f, 0.0f);\n\t\tMovie[i].m_nActorId = -1;\n\t\tMovie[i].m_nActor2Id = -1;\n\t\tMovie[i].m_nVehicleId = -1;\n\t\tMovie[i].m_nModelIndex = 0;\n\t}\n\tm_vecGotoPosition = CVector(0.0f, 0.0f, 0.0f);\n\tm_bDrawGotoArrow = false;\n}\n\nvoid CSceneEdit::Update(void)\n{\n\tif (!m_bEditOn)\n\t\treturn;\n\tif (m_bRecording)\n\t\tProcessCommand();\n\telse {\n\t\tif (m_bCameraFollowActor && m_nActor != -1) {\n\t\t\tif (pActors[m_nActor]->bInVehicle)\n\t\t\t\tTheCamera.TakeControl(pActors[m_nActor]->m_pMyVehicle, CCam::MODE_BEHINDCAR, JUMP_CUT, CAMCONTROL_SCRIPT);\n\t\t\telse\n\t\t\t\tTheCamera.TakeControl(pActors[m_nActor], CCam::MODE_FOLLOWPED, JUMP_CUT, CAMCONTROL_SCRIPT);\n\t\t}\n\t\tPlayBack();\n\t}\n}\n\nvoid CSceneEdit::Draw(void)\n{\n\tchar str[200];\n\twchar wstr[200];\n\tif (TheCamera.m_WideScreenOn)\n\t\treturn;\n#ifndef FIX_BUGS\n\tCFont::SetPropOff();\n#endif\n\tCFont::SetBackgroundOff();\n\tCFont::SetScale(SCREEN_SCALE_X(0.8f), SCREEN_SCALE_Y(1.35f));\n\tCFont::SetCentreOn();\n\tCFont::SetRightJustifyOn();\n\tCFont::SetRightJustifyWrap(0.0f);\n\tCFont::SetBackGroundOnlyTextOff();\n#ifdef FIX_BUGS\n\tCFont::SetFontStyle(FONT_STANDARD);\n\tCFont::SetPropOn();\n\tCFont::SetDropColor(CRGBA(0, 0, 0, 255));\n\tCFont::SetDropShadowPosition(1);\n#else\n\tCFont::SetFontStyle(FONT_HEADING);\n\tCFont::SetPropOff();\n#endif\n\tsprintf(str, \"Action\");\n\tAsciiToUnicode(str, wstr);\n\tCFont::SetColor(CRGBA(0, 0, 0, 255));\n#ifdef FIX_BUGS\n\tCFont::PrintString(SCREEN_SCALE_FROM_RIGHT(ACTION_MESSAGE_X_RIGHT - SHADOW_OFFSET), SCREEN_SCALE_Y(ACTION_MESSAGE_Y + SHADOW_OFFSET), wstr);\n#else\n\tCFont::PrintString(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH-ACTION_MESSAGE_X_RIGHT) + SHADOW_OFFSET, SCREEN_SCALE_FROM_BOTTOM(DEFAULT_SCREEN_HEIGHT-ACTION_MESSAGE_Y) + SHADOW_OFFSET, wstr);\n#endif\n\tCFont::SetColor(CRGBA(193, 164, 120, 255));\n#ifdef FIX_BUGS\n\tCFont::PrintString(SCREEN_SCALE_FROM_RIGHT(ACTION_MESSAGE_X_RIGHT), SCREEN_SCALE_Y(ACTION_MESSAGE_Y), wstr);\n#else\n\tCFont::PrintString(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH-ACTION_MESSAGE_X_RIGHT), SCREEN_SCALE_FROM_BOTTOM(DEFAULT_SCREEN_HEIGHT-ACTION_MESSAGE_Y), wstr);\n#endif\n\tsprintf(str, \"Selected\");\n\tAsciiToUnicode(str, wstr);\n\tCFont::SetColor(CRGBA(0, 0, 0, 255));\n#ifdef FIX_BUGS\n\tCFont::PrintString(SCREEN_SCALE_FROM_RIGHT(SELECTED_MESSAGE_X_RIGHT - SHADOW_OFFSET), SCREEN_SCALE_Y(SELECTED_MESSAGE_Y + SHADOW_OFFSET), wstr);\n#else\n\tCFont::PrintString(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH-SELECTED_MESSAGE_X_RIGHT) + SHADOW_OFFSET, SCREEN_SCALE_FROM_BOTTOM(DEFAULT_SCREEN_HEIGHT-SELECTED_MESSAGE_Y) + SHADOW_OFFSET, wstr);\n#endif\n\tCFont::SetColor(CRGBA(193, 164, 120, 255));\n#ifdef FIX_BUGS\n\tCFont::PrintString(SCREEN_SCALE_FROM_RIGHT(SELECTED_MESSAGE_X_RIGHT), SCREEN_SCALE_Y(SELECTED_MESSAGE_Y), wstr);\n#else\n\tCFont::PrintString(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH-SELECTED_MESSAGE_X_RIGHT), SCREEN_SCALE_FROM_BOTTOM(DEFAULT_SCREEN_HEIGHT-SELECTED_MESSAGE_Y), wstr);\n#endif\n\tCFont::SetCentreOff();\n#ifdef FIX_BUGS\n\tCFont::SetScale(SCREEN_SCALE_X(0.7f), SCREEN_SCALE_Y(0.7f));\n#else\n\tCFont::SetScale(0.7f, 0.7f);\n#endif\n#ifdef FIX_BUGS\n\tCFont::SetFontStyle(FONT_STANDARD);\n#else\n\tCFont::SetFontStyle(FONT_HEADING);\n#endif\n\tCFont::SetColor(CRGBA(0, 0, 0, 255));\n\tfor (int i = 0; i < NUM_COMMANDS_TO_DRAW; i++) {\n\t\tint16 nCommandDrawn = m_nCurrentCommand + i - NUM_COMMANDS_TO_DRAW / 2;\n\t\tif (nCommandDrawn >= MOVIE_TOTAL_COMMANDS)\n\t\t\tnCommandDrawn -= (MOVIE_TOTAL_COMMANDS - 1);\n\t\tif (nCommandDrawn <= MOVIE_DO_NOTHING)\n\t\t\tnCommandDrawn += (MOVIE_TOTAL_COMMANDS - 1);\n\t\tsprintf(str, \"%s\", pCommandStrings[nCommandDrawn]);\n\t\tAsciiToUnicode(str, wstr);\n\t\tCFont::SetColor(CRGBA(0, 0, 0, 255));\n#ifdef FIX_BUGS\n\t\tCFont::PrintString(SCREEN_SCALE_FROM_RIGHT(COMMAND_NAME_X_RIGHT - SHADOW_OFFSET), SCREEN_SCALE_Y(COMMAND_NAME_Y + SHADOW_OFFSET + i * COMMAND_NAME_HEIGHT), wstr);\n#else\n\t\tCFont::PrintString(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH-COMMAND_NAME_X_RIGHT) + SHADOW_OFFSET, SCREEN_SCALE_FROM_BOTTOM(DEFAULT_SCREEN_HEIGHT-COMMAND_NAME_Y) + SHADOW_OFFSET + i * COMMAND_NAME_HEIGHT, wstr);\n#endif\n\t\tif (nCommandDrawn == m_nCurrentCommand)\n\t\t\tCFont::SetColor(CRGBA(156, 91, 40, 255));\n\t\telse\n\t\t\tCFont::SetColor(CRGBA(193, 164, 120, 255));\n#ifdef FIX_BUGS\n\t\tCFont::PrintString(SCREEN_SCALE_FROM_RIGHT(COMMAND_NAME_X_RIGHT), SCREEN_SCALE_Y(COMMAND_NAME_Y + i * COMMAND_NAME_HEIGHT), wstr);\n#else\n\t\tCFont::PrintString(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH-COMMAND_NAME_X_RIGHT), SCREEN_SCALE_FROM_BOTTOM(DEFAULT_SCREEN_HEIGHT-COMMAND_NAME_Y) + i * COMMAND_NAME_HEIGHT, wstr);\n#endif\n\t}\n}\n\nvoid CSceneEdit::ProcessCommand(void)\n{\n\tif (!m_bCommandActive) {\n\t\tClearForNewCommand();\n\t\tif (CPad::GetPad(1)->GetDPadUpJustDown()) {\n\t\t\tif (--m_nCurrentCommand == MOVIE_DO_NOTHING)\n\t\t\t\tm_nCurrentCommand = MOVIE_END;\n\t\t}\n\t\tif (CPad::GetPad(1)->GetDPadDownJustDown()) {\n\t\t\tif (++m_nCurrentCommand == MOVIE_TOTAL_COMMANDS)\n\t\t\t\tm_nCurrentCommand = MOVIE_NEW_ACTOR;\n\t\t}\n\t\tif (CPad::GetPad(1)->GetTriangleJustDown()) {\n\t\t\tif (m_nCurrentCommand != MOVIE_DO_NOTHING)\n\t\t\t\tm_bCommandActive = true;\n\t\t}\n\t\treturn;\n\t}\n\tswitch (m_nCurrentCommand) {\n\tcase MOVIE_DO_NOTHING:\n\t\tm_bCommandActive = false;\n\t\tbreak;\n\tcase MOVIE_NEW_ACTOR:\n\t\tif (m_nActor == -1) {\n\t\t\tif (m_nNumActors == NUM_ACTORS_IN_MOVIE)\n\t\t\t\tbreak;\n\t\t\tif (!CStreaming::HasModelLoaded(m_nPedmodelId)) {\n\t\t\t\tCStreaming::RequestModel(m_nPedmodelId, 0);\n#ifdef FIX_BUGS\n\t\t\t\tCStreaming::LoadAllRequestedModels(false); // otherwise gets stuck :(\n#endif\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tCPed* pPed = new CCivilianPed(PEDTYPE_SPECIAL, m_nPedmodelId);\n\t\t\tpPed->CharCreatedBy = MISSION_CHAR;\n\t\t\tpPed->SetPosition(m_vecCurrentPosition);\n\t\t\tpPed->SetOrientation(0.0f, 0.0f, 0.0f);\n\t\t\tCWorld::Add(pPed);\n\t\t\tpPed->bUsesCollision = false;\n\t\t\tpPed->bAffectedByGravity = false;\n\t\t\tfor (int i = 0; i < NUM_ACTORS_IN_MOVIE; i++) {\n\t\t\t\tif (pActors[i] == nil) {\n\t\t\t\t\tm_nActor = i;\n\t\t\t\t\tpActors[i] = pPed;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tpActors[m_nActor]->SetPosition(m_vecCurrentPosition);\n\t\t\tpActors[m_nActor]->SetOrientation(0.0f, 0.0f, 0.0f);\n\t\t\tint32 mi = m_nPedmodelId;\n\t\t\tif (CPad::GetPad(1)->GetLeftShoulder1JustDown())\n\t\t\t\tmi = NextValidModelId(m_nPedmodelId, -1);\n\t\t\telse if (CPad::GetPad(1)->GetRightShoulder1JustDown())\n\t\t\t\tmi = NextValidModelId(m_nPedmodelId, 1);\n\t\t\tif (mi == m_nPedmodelId) {\n\t\t\t\tif (CPad::GetPad(1)->GetTriangleJustDown()) {\n\t\t\t\t\tpActors[m_nActor]->bUsesCollision = true;\n\t\t\t\t\tpActors[m_nActor]->bAffectedByGravity = true;\n\t\t\t\t\t++m_nNumActors;\n\t\t\t\t\tMovie[m_nNumMovieCommands].m_nCommandId = MOVIE_NEW_ACTOR;\n\t\t\t\t\tMovie[m_nNumMovieCommands].m_vecPosition = m_vecCurrentPosition;\n\t\t\t\t\tMovie[m_nNumMovieCommands].m_nModelIndex = m_nPedmodelId;\n\t\t\t\t\tMovie[m_nNumMovieCommands++].m_nActorId = m_nActor;\n\t\t\t\t\tm_nActor = -1;\n\t\t\t\t\tm_bCommandActive = false;\n\t\t\t\t}\n\t\t\t\tif (CPad::GetPad(1)->GetCircleJustDown()) {\n\t\t\t\t\tCWorld::Remove(pActors[m_nActor]);\n\t\t\t\t\tdelete pActors[m_nActor];\n\t\t\t\t\tpActors[m_nActor] = nil;\n\t\t\t\t\tm_nActor = -1;\n\t\t\t\t\tm_bCommandActive = false;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tm_nPedmodelId = mi;\n\t\t\t\tif (pActors[m_nActor]) {\n\t\t\t\t\tCWorld::Remove(pActors[m_nActor]);\n\t\t\t\t\tdelete pActors[m_nActor];\n\t\t\t\t}\n\t\t\t\tpActors[m_nActor] = nil;\n\t\t\t\tm_nActor = -1;\n\t\t\t}\n\t\t}\n\t\tbreak;\n\tcase MOVIE_MOVE_ACTOR:\n\t\tSelectActor();\n\t\tif (m_bCommandActive)\n\t\t\tbreak;\n\t\tpActors[m_nActor]->SetPosition(m_vecCurrentPosition);\n\t\tif (CPad::GetPad(1)->GetTriangleJustDown()) {\n\t\t\tm_bCommandActive = false;\n#ifndef FIX_BUGS // why? it crashes, also makes no sense\n\t\t\tpActors[m_nActor] = nil;\n#endif\n\t\t\tSelectActor();\n\t\t}\n\t\tbreak;\n\tcase MOVIE_SELECT_ACTOR:\n\t\tSelectActor();\n\t\tbreak;\n\tcase MOVIE_DELETE_ACTOR:\n\t\tSelectActor();\n\t\tif (m_bActorSelected) {\n\t\t\tCPopulation::RemovePed(pActors[m_nActor]);\n\t\t\tm_nCurrentActor = 0;\n\t\t\t--m_nNumActors;\n#ifdef FIX_BUGS\n\t\t\tpActors[m_nActor] = nil;\n\t\t\tm_nActor = -1;\n#else\n\t\t\tm_nActor = -1;\n\t\t\tpActors[m_nActor] = nil;\n#endif\n\t\t\tSelectActor();\n\t\t\tm_bCommandActive = false;\n\t\t}\n\t\telse if (CPad::GetPad(1)->GetCircleJustDown()) {\n\t\t\tm_nActor = -1;\n\t\t\tm_bCommandActive = false;\n\t\t}\n\t\tbreak;\n\tcase MOVIE_NEW_VEHICLE:\n\t\tif (m_nVehicle == -1) {\n\t\t\tif (m_nNumVehicles == NUM_VEHICLES_IN_MOVIE)\n\t\t\t\tbreak;\n\t\t\tif (!CStreaming::HasModelLoaded(m_nVehiclemodelId)) {\n\t\t\t\tCStreaming::RequestModel(m_nVehiclemodelId, 0);\n#ifdef FIX_BUGS\n\t\t\t\tCStreaming::LoadAllRequestedModels(false); // otherwise gets stuck :(\n#endif\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tCVehicle* pVehicle = new CAutomobile(m_nVehiclemodelId, MISSION_VEHICLE);\n\t\t\tpVehicle->SetStatus(STATUS_PHYSICS);\n\t\t\tpVehicle->SetPosition(m_vecCurrentPosition);\n\t\t\tpVehicle->SetOrientation(0.0f, 0.0f, 0.0f);\n\t\t\tCWorld::Add(pVehicle);\n\t\t\tpVehicle->bUsesCollision = false;\n\t\t\tpVehicle->bAffectedByGravity = false;\n\t\t\tfor (int i = 0; i < NUM_VEHICLES_IN_MOVIE; i++) {\n\t\t\t\tif (pVehicles[i] == nil) {\n\t\t\t\t\tm_nVehicle = i;\n\t\t\t\t\tpVehicles[i] = pVehicle;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tpVehicles[m_nVehicle]->SetPosition(m_vecCurrentPosition);\n\t\t\tpVehicles[m_nVehicle]->SetOrientation(0.0f, 0.0f, 0.0f);\n\t\t\tint32 mi = m_nVehiclemodelId;\n\t\t\tif (CPad::GetPad(1)->GetLeftShoulder1JustDown())\n\t\t\t\tmi = NextValidModelId(m_nVehiclemodelId, -1);\n\t\t\telse if (CPad::GetPad(1)->GetRightShoulder1JustDown())\n\t\t\t\tmi = NextValidModelId(m_nVehiclemodelId, 1);\n\t\t\tif (mi == m_nVehiclemodelId) {\n\t\t\t\tif (CPad::GetPad(1)->GetTriangleJustDown()) {\n\t\t\t\t\tpVehicles[m_nVehicle]->bUsesCollision = true;\n\t\t\t\t\tpVehicles[m_nVehicle]->bAffectedByGravity = true;\n\t\t\t\t\t++m_nNumVehicles;\n\t\t\t\t\tMovie[m_nNumMovieCommands].m_nCommandId = MOVIE_NEW_VEHICLE;\n\t\t\t\t\tMovie[m_nNumMovieCommands].m_vecPosition = m_vecCurrentPosition;\n\t\t\t\t\tMovie[m_nNumMovieCommands].m_nModelIndex = m_nVehiclemodelId;\n\t\t\t\t\tMovie[m_nNumMovieCommands++].m_nVehicleId = m_nVehicle;\n\t\t\t\t\tm_nVehicle = -1;\n\t\t\t\t\tm_bCommandActive = false;\n\t\t\t\t}\n\t\t\t\tif (CPad::GetPad(1)->GetCircleJustDown()) {\n\t\t\t\t\tCWorld::Remove(pVehicles[m_nVehicle]);\n\t\t\t\t\tdelete pVehicles[m_nVehicle];\n\t\t\t\t\tpVehicles[m_nVehicle] = nil;\n\t\t\t\t\tm_nVehicle = -1;\n\t\t\t\t\tm_bCommandActive = false;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tm_nVehiclemodelId = mi;\n\t\t\t\tif (pVehicles[m_nVehicle]) {\n\t\t\t\t\tCWorld::Remove(pVehicles[m_nVehicle]);\n\t\t\t\t\tdelete pVehicles[m_nVehicle];\n\t\t\t\t}\n\t\t\t\tpVehicles[m_nVehicle] = nil;\n\t\t\t\tm_nVehicle = -1;\n\t\t\t}\n\t\t}\n\t\tbreak;\n\tcase MOVIE_MOVE_VEHICLE:\n\t\tSelectVehicle();\n\t\tif (m_bCommandActive)\n\t\t\tbreak;\n\t\tpVehicles[m_nVehicle]->SetPosition(m_vecCurrentPosition);\n\t\tif (CPad::GetPad(1)->GetTriangleJustDown()) {\n\t\t\tm_bCommandActive = false;\n#ifndef FIX_BUGS // again, why? works wrong\n\t\t\tpVehicles[m_nVehicle] = nil;\n#endif\n\t\t\tm_nVehicle = -1;\n\t\t}\n\t\tbreak;\n\tcase MOVIE_SELECT_VEHICLE:\n\t\tSelectVehicle();\n\t\tbreak;\n\tcase MOVIE_DELETE_VEHICLE:\n\t\tSelectVehicle();\n\t\tif (m_bVehicleSelected) {\n\t\t\tCWorld::Remove(pVehicles[m_nVehicle]);\n\t\t\tdelete pVehicles[m_nVehicle];\n\t\t\tm_nCurrentVehicle = 0;\n\t\t\t--m_nNumVehicles;\n\t\t\tpVehicles[m_nVehicle] = nil;\n\t\t\tm_nVehicle = -1;\n\t\t\tSelectVehicle();\n\t\t\tm_bCommandActive = false;\n\t\t}\n\t\telse if (CPad::GetPad(1)->GetCircleJustDown()) {\n\t\t\tpVehicles[m_nVehicle] = nil;\n\t\t\tm_nVehicle = -1;\n\t\t\tm_bCommandActive = false;\n\t\t}\n\t\tbreak;\n\tcase MOVIE_GIVE_WEAPON:\n\t\tif (m_bActorSelected) {\n\t\t\tif (SelectWeapon()) {\n\t\t\t\tm_bCommandActive = false;\n\t\t\t\tMovie[m_nNumMovieCommands].m_nCommandId = MOVIE_GIVE_WEAPON;\n\t\t\t\tMovie[m_nNumMovieCommands].m_nActorId = m_nActor;\n\t\t\t\tMovie[m_nNumMovieCommands++].m_nModelIndex = m_nWeaponType;\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tSelectActor();\n\t\t\tm_bCommandActive = true;\n\t\t}\n\t\tbreak;\n\tcase MOVIE_GOTO:\n\tcase MOVIE_GOTO_WAIT:\n\t\tif (!m_bActorSelected) {\n\t\t\tm_bDrawGotoArrow = true;\n\t\t\tSelectActor();\n\t\t\tif (m_nActor == -1)\n\t\t\t\tm_bCommandActive = true;\n\t\t}\n\t\telse {\n\t\t\tm_vecGotoPosition = m_vecCurrentPosition;\n\t\t\tif (CPad::GetPad(1)->GetTriangleJustDown()) {\n\t\t\t\tif (pActors[m_nActor]->bInVehicle) {\n\t\t\t\t\tif (CCarCtrl::JoinCarWithRoadSystemGotoCoors(pActors[m_nActor]->m_pMyVehicle, m_vecGotoPosition, false))\n\t\t\t\t\t\tpActors[m_nActor]->m_pMyVehicle->AutoPilot.m_nCarMission = MISSION_GOTOCOORDS_STRAIGHT;\n\t\t\t\t\telse\n\t\t\t\t\t\tpActors[m_nActor]->m_pMyVehicle->AutoPilot.m_nCarMission = MISSION_GOTOCOORDS;\n\t\t\t\t\tpActors[m_nActor]->m_pMyVehicle->SetStatus(STATUS_PHYSICS);\n\t\t\t\t\tpActors[m_nActor]->m_pMyVehicle->bEngineOn = true;\n\t\t\t\t\tpActors[m_nActor]->m_pMyVehicle->AutoPilot.m_nCruiseSpeed = Max(16, pActors[m_nActor]->m_pMyVehicle->AutoPilot.m_nCruiseSpeed);\n\t\t\t\t\tpActors[m_nActor]->m_pMyVehicle->AutoPilot.m_nAntiReverseTimer = CTimer::GetTimeInMilliseconds();\n\t\t\t\t\tTheCamera.TakeControl(pActors[m_nActor]->m_pMyVehicle, CCam::MODE_BEHINDCAR, JUMP_CUT, CAMCONTROL_SCRIPT);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tpActors[m_nActor]->SetObjective(OBJECTIVE_GOTO_AREA_ON_FOOT, m_vecGotoPosition);\n\t\t\t\t\tTheCamera.TakeControl(pActors[m_nActor], CCam::MODE_FOLLOWPED, JUMP_CUT, CAMCONTROL_SCRIPT);\n\t\t\t\t}\n\t\t\t\tm_bDrawGotoArrow = false;\n\t\t\t\tMovie[m_nNumMovieCommands].m_nCommandId = MOVIE_GOTO;\n\t\t\t\tMovie[m_nNumMovieCommands].m_nActorId = m_nActor;\n\t\t\t\tMovie[m_nNumMovieCommands++].m_vecPosition = m_vecGotoPosition;\n\t\t\t}\n\t\t\tif (!m_bDrawGotoArrow) {\n\t\t\t\tif (pActors[m_nActor]->bInVehicle && pActors[m_nActor]->m_pMyVehicle->AutoPilot.m_nCarMission == MISSION_NONE ||\n\t\t\t\t\t!pActors[m_nActor]->bInVehicle && pActors[m_nActor]->m_objective == OBJECTIVE_NONE) {\n\t\t\t\t\tif (pActors[m_nActor]) // if there is something that requires this check the least, it's this one\n\t\t\t\t\t\tm_vecCamHeading = TheCamera.Cams[TheCamera.ActiveCam].CamTargetEntity->GetPosition() - TheCamera.Cams[TheCamera.ActiveCam].Source;\n\t\t\t\t\tm_bCommandActive = false;\n\t\t\t\t\tTheCamera.Cams[TheCamera.ActiveCam].Mode = CCam::MODE_FIGHT_CAM_RUNABOUT;\n\t\t\t\t\tm_vecCurrentPosition = pActors[m_nActor]->GetPosition();\n\t\t\t\t\tpActors[m_nActor]->SetObjective(OBJECTIVE_NONE);\n\t\t\t\t\tif (pActors[m_nActor]->bInVehicle)\n\t\t\t\t\t\tpActors[m_nActor]->m_pMyVehicle->AutoPilot.m_nCarMission = MISSION_NONE;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (CPad::GetPad(1)->GetCircleJustDown()) {\n\t\t\t\tpActors[m_nActor] = nil;\n\t\t\t\tm_nActor = -1;\n\t\t\t\tm_bCommandActive = false;\n\t\t\t}\n\t\t}\n\t\tbreak;\n\tcase MOVIE_GET_IN_CAR:\n\t\tif (m_bActorSelected)\n\t\t\tSelectVehicle();\n\t\telse {\n\t\t\tSelectActor();\n\t\t\tif (m_nActor != -1)\n\t\t\t\tm_bCommandActive = true;\n\t\t}\n\t\tif (m_bVehicleSelected) {\n\t\t\tpActors[m_nActor]->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, pVehicles[m_nVehicle]);\n\t\t\tMovie[m_nNumMovieCommands].m_nCommandId = MOVIE_GET_IN_CAR;\n\t\t\tMovie[m_nNumMovieCommands].m_nActorId = m_nActor;\n\t\t\tMovie[m_nNumMovieCommands++].m_nVehicleId = m_nVehicle;\n\t\t\tm_nVehicle = -1;\n\t\t\tm_bCommandActive = false;\n\t\t}\n\t\tif (CPad::GetPad(1)->GetCircleJustDown()) {\n\t\t\tpVehicles[m_nVehicle] = nil;\n\t\t\tm_nVehicle = -1;\n\t\t\tpActors[m_nActor] = nil;\n\t\t\tm_nActor = -1;\n\t\t\tm_bCommandActive = false;\n\t\t}\n\t\tbreak;\n\tcase MOVIE_GET_OUT_CAR:\n\t\tSelectActor();\n\t\tif (m_bActorSelected) {\n\t\t\tif (pActors[m_nActor]->bInVehicle) {\n\t\t\t\tpActors[m_nActor]->SetObjective(OBJECTIVE_LEAVE_CAR);\n\t\t\t\tMovie[m_nNumMovieCommands].m_nCommandId = MOVIE_GET_OUT_CAR;\n\t\t\t\tMovie[m_nNumMovieCommands++].m_nActorId = m_nActor;\n\t\t\t}\n\t\t\tm_nActor = -1;\n\t\t\tm_bCommandActive = false;\n\t\t}\n\t\tif (CPad::GetPad(1)->GetCircleJustDown()) {\n\t\t\tpVehicles[m_nVehicle] = nil;\n\t\t\tm_nVehicle = -1;\n\t\t\tpActors[m_nActor] = nil;\n\t\t\tm_nActor = -1;\n\t\t\tm_bCommandActive = false;\n\t\t}\n\t\tbreak;\n\tcase MOVIE_KILL:\n\t\tif (!m_bActorSelected) {\n\t\t\tSelectActor();\n\t\t\tm_bCommandActive = true;\n\t\t}\n\t\telse if (!m_bActor2Selected) {\n\t\t\tSelectActor2();\n\t\t\tif (m_bActorSelected && m_bActor2Selected && m_nActor != -1 && m_nActor2 != -1 && m_nActor != m_nActor2) {\n\t\t\t\tpActors[m_nActor]->SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, pActors[m_nActor2]);\n\t\t\t\tMovie[m_nNumMovieCommands].m_nCommandId = MOVIE_KILL;\n\t\t\t\tMovie[m_nNumMovieCommands].m_nActorId = m_nActor;\n\t\t\t\tMovie[m_nNumMovieCommands++].m_nActor2Id = m_nActor2;\n\t\t\t\tm_bCommandActive = false;\n\t\t\t}\n\t\t}\n\t\tif (CPad::GetPad(1)->GetCircleJustDown()) {\n\t\t\tpActors[m_nActor] = nil;\n\t\t\tm_nActor = -1;\n\t\t\tpActors[m_nActor2] = nil;\n\t\t\tm_nActor2 = -1;\n\t\t\tm_bCommandActive = false;\n\t\t}\n\t\tbreak;\n\tcase MOVIE_FLEE:\n\t\tif (!m_bActorSelected) {\n\t\t\tSelectActor();\n\t\t\tm_bCommandActive = true;\n\t\t}\n\t\telse if (!m_bActor2Selected) {\n\t\t\tSelectActor2();\n\t\t\tif (m_bActorSelected && m_bActor2Selected && m_nActor != -1 && m_nActor2 != -1 && m_nActor != m_nActor2) {\n\t\t\t\tpActors[m_nActor]->SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_ALWAYS, pActors[m_nActor2]);\n\t\t\t\tMovie[m_nNumMovieCommands].m_nCommandId = MOVIE_FLEE;\n\t\t\t\tMovie[m_nNumMovieCommands].m_nActorId = m_nActor;\n\t\t\t\tMovie[m_nNumMovieCommands++].m_nActor2Id = m_nActor2;\n\t\t\t\tm_bCommandActive = false;\n\t\t\t}\n\t\t}\n\t\tif (CPad::GetPad(1)->GetCircleJustDown()) {\n\t\t\tpActors[m_nActor] = nil;\n\t\t\tm_nActor = -1;\n\t\t\tpActors[m_nActor2] = nil;\n\t\t\tm_nActor2 = -1;\n\t\t\tm_bCommandActive = false;\n\t\t}\n\t\tbreak;\n\tcase MOVIE_WAIT:\n\t\tSelectActor();\n\t\tif (m_bActorSelected) {\n\t\t\tpActors[m_nActor]->SetObjective(OBJECTIVE_WAIT_ON_FOOT);\n\t\t\tMovie[m_nNumMovieCommands].m_nCommandId = MOVIE_WAIT;\n\t\t\tMovie[m_nNumMovieCommands++].m_nActorId = m_nActor;\n\t\t}\n\t\tif (CPad::GetPad(1)->GetCircleJustDown()) {\n\t\t\tpActors[m_nActor] = nil;\n\t\t\tm_nActor = -1;\n\t\t\tm_bCommandActive = false;\n\t\t}\n\t\tbreak;\n\tcase MOVIE_POSITION_CAMERA:\n\t\tif (CPad::GetPad(1)->GetTriangleJustDown()) {\n\t\t\tMovie[m_nNumMovieCommands].m_nCommandId = MOVIE_POSITION_CAMERA;\n\t\t\tMovie[m_nNumMovieCommands].m_vecPosition = TheCamera.Cams[TheCamera.ActiveCam].Source;\n\t\t\tMovie[m_nNumMovieCommands++].m_vecCamera = m_vecCamHeading;\n\t\t\tm_bCommandActive = false;\n\t\t}\n\t\tif (CPad::GetPad(1)->GetCircleJustDown()) {\n\t\t\tm_bCommandActive = false;\n\t\t}\n\t\tbreak;\n\tcase MOVIE_SET_CAMERA_TARGET:\n\t\tif (!m_bActorSelected) {\n\t\t\tSelectActor();\n\t\t\tm_bCommandActive = true;\n\t\t}\n\t\telse {\n\t\t\tTheCamera.Cams[TheCamera.ActiveCam].CamTargetEntity = pActors[m_nActor];\n\t\t\tif (CPad::GetPad(1)->GetTriangleJustDown()) {\n\t\t\t\tMovie[m_nNumMovieCommands].m_nCommandId = MOVIE_SET_CAMERA_TARGET;\n\t\t\t\tMovie[m_nNumMovieCommands++].m_nActorId = m_nActor;\n\t\t\t\tm_bCommandActive = false;\n\t\t\t}\n\t\t}\n\t\tbreak;\n\tcase MOVIE_SELECT_CAMERA_MODE:\n\t\tm_bCommandActive = false;\n\t\tbreak;\n\tcase MOVIE_SAVE_MOVIE:\n\t\tSaveMovie();\n\t\tbreak;\n\tcase MOVIE_LOAD_MOVIE:\n\t\tLoadMovie();\n\t\tbreak;\n\tcase MOVIE_PLAY_MOVIE:\n\t\tInitPlayback();\n\t\tLoadMovie();\n\t\tm_bRecording = false;\n\t\tbreak;\n\tcase MOVIE_END:\n\t\tm_bRecording = false;\n\t\tbreak;\n\tdefault:\n\t\tassert(0);\n\t}\n}\n\nvoid CSceneEdit::PlayBack(void)\n{\n\tm_nCurrentCommand = Movie[m_nCurrentMovieCommand].m_nCommandId;\n\tif (m_nCurrentMovieCommand >= m_nNumMovieCommands) {\n\t\tif (CPad::GetPad(1)->GetTriangleJustDown()) {\n\t\t\tm_nCurrentCommand = MOVIE_DO_NOTHING;\n\t\t\tm_bRecording = true;\n\t\t\tReInitialise();\n\t\t}\n\t\treturn;\n\t}\n\tswitch (m_nCurrentCommand) {\n\tcase MOVIE_DO_NOTHING:\n\tcase MOVIE_MOVE_ACTOR:\n\tcase MOVIE_SELECT_ACTOR:\n\tcase MOVIE_DELETE_ACTOR:\n\tcase MOVIE_MOVE_VEHICLE:\n\tcase MOVIE_SELECT_VEHICLE:\n\tcase MOVIE_DELETE_VEHICLE:\n\t\tbreak;\n\tcase MOVIE_NEW_ACTOR:\n\t{\n\t\tm_nPedmodelId = Movie[m_nCurrentMovieCommand].m_nModelIndex;\n\t\tm_vecCurrentPosition = Movie[m_nCurrentMovieCommand].m_vecPosition;\n\t\tif (!CStreaming::HasModelLoaded(m_nPedmodelId)) {\n\t\t\tCStreaming::RequestModel(m_nPedmodelId, 0);\n#ifdef FIX_BUGS\n\t\t\tCStreaming::LoadAllRequestedModels(false); // otherwise gets stuck :(\n#endif\n\t\t\tbreak;\n\t\t}\n\t\tCPed* pPed = new CCivilianPed(PEDTYPE_SPECIAL, m_nPedmodelId);\n\t\tpPed->CharCreatedBy = MISSION_CHAR;\n\t\tCWorld::Add(pPed);\n\t\tpPed->SetPosition(m_vecCurrentPosition);\n\t\tpPed->SetOrientation(0.0f, 0.0f, 0.0f);\n\t\tfor (int i = 0; i < NUM_ACTORS_IN_MOVIE; i++) {\n\t\t\tif (pActors[i] == nil) {\n\t\t\t\tm_nActor = i;\n\t\t\t\tpActors[i] = pPed;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tm_nNumActors++;\n\t\tm_nCurrentMovieCommand++;\n\t\tbreak;\n\t}\n\tcase MOVIE_NEW_VEHICLE:\n\t{\n\t\tm_nVehiclemodelId = Movie[m_nCurrentMovieCommand].m_nModelIndex;\n\t\tm_vecCurrentPosition = Movie[m_nCurrentMovieCommand].m_vecPosition;\n\t\tif (!CStreaming::HasModelLoaded(m_nVehiclemodelId)) {\n\t\t\tCStreaming::RequestModel(m_nVehiclemodelId, 0);\n#ifdef FIX_BUGS\n\t\t\tCStreaming::LoadAllRequestedModels(false); // otherwise gets stuck :(\n#endif\n\t\t\tbreak;\n\t\t}\n\t\tCVehicle* pVehicle = new CAutomobile(m_nVehiclemodelId, MISSION_VEHICLE);\n\t\tpVehicle->SetStatus(STATUS_PHYSICS);\n\t\tpVehicle->SetPosition(m_vecCurrentPosition);\n\t\tpVehicle->SetOrientation(0.0f, 0.0f, 0.0f);\n\t\tCWorld::Add(pVehicle);\n\t\tfor (int i = 0; i < NUM_VEHICLES_IN_MOVIE; i++) {\n\t\t\tif (pVehicles[i] == nil) {\n\t\t\t\tm_nVehicle = i;\n\t\t\t\tpVehicles[i] = pVehicle;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tm_nNumVehicles++;\n\t\tm_nCurrentMovieCommand++;\n\t\tbreak;\n\t}\n\tcase MOVIE_GIVE_WEAPON:\n\t\tm_nActor = Movie[m_nCurrentMovieCommand].m_nActorId;\n\t\tm_nWeaponType = Movie[m_nCurrentMovieCommand].m_nModelIndex;\n\t\tpActors[m_nActor]->GiveWeapon((eWeaponType)m_nWeaponType, 1000);\n\t\tpActors[m_nActor]->AddWeaponModel(CWeaponInfo::GetWeaponInfo(pActors[m_nActor]->GetWeapon()->m_eWeaponType)->m_nModelId);\n\t\tpActors[m_nActor]->SetCurrentWeapon(m_nWeaponType);\n\t\tm_nCurrentMovieCommand++;\n\t\tbreak;\n\tcase MOVIE_GOTO:\n\tcase MOVIE_GOTO_WAIT:\n\t\tm_nActor = Movie[m_nCurrentMovieCommand].m_nActorId;\n\t\tm_vecGotoPosition = Movie[m_nCurrentMovieCommand].m_vecPosition;\n\t\tif (pActors[m_nActor]->bInVehicle) {\n\t\t\tif (pActors[m_nActor]->m_pMyVehicle->AutoPilot.m_nCarMission != MISSION_GOTOCOORDS &&\n\t\t\t\tpActors[m_nActor]->m_pMyVehicle->AutoPilot.m_nCarMission != MISSION_GOTOCOORDS_STRAIGHT) {\n\t\t\t\tif ((pActors[m_nActor]->m_pMyVehicle->GetPosition() - m_vecGotoPosition).Magnitude() < 5.0f) {\n\t\t\t\t\tif (CCarCtrl::JoinCarWithRoadSystemGotoCoors(pActors[m_nActor]->m_pMyVehicle, m_vecGotoPosition, false))\n\t\t\t\t\t\tpActors[m_nActor]->m_pMyVehicle->AutoPilot.m_nCarMission = MISSION_GOTOCOORDS_STRAIGHT;\n\t\t\t\t\telse\n\t\t\t\t\t\tpActors[m_nActor]->m_pMyVehicle->AutoPilot.m_nCarMission = MISSION_GOTOCOORDS;\n\t\t\t\t\tpActors[m_nActor]->m_pMyVehicle->SetStatus(STATUS_PHYSICS);\n\t\t\t\t\tpActors[m_nActor]->m_pMyVehicle->bEngineOn = true;\n\t\t\t\t\tpActors[m_nActor]->m_pMyVehicle->AutoPilot.m_nCruiseSpeed = Max(16, pActors[m_nActor]->m_pMyVehicle->AutoPilot.m_nCruiseSpeed);\n\t\t\t\t\tpActors[m_nActor]->m_pMyVehicle->AutoPilot.m_nAntiReverseTimer = CTimer::GetTimeInMilliseconds();\n\t\t\t\t\tif (m_nCurrentCommand != MOVIE_GOTO_WAIT)\n\t\t\t\t\t\t++m_nCurrentMovieCommand;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\t++m_nCurrentMovieCommand;\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tif (pActors[m_nActor]->m_objective != OBJECTIVE_GOTO_AREA_ON_FOOT) {\n\t\t\t\tpActors[m_nActor]->SetObjective(OBJECTIVE_GOTO_AREA_ON_FOOT, m_vecGotoPosition);\n\t\t\t\t++m_nCurrentMovieCommand;\n\t\t\t}\n\t\t}\n\t\tbreak;\n\tcase MOVIE_GET_IN_CAR:\n\t\tm_nActor = Movie[m_nCurrentMovieCommand].m_nActorId;\n\t\tif (!pActors[m_nActor]->bInVehicle){\n\t\t\tm_nVehicle = Movie[m_nCurrentMovieCommand].m_nVehicleId;\n\t\t\tpActors[m_nActor]->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, pVehicles[m_nVehicle]);\n\t\t}\n\t\telse\n\t\t\t++m_nCurrentMovieCommand;\n\t\tbreak;\n\tcase MOVIE_GET_OUT_CAR:\n\t\tm_nActor = Movie[m_nCurrentMovieCommand].m_nActorId;\n\t\tif (pActors[m_nActor]->bInVehicle)\n\t\t\tpActors[m_nActor]->SetObjective(OBJECTIVE_LEAVE_CAR);\n\t\telse\n\t\t\t++m_nCurrentMovieCommand;\n\t\tbreak;\n\tcase MOVIE_KILL:\n\t\tm_nActor = Movie[m_nCurrentMovieCommand].m_nActorId;\n\t\tm_nActor2 = Movie[m_nCurrentMovieCommand].m_nActor2Id;\n\t\tpActors[m_nActor]->SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, pActors[m_nActor2]);\n\t\tif (pActors[m_nActor2]->GetPedState() == PED_DEAD)\n\t\t\t++m_nCurrentMovieCommand;\n\t\tbreak;\n\tcase MOVIE_FLEE:\n\t\tm_nActor = Movie[m_nCurrentMovieCommand].m_nActorId;\n\t\tm_nActor2 = Movie[m_nCurrentMovieCommand].m_nActor2Id;\n\t\tpActors[m_nActor]->SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_ALWAYS, pActors[m_nActor2]);\n\t\t++m_nCurrentMovieCommand;\n\t\tbreak;\n\tcase MOVIE_WAIT:\n\t\tm_nActor = Movie[m_nCurrentMovieCommand].m_nActorId;\n\t\tpActors[m_nActor]->SetObjective(OBJECTIVE_WAIT_ON_FOOT);\n\t\t++m_nCurrentMovieCommand;\n\t\tbreak;\n\tcase MOVIE_POSITION_CAMERA:\n\t\tTheCamera.Cams[TheCamera.ActiveCam].Source = Movie[m_nCurrentMovieCommand].m_vecPosition;\n\t\tm_vecCamHeading = Movie[m_nCurrentMovieCommand].m_vecCamera;\n\t\tTheCamera.Cams[TheCamera.ActiveCam].Front = m_vecCamHeading;\n\t\t++m_nCurrentMovieCommand;\n\t\tbreak;\n\tcase MOVIE_SET_CAMERA_TARGET:\n\t\tm_bCameraFollowActor = true;\n\t\tTheCamera.Cams[TheCamera.ActiveCam].CamTargetEntity = pActors[Movie[m_nNumMovieCommands].m_nActorId];\n\t\tTheCamera.pTargetEntity = pActors[Movie[m_nNumMovieCommands].m_nActorId];\n\t\tTheCamera.m_bLookingAtPlayer = false;\n\t\t++m_nCurrentMovieCommand;\n\t\tbreak;\n\tcase MOVIE_SELECT_CAMERA_MODE:\n\t\tm_bCommandActive = false; // this is wrong\n\t\tbreak;\n\t}\n}\n\nvoid CSceneEdit::ClearForNewCommand(void)\n{\n\tm_nActor = -1;\n\tm_nActor2 = -1;\n\tm_nVehicle = -1;\n\tm_bActorSelected = false;\n\tm_bActor2Selected = false;\n\tm_bVehicleSelected = false;\n\tm_bDrawGotoArrow = false;\n}\nvoid CSceneEdit::SelectActor(void)\n{\n\tm_bActorSelected = false;\n\tif (m_nActor != -1) {\n\t\tif (CPad::GetPad(1)->GetLeftShoulder1JustDown()) {\n\t\t\tCPed* pPed;\n\t\t\tdo {\n\t\t\t\tif (--m_nActor < 0)\n\t\t\t\t\tm_nActor = NUM_ACTORS_IN_MOVIE - 1;\n\t\t\t\tpPed = pActors[m_nActor];\n\t\t\t} while (pPed == nil);\n\t\t\tTheCamera.Cams[TheCamera.ActiveCam].Source = pPed->GetPosition() - m_vecCamHeading;\n\t\t}\n\t\telse if (CPad::GetPad(1)->GetRightShoulder1JustDown()) {\n\t\t\tCPed* pPed;\n\t\t\tdo {\n\t\t\t\tif (++m_nActor == NUM_ACTORS_IN_MOVIE)\n\t\t\t\t\tm_nActor = 0;\n\t\t\t\tpPed = pActors[m_nActor];\n\t\t\t} while (pPed == nil);\n\t\t\tTheCamera.Cams[TheCamera.ActiveCam].Source = pPed->GetPosition() - m_vecCamHeading;\n\t\t}\n\t\tm_vecCurrentPosition = pActors[m_nActor]->GetPosition();\n\t\tif (CPad::GetPad(1)->GetTriangleJustDown()) {\n\t\t\tm_bActorSelected = true;\n\t\t\tm_bCommandActive = false;\n\t\t}\n\t\telse if (CPad::GetPad(1)->GetCircleJustDown()) {\n\t\t\tm_nActor = -1;\n\t\t}\n\t}\n\telse if (m_nNumActors != 0) {\n\t\tfor (int i = 0; i < NUM_ACTORS_IN_MOVIE; i++) {\n\t\t\tif (pActors[i] != nil) {\n\t\t\t\tm_nActor = i;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tTheCamera.Cams[TheCamera.ActiveCam].Source = pActors[m_nActor]->GetPosition() - m_vecCamHeading;\n\t\tif (m_nNumActors == 1) {\n\t\t\tm_bActorSelected = true;\n\t\t\tm_bCommandActive = false;\n\t\t}\n\t}\n\telse {\n\t\tm_bCommandActive = false;\n\t}\n}\n\nvoid CSceneEdit::SelectActor2(void)\n{\n\tm_bActor2Selected = false;\n\tif (m_nNumActors <= 1) {\n\t\tm_bCommandActive = false;\n\t\treturn;\n\t}\n\tif (m_nActor2 != -1) {\n\t\tif (CPad::GetPad(1)->GetLeftShoulder1JustDown()) {\n\t\t\tCPed* pPed;\n\t\t\tdo {\n\t\t\t\tif (--m_nActor2 < 0)\n\t\t\t\t\tm_nActor2 = NUM_ACTORS_IN_MOVIE - 1;\n\t\t\t\tpPed = pActors[m_nActor2];\n\t\t\t} while (pPed == nil || pPed == pActors[m_nActor]);\n\t\t\tTheCamera.Cams[TheCamera.ActiveCam].Source = pPed->GetPosition() - m_vecCamHeading;\n\t\t}\n\t\telse if (CPad::GetPad(1)->GetRightShoulder1JustDown()) {\n\t\t\tCPed* pPed;\n\t\t\tdo {\n\t\t\t\tif (++m_nActor2 == NUM_ACTORS_IN_MOVIE)\n\t\t\t\t\tm_nActor2 = 0;\n\t\t\t\tpPed = pActors[m_nActor2];\n\t\t\t} while (pPed == nil || pPed == pActors[m_nActor]);\n\t\t\tTheCamera.Cams[TheCamera.ActiveCam].Source = pPed->GetPosition() - m_vecCamHeading;\n\t\t}\n\t\tm_vecCurrentPosition = pActors[m_nActor2]->GetPosition();\n\t\tif (CPad::GetPad(1)->GetTriangleJustDown()) {\n\t\t\tm_bActor2Selected = true;\n\t\t\tm_bCommandActive = false;\n\t\t}\n\t\telse if (CPad::GetPad(1)->GetCircleJustDown()) {\n\t\t\tm_nActor2 = -1;\n\t\t}\n\t}\n\telse {\n\t\tfor (int i = 0; i < NUM_ACTORS_IN_MOVIE; i++) {\n\t\t\tif (pActors[i] != nil && pActors[m_nActor] != pActors[i] ) {\n\t\t\t\tm_nActor2 = i;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tTheCamera.Cams[TheCamera.ActiveCam].Source = pActors[m_nActor2]->GetPosition() - m_vecCamHeading;\n\t}\n}\n\nvoid CSceneEdit::SelectVehicle(void)\n{\n\tm_bVehicleSelected = false;\n\tif (m_nVehicle != -1) {\n\t\tif (CPad::GetPad(1)->GetLeftShoulder1JustDown()) {\n\t\t\tCVehicle* pVehicle;\n\t\t\tdo {\n\t\t\t\tif (--m_nVehicle < 0)\n\t\t\t\t\tm_nVehicle = NUM_VEHICLES_IN_MOVIE - 1;\n\t\t\t\tpVehicle = pVehicles[m_nVehicle];\n\t\t\t} while (pVehicle == nil);\n\t\t}\n\t\telse if (CPad::GetPad(1)->GetRightShoulder1JustDown()) {\n\t\t\tCVehicle* pVehicle;\n\t\t\tdo {\n\t\t\t\tif (++m_nVehicle == NUM_VEHICLES_IN_MOVIE)\n\t\t\t\t\tm_nVehicle = 0;\n\t\t\t\tpVehicle = pVehicles[m_nVehicle];\n\t\t\t} while (pVehicle == nil);\n\t\t}\n\t\tm_vecCurrentPosition = pVehicles[m_nVehicle]->GetPosition();\n\t\tTheCamera.Cams[TheCamera.ActiveCam].Source = pVehicles[m_nVehicle]->GetPosition() - m_vecCamHeading;\n\t\tif (CPad::GetPad(1)->GetTriangleJustDown()) {\n\t\t\tm_bVehicleSelected = true;\n\t\t\tm_bCommandActive = false;\n\t\t}\n\t\telse if (CPad::GetPad(1)->GetCircleJustDown()) {\n\t\t\tm_nVehicle = -1;\n\t\t}\n\t}\n\telse if (m_nNumVehicles != 0) {\n\t\tfor (int i = 0; i < NUM_ACTORS_IN_MOVIE; i++) {\n\t\t\tif (pVehicles[i] != nil) {\n\t\t\t\tm_nVehicle = i;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n}\n\nbool CSceneEdit::SelectWeapon(void)\n{\n\tif (m_nWeaponType == WEAPONTYPE_UNARMED) {\n\t\tm_nWeaponType = WEAPONTYPE_COLT45;\n\t\treturn false;\n\t}\n\tif (CPad::GetPad(1)->GetLeftShoulder1JustDown()) {\n\t\tif (++m_nWeaponType >= WEAPONTYPE_DETONATOR)\n\t\t\tm_nWeaponType = WEAPONTYPE_BRASSKNUCKLE;\n\t\tpActors[m_nActor]->ClearWeapons();\n\t\tpActors[m_nActor]->GiveWeapon((eWeaponType)m_nWeaponType, 1000);\n\t\tpActors[m_nActor]->AddWeaponModel(CWeaponInfo::GetWeaponInfo(pActors[m_nActor]->GetWeapon()->m_eWeaponType)->m_nModelId);\n\t\tpActors[m_nActor]->SetCurrentWeapon(m_nWeaponType);\n\t}\n\telse if (CPad::GetPad(1)->GetRightShoulder1JustDown()){\n\t\tif (--m_nWeaponType <= WEAPONTYPE_UNARMED)\n\t\t\tm_nWeaponType = WEAPONTYPE_MINIGUN;\n\t\tpActors[m_nActor]->ClearWeapons();\n\t\tpActors[m_nActor]->GiveWeapon((eWeaponType)m_nWeaponType, 1000);\n\t\tpActors[m_nActor]->AddWeaponModel(CWeaponInfo::GetWeaponInfo(pActors[m_nActor]->GetWeapon()->m_eWeaponType)->m_nModelId);\n\t\tpActors[m_nActor]->SetCurrentWeapon(m_nWeaponType);\n\t}\n\tif (CPad::GetPad(1)->GetTriangleJustDown()) {\n\t\tm_bCommandActive = false;\n\t\treturn true;\n\t}\n\tif (CPad::GetPad(1)->GetCircleJustDown()) {\n\t\tpActors[m_nActor]->ClearWeapons();\n\t\tm_nWeaponType = WEAPONTYPE_UNARMED;\n\t\tm_bCommandActive = false;\n\t\treturn false;\n\t}\n\treturn false;\n}\n#endif\n"
  },
  {
    "path": "src/control/SceneEdit.h",
    "content": "#pragma once\n#ifdef GTA_SCENE_EDIT\nclass CPed;\nclass CVehicle;\n\nstruct CMovieCommand\n{\n\tint32 m_nCommandId;\n\tCVector m_vecPosition;\n\tCVector m_vecCamera;\n\tint16 m_nActorId;\n\tint16 m_nActor2Id;\n\tint16 m_nVehicleId;\n\tint16 m_nModelIndex;\n};\n\nclass CSceneEdit\n{\npublic:\n\tenum {\n\t\tMOVIE_DO_NOTHING = 0,\n\t\tMOVIE_NEW_ACTOR,\n\t\tMOVIE_MOVE_ACTOR,\n\t\tMOVIE_SELECT_ACTOR,\n\t\tMOVIE_DELETE_ACTOR,\n\t\tMOVIE_NEW_VEHICLE,\n\t\tMOVIE_MOVE_VEHICLE,\n\t\tMOVIE_SELECT_VEHICLE,\n\t\tMOVIE_DELETE_VEHICLE,\n\t\tMOVIE_GIVE_WEAPON,\n\t\tMOVIE_GOTO,\n\t\tMOVIE_GOTO_WAIT,\n\t\tMOVIE_GET_IN_CAR,\n\t\tMOVIE_GET_OUT_CAR,\n\t\tMOVIE_KILL,\n\t\tMOVIE_FLEE,\n\t\tMOVIE_WAIT,\n\t\tMOVIE_POSITION_CAMERA,\n\t\tMOVIE_SET_CAMERA_TARGET,\n\t\tMOVIE_SELECT_CAMERA_MODE,\n\t\tMOVIE_SAVE_MOVIE,\n\t\tMOVIE_LOAD_MOVIE,\n\t\tMOVIE_PLAY_MOVIE,\n\t\tMOVIE_END,\n\t\tMOVIE_TOTAL_COMMANDS\n\t};\n\tenum {\n\t\tNUM_ACTORS_IN_MOVIE = 5,\n\t\tNUM_VEHICLES_IN_MOVIE = 5,\n\t\tNUM_COMMANDS_IN_MOVIE = 20\n\t};\n\tstatic int32 m_bCameraFollowActor;\n\tstatic CVector m_vecCurrentPosition;\n\tstatic CVector m_vecCamHeading;\n\tstatic CVector m_vecGotoPosition;\n\tstatic int32 m_nVehicle;\n\tstatic int32 m_nVehicle2;\n\tstatic int32 m_nActor;\n\tstatic int32 m_nActor2;\n\tstatic int32 m_nVehiclemodelId;\n\tstatic int32 m_nPedmodelId;\n\tstatic int16 m_nCurrentMovieCommand;\n\tstatic int16 m_nCurrentCommand;\n\tstatic int16 m_nCurrentVehicle;\n\tstatic int16 m_nCurrentActor;\n\tstatic bool m_bEditOn;\n\tstatic bool m_bRecording;\n\tstatic bool m_bCommandActive;\n\tstatic bool m_bActorSelected;\n\tstatic bool m_bActor2Selected;\n\tstatic bool m_bVehicleSelected;\n\tstatic int16 m_nNumActors;\n\tstatic int16 m_nNumVehicles;\n\tstatic int16 m_nNumMovieCommands;\n\tstatic int16 m_nWeaponType;\n\tstatic CPed* pActors[NUM_ACTORS_IN_MOVIE];\n\tstatic CVehicle* pVehicles[NUM_VEHICLES_IN_MOVIE];\n\tstatic bool m_bDrawGotoArrow;\n\tstatic CMovieCommand Movie[NUM_COMMANDS_IN_MOVIE];\n\n\tstatic void LoadMovie(void);\n\tstatic void SaveMovie(void);\n\tstatic void Initialise(void);\n\tstatic void InitPlayback(void);\n\tstatic void ReInitialise(void);\n\tstatic void Update(void);\n\tstatic void Draw(void);\n\tstatic void ProcessCommand(void);\n\tstatic void PlayBack(void);\n\tstatic void ClearForNewCommand(void);\n\tstatic void SelectActor(void);\n\tstatic void SelectActor2(void);\n\tstatic void SelectVehicle(void);\n\tstatic bool SelectWeapon(void);\n};\n#endif\n"
  },
  {
    "path": "src/control/Script.cpp",
    "content": "#include \"common.h\"\n\n#include \"Script.h\"\n#include \"ScriptCommands.h\"\n\n#include \"AnimBlendAssociation.h\"\n#include \"AudioManager.h\"\n#include \"Boat.h\"\n#include \"Camera.h\"\n#include \"CarCtrl.h\"\n#include \"CivilianPed.h\"\n#include \"Clock.h\"\n#include \"CopPed.h\"\n#include \"Debug.h\"\n#include \"DMAudio.h\"\n#include \"EmergencyPed.h\"\n#include \"FileMgr.h\"\n#include \"Frontend.h\"\n#include \"General.h\"\n#ifdef MISSION_REPLAY\n#include \"GenericGameStorage.h\"\n#endif\n#include \"HandlingMgr.h\"\n#include \"Heli.h\"\n#include \"Hud.h\"\n#include \"Lines.h\"\n#include \"Messages.h\"\n#include \"Pad.h\"\n#include \"Pickups.h\"\n#include \"Pools.h\"\n#include \"Population.h\"\n#include \"Remote.h\"\n#include \"Replay.h\"\n#include \"Stats.h\"\n#include \"Streaming.h\"\n#include \"User.h\"\n#include \"Wanted.h\"\n#include \"Weather.h\"\n#include \"Zones.h\"\n#include \"main.h\"\n#include \"Ropes.h\"\n#include \"ColStore.h\"\n#include \"Fluff.h\"\n#include \"GameLogic.h\"\n#include \"MBlur.h\"\n#include \"PedRoutes.h\"\n#include \"RoadBlocks.h\"\n#include \"SpecialFX.h\"\n#include \"Timecycle.h\"\n#include \"TxdStore.h\"\n#include \"Bike.h\"\n#ifdef USE_ADVANCED_SCRIPT_DEBUG_OUTPUT\n#include <stdarg.h>\n#endif\n\nuint8 CTheScripts::ScriptSpace[SIZE_SCRIPT_SPACE];\nCRunningScript CTheScripts::ScriptsArray[MAX_NUM_SCRIPTS];\nintro_text_line CTheScripts::IntroTextLines[MAX_NUM_INTRO_TEXT_LINES];\nintro_script_rectangle CTheScripts::IntroRectangles[MAX_NUM_INTRO_RECTANGLES];\nCSprite2d CTheScripts::ScriptSprites[MAX_NUM_SCRIPT_SRPITES];\nscript_sphere_struct CTheScripts::ScriptSphereArray[MAX_NUM_SCRIPT_SPHERES];\ntUsedObject CTheScripts::UsedObjectArray[MAX_NUM_USED_OBJECTS];\nint32 CTheScripts::MultiScriptArray[MAX_NUM_MISSION_SCRIPTS];\ntBuildingSwap CTheScripts::BuildingSwapArray[MAX_NUM_BUILDING_SWAPS];\nCEntity* CTheScripts::InvisibilitySettingArray[MAX_NUM_INVISIBILITY_SETTINGS];\nCStoredLine CTheScripts::aStoredLines[MAX_NUM_STORED_LINES];\nbool CTheScripts::DbgFlag;\nuint32 CTheScripts::OnAMissionFlag;\nint32 CTheScripts::StoreVehicleIndex;\nbool CTheScripts::StoreVehicleWasRandom;\nCRunningScript *CTheScripts::pIdleScripts;\nCRunningScript *CTheScripts::pActiveScripts;\nint32 CTheScripts::NextFreeCollectiveIndex;\nint32 CTheScripts::LastRandomPedId;\nuint16 CTheScripts::NumberOfUsedObjects;\nbool CTheScripts::bAlreadyRunningAMissionScript;\nbool CTheScripts::bUsingAMultiScriptFile;\nuint16 CTheScripts::NumberOfMissionScripts;\nuint32 CTheScripts::LargestMissionScriptSize;\nuint32 CTheScripts::MainScriptSize;\nuint8 CTheScripts::FailCurrentMission;\nuint16 CTheScripts::NumScriptDebugLines;\nuint16 CTheScripts::NumberOfIntroRectanglesThisFrame;\nuint16 CTheScripts::NumberOfIntroTextLinesThisFrame;\nuint8 CTheScripts::UseTextCommands;\nCMissionCleanup CTheScripts::MissionCleanUp;\nCUpsideDownCarCheck CTheScripts::UpsideDownCars;\nCStuckCarCheck CTheScripts::StuckCars;\nuint16 CTheScripts::CommandsExecuted;\nuint16 CTheScripts::ScriptsUpdated;\nint32 ScriptParams[32];\nuint8 CTheScripts::RiotIntensity;\nuint32 CTheScripts::LastMissionPassedTime;\nuint16 CTheScripts::NumberOfExclusiveMissionScripts;\nbool CTheScripts::bPlayerHasMetDebbieHarry;\nbool CTheScripts::bPlayerIsInTheStatium;\n#if (defined GTA_PC && !defined GTAVC_JP_PATCH || defined GTA_XBOX || defined SUPPORT_XBOX_SCRIPT || defined GTA_MOBILE || defined SUPPORT_MOBILE_SCRIPT)\nint16 CTheScripts::CardStack[CARDS_IN_DECK * MAX_DECKS];\nint16 CTheScripts::CardStackPosition;\n#endif\n\n#ifdef MISSION_REPLAY\n\nstatic const char* nonMissionScripts[] = {\n\t\"copcar\",\n\t\"ambulan\",\n\t\"taxi\",\n\t\"firetru\",\n\t\"rampage\",\n\t\"t4x4_1\",\n\t\"t4x4_2\",\n\t\"t4x4_3\",\n\t\"rc1\",\n\t\"rc2\",\n\t\"rc3\",\n\t\"rc4\",\n\t\"hj\",\n\t\"usj\",\n\t\"mayhem\"\n};\n\nint AllowMissionReplay;\nuint32 NextMissionDelay;\nuint32 MissionStartTime;\nuint32 WaitForMissionActivate;\nuint32 WaitForSave;\nfloat oldTargetX;\nfloat oldTargetY;\nint missionRetryScriptIndex;\nbool doingMissionRetry;\nbool gbTryingPorn4Again;\nint IsInAmmunation;\nint MissionSkipLevel;\n\n#endif\n\n#ifdef USE_ADVANCED_SCRIPT_DEBUG_OUTPUT\n\n#define REGISTER_COMMAND(command, in, out, cond, ovrd, visual) { command, #command, in, out, cond, ovrd, visual }\n#define INPUT_ARGUMENTS(...) { __VA_ARGS__ ARGTYPE_NONE }\n#define OUTPUT_ARGUMENTS(...) { __VA_ARGS__ ARGTYPE_NONE }\nconst tScriptCommandData commands[] = {\n\tREGISTER_COMMAND(COMMAND_NOP, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_WAIT, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GOTO, INPUT_ARGUMENTS(ARGTYPE_LABEL,), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SHAKE_CAM, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_VAR_INT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, 0, \" =\"),\n\tREGISTER_COMMAND(COMMAND_SET_VAR_FLOAT, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, 0, \" =\"),\n\tREGISTER_COMMAND(COMMAND_SET_LVAR_INT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, 0, \" =\"),\n\tREGISTER_COMMAND(COMMAND_SET_LVAR_FLOAT, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, 0, \" =\"),\n\tREGISTER_COMMAND(COMMAND_ADD_VAL_TO_INT_VAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, 0, \" +=\"),\n\tREGISTER_COMMAND(COMMAND_ADD_VAL_TO_FLOAT_VAR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, 0, \" +=\"),\n\tREGISTER_COMMAND(COMMAND_ADD_VAL_TO_INT_LVAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, 0, \" +=\"),\n\tREGISTER_COMMAND(COMMAND_ADD_VAL_TO_FLOAT_LVAR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, 0, \" +=\"),\n\tREGISTER_COMMAND(COMMAND_SUB_VAL_FROM_INT_VAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, 0, \" -=\"),\n\tREGISTER_COMMAND(COMMAND_SUB_VAL_FROM_FLOAT_VAR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, 0, \" -=\"),\n\tREGISTER_COMMAND(COMMAND_SUB_VAL_FROM_INT_LVAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, 0, \" -=\"),\n\tREGISTER_COMMAND(COMMAND_SUB_VAL_FROM_FLOAT_LVAR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, 0, \" -=\"),\n\tREGISTER_COMMAND(COMMAND_MULT_INT_VAR_BY_VAL, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, 0, \" *=\"),\n\tREGISTER_COMMAND(COMMAND_MULT_FLOAT_VAR_BY_VAL, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, 0, \" *=\"),\n\tREGISTER_COMMAND(COMMAND_MULT_INT_LVAR_BY_VAL, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, 0, \" *=\"),\n\tREGISTER_COMMAND(COMMAND_MULT_FLOAT_LVAR_BY_VAL, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, 0, \" *=\"),\n\tREGISTER_COMMAND(COMMAND_DIV_INT_VAR_BY_VAL, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, 0, \" /=\"),\n\tREGISTER_COMMAND(COMMAND_DIV_FLOAT_VAR_BY_VAL, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, 0, \" /=\"),\n\tREGISTER_COMMAND(COMMAND_DIV_INT_LVAR_BY_VAL, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, 0, \" /=\"),\n\tREGISTER_COMMAND(COMMAND_DIV_FLOAT_LVAR_BY_VAL, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, 0, \" /=\"),\n\tREGISTER_COMMAND(COMMAND_IS_INT_VAR_GREATER_THAN_NUMBER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, 0, \" >\"),\n\tREGISTER_COMMAND(COMMAND_IS_INT_LVAR_GREATER_THAN_NUMBER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, 0, \" >\"),\n\tREGISTER_COMMAND(COMMAND_IS_NUMBER_GREATER_THAN_INT_VAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, 0, \" >\"),\n\tREGISTER_COMMAND(COMMAND_IS_NUMBER_GREATER_THAN_INT_LVAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, 0, \" >\"),\n\tREGISTER_COMMAND(COMMAND_IS_INT_VAR_GREATER_THAN_INT_VAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, 0, \" >\"),\n\tREGISTER_COMMAND(COMMAND_IS_INT_LVAR_GREATER_THAN_INT_LVAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, 0, \" >\"),\n\tREGISTER_COMMAND(COMMAND_IS_INT_VAR_GREATER_THAN_INT_LVAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, 0, \" >\"),\n\tREGISTER_COMMAND(COMMAND_IS_INT_LVAR_GREATER_THAN_INT_VAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, 0, \" >\"),\n\tREGISTER_COMMAND(COMMAND_IS_FLOAT_VAR_GREATER_THAN_NUMBER, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), true, 0, \" >\"),\n\tREGISTER_COMMAND(COMMAND_IS_FLOAT_LVAR_GREATER_THAN_NUMBER, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), true, 0, \" >\"),\n\tREGISTER_COMMAND(COMMAND_IS_NUMBER_GREATER_THAN_FLOAT_VAR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), true, 0, \" >\"),\n\tREGISTER_COMMAND(COMMAND_IS_NUMBER_GREATER_THAN_FLOAT_LVAR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), true, 0, \" >\"),\n\tREGISTER_COMMAND(COMMAND_IS_FLOAT_VAR_GREATER_THAN_FLOAT_VAR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), true, 0, \" >\"),\n\tREGISTER_COMMAND(COMMAND_IS_FLOAT_LVAR_GREATER_THAN_FLOAT_LVAR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), true, 0, \" >\"),\n\tREGISTER_COMMAND(COMMAND_IS_FLOAT_VAR_GREATER_THAN_FLOAT_LVAR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), true, 0, \" >\"),\n\tREGISTER_COMMAND(COMMAND_IS_FLOAT_LVAR_GREATER_THAN_FLOAT_VAR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), true, 0, \" >\"),\n\tREGISTER_COMMAND(COMMAND_IS_INT_VAR_GREATER_OR_EQUAL_TO_NUMBER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, 0, \" >=\"),\n\tREGISTER_COMMAND(COMMAND_IS_INT_LVAR_GREATER_OR_EQUAL_TO_NUMBER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, 0, \" >=\"),\n\tREGISTER_COMMAND(COMMAND_IS_NUMBER_GREATER_OR_EQUAL_TO_INT_VAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, 0, \" >=\"),\n\tREGISTER_COMMAND(COMMAND_IS_NUMBER_GREATER_OR_EQUAL_TO_INT_LVAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, 0, \" >=\"),\n\tREGISTER_COMMAND(COMMAND_IS_INT_VAR_GREATER_OR_EQUAL_TO_INT_VAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, 0, \" >=\"),\n\tREGISTER_COMMAND(COMMAND_IS_INT_LVAR_GREATER_OR_EQUAL_TO_INT_LVAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, 0, \" >=\"),\n\tREGISTER_COMMAND(COMMAND_IS_INT_VAR_GREATER_OR_EQUAL_TO_INT_LVAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, 0, \" >=\"),\n\tREGISTER_COMMAND(COMMAND_IS_INT_LVAR_GREATER_OR_EQUAL_TO_INT_VAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, 0, \" >=\"),\n\tREGISTER_COMMAND(COMMAND_IS_FLOAT_VAR_GREATER_OR_EQUAL_TO_NUMBER, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), true, 0, \" >=\"),\n\tREGISTER_COMMAND(COMMAND_IS_FLOAT_LVAR_GREATER_OR_EQUAL_TO_NUMBER, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), true, 0, \" >=\"),\n\tREGISTER_COMMAND(COMMAND_IS_NUMBER_GREATER_OR_EQUAL_TO_FLOAT_VAR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), true, 0, \" >=\"),\n\tREGISTER_COMMAND(COMMAND_IS_NUMBER_GREATER_OR_EQUAL_TO_FLOAT_LVAR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), true, 0, \" >=\"),\n\tREGISTER_COMMAND(COMMAND_IS_FLOAT_VAR_GREATER_OR_EQUAL_TO_FLOAT_VAR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), true, 0, \" >=\"),\n\tREGISTER_COMMAND(COMMAND_IS_FLOAT_LVAR_GREATER_OR_EQUAL_TO_FLOAT_LVAR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), true, 0, \" >=\"),\n\tREGISTER_COMMAND(COMMAND_IS_FLOAT_VAR_GREATER_OR_EQUAL_TO_FLOAT_LVAR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), true, 0, \" >=\"),\n\tREGISTER_COMMAND(COMMAND_IS_FLOAT_LVAR_GREATER_OR_EQUAL_TO_FLOAT_VAR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), true, 0, \" >=\"),\n\tREGISTER_COMMAND(COMMAND_IS_INT_VAR_EQUAL_TO_NUMBER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, 0, \" ==\"),\n\tREGISTER_COMMAND(COMMAND_IS_INT_LVAR_EQUAL_TO_NUMBER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, 0, \" ==\"),\n\tREGISTER_COMMAND(COMMAND_IS_INT_VAR_EQUAL_TO_INT_VAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, 0, \" ==\"),\n\tREGISTER_COMMAND(COMMAND_IS_INT_LVAR_EQUAL_TO_INT_LVAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, 0, \" ==\"),\n\tREGISTER_COMMAND(COMMAND_IS_INT_VAR_EQUAL_TO_INT_LVAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, 0, \" ==\"),\n\tREGISTER_COMMAND(COMMAND_IS_INT_VAR_NOT_EQUAL_TO_NUMBER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, 0, \" !=\"),\n\tREGISTER_COMMAND(COMMAND_IS_INT_LVAR_NOT_EQUAL_TO_NUMBER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, 0, \" !=\"),\n\tREGISTER_COMMAND(COMMAND_IS_INT_VAR_NOT_EQUAL_TO_INT_VAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, 0, \" !=\"),\n\tREGISTER_COMMAND(COMMAND_IS_INT_LVAR_NOT_EQUAL_TO_INT_LVAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, 0, \" !=\"),\n\tREGISTER_COMMAND(COMMAND_IS_INT_VAR_NOT_EQUAL_TO_INT_LVAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), true, 0, \" !=\"),\n\tREGISTER_COMMAND(COMMAND_IS_FLOAT_VAR_EQUAL_TO_NUMBER, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), true, 0, \" ==\"),\n\tREGISTER_COMMAND(COMMAND_IS_FLOAT_LVAR_EQUAL_TO_NUMBER, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), true, 0, \" ==\"),\n\tREGISTER_COMMAND(COMMAND_IS_FLOAT_VAR_EQUAL_TO_FLOAT_VAR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), true, 0, \" ==\"),\n\tREGISTER_COMMAND(COMMAND_IS_FLOAT_LVAR_EQUAL_TO_FLOAT_LVAR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), true, 0, \" ==\"),\n\tREGISTER_COMMAND(COMMAND_IS_FLOAT_VAR_EQUAL_TO_FLOAT_LVAR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), true, 0, \" ==\"),\n\tREGISTER_COMMAND(COMMAND_IS_FLOAT_VAR_NOT_EQUAL_TO_NUMBER, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), true, 0, \" !=\"),\n\tREGISTER_COMMAND(COMMAND_IS_FLOAT_LVAR_NOT_EQUAL_TO_NUMBER, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), true, 0, \" !=\"),\n\tREGISTER_COMMAND(COMMAND_IS_FLOAT_VAR_NOT_EQUAL_TO_FLOAT_VAR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), true, 0, \" !=\"),\n\tREGISTER_COMMAND(COMMAND_IS_FLOAT_LVAR_NOT_EQUAL_TO_FLOAT_LVAR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), true, 0, \" !=\"),\n\tREGISTER_COMMAND(COMMAND_IS_FLOAT_VAR_NOT_EQUAL_TO_FLOAT_LVAR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), true, 0, \" !=\"),\n\tREGISTER_COMMAND(COMMAND_GOTO_IF_TRUE, INPUT_ARGUMENTS(ARGTYPE_LABEL,), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GOTO_IF_FALSE, INPUT_ARGUMENTS(ARGTYPE_LABEL,), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_TERMINATE_THIS_SCRIPT, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_START_NEW_SCRIPT, INPUT_ARGUMENTS(ARGTYPE_LABEL,), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GOSUB, INPUT_ARGUMENTS(ARGTYPE_LABEL,), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_RETURN, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LINE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CREATE_PLAYER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_PLAYER_COORDINATES, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_PLAYER_COORDINATES, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_PLAYER_IN_AREA_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_BOOL,), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_PLAYER_IN_AREA_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_BOOL,), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ADD_INT_VAR_TO_INT_VAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, 0, \" +=\"),\n\tREGISTER_COMMAND(COMMAND_ADD_FLOAT_VAR_TO_FLOAT_VAR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, 0, \" +=\"),\n\tREGISTER_COMMAND(COMMAND_ADD_INT_LVAR_TO_INT_LVAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, 0, \" +=\"),\n\tREGISTER_COMMAND(COMMAND_ADD_FLOAT_LVAR_TO_FLOAT_LVAR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, 0, \" +=\"),\n\tREGISTER_COMMAND(COMMAND_ADD_INT_VAR_TO_INT_LVAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, 0, \" +=\"),\n\tREGISTER_COMMAND(COMMAND_ADD_FLOAT_VAR_TO_FLOAT_LVAR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, 0, \" +=\"),\n\tREGISTER_COMMAND(COMMAND_ADD_INT_LVAR_TO_INT_VAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, 0, \" +=\"),\n\tREGISTER_COMMAND(COMMAND_ADD_FLOAT_LVAR_TO_FLOAT_VAR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, 0, \" +=\"),\n\tREGISTER_COMMAND(COMMAND_SUB_INT_VAR_FROM_INT_VAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, 0, \" -=\"),\n\tREGISTER_COMMAND(COMMAND_SUB_FLOAT_VAR_FROM_FLOAT_VAR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, 0, \" -=\"),\n\tREGISTER_COMMAND(COMMAND_SUB_INT_LVAR_FROM_INT_LVAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, 0, \" -=\"),\n\tREGISTER_COMMAND(COMMAND_SUB_FLOAT_LVAR_FROM_FLOAT_LVAR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, 0, \" -=\"),\n\tREGISTER_COMMAND(COMMAND_SUB_INT_VAR_FROM_INT_LVAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, 0, \" -=\"),\n\tREGISTER_COMMAND(COMMAND_SUB_FLOAT_VAR_FROM_FLOAT_LVAR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, 0, \" -=\"),\n\tREGISTER_COMMAND(COMMAND_SUB_INT_LVAR_FROM_INT_VAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, 0, \" -=\"),\n\tREGISTER_COMMAND(COMMAND_SUB_FLOAT_LVAR_FROM_FLOAT_VAR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, 0, \" -=\"),\n\tREGISTER_COMMAND(COMMAND_MULT_INT_VAR_BY_INT_VAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, 0, \" *=\"),\n\tREGISTER_COMMAND(COMMAND_MULT_FLOAT_VAR_BY_FLOAT_VAR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, 0, \" *=\"),\n\tREGISTER_COMMAND(COMMAND_MULT_INT_LVAR_BY_INT_LVAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, 0, \" *=\"),\n\tREGISTER_COMMAND(COMMAND_MULT_FLOAT_LVAR_BY_FLOAT_LVAR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, 0, \" *=\"),\n\tREGISTER_COMMAND(COMMAND_MULT_INT_VAR_BY_INT_LVAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, 0, \" *=\"),\n\tREGISTER_COMMAND(COMMAND_MULT_FLOAT_VAR_BY_FLOAT_LVAR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, 0, \" *=\"),\n\tREGISTER_COMMAND(COMMAND_MULT_INT_LVAR_BY_INT_VAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, 0, \" *=\"),\n\tREGISTER_COMMAND(COMMAND_MULT_FLOAT_LVAR_BY_FLOAT_VAR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, 0, \" *=\"),\n\tREGISTER_COMMAND(COMMAND_DIV_INT_VAR_BY_INT_VAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, 0, \" /=\"),\n\tREGISTER_COMMAND(COMMAND_DIV_FLOAT_VAR_BY_FLOAT_VAR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, 0, \" /=\"),\n\tREGISTER_COMMAND(COMMAND_DIV_INT_LVAR_BY_INT_LVAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, 0, \" /=\"),\n\tREGISTER_COMMAND(COMMAND_DIV_FLOAT_LVAR_BY_FLOAT_LVAR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, 0, \" /=\"),\n\tREGISTER_COMMAND(COMMAND_DIV_INT_VAR_BY_INT_LVAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, 0, \" /=\"),\n\tREGISTER_COMMAND(COMMAND_DIV_FLOAT_VAR_BY_FLOAT_LVAR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, 0, \" /=\"),\n\tREGISTER_COMMAND(COMMAND_DIV_INT_LVAR_BY_INT_VAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, 0, \" /=\"),\n\tREGISTER_COMMAND(COMMAND_DIV_FLOAT_LVAR_BY_FLOAT_VAR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, 0, \" /=\"),\n\tREGISTER_COMMAND(COMMAND_ADD_TIMED_VAL_TO_FLOAT_VAR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, 0, \" +=@\"),\n\tREGISTER_COMMAND(COMMAND_ADD_TIMED_VAL_TO_FLOAT_LVAR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, 0, \" +=@\"),\n\tREGISTER_COMMAND(COMMAND_ADD_TIMED_FLOAT_VAR_TO_FLOAT_VAR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, 0, \" +=@\"),\n\tREGISTER_COMMAND(COMMAND_ADD_TIMED_FLOAT_LVAR_TO_FLOAT_LVAR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, 0, \" +=@\"),\n\tREGISTER_COMMAND(COMMAND_ADD_TIMED_FLOAT_LVAR_TO_FLOAT_VAR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, 0, \" +=@\"),\n\tREGISTER_COMMAND(COMMAND_ADD_TIMED_FLOAT_VAR_TO_FLOAT_LVAR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, 0, \" +=@\"),\n\tREGISTER_COMMAND(COMMAND_SUB_TIMED_VAL_FROM_FLOAT_VAR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, 0, \" -=@\"),\n\tREGISTER_COMMAND(COMMAND_SUB_TIMED_VAL_FROM_FLOAT_LVAR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, 0, \" -=@\"),\n\tREGISTER_COMMAND(COMMAND_SUB_TIMED_FLOAT_VAR_FROM_FLOAT_VAR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, 0, \" -=@\"),\n\tREGISTER_COMMAND(COMMAND_SUB_TIMED_FLOAT_LVAR_FROM_FLOAT_LVAR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, 0, \" -=@\"),\n\tREGISTER_COMMAND(COMMAND_SUB_TIMED_FLOAT_LVAR_FROM_FLOAT_VAR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, 0, \" -=@\"),\n\tREGISTER_COMMAND(COMMAND_SUB_TIMED_FLOAT_VAR_FROM_FLOAT_LVAR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, 0, \" -=@\"),\n\tREGISTER_COMMAND(COMMAND_SET_VAR_INT_TO_VAR_INT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, 0, \" =\"),\n\tREGISTER_COMMAND(COMMAND_SET_LVAR_INT_TO_LVAR_INT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, 0, \" =\"),\n\tREGISTER_COMMAND(COMMAND_SET_VAR_FLOAT_TO_VAR_FLOAT, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, 0, \" =\"),\n\tREGISTER_COMMAND(COMMAND_SET_LVAR_FLOAT_TO_LVAR_FLOAT, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, 0, \" =\"),\n\tREGISTER_COMMAND(COMMAND_SET_VAR_FLOAT_TO_LVAR_FLOAT, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, 0, \" =\"),\n\tREGISTER_COMMAND(COMMAND_SET_LVAR_FLOAT_TO_VAR_FLOAT, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, 0, \" =\"),\n\tREGISTER_COMMAND(COMMAND_SET_VAR_INT_TO_LVAR_INT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, 0, \" =\"),\n\tREGISTER_COMMAND(COMMAND_SET_LVAR_INT_TO_VAR_INT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, 0, \" =\"),\n\tREGISTER_COMMAND(COMMAND_CSET_VAR_INT_TO_VAR_FLOAT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, 0, \" =#\"),\n\tREGISTER_COMMAND(COMMAND_CSET_VAR_FLOAT_TO_VAR_INT, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, 0, \" =#\"),\n\tREGISTER_COMMAND(COMMAND_CSET_LVAR_INT_TO_VAR_FLOAT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, 0, \" =#\"),\n\tREGISTER_COMMAND(COMMAND_CSET_LVAR_FLOAT_TO_VAR_INT, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, 0, \" =#\"),\n\tREGISTER_COMMAND(COMMAND_CSET_VAR_INT_TO_LVAR_FLOAT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, 0, \" =#\"),\n\tREGISTER_COMMAND(COMMAND_CSET_VAR_FLOAT_TO_LVAR_INT, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, 0, \" =#\"),\n\tREGISTER_COMMAND(COMMAND_CSET_LVAR_INT_TO_LVAR_FLOAT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, 0, \" =#\"),\n\tREGISTER_COMMAND(COMMAND_CSET_LVAR_FLOAT_TO_LVAR_INT, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, 0, \" =#\"),\n\tREGISTER_COMMAND(COMMAND_ABS_VAR_INT, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, 0, \" ABS\"),\n\tREGISTER_COMMAND(COMMAND_ABS_LVAR_INT, INPUT_ARGUMENTS(ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, 0, \" ABS\"),\n\tREGISTER_COMMAND(COMMAND_ABS_VAR_FLOAT, INPUT_ARGUMENTS(ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, 0, \" ABS\"),\n\tREGISTER_COMMAND(COMMAND_ABS_LVAR_FLOAT, INPUT_ARGUMENTS(ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, 0, \" ABS\"),\n\tREGISTER_COMMAND(COMMAND_GENERATE_RANDOM_FLOAT, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT,), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GENERATE_RANDOM_INT, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CREATE_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(ARGTYPE_PED_HANDLE,), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_DELETE_CHAR, INPUT_ARGUMENTS(ARGTYPE_PED_HANDLE,), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CHAR_WANDER_DIR, INPUT_ARGUMENTS(ARGTYPE_PED_HANDLE, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CHAR_WANDER_RANGE, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CHAR_FOLLOW_PATH, INPUT_ARGUMENTS(ARGTYPE_PED_HANDLE, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CHAR_SET_IDLE, INPUT_ARGUMENTS(ARGTYPE_PED_HANDLE,), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_CHAR_COORDINATES, INPUT_ARGUMENTS(ARGTYPE_PED_HANDLE,), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_COORDINATES, INPUT_ARGUMENTS(ARGTYPE_PED_HANDLE, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CHAR_STILL_ALIVE, INPUT_ARGUMENTS(ARGTYPE_PED_HANDLE,), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CHAR_IN_AREA_2D, INPUT_ARGUMENTS(ARGTYPE_PED_HANDLE, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_BOOL,), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CHAR_IN_AREA_3D, INPUT_ARGUMENTS(ARGTYPE_PED_HANDLE, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_BOOL,), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CREATE_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(ARGTYPE_VEHICLE_HANDLE,), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_DELETE_CAR, INPUT_ARGUMENTS(ARGTYPE_VEHICLE_HANDLE,), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CAR_GOTO_COORDINATES, INPUT_ARGUMENTS(ARGTYPE_VEHICLE_HANDLE, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CAR_WANDER_RANDOMLY, INPUT_ARGUMENTS(ARGTYPE_VEHICLE_HANDLE,), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CAR_SET_IDLE, INPUT_ARGUMENTS(ARGTYPE_VEHICLE_HANDLE,), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_CAR_COORDINATES, INPUT_ARGUMENTS(ARGTYPE_VEHICLE_HANDLE,), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CAR_COORDINATES, INPUT_ARGUMENTS(ARGTYPE_VEHICLE_HANDLE, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CAR_STILL_ALIVE, INPUT_ARGUMENTS(ARGTYPE_VEHICLE_HANDLE,), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CAR_CRUISE_SPEED, INPUT_ARGUMENTS(ARGTYPE_VEHICLE_HANDLE, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CAR_DRIVING_STYLE, INPUT_ARGUMENTS(ARGTYPE_VEHICLE_HANDLE, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CAR_MISSION, INPUT_ARGUMENTS(ARGTYPE_VEHICLE_HANDLE, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CAR_IN_AREA_2D, INPUT_ARGUMENTS(ARGTYPE_VEHICLE_HANDLE, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_BOOL,), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CAR_IN_AREA_3D, INPUT_ARGUMENTS(ARGTYPE_VEHICLE_HANDLE, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_BOOL,), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SPECIAL_0, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SPECIAL_1, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SPECIAL_2, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SPECIAL_3, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SPECIAL_4, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SPECIAL_5, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SPECIAL_6, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SPECIAL_7, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_PRINT_BIG, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_PRINT, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_PRINT_NOW, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_PRINT_SOON, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CLEAR_PRINTS, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_TIME_OF_DAY, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_TIME_OF_DAY, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_MINUTES_TO_TIME_OF_DAY, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT,), OUTPUT_ARGUMENTS(ARGTYPE_INT,), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_POINT_ON_SCREEN, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT,), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_DEBUG_ON, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_DEBUG_OFF, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_RETURN_TRUE, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_RETURN_FALSE, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_VAR_INT, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_VAR_FLOAT, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LVAR_INT, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LVAR_FLOAT, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LBRACKET, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_RBRACKET, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_REPEAT, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ENDREPEAT, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IF, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IFNOT, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ELSE, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ENDIF, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_WHILE, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_WHILENOT, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ENDWHILE, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ANDOR, INPUT_ARGUMENTS(ARGTYPE_ANDOR,), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LAUNCH_MISSION, INPUT_ARGUMENTS(ARGTYPE_LABEL,), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_MISSION_HAS_FINISHED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_STORE_CAR_CHAR_IS_IN, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_STORE_CAR_PLAYER_IS_IN, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CHAR_IN_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_PLAYER_IN_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CHAR_IN_MODEL, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_PLAYER_IN_MODEL, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CHAR_IN_ANY_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_PLAYER_IN_ANY_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_BUTTON_PRESSED, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_PAD_STATE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOCATE_PLAYER_ANY_MEANS_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOCATE_PLAYER_ON_FOOT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOCATE_PLAYER_IN_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOCATE_STOPPED_PLAYER_ANY_MEANS_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOCATE_STOPPED_PLAYER_ON_FOOT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOCATE_STOPPED_PLAYER_IN_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOCATE_PLAYER_ANY_MEANS_CHAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOCATE_PLAYER_ON_FOOT_CHAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOCATE_PLAYER_IN_CAR_CHAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOCATE_CHAR_ANY_MEANS_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOCATE_CHAR_ON_FOOT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOCATE_CHAR_IN_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOCATE_STOPPED_CHAR_ANY_MEANS_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOCATE_STOPPED_CHAR_ON_FOOT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOCATE_STOPPED_CHAR_IN_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOCATE_CHAR_ANY_MEANS_CHAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOCATE_CHAR_ON_FOOT_CHAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOCATE_CHAR_IN_CAR_CHAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOCATE_PLAYER_ANY_MEANS_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOCATE_PLAYER_ON_FOOT_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOCATE_PLAYER_IN_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOCATE_STOPPED_PLAYER_ANY_MEANS_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOCATE_STOPPED_PLAYER_ON_FOOT_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOCATE_STOPPED_PLAYER_IN_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOCATE_PLAYER_ANY_MEANS_CHAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOCATE_PLAYER_ON_FOOT_CHAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOCATE_PLAYER_IN_CAR_CHAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOCATE_CHAR_ANY_MEANS_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOCATE_CHAR_ON_FOOT_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOCATE_CHAR_IN_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOCATE_STOPPED_CHAR_ANY_MEANS_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOCATE_STOPPED_CHAR_ON_FOOT_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOCATE_STOPPED_CHAR_IN_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOCATE_CHAR_ANY_MEANS_CHAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOCATE_CHAR_ON_FOOT_CHAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOCATE_CHAR_IN_CAR_CHAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CREATE_OBJECT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_DELETE_OBJECT, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ADD_SCORE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_SCORE_GREATER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_STORE_SCORE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GIVE_REMOTE_CONTROLLED_CAR_TO_PLAYER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ALTER_WANTED_LEVEL, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ALTER_WANTED_LEVEL_NO_DROP, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_WANTED_LEVEL_GREATER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CLEAR_WANTED_LEVEL, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_DEATHARREST_STATE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_HAS_DEATHARREST_BEEN_EXECUTED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ADD_AMMO_TO_PLAYER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ADD_AMMO_TO_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ADD_AMMO_TO_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_PLAYER_STILL_ALIVE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_PLAYER_DEAD, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CHAR_DEAD, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CAR_DEAD, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_THREAT_SEARCH, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_THREAT_REACTION, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_NO_OBJ, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ORDER_DRIVER_OUT_OF_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ORDER_CHAR_TO_DRIVE_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ADD_PATROL_POINT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_PLAYER_IN_GANGZONE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_PLAYER_IN_ZONE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_PLAYER_PRESSING_HORN, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_HAS_CHAR_SPOTTED_PLAYER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ORDER_CHAR_TO_BACKDOOR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ADD_CHAR_TO_GANG, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CHAR_OBJECTIVE_PASSED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_DRIVE_AGGRESSION, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_MAX_DRIVESPEED, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CREATE_CHAR_INSIDE_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_WARP_PLAYER_FROM_CAR_TO_COORD, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_MAKE_CHAR_DO_NOTHING, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_INVINCIBLE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_PLAYER_INVINCIBLE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_GRAPHIC_TYPE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_PLAYER_GRAPHIC_TYPE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_HAS_PLAYER_BEEN_ARRESTED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_STOP_CHAR_DRIVING, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_KILL_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_FAVOURITE_CAR_MODEL_FOR_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_OCCUPATION, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CHANGE_CAR_LOCK, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SHAKE_CAM_WITH_POINT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CAR_MODEL, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CAR_REMAP, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_HAS_CAR_JUST_SUNK, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CAR_NO_COLLIDE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CAR_DEAD_IN_AREA_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CAR_DEAD_IN_AREA_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_TRAILER_ATTACHED, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CAR_ON_TRAILER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_HAS_CAR_GOT_WEAPON, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_PARK, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_HAS_PARK_FINISHED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_KILL_ALL_PASSENGERS, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CAR_BULLETPROOF, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CAR_FLAMEPROOF, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CAR_ROCKETPROOF, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CARBOMB_ACTIVE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GIVE_CAR_ALARM, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_PUT_CAR_ON_TRAILER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CAR_CRUSHED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CREATE_GANG_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CREATE_CAR_GENERATOR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SWITCH_CAR_GENERATOR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ADD_PAGER_MESSAGE, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_DISPLAY_ONSCREEN_TIMER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CLEAR_ONSCREEN_TIMER, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_DISPLAY_ONSCREEN_COUNTER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CLEAR_ONSCREEN_COUNTER, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_ZONE_CAR_INFO, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CHAR_IN_GANG_ZONE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CHAR_IN_ZONE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CAR_DENSITY, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_PED_DENSITY, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_POINT_CAMERA_AT_PLAYER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_POINT_CAMERA_AT_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_POINT_CAMERA_AT_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_RESTORE_CAMERA, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SHAKE_PAD, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_ZONE_PED_INFO, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_TIME_SCALE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CAR_IN_AIR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_FIXED_CAMERA_POSITION, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_POINT_CAMERA_AT_POINT, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ADD_BLIP_FOR_CAR_OLD, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ADD_BLIP_FOR_CHAR_OLD, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ADD_BLIP_FOR_OBJECT_OLD, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_REMOVE_BLIP, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CHANGE_BLIP_COLOUR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_DIM_BLIP, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ADD_BLIP_FOR_COORD_OLD, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CHANGE_BLIP_SCALE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_FADING_COLOUR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_DO_FADE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_FADING_STATUS, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ADD_HOSPITAL_RESTART, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ADD_POLICE_RESTART, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_OVERRIDE_NEXT_RESTART, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_DRAW_SHADOW, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_PLAYER_HEADING, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_PLAYER_HEADING, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_CHAR_HEADING, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_HEADING, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_CAR_HEADING, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CAR_HEADING, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_OBJECT_HEADING, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_OBJECT_HEADING, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_PLAYER_TOUCHING_OBJECT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CHAR_TOUCHING_OBJECT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_PLAYER_AMMO, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_AMMO, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CAR_AMMO, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOAD_CAMERA_SPLINE, INPUT_ARGUMENTS(ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_MOVE_CAMERA_ALONG_SPLINE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_CAMERA_POSITION_ALONG_SPLINE, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_DECLARE_MISSION_FLAG, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_DECLARE_MISSION_FLAG_FOR_CONTACT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_DECLARE_BASE_BRIEF_ID_FOR_CONTACT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_PLAYER_HEALTH_GREATER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CHAR_HEALTH_GREATER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CAR_HEALTH_GREATER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ADD_BLIP_FOR_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ADD_BLIP_FOR_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ADD_BLIP_FOR_OBJECT, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ADD_BLIP_FOR_CONTACT_POINT, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ADD_BLIP_FOR_COORD, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CHANGE_BLIP_DISPLAY, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ADD_ONE_OFF_SOUND, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ADD_CONTINUOUS_SOUND, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_REMOVE_SOUND, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CAR_STUCK_ON_ROOF, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ADD_UPSIDEDOWN_CAR_CHECK, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_REMOVE_UPSIDEDOWN_CAR_CHECK, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_WAIT_ON_FOOT, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_FLEE_ON_FOOT_TILL_SAFE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_GUARD_SPOT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_GUARD_AREA, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_WAIT_IN_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_PLAYER_IN_AREA_ON_FOOT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_PLAYER_IN_AREA_IN_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_PLAYER_STOPPED_IN_AREA_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_PLAYER_STOPPED_IN_AREA_ON_FOOT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_PLAYER_STOPPED_IN_AREA_IN_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_PLAYER_IN_AREA_ON_FOOT_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_PLAYER_IN_AREA_IN_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_PLAYER_STOPPED_IN_AREA_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_PLAYER_STOPPED_IN_AREA_ON_FOOT_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_PLAYER_STOPPED_IN_AREA_IN_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CHAR_IN_AREA_ON_FOOT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CHAR_IN_AREA_IN_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CHAR_STOPPED_IN_AREA_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CHAR_STOPPED_IN_AREA_ON_FOOT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CHAR_STOPPED_IN_AREA_IN_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CHAR_IN_AREA_ON_FOOT_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CHAR_IN_AREA_IN_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CHAR_STOPPED_IN_AREA_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CHAR_STOPPED_IN_AREA_ON_FOOT_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CHAR_STOPPED_IN_AREA_IN_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CAR_STOPPED_IN_AREA_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CAR_STOPPED_IN_AREA_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOCATE_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOCATE_STOPPED_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOCATE_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOCATE_STOPPED_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GIVE_WEAPON_TO_PLAYER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GIVE_WEAPON_TO_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GIVE_WEAPON_TO_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_PLAYER_CONTROL, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_FORCE_WEATHER, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_FORCE_WEATHER_NOW, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_RELEASE_WEATHER, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CURRENT_PLAYER_WEAPON, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CURRENT_CHAR_WEAPON, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CURRENT_CAR_WEAPON, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_OBJECT_COORDINATES, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_OBJECT_COORDINATES, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_GAME_TIMER, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_TURN_CHAR_TO_FACE_COORD, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_TURN_PLAYER_TO_FACE_COORD, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_STORE_WANTED_LEVEL, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CAR_STOPPED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_MARK_CHAR_AS_NO_LONGER_NEEDED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_MARK_CAR_AS_NO_LONGER_NEEDED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_MARK_OBJECT_AS_NO_LONGER_NEEDED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_DONT_REMOVE_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_DONT_REMOVE_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_DONT_REMOVE_OBJECT, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CREATE_CHAR_AS_PASSENGER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_KILL_CHAR_ON_FOOT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_KILL_PLAYER_ON_FOOT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_KILL_CHAR_ANY_MEANS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_KILL_PLAYER_ANY_MEANS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_FLEE_CHAR_ON_FOOT_TILL_SAFE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_FLEE_PLAYER_ON_FOOT_TILL_SAFE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_FLEE_CHAR_ON_FOOT_ALWAYS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_FLEE_PLAYER_ON_FOOT_ALWAYS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_GOTO_CHAR_ON_FOOT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_GOTO_PLAYER_ON_FOOT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_LEAVE_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_ENTER_CAR_AS_PASSENGER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_ENTER_CAR_AS_DRIVER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_FOLLOW_CAR_IN_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_FIRE_AT_OBJECT_FROM_VEHICLE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_DESTROY_OBJECT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_DESTROY_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_GOTO_AREA_ON_FOOT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_GOTO_AREA_IN_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_FOLLOW_CAR_ON_FOOT_WITH_OFFSET, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_GUARD_ATTACK, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_AS_LEADER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_PLAYER_AS_LEADER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LEAVE_GROUP, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_FOLLOW_ROUTE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ADD_ROUTE_POINT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_PRINT_WITH_NUMBER_BIG, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_PRINT_WITH_NUMBER, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_PRINT_WITH_NUMBER_NOW, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_PRINT_WITH_NUMBER_SOON, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SWITCH_ROADS_ON, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SWITCH_ROADS_OFF, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_NUMBER_OF_PASSENGERS, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_MAXIMUM_NUMBER_OF_PASSENGERS, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CAR_DENSITY_MULTIPLIER, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CAR_HEAVY, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CLEAR_CHAR_THREAT_SEARCH, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ACTIVATE_CRANE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_DEACTIVATE_CRANE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_MAX_WANTED_LEVEL, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SAVE_VAR_INT, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SAVE_VAR_FLOAT, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CAR_IN_AIR_PROPER, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CAR_UPSIDEDOWN, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_PLAYER_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CANCEL_OVERRIDE_RESTART, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_POLICE_IGNORE_PLAYER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ADD_PAGER_MESSAGE_WITH_NUMBER, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_START_KILL_FRENZY, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_READ_KILL_FRENZY_STATUS, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SQRT, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOCATE_PLAYER_ANY_MEANS_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOCATE_PLAYER_ON_FOOT_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOCATE_PLAYER_IN_CAR_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOCATE_PLAYER_ANY_MEANS_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOCATE_PLAYER_ON_FOOT_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOCATE_PLAYER_IN_CAR_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOCATE_CHAR_ANY_MEANS_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOCATE_CHAR_ON_FOOT_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOCATE_CHAR_IN_CAR_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOCATE_CHAR_ANY_MEANS_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOCATE_CHAR_ON_FOOT_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOCATE_CHAR_IN_CAR_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GENERATE_RANDOM_FLOAT_IN_RANGE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GENERATE_RANDOM_INT_IN_RANGE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOCK_CAR_DOORS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_EXPLODE_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ADD_EXPLOSION, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CAR_UPRIGHT, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_TURN_CHAR_TO_FACE_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_TURN_CHAR_TO_FACE_PLAYER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_TURN_PLAYER_TO_FACE_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_GOTO_COORD_ON_FOOT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_GOTO_COORD_IN_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CREATE_PICKUP, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_HAS_PICKUP_BEEN_COLLECTED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_REMOVE_PICKUP, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_TAXI_LIGHTS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_PRINT_BIG_Q, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_PRINT_WITH_NUMBER_BIG_Q, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_GARAGE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_GARAGE_WITH_CAR_MODEL, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_TARGET_CAR_FOR_MISSION_GARAGE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CAR_IN_MISSION_GARAGE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_FREE_BOMBS, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_POWERPOINT, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_ALL_TAXI_LIGHTS, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CAR_ARMED_WITH_ANY_BOMB, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_APPLY_BRAKES_TO_PLAYERS_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_PLAYER_HEALTH, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_HEALTH, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CAR_HEALTH, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_PLAYER_HEALTH, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_CHAR_HEALTH, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_CAR_HEALTH, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CAR_ARMED_WITH_BOMB, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CHANGE_CAR_COLOUR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SWITCH_PED_ROADS_ON, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SWITCH_PED_ROADS_OFF, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CHAR_LOOK_AT_CHAR_ALWAYS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CHAR_LOOK_AT_PLAYER_ALWAYS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_PLAYER_LOOK_AT_CHAR_ALWAYS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_STOP_CHAR_LOOKING, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_STOP_PLAYER_LOOKING, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SWITCH_HELICOPTER, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_GANG_ATTITUDE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_GANG_GANG_ATTITUDE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_GANG_PLAYER_ATTITUDE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_GANG_PED_MODELS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_GANG_CAR_MODEL, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_GANG_WEAPONS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_RUN_TO_AREA, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_RUN_TO_COORD, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_PLAYER_TOUCHING_OBJECT_ON_FOOT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CHAR_TOUCHING_OBJECT_ON_FOOT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOAD_SPECIAL_CHARACTER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_HAS_SPECIAL_CHARACTER_LOADED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_FLASH_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_FLASH_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_FLASH_OBJECT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_PLAYER_IN_REMOTE_MODE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ARM_CAR_WITH_BOMB, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_PERSONALITY, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CUTSCENE_OFFSET, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_ANIM_GROUP_FOR_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_ANIM_GROUP_FOR_PLAYER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_REQUEST_MODEL, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_HAS_MODEL_LOADED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_MARK_MODEL_AS_NO_LONGER_NEEDED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GRAB_PHONE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_REPEATED_PHONE_MESSAGE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_PHONE_MESSAGE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_HAS_PHONE_DISPLAYED_MESSAGE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_TURN_PHONE_OFF, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_DRAW_CORONA, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_DRAW_LIGHT, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_STORE_WEATHER, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_RESTORE_WEATHER, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_STORE_CLOCK, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_RESTORE_CLOCK, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_RESTART_CRITICAL_MISSION, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_PLAYER_PLAYING, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_COLL_OBJ_NO_OBJ, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_COLL_OBJ_WAIT_ON_FOOT, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_COLL_OBJ_FLEE_ON_FOOT_TILL_SAFE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_COLL_OBJ_GUARD_SPOT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_COLL_OBJ_GUARD_AREA, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_COLL_OBJ_WAIT_IN_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_COLL_OBJ_KILL_CHAR_ON_FOOT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_COLL_OBJ_KILL_PLAYER_ON_FOOT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_COLL_OBJ_KILL_CHAR_ANY_MEANS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_COLL_OBJ_KILL_PLAYER_ANY_MEANS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_COLL_OBJ_FLEE_CHAR_ON_FOOT_TILL_SAFE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_COLL_OBJ_FLEE_PLAYER_ON_FOOT_TILL_SAFE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_COLL_OBJ_FLEE_CHAR_ON_FOOT_ALWAYS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_COLL_OBJ_FLEE_PLAYER_ON_FOOT_ALWAYS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_COLL_OBJ_GOTO_CHAR_ON_FOOT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_COLL_OBJ_GOTO_PLAYER_ON_FOOT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_COLL_OBJ_LEAVE_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_COLL_OBJ_ENTER_CAR_AS_PASSENGER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_COLL_OBJ_ENTER_CAR_AS_DRIVER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_COLL_OBJ_FOLLOW_CAR_IN_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_COLL_OBJ_FIRE_AT_OBJECT_FROM_VEHICLE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_COLL_OBJ_DESTROY_OBJECT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_COLL_OBJ_DESTROY_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_COLL_OBJ_GOTO_AREA_ON_FOOT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_COLL_OBJ_GOTO_AREA_IN_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_COLL_OBJ_FOLLOW_CAR_ON_FOOT_WITH_OFFSET, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_COLL_OBJ_GUARD_ATTACK, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_COLL_OBJ_FOLLOW_ROUTE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_COLL_OBJ_GOTO_COORD_ON_FOOT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_COLL_OBJ_GOTO_COORD_IN_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_COLL_OBJ_RUN_TO_AREA, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_COLL_OBJ_RUN_TO_COORD, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ADD_PEDS_IN_AREA_TO_COLL, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ADD_PEDS_IN_VEHICLE_TO_COLL, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CLEAR_COLL, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_COLL_IN_CARS, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOCATE_COLL_ANY_MEANS_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOCATE_COLL_ON_FOOT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOCATE_COLL_IN_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOCATE_STOPPED_COLL_ANY_MEANS_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOCATE_STOPPED_COLL_ON_FOOT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOCATE_STOPPED_COLL_IN_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOCATE_COLL_ANY_MEANS_CHAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOCATE_COLL_ON_FOOT_CHAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOCATE_COLL_IN_CAR_CHAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOCATE_COLL_ANY_MEANS_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOCATE_COLL_ON_FOOT_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOCATE_COLL_IN_CAR_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOCATE_COLL_ANY_MEANS_PLAYER_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOCATE_COLL_ON_FOOT_PLAYER_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOCATE_COLL_IN_CAR_PLAYER_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_COLL_IN_AREA_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_COLL_IN_AREA_ON_FOOT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_COLL_IN_AREA_IN_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_COLL_STOPPED_IN_AREA_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_COLL_STOPPED_IN_AREA_ON_FOOT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_COLL_STOPPED_IN_AREA_IN_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_NUMBER_OF_PEDS_IN_COLL, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_HEED_THREATS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_PLAYER_HEED_THREATS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_CONTROLLER_MODE, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CAN_RESPRAY_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_TAXI, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_UNLOAD_SPECIAL_CHARACTER, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_RESET_NUM_OF_MODELS_KILLED_BY_PLAYER, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_NUM_OF_MODELS_KILLED_BY_PLAYER, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ACTIVATE_GARAGE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SWITCH_TAXI_TIMER, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CREATE_OBJECT_NO_OFFSET, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_BOAT, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_GOTO_AREA_ANY_MEANS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_COLL_OBJ_GOTO_AREA_ANY_MEANS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_PLAYER_STOPPED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CHAR_STOPPED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_MESSAGE_WAIT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ADD_PARTICLE_EFFECT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SWITCH_WIDESCREEN, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ADD_SPRITE_BLIP_FOR_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ADD_SPRITE_BLIP_FOR_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ADD_SPRITE_BLIP_FOR_OBJECT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ADD_SPRITE_BLIP_FOR_CONTACT_POINT, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ADD_SPRITE_BLIP_FOR_COORD, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_ONLY_DAMAGED_BY_PLAYER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CAR_ONLY_DAMAGED_BY_PLAYER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_PROOFS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CAR_PROOFS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_PLAYER_IN_ANGLED_AREA_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_PLAYER_IN_ANGLED_AREA_ON_FOOT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_PLAYER_IN_ANGLED_AREA_IN_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_ON_FOOT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_IN_CAR_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_PLAYER_IN_ANGLED_AREA_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_PLAYER_IN_ANGLED_AREA_ON_FOOT_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_PLAYER_IN_ANGLED_AREA_IN_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_ON_FOOT_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_IN_CAR_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_DEACTIVATE_GARAGE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_NUMBER_OF_CARS_COLLECTED_BY_GARAGE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_HAS_CAR_BEEN_TAKEN_TO_GARAGE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_SWAT_REQUIRED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_FBI_REQUIRED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_ARMY_REQUIRED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CAR_IN_WATER, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_CLOSEST_CHAR_NODE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_CLOSEST_CAR_NODE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CAR_GOTO_COORDINATES_ACCURATE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_START_PACMAN_RACE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_START_PACMAN_RECORD, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_NUMBER_OF_POWER_PILLS_EATEN, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CLEAR_PACMAN, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_START_PACMAN_SCRAMBLE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_NUMBER_OF_POWER_PILLS_CARRIED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CLEAR_NUMBER_OF_POWER_PILLS_CARRIED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CAR_ON_SCREEN, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CHAR_ON_SCREEN, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_OBJECT_ON_SCREEN, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GOSUB_FILE, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_GROUND_Z_FOR_3D_COORD, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_START_SCRIPT_FIRE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_SCRIPT_FIRE_EXTINGUISHED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_REMOVE_SCRIPT_FIRE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_COMEDY_CONTROLS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_BOAT_GOTO_COORDS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_BOAT_STOP, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_PLAYER_SHOOTING_IN_AREA, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CHAR_SHOOTING_IN_AREA, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CURRENT_PLAYER_WEAPON, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CURRENT_CHAR_WEAPON, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CLEAR_NUMBER_OF_POWER_PILLS_EATEN, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ADD_POWER_PILL, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_BOAT_CRUISE_SPEED, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_RANDOM_CHAR_IN_AREA, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_RANDOM_CHAR_IN_ZONE, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_PLAYER_IN_TAXI, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_PLAYER_SHOOTING, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CHAR_SHOOTING, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CREATE_MONEY_PICKUP, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_ACCURACY, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_CAR_SPEED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOAD_CUTSCENE, INPUT_ARGUMENTS(ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CREATE_CUTSCENE_OBJECT, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CUTSCENE_ANIM, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_START_CUTSCENE, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_CUTSCENE_TIME, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_HAS_CUTSCENE_FINISHED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CLEAR_CUTSCENE, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_RESTORE_CAMERA_JUMPCUT, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CREATE_COLLECTABLE1, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_COLLECTABLE1_TOTAL, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_PROJECTILE_IN_AREA, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_DESTROY_PROJECTILES_IN_AREA, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_DROP_MINE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_DROP_NAUTICAL_MINE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CHAR_MODEL, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOAD_SPECIAL_MODEL, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CREATE_CUTSCENE_HEAD, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CUTSCENE_HEAD_ANIM, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SIN, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_COS, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_CAR_FORWARD_X, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_CAR_FORWARD_Y, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CHANGE_GARAGE_TYPE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ACTIVATE_CRUSHER_CRANE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_PRINT_WITH_2_NUMBERS, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_PRINT_WITH_2_NUMBERS_NOW, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_PRINT_WITH_2_NUMBERS_SOON, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_PRINT_WITH_3_NUMBERS, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_PRINT_WITH_3_NUMBERS_NOW, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_PRINT_WITH_3_NUMBERS_SOON, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_PRINT_WITH_4_NUMBERS, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_PRINT_WITH_4_NUMBERS_NOW, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_PRINT_WITH_4_NUMBERS_SOON, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_PRINT_WITH_5_NUMBERS, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_PRINT_WITH_5_NUMBERS_NOW, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_PRINT_WITH_5_NUMBERS_SOON, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_PRINT_WITH_6_NUMBERS, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_PRINT_WITH_6_NUMBERS_NOW, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_PRINT_WITH_6_NUMBERS_SOON, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_FOLLOW_CHAR_IN_FORMATION, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_PLAYER_MADE_PROGRESS, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_PROGRESS_TOTAL, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_REGISTER_JUMP_DISTANCE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_REGISTER_JUMP_HEIGHT, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_REGISTER_JUMP_FLIPS, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_REGISTER_JUMP_SPINS, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_REGISTER_JUMP_STUNT, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_REGISTER_UNIQUE_JUMP_FOUND, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_UNIQUE_JUMPS_TOTAL, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_REGISTER_PASSENGER_DROPPED_OFF_TAXI, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_REGISTER_MONEY_MADE_TAXI, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_REGISTER_MISSION_GIVEN, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_REGISTER_MISSION_PASSED, INPUT_ARGUMENTS(ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_RUNNING, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_REMOVE_ALL_SCRIPT_FIRES, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_FIRST_CAR_COLOUR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_SECOND_CAR_COLOUR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_HAS_CHAR_BEEN_DAMAGED_BY_WEAPON, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_HAS_CAR_BEEN_DAMAGED_BY_WEAPON, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CHAR_IN_CHARS_GROUP, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CHAR_IN_PLAYERS_GROUP, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_EXPLODE_CHAR_HEAD, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_EXPLODE_PLAYER_HEAD, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ANCHOR_BOAT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_ZONE_GROUP, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_START_CAR_FIRE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_START_CHAR_FIRE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_RANDOM_CAR_OF_TYPE_IN_AREA, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_RANDOM_CAR_OF_TYPE_IN_ZONE, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_HAS_RESPRAY_HAPPENED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CAMERA_ZOOM, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CREATE_PICKUP_WITH_AMMO, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CAR_RAM_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CAR_BLOCK_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_CATCH_TRAIN, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_COLL_OBJ_CATCH_TRAIN, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_PLAYER_NEVER_GETS_TIRED, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_PLAYER_FAST_RELOAD, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_BLEEDING, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CAR_FUNNY_SUSPENSION, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CAR_BIG_WHEELS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_FREE_RESPRAYS, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_PLAYER_VISIBLE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_VISIBLE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CAR_VISIBLE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_AREA_OCCUPIED, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_START_DRUG_RUN, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_HAS_DRUG_RUN_BEEN_COMPLETED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_HAS_DRUG_PLANE_BEEN_SHOT_DOWN, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SAVE_PLAYER_FROM_FIRES, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_DISPLAY_TEXT, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_TEXT_SCALE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_TEXT_COLOUR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_TEXT_JUSTIFY, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_TEXT_CENTRE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_TEXT_WRAPX, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_TEXT_CENTRE_SIZE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_TEXT_BACKGROUND, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_TEXT_BACKGROUND_COLOUR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_TEXT_BACKGROUND_ONLY_TEXT, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_TEXT_PROPORTIONAL, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_TEXT_FONT, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_INDUSTRIAL_PASSED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_COMMERCIAL_PASSED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SUBURBAN_PASSED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ROTATE_OBJECT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SLIDE_OBJECT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_REMOVE_CHAR_ELEGANTLY, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_STAY_IN_SAME_PLACE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_NASTY_GAME, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_UNDRESS_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_DRESS_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_START_CHASE_SCENE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_STOP_CHASE_SCENE, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_EXPLOSION_IN_AREA, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_EXPLOSION_IN_ZONE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_START_DRUG_DROP_OFF, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_HAS_DROP_OFF_PLANE_BEEN_SHOT_DOWN, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_FIND_DROP_OFF_PLANE_COORDINATES, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CREATE_FLOATING_PACKAGE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_PLACE_OBJECT_RELATIVE_TO_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_MAKE_OBJECT_TARGETTABLE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ADD_ARMOUR_TO_PLAYER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ADD_ARMOUR_TO_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_OPEN_GARAGE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CLOSE_GARAGE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_WARP_CHAR_FROM_CAR_TO_COORD, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_VISIBILITY_OF_CLOSEST_OBJECT_OF_TYPE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_HAS_CHAR_SPOTTED_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_HAIL_TAXI, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_HAS_OBJECT_BEEN_DAMAGED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_START_KILL_FRENZY_HEADSHOT, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ACTIVATE_MILITARY_CRANE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_WARP_PLAYER_INTO_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_WARP_CHAR_INTO_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SWITCH_CAR_RADIO, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_AUDIO_STREAM, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_PRINT_WITH_2_NUMBERS_BIG, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_PRINT_WITH_3_NUMBERS_BIG, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_PRINT_WITH_4_NUMBERS_BIG, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_PRINT_WITH_5_NUMBERS_BIG, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_PRINT_WITH_6_NUMBERS_BIG, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_WAIT_STATE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CAMERA_BEHIND_PLAYER, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_MOTION_BLUR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_PRINT_STRING_IN_STRING, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CREATE_RANDOM_CHAR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_STEAL_ANY_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_2_REPEATED_PHONE_MESSAGES, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_2_PHONE_MESSAGES, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_3_REPEATED_PHONE_MESSAGES, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_3_PHONE_MESSAGES, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_4_REPEATED_PHONE_MESSAGES, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_4_PHONE_MESSAGES, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_SNIPER_BULLET_IN_AREA, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GIVE_PLAYER_DETONATOR, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_COLL_OBJ_STEAL_ANY_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_OBJECT_VELOCITY, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_OBJECT_COLLISION, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_ICECREAM_JINGLE_ON, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_PRINT_STRING_IN_STRING_NOW, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_PRINT_STRING_IN_STRING_SOON, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_5_REPEATED_PHONE_MESSAGES, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_5_PHONE_MESSAGES, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_6_REPEATED_PHONE_MESSAGES, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_6_PHONE_MESSAGES, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_STRING, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_POINT_OBSCURED_BY_A_MISSION_ENTITY, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOAD_ALL_MODELS_NOW, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ADD_TO_OBJECT_VELOCITY, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_DRAW_SPRITE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_DRAW_RECT, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOAD_SPRITE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOAD_TEXTURE_DICTIONARY, INPUT_ARGUMENTS(ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_REMOVE_TEXTURE_DICTIONARY, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_OBJECT_DYNAMIC, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_ANIM_SPEED, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_PLAY_MISSION_PASSED_TUNE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CLEAR_AREA, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_FREEZE_ONSCREEN_TIMER, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SWITCH_CAR_SIREN, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SWITCH_PED_ROADS_ON_ANGLED, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SWITCH_PED_ROADS_OFF_ANGLED, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SWITCH_ROADS_ON_ANGLED, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SWITCH_ROADS_OFF_ANGLED, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CAR_WATERTIGHT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ADD_MOVING_PARTICLE_EFFECT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_CANT_BE_DRAGGED_OUT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_TURN_CAR_TO_FACE_COORD, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CRANE_LIFTING_CAR, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_DRAW_SPHERE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CAR_STATUS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CHAR_MALE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SCRIPT_NAME, INPUT_ARGUMENTS(ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CHANGE_GARAGE_TYPE_WITH_CAR_MODEL, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_FIND_DRUG_PLANE_COORDINATES, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SAVE_INT_TO_DEBUG_FILE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SAVE_FLOAT_TO_DEBUG_FILE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SAVE_NEWLINE_TO_DEBUG_FILE, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_POLICE_RADIO_MESSAGE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CAR_STRONG, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_REMOVE_ROUTE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SWITCH_RUBBISH, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_REMOVE_PARTICLE_EFFECTS_IN_AREA, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SWITCH_STREAMING, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_GARAGE_OPEN, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_GARAGE_CLOSED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_START_CATALINA_HELI, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CATALINA_HELI_TAKE_OFF, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_REMOVE_CATALINA_HELI, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_HAS_CATALINA_HELI_BEEN_SHOT_DOWN, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SWAP_NEAREST_BUILDING_MODEL, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SWITCH_WORLD_PROCESSING, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_REMOVE_ALL_PLAYER_WEAPONS, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GRAB_CATALINA_HELI, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CLEAR_AREA_OF_CARS, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_ROTATING_GARAGE_DOOR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ADD_SPHERE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_REMOVE_SPHERE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CATALINA_HELI_FLY_AWAY, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_EVERYONE_IGNORE_PLAYER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_STORE_CAR_CHAR_IS_IN_NO_SAVE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_STORE_CAR_PLAYER_IS_IN_NO_SAVE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_PHONE_DISPLAYING_MESSAGE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_DISPLAY_ONSCREEN_TIMER_WITH_STRING, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_DISPLAY_ONSCREEN_COUNTER_WITH_STRING, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CREATE_RANDOM_CAR_FOR_CAR_PARK, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_COLLISION_IN_MEMORY, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_WANTED_MULTIPLIER, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CAMERA_IN_FRONT_OF_PLAYER, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CAR_VISIBLY_DAMAGED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_DOES_OBJECT_EXIST, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOAD_SCENE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ADD_STUCK_CAR_CHECK, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_REMOVE_STUCK_CAR_CHECK, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CAR_STUCK, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOAD_MISSION_AUDIO, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_HAS_MISSION_AUDIO_LOADED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_PLAY_MISSION_AUDIO, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_HAS_MISSION_AUDIO_FINISHED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_CLOSEST_CAR_NODE_WITH_HEADING, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_HAS_IMPORT_GARAGE_SLOT_BEEN_FILLED, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CLEAR_THIS_PRINT, INPUT_ARGUMENTS(ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CLEAR_THIS_BIG_PRINT, INPUT_ARGUMENTS(ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_MISSION_AUDIO_POSITION, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ACTIVATE_SAVE_MENU, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_HAS_SAVE_GAME_FINISHED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_NO_SPECIAL_CAMERA_FOR_THIS_GARAGE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ADD_BLIP_FOR_PICKUP_OLD, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ADD_BLIP_FOR_PICKUP, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ADD_SPRITE_BLIP_FOR_PICKUP, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_PED_DENSITY_MULTIPLIER, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_FORCE_RANDOM_PED_TYPE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_TEXT_DRAW_BEFORE_FADE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_COLLECTABLE1S_COLLECTED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_LEAVE_ANY_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_SPRITES_DRAW_BEFORE_FADE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_TEXT_RIGHT_JUSTIFY, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_PRINT_HELP, INPUT_ARGUMENTS(ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CLEAR_HELP, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_FLASH_HUD_OBJECT, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_FLASH_RADAR_BLIP, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CHAR_IN_CONTROL, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_GENERATE_CARS_AROUND_CAMERA, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CLEAR_SMALL_PRINTS, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_HAS_MILITARY_CRANE_COLLECTED_ALL_CARS, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_UPSIDEDOWN_CAR_NOT_DAMAGED, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CAN_PLAYER_START_MISSION, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_MAKE_PLAYER_SAFE_FOR_CUTSCENE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_USE_TEXT_COMMANDS, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_THREAT_FOR_PED_TYPE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CLEAR_THREAT_FOR_PED_TYPE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_CAR_COLOURS, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_ALL_CARS_CAN_BE_DAMAGED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CAR_CAN_BE_DAMAGED, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_MAKE_PLAYER_UNSAFE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOAD_COLLISION, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_BODY_CAST_HEALTH, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHARS_CHATTING, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_MAKE_PLAYER_SAFE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CAR_STAYS_IN_CURRENT_LEVEL, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_STAYS_IN_CURRENT_LEVEL, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_DRUNK_INPUT_DELAY, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_MONEY, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_INCREASE_CHAR_MONEY, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_OFFSET_FROM_OBJECT_IN_WORLD_COORDS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_REGISTER_LIFE_SAVED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_REGISTER_CRIMINAL_CAUGHT, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_REGISTER_AMBULANCE_LEVEL, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_REGISTER_FIRE_EXTINGUISHED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_TURN_PHONE_ON, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_REGISTER_LONGEST_DODO_FLIGHT, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_OFFSET_FROM_CAR_IN_WORLD_COORDS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_TOTAL_NUMBER_OF_KILL_FRENZIES, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_BLOW_UP_RC_BUGGY, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_REMOVE_CAR_FROM_CHASE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_FRENCH_GAME, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_GERMAN_GAME, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CLEAR_MISSION_AUDIO, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_FADE_IN_AFTER_NEXT_ARREST, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_FADE_IN_AFTER_NEXT_DEATH, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_GANG_PED_MODEL_PREFERENCE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_USE_PEDNODE_SEEK, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SWITCH_VEHICLE_WEAPONS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_GET_OUT_OF_JAIL_FREE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_FREE_HEALTH_CARE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CAR_DOOR_CLOSED, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOAD_AND_LAUNCH_MISSION, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOAD_AND_LAUNCH_MISSION_INTERNAL, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_OBJECT_DRAW_LAST, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_AMMO_IN_PLAYER_WEAPON, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_AMMO_IN_CHAR_WEAPON, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_REGISTER_KILL_FRENZY_PASSED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_SAY, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_NEAR_CLIP, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_RADIO_CHANNEL, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_OVERRIDE_HOSPITAL_LEVEL, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_OVERRIDE_POLICE_STATION_LEVEL, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_FORCE_RAIN, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_DOES_GARAGE_CONTAIN_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CAR_TRACTION, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ARE_MEASUREMENTS_IN_METRES, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CONVERT_METRES_TO_FEET, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_MARK_ROADS_BETWEEN_LEVELS, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_MARK_PED_ROADS_BETWEEN_LEVELS, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CAR_AVOID_LEVEL_TRANSITIONS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_AVOID_LEVEL_TRANSITIONS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_THREAT_FOR_PED_TYPE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CLEAR_AREA_OF_CHARS, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_TOTAL_NUMBER_OF_MISSIONS, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CONVERT_METRES_TO_FEET_INT, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_REGISTER_FASTEST_TIME, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_REGISTER_HIGHEST_SCORE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_WARP_CHAR_INTO_CAR_AS_PASSENGER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CAR_PASSENGER_SEAT_FREE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_CHAR_IN_CAR_PASSENGER_SEAT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_IS_CHRIS_CRIMINAL, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_START_CREDITS, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_STOP_CREDITS, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ARE_CREDITS_FINISHED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CREATE_SINGLE_PARTICLE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_IGNORE_LEVEL_TRANSITIONS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_CHASE_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_START_BOAT_FOAM_ANIMATION, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_UPDATE_BOAT_FOAM_ANIMATION, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_MUSIC_DOES_FADE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_INTRO_IS_PLAYING, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_PLAYER_HOOKER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_PLAY_END_OF_GAME_TUNE, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_STOP_END_OF_GAME_TUNE, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_CAR_MODEL, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_PLAYER_SITTING_IN_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_PLAYER_SITTING_IN_ANY_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_SCRIPT_FIRE_AUDIO, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ARE_ANY_CAR_CHEATS_ACTIVATED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_SUFFERS_CRITICAL_HITS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_PLAYER_LIFTING_A_PHONE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CHAR_SITTING_IN_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CHAR_SITTING_IN_ANY_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_PLAYER_ON_FOOT, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CHAR_ON_FOOT, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOAD_COLLISION_WITH_SCREEN, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOAD_SPLASH_SCREEN, INPUT_ARGUMENTS(ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CAR_IGNORE_LEVEL_TRANSITIONS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_MAKE_CRAIGS_CAR_A_BIT_STRONGER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_JAMES_CAR_ON_PATH_TO_PLAYER, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOAD_END_OF_GAME_TUNE, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ENABLE_PLAYER_CONTROL_CAMERA, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_OBJECT_ROTATION, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_DEBUG_CAMERA_COORDINATES, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_DEBUG_CAMERA_FRONT_VECTOR, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_PLAYER_TARGETTING_ANY_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_PLAYER_TARGETTING_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_PLAYER_TARGETTING_OBJECT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_TERMINATE_ALL_SCRIPTS_WITH_THIS_NAME, INPUT_ARGUMENTS(ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_DISPLAY_TEXT_WITH_NUMBER, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_STRING, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_DISPLAY_TEXT_WITH_2_NUMBERS, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_FAIL_CURRENT_MISSION, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_CLOSEST_OBJECT_OF_TYPE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_PLACE_OBJECT_RELATIVE_TO_OBJECT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_ALL_OCCUPANTS_OF_CAR_LEAVE_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_INTERPOLATION_PARAMETERS, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_CLOSEST_CAR_NODE_WITH_HEADING_TOWARDS_POINT, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_CLOSEST_CAR_NODE_WITH_HEADING_AWAY_POINT, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_DEBUG_CAMERA_POINT_AT, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ATTACH_CHAR_TO_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_DETACH_CHAR_FROM_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CAR_CHANGE_LANE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CLEAR_CHAR_LAST_WEAPON_DAMAGE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CLEAR_CAR_LAST_WEAPON_DAMAGE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_RANDOM_COP_IN_AREA, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_RANDOM_COP_IN_ZONE, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_FLEE_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_DRIVER_OF_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_NUMBER_OF_FOLLOWERS, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GIVE_REMOTE_CONTROLLED_MODEL_TO_PLAYER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_CURRENT_PLAYER_WEAPON, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_CURRENT_CHAR_WEAPON, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOCATE_CHAR_ANY_MEANS_OBJECT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOCATE_CHAR_ON_FOOT_OBJECT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOCATE_CHAR_IN_CAR_OBJECT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOCATE_CHAR_ANY_MEANS_OBJECT_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOCATE_CHAR_ON_FOOT_OBJECT_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOCATE_CHAR_IN_CAR_OBJECT_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CAR_TEMP_ACTION, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CAR_HANDBRAKE_TURN_RIGHT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CAR_HANDBRAKE_STOP, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CHAR_ON_ANY_BIKE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOCATE_SNIPER_BULLET_2D, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOCATE_SNIPER_BULLET_3D, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_NUMBER_OF_SEATS_IN_MODEL, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_PLAYER_ON_ANY_BIKE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CHAR_LYING_DOWN, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CAN_CHAR_SEE_DEAD_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_ENTER_CAR_RANGE_MULTIPLIER, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_THREAT_REACTION_RANGE_MULTIPLIER, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_CEASE_ATTACK_TIMER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_REMOTE_CONTROLLED_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_PC_VERSION, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_REPLAY, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_REPLAY_PLAYING, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_MODEL_AVAILABLE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SHUT_CHAR_UP, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_ENABLE_RC_DETONATE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CAR_RANDOM_ROUTE_SEED, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_ANY_PICKUP_AT_COORDS, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_FIRST_PICKUP_COORDS, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_NEXT_PICKUP_COORDS, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_REMOVE_ALL_CHAR_WEAPONS, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_HAS_PLAYER_GOT_WEAPON, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_HAS_CHAR_GOT_WEAPON, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_PLAYER_FACING_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_TANK_DETONATE_CARS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_POSITION_OF_ANALOGUE_STICKS, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CAR_ON_FIRE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CAR_TYRE_BURST, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CAR_DRIVE_STRAIGHT_AHEAD, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CAR_WAIT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_PLAYER_STANDING_ON_A_VEHICLE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_PLAYER_FOOT_DOWN, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CHAR_FOOT_DOWN, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_INITIALISE_OBJECT_PATH, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_START_OBJECT_ON_PATH, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_OBJECT_PATH_SPEED, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_OBJECT_PATH_POSITION, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_OBJECT_DISTANCE_ALONG_PATH, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CLEAR_OBJECT_PATH, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_HELI_GOTO_COORDS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_INT_VAR_EQUAL_TO_CONSTANT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_INT_LVAR_EQUAL_TO_CONSTANT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_DEAD_CHAR_PICKUP_COORDS, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CREATE_PROTECTION_PICKUP, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CHAR_IN_ANY_BOAT, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_PLAYER_IN_ANY_BOAT, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CHAR_IN_ANY_HELI, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_PLAYER_IN_ANY_HELI, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CHAR_IN_ANY_PLANE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_PLAYER_IN_ANY_PLANE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CHAR_IN_WATER, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_VAR_INT_TO_CONSTANT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, 0, \" =\"),\n\tREGISTER_COMMAND(COMMAND_SET_LVAR_INT_TO_CONSTANT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, 0, \" =\"),\n\tREGISTER_COMMAND(COMMAND_IS_INT_VAR_GREATER_THAN_CONSTANT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, 0, \" >\"),\n\tREGISTER_COMMAND(COMMAND_IS_INT_LVAR_GREATER_THAN_CONSTANT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, 0, \" >\"),\n\tREGISTER_COMMAND(COMMAND_IS_CONSTANT_GREATER_THAN_INT_VAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, 0, \" >\"),\n\tREGISTER_COMMAND(COMMAND_IS_CONSTANT_GREATER_THAN_INT_LVAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, 0, \" >\"),\n\tREGISTER_COMMAND(COMMAND_IS_INT_VAR_GREATER_OR_EQUAL_TO_CONSTANT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, 0, \" >=\"),\n\tREGISTER_COMMAND(COMMAND_IS_INT_LVAR_GREATER_OR_EQUAL_TO_CONSTANT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, 0, \" >=\"),\n\tREGISTER_COMMAND(COMMAND_IS_CONSTANT_GREATER_OR_EQUAL_TO_INT_VAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, 0, \" >=\"),\n\tREGISTER_COMMAND(COMMAND_IS_CONSTANT_GREATER_OR_EQUAL_TO_INT_LVAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, 0, \" >=\"),\n\tREGISTER_COMMAND(COMMAND_GET_CHAR_WEAPON_IN_SLOT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_CLOSEST_STRAIGHT_ROAD, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CAR_FORWARD_SPEED, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_AREA_VISIBLE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CUTSCENE_ANIM_TO_LOOP, INPUT_ARGUMENTS(ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_MARK_CAR_AS_CONVOY_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_RESET_HAVOC_CAUSED_BY_PLAYER, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_HAVOC_CAUSED_BY_PLAYER, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CREATE_SCRIPT_ROADBLOCK, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CLEAR_ALL_SCRIPT_ROADBLOCKS, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_WALK_TO_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_PICKUP_IN_ZONE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_OFFSET_FROM_CHAR_IN_WORLD_COORDS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_HAS_CHAR_BEEN_PHOTOGRAPHED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_AIM_GUN_AT_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SWITCH_SECURITY_CAMERA, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CHAR_IN_FLYING_VEHICLE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_PLAYER_IN_FLYING_VEHICLE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_HAS_SONY_CD_BEEN_READ, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_NUMBER_OF_SONY_CDS_READ, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ADD_SHORT_RANGE_BLIP_FOR_COORD_OLD, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ADD_SHORT_RANGE_BLIP_FOR_COORD, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ADD_SHORT_RANGE_SPRITE_BLIP_FOR_COORD, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ADD_MONEY_SPENT_ON_CLOTHES, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_HELI_ORIENTATION, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CLEAR_HELI_ORIENTATION, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_PLANE_GOTO_COORDS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_NTH_CLOSEST_CAR_NODE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_NTH_CLOSEST_CHAR_NODE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_DRAW_WEAPONSHOP_CORONA, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_ENABLE_RC_DETONATE_ON_CONTACT, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_FREEZE_CHAR_POSITION, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_DROWNS_IN_WATER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_OBJECT_RECORDS_COLLISIONS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_HAS_OBJECT_COLLIDED_WITH_ANYTHING, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_REMOVE_RC_BUGGY, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_HAS_PHOTOGRAPH_BEEN_TAKEN, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_CHAR_ARMOUR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_ARMOUR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_HELI_STABILISER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CAR_STRAIGHT_LINE_DISTANCE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_POP_CAR_BOOT, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SHUT_PLAYER_UP, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_PLAYER_MOOD, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_REQUEST_COLLISION, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOCATE_OBJECT_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOCATE_OBJECT_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_OBJECT_IN_WATER, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_STEAL_ANY_CAR_EVEN_MISSION_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_OBJECT_IN_AREA_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_OBJECT_IN_AREA_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_CROUCH, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_ZONE_CIVILIAN_CAR_INFO, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_REQUEST_ANIMATION, INPUT_ARGUMENTS(ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_HAS_ANIMATION_LOADED, INPUT_ARGUMENTS(ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_REMOVE_ANIMATION, INPUT_ARGUMENTS(ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CHAR_WAITING_FOR_WORLD_COLLISION, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CAR_WAITING_FOR_WORLD_COLLISION, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_OBJECT_WAITING_FOR_WORLD_COLLISION, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_SHUFFLE_INTO_DRIVERS_SEAT, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ATTACH_CHAR_TO_OBJECT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_AS_PLAYER_FRIEND, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_DISPLAY_NTH_ONSCREEN_COUNTER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_DISPLAY_NTH_ONSCREEN_COUNTER_WITH_STRING, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ADD_SET_PIECE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_EXTRA_COLOURS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CLEAR_EXTRA_COLOURS, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CLOSE_CAR_BOOT, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_WHEELIE_STATS, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_FLOAT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_DISARM_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_BURST_CAR_TYRE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CHAR_OBJ_NO_OBJ, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_PLAYER_WEARING, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_PLAYER_CAN_DO_DRIVE_BY, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_SPRINT_TO_COORD, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CREATE_SWAT_ROPE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_FIRST_PERSON_CONTROL_CAMERA, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_NEAREST_TYRE_TO_POINT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CAR_MODEL_COMPONENTS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SWITCH_LIFT_CAMERA, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CLOSE_ALL_CAR_DOORS, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_DISTANCE_BETWEEN_COORDS_2D, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_DISTANCE_BETWEEN_COORDS_3D, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_POP_CAR_BOOT_USING_PHYSICS, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_FIRST_PERSON_WEAPON_CAMERA, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CHAR_LEAVING_VEHICLE_TO_DIE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SORT_OUT_OBJECT_COLLISION_WITH_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_MAX_WANTED_LEVEL, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CHAR_WANDER_PATH_CLEAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_PRINT_HELP_WITH_NUMBER, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_PRINT_HELP_FOREVER, INPUT_ARGUMENTS(ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_PRINT_HELP_FOREVER_WITH_NUMBER, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_CAN_BE_DAMAGED_BY_MEMBERS_OF_GANG, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOAD_AND_LAUNCH_MISSION_EXCLUSIVE, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_MISSION_AUDIO_PLAYING, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CREATE_LOCKED_PROPERTY_PICKUP, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CREATE_FORSALE_PROPERTY_PICKUP, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_FREEZE_CAR_POSITION, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_HAS_CHAR_BEEN_DAMAGED_BY_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_HAS_CHAR_BEEN_DAMAGED_BY_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_HAS_CAR_BEEN_DAMAGED_BY_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_HAS_CAR_BEEN_DAMAGED_BY_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_RADIO_CHANNEL, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_DISPLAY_TEXT_WITH_3_NUMBERS, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CAR_DROWNING_IN_WATER, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CHAR_DROWNING_IN_WATER, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_DISABLE_CUTSCENE_SHADOWS, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_HAS_GLASS_BEEN_SHATTERED_NEARBY, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ATTACH_CUTSCENE_OBJECT_TO_BONE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ATTACH_CUTSCENE_OBJECT_TO_COMPONENT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_STAY_IN_CAR_WHEN_JACKED, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_MISSION_AUDIO_LOADING, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ADD_MONEY_SPENT_ON_WEAPONS, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ADD_MONEY_SPENT_ON_PROPERTY, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ADD_MONEY_SPENT_ON_AUTO_PAINTING, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_ANSWERING_MOBILE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_PLAYER_DRUNKENNESS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_PLAYER_DRUNKENNESS, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_PLAYER_DRUG_LEVEL, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_PLAYER_DRUG_LEVEL, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ADD_LOAN_SHARK_VISITS, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ADD_STORES_KNOCKED_OFF, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ADD_MOVIE_STUNTS, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ADD_NUMBER_OF_ASSASSINATIONS, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ADD_PIZZAS_DELIVERED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ADD_GARBAGE_PICKUPS, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ADD_ICE_CREAMS_SOLD, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_TOP_SHOOTING_RANGE_SCORE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ADD_SHOOTING_RANGE_RANK, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ADD_MONEY_SPENT_ON_GAMBLING, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ADD_MONEY_WON_ON_GAMBLING, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_LARGEST_GAMBLING_WIN, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_IN_PLAYERS_GROUP_CAN_FIGHT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CLEAR_CHAR_WAIT_STATE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_RANDOM_CAR_OF_TYPE_IN_AREA_NO_SAVE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CAN_BURST_CAR_TYRES, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_PLAYER_AUTO_AIM, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_FIRE_HUNTER_GUN, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_PROPERTY_AS_OWNED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ADD_BLOOD_RING_KILLS, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_LONGEST_TIME_IN_BLOOD_RING, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_REMOVE_EVERYTHING_FOR_HUGE_CUTSCENE, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_PLAYER_TOUCHING_VEHICLE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CHAR_TOUCHING_VEHICLE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CHECK_FOR_PED_MODEL_AROUND_PLAYER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CLEAR_CHAR_FOLLOW_PATH, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_CAN_BE_SHOT_IN_VEHICLE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ATTACH_CUTSCENE_OBJECT_TO_VEHICLE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOAD_MISSION_TEXT, INPUT_ARGUMENTS(ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_TONIGHTS_EVENT, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CLEAR_CHAR_LAST_DAMAGE_ENTITY, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CLEAR_CAR_LAST_DAMAGE_ENTITY, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_FREEZE_OBJECT_POSITION, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_PLAYER_HAS_MET_DEBBIE_HARRY, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_RIOT_INTENSITY, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CAR_IN_ANGLED_AREA_2D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CAR_IN_ANGLED_AREA_3D, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_REMOVE_WEAPON_FROM_CHAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_UP_TAXI_SHORTCUT, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CLEAR_TAXI_SHORTCUT, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_GOTO_CAR_ON_FOOT, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_CLOSEST_WATER_NODE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ADD_PORN_LEAFLET_TO_RUBBISH, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CREATE_CLOTHES_PICKUP, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CHANGE_BLIP_THRESHOLD, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_MAKE_PLAYER_FIRE_PROOF, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_INCREASE_PLAYER_MAX_HEALTH, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_INCREASE_PLAYER_MAX_ARMOUR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CREATE_RANDOM_CHAR_AS_DRIVER, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CREATE_RANDOM_CHAR_AS_PASSENGER, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_IGNORE_THREATS_BEHIND_OBJECTS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ENSURE_PLAYER_HAS_DRIVE_BY_WEAPON, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_MAKE_HELI_COME_CRASHING_DOWN, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ADD_EXPLOSION_NO_SOUND, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_OBJECT_AREA_VISIBLE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_WAS_VEHICLE_EVER_POLICE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_NEVER_TARGETTED, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_LOAD_UNCOMPRESSED_ANIM, INPUT_ARGUMENTS(ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_WAS_CUTSCENE_SKIPPED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_CROUCH_WHEN_THREATENED, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CHAR_IN_ANY_POLICE_VEHICLE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_DOES_CHAR_EXIST, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_DOES_VEHICLE_EXIST, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ADD_SHORT_RANGE_BLIP_FOR_CONTACT_POINT, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ADD_SHORT_RANGE_SPRITE_BLIP_FOR_CONTACT_POINT, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CHAR_STUCK, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_ALL_TAXIS_HAVE_NITRO, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_STOP_SHOOT_DONT_SEEK_ENTITY, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_FREEZE_CAR_POSITION_AND_DONT_LOAD_COLLISION, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_FREEZE_CHAR_POSITION_AND_DONT_LOAD_COLLISION, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_FREEZE_OBJECT_POSITION_AND_DONT_LOAD_COLLISION, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_FADE_AND_JUMPCUT_AFTER_RC_EXPLOSION, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_REGISTER_VIGILANTE_LEVEL, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CLEAR_ALL_CHAR_ANIMS, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_MAXIMUM_NUMBER_OF_CARS_IN_GARAGE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_WANTED_STARS_ARE_FLASHING, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_ALLOW_HURRICANES, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_PLAY_ANNOUNCEMENT, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_PLAYER_IS_IN_STADIUM, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_BUS_FARES_COLLECTED_BY_PLAYER, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_OBJ_BUY_ICE_CREAM, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_DISPLAY_RADAR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_REGISTER_BEST_POSITION, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_PLAYER_IN_INFO_ZONE, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_STRING, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CLEAR_CHAR_ICE_CREAM_PURCHASE, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_IN_CAR_FIRE_BUTTON_PRESSED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_HAS_CHAR_ATTEMPTED_ATTRACTOR, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_LOAD_COLLISION_FOR_CAR_FLAG, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_LOAD_COLLISION_FOR_CHAR_FLAG, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_LOAD_COLLISION_FOR_OBJECT_FLAG, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ADD_BIG_GUN_FLASH, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_HAS_CHAR_BOUGHT_ICE_CREAM, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_PROGRESS_PERCENTAGE, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_SHORTCUT_PICKUP_POINT, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_SHORTCUT_DROPOFF_POINT_FOR_MISSION, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_RANDOM_ICE_CREAM_CUSTOMER_IN_AREA, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_RANDOM_ICE_CREAM_CUSTOMER_IN_ZONE, INPUT_ARGUMENTS(ARGTYPE_STRING, ARGTYPE_INT, ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_UNLOCK_ALL_CAR_DOORS_IN_AREA, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_GANG_ATTACK_PLAYER_WITH_COPS, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_CHAR_FRIGHTENED_IN_JACKED_CAR, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_VEHICLE_TO_FADE_IN, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_REGISTER_ODDJOB_MISSION_PASSED, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_PLAYER_IN_SHORTCUT_TAXI, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_CHAR_DUCKING, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CREATE_DUST_EFFECT_FOR_CUTSCENE_HELI, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_REGISTER_FIRE_LEVEL, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_AUSTRALIAN_GAME, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_DISARM_CAR_BOMB, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n#if (defined GTAVC_JP_PATCH || defined SUPPORT_JAPANESE_SCRIPT)\n\tREGISTER_COMMAND(COMMAND_IS_JAPANESE_GAME, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n#elif (!defined GTA_PS2)\n\tREGISTER_COMMAND(COMMAND_SET_ONSCREEN_COUNTER_FLASH_WHEN_FIRST_DISPLAYED, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n#endif\n#if (defined GTA_PC && !defined GTAVC_JP_PATCH || defined GTA_XBOX || defined SUPPORT_XBOX_SCRIPT || defined GTA_MOBILE || defined SUPPORT_MOBILE_SCRIPT)\n\tREGISTER_COMMAND(COMMAND_SHUFFLE_CARD_DECKS, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_FETCH_NEXT_CARD, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_OBJECT_VELOCITY, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_DEBUG_CAMERA_ON, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ADD_TO_OBJECT_ROTATION_VELOCITY, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_OBJECT_ROTATION_VELOCITY, INPUT_ARGUMENTS(ARGTYPE_INT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_OBJECT_STATIC, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_ANGLE_BETWEEN_2D_VECTORS, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_DO_2D_RECTANGLES_COLLIDE, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), true, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_OBJECT_ROTATION_VELOCITY, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_ADD_VELOCITY_RELATIVE_TO_OBJECT_VELOCITY, INPUT_ARGUMENTS(ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ARGTYPE_FLOAT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_GET_OBJECT_SPEED, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(ARGTYPE_FLOAT, ), false, -1, \"\"),\n#endif\n#if (defined GTA_XBOX || defined SUPPORT_XBOX_SCRIPT)\n\tREGISTER_COMMAND(COMMAND_MARK_CUTSCENE_START, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_MARK_CUTSCENE_END, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CUTSCENE_SCROLL, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n#elif (defined GTA_MOBILE || defined SUPPORT_MOBILE_SCRIPT)\n\tREGISTER_COMMAND(COMMAND_IS_MISSION_SKIP, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_SET_IN_AMMUNATION, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_DO_SAVE_GAME, INPUT_ARGUMENTS(ARGTYPE_INT, ), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_IS_RETRY, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(ARGTYPE_INT, ), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_DUMMY, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_MARK_CUTSCENE_START, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_MARK_CUTSCENE_END, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n\tREGISTER_COMMAND(COMMAND_CUTSCENE_SCROLL, INPUT_ARGUMENTS(), OUTPUT_ARGUMENTS(), false, -1, \"\"),\n#endif\n};\n#undef REGISTER_COMMAND\n#undef INPUT_ARGUMENTS\n#undef OUTPUT_ARGUMENTS\n\nstatic_assert(ARRAY_SIZE(commands) == LAST_SCRIPT_COMMAND, \"commands array not filled\");\n\n#if SCRIPT_LOG_FILE_LEVEL == 1 || SCRIPT_LOG_FILE_LEVEL == 2\nstatic FILE* dbg_log;\n#endif\n\nstatic void PrintToLog(const char* format, ...)\n{\n\tva_list va;\n\tva_start(va, format);\n\tchar tmp[1024];\n#ifdef _WIN32\n\tvsprintf_s(tmp, 1024, format, va);\n#else\n\tvsprintf(tmp, format, va);\n#endif\n\tva_end(va);\n\n#if SCRIPT_LOG_FILE_LEVEL == 1 || SCRIPT_LOG_FILE_LEVEL == 2\n\tif (dbg_log)\n\t\tfwrite(tmp, 1, strlen(tmp), dbg_log);\n#endif\n}\n\n#endif\n\nvoid FlushLog()\n{\n#ifdef USE_ADVANCED_SCRIPT_DEBUG_OUTPUT\n#if SCRIPT_LOG_FILE_LEVEL == 1 || SCRIPT_LOG_FILE_LEVEL == 2\n\tif (dbg_log)\n\t\tfflush(dbg_log);\n#endif\n#endif\n}\n\nconst uint32 CRunningScript::nSaveStructSize =\n#ifdef COMPATIBLE_SAVES\n\t136;\n#else\n\tsizeof(CRunningScript);\n#endif\n\nCMissionCleanup::CMissionCleanup()\n{\n\tInit();\n}\n\nvoid CMissionCleanup::Init()\n{\n\tm_nCount = 0;\n\tfor (int i = 0; i < MAX_CLEANUP; i++){\n\t\tm_sEntities[i].type = CLEANUP_UNUSED;\n\t\tm_sEntities[i].id = 0;\n\t}\n}\n\ncleanup_entity_struct* CMissionCleanup::FindFree()\n{\n\tfor (int i = 0; i < MAX_CLEANUP; i++){\n\t\tif (m_sEntities[i].type == CLEANUP_UNUSED)\n\t\t\treturn &m_sEntities[i];\n\t}\n\tscript_assert(0);\n\treturn nil;\n}\n\nvoid CMissionCleanup::AddEntityToList(int32 id, uint8 type)\n{\n\tcleanup_entity_struct* pNew = FindFree();\n\tif (!pNew)\n\t\treturn;\n\tpNew->id = id;\n\tpNew->type = type;\n\tm_nCount++;\n}\n\nvoid CMissionCleanup::RemoveEntityFromList(int32 id, uint8 type)\n{\n\tfor (int i = 0; i < MAX_CLEANUP; i++){\n\t\tif (m_sEntities[i].type == type && m_sEntities[i].id == id){\n\t\t\tswitch (m_sEntities[i].type) {\n\t\t\tcase CLEANUP_CAR:\n\t\t\t{\n\t\t\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(m_sEntities[i].id);\n\t\t\t\tif (pVehicle) {\n\t\t\t\t\tif (pVehicle->bIsStaticWaitingForCollision) {\n\t\t\t\t\t\tpVehicle->bIsStaticWaitingForCollision = false;\n\t\t\t\t\t\tif (!pVehicle->GetIsStatic())\n\t\t\t\t\t\t\tpVehicle->AddToMovingList();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase CLEANUP_CHAR:\n\t\t\t{\n\t\t\t\tCPed* pPed = CPools::GetPedPool()->GetAt(m_sEntities[i].id);\n\t\t\t\tif (pPed) {\n\t\t\t\t\tif (pPed->bIsStaticWaitingForCollision) {\n\t\t\t\t\t\tpPed->bIsStaticWaitingForCollision = false;\n\t\t\t\t\t\tif (!pPed->GetIsStatic())\n\t\t\t\t\t\t\tpPed->AddToMovingList();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase CLEANUP_OBJECT:\n\t\t\t{\n\t\t\t\tCObject* pObject = CPools::GetObjectPool()->GetAt(m_sEntities[i].id);\n\t\t\t\tif (pObject) {\n\t\t\t\t\tif (pObject->bIsStaticWaitingForCollision) {\n\t\t\t\t\t\tpObject->bIsStaticWaitingForCollision = false;\n\t\t\t\t\t\tif (!pObject->GetIsStatic())\n\t\t\t\t\t\t\tpObject->AddToMovingList();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tm_sEntities[i].id = 0;\n\t\t\tm_sEntities[i].type = CLEANUP_UNUSED;\n\t\t\tm_nCount--;\n\t\t}\n\t}\n}\n\nvoid CMissionCleanup::CheckIfCollisionHasLoadedForMissionObjects()\n{\n\tfor (int i = 0; i < MAX_CLEANUP; i++) {\n\t\tswitch (m_sEntities[i].type) {\n\t\tcase CLEANUP_CAR:\n\t\t{\n\t\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(m_sEntities[i].id);\n\t\t\tif (pVehicle) {\n\t\t\t\tif (pVehicle->bIsStaticWaitingForCollision) {\n\t\t\t\t\tif (CColStore::HasCollisionLoaded(pVehicle->GetPosition())) {\n\t\t\t\t\t\tpVehicle->bIsStaticWaitingForCollision = false;\n\t\t\t\t\t\t\tif (!pVehicle->GetIsStatic())\n\t\t\t\t\t\t\t\tpVehicle->AddToMovingList();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tcase CLEANUP_CHAR:\n\t\t{\n\t\t\tCPed* pPed = CPools::GetPedPool()->GetAt(m_sEntities[i].id);\n\t\t\tif (pPed) {\n\t\t\t\tif (pPed->bIsStaticWaitingForCollision) {\n\t\t\t\t\tif (CColStore::HasCollisionLoaded(pPed->GetPosition())) {\n\t\t\t\t\t\tpPed->bIsStaticWaitingForCollision = false;\n\t\t\t\t\t\tif (!pPed->GetIsStatic())\n\t\t\t\t\t\t\tpPed->AddToMovingList();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tcase CLEANUP_OBJECT:\n\t\t{\n\t\t\tCObject* pObject = CPools::GetObjectPool()->GetAt(m_sEntities[i].id);\n\t\t\tif (pObject) {\n\t\t\t\tif (pObject->bIsStaticWaitingForCollision) {\n\t\t\t\t\tif (CColStore::HasCollisionLoaded(pObject->GetPosition())) {\n\t\t\t\t\t\tpObject->bIsStaticWaitingForCollision = false;\n\t\t\t\t\t\tif (!pObject->GetIsStatic())\n\t\t\t\t\t\t\tpObject->AddToMovingList();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\nvoid CMissionCleanup::Process()\n{\n\tCPopulation::m_AllRandomPedsThisType = -1;\n\tCPopulation::PedDensityMultiplier = 1.0f;\n\tCCarCtrl::CarDensityMultiplier = 1.0f;\n\tCPed::nThreatReactionRangeMultiplier = 1;\n\tCPed::nEnterCarRangeMultiplier = 1;\n\tFindPlayerPed()->m_pWanted->m_fCrimeSensitivity = 1.0f;\n\tCRoadBlocks::ClearScriptRoadBlocks();\n\tCRouteNode::Initialise();\n\tif (!CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle)\n\t\tTheCamera.Restore();\n\tTheCamera.SetWideScreenOff();\n\tCSpecialFX::bLiftCam = false;\n\tCSpecialFX::bVideoCam = false;\n\tCTimeCycle::StopExtraColour(0);\n\tfor (int i = 0; i < MISSION_AUDIO_SLOTS; i++)\n\t\tDMAudio.ClearMissionAudio(i);\n\tCWeather::ReleaseWeather();\n\tfor (int i = 0; i < NUM_OF_SPECIAL_CHARS; i++)\n\t\tCStreaming::SetMissionDoesntRequireSpecialChar(i);\n\tfor (int i = 0; i < NUM_OF_CUTSCENE_OBJECTS; i++)\n\t\tCStreaming::SetMissionDoesntRequireModel(MI_CUTOBJ01 + i);\n\tCStreaming::ms_disableStreaming = false;\n\tCHud::m_ItemToFlash = -1;\n\tCHud::SetHelpMessage(nil, false);\n\tCUserDisplay::OnscnTimer.m_bDisabled = false;\n\tCTheScripts::RemoveScriptTextureDictionary();\n\tCWorld::Players[0].m_pPed->m_pWanted->m_bIgnoredByCops = false;\n\tCWorld::Players[0].m_pPed->m_pWanted->m_bIgnoredByEveryone = false;\n\tCWorld::Players[0].MakePlayerSafe(false);\n\tCWorld::Players[0].m_pPed->m_nFadeDrunkenness = 1;\n\tCWorld::Players[0].m_pPed->m_nDrunkCountdown = 0;\n\tCPad::GetPad(0)->SetDrunkInputDelay(0);\n\tCWorld::Players[0].m_bDriveByAllowed = true;\n\tDMAudio.ShutUpPlayerTalking(0);\n\tCVehicle::bDisableRemoteDetonation = false;\n\tCVehicle::bDisableRemoteDetonationOnContact = false;\n\tCGameLogic::ClearShortCut();\n\tCTheScripts::RiotIntensity = 0;\n\tCTheScripts::StoreVehicleIndex = -1;\n\tCTheScripts::StoreVehicleWasRandom = true;\n\tCTheScripts::UpsideDownCars.Init();\n\tCTheScripts::StuckCars.Init();\n\tfor (int i = 0; i < MAX_CLEANUP; i++){\n\t\tif (m_sEntities[i].type == CLEANUP_UNUSED)\n\t\t\tcontinue;\n\t\tswitch (m_sEntities[i].type) {\n\t\tcase CLEANUP_CAR:\n\t\t{\n\t\t\tCVehicle* v = CPools::GetVehiclePool()->GetAt(m_sEntities[i].id);\n\t\t\tif (v)\n\t\t\t\tCTheScripts::CleanUpThisVehicle(v);\n\t\t\tbreak;\n\t\t}\n\t\tcase CLEANUP_CHAR:\n\t\t{\n\t\t\tCPed* p = CPools::GetPedPool()->GetAt(m_sEntities[i].id);\n\t\t\tif (p)\n\t\t\t\tCTheScripts::CleanUpThisPed(p);\n\t\t\tbreak;\n\t\t}\n\t\tcase CLEANUP_OBJECT:\n\t\t{\n\t\t\tCObject* o = CPools::GetObjectPool()->GetAt(m_sEntities[i].id);\n\t\t\tif (o)\n\t\t\t\tCTheScripts::CleanUpThisObject(o);\n\t\t\tbreak;\n\t\t}\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\t\tRemoveEntityFromList(m_sEntities[i].id, m_sEntities[i].type);\n\t}\n#ifdef SECUROM\n\tif ((myrand() & 3) == 2){\n\t\t// if pirated game\n\t\tCWeather::ForceHurricaneWeather();\n\t}\n#endif\n}\n\n/* NB: CUpsideDownCarCheck is not used by actual script at all\n * It has a weird usage: AreAnyCarsUpsideDown would fail any mission\n * just like death or arrest. */\n\nvoid CUpsideDownCarCheck::Init()\n{\n\tfor (int i = 0; i < MAX_UPSIDEDOWN_CAR_CHECKS; i++){\n\t\tm_sCars[i].m_nVehicleIndex = -1;\n\t\tm_sCars[i].m_nUpsideDownTimer = 0;\n\t}\n}\n\nbool CUpsideDownCarCheck::IsCarUpsideDown(int32 id)\n{\n\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(id);\n\treturn IsCarUpsideDown(pVehicle);\n}\n\nbool CUpsideDownCarCheck::IsCarUpsideDown(CVehicle* pVehicle)\n{\n\tassert(pVehicle);\n\treturn pVehicle->GetUp().z <= UPSIDEDOWN_UP_THRESHOLD &&\n\t\tpVehicle->GetMoveSpeed().Magnitude() < UPSIDEDOWN_MOVE_SPEED_THRESHOLD &&\n\t\tpVehicle->GetTurnSpeed().Magnitude() < UPSIDEDOWN_TURN_SPEED_THRESHOLD;\n}\n\nvoid CUpsideDownCarCheck::UpdateTimers()\n{\n\tuint32 timeStep = CTimer::GetTimeStepInMilliseconds();\n\tfor (int i = 0; i < MAX_UPSIDEDOWN_CAR_CHECKS; i++){\n\t\tCVehicle* v = CPools::GetVehiclePool()->GetAt(m_sCars[i].m_nVehicleIndex);\n\t\tif (v){\n\t\t\tif (IsCarUpsideDown(m_sCars[i].m_nVehicleIndex))\n\t\t\t\tm_sCars[i].m_nUpsideDownTimer += timeStep;\n\t\t\telse\n\t\t\t\tm_sCars[i].m_nUpsideDownTimer = 0;\n\t\t}else{\n\t\t\tm_sCars[i].m_nVehicleIndex = -1;\n\t\t\tm_sCars[i].m_nUpsideDownTimer = 0;\n\t\t}\n\t}\n}\n\nbool CUpsideDownCarCheck::AreAnyCarsUpsideDown()\n{\n\tfor (int i = 0; i < MAX_UPSIDEDOWN_CAR_CHECKS; i++){\n\t\tif (m_sCars[i].m_nVehicleIndex >= 0 && m_sCars[i].m_nUpsideDownTimer > UPSIDEDOWN_TIMER_THRESHOLD)\n\t\t\treturn true;\n\t}\n\treturn false;\n}\n\nvoid CUpsideDownCarCheck::AddCarToCheck(int32 id)\n{\n\tuint16 index = 0;\n\twhile (index < MAX_UPSIDEDOWN_CAR_CHECKS && m_sCars[index].m_nVehicleIndex >= 0)\n\t\tindex++;\n#ifdef FIX_BUGS\n\tif (index >= MAX_UPSIDEDOWN_CAR_CHECKS)\n\t\treturn;\n#endif\n\tm_sCars[index].m_nVehicleIndex = id;\n\tm_sCars[index].m_nUpsideDownTimer = 0;\n}\n\nvoid CUpsideDownCarCheck::RemoveCarFromCheck(int32 id)\n{\n\tfor (int i = 0; i < MAX_UPSIDEDOWN_CAR_CHECKS; i++){\n\t\tif (m_sCars[i].m_nVehicleIndex == id){\n\t\t\tm_sCars[i].m_nVehicleIndex = -1;\n\t\t\tm_sCars[i].m_nUpsideDownTimer = 0;\n\t\t}\n\t}\n}\n\nbool CUpsideDownCarCheck::HasCarBeenUpsideDownForAWhile(int32 id)\n{\n\tfor (int i = 0; i < MAX_UPSIDEDOWN_CAR_CHECKS; i++){\n\t\tif (m_sCars[i].m_nVehicleIndex == id)\n\t\t\treturn m_sCars[i].m_nUpsideDownTimer > UPSIDEDOWN_TIMER_THRESHOLD;\n\t}\n\treturn false;\n}\n\nvoid stuck_car_data::Reset()\n{\n\tm_nVehicleIndex = -1;\n\tm_vecPos = CVector(-5000.0f, -5000.0f, -5000.0f);\n\tm_nLastCheck = -1;\n\tm_fRadius = 0.0f;\n\tm_nStuckTime = 0;\n\tm_bStuck = false;\n}\n\nvoid CStuckCarCheck::Init()\n{\n\tfor (int i = 0; i < MAX_STUCK_CAR_CHECKS; i++) {\n\t\tm_sCars[i].Reset();\n\t}\n}\n\nvoid CStuckCarCheck::Process()\n{\n\tuint32 timer = CTimer::GetTimeInMilliseconds();\n\tfor (int i = 0; i < MAX_STUCK_CAR_CHECKS; i++){\n\t\tif (m_sCars[i].m_nVehicleIndex < 0)\n\t\t\tcontinue;\n\t\tif (timer <= m_sCars[i].m_nStuckTime + m_sCars[i].m_nLastCheck)\n\t\t\tcontinue;\n\t\tCVehicle* pv = CPools::GetVehiclePool()->GetAt(m_sCars[i].m_nVehicleIndex);\n\t\tif (!pv){\n\t\t\tm_sCars[i].Reset();\n\t\t\tcontinue;\n\t\t}\n\t\tfloat distance = (pv->GetPosition() - m_sCars[i].m_vecPos).Magnitude();\n\t\tm_sCars[i].m_bStuck = distance < m_sCars[i].m_fRadius;\n\t\tm_sCars[i].m_vecPos = pv->GetPosition();\n\t\tm_sCars[i].m_nLastCheck = timer;\n\t}\n}\n\nvoid CStuckCarCheck::AddCarToCheck(int32 id, float radius, uint32 time)\n{\n\tCVehicle* pv = CPools::GetVehiclePool()->GetAt(id);\n\tif (!pv)\n\t\treturn;\n\tint index = 0;\n\twhile (index < MAX_STUCK_CAR_CHECKS && m_sCars[index].m_nVehicleIndex >= 0)\n\t\tindex++;\n#ifdef FIX_BUGS\n\tif (index >= MAX_STUCK_CAR_CHECKS)\n\t\treturn;\n#endif\n\tm_sCars[index].m_nVehicleIndex = id;\n\tm_sCars[index].m_vecPos = pv->GetPosition();\n\tm_sCars[index].m_nLastCheck = CTimer::GetTimeInMilliseconds();\n\tm_sCars[index].m_fRadius = radius;\n\tm_sCars[index].m_nStuckTime = time;\n\tm_sCars[index].m_bStuck = false;\n}\n\nvoid CStuckCarCheck::RemoveCarFromCheck(int32 id)\n{\n\tfor (int i = 0; i < MAX_STUCK_CAR_CHECKS; i++){\n\t\tif (m_sCars[i].m_nVehicleIndex == id){\n\t\t\tm_sCars[i].Reset();\n\t\t}\n\t}\n}\n\nbool CStuckCarCheck::HasCarBeenStuckForAWhile(int32 id)\n{\n\tfor (int i = 0; i < MAX_STUCK_CAR_CHECKS; i++){\n\t\tif (m_sCars[i].m_nVehicleIndex == id)\n\t\t\treturn m_sCars[i].m_bStuck;\n\t}\n\treturn false;\n}\n\nvoid CRunningScript::CollectParameters(uint32* pIp, int16 total)\n{\n\tfor (int16 i = 0; i < total; i++){\n\t\tuint16 varIndex;\n\t\tswitch (CTheScripts::Read1ByteFromScript(pIp))\n\t\t{\n\t\tcase ARGUMENT_INT32:\n\t\tcase ARGUMENT_FLOAT:\n\t\t\tScriptParams[i] = CTheScripts::Read4BytesFromScript(pIp);\n\t\t\tbreak;\n\t\tcase ARGUMENT_GLOBALVAR:\n\t\t\tvarIndex = CTheScripts::Read2BytesFromScript(pIp);\n\t\t\tscript_assert(varIndex >= 8 && varIndex < CTheScripts::GetSizeOfVariableSpace());\n\t\t\tScriptParams[i] = *((int32*)&CTheScripts::ScriptSpace[varIndex]);\n\t\t\tbreak;\n\t\tcase ARGUMENT_LOCALVAR:\n\t\t\tvarIndex = CTheScripts::Read2BytesFromScript(pIp);\n\t\t\tscript_assert(varIndex >= 0 && varIndex < ARRAY_SIZE(m_anLocalVariables));\n\t\t\tScriptParams[i] = m_anLocalVariables[varIndex];\n\t\t\tbreak;\n\t\tcase ARGUMENT_INT8:\n\t\t\tScriptParams[i] = CTheScripts::Read1ByteFromScript(pIp);\n\t\t\tbreak;\n\t\tcase ARGUMENT_INT16:\n\t\t\tScriptParams[i] = CTheScripts::Read2BytesFromScript(pIp);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tscript_assert(0);\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\n#ifdef USE_ADVANCED_SCRIPT_DEBUG_OUTPUT\nint CRunningScript::CollectParameterForDebug(char* buf, bool& var)\n{\n\tuint16 varIndex;\n\tchar tmpstr[24];\n\tvar = false;\n\tswitch (CTheScripts::Read1ByteFromScript(&m_nIp))\n\t{\n\tcase ARGUMENT_INT32:\n\tcase ARGUMENT_FLOAT:\n\t\treturn CTheScripts::Read4BytesFromScript(&m_nIp);\n\tcase ARGUMENT_GLOBALVAR:\n\t\tvarIndex = CTheScripts::Read2BytesFromScript(&m_nIp);\n\t\tscript_assert(varIndex >= 8 && varIndex < CTheScripts::GetSizeOfVariableSpace());\n\t\tvar = true;\n\t\tsprintf(tmpstr, \" $%d\", varIndex / 4);\n\t\tstrcat(buf, tmpstr);\n\t\treturn *((int32*)&CTheScripts::ScriptSpace[varIndex]);\n\tcase ARGUMENT_LOCALVAR:\n\t\tvarIndex = CTheScripts::Read2BytesFromScript(&m_nIp);\n\t\tscript_assert(varIndex >= 0 && varIndex < ARRAY_SIZE(m_anLocalVariables));\n\t\tvar = true;\n\t\tsprintf(tmpstr, \" %d@\", varIndex);\n\t\tstrcat(buf, tmpstr);\n\t\treturn m_anLocalVariables[varIndex];\n\tcase ARGUMENT_INT8:\n\t\treturn CTheScripts::Read1ByteFromScript(&m_nIp);\n\tcase ARGUMENT_INT16:\n\t\treturn CTheScripts::Read2BytesFromScript(&m_nIp);\n\tdefault:\n\t\tPrintToLog(\"%s - script assertion failed in CollectParameterForDebug\", buf);\n\t\tscript_assert(0);\n\t\tbreak;\n\t}\n\treturn 0;\n}\n\nvoid CRunningScript::GetStoredParameterForDebug(char* buf)\n{\n\tuint16 varIndex;\n\tchar tmpstr[24];\n\tswitch (CTheScripts::Read1ByteFromScript(&m_nIp)) {\n\tcase ARGUMENT_GLOBALVAR:\n\t\tvarIndex = CTheScripts::Read2BytesFromScript(&m_nIp);\n\t\tsprintf(tmpstr, \" $%d\", varIndex / 4);\n\t\tstrcat(buf, tmpstr);\n\t\tbreak;\n\tcase ARGUMENT_LOCALVAR:\n\t\tvarIndex = CTheScripts::Read2BytesFromScript(&m_nIp);\n\t\tsprintf(tmpstr, \" %d@\", varIndex);\n\t\tstrcat(buf, tmpstr);\n\t\tbreak;\n\tdefault:\n\t\tPrintToLog(\"%s - script_assertion failed in GetStoredParameterForDebug\", buf);\n\t\tscript_assert(0);\n\t}\n}\n#endif\n\nint32 CRunningScript::CollectNextParameterWithoutIncreasingPC(uint32 ip)\n{\n\tuint32* pIp = &ip;\n\tswitch (CTheScripts::Read1ByteFromScript(pIp))\n\t{\n\tcase ARGUMENT_INT32:\n\t\treturn CTheScripts::Read4BytesFromScript(pIp);\n\tcase ARGUMENT_GLOBALVAR:\n\t\treturn *((int32*)&CTheScripts::ScriptSpace[(uint16)CTheScripts::Read2BytesFromScript(pIp)]);\n\tcase ARGUMENT_LOCALVAR:\n\t\treturn m_anLocalVariables[CTheScripts::Read2BytesFromScript(pIp)];\n\tcase ARGUMENT_INT8:\n\t\treturn CTheScripts::Read1ByteFromScript(pIp);\n\tcase ARGUMENT_INT16:\n\t\treturn CTheScripts::Read2BytesFromScript(pIp);\n\tcase ARGUMENT_FLOAT:\n\t\treturn CTheScripts::Read4BytesFromScript(pIp);\n\tdefault:\n\t\tscript_assert(0);\n\t}\n\treturn -1;\n}\n\nvoid CRunningScript::StoreParameters(uint32* pIp, int16 number)\n{\n\tfor (int16 i = 0; i < number; i++){\n\t\tswitch (CTheScripts::Read1ByteFromScript(pIp)) {\n\t\tcase ARGUMENT_GLOBALVAR:\n\t\t\t*(int32*)&CTheScripts::ScriptSpace[(uint16)CTheScripts::Read2BytesFromScript(pIp)] = ScriptParams[i];\n\t\t\tbreak;\n\t\tcase ARGUMENT_LOCALVAR:\n\t\t\tm_anLocalVariables[CTheScripts::Read2BytesFromScript(pIp)] = ScriptParams[i];\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tscript_assert(0);\n\t\t}\n\t}\n}\n\nint32 *CRunningScript::GetPointerToScriptVariable(uint32* pIp, int16 type)\n{\n\tswitch (CTheScripts::Read1ByteFromScript(pIp))\n\t{\n\tcase ARGUMENT_GLOBALVAR:\n\t\tscript_assert(type == VAR_GLOBAL);\n\t\treturn (int32*)&CTheScripts::ScriptSpace[(uint16)CTheScripts::Read2BytesFromScript(pIp)];\n\tcase ARGUMENT_LOCALVAR:\n\t\tscript_assert(type == VAR_LOCAL);\n\t\treturn &m_anLocalVariables[CTheScripts::Read2BytesFromScript(pIp)];\n\tdefault:\n\t\tscript_assert(0);\n\t}\n\treturn nil;\n}\n\nvoid CRunningScript::Init()\n{\n\tstrcpy(m_abScriptName, \"noname\");\n\tnext = prev = nil;\n\tSetIP(0);\n\tfor (int i = 0; i < MAX_STACK_DEPTH; i++)\n\t\tm_anStack[i] = 0;\n\tm_nStackPointer = 0;\n\tm_nWakeTime = 0;\n\tm_bIsActive = false;\n\tm_bCondResult = false;\n\tm_bIsMissionScript = false;\n\tm_bSkipWakeTime = false;\n\tfor (int i = 0; i < NUM_LOCAL_VARS + NUM_TIMERS; i++)\n\t\tm_anLocalVariables[i] = 0;\n\tm_nAndOrState = 0;\n\tm_bNotFlag = false;\n\tm_bDeatharrestEnabled = true;\n\tm_bDeatharrestExecuted = false;\n\tm_bMissionFlag = false;\n}\n\n#ifdef USE_DEBUG_SCRIPT_LOADER\nint scriptToLoad = 0;\nconst char *scriptfile = \"main.scm\";\n\n#ifdef _WIN32\n#include <Windows.h>\n#endif\nint open_script()\n{\n\t// glfwGetKey doesn't work because of CGame::Initialise is blocking\n#ifdef _WIN32\n\tif (GetAsyncKeyState('G') & 0x8000)\n\t\tscriptToLoad = 0;\n\tif (GetAsyncKeyState('R') & 0x8000)\n\t\tscriptToLoad = 1;\n\tif (GetAsyncKeyState('D') & 0x8000)\n\t\tscriptToLoad = 2;\n#endif\n\tswitch (scriptToLoad) {\n\tcase 0: scriptfile = \"main.scm\"; break;\n\tcase 1: scriptfile = \"freeroam_miami.scm\"; break;\n\tcase 2: scriptfile = \"main_d.scm\"; break;\n\t}\n\treturn CFileMgr::OpenFile(scriptfile, \"rb\");\n}\n#endif\n\nvoid CTheScripts::Init()\n{\n\tfor (int i = 0; i < SIZE_SCRIPT_SPACE; i++)\n\t\tScriptSpace[i] = 0;\n\tpActiveScripts = pIdleScripts = nil;\n\tfor (int i = 0; i < MAX_NUM_SCRIPTS; i++){\n\t\tScriptsArray[i].Init();\n\t\tScriptsArray[i].AddScriptToList(&pIdleScripts);\n\t}\n\tMissionCleanUp.Init();\n\tUpsideDownCars.Init();\n\tStuckCars.Init();\n\tCFileMgr::SetDir(\"data\");\n#ifdef USE_DEBUG_SCRIPT_LOADER\n\tint mainf = open_script();\n#else\n\tint mainf = CFileMgr::OpenFile(\"main.scm\", \"rb\");\n#endif\n\tCFileMgr::Read(mainf, (char*)ScriptSpace, SIZE_MAIN_SCRIPT);\n\tCFileMgr::CloseFile(mainf);\n\tCFileMgr::SetDir(\"\");\n\tStoreVehicleIndex = -1;\n\tStoreVehicleWasRandom = true;\n\tOnAMissionFlag = 0;\n\tLastMissionPassedTime = (uint32)-1;\n\tLastRandomPedId = -1;\n\tfor (int i = 0; i < MAX_NUM_USED_OBJECTS; i++){\n\t\tmemset(&UsedObjectArray[i].name, 0, sizeof(UsedObjectArray[i].name));\n\t\tUsedObjectArray[i].index = 0;\n\t}\n\tNumberOfUsedObjects = 0;\n\tReadObjectNamesFromScript();\n\tUpdateObjectIndices();\n\tbAlreadyRunningAMissionScript = false;\n\tbUsingAMultiScriptFile = true;\n\tfor (int i = 0; i < MAX_NUM_MISSION_SCRIPTS; i++)\n\t\tMultiScriptArray[i] = 0;\n\tNumberOfExclusiveMissionScripts = 0;\n\tNumberOfMissionScripts = 0;\n\tLargestMissionScriptSize = 0;\n\tMainScriptSize = 0;\n\tReadMultiScriptFileOffsetsFromScript();\n\tFailCurrentMission = 0;\n\tDbgFlag = false;\n\tNumScriptDebugLines = 0;\n\tRiotIntensity = 0;\n\tbPlayerHasMetDebbieHarry = false;\n\tbPlayerIsInTheStatium = false;\n\tfor (int i = 0; i < MAX_NUM_SCRIPT_SPHERES; i++){\n\t\tScriptSphereArray[i].m_bInUse = false;\n\t\tScriptSphereArray[i].m_Index = 1;\n\t\tScriptSphereArray[i].m_Id = 0;\n\t\tScriptSphereArray[i].m_vecCenter = CVector(0.0f, 0.0f, 0.0f);\n\t\tScriptSphereArray[i].m_fRadius = 0.0f;\n\t}\n\tfor (int i = 0; i < MAX_NUM_INTRO_TEXT_LINES; i++){\n\t\tIntroTextLines[i].Reset();\n\t}\n\tNumberOfIntroTextLinesThisFrame = 0;\n\tUseTextCommands = 0;\n\tfor (int i = 0; i < MAX_NUM_INTRO_RECTANGLES; i++){\n\t\tIntroRectangles[i].m_bIsUsed = false;\n\t\tIntroRectangles[i].m_bBeforeFade = false;\n\t\tIntroRectangles[i].m_nTextureId = -1;\n\t\tIntroRectangles[i].m_sRect = CRect(0.0f, 0.0f, 0.0f, 0.0f);\n\t\tIntroRectangles[i].m_sColor = CRGBA(255, 255, 255, 255);\n\t}\n\tNumberOfIntroRectanglesThisFrame = 0;\n\tRemoveScriptTextureDictionary();\n\tfor (int i = 0; i < MAX_NUM_BUILDING_SWAPS; i++){\n\t\tBuildingSwapArray[i].m_pBuilding = nil;\n\t\tBuildingSwapArray[i].m_nNewModel = -1;\n\t\tBuildingSwapArray[i].m_nOldModel = -1;\n\t}\n\tfor (int i = 0; i < MAX_NUM_INVISIBILITY_SETTINGS; i++)\n\t\tInvisibilitySettingArray[i] = nil;\n\n#if defined USE_ADVANCED_SCRIPT_DEBUG_OUTPUT && SCRIPT_LOG_FILE_LEVEL == 2\n\tCFileMgr::SetDirMyDocuments();\n\tif (dbg_log)\n\t\tfclose(dbg_log);\n\tdbg_log = fopen(\"SCRDBG.LOG\", \"w\");\n\tstatic const char* init_msg = \"Starting debug script log\\n\\n\";\n\tPrintToLog(init_msg);\n\tCFileMgr::SetDir(\"\");\n#endif\n}\n\nvoid CTheScripts::RemoveScriptTextureDictionary()\n{\n\tfor (int i = 0; i < ARRAY_SIZE(CTheScripts::ScriptSprites); i++)\n\t\tCTheScripts::ScriptSprites[i].Delete();\n\tint slot = CTxdStore::FindTxdSlot(\"script\");\n\tif (slot != -1)\n\t\tCTxdStore::RemoveTxd(slot);\n}\n\nvoid CRunningScript::RemoveScriptFromList(CRunningScript** ppScript)\n{\n\tif (prev)\n\t\tprev->next = next;\n\telse\n\t\t*ppScript = next;\n\tif (next)\n\t\tnext->prev = prev;\n}\n\nvoid CRunningScript::AddScriptToList(CRunningScript** ppScript)\n{\n\tnext = *ppScript;\n\tprev = nil;\n\tif (*ppScript)\n\t\t(*ppScript)->prev = this;\n\t*ppScript = this;\n}\n\nCRunningScript* CTheScripts::StartNewScript(uint32 ip)\n{\n\tCRunningScript* pNew = pIdleScripts;\n\tscript_assert(pNew);\n\tpNew->RemoveScriptFromList(&pIdleScripts);\n\tpNew->Init();\n\tpNew->SetIP(ip);\n\tpNew->AddScriptToList(&pActiveScripts);\n\tpNew->m_bIsActive = true;\n\treturn pNew;\n}\n\nvoid CTheScripts::Process()\n{\n\tif (CReplay::IsPlayingBack())\n\t\treturn;\n\tCommandsExecuted = 0;\n\tScriptsUpdated = 0;\n\tfloat timeStep = CTimer::GetTimeStepInMilliseconds();\n\tUpsideDownCars.UpdateTimers();\n\tStuckCars.Process();\n\tMissionCleanUp.CheckIfCollisionHasLoadedForMissionObjects();\n\tDrawScriptSpheres();\n\tif (FailCurrentMission)\n\t\t--FailCurrentMission;\n\tif (UseTextCommands){\n\t\tfor (int i = 0; i < MAX_NUM_INTRO_TEXT_LINES; i++)\n\t\t\tIntroTextLines[i].Reset();\n\t\tNumberOfIntroTextLinesThisFrame = 0;\n\t\tfor (int i = 0; i < MAX_NUM_INTRO_RECTANGLES; i++){\n\t\t\tIntroRectangles[i].m_bIsUsed = false;\n\t\t\tIntroRectangles[i].m_bBeforeFade = false;\n\t\t}\n\t\tNumberOfIntroRectanglesThisFrame = 0;\n\t\tif (UseTextCommands == 1)\n\t\t\tUseTextCommands = 0;\n\t}\n\n#ifdef MISSION_REPLAY\n\tstatic uint32 TimeToWaitTill;\n\tswitch (AllowMissionReplay) {\n\tcase 2:\n\t\tAllowMissionReplay = 3;\n\t\tTimeToWaitTill = CTimer::GetTimeInMilliseconds() + (AddExtraDeathDelay() > 1000 ? 4000 : 2500);\n\t\tbreak;\n\tcase 3:\n\t\tif (TimeToWaitTill < CTimer::GetTimeInMilliseconds())\n\t\t\tAllowMissionReplay = 4;\n\t\tbreak;\n\tcase 4:\n\t\tAllowMissionReplay = 5;\n\t\tRetryMission(0, 0);\n\t\tbreak;\n\tcase 6:\n\t\tAllowMissionReplay = 7;\n\t\tTimeToWaitTill = CTimer::GetTimeInMilliseconds() + 500;\n\t\tbreak;\n\tcase 7:\n\t\tif (TimeToWaitTill < CTimer::GetTimeInMilliseconds()) {\n\t\t\tAllowMissionReplay = 0;\n\t\t\treturn;\n\t\t}\n\t\tbreak;\n\t}\n\tif (WaitForMissionActivate) {\n\t\tif (WaitForMissionActivate > CTimer::GetTimeInMilliseconds())\n\t\t\treturn;\n\t\tWaitForMissionActivate = 0;\n\t\tWaitForSave = CTimer::GetTimeInMilliseconds() + 3000;\n\t}\n\tif (WaitForSave && WaitForSave > CTimer::GetTimeInMilliseconds())\n\t\tWaitForSave = 0;\n#endif\n\n#ifdef USE_ADVANCED_SCRIPT_DEBUG_OUTPUT\n#if SCRIPT_LOG_FILE_LEVEL == 1\n\tCFileMgr::SetDirMyDocuments();\n\tdbg_log = fopen(\"SCRDBG.LOG\", \"w\");\n\tstatic const char* init_msg = \"Starting debug script log\\n\\n\";\n\tPrintToLog(init_msg);\n\tCFileMgr::SetDir(\"\");\n#endif\n\tPrintToLog(\"------------------------\\n\");\n\tPrintToLog(\"CTheScripts::Process started, CTimer::GetTimeInMilliseconds == %u\\n\", CTimer::GetTimeInMilliseconds());\n#endif\n\n\tCRunningScript* script = pActiveScripts;\n\twhile (script != nil){\n\t\tCRunningScript* next = script->GetNext();\n\t\t++ScriptsUpdated;\n\t\tscript->UpdateTimers(timeStep);\n\t\tscript->Process();\n\t\tscript = next;\n\t\tif (script && !script->m_bIsActive)\n\t\t\tscript = nil;\n\t}\n\tDbgFlag = false;\n#ifdef USE_ADVANCED_SCRIPT_DEBUG_OUTPUT\n\tPrintToLog(\"Script processing done, ScriptsUpdated: %d, CommandsExecuted: %d\\n\", ScriptsUpdated, CommandsExecuted);\n#if SCRIPT_LOG_FILE_LEVEL == 1\n\tfclose(dbg_log);\n\tdbg_log = nil;\n#endif\n#endif\n}\n\nCRunningScript* CTheScripts::StartTestScript()\n{\n\treturn StartNewScript(0);\n}\n\nbool CTheScripts::IsPlayerOnAMission()\n{\n\treturn OnAMissionFlag && *(int32*)&ScriptSpace[OnAMissionFlag] == 1;\n}\n\nvoid CRunningScript::Process()\n{\n#ifdef USE_ADVANCED_SCRIPT_DEBUG_OUTPUT\n\tPrintToLog(\"\\n\\nProcessing script %s (id %d)\\n\\n\", m_abScriptName, this - CTheScripts::ScriptsArray);\n#endif\n\tif (m_bIsMissionScript)\n\t\tDoDeatharrestCheck();\n\tif (m_bMissionFlag && CTheScripts::FailCurrentMission == 1 && m_nStackPointer == 1)\n\t\tSetIP(m_anStack[--m_nStackPointer]);\n\tif (CTimer::GetTimeInMilliseconds() >= m_nWakeTime){\n\t\twhile (!ProcessOneCommand())\n\t\t\t;\n\t\treturn;\n\t}\n\tif (!m_bSkipWakeTime)\n\t\treturn;\n\tif (!CPad::GetPad(0)->GetCrossJustDown())\n\t\treturn;\n\tm_nWakeTime = 0;\n\tfor (int i = 0; i < NUMBIGMESSAGES; i++){\n\t\tif (CMessages::BIGMessages[i].m_Stack[0].m_pText != nil)\n\t\t\tCMessages::BIGMessages[i].m_Stack[0].m_nStartTime = 0;\n\t}\n\tif (CMessages::BriefMessages[0].m_pText != nil)\n\t\tCMessages::BriefMessages[0].m_nStartTime = 0;\n}\n\nint8 CRunningScript::ProcessOneCommand()\n{\n\tint8 retval = -1;\n\t++CTheScripts::CommandsExecuted;\n\tint32 command = (uint16)CTheScripts::Read2BytesFromScript(&m_nIp);\n\tm_bNotFlag = (command & 0x8000);\n\tcommand &= 0x7FFF;\n#ifdef USE_ADVANCED_SCRIPT_DEBUG_OUTPUT\n\tchar commandInfo[1024];\n\tuint32 ip = m_nIp;\n\tif (command < ARRAY_SIZE(commands)) {\n\t\tscript_assert(commands[command].id == command);\n\t\tm_nIp -= 2;\n\t\tsprintf(commandInfo, m_nIp >= SIZE_MAIN_SCRIPT ? \"M<%5d> \" : \"<%6d> \", m_nIp >= SIZE_MAIN_SCRIPT ? m_nIp - SIZE_MAIN_SCRIPT : m_nIp);\n\t\tm_nIp += 2;\n\t\tif (m_bNotFlag)\n\t\t\tstrcat(commandInfo, \"NOT \");\n\t\tif (commands[command].position == -1)\n\t\t\tstrcat(commandInfo, commands[command].name + sizeof(\"COMMAND_\") - 1);\n\t\tfor (int i = 0; commands[command].input[i] != ARGTYPE_NONE; i++) {\n\t\t\tchar tmp[32];\n\t\t\tbool var = false;\n\t\t\tint value;\n\t\t\tswitch (commands[command].input[i]) {\n\t\t\tcase ARGTYPE_INT:\n\t\t\tcase ARGTYPE_PED_HANDLE:\n\t\t\tcase ARGTYPE_VEHICLE_HANDLE: \n\t\t\tcase ARGTYPE_OBJECT_HANDLE: value = CollectParameterForDebug(commandInfo, var); sprintf(tmp, var ? \" (%d)\" : \" %d\", value); break;\n\t\t\tcase ARGTYPE_FLOAT: value = CollectParameterForDebug(commandInfo, var); sprintf(tmp, var ? \" (%.3f)\" : \" %.3f\", *(float*)&value); break;\n\t\t\tcase ARGTYPE_STRING: sprintf(tmp, \" '%s'\", (const char*)&CTheScripts::ScriptSpace[m_nIp]); m_nIp += KEY_LENGTH_IN_SCRIPT; break;\n\t\t\tcase ARGTYPE_LABEL: value = CollectParameterForDebug(commandInfo, var); sprintf(tmp, var ? \" (%s(%d))\" : \" %s(%d)\", value >= 0 ? \"G\" : \"L\", abs(value)); break;\n\t\t\tcase ARGTYPE_BOOL: value = CollectParameterForDebug(commandInfo, var); sprintf(tmp, var ? \" (%s)\" : \" %s\", value ? \"TRUE\" : \"FALSE\"); break;\n\t\t\tcase ARGTYPE_ANDOR: value = CollectParameterForDebug(commandInfo, var); sprintf(tmp, \" %d %ss\", (value + 1) % 10, value / 10 == 0 ? \"AND\" : \"OR\"); break;\n\t\t\tdefault: script_assert(0);\n\t\t\t}\n\t\t\tstrcat(commandInfo, tmp);\n\t\t\tif (commands[command].position == i)\n\t\t\t\tstrcat(commandInfo, commands[command].name_override);\n\t\t}\n\t\tuint32 t = m_nIp;\n\t\tm_nIp = ip;\n\t\tip = t;\n\t}\n#endif\n\tif (command < 100)\n\t\tretval = ProcessCommands0To99(command);\n\telse if (command < 200)\n\t\tretval = ProcessCommands100To199(command);\n\telse if (command < 300)\n\t\tretval = ProcessCommands200To299(command);\n\telse if (command < 400)\n\t\tretval = ProcessCommands300To399(command);\n\telse if (command < 500)\n\t\tretval = ProcessCommands400To499(command);\n\telse if (command < 600)\n\t\tretval = ProcessCommands500To599(command);\n\telse if (command < 700)\n\t\tretval = ProcessCommands600To699(command);\n\telse if (command < 800)\n\t\tretval = ProcessCommands700To799(command);\n\telse if (command < 900)\n\t\tretval = ProcessCommands800To899(command);\n\telse if (command < 1000)\n\t\tretval = ProcessCommands900To999(command);\n\telse if (command < 1100)\n\t\tretval = ProcessCommands1000To1099(command);\n\telse if (command < 1200)\n\t\tretval = ProcessCommands1100To1199(command);\n\telse if (command < 1300)\n\t\tretval = ProcessCommands1200To1299(command);\n\telse if (command < 1400)\n\t\tretval = ProcessCommands1300To1399(command);\n\telse if (command < 1500)\n\t\tretval = ProcessCommands1400To1499(command);\n#ifdef USE_ADVANCED_SCRIPT_DEBUG_OUTPUT\n\tif (command < ARRAY_SIZE(commands)) {\n\t\tif (commands[command].cond || commands[command].output[0] != ARGTYPE_NONE) {\n\t\t\tstrcat(commandInfo, \" ->\");\n\t\t\tif (commands[command].cond)\n\t\t\t\tstrcat(commandInfo, m_bCondResult ? \" TRUE\" : \" FALSE\");\n\t\t\tuint32 t = m_nIp;\n\t\t\tm_nIp = ip;\n\t\t\tip = t;\n\t\t\tfor (int i = 0; commands[command].output[i] != ARGTYPE_NONE; i++) {\n\t\t\t\tchar tmp[32];\n\t\t\t\tswitch (commands[command].output[i]) {\n\t\t\t\tcase ARGTYPE_INT:\n\t\t\t\tcase ARGTYPE_PED_HANDLE:\n\t\t\t\tcase ARGTYPE_VEHICLE_HANDLE:\n\t\t\t\tcase ARGTYPE_OBJECT_HANDLE: GetStoredParameterForDebug(commandInfo); sprintf(tmp, \" (%d)\", ScriptParams[i]); strcat(commandInfo, tmp); break;\n\t\t\t\tcase ARGTYPE_FLOAT: GetStoredParameterForDebug(commandInfo); sprintf(tmp, \" (%8.3f)\", *(float*)&ScriptParams[i]); strcat(commandInfo, tmp); break;\n\t\t\t\tdefault: script_assert(0 && \"Script only returns INTs and FLOATs\");\n\t\t\t\t}\n\t\t\t}\n\t\t\tm_nIp = ip;\n\t\t}\n\t\tPrintToLog(\"%s\\n\", commandInfo);\n\t\tif (m_bMissionFlag) {\n\t\t\tfor (int i = 0; commandInfo[i]; i++) {\n\t\t\t\tif (commandInfo[i] == '_')\n\t\t\t\t\tcommandInfo[i] = ' ';\n\t\t\t}\n\t\t\tCDebug::DebugAddText(commandInfo);\n\t\t}\n\t}\n#elif defined USE_BASIC_SCRIPT_DEBUG_OUTPUT\n\tif (m_bMissionFlag) {\n\t\tchar tmp[128];\n\t\tsprintf(tmp, \"Comm %d Cmp %d\", command, m_bCondResult);\n\t\tCDebug::DebugAddText(tmp);\n\t}\n#endif\n\treturn retval;\n}\n\nint8 CRunningScript::ProcessCommands0To99(int32 command)\n{\n\tfloat *fScriptVar1;\n\tint *nScriptVar1;\n\tswitch (command) {\n\tcase COMMAND_NOP:\n\t\treturn 0;\n\tcase COMMAND_WAIT:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tm_nWakeTime = CTimer::GetTimeInMilliseconds() + ScriptParams[0];\n\t\tm_bSkipWakeTime = false;\n\t\treturn 1;\n\tcase COMMAND_GOTO:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tSetIP(ScriptParams[0] >= 0 ? ScriptParams[0] : SIZE_MAIN_SCRIPT - ScriptParams[0]);\n\t\t/* Known issue: GOTO to 0. It might have been \"better\" to use > instead of >= */\n\t\t/* simply because it never makes sense to jump to start of the script */\n\t\t/* but jumping to start of a custom mission is an issue for simple mission-like scripts */\n\t\t/* However, it's not an issue for actual mission scripts, because they follow a structure */\n\t\t/* and never start with a loop. */\n\t\treturn 0;\n\tcase COMMAND_SHAKE_CAM:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCamShakeNoPos(&TheCamera, ScriptParams[0] / 1000.0f);\n\t\treturn 0;\n\tcase COMMAND_SET_VAR_INT:\n\t{\n\t\tint32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\tCollectParameters(&m_nIp, 1);\n\t\t*ptr = ScriptParams[0];\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_VAR_FLOAT:\n\t{\n\t\tint32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\tCollectParameters(&m_nIp, 1);\n\t\t*(float*)ptr = *(float*)&ScriptParams[0];\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_LVAR_INT:\n\t{\n\t\tint32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\tCollectParameters(&m_nIp, 1);\n\t\t*ptr = ScriptParams[0];\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_LVAR_FLOAT:\n\t{\n\t\tint32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\tCollectParameters(&m_nIp, 1);\n\t\t*(float*)ptr = *(float*)&ScriptParams[0];\n\t\treturn 0;\n\t}\n\tcase COMMAND_ADD_VAL_TO_INT_VAR:\n\t{\n\t\tint32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\tCollectParameters(&m_nIp, 1);\n\t\t*ptr += ScriptParams[0];\n\t\treturn 0;\n\t}\n\tcase COMMAND_ADD_VAL_TO_FLOAT_VAR:\n\t{\n\t\tint32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\tCollectParameters(&m_nIp, 1);\n\t\t*(float*)ptr += *(float*)&ScriptParams[0];\n\t\treturn 0;\n\t}\n\tcase COMMAND_ADD_VAL_TO_INT_LVAR:\n\t{\n\t\tint32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\tCollectParameters(&m_nIp, 1);\n\t\t*ptr += ScriptParams[0];\n\t\treturn 0;\n\t}\n\tcase COMMAND_ADD_VAL_TO_FLOAT_LVAR:\n\t{\n\t\tint32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\tCollectParameters(&m_nIp, 1);\n\t\t*(float*)ptr += *(float*)&ScriptParams[0];\n\t\treturn 0;\n\t}\n\tcase COMMAND_SUB_VAL_FROM_INT_VAR:\n\t{\n\t\tint32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\tCollectParameters(&m_nIp, 1);\n\t\t*ptr -= ScriptParams[0];\n\t\treturn 0;\n\t}\n\tcase COMMAND_SUB_VAL_FROM_FLOAT_VAR:\n\t{\n\t\tint32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\tCollectParameters(&m_nIp, 1);\n\t\t*(float*)ptr -= *(float*)&ScriptParams[0];\n\t\treturn 0;\n\t}\n\tcase COMMAND_SUB_VAL_FROM_INT_LVAR:\n\t{\n\t\tint32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\tCollectParameters(&m_nIp, 1);\n\t\t*ptr -= ScriptParams[0];\n\t\treturn 0;\n\t}\n\tcase COMMAND_SUB_VAL_FROM_FLOAT_LVAR:\n\t{\n\t\tint32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\tCollectParameters(&m_nIp, 1);\n\t\t*(float*)ptr -= *(float*)&ScriptParams[0];\n\t\treturn 0;\n\t}\n\tcase COMMAND_MULT_INT_VAR_BY_VAL:\n\t{\n\t\tint32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\tCollectParameters(&m_nIp, 1);\n\t\t*ptr *= ScriptParams[0];\n\t\treturn 0;\n\t}\n\tcase COMMAND_MULT_FLOAT_VAR_BY_VAL:\n\t{\n\t\tint32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\tCollectParameters(&m_nIp, 1);\n\t\t*(float*)ptr *= *(float*)&ScriptParams[0];\n\t\treturn 0;\n\t}\n\tcase COMMAND_MULT_INT_LVAR_BY_VAL:\n\t{\n\t\tint32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\tCollectParameters(&m_nIp, 1);\n\t\t*ptr *= ScriptParams[0];\n\t\treturn 0;\n\t}\n\tcase COMMAND_MULT_FLOAT_LVAR_BY_VAL:\n\t{\n\t\tint32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\tCollectParameters(&m_nIp, 1);\n\t\t*(float*)ptr *= *(float*)&ScriptParams[0];\n\t\treturn 0;\n\t}\n\tcase COMMAND_DIV_INT_VAR_BY_VAL:\n\t{\n\t\tint32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\tCollectParameters(&m_nIp, 1);\n\t\t*ptr /= ScriptParams[0];\n\t\treturn 0;\n\t}\n\tcase COMMAND_DIV_FLOAT_VAR_BY_VAL:\n\t{\n\t\tint32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\tCollectParameters(&m_nIp, 1);\n\t\t*(float*)ptr /= *(float*)&ScriptParams[0];\n\t\treturn 0;\n\t}\n\tcase COMMAND_DIV_INT_LVAR_BY_VAL:\n\t{\n\t\tint32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\tCollectParameters(&m_nIp, 1);\n\t\t*ptr /= ScriptParams[0];\n\t\treturn 0;\n\t}\n\tcase COMMAND_DIV_FLOAT_LVAR_BY_VAL:\n\t{\n\t\tint32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\tCollectParameters(&m_nIp, 1);\n\t\t*(float*)ptr /= *(float*)&ScriptParams[0];\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_INT_VAR_GREATER_THAN_NUMBER:\n\t{\n\t\tint32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\tCollectParameters(&m_nIp, 1);\n\t\tUpdateCompareFlag(*ptr > ScriptParams[0]);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_INT_LVAR_GREATER_THAN_NUMBER:\n\t{\n\t\tint32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\tCollectParameters(&m_nIp, 1);\n\t\tUpdateCompareFlag(*ptr > ScriptParams[0]);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_NUMBER_GREATER_THAN_INT_VAR:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tint32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\tUpdateCompareFlag(ScriptParams[0] > *ptr);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_NUMBER_GREATER_THAN_INT_LVAR:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tint32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\tUpdateCompareFlag(ScriptParams[0] > *ptr);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_INT_VAR_GREATER_THAN_INT_VAR:\n\t{\n\t\tint32* ptr1 = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\tint32* ptr2 = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\tUpdateCompareFlag(*ptr1 > *ptr2);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_INT_LVAR_GREATER_THAN_INT_VAR:\n\t{\n\t\tint32* ptr1 = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\tint32* ptr2 = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\tUpdateCompareFlag(*ptr1 > *ptr2);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_INT_VAR_GREATER_THAN_INT_LVAR:\n\t{\n\t\tint32* ptr1 = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\tint32* ptr2 = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\tUpdateCompareFlag(*ptr1 > *ptr2);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_INT_LVAR_GREATER_THAN_INT_LVAR:\n\t{\n\t\tint32* ptr1 = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\tint32* ptr2 = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\tUpdateCompareFlag(*ptr1 > *ptr2);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_FLOAT_VAR_GREATER_THAN_NUMBER:\n\t{\n\t\tint32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\tCollectParameters(&m_nIp, 1);\n\t\tUpdateCompareFlag(*(float*)ptr > *(float*)&ScriptParams[0]);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_FLOAT_LVAR_GREATER_THAN_NUMBER:\n\t{\n\t\tint32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\tCollectParameters(&m_nIp, 1);\n\t\tUpdateCompareFlag(*(float*)ptr > *(float*)&ScriptParams[0]);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_NUMBER_GREATER_THAN_FLOAT_VAR:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tint32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\tUpdateCompareFlag(*(float*)&ScriptParams[0] > *(float*)ptr);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_NUMBER_GREATER_THAN_FLOAT_LVAR:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tint32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\tUpdateCompareFlag(*(float*)&ScriptParams[0] > *(float*)ptr);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_FLOAT_VAR_GREATER_THAN_FLOAT_VAR:\n\t{\n\t\tint32* ptr1 = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\tint32* ptr2 = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\tUpdateCompareFlag(*(float*)ptr1 > *(float*)ptr2);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_FLOAT_LVAR_GREATER_THAN_FLOAT_VAR:\n\t{\n\t\tint32* ptr1 = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\tint32* ptr2 = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\tUpdateCompareFlag(*(float*)ptr1 > *(float*)ptr2);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_FLOAT_VAR_GREATER_THAN_FLOAT_LVAR:\n\t{\n\t\tint32* ptr1 = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\tint32* ptr2 = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\tUpdateCompareFlag(*(float*)ptr1 > *(float*)ptr2);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_FLOAT_LVAR_GREATER_THAN_FLOAT_LVAR:\n\t{\n\t\tint32* ptr1 = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\tint32* ptr2 = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\tUpdateCompareFlag(*(float*)ptr1 > *(float*)ptr2);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_INT_VAR_GREATER_OR_EQUAL_TO_NUMBER:\n\t{\n\t\tint32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\tCollectParameters(&m_nIp, 1);\n\t\tUpdateCompareFlag(*ptr >= ScriptParams[0]);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_INT_LVAR_GREATER_OR_EQUAL_TO_NUMBER:\n\t{\n\t\tint32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\tCollectParameters(&m_nIp, 1);\n\t\tUpdateCompareFlag(*ptr >= ScriptParams[0]);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_NUMBER_GREATER_OR_EQUAL_TO_INT_VAR:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tint32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\tUpdateCompareFlag(ScriptParams[0] >= *ptr);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_NUMBER_GREATER_OR_EQUAL_TO_INT_LVAR:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tint32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\tUpdateCompareFlag(ScriptParams[0] >= *ptr);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_INT_VAR_GREATER_OR_EQUAL_TO_INT_VAR:\n\t{\n\t\tint32* ptr1 = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\tint32* ptr2 = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\tUpdateCompareFlag(*ptr1 >= *ptr2);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_INT_LVAR_GREATER_OR_EQUAL_TO_INT_VAR:\n\t{\n\t\tint32* ptr1 = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\tint32* ptr2 = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\tUpdateCompareFlag(*ptr1 >= *ptr2);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_INT_VAR_GREATER_OR_EQUAL_TO_INT_LVAR:\n\t{\n\t\tint32* ptr1 = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\tint32* ptr2 = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\tUpdateCompareFlag(*ptr1 >= *ptr2);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_INT_LVAR_GREATER_OR_EQUAL_TO_INT_LVAR:\n\t{\n\t\tint32* ptr1 = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\tint32* ptr2 = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\tUpdateCompareFlag(*ptr1 >= *ptr2);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_FLOAT_VAR_GREATER_OR_EQUAL_TO_NUMBER:\n\t{\n\t\tint32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\tCollectParameters(&m_nIp, 1);\n\t\tUpdateCompareFlag(*(float*)ptr >= *(float*)&ScriptParams[0]);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_FLOAT_LVAR_GREATER_OR_EQUAL_TO_NUMBER:\n\t{\n\t\tint32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\tCollectParameters(&m_nIp, 1);\n\t\tUpdateCompareFlag(*(float*)ptr >= *(float*)&ScriptParams[0]);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_NUMBER_GREATER_OR_EQUAL_TO_FLOAT_VAR:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tint32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\tUpdateCompareFlag(*(float*)&ScriptParams[0] >= *(float*)ptr);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_NUMBER_GREATER_OR_EQUAL_TO_FLOAT_LVAR:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tint32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\tUpdateCompareFlag(*(float*)&ScriptParams[0] >= *(float*)ptr);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_FLOAT_VAR_GREATER_OR_EQUAL_TO_FLOAT_VAR:\n\t{\n\t\tint32* ptr1 = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\tint32* ptr2 = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\tUpdateCompareFlag(*(float*)ptr1 >= *(float*)ptr2);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_FLOAT_LVAR_GREATER_OR_EQUAL_TO_FLOAT_VAR:\n\t{\n\t\tint32* ptr1 = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\tint32* ptr2 = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\tUpdateCompareFlag(*(float*)ptr1 >= *(float*)ptr2);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_FLOAT_VAR_GREATER_OR_EQUAL_TO_FLOAT_LVAR:\n\t{\n\t\tint32* ptr1 = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\tint32* ptr2 = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\tUpdateCompareFlag(*(float*)ptr1 >= *(float*)ptr2);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_FLOAT_LVAR_GREATER_OR_EQUAL_TO_FLOAT_LVAR:\n\t{\n\t\tint32* ptr1 = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\tint32* ptr2 = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\tUpdateCompareFlag(*(float*)ptr1 >= *(float*)ptr2);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_INT_VAR_EQUAL_TO_NUMBER:\n\t{\n\t\tint32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\tCollectParameters(&m_nIp, 1);\n\t\tUpdateCompareFlag(*ptr == ScriptParams[0]);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_INT_LVAR_EQUAL_TO_NUMBER:\n\t{\n\t\tint32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\tCollectParameters(&m_nIp, 1);\n\t\tUpdateCompareFlag(*ptr == ScriptParams[0]);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_INT_VAR_EQUAL_TO_INT_VAR:\n\t{\n\t\tint32* ptr1 = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\tint32* ptr2 = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\tUpdateCompareFlag(*ptr1 == *ptr2);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_INT_VAR_EQUAL_TO_INT_LVAR:\n\t{\n\t\tint32* ptr1 = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\tint32* ptr2 = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\tUpdateCompareFlag(*ptr1 == *ptr2);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_INT_LVAR_EQUAL_TO_INT_LVAR:\n\t{\n\t\tint32* ptr1 = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\tint32* ptr2 = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\tUpdateCompareFlag(*ptr1 == *ptr2);\n\t\treturn 0;\n\t}\n\t//case COMMAND_IS_INT_VAR_NOT_EQUAL_TO_NUMBER:\n\t//case COMMAND_IS_INT_LVAR_NOT_EQUAL_TO_NUMBER:\n\t//case COMMAND_IS_INT_VAR_NOT_EQUAL_TO_INT_VAR:\n\t//case COMMAND_IS_INT_LVAR_NOT_EQUAL_TO_INT_LVAR:\n\t//case COMMAND_IS_INT_VAR_NOT_EQUAL_TO_INT_LVAR:\n\tcase COMMAND_IS_FLOAT_VAR_EQUAL_TO_NUMBER:\n\t{\n\t\tint32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\tCollectParameters(&m_nIp, 1);\n\t\tUpdateCompareFlag(*(float*)ptr == *(float*)&ScriptParams[0]);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_FLOAT_LVAR_EQUAL_TO_NUMBER:\n\t{\n\t\tint32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\tCollectParameters(&m_nIp, 1);\n\t\tUpdateCompareFlag(*(float*)ptr == *(float*)&ScriptParams[0]);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_FLOAT_VAR_EQUAL_TO_FLOAT_VAR:\n\t{\n\t\tint32* ptr1 = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\tint32* ptr2 = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\tUpdateCompareFlag(*(float*)ptr1 == *(float*)ptr2);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_FLOAT_VAR_EQUAL_TO_FLOAT_LVAR:\n\t{\n\t\tint32* ptr1 = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\tint32* ptr2 = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\tUpdateCompareFlag(*(float*)ptr1 == *(float*)ptr2);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_FLOAT_LVAR_EQUAL_TO_FLOAT_LVAR:\n\t{\n\t\tint32* ptr1 = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\tint32* ptr2 = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\tUpdateCompareFlag(*(float*)ptr1 == *(float*)ptr2);\n\t\treturn 0;\n\t}\n\t//case COMMAND_IS_FLOAT_VAR_NOT_EQUAL_TO_NUMBER:\n\t//case COMMAND_IS_FLOAT_LVAR_NOT_EQUAL_TO_NUMBER:\n\t//case COMMAND_IS_FLOAT_VAR_NOT_EQUAL_TO_FLOAT_VAR:\n\t//case COMMAND_IS_FLOAT_LVAR_NOT_EQUAL_TO_FLOAT_LVAR:\n\t//case COMMAND_IS_FLOAT_VAR_NOT_EQUAL_TO_FLOAT_LVAR:\n\t/*\n\tcase COMMAND_GOTO_IF_TRUE:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tif (m_bCondResult)\n\t\t\tSetIP(ScriptParams[0] >= 0 ? ScriptParams[0] : SIZE_MAIN_SCRIPT - ScriptParams[0]);\n\t\treturn 0;\n\t*/\n\tcase COMMAND_GOTO_IF_FALSE:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tif (!m_bCondResult)\n\t\t\tSetIP(ScriptParams[0] >= 0 ? ScriptParams[0] : SIZE_MAIN_SCRIPT - ScriptParams[0]);\n\t\t/* Check COMMAND_GOTO note. */\n\t\treturn 0;\n\tcase COMMAND_TERMINATE_THIS_SCRIPT:\n\t\tif (m_bMissionFlag)\n\t\t\tCTheScripts::bAlreadyRunningAMissionScript = false;\n\t\tRemoveScriptFromList(&CTheScripts::pActiveScripts);\n\t\tAddScriptToList(&CTheScripts::pIdleScripts);\n\t\tm_bIsActive = false;\n#ifdef MISSION_REPLAY\n\t\tif (m_bMissionFlag) {\n\t\t\tCPlayerInfo* pPlayerInfo = &CWorld::Players[CWorld::PlayerInFocus];\n#if 0 // makeing autosave is pointless and is a bit buggy\n\t\t\tif (pPlayerInfo->m_pPed->GetPedState() != PED_DEAD && pPlayerInfo->m_WBState == WBSTATE_PLAYING && !m_bDeatharrestExecuted)\n\t\t\t\tSaveGameForPause(1);\n#endif\n\t\t\toldTargetX = oldTargetY = 0.0f;\n\t\t\tif (AllowMissionReplay == 1)\n\t\t\t\tAllowMissionReplay = 2;\n\t\t\t// I am fairly sure they forgot to set return value here\n\t\t}\n#endif\n\t\treturn 1;\n\tcase COMMAND_START_NEW_SCRIPT:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tscript_assert(ScriptParams[0] >= 0);\n\t\tCRunningScript* pNew = CTheScripts::StartNewScript(ScriptParams[0]);\n\t\tpNew->m_bIsActive = true;\n\t\tint8 type = CTheScripts::Read1ByteFromScript(&m_nIp);\n\t\tfloat tmp;\n\t\tfor (int i = 0; type != ARGUMENT_END; type = CTheScripts::Read1ByteFromScript(&m_nIp), i++) {\n\t\t\tswitch (type) {\n\t\t\tcase ARGUMENT_INT32:\n\t\t\t\tpNew->m_anLocalVariables[i] = CTheScripts::Read4BytesFromScript(&m_nIp);\n\t\t\t\tbreak;\n\t\t\tcase ARGUMENT_GLOBALVAR:\n\t\t\t\tpNew->m_anLocalVariables[i] = *(int32*)&CTheScripts::ScriptSpace[(uint16)CTheScripts::Read2BytesFromScript(&m_nIp)];\n\t\t\t\tbreak;\n\t\t\tcase ARGUMENT_LOCALVAR:\n\t\t\t\tpNew->m_anLocalVariables[i] = m_anLocalVariables[CTheScripts::Read2BytesFromScript(&m_nIp)];\n\t\t\t\tbreak;\n\t\t\tcase ARGUMENT_INT8:\n\t\t\t\tpNew->m_anLocalVariables[i] = CTheScripts::Read1ByteFromScript(&m_nIp);\n\t\t\t\tbreak;\n\t\t\tcase ARGUMENT_INT16:\n\t\t\t\tpNew->m_anLocalVariables[i] = CTheScripts::Read2BytesFromScript(&m_nIp);\n\t\t\t\tbreak;\n\t\t\tcase ARGUMENT_FLOAT:\n\t\t\t\ttmp = CTheScripts::ReadFloatFromScript(&m_nIp);\n\t\t\t\tpNew->m_anLocalVariables[i] = *(int32*)&tmp;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\treturn 0;\n\t}\n\tcase COMMAND_GOSUB:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tscript_assert(m_nStackPointer < MAX_STACK_DEPTH);\n\t\tm_anStack[m_nStackPointer++] = m_nIp;\n\t\tSetIP(ScriptParams[0] >= 0 ? ScriptParams[0] : SIZE_MAIN_SCRIPT - ScriptParams[0]);\n\t\treturn 0;\n\tcase COMMAND_RETURN:\n\t\tscript_assert(m_nStackPointer > 0); /* No more SSU */\n\t\tSetIP(m_anStack[--m_nStackPointer]);\n\t\treturn 0;\n\tcase COMMAND_LINE:\n\t\tCollectParameters(&m_nIp, 6);\n\t\t/* Something must have been here */\n\t\treturn 0;\n\tcase COMMAND_CREATE_PLAYER:\n\t{\n\t\tCollectParameters(&m_nIp, 4);\n\t\tint32 index = ScriptParams[0];\n\t\tscript_assert(index < NUMPLAYERS);\n\t\tprintf(\"&&&&&&&&&&&&&Creating player: %d\\n\", index);\n\t\tif (!CStreaming::HasModelLoaded(MI_PLAYER)) {\n\t\t\tCStreaming::RequestSpecialModel(MI_PLAYER, \"player\", STREAMFLAGS_DONT_REMOVE | STREAMFLAGS_DEPENDENCY);\n\t\t\tCStreaming::LoadAllRequestedModels(false);\n\t\t}\n\t\tCPlayerPed::SetupPlayerPed(index);\n\t\tCWorld::Players[index].m_pPed->CharCreatedBy = MISSION_CHAR;\n\t\tCPlayerPed::DeactivatePlayerPed(index);\n\t\tCVector pos = *(CVector*)&ScriptParams[1];\n\t\tif (pos.z <= MAP_Z_LOW_LIMIT)\n\t\t\tpos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);\n\t\tpos.z += CWorld::Players[index].m_pPed->GetDistanceFromCentreOfMassToBaseOfModel();\n\t\tCWorld::Players[index].m_pPed->SetPosition(pos);\n\t\tCTheScripts::ClearSpaceForMissionEntity(pos, CWorld::Players[index].m_pPed);\n\t\tCPlayerPed::ReactivatePlayerPed(index);\n\t\tScriptParams[0] = index;\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\tcase COMMAND_GET_PLAYER_COORDINATES:\n\t{\n\t\tCVector pos;\n\t\tCollectParameters(&m_nIp, 1);\n\t\tif (CWorld::Players[ScriptParams[0]].m_pPed->bInVehicle)\n\t\t\tpos = CWorld::Players[ScriptParams[0]].m_pPed->m_pMyVehicle->GetPosition();\n\t\telse\n\t\t\tpos = CWorld::Players[ScriptParams[0]].m_pPed->GetPosition();\n\t\t*(CVector*)&ScriptParams[0] = pos;\n\t\tStoreParameters(&m_nIp, 3);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_PLAYER_COORDINATES:\n\t{\n\t\tCollectParameters(&m_nIp, 4);\n\t\tCVector pos = *(CVector*)&ScriptParams[1];\n\t\tint index = ScriptParams[0];\n\t\tif (pos.z <= MAP_Z_LOW_LIMIT)\n\t\t\tpos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);\n\t\tCPlayerPed* ped = CWorld::Players[index].m_pPed;\n\t\tif (ped->bInVehicle) {\n\t\t\tpos.z += ped->m_pMyVehicle->GetDistanceFromCentreOfMassToBaseOfModel();\n\t\t\tped->m_pMyVehicle->Teleport(pos); // removed dumb stuff that was present here\n\t\t\tCTheScripts::ClearSpaceForMissionEntity(pos, ped->m_pMyVehicle);\n\t\t\treturn 0;\n\t\t}\n\t\tpos.z += ped->GetDistanceFromCentreOfMassToBaseOfModel();\n\t\tCVector vOldPos = ped->GetPosition();\n\t\tped->Teleport(pos);\n\t\tCTheScripts::ClearSpaceForMissionEntity(pos, ped);\n\t\tif (ped) { // great time to check\n\t\t\tfor (int i = 0; i < ped->m_numNearPeds; i++) {\n\t\t\t\tCPed* pTestedPed = ped->m_nearPeds[i];\n\t\t\t\tif (!pTestedPed || !IsPedPointerValid(pTestedPed))\n\t\t\t\t\tcontinue;\n\t\t\t\tif (pTestedPed->m_pedInObjective == ped && pTestedPed->m_objective == OBJECTIVE_FOLLOW_CHAR_IN_FORMATION) {\n\t\t\t\t\tCVector vFollowerPos = pTestedPed->GetFormationPosition();\n\t\t\t\t\tCTheScripts::ClearSpaceForMissionEntity(vFollowerPos, ped);\n\t\t\t\t\tbool bFound = false;\n\t\t\t\t\tvFollowerPos.z = CWorld::FindGroundZFor3DCoord(vFollowerPos.x, vFollowerPos.y, vFollowerPos.z + 1.0f, &bFound) + 1.0f;\n\t\t\t\t\tif (bFound) {\n\t\t\t\t\t\tif (CWorld::GetIsLineOfSightClear(vFollowerPos, ped->GetPosition(), true, false, false, true, false, false)) {\n\t\t\t\t\t\t\tpTestedPed->Teleport(vFollowerPos);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if (pTestedPed->m_leader == ped) {\n\t\t\t\t\tCVector vFollowerPos;\n\t\t\t\t\tif (pTestedPed->m_pedFormation)\n\t\t\t\t\t\tvFollowerPos = pTestedPed->GetFormationPosition();\n\t\t\t\t\telse\n\t\t\t\t\t\tvFollowerPos = ped->GetPosition() + pTestedPed->GetPosition() - vOldPos;\n\t\t\t\t\tCTheScripts::ClearSpaceForMissionEntity(vFollowerPos, ped);\n\t\t\t\t\tbool bFound = false;\n\t\t\t\t\tvFollowerPos.z = CWorld::FindGroundZFor3DCoord(vFollowerPos.x, vFollowerPos.y, vFollowerPos.z + 1.0f, &bFound) + 1.0f;\n\t\t\t\t\tif (bFound) {\n\t\t\t\t\t\tif (CWorld::GetIsLineOfSightClear(vFollowerPos, ped->GetPosition(), true, false, false, true, false, false)) {\n\t\t\t\t\t\t\tpTestedPed->Teleport(vFollowerPos);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_PLAYER_IN_AREA_2D:\n\t{\n\t\tCollectParameters(&m_nIp, 6);\n\t\tCPlayerPed* ped = CWorld::Players[ScriptParams[0]].m_pPed;\n\t\tfloat x1 = *(float*)&ScriptParams[1];\n\t\tfloat y1 = *(float*)&ScriptParams[2];\n\t\tfloat x2 = *(float*)&ScriptParams[3];\n\t\tfloat y2 = *(float*)&ScriptParams[4];\n\t\tif (!ped->bInVehicle)\n\t\t\tUpdateCompareFlag(ped->IsWithinArea(x1, y1, x2, y2));\n\t\telse\n\t\t\tUpdateCompareFlag(ped->m_pMyVehicle->IsWithinArea(x1, y1, x2, y2));\n\t\tif (ScriptParams[5])\n\t\t\tCTheScripts::HighlightImportantArea((uintptr)this + m_nIp, x1, y1, x2, y2, MAP_Z_LOW_LIMIT);\n\t\tif (CTheScripts::DbgFlag)\n\t\t\tCTheScripts::DrawDebugSquare(x1, y1, x2, y2);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_PLAYER_IN_AREA_3D:\n\t{\n\t\tCollectParameters(&m_nIp, 8);\n\t\tCPlayerPed* ped = CWorld::Players[ScriptParams[0]].m_pPed;\n\t\tfloat x1 = *(float*)&ScriptParams[1];\n\t\tfloat y1 = *(float*)&ScriptParams[2];\n\t\tfloat z1 = *(float*)&ScriptParams[3];\n\t\tfloat x2 = *(float*)&ScriptParams[4];\n\t\tfloat y2 = *(float*)&ScriptParams[5];\n\t\tfloat z2 = *(float*)&ScriptParams[6];\n\t\tif (ped->bInVehicle)\n\t\t\tUpdateCompareFlag(ped->m_pMyVehicle->IsWithinArea(x1, y1, z1, x2, y2, z2));\n\t\telse\n\t\t\tUpdateCompareFlag(ped->IsWithinArea(x1, y1, z1, x2, y2, z2));\n\t\tif (ScriptParams[7])\n\t\t\tCTheScripts::HighlightImportantArea((uintptr)this + m_nIp, x1, y1, x2, y2, (z1 + z2) / 2);\n\t\tif (CTheScripts::DbgFlag)\n\t\t\tCTheScripts::DrawDebugCube(x1, y1, z1, x2, y2, z2);\n\t\treturn 0;\n\t}\n\tcase COMMAND_ADD_INT_VAR_TO_INT_VAR:\n\t\tnScriptVar1 = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\t*nScriptVar1 += *GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\treturn 0;\n\tcase COMMAND_ADD_INT_LVAR_TO_INT_VAR:\n\t\tnScriptVar1 = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\t*nScriptVar1 += *GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\treturn 0;\n\tcase COMMAND_ADD_INT_VAR_TO_INT_LVAR:\n\t\tnScriptVar1 = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\t*nScriptVar1 += *GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\treturn 0;\n\tcase COMMAND_ADD_INT_LVAR_TO_INT_LVAR:\n\t\tnScriptVar1 = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\t*nScriptVar1 += *GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\treturn 0;\n\tcase COMMAND_ADD_FLOAT_VAR_TO_FLOAT_VAR:\n\t\tfScriptVar1 = (float*)GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\t*fScriptVar1 += *(float*)GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\treturn 0;\n\tcase COMMAND_ADD_FLOAT_LVAR_TO_FLOAT_VAR:\n\t\tfScriptVar1 = (float*)GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\t*fScriptVar1 += *(float*)GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\treturn 0;\n\tcase COMMAND_ADD_FLOAT_VAR_TO_FLOAT_LVAR:\n\t\tfScriptVar1 = (float*)GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\t*fScriptVar1 += *(float*)GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\treturn 0;\n\tcase COMMAND_ADD_FLOAT_LVAR_TO_FLOAT_LVAR:\n\t\tfScriptVar1 = (float*)GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\t*fScriptVar1 += *(float*)GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\treturn 0;\n\tcase COMMAND_SUB_INT_VAR_FROM_INT_VAR:\n\t\tnScriptVar1 = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\t*nScriptVar1 -= *GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\treturn 0;\n\tcase COMMAND_SUB_INT_LVAR_FROM_INT_LVAR:\n\t\tnScriptVar1 = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\t*nScriptVar1 -= *GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\treturn 0;\n\tcase COMMAND_SUB_FLOAT_VAR_FROM_FLOAT_VAR:\n\t\tfScriptVar1 = (float*)GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\t*fScriptVar1 -= *(float*)GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\treturn 0;\n\tcase COMMAND_SUB_FLOAT_LVAR_FROM_FLOAT_LVAR:\n\t\tfScriptVar1 = (float*)GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\t*fScriptVar1 -= *(float*)GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\treturn 0;\n\tdefault:\n\t\tscript_assert(0);\n\t\tbreak;\n\t}\n\treturn -1;\n}\n\nint8 CRunningScript::ProcessCommands100To199(int32 command)\n{\n\tfloat *fScriptVar1;\n\tint *nScriptVar1;\n\tswitch (command) {\n\tcase COMMAND_SUB_INT_LVAR_FROM_INT_VAR:\n\t\tnScriptVar1 = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\t*nScriptVar1 -= *GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\treturn 0;\n\tcase COMMAND_SUB_INT_VAR_FROM_INT_LVAR:\n\t\tnScriptVar1 = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\t*nScriptVar1 -= *GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\treturn 0;\n\tcase COMMAND_SUB_FLOAT_LVAR_FROM_FLOAT_VAR:\n\t\tfScriptVar1 = (float*)GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\t*fScriptVar1 -= *(float*)GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\treturn 0;\n\tcase COMMAND_SUB_FLOAT_VAR_FROM_FLOAT_LVAR:\n\t\tfScriptVar1 = (float*)GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\t*fScriptVar1 -= *(float*)GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\treturn 0;\n\tcase COMMAND_MULT_INT_VAR_BY_INT_VAR:\n\t\tnScriptVar1 = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\t*nScriptVar1 *= *GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\treturn 0;\n\tcase COMMAND_MULT_INT_VAR_BY_INT_LVAR:\n\t\tnScriptVar1 = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\t*nScriptVar1 *= *GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\treturn 0;\n\tcase COMMAND_MULT_INT_LVAR_BY_INT_VAR:\n\t\tnScriptVar1 = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\t*nScriptVar1 *= *GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\treturn 0;\n\tcase COMMAND_MULT_INT_LVAR_BY_INT_LVAR:\n\t\tnScriptVar1 = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\t*nScriptVar1 *= *GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\treturn 0;\n\tcase COMMAND_MULT_FLOAT_VAR_BY_FLOAT_VAR:\n\t\tfScriptVar1 = (float*)GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\t*fScriptVar1 *= *(float*)GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\treturn 0;\n\tcase COMMAND_MULT_FLOAT_VAR_BY_FLOAT_LVAR:\n\t\tfScriptVar1 = (float*)GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\t*fScriptVar1 *= *(float*)GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\treturn 0;\n\tcase COMMAND_MULT_FLOAT_LVAR_BY_FLOAT_VAR:\n\t\tfScriptVar1 = (float*)GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\t*fScriptVar1 *= *(float*)GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\treturn 0;\n\tcase COMMAND_MULT_FLOAT_LVAR_BY_FLOAT_LVAR:\n\t\tfScriptVar1 = (float*)GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\t*fScriptVar1 *= *(float*)GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\treturn 0;\n\tcase COMMAND_DIV_INT_VAR_BY_INT_VAR:\n\t\tnScriptVar1 = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\t*nScriptVar1 /= *GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\treturn 0;\n\tcase COMMAND_DIV_INT_VAR_BY_INT_LVAR:\n\t\tnScriptVar1 = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\t*nScriptVar1 /= *GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\treturn 0;\n\tcase COMMAND_DIV_INT_LVAR_BY_INT_VAR:\n\t\tnScriptVar1 = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\t*nScriptVar1 /= *GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\treturn 0;\n\tcase COMMAND_DIV_INT_LVAR_BY_INT_LVAR:\n\t\tnScriptVar1 = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\t*nScriptVar1 /= *GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\treturn 0;\n\tcase COMMAND_DIV_FLOAT_VAR_BY_FLOAT_VAR:\n\t\tfScriptVar1 = (float*)GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\t*fScriptVar1 /= *(float*)GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\treturn 0;\n\tcase COMMAND_DIV_FLOAT_VAR_BY_FLOAT_LVAR:\n\t\tfScriptVar1 = (float*)GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\t*fScriptVar1 /= *(float*)GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\treturn 0;\n\tcase COMMAND_DIV_FLOAT_LVAR_BY_FLOAT_VAR:\n\t\tfScriptVar1 = (float*)GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\t*fScriptVar1 /= *(float*)GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\treturn 0;\n\tcase COMMAND_DIV_FLOAT_LVAR_BY_FLOAT_LVAR:\n\t\tfScriptVar1 = (float*)GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\t*fScriptVar1 /= *(float*)GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\treturn 0;\n\tcase COMMAND_ADD_TIMED_VAL_TO_FLOAT_VAR:\n\t{\n\t\tint32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\tCollectParameters(&m_nIp, 1);\n\t\t*(float*)ptr += CTimer::GetTimeStep() * *(float*)&ScriptParams[0];\n\t\treturn 0;\n\t}\n\tcase COMMAND_ADD_TIMED_VAL_TO_FLOAT_LVAR:\n\t{\n\t\tint32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\tCollectParameters(&m_nIp, 1);\n\t\t*(float*)ptr += CTimer::GetTimeStep() * *(float*)&ScriptParams[0];\n\t\treturn 0;\n\t}\n\tcase COMMAND_ADD_TIMED_FLOAT_VAR_TO_FLOAT_VAR:\n\t\tfScriptVar1 = (float*)GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\t*fScriptVar1 += CTimer::GetTimeStep() * *(float*)GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\treturn 0;\n#ifdef FIX_BUGS\n\tcase COMMAND_ADD_TIMED_FLOAT_VAR_TO_FLOAT_LVAR:\n#else\n\tcase COMMAND_ADD_TIMED_FLOAT_LVAR_TO_FLOAT_VAR:\n#endif\n\t\tfScriptVar1 = (float*)GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\t*fScriptVar1 += CTimer::GetTimeStep() * *(float*)GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\treturn 0;\n#ifdef FIX_BUGS\n\tcase COMMAND_ADD_TIMED_FLOAT_LVAR_TO_FLOAT_VAR:\n#else\n\tcase COMMAND_ADD_TIMED_FLOAT_VAR_TO_FLOAT_LVAR:\n#endif\n\t\tfScriptVar1 = (float*)GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\t*fScriptVar1 += CTimer::GetTimeStep() * *(float*)GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\treturn 0;\n\tcase COMMAND_ADD_TIMED_FLOAT_LVAR_TO_FLOAT_LVAR:\n\t\tfScriptVar1 = (float*)GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\t*fScriptVar1 += CTimer::GetTimeStep() * *(float*)GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\treturn 0;\n\tcase COMMAND_SUB_TIMED_VAL_FROM_FLOAT_VAR:\n\t{\n\t\tint32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\tCollectParameters(&m_nIp, 1);\n\t\t*(float*)ptr -= CTimer::GetTimeStep() * *(float*)&ScriptParams[0];\n\t\treturn 0;\n\t}\n\tcase COMMAND_SUB_TIMED_VAL_FROM_FLOAT_LVAR:\n\t{\n\t\tint32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\tCollectParameters(&m_nIp, 1);\n\t\t*(float*)ptr -= CTimer::GetTimeStep() * *(float*)&ScriptParams[0];\n\t\treturn 0;\n\t}\n\tcase COMMAND_SUB_TIMED_FLOAT_VAR_FROM_FLOAT_VAR:\n\t\tfScriptVar1 = (float*)GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\t*fScriptVar1 -= CTimer::GetTimeStep() * *(float*)GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\treturn 0;\n#ifdef FIX_BUGS // in SA it was fixed by reversing their order in enum\n\tcase COMMAND_SUB_TIMED_FLOAT_VAR_FROM_FLOAT_LVAR:\n#else\n\tcase COMMAND_SUB_TIMED_FLOAT_LVAR_FROM_FLOAT_VAR:\n#endif\n\t\tfScriptVar1 = (float*)GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\t*fScriptVar1 -= CTimer::GetTimeStep() * *(float*)GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\treturn 0;\n#ifdef FIX_BUGS\n\tcase COMMAND_SUB_TIMED_FLOAT_LVAR_FROM_FLOAT_VAR:\n#else\n\tcase COMMAND_SUB_TIMED_FLOAT_VAR_FROM_FLOAT_LVAR:\n#endif\n\t\tfScriptVar1 = (float*)GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\t*fScriptVar1 -= CTimer::GetTimeStep() * *(float*)GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\treturn 0;\n\tcase COMMAND_SUB_TIMED_FLOAT_LVAR_FROM_FLOAT_LVAR:\n\t\tfScriptVar1 = (float*)GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\t*fScriptVar1 -= CTimer::GetTimeStep() * *(float*)GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\treturn 0;\n\tcase COMMAND_SET_VAR_INT_TO_VAR_INT:\n\t{\n\t\tint32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\t*ptr = *GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_VAR_INT_TO_LVAR_INT:\n\t{\n\t\tint32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\t*ptr = *GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_LVAR_INT_TO_VAR_INT:\n\t{\n\t\tint32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\t*ptr = *GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_LVAR_INT_TO_LVAR_INT:\n\t{\n\t\tint32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\t*ptr = *GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_VAR_FLOAT_TO_VAR_FLOAT:\n\t{\n\t\tfloat* ptr = (float*)GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\t*ptr = *(float*)GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_VAR_FLOAT_TO_LVAR_FLOAT:\n\t{\n\t\tfloat* ptr = (float*)GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\t*ptr = *(float*)GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_LVAR_FLOAT_TO_VAR_FLOAT:\n\t{\n\t\tfloat* ptr = (float*)GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\t*ptr = *(float*)GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_LVAR_FLOAT_TO_LVAR_FLOAT:\n\t{\n\t\tfloat* ptr = (float*)GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\t*ptr = *(float*)GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\treturn 0;\n\t}\n\tcase COMMAND_CSET_VAR_INT_TO_VAR_FLOAT:\n\t{\n\t\tint32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\t*ptr = *(float*)GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\treturn 0;\n\t}\n\tcase COMMAND_CSET_VAR_INT_TO_LVAR_FLOAT:\n\t{\n\t\tint32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\t*ptr = *(float*)GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\treturn 0;\n\t}\n\tcase COMMAND_CSET_LVAR_INT_TO_VAR_FLOAT:\n\t{\n\t\tint32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\t*ptr = *(float*)GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\treturn 0;\n\t}\n\tcase COMMAND_CSET_LVAR_INT_TO_LVAR_FLOAT:\n\t{\n\t\tint32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\t*ptr = *(float*)GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\treturn 0;\n\t}\n\tcase COMMAND_CSET_VAR_FLOAT_TO_VAR_INT:\n\t{\n\t\tfloat* ptr = (float*)GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\t*ptr = *GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\treturn 0;\n\t}\n\tcase COMMAND_CSET_VAR_FLOAT_TO_LVAR_INT:\n\t{\n\t\tfloat* ptr = (float*)GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\t*ptr = *GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\treturn 0;\n\t}\n\tcase COMMAND_CSET_LVAR_FLOAT_TO_VAR_INT:\n\t{\n\t\tfloat* ptr = (float*)GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\t*ptr = *GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\treturn 0;\n\t}\n\tcase COMMAND_CSET_LVAR_FLOAT_TO_LVAR_INT:\n\t{\n\t\tfloat* ptr = (float*)GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\t*ptr = *GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\treturn 0;\n\t}\n\tcase COMMAND_ABS_VAR_INT:\n\t{\n\t\tint32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\t*ptr = ABS(*ptr);\n\t\treturn 0;\n\t}\n\tcase COMMAND_ABS_LVAR_INT:\n\t{\n\t\tint32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\t*ptr = ABS(*ptr);\n\t\treturn 0;\n\t}\n\tcase COMMAND_ABS_VAR_FLOAT:\n\t{\n\t\tfloat* ptr = (float*)GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\t*ptr = ABS(*ptr);\n\t\treturn 0;\n\t}\n\tcase COMMAND_ABS_LVAR_FLOAT:\n\t{\n\t\tfloat* ptr = (float*)GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\t*ptr = ABS(*ptr);\n\t\treturn 0;\n\t}\n\tcase COMMAND_GENERATE_RANDOM_FLOAT:\n\t{\n\t\tfloat* ptr = (float*)GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\tCGeneral::GetRandomNumber();\n\t\tCGeneral::GetRandomNumber();\n\t\tCGeneral::GetRandomNumber(); /* To make it EXTRA random! */\n#ifdef FIX_BUGS\n\t\t*ptr = CGeneral::GetRandomNumberInRange(0.0f, 1.0f);\n#else\n\t\t*ptr = CGeneral::GetRandomNumber() / 65536.0f;\n\t\t/* Between 0 and 0.5 on PC (oh well...), never used in original script. */\n#endif\n\n\t\treturn 0;\n\t}\n\tcase COMMAND_GENERATE_RANDOM_INT:\n\t\t*GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL) = CGeneral::GetRandomNumber();\n\t\treturn 0;\n\tcase COMMAND_CREATE_CHAR:\n\t{\n\t\tCollectParameters(&m_nIp, 5);\n\t\tswitch (ScriptParams[1]) {\n\t\tcase MI_COP:\n\t\t\tif (ScriptParams[0] == PEDTYPE_COP)\n\t\t\t\tScriptParams[1] = COP_STREET;\n\t\t\tbreak;\n\t\tcase MI_SWAT:\n\t\t\tif (ScriptParams[0] == PEDTYPE_COP)\n\t\t\t\tScriptParams[1] = COP_SWAT;\n\t\t\tbreak;\n\t\tcase MI_FBI:\n\t\t\tif (ScriptParams[0] == PEDTYPE_COP)\n\t\t\t\tScriptParams[1] = COP_FBI;\n\t\t\tbreak;\n\t\tcase MI_ARMY:\n\t\t\tif (ScriptParams[0] == PEDTYPE_COP)\n\t\t\t\tScriptParams[1] = COP_ARMY;\n\t\t\tbreak;\n\t\tcase MI_MEDIC:\n\t\t\tif (ScriptParams[0] == PEDTYPE_EMERGENCY)\n\t\t\t\tScriptParams[1] = PEDTYPE_EMERGENCY;\n\t\t\tbreak;\n\t\tcase MI_FIREMAN:\n\t\t\tif (ScriptParams[0] == PEDTYPE_FIREMAN)\n\t\t\t\tScriptParams[1] = PEDTYPE_FIREMAN;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\t\tCPed* ped;\n\t\tif (ScriptParams[0] == PEDTYPE_COP)\n\t\t\tped = new CCopPed((eCopType)ScriptParams[1]);\n\t\telse if (ScriptParams[0] == PEDTYPE_EMERGENCY || ScriptParams[0] == PEDTYPE_FIREMAN)\n\t\t\tped = new CEmergencyPed(ScriptParams[1]);\n\t\telse\n\t\t\tped = new CCivilianPed((ePedType)ScriptParams[0], ScriptParams[1]);\n\t\tped->CharCreatedBy = MISSION_CHAR;\n\t\tped->bRespondsToThreats = false;\n\t\tped->bAllowMedicsToReviveMe = false;\n\t\tped->bIsPlayerFriend = false;\n\t\tCVector pos = *(CVector*)&ScriptParams[2];\n\t\tif (pos.z <= MAP_Z_LOW_LIMIT)\n\t\t\tpos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);\n\t\tpos.z += 1.0f;\n\t\tped->SetPosition(pos);\n\t\tped->SetOrientation(0.0f, 0.0f, 0.0f);\n\t\tCTheScripts::ClearSpaceForMissionEntity(pos, ped);\n\t\tif (m_bIsMissionScript)\n\t\t\tped->bIsStaticWaitingForCollision = true;\n\t\tCWorld::Add(ped);\n\t\tped->m_nZoneLevel = CTheZones::GetLevelFromPosition(&pos);\n\t\tCPopulation::ms_nTotalMissionPeds++;\n\t\tScriptParams[0] = CPools::GetPedPool()->GetIndex(ped);\n\t\tStoreParameters(&m_nIp, 1);\n\t\tif (m_bIsMissionScript)\n\t\t\tCTheScripts::MissionCleanUp.AddEntityToList(ScriptParams[0], CLEANUP_CHAR);\n\t\treturn 0;\n\t}\n\tcase COMMAND_DELETE_CHAR:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* ped = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tCTheScripts::RemoveThisPed(ped);\n\t\tif (m_bIsMissionScript)\n\t\t\tCTheScripts::MissionCleanUp.RemoveEntityFromList(ScriptParams[0], CLEANUP_CHAR);\n\t\treturn 0;\n\t}\n\tcase COMMAND_CHAR_WANDER_DIR:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* ped = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(ped);\n\t\tped->ClearAll();\n\t\tint8 path = ScriptParams[1];\n\t\tif (ScriptParams[1] < 0 || ScriptParams[1] > 7)\n\t\t\t// Max number GetRandomNumberInRange returns is max-1\n#ifdef FIX_BUGS\n\t\t\tpath = CGeneral::GetRandomNumberInRange(0, 8);\n#else\n\t\t\tpath = CGeneral::GetRandomNumberInRange(0, 7);\n#endif\n\n\t\tped->SetWanderPath(path);\n\t\treturn 0;\n\t}\n\t//case COMMAND_CHAR_WANDER_RANGE:\n\tcase COMMAND_CHAR_FOLLOW_PATH:\n\t{\n\t\tCollectParameters(&m_nIp, 6);\n\t\tCPed* ped = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(ped);\n\t\tif (ped->GetPedState() == PED_ATTACK || ped->GetPedState() == PED_FIGHT || !ped->IsPedInControl())\n\t\t\treturn 0;\n\t\tCVector pos = *(CVector*)&ScriptParams[1];\n\t\tif (pos.z <= MAP_Z_LOW_LIMIT)\n\t\t\tpos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);\n\t\tfloat radius = *(float*)&ScriptParams[4];\n\t\teMoveState state;\n\t\tswitch (ScriptParams[5]) {\n\t\tcase 0: state = PEDMOVE_WALK; break;\n\t\tcase 1: state = PEDMOVE_RUN; break;\n\t\tdefault: assert(0);\n\t\t}\n\t\tped->ClearAll();\n\t\tped->m_pathNodeTimer = 0;\n\t\tped->SetFollowPath(pos, radius, state, nil, nil, 999999);\n\t\treturn 0;\n\t}\n\tcase COMMAND_CHAR_SET_IDLE:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* ped = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(ped);\n\t\tped->bScriptObjectiveCompleted = false;\n\t\tped->SetObjective(OBJECTIVE_WAIT_ON_FOOT);\n\t\treturn 0;\n\t}\n\tcase COMMAND_GET_CHAR_COORDINATES:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* ped = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(ped);\n\t\tCVehicle* vehicle;\n\t\tCVector pos;\n\t\t/* Seems a bit clumsy but I'll leave original flow */\n\t\tif (ped->bInVehicle)\n\t\t\tvehicle = ped->m_pMyVehicle;\n\t\telse\n\t\t\tvehicle = nil;\n\t\tif (vehicle)\n\t\t\tpos = vehicle->GetPosition();\n\t\telse\n\t\t\tpos = ped->GetPosition();\n\t\t*(CVector*)&ScriptParams[0] = pos;\n\t\tStoreParameters(&m_nIp, 3);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_CHAR_COORDINATES:\n\t{\n\t\tCollectParameters(&m_nIp, 4);\n\t\tCPed* ped = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(ped);\n\t\tCVehicle* vehicle;\n\t\tif (ped->bInVehicle)\n\t\t\tvehicle = ped->m_pMyVehicle;\n\t\telse\n\t\t\tvehicle = nil;\n\t\tCVector pos = *(CVector*)&ScriptParams[1];\n\t\tif (pos.z <= MAP_Z_LOW_LIMIT)\n\t\t\tpos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);\n\t\t// removed dumb stuff again\n\t\tif (!vehicle) {\n\t\t\tpos.z += ped->GetDistanceFromCentreOfMassToBaseOfModel();\n\t\t\tped->Teleport(pos);\n\t\t\tCTheScripts::ClearSpaceForMissionEntity(pos, ped);\n\t\t\tfor (int i = 0; i < ped->m_numNearPeds; i++) {\n\t\t\t\tCPed* pNearPed = ped->m_nearPeds[i];\n\t\t\t\tif (pNearPed->m_leader == ped) {\n\t\t\t\t\tpNearPed->Teleport(pos);\n\t\t\t\t\tpNearPed->PositionAnyPedOutOfCollision();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tpos.z += vehicle->GetDistanceFromCentreOfMassToBaseOfModel();\n\t\t\tvehicle->Teleport(pos);\n\t\t\tCTheScripts::ClearSpaceForMissionEntity(pos, vehicle);\n\t\t}\n\t\treturn 0;\n\t}\n\t/*\n\tcase COMMAND_IS_CHAR_STILL_ALIVE:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* ped = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tUpdateCompareFlag(ped && ped->GetPedState() != PED_DEAD && ped->GetPedState() != PED_DIE);\n\t\treturn 0;\n\t}\n\t*/\n\tcase COMMAND_IS_CHAR_IN_AREA_2D:\n\t{\n\t\tCollectParameters(&m_nIp, 6);\n\t\tCPed* ped = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(ped);\n\t\tCVehicle* vehicle;\n\t\tif (ped->bInVehicle)\n\t\t\tvehicle = ped->m_pMyVehicle;\n\t\telse\n\t\t\tvehicle = nil;\n\t\tfloat x1 = *(float*)&ScriptParams[1];\n\t\tfloat y1 = *(float*)&ScriptParams[2];\n\t\tfloat x2 = *(float*)&ScriptParams[3];\n\t\tfloat y2 = *(float*)&ScriptParams[4];\n\t\tif (vehicle)\n\t\t\tUpdateCompareFlag(ped->m_pMyVehicle->IsWithinArea(x1, y1, x2, y2));\n\t\telse\n\t\t\tUpdateCompareFlag(ped->IsWithinArea(x1, y1, x2, y2));\n\t\tif (ScriptParams[5])\n\t\t\tCTheScripts::HighlightImportantArea((uintptr)this + m_nIp, x1, y1, x2, y2, MAP_Z_LOW_LIMIT);\n\t\tif (CTheScripts::DbgFlag)\n\t\t\tCTheScripts::DrawDebugSquare(x1, y1, x2, y2);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_CHAR_IN_AREA_3D:\n\t{\n\t\tCollectParameters(&m_nIp, 8);\n\t\tCPed* ped = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(ped);\n\t\tCVehicle* vehicle;\n\t\tif (ped->bInVehicle)\n\t\t\tvehicle = ped->m_pMyVehicle;\n\t\telse\n\t\t\tvehicle = nil;\n\t\tfloat x1 = *(float*)&ScriptParams[1];\n\t\tfloat y1 = *(float*)&ScriptParams[2];\n\t\tfloat z1 = *(float*)&ScriptParams[3];\n\t\tfloat x2 = *(float*)&ScriptParams[4];\n\t\tfloat y2 = *(float*)&ScriptParams[5];\n\t\tfloat z2 = *(float*)&ScriptParams[6];\n\t\tif (vehicle)\n\t\t\tUpdateCompareFlag(ped->m_pMyVehicle->IsWithinArea(x1, y1, z1, x2, y2, z2));\n\t\telse\n\t\t\tUpdateCompareFlag(ped->IsWithinArea(x1, y1, z1, x2, y2, z2));\n\t\tif (ScriptParams[7])\n\t\t\tCTheScripts::HighlightImportantArea((uintptr)this + m_nIp, x1, y1, x2, y2, (z1 + z2) / 2);\n\t\tif (CTheScripts::DbgFlag)\n\t\t\tCTheScripts::DrawDebugCube(x1, y1, z1, x2, y2, z2);\n\t\treturn 0;\n\t}\n\tcase COMMAND_CREATE_CAR:\n\t{\n\t\tCollectParameters(&m_nIp, 4);\n\t\tint32 handle;\n\t\tif (CModelInfo::IsBoatModel(ScriptParams[0])) {\n\t\t\tCBoat* boat = new CBoat(ScriptParams[0], MISSION_VEHICLE);\n\t\t\tCVector pos = *(CVector*)&ScriptParams[1];\n\t\t\tif (pos.z <= MAP_Z_LOW_LIMIT)\n\t\t\t\tpos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);\n\t\t\tpos.z += boat->GetDistanceFromCentreOfMassToBaseOfModel();\n\t\t\tboat->SetPosition(pos);\n\t\t\tCTheScripts::ClearSpaceForMissionEntity(pos, boat);\n\t\t\tboat->SetStatus(STATUS_ABANDONED);\n\t\t\tboat->bIsLocked = true;\n\t\t\tboat->AutoPilot.m_nCarMission = MISSION_NONE;\n\t\t\tboat->AutoPilot.m_nTempAction = TEMPACT_NONE;\n\t\t\tboat->AutoPilot.m_nCruiseSpeed = boat->AutoPilot.m_fMaxTrafficSpeed = 20.0f;\n\t\t\tif (m_bIsMissionScript)\n\t\t\t\tboat->bIsStaticWaitingForCollision = true;\n\t\t\tCWorld::Add(boat);\n\t\t\thandle = CPools::GetVehiclePool()->GetIndex(boat);\n\t\t}\n\t\telse {\n\t\t\tCVehicle* car;\n\n\t\t\tif (!CModelInfo::IsBikeModel(ScriptParams[0]))\n\t\t\t\tcar = new CAutomobile(ScriptParams[0], MISSION_VEHICLE);\n\t\t\telse {\n\t\t\t\tcar = new CBike(ScriptParams[0], MISSION_VEHICLE);\n\t\t\t\t((CBike*)(car))->bIsStanding = true;\n\t\t\t}\n\t\t\tCVector pos = *(CVector*)&ScriptParams[1];\n\t\t\tif (pos.z <= MAP_Z_LOW_LIMIT)\n\t\t\t\tpos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);\n\t\t\tpos.z += car->GetDistanceFromCentreOfMassToBaseOfModel();\n\t\t\tcar->SetPosition(pos);\n\t\t\tCTheScripts::ClearSpaceForMissionEntity(pos, car);\n\t\t\tcar->SetStatus(STATUS_ABANDONED);\n\t\t\tcar->bIsLocked = true;\n\t\t\tCCarCtrl::JoinCarWithRoadSystem(car);\n\t\t\tcar->AutoPilot.m_nCarMission = MISSION_NONE;\n\t\t\tcar->AutoPilot.m_nTempAction = TEMPACT_NONE;\n\t\t\tcar->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_STOP_FOR_CARS;\n\t\t\tcar->AutoPilot.m_nCruiseSpeed = car->AutoPilot.m_fMaxTrafficSpeed = 9.0f;\n\t\t\tcar->AutoPilot.m_nCurrentLane = car->AutoPilot.m_nNextLane = 0;\n\t\t\tcar->bEngineOn = false;\n\t\t\tcar->m_nZoneLevel = CTheZones::GetLevelFromPosition(&pos);\n\t\t\tcar->bHasBeenOwnedByPlayer = true;\n\t\t\tif (m_bIsMissionScript)\n\t\t\t\tcar->bIsStaticWaitingForCollision = true;\n\t\t\tCWorld::Add(car);\n\t\t\thandle = CPools::GetVehiclePool()->GetIndex(car);\n\t\t}\n\t\tScriptParams[0] = handle;\n\t\tStoreParameters(&m_nIp, 1);\n\t\tif (m_bIsMissionScript)\n\t\t\tCTheScripts::MissionCleanUp.AddEntityToList(handle, CLEANUP_CAR);\n\t\treturn 0;\n\t}\n\tcase COMMAND_DELETE_CAR:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCVehicle* car = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tif (car) {\n\t\t\tCWorld::Remove(car);\n\t\t\tCWorld::RemoveReferencesToDeletedObject(car);\n\t\t\tdelete car;\n\t\t}\n\t\tif (m_bIsMissionScript)\n\t\t\tCTheScripts::MissionCleanUp.RemoveEntityFromList(ScriptParams[0], CLEANUP_CAR);\n\t\treturn 0;\n\t}\n\tcase COMMAND_CAR_GOTO_COORDINATES:\n\t{\n\t\tCollectParameters(&m_nIp, 4);\n\t\tCVehicle* car = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(car);\n\t\tCVector pos = *(CVector*)&ScriptParams[1];\n\t\tif (pos.z <= MAP_Z_LOW_LIMIT)\n\t\t\tpos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);\n\t\tpos.z += car->GetDistanceFromCentreOfMassToBaseOfModel();\n\t\tif (CCarCtrl::JoinCarWithRoadSystemGotoCoors(car, pos, false))\n\t\t\tcar->AutoPilot.m_nCarMission = MISSION_GOTOCOORDS_STRAIGHT;\n\t\telse\n\t\t\tcar->AutoPilot.m_nCarMission = MISSION_GOTOCOORDS;\n\t\tcar->SetStatus(STATUS_PHYSICS);\n\t\tcar->bEngineOn = true;\n\t\tcar->AutoPilot.m_nCruiseSpeed = Max(1, car->AutoPilot.m_nCruiseSpeed);\n\t\tcar->AutoPilot.m_nAntiReverseTimer = CTimer::GetTimeInMilliseconds();\n\t\treturn 0;\n\t}\n\tcase COMMAND_CAR_WANDER_RANDOMLY:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCVehicle* car = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(car);\n\t\tCCarCtrl::JoinCarWithRoadSystem(car);\n\t\tcar->AutoPilot.m_nCarMission = MISSION_CRUISE;\n\t\tcar->bEngineOn = true;\n\t\tcar->AutoPilot.m_nCruiseSpeed = Max(1, car->AutoPilot.m_nCruiseSpeed);\n\t\tcar->AutoPilot.m_nAntiReverseTimer = CTimer::GetTimeInMilliseconds();\n\t\treturn 0;\n\t}\n\tcase COMMAND_CAR_SET_IDLE:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCVehicle* car = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(car);\n\t\tcar->AutoPilot.m_nCarMission = MISSION_NONE;\n\t\treturn 0;\n\t}\n\tcase COMMAND_GET_CAR_COORDINATES:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCVehicle* car = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(car);\n\t\t*(CVector*)&ScriptParams[0] = car->GetPosition();\n\t\tStoreParameters(&m_nIp, 3);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_CAR_COORDINATES:\n\t{\n\t\tCollectParameters(&m_nIp, 4);\n\t\tCVehicle* car = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(car);\n\t\tCVector pos = *(CVector*)&ScriptParams[1];\n\t\tif (pos.z <= MAP_Z_LOW_LIMIT)\n\t\t\tpos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);\n\t\tpos.z += car->GetDistanceFromCentreOfMassToBaseOfModel();\n\t\tcar->SetIsStatic(false);\n\t\t/* Again weird usage of virtual functions. */\n\t\tif (car->IsBoat()) {\n\t\t\tcar->Teleport(pos);\n\t\t\tCTheScripts::ClearSpaceForMissionEntity(pos, car);\n\t\t}\n\t\telse {\n\t\t\tcar->Teleport(pos);\n\t\t\tCTheScripts::ClearSpaceForMissionEntity(pos, car);\n\t\t\t/* May the following be inlined CCarCtrl function? */\n\t\t\tswitch (car->AutoPilot.m_nCarMission) {\n\t\t\tcase MISSION_CRUISE:\n\t\t\t\tCCarCtrl::JoinCarWithRoadSystem(car);\n\t\t\t\tbreak;\n\t\t\tcase MISSION_RAMPLAYER_FARAWAY:\n\t\t\tcase MISSION_RAMPLAYER_CLOSE:\n\t\t\tcase MISSION_BLOCKPLAYER_FARAWAY:\n\t\t\tcase MISSION_BLOCKPLAYER_CLOSE:\n\t\t\tcase MISSION_BLOCKPLAYER_HANDBRAKESTOP:\n\t\t\t\tCCarCtrl::JoinCarWithRoadSystemGotoCoors(car, FindPlayerCoors(), false);\n\t\t\t\tbreak;\n\t\t\tcase MISSION_GOTOCOORDS:\n\t\t\tcase MISSION_GOTOCOORDS_STRAIGHT:\n\t\t\t\tCCarCtrl::JoinCarWithRoadSystemGotoCoors(car, car->AutoPilot.m_vecDestinationCoors, false);\n\t\t\t\tbreak;\n\t\t\tcase MISSION_GOTOCOORDS_ACCURATE:\n\t\t\tcase MISSION_GOTO_COORDS_STRAIGHT_ACCURATE:\n\t\t\t\tCCarCtrl::JoinCarWithRoadSystemGotoCoors(car, car->AutoPilot.m_vecDestinationCoors, false);\n\t\t\t\tbreak;\n\t\t\tcase MISSION_RAMCAR_FARAWAY:\n\t\t\tcase MISSION_RAMCAR_CLOSE:\n\t\t\tcase MISSION_BLOCKCAR_FARAWAY:\n\t\t\tcase MISSION_BLOCKCAR_CLOSE:\n\t\t\tcase MISSION_BLOCKCAR_HANDBRAKESTOP:\n\t\t\t\tCCarCtrl::JoinCarWithRoadSystemGotoCoors(car, car->AutoPilot.m_pTargetCar->GetPosition(), false);\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\treturn 0;\n\t}\n\t/*\n\tcase COMMAND_IS_CAR_STILL_ALIVE:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCVehicle* car = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tUpdateCompareFlag(car && car->GetStatus() != STATUS_WRECKED && (car->IsBoat() || !car->bIsInWater));\n\t\treturn 0;\n\t}\n\t*/\n\tcase COMMAND_SET_CAR_CRUISE_SPEED:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCVehicle* car = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(car);\n#if defined MISSION_REPLAY && defined SIMPLIER_MISSIONS\n\t\tcar->AutoPilot.m_nCruiseSpeed = *(float*)&ScriptParams[1];\n\t\tif (missionRetryScriptIndex == 40 && car->GetModelIndex() == MI_CHEETAH) // Turismo\n\t\t\tcar->AutoPilot.m_nCruiseSpeed = 8 * car->AutoPilot.m_nCruiseSpeed / 10;\n\t\tcar->AutoPilot.m_nCruiseSpeed = Min(car->AutoPilot.m_nCruiseSpeed, 60.0f * car->pHandling->Transmission.fMaxCruiseVelocity);\n#else\n\t\tcar->AutoPilot.m_nCruiseSpeed = Min(*(float*)&ScriptParams[1], 60.0f * car->pHandling->Transmission.fMaxCruiseVelocity);\n#endif\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_CAR_DRIVING_STYLE:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCVehicle* car = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(car);\n\t\tcar->AutoPilot.m_nDrivingStyle = (uint8)ScriptParams[1];\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_CAR_MISSION:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCVehicle* car = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(car);\n\t\tcar->AutoPilot.m_nCarMission = (uint8)ScriptParams[1];\n\t\tcar->AutoPilot.m_nAntiReverseTimer = CTimer::GetTimeInMilliseconds();\n\t\tcar->bEngineOn = true;\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_CAR_IN_AREA_2D:\n\t{\n\t\tCollectParameters(&m_nIp, 6);\n\t\tCVehicle* vehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(vehicle);\n\t\tfloat x1 = *(float*)&ScriptParams[1];\n\t\tfloat y1 = *(float*)&ScriptParams[2];\n\t\tfloat x2 = *(float*)&ScriptParams[3];\n\t\tfloat y2 = *(float*)&ScriptParams[4];\n\t\tUpdateCompareFlag(vehicle->IsWithinArea(x1, y1, x2, y2));\n\t\tif (ScriptParams[5])\n\t\t\tCTheScripts::HighlightImportantArea((uintptr)this + m_nIp, x1, y1, x2, y2, MAP_Z_LOW_LIMIT);\n\t\tif (CTheScripts::DbgFlag)\n\t\t\tCTheScripts::DrawDebugSquare(x1, y1, x2, y2);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_CAR_IN_AREA_3D:\n\t{\n\t\tCollectParameters(&m_nIp, 8);\n\t\tCVehicle* vehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(vehicle);\n\t\tfloat x1 = *(float*)&ScriptParams[1];\n\t\tfloat y1 = *(float*)&ScriptParams[2];\n\t\tfloat z1 = *(float*)&ScriptParams[3];\n\t\tfloat x2 = *(float*)&ScriptParams[4];\n\t\tfloat y2 = *(float*)&ScriptParams[5];\n\t\tfloat z2 = *(float*)&ScriptParams[6];\n\t\tUpdateCompareFlag(vehicle->IsWithinArea(x1, y1, z1, x2, y2, z2));\n\t\tif (ScriptParams[7])\n\t\t\tCTheScripts::HighlightImportantArea((uintptr)this + m_nIp, x1, y1, x2, y2, (z1 + z2) / 2);\n\t\tif (CTheScripts::DbgFlag)\n\t\t\tCTheScripts::DrawDebugCube(x1, y1, z1, x2, y2, z2);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SPECIAL_0:\n\tcase COMMAND_SPECIAL_1:\n\tcase COMMAND_SPECIAL_2:\n\tcase COMMAND_SPECIAL_3:\n\tcase COMMAND_SPECIAL_4:\n\tcase COMMAND_SPECIAL_5:\n\tcase COMMAND_SPECIAL_6:\n\tcase COMMAND_SPECIAL_7:\n\t\tscript_assert(0);\n\t\treturn 0;\n\tcase COMMAND_PRINT_BIG:\n\t{\n\t\twchar* key = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n#ifdef MISSION_REPLAY\n\t\tif (strcmp((char*)&CTheScripts::ScriptSpace[m_nIp], \"M_FAIL\") == 0 && CanAllowMissionReplay())\n\t\t\tAllowMissionReplay = 1;\n#endif\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCMessages::AddBigMessage(key, ScriptParams[0], ScriptParams[1] - 1);\n\t\treturn 0;\n\t}\n\tcase COMMAND_PRINT:\n\t{\n\t\twchar* key = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCMessages::AddMessage(key, ScriptParams[0], ScriptParams[1]);\n\t\treturn 0;\n\t}\n\tcase COMMAND_PRINT_NOW:\n\t{\n\t\twchar* key = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCMessages::AddMessageJumpQ(key, ScriptParams[0], ScriptParams[1]);\n\t\treturn 0;\n\t}\n\t/*\n\tcase COMMAND_PRINT_SOON:\n\t{\n\t\twchar* key = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCMessages::AddMessageSoon(key, ScriptParams[0], ScriptParams[1]);\n\t\treturn 0;\n\t}\n\t*/\n\tcase COMMAND_CLEAR_PRINTS:\n\t\tCMessages::ClearMessages();\n\t\treturn 0;\n\tcase COMMAND_GET_TIME_OF_DAY:\n\t\tScriptParams[0] = CClock::GetHours();\n\t\tScriptParams[1] = CClock::GetMinutes();\n\t\tStoreParameters(&m_nIp, 2);\n\t\treturn 0;\n\tcase COMMAND_SET_TIME_OF_DAY:\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCClock::SetGameClock(ScriptParams[0], ScriptParams[1]);\n\t\treturn 0;\n\tcase COMMAND_GET_MINUTES_TO_TIME_OF_DAY:\n\t\tCollectParameters(&m_nIp, 2);\n\t\tScriptParams[0] = CClock::GetGameClockMinutesUntil(ScriptParams[0], ScriptParams[1]);\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\tcase COMMAND_IS_POINT_ON_SCREEN:\n\t{\n\t\tCollectParameters(&m_nIp, 4);\n\t\tCVector pos = *(CVector*)&ScriptParams[0];\n\t\tif (pos.z <= -100)\n\t\t\tpos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);\n\t\tUpdateCompareFlag(TheCamera.IsSphereVisible(pos, *(float*)&ScriptParams[3]));\n\t\treturn 0;\n\t}\n\tcase COMMAND_DEBUG_ON:\n\t\tCTheScripts::DbgFlag = true;\n\t\treturn 0;\n\tcase COMMAND_DEBUG_OFF:\n\t\tCTheScripts::DbgFlag = false;\n\t\treturn 0;\n\t/*\n\tcase COMMAND_RETURN_TRUE:\n\t\tUpdateCompareFlag(true);\n\t\treturn 0;\n\tcase COMMAND_RETURN_FALSE:\n\t\tUpdateCompareFlag(false);\n\t\treturn 0;\n\t*/\n\t//case COMMAND_VAR_INT:\n\tdefault:\n\t\tscript_assert(0);\n\t\tbreak;\n\t}\n\treturn -1;\n}\n\nint8 CRunningScript::ProcessCommands200To299(int32 command)\n{\n\tswitch (command) {\n\t/* Special commands.\n\tcase COMMAND_VAR_FLOAT:\n\tcase COMMAND_LVAR_INT:\n\tcase COMMAND_LVAR_FLOAT:\n\tcase COMMAND_LBRACKET:\n\tcase COMMAND_RBRACKET:\n\tcase COMMAND_REPEAT:\n\tcase COMMAND_ENDREPEAT:\n\tcase COMMAND_IF:\n\tcase COMMAND_IFNOT:\n\tcase COMMAND_ELSE:\n\tcase COMMAND_ENDIF:\n\tcase COMMAND_WHILE:\n\tcase COMMAND_WHILENOT:\n\tcase COMMAND_ENDWHILE:\n\t*/\n\tcase COMMAND_ANDOR:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tm_nAndOrState = ScriptParams[0];\n\t\tif (m_nAndOrState == ANDOR_NONE){\n\t\t\tm_bCondResult = false; // pointless\n\t\t}else if (m_nAndOrState >= ANDS_1 && m_nAndOrState <= ANDS_8){\n\t\t\tm_bCondResult = true;\n\t\t\tm_nAndOrState++;\n\t\t}else if (m_nAndOrState >= ORS_1 && m_nAndOrState <= ORS_8){\n\t\t\tm_bCondResult = false;\n\t\t\tm_nAndOrState++;\n\t\t}else{\n\t\t\tscript_assert(0 && \"COMMAND_ANDOR: invalid ANDOR state\");\n\t\t}\n\t\treturn 0;\n\tcase COMMAND_LAUNCH_MISSION:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCRunningScript* pNew = CTheScripts::StartNewScript(ScriptParams[0]);\n\t\tpNew->m_bIsMissionScript = true;\n\t\treturn 0;\n\t}\n\tcase COMMAND_MISSION_HAS_FINISHED:\n\t{\n\t\tif (!m_bIsMissionScript)\n\t\t\treturn 0;\n\t\tCTheScripts::MissionCleanUp.Process();\n\t\treturn 0;\n\t}\n\tcase COMMAND_STORE_CAR_CHAR_IS_IN:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* ped = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(ped);\n\t\tCVehicle* pCurrent = nil;\n\t\tif (ped->bInVehicle) {\n\t\t\tpCurrent = ped->m_pMyVehicle;\n\t\t}\n\t\tscript_assert(pCurrent); // GetIndex(0) doesn't look good\n\t\tint handle = CPools::GetVehiclePool()->GetIndex(pCurrent);\n\t\tif (handle != CTheScripts::StoreVehicleIndex && m_bIsMissionScript){\n\t\t\tCVehicle* pOld = CPools::GetVehiclePool()->GetAt(CTheScripts::StoreVehicleIndex);\n\t\t\tif (pOld){\n\t\t\t\tCCarCtrl::RemoveFromInterestingVehicleList(pOld);\n\t\t\t\tif (pOld->VehicleCreatedBy == MISSION_VEHICLE && CTheScripts::StoreVehicleWasRandom){\n\t\t\t\t\tpOld->VehicleCreatedBy = RANDOM_VEHICLE;\n\t\t\t\t\tpOld->bIsLocked = false;\n\t\t\t\t\tCCarCtrl::NumRandomCars++;\n\t\t\t\t\tCCarCtrl::NumMissionCars--;\n\t\t\t\t\tCTheScripts::MissionCleanUp.RemoveEntityFromList(CTheScripts::StoreVehicleIndex, CLEANUP_CAR);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tCTheScripts::StoreVehicleIndex = handle;\n\t\t\tswitch (pCurrent->VehicleCreatedBy){\n\t\t\tcase RANDOM_VEHICLE:\n\t\t\t\tpCurrent->VehicleCreatedBy = MISSION_VEHICLE;\n\t\t\t\tCCarCtrl::NumMissionCars++;\n\t\t\t\tCCarCtrl::NumRandomCars--;\n\t\t\t\tCTheScripts::StoreVehicleWasRandom = true;\n\t\t\t\tCTheScripts::MissionCleanUp.AddEntityToList(CTheScripts::StoreVehicleIndex, CLEANUP_CAR);\n\t\t\t\tbreak;\n\t\t\tcase PARKED_VEHICLE:\n\t\t\t\tpCurrent->VehicleCreatedBy = MISSION_VEHICLE;\n\t\t\t\tCCarCtrl::NumMissionCars++;\n\t\t\t\tCCarCtrl::NumParkedCars--;\n\t\t\t\tCTheScripts::StoreVehicleWasRandom = true;\n\t\t\t\tCTheScripts::MissionCleanUp.AddEntityToList(CTheScripts::StoreVehicleIndex, CLEANUP_CAR);\n\t\t\t\tbreak;\n\t\t\tcase MISSION_VEHICLE:\n\t\t\tcase PERMANENT_VEHICLE:\n\t\t\t\tCTheScripts::StoreVehicleWasRandom = false;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tScriptParams[0] = CTheScripts::StoreVehicleIndex;\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\tcase COMMAND_STORE_CAR_PLAYER_IS_IN:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* ped = CWorld::Players[ScriptParams[0]].m_pPed;\n\t\tscript_assert(ped);\n\t\tif (!ped->bInVehicle)\n\t\t\treturn 0; // No value written to output variable\n\t\tCVehicle* pCurrent = ped->m_pMyVehicle;\n\t\tscript_assert(pCurrent); // Here pCurrent shouldn't be NULL anyway\n\t\tint handle = CPools::GetVehiclePool()->GetIndex(pCurrent);\n\t\tif (handle != CTheScripts::StoreVehicleIndex && m_bIsMissionScript) {\n\t\t\tCVehicle* pOld = CPools::GetVehiclePool()->GetAt(CTheScripts::StoreVehicleIndex);\n\t\t\tif (pOld){\n\t\t\t\tCCarCtrl::RemoveFromInterestingVehicleList(pOld);\n\t\t\t\tif (pOld->VehicleCreatedBy == MISSION_VEHICLE && CTheScripts::StoreVehicleWasRandom){\n\t\t\t\t\tpOld->VehicleCreatedBy = RANDOM_VEHICLE;\n\t\t\t\t\tpOld->bIsLocked = false;\n\t\t\t\t\tCCarCtrl::NumRandomCars++;\n\t\t\t\t\tCCarCtrl::NumMissionCars--;\n\t\t\t\t\tCTheScripts::MissionCleanUp.RemoveEntityFromList(CTheScripts::StoreVehicleIndex, CLEANUP_CAR);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tCTheScripts::StoreVehicleIndex = handle;\n\t\t\tswitch (pCurrent->VehicleCreatedBy) {\n\t\t\tcase RANDOM_VEHICLE:\n\t\t\t\tpCurrent->VehicleCreatedBy = MISSION_VEHICLE;\n\t\t\t\tCCarCtrl::NumMissionCars++;\n\t\t\t\tCCarCtrl::NumRandomCars--;\n\t\t\t\tCTheScripts::StoreVehicleWasRandom = true;\n\t\t\t\tCTheScripts::MissionCleanUp.AddEntityToList(CTheScripts::StoreVehicleIndex, CLEANUP_CAR);\n\t\t\t\tbreak;\n\t\t\tcase PARKED_VEHICLE:\n\t\t\t\tpCurrent->VehicleCreatedBy = MISSION_VEHICLE;\n\t\t\t\tCCarCtrl::NumMissionCars++;\n\t\t\t\tCCarCtrl::NumParkedCars--;\n\t\t\t\tCTheScripts::StoreVehicleWasRandom = true;\n\t\t\t\tCTheScripts::MissionCleanUp.AddEntityToList(CTheScripts::StoreVehicleIndex, CLEANUP_CAR);\n\t\t\t\tbreak;\n\t\t\tcase MISSION_VEHICLE:\n\t\t\tcase PERMANENT_VEHICLE:\n\t\t\t\tCTheScripts::StoreVehicleWasRandom = false;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tScriptParams[0] = CTheScripts::StoreVehicleIndex;\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_CHAR_IN_CAR:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tCVehicle* pCheckedVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]);\n\t\tCVehicle* pActualVehicle = pPed->bInVehicle ? pPed->m_pMyVehicle : nil;\n\t\tUpdateCompareFlag(pActualVehicle && pActualVehicle == pCheckedVehicle);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_PLAYER_IN_CAR:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCVehicle* pCheckedVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]);\n\t\tCPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;\n\t\tUpdateCompareFlag(pPed->bInVehicle && pPed->m_pMyVehicle == pCheckedVehicle);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_CHAR_IN_MODEL:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tCVehicle* pActualVehicle = pPed->bInVehicle ? pPed->m_pMyVehicle : nil;\n\t\tUpdateCompareFlag(pActualVehicle && pActualVehicle->GetModelIndex() == ScriptParams[1]);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_PLAYER_IN_MODEL:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;\n\t\tUpdateCompareFlag(pPed->bInVehicle && pPed->m_pMyVehicle->GetModelIndex() == ScriptParams[1]);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_CHAR_IN_ANY_CAR:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tUpdateCompareFlag(pPed->bInVehicle && pPed->m_pMyVehicle);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_PLAYER_IN_ANY_CAR:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;\n\t\tUpdateCompareFlag(pPed->bInVehicle && pPed->m_pMyVehicle);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_BUTTON_PRESSED:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tUpdateCompareFlag(GetPadState(ScriptParams[0], ScriptParams[1]) != 0);\n\t\treturn 0;\n\t}\n\t/*\n\tcase COMMAND_GET_PAD_STATE:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tScriptParams[0] = GetPadState(ScriptParams[0], ScriptParams[1]);\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\t*/\n\tcase COMMAND_LOCATE_PLAYER_ANY_MEANS_2D:\n\tcase COMMAND_LOCATE_PLAYER_ON_FOOT_2D:\n\tcase COMMAND_LOCATE_PLAYER_IN_CAR_2D:\n\tcase COMMAND_LOCATE_STOPPED_PLAYER_ANY_MEANS_2D:\n\tcase COMMAND_LOCATE_STOPPED_PLAYER_ON_FOOT_2D:\n\tcase COMMAND_LOCATE_STOPPED_PLAYER_IN_CAR_2D:\n\t\tLocatePlayerCommand(command, &m_nIp);\n\t\treturn 0;\n\tcase COMMAND_LOCATE_PLAYER_ANY_MEANS_CHAR_2D:\n\tcase COMMAND_LOCATE_PLAYER_ON_FOOT_CHAR_2D:\n\tcase COMMAND_LOCATE_PLAYER_IN_CAR_CHAR_2D:\n\t\tLocatePlayerCharCommand(command, &m_nIp);\n\t\treturn 0;\n\tcase COMMAND_LOCATE_CHAR_ANY_MEANS_2D:\n\tcase COMMAND_LOCATE_CHAR_ON_FOOT_2D:\n\tcase COMMAND_LOCATE_CHAR_IN_CAR_2D:\n\tcase COMMAND_LOCATE_STOPPED_CHAR_ANY_MEANS_2D:\n\tcase COMMAND_LOCATE_STOPPED_CHAR_ON_FOOT_2D:\n\tcase COMMAND_LOCATE_STOPPED_CHAR_IN_CAR_2D:\n\t\tLocateCharCommand(command, &m_nIp);\n\t\treturn 0;\n\tcase COMMAND_LOCATE_CHAR_ANY_MEANS_CHAR_2D:\n\tcase COMMAND_LOCATE_CHAR_ON_FOOT_CHAR_2D:\n\tcase COMMAND_LOCATE_CHAR_IN_CAR_CHAR_2D:\n\t\tLocateCharCharCommand(command, &m_nIp);\n\t\treturn 0;\n\tcase COMMAND_LOCATE_PLAYER_ANY_MEANS_3D:\n\tcase COMMAND_LOCATE_PLAYER_ON_FOOT_3D:\n\tcase COMMAND_LOCATE_PLAYER_IN_CAR_3D:\n\tcase COMMAND_LOCATE_STOPPED_PLAYER_ANY_MEANS_3D:\n\tcase COMMAND_LOCATE_STOPPED_PLAYER_ON_FOOT_3D:\n\tcase COMMAND_LOCATE_STOPPED_PLAYER_IN_CAR_3D:\n\t\tLocatePlayerCommand(command, &m_nIp);\n\t\treturn 0;\n\tcase COMMAND_LOCATE_PLAYER_ANY_MEANS_CHAR_3D:\n\tcase COMMAND_LOCATE_PLAYER_ON_FOOT_CHAR_3D:\n\tcase COMMAND_LOCATE_PLAYER_IN_CAR_CHAR_3D:\n\t\tLocatePlayerCharCommand(command, &m_nIp);\n\t\treturn 0;\n\tcase COMMAND_LOCATE_CHAR_ANY_MEANS_3D:\n\tcase COMMAND_LOCATE_CHAR_ON_FOOT_3D:\n\tcase COMMAND_LOCATE_CHAR_IN_CAR_3D:\n\tcase COMMAND_LOCATE_STOPPED_CHAR_ANY_MEANS_3D:\n\tcase COMMAND_LOCATE_STOPPED_CHAR_ON_FOOT_3D:\n\tcase COMMAND_LOCATE_STOPPED_CHAR_IN_CAR_3D:\n\t\tLocateCharCommand(command, &m_nIp);\n\t\treturn 0;\n\tcase COMMAND_LOCATE_CHAR_ANY_MEANS_CHAR_3D:\n\tcase COMMAND_LOCATE_CHAR_ON_FOOT_CHAR_3D:\n\tcase COMMAND_LOCATE_CHAR_IN_CAR_CHAR_3D:\n\t\tLocateCharCharCommand(command, &m_nIp);\n\t\treturn 0;\n\tcase COMMAND_CREATE_OBJECT:\n\t{\n\t\tCollectParameters(&m_nIp, 4);\n\t\tint mi = ScriptParams[0] >= 0 ? ScriptParams[0] : CTheScripts::UsedObjectArray[-ScriptParams[0]].index;\n\t\tCObject* pObj = new CObject(mi, false);\n\t\tpObj->ObjectCreatedBy = MISSION_OBJECT;\n\t\tCVector pos = *(CVector*)&ScriptParams[1];\n\t\tif (pos.z <= MAP_Z_LOW_LIMIT)\n\t\t\tpos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);\n\t\tpos.z += pObj->GetDistanceFromCentreOfMassToBaseOfModel();\n\t\tpObj->SetPosition(pos);\n\t\tpObj->SetOrientation(0.0f, 0.0f, 0.0f);\n\t\tpObj->GetMatrix().UpdateRW();\n\t\tpObj->UpdateRwFrame();\n\t\tCBaseModelInfo* pModelInfo = CModelInfo::GetModelInfo(mi);\n\t\tif (pModelInfo->IsBuilding() && ((CSimpleModelInfo*)pModelInfo)->m_isBigBuilding)\n\t\t\tpObj->SetupBigBuilding();\n\t\tCTheScripts::ClearSpaceForMissionEntity(pos, pObj);\n\t\tCWorld::Add(pObj);\n\t\tScriptParams[0] = CPools::GetObjectPool()->GetIndex(pObj);\n\t\tStoreParameters(&m_nIp, 1);\n\t\tif (m_bIsMissionScript)\n\t\t\tCTheScripts::MissionCleanUp.AddEntityToList(ScriptParams[0], CLEANUP_OBJECT);\n\t\treturn 0;\n\t}\n\tcase COMMAND_DELETE_OBJECT:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCObject* pObj = CPools::GetObjectPool()->GetAt(ScriptParams[0]);\n\t\tif (pObj){\n\t\t\tCWorld::Remove(pObj);\n\t\t\tCWorld::RemoveReferencesToDeletedObject(pObj);\n\t\t\tdelete pObj;\n\t\t}\n\t\tif (m_bIsMissionScript)\n\t\t\tCTheScripts::MissionCleanUp.RemoveEntityFromList(ScriptParams[0], CLEANUP_OBJECT);\n\t\treturn 0;\n\t}\n\tcase COMMAND_ADD_SCORE:\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCWorld::Players[ScriptParams[0]].m_nMoney += ScriptParams[1];\n\t\tif (CWorld::Players[ScriptParams[0]].m_nMoney < 0)\n\t\t\tCWorld::Players[ScriptParams[0]].m_nMoney = 0;\n\t\treturn 0;\n\tcase COMMAND_IS_SCORE_GREATER:\n\t\tCollectParameters(&m_nIp, 2);\n\t\tUpdateCompareFlag(CWorld::Players[ScriptParams[0]].m_nMoney > ScriptParams[1]);\n\t\treturn 0;\n\tcase COMMAND_STORE_SCORE:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tScriptParams[0] = CWorld::Players[ScriptParams[0]].m_nMoney;\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\tcase COMMAND_GIVE_REMOTE_CONTROLLED_CAR_TO_PLAYER:\n\t{\n\t\tCollectParameters(&m_nIp, 5);\n\t\tCVector pos = *(CVector*)&ScriptParams[1];\n\t\tif (pos.z <= MAP_Z_LOW_LIMIT)\n\t\t\tpos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);\n\t\tCRemote::GivePlayerRemoteControlledCar(pos.x, pos.y, pos.z, DEGTORAD(*(float*)&ScriptParams[4]), MI_RCBANDIT);\n\t\treturn 0;\n\t}\n\tcase COMMAND_ALTER_WANTED_LEVEL:\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCWorld::Players[ScriptParams[0]].m_pPed->SetWantedLevel(ScriptParams[1]);\n\t\treturn 0;\n\tcase COMMAND_ALTER_WANTED_LEVEL_NO_DROP:\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCWorld::Players[ScriptParams[0]].m_pPed->SetWantedLevelNoDrop(ScriptParams[1]);\n\t\treturn 0;\n\tcase COMMAND_IS_WANTED_LEVEL_GREATER:\n\t\tCollectParameters(&m_nIp, 2);\n\t\tUpdateCompareFlag(CWorld::Players[ScriptParams[0]].m_pPed->m_pWanted->GetWantedLevel() > ScriptParams[1]);\n\t\treturn 0;\n\tcase COMMAND_CLEAR_WANTED_LEVEL:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCWorld::Players[ScriptParams[0]].m_pPed->SetWantedLevel(0);\n\t\treturn 0;\n\tcase COMMAND_SET_DEATHARREST_STATE:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tm_bDeatharrestEnabled = (ScriptParams[0] == 1);\n\t\treturn 0;\n\tcase COMMAND_HAS_DEATHARREST_BEEN_EXECUTED:\n\t\tUpdateCompareFlag(m_bDeatharrestExecuted);\n\t\treturn 0;\n\t/*\n\tcase COMMAND_ADD_AMMO_TO_PLAYER:\n\t{\n\t\tCollectParameters(&m_nIp, 3);\n\t\tCWorld::Players[ScriptParams[0]].m_pPed->GrantAmmo((eWeaponType)ScriptParams[1], ScriptParams[2]);\n\t\treturn 0;\n\t}\n\t*/\n\tcase COMMAND_ADD_AMMO_TO_CHAR:\n\t{\n\t\tCollectParameters(&m_nIp, 3);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tpPed->GrantAmmo((eWeaponType)ScriptParams[1], ScriptParams[2]);\n\t\treturn 0;\n\t}\n\t//case COMMAND_ADD_AMMO_TO_CAR:\n\t//case COMMAND_IS_PLAYER_STILL_ALIVE:\n\tcase COMMAND_IS_PLAYER_DEAD:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tUpdateCompareFlag(CWorld::Players[ScriptParams[0]].m_WBState == WBSTATE_WASTED);\n\t\treturn 0;\n\tcase COMMAND_IS_CHAR_DEAD:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tUpdateCompareFlag(!pPed || pPed->DyingOrDead());\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_CAR_DEAD:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tUpdateCompareFlag(!pVehicle || pVehicle->GetStatus() == STATUS_WRECKED || pVehicle->bIsDrowning);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_CHAR_THREAT_SEARCH:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tpPed->m_fearFlags |= ScriptParams[1];\n\t\treturn 0;\n\t}\n\t//case COMMAND_SET_CHAR_THREAT_REACTION:\n\tcase COMMAND_SET_CHAR_OBJ_NO_OBJ:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tpPed->bScriptObjectiveCompleted = false;\n\t\tpPed->ClearObjective();\n\t\treturn 0;\n\t}\n\t//case COMMAND_ORDER_DRIVER_OUT_OF_CAR:\n\t//case COMMAND_ORDER_CHAR_TO_DRIVE_CAR:\n\t//case COMMAND_ADD_PATROL_POINT:\n\t//case COMMAND_IS_PLAYER_IN_GANGZONE:\n\tcase COMMAND_IS_PLAYER_IN_ZONE:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPlayerInfo* pPlayer = &CWorld::Players[ScriptParams[0]];\n\t\tchar label[12];\n\t\tCTheScripts::ReadTextLabelFromScript(&m_nIp, label);\n\t\tint zoneToCheck = CTheZones::FindZoneByLabelAndReturnIndex(label, ZONE_DEFAULT);\n\t\tif (zoneToCheck != -1)\n\t\t\tm_nIp += KEY_LENGTH_IN_SCRIPT; /* why only if zone != 1? */\n\t\tCVector pos = pPlayer->GetPos();\n\t\tCZone* pZone = CTheZones::GetNavigationZone(zoneToCheck);\n\t\tUpdateCompareFlag(CTheZones::PointLiesWithinZone(&pos, pZone));\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_PLAYER_PRESSING_HORN:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tUpdateCompareFlag(CWorld::Players[ScriptParams[0]].m_pPed->GetPedState() == PED_DRIVING &&\n\t\t\tCPad::GetPad(ScriptParams[0])->GetHorn());\n\t\treturn 0;\n\tcase COMMAND_HAS_CHAR_SPOTTED_PLAYER:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tUpdateCompareFlag(pPed->OurPedCanSeeThisOne(CWorld::Players[ScriptParams[1]].m_pPed));\n\t\treturn 0;\n\t}\n\t//case COMMAND_ORDER_CHAR_TO_BACKDOOR:\n\t//case COMMAND_ADD_CHAR_TO_GANG:\n\tcase COMMAND_IS_CHAR_OBJECTIVE_PASSED:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tUpdateCompareFlag(pPed->bScriptObjectiveCompleted);\n\t\treturn 0;\n\t}\n\t/* Not implemented.\n\tcase COMMAND_SET_CHAR_DRIVE_AGGRESSION:\n\tcase COMMAND_SET_CHAR_MAX_DRIVESPEED:\n\t*/\n\tcase COMMAND_CREATE_CHAR_INSIDE_CAR:\n\t{\n\t\tCollectParameters(&m_nIp, 3);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tswitch (ScriptParams[2]) {\n\t\tcase MI_COP:\n\t\t\tif (ScriptParams[1] == PEDTYPE_COP)\n\t\t\t\tScriptParams[2] = COP_STREET;\n\t\t\tbreak;\n\t\tcase MI_SWAT:\n\t\t\tif (ScriptParams[1] == PEDTYPE_COP)\n\t\t\t\tScriptParams[2] = COP_SWAT;\n\t\t\tbreak;\n\t\tcase MI_FBI:\n\t\t\tif (ScriptParams[1] == PEDTYPE_COP)\n\t\t\t\tScriptParams[2] = COP_FBI;\n\t\t\tbreak;\n\t\tcase MI_ARMY:\n\t\t\tif (ScriptParams[1] == PEDTYPE_COP)\n\t\t\t\tScriptParams[2] = COP_ARMY;\n\t\t\tbreak;\n\t\tcase MI_MEDIC:\n\t\t\tif (ScriptParams[1] == PEDTYPE_EMERGENCY)\n\t\t\t\tScriptParams[2] = PEDTYPE_EMERGENCY;\n\t\t\tbreak;\n\t\tcase MI_FIREMAN:\n\t\t\tif (ScriptParams[1] == PEDTYPE_FIREMAN)\n\t\t\t\tScriptParams[2] = PEDTYPE_FIREMAN;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\t\tCPed* pPed;\n\t\tif (ScriptParams[1] == PEDTYPE_COP)\n\t\t\tpPed = new CCopPed((eCopType)ScriptParams[2]);\n\t\telse if (ScriptParams[1] == PEDTYPE_EMERGENCY || ScriptParams[1] == PEDTYPE_FIREMAN)\n\t\t\tpPed = new CEmergencyPed(ScriptParams[2]);\n\t\telse\n\t\t\tpPed = new CCivilianPed((ePedType)ScriptParams[1], ScriptParams[2]);\n\t\tpPed->CharCreatedBy = MISSION_CHAR;\n\t\tpPed->bRespondsToThreats = false;\n\t\tpPed->bAllowMedicsToReviveMe = false;\n\t\tpPed->bIsPlayerFriend = false;\n\t\tif (pVehicle->bIsBus)\n\t\t\tpPed->bRenderPedInCar = false;\n\t\tpPed->SetPosition(pVehicle->GetPosition());\n\t\tpPed->SetOrientation(0.0f, 0.0f, 0.0f);\n\t\tpPed->SetPedState(PED_DRIVING);\n\t\tCPopulation::ms_nTotalMissionPeds++;\n\t\tscript_assert(!pVehicle->pDriver);\n\t\tpVehicle->pDriver = pPed;\n\t\tpVehicle->pDriver->RegisterReference((CEntity**)&pVehicle->pDriver);\n\t\tpPed->m_pMyVehicle = pVehicle;\n\t\tpPed->m_pMyVehicle->RegisterReference((CEntity**)&pPed->m_pMyVehicle);\n\t\tpPed->bInVehicle = true;\n\t\tpVehicle->SetStatus(STATUS_PHYSICS);\n\t\tif (!pVehicle->IsBoat())\n\t\t\tpVehicle->AutoPilot.m_nCarMission = MISSION_CRUISE;\n\t\tpVehicle->bEngineOn = true;\n\t\tpPed->bUsesCollision = false;\n\t\tpPed->AddInCarAnims(pVehicle, true);\n\t\tpPed->m_nZoneLevel = CTheZones::GetLevelFromPosition(&pPed->GetPosition());\n\t\tCWorld::Add(pPed);\n\t\tScriptParams[0] = CPools::GetPedPool()->GetIndex(pPed);\n\t\tStoreParameters(&m_nIp, 1);\n\t\tif (m_bIsMissionScript)\n\t\t\tCTheScripts::MissionCleanUp.AddEntityToList(ScriptParams[0], CLEANUP_CHAR);\n\t\treturn 0;\n\t}\n\tcase COMMAND_WARP_PLAYER_FROM_CAR_TO_COORD:\n\t{\n\t\tCollectParameters(&m_nIp, 4);\n\t\tCVector pos = *(CVector*)&ScriptParams[1];\n\t\tCPlayerInfo* pPlayer = &CWorld::Players[ScriptParams[0]];\n\t\tif (pos.z <= MAP_Z_LOW_LIMIT)\n\t\t\tpos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);\n\t\tif (pPlayer->m_pPed->bInVehicle){\n\t\t\tscript_assert(pPlayer->m_pPed->m_pMyVehicle);\n\t\t\tif (pPlayer->m_pPed->m_pMyVehicle->bIsBus)\n\t\t\t\tpPlayer->m_pPed->bRenderPedInCar = true;\n\t\t\tif (pPlayer->m_pPed->m_pMyVehicle->pDriver == pPlayer->m_pPed){\n\t\t\t\tpPlayer->m_pPed->m_pMyVehicle->RemoveDriver();\n\t\t\t\tpPlayer->m_pPed->m_pMyVehicle->SetStatus(STATUS_ABANDONED);\n\t\t\t\tpPlayer->m_pPed->m_pMyVehicle->bEngineOn = false;\n\t\t\t\tpPlayer->m_pPed->m_pMyVehicle->AutoPilot.m_nCruiseSpeed = 0;\n\t\t\t}else{\n\t\t\t\tpPlayer->m_pPed->m_pMyVehicle->RemovePassenger(pPlayer->m_pPed);\n\t\t\t}\n\t\t}\n\t\tpPlayer->m_pPed->RemoveInCarAnims();\n\t\tpPlayer->m_pPed->bInVehicle = false;\n\t\tpPlayer->m_pPed->m_pMyVehicle = nil;\n\t\tpPlayer->m_pPed->SetPedState(PED_IDLE);\n\t\tpPlayer->m_pPed->bUsesCollision = true;\n\t\tpPlayer->m_pPed->SetMoveSpeed(0.0f, 0.0f, 0.0f);\n\t\tpPlayer->m_pPed->ReplaceWeaponWhenExitingVehicle();\n\t\tif (pPlayer->m_pPed->m_pVehicleAnim)\n\t\t\tpPlayer->m_pPed->m_pVehicleAnim->blendDelta = -1000.0f;\n\t\tpPlayer->m_pPed->m_pVehicleAnim = nil;\n\t\tpPlayer->m_pPed->SetMoveState(PEDMOVE_NONE);\n\t\tCAnimManager::BlendAnimation(pPlayer->m_pPed->GetClump(), pPlayer->m_pPed->m_animGroup, ANIM_STD_IDLE, 1000.0f);\n\t\tpPlayer->m_pPed->RestartNonPartialAnims();\n\t\tAudioManager.PlayerJustLeftCar();\n\t\tpos.z += pPlayer->m_pPed->GetDistanceFromCentreOfMassToBaseOfModel();\n\t\tpPlayer->m_pPed->Teleport(pos);\n\t\tCTheScripts::ClearSpaceForMissionEntity(pos, pPlayer->m_pPed);\n\t\treturn 0;\n\t}\n\t//case COMMAND_MAKE_CHAR_DO_NOTHING:\n\tdefault:\n\t\tscript_assert(0);\n\t\tbreak;\n\t}\n\treturn -1;\n}\n\n#ifdef MISSION_REPLAY\n\nbool CRunningScript::CanAllowMissionReplay()\n{\n\tif (AllowMissionReplay)\n\t\treturn false;\n\tif (CStats::LastMissionPassedName[0] == '\\0')\n\t\treturn false;\n\tfor (int i = 0; i < ARRAY_SIZE(nonMissionScripts); i++) {\n\t\tif (strcmp(m_abScriptName, nonMissionScripts[i]) == 0)\n\t\t\treturn false;\n\t}\n\treturn true;\n}\n\nuint32 AddExtraDeathDelay()\n{\n\tif (missionRetryScriptIndex == 63)\n\t\treturn 7000;\n\tif (missionRetryScriptIndex == 64)\n\t\treturn 4000;\n\treturn 1000;\n}\n\nvoid RetryMission(int type, int unk)\n{\n\tif (type == 0) {\n\t\tdoingMissionRetry = true;\n\t\tFrontEndMenuManager.m_nCurrScreen = 57; // MENUPAGE_MISSION_RETRY\n\t\tFrontEndMenuManager.RequestFrontEndStartUp();\n\t}\n\telse if (type == 2) {\n\t\tdoingMissionRetry = false;\n\t\tAllowMissionReplay = 6;\n\t\tCTheScripts::MissionCleanUp.Process();\n\t}\n}\n\n#endif\n\n#ifdef MISSION_SWITCHER\nvoid\nCTheScripts::SwitchToMission(int32 mission)\n{\n\tfor (CRunningScript* pScript = CTheScripts::pActiveScripts; pScript != nil; pScript = pScript->GetNext()) {\n\t\tif (!pScript->m_bIsMissionScript || !pScript->m_bDeatharrestEnabled) {\n\t\t\tcontinue;\n\t\t}\n\t\twhile (pScript->m_nStackPointer > 0)\n\t\t\t--pScript->m_nStackPointer;\n\n\t\tpScript->m_nIp = pScript->m_anStack[pScript->m_nStackPointer];\n\t\t*(int32*)&CTheScripts::ScriptSpace[CTheScripts::OnAMissionFlag] = 0;\n\t\tpScript->m_nWakeTime = 0;\n\t\tpScript->m_bDeatharrestExecuted = true;\n\n\t\twhile (!pScript->ProcessOneCommand());\n\n\t\tCMessages::ClearMessages();\n\t}\n\n\tif (CTheScripts::NumberOfExclusiveMissionScripts > 0 && mission <= UINT16_MAX - 2)\n\t\treturn;\n\n#ifdef MISSION_REPLAY\n\tmissionRetryScriptIndex = mission;\n\tif (missionRetryScriptIndex == 19)\n\t\tCStats::LastMissionPassedName[0] = '\\0';\n#endif\n\tCTimer::Suspend();\n\tint offset = CTheScripts::MultiScriptArray[mission];\n#ifdef USE_DEBUG_SCRIPT_LOADER\n\tCFileMgr::ChangeDir(\"\\\\data\\\\\");\n\tint handle = CFileMgr::OpenFile(scriptfile, \"rb\");\n\tCFileMgr::ChangeDir(\"\\\\\");\n#else\n\tCFileMgr::ChangeDir(\"\\\\\");\n\tint handle = CFileMgr::OpenFile(\"data\\\\main.scm\", \"rb\");\n#endif\n\tCFileMgr::Seek(handle, offset, 0);\n\tCFileMgr::Read(handle, (const char*)&CTheScripts::ScriptSpace[SIZE_MAIN_SCRIPT], SIZE_MISSION_SCRIPT);\n\tCFileMgr::CloseFile(handle);\n\tCRunningScript* pMissionScript = CTheScripts::StartNewScript(SIZE_MAIN_SCRIPT);\n\tCTimer::Resume();\n\tpMissionScript->m_bIsMissionScript = true;\n\tpMissionScript->m_bMissionFlag = true;\n\tCTheScripts::bAlreadyRunningAMissionScript = true;\n\tCGameLogic::ClearShortCut();\n}\n#endif\n"
  },
  {
    "path": "src/control/Script.h",
    "content": "#pragma once\n#include \"Font.h\"\n#include \"PedType.h\"\n#include \"Text.h\"\n#include \"Sprite2d.h\"\n\nclass CEntity;\nclass CBuilding;\nclass CPhysical;\nclass CVehicle;\nclass CPed;\nclass CObject;\nclass CPlayerInfo;\n\nclass CRunningScript;\n\nextern int32 ScriptParams[32];\n\nvoid FlushLog();\n#define script_assert(_Expression) FlushLog(); assert(_Expression);\n\n#define PICKUP_PLACEMENT_OFFSET (0.5f)\n#define PED_FIND_Z_OFFSET (5.0f)\n#define COP_PED_FIND_Z_OFFSET (10.0f)\n\n#define UPSIDEDOWN_UP_THRESHOLD (-0.97f)\n#define UPSIDEDOWN_MOVE_SPEED_THRESHOLD (0.01f)\n#define UPSIDEDOWN_TURN_SPEED_THRESHOLD (0.02f)\n#define UPSIDEDOWN_TIMER_THRESHOLD (1000)\n\n#define SPHERE_MARKER_R (252)\n#define SPHERE_MARKER_G (138)\n#define SPHERE_MARKER_B (242)\n#define SPHERE_MARKER_A (228)\n#define SPHERE_MARKER_PULSE_PERIOD 2048\n#define SPHERE_MARKER_PULSE_FRACTION 0.1f\n\n#ifdef USE_PRECISE_MEASUREMENT_CONVERTION\n#define MILES_IN_METER (0.000621371192f)\n#define METERS_IN_FOOT (0.3048f)\n#define FEET_IN_METER (3.28084f)\n#else\n#define MILES_IN_METER (1 / 1670.f)\n#define METERS_IN_FOOT (0.3f)\n#define FEET_IN_METER (3.33f)\n#endif\n\n#define KEY_LENGTH_IN_SCRIPT (8)\n\n//#define GTA_SCRIPT_COLLECTIVE\n\nstruct intro_script_rectangle \n{\n\tbool m_bIsUsed;\n\tbool m_bBeforeFade;\n\tint16 m_nTextureId;\n\tCRect m_sRect;\n\tCRGBA m_sColor;\n\t\n\tintro_script_rectangle() { }\n\t~intro_script_rectangle() { }\n};\n\nVALIDATE_SIZE(intro_script_rectangle, 0x18);\n\nenum {\n\tSCRIPT_TEXT_MAX_LENGTH = 100\n};\n\nstruct intro_text_line \n{\n\tfloat m_fScaleX;\n\tfloat m_fScaleY;\n\tCRGBA m_sColor;\n\tbool m_bJustify;\n\tbool m_bCentered;\n\tbool m_bBackground;\n\tbool m_bBackgroundOnly;\n\tfloat m_fWrapX;\n\tfloat m_fCenterSize;\n\tCRGBA m_sBackgroundColor;\n\tbool m_bTextProportional;\n\tbool m_bTextBeforeFade;\n\tbool m_bRightJustify;\n\tint32 m_nFont;\n\tfloat m_fAtX;\n\tfloat m_fAtY;\n\twchar m_Text[SCRIPT_TEXT_MAX_LENGTH];\n\n\tintro_text_line() { }\n\t~intro_text_line() { }\n\t\n\tvoid Reset()\n\t{\n\t\tm_fScaleX = 0.48f;\n\t\tm_fScaleY = 1.12f;\n\t\tm_sColor = CRGBA(225, 225, 225, 255);\n\t\tm_bJustify = false;\n\t\tm_bRightJustify = false;\n\t\tm_bCentered = false;\n\t\tm_bBackground = false;\n\t\tm_bBackgroundOnly = false;\n\t\tm_fWrapX = 182.0f;\n\t\tm_fCenterSize = DEFAULT_SCREEN_WIDTH;\n\t\tm_sBackgroundColor = CRGBA(128, 128, 128, 128);\n\t\tm_bTextProportional = true;\n\t\tm_bTextBeforeFade = false;\n\t\tm_nFont = FONT_STANDARD;\n\t\tm_fAtX = 0.0f;\n\t\tm_fAtY = 0.0f;\n\t\tmemset(&m_Text, 0, sizeof(m_Text));\n\t}\n};\n\nVALIDATE_SIZE(intro_text_line, 0x414);\n\nstruct script_sphere_struct\n{\n\tbool m_bInUse;\n\tuint16 m_Index;\n\tuint32 m_Id;\n\tCVector m_vecCenter;\n\tfloat m_fRadius;\n\t\n\tscript_sphere_struct() { }\n};\n\nstruct CStoredLine\n{\n\tCVector vecInf;\n\tCVector vecSup;\n\tuint32 color1;\n\tuint32 color2;\n};\n\nenum {\n\tCLEANUP_UNUSED = 0,\n\tCLEANUP_CAR,\n\tCLEANUP_CHAR,\n\tCLEANUP_OBJECT\n};\n\nstruct cleanup_entity_struct\n{\n\tuint8 type;\n\tint32 id;\n};\n\nenum {\n\tMAX_CLEANUP = 50,\n\tMAX_UPSIDEDOWN_CAR_CHECKS = 6,\n\tMAX_STUCK_CAR_CHECKS = 16\n};\n\nclass CMissionCleanup\n{\npublic:\n\tcleanup_entity_struct m_sEntities[MAX_CLEANUP];\n\tuint8 m_nCount;\n\n\tCMissionCleanup();\n\n\tvoid Init();\n\tcleanup_entity_struct* FindFree();\n\tvoid AddEntityToList(int32, uint8);\n\tvoid RemoveEntityFromList(int32, uint8);\n\tvoid Process();\n\tvoid CheckIfCollisionHasLoadedForMissionObjects();\n};\n\nstruct upsidedown_car_data\n{\n\tint32 m_nVehicleIndex;\n\tuint32 m_nUpsideDownTimer;\n};\n\nclass CUpsideDownCarCheck\n{\n\tupsidedown_car_data m_sCars[MAX_UPSIDEDOWN_CAR_CHECKS];\n\npublic:\n\tvoid Init();\n\tbool IsCarUpsideDown(int32);\n\tbool IsCarUpsideDown(CVehicle*);\n\tvoid UpdateTimers();\n\tbool AreAnyCarsUpsideDown();\n\tvoid AddCarToCheck(int32);\n\tvoid RemoveCarFromCheck(int32);\n\tbool HasCarBeenUpsideDownForAWhile(int32);\n};\n\nstruct stuck_car_data\n{\n\tint32 m_nVehicleIndex;\n\tCVector m_vecPos;\n\tint32 m_nLastCheck;\n\tfloat m_fRadius;\n\tuint32 m_nStuckTime;\n\tbool m_bStuck;\n\n\tstuck_car_data() { }\n\tvoid Reset();\n};\n\nclass CStuckCarCheck\n{\n\tstuck_car_data m_sCars[MAX_STUCK_CAR_CHECKS];\n\npublic:\n\tvoid Init();\n\tvoid Process();\n\tvoid AddCarToCheck(int32, float, uint32);\n\tvoid RemoveCarFromCheck(int32);\n\tbool HasCarBeenStuckForAWhile(int32);\n};\n\nenum {\n\tARGUMENT_END = 0,\n\tARGUMENT_INT32,\n\tARGUMENT_GLOBALVAR,\n\tARGUMENT_LOCALVAR,\n\tARGUMENT_INT8,\n\tARGUMENT_INT16,\n\tARGUMENT_FLOAT\n};\n\nstruct tCollectiveData\n{\n\tint32 colIndex;\n\tint32 pedIndex;\n};\n\nenum {\n\tUSED_OBJECT_NAME_LENGTH = 24\n};\n\nstruct tUsedObject\n{\n\tchar name[USED_OBJECT_NAME_LENGTH];\n\tint32 index;\n};\n\nstruct tBuildingSwap\n{\n\tCBuilding* m_pBuilding;\n\tint32 m_nNewModel;\n\tint32 m_nOldModel;\n};\n\n\nenum {\n\tMAX_STACK_DEPTH = 6,\n\tNUM_LOCAL_VARS = 16,\n\tNUM_TIMERS = 2\n};\n\nclass CRunningScript\n{\n\tenum {\n\t\tANDOR_NONE = 0,\n\t\tANDS_1 = 1,\n\t\tANDS_2,\n\t\tANDS_3,\n\t\tANDS_4,\n\t\tANDS_5,\n\t\tANDS_6,\n\t\tANDS_7,\n\t\tANDS_8,\n\t\tORS_1 = 21,\n\t\tORS_2,\n\t\tORS_3,\n\t\tORS_4,\n\t\tORS_5,\n\t\tORS_6,\n\t\tORS_7,\n\t\tORS_8\n\t};\n\npublic:\n\tCRunningScript* next;\n\tCRunningScript* prev;\n\tchar m_abScriptName[8];\n\tuint32 m_nIp;\n\tuint32 m_anStack[MAX_STACK_DEPTH];\n\tuint16 m_nStackPointer;\n\tint32 m_anLocalVariables[NUM_LOCAL_VARS + NUM_TIMERS];\n\tbool m_bIsActive;\n\tbool m_bCondResult;\n\tbool m_bIsMissionScript;\n\tbool m_bSkipWakeTime;\n\tuint32 m_nWakeTime;\n\tuint16 m_nAndOrState;\n\tbool m_bNotFlag;\n\tbool m_bDeatharrestEnabled;\n\tbool m_bDeatharrestExecuted;\n\tbool m_bMissionFlag;\n\npublic:\n\tvoid SetIP(uint32 ip) { m_nIp = ip; }\n\tCRunningScript* GetNext() const { return next; }\n\n\tvoid Save(uint8*& buf);\n\tvoid Load(uint8*& buf);\n\n\tvoid UpdateTimers(float timeStep) {\n\t\tm_anLocalVariables[NUM_LOCAL_VARS] += timeStep;\n\t\tm_anLocalVariables[NUM_LOCAL_VARS + 1] += timeStep;\n\t}\n\n\tvoid Init();\n\tvoid Process();\n\n\tvoid RemoveScriptFromList(CRunningScript**);\n\tvoid AddScriptToList(CRunningScript**);\n\n\tstatic const uint32 nSaveStructSize;\n\n\tvoid CollectParameters(uint32*, int16);\n\tint32 CollectNextParameterWithoutIncreasingPC(uint32);\n\tint32* GetPointerToScriptVariable(uint32*, int16);\n\tvoid StoreParameters(uint32*, int16);\n\n\tint8 ProcessOneCommand();\n\tvoid DoDeatharrestCheck();\n\tvoid UpdateCompareFlag(bool);\n\tint16 GetPadState(uint16, uint16);\n\n\tint8 ProcessCommands0To99(int32);\n\tint8 ProcessCommands100To199(int32);\n\tint8 ProcessCommands200To299(int32);\n\tint8 ProcessCommands300To399(int32);\n\tint8 ProcessCommands400To499(int32);\n\tint8 ProcessCommands500To599(int32);\n\tint8 ProcessCommands600To699(int32);\n\tint8 ProcessCommands700To799(int32);\n\tint8 ProcessCommands800To899(int32);\n\tint8 ProcessCommands900To999(int32);\n\tint8 ProcessCommands1000To1099(int32);\n\tint8 ProcessCommands1100To1199(int32);\n\tint8 ProcessCommands1200To1299(int32);\n\tint8 ProcessCommands1300To1399(int32);\n\tint8 ProcessCommands1400To1499(int32);\n\n\tvoid LocatePlayerCommand(int32, uint32*);\n\tvoid LocatePlayerCharCommand(int32, uint32*);\n\tvoid LocatePlayerCarCommand(int32, uint32*);\n\tvoid LocateCharCommand(int32, uint32*);\n\tvoid LocateCharCharCommand(int32, uint32*);\n\tvoid LocateCharCarCommand(int32, uint32*);\n\tvoid LocateCharObjectCommand(int32, uint32*);\n\tvoid LocateCarCommand(int32, uint32*);\n\tvoid LocateSniperBulletCommand(int32, uint32*);\n\tvoid PlayerInAreaCheckCommand(int32, uint32*);\n\tvoid PlayerInAngledAreaCheckCommand(int32, uint32*);\n\tvoid CharInAreaCheckCommand(int32, uint32*);\n\tvoid CarInAreaCheckCommand(int32, uint32*);\n\tvoid LocateObjectCommand(int32, uint32*);\n\tvoid ObjectInAreaCheckCommand(int32, uint32*);\n\n#ifdef GTA_SCRIPT_COLLECTIVE\n\tvoid LocateCollectiveCommand(int32, uint32*);\n\tvoid LocateCollectiveCharCommand(int32, uint32*);\n\tvoid LocateCollectiveCarCommand(int32, uint32*);\n\tvoid LocateCollectivePlayerCommand(int32, uint32*);\n\tvoid CollectiveInAreaCheckCommand(int32, uint32*);\n#endif\n\n#ifdef MISSION_REPLAY\n\tbool CanAllowMissionReplay();\n#endif\n\n#ifdef USE_ADVANCED_SCRIPT_DEBUG_OUTPUT\n\tint CollectParameterForDebug(char* buf, bool& var);\n\tvoid GetStoredParameterForDebug(char* buf);\n#endif\n\n\tfloat LimitAngleOnCircle(float angle) { return angle < 0.0f ? angle + 360.0f : angle; }\n\n\tbool ThisIsAValidRandomCop(uint32 mi, int cop, int swat, int fbi, int army, int miami);\n\tbool ThisIsAValidRandomPed(uint32 pedtype, int civ, int gang, int criminal);\n\n\tbool CheckDamagedWeaponType(int32 actual, int32 type);\n\t\n};\n\n\nenum {\n\tVAR_LOCAL = 1,\n\tVAR_GLOBAL = 2,\n};\n\nenum {\n#ifdef PS2\n\tSIZE_MAIN_SCRIPT = 205512,\n#else\n\tSIZE_MAIN_SCRIPT = 225512,\n#endif\n\tSIZE_MISSION_SCRIPT = 35000,\n\tSIZE_SCRIPT_SPACE = SIZE_MAIN_SCRIPT + SIZE_MISSION_SCRIPT\n};\n\nenum {\n\tMAX_NUM_SCRIPTS = 128,\n\tMAX_NUM_INTRO_TEXT_LINES = 48,\n\tMAX_NUM_INTRO_RECTANGLES = 16,\n\tMAX_NUM_SCRIPT_SRPITES = 16,\n\tMAX_NUM_SCRIPT_SPHERES = 16,\n\tMAX_NUM_USED_OBJECTS = 220,\n\tMAX_NUM_MISSION_SCRIPTS = 120,\n\tMAX_NUM_BUILDING_SWAPS = 25,\n\tMAX_NUM_INVISIBILITY_SETTINGS = 20,\n\tMAX_NUM_STORED_LINES = 1024\n};\n\nclass CTheScripts\n{\npublic:\n\tstatic uint8 ScriptSpace[SIZE_SCRIPT_SPACE];\n\tstatic CRunningScript ScriptsArray[MAX_NUM_SCRIPTS];\n\tstatic intro_text_line IntroTextLines[MAX_NUM_INTRO_TEXT_LINES];\n\tstatic intro_script_rectangle IntroRectangles[MAX_NUM_INTRO_RECTANGLES];\n\tstatic CSprite2d ScriptSprites[MAX_NUM_SCRIPT_SRPITES];\n\tstatic script_sphere_struct ScriptSphereArray[MAX_NUM_SCRIPT_SPHERES];\n\tstatic tUsedObject UsedObjectArray[MAX_NUM_USED_OBJECTS];\n\tstatic int32 MultiScriptArray[MAX_NUM_MISSION_SCRIPTS];\n\tstatic tBuildingSwap BuildingSwapArray[MAX_NUM_BUILDING_SWAPS];\n\tstatic CEntity* InvisibilitySettingArray[MAX_NUM_INVISIBILITY_SETTINGS];\n\tstatic CStoredLine aStoredLines[MAX_NUM_STORED_LINES];\n\tstatic bool DbgFlag;\n\tstatic uint32 OnAMissionFlag;\n\tstatic CMissionCleanup MissionCleanUp;\n\tstatic CStuckCarCheck StuckCars;\n\tstatic CUpsideDownCarCheck UpsideDownCars;\n\tstatic int32 StoreVehicleIndex;\n\tstatic bool StoreVehicleWasRandom;\n\tstatic CRunningScript *pIdleScripts;\n\tstatic CRunningScript *pActiveScripts;\n\tstatic int32 NextFreeCollectiveIndex;\n\tstatic int32 LastRandomPedId;\n\tstatic uint16 NumberOfUsedObjects;\n\tstatic bool bAlreadyRunningAMissionScript;\n\tstatic bool bUsingAMultiScriptFile;\n\tstatic uint16 NumberOfMissionScripts;\n\tstatic uint32 LargestMissionScriptSize;\n\tstatic uint32 MainScriptSize;\n\tstatic uint8 FailCurrentMission;\n\tstatic uint16 NumScriptDebugLines;\n\tstatic uint16 NumberOfIntroRectanglesThisFrame;\n\tstatic uint16 NumberOfIntroTextLinesThisFrame;\n\tstatic uint8 UseTextCommands;\n\tstatic uint16 CommandsExecuted;\n\tstatic uint16 ScriptsUpdated;\n\tstatic uint32 LastMissionPassedTime;\n\tstatic uint16 NumberOfExclusiveMissionScripts;\n#if (defined GTA_PC && !defined GTAVC_JP_PATCH || defined GTA_XBOX || defined SUPPORT_XBOX_SCRIPT || defined GTA_MOBILE || defined SUPPORT_MOBILE_SCRIPT)\n#define CARDS_IN_SUIT (13)\n#define NUM_SUITS (4)\n#define MAX_DECKS (6)\n#define CARDS_IN_DECK (CARDS_IN_SUIT * NUM_SUITS)\n#define CARDS_IN_STACK (CARDS_IN_DECK * MAX_DECKS)\n\tstatic int16 CardStack[CARDS_IN_STACK];\n\tstatic int16 CardStackPosition;\n#endif\n\tstatic bool bPlayerIsInTheStatium;\n\tstatic uint8 RiotIntensity;\n\tstatic bool bPlayerHasMetDebbieHarry;\n\n\tstatic void Init();\n\tstatic void Process();\n\n\tstatic CRunningScript* StartTestScript();\n\tstatic bool IsPlayerOnAMission();\n\tstatic void ClearSpaceForMissionEntity(const CVector&, CEntity*);\n\n\tstatic void UndoBuildingSwaps();\n\tstatic void UndoEntityInvisibilitySettings();\n\n\tstatic void ScriptDebugLine3D(float x1, float y1, float z1, float x2, float y2, float z2, uint32 col, uint32 col2);\n\tstatic void RenderTheScriptDebugLines();\n\n\tstatic void SaveAllScripts(uint8*, uint32*);\n\tstatic void LoadAllScripts(uint8*, uint32);\n\n\tstatic bool IsDebugOn() { return DbgFlag; };\n\tstatic void InvertDebugFlag() { DbgFlag = !DbgFlag; }\n\n\tstatic int32* GetPointerToScriptVariable(int32 offset) { assert(offset >= 8 && offset < CTheScripts::GetSizeOfVariableSpace()); return (int32*)&ScriptSpace[offset]; }\n\n\tstatic int32 Read4BytesFromScript(uint32* pIp) {\n\t\tint32 retval = ScriptSpace[*pIp + 3] << 24 | ScriptSpace[*pIp + 2] << 16 | ScriptSpace[*pIp + 1] << 8 | ScriptSpace[*pIp];\n\t\t*pIp += 4;\n\t\treturn retval;\n\t}\n\tstatic int16 Read2BytesFromScript(uint32* pIp) {\n\t\tint16 retval = ScriptSpace[*pIp + 1] << 8 | ScriptSpace[*pIp];\n\t\t*pIp += 2;\n\t\treturn retval;\n\t}\n\tstatic int8 Read1ByteFromScript(uint32* pIp) {\n\t\tint8 retval = ScriptSpace[*pIp];\n\t\t*pIp += 1;\n\t\treturn retval;\n\t}\n\tstatic float ReadFloatFromScript(uint32* pIp) {\n\t\treturn Read2BytesFromScript(pIp) / 16.0f;\n\t}\n\tstatic void ReadTextLabelFromScript(uint32* pIp, char* buf) {\n\t\tstrncpy(buf, (const char*)&CTheScripts::ScriptSpace[*pIp], KEY_LENGTH_IN_SCRIPT);\n\t}\n\tstatic wchar* GetTextByKeyFromScript(uint32* pIp) {\n\t\twchar* text = TheText.Get((const char*)&CTheScripts::ScriptSpace[*pIp]);\n\t\t*pIp += KEY_LENGTH_IN_SCRIPT;\n\t\treturn text;\n\t}\n\tstatic int32 GetSizeOfVariableSpace()\n\t{\n\t\tuint32 tmp = 3;\n\t\treturn Read4BytesFromScript(&tmp);\n\t}\n\n\tstatic CRunningScript* StartNewScript(uint32);\n\n\tstatic void CleanUpThisVehicle(CVehicle*);\n\tstatic void CleanUpThisPed(CPed*);\n\tstatic void CleanUpThisObject(CObject*);\n\n\tstatic bool IsPedStopped(CPed*);\n\tstatic bool IsPlayerStopped(CPlayerInfo*);\n\tstatic bool IsVehicleStopped(CVehicle*);\n\n\tstatic void PrintListSizes();\n\tstatic void ReadObjectNamesFromScript();\n\tstatic void UpdateObjectIndices();\n\tstatic void ReadMultiScriptFileOffsetsFromScript();\n\tstatic void DrawScriptSpheres();\n\tstatic void HighlightImportantArea(uint32, float, float, float, float, float);\n\tstatic void HighlightImportantAngledArea(uint32, float, float, float, float, float, float, float, float, float);\n\tstatic void DrawDebugSquare(float, float, float, float);\n\tstatic void DrawDebugAngledSquare(float, float, float, float, float, float, float, float);\n\tstatic void DrawDebugCube(float, float, float, float, float, float);\n\tstatic void DrawDebugAngledCube(float, float, float, float, float, float, float, float, float, float);\n\n\tstatic void AddToInvisibilitySwapArray(CEntity*, bool);\n\tstatic void AddToBuildingSwapArray(CBuilding*, int32, int32);\n\n\tstatic int32 GetActualScriptSphereIndex(int32 index);\n\tstatic int32 AddScriptSphere(int32 id, CVector pos, float radius);\n\tstatic int32 GetNewUniqueScriptSphereIndex(int32 index);\n\tstatic void RemoveScriptSphere(int32 index);\n\tstatic void RemoveScriptTextureDictionary();\npublic:\n\tstatic void RemoveThisPed(CPed* pPed);\n\n\tstatic uint32& GetLastMissionPassedTime() { return LastMissionPassedTime; }\n#ifdef MISSION_SWITCHER\n\tstatic void SwitchToMission(int32 mission);\n#endif\n\n#ifdef GTA_SCRIPT_COLLECTIVE\n\tstatic void AdvanceCollectiveIndex()\n\t{\n\t\tif (NextFreeCollectiveIndex == INT32_MAX)\n\t\t\tNextFreeCollectiveIndex = 0;\n\t\telse\n\t\t\tNextFreeCollectiveIndex++;\n\t}\n\n\tstatic int AddPedsInVehicleToCollective(int);\n\tstatic int AddPedsInAreaToCollective(float, float, float, float);\n\tstatic int FindFreeSlotInCollectiveArray();\n\tstatic void SetObjectiveForAllPedsInCollective(int, eObjective, int16, int16);\n\tstatic void SetObjectiveForAllPedsInCollective(int, eObjective, CVector, float);\n\tstatic void SetObjectiveForAllPedsInCollective(int, eObjective, CVector);\n\tstatic void SetObjectiveForAllPedsInCollective(int, eObjective, void*);\n\tstatic void SetObjectiveForAllPedsInCollective(int, eObjective);\n#endif\n\n};\n\n#ifdef USE_DEBUG_SCRIPT_LOADER\nextern int scriptToLoad;\n#endif\n#ifdef MISSION_REPLAY\nstatic_assert(false, \"Mission replay is not supported\");\nextern int AllowMissionReplay;\nextern uint32 WaitForMissionActivate;\nextern uint32 WaitForSave;\nextern uint32 MissionStartTime;\nextern int missionRetryScriptIndex;\nextern bool doingMissionRetry;\nextern bool gbTryingPorn4Again;\nextern int IsInAmmunation;\nextern int MissionSkipLevel;\n\nuint32 AddExtraDeathDelay();\nvoid RetryMission(int, int);\n#endif\n\n#ifdef USE_DEBUG_SCRIPT_LOADER\nextern int scriptToLoad;\n#endif\n"
  },
  {
    "path": "src/control/Script2.cpp",
    "content": "#include \"common.h\"\n\n#include \"Script.h\"\n#include \"ScriptCommands.h\"\n\n#include \"Camera.h\"\n#include \"CarCtrl.h\"\n#include \"CarGen.h\"\n#include \"CivilianPed.h\"\n#include \"CopPed.h\"\n#include \"Cranes.h\"\n#include \"DMAudio.h\"\n#include \"EmergencyPed.h\"\n#include \"Garages.h\"\n#include \"General.h\"\n#include \"Messages.h\"\n#include \"Pad.h\"\n#include \"PedRoutes.h\"\n#include \"Pools.h\"\n#include \"Population.h\"\n#include \"Radar.h\"\n#include \"Restart.h\"\n#include \"Shadows.h\"\n#include \"User.h\"\n#include \"Wanted.h\"\n#include \"WaterLevel.h\"\n#include \"Weather.h\"\n#include \"World.h\"\n#include \"Zones.h\"\n\nint8 CRunningScript::ProcessCommands300To399(int32 command)\n{\n\tswitch (command) {\n\t//case COMMAND_SET_CHAR_INVINCIBLE:\n\t//case COMMAND_SET_PLAYER_INVINCIBLE:\n\t//case COMMAND_SET_CHAR_GRAPHIC_TYPE:\n\t//case COMMAND_SET_PLAYER_GRAPHIC_TYPE:\n\t/*\n\tcase COMMAND_HAS_PLAYER_BEEN_ARRESTED:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tUpdateCompareFlag(CWorld::Players[ScriptParams[0]].m_WBState == WBSTATE_BUSTED);\n\t\treturn 0;\n\t*/\n\t//case COMMAND_STOP_CHAR_DRIVING:\n\t//case COMMAND_KILL_CHAR:\n\t//case COMMAND_SET_FAVOURITE_CAR_MODEL_FOR_CHAR:\n\t//case COMMAND_SET_CHAR_OCCUPATION:\n\t/*\n\tcase COMMAND_CHANGE_CAR_LOCK:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tpVehicle->m_nDoorLock = (eCarLock)ScriptParams[1];\n\t\treturn 0;\n\t}\n\tcase COMMAND_SHAKE_CAM_WITH_POINT:\n\t\tCollectParameters(&m_nIp, 4);\n\t\tTheCamera.CamShake(ScriptParams[0] / 1000.0f,\n\t\t\t*(float*)&ScriptParams[1],\n\t\t\t*(float*)&ScriptParams[2],\n\t\t\t*(float*)&ScriptParams[3]);\n\t\treturn 0;\n\t*/\n\tcase COMMAND_IS_CAR_MODEL:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tUpdateCompareFlag(pVehicle->GetModelIndex() == ScriptParams[1]);\n\t\treturn 0;\n\t}\n\t//case COMMAND_IS_CAR_REMAP:\n\t//case COMMAND_HAS_CAR_JUST_SUNK:\n\t//case COMMAND_SET_CAR_NO_COLLIDE:\n\t/*\n\tcase COMMAND_IS_CAR_DEAD_IN_AREA_2D:\n\t{\n\t\tCollectParameters(&m_nIp, 6);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tfloat x1 = *(float*)&ScriptParams[1];\n\t\tfloat y1 = *(float*)&ScriptParams[2];\n\t\tfloat x2 = *(float*)&ScriptParams[3];\n\t\tfloat y2 = *(float*)&ScriptParams[4];\n\t\tUpdateCompareFlag(pVehicle->GetStatus() == STATUS_WRECKED &&\n\t\t\tpVehicle->IsWithinArea(x1, y1, x2, y2));\n\t\tif (ScriptParams[5])\n\t\t\tCTheScripts::HighlightImportantArea((uintptr)this + m_nIp, x1, y1, x2, y2, MAP_Z_LOW_LIMIT);\n\t\tif (CTheScripts::DbgFlag)\n\t\t\tCTheScripts::DrawDebugSquare(x1, y1, x2, y2);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_CAR_DEAD_IN_AREA_3D:\n\t{\n\t\tCollectParameters(&m_nIp, 8);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tfloat x1 = *(float*)&ScriptParams[1];\n\t\tfloat y1 = *(float*)&ScriptParams[2];\n\t\tfloat z1 = *(float*)&ScriptParams[3];\n\t\tfloat x2 = *(float*)&ScriptParams[4];\n\t\tfloat y2 = *(float*)&ScriptParams[5];\n\t\tfloat z2 = *(float*)&ScriptParams[6];\n\t\tUpdateCompareFlag(pVehicle->GetStatus() == STATUS_WRECKED &&\n\t\t\tpVehicle->IsWithinArea(x1, y1, z1, x2, y2, z2));\n\t\tif (ScriptParams[7])\n\t\t\tCTheScripts::HighlightImportantArea((uintptr)this + m_nIp, x1, y1, x2, y2, (z1 + z2) / 2);\n\t\tif (CTheScripts::DbgFlag)\n\t\t\tCTheScripts::DrawDebugCube(x1, y1, z1, x2, y2, z2);\n\t\treturn 0;\n\t}\n\t*/\n\t//case COMMAND_IS_TRAILER_ATTACHED:\n\t//case COMMAND_IS_CAR_ON_TRAILER:\n\t//case COMMAND_HAS_CAR_GOT_WEAPON:\n\t//case COMMAND_PARK:\n\t//case COMMAND_HAS_PARK_FINISHED:\n\t//case COMMAND_KILL_ALL_PASSENGERS:\n\t//case COMMAND_SET_CAR_BULLETPROOF:\n\t//case COMMAND_SET_CAR_FLAMEPROOF:\n\t//case COMMAND_SET_CAR_ROCKETPROOF:\n\t//case COMMAND_IS_CARBOMB_ACTIVE:\n\t//case COMMAND_GIVE_CAR_ALARM:\n\t//case COMMAND_PUT_CAR_ON_TRAILER:\n\t/*\n\tcase COMMAND_IS_CAR_CRUSHED:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tUpdateCompareFlag(CGarages::HasCarBeenCrushed(ScriptParams[0]));\n\t\treturn 0;\n\t*/\n\t//case COMMAND_CREATE_GANG_CAR:\n\tcase COMMAND_CREATE_CAR_GENERATOR:\n\t{\n\t\tCollectParameters(&m_nIp, 12);\n\t\tCVector pos = *(CVector*)&ScriptParams[0];\n\t\tif (pos.z > MAP_Z_LOW_LIMIT)\n\t\t\tpos.z += 0.015f;\n\t\tScriptParams[0] = CTheCarGenerators::CreateCarGenerator(\n\t\t\tpos.x, pos.y, pos.z, *(float*)&ScriptParams[3],\n\t\t\tScriptParams[4], ScriptParams[5], ScriptParams[6], ScriptParams[7],\n\t\t\tScriptParams[8], ScriptParams[9], ScriptParams[10], ScriptParams[11]);\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SWITCH_CAR_GENERATOR:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCCarGenerator* pCarGen = &CTheCarGenerators::CarGeneratorArray[ScriptParams[0]];\n\t\tif (ScriptParams[1] == 0){\n\t\t\tpCarGen->SwitchOff();\n\t\t}else if (ScriptParams[1] <= 100){\n\t\t\tpCarGen->SwitchOn();\n\t\t\tpCarGen->SetUsesRemaining(ScriptParams[1]);\n\t\t}else{\n\t\t\tpCarGen->SwitchOn();\n\t\t}\n\t\treturn 0;\n\t}\n\t/*\n\tcase COMMAND_ADD_PAGER_MESSAGE:\n\t{\n\t\twchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\tCollectParameters(&m_nIp, 3);\n\t\tCUserDisplay::Pager.AddMessage(text, ScriptParams[0], ScriptParams[1], ScriptParams[2]);\n\t\treturn 0;\n\t}\n\t*/\n\tcase COMMAND_DISPLAY_ONSCREEN_TIMER:\n\t{\n\t\tscript_assert(CTheScripts::ScriptSpace[m_nIp] == ARGUMENT_GLOBALVAR);\n\t\tm_nIp++;\n\t\tuint16 offset = CTheScripts::Read2BytesFromScript(&m_nIp);\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCUserDisplay::OnscnTimer.AddClock(offset, nil, ScriptParams[0] != 0);\n\t\treturn 0;\n\t}\n\tcase COMMAND_CLEAR_ONSCREEN_TIMER:\n\t{\n\t\tscript_assert(CTheScripts::ScriptSpace[m_nIp] == ARGUMENT_GLOBALVAR);\n\t\tm_nIp++;\n\t\tCUserDisplay::OnscnTimer.ClearClock((uint16)CTheScripts::Read2BytesFromScript(&m_nIp));\n\t\treturn 0;\n\t}\n\tcase COMMAND_DISPLAY_ONSCREEN_COUNTER:\n\t{\n\t\tscript_assert(CTheScripts::ScriptSpace[m_nIp] == ARGUMENT_GLOBALVAR);\n\t\tm_nIp++;\n\t\tint16 counter = CTheScripts::Read2BytesFromScript(&m_nIp);\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCUserDisplay::OnscnTimer.AddCounter(counter, ScriptParams[0], nil, 0);\n\t\treturn 0;\n\t}\n\tcase COMMAND_CLEAR_ONSCREEN_COUNTER:\n\t{\n\t\tscript_assert(CTheScripts::ScriptSpace[m_nIp] == ARGUMENT_GLOBALVAR);\n\t\tm_nIp++;\n\t\tCUserDisplay::OnscnTimer.ClearCounter((uint16)CTheScripts::Read2BytesFromScript(&m_nIp));\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_ZONE_CAR_INFO:\n\t{\n\t\tchar label[12];\n\t\tint16 gangDensities[NUM_GANGS] = { 0 };\n\t\tint i;\n\n\t\tCTheScripts::ReadTextLabelFromScript(&m_nIp, label);\n\t\tm_nIp += KEY_LENGTH_IN_SCRIPT;\n\t\tCollectParameters(&m_nIp, 12);\n\t\tfor (i = 0; i < NUM_GANGS; i++)\n\t\t\tgangDensities[i] = ScriptParams[i + 2];\n\t\tint zone = CTheZones::FindZoneByLabelAndReturnIndex(label, ZONE_INFO);\n\t\tfor (int i = 0; i < NUM_GANGS; i++) {\n\t\t\tif (gangDensities[i] != 0 && CGangs::GetGangInfo(i)->m_nVehicleMI == -1)\n\t\t\t\tdebug(\"SET_ZONE_CAR_INFO - Gang %d car ratio should be 0 in %s zone\\n\", i + 1, label);\n\t\t}\n\t\tif (zone < 0) {\n\t\t\tdebug(\"Couldn't find zone - %s\\n\", label);\n\t\t\treturn 0;\n\t\t}\n\t\twhile (zone >= 0) {\n\t\t\tCTheZones::SetZoneCarInfo(zone, ScriptParams[0], ScriptParams[1], ScriptParams[11], gangDensities);\n\t\t\tzone = CTheZones::FindNextZoneByLabelAndReturnIndex(label, ZONE_INFO);\n\t\t}\n\t\treturn 0;\n\t}\n\t//case COMMAND_IS_CHAR_IN_GANG_ZONE:\n\tcase COMMAND_IS_CHAR_IN_ZONE:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tchar label[12];\n\t\tCTheScripts::ReadTextLabelFromScript(&m_nIp, label);\n\t\tint zone = CTheZones::FindZoneByLabelAndReturnIndex(label, ZONE_DEFAULT);\n\t\tif (zone != -1)\n\t\t\tm_nIp += KEY_LENGTH_IN_SCRIPT;\n\t\tCVector pos = pPed->bInVehicle ? pPed->m_pMyVehicle->GetPosition() : pPed->GetPosition();\n\t\tUpdateCompareFlag(CTheZones::PointLiesWithinZone(&pos, CTheZones::GetNavigationZone(zone)));\n\t\treturn 0;\n\t}\n\t//case COMMAND_SET_CAR_DENSITY:\n\t//case COMMAND_SET_PED_DENSITY:\n\tcase COMMAND_POINT_CAMERA_AT_PLAYER:\n\t{\n\t\tCollectParameters(&m_nIp, 3);\n\t\t// ScriptParams[0] is unused.\n\t\tTheCamera.TakeControl(nil, ScriptParams[1], ScriptParams[2], CAMCONTROL_SCRIPT);\n\t\treturn 0;\n\t}\n\tcase COMMAND_POINT_CAMERA_AT_CAR:\n\t{\n\t\tCollectParameters(&m_nIp, 3);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tif (pVehicle)\n\t\t\tTheCamera.TakeControl(pVehicle, ScriptParams[1], ScriptParams[2], CAMCONTROL_SCRIPT);\n\t\treturn 0;\n\t}\n\tcase COMMAND_POINT_CAMERA_AT_CHAR:\n\t{\n\t\tCollectParameters(&m_nIp, 3);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tif (pPed)\n\t\t\tTheCamera.TakeControl(pPed, ScriptParams[1], ScriptParams[2], CAMCONTROL_SCRIPT);\n\t\treturn 0;\n\t}\n\tcase COMMAND_RESTORE_CAMERA:\n\t\tTheCamera.Restore();\n\t\treturn 0;\n\t/*\n\tcase COMMAND_SHAKE_PAD:\n\t\tCPad::GetPad(ScriptParams[0])->StartShake(ScriptParams[1], ScriptParams[2]);\n\t\treturn 0;\n\t*/\n\tcase COMMAND_SET_ZONE_PED_INFO:\n\t{\n\t\tchar label[12];\n\t\tCTheScripts::ReadTextLabelFromScript(&m_nIp, label);\n\t\tm_nIp += KEY_LENGTH_IN_SCRIPT;\n\t\tCollectParameters(&m_nIp, 12);\n\t\tint16 zone = CTheZones::FindZoneByLabelAndReturnIndex(label, ZONE_INFO);\n\t\tif (zone < 0) {\n\t\t\tdebug(\"Couldn't find zone - %s\\n\", label);\n\t\t\treturn 0;\n\t\t}\n\t\twhile (zone >= 0) {\n\t\t\tCTheZones::SetZonePedInfo(zone, ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3],\n\t\t\t\tScriptParams[4], ScriptParams[5], ScriptParams[6], ScriptParams[7], ScriptParams[8], ScriptParams[9], ScriptParams[10], ScriptParams[11]);\n\t\t\tzone = CTheZones::FindNextZoneByLabelAndReturnIndex(label, ZONE_INFO);\n\t\t}\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_TIME_SCALE:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCTimer::SetTimeScale(*(float*)&ScriptParams[0]);\n\t\treturn 0;\n\t/*\n\tcase COMMAND_IS_CAR_IN_AIR:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle && pVehicle->IsCar());\n\t\tCAutomobile* pCar = (CAutomobile*)pVehicle;\n\t\tUpdateCompareFlag(pCar->GetAllWheelsOffGround());\n\t\treturn 0;\n\t}\n\t*/\n\tcase COMMAND_SET_FIXED_CAMERA_POSITION:\n\t{\n\t\tCollectParameters(&m_nIp, 6);\n\t\tTheCamera.SetCamPositionForFixedMode(\n\t\t\tCVector(*(float*)&ScriptParams[0], *(float*)&ScriptParams[1], *(float*)&ScriptParams[2]),\n\t\t\tCVector(*(float*)&ScriptParams[3], *(float*)&ScriptParams[4], *(float*)&ScriptParams[5]));\n\t\treturn 0;\n\t}\n\tcase COMMAND_POINT_CAMERA_AT_POINT:\n\t{\n\t\tCollectParameters(&m_nIp, 4);\n\t\tCVector pos = *(CVector*)&ScriptParams[0];\n\t\tif (pos.z <= MAP_Z_LOW_LIMIT)\n\t\t\tpos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);\n\t\tTheCamera.TakeControlNoEntity(pos, ScriptParams[3], CAMCONTROL_SCRIPT);\n\t\treturn 0;\n\t}\n\tcase COMMAND_ADD_BLIP_FOR_CAR_OLD:\n\t{\n\t\tCollectParameters(&m_nIp, 3);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tCRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));\n\t\tScriptParams[0] = CRadar::SetEntityBlip(BLIP_CAR, ScriptParams[0], ScriptParams[1], (eBlipDisplay)ScriptParams[2]);\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\tcase COMMAND_ADD_BLIP_FOR_CHAR_OLD:\n\t{\n\t\tCollectParameters(&m_nIp, 3);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tCRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));\n\t\tScriptParams[0] = CRadar::SetEntityBlip(BLIP_CHAR, ScriptParams[0], ScriptParams[1], (eBlipDisplay)ScriptParams[2]);\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\t/*\n\tcase COMMAND_ADD_BLIP_FOR_OBJECT_OLD:\n\t{\n\t\tCollectParameters(&m_nIp, 3);\n\t\tCObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pObject);\n\t\tCRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));\n\t\tScriptParams[0] = CRadar::SetEntityBlip(BLIP_OBJECT, ScriptParams[0], ScriptParams[1], (eBlipDisplay)ScriptParams[2]);\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\t*/\n\tcase COMMAND_REMOVE_BLIP:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCRadar::ClearBlip(ScriptParams[0]);\n\t\treturn 0;\n\tcase COMMAND_CHANGE_BLIP_COLOUR:\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCRadar::ChangeBlipColour(ScriptParams[0], ScriptParams[1]);\n\t\treturn 0;\n\tcase COMMAND_DIM_BLIP:\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCRadar::ChangeBlipBrightness(ScriptParams[0], ScriptParams[1]);\n\t\treturn 0;\n\tcase COMMAND_ADD_BLIP_FOR_COORD_OLD:\n\t{\n\t\tCollectParameters(&m_nIp, 5);\n\t\tCVector pos = *(CVector*)&ScriptParams[0];\n\t\tif (pos.z <= MAP_Z_LOW_LIMIT)\n\t\t\tpos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);\n\t\tCRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));\n\t\tScriptParams[0] = CRadar::SetCoordBlip(BLIP_COORD, pos, ScriptParams[3], (eBlipDisplay)ScriptParams[4]);\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\tcase COMMAND_CHANGE_BLIP_SCALE:\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCRadar::ChangeBlipScale(ScriptParams[0], ScriptParams[1]);\n\t\treturn 0;\n\tcase COMMAND_SET_FADING_COLOUR:\n\t\tCollectParameters(&m_nIp, 3);\n\t\tTheCamera.SetFadeColour(ScriptParams[0], ScriptParams[1], ScriptParams[2]);\n\t\treturn 0;\n\tcase COMMAND_DO_FADE:\n\t\tCollectParameters(&m_nIp, 2);\n\t\tTheCamera.Fade(ScriptParams[0] / 1000.0f, ScriptParams[1]);\n\t\treturn 0;\n\tcase COMMAND_GET_FADING_STATUS:\n\t\tUpdateCompareFlag(TheCamera.GetFading());\n\t\treturn 0;\n\tcase COMMAND_ADD_HOSPITAL_RESTART:\n\t{\n\t\tCollectParameters(&m_nIp, 4);\n\t\tCVector pos = *(CVector*)&ScriptParams[0];\n\t\tfloat angle = *(float*)&ScriptParams[3];\n\t\tif (pos.z <= MAP_Z_LOW_LIMIT)\n\t\t\tpos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);\n\t\tCRestart::AddHospitalRestartPoint(pos, angle);\n\t\treturn 0;\n\t}\n\tcase COMMAND_ADD_POLICE_RESTART:\n\t{\n\t\tCollectParameters(&m_nIp, 4);\n\t\tCVector pos = *(CVector*)&ScriptParams[0];\n\t\tfloat angle = *(float*)&ScriptParams[3];\n\t\tif (pos.z <= MAP_Z_LOW_LIMIT)\n\t\t\tpos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);\n\t\tCRestart::AddPoliceRestartPoint(pos, angle);\n\t\treturn 0;\n\t}\n\tcase COMMAND_OVERRIDE_NEXT_RESTART:\n\t{\n\t\tCollectParameters(&m_nIp, 4);\n\t\tCVector pos = *(CVector*)&ScriptParams[0];\n\t\tfloat angle = *(float*)&ScriptParams[3];\n\t\tif (pos.z <= MAP_Z_LOW_LIMIT)\n\t\t\tpos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);\n\t\tCRestart::OverrideNextRestart(pos, angle);\n\t\treturn 0;\n\t}\n\t/*\n\tcase COMMAND_DRAW_SHADOW:\n\t{\n\t\tCollectParameters(&m_nIp, 10);\n\t\tCVector pos = *(CVector*)&ScriptParams[1];\n\t\tfloat angle = *(float*)&ScriptParams[4];\n\t\tfloat length = *(float*)&ScriptParams[5];\n\t\tfloat x, y;\n\t\tif (angle != 0.0f){\n\t\t\ty = cos(angle) * length;\n\t\t\tx = sin(angle) * length;\n\t\t}else{\n\t\t\ty = length;\n\t\t\tx = 0.0f;\n\t\t}\n\t\tfloat frontX = -x;\n\t\tfloat frontY = y;\n\t\tfloat sideX = y;\n\t\tfloat sideY = x;\n\t\tCShadows::StoreShadowToBeRendered(ScriptParams[0], &pos, frontX, frontY, sideX, sideY,\n\t\t\tScriptParams[6], ScriptParams[7], ScriptParams[8], ScriptParams[9]);\n\t\treturn 0;\n\t}\n\t*/\n\tcase COMMAND_GET_PLAYER_HEADING:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;\n\t\tfloat angle = pPed->bInVehicle ? pPed->m_pMyVehicle->GetForward().Heading() : pPed->GetForward().Heading();\n\t\tangle = RADTODEG(angle);\n\t\tif (angle < 0.0f)\n\t\t\tangle += 360.0f;\n\t\tif (angle > 360.0f)\n\t\t\tangle -= 360.0f;\n\t\t*(float*)&ScriptParams[0] = angle;\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_PLAYER_HEADING:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;\n\t\tscript_assert(pPed);\n\t\tif (pPed->bInVehicle)\n\t\t\treturn 0;\n\t\tpPed->m_fRotationDest = pPed->m_fRotationCur = DEGTORAD(*(float*)&ScriptParams[1]);\n\t\tpPed->SetHeading(DEGTORAD(*(float*)&ScriptParams[1]));\n\t\treturn 0;\n\t}\n\tcase COMMAND_GET_CHAR_HEADING:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tfloat angle = pPed->bInVehicle ? pPed->m_pMyVehicle->GetForward().Heading() : pPed->GetForward().Heading();\n\t\tangle = RADTODEG(angle);\n\t\tif (angle < 0.0f)\n\t\t\tangle += 360.0f;\n\t\tif (angle > 360.0f)\n\t\t\tangle -= 360.0f;\n\t\t*(float*)&ScriptParams[0] = angle;\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_CHAR_HEADING:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tif (pPed->bInVehicle)\n\t\t\treturn 0;\n\t\tpPed->m_fRotationDest = pPed->m_fRotationCur = DEGTORAD(*(float*)&ScriptParams[1]);\n\t\tpPed->SetHeading(DEGTORAD(*(float*)&ScriptParams[1]));\n\t\treturn 0;\n\t}\n\tcase COMMAND_GET_CAR_HEADING:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tfloat angle = pVehicle->GetForward().Heading();\n\t\tangle = RADTODEG(angle);\n\t\tif (angle < 0.0f)\n\t\t\tangle += 360.0f;\n\t\tif (angle > 360.0f)\n\t\t\tangle -= 360.0f;\n\t\t*(float*)&ScriptParams[0] = angle;\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_CAR_HEADING:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tpVehicle->SetHeading(DEGTORAD(*(float*)&ScriptParams[1]));\n\t\treturn 0;\n\t}\n\tcase COMMAND_GET_OBJECT_HEADING:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pObject);\n\t\tfloat angle = pObject->GetForward().Heading();\n\t\tangle = RADTODEG(angle);\n\t\tif (angle < 0.0f)\n\t\t\tangle += 360.0f;\n\t\tif (angle > 360.0f)\n\t\t\tangle -= 360.0f;\n\t\t*(float*)&ScriptParams[0] = angle;\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_OBJECT_HEADING:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pObject);\n\t\tCWorld::Remove(pObject);\n\t\tpObject->SetHeading(DEGTORAD(*(float*)&ScriptParams[1]));\n\t\tpObject->GetMatrix().UpdateRW();\n\t\tpObject->UpdateRwFrame();\n\t\tCWorld::Add(pObject);\n\t\treturn 0;\n\t}\n\t/*\n\tcase COMMAND_IS_PLAYER_TOUCHING_OBJECT:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;\n\t\tCObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[1]);\n\t\tscript_assert(pObject);\n\t\tCPhysical* pEntityToTest = pPed->bInVehicle ? (CPhysical*)pPed->m_pMyVehicle : pPed;\n\t\tUpdateCompareFlag(pEntityToTest->GetHasCollidedWith(pObject));\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_CHAR_TOUCHING_OBJECT:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tCObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[1]);\n\t\tscript_assert(pObject);\n\t\tCPhysical* pEntityToTest = pPed->bInVehicle ? (CPhysical*)pPed->m_pMyVehicle : pPed;\n\t\tUpdateCompareFlag(pEntityToTest->GetHasCollidedWith(pObject));\n\t\treturn 0;\n\t}\n\t*/\n\tcase COMMAND_SET_PLAYER_AMMO:\n\t{\n\t\tCollectParameters(&m_nIp, 3);\n\t\tCWorld::Players[0].m_pPed->SetAmmo((eWeaponType)ScriptParams[1], ScriptParams[2]);\n\t\treturn 0;\n\t}\n\t/*\n\tcase COMMAND_SET_CHAR_AMMO:\n\t{\n\t\tCollectParameters(&m_nIp, 3);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tpPed->SetAmmo((eWeaponType)ScriptParams[1], ScriptParams[2]);\n\t\treturn 0;\n\t}\n\t*/\n\t//case COMMAND_SET_CAR_AMMO:\n\t//case COMMAND_LOAD_CAMERA_SPLINE:\n\t//case COMMAND_MOVE_CAMERA_ALONG_SPLINE:\n\t//case COMMAND_GET_CAMERA_POSITION_ALONG_SPLINE:\n\tcase COMMAND_DECLARE_MISSION_FLAG:\n\t\tCTheScripts::OnAMissionFlag = (uint16)CTheScripts::Read2BytesFromScript(&++m_nIp);\n\t\treturn 0;\n\tcase COMMAND_DECLARE_MISSION_FLAG_FOR_CONTACT:\n\t\treturn 0;\n\t//case COMMAND_DECLARE_BASE_BRIEF_ID_FOR_CONTACT:\n\tcase COMMAND_IS_PLAYER_HEALTH_GREATER:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;\n\t\tUpdateCompareFlag(pPed->m_fHealth > ScriptParams[1]);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_CHAR_HEALTH_GREATER:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tUpdateCompareFlag(pPed->m_fHealth > ScriptParams[1]);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_CAR_HEALTH_GREATER:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tUpdateCompareFlag(pVehicle->m_fHealth > ScriptParams[1]);\n\t\treturn 0;\n\t}\n\tcase COMMAND_ADD_BLIP_FOR_CAR:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tCRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));\n\t\tint handle = CRadar::SetEntityBlip(BLIP_CAR, ScriptParams[0], 0, BLIP_DISPLAY_BOTH);\n\t\tCRadar::ChangeBlipScale(handle, 3);\n\t\tScriptParams[0] = handle;\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\tcase COMMAND_ADD_BLIP_FOR_CHAR:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tCRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));\n\t\tint handle = CRadar::SetEntityBlip(BLIP_CHAR, ScriptParams[0], 1, BLIP_DISPLAY_BOTH);\n\t\tCRadar::ChangeBlipScale(handle, 3);\n\t\tScriptParams[0] = handle;\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\tcase COMMAND_ADD_BLIP_FOR_OBJECT:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pObject);\n\t\tCRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));\n\t\tint handle = CRadar::SetEntityBlip(BLIP_OBJECT, ScriptParams[0], 6, BLIP_DISPLAY_BOTH);\n\t\tCRadar::ChangeBlipScale(handle, 3);\n\t\tScriptParams[0] = handle;\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\tcase COMMAND_ADD_BLIP_FOR_CONTACT_POINT:\n\t{\n\t\tCollectParameters(&m_nIp, 3);\n\t\tCVector pos = *(CVector*)&ScriptParams[0];\n\t\tif (pos.z <= MAP_Z_LOW_LIMIT)\n\t\t\tpos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);\n\t\tCRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));\n\t\tint handle = CRadar::SetCoordBlip(BLIP_CONTACT_POINT, pos, 2, BLIP_DISPLAY_BOTH);\n\t\tCRadar::ChangeBlipScale(handle, 3);\n\t\tScriptParams[0] = handle;\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\tcase COMMAND_ADD_BLIP_FOR_COORD:\n\t{\n\t\tCollectParameters(&m_nIp, 3);\n\t\tCVector pos = *(CVector*)&ScriptParams[0];\n\t\tif (pos.z <= MAP_Z_LOW_LIMIT)\n\t\t\tpos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);\n\t\tCRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));\n\t\tint handle = CRadar::SetCoordBlip(BLIP_COORD, pos, 5, BLIP_DISPLAY_BOTH);\n\t\tCRadar::ChangeBlipScale(handle, 3);\n\t\tScriptParams[0] = handle;\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\tcase COMMAND_CHANGE_BLIP_DISPLAY:\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCRadar::ChangeBlipDisplay(ScriptParams[0], (eBlipDisplay)ScriptParams[1]);\n\t\treturn 0;\n\tcase COMMAND_ADD_ONE_OFF_SOUND:\n\t{\n\t\tCollectParameters(&m_nIp, 4);\n\t\tswitch (ScriptParams[3]) {\n\t\tcase SCRIPT_SOUND_PART_MISSION_COMPLETE:\n\t\t\tDMAudio.PlayFrontEndSound(SOUND_PART_MISSION_COMPLETE, 0);\n\t\t\treturn 0;\n\t\tcase SCRIPT_SOUND_RACE_START_3:\n\t\t\tDMAudio.PlayFrontEndSound(SOUND_RACE_START_3, 0);\n\t\t\treturn 0;\n\t\tcase SCRIPT_SOUND_RACE_START_2:\n\t\t\tDMAudio.PlayFrontEndSound(SOUND_RACE_START_2, 0);\n\t\t\treturn 0;\n\t\tcase SCRIPT_SOUND_RACE_START_1:\n\t\t\tDMAudio.PlayFrontEndSound(SOUND_RACE_START_1, 0);\n\t\t\treturn 0;\n\t\tcase SCRIPT_SOUND_RACE_START_GO:\n\t\t\tDMAudio.PlayFrontEndSound(SOUND_RACE_START_GO, 0);\n\t\t\treturn 0;\n\t\tcase SCRIPT_SOUND_AMMUNATION_BUY_WEAPON:\n\t\t\tDMAudio.PlayFrontEndSound(SOUND_PICKUP_WEAPON_BOUGHT, 0);\n\t\t\treturn 0;\n\t\tcase SCRIPT_SOUND_AMMUNATION_BUY_WEAPON_DENIED:\n\t\t\tDMAudio.PlayFrontEndSound(SOUND_GARAGE_NO_MONEY, 0);\n\t\t\treturn 0;\n\t\tcase SCRIPT_SOUND_IMRAN_ARM_BOMB:\n\t\t\tDMAudio.PlayFrontEndSound(SOUND_AMMUNATION_IMRAN_ARM_BOMB, 0);\n\t\t\treturn 0;\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\t\tif (!DMAudio.IsAudioInitialised())\n\t\t\treturn 0;\n\t\tcAudioScriptObject* obj = new cAudioScriptObject();\n\t\tobj->Posn = *(CVector*)&ScriptParams[0];\n\t\tobj->AudioId = ScriptParams[3];\n\t\tobj->AudioEntity = AEHANDLE_NONE;\n\t\tDMAudio.CreateOneShotScriptObject(obj);\n\t\treturn 0;\n\t}\n\tcase COMMAND_ADD_CONTINUOUS_SOUND:\n\t{\n\t\tCollectParameters(&m_nIp, 4);\n\t\tif (DMAudio.IsAudioInitialised()) {\n\t\t\tcAudioScriptObject* obj = new cAudioScriptObject();\n\t\t\tobj->Posn = *(CVector*)&ScriptParams[0];\n\t\t\tobj->AudioId = ScriptParams[3];\n\t\t\tobj->AudioEntity = DMAudio.CreateLoopingScriptObject(obj);\n\t\t\tScriptParams[0] = CPools::GetAudioScriptObjectPool()->GetIndex(obj);\n\t\t}\n\t\telse\n\t\t\tScriptParams[0] = -1;\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\tcase COMMAND_REMOVE_SOUND:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tcAudioScriptObject* obj = CPools::GetAudioScriptObjectPool()->GetAt(ScriptParams[0]);\n\t\tif (!obj){\n\t\t\tdebug(\"REMOVE_SOUND - Sound doesn't exist\\n\");\n\t\t\treturn 0;\n\t\t}\n\t\tDMAudio.DestroyLoopingScriptObject(obj->AudioEntity);\n\t\tdelete obj;\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_CAR_STUCK_ON_ROOF:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tUpdateCompareFlag(CTheScripts::UpsideDownCars.HasCarBeenUpsideDownForAWhile(ScriptParams[0]));\n\t\treturn 0;\n\t}\n\tdefault:\n\t\tscript_assert(0);\n\t}\n\treturn -1;\n}\n\nint8 CRunningScript::ProcessCommands400To499(int32 command)\n{\n\tswitch (command) {\n\tcase COMMAND_ADD_UPSIDEDOWN_CAR_CHECK:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tCTheScripts::UpsideDownCars.AddCarToCheck(ScriptParams[0]);\n\t\treturn 0;\n\t}\n\tcase COMMAND_REMOVE_UPSIDEDOWN_CAR_CHECK:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tCTheScripts::UpsideDownCars.RemoveCarFromCheck(ScriptParams[0]);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_CHAR_OBJ_WAIT_ON_FOOT:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tpPed->bScriptObjectiveCompleted = false;\n\t\tpPed->SetObjective(OBJECTIVE_WAIT_ON_FOOT);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_CHAR_OBJ_FLEE_ON_FOOT_TILL_SAFE:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tpPed->bScriptObjectiveCompleted = false;\n\t\tpPed->SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_CHAR_OBJ_GUARD_SPOT:\n\t{\n\t\tCollectParameters(&m_nIp, 4);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tCVector pos = *(CVector*)&ScriptParams[1];\n\t\tif (pos.z <= MAP_Z_LOW_LIMIT)\n\t\t\tpos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);\n\t\tpPed->bScriptObjectiveCompleted = false;\n\t\tpPed->SetObjective(OBJECTIVE_GUARD_SPOT, pos);\n\t\treturn 0;\n\t}\n\t/*\n\tcase COMMAND_SET_CHAR_OBJ_GUARD_AREA:\n\t{\n\t\tCollectParameters(&m_nIp, 5);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tfloat infX = *(float*)&ScriptParams[1];\n\t\tfloat infY = *(float*)&ScriptParams[2];\n\t\tfloat supX = *(float*)&ScriptParams[3];\n\t\tfloat supY = *(float*)&ScriptParams[4];\n\t\tif (infX > supX){\n\t\t\tinfX = *(float*)&ScriptParams[3];\n\t\t\tsupX = *(float*)&ScriptParams[1];\n\t\t}\n\t\tif (infY > supY) {\n\t\t\tinfY = *(float*)&ScriptParams[4];\n\t\t\tsupY = *(float*)&ScriptParams[2];\n\t\t}\n\t\tCVector pos;\n\t\tpos.x = (infX + supX) / 2;\n\t\tpos.y = (infY + supY) / 2;\n\t\tpos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);\n\t\tfloat radius = Max(pos.x - infX, pos.y - infY);\n\t\tpPed->bScriptObjectiveCompleted = false;\n\t\tpPed->SetObjective(OBJECTIVE_GUARD_SPOT, pos, radius);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_CHAR_OBJ_WAIT_IN_CAR:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tpPed->bScriptObjectiveCompleted = false;\n\t\tpPed->SetObjective(OBJECTIVE_WAIT_IN_CAR);\n\t\treturn 0;\n\t}\n\t*/\n\tcase COMMAND_IS_PLAYER_IN_AREA_ON_FOOT_2D:\n\tcase COMMAND_IS_PLAYER_IN_AREA_IN_CAR_2D:\n\tcase COMMAND_IS_PLAYER_STOPPED_IN_AREA_2D:\n\tcase COMMAND_IS_PLAYER_STOPPED_IN_AREA_ON_FOOT_2D:\n\tcase COMMAND_IS_PLAYER_STOPPED_IN_AREA_IN_CAR_2D:\n\tcase COMMAND_IS_PLAYER_IN_AREA_ON_FOOT_3D:\n\tcase COMMAND_IS_PLAYER_IN_AREA_IN_CAR_3D:\n\tcase COMMAND_IS_PLAYER_STOPPED_IN_AREA_3D:\n\tcase COMMAND_IS_PLAYER_STOPPED_IN_AREA_ON_FOOT_3D:\n\tcase COMMAND_IS_PLAYER_STOPPED_IN_AREA_IN_CAR_3D:\n\t\tPlayerInAreaCheckCommand(command, &m_nIp);\n\t\treturn 0;\n\tcase COMMAND_IS_CHAR_IN_AREA_ON_FOOT_2D:\n\tcase COMMAND_IS_CHAR_IN_AREA_IN_CAR_2D:\n\tcase COMMAND_IS_CHAR_STOPPED_IN_AREA_2D:\n\tcase COMMAND_IS_CHAR_STOPPED_IN_AREA_ON_FOOT_2D:\n\tcase COMMAND_IS_CHAR_STOPPED_IN_AREA_IN_CAR_2D:\n\tcase COMMAND_IS_CHAR_IN_AREA_ON_FOOT_3D:\n\tcase COMMAND_IS_CHAR_IN_AREA_IN_CAR_3D:\n\tcase COMMAND_IS_CHAR_STOPPED_IN_AREA_3D:\n\tcase COMMAND_IS_CHAR_STOPPED_IN_AREA_ON_FOOT_3D:\n\tcase COMMAND_IS_CHAR_STOPPED_IN_AREA_IN_CAR_3D:\n\t\tCharInAreaCheckCommand(command, &m_nIp);\n\t\treturn 0;\n\tcase COMMAND_IS_CAR_STOPPED_IN_AREA_2D:\n\tcase COMMAND_IS_CAR_STOPPED_IN_AREA_3D:\n\t\tCarInAreaCheckCommand(command, &m_nIp);\n\t\treturn 0;\n\tcase COMMAND_LOCATE_CAR_2D:\n\tcase COMMAND_LOCATE_STOPPED_CAR_2D:\n\tcase COMMAND_LOCATE_CAR_3D:\n\tcase COMMAND_LOCATE_STOPPED_CAR_3D:\n\t\tLocateCarCommand(command, &m_nIp);\n\t\treturn 0;\n\tcase COMMAND_GIVE_WEAPON_TO_PLAYER:\n\t{\n\t\tCollectParameters(&m_nIp, 3);\n\t\tCPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;\n\t\tscript_assert(pPed);\n\t\tpPed->m_nSelectedWepSlot = pPed->GiveWeapon((eWeaponType)ScriptParams[1], ScriptParams[2]);\n\t\treturn 0;\n\t}\n\tcase COMMAND_GIVE_WEAPON_TO_CHAR:\n\t{\n\t\tCollectParameters(&m_nIp, 3);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tpPed->SetCurrentWeapon(pPed->GiveWeapon((eWeaponType)ScriptParams[1], ScriptParams[2]));\n\t\tif (pPed->bInVehicle && pPed->m_pMyVehicle)\n\t\t\tpPed->RemoveWeaponModel(CWeaponInfo::GetWeaponInfo(pPed->m_weapons[pPed->m_currentWeapon].m_eWeaponType)->m_nModelId);\n\t\treturn 0;\n\t}\n\t//case COMMAND_GIVE_WEAPON_TO_CAR:\n\tcase COMMAND_SET_PLAYER_CONTROL:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPlayerInfo* pPlayer = &CWorld::Players[ScriptParams[0]];\n\t\tif (ScriptParams[1]){\n\t\t\tpPlayer->MakePlayerSafe(false);\n\t\t\tif (strcmp(m_abScriptName, \"serg1\") == 0) // Four Iron\n\t\t\t\tpPlayer->m_pPed->ClearFollowPath();\n\t\t}else{\n\t\t\tpPlayer->MakePlayerSafe(true);\n\t\t}\n\t\treturn 0;\n\t}\n\tcase COMMAND_FORCE_WEATHER:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCWeather::ForceWeather(ScriptParams[0]);\n\t\treturn 0;\n\tcase COMMAND_FORCE_WEATHER_NOW:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCWeather::ForceWeatherNow(ScriptParams[0]);\n\t\treturn 0;\n\tcase COMMAND_RELEASE_WEATHER:\n\t\tCWeather::ReleaseWeather();\n\t\treturn 0;\n\tcase COMMAND_SET_CURRENT_PLAYER_WEAPON:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;\n\t\tfor (int i = 0; i < TOTAL_WEAPON_SLOTS; i++){\n\t\t\tif (pPed->m_weapons[i].m_eWeaponType == ScriptParams[1])\n\t\t\t\tpPed->m_nSelectedWepSlot = i;\n\t\t}\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_CURRENT_CHAR_WEAPON:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tfor (int i = 0; i < TOTAL_WEAPON_SLOTS; i++) {\n\t\t\tif (pPed->m_weapons[i].m_eWeaponType == ScriptParams[1])\n\t\t\t\tpPed->SetCurrentWeapon(i);\n\t\t}\n\t\treturn 0;\n\t}\n\t//case COMMAND_SET_CURRENT_CAR_WEAPON:\n\tcase COMMAND_GET_OBJECT_COORDINATES:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pObject);\n\t\t*(CVector*)&ScriptParams[0] = pObject->GetPosition();\n\t\tStoreParameters(&m_nIp, 3);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_OBJECT_COORDINATES:\n\t{\n\t\tCollectParameters(&m_nIp, 4);\n\t\tCObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pObject);\n\t\tCVector pos = *(CVector*)&ScriptParams[1];\n\t\tif (pos.z <= MAP_Z_LOW_LIMIT)\n\t\t\tpos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);\n\t\tpObject->Teleport(pos);\n\t\tCTheScripts::ClearSpaceForMissionEntity(pos, pObject);\n\t\treturn 0;\n\t}\n\tcase COMMAND_GET_GAME_TIMER:\n\t\tScriptParams[0] = CTimer::GetTimeInMilliseconds();\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\tcase COMMAND_TURN_CHAR_TO_FACE_COORD:\n\t{\n\t\tCollectParameters(&m_nIp, 4);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tCVehicle* pVehicle;\n\t\tCVector pos;\n\t\tif (pPed->bInVehicle)\n\t\t\tpVehicle = pPed->m_pMyVehicle;\n\t\telse\n\t\t\tpVehicle = nil;\n\t\tif (pVehicle)\n\t\t\tpos = pVehicle->GetPosition();\n\t\telse\n\t\t\tpos = pPed->GetPosition();\n\t\tfloat heading = CGeneral::GetATanOfXY(pos.x - *(float*)&ScriptParams[1], pos.y - *(float*)&ScriptParams[2]);\n\t\theading += HALFPI;\n\t\tif (heading > TWOPI)\n\t\t\theading -= TWOPI;\n\t\tif (!pVehicle){\n\t\t\tpPed->m_fRotationCur = heading;\n\t\t\tpPed->m_fRotationDest = heading;\n\t\t\tpPed->SetHeading(heading);\n\t\t}\n\t\treturn 0;\n\t}\n\tcase COMMAND_TURN_PLAYER_TO_FACE_COORD:\n\t{\n\t\tCollectParameters(&m_nIp, 4);\n\t\tCPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;\n\t\tscript_assert(pPed);\n\t\tCVehicle* pVehicle;\n\t\tCVector pos;\n\t\tif (pPed->bInVehicle)\n\t\t\tpVehicle = pPed->m_pMyVehicle;\n\t\telse\n\t\t\tpVehicle = nil;\n\t\tif (pVehicle)\n\t\t\tpos = pVehicle->GetPosition();\n\t\telse\n\t\t\tpos = pPed->GetPosition();\n\t\tfloat heading = CGeneral::GetATanOfXY(pos.x - *(float*)&ScriptParams[1], pos.y - *(float*)&ScriptParams[2]);\n\t\theading += HALFPI;\n\t\tif (heading > TWOPI)\n\t\t\theading -= TWOPI;\n\t\tif (!pVehicle) {\n\t\t\tpPed->m_fRotationCur = heading;\n\t\t\tpPed->m_fRotationDest = heading;\n\t\t\tpPed->SetHeading(heading);\n\t\t}\n\t\treturn 0;\n\t}\n\tcase COMMAND_STORE_WANTED_LEVEL:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;\n\t\tscript_assert(pPed);\n\t\tScriptParams[0] = pPed->m_pWanted->GetWantedLevel();\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_CAR_STOPPED:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tUpdateCompareFlag(CTheScripts::IsVehicleStopped(pVehicle));\n\t\treturn 0;\n\t}\n\tcase COMMAND_MARK_CHAR_AS_NO_LONGER_NEEDED:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tCTheScripts::CleanUpThisPed(pPed);\n\t\tif (m_bIsMissionScript)\n\t\t\tCTheScripts::MissionCleanUp.RemoveEntityFromList(ScriptParams[0], CLEANUP_CHAR);\n\t\treturn 0;\n\t}\n\tcase COMMAND_MARK_CAR_AS_NO_LONGER_NEEDED:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tCTheScripts::CleanUpThisVehicle(pVehicle);\n\t\tif (m_bIsMissionScript)\n\t\t\tCTheScripts::MissionCleanUp.RemoveEntityFromList(ScriptParams[0], CLEANUP_CAR);\n\t\treturn 0;\n\t}\n\tcase COMMAND_MARK_OBJECT_AS_NO_LONGER_NEEDED:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);\n\t\tCTheScripts::CleanUpThisObject(pObject);\n\t\tif (m_bIsMissionScript)\n\t\t\tCTheScripts::MissionCleanUp.RemoveEntityFromList(ScriptParams[0], CLEANUP_OBJECT);\n\t\treturn 0;\n\t}\n\tcase COMMAND_DONT_REMOVE_CHAR:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tCTheScripts::MissionCleanUp.RemoveEntityFromList(ScriptParams[0], CLEANUP_CHAR);\n\t\treturn 0;\n\t}\n\tcase COMMAND_DONT_REMOVE_CAR:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tCTheScripts::MissionCleanUp.RemoveEntityFromList(ScriptParams[0], CLEANUP_CAR);\n\t\treturn 0;\n\t}\n\tcase COMMAND_DONT_REMOVE_OBJECT:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pObject);\n\t\tCTheScripts::MissionCleanUp.RemoveEntityFromList(ScriptParams[0], CLEANUP_OBJECT);\n\t\treturn 0;\n\t}\n\tcase COMMAND_CREATE_CHAR_AS_PASSENGER:\n\t{\n\t\tCollectParameters(&m_nIp, 4);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tswitch (ScriptParams[2]) {\n\t\tcase MI_COP:\n\t\t\tif (ScriptParams[1] == PEDTYPE_COP)\n\t\t\t\tScriptParams[2] = COP_STREET;\n\t\t\tbreak;\n\t\tcase MI_SWAT:\n\t\t\tif (ScriptParams[1] == PEDTYPE_COP)\n\t\t\t\tScriptParams[2] = COP_SWAT;\n\t\t\tbreak;\n\t\tcase MI_FBI:\n\t\t\tif (ScriptParams[1] == PEDTYPE_COP)\n\t\t\t\tScriptParams[2] = COP_FBI;\n\t\t\tbreak;\n\t\tcase MI_ARMY:\n\t\t\tif (ScriptParams[1] == PEDTYPE_COP)\n\t\t\t\tScriptParams[2] = COP_ARMY;\n\t\t\tbreak;\n\t\tcase MI_MEDIC:\n\t\t\tif (ScriptParams[1] == PEDTYPE_EMERGENCY)\n\t\t\t\tScriptParams[2] = PEDTYPE_EMERGENCY;\n\t\t\tbreak;\n\t\tcase MI_FIREMAN:\n\t\t\tif (ScriptParams[1] == PEDTYPE_FIREMAN)\n\t\t\t\tScriptParams[2] = PEDTYPE_FIREMAN;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\t\tCPed* pPed;\n\t\tif (ScriptParams[1] == PEDTYPE_COP)\n\t\t\tpPed = new CCopPed((eCopType)ScriptParams[2]);\n\t\telse if (ScriptParams[1] == PEDTYPE_EMERGENCY || ScriptParams[1] == PEDTYPE_FIREMAN)\n\t\t\tpPed = new CEmergencyPed(ScriptParams[2]);\n\t\telse\n\t\t\tpPed = new CCivilianPed((ePedType)ScriptParams[1], ScriptParams[2]);\n\t\tpPed->CharCreatedBy = MISSION_CHAR;\n\t\tpPed->bRespondsToThreats = false;\n\t\tpPed->bAllowMedicsToReviveMe = false;\n\t\tpPed->bIsPlayerFriend = false;\n\t\tif (pVehicle->bIsBus)\n\t\t\tpPed->bRenderPedInCar = false;\n\t\tpPed->SetPosition(pVehicle->GetPosition());\n\t\tpPed->SetOrientation(0.0f, 0.0f, 0.0f);\n\t\tCPopulation::ms_nTotalMissionPeds++;\n\t\tCWorld::Add(pPed);\n\t\tif (ScriptParams[3] >= 0)\n\t\t\tpVehicle->AddPassenger(pPed, ScriptParams[3]);\n\t\telse\n\t\t\tpVehicle->AddPassenger(pPed);\n\t\tpPed->m_pMyVehicle = pVehicle;\n\t\tpPed->m_pMyVehicle->RegisterReference((CEntity**)&pPed->m_pMyVehicle);\n\t\tpPed->bInVehicle = true;\n\t\tpPed->SetPedState(PED_DRIVING);\n\t\tpPed->bUsesCollision = false;\n\t\tpPed->AddInCarAnims(pVehicle, false);\n\t\tpPed->m_nZoneLevel = CTheZones::GetLevelFromPosition(&pPed->GetPosition());\n\t\tScriptParams[0] = CPools::GetPedPool()->GetIndex(pPed);\n\t\tStoreParameters(&m_nIp, 1);\n\t\tif (m_bIsMissionScript)\n\t\t\tCTheScripts::MissionCleanUp.AddEntityToList(ScriptParams[0], CLEANUP_CHAR);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_CHAR_OBJ_KILL_CHAR_ON_FOOT:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tCPed* pTarget = CPools::GetPedPool()->GetAt(ScriptParams[1]);\n\t\tpPed->bScriptObjectiveCompleted = false;\n\t\tpPed->SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, pTarget);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_CHAR_OBJ_KILL_PLAYER_ON_FOOT:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tCPed* pTarget = CWorld::Players[ScriptParams[1]].m_pPed;\n\t\tpPed->bScriptObjectiveCompleted = false;\n\t\tpPed->SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, pTarget);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_CHAR_OBJ_KILL_CHAR_ANY_MEANS:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tCPed* pTarget = CPools::GetPedPool()->GetAt(ScriptParams[1]);\n\t\tpPed->bScriptObjectiveCompleted = false;\n\t\tpPed->SetObjective(OBJECTIVE_KILL_CHAR_ANY_MEANS, pTarget);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_CHAR_OBJ_KILL_PLAYER_ANY_MEANS:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tCPed* pTarget = CWorld::Players[ScriptParams[1]].m_pPed;\n\t\tpPed->bScriptObjectiveCompleted = false;\n\t\tpPed->SetObjective(OBJECTIVE_KILL_CHAR_ANY_MEANS, pTarget);\n\t\treturn 0;\n\t}\n\t/*\n\tcase COMMAND_SET_CHAR_OBJ_FLEE_CHAR_ON_FOOT_TILL_SAFE:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tCPed* pTarget = CPools::GetPedPool()->GetAt(ScriptParams[1]);\n\t\tpPed->bScriptObjectiveCompleted = false;\n\t\tpPed->SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE, pTarget);\n\t\treturn 0;\n\t}\n\t*/\n\tcase COMMAND_SET_CHAR_OBJ_FLEE_PLAYER_ON_FOOT_TILL_SAFE:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tCPed* pTarget = CWorld::Players[ScriptParams[1]].m_pPed;\n\t\tpPed->bScriptObjectiveCompleted = false;\n\t\tpPed->SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE, pTarget);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_CHAR_OBJ_FLEE_CHAR_ON_FOOT_ALWAYS:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tCPed* pTarget = CPools::GetPedPool()->GetAt(ScriptParams[1]);\n\t\tpPed->bScriptObjectiveCompleted = false;\n\t\tpPed->SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_ALWAYS, pTarget);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_CHAR_OBJ_FLEE_PLAYER_ON_FOOT_ALWAYS:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tCPed* pTarget = CWorld::Players[ScriptParams[1]].m_pPed;\n\t\tpPed->bScriptObjectiveCompleted = false;\n\t\tpPed->SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_ALWAYS, pTarget);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_CHAR_OBJ_GOTO_CHAR_ON_FOOT:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tCPed* pTarget = CPools::GetPedPool()->GetAt(ScriptParams[1]);\n\t\tpPed->bScriptObjectiveCompleted = false;\n\t\tpPed->SetObjective(OBJECTIVE_GOTO_CHAR_ON_FOOT, pTarget);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_CHAR_OBJ_GOTO_PLAYER_ON_FOOT:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tCPed* pTarget = CWorld::Players[ScriptParams[1]].m_pPed;\n\t\tpPed->bScriptObjectiveCompleted = false;\n\t\tpPed->SetObjective(OBJECTIVE_GOTO_CHAR_ON_FOOT, pTarget);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_CHAR_OBJ_LEAVE_CAR:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]);\n\t\tpPed->bScriptObjectiveCompleted = false;\n\t\tpPed->SetObjective(OBJECTIVE_LEAVE_CAR, pVehicle);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_CHAR_OBJ_ENTER_CAR_AS_PASSENGER:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]);\n\t\tpPed->bScriptObjectiveCompleted = false;\n\t\tpPed->SetObjective(OBJECTIVE_ENTER_CAR_AS_PASSENGER, pVehicle);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_CHAR_OBJ_ENTER_CAR_AS_DRIVER:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]);\n\t\tpPed->bScriptObjectiveCompleted = false;\n\t\tpPed->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, pVehicle);\n\t\treturn 0;\n\t}\n\t//case COMMAND_SET_CHAR_OBJ_FOLLOW_CAR_IN_CAR:\n\t//case COMMAND_SET_CHAR_OBJ_FIRE_AT_OBJECT_FROM_VEHICLE:\n\tcase COMMAND_SET_CHAR_OBJ_DESTROY_OBJECT:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tCObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[1]);\n\t\tpPed->bScriptObjectiveCompleted = false;\n\t\tpPed->SetObjective(OBJECTIVE_DESTROY_OBJECT, pObject);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_CHAR_OBJ_DESTROY_CAR:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]);\n\t\tpPed->bScriptObjectiveCompleted = false;\n\t\tpPed->SetObjective(OBJECTIVE_DESTROY_CAR, pVehicle);\n\t\treturn 0;\n\t}\n\t/*\n\tcase COMMAND_SET_CHAR_OBJ_GOTO_AREA_ON_FOOT:\n\t{\n\t\tCollectParameters(&m_nIp, 5);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tfloat infX = *(float*)&ScriptParams[1];\n\t\tfloat infY = *(float*)&ScriptParams[2];\n\t\tfloat supX = *(float*)&ScriptParams[3];\n\t\tfloat supY = *(float*)&ScriptParams[4];\n\t\tif (infX > supX) {\n\t\t\tinfX = *(float*)&ScriptParams[3];\n\t\t\tsupX = *(float*)&ScriptParams[1];\n\t\t}\n\t\tif (infY > supY) {\n\t\t\tinfY = *(float*)&ScriptParams[4];\n\t\t\tsupY = *(float*)&ScriptParams[2];\n\t\t}\n\t\tCVector pos;\n\t\tpos.x = (infX + supX) / 2;\n\t\tpos.y = (infY + supY) / 2;\n\t\tpos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);\n\t\tfloat radius = Max(pos.x - infX, pos.y - infY);\n\t\tpPed->bScriptObjectiveCompleted = false;\n\t\tpPed->SetObjective(OBJECTIVE_GOTO_AREA_ON_FOOT, pos, radius);\n\t\treturn 0;\n\t}\n\t*/\n\t//case COMMAND_SET_CHAR_OBJ_GOTO_AREA_IN_CAR:\n\t//case COMMAND_SET_CHAR_OBJ_FOLLOW_CAR_ON_FOOT_WITH_OFFSET:\n\t//case COMMAND_SET_CHAR_OBJ_GUARD_ATTACK:\n\tcase COMMAND_SET_CHAR_AS_LEADER:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tCPed* pTarget = CPools::GetPedPool()->GetAt(ScriptParams[1]);\n\t\tpPed->SetObjective(OBJECTIVE_SET_LEADER, pTarget);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_PLAYER_AS_LEADER:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tCPed* pTarget = CWorld::Players[ScriptParams[1]].m_pPed;\n\t\tpPed->SetObjective(OBJECTIVE_SET_LEADER, pTarget);\n\t\treturn 0;\n\t}\n\tcase COMMAND_LEAVE_GROUP:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tpPed->ClearLeader();\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_CHAR_OBJ_FOLLOW_ROUTE:\n\t{\n\t\tCollectParameters(&m_nIp, 3);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tpPed->bScriptObjectiveCompleted = false;\n\t\tpPed->SetObjective(OBJECTIVE_FOLLOW_ROUTE, ScriptParams[1], ScriptParams[2]);\n\t\treturn 0;\n\t}\n\tcase COMMAND_ADD_ROUTE_POINT:\n\t{\n\t\tCollectParameters(&m_nIp, 4);\n\t\tCRouteNode::AddRoutePoint(ScriptParams[0], *(CVector*)&ScriptParams[1]);\n\t\treturn 0;\n\t}\n\tcase COMMAND_PRINT_WITH_NUMBER_BIG:\n\t{\n\t\twchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\tCollectParameters(&m_nIp, 3);\n\t\tCMessages::AddBigMessageWithNumber(text, ScriptParams[1], ScriptParams[2] - 1, ScriptParams[0], -1, -1, -1, -1, -1);\n\t\treturn 0;\n\t}\n\tcase COMMAND_PRINT_WITH_NUMBER:\n\t{\n\t\twchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\tCollectParameters(&m_nIp, 3);\n\t\tCMessages::AddMessageWithNumber(text, ScriptParams[1], ScriptParams[2], ScriptParams[0], -1, -1, -1, -1, -1);\n\t\treturn 0;\n\t}\n\tcase COMMAND_PRINT_WITH_NUMBER_NOW:\n\t{\n\t\twchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\tCollectParameters(&m_nIp, 3);\n\t\tCMessages::AddMessageJumpQWithNumber(text, ScriptParams[1], ScriptParams[2], ScriptParams[0], -1, -1, -1, -1, -1);\n\t\treturn 0;\n\t}\n\t//case COMMAND_PRINT_WITH_NUMBER_SOON:\n\tcase COMMAND_SWITCH_ROADS_ON:\n\t{\n\t\tCollectParameters(&m_nIp, 6);\n\t\tfloat infX = *(float*)&ScriptParams[0];\n\t\tfloat infY = *(float*)&ScriptParams[1];\n\t\tfloat infZ = *(float*)&ScriptParams[2];\n\t\tfloat supX = *(float*)&ScriptParams[3];\n\t\tfloat supY = *(float*)&ScriptParams[4];\n\t\tfloat supZ = *(float*)&ScriptParams[5];\n\t\tif (infX > supX){\n\t\t\tinfX = *(float*)&ScriptParams[3];\n\t\t\tsupX = *(float*)&ScriptParams[0];\n\t\t}\n\t\tif (infY > supY){\n\t\t\tinfY = *(float*)&ScriptParams[4];\n\t\t\tsupY = *(float*)&ScriptParams[1];\n\t\t}\n\t\tif (infZ > supZ){\n\t\t\tinfZ = *(float*)&ScriptParams[5];\n\t\t\tsupZ = *(float*)&ScriptParams[2];\n\t\t}\n\t\tThePaths.SwitchRoadsOffInArea(infX, supX, infY, supY, infZ, supZ, false);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SWITCH_ROADS_OFF:\n\t{\n\t\tCollectParameters(&m_nIp, 6);\n\t\tfloat infX = *(float*)&ScriptParams[0];\n\t\tfloat infY = *(float*)&ScriptParams[1];\n\t\tfloat infZ = *(float*)&ScriptParams[2];\n\t\tfloat supX = *(float*)&ScriptParams[3];\n\t\tfloat supY = *(float*)&ScriptParams[4];\n\t\tfloat supZ = *(float*)&ScriptParams[5];\n\t\tif (infX > supX) {\n\t\t\tinfX = *(float*)&ScriptParams[3];\n\t\t\tsupX = *(float*)&ScriptParams[0];\n\t\t}\n\t\tif (infY > supY) {\n\t\t\tinfY = *(float*)&ScriptParams[4];\n\t\t\tsupY = *(float*)&ScriptParams[1];\n\t\t}\n\t\tif (infZ > supZ) {\n\t\t\tinfZ = *(float*)&ScriptParams[5];\n\t\t\tsupZ = *(float*)&ScriptParams[2];\n\t\t}\n\t\tThePaths.SwitchRoadsOffInArea(infX, supX, infY, supY, infZ, supZ, true);\n\t\treturn 0;\n\t}\n\tcase COMMAND_GET_NUMBER_OF_PASSENGERS:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tScriptParams[0] = pVehicle->m_nNumPassengers;\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\tcase COMMAND_GET_MAXIMUM_NUMBER_OF_PASSENGERS:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tScriptParams[0] = pVehicle->m_nNumMaxPassengers;\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_CAR_DENSITY_MULTIPLIER:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCCarCtrl::CarDensityMultiplier = *(float*)&ScriptParams[0];\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_CAR_HEAVY:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tif (ScriptParams[1] != 0) {\n\t\t\tpVehicle->bIsHeavy = true;\n\t\t\tpVehicle->m_fMass = 3.0f * pVehicle->pHandling->fMass;\n\t\t\tpVehicle->m_fTurnMass = 5.0f * pVehicle->pHandling->fTurnMass;\n\t\t}\n\t\telse {\n\t\t\tpVehicle->bIsHeavy = false;\n\t\t\tpVehicle->m_fMass = pVehicle->pHandling->fMass;\n\t\t\tpVehicle->m_fTurnMass = pVehicle->pHandling->fTurnMass;\n\t\t}\n\t\treturn 0;\n\t}\n\tcase COMMAND_CLEAR_CHAR_THREAT_SEARCH:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tpPed->m_fearFlags = 0;\n\t\treturn 0;\n\t}\n\t/*\n\tcase COMMAND_ACTIVATE_CRANE:\n\t{\n\t\tCollectParameters(&m_nIp, 10);\n\t\tfloat infX = *(float*)&ScriptParams[2];\n\t\tfloat infY = *(float*)&ScriptParams[3];\n\t\tfloat supX = *(float*)&ScriptParams[4];\n\t\tfloat supY = *(float*)&ScriptParams[5];\n\t\tif (infX > supX) {\n\t\t\tinfX = *(float*)&ScriptParams[4];\n\t\t\tsupX = *(float*)&ScriptParams[2];\n\t\t}\n\t\tif (infY > supY) {\n\t\t\tinfY = *(float*)&ScriptParams[5];\n\t\t\tsupY = *(float*)&ScriptParams[3];\n\t\t}\n\t\tCCranes::ActivateCrane(infX, supX, infY, supY,\n\t\t\t*(float*)&ScriptParams[6], *(float*)&ScriptParams[7], *(float*)&ScriptParams[8],\n\t\t\tDEGTORAD(*(float*)&ScriptParams[9]), false, false,\n\t\t\t*(float*)&ScriptParams[0], *(float*)&ScriptParams[1]);\n\t\treturn 0;\n\t}\n\tcase COMMAND_DEACTIVATE_CRANE:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCCranes::DeActivateCrane(*(float*)&ScriptParams[0], *(float*)&ScriptParams[1]);\n\t\treturn 0;\n\t}\n\t*/\n\tcase COMMAND_SET_MAX_WANTED_LEVEL:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCWanted::SetMaximumWantedLevel(ScriptParams[0]);\n\t\treturn 0;\n\t}\n\t//case COMMAND_SAVE_VAR_INT:\n\t//case COMMAND_SAVE_VAR_FLOAT:\n\tcase COMMAND_IS_CAR_IN_AIR_PROPER:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tUpdateCompareFlag(pVehicle->m_nCollisionRecords == 0);\n\t\treturn 0;\n\t}\n\tdefault:\n\t\tscript_assert(0);\n\t}\n\treturn -1;\n}\n"
  },
  {
    "path": "src/control/Script3.cpp",
    "content": "#include \"common.h\"\n\n#include \"Script.h\"\n#include \"ScriptCommands.h\"\n\n#include \"Boat.h\"\n#include \"CarCtrl.h\"\n#include \"Clock.h\"\n#include \"Coronas.h\"\n#include \"Cranes.h\"\n#include \"CutsceneMgr.h\"\n#include \"Darkel.h\"\n#include \"Explosion.h\"\n#include \"Fire.h\"\n#include \"General.h\"\n#include \"Garages.h\"\n#include \"Heli.h\"\n#include \"Messages.h\"\n#include \"Pad.h\"\n#include \"ParticleObject.h\"\n#include \"Phones.h\"\n#include \"Pickups.h\"\n#include \"PointLights.h\"\n#include \"Population.h\"\n#include \"Pools.h\"\n#include \"ProjectileInfo.h\"\n#include \"Radar.h\"\n#include \"Restart.h\"\n#include \"Stats.h\"\n#include \"Streaming.h\"\n#include \"User.h\"\n#include \"WaterLevel.h\"\n#include \"Weather.h\"\n#include \"Zones.h\"\n#include \"GameLogic.h\"\n#include \"Bike.h\"\n#include \"Wanted.h\"\n\nint8 CRunningScript::ProcessCommands500To599(int32 command)\n{\n\tswitch (command) {\n\tcase COMMAND_IS_CAR_UPSIDEDOWN:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tUpdateCompareFlag(pVehicle->GetUp().z <= -0.97f);\n\t\treturn 0;\n\t}\n\tcase COMMAND_GET_PLAYER_CHAR:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;\n\t\tscript_assert(pPed);\n\t\tScriptParams[0] = CPools::GetPedPool()->GetIndex(pPed);\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\tcase COMMAND_CANCEL_OVERRIDE_RESTART:\n\t\tCRestart::CancelOverrideRestart();\n\t\treturn 0;\n\tcase COMMAND_SET_POLICE_IGNORE_PLAYER:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;\n\t\tscript_assert(pPed);\n\t\tif (ScriptParams[1]) {\n\t\t\tpPed->m_pWanted->m_bIgnoredByCops = true;\n\t\t\tCWorld::StopAllLawEnforcersInTheirTracks();\n\t\t}\n\t\telse {\n\t\t\tpPed->m_pWanted->m_bIgnoredByCops = false;\n\t\t}\n\t\treturn 0;\n\t}\n\t/*\n\tcase COMMAND_ADD_PAGER_MESSAGE_WITH_NUMBER:\n\t{\n\t\twchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\tCollectParameters(&m_nIp, 4);\n\t\tCUserDisplay::Pager.AddMessageWithNumber(text, ScriptParams[0], -1, -1, -1, -1, -1,\n\t\t\tScriptParams[1], ScriptParams[2], ScriptParams[3]);\n\t\treturn 0;\n\t}\n\t*/\n\tcase COMMAND_START_KILL_FRENZY:\n\t{\n\t\twchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\tCollectParameters(&m_nIp, 8);\n\t\tCDarkel::StartFrenzy((eWeaponType)ScriptParams[0], ScriptParams[1], ScriptParams[2],\n\t\t\tScriptParams[3], text, ScriptParams[4], ScriptParams[5],\n\t\t\tScriptParams[6], ScriptParams[7] != 0, false);\n\t\treturn 0;\n\t}\n\tcase COMMAND_READ_KILL_FRENZY_STATUS:\n\t{\n\t\tScriptParams[0] = CDarkel::ReadStatus();\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SQRT:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\t*(float*)&ScriptParams[0] = Sqrt(*(float*)&ScriptParams[0]);\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\tcase COMMAND_LOCATE_PLAYER_ANY_MEANS_CAR_2D:\n\tcase COMMAND_LOCATE_PLAYER_ON_FOOT_CAR_2D:\n\tcase COMMAND_LOCATE_PLAYER_IN_CAR_CAR_2D:\n\tcase COMMAND_LOCATE_PLAYER_ANY_MEANS_CAR_3D:\n\tcase COMMAND_LOCATE_PLAYER_ON_FOOT_CAR_3D:\n\tcase COMMAND_LOCATE_PLAYER_IN_CAR_CAR_3D:\n\t\tLocatePlayerCarCommand(command, &m_nIp);\n\t\treturn 0;\n\tcase COMMAND_LOCATE_CHAR_ANY_MEANS_CAR_2D:\n\tcase COMMAND_LOCATE_CHAR_ON_FOOT_CAR_2D:\n\tcase COMMAND_LOCATE_CHAR_IN_CAR_CAR_2D:\n\tcase COMMAND_LOCATE_CHAR_ANY_MEANS_CAR_3D:\n\tcase COMMAND_LOCATE_CHAR_ON_FOOT_CAR_3D:\n\tcase COMMAND_LOCATE_CHAR_IN_CAR_CAR_3D:\n\t\tLocateCharCarCommand(command, &m_nIp);\n\t\treturn 0;\n\tcase COMMAND_GENERATE_RANDOM_FLOAT_IN_RANGE:\n\t\tCollectParameters(&m_nIp, 2);\n\t\t*(float*)&ScriptParams[0] = CGeneral::GetRandomNumberInRange(*(float*)&ScriptParams[0], *(float*)&ScriptParams[1]);\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\tcase COMMAND_GENERATE_RANDOM_INT_IN_RANGE:\n\t\tCollectParameters(&m_nIp, 2);\n\t\tScriptParams[0] = CGeneral::GetRandomNumberInRange(ScriptParams[0], ScriptParams[1]);\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\tcase COMMAND_LOCK_CAR_DOORS:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tpVehicle->m_nDoorLock = (eCarLock)ScriptParams[1];\n\t\treturn 0;\n\t}\n\tcase COMMAND_EXPLODE_CAR:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tpVehicle->BlowUpCar(nil);\n\t\treturn 0;\n\t}\n\tcase COMMAND_ADD_EXPLOSION:\n\t\tCollectParameters(&m_nIp, 4);\n\t\tCExplosion::AddExplosion(nil, nil, (eExplosionType)ScriptParams[3], *(CVector*)&ScriptParams[0], 0, true);\n\t\treturn 0;\n\n\tcase COMMAND_IS_CAR_UPRIGHT:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tUpdateCompareFlag(pVehicle->GetUp().z >= 0.0f);\n\t\treturn 0;\n\t}\n\tcase COMMAND_TURN_CHAR_TO_FACE_CHAR:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pSourcePed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tCPed* pTargetPed = CPools::GetPedPool()->GetAt(ScriptParams[1]);\n\t\tCVehicle* pVehicle = pSourcePed->bInVehicle ? pSourcePed->m_pMyVehicle : nil;\n\t\tCVector2D sourcePos = pSourcePed->bInVehicle ? pVehicle->GetPosition() : pSourcePed->GetPosition();\n\t\tCVector2D targetPos = pTargetPed->bInVehicle ? pTargetPed->m_pMyVehicle->GetPosition() : pTargetPed->GetPosition();\n\t\tfloat angle = CGeneral::GetATanOfXY(sourcePos.x - targetPos.x, sourcePos.y - targetPos.y) + HALFPI;\n\t\tif (angle > TWOPI)\n\t\t\tangle -= TWOPI;\n\t\tif (!pVehicle) {\n\t\t\tpSourcePed->m_fRotationCur = angle;\n\t\t\tpSourcePed->m_fRotationDest = angle;\n\t\t\tpSourcePed->SetHeading(angle);\n\t\t}\n\t\treturn 0;\n\t}\n\tcase COMMAND_TURN_CHAR_TO_FACE_PLAYER:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pSourcePed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tCPed* pTargetPed = CWorld::Players[ScriptParams[1]].m_pPed;\n\t\tCVehicle* pVehicle = pSourcePed->bInVehicle ? pSourcePed->m_pMyVehicle : nil;\n\t\tCVector2D sourcePos = pSourcePed->bInVehicle ? pVehicle->GetPosition() : pSourcePed->GetPosition();\n\t\tCVector2D targetPos = pTargetPed->bInVehicle ? pTargetPed->m_pMyVehicle->GetPosition() : pTargetPed->GetPosition();\n\t\tfloat angle = CGeneral::GetATanOfXY(sourcePos.x - targetPos.x, sourcePos.y - targetPos.y) + HALFPI;\n\t\tif (angle > TWOPI)\n\t\t\tangle -= TWOPI;\n\t\tif (!pVehicle) {\n\t\t\tpSourcePed->m_fRotationCur = angle;\n\t\t\tpSourcePed->m_fRotationDest = angle;\n\t\t\tpSourcePed->SetHeading(angle);\n\t\t}\n\t\treturn 0;\n\t}\n\tcase COMMAND_TURN_PLAYER_TO_FACE_CHAR:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pSourcePed = CWorld::Players[ScriptParams[0]].m_pPed;\n\t\tCPed* pTargetPed = CPools::GetPedPool()->GetAt(ScriptParams[1]);\n\t\tCVehicle* pVehicle = pSourcePed->bInVehicle ? pSourcePed->m_pMyVehicle : nil;\n\t\tCVector2D sourcePos = pSourcePed->bInVehicle ? pVehicle->GetPosition() : pSourcePed->GetPosition();\n\t\tCVector2D targetPos = pTargetPed->bInVehicle ? pTargetPed->m_pMyVehicle->GetPosition() : pTargetPed->GetPosition();\n\t\tfloat angle = CGeneral::GetATanOfXY(sourcePos.x - targetPos.x, sourcePos.y - targetPos.y) + HALFPI;\n\t\tif (angle > TWOPI)\n\t\t\tangle -= TWOPI;\n\t\tif (!pVehicle) {\n\t\t\tpSourcePed->m_fRotationCur = angle;\n\t\t\tpSourcePed->m_fRotationDest = angle;\n\t\t\tpSourcePed->SetHeading(angle);\n\t\t}\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_CHAR_OBJ_GOTO_COORD_ON_FOOT:\n\t{\n\t\tCollectParameters(&m_nIp, 3);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tCVector target;\n\t\ttarget.x = *(float*)&ScriptParams[1];\n\t\ttarget.y = *(float*)&ScriptParams[2];\n\t\ttarget.z = CWorld::FindGroundZForCoord(target.x, target.y);\n\t\tpPed->bScriptObjectiveCompleted = false;\n\t\tpPed->SetObjective(OBJECTIVE_GOTO_AREA_ON_FOOT, target);\n\t\treturn 0;\n\t}\n\t//case COMMAND_SET_CHAR_OBJ_GOTO_COORD_IN_CAR:\n\tcase COMMAND_CREATE_PICKUP:\n\t{\n\t\tCollectParameters(&m_nIp, 5);\n\t\tint16 model = ScriptParams[0];\n\t\tif (model < 0)\n\t\t\tmodel = CTheScripts::UsedObjectArray[-model].index;\n\t\tCVector pos = *(CVector*)&ScriptParams[2];\n\t\tif (pos.z <= MAP_Z_LOW_LIMIT)\n\t\t\tpos.z = CWorld::FindGroundZForCoord(pos.x, pos.y) + PICKUP_PLACEMENT_OFFSET;\n\t\tCPickups::GetActualPickupIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));\n\t\tScriptParams[0] = CPickups::GenerateNewOne(pos, model, ScriptParams[1], 0);\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\tcase COMMAND_HAS_PICKUP_BEEN_COLLECTED:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tUpdateCompareFlag(CPickups::IsPickUpPickedUp(ScriptParams[0]) != 0);\n\t\treturn 0;\n\tcase COMMAND_REMOVE_PICKUP:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPickups::RemovePickUp(ScriptParams[0]);\n\t\treturn 0;\n\tcase COMMAND_SET_TAXI_LIGHTS:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tscript_assert(pVehicle->m_vehType == VEHICLE_TYPE_CAR);\n\t\t((CAutomobile*)pVehicle)->SetTaxiLight(ScriptParams[1] != 0);\n\t\treturn 0;\n\t}\n\tcase COMMAND_PRINT_BIG_Q:\n\t{\n\t\twchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCMessages::AddBigMessageQ(text, ScriptParams[0], ScriptParams[1] - 1);\n\t\treturn 0;\n\t}\n\t/*\n\tcase COMMAND_PRINT_WITH_NUMBER_BIG_Q:\n\t{\n\t\twchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\tCollectParameters(&m_nIp, 3);\n\t\tCMessages::AddBigMessageWithNumberQ(text, ScriptParams[1], ScriptParams[2] - 1,\n\t\t\tScriptParams[0], -1, -1, -1, -1, -1);\n\t\treturn 0;\n\t}\n\t*/\n\tcase COMMAND_SET_GARAGE:\n\t{\n\t\tCollectParameters(&m_nIp, 9);\n\t\tfloat infX = *(float*)&ScriptParams[0];\n\t\tfloat infY = *(float*)&ScriptParams[1];\n\t\tfloat infZ = *(float*)&ScriptParams[2];\n\t\tfloat X2 = *(float*)&ScriptParams[3];\n\t\tfloat Y2 = *(float*)&ScriptParams[4];\n\t\tfloat supX = *(float*)&ScriptParams[5];\n\t\tfloat supY = *(float*)&ScriptParams[6];\n\t\tfloat supZ = *(float*)&ScriptParams[7];\n\t\tScriptParams[0] = CGarages::AddOne(infX, infY, infZ, X2, Y2, supX, supY, supZ, ScriptParams[8], 0);\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\t/*\n\tcase COMMAND_SET_GARAGE_WITH_CAR_MODEL:\n\t{\n\t\tCollectParameters(&m_nIp, 10);\n\t\tfloat infX = *(float*)&ScriptParams[0];\n\t\tfloat infY = *(float*)&ScriptParams[1];\n\t\tfloat infZ = *(float*)&ScriptParams[2];\n\t\tfloat X2 = *(float*)&ScriptParams[3];\n\t\tfloat Y2 = *(float*)&ScriptParams[4];\n\t\tfloat supX = *(float*)&ScriptParams[5];\n\t\tfloat supY = *(float*)&ScriptParams[6];\n\t\tfloat supZ = *(float*)&ScriptParams[7];\n\t\tScriptParams[0] = CGarages::AddOne(infX, infY, infZ, X2, Y2, supX, supY, supZ, ScriptParams[8], ScriptParams[9]);\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\t*/\n\tcase COMMAND_SET_TARGET_CAR_FOR_MISSION_GARAGE:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCVehicle* pTarget;\n\t\tif (ScriptParams[1] >= 0) {\n\t\t\tpTarget = CPools::GetVehiclePool()->GetAt(ScriptParams[1]);\n\t\t\tscript_assert(pTarget);\n\t\t}\n\t\telse {\n\t\t\tpTarget = nil;\n\t\t}\n\t\tCGarages::SetTargetCarForMissonGarage(ScriptParams[0], pTarget);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_CAR_IN_MISSION_GARAGE:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tUpdateCompareFlag(CGarages::HasCarBeenDroppedOffYet(ScriptParams[0]));\n\t\treturn 0;\n/*\n\tcase COMMAND_SET_FREE_BOMBS:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCGarages::SetFreeBombs(ScriptParams[0] != 0);\n\t\treturn 0;\n\tcase COMMAND_SET_POWERPOINT:\n\t{\n\t\tCollectParameters(&m_nIp, 7);\n\t\tfloat f1 = *(float*)&ScriptParams[0];\n\t\tfloat f2 = *(float*)&ScriptParams[1];\n\t\tfloat f3 = *(float*)&ScriptParams[2];\n\t\tfloat f4 = *(float*)&ScriptParams[3];\n\t\tfloat f5 = *(float*)&ScriptParams[4];\n\t\tfloat f6 = *(float*)&ScriptParams[5];\n\t\tfloat temp;\n\n\t\tif (f1 > f4) {\n\t\t\ttemp = f1;\n\t\t\tf1 = f4;\n\t\t\tf4 = temp;\n\t\t}\n\n\t\tif (f2 > f5) {\n\t\t\ttemp = f2;\n\t\t\tf2 = f5;\n\t\t\tf5 = temp;\n\t\t}\n\n\t\tif (f3 > f6) {\n\t\t\ttemp = f3;\n\t\t\tf3 = f6;\n\t\t\tf6 = temp;\n\t\t}\n\n\t\tCPowerPoints::GenerateNewOne(f1, f2, f3, f4, f5, f6, *(uint8*)&ScriptParams[6]);\n\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_ALL_TAXI_LIGHTS:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCAutomobile::SetAllTaxiLights(ScriptParams[0] != 0);\n\t\treturn 0;\n\tcase COMMAND_IS_CAR_ARMED_WITH_ANY_BOMB:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCAutomobile* pCar = (CAutomobile*)CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pCar);\n\t\tscript_assert(pCar->m_vehType == VEHICLE_TYPE_CAR);\n\t\tUpdateCompareFlag(pCar->m_bombType != 0); //TODO: enum\n\t\treturn 0;\n\t}\n\t*/\n\tcase COMMAND_APPLY_BRAKES_TO_PLAYERS_CAR:\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPad::GetPad(ScriptParams[0])->bApplyBrakes = (ScriptParams[1] != 0);\n\t\treturn 0;\n\tcase COMMAND_SET_PLAYER_HEALTH:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;\n\t\tscript_assert(pPed);\n\t\tpPed->m_fHealth = Min(ScriptParams[1], CWorld::Players[ScriptParams[0]].m_nMaxHealth);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_CHAR_HEALTH:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tif (ScriptParams[1]) {\n\t\t\tpPed->m_fHealth = ScriptParams[1];\n\t\t}\n\t\telse if (pPed->bInVehicle) {\n\t\t\tpPed->SetDead();\n\t\t\tif (!pPed->IsPlayer())\n\t\t\t\tpPed->FlagToDestroyWhenNextProcessed();\n\t\t}\n\t\telse {\n\t\t\tpPed->SetDie();\n\t\t}\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_CAR_HEALTH:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tpVehicle->m_fHealth = ScriptParams[1];\n\t\treturn 0;\n\t}\n\tcase COMMAND_GET_PLAYER_HEALTH:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;\n\t\tscript_assert(pPed);\n\t\tScriptParams[0] = pPed->m_fHealth;\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\tcase COMMAND_GET_CHAR_HEALTH:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tScriptParams[0] = pPed->m_fHealth;\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\tcase COMMAND_GET_CAR_HEALTH:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tScriptParams[0] = pVehicle->m_fHealth;\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\t/*\n\tcase COMMAND_IS_CAR_ARMED_WITH_BOMB:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCAutomobile* pCar = (CAutomobile*)CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pCar);\n\t\tscript_assert(pCar->m_vehType == VEHICLE_TYPE_CAR);\n\t\tUpdateCompareFlag(pCar->m_bombType == ScriptParams[1]);\n\t\treturn 0;\n\t}\n\t*/\n\tcase COMMAND_CHANGE_CAR_COLOUR:\n\t{\n\t\tCollectParameters(&m_nIp, 3);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tif (ScriptParams[1] >= 256 || ScriptParams[2] >= 256)\n\t\t\tdebug(\"CHANGE_CAR_COLOUR - Colours must be less than %d\", 256);\n\t\tpVehicle->m_currentColour1 = ScriptParams[1];\n\t\tpVehicle->m_currentColour2 = ScriptParams[2];\n\t\treturn 0;\n\t}\n\tcase COMMAND_SWITCH_PED_ROADS_ON:\n\t{\n\t\tCollectParameters(&m_nIp, 6);\n\t\tfloat infX = *(float*)&ScriptParams[0];\n\t\tfloat infY = *(float*)&ScriptParams[1];\n\t\tfloat infZ = *(float*)&ScriptParams[2];\n\t\tfloat supX = *(float*)&ScriptParams[3];\n\t\tfloat supY = *(float*)&ScriptParams[4];\n\t\tfloat supZ = *(float*)&ScriptParams[5];\n\t\tif (infX > supX) {\n\t\t\tinfX = *(float*)&ScriptParams[3];\n\t\t\tsupX = *(float*)&ScriptParams[0];\n\t\t}\n\t\tif (infY > supY) {\n\t\t\tinfY = *(float*)&ScriptParams[4];\n\t\t\tsupY = *(float*)&ScriptParams[1];\n\t\t}\n\t\tif (infZ > supZ) {\n\t\t\tinfZ = *(float*)&ScriptParams[5];\n\t\t\tsupZ = *(float*)&ScriptParams[2];\n\t\t}\n\t\tThePaths.SwitchPedRoadsOffInArea(infX, supX, infY, supY, infZ, supZ, false);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SWITCH_PED_ROADS_OFF:\n\t{\n\t\tCollectParameters(&m_nIp, 6);\n\t\tfloat infX = *(float*)&ScriptParams[0];\n\t\tfloat infY = *(float*)&ScriptParams[1];\n\t\tfloat infZ = *(float*)&ScriptParams[2];\n\t\tfloat supX = *(float*)&ScriptParams[3];\n\t\tfloat supY = *(float*)&ScriptParams[4];\n\t\tfloat supZ = *(float*)&ScriptParams[5];\n\t\tif (infX > supX) {\n\t\t\tinfX = *(float*)&ScriptParams[3];\n\t\t\tsupX = *(float*)&ScriptParams[0];\n\t\t}\n\t\tif (infY > supY) {\n\t\t\tinfY = *(float*)&ScriptParams[4];\n\t\t\tsupY = *(float*)&ScriptParams[1];\n\t\t}\n\t\tif (infZ > supZ) {\n\t\t\tinfZ = *(float*)&ScriptParams[5];\n\t\t\tsupZ = *(float*)&ScriptParams[2];\n\t\t}\n\t\tThePaths.SwitchPedRoadsOffInArea(infX, supX, infY, supY, infZ, supZ, true);\n\t\treturn 0;\n\t}\n\tcase COMMAND_CHAR_LOOK_AT_CHAR_ALWAYS:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pSourcePed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pSourcePed);\n\t\tCPed* pTargetPed = CPools::GetPedPool()->GetAt(ScriptParams[1]);\n\t\tscript_assert(pTargetPed);\n\t\tpSourcePed->SetLookFlag(pTargetPed, true);\n\t\tpSourcePed->SetLookTimer(60000);\n\t\treturn 0;\n\t}\n\tcase COMMAND_CHAR_LOOK_AT_PLAYER_ALWAYS:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pSourcePed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pSourcePed);\n\t\tCPed* pTargetPed = CWorld::Players[ScriptParams[1]].m_pPed;\n\t\tscript_assert(pTargetPed);\n\t\tpSourcePed->SetLookFlag(pTargetPed, true);\n\t\tpSourcePed->SetLookTimer(60000);\n\t\treturn 0;\n\t}\n\tcase COMMAND_PLAYER_LOOK_AT_CHAR_ALWAYS:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pSourcePed = CWorld::Players[ScriptParams[0]].m_pPed;\n\t\tscript_assert(pSourcePed);\n\t\tCPed* pTargetPed = CPools::GetPedPool()->GetAt(ScriptParams[1]);\n\t\tscript_assert(pTargetPed);\n\t\tpSourcePed->SetLookFlag(pTargetPed, true);\n\t\tpSourcePed->SetLookTimer(60000);\n\t\treturn 0;\n\t}\n\tcase COMMAND_STOP_CHAR_LOOKING:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* pSourcePed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pSourcePed);\n\t\tpSourcePed->ClearLookFlag();\n\t\tpSourcePed->bKeepTryingToLook = false;\n\t\tif (pSourcePed->GetPedState() == PED_LOOK_HEADING || pSourcePed->GetPedState() == PED_LOOK_ENTITY)\n\t\t\tpSourcePed->RestorePreviousState();\n\t\treturn 0;\n\t}\n\tcase COMMAND_STOP_PLAYER_LOOKING:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* pSourcePed = CWorld::Players[ScriptParams[0]].m_pPed;\n\t\tscript_assert(pSourcePed);\n\t\tpSourcePed->ClearLookFlag();\n\t\tpSourcePed->bKeepTryingToLook = false;\n\t\tif (pSourcePed->GetPedState() == PED_LOOK_HEADING || pSourcePed->GetPedState() == PED_LOOK_ENTITY)\n\t\t\tpSourcePed->RestorePreviousState();\n\t\treturn 0;\n\t}\n\t/*\n\tcase COMMAND_SWITCH_HELICOPTER:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCHeli::ActivateHeli(ScriptParams[0] != 0);\n\t\treturn 0;\n\t*/\n\t//case COMMAND_SET_GANG_ATTITUDE:\n\t//case COMMAND_SET_GANG_GANG_ATTITUDE:\n\t//case COMMAND_SET_GANG_PLAYER_ATTITUDE:\n\tcase COMMAND_SET_GANG_PED_MODELS:\n\t\tCollectParameters(&m_nIp, 3);\n\t\tCGangs::SetGangPedModels(ScriptParams[0], ScriptParams[1], ScriptParams[2]);\n\t\treturn 0;\n\tcase COMMAND_SET_GANG_CAR_MODEL:\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCGangs::SetGangVehicleModel(ScriptParams[0], ScriptParams[1]);\n\t\treturn 0;\n\tcase COMMAND_SET_GANG_WEAPONS:\n\t\tCollectParameters(&m_nIp, 3);\n\t\tCGangs::SetGangWeapons(ScriptParams[0], (eWeaponType)ScriptParams[1], (eWeaponType)ScriptParams[2]);\n\t\treturn 0;\n\t/*\n\tcase COMMAND_SET_CHAR_OBJ_RUN_TO_AREA:\n\t{\n\t\tCollectParameters(&m_nIp, 5);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tfloat infX = *(float*)&ScriptParams[1];\n\t\tfloat infY = *(float*)&ScriptParams[2];\n\t\tfloat supX = *(float*)&ScriptParams[3];\n\t\tfloat supY = *(float*)&ScriptParams[4];\n\t\tif (infX > supX) {\n\t\t\tinfX = *(float*)&ScriptParams[3];\n\t\t\tsupX = *(float*)&ScriptParams[1];\n\t\t}\n\t\tif (infY > supY) {\n\t\t\tinfY = *(float*)&ScriptParams[4];\n\t\t\tsupY = *(float*)&ScriptParams[2];\n\t\t}\n\t\tCVector pos;\n\t\tpos.x = (infX + supX) / 2;\n\t\tpos.y = (infY + supY) / 2;\n\t\tpos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);\n\t\tfloat radius = Max(pos.x - infX, pos.y - infY);\n\t\tpPed->bScriptObjectiveCompleted = false;\n\t\tpPed->SetObjective(OBJECTIVE_RUN_TO_AREA, pos, radius);\n\t\treturn 0;\n\t}\n\t*/\n\tcase COMMAND_SET_CHAR_OBJ_RUN_TO_COORD:\n\t{\n\t\tCollectParameters(&m_nIp, 3);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tCVector pos;\n\t\tpos.x = *(float*)&ScriptParams[1];\n\t\tpos.y = *(float*)&ScriptParams[2];\n\t\tpos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);\n\t\tpPed->bScriptObjectiveCompleted = false;\n\t\tpPed->SetObjective(OBJECTIVE_RUN_TO_AREA, pos);\n\t\treturn 0;\n\t}\n\t/*\n\tcase COMMAND_IS_PLAYER_TOUCHING_OBJECT_ON_FOOT:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;\n\t\tscript_assert(pPed);\n\t\tCObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[1]);\n\t\tbool isTouching = false;\n\t\tif (pPed->bInVehicle)\n\t\t\tisTouching = false;\n\t\telse if (pPed->GetHasCollidedWith(pObject))\n\t\t\tisTouching = true;\n\t\tUpdateCompareFlag(isTouching);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_CHAR_TOUCHING_OBJECT_ON_FOOT:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tCObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[1]);\n\t\tbool isTouching = false;\n\t\tif (pPed->InVehicle())\n\t\t\tisTouching = false;\n\t\telse if (pPed->GetHasCollidedWith(pObject))\n\t\t\tisTouching = true;\n\t\tUpdateCompareFlag(isTouching);\n\t\treturn 0;\n\t}\n\t*/\n\tcase COMMAND_LOAD_SPECIAL_CHARACTER:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tchar name[16];\n\t\tstrncpy(name, (char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT);\n\t\tfor (int i = 0; i < KEY_LENGTH_IN_SCRIPT; i++)\n\t\t\tname[i] = tolower(name[i]);\n\t\tCStreaming::RequestSpecialChar(ScriptParams[0] - 1, name, STREAMFLAGS_DEPENDENCY | STREAMFLAGS_SCRIPTOWNED);\n\t\tm_nIp += KEY_LENGTH_IN_SCRIPT;\n\t\treturn 0;\n\t}\n\tcase COMMAND_HAS_SPECIAL_CHARACTER_LOADED:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tUpdateCompareFlag(CStreaming::HasSpecialCharLoaded(ScriptParams[0] - 1));\n\t\treturn 0;\n\t}\n\t/*\n\tcase COMMAND_FLASH_CAR:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tpVehicle->bHasBlip = (ScriptParams[1] != 0);\n\t\treturn 0;\n\t}\n\tcase COMMAND_FLASH_CHAR:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tpPed->bHasBlip = (ScriptParams[1] != 0);\n\t\treturn 0;\n\t}\n\tcase COMMAND_FLASH_OBJECT:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pObject);\n\t\tpObject->bHasBlip = (ScriptParams[1] != 0);\n\t\treturn 0;\n\t}\n\t*/\n\tcase COMMAND_IS_PLAYER_IN_REMOTE_MODE:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tUpdateCompareFlag(CWorld::Players[ScriptParams[0]].IsPlayerInRemoteMode());\n\t\treturn 0;\n\t/*\n\tcase COMMAND_ARM_CAR_WITH_BOMB:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tscript_assert(pVehicle->m_vehType == VEHICLE_TYPE_CAR);\n\t\t((CAutomobile*)pVehicle)->m_bombType = ScriptParams[1];\n\t\t((CAutomobile*)pVehicle)->m_pBombRigger = FindPlayerPed();\n\t\treturn 0;\n\t}\n\t*/\n\tcase COMMAND_SET_CHAR_PERSONALITY:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tpPed->SetPedStats((ePedStats)ScriptParams[1]);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_CUTSCENE_OFFSET:\n\t\tCollectParameters(&m_nIp, 3);\n\t\tCCutsceneMgr::SetCutsceneOffset(*(CVector*)&ScriptParams[0]);\n\t\treturn 0;\n\tcase COMMAND_SET_ANIM_GROUP_FOR_CHAR:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tpPed->m_animGroup = (AssocGroupId)ScriptParams[1];\n\t\treturn 0;\n\t}\n\t/*\n\tcase COMMAND_SET_ANIM_GROUP_FOR_PLAYER:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;\n\t\tscript_assert(pPed);\n\t\tpPed->m_animGroup = (AssocGroupId)ScriptParams[1];\n\t\treturn 0;\n\t}\n\t*/\n\tcase COMMAND_REQUEST_MODEL:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tint model = ScriptParams[0];\n\t\tif (model < 0)\n\t\t\tmodel = CTheScripts::UsedObjectArray[-model].index;\n\t\tCStreaming::RequestModel(model, STREAMFLAGS_DEPENDENCY | STREAMFLAGS_NOFADE | STREAMFLAGS_SCRIPTOWNED);\n\t\treturn 0;\n\t}\n\tcase COMMAND_HAS_MODEL_LOADED:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tint model = ScriptParams[0];\n\t\tif (model < 0)\n\t\t\tmodel = CTheScripts::UsedObjectArray[-model].index;\n\t\tUpdateCompareFlag(CStreaming::HasModelLoaded(model));\n\t\treturn 0;\n\t}\n\tcase COMMAND_MARK_MODEL_AS_NO_LONGER_NEEDED:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tint model = ScriptParams[0];\n\t\tif (model < 0)\n\t\t\tmodel = CTheScripts::UsedObjectArray[-model].index;\n\t\tCStreaming::SetMissionDoesntRequireModel(model);\n\t\treturn 0;\n\t}\n\tcase COMMAND_GRAB_PHONE:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tScriptParams[0] = gPhoneInfo.GrabPhone(*(float*)&ScriptParams[0], *(float*)&ScriptParams[1]);\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\t/*\n\tcase COMMAND_SET_REPEATED_PHONE_MESSAGE:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\twchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\tgPhoneInfo.SetPhoneMessage_Repeatedly(ScriptParams[0], text, nil, nil, nil, nil, nil);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_PHONE_MESSAGE:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\twchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\tgPhoneInfo.SetPhoneMessage_JustOnce(ScriptParams[0], text, nil, nil, nil, nil, nil);\n\t\treturn 0;\n\t}\n\tcase COMMAND_HAS_PHONE_DISPLAYED_MESSAGE:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tUpdateCompareFlag(gPhoneInfo.HasMessageBeenDisplayed(ScriptParams[0]));\n\t\treturn 0;\n\t}\n\t*/\n\tcase COMMAND_TURN_PHONE_OFF:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tgPhoneInfo.SetPhoneMessage_JustOnce(ScriptParams[0], nil, nil, nil, nil, nil, nil);\n\t\treturn 0;\n\t}\n\tcase COMMAND_DRAW_CORONA:\n\t{\n\t\tCollectParameters(&m_nIp, 9);\n\t\tCVector pos = *(CVector*)&ScriptParams[0];\n\t\tif (pos.z <= MAP_Z_LOW_LIMIT)\n\t\t\tpos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);\n\t\tCCoronas::RegisterCorona((uintptr)this + m_nIp, ScriptParams[6], ScriptParams[7], ScriptParams[8],\n\t\t\t255, pos, *(float*)&ScriptParams[3], 450.0f, ScriptParams[4], ScriptParams[5], 1, 0, 0, 0.0f);\n\t\treturn 0;\n\t}\n\tcase COMMAND_DRAW_LIGHT:\n\t{\n\t\tCollectParameters(&m_nIp, 6);\n\t\tCVector pos = *(CVector*)&ScriptParams[0];\n\t\tCVector unused(0.0f, 0.0f, 0.0f);\n\t\tCPointLights::AddLight(0, *(CVector*)&ScriptParams[0], CVector(0.0f, 0.0f, 0.0f), 12.0f,\n\t\t\tScriptParams[3] / 255.0f, ScriptParams[4] / 255.0f, ScriptParams[5] / 255.0f, 0, true);\n\t\treturn 0;\n\t}\n\t//case COMMAND_STORE_WEATHER:\n\t//case COMMAND_RESTORE_WEATHER:\n\tcase COMMAND_STORE_CLOCK:\n\t\tCClock::StoreClock();\n\t\treturn 0;\n\tcase COMMAND_RESTORE_CLOCK:\n\t\tCClock::RestoreClock();\n\t\treturn 0;\n\t/*\n\tcase COMMAND_RESTART_CRITICAL_MISSION:\n\t{\n\t\tCollectParameters(&m_nIp, 4);\n\t\tCVector pos = *(CVector*)&ScriptParams[0];\n\t\tif (pos.z <= MAP_Z_LOW_LIMIT)\n\t\t\tpos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);\n\t\tCRestart::OverrideNextRestart(pos, *(float*)&ScriptParams[3]);\n\t\tif (CWorld::Players[CWorld::PlayerInFocus].m_WBState != WBSTATE_PLAYING)\n\t\t\tprintf(\"RESTART_CRITICAL_MISSION - Player state is not PLAYING\\n\");\n\t\tCWorld::Players[CWorld::PlayerInFocus].PlayerFailedCriticalMission();\n\t\treturn 0;\n\t}\n\t*/\n\tcase COMMAND_IS_PLAYER_PLAYING:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tUpdateCompareFlag(CWorld::Players[ScriptParams[0]].m_WBState == WBSTATE_PLAYING);\n\t\treturn 0;\n\t}\n#ifdef GTA_SCRIPT_COLLECTIVE\n\tcase COMMAND_SET_COLL_OBJ_NO_OBJ:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCTheScripts::SetObjectiveForAllPedsInCollective(ScriptParams[0], OBJECTIVE_NONE);\n\t\treturn 0;\n#endif\n\tdefault:\n\t\tscript_assert(0);\n\t}\n\treturn -1;\n}\n\nint8 CRunningScript::ProcessCommands600To699(int32 command)\n{\n\tswitch (command){\n#ifdef GTA_SCRIPT_COLLECTIVE\n\tcase COMMAND_SET_COLL_OBJ_WAIT_ON_FOOT:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCTheScripts::SetObjectiveForAllPedsInCollective(ScriptParams[0], OBJECTIVE_WAIT_ON_FOOT);\n\t\treturn 0;\n\tcase COMMAND_SET_COLL_OBJ_FLEE_ON_FOOT_TILL_SAFE:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCTheScripts::SetObjectiveForAllPedsInCollective(ScriptParams[0], OBJECTIVE_FLEE_ON_FOOT_TILL_SAFE);\n\t\treturn 0;\n\tcase COMMAND_SET_COLL_OBJ_GUARD_SPOT:\n\t{\n\t\tCollectParameters(&m_nIp, 4);\n\t\tCVector pos = *(CVector*)&ScriptParams[1];\n\t\tif (pos.z <= MAP_Z_LOW_LIMIT)\n\t\t\tpos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);\n\t\tCTheScripts::SetObjectiveForAllPedsInCollective(ScriptParams[0], OBJECTIVE_GUARD_AREA, pos);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_COLL_OBJ_GUARD_AREA:\n\t{\n\t\tCollectParameters(&m_nIp, 5);\n\t\tfloat infX = *(float*)&ScriptParams[1];\n\t\tfloat supX = *(float*)&ScriptParams[3];\n\t\tif (infX > supX) {\n\t\t\tinfX = *(float*)&ScriptParams[3];\n\t\t\tsupX = *(float*)&ScriptParams[1];\n\t\t}\n\t\tfloat infY = *(float*)&ScriptParams[2];\n\t\tfloat supY = *(float*)&ScriptParams[4];\n\t\tif (infY > supY) {\n\t\t\tinfY = *(float*)&ScriptParams[4];\n\t\t\tsupY = *(float*)&ScriptParams[2];\n\t\t}\n\t\tCVector pos;\n\t\tpos.x = (infX + supX) / 2;\n\t\tpos.y = (infY + supY) / 2;\n\t\tpos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);\n\t\tfloat radius = Max(pos.x - infX, pos.y - infY);\n\t\tCTheScripts::SetObjectiveForAllPedsInCollective(ScriptParams[0], OBJECTIVE_GUARD_AREA, pos, radius);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_COLL_OBJ_WAIT_IN_CAR:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCTheScripts::SetObjectiveForAllPedsInCollective(ScriptParams[0], OBJECTIVE_WAIT_IN_CAR);\n\t\treturn 0;\n\tcase COMMAND_SET_COLL_OBJ_KILL_CHAR_ON_FOOT:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[1]);\n\t\tCTheScripts::SetObjectiveForAllPedsInCollective(ScriptParams[0], OBJECTIVE_KILL_CHAR_ON_FOOT, pPed);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_COLL_OBJ_KILL_PLAYER_ON_FOOT:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CWorld::Players[ScriptParams[1]].m_pPed;\n\t\tCTheScripts::SetObjectiveForAllPedsInCollective(ScriptParams[0], OBJECTIVE_KILL_CHAR_ON_FOOT, pPed);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_COLL_OBJ_KILL_CHAR_ANY_MEANS:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[1]);\n\t\tCTheScripts::SetObjectiveForAllPedsInCollective(ScriptParams[0], OBJECTIVE_KILL_CHAR_ANY_MEANS, pPed);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_COLL_OBJ_KILL_PLAYER_ANY_MEANS:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CWorld::Players[ScriptParams[1]].m_pPed;\n\t\tCTheScripts::SetObjectiveForAllPedsInCollective(ScriptParams[0], OBJECTIVE_KILL_CHAR_ANY_MEANS, pPed);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_COLL_OBJ_FLEE_CHAR_ON_FOOT_TILL_SAFE:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[1]);\n\t\tCTheScripts::SetObjectiveForAllPedsInCollective(ScriptParams[0], OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE, pPed);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_COLL_OBJ_FLEE_PLAYER_ON_FOOT_TILL_SAFE:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CWorld::Players[ScriptParams[1]].m_pPed;\n\t\tCTheScripts::SetObjectiveForAllPedsInCollective(ScriptParams[0], OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE, pPed);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_COLL_OBJ_FLEE_CHAR_ON_FOOT_ALWAYS:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[1]);\n\t\tCTheScripts::SetObjectiveForAllPedsInCollective(ScriptParams[0], OBJECTIVE_FLEE_CHAR_ON_FOOT_ALWAYS, pPed);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_COLL_OBJ_FLEE_PLAYER_ON_FOOT_ALWAYS:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CWorld::Players[ScriptParams[1]].m_pPed;\n\t\tCTheScripts::SetObjectiveForAllPedsInCollective(ScriptParams[0], OBJECTIVE_FLEE_CHAR_ON_FOOT_ALWAYS, pPed);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_COLL_OBJ_GOTO_CHAR_ON_FOOT:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[1]);\n\t\tCTheScripts::SetObjectiveForAllPedsInCollective(ScriptParams[0], OBJECTIVE_GOTO_CHAR_ON_FOOT, pPed);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_COLL_OBJ_GOTO_PLAYER_ON_FOOT:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CWorld::Players[ScriptParams[1]].m_pPed;\n\t\tCTheScripts::SetObjectiveForAllPedsInCollective(ScriptParams[0], OBJECTIVE_GOTO_CHAR_ON_FOOT, pPed);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_COLL_OBJ_LEAVE_CAR:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCTheScripts::SetObjectiveForAllPedsInCollective(ScriptParams[0], OBJECTIVE_LEAVE_CAR);\n\t\treturn 0;\n\tcase COMMAND_SET_COLL_OBJ_ENTER_CAR_AS_PASSENGER:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]);\n\t\tCTheScripts::SetObjectiveForAllPedsInCollective(ScriptParams[0], OBJECTIVE_ENTER_CAR_AS_PASSENGER, pVehicle);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_COLL_OBJ_ENTER_CAR_AS_DRIVER:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]);\n\t\tCTheScripts::SetObjectiveForAllPedsInCollective(ScriptParams[0], OBJECTIVE_ENTER_CAR_AS_DRIVER, pVehicle);\n\t\treturn 0;\n\t}\n\t/*\n\tcase COMMAND_SET_COLL_OBJ_FOLLOW_CAR_IN_CAR:\n\tcase COMMAND_SET_COLL_OBJ_FIRE_AT_OBJECT_FROM_VEHICLE:\n\tcase COMMAND_SET_COLL_OBJ_DESTROY_OBJECT:\n\t*/\n\tcase COMMAND_SET_COLL_OBJ_DESTROY_CAR:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]);\n\t\tCTheScripts::SetObjectiveForAllPedsInCollective(ScriptParams[0], OBJECTIVE_DESTROY_CAR, pVehicle);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_COLL_OBJ_GOTO_AREA_ON_FOOT:\n\t{\n\t\tCollectParameters(&m_nIp, 5);\n\t\tfloat infX = *(float*)&ScriptParams[1];\n\t\tfloat supX = *(float*)&ScriptParams[3];\n\t\tif (infX > supX) {\n\t\t\tinfX = *(float*)&ScriptParams[3];\n\t\t\tsupX = *(float*)&ScriptParams[1];\n\t\t}\n\t\tfloat infY = *(float*)&ScriptParams[2];\n\t\tfloat supY = *(float*)&ScriptParams[4];\n\t\tif (infY > supY) {\n\t\t\tinfY = *(float*)&ScriptParams[4];\n\t\t\tsupY = *(float*)&ScriptParams[2];\n\t\t}\n\t\tCVector pos;\n\t\tpos.x = (infX + supX) / 2;\n\t\tpos.y = (infY + supY) / 2;\n\t\tpos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);\n\t\tfloat radius = Max(pos.x - infX, pos.y - infY);\n\t\tCTheScripts::SetObjectiveForAllPedsInCollective(ScriptParams[0], OBJECTIVE_GOTO_AREA_ON_FOOT, pos, radius);\n\t\treturn 0;\n\t}\n\t/*\n\tcase COMMAND_SET_COLL_OBJ_GOTO_AREA_IN_CAR:\n\tcase COMMAND_SET_COLL_OBJ_FOLLOW_CAR_ON_FOOT_WITH_OFFSET:\n\tcase COMMAND_SET_COLL_OBJ_GUARD_ATTACK:\n\t*/\n\tcase COMMAND_SET_COLL_OBJ_FOLLOW_ROUTE:\n\t\tCollectParameters(&m_nIp, 3);\n\t\tCTheScripts::SetObjectiveForAllPedsInCollective(ScriptParams[0], OBJECTIVE_FOLLOW_ROUTE, ScriptParams[1], ScriptParams[2]);\n\t\treturn 0;\n\tcase COMMAND_SET_COLL_OBJ_GOTO_COORD_ON_FOOT:\n\t{\n\t\tCollectParameters(&m_nIp, 3);\n\t\tCVector pos(*(float*)&ScriptParams[1], *(float*)&ScriptParams[2], CWorld::FindGroundZForCoord(*(float*)&ScriptParams[1], *(float*)&ScriptParams[2]));\n\t\tCTheScripts::SetObjectiveForAllPedsInCollective(ScriptParams[0], OBJECTIVE_GOTO_AREA_ON_FOOT, pos);\n\t\treturn 0;\n\t}\n\t//case COMMAND_SET_COLL_OBJ_GOTO_COORD_IN_CAR:\n\tcase COMMAND_SET_COLL_OBJ_RUN_TO_AREA:\n\t{\n\t\tCollectParameters(&m_nIp, 5);\n\t\tfloat infX = *(float*)&ScriptParams[1];\n\t\tfloat supX = *(float*)&ScriptParams[3];\n\t\tif (infX > supX) {\n\t\t\tinfX = *(float*)&ScriptParams[3];\n\t\t\tsupX = *(float*)&ScriptParams[1];\n\t\t}\n\t\tfloat infY = *(float*)&ScriptParams[2];\n\t\tfloat supY = *(float*)&ScriptParams[4];\n\t\tif (infY > supY) {\n\t\t\tinfY = *(float*)&ScriptParams[4];\n\t\t\tsupY = *(float*)&ScriptParams[2];\n\t\t}\n\t\tCVector pos;\n\t\tpos.x = (infX + supX) / 2;\n\t\tpos.y = (infY + supY) / 2;\n\t\tpos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);\n\t\tfloat radius = Max(pos.x - infX, pos.y - infY);\n\t\tCTheScripts::SetObjectiveForAllPedsInCollective(ScriptParams[0], OBJECTIVE_RUN_TO_AREA, pos, radius);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_COLL_OBJ_RUN_TO_COORD:\n\t{\n\t\tCollectParameters(&m_nIp, 3);\n\t\tCVector pos(*(float*)&ScriptParams[1], *(float*)&ScriptParams[2], CWorld::FindGroundZForCoord(*(float*)&ScriptParams[1], *(float*)&ScriptParams[2]));\n\t\tCTheScripts::SetObjectiveForAllPedsInCollective(ScriptParams[0], OBJECTIVE_RUN_TO_AREA, pos);\n\t\treturn 0;\n\t}\n\tcase COMMAND_ADD_PEDS_IN_AREA_TO_COLL:\n\t{\n\t\tCollectParameters(&m_nIp, 3);\n\t\tfloat X = *(float*)&ScriptParams[0];\n\t\tfloat Y = *(float*)&ScriptParams[1];\n\t\tfloat Z = CWorld::FindGroundZForCoord(X, Y);\n\t\tfloat radius = *(float*)&ScriptParams[2];\n\t\tScriptParams[0] = CTheScripts::AddPedsInAreaToCollective(X, Y, Z, radius);\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\tcase COMMAND_ADD_PEDS_IN_VEHICLE_TO_COLL:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tScriptParams[0] = CTheScripts::AddPedsInVehicleToCollective(ScriptParams[0]);\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\tcase COMMAND_CLEAR_COLL:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tfor (int i = 0; i < MAX_NUM_COLLECTIVES; i++) {\n\t\t\tif (CTheScripts::CollectiveArray[i].colIndex == ScriptParams[0]) {\n\t\t\t\tCTheScripts::CollectiveArray[i].colIndex = -1;\n\t\t\t\tCTheScripts::CollectiveArray[i].pedIndex = 0;\n\t\t\t}\n\t\t}\n\t\treturn 0;\n\tcase COMMAND_IS_COLL_IN_CARS:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tbool result = true;\n\t\tfor (int i = 0; i < MAX_NUM_COLLECTIVES; i++) {\n\t\t\tCPed* pPed = CPools::GetPedPool()->GetAt(CTheScripts::CollectiveArray[i].pedIndex);\n\t\t\tif (!pPed) {\n\t\t\t\tCTheScripts::CollectiveArray[i].colIndex = -1;\n\t\t\t\tCTheScripts::CollectiveArray[i].pedIndex = 0;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tresult = false;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tUpdateCompareFlag(result);\n\t\treturn 0;\n\t}\n\tcase COMMAND_LOCATE_COLL_ANY_MEANS_2D:\n\tcase COMMAND_LOCATE_COLL_ON_FOOT_2D:\n\tcase COMMAND_LOCATE_COLL_IN_CAR_2D:\n\tcase COMMAND_LOCATE_STOPPED_COLL_ANY_MEANS_2D:\n\tcase COMMAND_LOCATE_STOPPED_COLL_ON_FOOT_2D:\n\tcase COMMAND_LOCATE_STOPPED_COLL_IN_CAR_2D:\n\t\tLocateCollectiveCommand(command, &m_nIp);\n\t\treturn 0;\n\tcase COMMAND_LOCATE_COLL_ANY_MEANS_CHAR_2D:\n\tcase COMMAND_LOCATE_COLL_ON_FOOT_CHAR_2D:\n\tcase COMMAND_LOCATE_COLL_IN_CAR_CHAR_2D:\n\t\tLocateCollectiveCharCommand(command, &m_nIp);\n\t\treturn 0;\n\tcase COMMAND_LOCATE_COLL_ANY_MEANS_CAR_2D:\n\tcase COMMAND_LOCATE_COLL_ON_FOOT_CAR_2D:\n\tcase COMMAND_LOCATE_COLL_IN_CAR_CAR_2D:\n\t\tLocateCollectiveCarCommand(command, &m_nIp);\n\t\treturn 0;\n\tcase COMMAND_LOCATE_COLL_ANY_MEANS_PLAYER_2D:\n\tcase COMMAND_LOCATE_COLL_ON_FOOT_PLAYER_2D:\n\tcase COMMAND_LOCATE_COLL_IN_CAR_PLAYER_2D:\n\t\tLocateCollectivePlayerCommand(command, &m_nIp);\n\t\treturn 0;\n\tcase COMMAND_IS_COLL_IN_AREA_2D:\n\tcase COMMAND_IS_COLL_IN_AREA_ON_FOOT_2D:\n\tcase COMMAND_IS_COLL_IN_AREA_IN_CAR_2D:\n\tcase COMMAND_IS_COLL_STOPPED_IN_AREA_2D:\n\tcase COMMAND_IS_COLL_STOPPED_IN_AREA_ON_FOOT_2D:\n\tcase COMMAND_IS_COLL_STOPPED_IN_AREA_IN_CAR_2D:\n\t\tCollectiveInAreaCheckCommand(command, &m_nIp);\n\t\treturn 0;\n\tcase COMMAND_GET_NUMBER_OF_PEDS_IN_COLL:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tint total = 0;\n\t\tfor (int i = 0; i < MAX_NUM_COLLECTIVES; i++) {\n\t\t\tCPed* pPed = CPools::GetPedPool()->GetAt(CTheScripts::CollectiveArray[i].pedIndex);\n\t\t\tif (!pPed) {\n\t\t\t\tCTheScripts::CollectiveArray[i].colIndex = -1;\n\t\t\t\tCTheScripts::CollectiveArray[i].pedIndex = 0;\n\t\t\t}\n\t\t\telse {\n\t\t\t\ttotal++;\n\t\t\t}\n\t\t}\n\t\tScriptParams[0] = total;\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n#endif\n\tcase COMMAND_SET_CHAR_HEED_THREATS:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tpPed->bRespondsToThreats = (ScriptParams[1] != 0);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_PLAYER_HEED_THREATS:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;\n\t\tscript_assert(pPed);\n\t\tpPed->bRespondsToThreats = (ScriptParams[1] != 0);\n\t\treturn 0;\n\t}\n\tcase COMMAND_GET_CONTROLLER_MODE:\n#if defined(GTA_PC) && !defined(DETECT_PAD_INPUT_SWITCH)\n\t\tScriptParams[0] = 0;\n#else\n\t\tScriptParams[0] = CPad::IsAffectedByController ? CPad::GetPad(0)->Mode : 0;\n#endif\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\tcase COMMAND_SET_CAN_RESPRAY_CAR:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\t//assert(pVehicle->m_vehType == VEHICLE_TYPE_CAR);\n\t\t// they DO call this for bikes, we don't really want to destroy the structure...\n#ifdef FIX_BUGS\n\t\tif (pVehicle->m_vehType == VEHICLE_TYPE_CAR)\n#endif\n\t\t\t((CAutomobile*)pVehicle)->bFixedColour = (ScriptParams[1] == 0);\n\t\t\n\t\treturn 0;\n\t}\n\t/*\n\tcase COMMAND_IS_TAXI:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tUpdateCompareFlag(pVehicle->IsTaxi());\n\t\treturn 0;\n\t}\n\t*/\n\tcase COMMAND_UNLOAD_SPECIAL_CHARACTER:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCStreaming::SetMissionDoesntRequireSpecialChar(ScriptParams[0] - 1);\n\t\treturn 0;\n\tcase COMMAND_RESET_NUM_OF_MODELS_KILLED_BY_PLAYER:\n\t\tCDarkel::ResetModelsKilledByPlayer();\n\t\treturn 0;\n\tcase COMMAND_GET_NUM_OF_MODELS_KILLED_BY_PLAYER:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tScriptParams[0] = CDarkel::QueryModelsKilledByPlayer(ScriptParams[0]);\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t/*\n\tcase COMMAND_ACTIVATE_GARAGE:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCGarages::ActivateGarage(ScriptParams[0]);\n\t\treturn 0;\n\tcase COMMAND_SWITCH_TAXI_TIMER:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tif (ScriptParams[0] != 0){\n\t\t\tCWorld::Players[CWorld::PlayerInFocus].m_nUnusedTaxiTimer = CTimer::GetTimeInMilliseconds();\n\t\t\tCWorld::Players[CWorld::PlayerInFocus].m_bUnusedTaxiThing = true;\n\t\t}else{\n\t\t\tCWorld::Players[CWorld::PlayerInFocus].m_bUnusedTaxiThing = false;\n\t\t}\n\t\treturn 0;\n\t}\n\t*/\n\tcase COMMAND_CREATE_OBJECT_NO_OFFSET:\n\t{\n\t\tCollectParameters(&m_nIp, 4);\n\t\tint mi = ScriptParams[0] >= 0 ? ScriptParams[0] : CTheScripts::UsedObjectArray[-ScriptParams[0]].index;\n\t\tCObject* pObj = new CObject(mi, false);\n;\t\tpObj->ObjectCreatedBy = MISSION_OBJECT;\n\t\tCVector pos = *(CVector*)&ScriptParams[1];\n\t\tif (pos.z <= MAP_Z_LOW_LIMIT)\n\t\t\tpos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);\n\t\tpObj->SetPosition(pos);\n\t\tpObj->SetOrientation(0.0f, 0.0f, 0.0f);\n\t\tpObj->GetMatrix().UpdateRW();\n\t\tpObj->UpdateRwFrame();\n\t\tCBaseModelInfo* pModelInfo = CModelInfo::GetModelInfo(mi);\n\t\tif (pModelInfo->IsBuilding() && ((CSimpleModelInfo*)pModelInfo)->m_isBigBuilding)\n\t\t\tpObj->SetupBigBuilding();\n\t\tCTheScripts::ClearSpaceForMissionEntity(pos, pObj);\n\t\tCWorld::Add(pObj);\n\t\tScriptParams[0] = CPools::GetObjectPool()->GetIndex(pObj);\n\t\tStoreParameters(&m_nIp, 1);\n\t\tif (m_bIsMissionScript)\n\t\t\tCTheScripts::MissionCleanUp.AddEntityToList(ScriptParams[0], CLEANUP_OBJECT);\n\t\treturn 0;\n\t}\n\t/*\n\tcase COMMAND_IS_BOAT:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tUpdateCompareFlag(pVehicle->m_vehType == VEHICLE_TYPE_BOAT);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_CHAR_OBJ_GOTO_AREA_ANY_MEANS:\n\t{\n\t\tCollectParameters(&m_nIp, 5);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tfloat infX = *(float*)&ScriptParams[1];\n\t\tfloat infY = *(float*)&ScriptParams[2];\n\t\tfloat supX = *(float*)&ScriptParams[3];\n\t\tfloat supY = *(float*)&ScriptParams[4];\n\t\tif (infX > supX) {\n\t\t\tinfX = *(float*)&ScriptParams[3];\n\t\t\tsupX = *(float*)&ScriptParams[1];\n\t\t}\n\t\tif (infY > supY) {\n\t\t\tinfY = *(float*)&ScriptParams[4];\n\t\t\tsupY = *(float*)&ScriptParams[2];\n\t\t}\n\t\tCVector pos;\n\t\tpos.x = (infX + supX) / 2;\n\t\tpos.y = (infY + supY) / 2;\n\t\tpos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);\n\t\tfloat radius = Max(pos.x - infX, pos.y - infY);\n\t\tpPed->bScriptObjectiveCompleted = false;\n\t\tpPed->SetObjective(OBJECTIVE_GOTO_AREA_ANY_MEANS, pos, radius);\n\t\treturn 0;\n\t}\n\t*/\n#ifdef GTA_SCRIPT_COLLECTIVE\n\tcase COMMAND_SET_COLL_OBJ_GOTO_AREA_ANY_MEANS:\n\t{\n\t\tCollectParameters(&m_nIp, 5);\n\t\tfloat infX = *(float*)&ScriptParams[1];\n\t\tfloat supX = *(float*)&ScriptParams[3];\n\t\tif (infX > supX) {\n\t\t\tinfX = *(float*)&ScriptParams[3];\n\t\t\tsupX = *(float*)&ScriptParams[1];\n\t\t}\n\t\tfloat infY = *(float*)&ScriptParams[2];\n\t\tfloat supY = *(float*)&ScriptParams[4];\n\t\tif (infY > supY) {\n\t\t\tinfY = *(float*)&ScriptParams[4];\n\t\t\tsupY = *(float*)&ScriptParams[2];\n\t\t}\n\t\tCVector pos;\n\t\tpos.x = (infX + supX) / 2;\n\t\tpos.y = (infY + supY) / 2;\n\t\tpos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);\n\t\tfloat radius = Max(pos.x - infX, pos.y - infY);\n\t\tCTheScripts::SetObjectiveForAllPedsInCollective(ScriptParams[0], OBJECTIVE_GOTO_AREA_ANY_MEANS, pos, radius);\n\t\treturn 0;\n\t}\n#endif\n\tcase COMMAND_IS_PLAYER_STOPPED:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPlayerInfo* pPlayer = &CWorld::Players[ScriptParams[0]];\n\t\tUpdateCompareFlag(CTheScripts::IsPlayerStopped(pPlayer));\n\t\treturn 0;\n\t\n\t}\n\t/*\n\tcase COMMAND_IS_CHAR_STOPPED:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tUpdateCompareFlag(CTheScripts::IsPedStopped(pPed));\n\t\treturn 0;\n\t}\n\tcase COMMAND_MESSAGE_WAIT:\n\t\tCollectParameters(&m_nIp, 2);\n\t\tm_nWakeTime = CTimer::GetTimeInMilliseconds() + ScriptParams[0];\n\t\tif (ScriptParams[1] != 0)\n\t\t\tm_bSkipWakeTime = true;\n\t\treturn 1;\n\tcase COMMAND_ADD_PARTICLE_EFFECT:\n\t{\n\t\tCollectParameters(&m_nIp, 5);\n\t\tCVector pos = *(CVector*)&ScriptParams[1];\n\t\tif (pos.z <= MAP_Z_LOW_LIMIT)\n\t\t\tpos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);\n\t\tCParticleObject::AddObject(ScriptParams[0], pos, ScriptParams[4] != 0);\n\t\treturn 0;\n\t}\n\t*/\n\tcase COMMAND_SWITCH_WIDESCREEN:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tif (ScriptParams[0] != 0)\n\t\t\tTheCamera.SetWideScreenOn();\n\t\telse\n\t\t\tTheCamera.SetWideScreenOff();\n\t\treturn 0;\n\t/*\n\tcase COMMAND_ADD_SPRITE_BLIP_FOR_CAR:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tCRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));\n\t\tint id = CRadar::SetEntityBlip(BLIP_CAR, ScriptParams[0], 0, BLIP_DISPLAY_BOTH);\n\t\tCRadar::SetBlipSprite(id, ScriptParams[1]);\n\t\tScriptParams[0] = id;\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\tcase COMMAND_ADD_SPRITE_BLIP_FOR_CHAR:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tCRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));\n\t\tint id = CRadar::SetEntityBlip(BLIP_CHAR, ScriptParams[0], 1, BLIP_DISPLAY_BOTH);\n\t\tCRadar::SetBlipSprite(id, ScriptParams[1]);\n\t\tScriptParams[0] = id;\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\tcase COMMAND_ADD_SPRITE_BLIP_FOR_OBJECT:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pObject);\n\t\tCRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));\n\t\tint id = CRadar::SetEntityBlip(BLIP_OBJECT, ScriptParams[0], 6, BLIP_DISPLAY_BOTH);\n\t\tCRadar::SetBlipSprite(id, ScriptParams[1]);\n\t\tScriptParams[0] = id;\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\t*/\n\tcase COMMAND_ADD_SPRITE_BLIP_FOR_CONTACT_POINT:\n\t{\n\t\tCollectParameters(&m_nIp, 4);\n\t\tCVector pos = *(CVector*)&ScriptParams[0];\n\t\tif (pos.z <= MAP_Z_LOW_LIMIT)\n\t\t\tpos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);\n\t\tCRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));\n\t\tint id = CRadar::SetCoordBlip(BLIP_CONTACT_POINT, pos, 2, BLIP_DISPLAY_BOTH);\n\t\tCRadar::SetBlipSprite(id, ScriptParams[3]);\n\t\tScriptParams[0] = id;\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\tcase COMMAND_ADD_SPRITE_BLIP_FOR_COORD:\n\t{\n\t\tCollectParameters(&m_nIp, 4);\n\t\tCVector pos = *(CVector*)&ScriptParams[0];\n\t\tif (pos.z <= MAP_Z_LOW_LIMIT)\n\t\t\tpos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);\n\t\tCRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));\n\t\tint id = CRadar::SetCoordBlip(BLIP_COORD, pos, 5, BLIP_DISPLAY_BOTH);\n\t\tCRadar::SetBlipSprite(id, ScriptParams[3]);\n\t\tScriptParams[0] = id;\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_CHAR_ONLY_DAMAGED_BY_PLAYER:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tpPed->bOnlyDamagedByPlayer = (ScriptParams[1] != 0);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_CAR_ONLY_DAMAGED_BY_PLAYER:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tpVehicle->bOnlyDamagedByPlayer = (ScriptParams[1] != 0);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_CHAR_PROOFS:\n\t{\n\t\tCollectParameters(&m_nIp, 6);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tpPed->bBulletProof = (ScriptParams[1] != 0);\n\t\tpPed->bFireProof = (ScriptParams[2] != 0);\n\t\tpPed->bExplosionProof = (ScriptParams[3] != 0);\n\t\tpPed->bCollisionProof = (ScriptParams[4] != 0);\n\t\tpPed->bMeleeProof = (ScriptParams[5] != 0);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_CAR_PROOFS:\n\t{\n\t\tCollectParameters(&m_nIp, 6);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tpVehicle->bBulletProof = (ScriptParams[1] != 0);\n\t\tpVehicle->bFireProof = (ScriptParams[2] != 0);\n\t\tpVehicle->bExplosionProof = (ScriptParams[3] != 0);\n\t\tpVehicle->bCollisionProof = (ScriptParams[4] != 0);\n\t\tpVehicle->bMeleeProof = (ScriptParams[5] != 0);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_PLAYER_IN_ANGLED_AREA_2D:\n\tcase COMMAND_IS_PLAYER_IN_ANGLED_AREA_ON_FOOT_2D:\n\tcase COMMAND_IS_PLAYER_IN_ANGLED_AREA_IN_CAR_2D:\n\tcase COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_2D:\n\tcase COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_ON_FOOT_2D:\n\tcase COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_IN_CAR_2D:\n\tcase COMMAND_IS_PLAYER_IN_ANGLED_AREA_3D:\n\tcase COMMAND_IS_PLAYER_IN_ANGLED_AREA_ON_FOOT_3D:\n\tcase COMMAND_IS_PLAYER_IN_ANGLED_AREA_IN_CAR_3D:\n\tcase COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_3D:\n\tcase COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_ON_FOOT_3D:\n\tcase COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_IN_CAR_3D:\n\t\tPlayerInAngledAreaCheckCommand(command, &m_nIp);\n\t\treturn 0;\n\t/*\n\tcase COMMAND_DEACTIVATE_GARAGE:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCGarages::DeActivateGarage(ScriptParams[0]);\n\t\treturn 0;\n\tcase COMMAND_GET_NUMBER_OF_CARS_COLLECTED_BY_GARAGE:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tScriptParams[0] = CGarages::QueryCarsCollected(ScriptParams[0]);\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\tcase COMMAND_HAS_CAR_BEEN_TAKEN_TO_GARAGE:\n\t\tCollectParameters(&m_nIp, 2);\n\t\tUpdateCompareFlag(CGarages::HasThisCarBeenCollected(ScriptParams[0], ScriptParams[1] - 1));\n\t\treturn 0;\n\t*/\n\tdefault:\n\t\tscript_assert(0);\n\t}\n\treturn -1;\n}\n\nint8 CRunningScript::ProcessCommands700To799(int32 command)\n{\n\tswitch (command){\n\t/*\n\tcase COMMAND_SET_SWAT_REQUIRED:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tFindPlayerPed()->m_pWanted->m_bSwatRequired = (ScriptParams[0] != 0);\n\t\treturn 0;\n\tcase COMMAND_SET_FBI_REQUIRED:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tFindPlayerPed()->m_pWanted->m_bFbiRequired = (ScriptParams[0] != 0);\n\t\treturn 0;\n\tcase COMMAND_SET_ARMY_REQUIRED:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tFindPlayerPed()->m_pWanted->m_bArmyRequired = (ScriptParams[0] != 0);\n\t\treturn 0;\n\t*/\n\tcase COMMAND_IS_CAR_IN_WATER:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tUpdateCompareFlag(pVehicle && pVehicle->bIsInWater);\n\t\treturn 0;\n\t}\n\tcase COMMAND_GET_CLOSEST_CHAR_NODE:\n\t{\n\t\tCollectParameters(&m_nIp, 3);\n\t\tCVector pos = *(CVector*)&ScriptParams[0];\n\t\tif (pos.z <= MAP_Z_LOW_LIMIT)\n\t\t\tpos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);\n\t\tCPathNode* pNode = &ThePaths.m_pathNodes[ThePaths.FindNodeClosestToCoors(pos, 1, 999999.9f, true)];\n\t\t*(CVector*)&ScriptParams[0] = pNode->GetPosition();\n\t\tStoreParameters(&m_nIp, 3);\n\t\treturn 0;\n\t}\n\tcase COMMAND_GET_CLOSEST_CAR_NODE:\n\t{\n\t\tCollectParameters(&m_nIp, 3);\n\t\tCVector pos = *(CVector*)&ScriptParams[0];\n\t\tif (pos.z <= MAP_Z_LOW_LIMIT)\n\t\t\tpos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);\n\t\t*(CVector*)&ScriptParams[0] = ThePaths.FindNodeCoorsForScript(ThePaths.FindNodeClosestToCoors(pos, 0, 999999.9f, true, true));\n\t\tStoreParameters(&m_nIp, 3);\n\t\treturn 0;\n\t}\n\tcase COMMAND_CAR_GOTO_COORDINATES_ACCURATE:\n\t{\n\t\tCollectParameters(&m_nIp, 4);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tCVector pos = *(CVector*)&ScriptParams[1];\n\t\tif (pos.z <= MAP_Z_LOW_LIMIT)\n\t\t\tpos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);\n\t\tpos.z += pVehicle->GetDistanceFromCentreOfMassToBaseOfModel();\n\t\tif (CCarCtrl::JoinCarWithRoadSystemGotoCoors(pVehicle, pos, false))\n\t\t\tpVehicle->AutoPilot.m_nCarMission = MISSION_GOTO_COORDS_STRAIGHT_ACCURATE;\n\t\telse\n\t\t\tpVehicle->AutoPilot.m_nCarMission = MISSION_GOTOCOORDS_ACCURATE;\n\t\tpVehicle->SetStatus(STATUS_PHYSICS);\n\t\tpVehicle->bEngineOn = true;\n\t\tpVehicle->AutoPilot.m_nCruiseSpeed = Max(1, pVehicle->AutoPilot.m_nCruiseSpeed);\n\t\tpVehicle->AutoPilot.m_nAntiReverseTimer = CTimer::GetTimeInMilliseconds();\n\t\treturn 0;\n\t}\n\t/*\n\tcase COMMAND_START_PACMAN_RACE:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPacManPickups::StartPacManRace(ScriptParams[0]);\n\t\treturn 0;\n\tcase COMMAND_START_PACMAN_RECORD:\n\t\tCPacManPickups::StartPacManRecord();\n\t\treturn 0;\n\tcase COMMAND_GET_NUMBER_OF_POWER_PILLS_EATEN:\n\t\tScriptParams[0] = CPacManPickups::QueryPowerPillsEatenInRace();\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\tcase COMMAND_CLEAR_PACMAN:\n\t\tCPacManPickups::CleanUpPacManStuff();\n\t\treturn 0;\n\tcase COMMAND_START_PACMAN_SCRAMBLE:\n\t{\n\t\tCollectParameters(&m_nIp, 5);\n\t\tCVector pos = *(CVector*)&ScriptParams[0];\n\t\tif (pos.z <= MAP_Z_LOW_LIMIT)\n\t\t\tpos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);\n\t\tCPacManPickups::StartPacManScramble(pos, *(float*)&ScriptParams[3], ScriptParams[4]);\n\t\treturn 0;\n\t}\n\tcase COMMAND_GET_NUMBER_OF_POWER_PILLS_CARRIED:\n\t\tScriptParams[0] = CPacManPickups::QueryPowerPillsCarriedByPlayer();\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\tcase COMMAND_CLEAR_NUMBER_OF_POWER_PILLS_CARRIED:\n\t\tCPacManPickups::ResetPowerPillsCarriedByPlayer();\n\t\treturn 0;\n\t*/\n\tcase COMMAND_IS_CAR_ON_SCREEN:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tUpdateCompareFlag(TheCamera.IsSphereVisible(pVehicle->GetBoundCentre(), pVehicle->GetBoundRadius()));\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_CHAR_ON_SCREEN:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tUpdateCompareFlag(TheCamera.IsSphereVisible(pPed->GetBoundCentre(), pPed->GetBoundRadius()));\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_OBJECT_ON_SCREEN:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pObject);\n\t\tUpdateCompareFlag(TheCamera.IsSphereVisible(pObject->GetBoundCentre(), pObject->GetBoundRadius()));\n\t\treturn 0;\n\t}\n\t/*\n\tcase COMMAND_GOSUB_FILE:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tscript_assert(m_nStackPointer < MAX_STACK_DEPTH);\n\t\tm_anStack[m_nStackPointer++] = m_nIp;\n\t\tSetIP(ScriptParams[0]);\n\t\t// ScriptParams[1] == filename\n\t\treturn 0;\n\t}\n\t*/\n\tcase COMMAND_GET_GROUND_Z_FOR_3D_COORD:\n\t{\n\t\tCollectParameters(&m_nIp, 3);\n\t\tCVector pos = *(CVector*)&ScriptParams[0];\n\t\tbool success;\n\t\t*(float*)&ScriptParams[0] = CWorld::FindGroundZFor3DCoord(pos.x, pos.y, pos.z, &success);\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\tcase COMMAND_START_SCRIPT_FIRE:\n\t{\n\t\tCollectParameters(&m_nIp, 3);\n\t\tCVector pos = *(CVector*)&ScriptParams[0];\n\t\tif (pos.z <= MAP_Z_LOW_LIMIT)\n\t\t\tpos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);\n\t\tScriptParams[0] = gFireManager.StartScriptFire(pos, nil, 0.8f, 1);\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_SCRIPT_FIRE_EXTINGUISHED:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tUpdateCompareFlag(gFireManager.IsScriptFireExtinguish(ScriptParams[0]));\n\t\treturn 0;\n\tcase COMMAND_REMOVE_SCRIPT_FIRE:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tgFireManager.RemoveScriptFire(ScriptParams[0]);\n\t\treturn 0;\n\t/*\n\tcase COMMAND_SET_COMEDY_CONTROLS:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tpVehicle->bComedyControls = (ScriptParams[1] != 0);\n\t\treturn 0;\n\t}\n\t*/\n\tcase COMMAND_BOAT_GOTO_COORDS:\n\t{\n\t\tCollectParameters(&m_nIp, 4);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tscript_assert(pVehicle->m_vehType == VEHICLE_TYPE_BOAT);\n\t\tCBoat* pBoat = (CBoat*)pVehicle;\n\t\tCVector pos = *(CVector*)&ScriptParams[1];\n\t\tif (pos.z <= MAP_Z_LOW_LIMIT)\n\t\t\tCWaterLevel::GetWaterLevel(pos.x, pos.y, pos.z, &pos.z, false);\n\t\tpBoat->AutoPilot.m_nCarMission = MISSION_GOTOCOORDS_ASTHECROWSWIMS;\n\t\tpBoat->AutoPilot.m_vecDestinationCoors = pos;\n\t\tpBoat->SetStatus(STATUS_PHYSICS);\n\t\tpBoat->bEngineOn = true;\n\t\tpBoat->AutoPilot.m_nCruiseSpeed = Max(1, pBoat->AutoPilot.m_nCruiseSpeed);\n\t\tpBoat->AutoPilot.m_nAntiReverseTimer = CTimer::GetTimeInMilliseconds();\n\t\treturn 0;\n\t}\n\tcase COMMAND_BOAT_STOP:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tscript_assert(pVehicle->m_vehType == VEHICLE_TYPE_BOAT);\n\t\tCBoat* pBoat = (CBoat*)pVehicle;\n\t\tpBoat->AutoPilot.m_nCarMission = MISSION_NONE;\n\t\tpBoat->SetStatus(STATUS_PHYSICS);\n\t\tpBoat->bEngineOn = false;\n\t\tpBoat->AutoPilot.m_nCruiseSpeed = 0;\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_PLAYER_SHOOTING_IN_AREA:\n\t{\n\t\tCollectParameters(&m_nIp, 6);\n\t\tCPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;\n\t\tscript_assert(pPed);\n\t\tfloat x1 = *(float*)&ScriptParams[1];\n\t\tfloat y1 = *(float*)&ScriptParams[2];\n\t\tfloat x2 = *(float*)&ScriptParams[3];\n\t\tfloat y2 = *(float*)&ScriptParams[4];\n\t\tUpdateCompareFlag(pPed->bIsShooting && pPed->IsWithinArea(x1, y1, x2, y2));\n\t\tif (ScriptParams[5])\n\t\t\tCTheScripts::HighlightImportantArea((uintptr)this + m_nIp, x1, y1, x2, y2, MAP_Z_LOW_LIMIT);\n\t\tif (CTheScripts::DbgFlag)\n\t\t\tCTheScripts::DrawDebugSquare(x1, y1, x2, y2);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_CHAR_SHOOTING_IN_AREA:\n\t{\n\t\tCollectParameters(&m_nIp, 6);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tfloat x1 = *(float*)&ScriptParams[1];\n\t\tfloat y1 = *(float*)&ScriptParams[2];\n\t\tfloat x2 = *(float*)&ScriptParams[3];\n\t\tfloat y2 = *(float*)&ScriptParams[4];\n\t\tUpdateCompareFlag(pPed->bIsShooting && pPed->IsWithinArea(x1, y1, x2, y2));\n\t\tif (ScriptParams[5])\n\t\t\tCTheScripts::HighlightImportantArea((uintptr)this + m_nIp, x1, y1, x2, y2, MAP_Z_LOW_LIMIT);\n\t\tif (CTheScripts::DbgFlag)\n\t\t\tCTheScripts::DrawDebugSquare(x1, y1, x2, y2);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_CURRENT_PLAYER_WEAPON:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;\n\t\tscript_assert(pPed);\n\t\tUpdateCompareFlag(ScriptParams[1] == pPed->GetWeapon()->m_eWeaponType);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_CURRENT_CHAR_WEAPON:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tUpdateCompareFlag(ScriptParams[1] == pPed->GetWeapon()->m_eWeaponType);\n\t\treturn 0;\n\t}\n\t/*\n\tcase COMMAND_CLEAR_NUMBER_OF_POWER_PILLS_EATEN:\n\t\tCPacManPickups::ResetPowerPillsEatenInRace();\n\t\treturn 0;\n\tcase COMMAND_ADD_POWER_PILL:\n\t{\n\t\tCollectParameters(&m_nIp, 3);\n\t\tCVector pos = *(CVector*)&ScriptParams[0];\n\t\tif (pos.z <= MAP_Z_LOW_LIMIT)\n\t\t\tpos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);\n\t\tCPacManPickups::GenerateOnePMPickUp(pos);\n\t\treturn 0;\n\t}\n\t*/\n\tcase COMMAND_SET_BOAT_CRUISE_SPEED:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tscript_assert(pVehicle->m_vehType == VEHICLE_TYPE_BOAT);\n\t\tCBoat* pBoat = (CBoat*)pVehicle;\n\t\tpBoat->AutoPilot.m_nCruiseSpeed = *(float*)&ScriptParams[1];\n\t\treturn 0;\n\t}\n\t/*\n\tcase COMMAND_GET_RANDOM_CHAR_IN_AREA:\n\t{\n\t\tCollectParameters(&m_nIp, 4);\n\t\tint ped_handle = -1;\n\t\tCVector pos = FindPlayerCoors();\n\t\tfloat x1 = *(float*)&ScriptParams[0];\n\t\tfloat y1 = *(float*)&ScriptParams[1];\n\t\tfloat x2 = *(float*)&ScriptParams[2];\n\t\tfloat y2 = *(float*)&ScriptParams[3];\n\t\tint i = CPools::GetPedPool()->GetSize();\n\t\twhile (--i && ped_handle == -1){\n\t\t\tCPed* pPed = CPools::GetPedPool()->GetSlot(i);\n\t\t\tif (!pPed)\n\t\t\t\tcontinue;\n\t\t\tif (CTheScripts::LastRandomPedId == CPools::GetPedPool()->GetIndex(pPed))\n\t\t\t\tcontinue;\n\t\t\tif (pPed->CharCreatedBy != RANDOM_CHAR)\n\t\t\t\tcontinue;\n\t\t\tif (!pPed->IsPedInControl())\n\t\t\t\tcontinue;\n\t\t\tif (pPed->bRemoveFromWorld)\n\t\t\t\tcontinue;\n\t\t\tif (pPed->bFadeOut)\n\t\t\t\tcontinue;\n//\t\t\tif (pPed->GetModelIndex() == MI_SCUM_WOM || pPed->GetModelIndex() == MI_SCUM_MAN)\n//\t\t\t\tcontinue;\n\t\t\tif (!ThisIsAValidRandomPed(pPed->m_nPedType))\n\t\t\t\tcontinue;\n\t\t\tif (pPed->bIsLeader || pPed->m_leader)\n\t\t\t\tcontinue;\n\t\t\tif (!pPed->IsWithinArea(x1, y1, x2, y2))\n\t\t\t\tcontinue;\n\t\t\tif (pos.z - PED_FIND_Z_OFFSET > pPed->GetPosition().z)\n\t\t\t\tcontinue;\n\t\t\tif (pos.z + PED_FIND_Z_OFFSET < pPed->GetPosition().z)\n\t\t\t\tcontinue;\n\t\t\tped_handle = CPools::GetPedPool()->GetIndex(pPed);\n\t\t\tCTheScripts::LastRandomPedId = ped_handle;\n\t\t\tpPed->CharCreatedBy = MISSION_CHAR;\n\t\t\tpPed->bRespondsToThreats = false;\n\t\t\t++CPopulation::ms_nTotalMissionPeds;\n\t\t\tif (m_bIsMissionScript)\n\t\t\t\tCTheScripts::MissionCleanUp.AddEntityToList(ped_handle, CLEANUP_CHAR);\n\t\t}\n\t\tScriptParams[0] = ped_handle;\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\t*/\n\tcase COMMAND_GET_RANDOM_CHAR_IN_ZONE:\n\t{\n\t\tchar zone[KEY_LENGTH_IN_SCRIPT];\n\t\tstrncpy(zone, (const char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT);\n\t\tint nZone = CTheZones::FindZoneByLabelAndReturnIndex(zone, ZONE_DEFAULT);\n\t\tif (nZone != -1)\n\t\t\tm_nIp += KEY_LENGTH_IN_SCRIPT;\n\t\tCZone* pZone = CTheZones::GetNavigationZone(nZone);\n\t\tCollectParameters(&m_nIp, 3);\n\t\tint ped_handle = -1;\n\t\tCVector pos = FindPlayerCoors();\n\t\tint i = CPools::GetPedPool()->GetSize();\n\t\twhile (--i && ped_handle == -1) {\n\t\t\tCPed* pPed = CPools::GetPedPool()->GetSlot(i);\n\t\t\tif (!pPed)\n\t\t\t\tcontinue;\n\t\t\tif (CTheScripts::LastRandomPedId == CPools::GetPedPool()->GetIndex(pPed))\n\t\t\t\tcontinue;\n\t\t\tif (pPed->CharCreatedBy != RANDOM_CHAR)\n\t\t\t\tcontinue;\n\t\t\tif (!pPed->IsPedInControl())\n\t\t\t\tcontinue;\n\t\t\tif (pPed->bRemoveFromWorld)\n\t\t\t\tcontinue;\n\t\t\tif (pPed->bFadeOut)\n\t\t\t\tcontinue;\n\t\t\tif (pPed->m_nWaitState != WAITSTATE_FALSE)\n\t\t\t\tcontinue;\n\t\t\tif (!ThisIsAValidRandomPed(pPed->m_nPedType, ScriptParams[0], ScriptParams[1], ScriptParams[2]))\n\t\t\t\tcontinue;\n\t\t\tif (pPed->bIsLeader || pPed->m_leader)\n\t\t\t\tcontinue;\n\t\t\tif (!CTheZones::PointLiesWithinZone(&pPed->GetPosition(), pZone))\n\t\t\t\tcontinue;\n\t\t\tif (pos.z - PED_FIND_Z_OFFSET > pPed->GetPosition().z)\n\t\t\t\tcontinue;\n\t\t\tif (pos.z + PED_FIND_Z_OFFSET < pPed->GetPosition().z)\n\t\t\t\tcontinue;\n\t\t\tbool found;\n\t\t\tCWorld::FindRoofZFor3DCoord(pos.x, pos.y, pos.z, &found);\n\t\t\tif (found)\n\t\t\t\tcontinue;\n\t\t\tped_handle = CPools::GetPedPool()->GetIndex(pPed);\n\t\t\tCTheScripts::LastRandomPedId = ped_handle;\n\t\t\tpPed->CharCreatedBy = MISSION_CHAR;\n\t\t\tpPed->bRespondsToThreats = false;\n\t\t\t++CPopulation::ms_nTotalMissionPeds;\n\t\t\tif (m_bIsMissionScript)\n\t\t\t\tCTheScripts::MissionCleanUp.AddEntityToList(ped_handle, CLEANUP_CHAR);\n\t\t}\n\t\tScriptParams[0] = ped_handle;\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_PLAYER_IN_TAXI:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;\n\t\tscript_assert(pPed);\n\t\tUpdateCompareFlag(pPed->bInVehicle && pPed->m_pMyVehicle->IsTaxi());\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_PLAYER_SHOOTING:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;\n\t\tscript_assert(pPed);\n\t\tUpdateCompareFlag(pPed->bIsShooting);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_CHAR_SHOOTING:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tUpdateCompareFlag(pPed->bIsShooting);\n\t\treturn 0;\n\t}\n\tcase COMMAND_CREATE_MONEY_PICKUP:\n\t{\n\t\tCollectParameters(&m_nIp, 4);\n\t\tCVector pos = *(CVector*)&ScriptParams[0];\n\t\tif (pos.z <= MAP_Z_LOW_LIMIT)\n\t\t\tpos.z = CWorld::FindGroundZForCoord(pos.x, pos.y) + PICKUP_PLACEMENT_OFFSET;\n\t\tCPickups::GetActualPickupIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));\n\t\tScriptParams[0] = CPickups::GenerateNewOne(pos, MI_MONEY, PICKUP_MONEY, ScriptParams[3]);\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_CHAR_ACCURACY:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tpPed->m_wepAccuracy = ScriptParams[1];\n\t\treturn 0;\n\t}\n\tcase COMMAND_GET_CAR_SPEED:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\t*(float*)&ScriptParams[0] = pVehicle->GetSpeed().Magnitude() * GAME_SPEED_TO_METERS_PER_SECOND;\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\tcase COMMAND_LOAD_CUTSCENE:\n\t{\n\t\tchar name[KEY_LENGTH_IN_SCRIPT];\n\t\tstrncpy(name, (const char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT);\n\t\tm_nIp += KEY_LENGTH_IN_SCRIPT;\n\t\tCCutsceneMgr::LoadCutsceneData(name);\n\t\treturn 0;\n\t}\n\tcase COMMAND_CREATE_CUTSCENE_OBJECT:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCCutsceneObject* pCutObj = CCutsceneMgr::CreateCutsceneObject(ScriptParams[0]);\n\t\tScriptParams[0] = CPools::GetObjectPool()->GetIndex(pCutObj);\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_CUTSCENE_ANIM:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tchar name[KEY_LENGTH_IN_SCRIPT];\n\t\tCObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pObject);\n\t\tstrncpy(name, (const char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT);\n\t\tm_nIp += KEY_LENGTH_IN_SCRIPT;\n\t\tCCutsceneMgr::SetCutsceneAnim(name, pObject);\n\t\treturn 0;\n\t}\n\tcase COMMAND_START_CUTSCENE:\n\t\tCCutsceneMgr::ms_cutsceneLoadStatus = 1;\n\t\treturn 0;\n\tcase COMMAND_GET_CUTSCENE_TIME:\n\t\tScriptParams[0] = CCutsceneMgr::GetCutsceneTimeInMilleseconds();\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\tcase COMMAND_HAS_CUTSCENE_FINISHED:\n\t\tUpdateCompareFlag(CCutsceneMgr::HasCutsceneFinished());\n\t\treturn 0;\n\tcase COMMAND_CLEAR_CUTSCENE:\n\t\tCCutsceneMgr::DeleteCutsceneData();\n\t\treturn 0;\n\tcase COMMAND_RESTORE_CAMERA_JUMPCUT:\n\t\tTheCamera.RestoreWithJumpCut();\n\t\treturn 0;\n\tcase COMMAND_CREATE_COLLECTABLE1:\n\t{\n\t\tCollectParameters(&m_nIp, 3);\n\t\tCVector pos = *(CVector*)&ScriptParams[0];\n\t\tif (pos.z <= MAP_Z_LOW_LIMIT)\n\t\t\tpos.z = CWorld::FindGroundZForCoord(pos.x, pos.y) + PICKUP_PLACEMENT_OFFSET;\n\t\tCPickups::GenerateNewOne(pos, MI_COLLECTABLE1, PICKUP_COLLECTABLE1, 0);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_COLLECTABLE1_TOTAL:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCWorld::Players[CWorld::PlayerInFocus].m_nTotalPackages = ScriptParams[0];\n\t\treturn 0;\n\t/*\n\tcase COMMAND_IS_PROJECTILE_IN_AREA:\n\t{\n\t\tCollectParameters(&m_nIp, 6);\n\t\tfloat infX = *(float*)&ScriptParams[0];\n\t\tfloat infY = *(float*)&ScriptParams[1];\n\t\tfloat infZ = *(float*)&ScriptParams[2];\n\t\tfloat supX = *(float*)&ScriptParams[3];\n\t\tfloat supY = *(float*)&ScriptParams[4];\n\t\tfloat supZ = *(float*)&ScriptParams[5];\n\t\tif (infX > supX) {\n\t\t\tinfX = *(float*)&ScriptParams[3];\n\t\t\tsupX = *(float*)&ScriptParams[0];\n\t\t}\n\t\tif (infY > supY) {\n\t\t\tinfY = *(float*)&ScriptParams[4];\n\t\t\tsupY = *(float*)&ScriptParams[1];\n\t\t}\n\t\tif (infZ > supZ) {\n\t\t\tinfZ = *(float*)&ScriptParams[5];\n\t\t\tsupZ = *(float*)&ScriptParams[2];\n\t\t}\n\t\tUpdateCompareFlag(CProjectileInfo::IsProjectileInRange(infX, supX, infY, supY, infZ, supZ, false));\n\t\tif (CTheScripts::DbgFlag)\n\t\t\tCTheScripts::DrawDebugCube(infX, infY, infZ, supX, supY, supZ);\n\t\treturn 0;\n\t}\n\tcase COMMAND_DESTROY_PROJECTILES_IN_AREA:\n\t{\n\t\tCollectParameters(&m_nIp, 6);\n\t\tfloat infX = *(float*)&ScriptParams[0];\n\t\tfloat infY = *(float*)&ScriptParams[1];\n\t\tfloat infZ = *(float*)&ScriptParams[2];\n\t\tfloat supX = *(float*)&ScriptParams[3];\n\t\tfloat supY = *(float*)&ScriptParams[4];\n\t\tfloat supZ = *(float*)&ScriptParams[5];\n\t\tif (infX > supX) {\n\t\t\tinfX = *(float*)&ScriptParams[3];\n\t\t\tsupX = *(float*)&ScriptParams[0];\n\t\t}\n\t\tif (infY > supY) {\n\t\t\tinfY = *(float*)&ScriptParams[4];\n\t\t\tsupY = *(float*)&ScriptParams[1];\n\t\t}\n\t\tif (infZ > supZ) {\n\t\t\tinfZ = *(float*)&ScriptParams[5];\n\t\t\tsupZ = *(float*)&ScriptParams[2];\n\t\t}\n\t\tUpdateCompareFlag(CProjectileInfo::IsProjectileInRange(infX, supX, infY, supY, infZ, supZ, true));\n\t\tif (CTheScripts::DbgFlag)\n\t\t\tCTheScripts::DrawDebugCube(infX, infY, infZ, supX, supY, supZ);\n\t\treturn 0;\n\t}\n\tcase COMMAND_DROP_MINE:\n\t{\n\t\tCollectParameters(&m_nIp, 3);\n\t\tCVector pos = *(CVector*)&ScriptParams[0];\n\t\tif (pos.z <= MAP_Z_LOW_LIMIT)\n\t\t\tpos.z = CWorld::FindGroundZForCoord(pos.x, pos.y) + PICKUP_PLACEMENT_OFFSET;\n\t\tCPickups::GenerateNewOne(pos, MI_CARMINE, PICKUP_MINE_INACTIVE, 0);\n\t\treturn 0;\n\t}\n\tcase COMMAND_DROP_NAUTICAL_MINE:\n\t{\n\t\tCollectParameters(&m_nIp, 3);\n\t\tCVector pos = *(CVector*)&ScriptParams[0];\n\t\tif (pos.z <= MAP_Z_LOW_LIMIT)\n\t\t\tpos.z = CWorld::FindGroundZForCoord(pos.x, pos.y) + PICKUP_PLACEMENT_OFFSET;\n\t\tCPickups::GenerateNewOne(pos, MI_NAUTICALMINE, PICKUP_MINE_INACTIVE, 0);\n\t\treturn 0;\n\t}\n\t*/\n\tcase COMMAND_IS_CHAR_MODEL:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tUpdateCompareFlag(ScriptParams[1] == pPed->GetModelIndex());\n\t\treturn 0;\n\t}\n\tcase COMMAND_LOAD_SPECIAL_MODEL:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tchar name[KEY_LENGTH_IN_SCRIPT];\n\t\tstrncpy(name, (const char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT);\n\t\tfor (int i = 0; i < KEY_LENGTH_IN_SCRIPT; i++)\n\t\t\tname[i] = tolower(name[i]);\n\t\tCStreaming::RequestSpecialModel(ScriptParams[0], name, STREAMFLAGS_DEPENDENCY | STREAMFLAGS_SCRIPTOWNED);\n\t\tm_nIp += KEY_LENGTH_IN_SCRIPT;\n\t\treturn 0;\n\t}\n\t//case COMMAND_CREATE_CUTSCENE_HEAD:\n\t//case COMMAND_SET_CUTSCENE_HEAD_ANIM:\n\tcase COMMAND_SIN:\n\t\tCollectParameters(&m_nIp, 1);\n\t\t*(float*)&ScriptParams[0] = Sin(DEGTORAD(*(float*)&ScriptParams[0]));\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\tcase COMMAND_COS:\n\t\tCollectParameters(&m_nIp, 1);\n\t\t*(float*)&ScriptParams[0] = Cos(DEGTORAD(*(float*)&ScriptParams[0]));\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\tcase COMMAND_GET_CAR_FORWARD_X:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tfloat forwardX = pVehicle->GetForward().x / pVehicle->GetForward().Magnitude2D();\n\t\t*(float*)&ScriptParams[0] = forwardX;\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\tcase COMMAND_GET_CAR_FORWARD_Y:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tfloat forwardY = pVehicle->GetForward().y / pVehicle->GetForward().Magnitude2D();\n\t\t*(float*)&ScriptParams[0] = forwardY;\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\tcase COMMAND_CHANGE_GARAGE_TYPE:\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCGarages::ChangeGarageType(ScriptParams[0], ScriptParams[1], 0);\n\t\treturn 0;\n\t/*\n\tcase COMMAND_ACTIVATE_CRUSHER_CRANE:\n\t{\n\t\tCollectParameters(&m_nIp, 10);\n\t\tfloat infX = *(float*)&ScriptParams[2];\n\t\tfloat infY = *(float*)&ScriptParams[3];\n\t\tfloat supX = *(float*)&ScriptParams[4];\n\t\tfloat supY = *(float*)&ScriptParams[5];\n\t\tif (infX > supX) {\n\t\t\tinfX = *(float*)&ScriptParams[4];\n\t\t\tsupX = *(float*)&ScriptParams[2];\n\t\t}\n\t\tif (infY > supY) {\n\t\t\tinfY = *(float*)&ScriptParams[5];\n\t\t\tsupY = *(float*)&ScriptParams[3];\n\t\t}\n\t\tCCranes::ActivateCrane(infX, supX, infY, supY,\n\t\t\t*(float*)&ScriptParams[6], *(float*)&ScriptParams[7], *(float*)&ScriptParams[8],\n\t\t\tDEGTORAD(*(float*)&ScriptParams[9]), true, false,\n\t\t\t*(float*)&ScriptParams[0], *(float*)&ScriptParams[1]);\n\t\treturn 0;\n\t}\n\tcase COMMAND_PRINT_WITH_2_NUMBERS:\n\t{\n\t\twchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\tCollectParameters(&m_nIp, 4);\n\t\tCMessages::AddMessageWithNumber(text, ScriptParams[2], ScriptParams[3], ScriptParams[0], ScriptParams[1], -1, -1, -1, -1);\n\t\treturn 0;\n\t}\n\t*/\n\tcase COMMAND_PRINT_WITH_2_NUMBERS_NOW:\n\t{\n\t\twchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\tCollectParameters(&m_nIp, 4);\n\t\tCMessages::AddMessageJumpQWithNumber(text, ScriptParams[2], ScriptParams[3], ScriptParams[0], ScriptParams[1], -1, -1, -1, -1);\n\t\treturn 0;\n\t}\n\t/*\n\tcase COMMAND_PRINT_WITH_2_NUMBERS_SOON:\n\t{\n\t\twchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\tCollectParameters(&m_nIp, 4);\n\t\tCMessages::AddMessageSoonWithNumber(text, ScriptParams[2], ScriptParams[3], ScriptParams[0], ScriptParams[1], -1, -1, -1, -1);\n\t\treturn 0;\n\t}\n\t*/\n\tcase COMMAND_PRINT_WITH_3_NUMBERS:\n\t{\n\t\twchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\tCollectParameters(&m_nIp, 5);\n\t\tCMessages::AddMessageWithNumber(text, ScriptParams[3], ScriptParams[4], ScriptParams[0], ScriptParams[1], ScriptParams[2], -1, -1, -1);\n\t\treturn 0;\n\t}\n\t/*\n\tcase COMMAND_PRINT_WITH_3_NUMBERS_NOW:\n\t{\n\t\twchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\tCollectParameters(&m_nIp, 5);\n\t\tCMessages::AddMessageJumpQWithNumber(text, ScriptParams[3], ScriptParams[4], ScriptParams[0], ScriptParams[1], ScriptParams[2], -1, -1, -1);\n\t\treturn 0;\n\t}\n\tcase COMMAND_PRINT_WITH_3_NUMBERS_SOON:\n\t{\n\t\twchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\tCollectParameters(&m_nIp, 5);\n\t\tCMessages::AddMessageSoonWithNumber(text, ScriptParams[3], ScriptParams[4], ScriptParams[0], ScriptParams[1], ScriptParams[2], -1, -1, -1);\n\t\treturn 0;\n\t}\n\t*/\n\tcase COMMAND_PRINT_WITH_4_NUMBERS:\n\t{\n\t\twchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\tCollectParameters(&m_nIp, 6);\n\t\tCMessages::AddMessageWithNumber(text, ScriptParams[4], ScriptParams[5], ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], -1, -1);\n\t\treturn 0;\n\t}\n\t/*\n\tcase COMMAND_PRINT_WITH_4_NUMBERS_NOW:\n\t{\n\t\twchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\tCollectParameters(&m_nIp, 6);\n\t\tCMessages::AddMessageJumpQWithNumber(text, ScriptParams[4], ScriptParams[5], ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], -1, -1);\n\t\treturn 0;\n\t}\n\tcase COMMAND_PRINT_WITH_4_NUMBERS_SOON:\n\t{\n\t\twchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\tCollectParameters(&m_nIp, 6);\n\t\tCMessages::AddMessageSoonWithNumber(text, ScriptParams[4], ScriptParams[5], ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], -1, -1);\n\t\treturn 0;\n\t}\n\tcase COMMAND_PRINT_WITH_5_NUMBERS:\n\t{\n\t\twchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\tCollectParameters(&m_nIp, 7);\n\t\tCMessages::AddMessageWithNumber(text, ScriptParams[5], ScriptParams[6], ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], ScriptParams[4], -1);\n\t\treturn 0;\n\t}\n\tcase COMMAND_PRINT_WITH_5_NUMBERS_NOW:\n\t{\n\t\twchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\tCollectParameters(&m_nIp, 7);\n\t\tCMessages::AddMessageJumpQWithNumber(text, ScriptParams[5], ScriptParams[6], ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], ScriptParams[4], -1);\n\t\treturn 0;\n\t}\n\tcase COMMAND_PRINT_WITH_5_NUMBERS_SOON:\n\t{\n\t\twchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\tCollectParameters(&m_nIp, 7);\n\t\tCMessages::AddMessageSoonWithNumber(text, ScriptParams[5], ScriptParams[6], ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], ScriptParams[4], -1);\n\t\treturn 0;\n\t}\n\t*/\n\tcase COMMAND_PRINT_WITH_6_NUMBERS:\n\t{\n\t\twchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\tCollectParameters(&m_nIp, 8);\n\t\tCMessages::AddMessageWithNumber(text, ScriptParams[6], ScriptParams[7], ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], ScriptParams[4], ScriptParams[5]);\n\t\treturn 0;\n\t}\n\t/*\n\tcase COMMAND_PRINT_WITH_6_NUMBERS_NOW:\n\t{\n\t\twchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\tCollectParameters(&m_nIp, 8);\n\t\tCMessages::AddMessageJumpQWithNumber(text, ScriptParams[6], ScriptParams[7], ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], ScriptParams[4], ScriptParams[5]);\n\t\treturn 0;\n\t}\n\tcase COMMAND_PRINT_WITH_6_NUMBERS_SOON:\n\t{\n\t\twchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\tCollectParameters(&m_nIp, 8);\n\t\tCMessages::AddMessageSoonWithNumber(text, ScriptParams[6], ScriptParams[7], ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], ScriptParams[4], ScriptParams[5]);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_CHAR_OBJ_FOLLOW_CHAR_IN_FORMATION:\n\t{\n\t\tCollectParameters(&m_nIp, 3);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tCPed* pTargetPed = CPools::GetPedPool()->GetAt(ScriptParams[1]);\n\t\tpPed->bScriptObjectiveCompleted = false;\n\t\tpPed->SetObjective(OBJECTIVE_FOLLOW_CHAR_IN_FORMATION, pTargetPed);\n\t\tpPed->SetFormation((eFormation)ScriptParams[2]);\n\t\treturn 0;\n\t}\n\t*/\n\tcase COMMAND_PLAYER_MADE_PROGRESS:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCStats::ProgressMade += ScriptParams[0];\n\t\treturn 0;\n\tcase COMMAND_SET_PROGRESS_TOTAL:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCStats::TotalProgressInGame = ScriptParams[0];\n\t\tif (CGame::germanGame)\n\t\t\tCStats::TotalProgressInGame -= 2;\n\t\treturn 0;\n\tcase COMMAND_REGISTER_JUMP_DISTANCE:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCStats::MaximumJumpDistance = Max(CStats::MaximumJumpDistance, *(float*)&ScriptParams[0]);\n\t\treturn 0;\n\tcase COMMAND_REGISTER_JUMP_HEIGHT:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCStats::MaximumJumpHeight = Max(CStats::MaximumJumpHeight, *(float*)&ScriptParams[0]);\n\t\treturn 0;\n\tcase COMMAND_REGISTER_JUMP_FLIPS:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCStats::MaximumJumpFlips = Max(CStats::MaximumJumpFlips, ScriptParams[0]);\n\t\treturn 0;\n\tcase COMMAND_REGISTER_JUMP_SPINS:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCStats::MaximumJumpSpins = Max(CStats::MaximumJumpSpins, ScriptParams[0]);\n\t\treturn 0;\n\tcase COMMAND_REGISTER_JUMP_STUNT:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCStats::BestStuntJump = Max(CStats::BestStuntJump, ScriptParams[0]);\n\t\treturn 0;\n\tcase COMMAND_REGISTER_UNIQUE_JUMP_FOUND:\n\t\t++CStats::NumberOfUniqueJumpsFound;\n\t\treturn 0;\n\tcase COMMAND_SET_UNIQUE_JUMPS_TOTAL:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCStats::TotalNumberOfUniqueJumps = ScriptParams[0];\n\t\treturn 0;\n\tcase COMMAND_REGISTER_PASSENGER_DROPPED_OFF_TAXI:\n\t\t++CStats::PassengersDroppedOffWithTaxi;\n\t\treturn 0;\n\tcase COMMAND_REGISTER_MONEY_MADE_TAXI:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCStats::MoneyMadeWithTaxi += ScriptParams[0];\n\t\treturn 0;\n\tcase COMMAND_REGISTER_MISSION_GIVEN:\n\t\t++CStats::MissionsGiven;\n\t\treturn 0;\n\tcase COMMAND_REGISTER_MISSION_PASSED:\n\t{\n\t\tchar name[KEY_LENGTH_IN_SCRIPT];\n\t\tstrncpy(name, (const char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT);\n\t\tm_nIp += KEY_LENGTH_IN_SCRIPT;\n\t\tstrncpy(CStats::LastMissionPassedName, name, KEY_LENGTH_IN_SCRIPT);\n\t\t++CStats::MissionsPassed;\n\t\tCStats::CheckPointReachedSuccessfully();\n\t\tCTheScripts::LastMissionPassedTime = CTimer::GetTimeInMilliseconds();\n\t\tCGameLogic::RemoveShortCutDropOffPointForMission();\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_CHAR_RUNNING:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tpPed->bIsRunning = (ScriptParams[1] != 0);\n\t\treturn 0;\n\t}\n\tcase COMMAND_REMOVE_ALL_SCRIPT_FIRES:\n\t\tgFireManager.RemoveAllScriptFires();\n\t\treturn 0;\n\t/*\n\tcase COMMAND_IS_FIRST_CAR_COLOUR:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tUpdateCompareFlag(pVehicle->m_currentColour1 == ScriptParams[1]);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_SECOND_CAR_COLOUR:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tUpdateCompareFlag(pVehicle->m_currentColour2 == ScriptParams[1]);\n\t\treturn 0;\n\t}\n\t*/\n\tcase COMMAND_HAS_CHAR_BEEN_DAMAGED_BY_WEAPON:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tbool result = false;\n\t\tif (!pPed)\n\t\t\tprintf(\"HAS_CHAR_BEEN_DAMAGED_BY_WEAPON - Character doesn't exist\\n\");\n\t\telse {\n\t\t\tif (ScriptParams[1] == WEAPONTYPE_ANYMELEE || ScriptParams[1] == WEAPONTYPE_ANYWEAPON)\n\t\t\t\tresult = CheckDamagedWeaponType(pPed->m_lastWepDam, ScriptParams[1]);\n\t\t\telse\n\t\t\t\tresult = ScriptParams[1] == pPed->m_lastWepDam;\n\t\t}\n\t\tUpdateCompareFlag(result);\n\t\treturn 0;\n\t}\n\tcase COMMAND_HAS_CAR_BEEN_DAMAGED_BY_WEAPON:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tbool result = false;\n\t\tif (!pVehicle)\n\t\t\tprintf(\"HAS_CAR_BEEN_DAMAGED_BY_WEAPON - Vehicle doesn't exist\\n\");\n\t\telse {\n\t\t\tif (ScriptParams[1] == WEAPONTYPE_ANYMELEE || ScriptParams[1] == WEAPONTYPE_ANYWEAPON)\n\t\t\t\tresult = CheckDamagedWeaponType(pVehicle->m_nLastWeaponDamage, ScriptParams[1]);\n\t\t\telse\n\t\t\t\tresult = ScriptParams[1] == pVehicle->m_nLastWeaponDamage;\n\t\t}\n\t\tUpdateCompareFlag(result);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_CHAR_IN_CHARS_GROUP:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tCPed* pLeader = CPools::GetPedPool()->GetAt(ScriptParams[1]);\n\t\tscript_assert(pPed);\n\t\tscript_assert(pLeader);\n\t\tUpdateCompareFlag(pPed->m_leader == pLeader && !pPed->bWaitForLeaderToComeCloser);\n\t\treturn 0;\n\t}\n\tdefault:\n\t\tscript_assert(0);\n\t}\n\treturn -1;\n}\n"
  },
  {
    "path": "src/control/Script4.cpp",
    "content": "#include \"common.h\"\n\n#include \"Script.h\"\n#include \"ScriptCommands.h\"\n\n#include \"AnimBlendAssociation.h\"\n#include \"BulletInfo.h\"\n#include \"CarAI.h\"\n#include \"CarCtrl.h\"\n#include \"CivilianPed.h\"\n#include \"Cranes.h\"\n#include \"DMAudio.h\"\n#include \"Darkel.h\"\n#include \"Explosion.h\"\n#include \"Fire.h\"\n#include \"Frontend.h\"\n#include \"Garages.h\"\n#include \"General.h\"\n#include \"Heli.h\"\n#include \"Hud.h\"\n#include \"Messages.h\"\n#include \"ParticleObject.h\"\n#include \"PedRoutes.h\"\n#include \"Phones.h\"\n#include \"Pickups.h\"\n#include \"Plane.h\"\n#include \"Pools.h\"\n#include \"Population.h\"\n#include \"Radar.h\"\n#include \"Record.h\"\n#include \"RpAnimBlend.h\"\n#include \"Rubbish.h\"\n#include \"SpecialFX.h\"\n#include \"Stats.h\"\n#include \"Streaming.h\"\n#include \"TxdStore.h\"\n#include \"User.h\"\n#include \"WaterLevel.h\"\n#include \"World.h\"\n#include \"Zones.h\"\n#include \"Bike.h\"\n#include \"Wanted.h\"\n\n#ifdef FIX_BUGS\nstatic bool IsSlideObjectUsedWrongByScript(const CVector& posTarget, const CVector& slideBy)\n{\n\tif (posTarget == CVector(-559.476f, 784.807f, 23.279f) && slideBy == CVector(0.0f, 10.0f, 0.0f))\n\t\treturn true; // G-Spotlight bottom elevator, east side\n\tif (posTarget == CVector(-559.476f, 779.64f, 23.279f) && slideBy == CVector(0.0f, 10.0f, 0.0f))\n\t\treturn true; // G-Spotlight bottom elevator, west side\n\tif (posTarget == CVector(-553.563f, 790.595f, 97.917f) && slideBy == CVector(0.0f, 10.0f, 0.0f))\n\t\treturn true; // G-Spotlight top elevator, east side\n\tif (posTarget == CVector(-553.563f, 785.427f, 97.917f) && slideBy == CVector(0.0f, 10.0f, 0.0f))\n\t\treturn true; // G-Spotlight top elevator, west side\n\tif (posTarget == CVector(-866.689f, -572.095f, 15.573f) && slideBy == CVector(0.0f, 0.0f, 4.5f))\n\t\treturn true; // Cherry Popper garage door\n\treturn false;\n}\n#endif\n\nint8 CRunningScript::ProcessCommands800To899(int32 command)\n{\n\tCMatrix tmp_matrix;\n\tswitch (command) {\n\tcase COMMAND_IS_CHAR_IN_PLAYERS_GROUP:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tCPed* pLeader = CWorld::Players[ScriptParams[1]].m_pPed;\n\t\tscript_assert(pPed);\n\t\tscript_assert(pLeader);\n\t\tUpdateCompareFlag(pPed->m_leader == pLeader && !pPed->bWaitForLeaderToComeCloser);\n\t\treturn 0;\n\t}\n\tcase COMMAND_EXPLODE_CHAR_HEAD:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tpPed->InflictDamage(nil, WEAPONTYPE_SNIPERRIFLE, 1000.0f, PEDPIECE_HEAD, 0);\n\t\treturn 0;\n\t}\n\tcase COMMAND_EXPLODE_PLAYER_HEAD:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;\n\t\tscript_assert(pPed);\n\t\tpPed->InflictDamage(nil, WEAPONTYPE_SNIPERRIFLE, 1000.0f, PEDPIECE_HEAD, 0);\n\t\treturn 0;\n\t}\n\tcase COMMAND_ANCHOR_BOAT:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCBoat* pBoat = (CBoat*)CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pBoat && pBoat->m_vehType == VEHICLE_TYPE_BOAT);\n\t\tpBoat->m_bIsAnchored = (ScriptParams[1] != 0);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_ZONE_GROUP:\n\t{\n\t\tchar zone[KEY_LENGTH_IN_SCRIPT];\n\t\tCTheScripts::ReadTextLabelFromScript(&m_nIp, zone);\n\t\tm_nIp += KEY_LENGTH_IN_SCRIPT;\n\t\tCollectParameters(&m_nIp, 2);\n\t\tint zone_id = CTheZones::FindZoneByLabelAndReturnIndex(zone, ZONE_INFO);\n\t\tif (zone_id < 0) {\n\t\t\tprintf(\"Couldn't find zone - %s\\n\", zone);\n\t\t\treturn 0;\n\t\t}\n\t\twhile (zone_id >= 0) {\n\t\t\tCTheZones::SetPedGroup(zone_id, ScriptParams[0], ScriptParams[1]);\n\t\t\tzone_id = CTheZones::FindNextZoneByLabelAndReturnIndex(zone, ZONE_INFO);\n\t\t}\n\t\treturn 0;\n\t}\n\tcase COMMAND_START_CAR_FIRE:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tScriptParams[0] = gFireManager.StartScriptFire(pVehicle->GetPosition(), pVehicle, 0.8f, 1);\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\tcase COMMAND_START_CHAR_FIRE:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tScriptParams[0] = gFireManager.StartScriptFire(pPed->GetPosition(), pPed, 0.8f, 1);\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\tcase COMMAND_GET_RANDOM_CAR_OF_TYPE_IN_AREA:\n\t{\n\t\tCollectParameters(&m_nIp, 5);\n\t\tint handle = -1;\n\t\tuint32 i = CPools::GetVehiclePool()->GetSize();\n\t\tfloat infX = *(float*)&ScriptParams[0];\n\t\tfloat infY = *(float*)&ScriptParams[1];\n\t\tfloat supX = *(float*)&ScriptParams[2];\n\t\tfloat supY = *(float*)&ScriptParams[3];\n\t\twhile (i--) {\n\t\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetSlot(i);\n\t\t\tif (!pVehicle)\n\t\t\t\tcontinue;\n\t\t\tif (pVehicle->GetVehicleAppearance() != VEHICLE_APPEARANCE_CAR && pVehicle->GetVehicleAppearance() != VEHICLE_APPEARANCE_BIKE)\n\t\t\t\tcontinue;\n\t\t\tif (!pVehicle->bUsesCollision)\n\t\t\t\tcontinue;\n\t\t\tif (ScriptParams[4] != pVehicle->GetModelIndex() && ScriptParams[4] >= 0)\n\t\t\t\tcontinue;\n\t\t\tif (pVehicle->VehicleCreatedBy != RANDOM_VEHICLE)\n\t\t\t\tcontinue;\n\t\t\tif (!pVehicle->IsWithinArea(infX, infY, supX, supY))\n\t\t\t\tcontinue;\n\t\t\thandle = CPools::GetVehiclePool()->GetIndex(pVehicle);\n\t\t\tpVehicle->VehicleCreatedBy = MISSION_VEHICLE;\n\t\t\t++CCarCtrl::NumMissionCars;\n\t\t\t--CCarCtrl::NumRandomCars;\n\t\t\tif (m_bIsMissionScript)\n\t\t\t\tCTheScripts::MissionCleanUp.AddEntityToList(handle, CLEANUP_CAR);\n\t\t}\n\t\tScriptParams[0] = handle;\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\t/*\n\tcase COMMAND_GET_RANDOM_CAR_OF_TYPE_IN_ZONE:\n\t{\n\t\tchar zone[KEY_LENGTH_IN_SCRIPT];\n\t\tCTheScripts::ReadTextLabelFromScript(&m_nIp, zone);\n\t\tint zone_id = CTheZones::FindZoneByLabelAndReturnIndex(zone, ZONE_DEFAULT);\n\t\tif (zone_id != -1)\n\t\t\tm_nIp += KEY_LENGTH_IN_SCRIPT;\n\t\tCZone* pZone = CTheZones::GetNavigationZone(zone_id);\n\t\tCollectParameters(&m_nIp, 1);\n\t\tint handle = -1;\n\t\tuint32 i = CPools::GetVehiclePool()->GetSize();\n\t\twhile (i--) {\n\t\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetSlot(i);\n\t\t\tif (!pVehicle)\n\t\t\t\tcontinue;\n\t\t\tif (ScriptParams[0] != pVehicle->GetModelIndex() && ScriptParams[0] >= 0)\n\t\t\t\tcontinue;\n\t\t\tif (pVehicle->VehicleCreatedBy != RANDOM_VEHICLE)\n\t\t\t\tcontinue;\n\t\t\tif (!CTheZones::PointLiesWithinZone(&pVehicle->GetPosition(), pZone))\n\t\t\t\tcontinue;\n\t\t\thandle = CPools::GetVehiclePool()->GetIndex(pVehicle);\n\t\t\tpVehicle->VehicleCreatedBy = MISSION_VEHICLE;\n\t\t\t++CCarCtrl::NumMissionCars;\n\t\t\t--CCarCtrl::NumRandomCars;\n\t\t\tif (m_bIsMissionScript)\n\t\t\t\tCTheScripts::MissionCleanUp.AddEntityToList(handle, CLEANUP_CAR);\n\t\t}\n\t\tScriptParams[0] = handle;\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\t*/\n\tcase COMMAND_HAS_RESPRAY_HAPPENED:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tUpdateCompareFlag(CGarages::HasResprayHappened(ScriptParams[0]));\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_CAMERA_ZOOM:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tif (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_FOLLOWPED)\n\t\t\tTheCamera.SetZoomValueFollowPedScript(ScriptParams[0]);\n\t\telse if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_CAM_ON_A_STRING)\n\t\t\tTheCamera.SetZoomValueCamStringScript(ScriptParams[0]);\n\t\treturn 0;\n\t}\n\tcase COMMAND_CREATE_PICKUP_WITH_AMMO:\n\t{\n\t\tCollectParameters(&m_nIp, 6);\n\t\tint16 model = ScriptParams[0];\n\t\tif (model < 0)\n\t\t\tmodel = CTheScripts::UsedObjectArray[-model].index;\n\t\tCVector pos = *(CVector*)&ScriptParams[3];\n\t\tif (pos.z <= MAP_Z_LOW_LIMIT)\n\t\t\tpos.z = CWorld::FindGroundZForCoord(pos.x, pos.y) + PICKUP_PLACEMENT_OFFSET;\n\t\tCPickups::GetActualPickupIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));\n\t\tScriptParams[0] = CPickups::GenerateNewOne(pos, model, ScriptParams[1], ScriptParams[2]);\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_CAR_RAM_CAR:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tCVehicle* pTarget = CPools::GetVehiclePool()->GetAt(ScriptParams[1]);\n\t\tscript_assert(pTarget);\n\t\tCCarAI::TellCarToRamOtherCar(pVehicle, pTarget);\n\t\treturn 0;\n\t}\n\t/*\n\tcase COMMAND_SET_CAR_BLOCK_CAR:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tCVehicle* pTarget = CPools::GetVehiclePool()->GetAt(ScriptParams[1]);\n\t\tscript_assert(pTarget);\n\t\tCCarAI::TellCarToBlockOtherCar(pVehicle, pTarget);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_CHAR_OBJ_CATCH_TRAIN:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tpPed->bScriptObjectiveCompleted = false;\n\t\tpPed->SetObjective(OBJECTIVE_CATCH_TRAIN);\n\t\treturn 0;\n\t}\n\t*/\n#ifdef GTA_SCRIPT_COLLECTIVE\n\tcase COMMAND_SET_COLL_OBJ_CATCH_TRAIN:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCTheScripts::SetObjectiveForAllPedsInCollective(ScriptParams[0], OBJECTIVE_CATCH_TRAIN);\n\t\treturn 0;\n#endif\n\tcase COMMAND_SET_PLAYER_NEVER_GETS_TIRED:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPlayerInfo* pPlayer = &CWorld::Players[ScriptParams[0]];\n\t\tpPlayer->m_bInfiniteSprint = (ScriptParams[1] != 0);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_PLAYER_FAST_RELOAD:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPlayerInfo* pPlayer = &CWorld::Players[ScriptParams[0]];\n\t\tpPlayer->m_bFastReload = (ScriptParams[1] != 0);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_CHAR_BLEEDING:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tpPed->bPedIsBleeding = (ScriptParams[1] != 0);\n\t\treturn 0;\n\t}\n\t/*\n\tcase COMMAND_SET_CAR_FUNNY_SUSPENSION:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\t// no action\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_CAR_BIG_WHEELS:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tscript_assert(pVehicle->m_vehType == VEHICLE_TYPE_CAR);\n\t\tCAutomobile* pCar = (CAutomobile*)pVehicle;\n\t\tpCar->bBigWheels = (ScriptParams[1] != 0);\n\t\treturn 0;\n\t}\n\t*/\n\tcase COMMAND_SET_FREE_RESPRAYS:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCGarages::SetFreeResprays(ScriptParams[0] != 0);\n\t\treturn 0;\n\tcase COMMAND_SET_PLAYER_VISIBLE:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;\n\t\tscript_assert(pPed);\n\t\tpPed->bIsVisible = (ScriptParams[1] != 0);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_CHAR_VISIBLE:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tpPed->bIsVisible = (ScriptParams[1] != 0);\n\t\treturn 0;\n\t}\n\t/*\n\tcase COMMAND_SET_CAR_VISIBLE:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tpVehicle->bIsVisible = (ScriptParams[1] != 0);\n\t\treturn 0;\n\t}\n\t*/\n\tcase COMMAND_IS_AREA_OCCUPIED:\n\t{\n\t\tCollectParameters(&m_nIp, 11);\n\t\tfloat infX = *(float*)&ScriptParams[0];\n\t\tfloat infY = *(float*)&ScriptParams[1];\n\t\tfloat infZ = *(float*)&ScriptParams[2];\n\t\tfloat supX = *(float*)&ScriptParams[3];\n\t\tfloat supY = *(float*)&ScriptParams[4];\n\t\tfloat supZ = *(float*)&ScriptParams[5];\n\t\tif (infX > supX) {\n\t\t\tinfX = *(float*)&ScriptParams[3];\n\t\t\tsupX = *(float*)&ScriptParams[0];\n\t\t}\n\t\tif (infY > supY) {\n\t\t\tinfY = *(float*)&ScriptParams[4];\n\t\t\tsupY = *(float*)&ScriptParams[1];\n\t\t}\n\t\tif (infZ > supZ) {\n\t\t\tinfZ = *(float*)&ScriptParams[5];\n\t\t\tsupZ = *(float*)&ScriptParams[2];\n\t\t}\n\t\tint16 total;\n\t\tCWorld::FindObjectsIntersectingCube(CVector(infX, infY, infZ), CVector(supX, supY, supZ), &total, 2, nil,\n\t\t\t!!ScriptParams[6], !!ScriptParams[7], !!ScriptParams[8], !!ScriptParams[9], !!ScriptParams[10]);\n\t\tUpdateCompareFlag(total > 0);\n\t\treturn 0;\n\t}\n\t/*\n\tcase COMMAND_START_DRUG_RUN:\n\t\tCPlane::CreateIncomingCesna();\n\t\treturn 0;\n\tcase COMMAND_HAS_DRUG_RUN_BEEN_COMPLETED:\n\t\tUpdateCompareFlag(CPlane::HasCesnaLanded());\n\t\treturn 0;\n\tcase COMMAND_HAS_DRUG_PLANE_BEEN_SHOT_DOWN:\n\t\tUpdateCompareFlag(CPlane::HasCesnaBeenDestroyed());\n\t\treturn 0;\n\tcase COMMAND_SAVE_PLAYER_FROM_FIRES:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tgFireManager.ExtinguishPoint(CWorld::Players[ScriptParams[0]].GetPos(), 3.0f);\n\t\treturn 0;\n\t*/\n\tcase COMMAND_DISPLAY_TEXT:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\twchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\tCTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_fAtX = *(float*)&ScriptParams[0];\n\t\tCTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_fAtY = *(float*)&ScriptParams[1];\n\t\tuint16 len = CMessages::GetWideStringLength(text);\n\t\tfor (uint16 i = 0; i < len; i++)\n\t\t\tCTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_Text[i] = text[i];\n\t\tfor (uint16 i = len; i < SCRIPT_TEXT_MAX_LENGTH; i++)\n\t\t\tCTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_Text[i] = 0;\n\t\t++CTheScripts::NumberOfIntroTextLinesThisFrame;\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_TEXT_SCALE:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_fScaleX = *(float*)&ScriptParams[0];\n\t\tCTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_fScaleY = *(float*)&ScriptParams[1];\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_TEXT_COLOUR:\n\t{\n\t\tCollectParameters(&m_nIp, 4);\n\t\tCTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_sColor =\n\t\t\tCRGBA(ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3]);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_TEXT_JUSTIFY:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_bJustify = (ScriptParams[0] != 0);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_TEXT_CENTRE:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_bCentered = (ScriptParams[0] != 0);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_TEXT_WRAPX:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_fWrapX = *(float*)&ScriptParams[0];\n\t\treturn 0;\n\t}\n\t/*\n\tcase COMMAND_SET_TEXT_CENTRE_SIZE:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_fCenterSize = *(float*)&ScriptParams[0];\n\t\treturn 0;\n\t}\n\t*/\n\tcase COMMAND_SET_TEXT_BACKGROUND:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_bBackground = (ScriptParams[0] != 0);\n\t\treturn 0;\n\t}\n\t/*\n\tcase COMMAND_SET_TEXT_BACKGROUND_COLOUR:\n\t{\n\t\tCollectParameters(&m_nIp, 4);\n\t\tCTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_sBackgroundColor =\n\t\t\tCRGBA(ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3]);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_TEXT_BACKGROUND_ONLY_TEXT:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_bBackgroundOnly = (ScriptParams[0] != 0);\n\t\treturn 0;\n\t}\n\t*/\n\tcase COMMAND_SET_TEXT_PROPORTIONAL:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_bTextProportional = (ScriptParams[0] != 0);\n\t\treturn 0;\n\t}\n\t/*\n\tcase COMMAND_SET_TEXT_FONT:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_nFont = ScriptParams[0];\n\t\treturn 0;\n\t}\n\tcase COMMAND_INDUSTRIAL_PASSED:\n\t\tCStats::IndustrialPassed = true;\n\t\tDMAudio.PlayRadioAnnouncement(STREAMED_SOUND_ANNOUNCE_COMMERCIAL_OPEN);\n\t\treturn 0;\n\tcase COMMAND_COMMERCIAL_PASSED:\n\t\tCStats::CommercialPassed = true;\n\t\tDMAudio.PlayRadioAnnouncement(STREAMED_SOUND_ANNOUNCE_SUBURBAN_OPEN);\n\t\treturn 0;\n\tcase COMMAND_SUBURBAN_PASSED:\n\t\tCStats::SuburbanPassed = true;\n\t\treturn 0;\n\t*/\n\tcase COMMAND_ROTATE_OBJECT:\n\t{\n\t\tCollectParameters(&m_nIp, 4);\n\t\tCObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pObject);\n\t\tfloat heading = LimitAngleOnCircle(\n\t\t\tRADTODEG(Atan2(-pObject->GetForward().x, pObject->GetForward().y)));\n\t\tfloat headingTarget = *(float*)&ScriptParams[1];\n#ifdef FIX_BUGS\n\t\tfloat rotateBy = *(float*)&ScriptParams[2] * CTimer::GetTimeStepFix();\n#else\n\t\tfloat rotateBy = *(float*)&ScriptParams[2];\n#endif\n\t\tif (headingTarget == heading) { // using direct comparasion here is fine\n\t\t\tUpdateCompareFlag(true);\n\t\t\treturn 0;\n\t\t}\n\t\tfloat angleClockwise = LimitAngleOnCircle(headingTarget - heading);\n\t\tfloat angleCounterclockwise = LimitAngleOnCircle(heading - headingTarget);\n\t\tfloat newHeading;\n\t\tif (angleClockwise < angleCounterclockwise)\n\t\t\tnewHeading = rotateBy < angleClockwise ? heading + rotateBy : headingTarget;\n\t\telse\n\t\t\tnewHeading = rotateBy < angleCounterclockwise ? heading - rotateBy : headingTarget;\n\t\tbool obstacleInPath = false;\n\t\tif (ScriptParams[3]) {\n\t\t\tCVector pos = pObject->GetPosition();\n\t\t\ttmp_matrix.SetRotateZ(DEGTORAD(newHeading));\n\t\t\ttmp_matrix.GetPosition() += pos;\n\t\t\tCColModel* pColModel = pObject->GetColModel();\n\t\t\tCVector cp1 = tmp_matrix * pColModel->boundingBox.min;\n\t\t\tCVector cp2 = tmp_matrix * CVector(pColModel->boundingBox.max.x, pColModel->boundingBox.min.y, pColModel->boundingBox.min.z);\n\t\t\tCVector cp3 = tmp_matrix * CVector(pColModel->boundingBox.min.x, pColModel->boundingBox.max.y, pColModel->boundingBox.min.z);\n\t\t\tCVector cp4 = tmp_matrix * CVector(pColModel->boundingBox.min.x, pColModel->boundingBox.min.y, pColModel->boundingBox.max.z);\n\t\t\tint16 collisions;\n\t\t\tCWorld::FindObjectsIntersectingAngledCollisionBox(pColModel->boundingBox, tmp_matrix, pos,\n\t\t\t\tMin(cp1.x, Min(cp2.x, Min(cp3.x, cp4.x))),\n\t\t\t\tMin(cp1.y, Min(cp2.y, Min(cp3.y, cp4.y))),\n\t\t\t\tMax(cp1.x, Max(cp2.x, Max(cp3.x, cp4.x))),\n\t\t\t\tMax(cp1.y, Max(cp2.y, Max(cp3.y, cp4.y))),\n\t\t\t\t&collisions, 2, nil, false, true, true, false, false);\n\t\t\tif (collisions > 0)\n\t\t\t\tobstacleInPath = true;\n\t\t}\n\t\tif (obstacleInPath) {\n\t\t\tUpdateCompareFlag(true);\n\t\t\treturn 0;\n\t\t}\n\t\tpObject->SetHeading(DEGTORAD(newHeading));\n\t\tpObject->GetMatrix().UpdateRW();\n\t\tpObject->UpdateRwFrame();\n\t\tUpdateCompareFlag(newHeading == headingTarget); // using direct comparasion here is fine\n\t\treturn 0;\n\t}\n\tcase COMMAND_SLIDE_OBJECT:\n\t{\n\t\tCollectParameters(&m_nIp, 8);\n\t\tCObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pObject);\n\t\tCVector pos = pObject->GetPosition();\n\t\tCVector posTarget = *(CVector*)&ScriptParams[1];\n\t\tCVector slideBy = *(CVector*)&ScriptParams[4];\n#ifdef FIX_BUGS\n\t\t// the check is a hack for original script, where some objects are moved\n\t\t// via SLIDE_OBJECT instead of SET_OBJECT_POSITION\n\t\t// assuming the slide will take exactly one frame, which is true\n\t\t// only without accounting time step (which is a bug)\n\t\tif (!IsSlideObjectUsedWrongByScript(posTarget, slideBy))\n\t\t\tslideBy *= CTimer::GetTimeStepFix();\n#endif\n\t\tif (posTarget == pos) { // using direct comparasion here is fine\n\t\t\tUpdateCompareFlag(true);\n\t\t\treturn 0;\n\t\t}\n\t\tCVector posDiff = pos - posTarget;\n\t\tCVector newPosition;\n\t\tif (posDiff.x < 0)\n\t\t\tnewPosition.x = -posDiff.x < slideBy.x ? posTarget.x : pos.x + slideBy.x;\n\t\telse\n\t\t\tnewPosition.x = posDiff.x < slideBy.x ? posTarget.x : pos.x - slideBy.x;\n\t\tif (posDiff.y < 0)\n\t\t\tnewPosition.y = -posDiff.y < slideBy.y ? posTarget.y : pos.y + slideBy.y;\n\t\telse\n\t\t\tnewPosition.y = posDiff.y < slideBy.y ? posTarget.y : pos.y - slideBy.y;\n\t\tif (posDiff.z < 0)\n\t\t\tnewPosition.z = -posDiff.z < slideBy.z ? posTarget.z : pos.z + slideBy.z;\n\t\telse\n\t\t\tnewPosition.z = posDiff.z < slideBy.z ? posTarget.z : pos.z - slideBy.z;\n\t\tbool obstacleInPath = false;\n\t\tif (ScriptParams[7]) {\n\t\t\ttmp_matrix = pObject->GetMatrix();\n\t\t\ttmp_matrix.GetPosition() = newPosition;\n\t\t\tCColModel* pColModel = pObject->GetColModel();\n\t\t\tCVector cp1 = tmp_matrix * pColModel->boundingBox.min;\n\t\t\tCVector cp2 = tmp_matrix * CVector(pColModel->boundingBox.max.x, pColModel->boundingBox.min.y, pColModel->boundingBox.min.z);\n\t\t\tCVector cp3 = tmp_matrix * CVector(pColModel->boundingBox.min.x, pColModel->boundingBox.max.y, pColModel->boundingBox.min.z);\n\t\t\tCVector cp4 = tmp_matrix * CVector(pColModel->boundingBox.min.x, pColModel->boundingBox.min.y, pColModel->boundingBox.max.z);\n\t\t\tint16 collisions;\n\t\t\tCWorld::FindObjectsIntersectingAngledCollisionBox(pColModel->boundingBox, tmp_matrix, newPosition,\n\t\t\t\tMin(cp1.x, Min(cp2.x, Min(cp3.x, cp4.x))),\n\t\t\t\tMin(cp1.y, Min(cp2.y, Min(cp3.y, cp4.y))),\n\t\t\t\tMax(cp1.x, Max(cp2.x, Max(cp3.x, cp4.x))),\n\t\t\t\tMax(cp1.y, Max(cp2.y, Max(cp3.y, cp4.y))),\n\t\t\t\t&collisions, 2, nil, false, true, true, false, false);\n\t\t\tif (collisions > 0)\n\t\t\t\tobstacleInPath = true;\n\t\t}\n\t\tif (obstacleInPath) {\n\t\t\tUpdateCompareFlag(true);\n\t\t\treturn 0;\n\t\t}\n\t\tpObject->Teleport(newPosition);\n\t\tUpdateCompareFlag(newPosition == posTarget); // using direct comparasion here is fine\n\t\treturn 0;\n\t}\n\tcase COMMAND_REMOVE_CHAR_ELEGANTLY:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tif (pPed && pPed->CharCreatedBy == MISSION_CHAR){\n\t\t\tCWorld::RemoveReferencesToDeletedObject(pPed);\n\t\t\tif (pPed->bInVehicle && pPed->m_pMyVehicle)\n\t\t\t\tCTheScripts::RemoveThisPed(pPed);\n\t\t\telse{\n\t\t\t\tpPed->CharCreatedBy = RANDOM_CHAR;\n\t\t\t\tpPed->bRespondsToThreats = true;\n\t\t\t\tpPed->bScriptObjectiveCompleted = false;\n\t\t\t\tpPed->ClearLeader();\n\t\t\t\t--CPopulation::ms_nTotalMissionPeds;\n\t\t\t\tpPed->bFadeOut = true;\n\t\t\t\tCWorld::RemoveReferencesToDeletedObject(pPed);\n\t\t\t}\n\t\t}\n\t\tif (m_bIsMissionScript)\n\t\t\tCTheScripts::MissionCleanUp.RemoveEntityFromList(ScriptParams[0], CLEANUP_CHAR);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_CHAR_STAY_IN_SAME_PLACE:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tpPed->bKindaStayInSamePlace = (ScriptParams[1] != 0);\n\t\treturn 0;\n\t}\n\t/*\n\tcase COMMAND_IS_NASTY_GAME:\n\t\tUpdateCompareFlag(CGame::nastyGame);\n\t\treturn 0;\n\t*/\n\tcase COMMAND_UNDRESS_CHAR:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tchar name[KEY_LENGTH_IN_SCRIPT];\n\t\tCTheScripts::ReadTextLabelFromScript(&m_nIp, name);\n\t\tfor (int i = 0; i < KEY_LENGTH_IN_SCRIPT; i++)\n\t\t\tname[i] = tolower(name[i]);\n\t\tm_nIp += KEY_LENGTH_IN_SCRIPT;\n\t\tpPed->Undress(name);\n\t\treturn 0;\n\t}\n\tcase COMMAND_DRESS_CHAR:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tpPed->Dress();\n\t\treturn 0;\n\t}\n\t/*\n\tcase COMMAND_START_CHASE_SCENE:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCTimer::Suspend();\n\t\tCStreaming::DeleteAllRwObjects();\n\t\tCRecordDataForChase::StartChaseScene(*(float*)&ScriptParams[0]);\n\t\tCTimer::Resume();\n\t\treturn 0;\n\tcase COMMAND_STOP_CHASE_SCENE:\n\t\tCRecordDataForChase::CleanUpChaseScene();\n\t\treturn 0;\n\tcase COMMAND_IS_EXPLOSION_IN_AREA:\n\t{\n\t\tCollectParameters(&m_nIp, 7);\n\t\tfloat infX = *(float*)&ScriptParams[1];\n\t\tfloat infY = *(float*)&ScriptParams[2];\n\t\tfloat infZ = *(float*)&ScriptParams[3];\n\t\tfloat supX = *(float*)&ScriptParams[4];\n\t\tfloat supY = *(float*)&ScriptParams[5];\n\t\tfloat supZ = *(float*)&ScriptParams[6];\n\t\tif (infX > supX) {\n\t\t\tinfX = *(float*)&ScriptParams[4];\n\t\t\tsupX = *(float*)&ScriptParams[1];\n\t\t}\n\t\tif (infY > supY) {\n\t\t\tinfY = *(float*)&ScriptParams[5];\n\t\t\tsupY = *(float*)&ScriptParams[2];\n\t\t}\n\t\tif (infZ > supZ) {\n\t\t\tinfZ = *(float*)&ScriptParams[6];\n\t\t\tsupZ = *(float*)&ScriptParams[3];\n\t\t}\n\t\tUpdateCompareFlag(CExplosion::TestForExplosionInArea((eExplosionType)ScriptParams[0],\n\t\t\tinfX, supX, infY, supY, infZ, supZ));\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_EXPLOSION_IN_ZONE:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tchar zone[KEY_LENGTH_IN_SCRIPT];\n\t\tCTheScripts::ReadTextLabelFromScript(&m_nIp, zone);\n\t\tint zone_id = CTheZones::FindZoneByLabelAndReturnIndex(zone, ZONE_DEFAULT);\n\t\tif (zone_id != -1)\n\t\t\tm_nIp += KEY_LENGTH_IN_SCRIPT;\n\t\tCZone* pZone = CTheZones::GetNavigationZone(zone_id);\n\t\tUpdateCompareFlag(CExplosion::TestForExplosionInArea((eExplosionType)ScriptParams[0],\n\t\t\tpZone->minx, pZone->maxx, pZone->miny, pZone->maxy, pZone->minz, pZone->maxz));\n\t\treturn 0;\n\t}\n\tcase COMMAND_START_DRUG_DROP_OFF:\n\t\tCPlane::CreateDropOffCesna();\n\t\treturn 0;\n\tcase COMMAND_HAS_DROP_OFF_PLANE_BEEN_SHOT_DOWN:\n\t\tUpdateCompareFlag(CPlane::HasDropOffCesnaBeenShotDown());\n\t\treturn 0;\n\tcase COMMAND_FIND_DROP_OFF_PLANE_COORDINATES:\n\t{\n\t\tCVector pos = CPlane::FindDropOffCesnaCoordinates();\n\t\t*(CVector*)&ScriptParams[0] = pos;\n\t\tStoreParameters(&m_nIp, 3);\n\t\treturn 0;\n\t}\n\tcase COMMAND_CREATE_FLOATING_PACKAGE:\n\t{\n\t\tCollectParameters(&m_nIp, 3);\n\t\tCVector pos = *(CVector*)&ScriptParams[0];\n\t\tif (pos.z <= MAP_Z_LOW_LIMIT)\n\t\t\tpos.z = CWorld::FindGroundZForCoord(pos.x, pos.y) + PICKUP_PLACEMENT_OFFSET;\n\t\tScriptParams[0] = CPickups::GenerateNewOne(pos, MI_FLOATPACKAGE1, PICKUP_FLOATINGPACKAGE, 0);\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\t*/\n\tcase COMMAND_PLACE_OBJECT_RELATIVE_TO_CAR:\n\t{\n\t\tCollectParameters(&m_nIp, 5);\n\t\tCObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pObject);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]);\n\t\tscript_assert(pVehicle);\n\t\tCVector offset = *(CVector*)&ScriptParams[2];\n\t\tCPhysical::PlacePhysicalRelativeToOtherPhysical(pVehicle, pObject, offset);\n\t\treturn 0;\n\t}\n\tcase COMMAND_MAKE_OBJECT_TARGETTABLE:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pObject);\n\t\tCPlayerPed* pPlayerPed = CWorld::Players[CWorld::PlayerInFocus].m_pPed;\n\t\tscript_assert(pPlayerPed);\n\t\tpPlayerPed->MakeObjectTargettable(ScriptParams[0]);\n\t\treturn 0;\n\t}\n\tcase COMMAND_ADD_ARMOUR_TO_PLAYER:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPlayerPed* pPlayerPed = CWorld::Players[ScriptParams[0]].m_pPed;\n\t\tscript_assert(pPlayerPed);\n\t\tpPlayerPed->m_fArmour = clamp(pPlayerPed->m_fArmour + ScriptParams[1], 0.0f, CWorld::Players[ScriptParams[0]].m_nMaxArmour);\n\t\treturn 0;\n\t}\n\tcase COMMAND_ADD_ARMOUR_TO_CHAR:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tpPed->m_fArmour = clamp(pPed->m_fArmour + ScriptParams[1], 0.0f, 100.0f);\n\t\treturn 0;\n\t}\n\tcase COMMAND_OPEN_GARAGE:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCGarages::OpenGarage(ScriptParams[0]);\n\t\treturn 0;\n\t}\n\tcase COMMAND_CLOSE_GARAGE:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCGarages::CloseGarage(ScriptParams[0]);\n\t\treturn 0;\n\t}\n\tcase COMMAND_WARP_CHAR_FROM_CAR_TO_COORD:\n\t{\n\t\tCollectParameters(&m_nIp, 4);\n\t\tCPed *pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tCVector pos = *(CVector*)&ScriptParams[1];\n\t\tif (pos.z <= MAP_Z_LOW_LIMIT)\n\t\t\tpos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);\n\t\tif (pPed->bInVehicle){\n\t\t\tif (pPed->m_pMyVehicle->bIsBus)\n\t\t\t\tpPed->bRenderPedInCar = true;\n\t\t\tif (pPed->m_pMyVehicle->pDriver == pPed){\n\t\t\t\tpPed->m_pMyVehicle->RemoveDriver();\n\t\t\t\tpPed->m_pMyVehicle->SetStatus(STATUS_ABANDONED);\n\t\t\t\tpPed->m_pMyVehicle->bEngineOn = false;\n\t\t\t\tpPed->m_pMyVehicle->AutoPilot.m_nCruiseSpeed = 0;\n\t\t\t\tpPed->m_pMyVehicle->SetMoveSpeed(0.0f, 0.0f, -0.00001f);\n\t\t\t\tpPed->m_pMyVehicle->SetTurnSpeed(0.0f, 0.0f, 0.0f);\n\t\t\t}else{\n\t\t\t\tpPed->m_pMyVehicle->RemovePassenger(pPed);\n\t\t\t}\n\t\t\tif (pPed->m_vehDoor) {\n\t\t\t\tif (pPed->GetPedState() == PED_EXIT_CAR || pPed->GetPedState() == PED_DRAG_FROM_CAR) {\n\t\t\t\t\tuint8 flags = 0;\n\t\t\t\t\tif (pPed->m_pMyVehicle->IsBike()) {\n\t\t\t\t\t\tif (pPed->m_vehDoor == CAR_DOOR_LF ||\n\t\t\t\t\t\t\tpPed->m_vehDoor == CAR_DOOR_RF ||\n\t\t\t\t\t\t\tpPed->m_vehDoor == CAR_WINDSCREEN)\n\t\t\t\t\t\t\tflags = CAR_DOOR_FLAG_LF | CAR_DOOR_FLAG_RF;\n\t\t\t\t\t\telse if (pPed->m_vehDoor == CAR_DOOR_LR ||\n\t\t\t\t\t\t\tpPed->m_vehDoor == CAR_DOOR_RR)\n\t\t\t\t\t\t\tflags = CAR_DOOR_FLAG_LR | CAR_DOOR_FLAG_RR;\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tswitch (pPed->m_vehDoor) {\n\t\t\t\t\t\tcase CAR_DOOR_LF:\n\t\t\t\t\t\t\tflags = pPed->m_pMyVehicle->m_nNumMaxPassengers != 0 ? CAR_DOOR_FLAG_LF : CAR_DOOR_FLAG_LF | CAR_DOOR_FLAG_LR;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase CAR_DOOR_LR:\n\t\t\t\t\t\t\tflags = pPed->m_pMyVehicle->m_nNumMaxPassengers != 0 ? CAR_DOOR_FLAG_RF : CAR_DOOR_FLAG_LF | CAR_DOOR_FLAG_LR;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase CAR_DOOR_RF:\n\t\t\t\t\t\t\tflags = CAR_DOOR_FLAG_RF;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase CAR_DOOR_RR:\n\t\t\t\t\t\t\tflags = CAR_DOOR_FLAG_RR;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tpPed->m_pMyVehicle->m_nGettingOutFlags &= ~flags;\n\t\t\t\t\tpPed->m_pMyVehicle->ProcessOpenDoor(pPed->m_vehDoor, ANIM_STD_NUM, 0.0f);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tpPed->RemoveInCarAnims();\n\t\tpPed->bInVehicle = false;\n\t\tpPed->m_pMyVehicle = nil;\n\t\tpPed->SetPedState(PED_IDLE);\n\t\tpPed->m_nLastPedState = PED_NONE;\n\t\tpPed->bUsesCollision = true;\n\t\tpPed->SetMoveSpeed(0.0f, 0.0f, 0.0f);\n\t\tpPed->ReplaceWeaponWhenExitingVehicle();\n\t\tif (pPed->m_pVehicleAnim)\n\t\t\tpPed->m_pVehicleAnim->blendDelta = -1000.0f;\n\t\tpPed->m_pVehicleAnim = nil;\n\t\tpPed->RestartNonPartialAnims();\n\t\tpPed->SetMoveState(PEDMOVE_NONE);\n\t\tCAnimManager::BlendAnimation(pPed->GetClump(), pPed->m_animGroup, ANIM_STD_IDLE, 1000.0f);\n\t\tpos.z += pPed->GetDistanceFromCentreOfMassToBaseOfModel();\n\t\tpPed->Teleport(pos);\n\t\tCTheScripts::ClearSpaceForMissionEntity(pos, pPed);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_VISIBILITY_OF_CLOSEST_OBJECT_OF_TYPE:\n\t{\n\t\tCollectParameters(&m_nIp, 6);\n\t\tCVector pos = *(CVector*)&ScriptParams[0];\n\t\tif (pos.z <= MAP_Z_LOW_LIMIT)\n\t\t\tpos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);\n\t\tfloat range = *(float*)&ScriptParams[3];\n\t\tint mi = ScriptParams[4] < 0 ? CTheScripts::UsedObjectArray[-ScriptParams[4]].index : ScriptParams[4];\n\t\tint16 total;\n\t\tCEntity* apEntities[16];\n\t\tCWorld::FindObjectsOfTypeInRange(mi, pos, range, true, &total, 16, apEntities, true, false, false, true, true);\n\t\tif (total == 0)\n\t\t\tCWorld::FindObjectsOfTypeInRangeSectorList(mi, CWorld::GetBigBuildingList(LEVEL_GENERIC), pos, range, true, &total, 16, apEntities);\n\t\tif (total == 0)\n\t\t\tCWorld::FindObjectsOfTypeInRangeSectorList(mi, CWorld::GetBigBuildingList(CTheZones::GetLevelFromPosition(&pos)), pos, range, true, &total, 16, apEntities);\n\t\tCEntity* pClosestEntity = nil;\n\t\tfloat min_dist = 2.0f * range;\n\t\tfor (int i = 0; i < total; i++) {\n\t\t\tfloat dist = (apEntities[i]->GetPosition() - pos).Magnitude();\n\t\t\tif (dist < min_dist) {\n\t\t\t\tmin_dist = dist;\n\t\t\t\tpClosestEntity = apEntities[i];\n\t\t\t}\n\t\t}\n\t\tif (pClosestEntity) {\n\t\t\tpClosestEntity->bIsVisible = (ScriptParams[5] != 0);\n\t\t\tCTheScripts::AddToInvisibilitySwapArray(pClosestEntity, ScriptParams[5] != 0);\n\t\t}\n\t\treturn 0;\n\t}\n\t/*\n\tcase COMMAND_HAS_CHAR_SPOTTED_CHAR:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tCPed* pTarget = CPools::GetPedPool()->GetAt(ScriptParams[1]);\n\t\tscript_assert(pTarget);\n\t\tUpdateCompareFlag(pPed->OurPedCanSeeThisOne(pTarget));\n\t\treturn 0;\n\t}\n\t*/\n\tcase COMMAND_SET_CHAR_OBJ_HAIL_TAXI:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tpPed->bScriptObjectiveCompleted = false;\n\t\tpPed->SetObjective(OBJECTIVE_HAIL_TAXI);\n\t\treturn 0;\n\t}\n\tcase COMMAND_HAS_OBJECT_BEEN_DAMAGED:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pObject);\n\t\tUpdateCompareFlag(pObject->bRenderDamaged || !pObject->bIsVisible);\n\t\treturn 0;\n\t}\n\t/*\n\tcase COMMAND_START_KILL_FRENZY_HEADSHOT:\n\t{\n\t\twchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\tCollectParameters(&m_nIp, 8);\n\t\tCDarkel::StartFrenzy((eWeaponType)ScriptParams[0], ScriptParams[1], ScriptParams[2],\n\t\t\tScriptParams[3], text, ScriptParams[4], ScriptParams[5],\n\t\t\tScriptParams[6], ScriptParams[7] != 0, true);\n\t\treturn 0;\n\t}\n\tcase COMMAND_ACTIVATE_MILITARY_CRANE:\n\t{\n\t\tCollectParameters(&m_nIp, 10);\n\t\tfloat infX = *(float*)&ScriptParams[2];\n\t\tfloat infY = *(float*)&ScriptParams[3];\n\t\tfloat supX = *(float*)&ScriptParams[4];\n\t\tfloat supY = *(float*)&ScriptParams[5];\n\t\tif (infX > supX) {\n\t\t\tinfX = *(float*)&ScriptParams[4];\n\t\t\tsupX = *(float*)&ScriptParams[2];\n\t\t}\n\t\tif (infY > supY) {\n\t\t\tinfY = *(float*)&ScriptParams[5];\n\t\t\tsupY = *(float*)&ScriptParams[3];\n\t\t}\n\t\tCCranes::ActivateCrane(infX, supX, infY, supY,\n\t\t\t*(float*)&ScriptParams[6], *(float*)&ScriptParams[7], *(float*)&ScriptParams[8],\n\t\t\tDEGTORAD(*(float*)&ScriptParams[9]), false, true,\n\t\t\t*(float*)&ScriptParams[0], *(float*)&ScriptParams[1]);\n\t\treturn 0;\n\t}\n\t*/\n\tcase COMMAND_WARP_PLAYER_INTO_CAR:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;\n\t\tscript_assert(pPed);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]);\n\t\tscript_assert(pVehicle);\n\t\tpPed->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, pVehicle);\n\t\tpPed->WarpPedIntoCar(pVehicle);\n\t\treturn 0;\n\t}\n\tcase COMMAND_WARP_CHAR_INTO_CAR:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]);\n\t\tscript_assert(pVehicle);\n\t\tpPed->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, pVehicle);\n\t\tpPed->WarpPedIntoCar(pVehicle);\n\t\treturn 0;\n\t}\n\t//case COMMAND_SWITCH_CAR_RADIO:\n\t//case COMMAND_SET_AUDIO_STREAM:\n\tcase COMMAND_PRINT_WITH_2_NUMBERS_BIG:\n\t{\n\t\twchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\tCollectParameters(&m_nIp, 4);\n\t\tCMessages::AddBigMessageWithNumber(text, ScriptParams[2], ScriptParams[3] - 1, ScriptParams[0], ScriptParams[1], -1, -1, -1, -1);\n\t\treturn 0;\n\t}\n\t/*\n\tcase COMMAND_PRINT_WITH_3_NUMBERS_BIG:\n\t{\n\t\twchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\tCollectParameters(&m_nIp, 5);\n\t\tCMessages::AddBigMessageWithNumber(text, ScriptParams[3], ScriptParams[4] - 1, ScriptParams[0], ScriptParams[1], ScriptParams[2], -1, -1, -1);\n\t\treturn 0;\n\t}\n\tcase COMMAND_PRINT_WITH_4_NUMBERS_BIG:\n\t{\n\t\twchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\tCollectParameters(&m_nIp, 6);\n\t\tCMessages::AddBigMessageWithNumber(text, ScriptParams[4], ScriptParams[5] - 1, ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], -1, -1);\n\t\treturn 0;\n\t}\n\tcase COMMAND_PRINT_WITH_5_NUMBERS_BIG:\n\t{\n\t\twchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\tCollectParameters(&m_nIp, 7);\n\t\tCMessages::AddBigMessageWithNumber(text, ScriptParams[5], ScriptParams[6] - 1, ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], ScriptParams[4], -1);\n\t\treturn 0;\n\t}\n\tcase COMMAND_PRINT_WITH_6_NUMBERS_BIG:\n\t{\n\t\twchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\tCollectParameters(&m_nIp, 8);\n\t\tCMessages::AddBigMessageWithNumber(text, ScriptParams[6], ScriptParams[7] - 1, ScriptParams[0], ScriptParams[1], ScriptParams[2], ScriptParams[3], ScriptParams[4], ScriptParams[5]);\n\t\treturn 0;\n\t}\n\t*/\n\tcase COMMAND_SET_CHAR_WAIT_STATE:\n\t{\n\t\tCollectParameters(&m_nIp, 3);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tpPed->SetWaitState((eWaitState)ScriptParams[1], ScriptParams[2] >= 0 ? &ScriptParams[2] : nil);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_CAMERA_BEHIND_PLAYER:\n\t\tTheCamera.SetCameraDirectlyBehindForFollowPed_CamOnAString();\n\t\treturn 0;\n\t/*\n\tcase COMMAND_SET_MOTION_BLUR:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tTheCamera.SetMotionBlur(0, 0, 0, 0, ScriptParams[0]);\n\t\treturn 0;\n\tcase COMMAND_PRINT_STRING_IN_STRING:\n\t{\n\t\twchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\twchar* string = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCMessages::AddMessageWithString(text, ScriptParams[0], ScriptParams[1], string);\n\t\treturn 0;\n\t}\n\t*/\n\tcase COMMAND_CREATE_RANDOM_CHAR:\n\t{\n\t\tCollectParameters(&m_nIp, 3);\n\t\tCZoneInfo zoneinfo;\n\t\tCTheZones::GetZoneInfoForTimeOfDay(&CWorld::Players[CWorld::PlayerInFocus].GetPos(), &zoneinfo);\n\t\tint mi;\n\t\tePedType pedtype = PEDTYPE_COP;\n\t\tint attempt = 0;\n\t\twhile (pedtype != PEDTYPE_CIVMALE && pedtype != PEDTYPE_CIVFEMALE && attempt < 5) {\n\t\t\tmi = CPopulation::ChooseCivilianOccupation(zoneinfo.pedGroup);\n\t\t\tif (CModelInfo::GetModelInfo(mi)->GetRwObject())\n\t\t\t\tpedtype = ((CPedModelInfo*)(CModelInfo::GetModelInfo(mi)))->m_pedType;\n\t\t\tattempt++;\n\t\t}\n\t\tif (!CModelInfo::GetModelInfo(mi)->GetRwObject()) {\n\t\t\tmi = MI_MALE01;\n\t\t\tpedtype = ((CPedModelInfo*)(CModelInfo::GetModelInfo(mi)))->m_pedType;\n\t\t}\n\t\tCPed* ped = new CCivilianPed(pedtype, mi);\n\t\tped->CharCreatedBy = MISSION_CHAR;\n\t\tped->bRespondsToThreats = false;\n\t\tped->bAllowMedicsToReviveMe = false;\n\t\tped->bIsPlayerFriend = false;\n\t\tCVector pos = *(CVector*)&ScriptParams[0];\n\t\tif (pos.z <= MAP_Z_LOW_LIMIT)\n\t\t\tpos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);\n\t\tpos.z += 1.0f;\n\t\tped->SetPosition(pos);\n\t\tped->SetOrientation(0.0f, 0.0f, 0.0f);\n\t\tCTheScripts::ClearSpaceForMissionEntity(pos, ped);\n\t\tif (m_bIsMissionScript)\n\t\t\tped->bIsStaticWaitingForCollision = true;\n\t\tCWorld::Add(ped);\n\t\tped->m_nZoneLevel = CTheZones::GetLevelFromPosition(&pos);\n\t\tCPopulation::ms_nTotalMissionPeds++;\n\t\tScriptParams[0] = CPools::GetPedPool()->GetIndex(ped);\n\t\tStoreParameters(&m_nIp, 1);\n\t\tif (m_bIsMissionScript)\n\t\t\tCTheScripts::MissionCleanUp.AddEntityToList(ScriptParams[0], CLEANUP_CHAR);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_CHAR_OBJ_STEAL_ANY_CAR:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tpPed->bScriptObjectiveCompleted = false;\n\t\tpPed->SetObjective(OBJECTIVE_STEAL_ANY_CAR);\n\t\treturn 0;\n\t}\n\t/*\n\tcase COMMAND_SET_2_REPEATED_PHONE_MESSAGES:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\twchar* text1 = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\twchar* text2 = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\tgPhoneInfo.SetPhoneMessage_Repeatedly(ScriptParams[0], text1, text2, nil, nil, nil, nil);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_2_PHONE_MESSAGES:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\twchar* text1 = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\twchar* text2 = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\tgPhoneInfo.SetPhoneMessage_JustOnce(ScriptParams[0], text1, text2, nil, nil, nil, nil);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_3_REPEATED_PHONE_MESSAGES:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\twchar* text1 = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\twchar* text2 = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\twchar* text3 = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\tgPhoneInfo.SetPhoneMessage_Repeatedly(ScriptParams[0], text1, text2, text3, nil, nil, nil);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_3_PHONE_MESSAGES:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\twchar* text1 = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\twchar* text2 = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\twchar* text3 = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\tgPhoneInfo.SetPhoneMessage_JustOnce(ScriptParams[0], text1, text2, text3, nil, nil, nil);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_4_REPEATED_PHONE_MESSAGES:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\twchar* text1 = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\twchar* text2 = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\twchar* text3 = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\twchar* text4 = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\tgPhoneInfo.SetPhoneMessage_Repeatedly(ScriptParams[0], text1, text2, text3, text4, nil, nil);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_4_PHONE_MESSAGES:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\twchar* text1 = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\twchar* text2 = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\twchar* text3 = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\twchar* text4 = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\tgPhoneInfo.SetPhoneMessage_JustOnce(ScriptParams[0], text1, text2, text3, text4, nil, nil);\n\t\treturn 0;\n\t}\n\t*/\n\tcase COMMAND_IS_SNIPER_BULLET_IN_AREA:\n\t{\n\t\tCollectParameters(&m_nIp, 6);\n\t\tfloat infX = *(float*)&ScriptParams[0];\n\t\tfloat infY = *(float*)&ScriptParams[1];\n\t\tfloat infZ = *(float*)&ScriptParams[2];\n\t\tfloat supX = *(float*)&ScriptParams[3];\n\t\tfloat supY = *(float*)&ScriptParams[4];\n\t\tfloat supZ = *(float*)&ScriptParams[5];\n\t\tif (infX > supX) {\n\t\t\tinfX = *(float*)&ScriptParams[3];\n\t\t\tsupX = *(float*)&ScriptParams[0];\n\t\t}\n\t\tif (infY > supY) {\n\t\t\tinfY = *(float*)&ScriptParams[4];\n\t\t\tsupY = *(float*)&ScriptParams[1];\n\t\t}\n\t\tif (infZ > supZ) {\n\t\t\tinfZ = *(float*)&ScriptParams[5];\n\t\t\tsupZ = *(float*)&ScriptParams[2];\n\t\t}\n\t\tUpdateCompareFlag(CBulletInfo::TestForSniperBullet(infX, supX, infY, supY, infZ, supZ));\n\t\treturn 0;\n\t}\n\t/*\n\tcase COMMAND_GIVE_PLAYER_DETONATOR:\n\t\tCGarages::GivePlayerDetonator();\n\t\treturn 0;\n\t*/\n#ifdef GTA_SCRIPT_COLLECTIVE\n\tcase COMMAND_SET_COLL_OBJ_STEAL_ANY_CAR:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCTheScripts::SetObjectiveForAllPedsInCollective(ScriptParams[0], OBJECTIVE_STEAL_ANY_CAR);\n\t\treturn 0;\n#endif\n\tcase COMMAND_SET_OBJECT_VELOCITY:\n\t{\n\t\tCollectParameters(&m_nIp, 4);\n\t\tCObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pObject);\n\t\tpObject->SetMoveSpeed(*(CVector*)&ScriptParams[1] * METERS_PER_SECOND_TO_GAME_SPEED);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_OBJECT_COLLISION:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pObject);\n\t\tpObject->bUsesCollision = (ScriptParams[1] != 0);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_ICECREAM_JINGLE_ON:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\t// Adding this check to correspond to command name.\n\t\t// All original game scripts always assume that the vehicle is actually Mr. Whoopee,\n\t\t// but maybe there are mods that use it as \"is alarm activated\"?\n\t\tscript_assert(pVehicle->GetModelIndex() == MI_MRWHOOP);\n\t\tUpdateCompareFlag(pVehicle->m_bSirenOrAlarm);\n\t\treturn 0;\n\t}\n\tdefault:\n\t\tscript_assert(0);\n\t}\n\treturn -1;\n}\n\nint8 CRunningScript::ProcessCommands900To999(int32 command)\n{\n\tchar str[52];\n\tchar onscreen_str[KEY_LENGTH_IN_SCRIPT];\n\tswitch (command) {\n\tcase COMMAND_PRINT_STRING_IN_STRING_NOW:\n\t{\n\t\twchar* source = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\twchar* pstr = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCMessages::AddMessageJumpQWithString(source, ScriptParams[0], ScriptParams[1], pstr);\n\t\treturn 0;\n\t}\n\t//case COMMAND_PRINT_STRING_IN_STRING_SOON:\n\t/*\n\tcase COMMAND_SET_5_REPEATED_PHONE_MESSAGES:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\twchar* text1 = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\twchar* text2 = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\twchar* text3 = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\twchar* text4 = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\twchar* text5 = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\tgPhoneInfo.SetPhoneMessage_Repeatedly(ScriptParams[0], text1, text2, text3, text4, text5, nil);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_5_PHONE_MESSAGES:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\twchar* text1 = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\twchar* text2 = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\twchar* text3 = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\twchar* text4 = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\twchar* text5 = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\tgPhoneInfo.SetPhoneMessage_JustOnce(ScriptParams[0], text1, text2, text3, text4, text5, nil);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_6_REPEATED_PHONE_MESSAGES:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\twchar* text1 = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\twchar* text2 = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\twchar* text3 = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\twchar* text4 = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\twchar* text5 = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\twchar* text6 = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\tgPhoneInfo.SetPhoneMessage_Repeatedly(ScriptParams[0], text1, text2, text3, text4, text5, text6);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_6_PHONE_MESSAGES:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\twchar* text1 = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\twchar* text2 = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\twchar* text3 = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\twchar* text4 = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\twchar* text5 = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\twchar* text6 = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\tgPhoneInfo.SetPhoneMessage_JustOnce(ScriptParams[0], text1, text2, text3, text4, text5, text6);\n\t\treturn 0;\n\t}\n\t*/\n\tcase COMMAND_IS_POINT_OBSCURED_BY_A_MISSION_ENTITY:\n\t{\n\t\tCollectParameters(&m_nIp, 6);\n\t\tfloat infX = *(float*)&ScriptParams[0] - *(float*)&ScriptParams[3];\n\t\tfloat supX = *(float*)&ScriptParams[0] + *(float*)&ScriptParams[3];\n\t\tfloat infY = *(float*)&ScriptParams[1] - *(float*)&ScriptParams[4];\n\t\tfloat supY = *(float*)&ScriptParams[1] + *(float*)&ScriptParams[4];\n\t\tfloat infZ = *(float*)&ScriptParams[2] - *(float*)&ScriptParams[5];\n\t\tfloat supZ = *(float*)&ScriptParams[2] + *(float*)&ScriptParams[5];\n\t\tif (infX > supX) {\n\t\t\tfloat tmp = infX;\n\t\t\tinfX = supX;\n\t\t\tsupX = tmp;\n\t\t}\n\t\tif (infY > supY) {\n\t\t\tfloat tmp = infY;\n\t\t\tinfY = supY;\n\t\t\tsupY = tmp;\n\t\t}\n\t\tif (infZ > supZ) {\n\t\t\tfloat tmp = infZ;\n\t\t\tinfZ = supZ;\n\t\t\tsupZ = tmp;\n\t\t}\n\t\tint16 total;\n\t\tCWorld::FindMissionEntitiesIntersectingCube(CVector(infX, infY, infZ), CVector(supX, supY, supZ), &total, 2, nil, true, true, true);\n\t\tUpdateCompareFlag(total > 0);\n\t\treturn 0;\n\t}\n\tcase COMMAND_LOAD_ALL_MODELS_NOW:\n#ifdef FIX_BUGS\n\t\tCTimer::Suspend();\n#else\n\t\tCTimer::Stop();\n#endif\n\t\tCStreaming::LoadAllRequestedModels(false);\n#ifdef FIX_BUGS\n\t\tCTimer::Resume();\n#else\n\t\tCTimer::Update();\n#endif\n\t\treturn 0;\n\tcase COMMAND_ADD_TO_OBJECT_VELOCITY:\n\t{\n\t\tCollectParameters(&m_nIp, 4);\n\t\tCObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pObject);\n\t\tpObject->AddToMoveSpeed(*(CVector*)&ScriptParams[1] * METERS_PER_SECOND_TO_GAME_SPEED);\n\t\treturn 0;\n\t}\n\tcase COMMAND_DRAW_SPRITE:\n\t{\n\t\tCollectParameters(&m_nIp, 9);\n\t\tCTheScripts::IntroRectangles[CTheScripts::NumberOfIntroRectanglesThisFrame].m_bIsUsed = true;\n\t\tCTheScripts::IntroRectangles[CTheScripts::NumberOfIntroRectanglesThisFrame].m_nTextureId = ScriptParams[0] - 1;\n\t\tCTheScripts::IntroRectangles[CTheScripts::NumberOfIntroRectanglesThisFrame].m_sRect = CRect(\n\t\t\t*(float*)&ScriptParams[1], *(float*)&ScriptParams[2], *(float*)&ScriptParams[1] + *(float*)&ScriptParams[3], *(float*)&ScriptParams[2] + *(float*)&ScriptParams[4]);\n\t\tCTheScripts::IntroRectangles[CTheScripts::NumberOfIntroRectanglesThisFrame].m_sColor = CRGBA(ScriptParams[5], ScriptParams[6], ScriptParams[7], ScriptParams[8]);\n\t\tCTheScripts::NumberOfIntroRectanglesThisFrame++;\n\t\treturn 0;\n\t}\n\tcase COMMAND_DRAW_RECT:\n\t{\n\t\tCollectParameters(&m_nIp, 8);\n\t\tCTheScripts::IntroRectangles[CTheScripts::NumberOfIntroRectanglesThisFrame].m_bIsUsed = true;\n\t\tCTheScripts::IntroRectangles[CTheScripts::NumberOfIntroRectanglesThisFrame].m_nTextureId = -1;\n\t\tCTheScripts::IntroRectangles[CTheScripts::NumberOfIntroRectanglesThisFrame].m_sRect = CRect(\n\t\t\t*(float*)&ScriptParams[0], *(float*)&ScriptParams[1], *(float*)&ScriptParams[0] + *(float*)&ScriptParams[2], *(float*)&ScriptParams[1] + *(float*)&ScriptParams[3]);\n\t\tCTheScripts::IntroRectangles[CTheScripts::NumberOfIntroRectanglesThisFrame].m_sColor = CRGBA(ScriptParams[4], ScriptParams[5], ScriptParams[6], ScriptParams[7]);\n\t\tCTheScripts::NumberOfIntroRectanglesThisFrame++;\n\t\treturn 0;\n\t}\n\tcase COMMAND_LOAD_SPRITE:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tstrncpy(str, (char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT);\n\t\tfor (int i = 0; i < KEY_LENGTH_IN_SCRIPT; i++)\n\t\t\tstr[i] = tolower(str[i]);\n\t\tm_nIp += KEY_LENGTH_IN_SCRIPT;\n\t\tint slot = CTxdStore::FindTxdSlot(\"script\");\n\t\tCTxdStore::PushCurrentTxd();\n\t\tCTxdStore::SetCurrentTxd(slot);\n\t\tCTheScripts::ScriptSprites[ScriptParams[0] - 1].SetTexture(str);\n\t\tCTxdStore::PopCurrentTxd();\n\t\treturn 0;\n\t}\n\tcase COMMAND_LOAD_TEXTURE_DICTIONARY:\n\t{\n\t\tstrcpy(str, \"models\\\\\");\n\t\tstrncpy(str + sizeof(\"models\\\\\"), (char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT);\n\t\tstrcat(str, \".txd\");\n\t\tm_nIp += KEY_LENGTH_IN_SCRIPT;\n\t\tint slot = CTxdStore::FindTxdSlot(\"script\");\n\t\tif (slot == -1)\n\t\t\tslot = CTxdStore::AddTxdSlot(\"script\");\n\t\tCTxdStore::LoadTxd(slot, str);\n\t\tCTxdStore::AddRef(slot);\n\t\treturn 0;\n\t}\n\tcase COMMAND_REMOVE_TEXTURE_DICTIONARY:\n\t{\n\t\tCTheScripts::RemoveScriptTextureDictionary();\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_OBJECT_DYNAMIC:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pObject);\n\t\tif (ScriptParams[1]) {\n\t\t\tif (pObject->bIsStatic) {\n\t\t\t\tpObject->SetIsStatic(false);\n\t\t\t\tpObject->AddToMovingList();\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tif (!pObject->bIsStatic) {\n\t\t\t\tpObject->SetIsStatic(true);\n\t\t\t\tpObject->RemoveFromMovingList();\n\t\t\t}\n\t\t}\n\t\treturn 0;\n\t}\n\t/*\n\tcase COMMAND_SET_CHAR_ANIM_SPEED:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tCAnimBlendAssociation* pAssoc = RpAnimBlendClumpGetFirstAssociation(pPed->GetClump());\n\t\tif (pAssoc)\n\t\t\tpAssoc->speed = *(float*)&ScriptParams[1];\n\t\treturn 0;\n\t}\n\t*/\n\tcase COMMAND_PLAY_MISSION_PASSED_TUNE:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tDMAudio.ChangeMusicMode(MUSICMODE_FRONTEND);\n\t\tDMAudio.PlayFrontEndTrack(ScriptParams[0] + STREAMED_SOUND_MISSION_COMPLETED - 1, 0);\n\t\treturn 0;\n\t}\n\tcase COMMAND_CLEAR_AREA:\n\t{\n\t\tCollectParameters(&m_nIp, 5);\n\t\tCVector pos = *(CVector*)&ScriptParams[0];\n\t\tif (pos.z <= MAP_Z_LOW_LIMIT)\n\t\t\tpos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);\n\t\tCWorld::ClearExcitingStuffFromArea(pos, *(float*)&ScriptParams[3], ScriptParams[4]);\n\t\treturn 0;\n\t}\n\tcase COMMAND_FREEZE_ONSCREEN_TIMER:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCUserDisplay::OnscnTimer.m_bDisabled = ScriptParams[0] != 0;\n\t\treturn 0;\n\tcase COMMAND_SWITCH_CAR_SIREN:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tpVehicle->m_bSirenOrAlarm = ScriptParams[1] != 0;\n\t\treturn 0;\n\t}\n\t/*\n\tcase COMMAND_SWITCH_PED_ROADS_ON_ANGLED:\n\t{\n\t\tCollectParameters(&m_nIp, 7);\n\t\tThePaths.SwitchRoadsInAngledArea(*(float*)&ScriptParams[0], *(float*)&ScriptParams[1], *(float*)&ScriptParams[2],\n\t\t\t*(float*)&ScriptParams[3], *(float*)&ScriptParams[4], *(float*)&ScriptParams[5], *(float*)&ScriptParams[6], 0, 1);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SWITCH_PED_ROADS_OFF_ANGLED:\n\t\tCollectParameters(&m_nIp, 7);\n\t\tThePaths.SwitchRoadsInAngledArea(*(float*)&ScriptParams[0], *(float*)&ScriptParams[1], *(float*)&ScriptParams[2],\n\t\t\t*(float*)&ScriptParams[3], *(float*)&ScriptParams[4], *(float*)&ScriptParams[5], *(float*)&ScriptParams[6], 0, 0);\n\t\treturn 0;\n\tcase COMMAND_SWITCH_ROADS_ON_ANGLED:\n\t\tCollectParameters(&m_nIp, 7);\n\t\tThePaths.SwitchRoadsInAngledArea(*(float*)&ScriptParams[0], *(float*)&ScriptParams[1], *(float*)&ScriptParams[2],\n\t\t\t*(float*)&ScriptParams[3], *(float*)&ScriptParams[4], *(float*)&ScriptParams[5], *(float*)&ScriptParams[6], 1, 1);\n\t\treturn 0;\n\tcase COMMAND_SWITCH_ROADS_OFF_ANGLED:\n\t\tCollectParameters(&m_nIp, 7);\n\t\tThePaths.SwitchRoadsInAngledArea(*(float*)&ScriptParams[0], *(float*)&ScriptParams[1], *(float*)&ScriptParams[2],\n\t\t\t*(float*)&ScriptParams[3], *(float*)&ScriptParams[4], *(float*)&ScriptParams[5], *(float*)&ScriptParams[6], 1, 0);\n\t\treturn 0;\n\t*/\n\tcase COMMAND_SET_CAR_WATERTIGHT:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tif (pVehicle->IsBike()) {\n\t\t\tCBike* pBike = (CBike*)pVehicle;\n\t\t\tpBike->bWaterTight = ScriptParams[1] != 0;\n\t\t}\n\t\telse if (pVehicle->IsCar()) {\n\t\t\tCAutomobile* pCar = (CAutomobile*)pVehicle;\n\t\t\tpCar->bWaterTight = ScriptParams[1] != 0;\n\t\t}\n\t\treturn 0;\n\t}\n\tcase COMMAND_ADD_MOVING_PARTICLE_EFFECT:\n\t{\n\t\tCollectParameters(&m_nIp, 12);\n\t\tCVector pos = *(CVector*)&ScriptParams[1];\n\t\tif (pos.z <= MAP_Z_LOW_LIMIT)\n\t\t\tpos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);\n\t\tfloat size = Max(0.0f, *(float*)&ScriptParams[7]);\n\t\teParticleObjectType type = (eParticleObjectType)ScriptParams[0];\n\t\tRwRGBA color;\n\t\tif (type == POBJECT_SMOKE_TRAIL){\n\t\t\tcolor.alpha = -1;\n\t\t\tcolor.red = ScriptParams[8];\n\t\t\tcolor.green = ScriptParams[9];\n\t\t\tcolor.blue = ScriptParams[10];\n\t\t}else{\n\t\t\tcolor.alpha = color.red = color.blue = color.green = 0;\n\t\t}\n\t\tCVector target = *(CVector*)&ScriptParams[4];\n\t\tCParticleObject::AddObject(type, pos, target, size, ScriptParams[11], color, 1);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_CHAR_CANT_BE_DRAGGED_OUT:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tpPed->bDontDragMeOutCar = ScriptParams[1] != 0;\n\t\treturn 0;\n\t}\n\tcase COMMAND_TURN_CAR_TO_FACE_COORD:\n\t{\n\t\tCollectParameters(&m_nIp, 3);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tconst CVector& pos = pVehicle->GetPosition();\n\t\tfloat heading = CGeneral::GetATanOfXY(pos.x - *(float*)&ScriptParams[1], pos.y - *(float*)&ScriptParams[2]) + HALFPI;\n\t\tif (heading > TWOPI)\n\t\t\theading -= TWOPI;\n\t\tpVehicle->SetHeading(heading);\n\t\treturn 0;\n\t}\n\t/*\n\tcase COMMAND_IS_CRANE_LIFTING_CAR:\n\t{\n\t\tCollectParameters(&m_nIp, 3);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[2]);\n\t\tUpdateCompareFlag(CCranes::IsThisCarPickedUp(*(float*)&ScriptParams[0], *(float*)&ScriptParams[1], pVehicle));\n\t\treturn 0;\n\t}\n\t*/\n\tcase COMMAND_DRAW_SPHERE:\n\t{\n\t\tCollectParameters(&m_nIp, 4);\n\t\tCVector pos = *(CVector*)&ScriptParams[0];\n\t\tif (pos.z <= MAP_Z_LOW_LIMIT)\n\t\t\tpos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);\n\t\tC3dMarkers::PlaceMarkerSet((uintptr)this + m_nIp, MARKERTYPE_CYLINDER, pos, *(float*)&ScriptParams[3],\n\t\t\tSPHERE_MARKER_R, SPHERE_MARKER_G, SPHERE_MARKER_B, SPHERE_MARKER_A,\n\t\t\tSPHERE_MARKER_PULSE_PERIOD, SPHERE_MARKER_PULSE_FRACTION, 0);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_CAR_STATUS:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tpVehicle->SetStatus(ScriptParams[1]);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_CHAR_MALE:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tUpdateCompareFlag(pPed->m_nPedType != PEDTYPE_CIVFEMALE && pPed->m_nPedType != PEDTYPE_PROSTITUTE);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SCRIPT_NAME:\n\t{\n\t\tstrncpy(str, (char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT);\n\t\tfor (int i = 0; i < KEY_LENGTH_IN_SCRIPT; i++)\n\t\t\tstr[i] = tolower(str[i]);\n\t\tm_nIp += KEY_LENGTH_IN_SCRIPT;\n\t\tstrncpy(m_abScriptName, str, KEY_LENGTH_IN_SCRIPT);\n\t\treturn 0;\n\t}\n\t/*\n\tcase COMMAND_CHANGE_GARAGE_TYPE_WITH_CAR_MODEL:\n\t{\n\t\tCollectParameters(&m_nIp, 3);\n\t\tCGarages::ChangeGarageType(ScriptParams[0], ScriptParams[1], ScriptParams[2]);\n\t\treturn 0;\n\t}\n\tcase COMMAND_FIND_DRUG_PLANE_COORDINATES:\n\t\t*(CVector*)&ScriptParams[0] = CPlane::FindDrugPlaneCoordinates();\n\t\tStoreParameters(&m_nIp, 3);\n\t\treturn 0;\n\t*/\n\tcase COMMAND_SAVE_INT_TO_DEBUG_FILE:\n\t\t// TODO: implement something here\n\t\tCollectParameters(&m_nIp, 1);\n\t\treturn 0;\n\tcase COMMAND_SAVE_FLOAT_TO_DEBUG_FILE:\n\t\tCollectParameters(&m_nIp, 1);\n\t\treturn 0;\n\tcase COMMAND_SAVE_NEWLINE_TO_DEBUG_FILE:\n\t\treturn 0;\n\tcase COMMAND_POLICE_RADIO_MESSAGE:\n\t\tCollectParameters(&m_nIp, 3);\n\t\tDMAudio.PlaySuspectLastSeen(*(float*)&ScriptParams[0], *(float*)&ScriptParams[1], *(float*)&ScriptParams[2]);\n\t\treturn 0;\n\tcase COMMAND_SET_CAR_STRONG:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tpVehicle->bTakeLessDamage = ScriptParams[1] != 0;\n\t\treturn 0;\n\t}\n\tcase COMMAND_REMOVE_ROUTE:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCRouteNode::RemoveRoute(ScriptParams[0]);\n\t\treturn 0;\n\tcase COMMAND_SWITCH_RUBBISH:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCRubbish::SetVisibility(ScriptParams[0] != 0);\n\t\treturn 0;\n\tcase COMMAND_REMOVE_PARTICLE_EFFECTS_IN_AREA:\n\t{\n\t\tCollectParameters(&m_nIp, 6);\n\t\tfloat x1 = *(float*)&ScriptParams[0];\n\t\tfloat y1 = *(float*)&ScriptParams[1];\n\t\tfloat z1 = *(float*)&ScriptParams[2];\n\t\tfloat x2 = *(float*)&ScriptParams[3];\n\t\tfloat y2 = *(float*)&ScriptParams[4];\n\t\tfloat z2 = *(float*)&ScriptParams[5];\n\t\tCParticleObject* tmp = CParticleObject::pCloseListHead;\n\t\twhile (tmp) {\n\t\t\tCParticleObject* next = tmp->m_pNext;\n\t\t\tif (tmp->IsWithinArea(x1, y1, z1, x2, y2, z2))\n\t\t\t\ttmp->RemoveObject();\n\t\t\ttmp = next;\n\t\t}\n\t\ttmp = CParticleObject::pFarListHead;\n\t\twhile (tmp) {\n\t\t\tCParticleObject* next = tmp->m_pNext;\n\t\t\tif (tmp->IsWithinArea(x1, y1, z1, x2, y2, z2))\n\t\t\t\ttmp->RemoveObject();\n\t\t\ttmp = next;\n\t\t}\n\t\treturn 0;\n\t}\n\tcase COMMAND_SWITCH_STREAMING:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCStreaming::ms_disableStreaming = ScriptParams[0] == 0;\n\t\treturn 0;\n\tcase COMMAND_IS_GARAGE_OPEN:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tUpdateCompareFlag(CGarages::IsGarageOpen(ScriptParams[0]));\n\t\treturn 0;\n\tcase COMMAND_IS_GARAGE_CLOSED:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tUpdateCompareFlag(CGarages::IsGarageClosed(ScriptParams[0]));\n\t\treturn 0;\n\t/*\n\tcase COMMAND_START_CATALINA_HELI:\n\t\tCHeli::StartCatalinaFlyBy();\n\t\treturn 0;\n\tcase COMMAND_CATALINA_HELI_TAKE_OFF:\n\t\tCHeli::CatalinaTakeOff();\n\t\treturn 0;\n\tcase COMMAND_REMOVE_CATALINA_HELI:\n\t\tCHeli::RemoveCatalinaHeli();\n\t\treturn 0;\n\tcase COMMAND_HAS_CATALINA_HELI_BEEN_SHOT_DOWN:\n\t\tUpdateCompareFlag(CHeli::HasCatalinaBeenShotDown());\n\t\treturn 0;\n\t*/\n\tcase COMMAND_SWAP_NEAREST_BUILDING_MODEL:\n\t{\n\t\tCollectParameters(&m_nIp, 6);\n\t\tCVector pos = *(CVector*)&ScriptParams[0];\n\t\tif (pos.z <= MAP_Z_LOW_LIMIT)\n\t\t\tpos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);\n\t\tfloat radius = *(float*)&ScriptParams[3];\n\t\tint mi1 = ScriptParams[4] >= 0 ? ScriptParams[4] : CTheScripts::UsedObjectArray[-ScriptParams[4]].index;\n\t\tint mi2 = ScriptParams[5] >= 0 ? ScriptParams[5] : CTheScripts::UsedObjectArray[-ScriptParams[5]].index;\n\t\tint16 total;\n\t\tCEntity* apEntities[16];\n\t\tCWorld::FindObjectsOfTypeInRange(mi1, pos, radius, true, &total, 16, apEntities, true, false, false, false, false);\n\t\tif (total == 0)\n\t\t\tCWorld::FindObjectsOfTypeInRangeSectorList(mi1, CWorld::GetBigBuildingList(LEVEL_GENERIC), pos, radius, true, &total, 16, apEntities);\n\t\tif (total == 0)\n\t\t\tCWorld::FindObjectsOfTypeInRangeSectorList(mi1, CWorld::GetBigBuildingList(CTheZones::GetLevelFromPosition(&pos)), pos, radius, true, &total, 16, apEntities);\n\t\tCEntity* pClosestEntity = nil;\n\t\tfloat min_dist = 2.0f * radius;\n\t\tfor (int i = 0; i < total; i++) {\n\t\t\tfloat dist = (apEntities[i]->GetPosition() - pos).Magnitude();\n\t\t\tif (dist < min_dist) {\n\t\t\t\tmin_dist = dist;\n\t\t\t\tpClosestEntity = apEntities[i];\n\t\t\t}\n\t\t}\n\t\tif (!pClosestEntity) {\n\t\t\tprintf(\"Failed to find building\\n\");\n\t\t\treturn 0;\n\t\t}\n\t\tCBuilding* pReplacedBuilding = ((CBuilding*)pClosestEntity);\n\t\tpReplacedBuilding->ReplaceWithNewModel(mi2);\n\t\tCTheScripts::AddToBuildingSwapArray(pReplacedBuilding, mi1, mi2);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SWITCH_WORLD_PROCESSING:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCWorld::bProcessCutsceneOnly = ScriptParams[0] == 0;\n\t\treturn 0;\n\tcase COMMAND_REMOVE_ALL_PLAYER_WEAPONS:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;\n\t\tscript_assert(pPed);\n\t\tpPed->ClearWeapons();\n\t\treturn 0;\n\t}\n\t/*\n\tcase COMMAND_GRAB_CATALINA_HELI:\n\t{\n\t\tCHeli* pHeli = CHeli::FindPointerToCatalinasHeli();\n\t\tScriptParams[0] = pHeli ? CPools::GetVehiclePool()->GetIndex(pHeli) : -1;\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\t*/\n\tcase COMMAND_CLEAR_AREA_OF_CARS:\n\t{\n\t\tCollectParameters(&m_nIp, 6);\n\t\tfloat infX = *(float*)&ScriptParams[0];\n\t\tfloat infY = *(float*)&ScriptParams[1];\n\t\tfloat infZ = *(float*)&ScriptParams[2];\n\t\tfloat supX = *(float*)&ScriptParams[3];\n\t\tfloat supY = *(float*)&ScriptParams[4];\n\t\tfloat supZ = *(float*)&ScriptParams[5];\n\t\tif (infX > supX) {\n\t\t\tinfX = *(float*)&ScriptParams[3];\n\t\t\tsupX = *(float*)&ScriptParams[0];\n\t\t}\n\t\tif (infY > supY) {\n\t\t\tinfY = *(float*)&ScriptParams[4];\n\t\t\tsupY = *(float*)&ScriptParams[1];\n\t\t}\n\t\tif (infZ > supZ) {\n\t\t\tinfZ = *(float*)&ScriptParams[5];\n\t\t\tsupZ = *(float*)&ScriptParams[2];\n\t\t}\n\t\tCWorld::ClearCarsFromArea(infX, infY, infZ, supX, supY, supZ);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_ROTATING_GARAGE_DOOR:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCGarages::SetGarageDoorToRotate(ScriptParams[0]);\n\t\treturn 0;\n\tcase COMMAND_ADD_SPHERE:\n\t{\n\t\tCollectParameters(&m_nIp, 4);\n\t\tCVector pos = *(CVector*)&ScriptParams[0];\n\t\tif (pos.z <= MAP_Z_LOW_LIMIT)\n\t\t\tpos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);\n\t\tfloat radius = *(float*)&ScriptParams[3];\n\t\tCTheScripts::GetActualScriptSphereIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));\n\t\tScriptParams[0] = CTheScripts::AddScriptSphere((uintptr)this + m_nIp, pos, radius);\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\tcase COMMAND_REMOVE_SPHERE:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCTheScripts::RemoveScriptSphere(ScriptParams[0]);\n\t\treturn 0;\n\t/*\n\tcase COMMAND_CATALINA_HELI_FLY_AWAY:\n\t\tCHeli::MakeCatalinaHeliFlyAway();\n\t\treturn 0;\n\t*/\n\tcase COMMAND_SET_EVERYONE_IGNORE_PLAYER:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;\n\t\tscript_assert(pPed);\n\t\tif (ScriptParams[1]) {\n\t\t\tpPed->m_pWanted->m_bIgnoredByEveryone = true;\n\t\t\tCWorld::StopAllLawEnforcersInTheirTracks();\n\t\t}\n\t\telse {\n\t\t\tpPed->m_pWanted->m_bIgnoredByEveryone = false;\n\t\t}\n\t\treturn 0;\n\t}\n\tcase COMMAND_STORE_CAR_CHAR_IS_IN_NO_SAVE:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tCVehicle* pVehicle = pPed->bInVehicle ? pPed->m_pMyVehicle : nil;\n\t\tScriptParams[0] = CPools::GetVehiclePool()->GetIndex(pVehicle);\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\tcase COMMAND_STORE_CAR_PLAYER_IS_IN_NO_SAVE:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;\n\t\tscript_assert(pPed);\n\t\tCVehicle* pVehicle = pPed->bInVehicle ? pPed->m_pMyVehicle : nil;\n\t\tScriptParams[0] = CPools::GetVehiclePool()->GetIndex(pVehicle);\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\t/*\n\tcase COMMAND_IS_PHONE_DISPLAYING_MESSAGE:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tUpdateCompareFlag(gPhoneInfo.IsMessageBeingDisplayed(ScriptParams[0]));\n\t\treturn 0;\n\t*/\n\tcase COMMAND_DISPLAY_ONSCREEN_TIMER_WITH_STRING:\n\t{\n\t\tscript_assert(CTheScripts::ScriptSpace[m_nIp++] == ARGUMENT_GLOBALVAR);\n\t\tuint16 var = CTheScripts::Read2BytesFromScript(&m_nIp);\n\t\tCollectParameters(&m_nIp, 1);\n\t\twchar* text = TheText.Get((char*)&CTheScripts::ScriptSpace[m_nIp]); // ???\n\t\tstrncpy(onscreen_str, (char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT);\n\t\tm_nIp += KEY_LENGTH_IN_SCRIPT;\n\t\tCUserDisplay::OnscnTimer.AddClock(var, onscreen_str, ScriptParams[0] != 0);\n\t\treturn 0;\n\t}\n\tcase COMMAND_DISPLAY_ONSCREEN_COUNTER_WITH_STRING:\n\t{\n\t\tscript_assert(CTheScripts::ScriptSpace[m_nIp++] == ARGUMENT_GLOBALVAR);\n\t\tuint16 var = CTheScripts::Read2BytesFromScript(&m_nIp);\n\t\tCollectParameters(&m_nIp, 1);\n\t\twchar* text = TheText.Get((char*)&CTheScripts::ScriptSpace[m_nIp]); // ???\n\t\tstrncpy(onscreen_str, (char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT);\n\t\tm_nIp += KEY_LENGTH_IN_SCRIPT;\n\t\tCUserDisplay::OnscnTimer.AddCounter(var, ScriptParams[0], onscreen_str, 0);\n\t\treturn 0;\n\t}\n\tcase COMMAND_CREATE_RANDOM_CAR_FOR_CAR_PARK:\n\t{\n\t\tCollectParameters(&m_nIp, 4);\n\t\tif (CCarCtrl::NumRandomCars >= 30)\n\t\t\treturn 0;\n\t\tint attempts;\n\t\tint model = -1;\n\t\tint index = CGeneral::GetRandomNumberInRange(0, MAXVEHICLESLOADED);\n\t\tfor (attempts = 0; attempts < MAXVEHICLESLOADED; attempts++) {\n\t\t\tif (model != -1)\n\t\t\t\tbreak;\n\t\t\tmodel = CStreaming::ms_vehiclesLoaded[index];\n\t\t\tif (model == -1)\n\t\t\t\tcontinue;\n\t\t\tif (CModelInfo::IsCarModel(model) || CModelInfo::IsBikeModel(model)) {\n\t\t\t\tswitch (model) {\n\t\t\t\tcase MI_LANDSTAL:\n\t\t\t\tcase MI_LINERUN:\n\t\t\t\tcase MI_RIO:\n\t\t\t\tcase MI_FIRETRUCK:\n\t\t\t\tcase MI_TRASH:\n\t\t\t\tcase MI_STRETCH:\n\t\t\t\tcase MI_VOODOO:\n\t\t\t\tcase MI_MULE:\n\t\t\t\tcase MI_AMBULAN:\n\t\t\t\tcase MI_FBICAR:\n\t\t\t\tcase MI_MRWHOOP:\n\t\t\t\tcase MI_BFINJECT:\n\t\t\t\tcase MI_HUNTER:\n\t\t\t\tcase MI_POLICE:\n\t\t\t\tcase MI_ENFORCER:\n\t\t\t\tcase MI_SECURICA:\n\t\t\t\tcase MI_PREDATOR:\n\t\t\t\tcase MI_BUS:\n\t\t\t\tcase MI_RHINO:\n\t\t\t\tcase MI_BARRACKS:\n\t\t\t\tcase MI_CUBAN:\n\t\t\t\tcase MI_CHOPPER:\n\t\t\t\tcase MI_ANGEL:\n\t\t\t\tcase MI_COACH:\n\t\t\t\tcase MI_RCBANDIT:\n\t\t\t\tcase MI_ROMERO:\n\t\t\t\tcase MI_PACKER:\n\t\t\t\tcase MI_SENTXS:\n\t\t\t\tcase MI_SQUALO:\n\t\t\t\tcase MI_SEASPAR:\n\t\t\t\tcase MI_PIZZABOY:\n\t\t\t\tcase MI_GANGBUR:\n\t\t\t\tcase MI_AIRTRAIN:\n\t\t\t\tcase MI_DEADDODO:\n\t\t\t\tcase MI_SPEEDER:\n\t\t\t\tcase MI_REEFER:\n\t\t\t\tcase MI_TROPIC:\n\t\t\t\tcase MI_FLATBED:\n\t\t\t\tcase MI_YANKEE:\n\t\t\t\tcase MI_CADDY:\n\t\t\t\tcase MI_ZEBRA:\n\t\t\t\tcase MI_TOPFUN:\n\t\t\t\tcase MI_SKIMMER:\n\t\t\t\tcase MI_RCBARON:\n\t\t\t\tcase MI_RCRAIDER:\n\t\t\t\tcase MI_SPARROW:\n\t\t\t\tcase MI_PATRIOT:\n\t\t\t\tcase MI_LOVEFIST:\n\t\t\t\tcase MI_COASTG:\n\t\t\t\tcase MI_DINGHY:\n\t\t\t\tcase MI_HERMES:\n\t\t\t\tcase MI_SABRETUR:\n\t\t\t\tcase MI_PHEONIX:\n\t\t\t\tcase MI_WALTON:\n\t\t\t\tcase MI_COMET:\n\t\t\t\tcase MI_DELUXO:\n\t\t\t\tcase MI_BURRITO:\n\t\t\t\tcase MI_SPAND:\n\t\t\t\tcase MI_MARQUIS:\n\t\t\t\tcase MI_BAGGAGE:\n\t\t\t\tcase MI_KAUFMAN:\n\t\t\t\tcase MI_MAVERICK:\n\t\t\t\tcase MI_VCNMAV:\n\t\t\t\tcase MI_RANCHER:\n\t\t\t\tcase MI_FBIRANCH:\n\t\t\t\tcase MI_JETMAX:\n\t\t\t\tcase MI_HOTRING:\n\t\t\t\tcase MI_SANDKING:\n\t\t\t\tcase MI_BLISTAC:\n\t\t\t\tcase MI_POLMAV:\n\t\t\t\tcase MI_BOXVILLE:\n\t\t\t\tcase MI_BENSON:\n\t\t\t\tcase MI_MESA:\n\t\t\t\tcase MI_RCGOBLIN:\n\t\t\t\tcase MI_HOTRINA:\n\t\t\t\tcase MI_HOTRINB:\n\t\t\t\tcase MI_BLOODRA:\n\t\t\t\tcase MI_BLOODRB:\n\t\t\t\tcase MI_VICECHEE:\n\t\t\t\t\tmodel = -1;\n\t\t\t\t\tbreak;\n\t\t\t\tcase MI_IDAHO:\n\t\t\t\tcase MI_STINGER:\n\t\t\t\tcase MI_PEREN:\n\t\t\t\tcase MI_SENTINEL:\n\t\t\t\tcase MI_MANANA:\n\t\t\t\tcase MI_INFERNUS:\n\t\t\t\tcase MI_PONY:\n\t\t\t\tcase MI_CHEETAH:\n\t\t\t\tcase MI_MOONBEAM:\n\t\t\t\tcase MI_ESPERANT:\n\t\t\t\tcase MI_TAXI:\n\t\t\t\tcase MI_WASHING:\n\t\t\t\tcase MI_BOBCAT:\n\t\t\t\tcase MI_BANSHEE:\n\t\t\t\tcase MI_CABBIE:\n\t\t\t\tcase MI_STALLION:\n\t\t\t\tcase MI_RUMPO:\n\t\t\t\tcase MI_ADMIRAL:\n\t\t\t\tcase MI_PCJ600:\n\t\t\t\tcase MI_FAGGIO:\n\t\t\t\tcase MI_FREEWAY:\n\t\t\t\tcase MI_GLENDALE:\n\t\t\t\tcase MI_OCEANIC:\n\t\t\t\tcase MI_SANCHEZ:\n\t\t\t\tcase MI_SABRE:\n\t\t\t\tcase MI_REGINA:\n\t\t\t\tcase MI_VIRGO:\n\t\t\t\tcase MI_GREENWOO:\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tprintf(\"CREATE_RANDOM_CAR_FOR_CAR_PARK - Unknown car model %d\\n\", CStreaming::ms_vehiclesLoaded[index]);\n\t\t\t\t\tmodel = -1;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t\tmodel = -1;\n\t\t\tif (++index >= 50)\n\t\t\t\tindex = 0;\n\t\t}\n\t\tif (model == -1)\n\t\t\treturn 0;\n\t\tCVehicle* car;\n\t\tif (CModelInfo::IsBikeModel(model)) {\n\t\t\tcar = new CBike(model, RANDOM_VEHICLE);\n\t\t\t((CBike*)(car))->bIsStanding = true;\n\t\t}\n\t\telse\n\t\t\tcar = new CAutomobile(model, RANDOM_VEHICLE);\n\t\tCVector pos = *(CVector*)&ScriptParams[0];\n\t\tpos.z += car->GetDistanceFromCentreOfMassToBaseOfModel();\n\t\tcar->SetPosition(pos);\n\t\tcar->SetHeading(DEGTORAD(*(float*)&ScriptParams[3]));\n\t\tCTheScripts::ClearSpaceForMissionEntity(pos, car);\n\t\tcar->SetStatus(STATUS_ABANDONED);\n\t\tcar->bIsLocked = false;\n\t\tcar->bIsCarParkVehicle = true;\n\t\tCCarCtrl::JoinCarWithRoadSystem(car);\n\t\tcar->AutoPilot.m_nCarMission = MISSION_NONE;\n\t\tcar->AutoPilot.m_nTempAction = TEMPACT_NONE;\n\t\tcar->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_STOP_FOR_CARS;\n\t\tcar->AutoPilot.m_nCruiseSpeed = car->AutoPilot.m_fMaxTrafficSpeed = 9.0f;\n\t\tcar->AutoPilot.m_nCurrentLane = car->AutoPilot.m_nNextLane = 0;\n\t\tcar->bEngineOn = false;\n\t\tcar->m_nZoneLevel = CTheZones::GetLevelFromPosition(&pos);\n\t\tCWorld::Add(car);\n\t\treturn 0;\n\t}\n\t/*\n\tcase COMMAND_IS_COLLISION_IN_MEMORY:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tUpdateCompareFlag(CCollision::ms_collisionInMemory == ScriptParams[0]);\n\t\treturn 0;\n\t*/\n\tcase COMMAND_SET_WANTED_MULTIPLIER:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tFindPlayerPed()->m_pWanted->m_fCrimeSensitivity = *(float*)&ScriptParams[0];\n\t\treturn 0;\n\tcase COMMAND_SET_CAMERA_IN_FRONT_OF_PLAYER:\n\t\tTheCamera.SetCameraDirectlyInFrontForFollowPed_CamOnAString();\n\t\treturn 0;\n\t/*\n\tcase COMMAND_IS_CAR_VISIBLY_DAMAGED:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tUpdateCompareFlag(pVehicle->bIsDamaged);\n\t\treturn 0;\n\t}\n\t*/\n\tcase COMMAND_DOES_OBJECT_EXIST:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tUpdateCompareFlag(CPools::GetObjectPool()->GetAt(ScriptParams[0]));\n\t\treturn 0;\n\tcase COMMAND_LOAD_SCENE:\n\t{\n\t\tCollectParameters(&m_nIp, 3);\n\t\tCVector pos = *(CVector*)&ScriptParams[0];\n#ifdef FIX_BUGS\n\t\tCTimer::Suspend();\n#else\n\t\tCTimer::Stop();\n#endif\n\t\tCStreaming::LoadScene(pos);\n#ifdef FIX_BUGS\n\t\tCTimer::Suspend();\n#else\n\t\tCTimer::Update();\n#endif\n\t\treturn 0;\n\t}\n\tcase COMMAND_ADD_STUCK_CAR_CHECK:\n\t{\n\t\tCollectParameters(&m_nIp, 3);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tCTheScripts::StuckCars.AddCarToCheck(ScriptParams[0], *(float*)&ScriptParams[1], ScriptParams[2]);\n\t\treturn 0;\n\t}\n\tcase COMMAND_REMOVE_STUCK_CAR_CHECK:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCTheScripts::StuckCars.RemoveCarFromCheck(ScriptParams[0]);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_CAR_STUCK:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tUpdateCompareFlag(CTheScripts::StuckCars.HasCarBeenStuckForAWhile(ScriptParams[0]));\n\t\treturn 0;\n\tcase COMMAND_LOAD_MISSION_AUDIO:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tstrncpy(str, (char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT);\n\t\tfor (int i = 0; i < KEY_LENGTH_IN_SCRIPT; i++)\n\t\t\tstr[i] = tolower(str[i]);\n\t\tm_nIp += KEY_LENGTH_IN_SCRIPT;\n\t\tDMAudio.PreloadMissionAudio(ScriptParams[0] - 1, str);\n\t\treturn 0;\n\t}\n\tcase COMMAND_HAS_MISSION_AUDIO_LOADED:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tUpdateCompareFlag(DMAudio.GetMissionAudioLoadingStatus(ScriptParams[0] - 1) == 1);\n\t\treturn 0;\n\t}\n\tcase COMMAND_PLAY_MISSION_AUDIO:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tDMAudio.PlayLoadedMissionAudio(ScriptParams[0] - 1);\n\t\treturn 0;\n\tcase COMMAND_HAS_MISSION_AUDIO_FINISHED:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tUpdateCompareFlag(DMAudio.IsMissionAudioSampleFinished(ScriptParams[0] - 1));\n\t\treturn 0;\n\t}\n\tcase COMMAND_GET_CLOSEST_CAR_NODE_WITH_HEADING:\n\t{\n\t\tCollectParameters(&m_nIp, 3);\n\t\tCVector pos = *(CVector*)&ScriptParams[0];\n\t\tif (pos.z <= MAP_Z_LOW_LIMIT)\n\t\t\tpos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);\n\t\tint node = ThePaths.FindNodeClosestToCoors(pos, 0, 999999.9f, true, true);\n\t\t*(CVector*)&ScriptParams[0] = ThePaths.FindNodeCoorsForScript(node);\n\t\t*(float*)&ScriptParams[3] = ThePaths.FindNodeOrientationForCarPlacement(node);\n\t\tStoreParameters(&m_nIp, 4);\n\t\treturn 0;\n\t}\n\tcase COMMAND_HAS_IMPORT_GARAGE_SLOT_BEEN_FILLED:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tUpdateCompareFlag(CGarages::HasImportExportGarageCollectedThisCar(ScriptParams[0], ScriptParams[1] - 1));\n\t\treturn 0;\n\t}\n\tcase COMMAND_CLEAR_THIS_PRINT:\n\t{\n\t\twchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\tCMessages::ClearThisPrint(text);\n\t\treturn 0;\n\t}\n\tcase COMMAND_CLEAR_THIS_BIG_PRINT:\n\t{\n\t\twchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\tCMessages::ClearThisBigPrint(text);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_MISSION_AUDIO_POSITION:\n\t{\n\t\tCollectParameters(&m_nIp, 4);\n\t\tCVector pos = *(CVector*)&ScriptParams[1];\n\t\tDMAudio.SetMissionAudioLocation(ScriptParams[0] - 1, pos.x, pos.y, pos.z);\n\t\treturn 0;\n\t}\n\tcase COMMAND_ACTIVATE_SAVE_MENU:\n\t{\n\t\tCStats::SafeHouseVisits++;\n\t\tFrontEndMenuManager.m_bActivateSaveMenu = true;\n\t\tFindPlayerPed()->SetMoveSpeed(0.0f, 0.0f, 0.0f);\n\t\tFindPlayerPed()->SetTurnSpeed(0.0f, 0.0f, 0.0f);\n\t\treturn 0;\n\t}\n\tcase COMMAND_HAS_SAVE_GAME_FINISHED:\n\t\tUpdateCompareFlag(!FrontEndMenuManager.m_bMenuActive && !FrontEndMenuManager.m_bActivateSaveMenu);\n\t\treturn 0;\n\tcase COMMAND_NO_SPECIAL_CAMERA_FOR_THIS_GARAGE:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCGarages::SetLeaveCameraForThisGarage(ScriptParams[0]);\n\t\treturn 0;\n\t/*\n\tcase COMMAND_ADD_BLIP_FOR_PICKUP_OLD:\n\t{\n\t\tCollectParameters(&m_nIp, 3);\n\t\tCObject* pObject = CPickups::aPickUps[CPickups::GetActualPickupIndex(ScriptParams[0])].m_pObject;\n\t\tCRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));\n\t\tScriptParams[0] = CRadar::SetEntityBlip(BLIP_OBJECT, CPools::GetObjectPool()->GetIndex(pObject), ScriptParams[1], (eBlipDisplay)ScriptParams[2]);\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\t*/\n\tcase COMMAND_ADD_BLIP_FOR_PICKUP:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCObject* pObject = CPickups::aPickUps[CPickups::GetActualPickupIndex(ScriptParams[0])].m_pObject;\n\t\tCRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));\n\t\tint handle = CRadar::SetEntityBlip(BLIP_OBJECT, CPools::GetObjectPool()->GetIndex(pObject), 6, BLIP_DISPLAY_BOTH);\n\t\tCRadar::ChangeBlipScale(handle, 3);\n\t\tScriptParams[0] = handle;\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\t/*\n\tcase COMMAND_ADD_SPRITE_BLIP_FOR_PICKUP:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCObject* pObject = CPickups::aPickUps[CPickups::GetActualPickupIndex(ScriptParams[0])].m_pObject;\n\t\tCRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));\n\t\tint handle = CRadar::SetEntityBlip(BLIP_OBJECT, CPools::GetObjectPool()->GetIndex(pObject), 6, BLIP_DISPLAY_BOTH);\n\t\tCRadar::SetBlipSprite(handle, ScriptParams[1]);\n\t\tScriptParams[0] = handle;\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\t*/\n\tcase COMMAND_SET_PED_DENSITY_MULTIPLIER:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPopulation::PedDensityMultiplier = *(float*)&ScriptParams[0];\n\t\treturn 0;\n\tcase COMMAND_FORCE_RANDOM_PED_TYPE:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPopulation::m_AllRandomPedsThisType = ScriptParams[0];\n\t\treturn 0;\n\t/*\n\tcase COMMAND_SET_TEXT_DRAW_BEFORE_FADE:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_bTextBeforeFade = ScriptParams[0] != 0;\n\t\treturn 0;\n\t*/\n\tcase COMMAND_GET_COLLECTABLE1S_COLLECTED:\n\t\tScriptParams[0] = CWorld::Players[CWorld::PlayerInFocus].m_nCollectedPackages;\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\tcase COMMAND_SET_CHAR_OBJ_LEAVE_ANY_CAR:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tpPed->bScriptObjectiveCompleted = false;\n\t\tpPed->SetObjective(OBJECTIVE_LEAVE_CAR, pPed->m_pMyVehicle);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_SPRITES_DRAW_BEFORE_FADE:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCTheScripts::IntroRectangles[CTheScripts::NumberOfIntroRectanglesThisFrame].m_bBeforeFade = ScriptParams[0] != 0;\n\t\treturn 0;\n\tcase COMMAND_SET_TEXT_RIGHT_JUSTIFY:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_bRightJustify = ScriptParams[0] != 0;\n\t\treturn 0;\n\tcase COMMAND_PRINT_HELP:\n\t{\n\t\tif (CCamera::m_bUseMouse3rdPerson && (\n\t\t\tstrcmp((char*)&CTheScripts::ScriptSpace[m_nIp], \"HELP15\") == 0 ||\n\t\t\tstrcmp((char*)&CTheScripts::ScriptSpace[m_nIp], \"GUN_2A\") == 0 ||\n\t\t\tstrcmp((char*)&CTheScripts::ScriptSpace[m_nIp], \"GUN_2C\") == 0 ||\n\t\t\tstrcmp((char*)&CTheScripts::ScriptSpace[m_nIp], \"GUN_2D\") == 0)) {\n\t\t\tm_nIp += KEY_LENGTH_IN_SCRIPT;\n\t\t\treturn 0;\n\t\t}\n\t\twchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\tCHud::SetHelpMessage(text, false);\n\t\treturn 0;\n\t}\n\tcase COMMAND_CLEAR_HELP:\n\t\tCHud::SetHelpMessage(nil, false);\n\t\treturn 0;\n\tcase COMMAND_FLASH_HUD_OBJECT:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCHud::m_ItemToFlash = ScriptParams[0];\n\t\treturn 0;\n\tdefault:\n\t\tscript_assert(0);\n\t}\n\treturn -1;\n}\n\nint32 CTheScripts::GetNewUniqueScriptSphereIndex(int32 index)\n{\n\tif (ScriptSphereArray[index].m_Index >= UINT16_MAX - 1)\n\t\tScriptSphereArray[index].m_Index = 1;\n\telse\n\t\tScriptSphereArray[index].m_Index++;\n\treturn (uint16)index | ScriptSphereArray[index].m_Index << 16;\n}\n\nint32 CTheScripts::GetActualScriptSphereIndex(int32 index)\n{\n\tif (index == -1)\n\t\treturn -1;\n\tuint16 check = (uint32)index >> 16;\n\tuint16 array_idx = index & (0xFFFF);\n\tscript_assert(array_idx < ARRAY_SIZE(ScriptSphereArray));\n\tif (check != ScriptSphereArray[array_idx].m_Index)\n\t\treturn -1;\n\treturn array_idx;\n}\n\nvoid CTheScripts::DrawScriptSpheres()\n{\n\tfor (int i = 0; i < MAX_NUM_SCRIPT_SPHERES; i++) {\n\t\tif (ScriptSphereArray[i].m_bInUse)\n\t\t\tC3dMarkers::PlaceMarkerSet(ScriptSphereArray[i].m_Id, MARKERTYPE_CYLINDER, ScriptSphereArray[i].m_vecCenter, ScriptSphereArray[i].m_fRadius,\n\t\t\t\tSPHERE_MARKER_R, SPHERE_MARKER_G, SPHERE_MARKER_B, SPHERE_MARKER_A, SPHERE_MARKER_PULSE_PERIOD, SPHERE_MARKER_PULSE_FRACTION, 0);\n\t}\n}\n\nint32 CTheScripts::AddScriptSphere(int32 id, CVector pos, float radius)\n{\n\tint16 i = 0;\n\tfor (i = 0; i < MAX_NUM_SCRIPT_SPHERES; i++) {\n\t\tif (!ScriptSphereArray[i].m_bInUse)\n\t\t\tbreak;\n\t}\n#ifdef FIX_BUGS\n\tif (i == MAX_NUM_SCRIPT_SPHERES)\n\t\treturn -1;\n#endif\n\tScriptSphereArray[i].m_bInUse = true;\n\tScriptSphereArray[i].m_Id = id;\n\tScriptSphereArray[i].m_vecCenter = pos;\n\tScriptSphereArray[i].m_fRadius = radius;\n\treturn GetNewUniqueScriptSphereIndex(i);\n}\n\nvoid CTheScripts::RemoveScriptSphere(int32 index)\n{\n\tindex = GetActualScriptSphereIndex(index);\n\tif (index == -1)\n\t\treturn;\n\tScriptSphereArray[index].m_bInUse = false;\n\tScriptSphereArray[index].m_Id = 0;\n}\n\nvoid CTheScripts::AddToBuildingSwapArray(CBuilding* pBuilding, int32 old_model, int32 new_model)\n{\n\tint i = 0;\n\tbool found = false;\n\twhile (i < MAX_NUM_BUILDING_SWAPS && !found) {\n\t\tif (BuildingSwapArray[i].m_pBuilding == pBuilding)\n\t\t\tfound = true;\n\t\telse\n\t\t\ti++;\n\t}\n\tif (found) {\n\t\tif (BuildingSwapArray[i].m_nOldModel == new_model) {\n\t\t\tBuildingSwapArray[i].m_pBuilding = nil;\n\t\t\tBuildingSwapArray[i].m_nOldModel = BuildingSwapArray[i].m_nNewModel = -1;\n\t\t}\n\t\telse {\n\t\t\tBuildingSwapArray[i].m_nNewModel = new_model;\n\t\t}\n\t}\n\telse {\n\t\ti = 0;\n\t\twhile (i < MAX_NUM_BUILDING_SWAPS && !found) {\n\t\t\tif (BuildingSwapArray[i].m_pBuilding == nil)\n\t\t\t\tfound = true;\n\t\t\telse\n\t\t\t\ti++;\n\t\t}\n\t\tif (found) {\n\t\t\tBuildingSwapArray[i].m_pBuilding = pBuilding;\n\t\t\tBuildingSwapArray[i].m_nNewModel = new_model;\n\t\t\tBuildingSwapArray[i].m_nOldModel = old_model;\n\t\t}\n\t}\n}\n\nvoid CTheScripts::AddToInvisibilitySwapArray(CEntity* pEntity, bool remove)\n{\n\tint i = 0;\n\tbool found = false;\n\twhile (i < MAX_NUM_INVISIBILITY_SETTINGS && !found) {\n\t\tif (InvisibilitySettingArray[i] == pEntity)\n\t\t\tfound = true;\n\t\telse\n\t\t\ti++;\n\t}\n\tif (found) {\n\t\tif (remove)\n\t\t\tInvisibilitySettingArray[i] = nil;\n\t}\n\telse if (!remove) {\n\t\ti = 0;\n\t\twhile (i < MAX_NUM_INVISIBILITY_SETTINGS && !found) {\n\t\t\tif (InvisibilitySettingArray[i] == nil)\n\t\t\t\tfound = true;\n\t\t\telse\n\t\t\t\ti++;\n\t\t}\n\t\tif (found)\n\t\t\tInvisibilitySettingArray[i] = pEntity;\n\t}\n}\n\nvoid CTheScripts::UndoBuildingSwaps()\n{\n\tfor (int i = 0; i < MAX_NUM_BUILDING_SWAPS; i++) {\n\t\tif (BuildingSwapArray[i].m_pBuilding) {\n\t\t\tBuildingSwapArray[i].m_pBuilding->ReplaceWithNewModel(BuildingSwapArray[i].m_nOldModel);\n\t\t\tBuildingSwapArray[i].m_pBuilding = nil;\n\t\t\tBuildingSwapArray[i].m_nOldModel = BuildingSwapArray[i].m_nNewModel = -1;\n\t\t}\n\t}\n}\n\nvoid CTheScripts::UndoEntityInvisibilitySettings()\n{\n\tfor (int i = 0; i < MAX_NUM_INVISIBILITY_SETTINGS; i++) {\n\t\tif (InvisibilitySettingArray[i]) {\n\t\t\tInvisibilitySettingArray[i]->bIsVisible = true;\n\t\t\tInvisibilitySettingArray[i] = nil;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/control/Script5.cpp",
    "content": "#include \"common.h\"\n\n#include \"Script.h\"\n#include \"ScriptCommands.h\"\n\n#include \"CarCtrl.h\"\n#include \"BulletInfo.h\"\n#include \"General.h\"\n#include \"Lines.h\"\n#include \"Messages.h\"\n#include \"Pad.h\"\n#include \"Pools.h\"\n#include \"Population.h\"\n#include \"RpAnimBlend.h\"\n#include \"Shadows.h\"\n#include \"SpecialFX.h\"\n#include \"World.h\"\n#include \"main.h\"\n\nvoid CRunningScript::UpdateCompareFlag(bool flag)\n{\n\tif (m_bNotFlag)\n\t\tflag = !flag;\n\tif (m_nAndOrState == ANDOR_NONE) {\n\t\tm_bCondResult = flag;\n\t\treturn;\n\t}\n\tif (m_nAndOrState >= ANDS_1 && m_nAndOrState <= ANDS_8) {\n\t\tm_bCondResult &= flag;\n\t\tif (m_nAndOrState == ANDS_1) {\n\t\t\tm_nAndOrState = ANDOR_NONE;\n\t\t\treturn;\n\t\t}\n\t}\n\telse if (m_nAndOrState >= ORS_1 && m_nAndOrState <= ORS_8) {\n\t\tm_bCondResult |= flag;\n\t\tif (m_nAndOrState == ORS_1) {\n\t\t\tm_nAndOrState = ANDOR_NONE;\n\t\t\treturn;\n\t\t}\n\t}\n\telse {\n\t\treturn;\n\t}\n\tm_nAndOrState--;\n}\n\nvoid CRunningScript::LocatePlayerCommand(int32 command, uint32* pIp)\n{\n\tbool b3D, result, debug, decided = false;\n\tfloat X, Y, Z, dX, dY, dZ;\n\tswitch (command) {\n\tcase COMMAND_LOCATE_PLAYER_ANY_MEANS_3D:\n\tcase COMMAND_LOCATE_PLAYER_ON_FOOT_3D:\n\tcase COMMAND_LOCATE_PLAYER_IN_CAR_3D:\n\tcase COMMAND_LOCATE_STOPPED_PLAYER_ANY_MEANS_3D:\n\tcase COMMAND_LOCATE_STOPPED_PLAYER_ON_FOOT_3D:\n\tcase COMMAND_LOCATE_STOPPED_PLAYER_IN_CAR_3D:\n\t\tb3D = true;\n\t\tbreak;\n\tdefault:\n\t\tb3D = false;\n\t\tbreak;\n\t}\n\tCollectParameters(pIp, b3D ? 8 : 6);\n\tCPlayerInfo* pPlayerInfo = &CWorld::Players[ScriptParams[0]];\n\tswitch (command) {\n\tcase COMMAND_LOCATE_STOPPED_PLAYER_ANY_MEANS_2D:\n\tcase COMMAND_LOCATE_STOPPED_PLAYER_ANY_MEANS_3D:\n\tcase COMMAND_LOCATE_STOPPED_PLAYER_IN_CAR_2D:\n\tcase COMMAND_LOCATE_STOPPED_PLAYER_IN_CAR_3D:\n\tcase COMMAND_LOCATE_STOPPED_PLAYER_ON_FOOT_2D:\n\tcase COMMAND_LOCATE_STOPPED_PLAYER_ON_FOOT_3D:\n\t\tif (!CTheScripts::IsPlayerStopped(pPlayerInfo)) {\n\t\t\tresult = false;\n\t\t\tdecided = true;\n\t\t}\n\t\tbreak;\n\tdefault:\n\t\tbreak;\n\t}\n\tX = *(float*)&ScriptParams[1];\n\tY = *(float*)&ScriptParams[2];\n\tif (b3D) {\n\t\tZ = *(float*)&ScriptParams[3];\n\t\tdX = *(float*)&ScriptParams[4];\n\t\tdY = *(float*)&ScriptParams[5];\n\t\tdZ = *(float*)&ScriptParams[6];\n\t\tdebug = ScriptParams[7];\n\t} else {\n\t\tdX = *(float*)&ScriptParams[3];\n\t\tdY = *(float*)&ScriptParams[4];\n\t\tdebug = ScriptParams[5];\n\t}\n\tif (!decided) {\n\t\tCVector pos = pPlayerInfo->GetPos();\n\t\tresult = false;\n\t\tbool in_area;\n\t\tif (b3D) {\n\t\t\tin_area = X - dX <= pos.x &&\n\t\t\t\tX + dX >= pos.x &&\n\t\t\t\tY - dY <= pos.y &&\n\t\t\t\tY + dY >= pos.y &&\n\t\t\t\tZ - dZ <= pos.z &&\n\t\t\t\tZ + dZ >= pos.z;\n\t\t} else {\n\t\t\tin_area = X - dX <= pos.x &&\n\t\t\t\tX + dX >= pos.x &&\n\t\t\t\tY - dY <= pos.y &&\n\t\t\t\tY + dY >= pos.y;\n\t\t}\n\t\tif (in_area) {\n\t\t\tswitch (command) {\n\t\t\tcase COMMAND_LOCATE_PLAYER_ANY_MEANS_2D:\n\t\t\tcase COMMAND_LOCATE_PLAYER_ANY_MEANS_3D:\n\t\t\tcase COMMAND_LOCATE_STOPPED_PLAYER_ANY_MEANS_2D:\n\t\t\tcase COMMAND_LOCATE_STOPPED_PLAYER_ANY_MEANS_3D:\n\t\t\t\tresult = true;\n\t\t\t\tbreak;\n\t\t\tcase COMMAND_LOCATE_PLAYER_ON_FOOT_2D:\n\t\t\tcase COMMAND_LOCATE_PLAYER_ON_FOOT_3D:\n\t\t\tcase COMMAND_LOCATE_STOPPED_PLAYER_ON_FOOT_2D:\n\t\t\tcase COMMAND_LOCATE_STOPPED_PLAYER_ON_FOOT_3D:\n\t\t\t\tresult = !pPlayerInfo->m_pPed->bInVehicle;\n\t\t\t\tbreak;\n\t\t\tcase COMMAND_LOCATE_PLAYER_IN_CAR_2D:\n\t\t\tcase COMMAND_LOCATE_PLAYER_IN_CAR_3D:\n\t\t\tcase COMMAND_LOCATE_STOPPED_PLAYER_IN_CAR_2D:\n\t\t\tcase COMMAND_LOCATE_STOPPED_PLAYER_IN_CAR_3D:\n\t\t\t\tresult = pPlayerInfo->m_pPed->bInVehicle;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tscript_assert(false);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\tUpdateCompareFlag(result);\n\tif (debug)\n\t\tCTheScripts::HighlightImportantArea((uintptr)this + m_nIp, X - dX, Y - dY, X + dX, Y + dY, b3D ? Z : MAP_Z_LOW_LIMIT);\n\tif (CTheScripts::DbgFlag) {\n\t\tif (b3D)\n\t\t\tCTheScripts::DrawDebugCube(X - dX, Y - dY, Z - dZ, X + dX, Y + dY, Z + dZ);\n\t\telse\n\t\t\tCTheScripts::DrawDebugSquare(X - dX, Y - dY, X + dX, Y + dY);\n\t}\n}\n\nvoid CRunningScript::LocatePlayerCharCommand(int32 command, uint32* pIp)\n{\n\tbool b3D, result, debug;\n\tfloat X, Y, Z, dX, dY, dZ;\n\tswitch (command) {\n\tcase COMMAND_LOCATE_PLAYER_ANY_MEANS_CHAR_3D:\n\tcase COMMAND_LOCATE_PLAYER_ON_FOOT_CHAR_3D:\n\tcase COMMAND_LOCATE_PLAYER_IN_CAR_CHAR_3D:\n\t\tb3D = true;\n\t\tbreak;\n\tdefault:\n\t\tb3D = false;\n\t\tbreak;\n\t}\n\tCollectParameters(pIp, b3D ? 6 : 5);\n\tCPlayerInfo* pPlayerInfo = &CWorld::Players[ScriptParams[0]];\n\tCPed* pTarget = CPools::GetPedPool()->GetAt(ScriptParams[1]);\n\tscript_assert(pTarget);\n\tCVector pos = pPlayerInfo->GetPos();\n\tif (pTarget->bInVehicle) {\n\t\tX = pTarget->m_pMyVehicle->GetPosition().x;\n\t\tY = pTarget->m_pMyVehicle->GetPosition().y;\n\t\tZ = pTarget->m_pMyVehicle->GetPosition().z;\n\t} else {\n\t\tX = pTarget->GetPosition().x;\n\t\tY = pTarget->GetPosition().y;\n\t\tZ = pTarget->GetPosition().z;\n\t}\n\tdX = *(float*)&ScriptParams[2];\n\tdY = *(float*)&ScriptParams[3];\n\tif (b3D) {\n\t\tdZ = *(float*)&ScriptParams[4];\n\t\tdebug = ScriptParams[5];\n\t}\n\telse {\n\t\tdebug = ScriptParams[4];\n\t}\n\tresult = false;\n\tbool in_area;\n\tif (b3D) {\n\t\tin_area = X - dX <= pos.x &&\n\t\t\tX + dX >= pos.x &&\n\t\t\tY - dY <= pos.y &&\n\t\t\tY + dY >= pos.y &&\n\t\t\tZ - dZ <= pos.z &&\n\t\t\tZ + dZ >= pos.z;\n\t}\n\telse {\n\t\tin_area = X - dX <= pos.x &&\n\t\t\tX + dX >= pos.x &&\n\t\t\tY - dY <= pos.y &&\n\t\t\tY + dY >= pos.y;\n\t}\n\tif (in_area) {\n\t\tswitch (command) {\n\t\tcase COMMAND_LOCATE_PLAYER_ANY_MEANS_CHAR_2D:\n\t\tcase COMMAND_LOCATE_PLAYER_ANY_MEANS_CHAR_3D:\n\t\t\tresult = true;\n\t\t\tbreak;\n\t\tcase COMMAND_LOCATE_PLAYER_ON_FOOT_CHAR_2D:\n\t\tcase COMMAND_LOCATE_PLAYER_ON_FOOT_CHAR_3D:\n\t\t\tresult = !pPlayerInfo->m_pPed->bInVehicle;\n\t\t\tbreak;\n\t\tcase COMMAND_LOCATE_PLAYER_IN_CAR_CHAR_2D:\n\t\tcase COMMAND_LOCATE_PLAYER_IN_CAR_CHAR_3D:\n\t\t\tresult = pPlayerInfo->m_pPed->bInVehicle;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tscript_assert(false);\n\t\t\tbreak;\n\t\t}\n\t}\n\tUpdateCompareFlag(result);\n\tif (debug)\n#ifdef FIX_BUGS\n\t\tCTheScripts::HighlightImportantArea((uintptr)this + m_nIp, X - dX, Y - dY, X + dX, Y + dY, b3D ? Z : MAP_Z_LOW_LIMIT);\n#else\n\t\tCTheScripts::HighlightImportantArea((uintptr)this + m_nIp, X - dX, Y - dY, X + dX, Y + dX, b3D ? Z : MAP_Z_LOW_LIMIT);\n#endif\n\tif (CTheScripts::DbgFlag) {\n\t\tif (b3D)\n\t\t\tCTheScripts::DrawDebugCube(X - dX, Y - dY, Z - dZ, X + dX, Y + dY, Z + dZ);\n\t\telse\n\t\t\tCTheScripts::DrawDebugSquare(X - dX, Y - dY, X + dX, Y + dY);\n\t}\n}\n\nvoid CRunningScript::LocatePlayerCarCommand(int32 command, uint32* pIp)\n{\n\tbool b3D, result, debug;\n\tfloat X, Y, Z, dX, dY, dZ;\n\tswitch (command) {\n\tcase COMMAND_LOCATE_PLAYER_ANY_MEANS_CAR_3D:\n\tcase COMMAND_LOCATE_PLAYER_ON_FOOT_CAR_3D:\n\tcase COMMAND_LOCATE_PLAYER_IN_CAR_CAR_3D:\n\t\tb3D = true;\n\t\tbreak;\n\tdefault:\n\t\tb3D = false;\n\t\tbreak;\n\t}\n\tCollectParameters(pIp, b3D ? 6 : 5);\n\tCPlayerInfo* pPlayerInfo = &CWorld::Players[ScriptParams[0]];\n\tCVehicle* pTarget = CPools::GetVehiclePool()->GetAt(ScriptParams[1]);\n\tscript_assert(pTarget);\n\tCVector pos = pPlayerInfo->GetPos();\n\tX = pTarget->GetPosition().x;\n\tY = pTarget->GetPosition().y;\n\tZ = pTarget->GetPosition().z;\n\tdX = *(float*)&ScriptParams[2];\n\tdY = *(float*)&ScriptParams[3];\n\tif (b3D) {\n\t\tdZ = *(float*)&ScriptParams[4];\n\t\tdebug = ScriptParams[5];\n\t}\n\telse {\n\t\tdebug = ScriptParams[4];\n\t}\n\tresult = false;\n\tbool in_area;\n\tif (b3D) {\n\t\tin_area = X - dX <= pos.x &&\n\t\t\tX + dX >= pos.x &&\n\t\t\tY - dY <= pos.y &&\n\t\t\tY + dY >= pos.y &&\n\t\t\tZ - dZ <= pos.z &&\n\t\t\tZ + dZ >= pos.z;\n\t}\n\telse {\n\t\tin_area = X - dX <= pos.x &&\n\t\t\tX + dX >= pos.x &&\n\t\t\tY - dY <= pos.y &&\n\t\t\tY + dY >= pos.y;\n\t}\n\tif (in_area) {\n\t\tswitch (command) {\n\t\tcase COMMAND_LOCATE_PLAYER_ANY_MEANS_CAR_2D:\n\t\tcase COMMAND_LOCATE_PLAYER_ANY_MEANS_CAR_3D:\n\t\t\tresult = true;\n\t\t\tbreak;\n\t\tcase COMMAND_LOCATE_PLAYER_ON_FOOT_CAR_2D:\n\t\tcase COMMAND_LOCATE_PLAYER_ON_FOOT_CAR_3D:\n\t\t\tresult = !pPlayerInfo->m_pPed->bInVehicle;\n\t\t\tbreak;\n\t\tcase COMMAND_LOCATE_PLAYER_IN_CAR_CAR_2D:\n\t\tcase COMMAND_LOCATE_PLAYER_IN_CAR_CAR_3D:\n\t\t\tresult = pPlayerInfo->m_pPed->bInVehicle;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tscript_assert(false);\n\t\t\tbreak;\n\t\t}\n\t}\n\tUpdateCompareFlag(result);\n\tif (debug)\n\t\tCTheScripts::HighlightImportantArea((uintptr)this + m_nIp, X - dX, Y - dY, X + dX, Y + dY, b3D ? Z : MAP_Z_LOW_LIMIT);\n\tif (CTheScripts::DbgFlag) {\n\t\tif (b3D)\n\t\t\tCTheScripts::DrawDebugCube(X - dX, Y - dY, Z - dZ, X + dX, Y + dY, Z + dZ);\n\t\telse\n\t\t\tCTheScripts::DrawDebugSquare(X - dX, Y - dY, X + dX, Y + dY);\n\t}\n}\n\nvoid CRunningScript::LocateCharCommand(int32 command, uint32* pIp)\n{\n\tbool b3D, result, debug, decided = false;\n\tfloat X, Y, Z, dX, dY, dZ;\n\tswitch (command) {\n\tcase COMMAND_LOCATE_CHAR_ANY_MEANS_3D:\n\tcase COMMAND_LOCATE_CHAR_ON_FOOT_3D:\n\tcase COMMAND_LOCATE_CHAR_IN_CAR_3D:\n\tcase COMMAND_LOCATE_STOPPED_CHAR_ANY_MEANS_3D:\n\tcase COMMAND_LOCATE_STOPPED_CHAR_ON_FOOT_3D:\n\tcase COMMAND_LOCATE_STOPPED_CHAR_IN_CAR_3D:\n\t\tb3D = true;\n\t\tbreak;\n\tdefault:\n\t\tb3D = false;\n\t\tbreak;\n\t}\n\tCollectParameters(pIp, b3D ? 8 : 6);\n\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\tscript_assert(pPed);\n\tCVector pos = pPed->InVehicle() ? pPed->m_pMyVehicle->GetPosition() : pPed->GetPosition();\n\tswitch (command) {\n\tcase COMMAND_LOCATE_STOPPED_CHAR_ANY_MEANS_2D:\n\tcase COMMAND_LOCATE_STOPPED_CHAR_ANY_MEANS_3D:\n\tcase COMMAND_LOCATE_STOPPED_CHAR_IN_CAR_2D:\n\tcase COMMAND_LOCATE_STOPPED_CHAR_IN_CAR_3D:\n\tcase COMMAND_LOCATE_STOPPED_CHAR_ON_FOOT_2D:\n\tcase COMMAND_LOCATE_STOPPED_CHAR_ON_FOOT_3D:\n\t\tif (!CTheScripts::IsPedStopped(pPed)) {\n\t\t\tresult = false;\n\t\t\tdecided = true;\n\t\t}\n\t\tbreak;\n\tdefault:\n\t\tbreak;\n\t}\n\tX = *(float*)&ScriptParams[1];\n\tY = *(float*)&ScriptParams[2];\n\tif (b3D) {\n\t\tZ = *(float*)&ScriptParams[3];\n\t\tdX = *(float*)&ScriptParams[4];\n\t\tdY = *(float*)&ScriptParams[5];\n\t\tdZ = *(float*)&ScriptParams[6];\n\t\tdebug = ScriptParams[7];\n\t}\n\telse {\n\t\tdX = *(float*)&ScriptParams[3];\n\t\tdY = *(float*)&ScriptParams[4];\n\t\tdebug = ScriptParams[5];\n\t}\n\tif (!decided) {\n\t\tresult = false;\n\t\tbool in_area;\n\t\tif (b3D) {\n\t\t\tin_area = X - dX <= pos.x &&\n\t\t\t\tX + dX >= pos.x &&\n\t\t\t\tY - dY <= pos.y &&\n\t\t\t\tY + dY >= pos.y &&\n\t\t\t\tZ - dZ <= pos.z &&\n\t\t\t\tZ + dZ >= pos.z;\n\t\t}\n\t\telse {\n\t\t\tin_area = X - dX <= pos.x &&\n\t\t\t\tX + dX >= pos.x &&\n\t\t\t\tY - dY <= pos.y &&\n\t\t\t\tY + dY >= pos.y;\n\t\t}\n\t\tif (in_area) {\n\t\t\tswitch (command) {\n\t\t\tcase COMMAND_LOCATE_CHAR_ANY_MEANS_2D:\n\t\t\tcase COMMAND_LOCATE_CHAR_ANY_MEANS_3D:\n\t\t\tcase COMMAND_LOCATE_STOPPED_CHAR_ANY_MEANS_2D:\n\t\t\tcase COMMAND_LOCATE_STOPPED_CHAR_ANY_MEANS_3D:\n\t\t\t\tresult = true;\n\t\t\t\tbreak;\n\t\t\tcase COMMAND_LOCATE_CHAR_ON_FOOT_2D:\n\t\t\tcase COMMAND_LOCATE_CHAR_ON_FOOT_3D:\n\t\t\tcase COMMAND_LOCATE_STOPPED_CHAR_ON_FOOT_2D:\n\t\t\tcase COMMAND_LOCATE_STOPPED_CHAR_ON_FOOT_3D:\n\t\t\t\tresult = !pPed->bInVehicle;\n\t\t\t\tbreak;\n\t\t\tcase COMMAND_LOCATE_CHAR_IN_CAR_2D:\n\t\t\tcase COMMAND_LOCATE_CHAR_IN_CAR_3D:\n\t\t\tcase COMMAND_LOCATE_STOPPED_CHAR_IN_CAR_2D:\n\t\t\tcase COMMAND_LOCATE_STOPPED_CHAR_IN_CAR_3D:\n\t\t\t\tresult = pPed->bInVehicle;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tscript_assert(false);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\tUpdateCompareFlag(result);\n\tif (debug)\n\t\tCTheScripts::HighlightImportantArea((uintptr)this + m_nIp, X - dX, Y - dY, X + dX, Y + dY, b3D ? Z : MAP_Z_LOW_LIMIT);\n\tif (CTheScripts::DbgFlag) {\n\t\tif (b3D)\n\t\t\tCTheScripts::DrawDebugCube(X - dX, Y - dY, Z - dZ, X + dX, Y + dY, Z + dZ);\n\t\telse\n\t\t\tCTheScripts::DrawDebugSquare(X - dX, Y - dY, X + dX, Y + dY);\n\t}\n}\n\nvoid CRunningScript::LocateCharCharCommand(int32 command, uint32* pIp)\n{\n\tbool b3D, result, debug;\n\tfloat X, Y, Z, dX, dY, dZ;\n\tswitch (command) {\n\tcase COMMAND_LOCATE_CHAR_ANY_MEANS_CHAR_3D:\n\tcase COMMAND_LOCATE_CHAR_ON_FOOT_CHAR_3D:\n\tcase COMMAND_LOCATE_CHAR_IN_CAR_CHAR_3D:\n\t\tb3D = true;\n\t\tbreak;\n\tdefault:\n\t\tb3D = false;\n\t\tbreak;\n\t}\n\tCollectParameters(pIp, b3D ? 6 : 5);\n\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\tscript_assert(pPed);\n\tCPed* pTarget = CPools::GetPedPool()->GetAt(ScriptParams[1]);\n\tscript_assert(pTarget);\n\tCVector pos = pPed->bInVehicle ? pPed->m_pMyVehicle->GetPosition() : pPed->GetPosition();\n\tif (pTarget->bInVehicle) {\n\t\tX = pTarget->m_pMyVehicle->GetPosition().x;\n\t\tY = pTarget->m_pMyVehicle->GetPosition().y;\n\t\tZ = pTarget->m_pMyVehicle->GetPosition().z;\n\t}\n\telse {\n\t\tX = pTarget->GetPosition().x;\n\t\tY = pTarget->GetPosition().y;\n\t\tZ = pTarget->GetPosition().z;\n\t}\n\tdX = *(float*)&ScriptParams[2];\n\tdY = *(float*)&ScriptParams[3];\n\tif (b3D) {\n\t\tdZ = *(float*)&ScriptParams[4];\n\t\tdebug = ScriptParams[5];\n\t}\n\telse {\n\t\tdebug = ScriptParams[4];\n\t}\n\tresult = false;\n\tbool in_area;\n\tif (b3D) {\n\t\tin_area = X - dX <= pos.x &&\n\t\t\tX + dX >= pos.x &&\n\t\t\tY - dY <= pos.y &&\n\t\t\tY + dY >= pos.y &&\n\t\t\tZ - dZ <= pos.z &&\n\t\t\tZ + dZ >= pos.z;\n\t}\n\telse {\n\t\tin_area = X - dX <= pos.x &&\n\t\t\tX + dX >= pos.x &&\n\t\t\tY - dY <= pos.y &&\n\t\t\tY + dY >= pos.y;\n\t}\n\tif (in_area) {\n\t\tswitch (command) {\n\t\tcase COMMAND_LOCATE_CHAR_ANY_MEANS_CHAR_2D:\n\t\tcase COMMAND_LOCATE_CHAR_ANY_MEANS_CHAR_3D:\n\t\t\tresult = true;\n\t\t\tbreak;\n\t\tcase COMMAND_LOCATE_CHAR_ON_FOOT_CHAR_2D:\n\t\tcase COMMAND_LOCATE_CHAR_ON_FOOT_CHAR_3D:\n\t\t\tresult = !pPed->bInVehicle;\n\t\t\tbreak;\n\t\tcase COMMAND_LOCATE_CHAR_IN_CAR_CHAR_2D:\n\t\tcase COMMAND_LOCATE_CHAR_IN_CAR_CHAR_3D:\n\t\t\tresult = pPed->bInVehicle;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tscript_assert(false);\n\t\t\tbreak;\n\t\t}\n\t}\n\tUpdateCompareFlag(result);\n\tif (debug)\n#ifdef FIX_BUGS\n\t\tCTheScripts::HighlightImportantArea((uintptr)this + m_nIp, X - dX, Y - dY, X + dX, Y + dY, b3D ? Z : MAP_Z_LOW_LIMIT);\n#else\n\t\tCTheScripts::HighlightImportantArea((uintptr)this + m_nIp, X - dX, Y - dY, X + dX, Y + dX, b3D ? Z : MAP_Z_LOW_LIMIT);\n#endif\n\tif (CTheScripts::DbgFlag) {\n\t\tif (b3D)\n\t\t\tCTheScripts::DrawDebugCube(X - dX, Y - dY, Z - dZ, X + dX, Y + dY, Z + dZ);\n\t\telse\n\t\t\tCTheScripts::DrawDebugSquare(X - dX, Y - dY, X + dX, Y + dY);\n\t}\n}\n\nvoid CRunningScript::LocateCharCarCommand(int32 command, uint32* pIp)\n{\n\tbool b3D, result, debug;\n\tfloat X, Y, Z, dX, dY, dZ;\n\tswitch (command) {\n\tcase COMMAND_LOCATE_CHAR_ANY_MEANS_CAR_3D:\n\tcase COMMAND_LOCATE_CHAR_ON_FOOT_CAR_3D:\n\tcase COMMAND_LOCATE_CHAR_IN_CAR_CAR_3D:\n\t\tb3D = true;\n\t\tbreak;\n\tdefault:\n\t\tb3D = false;\n\t\tbreak;\n\t}\n\tCollectParameters(pIp, b3D ? 6 : 5);\n\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\tscript_assert(pPed);\n\tCVehicle* pTarget = CPools::GetVehiclePool()->GetAt(ScriptParams[1]);\n\tscript_assert(pTarget);\n\tCVector pos = pPed->bInVehicle ? pPed->m_pMyVehicle->GetPosition() : pPed->GetPosition();\n\tX = pTarget->GetPosition().x;\n\tY = pTarget->GetPosition().y;\n\tZ = pTarget->GetPosition().z;\n\tdX = *(float*)&ScriptParams[2];\n\tdY = *(float*)&ScriptParams[3];\n\tif (b3D) {\n\t\tdZ = *(float*)&ScriptParams[4];\n\t\tdebug = ScriptParams[5];\n\t}\n\telse {\n\t\tdebug = ScriptParams[4];\n\t}\n\tresult = false;\n\tbool in_area;\n\tif (b3D) {\n\t\tin_area = X - dX <= pos.x &&\n\t\t\tX + dX >= pos.x &&\n\t\t\tY - dY <= pos.y &&\n\t\t\tY + dY >= pos.y &&\n\t\t\tZ - dZ <= pos.z &&\n\t\t\tZ + dZ >= pos.z;\n\t}\n\telse {\n\t\tin_area = X - dX <= pos.x &&\n\t\t\tX + dX >= pos.x &&\n\t\t\tY - dY <= pos.y &&\n\t\t\tY + dY >= pos.y;\n\t}\n\tif (in_area) {\n\t\tswitch (command) {\n\t\tcase COMMAND_LOCATE_CHAR_ANY_MEANS_CAR_2D:\n\t\tcase COMMAND_LOCATE_CHAR_ANY_MEANS_CAR_3D:\n\t\t\tresult = true;\n\t\t\tbreak;\n\t\tcase COMMAND_LOCATE_CHAR_ON_FOOT_CAR_2D:\n\t\tcase COMMAND_LOCATE_CHAR_ON_FOOT_CAR_3D:\n\t\t\tresult = !pPed->bInVehicle;\n\t\t\tbreak;\n\t\tcase COMMAND_LOCATE_CHAR_IN_CAR_CAR_2D:\n\t\tcase COMMAND_LOCATE_CHAR_IN_CAR_CAR_3D:\n\t\t\tresult = pPed->bInVehicle;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tscript_assert(false);\n\t\t\tbreak;\n\t\t}\n\t}\n\tUpdateCompareFlag(result);\n\tif (debug)\n\t\tCTheScripts::HighlightImportantArea((uintptr)this + m_nIp, X - dX, Y - dY, X + dX, Y + dY, b3D ? Z : MAP_Z_LOW_LIMIT);\n\tif (CTheScripts::DbgFlag) {\n\t\tif (b3D)\n\t\t\tCTheScripts::DrawDebugCube(X - dX, Y - dY, Z - dZ, X + dX, Y + dY, Z + dZ);\n\t\telse\n\t\t\tCTheScripts::DrawDebugSquare(X - dX, Y - dY, X + dX, Y + dY);\n\t}\n}\n\nvoid CRunningScript::LocateCharObjectCommand(int32 command, uint32* pIp)\n{\n\tbool b3D, result, debug;\n\tfloat X, Y, Z, dX, dY, dZ;\n\tswitch (command) {\n\tcase COMMAND_LOCATE_CHAR_ANY_MEANS_OBJECT_3D:\n\tcase COMMAND_LOCATE_CHAR_ON_FOOT_OBJECT_3D:\n\tcase COMMAND_LOCATE_CHAR_IN_CAR_OBJECT_3D:\n\t\tb3D = true;\n\t\tbreak;\n\tdefault:\n\t\tb3D = false;\n\t\tbreak;\n\t}\n\tCollectParameters(pIp, b3D ? 6 : 5);\n\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\tscript_assert(pPed);\n\tCObject* pTarget = CPools::GetObjectPool()->GetAt(ScriptParams[1]);\n\tscript_assert(pTarget);\n\tCVector pos = pPed->bInVehicle ? pPed->m_pMyVehicle->GetPosition() : pPed->GetPosition();\n\tX = pTarget->GetPosition().x;\n\tY = pTarget->GetPosition().y;\n\tZ = pTarget->GetPosition().z;\n\tdX = *(float*)&ScriptParams[2];\n\tdY = *(float*)&ScriptParams[3];\n\tif (b3D) {\n\t\tdZ = *(float*)&ScriptParams[4];\n\t\tdebug = ScriptParams[5];\n\t}\n\telse {\n\t\tdebug = ScriptParams[4];\n\t}\n\tresult = false;\n\tbool in_area;\n\tif (b3D) {\n\t\tin_area = X - dX <= pos.x &&\n\t\t\tX + dX >= pos.x &&\n\t\t\tY - dY <= pos.y &&\n\t\t\tY + dY >= pos.y &&\n\t\t\tZ - dZ <= pos.z &&\n\t\t\tZ + dZ >= pos.z;\n\t}\n\telse {\n\t\tin_area = X - dX <= pos.x &&\n\t\t\tX + dX >= pos.x &&\n\t\t\tY - dY <= pos.y &&\n\t\t\tY + dY >= pos.y;\n\t}\n\tif (in_area) {\n\t\tswitch (command) {\n\t\tcase COMMAND_LOCATE_CHAR_ANY_MEANS_OBJECT_2D:\n\t\tcase COMMAND_LOCATE_CHAR_ANY_MEANS_OBJECT_3D:\n\t\t\tresult = true;\n\t\t\tbreak;\n\t\tcase COMMAND_LOCATE_CHAR_ON_FOOT_OBJECT_2D:\n\t\tcase COMMAND_LOCATE_CHAR_ON_FOOT_OBJECT_3D:\n\t\t\tresult = !pPed->bInVehicle;\n\t\t\tbreak;\n\t\tcase COMMAND_LOCATE_CHAR_IN_CAR_OBJECT_2D:\n\t\tcase COMMAND_LOCATE_CHAR_IN_CAR_OBJECT_3D:\n\t\t\tresult = pPed->bInVehicle;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tscript_assert(false);\n\t\t\tbreak;\n\t\t}\n\t}\n\tUpdateCompareFlag(result);\n\tif (debug)\n\t\tCTheScripts::HighlightImportantArea((uintptr)this + m_nIp, X - dX, Y - dY, X + dX, Y + dY, b3D ? Z : MAP_Z_LOW_LIMIT);\n\tif (CTheScripts::DbgFlag) {\n\t\tif (b3D)\n\t\t\tCTheScripts::DrawDebugCube(X - dX, Y - dY, Z - dZ, X + dX, Y + dY, Z + dZ);\n\t\telse\n\t\t\tCTheScripts::DrawDebugSquare(X - dX, Y - dY, X + dX, Y + dY);\n\t}\n}\n\nvoid CRunningScript::LocateCarCommand(int32 command, uint32* pIp)\n{\n\tbool b3D, result, debug, decided = false;\n\tfloat X, Y, Z, dX, dY, dZ;\n\tswitch (command) {\n\tcase COMMAND_LOCATE_CAR_3D:\n\tcase COMMAND_LOCATE_STOPPED_CAR_3D:\n\t\tb3D = true;\n\t\tbreak;\n\tdefault:\n\t\tb3D = false;\n\t\tbreak;\n\t}\n\tCollectParameters(pIp, b3D ? 8 : 6);\n\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\tscript_assert(pVehicle);\n\tCVector pos = pVehicle->GetPosition();\n\tswitch (command) {\n\tcase COMMAND_LOCATE_STOPPED_CAR_2D:\n\tcase COMMAND_LOCATE_STOPPED_CAR_3D:\n\t\tif (!CTheScripts::IsVehicleStopped(pVehicle)) {\n\t\t\tresult = false;\n\t\t\tdecided = true;\n\t\t}\n\t\tbreak;\n\tdefault:\n\t\tbreak;\n\t}\n\tX = *(float*)&ScriptParams[1];\n\tY = *(float*)&ScriptParams[2];\n\tif (b3D) {\n\t\tZ = *(float*)&ScriptParams[3];\n\t\tdX = *(float*)&ScriptParams[4];\n\t\tdY = *(float*)&ScriptParams[5];\n\t\tdZ = *(float*)&ScriptParams[6];\n\t\tdebug = ScriptParams[7];\n\t}\n\telse {\n\t\tdX = *(float*)&ScriptParams[3];\n\t\tdY = *(float*)&ScriptParams[4];\n\t\tdebug = ScriptParams[5];\n\t}\n\tif (!decided) {\n\t\tresult = false;\n\t\tbool in_area;\n\t\tif (b3D) {\n\t\t\tin_area = X - dX <= pos.x &&\n\t\t\t\tX + dX >= pos.x &&\n\t\t\t\tY - dY <= pos.y &&\n\t\t\t\tY + dY >= pos.y &&\n\t\t\t\tZ - dZ <= pos.z &&\n\t\t\t\tZ + dZ >= pos.z;\n\t\t}\n\t\telse {\n\t\t\tin_area = X - dX <= pos.x &&\n\t\t\t\tX + dX >= pos.x &&\n\t\t\t\tY - dY <= pos.y &&\n\t\t\t\tY + dY >= pos.y;\n\t\t}\n\t\tresult = in_area;\n\t}\n\tUpdateCompareFlag(result);\n\tif (debug)\n\t\tCTheScripts::HighlightImportantArea((uintptr)this + m_nIp, X - dX, Y - dY, X + dX, Y + dY, b3D ? Z : MAP_Z_LOW_LIMIT);\n\tif (CTheScripts::DbgFlag) {\n\t\tif (b3D)\n\t\t\tCTheScripts::DrawDebugCube(X - dX, Y - dY, Z - dZ, X + dX, Y + dY, Z + dZ);\n\t\telse\n\t\t\tCTheScripts::DrawDebugSquare(X - dX, Y - dY, X + dX, Y + dY);\n\t}\n}\n\nvoid CRunningScript::LocateObjectCommand(int32 command, uint32* pIp)\n{\n\tbool b3D, result, debug;\n\tfloat X, Y, Z, dX, dY, dZ;\n\tswitch (command) {\n\tcase COMMAND_LOCATE_OBJECT_3D:\n\t\tb3D = true;\n\t\tbreak;\n\tdefault:\n\t\tb3D = false;\n\t\tbreak;\n\t}\n\tCollectParameters(pIp, b3D ? 8 : 6);\n\tCObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);\n\tscript_assert(pObject);\n\tCVector pos = pObject->GetPosition();\n\tX = *(float*)&ScriptParams[1];\n\tY = *(float*)&ScriptParams[2];\n\tif (b3D) {\n\t\tZ = *(float*)&ScriptParams[3];\n\t\tdX = *(float*)&ScriptParams[4];\n\t\tdY = *(float*)&ScriptParams[5];\n\t\tdZ = *(float*)&ScriptParams[6];\n\t\tdebug = ScriptParams[7];\n\t}\n\telse {\n\t\tdX = *(float*)&ScriptParams[3];\n\t\tdY = *(float*)&ScriptParams[4];\n\t\tdebug = ScriptParams[5];\n\t}\n\tresult = false;\n\tbool in_area;\n\tif (b3D) {\n\t\tin_area = X - dX <= pos.x &&\n\t\t\tX + dX >= pos.x &&\n\t\t\tY - dY <= pos.y &&\n\t\t\tY + dY >= pos.y &&\n\t\t\tZ - dZ <= pos.z &&\n\t\t\tZ + dZ >= pos.z;\n\t}\n\telse {\n\t\tin_area = X - dX <= pos.x &&\n\t\t\tX + dX >= pos.x &&\n\t\t\tY - dY <= pos.y &&\n\t\t\tY + dY >= pos.y;\n\t}\n\tresult = in_area;\n\tUpdateCompareFlag(result);\n\tif (debug)\n\t\tCTheScripts::HighlightImportantArea((uintptr)this + m_nIp, X - dX, Y - dY, X + dX, Y + dY, b3D ? Z : MAP_Z_LOW_LIMIT);\n\tif (CTheScripts::DbgFlag) {\n\t\tif (b3D)\n\t\t\tCTheScripts::DrawDebugCube(X - dX, Y - dY, Z - dZ, X + dX, Y + dY, Z + dZ);\n\t\telse\n\t\t\tCTheScripts::DrawDebugSquare(X - dX, Y - dY, X + dX, Y + dY);\n\t}\n}\n\nvoid CRunningScript::LocateSniperBulletCommand(int32 command, uint32* pIp)\n{\n\tbool b3D, result, debug;\n\tfloat X, Y, Z, dX, dY, dZ;\n\tswitch (command) {\n\tcase COMMAND_LOCATE_SNIPER_BULLET_3D:\n\t\tb3D = true;\n\t\tbreak;\n\tdefault:\n\t\tb3D = false;\n\t\tbreak;\n\t}\n\tCollectParameters(pIp, b3D ? 7 : 5);\n\tX = *(float*)&ScriptParams[0];\n\tY = *(float*)&ScriptParams[1];\n\tif (b3D) {\n\t\tZ = *(float*)&ScriptParams[2];\n\t\tdX = *(float*)&ScriptParams[3];\n\t\tdY = *(float*)&ScriptParams[4];\n\t\tdZ = *(float*)&ScriptParams[5];\n\t\tdebug = ScriptParams[6];\n\t}\n\telse {\n\t\tdX = *(float*)&ScriptParams[2];\n\t\tdY = *(float*)&ScriptParams[3];\n\t\tdebug = ScriptParams[4];\n\t}\n\tresult = CBulletInfo::TestForSniperBullet(X - dX, X + dX, Y - dY, Y + dY, b3D ? Z - dZ : -1000.0f, b3D ? Z + dZ : 1000.0f);\n\tUpdateCompareFlag(result);\n\tif (debug)\n\t\tCTheScripts::HighlightImportantArea((uintptr)this + m_nIp, X - dX, Y - dY, X + dX, Y + dY, b3D ? Z : MAP_Z_LOW_LIMIT);\n\tif (CTheScripts::DbgFlag) {\n\t\tif (b3D)\n\t\t\tCTheScripts::DrawDebugCube(X - dX, Y - dY, Z - dZ, X + dX, Y + dY, Z + dZ);\n\t\telse\n\t\t\tCTheScripts::DrawDebugSquare(X - dX, Y - dY, X + dX, Y + dY);\n\t}\n}\n\nvoid CRunningScript::PlayerInAreaCheckCommand(int32 command, uint32* pIp)\n{\n\tbool b3D, result, debug, decided = false;\n\tfloat infX, infY, infZ, supX, supY, supZ;\n\tswitch (command) {\n\tcase COMMAND_IS_PLAYER_IN_AREA_3D:\n\tcase COMMAND_IS_PLAYER_IN_AREA_ON_FOOT_3D:\n\tcase COMMAND_IS_PLAYER_IN_AREA_IN_CAR_3D:\n\tcase COMMAND_IS_PLAYER_STOPPED_IN_AREA_3D:\n\tcase COMMAND_IS_PLAYER_STOPPED_IN_AREA_ON_FOOT_3D:\n\tcase COMMAND_IS_PLAYER_STOPPED_IN_AREA_IN_CAR_3D:\n\t\tb3D = true;\n\t\tbreak;\n\tdefault:\n\t\tb3D = false;\n\t\tbreak;\n\t}\n\tCollectParameters(pIp, b3D ? 8 : 6);\n\tCPlayerInfo* pPlayerInfo = &CWorld::Players[ScriptParams[0]];\n\tswitch (command) {\n\tcase COMMAND_IS_PLAYER_STOPPED_IN_AREA_3D:\n\tcase COMMAND_IS_PLAYER_STOPPED_IN_AREA_ON_FOOT_3D:\n\tcase COMMAND_IS_PLAYER_STOPPED_IN_AREA_IN_CAR_3D:\n\tcase COMMAND_IS_PLAYER_STOPPED_IN_AREA_2D:\n\tcase COMMAND_IS_PLAYER_STOPPED_IN_AREA_ON_FOOT_2D:\n\tcase COMMAND_IS_PLAYER_STOPPED_IN_AREA_IN_CAR_2D:\n\t\tif (!CTheScripts::IsPlayerStopped(pPlayerInfo)) {\n\t\t\tresult = false;\n\t\t\tdecided = true;\n\t\t}\n\t\tbreak;\n\tdefault:\n\t\tbreak;\n\t}\n\tinfX = *(float*)&ScriptParams[1];\n\tinfY = *(float*)&ScriptParams[2];\n\tif (b3D) {\n\t\tinfZ = *(float*)&ScriptParams[3];\n\t\tsupX = *(float*)&ScriptParams[4];\n\t\tsupY = *(float*)&ScriptParams[5];\n\t\tsupZ = *(float*)&ScriptParams[6];\n\t\tif (infZ > supZ) {\n\t\t\tinfZ = *(float*)&ScriptParams[6];\n\t\t\tsupZ = *(float*)&ScriptParams[3];\n\t\t}\n\t\tdebug = ScriptParams[7];\n\t}\n\telse {\n\t\tsupX = *(float*)&ScriptParams[3];\n\t\tsupY = *(float*)&ScriptParams[4];\n\t\tdebug = ScriptParams[5];\n\t}\n\tif (infX > supX) {\n\t\tfloat tmp = infX;\n\t\tinfX = supX;\n\t\tsupX = tmp;\n\t}\n\tif (infY > supY) {\n\t\tfloat tmp = infY;\n\t\tinfY = supY;\n\t\tsupY = tmp;\n\t}\n\tif (!decided) {\n\t\tCVector pos = pPlayerInfo->GetPos();\n\t\tresult = false;\n\t\tbool in_area;\n\t\tif (b3D) {\n\t\t\tin_area = infX <= pos.x &&\n\t\t\t\tsupX >= pos.x &&\n\t\t\t\tinfY <= pos.y &&\n\t\t\t\tsupY >= pos.y &&\n\t\t\t\tinfZ <= pos.z &&\n\t\t\t\tsupZ >= pos.z;\n\t\t}\n\t\telse {\n\t\t\tin_area = infX <= pos.x &&\n\t\t\t\tsupX >= pos.x &&\n\t\t\t\tinfY <= pos.y &&\n\t\t\t\tsupY >= pos.y;\n\t\t}\n\t\tif (in_area) {\n\t\t\tswitch (command) {\n\t\t\tcase COMMAND_IS_PLAYER_IN_AREA_2D:\n\t\t\tcase COMMAND_IS_PLAYER_IN_AREA_3D:\n\t\t\tcase COMMAND_IS_PLAYER_STOPPED_IN_AREA_2D:\n\t\t\tcase COMMAND_IS_PLAYER_STOPPED_IN_AREA_3D:\n\t\t\t\tresult = true;\n\t\t\t\tbreak;\n\t\t\tcase COMMAND_IS_PLAYER_IN_AREA_ON_FOOT_2D:\n\t\t\tcase COMMAND_IS_PLAYER_IN_AREA_ON_FOOT_3D:\n\t\t\tcase COMMAND_IS_PLAYER_STOPPED_IN_AREA_ON_FOOT_2D:\n\t\t\tcase COMMAND_IS_PLAYER_STOPPED_IN_AREA_ON_FOOT_3D:\n\t\t\t\tresult = !pPlayerInfo->m_pPed->bInVehicle;\n\t\t\t\tbreak;\n\t\t\tcase COMMAND_IS_PLAYER_IN_AREA_IN_CAR_2D:\n\t\t\tcase COMMAND_IS_PLAYER_IN_AREA_IN_CAR_3D:\n\t\t\tcase COMMAND_IS_PLAYER_STOPPED_IN_AREA_IN_CAR_2D:\n\t\t\tcase COMMAND_IS_PLAYER_STOPPED_IN_AREA_IN_CAR_3D:\n\t\t\t\tresult = pPlayerInfo->m_pPed->bInVehicle;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tscript_assert(false);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\tUpdateCompareFlag(result);\n\tif (debug)\n\t\tCTheScripts::HighlightImportantArea((uintptr)this + m_nIp, infX, infY, supX, supY, b3D ? (infZ + supZ) / 2 : MAP_Z_LOW_LIMIT);\n\tif (CTheScripts::DbgFlag) {\n\t\tif (b3D)\n\t\t\tCTheScripts::DrawDebugCube(infX, infY, infZ, supX, supY, supZ);\n\t\telse\n\t\t\tCTheScripts::DrawDebugSquare(infX, infY, supX, supY);\n\t}\n}\n\nvoid CRunningScript::PlayerInAngledAreaCheckCommand(int32 command, uint32* pIp)\n{\n\tbool b3D, result, debug, decided = false;\n\tfloat infX, infY, infZ, supX, supY, supZ, side2length;\n\tswitch (command) {\n\tcase COMMAND_IS_PLAYER_IN_ANGLED_AREA_3D:\n\tcase COMMAND_IS_PLAYER_IN_ANGLED_AREA_ON_FOOT_3D:\n\tcase COMMAND_IS_PLAYER_IN_ANGLED_AREA_IN_CAR_3D:\n\tcase COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_3D:\n\tcase COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_ON_FOOT_3D:\n\tcase COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_IN_CAR_3D:\n\t\tb3D = true;\n\t\tbreak;\n\tdefault:\n\t\tb3D = false;\n\t\tbreak;\n\t}\n\tCollectParameters(pIp, b3D ? 9 : 7);\n\tCPlayerInfo* pPlayerInfo = &CWorld::Players[ScriptParams[0]];\n\tswitch (command) {\n\tcase COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_3D:\n\tcase COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_ON_FOOT_3D:\n\tcase COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_IN_CAR_3D:\n\tcase COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_2D:\n\tcase COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_ON_FOOT_2D:\n\tcase COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_IN_CAR_2D:\n\t\tif (!CTheScripts::IsPlayerStopped(pPlayerInfo)) {\n\t\t\tresult = false;\n\t\t\tdecided = true;\n\t\t}\n\t\tbreak;\n\tdefault:\n\t\tbreak;\n\t}\n\tinfX = *(float*)&ScriptParams[1];\n\tinfY = *(float*)&ScriptParams[2];\n\tif (b3D) {\n\t\tinfZ = *(float*)&ScriptParams[3];\n\t\tsupX = *(float*)&ScriptParams[4];\n\t\tsupY = *(float*)&ScriptParams[5];\n\t\tsupZ = *(float*)&ScriptParams[6];\n\t\tif (infZ > supZ) {\n\t\t\tinfZ = *(float*)&ScriptParams[6];\n\t\t\tsupZ = *(float*)&ScriptParams[3];\n\t\t}\n\t\tside2length = *(float*)&ScriptParams[7];\n\t\tdebug = ScriptParams[8];\n\t}\n\telse {\n\t\tsupX = *(float*)&ScriptParams[3];\n\t\tsupY = *(float*)&ScriptParams[4];\n\t\tside2length = *(float*)&ScriptParams[5];\n\t\tdebug = ScriptParams[6];\n\t}\n\tfloat initAngle = CGeneral::GetRadianAngleBetweenPoints(infX, infY, supX, supY) + HALFPI;\n\twhile (initAngle < 0.0f)\n\t\tinitAngle += TWOPI;\n\twhile (initAngle > TWOPI)\n\t\tinitAngle -= TWOPI;\n\t// it looks like the idea is to use a rectangle using the diagonal of the rectangle as\n\t// the side of new rectangle, with \"length\" being the length of second side\n\tfloat rotatedSupX = supX + side2length * sin(initAngle);\n\tfloat rotatedSupY = supY - side2length * cos(initAngle);\n\tfloat rotatedInfX = infX + side2length * sin(initAngle);\n\tfloat rotatedInfY = infY - side2length * cos(initAngle);\n\tfloat side1X = supX - infX;\n\tfloat side1Y = supY - infY;\n\tfloat side1Length = CVector2D(side1X, side1Y).Magnitude();\n\tfloat side2X = rotatedInfX - infX;\n\tfloat side2Y = rotatedInfY - infY;\n\tfloat side2Length = CVector2D(side2X, side2Y).Magnitude(); // == side2length?\n\tif (!decided) {\n\t\tCVector pos = pPlayerInfo->GetPos();\n\t\tresult = false;\n\t\tfloat X = pos.x - infX;\n\t\tfloat Y = pos.y - infY;\n\t\tfloat positionAlongSide1 = X * side1X / side1Length + Y * side1Y / side1Length;\n\t\tbool in_area = false;\n\t\tif (positionAlongSide1 >= 0.0f && positionAlongSide1 <= side1Length) {\n\t\t\tfloat positionAlongSide2 = X * side2X / side2Length + Y * side2Y / side2Length;\n\t\t\tif (positionAlongSide2 >= 0.0f && positionAlongSide2 <= side2Length) {\n\t\t\t\tin_area = !b3D || pos.z >= infZ && pos.z <= supZ;\n\t\t\t}\n\t\t}\n\n\t\tif (in_area) {\n\t\t\tswitch (command) {\n\t\t\tcase COMMAND_IS_PLAYER_IN_ANGLED_AREA_2D:\n\t\t\tcase COMMAND_IS_PLAYER_IN_ANGLED_AREA_3D:\n\t\t\tcase COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_2D:\n\t\t\tcase COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_3D:\n\t\t\t\tresult = true;\n\t\t\t\tbreak;\n\t\t\tcase COMMAND_IS_PLAYER_IN_ANGLED_AREA_ON_FOOT_2D:\n\t\t\tcase COMMAND_IS_PLAYER_IN_ANGLED_AREA_ON_FOOT_3D:\n\t\t\tcase COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_ON_FOOT_2D:\n\t\t\tcase COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_ON_FOOT_3D:\n\t\t\t\tresult = !pPlayerInfo->m_pPed->bInVehicle;\n\t\t\t\tbreak;\n\t\t\tcase COMMAND_IS_PLAYER_IN_ANGLED_AREA_IN_CAR_2D:\n\t\t\tcase COMMAND_IS_PLAYER_IN_ANGLED_AREA_IN_CAR_3D:\n\t\t\tcase COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_IN_CAR_2D:\n\t\t\tcase COMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_IN_CAR_3D:\n\t\t\t\tresult = pPlayerInfo->m_pPed->bInVehicle;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tscript_assert(false);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\tUpdateCompareFlag(result);\n\tif (debug)\n\t\tCTheScripts::HighlightImportantAngledArea((uintptr)this + m_nIp, infX, infY, supX, supY,\n\t\t\trotatedSupX, rotatedSupY, rotatedInfX, rotatedInfY, b3D ? (infZ + supZ) / 2 : MAP_Z_LOW_LIMIT);\n\tif (CTheScripts::DbgFlag) {\n\t\tif (b3D)\n\t\t\tCTheScripts::DrawDebugAngledCube(infX, infY, infZ, supX, supY, supZ,\n\t\t\t\trotatedSupX, rotatedSupY, rotatedInfX, rotatedInfY);\n\t\telse\n\t\t\tCTheScripts::DrawDebugAngledSquare(infX, infY, supX, supY,\n\t\t\t\trotatedSupX, rotatedSupY, rotatedInfX, rotatedInfY);\n\t}\n}\n\nvoid CRunningScript::CharInAreaCheckCommand(int32 command, uint32* pIp)\n{\n\tbool b3D, result, debug, decided = false;\n\tfloat infX, infY, infZ, supX, supY, supZ;\n\tswitch (command) {\n\tcase COMMAND_IS_CHAR_IN_AREA_3D:\n\tcase COMMAND_IS_CHAR_IN_AREA_ON_FOOT_3D:\n\tcase COMMAND_IS_CHAR_IN_AREA_IN_CAR_3D:\n\tcase COMMAND_IS_CHAR_STOPPED_IN_AREA_3D:\n\tcase COMMAND_IS_CHAR_STOPPED_IN_AREA_ON_FOOT_3D:\n\tcase COMMAND_IS_CHAR_STOPPED_IN_AREA_IN_CAR_3D:\n\t\tb3D = true;\n\t\tbreak;\n\tdefault:\n\t\tb3D = false;\n\t\tbreak;\n\t}\n\tCollectParameters(pIp, b3D ? 8 : 6);\n\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\tscript_assert(pPed);\n\tCVector pos = pPed->InVehicle() ? pPed->m_pMyVehicle->GetPosition() : pPed->GetPosition();\n\tswitch (command) {\n\tcase COMMAND_IS_CHAR_STOPPED_IN_AREA_3D:\n\tcase COMMAND_IS_CHAR_STOPPED_IN_AREA_ON_FOOT_3D:\n\tcase COMMAND_IS_CHAR_STOPPED_IN_AREA_IN_CAR_3D:\n\tcase COMMAND_IS_CHAR_STOPPED_IN_AREA_2D:\n\tcase COMMAND_IS_CHAR_STOPPED_IN_AREA_ON_FOOT_2D:\n\tcase COMMAND_IS_CHAR_STOPPED_IN_AREA_IN_CAR_2D:\n\t\tif (!CTheScripts::IsPedStopped(pPed)) {\n\t\t\tresult = false;\n\t\t\tdecided = true;\n\t\t}\n\t\tbreak;\n\tdefault:\n\t\tbreak;\n\t}\n\tinfX = *(float*)&ScriptParams[1];\n\tinfY = *(float*)&ScriptParams[2];\n\tif (b3D) {\n\t\tinfZ = *(float*)&ScriptParams[3];\n\t\tsupX = *(float*)&ScriptParams[4];\n\t\tsupY = *(float*)&ScriptParams[5];\n\t\tsupZ = *(float*)&ScriptParams[6];\n\t\tif (infZ > supZ) {\n\t\t\tinfZ = *(float*)&ScriptParams[6];\n\t\t\tsupZ = *(float*)&ScriptParams[3];\n\t\t}\n\t\tdebug = ScriptParams[7];\n\t}\n\telse {\n\t\tsupX = *(float*)&ScriptParams[3];\n\t\tsupY = *(float*)&ScriptParams[4];\n\t\tdebug = ScriptParams[5];\n\t}\n\tif (infX > supX) {\n\t\tfloat tmp = infX;\n\t\tinfX = supX;\n\t\tsupX = tmp;\n\t}\n\tif (infY > supY) {\n\t\tfloat tmp = infY;\n\t\tinfY = supY;\n\t\tsupY = tmp;\n\t}\n\tif (!decided) {\n\t\tresult = false;\n\t\tbool in_area;\n\t\tif (b3D) {\n\t\t\tin_area = infX <= pos.x &&\n\t\t\t\tsupX >= pos.x &&\n\t\t\t\tinfY <= pos.y &&\n\t\t\t\tsupY >= pos.y &&\n\t\t\t\tinfZ <= pos.z &&\n\t\t\t\tsupZ >= pos.z;\n\t\t}\n\t\telse {\n\t\t\tin_area = infX <= pos.x &&\n\t\t\t\tsupX >= pos.x &&\n\t\t\t\tinfY <= pos.y &&\n\t\t\t\tsupY >= pos.y;\n\t\t}\n\t\tif (in_area) {\n\t\t\tswitch (command) {\n\t\t\tcase COMMAND_IS_CHAR_IN_AREA_2D:\n\t\t\tcase COMMAND_IS_CHAR_IN_AREA_3D:\n\t\t\tcase COMMAND_IS_CHAR_STOPPED_IN_AREA_2D:\n\t\t\tcase COMMAND_IS_CHAR_STOPPED_IN_AREA_3D:\n\t\t\t\tresult = true;\n\t\t\t\tbreak;\n\t\t\tcase COMMAND_IS_CHAR_IN_AREA_ON_FOOT_2D:\n\t\t\tcase COMMAND_IS_CHAR_IN_AREA_ON_FOOT_3D:\n\t\t\tcase COMMAND_IS_CHAR_STOPPED_IN_AREA_ON_FOOT_2D:\n\t\t\tcase COMMAND_IS_CHAR_STOPPED_IN_AREA_ON_FOOT_3D:\n\t\t\t\tresult = !pPed->bInVehicle;\n\t\t\t\tbreak;\n\t\t\tcase COMMAND_IS_CHAR_IN_AREA_IN_CAR_2D:\n\t\t\tcase COMMAND_IS_CHAR_IN_AREA_IN_CAR_3D:\n\t\t\tcase COMMAND_IS_CHAR_STOPPED_IN_AREA_IN_CAR_2D:\n\t\t\tcase COMMAND_IS_CHAR_STOPPED_IN_AREA_IN_CAR_3D:\n\t\t\t\tresult = pPed->bInVehicle;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tscript_assert(false);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\tUpdateCompareFlag(result);\n\tif (debug)\n\t\tCTheScripts::HighlightImportantArea((uintptr)this + m_nIp, infX, infY, supX, supY, b3D ? (infZ + supZ) / 2 : MAP_Z_LOW_LIMIT);\n\tif (CTheScripts::DbgFlag) {\n\t\tif (b3D)\n\t\t\tCTheScripts::DrawDebugCube(infX, infY, infZ, supX, supY, supZ);\n\t\telse\n\t\t\tCTheScripts::DrawDebugSquare(infX, infY, supX, supY);\n\t}\n}\n\nvoid CRunningScript::CarInAreaCheckCommand(int32 command, uint32* pIp)\n{\n\tbool b3D, result, debug, decided = false;\n\tfloat infX, infY, infZ, supX, supY, supZ;\n\tswitch (command) {\n\tcase COMMAND_IS_CAR_IN_AREA_3D:\n\tcase COMMAND_IS_CAR_STOPPED_IN_AREA_3D:\n\t\tb3D = true;\n\t\tbreak;\n\tdefault:\n\t\tb3D = false;\n\t\tbreak;\n\t}\n\tCollectParameters(pIp, b3D ? 8 : 6);\n\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\tscript_assert(pVehicle);\n\tCVector pos = pVehicle->GetPosition();\n\tswitch (command) {\n\tcase COMMAND_IS_CAR_STOPPED_IN_AREA_3D:\n\tcase COMMAND_IS_CAR_STOPPED_IN_AREA_2D:\n\t\tif (!CTheScripts::IsVehicleStopped(pVehicle)) {\n\t\t\tresult = false;\n\t\t\tdecided = true;\n\t\t}\n\t\tbreak;\n\tdefault:\n\t\tbreak;\n\t}\n\tinfX = *(float*)&ScriptParams[1];\n\tinfY = *(float*)&ScriptParams[2];\n\tif (b3D) {\n\t\tinfZ = *(float*)&ScriptParams[3];\n\t\tsupX = *(float*)&ScriptParams[4];\n\t\tsupY = *(float*)&ScriptParams[5];\n\t\tsupZ = *(float*)&ScriptParams[6];\n\t\tif (infZ > supZ) {\n\t\t\tinfZ = *(float*)&ScriptParams[6];\n\t\t\tsupZ = *(float*)&ScriptParams[3];\n\t\t}\n\t\tdebug = ScriptParams[7];\n\t}\n\telse {\n\t\tsupX = *(float*)&ScriptParams[3];\n\t\tsupY = *(float*)&ScriptParams[4];\n\t\tdebug = ScriptParams[5];\n\t}\n\tif (infX > supX) {\n\t\tfloat tmp = infX;\n\t\tinfX = supX;\n\t\tsupX = tmp;\n\t}\n\tif (infY > supY) {\n\t\tfloat tmp = infY;\n\t\tinfY = supY;\n\t\tsupY = tmp;\n\t}\n\tif (!decided) {\n\t\tresult = false;\n\t\tbool in_area;\n\t\tif (b3D) {\n\t\t\tin_area = infX <= pos.x &&\n\t\t\t\tsupX >= pos.x &&\n\t\t\t\tinfY <= pos.y &&\n\t\t\t\tsupY >= pos.y &&\n\t\t\t\tinfZ <= pos.z &&\n\t\t\t\tsupZ >= pos.z;\n\t\t}\n\t\telse {\n\t\t\tin_area = infX <= pos.x &&\n\t\t\t\tsupX >= pos.x &&\n\t\t\t\tinfY <= pos.y &&\n\t\t\t\tsupY >= pos.y;\n\t\t}\n\t\tif (in_area) {\n\t\t\tswitch (command) {\n\t\t\tcase COMMAND_IS_CAR_IN_AREA_2D:\n\t\t\tcase COMMAND_IS_CAR_IN_AREA_3D:\n\t\t\tcase COMMAND_IS_CAR_STOPPED_IN_AREA_2D:\n\t\t\tcase COMMAND_IS_CAR_STOPPED_IN_AREA_3D:\n\t\t\t\tresult = true;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tscript_assert(false);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\tUpdateCompareFlag(result);\n\tif (debug)\n\t\tCTheScripts::HighlightImportantArea((uintptr)this + m_nIp, infX, infY, supX, supY, b3D ? (infZ + supZ) / 2 : MAP_Z_LOW_LIMIT);\n\tif (CTheScripts::DbgFlag) {\n\t\tif (b3D)\n\t\t\tCTheScripts::DrawDebugCube(infX, infY, infZ, supX, supY, supZ);\n\t\telse\n\t\t\tCTheScripts::DrawDebugSquare(infX, infY, supX, supY);\n\t}\n}\n\nvoid CRunningScript::ObjectInAreaCheckCommand(int32 command, uint32* pIp)\n{\n\tbool b3D, result, debug;\n\tfloat infX, infY, infZ, supX, supY, supZ;\n\tswitch (command) {\n\tcase COMMAND_IS_OBJECT_IN_AREA_3D:\n\t\tb3D = true;\n\t\tbreak;\n\tdefault:\n\t\tb3D = false;\n\t\tbreak;\n\t}\n\tCollectParameters(pIp, b3D ? 8 : 6);\n\tCObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);\n\tscript_assert(pObject);\n\tCVector pos = pObject->GetPosition();\n\tinfX = *(float*)&ScriptParams[1];\n\tinfY = *(float*)&ScriptParams[2];\n\tif (b3D) {\n\t\tinfZ = *(float*)&ScriptParams[3];\n\t\tsupX = *(float*)&ScriptParams[4];\n\t\tsupY = *(float*)&ScriptParams[5];\n\t\tsupZ = *(float*)&ScriptParams[6];\n\t\tif (infZ > supZ) {\n\t\t\tinfZ = *(float*)&ScriptParams[6];\n\t\t\tsupZ = *(float*)&ScriptParams[3];\n\t\t}\n\t\tdebug = ScriptParams[7];\n\t}\n\telse {\n\t\tsupX = *(float*)&ScriptParams[3];\n\t\tsupY = *(float*)&ScriptParams[4];\n\t\tdebug = ScriptParams[5];\n\t}\n\tif (infX > supX) {\n\t\tfloat tmp = infX;\n\t\tinfX = supX;\n\t\tsupX = tmp;\n\t}\n\tif (infY > supY) {\n\t\tfloat tmp = infY;\n\t\tinfY = supY;\n\t\tsupY = tmp;\n\t}\n\tresult = false;\n\tbool in_area;\n\tif (b3D) {\n\t\tin_area = infX <= pos.x &&\n\t\t\tsupX >= pos.x &&\n\t\t\tinfY <= pos.y &&\n\t\t\tsupY >= pos.y &&\n\t\t\tinfZ <= pos.z &&\n\t\t\tsupZ >= pos.z;\n\t}\n\telse {\n\t\tin_area = infX <= pos.x &&\n\t\t\tsupX >= pos.x &&\n\t\t\tinfY <= pos.y &&\n\t\t\tsupY >= pos.y;\n\t}\n\tif (in_area) {\n\t\tswitch (command) {\n\t\tcase COMMAND_IS_OBJECT_IN_AREA_2D:\n\t\tcase COMMAND_IS_OBJECT_IN_AREA_3D:\n\t\t\tresult = true;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tscript_assert(false);\n\t\t\tbreak;\n\t\t}\n\t}\n\tUpdateCompareFlag(result);\n\tif (debug)\n\t\tCTheScripts::HighlightImportantArea((uintptr)this + m_nIp, infX, infY, supX, supY, b3D ? (infZ + supZ) / 2 : MAP_Z_LOW_LIMIT);\n\tif (CTheScripts::DbgFlag) {\n\t\tif (b3D)\n\t\t\tCTheScripts::DrawDebugCube(infX, infY, infZ, supX, supY, supZ);\n\t\telse\n\t\t\tCTheScripts::DrawDebugSquare(infX, infY, supX, supY);\n\t}\n}\n\nvoid CRunningScript::DoDeatharrestCheck()\n{\n\tif (!m_bDeatharrestEnabled)\n\t\treturn;\n\tif (!CTheScripts::IsPlayerOnAMission())\n\t\treturn;\n\tCPlayerInfo* pPlayer = &CWorld::Players[CWorld::PlayerInFocus];\n\tif (!pPlayer->IsRestartingAfterDeath() && !pPlayer->IsRestartingAfterArrest())\n\t\treturn;\n#ifdef MISSION_REPLAY\n\tif (AllowMissionReplay != 0)\n\t\treturn;\n\tif (CanAllowMissionReplay())\n\t\tAllowMissionReplay = 1;\n#endif\n\tscript_assert(m_nStackPointer > 0);\n\twhile (m_nStackPointer > 1)\n\t\t--m_nStackPointer;\n\tm_nIp = m_anStack[--m_nStackPointer];\n\tCMessages::ClearSmallMessagesOnly();\n\t*(int32*)&CTheScripts::ScriptSpace[CTheScripts::OnAMissionFlag] = 0;\n\tm_bDeatharrestExecuted = true;\n\tm_nWakeTime = 0;\n}\n\nint16 CRunningScript::GetPadState(uint16 pad, uint16 button)\n{\n\tCPad* pPad = CPad::GetPad(pad);\n\tswitch (button) {\n\tcase 0: return pPad->NewState.LeftStickX;\n\tcase 1: return pPad->NewState.LeftStickY;\n\tcase 2: return pPad->NewState.RightStickX;\n\tcase 3: return pPad->NewState.RightStickY;\n\tcase 4: return pPad->NewState.LeftShoulder1;\n\tcase 5: return pPad->NewState.LeftShoulder2;\n\tcase 6: return pPad->NewState.RightShoulder1;\n\tcase 7: return pPad->NewState.RightShoulder2;\n\tcase 8: return pPad->NewState.DPadUp;\n\tcase 9: return pPad->NewState.DPadDown;\n\tcase 10: return pPad->NewState.DPadLeft;\n\tcase 11: return pPad->NewState.DPadRight;\n\tcase 12: return pPad->NewState.Start;\n\tcase 13: return pPad->NewState.Select;\n\tcase 14: return pPad->NewState.Square;\n\tcase 15: return pPad->NewState.Triangle;\n\tcase 16: return pPad->NewState.Cross;\n\tcase 17: return pPad->NewState.Circle;\n\tcase 18: return pPad->NewState.LeftShock;\n\tcase 19: return pPad->NewState.RightShock;\n\tdefault: break;\n\t}\n\treturn 0;\n}\n\n#ifdef GTA_SCRIPT_COLLECTIVE\nvoid CRunningScript::LocateCollectiveCommand(int32 command, uint32* pIp)\n{\n\tbool b3D, result, debug, decided = false;\n\tfloat X, Y, Z, dX, dY, dZ;\n\tswitch (command) {\n\tcase COMMAND_LOCATE_COLL_ANY_MEANS_2D:\n\tcase COMMAND_LOCATE_COLL_ON_FOOT_2D:\n\tcase COMMAND_LOCATE_COLL_IN_CAR_2D:\n\tcase COMMAND_LOCATE_STOPPED_COLL_ANY_MEANS_2D:\n\tcase COMMAND_LOCATE_STOPPED_COLL_ON_FOOT_2D:\n\tcase COMMAND_LOCATE_STOPPED_COLL_IN_CAR_2D:\n\t\tb3D = false;\n\t\tbreak;\n\tdefault:\n\t\tb3D = true;\n\t\tbreak;\n\t}\n\tCollectParameters(pIp, b3D ? 8 : 6);\n\tX = *(float*)&ScriptParams[1];\n\tY = *(float*)&ScriptParams[2];\n\tif (b3D) {\n\t\tZ = *(float*)&ScriptParams[3];\n\t\tdX = *(float*)&ScriptParams[4];\n\t\tdY = *(float*)&ScriptParams[5];\n\t\tdZ = *(float*)&ScriptParams[6];\n\t\tdebug = ScriptParams[7];\n\t}\n\telse {\n\t\tdX = *(float*)&ScriptParams[3];\n\t\tdY = *(float*)&ScriptParams[4];\n\t\tdebug = ScriptParams[5];\n\t}\n\tresult = true;\n\tfor (int i = 0; i < MAX_NUM_COLLECTIVES && result; i++) {\n\t\tif (ScriptParams[0] != CTheScripts::CollectiveArray[i].colIndex)\n\t\t\tcontinue;\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(CTheScripts::CollectiveArray[i].pedIndex);\n\t\tif (!pPed) {\n\t\t\tCTheScripts::CollectiveArray[i].colIndex = -1;\n\t\t\tCTheScripts::CollectiveArray[i].pedIndex = 0;\n\t\t\tcontinue;\n\t\t}\n\t\tCVector pos = pPed->bInVehicle ? pPed->m_pMyVehicle->GetPosition() : pPed->GetPosition();\n\t\tswitch (command) {\n\t\tcase COMMAND_LOCATE_STOPPED_COLL_ANY_MEANS_2D:\n\t\tcase COMMAND_LOCATE_STOPPED_COLL_ON_FOOT_2D:\n\t\tcase COMMAND_LOCATE_STOPPED_COLL_IN_CAR_2D:\n\t\t\tif (!CTheScripts::IsPedStopped(pPed)) {\n\t\t\t\tresult = false;\n\t\t\t\tdecided = true;\n\t\t\t}\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\t\tif (!decided) {\n\t\t\tbool in_area;\n\t\t\tif (b3D) {\n\t\t\t\tin_area = X - dX <= pos.x &&\n\t\t\t\t\tX + dX >= pos.x &&\n\t\t\t\t\tY - dY <= pos.y &&\n\t\t\t\t\tY + dY >= pos.y &&\n\t\t\t\t\tZ - dZ <= pos.z &&\n\t\t\t\t\tZ + dZ >= pos.z;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tin_area = X - dX <= pos.x &&\n\t\t\t\t\tX + dX >= pos.x &&\n\t\t\t\t\tY - dY <= pos.y &&\n\t\t\t\t\tY + dY >= pos.y;\n\t\t\t}\n\t\t\tresult = false;\n\t\t\tif (in_area) {\n\t\t\t\tswitch (command) {\n\t\t\t\tcase COMMAND_LOCATE_COLL_ANY_MEANS_2D:\n\t\t\t\tcase COMMAND_LOCATE_STOPPED_COLL_ANY_MEANS_2D:\n\t\t\t\t\tresult = true;\n\t\t\t\t\tbreak;\n\t\t\t\tcase COMMAND_LOCATE_COLL_ON_FOOT_2D:\n\t\t\t\tcase COMMAND_LOCATE_STOPPED_COLL_ON_FOOT_2D:\n\t\t\t\t\tresult = !pPed->bInVehicle;\n\t\t\t\t\tbreak;\n\t\t\t\tcase COMMAND_LOCATE_COLL_IN_CAR_2D:\n\t\t\t\tcase COMMAND_LOCATE_STOPPED_COLL_IN_CAR_2D:\n\t\t\t\t\tresult = pPed->bInVehicle;\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tscript_assert(false);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tUpdateCompareFlag(result);\n\tif (debug)\n\t\tCTheScripts::HighlightImportantArea((uintptr)this + m_nIp, X - dX, Y - dY, X + dX, Y + dY, b3D ? Z : MAP_Z_LOW_LIMIT);\n\tif (CTheScripts::DbgFlag) {\n\t\tif (b3D)\n\t\t\tCTheScripts::DrawDebugCube(X - dX, Y - dY, Z - dZ, X + dX, Y + dY, Z + dZ);\n\t\telse\n\t\t\tCTheScripts::DrawDebugSquare(X - dX, Y - dY, X + dX, Y + dY);\n\t}\n}\n\nvoid CRunningScript::LocateCollectiveCharCommand(int32 command, uint32* pIp)\n{\n\tbool b3D, result, debug;\n\tfloat X, Y, Z, dX, dY, dZ;\n\tswitch (command) {\n\tcase COMMAND_LOCATE_COLL_ANY_MEANS_CHAR_2D:\n\tcase COMMAND_LOCATE_COLL_ON_FOOT_CHAR_2D:\n\tcase COMMAND_LOCATE_COLL_IN_CAR_CHAR_2D:\n\t\tb3D = false;\n\t\tbreak;\n\tdefault:\n\t\tb3D = true;\n\t\tbreak;\n\t}\n\tCollectParameters(pIp, b3D ? 6 : 5);\n\tCPed* pTarget = CPools::GetPedPool()->GetAt(ScriptParams[1]);\n\tscript_assert(pTarget);\n\tif (pTarget->bInVehicle) {\n\t\tX = pTarget->m_pMyVehicle->GetPosition().x;\n\t\tY = pTarget->m_pMyVehicle->GetPosition().y;\n\t\tZ = pTarget->m_pMyVehicle->GetPosition().z;\n\t}\n\telse {\n\t\tX = pTarget->GetPosition().x;\n\t\tY = pTarget->GetPosition().y;\n\t\tZ = pTarget->GetPosition().z;\n\t}\n\tdX = *(float*)&ScriptParams[2];\n\tdY = *(float*)&ScriptParams[3];\n\tif (b3D) {\n\t\tdZ = *(float*)&ScriptParams[4];\n\t\tdebug = ScriptParams[5];\n\t}\n\telse {\n\t\tdebug = ScriptParams[4];\n\t}\n\tresult = true;\n\tfor (int i = 0; i < MAX_NUM_COLLECTIVES && result; i++) {\n\t\tif (ScriptParams[0] != CTheScripts::CollectiveArray[i].colIndex)\n\t\t\tcontinue;\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(CTheScripts::CollectiveArray[i].pedIndex);\n\t\tif (!pPed) {\n\t\t\tCTheScripts::CollectiveArray[i].colIndex = -1;\n\t\t\tCTheScripts::CollectiveArray[i].pedIndex = 0;\n\t\t\tcontinue;\n\t\t}\n\t\tCVector pos = pPed->bInVehicle ? pPed->m_pMyVehicle->GetPosition() : pPed->GetPosition();\n\t\tbool in_area;\n\t\tif (b3D) {\n\t\t\tin_area = X - dX <= pos.x &&\n\t\t\t\tX + dX >= pos.x &&\n\t\t\t\tY - dY <= pos.y &&\n\t\t\t\tY + dY >= pos.y &&\n\t\t\t\tZ - dZ <= pos.z &&\n\t\t\t\tZ + dZ >= pos.z;\n\t\t}\n\t\telse {\n\t\t\tin_area = X - dX <= pos.x &&\n\t\t\t\tX + dX >= pos.x &&\n\t\t\t\tY - dY <= pos.y &&\n\t\t\t\tY + dY >= pos.y;\n\t\t}\n\t\tresult = false;\n\t\tif (in_area) {\n\t\t\tswitch (command) {\n\t\t\tcase COMMAND_LOCATE_COLL_ANY_MEANS_CHAR_2D:\n\t\t\t\tresult = true;\n\t\t\t\tbreak;\n\t\t\tcase COMMAND_LOCATE_COLL_ON_FOOT_CHAR_2D:\n\t\t\t\tresult = !pPed->bInVehicle;\n\t\t\t\tbreak;\n\t\t\tcase COMMAND_LOCATE_COLL_IN_CAR_CHAR_2D:\n\t\t\t\tresult = pPed->bInVehicle;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tscript_assert(false);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\tUpdateCompareFlag(result);\n\tif (debug)\n\t\tCTheScripts::HighlightImportantArea((uintptr)this + m_nIp, X - dX, Y - dY, X + dX, Y + dY, b3D ? Z : MAP_Z_LOW_LIMIT);\n\tif (CTheScripts::DbgFlag) {\n\t\tif (b3D)\n\t\t\tCTheScripts::DrawDebugCube(X - dX, Y - dY, Z - dZ, X + dX, Y + dY, Z + dZ);\n\t\telse\n\t\t\tCTheScripts::DrawDebugSquare(X - dX, Y - dY, X + dX, Y + dY);\n\t}\n}\n\nvoid CRunningScript::LocateCollectiveCarCommand(int32 command, uint32* pIp)\n{\n\tbool b3D, result, debug;\n\tfloat X, Y, Z, dX, dY, dZ;\n\tswitch (command) {\n\tcase COMMAND_LOCATE_COLL_ANY_MEANS_CAR_2D:\n\tcase COMMAND_LOCATE_COLL_ON_FOOT_CAR_2D:\n\tcase COMMAND_LOCATE_COLL_IN_CAR_CAR_2D:\n\t\tb3D = false;\n\t\tbreak;\n\tdefault:\n\t\tb3D = true;\n\t\tbreak;\n\t}\n\tCollectParameters(pIp, b3D ? 6 : 5);\n\tCVehicle* pTarget = CPools::GetVehiclePool()->GetAt(ScriptParams[1]);\n\tscript_assert(pTarget);\n\tX = pTarget->GetPosition().x;\n\tY = pTarget->GetPosition().y;\n\tZ = pTarget->GetPosition().z;\n\tdX = *(float*)&ScriptParams[2];\n\tdY = *(float*)&ScriptParams[3];\n\tif (b3D) {\n\t\tdZ = *(float*)&ScriptParams[4];\n\t\tdebug = ScriptParams[5];\n\t}\n\telse {\n\t\tdebug = ScriptParams[4];\n\t}\n\tresult = true;\n\tfor (int i = 0; i < MAX_NUM_COLLECTIVES && result; i++) {\n\t\tif (ScriptParams[0] != CTheScripts::CollectiveArray[i].colIndex)\n\t\t\tcontinue;\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(CTheScripts::CollectiveArray[i].pedIndex);\n\t\tif (!pPed) {\n\t\t\tCTheScripts::CollectiveArray[i].colIndex = -1;\n\t\t\tCTheScripts::CollectiveArray[i].pedIndex = 0;\n\t\t\tcontinue;\n\t\t}\n\t\tCVector pos = pPed->bInVehicle ? pPed->m_pMyVehicle->GetPosition() : pPed->GetPosition();\n\t\tbool in_area;\n\t\tif (b3D) {\n\t\t\tin_area = X - dX <= pos.x &&\n\t\t\t\tX + dX >= pos.x &&\n\t\t\t\tY - dY <= pos.y &&\n\t\t\t\tY + dY >= pos.y &&\n\t\t\t\tZ - dZ <= pos.z &&\n\t\t\t\tZ + dZ >= pos.z;\n\t\t}\n\t\telse {\n\t\t\tin_area = X - dX <= pos.x &&\n\t\t\t\tX + dX >= pos.x &&\n\t\t\t\tY - dY <= pos.y &&\n\t\t\t\tY + dY >= pos.y;\n\t\t}\n\t\tresult = false;\n\t\tif (in_area) {\n\t\t\tswitch (command) {\n\t\t\tcase COMMAND_LOCATE_COLL_ANY_MEANS_CAR_2D:\n\t\t\t\tresult = true;\n\t\t\t\tbreak;\n\t\t\tcase COMMAND_LOCATE_COLL_ON_FOOT_CAR_2D:\n\t\t\t\tresult = !pPed->bInVehicle;\n\t\t\t\tbreak;\n\t\t\tcase COMMAND_LOCATE_COLL_IN_CAR_CAR_2D:\n\t\t\t\tresult = pPed->bInVehicle;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tscript_assert(false);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\tUpdateCompareFlag(result);\n\tif (debug)\n\t\tCTheScripts::HighlightImportantArea((uintptr)this + m_nIp, X - dX, Y - dY, X + dX, Y + dY, b3D ? Z : MAP_Z_LOW_LIMIT);\n\tif (CTheScripts::DbgFlag) {\n\t\tif (b3D)\n\t\t\tCTheScripts::DrawDebugCube(X - dX, Y - dY, Z - dZ, X + dX, Y + dY, Z + dZ);\n\t\telse\n\t\t\tCTheScripts::DrawDebugSquare(X - dX, Y - dY, X + dX, Y + dY);\n\t}\n}\n\nvoid CRunningScript::LocateCollectivePlayerCommand(int32 command, uint32* pIp)\n{\n\tbool b3D, result, debug;\n\tfloat X, Y, Z, dX, dY, dZ;\n\tswitch (command) {\n\tcase COMMAND_LOCATE_COLL_ANY_MEANS_PLAYER_2D:\n\tcase COMMAND_LOCATE_COLL_ON_FOOT_PLAYER_2D:\n\tcase COMMAND_LOCATE_COLL_IN_CAR_PLAYER_2D:\n\t\tb3D = false;\n\t\tbreak;\n\tdefault:\n\t\tb3D = true;\n\t\tbreak;\n\t}\n\tCollectParameters(pIp, b3D ? 6 : 5);\n\tCVector pos = CWorld::Players[ScriptParams[1]].GetPos();\n\tX = pos.x;\n\tY = pos.y;\n\tZ = pos.z;\n\tdX = *(float*)&ScriptParams[2];\n\tdY = *(float*)&ScriptParams[3];\n\tif (b3D) {\n\t\tdZ = *(float*)&ScriptParams[4];\n\t\tdebug = ScriptParams[5];\n\t}\n\telse {\n\t\tdebug = ScriptParams[4];\n\t}\n\tresult = true;\n\tfor (int i = 0; i < MAX_NUM_COLLECTIVES && result; i++) {\n\t\tif (ScriptParams[0] != CTheScripts::CollectiveArray[i].colIndex)\n\t\t\tcontinue;\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(CTheScripts::CollectiveArray[i].pedIndex);\n\t\tif (!pPed) {\n\t\t\tCTheScripts::CollectiveArray[i].colIndex = -1;\n\t\t\tCTheScripts::CollectiveArray[i].pedIndex = 0;\n\t\t\tcontinue;\n\t\t}\n\t\tCVector pos = pPed->bInVehicle ? pPed->m_pMyVehicle->GetPosition() : pPed->GetPosition();\n\t\tbool in_area;\n\t\tif (b3D) {\n\t\t\tin_area = X - dX <= pos.x &&\n\t\t\t\tX + dX >= pos.x &&\n\t\t\t\tY - dY <= pos.y &&\n\t\t\t\tY + dY >= pos.y &&\n\t\t\t\tZ - dZ <= pos.z &&\n\t\t\t\tZ + dZ >= pos.z;\n\t\t}\n\t\telse {\n\t\t\tin_area = X - dX <= pos.x &&\n\t\t\t\tX + dX >= pos.x &&\n\t\t\t\tY - dY <= pos.y &&\n\t\t\t\tY + dY >= pos.y;\n\t\t}\n\t\tresult = false;\n\t\tif (in_area) {\n\t\t\tswitch (command) {\n\t\t\tcase COMMAND_LOCATE_COLL_ANY_MEANS_PLAYER_2D:\n\t\t\t\tresult = true;\n\t\t\t\tbreak;\n\t\t\tcase COMMAND_LOCATE_COLL_ON_FOOT_PLAYER_2D:\n\t\t\t\tresult = !pPed->bInVehicle;\n\t\t\t\tbreak;\n\t\t\tcase COMMAND_LOCATE_COLL_IN_CAR_PLAYER_2D:\n\t\t\t\tresult = pPed->bInVehicle;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tscript_assert(false);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\tUpdateCompareFlag(result);\n\tif (debug)\n\t\tCTheScripts::HighlightImportantArea((uintptr)this + m_nIp, X - dX, Y - dY, X + dX, Y + dY, b3D ? Z : MAP_Z_LOW_LIMIT);\n\tif (CTheScripts::DbgFlag) {\n\t\tif (b3D)\n\t\t\tCTheScripts::DrawDebugCube(X - dX, Y - dY, Z - dZ, X + dX, Y + dY, Z + dZ);\n\t\telse\n\t\t\tCTheScripts::DrawDebugSquare(X - dX, Y - dY, X + dX, Y + dY);\n\t}\n}\n\nvoid CRunningScript::CollectiveInAreaCheckCommand(int32 command, uint32* pIp)\n{\n\tbool b3D, result, debug, decided = false;\n\tfloat infX, infY, infZ, supX, supY, supZ;\n\tswitch (command) {\n\tcase COMMAND_IS_COLL_IN_AREA_2D:\n\tcase COMMAND_IS_COLL_IN_AREA_ON_FOOT_2D:\n\tcase COMMAND_IS_COLL_IN_AREA_IN_CAR_2D:\n\tcase COMMAND_IS_COLL_STOPPED_IN_AREA_2D:\n\tcase COMMAND_IS_COLL_STOPPED_IN_AREA_ON_FOOT_2D:\n\tcase COMMAND_IS_COLL_STOPPED_IN_AREA_IN_CAR_2D:\n\t\tb3D = false;\n\t\tbreak;\n\tdefault:\n\t\tb3D = true;\n\t\tbreak;\n\t}\n\tCollectParameters(pIp, b3D ? 8 : 6);\n\tinfX = *(float*)&ScriptParams[1];\n\tinfY = *(float*)&ScriptParams[2];\n\tif (b3D) {\n\t\tinfZ = *(float*)&ScriptParams[3];\n\t\tsupX = *(float*)&ScriptParams[4];\n\t\tsupY = *(float*)&ScriptParams[5];\n\t\tsupZ = *(float*)&ScriptParams[6];\n\t\tif (infZ > supZ) {\n\t\t\tinfZ = *(float*)&ScriptParams[6];\n\t\t\tsupZ = *(float*)&ScriptParams[3];\n\t\t}\n\t\tdebug = ScriptParams[7];\n\t}\n\telse {\n\t\tsupX = *(float*)&ScriptParams[3];\n\t\tsupY = *(float*)&ScriptParams[4];\n\t\tdebug = ScriptParams[5];\n\t}\n\tif (infX > supX) {\n\t\tfloat tmp = infX;\n\t\tinfX = supX;\n\t\tsupX = tmp;\n\t}\n\tif (infY > supY) {\n\t\tfloat tmp = infY;\n\t\tinfY = supY;\n\t\tsupY = tmp;\n\t}\n\tresult = true;\n\tfor (int i = 0; i < MAX_NUM_COLLECTIVES && result; i++) {\n\t\tif (ScriptParams[0] != CTheScripts::CollectiveArray[i].colIndex)\n\t\t\tcontinue;\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(CTheScripts::CollectiveArray[i].pedIndex);\n\t\tif (!pPed) {\n\t\t\tCTheScripts::CollectiveArray[i].colIndex = -1;\n\t\t\tCTheScripts::CollectiveArray[i].pedIndex = 0;\n\t\t\tcontinue;\n\t\t}\n\t\tCVector pos = pPed->bInVehicle ? pPed->m_pMyVehicle->GetPosition() : pPed->GetPosition();\n\t\tswitch (command) {\n\t\tcase COMMAND_IS_COLL_STOPPED_IN_AREA_2D:\n\t\tcase COMMAND_IS_COLL_STOPPED_IN_AREA_ON_FOOT_2D:\n\t\tcase COMMAND_IS_COLL_STOPPED_IN_AREA_IN_CAR_2D:\n\t\t\tif (!CTheScripts::IsPedStopped(pPed)) {\n\t\t\t\tresult = false;\n\t\t\t\tdecided = true;\n\t\t\t}\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\t\tif (!decided) {\n\t\t\tbool in_area;\n\t\t\tif (b3D) {\n\t\t\t\tin_area = infX <= pos.x &&\n\t\t\t\t\tsupX >= pos.x &&\n\t\t\t\t\tinfY <= pos.y &&\n\t\t\t\t\tsupY >= pos.y &&\n\t\t\t\t\tinfZ <= pos.z &&\n\t\t\t\t\tsupZ >= pos.z;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tin_area = infX <= pos.x &&\n\t\t\t\t\tsupX >= pos.x &&\n\t\t\t\t\tinfY <= pos.y &&\n\t\t\t\t\tsupY >= pos.y;\n\t\t\t}\n\t\t\tresult = false;\n\t\t\tif (in_area) {\n\t\t\t\tswitch (command) {\n\t\t\t\tcase COMMAND_IS_COLL_IN_AREA_2D:\n\t\t\t\tcase COMMAND_IS_COLL_STOPPED_IN_AREA_2D:\n\t\t\t\t\tresult = true;\n\t\t\t\t\tbreak;\n\t\t\t\tcase COMMAND_IS_COLL_IN_AREA_ON_FOOT_2D:\n\t\t\t\tcase COMMAND_IS_COLL_STOPPED_IN_AREA_ON_FOOT_2D:\n\t\t\t\t\tresult = !pPed->bInVehicle;\n\t\t\t\t\tbreak;\n\t\t\t\tcase COMMAND_IS_COLL_IN_AREA_IN_CAR_2D:\n\t\t\t\tcase COMMAND_IS_COLL_STOPPED_IN_AREA_IN_CAR_2D:\n\t\t\t\t\tresult = pPed->bInVehicle;\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tscript_assert(false);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tUpdateCompareFlag(result);\n\tif (debug)\n\t\tCTheScripts::HighlightImportantArea((uintptr)this + m_nIp, infX, infY, supX, supY, b3D ? (infZ + supZ) / 2 : MAP_Z_LOW_LIMIT);\n\tif (CTheScripts::DbgFlag) {\n\t\tif (b3D)\n\t\t\tCTheScripts::DrawDebugCube(infX, infY, infZ, supX, supY, supZ);\n\t\telse\n\t\t\tCTheScripts::DrawDebugSquare(infX, infY, supX, supY);\n\t}\n}\n#endif\n\nbool CRunningScript::CheckDamagedWeaponType(int32 actual, int32 type)\n{\n\tif (actual == -1)\n\t\treturn false;\n\n\tif (type == WEAPONTYPE_ANYMELEE) {\n\t\tif (actual <= WEAPONTYPE_CHAINSAW)\n\t\t\treturn true;\n\t\tif (actual - WEAPONTYPE_GRENADE <= WEAPONTYPE_MINIGUN)\n\t\t\treturn false;\n\t\treturn false;\n\t}\n\n\tif (type != WEAPONTYPE_ANYWEAPON)\n\t\treturn false;\n\n\tswitch (actual) {\n\tcase WEAPONTYPE_UNARMED:\n\tcase WEAPONTYPE_BRASSKNUCKLE:\n\tcase WEAPONTYPE_SCREWDRIVER:\n\tcase WEAPONTYPE_GOLFCLUB:\n\tcase WEAPONTYPE_NIGHTSTICK:\n\tcase WEAPONTYPE_KNIFE:\n\tcase WEAPONTYPE_BASEBALLBAT:\n\tcase WEAPONTYPE_HAMMER:\n\tcase WEAPONTYPE_CLEAVER:\n\tcase WEAPONTYPE_MACHETE:\n\tcase WEAPONTYPE_KATANA:\n\tcase WEAPONTYPE_CHAINSAW:\n\tcase WEAPONTYPE_GRENADE:\n\tcase WEAPONTYPE_DETONATOR_GRENADE:\n\tcase WEAPONTYPE_TEARGAS:\n\tcase WEAPONTYPE_MOLOTOV:\n\tcase WEAPONTYPE_ROCKET:\n\tcase WEAPONTYPE_COLT45:\n\tcase WEAPONTYPE_PYTHON:\n\tcase WEAPONTYPE_SHOTGUN:\n\tcase WEAPONTYPE_SPAS12_SHOTGUN:\n\tcase WEAPONTYPE_STUBBY_SHOTGUN:\n\tcase WEAPONTYPE_TEC9:\n\tcase WEAPONTYPE_UZI:\n\tcase WEAPONTYPE_SILENCED_INGRAM:\n\tcase WEAPONTYPE_MP5:\n\tcase WEAPONTYPE_M4:\n\tcase WEAPONTYPE_RUGER:\n\tcase WEAPONTYPE_SNIPERRIFLE:\n\tcase WEAPONTYPE_LASERSCOPE:\n\tcase WEAPONTYPE_ROCKETLAUNCHER:\n\tcase WEAPONTYPE_FLAMETHROWER:\n\tcase WEAPONTYPE_M60:\n\tcase WEAPONTYPE_MINIGUN:\n\tcase WEAPONTYPE_DETONATOR:\n\tcase WEAPONTYPE_HELICANNON:\n\tcase WEAPONTYPE_CAMERA:\n\tcase WEAPONTYPE_EXPLOSION:\n\tcase WEAPONTYPE_UZI_DRIVEBY:\n\t\treturn true;\n\tcase WEAPONTYPE_HEALTH:\n\tcase WEAPONTYPE_ARMOUR:\n\tcase WEAPONTYPE_RAMMEDBYCAR:\n\tcase WEAPONTYPE_RUNOVERBYCAR:\n\tcase WEAPONTYPE_DROWNING:\n\tcase WEAPONTYPE_FALL:\n\tcase WEAPONTYPE_UNIDENTIFIED:\n\t\treturn false;\n\t}\n\n\treturn false;\n}\n\nvoid CTheScripts::PrintListSizes()\n{\n\tint active = 0;\n\tint idle = 0;\n\n\tfor (CRunningScript* pScript = pActiveScripts; pScript; pScript = pScript->GetNext())\n\t\tactive++;\n\tfor (CRunningScript* pScript = pIdleScripts; pScript; pScript = pScript->GetNext())\n\t\tidle++;\n\n\tdebug(\"active: %d, idle: %d\", active, idle);\n}\n\nuint32 DbgLineColour = 0x0000FFFF; // r = 0, g = 0, b = 255, a = 255\n\nvoid CTheScripts::DrawDebugSquare(float infX, float infY, float supX, float supY)\n{\n\tCColPoint tmpCP;\n\tCEntity* tmpEP;\n\tCVector p1, p2, p3, p4;\n\tp1 = CVector(infX, infY, -1000.0f);\n\tCWorld::ProcessVerticalLine(p1, 1000.0f, tmpCP, tmpEP, true, false, false, false, true, false, nil);\n\tp1.z = 2.0f + tmpCP.point.z;\n\tp2 = CVector(supX, supY, -1000.0f);\n\tCWorld::ProcessVerticalLine(p2, 1000.0f, tmpCP, tmpEP, true, false, false, false, true, false, nil);\n\tp2.z = 2.0f + tmpCP.point.z;\n\tp3 = CVector(infX, supY, -1000.0f);\n\tCWorld::ProcessVerticalLine(p3, 1000.0f, tmpCP, tmpEP, true, false, false, false, true, false, nil);\n\tp3.z = 2.0f + tmpCP.point.z;\n\tp4 = CVector(supX, infY, -1000.0f);\n\tCWorld::ProcessVerticalLine(p4, 1000.0f, tmpCP, tmpEP, true, false, false, false, true, false, nil);\n\tp4.z = 2.0f + tmpCP.point.z;\n\tCTheScripts::ScriptDebugLine3D(p1.x, p1.y, p1.z, p2.x, p2.y, p2.z, DbgLineColour, DbgLineColour);\n\tCTheScripts::ScriptDebugLine3D(p2.x, p2.y, p2.z, p3.x, p3.y, p3.z, DbgLineColour, DbgLineColour);\n\tCTheScripts::ScriptDebugLine3D(p3.x, p3.y, p3.z, p4.x, p4.y, p4.z, DbgLineColour, DbgLineColour);\n\tCTheScripts::ScriptDebugLine3D(p4.x, p4.y, p4.z, p1.x, p1.y, p1.z, DbgLineColour, DbgLineColour);\n}\n\nvoid CTheScripts::DrawDebugAngledSquare(float infX, float infY, float supX, float supY, float rotSupX, float rotSupY, float rotInfX, float rotInfY)\n{\n\tCColPoint tmpCP;\n\tCEntity* tmpEP;\n\tCVector p1, p2, p3, p4;\n\tp1 = CVector(infX, infY, -1000.0f);\n\tCWorld::ProcessVerticalLine(p1, 1000.0f, tmpCP, tmpEP, true, false, false, false, true, false, nil);\n\tp1.z = 2.0f + tmpCP.point.z;\n\tp2 = CVector(supX, supY, -1000.0f);\n\tCWorld::ProcessVerticalLine(p2, 1000.0f, tmpCP, tmpEP, true, false, false, false, true, false, nil);\n\tp2.z = 2.0f + tmpCP.point.z;\n\tp3 = CVector(rotSupX, rotSupY, -1000.0f);\n\tCWorld::ProcessVerticalLine(p3, 1000.0f, tmpCP, tmpEP, true, false, false, false, true, false, nil);\n\tp3.z = 2.0f + tmpCP.point.z;\n\tp4 = CVector(rotInfX, rotInfY, -1000.0f);\n\tCWorld::ProcessVerticalLine(p4, 1000.0f, tmpCP, tmpEP, true, false, false, false, true, false, nil);\n\tp4.z = 2.0f + tmpCP.point.z;\n\tCTheScripts::ScriptDebugLine3D(p1.x, p1.y, p1.z, p2.x, p2.y, p2.z, DbgLineColour, DbgLineColour);\n\tCTheScripts::ScriptDebugLine3D(p2.x, p2.y, p2.z, p3.x, p3.y, p3.z, DbgLineColour, DbgLineColour);\n\tCTheScripts::ScriptDebugLine3D(p3.x, p3.y, p3.z, p4.x, p4.y, p4.z, DbgLineColour, DbgLineColour);\n\tCTheScripts::ScriptDebugLine3D(p4.x, p4.y, p4.z, p1.x, p1.y, p1.z, DbgLineColour, DbgLineColour);\n}\n\nvoid CTheScripts::DrawDebugCube(float infX, float infY, float infZ, float supX, float supY, float supZ)\n{\n\tCTheScripts::ScriptDebugLine3D(infX, infY, infZ, supX, infY, infZ, DbgLineColour, DbgLineColour);\n\tCTheScripts::ScriptDebugLine3D(supX, infY, infZ, supX, supY, infZ, DbgLineColour, DbgLineColour);\n\tCTheScripts::ScriptDebugLine3D(supX, supY, infZ, infX, supY, infZ, DbgLineColour, DbgLineColour);\n\tCTheScripts::ScriptDebugLine3D(infX, supY, infZ, infX, infY, infZ, DbgLineColour, DbgLineColour);\n\tCTheScripts::ScriptDebugLine3D(infX, infY, supZ, supX, infY, supZ, DbgLineColour, DbgLineColour);\n\tCTheScripts::ScriptDebugLine3D(supX, infY, supZ, supX, supY, supZ, DbgLineColour, DbgLineColour);\n\tCTheScripts::ScriptDebugLine3D(supX, supY, supZ, infX, supY, supZ, DbgLineColour, DbgLineColour);\n\tCTheScripts::ScriptDebugLine3D(infX, supY, supZ, infX, infY, supZ, DbgLineColour, DbgLineColour);\n\tCTheScripts::ScriptDebugLine3D(infX, infY, supZ, infX, infY, infZ, DbgLineColour, DbgLineColour);\n\tCTheScripts::ScriptDebugLine3D(supX, infY, supZ, supX, infY, infZ, DbgLineColour, DbgLineColour);\n\tCTheScripts::ScriptDebugLine3D(supX, supY, supZ, supX, supY, infZ, DbgLineColour, DbgLineColour);\n\tCTheScripts::ScriptDebugLine3D(infX, supY, supZ, infX, supY, infZ, DbgLineColour, DbgLineColour);\n}\n\nvoid CTheScripts::DrawDebugAngledCube(float infX, float infY, float infZ, float supX, float supY, float supZ, float rotSupX, float rotSupY, float rotInfX, float rotInfY)\n{\n\tCTheScripts::ScriptDebugLine3D(infX, infY, infZ, supX, infY, infZ, DbgLineColour, DbgLineColour);\n\tCTheScripts::ScriptDebugLine3D(supX, infY, infZ, rotSupX, rotSupY, infZ, DbgLineColour, DbgLineColour);\n\tCTheScripts::ScriptDebugLine3D(rotSupX, rotSupY, infZ, rotInfX, rotInfY, infZ, DbgLineColour, DbgLineColour);\n\tCTheScripts::ScriptDebugLine3D(rotInfX, rotInfY, infZ, infX, infY, infZ, DbgLineColour, DbgLineColour);\n\tCTheScripts::ScriptDebugLine3D(infX, infY, supZ, supX, infY, supZ, DbgLineColour, DbgLineColour);\n\tCTheScripts::ScriptDebugLine3D(supX, infY, supZ, rotSupX, rotSupY, supZ, DbgLineColour, DbgLineColour);\n\tCTheScripts::ScriptDebugLine3D(rotSupX, rotSupY, rotInfX, rotInfY, supY, supZ, DbgLineColour, DbgLineColour);\n\tCTheScripts::ScriptDebugLine3D(rotInfX, rotInfY, supZ, infX, infY, supZ, DbgLineColour, DbgLineColour);\n\tCTheScripts::ScriptDebugLine3D(infX, infY, supZ, infX, infY, infZ, DbgLineColour, DbgLineColour);\n\tCTheScripts::ScriptDebugLine3D(supX, infY, supZ, supX, infY, infZ, DbgLineColour, DbgLineColour);\n\tCTheScripts::ScriptDebugLine3D(rotSupX, rotSupY, supZ, rotSupX, rotSupY, infZ, DbgLineColour, DbgLineColour);\n\tCTheScripts::ScriptDebugLine3D(rotInfX, rotInfY, supZ, rotInfX, rotInfY, infZ, DbgLineColour, DbgLineColour);\n}\n\nvoid CTheScripts::ScriptDebugLine3D(float x1, float y1, float z1, float x2, float y2, float z2, uint32 col, uint32 col2)\n{\n\tif (NumScriptDebugLines >= MAX_NUM_STORED_LINES)\n\t\treturn;\n\taStoredLines[NumScriptDebugLines].vecInf = CVector(x1, y1, z1);\n\taStoredLines[NumScriptDebugLines].vecSup = CVector(x2, y2, z2);\n\taStoredLines[NumScriptDebugLines].color1 = col;\n\taStoredLines[NumScriptDebugLines++].color2 = col2;\n}\n\nvoid CTheScripts::RenderTheScriptDebugLines()\n{\n\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)1);\n\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)1);\n\tfor (int i = 0; i < NumScriptDebugLines; i++) {\n\t\tCLines::RenderLineWithClipping(\n\t\t\taStoredLines[i].vecInf.x,\n\t\t\taStoredLines[i].vecInf.y,\n\t\t\taStoredLines[i].vecInf.z,\n\t\t\taStoredLines[i].vecSup.x,\n\t\t\taStoredLines[i].vecSup.y,\n\t\t\taStoredLines[i].vecSup.z,\n\t\t\taStoredLines[i].color1,\n\t\t\taStoredLines[i].color2);\n\t}\n\tNumScriptDebugLines = 0;\n\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)0);\n}\n\n#define SCRIPT_DATA_SIZE sizeof(CTheScripts::OnAMissionFlag) +\\\n\t4 * sizeof(uint32) * MAX_NUM_BUILDING_SWAPS + 2 * sizeof(uint32) * MAX_NUM_INVISIBILITY_SETTINGS + 5 * sizeof(uint32)\n\nvoid CTheScripts::SaveAllScripts(uint8* buf, uint32* size)\n{\nINITSAVEBUF\n\tuint32 varSpace = GetSizeOfVariableSpace();\n\tuint32 runningScripts = 0;\n\tfor (CRunningScript* pScript = pActiveScripts; pScript; pScript = pScript->GetNext())\n\t\trunningScripts++;\n\t*size = CRunningScript::nSaveStructSize * runningScripts + varSpace + SCRIPT_DATA_SIZE + SAVE_HEADER_SIZE + 3 * sizeof(uint32);\n\tWriteSaveHeader(buf, 'S', 'C', 'R', '\\0', *size - SAVE_HEADER_SIZE);\n\tWriteSaveBuf(buf, varSpace);\n\tfor (uint32 i = 0; i < varSpace; i++)\n\t\tWriteSaveBuf(buf, ScriptSpace[i]);\n#ifdef CHECK_STRUCT_SIZES\n\tstatic_assert(SCRIPT_DATA_SIZE == 968, \"CTheScripts::SaveAllScripts\");\n#endif\n\tuint32 script_data_size = SCRIPT_DATA_SIZE;\n\tWriteSaveBuf(buf, script_data_size);\n\tWriteSaveBuf(buf, OnAMissionFlag);\n\tWriteSaveBuf(buf, LastMissionPassedTime);\n\tfor (uint32 i = 0; i < MAX_NUM_BUILDING_SWAPS; i++) {\n\t\tCBuilding* pBuilding = BuildingSwapArray[i].m_pBuilding;\n\t\tuint32 type, handle;\n\t\tif (!pBuilding) {\n\t\t\ttype = 0;\n\t\t\thandle = 0;\n\t\t} else if (pBuilding->GetIsATreadable()) {\n\t\t\ttype = 1;\n\t\t\thandle = CPools::GetTreadablePool()->GetJustIndex_NoFreeAssert((CTreadable*)pBuilding) + 1;\n\t\t} else {\n\t\t\ttype = 2;\n\t\t\thandle = CPools::GetBuildingPool()->GetJustIndex_NoFreeAssert(pBuilding) + 1;\n\t\t}\n\t\tWriteSaveBuf(buf, type);\n\t\tWriteSaveBuf(buf, handle);\n\t\tWriteSaveBuf(buf, BuildingSwapArray[i].m_nNewModel);\n\t\tWriteSaveBuf(buf, BuildingSwapArray[i].m_nOldModel);\n\t}\n\tfor (uint32 i = 0; i < MAX_NUM_INVISIBILITY_SETTINGS; i++) {\n\t\tCEntity* pEntity = InvisibilitySettingArray[i];\n\t\tuint32 type, handle;\n\t\tif (!pEntity) {\n\t\t\ttype = 0;\n\t\t\thandle = 0;\n\t\t} else {\n\t\t\tswitch (pEntity->GetType()) {\n\t\t\tcase ENTITY_TYPE_BUILDING:\n\t\t\t\tif (((CBuilding*)pEntity)->GetIsATreadable()) {\n\t\t\t\t\ttype = 1;\n\t\t\t\t\thandle = CPools::GetTreadablePool()->GetJustIndex_NoFreeAssert((CTreadable*)pEntity) + 1;\n\t\t\t\t} else {\n\t\t\t\t\ttype = 2;\n\t\t\t\t\thandle = CPools::GetBuildingPool()->GetJustIndex_NoFreeAssert((CBuilding*)pEntity) + 1;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase ENTITY_TYPE_OBJECT:\n\t\t\t\ttype = 3;\n\t\t\t\thandle = CPools::GetObjectPool()->GetJustIndex_NoFreeAssert((CObject*)pEntity) + 1;\n\t\t\t\tbreak;\n\t\t\tcase ENTITY_TYPE_DUMMY:\n\t\t\t\ttype = 4;\n\t\t\t\thandle = CPools::GetDummyPool()->GetJustIndex_NoFreeAssert((CDummy*)pEntity) + 1;\n\t\t\tdefault: break;\n\t\t\t}\n\t\t}\n\t\tWriteSaveBuf(buf, type);\n\t\tWriteSaveBuf(buf, handle);\n\t}\n\tWriteSaveBuf(buf, bUsingAMultiScriptFile);\n\tWriteSaveBuf(buf, bPlayerHasMetDebbieHarry);\n\tWriteSaveBuf(buf, (uint16)0);\n\tWriteSaveBuf(buf, MainScriptSize);\n\tWriteSaveBuf(buf, LargestMissionScriptSize);\n\tWriteSaveBuf(buf, NumberOfMissionScripts);\n\tWriteSaveBuf(buf, NumberOfExclusiveMissionScripts);\n\tWriteSaveBuf(buf, runningScripts);\n\tfor (CRunningScript* pScript = pActiveScripts; pScript; pScript = pScript->GetNext())\n\t\tpScript->Save(buf);\nVALIDATESAVEBUF(*size)\n}\n\nvoid CTheScripts::LoadAllScripts(uint8* buf, uint32 size)\n{\n\tInit();\nINITSAVEBUF\n\tCheckSaveHeader(buf, 'S', 'C', 'R', '\\0', size - SAVE_HEADER_SIZE);\n\tuint32 varSpace = ReadSaveBuf<uint32>(buf);\n\tfor (uint32 i = 0; i < varSpace; i++)\n\t\tScriptSpace[i] = ReadSaveBuf<uint8>(buf);\n\tscript_assert(ReadSaveBuf<uint32>(buf) == SCRIPT_DATA_SIZE);\n\tOnAMissionFlag = ReadSaveBuf<uint32>(buf);\n\tLastMissionPassedTime = ReadSaveBuf<uint32>(buf);\n\tfor (uint32 i = 0; i < MAX_NUM_BUILDING_SWAPS; i++) {\n\t\tuint32 type = ReadSaveBuf<uint32>(buf);\n\t\tuint32 handle = ReadSaveBuf<uint32>(buf);\n\t\tswitch (type) {\n\t\tcase 0:\n\t\t\tBuildingSwapArray[i].m_pBuilding = nil;\n\t\t\tbreak;\n\t\tcase 1:\n\t\t\tBuildingSwapArray[i].m_pBuilding = CPools::GetTreadablePool()->GetSlot(handle - 1);\n\t\t\tbreak;\n\t\tcase 2:\n\t\t\tBuildingSwapArray[i].m_pBuilding = CPools::GetBuildingPool()->GetSlot(handle - 1);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tscript_assert(false);\n\t\t}\n\t\tBuildingSwapArray[i].m_nNewModel = ReadSaveBuf<uint32>(buf);\n\t\tBuildingSwapArray[i].m_nOldModel = ReadSaveBuf<uint32>(buf);\n\t\tif (BuildingSwapArray[i].m_pBuilding)\n\t\t\tBuildingSwapArray[i].m_pBuilding->ReplaceWithNewModel(BuildingSwapArray[i].m_nNewModel);\n\t}\n\tfor (uint32 i = 0; i < MAX_NUM_INVISIBILITY_SETTINGS; i++) {\n\t\tuint32 type = ReadSaveBuf<uint32>(buf);\n\t\tuint32 handle = ReadSaveBuf<uint32>(buf);\n\t\tswitch (type) {\n\t\tcase 0:\n\t\t\tInvisibilitySettingArray[i] = nil;\n\t\t\tbreak;\n\t\tcase 1:\n\t\t\tInvisibilitySettingArray[i] = CPools::GetTreadablePool()->GetSlot(handle - 1);\n\t\t\tbreak;\n\t\tcase 2:\n\t\t\tInvisibilitySettingArray[i] = CPools::GetBuildingPool()->GetSlot(handle - 1);\n\t\t\tbreak;\n\t\tcase 3:\n\t\t\tInvisibilitySettingArray[i] = CPools::GetObjectPool()->GetSlot(handle - 1);\n\t\t\tbreak;\n\t\tcase 4:\n\t\t\tInvisibilitySettingArray[i] = CPools::GetDummyPool()->GetSlot(handle - 1);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tscript_assert(false);\n\t\t}\n\t\tif (InvisibilitySettingArray[i])\n\t\t\tInvisibilitySettingArray[i]->bIsVisible = false;\n\t}\n\tscript_assert(ReadSaveBuf<bool>(buf) == bUsingAMultiScriptFile);\n\tbPlayerHasMetDebbieHarry = ReadSaveBuf<uint8>(buf);\n\tReadSaveBuf<uint16>(buf);\n\tscript_assert(ReadSaveBuf<uint32>(buf) == MainScriptSize);\n\tscript_assert(ReadSaveBuf<uint32>(buf) == LargestMissionScriptSize);\n\tscript_assert(ReadSaveBuf<uint16>(buf) == NumberOfMissionScripts);\n\tscript_assert(ReadSaveBuf<uint16>(buf) == NumberOfExclusiveMissionScripts);\n\tuint32 runningScripts = ReadSaveBuf<uint32>(buf);\n\tfor (uint32 i = 0; i < runningScripts; i++)\n\t\tStartNewScript(0)->Load(buf);\nVALIDATESAVEBUF(size)\n}\n\n#undef SCRIPT_DATA_SIZE\n\nvoid CRunningScript::Save(uint8*& buf)\n{\n#ifdef COMPATIBLE_SAVES\n\tSkipSaveBuf(buf, 8);\n\tfor (int i = 0; i < 8; i++)\n\t\tWriteSaveBuf<char>(buf, m_abScriptName[i]);\n\tWriteSaveBuf<uint32>(buf, m_nIp);\n#ifdef CHECK_STRUCT_SIZES\n\tstatic_assert(MAX_STACK_DEPTH == 6, \"Compatibility loss: MAX_STACK_DEPTH != 6\");\n#endif\n\tfor (int i = 0; i < MAX_STACK_DEPTH; i++)\n\t\tWriteSaveBuf<uint32>(buf, m_anStack[i]);\n\tWriteSaveBuf<uint16>(buf, m_nStackPointer);\n\tSkipSaveBuf(buf, 2);\n#ifdef CHECK_STRUCT_SIZES\n\tstatic_assert(NUM_LOCAL_VARS + NUM_TIMERS == 18, \"Compatibility loss: NUM_LOCAL_VARS + NUM_TIMERS != 18\");\n#endif\n\tfor (int i = 0; i < NUM_LOCAL_VARS + NUM_TIMERS; i++)\n\t\tWriteSaveBuf<int32>(buf, m_anLocalVariables[i]);\n\tWriteSaveBuf<bool>(buf, m_bIsActive);\n\tWriteSaveBuf<bool>(buf, m_bCondResult);\n\tWriteSaveBuf<bool>(buf, m_bIsMissionScript);\n\tWriteSaveBuf<bool>(buf, m_bSkipWakeTime);\n\tWriteSaveBuf<uint32>(buf, m_nWakeTime);\n\tWriteSaveBuf<uint16>(buf, m_nAndOrState);\n\tWriteSaveBuf<bool>(buf, m_bNotFlag);\n\tWriteSaveBuf<bool>(buf, m_bDeatharrestEnabled);\n\tWriteSaveBuf<bool>(buf, m_bDeatharrestExecuted);\n\tWriteSaveBuf<bool>(buf, m_bMissionFlag);\n\tSkipSaveBuf(buf, 2);\n#else\n\tWriteSaveBuf(buf, *this);\n#endif\n}\n\nvoid CRunningScript::Load(uint8*& buf)\n{\n#ifdef COMPATIBLE_SAVES\n\tSkipSaveBuf(buf, 8);\n\tfor (int i = 0; i < 8; i++)\n\t\tm_abScriptName[i] = ReadSaveBuf<char>(buf);\n\tm_nIp = ReadSaveBuf<uint32>(buf);\n#ifdef CHECK_STRUCT_SIZES\n\tstatic_assert(MAX_STACK_DEPTH == 6, \"Compatibility loss: MAX_STACK_DEPTH != 6\");\n#endif\n\tfor (int i = 0; i < MAX_STACK_DEPTH; i++)\n\t\tm_anStack[i] = ReadSaveBuf<uint32>(buf);\n\tm_nStackPointer = ReadSaveBuf<uint16>(buf);\n\tSkipSaveBuf(buf, 2);\n#ifdef CHECK_STRUCT_SIZES\n\tstatic_assert(NUM_LOCAL_VARS + NUM_TIMERS == 18, \"Compatibility loss: NUM_LOCAL_VARS + NUM_TIMERS != 18\");\n#endif\n\tfor (int i = 0; i < NUM_LOCAL_VARS + NUM_TIMERS; i++)\n\t\tm_anLocalVariables[i] = ReadSaveBuf<int32>(buf);\n\tm_bIsActive = ReadSaveBuf<bool>(buf);\n\tm_bCondResult = ReadSaveBuf<bool>(buf);\n\tm_bIsMissionScript = ReadSaveBuf<bool>(buf);\n\tm_bSkipWakeTime = ReadSaveBuf<bool>(buf);\n\tm_nWakeTime = ReadSaveBuf<uint32>(buf);\n\tm_nAndOrState = ReadSaveBuf<uint16>(buf);\n\tm_bNotFlag = ReadSaveBuf<bool>(buf);\n\tm_bDeatharrestEnabled = ReadSaveBuf<bool>(buf);\n\tm_bDeatharrestExecuted = ReadSaveBuf<bool>(buf);\n\tm_bMissionFlag = ReadSaveBuf<bool>(buf);\n\tSkipSaveBuf(buf, 2);\n#else\n\tCRunningScript* n = next;\n\tCRunningScript* p = prev;\n\t*this = ReadSaveBuf<CRunningScript>(buf);\n\tnext = n;\n\tprev = p;\n#endif\n}\n\nvoid CTheScripts::ClearSpaceForMissionEntity(const CVector& pos, CEntity* pEntity)\n{\n\tstatic CColPoint aTempColPoints[MAX_COLLISION_POINTS];\n\tint16 entities = 0;\n\tCEntity* aEntities[16];\n\tCWorld::FindObjectsKindaColliding(pos, pEntity->GetBoundRadius(), false, &entities, 16, aEntities, false, true, true, false, false);\n\tif (entities <= 0)\n\t\treturn;\n\tfor (uint16 i = 0; i < entities; i++) {\n\t\tif (aEntities[i] != pEntity && aEntities[i]->IsPed() && ((CPed*)aEntities[i])->bInVehicle)\n\t\t\taEntities[i] = nil;\n\t}\n\tfor (uint16 i = 0; i < entities; i++) {\n\t\tif (aEntities[i] == pEntity || !aEntities[i])\n\t\t\tcontinue;\n\t\tCEntity* pFound = aEntities[i];\n\t\tint cols;\n\t\tif (pEntity->GetColModel()->numLines <= 0)\n\t\t\tcols = CCollision::ProcessColModels(pEntity->GetMatrix(), *pEntity->GetColModel(),\n\t\t\t\tpFound->GetMatrix(), *pFound->GetColModel(), aTempColPoints, nil, nil);\n\t\telse {\n\t\t\tfloat lines[4];\n\t\t\tlines[0] = lines[1] = lines[2] = lines[3] = 1.0f;\n\t\t\tCColPoint tmp[4];\n\t\t\tcols = CCollision::ProcessColModels(pEntity->GetMatrix(), *pEntity->GetColModel(),\n\t\t\t\tpFound->GetMatrix(), *pFound->GetColModel(), aTempColPoints,tmp, lines);\n\t\t}\n\t\tif (cols <= 0)\n\t\t\tcontinue;\n\t\tswitch (pFound->GetType()) {\n\t\tcase ENTITY_TYPE_VEHICLE:\n\t\t{\n\t\t\tprintf(\"Will try to delete a vehicle where a mission entity should be\\n\");\n\t\t\tCVehicle* pVehicle = (CVehicle*)pFound;\n\t\t\tif (pVehicle->bIsLocked || !pVehicle->CanBeDeleted())\n\t\t\t\tbreak;\n\t\t\tif (pVehicle->pDriver) {\n\t\t\t\tCPopulation::RemovePed(pVehicle->pDriver);\n\t\t\t\tpVehicle->pDriver = nil;\n\t\t\t}\n\t\t\tfor (int i = 0; i < pVehicle->m_nNumMaxPassengers; i++) {\n\t\t\t\tif (pVehicle->pPassengers[i]) {\n\t\t\t\t\tCPopulation::RemovePed(pVehicle->pPassengers[i]);\n\t\t\t\t\tpVehicle->pPassengers[i] = 0;\n\t\t\t\t\tpVehicle->m_nNumPassengers--;\n\t\t\t\t}\n\t\t\t}\n\t\t\tCCarCtrl::RemoveFromInterestingVehicleList(pVehicle);\n\t\t\tCWorld::Remove(pVehicle);\n\t\t\tdelete pVehicle;\n\t\t\tbreak;\n\t\t}\n\t\tcase ENTITY_TYPE_PED:\n\t\t{\n\t\t\tCPed* pPed = (CPed*)pFound;\n\t\t\tif (pPed->IsPlayer() || !pPed->CanBeDeleted())\n\t\t\t\tbreak;\n\t\t\tCPopulation::RemovePed(pPed);\n\t\t\tprintf(\"Deleted a ped where a mission entity should be\\n\");\n\t\t\tbreak;\n\t\t}\n\t\tdefault: break;\n\t\t}\n\t}\n}\n\nvoid CTheScripts::HighlightImportantArea(uint32 id, float x1, float y1, float x2, float y2, float z)\n{\n\tfloat infX, infY, supX, supY;\n\tif (x1 < x2) {\n\t\tinfX = x1;\n\t\tsupX = x2;\n\t} else {\n\t\tinfX = x2;\n\t\tsupX = x1;\n\t}\n\tif (y1 < y2) {\n\t\tinfY = y1;\n\t\tsupY = y2;\n\t}\n\telse {\n\t\tinfY = y2;\n\t\tsupY = y1;\n\t}\n\tCVector center;\n\tcenter.x = (infX + supX) / 2;\n\tcenter.y = (infY + supY) / 2;\n\tcenter.z = (z <= MAP_Z_LOW_LIMIT) ? CWorld::FindGroundZForCoord(center.x, center.y) : z;\n\tCShadows::RenderIndicatorShadow(id, 2, gpGoalTex, &center, supX - center.x, 0.0f, 0.0f, center.y - supY, 0);\n}\n\nvoid CTheScripts::HighlightImportantAngledArea(uint32 id, float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4, float z)\n{\n\tfloat infX, infY, supX, supY, X, Y;\n\tX = (x1 + x2) / 2;\n\tY = (y1 + y2) / 2;\n\tsupX = infX = X;\n\tsupY = infY = Y;\n\tX = (x2 + x3) / 2;\n\tY = (y2 + y3) / 2;\n\tinfX = Min(infX, X);\n\tsupX = Max(supX, X);\n\tinfY = Min(infY, Y);\n\tsupY = Max(supY, Y);\n\tX = (x3 + x4) / 2;\n\tY = (y3 + y4) / 2;\n\tinfX = Min(infX, X);\n\tsupX = Max(supX, X);\n\tinfY = Min(infY, Y);\n\tsupY = Max(supY, Y);\n\tX = (x4 + x1) / 2;\n\tY = (y4 + y1) / 2;\n\tinfX = Min(infX, X);\n\tsupX = Max(supX, X);\n\tinfY = Min(infY, Y);\n\tsupY = Max(supY, Y);\n\tCVector center;\n\tcenter.x = (infX + supX) / 2;\n\tcenter.y = (infY + supY) / 2;\n\tcenter.z = (z <= MAP_Z_LOW_LIMIT) ? CWorld::FindGroundZForCoord(center.x, center.y) : z;\n\tCShadows::RenderIndicatorShadow(id, 2, gpGoalTex, &center, supX - center.x, 0.0f, 0.0f, center.y - supY, 0);\n}\n\n#ifdef GTA_SCRIPT_COLLECTIVE\nint CTheScripts::AddPedsInVehicleToCollective(int index)\n{\n\tint colIndex = NextFreeCollectiveIndex;\n\tAdvanceCollectiveIndex();\n\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(index);\n\tscript_assert(pVehicle);\n\tCPed* pDriver = pVehicle->pDriver;\n\tif (pDriver && !pDriver->IsPlayer() && pDriver->CharCreatedBy != MISSION_CHAR && pDriver->m_nPedType != PEDTYPE_COP) {\n\t\tint index = FindFreeSlotInCollectiveArray();\n\t\tif (index > -1) {\n\t\t\tCollectiveArray[index].colIndex = colIndex;\n\t\t\tCollectiveArray[index].pedIndex = CPools::GetPedPool()->GetIndex(pDriver);\n\t\t}\n\t}\n\tfor (int i = 0; i < pVehicle->m_nNumMaxPassengers; i++) {\n\t\tCPed* pPassenger = pVehicle->pPassengers[i];\n\t\tif (pPassenger && !pPassenger->IsPlayer() && pPassenger->CharCreatedBy != MISSION_CHAR && pPassenger->m_nPedType != PEDTYPE_COP) {\n\t\t\tint index = FindFreeSlotInCollectiveArray();\n\t\t\tif (index > -1) {\n\t\t\t\tCollectiveArray[index].colIndex = colIndex;\n\t\t\t\tCollectiveArray[index].pedIndex = CPools::GetPedPool()->GetIndex(pPassenger);\n\t\t\t}\n\t\t}\n\t}\n\treturn colIndex;\n}\n\nint CTheScripts::AddPedsInAreaToCollective(float x, float y, float z, float radius)\n{\n\tint16 numFound;\n\tCEntity* pEntities[64];\n\tint colIndex = NextFreeCollectiveIndex;\n\tAdvanceCollectiveIndex();\n\tCWorld::FindObjectsInRange(CVector(x, y, z), radius, true, &numFound, 64, pEntities, false, true, true, false, false);\n\tfor (int16 i = 0; i < numFound; i++) {\n\t\tif (pEntities[i]->GetType() == ENTITY_TYPE_PED) {\n\t\t\tCPed* pPed = (CPed*)pEntities[i];\n\t\t\tif (pPed && !pPed->IsPlayer() && pPed->CharCreatedBy != MISSION_CHAR && pPed->m_nPedType != PEDTYPE_COP) {\n\t\t\t\tint index = FindFreeSlotInCollectiveArray();\n\t\t\t\tif (index > -1) {\n\t\t\t\t\tCollectiveArray[index].colIndex = colIndex;\n\t\t\t\t\tCollectiveArray[index].pedIndex = CPools::GetPedPool()->GetIndex(pPed);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse if (pEntities[i]->GetType() == ENTITY_TYPE_VEHICLE) {\n\t\t\tCVehicle* pVehicle = (CVehicle*)pEntities[i];\n\t\t\tCPed* pDriver = pVehicle->pDriver;\n\t\t\tif (pDriver && !pDriver->IsPlayer() && pDriver->CharCreatedBy != MISSION_CHAR && pDriver->m_nPedType != PEDTYPE_COP) {\n\t\t\t\tint index = FindFreeSlotInCollectiveArray();\n\t\t\t\tif (index > -1) {\n\t\t\t\t\tCollectiveArray[index].colIndex = colIndex;\n\t\t\t\t\tCollectiveArray[index].pedIndex = CPools::GetPedPool()->GetIndex(pDriver);\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (int i = 0; i < pVehicle->m_nNumMaxPassengers; i++) {\n\t\t\t\tCPed* pPassenger = pVehicle->pPassengers[i];\n\t\t\t\tif (pPassenger && !pPassenger->IsPlayer() && pPassenger->CharCreatedBy != MISSION_CHAR && pPassenger->m_nPedType != PEDTYPE_COP) {\n\t\t\t\t\tint index = FindFreeSlotInCollectiveArray();\n\t\t\t\t\tif (index > -1) {\n\t\t\t\t\t\tCollectiveArray[index].colIndex = colIndex;\n\t\t\t\t\t\tCollectiveArray[index].pedIndex = CPools::GetPedPool()->GetIndex(pPassenger);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn colIndex;\n}\n\nint CTheScripts::FindFreeSlotInCollectiveArray()\n{\n\tfor (int i = 0; i < MAX_NUM_COLLECTIVES; i++) {\n\t\tif (CollectiveArray[i].colIndex == -1)\n\t\t\treturn i;\n\t}\n\treturn -1;\n}\n\nvoid CTheScripts::SetObjectiveForAllPedsInCollective(int colIndex, eObjective objective, int16 p1, int16 p2)\n{\n\tfor (int i = 0; i < MAX_NUM_COLLECTIVES; i++) {\n\t\tif (CollectiveArray[i].colIndex == colIndex) {\n\t\t\tCPed* pPed = CPools::GetPedPool()->GetAt(CollectiveArray[i].pedIndex);\n\t\t\tif (pPed == nil) {\n\t\t\t\tCollectiveArray[i].colIndex = -1;\n\t\t\t\tCollectiveArray[i].pedIndex = 0;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tpPed->bScriptObjectiveCompleted = false;\n\t\t\t\tpPed->SetObjective(objective, p1, p2);\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid CTheScripts::SetObjectiveForAllPedsInCollective(int colIndex, eObjective objective, CVector p1, float p2)\n{\n\tfor (int i = 0; i < MAX_NUM_COLLECTIVES; i++) {\n\t\tif (CollectiveArray[i].colIndex == colIndex) {\n\t\t\tCPed* pPed = CPools::GetPedPool()->GetAt(CollectiveArray[i].pedIndex);\n\t\t\tif (pPed == nil) {\n\t\t\t\tCollectiveArray[i].colIndex = -1;\n\t\t\t\tCollectiveArray[i].pedIndex = 0;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tpPed->bScriptObjectiveCompleted = false;\n\t\t\t\tpPed->SetObjective(objective, p1, p2);\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid CTheScripts::SetObjectiveForAllPedsInCollective(int colIndex, eObjective objective, CVector p1)\n{\n\tfor (int i = 0; i < MAX_NUM_COLLECTIVES; i++) {\n\t\tif (CollectiveArray[i].colIndex == colIndex) {\n\t\t\tCPed* pPed = CPools::GetPedPool()->GetAt(CollectiveArray[i].pedIndex);\n\t\t\tif (pPed == nil) {\n\t\t\t\tCollectiveArray[i].colIndex = -1;\n\t\t\t\tCollectiveArray[i].pedIndex = 0;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tpPed->bScriptObjectiveCompleted = false;\n\t\t\t\tpPed->SetObjective(objective, p1);\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid CTheScripts::SetObjectiveForAllPedsInCollective(int colIndex, eObjective objective, void* p1)\n{\n\tfor (int i = 0; i < MAX_NUM_COLLECTIVES; i++) {\n\t\tif (CollectiveArray[i].colIndex == colIndex) {\n\t\t\tCPed* pPed = CPools::GetPedPool()->GetAt(CollectiveArray[i].pedIndex);\n\t\t\tif (pPed == nil) {\n\t\t\t\tCollectiveArray[i].colIndex = -1;\n\t\t\t\tCollectiveArray[i].pedIndex = 0;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tpPed->bScriptObjectiveCompleted = false;\n\t\t\t\tpPed->SetObjective(objective, p1);\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid CTheScripts::SetObjectiveForAllPedsInCollective(int colIndex, eObjective objective)\n{\n\tfor (int i = 0; i < MAX_NUM_COLLECTIVES; i++) {\n\t\tif (CollectiveArray[i].colIndex == colIndex) {\n\t\t\tCPed* pPed = CPools::GetPedPool()->GetAt(CollectiveArray[i].pedIndex);\n\t\t\tif (pPed == nil) {\n\t\t\t\tCollectiveArray[i].colIndex = -1;\n\t\t\t\tCollectiveArray[i].pedIndex = 0;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tpPed->bScriptObjectiveCompleted = false;\n\t\t\t\tpPed->SetObjective(objective);\n\t\t\t}\n\t\t}\n\t}\n}\n#endif //GTA_SCRIPT_COLLECTIVE\n\nbool CTheScripts::IsPedStopped(CPed* pPed)\n{\n\tif (pPed->InVehicle())\n\t\treturn IsVehicleStopped(pPed->m_pMyVehicle);\n\treturn (pPed->m_nMoveState == PEDMOVE_NONE || pPed->m_nMoveState == PEDMOVE_STILL) &&\n\t\t!pPed->bIsInTheAir && !pPed->bIsLanding && pPed->bIsStanding && pPed->m_vecAnimMoveDelta.x == 0.0f && pPed->m_vecAnimMoveDelta.y == 0.0f;\n}\n\nbool CTheScripts::IsPlayerStopped(CPlayerInfo* pPlayer)\n{\n\tCPed* pPed = pPlayer->m_pPed;\n\tif (pPed->InVehicle())\n\t\treturn IsVehicleStopped(pPed->m_pMyVehicle);\n\tif (RpAnimBlendClumpGetAssociation(pPed->GetClump(), ANIM_STD_RUNSTOP1) ||\n\t\tRpAnimBlendClumpGetAssociation(pPed->GetClump(), ANIM_STD_RUNSTOP2) ||\n\t\tRpAnimBlendClumpGetAssociation(pPed->GetClump(), ANIM_STD_JUMP_LAUNCH) ||\n\t\tRpAnimBlendClumpGetAssociation(pPed->GetClump(), ANIM_STD_JUMP_GLIDE))\n\t\treturn false;\n\treturn (pPed->m_nMoveState == PEDMOVE_NONE || pPed->m_nMoveState == PEDMOVE_STILL) &&\n\t\t!pPed->bIsInTheAir && !pPed->bIsLanding && pPed->bIsStanding && pPed->m_vecAnimMoveDelta.x == 0.0f && pPed->m_vecAnimMoveDelta.y == 0.0f;\n}\n\nbool CTheScripts::IsVehicleStopped(CVehicle* pVehicle)\n{\n\treturn 0.01f * CTimer::GetTimeStep() >= pVehicle->m_fDistanceTravelled;\n}\n\nvoid CTheScripts::RemoveThisPed(CPed* pPed)\n{\n\tif (pPed) {\n\t\tbool bWasMissionPed = pPed->CharCreatedBy == MISSION_CHAR;\n\t\tif (pPed->InVehicle() && pPed->m_pMyVehicle) {\n\t\t\tif (pPed->m_pMyVehicle->pDriver == pPed) {\n\t\t\t\tpPed->m_pMyVehicle->RemoveDriver();\n\t\t\t\tpPed->m_pMyVehicle->SetStatus(STATUS_ABANDONED);\n\t\t\t\tif (pPed->m_pMyVehicle->m_nDoorLock == CARLOCK_LOCKED_INITIALLY)\n\t\t\t\t\tpPed->m_pMyVehicle->m_nDoorLock = CARLOCK_UNLOCKED;\n\t\t\t\tif (pPed->m_nPedType == PEDTYPE_COP && pPed->m_pMyVehicle->IsLawEnforcementVehicle())\n\t\t\t\t\tpPed->m_pMyVehicle->ChangeLawEnforcerState(0);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tpPed->m_pMyVehicle->RemovePassenger(pPed);\n\t\t\t}\n\t\t}\n\t\tCWorld::RemoveReferencesToDeletedObject(pPed);\n\t\tdelete pPed;\n\t\tif (bWasMissionPed)\n\t\t\t--CPopulation::ms_nTotalMissionPeds;\n\t}\n}\n\nvoid CTheScripts::CleanUpThisPed(CPed* pPed)\n{\n\tif (!pPed)\n\t\treturn;\n\tif (pPed->CharCreatedBy != MISSION_CHAR)\n\t\treturn;\n\tpPed->CharCreatedBy = RANDOM_CHAR;\n\tif (pPed->m_nPedType == PEDTYPE_PROSTITUTE)\n\t\tpPed->m_objectiveTimer = CTimer::GetTimeInMilliseconds() + 30000;\n\tif (pPed->InVehicle()) {\n\t\tif (pPed->m_pMyVehicle->pDriver == pPed) {\n\t\t\tif (pPed->m_pMyVehicle->m_vehType == VEHICLE_TYPE_CAR) {\n\t\t\t\tCCarCtrl::JoinCarWithRoadSystem(pPed->m_pMyVehicle);\n\t\t\t\tpPed->m_pMyVehicle->AutoPilot.m_nCarMission = MISSION_CRUISE;\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tif (pPed->m_pMyVehicle->m_vehType == VEHICLE_TYPE_CAR) {\n\t\t\t\tpPed->SetObjective(OBJECTIVE_LEAVE_CAR, pPed->m_pMyVehicle);\n\t\t\t\tpPed->bWanderPathAfterExitingCar = true;\n\t\t\t}\n\t\t}\n\t}\n\tbool flees = false;\n\tPedState state;\n\teMoveState ms;\n\tif (pPed->m_nPedState == PED_FLEE_ENTITY || pPed->m_nPedState == PED_FLEE_POS) {\n\t\tms = pPed->m_nMoveState;\n\t\tstate = pPed->m_nPedState;\n\t\tflees = true;\n\t}\n\tpPed->ClearObjective();\n\tpPed->bRespondsToThreats = true;\n\tpPed->bScriptObjectiveCompleted = false;\n\tpPed->bKindaStayInSamePlace = false;\n\tpPed->ClearLeader();\n\tif (pPed->IsPedInControl())\n\t\tpPed->SetWanderPath(CGeneral::GetRandomNumber() & 7);\n\tif (flees) {\n\t\tpPed->SetPedState(state);\n\t\tpPed->SetMoveState(ms);\n\t}\n\t--CPopulation::ms_nTotalMissionPeds;\n}\n\nvoid CTheScripts::CleanUpThisVehicle(CVehicle* pVehicle)\n{\n\tif (!pVehicle)\n\t\treturn;\n\tif (pVehicle->VehicleCreatedBy != MISSION_VEHICLE)\n\t\treturn;\n\tpVehicle->bIsLocked = false;\n\tCCarCtrl::RemoveFromInterestingVehicleList(pVehicle);\n\tpVehicle->VehicleCreatedBy = RANDOM_VEHICLE;\n\t++CCarCtrl::NumRandomCars;\n\t--CCarCtrl::NumMissionCars;\n}\n\nvoid CTheScripts::CleanUpThisObject(CObject* pObject)\n{\n\tif (!pObject)\n\t\treturn;\n\tif (pObject->ObjectCreatedBy != MISSION_OBJECT)\n\t\treturn;\n\tpObject->ObjectCreatedBy = TEMP_OBJECT;\n\tpObject->m_nEndOfLifeTime = CTimer::GetTimeInMilliseconds() + 20000000;\n\tpObject->m_nRefModelIndex = -1;\n\tpObject->bUseVehicleColours = false;\n\t++CObject::nNoTempObjects;\n}\n\nvoid CTheScripts::ReadObjectNamesFromScript()\n{\n\tint32 varSpace = GetSizeOfVariableSpace();\n\tuint32 ip = varSpace + 8;\n\tNumberOfUsedObjects = Read2BytesFromScript(&ip);\n\tip += 2;\n\tfor (uint16 i = 0; i < NumberOfUsedObjects; i++) {\n\t\tfor (int j = 0; j < USED_OBJECT_NAME_LENGTH; j++)\n\t\t\tUsedObjectArray[i].name[j] = ScriptSpace[ip++];\n\t\tUsedObjectArray[i].index = 0;\n\t}\n}\n\nvoid CTheScripts::UpdateObjectIndices()\n{\n\tchar name[USED_OBJECT_NAME_LENGTH];\n\tchar error[112];\n\tfor (int i = 1; i < NumberOfUsedObjects; i++) {\n\t\tbool found = false;\n\t\tfor (int j = 0; j < MODELINFOSIZE && !found; j++) {\n\t\t\tCBaseModelInfo* pModel = CModelInfo::GetModelInfo(j);\n\t\t\tif (!pModel)\n\t\t\t\tcontinue;\n\t\t\tstrcpy(name, pModel->GetModelName());\n#ifdef FIX_BUGS\n\t\t\tfor (int k = 0; k < USED_OBJECT_NAME_LENGTH && name[k]; k++)\n#else\n\t\t\tfor (int k = 0; k < USED_OBJECT_NAME_LENGTH; k++)\n#endif\n\t\t\t\tname[k] = toupper(name[k]);\n\t\t\tif (strcmp(name, UsedObjectArray[i].name) == 0) {\n\t\t\t\tfound = true;\n\t\t\t\tUsedObjectArray[i].index = j;\n\t\t\t}\n\t\t}\n\t\tif (!found) {\n\t\t\tsprintf(error, \"CTheScripts::UpdateObjectIndices - Couldn't find %s\", UsedObjectArray[i].name);\n\t\t\tdebug(\"%s\\n\", error);\n\t\t}\n\t}\n}\n\nvoid CTheScripts::ReadMultiScriptFileOffsetsFromScript()\n{\n\tint32 varSpace = GetSizeOfVariableSpace();\n\tuint32 ip = varSpace + 3;\n\tint32 objectSize = Read4BytesFromScript(&ip);\n\tip = objectSize + 8;\n\tMainScriptSize = Read4BytesFromScript(&ip);\n\tLargestMissionScriptSize = Read4BytesFromScript(&ip);\n\tNumberOfMissionScripts = Read2BytesFromScript(&ip);\n\tNumberOfExclusiveMissionScripts = Read2BytesFromScript(&ip);\n\tfor (int i = 0; i < NumberOfMissionScripts; i++) {\n\t\tMultiScriptArray[i] = Read4BytesFromScript(&ip);\n\t}\n}\n"
  },
  {
    "path": "src/control/Script6.cpp",
    "content": "#include \"common.h\"\n\n#include \"Script.h\"\n#include \"ScriptCommands.h\"\n\n#include \"Bike.h\"\n#include \"CarCtrl.h\"\n#include \"Cranes.h\"\n#include \"Credits.h\"\n#include \"CutsceneMgr.h\"\n#include \"DMAudio.h\"\n#include \"FileMgr.h\"\n#include \"Fire.h\"\n#include \"Frontend.h\"\n#include \"Garages.h\"\n#include \"General.h\"\n#ifdef MISSION_REPLAY\n#include \"GenericGameStorage.h\"\n#endif\n#include \"Messages.h\"\n#include \"Pad.h\"\n#include \"Particle.h\"\n#include \"Phones.h\"\n#include \"Population.h\"\n#include \"Pools.h\"\n#include \"Record.h\"\n#include \"Remote.h\"\n#include \"Restart.h\"\n#include \"SpecialFX.h\"\n#include \"Stats.h\"\n#include \"Streaming.h\"\n#include \"Weather.h\"\n#include \"Zones.h\"\n#include \"main.h\"\n#include \"GameLogic.h\"\n#include \"Sprite.h\"\n#include \"CarAI.h\"\n#include \"Pickups.h\"\n#include \"Fluff.h\"\n\n#ifdef USE_DEBUG_SCRIPT_LOADER\nextern const char* scriptfile;\n#endif\n\nbool CRunningScript::ThisIsAValidRandomCop(uint32 mi, int cop, int swat, int fbi, int army, int miami)\n{\n\tswitch (mi)\n\t{\n\tcase MI_COP: if (cop) return true; break;\n\tcase MI_SWAT: if (swat) return true; break;\n\tcase MI_FBI: if (fbi) return true; break;\n\tcase MI_ARMY: if (army) return true; break;\n\tdefault: if (mi >= MI_VICE1 && mi <= MI_VICE8 && miami) return true; break;\n\t}\n\treturn false;\n}\n\nbool CRunningScript::ThisIsAValidRandomPed(uint32 pedtype, int civ, int gang, int criminal)\n{\n    switch (pedtype) {\n    case PEDTYPE_CIVMALE:\n    case PEDTYPE_CIVFEMALE:\n        return civ;\n    case PEDTYPE_GANG1:\n    case PEDTYPE_GANG2:\n    case PEDTYPE_GANG3:\n    case PEDTYPE_GANG4:\n    case PEDTYPE_GANG5:\n    case PEDTYPE_GANG6:\n    case PEDTYPE_GANG7:\n    case PEDTYPE_GANG8:\n    case PEDTYPE_GANG9:\n        return gang;\n    case PEDTYPE_CRIMINAL:\n    case PEDTYPE_PROSTITUTE:\n        return criminal;\n    default:\n        return false;\n    }\n}\n\nint8 CRunningScript::ProcessCommands1000To1099(int32 command)\n{\n\tswitch (command) {\n\t//case COMMAND_FLASH_RADAR_BLIP:\n\t/*\n\tcase COMMAND_IS_CHAR_IN_CONTROL:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tUpdateCompareFlag(pPed->IsPedInControl());\n\t\treturn 0;\n\t}\n\t*/\n\tcase COMMAND_SET_GENERATE_CARS_AROUND_CAMERA:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCCarCtrl::bCarsGeneratedAroundCamera = (ScriptParams[0] != 0);\n\t\treturn 0;\n\tcase COMMAND_CLEAR_SMALL_PRINTS:\n\t\tCMessages::ClearSmallMessagesOnly();\n\t\treturn 0;\n\t/*\n\tcase COMMAND_HAS_MILITARY_CRANE_COLLECTED_ALL_CARS:\n\t\tUpdateCompareFlag(CCranes::HaveAllCarsBeenCollectedByMilitaryCrane());\n\t\treturn 0;\n\t*/\n\tcase COMMAND_SET_UPSIDEDOWN_CAR_NOT_DAMAGED:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tscript_assert(pVehicle->m_vehType == VEHICLE_TYPE_CAR);\n\t\tCAutomobile* pCar = (CAutomobile*)pVehicle;\n\t\tpCar->bNotDamagedUpsideDown = (ScriptParams[1] != 0);\n\t\treturn 0;\n\t}\n\tcase COMMAND_CAN_PLAYER_START_MISSION:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPlayerPed* pPlayerPed = CWorld::Players[ScriptParams[0]].m_pPed;\n\t\tscript_assert(pPlayerPed);\n\t\tUpdateCompareFlag(pPlayerPed->IsPedInControl() || pPlayerPed->m_nPedState == PED_DRIVING);\n\t\treturn 0;\n\t}\n\tcase COMMAND_MAKE_PLAYER_SAFE_FOR_CUTSCENE:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n#ifdef MISSION_REPLAY\n\t\tAllowMissionReplay = 0;\n\t\tSaveGameForPause(3);\n#endif\n\t\tCPlayerInfo* pPlayerInfo = &CWorld::Players[ScriptParams[0]];\n\t\tCPad::GetPad(ScriptParams[0])->SetDisablePlayerControls(PLAYERCONTROL_CUTSCENE);\n\t\tpPlayerInfo->MakePlayerSafe(true);\n\t\tCCutsceneMgr::StartCutsceneProcessing();\n\t\treturn 0;\n\t}\n\tcase COMMAND_USE_TEXT_COMMANDS:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCTheScripts::UseTextCommands = (ScriptParams[0] != 0) ? 2 : 1;\n\t\treturn 0;\n\tcase COMMAND_SET_THREAT_FOR_PED_TYPE:\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPedType::AddThreat(ScriptParams[0], ScriptParams[1]);\n\t\treturn 0;\n\tcase COMMAND_CLEAR_THREAT_FOR_PED_TYPE:\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPedType::RemoveThreat(ScriptParams[0], ScriptParams[1]);\n\t\treturn 0;\n\tcase COMMAND_GET_CAR_COLOURS:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tScriptParams[0] = pVehicle->m_currentColour1;\n\t\tScriptParams[1] = pVehicle->m_currentColour2;\n\t\tStoreParameters(&m_nIp, 2);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_ALL_CARS_CAN_BE_DAMAGED:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCWorld::SetAllCarsCanBeDamaged(ScriptParams[0] != 0);\n\t\tif (!ScriptParams[0])\n\t\t\tCWorld::ExtinguishAllCarFiresInArea(FindPlayerCoors(), 4000.0f);\n\t\treturn 0;\n\tcase COMMAND_SET_CAR_CAN_BE_DAMAGED:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tpVehicle->bCanBeDamaged = ScriptParams[1] != 0;\n\t\tif (!ScriptParams[1])\n\t\t\tpVehicle->ExtinguishCarFire();\n\t\treturn 0;\n\t}\n\t//case COMMAND_MAKE_PLAYER_UNSAFE:\n\t/*\n\tcase COMMAND_LOAD_COLLISION:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCTimer::Stop();\n\t\tCGame::currLevel = (eLevelName)ScriptParams[0];\n\t\tISLAND_LOADING_IS(LOW)\n\t\t{\n\t\t\tCStreaming::RemoveUnusedBigBuildings(CGame::currLevel);\n\t\t\tCStreaming::RemoveUnusedBuildings(CGame::currLevel);\n\t\t}\n\t\tCCollision::SortOutCollisionAfterLoad();\n\t\tISLAND_LOADING_ISNT(HIGH)\n\t\t{\n\t\t\tCStreaming::RequestIslands(CGame::currLevel);\n\t\t\tCStreaming::LoadAllRequestedModels(true);\n\t\t}\n\t\tCTimer::Update();\n\t\treturn 0;\n\t}\n\tcase COMMAND_GET_BODY_CAST_HEALTH:\n\t//\tScriptParams[0] = CObject::nBodyCastHealth;\n\t//\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t*/\n\tcase COMMAND_SET_CHARS_CHATTING:\n\t{\n\t\tCollectParameters(&m_nIp, 3);\n\t\tCPed* pPed1 = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tCPed* pPed2 = CPools::GetPedPool()->GetAt(ScriptParams[1]);\n\t\tscript_assert(pPed1 && pPed2);\n\t\tpPed1->SetChat(pPed2, ScriptParams[2]);\n\t\tpPed2->SetChat(pPed1, ScriptParams[2]);\n\t\treturn 0;\n\t}\n\t//case COMMAND_MAKE_PLAYER_SAFE:\n\t/*\n\tcase COMMAND_SET_CAR_STAYS_IN_CURRENT_LEVEL:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tif (ScriptParams[1])\n\t\t\tpVehicle->m_nZoneLevel = CTheZones::GetLevelFromPosition(&pVehicle->GetPosition());\n\t\telse\n\t\t\tpVehicle->m_nZoneLevel = LEVEL_GENERIC;\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_CHAR_STAYS_IN_CURRENT_LEVEL:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tif (ScriptParams[1])\n\t\t\tpPed->m_nZoneLevel = CTheZones::GetLevelFromPosition(&pPed->GetPosition());\n\t\telse\n\t\t\tpPed->m_nZoneLevel = LEVEL_GENERIC;\n\t\treturn 0;\n\t}\n\t*/\n\tcase COMMAND_SET_DRUNK_INPUT_DELAY:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tassert(ScriptParams[1] < CPad::DRUNK_STEERING_BUFFER_SIZE);\n\t\tCPad::GetPad(ScriptParams[0])->SetDrunkInputDelay(ScriptParams[1]);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_CHAR_MONEY:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tpPed->m_nPedMoney = ScriptParams[1];\n\t\tpPed->bMoneyHasBeenGivenByScript = true;\n\t\treturn 0;\n\t}\n\t//case COMMAND_INCREASE_CHAR_MONEY:\n\tcase COMMAND_GET_OFFSET_FROM_OBJECT_IN_WORLD_COORDS:\n\t{\n\t\tCollectParameters(&m_nIp, 4);\n\t\tCObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pObject);\n\t\tCVector result = Multiply3x3(pObject->GetMatrix(), *(CVector*)&ScriptParams[1]) + pObject->GetPosition();\n\t\t*(CVector*)&ScriptParams[0] = result;\n\t\tStoreParameters(&m_nIp, 3);\n\t\treturn 0;\n\t}\n\tcase COMMAND_REGISTER_LIFE_SAVED:\n\t\tCStats::AnotherLifeSavedWithAmbulance();\n\t\treturn 0;\n\tcase COMMAND_REGISTER_CRIMINAL_CAUGHT:\n\t\tCStats::AnotherCriminalCaught();\n\t\treturn 0;\n\tcase COMMAND_REGISTER_AMBULANCE_LEVEL:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCStats::RegisterLevelAmbulanceMission(ScriptParams[0]);\n\t\treturn 0;\n\tcase COMMAND_REGISTER_FIRE_EXTINGUISHED:\n\t\tCStats::AnotherFireExtinguished();\n\t\treturn 0;\n\tcase COMMAND_TURN_PHONE_ON:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tgPhoneInfo.m_aPhones[ScriptParams[0]].m_nState = PHONE_STATE_9;\n\t\treturn 0;\n\t/*\n\tcase COMMAND_REGISTER_LONGEST_DODO_FLIGHT:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCStats::RegisterLongestFlightInDodo(ScriptParams[0]);\n\t\treturn 0;\n\t*/\n\tcase COMMAND_GET_OFFSET_FROM_CAR_IN_WORLD_COORDS:\n\t{\n\t\tCollectParameters(&m_nIp, 4);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tCVector result = Multiply3x3(pVehicle->GetMatrix(), *(CVector*)&ScriptParams[1]) + pVehicle->GetPosition();\n\t\t*(CVector*)&ScriptParams[0] = result;\n\t\tStoreParameters(&m_nIp, 3);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_TOTAL_NUMBER_OF_KILL_FRENZIES:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCStats::SetTotalNumberKillFrenzies(ScriptParams[0]);\n\t\treturn 0;\n\tcase COMMAND_BLOW_UP_RC_BUGGY:\n\t\tCWorld::Players[CWorld::PlayerInFocus].BlowUpRCBuggy(true);\n\t\treturn 0;\n\t/*\n\tcase COMMAND_REMOVE_CAR_FROM_CHASE:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCRecordDataForChase::RemoveCarFromChase(ScriptParams[0]);\n\t\treturn 0;\n\t*/\n\tcase COMMAND_IS_FRENCH_GAME:\n\t\tUpdateCompareFlag(CGame::frenchGame);\n\t\treturn 0;\n\tcase COMMAND_IS_GERMAN_GAME:\n\t\tUpdateCompareFlag(CGame::germanGame);\n\t\treturn 0;\n\tcase COMMAND_CLEAR_MISSION_AUDIO:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tDMAudio.ClearMissionAudio(ScriptParams[0] - 1);\n\t\treturn 0;\n\t/*\n\tcase COMMAND_SET_FADE_IN_AFTER_NEXT_ARREST:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCRestart::bFadeInAfterNextArrest = !!ScriptParams[0];\n\t\treturn 0;\n\tcase COMMAND_SET_FADE_IN_AFTER_NEXT_DEATH:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCRestart::bFadeInAfterNextDeath = !!ScriptParams[0];\n\t\treturn 0;\n\tcase COMMAND_SET_GANG_PED_MODEL_PREFERENCE:\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCGangs::SetGangPedModelOverride(ScriptParams[0], ScriptParams[1]);\n\t\treturn 0;\n\t*/\n\tcase COMMAND_SET_CHAR_USE_PEDNODE_SEEK:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tif (ScriptParams[1])\n\t\t\tpPed->m_pNextPathNode = nil;\n\t\tpPed->bUsePedNodeSeek = !!ScriptParams[1];\n\t\treturn 0;\n\t}\n\t/*\n\tcase COMMAND_SWITCH_VEHICLE_WEAPONS:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tpVehicle->bGunSwitchedOff = !ScriptParams[1];\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_GET_OUT_OF_JAIL_FREE:\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCWorld::Players[ScriptParams[0]].m_bGetOutOfJailFree = !!ScriptParams[1];\n\t\treturn 0;\n\t*/\n\tcase COMMAND_SET_FREE_HEALTH_CARE:\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCWorld::Players[ScriptParams[0]].m_bGetOutOfHospitalFree = !!ScriptParams[1];\n\t\treturn 0;\n\t/*\n\tcase COMMAND_IS_CAR_DOOR_CLOSED:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tUpdateCompareFlag(!pVehicle->IsDoorMissing((eDoors)ScriptParams[1]) && pVehicle->IsDoorClosed((eDoors)ScriptParams[1]));\n\t\treturn 0;\n\t}\n\t*/\n\tcase COMMAND_LOAD_AND_LAUNCH_MISSION:\n\t\treturn 0;\n\tcase COMMAND_LOAD_AND_LAUNCH_MISSION_INTERNAL:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\n\t\tif (CTheScripts::NumberOfExclusiveMissionScripts > 0 && ScriptParams[0] <= UINT16_MAX - 2)\n\t\t\treturn 0;\n#ifdef MISSION_REPLAY\n\t\tmissionRetryScriptIndex = ScriptParams[0];\n\t\tif (missionRetryScriptIndex == 19)\n\t\t\tCStats::LastMissionPassedName[0] = '\\0';\n#endif\n\t\tCTimer::Suspend();\n\t\tint offset = CTheScripts::MultiScriptArray[ScriptParams[0]];\n#ifdef USE_DEBUG_SCRIPT_LOADER\n\t\tCFileMgr::ChangeDir(\"\\\\data\\\\\");\n\t\tint handle = CFileMgr::OpenFile(scriptfile, \"rb\");\n\t\tCFileMgr::ChangeDir(\"\\\\\");\n#else\n\t\tCFileMgr::ChangeDir(\"\\\\\");\n\t\tint handle = CFileMgr::OpenFile(\"data\\\\main.scm\", \"rb\");\n#endif\n\t\tCFileMgr::Seek(handle, offset, 0);\n\t\tCFileMgr::Read(handle, (const char*)&CTheScripts::ScriptSpace[SIZE_MAIN_SCRIPT], SIZE_MISSION_SCRIPT);\n\t\tCFileMgr::CloseFile(handle);\n\t\tCRunningScript* pMissionScript = CTheScripts::StartNewScript(SIZE_MAIN_SCRIPT);\n\t\tCTimer::Resume();\n\t\tpMissionScript->m_bIsMissionScript = true;\n\t\tpMissionScript->m_bMissionFlag = true;\n\t\tCTheScripts::bAlreadyRunningAMissionScript = true;\n\t\tCGameLogic::ClearShortCut();\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_OBJECT_DRAW_LAST:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pObject);\n\t\tpObject->bDrawLast = !!ScriptParams[1];\n\t\treturn 0;\n\t}\n\tcase COMMAND_GET_AMMO_IN_PLAYER_WEAPON:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;\n\t\tscript_assert(pPed);\n\t\tScriptParams[0] = 0;\n\t\tfor (int i = 0; i < TOTAL_WEAPON_SLOTS; i++) {\n\t\t\tif (pPed->GetWeapon(i).m_eWeaponType == (eWeaponType)ScriptParams[1])\n\t\t\t\tScriptParams[0] = pPed->GetWeapon(i).m_nAmmoTotal;\n\t\t}\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\t/*\n\tcase COMMAND_GET_AMMO_IN_CHAR_WEAPON:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tCWeapon* pWeaponSlot = &pPed->m_weapons[ScriptParams[1]];\n\t\tif (pWeaponSlot->m_eWeaponType == (eWeaponType)ScriptParams[1])\n\t\t\tScriptParams[0] = pWeaponSlot->m_nAmmoTotal;\n\t\telse\n\t\t\tScriptParams[0] = 0;\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\tcase COMMAND_REGISTER_KILL_FRENZY_PASSED:\n\t\tCStats::AnotherKillFrenzyPassed();\n\t\treturn 0;\n\tcase COMMAND_SET_CHAR_SAY:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tswitch (ScriptParams[1]) {\n\t\tcase SCRIPT_SOUND_CHUNKY_RUN_SHOUT:\n\t\t\tpPed->Say(SOUND_PED_FLEE_RUN);\n\t\t\tbreak;\n\t\tcase SCRIPT_SOUND_SECURITY_GUARD_AWAY_SHOUT:\n\t\t\tpPed->Say(SOUND_PED_FLEE_RUN);\n\t\t\tbreak;\n\t\tcase SCRIPT_SOUND_SWAT_PED_SHOUT:\n\t\t\tpPed->Say(SOUND_PED_PURSUIT_SWAT);\n\t\t\tbreak;\n\t\tcase SCRIPT_SOUND_AMMUNATION_CHAT_1:\n\t\t\tpPed->Say(SOUND_AMMUNATION_WELCOME_1);\n\t\t\tbreak;\n\t\tcase SCRIPT_SOUND_AMMUNATION_CHAT_2:\n\t\t\tpPed->Say(SOUND_AMMUNATION_WELCOME_2);\n\t\t\tbreak;\n\t\tcase SCRIPT_SOUND_AMMUNATION_CHAT_3:\n\t\t\tpPed->Say(SOUND_AMMUNATION_WELCOME_3);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\t\treturn 0;\n\t}\n\t*/\n\tcase COMMAND_SET_NEAR_CLIP:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tTheCamera.SetNearClipScript(*(float*)&ScriptParams[0]);\n\t\treturn 0;\n\tcase COMMAND_SET_RADIO_CHANNEL:\n\t\tCollectParameters(&m_nIp, 2);\n\t\tDMAudio.SetRadioChannel(ScriptParams[0], ScriptParams[1]);\n\t\treturn 0;\n\t/*\n\tcase COMMAND_OVERRIDE_HOSPITAL_LEVEL:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCRestart::OverrideHospitalLevel = ScriptParams[0];\n\t\treturn 0;\n\tcase COMMAND_OVERRIDE_POLICE_STATION_LEVEL:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCRestart::OverridePoliceStationLevel = ScriptParams[0];\n\t\treturn 0;\n\tcase COMMAND_FORCE_RAIN:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCWeather::bScriptsForceRain = !!ScriptParams[0];\n\t\treturn 0;\n\tcase COMMAND_DOES_GARAGE_CONTAIN_CAR:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]);\n\t\tscript_assert(pVehicle);\n\t\tUpdateCompareFlag(CGarages::IsThisCarWithinGarageArea(ScriptParams[0], pVehicle));\n\t\treturn 0;\n\t}\n\t*/\n\tcase COMMAND_SET_CAR_TRACTION:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tfloat fTraction = *(float*)&ScriptParams[1];\n\t\tscript_assert(pVehicle->m_vehType == VEHICLE_TYPE_CAR || pVehicle->m_vehType == VEHICLE_TYPE_BIKE);\n\t\tif (pVehicle->m_vehType == VEHICLE_TYPE_CAR)\n\t\t\t((CAutomobile*)pVehicle)->m_fTraction = fTraction;\n\t\telse\n\t\t\t((CBike*)pVehicle)->m_fTraction = fTraction;\n\t\treturn 0;\n\t}\n\tcase COMMAND_ARE_MEASUREMENTS_IN_METRES:\n#ifdef USE_MEASUREMENTS_IN_METERS\n\t\tUpdateCompareFlag(true);\n#else\n\t\tUpdateCompareFlag(false);\n#endif\n\t\treturn 0;\n\tcase COMMAND_CONVERT_METRES_TO_FEET:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tfloat fMeterValue = *(float*)&ScriptParams[0];\n\t\tfloat fFeetValue = fMeterValue / METERS_IN_FOOT;\n\t\t*(float*)&ScriptParams[0] = fFeetValue;\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\t/*\n\tcase COMMAND_MARK_ROADS_BETWEEN_LEVELS:\n\t{\n\t\tCollectParameters(&m_nIp, 6);\n\t\tfloat infX = *(float*)&ScriptParams[0];\n\t\tfloat infY = *(float*)&ScriptParams[1];\n\t\tfloat infZ = *(float*)&ScriptParams[2];\n\t\tfloat supX = *(float*)&ScriptParams[3];\n\t\tfloat supY = *(float*)&ScriptParams[4];\n\t\tfloat supZ = *(float*)&ScriptParams[5];\n\t\tif (infX > supX) {\n\t\t\tinfX = *(float*)&ScriptParams[3];\n\t\t\tsupX = *(float*)&ScriptParams[0];\n\t\t}\n\t\tif (infY > supY) {\n\t\t\tinfY = *(float*)&ScriptParams[4];\n\t\t\tsupY = *(float*)&ScriptParams[1];\n\t\t}\n\t\tif (infZ > supZ) {\n\t\t\tinfZ = *(float*)&ScriptParams[5];\n\t\t\tsupZ = *(float*)&ScriptParams[2];\n\t\t}\n\t\tThePaths.MarkRoadsBetweenLevelsInArea(infX, supX, infY, supY, infZ, supZ);\n\t\treturn 0;\n\t}\n\tcase COMMAND_MARK_PED_ROADS_BETWEEN_LEVELS:\n\t{\n\t\tCollectParameters(&m_nIp, 6);\n\t\tfloat infX = *(float*)&ScriptParams[0];\n\t\tfloat infY = *(float*)&ScriptParams[1];\n\t\tfloat infZ = *(float*)&ScriptParams[2];\n\t\tfloat supX = *(float*)&ScriptParams[3];\n\t\tfloat supY = *(float*)&ScriptParams[4];\n\t\tfloat supZ = *(float*)&ScriptParams[5];\n\t\tif (infX > supX) {\n\t\t\tinfX = *(float*)&ScriptParams[3];\n\t\t\tsupX = *(float*)&ScriptParams[0];\n\t\t}\n\t\tif (infY > supY) {\n\t\t\tinfY = *(float*)&ScriptParams[4];\n\t\t\tsupY = *(float*)&ScriptParams[1];\n\t\t}\n\t\tif (infZ > supZ) {\n\t\t\tinfZ = *(float*)&ScriptParams[5];\n\t\t\tsupZ = *(float*)&ScriptParams[2];\n\t\t}\n\t\tThePaths.PedMarkRoadsBetweenLevelsInArea(infX, supX, infY, supY, infZ, supZ);\n\t\treturn 0;\n\t}\n\t*/\n\tcase COMMAND_SET_CAR_AVOID_LEVEL_TRANSITIONS:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tpVehicle->AutoPilot.m_bStayInCurrentLevel = !!ScriptParams[1];\n\t\treturn 0;\n\t}\n\t/*\n\tcase COMMAND_SET_CHAR_AVOID_LEVEL_TRANSITIONS:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[1]);\n\t\tscript_assert(pPed);\n\t\t// not implemented\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_THREAT_FOR_PED_TYPE:\n\t\tCollectParameters(&m_nIp, 2);\n\t\tUpdateCompareFlag(CPedType::IsThreat(ScriptParams[0], ScriptParams[1]));\n\t\treturn 0;\n\t*/\n\tcase COMMAND_CLEAR_AREA_OF_CHARS:\n\t{\n\t\tCollectParameters(&m_nIp, 6);\n\t\tfloat infX = *(float*)&ScriptParams[0];\n\t\tfloat infY = *(float*)&ScriptParams[1];\n\t\tfloat infZ = *(float*)&ScriptParams[2];\n\t\tfloat supX = *(float*)&ScriptParams[3];\n\t\tfloat supY = *(float*)&ScriptParams[4];\n\t\tfloat supZ = *(float*)&ScriptParams[5];\n\t\tif (infX > supX) {\n\t\t\tinfX = *(float*)&ScriptParams[3];\n\t\t\tsupX = *(float*)&ScriptParams[0];\n\t\t}\n\t\tif (infY > supY) {\n\t\t\tinfY = *(float*)&ScriptParams[4];\n\t\t\tsupY = *(float*)&ScriptParams[1];\n\t\t}\n\t\tif (infZ > supZ) {\n\t\t\tinfZ = *(float*)&ScriptParams[5];\n\t\t\tsupZ = *(float*)&ScriptParams[2];\n\t\t}\n\t\tCWorld::ClearPedsFromArea(infX, infY, infZ, supX, supY, supZ);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_TOTAL_NUMBER_OF_MISSIONS:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCStats::SetTotalNumberMissions(CGame::germanGame ? ScriptParams[0] - 2 : ScriptParams[0]);\n\t\treturn 0;\n\tcase COMMAND_CONVERT_METRES_TO_FEET_INT:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tScriptParams[0] *= FEET_IN_METER;\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\tcase COMMAND_REGISTER_FASTEST_TIME:\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCStats::RegisterFastestTime(ScriptParams[0], ScriptParams[1]);\n\t\treturn 0;\n\tcase COMMAND_REGISTER_HIGHEST_SCORE:\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCStats::RegisterHighestScore(ScriptParams[0], ScriptParams[1]);\n\t\treturn 0;\n\t//case COMMAND_WARP_CHAR_INTO_CAR_AS_PASSENGER:\n\tcase COMMAND_IS_CAR_PASSENGER_SEAT_FREE:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tUpdateCompareFlag(ScriptParams[1] < pVehicle->m_nNumMaxPassengers && pVehicle->pPassengers[ScriptParams[1]] == nil);\n\t\treturn 0;\n\t}\n\t/*\n\tcase COMMAND_GET_CHAR_IN_CAR_PASSENGER_SEAT:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tscript_assert(ScriptParams[1] >= 0 && ScriptParams[1] < ARRAY_SIZE(pVehicle->pPassengers));\n\t\tCPed* pPassenger = pVehicle->pPassengers[ScriptParams[1]];\n\t\tScriptParams[0] = CPools::GetPedPool()->GetIndex(pPassenger);\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\t*/\n\tcase COMMAND_SET_CHAR_IS_CHRIS_CRIMINAL:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tpPed->bChrisCriminal = !!ScriptParams[1];\n\t\treturn 0;\n\t}\n\tcase COMMAND_START_CREDITS:\n\t\tCCredits::Start();\n\t\treturn 0;\n\tcase COMMAND_STOP_CREDITS:\n\t\tCCredits::Stop();\n\t\treturn 0;\n\tcase COMMAND_ARE_CREDITS_FINISHED:\n\t\tUpdateCompareFlag(CCredits::AreCreditsDone());\n\t\treturn 0;\n\tcase COMMAND_CREATE_SINGLE_PARTICLE:\n\t\tCollectParameters(&m_nIp, 8);\n\t\tCParticle::AddParticle((tParticleType)ScriptParams[0], *(CVector*)&ScriptParams[1],\n\t\t\t*(CVector*)&ScriptParams[4], nil, *(float*)&ScriptParams[7], 0, 0, 0, 0);\n\t\treturn 0;\n\t/*\n\tcase COMMAND_SET_CHAR_IGNORE_LEVEL_TRANSITIONS:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tif (ScriptParams[1])\n\t\t\tpPed->m_nZoneLevel = LEVEL_IGNORE;\n\t\telse\n\t\t\tpPed->m_nZoneLevel = CTheZones::GetLevelFromPosition(&pPed->GetPosition());\n\t\treturn 0;\n\t}\n\tcase COMMAND_GET_CHASE_CAR:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCVehicle* pVehicle = CRecordDataForChase::TurnChaseCarIntoScriptCar(ScriptParams[0]);\n\t\tScriptParams[0] = CPools::GetVehiclePool()->GetIndex(pVehicle);\n\t\tStoreParameters(&m_nIp, 1);\n\t\tif (m_bIsMissionScript)\n\t\t\tCTheScripts::MissionCleanUp.AddEntityToList(ScriptParams[0], CLEANUP_CAR);\n\t\treturn 0;\n\t}\n\tcase COMMAND_START_BOAT_FOAM_ANIMATION:\n\t\tCSpecialParticleStuff::StartBoatFoamAnimation();\n\t\treturn 0;\n\tcase COMMAND_UPDATE_BOAT_FOAM_ANIMATION:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pObject);\n\t\tCSpecialParticleStuff::UpdateBoatFoamAnimation(&pObject->GetMatrix());\n\t\treturn 0;\n\t}\n\t*/\n\tcase COMMAND_SET_MUSIC_DOES_FADE:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tTheCamera.m_bIgnoreFadingStuffForMusic = (ScriptParams[0] == 0);\n\t\treturn 0;\n\t/*\n\tcase COMMAND_SET_INTRO_IS_PLAYING:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tif (ScriptParams[0]) {\n\t\t\tCGame::playingIntro = true;\n\t\t\tCStreaming::RemoveCurrentZonesModels();\n\t\t} else {\n\t\t\tCGame::playingIntro = false;\n\t\t\tDMAudio.ChangeMusicMode(MUSICMODE_GAME);\n\t\t\tint mi;\n\t\t\tCModelInfo::GetModelInfo(\"bridgefukb\", &mi);\n\t\t\tCStreaming::RequestModel(mi, STREAMFLAGS_DEPENDENCY);\n\t\t\tCStreaming::LoadAllRequestedModels(false);\n\t\t}\n\t\treturn 0;\n\t*/\n\tcase COMMAND_SET_PLAYER_HOOKER:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPlayerInfo* pPlayerInfo = &CWorld::Players[ScriptParams[0]];\n\t\tif (ScriptParams[1] < 0) {\n\t\t\tpPlayerInfo->m_pHooker = nil;\n\t\t\tpPlayerInfo->m_nNextSexFrequencyUpdateTime = 0;\n\t\t\tpPlayerInfo->m_nNextSexMoneyUpdateTime = 0;\n\t\t} else {\n\t\t\tCPed* pHooker = CPools::GetPedPool()->GetAt(ScriptParams[1]);\n\t\t\tscript_assert(pHooker);\n\t\t\tpPlayerInfo->m_pHooker = (CCivilianPed*)pHooker;\n\t\t\tpPlayerInfo->m_nSexFrequency = 1000;\n\t\t\tpPlayerInfo->m_nNextSexFrequencyUpdateTime = CTimer::GetTimeInMilliseconds() + 1000;\n\t\t\tpPlayerInfo->m_nNextSexMoneyUpdateTime = CTimer::GetTimeInMilliseconds() + 3000;\n\t\t}\n\t\treturn 0;\n\t}\n\tcase COMMAND_PLAY_END_OF_GAME_TUNE:\n\t\tDMAudio.PlayPreloadedCutSceneMusic();\n\t\treturn 0;\n\tcase COMMAND_STOP_END_OF_GAME_TUNE:\n\t\tDMAudio.StopCutSceneMusic();\n\t\tDMAudio.ChangeMusicMode(MUSICMODE_GAME);\n\t\treturn 0;\n\tcase COMMAND_GET_CAR_MODEL:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tScriptParams[0] = pVehicle->GetModelIndex();\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_PLAYER_SITTING_IN_CAR:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;\n\t\tscript_assert(pPed);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]);\n\t\tUpdateCompareFlag(pPed->GetPedState() == PED_DRIVING && pPed->m_objective != OBJECTIVE_LEAVE_CAR && pPed->m_pMyVehicle == pVehicle);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_PLAYER_SITTING_IN_ANY_CAR:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;\n\t\tscript_assert(pPed);\n\t\tUpdateCompareFlag(pPed->GetPedState() == PED_DRIVING && pPed->m_objective != OBJECTIVE_LEAVE_CAR);\n\t\treturn 0;\n\t}\n\t/*\n\tcase COMMAND_SET_SCRIPT_FIRE_AUDIO:\n\t\tCollectParameters(&m_nIp, 2);\n\t\tgFireManager.SetScriptFireAudio(ScriptParams[0], !!ScriptParams[1]);\n\t\treturn 0;\n\t*/\n\tcase COMMAND_ARE_ANY_CAR_CHEATS_ACTIVATED:\n\t\tUpdateCompareFlag(CVehicle::bAllDodosCheat || CVehicle::bCheat3 || CVehicle::bHoverCheat || CVehicle::bCheat8 || CVehicle::bCheat9);\n\t\treturn 0;\n\tcase COMMAND_SET_CHAR_SUFFERS_CRITICAL_HITS:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tpPed->bNoCriticalHits = (ScriptParams[1] == 0);\n\t\treturn 0;\n\t}\n\t/*\n\tcase COMMAND_IS_PLAYER_LIFTING_A_PHONE:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;\n\t\tscript_assert(pPed);\n\t\tUpdateCompareFlag(pPed->GetPedState() == PED_MAKE_CALL);\n\t\treturn 0;\n\t}\n\t*/\n\tcase COMMAND_IS_CHAR_SITTING_IN_CAR:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]);\n\t\tscript_assert(pVehicle);\n\t\tUpdateCompareFlag(pPed->GetPedState() == PED_DRIVING && pPed->m_objective != OBJECTIVE_LEAVE_CAR && pPed->m_pMyVehicle == pVehicle);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_CHAR_SITTING_IN_ANY_CAR:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tUpdateCompareFlag(pPed->GetPedState() == PED_DRIVING && pPed->m_objective != OBJECTIVE_LEAVE_CAR);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_PLAYER_ON_FOOT:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;\n\t\tscript_assert(pPed);\n\t\tUpdateCompareFlag(!pPed->bInVehicle && pPed->m_objective != OBJECTIVE_ENTER_CAR_AS_PASSENGER &&\n\t\t\tpPed->m_objective != OBJECTIVE_ENTER_CAR_AS_DRIVER);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_CHAR_ON_FOOT:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tUpdateCompareFlag(!pPed->bInVehicle && pPed->m_objective != OBJECTIVE_ENTER_CAR_AS_PASSENGER &&\n\t\t\tpPed->m_objective != OBJECTIVE_ENTER_CAR_AS_DRIVER);\n\t\treturn 0;\n\t}\n\tdefault:\n\t\tscript_assert(0);\n\t}\n\treturn -1;\n}\n\nint8 CRunningScript::ProcessCommands1100To1199(int32 command)\n{\n\tchar tmp[48];\n\tswitch (command) {\n\t/*\n\tcase COMMAND_LOAD_COLLISION_WITH_SCREEN:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCTimer::Stop();\n\t\tCGame::currLevel = (eLevelName)ScriptParams[0];\n\t\tif (CGame::currLevel != CCollision::ms_collisionInMemory) {\n\t\t\tISLAND_LOADING_IS(LOW)\n\t\t\t{\n\t\t\t\tDMAudio.SetEffectsFadeVol(0);\n\t\t\t\tCPad::StopPadsShaking();\n\t\t\t\tCCollision::LoadCollisionScreen(CGame::currLevel);\n\t\t\t\tDMAudio.Service();\n\t\t\t}\n\t\t\tCPopulation::DealWithZoneChange(CCollision::ms_collisionInMemory, CGame::currLevel, false);\n\n\t\t\tISLAND_LOADING_IS(LOW)\n\t\t\t{\n\t\t\t\tCStreaming::RemoveUnusedBigBuildings(CGame::currLevel);\n\t\t\t\tCStreaming::RemoveUnusedBuildings(CGame::currLevel);\n\t\t\t}\n\t\t\tCCollision::SortOutCollisionAfterLoad();\n\n\t\t\tISLAND_LOADING_ISNT(HIGH)\n\t\t\t\tCStreaming::RequestIslands(CGame::currLevel);\n\n\t\t\tISLAND_LOADING_IS(LOW)\n\t\t\t\tCStreaming::RequestBigBuildings(CGame::currLevel);\n\n\t\t\tISLAND_LOADING_ISNT(HIGH)\n\t\t\t\tCStreaming::LoadAllRequestedModels(true);\n\n\t\t\tISLAND_LOADING_IS(LOW)\n\t\t\t\tDMAudio.SetEffectsFadeVol(127);\n\t\t}\n\t\tCTimer::Update();\n\t\treturn 0;\n\t*/\n\tcase COMMAND_LOAD_SPLASH_SCREEN:\n\t\tCTheScripts::ReadTextLabelFromScript(&m_nIp, tmp);\n\t\tfor (int i = 0; i < KEY_LENGTH_IN_SCRIPT; i++)\n\t\t\ttmp[i] = tolower(tmp[i]);\n\t\tm_nIp += 8;\n\t\tLoadSplash(tmp);\n\t\treturn 0;\n\t/*\n\tcase COMMAND_SET_CAR_IGNORE_LEVEL_TRANSITIONS:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tif (ScriptParams[1])\n\t\t\tpVehicle->m_nZoneLevel = LEVEL_IGNORE;\n\t\telse\n\t\t\tpVehicle->m_nZoneLevel = CTheZones::GetLevelFromPosition(&pVehicle->GetPosition());\n\t\treturn 0;\n\t}\n\tcase COMMAND_MAKE_CRAIGS_CAR_A_BIT_STRONGER:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tscript_assert(pVehicle->m_vehType == VEHICLE_TYPE_CAR);\n\t\tCAutomobile* pCar = (CAutomobile*)pVehicle;\n\t\tpCar->bMoreResistantToDamage = ScriptParams[1];\n\t\treturn 0;\n\t}\n\t*/\n\tcase COMMAND_SET_JAMES_CAR_ON_PATH_TO_PLAYER:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tCCarCtrl::JoinCarWithRoadSystemGotoCoors(pVehicle, FindPlayerCoors(), false);\n\t\treturn 0;\n\t}\n\tcase COMMAND_LOAD_END_OF_GAME_TUNE:\n\t\tDMAudio.ChangeMusicMode(MUSICMODE_CUTSCENE);\n\t\tprintf(\"Start preload end of game audio\\n\");\n\t\tDMAudio.PreloadCutSceneMusic(STREAMED_SOUND_CUTSCENE_FINALE);\n\t\tprintf(\"End preload end of game audio\\n\");\n\t\treturn 0;\n\t/*\n\tcase COMMAND_ENABLE_PLAYER_CONTROL_CAMERA:\n\t\tCPad::GetPad(0)->SetEnablePlayerControls(PLAYERCONTROL_CAMERA);\n\t\treturn 0;\n\t*/\n\tcase COMMAND_SET_OBJECT_ROTATION:\n\t{\n\t\tCollectParameters(&m_nIp, 4);\n\t\tCObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pObject);\n\t\tCWorld::Remove(pObject);\n\t\tpObject->SetOrientation(\n\t\t\tDEGTORAD(*(float*)&ScriptParams[1]),\n\t\t\tDEGTORAD(*(float*)&ScriptParams[2]),\n\t\t\tDEGTORAD(*(float*)&ScriptParams[3]));\n\t\tpObject->GetMatrix().UpdateRW();\n\t\tpObject->UpdateRwFrame();\n\t\tCWorld::Add(pObject);\n\t\treturn 0;\n\t}\n\tcase COMMAND_GET_DEBUG_CAMERA_COORDINATES:\n\t\t*(CVector*)&ScriptParams[0] = TheCamera.Cams[2].Source;\n\t\tStoreParameters(&m_nIp, 3);\n\t\treturn 0;\n\t/*\n\tcase COMMAND_GET_DEBUG_CAMERA_FRONT_VECTOR:\n\t\t*(CVector*)&ScriptParams[0] = TheCamera.Cams[2].Front;\n\t\tStoreParameters(&m_nIp, 3);\n\t\treturn 0;\n\tcase COMMAND_IS_PLAYER_TARGETTING_ANY_CHAR:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;\n\t\tscript_assert(pPed);\n\t\tCEntity* pTarget = pPed->m_pPointGunAt;\n\t\tUpdateCompareFlag(pTarget && pTarget->IsPed());\n\t\treturn 0;\n\t}\n\t*/\n\tcase COMMAND_IS_PLAYER_TARGETTING_CHAR:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;\n\t\tscript_assert(pPed);\n\t\tCPed* pTestedPed = CPools::GetPedPool()->GetAt(ScriptParams[1]);\n\t\tscript_assert(pTestedPed);\n\t\tCEntity* pTarget = pPed->m_pPointGunAt;\n\t\tbool bTargetting = pTarget && pTarget->IsPed() && pTarget == pTestedPed;\n\t\t// PC shit\n\t\tstatic int nCounter = 0;\n\t\tnCounter = Max(0, nCounter - 1);\n\t\tif (!pPed->GetWeapon()->IsTypeMelee() && !bTargetting) {\n\t\t\tif ((pTestedPed->GetPosition() - TheCamera.GetPosition()).Magnitude() < 10.0f) {\n\t\t\t\tCVector vTestedPos(pTestedPed->GetPosition().x, pTestedPed->GetPosition().y, pTestedPed->GetPosition().z + 0.4);\n\t\t\t\tCVector vScreenPos;\n\t\t\t\tfloat w, h;\n\t\t\t\tif (CSprite::CalcScreenCoors(vTestedPos, &vScreenPos, &w, &h, false)) {\n\t\t\t\t\tCVector2D vCrosshairPosition(CCamera::m_f3rdPersonCHairMultX * RsGlobal.maximumWidth, CCamera::m_f3rdPersonCHairMultY * RsGlobal.maximumHeight);\n\t\t\t\t\tfloat fScreenDistance = ((CVector2D)vScreenPos - vCrosshairPosition).Magnitude();\n\t\t\t\t\tif (SCREEN_STRETCH_X(0.45f) > fScreenDistance / w) {\n\t\t\t\t\t\tCColPoint point;\n\t\t\t\t\t\tCEntity* entity;\n\t\t\t\t\t\tif (!CWorld::ProcessLineOfSight(TheCamera.GetPosition() + 2.0f * TheCamera.GetForward(),\n\t\t\t\t\t\t\tvTestedPos, point, entity, true, true, true, true, true, false) ||\n\t\t\t\t\t\t\tentity == pTestedPed) {\n\t\t\t\t\t\t\tnCounter += 2;\n\t\t\t\t\t\t\tif (nCounter > 20) {\n\t\t\t\t\t\t\t\tbTargetting = true;\n\t\t\t\t\t\t\t\tnCounter = 20;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tUpdateCompareFlag(bTargetting);\n\t\treturn 0;\n\t}\n\t/*\n\tcase COMMAND_IS_PLAYER_TARGETTING_OBJECT:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPlayerPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;\n\t\tscript_assert(pPed);\n\t\tCObject* pTestedObject = CPools::GetObjectPool()->GetAt(ScriptParams[1]);\n\t\tscript_assert(pTestedObject);\n\t\tCEntity* pTarget = pPed->m_pPointGunAt;\n\t\tUpdateCompareFlag(pTarget && pTarget->IsObject() && pTarget == pTestedObject);\n\t\treturn 0;\n\t}\n\t*/\n\tcase COMMAND_TERMINATE_ALL_SCRIPTS_WITH_THIS_NAME:\n\t{\n\t\tCTheScripts::ReadTextLabelFromScript(&m_nIp, tmp);\n\t\tfor (int i = 0; i < KEY_LENGTH_IN_SCRIPT; i++)\n\t\t\ttmp[i] = tolower(tmp[i]);\n\t\tm_nIp += 8;\n\t\tCRunningScript* pScript = CTheScripts::pActiveScripts;\n\t\twhile (pScript) {\n\t\t\tCRunningScript* pNext = pScript->next;\n\t\t\tif (strcmp(pScript->m_abScriptName, tmp) == 0) {\n\t\t\t\tpScript->RemoveScriptFromList(&CTheScripts::pActiveScripts);\n\t\t\t\tpScript->AddScriptToList(&CTheScripts::pIdleScripts);\n\t\t\t}\n\t\t\tpScript = pNext;\n\t\t}\n\t\treturn 0;\n\t}\n\tcase COMMAND_DISPLAY_TEXT_WITH_NUMBER:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\twchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\tCTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_fAtX = *(float*)&ScriptParams[0];\n\t\tCTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_fAtY = *(float*)&ScriptParams[1];\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCMessages::InsertNumberInString(text, ScriptParams[0], -1, -1, -1, -1, -1,\n\t\t\tCTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame++].m_Text);\n\t\treturn 0;\n\t}\n\tcase COMMAND_DISPLAY_TEXT_WITH_2_NUMBERS:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\twchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\tCTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_fAtX = *(float*)&ScriptParams[0];\n\t\tCTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame].m_fAtY = *(float*)&ScriptParams[1];\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCMessages::InsertNumberInString(text, ScriptParams[0], ScriptParams[1], -1, -1, -1, -1,\n\t\t\tCTheScripts::IntroTextLines[CTheScripts::NumberOfIntroTextLinesThisFrame++].m_Text);\n\t\treturn 0;\n\t}\n\tcase COMMAND_FAIL_CURRENT_MISSION:\n\t\tCTheScripts::FailCurrentMission = 2;\n\t\treturn 0;\n\tcase COMMAND_GET_CLOSEST_OBJECT_OF_TYPE:\n\t{\n\t\treturn 0;\n/*\n\t\tCollectParameters(&m_nIp, 5);\n\t\tCVector pos = *(CVector*)&ScriptParams[0];\n\t\tif (pos.z <= MAP_Z_LOW_LIMIT)\n\t\t\tpos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);\n\t\tfloat range = *(float*)&ScriptParams[3];\n\t\tint mi = ScriptParams[4] < 0 ? CTheScripts::UsedObjectArray[-ScriptParams[4]].index : ScriptParams[4];\n\t\tint16 total;\n\t\tCEntity* apEntities[16];\n\t\tCWorld::FindObjectsOfTypeInRange(mi, pos, range, true, &total, 16, apEntities, false, false, false, true, true);\n\t\tCEntity* pClosestEntity = nil;\n\t\tfloat min_dist = 2.0f * range;\n\t\tfor (int i = 0; i < total; i++) {\n\t\t\tfloat dist = (apEntities[i]->GetPosition() - pos).Magnitude();\n\t\t\tif (dist < min_dist) {\n\t\t\t\tmin_dist = dist;\n\t\t\t\tpClosestEntity = apEntities[i];\n\t\t\t}\n\t\t}\n\t\tif (pClosestEntity && pClosestEntity->IsDummy()) {\n\t\t\tCPopulation::ConvertToRealObject((CDummyObject*)pClosestEntity);\n\t\t\tCWorld::FindObjectsOfTypeInRange(mi, pos, range, true, &total, 16, apEntities, false, false, false, true, true);\n\t\t\tpClosestEntity = nil;\n\t\t\tfloat min_dist = 2.0f * range;\n\t\t\tfor (int i = 0; i < total; i++) {\n\t\t\t\tfloat dist = (apEntities[i]->GetPosition() - pos).Magnitude();\n\t\t\t\tif (dist < min_dist) {\n\t\t\t\t\tmin_dist = dist;\n\t\t\t\t\tpClosestEntity = apEntities[i];\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (pClosestEntity->IsDummy())\n\t\t\t\tpClosestEntity = nil;\n\t\t}\n\t\tif (pClosestEntity) {\n\t\t\tscript_assert(pClosestEntity->IsObject());\n\t\t\tCObject* pObject = (CObject*)pClosestEntity;\n\t\t\tpObject->ObjectCreatedBy = MISSION_OBJECT;\n\t\t\tScriptParams[0] = CPools::GetObjectPool()->GetIndex(pObject);\n\t\t} else {\n\t\t\tScriptParams[0] = -1;\n\t\t}\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n*/\n\t}\n\t/*\n\tcase COMMAND_PLACE_OBJECT_RELATIVE_TO_OBJECT:\n\t{\n\t\tCollectParameters(&m_nIp, 5);\n\t\tCObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pObject);\n\t\tCObject* pTarget = CPools::GetObjectPool()->GetAt(ScriptParams[1]);\n\t\tscript_assert(pTarget);\n\t\tCVector offset = *(CVector*)&ScriptParams[2];\n\t\tCPhysical::PlacePhysicalRelativeToOtherPhysical(pTarget, pObject, offset);\n\t\treturn 0;\n\t}\n\t*/\n\tcase COMMAND_SET_ALL_OCCUPANTS_OF_CAR_LEAVE_CAR:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tCCarAI::TellOccupantsToLeaveCar(pVehicle);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_INTERPOLATION_PARAMETERS:\n\t\tCollectParameters(&m_nIp, 2);\n\t\tTheCamera.SetParametersForScriptInterpolation(*(float*)&ScriptParams[0], 100.0f - *(float*)&ScriptParams[0], ScriptParams[1]);\n\t\treturn 0;\n\t/*\n\tcase COMMAND_GET_CLOSEST_CAR_NODE_WITH_HEADING_TOWARDS_POINT:\n\t{\n\t\tCollectParameters(&m_nIp, 5);\n\t\tCVector pos = *(CVector*)&ScriptParams[0];\n\t\tif (pos.z <= MAP_Z_LOW_LIMIT)\n\t\t\tpos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);\n\t\tfloat destX = *(float*)&ScriptParams[3];\n\t\tfloat destY = *(float*)&ScriptParams[4];\n\t\tint32 nid = ThePaths.FindNodeClosestToCoors(pos, 0, 999999.9f, true, true);\n\t\tCPathNode* pNode = &ThePaths.m_pathNodes[nid];\n\t\t*(CVector*)&ScriptParams[0] = pNode->GetPosition();\n\t\t*(float*)&ScriptParams[3] = ThePaths.FindNodeOrientationForCarPlacementFacingDestination(nid, destX, destY, true);\n\t\tStoreParameters(&m_nIp, 4);\n\t\treturn 0;\n\t}\n\tcase COMMAND_GET_CLOSEST_CAR_NODE_WITH_HEADING_AWAY_POINT:\n\t{\n\t\tCollectParameters(&m_nIp, 5);\n\t\tCVector pos = *(CVector*)&ScriptParams[0];\n\t\tif (pos.z <= MAP_Z_LOW_LIMIT)\n\t\t\tpos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);\n\t\tfloat destX = *(float*)&ScriptParams[3];\n\t\tfloat destY = *(float*)&ScriptParams[4];\n\t\tint32 nid = ThePaths.FindNodeClosestToCoors(pos, 0, 999999.9f, true, true);\n\t\tCPathNode* pNode = &ThePaths.m_pathNodes[nid];\n\t\t*(CVector*)&ScriptParams[0] = pNode->GetPosition();\n\t\t*(float*)&ScriptParams[3] = ThePaths.FindNodeOrientationForCarPlacementFacingDestination(nid, destX, destY, false);\n\t\tStoreParameters(&m_nIp, 4);\n\t\treturn 0;\n\t}\n\t*/\n\tcase COMMAND_GET_DEBUG_CAMERA_POINT_AT:\n\t\t*(CVector*)&ScriptParams[0] = TheCamera.Cams[2].Source + TheCamera.Cams[2].Front;\n\t\tStoreParameters(&m_nIp, 3);\n\t\treturn 0;\n\tcase COMMAND_ATTACH_CHAR_TO_CAR:\n\t{\n\t\tCollectParameters(&m_nIp, 8);\n\t\tCPed *pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tCVehicle *pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]);\n\t\tpPed->AttachPedToEntity(pVehicle, *(CVector*)&ScriptParams[2], ScriptParams[5], DEGTORAD(*(float*)&ScriptParams[6]), (eWeaponType)ScriptParams[7]);\n\t\treturn 0;\n\t}\n\tcase COMMAND_DETACH_CHAR_FROM_CAR:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed *pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tif (pPed && pPed->m_attachedTo)\n\t\t\tpPed->DettachPedFromEntity();\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_CAR_CHANGE_LANE: // for some reason changed in SA\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tpVehicle->AutoPilot.m_bStayInFastLane = !ScriptParams[1];\n\t\treturn 0;\n\t}\n\tcase COMMAND_CLEAR_CHAR_LAST_WEAPON_DAMAGE:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tif (pPed)\n\t\t\tpPed->m_lastWepDam = -1;\n\t\telse\n\t\t\tdebug(\"CLEAR_CHAR_LAST_WEAPON_DAMAGE - Character doesn't exist\\n\");\n\t\treturn 0;\n\t}\n\tcase COMMAND_CLEAR_CAR_LAST_WEAPON_DAMAGE:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tif (pVehicle)\n\t\t\tpVehicle->m_nLastWeaponDamage = -1;\n\t\telse\n\t\t\tdebug(\"CLEAR_CAR_LAST_WEAPON_DAMAGE - Vehicle doesn't exist\\n\");\n\t\treturn 0;\n\t}\n\tcase COMMAND_GET_RANDOM_COP_IN_AREA:\n\t{\n\t\tCollectParameters(&m_nIp, 9);\n\t\tint ped_handle = -1;\n\t\tCVector pos = FindPlayerCoors();\n\t\tfloat x1 = *(float*)&ScriptParams[0];\n\t\tfloat y1 = *(float*)&ScriptParams[1];\n\t\tfloat x2 = *(float*)&ScriptParams[2];\n\t\tfloat y2 = *(float*)&ScriptParams[3];\n\t\tint i = CPools::GetPedPool()->GetSize();\n\t\twhile (--i && ped_handle == -1) {\n\t\t\tCPed* pPed = CPools::GetPedPool()->GetSlot(i);\n\t\t\tif (!pPed)\n\t\t\t\tcontinue;\n\t\t\tif (CTheScripts::LastRandomPedId == CPools::GetPedPool()->GetIndex(pPed))\n\t\t\t\tcontinue;\n\t\t\tif (pPed->m_nPedType != PEDTYPE_COP)\n\t\t\t\tcontinue;\n\t\t\tif (!ThisIsAValidRandomCop(pPed->GetModelIndex(), ScriptParams[4], ScriptParams[5], ScriptParams[6], ScriptParams[7], ScriptParams[8]))\n\t\t\t\tcontinue;\n\t\t\tif (pPed->CharCreatedBy != RANDOM_CHAR)\n\t\t\t\tcontinue;\n\t\t\tif (!pPed->IsPedInControl() && pPed->GetPedState() != PED_DRIVING && pPed->GetPedState() != PED_ABSEIL)\n\t\t\t\tcontinue;\n\t\t\tif (pPed->bRemoveFromWorld)\n\t\t\t\tcontinue;\n\t\t\tif (pPed->bFadeOut)\n\t\t\t\tcontinue;\n\t\t\tif (pPed->bIsLeader || pPed->m_leader)\n\t\t\t\tcontinue;\n\t\t\tif (!pPed->IsWithinArea(x1, y1, x2, y2))\n\t\t\t\tcontinue;\n\t\t\tif (pos.z - COP_PED_FIND_Z_OFFSET > pPed->GetPosition().z)\n\t\t\t\tcontinue;\n\t\t\tif (pos.z + COP_PED_FIND_Z_OFFSET < pPed->GetPosition().z)\n\t\t\t\tcontinue;\n\t\t\tped_handle = CPools::GetPedPool()->GetIndex(pPed);\n\t\t\tCTheScripts::LastRandomPedId = ped_handle;\n\t\t\tpPed->CharCreatedBy = MISSION_CHAR;\n\t\t\tpPed->bRespondsToThreats = false;\n\t\t\t++CPopulation::ms_nTotalMissionPeds;\n\t\t\tif (m_bIsMissionScript)\n\t\t\t\tCTheScripts::MissionCleanUp.AddEntityToList(ped_handle, CLEANUP_CHAR);\n\t\t}\n\t\tScriptParams[0] = ped_handle;\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\t/*\n\tcase COMMAND_GET_RANDOM_COP_IN_ZONE:\n\t{\n\t\tchar zone[KEY_LENGTH_IN_SCRIPT];\n\t\tstrncpy(zone, (const char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT);\n\t\tint nZone = CTheZones::FindZoneByLabelAndReturnIndex(zone, ZONE_DEFAULT);\n\t\tif (nZone != -1)\n\t\t\tm_nIp += KEY_LENGTH_IN_SCRIPT;\n\t\tCZone* pZone = CTheZones::GetNavigationZone(nZone);\n\t\tint ped_handle = -1;\n\t\tCVector pos = FindPlayerCoors();\n\t\tint i = CPools::GetPedPool()->GetSize();\n\t\twhile (--i && ped_handle == -1) {\n\t\t\tCPed* pPed = CPools::GetPedPool()->GetSlot(i);\n\t\t\tif (!pPed)\n\t\t\t\tcontinue;\n\t\t\tif (CTheScripts::LastRandomPedId == CPools::GetPedPool()->GetIndex(pPed))\n\t\t\t\tcontinue;\n\t\t\tif (pPed->m_nPedType != PEDTYPE_COP)\n\t\t\t\tcontinue;\n\t\t\tif (pPed->CharCreatedBy != RANDOM_CHAR)\n\t\t\t\tcontinue;\n\t\t\tif (!pPed->IsPedInControl() && pPed->GetPedState() != PED_DRIVING)\n\t\t\t\tcontinue;\n\t\t\tif (pPed->bRemoveFromWorld)\n\t\t\t\tcontinue;\n\t\t\tif (pPed->bFadeOut)\n\t\t\t\tcontinue;\n\t\t\tif (pPed->bIsLeader || pPed->m_leader)\n\t\t\t\tcontinue;\n\t\t\tif (!CTheZones::PointLiesWithinZone(&pPed->GetPosition(), pZone))\n\t\t\t\tcontinue;\n\t\t\tif (pos.z - COP_PED_FIND_Z_OFFSET > pPed->GetPosition().z)\n\t\t\t\tcontinue;\n\t\t\tif (pos.z + COP_PED_FIND_Z_OFFSET < pPed->GetPosition().z)\n\t\t\t\tcontinue;\n\t\t\tped_handle = CPools::GetPedPool()->GetIndex(pPed);\n\t\t\tCTheScripts::LastRandomPedId = ped_handle;\n\t\t\tpPed->CharCreatedBy = MISSION_CHAR;\n\t\t\tpPed->bRespondsToThreats = false;\n\t\t\t++CPopulation::ms_nTotalMissionPeds;\n\t\t\tif (m_bIsMissionScript)\n\t\t\t\tCTheScripts::MissionCleanUp.AddEntityToList(ped_handle, CLEANUP_CHAR);\n\t\t}\n\t\tScriptParams[0] = ped_handle;\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\t*/\n\tcase COMMAND_SET_CHAR_OBJ_FLEE_CAR:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]);\n\t\tscript_assert(pVehicle);\n\t\tpPed->bScriptObjectiveCompleted = false;\n\t\tpPed->SetObjective(OBJECTIVE_FLEE_CAR, pVehicle);\n\t\treturn 0;\n\t}\n\tcase COMMAND_GET_DRIVER_OF_CAR:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tCPed* pDriver = pVehicle->pDriver;\n\t\tif (pDriver)\n\t\t\tScriptParams[0] = CPools::GetPedPool()->GetIndex(pDriver);\n\t\telse\n\t\t\tScriptParams[0] = -1;\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\tcase COMMAND_GET_NUMBER_OF_FOLLOWERS:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* pLeader = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pLeader);\n\t\tint total = 0;\n\t\tint i = CPools::GetPedPool()->GetSize();\n\t\twhile (--i) {\n\t\t\tCPed* pPed = CPools::GetPedPool()->GetSlot(i);\n\t\t\tif (!pPed)\n\t\t\t\tcontinue;\n\t\t\tif (pPed->m_leader == pLeader)\n\t\t\t\ttotal++;\n\t\t}\n\t\tScriptParams[0] = total;\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\tcase COMMAND_GIVE_REMOTE_CONTROLLED_MODEL_TO_PLAYER:\n\t{\n\t\tCollectParameters(&m_nIp, 6);\n\t\tCVector pos = *(CVector*)&ScriptParams[1];\n\t\tif (pos.z <= MAP_Z_LOW_LIMIT)\n\t\t\tpos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);\n\t\tCRemote::GivePlayerRemoteControlledCar(pos.x, pos.y, pos.z, DEGTORAD(*(float*)&ScriptParams[4]), ScriptParams[5]);\n\t\treturn 0;\n\t}\n\tcase COMMAND_GET_CURRENT_PLAYER_WEAPON:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;\n\t\tscript_assert(pPed);\n\t\tScriptParams[0] = pPed->GetWeapon()->m_eWeaponType;\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\tcase COMMAND_GET_CURRENT_CHAR_WEAPON:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tScriptParams[0] = pPed->GetWeapon()->m_eWeaponType;\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\tcase COMMAND_LOCATE_CHAR_ANY_MEANS_OBJECT_2D:\n\tcase COMMAND_LOCATE_CHAR_ON_FOOT_OBJECT_2D:\n\tcase COMMAND_LOCATE_CHAR_IN_CAR_OBJECT_2D:\n\tcase COMMAND_LOCATE_CHAR_ANY_MEANS_OBJECT_3D:\n\tcase COMMAND_LOCATE_CHAR_ON_FOOT_OBJECT_3D:\n\tcase COMMAND_LOCATE_CHAR_IN_CAR_OBJECT_3D:\n\t\tLocateCharObjectCommand(command, &m_nIp);\n\t\treturn 0;\n\tcase COMMAND_SET_CAR_TEMP_ACTION:\n\t{\n\t\tCollectParameters(&m_nIp, 3);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tpVehicle->AutoPilot.m_nTempAction = (uint8)ScriptParams[1];\n\t\tpVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + ScriptParams[2];\n\t\treturn 0;\n\t}\n\t/*\n\tcase COMMAND_SET_CAR_HANDBRAKE_TURN_RIGHT:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tpVehicle->AutoPilot.m_nTempAction = TEMPACT_HANDBRAKETURNRIGHT;\n\t\tpVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + ScriptParams[1];\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_CAR_HANDBRAKE_STOP:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tpVehicle->AutoPilot.m_nTempAction = TEMPACT_HANDBRAKESTRAIGHT;\n\t\tpVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + ScriptParams[1];\n\t\treturn 0;\n\t}\n\t*/\n\tcase COMMAND_IS_CHAR_ON_ANY_BIKE:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tUpdateCompareFlag(pPed->bInVehicle&& pPed->m_pMyVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_BIKE);\n\t\treturn 0;\n\t}\n\t/*\n\tcase COMMAND_LOCATE_SNIPER_BULLET_2D:\n\tcase COMMAND_LOCATE_SNIPER_BULLET_3D:\n\t\tLocateSniperBulletCommand(command, &m_nIp);\n\t\treturn 0;\n\t*/\n\tcase COMMAND_GET_NUMBER_OF_SEATS_IN_MODEL:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tScriptParams[0] = CVehicleModelInfo::GetMaximumNumberOfPassengersFromNumberOfDoors(ScriptParams[0]) + 1;\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\tcase COMMAND_IS_PLAYER_ON_ANY_BIKE:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;\n\t\tscript_assert(pPed);\n\t\tUpdateCompareFlag(pPed->bInVehicle && pPed->m_pMyVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_BIKE);\n\t\treturn 0;\n\t}\n\t/*\n\tcase COMMAND_IS_CHAR_LYING_DOWN:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tUpdateCompareFlag(pPed->bFallenDown);\n\t\treturn 0;\n\t}\n\t*/\n\tcase COMMAND_CAN_CHAR_SEE_DEAD_CHAR:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tint pedtype = ScriptParams[1];\n\t\tbool can = false;\n\t\tfor (int i = 0; i < pPed->m_numNearPeds; i++) {\n\t\t\tCPed* pTestPed = pPed->m_nearPeds[i];\n\t\t\tif (pTestPed->m_fHealth <= 0.0f && pTestPed->m_nPedType == pedtype && pPed->OurPedCanSeeThisOne(pTestPed))\n\t\t\t\tcan = true;\n\t\t}\n\t\tUpdateCompareFlag(can);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_ENTER_CAR_RANGE_MULTIPLIER:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed::nEnterCarRangeMultiplier = *(float*)&ScriptParams[0];\n\t\treturn 0;\n\tcase COMMAND_SET_THREAT_REACTION_RANGE_MULTIPLIER:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed::nThreatReactionRangeMultiplier = *(float*)&ScriptParams[0];\n\t\treturn 0;\n\tcase COMMAND_SET_CHAR_CEASE_ATTACK_TIMER:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tpPed->m_ceaseAttackTimer = ScriptParams[1];\n\t\treturn 0;\n\t}\n\tcase COMMAND_GET_REMOTE_CONTROLLED_CAR:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCVehicle* pVehicle = CWorld::Players[ScriptParams[0]].m_pRemoteVehicle;\n\t\tif (pVehicle)\n\t\t\tScriptParams[0] = CPools::GetVehiclePool()->GetIndex(pVehicle);\n\t\telse\n\t\t\tScriptParams[0] = -1;\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_PC_VERSION:\n\t\tUpdateCompareFlag(true);\n\t\treturn 0;\n\t//case COMMAND_REPLAY:\n\t//case COMMAND_IS_REPLAY_PLAYING:\n\tcase COMMAND_IS_MODEL_AVAILABLE:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tUpdateCompareFlag(CModelInfo::GetModelInfo(ScriptParams[0]) != nil);\n\t\treturn 0;\n\tcase COMMAND_SHUT_CHAR_UP:\n\t\tCollectParameters(&m_nIp, 2);\n\t\tDMAudio.SetPedTalkingStatus(CPools::GetPedPool()->GetAt(ScriptParams[0]), ScriptParams[1] == 0);\n\t\treturn 0;\n\tcase COMMAND_SET_ENABLE_RC_DETONATE:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCVehicle::bDisableRemoteDetonation = !ScriptParams[0];\n\t\treturn 0;\n\tcase COMMAND_SET_CAR_RANDOM_ROUTE_SEED:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tpVehicle->m_nRouteSeed = ScriptParams[1];\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_ANY_PICKUP_AT_COORDS:\n\t{\n\t\tCollectParameters(&m_nIp, 3);\n\t\tCVector pos = *(CVector*)&ScriptParams[0];\n\t\tCRunningScript::UpdateCompareFlag(CPickups::TestForPickupsInBubble(pos, 0.5f));\n\t\treturn 0;\n\t}\n\tcase COMMAND_GET_FIRST_PICKUP_COORDS:\n\tcase COMMAND_GET_NEXT_PICKUP_COORDS:\n\tcase COMMAND_REMOVE_ALL_CHAR_WEAPONS:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tpPed->ClearWeapons();\n\t\treturn 0;\n\t}\n\tcase COMMAND_HAS_PLAYER_GOT_WEAPON:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;\n\t\tscript_assert(pPed);\n\t\tbool bFound = false;\n\t\tfor (int i = 0; i < TOTAL_WEAPON_SLOTS; i++) {\n\t\t\tif (pPed->GetWeapon(i).m_eWeaponType == ScriptParams[1]) {\n\t\t\t\tbFound = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tUpdateCompareFlag(bFound);\n\t\treturn 0;\n\t}\n\t//case COMMAND_HAS_CHAR_GOT_WEAPON:\n\t//case COMMAND_IS_PLAYER_FACING_CHAR:\n\tcase COMMAND_SET_TANK_DETONATE_CARS:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle && pVehicle->m_vehType == VEHICLE_TYPE_CAR);\n\t\t((CAutomobile*)pVehicle)->bTankDetonateCars = ScriptParams[1];\n\t\treturn 0;\n\t}\n\tcase COMMAND_GET_POSITION_OF_ANALOGUE_STICKS:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPad* pPad = CPad::GetPad(ScriptParams[0]);\n\t\tScriptParams[0] = pPad->NewState.LeftStickX;\n\t\tScriptParams[1] = pPad->NewState.LeftStickY;\n\t\tScriptParams[2] = pPad->NewState.RightStickX;\n\t\tScriptParams[3] = pPad->NewState.RightStickY;\n\t\tStoreParameters(&m_nIp, 4);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_CAR_ON_FIRE:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tbool bOnFire = false;\n\t\tif (pVehicle->m_pCarFire)\n\t\t\tbOnFire = true;\n\t\tif (pVehicle->m_vehType == VEHICLE_TYPE_CAR && ((CAutomobile*)pVehicle)->Damage.GetEngineStatus() >= ENGINE_STATUS_ON_FIRE)\n\t\t\tbOnFire = true;\n\t\tif (pVehicle->m_fHealth < 250.0f)\n\t\t\tbOnFire = true;\n\t\tUpdateCompareFlag(bOnFire);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_CAR_TYRE_BURST:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tbool bIsBurst = false;\n\t\tCBike* pBike = (CBike*)pVehicle;\n\t\tif (pVehicle->IsBike()) {\n\t\t\tif (ScriptParams[1] == 4) {\n\t\t\t\tfor (int i = 0; i < 2; i++) {\n\t\t\t\t\tif (pBike->m_wheelStatus[i] == WHEEL_STATUS_BURST)\n\t\t\t\t\t\tbIsBurst = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tif (ScriptParams[1] == 2)\n\t\t\t\t\tScriptParams[1] = 0;\n\t\t\t\tif (ScriptParams[1] == 3)\n\t\t\t\t\tScriptParams[1] = 1;\n\t\t\t\tbIsBurst = pBike->m_wheelStatus[ScriptParams[1]] == WHEEL_STATUS_BURST;\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tCAutomobile* pCar = (CAutomobile*)pVehicle;\n\t\t\tif (ScriptParams[1] == 4) {\n\t\t\t\tfor (int i = 0; i < 4; i++) {\n\t\t\t\t\tif (pCar->Damage.GetWheelStatus(i) == WHEEL_STATUS_BURST)\n\t\t\t\t\t\tbIsBurst = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t\tbIsBurst = pCar->Damage.GetWheelStatus(ScriptParams[1] == WHEEL_STATUS_BURST);\n\t\t}\n\t\tUpdateCompareFlag(bIsBurst);\n\t\treturn 0;\n\t}\n\t//case COMMAND_SET_CAR_DRIVE_STRAIGHT_AHEAD:\n\t//case COMMAND_SET_CAR_WAIT:\n\t//case COMMAND_IS_PLAYER_STANDING_ON_A_VEHICLE:\n\t//case COMMAND_IS_PLAYER_FOOT_DOWN:\n\t//case COMMAND_IS_CHAR_FOOT_DOWN:\n\tcase COMMAND_INITIALISE_OBJECT_PATH: {\n\t\tCollectParameters(&m_nIp, 2);\n\t\tint32 counter = 0;\n\t\twhile (counter < 3 && CScriptPaths::aArray[counter].m_state != SCRIPT_PATH_DISABLED) {\n\t\t\tcounter++;\n\t\t}\n\t\tCScriptPaths::aArray[counter].InitialiseOne(ScriptParams[0], *(float*)&ScriptParams[1]);\n\t\tScriptParams[0] = counter;\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\tcase COMMAND_START_OBJECT_ON_PATH:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCObject *pObj = CPools::GetObjectPool()->GetAt(ScriptParams[0]);\n\t\tassert(pObj);\n\t\tCScriptPaths::aArray[ScriptParams[1]].SetObjectToControl(pObj);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_OBJECT_PATH_SPEED:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCScriptPaths::aArray[ScriptParams[0]].m_fSpeed = *(float*)&ScriptParams[1];\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_OBJECT_PATH_POSITION:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCScriptPaths::aArray[ScriptParams[0]].m_fPosition = *(float*)&ScriptParams[1];\n\t\treturn 0;\n\t}\n\t//case COMMAND_GET_OBJECT_DISTANCE_ALONG_PATH:\n\tcase COMMAND_CLEAR_OBJECT_PATH:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCScriptPaths::aArray[ScriptParams[0]].Clear();\n\t\treturn 0;\n\t}\n\tcase COMMAND_HELI_GOTO_COORDS:\n\t{\n\t\tCollectParameters(&m_nIp, 5);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle && pVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_HELI);\n\t\t((CAutomobile*)pVehicle)->TellHeliToGoToCoors(*(float*)&ScriptParams[1], *(float*)&ScriptParams[2], *(float*)&ScriptParams[3], ScriptParams[4]);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_INT_VAR_EQUAL_TO_CONSTANT:\n\t{\n\t\tint32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\tCollectParameters(&m_nIp, 1);\n\t\tUpdateCompareFlag(*ptr == ScriptParams[0]);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_INT_LVAR_EQUAL_TO_CONSTANT:\n\t{\n\t\tint32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\tCollectParameters(&m_nIp, 1);\n\t\tUpdateCompareFlag(*ptr == ScriptParams[0]);\n\t\treturn 0;\n\t}\n\tcase COMMAND_GET_DEAD_CHAR_PICKUP_COORDS:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed *pTarget = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tCVector pos;\n\t\tpTarget->CreateDeadPedPickupCoors(&pos.x, &pos.y, &pos.z);\n\t\t*(CVector*)&ScriptParams[0] = pos;\n\t\tStoreParameters(&m_nIp, 3);\n\t\treturn 0;\n\t}\n\tcase COMMAND_CREATE_PROTECTION_PICKUP:\n\t{\n\t\tCollectParameters(&m_nIp, 5);\n\t\tCVector pos = *(CVector*)&ScriptParams[0];\n\t\tif (pos.z <= MAP_Z_LOW_LIMIT)\n\t\t\tpos.z = CWorld::FindGroundZForCoord(pos.x, pos.y) + PICKUP_PLACEMENT_OFFSET;\n\t\tCPickups::GetActualPickupIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));\n\t\tScriptParams[0] = CPickups::GenerateNewOne(pos, MI_PICKUP_REVENUE, PICKUP_ASSET_REVENUE, ScriptParams[3], ScriptParams[4]);\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_CHAR_IN_ANY_BOAT:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tUpdateCompareFlag(pPed->bInVehicle && pPed->m_pMyVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_BOAT);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_PLAYER_IN_ANY_BOAT:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;\n\t\tscript_assert(pPed);\n\t\tUpdateCompareFlag(pPed->bInVehicle && pPed->m_pMyVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_BOAT);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_CHAR_IN_ANY_HELI:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tUpdateCompareFlag(pPed->bInVehicle && pPed->m_pMyVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_HELI);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_PLAYER_IN_ANY_HELI:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;\n\t\tscript_assert(pPed);\n\t\tUpdateCompareFlag(pPed->bInVehicle && pPed->m_pMyVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_HELI);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_CHAR_IN_ANY_PLANE:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tUpdateCompareFlag(pPed->bInVehicle && pPed->m_pMyVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_PLANE);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_PLAYER_IN_ANY_PLANE:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;\n\t\tscript_assert(pPed);\n\t\tUpdateCompareFlag(pPed->bInVehicle && pPed->m_pMyVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_HELI);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_CHAR_IN_WATER:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tUpdateCompareFlag(pPed && pPed->bIsInWater);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_VAR_INT_TO_CONSTANT:\n\t{\n\t\tint32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\tCollectParameters(&m_nIp, 1);\n\t\t*ptr = ScriptParams[0];\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_LVAR_INT_TO_CONSTANT:\n\t{\n\t\tint32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\tCollectParameters(&m_nIp, 1);\n\t\t*ptr = ScriptParams[0];\n\t\treturn 0;\n\t}\n\tdefault:\n\t\tscript_assert(0);\n\t}\n\treturn -1;\n}\n"
  },
  {
    "path": "src/control/Script7.cpp",
    "content": "#include \"common.h\"\n\n#include \"Script.h\"\n#include \"ScriptCommands.h\"\n\n#include \"CarCtrl.h\"\n#include \"ColStore.h\"\n#include \"Coronas.h\"\n#include \"CutsceneMgr.h\"\n#include \"DMAudio.h\"\n#include \"Explosion.h\"\n#include \"GameLogic.h\"\n#include \"General.h\"\n#include \"Glass.h\"\n#include \"Fluff.h\"\n#include \"Hud.h\"\n#include \"MBlur.h\"\n#include \"Pad.h\"\n#include \"Pickups.h\"\n#include \"Pools.h\"\n#include \"Population.h\"\n#include \"Radar.h\"\n#include \"RoadBlocks.h\"\n#include \"Ropes.h\"\n#include \"SetPieces.h\"\n#include \"SpecialFX.h\"\n#include \"Stats.h\"\n#include \"Streaming.h\"\n#include \"Timecycle.h\"\n#include \"User.h\"\n#include \"World.h\"\n#include \"Zones.h\"\n\nint8 CRunningScript::ProcessCommands1200To1299(int32 command)\n{\n\tswitch (command) {\n\tcase COMMAND_IS_INT_VAR_GREATER_THAN_CONSTANT:\n\t{\n\t\tint32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\tCollectParameters(&m_nIp, 1);\n\t\tUpdateCompareFlag(*ptr > ScriptParams[0]);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_INT_LVAR_GREATER_THAN_CONSTANT:\n\t{\n\t\tint32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\tCollectParameters(&m_nIp, 1);\n\t\tUpdateCompareFlag(*ptr > ScriptParams[0]);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_CONSTANT_GREATER_THAN_INT_VAR:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tint32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\tUpdateCompareFlag(ScriptParams[0] > *ptr);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_CONSTANT_GREATER_THAN_INT_LVAR:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tint32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\tUpdateCompareFlag(ScriptParams[0] > *ptr);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_INT_VAR_GREATER_OR_EQUAL_TO_CONSTANT:\n\t{\n\t\tint32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\tCollectParameters(&m_nIp, 1);\n\t\tUpdateCompareFlag(*ptr >= ScriptParams[0]);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_INT_LVAR_GREATER_OR_EQUAL_TO_CONSTANT:\n\t{\n\t\tint32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\tCollectParameters(&m_nIp, 1);\n\t\tUpdateCompareFlag(*ptr >= ScriptParams[0]);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_CONSTANT_GREATER_OR_EQUAL_TO_INT_VAR:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tint32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_GLOBAL);\n\t\tUpdateCompareFlag(ScriptParams[0] >= *ptr);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_CONSTANT_GREATER_OR_EQUAL_TO_INT_LVAR:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tint32* ptr = GetPointerToScriptVariable(&m_nIp, VAR_LOCAL);\n\t\tUpdateCompareFlag(ScriptParams[0] >= *ptr);\n\t\treturn 0;\n\t}\n\tcase COMMAND_GET_CHAR_WEAPON_IN_SLOT:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tScriptParams[0] = pPed->GetWeapon(ScriptParams[1] - 1).m_eWeaponType;\n\t\tScriptParams[1] = pPed->GetWeapon(ScriptParams[1] - 1).m_nAmmoTotal;\n\t\tScriptParams[2] = CPickups::ModelForWeapon((eWeaponType)ScriptParams[0]);\n\t\tStoreParameters(&m_nIp, 3);\n\t\treturn 0;\n\t}\n\tcase COMMAND_GET_CLOSEST_STRAIGHT_ROAD:\n\t{\n\t\tCollectParameters(&m_nIp, 5);\n\t\tint node1, node2;\n\t\tfloat angle;\n\t\tThePaths.FindNodePairClosestToCoors(*(CVector*)&ScriptParams[0], PATH_CAR, &node1, &node2, &angle,\n\t\t\t*(float*)&ScriptParams[3], *(float*)&ScriptParams[4], true, true);\n\t\tif (node1 == -1) {\n\t\t\tfor (int i = 0; i < 7; i++)\n\t\t\t\tScriptParams[i] = 0;\n\t\t}\n\t\telse {\n\t\t\t*(CVector*)&ScriptParams[0] = ThePaths.FindNodeCoorsForScript(node1);\n\t\t\t*(CVector*)&ScriptParams[3] = ThePaths.FindNodeCoorsForScript(node2);\n\t\t\t*(float*)&ScriptParams[6] = angle;\n\t\t}\n\t\tStoreParameters(&m_nIp, 7);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_CAR_FORWARD_SPEED:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tfloat speed = *(float*)&ScriptParams[1] / GAME_SPEED_TO_CARAI_SPEED;\n\t\tpVehicle->SetMoveSpeed(pVehicle->GetForward() * speed);\n\t\tif (pVehicle->IsRealHeli() && pVehicle->IsCar())\n\t\t\t((CAutomobile*)pVehicle)->m_aWheelSpeed[1] = 0.22f;\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_AREA_VISIBLE:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCGame::currArea = ScriptParams[0];\n\t\tCStreaming::RemoveBuildingsNotInArea(ScriptParams[0]); \n\t\treturn 0;\n\tcase COMMAND_SET_CUTSCENE_ANIM_TO_LOOP:\n\t{\n\t\tchar key[KEY_LENGTH_IN_SCRIPT];\n\t\tCTheScripts::ReadTextLabelFromScript(&m_nIp, key);\n\t\tm_nIp += KEY_LENGTH_IN_SCRIPT;\n\t\tCCutsceneMgr::SetCutsceneAnimToLoop(key);\n\t\treturn 0;\n\t}\n\tcase COMMAND_MARK_CAR_AS_CONVOY_CAR:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tpVehicle->bPartOfConvoy = ScriptParams[1];\n\t\treturn 0;\n\t}\n\tcase COMMAND_RESET_HAVOC_CAUSED_BY_PLAYER:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCWorld::Players[ScriptParams[0]].m_nHavocLevel = 0;\n\t\treturn 0;\n\t}\n\tcase COMMAND_GET_HAVOC_CAUSED_BY_PLAYER:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tScriptParams[0] = CWorld::Players[ScriptParams[0]].m_nHavocLevel;\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\tcase COMMAND_CREATE_SCRIPT_ROADBLOCK:\n\t{\n\t\tCollectParameters(&m_nIp, 6);\n\t\tCRoadBlocks::RegisterScriptRoadBlock(*(CVector*)&ScriptParams[0], *(CVector*)&ScriptParams[3]);\n\t\treturn 0;\n\t}\n\tcase COMMAND_CLEAR_ALL_SCRIPT_ROADBLOCKS:\n\t{\n\t\tCRoadBlocks::ClearScriptRoadBlocks();\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_CHAR_OBJ_WALK_TO_CHAR:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tCPed* pTargetPed = CPools::GetPedPool()->GetAt(ScriptParams[1]);\n\t\tscript_assert(pTargetPed);\n\t\tpPed->bScriptObjectiveCompleted = false;\n\t\tpPed->SetObjective(OBJECTIVE_GOTO_CHAR_ON_FOOT_WALKING, pTargetPed);\n\t\treturn 0;\n\t}\n\t//case COMMAND_IS_PICKUP_IN_ZONE:\n\tcase COMMAND_GET_OFFSET_FROM_CHAR_IN_WORLD_COORDS:\n\t{\n\t\tCollectParameters(&m_nIp, 4);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tCVector result = Multiply3x3(pPed->GetMatrix(), *(CVector*)&ScriptParams[1]) + pPed->GetPosition();\n\t\t*(CVector*)&ScriptParams[0] = result;\n\t\tStoreParameters(&m_nIp, 3);\n\t\treturn 0;\n\t}\n\tcase COMMAND_HAS_CHAR_BEEN_PHOTOGRAPHED:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tbool result = false;\n\t\tif (pPed->bHasBeenPhotographed) {\n\t\t\tresult = true;\n\t\t\tpPed->bHasBeenPhotographed = false;\n\t\t}\n\t\tUpdateCompareFlag(result);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_CHAR_OBJ_AIM_GUN_AT_CHAR:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tCPed* pTargetPed = CPools::GetPedPool()->GetAt(ScriptParams[1]);\n\t\tscript_assert(pTargetPed);\n\t\tpPed->bScriptObjectiveCompleted = false;\n\t\tpPed->SetObjective(OBJECTIVE_AIM_GUN_AT, pTargetPed);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SWITCH_SECURITY_CAMERA:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCSpecialFX::bVideoCam = ScriptParams[0] != 0;\n\t\treturn 0;\n\t}\n\t//case COMMAND_IS_CHAR_IN_FLYING_VEHICLE:\n\tcase COMMAND_IS_PLAYER_IN_FLYING_VEHICLE:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;\n\t\tscript_assert(pPed);\n\t\tUpdateCompareFlag(pPed->bInVehicle && (pPed->m_pMyVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_HELI || pPed->m_pMyVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_PLANE));\n\t\treturn 0;\n\t}\n\t//case COMMAND_HAS_SONY_CD_BEEN_READ:\n\t//case COMMAND_GET_NUMBER_OF_SONY_CDS_READ:\n\t//case COMMAND_ADD_SHORT_RANGE_BLIP_FOR_COORD_OLD:\n\t//case COMMAND_ADD_SHORT_RANGE_BLIP_FOR_COORD:\n\tcase COMMAND_ADD_SHORT_RANGE_SPRITE_BLIP_FOR_COORD:\n\t{\n\t\tCollectParameters(&m_nIp, 4);\n\t\tCVector pos = *(CVector*)&ScriptParams[0];\n\t\tif (pos.z <= MAP_Z_LOW_LIMIT)\n\t\t\tpos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);\n\t\tCRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));\n\t\tint id = CRadar::SetShortRangeCoordBlip(BLIP_COORD, pos, 5, BLIP_DISPLAY_BOTH);\n\t\tCRadar::SetBlipSprite(id, ScriptParams[3]);\n\t\tScriptParams[0] = id;\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\tcase COMMAND_ADD_MONEY_SPENT_ON_CLOTHES:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCStats::MoneySpentOnFashion(ScriptParams[0]);\n\t\treturn 0;\n\t\t\n\tcase COMMAND_SET_HELI_ORIENTATION:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCAutomobile* pHeli = (CAutomobile*)CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pHeli && pHeli->IsCar() && pHeli->IsRealHeli());\n\t\tfloat fAngle = DEGTORAD(*(float*)&ScriptParams[1] - 90.0f);\n\t\twhile (fAngle < 0.0f)\n\t\t\tfAngle += TWOPI;\n\t\twhile (fAngle > TWOPI)\n\t\t\tfAngle -= TWOPI;\n\t\tpHeli->SetHeliOrientation(fAngle);\n\t\treturn 0;\n\t}\n\tcase COMMAND_CLEAR_HELI_ORIENTATION:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCAutomobile* pHeli = (CAutomobile*)CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pHeli && pHeli->IsCar() && pHeli->IsRealHeli());\n\t\tpHeli->ClearHeliOrientation();\n\t\treturn 0;\n\t}\n\tcase COMMAND_PLANE_GOTO_COORDS:\n\t{\n\t\tCollectParameters(&m_nIp, 5);\n\t\tCAutomobile* pPlane = (CAutomobile*)CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPlane && pPlane->IsCar() && pPlane->IsRealPlane());\n\t\tpPlane->TellPlaneToGoToCoors(*(float*)&ScriptParams[1], *(float*)&ScriptParams[2], *(float*)&ScriptParams[3], ScriptParams[4]);\n\t\treturn 0;\n\t}\n\tcase COMMAND_GET_NTH_CLOSEST_CAR_NODE:\n\t{\n\t\tCollectParameters(&m_nIp, 4);\n\t\tCVector pos = *(CVector*)&ScriptParams[0];\n\t\tif (pos.z <= MAP_Z_LOW_LIMIT)\n\t\t\tpos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);\n\t\t*(CVector*)&ScriptParams[0] = ThePaths.FindNodeCoorsForScript(ThePaths.FindNthNodeClosestToCoors(pos, 0, 999999.9f, true, true, ScriptParams[3] - 1));\n\t\tStoreParameters(&m_nIp, 3);\n\t\treturn 0;\n\t}\n\t//case COMMAND_GET_NTH_CLOSEST_CHAR_NODE:\n\tcase COMMAND_DRAW_WEAPONSHOP_CORONA:\n\t{\n\t\tCollectParameters(&m_nIp, 9);\n\t\tCVector pos = *(CVector*)&ScriptParams[0];\n\t\tif (pos.z <= MAP_Z_LOW_LIMIT)\n\t\t\tpos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);\n\t\tCCoronas::RegisterCorona((uintptr)this + m_nIp, ScriptParams[6], ScriptParams[7], ScriptParams[8], 255, pos, *(float*)&ScriptParams[3],\n\t\t\t150.0f, ScriptParams[4], ScriptParams[5], 1, 0, 0, 0.0f, false, 0.2f);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_ENABLE_RC_DETONATE_ON_CONTACT:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCVehicle::bDisableRemoteDetonationOnContact = (ScriptParams[0] == 0);\n\t\treturn 0;\n\t}\n\tcase COMMAND_FREEZE_CHAR_POSITION:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tpPed->bIsFrozen = ScriptParams[1];\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_CHAR_DROWNS_IN_WATER:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tpPed->bDrownsInWater = ScriptParams[1];\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_OBJECT_RECORDS_COLLISIONS:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pObject);\n\t\tpObject->bUseCollisionRecords = ScriptParams[1];\n\t\treturn 0;\n\t}\n\tcase COMMAND_HAS_OBJECT_COLLIDED_WITH_ANYTHING:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pObject);\n\t\tUpdateCompareFlag(pObject->m_nCollisionRecords != 0);\n\t\treturn 0;\n\t}\n\tcase COMMAND_REMOVE_RC_BUGGY:\n\t{\n\t\tCWorld::Players[CWorld::PlayerInFocus].BlowUpRCBuggy(false);\n\t\treturn 0;\n\t}\n\t//case COMMAND_HAS_PHOTOGRAPH_BEEN_TAKEN:\n\tcase COMMAND_GET_CHAR_ARMOUR:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tScriptParams[0] = pPed->m_fArmour;\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\t//case COMMAND_SET_CHAR_ARMOUR:\n\tcase COMMAND_SET_HELI_STABILISER:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tpVehicle->bHeliMinimumTilt = ScriptParams[1];\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_CAR_STRAIGHT_LINE_DISTANCE:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tpVehicle->AutoPilot.m_nSwitchDistance = ScriptParams[1];\n\t\treturn 0;\n\t}\n\tcase COMMAND_POP_CAR_BOOT:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCAutomobile* pCar = (CAutomobile*)CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pCar&& pCar->IsCar());\n\t\tpCar->PopBoot();\n\t\treturn 0;\n\t}\n\tcase COMMAND_SHUT_PLAYER_UP:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tDMAudio.ShutUpPlayerTalking(!!ScriptParams[1]);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_PLAYER_MOOD:\n\t{\n\t\tCollectParameters(&m_nIp, 3);\n\t\tDMAudio.SetPlayersMood(ScriptParams[1], ScriptParams[2]);\n\t\treturn 0;\n\t}\n\tcase COMMAND_REQUEST_COLLISION:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCVector2D pos;\n\t\tpos.x = *(float*)&ScriptParams[0];\n\t\tpos.y = *(float*)&ScriptParams[1];\n\t\tCColStore::RequestCollision(pos);\n\t\treturn 0;\n\t}\n\tcase COMMAND_LOCATE_OBJECT_2D:\n\tcase COMMAND_LOCATE_OBJECT_3D:\n\t\tLocateObjectCommand(command, &m_nIp);\n\t\treturn 0;\n\tcase COMMAND_IS_OBJECT_IN_WATER:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pObject);\n\t\tUpdateCompareFlag(pObject->bIsInWater);\n\t\treturn 0;\n\t}\n\t//case COMMAND_SET_CHAR_OBJ_STEAL_ANY_CAR_EVEN_MISSION_CAR:\n\tcase COMMAND_IS_OBJECT_IN_AREA_2D:\n\tcase COMMAND_IS_OBJECT_IN_AREA_3D:\n\t\tObjectInAreaCheckCommand(command, &m_nIp);\n\t\treturn 0;\n\tcase COMMAND_SET_CHAR_CROUCH:\n\t{\n\t\tCollectParameters(&m_nIp, 3);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tif (ScriptParams[1]) {\n\t\t\tpPed->bCrouchWhenShooting = true;\n\t\t\tpPed->SetDuck(ScriptParams[2], true);\n\t\t}\n\t\telse {\n\t\t\tpPed->ClearDuck(true);\n\t\t\tpPed->bCrouchWhenShooting = false;\n\t\t}\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_ZONE_CIVILIAN_CAR_INFO:\n\t{\n\t\tchar label[12];\n\t\tint16 carDensities[CCarCtrl::NUM_CAR_CLASSES] = { 0 };\n\t\tint16 boatDensities[CCarCtrl::NUM_BOAT_CLASSES] = { 0 };\n\t\tint i;\n\n\t\tCTheScripts::ReadTextLabelFromScript(&m_nIp, label);\n\t\tm_nIp += KEY_LENGTH_IN_SCRIPT;\n\t\tCollectParameters(&m_nIp, 12);\n\t\tfor (i = 0; i < CCarCtrl::NUM_CAR_CLASSES; i++)\n\t\t\tcarDensities[i] = ScriptParams[i + 1];\n\t\tfor (i = 0; i < CCarCtrl::NUM_BOAT_CLASSES; i++)\n\t\t\tboatDensities[i] = ScriptParams[i + 1 + CCarCtrl::NUM_CAR_CLASSES];\n\t\tint zone = CTheZones::FindZoneByLabelAndReturnIndex(label, ZONE_INFO);\n\t\tif (zone < 0) {\n\t\t\tdebug(\"Couldn't find zone - %s\\n\", label);\n\t\t\treturn 0;\n\t\t}\n\t\twhile (zone >= 0) {\n\t\t\tCTheZones::SetZoneCivilianCarInfo(zone, ScriptParams[0], carDensities, boatDensities);\n\t\t\tzone = CTheZones::FindNextZoneByLabelAndReturnIndex(label, ZONE_INFO);\n\t\t}\n\t\treturn 0;\n\t}\n\tcase COMMAND_REQUEST_ANIMATION:\n\t{\n\t\tchar key[KEY_LENGTH_IN_SCRIPT];\n\t\tCTheScripts::ReadTextLabelFromScript(&m_nIp, key);\n\t\tm_nIp += KEY_LENGTH_IN_SCRIPT;\n\t\tCStreaming::RequestAnim(CAnimManager::GetAnimationBlockIndex(key), STREAMFLAGS_SCRIPTOWNED);\n\t\treturn 0;\n\t}\n\tcase COMMAND_HAS_ANIMATION_LOADED:\n\t{\n\t\tchar key[KEY_LENGTH_IN_SCRIPT];\n\t\tCTheScripts::ReadTextLabelFromScript(&m_nIp, key);\n\t\tm_nIp += KEY_LENGTH_IN_SCRIPT;\n\t\tUpdateCompareFlag(CAnimManager::GetAnimationBlock(key)->isLoaded);\n\t\treturn 0;\n\t}\n\tcase COMMAND_REMOVE_ANIMATION:\n\t{\n\t\tchar key[KEY_LENGTH_IN_SCRIPT];\n\t\tCTheScripts::ReadTextLabelFromScript(&m_nIp, key);\n\t\tm_nIp += KEY_LENGTH_IN_SCRIPT;\n\t\tCStreaming::RemoveAnim(CAnimManager::GetAnimationBlockIndex(key));\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_CHAR_WAITING_FOR_WORLD_COLLISION:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tUpdateCompareFlag(pPed->bIsStaticWaitingForCollision);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_CAR_WAITING_FOR_WORLD_COLLISION:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tUpdateCompareFlag(pVehicle->bIsStaticWaitingForCollision);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_OBJECT_WAITING_FOR_WORLD_COLLISION:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pObject);\n\t\tUpdateCompareFlag(pObject->bIsStaticWaitingForCollision);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_CHAR_SHUFFLE_INTO_DRIVERS_SEAT:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tpPed->PedShuffle();\n\t\treturn 0;\n\t}\n\tcase COMMAND_ATTACH_CHAR_TO_OBJECT:\n\t{\n\t\tCollectParameters(&m_nIp, 8);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tCObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[1]);\n\t\tpPed->AttachPedToEntity(pObject, *(CVector*)&ScriptParams[2], ScriptParams[5], DEGTORAD(ScriptParams[6]), (eWeaponType)ScriptParams[7]);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_CHAR_AS_PLAYER_FRIEND:\n\t{\n\t\tCollectParameters(&m_nIp, 3);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tpPed->bIsPlayerFriend = ScriptParams[2];\n\t\treturn 0;\n\t}\n\t//case COMMAND_DISPLAY_NTH_ONSCREEN_COUNTER:\n\tcase COMMAND_DISPLAY_NTH_ONSCREEN_COUNTER_WITH_STRING:\n\t{\n\t\tchar onscreen_str[12];\n\t\tscript_assert(CTheScripts::ScriptSpace[m_nIp++] == ARGUMENT_GLOBALVAR);\n\t\tuint16 var = CTheScripts::Read2BytesFromScript(&m_nIp);\n\t\tCollectParameters(&m_nIp, 2);\n\t\twchar* text = TheText.Get((char*)&CTheScripts::ScriptSpace[m_nIp]); // ???\n\t\tstrncpy(onscreen_str, (char*)&CTheScripts::ScriptSpace[m_nIp], KEY_LENGTH_IN_SCRIPT);\n\t\tm_nIp += KEY_LENGTH_IN_SCRIPT;\n\t\tCUserDisplay::OnscnTimer.AddCounter(var, ScriptParams[0], onscreen_str, ScriptParams[1] - 1);\n\t\treturn 0;\n\t}\n\tcase COMMAND_ADD_SET_PIECE:\n\t{\n\t\tCollectParameters(&m_nIp, 13);\n\t\tCSetPieces::AddOne(ScriptParams[0],\n\t\t\t*(CVector2D*)&ScriptParams[1], *(CVector2D*)&ScriptParams[3],\n\t\t\t*(CVector2D*)&ScriptParams[5], *(CVector2D*)&ScriptParams[7],\n\t\t\t*(CVector2D*)&ScriptParams[9], *(CVector2D*)&ScriptParams[11]);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_EXTRA_COLOURS:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCTimeCycle::StartExtraColour(ScriptParams[0]-1, ScriptParams[1] != 0);\n\t\treturn 0;\n\t}\n\tcase COMMAND_CLEAR_EXTRA_COLOURS:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCTimeCycle::StopExtraColour(ScriptParams[0]);\n\t\treturn 0;\n\t}\n\t//case COMMAND_CLOSE_CAR_BOOT:\n\tcase COMMAND_GET_WHEELIE_STATS:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPlayerInfo* pPlayerInfo = &CWorld::Players[ScriptParams[0]];\n\t\tScriptParams[0] = pPlayerInfo->m_nLastTimeCarSpentOnTwoWheels;\n\t\t*(float*)&ScriptParams[1] = pPlayerInfo->m_nLastDistanceCarTravelledOnTwoWheels;\n\t\tScriptParams[2] = pPlayerInfo->m_nLastTimeSpentOnWheelie;\n\t\t*(float*)&ScriptParams[3] = pPlayerInfo->m_nLastDistanceTravelledOnWheelie;\n\t\tScriptParams[4] = pPlayerInfo->m_nLastTimeSpentOnStoppie;\n\t\t*(float*)&ScriptParams[5] = pPlayerInfo->m_nLastDistanceTravelledOnStoppie;\n\t\tStoreParameters(&m_nIp, 6);\n\t\tpPlayerInfo->m_nLastTimeCarSpentOnTwoWheels = 0;\n\t\tpPlayerInfo->m_nLastDistanceCarTravelledOnTwoWheels = 0.0f;\n\t\tpPlayerInfo->m_nLastTimeSpentOnWheelie = 0;\n\t\tpPlayerInfo->m_nLastDistanceTravelledOnWheelie = 0.0f;\n\t\tpPlayerInfo->m_nLastTimeSpentOnStoppie = 0;\n\t\tpPlayerInfo->m_nLastDistanceTravelledOnStoppie = 0.0f;\n\t\treturn 0;\n\t}\n\t//case COMMAND_DISARM_CHAR:\n\tcase COMMAND_BURST_CAR_TYRE:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tif (pVehicle->IsBike()) {\n\t\t\tif (ScriptParams[1] == 2)\n\t\t\t\tScriptParams[1] = 0;\n\t\t\telse if (ScriptParams[1] == 3)\n\t\t\t\tScriptParams[1] = 1;\n\t\t\tpVehicle->BurstTyre(ScriptParams[1], true);\n\t\t}\n\t\telse {\n\t\t\tpVehicle->BurstTyre(ScriptParams[1], true);\n\t\t}\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_CHAR_OBJ_NO_OBJ:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tUpdateCompareFlag(pPed->m_prevObjective == OBJECTIVE_NONE && pPed->m_objective == OBJECTIVE_NONE);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_PLAYER_WEARING:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tchar key[12];\n\t\tCTheScripts::ReadTextLabelFromScript(&m_nIp, key);\n\t\tm_nIp += KEY_LENGTH_IN_SCRIPT;\n\t\tfor (int i = 0; i < KEY_LENGTH_IN_SCRIPT; i++)\n\t\t\tkey[i] = tolower(key[i]);\n\t\tCPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;\n\t\tscript_assert(pPed);\n\t\tUpdateCompareFlag(strcmp(key, CModelInfo::GetModelInfo(pPed->GetModelIndex())->GetModelName()) == 0);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_PLAYER_CAN_DO_DRIVE_BY:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPlayerInfo* pPlayerInfo = &CWorld::Players[ScriptParams[0]];\n\t\tpPlayerInfo->m_bDriveByAllowed = ScriptParams[1];\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_CHAR_OBJ_SPRINT_TO_COORD:\n\t{\n\t\tCollectParameters(&m_nIp, 3);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tCVector pos;\n\t\tpos.x = *(float*)&ScriptParams[1];\n\t\tpos.y = *(float*)&ScriptParams[2];\n\t\tpos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);\n\t\tpPed->bScriptObjectiveCompleted = false;\n\t\tpPed->SetObjective(OBJECTIVE_SPRINT_TO_AREA, pos);\n\t\treturn 0;\n\t}\n\tcase COMMAND_CREATE_SWAT_ROPE:\n\t{\n\t\tCollectParameters(&m_nIp, 3);\n\t\tCRopes::CreateRopeWithSwatComingDown(*(CVector*)&ScriptParams[0]);\n\t\treturn 0;\n\t}\n\t//case COMMAND_SET_FIRST_PERSON_CONTROL_CAMERA:\n\t//case COMMAND_GET_NEAREST_TYRE_TO_POINT:\n\tcase COMMAND_SET_CAR_MODEL_COMPONENTS:\n\t{\n\t\tCollectParameters(&m_nIp, 3);\n\t\tCVehicleModelInfo::SetComponentsToUse(ScriptParams[1], ScriptParams[2]);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SWITCH_LIFT_CAMERA:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCSpecialFX::bLiftCam = ScriptParams[0] != 0;\n\t\treturn 0;\n\t}\n\tcase COMMAND_CLOSE_ALL_CAR_DOORS:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCAutomobile* pCar = (CAutomobile*)CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pCar&& pCar->IsCar());\n\t\tpCar->CloseAllDoors();\n\t\treturn 0;\n\t}\n\tcase COMMAND_GET_DISTANCE_BETWEEN_COORDS_2D:\n\t{\n\t\tCollectParameters(&m_nIp, 4);\n\t\t*(float*)&ScriptParams[0] = (*(CVector2D*)&ScriptParams[0] - *(CVector2D*)&ScriptParams[2]).Magnitude();\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\tcase COMMAND_GET_DISTANCE_BETWEEN_COORDS_3D:\n\t{\n\t\tCollectParameters(&m_nIp, 6);\n\t\t*(float*)&ScriptParams[0] = (*(CVector*)&ScriptParams[0] - *(CVector*)&ScriptParams[3]).Magnitude();\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\tcase COMMAND_POP_CAR_BOOT_USING_PHYSICS:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCAutomobile* pCar = (CAutomobile*)CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pCar && pCar->IsCar());\n\t\tpCar->PopBootUsingPhysics();\n\t\treturn 0;\n\t}\n\t//case COMMAND_SET_FIRST_PERSON_WEAPON_CAMERA:\n\tcase COMMAND_IS_CHAR_LEAVING_VEHICLE_TO_DIE:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tUpdateCompareFlag(pPed->m_objective == OBJECTIVE_LEAVE_CAR_AND_DIE);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SORT_OUT_OBJECT_COLLISION_WITH_CAR:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pObject);\n\t\tpObject->m_pCollidingEntity = CPools::GetVehiclePool()->GetAt(ScriptParams[1]);\n\t\treturn 0;\n\t}\n\t//case COMMAND_GET_MAX_WANTED_LEVEL:\n\tcase COMMAND_IS_CHAR_WANDER_PATH_CLEAR:\n\t{\n\t\tCollectParameters(&m_nIp, 5);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tUpdateCompareFlag(CWorld::IsWanderPathClear(pPed->GetPosition(), *(CVector*)&ScriptParams[0], *(float*)&ScriptParams[3], 4));\n\t\treturn 0;\n\t}\n\t//case COMMAND_PRINT_HELP_WITH_NUMBER:\n\tcase COMMAND_PRINT_HELP_FOREVER:\n\t{\n\t\twchar* text = CTheScripts::GetTextByKeyFromScript(&m_nIp);\n\t\tCHud::SetHelpMessage(text, false, true);\n\t\treturn 0;\n\t}\n\t//case COMMAND_PRINT_HELP_FOREVER_WITH_NUMBER:\n\tdefault:\n\t\tscript_assert(0);\n\t}\n\treturn -1;\n}\n\nint8 CRunningScript::ProcessCommands1300To1399(int32 command)\n{\n\tswitch (command) {\n\tcase COMMAND_SET_CHAR_CAN_BE_DAMAGED_BY_MEMBERS_OF_GANG:\n\t{\n\t\tCollectParameters(&m_nIp, 3);\n\t\tCPed* pTarget = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pTarget);\n\t\tuint8 flag = 1 << (uint8)ScriptParams[1];\n\t\tif (ScriptParams[2])\n\t\t\tpTarget->m_gangFlags |= flag;\n\t\telse\n\t\t\tpTarget->m_gangFlags &= ~flag;\n\n\t\treturn 0;\n\t}\n\tcase COMMAND_LOAD_AND_LAUNCH_MISSION_EXCLUSIVE:\n\t\treturn 0;\n\t//case COMMAND_IS_MISSION_AUDIO_PLAYING:\n\tcase COMMAND_CREATE_LOCKED_PROPERTY_PICKUP:\n\t{\n\t\tCollectParameters(&m_nIp, 3);\n\t\tCVector pos = *(CVector*)&ScriptParams[0];\n\t\tif (pos.z <= MAP_Z_LOW_LIMIT)\n\t\t\tpos.z = CWorld::FindGroundZForCoord(pos.x, pos.y) + PICKUP_PLACEMENT_OFFSET;\n\t\tchar key[KEY_LENGTH_IN_SCRIPT];\n\t\tCTheScripts::ReadTextLabelFromScript(&m_nIp, key);\n\t\tm_nIp += KEY_LENGTH_IN_SCRIPT;\n\t\t// TheText.Get(key);\n\t\tCPickups::GetActualPickupIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));\n\t\tScriptParams[0] = CPickups::GenerateNewOne(pos, MI_PICKUP_PROPERTY, PICKUP_PROPERTY_LOCKED, 0, 0, false, key);\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\tcase COMMAND_CREATE_FORSALE_PROPERTY_PICKUP:\n\t{\n\t\tCollectParameters(&m_nIp, 4);\n\t\tCVector pos = *(CVector*)&ScriptParams[0];\n\t\tif (pos.z <= MAP_Z_LOW_LIMIT)\n\t\t\tpos.z = CWorld::FindGroundZForCoord(pos.x, pos.y) + PICKUP_PLACEMENT_OFFSET;\n\t\tchar key[KEY_LENGTH_IN_SCRIPT];\n\t\tCTheScripts::ReadTextLabelFromScript(&m_nIp, key);\n\t\tm_nIp += KEY_LENGTH_IN_SCRIPT;\n\t\t// TheText.Get(key);\n\t\tCPickups::GetActualPickupIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));\n\t\tScriptParams[0] = CPickups::GenerateNewOne(pos, MI_PICKUP_PROPERTY_FORSALE, PICKUP_PROPERTY_FORSALE, ScriptParams[3], 0, false, key);\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\tcase COMMAND_FREEZE_CAR_POSITION:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tpVehicle->bIsFrozen = ScriptParams[1];\n\t\tpVehicle->bInfiniteMass = ScriptParams[1];\n\t\treturn 0;\n\t}\n\tcase COMMAND_HAS_CHAR_BEEN_DAMAGED_BY_CHAR:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tCPed* pTestedPed = CPools::GetPedPool()->GetAt(ScriptParams[1]);\n\t\tbool result = false;\n\t\tif (pPed) {\n\t\t\tif (pPed->m_lastDamEntity) {\n\t\t\t\tif (pPed->m_lastDamEntity == pTestedPed)\n\t\t\t\t\tresult = true;\n\t\t\t\tif (pTestedPed->bInVehicle && pPed->m_lastDamEntity == pTestedPed->m_pMyVehicle)\n\t\t\t\t\tresult = true;\n\t\t\t}\n\t\t}else\n\t\t\tdebug(\"HAS_CHAR_BEEN_DAMAGED_BY_CHAR - First character doesn't exist\\n\");\n\t\tUpdateCompareFlag(result);\n\t\treturn 0;\n\t}\n\t//case COMMAND_HAS_CHAR_BEEN_DAMAGED_BY_CAR:\n\t//case COMMAND_HAS_CAR_BEEN_DAMAGED_BY_CHAR:\n\t//case COMMAND_HAS_CAR_BEEN_DAMAGED_BY_CAR:\n\t//case COMMAND_GET_RADIO_CHANNEL:\n\t//case COMMAND_DISPLAY_TEXT_WITH_3_NUMBERS:\n\t//case COMMAND_IS_CAR_DROWNING_IN_WATER:\n\tcase COMMAND_IS_CHAR_DROWNING_IN_WATER:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tUpdateCompareFlag(pPed && pPed->bIsDrowning);\n\t\treturn 0;\n\t}\n\tcase COMMAND_DISABLE_CUTSCENE_SHADOWS:\n\t{\n\t\tCCutsceneMgr::DisableCutsceneShadows();\n\t\treturn 0;\n\t}\n\tcase COMMAND_HAS_GLASS_BEEN_SHATTERED_NEARBY:\n\t{\n\t\tCollectParameters(&m_nIp, 3);\n\t\t\n\t\tbool shattered = false;\n\t\tif ( CGlass::HasGlassBeenShatteredAtCoors(*(float*)&ScriptParams[0], *(float*)&ScriptParams[1], *(float*)&ScriptParams[2]) )\n\t\t\tshattered = true;\n\t\t\n\t\tUpdateCompareFlag(shattered);\n\t\treturn 0;\n\t}\n\tcase COMMAND_ATTACH_CUTSCENE_OBJECT_TO_BONE:\n\t{\n\t\tCollectParameters(&m_nIp, 3);\n\t\tCCutsceneMgr::AttachObjectToBone(CPools::GetObjectPool()->GetAt(ScriptParams[0]), CPools::GetObjectPool()->GetAt(ScriptParams[1]), ScriptParams[2]);\n\t\treturn 0;\n\t}\n\tcase COMMAND_ATTACH_CUTSCENE_OBJECT_TO_COMPONENT:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCObject *obj1 = CPools::GetObjectPool()->GetAt(ScriptParams[0]);\n\t\tCObject *obj2 = CPools::GetObjectPool()->GetAt(ScriptParams[1]);\n\n\t\tchar key[KEY_LENGTH_IN_SCRIPT];\n\t\tCTheScripts::ReadTextLabelFromScript(&m_nIp, key);\n\t\tm_nIp += KEY_LENGTH_IN_SCRIPT;\n\n\t\tCCutsceneMgr::AttachObjectToFrame(obj1, obj2, key);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_CHAR_STAY_IN_CAR_WHEN_JACKED:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tpPed->bStayInCarOnJack = ScriptParams[1];\n\t\treturn 0;\n\t}\n\t//case COMMAND_IS_MISSION_AUDIO_LOADING:\n\tcase COMMAND_ADD_MONEY_SPENT_ON_WEAPONS:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCStats::MoneySpentOnWeapons(ScriptParams[0]);\n\t\treturn 0;\n\tcase COMMAND_ADD_MONEY_SPENT_ON_PROPERTY:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCStats::MoneySpentOnProperty(ScriptParams[0]);\n\t\treturn 0;\n\t//case COMMAND_ADD_MONEY_SPENT_ON_AUTO_PAINTING:\n\tcase COMMAND_SET_CHAR_ANSWERING_MOBILE:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tif (ScriptParams[1])\n\t\t\tpPed->SetAnswerMobile();\n\t\telse\n\t\t\tpPed->ClearAnswerMobile();\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_PLAYER_DRUNKENNESS:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPlayerInfo* pPlayerInfo = &CWorld::Players[ScriptParams[0]];\n\t\tpPlayerInfo->m_pPed->m_nDrunkenness = ScriptParams[1];\n\t\tpPlayerInfo->m_pPed->m_nFadeDrunkenness = 0;\n\t\tif (pPlayerInfo->m_pPed->m_nDrunkenness == 0)\n\t\t\tCMBlur::ClearDrunkBlur();\n\t\treturn 0;\n\t}\n\t//case COMMAND_GET_PLAYER_DRUNKENNESS:\n\t//case COMMAND_SET_PLAYER_DRUG_LEVEL:\n\t//case COMMAND_GET_PLAYER_DRUG_LEVEL:\n\t//case COMMAND_ADD_LOAN_SHARK_VISITS:\n\tcase COMMAND_ADD_STORES_KNOCKED_OFF:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCStats::NumOfStoresKnockedOff(ScriptParams[0]);\n\t\treturn 0;\n\t//case COMMAND_ADD_MOVIE_STUNTS:\n\tcase COMMAND_ADD_NUMBER_OF_ASSASSINATIONS:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCStats::NumOfAssassinations(ScriptParams[0]);\n\t\treturn 0;\n\tcase COMMAND_ADD_PIZZAS_DELIVERED:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCStats::NumOfPizzasDelivered(ScriptParams[0]);\n\t\treturn 0;\n\t//case COMMAND_ADD_GARBAGE_PICKUPS:\n\tcase COMMAND_ADD_ICE_CREAMS_SOLD:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCStats::NumOfIceCreamSold(ScriptParams[0]);\n\t\treturn 0;\n\t//case COMMAND_SET_TOP_SHOOTING_RANGE_SCORE:\n\t//case COMMAND_ADD_SHOOTING_RANGE_RANK:\n\t//case COMMAND_ADD_MONEY_SPENT_ON_GAMBLING:\n\t//case COMMAND_ADD_MONEY_WON_ON_GAMBLING:\n\t//case COMMAND_SET_LARGEST_GAMBLING_WIN:\n\tcase COMMAND_SET_CHAR_IN_PLAYERS_GROUP_CAN_FIGHT:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tpPed->bDontFight = !ScriptParams[1];\n\t\treturn 0;\n\t}\n\tcase COMMAND_CLEAR_CHAR_WAIT_STATE:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tpPed->ClearWaitState();\n\t\treturn 0;\n\t}\n\tcase COMMAND_GET_RANDOM_CAR_OF_TYPE_IN_AREA_NO_SAVE:\n\t{\n\t\tCollectParameters(&m_nIp, 5);\n\t\tint handle = -1;\n\t\tuint32 i = CPools::GetVehiclePool()->GetSize();\n\t\tfloat infX = *(float*)&ScriptParams[0];\n\t\tfloat infY = *(float*)&ScriptParams[1];\n\t\tfloat supX = *(float*)&ScriptParams[2];\n\t\tfloat supY = *(float*)&ScriptParams[3];\n\t\twhile (i--) {\n\t\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetSlot(i);\n\t\t\tif (!pVehicle)\n\t\t\t\tcontinue;\n\t\t\tif (pVehicle->GetVehicleAppearance() != VEHICLE_APPEARANCE_CAR && pVehicle->GetVehicleAppearance() != VEHICLE_APPEARANCE_BIKE)\n\t\t\t\tcontinue;\n\t\t\tif (ScriptParams[4] != pVehicle->GetModelIndex() && ScriptParams[4] >= 0)\n\t\t\t\tcontinue;\n\t\t\tif (pVehicle->VehicleCreatedBy != RANDOM_VEHICLE)\n\t\t\t\tcontinue;\n\t\t\tif (!pVehicle->IsWithinArea(infX, infY, supX, supY))\n\t\t\t\tcontinue;\n\t\t\thandle = CPools::GetVehiclePool()->GetIndex(pVehicle);\n\t\t}\n\t\tScriptParams[0] = handle;\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_CAN_BURST_CAR_TYRES:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tpVehicle->bTyresDontBurst = !ScriptParams[1];\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_PLAYER_AUTO_AIM:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;\n\t\tscript_assert(pPed);\n\t\tpPed->bDoomAim = ScriptParams[1];\n\t\treturn 0;\n\t}\n\tcase COMMAND_FIRE_HUNTER_GUN:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCVehicle *pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tif (CTimer::GetTimeInMilliseconds() > pVehicle->m_nGunFiringTime + 150) {\n\t\t\tCWeapon gun(WEAPONTYPE_HELICANNON, 5000);\n\t\t\tCVector worldGunPos = (pVehicle->GetMatrix() * vecHunterGunPos) + (CTimer::GetTimeStep() * pVehicle->m_vecMoveSpeed);\n\t\t\tgun.FireInstantHit(pVehicle, &worldGunPos);\n\t\t\tgun.AddGunshell(pVehicle, worldGunPos, CVector2D(0.f, 0.1f), 0.025f);\n\t\t\tDMAudio.PlayOneShot(pVehicle->m_audioEntityId, SOUND_WEAPON_SHOT_FIRED, 0.f);\n\t\t\tpVehicle->m_nGunFiringTime = CTimer::GetTimeInMilliseconds();\n\t\t}\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_PROPERTY_AS_OWNED:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCStats::AddPropertyAsOwned(ScriptParams[0]);\n\t\treturn 0;\n\tcase COMMAND_ADD_BLOOD_RING_KILLS:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCStats::AddNumBloodRingKills(ScriptParams[0]);\n\t\treturn 0;\n\tcase COMMAND_SET_LONGEST_TIME_IN_BLOOD_RING:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCStats::LongestTimeInBloodRing(ScriptParams[0]);\n\t\treturn 0;\n\tcase COMMAND_REMOVE_EVERYTHING_FOR_HUGE_CUTSCENE:\n\t{\n\t\tCCutsceneMgr::RemoveEverythingFromTheWorldForTheBiggestFuckoffCutsceneEver();\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_PLAYER_TOUCHING_VEHICLE:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;\n\t\tscript_assert(pPed);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]);\n\t\tCPhysical* pTestedEntity = pPed;\n\t\tif (pPed->bInVehicle && pPed->m_pMyVehicle)\n\t\t\tpTestedEntity = pPed->m_pMyVehicle;\n\t\tUpdateCompareFlag(pTestedEntity->GetHasCollidedWith(pVehicle));\n\t\treturn 0;\n\t}\n\t//case COMMAND_IS_CHAR_TOUCHING_VEHICLE:\n\tcase COMMAND_CHECK_FOR_PED_MODEL_AROUND_PLAYER:\n\t{\n\t\tCollectParameters(&m_nIp, 6);\n\t\tCVector d1 = CWorld::Players[ScriptParams[0]].GetPos() - *(CVector*)&ScriptParams[1];\n\t\tCVector d2 = CWorld::Players[ScriptParams[0]].GetPos() + *(CVector*)&ScriptParams[1];\n\t\tint i = CPools::GetPedPool()->GetSize();\n\t\tbool result = false;\n\t\twhile (i--) {\n\t\t\tCPed* pPed = CPools::GetPedPool()->GetSlot(i);\n\t\t\tif (!pPed)\n\t\t\t\tcontinue;\n\t\t\tif (ScriptParams[4] != pPed->GetModelIndex() && ScriptParams[5] != pPed->GetModelIndex())\n\t\t\t\tcontinue;\n\t\t\tif (pPed->IsWithinArea(d1.x, d1.y, d1.z, d2.x, d2.y, d2.z))\n\t\t\t\tresult = true;\n\t\t}\n\t\tUpdateCompareFlag(result);\n\t\treturn 0;\n\t}\n\tcase COMMAND_CLEAR_CHAR_FOLLOW_PATH:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tif (pPed->GetPedState() == PED_FOLLOW_PATH) {\n\t\t\tpPed->RestorePreviousState();\n\t\t\tpPed->ClearFollowPath();\n\t\t}\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_CHAR_CAN_BE_SHOT_IN_VEHICLE:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tpPed->bCanBeShotInVehicle = ScriptParams[1];\n\t\treturn 0;\n\t}\n\tcase COMMAND_ATTACH_CUTSCENE_OBJECT_TO_VEHICLE:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCCutsceneMgr::AttachObjectToParent(CPools::GetObjectPool()->GetAt(ScriptParams[0]), CPools::GetVehiclePool()->GetAt(ScriptParams[1]));\n\t\treturn 0;\n\t}\n\tcase COMMAND_LOAD_MISSION_TEXT:\n\t{\n\t\tchar key[8];\n\t\tCTheScripts::ReadTextLabelFromScript(&m_nIp, key);\n\t\tm_nIp += KEY_LENGTH_IN_SCRIPT;\n\t\tTheText.LoadMissionText(key);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_TONIGHTS_EVENT:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCScrollBar::TonightsEvent = ScriptParams[0];\n\t\treturn 0;\n\t}\n\tcase COMMAND_CLEAR_CHAR_LAST_DAMAGE_ENTITY:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tif (pPed)\n\t\t\tpPed->m_lastDamEntity = nil;\n\t\telse\n\t\t\tdebug(\"CLEAR_CHAR_LAST_DAMAGE_ENTITY - Character doesn't exist\\n\");\n\t\treturn 0;\n\t}\n\t//case COMMAND_CLEAR_CAR_LAST_DAMAGE_ENTITY:\n\tcase COMMAND_FREEZE_OBJECT_POSITION:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pObject);\n\t\tpObject->bIsFrozen = ScriptParams[1];\n\t\tpObject->bInfiniteMass = ScriptParams[1];\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_PLAYER_HAS_MET_DEBBIE_HARRY:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCTheScripts::bPlayerHasMetDebbieHarry = ScriptParams[0];\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_RIOT_INTENSITY:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCTheScripts::RiotIntensity = ScriptParams[0];\n\t\treturn 0;\n\t}\n\t//case COMMAND_IS_CAR_IN_ANGLED_AREA_2D:\n\t//case COMMAND_IS_CAR_IN_ANGLED_AREA_3D:\n\t//case COMMAND_REMOVE_WEAPON_FROM_CHAR:\n\tcase COMMAND_SET_UP_TAXI_SHORTCUT:\n\t{\n\t\tCollectParameters(&m_nIp, 8);\n\t\tCGameLogic::SetUpShortCut(\n\t\t\t*(CVector*)&ScriptParams[0], *(float*)&ScriptParams[3],\n\t\t\t*(CVector*)&ScriptParams[4], *(float*)&ScriptParams[7]);\n\t\treturn 0;\n\t}\n\tcase COMMAND_CLEAR_TAXI_SHORTCUT:\n\t\tCGameLogic::ClearShortCut();\n\t\treturn 0;\n\t//case COMMAND_SET_CHAR_OBJ_GOTO_CAR_ON_FOOT:\n\t//case COMMAND_GET_CLOSEST_WATER_NODE:\n\tcase COMMAND_ADD_PORN_LEAFLET_TO_RUBBISH:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCStats::PamphletMissionPassed = ScriptParams[0];\n\t\treturn 0;\n\tcase COMMAND_CREATE_CLOTHES_PICKUP:\n\t{\n\t\tCollectParameters(&m_nIp, 4);\n\t\tCVector pos = *(CVector*)&ScriptParams[0];\n\t\tif (pos.z <= MAP_Z_LOW_LIMIT)\n\t\t\tpos.z = CWorld::FindGroundZForCoord(pos.x, pos.y) + PICKUP_PLACEMENT_OFFSET;\n\t\tCPickups::GetActualPickupIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));\n\t\tScriptParams[0] = CPickups::GenerateNewOne(pos, MI_PICKUP_CLOTHES, PICKUP_ON_STREET, ScriptParams[3]);\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\t//case COMMAND_CHANGE_BLIP_THRESHOLD:\n\tcase COMMAND_MAKE_PLAYER_FIRE_PROOF:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPlayerInfo* pPlayerInfo = &CWorld::Players[ScriptParams[0]];\n\t\tpPlayerInfo->m_bFireproof = ScriptParams[1];\n\t\treturn 0;\n\t}\n\tcase COMMAND_INCREASE_PLAYER_MAX_HEALTH:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPlayerInfo* pPlayerInfo = &CWorld::Players[ScriptParams[0]];\n\t\tpPlayerInfo->m_nMaxHealth += ScriptParams[1];\n\t\tpPlayerInfo->m_pPed->m_fHealth = pPlayerInfo->m_nMaxHealth;\n\t\treturn 0;\n\t}\n\tcase COMMAND_INCREASE_PLAYER_MAX_ARMOUR:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPlayerInfo* pPlayerInfo = &CWorld::Players[ScriptParams[0]];\n\t\tpPlayerInfo->m_nMaxArmour += ScriptParams[1];\n\t\tpPlayerInfo->m_pPed->m_fArmour = pPlayerInfo->m_nMaxArmour;\n\t\treturn 0;\n\t}\n\tcase COMMAND_CREATE_RANDOM_CHAR_AS_DRIVER:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tCPed* pPed = CPopulation::AddPedInCar(pVehicle, true);\n\t\tpPed->CharCreatedBy = MISSION_CHAR;\n\t\tpPed->bRespondsToThreats = false;\n\t\tpPed->bAllowMedicsToReviveMe = false;\n\t\tpPed->bIsPlayerFriend = false;\n\t\tif (pVehicle->bIsBus)\n\t\t\tpPed->bRenderPedInCar = false;\n\t\tpPed->SetPosition(pVehicle->GetPosition());\n\t\tpPed->SetOrientation(0.0f, 0.0f, 0.0f);\n\t\tpPed->SetPedState(PED_DRIVING);\n\t\tpPed->m_pMyVehicle = pVehicle;\n\t\tpPed->m_pMyVehicle->RegisterReference((CEntity**)&pPed->m_pMyVehicle);\n\t\tpVehicle->pDriver = pPed;\n\t\tpVehicle->pDriver->RegisterReference((CEntity**)&pVehicle->pDriver);\n\t\tpPed->bInVehicle = true;\n\t\tpVehicle->SetStatus(STATUS_PHYSICS);\n\t\tif (pVehicle->m_vehType == VEHICLE_TYPE_BOAT)\n\t\t\tpVehicle->AutoPilot.m_nCarMission = MISSION_CRUISE;\n\t\tpVehicle->bEngineOn = true;\n\t\tpVehicle->m_nZoneLevel = CTheZones::GetLevelFromPosition(&pVehicle->GetPosition());\n\t\tCPopulation::ms_nTotalMissionPeds++;\n\t\tScriptParams[0] = CPools::GetPedPool()->GetIndex(pPed);\n\t\tStoreParameters(&m_nIp, 1);\n\t\tif (m_bIsMissionScript)\n\t\t\tCTheScripts::MissionCleanUp.AddEntityToList(ScriptParams[0], CLEANUP_CHAR);\n\t\treturn 0;\n\t}\n\tcase COMMAND_CREATE_RANDOM_CHAR_AS_PASSENGER:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tCPed* pPed = CPopulation::AddPedInCar(pVehicle, false);\n\t\tpPed->CharCreatedBy = MISSION_CHAR;\n\t\tpPed->bRespondsToThreats = false;\n\t\tpPed->bAllowMedicsToReviveMe = false;\n\t\tpPed->bIsPlayerFriend = false;\n\t\tif (pVehicle->bIsBus)\n\t\t\tpPed->bRenderPedInCar = false;\n\t\tpPed->SetPosition(pVehicle->GetPosition());\n\t\tpPed->SetOrientation(0.0f, 0.0f, 0.0f);\n\t\tCPopulation::ms_nTotalMissionPeds++;\n\t\tpVehicle->m_nZoneLevel = CTheZones::GetLevelFromPosition(&pVehicle->GetPosition());\n\t\tif (ScriptParams[1] >= 0)\n\t\t\tpVehicle->AddPassenger(pPed, ScriptParams[1]);\n\t\telse\n\t\t\tpVehicle->AddPassenger(pPed);\n\n\t\tpPed->m_pMyVehicle = pVehicle;\n\t\tpPed->m_pMyVehicle->RegisterReference((CEntity**)&pPed->m_pMyVehicle);\n\t\tpPed->bInVehicle = true;\n\t\tpPed->SetPedState(PED_DRIVING);\n\t\tScriptParams[0] = CPools::GetPedPool()->GetIndex(pPed);\n\t\tStoreParameters(&m_nIp, 1);\n\t\tif (m_bIsMissionScript)\n\t\t\tCTheScripts::MissionCleanUp.AddEntityToList(ScriptParams[0], CLEANUP_CHAR);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_CHAR_IGNORE_THREATS_BEHIND_OBJECTS:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tpPed->bIgnoreThreatsBehindObjects = ScriptParams[1];\n\t\treturn 0;\n\t}\n\tcase COMMAND_ENSURE_PLAYER_HAS_DRIVE_BY_WEAPON:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;\n\t\tscript_assert(pPed);\n\t\tif (pPed->bInVehicle) {\n\t\t\tif (pPed->GetWeapon(WEAPONSLOT_SUBMACHINEGUN).m_eWeaponType) {\n\t\t\t\tif (pPed->GetWeapon(WEAPONSLOT_SUBMACHINEGUN).m_nAmmoTotal < ScriptParams[1])\n\t\t\t\t\tpPed->SetAmmo(pPed->GetWeapon(WEAPONSLOT_SUBMACHINEGUN).m_eWeaponType, ScriptParams[1]);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tpPed->GiveWeapon(WEAPONTYPE_UZI, ScriptParams[1], true);\n\t\t\t\tif (pPed->m_storedWeapon == WEAPONTYPE_UNIDENTIFIED)\n\t\t\t\t\tpPed->m_storedWeapon = pPed->GetWeapon()->m_eWeaponType;\n\t\t\t\tpPed->SetCurrentWeapon(WEAPONTYPE_UZI);\n\t\t\t}\n\t\t}\n\t\treturn 0;\n\t}\n\tcase COMMAND_MAKE_HELI_COME_CRASHING_DOWN:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCAutomobile* pHeli = (CAutomobile*)CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pHeli && pHeli->IsCar() && pHeli->IsRealHeli());\n\t\tpHeli->bHeliDestroyed = true;\n\t\treturn 0;\n\t}\n\tcase COMMAND_ADD_EXPLOSION_NO_SOUND:\n\t{\n\t\tCollectParameters(&m_nIp, 4);\n\t\tCExplosion::AddExplosion(nil, nil, (eExplosionType)ScriptParams[3], *(CVector*)&ScriptParams[0], 0, false);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_OBJECT_AREA_VISIBLE:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pObject);\n\t\tpObject->m_area = ScriptParams[1];\n\t\treturn 0;\n\t}\n\t//case COMMAND_WAS_VEHICLE_EVER_POLICE:\n\tcase COMMAND_SET_CHAR_NEVER_TARGETTED:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tpPed->bNeverEverTargetThisPed = ScriptParams[1];\n\t\treturn 0;\n\t}\n\tcase COMMAND_LOAD_UNCOMPRESSED_ANIM:\n\t{\n\t\tchar key[KEY_LENGTH_IN_SCRIPT];\n\t\tCTheScripts::ReadTextLabelFromScript(&m_nIp, key);\n\t\tm_nIp += KEY_LENGTH_IN_SCRIPT;\n\t\tCCutsceneMgr::LoadAnimationUncompressed(key);\n\t\treturn 0;\n\t}\n\tcase COMMAND_WAS_CUTSCENE_SKIPPED:\n\t{\n\t\tUpdateCompareFlag(CCutsceneMgr::WasCutsceneSkipped());\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_CHAR_CROUCH_WHEN_THREATENED:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tpPed->bCrouchWhenScared = true;\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_CHAR_IN_ANY_POLICE_VEHICLE:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tUpdateCompareFlag(pPed->bInVehicle && pPed->m_pMyVehicle &&\n\t\t\tpPed->m_pMyVehicle->IsLawEnforcementVehicle() &&\n\t\t\tpPed->m_pMyVehicle->GetModelIndex() != MI_PREDATOR);\n\t\treturn 0;\n\t}\n\tcase COMMAND_DOES_CHAR_EXIST:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tUpdateCompareFlag(CPools::GetPedPool()->GetAt(ScriptParams[0]) != 0);\n\t\treturn 0;\n\t//case COMMAND_DOES_VEHICLE_EXIST:\n\t//case COMMAND_ADD_SHORT_RANGE_BLIP_FOR_CONTACT_POINT:\n\tcase COMMAND_ADD_SHORT_RANGE_SPRITE_BLIP_FOR_CONTACT_POINT:\n\t{\n\t\tCollectParameters(&m_nIp, 4);\n\t\tCVector pos = *(CVector*)&ScriptParams[0];\n\t\tif (pos.z <= MAP_Z_LOW_LIMIT)\n\t\t\tpos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);\n\t\tCRadar::GetActualBlipArrayIndex(CollectNextParameterWithoutIncreasingPC(m_nIp));\n\t\tint id = CRadar::SetShortRangeCoordBlip(BLIP_COORD, pos, 2, BLIP_DISPLAY_BOTH);\n\t\tCRadar::SetBlipSprite(id, ScriptParams[3]);\n\t\tScriptParams[0] = id;\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_CHAR_STUCK:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tUpdateCompareFlag(pPed->m_nWaitState == WAITSTATE_STUCK);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_ALL_TAXIS_HAVE_NITRO:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCVehicle::bAllTaxisHaveNitro = ScriptParams[0] != 0;\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_CHAR_STOP_SHOOT_DONT_SEEK_ENTITY:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tif (ScriptParams[1]) {\n\t\t\tpPed->bKindaStayInSamePlace = true;\n\t\t\tpPed->bStopAndShoot = true;\n\t\t}\n\t\telse {\n\t\t\tpPed->bKindaStayInSamePlace = false;\n\t\t\tpPed->bStopAndShoot = false;\n\t\t}\n\t\tpPed->m_nLastPedState = PED_NONE;\n\t\treturn 0;\n\t}\n\tcase COMMAND_FREEZE_CAR_POSITION_AND_DONT_LOAD_COLLISION:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tif (ScriptParams[1]) {\n\t\t\tpVehicle->bIsFrozen = true;\n\t\t\tpVehicle->bInfiniteMass = true;\n\t\t\tif (m_bIsMissionScript) {\n\t\t\t\tCWorld::Remove(pVehicle);\n\t\t\t\tpVehicle->bIsStaticWaitingForCollision = true;\n\t\t\t\tCWorld::Add(pVehicle);\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tpVehicle->bIsFrozen = false;\n\t\t\tpVehicle->bInfiniteMass = false;\n\t\t}\n\t\treturn 0;\n\t}\n\t//case COMMAND_FREEZE_CHAR_POSITION_AND_DONT_LOAD_COLLISION:\n\t//case COMMAND_FREEZE_OBJECT_POSITION_AND_DONT_LOAD_COLLISION:\n\t//case COMMAND_SET_FADE_AND_JUMPCUT_AFTER_RC_EXPLOSION:\n\tdefault:\n\t\tscript_assert(0);\n\t}\n\treturn -1;\n}\n"
  },
  {
    "path": "src/control/Script8.cpp",
    "content": "#include \"common.h\"\n\n#include \"Script.h\"\n#include \"ScriptCommands.h\"\n\n#include \"DMAudio.h\"\n#if ((defined GTAVC_JP_PATCH || defined SUPPORT_JAPANESE_SCRIPT) && defined MORE_LANGUAGES)\n#include \"Frontend.h\"\n#endif\n#include \"GameLogic.h\"\n#include \"Garages.h\"\n#ifdef MISSION_REPLAY\n#include \"GenericGameStorage.h\"\n#endif\n#if (defined GTA_PC && !defined GTAVC_JP_PATCH || defined GTA_XBOX || defined SUPPORT_XBOX_SCRIPT || defined GTA_MOBILE || defined SUPPORT_MOBILE_SCRIPT)\n#include \"General.h\"\n#include \"maths.h\"\n#endif\n#include \"Hud.h\"\n#include \"Pad.h\"\n#include \"PedAttractor.h\"\n#include \"Population.h\"\n#include \"Pools.h\"\n#include \"RpAnimBlend.h\"\n#include \"Stats.h\"\n#include \"VisibilityPlugins.h\"\n#include \"Wanted.h\"\n#include \"WaterLevel.h\"\n#include \"World.h\"\n#include \"Zones.h\"\n\nint8 CRunningScript::ProcessCommands1400To1499(int32 command)\n{\n\tswitch (command) {\n\tcase COMMAND_REGISTER_VIGILANTE_LEVEL:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCStats::RegisterLevelVigilanteMission(ScriptParams[0]);\n\t\treturn 0;\n\tcase COMMAND_CLEAR_ALL_CHAR_ANIMS:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tif (!pPed->bInVehicle) {\n\t\t\tpPed->m_pVehicleAnim = nil;\n\t\t\tpPed->RestartNonPartialAnims();\n\t\t\tRpAnimBlendClumpRemoveAllAssociations(pPed->GetClump());\n\t\t\tpPed->SetPedState(PED_IDLE);\n\t\t\tpPed->SetMoveState(PEDMOVE_STILL);\n\t\t\tpPed->m_nLastPedState = PED_NONE;\n\t\t\tpPed->ClearAimFlag();\n\t\t\tpPed->ClearLookFlag();\n\t\t\tpPed->bIsPointingGunAt = false;\n\t\t\tif (pPed->IsPlayer())\n\t\t\t\t((CPlayerPed*)pPed)->m_fMoveSpeed = 0.0f;\n\t\t\telse\n\t\t\t\tpPed->m_nStoredMoveState = PEDMOVE_STILL;\n\t\t\tCAnimManager::AddAnimation(pPed->GetClump(), pPed->m_animGroup, ANIM_STD_IDLE);\n\t\t\tpPed->bIsPedDieAnimPlaying = false;\n\t\t}\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_MAXIMUM_NUMBER_OF_CARS_IN_GARAGE:\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCGarages::SetMaxNumStoredCarsForGarage(ScriptParams[0], ScriptParams[1]);\n\t\treturn 0;\n\tcase COMMAND_WANTED_STARS_ARE_FLASHING:\n\t{\n\t\tCWanted* pWanted = CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_pWanted;\n\t\tUpdateCompareFlag(pWanted->m_nMinWantedLevel - pWanted->GetWantedLevel() > 0);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_ALLOW_HURRICANES:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCStats::NoMoreHurricanes = ScriptParams[0];\n\t\treturn 0;\n\tcase COMMAND_PLAY_ANNOUNCEMENT:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tDMAudio.PlayRadioAnnouncement(ScriptParams[0] + STREAMED_SOUND_ANNOUNCE_BRIDGE_CLOSED);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_PLAYER_IS_IN_STADIUM:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCTheScripts::bPlayerIsInTheStatium = ScriptParams[0];\n\t\treturn 0;\n\t}\n\tcase COMMAND_GET_BUS_FARES_COLLECTED_BY_PLAYER:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPlayerInfo* pPlayerInfo = &CWorld::Players[ScriptParams[0]];\n\t\tScriptParams[0] = pPlayerInfo->m_pPed->m_nLastBusFareCollected;\n\t\tpPlayerInfo->m_pPed->m_nLastBusFareCollected = 0;\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_CHAR_OBJ_BUY_ICE_CREAM:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[1]);\n\t\tscript_assert(pVehicle);\n\t\tScriptParams[0] = 0;\n\t\tif (pPed->m_objective == OBJECTIVE_NONE && !pPed->bHasAlreadyUsedAttractor) {\n\t\t\tC2dEffect* pEffect = (C2dEffect*)GetPedAttractorManager()->GetEffectForIceCreamVan(pVehicle, pPed->GetPosition()); // has to be casted, because inner methods are const\n\t\t\tif (pEffect) {\n\t\t\t\tCVector pos;\n\t\t\t\tCPedAttractorManager::ComputeEffectPos(pEffect, pVehicle->GetMatrix(), pos);\n\t\t\t\tif ((pPed->GetPosition() - pos).MagnitudeSqr() < SQR(20.0f)) {\n\t\t\t\t\tif (GetPedAttractorManager()->HasEmptySlot(pEffect) && GetPedAttractorManager()->IsApproachable(pEffect, pVehicle->GetMatrix(), 0, pPed)) {\n\t\t\t\t\t\tif (GetPedAttractorManager()->RegisterPedWithAttractor(pPed, pEffect, pVehicle->GetMatrix()))\n\t\t\t\t\t\t\tScriptParams[0] = 1;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\tcase COMMAND_DISPLAY_RADAR:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCHud::m_HideRadar = ScriptParams[0] == 0;\n\t\treturn 0;\n\tcase COMMAND_REGISTER_BEST_POSITION:\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCStats::RegisterBestPosition(ScriptParams[0], ScriptParams[1]);\n\t\treturn 0;\n\tcase COMMAND_IS_PLAYER_IN_INFO_ZONE:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPlayerInfo* pPlayerInfo = &CWorld::Players[ScriptParams[0]];\n\t\tchar key[KEY_LENGTH_IN_SCRIPT];\n\t\tmemset(key, 0, KEY_LENGTH_IN_SCRIPT);\n\t\tCTheScripts::ReadTextLabelFromScript(&m_nIp, key);\n\t\tm_nIp += KEY_LENGTH_IN_SCRIPT;\n\t\tCVector pos = pPlayerInfo->GetPos();\n\t\tCZone* infoZone = CTheZones::FindInformationZoneForPosition(&pos);\n\t\tUpdateCompareFlag(strncmp(key, infoZone->name, 8) == 0); // original code doesn't seem to be using strncmp in here and compare 2 ints instead\n\t\treturn 0;\n\t}\n\tcase COMMAND_CLEAR_CHAR_ICE_CREAM_PURCHASE:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tif (pPed->m_attractor)\n\t\t\tGetPedAttractorManager()->DeRegisterPed(pPed, pPed->m_attractor);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_IN_CAR_FIRE_BUTTON_PRESSED:\n\t\tUpdateCompareFlag(CPad::GetPad(0)->GetCarGunFired());\n\t\treturn 0;\n\tcase COMMAND_HAS_CHAR_ATTEMPTED_ATTRACTOR:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tUpdateCompareFlag(pPed->bHasAlreadyUsedAttractor);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_LOAD_COLLISION_FOR_CAR_FLAG:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tif (ScriptParams[1]) {\n\t\t\tpVehicle->bDontLoadCollision = false;\n\t\t\tif (m_bMissionFlag) {\n\t\t\t\tCWorld::Remove(pVehicle);\n\t\t\t\tpVehicle->bIsStaticWaitingForCollision = true;\n\t\t\t\tCWorld::Add(pVehicle);\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tpVehicle->bDontLoadCollision = true;\n\t\t\tif (pVehicle->bIsStaticWaitingForCollision) {\n\t\t\t\tpVehicle->bIsStaticWaitingForCollision = false;\n\t\t\t\tif (!pVehicle->GetIsStatic())\n\t\t\t\t\tpVehicle->AddToMovingList();\n\t\t\t}\n\t\t}\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_LOAD_COLLISION_FOR_CHAR_FLAG:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tif (ScriptParams[1]) {\n\t\t\tpPed->bDontLoadCollision = false;\n\t\t\tif (m_bMissionFlag) {\n\t\t\t\tCWorld::Remove(pPed);\n\t\t\t\tpPed->bIsStaticWaitingForCollision = true;\n\t\t\t\tCWorld::Add(pPed);\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tpPed->bDontLoadCollision = true;\n\t\t\tif (pPed->bIsStaticWaitingForCollision) {\n\t\t\t\tpPed->bIsStaticWaitingForCollision = false;\n\t\t\t\tif (!pPed->GetIsStatic())\n\t\t\t\t\tpPed->AddToMovingList();\n\t\t\t}\n\t\t}\n\t\treturn 0;\n\t}\n\t//case COMMAND_SET_LOAD_COLLISION_FOR_OBJECT_FLAG:\n\tcase COMMAND_ADD_BIG_GUN_FLASH:\n\t{\n\t\tCollectParameters(&m_nIp, 6);\n\t\tCWeapon::AddGunFlashBigGuns(*(CVector*)&ScriptParams[0], *(CVector*)&ScriptParams[3]);\n\t\treturn 0;\n\t}\n\tcase COMMAND_HAS_CHAR_BOUGHT_ICE_CREAM:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tUpdateCompareFlag(pPed->bBoughtIceCream);\n\t\treturn 0;\n\t}\n\tcase COMMAND_GET_PROGRESS_PERCENTAGE:\n\t\t*(float*)&ScriptParams[0] = CStats::GetPercentageProgress();\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\tcase COMMAND_SET_SHORTCUT_PICKUP_POINT:\n\t{\n\t\tCollectParameters(&m_nIp, 4);\n\t\tCGameLogic::AddShortCutPointAfterDeath(*(CVector*)&ScriptParams[0], *(float*)&ScriptParams[3]);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_SHORTCUT_DROPOFF_POINT_FOR_MISSION:\n\t{\n\t\tCollectParameters(&m_nIp, 4);\n\t\tCGameLogic::AddShortCutDropOffPointForMission(*(CVector*)&ScriptParams[0], *(float*)&ScriptParams[3]);\n\t\treturn 0;\n\t}\n\tcase COMMAND_GET_RANDOM_ICE_CREAM_CUSTOMER_IN_AREA:\n\t{\n\t\tCollectParameters(&m_nIp, 7);\n\t\tint ped_handle = -1;\n\t\tCVector pos = FindPlayerCoors();\n\t\tfloat x1 = *(float*)&ScriptParams[0];\n\t\tfloat y1 = *(float*)&ScriptParams[1];\n\t\tfloat x2 = *(float*)&ScriptParams[2];\n\t\tfloat y2 = *(float*)&ScriptParams[3];\n\t\tint i = CPools::GetPedPool()->GetSize();\n\t\twhile (--i && ped_handle == -1) {\n\t\t\tCPed* pPed = CPools::GetPedPool()->GetSlot(i);\n\t\t\tif (!pPed)\n\t\t\t\tcontinue;\n\t\t\tif (CTheScripts::LastRandomPedId == CPools::GetPedPool()->GetIndex(pPed))\n\t\t\t\tcontinue;\n\t\t\tif (pPed->CharCreatedBy != RANDOM_CHAR)\n\t\t\t\tcontinue;\n\t\t\tif (!pPed->IsPedInControl())\n\t\t\t\tcontinue;\n\t\t\tif (pPed->bRemoveFromWorld)\n\t\t\t\tcontinue;\n\t\t\tif (pPed->bFadeOut)\n\t\t\t\tcontinue;\n\t\t\tif (pPed->m_nWaitState != WAITSTATE_FALSE)\n\t\t\t\tcontinue;\n\t\t\tif (pPed->bHasAlreadyUsedAttractor)\n\t\t\t\tcontinue;\n\t\t\tif (pPed->m_attractor)\n\t\t\t\tcontinue;\n\t\t\tif (!ThisIsAValidRandomPed(pPed->m_nPedType, ScriptParams[4], ScriptParams[5], ScriptParams[6]))\n\t\t\t\tcontinue;\n\t\t\tif (pPed->bIsLeader || pPed->m_leader)\n\t\t\t\tcontinue;\n\t\t\tif (!pPed->IsWithinArea(x1, y1, x2, y2))\n\t\t\t\tcontinue;\n\t\t\tif (pos.z - PED_FIND_Z_OFFSET > pPed->GetPosition().z)\n\t\t\t\tcontinue;\n\t\t\tif (pos.z + PED_FIND_Z_OFFSET < pPed->GetPosition().z)\n\t\t\t\tcontinue;\n\t\t\tped_handle = CPools::GetPedPool()->GetIndex(pPed);\n\t\t\tCTheScripts::LastRandomPedId = ped_handle;\n\t\t\tpPed->CharCreatedBy = MISSION_CHAR;\n\t\t\tpPed->bRespondsToThreats = false;\n\t\t\t++CPopulation::ms_nTotalMissionPeds;\n\t\t\tif (m_bIsMissionScript)\n\t\t\t\tCTheScripts::MissionCleanUp.AddEntityToList(ped_handle, CLEANUP_CHAR);\n\t\t}\n\t\tScriptParams[0] = ped_handle;\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\t//case COMMAND_GET_RANDOM_ICE_CREAM_CUSTOMER_IN_ZONE:\n\tcase COMMAND_UNLOCK_ALL_CAR_DOORS_IN_AREA:\n\t{\n\t\tCollectParameters(&m_nIp, 4);\n\t\tuint32 i = CPools::GetVehiclePool()->GetSize();\n\t\tfloat infX = *(float*)&ScriptParams[0];\n\t\tfloat infY = *(float*)&ScriptParams[1];\n\t\tfloat supX = *(float*)&ScriptParams[2];\n\t\tfloat supY = *(float*)&ScriptParams[3];\n\t\twhile (i--) {\n\t\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetSlot(i);\n\t\t\tif (!pVehicle)\n\t\t\t\tcontinue;\n\t\t\tif (pVehicle->IsWithinArea(infX, infY, supX, supY))\n\t\t\t\tpVehicle->m_nDoorLock = CARLOCK_UNLOCKED;\n\t\t}\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_GANG_ATTACK_PLAYER_WITH_COPS:\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCGangs::SetWillAttackPlayerWithCops((ePedType)((int)PEDTYPE_GANG1 + ScriptParams[0]), !!ScriptParams[1]);\n\t\treturn 0;\n\tcase COMMAND_SET_CHAR_FRIGHTENED_IN_JACKED_CAR:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tpPed->bHeldHostageInCar = ScriptParams[1];\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_VEHICLE_TO_FADE_IN:\n\t{\n\t\tCollectParameters(&m_nIp, 2);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pVehicle);\n\t\tCVisibilityPlugins::SetClumpAlpha(pVehicle->GetClump(), ScriptParams[1]);\n\t\treturn 0;\n\t}\n\tcase COMMAND_REGISTER_ODDJOB_MISSION_PASSED:\n\t\t++CStats::MissionsPassed;\n\t\tCStats::CheckPointReachedSuccessfully();\n\t\tCTheScripts::LastMissionPassedTime = CTimer::GetTimeInMilliseconds();\n\t\tCGameLogic::RemoveShortCutDropOffPointForMission();\n\t\treturn 0;\n\tcase COMMAND_IS_PLAYER_IN_SHORTCUT_TAXI:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* pPed = CWorld::Players[ScriptParams[0]].m_pPed;\n\t\tscript_assert(pPed);\n\t\tUpdateCompareFlag(pPed->bInVehicle && pPed->m_pMyVehicle && pPed->m_pMyVehicle == CGameLogic::pShortCutTaxi);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_CHAR_DUCKING:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCPed* pPed = CPools::GetPedPool()->GetAt(ScriptParams[0]);\n\t\tscript_assert(pPed);\n\t\tUpdateCompareFlag(RpAnimBlendClumpGetAssociation(pPed->GetClump(), ANIM_STD_DUCK_DOWN) != nil);\n\t\treturn 0;\n\t}\n\tcase COMMAND_CREATE_DUST_EFFECT_FOR_CUTSCENE_HELI:\n\t{\n\t\tCollectParameters(&m_nIp, 3);\n\t\tCObject* pHeli = CPools::GetObjectPool()->GetAt(ScriptParams[0]);\n\t\tbool found = false;\n\t\tfloat waterLevel = -1000.0f;\n\t\tCVector pos = pHeli->GetPosition();\n\t\tfloat radius = *(float*)&ScriptParams[1];\n\t\tfloat ground = CWorld::FindGroundZFor3DCoord(pos.x, pos.y, pos.z, &found);\n\t\tif (!CWaterLevel::GetWaterLevel(pos.x, pos.y, pos.z, &waterLevel, false))\n\t\t\twaterLevel = 0.0f;\n\t\tif (waterLevel > ground)\n\t\t\tground = waterLevel;\n\t\tif (ScriptParams[2] > 8)\n\t\t\tScriptParams[2] = 8;\n\t\tCVehicle::HeliDustGenerate(pHeli, (pos.z - ground - 1.0f - radius) * 0.3 + radius, ground, ScriptParams[2]);\n\t\treturn 0;\n\t}\n\tcase COMMAND_REGISTER_FIRE_LEVEL:\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCStats::RegisterLevelFireMission(ScriptParams[0]);\n\t\treturn 0;\n\tcase COMMAND_IS_AUSTRALIAN_GAME:\n\t\tUpdateCompareFlag(false); // should we make some check?\n\t\treturn 0;\n\tcase COMMAND_DISARM_CAR_BOMB:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(ScriptParams[0]);\n\t\tif (pVehicle->m_bombType != CARBOMB_NONE) {\n\t\t\tpVehicle->m_bombType = CARBOMB_NONE;\n\t\t\tpVehicle->m_pBombRigger = nil;\n\t\t}\n\t\treturn 0;\n\t}\n#if (defined GTAVC_JP_PATCH || defined SUPPORT_JAPANESE_SCRIPT)\n\tcase COMMAND_IS_JAPANESE_GAME:\n#ifdef MORE_LANGUAGES\n\t\tUpdateCompareFlag(FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_JAPANESE);\n#elif (defined GTAVC_JP_PATCH)\n\t\tUpdateCompareFlag(true);\n#else\n\t\tUpdateCompareFlag(false);\n#endif\n\t\treturn 0;\n#elif (!defined GTA_PS2)\n\tcase COMMAND_SET_ONSCREEN_COUNTER_FLASH_WHEN_FIRST_DISPLAYED:\n\t{\n\t\tscript_assert(CTheScripts::ScriptSpace[m_nIp++] == ARGUMENT_GLOBALVAR);\n\t\tuint16 var = CTheScripts::Read2BytesFromScript(&m_nIp);\n\t\tCollectParameters(&m_nIp, 1);\n\t\t//CUserDisplay::OnscnTimer.SetCounterFlashWhenFirstDisplayed(var, ScriptParams[0]);\n\t\treturn 0;\n\t}\n#endif\n#if (defined GTA_PC && !defined GTAVC_JP_PATCH || defined GTA_XBOX || defined SUPPORT_XBOX_SCRIPT || defined GTA_MOBILE || defined SUPPORT_MOBILE_SCRIPT)\n\tcase COMMAND_SHUFFLE_CARD_DECKS:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tscript_assert(ScriptParams[0] >= 0 && ScriptParams[0] <= 6);\n\t\tfor (int i = 0; i < CARDS_IN_STACK; i++)\n\t\t\tCTheScripts::CardStack[i] = 0;\n\t\tint16 seq[CARDS_IN_STACK];\n\t\tfor (int i = 0; i < MAX_DECKS * CARDS_IN_DECK; i++)\n\t\t\tseq[i] = i;\n\t\tint cards_left = CARDS_IN_DECK * ScriptParams[0];\n\t\tfor (int k = 1; k < CARDS_IN_DECK + 1; k++) {\n\t\t\tfor (int deck = 0; deck < ScriptParams[0]; deck++) {\n\t\t\t\tint index = CGeneral::GetRandomNumberInRange(0, cards_left);\n\t\t\t\tCTheScripts::CardStack[seq[index]] = k;\n\t\t\t\tfor (int l = index; l < cards_left; l++) {\n\t\t\t\t\tif (l + 1 < CARDS_IN_STACK)\n\t\t\t\t\t\tseq[l] = seq[l + 1];\n\t\t\t\t\telse\n\t\t\t\t\t\tseq[l] = 0;\n\t\t\t\t}\n\t\t\t\t--cards_left;\n\t\t\t}\n\t\t}\n\t\tCTheScripts::CardStackPosition = 0;\n\t\treturn 0;\n\t}\n\tcase COMMAND_FETCH_NEXT_CARD:\n\t{\n\t\tif (CTheScripts::CardStack[CTheScripts::CardStackPosition] == 0)\n\t\t\tCTheScripts::CardStackPosition = 0;\n\t\tScriptParams[0] = CTheScripts::CardStack[CTheScripts::CardStackPosition++];\n\t\tif (CTheScripts::CardStackPosition == CARDS_IN_DECK * MAX_DECKS)\n\t\t\tCTheScripts::CardStackPosition = 0;\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n\tcase COMMAND_GET_OBJECT_VELOCITY:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);\n\t\t*(CVector*)&ScriptParams[0] = GAME_SPEED_TO_METERS_PER_SECOND * pObject->GetMoveSpeed();\n\t\tStoreParameters(&m_nIp, 3);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_DEBUG_CAMERA_ON:\n\t\tUpdateCompareFlag(TheCamera.WorldViewerBeingUsed);\n\t\treturn 0;\n\tcase COMMAND_ADD_TO_OBJECT_ROTATION_VELOCITY:\n\t{\n\t\tCollectParameters(&m_nIp, 4);\n\t\tCObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);\n\t\tCVector newSpeed = pObject->GetTurnSpeed() + *(CVector*)&ScriptParams[1] / GAME_SPEED_TO_METERS_PER_SECOND;\n\t\tif (pObject->bIsStatic) {\n\t\t\tpObject->SetIsStatic(false);\n\t\t\tpObject->AddToMovingList();\n\t\t}\n\t\tpObject->SetTurnSpeed(newSpeed.x, newSpeed.y, newSpeed.z);\n\t\treturn 0;\n\t}\n\tcase COMMAND_SET_OBJECT_ROTATION_VELOCITY:\n\t{\n\t\tCollectParameters(&m_nIp, 4);\n\t\tCObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);\n\t\tCVector newSpeed = *(CVector*)&ScriptParams[1] / GAME_SPEED_TO_METERS_PER_SECOND;\n\t\tif (pObject->bIsStatic) {\n\t\t\tpObject->SetIsStatic(false);\n\t\t\tpObject->AddToMovingList();\n\t\t}\n\t\tpObject->SetTurnSpeed(newSpeed.x, newSpeed.y, newSpeed.z);\n\t\treturn 0;\n\t}\n\tcase COMMAND_IS_OBJECT_STATIC:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);\n\t\tUpdateCompareFlag(pObject->GetIsStatic());\n\t\treturn 0;\n\t}\n\tcase COMMAND_GET_ANGLE_BETWEEN_2D_VECTORS:\n\t{\n\t\tCollectParameters(&m_nIp, 4);\n\t\tCVector2D v1 = *(CVector2D*)&ScriptParams[0];\n\t\tCVector2D v2 = *(CVector2D*)&ScriptParams[2];\n\t\tfloat c = DotProduct2D(v1, v2) / (v1.Magnitude() * v2.Magnitude());\n#ifdef FIX_BUGS // command is a SA leftover where it was fixed to this\n\t\t*(float*)&ScriptParams[0] = RADTODEG(Acos(c));\n#else\n\t\t*(float*)&ScriptParams[0] = Acos(c);\n#endif\n\t\treturn 0;\n\t}\n\tcase COMMAND_DO_2D_RECTANGLES_COLLIDE:\n\t{\n\t\tCollectParameters(&m_nIp, 8);\n\t\tfloat infX1 = *(float*)&ScriptParams[0] - *(float*)&ScriptParams[2] * 0.5; // NB: not float\n\t\tfloat supX1 = *(float*)&ScriptParams[0] + *(float*)&ScriptParams[2] * 0.5;\n\t\tfloat infX2 = *(float*)&ScriptParams[4] - *(float*)&ScriptParams[6] * 0.5;\n\t\tfloat supX2 = *(float*)&ScriptParams[4] + *(float*)&ScriptParams[6] * 0.5;\n\t\tfloat infY1 = *(float*)&ScriptParams[1] - *(float*)&ScriptParams[3] * 0.5;\n\t\tfloat supY1 = *(float*)&ScriptParams[1] + *(float*)&ScriptParams[3] * 0.5;\n\t\tfloat infY2 = *(float*)&ScriptParams[5] - *(float*)&ScriptParams[7] * 0.5;\n\t\tfloat supY2 = *(float*)&ScriptParams[5] + *(float*)&ScriptParams[7] * 0.5;\n\t\tbool collide = true;\n\t\tif (infY2 > supY1)\n\t\t\tcollide = false;\n\t\tif (infY1 > supY2)\n\t\t\tcollide = false;\n\t\tif (infX2 > supX1)\n\t\t\tcollide = false;\n\t\tif (infX1 > supX2)\n\t\t\tcollide = false;\n\t\tUpdateCompareFlag(collide);\n\t\treturn 0;\n\t}\n\tcase COMMAND_GET_OBJECT_ROTATION_VELOCITY:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);\n\t\t*(CVector*)&ScriptParams[0] = pObject->GetTurnSpeed() * GAME_SPEED_TO_METERS_PER_SECOND;\n\t\tStoreParameters(&m_nIp, 3);\n\t\treturn 0;\n\t}\n\tcase COMMAND_ADD_VELOCITY_RELATIVE_TO_OBJECT_VELOCITY:\n\t{\n\t\tCollectParameters(&m_nIp, 4);\n\t\tCObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);\n\t\tCVector vecAddition = *(CVector*)&ScriptParams[1] * CTimer::GetTimeStep() / GAME_SPEED_TO_METERS_PER_SECOND;\n\t\tif (!pObject->bIsStatic) {\n\t\t\tCVector vecCurrSpeed = pObject->GetSpeed();\n\t\t\tvecCurrSpeed.Normalise();\n\t\t\tif (vecCurrSpeed.z != 1.0) { // NB: not float!\n\t\t\t\tCVector vx = CrossProduct(vecCurrSpeed, CVector(0.0f, 0.0f, 1.0f));\n\t\t\t\tvx.Normalise();\n\t\t\t\tCVector vz = CrossProduct(vx, vecCurrSpeed);\n\t\t\t\tvz.Normalise();\n\t\t\t\tCVector vecNewSpeed = pObject->GetSpeed() + vecAddition.x * vx + vecAddition.y * vecCurrSpeed + vecAddition.z * vecCurrSpeed;\n\t\t\t\tif (pObject->bIsStatic) {\n\t\t\t\t\tpObject->SetIsStatic(false);\n\t\t\t\t\tpObject->AddToMovingList();\n\t\t\t\t}\n\t\t\t\tpObject->SetMoveSpeed(vecNewSpeed);\n\t\t\t}\n\t\t}\n\t\treturn 0;\n\t}\n\tcase COMMAND_GET_OBJECT_SPEED:\n\t{\n\t\tCollectParameters(&m_nIp, 1);\n\t\tCObject* pObject = CPools::GetObjectPool()->GetAt(ScriptParams[0]);\n\t\t*(float*)&ScriptParams[0] = pObject->GetMoveSpeed().Magnitude() * GAME_SPEED_TO_METERS_PER_SECOND;\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\t}\n#endif\n#if (defined GTA_MOBILE || defined SUPPORT_MOBILE_SCRIPT)\n\tcase COMMAND_IS_MISSION_SKIP:\n#ifdef MISSION_REPLAY\n\t\tScriptParams[0] = MissionSkipLevel;\n#else\n\t\tScriptParams[0] = 0;\n#endif\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\tcase COMMAND_SET_IN_AMMUNATION:\n\t\tCollectParameters(&m_nIp, 1);\n#ifdef MISSION_REPLAY\n\t\tIsInAmmunation = ScriptParams[0];\n#endif\n\t\treturn 0;\n\tcase COMMAND_DO_SAVE_GAME:\n\t\tCollectParameters(&m_nIp, 1);\n#ifdef MISSION_REPLAY\n\t\tSaveGameForPause(ScriptParams[0]);\n#endif\n\t\treturn 0;\n\tcase COMMAND_IS_RETRY:\n#ifdef MISSION_REPLAY\n\t\tif (strcmp(m_abScriptName, \"porno4\") != 0)\n\t\t\tScriptParams[0] = AllowMissionReplay;\n#ifdef FIX_BUGS\n\t\telse\n\t\t\tScriptParams[0] = gbTryingPorn4Again;\n#else\n\t\telse if (gbTryingPorn4Again)\n\t\t\tScriptParams[0] = 1;\n#endif\n#else\n\t\tScriptParams[0] = 0;\n#endif\n\t\tStoreParameters(&m_nIp, 1);\n\t\treturn 0;\n\tcase COMMAND_DUMMY:\n\t\treturn 0;\n#endif\n#if (defined GTA_XBOX || defined SUPPORT_XBOX_SCRIPT || defined GTA_MOBILE || defined SUPPORT_MOBILE_SCRIPT)\n\t// it is unknown what these commands do but they don't take parameters\n\tcase COMMAND_MARK_CUTSCENE_START:\n\t\treturn 0;\n\tcase COMMAND_MARK_CUTSCENE_END:\n\t\treturn 0;\n\tcase COMMAND_CUTSCENE_SCROLL:\n\t\treturn 0;\n#endif\n\tdefault:\n\t\tscript_assert(0);\n\t}\n\treturn -1;\n}\n"
  },
  {
    "path": "src/control/ScriptCommands.h",
    "content": "#pragma once\n\nenum {\n\tCOMMAND_NOP = 0,\n\tCOMMAND_WAIT,\n\tCOMMAND_GOTO,\n\tCOMMAND_SHAKE_CAM,\n\tCOMMAND_SET_VAR_INT,\n\tCOMMAND_SET_VAR_FLOAT,\n\tCOMMAND_SET_LVAR_INT,\n\tCOMMAND_SET_LVAR_FLOAT,\n\tCOMMAND_ADD_VAL_TO_INT_VAR,\n\tCOMMAND_ADD_VAL_TO_FLOAT_VAR,\n\tCOMMAND_ADD_VAL_TO_INT_LVAR,\n\tCOMMAND_ADD_VAL_TO_FLOAT_LVAR,\n\tCOMMAND_SUB_VAL_FROM_INT_VAR,\n\tCOMMAND_SUB_VAL_FROM_FLOAT_VAR,\n\tCOMMAND_SUB_VAL_FROM_INT_LVAR,\n\tCOMMAND_SUB_VAL_FROM_FLOAT_LVAR,\n\tCOMMAND_MULT_INT_VAR_BY_VAL,\n\tCOMMAND_MULT_FLOAT_VAR_BY_VAL,\n\tCOMMAND_MULT_INT_LVAR_BY_VAL,\n\tCOMMAND_MULT_FLOAT_LVAR_BY_VAL,\n\tCOMMAND_DIV_INT_VAR_BY_VAL,\n\tCOMMAND_DIV_FLOAT_VAR_BY_VAL,\n\tCOMMAND_DIV_INT_LVAR_BY_VAL,\n\tCOMMAND_DIV_FLOAT_LVAR_BY_VAL,\n\tCOMMAND_IS_INT_VAR_GREATER_THAN_NUMBER,\n\tCOMMAND_IS_INT_LVAR_GREATER_THAN_NUMBER,\n\tCOMMAND_IS_NUMBER_GREATER_THAN_INT_VAR,\n\tCOMMAND_IS_NUMBER_GREATER_THAN_INT_LVAR,\n\tCOMMAND_IS_INT_VAR_GREATER_THAN_INT_VAR,\n\tCOMMAND_IS_INT_LVAR_GREATER_THAN_INT_LVAR,\n\tCOMMAND_IS_INT_VAR_GREATER_THAN_INT_LVAR,\n\tCOMMAND_IS_INT_LVAR_GREATER_THAN_INT_VAR,\n\tCOMMAND_IS_FLOAT_VAR_GREATER_THAN_NUMBER,\n\tCOMMAND_IS_FLOAT_LVAR_GREATER_THAN_NUMBER,\n\tCOMMAND_IS_NUMBER_GREATER_THAN_FLOAT_VAR,\n\tCOMMAND_IS_NUMBER_GREATER_THAN_FLOAT_LVAR,\n\tCOMMAND_IS_FLOAT_VAR_GREATER_THAN_FLOAT_VAR,\n\tCOMMAND_IS_FLOAT_LVAR_GREATER_THAN_FLOAT_LVAR,\n\tCOMMAND_IS_FLOAT_VAR_GREATER_THAN_FLOAT_LVAR,\n\tCOMMAND_IS_FLOAT_LVAR_GREATER_THAN_FLOAT_VAR,\n\tCOMMAND_IS_INT_VAR_GREATER_OR_EQUAL_TO_NUMBER,\n\tCOMMAND_IS_INT_LVAR_GREATER_OR_EQUAL_TO_NUMBER,\n\tCOMMAND_IS_NUMBER_GREATER_OR_EQUAL_TO_INT_VAR,\n\tCOMMAND_IS_NUMBER_GREATER_OR_EQUAL_TO_INT_LVAR,\n\tCOMMAND_IS_INT_VAR_GREATER_OR_EQUAL_TO_INT_VAR,\n\tCOMMAND_IS_INT_LVAR_GREATER_OR_EQUAL_TO_INT_LVAR,\n\tCOMMAND_IS_INT_VAR_GREATER_OR_EQUAL_TO_INT_LVAR,\n\tCOMMAND_IS_INT_LVAR_GREATER_OR_EQUAL_TO_INT_VAR,\n\tCOMMAND_IS_FLOAT_VAR_GREATER_OR_EQUAL_TO_NUMBER,\n\tCOMMAND_IS_FLOAT_LVAR_GREATER_OR_EQUAL_TO_NUMBER,\n\tCOMMAND_IS_NUMBER_GREATER_OR_EQUAL_TO_FLOAT_VAR,\n\tCOMMAND_IS_NUMBER_GREATER_OR_EQUAL_TO_FLOAT_LVAR,\n\tCOMMAND_IS_FLOAT_VAR_GREATER_OR_EQUAL_TO_FLOAT_VAR,\n\tCOMMAND_IS_FLOAT_LVAR_GREATER_OR_EQUAL_TO_FLOAT_LVAR,\n\tCOMMAND_IS_FLOAT_VAR_GREATER_OR_EQUAL_TO_FLOAT_LVAR,\n\tCOMMAND_IS_FLOAT_LVAR_GREATER_OR_EQUAL_TO_FLOAT_VAR,\n\tCOMMAND_IS_INT_VAR_EQUAL_TO_NUMBER,\n\tCOMMAND_IS_INT_LVAR_EQUAL_TO_NUMBER,\n\tCOMMAND_IS_INT_VAR_EQUAL_TO_INT_VAR,\n\tCOMMAND_IS_INT_LVAR_EQUAL_TO_INT_LVAR,\n\tCOMMAND_IS_INT_VAR_EQUAL_TO_INT_LVAR,\n\tCOMMAND_IS_INT_VAR_NOT_EQUAL_TO_NUMBER,\n\tCOMMAND_IS_INT_LVAR_NOT_EQUAL_TO_NUMBER,\n\tCOMMAND_IS_INT_VAR_NOT_EQUAL_TO_INT_VAR,\n\tCOMMAND_IS_INT_LVAR_NOT_EQUAL_TO_INT_LVAR,\n\tCOMMAND_IS_INT_VAR_NOT_EQUAL_TO_INT_LVAR,\n\tCOMMAND_IS_FLOAT_VAR_EQUAL_TO_NUMBER,\n\tCOMMAND_IS_FLOAT_LVAR_EQUAL_TO_NUMBER,\n\tCOMMAND_IS_FLOAT_VAR_EQUAL_TO_FLOAT_VAR,\n\tCOMMAND_IS_FLOAT_LVAR_EQUAL_TO_FLOAT_LVAR,\n\tCOMMAND_IS_FLOAT_VAR_EQUAL_TO_FLOAT_LVAR,\n\tCOMMAND_IS_FLOAT_VAR_NOT_EQUAL_TO_NUMBER,\n\tCOMMAND_IS_FLOAT_LVAR_NOT_EQUAL_TO_NUMBER,\n\tCOMMAND_IS_FLOAT_VAR_NOT_EQUAL_TO_FLOAT_VAR,\n\tCOMMAND_IS_FLOAT_LVAR_NOT_EQUAL_TO_FLOAT_LVAR,\n\tCOMMAND_IS_FLOAT_VAR_NOT_EQUAL_TO_FLOAT_LVAR,\n\tCOMMAND_GOTO_IF_TRUE,\n\tCOMMAND_GOTO_IF_FALSE,\n\tCOMMAND_TERMINATE_THIS_SCRIPT,\n\tCOMMAND_START_NEW_SCRIPT,\n\tCOMMAND_GOSUB,\n\tCOMMAND_RETURN,\n\tCOMMAND_LINE,\n\tCOMMAND_CREATE_PLAYER,\n\tCOMMAND_GET_PLAYER_COORDINATES,\n\tCOMMAND_SET_PLAYER_COORDINATES,\n\tCOMMAND_IS_PLAYER_IN_AREA_2D,\n\tCOMMAND_IS_PLAYER_IN_AREA_3D,\n\tCOMMAND_ADD_INT_VAR_TO_INT_VAR,\n\tCOMMAND_ADD_FLOAT_VAR_TO_FLOAT_VAR,\n\tCOMMAND_ADD_INT_LVAR_TO_INT_LVAR,\n\tCOMMAND_ADD_FLOAT_LVAR_TO_FLOAT_LVAR,\n\tCOMMAND_ADD_INT_VAR_TO_INT_LVAR,\n\tCOMMAND_ADD_FLOAT_VAR_TO_FLOAT_LVAR,\n\tCOMMAND_ADD_INT_LVAR_TO_INT_VAR,\n\tCOMMAND_ADD_FLOAT_LVAR_TO_FLOAT_VAR,\n\tCOMMAND_SUB_INT_VAR_FROM_INT_VAR,\n\tCOMMAND_SUB_FLOAT_VAR_FROM_FLOAT_VAR,\n\tCOMMAND_SUB_INT_LVAR_FROM_INT_LVAR,\n\tCOMMAND_SUB_FLOAT_LVAR_FROM_FLOAT_LVAR,\n\tCOMMAND_SUB_INT_VAR_FROM_INT_LVAR,\n\tCOMMAND_SUB_FLOAT_VAR_FROM_FLOAT_LVAR,\n\tCOMMAND_SUB_INT_LVAR_FROM_INT_VAR,\n\tCOMMAND_SUB_FLOAT_LVAR_FROM_FLOAT_VAR,\n\tCOMMAND_MULT_INT_VAR_BY_INT_VAR,\n\tCOMMAND_MULT_FLOAT_VAR_BY_FLOAT_VAR,\n\tCOMMAND_MULT_INT_LVAR_BY_INT_LVAR,\n\tCOMMAND_MULT_FLOAT_LVAR_BY_FLOAT_LVAR,\n\tCOMMAND_MULT_INT_VAR_BY_INT_LVAR,\n\tCOMMAND_MULT_FLOAT_VAR_BY_FLOAT_LVAR,\n\tCOMMAND_MULT_INT_LVAR_BY_INT_VAR,\n\tCOMMAND_MULT_FLOAT_LVAR_BY_FLOAT_VAR,\n\tCOMMAND_DIV_INT_VAR_BY_INT_VAR,\n\tCOMMAND_DIV_FLOAT_VAR_BY_FLOAT_VAR,\n\tCOMMAND_DIV_INT_LVAR_BY_INT_LVAR,\n\tCOMMAND_DIV_FLOAT_LVAR_BY_FLOAT_LVAR,\n\tCOMMAND_DIV_INT_VAR_BY_INT_LVAR,\n\tCOMMAND_DIV_FLOAT_VAR_BY_FLOAT_LVAR,\n\tCOMMAND_DIV_INT_LVAR_BY_INT_VAR,\n\tCOMMAND_DIV_FLOAT_LVAR_BY_FLOAT_VAR,\n\tCOMMAND_ADD_TIMED_VAL_TO_FLOAT_VAR,\n\tCOMMAND_ADD_TIMED_VAL_TO_FLOAT_LVAR,\n\tCOMMAND_ADD_TIMED_FLOAT_VAR_TO_FLOAT_VAR,\n\tCOMMAND_ADD_TIMED_FLOAT_LVAR_TO_FLOAT_LVAR,\n\tCOMMAND_ADD_TIMED_FLOAT_LVAR_TO_FLOAT_VAR,\n\tCOMMAND_ADD_TIMED_FLOAT_VAR_TO_FLOAT_LVAR,\n\tCOMMAND_SUB_TIMED_VAL_FROM_FLOAT_VAR,\n\tCOMMAND_SUB_TIMED_VAL_FROM_FLOAT_LVAR,\n\tCOMMAND_SUB_TIMED_FLOAT_VAR_FROM_FLOAT_VAR,\n\tCOMMAND_SUB_TIMED_FLOAT_LVAR_FROM_FLOAT_LVAR,\n\tCOMMAND_SUB_TIMED_FLOAT_LVAR_FROM_FLOAT_VAR,\n\tCOMMAND_SUB_TIMED_FLOAT_VAR_FROM_FLOAT_LVAR,\n\tCOMMAND_SET_VAR_INT_TO_VAR_INT,\n\tCOMMAND_SET_LVAR_INT_TO_LVAR_INT,\n\tCOMMAND_SET_VAR_FLOAT_TO_VAR_FLOAT,\n\tCOMMAND_SET_LVAR_FLOAT_TO_LVAR_FLOAT,\n\tCOMMAND_SET_VAR_FLOAT_TO_LVAR_FLOAT,\n\tCOMMAND_SET_LVAR_FLOAT_TO_VAR_FLOAT,\n\tCOMMAND_SET_VAR_INT_TO_LVAR_INT,\n\tCOMMAND_SET_LVAR_INT_TO_VAR_INT,\n\tCOMMAND_CSET_VAR_INT_TO_VAR_FLOAT,\n\tCOMMAND_CSET_VAR_FLOAT_TO_VAR_INT,\n\tCOMMAND_CSET_LVAR_INT_TO_VAR_FLOAT,\n\tCOMMAND_CSET_LVAR_FLOAT_TO_VAR_INT,\n\tCOMMAND_CSET_VAR_INT_TO_LVAR_FLOAT,\n\tCOMMAND_CSET_VAR_FLOAT_TO_LVAR_INT,\n\tCOMMAND_CSET_LVAR_INT_TO_LVAR_FLOAT,\n\tCOMMAND_CSET_LVAR_FLOAT_TO_LVAR_INT,\n\tCOMMAND_ABS_VAR_INT,\n\tCOMMAND_ABS_LVAR_INT,\n\tCOMMAND_ABS_VAR_FLOAT,\n\tCOMMAND_ABS_LVAR_FLOAT,\n\tCOMMAND_GENERATE_RANDOM_FLOAT,\n\tCOMMAND_GENERATE_RANDOM_INT,\n\tCOMMAND_CREATE_CHAR,\n\tCOMMAND_DELETE_CHAR,\n\tCOMMAND_CHAR_WANDER_DIR,\n\tCOMMAND_CHAR_WANDER_RANGE,\n\tCOMMAND_CHAR_FOLLOW_PATH,\n\tCOMMAND_CHAR_SET_IDLE,\n\tCOMMAND_GET_CHAR_COORDINATES,\n\tCOMMAND_SET_CHAR_COORDINATES,\n\tCOMMAND_IS_CHAR_STILL_ALIVE,\n\tCOMMAND_IS_CHAR_IN_AREA_2D,\n\tCOMMAND_IS_CHAR_IN_AREA_3D,\n\tCOMMAND_CREATE_CAR,\n\tCOMMAND_DELETE_CAR,\n\tCOMMAND_CAR_GOTO_COORDINATES,\n\tCOMMAND_CAR_WANDER_RANDOMLY,\n\tCOMMAND_CAR_SET_IDLE,\n\tCOMMAND_GET_CAR_COORDINATES,\n\tCOMMAND_SET_CAR_COORDINATES,\n\tCOMMAND_IS_CAR_STILL_ALIVE,\n\tCOMMAND_SET_CAR_CRUISE_SPEED,\n\tCOMMAND_SET_CAR_DRIVING_STYLE,\n\tCOMMAND_SET_CAR_MISSION,\n\tCOMMAND_IS_CAR_IN_AREA_2D,\n\tCOMMAND_IS_CAR_IN_AREA_3D,\n\tCOMMAND_SPECIAL_0,\n\tCOMMAND_SPECIAL_1,\n\tCOMMAND_SPECIAL_2,\n\tCOMMAND_SPECIAL_3,\n\tCOMMAND_SPECIAL_4,\n\tCOMMAND_SPECIAL_5,\n\tCOMMAND_SPECIAL_6,\n\tCOMMAND_SPECIAL_7,\n\tCOMMAND_PRINT_BIG,\n\tCOMMAND_PRINT,\n\tCOMMAND_PRINT_NOW,\n\tCOMMAND_PRINT_SOON,\n\tCOMMAND_CLEAR_PRINTS,\n\tCOMMAND_GET_TIME_OF_DAY,\n\tCOMMAND_SET_TIME_OF_DAY,\n\tCOMMAND_GET_MINUTES_TO_TIME_OF_DAY,\n\tCOMMAND_IS_POINT_ON_SCREEN,\n\tCOMMAND_DEBUG_ON,\n\tCOMMAND_DEBUG_OFF,\n\tCOMMAND_RETURN_TRUE,\n\tCOMMAND_RETURN_FALSE,\n\tCOMMAND_VAR_INT,\n\tCOMMAND_VAR_FLOAT,\n\tCOMMAND_LVAR_INT,\n\tCOMMAND_LVAR_FLOAT,\n\tCOMMAND_LBRACKET,\n\tCOMMAND_RBRACKET,\n\tCOMMAND_REPEAT,\n\tCOMMAND_ENDREPEAT,\n\tCOMMAND_IF,\n\tCOMMAND_IFNOT,\n\tCOMMAND_ELSE,\n\tCOMMAND_ENDIF,\n\tCOMMAND_WHILE,\n\tCOMMAND_WHILENOT,\n\tCOMMAND_ENDWHILE,\n\tCOMMAND_ANDOR,\n\tCOMMAND_LAUNCH_MISSION,\n\tCOMMAND_MISSION_HAS_FINISHED,\n\tCOMMAND_STORE_CAR_CHAR_IS_IN,\n\tCOMMAND_STORE_CAR_PLAYER_IS_IN,\n\tCOMMAND_IS_CHAR_IN_CAR,\n\tCOMMAND_IS_PLAYER_IN_CAR,\n\tCOMMAND_IS_CHAR_IN_MODEL,\n\tCOMMAND_IS_PLAYER_IN_MODEL,\n\tCOMMAND_IS_CHAR_IN_ANY_CAR,\n\tCOMMAND_IS_PLAYER_IN_ANY_CAR,\n\tCOMMAND_IS_BUTTON_PRESSED,\n\tCOMMAND_GET_PAD_STATE,\n\tCOMMAND_LOCATE_PLAYER_ANY_MEANS_2D,\n\tCOMMAND_LOCATE_PLAYER_ON_FOOT_2D,\n\tCOMMAND_LOCATE_PLAYER_IN_CAR_2D,\n\tCOMMAND_LOCATE_STOPPED_PLAYER_ANY_MEANS_2D,\n\tCOMMAND_LOCATE_STOPPED_PLAYER_ON_FOOT_2D,\n\tCOMMAND_LOCATE_STOPPED_PLAYER_IN_CAR_2D,\n\tCOMMAND_LOCATE_PLAYER_ANY_MEANS_CHAR_2D,\n\tCOMMAND_LOCATE_PLAYER_ON_FOOT_CHAR_2D,\n\tCOMMAND_LOCATE_PLAYER_IN_CAR_CHAR_2D,\n\tCOMMAND_LOCATE_CHAR_ANY_MEANS_2D,\n\tCOMMAND_LOCATE_CHAR_ON_FOOT_2D,\n\tCOMMAND_LOCATE_CHAR_IN_CAR_2D,\n\tCOMMAND_LOCATE_STOPPED_CHAR_ANY_MEANS_2D,\n\tCOMMAND_LOCATE_STOPPED_CHAR_ON_FOOT_2D,\n\tCOMMAND_LOCATE_STOPPED_CHAR_IN_CAR_2D,\n\tCOMMAND_LOCATE_CHAR_ANY_MEANS_CHAR_2D,\n\tCOMMAND_LOCATE_CHAR_ON_FOOT_CHAR_2D,\n\tCOMMAND_LOCATE_CHAR_IN_CAR_CHAR_2D,\n\tCOMMAND_LOCATE_PLAYER_ANY_MEANS_3D,\n\tCOMMAND_LOCATE_PLAYER_ON_FOOT_3D,\n\tCOMMAND_LOCATE_PLAYER_IN_CAR_3D,\n\tCOMMAND_LOCATE_STOPPED_PLAYER_ANY_MEANS_3D,\n\tCOMMAND_LOCATE_STOPPED_PLAYER_ON_FOOT_3D,\n\tCOMMAND_LOCATE_STOPPED_PLAYER_IN_CAR_3D,\n\tCOMMAND_LOCATE_PLAYER_ANY_MEANS_CHAR_3D,\n\tCOMMAND_LOCATE_PLAYER_ON_FOOT_CHAR_3D,\n\tCOMMAND_LOCATE_PLAYER_IN_CAR_CHAR_3D,\n\tCOMMAND_LOCATE_CHAR_ANY_MEANS_3D,\n\tCOMMAND_LOCATE_CHAR_ON_FOOT_3D,\n\tCOMMAND_LOCATE_CHAR_IN_CAR_3D,\n\tCOMMAND_LOCATE_STOPPED_CHAR_ANY_MEANS_3D,\n\tCOMMAND_LOCATE_STOPPED_CHAR_ON_FOOT_3D,\n\tCOMMAND_LOCATE_STOPPED_CHAR_IN_CAR_3D,\n\tCOMMAND_LOCATE_CHAR_ANY_MEANS_CHAR_3D,\n\tCOMMAND_LOCATE_CHAR_ON_FOOT_CHAR_3D,\n\tCOMMAND_LOCATE_CHAR_IN_CAR_CHAR_3D,\n\tCOMMAND_CREATE_OBJECT,\n\tCOMMAND_DELETE_OBJECT,\n\tCOMMAND_ADD_SCORE,\n\tCOMMAND_IS_SCORE_GREATER,\n\tCOMMAND_STORE_SCORE,\n\tCOMMAND_GIVE_REMOTE_CONTROLLED_CAR_TO_PLAYER,\n\tCOMMAND_ALTER_WANTED_LEVEL,\n\tCOMMAND_ALTER_WANTED_LEVEL_NO_DROP,\n\tCOMMAND_IS_WANTED_LEVEL_GREATER,\n\tCOMMAND_CLEAR_WANTED_LEVEL,\n\tCOMMAND_SET_DEATHARREST_STATE,\n\tCOMMAND_HAS_DEATHARREST_BEEN_EXECUTED,\n\tCOMMAND_ADD_AMMO_TO_PLAYER,\n\tCOMMAND_ADD_AMMO_TO_CHAR,\n\tCOMMAND_ADD_AMMO_TO_CAR,\n\tCOMMAND_IS_PLAYER_STILL_ALIVE,\n\tCOMMAND_IS_PLAYER_DEAD,\n\tCOMMAND_IS_CHAR_DEAD,\n\tCOMMAND_IS_CAR_DEAD,\n\tCOMMAND_SET_CHAR_THREAT_SEARCH,\n\tCOMMAND_SET_CHAR_THREAT_REACTION,\n\tCOMMAND_SET_CHAR_OBJ_NO_OBJ,\n\tCOMMAND_ORDER_DRIVER_OUT_OF_CAR,\n\tCOMMAND_ORDER_CHAR_TO_DRIVE_CAR,\n\tCOMMAND_ADD_PATROL_POINT,\n\tCOMMAND_IS_PLAYER_IN_GANGZONE,\n\tCOMMAND_IS_PLAYER_IN_ZONE,\n\tCOMMAND_IS_PLAYER_PRESSING_HORN,\n\tCOMMAND_HAS_CHAR_SPOTTED_PLAYER,\n\tCOMMAND_ORDER_CHAR_TO_BACKDOOR,\n\tCOMMAND_ADD_CHAR_TO_GANG,\n\tCOMMAND_IS_CHAR_OBJECTIVE_PASSED,\n\tCOMMAND_SET_CHAR_DRIVE_AGGRESSION,\n\tCOMMAND_SET_CHAR_MAX_DRIVESPEED,\n\tCOMMAND_CREATE_CHAR_INSIDE_CAR,\n\tCOMMAND_WARP_PLAYER_FROM_CAR_TO_COORD,\n\tCOMMAND_MAKE_CHAR_DO_NOTHING,\n\tCOMMAND_SET_CHAR_INVINCIBLE,\n\tCOMMAND_SET_PLAYER_INVINCIBLE,\n\tCOMMAND_SET_CHAR_GRAPHIC_TYPE,\n\tCOMMAND_SET_PLAYER_GRAPHIC_TYPE,\n\tCOMMAND_HAS_PLAYER_BEEN_ARRESTED,\n\tCOMMAND_STOP_CHAR_DRIVING,\n\tCOMMAND_KILL_CHAR,\n\tCOMMAND_SET_FAVOURITE_CAR_MODEL_FOR_CHAR,\n\tCOMMAND_SET_CHAR_OCCUPATION,\n\tCOMMAND_CHANGE_CAR_LOCK,\n\tCOMMAND_SHAKE_CAM_WITH_POINT,\n\tCOMMAND_IS_CAR_MODEL,\n\tCOMMAND_IS_CAR_REMAP,\n\tCOMMAND_HAS_CAR_JUST_SUNK,\n\tCOMMAND_SET_CAR_NO_COLLIDE,\n\tCOMMAND_IS_CAR_DEAD_IN_AREA_2D,\n\tCOMMAND_IS_CAR_DEAD_IN_AREA_3D,\n\tCOMMAND_IS_TRAILER_ATTACHED,\n\tCOMMAND_IS_CAR_ON_TRAILER,\n\tCOMMAND_HAS_CAR_GOT_WEAPON,\n\tCOMMAND_PARK,\n\tCOMMAND_HAS_PARK_FINISHED,\n\tCOMMAND_KILL_ALL_PASSENGERS,\n\tCOMMAND_SET_CAR_BULLETPROOF,\n\tCOMMAND_SET_CAR_FLAMEPROOF,\n\tCOMMAND_SET_CAR_ROCKETPROOF,\n\tCOMMAND_IS_CARBOMB_ACTIVE,\n\tCOMMAND_GIVE_CAR_ALARM,\n\tCOMMAND_PUT_CAR_ON_TRAILER,\n\tCOMMAND_IS_CAR_CRUSHED,\n\tCOMMAND_CREATE_GANG_CAR,\n\tCOMMAND_CREATE_CAR_GENERATOR,\n\tCOMMAND_SWITCH_CAR_GENERATOR,\n\tCOMMAND_ADD_PAGER_MESSAGE,\n\tCOMMAND_DISPLAY_ONSCREEN_TIMER,\n\tCOMMAND_CLEAR_ONSCREEN_TIMER,\n\tCOMMAND_DISPLAY_ONSCREEN_COUNTER,\n\tCOMMAND_CLEAR_ONSCREEN_COUNTER,\n\tCOMMAND_SET_ZONE_CAR_INFO,\n\tCOMMAND_IS_CHAR_IN_GANG_ZONE,\n\tCOMMAND_IS_CHAR_IN_ZONE,\n\tCOMMAND_SET_CAR_DENSITY,\n\tCOMMAND_SET_PED_DENSITY,\n\tCOMMAND_POINT_CAMERA_AT_PLAYER,\n\tCOMMAND_POINT_CAMERA_AT_CAR,\n\tCOMMAND_POINT_CAMERA_AT_CHAR,\n\tCOMMAND_RESTORE_CAMERA,\n\tCOMMAND_SHAKE_PAD,\n\tCOMMAND_SET_ZONE_PED_INFO,\n\tCOMMAND_SET_TIME_SCALE,\n\tCOMMAND_IS_CAR_IN_AIR,\n\tCOMMAND_SET_FIXED_CAMERA_POSITION,\n\tCOMMAND_POINT_CAMERA_AT_POINT,\n\tCOMMAND_ADD_BLIP_FOR_CAR_OLD,\n\tCOMMAND_ADD_BLIP_FOR_CHAR_OLD,\n\tCOMMAND_ADD_BLIP_FOR_OBJECT_OLD,\n\tCOMMAND_REMOVE_BLIP,\n\tCOMMAND_CHANGE_BLIP_COLOUR,\n\tCOMMAND_DIM_BLIP,\n\tCOMMAND_ADD_BLIP_FOR_COORD_OLD,\n\tCOMMAND_CHANGE_BLIP_SCALE,\n\tCOMMAND_SET_FADING_COLOUR,\n\tCOMMAND_DO_FADE,\n\tCOMMAND_GET_FADING_STATUS,\n\tCOMMAND_ADD_HOSPITAL_RESTART,\n\tCOMMAND_ADD_POLICE_RESTART,\n\tCOMMAND_OVERRIDE_NEXT_RESTART,\n\tCOMMAND_DRAW_SHADOW,\n\tCOMMAND_GET_PLAYER_HEADING,\n\tCOMMAND_SET_PLAYER_HEADING,\n\tCOMMAND_GET_CHAR_HEADING,\n\tCOMMAND_SET_CHAR_HEADING,\n\tCOMMAND_GET_CAR_HEADING,\n\tCOMMAND_SET_CAR_HEADING,\n\tCOMMAND_GET_OBJECT_HEADING,\n\tCOMMAND_SET_OBJECT_HEADING,\n\tCOMMAND_IS_PLAYER_TOUCHING_OBJECT,\n\tCOMMAND_IS_CHAR_TOUCHING_OBJECT,\n\tCOMMAND_SET_PLAYER_AMMO,\n\tCOMMAND_SET_CHAR_AMMO,\n\tCOMMAND_SET_CAR_AMMO,\n\tCOMMAND_LOAD_CAMERA_SPLINE,\n\tCOMMAND_MOVE_CAMERA_ALONG_SPLINE,\n\tCOMMAND_GET_CAMERA_POSITION_ALONG_SPLINE,\n\tCOMMAND_DECLARE_MISSION_FLAG,\n\tCOMMAND_DECLARE_MISSION_FLAG_FOR_CONTACT,\n\tCOMMAND_DECLARE_BASE_BRIEF_ID_FOR_CONTACT,\n\tCOMMAND_IS_PLAYER_HEALTH_GREATER,\n\tCOMMAND_IS_CHAR_HEALTH_GREATER,\n\tCOMMAND_IS_CAR_HEALTH_GREATER,\n\tCOMMAND_ADD_BLIP_FOR_CAR,\n\tCOMMAND_ADD_BLIP_FOR_CHAR,\n\tCOMMAND_ADD_BLIP_FOR_OBJECT,\n\tCOMMAND_ADD_BLIP_FOR_CONTACT_POINT,\n\tCOMMAND_ADD_BLIP_FOR_COORD,\n\tCOMMAND_CHANGE_BLIP_DISPLAY,\n\tCOMMAND_ADD_ONE_OFF_SOUND,\n\tCOMMAND_ADD_CONTINUOUS_SOUND,\n\tCOMMAND_REMOVE_SOUND,\n\tCOMMAND_IS_CAR_STUCK_ON_ROOF,\n\tCOMMAND_ADD_UPSIDEDOWN_CAR_CHECK,\n\tCOMMAND_REMOVE_UPSIDEDOWN_CAR_CHECK,\n\tCOMMAND_SET_CHAR_OBJ_WAIT_ON_FOOT,\n\tCOMMAND_SET_CHAR_OBJ_FLEE_ON_FOOT_TILL_SAFE,\n\tCOMMAND_SET_CHAR_OBJ_GUARD_SPOT,\n\tCOMMAND_SET_CHAR_OBJ_GUARD_AREA,\n\tCOMMAND_SET_CHAR_OBJ_WAIT_IN_CAR,\n\tCOMMAND_IS_PLAYER_IN_AREA_ON_FOOT_2D,\n\tCOMMAND_IS_PLAYER_IN_AREA_IN_CAR_2D,\n\tCOMMAND_IS_PLAYER_STOPPED_IN_AREA_2D,\n\tCOMMAND_IS_PLAYER_STOPPED_IN_AREA_ON_FOOT_2D,\n\tCOMMAND_IS_PLAYER_STOPPED_IN_AREA_IN_CAR_2D,\n\tCOMMAND_IS_PLAYER_IN_AREA_ON_FOOT_3D,\n\tCOMMAND_IS_PLAYER_IN_AREA_IN_CAR_3D,\n\tCOMMAND_IS_PLAYER_STOPPED_IN_AREA_3D,\n\tCOMMAND_IS_PLAYER_STOPPED_IN_AREA_ON_FOOT_3D,\n\tCOMMAND_IS_PLAYER_STOPPED_IN_AREA_IN_CAR_3D,\n\tCOMMAND_IS_CHAR_IN_AREA_ON_FOOT_2D,\n\tCOMMAND_IS_CHAR_IN_AREA_IN_CAR_2D,\n\tCOMMAND_IS_CHAR_STOPPED_IN_AREA_2D,\n\tCOMMAND_IS_CHAR_STOPPED_IN_AREA_ON_FOOT_2D,\n\tCOMMAND_IS_CHAR_STOPPED_IN_AREA_IN_CAR_2D,\n\tCOMMAND_IS_CHAR_IN_AREA_ON_FOOT_3D,\n\tCOMMAND_IS_CHAR_IN_AREA_IN_CAR_3D,\n\tCOMMAND_IS_CHAR_STOPPED_IN_AREA_3D,\n\tCOMMAND_IS_CHAR_STOPPED_IN_AREA_ON_FOOT_3D,\n\tCOMMAND_IS_CHAR_STOPPED_IN_AREA_IN_CAR_3D,\n\tCOMMAND_IS_CAR_STOPPED_IN_AREA_2D,\n\tCOMMAND_IS_CAR_STOPPED_IN_AREA_3D,\n\tCOMMAND_LOCATE_CAR_2D,\n\tCOMMAND_LOCATE_STOPPED_CAR_2D,\n\tCOMMAND_LOCATE_CAR_3D,\n\tCOMMAND_LOCATE_STOPPED_CAR_3D,\n\tCOMMAND_GIVE_WEAPON_TO_PLAYER,\n\tCOMMAND_GIVE_WEAPON_TO_CHAR,\n\tCOMMAND_GIVE_WEAPON_TO_CAR,\n\tCOMMAND_SET_PLAYER_CONTROL,\n\tCOMMAND_FORCE_WEATHER,\n\tCOMMAND_FORCE_WEATHER_NOW,\n\tCOMMAND_RELEASE_WEATHER,\n\tCOMMAND_SET_CURRENT_PLAYER_WEAPON,\n\tCOMMAND_SET_CURRENT_CHAR_WEAPON,\n\tCOMMAND_SET_CURRENT_CAR_WEAPON,\n\tCOMMAND_GET_OBJECT_COORDINATES,\n\tCOMMAND_SET_OBJECT_COORDINATES,\n\tCOMMAND_GET_GAME_TIMER,\n\tCOMMAND_TURN_CHAR_TO_FACE_COORD,\n\tCOMMAND_TURN_PLAYER_TO_FACE_COORD,\n\tCOMMAND_STORE_WANTED_LEVEL,\n\tCOMMAND_IS_CAR_STOPPED,\n\tCOMMAND_MARK_CHAR_AS_NO_LONGER_NEEDED,\n\tCOMMAND_MARK_CAR_AS_NO_LONGER_NEEDED,\n\tCOMMAND_MARK_OBJECT_AS_NO_LONGER_NEEDED,\n\tCOMMAND_DONT_REMOVE_CHAR,\n\tCOMMAND_DONT_REMOVE_CAR,\n\tCOMMAND_DONT_REMOVE_OBJECT,\n\tCOMMAND_CREATE_CHAR_AS_PASSENGER,\n\tCOMMAND_SET_CHAR_OBJ_KILL_CHAR_ON_FOOT,\n\tCOMMAND_SET_CHAR_OBJ_KILL_PLAYER_ON_FOOT,\n\tCOMMAND_SET_CHAR_OBJ_KILL_CHAR_ANY_MEANS,\n\tCOMMAND_SET_CHAR_OBJ_KILL_PLAYER_ANY_MEANS,\n\tCOMMAND_SET_CHAR_OBJ_FLEE_CHAR_ON_FOOT_TILL_SAFE,\n\tCOMMAND_SET_CHAR_OBJ_FLEE_PLAYER_ON_FOOT_TILL_SAFE,\n\tCOMMAND_SET_CHAR_OBJ_FLEE_CHAR_ON_FOOT_ALWAYS,\n\tCOMMAND_SET_CHAR_OBJ_FLEE_PLAYER_ON_FOOT_ALWAYS,\n\tCOMMAND_SET_CHAR_OBJ_GOTO_CHAR_ON_FOOT,\n\tCOMMAND_SET_CHAR_OBJ_GOTO_PLAYER_ON_FOOT,\n\tCOMMAND_SET_CHAR_OBJ_LEAVE_CAR,\n\tCOMMAND_SET_CHAR_OBJ_ENTER_CAR_AS_PASSENGER,\n\tCOMMAND_SET_CHAR_OBJ_ENTER_CAR_AS_DRIVER,\n\tCOMMAND_SET_CHAR_OBJ_FOLLOW_CAR_IN_CAR,\n\tCOMMAND_SET_CHAR_OBJ_FIRE_AT_OBJECT_FROM_VEHICLE,\n\tCOMMAND_SET_CHAR_OBJ_DESTROY_OBJECT,\n\tCOMMAND_SET_CHAR_OBJ_DESTROY_CAR,\n\tCOMMAND_SET_CHAR_OBJ_GOTO_AREA_ON_FOOT,\n\tCOMMAND_SET_CHAR_OBJ_GOTO_AREA_IN_CAR,\n\tCOMMAND_SET_CHAR_OBJ_FOLLOW_CAR_ON_FOOT_WITH_OFFSET,\n\tCOMMAND_SET_CHAR_OBJ_GUARD_ATTACK,\n\tCOMMAND_SET_CHAR_AS_LEADER,\n\tCOMMAND_SET_PLAYER_AS_LEADER,\n\tCOMMAND_LEAVE_GROUP,\n\tCOMMAND_SET_CHAR_OBJ_FOLLOW_ROUTE,\n\tCOMMAND_ADD_ROUTE_POINT,\n\tCOMMAND_PRINT_WITH_NUMBER_BIG,\n\tCOMMAND_PRINT_WITH_NUMBER,\n\tCOMMAND_PRINT_WITH_NUMBER_NOW,\n\tCOMMAND_PRINT_WITH_NUMBER_SOON,\n\tCOMMAND_SWITCH_ROADS_ON,\n\tCOMMAND_SWITCH_ROADS_OFF,\n\tCOMMAND_GET_NUMBER_OF_PASSENGERS,\n\tCOMMAND_GET_MAXIMUM_NUMBER_OF_PASSENGERS,\n\tCOMMAND_SET_CAR_DENSITY_MULTIPLIER,\n\tCOMMAND_SET_CAR_HEAVY,\n\tCOMMAND_CLEAR_CHAR_THREAT_SEARCH,\n\tCOMMAND_ACTIVATE_CRANE,\n\tCOMMAND_DEACTIVATE_CRANE,\n\tCOMMAND_SET_MAX_WANTED_LEVEL,\n\tCOMMAND_SAVE_VAR_INT,\n\tCOMMAND_SAVE_VAR_FLOAT,\n\tCOMMAND_IS_CAR_IN_AIR_PROPER,\n\tCOMMAND_IS_CAR_UPSIDEDOWN,\n\tCOMMAND_GET_PLAYER_CHAR,\n\tCOMMAND_CANCEL_OVERRIDE_RESTART,\n\tCOMMAND_SET_POLICE_IGNORE_PLAYER,\n\tCOMMAND_ADD_PAGER_MESSAGE_WITH_NUMBER,\n\tCOMMAND_START_KILL_FRENZY,\n\tCOMMAND_READ_KILL_FRENZY_STATUS,\n\tCOMMAND_SQRT,\n\tCOMMAND_LOCATE_PLAYER_ANY_MEANS_CAR_2D,\n\tCOMMAND_LOCATE_PLAYER_ON_FOOT_CAR_2D,\n\tCOMMAND_LOCATE_PLAYER_IN_CAR_CAR_2D,\n\tCOMMAND_LOCATE_PLAYER_ANY_MEANS_CAR_3D,\n\tCOMMAND_LOCATE_PLAYER_ON_FOOT_CAR_3D,\n\tCOMMAND_LOCATE_PLAYER_IN_CAR_CAR_3D,\n\tCOMMAND_LOCATE_CHAR_ANY_MEANS_CAR_2D,\n\tCOMMAND_LOCATE_CHAR_ON_FOOT_CAR_2D,\n\tCOMMAND_LOCATE_CHAR_IN_CAR_CAR_2D,\n\tCOMMAND_LOCATE_CHAR_ANY_MEANS_CAR_3D,\n\tCOMMAND_LOCATE_CHAR_ON_FOOT_CAR_3D,\n\tCOMMAND_LOCATE_CHAR_IN_CAR_CAR_3D,\n\tCOMMAND_GENERATE_RANDOM_FLOAT_IN_RANGE,\n\tCOMMAND_GENERATE_RANDOM_INT_IN_RANGE,\n\tCOMMAND_LOCK_CAR_DOORS,\n\tCOMMAND_EXPLODE_CAR,\n\tCOMMAND_ADD_EXPLOSION,\n\tCOMMAND_IS_CAR_UPRIGHT,\n\tCOMMAND_TURN_CHAR_TO_FACE_CHAR,\n\tCOMMAND_TURN_CHAR_TO_FACE_PLAYER,\n\tCOMMAND_TURN_PLAYER_TO_FACE_CHAR,\n\tCOMMAND_SET_CHAR_OBJ_GOTO_COORD_ON_FOOT,\n\tCOMMAND_SET_CHAR_OBJ_GOTO_COORD_IN_CAR,\n\tCOMMAND_CREATE_PICKUP,\n\tCOMMAND_HAS_PICKUP_BEEN_COLLECTED,\n\tCOMMAND_REMOVE_PICKUP,\n\tCOMMAND_SET_TAXI_LIGHTS,\n\tCOMMAND_PRINT_BIG_Q,\n\tCOMMAND_PRINT_WITH_NUMBER_BIG_Q,\n\tCOMMAND_SET_GARAGE,\n\tCOMMAND_SET_GARAGE_WITH_CAR_MODEL,\n\tCOMMAND_SET_TARGET_CAR_FOR_MISSION_GARAGE,\n\tCOMMAND_IS_CAR_IN_MISSION_GARAGE,\n\tCOMMAND_SET_FREE_BOMBS,\n\tCOMMAND_SET_POWERPOINT,\n\tCOMMAND_SET_ALL_TAXI_LIGHTS,\n\tCOMMAND_IS_CAR_ARMED_WITH_ANY_BOMB,\n\tCOMMAND_APPLY_BRAKES_TO_PLAYERS_CAR,\n\tCOMMAND_SET_PLAYER_HEALTH,\n\tCOMMAND_SET_CHAR_HEALTH,\n\tCOMMAND_SET_CAR_HEALTH,\n\tCOMMAND_GET_PLAYER_HEALTH,\n\tCOMMAND_GET_CHAR_HEALTH,\n\tCOMMAND_GET_CAR_HEALTH,\n\tCOMMAND_IS_CAR_ARMED_WITH_BOMB,\n\tCOMMAND_CHANGE_CAR_COLOUR,\n\tCOMMAND_SWITCH_PED_ROADS_ON,\n\tCOMMAND_SWITCH_PED_ROADS_OFF,\n\tCOMMAND_CHAR_LOOK_AT_CHAR_ALWAYS,\n\tCOMMAND_CHAR_LOOK_AT_PLAYER_ALWAYS,\n\tCOMMAND_PLAYER_LOOK_AT_CHAR_ALWAYS,\n\tCOMMAND_STOP_CHAR_LOOKING,\n\tCOMMAND_STOP_PLAYER_LOOKING,\n\tCOMMAND_SWITCH_HELICOPTER,\n\tCOMMAND_SET_GANG_ATTITUDE,\n\tCOMMAND_SET_GANG_GANG_ATTITUDE,\n\tCOMMAND_SET_GANG_PLAYER_ATTITUDE,\n\tCOMMAND_SET_GANG_PED_MODELS,\n\tCOMMAND_SET_GANG_CAR_MODEL,\n\tCOMMAND_SET_GANG_WEAPONS,\n\tCOMMAND_SET_CHAR_OBJ_RUN_TO_AREA,\n\tCOMMAND_SET_CHAR_OBJ_RUN_TO_COORD,\n\tCOMMAND_IS_PLAYER_TOUCHING_OBJECT_ON_FOOT,\n\tCOMMAND_IS_CHAR_TOUCHING_OBJECT_ON_FOOT,\n\tCOMMAND_LOAD_SPECIAL_CHARACTER,\n\tCOMMAND_HAS_SPECIAL_CHARACTER_LOADED,\n\tCOMMAND_FLASH_CAR,\n\tCOMMAND_FLASH_CHAR,\n\tCOMMAND_FLASH_OBJECT,\n\tCOMMAND_IS_PLAYER_IN_REMOTE_MODE,\n\tCOMMAND_ARM_CAR_WITH_BOMB,\n\tCOMMAND_SET_CHAR_PERSONALITY,\n\tCOMMAND_SET_CUTSCENE_OFFSET,\n\tCOMMAND_SET_ANIM_GROUP_FOR_CHAR,\n\tCOMMAND_SET_ANIM_GROUP_FOR_PLAYER,\n\tCOMMAND_REQUEST_MODEL,\n\tCOMMAND_HAS_MODEL_LOADED,\n\tCOMMAND_MARK_MODEL_AS_NO_LONGER_NEEDED,\n\tCOMMAND_GRAB_PHONE,\n\tCOMMAND_SET_REPEATED_PHONE_MESSAGE,\n\tCOMMAND_SET_PHONE_MESSAGE,\n\tCOMMAND_HAS_PHONE_DISPLAYED_MESSAGE,\n\tCOMMAND_TURN_PHONE_OFF,\n\tCOMMAND_DRAW_CORONA,\n\tCOMMAND_DRAW_LIGHT,\n\tCOMMAND_STORE_WEATHER,\n\tCOMMAND_RESTORE_WEATHER,\n\tCOMMAND_STORE_CLOCK,\n\tCOMMAND_RESTORE_CLOCK,\n\tCOMMAND_RESTART_CRITICAL_MISSION,\n\tCOMMAND_IS_PLAYER_PLAYING,\n\tCOMMAND_SET_COLL_OBJ_NO_OBJ,\n\tCOMMAND_SET_COLL_OBJ_WAIT_ON_FOOT,\n\tCOMMAND_SET_COLL_OBJ_FLEE_ON_FOOT_TILL_SAFE,\n\tCOMMAND_SET_COLL_OBJ_GUARD_SPOT,\n\tCOMMAND_SET_COLL_OBJ_GUARD_AREA,\n\tCOMMAND_SET_COLL_OBJ_WAIT_IN_CAR,\n\tCOMMAND_SET_COLL_OBJ_KILL_CHAR_ON_FOOT,\n\tCOMMAND_SET_COLL_OBJ_KILL_PLAYER_ON_FOOT,\n\tCOMMAND_SET_COLL_OBJ_KILL_CHAR_ANY_MEANS,\n\tCOMMAND_SET_COLL_OBJ_KILL_PLAYER_ANY_MEANS,\n\tCOMMAND_SET_COLL_OBJ_FLEE_CHAR_ON_FOOT_TILL_SAFE,\n\tCOMMAND_SET_COLL_OBJ_FLEE_PLAYER_ON_FOOT_TILL_SAFE,\n\tCOMMAND_SET_COLL_OBJ_FLEE_CHAR_ON_FOOT_ALWAYS,\n\tCOMMAND_SET_COLL_OBJ_FLEE_PLAYER_ON_FOOT_ALWAYS,\n\tCOMMAND_SET_COLL_OBJ_GOTO_CHAR_ON_FOOT,\n\tCOMMAND_SET_COLL_OBJ_GOTO_PLAYER_ON_FOOT,\n\tCOMMAND_SET_COLL_OBJ_LEAVE_CAR,\n\tCOMMAND_SET_COLL_OBJ_ENTER_CAR_AS_PASSENGER,\n\tCOMMAND_SET_COLL_OBJ_ENTER_CAR_AS_DRIVER,\n\tCOMMAND_SET_COLL_OBJ_FOLLOW_CAR_IN_CAR,\n\tCOMMAND_SET_COLL_OBJ_FIRE_AT_OBJECT_FROM_VEHICLE,\n\tCOMMAND_SET_COLL_OBJ_DESTROY_OBJECT,\n\tCOMMAND_SET_COLL_OBJ_DESTROY_CAR,\n\tCOMMAND_SET_COLL_OBJ_GOTO_AREA_ON_FOOT,\n\tCOMMAND_SET_COLL_OBJ_GOTO_AREA_IN_CAR,\n\tCOMMAND_SET_COLL_OBJ_FOLLOW_CAR_ON_FOOT_WITH_OFFSET,\n\tCOMMAND_SET_COLL_OBJ_GUARD_ATTACK,\n\tCOMMAND_SET_COLL_OBJ_FOLLOW_ROUTE,\n\tCOMMAND_SET_COLL_OBJ_GOTO_COORD_ON_FOOT,\n\tCOMMAND_SET_COLL_OBJ_GOTO_COORD_IN_CAR,\n\tCOMMAND_SET_COLL_OBJ_RUN_TO_AREA,\n\tCOMMAND_SET_COLL_OBJ_RUN_TO_COORD,\n\tCOMMAND_ADD_PEDS_IN_AREA_TO_COLL,\n\tCOMMAND_ADD_PEDS_IN_VEHICLE_TO_COLL,\n\tCOMMAND_CLEAR_COLL,\n\tCOMMAND_IS_COLL_IN_CARS,\n\tCOMMAND_LOCATE_COLL_ANY_MEANS_2D,\n\tCOMMAND_LOCATE_COLL_ON_FOOT_2D,\n\tCOMMAND_LOCATE_COLL_IN_CAR_2D,\n\tCOMMAND_LOCATE_STOPPED_COLL_ANY_MEANS_2D,\n\tCOMMAND_LOCATE_STOPPED_COLL_ON_FOOT_2D,\n\tCOMMAND_LOCATE_STOPPED_COLL_IN_CAR_2D,\n\tCOMMAND_LOCATE_COLL_ANY_MEANS_CHAR_2D,\n\tCOMMAND_LOCATE_COLL_ON_FOOT_CHAR_2D,\n\tCOMMAND_LOCATE_COLL_IN_CAR_CHAR_2D,\n\tCOMMAND_LOCATE_COLL_ANY_MEANS_CAR_2D,\n\tCOMMAND_LOCATE_COLL_ON_FOOT_CAR_2D,\n\tCOMMAND_LOCATE_COLL_IN_CAR_CAR_2D,\n\tCOMMAND_LOCATE_COLL_ANY_MEANS_PLAYER_2D,\n\tCOMMAND_LOCATE_COLL_ON_FOOT_PLAYER_2D,\n\tCOMMAND_LOCATE_COLL_IN_CAR_PLAYER_2D,\n\tCOMMAND_IS_COLL_IN_AREA_2D,\n\tCOMMAND_IS_COLL_IN_AREA_ON_FOOT_2D,\n\tCOMMAND_IS_COLL_IN_AREA_IN_CAR_2D,\n\tCOMMAND_IS_COLL_STOPPED_IN_AREA_2D,\n\tCOMMAND_IS_COLL_STOPPED_IN_AREA_ON_FOOT_2D,\n\tCOMMAND_IS_COLL_STOPPED_IN_AREA_IN_CAR_2D,\n\tCOMMAND_GET_NUMBER_OF_PEDS_IN_COLL,\n\tCOMMAND_SET_CHAR_HEED_THREATS,\n\tCOMMAND_SET_PLAYER_HEED_THREATS,\n\tCOMMAND_GET_CONTROLLER_MODE,\n\tCOMMAND_SET_CAN_RESPRAY_CAR,\n\tCOMMAND_IS_TAXI,\n\tCOMMAND_UNLOAD_SPECIAL_CHARACTER,\n\tCOMMAND_RESET_NUM_OF_MODELS_KILLED_BY_PLAYER,\n\tCOMMAND_GET_NUM_OF_MODELS_KILLED_BY_PLAYER,\n\tCOMMAND_ACTIVATE_GARAGE,\n\tCOMMAND_SWITCH_TAXI_TIMER,\n\tCOMMAND_CREATE_OBJECT_NO_OFFSET,\n\tCOMMAND_IS_BOAT,\n\tCOMMAND_SET_CHAR_OBJ_GOTO_AREA_ANY_MEANS,\n\tCOMMAND_SET_COLL_OBJ_GOTO_AREA_ANY_MEANS,\n\tCOMMAND_IS_PLAYER_STOPPED,\n\tCOMMAND_IS_CHAR_STOPPED,\n\tCOMMAND_MESSAGE_WAIT,\n\tCOMMAND_ADD_PARTICLE_EFFECT,\n\tCOMMAND_SWITCH_WIDESCREEN,\n\tCOMMAND_ADD_SPRITE_BLIP_FOR_CAR,\n\tCOMMAND_ADD_SPRITE_BLIP_FOR_CHAR,\n\tCOMMAND_ADD_SPRITE_BLIP_FOR_OBJECT,\n\tCOMMAND_ADD_SPRITE_BLIP_FOR_CONTACT_POINT,\n\tCOMMAND_ADD_SPRITE_BLIP_FOR_COORD,\n\tCOMMAND_SET_CHAR_ONLY_DAMAGED_BY_PLAYER,\n\tCOMMAND_SET_CAR_ONLY_DAMAGED_BY_PLAYER,\n\tCOMMAND_SET_CHAR_PROOFS,\n\tCOMMAND_SET_CAR_PROOFS,\n\tCOMMAND_IS_PLAYER_IN_ANGLED_AREA_2D,\n\tCOMMAND_IS_PLAYER_IN_ANGLED_AREA_ON_FOOT_2D,\n\tCOMMAND_IS_PLAYER_IN_ANGLED_AREA_IN_CAR_2D,\n\tCOMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_2D,\n\tCOMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_ON_FOOT_2D,\n\tCOMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_IN_CAR_2D,\n\tCOMMAND_IS_PLAYER_IN_ANGLED_AREA_3D,\n\tCOMMAND_IS_PLAYER_IN_ANGLED_AREA_ON_FOOT_3D,\n\tCOMMAND_IS_PLAYER_IN_ANGLED_AREA_IN_CAR_3D,\n\tCOMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_3D,\n\tCOMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_ON_FOOT_3D,\n\tCOMMAND_IS_PLAYER_STOPPED_IN_ANGLED_AREA_IN_CAR_3D,\n\tCOMMAND_DEACTIVATE_GARAGE,\n\tCOMMAND_GET_NUMBER_OF_CARS_COLLECTED_BY_GARAGE,\n\tCOMMAND_HAS_CAR_BEEN_TAKEN_TO_GARAGE,\n\tCOMMAND_SET_SWAT_REQUIRED,\n\tCOMMAND_SET_FBI_REQUIRED,\n\tCOMMAND_SET_ARMY_REQUIRED,\n\tCOMMAND_IS_CAR_IN_WATER,\n\tCOMMAND_GET_CLOSEST_CHAR_NODE,\n\tCOMMAND_GET_CLOSEST_CAR_NODE,\n\tCOMMAND_CAR_GOTO_COORDINATES_ACCURATE,\n\tCOMMAND_START_PACMAN_RACE,\n\tCOMMAND_START_PACMAN_RECORD,\n\tCOMMAND_GET_NUMBER_OF_POWER_PILLS_EATEN,\n\tCOMMAND_CLEAR_PACMAN,\n\tCOMMAND_START_PACMAN_SCRAMBLE,\n\tCOMMAND_GET_NUMBER_OF_POWER_PILLS_CARRIED,\n\tCOMMAND_CLEAR_NUMBER_OF_POWER_PILLS_CARRIED,\n\tCOMMAND_IS_CAR_ON_SCREEN,\n\tCOMMAND_IS_CHAR_ON_SCREEN,\n\tCOMMAND_IS_OBJECT_ON_SCREEN,\n\tCOMMAND_GOSUB_FILE,\n\tCOMMAND_GET_GROUND_Z_FOR_3D_COORD,\n\tCOMMAND_START_SCRIPT_FIRE,\n\tCOMMAND_IS_SCRIPT_FIRE_EXTINGUISHED,\n\tCOMMAND_REMOVE_SCRIPT_FIRE,\n\tCOMMAND_SET_COMEDY_CONTROLS,\n\tCOMMAND_BOAT_GOTO_COORDS,\n\tCOMMAND_BOAT_STOP,\n\tCOMMAND_IS_PLAYER_SHOOTING_IN_AREA,\n\tCOMMAND_IS_CHAR_SHOOTING_IN_AREA,\n\tCOMMAND_IS_CURRENT_PLAYER_WEAPON,\n\tCOMMAND_IS_CURRENT_CHAR_WEAPON,\n\tCOMMAND_CLEAR_NUMBER_OF_POWER_PILLS_EATEN,\n\tCOMMAND_ADD_POWER_PILL,\n\tCOMMAND_SET_BOAT_CRUISE_SPEED,\n\tCOMMAND_GET_RANDOM_CHAR_IN_AREA,\n\tCOMMAND_GET_RANDOM_CHAR_IN_ZONE,\n\tCOMMAND_IS_PLAYER_IN_TAXI,\n\tCOMMAND_IS_PLAYER_SHOOTING,\n\tCOMMAND_IS_CHAR_SHOOTING,\n\tCOMMAND_CREATE_MONEY_PICKUP,\n\tCOMMAND_SET_CHAR_ACCURACY,\n\tCOMMAND_GET_CAR_SPEED,\n\tCOMMAND_LOAD_CUTSCENE,\n\tCOMMAND_CREATE_CUTSCENE_OBJECT,\n\tCOMMAND_SET_CUTSCENE_ANIM,\n\tCOMMAND_START_CUTSCENE,\n\tCOMMAND_GET_CUTSCENE_TIME,\n\tCOMMAND_HAS_CUTSCENE_FINISHED,\n\tCOMMAND_CLEAR_CUTSCENE,\n\tCOMMAND_RESTORE_CAMERA_JUMPCUT,\n\tCOMMAND_CREATE_COLLECTABLE1,\n\tCOMMAND_SET_COLLECTABLE1_TOTAL,\n\tCOMMAND_IS_PROJECTILE_IN_AREA,\n\tCOMMAND_DESTROY_PROJECTILES_IN_AREA,\n\tCOMMAND_DROP_MINE,\n\tCOMMAND_DROP_NAUTICAL_MINE,\n\tCOMMAND_IS_CHAR_MODEL,\n\tCOMMAND_LOAD_SPECIAL_MODEL,\n\tCOMMAND_CREATE_CUTSCENE_HEAD,\n\tCOMMAND_SET_CUTSCENE_HEAD_ANIM,\n\tCOMMAND_SIN,\n\tCOMMAND_COS,\n\tCOMMAND_GET_CAR_FORWARD_X,\n\tCOMMAND_GET_CAR_FORWARD_Y,\n\tCOMMAND_CHANGE_GARAGE_TYPE,\n\tCOMMAND_ACTIVATE_CRUSHER_CRANE,\n\tCOMMAND_PRINT_WITH_2_NUMBERS,\n\tCOMMAND_PRINT_WITH_2_NUMBERS_NOW,\n\tCOMMAND_PRINT_WITH_2_NUMBERS_SOON,\n\tCOMMAND_PRINT_WITH_3_NUMBERS,\n\tCOMMAND_PRINT_WITH_3_NUMBERS_NOW,\n\tCOMMAND_PRINT_WITH_3_NUMBERS_SOON,\n\tCOMMAND_PRINT_WITH_4_NUMBERS,\n\tCOMMAND_PRINT_WITH_4_NUMBERS_NOW,\n\tCOMMAND_PRINT_WITH_4_NUMBERS_SOON,\n\tCOMMAND_PRINT_WITH_5_NUMBERS,\n\tCOMMAND_PRINT_WITH_5_NUMBERS_NOW,\n\tCOMMAND_PRINT_WITH_5_NUMBERS_SOON,\n\tCOMMAND_PRINT_WITH_6_NUMBERS,\n\tCOMMAND_PRINT_WITH_6_NUMBERS_NOW,\n\tCOMMAND_PRINT_WITH_6_NUMBERS_SOON,\n\tCOMMAND_SET_CHAR_OBJ_FOLLOW_CHAR_IN_FORMATION,\n\tCOMMAND_PLAYER_MADE_PROGRESS,\n\tCOMMAND_SET_PROGRESS_TOTAL,\n\tCOMMAND_REGISTER_JUMP_DISTANCE,\n\tCOMMAND_REGISTER_JUMP_HEIGHT,\n\tCOMMAND_REGISTER_JUMP_FLIPS,\n\tCOMMAND_REGISTER_JUMP_SPINS,\n\tCOMMAND_REGISTER_JUMP_STUNT,\n\tCOMMAND_REGISTER_UNIQUE_JUMP_FOUND,\n\tCOMMAND_SET_UNIQUE_JUMPS_TOTAL,\n\tCOMMAND_REGISTER_PASSENGER_DROPPED_OFF_TAXI,\n\tCOMMAND_REGISTER_MONEY_MADE_TAXI,\n\tCOMMAND_REGISTER_MISSION_GIVEN,\n\tCOMMAND_REGISTER_MISSION_PASSED,\n\tCOMMAND_SET_CHAR_RUNNING,\n\tCOMMAND_REMOVE_ALL_SCRIPT_FIRES,\n\tCOMMAND_IS_FIRST_CAR_COLOUR,\n\tCOMMAND_IS_SECOND_CAR_COLOUR,\n\tCOMMAND_HAS_CHAR_BEEN_DAMAGED_BY_WEAPON,\n\tCOMMAND_HAS_CAR_BEEN_DAMAGED_BY_WEAPON,\n\tCOMMAND_IS_CHAR_IN_CHARS_GROUP,\n\tCOMMAND_IS_CHAR_IN_PLAYERS_GROUP,\n\tCOMMAND_EXPLODE_CHAR_HEAD,\n\tCOMMAND_EXPLODE_PLAYER_HEAD,\n\tCOMMAND_ANCHOR_BOAT,\n\tCOMMAND_SET_ZONE_GROUP,\n\tCOMMAND_START_CAR_FIRE,\n\tCOMMAND_START_CHAR_FIRE,\n\tCOMMAND_GET_RANDOM_CAR_OF_TYPE_IN_AREA,\n\tCOMMAND_GET_RANDOM_CAR_OF_TYPE_IN_ZONE,\n\tCOMMAND_HAS_RESPRAY_HAPPENED,\n\tCOMMAND_SET_CAMERA_ZOOM,\n\tCOMMAND_CREATE_PICKUP_WITH_AMMO,\n\tCOMMAND_SET_CAR_RAM_CAR,\n\tCOMMAND_SET_CAR_BLOCK_CAR,\n\tCOMMAND_SET_CHAR_OBJ_CATCH_TRAIN,\n\tCOMMAND_SET_COLL_OBJ_CATCH_TRAIN,\n\tCOMMAND_SET_PLAYER_NEVER_GETS_TIRED,\n\tCOMMAND_SET_PLAYER_FAST_RELOAD,\n\tCOMMAND_SET_CHAR_BLEEDING,\n\tCOMMAND_SET_CAR_FUNNY_SUSPENSION,\n\tCOMMAND_SET_CAR_BIG_WHEELS,\n\tCOMMAND_SET_FREE_RESPRAYS,\n\tCOMMAND_SET_PLAYER_VISIBLE,\n\tCOMMAND_SET_CHAR_VISIBLE,\n\tCOMMAND_SET_CAR_VISIBLE,\n\tCOMMAND_IS_AREA_OCCUPIED,\n\tCOMMAND_START_DRUG_RUN,\n\tCOMMAND_HAS_DRUG_RUN_BEEN_COMPLETED,\n\tCOMMAND_HAS_DRUG_PLANE_BEEN_SHOT_DOWN,\n\tCOMMAND_SAVE_PLAYER_FROM_FIRES,\n\tCOMMAND_DISPLAY_TEXT,\n\tCOMMAND_SET_TEXT_SCALE,\n\tCOMMAND_SET_TEXT_COLOUR,\n\tCOMMAND_SET_TEXT_JUSTIFY,\n\tCOMMAND_SET_TEXT_CENTRE,\n\tCOMMAND_SET_TEXT_WRAPX,\n\tCOMMAND_SET_TEXT_CENTRE_SIZE,\n\tCOMMAND_SET_TEXT_BACKGROUND,\n\tCOMMAND_SET_TEXT_BACKGROUND_COLOUR,\n\tCOMMAND_SET_TEXT_BACKGROUND_ONLY_TEXT,\n\tCOMMAND_SET_TEXT_PROPORTIONAL,\n\tCOMMAND_SET_TEXT_FONT,\n\tCOMMAND_INDUSTRIAL_PASSED,\n\tCOMMAND_COMMERCIAL_PASSED,\n\tCOMMAND_SUBURBAN_PASSED,\n\tCOMMAND_ROTATE_OBJECT,\n\tCOMMAND_SLIDE_OBJECT,\n\tCOMMAND_REMOVE_CHAR_ELEGANTLY,\n\tCOMMAND_SET_CHAR_STAY_IN_SAME_PLACE,\n\tCOMMAND_IS_NASTY_GAME,\n\tCOMMAND_UNDRESS_CHAR,\n\tCOMMAND_DRESS_CHAR,\n\tCOMMAND_START_CHASE_SCENE,\n\tCOMMAND_STOP_CHASE_SCENE,\n\tCOMMAND_IS_EXPLOSION_IN_AREA,\n\tCOMMAND_IS_EXPLOSION_IN_ZONE,\n\tCOMMAND_START_DRUG_DROP_OFF,\n\tCOMMAND_HAS_DROP_OFF_PLANE_BEEN_SHOT_DOWN,\n\tCOMMAND_FIND_DROP_OFF_PLANE_COORDINATES,\n\tCOMMAND_CREATE_FLOATING_PACKAGE,\n\tCOMMAND_PLACE_OBJECT_RELATIVE_TO_CAR,\n\tCOMMAND_MAKE_OBJECT_TARGETTABLE,\n\tCOMMAND_ADD_ARMOUR_TO_PLAYER,\n\tCOMMAND_ADD_ARMOUR_TO_CHAR,\n\tCOMMAND_OPEN_GARAGE,\n\tCOMMAND_CLOSE_GARAGE,\n\tCOMMAND_WARP_CHAR_FROM_CAR_TO_COORD,\n\tCOMMAND_SET_VISIBILITY_OF_CLOSEST_OBJECT_OF_TYPE,\n\tCOMMAND_HAS_CHAR_SPOTTED_CHAR,\n\tCOMMAND_SET_CHAR_OBJ_HAIL_TAXI,\n\tCOMMAND_HAS_OBJECT_BEEN_DAMAGED,\n\tCOMMAND_START_KILL_FRENZY_HEADSHOT,\n\tCOMMAND_ACTIVATE_MILITARY_CRANE,\n\tCOMMAND_WARP_PLAYER_INTO_CAR,\n\tCOMMAND_WARP_CHAR_INTO_CAR,\n\tCOMMAND_SWITCH_CAR_RADIO,\n\tCOMMAND_SET_AUDIO_STREAM,\n\tCOMMAND_PRINT_WITH_2_NUMBERS_BIG,\n\tCOMMAND_PRINT_WITH_3_NUMBERS_BIG,\n\tCOMMAND_PRINT_WITH_4_NUMBERS_BIG,\n\tCOMMAND_PRINT_WITH_5_NUMBERS_BIG,\n\tCOMMAND_PRINT_WITH_6_NUMBERS_BIG,\n\tCOMMAND_SET_CHAR_WAIT_STATE,\n\tCOMMAND_SET_CAMERA_BEHIND_PLAYER,\n\tCOMMAND_SET_MOTION_BLUR,\n\tCOMMAND_PRINT_STRING_IN_STRING,\n\tCOMMAND_CREATE_RANDOM_CHAR,\n\tCOMMAND_SET_CHAR_OBJ_STEAL_ANY_CAR,\n\tCOMMAND_SET_2_REPEATED_PHONE_MESSAGES,\n\tCOMMAND_SET_2_PHONE_MESSAGES,\n\tCOMMAND_SET_3_REPEATED_PHONE_MESSAGES,\n\tCOMMAND_SET_3_PHONE_MESSAGES,\n\tCOMMAND_SET_4_REPEATED_PHONE_MESSAGES,\n\tCOMMAND_SET_4_PHONE_MESSAGES,\n\tCOMMAND_IS_SNIPER_BULLET_IN_AREA,\n\tCOMMAND_GIVE_PLAYER_DETONATOR,\n\tCOMMAND_SET_COLL_OBJ_STEAL_ANY_CAR,\n\tCOMMAND_SET_OBJECT_VELOCITY,\n\tCOMMAND_SET_OBJECT_COLLISION,\n\tCOMMAND_IS_ICECREAM_JINGLE_ON,\n\tCOMMAND_PRINT_STRING_IN_STRING_NOW,\n\tCOMMAND_PRINT_STRING_IN_STRING_SOON,\n\tCOMMAND_SET_5_REPEATED_PHONE_MESSAGES,\n\tCOMMAND_SET_5_PHONE_MESSAGES,\n\tCOMMAND_SET_6_REPEATED_PHONE_MESSAGES,\n\tCOMMAND_SET_6_PHONE_MESSAGES,\n\tCOMMAND_IS_POINT_OBSCURED_BY_A_MISSION_ENTITY,\n\tCOMMAND_LOAD_ALL_MODELS_NOW,\n\tCOMMAND_ADD_TO_OBJECT_VELOCITY,\n\tCOMMAND_DRAW_SPRITE,\n\tCOMMAND_DRAW_RECT,\n\tCOMMAND_LOAD_SPRITE,\n\tCOMMAND_LOAD_TEXTURE_DICTIONARY,\n\tCOMMAND_REMOVE_TEXTURE_DICTIONARY,\n\tCOMMAND_SET_OBJECT_DYNAMIC,\n\tCOMMAND_SET_CHAR_ANIM_SPEED,\n\tCOMMAND_PLAY_MISSION_PASSED_TUNE,\n\tCOMMAND_CLEAR_AREA,\n\tCOMMAND_FREEZE_ONSCREEN_TIMER,\n\tCOMMAND_SWITCH_CAR_SIREN,\n\tCOMMAND_SWITCH_PED_ROADS_ON_ANGLED,\n\tCOMMAND_SWITCH_PED_ROADS_OFF_ANGLED,\n\tCOMMAND_SWITCH_ROADS_ON_ANGLED,\n\tCOMMAND_SWITCH_ROADS_OFF_ANGLED,\n\tCOMMAND_SET_CAR_WATERTIGHT,\n\tCOMMAND_ADD_MOVING_PARTICLE_EFFECT,\n\tCOMMAND_SET_CHAR_CANT_BE_DRAGGED_OUT,\n\tCOMMAND_TURN_CAR_TO_FACE_COORD,\n\tCOMMAND_IS_CRANE_LIFTING_CAR,\n\tCOMMAND_DRAW_SPHERE,\n\tCOMMAND_SET_CAR_STATUS,\n\tCOMMAND_IS_CHAR_MALE,\n\tCOMMAND_SCRIPT_NAME,\n\tCOMMAND_CHANGE_GARAGE_TYPE_WITH_CAR_MODEL,\n\tCOMMAND_FIND_DRUG_PLANE_COORDINATES,\n\tCOMMAND_SAVE_INT_TO_DEBUG_FILE,\n\tCOMMAND_SAVE_FLOAT_TO_DEBUG_FILE,\n\tCOMMAND_SAVE_NEWLINE_TO_DEBUG_FILE,\n\tCOMMAND_POLICE_RADIO_MESSAGE,\n\tCOMMAND_SET_CAR_STRONG,\n\tCOMMAND_REMOVE_ROUTE,\n\tCOMMAND_SWITCH_RUBBISH,\n\tCOMMAND_REMOVE_PARTICLE_EFFECTS_IN_AREA,\n\tCOMMAND_SWITCH_STREAMING,\n\tCOMMAND_IS_GARAGE_OPEN,\n\tCOMMAND_IS_GARAGE_CLOSED,\n\tCOMMAND_START_CATALINA_HELI,\n\tCOMMAND_CATALINA_HELI_TAKE_OFF,\n\tCOMMAND_REMOVE_CATALINA_HELI,\n\tCOMMAND_HAS_CATALINA_HELI_BEEN_SHOT_DOWN,\n\tCOMMAND_SWAP_NEAREST_BUILDING_MODEL,\n\tCOMMAND_SWITCH_WORLD_PROCESSING,\n\tCOMMAND_REMOVE_ALL_PLAYER_WEAPONS,\n\tCOMMAND_GRAB_CATALINA_HELI,\n\tCOMMAND_CLEAR_AREA_OF_CARS,\n\tCOMMAND_SET_ROTATING_GARAGE_DOOR,\n\tCOMMAND_ADD_SPHERE,\n\tCOMMAND_REMOVE_SPHERE,\n\tCOMMAND_CATALINA_HELI_FLY_AWAY,\n\tCOMMAND_SET_EVERYONE_IGNORE_PLAYER,\n\tCOMMAND_STORE_CAR_CHAR_IS_IN_NO_SAVE,\n\tCOMMAND_STORE_CAR_PLAYER_IS_IN_NO_SAVE,\n\tCOMMAND_IS_PHONE_DISPLAYING_MESSAGE,\n\tCOMMAND_DISPLAY_ONSCREEN_TIMER_WITH_STRING,\n\tCOMMAND_DISPLAY_ONSCREEN_COUNTER_WITH_STRING,\n\tCOMMAND_CREATE_RANDOM_CAR_FOR_CAR_PARK,\n\tCOMMAND_IS_COLLISION_IN_MEMORY,\n\tCOMMAND_SET_WANTED_MULTIPLIER,\n\tCOMMAND_SET_CAMERA_IN_FRONT_OF_PLAYER,\n\tCOMMAND_IS_CAR_VISIBLY_DAMAGED,\n\tCOMMAND_DOES_OBJECT_EXIST,\n\tCOMMAND_LOAD_SCENE,\n\tCOMMAND_ADD_STUCK_CAR_CHECK,\n\tCOMMAND_REMOVE_STUCK_CAR_CHECK,\n\tCOMMAND_IS_CAR_STUCK,\n\tCOMMAND_LOAD_MISSION_AUDIO,\n\tCOMMAND_HAS_MISSION_AUDIO_LOADED,\n\tCOMMAND_PLAY_MISSION_AUDIO,\n\tCOMMAND_HAS_MISSION_AUDIO_FINISHED,\n\tCOMMAND_GET_CLOSEST_CAR_NODE_WITH_HEADING,\n\tCOMMAND_HAS_IMPORT_GARAGE_SLOT_BEEN_FILLED,\n\tCOMMAND_CLEAR_THIS_PRINT,\n\tCOMMAND_CLEAR_THIS_BIG_PRINT,\n\tCOMMAND_SET_MISSION_AUDIO_POSITION,\n\tCOMMAND_ACTIVATE_SAVE_MENU,\n\tCOMMAND_HAS_SAVE_GAME_FINISHED,\n\tCOMMAND_NO_SPECIAL_CAMERA_FOR_THIS_GARAGE,\n\tCOMMAND_ADD_BLIP_FOR_PICKUP_OLD,\n\tCOMMAND_ADD_BLIP_FOR_PICKUP,\n\tCOMMAND_ADD_SPRITE_BLIP_FOR_PICKUP,\n\tCOMMAND_SET_PED_DENSITY_MULTIPLIER,\n\tCOMMAND_FORCE_RANDOM_PED_TYPE,\n\tCOMMAND_SET_TEXT_DRAW_BEFORE_FADE,\n\tCOMMAND_GET_COLLECTABLE1S_COLLECTED,\n\tCOMMAND_SET_CHAR_OBJ_LEAVE_ANY_CAR,\n\tCOMMAND_SET_SPRITES_DRAW_BEFORE_FADE,\n\tCOMMAND_SET_TEXT_RIGHT_JUSTIFY,\n\tCOMMAND_PRINT_HELP,\n\tCOMMAND_CLEAR_HELP,\n\tCOMMAND_FLASH_HUD_OBJECT,\n\tCOMMAND_FLASH_RADAR_BLIP,\n\tCOMMAND_IS_CHAR_IN_CONTROL,\n\tCOMMAND_SET_GENERATE_CARS_AROUND_CAMERA,\n\tCOMMAND_CLEAR_SMALL_PRINTS,\n\tCOMMAND_HAS_MILITARY_CRANE_COLLECTED_ALL_CARS,\n\tCOMMAND_SET_UPSIDEDOWN_CAR_NOT_DAMAGED,\n\tCOMMAND_CAN_PLAYER_START_MISSION,\n\tCOMMAND_MAKE_PLAYER_SAFE_FOR_CUTSCENE,\n\tCOMMAND_USE_TEXT_COMMANDS,\n\tCOMMAND_SET_THREAT_FOR_PED_TYPE,\n\tCOMMAND_CLEAR_THREAT_FOR_PED_TYPE,\n\tCOMMAND_GET_CAR_COLOURS,\n\tCOMMAND_SET_ALL_CARS_CAN_BE_DAMAGED,\n\tCOMMAND_SET_CAR_CAN_BE_DAMAGED,\n\tCOMMAND_MAKE_PLAYER_UNSAFE,\n\tCOMMAND_LOAD_COLLISION,\n\tCOMMAND_GET_BODY_CAST_HEALTH,\n\tCOMMAND_SET_CHARS_CHATTING,\n\tCOMMAND_MAKE_PLAYER_SAFE,\n\tCOMMAND_SET_CAR_STAYS_IN_CURRENT_LEVEL,\n\tCOMMAND_SET_CHAR_STAYS_IN_CURRENT_LEVEL,\n\tCOMMAND_SET_DRUNK_INPUT_DELAY,\n\tCOMMAND_SET_CHAR_MONEY,\n\tCOMMAND_INCREASE_CHAR_MONEY,\n\tCOMMAND_GET_OFFSET_FROM_OBJECT_IN_WORLD_COORDS,\n\tCOMMAND_REGISTER_LIFE_SAVED,\n\tCOMMAND_REGISTER_CRIMINAL_CAUGHT,\n\tCOMMAND_REGISTER_AMBULANCE_LEVEL,\n\tCOMMAND_REGISTER_FIRE_EXTINGUISHED,\n\tCOMMAND_TURN_PHONE_ON,\n\tCOMMAND_REGISTER_LONGEST_DODO_FLIGHT,\n\tCOMMAND_GET_OFFSET_FROM_CAR_IN_WORLD_COORDS,\n\tCOMMAND_SET_TOTAL_NUMBER_OF_KILL_FRENZIES,\n\tCOMMAND_BLOW_UP_RC_BUGGY,\n\tCOMMAND_REMOVE_CAR_FROM_CHASE,\n\tCOMMAND_IS_FRENCH_GAME,\n\tCOMMAND_IS_GERMAN_GAME,\n\tCOMMAND_CLEAR_MISSION_AUDIO,\n\tCOMMAND_SET_FADE_IN_AFTER_NEXT_ARREST,\n\tCOMMAND_SET_FADE_IN_AFTER_NEXT_DEATH,\n\tCOMMAND_SET_GANG_PED_MODEL_PREFERENCE,\n\tCOMMAND_SET_CHAR_USE_PEDNODE_SEEK,\n\tCOMMAND_SWITCH_VEHICLE_WEAPONS,\n\tCOMMAND_SET_GET_OUT_OF_JAIL_FREE,\n\tCOMMAND_SET_FREE_HEALTH_CARE,\n\tCOMMAND_IS_CAR_DOOR_CLOSED,\n\tCOMMAND_LOAD_AND_LAUNCH_MISSION,\n\tCOMMAND_LOAD_AND_LAUNCH_MISSION_INTERNAL,\n\tCOMMAND_SET_OBJECT_DRAW_LAST,\n\tCOMMAND_GET_AMMO_IN_PLAYER_WEAPON,\n\tCOMMAND_GET_AMMO_IN_CHAR_WEAPON,\n\tCOMMAND_REGISTER_KILL_FRENZY_PASSED,\n\tCOMMAND_SET_CHAR_SAY,\n\tCOMMAND_SET_NEAR_CLIP,\n\tCOMMAND_SET_RADIO_CHANNEL,\n\tCOMMAND_OVERRIDE_HOSPITAL_LEVEL,\n\tCOMMAND_OVERRIDE_POLICE_STATION_LEVEL,\n\tCOMMAND_FORCE_RAIN,\n\tCOMMAND_DOES_GARAGE_CONTAIN_CAR,\n\tCOMMAND_SET_CAR_TRACTION,\n\tCOMMAND_ARE_MEASUREMENTS_IN_METRES,\n\tCOMMAND_CONVERT_METRES_TO_FEET,\n\tCOMMAND_MARK_ROADS_BETWEEN_LEVELS,\n\tCOMMAND_MARK_PED_ROADS_BETWEEN_LEVELS,\n\tCOMMAND_SET_CAR_AVOID_LEVEL_TRANSITIONS,\n\tCOMMAND_SET_CHAR_AVOID_LEVEL_TRANSITIONS,\n\tCOMMAND_IS_THREAT_FOR_PED_TYPE,\n\tCOMMAND_CLEAR_AREA_OF_CHARS,\n\tCOMMAND_SET_TOTAL_NUMBER_OF_MISSIONS,\n\tCOMMAND_CONVERT_METRES_TO_FEET_INT,\n\tCOMMAND_REGISTER_FASTEST_TIME,\n\tCOMMAND_REGISTER_HIGHEST_SCORE,\n\tCOMMAND_WARP_CHAR_INTO_CAR_AS_PASSENGER,\n\tCOMMAND_IS_CAR_PASSENGER_SEAT_FREE,\n\tCOMMAND_GET_CHAR_IN_CAR_PASSENGER_SEAT,\n\tCOMMAND_SET_CHAR_IS_CHRIS_CRIMINAL,\n\tCOMMAND_START_CREDITS,\n\tCOMMAND_STOP_CREDITS,\n\tCOMMAND_ARE_CREDITS_FINISHED,\n\tCOMMAND_CREATE_SINGLE_PARTICLE,\n\tCOMMAND_SET_CHAR_IGNORE_LEVEL_TRANSITIONS,\n\tCOMMAND_GET_CHASE_CAR,\n\tCOMMAND_START_BOAT_FOAM_ANIMATION,\n\tCOMMAND_UPDATE_BOAT_FOAM_ANIMATION,\n\tCOMMAND_SET_MUSIC_DOES_FADE,\n\tCOMMAND_SET_INTRO_IS_PLAYING,\n\tCOMMAND_SET_PLAYER_HOOKER,\n\tCOMMAND_PLAY_END_OF_GAME_TUNE,\n\tCOMMAND_STOP_END_OF_GAME_TUNE,\n\tCOMMAND_GET_CAR_MODEL,\n\tCOMMAND_IS_PLAYER_SITTING_IN_CAR,\n\tCOMMAND_IS_PLAYER_SITTING_IN_ANY_CAR,\n\tCOMMAND_SET_SCRIPT_FIRE_AUDIO,\n\tCOMMAND_ARE_ANY_CAR_CHEATS_ACTIVATED,\n\tCOMMAND_SET_CHAR_SUFFERS_CRITICAL_HITS,\n\tCOMMAND_IS_PLAYER_LIFTING_A_PHONE,\n\tCOMMAND_IS_CHAR_SITTING_IN_CAR,\n\tCOMMAND_IS_CHAR_SITTING_IN_ANY_CAR,\n\tCOMMAND_IS_PLAYER_ON_FOOT,\n\tCOMMAND_IS_CHAR_ON_FOOT,\n\tCOMMAND_LOAD_COLLISION_WITH_SCREEN,\n\tCOMMAND_LOAD_SPLASH_SCREEN,\n\tCOMMAND_SET_CAR_IGNORE_LEVEL_TRANSITIONS,\n\tCOMMAND_MAKE_CRAIGS_CAR_A_BIT_STRONGER,\n\tCOMMAND_SET_JAMES_CAR_ON_PATH_TO_PLAYER,\n\tCOMMAND_LOAD_END_OF_GAME_TUNE,\n\tCOMMAND_ENABLE_PLAYER_CONTROL_CAMERA,\n\tCOMMAND_SET_OBJECT_ROTATION,\n\tCOMMAND_GET_DEBUG_CAMERA_COORDINATES,\n\tCOMMAND_GET_DEBUG_CAMERA_FRONT_VECTOR,\n\tCOMMAND_IS_PLAYER_TARGETTING_ANY_CHAR,\n\tCOMMAND_IS_PLAYER_TARGETTING_CHAR,\n\tCOMMAND_IS_PLAYER_TARGETTING_OBJECT,\n\tCOMMAND_TERMINATE_ALL_SCRIPTS_WITH_THIS_NAME,\n\tCOMMAND_DISPLAY_TEXT_WITH_NUMBER,\n\tCOMMAND_DISPLAY_TEXT_WITH_2_NUMBERS,\n\tCOMMAND_FAIL_CURRENT_MISSION,\n\tCOMMAND_GET_CLOSEST_OBJECT_OF_TYPE,\n\tCOMMAND_PLACE_OBJECT_RELATIVE_TO_OBJECT,\n\tCOMMAND_SET_ALL_OCCUPANTS_OF_CAR_LEAVE_CAR,\n\tCOMMAND_SET_INTERPOLATION_PARAMETERS,\n\tCOMMAND_GET_CLOSEST_CAR_NODE_WITH_HEADING_TOWARDS_POINT,\n\tCOMMAND_GET_CLOSEST_CAR_NODE_WITH_HEADING_AWAY_POINT,\n\tCOMMAND_GET_DEBUG_CAMERA_POINT_AT,\n\tCOMMAND_ATTACH_CHAR_TO_CAR,\n\tCOMMAND_DETACH_CHAR_FROM_CAR,\n\tCOMMAND_SET_CAR_CHANGE_LANE,\n\tCOMMAND_CLEAR_CHAR_LAST_WEAPON_DAMAGE,\n\tCOMMAND_CLEAR_CAR_LAST_WEAPON_DAMAGE,\n\tCOMMAND_GET_RANDOM_COP_IN_AREA,\n\tCOMMAND_GET_RANDOM_COP_IN_ZONE,\n\tCOMMAND_SET_CHAR_OBJ_FLEE_CAR,\n\tCOMMAND_GET_DRIVER_OF_CAR,\n\tCOMMAND_GET_NUMBER_OF_FOLLOWERS,\n\tCOMMAND_GIVE_REMOTE_CONTROLLED_MODEL_TO_PLAYER,\n\tCOMMAND_GET_CURRENT_PLAYER_WEAPON,\n\tCOMMAND_GET_CURRENT_CHAR_WEAPON,\n\tCOMMAND_LOCATE_CHAR_ANY_MEANS_OBJECT_2D,\n\tCOMMAND_LOCATE_CHAR_ON_FOOT_OBJECT_2D,\n\tCOMMAND_LOCATE_CHAR_IN_CAR_OBJECT_2D,\n\tCOMMAND_LOCATE_CHAR_ANY_MEANS_OBJECT_3D,\n\tCOMMAND_LOCATE_CHAR_ON_FOOT_OBJECT_3D,\n\tCOMMAND_LOCATE_CHAR_IN_CAR_OBJECT_3D,\n\tCOMMAND_SET_CAR_TEMP_ACTION,\n\tCOMMAND_SET_CAR_HANDBRAKE_TURN_RIGHT,\n\tCOMMAND_SET_CAR_HANDBRAKE_STOP,\n\tCOMMAND_IS_CHAR_ON_ANY_BIKE,\n\tCOMMAND_LOCATE_SNIPER_BULLET_2D,\n\tCOMMAND_LOCATE_SNIPER_BULLET_3D,\n\tCOMMAND_GET_NUMBER_OF_SEATS_IN_MODEL,\n\tCOMMAND_IS_PLAYER_ON_ANY_BIKE,\n\tCOMMAND_IS_CHAR_LYING_DOWN,\n\tCOMMAND_CAN_CHAR_SEE_DEAD_CHAR,\n\tCOMMAND_SET_ENTER_CAR_RANGE_MULTIPLIER,\n\tCOMMAND_SET_THREAT_REACTION_RANGE_MULTIPLIER,\n\tCOMMAND_SET_CHAR_CEASE_ATTACK_TIMER,\n\tCOMMAND_GET_REMOTE_CONTROLLED_CAR,\n\tCOMMAND_IS_PC_VERSION,\n\tCOMMAND_REPLAY,\n\tCOMMAND_IS_REPLAY_PLAYING,\n\tCOMMAND_IS_MODEL_AVAILABLE,\n\tCOMMAND_SHUT_CHAR_UP,\n\tCOMMAND_SET_ENABLE_RC_DETONATE,\n\tCOMMAND_SET_CAR_RANDOM_ROUTE_SEED,\n\tCOMMAND_IS_ANY_PICKUP_AT_COORDS,\n\tCOMMAND_GET_FIRST_PICKUP_COORDS,\n\tCOMMAND_GET_NEXT_PICKUP_COORDS,\n\tCOMMAND_REMOVE_ALL_CHAR_WEAPONS,\n\tCOMMAND_HAS_PLAYER_GOT_WEAPON,\n\tCOMMAND_HAS_CHAR_GOT_WEAPON,\n\tCOMMAND_IS_PLAYER_FACING_CHAR,\n\tCOMMAND_SET_TANK_DETONATE_CARS,\n\tCOMMAND_GET_POSITION_OF_ANALOGUE_STICKS,\n\tCOMMAND_IS_CAR_ON_FIRE,\n\tCOMMAND_IS_CAR_TYRE_BURST,\n\tCOMMAND_SET_CAR_DRIVE_STRAIGHT_AHEAD,\n\tCOMMAND_SET_CAR_WAIT,\n\tCOMMAND_IS_PLAYER_STANDING_ON_A_VEHICLE,\n\tCOMMAND_IS_PLAYER_FOOT_DOWN,\n\tCOMMAND_IS_CHAR_FOOT_DOWN,\n\tCOMMAND_INITIALISE_OBJECT_PATH,\n\tCOMMAND_START_OBJECT_ON_PATH,\n\tCOMMAND_SET_OBJECT_PATH_SPEED,\n\tCOMMAND_SET_OBJECT_PATH_POSITION,\n\tCOMMAND_GET_OBJECT_DISTANCE_ALONG_PATH,\n\tCOMMAND_CLEAR_OBJECT_PATH,\n\tCOMMAND_HELI_GOTO_COORDS,\n\tCOMMAND_IS_INT_VAR_EQUAL_TO_CONSTANT,\n\tCOMMAND_IS_INT_LVAR_EQUAL_TO_CONSTANT,\n\tCOMMAND_GET_DEAD_CHAR_PICKUP_COORDS,\n\tCOMMAND_CREATE_PROTECTION_PICKUP,\n\tCOMMAND_IS_CHAR_IN_ANY_BOAT,\n\tCOMMAND_IS_PLAYER_IN_ANY_BOAT,\n\tCOMMAND_IS_CHAR_IN_ANY_HELI,\n\tCOMMAND_IS_PLAYER_IN_ANY_HELI,\n\tCOMMAND_IS_CHAR_IN_ANY_PLANE,\n\tCOMMAND_IS_PLAYER_IN_ANY_PLANE,\n\tCOMMAND_IS_CHAR_IN_WATER,\n\tCOMMAND_SET_VAR_INT_TO_CONSTANT,\n\tCOMMAND_SET_LVAR_INT_TO_CONSTANT,\n\tCOMMAND_IS_INT_VAR_GREATER_THAN_CONSTANT,\n\tCOMMAND_IS_INT_LVAR_GREATER_THAN_CONSTANT,\n\tCOMMAND_IS_CONSTANT_GREATER_THAN_INT_VAR,\n\tCOMMAND_IS_CONSTANT_GREATER_THAN_INT_LVAR,\n\tCOMMAND_IS_INT_VAR_GREATER_OR_EQUAL_TO_CONSTANT,\n\tCOMMAND_IS_INT_LVAR_GREATER_OR_EQUAL_TO_CONSTANT,\n\tCOMMAND_IS_CONSTANT_GREATER_OR_EQUAL_TO_INT_VAR,\n\tCOMMAND_IS_CONSTANT_GREATER_OR_EQUAL_TO_INT_LVAR,\n\tCOMMAND_GET_CHAR_WEAPON_IN_SLOT,\n\tCOMMAND_GET_CLOSEST_STRAIGHT_ROAD,\n\tCOMMAND_SET_CAR_FORWARD_SPEED,\n\tCOMMAND_SET_AREA_VISIBLE,\n\tCOMMAND_SET_CUTSCENE_ANIM_TO_LOOP,\n\tCOMMAND_MARK_CAR_AS_CONVOY_CAR,\n\tCOMMAND_RESET_HAVOC_CAUSED_BY_PLAYER,\n\tCOMMAND_GET_HAVOC_CAUSED_BY_PLAYER,\n\tCOMMAND_CREATE_SCRIPT_ROADBLOCK,\n\tCOMMAND_CLEAR_ALL_SCRIPT_ROADBLOCKS,\n\tCOMMAND_SET_CHAR_OBJ_WALK_TO_CHAR,\n\tCOMMAND_IS_PICKUP_IN_ZONE,\n\tCOMMAND_GET_OFFSET_FROM_CHAR_IN_WORLD_COORDS,\n\tCOMMAND_HAS_CHAR_BEEN_PHOTOGRAPHED,\n\tCOMMAND_SET_CHAR_OBJ_AIM_GUN_AT_CHAR,\n\tCOMMAND_SWITCH_SECURITY_CAMERA,\n\tCOMMAND_IS_CHAR_IN_FLYING_VEHICLE,\n\tCOMMAND_IS_PLAYER_IN_FLYING_VEHICLE,\n\tCOMMAND_HAS_SONY_CD_BEEN_READ,\n\tCOMMAND_GET_NUMBER_OF_SONY_CDS_READ,\n\tCOMMAND_ADD_SHORT_RANGE_BLIP_FOR_COORD_OLD,\n\tCOMMAND_ADD_SHORT_RANGE_BLIP_FOR_COORD,\n\tCOMMAND_ADD_SHORT_RANGE_SPRITE_BLIP_FOR_COORD,\n\tCOMMAND_ADD_MONEY_SPENT_ON_CLOTHES,\n\tCOMMAND_SET_HELI_ORIENTATION,\n\tCOMMAND_CLEAR_HELI_ORIENTATION,\n\tCOMMAND_PLANE_GOTO_COORDS,\n\tCOMMAND_GET_NTH_CLOSEST_CAR_NODE,\n\tCOMMAND_GET_NTH_CLOSEST_CHAR_NODE,\n\tCOMMAND_DRAW_WEAPONSHOP_CORONA,\n\tCOMMAND_SET_ENABLE_RC_DETONATE_ON_CONTACT,\n\tCOMMAND_FREEZE_CHAR_POSITION,\n\tCOMMAND_SET_CHAR_DROWNS_IN_WATER,\n\tCOMMAND_SET_OBJECT_RECORDS_COLLISIONS,\n\tCOMMAND_HAS_OBJECT_COLLIDED_WITH_ANYTHING,\n\tCOMMAND_REMOVE_RC_BUGGY,\n\tCOMMAND_HAS_PHOTOGRAPH_BEEN_TAKEN,\n\tCOMMAND_GET_CHAR_ARMOUR,\n\tCOMMAND_SET_CHAR_ARMOUR,\n\tCOMMAND_SET_HELI_STABILISER,\n\tCOMMAND_SET_CAR_STRAIGHT_LINE_DISTANCE,\n\tCOMMAND_POP_CAR_BOOT,\n\tCOMMAND_SHUT_PLAYER_UP,\n\tCOMMAND_SET_PLAYER_MOOD,\n\tCOMMAND_REQUEST_COLLISION,\n\tCOMMAND_LOCATE_OBJECT_2D,\n\tCOMMAND_LOCATE_OBJECT_3D,\n\tCOMMAND_IS_OBJECT_IN_WATER,\n\tCOMMAND_SET_CHAR_OBJ_STEAL_ANY_CAR_EVEN_MISSION_CAR,\n\tCOMMAND_IS_OBJECT_IN_AREA_2D,\n\tCOMMAND_IS_OBJECT_IN_AREA_3D,\n\tCOMMAND_SET_CHAR_CROUCH,\n\tCOMMAND_SET_ZONE_CIVILIAN_CAR_INFO,\n\tCOMMAND_REQUEST_ANIMATION,\n\tCOMMAND_HAS_ANIMATION_LOADED,\n\tCOMMAND_REMOVE_ANIMATION,\n\tCOMMAND_IS_CHAR_WAITING_FOR_WORLD_COLLISION,\n\tCOMMAND_IS_CAR_WAITING_FOR_WORLD_COLLISION,\n\tCOMMAND_IS_OBJECT_WAITING_FOR_WORLD_COLLISION,\n\tCOMMAND_SET_CHAR_SHUFFLE_INTO_DRIVERS_SEAT,\n\tCOMMAND_ATTACH_CHAR_TO_OBJECT,\n\tCOMMAND_SET_CHAR_AS_PLAYER_FRIEND,\n\tCOMMAND_DISPLAY_NTH_ONSCREEN_COUNTER,\n\tCOMMAND_DISPLAY_NTH_ONSCREEN_COUNTER_WITH_STRING,\n\tCOMMAND_ADD_SET_PIECE,\n\tCOMMAND_SET_EXTRA_COLOURS,\n\tCOMMAND_CLEAR_EXTRA_COLOURS,\n\tCOMMAND_CLOSE_CAR_BOOT,\n\tCOMMAND_GET_WHEELIE_STATS,\n\tCOMMAND_DISARM_CHAR,\n\tCOMMAND_BURST_CAR_TYRE,\n\tCOMMAND_IS_CHAR_OBJ_NO_OBJ,\n\tCOMMAND_IS_PLAYER_WEARING,\n\tCOMMAND_SET_PLAYER_CAN_DO_DRIVE_BY,\n\tCOMMAND_SET_CHAR_OBJ_SPRINT_TO_COORD,\n\tCOMMAND_CREATE_SWAT_ROPE,\n\tCOMMAND_SET_FIRST_PERSON_CONTROL_CAMERA,\n\tCOMMAND_GET_NEAREST_TYRE_TO_POINT,\n\tCOMMAND_SET_CAR_MODEL_COMPONENTS,\n\tCOMMAND_SWITCH_LIFT_CAMERA,\n\tCOMMAND_CLOSE_ALL_CAR_DOORS,\n\tCOMMAND_GET_DISTANCE_BETWEEN_COORDS_2D,\n\tCOMMAND_GET_DISTANCE_BETWEEN_COORDS_3D,\n\tCOMMAND_POP_CAR_BOOT_USING_PHYSICS,\n\tCOMMAND_SET_FIRST_PERSON_WEAPON_CAMERA,\n\tCOMMAND_IS_CHAR_LEAVING_VEHICLE_TO_DIE,\n\tCOMMAND_SORT_OUT_OBJECT_COLLISION_WITH_CAR,\n\tCOMMAND_GET_MAX_WANTED_LEVEL,\n\tCOMMAND_IS_CHAR_WANDER_PATH_CLEAR,\n\tCOMMAND_PRINT_HELP_WITH_NUMBER,\n\tCOMMAND_PRINT_HELP_FOREVER,\n\tCOMMAND_PRINT_HELP_FOREVER_WITH_NUMBER,\n\tCOMMAND_SET_CHAR_CAN_BE_DAMAGED_BY_MEMBERS_OF_GANG,\n\tCOMMAND_LOAD_AND_LAUNCH_MISSION_EXCLUSIVE,\n\tCOMMAND_IS_MISSION_AUDIO_PLAYING,\n\tCOMMAND_CREATE_LOCKED_PROPERTY_PICKUP,\n\tCOMMAND_CREATE_FORSALE_PROPERTY_PICKUP,\n\tCOMMAND_FREEZE_CAR_POSITION,\n\tCOMMAND_HAS_CHAR_BEEN_DAMAGED_BY_CHAR,\n\tCOMMAND_HAS_CHAR_BEEN_DAMAGED_BY_CAR,\n\tCOMMAND_HAS_CAR_BEEN_DAMAGED_BY_CHAR,\n\tCOMMAND_HAS_CAR_BEEN_DAMAGED_BY_CAR,\n\tCOMMAND_GET_RADIO_CHANNEL,\n\tCOMMAND_DISPLAY_TEXT_WITH_3_NUMBERS,\n\tCOMMAND_IS_CAR_DROWNING_IN_WATER,\n\tCOMMAND_IS_CHAR_DROWNING_IN_WATER,\n\tCOMMAND_DISABLE_CUTSCENE_SHADOWS,\n\tCOMMAND_HAS_GLASS_BEEN_SHATTERED_NEARBY,\n\tCOMMAND_ATTACH_CUTSCENE_OBJECT_TO_BONE,\n\tCOMMAND_ATTACH_CUTSCENE_OBJECT_TO_COMPONENT,\n\tCOMMAND_SET_CHAR_STAY_IN_CAR_WHEN_JACKED,\n\tCOMMAND_IS_MISSION_AUDIO_LOADING,\n\tCOMMAND_ADD_MONEY_SPENT_ON_WEAPONS,\n\tCOMMAND_ADD_MONEY_SPENT_ON_PROPERTY,\n\tCOMMAND_ADD_MONEY_SPENT_ON_AUTO_PAINTING,\n\tCOMMAND_SET_CHAR_ANSWERING_MOBILE,\n\tCOMMAND_SET_PLAYER_DRUNKENNESS,\n\tCOMMAND_GET_PLAYER_DRUNKENNESS,\n\tCOMMAND_SET_PLAYER_DRUG_LEVEL,\n\tCOMMAND_GET_PLAYER_DRUG_LEVEL,\n\tCOMMAND_ADD_LOAN_SHARK_VISITS,\n\tCOMMAND_ADD_STORES_KNOCKED_OFF,\n\tCOMMAND_ADD_MOVIE_STUNTS,\n\tCOMMAND_ADD_NUMBER_OF_ASSASSINATIONS,\n\tCOMMAND_ADD_PIZZAS_DELIVERED,\n\tCOMMAND_ADD_GARBAGE_PICKUPS,\n\tCOMMAND_ADD_ICE_CREAMS_SOLD,\n\tCOMMAND_SET_TOP_SHOOTING_RANGE_SCORE,\n\tCOMMAND_ADD_SHOOTING_RANGE_RANK,\n\tCOMMAND_ADD_MONEY_SPENT_ON_GAMBLING,\n\tCOMMAND_ADD_MONEY_WON_ON_GAMBLING,\n\tCOMMAND_SET_LARGEST_GAMBLING_WIN,\n\tCOMMAND_SET_CHAR_IN_PLAYERS_GROUP_CAN_FIGHT,\n\tCOMMAND_CLEAR_CHAR_WAIT_STATE,\n\tCOMMAND_GET_RANDOM_CAR_OF_TYPE_IN_AREA_NO_SAVE,\n\tCOMMAND_SET_CAN_BURST_CAR_TYRES,\n\tCOMMAND_SET_PLAYER_AUTO_AIM,\n\tCOMMAND_FIRE_HUNTER_GUN,\n\tCOMMAND_SET_PROPERTY_AS_OWNED,\n\tCOMMAND_ADD_BLOOD_RING_KILLS,\n\tCOMMAND_SET_LONGEST_TIME_IN_BLOOD_RING,\n\tCOMMAND_REMOVE_EVERYTHING_FOR_HUGE_CUTSCENE,\n\tCOMMAND_IS_PLAYER_TOUCHING_VEHICLE,\n\tCOMMAND_IS_CHAR_TOUCHING_VEHICLE,\n\tCOMMAND_CHECK_FOR_PED_MODEL_AROUND_PLAYER,\n\tCOMMAND_CLEAR_CHAR_FOLLOW_PATH,\n\tCOMMAND_SET_CHAR_CAN_BE_SHOT_IN_VEHICLE,\n\tCOMMAND_ATTACH_CUTSCENE_OBJECT_TO_VEHICLE,\n\tCOMMAND_LOAD_MISSION_TEXT,\n\tCOMMAND_SET_TONIGHTS_EVENT,\n\tCOMMAND_CLEAR_CHAR_LAST_DAMAGE_ENTITY,\n\tCOMMAND_CLEAR_CAR_LAST_DAMAGE_ENTITY,\n\tCOMMAND_FREEZE_OBJECT_POSITION,\n\tCOMMAND_SET_PLAYER_HAS_MET_DEBBIE_HARRY,\n\tCOMMAND_SET_RIOT_INTENSITY,\n\tCOMMAND_IS_CAR_IN_ANGLED_AREA_2D,\n\tCOMMAND_IS_CAR_IN_ANGLED_AREA_3D,\n\tCOMMAND_REMOVE_WEAPON_FROM_CHAR,\n\tCOMMAND_SET_UP_TAXI_SHORTCUT,\n\tCOMMAND_CLEAR_TAXI_SHORTCUT,\n\tCOMMAND_SET_CHAR_OBJ_GOTO_CAR_ON_FOOT,\n\tCOMMAND_GET_CLOSEST_WATER_NODE,\n\tCOMMAND_ADD_PORN_LEAFLET_TO_RUBBISH,\n\tCOMMAND_CREATE_CLOTHES_PICKUP,\n\tCOMMAND_CHANGE_BLIP_THRESHOLD,\n\tCOMMAND_MAKE_PLAYER_FIRE_PROOF,\n\tCOMMAND_INCREASE_PLAYER_MAX_HEALTH,\n\tCOMMAND_INCREASE_PLAYER_MAX_ARMOUR,\n\tCOMMAND_CREATE_RANDOM_CHAR_AS_DRIVER,\n\tCOMMAND_CREATE_RANDOM_CHAR_AS_PASSENGER,\n\tCOMMAND_SET_CHAR_IGNORE_THREATS_BEHIND_OBJECTS,\n\tCOMMAND_ENSURE_PLAYER_HAS_DRIVE_BY_WEAPON,\n\tCOMMAND_MAKE_HELI_COME_CRASHING_DOWN,\n\tCOMMAND_ADD_EXPLOSION_NO_SOUND,\n\tCOMMAND_SET_OBJECT_AREA_VISIBLE,\n\tCOMMAND_WAS_VEHICLE_EVER_POLICE,\n\tCOMMAND_SET_CHAR_NEVER_TARGETTED,\n\tCOMMAND_LOAD_UNCOMPRESSED_ANIM,\n\tCOMMAND_WAS_CUTSCENE_SKIPPED,\n\tCOMMAND_SET_CHAR_CROUCH_WHEN_THREATENED,\n\tCOMMAND_IS_CHAR_IN_ANY_POLICE_VEHICLE,\n\tCOMMAND_DOES_CHAR_EXIST,\n\tCOMMAND_DOES_VEHICLE_EXIST,\n\tCOMMAND_ADD_SHORT_RANGE_BLIP_FOR_CONTACT_POINT,\n\tCOMMAND_ADD_SHORT_RANGE_SPRITE_BLIP_FOR_CONTACT_POINT,\n\tCOMMAND_IS_CHAR_STUCK,\n\tCOMMAND_SET_ALL_TAXIS_HAVE_NITRO,\n\tCOMMAND_SET_CHAR_STOP_SHOOT_DONT_SEEK_ENTITY,\n\tCOMMAND_FREEZE_CAR_POSITION_AND_DONT_LOAD_COLLISION,\n\tCOMMAND_FREEZE_CHAR_POSITION_AND_DONT_LOAD_COLLISION,\n\tCOMMAND_FREEZE_OBJECT_POSITION_AND_DONT_LOAD_COLLISION,\n\tCOMMAND_SET_FADE_AND_JUMPCUT_AFTER_RC_EXPLOSION,\n\tCOMMAND_REGISTER_VIGILANTE_LEVEL,\n\tCOMMAND_CLEAR_ALL_CHAR_ANIMS,\n\tCOMMAND_SET_MAXIMUM_NUMBER_OF_CARS_IN_GARAGE,\n\tCOMMAND_WANTED_STARS_ARE_FLASHING,\n\tCOMMAND_SET_ALLOW_HURRICANES,\n\tCOMMAND_PLAY_ANNOUNCEMENT,\n\tCOMMAND_SET_PLAYER_IS_IN_STADIUM,\n\tCOMMAND_GET_BUS_FARES_COLLECTED_BY_PLAYER,\n\tCOMMAND_SET_CHAR_OBJ_BUY_ICE_CREAM,\n\tCOMMAND_DISPLAY_RADAR,\n\tCOMMAND_REGISTER_BEST_POSITION,\n\tCOMMAND_IS_PLAYER_IN_INFO_ZONE,\n\tCOMMAND_CLEAR_CHAR_ICE_CREAM_PURCHASE,\n\tCOMMAND_IS_IN_CAR_FIRE_BUTTON_PRESSED,\n\tCOMMAND_HAS_CHAR_ATTEMPTED_ATTRACTOR,\n\tCOMMAND_SET_LOAD_COLLISION_FOR_CAR_FLAG,\n\tCOMMAND_SET_LOAD_COLLISION_FOR_CHAR_FLAG,\n\tCOMMAND_SET_LOAD_COLLISION_FOR_OBJECT_FLAG,\n\tCOMMAND_ADD_BIG_GUN_FLASH,\n\tCOMMAND_HAS_CHAR_BOUGHT_ICE_CREAM,\n\tCOMMAND_GET_PROGRESS_PERCENTAGE,\n\tCOMMAND_SET_SHORTCUT_PICKUP_POINT,\n\tCOMMAND_SET_SHORTCUT_DROPOFF_POINT_FOR_MISSION,\n\tCOMMAND_GET_RANDOM_ICE_CREAM_CUSTOMER_IN_AREA,\n\tCOMMAND_GET_RANDOM_ICE_CREAM_CUSTOMER_IN_ZONE,\n\tCOMMAND_UNLOCK_ALL_CAR_DOORS_IN_AREA,\n\tCOMMAND_SET_GANG_ATTACK_PLAYER_WITH_COPS,\n\tCOMMAND_SET_CHAR_FRIGHTENED_IN_JACKED_CAR,\n\tCOMMAND_SET_VEHICLE_TO_FADE_IN,\n\tCOMMAND_REGISTER_ODDJOB_MISSION_PASSED,\n\tCOMMAND_IS_PLAYER_IN_SHORTCUT_TAXI,\n\tCOMMAND_IS_CHAR_DUCKING,\n\tCOMMAND_CREATE_DUST_EFFECT_FOR_CUTSCENE_HELI,\n\tCOMMAND_REGISTER_FIRE_LEVEL,\n\tCOMMAND_IS_AUSTRALIAN_GAME,\n\tCOMMAND_DISARM_CAR_BOMB,\n#if (defined GTAVC_JP_PATCH || defined SUPPORT_JAPANESE_SCRIPT)\n\tCOMMAND_IS_JAPANESE_GAME,\n#elif (!defined GTA_PS2)\n\tCOMMAND_SET_ONSCREEN_COUNTER_FLASH_WHEN_FIRST_DISPLAYED,\n#endif\n#if (defined GTA_PC && !defined GTAVC_JP_PATCH || defined GTA_XBOX || defined SUPPORT_XBOX_SCRIPT || defined GTA_MOBILE || defined SUPPORT_MOBILE_SCRIPT)\n\tCOMMAND_SHUFFLE_CARD_DECKS,\n\tCOMMAND_FETCH_NEXT_CARD,\n\tCOMMAND_GET_OBJECT_VELOCITY,\n\tCOMMAND_IS_DEBUG_CAMERA_ON,\n\tCOMMAND_ADD_TO_OBJECT_ROTATION_VELOCITY,\n\tCOMMAND_SET_OBJECT_ROTATION_VELOCITY,\n\tCOMMAND_IS_OBJECT_STATIC,\n\tCOMMAND_GET_ANGLE_BETWEEN_2D_VECTORS,\n\tCOMMAND_DO_2D_RECTANGLES_COLLIDE,\n\tCOMMAND_GET_OBJECT_ROTATION_VELOCITY,\n\tCOMMAND_ADD_VELOCITY_RELATIVE_TO_OBJECT_VELOCITY,\n\tCOMMAND_GET_OBJECT_SPEED,\n#endif\n#if (defined GTA_XBOX || defined SUPPORT_XBOX_SCRIPT)\n\tCOMMAND_MARK_CUTSCENE_START,\n\tCOMMAND_MARK_CUTSCENE_END,\n\tCOMMAND_CUTSCENE_SCROLL,\n#elif (defined GTA_MOBILE || defined SUPPORT_MOBILE_SCRIPT)\n\tCOMMAND_IS_MISSION_SKIP,\n\tCOMMAND_SET_IN_AMMUNATION,\n\tCOMMAND_DO_SAVE_GAME,\n\tCOMMAND_IS_RETRY,\n\tCOMMAND_DUMMY,\n\tCOMMAND_MARK_CUTSCENE_START,\n\tCOMMAND_MARK_CUTSCENE_END,\n\tCOMMAND_CUTSCENE_SCROLL,\n#endif\n#ifdef USE_ADVANCED_SCRIPT_DEBUG_OUTPUT\n\tLAST_SCRIPT_COMMAND\n#endif\n};\n\n#ifdef USE_ADVANCED_SCRIPT_DEBUG_OUTPUT\n\nenum eScriptArgument\n{\n\tARGTYPE_NONE = 0,\n\tARGTYPE_INT,\n\tARGTYPE_FLOAT,\n\tARGTYPE_STRING,\n\tARGTYPE_LABEL,\n\tARGTYPE_BOOL,\n\tARGTYPE_PED_HANDLE,\n\tARGTYPE_VEHICLE_HANDLE,\n\tARGTYPE_OBJECT_HANDLE,\n\tARGTYPE_ANDOR\n};\n\nstruct tScriptCommandData\n{\n\tint id;\n\tconst char name[64];\n\teScriptArgument input[18];\n\teScriptArgument output[18];\n\tbool cond;\n\tint position;\n\tconst char name_override[8];\n};\n#endif"
  },
  {
    "path": "src/control/SetPieces.cpp",
    "content": "#include \"common.h\"\n\n#include \"SetPieces.h\"\n#include \"Automobile.h\"\n#include \"CarAI.h\"\n#include \"CopPed.h\"\n#include \"GenericGameStorage.h\"\n#include \"PlayerPed.h\"\n#include \"Timer.h\"\n#include \"Vehicle.h\"\n#include \"Wanted.h\"\n#include \"World.h\"\n#include \"VarConsole.h\"\n\n#define TIME_BETWEEN_SETPIECE_SPAWNS 20000\n\nbool CSetPieces::bDebug;\nuint32 CSetPieces::NumSetPieces;\nCSetPiece CSetPieces::aSetPieces[NUM_SETPIECES];\n\nvoid CSetPieces::Init(void)\n{\n\tbDebug = false;\n\tNumSetPieces = 0;\n#ifndef MASTER\n\tVarConsole.Add(\"Show set pieces\", &bDebug, true);\n#endif\n}\n\nvoid CSetPieces::AddOne(uint8 type, CVector2D vTriggerInf, CVector2D vTriggerSup, CVector2D vSpawn1, CVector2D vTarget1, CVector2D vSpawn2, CVector2D vTarget2)\n{\n\tif (NumSetPieces >= NUM_SETPIECES)\n\t\treturn;\n\taSetPieces[NumSetPieces].m_nType = type;\n\taSetPieces[NumSetPieces].m_vTriggerInf.x = Min(vTriggerInf.x, vTriggerSup.x);\n\taSetPieces[NumSetPieces].m_vTriggerInf.y = Min(vTriggerInf.y, vTriggerSup.y);\n\taSetPieces[NumSetPieces].m_vTriggerSup.x = Max(vTriggerInf.x, vTriggerSup.x);\n\taSetPieces[NumSetPieces].m_vTriggerSup.y = Max(vTriggerInf.y, vTriggerSup.y);\n\taSetPieces[NumSetPieces].m_vSpawn1 = vSpawn1;\n\taSetPieces[NumSetPieces].m_vSpawn2 = vSpawn2;\n\taSetPieces[NumSetPieces].m_vTarget1 = vTarget1;\n\taSetPieces[NumSetPieces].m_vTarget2 = vTarget2;\n\t++NumSetPieces;\n}\n\nvoid CSetPieces::Update(void)\n{\n\tint nFirst = NumSetPieces * (CTimer::GetFrameCounter() % 8) / 8;\n\tint nLast = NumSetPieces * (CTimer::GetFrameCounter() % 8 + 1) / 8;\n\tfor (int i = nFirst; i < nLast; i++)\n\t\taSetPieces[i].Update();\n#ifndef MASTER\n\t// TODO: debug code from mobile\n#endif // !MASTER\n}\n\nvoid CSetPieces::Save(uint8* buf, uint32* size)\n{\nINITSAVEBUF\n\tWriteSaveBuf(buf, NumSetPieces);\n\tfor (int i = 0; i < NUM_SETPIECES; i++)\n\t\tWriteSaveBuf(buf, aSetPieces[i]);\n\t*size = sizeof(NumSetPieces) + NUM_SETPIECES * sizeof(CSetPiece);\nVALIDATESAVEBUF(*size)\n}\n\nvoid CSetPieces::Load(uint8* buf, uint32 size)\n{\nINITSAVEBUF\n\tNumSetPieces = ReadSaveBuf<uint32>(buf);\n\tfor (int i = 0; i < NUM_SETPIECES; i++)\n\t\taSetPieces[i] = ReadSaveBuf<CSetPiece>(buf);\nVALIDATESAVEBUF(size)\n}\n\nvoid CSetPiece::Update(void)\n{\n\tif (m_nLastTimeCreated != 0 && CTimer::GetTimeInMilliseconds() <= m_nLastTimeCreated + TIME_BETWEEN_SETPIECE_SPAWNS)\n\t\treturn;\n\tCVector pos = FindPlayerCoors();\n\tif (pos.x < m_vTriggerInf.x || pos.x > m_vTriggerSup.x ||\n\t\tpos.y < m_vTriggerInf.y || pos.y > m_vTriggerSup.y)\n\t\treturn;\n\tswitch (m_nType) {\n\tcase SETPIECE_TWOCOPCARSINALLEY:\n\t{\n\t\tif (FindPlayerPed()->m_pWanted->GetWantedLevel() < 1 || FindPlayerVehicle())\n\t\t\treturn;\n\t\tCVehicle* pVehicle1 = TryToGenerateCopCar(m_vSpawn1, m_vTarget1);\n\t\tif (!pVehicle1)\n\t\t\treturn;\n\t\tCVehicle* pVehicle2 = TryToGenerateCopCar(m_vSpawn2, m_vTarget2);\n\t\tif (!pVehicle2) {\n\t\t\tCWorld::Remove(pVehicle1);\n\t\t\tdelete pVehicle1;\n\t\t\treturn;\n\t\t}\n\t\tpVehicle1->SetStatus(STATUS_PHYSICS);\n\t\tpVehicle1->AutoPilot.m_fMaxTrafficSpeed = pVehicle1->AutoPilot.m_nCruiseSpeed = 4;\n\t\tpVehicle1->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_SLOW_DOWN_FOR_CARS;\n\t\tpVehicle1->AutoPilot.m_nCarMission = MISSION_SLOWLY_DRIVE_TOWARDS_PLAYER_1;\n\t\tpVehicle1->AutoPilot.m_vecDestinationCoors.x = m_vTarget1.x;\n\t\tpVehicle1->AutoPilot.m_vecDestinationCoors.y = m_vTarget1.y;\n\t\tpVehicle1->AutoPilot.m_vecDestinationCoors.z = 0.0f;\n\t\tpVehicle1->m_nSetPieceExtendedRangeTime = CTimer::GetTimeInMilliseconds() + 25000;\n\t\tCCarAI::AddPoliceCarOccupants(pVehicle1);\n\t\tpVehicle2->SetStatus(STATUS_PHYSICS);\n\t\tpVehicle2->AutoPilot.m_fMaxTrafficSpeed = pVehicle2->AutoPilot.m_nCruiseSpeed = 4;\n\t\tpVehicle2->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_SLOW_DOWN_FOR_CARS;\n\t\tpVehicle2->AutoPilot.m_nCarMission = MISSION_SLOWLY_DRIVE_TOWARDS_PLAYER_1;\n\t\tpVehicle2->AutoPilot.m_vecDestinationCoors.x = m_vTarget2.x;\n\t\tpVehicle2->AutoPilot.m_vecDestinationCoors.y = m_vTarget2.y;\n\t\tpVehicle2->AutoPilot.m_vecDestinationCoors.z = 0.0f;\n\t\tpVehicle2->m_nSetPieceExtendedRangeTime = CTimer::GetTimeInMilliseconds() + 25000;\n\t\tCCarAI::AddPoliceCarOccupants(pVehicle2);\n\t\tm_nLastTimeCreated = CTimer::GetTimeInMilliseconds();\n\t\tbreak;\n\t}\n\tcase SETPIECE_CARBLOCKINGPLAYERFROMSIDE:\n\t{\n\t\tif (FindPlayerPed()->m_pWanted->GetWantedLevel() < 2)\n\t\t\treturn;\n\t\tif (!FindPlayerVehicle())\n\t\t\treturn;\n\t\tif (DotProduct2D(FindPlayerSpeed(), (CVector2D)FindPlayerCoors() - m_vSpawn1) >= 0.0f)\n\t\t\treturn;\n\t\tCVehicle* pVehicle1 = TryToGenerateCopCar(m_vSpawn1, m_vTarget1);\n\t\tif (!pVehicle1)\n\t\t\treturn;\n\t\tpVehicle1->SetStatus(STATUS_PHYSICS);\n\t\tpVehicle1->AutoPilot.m_fMaxTrafficSpeed = pVehicle1->AutoPilot.m_nCruiseSpeed = 16;\n\t\tpVehicle1->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_PLOUGH_THROUGH;\n\t\tpVehicle1->AutoPilot.m_nCarMission = MISSION_BLOCKPLAYER_FORWARDANDBACK;\n\t\tpVehicle1->AutoPilot.m_nTempAction = TEMPACT_GOFORWARD;\n\t\tpVehicle1->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 100;\n\t\tpVehicle1->m_nSetPieceExtendedRangeTime = CTimer::GetTimeInMilliseconds() + 10000;\n\t\tpVehicle1->SetMoveSpeed(2.0f * pVehicle1->GetForward() / 3.0f);\n\t\tCCarAI::AddPoliceCarOccupants(pVehicle1);\n\t\tm_nLastTimeCreated = CTimer::GetTimeInMilliseconds();\n\t\treturn;\n\t}\n\tcase SETPIECE_CARRAMMINGPLAYERFROMSIDE:\n\t{\n\t\tif (FindPlayerPed()->m_pWanted->GetWantedLevel() < 2)\n\t\t\treturn;\n\t\tif (!FindPlayerVehicle())\n\t\t\treturn;\n\t\tif (DotProduct2D(FindPlayerSpeed(), (CVector2D)FindPlayerCoors() - m_vSpawn1) >= 0.0f)\n\t\t\treturn;\n\t\tCVehicle* pVehicle1 = TryToGenerateCopCar(m_vSpawn1, m_vTarget1);\n\t\tif (!pVehicle1)\n\t\t\treturn;\n\t\tpVehicle1->SetStatus(STATUS_PHYSICS);\n\t\tpVehicle1->AutoPilot.m_fMaxTrafficSpeed = pVehicle1->AutoPilot.m_nCruiseSpeed = 16;\n\t\tpVehicle1->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS;\n\t\tpVehicle1->AutoPilot.m_nCarMission = MISSION_RAMCAR_CLOSE;\n\t\tpVehicle1->AutoPilot.m_nTempAction = TEMPACT_GOFORWARD;\n\t\tpVehicle1->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 100;\n\t\tpVehicle1->m_nSetPieceExtendedRangeTime = CTimer::GetTimeInMilliseconds() + 10000;\n\t\tpVehicle1->SetMoveSpeed(2.0f * pVehicle1->GetForward() / 3.0f);\n\t\tCCarAI::AddPoliceCarOccupants(pVehicle1);\n\t\tm_nLastTimeCreated = CTimer::GetTimeInMilliseconds();\n\t\treturn;\n\t}\n\tcase SETPIECE_CREATECOPPERONFOOT:\n\t{\n\t\tif (FindPlayerPed()->m_pWanted->GetWantedLevel() < 1 || FindPlayerVehicle())\n\t\t\treturn;\n\t\tCCopPed* pCop = TryToGenerateCopPed(m_vSpawn1);\n\t\tif (!pCop)\n\t\t\treturn;\n\t\tfloat z = CWorld::FindGroundZForCoord(m_vTarget1.x, m_vTarget1.y);\n\t\tpCop->bScriptObjectiveCompleted = false;\n\t\tpCop->SetObjective(OBJECTIVE_GOTO_AREA_ON_FOOT, CVector(m_vTarget1.x, m_vTarget1.y, z));\n\t\tpCop->m_nExtendedRangeTimer = CTimer::GetTimeInMilliseconds() + 10000;\n\t\tm_nLastTimeCreated = CTimer::GetTimeInMilliseconds();\n\t\treturn;\n\t}\n\tcase SETPIECE_CREATETWOCOPPERSONFOOT:\n\t{\n\t\tif (FindPlayerPed()->m_pWanted->GetWantedLevel() < 1 || FindPlayerVehicle())\n\t\t\treturn;\n\t\tCCopPed* pCop = TryToGenerateCopPed(m_vSpawn1);\n\t\tif (!pCop)\n\t\t\treturn;\n\t\tfloat z = CWorld::FindGroundZForCoord(m_vTarget1.x, m_vTarget1.y);\n\t\tpCop->bScriptObjectiveCompleted = false;\n\t\tpCop->SetObjective(OBJECTIVE_GOTO_AREA_ON_FOOT, CVector(m_vTarget1.x, m_vTarget1.y, z));\n\t\tpCop->m_nExtendedRangeTimer = CTimer::GetTimeInMilliseconds() + 10000;\n\t\tCCopPed* pCop2 = TryToGenerateCopPed(m_vSpawn2);\n\t\tif (!pCop2) {\n\t\t\tCWorld::Remove(pCop);\n\t\t\tdelete pCop;\n\t\t\treturn;\n\t\t}\n\t\tz = CWorld::FindGroundZForCoord(m_vTarget2.x, m_vTarget2.y);\n\t\tpCop2->bScriptObjectiveCompleted = false;\n\t\tpCop2->SetObjective(OBJECTIVE_GOTO_AREA_ON_FOOT, CVector(m_vTarget2.x, m_vTarget2.y, z));\n\t\tpCop2->m_nExtendedRangeTimer = CTimer::GetTimeInMilliseconds() + 10000;\n\t\tm_nLastTimeCreated = CTimer::GetTimeInMilliseconds();\n\t\treturn;\n\t}\n\tcase SETPIECE_TWOCARSBLOCKINGPLAYERFROMSIDE:\n\t{\n\t\tif (FindPlayerPed()->m_pWanted->GetWantedLevel() < 2)\n\t\t\treturn;\n\t\tif (!FindPlayerVehicle())\n\t\t\treturn;\n\t\tif (DotProduct2D(FindPlayerSpeed(), (CVector2D)FindPlayerCoors() - m_vSpawn1) >= 0.0f)\n\t\t\treturn;\n\t\tCVehicle* pVehicle1 = TryToGenerateCopCar(m_vSpawn1, m_vTarget1);\n\t\tif (!pVehicle1)\n\t\t\treturn;\n\t\tpVehicle1->SetStatus(STATUS_PHYSICS);\n\t\tpVehicle1->AutoPilot.m_fMaxTrafficSpeed = pVehicle1->AutoPilot.m_nCruiseSpeed = 16;\n\t\tpVehicle1->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_PLOUGH_THROUGH;\n\t\tpVehicle1->AutoPilot.m_nCarMission = MISSION_BLOCKPLAYER_FORWARDANDBACK;\n\t\tpVehicle1->AutoPilot.m_nTempAction = TEMPACT_GOFORWARD;\n\t\tpVehicle1->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 100;\n\t\tpVehicle1->m_nSetPieceExtendedRangeTime = CTimer::GetTimeInMilliseconds() + 10000;\n\t\tpVehicle1->SetMoveSpeed(2.0f * pVehicle1->GetForward() / 3.0f);\n\t\tCCarAI::AddPoliceCarOccupants(pVehicle1);\n\t\tCVehicle* pVehicle2 = TryToGenerateCopCar(m_vSpawn2, m_vTarget2);\n\t\tif (!pVehicle2) {\n\t\t\tCWorld::Remove(pVehicle1);\n\t\t\tdelete pVehicle1;\n\t\t\treturn;\n\t\t}\n\t\tpVehicle2->SetStatus(STATUS_PHYSICS);\n\t\tpVehicle2->AutoPilot.m_fMaxTrafficSpeed = pVehicle1->AutoPilot.m_nCruiseSpeed = 16;\n\t\tpVehicle2->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_PLOUGH_THROUGH;\n\t\tpVehicle2->AutoPilot.m_nCarMission = MISSION_BLOCKPLAYER_FORWARDANDBACK;\n\t\tpVehicle2->AutoPilot.m_nTempAction = TEMPACT_GOFORWARD;\n\t\tpVehicle2->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 100;\n\t\tpVehicle2->m_nSetPieceExtendedRangeTime = CTimer::GetTimeInMilliseconds() + 10000;\n\t\tpVehicle2->SetMoveSpeed(2.0f * pVehicle2->GetForward() / 3.0f);\n\t\tCCarAI::AddPoliceCarOccupants(pVehicle2);\n\t\tm_nLastTimeCreated = CTimer::GetTimeInMilliseconds();\n\t\treturn;\n\t}\n\tcase SETPIECE_TWOCARSRAMMINGPLAYERFROMSIDE:\n\t{\n\t\tif (FindPlayerPed()->m_pWanted->GetWantedLevel() < 2)\n\t\t\treturn;\n\t\tif (!FindPlayerVehicle())\n\t\t\treturn;\n\t\tif (DotProduct2D(FindPlayerSpeed(), (CVector2D)FindPlayerCoors() - m_vSpawn1) >= 0.0f)\n\t\t\treturn;\n\t\tCVehicle* pVehicle1 = TryToGenerateCopCar(m_vSpawn1, m_vTarget1);\n\t\tif (!pVehicle1)\n\t\t\treturn;\n\t\tpVehicle1->SetStatus(STATUS_PHYSICS);\n\t\tpVehicle1->AutoPilot.m_fMaxTrafficSpeed = pVehicle1->AutoPilot.m_nCruiseSpeed = 16;\n\t\tpVehicle1->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS;\n\t\tpVehicle1->AutoPilot.m_nCarMission = MISSION_RAMCAR_CLOSE;\n\t\tpVehicle1->AutoPilot.m_nTempAction = TEMPACT_GOFORWARD;\n\t\tpVehicle1->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 100;\n\t\tpVehicle1->m_nSetPieceExtendedRangeTime = CTimer::GetTimeInMilliseconds() + 10000;\n\t\tpVehicle1->SetMoveSpeed(2.0f * pVehicle1->GetForward() / 3.0f);\n\t\tCCarAI::AddPoliceCarOccupants(pVehicle1);\n\t\tCVehicle* pVehicle2 = TryToGenerateCopCar(m_vSpawn2, m_vTarget2);\n\t\tif (!pVehicle2) {\n\t\t\tCWorld::Remove(pVehicle1);\n\t\t\tdelete pVehicle1;\n\t\t\treturn;\n\t\t}\n\t\tpVehicle2->SetStatus(STATUS_PHYSICS);\n\t\tpVehicle2->AutoPilot.m_fMaxTrafficSpeed = pVehicle2->AutoPilot.m_nCruiseSpeed = 16;\n\t\tpVehicle2->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS;\n\t\tpVehicle2->AutoPilot.m_nCarMission = MISSION_RAMCAR_CLOSE;\n\t\tpVehicle2->AutoPilot.m_nTempAction = TEMPACT_GOFORWARD;\n\t\tpVehicle2->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 100;\n\t\tpVehicle2->m_nSetPieceExtendedRangeTime = CTimer::GetTimeInMilliseconds() + 10000;\n\t\tpVehicle2->SetMoveSpeed(2.0f * pVehicle2->GetForward() / 3.0f);\n\t\tCCarAI::AddPoliceCarOccupants(pVehicle2);\n\t\tm_nLastTimeCreated = CTimer::GetTimeInMilliseconds();\n\t\treturn;\n\t}\n\t}\n}\n\nCVehicle* CSetPiece::TryToGenerateCopCar(CVector2D vSpawn, CVector2D vTarget)\n{\n\tCVehicle* pVehicle = new CAutomobile(MI_POLICE, RANDOM_VEHICLE);\n\tCVector pos(vSpawn.x, vSpawn.y, 1000.0f);\n\tCColPoint point;\n\tCEntity* pEntity;\n\tif (CWorld::ProcessVerticalLine(pos, -1000.0f, point, pEntity, true, false, false, false, true, false, nil))\n\t\tpos.z = point.point.z + pVehicle->GetHeightAboveRoad();\n\tCVector vDirection(vTarget.x - vSpawn.x, vTarget.y - vSpawn.y, 0.0f);\n\tvDirection.Normalise();\n\tpVehicle->GetForward() = CVector(vDirection.x, vDirection.y, 0.0f);\n\tpVehicle->GetRight() = CVector(vDirection.y, -vDirection.x, 0.0f);\n\tpVehicle->GetUp() = CVector(0.0f, 0.0f, 1.0f);\n\tpVehicle->SetPosition(pos);\n\tint16 total;\n\tCWorld::FindObjectsKindaColliding(pos, pVehicle->GetColModel()->spheres->radius, false, &total, 16, nil, false, true, true, false, false);\n\tif (total != 0) {\n\t\tdelete pVehicle;\n\t\treturn nil;\n\t}\n\tpVehicle->ChangeLawEnforcerState(true);\n\tCWorld::Add(pVehicle);\n\treturn pVehicle;\n}\n\nCCopPed* CSetPiece::TryToGenerateCopPed(CVector2D vSpawn)\n{\n\tCCopPed* pCop = new CCopPed(COP_STREET);\n\tCVector pos(vSpawn.x, vSpawn.y, 1000.0f);\n\tCColPoint point;\n\tCEntity* pEntity;\n\tif (CWorld::ProcessVerticalLine(pos, -1000.0f, point, pEntity, true, false, false, false, true, false, nil))\n\t\tpos.z = point.point.z + 0.9f;\n\tpCop->SetPosition(pos);\n\tint16 total;\n\tCWorld::FindObjectsKindaColliding(pos, pCop->GetColModel()->spheres->radius, false, &total, 16, nil, false, true, true, false, false);\n\tif (total != 0) {\n\t\tdelete pCop;\n\t\treturn nil;\n\t}\n\tCWorld::Add(pCop);\n\treturn pCop;\n}"
  },
  {
    "path": "src/control/SetPieces.h",
    "content": "#pragma once\n\n#include \"config.h\"\n\nclass CVehicle;\nclass CCopPed;\n\nenum eSetPieceType\n{\n\tSETPIECE_NONE = 0,\n\tSETPIECE_TWOCOPCARSINALLEY,\n\tSETPIECE_CARBLOCKINGPLAYERFROMSIDE,\n\tSETPIECE_CARRAMMINGPLAYERFROMSIDE,\n\tSETPIECE_CREATECOPPERONFOOT,\n\tSETPIECE_CREATETWOCOPPERSONFOOT,\n\tSETPIECE_TWOCARSBLOCKINGPLAYERFROMSIDE,\n\tSETPIECE_TWOCARSRAMMINGPLAYERFROMSIDE\n};\n\nclass CSetPiece\n{\npublic:\n\tuint8 m_nType;\n\tuint32 m_nLastTimeCreated;\n\tCVector2D m_vTriggerInf;\n\tCVector2D m_vTriggerSup;\n\tCVector2D m_vSpawn1;\n\tCVector2D m_vSpawn2;\n\tCVector2D m_vTarget1;\n\tCVector2D m_vTarget2;\n\n\tCVehicle* TryToGenerateCopCar(CVector2D, CVector2D);\n\tCCopPed* TryToGenerateCopPed(CVector2D);\n\tvoid Update(void);\n};\n\nclass CSetPieces\n{\n\tstatic bool bDebug;\n\tstatic uint32 NumSetPieces;\n\tstatic CSetPiece aSetPieces[NUM_SETPIECES];\npublic:\n\tstatic void Init(void);\n\tstatic void AddOne(uint8 type, CVector2D, CVector2D, CVector2D, CVector2D, CVector2D, CVector2D);\n\tstatic void Save(uint8*, uint32*);\n\tstatic void Load(uint8*, uint32);\n\tstatic void Update(void);\n};\n"
  },
  {
    "path": "src/control/TrafficLights.cpp",
    "content": "#include \"common.h\"\n\n#include \"Camera.h\"\n#include \"Clock.h\"\n#include \"Coronas.h\"\n#include \"General.h\"\n#include \"PathFind.h\"\n#include \"PointLights.h\"\n#include \"Shadows.h\"\n#include \"SpecialFX.h\"\n#include \"Timecycle.h\"\n#include \"Timer.h\"\n#include \"TrafficLights.h\"\n#include \"Vehicle.h\"\n#include \"Weather.h\"\n#include \"World.h\"\n\nbool CTrafficLights::bGreenLightsCheat;\n\nvoid\nCTrafficLights::DisplayActualLight(CEntity *ent)\n{\n\tif(ent->GetUp().z < 0.96f || ent->bRenderDamaged)\n\t\treturn;\n\n\tint phase;\n\tif(FindTrafficLightType(ent) == 1)\n\t\tphase = LightForCars1_Visual();\n\telse\n\t\tphase = LightForCars2_Visual();\n\n\tint i, m = ent->GetModelIndex();\n\tif (MI_TRAFFICLIGHTS == m) {\n\t\tCBaseModelInfo* mi = CModelInfo::GetModelInfo(ent->GetModelIndex());\n\t\tfloat x = mi->Get2dEffect(0)->pos.x;\n\t\tfloat yMin = mi->Get2dEffect(0)->pos.y;\n\t\tfloat yMax = mi->Get2dEffect(0)->pos.y;\n\t\tfloat zMin = mi->Get2dEffect(0)->pos.z;\n\t\tfloat zMax = mi->Get2dEffect(0)->pos.z;\n\t\tfor (i = 1; i < 6; i++) {\n\t\t\tassert(mi->Get2dEffect(i));\n\t\t\tyMin = Min(yMin, mi->Get2dEffect(i)->pos.y);\n\t\t\tyMax = Max(yMax, mi->Get2dEffect(i)->pos.y);\n\t\t\tzMin = Min(zMin, mi->Get2dEffect(i)->pos.z);\n\t\t\tzMax = Max(zMax, mi->Get2dEffect(i)->pos.z);\n\t\t}\n\n\t\tCVector pos1, pos2;\n\t\tuint8 r, g;\n\t\tint id;\n\t\tswitch (phase) {\n\t\tcase CAR_LIGHTS_GREEN:\n\t\t\tr = 0;\n\t\t\tg = 255;\n\t\t\tpos1 = ent->GetMatrix() * CVector(x, yMax, zMin);\n\t\t\tpos2 = ent->GetMatrix() * CVector(x, yMin, zMin);\n\t\t\tid = 0;\n\t\t\tbreak;\n\t\tcase CAR_LIGHTS_YELLOW:\n\t\t\tr = 255;\n\t\t\tg = 128;\n\t\t\tpos1 = ent->GetMatrix() * CVector(x, yMax, (zMin + zMax) / 2.0f);\n\t\t\tpos2 = ent->GetMatrix() * CVector(x, yMin, (zMin + zMax) / 2.0f);\n\t\t\tid = 1;\n\t\t\tbreak;\n\t\tcase CAR_LIGHTS_RED:\n\t\t\tr = 255;\n\t\t\tg = 0;\n\t\t\tpos1 = ent->GetMatrix() * CVector(x, yMax, zMax);\n\t\t\tpos2 = ent->GetMatrix() * CVector(x, yMin, zMax);\n\t\t\tid = 2;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tr = 0;\n\t\t\tg = 0;\n\t\t\tpos1 = ent->GetMatrix() * CVector(x, yMax, (zMin + zMax) / 2.0f);\n\t\t\tpos2 = ent->GetMatrix() * CVector(x, yMin, (zMin + zMax) / 2.0f);\n\t\t\tid = -1;\n\t\t\tbreak;\n\t\t}\n\n\t\tif (CWeather::TrafficLightBrightness > 0.5f)\n\t\t\tCPointLights::AddLight(CPointLights::LIGHT_POINT,\n\t\t\t\tpos1, CVector(0.0f, 0.0f, 0.0f), 8.0f,\n\t\t\t\tr / 255.0f, g / 255.0f, 0 / 255.0f, CPointLights::FOG_NORMAL, true);\n\n\t\tif (CWeather::TrafficLightBrightness > 0.05f)\n\t\t\tCShadows::StoreStaticShadow((uintptr)ent,\n\t\t\t\tSHADOWTYPE_ADDITIVE, gpShadowExplosionTex, &pos1,\n\t\t\t\t8.0f, 0.0f, 0.0f, -8.0f, 128,\n\t\t\t\tr * CTimeCycle::GetLightOnGroundBrightness() * CWeather::TrafficLightBrightness / 8.0f,\n\t\t\t\tg * CTimeCycle::GetLightOnGroundBrightness() * CWeather::TrafficLightBrightness / 8.0f,\n\t\t\t\t0 * CTimeCycle::GetLightOnGroundBrightness() * CWeather::TrafficLightBrightness / 8.0f,\n\t\t\t\t12.0f, 1.0f, 40.0f, false, 0.0f);\n\n\t\tif (DotProduct(TheCamera.GetForward(), ent->GetForward()) < 0.0f)\n\t\t\tCCoronas::RegisterCorona((uintptr)ent + id,\n\t\t\t\tr * CTimeCycle::GetSpriteBrightness() * 0.7f,\n\t\t\t\tg * CTimeCycle::GetSpriteBrightness() * 0.7f,\n\t\t\t\t0 * CTimeCycle::GetSpriteBrightness() * 0.7f,\n\t\t\t\t255,\n\t\t\t\tpos1, 1.75f * CTimeCycle::GetSpriteSize(), 50.0f,\n\t\t\t\tCCoronas::TYPE_STAR, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON,\n\t\t\t\tCCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);\n\t\telse\n\t\t\tCCoronas::RegisterCorona((uintptr)ent + id + 3,\n\t\t\t\tr * CTimeCycle::GetSpriteBrightness() * 0.7f,\n\t\t\t\tg * CTimeCycle::GetSpriteBrightness() * 0.7f,\n\t\t\t\t0 * CTimeCycle::GetSpriteBrightness() * 0.7f,\n\t\t\t\t255,\n\t\t\t\tpos2, 1.75f * CTimeCycle::GetSpriteSize(), 50.0f,\n\t\t\t\tCCoronas::TYPE_STAR, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON,\n\t\t\t\tCCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);\n\n\t\tCBrightLights::RegisterOne(pos1, ent->GetUp(), ent->GetRight(), CVector(0.0f, 0.0f, 0.0f), id + BRIGHTLIGHT_TRAFFIC_GREEN);\n\t\tCBrightLights::RegisterOne(pos2, ent->GetUp(), -ent->GetRight(), CVector(0.0f, 0.0f, 0.0f), id + BRIGHTLIGHT_TRAFFIC_GREEN);\n\t}\n\telse if (MI_TRAFFICLIGHTS_VERTICAL == m) {\n\t\tCBaseModelInfo* mi = CModelInfo::GetModelInfo(ent->GetModelIndex());\n\t\tfloat x = mi->Get2dEffect(0)->pos.x;\n\t\tfloat yMin = mi->Get2dEffect(0)->pos.y;\n\t\tfloat yMax = mi->Get2dEffect(0)->pos.y;\n\t\tfloat zMin = mi->Get2dEffect(0)->pos.z;\n\t\tfloat zMax = mi->Get2dEffect(0)->pos.z;\n\t\tfor (i = 1; i < 6; i++) {\n\t\t\tassert(mi->Get2dEffect(i));\n\t\t\tyMin = Min(yMin, mi->Get2dEffect(i)->pos.y);\n\t\t\tyMax = Max(yMax, mi->Get2dEffect(i)->pos.y);\n\t\t\tzMin = Min(zMin, mi->Get2dEffect(i)->pos.z);\n\t\t\tzMax = Max(zMax, mi->Get2dEffect(i)->pos.z);\n\t\t}\n\n\t\tCVector pos1;\n\t\tuint8 r, g;\n\t\tint id;\n\t\tswitch (phase) {\n\t\tcase CAR_LIGHTS_GREEN:\n\t\t\tr = 0;\n\t\t\tg = 255;\n\t\t\tpos1 = ent->GetMatrix() * mi->Get2dEffect(2)->pos;\n\t\t\tid = 0;\n\t\t\tbreak;\n\t\tcase CAR_LIGHTS_YELLOW:\n\t\t\tr = 255;\n\t\t\tg = 128;\n\t\t\tpos1 = ent->GetMatrix() * mi->Get2dEffect(1)->pos;\n\t\t\tid = 1;\n\t\t\tbreak;\n\t\tcase CAR_LIGHTS_RED:\n\t\t\tr = 255;\n\t\t\tg = 0;\n\t\t\tpos1 = ent->GetMatrix() * mi->Get2dEffect(0)->pos;\n\t\t\tid = 2;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tr = 0;\n\t\t\tg = 0;\n\t\t\tpos1 = ent->GetMatrix() * mi->Get2dEffect(1)->pos;\n\t\t\tid = -1;\n\t\t\tbreak;\n\t\t}\n\n\t\tCBrightLights::RegisterOne(pos1, ent->GetUp(), ent->GetRight(), CVector(0.0f, 0.0f, 0.0f), id + BRIGHTLIGHT_TRAFFIC_GREEN);\n\n\t\tif (CWeather::TrafficLightBrightness > 0.5f)\n\t\t\tCPointLights::AddLight(CPointLights::LIGHT_POINT,\n\t\t\t\tpos1, CVector(0.0f, 0.0f, 0.0f), 8.0f,\n\t\t\t\tr / 255.0f, g / 255.0f, 0 / 255.0f, CPointLights::FOG_NORMAL, true);\n\n\t\tif (CWeather::TrafficLightBrightness > 0.05f)\n\t\t\tCShadows::StoreStaticShadow((uintptr)ent,\n\t\t\t\tSHADOWTYPE_ADDITIVE, gpShadowExplosionTex, &pos1,\n\t\t\t\t8.0f, 0.0f, 0.0f, -8.0f, 128,\n\t\t\t\tr * CTimeCycle::GetLightOnGroundBrightness() * CWeather::TrafficLightBrightness / 8.0f,\n\t\t\t\tg * CTimeCycle::GetLightOnGroundBrightness() * CWeather::TrafficLightBrightness / 8.0f,\n\t\t\t\t0 * CTimeCycle::GetLightOnGroundBrightness() * CWeather::TrafficLightBrightness / 8.0f,\n\t\t\t\t12.0f, 1.0f, 40.0f, false, 0.0f);\n\n\t\tif (DotProduct(TheCamera.GetForward(), ent->GetForward()) < 0.0f)\n\t\t\tCCoronas::RegisterCorona((uintptr)ent + id,\n\t\t\t\tr * CTimeCycle::GetSpriteBrightness() * 0.7f,\n\t\t\t\tg * CTimeCycle::GetSpriteBrightness() * 0.7f,\n\t\t\t\t0 * CTimeCycle::GetSpriteBrightness() * 0.7f,\n\t\t\t\t255,\n\t\t\t\tpos1, 1.75f * CTimeCycle::GetSpriteSize(), 50.0f,\n\t\t\t\tCCoronas::TYPE_STAR, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON,\n\t\t\t\tCCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);\n\t}\n\telse if (MI_TRAFFICLIGHTS_MIAMI == m || MI_TRAFFICLIGHTS_TWOVERTICAL == m) {\n\t\tCBaseModelInfo* mi = CModelInfo::GetModelInfo(ent->GetModelIndex());\n\t\tCVector pos1, pos2;\n\t\tuint8 r, g;\n\t\tint id;\n\t\tif (MI_TRAFFICLIGHTS_MIAMI == m) {\n\t\t\tswitch (phase) {\n\t\t\tcase CAR_LIGHTS_GREEN:\n\t\t\t\tr = 0;\n\t\t\t\tg = 255;\n\t\t\t\tpos1 = ent->GetMatrix() * mi->Get2dEffect(4)->pos;\n\t\t\t\tpos2 = ent->GetMatrix() * mi->Get2dEffect(5)->pos;\n\t\t\t\tid = 0;\n\t\t\t\tbreak;\n\t\t\tcase CAR_LIGHTS_YELLOW:\n\t\t\t\tr = 255;\n\t\t\t\tg = 128;\n\t\t\t\tpos1 = ent->GetMatrix() * mi->Get2dEffect(2)->pos;\n\t\t\t\tpos2 = ent->GetMatrix() * mi->Get2dEffect(3)->pos;\n\t\t\t\tid = 1;\n\t\t\t\tbreak;\n\t\t\tcase CAR_LIGHTS_RED:\n\t\t\t\tr = 255;\n\t\t\t\tg = 0;\n\t\t\t\tpos1 = ent->GetMatrix() * mi->Get2dEffect(0)->pos;\n\t\t\t\tpos2 = ent->GetMatrix() * mi->Get2dEffect(1)->pos;\n\t\t\t\tid = 2;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tr = 0;\n\t\t\t\tg = 0;\n\t\t\t\tpos1 = ent->GetMatrix() * mi->Get2dEffect(2)->pos;\n\t\t\t\tpos2 = ent->GetMatrix() * mi->Get2dEffect(3)->pos;\n\t\t\t\tid = -1;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tswitch (phase) {\n\t\t\tcase CAR_LIGHTS_GREEN:\n\t\t\t\tr = 0;\n\t\t\t\tg = 255;\n\t\t\t\tpos1 = ent->GetMatrix() * mi->Get2dEffect(2)->pos;\n\t\t\t\tpos2 = ent->GetMatrix() * mi->Get2dEffect(5)->pos;\n\t\t\t\tid = 0;\n\t\t\t\tbreak;\n\t\t\tcase CAR_LIGHTS_YELLOW:\n\t\t\t\tr = 255;\n\t\t\t\tg = 128;\n\t\t\t\tpos1 = ent->GetMatrix() * mi->Get2dEffect(1)->pos;\n\t\t\t\tpos2 = ent->GetMatrix() * mi->Get2dEffect(4)->pos;\n\t\t\t\tid = 1;\n\t\t\t\tbreak;\n\t\t\tcase CAR_LIGHTS_RED:\n\t\t\t\tr = 255;\n\t\t\t\tg = 0;\n\t\t\t\tpos1 = ent->GetMatrix() * mi->Get2dEffect(0)->pos;\n\t\t\t\tpos2 = ent->GetMatrix() * mi->Get2dEffect(3)->pos;\n\t\t\t\tid = 2;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tr = 0;\n\t\t\t\tg = 0;\n\t\t\t\tpos1 = ent->GetMatrix() * mi->Get2dEffect(1)->pos;\n\t\t\t\tpos2 = ent->GetMatrix() * mi->Get2dEffect(4)->pos;\n\t\t\t\tid = -1;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tCVector pos = (pos1 + pos2) / 2;\n\t\tif (id >= 0) {\n\t\t\tCBrightLights::RegisterOne(pos1, ent->GetUp(), ent->GetRight(), CVector(0.0f, 0.0f, 0.0f), id + BRIGHTLIGHT_TRAFFIC_GREEN);\n\t\t\tCBrightLights::RegisterOne(pos2, ent->GetUp(), ent->GetRight(), CVector(0.0f, 0.0f, 0.0f), id + BRIGHTLIGHT_TRAFFIC_GREEN);\n\t\t}\n\n\t\tif (CWeather::TrafficLightBrightness > 0.5f)\n\t\t\tCPointLights::AddLight(CPointLights::LIGHT_POINT,\n\t\t\t\tpos, CVector(0.0f, 0.0f, 0.0f), 8.0f,\n\t\t\t\tr / 255.0f, g / 255.0f, 0 / 255.0f, CPointLights::FOG_NORMAL, true);\n\n\t\tif (CWeather::TrafficLightBrightness > 0.05f)\n\t\t\tCShadows::StoreStaticShadow((uintptr)ent,\n\t\t\t\tSHADOWTYPE_ADDITIVE, gpShadowExplosionTex, &pos,\n\t\t\t\t8.0f, 0.0f, 0.0f, -8.0f, 128,\n\t\t\t\tr * CTimeCycle::GetLightOnGroundBrightness() * CWeather::TrafficLightBrightness / 8.0f,\n\t\t\t\tg * CTimeCycle::GetLightOnGroundBrightness() * CWeather::TrafficLightBrightness / 8.0f,\n\t\t\t\t0 * CTimeCycle::GetLightOnGroundBrightness() * CWeather::TrafficLightBrightness / 8.0f,\n\t\t\t\t12.0f, 1.0f, 40.0f, false, 0.0f);\n\n\t\tif (id >= 0) {\n\t\t\tif (DotProduct(TheCamera.GetForward(), ent->GetForward()) < 0.0f)\n\t\t\t\tCCoronas::RegisterCorona((uintptr)ent + id,\n\t\t\t\t\tr * CTimeCycle::GetSpriteBrightness() * 0.7f,\n\t\t\t\t\tg * CTimeCycle::GetSpriteBrightness() * 0.7f,\n\t\t\t\t\t0 * CTimeCycle::GetSpriteBrightness() * 0.7f,\n\t\t\t\t\t255,\n\t\t\t\t\tpos1, 1.75f * CTimeCycle::GetSpriteSize(), 50.0f,\n\t\t\t\t\tCCoronas::TYPE_STAR, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON,\n\t\t\t\t\tCCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);\n\t\t\telse\n\t\t\t\tCCoronas::RegisterCorona((uintptr)ent + id,\n\t\t\t\t\tr * CTimeCycle::GetSpriteBrightness() * 0.7f,\n\t\t\t\t\tg * CTimeCycle::GetSpriteBrightness() * 0.7f,\n\t\t\t\t\t0 * CTimeCycle::GetSpriteBrightness() * 0.7f,\n\t\t\t\t\t255,\n\t\t\t\t\tpos2, 1.75f * CTimeCycle::GetSpriteSize(), 50.0f,\n\t\t\t\t\tCCoronas::TYPE_STAR, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON,\n\t\t\t\t\tCCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);\n\t\t}\n\t}\n}\n\nbool DoesLineSegmentIntersect(float l1x1, float l1y1, float l1x2, float l1y2, float l2x1, float l2y1, float l2x2, float l2y2)\n{\n\treturn ((l2y2 - l1y1) * (l1x2 - l1x1) + (l1x1 - l2x2) * (l1y2 - l1y1)) *\n\t\t((l2y1 - l1y1) * (l1x2 - l1x1) + (l1x1 - l2x1) * (l1y2 - l1y1)) <= 0.0f &&\n\t\t((l1y2 - l2y1) * (l2x2 - l2x1) + (l2y2 - l2y1) * (l2x1 - l1x2)) *\n\t\t((l1y1 - l2y1) * (l2x2 - l2x1) + (l2y2 - l2y1) * (l2x1 - l1x1)) <= 0.0f;\n}\n\nvoid\nCTrafficLights::ScanForLightsOnMap(void)\n{\n\tint x, y;\n\tint i, j, k, l;\n\tCPtrNode *node;\n\n\tfor(x = 0; x < NUMSECTORS_X; x++)\n\tfor(y = 0; y < NUMSECTORS_Y; y++){\n\t\tCPtrList &list = CWorld::GetSector(x, y)->m_lists[ENTITYLIST_DUMMIES];\n\t\tfor(node = list.first; node; node = node->next){\n\t\t\tCEntity *light = (CEntity*)node->item;\n\t\t\tif (!IsTrafficLight(light->GetModelIndex()))\n\t\t\t\tcontinue;\n\n\t\t\tCVector pos1 = light->GetMatrix() * CVector(17.0f, 0.0f, 0.0f);\n\t\t\tCVector pos2 = light->GetMatrix() * CVector(-15.0f, 0.0f, 0.0f);\n\n\t\t\t// Check cars\n\t\t\tfor(i = 0; i < ThePaths.m_numCarPathNodes; i++){\n\t\t\t\tif ((ThePaths.m_pathNodes[i].GetPosition() - pos1).MagnitudeSqr() >= SQR(100.0f))\n\t\t\t\t\tcontinue;\n\t\t\t\tfor (j = 0; j < ThePaths.m_pathNodes[i].numLinks; j++){\n\t\t\t\t\tint con = ThePaths.ConnectedNode(ThePaths.m_pathNodes[i].firstLink + j);\n\t\t\t\t\tif (i < con) {\n\t\t\t\t\t\tCVector i_pos = ThePaths.m_pathNodes[i].GetPosition();\n\t\t\t\t\t\tCVector con_pos = ThePaths.m_pathNodes[con].GetPosition();\n\t\t\t\t\t\tif (Abs(pos1.z - (i_pos.z + con_pos.z) / 2) < 10.0f &&\n\t\t\t\t\t\t\tDoesLineSegmentIntersect(pos1.x, pos1.y, pos2.x, pos2.y, i_pos.x, i_pos.y, con_pos.x, con_pos.y)) {\n\t\t\t\t\t\t\t//debug(\"Setting up light: nodes %f %f %f - %f %f %f, light %f %f %f - %f %f %f\\n\", i_pos.x, i_pos.y, i_pos.z, con_pos.x, con_pos.y, con_pos.z, pos1.x, pos1.y, pos1.z, pos2.x, pos2.y, pos2.z);\n\t\t\t\t\t\t\tint link = ThePaths.m_carPathConnections[ThePaths.m_pathNodes[i].firstLink + j];\n\t\t\t\t\t\t\tThePaths.m_carPathLinks[link].trafficLightType = FindTrafficLightType(light);\n\t\t\t\t\t\t\tif (ThePaths.m_pathNodes[i].numLinks > ThePaths.m_pathNodes[con].numLinks)\n\t\t\t\t\t\t\t\tcon = i;\n\t\t\t\t\t\t\tif (ThePaths.m_carPathLinks[link].pathNodeIndex != con)\n\t\t\t\t\t\t\t\tThePaths.m_carPathLinks[link].trafficLightDirection = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Check peds\n\t\t\tfor(i = ThePaths.m_numCarPathNodes; i < ThePaths.m_numPathNodes; i++){\n\t\t\t\tfloat dist1, dist2;\n\t\t\t\tdist1 = Abs(ThePaths.m_pathNodes[i].GetX() - light->GetPosition().x) +\n\t\t\t\t\tAbs(ThePaths.m_pathNodes[i].GetY() - light->GetPosition().y);\n\t\t\t\tif(dist1 < 50.0f){\n\t\t\t\t\tfor(l = 0; l < ThePaths.m_pathNodes[i].numLinks; l++){\n\t\t\t\t\t\tj = ThePaths.m_pathNodes[i].firstLink + l;\n\t\t\t\t\t\tif(ThePaths.ConnectionCrossesRoad(j)){\n\t\t\t\t\t\t\tk = ThePaths.ConnectedNode(j);\n\t\t\t\t\t\t\tdist2 = Abs(ThePaths.m_pathNodes[k].GetX() - light->GetPosition().x) +\n\t\t\t\t\t\t\t\tAbs(ThePaths.m_pathNodes[k].GetY() - light->GetPosition().y);\n\t\t\t\t\t\t\tif(dist1 < 15.0f || dist2 < 15.0f)\n\t\t\t\t\t\t\t\tThePaths.ConnectionSetTrafficLight(j);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nbool\nCTrafficLights::ShouldCarStopForLight(CVehicle *vehicle, bool alwaysStop)\n{\n\tint node, type;\n\tbool direction;\n\n\tnode = vehicle->AutoPilot.m_nNextPathNodeInfo;\n\ttype = ThePaths.m_carPathLinks[node].trafficLightType;\n\tdirection = ThePaths.m_carPathLinks[node].trafficLightDirection;\n\n\tif(type){\n\t\tif((direction || ThePaths.m_carPathLinks[node].pathNodeIndex == vehicle->AutoPilot.m_nNextRouteNode) &&\n\t\t   (!direction || ThePaths.m_carPathLinks[node].pathNodeIndex != vehicle->AutoPilot.m_nNextRouteNode))\n\t\t\tif(alwaysStop ||\n\t\t\t   type == 1 && LightForCars1() != CAR_LIGHTS_GREEN ||\n\t\t\t   type == 2 && LightForCars2() != CAR_LIGHTS_GREEN){\n\t\t\t\tfloat dist = DotProduct2D(CVector2D(vehicle->GetPosition()) - ThePaths.m_carPathLinks[node].GetPosition(),\n\t\t\t\t\t\tThePaths.m_carPathLinks[node].GetDirection());\n\t\t\t\tif(vehicle->AutoPilot.m_nNextDirection == -1){\n\t\t\t\t\tif(dist > 0.0f && dist < 8.0f)\n\t\t\t\t\t\treturn true;\n\t\t\t\t}else{\n\t\t\t\t\tif(dist < 0.0f && dist > -8.0f)\n\t\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t}\n\n\tnode = vehicle->AutoPilot.m_nCurrentPathNodeInfo;\n\ttype = ThePaths.m_carPathLinks[node].trafficLightType;\n\tdirection = ThePaths.m_carPathLinks[node].trafficLightDirection;\n\tif(type){\n\t\tif((direction || ThePaths.m_carPathLinks[node].pathNodeIndex == vehicle->AutoPilot.m_nCurrentRouteNode) &&\n\t\t   (!direction || ThePaths.m_carPathLinks[node].pathNodeIndex != vehicle->AutoPilot.m_nCurrentRouteNode))\n\t\t\tif(alwaysStop ||\n\t\t\t   type == 1 && LightForCars1() != CAR_LIGHTS_GREEN ||\n\t\t\t   type == 2 && LightForCars2() != CAR_LIGHTS_GREEN){\n\t\t\t\tfloat dist = DotProduct2D(CVector2D(vehicle->GetPosition()) - ThePaths.m_carPathLinks[node].GetPosition(),\n\t\t\t\t\t\tThePaths.m_carPathLinks[node].GetDirection());\n\t\t\t\tif(vehicle->AutoPilot.m_nCurrentDirection == -1){\n\t\t\t\t\tif(dist > 0.0f && dist < 8.0f)\n\t\t\t\t\t\treturn true;\n\t\t\t\t}else{\n\t\t\t\t\tif(dist < 0.0f && dist > -8.0f)\n\t\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t}\n\n\tif(vehicle->GetStatus() == STATUS_PHYSICS){\n\t\tnode = vehicle->AutoPilot.m_nPreviousPathNodeInfo;\n\t\ttype = ThePaths.m_carPathLinks[node].trafficLightType;\n\t\tdirection = ThePaths.m_carPathLinks[node].trafficLightDirection;\n\t\tif(type){\n\t\t\tif((direction || ThePaths.m_carPathLinks[node].pathNodeIndex == vehicle->AutoPilot.m_nPrevRouteNode) &&\n\t\t\t   (!direction || ThePaths.m_carPathLinks[node].pathNodeIndex != vehicle->AutoPilot.m_nPrevRouteNode))\n\t\t\t\tif(alwaysStop ||\n\t\t\t\t   type == 1 && LightForCars1() != CAR_LIGHTS_GREEN ||\n\t\t\t\t   type == 2 && LightForCars2() != CAR_LIGHTS_GREEN){\n\t\t\t\t\tfloat dist = DotProduct2D(CVector2D(vehicle->GetPosition()) - ThePaths.m_carPathLinks[node].GetPosition(),\n\t\t\t\t\t\t\tThePaths.m_carPathLinks[node].GetDirection());\n\t\t\t\t\tif(vehicle->AutoPilot.m_nPreviousDirection == -1){\n\t\t\t\t\t\tif(dist > 0.0f && dist < 6.0f)\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t}else{\n\t\t\t\t\t\tif(dist < 0.0f && dist > -6.0f)\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t}\n\t}\n\n\treturn false;\n}\n\nbool\nCTrafficLights::ShouldCarStopForBridge(CVehicle *vehicle)\n{\n#ifdef GTA_BRIDGE\n\treturn ThePaths.m_carPathLinks[vehicle->AutoPilot.m_nNextPathNodeInfo].bBridgeLights &&\n\t\t!ThePaths.m_carPathLinks[vehicle->AutoPilot.m_nCurrentPathNodeInfo].bBridgeLights;\n#else\n\treturn false;\n#endif\n}\n\nint\nCTrafficLights::FindTrafficLightType(CEntity *light)\n{\n\tfloat orientation = RADTODEG(CGeneral::GetATanOfXY(light->GetForward().x, light->GetForward().y));\n\tif((orientation > 60.0f && orientation < 60.0f + 90.0f) ||\n\t   (orientation > 240.0f && orientation < 240.0f + 90.0f))\n\t\treturn 1;\n\treturn 2;\n}\n\nuint8\nCTrafficLights::LightForPeds(void)\n{\n\tuint32 period = CTimer::GetTimeInMilliseconds() % 16384;\n\n\tif(period < 12000)\n\t\treturn PED_LIGHTS_DONT_WALK;\n\telse if(period < 16384 - 1000)\n\t\treturn PED_LIGHTS_WALK;\n\telse\n\t\treturn PED_LIGHTS_WALK_BLINK;\n}\n\nuint8\nCTrafficLights::LightForCars1(void)\n{\n\tif (CWeather::Wind > 1.1f)\n\t\treturn CAR_LIGHTS_GREEN;\n\n\tif (bGreenLightsCheat)\n\t\treturn CAR_LIGHTS_GREEN;\n\n\tuint32 period = CTimer::GetTimeInMilliseconds() % 16384;\n\n\tif(period < 5000)\n\t\treturn CAR_LIGHTS_GREEN;\n\telse if(period < 5000 + 1000)\n\t\treturn CAR_LIGHTS_YELLOW;\n\telse\n\t\treturn CAR_LIGHTS_RED;\n}\n\nuint8\nCTrafficLights::LightForCars2(void)\n{\n\tif (CWeather::Wind > 1.1f)\n\t\treturn CAR_LIGHTS_GREEN;\n\n\tif (bGreenLightsCheat)\n\t\treturn CAR_LIGHTS_GREEN;\n\n\tuint32 period = CTimer::GetTimeInMilliseconds() % 16384;\n\n\tif(period < 6000)\n\t\treturn CAR_LIGHTS_RED;\n\telse if(period < 12000 - 1000)\n\t\treturn CAR_LIGHTS_GREEN;\n\telse if(period < 12000)\n\t\treturn CAR_LIGHTS_YELLOW;\n\telse\n\t\treturn CAR_LIGHTS_RED;\n}\n\nuint8\nCTrafficLights::LightForCars1_Visual(void)\n{\n\tif (CWeather::Wind <= 1.1f)\n\t\treturn LightForCars1();\n\treturn (CTimer::GetTimeInMilliseconds() & 0x400 ? CAR_LIGHTS_NONE : CAR_LIGHTS_YELLOW);\n}\n\nuint8\nCTrafficLights::LightForCars2_Visual(void)\n{\n\tif (CWeather::Wind <= 1.1f)\n\t\treturn LightForCars2();\n\treturn (CTimer::GetTimeInMilliseconds() & 0x400 ? CAR_LIGHTS_NONE : CAR_LIGHTS_YELLOW);\n}\n"
  },
  {
    "path": "src/control/TrafficLights.h",
    "content": "#pragma once\n\nclass CEntity;\nclass CVehicle;\n\nenum {\n\tPED_LIGHTS_WALK,\n\tPED_LIGHTS_WALK_BLINK,\n\tPED_LIGHTS_DONT_WALK,\n\n\tCAR_LIGHTS_GREEN = 0,\n\tCAR_LIGHTS_YELLOW,\n\tCAR_LIGHTS_RED,\n\tCAR_LIGHTS_NONE\n};\n\nclass CTrafficLights\n{\npublic:\n\tstatic bool bGreenLightsCheat;\n\n\tstatic void DisplayActualLight(CEntity *ent);\n\tstatic void ScanForLightsOnMap(void);\n\tstatic int FindTrafficLightType(CEntity *light);\n\tstatic uint8 LightForPeds(void);\n\tstatic uint8 LightForCars1(void);\n\tstatic uint8 LightForCars2(void);\n\tstatic uint8 LightForCars1_Visual(void);\n\tstatic uint8 LightForCars2_Visual(void);\n\tstatic bool ShouldCarStopForLight(CVehicle*, bool);\n\tstatic bool ShouldCarStopForBridge(CVehicle*);\n};\n"
  },
  {
    "path": "src/core/Accident.cpp",
    "content": "#include \"common.h\"\n\n#include \"Accident.h\"\n\n#include \"Ped.h\"\n#include \"Pools.h\"\n#include \"World.h\"\n\nCAccidentManager gAccidentManager;\n\nCAccident*\nCAccidentManager::GetNextFreeAccident()\n{\n\tfor (int i = 0; i < NUM_ACCIDENTS; i++) {\n\t\tif (m_aAccidents[i].m_pVictim == nil)\n\t\t\treturn &m_aAccidents[i];\n\t}\n\n\treturn nil;\n}\n\nvoid\nCAccidentManager::ReportAccident(CPed *ped)\n{\n\tif (!ped->IsPlayer() && ped->CharCreatedBy != MISSION_CHAR && !ped->bRenderScorched && !ped->bBodyPartJustCameOff && ped->bAllowMedicsToReviveMe && !ped->bIsInWater) {\n\t\tfor (int i = 0; i < NUM_ACCIDENTS; i++) {\n\t\t\tif (m_aAccidents[i].m_pVictim != nil && m_aAccidents[i].m_pVictim == ped)\n\t\t\t\treturn;\n\t\t}\n\n\t\tif (ped->m_pCurrentPhysSurface == nil) {\n\t\t\tCVector point = ped->GetPosition();\n\t\t\tpoint.z -= 2.0f;\n\n\t\t\tCColPoint colPoint;\n\t\t\tCEntity *pEntity; \n\n\t\t\tif (!CWorld::ProcessVerticalLine(point, -100.0f, colPoint, pEntity, true, false, false, false, false, false, nil)) {\n\t\t\t\tCAccident *accident = GetNextFreeAccident();\n\t\t\t\tif (accident != nil) {\n\t\t\t\t\taccident->m_pVictim = ped;\n\t\t\t\t\tped->RegisterReference((CEntity**)&accident->m_pVictim);\n\t\t\t\t\taccident->m_nMedicsPerformingCPR = 0;\n\t\t\t\t\taccident->m_nMedicsAttending = 0;\n\t\t\t\t\tped->m_lastAccident = accident;\n\t\t\t\t\tWorkToDoForMedics();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nCAccidentManager::Update()\n{\n#ifdef SQUEEZE_PERFORMANCE\n\t// Handled after injury registered.\n\treturn;\n#endif\n\tint32 e;\n\tif (CEventList::GetEvent(EVENT_INJURED_PED, &e)) {\n\t\tCPed *ped = CPools::GetPed(gaEvent[e].entityRef);\n\t\tif (ped) {\n\t\t\tReportAccident(ped);\n\t\t\tCEventList::ClearEvent(e);\n\t\t}\n\t}\n}\n\nCAccident*\nCAccidentManager::FindNearestAccident(CVector vecPos, float *pDistance)\n{\n\tfor (int i = 0; i < MAX_MEDICS_TO_ATTEND_ACCIDENT; i++){\n\t\tint accidentId = -1;\n\t\tfloat minDistance = 999999;\n\t\tfor (int j = 0; j < NUM_ACCIDENTS; j++){\n\t\t\tCPed* pVictim = m_aAccidents[j].m_pVictim;\n\t\t\tif (!pVictim)\n\t\t\t\tcontinue;\n\t\t\tif (pVictim->CharCreatedBy == MISSION_CHAR)\n\t\t\t\tcontinue;\n\t\t\tif (pVictim->m_fHealth != 0.0f)\n\t\t\t\tcontinue;\n\t\t\tif (m_aAccidents[j].m_nMedicsPerformingCPR != i)\n\t\t\t\tcontinue;\n\t\t\tfloat distance = (pVictim->GetPosition() - vecPos).Magnitude2D();\n\t\t\tif (distance / 2 > pVictim->GetPosition().z - vecPos.z && distance < minDistance){\n\t\t\t\tminDistance = distance;\n\t\t\t\taccidentId = j;\n\t\t\t}\n\t\t}\n\t\t*pDistance = minDistance;\n\t\tif (accidentId != -1)\n\t\t\treturn &m_aAccidents[accidentId];\n\t}\n\treturn nil;\n}\n\nuint16\nCAccidentManager::CountActiveAccidents()\n{\n\tuint16 accidents = 0;\n\tfor (int i = 0; i < NUM_ACCIDENTS; i++) {\n\t\tif (m_aAccidents[i].m_pVictim)\n\t\t\taccidents++;\n\t}\n\treturn accidents;\n}\n\nbool\nCAccidentManager::WorkToDoForMedics()\n{\n\tfor (int i = 0; i < NUM_ACCIDENTS; i++) {\n\t\tif (m_aAccidents[i].m_pVictim != nil && m_aAccidents[i].m_nMedicsAttending < MAX_MEDICS_TO_ATTEND_ACCIDENT)\n\t\t\treturn true;\n\t}\n\treturn false;\n}\n\nbool\nCAccidentManager::UnattendedAccidents()\n{\n\tfor (int i = 0; i < NUM_ACCIDENTS; i++) {\n\t\tif (m_aAccidents[i].m_pVictim != nil && m_aAccidents[i].m_nMedicsAttending == 0)\n\t\t\treturn true;\n\t}\n\treturn false;\n}\n"
  },
  {
    "path": "src/core/Accident.h",
    "content": "#pragma once\n#include \"config.h\"\n\nclass CPed;\n\nclass CAccident\n{\npublic:\n\tCPed *m_pVictim;\n\tuint32 m_nMedicsAttending;\n\tuint32 m_nMedicsPerformingCPR;\n\tCAccident() : m_pVictim(nil), m_nMedicsAttending(0), m_nMedicsPerformingCPR(0) {}\n};\n\nclass CAccidentManager\n{\n\tCAccident m_aAccidents[NUM_ACCIDENTS];\n\tenum {\n\t\tMAX_MEDICS_TO_ATTEND_ACCIDENT = 2\n\t};\npublic:\n\tCAccident *GetNextFreeAccident();\n\tvoid ReportAccident(CPed *ped);\n\tvoid Update();\n\tCAccident *FindNearestAccident(CVector vecPos, float *pDistance);\n\tuint16 CountActiveAccidents();\n\tbool UnattendedAccidents();\n\tbool WorkToDoForMedics();\n};\n\nextern CAccidentManager gAccidentManager;"
  },
  {
    "path": "src/core/AnimViewer.cpp",
    "content": "#include \"common.h\"\n\n#include \"Font.h\"\n#include \"Pad.h\"\n#include \"Text.h\"\n#include \"main.h\"\n#include \"Timer.h\"\n#include \"DMAudio.h\"\n#include \"FileMgr.h\"\n#include \"Streaming.h\"\n#include \"TxdStore.h\"\n#include \"General.h\"\n#include \"Camera.h\"\n#include \"Vehicle.h\"\n#include \"Bike.h\"\n#include \"PlayerSkin.h\"\n#include \"PlayerInfo.h\"\n#include \"World.h\"\n#include \"Renderer.h\"\n#include \"AnimManager.h\"\n#include \"AnimBlendAssocGroup.h\"\n#include \"AnimViewer.h\"\n#include \"PlayerPed.h\"\n#include \"Pools.h\"\n#include \"References.h\"\n#include \"PathFind.h\"\n#include \"HandlingMgr.h\"\n#include \"TempColModels.h\"\n#include \"Particle.h\"\n#include \"CdStream.h\"\n#include \"Messages.h\"\n#include \"CarCtrl.h\"\n#include \"FileLoader.h\"\n#include \"ModelIndices.h\"\n#include \"Clock.h\"\n#include \"Timecycle.h\"\n#include \"RpAnimBlend.h\"\n#include \"AnimBlendAssociation.h\"\n#include \"Shadows.h\"\n#include \"Radar.h\"\n#include \"Hud.h\"\n#include \"debugmenu.h\"\n\nint CAnimViewer::animTxdSlot = 0;\nCEntity *CAnimViewer::pTarget = nil;\n\nvoid\nCAnimViewer::Render(void) {\n\tif (pTarget) {\n\t\tif (pTarget) {\n#ifdef FIX_BUGS\n\t\t\tif(pTarget->IsPed())\n\t\t\t\t((CPed*)pTarget)->UpdateRpHAnim();\n#endif\n\t\t\tpTarget->Render();\n\t\t\tCRenderer::RenderOneNonRoad(pTarget);\n\t\t}\n\t}\n}\n\nvoid\nCAnimViewer::Initialise(void) {\n\n\t// we need messages, messages needs hud, hud needs those\n\tint hudSlot = CTxdStore::AddTxdSlot(\"hud\");\n\tCTxdStore::LoadTxd(hudSlot, \"MODELS/HUD.TXD\");\n\tCHud::m_Wants_To_Draw_Hud = false;\n\n\tanimTxdSlot = CTxdStore::AddTxdSlot(\"generic\");\n\tCTxdStore::Create(animTxdSlot);\n\tint particleSlot = CTxdStore::AddTxdSlot(\"particle\");\n\tCTxdStore::LoadTxd(particleSlot, \"MODELS/PARTICLE.TXD\");\n\tCTxdStore::SetCurrentTxd(animTxdSlot);\n\tCPools::Initialise();\n\tCReferences::Init();\n\tTheCamera.Init();\n\tTheCamera.SetRwCamera(Scene.camera);\n\tTheCamera.Cams[TheCamera.ActiveCam].Distance = 5.0f;\n\tThePaths.Init();\n\tThePaths.AllocatePathFindInfoMem(4500);\n\tCCollision::Init();\n\tCWorld::Initialise();\n\tmod_HandlingManager.Initialise();\n\tCTempColModels::Initialise();\n\tCAnimManager::Initialise();\n\tCModelInfo::Initialise();\n\tCParticle::Initialise();\n\tCCarCtrl::Init();\n\tCPedStats::Initialise();\n\tCMessages::Init();\n\tCdStreamAddImage(\"MODELS\\\\GTA3.IMG\");\n\tCFileLoader::LoadLevel(\"DATA\\\\DEFAULT.DAT\");\n\tCFileLoader::LoadLevel(\"DATA\\\\ANIMVIEWER.DAT\");\n\tCStreaming::Init();\n\tfor(int i = 0; i < MODELINFOSIZE; i++)\n\t\tif(CModelInfo::GetModelInfo(i))\n\t\t\tCModelInfo::GetModelInfo(i)->ConvertAnimFileIndex();\n\tCStreaming::LoadInitialPeds();\n\tCStreaming::RequestSpecialModel(MI_PLAYER, \"player\", STREAMFLAGS_DONT_REMOVE);\n\tCStreaming::LoadAllRequestedModels(false);\n\tCRenderer::Init();\n\tCVehicleModelInfo::LoadVehicleColours();\n#ifdef FIX_BUGS\n\tCVehicleModelInfo::LoadEnvironmentMaps();\n#endif\n\tCAnimManager::LoadAnimFiles();\n\tCWorld::PlayerInFocus = 0;\n\tCWeapon::InitialiseWeapons();\n\tCPed::Initialise();\n\tCTimer::Initialise();\n\tCClock::Initialise(60000);\n\tCTimeCycle::Initialise();\n\tCCarCtrl::Init();\n\tCPlayerPed *player = new CPlayerPed();\n\tplayer->SetPosition(1000.0f, 1000.0f, 1000.0f);\n\tCWorld::Players[0].m_pPed = player;\n\tCDraw::SetFOV(120.0f);\n\tCDraw::ms_fLODDistance = 500.0f;\n\n\tint fd = CFileMgr::OpenFile(\"DATA\\\\SPECIAL.TXT\", \"r\");\n\tchar animGroup[32], modelName[32];\n\tif (fd) {\n\t\tfor (int lineId = 0; lineId < NUM_OF_SPECIAL_CHARS; lineId++) {\n\t\t\tif (!CFileMgr::ReadLine(fd, gString, 255))\n\t\t\t\tbreak;\n\n\t\t\tsscanf(gString, \"%s %s\", modelName, animGroup);\n\t\t\tint groupId;\n\t\t\tfor (groupId = 0; groupId < NUM_ANIM_ASSOC_GROUPS; groupId++) {\n\t\t\t\tif (!strcmp(animGroup, CAnimManager::GetAnimGroupName((AssocGroupId)groupId)))\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tif (groupId != NUM_ANIM_ASSOC_GROUPS)\n\t\t\t\t((CPedModelInfo*)CModelInfo::GetModelInfo(MI_SPECIAL01 + lineId))->m_animGroup = groupId;\n\n\t\t\tCStreaming::RequestSpecialChar(lineId, modelName, STREAMFLAGS_DONT_REMOVE);\n\t\t}\n\t\tCFileMgr::CloseFile(fd);\n\t} else {\n\t\t// TODO? maybe request some special models here so the thing doesn't crash\n\t}\n\n\t// From LCS. idk if needed\n\tint vanBlock = CAnimManager::GetAnimationBlockIndex(\"van\");\n\tint bikesBlock = CAnimManager::GetAnimationBlockIndex(\"bikes\");\n\tint bikevBlock = CAnimManager::GetAnimationBlockIndex(\"bikev\");\n\tint bikehBlock = CAnimManager::GetAnimationBlockIndex(\"bikeh\");\n\tint bikedBlock = CAnimManager::GetAnimationBlockIndex(\"biked\");\n\tCStreaming::FlushRequestList();\n\tCStreaming::RequestAnim(vanBlock, STREAMFLAGS_DEPENDENCY);\n\tCStreaming::RequestAnim(bikesBlock, STREAMFLAGS_DEPENDENCY);\n\tCStreaming::RequestAnim(bikevBlock, STREAMFLAGS_DEPENDENCY);\n\tCStreaming::RequestAnim(bikehBlock, STREAMFLAGS_DEPENDENCY);\n\tCStreaming::RequestAnim(bikedBlock, STREAMFLAGS_DEPENDENCY);\n\tCStreaming::LoadAllRequestedModels(false);\n\tCAnimManager::AddAnimBlockRef(vanBlock);\n\tCAnimManager::AddAnimBlockRef(bikesBlock);\n\tCAnimManager::AddAnimBlockRef(bikevBlock);\n\tCAnimManager::AddAnimBlockRef(bikehBlock);\n\tCAnimManager::AddAnimBlockRef(bikedBlock);\n}\n\nint\nLastPedModelId(int modelId)\n{\n\tCBaseModelInfo *model;\n\tfor(;;){\n\t\tassert(modelId < MODELINFOSIZE);\n\t\tmodel = CModelInfo::GetModelInfo(modelId);\n\t\tif (model && model->GetModelType() == MITYPE_PED)\n\t\t\tbreak;\n\t\tmodelId--;\n\t}\n\treturn modelId;\n}\n\nint\nFirstCarModelId(int modelId)\n{\n\tCBaseModelInfo *model;\n\tfor(;;){\n\t\tassert(modelId < MODELINFOSIZE);\n\t\tmodel = CModelInfo::GetModelInfo(modelId);\n\t\tif (model && model->GetModelType() == MITYPE_VEHICLE)\n\t\t\tbreak;\n\t\tmodelId++;\n\t}\n\treturn modelId;\n}\n\n\nint\nNextModelId(int modelId, int wantedChange)\n{\n\t// Max. 2 trials wasn't here, it's me that added it.\n\n\tint tryCount = 2;\n\tint ogModelId = modelId;\n\n\twhile(tryCount != 0) {\n\t\tmodelId += wantedChange;\n\t\tif (modelId < 0 || modelId >= MODELINFOSIZE) {\n\t\t\ttryCount--;\n\t\t\twantedChange = -wantedChange;\n\t\t} else if (modelId != 5 && modelId != 6 && modelId != 405) {\n\t\t\tCBaseModelInfo *model = CModelInfo::GetModelInfo(modelId);\n\t\t\tif (model)\n\t\t\t{\n\t\t\t\t//int type = model->m_type;\n\t\t\t\treturn modelId;\n\t\t\t}\n\t\t}\n\t}\n\treturn ogModelId;\n}\n\nvoid\nPlayAnimation(RpClump *clump, AssocGroupId animGroup, AnimationId anim)\n{\n\tCAnimBlendAssociation *currentAssoc = RpAnimBlendClumpGetAssociation(clump, anim);\n\n\tif (currentAssoc && currentAssoc->IsPartial())\n\t\tdelete currentAssoc;\n\n\tRpAnimBlendClumpSetBlendDeltas(clump, ASSOC_PARTIAL, -8.0f);\n\n\tCAnimBlendAssociation *animAssoc = CAnimManager::BlendAnimation(clump, animGroup, anim, 8.0f);\n\tanimAssoc->flags |= ASSOC_DELETEFADEDOUT;\n\tanimAssoc->SetCurrentTime(0.0f);\n\tanimAssoc->SetRun();\n}\n\nvoid\nCAnimViewer::Update(void)\n{\n\tstatic int modelId = 0;\n\tstatic int animId = 0;\n\tstatic bool reloadIFP = false;\n\n\tAssocGroupId animGroup = ASSOCGRP_STD;\n\tint nextModelId = modelId;\n\tCBaseModelInfo *modelInfo = CModelInfo::GetModelInfo(modelId);\n\n\tif (modelInfo->GetModelType() == MITYPE_PED) {\n\t\tint animGroup = ((CPedModelInfo*)modelInfo)->m_animGroup;\n\n\t\tif (animId > ANIM_STD_IDLE)\n\t\t\tanimGroup = ASSOCGRP_STD;\n\n\t\tif (reloadIFP) {\n\t\t\tif (pTarget) {\n\t\t\t\tCWorld::Remove(pTarget);\n\t\t\t\tif (pTarget)\n\t\t\t\t\tdelete pTarget;\n\t\t\t}\n\t\t\tpTarget = nil;\n\t\t\t\n\t\t\t// These calls were inside of LoadIFP function.\n\t\t\tCAnimManager::Shutdown();\n\t\t\tCAnimManager::Initialise();\n\t\t\tCAnimManager::LoadAnimFiles();\n\n\t\t\treloadIFP = false;\n\t\t}\n\t} else {\n\t\tanimGroup = ASSOCGRP_STD;\n\t}\n\tCPad::UpdatePads();\n\tCPad* pad = CPad::GetPad(0);\n#ifdef DEBUGMENU\n\tDebugMenuProcess();\n#endif\n\n\tCStreaming::UpdateForAnimViewer();\n\tCStreaming::RequestModel(modelId, 0);\n\tif (CStreaming::HasModelLoaded(modelId)) {\n\n\t\tif (!pTarget) {\n\n\t\t\tif (modelInfo->GetModelType() == MITYPE_VEHICLE) {\n\n\t\t\t\tCVehicleModelInfo* veh = (CVehicleModelInfo*)modelInfo;\n\t\t\t\tif (veh->m_vehicleType == VEHICLE_TYPE_CAR) {\n\t\t\t\t\tpTarget = new CAutomobile(modelId, RANDOM_VEHICLE);\n\t\t\t\t} else if (veh->m_vehicleType == VEHICLE_TYPE_BOAT) {\n\t\t\t\t\tpTarget = new CBoat(modelId, RANDOM_VEHICLE);\n\t\t\t\t} else if (veh->m_vehicleType == VEHICLE_TYPE_BIKE) {\n\t\t\t\t\tpTarget = new CBike(modelId, RANDOM_VEHICLE);\n\t\t\t\t} else {\n\t\t\t\t\tpTarget = new CObject(modelId, true);\n\t\t\t\t\tif (!modelInfo->GetColModel()) {\n\t\t\t\t\t\tmodelInfo->SetColModel(&CTempColModels::ms_colModelWheel1);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tpTarget->SetStatus(STATUS_ABANDONED);\n\t\t\t} else if (modelInfo->GetModelType() == MITYPE_PED) {\n\t\t\t\tpTarget = new CPed(PEDTYPE_CIVMALE);\n\t\t\t\tpTarget->SetModelIndex(modelId);\n\t\t\t} else {\n\t\t\t\tpTarget = new CObject(modelId, true);\n\t\t\t\tif (!modelInfo->GetColModel())\n\t\t\t\t{\n\t\t\t\t\tmodelInfo->SetColModel(&CTempColModels::ms_colModelWheel1);\n\t\t\t\t}\n\t\t\t\tpTarget->SetStatus(STATUS_ABANDONED);\n\t\t\t}\n\t\t\tpTarget->SetPosition(0.0f, 0.0f, 0.0f);\n\t\t\tCWorld::Add(pTarget);\n\t\t\tTheCamera.TakeControl(pTarget, CCam::MODE_MODELVIEW, JUMP_CUT, CAMCONTROL_SCRIPT);\n\t\t}\n\t\tif (pTarget->IsVehicle() || pTarget->IsPed() || pTarget->IsObject()) {\n\t\t\t((CPhysical*)pTarget)->m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);\n\t\t}\n#ifdef FIX_BUGS\n\t\t// so we don't end up in the water\n\t\tpTarget->GetMatrix().GetPosition().z = 10.0f;\n#else\n\t\tpTarget->GetMatrix().GetPosition().z = 0.0f;\n#endif\n\n\t\tif (modelInfo->GetModelType() == MITYPE_PED) {\n\t\t\t((CPed*)pTarget)->bKindaStayInSamePlace = true;\n\n\t\t\t// Triangle in mobile\n\t\t\tif (pad->GetSquareJustDown()) {\n\t\t\t\treloadIFP = true;\n\t\t\t\tAsciiToUnicode(\"IFP reloaded\", gUString);\n\t\t\t\tCMessages::AddMessage(gUString, 1000, 0);\n\n\t\t\t} else if (pad->GetCrossJustDown()) {\n\t\t\t\tPlayAnimation(pTarget->GetClump(), animGroup, (AnimationId)animId);\n\t\t\t\tAsciiToUnicode(\"Animation restarted\", gUString);\n\t\t\t\tCMessages::AddMessage(gUString, 1000, 0);\n\n\t\t\t} else if (pad->GetCircleJustDown()) {\n\t\t\t\tPlayAnimation(pTarget->GetClump(), animGroup, ANIM_STD_IDLE);\n\t\t\t\tAsciiToUnicode(\"Idle animation playing\", gUString);\n\t\t\t\tCMessages::AddMessage(gUString, 1000, 0);\n\n\t\t\t} else if (pad->GetDPadUpJustDown()) {\n\t\t\t\tanimId--;\n\t\t\t\tif (animId < 0) {\n\t\t\t\t\tanimId = ANIM_STD_NUM - 1;\n\t\t\t\t}\n\t\t\t\tPlayAnimation(pTarget->GetClump(), animGroup, (AnimationId)animId);\n\n\t\t\t\tsprintf(gString, \"Current anim: %d\", animId);\n\t\t\t\tAsciiToUnicode(gString, gUString);\n\t\t\t\tCMessages::AddMessage(gUString, 1000, 0);\n\n\t\t\t} else if (pad->GetDPadDownJustDown()) {\n\t\t\t\tanimId = (animId == (ANIM_STD_NUM - 1) ? 0 : animId + 1);\n\t\t\t\tPlayAnimation(pTarget->GetClump(), animGroup, (AnimationId)animId);\n\n\t\t\t\tsprintf(gString, \"Current anim: %d\", animId);\n\t\t\t\tAsciiToUnicode(gString, gUString);\n\t\t\t\tCMessages::AddMessage(gUString, 1000, 0);\n\n\t\t\t} else if (pad->GetStartJustDown()) {\n\n\t\t\t} else if (pad->GetLeftShoulder1JustDown()) {\n\t\t\t\tnextModelId = FirstCarModelId(modelId);\n\t\t\t\tAsciiToUnicode(\"Switched to vehicles\", gUString);\n\t\t\t\tCMessages::AddMessage(gUString, 1000, 0);\n\t\t\t\t// Originally it was GetPad(1)->LeftShoulder2\n\t\t\t} else if (pad->NewState.Triangle) {\n\t\t\t\t((CPedModelInfo *)CModelInfo::GetModelInfo(pTarget->GetModelIndex()))->AnimatePedColModelSkinned(pTarget->GetClump());\n\t\t\t\tAsciiToUnicode(\"Ped Col model will be animated as long as you hold the button\", gUString);\n\t\t\t\tCMessages::AddMessage(gUString, 100, 0);\n\t\t\t}\n\n\t\t\t// From LCS\n\t\t\tif (CAnimManager::GetAnimAssocGroups()[animGroup].numAssociations <= animId)\n\t\t\t\tanimId = 0;\n\n\t\t} else if (modelInfo->GetModelType() == MITYPE_VEHICLE) {\n\n\t\t\tif (pad->GetLeftShoulder1JustDown()) {\n\t\t\t\tnextModelId = LastPedModelId(modelId);\n\t\t\t\tAsciiToUnicode(\"Switched to peds\", gUString);\n\t\t\t\tCMessages::AddMessage(gUString, 1000, 0);\n\t\t\t\t// Start in mobile\n\t\t\t} else if (pad->GetSquareJustDown()) {\n\t\t\t\tCVehicleModelInfo::LoadVehicleColours();\n\t\t\t\tAsciiToUnicode(\"Carcols.dat reloaded\", gUString);\n\t\t\t\tCMessages::AddMessage(gUString, 1000, 0);\n\t\t\t}\n\t\t}\n\t}\n\n\tif (pad->GetDPadLeftJustDown()) {\n\t\tnextModelId = NextModelId(modelId, -1);\n\n\t\tsprintf(gString, \"Current model ID: %d\", nextModelId);\n\t\tAsciiToUnicode(gString, gUString);\n\t\tCMessages::AddMessage(gUString, 1000, 0);\n\n\t} else if (pad->GetDPadRightJustDown()) {\n\t\tnextModelId = NextModelId(modelId, 1);\n\n\t\tsprintf(gString, \"Current model ID: %d\", nextModelId);\n\t\tAsciiToUnicode(gString, gUString);\n\t\tCMessages::AddMessage(gUString, 1000, 0);\n\t}\n\t// There were extra codes here to let us change model id by 50, but xbox CPad struct is different, so I couldn't port.\n\n\tif (nextModelId != modelId) {\n\t\tmodelId = nextModelId;\n\t\tif (pTarget) {\n\t\t\tCWorld::Remove(pTarget);\n\t\t\tif (pTarget)\n\t\t\t\tdelete pTarget;\n\t\t}\n\t\tpTarget = nil;\n\t\treturn;\n\t}\n\n\tCTimeCycle::Update();\n\tCWorld::Process();\n\tif (pTarget)\n\t\tTheCamera.Process();\n}\n\nvoid\nCAnimViewer::Shutdown(void)\n{\n\tif (CWorld::Players[0].m_pPed)\n\t\tdelete CWorld::Players[0].m_pPed;\n\n\tCWorld::ShutDown();\n\tCModelInfo::ShutDown();\n\tCAnimManager::Shutdown();\n\tCTimer::Shutdown();\n\tCStreaming::Shutdown();\n\tCTxdStore::RemoveTxdSlot(animTxdSlot);\n}\n"
  },
  {
    "path": "src/core/AnimViewer.h",
    "content": "#pragma once\n\nclass CAnimViewer {\npublic:\n\tstatic int animTxdSlot;\n\tstatic CEntity *pTarget;\n\t\n\tstatic void Initialise();\n\tstatic void Render();\n\tstatic void Shutdown();\n\tstatic void Update();\n};"
  },
  {
    "path": "src/core/Cam.cpp",
    "content": "#include \"common.h\"\n\n#include \"main.h\"\n#include \"Draw.h\"\n#include \"World.h\"\n#include \"Vehicle.h\"\n#include \"Automobile.h\"\n#include \"Boat.h\"\n#include \"Bones.h\"\n#include \"Ped.h\"\n#include \"PlayerPed.h\"\n#include \"CopPed.h\"\n#include \"RpAnimBlend.h\"\n#include \"ControllerConfig.h\"\n#include \"Pad.h\"\n#include \"Frontend.h\"\n#include \"General.h\"\n#include \"Timecycle.h\"\n#include \"Renderer.h\"\n#include \"Shadows.h\"\n#include \"Hud.h\"\n#include \"ZoneCull.h\"\n#include \"SurfaceTable.h\"\n#include \"WaterLevel.h\"\n#include \"MBlur.h\"\n#include \"SceneEdit.h\"\n#include \"Debug.h\"\n#include \"Camera.h\"\n#include \"DMAudio.h\"\n#include \"Bike.h\"\n#include \"Pickups.h\"\n\nbool PrintDebugCode = false;\nint16 DebugCamMode;\n\nextern float fRangePlayerRadius;\nextern float fCloseNearClipLimit;\n\n#ifdef FREE_CAM\nbool CCamera::bFreeCam = false;\nint nPreviousMode = -1;\n#endif\n\nvoid\nCCam::Init(void)\n{\n\tMode = MODE_FOLLOWPED;\n\tFront = CVector(0.0f, 0.0f, -1.0f);\n\tUp = CVector(0.0f, 0.0f, 1.0f);\n\tRotating = false;\n\tm_iDoCollisionChecksOnFrameNum = 1;\n\tm_iDoCollisionCheckEveryNumOfFrames = 9;\n\tm_iFrameNumWereAt = 0;\n\tm_bCollisionChecksOn = false;\n\tm_fRealGroundDist = 0.0f;\n\tBetaSpeed = 0.0f;\n\tAlphaSpeed = 0.0f;\n\tDistanceSpeed = 0.0f;\n\tf_max_role_angle = DEGTORAD(5.0f);\n\tDistance = 30.0f;\n\tDistanceSpeed = 0.0f;\n\tm_pLastCarEntered = nil;\n\tm_pLastPedLookedAt = nil;\n\tResetStatics = true;\n\tBeta = 0.0f;\n\tm_fTilt = 0.0f;\n\tm_fTiltSpeed = 0.0f;\n\tm_bFixingBeta = false;\n\tCA_MIN_DISTANCE = 0.0f;\n\tCA_MAX_DISTANCE = 0.0f;\n\tLookingBehind = false;\n\tLookingLeft = false;\n\tLookingRight = false;\n\tm_fPlayerInFrontSyphonAngleOffSet = DEGTORAD(20.0f);\n\tm_fSyphonModeTargetZOffSet = 0.5f;\n\tm_fRadiusForDead = 1.5f;\n\tDirectionWasLooking = LOOKING_FORWARD;\n\tLookBehindCamWasInFront = false;\n\tf_Roll = 0.0f;\n\tf_rollSpeed = 0.0f;\n\tm_fCloseInPedHeightOffset = 0.0f;\n\tm_fCloseInPedHeightOffsetSpeed = 0.0f;\n\tm_fCloseInCarHeightOffset = 0.0f;\n\tm_fCloseInCarHeightOffsetSpeed = 0.0f;\n\tm_fPedBetweenCameraHeightOffset = 0.0f;\n\tm_fTargetBeta = 0.0f;\n\tm_fBufferedTargetBeta = 0.0f;\n\tm_fBufferedTargetOrientation = 0.0f;\n\tm_fBufferedTargetOrientationSpeed = 0.0f;\n\tm_fDimensionOfHighestNearCar = 0.0f;\n}\n\nfloat PLAYERPED_LEVEL_SMOOTHING_CONST_INV = 0.6f;\nfloat PLAYERPED_TREND_SMOOTHING_CONST_INV = 0.8f;\n\nvoid\nCCam::Process(void)\n{\n\tCVector CameraTarget;\n\tfloat TargetSpeedVar = 0.0f;\n\tfloat TargetOrientation = 0.0f;\n\n\tstatic CVector SmoothedPos(0.0f, 0.0f, 10000.0f);\n\tstatic CVector SmoothedSpeed(0.0f, 0.0f, 0.0f);\n\n\tif(CamTargetEntity == nil)\n\t\tCamTargetEntity = TheCamera.pTargetEntity;\n\n\tm_iFrameNumWereAt++;\n\tif(m_iFrameNumWereAt > m_iDoCollisionCheckEveryNumOfFrames)\n\t\tm_iFrameNumWereAt = 1;\n\tm_bCollisionChecksOn = m_iFrameNumWereAt == m_iDoCollisionChecksOnFrameNum;\n\n\tif(m_bCamLookingAtVector){\n\t\tCameraTarget = m_cvecCamFixedModeVector;\n\t}else if(CamTargetEntity->IsVehicle()){\n\t\tCameraTarget = CamTargetEntity->GetPosition();\n\n\t\tif(CamTargetEntity->GetForward().x == 0.0f && CamTargetEntity->GetForward().y == 0.0f)\n\t\t\tTargetOrientation = 0.0f;\n\t\telse\n\t\t\tTargetOrientation = CGeneral::GetATanOfXY(CamTargetEntity->GetForward().x, CamTargetEntity->GetForward().y);\n\n\t\tCVector Fwd(0.0f, 0.0f, 0.0f);\n\t\tFwd.x = CamTargetEntity->GetForward().x;\n\t\tFwd.y = CamTargetEntity->GetForward().y;\n\t\tFwd.Normalise();\n\t\tfloat FwdLength = Fwd.Magnitude2D();\n\t\tif(FwdLength != 0.0f){\n\t\t\tFwd.x /= FwdLength;\n\t\t\tFwd.y /= FwdLength;\n\t\t}\n\n\t\tfloat FwdSpeedX = ((CVehicle*)CamTargetEntity)->GetMoveSpeed().x * Fwd.x;\n\t\tfloat FwdSpeedY = ((CVehicle*)CamTargetEntity)->GetMoveSpeed().y * Fwd.y;\n\t\tif(FwdSpeedX + FwdSpeedY > 0.0f)\n\t\t\tTargetSpeedVar = Min(Sqrt(SQR(FwdSpeedX) + SQR(FwdSpeedY))/0.9f, 1.0f);\n\t\telse\n\t\t\tTargetSpeedVar = -Min(Sqrt(SQR(FwdSpeedX) + SQR(FwdSpeedY))/1.8f, 0.5f);\n\t\tSpeedVar = 0.895f*SpeedVar + 0.105*TargetSpeedVar;\n\t}else{\n\t\tif(CamTargetEntity == FindPlayerPed()){\n\t\t\t// Some fancy smoothing of player position and speed\n\t\t\tfloat LevelSmoothing = 1.0f - Pow(PLAYERPED_LEVEL_SMOOTHING_CONST_INV, CTimer::GetTimeStep());\n\t\t\tfloat TrendSmoothing = 1.0f - Pow(PLAYERPED_TREND_SMOOTHING_CONST_INV, CTimer::GetTimeStep());\n\n\t\t\tCVector NewSmoothedPos, NewSmoothedSpeed;\n\t\t\tif((SmoothedPos - CamTargetEntity->GetPosition()).MagnitudeSqr() > SQR(3.0f) ||\n\t\t\t   CTimer::GetTimeStep() < 0.2f || Using3rdPersonMouseCam()){\n\t\t\t\t// Reset values\n\t\t\t\tNewSmoothedPos = CamTargetEntity->GetPosition();\n\t\t\t\tNewSmoothedSpeed = CVector(0.0f, 0.0f, 0.0f);\n\t\t\t}else{\n\t\t\t\tNewSmoothedPos = LevelSmoothing*CamTargetEntity->GetPosition() + (1.0f-LevelSmoothing)*(SmoothedPos + SmoothedSpeed*CTimer::GetTimeStep());\n\t\t\t\tNewSmoothedSpeed = TrendSmoothing*(NewSmoothedPos-SmoothedPos)/CTimer::GetTimeStep() + (1.0f-TrendSmoothing)*SmoothedSpeed;\n\t\t\t}\n\t\t\t   \n\t\t\tCameraTarget = NewSmoothedPos;\n\t\t\tSmoothedPos = NewSmoothedPos;\n\t\t\tSmoothedSpeed = NewSmoothedSpeed;\n\t\t}else\n\t\t\tCameraTarget = CamTargetEntity->GetPosition();\n\n\t\tif(CamTargetEntity->GetForward().x == 0.0f && CamTargetEntity->GetForward().y == 0.0f)\n\t\t\tTargetOrientation = 0.0f;\n\t\telse\n\t\t\tTargetOrientation = CGeneral::GetATanOfXY(CamTargetEntity->GetForward().x, CamTargetEntity->GetForward().y);\n\t\tTargetSpeedVar = 0.0f;\n\t\tSpeedVar = 0.0f;\n\t}\n\n\tswitch(Mode){\n\tcase MODE_TOPDOWN:\n\tcase MODE_GTACLASSIC:\n\t//\tProcess_TopDown(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);\n\t\tbreak;\n\tcase MODE_BEHINDCAR:\n\t\tProcess_BehindCar(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);\n\t\tbreak;\n\tcase MODE_FOLLOWPED:\n#ifdef PC_PLAYER_CONTROLS\n\t\tif(CCamera::m_bUseMouse3rdPerson)\n\t\t\tProcess_FollowPedWithMouse(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);\n\t\telse\n#endif\n#ifdef FREE_CAM\n\t\t\tif(CCamera::bFreeCam)\n\t\t\t\tProcess_FollowPed_Rotation(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);\n\t\t\telse\n#endif\n\t\t\tProcess_FollowPed(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);\n\t\tbreak;\n//\tcase MODE_AIMING:\n\tcase MODE_DEBUG:\n\t\tProcess_Debug(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);\n\t\tbreak;\n\tcase MODE_SNIPER:\n\tcase MODE_CAMERA:\n\t\tProcess_Sniper(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);\n\t\tbreak;\n\tcase MODE_ROCKETLAUNCHER:\n\t\tProcess_Rocket(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);\n\t\tbreak;\n\tcase MODE_MODELVIEW:\n\t\tProcess_ModelView(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);\n\t\tbreak;\n//\tcase MODE_BILL:\n\tcase MODE_SYPHON:\n\t\tProcess_Syphon(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);\n\t\tbreak;\n\tcase MODE_CIRCLE:\n//\t\tProcess_Circle(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);\n\t\tbreak;\n//\tcase MODE_CHEESYZOOM:\n\tcase MODE_WHEELCAM:\n\t\tProcess_WheelCam(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);\n\t\tbreak;\n\tcase MODE_FIXED:\n\t\tProcess_Fixed(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);\n\t\tbreak;\n\tcase MODE_1STPERSON:\n\t\tProcess_1stPerson(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);\n\t\tbreak;\n\tcase MODE_FLYBY:\n\t\tProcess_FlyBy(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);\n\t\tbreak;\n\tcase MODE_CAM_ON_A_STRING:\n#ifdef FREE_CAM\n\t\tif(CCamera::bFreeCam)\n\t\t\tProcess_FollowCar_SA(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);\n\t\telse\n#endif\n\t\t\tProcess_Cam_On_A_String(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);\n\t\tbreak;\n//\tcase MODE_REACTION:\n//\tcase MODE_FOLLOW_PED_WITH_BIND:\n//\tcase MODE_CHRIS:\n\tcase MODE_BEHINDBOAT:\n#ifdef FREE_CAM\n\t\tif (CCamera::bFreeCam)\n\t\t\tProcess_FollowCar_SA(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);\n\t\telse\n#endif\n\t\t\tProcess_BehindBoat(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);\n\t\tbreak;\n\tcase MODE_PLAYER_FALLEN_WATER:\n\t\tProcess_Player_Fallen_Water(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);\n\t\tbreak;\n//\tcase MODE_CAM_ON_TRAIN_ROOF:\n//\tcase MODE_CAM_RUNNING_SIDE_TRAIN:\n//\tcase MODE_BLOOD_ON_THE_TRACKS:\n//\tcase MODE_IM_THE_PASSENGER_WOOWOO:\n\tcase MODE_SYPHON_CRIM_IN_FRONT:\n\t\tProcess_Syphon_Crim_In_Front(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);\n\t\tbreak;\n\tcase MODE_PED_DEAD_BABY:\n\t\tProcessPedsDeadBaby();\n\t\tbreak;\n//\tcase MODE_PILLOWS_PAPS:\n//\tcase MODE_LOOK_AT_CARS:\n\tcase MODE_ARRESTCAM_ONE:\n\t\tProcessArrestCamOne();\n\t\tbreak;\n\tcase MODE_ARRESTCAM_TWO:\n\t\tProcessArrestCamTwo();\n\t\tbreak;\n\tcase MODE_M16_1STPERSON:\n\tcase MODE_HELICANNON_1STPERSON:\n\t\tProcess_M16_1stPerson(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);\n\t\tbreak;\n\tcase MODE_SPECIAL_FIXED_FOR_SYPHON:\n\t\tProcess_SpecialFixedForSyphon(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);\n\t\tbreak;\n\tcase MODE_FIGHT_CAM:\n\t\tProcess_Fight_Cam(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);\n\t\tbreak;\n\tcase MODE_LIGHTHOUSE:\n\t\tProcess_LightHouse(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);\n\t\tbreak;\n\tcase MODE_TOP_DOWN_PED:\n\t//\tProcess_TopDownPed(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);\n\t\tbreak;\n\tcase MODE_SNIPER_RUNABOUT:\n\tcase MODE_ROCKETLAUNCHER_RUNABOUT:\n\tcase MODE_1STPERSON_RUNABOUT:\n\tcase MODE_M16_1STPERSON_RUNABOUT:\n\tcase MODE_FIGHT_CAM_RUNABOUT:\n\t\tProcess_1rstPersonPedOnPC(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);\n\t\tbreak;\n#ifdef GTA_SCENE_EDIT\n\tcase MODE_EDITOR:\n\t\tProcess_Editor(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar);\n\t\tbreak;\n#endif\n\tdefault:\n\t\tSource = CVector(0.0f, 0.0f, 0.0f);\n\t\tFront = CVector(0.0f, 1.0f, 0.0f);\n\t\tUp = CVector(0.0f, 0.0f, 1.0f);\n\t}\n\n#ifdef FREE_CAM\n\tnPreviousMode = Mode;\n#endif\n\tCVector TargetToCam = Source - m_cvecTargetCoorsForFudgeInter;\n\tfloat DistOnGround = TargetToCam.Magnitude2D();\n\tm_fTrueBeta = CGeneral::GetATanOfXY(TargetToCam.x, TargetToCam.y);\n\tm_fTrueAlpha = CGeneral::GetATanOfXY(DistOnGround, TargetToCam.z);\n\tif(TheCamera.m_uiTransitionState == 0)\n\t\tKeepTrackOfTheSpeed(Source, m_cvecTargetCoorsForFudgeInter, Up, m_fTrueAlpha, m_fTrueBeta, FOV);\n\n\t// Look Behind, Left, Right\n\tLookingBehind = false;\n\tLookingLeft = false;\n\tLookingRight = false;\n\tSourceBeforeLookBehind = Source;\n\tif(&TheCamera.Cams[TheCamera.ActiveCam] == this){\n\t\tif((Mode == MODE_CAM_ON_A_STRING || Mode == MODE_1STPERSON || Mode == MODE_BEHINDBOAT || Mode == MODE_BEHINDCAR) &&\n\t\t   CamTargetEntity->IsVehicle()){\n\t\t\tbool bDisableLR = CamTargetEntity &&\n\t\t\t\t(((CVehicle*)CamTargetEntity)->GetVehicleAppearance() == VEHICLE_APPEARANCE_HELI || CamTargetEntity->GetModelIndex() == MI_RCBARON);\n\t\t\tif(CPad::GetPad(0)->GetLookBehindForCar()){\n\t\t\t\tLookBehind();\n\t\t\t\tif(DirectionWasLooking != LOOKING_BEHIND)\n\t\t\t\t\tTheCamera.m_bJust_Switched = true;\n\t\t\t\tDirectionWasLooking = LOOKING_BEHIND;\n\t\t\t}else if(bDisableLR){\n\t\t\t\tif(DirectionWasLooking != LOOKING_FORWARD)\n\t\t\t\t\tTheCamera.m_bJust_Switched = true;\n\t\t\t\tDirectionWasLooking = LOOKING_FORWARD;\n\t\t\t}else if(CPad::GetPad(0)->GetLookLeft()){\n\t\t\t\tLookLeft();\n\t\t\t\tif(DirectionWasLooking != LOOKING_LEFT)\n\t\t\t\t\tTheCamera.m_bJust_Switched = true;\n\t\t\t\tDirectionWasLooking = LOOKING_LEFT;\n\t\t\t}else if(CPad::GetPad(0)->GetLookRight()){\n\t\t\t\tLookRight();\n\t\t\t\tif(DirectionWasLooking != LOOKING_RIGHT)\n\t\t\t\t\tTheCamera.m_bJust_Switched = true;\n\t\t\t\tDirectionWasLooking = LOOKING_RIGHT;\n\t\t\t}else{\n\t\t\t\tif(DirectionWasLooking != LOOKING_FORWARD)\n\t\t\t\t\tTheCamera.m_bJust_Switched = true;\n\t\t\t\tDirectionWasLooking = LOOKING_FORWARD;\n\t\t\t}\n\t\t}\n\t\tif(Mode == MODE_FOLLOWPED && CamTargetEntity->IsPed()){\n\t\t\tif(CPad::GetPad(0)->GetLookBehindForPed()){\n\t\t\t\tLookBehind();\n\t\t\t\tif(DirectionWasLooking != LOOKING_BEHIND)\n\t\t\t\t\tTheCamera.m_bJust_Switched = true;\n\t\t\t\tDirectionWasLooking = LOOKING_BEHIND;\n\t\t\t}else\n\t\t\t\tDirectionWasLooking = LOOKING_FORWARD;\n\t\t}\n\t}\n\n\tif(Mode == MODE_SNIPER || Mode == MODE_ROCKETLAUNCHER || Mode == MODE_M16_1STPERSON ||\n\t   Mode == MODE_1STPERSON || Mode == MODE_HELICANNON_1STPERSON || Mode == MODE_CAMERA || GetWeaponFirstPersonOn())\n\t\tClipIfPedInFrontOfPlayer();\n}\n\n// MaxSpeed is a limit of how fast the value is allowed to change. 1.0 = to Target in up to 1ms\n// Acceleration is how fast the speed will change to MaxSpeed. 1.0 = to MaxSpeed in 1ms\nvoid\nWellBufferMe(float Target, float *CurrentValue, float *CurrentSpeed, float MaxSpeed, float Acceleration, bool IsAngle)\n{\n\tfloat Delta = Target - *CurrentValue;\n\n\tif(IsAngle){\n\t\twhile(Delta >= PI) Delta -= 2*PI;\n\t\twhile(Delta < -PI) Delta += 2*PI;\n\t}\n\n\tfloat TargetSpeed = Delta * MaxSpeed;\n\t// Add or subtract absolute depending on sign, genius!\n//\tif(TargetSpeed - *CurrentSpeed > 0.0f)\n//\t\t*CurrentSpeed += Acceleration * Abs(TargetSpeed - *CurrentSpeed) * CTimer::GetTimeStep();\n//\telse\n//\t\t*CurrentSpeed -= Acceleration * Abs(TargetSpeed - *CurrentSpeed) * CTimer::GetTimeStep();\n\t// this is simpler:\n\t*CurrentSpeed += Acceleration * (TargetSpeed - *CurrentSpeed) * CTimer::GetTimeStep();\n\n\t// Clamp speed if we overshot\n\tif(TargetSpeed < 0.0f && *CurrentSpeed < TargetSpeed)\n\t\t*CurrentSpeed = TargetSpeed;\n\telse if(TargetSpeed > 0.0f && *CurrentSpeed > TargetSpeed)\n\t\t*CurrentSpeed = TargetSpeed;\n\n\t*CurrentValue += *CurrentSpeed * Min(10.0f, CTimer::GetTimeStep());\n}\n\nvoid\nMakeAngleLessThan180(float &Angle)\n{\n\twhile(Angle >= PI) Angle -= 2*PI;\n\twhile(Angle < -PI) Angle += 2*PI;\n}\n\nvoid\nCCam::ProcessSpecialHeightRoutines(void)\n{\n\tint i;\n\tbool StandingOnBoat = false;\n\tstatic bool PreviouslyFailedRoadHeightCheck = false;\n\tCVector CamToTarget, CamToPed;\n\tfloat DistOnGround, BetaAngle;\n\tCPed *Player;\n\tfloat PedZDist;\n\tCColPoint colPoint;\n\n\tCamToTarget = TheCamera.pTargetEntity->GetPosition() - TheCamera.GetGameCamPosition();\n\tDistOnGround = CamToTarget.Magnitude2D();\n\tBetaAngle = CGeneral::GetATanOfXY(CamToTarget.x, CamToTarget.y);\n\tm_bTheHeightFixerVehicleIsATrain = false;\n\t// CGeneral::GetATanOfXY(TheCamera.GetForward().x, TheCamera.GetForward().y);\n\tPlayer = CWorld::Players[CWorld::PlayerInFocus].m_pPed;\n\n\tif(DistOnGround > 10.0f)\n\t\tDistOnGround = 10.0f;\n\n\tif(CamTargetEntity && CamTargetEntity->IsPed()){\n\t\tif(FindPlayerPed()->m_pCurSurface && FindPlayerPed()->m_pCurSurface->IsVehicle() &&\n\t\t   ((CVehicle*)FindPlayerPed()->m_pCurSurface)->IsBoat())\n\t\t\tStandingOnBoat = true;\n\n\t\tfloat FoundPedZ = -100.0f;\n\n\t\t// Move up the camera if there is a ped close to it\n\t\tif(Mode == MODE_FOLLOWPED || Mode == MODE_FIGHT_CAM || Mode == MODE_PILLOWS_PAPS){\n\t\t\t// Find highest ped close to camera\n\t\t\tfor(i = 0; i < Player->m_numNearPeds; i++){\n\t\t\t\tCPed *nearPed = Player->m_nearPeds[i];\n\t\t\t\tif(nearPed && nearPed->GetPedState() != PED_DEAD){\n\t\t\t\t\tCamToPed = nearPed->GetPosition() - TheCamera.GetGameCamPosition();\n\t\t\t\t\tif(Abs(CamToPed.z) < 1.0f){\n\t\t\t\t\t\tfloat DistSq = CamToPed.MagnitudeSqr();\n\t\t\t\t\t\tif(DistSq < SQR(2.1f)){\n\t\t\t\t\t\t\tif(nearPed->GetPosition().z > FoundPedZ)\n\t\t\t\t\t\t\t\tFoundPedZ = nearPed->GetPosition().z;\n\t\t\t\t\t\t}else{\n\t\t\t\t\t\t\tfloat Dist = Sqrt(DistSq);\n\t\t\t\t\t\t\tCamToPed /= Dist;\n\t\t\t\t\t\t\t// strange calculation\n\t\t\t\t\t\t\tCVector PlayerCamSpeed = DotProduct(Front, Player->m_vecMoveSpeed)*Front;\n\t\t\t\t\t\t\tfloat SpeedDiff = DotProduct(PlayerCamSpeed - nearPed->m_vecMoveSpeed, CamToPed);\n\t\t\t\t\t\t\tif(SpeedDiff > 0.01f &&\n\t\t\t\t\t\t\t   (m_fPedBetweenCameraHeightOffset > 0.0f && (Dist-2.1f)/SpeedDiff < 75.0f ||\n\t\t\t\t\t\t\t    m_fPedBetweenCameraHeightOffset <= 0.0f && (Dist-2.1f)/SpeedDiff < 75.0f * 0.1f))\n\t\t\t\t\t\t\t\tif(nearPed->GetPosition().z > FoundPedZ)\n\t\t\t\t\t\t\t\t\tFoundPedZ = nearPed->GetPosition().z;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif(FoundPedZ > -99.0f){\n\t\t\t\tfloat Offset = 0.0f;\n\t\t\t\tPedZDist = 0.0f;\n\t\t\t\tif(FoundPedZ > Player->GetPosition().z)\n\t\t\t\t\tPedZDist = FoundPedZ - Player->GetPosition().z;\n\n\t\t\t\tif(Mode == MODE_FOLLOWPED){\n\t\t\t\t\tif(TheCamera.PedZoomIndicator == CAM_ZOOM_1 &&\n\t\t\t\t\t   ((CPed*)CamTargetEntity)->GetPedState() != PED_ENTER_CAR &&\n\t\t\t\t\t   ((CPed*)CamTargetEntity)->GetPedState() != PED_CARJACK)\n\t\t\t\t\t\tOffset = 0.45f + PedZDist;\n\t\t\t\t\t// BUG: overrides this ^ case\n\t\t\t\t\tif(TheCamera.PedZoomIndicator == CAM_ZOOM_2 || TheCamera.PedZoomIndicator == CAM_ZOOM_1)\n\t\t\t\t\t\tOffset = 0.35f + PedZDist;\n\t\t\t\t\tif(TheCamera.PedZoomIndicator == CAM_ZOOM_3)\n\t\t\t\t\t\tOffset = 0.25f + PedZDist;\n\t\t\t\t\tm_fPedBetweenCameraHeightOffset = Offset + 1.3f;\n\t\t\t\t}else if(Mode == MODE_FIGHT_CAM)\n\t\t\t\t\tm_fPedBetweenCameraHeightOffset = PedZDist + 1.3f + 0.5f;\n\t\t\t\telse if(Mode == MODE_PILLOWS_PAPS)\n\t\t\t\t\tm_fPedBetweenCameraHeightOffset = PedZDist + 1.3f + 0.45f;\n\t\t\t}else{\n\t\t\t\tm_fPedBetweenCameraHeightOffset = 0.0f;\n\t\t\t}\n\t\t}\n\n\n\t\t// Move camera up for vehicles in the way\n\t\tif(m_bCollisionChecksOn && (Mode == MODE_FOLLOWPED || Mode == MODE_FIGHT_CAM)){\n\t\t\tbool FoundCar = false;\n\t\t\tCEntity *vehicle = nil;\n\t\t\tfloat TestDist = DistOnGround + 1.25f;\n\t\t\tfloat HighestCar = 0.0f;\n\t\t\tif(m_fDimensionOfHighestNearCar > 0.0f)\n\t\t\t\tTestDist += 0.3f;\n\t\t\tCVector TestBase = CamTargetEntity->GetPosition();\n\t\t\tCVector TestPoint;\n\t\t\tTestBase.z -= 0.15f;\n\n\t\t\tTestPoint = TestBase - TestDist * CVector(Cos(BetaAngle), Sin(BetaAngle), 0.0f);\n\t\t\tif(CWorld::ProcessLineOfSight(CamTargetEntity->GetPosition(), TestPoint, colPoint, vehicle, false, true, false, false, false, false) &&\n\t\t\t   vehicle->IsVehicle()){\n\t\t\t\tfloat height = vehicle->GetColModel()->boundingBox.GetSize().z;\n\t\t\t\tFoundCar = true;\n\t\t\t\tHighestCar = height;\n\t\t\t\tif(((CVehicle*)vehicle)->IsTrain())\n\t\t\t\t\tm_bTheHeightFixerVehicleIsATrain = true;\n\t\t\t}\n\n\t\t\tTestPoint = TestBase - TestDist * CVector(Cos(BetaAngle+DEGTORAD(28.0f)), Sin(BetaAngle+DEGTORAD(28.0f)), 0.0f);\n\t\t\tif(CWorld::ProcessLineOfSight(CamTargetEntity->GetPosition(), TestPoint, colPoint, vehicle, false, true, false, false, false, false) &&\n\t\t\t   vehicle->IsVehicle()){\n\t\t\t\tfloat height = vehicle->GetColModel()->boundingBox.GetSize().z;\n\t\t\t\tif(FoundCar){\n\t\t\t\t\tHighestCar = Max(HighestCar, height);\n\t\t\t\t}else{\n\t\t\t\t\tFoundCar = true;\n\t\t\t\t\tHighestCar = height;\n\t\t\t\t}\n\t\t\t\tif(((CVehicle*)vehicle)->IsTrain())\n\t\t\t\t\tm_bTheHeightFixerVehicleIsATrain = true;\n\t\t\t}\n\n\t\t\tTestPoint = TestBase - TestDist * CVector(Cos(BetaAngle-DEGTORAD(28.0f)), Sin(BetaAngle-DEGTORAD(28.0f)), 0.0f);\n\t\t\tif(CWorld::ProcessLineOfSight(CamTargetEntity->GetPosition(), TestPoint, colPoint, vehicle, false, true, false, false, false, false) &&\n\t\t\t   vehicle->IsVehicle()){\n\t\t\t\tfloat height = vehicle->GetColModel()->boundingBox.GetSize().z;\n\t\t\t\tif(FoundCar){\n\t\t\t\t\tHighestCar = Max(HighestCar, height);\n\t\t\t\t}else{\n\t\t\t\t\tFoundCar = true;\n\t\t\t\t\tHighestCar = height;\n\t\t\t\t}\n\t\t\t\tif(((CVehicle*)vehicle)->IsTrain())\n\t\t\t\t\tm_bTheHeightFixerVehicleIsATrain = true;\n\t\t\t}\n\n\t\t\tif(FoundCar){\n\t\t\t\tm_fDimensionOfHighestNearCar = HighestCar + 0.1f;\n\t\t\t\tif(Mode == MODE_FIGHT_CAM)\n\t\t\t\t\tm_fDimensionOfHighestNearCar += 0.75f;\n\t\t\t}else\n\t\t\t\tm_fDimensionOfHighestNearCar = 0.0f;\n\t\t}\n\t}\n\n\tif(StandingOnBoat){\n\t\tm_fDimensionOfHighestNearCar = 1.0f;\n\t\tm_fPedBetweenCameraHeightOffset = 0.0f;\n\t}\n}\n\nvoid\nCCam::GetVectorsReadyForRW(void)\n{\n\tCVector right;\n\tUp = CVector(0.0f, 0.0f, 1.0f);\n\tFront.Normalise();\n\tif(Front.x == 0.0f && Front.y == 0.0f){\n\t\tFront.x = 0.0001f;\n\t\tFront.y = 0.0001f;\n\t}\n\tright = CrossProduct(Front, Up);\n\tright.Normalise();\n\tUp = CrossProduct(right, Front);\n}\n\nbool\nCCam::GetBoatLook_L_R_HeightOffset(float &Offset)\n{\n\tif(CamTargetEntity == nil)\n\t\treturn false;\n\tCVehicleModelInfo *mi = (CVehicleModelInfo*)CModelInfo::GetModelInfo(CamTargetEntity->GetModelIndex());\n\ttBoatHandlingData *handling = mod_HandlingManager.GetBoatPointer(mi->m_handlingId);\n\tif(handling){\n\t\tOffset = handling->fLook_L_R_BehindCamHeight;\n\t\treturn true;\n\t}\n\treturn false;\t// can't happen, we always get a boat pointer back\n}\n\nvoid\nCCam::LookBehind(void)\n{\n\tfloat Dist, DeltaBeta, TargetOrientation, Angle;\n\tCVector TargetCoors, TargetFwd, TestCoors;\n\n\tTargetCoors = CamTargetEntity->GetPosition();\n\tFront = CamTargetEntity->GetPosition() - Source;\n\n\tif((Mode == MODE_CAM_ON_A_STRING || Mode == MODE_BEHINDBOAT || Mode == MODE_BEHINDCAR) && CamTargetEntity->IsVehicle()){\n\t\tLookingBehind = true;\n\t\tDist = Mode == MODE_CAM_ON_A_STRING ? CA_MAX_DISTANCE : 15.5f;\n\t\tTargetFwd = CamTargetEntity->GetForward();\n\t\tTargetFwd.Normalise();\n\t\tTargetOrientation = CGeneral::GetATanOfXY(TargetFwd.x, TargetFwd.y);\n\t\tDeltaBeta = TargetOrientation - Beta;\n\t\twhile(DeltaBeta >= PI) DeltaBeta -= 2*PI;\n\t\twhile(DeltaBeta < -PI) DeltaBeta += 2*PI;\n\t\tif(DirectionWasLooking != LOOKING_BEHIND)\n\t\t\tLookBehindCamWasInFront = DeltaBeta <= -HALFPI || DeltaBeta >= HALFPI;\n\t\tif(LookBehindCamWasInFront)\n\t\t\tTargetOrientation += PI;\n\t\tSource.x = Dist*Cos(TargetOrientation) + TargetCoors.x;\n\t\tSource.y = Dist*Sin(TargetOrientation) + TargetCoors.y;\n\t\tCVector OrigSource = Source;\n\t\tTheCamera.AvoidTheGeometry(OrigSource, TargetCoors, Source, FOV);\n\t\tFront = CamTargetEntity->GetPosition() - Source;\n\t\tGetVectorsReadyForRW();\n\t}\n\tif(Mode == MODE_1STPERSON && CamTargetEntity->IsVehicle()){\n\t\tLookingBehind = true;\n\t\tRwCameraSetNearClipPlane(Scene.camera, 0.25f);\n\t\tFront = CamTargetEntity->GetForward();\n\t\tFront.Normalise();\n\t\tif(((CVehicle*)CamTargetEntity)->IsBoat())\n\t\t\tSource.z -= 0.5f;\n\t\tif(((CVehicle*)CamTargetEntity)->GetVehicleAppearance() == VEHICLE_APPEARANCE_BIKE){\n\t\t\tfloat FrontDist = 1.1f;\n\t\t\tif(((CVehicle*)CamTargetEntity)->pDriver){\n\t\t\t\tCVector ExtraFwd(0.0f, 0.0f, 0.0f);\n\t\t\t\t((CVehicle*)CamTargetEntity)->pDriver->m_pedIK.GetComponentPosition(ExtraFwd, PED_HEAD);\n\t\t\t\tExtraFwd += ((CVehicle*)CamTargetEntity)->m_vecMoveSpeed*CTimer::GetTimeStep() - CamTargetEntity->GetPosition();\n\t\t\t\tFrontDist += 0.2f + Max(DotProduct(ExtraFwd, CamTargetEntity->GetForward()), 0.0f);\n\t\t\t}\n\t\t\tSource += FrontDist*Front;\n\t\t\tFront = -Front;\n\t\t}else if(((CVehicle*)CamTargetEntity)->GetVehicleAppearance() == VEHICLE_APPEARANCE_HELI){\n\t\t\tFront = -1.0f*CamTargetEntity->GetUp();\n\t\t\tUp = CamTargetEntity->GetForward();\n\t\t\tSource += 0.25f*Front;\n\t\t}else{\n\t\t\tSource += 0.25f*Front;\n\t\t\tFront = -Front;\n\t\t}\n\t}\n\tif(CamTargetEntity->IsPed()){\n\t\tAngle = CGeneral::GetATanOfXY(Source.x - TargetCoors.x, Source.y - TargetCoors.y) + PI;\n\t\tSource.x = 4.5f*Cos(Angle) + TargetCoors.x;\n\t\tSource.y = 4.5f*Sin(Angle) + TargetCoors.y;\n\t\tSource.z = 1.15f + TargetCoors.z;\n\t\tCVector OrigSource = Source;\n\t\tTheCamera.AvoidTheGeometry(OrigSource, TargetCoors, Source, FOV);\n\t\tFront = TargetCoors - Source;\n\t\tGetVectorsReadyForRW();\n\t}\n}\n\nfloat BOAT_1STPERSON_L_OFFSETX = 0.7f;\nfloat BOAT_1STPERSON_R_OFFSETX = 0.3f;\nfloat BOAT_1STPERSON_LR_OFFSETZ = 0.2f;\n\nvoid\nCCam::LookLeft(void)\n{\n\tfloat Dist, TargetOrientation;\n\tCVector TargetCoors, TargetFwd;\n\n\tif((Mode == MODE_CAM_ON_A_STRING || Mode == MODE_BEHINDBOAT || Mode == MODE_BEHINDCAR) && CamTargetEntity->IsVehicle()){\n\t\tLookingLeft = true;\n\t\tTargetCoors = CamTargetEntity->GetPosition();\n\t\tFront = CamTargetEntity->GetPosition() - Source;\n\t\tif(Mode == MODE_CAM_ON_A_STRING)\n\t\t\tDist = CA_MAX_DISTANCE;\n\t\telse if(Mode == MODE_BEHINDBOAT){\n\t\t\tDist = 9.0f;\n\t\t\tfloat Offset = 0.0f;\n\t\t\tif(GetBoatLook_L_R_HeightOffset(Offset) && !CCullZones::Cam1stPersonForPlayer())\n\t\t\t\tSource.z = TargetCoors.z + Offset;\n\t\t}else\n\t\t\tDist = 9.0f;\n\t\tTargetFwd = CamTargetEntity->GetForward();\n\t\tTargetFwd.Normalise();\n\t\tTargetOrientation = CGeneral::GetATanOfXY(TargetFwd.x, TargetFwd.y);\n\t\tSource.x = Dist*Cos(TargetOrientation - HALFPI) + TargetCoors.x;\n\t\tSource.y = Dist*Sin(TargetOrientation - HALFPI) + TargetCoors.y;\n\n\t\tCColModel *colModel = CamTargetEntity->GetColModel();\n\t\tCVector OrigSource = Source;\n\t\tTheCamera.AvoidTheGeometry(OrigSource, TargetCoors, Source, FOV);\n\n\t\tCVector TopRight = CamTargetEntity->GetPosition() +\n\t\t\tCamTargetEntity->GetRight()*colModel->boundingBox.max.x +\n\t\t\tCamTargetEntity->GetUp()*colModel->boundingBox.max.z;\n\t\tfloat Height = Min(Max(m_cvecTargetCoorsForFudgeInter.z, TopRight.z)+0.1f, OrigSource.z);\n\t\tSource.z = Max(Height, Source.z);\n\n\t\tFront = CamTargetEntity->GetPosition() - Source;\n\t\tFront.z += 1.1f;\n\t\tif(Mode == MODE_BEHINDBOAT)\n\t\t\tFront.z += 1.2f;\n\t\tGetVectorsReadyForRW();\n\t}\n\tif(Mode == MODE_1STPERSON && CamTargetEntity->IsVehicle()){\n\t\tLookingLeft = true;\n\t\tRwCameraSetNearClipPlane(Scene.camera, 0.25f);\n\t\tif(((CVehicle*)CamTargetEntity)->IsBoat()){\n\t\t\tif(((CVehicle*)CamTargetEntity)->pDriver){\n\t\t\t\tCVector neck(0.0f, 0.0f, 0.0f);\n\t\t\t\tCPed *driver = ((CVehicle*)CamTargetEntity)->pDriver;\n\t\t\t\tdriver->SetPedPositionInCar();\n\t\t\t\tdriver->GetMatrix().UpdateRW();\n\t\t\t\tdriver->UpdateRwFrame();\n\t\t\t\tdriver->UpdateRpHAnim();\n\t\t\t\tdriver->m_pedIK.GetComponentPosition(neck, PED_NECK);\n\t\t\t\tSource = neck +\n\t\t\t\t\tBOAT_1STPERSON_L_OFFSETX*CamTargetEntity->GetRight() +\n\t\t\t\t\tBOAT_1STPERSON_LR_OFFSETZ*CamTargetEntity->GetUp();\n\t\t\t}else\n\t\t\t\tSource.z -= 0.5f;\n\t\t}\n\n\t\tUp = CamTargetEntity->GetUp();\n\t\tUp.Normalise();\n\t\tFront = CamTargetEntity->GetForward();\n\t\tFront.Normalise();\n\t\tFront = -CrossProduct(Front, Up);\n\t\tFront.Normalise();\n\t\tif(((CVehicle*)CamTargetEntity)->GetVehicleAppearance() == VEHICLE_APPEARANCE_BIKE)\n\t\t\tSource -= 1.45f*Front;\n\t}\n}\n\nvoid\nCCam::LookRight(void)\n{\n\tfloat Dist, TargetOrientation;\n\tCVector TargetCoors, TargetFwd;\n\tCColPoint colPoint;\n\n\tif((Mode == MODE_CAM_ON_A_STRING || Mode == MODE_BEHINDBOAT) && CamTargetEntity->IsVehicle()){\n\t\tLookingRight = true;\n\t\tTargetCoors = CamTargetEntity->GetPosition();\n\t\tFront = CamTargetEntity->GetPosition() - Source;\n\t\tif(Mode == MODE_CAM_ON_A_STRING)\n\t\t\tDist = CA_MAX_DISTANCE;\n\t\telse if(Mode == MODE_BEHINDBOAT){\n\t\t\tDist = 9.0f;\n\t\t\tfloat Offset = 0.0f;\n\t\t\tif(GetBoatLook_L_R_HeightOffset(Offset) && !CCullZones::Cam1stPersonForPlayer())\n\t\t\t\tSource.z = TargetCoors.z + Offset;\n\t\t}else\n\t\t\tDist = 9.0f;\n\t\tTargetFwd = CamTargetEntity->GetForward();\n\t\tTargetFwd.Normalise();\n\t\tTargetOrientation = CGeneral::GetATanOfXY(TargetFwd.x, TargetFwd.y);\n\t\tSource.x = Dist*Cos(TargetOrientation + HALFPI) + TargetCoors.x;\n\t\tSource.y = Dist*Sin(TargetOrientation + HALFPI) + TargetCoors.y;\n\n\t\tCColModel *colModel = CamTargetEntity->GetColModel();\n\t\tCVector OrigSource = Source;\n\t\tTheCamera.AvoidTheGeometry(OrigSource, TargetCoors, Source, FOV);\n\n\t\tCVector TopLeft = CamTargetEntity->GetPosition() +\n\t\t\tCamTargetEntity->GetRight()*colModel->boundingBox.min.x +\n\t\t\tCamTargetEntity->GetUp()*colModel->boundingBox.max.z;\n\t\tfloat Height = Min(Max(m_cvecTargetCoorsForFudgeInter.z, TopLeft.z)+0.1f, OrigSource.z);\n\t\tSource.z = Max(Height, Source.z);\n\n\t\tFront = CamTargetEntity->GetPosition() - Source;\n\t\tFront.z += 1.1f;\n\t\tif(Mode == MODE_BEHINDBOAT)\n\t\t\tFront.z += 1.2f;\n\t\tGetVectorsReadyForRW();\n\t}\n\tif(Mode == MODE_1STPERSON && CamTargetEntity->IsVehicle()){\n\t\tLookingRight = true;\n\t\tRwCameraSetNearClipPlane(Scene.camera, 0.25f);\n\t\tif(((CVehicle*)CamTargetEntity)->IsBoat()){\n\t\t\tif(((CVehicle*)CamTargetEntity)->pDriver){\n\t\t\t\tCVector neck(0.0f, 0.0f, 0.0f);\n\t\t\t\tCPed *driver = ((CVehicle*)CamTargetEntity)->pDriver;\n\t\t\t\tdriver->SetPedPositionInCar();\n\t\t\t\tdriver->GetMatrix().UpdateRW();\n\t\t\t\tdriver->UpdateRwFrame();\n\t\t\t\tdriver->UpdateRpHAnim();\n\t\t\t\tdriver->m_pedIK.GetComponentPosition(neck, PED_NECK);\n\t\t\t\tSource = neck +\n\t\t\t\t\tBOAT_1STPERSON_R_OFFSETX*CamTargetEntity->GetRight() +\n\t\t\t\t\tBOAT_1STPERSON_LR_OFFSETZ*CamTargetEntity->GetUp();\n\t\t\t}else\n\t\t\t\tSource.z -= 0.5f;\n\t\t}\n\n\t\tUp = CamTargetEntity->GetUp();\n\t\tUp.Normalise();\n\t\tFront = CamTargetEntity->GetForward();\n\t\tFront.Normalise();\n\t\tFront = CrossProduct(Front, Up);\n\t\tFront.Normalise();\n\t\tif(((CVehicle*)CamTargetEntity)->GetVehicleAppearance() == VEHICLE_APPEARANCE_BIKE)\n\t\t\tSource -= 1.45f*Front;\n\t}\n}\n\nvoid\nCCam::ClipIfPedInFrontOfPlayer(void)\n{\n\tfloat FwdAngle, PedAngle, DeltaAngle, fDist, Near;\n\tCVector vDist;\n\tCPed *Player;\n\tbool found = false;\n\tint ped = 0;\n\n\t// unused: TheCamera.pTargetEntity->GetPosition() - TheCamera.GetGameCamPosition();\n\n\tFwdAngle = CGeneral::GetATanOfXY(TheCamera.GetForward().x, TheCamera.GetForward().y);\n\tPlayer = CWorld::Players[CWorld::PlayerInFocus].m_pPed;\n\twhile(ped < Player->m_numNearPeds && !found)\n\t\tif(Player->m_nearPeds[ped] && Player->m_nearPeds[ped]->GetPedState() != PED_DEAD)\n\t\t\tfound = true;\n\t\telse\n\t\t\tped++;\n\tif(found){\n\t\tvDist = Player->m_nearPeds[ped]->GetPosition() - TheCamera.GetGameCamPosition();\n\t\tPedAngle = CGeneral::GetATanOfXY(vDist.x, vDist.y);\n\t\tDeltaAngle = FwdAngle - PedAngle;\n\t\twhile(DeltaAngle >= PI) DeltaAngle -= 2*PI;\n\t\twhile(DeltaAngle < -PI) DeltaAngle += 2*PI;\n\t\tif(Abs(DeltaAngle) < HALFPI){\n\t\t\tfDist = vDist.Magnitude2D();\n\t\t\tif(fDist < 1.25f){\n\t\t\t\tNear = DEFAULT_NEAR - (1.25f - fDist);\n\t\t\t\tif(Near < 0.05f)\n\t\t\t\t\tNear = 0.05f;\n\t\t\t\tRwCameraSetNearClipPlane(Scene.camera, Near);\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nCCam::KeepTrackOfTheSpeed(const CVector &source, const CVector &target, const CVector &up, const float &alpha, const float &beta, const float &fov)\n{\n\tstatic CVector PreviousSource = source;\n\tstatic CVector PreviousTarget = target;\n\tstatic CVector PreviousUp = up;\n\tstatic float PreviousBeta = beta;\n\tstatic float PreviousAlpha = alpha;\n\tstatic float PreviousFov = fov;\n\n\tif(TheCamera.m_bJust_Switched){\n\t\tPreviousSource = source;\n\t\tPreviousTarget = target;\n\t\tPreviousUp = up;\n\t}\n\n\tm_cvecSourceSpeedOverOneFrame = source - PreviousSource;\n\tm_cvecTargetSpeedOverOneFrame = target - PreviousTarget;\n\tm_cvecUpOverOneFrame = up - PreviousUp;\n\tm_fFovSpeedOverOneFrame = fov - PreviousFov;\n\tm_fBetaSpeedOverOneFrame = beta - PreviousBeta;\n\tMakeAngleLessThan180(m_fBetaSpeedOverOneFrame);\n\tm_fAlphaSpeedOverOneFrame = alpha - PreviousAlpha;\n\tMakeAngleLessThan180(m_fAlphaSpeedOverOneFrame);\n\n\tPreviousSource = source;\n\tPreviousTarget = target;\n\tPreviousUp = up;\n\tPreviousBeta = beta;\n\tPreviousAlpha = alpha;\n\tPreviousFov = fov;\n}\n\nbool\nCCam::Using3rdPersonMouseCam(void) \n{\n\treturn CCamera::m_bUseMouse3rdPerson && Mode == MODE_FOLLOWPED;\n}\n\nbool\nCCam::GetWeaponFirstPersonOn(void)\n{\n\treturn CamTargetEntity && CamTargetEntity->IsPed() && ((CPed*)CamTargetEntity)->GetWeapon()->m_bAddRotOffset;\n}\n\nbool\nCCam::IsTargetInWater(const CVector &CamCoors)\n{\n\tif(CamTargetEntity){\n\t\tfloat WaterZ = -6000.0f;\n\t\tCWaterLevel::GetWaterLevel(CamTargetEntity->GetPosition(), &WaterZ, false);\n\t\tif(CamTargetEntity->IsPed()){\n\t\t\tif(((CPed*)CamTargetEntity)->bIsDrowning ||\n\t\t\t   ((CPed*)CamTargetEntity)->bIsInWater && CamTargetEntity->GetPosition().z < WaterZ)\n\t\t\t\treturn true;\n\t\t}else{\n\t\t\tassert(CamTargetEntity->IsVehicle());\n\t\t\tif(((CVehicle*)CamTargetEntity)->bIsDrowning ||\n\t\t\t   ((CVehicle*)CamTargetEntity)->bIsInWater && CamTargetEntity->GetPosition().z < WaterZ)\n\t\t\t\treturn true;\n\t\t}\n\t}\n\tm_vecLastAboveWaterCamPosition = Source;\n\treturn false;\n}\n\nvoid\nCCam::PrintMode(void)\n{\n\t// Doesn't do anything\n\tchar buf[256];\n\n\tif(PrintDebugCode){\n\t\tsprintf(buf, \"                                                   \");\n\t\tsprintf(buf, \"                                                   \");\n\t\tsprintf(buf, \"                                                   \");\n\n\t\tstatic Const char *modes[] = { \"None\",\n\t\t\t\"Top Down\", \"GTA Classic\", \"Behind Car\", \"Follow Ped\",\n\t\t\t\"Aiming\", \"Debug\", \"Sniper\", \"Rocket\", \"Model Viewer\", \"Bill\",\n\t\t\t\"Syphon\", \"Circle\", \"Cheesy Zoom\", \"Wheel\", \"Fixed\",\n\t\t\t\"1st Person\", \"Fly by\", \"on a String\", \"Reaction\",\n\t\t\t\"Follow Ped with Bind\", \"Chris\", \"Behind Boat\",\n\t\t\t\"Player fallen in Water\", \"Train Roof\", \"Train Side\",\n\t\t\t\"Blood on the tracks\", \"Passenger\", \"Syphon Crim in Front\",\n\t\t\t\"Dead Baby\", \"Pillow Paps\", \"Look at Cars\", \"Arrest One\",\n\t\t\t\"Arrest Two\", \"M16\", \"Special fixed for Syphon\", \"Fight\",\n\t\t\t\"Top Down Ped\", \"Lighthouse\",\n\t\t\t\"Sniper run about\", \"Rocket run about\",\n\t\t\t\"1st Person run about\", \"M16 run about\", \"Fight run about\",\n\t\t\t\"Editor\", \"Helicannon\", \"Camera\"\n\t\t};\n\t\tsprintf(buf, \"Cam: %s\", modes[TheCamera.Cams[TheCamera.ActiveCam].Mode]);\n\t\tCDebug::PrintAt(buf, 2, 5);\n\t}\n\n\tif(DebugCamMode != MODE_NONE){\n\t\tswitch(Mode){\n\t\tcase MODE_FOLLOWPED:\n\t\t\tsprintf(buf, \"Debug:- Cam Choice1. No Locking, used as game default\");\n\t\t\tbreak;\n\t\tcase MODE_REACTION:\n\t\t\tsprintf(buf, \"Debug:- Cam Choice2. Reaction Cam On A String \");\n\t\t\tsprintf(buf, \"        Uses Locking Button LeftShoulder 1. \");\t// lie\n\t\t\tbreak;\n\t\tcase MODE_FOLLOW_PED_WITH_BIND:\n\t\t\tsprintf(buf, \"Debug:- Cam Choice3. Game ReactionCam with Locking \");\n\t\t\tsprintf(buf, \"        Uses Locking Button LeftShoulder 1. \");\n\t\t\tbreak;\n\t\tcase MODE_CHRIS:\n\t\t\tsprintf(buf, \"Debug:- Cam Choice4. Chris's idea.  \");\n\t\t\tsprintf(buf, \"        Uses Locking Button LeftShoulder 1. \");\n\t\t\tsprintf(buf, \"        Also control the camera using the right analogue stick.\");\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\n// This code is really bad. wtf R*?\nCVector\nCCam::DoAverageOnVector(const CVector &vec)\n{\n\tint i;\n\tCVector Average = CVector(0.0f, 0.0f, 0.0f);\n\n\tif(ResetStatics){\n\t\tm_iRunningVectorArrayPos = 0;\n\t\tm_iRunningVectorCounter = 1;\n\t}\n\n\t// TODO: make this work with NUMBER_OF_VECTORS_FOR_AVERAGE != 2\n\tif(m_iRunningVectorCounter == 3){\n\t\tm_arrPreviousVectors[0] = m_arrPreviousVectors[1];\n\t\tm_arrPreviousVectors[1] = vec;\n\t}else\n\t\tm_arrPreviousVectors[m_iRunningVectorArrayPos] = vec;\n\n\tfor(i = 0; i <= m_iRunningVectorArrayPos; i++)\n\t\tAverage += m_arrPreviousVectors[i];\n\tAverage /= i;\n\n\tm_iRunningVectorArrayPos++;\n\tm_iRunningVectorCounter++;\n\tif(m_iRunningVectorArrayPos >= NUMBER_OF_VECTORS_FOR_AVERAGE)\n\t\tm_iRunningVectorArrayPos = NUMBER_OF_VECTORS_FOR_AVERAGE-1;\n\tif(m_iRunningVectorCounter > NUMBER_OF_VECTORS_FOR_AVERAGE+1)\n\t\tm_iRunningVectorCounter = NUMBER_OF_VECTORS_FOR_AVERAGE+1;\n\n\treturn Average;\n}\n\nfloat DefaultAcceleration = 0.045f;\nfloat DefaultMaxStep = 0.15f;\nfloat fDefaultSpeedStep = 0.025f;\nfloat fDefaultSpeedMultiplier = 0.09f;\nfloat fDefaultSpeedLimit = 0.15f;\nfloat fDefaultSpeedStep4Avoid = 0.02f;\nfloat fDefaultSpeedMultiplier4Avoid = 0.05f;\nfloat fDefaultSpeedLimit4Avoid = 0.25f;\nfloat fAvoidGeomThreshhold = 1.5f;\nfloat fMiniGunBetaOffset = 0.3f;\n\nvoid\nCCam::Process_FollowPed(const CVector &CameraTarget, float TargetOrientation, float, float)\n{\n\tif(!CamTargetEntity->IsPed())\n\t\treturn;\n\n\tCVector TargetCoors, Dist, IdealSource;\n\tfloat Length = 0.0f;\n\tstatic bool PickedASide;\n\tstatic float FixedTargetOrientation = 0.0f;\n\tfloat AngleToGoTo = 0.0f;\n\tbool StandingInTrain = false;\n\tfloat ZoomGroundTarget = 0.0f;\n\tfloat ZoomZTarget = 0.0f;\n\tstatic int TimeIndicatedWantedToGoDown = 0;\n\tstatic bool StartedCountingForGoDown = false;\n\tstatic float ZoomGround = 0.0f;\n\tstatic float ZoomGroundSpeed = 0.0f;\n\tstatic float ZoomZ = 0.0f;\n\tstatic float ZoomZSpeed = 0.0f;\n\tfloat DeltaBeta;\n\n\tm_bFixingBeta = false;\n\tbBelowMinDist = false;\n\tbBehindPlayerDesired = false;\n\n\tFOV = DefaultFOV;\n\n\tif(ResetStatics){\n\t\tRotating = false;\n\t\tm_bCollisionChecksOn = true;\n\t\tFixedTargetOrientation = 0.0f;\n\t\tPickedASide = false;\n\t\tStartedCountingForGoDown = false;\n\t\tAngleToGoTo = 0.0f;\n\t\tZoomGround = 0.0f;\n\t\tZoomGroundSpeed = 0.0f;\n\t\tZoomZ = 0.0f;\n\t\tZoomZSpeed = 0.0f;\n\t\tDistance = 500.0f;\n\t}\n\n\n\tTargetCoors = CameraTarget;\n\n\t// Take speed of thing we're standing on into account\n\tCVector GroundMovement(0.0f, 0.0f, 0.0f);\n\tCPhysical *ground = (CPhysical*)((CPed*)CamTargetEntity)->m_pCurSurface;\n\tif(ground && (ground->IsVehicle() || ground->IsObject()))\n\t\tGroundMovement += ground->GetSpeed(CamTargetEntity->GetPosition() - ground->GetPosition()) * CTimer::GetTimeStep();\n\n\tSource += GroundMovement;\n\tIdealSource = Source;\n\tTargetCoors.z += m_fSyphonModeTargetZOffSet;\n\n\tTargetCoors.z = DoAverageOnVector(TargetCoors).z;\n\n\tDist.x = IdealSource.x - TargetCoors.x;\n\tDist.y = IdealSource.y - TargetCoors.y;\n\tLength = Dist.Magnitude2D();\n\n\t// Cam on a string. With a fixed distance. Zoom in/out is done later.\n\tif(Length != 0.0f){\n\t\tIdealSource = TargetCoors + CVector(Dist.x, Dist.y, 0.0f)/Length * m_fMinRealGroundDist;\n\t\tIdealSource.z += GroundMovement.z;\n\t}else\n\t\tIdealSource = TargetCoors + CVector(1.0f, 1.0f, 0.0f);\n\n\tif(TheCamera.m_bUseTransitionBeta && ResetStatics){\n\t\tCVector VecDistance;\n\t\tIdealSource.x = TargetCoors.x + m_fMinRealGroundDist*Cos(m_fTransitionBeta);\n\t\tIdealSource.y = TargetCoors.y + m_fMinRealGroundDist*Sin(m_fTransitionBeta);\n\t\tBeta = CGeneral::GetATanOfXY(IdealSource.x - TargetCoors.x, IdealSource.y - TargetCoors.y);\n\t}else\n\t\tBeta = CGeneral::GetATanOfXY(Source.x - TargetCoors.x, Source.y - TargetCoors.y);\n\n\tif(TheCamera.m_bCamDirectlyBehind){\n\t\t m_bCollisionChecksOn = true;\n\t\t Beta = TargetOrientation + PI;\n\t}\n\n\tif(FindPlayerVehicle())\n\t\tif(FindPlayerVehicle()->m_vehType == VEHICLE_TYPE_TRAIN)\n\t\t\tStandingInTrain = true;\n\n\tif(TheCamera.m_bCamDirectlyInFront){\n\t\t m_bCollisionChecksOn = true;\n\t\t Beta = TargetOrientation;\n\t}\n\n\twhile(Beta >= PI) Beta -= 2.0f * PI;\n\twhile(Beta < -PI) Beta += 2.0f * PI;\n\n\tif(TheCamera.PedZoomIndicator == CAM_ZOOM_1 &&\n\t   ((CPed*)CamTargetEntity)->GetPedState() != PED_ENTER_CAR &&\n\t   ((CPed*)CamTargetEntity)->GetPedState() != PED_CARJACK){\n\t\tZoomGroundTarget = m_fTargetZoomGroundOne;\n\t\tZoomZTarget = m_fTargetZoomOneZExtra;\n\t}else if(TheCamera.PedZoomIndicator == CAM_ZOOM_2 || TheCamera.PedZoomIndicator == CAM_ZOOM_1){\n\t\tZoomGroundTarget = m_fTargetZoomGroundTwo;\n\t\tZoomZTarget = m_fTargetZoomTwoZExtra;\n\t}else if(TheCamera.PedZoomIndicator == CAM_ZOOM_3){\n\t\tZoomGroundTarget = m_fTargetZoomGroundThree;\n\t\tZoomZTarget = m_fTargetZoomThreeZExtra;\n\t}\n\tif(m_fCloseInPedHeightOffset >  0.00001f){\n\t\tZoomGroundTarget = m_fTargetCloseInDist;\n\t\tZoomZTarget = m_fTargetZoomZCloseIn;\n\t}\n\tif(ResetStatics){\n\t\tZoomGround = ZoomGroundTarget;\n\t\tZoomZ = ZoomZTarget;\n\t}\n\n\tfloat SpeedStep = fDefaultSpeedStep;\n\tfloat SpeedMultiplier = fDefaultSpeedMultiplier;\n\tfloat SpeedLimit = fDefaultSpeedLimit;\n\tbool Shooting = false;\n\tCPed *ped = (CPed*)CamTargetEntity;\n\tif(ped->GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED)\n\t\tif(CPad::GetPad(0)->GetWeapon())\n\t\t\tShooting = true;\n\tif(ped->GetWeapon()->m_eWeaponType == WEAPONTYPE_DETONATOR ||\n\t   ped->GetWeapon()->m_eWeaponType == WEAPONTYPE_BASEBALLBAT)\n\t\tShooting = false;\n\n\n\t// Figure out if and where we want to rotate\n\n\tif(CPad::GetPad(0)->ForceCameraBehindPlayer() && !CPickups::PlayerOnWeaponPickup || Shooting){\n\n\t\t// Center cam behind player\n\n\t\tif(PickedASide){\n\t\t\tif(AngleToGoTo == 0.0f){\n\t\t\t\tFixedTargetOrientation = TargetOrientation + PI;\n\t\t\t\tif(Shooting && ped->GetWeapon()->m_eWeaponType == WEAPONTYPE_MINIGUN)\n\t\t\t\t\tFixedTargetOrientation -= fMiniGunBetaOffset;\n\t\t\t}\n\t\t\tRotating = true;\n\t\t}else{\n\t\t\tFixedTargetOrientation = TargetOrientation + PI;\n\t\t\tRotating = true;\n\t\t\tPickedASide = true;\n\t\t\tif(Shooting && ped->GetWeapon()->m_eWeaponType == WEAPONTYPE_MINIGUN)\n\t\t\t\tFixedTargetOrientation -= fMiniGunBetaOffset;\n\t\t}\n\t}else if(Abs(TheCamera.m_fAvoidTheGeometryProbsTimer) > fAvoidGeomThreshhold && !Rotating ){\n\n\t\tif(TheCamera.m_fAvoidTheGeometryProbsTimer < 0.0f)\n\t\t\tFixedTargetOrientation = TargetOrientation;\n\t\telse\n\t\t\tFixedTargetOrientation = TargetOrientation + PI;\n\t\tfloat dist = (Source - TargetCoors).Magnitude();\n\t\tfloat mult = dist > 0.1f ? 1.0f/dist : 10.0f;\n\t\tSpeedStep = mult * fDefaultSpeedStep4Avoid;\n\t\tSpeedMultiplier = mult * fDefaultSpeedMultiplier4Avoid;\n\t\tSpeedLimit = mult * fDefaultSpeedLimit4Avoid;\n\t}\n\n\tint MoveState = ((CPed*)CamTargetEntity)->m_nMoveState;\n\tif(MoveState != PEDMOVE_NONE && MoveState != PEDMOVE_STILL &&\n\t   !(CPad::GetPad(0)->ForceCameraBehindPlayer() && !CPickups::PlayerOnWeaponPickup) && !Shooting){\n\t\tRotating = false;\n\t\tif(TheCamera.m_fAvoidTheGeometryProbsTimer <= fAvoidGeomThreshhold)\n\t\t\tBetaSpeed = 0.0f;\n\t}\n\n\t// Now do the Beta rotation\n\n\tfloat RotDistance = m_fMinRealGroundDist;\n\n\tif(Rotating || TheCamera.m_fAvoidTheGeometryProbsTimer > fAvoidGeomThreshhold){\n\t\tm_bFixingBeta = true;\n\n\t\twhile(FixedTargetOrientation >= PI) FixedTargetOrientation -= 2*PI;\n\t\twhile(FixedTargetOrientation < -PI) FixedTargetOrientation += 2*PI;\n\n\t\twhile(Beta >= PI) Beta -= 2*PI;\n\t\twhile(Beta < -PI) Beta += 2*PI;\n\n\n\t\t// This is inlined WellBufferMe - unfortunately modified so we can't just call it\n\t\t{\n\t\tDeltaBeta = FixedTargetOrientation - Beta;\n\t\twhile(DeltaBeta >= PI) DeltaBeta -= 2*PI;\n\t\twhile(DeltaBeta < -PI) DeltaBeta += 2*PI;\n\n\t\t// this is the added bit\n\t\tif(!Rotating){\n\t\t\tif(TheCamera.m_nAvoidTheGeometryProbsDirn == -1 && DeltaBeta > 0.0f ||\n\t\t\t   TheCamera.m_nAvoidTheGeometryProbsDirn == 1 && DeltaBeta < 0.0f)\n\t\t\t\tDeltaBeta *= -1.0f;\n\t\t}\n\n\t\tfloat ReqSpeed = DeltaBeta * SpeedMultiplier;\n\t\t// this is also added\n\t\tReqSpeed = clamp(ReqSpeed, -SpeedLimit, SpeedLimit);\n\n\t\t// Add or subtract absolute depending on sign, genius!\n\t\tif(ReqSpeed - BetaSpeed > 0.0f)\n\t\t\tBetaSpeed += SpeedStep * Abs(ReqSpeed - BetaSpeed) * CTimer::GetTimeStep();\n\t\telse\n\t\t\tBetaSpeed -= SpeedStep * Abs(ReqSpeed - BetaSpeed) * CTimer::GetTimeStep();\n\t\t// this would be simpler:\n\t\t// BetaSpeed += SpeedStep * (ReqSpeed - BetaSpeed) * CTimer::ms_fTimeStep;\n\n\t\tif(ReqSpeed < 0.0f && BetaSpeed < ReqSpeed)\n\t\t\tBetaSpeed = ReqSpeed;\n\t\telse if(ReqSpeed > 0.0f && BetaSpeed > ReqSpeed)\n\t\t\tBetaSpeed = ReqSpeed;\n\n\t\tBeta += BetaSpeed * Min(10.0f, CTimer::GetTimeStep());\n\t\t}\n\n\t\tif(ResetStatics){\n\t\t\tBeta = FixedTargetOrientation;\n\t\t\tBetaSpeed = 0.0f;\n\t\t}\n\n\t\tSource.x = TargetCoors.x + RotDistance * Cos(Beta);\n\t\tSource.y = TargetCoors.y + RotDistance * Sin(Beta);\n\n\t\t// Check if we can stop rotating\n\t\tDeltaBeta = FixedTargetOrientation - Beta;\n\t\twhile(DeltaBeta >= PI) DeltaBeta -= 2*PI;\n\t\twhile(DeltaBeta < -PI) DeltaBeta += 2*PI;\n\t\tif(Abs(DeltaBeta) < DEGTORAD(1.0f) && !bBehindPlayerDesired){\n\t\t\t// Stop rotation\n\t\t\tPickedASide = false;\n\t\t\tRotating = false;\n\t\t\tBetaSpeed = 0.0f;\n\t\t}\n\t}\n\n\n\tif(TheCamera.m_bCamDirectlyBehind || TheCamera.m_bCamDirectlyInFront ||\n\t   StandingInTrain || Rotating ||\n\t   TheCamera.m_bUseTransitionBeta && ResetStatics ||\n\t   Abs(TheCamera.m_fAvoidTheGeometryProbsTimer) > fAvoidGeomThreshhold){\n\t\tif(TheCamera.m_bUseTransitionBeta){\n\t\t\tBeta = m_fTransitionBeta;\n\t\t\tSource.x = TargetCoors.x + RotDistance * Cos(m_fTransitionBeta);\n\t\t\tSource.y = TargetCoors.y + RotDistance * Sin(m_fTransitionBeta);\n\t\t}\n\t\tif(TheCamera.m_bCamDirectlyBehind){\n\t\t\tBeta = TargetOrientation + PI;\n\t\t\tSource.x = TargetCoors.x + RotDistance * Cos(Beta);\n\t\t\tSource.y = TargetCoors.y + RotDistance * Sin(Beta);\n\t\t}\n\t\tif(TheCamera.m_bCamDirectlyInFront){\n\t\t\tBeta = TargetOrientation;\n\t\t\tSource.x = TargetCoors.x + RotDistance * Cos(Beta);\n\t\t\tSource.y = TargetCoors.y + RotDistance * Sin(Beta);\n\t\t}\n\t\tif(StandingInTrain){\n\t\t\tBeta = TargetOrientation + PI;\n\t\t\tSource.x = TargetCoors.x + RotDistance * Cos(Beta);\n\t\t\tSource.y = TargetCoors.y + RotDistance * Sin(Beta);\n\t\t\tm_fDimensionOfHighestNearCar = 0.0f;\n\t\t\tm_fCamBufferedHeight = 0.0f;\n\t\t\tm_fCamBufferedHeightSpeed = 0.0f;\n\t\t}\n\t\tif(StandingInTrain){\n\t\t\tBeta = TargetOrientation + PI;\n\t\t\tSource.x = TargetCoors.x + RotDistance * Cos(Beta);\n\t\t\tSource.y = TargetCoors.y + RotDistance * Sin(Beta);\n\t\t\tm_fDimensionOfHighestNearCar = 0.0f;\n\t\t\tm_fCamBufferedHeight = 0.0f;\n\t\t\tm_fCamBufferedHeightSpeed = 0.0f;\n\t\t}\n\n\t\t// Beta and Source already set in the rotation code\n\t}else{\n\t\tSource = IdealSource;\n\t\tBetaSpeed = 0.0f;\n\t}\n\tSource.z = IdealSource.z;\n\n\t// Zoom out camera\n\tFront = TargetCoors - Source;\n\tFront.Normalise();\n\tWellBufferMe(ZoomGroundTarget, &ZoomGround, &ZoomGroundSpeed, 0.2f, 0.07f, false);\n\tWellBufferMe(ZoomZTarget, &ZoomZ, &ZoomZSpeed, 0.2f, 0.07f, false);\n\tSource.x -= Front.x*ZoomGround;\n\tSource.y -= Front.y*ZoomGround;\n\tSource.z += ZoomZ;\n\n\n\t// Process height offset to avoid peds and cars\n\n\tfloat TargetZOffSet = Max(m_fDimensionOfHighestNearCar, m_fPedBetweenCameraHeightOffset);\n\tfloat TargetHeight = CameraTarget.z + TargetZOffSet - Source.z;\n\n\tif(TargetHeight > m_fCamBufferedHeight){\n\t\t// Have to go up\n\t\tif(TargetZOffSet == m_fPedBetweenCameraHeightOffset && TargetZOffSet > m_fCamBufferedHeight)\n\t\t\tWellBufferMe(TargetHeight, &m_fCamBufferedHeight, &m_fCamBufferedHeightSpeed, 0.2f, 0.04f, false);\n\t\telse\n\t\t\tWellBufferMe(TargetHeight, &m_fCamBufferedHeight, &m_fCamBufferedHeightSpeed, 0.2f, 0.025f, false);\n\t\tStartedCountingForGoDown = false;\n\t}else{\n\t\t// Have to go down\n\t\tif(StartedCountingForGoDown){\n\t\t\tif(CTimer::GetTimeInMilliseconds() != TimeIndicatedWantedToGoDown){\n\t\t\t\tif(TargetHeight > 0.0f)\n\t\t\t\t\tWellBufferMe(TargetHeight, &m_fCamBufferedHeight, &m_fCamBufferedHeightSpeed, 0.2f, 0.01f, false);\n\t\t\t\telse\n\t\t\t\t\tWellBufferMe(0.0f, &m_fCamBufferedHeight, &m_fCamBufferedHeightSpeed, 0.2f, 0.01f, false);\n\t\t\t}\n\t\t}else{\n\t\t\tStartedCountingForGoDown = true;\n\t\t\tTimeIndicatedWantedToGoDown = CTimer::GetTimeInMilliseconds();\n\t\t}\n\t}\n\n\tSource.z += m_fCamBufferedHeight;\n\tTargetCoors.z += Min(1.0f, m_fCamBufferedHeight/2.0f);\n\tm_cvecTargetCoorsForFudgeInter = TargetCoors;\n\n\tCVector OrigSource = Source;\n\tTheCamera.AvoidTheGeometry(OrigSource, TargetCoors, Source, FOV);\n\tfloat TargetDist = (TargetCoors - Source).Magnitude();\n\tif(TargetDist < Distance)\n\t\tDistance = TargetDist;\n\telse{\n\t\tfloat f = Pow(0.97f, CTimer::GetTimeStep());\n\t\tDistance = (1.0f - f)*TargetDist + f*Distance;\n\t\tif(TargetDist > 0.05f)\n\t\t\tSource = TargetCoors + (Source-TargetCoors)*Distance/TargetDist;\n\t\tfloat clip = Distance-fRangePlayerRadius;\n\t\tif(clip < RwCameraGetNearClipPlane(Scene.camera))\n\t\t\tRwCameraSetNearClipPlane(Scene.camera, Max(clip, fCloseNearClipLimit));\n\t}\n\n\tFront = TargetCoors - Source;\n\tm_fRealGroundDist = Front.Magnitude2D();\n\tm_fMinDistAwayFromCamWhenInterPolating = m_fRealGroundDist;\t\n\tFront.Normalise();\n\tGetVectorsReadyForRW();\n\tTheCamera.m_bCamDirectlyBehind = false;\n\tTheCamera.m_bCamDirectlyInFront = false;\n\n\tResetStatics = false;\n}\n\nfloat fBaseDist = 1.7f;\nfloat fAngleDist = 2.0f;\nfloat fFalloff = 3.0f;\nfloat fStickSens = 0.01f;\nfloat fTweakFOV = 1.1f;\nfloat fTranslateCamUp = 0.8f;\nint16 nFadeControlThreshhold = 45;\nfloat fDefaultAlphaOrient = -0.22f;\nfloat fMouseAvoidGeomReturnRate = 0.92f;\n\nvoid\nCCam::Process_FollowPedWithMouse(const CVector &CameraTarget, float TargetOrientation, float, float)\n{\n\tFOV = DefaultFOV;\n\n\tif(!CamTargetEntity->IsPed())\n\t\treturn;\n\n\tCVector TargetCoors;\n\tfloat CamDist;\n\tCColPoint colPoint;\n\tCEntity *entity;\n\n\tif(ResetStatics){\n\t\tRotating = false;\n\t\tm_bCollisionChecksOn = true;\n\t\tCPad::GetPad(0)->ClearMouseHistory();\n\t\tResetStatics = false;\n\t}\n\n\tbool OnTrain = FindPlayerVehicle() && FindPlayerVehicle()->IsTrain();\n\n\tTargetCoors = CameraTarget;\n\tTargetCoors.z += fTranslateCamUp;\n\n\tfloat AlphaOffset, BetaOffset;\n\tif(CPad::GetPad(0)->IsPlayerControlsDisabledBy(PLAYERCONTROL_PLAYERINFO)){\n\t\tCVector ToCam = Source - TargetCoors;\n\t\tToCam.Normalise();\n\t\tif(ToCam.z < -0.9f)\n\t\t\tBetaOffset = TargetOrientation + PI;\n\t\telse\n\t\t\tBetaOffset = Atan2(ToCam.y, ToCam.x);\n\t\tBetaOffset -= Beta;\n\t\tAlphaOffset = 0.0f;\n\t}else{\n\t\t// Look around\n\t\tbool UseMouse = false;\n\t\tfloat MouseX = CPad::GetPad(0)->GetMouseX();\n\t\tfloat MouseY = CPad::GetPad(0)->GetMouseY();\n\t\tfloat LookLeftRight, LookUpDown;\n\t\tif((MouseX != 0.0f || MouseY != 0.0f) && !CPad::GetPad(0)->ArePlayerControlsDisabled()){\n\t\t\tUseMouse = true;\n\t\t\tLookLeftRight = -2.5f*MouseX;\n\t\t\tLookUpDown = 4.0f*MouseY;\n\t\t}else{\n\t\t\tLookLeftRight = -CPad::GetPad(0)->LookAroundLeftRight();\n\t\t\tLookUpDown = CPad::GetPad(0)->LookAroundUpDown();\n\t\t}\n\t\tif(UseMouse){\n\t\t\tBetaOffset = LookLeftRight * TheCamera.m_fMouseAccelHorzntl * FOV/80.0f;\n\t\t\tAlphaOffset = LookUpDown * TheCamera.m_fMouseAccelVertical * FOV/80.0f;\n\t\t}else{\n\t\t\tBetaOffset = LookLeftRight * fStickSens * (1.0f/14.0f) * FOV/80.0f * CTimer::GetTimeStep();\n\t\t\tAlphaOffset = LookUpDown * fStickSens * (0.6f/14.0f) * FOV/80.0f * CTimer::GetTimeStep();\n\t\t}\n\t}\n\n\tif(TheCamera.GetFading() && TheCamera.GetFadingDirection() == FADE_IN && nFadeControlThreshhold < CDraw::FadeValue ||\n\t   CDraw::FadeValue > 200 ||\n\t   CPad::GetPad(0)->IsPlayerControlsDisabledBy(PLAYERCONTROL_PLAYERINFO)){\n\t\tif(Alpha < fDefaultAlphaOrient-0.05f)\n\t\t\tAlphaOffset = 0.05f;\n\t\telse if(Alpha < fDefaultAlphaOrient)\n\t\t\tAlphaOffset = fDefaultAlphaOrient - Alpha;\n\t\telse if(Alpha > fDefaultAlphaOrient+0.05f)\n\t\t\tAlphaOffset = -0.05f;\n\t\telse if(Alpha > fDefaultAlphaOrient)\n\t\t\tAlphaOffset = fDefaultAlphaOrient - Alpha;\n\t\telse\n\t\t\tAlphaOffset = 0.0f;\n\t}\n\n\tAlpha += AlphaOffset;\n\tBeta += BetaOffset;\n\twhile(Beta >= PI) Beta -= 2*PI;\n\twhile(Beta < -PI) Beta += 2*PI;\n\tif(Alpha > DEGTORAD(45.0f)) Alpha = DEGTORAD(45.0f);\n\telse if(Alpha < -DEGTORAD(89.5f)) Alpha = -DEGTORAD(89.5f);\n\n\t// SA code\n#ifdef FREE_CAM\n\tif((CCamera::bFreeCam && Alpha > 0.0f) || (!CCamera::bFreeCam && Alpha > fBaseDist))\n#else\n\tif(Alpha > fBaseDist)\t// comparing an angle against a distance?\n#endif\n\t\tCamDist = fBaseDist + Cos(Min(Alpha*fFalloff, HALFPI))*fAngleDist;\n\telse\n\t\tCamDist = fBaseDist + Cos(Alpha)*fAngleDist;\n\n\tif(TheCamera.m_bUseTransitionBeta)\n\t\tBeta = m_fTransitionBeta;\n\n\tif(TheCamera.m_bCamDirectlyBehind)\n\t\tBeta = TheCamera.m_PedOrientForBehindOrInFront + PI;\n\tif(TheCamera.m_bCamDirectlyInFront)\n\t\tBeta = TheCamera.m_PedOrientForBehindOrInFront;\n\tif(OnTrain)\n\t\tBeta = TargetOrientation;\n\n\tFront.x = Cos(Alpha) * -Cos(Beta);\n\tFront.y = Cos(Alpha) * -Sin(Beta);\n\tFront.z = Sin(Alpha);\n\tSource = TargetCoors - Front*CamDist;\n\tm_cvecTargetCoorsForFudgeInter = TargetCoors;\n\n\t// Clip Source and fix near clip\n\tCWorld::pIgnoreEntity = CamTargetEntity;\n\tentity = nil;\n\tif(CWorld::ProcessLineOfSight(TargetCoors, Source, colPoint, entity, true, true, true, true, false, false, true)){\n\t\tfloat PedColDist = (TargetCoors - colPoint.point).Magnitude();\n\t\tfloat ColCamDist = CamDist - PedColDist;\n\t\tif(entity->IsPed() && ColCamDist > DEFAULT_NEAR + 0.1f){\n\t\t\t// Ped in the way but not clipping through\n\t\t\tif(CWorld::ProcessLineOfSight(colPoint.point, Source, colPoint, entity, true, true, true, true, false, false, true)){\n\t\t\t\tPedColDist = (TargetCoors - colPoint.point).Magnitude();\n\t\t\t\tSource = colPoint.point;\n\t\t\t\tif(PedColDist < DEFAULT_NEAR + 0.3f)\n\t\t\t\t\tRwCameraSetNearClipPlane(Scene.camera, Max(PedColDist-0.3f, 0.05f));\n\t\t\t}else{\n\t\t\t\tRwCameraSetNearClipPlane(Scene.camera, Min(ColCamDist-0.35f, DEFAULT_NEAR));\n\t\t\t}\n\t\t}else{\n\t\t\tSource = colPoint.point;\n\t\t\tif(PedColDist < DEFAULT_NEAR + 0.3f)\n\t\t\t\tRwCameraSetNearClipPlane(Scene.camera, Max(PedColDist-0.3f, 0.05f));\n\t\t}\n\t}\n\tCWorld::pIgnoreEntity = nil;\n\n\tfloat ViewPlaneHeight = Tan(DEGTORAD(FOV) / 2.0f);\n\tfloat ViewPlaneWidth = ViewPlaneHeight * CDraw::CalculateAspectRatio() * fTweakFOV;\n\tfloat Near = RwCameraGetNearClipPlane(Scene.camera);\n\tfloat radius = ViewPlaneWidth*Near;\n\tentity = CWorld::TestSphereAgainstWorld(Source + Front*Near, radius, nil, true, true, false, true, false, false);\n\tint i = 0;\n\twhile(entity){\n\t\tCVector CamToCol = gaTempSphereColPoints[0].point - Source;\n\t\tfloat frontDist = DotProduct(CamToCol, Front);\n\t\tfloat dist = (CamToCol - Front*frontDist).Magnitude() / ViewPlaneWidth;\n\n\t\t// Try to decrease near clip\n\t\tdist = Max(Min(Near, dist), 0.1f);\n\t\tif(dist < Near)\n\t\t\tRwCameraSetNearClipPlane(Scene.camera, dist);\n\n\t\t// Move forward a bit\n\t\tif(dist == 0.1f)\n\t\t\tSource += (TargetCoors - Source)*0.3f;\n\n\t\tNear = RwCameraGetNearClipPlane(Scene.camera);\n#ifndef FIX_BUGS\n\t\t// this is wrong...DEGTORAD missing\n\t\tradius = Tan(FOV / 2.0f) * CDraw::CalculateAspectRatio() * fTweakFOV * Near;\n#else\n\t\tradius = ViewPlaneWidth*Near;\n#endif\n\t\t// Keep testing\n\t\tentity = CWorld::TestSphereAgainstWorld(Source + Front*Near, radius, nil, true, true, false, true, false, false);\n\n\t\ti++;\n\t\tif(i > 5)\n\t\t\tentity = nil;\n\t}\n\n\tfloat TargetDist = (TargetCoors - Source).Magnitude();\n\tif(TargetDist < Distance)\n\t\tDistance = TargetDist;\n\telse{\n\t\tfloat f = Pow(fMouseAvoidGeomReturnRate, CTimer::GetTimeStep());\n\t\tDistance = (1.0f - f)*TargetDist + f*Distance;\n\t\tif(TargetDist > 0.05f)\n\t\t\tSource = TargetCoors + (Source-TargetCoors)*Distance/TargetDist;\n\t\tfloat clip = Distance-fRangePlayerRadius;\n\t\tif(clip < RwCameraGetNearClipPlane(Scene.camera))\n\t\t\tRwCameraSetNearClipPlane(Scene.camera, Max(clip, fCloseNearClipLimit));\n\t}\n\n\tTheCamera.m_bCamDirectlyInFront = false;\n\tTheCamera.m_bCamDirectlyBehind = false;\n\n\tGetVectorsReadyForRW();\n\n\tif(((CPed*)CamTargetEntity)->CanStrafeOrMouseControl() && CDraw::FadeValue < 250 &&\n\t   (TheCamera.GetFadingDirection() != FADE_OUT || CDraw::FadeValue <= 100) &&\n\t   !CPad::GetPad(0)->IsPlayerControlsDisabledBy(PLAYERCONTROL_PLAYERINFO)){\n\t\tfloat Heading = Front.Heading();\n\t\t((CPed*)TheCamera.pTargetEntity)->m_fRotationCur = Heading;\n\t\t((CPed*)TheCamera.pTargetEntity)->m_fRotationDest = Heading;\n\t\tTheCamera.pTargetEntity->SetHeading(Heading);\n\t\tTheCamera.pTargetEntity->GetMatrix().UpdateRW();\n\t}\n}\n\nfloat fBillsBetaOffset;\t// made up name, actually in CCam\n\nvoid\nCCam::Process_BehindCar(const CVector &CameraTarget, float TargetOrientation, float, float)\n{\n\tFOV = DefaultFOV;\n\n\tif(!CamTargetEntity->IsVehicle())\n\t\treturn;\n\n\tCVector TargetCoors = CameraTarget;\n\tTargetCoors.z -= 0.2f;\n\tCA_MAX_DISTANCE = 9.95f;\n\tCA_MIN_DISTANCE = 8.5f;\n\n\tCVector Dist = Source - TargetCoors;\n\tfloat Length = Dist.Magnitude2D();\n\tm_fDistanceBeforeChanges = Length;\n\tif(Length < 0.002f)\n\t\tLength = 0.002f;\n\tBeta = CGeneral::GetATanOfXY(TargetCoors.x - Source.x, TargetCoors.y - Source.y);\n#ifdef TOGGLEABLE_BETA_FEATURES\n\t// This is completely made up but Bill's cam manipulates an angle before calling this\n\t// and otherwise calculating Beta doesn't make much sense.\n\tBeta += fBillsBetaOffset;\n\tfBillsBetaOffset = 0.0f;\n\tDist.x = -Length*Cos(Beta);\n\tDist.y = -Length*Sin(Beta);\n\tSource = TargetCoors + Dist;\n#endif\n\tif(Length > CA_MAX_DISTANCE){\n\t\tSource.x = TargetCoors.x + Dist.x/Length * CA_MAX_DISTANCE;\n\t\tSource.y = TargetCoors.y + Dist.y/Length * CA_MAX_DISTANCE;\n\t}else if(Length < CA_MIN_DISTANCE){\n\t\tSource.x = TargetCoors.x + Dist.x/Length * CA_MIN_DISTANCE;\n\t\tSource.y = TargetCoors.y + Dist.y/Length * CA_MIN_DISTANCE;\n\t}\n\tTargetCoors.z += 0.8f;\n\n\tAlpha = DEGTORAD(25.0f);\n\tSource.z = TargetCoors.z + CA_MAX_DISTANCE*Sin(Alpha);\n\n\tRotCamIfInFrontCar(TargetCoors, TargetOrientation);\n\tm_cvecTargetCoorsForFudgeInter = TargetCoors;\n\tCVector OrigSource = Source;\n\tTheCamera.AvoidTheGeometry(OrigSource, m_cvecTargetCoorsForFudgeInter, Source, FOV);\n\n\tFront = TargetCoors - Source;\n\tResetStatics = false;\n\tGetVectorsReadyForRW();\n}\n\nfloat ZmOneAlphaOffset[] = { -0.01f, 0.1f, 0.125f, -0.1f, -0.06f };\nfloat ZmTwoAlphaOffset[] = { 0.045f, 0.12f, 0.045f, 0.045f, -0.035f };\nfloat ZmThreeAlphaOffset[] = { 0.005f, 0.005f, 0.15f, 0.005f, 0.12f };\nfloat INIT_RC_HELI_HORI_EXTRA = 6.0f;\nfloat INIT_RC_PLANE_HORI_EXTRA = 9.5f;\nfloat INIT_RC_HELI_ALPHA_EXTRA = 0.2f;\nfloat INIT_RC_PLANE_ALPHA_EXTRA = 0.295f;\n\nvoid\nCCam::WorkOutCamHeight(const CVector &TargetCoors, float TargetOrientation, float TargetHeight)\n{\n\tif(!CamTargetEntity->IsVehicle())\n\t\treturn;\n\n\tstatic float AlphaOffset = 0.0;\n\tstatic float AlphaOffsetSpeed = 0.0;\n\tstatic float AlphaDec = 0.0f;\n\n\tbool isHeli = false;\n\tbool isBike = false;\n\tint appearance = ((CVehicle*)CamTargetEntity)->GetVehicleAppearance();\n\tif(appearance == VEHICLE_APPEARANCE_BIKE)\n\t\tisBike = true;\n\tif(appearance == VEHICLE_APPEARANCE_HELI)\n\t\tisHeli = true;\n\tint index = 0;\n\tTheCamera.GetArrPosForVehicleType(appearance, index);\n\n\tfloat ExtraOffset = 0.0f;\n\tint id = CamTargetEntity->GetModelIndex();\n\tif(id == MI_RCRAIDER || id == MI_RCGOBLIN)\n\t\tExtraOffset = INIT_RC_HELI_ALPHA_EXTRA;\n\telse if(id == MI_RCBARON)\n\t\tExtraOffset = INIT_RC_PLANE_ALPHA_EXTRA;\n\n\tif(ResetStatics){\n\t\tAlphaOffset = 0.0f;\n\t\tAlphaOffsetSpeed = 0.0f;\n\t\tAlphaDec = 0.0f;\n\n\t\tif(TheCamera.CarZoomIndicator == CAM_ZOOM_1)\n\t\t\tAlphaOffset = ZmOneAlphaOffset[index] + ExtraOffset;\n\t\telse if(TheCamera.CarZoomIndicator == CAM_ZOOM_2)\n\t\t\tAlphaOffset = ZmTwoAlphaOffset[index] + ExtraOffset;\n\t\telse if(TheCamera.CarZoomIndicator == CAM_ZOOM_3)\n\t\t\tAlphaOffset = ZmThreeAlphaOffset[index] + ExtraOffset;\n\t}\n\n\tif(TheCamera.CarZoomIndicator == CAM_ZOOM_1)\n\t\tWellBufferMe(ZmOneAlphaOffset[index] + ExtraOffset, &AlphaOffset, &AlphaOffsetSpeed, 0.17f, 0.08f, false);\n\telse if(TheCamera.CarZoomIndicator == CAM_ZOOM_2)\n\t\tWellBufferMe(ZmTwoAlphaOffset[index] + ExtraOffset, &AlphaOffset, &AlphaOffsetSpeed, 0.17f, 0.08f, false);\n\telse if(TheCamera.CarZoomIndicator == CAM_ZOOM_3)\n\t\tWellBufferMe(ZmThreeAlphaOffset[index] + ExtraOffset, &AlphaOffset, &AlphaOffsetSpeed, 0.17f, 0.08f, false);\n\n\tfloat Length = (Source - TargetCoors).Magnitude2D();\n\n\tCVector Forward = CamTargetEntity->GetForward();\n\tfloat CarAlpha = CGeneral::GetATanOfXY(Forward.Magnitude2D(), Forward.z);\n\t// this shouldn't be necessary....\n\twhile(CarAlpha >= PI) CarAlpha -= 2*PI;\n\twhile(CarAlpha < -PI) CarAlpha += 2*PI;\n\n\twhile(Beta >= PI) Beta -= 2*PI;\n\twhile(Beta < -PI) Beta += 2*PI;\n\n\tfloat DeltaBeta = Beta - TargetOrientation;\n\twhile(DeltaBeta >= PI) DeltaBeta -= 2*PI;\n\twhile(DeltaBeta < -PI) DeltaBeta += 2*PI;\n\n\tfloat BehindCarNess = Cos(DeltaBeta);\t// 1 if behind car, 0 if side, -1 if in front\n\tCarAlpha = -CarAlpha * BehindCarNess;\n\n\tfloat fwdSpeed = DotProduct(((CPhysical*)CamTargetEntity)->m_vecMoveSpeed, CamTargetEntity->GetForward())*180.0f;\n\tif(CamTargetEntity->GetModelIndex() == MI_FIRETRUCK && CPad::GetPad(0)->GetCarGunFired()){\n\t\tCarAlpha = DEGTORAD(10.0f);\n\t}else if(isHeli){\n\t\tCarAlpha = 0.0f;\n\t\tfloat heliFwdZ = CamTargetEntity->GetForward().z;\n\t\tfloat heliFwdXY = CamTargetEntity->GetForward().Magnitude2D();\n\t\tfloat alphaAmount = Min(Abs(fwdSpeed/90.0f), 1.0f);\n\t\tif(heliFwdXY != 0.0f || heliFwdZ != 0.0f)\n\t\t\tCarAlpha = CGeneral::GetATanOfXY(heliFwdXY, Abs(heliFwdZ)) * alphaAmount;\n\n\t\tCColPoint point;\n\t\tCEntity *entity = nil;\n\t\tCVector Test = Source;\n\t\tTest.z = TargetCoors.z + 0.2f + Length*Sin(CarAlpha+AlphaOffset) + m_fCloseInCarHeightOffset;\n\t\tif(CWorld::ProcessVerticalLine(Test, CamTargetEntity->GetPosition().z, point, entity, true, false, false, false, false, false, nil)){\n\t\t\tfloat sin = (point.point.z - TargetCoors.z - 0.2f - m_fCloseInCarHeightOffset)/Length;\n\t\t\tCarAlpha = Asin(clamp(sin, -1.0f, 1.0f)) - AlphaOffset;\n\t\t\tif(CarAlpha < 0.0f)\n\t\t\t\tAlphaOffset += CarAlpha;\n\t\t} \n\t}\n\n\tCarAlpha = CGeneral::LimitRadianAngle(CarAlpha);\n\tif(CarAlpha < 0.0f) CarAlpha = 0.0f;\n\tif(CarAlpha > DEGTORAD(89.0f)) CarAlpha = DEGTORAD(89.0f);\n\n\tif(ResetStatics)\n\t\tAlpha = CarAlpha;\n\n\tfloat TargetAlpha = Alpha;\n\tfloat DeltaAlpha = CarAlpha - TargetAlpha;\n\twhile(DeltaAlpha >= PI) DeltaAlpha -= 2*PI;\n\twhile(DeltaAlpha < -PI) DeltaAlpha += 2*PI;\n\tif(Abs(DeltaAlpha) > 0.0f && !TheCamera.m_bVehicleSuspenHigh)\n\t\tTargetAlpha = CarAlpha;\n\n\tif(isBike)\n\t\tWellBufferMe(TargetAlpha, &Alpha, &AlphaSpeed, 0.09f, 0.04f, true);\n\telse if(isHeli)\n\t\tWellBufferMe(TargetAlpha, &Alpha, &AlphaSpeed, 0.09f, 0.04f, true);\n\telse\n\t\tWellBufferMe(TargetAlpha, &Alpha, &AlphaSpeed, 0.15f, 0.07f, true);\n\n\tSource.z = TargetCoors.z + Sin(Alpha + AlphaOffset)*Length + m_fCloseInCarHeightOffset;\n\tAlphaOffset -= AlphaDec;\n}\n\n// Rotate cam behind the car when the car is moving forward\nbool\nCCam::RotCamIfInFrontCar(CVector &TargetCoors, float TargetOrientation)\n{\n\tfloat BetaMaxSpeed = 0.15f;\n\tfloat BetaAcceleration = 0.007f;\n\tbool MovingForward = false;\n\tfloat MaxDiffBeta = DEGTORAD(160.0f);\n\tCPhysical *phys = (CPhysical*)CamTargetEntity;\n\n\tfloat ForwardSpeed = DotProduct(phys->GetForward(), phys->GetSpeed(CVector(0.0f, 0.0f, 0.0f)));\n\tif(ForwardSpeed > 0.02f)\n\t\tMovingForward = true;\n\n\tif(phys->IsVehicle() && (phys->GetModelIndex() == MI_SPARROW || phys->GetModelIndex() == MI_HUNTER)){\n\t\tMaxDiffBeta = DEGTORAD(160.0f);\n\t\tBetaMaxSpeed = 0.1f;\n\t\tBetaAcceleration = 0.003f;\n\t\tCVector speed = phys->GetSpeed(CVector(0.0f, 0.0f, 0.0f));\n\t\tspeed.z = 0.0f;\n\t\tif(50.0f*speed.Magnitude() > 3.13f)\n\t\t\tTargetOrientation = CGeneral::GetATanOfXY(speed.x, speed.y);\n\t}\n\n\tfloat Dist = (Source - TargetCoors).Magnitude2D();\n\n\tfloat DeltaBeta = TargetOrientation - Beta;\n\twhile(DeltaBeta >= PI) DeltaBeta -= 2*PI;\n\twhile(DeltaBeta < -PI) DeltaBeta += 2*PI;\n\n\tif(Abs(DeltaBeta) > PI-MaxDiffBeta && MovingForward && TheCamera.m_uiTransitionState == 0)\n\t\tm_bFixingBeta = true;\n\n\tCPad *pad = CPad::GetPad(0);\n\tif(!(pad->GetLookBehindForCar() || pad->GetLookBehindForPed() || pad->GetLookLeft() || pad->GetLookRight()))\n\t\tif(DirectionWasLooking != LOOKING_FORWARD)\n\t\t\tTheCamera.m_bCamDirectlyBehind = true;\n\n\tif(!m_bFixingBeta && !TheCamera.m_bUseTransitionBeta && !TheCamera.m_bCamDirectlyBehind && !TheCamera.m_bCamDirectlyInFront)\n\t\treturn false;\n\n\tbool SetBeta = false;\n\tif(TheCamera.m_bCamDirectlyBehind || TheCamera.m_bCamDirectlyInFront || TheCamera.m_bUseTransitionBeta)\n\t\tif(&TheCamera.Cams[TheCamera.ActiveCam] == this)\n\t\t\tSetBeta = true;\n\n\tif(m_bFixingBeta || SetBeta){\n\t\tWellBufferMe(TargetOrientation, &Beta, &BetaSpeed, BetaMaxSpeed, BetaAcceleration, true);\n\n\t\tif(TheCamera.m_bCamDirectlyBehind && &TheCamera.Cams[TheCamera.ActiveCam] == this)\n\t\t\tBeta = TargetOrientation;\n\t\tif(TheCamera.m_bCamDirectlyInFront && &TheCamera.Cams[TheCamera.ActiveCam] == this)\n\t\t\tBeta = TargetOrientation + PI;\n\t\tif(TheCamera.m_bUseTransitionBeta && &TheCamera.Cams[TheCamera.ActiveCam] == this)\n\t\t\tBeta = m_fTransitionBeta;\n\n\t\tSource.x = TargetCoors.x - Cos(Beta)*Dist;\n\t\tSource.y = TargetCoors.y - Sin(Beta)*Dist;\n\n\t\t// Check if we're done\n\t\tDeltaBeta = TargetOrientation - Beta;\n\t\twhile(DeltaBeta >= PI) DeltaBeta -= 2*PI;\n\t\twhile(DeltaBeta < -PI) DeltaBeta += 2*PI;\n\t\tif(Abs(DeltaBeta) < DEGTORAD(2.0f))\n\t\t\tm_bFixingBeta = false;\n\t}\n\tTheCamera.m_bCamDirectlyBehind = false;\n\tTheCamera.m_bCamDirectlyInFront = false;\n\treturn true;\n}\n\nfloat FIRETRUCK_TRACKING_MULT = 0.1f;\nfloat fTestShiftHeliCamTarget = 0.6f;\nfloat TiltTopSpeed[] = { 0.035f, 0.035f, 0.001f, 0.005f, 0.035f };\nfloat TiltSpeedStep[] = { 0.016f, 0.016f, 0.0002f, 0.0014f, 0.016f };\nfloat TiltOverShoot[] = { 1.05f, 1.05f, 0.0f, 0.0f, 1.0f };\n\nvoid\nCCam::Process_Cam_On_A_String(const CVector &CameraTarget, float TargetOrientation, float, float)\n{\n\tif(!CamTargetEntity->IsVehicle())\n\t\treturn;\n\n\t// unused\n\t// ((CVehicle*)CamTargetEntity)->GetVehicleAppearance();\n\n\tFOV = DefaultFOV;\n\n\tif(ResetStatics){\n\t\tAlphaSpeed = 0.0f;\n\t\tm_fTilt = 0.0f;\n\t\tm_fTiltSpeed = 0.0;\n\t}\n\n\tCBaseModelInfo *mi = CModelInfo::GetModelInfo(CamTargetEntity->GetModelIndex());\n\tCVector Dimensions = mi->GetColModel()->boundingBox.max - mi->GetColModel()->boundingBox.min;\n\tCVector TargetCoors = CameraTarget;\n\tfloat BaseDist = Dimensions.Magnitude();\n\n\tif(((CVehicle*)CamTargetEntity)->IsBike())\n\t\tBaseDist *= 1.45f;\n\tif(((CVehicle*)CamTargetEntity)->GetVehicleAppearance() == VEHICLE_APPEARANCE_HELI &&\n\t   CamTargetEntity->GetStatus() != STATUS_PLAYER_REMOTE)\n\t\tTargetCoors += fTestShiftHeliCamTarget * CamTargetEntity->GetUp() * Dimensions.z;\n\telse\n\t\tTargetCoors.z += 0.8f*Dimensions.z;\n\n\tBeta = CGeneral::GetATanOfXY(TargetCoors.x - Source.x, TargetCoors.y - Source.y);\n\tAlpha = CGeneral::LimitRadianAngle(Alpha);\n\tBeta = CGeneral::LimitRadianAngle(Beta);\n\n\tif(CamTargetEntity->GetModelIndex() == MI_FIRETRUCK && CPad::GetPad(0)->GetCarGunFired() &&\n\t   ((CVehicle*)CamTargetEntity)->m_vecMoveSpeed.Magnitude2D() < 0.01f){\n\t\tfloat TargetBeta = CamTargetEntity->GetForward().Heading() - ((CAutomobile*)CamTargetEntity)->m_fCarGunLR + HALFPI;\n\t\tTargetBeta = CGeneral::LimitRadianAngle(TargetBeta);\n\t\tfloat DeltaBeta = TargetBeta - Beta;\n\t\tif(DeltaBeta > PI) DeltaBeta -= TWOPI;\n\t\telse if(DeltaBeta < -PI) DeltaBeta += TWOPI;\n\t\tfloat dist = (TargetCoors - Source).Magnitude();\n\t\tdist = FIRETRUCK_TRACKING_MULT*dist*clamp(DeltaBeta, -0.8f, 0.8f);\n\t\tSource += dist*CrossProduct(Front, CVector(0.0f, 0.0f, 1.0f));\n\t}\n\n\tm_fDistanceBeforeChanges = (Source - TargetCoors).Magnitude2D();\n\n\tCam_On_A_String_Unobscured(TargetCoors, BaseDist);\n\tWorkOutCamHeight(TargetCoors, TargetOrientation, Dimensions.z);\n\tRotCamIfInFrontCar(TargetCoors, TargetOrientation);\n\tFixCamWhenObscuredByVehicle(TargetCoors);\n\n\tm_cvecTargetCoorsForFudgeInter = TargetCoors;\n\tCVector OrigSource = Source;\n\tif(CWorld::GetIsLineOfSightClear(CamTargetEntity->GetPosition(), m_cvecTargetCoorsForFudgeInter, true, false, false, true, false, false, true))\n\t\tTheCamera.AvoidTheGeometry(OrigSource, m_cvecTargetCoorsForFudgeInter, Source, FOV);\n\telse\n\t\tTheCamera.AvoidTheGeometry(OrigSource, CamTargetEntity->GetPosition(), Source, FOV);\n\n\tFront = TargetCoors - Source;\n\tFront.Normalise();\n\n\tint appearance = ((CVehicle*)CamTargetEntity)->GetVehicleAppearance();\n\tint index = 0;\n\tTheCamera.GetArrPosForVehicleType(appearance, index);\n\n\tif(appearance == VEHICLE_APPEARANCE_HELI){\n\t\tfloat TargetTilt = DotProduct(Front, ((CVehicle*)CamTargetEntity)->GetSpeed(CVector(0.0f, 0.0f, 0.0f)));\n\t\tCVector UpTarget = CamTargetEntity->GetUp();\n\t\tUpTarget.Normalise();\n\t\tint dir = TargetTilt < 0.0f ? -1 : 1;\n\t\tif(m_fTilt != 0.0f)\n\t\t\tTargetTilt += TiltOverShoot[index]*TargetTilt/m_fTilt * dir;\n\t\tWellBufferMe(TargetTilt, &m_fTilt, &m_fTiltSpeed, TiltTopSpeed[index], TiltSpeedStep[index], false);\n\n\t\tUp = CVector(0.0f, 0.0f, 1.0f) - (CVector(0.0f, 0.0f, 1.0f) - UpTarget)*m_fTilt;\n\t\tUp.Normalise();\n\t\tFront.Normalise();\n\t\tCVector Left = CrossProduct(Up, Front);\n\t\tUp = CrossProduct(Front, Left);\n\t\tUp.Normalise();\n\t}else{\n\t\tfloat TargetRoll;\n\t\tif(CPad::GetPad(0)->GetDPadLeft() || CPad::GetPad(0)->GetDPadRight()){\n\t\t\tfloat fwdSpeed = 180.0f*DotProduct(((CVehicle*)CamTargetEntity)->m_vecMoveSpeed, CamTargetEntity->GetForward());\n\t\t\tif(fwdSpeed > 210.0f) fwdSpeed = 210.0f;\n\t\t\tif(CPad::GetPad(0)->GetDPadLeft())\n\t\t\t\tTargetRoll = DEGTORAD(10.0f)*TiltOverShoot[index] + f_max_role_angle;\n\t\t\telse\n\t\t\t\tTargetRoll = -(DEGTORAD(10.0f)*TiltOverShoot[index] + f_max_role_angle);\n\t\t\tCVector FwdTarget = CamTargetEntity->GetForward();\n\t\t\tFwdTarget.Normalise();\n\t\t\tfloat AngleDiff = DotProduct(FwdTarget, Front);\n\t\t\tAngleDiff = Acos(Min(Abs(AngleDiff), 1.0f));\n\t\t\tTargetRoll *= fwdSpeed/210.0f * Sin(AngleDiff);\n\t\t}else{\n\t\t\tfloat fwdSpeed = 180.0f*DotProduct(((CVehicle*)CamTargetEntity)->m_vecMoveSpeed, CamTargetEntity->GetForward());\n\t\t\tif(fwdSpeed > 210.0f) fwdSpeed = 210.0f;\n\t\t\tTargetRoll = CPad::GetPad(0)->GetLeftStickX()/128.0f * fwdSpeed/210.0f;\n\t\t\tCVector FwdTarget = CamTargetEntity->GetForward();\n\t\t\tFwdTarget.Normalise();\n\t\t\tfloat AngleDiff = DotProduct(FwdTarget, Front);\n\t\t\tAngleDiff = Acos(Min(Abs(AngleDiff), 1.0f));\n\t\t\tTargetRoll *= (DEGTORAD(10.0f)*TiltOverShoot[index] + f_max_role_angle) * Sin(AngleDiff);\n\t\t}\n\n\t\tWellBufferMe(TargetRoll, &f_Roll, &f_rollSpeed, 0.15f, 0.07f, false);\n\t\tUp = CVector(Cos(f_Roll + HALFPI), 0.0f, Sin(f_Roll + HALFPI));\n\t\tUp.Normalise();\n\t\tFront.Normalise();\n\t\tCVector Left = CrossProduct(Up, Front);\n\t\tLeft.Normalise();\n\t\tUp = CrossProduct(Front, Left);\n\t\tUp.Normalise();\n\t}\n\n\tResetStatics = false;\n}\n\n// Basic Cam on a string algorithm\nvoid\nCCam::Cam_On_A_String_Unobscured(const CVector &TargetCoors, float BaseDist)\n{\n\tint id = CamTargetEntity->GetModelIndex();\n\tfloat ExtraDist = 0.0f;\n\tif(id == MI_RCRAIDER || id == MI_RCGOBLIN)\n\t\tExtraDist = INIT_RC_HELI_HORI_EXTRA;\n\telse if(id == MI_RCBARON)\n\t\tExtraDist = INIT_RC_PLANE_HORI_EXTRA;\n\n\tCA_MAX_DISTANCE = BaseDist + 0.1f + TheCamera.CarZoomValueSmooth + ExtraDist;\n\tCA_MIN_DISTANCE = Min(BaseDist*0.6f, 3.5f);\n\tif(CA_MIN_DISTANCE > CA_MAX_DISTANCE)\n\t\tCA_MIN_DISTANCE = CA_MAX_DISTANCE - 0.05f;\n\n\tCVector Dist = Source - TargetCoors;\n\n\tif(ResetStatics)\n\t\tSource = TargetCoors + Dist*(CA_MAX_DISTANCE + 1.0f);\n\n\tDist = Source - TargetCoors;\n\n\tfloat Length = Dist.Magnitude2D();\n\tif(Length < 0.001f){\n\t\t// This probably shouldn't happen. reset view\n\t\tCVector Forward = CamTargetEntity->GetForward();\n\t\tForward.z = 0.0f;\n\t\tForward.Normalise();\n\t\tSource = TargetCoors - Forward*CA_MAX_DISTANCE;\n\t\tDist = Source - TargetCoors;\n\t\tLength = Dist.Magnitude2D();\n\t}\n\n\tif(Length > CA_MAX_DISTANCE){\n\t\tSource.x = TargetCoors.x + Dist.x/Length * CA_MAX_DISTANCE;\n\t\tSource.y = TargetCoors.y + Dist.y/Length * CA_MAX_DISTANCE;\n\t}else if(Length < CA_MIN_DISTANCE){\n\t\tSource.x = TargetCoors.x + Dist.x/Length * CA_MIN_DISTANCE;\n\t\tSource.y = TargetCoors.y + Dist.y/Length * CA_MIN_DISTANCE;\n\t}\n}\n\nvoid\nCCam::FixCamWhenObscuredByVehicle(const CVector &TargetCoors)\n{\n\t// BUG? is this never reset\n\tstatic float HeightFixerCarsObscuring = 0.0f;\n\tstatic float HeightFixerCarsObscuringSpeed = 0.0f;\n\tCColPoint colPoint;\n\tCEntity *entity = nil;\n\n\tfloat HeightTarget = 0.0f;\n\tif(CWorld::ProcessLineOfSight(TargetCoors, Source, colPoint, entity, false, true, false, false, false, false, false)){\n\t\tCBaseModelInfo *mi = CModelInfo::GetModelInfo(entity->GetModelIndex());\n\t\tHeightTarget = mi->GetColModel()->boundingBox.max.z + 1.0f + TargetCoors.z - Source.z;\n\t\tif(HeightTarget < 0.0f)\n\t\t\tHeightTarget = 0.0f;\n\t}\n\tWellBufferMe(HeightTarget, &HeightFixerCarsObscuring, &HeightFixerCarsObscuringSpeed, 0.2f, 0.025f, false);\n\tSource.z += HeightFixerCarsObscuring;\n}\n\nvoid\nCCam::Process_TopDown(const CVector &CameraTarget, float TargetOrientation, float SpeedVar, float TargetSpeedVar)\n{\n\tFOV = DefaultFOV;\n\n\tif(!CamTargetEntity->IsVehicle())\n\t\treturn;\n\n\tfloat Dist;\n\tfloat HeightTarget = 0.0f;\n\tstatic float AdjustHeightTargetMoveBuffer = 0.0f;\n\tstatic float AdjustHeightTargetMoveSpeed = 0.0f;\n\tstatic float NearClipDistance = 1.5f;\n\tconst float FarClipDistance = 200.0f;\n\tCVector TargetFront, Target;\n\tCVector TestSource, TestTarget;\n\tCColPoint colPoint;\n\tCEntity *entity;\n\n\tTargetFront = CameraTarget;\n\tTargetFront.x += 18.0f*CamTargetEntity->GetForward().x*SpeedVar;\n\tTargetFront.y += 18.0f*CamTargetEntity->GetForward().y*SpeedVar;\n\n\tif(ResetStatics){\n\t\tAdjustHeightTargetMoveBuffer = 0.0f;\n\t\tAdjustHeightTargetMoveSpeed = 0.0f;\n\t}\n\n\tfloat f = Pow(0.8f, 4.0f);\n\tTarget = f*CameraTarget + (1.0f-f)*TargetFront;\n\tif(Mode == MODE_GTACLASSIC)\n\t\tSpeedVar = TargetSpeedVar;\n\tSource = Target + CVector(0.0f, 0.0f, (40.0f*SpeedVar + 30.0f)*0.8f);\n\t// What is this? looks horrible\n\tif(Mode == MODE_GTACLASSIC)\n\t\tSource.x += (uint8)(100.0f*CameraTarget.x)/500.0f;\n\n\tTestSource = Source;\n\tTestTarget = TestSource;\n\tTestTarget.z = Target.z;\n\tif(CWorld::ProcessLineOfSight(TestTarget, TestSource, colPoint, entity, true, false, false, false, false, false, false)){\n\t\tif(Source.z < colPoint.point.z+3.0f)\n\t\t\tHeightTarget = colPoint.point.z+3.0f - Source.z;\n\t}else{\n\t\tTestSource = Source;\n\t\tTestTarget = TestSource;\n\t\tTestTarget.z += 10.0f;\n\t\tif(CWorld::ProcessLineOfSight(TestTarget, TestSource, colPoint, entity, true, false, false, false, false, false, false))\n\t\t\tif(Source.z < colPoint.point.z+3.0f)\n\t\t\t\tHeightTarget = colPoint.point.z+3.0f - Source.z;\n\t}\n\tWellBufferMe(HeightTarget, &AdjustHeightTargetMoveBuffer, &AdjustHeightTargetMoveSpeed, 0.2f, 0.02f, false);\n\tSource.z += AdjustHeightTargetMoveBuffer;\n\n\tif(RwCameraGetFarClipPlane(Scene.camera) > FarClipDistance)\n\t\tRwCameraSetFarClipPlane(Scene.camera, FarClipDistance);\n\tRwCameraSetNearClipPlane(Scene.camera, NearClipDistance);\n\n\tFront = CVector(-0.01f, -0.01f, -1.0f);\t// look down\n\tFront.Normalise();\n\tDist = (Source - CameraTarget).Magnitude();\n\tm_cvecTargetCoorsForFudgeInter = Dist*Front + Source;\n\tUp = CVector(0.0f, 1.0f, 0.0f);\n\n\tResetStatics = false;\n}\n\nvoid\nCCam::AvoidWallsTopDownPed(const CVector &TargetCoors, const CVector &Offset, float *Adjuster, float *AdjusterSpeed, float yDistLimit)\n{\n\tfloat Target = 0.0f;\n\tfloat MaxSpeed = 0.13f;\n\tfloat Acceleration = 0.015f;\n\tfloat SpeedMult;\n\tfloat dy;\n\tCVector TestPoint2;\n\tCVector TestPoint1;\n\tCColPoint colPoint;\n\tCEntity *entity;\n\n\tTestPoint2 = TargetCoors + Offset;\n\tTestPoint1 = TargetCoors;\n\tTestPoint1.z = TestPoint2.z;\n\tif(CWorld::ProcessLineOfSight(TestPoint1, TestPoint2, colPoint, entity, true, false, false, false, false, false, false)){\n\t\t// What is this even?\n\t\tdy = TestPoint1.y - colPoint.point.y;\n\t\tif(dy > yDistLimit)\n\t\t\tdy = yDistLimit;\n\t\tSpeedMult = yDistLimit - Abs(dy/yDistLimit);\n\n\t\tTarget = 2.5f;\n\t\tMaxSpeed += SpeedMult*0.3f;\n\t\tAcceleration += SpeedMult*0.03f;\n\t}\n\tWellBufferMe(Target, Adjuster, AdjusterSpeed, MaxSpeed, Acceleration, false);\n}\n\nvoid\nCCam::Process_TopDownPed(const CVector &CameraTarget, float TargetOrientation, float, float)\n{\n\tif(!CamTargetEntity->IsPed())\n\t\treturn;\n\n\tfloat Dist;\n\tfloat HeightTarget;\n\tstatic int NumPedPosCountsSoFar = 0;\n\tstatic float PedAverageSpeed = 0.0f;\n\tstatic float AdjustHeightTargetMoveBuffer = 0.0f;\n\tstatic float AdjustHeightTargetMoveSpeed = 0.0f;\n\tstatic float PedSpeedSoFar = 0.0f;\n\tstatic float FarClipDistance = 200.0f;\n\tstatic float NearClipDistance = 1.5f;\n\tstatic float TargetAdjusterForSouth = 0.0f;\n\tstatic float TargetAdjusterSpeedForSouth = 0.0f;\n\tstatic float TargetAdjusterForNorth = 0.0f;\n\tstatic float TargetAdjusterSpeedForNorth = 0.0f;\n\tstatic float TargetAdjusterForEast = 0.0f;\n\tstatic float TargetAdjusterSpeedForEast = 0.0f;\n\tstatic float TargetAdjusterForWest = 0.0f;\n\tstatic float TargetAdjusterSpeedForWest = 0.0f;\n\tstatic CVector PreviousPlayerMoveSpeedVec;\n\tCVector TargetCoors, PlayerMoveSpeed;\n\tCVector TestSource, TestTarget;\n\tCColPoint colPoint;\n\tCEntity *entity;\n\n\tFOV = DefaultFOV;\n\tTargetCoors = CameraTarget;\n\tPlayerMoveSpeed = ((CPed*)CamTargetEntity)->GetMoveSpeed();\n\n\tif(ResetStatics){\n\t\tPreviousPlayerMoveSpeedVec = PlayerMoveSpeed;\n\t\tAdjustHeightTargetMoveBuffer = 0.0f;\n\t\tAdjustHeightTargetMoveSpeed = 0.0f;\n\t\tNumPedPosCountsSoFar = 0;\n\t\tPedSpeedSoFar = 0.0f;\n\t\tPedAverageSpeed = 0.0f;\n\t\tTargetAdjusterForWest = 0.0f;\n\t\tTargetAdjusterSpeedForWest = 0.0f;\n\t\tTargetAdjusterForEast = 0.0f;\n\t\tTargetAdjusterSpeedForEast = 0.0f;\n\t\tTargetAdjusterForNorth = 0.0f;\n\t\tTargetAdjusterSpeedForNorth = 0.0f;\n\t\tTargetAdjusterForSouth = 0.0f;\n\t\tTargetAdjusterSpeedForSouth = 0.0f;\n\t}\n\n\tif(RwCameraGetFarClipPlane(Scene.camera) > FarClipDistance)\n\t\tRwCameraSetFarClipPlane(Scene.camera, FarClipDistance);\n\tRwCameraSetNearClipPlane(Scene.camera, NearClipDistance);\n\n\t// Average ped speed\n\tNumPedPosCountsSoFar++;\n\tPedSpeedSoFar += PlayerMoveSpeed.Magnitude();\n\tif(NumPedPosCountsSoFar == 5){\n\t\tPedAverageSpeed = 0.4f*PedAverageSpeed + 0.6*(PedSpeedSoFar/5.0f);\n\t\tNumPedPosCountsSoFar = 0;\n\t\tPedSpeedSoFar = 0.0f;\n\t}\n\tPreviousPlayerMoveSpeedVec = PlayerMoveSpeed;\n\n\t// Zoom out depending on speed\n\tif(PedAverageSpeed > 0.01f && PedAverageSpeed <= 0.04f)\n\t\tHeightTarget = 2.5f;\n\telse if(PedAverageSpeed > 0.04f && PedAverageSpeed <= 0.145f)\n\t\tHeightTarget = 4.5f;\n\telse if(PedAverageSpeed > 0.145f)\n\t\tHeightTarget = 7.0f;\n\telse\n\t\tHeightTarget = 0.0f;\n\n\t// Zoom out if locked on target is far away\n\tif(FindPlayerPed()->m_pPointGunAt){\n\t\tDist = (FindPlayerPed()->m_pPointGunAt->GetPosition() - CameraTarget).Magnitude2D();\n\t\tif(Dist > 6.0f)\n\t\t\tHeightTarget = Max(HeightTarget, Dist/22.0f*37.0f);\n\t}\n\n\tSource = TargetCoors + CVector(0.0f, -1.0f, 9.0f);\n\n\t// Collision checks\n\tentity = nil;\n\tTestSource = TargetCoors + CVector(0.0f, -1.0f, 9.0f);\n\tTestTarget = TestSource;\n\tTestTarget.z = TargetCoors.z;\n\tif(CWorld::ProcessLineOfSight(TestTarget, TestSource, colPoint, entity, true, false, false, false, false, false, false)){\n\t\tif(TargetCoors.z+9.0f+HeightTarget < colPoint.point.z+3.0f)\n\t\t\tHeightTarget = colPoint.point.z+3.0f - (TargetCoors.z+9.0f);\n\t}else{\n\t\tTestSource = TargetCoors + CVector(0.0f, -1.0f, 9.0f);\n\t\tTestTarget = TestSource;\n\t\tTestSource.z += HeightTarget;\n\t\tTestTarget.z = TestSource.z + 10.0f;\n\t\tif(CWorld::ProcessLineOfSight(TestTarget, TestSource, colPoint, entity, true, false, false, false, false, false, false)){\n\t\t\tif(TargetCoors.z+9.0f+HeightTarget < colPoint.point.z+3.0f)\n\t\t\t\tHeightTarget = colPoint.point.z+3.0f - (TargetCoors.z+9.0f);\n\t\t}\n\t}\n\n\tWellBufferMe(HeightTarget, &AdjustHeightTargetMoveBuffer, &AdjustHeightTargetMoveSpeed, 0.3f, 0.03f, false);\n\tSource.z += AdjustHeightTargetMoveBuffer;\n\n\t// Wall checks\n\tAvoidWallsTopDownPed(TargetCoors, CVector(0.0f, -3.0f, 3.0f), &TargetAdjusterForSouth, &TargetAdjusterSpeedForSouth, 1.0f);\n\tSource.y += TargetAdjusterForSouth;\n\tAvoidWallsTopDownPed(TargetCoors, CVector(0.0f, 3.0f, 3.0f), &TargetAdjusterForNorth, &TargetAdjusterSpeedForNorth, 1.0f);\n\tSource.y -= TargetAdjusterForNorth;\n\t// BUG: east and west flipped\n\tAvoidWallsTopDownPed(TargetCoors, CVector(3.0f, 0.0f, 3.0f), &TargetAdjusterForWest, &TargetAdjusterSpeedForWest, 1.0f);\n\tSource.x -= TargetAdjusterForWest;\n\tAvoidWallsTopDownPed(TargetCoors, CVector(-3.0f, 0.0f, 3.0f), &TargetAdjusterForEast, &TargetAdjusterSpeedForEast, 1.0f);\n\tSource.x += TargetAdjusterForEast;\n\n\tTargetCoors.y = Source.y + 1.0f;\n\tTargetCoors.y += TargetAdjusterForSouth;\n\tTargetCoors.x += TargetAdjusterForEast;\n\tTargetCoors.x -= TargetAdjusterForWest;\n\n\tFront = TargetCoors - Source;\n\tFront.Normalise();\n#ifdef FIX_BUGS\n\tif(Front.x == 0.0f && Front.y == 0.0f)\n\t\tFront.y = 0.0001f;\n#else\n\t// someone used = instead of == in the above check by accident\n\tFront.x = 0.0f;\n#endif\n\tm_cvecTargetCoorsForFudgeInter = TargetCoors;\n\tUp = CrossProduct(Front, CVector(-1.0f, 0.0f, 0.0f));\n\tUp.Normalise();\n\n\tResetStatics = false;\n}\n\nvoid\nCCam::Process_Rocket(const CVector &CameraTarget, float, float, float)\n{\n\tif(!CamTargetEntity->IsPed())\n\t\treturn;\n\n\tfloat BackOffset = 0.19f;\n\tstatic bool FailedTestTwelveFramesAgo = false;\n\tRwV3d HeadPos;\n\tCVector TargetCoors;\n\n\tFOV = DefaultFOV;\n\tTargetCoors = CameraTarget;\n\n\tif(ResetStatics){\n\t\tBeta = ((CPed*)CamTargetEntity)->m_fRotationCur + HALFPI;\n\t\tAlpha = 0.0f;\n\t\tm_fInitialPlayerOrientation = ((CPed*)CamTargetEntity)->m_fRotationCur + HALFPI;\n\t\tFailedTestTwelveFramesAgo = false;\n\t\t// static DPadVertical unused\n\t\t// static DPadHorizontal unused\n\t\tm_bCollisionChecksOn = true;\n\t\tResetStatics = false;\n\t}\n\n\tif(((CPed*)CamTargetEntity)->bIsDucking)\n\t\tBackOffset = 0.8f;\n\tCamTargetEntity->GetMatrix().UpdateRW();\n\tCamTargetEntity->UpdateRwFrame();\n\tCamTargetEntity->UpdateRpHAnim();\n\t((CPed*)CamTargetEntity)->m_pedIK.GetComponentPosition(HeadPos, PED_HEAD);\n\tSource = HeadPos;\n\tSource.z += 0.1f;\n\tSource.x -= BackOffset*Cos(m_fInitialPlayerOrientation);\n\tSource.y -= BackOffset*Sin(m_fInitialPlayerOrientation);\n\n\t// Look around\n\tbool UseMouse = false;\n\tfloat MouseX = CPad::GetPad(0)->GetMouseX();\n\tfloat MouseY = CPad::GetPad(0)->GetMouseY();\n\tfloat LookLeftRight, LookUpDown;\n\tif(MouseX != 0.0f || MouseY != 0.0f){\n\t\tUseMouse = true;\n\t\tLookLeftRight = -3.0f*MouseX;\n\t\tLookUpDown = 4.0f*MouseY;\n\t}else{\n\t\tLookLeftRight = -CPad::GetPad(0)->SniperModeLookLeftRight();\n\t\tLookUpDown = CPad::GetPad(0)->SniperModeLookUpDown();\n\t}\n\tif(UseMouse){\n\t\tBeta += TheCamera.m_fMouseAccelHorzntl * LookLeftRight * FOV/80.0f;\n\t\tAlpha += TheCamera.m_fMouseAccelVertical * LookUpDown * FOV/80.0f;\n\t}else{\n\t\tfloat xdir = LookLeftRight < 0.0f ? -1.0f : 1.0f;\n\t\tfloat ydir = LookUpDown < 0.0f ? -1.0f : 1.0f;\n\t\tBeta += SQR(LookLeftRight/100.0f)*xdir*0.8f/14.0f * FOV/80.0f * CTimer::GetTimeStep();\n\t\tAlpha += SQR(LookUpDown/150.0f)*ydir*1.0f/14.0f * FOV/80.0f * CTimer::GetTimeStep();\n\t}\n\twhile(Beta >= PI) Beta -= 2*PI;\n\twhile(Beta < -PI) Beta += 2*PI;\n\tif(Alpha > DEGTORAD(60.0f)) Alpha = DEGTORAD(60.0f);\n\telse if(Alpha < -DEGTORAD(89.5f)) Alpha = -DEGTORAD(89.5f);\n\n\tTargetCoors.x = 3.0f * Cos(Alpha) * Cos(Beta) + Source.x;\n\tTargetCoors.y = 3.0f * Cos(Alpha) * Sin(Beta) + Source.y;\n\tTargetCoors.z = 3.0f * Sin(Alpha) + Source.z;\n\tFront = TargetCoors - Source;\n\tFront.Normalise();\n\tSource += Front*0.4f;\n\n\tif(m_bCollisionChecksOn){\n\t\tif(!CWorld::GetIsLineOfSightClear(TargetCoors, Source, true, true, false, true, false, true, true)){\n\t\t\tRwCameraSetNearClipPlane(Scene.camera, 0.4f);\n\t\t\tFailedTestTwelveFramesAgo = true;\n\t\t}else{\n\t\t\tCVector TestPoint;\n\t\t\tTestPoint.x = 3.0f * Cos(Alpha - DEGTORAD(20.0f)) * Cos(Beta + DEGTORAD(35.0f)) + Source.x;\n\t\t\tTestPoint.y = 3.0f * Cos(Alpha - DEGTORAD(20.0f)) * Sin(Beta + DEGTORAD(35.0f)) + Source.y;\n\t\t\tTestPoint.z = 3.0f * Sin(Alpha - DEGTORAD(20.0f)) + Source.z;\n\t\t\tif(!CWorld::GetIsLineOfSightClear(TestPoint, Source, true, true, false, true, false, true, true)){\n\t\t\t\tRwCameraSetNearClipPlane(Scene.camera, 0.4f);\n\t\t\t\tFailedTestTwelveFramesAgo = true;\n\t\t\t}else{\n\t\t\t\tTestPoint.x = 3.0f * Cos(Alpha - DEGTORAD(20.0f)) * Cos(Beta - DEGTORAD(35.0f)) + Source.x;\n\t\t\t\tTestPoint.y = 3.0f * Cos(Alpha - DEGTORAD(20.0f)) * Sin(Beta - DEGTORAD(35.0f)) + Source.y;\n\t\t\t\tTestPoint.z = 3.0f * Sin(Alpha - DEGTORAD(20.0f)) + Source.z;\n\t\t\t\tif(!CWorld::GetIsLineOfSightClear(TestPoint, Source, true, true, false, true, false, true, true)){\n\t\t\t\t\tRwCameraSetNearClipPlane(Scene.camera, 0.4f);\n\t\t\t\t\tFailedTestTwelveFramesAgo = true;\n\t\t\t\t}else\n\t\t\t\t\tFailedTestTwelveFramesAgo = false;\n\t\t\t}\n\t\t}\n\t}\n\n\tif(FailedTestTwelveFramesAgo)\n\t\tRwCameraSetNearClipPlane(Scene.camera, 0.4f);\n\tSource -= Front*0.4f;\n\n\tGetVectorsReadyForRW();\n\tfloat Rotation = CGeneral::GetATanOfXY(Front.x, Front.y) - HALFPI;\n\t((CPed*)TheCamera.pTargetEntity)->m_fRotationCur = Rotation;\n\t((CPed*)TheCamera.pTargetEntity)->m_fRotationDest = Rotation;\n}\n\nfloat fDuckingBackOffset = 0.5f;\nfloat fDuckingRightOffset = 0.18f;\n\nvoid\nCCam::Process_M16_1stPerson(const CVector &CameraTarget, float, float, float)\n{\n\tif(!CamTargetEntity->IsPed())\n\t\treturn;\n\n\tfloat BackOffset = 0.3f;\n\tstatic bool FailedTestTwelveFramesAgo = false;\n\tRwV3d HeadPos;\n\tCVector TargetCoors;\n\n\tbool isAttached = ((CPed*)CamTargetEntity)->IsPlayer() && ((CPed*)CamTargetEntity)->m_attachedTo;\n\n\tFOV = DefaultFOV;\n\tTargetCoors = CameraTarget;\n\n\tif(ResetStatics){\n\t\tif(isAttached)\n\t\t\tBeta = 0.0f;\n\t\telse\n\t\t\tBeta = ((CPed*)CamTargetEntity)->m_fRotationCur + HALFPI;\n\t\tAlpha = 0.0f;\n\t\tm_fInitialPlayerOrientation = ((CPed*)CamTargetEntity)->m_fRotationCur + HALFPI;\n\t\tFailedTestTwelveFramesAgo = false;\n\t\t// static DPadVertical unused\n\t\t// static DPadHorizontal unused\n\t\tm_bCollisionChecksOn = true;\n\t\tResetStatics = false;\n\t}\n\n\t// Look around\n\tbool UseMouse = false;\n\tfloat MouseX = CPad::GetPad(0)->GetMouseX();\n\tfloat MouseY = CPad::GetPad(0)->GetMouseY();\n\tfloat LookLeftRight, LookUpDown;\n\tif(MouseX != 0.0f || MouseY != 0.0f){\n\t\tUseMouse = true;\n\t\tLookLeftRight = -3.0f*MouseX;\n\t\tLookUpDown = 4.0f*MouseY;\n\t}else{\n\t\tLookLeftRight = -CPad::GetPad(0)->SniperModeLookLeftRight();\n\t\tLookUpDown = CPad::GetPad(0)->SniperModeLookUpDown();\n\t}\n\tif(UseMouse){\n\t\tBeta += TheCamera.m_fMouseAccelHorzntl * LookLeftRight * FOV/80.0f;\n\t\tAlpha += TheCamera.m_fMouseAccelVertical * LookUpDown * FOV/80.0f;\n\t}else if(Mode == MODE_HELICANNON_1STPERSON){\n\t\tLookLeftRight /= 128.0f;\n\t\tLookUpDown /= 128.0f;\n\t\tBeta += LookLeftRight*Abs(LookLeftRight)*0.56f/14.0f * FOV/80.0f * CTimer::GetTimeStep();\n\t\tAlpha += LookUpDown*Abs(LookUpDown)*0.48f/14.0f * FOV/80.0f * CTimer::GetTimeStep();\n\t}else{\n\t\tfloat xdir = LookLeftRight < 0.0f ? -1.0f : 1.0f;\n\t\tfloat ydir = LookUpDown < 0.0f ? -1.0f : 1.0f;\n\t\tBeta += SQR(LookLeftRight/100.0f)*xdir*0.8f/14.0f * FOV/80.0f * CTimer::GetTimeStep();\n\t\tAlpha += SQR(LookUpDown/150.0f)*ydir*1.0f/14.0f * FOV/80.0f * CTimer::GetTimeStep();\n\t}\n\tif (!isAttached) {\n\t\twhile(Beta >= TWOPI) Beta -= TWOPI;\n\t\twhile(Beta < 0) Beta += TWOPI;\n\t}\n\tif(Alpha > DEGTORAD(60.0f)) Alpha = DEGTORAD(60.0f);\n\telse if(Alpha < -DEGTORAD(89.5f)) Alpha = -DEGTORAD(89.5f);\n\n\tif(((CPed*)CamTargetEntity)->bIsDucking)\n\t\tBackOffset = 0.8f;\n\tif(isAttached){\n\t\tCMatrix mat, rot;\n\t\tCPed *TargetPed = (CPed*)CamTargetEntity;\n\t\tTargetPed->PositionAttachedPed();\n\t\tCamTargetEntity->GetMatrix().UpdateRW();\n\t\tCamTargetEntity->UpdateRwFrame();\n\t\tCamTargetEntity->UpdateRpHAnim();\n\n\t\tHeadPos.x = 0.0f;\n\t\tHeadPos.y = 0.0f;\n\t\tHeadPos.z = 0.0f;\n\t\tTargetPed->m_pedIK.GetComponentPosition(HeadPos, PED_HEAD);\n\t\tSource = HeadPos;\n\t\tSource += 0.1f*CamTargetEntity->GetUp();\n\t\tSource -= BackOffset*CamTargetEntity->GetForward();\n\n\t\tif(TargetPed->m_attachRotStep < PI){\n\t\t\tif(Beta > TargetPed->m_attachRotStep){\n\t\t\t\tBeta = TargetPed->m_attachRotStep;\n\t\t\t\tCAutomobile *heli = (CAutomobile*)TargetPed->m_attachedTo;\n\t\t\t\tif(heli->IsVehicle() && heli->IsCar() && heli->IsRealHeli() && heli->m_fHeliOrientation > 0.0f){\n\t\t\t\t\tfloat heliOrient = heli->m_fHeliOrientation + CTimer::GetTimeStep()*0.01f;\n\t\t\t\t\tif(heliOrient < 0.0f) heliOrient += TWOPI;\n\t\t\t\t\telse if(heliOrient > TWOPI) heliOrient -= TWOPI;\n\t\t\t\t\theli->SetHeliOrientation(heliOrient);\n\t\t\t\t}\n\t\t\t}else if(Beta < -TargetPed->m_attachRotStep){\n\t\t\t\tBeta = -TargetPed->m_attachRotStep;\n\t\t\t\tCAutomobile *heli = (CAutomobile*)TargetPed->m_attachedTo;\n\t\t\t\tif(heli->IsVehicle() && heli->IsCar() && heli->IsRealHeli() && heli->m_fHeliOrientation > 0.0f){\n\t\t\t\t\tfloat heliOrient = heli->m_fHeliOrientation - CTimer::GetTimeStep()*0.01f;\n\t\t\t\t\tif(heliOrient < 0.0f) heliOrient += TWOPI;\n\t\t\t\t\telse if(heliOrient > TWOPI) heliOrient -= TWOPI;\n\t\t\t\t\theli->SetHeliOrientation(heliOrient);\n\t\t\t\t}\n\t\t\t}\n\t\t}else{\n\t\t\twhile(Beta < -PI) Beta += TWOPI;\n\t\t\twhile(Beta >= PI) Beta -= TWOPI;\n\t\t}\n\n\t\tmat = TargetPed->m_attachedTo->GetMatrix();\n\t\trot.SetRotateX(Alpha);\n\t\tswitch(TargetPed->m_attachType){\n\t\tcase 0: rot.RotateZ(Beta); break;\n\t\tcase 1: rot.RotateZ(Beta + HALFPI); break;\n\t\tcase 2: rot.RotateZ(Beta + PI); break;\n\t\tcase 3: rot.RotateZ(Beta - HALFPI); break;\n\t\t}\n\t\tmat = mat * rot;\n\t\tFront = mat.GetForward();\n\t\tUp = mat.GetUp();\n\t\tTargetCoors = Source + 3.0f*Front;\n\t\tRwCameraSetNearClipPlane(Scene.camera, 0.4f);\n\n\t\tfloat Rotation = CGeneral::GetATanOfXY(Front.x, Front.y) - HALFPI;\n\t\t((CPed*)TheCamera.pTargetEntity)->m_fRotationCur = Rotation;\n\t\t((CPed*)TheCamera.pTargetEntity)->m_fRotationDest = Rotation;\n\t}else{\n\t\tCamTargetEntity->GetMatrix().UpdateRW();\n\t\tCamTargetEntity->UpdateRwFrame();\n\t\tCamTargetEntity->UpdateRpHAnim();\n\t\tHeadPos.x = 0.0f;\n\t\tHeadPos.y = 0.0f;\n\t\tHeadPos.z = 0.0f;\n\t\t((CPed*)CamTargetEntity)->m_pedIK.GetComponentPosition(HeadPos, PED_HEAD);\n\t\tSource = HeadPos;\n\t\tSource.z += 0.1f;\n\t\tif(((CPed*)CamTargetEntity)->bIsDucking){\n\t\t\tSource.x -= fDuckingBackOffset*CamTargetEntity->GetForward().x;\n\t\t\tSource.y -= fDuckingBackOffset*CamTargetEntity->GetForward().y;\n\t\t\tSource.x -= fDuckingRightOffset*CamTargetEntity->GetRight().x;\n\t\t\tSource.y -= fDuckingRightOffset*CamTargetEntity->GetRight().y;\n\t\t}else{\n\t\t\tSource.x -= BackOffset*CamTargetEntity->GetForward().x;\n\t\t\tSource.y -= BackOffset*CamTargetEntity->GetForward().y;\n\t\t}\n\n\t\tTargetCoors.x = 3.0f * Cos(Alpha) * Cos(Beta) + Source.x;\n\t\tTargetCoors.y = 3.0f * Cos(Alpha) * Sin(Beta) + Source.y;\n\t\tTargetCoors.z = 3.0f * Sin(Alpha) + Source.z;\n\t\tFront = TargetCoors - Source;\n\t\tFront.Normalise();\n\t\tSource += Front*0.4f;\n\n\t\tif(m_bCollisionChecksOn){\n\t\t\tif(!CWorld::GetIsLineOfSightClear(TargetCoors, Source, true, true, false, true, false, true, true)){\n\t\t\t\tRwCameraSetNearClipPlane(Scene.camera, 0.4f);\n\t\t\t\tFailedTestTwelveFramesAgo = true;\n\t\t\t}else{\n\t\t\t\tCVector TestPoint;\n\t\t\t\tTestPoint.x = 3.0f * Cos(Alpha - DEGTORAD(20.0f)) * Cos(Beta + DEGTORAD(35.0f)) + Source.x;\n\t\t\t\tTestPoint.y = 3.0f * Cos(Alpha - DEGTORAD(20.0f)) * Sin(Beta + DEGTORAD(35.0f)) + Source.y;\n\t\t\t\tTestPoint.z = 3.0f * Sin(Alpha - DEGTORAD(20.0f)) + Source.z;\n\t\t\t\tif(!CWorld::GetIsLineOfSightClear(TestPoint, Source, true, true, false, true, false, true, true)){\n\t\t\t\t\tRwCameraSetNearClipPlane(Scene.camera, 0.4f);\n\t\t\t\t\tFailedTestTwelveFramesAgo = true;\n\t\t\t\t}else{\n\t\t\t\t\tTestPoint.x = 3.0f * Cos(Alpha - DEGTORAD(20.0f)) * Cos(Beta - DEGTORAD(35.0f)) + Source.x;\n\t\t\t\t\tTestPoint.y = 3.0f * Cos(Alpha - DEGTORAD(20.0f)) * Sin(Beta - DEGTORAD(35.0f)) + Source.y;\n\t\t\t\t\tTestPoint.z = 3.0f * Sin(Alpha - DEGTORAD(20.0f)) + Source.z;\n\t\t\t\t\tif(!CWorld::GetIsLineOfSightClear(TestPoint, Source, true, true, false, true, false, true, true)){\n\t\t\t\t\t\tRwCameraSetNearClipPlane(Scene.camera, 0.4f);\n\t\t\t\t\t\tFailedTestTwelveFramesAgo = true;\n\t\t\t\t\t}else\n\t\t\t\t\t\tFailedTestTwelveFramesAgo = false;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif(FailedTestTwelveFramesAgo)\n\t\t\tRwCameraSetNearClipPlane(Scene.camera, 0.4f);\n\t\tSource -= Front*0.4f;\n\n\t\tGetVectorsReadyForRW();\n\t\tfloat Rotation = CGeneral::GetATanOfXY(Front.x, Front.y) - HALFPI;\n\t\t((CPed*)TheCamera.pTargetEntity)->m_fRotationCur = Rotation;\n\t\t((CPed*)TheCamera.pTargetEntity)->m_fRotationDest = Rotation;\n\t}\n}\n\nfloat fBike1stPersonOffsetZ = 0.15f;\n\nvoid\nCCam::Process_1stPerson(const CVector &CameraTarget, float TargetOrientation, float SpeedVar, float TargetSpeedVar)\n{\n\tfloat BackOffset = 0.3f;\n\tstatic float DontLookThroughWorldFixer = 0.0f;\n\tCVector TargetCoors;\n\n\tFOV = DefaultFOV;\n\tTargetCoors = CameraTarget;\n\tif(CamTargetEntity->m_rwObject == nil)\n\t\treturn;\n\n\tif(ResetStatics){\n\t\tBeta = TargetOrientation;\n\t\tAlpha = 0.0f;\n\t\tm_fInitialPlayerOrientation = TargetOrientation;\n\t\tif(CamTargetEntity->IsPed()){\n\t\t\tBeta = ((CPed*)CamTargetEntity)->m_fRotationCur + HALFPI;\n\t\t\tAlpha = 0.0f;\n\t\t\tm_fInitialPlayerOrientation = ((CPed*)CamTargetEntity)->m_fRotationCur + HALFPI;\n\t\t}\n\t\tTheCamera.m_fAvoidTheGeometryProbsTimer = 0.0f;\n\t\tDontLookThroughWorldFixer = 0.0f;\n\t}\n\n\tif(CamTargetEntity->IsPed()){\n\t\tstatic bool FailedTestTwelveFramesAgo = false;\n\t\tRwV3d HeadPos;\n\n\t\tTargetCoors = CameraTarget;\n\n\t\tif(ResetStatics){\n\t\t\tBeta = ((CPed*)CamTargetEntity)->m_fRotationCur + HALFPI;\n\t\t\tAlpha = 0.0f;\n\t\t\tm_fInitialPlayerOrientation = ((CPed*)CamTargetEntity)->m_fRotationCur + HALFPI;\n\t\t\tFailedTestTwelveFramesAgo = false;\n\t\t\t// static DPadVertical unused\n\t\t\t// static DPadHorizontal unused\n\t\t\tm_bCollisionChecksOn = true;\n\t\t\tResetStatics = false;\n\t\t}\n\n\t\tCamTargetEntity->GetMatrix().UpdateRW();\n\t\tCamTargetEntity->UpdateRwFrame();\n\t\tCamTargetEntity->UpdateRpHAnim();\n\n\t\t((CPed*)CamTargetEntity)->m_pedIK.GetComponentPosition(HeadPos, PED_HEAD);\n\t\tSource = HeadPos;\n\t\tSource.z += 0.1f;\n\t\tif(((CPed*)CamTargetEntity)->bIsDucking){\n\t\t\tSource.x -= fDuckingBackOffset*CamTargetEntity->GetForward().x;\n\t\t\tSource.y -= fDuckingBackOffset*CamTargetEntity->GetForward().y;\n\t\t\tSource.x -= fDuckingRightOffset*CamTargetEntity->GetRight().x;\n\t\t\tSource.y -= fDuckingRightOffset*CamTargetEntity->GetRight().y;\n\t\t}else{\n\t\t\tSource.x -= BackOffset*CamTargetEntity->GetForward().x;\n\t\t\tSource.y -= BackOffset*CamTargetEntity->GetForward().y;\n\t\t}\n\n\t\tfloat LookLeftRight, LookUpDown;\n\t\tLookLeftRight = -CPad::GetPad(0)->LookAroundLeftRight();\n\t\tLookUpDown = CPad::GetPad(0)->LookAroundUpDown();\n\t\tfloat xdir = LookLeftRight < 0.0f ? -1.0f : 1.0f;\n\t\tfloat ydir = LookUpDown < 0.0f ? -1.0f : 1.0f;\n\t\tBeta += SQR(LookLeftRight/100.0f)*xdir*0.8f/14.0f * FOV/80.0f * CTimer::GetTimeStep();\n\t\tAlpha += SQR(LookUpDown/150.0f)*ydir*1.0f/14.0f * FOV/80.0f * CTimer::GetTimeStep();\n\t\twhile(Beta >= PI) Beta -= 2*PI;\n\t\twhile(Beta < -PI) Beta += 2*PI;\n\t\tif(Alpha > DEGTORAD(60.0f)) Alpha = DEGTORAD(60.0f);\n\t\telse if(Alpha < -DEGTORAD(89.5f)) Alpha = -DEGTORAD(89.5f);\n\n\t\tTargetCoors.x = 3.0f * Cos(Alpha) * Cos(Beta) + Source.x;\n\t\tTargetCoors.y = 3.0f * Cos(Alpha) * Sin(Beta) + Source.y;\n\t\tTargetCoors.z = 3.0f * Sin(Alpha) + Source.z;\n\t\tFront = TargetCoors - Source;\n\t\tFront.Normalise();\n\t\tSource += Front*0.4f;\n\n\t\tif(m_bCollisionChecksOn){\n\t\t\tif(!CWorld::GetIsLineOfSightClear(TargetCoors, Source, true, true, false, true, false, true, true)){\n\t\t\t\tRwCameraSetNearClipPlane(Scene.camera, 0.4f);\n\t\t\t\tFailedTestTwelveFramesAgo = true;\n\t\t\t}else{\n\t\t\t\tCVector TestPoint;\n\t\t\t\tTestPoint.x = 3.0f * Cos(Alpha - DEGTORAD(20.0f)) * Cos(Beta + DEGTORAD(35.0f)) + Source.x;\n\t\t\t\tTestPoint.y = 3.0f * Cos(Alpha - DEGTORAD(20.0f)) * Sin(Beta + DEGTORAD(35.0f)) + Source.y;\n\t\t\t\tTestPoint.z = 3.0f * Sin(Alpha - DEGTORAD(20.0f)) + Source.z;\n\t\t\t\tif(!CWorld::GetIsLineOfSightClear(TestPoint, Source, true, true, false, true, false, true, true)){\n\t\t\t\t\tRwCameraSetNearClipPlane(Scene.camera, 0.4f);\n\t\t\t\t\tFailedTestTwelveFramesAgo = true;\n\t\t\t\t}else{\n\t\t\t\t\tTestPoint.x = 3.0f * Cos(Alpha - DEGTORAD(20.0f)) * Cos(Beta - DEGTORAD(35.0f)) + Source.x;\n\t\t\t\t\tTestPoint.y = 3.0f * Cos(Alpha - DEGTORAD(20.0f)) * Sin(Beta - DEGTORAD(35.0f)) + Source.y;\n\t\t\t\t\tTestPoint.z = 3.0f * Sin(Alpha - DEGTORAD(20.0f)) + Source.z;\n\t\t\t\t\tif(!CWorld::GetIsLineOfSightClear(TestPoint, Source, true, true, false, true, false, true, true)){\n\t\t\t\t\t\tRwCameraSetNearClipPlane(Scene.camera, 0.4f);\n\t\t\t\t\t\tFailedTestTwelveFramesAgo = true;\n\t\t\t\t\t}else\n\t\t\t\t\t\tFailedTestTwelveFramesAgo = false;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif(FailedTestTwelveFramesAgo)\n\t\t\tRwCameraSetNearClipPlane(Scene.camera, 0.4f);\n\t\tSource -= Front*0.4f;\n\n\t\tGetVectorsReadyForRW();\n\t\tfloat Rotation = CGeneral::GetATanOfXY(Front.x, Front.y) - HALFPI;\n\t\t((CPed*)TheCamera.pTargetEntity)->m_fRotationCur = Rotation;\n\t\t((CPed*)TheCamera.pTargetEntity)->m_fRotationDest = Rotation;\n\t}else{\n\t\tassert(CamTargetEntity->IsVehicle());\n\n\t\tif(((CVehicle*)CamTargetEntity)->IsBike() &&\n\t\t   (((CBike*)CamTargetEntity)->bWheelieCam || TheCamera.m_fAvoidTheGeometryProbsTimer > 0.0f)){\n\t\t\tif(CPad::GetPad(0)->GetLeftShoulder2() || CPad::GetPad(0)->GetRightShoulder2()){\n\t\t\t\tTheCamera.m_fAvoidTheGeometryProbsTimer = 0.0f;\n\t\t\t\t((CBike*)CamTargetEntity)->bWheelieCam = false;\n\t\t\t}else if(Process_WheelCam(CameraTarget, TargetOrientation, SpeedVar, TargetSpeedVar)){\n\t\t\t\tif(((CBike*)CamTargetEntity)->bWheelieCam)\n\t\t\t\t\tTheCamera.m_fAvoidTheGeometryProbsTimer = 50.0f;\n\t\t\t\telse{\n\t\t\t\t\tTheCamera.m_fAvoidTheGeometryProbsTimer -= CTimer::GetTimeStep();\n\t\t\t\t\t((CBike*)CamTargetEntity)->bWheelieCam = true;\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}else{\n\t\t\t\tTheCamera.m_fAvoidTheGeometryProbsTimer = 0.0f;\n\t\t\t\t((CBike*)CamTargetEntity)->bWheelieCam = false;\n\t\t\t}\n\t\t}\n\n\t\tCMatrix *matrix = &CamTargetEntity->GetMatrix();\n\t\tif(((CVehicle*)CamTargetEntity)->IsBike()){\n\t\t\t((CBike*)CamTargetEntity)->CalculateLeanMatrix();\n\t\t\tmatrix = &((CBike*)CamTargetEntity)->m_leanMatrix;\n\t\t}\n\n\t\tCVehicleModelInfo *mi = (CVehicleModelInfo*)CModelInfo::GetModelInfo(CamTargetEntity->GetModelIndex());\n\t\tCVector CamPos = mi->GetFrontSeatPosn();\n\t\tCamPos.x = 0.0f;\n\t\tCamPos.y += 0.08f;\n\t\tCamPos.z += 0.62f;\n\t\tFOV = 60.0f;\n\t\tSource = Multiply3x3(*matrix, CamPos);\n\t\tSource += CamTargetEntity->GetPosition();\n\t\tif(((CVehicle*)CamTargetEntity)->IsBoat())\n\t\t\tSource.z += 0.5f;\n\t\telse if(((CVehicle*)CamTargetEntity)->IsBike() && ((CVehicle*)CamTargetEntity)->pDriver){\n\t\t\tCVector Neck(0.0f, 0.0f, 0.0f);\n\t\t\t((CVehicle*)CamTargetEntity)->pDriver->m_pedIK.GetComponentPosition(Neck, PED_NECK);\n\t\t\tNeck += ((CVehicle*)CamTargetEntity)->m_vecMoveSpeed * CTimer::GetTimeStep();\n\t\t\tSource.z = Neck.z + fBike1stPersonOffsetZ;\n\t\t}\n\n\t\tif(((CVehicle*)CamTargetEntity)->IsUpsideDown()){\n\t\t\tif(DontLookThroughWorldFixer < 0.5f)\n\t\t\t\tDontLookThroughWorldFixer += 0.03f;\n\t\t\telse\n\t\t\t\tDontLookThroughWorldFixer = 0.5f;\n\t\t}else{\n\t\t\tif(DontLookThroughWorldFixer < 0.0f)\n#ifdef FIX_BUGS\n\t\t\t\tDontLookThroughWorldFixer += 0.03f;\n#else\n\t\t\t\tDontLookThroughWorldFixer -= 0.03f;\n#endif\n\t\t\telse\n\t\t\t\tDontLookThroughWorldFixer = 0.0f;\n\t\t}\n\t\tSource.z += DontLookThroughWorldFixer;\n\t\tFront = matrix->GetForward();\n\t\tFront.Normalise();\n\t\tUp = matrix->GetUp();\n\t\tUp.Normalise();\n\t\tCVector Right = CrossProduct(Front, Up);\n\t\tRight.Normalise();\n\t\tUp = CrossProduct(Right, Front);\n\t\tUp.Normalise();\n\t}\n\n\tResetStatics = false;\n}\n\nstatic CVector vecHeadCamOffset(0.06f, 0.05f, 0.0f);\n\nvoid\nCCam::Process_1rstPersonPedOnPC(const CVector&, float TargetOrientation, float, float)\n{\n\t// static int DontLookThroughWorldFixer = 0;\t// unused\n\tstatic CVector InitialHeadPos;\n\n\tif(Mode != MODE_SNIPER_RUNABOUT)\n\t\tFOV = DefaultFOV;\n\tTheCamera.m_1rstPersonRunCloseToAWall = false;\n\tif(CamTargetEntity->m_rwObject == nil)\n\t\treturn;\n\n\tif(CamTargetEntity->IsPed()){\n\t\t// static bool FailedTestTwelveFramesAgo = false;\t// unused\n\t\tCVector HeadPos = vecHeadCamOffset;\n\t\tCVector TargetCoors;\n\n\t\t((CPed*)CamTargetEntity)->TransformToNode(HeadPos, PED_HEAD);\n\t\tRpHAnimHierarchy *hier = GetAnimHierarchyFromSkinClump(CamTargetEntity->GetClump());\n\t\tint32 idx = RpHAnimIDGetIndex(hier, ConvertPedNode2BoneTag(PED_HEAD));\n\t\tRwMatrix *mats = RpHAnimHierarchyGetMatrixArray(hier);\n\t\tRwV3dTransformPoints(&HeadPos, &HeadPos, 1, &mats[idx]);\n\t\tRwV3d scl = { 0.0f, 0.0f, 0.0f };\n\t\tRwMatrixScale(&mats[idx], &scl, rwCOMBINEPRECONCAT);\n\n\t\tif(ResetStatics){\n\t\t\tBeta = TargetOrientation;\n\t\t\tAlpha = 0.0f;\n\t\t\tm_fInitialPlayerOrientation = TargetOrientation;\n\t\t\tif(CamTargetEntity->IsPed()){\t// useless check\n\t\t\t\tBeta = ((CPed*)CamTargetEntity)->m_fRotationCur + HALFPI;\n\t\t\t\tAlpha = 0.0f;\n\t\t\t\tm_fInitialPlayerOrientation = ((CPed*)CamTargetEntity)->m_fRotationCur + HALFPI;\n\t\t\t\t// FailedTestTwelveFramesAgo = false;\n\t\t\t\tm_bCollisionChecksOn = true;\n\t\t\t}\n\t\t\t// DontLookThroughWorldFixer = false;\n\t\t\tm_vecBufferedPlayerBodyOffset = HeadPos;\n\t\t\tInitialHeadPos = HeadPos;\n\t\t}\n\n\t\tm_vecBufferedPlayerBodyOffset.y = HeadPos.y;\n\n\t\tif(TheCamera.m_bHeadBob){\n\t\t\tm_vecBufferedPlayerBodyOffset.x =\n\t\t\t\tTheCamera.m_fGaitSwayBuffer * m_vecBufferedPlayerBodyOffset.x +\n\t\t\t\t(1.0f-TheCamera.m_fGaitSwayBuffer) * HeadPos.x;\n\t\t\tm_vecBufferedPlayerBodyOffset.z =\n\t\t\t\tTheCamera.m_fGaitSwayBuffer * m_vecBufferedPlayerBodyOffset.z +\n\t\t\t\t(1.0f-TheCamera.m_fGaitSwayBuffer) * HeadPos.z;\n\t\t\tHeadPos = (CamTargetEntity->GetMatrix() * m_vecBufferedPlayerBodyOffset);\n\t\t}else{\n\t\t\tfloat HeadDelta = (HeadPos - InitialHeadPos).Magnitude2D();\n\t\t\tCVector Fwd = CamTargetEntity->GetForward();\n\t\t\tFwd.z = 0.0f;\n\t\t\tFwd.Normalise();\n\t\t\tHeadPos = HeadDelta*1.23f*Fwd + CamTargetEntity->GetPosition();\n\t\t\tHeadPos.z += 0.59f;\n\t\t}\n\t\tSource = HeadPos;\n\n\t\t// unused:\n\t\t// ((CPed*)CamTargetEntity)->m_pedIK.GetComponentPosition(MidPos, PED_MID);\n\t\t// Source - MidPos;\n\n\t\t// Look around\n\t\tbool UseMouse = false;\n\t\tfloat MouseX = CPad::GetPad(0)->GetMouseX();\n\t\tfloat MouseY = CPad::GetPad(0)->GetMouseY();\n\t\tfloat LookLeftRight, LookUpDown;\n\t\tif(MouseX != 0.0f || MouseY != 0.0f){\n\t\t\tUseMouse = true;\n\t\t\tLookLeftRight = -3.0f*MouseX;\n\t\t\tLookUpDown = 4.0f*MouseY;\n\t\t}else{\n\t\t\tLookLeftRight = -CPad::GetPad(0)->LookAroundLeftRight();\n\t\t\tLookUpDown = CPad::GetPad(0)->LookAroundUpDown();\n\t\t}\n\t\tif(UseMouse){\n\t\t\tBeta += TheCamera.m_fMouseAccelHorzntl * LookLeftRight * FOV/80.0f;\n\t\t\tAlpha += TheCamera.m_fMouseAccelVertical * LookUpDown * FOV/80.0f;\n\t\t}else{\n\t\t\tfloat xdir = LookLeftRight < 0.0f ? -1.0f : 1.0f;\n\t\t\tfloat ydir = LookUpDown < 0.0f ? -1.0f : 1.0f;\n\t\t\tBeta += SQR(LookLeftRight/100.0f)*xdir*0.8f/14.0f * FOV/80.0f * CTimer::GetTimeStep();\n\t\t\tAlpha += SQR(LookUpDown/150.0f)*ydir*1.0f/14.0f * FOV/80.0f * CTimer::GetTimeStep();\n\t\t}\n\t\twhile(Beta >= PI) Beta -= 2*PI;\n\t\twhile(Beta < -PI) Beta += 2*PI;\n\t\tif(Alpha > DEGTORAD(60.0f)) Alpha = DEGTORAD(60.0f);\n\t\telse if(Alpha < -DEGTORAD(89.5f)) Alpha = -DEGTORAD(89.5f);\n\n\t\tif(((CPed*)CamTargetEntity)->IsPlayer() && ((CPed*)CamTargetEntity)->m_attachedTo){\n\t\t\tCPed *pedTarget = ((CPed*)CamTargetEntity);\n\t\t\tfloat NewBeta;\n\t\t\tswitch(pedTarget->m_attachType){\n\t\t\tcase 0:\n\t\t\t\tNewBeta = pedTarget->GetForward().Heading() + HALFPI;\n\t\t\t\tbreak;\n\t\t\tcase 1:\n\t\t\t\tNewBeta = pedTarget->GetForward().Heading() + PI;\n\t\t\t\tbreak;\n\t\t\tcase 2:\n\t\t\t\tNewBeta = pedTarget->GetForward().Heading() - HALFPI;\n\t\t\t\tbreak;\n\t\t\tcase 3:\n\t\t\t\tNewBeta = pedTarget->GetForward().Heading();\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tfloat BetaOffset = Beta - NewBeta;\n\t\t\tif(BetaOffset > PI) BetaOffset -= TWOPI;\n\t\t\telse if(BetaOffset < PI) BetaOffset += TWOPI;\n\n\t\t\tBetaOffset = clamp(BetaOffset, -pedTarget->m_attachRotStep, pedTarget->m_attachRotStep);\n\t\t\tBeta = NewBeta + BetaOffset;\n\t\t}\n\n\t\tTargetCoors.x = 3.0f * Cos(Alpha) * Cos(Beta) + Source.x;\n\t\tTargetCoors.y = 3.0f * Cos(Alpha) * Sin(Beta) + Source.y;\n\t\tTargetCoors.z = 3.0f * Sin(Alpha) + Source.z;\n\t\tFront = TargetCoors - Source;\n\t\tFront.Normalise();\n\t\tSource += Front*0.4f;\n\n\t\tTheCamera.m_AlphaForPlayerAnim1rstPerson = Alpha;\n\n\t\tGetVectorsReadyForRW();\n\n\t\tfloat Heading = Front.Heading();\n\t\t((CPed*)TheCamera.pTargetEntity)->m_fRotationCur = Heading;\n\t\t((CPed*)TheCamera.pTargetEntity)->m_fRotationDest = Heading;\n\t\tTheCamera.pTargetEntity->SetHeading(Heading);\n\t\tTheCamera.pTargetEntity->GetMatrix().UpdateRW();\n\n\t\tif(Mode == MODE_SNIPER_RUNABOUT){\n\t\t\t// no mouse wheel FOV buffering here like in normal sniper mode\n\t\t\tif(CPad::GetPad(0)->SniperZoomIn() || CPad::GetPad(0)->SniperZoomOut()){\n\t\t\t\tif(CPad::GetPad(0)->SniperZoomOut())\n\t\t\t\t\tFOV *= (255.0f*CTimer::GetTimeStep() + 10000.0f) / 10000.0f;\n\t\t\t\telse\n\t\t\t\t\tFOV /= (255.0f*CTimer::GetTimeStep() + 10000.0f) / 10000.0f;\n\t\t\t}\n\n\t\t\tTheCamera.SetMotionBlur(180, 255, 180, 120, MOTION_BLUR_SNIPER);\n\n\t\t\tif(FOV > DefaultFOV)\n\t\t\t\tFOV = DefaultFOV;\n\t\t\tif(FOV < 15.0f)\n\t\t\t\tFOV = 15.0f;\n\t\t}\n\t}\n\n\tResetStatics = false;\n\tRwCameraSetNearClipPlane(Scene.camera, 0.05f);\n}\n\nfloat fCameraNearClipMult = 0.15f;\n\nvoid\nCCam::Process_Sniper(const CVector &CameraTarget, float TargetOrientation, float, float)\n{\n\tif(!CamTargetEntity->IsPed())\n\t\treturn;\n\n\tfloat BackOffset = 0.19f;\n\tstatic bool FailedTestTwelveFramesAgo = false;\n\tRwV3d HeadPos;\n\tCVector TargetCoors;\n\tTargetCoors = CameraTarget;\n\n\tstatic float TargetFOV = 0.0f;\n\n\tif(ResetStatics){\n\t\tBeta = ((CPed*)CamTargetEntity)->m_fRotationCur + HALFPI;\n\t\tAlpha = 0.0f;\n\t\tm_fInitialPlayerOrientation = ((CPed*)CamTargetEntity)->m_fRotationCur + HALFPI;\n\t\tFailedTestTwelveFramesAgo = false;\n\t\t// static DPadVertical unused\n\t\t// static DPadHorizontal unused\n\t\tm_bCollisionChecksOn = true;\n\t\tFOVSpeed = 0.0f;\n\t\tTargetFOV = FOV;\n\t\tResetStatics = false;\n\t}\n\n\tif(((CPed*)CamTargetEntity)->bIsDucking)\n\t\tBackOffset = 0.8f;\n\tCamTargetEntity->GetMatrix().UpdateRW();\n\tCamTargetEntity->UpdateRwFrame();\n\tCamTargetEntity->UpdateRpHAnim();\n\t((CPed*)CamTargetEntity)->m_pedIK.GetComponentPosition(HeadPos, PED_HEAD);\n\tSource = HeadPos;\n\tSource.z += 0.1f;\n\tif(((CPed*)CamTargetEntity)->bIsDucking){\n\t\tSource.x -= fDuckingBackOffset*CamTargetEntity->GetForward().x;\n\t\tSource.y -= fDuckingBackOffset*CamTargetEntity->GetForward().y;\n\t\tSource.x -= fDuckingRightOffset*CamTargetEntity->GetRight().x;\n\t\tSource.y -= fDuckingRightOffset*CamTargetEntity->GetRight().y;\n\t}else{\n\t\tSource.x -= BackOffset*CamTargetEntity->GetForward().x;\n\t\tSource.y -= BackOffset*CamTargetEntity->GetForward().y;\n\t}\n\n\t// Look around\n\tbool UseMouse = false;\n\tfloat MouseX = CPad::GetPad(0)->GetMouseX();\n\tfloat MouseY = CPad::GetPad(0)->GetMouseY();\n\tfloat LookLeftRight, LookUpDown;\n\tif(MouseX != 0.0f || MouseY != 0.0f){\n\t\tUseMouse = true;\n\t\tLookLeftRight = -3.0f*MouseX;\n\t\tLookUpDown = 4.0f*MouseY;\n\t}else{\n\t\tLookLeftRight = -CPad::GetPad(0)->SniperModeLookLeftRight();\n\t\tLookUpDown = CPad::GetPad(0)->SniperModeLookUpDown();\n\t}\n\tif(UseMouse){\n\t\tBeta += TheCamera.m_fMouseAccelHorzntl * LookLeftRight * FOV/80.0f;\n\t\tAlpha += TheCamera.m_fMouseAccelVertical * LookUpDown * FOV/80.0f;\n\t}else{\n\t\tfloat xdir = LookLeftRight < 0.0f ? -1.0f : 1.0f;\n\t\tfloat ydir = LookUpDown < 0.0f ? -1.0f : 1.0f;\n\t\tBeta += SQR(LookLeftRight/100.0f)*xdir*0.8f/14.0f * FOV/80.0f * CTimer::GetTimeStep();\n\t\tAlpha += SQR(LookUpDown/150.0f)*ydir*1.0f/14.0f * FOV/80.0f * CTimer::GetTimeStep();\n\t}\n\twhile(Beta >= PI) Beta -= 2*PI;\n\twhile(Beta < -PI) Beta += 2*PI;\n\tif(Alpha > DEGTORAD(60.0f)) Alpha = DEGTORAD(60.0f);\n\telse if(Alpha < -DEGTORAD(89.5f)) Alpha = -DEGTORAD(89.5f);\n\n\tTargetCoors.x = 3.0f * Cos(Alpha) * Cos(Beta) + Source.x;\n\tTargetCoors.y = 3.0f * Cos(Alpha) * Sin(Beta) + Source.y;\n\tTargetCoors.z = 3.0f * Sin(Alpha) + Source.z;\n\n\tUseMouse = false;\n\tint ZoomInButton = ControlsManager.GetMouseButtonAssociatedWithAction(PED_SNIPER_ZOOM_IN);\n\tint ZoomOutButton = ControlsManager.GetMouseButtonAssociatedWithAction(PED_SNIPER_ZOOM_OUT);\n\tif(ZoomInButton == rsMOUSEWHEELUPBUTTON || ZoomInButton == rsMOUSEWHEELDOWNBUTTON || ZoomOutButton == rsMOUSEWHEELUPBUTTON || ZoomOutButton == rsMOUSEWHEELDOWNBUTTON){\n\t\tif(CPad::GetPad(0)->GetMouseWheelUp() || CPad::GetPad(0)->GetMouseWheelDown()){\n\t\t\tif(CPad::GetPad(0)->SniperZoomIn()){\n\t\t\t\tTargetFOV = FOV - 10.0f;\n\t\t\t\tUseMouse = true;\n\t\t\t}\n\t\t\tif(CPad::GetPad(0)->SniperZoomOut()){\n\t\t\t\tTargetFOV = FOV + 10.0f;\n\t\t\t\tUseMouse = true;\n\t\t\t}\n\t\t}\n\t}\n\tif((CPad::GetPad(0)->SniperZoomIn() || CPad::GetPad(0)->SniperZoomOut()) && !UseMouse){\n\t\tif(CPad::GetPad(0)->SniperZoomOut()){\n\t\t\tFOV *= (255.0f*CTimer::GetTimeStep() + 10000.0f) / 10000.0f;\n\t\t\tTargetFOV = FOV;\n\t\t\tFOVSpeed = 0.0f;\n\t\t}else{\n\t\t\tFOV /= (255.0f*CTimer::GetTimeStep() + 10000.0f) / 10000.0f;\n\t\t\tTargetFOV = FOV;\n\t\t\tFOVSpeed = 0.0f;\n\t\t}\n\t}else{\n\t\tif(Abs(TargetFOV - FOV) > 0.5f)\n\t\t\tWellBufferMe(TargetFOV, &FOV, &FOVSpeed, 0.5f, 0.25f, false);\n\t\telse\n\t\t\tFOVSpeed = 0.0f;\n\t}\n\n\tTheCamera.SetMotionBlur(180, 255, 180, 120, MOTION_BLUR_SNIPER);\n\n\tif(FOV > DefaultFOV)\n\t\tFOV = DefaultFOV;\n\tif(Mode == MODE_CAMERA){\n\t\tif(FOV < 3.0f)\n\t\t\tFOV = 3.0f;\n\t}else{\n\t\tif(FOV < 15.0f)\n\t\t\tFOV = 15.0f;\n\t}\n\n\tFront = TargetCoors - Source;\n\tFront.Normalise();\n\tSource += Front*0.4f;\n\n\tif(m_bCollisionChecksOn){\n\t\tif(!CWorld::GetIsLineOfSightClear(TargetCoors, Source, true, true, false, true, false, true, true)){\n\t\t\tRwCameraSetNearClipPlane(Scene.camera, 0.4f);\n\t\t\tFailedTestTwelveFramesAgo = true;\n\t\t}else{\n\t\t\tCVector TestPoint;\n\t\t\tTestPoint.x = 3.0f * Cos(Alpha - DEGTORAD(20.0f)) * Cos(Beta + DEGTORAD(35.0f)) + Source.x;\n\t\t\tTestPoint.y = 3.0f * Cos(Alpha - DEGTORAD(20.0f)) * Sin(Beta + DEGTORAD(35.0f)) + Source.y;\n\t\t\tTestPoint.z = 3.0f * Sin(Alpha - DEGTORAD(20.0f)) + Source.z;\n\t\t\tif(!CWorld::GetIsLineOfSightClear(TestPoint, Source, true, true, false, true, false, true, true)){\n\t\t\t\tRwCameraSetNearClipPlane(Scene.camera, 0.4f);\n\t\t\t\tFailedTestTwelveFramesAgo = true;\n\t\t\t}else{\n\t\t\t\tTestPoint.x = 3.0f * Cos(Alpha - DEGTORAD(20.0f)) * Cos(Beta - DEGTORAD(35.0f)) + Source.x;\n\t\t\t\tTestPoint.y = 3.0f * Cos(Alpha - DEGTORAD(20.0f)) * Sin(Beta - DEGTORAD(35.0f)) + Source.y;\n\t\t\t\tTestPoint.z = 3.0f * Sin(Alpha - DEGTORAD(20.0f)) + Source.z;\n\t\t\t\tif(!CWorld::GetIsLineOfSightClear(TestPoint, Source, true, true, false, true, false, true, true)){\n\t\t\t\t\tRwCameraSetNearClipPlane(Scene.camera, 0.4f);\n\t\t\t\t\tFailedTestTwelveFramesAgo = true;\n\t\t\t\t}else\n\t\t\t\t\tFailedTestTwelveFramesAgo = false;\n\t\t\t}\n\t\t}\n\t}\n\n\tif(FailedTestTwelveFramesAgo)\n\t\tRwCameraSetNearClipPlane(Scene.camera, 0.4f);\n\telse if(Mode == MODE_CAMERA)\n\t\tRwCameraSetNearClipPlane(Scene.camera, ((15.0f - Min(FOV, 15.0f))*fCameraNearClipMult + 1.0f)*DEFAULT_NEAR);\n\tSource -= Front*0.4f;\n\n\tGetVectorsReadyForRW();\n\tfloat Rotation = CGeneral::GetATanOfXY(Front.x, Front.y) - HALFPI;\n\t((CPed*)TheCamera.pTargetEntity)->m_fRotationCur = Rotation;\n\t((CPed*)TheCamera.pTargetEntity)->m_fRotationDest = Rotation;\n}\n\nfloat INIT_SYPHON_GROUND_DIST = 2.419f;\nfloat INIT_SYPHON_ALPHA_OFFSET = -DEGTORAD(3.0f);\nfloat INIT_SYPHON_DEGREE_OFFSET = -DEGTORAD(30.0f);\nfloat FrontOffsetSyphon = -DEGTORAD(25.5f);\t// unused\nfloat INIT_SYPHON_Z_OFFSET = -0.5f;\n\nvoid\nCCam::Process_Syphon(const CVector &CameraTarget, float, float, float)\n{\n\tFOV = DefaultFOV;\n\n\tif(!CamTargetEntity->IsPed())\n\t\treturn;\n\n\tstatic bool CameraObscured = false;\n\t// unused FailedClippingTestPrevously\n\tstatic float BetaOffset = INIT_SYPHON_DEGREE_OFFSET;\n\t// unused AngleToGoTo\n\t// unused AngleToGoToSpeed\n\t// unused DistBetweenPedAndPlayerPreviouslyOn\n\tstatic float HeightDown = INIT_SYPHON_Z_OFFSET;\n\tstatic float AlphaOffset = INIT_SYPHON_ALPHA_OFFSET;\n\tstatic bool NegateBetaOffset = true;\n\tCVector TargetCoors;\n\tfloat fAimingDist;\n\tfloat TargetAlpha;\n\n\tbool StandingOnMovingThing = false;\n\tTargetCoors = CameraTarget;\n\tAlphaOffset = INIT_SYPHON_ALPHA_OFFSET;\n\tfloat GroundDist = INIT_SYPHON_GROUND_DIST;\n\n\twhile(Beta >= PI) Beta -= 2*PI;\n\twhile(Beta < -PI) Beta += 2*PI;\n\n\tfloat NewBeta = CGeneral::GetATanOfXY(TheCamera.m_cvecAimingTargetCoors.x - TargetCoors.x, TheCamera.m_cvecAimingTargetCoors.y - TargetCoors.y) + PI;\n\tif(ResetStatics){\n\t\tBetaOffset = INIT_SYPHON_DEGREE_OFFSET;\n\t\tBeta = CGeneral::GetATanOfXY(Source.x - TargetCoors.x, Source.y - TargetCoors.y);\n\t\t// some unuseds\n\t\tResetStatics = false;\n\t}\n\tif(NegateBetaOffset)\n\t\tBetaOffset = -INIT_SYPHON_DEGREE_OFFSET;\n\tBeta = NewBeta + BetaOffset;\n\tSource = TargetCoors;\n\tSource.x += GroundDist*Cos(Beta);\n\tSource.y += GroundDist*Sin(Beta);\n\tCPhysical *ground = (CPhysical*)((CPed*)CamTargetEntity)->m_pCurSurface;\n\tif(ground && (ground->IsVehicle() || ground->IsObject()))\n\t\tStandingOnMovingThing = true;\n\tTargetCoors.z += m_fSyphonModeTargetZOffSet;\n\n\tbool PlayerTooClose = false;\n\tfAimingDist = (TheCamera.m_cvecAimingTargetCoors - TargetCoors).Magnitude2D();\n\tif(fAimingDist < 6.5f){\n\t\tfAimingDist = 6.5f;\n\t\tPlayerTooClose = true;\n\t}\n\tTargetAlpha = CGeneral::GetATanOfXY(fAimingDist, TheCamera.m_cvecAimingTargetCoors.z - TargetCoors.z);\n\tif(ResetStatics)\t// BUG: can never happen\n\t\tAlpha = -TargetAlpha;\n\twhile(TargetAlpha >= PI) TargetAlpha -= 2*PI;\n\twhile(TargetAlpha < -PI) TargetAlpha += 2*PI;\n\twhile(Alpha >= PI) Alpha -= 2*PI;\n\twhile(Alpha < -PI) Alpha += 2*PI;\n\n\t// inlined\n\tif(StandingOnMovingThing)\n\t\tWellBufferMe(-TargetAlpha, &Alpha, &AlphaSpeed, 0.07f/2.0f, 0.015f/2.0f, true);\n\telse\n\t\tWellBufferMe(-TargetAlpha, &Alpha, &AlphaSpeed, 0.07f, 0.015f, true);\n\n\tSource.z += GroundDist*Sin(Alpha+AlphaOffset) + GroundDist*0.2f;\n\tif(Source.z < TargetCoors.z + HeightDown)\n\t\tSource.z = TargetCoors.z + HeightDown;\n\n\tif(!PlayerTooClose){\n\t\tCColPoint point;\n\t\tCEntity *entity = nil;\n\t\tCWorld::pIgnoreEntity = CamTargetEntity;\n\t\tif(CWorld::ProcessLineOfSight(TheCamera.m_cvecAimingTargetCoors, Source, point, entity, true, false, false, true, false, false, true)){\n\t\t\tCVector TestFront = TheCamera.m_cvecAimingTargetCoors - Source;\n\t\t\tTestFront.Normalise();\n\t\t\tCVector CamToPlayer = CameraTarget - Source;\n\t\t\tCVector CamToCol = point.point - Source;\n\t\t\tif(DotProduct(TestFront, CamToCol) > DotProduct(TestFront, CamToPlayer)){\n\t\t\t\t// collision is beyond player\n\t\t\t\tfloat ColDist = (TheCamera.m_cvecAimingTargetCoors - point.point).Magnitude();\n\t\t\t\tCVector PlayerToTarget = TheCamera.m_cvecAimingTargetCoors - CameraTarget;\n\t\t\t\tfloat PlayerToTargetDist = PlayerToTarget.Magnitude();\n\t\t\t\tPlayerToTarget.Normalise();\n\t\t\t\tCVector Center = TheCamera.m_cvecAimingTargetCoors - ColDist*PlayerToTarget;\n\t\t\t\tfloat Radius = (point.point - Center).Magnitude();\n\t\t\t\tif(CWorld::TestSphereAgainstWorld(Center, Radius, nil, true, false, false, true, false, true)){\n\t\t\t\t\tCVector LineToCol = gaTempSphereColPoints[0].point - Center;\n\t\t\t\t\tLineToCol -= DotProduct(LineToCol, PlayerToTarget)*PlayerToTarget;\n\t\t\t\t\t// unused\n\t\t\t\t\tCVector LineToPrevCol = point.point - Center;\n\t\t\t\t\tLineToPrevCol -= DotProduct(LineToPrevCol, PlayerToTarget)*PlayerToTarget;\n\t\t\t\t\tfloat LineDist = LineToCol.Magnitude();\n\t\t\t\t\tfloat NewBetaOffset = 0.0f;\n\t\t\t\t\tif(LineDist > 0.0f && ColDist > 0.1f){\n\t\t\t\t\t\t// scale offset at center to offset at player\n\t\t\t\t\t\tfloat DistOffset = LineDist/ColDist * PlayerToTargetDist;\n\t\t\t\t\t\t// turn into an angle\n\t\t\t\t\t\tNewBetaOffset = 0.9f*Asin(Min(DistOffset/GroundDist, 1.0f));\n\t\t\t\t\t}\n\t\t\t\t\tif(NewBetaOffset < BetaOffset){\n\t\t\t\t\t\tfloat Ratio = NewBetaOffset / BetaOffset;\n\t\t\t\t\t\tBetaOffset = NewBetaOffset;\n\t\t\t\t\t\tBeta = NewBeta + NewBetaOffset;\n\t\t\t\t\t\tGroundDist *= Max(Ratio, 0.5f);\n\t\t\t\t\t\tSource.x = TargetCoors.x +  GroundDist*Cos(Beta);\n\t\t\t\t\t\tSource.y = TargetCoors.y +  GroundDist*Sin(Beta);\n\t\t\t\t\t\tSource.z += (1.0f-Ratio)*0.5f;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tCWorld::pIgnoreEntity = nil;\n\t}\n\n\tFront = TheCamera.m_cvecAimingTargetCoors - Source;\n\tfloat TargetDistGround = Front.Magnitude2D();\n\tFront.Normalise();\n\tm_cvecTargetCoorsForFudgeInter = Source + TargetDistGround*Front;\n\tm_cvecTargetCoorsForFudgeInter.z = TargetCoors.z;\n\n\tCVector OrigSource = Source;\n\tTheCamera.AvoidTheGeometry(OrigSource, CameraTarget + CVector(0.0f, 0.0f, 0.75f), Source, FOV);\n\tSource.z = OrigSource.z;\n\n\tGetVectorsReadyForRW();\n}\n\nvoid\nCCam::Process_Syphon_Crim_In_Front(const CVector &CameraTarget, float, float, float)\n{\n\tFOV = DefaultFOV;\n\n\tif(!CamTargetEntity->IsPed())\n\t\treturn;\n\n\tCVector TargetCoors = CameraTarget;\n\tCVector vDist;\n\tfloat fDist, TargetDist;\n\tfloat zOffset;\n\tfloat AimingAngle;\n\n\tTargetDist = TheCamera.m_fPedZoomValueSmooth * 0.5f + 4.0f;\n\tvDist = Source - TargetCoors;\n\tfDist = vDist.Magnitude2D();\n\tzOffset = TargetDist - 2.65f;\n\tif(zOffset < 0.0f)\n\t\tzOffset = 0.0f;\n\tif(zOffset == 0.0f)\n\t\tSource = TargetCoors + CVector(1.0f, 1.0f, zOffset);\n\telse\n\t\tSource = TargetCoors + CVector(vDist.x/fDist*TargetDist, vDist.y/fDist*TargetDist, zOffset);\n\n\tAimingAngle = CGeneral::GetATanOfXY(TheCamera.m_cvecAimingTargetCoors.x - TargetCoors.x, TheCamera.m_cvecAimingTargetCoors.y - TargetCoors.y);\n\twhile(AimingAngle >= PI) AimingAngle -= 2*PI;\n\twhile(AimingAngle < -PI) AimingAngle += 2*PI;\n\n\tif(ResetStatics){\n\t\tif(AimingAngle > 0.0f)\n\t\t\tm_fPlayerInFrontSyphonAngleOffSet = -m_fPlayerInFrontSyphonAngleOffSet;\n\t\tResetStatics = false;\n\t}\n\n\tif(TheCamera.PlayerWeaponMode.Mode == MODE_SYPHON)\n\t\tBeta = AimingAngle + m_fPlayerInFrontSyphonAngleOffSet;\n\n\tSource.x = TargetCoors.x;\n\tSource.y = TargetCoors.y;\n\tSource.x += Cos(Beta) * TargetDist;\n\tSource.y += Sin(Beta) * TargetDist;\n\n\tTargetCoors = CameraTarget;\n\tTargetCoors.z += m_fSyphonModeTargetZOffSet;\n\tm_cvecTargetCoorsForFudgeInter = TargetCoors;\n\n\tCVector OrigSource = Source;\n\tTheCamera.AvoidTheGeometry(OrigSource, TargetCoors, Source, FOV);\n\n\tFront = TargetCoors - Source;\n\tGetVectorsReadyForRW();\n}\n\nfloat MAX_HEIGHT_UP = 15.0f;\nfloat WATER_Z_ADDITION = 2.75f;\nfloat WATER_Z_ADDITION_MIN = 1.5f;\nfloat SMALLBOAT_CLOSE_ALPHA_MINUS = 0.2f;\nfloat afBoatBetaDiffMult[3] = { 0.15f, 0.07f, 0.01f };\nfloat afBoatBetaSpeedDiffMult[3] = { 0.02f, 0.015f, 0.005f };\n\nvoid\nCCam::Process_BehindBoat(const CVector &CameraTarget, float TargetOrientation, float, float)\n{\n\tif(!CamTargetEntity->IsVehicle()){\n\t\tResetStatics = false;\n\t\treturn;\n\t}\n\n\tCVector TargetCoors = CameraTarget;\n\tfloat DeltaBeta = 0.0f;\n\tstatic float TargetWhenChecksWereOn = 0.0f;\n\tstatic float CenterObscuredWhenChecksWereOn = 0.0f;\n\tstatic float WaterZAddition = 2.75f;\n\tfloat WaterLevel = 0.0f;\n\tfloat MaxHeightUp = MAX_HEIGHT_UP;\n\tstatic float WaterLevelBuffered = 0.0f;\n\tstatic float WaterLevelSpeed = 0.0f;\n\tfloat BetaDiffMult = 0.0f;\n\tfloat BetaSpeedDiffMult = 0.0f;\n\n\tBeta = CGeneral::GetATanOfXY(TargetCoors.x - Source.x, TargetCoors.y - Source.y);\n\tFOV = DefaultFOV;\n\tfloat TargetAlpha = 0.0f;\n\n\tif(ResetStatics){\n\t\tCenterObscuredWhenChecksWereOn = 0.0f;\n\t\tTargetWhenChecksWereOn = 0.0f;\n\t}else if(DirectionWasLooking != LOOKING_FORWARD)\n\t\tBeta = TargetOrientation;\n\n\tif(!CWaterLevel::GetWaterLevelNoWaves(TargetCoors.x, TargetCoors.y, TargetCoors.z, &WaterLevel))\n\t\tWaterLevel = TargetCoors.z - 0.5f;\n\tif(ResetStatics){\n\t\tWaterLevelBuffered = WaterLevel;\n\t\tWaterLevelSpeed = 0.0f;\n\t}\n\tWellBufferMe(WaterLevel, &WaterLevelBuffered, &WaterLevelSpeed, 0.2f, 0.07f, false);\n\n\tstatic float FixerForGoingBelowGround = 0.4f;\n\tif(-FixerForGoingBelowGround < TargetCoors.z-WaterLevelBuffered+WATER_Z_ADDITION)\n\t\tWaterLevelBuffered += TargetCoors.z-WaterLevelBuffered+WATER_Z_ADDITION - FixerForGoingBelowGround;\n\n\tCVector BoatDimensions = CamTargetEntity->GetColModel()->boundingBox.GetSize();\n\tfloat BoatSize = BoatDimensions.Magnitude2D();\n\tint index = 0;\n\tTheCamera.GetArrPosForVehicleType(((CVehicle*)CamTargetEntity)->GetVehicleAppearance(), index);\n\tif(TheCamera.CarZoomIndicator == CAM_ZOOM_1){\n\t\tTargetAlpha = ZmOneAlphaOffset[index];\n\t\tBetaDiffMult = afBoatBetaDiffMult[0];\n\t\tBetaSpeedDiffMult = afBoatBetaSpeedDiffMult[0];\n\t}else if(TheCamera.CarZoomIndicator == CAM_ZOOM_2){\n\t\tTargetAlpha = ZmTwoAlphaOffset[index];\n\t\tBetaDiffMult = afBoatBetaDiffMult[1];\n\t\tBetaSpeedDiffMult = afBoatBetaSpeedDiffMult[1];\n\t}else if(TheCamera.CarZoomIndicator == CAM_ZOOM_3){\n\t\tTargetAlpha = ZmThreeAlphaOffset[index];\n\t\tBetaDiffMult = afBoatBetaDiffMult[2];\n\t\tBetaSpeedDiffMult = afBoatBetaSpeedDiffMult[2];\n\t}\n\tif(TheCamera.CarZoomIndicator == CAM_ZOOM_1 && BoatSize < 10.0f){\n\t\tTargetAlpha -= SMALLBOAT_CLOSE_ALPHA_MINUS;\n\t\tBoatSize = 10.0f;\n\t}else if(CCullZones::Cam1stPersonForPlayer()){\n\t\tfloat Water = 0.0f;\n\t\t// useless call\n\t\t//CWaterLevel::GetWaterLevelNoWaves(TargetCoors.x, TargetCoors.y, TargetCoors.z, &Water);\n\t\tWater = (WaterLevel + WATER_Z_ADDITION_MIN - WaterLevelBuffered - WATER_Z_ADDITION)/(BoatDimensions.z/2.0f + MaxHeightUp);\n\t\tTargetAlpha = Asin(clamp(Water, -1.0f, 1.0f));\n\t}\n\n\tif(ResetStatics){\n\t\tAlpha = TargetAlpha;\n\t\tAlphaSpeed = 0.0f;\n\t}\n\tWellBufferMe(TargetAlpha, &Alpha, &AlphaSpeed, 0.15f, 0.07f, true);\n\n\tif(ResetStatics){\n\t\tBeta = TargetOrientation;\n\t\tDeltaBeta = 0.0f;\n\t}\n\t// inlined\n\tWellBufferMe(TargetOrientation, &Beta, &BetaSpeed, BetaDiffMult * ((CVehicle*)CamTargetEntity)->m_vecMoveSpeed.Magnitude(), BetaSpeedDiffMult, true);\n\n\tSource = (TheCamera.CarZoomValueSmooth+BoatSize) * CVector(-Cos(Beta), -Sin(Beta), 0.0f) + TargetCoors;\n\tSource.z = WaterLevelBuffered + WATER_Z_ADDITION + (BoatDimensions.z/2.0f + MaxHeightUp) * Sin(Alpha);\n\n\tm_cvecTargetCoorsForFudgeInter = TargetCoors;\n\tCVector OrigSource = Source;\n\tTheCamera.AvoidTheGeometry(OrigSource, TargetCoors, Source, FOV);\n\tFront = TargetCoors - Source;\n\tFront.Normalise();\n\n\n\tfloat TargetRoll;\n\tif(CPad::GetPad(0)->GetDPadLeft() || CPad::GetPad(0)->GetDPadRight()){\n#ifdef FIX_BUGS\n\t\tfloat fwdSpeed = 180.0f*DotProduct(((CVehicle*)CamTargetEntity)->m_vecMoveSpeed, CamTargetEntity->GetForward());\n\t\tif(fwdSpeed > 210.0f) fwdSpeed = 210.0f;\n#endif\n\t\tif(CPad::GetPad(0)->GetDPadLeft())\n\t\t\tTargetRoll = DEGTORAD(10.0f)*TiltOverShoot[index] + f_max_role_angle;\n\t\telse\n\t\t\tTargetRoll = -(DEGTORAD(10.0f)*TiltOverShoot[index] + f_max_role_angle);\n\t\tCVector FwdTarget = CamTargetEntity->GetForward();\n\t\tFwdTarget.Normalise();\n\t\tfloat AngleDiff = DotProduct(FwdTarget, Front);\n\t\tAngleDiff = Acos(Min(Abs(AngleDiff), 1.0f));\n#ifdef FIX_BUGS\n\t\tTargetRoll *= fwdSpeed/210.0f * Sin(AngleDiff);\n#else\n\t\tTargetRoll *= Sin(AngleDiff);\n#endif\n\t}else{\n\t\tfloat fwdSpeed = 180.0f*DotProduct(((CVehicle*)CamTargetEntity)->m_vecMoveSpeed, CamTargetEntity->GetForward());\n\t\tif(fwdSpeed > 210.0f) fwdSpeed = 210.0f;\n\t\tTargetRoll = CPad::GetPad(0)->GetLeftStickX()/128.0f * fwdSpeed/210.0f;\n\t\tCVector FwdTarget = CamTargetEntity->GetForward();\n\t\tFwdTarget.Normalise();\n\t\tfloat AngleDiff = DotProduct(FwdTarget, Front);\n\t\tAngleDiff = Acos(Min(Abs(AngleDiff), 1.0f));\n\t\tTargetRoll *= (DEGTORAD(10.0f)*TiltOverShoot[index] + f_max_role_angle) * Sin(AngleDiff);\n\t}\n\n\tWellBufferMe(TargetRoll, &f_Roll, &f_rollSpeed, 0.15f, 0.07f, false);\n\tUp = CVector(Cos(f_Roll + HALFPI), 0.0f, Sin(f_Roll + HALFPI));\n\tUp.Normalise();\n\tFront.Normalise();\n\tCVector Left = CrossProduct(Up, Front);\n\tLeft.Normalise();\n\tUp = CrossProduct(Front, Left);\n\tUp.Normalise();\n\n\tResetStatics = false;\n}\n\nfloat FIGHT_HORIZ_DIST = 3.0f;\nfloat FIGHT_VERT_DIST = 1.0f;\nfloat FIGHT_BETA_ANGLE = 125.0f;\n\nvoid\nCCam::Process_Fight_Cam(const CVector &CameraTarget, float TargetOrientation, float, float)\n{\n\tif(!CamTargetEntity->IsPed())\n\t\treturn;\n\n\tFOV = DefaultFOV;\n\tfloat HorizDist = FIGHT_HORIZ_DIST;\n\tfloat VertDist = FIGHT_VERT_DIST;\n\tfloat BetaLeft, BetaRight, DeltaBetaLeft, DeltaBetaRight;\n\tstatic bool PreviouslyFailedBuildingChecks = false;\n\tfloat TargetCamHeight;\n\tCVector TargetCoors;\n\n\tm_fMinDistAwayFromCamWhenInterPolating = FIGHT_HORIZ_DIST;\n\tFront = Source - CameraTarget;\n\tif(ResetStatics)\n\t\tBeta = CGeneral::GetATanOfXY(Front.x, Front.y);\n\twhile(TargetOrientation >= PI) TargetOrientation -= 2*PI;\n\twhile(TargetOrientation < -PI) TargetOrientation += 2*PI;\n\twhile(Beta >= PI) Beta -= 2*PI;\n\twhile(Beta < -PI) Beta += 2*PI;\n\n\t// Figure out Beta\n\tBetaLeft = TargetOrientation - DEGTORAD(FIGHT_BETA_ANGLE);\n\tBetaRight = TargetOrientation + DEGTORAD(FIGHT_BETA_ANGLE);\n\tDeltaBetaLeft = Beta - BetaLeft;\n\tDeltaBetaRight = Beta - BetaRight;\n\twhile(DeltaBetaLeft >= PI) DeltaBetaLeft -= 2*PI;\n\twhile(DeltaBetaLeft < -PI) DeltaBetaLeft += 2*PI;\n\twhile(DeltaBetaRight >= PI) DeltaBetaRight -= 2*PI;\n\twhile(DeltaBetaRight < -PI) DeltaBetaRight += 2*PI;\n\n\tif(ResetStatics){\n\t\tif(Abs(DeltaBetaLeft) < Abs(DeltaBetaRight))\n\t\t\tm_fTargetBeta = DeltaBetaLeft;\n\t\telse\n\t\t\tm_fTargetBeta = DeltaBetaRight;\n\t\tm_fBufferedTargetOrientation = TargetOrientation;\n\t\tm_fBufferedTargetOrientationSpeed = 0.0f;\n\t\tm_bCollisionChecksOn = true;\n\t\tBetaSpeed = 0.0f;\n\t}else if(CPad::GetPad(0)->WeaponJustDown()){\n\t\tif(Abs(DeltaBetaLeft) < Abs(DeltaBetaRight))\n\t\t\tm_fTargetBeta = DeltaBetaLeft;\n\t\telse\n\t\t\tm_fTargetBeta = DeltaBetaRight;\n\t}\n\n\tWellBufferMe(m_fTargetBeta, &Beta, &BetaSpeed, 0.015f, 0.007f, true);\n\n\tSource = CameraTarget + HorizDist*CVector(Cos(Beta), Sin(Beta), 0.0f);\n\tSource.z += VertDist;\n\n\tWellBufferMe(TargetOrientation, &m_fBufferedTargetOrientation, &m_fBufferedTargetOrientationSpeed, 0.07f, 0.004f, true);\n\tTargetCoors = CameraTarget + 0.1f*CVector(Cos(m_fBufferedTargetOrientation), Sin(m_fBufferedTargetOrientation), 0.0f);\n\n\tTargetCamHeight = CameraTarget.z - Source.z + Max(m_fPedBetweenCameraHeightOffset, m_fDimensionOfHighestNearCar) + VertDist;\n\tif(TargetCamHeight > m_fCamBufferedHeight)\n\t\tWellBufferMe(TargetCamHeight, &m_fCamBufferedHeight, &m_fCamBufferedHeightSpeed, 0.15f, 0.04f, false);\n\telse\n\t\tWellBufferMe(0.0f, &m_fCamBufferedHeight, &m_fCamBufferedHeightSpeed, 0.08f, 0.0175f, false);\n\tSource.z += m_fCamBufferedHeight;\n\n\tm_cvecTargetCoorsForFudgeInter = TargetCoors;\n\tCVector OrigSource = Source;\n\tTheCamera.AvoidTheGeometry(OrigSource, TargetCoors, Source, FOV);\n\tFront = TargetCoors - Source;\n\tFront.Normalise();\n\tGetVectorsReadyForRW();\n\n\tResetStatics = false;\n}\n\n/*\n// Spline format is this, but game doesn't seem to use any kind of struct:\nstruct Spline\n{\n\tfloat numFrames;\n\tstruct {\n\t\tfloat time;\n\t\tfloat f[3];\t// CVector for Vector spline\n\t} frames[1];\t// numFrames\n};\n*/\n\n// These two functions are pretty ugly\n\n#define MS(t) (uint32)((t)*1000.0f)\n\nvoid\nFindSplinePathPositionFloat(float *out, float *spline, uint32 time, uint32 &marker)\n{\n\t// marker is at time\n\tuint32 numFrames = spline[0];\n\tuint32 timeDelta = MS(spline[marker] - spline[marker-4]);\n\tuint32 endTime = MS(spline[4*(numFrames-1) + 1]);\n\tif(time < endTime){\n\t\tbool canAdvance = true;\n\t\tif((marker-1)/4 > numFrames){\n\t\t\tcanAdvance = false;\n\t\t\tmarker = 4*(numFrames-1) + 1;\n\t\t}\n\t\t// skipping over small time deltas apparently?\n\t\twhile(timeDelta <= 75 && canAdvance){\n\t\t\tmarker += 4;\n\t\t\tif((marker-1)/4 > numFrames){\n\t\t\t\tcanAdvance = false;\n\t\t\t\tmarker = 4*(numFrames-1) + 1;\n\t\t\t}\n\t\t\ttimeDelta = (spline[marker] - spline[marker-4]) * 1000.0f;\n\t\t}\n\t}\n\tfloat a = ((float)time - (float)MS(spline[marker-4])) / (float)MS(spline[marker] - spline[marker-4]);\n\ta = clamp(a, 0.0f, 1.0f);\n\tfloat b = 1.0f - a;\n\t*out =\tb*b*b * spline[marker-3] +\n\t\t3.0f*a*b*b * spline[marker-1] +\n\t\t3.0f*a*a*b * spline[marker+2] +\n\t\ta*a*a * spline[marker+1];\n}\n\nvoid\nFindSplinePathPositionVector(CVector *out, float *spline, uint32 time, uint32 &marker)\n{\n\t// marker is at time\n\tuint32 numFrames = spline[0];\n\tuint32 timeDelta = MS(spline[marker] - spline[marker-10]);\n\tuint32 endTime = MS(spline[10*(numFrames-1) + 1]);\n\tif(time < endTime){\n\t\tbool canAdvance = true;\n\t\tif((marker-1)/10 > numFrames){\n\t\t\tcanAdvance = false;\n\t\t\tmarker = 10*(numFrames-1) + 1;\n\t\t}\n\t\t// skipping over small time deltas apparently?\n\t\twhile(timeDelta <= 75 && canAdvance){\n\t\t\tmarker += 10;\n\t\t\tif((marker-1)/10 > numFrames){\n\t\t\t\tcanAdvance = false;\n\t\t\t\tmarker = 10*(numFrames-1) + 1;\n\t\t\t}\n\t\t\ttimeDelta = (spline[marker] - spline[marker-10]) * 1000.0f;\n\t\t}\n\t}\n\n\tif((marker-1)/10 > numFrames){\n\t\tprintf(\"Arraymarker %i \\n\", marker);\n\t\tprintf(\"Path zero %i \\n\", numFrames);\n\t}\n\n\tfloat a = ((float)time - (float)MS(spline[marker-10])) / (float)MS(spline[marker] - spline[marker-10]);\n\ta = clamp(a, 0.0f, 1.0f);\n\tfloat b = 1.0f - a;\n\tout->x =\n\t\tb*b*b * spline[marker-9] +\n\t\t3.0f*a*b*b * spline[marker-3] +\n\t\t3.0f*a*a*b * spline[marker+4] +\n\t\ta*a*a * spline[marker+1];\n\tout->y =\n\t\tb*b*b * spline[marker-8] +\n\t\t3.0f*a*b*b * spline[marker-2] +\n\t\t3.0f*a*a*b * spline[marker+5] +\n\t\ta*a*a * spline[marker+2];\n\tout->z =\n\t\tb*b*b * spline[marker-7] +\n\t\t3.0f*a*b*b * spline[marker-1] +\n\t\t3.0f*a*a*b * spline[marker+6] +\n\t\ta*a*a * spline[marker+3];\n\t*out += TheCamera.m_vecCutSceneOffset;\n}\n\nvoid\nCCam::Process_FlyBy(const CVector&, float, float, float)\n{\n\tfloat UpAngle = 0.0f;\n\tstatic float FirstFOVValue = 0.0f;\n\tstatic float PsuedoFOV;\n\tstatic uint32 ArrayMarkerFOV;\n\tstatic uint32 ArrayMarkerUp;\n\tstatic uint32 ArrayMarkerSource;\n\tstatic uint32 ArrayMarkerFront;\n\n\tif(TheCamera.m_bcutsceneFinished)\n\t\treturn;\n#ifdef FIX_BUGS\n\t// this would crash, not nice when cycling debug mode\n\tif(TheCamera.m_arrPathArray[0].m_arr_PathData == nil)\n\t\treturn;\n#endif\n\n\tUp = CVector(0.0f, 0.0f, 1.0f);\n\tif(TheCamera.m_bStartingSpline)\n\t\tm_fTimeElapsedFloat += CTimer::GetTimeStepNonClippedInMilliseconds();\n\telse{\n\t\tm_fTimeElapsedFloat = 0.0f;\n\t\tm_uiFinishTime = MS(TheCamera.m_arrPathArray[2].m_arr_PathData[10*((int)TheCamera.m_arrPathArray[2].m_arr_PathData[0]-1) + 1]);\n\t\tTheCamera.m_bStartingSpline = true;\n\t\tFirstFOVValue = TheCamera.m_arrPathArray[0].m_arr_PathData[2];\n\t\tPsuedoFOV = TheCamera.m_arrPathArray[0].m_arr_PathData[2];\n\t\tArrayMarkerFOV = 5;\n\t\tArrayMarkerUp = 5;\n\t\tArrayMarkerSource = 11;\n\t\tArrayMarkerFront = 11;\n\t}\n\n\tfloat fTime = m_fTimeElapsedFloat;\n\tuint32 uiFinishTime = m_uiFinishTime;\n\tuint32 uiTime = fTime;\n\tif(uiTime < uiFinishTime){\n\t\tTheCamera.m_fPositionAlongSpline = (float) uiTime / uiFinishTime;\n\n\t\twhile(uiTime >= (TheCamera.m_arrPathArray[2].m_arr_PathData[ArrayMarkerSource] - TheCamera.m_arrPathArray[2].m_arr_PathData[1])*1000.0f)\n\t\t\tArrayMarkerSource += 10;\n\t\tFindSplinePathPositionVector(&Source, TheCamera.m_arrPathArray[2].m_arr_PathData, uiTime, ArrayMarkerSource);\n\n\t\twhile(uiTime >= (TheCamera.m_arrPathArray[3].m_arr_PathData[ArrayMarkerFront] - TheCamera.m_arrPathArray[3].m_arr_PathData[1])*1000.0f)\n\t\t\tArrayMarkerFront += 10;\n\t\tFindSplinePathPositionVector(&Front, TheCamera.m_arrPathArray[3].m_arr_PathData, uiTime, ArrayMarkerFront);\n\n\t\twhile(uiTime >= (TheCamera.m_arrPathArray[1].m_arr_PathData[ArrayMarkerUp] - TheCamera.m_arrPathArray[1].m_arr_PathData[1])*1000.0f)\n\t\t\tArrayMarkerUp += 4;\n\t\tFindSplinePathPositionFloat(&UpAngle, TheCamera.m_arrPathArray[1].m_arr_PathData, uiTime, ArrayMarkerUp);\n\t\tUpAngle = DEGTORAD(UpAngle) + HALFPI;\n\t\tUp.x = Cos(UpAngle);\n\t\tUp.z = Sin(UpAngle);\n\n\t\twhile(uiTime >= (TheCamera.m_arrPathArray[0].m_arr_PathData[ArrayMarkerFOV] - TheCamera.m_arrPathArray[0].m_arr_PathData[1])*1000.0f)\n\t\t\tArrayMarkerFOV += 4;\n\t\tFindSplinePathPositionFloat(&PsuedoFOV, TheCamera.m_arrPathArray[0].m_arr_PathData, uiTime, ArrayMarkerFOV);\n\n\t\tm_cvecTargetCoorsForFudgeInter = Front;\n\t\tFront = Front - Source;\n\t\tFront.Normalise();\n\t\tCVector Left = CrossProduct(Up, Front);\n\t\tUp = CrossProduct(Front, Left);\n\t\tUp.Normalise();\n\t}else if(uiTime >= uiFinishTime){\n\t\t// end\n\t\tArrayMarkerSource = (TheCamera.m_arrPathArray[2].m_arr_PathData[0] - 1)*10 + 1;\n\t\tArrayMarkerFront = (TheCamera.m_arrPathArray[3].m_arr_PathData[0] - 1)*10 + 1;\n\t\tArrayMarkerUp = (TheCamera.m_arrPathArray[1].m_arr_PathData[0] - 1)*4 + 1;\n\t\tArrayMarkerFOV = (TheCamera.m_arrPathArray[0].m_arr_PathData[0] - 1)*4 + 1;\n\n\t\tFindSplinePathPositionVector(&Source, TheCamera.m_arrPathArray[2].m_arr_PathData, uiTime, ArrayMarkerSource);\n\t\tFindSplinePathPositionVector(&Front, TheCamera.m_arrPathArray[3].m_arr_PathData, uiTime, ArrayMarkerFront);\n\t\tFindSplinePathPositionFloat(&UpAngle, TheCamera.m_arrPathArray[1].m_arr_PathData, uiTime, ArrayMarkerUp);\n\t\tUpAngle = DEGTORAD(UpAngle) + HALFPI;\n\t\tUp.x = Cos(UpAngle);\n\t\tUp.z = Sin(UpAngle);\n\t\tFindSplinePathPositionFloat(&PsuedoFOV, TheCamera.m_arrPathArray[0].m_arr_PathData, uiTime, ArrayMarkerFOV);\n\n\t\tTheCamera.m_fPositionAlongSpline = 1.0f;\n\t\tArrayMarkerFOV = 0;\n\t\tArrayMarkerUp = 0;\n\t\tArrayMarkerSource = 0;\n\t\tArrayMarkerFront = 0;\n\n\t\tm_cvecTargetCoorsForFudgeInter = Front;\n\t\tFront = Front - Source;\n\t\tFront.Normalise();\n\t\tCVector Left = CrossProduct(Up, Front);\n\t\tUp = CrossProduct(Front, Left);\n\t\tUp.Normalise();\n\t}\n\tFOV = PsuedoFOV;\n}\n\nCVector vecWheelCamBoatOffset(-0.5f, -0.8f, 0.3f);\nCVector vecWheelCamBoatOffsetAlt(0.2f, -0.2f, -0.3f);\nfloat fWheelCamCarXOffset = 0.33f;\nfloat fWheelCamBikeXOffset = 0.2f;\n\nbool\nCCam::Process_WheelCam(const CVector&, float, float, float)\n{\n\tFOV = DefaultFOV;\n\n\tCVector WheelPos;\n\tif(CamTargetEntity->IsPed()){\n\t\t// what? ped with wheels or what?\n\t\tSource = Multiply3x3(CamTargetEntity->GetMatrix(), CVector(-0.3f, -0.5f, 0.1f));\n\t\tSource += CamTargetEntity->GetPosition();\n\t\tFront = CVector(1.0f, 0.0f, 0.0f);\n\t}else{\n\t\tWheelPos = CamTargetEntity->GetColModel()->boundingBox.min;\n\t\tWheelPos.x -= 0.33f;\n\t\tWheelPos.y = -2.3f;\n\t\tWheelPos.z = 0.3f;\n\t\tSource = CamTargetEntity->GetMatrix() * WheelPos;\n\t\tFront = CamTargetEntity->GetForward();\n\t}\n\n\tCVector NewUp, Right;\n\tif(CamTargetEntity->IsVehicle() &&\n\t   (((CVehicle*)CamTargetEntity)->GetVehicleAppearance() == VEHICLE_APPEARANCE_HELI ||\n\t    ((CVehicle*)CamTargetEntity)->GetVehicleAppearance() == VEHICLE_APPEARANCE_PLANE)){\n\t\tWheelPos.x = -1.55f;\n\t\tRight = CamTargetEntity->GetRight();\n\t\tNewUp = CamTargetEntity->GetUp();\n\t\tSource = CamTargetEntity->GetMatrix() * WheelPos;\n\t}else if(CamTargetEntity->IsVehicle() && ((CVehicle*)CamTargetEntity)->IsBoat()){\n\t\tNewUp = CVector(0.0f, 0.0f, 1.0f);\n\t\tRight = CrossProduct(Front, NewUp);\n\t\tRight.Normalise();\n\t\tNewUp = CrossProduct(Right, Front);\n\t\tNewUp.Normalise();\n\n\t\tCVector BoatCamPos(0.0f, 0.0f, 0.0f);\n\t\tif(((CVehicle*)CamTargetEntity)->pDriver){\n\t\t\t((CVehicle*)CamTargetEntity)->pDriver->m_pedIK.GetComponentPosition(BoatCamPos, PED_HEAD);\n\t\t\tBoatCamPos += ((CVehicle*)CamTargetEntity)->m_vecMoveSpeed * CTimer::GetTimeStep();\n\t\t\tBoatCamPos += vecWheelCamBoatOffset.x * Right;\n\t\t\tBoatCamPos += vecWheelCamBoatOffset.y * CamTargetEntity->GetForward();\n\t\t\tBoatCamPos.z += vecWheelCamBoatOffset.z;\n\t\t\tif(CamTargetEntity->GetModelIndex() == MI_PREDATOR){\n\t\t\t\tBoatCamPos += vecWheelCamBoatOffsetAlt.x * Right;\n\t\t\t\tBoatCamPos += vecWheelCamBoatOffsetAlt.y * CamTargetEntity->GetForward();\n\t\t\t\tBoatCamPos.z += vecWheelCamBoatOffsetAlt.z;\n\t\t\t}\n\t\t\tSource = BoatCamPos;\n\t\t}else\n\t\t\tSource.z += 2.0f*vecWheelCamBoatOffset.z;\n\t}else if(CamTargetEntity->IsVehicle() && ((CVehicle*)CamTargetEntity)->IsBike()){\n\t\tNewUp = CVector(0.0f, 0.0f, 1.0f);\n\t\tRight = CrossProduct(Front, NewUp);\n\t\tRight.Normalise();\n\t\tNewUp = CrossProduct(Right, Front);\n\t\tNewUp.Normalise();\n\n\t\tWheelPos.z += fWheelCamCarXOffset - fWheelCamBikeXOffset;\n\t\tSource = CamTargetEntity->GetPosition();\n\t\tSource += WheelPos.x * CamTargetEntity->GetRight();\n\t\tSource += WheelPos.y * Front;\n\t\tSource += WheelPos.z * Up;\n\t}else{\n\t\tNewUp = CVector(0.0f, 0.0f, 1.0f);\n\t\tRight = CrossProduct(Front, NewUp);\n\t\tRight.Normalise();\n\t\tNewUp = CrossProduct(Right, Front);\n\t\tNewUp.Normalise();\n\t}\n\n\tfloat Roll = Cos((CTimer::GetTimeInMilliseconds()&0x1FFFF)/(float)0x1FFFF * TWOPI);\n\tUp = Cos(Roll*0.4f)*NewUp + Sin(Roll*0.4f)*Right;\n\n\tCEntity *entity = nil;\n\tCColPoint point;\n\tCWorld::pIgnoreEntity = CamTargetEntity;\n\tbool blocked = CWorld::ProcessLineOfSight(Source, CamTargetEntity->GetPosition(), point, entity, true, false, false, true, false, false, true);\n\tCWorld::pIgnoreEntity = nil;\n\treturn !blocked;\n}\n\nint BOAT_UNDERWATER_CAM_BLUR = 20;\nfloat BOAT_UNDERWATER_CAM_COLORMAG_LIMIT = 10.0f;\n\n//--MIAIM: done\nvoid\nCCam::Process_Fixed(const CVector &CameraTarget, float, float, float)\n{\n\tif(DirectionWasLooking != LOOKING_FORWARD)\n\t\tDirectionWasLooking = LOOKING_FORWARD;\n\n\tSource = m_cvecCamFixedModeSource;\n\tFront = CameraTarget - Source;\n\tFront.Normalise();\n\tm_cvecTargetCoorsForFudgeInter = CameraTarget;\n\tGetVectorsReadyForRW();\n\n\tUp = CVector(0.0f, 0.0f, 1.0f) + m_cvecCamFixedModeUpOffSet;\n\tUp.Normalise();\n\tCVector Right = CrossProduct(Front, Up);\n\tRight.Normalise();\n\tUp = CrossProduct(Right, Front);\n\n\tFOV = DefaultFOV;\n\tif(TheCamera.m_bUseSpecialFovTrain)\n\t\tFOV = TheCamera.m_fFovForTrain;\n\n\tfloat WaterZ = 0.0f;\n\tif(CWaterLevel::GetWaterLevel(Source, &WaterZ, true) && Source.z < WaterZ){\n\t\tfloat WaterLum = Sqrt(SQR(CTimeCycle::GetWaterRed()) + SQR(CTimeCycle::GetWaterGreen()) + SQR(CTimeCycle::GetWaterBlue()));\n\t\tif(WaterLum > BOAT_UNDERWATER_CAM_COLORMAG_LIMIT){\n\t\t\tfloat f = BOAT_UNDERWATER_CAM_COLORMAG_LIMIT/WaterLum;\n\t\t\tTheCamera.SetMotionBlur(CTimeCycle::GetWaterRed()*f,\n\t\t\t\tCTimeCycle::GetWaterGreen()*f,\n\t\t\t\tCTimeCycle::GetWaterBlue()*f, BOAT_UNDERWATER_CAM_BLUR, MOTION_BLUR_LIGHT_SCENE);\n\t\t}else{\n\t\t\tTheCamera.SetMotionBlur(CTimeCycle::GetWaterRed(),\n\t\t\t\tCTimeCycle::GetWaterGreen(),\n\t\t\t\tCTimeCycle::GetWaterBlue(), BOAT_UNDERWATER_CAM_BLUR, MOTION_BLUR_LIGHT_SCENE);\n\t\t}\n\t}\n\n#ifdef PC_PLAYER_CONTROLS\n\tif(FrontEndMenuManager.m_ControlMethod == CONTROL_STANDARD && Using3rdPersonMouseCam()){\n\t\tCPed *player = FindPlayerPed();\n\t\tif(player && player->CanStrafeOrMouseControl()){\n\t\t\tfloat Heading = Front.Heading();\n\t\t\t((CPed*)TheCamera.pTargetEntity)->m_fRotationCur = Heading;\n\t\t\t((CPed*)TheCamera.pTargetEntity)->m_fRotationDest = Heading;\n\t\t\tTheCamera.pTargetEntity->SetHeading(Heading);\n\t\t\tTheCamera.pTargetEntity->GetMatrix().UpdateRW();\n\t\t}\n\t}\n#endif\n}\n\nvoid\nCCam::Process_LightHouse(const CVector &CameraTarget, float, float, float)\n{\n\tstatic float Timer;\n\n\tSource = CameraTarget;\n\tSource.x = 474.3f;\n\tSource.y = -1717.6f;\n\n\tint CamMode;\n\tif(CameraTarget.z > 57.0f && (CameraTarget-Source).Magnitude2D() > 3.2f){\n\t\t// Outside at top\n\t\tif(Timer > 0.0f){\n\t\t\tTimer -= CTimer::GetTimeStep();\n\t\t\tCamMode = 1;\n\t\t}else{\n\t\t\tTimer = -24.0f;\n\t\t\tCamMode = 2;\n\t\t}\n\t}else if(CameraTarget.z > 57.0f){\n\t\t// Inside at top\n\t\tif(Timer < 0.0f){\n\t\t\tTimer += CTimer::GetTimeStep();\n\t\t\tCamMode = 2;\n\t\t}else{\n\t\t\tTimer = 24.0f;\n\t\t\tCamMode = 1;\n\t\t}\n\t}else{\n\t\tTimer = 0.0f;\n\t\tCamMode = 0;\n\t}\n\n\tif(CamMode == 2){\n\t\tSource.z = 57.5f;\n\t\tFront = Source - CameraTarget;\n\t\tFront.Normalise();\n\t\tSource.x = CameraTarget.x - 5.0f*Front.x;\n\t\tSource.y = CameraTarget.y - 5.0f*Front.y;\n\t}else if(CamMode == 1){\n\t\tFront = CameraTarget - Source;\n\t\tFront.Normalise();\n\t\tSource.x = CameraTarget.x - 2.0f*Front.x;\n\t\tSource.y = CameraTarget.y - 2.0f*Front.y;\n\t}else{\n\t\tSource.z += 4.0f;\n\t\tFront = CameraTarget - Source;\n\t\tFront.Normalise();\n\t\tSource -= 4.0f*Front;\n\t\tSource.z = Min(Source.z, 55.0f);\n\t\tFront = CameraTarget - Source;\n\t}\n\n\tm_cvecTargetCoorsForFudgeInter = CameraTarget;\n\tGetVectorsReadyForRW();\n\n\tUp = CVector(0.0f, 0.0f, 1.0f) + m_cvecCamFixedModeUpOffSet;\n\tUp.Normalise();\n\tCVector Right = CrossProduct(Front, Up);\n\tRight.Normalise();\n\tUp = CrossProduct(Right, Front);\n\n\tFOV = DefaultFOV;\n\tif(TheCamera.m_bUseSpecialFovTrain)\t// uh, sure...\n\t\tFOV = TheCamera.m_fFovForTrain;\n}\n\nvoid\nCCam::Process_Player_Fallen_Water(const CVector &CameraTarget, float TargetOrientation, float, float)\n{\n\tCColPoint colPoint;\n\tCEntity *entity = nil;\n\n\tFOV = DefaultFOV;\n\tSource = m_vecLastAboveWaterCamPosition;\n\tSource.z += 4.0f;\n\n\tm_cvecTargetCoorsForFudgeInter = CameraTarget;\n\tFront = CameraTarget - Source;\n\tFront.Normalise();\n\tif(CWorld::ProcessLineOfSight(CameraTarget, Source, colPoint, entity, true, false, false, true, false, true, true))\n\t\tSource = colPoint.point;\n\tGetVectorsReadyForRW();\n\tFront = CameraTarget - Source;\n\tFront.Normalise();\n}\n\nvoid\nCCam::Process_SpecialFixedForSyphon(const CVector &CameraTarget, float, float, float)\n{\n\tSource = m_cvecCamFixedModeSource;\n\tm_cvecTargetCoorsForFudgeInter = CameraTarget;\n\tm_cvecTargetCoorsForFudgeInter.z += m_fSyphonModeTargetZOffSet;\n\tFront = CameraTarget - Source;\n\tCVector OrigSource = Source;\n\tTheCamera.AvoidTheGeometry(OrigSource, m_cvecTargetCoorsForFudgeInter, Source, FOV);\n\tFront.z += m_fSyphonModeTargetZOffSet;\n\n\tGetVectorsReadyForRW();\n\n\tUp += m_cvecCamFixedModeUpOffSet;\n\tUp.Normalise();\n\tCVector Left = CrossProduct(Up, Front);\n\tLeft.Normalise();\n\tFront = CrossProduct(Left, Up);\n\tFront.Normalise();\n\tFOV = DefaultFOV;\n}\n\n#ifdef IMPROVED_CAMERA\n\n#define KEYJUSTDOWN(k) ControlsManager.GetIsKeyboardKeyJustDown((RsKeyCodes)k)\n#define KEYDOWN(k) ControlsManager.GetIsKeyboardKeyDown((RsKeyCodes)k)\n#define CTRLJUSTDOWN(key) \\\n\t       ((KEYDOWN(rsLCTRL) || KEYDOWN(rsRCTRL)) && KEYJUSTDOWN((RsKeyCodes)key) || \\\n\t        (KEYJUSTDOWN(rsLCTRL) || KEYJUSTDOWN(rsRCTRL)) && KEYDOWN((RsKeyCodes)key))\n#define CTRLDOWN(key) ((KEYDOWN(rsLCTRL) || KEYDOWN(rsRCTRL)) && KEYDOWN((RsKeyCodes)key))\n\n\nvoid\nCCam::Process_Debug(const CVector&, float, float, float)\n{\n\tstatic float Speed = 0.0f;\n\tstatic float PanSpeedX = 0.0f;\n\tstatic float PanSpeedY = 0.0f;\n\tCVector TargetCoors;\n\n\tRwCameraSetNearClipPlane(Scene.camera, DEFAULT_NEAR);\n\tFOV = DefaultFOV;\n\tAlpha += DEGTORAD(CPad::GetPad(1)->GetLeftStickY()) / 50.0f;\n\tBeta  += DEGTORAD(CPad::GetPad(1)->GetLeftStickX()*1.5f) / 19.0f;\n\tif(CPad::GetPad(0)->GetLeftMouse()){\n\t\tAlpha += DEGTORAD(CPad::GetPad(0)->GetMouseY()/2.0f);\n\t\tBeta += DEGTORAD(CPad::GetPad(0)->GetMouseX()/2.0f);\n\t}\n\n\tTargetCoors.x = Source.x + Cos(Alpha) * Sin(Beta) * 7.0f;\n\tTargetCoors.y = Source.y + Cos(Alpha) * Cos(Beta) * 7.0f;\n\tTargetCoors.z = Source.z + Sin(Alpha) * 3.0f;\n\n\tif(Alpha > DEGTORAD(89.5f)) Alpha = DEGTORAD(89.5f);\n\telse if(Alpha < DEGTORAD(-89.5f)) Alpha = DEGTORAD(-89.5f);\n\n\tif(CPad::GetPad(1)->GetSquare() || KEYDOWN('W'))\n\t\tSpeed += 0.1f;\n\telse if(CPad::GetPad(1)->GetCross() || KEYDOWN('S'))\n\t\tSpeed -= 0.1f;\n\telse\n\t\tSpeed = 0.0f;\n\tif(Speed > 70.0f) Speed = 70.0f;\n\tif(Speed < -70.0f) Speed = -70.0f;\n\n\n\tif(KEYDOWN(rsRIGHT) || KEYDOWN('D'))\n\t\tPanSpeedX += 0.1f;\n\telse if(KEYDOWN(rsLEFT) || KEYDOWN('A'))\n\t\tPanSpeedX -= 0.1f;\n\telse\n\t\tPanSpeedX = 0.0f;\n\tif(PanSpeedX > 70.0f) PanSpeedX = 70.0f;\n\tif(PanSpeedX < -70.0f) PanSpeedX = -70.0f;\n\n\n\tif(KEYDOWN(rsUP))\n\t\tPanSpeedY += 0.1f;\n\telse if(KEYDOWN(rsDOWN))\n\t\tPanSpeedY -= 0.1f;\n\telse\n\t\tPanSpeedY = 0.0f;\n\tif(PanSpeedY > 70.0f) PanSpeedY = 70.0f;\n\tif(PanSpeedY < -70.0f) PanSpeedY = -70.0f;\n\n\n\tFront = TargetCoors - Source;\n\tFront.Normalise();\n\tSource = Source + Front*Speed;\n\n\tUp = CVector{ 0.0f, 0.0f, 1.0f };\n\tCVector Right = CrossProduct(Front, Up);\n\tUp = CrossProduct(Right, Front);\n\tSource = Source + Up*PanSpeedY + Right*PanSpeedX;\n\n\tif(Source.z < -450.0f)\n\t\tSource.z = -450.0f;\n\n\tif(CPad::GetPad(1)->GetRightShoulder2JustDown() || KEYJUSTDOWN(rsENTER)){\n\t\tif(FindPlayerVehicle())\n\t\t\tFindPlayerVehicle()->Teleport(Source);\n\t\telse\n\t\t\tCWorld::Players[CWorld::PlayerInFocus].m_pPed->SetPosition(Source);\n\t}\n\n\t// stay inside sectors\n\twhile(CWorld::GetSectorX(Source.x) > NUMSECTORS_X-5.0f)\n\t\tSource.x -= 1.0f;\n\twhile(CWorld::GetSectorX(Source.x) < 5.0f)\n\t\tSource.x += 1.0f;\n\twhile(CWorld::GetSectorY(Source.y) > NUMSECTORS_X-5.0f)\n\t\tSource.y -= 1.0f;\n\twhile(CWorld::GetSectorY(Source.y) < 5.0f)\n\t\tSource.y += 1.0f;\n\tGetVectorsReadyForRW();\n\n#ifdef FIX_BUGS\n\tCPad::GetPad(0)->SetDisablePlayerControls(PLAYERCONTROL_CAMERA);\n#else\n\tCPad::GetPad(0)->DisablePlayerControls = PLAYERCONTROL_CAMERA;\n#endif\n\n\tif(CPad::GetPad(1)->GetLeftShockJustDown() && gbBigWhiteDebugLightSwitchedOn)\n\t\tCShadows::StoreShadowToBeRendered(SHADOWTYPE_ADDITIVE, gpShadowExplosionTex, &Source,\n\t\t\t12.0f, 0.0f, 0.0f, -12.0f,\n\t\t\t128, 128, 128, 128, 1000.0f, false, 1.0f, nil, false);\n\n\tif(CHud::m_Wants_To_Draw_Hud){\n\t\tchar str[256];\n\t\tsprintf(str, \"CamX: %f CamY: %f  CamZ:  %f\", Source.x, Source.y, Source.z);\n\t\tsprintf(str, \"Frontx: %f, Fronty: %f, Frontz: %f \", Front.x, Front.y, Front.z);\n\t\tsprintf(str, \"Look@: %f, Look@: %f, Look@: %f \", Front.x + Source.x, Front.y + Source.y, Front.z + Source.z);\n\t}\n}\n#else\nvoid\nCCam::Process_Debug(const CVector&, float, float, float)\n{\n\tstatic float Speed = 0.0f;\n\tCVector TargetCoors;\n\n\tRwCameraSetNearClipPlane(Scene.camera, DEFAULT_NEAR);\n\tFOV = DefaultFOV;\n\tAlpha += DEGTORAD(CPad::GetPad(1)->GetLeftStickY()) / 50.0f;\n\tBeta  += DEGTORAD(CPad::GetPad(1)->GetLeftStickX()*1.5f) / 19.0f;\n\n\tTargetCoors.x = Source.x + Cos(Alpha) * Sin(Beta) * 7.0f;\n\tTargetCoors.y = Source.y + Cos(Alpha) * Cos(Beta) * 7.0f;\n\tTargetCoors.z = Source.z + Sin(Alpha) * 3.0f;\n\n\tif(Alpha > DEGTORAD(89.5f)) Alpha = DEGTORAD(89.5f);\n\telse if(Alpha < DEGTORAD(-89.5f)) Alpha = DEGTORAD(-89.5f);\n\n\tif(CPad::GetPad(1)->GetSquare() || CPad::GetPad(1)->GetLeftMouse())\n\t\tSpeed += 0.1f;\n\telse if(CPad::GetPad(1)->GetCross() || CPad::GetPad(1)->GetRightMouse())\n\t\tSpeed -= 0.1f;\n\telse\n\t\tSpeed = 0.0f;\n\tif(Speed > 70.0f) Speed = 70.0f;\n\tif(Speed < -70.0f) Speed = -70.0f;\n\n\tFront = TargetCoors - Source;\n\tFront.Normalise();\n\tSource = Source + Front*Speed;\n\n\tif(Source.z < -450.0f)\n\t\tSource.z = -450.0f;\n\n\tif(CPad::GetPad(1)->GetRightShoulder2JustDown()){\n\t\tif(FindPlayerVehicle())\n\t\t\tFindPlayerVehicle()->Teleport(Source);\n\t\telse\n\t\t\tCWorld::Players[CWorld::PlayerInFocus].m_pPed->SetPosition(Source);\n\t}\n\n\t// stay inside sectors\n\twhile(CWorld::GetSectorX(Source.x) > NUMSECTORS_X-5.0f)\n\t\tSource.x -= 1.0f;\n\twhile(CWorld::GetSectorX(Source.x) < 5.0f)\n\t\tSource.x += 1.0f;\n\twhile(CWorld::GetSectorY(Source.y) > NUMSECTORS_X-5.0f)\n\t\tSource.y -= 1.0f;\n\twhile(CWorld::GetSectorY(Source.y) < 5.0f)\n\t\tSource.y += 1.0f;\n\tGetVectorsReadyForRW();\n\n\tif(CPad::GetPad(1)->GetLeftShockJustDown() && gbBigWhiteDebugLightSwitchedOn)\n\t\tCShadows::StoreShadowToBeRendered(SHADOWTYPE_ADDITIVE, gpShadowExplosionTex, &Source,\n\t\t\t12.0f, 0.0f, 0.0f, -12.0f,\n\t\t\t128, 128, 128, 128, 1000.0f, false, 1.0f, nil, 1.0f);\n\n\tif(CHud::m_Wants_To_Draw_Hud){\n\t\tchar str[256];\n\t\tsprintf(str, \"CamX: %f CamY: %f  CamZ:  %f\", Source.x, Source.y, Source.z);\n\t\tsprintf(str, \"Frontx: %f, Fronty: %f, Frontz: %f \", Front.x, Front.y, Front.z);\n\t\tsprintf(str, \"Look@: %f, Look@: %f, Look@: %f \", Front.x + Source.x, Front.y + Source.y, Front.z + Source.z);\n\t}\n}\n#endif\n\n#ifdef GTA_SCENE_EDIT\nvoid\nCCam::Process_Editor(const CVector&, float, float, float)\n{\n\tstatic float Speed = 0.0f;\n\tCVector TargetCoors;\n\n\tif(ResetStatics){\n\t\tSource = CVector(796.0f, -937.0, 40.0f);\n\t\tCamTargetEntity = nil;\n\t}\n\tResetStatics = false;\n\n\tRwCameraSetNearClipPlane(Scene.camera, DEFAULT_NEAR);\n\tFOV = DefaultFOV;\n\tAlpha += DEGTORAD(CPad::GetPad(1)->GetLeftStickY()) / 50.0f;\n\tBeta  += DEGTORAD(CPad::GetPad(1)->GetLeftStickX()*1.5f) / 19.0f;\n\n\tif(CamTargetEntity && CSceneEdit::m_bCameraFollowActor){\n\t\tTargetCoors = CamTargetEntity->GetPosition();\n\t}else if(CSceneEdit::m_bRecording){\n\t\tTargetCoors.x = Source.x + Cos(Alpha) * Sin(Beta) * 7.0f;\n\t\tTargetCoors.y = Source.y + Cos(Alpha) * Cos(Beta) * 7.0f;\n\t\tTargetCoors.z = Source.z + Sin(Alpha) * 7.0f;\n\t}else\n\t\tTargetCoors = CSceneEdit::m_vecCamHeading + Source;\n\tCSceneEdit::m_vecCurrentPosition = TargetCoors;\n\tCSceneEdit::m_vecCamHeading = TargetCoors - Source;\n\n\tif(Alpha > DEGTORAD(89.5f)) Alpha = DEGTORAD(89.5f);\n\telse if(Alpha < DEGTORAD(-89.5f)) Alpha = DEGTORAD(-89.5f);\n\n\tif(CPad::GetPad(1)->GetSquare() || CPad::GetPad(1)->GetLeftMouse())\n\t\tSpeed += 0.1f;\n\telse if(CPad::GetPad(1)->GetCross() || CPad::GetPad(1)->GetRightMouse())\n\t\tSpeed -= 0.1f;\n\telse\n\t\tSpeed = 0.0f;\n\tif(Speed > 70.0f) Speed = 70.0f;\n\tif(Speed < -70.0f) Speed = -70.0f;\n\n\tFront = TargetCoors - Source;\n\tFront.Normalise();\n\tSource = Source + Front*Speed;\n\n\tif(Source.z < -450.0f)\n\t\tSource.z = -450.0f;\n\n\tif(CPad::GetPad(1)->GetRightShoulder2JustDown()){\n\t\tif(FindPlayerVehicle())\n\t\t\tFindPlayerVehicle()->Teleport(Source);\n\t\telse\n\t\t\tCWorld::Players[CWorld::PlayerInFocus].m_pPed->SetPosition(Source);\n\t\t\t\n\t}\n\n\t// stay inside sectors\n\twhile(CWorld::GetSectorX(Source.x) > NUMSECTORS_X-5.0f)\n\t\tSource.x -= 1.0f;\n\twhile(CWorld::GetSectorX(Source.x) < 5.0f)\n\t\tSource.x += 1.0f;\n\twhile(CWorld::GetSectorY(Source.y) > NUMSECTORS_X-5.0f)\n\t\tSource.y -= 1.0f;\n\twhile(CWorld::GetSectorY(Source.y) < 5.0f)\n\t\tSource.y += 1.0f;\n\tGetVectorsReadyForRW();\n\n\tif(CPad::GetPad(1)->GetLeftShockJustDown() && gbBigWhiteDebugLightSwitchedOn)\n\t\tCShadows::StoreShadowToBeRendered(SHADOWTYPE_ADDITIVE, gpShadowExplosionTex, &Source,\n\t\t\t12.0f, 0.0f, 0.0f, -12.0f,\n\t\t\t128, 128, 128, 128, 1000.0f, false, 1.0f, nil, false);\n\n\tif(CHud::m_Wants_To_Draw_Hud){\n\t\tchar str[256];\n\t\tsprintf(str, \"CamX: %f CamY: %f  CamZ:  %f\", Source.x, Source.y, Source.z);\n\t\tsprintf(str, \"Frontx: %f, Fronty: %f, Frontz: %f \", Front.x, Front.y, Front.z);\n\t\tsprintf(str, \"Look@: %f, Look@: %f, Look@: %f \", Front.x + Source.x, Front.y + Source.y, Front.z + Source.z);\n\t}\n}\n#endif\n\nvoid\nCCam::Process_ModelView(const CVector &CameraTarget, float, float, float)\n{\n\tCVector TargetCoors = CameraTarget;\n\tfloat Angle = Atan2(Front.x, Front.y);\n\tFOV = DefaultFOV;\n\n\tAngle += CPad::GetPad(0)->GetLeftStickX()/1280.0f;\n\tif(Distance < 10.0f)\n\t\tDistance += CPad::GetPad(0)->GetLeftStickY()/1000.0f;\n\telse\n\t\tDistance += CPad::GetPad(0)->GetLeftStickY() * ((Distance - 10.0f)/20.0f + 1.0f) / 1000.0f;\n#ifdef IMPROVED_CAMERA\n\tif(CPad::GetPad(0)->GetLeftMouse()){\n\t\tDistance += DEGTORAD(CPad::GetPad(0)->GetMouseY()/2.0f);\n\t\tAngle += DEGTORAD(CPad::GetPad(0)->GetMouseX()/2.0f);\n\t}\n#endif\n\tif(Distance < 1.5f)\n\t\tDistance = 1.5f;\n\n\tFront.x = Cos(0.3f) * Sin(Angle);\n\tFront.y = Cos(0.3f) * Cos(Angle);\n\tFront.z = -Sin(0.3f);\n\tSource = CameraTarget - Distance*Front;\n\n\tGetVectorsReadyForRW();\n}\n\nfloat DEADCAM_HEIGHT_START = 2.0f;\nfloat DEADCAM_HEIGHT_RATE = 0.04f;\nfloat DEADCAM_WAFT_AMPLITUDE = 2.0f;\nfloat DEADCAM_WAFT_RATE = 600.0f;\nfloat DEADCAM_WAFT_TILT_AMP = -0.35f;\n\nvoid\nCCam::ProcessPedsDeadBaby(void)\n{\n\tCVector TargetCoors;\n\tCVector CamPos;\n\n\tif(TheCamera.pTargetEntity->IsPed())\n\t\t((CPed*)TheCamera.pTargetEntity)->m_pedIK.GetComponentPosition(TargetCoors, PED_MID);\n\telse if(TheCamera.pTargetEntity->IsVehicle()){\n\t\tTargetCoors = TheCamera.pTargetEntity->GetPosition();\n\t\tTargetCoors.z += TheCamera.pTargetEntity->GetColModel()->boundingBox.max.z;\n\t}else\n\t\treturn;\n\n\tif(ResetStatics){\n\t\tTheCamera.m_uiTimeLastChange = CTimer::GetTimeInMilliseconds();\n\t\tCamPos = TargetCoors;\n\t\tCamPos.z += DEADCAM_HEIGHT_START;\n\t\tfloat WaterZ = 0.0f;\n\t\tif(CWaterLevel::GetWaterLevelNoWaves(TargetCoors.x, TargetCoors.y, TargetCoors.z, &WaterZ)){\n\t\t\tif(WaterZ + 1.5f > CamPos.z)\n\t\t\t\tCamPos.z = WaterZ + 1.5f;\n\t\t}\n\t\tCVector Right = CrossProduct(TheCamera.pTargetEntity->GetForward(), CVector(0.0f, 0.0f, 1.0f));\n\t\tRight.z = 0.0f;\n\t\tRight.Normalise();\n\t\tFront = TargetCoors - CamPos;\n\t\tFront.Normalise();\n\t\tUp = CrossProduct(Right, Front);\n\t\tUp.Normalise();\n\t\tResetStatics = false;\n\t}else{\n\t\tCamPos = Source;\n\t\tif(CWorld::TestSphereAgainstWorld(CamPos+CVector(0.0f, 0.0f, 0.2f), 0.3f, TheCamera.pTargetEntity, true, true, false, true, false, true) == nil)\n\t\t\tCamPos.z += DEADCAM_HEIGHT_RATE*CTimer::GetTimeStep();\n\t\tCVector Right = CrossProduct(TheCamera.pTargetEntity->GetForward(), CVector(0.0f, 0.0f, 1.0f));\n\t\tRight.z = 0.0f;\n\t\tRight.Normalise();\n\n\t\tfloat Time = CTimer::GetTimeInMilliseconds() - TheCamera.m_uiTimeLastChange;\n\t\tCVector WaftOffset = DEADCAM_WAFT_AMPLITUDE * Min(1000.0f,Time)/1000.0f * Sin(Time/DEADCAM_WAFT_RATE) * Right;\n\t\tCVector WaftPos = TargetCoors + WaftOffset;\n\t\tWaftPos.z = CamPos.z;\n\t\tCVector WaftFront = WaftPos - CamPos;\n\t\tWaftFront.Normalise();\n\t\tif(CWorld::TestSphereAgainstWorld(CamPos+0.2f*WaftFront, 0.3f, TheCamera.pTargetEntity, true, true, false, true, false, true) == nil)\n\t\t\tCamPos = WaftPos;\n\n\t\tFront = CVector(0.0f, 0.0f, -1.0f);\n\t\tFront += Cos(Time/DEADCAM_WAFT_RATE) * DEADCAM_WAFT_TILT_AMP * Min(2000.0f,Time)/2000.0f * Right;\n\n\t\tFront.Normalise();\n\t\tUp = CrossProduct(Right, Front);\n\t\tUp.Normalise();\n\t}\n\n\tSource = CamPos;\n\tCVector OrigSource = Source;\n\tTheCamera.AvoidTheGeometry(OrigSource, TargetCoors, Source, FOV);\n\tTheCamera.m_bMoveCamToAvoidGeom = false;\n}\n\nfloat ARRESTDIST_BEHIND_COP = 5.0f;\nfloat ARRESTDIST_RIGHTOF_COP = 3.0f;\nfloat ARRESTDIST_ABOVE_COP = 1.4f;\t// unused\nfloat ARRESTDIST_MINFROM_PLAYER = 8.0f;\nfloat ARRESTCAM_LAMP_BEST_DIST = 17.0f;\nfloat ARRESTCAM_ROTATION_SPEED = 0.1f;\nfloat ARRESTCAM_ROTATION_UP = 0.05f;\nfloat ARRESTCAM_S_ROTATION_UP = 0.1f;\nfloat ARRESTDIST_ALONG_GROUND = 5.0f;\nfloat ARRESTDIST_SIDE_GROUND = 10.0f;\nfloat ARRESTDIST_ABOVE_GROUND = 0.7f;\nfloat ARRESTCAM_LAMPPOST_ROTATEDIST = 10.0f;\nfloat ARRESTCAM_LAMPPOST_TRANSLATE = 0.1f;\n\nbool\nCCam::GetLookAlongGroundPos(CEntity *Target, CPed *Cop, CVector &TargetCoors, CVector &SourceOut)\n{\n\tif(Target == nil || Cop == nil)\n\t\treturn false;\n\tCVector CopToTarget = TargetCoors - Cop->GetPosition();\n\tCopToTarget.z = 0.0f;\n\tCopToTarget.Normalise();\n\tSourceOut = TargetCoors + ARRESTDIST_ALONG_GROUND*CopToTarget;\n\tCVector Side = CrossProduct(CopToTarget, CVector(0.0f, 0.0f, 1.0f));\n\tSourceOut += ARRESTDIST_SIDE_GROUND*Side;\n\tSourceOut.z += 5.0f;\n\tbool found = false;\n\tfloat ground = CWorld::FindGroundZFor3DCoord(SourceOut.x, SourceOut.y, SourceOut.z, &found);\n\tif(found)\n\t\tSourceOut.z = ground + ARRESTDIST_ABOVE_GROUND;\n\treturn true;\n}\n\nbool\nCCam::GetLookFromLampPostPos(CEntity *Target, CPed *Cop, CVector &TargetCoors, CVector &SourceOut)\n{\n\tint i;\n\tint16 NumObjects;\n\tCEntity *Objects[16];\n\tCEntity *NearestLampPost = nil;\n\tCWorld::FindObjectsInRange(TargetCoors, 30.0f, true, &NumObjects, 15, Objects, false, false, false, true, true);\n\tfloat NearestDist = 10000.0f;\n\tfor(i = 0; i < NumObjects; i++){\n\t\tif(Objects[i]->GetIsStatic() && Objects[i]->GetUp().z > 0.9f && IsLampPost(Objects[i]->GetModelIndex())){\n\t\t\tfloat Dist = (Objects[i]->GetPosition() - TargetCoors).Magnitude2D();\n\t\t\tif(Abs(ARRESTCAM_LAMP_BEST_DIST - Dist) < NearestDist){\n\t\t\t\tCVector TestStart = Objects[i]->GetColModel()->boundingBox.max;\n\t\t\t\tTestStart = Objects[i]->GetMatrix() * TestStart;\n\t\t\t\tCVector TestEnd = TestStart - TargetCoors;\n\t\t\t\tTestEnd.Normalise();\n\t\t\t\tTestEnd += TargetCoors;\n\t\t\t\tif(CWorld::GetIsLineOfSightClear(TestStart, TestEnd, true, false, false, false, false, true, true)){\n\t\t\t\t\tNearestDist = Abs(ARRESTCAM_LAMP_BEST_DIST - Dist);\n\t\t\t\t\tNearestLampPost = Objects[i];\n\t\t\t\t\tSourceOut = TestStart;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn NearestLampPost != nil;\n}\n\nbool\nCCam::GetLookOverShoulderPos(CEntity *Target, CPed *Cop, CVector &TargetCoors, CVector &SourceOut)\n{\n\tif(Target == nil || Cop == nil)\n\t\treturn false;\n\tCVector CopCoors = Cop->GetPosition();\n\tCVector CopToTarget = TargetCoors - CopCoors;\n\tCVector Side = CrossProduct(CopToTarget, CVector(0.0f, 0.0f, 1.0f));\n\tSide.Normalise();\n\tCopCoors += ARRESTDIST_RIGHTOF_COP * Side;\n\tCopToTarget.Normalise();\n\tif(CopToTarget.z < -0.7071f){\n\t\tCopToTarget.z = -0.7071f;\n\t\tfloat GroundDist = CopToTarget.Magnitude2D();\n\t\tif(GroundDist > 0.0f){\n\t\t\tCopToTarget.x *= 0.7071f/GroundDist;\n\t\t\tCopToTarget.y *= 0.7071f/GroundDist;\n\t\t}\n\t\tCopToTarget.Normalise();\n\t}else{\n\t\tif(CopToTarget.z > 0.0f){\n\t\t\tCopToTarget.z = 0.0f;\n\t\t\tCopToTarget.Normalise();\n\t\t}\n\t}\n\tCopCoors -= ARRESTDIST_BEHIND_COP * CopToTarget;\n\tCopToTarget = TargetCoors - CopCoors;\n\tfloat Dist = CopToTarget.Magnitude();\n\tif(Dist < ARRESTDIST_MINFROM_PLAYER && Dist > 0.0f)\n\t\tCopToTarget *= ARRESTDIST_MINFROM_PLAYER/Dist;\n\tSourceOut = TargetCoors - CopToTarget;\n\treturn true;\n}\n\nenum {\n\tARRESTCAM_OVERSHOULDER = 1,\n\tARRESTCAM_ALONGGROUND,\n\tARRESTCAM_ALONGGROUND_RIGHT,\n\tARRESTCAM_ALONGGROUND_RIGHT_UP,\n\tARRESTCAM_ALONGGROUND_LEFT,\n\tARRESTCAM_ALONGGROUND_LEFT_UP,\n\tARRESTCAM_LAMPPOST,\n};\n\nint nUsingWhichCamera;\nCPed *pStoredCopPed;\n\nbool\nCCam::ProcessArrestCamOne(void)\n{\n\tCVector TargetPos;\n\tCVector CamSource;\n\tCPed *cop = nil;\n\tFOV = 45.0f;\n\tbool foundPos = false;\n\tint ArrestModes[5] = { -1, -1, -1, -1, -1 };\n\n\tif(ResetStatics){\n\t\tCPed *targetPed = (CPed*)TheCamera.pTargetEntity;\n\t\tnUsingWhichCamera = 0;\n\t\tif(TheCamera.pTargetEntity->IsPed()){\n\t\t\t((CPed*)TheCamera.pTargetEntity)->m_pedIK.GetComponentPosition(TargetPos, PED_MID);\n\t\t\tif(FindPlayerPed() && FindPlayerPed()->m_pArrestingCop)\n\t\t\t\tcop = FindPlayerPed()->m_pArrestingCop;\n\t\t\tif(cop && CGeneral::GetRandomNumberInRange(0.0f, 1.0f) > 0.5f){\n\t\t\t\tArrestModes[0] = ARRESTCAM_OVERSHOULDER;\n\t\t\t\tArrestModes[1] = ARRESTCAM_ALONGGROUND;\n\t\t\t\tArrestModes[2] = ARRESTCAM_OVERSHOULDER;\n\t\t\t\tArrestModes[3] = ARRESTCAM_LAMPPOST;\n\t\t\t}else{\n\t\t\t\tArrestModes[0] = ARRESTCAM_ALONGGROUND;\n\t\t\t\tArrestModes[1] = ARRESTCAM_OVERSHOULDER;\n\t\t\t\tArrestModes[2] = ARRESTCAM_LAMPPOST;\n\t\t\t}\n\t\t}else if(TheCamera.pTargetEntity->IsVehicle()){\n\t\t\tCVehicle *targetVehicle = (CVehicle*)TheCamera.pTargetEntity;\n\t\t\tif(targetVehicle->pDriver && targetVehicle->pDriver->IsPlayer()){\n\t\t\t\ttargetPed = targetVehicle->pDriver;\n\t\t\t\ttargetPed->m_pedIK.GetComponentPosition(TargetPos, PED_MID);\n\t\t\t}else{\n\t\t\t\ttargetPed = nil;\n\t\t\t\tTargetPos = targetVehicle->GetPosition();\n\t\t\t}\n\n\t\t\tif(FindPlayerPed() && FindPlayerPed()->m_pArrestingCop)\n\t\t\t\tcop = FindPlayerPed()->m_pArrestingCop;\n\t\t\tif(cop && CGeneral::GetRandomNumberInRange(0.0f, 1.0f) > 0.65f){\n\t\t\t\tArrestModes[0] = ARRESTCAM_OVERSHOULDER;\n\t\t\t\tArrestModes[1] = ARRESTCAM_LAMPPOST;\n\t\t\t\tArrestModes[2] = ARRESTCAM_ALONGGROUND;\n\t\t\t\tArrestModes[3] = ARRESTCAM_OVERSHOULDER;\n\t\t\t}else{\n\t\t\t\tArrestModes[0] = ARRESTCAM_LAMPPOST;\n\t\t\t\tArrestModes[1] = ARRESTCAM_ALONGGROUND;\n\t\t\t\tArrestModes[2] = ARRESTCAM_OVERSHOULDER;\n\t\t\t}\n\t\t}else\n\t\t\treturn false;\n\n\t\tfor(int i = 0; nUsingWhichCamera == 0 && i < ARRAY_SIZE(ArrestModes) && ArrestModes[i] > 0; i++){\n\t\t\tswitch(ArrestModes[i]){\n\t\t\tcase ARRESTCAM_OVERSHOULDER:\n\t\t\t\tif(cop){\n\t\t\t\t\tfoundPos = GetLookOverShoulderPos(TheCamera.pTargetEntity, cop, TargetPos, CamSource);\n\t\t\t\t\tpStoredCopPed = cop;\n\t\t\t\t\tcop = nil;\n\t\t\t\t}else if(targetPed){\n\t\t\t\t\tfor(int j = 0; j < targetPed->m_numNearPeds; j++){\n\t\t\t\t\t\tCPed *nearPed = targetPed->m_nearPeds[j];\n\t\t\t\t\t\tif(nearPed->GetPedState() == PED_ARREST_PLAYER)\n\t\t\t\t\t\t\tfoundPos = GetLookOverShoulderPos(TheCamera.pTargetEntity, nearPed, TargetPos, CamSource);\n\t\t\t\t\t\tif(foundPos){\n\t\t\t\t\t\t\tpStoredCopPed = nearPed;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase ARRESTCAM_ALONGGROUND:\n\t\t\t\tif(cop){\n\t\t\t\t\tfoundPos = GetLookAlongGroundPos(TheCamera.pTargetEntity, cop, TargetPos, CamSource);\n\t\t\t\t\tpStoredCopPed = cop;\n\t\t\t\t\tcop = nil;\n\t\t\t\t}else if(targetPed){\n\t\t\t\t\tfor(int j = 0; j < targetPed->m_numNearPeds; j++){\n\t\t\t\t\t\tCPed *nearPed = targetPed->m_nearPeds[j];\n\t\t\t\t\t\tif(nearPed->GetPedState() == PED_ARREST_PLAYER)\n\t\t\t\t\t\t\tfoundPos = GetLookAlongGroundPos(TheCamera.pTargetEntity, nearPed, TargetPos, CamSource);\n\t\t\t\t\t\tif(foundPos){\n\t\t\t\t\t\t\tpStoredCopPed = nearPed;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase ARRESTCAM_LAMPPOST:\n\t\t\t\tfoundPos = GetLookFromLampPostPos(TheCamera.pTargetEntity, cop, TargetPos, CamSource);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tif(foundPos){\n\t\t\t\tif(pStoredCopPed)\n\t\t\t\t\tpStoredCopPed->RegisterReference((CEntity**)&pStoredCopPed);\n\t\t\t\tnUsingWhichCamera = ArrestModes[i];\n\t\t\t\tif(ArrestModes[i] == ARRESTCAM_ALONGGROUND){\n\t\t\t\t\tfloat rnd = CGeneral::GetRandomNumberInRange(0.0f, 5.0f);\n\t\t\t\t\tif(rnd < 1.0f) nUsingWhichCamera = ARRESTCAM_ALONGGROUND;\n\t\t\t\t\telse if(rnd < 2.0f) nUsingWhichCamera = ARRESTCAM_ALONGGROUND_RIGHT;\n\t\t\t\t\telse if(rnd < 3.0f) nUsingWhichCamera = ARRESTCAM_ALONGGROUND_RIGHT_UP;\n\t\t\t\t\telse if(rnd < 4.0f) nUsingWhichCamera = ARRESTCAM_ALONGGROUND_LEFT;\n\t\t\t\t\telse nUsingWhichCamera = ARRESTCAM_ALONGGROUND_LEFT_UP;\n\t\t\t\t}\n\t\t\t}else\n\t\t\t\tpStoredCopPed = nil;\n\t\t}\n\n\t\tSource = CamSource;\n\t\tCVector OrigSource = Source;\n\t\tTheCamera.AvoidTheGeometry(OrigSource, TargetPos, Source, FOV);\n\t\tFront = TargetPos - Source;\n\t\tFront.Normalise();\n\t\tUp = CVector(0.0f, 0.0f, 1.0f);\n\t\tCVector Right = CrossProduct(Front, Up);\n\t\tRight.Normalise();\n\t\tUp = CrossProduct(Right, Front);\n\t\tif(nUsingWhichCamera != 0)\n\t\t\tResetStatics = false;\n\t\treturn true;\n\t}\n\n\tif(TheCamera.pTargetEntity->IsPed()){\n\t\t((CPed*)TheCamera.pTargetEntity)->m_pedIK.GetComponentPosition(TargetPos, PED_MID);\n\t}else if(TheCamera.pTargetEntity->IsVehicle()){\n\t\tCPed *driver = ((CVehicle*)TheCamera.pTargetEntity)->pDriver;\n\t\tif(driver && driver->IsPlayer())\n\t\t\tdriver->m_pedIK.GetComponentPosition(TargetPos, PED_MID);\n\t\telse\n\t\t\tTargetPos = TheCamera.pTargetEntity->GetPosition();\n\t}else\n\t\treturn false;\n\n\tif(nUsingWhichCamera == ARRESTCAM_OVERSHOULDER && pStoredCopPed){\n\t\tfoundPos = GetLookOverShoulderPos(TheCamera.pTargetEntity, pStoredCopPed, TargetPos, CamSource);\n\t\tfloat newZ = Source.z + ARRESTCAM_S_ROTATION_UP*CTimer::GetTimeStep();\n\t\tif(CamSource.z > newZ)\n\t\t\tCamSource.z = newZ;\n\t}else if(nUsingWhichCamera >= ARRESTCAM_ALONGGROUND_RIGHT && nUsingWhichCamera <= ARRESTCAM_ALONGGROUND_LEFT_UP){\n\t\tCamSource = Source;\n\t\tFront = TargetPos - CamSource;\n\t\tFront.Normalise();\n\t\tUp = CVector(0.0f, 0.0f, 1.0f);\n\t\tCVector Right = CrossProduct(Front, Up);\n\t\tif(nUsingWhichCamera == ARRESTCAM_ALONGGROUND_LEFT || nUsingWhichCamera == ARRESTCAM_ALONGGROUND_LEFT_UP)\n\t\t\tRight *= -1.0f;\n\t\tif(CWorld::TestSphereAgainstWorld(CamSource + 0.5f*Right, 0.4f, TheCamera.pTargetEntity, true, true, false, true, false, true) == nil){\n\t\t\tfoundPos = true;\n\t\t\tCamSource += Right*ARRESTCAM_ROTATION_SPEED*CTimer::GetTimeStep();\n\t\t\tif(nUsingWhichCamera == ARRESTCAM_ALONGGROUND_RIGHT_UP || nUsingWhichCamera == ARRESTCAM_ALONGGROUND_LEFT_UP){\n\t\t\t\tCamSource.z += ARRESTCAM_ROTATION_UP*CTimer::GetTimeStep();\n\t\t\t}else{\n\t\t\t\tbool found = false;\n\t\t\t\tfloat ground = CWorld::FindGroundZFor3DCoord(CamSource.x, CamSource.y, CamSource.z, &found);\n\t\t\t\tif(found)\n\t\t\t\t\tCamSource.z = ground + ARRESTDIST_ABOVE_GROUND;\n\t\t\t}\n\t\t}\n\t}else if(nUsingWhichCamera == ARRESTCAM_LAMPPOST){\n\t\tCamSource = Source;\n\t\tFront = TargetPos - CamSource;\n\t\tFront.z = 0.0f;\n\t\tFront.Normalise();\n\t\tUp = CVector(0.0f, 0.0f, 1.0f);\n\t\tCVector Right = CrossProduct(Front, Up);\n\t\tRight.Normalise();\n\t\tFront = TargetPos - CamSource + Right*ARRESTCAM_LAMPPOST_ROTATEDIST;\n\t\tFront.z = 0.0f;\n\t\tFront.Normalise();\n\t\tif(CWorld::TestSphereAgainstWorld(CamSource + 0.5f*Front, 0.4f, TheCamera.pTargetEntity, true, true, false, true, false, true) == nil){\n\t\t\tfoundPos = true;\n\t\t\tCamSource += Front*ARRESTCAM_LAMPPOST_TRANSLATE*CTimer::GetTimeStep();\n\t\t}\n\t}\n\n\tif(foundPos){\n\t\tSource = CamSource;\n\t\tCVector OrigSource = Source;\n\t\tTheCamera.AvoidTheGeometry(OrigSource, TargetPos, Source, FOV);\n\t\tFront = TargetPos - Source;\n\t\tFront.Normalise();\n\t\tUp = CVector(0.0f, 0.0f, 1.0f);\n\t\tCVector Right = CrossProduct(Front, Up);\n\t\tRight.Normalise();\n\t\tUp = CrossProduct(Right, Front);\n\t}else{\n\t\tCVector OrigSource = Source;\n\t\tTheCamera.AvoidTheGeometry(OrigSource, TargetPos, Source, FOV);\n\t}\n\n\treturn true;\n}\n\nbool\nCCam::ProcessArrestCamTwo(void)\n{\n\tCPed *player = CWorld::Players[CWorld::PlayerInFocus].m_pPed;\n\tif(!ResetStatics)\n\t\treturn true;\n\tResetStatics = false;\n\n\tCVector TargetCoors, ToCamera;\n\tfloat BetaOffset;\n\tfloat SourceX, SourceY;\n\tif(&TheCamera.Cams[TheCamera.ActiveCam] == this){\n\t\tSourceX = TheCamera.Cams[(TheCamera.ActiveCam + 1) % 2].Source.x;\n\t\tSourceY = TheCamera.Cams[(TheCamera.ActiveCam + 1) % 2].Source.y;\n\t}else{\n\t\tSourceX = TheCamera.Cams[TheCamera.ActiveCam].Source.x;\n\t\tSourceY = TheCamera.Cams[TheCamera.ActiveCam].Source.y;\n\t}\n\n\tfor(int i = 0; i <= 1; i++){\n\t\tint Dir = i == 0 ? 1 : -1;\n\n\t\tFOV = 60.0f;\n\t\tTargetCoors = player->GetPosition();\n\t\tBeta = CGeneral::GetATanOfXY(TargetCoors.x-SourceX, TargetCoors.y-SourceY);\n\t\tBetaOffset = DEGTORAD(Dir*80);\n\t\tSource = TargetCoors + 11.5f*CVector(Cos(Beta+BetaOffset), Sin(Beta+BetaOffset), 0.0f);\n\n\t\tToCamera = Source - TargetCoors;\n\t\tToCamera.Normalise();\n\t\tTargetCoors.x += 0.4f*ToCamera.x;\n\t\tTargetCoors.y += 0.4f*ToCamera.y;\n\t\tif(CWorld::GetIsLineOfSightClear(Source, TargetCoors, true, true, false, true, false, true, true)){\n\t\t\tSource.z += 5.5f;\n\t\t\tTargetCoors += CVector(-0.8f*ToCamera.x, -0.8f*ToCamera.y, 2.2f);\n\t\t\tm_cvecTargetCoorsForFudgeInter = TargetCoors;\n\t\t\tFront = TargetCoors - Source;\n\t\t\tResetStatics = false;\n\t\t\tGetVectorsReadyForRW();\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n\n\n#ifdef FREE_CAM\nvoid\nCCam::Process_FollowPed_Rotation(const CVector &CameraTarget, float TargetOrientation, float, float)\n{\n\tFOV = DefaultFOV;\n\n\tconst float MinDist = 2.0f;\n\tconst float MaxDist = 2.0f + TheCamera.m_fPedZoomValueSmooth;\n\tconst float BaseOffset = 0.75f;\t// base height of camera above target\n\n\tCVector TargetCoors = CameraTarget;\n\n\tTargetCoors.z += m_fSyphonModeTargetZOffSet;\n\tTargetCoors = DoAverageOnVector(TargetCoors);\n\tTargetCoors.z += BaseOffset;\t// add offset so alpha evens out to 0\n//\tTargetCoors.z += m_fRoadOffSet;\n\n\tCVector Dist = Source - TargetCoors;\n\tCVector ToCam;\n\n\tbool Shooting = false;\n\tif(((CPed*)CamTargetEntity)->GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED)\n\t\tif(CPad::GetPad(0)->GetWeapon())\n\t\t\tShooting = true;\n\tif(((CPed*)CamTargetEntity)->GetWeapon()->m_eWeaponType == WEAPONTYPE_DETONATOR ||\n\t   ((CPed*)CamTargetEntity)->GetWeapon()->m_eWeaponType == WEAPONTYPE_BASEBALLBAT)\n\t\tShooting = false;\n\n\n\tif(ResetStatics){\n\t\t// Coming out of top down here probably\n\t\t// so keep Beta, reset alpha and calculate vectors\n\t\tBeta = CGeneral::GetATanOfXY(Dist.x, Dist.y);\n\t\tAlpha = 0.0f;\n\n\t\tDist = MaxDist*CVector(Cos(Alpha) * Cos(Beta), Cos(Alpha) * Sin(Beta), Sin(Alpha));\n\t\tSource = TargetCoors + Dist;\n\n\t\tResetStatics = false;\n\t}\n\n\t// Drag the camera along at the look-down offset\n\tfloat CamDist = Dist.Magnitude();\n\tif(CamDist == 0.0f)\n\t\tDist = CVector(1.0f, 1.0f, 0.0f);\n\telse if(CamDist < MinDist)\n\t\tDist *= MinDist/CamDist;\n\telse if(CamDist > MaxDist)\n\t\tDist *= MaxDist/CamDist;\n\tCamDist = Dist.Magnitude();\n\n\t// Beta = 0 is looking east, HALFPI is north, &c.\n\t// Alpha positive is looking up\n\tfloat GroundDist = Dist.Magnitude2D();\n\tBeta = CGeneral::GetATanOfXY(-Dist.x, -Dist.y);\n\tAlpha = CGeneral::GetATanOfXY(GroundDist, -Dist.z);\n\twhile(Beta >= PI) Beta -= 2.0f*PI;\n\twhile(Beta < -PI) Beta += 2.0f*PI;\n\twhile(Alpha >= PI) Alpha -= 2.0f*PI;\n\twhile(Alpha < -PI) Alpha += 2.0f*PI;\n\n\t// Look around\n\tbool UseMouse = false;\n\tfloat MouseX = CPad::GetPad(0)->GetMouseX();\n\tfloat MouseY = CPad::GetPad(0)->GetMouseY();\n\tfloat LookLeftRight, LookUpDown;\n/*\n\tif((MouseX != 0.0f || MouseY != 0.0f) && !CPad::GetPad(0)->ArePlayerControlsDisabled()){\n\t\tUseMouse = true;\n\t\tLookLeftRight = -2.5f*MouseX;\n\t\tLookUpDown = 4.0f*MouseY;\n\t}else\n*/\n\t{\n\t\tLookLeftRight = -CPad::GetPad(0)->LookAroundLeftRight();\n\t\tLookUpDown = CPad::GetPad(0)->LookAroundUpDown();\n\t}\n\tfloat AlphaOffset, BetaOffset;\n\tif(UseMouse){\n\t\tBetaOffset = LookLeftRight * TheCamera.m_fMouseAccelHorzntl * FOV/80.0f;\n\t\tAlphaOffset = LookUpDown * TheCamera.m_fMouseAccelVertical * FOV/80.0f;\n\t}else{\n\t\tBetaOffset = LookLeftRight * fStickSens * (1.0f/20.0f) * FOV/80.0f * CTimer::GetTimeStep();\n\t\tAlphaOffset = LookUpDown * fStickSens * (0.6f/20.0f) * FOV/80.0f * CTimer::GetTimeStep();\n\t}\n\n\t// Stop centering once stick has been touched\n\tif(BetaOffset)\n\t\tRotating = false;\n\n\tBeta += BetaOffset;\n\tAlpha += AlphaOffset;\n\twhile(Beta >= PI) Beta -= 2.0f*PI;\n\twhile(Beta < -PI) Beta += 2.0f*PI;\n\tif(Alpha > DEGTORAD(45.0f)) Alpha = DEGTORAD(45.0f);\n\telse if(Alpha < -DEGTORAD(89.5f)) Alpha = -DEGTORAD(89.5f);\n\n\n\tfloat BetaDiff = TargetOrientation+PI - Beta;\n\twhile(BetaDiff >= PI) BetaDiff -= 2.0f*PI;\n\twhile(BetaDiff < -PI) BetaDiff += 2.0f*PI;\n\tfloat TargetAlpha = Alpha;\n\t// 12deg to account for our little height offset. we're not working on the true alpha here\n\tconst float AlphaLimitUp = DEGTORAD(15.0f) + DEGTORAD(12.0f);\n\tconst float AlphaLimitDown = -DEGTORAD(15.0f) + DEGTORAD(12.0f);\n\tif(Abs(BetaDiff) < DEGTORAD(25.0f) && ((CPed*)CamTargetEntity)->GetMoveSpeed().Magnitude2D() > 0.01f){\n\t\t// Limit alpha when player is walking towards camera\n\t\tif(TargetAlpha > AlphaLimitUp) TargetAlpha = AlphaLimitUp;\n\t\tif(TargetAlpha < AlphaLimitDown) TargetAlpha = AlphaLimitDown;\n\t}\n\n\tWellBufferMe(TargetAlpha, &Alpha, &AlphaSpeed, 0.2f, 0.1f, true);\n\n\tif(CPad::GetPad(0)->ForceCameraBehindPlayer() || Shooting){\n\t\tm_fTargetBeta = TargetOrientation;\n\t\tRotating = true;\n\t}\n\n\tif(Rotating){\n\t\tWellBufferMe(m_fTargetBeta, &Beta, &BetaSpeed, 0.1f, 0.06f, true);\n\t\tfloat DeltaBeta = m_fTargetBeta - Beta;\n\t\twhile(DeltaBeta >= PI) DeltaBeta -= 2*PI;\n\t\twhile(DeltaBeta < -PI) DeltaBeta += 2*PI;\n\t\tif(Abs(DeltaBeta) < 0.06f)\n\t\t\tRotating = false;\n\t}\n\n\tif(TheCamera.m_bUseTransitionBeta)\n\t\tBeta = CGeneral::GetATanOfXY(-Cos(m_fTransitionBeta), -Sin(m_fTransitionBeta));\n\n\tif(TheCamera.m_bUseTransitionBeta)\n\t\tBeta = CGeneral::GetATanOfXY(-Cos(m_fTransitionBeta), -Sin(m_fTransitionBeta));\n\n\tFront = CVector(Cos(Alpha) * Cos(Beta), Cos(Alpha) * Sin(Beta), Sin(Alpha));\n\tSource = TargetCoors - Front*CamDist;\n\tTargetCoors.z -= BaseOffset;\t// now get back to the real target coors again\n\n\tm_cvecTargetCoorsForFudgeInter = TargetCoors;\n\n\n\tFront = TargetCoors - Source;\n\tFront.Normalise();\n\n\n\n\t/*\n\t * Handle collisions - taken from FollowPedWithMouse\n\t */\n\n\tCEntity *entity;\n\tCColPoint colPoint;\n\t// Clip Source and fix near clip\n\tCWorld::pIgnoreEntity = CamTargetEntity;\n\tentity = nil;\n\tif(CWorld::ProcessLineOfSight(TargetCoors, Source, colPoint, entity, true, true, true, true, false, false, true)){\n\t\tfloat PedColDist = (TargetCoors - colPoint.point).Magnitude();\n\t\tfloat ColCamDist = CamDist - PedColDist;\n\t\tif(entity->IsPed() && ColCamDist > DEFAULT_NEAR + 0.1f){\n\t\t\t// Ped in the way but not clipping through\n\t\t\tif(CWorld::ProcessLineOfSight(colPoint.point, Source, colPoint, entity, true, true, true, true, false, false, true)){\n\t\t\t\tPedColDist = (TargetCoors - colPoint.point).Magnitude();\n\t\t\t\tSource = colPoint.point;\n\t\t\t\tif(PedColDist < DEFAULT_NEAR + 0.3f)\n\t\t\t\t\tRwCameraSetNearClipPlane(Scene.camera, Max(PedColDist-0.3f, 0.05f));\n\t\t\t}else{\n\t\t\t\tRwCameraSetNearClipPlane(Scene.camera, Min(ColCamDist-0.35f, DEFAULT_NEAR));\n\t\t\t}\n\t\t}else{\n\t\t\tSource = colPoint.point;\n\t\t\tif(PedColDist < DEFAULT_NEAR + 0.3f)\n\t\t\t\tRwCameraSetNearClipPlane(Scene.camera, Max(PedColDist-0.3f, 0.05f));\n\t\t}\n\t}\n\tCWorld::pIgnoreEntity = nil;\n\n\tfloat ViewPlaneHeight = Tan(DEGTORAD(FOV) / 2.0f);\n\tfloat ViewPlaneWidth = ViewPlaneHeight * CDraw::CalculateAspectRatio() * fTweakFOV;\n\tfloat Near = RwCameraGetNearClipPlane(Scene.camera);\n\tfloat radius = ViewPlaneWidth*Near;\n\tentity = CWorld::TestSphereAgainstWorld(Source + Front*Near, radius, nil, true, true, false, true, false, false);\n\tint i = 0;\n\twhile(entity){\n\t\tCVector CamToCol = gaTempSphereColPoints[0].point - Source;\n\t\tfloat frontDist = DotProduct(CamToCol, Front);\n\t\tfloat dist = (CamToCol - Front*frontDist).Magnitude() / ViewPlaneWidth;\n\n\t\t// Try to decrease near clip\n\t\tdist = Max(Min(Near, dist), 0.1f);\n\t\tif(dist < Near)\n\t\t\tRwCameraSetNearClipPlane(Scene.camera, dist);\n\n\t\t// Move forward a bit\n\t\tif(dist == 0.1f)\n\t\t\tSource += (TargetCoors - Source)*0.3f;\n\n\t\t// Keep testing\n\t\tNear = RwCameraGetNearClipPlane(Scene.camera);\n\t\tradius = ViewPlaneWidth*Near;\n\t\tentity = CWorld::TestSphereAgainstWorld(Source + Front*Near, radius, nil, true, true, false, true, false, false);\n\n\t\ti++;\n\t\tif(i > 5)\n\t\t\tentity = nil;\n\t}\n\n\tGetVectorsReadyForRW();\n}\n\n// LCS cam hehe\nvoid\nCCam::Process_FollowCar_SA(const CVector& CameraTarget, float TargetOrientation, float, float)\n{\n\t// Missing things on III CCam\n\tstatic CVector m_aTargetHistoryPosOne;\n\tstatic CVector m_aTargetHistoryPosTwo;\n\tstatic CVector m_aTargetHistoryPosThree;\n\tstatic int m_nCurrentHistoryPoints = 0;\n\tstatic float lastBeta = -9999.0f;\n\tstatic float lastAlpha = -9999.0f;\n\tstatic float stepsLeftToChangeBetaByMouse;\n\tstatic float dontCollideWithCars;\n\tstatic bool alphaCorrected;\n\tstatic float heightIncreaseMult;\n\n\tif (!CamTargetEntity->IsVehicle())\n\t\treturn;\n\n\tCVehicle* car = (CVehicle*)CamTargetEntity;\n\tCVector TargetCoors = CameraTarget;\n\tuint8 camSetArrPos = 0;\n\n\t// We may need those later\n\tbool isPlane = car->GetVehicleAppearance() == VEHICLE_APPEARANCE_PLANE;\n\tbool isHeli = car->GetVehicleAppearance() == VEHICLE_APPEARANCE_HELI;\n\tbool isBike = car->GetVehicleAppearance() == VEHICLE_APPEARANCE_BIKE;\n\tbool isCar = car->IsCar() && !isPlane && !isHeli && !isBike;\n\n\tCPad* pad = CPad::GetPad(0);\n\n\t// Next direction is non-existent in III\n\tuint8 nextDirectionIsForward = !(pad->GetLookBehindForCar() || pad->GetLookBehindForPed() || pad->GetLookLeft() || pad->GetLookRight()) &&\n\t\tDirectionWasLooking == LOOKING_FORWARD;\n\n\tif (car->GetModelIndex() == MI_FIRETRUCK) {\n\t\tcamSetArrPos = 7;\n\t} else if (car->GetModelIndex() == MI_RCBANDIT || car->GetModelIndex() == MI_RCBARON) {\n\t\tcamSetArrPos = 5;\n\t} else if (car->GetModelIndex() == MI_RCGOBLIN || car->GetModelIndex() == MI_RCRAIDER) {\n\t\tcamSetArrPos = 6;\n\t} else if (car->IsBoat()) {\n\t\tcamSetArrPos = 4;\n\t} else if (isBike) {\n\t\tcamSetArrPos = 1;\n\t} else if (isPlane) {\n\t\tcamSetArrPos = 3;\n\t} else if (isHeli) {\n\t\tcamSetArrPos = 2;\n\t}\n\n\t// LCS one but index 1(firetruck) moved to last\n\tfloat CARCAM_SET[][15] = {\n\t\t{1.3f, 1.0f, 0.4f, 10.0f, 15.0f, 0.5f, 1.0f, 1.0f, 0.85f, 0.2f, 0.075f, 0.05f, 0.8f, DEGTORAD(45.0f), DEGTORAD(89.0f)}, // cars\n\t\t{1.1f, 1.0f, 0.1f, 10.0f, 11.0f, 0.5f, 1.0f, 1.0f, 0.85f, 0.2f, 0.075f, 0.05f, 0.75f, DEGTORAD(45.0f), DEGTORAD(89.0f)}, // bike\n\t\t{1.1f, 1.0f, 0.2f, 10.0f, 15.0f, 0.05f, 0.05f, 0.0f, 0.9f, 0.05f, 0.01f, 0.05f, 1.0f, DEGTORAD(10.0f), DEGTORAD(70.0f)}, // heli (SA values)\n\t\t{1.1f, 3.5f, 0.2f, 10.0f, 25.0f, 0.5f, 1.0f, 1.0f, 0.75f, 0.1f, 0.005f, 0.2f, 1.0f, DEGTORAD(89.0f), DEGTORAD(89.0f)}, // plane (SA values)\n\t\t{0.9f, 1.0f, 0.1f, 10.0f, 15.0f, 0.5f, 1.0f, 0.0f, 0.9f, 0.05f, 0.005f, 0.05f, 1.0f, -0.2f, DEGTORAD(70.0f)}, // boat\n\t\t{1.1f, 1.0f, 0.2f, 10.0f, 5.0f, 0.5f, 1.0f, 1.0f, 0.75f, 0.1f, 0.005f, 0.2f, 1.0f, DEGTORAD(45.0f), DEGTORAD(89.0f)}, // rc cars\n\t\t{1.1f, 1.0f, 0.2f, 10.0f, 5.0f, 0.5f, 1.0f, 1.0f, 0.75f, 0.1f, 0.005f, 0.2f, 1.0f, DEGTORAD(20.0f), DEGTORAD(70.0f)}, // rc heli/planes\n\t\t{1.3f, 1.0f, 0.4f, 10.0f, 15.0f, 0.5f, 1.0f, 1.0f, 0.85f, 0.2f, 0.075f, 0.05f, 0.8f, -0.18f, DEGTORAD(40.0f)}, // firetruck...\n\t};\n\n\t// RC Heli/planes use same alpha values with heli/planes (LCS firetruck will fallback to 0)\n\tuint8 alphaArrPos = (camSetArrPos > 4 ? (isPlane ? 3 : (isHeli ? 2 : 0)) : camSetArrPos);\n\tfloat zoomModeAlphaOffset = 0.0f;\n\tstatic float ZmOneAlphaOffsetLCS[] = { 0.12f, 0.08f, 0.15f, 0.08f, 0.08f };\n\tstatic float ZmTwoAlphaOffsetLCS[] = { 0.1f, 0.08f, 0.3f, 0.08f, 0.08f };\n\tstatic float ZmThreeAlphaOffsetLCS[] = { 0.065f, 0.05f, 0.15f, 0.06f, 0.08f };\n\n\tif (isHeli && car->GetStatus() == STATUS_PLAYER_REMOTE)\n\t\tzoomModeAlphaOffset = ZmTwoAlphaOffsetLCS[alphaArrPos];\n\telse {\n\t\tswitch ((int)TheCamera.CarZoomIndicator) {\n\t\t\t// near\n\t\tcase CAM_ZOOM_1:\n\t\t\tzoomModeAlphaOffset = ZmOneAlphaOffsetLCS[alphaArrPos];\n\t\t\tbreak;\n\t\t\t// mid\n\t\tcase CAM_ZOOM_2:\n\t\t\tzoomModeAlphaOffset = ZmTwoAlphaOffsetLCS[alphaArrPos];\n\t\t\tbreak;\n\t\t\t// far\n\t\tcase CAM_ZOOM_3:\n\t\t\tzoomModeAlphaOffset = ZmThreeAlphaOffsetLCS[alphaArrPos];\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tCColModel* carCol = (CColModel*)car->GetColModel();\n\tfloat colMaxZ = carCol->boundingBox.max.z;  // As opposed to LCS and SA, VC does this: carCol->boundingBox.max.z - carCol->boundingBox.min.z;\n\tfloat approxCarLength = 2.0f * Abs(carCol->boundingBox.min.y); // SA taxi min.y = -2.95, max.z = 0.883502f\n\n\tfloat newDistance = TheCamera.CarZoomValueSmooth + CARCAM_SET[camSetArrPos][1] + approxCarLength;\n\n\t// Taken from VC CCam::Cam_On_A_String_Unobscured. If we don't this, we will end up seeing the world from the inside of RC Goblin/Raider.\n\t// I couldn't find where SA does that. It's possible that they've increased the size of these veh.'s collision bounding box.\n\n\tif (car->m_modelIndex == MI_RCRAIDER || car->m_modelIndex == MI_RCGOBLIN)\n\t\tnewDistance += INIT_RC_HELI_HORI_EXTRA;\n\telse if (car->m_modelIndex == MI_RCBARON)\n\t\tnewDistance += INIT_RC_PLANE_HORI_EXTRA;\n\n\tfloat minDistForThisCar = approxCarLength * CARCAM_SET[camSetArrPos][3];\n\n\tif (!isHeli || car->GetStatus() == STATUS_PLAYER_REMOTE) {\n\t\tfloat radiusToStayOutside = colMaxZ * CARCAM_SET[camSetArrPos][0] - CARCAM_SET[camSetArrPos][2];\n\t\tif (radiusToStayOutside > 0.0f) {\n\t\t\tTargetCoors.z += radiusToStayOutside;\n\t\t\tnewDistance += radiusToStayOutside;\n\t\t\tzoomModeAlphaOffset += 0.3f / newDistance * radiusToStayOutside;\n\t\t}\n\t} else {\n\t\t// 0.6f = fTestShiftHeliCamTarget\n\t\tTargetCoors += 0.6f * car->GetUp() * colMaxZ;\n\t}\n\n\tif (car->m_modelIndex == MI_RCGOBLIN)\n\t\tzoomModeAlphaOffset += 0.178997f;\n\n\tfloat minDistForVehType = CARCAM_SET[camSetArrPos][4];\n\n\tif (TheCamera.CarZoomIndicator == CAM_ZOOM_1 && (camSetArrPos < 2 || camSetArrPos == 7)) {\n\t\tminDistForVehType = minDistForVehType * 0.65f;\n\t}\n\n\tfloat nextDistance = Max(newDistance, minDistForVehType);\n\n\tCA_MAX_DISTANCE = newDistance;\n\tCA_MIN_DISTANCE = 3.5f;\n\n\tif (ResetStatics) {\n\t\tFOV = DefaultFOV;\n\t} else {\n\t\tif (isCar || isBike) {\n\t\t\t// 0.4f: CAR_FOV_START_SPEED\n\t\t\tif (DotProduct(car->GetForward(), car->m_vecMoveSpeed) > 0.4f)\n\t\t\t\tFOV += (DotProduct(car->GetForward(), car->m_vecMoveSpeed) - 0.4f) * CTimer::GetTimeStep();\n\t\t}\n\n\t\tif (FOV > DefaultFOV)\n\t\t\t// 0.98f: CAR_FOV_FADE_MULT\n\t\t\tFOV = Pow(0.98f, CTimer::GetTimeStep()) * (FOV - DefaultFOV) + DefaultFOV;\n\n\t\tFOV = clamp(FOV, DefaultFOV, DefaultFOV + 30.0f);\n\t}\n\n\t// WORKAROUND: I still don't know how looking behind works (m_bCamDirectlyInFront is unused in III, they seem to use m_bUseTransitionBeta)\n\tif (pad->GetLookBehindForCar())\n\t\tif (DirectionWasLooking == LOOKING_FORWARD || !LookingBehind)\n\t\t\tTheCamera.m_bCamDirectlyInFront = true;\n\n\t// Taken from RotCamIfInFrontCar, because we don't call it anymore\n\tif (!(pad->GetLookBehindForCar() || pad->GetLookBehindForPed() || pad->GetLookLeft() || pad->GetLookRight()))\n\t\tif (DirectionWasLooking != LOOKING_FORWARD)\n\t\t\tTheCamera.m_bCamDirectlyBehind = true;\n\n\t// Called when we just entered the car, just started to look behind or returned back from looking left, right or behind\n\tif (ResetStatics || TheCamera.m_bCamDirectlyBehind || TheCamera.m_bCamDirectlyInFront) {\n\t\tResetStatics = false;\n\t\tRotating = false;\n\t\tm_bCollisionChecksOn = true;\n\n\t\tif (!TheCamera.m_bJustCameOutOfGarage) {\n\t\t\tAlpha = 0.0f;\n\t\t\tBeta = car->GetForward().Heading() - HALFPI;\n\t\t\tif (TheCamera.m_bCamDirectlyInFront) {\n\t\t\t\tBeta += PI;\n\t\t\t}\n\t\t}\n\n\t\tBetaSpeed = 0.0;\n\t\tAlphaSpeed = 0.0;\n\t\tDistance = 1000.0;\n\n\t\tFront.x = -(cos(Beta) * cos(Alpha));\n\t\tFront.y = -(sin(Beta) * cos(Alpha));\n\t\tFront.z = sin(Alpha);\n\n\t\tm_aTargetHistoryPosOne = TargetCoors - nextDistance * Front;\n\n\t\tm_aTargetHistoryPosTwo = TargetCoors - newDistance * Front;\n\n\t\tm_nCurrentHistoryPoints = 0;\n\t\tif (!TheCamera.m_bJustCameOutOfGarage)\n\t\t\tAlpha = -zoomModeAlphaOffset;\n\t}\n\n\tFront = TargetCoors - m_aTargetHistoryPosOne;\n\tFront.Normalise();\n\n\t// Code that makes cam rotate around the car\n\tfloat camRightHeading = Front.Heading() - HALFPI;\n\tif (camRightHeading < -PI)\n\t\tcamRightHeading = camRightHeading + TWOPI;\n\n\tfloat velocityRightHeading;\n\tif (car->m_vecMoveSpeed.Magnitude2D() <= 0.02f)\n\t\tvelocityRightHeading = camRightHeading;\n\telse\n\t\tvelocityRightHeading = car->m_vecMoveSpeed.Heading() - HALFPI;\n\n\tif (velocityRightHeading < camRightHeading - PI)\n\t\tvelocityRightHeading = velocityRightHeading + TWOPI;\n\telse if (velocityRightHeading > camRightHeading + PI)\n\t\tvelocityRightHeading = velocityRightHeading - TWOPI;\n\n\tfloat betaChangeMult1 = CTimer::GetTimeStep() * CARCAM_SET[camSetArrPos][10];\n\tfloat betaChangeLimit = CTimer::GetTimeStep() * CARCAM_SET[camSetArrPos][11];\n\n\tfloat betaChangeMult2 = (car->m_vecMoveSpeed - DotProduct(car->m_vecMoveSpeed, Front) * Front).Magnitude();\n\n\tfloat betaChange = Min(1.0f, betaChangeMult1 * betaChangeMult2) * (velocityRightHeading - camRightHeading);\n\tif (betaChange <= betaChangeLimit) {\n\t\tif (betaChange < -betaChangeLimit)\n\t\t\tbetaChange = -betaChangeLimit;\n\t} else {\n\t\tbetaChange = betaChangeLimit;\n\t}\n\tfloat targetBeta = camRightHeading + betaChange;\n\n\tif (targetBeta < Beta - HALFPI)\n\t\ttargetBeta += TWOPI;\n\telse if (targetBeta > Beta + PI)\n\t\ttargetBeta -= TWOPI;\n\n\tfloat carPosChange = (TargetCoors - m_aTargetHistoryPosTwo).Magnitude();\n\tif (carPosChange < newDistance && newDistance > minDistForThisCar) {\n\t\tnewDistance = Max(minDistForThisCar, carPosChange);\n\t}\n\tfloat maxAlphaAllowed = CARCAM_SET[camSetArrPos][13];\n\n\t// Originally this is to prevent camera enter into car while we're stopping, but what about moving???\n\t// This is also original LCS and SA bug, or some attempt to fix lag. We'll never know\n\n\t// if (car->m_vecMoveSpeed.MagnitudeSqr() < sq(0.2f))\n\t\tif (car->GetModelIndex() != MI_FIRETRUCK)\n\t\t\tif (!isBike || ((CBike*)car)->m_nWheelsOnGround > 3)\n\t\t\t\tif (!isHeli && (!isPlane || ((CAutomobile*)car)->m_nWheelsOnGround)) {\n\n\t\t\t\t\tCVector left = CrossProduct(car->GetForward(), CVector(0.0f, 0.0f, 1.0f));\n\t\t\t\t\tleft.Normalise();\n\t\t\t\t\tCVector up = CrossProduct(left, car->GetForward());\n\t\t\t\t\tup.Normalise();\n\t\t\t\t\tfloat lookingUp = DotProduct(up, Front);\n\t\t\t\t\tif (lookingUp > 0.0f) {\n\t\t\t\t\t\tfloat v88 = Asin(Abs(Sin(Beta - (car->GetForward().Heading() - HALFPI))));\n\t\t\t\t\t\tfloat v200;\n\t\t\t\t\t\tif (v88 <= Atan2(carCol->boundingBox.max.x, -carCol->boundingBox.min.y)) {\n\t\t\t\t\t\t\tv200 = (1.5f - carCol->boundingBox.min.y) / Cos(v88);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tfloat a6g = 1.2f + carCol->boundingBox.max.x;\n\t\t\t\t\t\t\tv200 = a6g / Cos(Max(0.0f, HALFPI - v88));\n\t\t\t\t\t\t}\n\t\t\t\t\t\tmaxAlphaAllowed = Cos(Beta - (car->GetForward().Heading() - HALFPI)) * Atan2(car->GetForward().z, car->GetForward().Magnitude2D())\n\t\t\t\t\t\t\t+ Atan2(TargetCoors.z - car->GetPosition().z + car->GetHeightAboveRoad(), v200 * 1.2f);\n\n\t\t\t\t\t\tif (isCar && ((CAutomobile*)car)->m_nWheelsOnGround > 1 && Abs(DotProduct(car->m_vecTurnSpeed, car->GetForward())) < 0.05f) {\n\t\t\t\t\t\t\tmaxAlphaAllowed += Cos(Beta - (car->GetForward().Heading() - HALFPI) + HALFPI) * Atan2(car->GetRight().z, car->GetRight().Magnitude2D());\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\tfloat targetAlpha = Asin(clamp(Front.z, -1.0f, 1.0f)) - zoomModeAlphaOffset;\n\tif (targetAlpha <= maxAlphaAllowed) {\n\t\tif (targetAlpha < -CARCAM_SET[camSetArrPos][14])\n\t\t\ttargetAlpha = -CARCAM_SET[camSetArrPos][14];\n\t} else {\n\t\ttargetAlpha = maxAlphaAllowed;\n\t}\n\tfloat maxAlphaBlendAmount = CTimer::GetTimeStep() * CARCAM_SET[camSetArrPos][6];\n\tfloat targetAlphaBlendAmount = (1.0f - Pow(CARCAM_SET[camSetArrPos][5], CTimer::GetTimeStep())) * (targetAlpha - Alpha);\n\tif (targetAlphaBlendAmount <= maxAlphaBlendAmount) {\n\t\tif (targetAlphaBlendAmount < -maxAlphaBlendAmount)\n\t\t\ttargetAlphaBlendAmount = -maxAlphaBlendAmount;\n\t} else {\n\t\ttargetAlphaBlendAmount = maxAlphaBlendAmount;\n\t}\n\n\t// Using GetCarGun(LR/UD) will give us same unprocessed RightStick value as SA\n\tfloat stickX = -(pad->GetCarGunLeftRight());\n\tfloat stickY = -pad->GetCarGunUpDown();\n\n\t// In SA this checks for m_bUseMouse3rdPerson so num2 / num8 do not move camera\n\t// when Keyboard & Mouse controls are used. To make it work better with III/VC, check for actual pad state instead\n\tif (!CPad::IsAffectedByController && !isCar)\n\t\tstickY = 0.0f;\n\telse if (CPad::bInvertLook4Pad)\n\t\tstickY = -stickY;\n\n\tfloat xMovement = Abs(stickX) * (FOV / 80.0f * 5.f / 70.f) * stickX * 0.007f * 0.007f;\n\tfloat yMovement = Abs(stickY) * (FOV / 80.0f * 3.f / 70.f) * stickY * 0.007f * 0.007f;\n\n\tbool correctAlpha = true;\n\t//\tif (SA checks if we aren't in work car, why?) {\n\tif (!isCar || car->GetModelIndex() != MI_VOODOO) {\n\t\tcorrectAlpha = false;\n\t}\n\telse {\n\t\txMovement = 0.0f;\n\t\tyMovement = 0.0f;\n\t}\n\t//\t} else\n\t//\t\tyMovement = 0.0;\n\n\tif (!nextDirectionIsForward) {\n\t\tyMovement = 0.0f;\n\t\txMovement = 0.0f;\n\t}\n\n\tif (camSetArrPos == 0 || camSetArrPos == 7) {\n\t\t// This is not working on cars as SA\n\t\t// Because III/VC doesn't have any buttons tied to LeftStick if you're not in Classic Configuration, using Dodo or using GInput/Pad, so :shrug:\n\t\tif (Abs(pad->GetSteeringUpDown()) > 120.0f) {\n\t\t\tif (car->pDriver && car->pDriver->m_objective != OBJECTIVE_LEAVE_CAR) {\n\t\t\t\tyMovement += Abs(pad->GetSteeringUpDown()) * (FOV / 80.0f * 3.f / 70.f) * pad->GetSteeringUpDown() * 0.007f * 0.007f * 0.5;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (yMovement > 0.0)\n\t\tyMovement = yMovement * 0.5;\n\n\tbool mouseChangesBeta = false;\n\n\t// FIX: Disable mouse movement in drive-by, it's buggy. Original SA bug.\n\tif (/*bFreeMouseCam &&*/ CCamera::m_bUseMouse3rdPerson && !pad->ArePlayerControlsDisabled() && nextDirectionIsForward) {\n\t\tfloat mouseY = pad->GetMouseY() * 2.0f;\n\t\tfloat mouseX = pad->GetMouseX() * -2.0f;\n\n\t\t// If you want an ability to toggle free cam while steering with mouse, you can add an OR after DisableMouseSteering.\n\t\t// There was a pad->NewState.m_bVehicleMouseLook in SA, which doesn't exists in III.\n\n\t\tif ((mouseX != 0.0 || mouseY != 0.0) && (CVehicle::m_bDisableMouseSteering)) {\n\t\t\tyMovement = mouseY * FOV / 80.0f * TheCamera.m_fMouseAccelHorzntl; // Same as SA, horizontal sensitivity.\n\t\t\tBetaSpeed = 0.0;\n\t\t\tAlphaSpeed = 0.0;\n\t\t\txMovement = mouseX * FOV / 80.0f * TheCamera.m_fMouseAccelHorzntl;\n\t\t\ttargetAlpha = Alpha;\n\t\t\tstepsLeftToChangeBetaByMouse = 1.0f * 50.0f;\n\t\t\tmouseChangesBeta = true;\n\t\t} else if (stepsLeftToChangeBetaByMouse > 0.0f) {\n\t\t\t// Finish rotation by decreasing speed when we stopped moving mouse\n\t\t\tBetaSpeed = 0.0;\n\t\t\tAlphaSpeed = 0.0;\n\t\t\tyMovement = 0.0;\n\t\t\txMovement = 0.0;\n\t\t\ttargetAlpha = Alpha;\n\t\t\tstepsLeftToChangeBetaByMouse = Max(0.0f, stepsLeftToChangeBetaByMouse - CTimer::GetTimeStep());\n\t\t\tmouseChangesBeta = true;\n\t\t}\n\t}\n\n\tif (correctAlpha) {\n\t\tif (nPreviousMode != MODE_CAM_ON_A_STRING)\n\t\t\talphaCorrected = false;\n\n\t\tif (!alphaCorrected && Abs(zoomModeAlphaOffset + Alpha) > 0.05f) {\n\t\t\tyMovement = (-zoomModeAlphaOffset - Alpha) * 0.05f;\n\t\t} else\n\t\t\talphaCorrected = true;\n\t}\n\tfloat alphaSpeedFromStickY = yMovement * CARCAM_SET[camSetArrPos][12];\n\tfloat betaSpeedFromStickX = xMovement * CARCAM_SET[camSetArrPos][12];\n\n\tfloat newAngleSpeedMaxBlendAmount = CARCAM_SET[camSetArrPos][9];\n\tfloat angleChangeStep = Pow(CARCAM_SET[camSetArrPos][8], CTimer::GetTimeStep());\n\tfloat targetBetaWithStickBlendAmount = betaSpeedFromStickX + (targetBeta - Beta) / Max(CTimer::GetTimeStep(), 1.0f);\n\n\tif (targetBetaWithStickBlendAmount < -newAngleSpeedMaxBlendAmount)\n\t\ttargetBetaWithStickBlendAmount = -newAngleSpeedMaxBlendAmount;\n\telse if (targetBetaWithStickBlendAmount > newAngleSpeedMaxBlendAmount)\n\t\ttargetBetaWithStickBlendAmount = newAngleSpeedMaxBlendAmount;\n\n\tfloat angleChangeStepLeft = 1.0f - angleChangeStep;\n\tBetaSpeed = targetBetaWithStickBlendAmount * angleChangeStepLeft + angleChangeStep * BetaSpeed;\n\tif (Abs(BetaSpeed) < 0.0001f)\n\t\tBetaSpeed = 0.0f;\n\n\tfloat betaChangePerFrame;\n\tif (mouseChangesBeta)\n\t\tbetaChangePerFrame = betaSpeedFromStickX;\n\telse\n\t\tbetaChangePerFrame = CTimer::GetTimeStep() * BetaSpeed;\n\tBeta = betaChangePerFrame + Beta;\n\n\tif (TheCamera.m_bJustCameOutOfGarage) {\n\t\tfloat invHeading = Atan2(Front.y, Front.x);\n\t\tif (invHeading < 0.0f)\n\t\t\tinvHeading += TWOPI;\n\n\t\tBeta = invHeading + PI;\n\t}\n\n\tBeta = CGeneral::LimitRadianAngle(Beta);\n\tif (Beta < 0.0f)\n\t\tBeta += TWOPI;\n\n\tif ((camSetArrPos <= 1 || camSetArrPos == 7) && targetAlpha < Alpha && carPosChange >= newDistance) {\n\t\tif (isCar && ((CAutomobile*)car)->m_nWheelsOnGround > 1 ||\n\t\t\tisBike && ((CBike*)car)->m_nWheelsOnGround > 1)\n\t\t\talphaSpeedFromStickY += (targetAlpha - Alpha) * 0.075f;\n\t}\n\n\tAlphaSpeed = angleChangeStepLeft * alphaSpeedFromStickY + angleChangeStep * AlphaSpeed;\n\tfloat maxAlphaSpeed = newAngleSpeedMaxBlendAmount;\n\tif (alphaSpeedFromStickY > 0.0f)\n\t\tmaxAlphaSpeed = maxAlphaSpeed * 0.5;\n\n\tif (AlphaSpeed <= maxAlphaSpeed) {\n\t\tfloat minAlphaSpeed = -maxAlphaSpeed;\n\t\tif (AlphaSpeed < minAlphaSpeed)\n\t\t\tAlphaSpeed = minAlphaSpeed;\n\t} else {\n\t\tAlphaSpeed = maxAlphaSpeed;\n\t}\n\n\tif (Abs(AlphaSpeed) < 0.0001f)\n\t\tAlphaSpeed = 0.0f;\n\n\t\tfloat alphaWithSpeedAccounted;\n\t\tif (mouseChangesBeta) {\n\t\t\talphaWithSpeedAccounted = alphaSpeedFromStickY + targetAlpha;\n\t\t\t\tAlpha += alphaSpeedFromStickY;\n\t\t} else {\n\t\t\talphaWithSpeedAccounted = CTimer::GetTimeStep() * AlphaSpeed + targetAlpha;\n\t\t\tAlpha += targetAlphaBlendAmount;\n\t\t}\n\n\tif (Alpha <= maxAlphaAllowed) {\n\t\tfloat minAlphaAllowed = -CARCAM_SET[camSetArrPos][14];\n\t\tif (minAlphaAllowed > Alpha) {\n\t\t\tAlpha = minAlphaAllowed;\n\t\t\tAlphaSpeed = 0.0f;\n\t\t}\n\t} else {\n\t\tAlpha = maxAlphaAllowed;\n\t\tAlphaSpeed = 0.0f;\n\t}\n\n\t// Prevent unsignificant angle changes\n\tif (Abs(lastAlpha - Alpha) < 0.0001f)\n\t\tAlpha = lastAlpha;\n\n\tlastAlpha = Alpha;\n\n\tif (Abs(lastBeta - Beta) < 0.0001f)\n\t\tBeta = lastBeta;\n\n\tlastBeta = Beta;\n\n\tFront.x = -(cos(Beta) * cos(Alpha));\n\tFront.y = -(sin(Beta) * cos(Alpha));\n\tFront.z = sin(Alpha);\n\tGetVectorsReadyForRW();\n\tTheCamera.m_bCamDirectlyBehind = false;\n\tTheCamera.m_bCamDirectlyInFront = false;\n\n\tSource = TargetCoors - newDistance * Front;\n\n\tm_cvecTargetCoorsForFudgeInter = TargetCoors;\n\tm_aTargetHistoryPosThree = m_aTargetHistoryPosOne;\n\tfloat nextAlpha = alphaWithSpeedAccounted + zoomModeAlphaOffset;\n\tfloat nextFrontX = -(cos(Beta) * cos(nextAlpha));\n\tfloat nextFrontY = -(sin(Beta) * cos(nextAlpha));\n\tfloat nextFrontZ = sin(nextAlpha);\n\n\tm_aTargetHistoryPosOne.x = TargetCoors.x - nextFrontX * nextDistance;\n\tm_aTargetHistoryPosOne.y = TargetCoors.y - nextFrontY * nextDistance;\n\tm_aTargetHistoryPosOne.z = TargetCoors.z - nextFrontZ * nextDistance;\n\n\tm_aTargetHistoryPosTwo.x = TargetCoors.x - nextFrontX * newDistance;\n\tm_aTargetHistoryPosTwo.y = TargetCoors.y - nextFrontY * newDistance;\n\tm_aTargetHistoryPosTwo.z = TargetCoors.z - nextFrontZ * newDistance;\n\n\t// SA calls SetColVarsVehicle in here\n\tif (nextDirectionIsForward) {\n\n\t\t// LCS uses exactly the same collision code as FollowPedWithMouse, so we will do so.\n\n\t\t// This is only in LCS!\n\t\tfloat timestepFactor = Pow(0.99f, CTimer::GetTimeStep());\n\t\tdontCollideWithCars = (timestepFactor * dontCollideWithCars) + ((1.0f - timestepFactor) * car->m_vecMoveSpeed.Magnitude());\n\n\t\t// Our addition\n#define IS_TRAFFIC_LIGHT(ent) (ent->IsObject() && IsLightObject(ent->GetModelIndex()))\n\n\t\t// Clip Source and fix near clip\n\t\tCColPoint colPoint;\n\t\tCEntity* entity;\n\t\tCWorld::pIgnoreEntity = CamTargetEntity;\n\t\tif(CWorld::ProcessLineOfSight(TargetCoors, Source, colPoint, entity, true, dontCollideWithCars < 0.1f, false, true, false, true, true) && !IS_TRAFFIC_LIGHT(entity)){\n\t\t\tfloat PedColDist = (TargetCoors - colPoint.point).Magnitude();\n\t\t\tfloat ColCamDist = newDistance - PedColDist;\n\t\t\tif(entity->IsPed() && ColCamDist > DEFAULT_NEAR + 0.1f){\n\t\t\t\t// Ped in the way but not clipping through\n\t\t\t\tif(CWorld::ProcessLineOfSight(colPoint.point, Source, colPoint, entity, true, dontCollideWithCars < 0.1f, false, true, false, true, true) || IS_TRAFFIC_LIGHT(entity)){\n\t\t\t\t\tPedColDist = (TargetCoors - colPoint.point).Magnitude();\n\t\t\t\t\tSource = colPoint.point;\n\t\t\t\t\tif(PedColDist < DEFAULT_NEAR + 0.3f)\n\t\t\t\t\t\tRwCameraSetNearClipPlane(Scene.camera, Max(PedColDist-0.3f, 0.05f));\n\t\t\t\t}else{\n\t\t\t\t\tRwCameraSetNearClipPlane(Scene.camera, Min(ColCamDist-0.35f, DEFAULT_NEAR));\n\t\t\t\t}\n\t\t\t}else{\n\t\t\t\tSource = colPoint.point;\n\t\t\t\tif(PedColDist < DEFAULT_NEAR + 0.3f)\n\t\t\t\t\tRwCameraSetNearClipPlane(Scene.camera, Max(PedColDist-0.3f, 0.05f));\n\t\t\t}\n\t\t}\n\t\t\n\t\tCWorld::pIgnoreEntity = nil;\n\n\t\t// If we're seeing blue hell due to camera intersects some surface, fix it.\n\t\t// SA and LCS have this unrolled.\n\n\t\tfloat ViewPlaneHeight = Tan(DEGTORAD(FOV) / 2.0f);\n\t\tfloat ViewPlaneWidth = ViewPlaneHeight * CDraw::CalculateAspectRatio() * fTweakFOV;\n\t\tfloat Near = RwCameraGetNearClipPlane(Scene.camera);\n\t\tfloat radius = ViewPlaneWidth*Near;\n\t\tentity = CWorld::TestSphereAgainstWorld(Source + Front*Near, radius, nil, true, true, false, true, false, true);\n\t\tint i = 0;\n\t\twhile(entity){\n\n\t\t\tif (IS_TRAFFIC_LIGHT(entity))\n\t\t\t\tbreak;\n\n\t\t\tCVector CamToCol = gaTempSphereColPoints[0].point - Source;\n\t\t\tfloat frontDist = DotProduct(CamToCol, Front);\n\t\t\tfloat dist = (CamToCol - Front*frontDist).Magnitude() / ViewPlaneWidth;\n\n\t\t\t// Try to decrease near clip\n\t\t\tdist = Max(Min(Near, dist), 0.1f);\n\t\t\tif(dist < Near)\n\t\t\t\tRwCameraSetNearClipPlane(Scene.camera, dist);\n\n\t\t\t// Move forward a bit\n\t\t\tif(dist == 0.1f)\n\t\t\t\tSource += (TargetCoors - Source)*0.3f;\n\n\t\t\t// Keep testing\n\t\t\tNear = RwCameraGetNearClipPlane(Scene.camera);\n\t\t\tradius = ViewPlaneWidth*Near;\n\t\t\tentity = CWorld::TestSphereAgainstWorld(Source + Front*Near, radius, nil, true, true, false, true, false, true);\n\n\t\t\ti++;\n\t\t\tif(i > 5)\n\t\t\t\tentity = nil;\n\t\t}\n#undef IS_TRAFFIC_LIGHT\n\t}\n\tTheCamera.m_bCamDirectlyBehind = false;\n\tTheCamera.m_bCamDirectlyInFront = false;\n\n\t// ------- LCS specific part starts\n\n\tif (camSetArrPos == 5 && Source.z < 1.0f) // RC Bandit and Baron\n\t\tSource.z = 1.0f;\n\n\t// CCam::FixSourceAboveWaterLevel\n\tif (CameraTarget.z >= -2.0f) {\n\t\tfloat level = -6000.0;\n\n\t\tif (CWaterLevel::GetWaterLevelNoWaves(Source.x, Source.y, Source.z, &level)) {\n\t\t\tif (Source.z < level)\n\t\t\t\tSource.z = level;\n\t\t}\n\t}\n\tFront = TargetCoors - Source;\n\n\t// -------- LCS specific part ends\n\n\tGetVectorsReadyForRW();\n\t// SA\n\t// gTargetCoordsForLookingBehind = TargetCoors;\n\n\t// SA code from CAutomobile::TankControl/FireTruckControl.\n\tif (car->GetModelIndex() == MI_RHINO || car->GetModelIndex() == MI_FIRETRUCK) {\n\n\t\tfloat &carGunLR = ((CAutomobile*)car)->m_fCarGunLR;\n\t\tCVector hi = Multiply3x3(Front, car->GetMatrix());\n\n\t\t// III/VC's firetruck turret angle is reversed\n\t\tfloat angleToFace = (car->GetModelIndex() == MI_FIRETRUCK ? -hi.Heading() : hi.Heading());\n\n\t\tif (angleToFace <= carGunLR + PI) {\n\t\t\tif (angleToFace < carGunLR - PI)\n\t\t\t\tangleToFace = angleToFace + TWOPI;\n\t\t} else {\n\t\t\tangleToFace = angleToFace - TWOPI;\n\t\t}\n\n\t\tfloat neededTurn = angleToFace - carGunLR;\n\t\tfloat turnPerFrame = CTimer::GetTimeStep() * (car->GetModelIndex() == MI_FIRETRUCK ? 0.05f : 0.015f);\n\t\tif (neededTurn <= turnPerFrame) {\n\t\t\tif (neededTurn < -turnPerFrame)\n\t\t\t\tangleToFace = carGunLR - turnPerFrame;\n\t\t} else {\n\t\t\tangleToFace = turnPerFrame + carGunLR;\n\t\t}\n\n\t\tif (car->GetModelIndex() == MI_RHINO && carGunLR != angleToFace) {\n\t\t\tDMAudio.PlayOneShot(car->m_audioEntityId, SOUND_CAR_TANK_TURRET_ROTATE, Abs(angleToFace - carGunLR));\n\t\t}\n\t\tcarGunLR = angleToFace;\n\n\t\tif (carGunLR < -PI) {\n\t\t\tcarGunLR += TWOPI;\n\t\t} else if (carGunLR > PI) {\n\t\t\tcarGunLR -= TWOPI;\n\t\t}\n\n\t\t// Because firetruk turret also has Y movement\n\t\tif (car->GetModelIndex() == MI_FIRETRUCK) {\n\t\t\tfloat &carGunUD = ((CAutomobile*)car)->m_fCarGunUD;\n\n\t\t\tfloat alphaToFace = Atan2(hi.z, hi.Magnitude2D()) + DEGTORAD(15.0f);\n\t\t\tfloat neededAlphaTurn = alphaToFace - carGunUD;\n\t\t\tfloat alphaTurnPerFrame = CTimer::GetTimeStep() * 0.02f;\n\n\t\t\tif (neededAlphaTurn > alphaTurnPerFrame) {\n\t\t\t\tneededTurn = alphaTurnPerFrame;\n\t\t\t\tcarGunUD = neededTurn + carGunUD;\n\t\t\t} else {\n\t\t\t\tif (neededAlphaTurn >= -alphaTurnPerFrame) {\n\t\t\t\t\tcarGunUD = alphaToFace;\n\t\t\t\t} else {\n\t\t\t\t\tcarGunUD = carGunUD - alphaTurnPerFrame;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfloat turretMinY = -DEGTORAD(20.0f);\n\t\t\tfloat turretMaxY = DEGTORAD(20.0f);\n\t\t\tif (turretMinY <= carGunUD) {\n\t\t\t\tif (carGunUD > turretMaxY)\n\t\t\t\t\tcarGunUD = turretMaxY;\n\t\t\t} else {\n\t\t\t\tcarGunUD = turretMinY;\n\t\t\t}\n\t\t}\n\t}\n}\n#endif\n"
  },
  {
    "path": "src/core/Camera.cpp",
    "content": "#include \"common.h\"\n\n#include \"main.h\"\n#include \"Draw.h\"\n#include \"World.h\"\n#include \"Vehicle.h\"\n#include \"Train.h\"\n#include \"Automobile.h\"\n#include \"Ped.h\"\n#include \"PlayerPed.h\"\n#include \"Wanted.h\"\n#include \"Pad.h\"\n#include \"ControllerConfig.h\"\n#include \"General.h\"\n#include \"ZoneCull.h\"\n#include \"SurfaceTable.h\"\n#include \"Particle.h\"\n#include \"WaterLevel.h\"\n#include \"World.h\"\n#include \"Garages.h\"\n#include \"Replay.h\"\n#include \"CutsceneMgr.h\"\n#include \"Renderer.h\"\n#include \"Timecycle.h\"\n#include \"MBlur.h\"\n#include \"Text.h\"\n#include \"Hud.h\"\n#include \"DMAudio.h\"\n#include \"FileMgr.h\"\n#include \"Frontend.h\"\n#include \"SceneEdit.h\"\n#include \"Pools.h\"\n#include \"Debug.h\"\n#include \"GenericGameStorage.h\"\n#include \"Camera.h\"\n\nenum\n{\n\t// car\n\tOBBE_WHEEL,\n\tOBBE_1,\n\tOBBE_2,\n\tOBBE_3,\n\tOBBE_1STPERSON,\t// unused\n\tOBBE_5,\n\tOBBE_ONSTRING,\n\tOBBE_COPCAR,\n\tOBBE_COPCAR_WHEEL,\n\t// ped\n\tOBBE_9,\n\tOBBE_10,\n\tOBBE_11,\n\tOBBE_12,\n\tOBBE_13,\n\t// heli\n\tOBBE_14,\n\tOBBE_15,\n\tOBBE_16,\n\tOBBE_17,\n\tOBBE_18,\n\tOBBE_19,\n\tOBBE_ONSTRING_HELI,\n\n\tOBBE_INVALID\n};\n\n// abbreviate a few things\n#define PLAYER (CWorld::Players[CWorld::PlayerInFocus].m_pPed)\n// NB: removed explicit TheCamera from all functions\n\nCCamera TheCamera;\n#ifdef PC_PLAYER_CONTROLS\nbool CCamera::m_bUseMouse3rdPerson = true;\n#else\nbool CCamera::m_bUseMouse3rdPerson = false;\n#endif\nbool bDidWeProcessAnyCinemaCam;\nstatic bool bSwitchedToObbeCam;\nfloat CCamera::m_fMouseAccelHorzntl;\nfloat CCamera::m_fMouseAccelVertical;\nfloat CCamera::m_f3rdPersonCHairMultX;\nfloat CCamera::m_f3rdPersonCHairMultY;\n\n#ifdef IMPROVED_CAMERA\n#define KEYJUSTDOWN(k) ControlsManager.GetIsKeyboardKeyJustDown((RsKeyCodes)k)\n#define KEYDOWN(k) ControlsManager.GetIsKeyboardKeyDown((RsKeyCodes)k)\n#define CTRLJUSTDOWN(key) \\\n\t       ((KEYDOWN(rsLCTRL) || KEYDOWN(rsRCTRL)) && KEYJUSTDOWN((RsKeyCodes)key) || \\\n\t        (KEYJUSTDOWN(rsLCTRL) || KEYJUSTDOWN(rsRCTRL)) && KEYDOWN((RsKeyCodes)key))\n#define CTRLDOWN(key) ((KEYDOWN(rsLCTRL) || KEYDOWN(rsRCTRL)) && KEYDOWN((RsKeyCodes)key))\n#endif\n\nconst float ZOOM_ONE_DISTANCE[] = { -0.6f, 0.05f, -3.2f, 0.05f, -2.41f };\nconst float ZOOM_TWO_DISTANCE[] = { 1.9f, 1.4f, 0.65f, 1.9f, 6.49f };\nconst float ZOOM_THREE_DISTANCE[] = { 15.9f, 15.9f, 15.9f, 15.9f, 25.25f };\n\n#ifdef FREE_CAM\nconst float LCS_ZOOM_ONE_DISTANCE[] = { -1.0f, -0.2f, -3.2f, 0.05f, -2.41f };\nconst float LCS_ZOOM_TWO_DISTANCE[] = { 2.0f, 2.2f, 1.65f, 2.9f, 6.49f };\nconst float LCS_ZOOM_THREE_DISTANCE[] = { 6.0f, 6.0f, 15.9f, 15.9f, 15.0f };\n#endif\n\nCCamera::CCamera(void)\n{\n\tInit();\n}\n\nvoid\nCCamera::Init(void)\n{\n\tmemset(this, 0, sizeof(CCamera));\t// this is fine, no vtable\n\tm_pRwCamera = nil;\n\tm_bPlayerWasOnBike = false;\n\tm_1rstPersonRunCloseToAWall = false;\n\tm_fPositionAlongSpline = 0.0f;\n\tm_bCameraJustRestored = false;\n\tCams[0].Init();\n\tCams[1].Init();\n\tCams[2].Init();\n\tCams[0].Mode = CCam::MODE_FOLLOWPED;\n\tCams[1].Mode = CCam::MODE_FOLLOWPED;\n\tm_bEnable1rstPersonCamCntrlsScript = false;\n\tm_bAllow1rstPersonWeaponsCamera = false;\n\tm_bVehicleSuspenHigh = false;\n\tCams[0].m_fMinRealGroundDist = 1.85f;\n\t// TODO: what weird value is this?\n\tCams[0].m_fTargetCloseInDist = 2.0837801f - Cams[0].m_fMinRealGroundDist;\n\tCams[0].m_fTargetZoomGroundOne = 0.25f;\n\tCams[0].m_fTargetZoomGroundTwo = 1.5f;\n\tCams[0].m_fTargetZoomGroundThree = 4.0f;\n\tCams[0].m_fTargetZoomOneZExtra = -0.14f;\n\tCams[0].m_fTargetZoomTwoZExtra = 0.16f;\n\tCams[0].m_fTargetZoomThreeZExtra = 0.25f;\n\t// TODO: another weird value\n\tCams[0].m_fTargetZoomZCloseIn = 0.90040702f;\n\tm_bMoveCamToAvoidGeom = false;\n\tClearPlayerWeaponMode();\n\tm_bInATunnelAndABigVehicle = false;\n\tm_iModeObbeCamIsInForCar = OBBE_INVALID;\n\tCams[0].CamTargetEntity = nil;\n\tCams[1].CamTargetEntity = nil;\n\tCams[2].CamTargetEntity = nil;\n\tCams[0].m_fCamBufferedHeight = 0.0f;\n\tCams[0].m_fCamBufferedHeightSpeed = 0.0f;\n\tCams[1].m_fCamBufferedHeight = 0.0f;\n\tCams[1].m_fCamBufferedHeightSpeed = 0.0f;\n\tCams[0].m_bCamLookingAtVector = false;\n\tCams[1].m_bCamLookingAtVector = false;\n\tCams[2].m_bCamLookingAtVector = false;\n\tCams[0].m_fPlayerVelocity = 0.0f;\n\tCams[1].m_fPlayerVelocity = 0.0f;\n\tCams[2].m_fPlayerVelocity = 0.0f;\n\tm_bHeadBob = false;\n\tm_fFractionInterToStopMoving = 0.25f;\n\tm_fFractionInterToStopCatchUp = 0.75f;\n\tm_fGaitSwayBuffer = 0.85f;\n\tm_bScriptParametersSetForInterPol = false;\n\tm_uiCamShakeStart = 0;\n\tm_fCamShakeForce = 0.0f;\n\tm_iModeObbeCamIsInForCar = OBBE_INVALID;\n\tm_bIgnoreFadingStuffForMusic = false;\n\tm_bWaitForInterpolToFinish = false;\n\tpToGarageWeAreIn = nil;\n\tpToGarageWeAreInForHackAvoidFirstPerson = nil;\n\tm_bPlayerIsInGarage = false;\n\tm_bJustCameOutOfGarage = false;\n\tm_fNearClipScript = DEFAULT_NEAR;\n\tm_bUseNearClipScript = false;\n\tm_vecDoingSpecialInterPolation = false;\n\tm_bAboveGroundTrainNodesLoaded = false;\n\tm_bBelowGroundTrainNodesLoaded = false;\n\tm_WideScreenOn = false;\n\tm_fFOV_Wide_Screen = 0.0f;\n\tm_bRestoreByJumpCut = false;\n\tCarZoomIndicator = CAM_ZOOM_2;\n\tPedZoomIndicator = CAM_ZOOM_2;\n\tCarZoomValueSmooth = 0.0f;\n\tm_fPedZoomValueSmooth = 0.0f;\n\tpTargetEntity = nil;\n\tif(FindPlayerVehicle())\n\t\tpTargetEntity = FindPlayerVehicle();\n\telse\n\t\tpTargetEntity = CWorld::Players[CWorld::PlayerInFocus].m_pPed;\n\tm_bInitialNodeFound = false;\n\tm_ScreenReductionPercentage = 0.0f;\n\tm_ScreenReductionSpeed = 0.0f;\n\tm_WideScreenOn = false;\n\tm_bWantsToSwitchWidescreenOff = false;\n\tWorldViewerBeingUsed = false;\n\tPlayerExhaustion = 1.0f;\n\tDebugCamMode = CCam::MODE_NONE;\n\tm_PedOrientForBehindOrInFront = 0.0f;\n\tif(!FrontEndMenuManager.m_bWantToRestart){\n\t\tm_bFading = false;\n\t\tCDraw::FadeValue = 0;\n\t\tm_fFLOATingFade = 0.0f;\n\t\tm_bMusicFading = false;\n\t\tm_fTimeToFadeMusic = 0.0f;\n\t\tm_fFLOATingFadeMusic = 0.0f;\n\t\tm_fMouseAccelVertical = 0.003f;\n\t\tm_fMouseAccelHorzntl = 0.0025f;\n\t}\n\tif(FrontEndMenuManager.m_bWantToRestart)\n\t\tm_fTimeToFadeMusic = 0.0f;\n\tm_bStartingSpline = false;\n\tm_iTypeOfSwitch = INTERPOLATION;\n\tm_bUseScriptZoomValuePed = false;\n\tm_bUseScriptZoomValueCar = false;\n\tm_fPedZoomValueScript = 0.0f;\n\tm_fCarZoomValueScript = 0.0f;\n\tm_bUseSpecialFovTrain = false;\n\tm_fFovForTrain = 70.0f;\t// or DefaultFOV from Cam.cpp\n\tm_iModeToGoTo = CCam::MODE_FOLLOWPED;\n\tm_bJust_Switched = false;\n\tm_bUseTransitionBeta = false;\n\tm_matrix.SetScale(1.0f);\n\tm_bTargetJustBeenOnTrain = false;\n\tm_bInitialNoNodeStaticsSet = false;\n\tm_uiLongestTimeInMill = 5000;\n\tm_uiTimeLastChange = 0;\n\tm_uiTimeWeEnteredIdle = 0;\n\tm_bIdleOn = false;\n\tm_uiTimeWeLeftIdle_StillNoInput = 0;\n\tm_uiTimeWeEnteredIdle = 0;\n\tLODDistMultiplier = 1.0f;\n\tm_bCamDirectlyBehind = false;\n\tm_bCamDirectlyInFront = false;\n\tm_motionBlur = 0;\n\tm_bGarageFixedCamPositionSet = false;\n\tSetMotionBlur(255, 255, 255, 0, 0);\n\tm_bCullZoneChecksOn = false;\n\tm_bFailedCullZoneTestPreviously = false;\n\tm_iCheckCullZoneThisNumFrames = 6;\n\tm_iZoneCullFrameNumWereAt = 0;\n\tm_CameraAverageSpeed = 0.0f;\n\tm_CameraSpeedSoFar = 0.0f;\n\tm_PreviousCameraPosition = CVector(0.0f, 0.0f, 0.0f);\n\tm_iWorkOutSpeedThisNumFrames = 4;\n\tm_iNumFramesSoFar = 0;\n\tm_bJustInitalised = true;\n\tm_uiTransitionState = 0;\n\tm_uiTimeTransitionStart = 0;\n\tm_bLookingAtPlayer = true;\n\tm_f3rdPersonCHairMultX = 0.53f;\n\tm_f3rdPersonCHairMultY = 0.4f;\n\tm_fAvoidTheGeometryProbsTimer = 0.0f;\n\tm_nAvoidTheGeometryProbsDirn = 0;\n}\n\nvoid\nCCamera::Process(void)\n{\n\t// static bool InterpolatorNotInitialised = true;\t// unused\n\tstatic float PlayerMinDist = 1.3f;\n\tstatic bool WasPreviouslyInterSyhonFollowPed = false;\t// only written\n\tfloat FOV = 0.0f;\n\tfloat oldBeta, newBeta;\n\tfloat deltaBeta = 0.0f;\n\tbool lookLRBVehicle = false;\n\tCVector CamFront, CamUp, CamRight, CamSource, Target;\n\n\tm_bJust_Switched = false;\n\tm_RealPreviousCameraPosition = GetPosition();\n\n\t// Update target entity\n\tif(m_bLookingAtPlayer || m_bTargetJustBeenOnTrain || WhoIsInControlOfTheCamera == CAMCONTROL_OBBE)\n\t\tUpdateTargetEntity();\n\tif(pTargetEntity == nil)\n\t\tpTargetEntity = FindPlayerPed();\n\tif(Cams[ActiveCam].CamTargetEntity == nil)\n\t\tCams[ActiveCam].CamTargetEntity = pTargetEntity;\n\tif(Cams[(ActiveCam+1)%2].CamTargetEntity == nil)\n\t\tCams[(ActiveCam+1)%2].CamTargetEntity = pTargetEntity;\n\n\tCamControl();\n\tif(m_bFading)\n\t\tProcessFade();\n\tif(m_bMusicFading)\n\t\tProcessMusicFade();\n\tif(m_WideScreenOn)\n\t\tProcessWideScreenOn();\n\n#ifndef MASTER\n#ifdef IMPROVED_CAMERA\n\tif(CPad::GetPad(1)->GetCircleJustDown() || CTRLJUSTDOWN('B')){\n#else\n\tif(CPad::GetPad(1)->GetCircleJustDown()){\n#endif\n\t\tWorldViewerBeingUsed = !WorldViewerBeingUsed;\n\t\tif(WorldViewerBeingUsed)\n\t\t\tInitialiseCameraForDebugMode();\n\t\telse\n\t\t\tCPad::m_bMapPadOneToPadTwo = false;\n\t}\n#endif\n\n\tRwCameraSetNearClipPlane(Scene.camera, DEFAULT_NEAR);\n\n\tif(Cams[ActiveCam].Front.x == 0.0f && Cams[ActiveCam].Front.y == 0.0f)\n\t\toldBeta = 0.0f;\n\telse\n\t\toldBeta = CGeneral::GetATanOfXY(Cams[ActiveCam].Front.x, Cams[ActiveCam].Front.y);\n\n\tCams[ActiveCam].Process();\n\tCams[ActiveCam].ProcessSpecialHeightRoutines();\n\n\tif(Cams[ActiveCam].Front.x == 0.0f && Cams[ActiveCam].Front.y == 0.0f)\n\t\tnewBeta = 0.0f;\n\telse\n\t\tnewBeta = CGeneral::GetATanOfXY(Cams[ActiveCam].Front.x, Cams[ActiveCam].Front.y);\n\n\n\t// Stop transition when it's done\n\tif(m_uiTransitionState != 0){\n\t\tif(CTimer::GetTimeInMilliseconds() > m_uiTransitionDuration+m_uiTimeTransitionStart){\n\t\t\tm_uiTransitionState = 0;\n\t\t\tm_vecDoingSpecialInterPolation = false;\n\t\t\tm_bWaitForInterpolToFinish = false;\n\t\t}\n\t}\n\n\tif(m_bUseNearClipScript)\n\t\tRwCameraSetNearClipPlane(Scene.camera, m_fNearClipScript);\n\n\tdeltaBeta = newBeta - oldBeta;\n\twhile(deltaBeta >= PI) deltaBeta -= 2*PI;\n\twhile(deltaBeta < -PI) deltaBeta += 2*PI;\n\tif(Abs(deltaBeta) > 0.3f)\n\t\tm_bJust_Switched = true;\n\n#ifndef MASTER\n\t// Debug stuff\n\tif(!gbModelViewer)\n\t\tCams[ActiveCam].PrintMode();\t// actually missing in VC\n\tif(WorldViewerBeingUsed)\n\t\tCams[2].Process();\n#endif\n\n\tif(Cams[ActiveCam].DirectionWasLooking != LOOKING_FORWARD && pTargetEntity->IsVehicle())\n\t\tlookLRBVehicle = true;\n\n\tif(m_uiTransitionState != 0 && !lookLRBVehicle){\n\t\t// Process transition\n\n\t\tuint32 currentTime = CTimer::GetTimeInMilliseconds() - m_uiTimeTransitionStart;\n\t\tif(currentTime >= m_uiTransitionDuration)\n\t\t\tcurrentTime = m_uiTransitionDuration;\n\t\tfloat fractionInter = (float) currentTime / m_uiTransitionDuration;\n\t\tfloat fractionInterTarget = (float) currentTime / m_uiTransitionDurationTargetCoors;\n\t\tfractionInterTarget = clamp(fractionInterTarget, 0.0f, 1.0f);\n\n\t\t// Interpolate target separately\n\t\tif(fractionInterTarget <= m_fFractionInterToStopMovingTarget){\n\t\t\tfloat inter;\n\t\t\tif(m_fFractionInterToStopMovingTarget == 0.0f)\n\t\t\t\tinter = 0.0f;\n\t\t\telse\n\t\t\t\tinter = (m_fFractionInterToStopMovingTarget - fractionInterTarget)/m_fFractionInterToStopMovingTarget;\n\t\t\tinter = 0.5f - 0.5*Cos(inter*PI);\t// smooth it\n\n\t\t\tm_vecTargetWhenInterPol = m_cvecStartingTargetForInterPol + inter*m_cvecTargetSpeedAtStartInter;\n\t\t\tTarget = m_vecTargetWhenInterPol;\n\t\t}else if(fractionInterTarget > m_fFractionInterToStopMovingTarget){\n\t\t\tfloat inter;\n\t\t\tif(m_fFractionInterToStopCatchUpTarget == 0.0f)\n\t\t\t\tinter = 0.0f;\n\t\t\telse\n\t\t\t\tinter = (fractionInterTarget - m_fFractionInterToStopMovingTarget)/m_fFractionInterToStopCatchUpTarget;\n\t\t\tinter = 0.5f - 0.5*Cos(inter*PI);\t// smooth it\n\n\t\t\tif(m_fFractionInterToStopMovingTarget == 0.0f)\n\t\t\t\tm_vecTargetWhenInterPol = m_cvecStartingTargetForInterPol;\n\t\t\tTarget = m_vecTargetWhenInterPol + inter*(Cams[ActiveCam].m_cvecTargetCoorsForFudgeInter - m_vecTargetWhenInterPol);\n\t\t}\n\n\t\tif(fractionInter <= m_fFractionInterToStopMoving){\n\t\t\tfloat inter;\n\t\t\tif(m_fFractionInterToStopMoving == 0.0f)\n\t\t\t\tinter = 0.0f;\n\t\t\telse\n\t\t\t\tinter = (m_fFractionInterToStopMoving - fractionInter)/m_fFractionInterToStopMoving;\n\t\t\tinter = 0.5f - 0.5*Cos(inter*PI);\t// smooth it\n\n\t\t\tm_vecSourceWhenInterPol = m_cvecStartingSourceForInterPol + inter*m_cvecSourceSpeedAtStartInter;\n\n\t\t\tif(m_bLookingAtPlayer){\n\t\t\t\tCVector ToCam = m_vecSourceWhenInterPol - Target;\n\t\t\t\tif(ToCam.Magnitude2D() < PlayerMinDist){\n\t\t\t\t\tfloat beta = CGeneral::GetATanOfXY(ToCam.x, ToCam.y);\n\t\t\t\t\tCamSource.x = Target.x + PlayerMinDist*Cos(beta);\n\t\t\t\t\tCamSource.y = Target.y + PlayerMinDist*Sin(beta);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tm_vecUpWhenInterPol = m_cvecStartingUpForInterPol + inter*m_cvecUpSpeedAtStartInter;\n\t\t\tm_fFOVWhenInterPol = m_fStartingFOVForInterPol + inter*m_fFOVSpeedAtStartInter;\n\n\t\t\tCamSource = m_vecSourceWhenInterPol;\n\t\t\tCamFront = Target - CamSource;\n\t\t\tStoreValuesDuringInterPol(CamSource, m_vecTargetWhenInterPol, m_vecUpWhenInterPol, m_fFOVWhenInterPol);\n\t\t\tCamFront.Normalise();\n\t\t\tif(m_bLookingAtPlayer)\n\t\t\t\tCamUp = CVector(0.0f, 0.0f, 1.0f);\n\t\t\telse\n\t\t\t\tCamUp = m_vecUpWhenInterPol;\n\t\t\tCamUp.Normalise();\n\n\t\t\tif(Cams[ActiveCam].Mode == CCam::MODE_TOPDOWN || Cams[ActiveCam].Mode == CCam::MODE_TOP_DOWN_PED){\n\t\t\t\tCamFront.Normalise();\n\t\t\t\tCamRight = CVector(-1.0f, 0.0f, 0.0f);\n\t\t\t\tCamUp = CrossProduct(CamFront, CamRight);\n\t\t\t\tCamUp.Normalise();\n\t\t\t}else{\n\t\t\t\tCamFront.Normalise();\n\t\t\t\tCamUp.Normalise();\n\t\t\t\tCamRight = CrossProduct(CamFront, CamUp);\n\t\t\t\tCamRight.Normalise();\n\t\t\t\tCamUp = CrossProduct(CamRight, CamFront);\n\t\t\t\tCamUp.Normalise();\n\t\t\t}\n\t\t\tFOV = m_fFOVWhenInterPol;\n\t\t}else if(fractionInter > m_fFractionInterToStopMoving && fractionInter <= 1.0f){\n\t\t\tfloat inter;\n\t\t\tif(m_fFractionInterToStopCatchUp == 0.0f)\n\t\t\t\tinter = 0.0f;\n\t\t\telse\n\t\t\t\tinter = (fractionInter - m_fFractionInterToStopMoving)/m_fFractionInterToStopCatchUp;\n\t\t\tinter = 0.5f - 0.5*Cos(inter*PI);\t// smooth it\n\n\t\t\tCamSource = m_vecSourceWhenInterPol + inter*(Cams[ActiveCam].Source - m_vecSourceWhenInterPol);\n\n\t\t\tif(m_bLookingAtPlayer){\n\t\t\t\tCVector ToCam = m_vecSourceWhenInterPol - Target;\n\t\t\t\tif(ToCam.Magnitude2D() < PlayerMinDist){\n\t\t\t\t\tfloat beta = CGeneral::GetATanOfXY(ToCam.x, ToCam.y);\n\t\t\t\t\tCamSource.x = Target.x + PlayerMinDist*Cos(beta);\n\t\t\t\t\tCamSource.y = Target.y + PlayerMinDist*Sin(beta);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tFOV = m_fFOVWhenInterPol + inter*(Cams[ActiveCam].FOV - m_fFOVWhenInterPol);\n\t\t\tCamUp = m_vecUpWhenInterPol + inter*(Cams[ActiveCam].Up - m_vecUpWhenInterPol);\n\t\t\tdeltaBeta = Cams[ActiveCam].m_fTrueBeta - m_fBetaWhenInterPol;\n\t\t\tMakeAngleLessThan180(deltaBeta);\n\n\t\t\tCamFront = Target - CamSource;\n\t\t\tStoreValuesDuringInterPol(CamSource, Target, CamUp, FOV);\n\t\t\tCamFront.Normalise();\n\t\t\tif(m_bLookingAtPlayer)\n\t\t\t\tCamUp = CVector(0.0f, 0.0f, 1.0f);\n\n\t\t\tif(Cams[ActiveCam].Mode == CCam::MODE_TOPDOWN || Cams[ActiveCam].Mode == CCam::MODE_TOP_DOWN_PED){\n\t\t\t\tCamFront.Normalise();\n\t\t\t\tCamRight = CVector(-1.0f, 0.0f, 0.0f);\n\t\t\t\tCamUp = CrossProduct(CamFront, CamRight);\n\t\t\t\tCamUp.Normalise();\n\t\t\t}else{\n\t\t\t\tCamFront.Normalise();\n\t\t\t\tCamUp.Normalise();\n\t\t\t\tCamRight = CrossProduct(CamFront, CamUp);\n\t\t\t\tCamRight.Normalise();\n\t\t\t\tCamUp = CrossProduct(CamRight, CamFront);\n\t\t\t\tCamUp.Normalise();\n\t\t\t}\n#ifndef FIX_BUGS\n\t\t\t// BUG: FOV was already interpolated but m_fFOVWhenInterPol was not\n\t\t\tFOV = m_fFOVWhenInterPol;\n#endif\n\t\t}\n\n\t\tCVector Dist = CamSource - Target;\n\t\tfloat DistOnGround = Dist.Magnitude2D();\n\t\tfloat Alpha = CGeneral::GetATanOfXY(DistOnGround, Dist.z);\n\t\tfloat Beta = CGeneral::GetATanOfXY(Dist.x, Dist.y);\n\t\tCams[ActiveCam].KeepTrackOfTheSpeed(CamSource, Target, CamUp, Alpha, Beta, FOV);\n\t}else{\n\t\t// No transition, take Cam values directly\n#ifndef MASTER\n\t\tif(WorldViewerBeingUsed){\n\t\t\tCamSource = Cams[2].Source;\n\t\t\tCamFront = Cams[2].Front;\n\t\t\tCamUp = Cams[2].Up;\n\t\t\tFOV = Cams[2].FOV;\n\t\t}else\n#endif\n\t\t{\n\t\t\tCamSource = Cams[ActiveCam].Source;\n\t\t\tCamUp = Cams[ActiveCam].Up;\n\t\t\tif(m_bMoveCamToAvoidGeom){\n\t\t\t\tCamSource += m_vecClearGeometryVec;\n\t\t\t\tCamFront = Cams[ActiveCam].m_cvecTargetCoorsForFudgeInter - CamSource;\n\t\t\t\tCamFront.Normalise();\n\t\t\t\tCVector Right = CrossProduct(CamFront, CamUp);\n\t\t\t\tRight.Normalise();\n\t\t\t\tCamUp = CrossProduct(Right, CamFront);\n\t\t\t\tCamUp.Normalise();\n\t\t\t}else{\n\t\t\t\tCamFront = Cams[ActiveCam].Front;\n\t\t\t\tCamUp = Cams[ActiveCam].Up;\n\t\t\t}\n\t\t\tFOV = Cams[ActiveCam].FOV;\n\t\t}\n\t\tWasPreviouslyInterSyhonFollowPed = false;\t// unused\n\t}\n\n\tif(m_uiTransitionState != 0)\n\t\tif(!m_bLookingAtVector && m_bLookingAtPlayer && !CCullZones::CamStairsForPlayer() && !m_bPlayerIsInGarage){\n\t\t\tCEntity *entity = nil;\n\t\t\tCColPoint colPoint;\n\t\t\tif(CWorld::ProcessLineOfSight(pTargetEntity->GetPosition(), CamSource, colPoint, entity, true, false, false, true, false, true, true)){\n\t\t\t\tCamSource = colPoint.point;\n\t\t\t\tRwCameraSetNearClipPlane(Scene.camera, 0.05f);\n\t\t\t}\n\t\t}\n\n\tif(CMBlur::Drunkness > 0.0f){\n\t\tstatic float DrunkAngle;\n\n\t\tint tableIndex = (int)(DEGTORAD(DrunkAngle)/TWOPI * CParticle::SIN_COS_TABLE_SIZE) & CParticle::SIN_COS_TABLE_SIZE-1;\n\t\tDrunkAngle += 5.0f;\n#ifndef FIX_BUGS\n\t\t// This just messes up interpolation, probably not what they intended\n\t\t// and multiplying the interpolated FOV is also a bit extreme\n\t\t// so let's not do any of this nonsense\n\t\tCams[ActiveCam].FOV *= (1.0f + CMBlur::Drunkness);\n#endif\n\n\t\tCamSource.x += -0.02f*CMBlur::Drunkness * CParticle::m_CosTable[tableIndex];\n\t\tCamSource.y += -0.02f*CMBlur::Drunkness * CParticle::m_SinTable[tableIndex];\n\n\t\tCamUp.Normalise();\n\t\tCamUp.x += 0.05f*CMBlur::Drunkness * CParticle::m_CosTable[tableIndex];\n\t\tCamUp.y += 0.05f*CMBlur::Drunkness * CParticle::m_SinTable[tableIndex];\n\t\tCamUp.Normalise();\n\n\t\tCamFront.Normalise();\n\t\tCamFront.x += -0.1f*CMBlur::Drunkness * CParticle::m_CosTable[tableIndex];\n\t\tCamFront.y += -0.1f*CMBlur::Drunkness * CParticle::m_SinTable[tableIndex];\n\t\tCamFront.Normalise();\n\n\t\tCamRight = CrossProduct(CamFront, CamUp);\n\t\tCamRight.Normalise();\n\t\tCamUp = CrossProduct(CamRight, CamFront);\n\t\tCamUp.Normalise();\n\t}\n\n\tGetMatrix().GetRight() = CrossProduct(CamUp, CamFront);\t// actually Left\n\tGetMatrix().GetForward() = CamFront;\n\tGetMatrix().GetUp() = CamUp;\n\tGetMatrix().GetPosition() = CamSource;\n\n\t// Process Shake\n\tfloat shakeStrength = m_fCamShakeForce - 0.28f*(CTimer::GetTimeInMilliseconds()-m_uiCamShakeStart)/1000.0f;\n\tshakeStrength = clamp(shakeStrength, 0.0f, 2.0f);\n\tint shakeRand = CGeneral::GetRandomNumber();\n\tfloat shakeOffset = shakeStrength*0.1f;\n\tGetMatrix().GetPosition().x += shakeOffset * ((shakeRand & 0xF) - 7);\n\tGetMatrix().GetPosition().y += shakeOffset * (((shakeRand & 0xF0) >> 4) - 7);\n\tGetMatrix().GetPosition().z += shakeOffset * (((shakeRand & 0xF00) >> 8) - 7);\n\n\tif(shakeOffset > 0.0f && m_BlurType != MOTION_BLUR_SNIPER)\n\t\tSetMotionBlurAlpha(Min((int)(shakeStrength*255.0f) + 25, 150));\n\n\tstatic bool bExtra1stPrsBlur = false;\n\tif(Cams[ActiveCam].Mode == CCam::MODE_1STPERSON && FindPlayerVehicle() && FindPlayerVehicle()->GetUp().z < 0.2f){\n\t\tSetMotionBlur(230, 230, 230, 215, MOTION_BLUR_LIGHT_SCENE);\n\t\tbExtra1stPrsBlur = true;\n\t}else if(bExtra1stPrsBlur){\n\t\tSetMotionBlur(CTimeCycle::GetBlurRed(), CTimeCycle::GetBlurGreen(), CTimeCycle::GetBlurBlue(), m_motionBlur, MOTION_BLUR_LIGHT_SCENE);\n\t\tbExtra1stPrsBlur = false;\n\t}\n\n\tCalculateDerivedValues();\n\tCDraw::SetFOV(FOV);\n\n\t// Set RW camera\n#ifndef MASTER\n\tif(WorldViewerBeingUsed){\n\t\tRwFrame *frame = RwCameraGetFrame(m_pRwCamera);\n\t\tCVector Source = Cams[2].Source;\n\t\tCVector Front = Cams[2].Front;\n\t\tCVector Up = Cams[2].Up;\n\n\t\tGetMatrix().GetRight() = CrossProduct(Up, Front);\n\t\tGetMatrix().GetForward() = Front;\n\t\tGetMatrix().GetUp() = Up;\n\t\tGetMatrix().GetPosition() = Source;\n\n\t\tCDraw::SetFOV(Cams[2].FOV);\n\t\tm_vecGameCamPos = Cams[ActiveCam].Source;\n\n\t\t*RwMatrixGetPos(RwFrameGetMatrix(frame)) = GetPosition();\n\t\t*RwMatrixGetAt(RwFrameGetMatrix(frame)) = GetForward();\n\t\t*RwMatrixGetUp(RwFrameGetMatrix(frame)) = GetUp();\n\t\t*RwMatrixGetRight(RwFrameGetMatrix(frame)) = GetRight();\n\t\tRwMatrixUpdate(RwFrameGetMatrix(frame));\n\t\tRwFrameUpdateObjects(frame);\n\t}else\n#endif\n\t{\n\t\tRwFrame *frame = RwCameraGetFrame(m_pRwCamera);\n\t\tm_vecGameCamPos = GetPosition();\n\t\t*RwMatrixGetPos(RwFrameGetMatrix(frame)) = GetPosition();\n\t\t*RwMatrixGetAt(RwFrameGetMatrix(frame)) = GetForward();\n\t\t*RwMatrixGetUp(RwFrameGetMatrix(frame)) = GetUp();\n\t\t*RwMatrixGetRight(RwFrameGetMatrix(frame)) = GetRight();\n\t\tRwMatrixUpdate(RwFrameGetMatrix(frame));\n\t\tRwFrameUpdateObjects(frame);\n\t\tRwFrameOrthoNormalize(frame);\n\t}\n\n\tUpdateSoundDistances();\n\n\tif((CTimer::GetFrameCounter()&0xF) == 3)\n\t\tDistanceToWater = CWaterLevel::CalcDistanceToWater(GetPosition().x, GetPosition().y);\n\n\t// LOD dist\n\tif(!CCutsceneMgr::IsRunning() || CCutsceneMgr::UseLodMultiplier()){\n\t\tLODDistMultiplier = 70.0f/CDraw::GetFOV();\n\n\t\tif(GetPosition().z > 55.0f && FindPlayerVehicle() && FindPlayerVehicle()->pHandling->Flags & (HANDLING_IS_HELI|HANDLING_IS_PLANE) ||\n\t\t   FindPlayerPed()->m_attachedTo){\n\t\t\tLODDistMultiplier *= 1.0f + Max((GetPosition().z - 55.0f)/60.0f, 0.0f);\n\t\t\tfloat NewNear = DEFAULT_NEAR * (1.0f + Max((GetPosition().z - 55.0f)/60.0f, 0.0f));\n\t\t\tif(RwCameraGetNearClipPlane(Scene.camera) >= DEFAULT_NEAR)\n\t\t\t\tRwCameraSetNearClipPlane(Scene.camera, NewNear);\n\t\t}\n\t\tif(LODDistMultiplier > 2.2f) LODDistMultiplier = 2.2f;\n\t}else\n\t\tLODDistMultiplier = 1.0f;\n\tGenerationDistMultiplier = LODDistMultiplier;\n\tLODDistMultiplier *= CRenderer::ms_lodDistScale;\n\n\tCDraw::SetNearClipZ(RwCameraGetNearClipPlane(m_pRwCamera));\n\tCDraw::SetFarClipZ(RwCameraGetFarClipPlane(m_pRwCamera));\n\n\t// Keep track of speed\n\tif(m_bJustInitalised || m_bJust_Switched){\n\t\tm_PreviousCameraPosition = GetPosition();\n\t\tm_bJustInitalised = false;\n\t}\n\tm_CameraSpeedSoFar += (GetPosition() - m_PreviousCameraPosition).Magnitude();\n\tm_iNumFramesSoFar++;\n\tif(m_iNumFramesSoFar == m_iWorkOutSpeedThisNumFrames){\n\t\tm_CameraAverageSpeed = m_CameraSpeedSoFar / m_iWorkOutSpeedThisNumFrames;\n\t\tm_CameraSpeedSoFar = 0.0f;\n\t\tm_iNumFramesSoFar = 0;\n\t}\n\tm_PreviousCameraPosition = GetPosition();\n\n\tif(Cams[ActiveCam].DirectionWasLooking != LOOKING_FORWARD && Cams[ActiveCam].Mode != CCam::MODE_TOP_DOWN_PED){\n\t\tCams[ActiveCam].Source = Cams[ActiveCam].SourceBeforeLookBehind;\n\t\tOrientation += PI;\n\t}\n\n\tif(m_uiTransitionState != 0){\n\t\tint OtherCam = (ActiveCam+1)%2;\n\t\tif(Cams[OtherCam].CamTargetEntity &&\n\t\t   pTargetEntity && pTargetEntity->IsPed() &&\n\t\t   !Cams[OtherCam].CamTargetEntity->IsVehicle() &&\n\t\t   Cams[ActiveCam].Mode != CCam::MODE_TOP_DOWN_PED && Cams[ActiveCam].DirectionWasLooking != LOOKING_FORWARD){\n\t\t\tCams[OtherCam].Source = Cams[ActiveCam%2].SourceBeforeLookBehind;\n\t\t\tOrientation += PI;\n\t\t}\n\t}\n\n\tm_bCameraJustRestored = false;\n\tm_bMoveCamToAvoidGeom = false;\n}\n\nvoid\nCCamera::CamControl(void)\n{\n\tstatic bool PlaceForFixedWhenSniperFound = false;\n\tstatic int16 ReqMode;\n\tbool switchByJumpCut = false;\n\tbool stairs = false;\n\tbool boatTarget = false;\n\tint PrevMode = Cams[ActiveCam].Mode;\n\tCVector targetPos;\n\tCVector garageCenter, garageDoorPos1, garageDoorPos2;\n\tCVector garageCenterToDoor, garageCamPos;\n\tint whichDoor;\n\n\tm_bObbeCinematicPedCamOn = false;\n\tm_bObbeCinematicCarCamOn = false;\n\tm_bUseTransitionBeta = false;\n\tm_bUseSpecialFovTrain = false;\n\tm_bJustCameOutOfGarage = false;\n\tm_bTargetJustCameOffTrain = false;\n\tm_bInATunnelAndABigVehicle = false;\n\tm_bJustJumpedOutOf1stPersonBecauseOfTarget = false;\n\tbSwitchedToObbeCam = false;\n\n\tif(Cams[ActiveCam].CamTargetEntity == nil && pTargetEntity == nil)\n\t\tpTargetEntity = PLAYER;\n\n\tm_iZoneCullFrameNumWereAt++;\n\tif(m_iZoneCullFrameNumWereAt > m_iCheckCullZoneThisNumFrames)\n\t\tm_iZoneCullFrameNumWereAt = 1;\n\tm_bCullZoneChecksOn = m_iZoneCullFrameNumWereAt == m_iCheckCullZoneThisNumFrames;\n\tif(m_bCullZoneChecksOn)\n\t\tm_bFailedCullZoneTestPreviously = CCullZones::CamCloseInForPlayer();\n\n\tif(m_bLookingAtPlayer){\n\t\tCPad::GetPad(0)->DisablePlayerControls &= ~PLAYERCONTROL_CAMERA;\n\t\tFindPlayerPed()->bIsVisible = true;\n\t}\n\n\tif(!CTimer::GetIsPaused() && !m_bIdleOn){\n\t\tfloat CloseInCarHeightTarget = 0.0f;\n\t\tfloat CloseInPedHeightTarget = 0.0f;\n\n\t\tif(m_bTargetJustBeenOnTrain){\n\t\t\t// Getting off train\n\t\t\tif(!pTargetEntity->IsVehicle() || !((CVehicle*)pTargetEntity)->IsTrain()){\n\t\t\t\tRestore();\n\t\t\t\tm_bTargetJustCameOffTrain = true;\n\t\t\t\tm_bTargetJustBeenOnTrain = false;\n\t\t\t\tSetWideScreenOff();\n\t\t\t}\n\t\t}\n\n\t\t// Vehicle target\n\t\tif(pTargetEntity->IsVehicle()){\n#ifdef GTA_TRAIN\n\t\t\tif(((CVehicle*)pTargetEntity)->IsTrain()){\n\t\t\t\tif(!m_bTargetJustBeenOnTrain){\n\t\t\t\t\tm_bInitialNodeFound = false;\n\t\t\t\t\tm_bInitialNoNodeStaticsSet = false;\n\t\t\t\t}\n\t\t\t\tProcess_Train_Camera_Control();\n\t\t\t}else\n#endif\n\t\t\t{\n\t\t\t\tif(((CVehicle*)pTargetEntity)->IsBoat() && pTargetEntity->GetModelIndex() != MI_SKIMMER)\n\t\t\t\t\tboatTarget = true;\n\n\t\t\t\t// Change user selected mode\n\t\t\t\tif(CPad::GetPad(0)->CycleCameraModeUpJustDown() && !CReplay::IsPlayingBack() &&\n\t\t\t\t   (m_bLookingAtPlayer || WhoIsInControlOfTheCamera == CAMCONTROL_OBBE) &&\n\t\t\t\t   !m_WideScreenOn){\n\t\t\t\t\tCarZoomIndicator--;\n\t\t\t\t\t// disable topdown here\n\t\t\t\t\tif(CarZoomIndicator == CAM_ZOOM_TOPDOWN)\n\t\t\t\t\t\tCarZoomIndicator--;\n\t\t\t\t}\n\t\t\t\tif(CPad::GetPad(0)->CycleCameraModeDownJustDown() && !CReplay::IsPlayingBack() &&\n\t\t\t\t   (m_bLookingAtPlayer || WhoIsInControlOfTheCamera == CAMCONTROL_OBBE) &&\n\t\t\t\t   !m_WideScreenOn){\n\t\t\t\t\tCarZoomIndicator++;\n\t\t\t\t\tif(CarZoomIndicator == CAM_ZOOM_TOPDOWN)\n\t\t\t\t\t\tCarZoomIndicator++;\n\t\t\t\t}\n\t\t\t\tif(!m_bFailedCullZoneTestPreviously){\n\t\t\t\t\tif(CarZoomIndicator < CAM_ZOOM_1STPRS) CarZoomIndicator = CAM_ZOOM_CINEMATIC;\n\t\t\t\t\telse if(CarZoomIndicator > CAM_ZOOM_CINEMATIC) CarZoomIndicator = CAM_ZOOM_1STPRS;\n\t\t\t\t}\n\n\t\t\t\tif(m_bFailedCullZoneTestPreviously)\n\t\t\t\t\tif(CarZoomIndicator != CAM_ZOOM_1STPRS && CarZoomIndicator != CAM_ZOOM_TOPDOWN)\n\t\t\t\t\t\tReqMode = CCam::MODE_CAM_ON_A_STRING;\n\n\t\t\t\tint vehType = ((CVehicle*)pTargetEntity)->m_vehType;\n\t\t\t\tif(((CVehicle*)pTargetEntity)->IsBoat() && pTargetEntity->GetModelIndex() == MI_SKIMMER)\n\t\t\t\t\tvehType = VEHICLE_TYPE_CAR;\n\n\t\t\t\tswitch(vehType){\n\t\t\t\tcase VEHICLE_TYPE_CAR:\n\t\t\t\tcase VEHICLE_TYPE_BIKE:{\n\t\t\t\t\tCAttributeZone *stairsZone = nil;\n\t\t\t\t\tif(vehType == VEHICLE_TYPE_BIKE && CCullZones::CamStairsForPlayer()){\n\t\t\t\t\t\tstairsZone = CCullZones::FindZoneWithStairsAttributeForPlayer();\n\t\t\t\t\t\tif(stairsZone)\n\t\t\t\t\t\t\tstairs = true;\n\t\t\t\t\t}\n\t\t\t\t\tif(CGarages::IsPointInAGarageCameraZone(pTargetEntity->GetPosition()) || stairs){\n\t\t\t\t\t\tif(!m_bGarageFixedCamPositionSet && m_bLookingAtPlayer ||\n\t\t\t\t\t\t   WhoIsInControlOfTheCamera == CAMCONTROL_OBBE){\n\t\t\t\t\t\t\tif(pToGarageWeAreIn || stairsZone){\n\t\t\t\t\t\t\t\tfloat ground;\n\t\t\t\t\t\t\t\tbool foundGround;\n\n\t\t\t\t\t\t\t\tif(pToGarageWeAreIn){\n\t\t\t\t\t\t\t\t\t// This is all very strange....\n\t\t\t\t\t\t\t\t\t// targetPos = pTargetEntity->GetPosition();\t// unused\n\t\t\t\t\t\t\t\t\tif(pToGarageWeAreIn->m_pDoor1){\n\t\t\t\t\t\t\t\t\t\twhichDoor = 1;\n\t\t\t\t\t\t\t\t\t\tgarageDoorPos1.x = pToGarageWeAreIn->m_fDoor1X;\n\t\t\t\t\t\t\t\t\t\tgarageDoorPos1.y = pToGarageWeAreIn->m_fDoor1Y;\n\t\t\t\t\t\t\t\t\t\tgarageDoorPos1.z = 0.0f;\n\t\t\t\t\t\t\t\t\t\t// targetPos.z = 0.0f;\t// unused\n\t\t\t\t\t\t\t\t\t\t// (targetPos - doorPos1).Magnitude();\t// unused\n\t\t\t\t\t\t\t\t\t}else if(pToGarageWeAreIn->m_pDoor2){\n\t\t\t\t\t\t\t\t\t\twhichDoor = 2;\n#ifdef FIX_BUGS\n\t\t\t\t\t\t\t\t\t\tgarageDoorPos2.x = pToGarageWeAreIn->m_fDoor2X;\n\t\t\t\t\t\t\t\t\t\tgarageDoorPos2.y = pToGarageWeAreIn->m_fDoor2Y;\n\t\t\t\t\t\t\t\t\t\tgarageDoorPos2.z = 0.0f;\n#endif\n\t\t\t\t\t\t\t\t\t}else{\n\t\t\t\t\t\t\t\t\t\twhichDoor = 1;\n\t\t\t\t\t\t\t\t\t\tgarageDoorPos1.x = pTargetEntity->GetPosition().x;\n\t\t\t\t\t\t\t\t\t\tgarageDoorPos1.y = pTargetEntity->GetPosition().y;\n#ifdef FIX_BUGS\n\t\t\t\t\t\t\t\t\t\tgarageDoorPos1.z = 0.0f;\n#else\n\t\t\t\t\t\t\t\t\t\tgarageDoorPos2.z = 0.0f;\n#endif\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}else{\n\t\t\t\t\t\t\t\t\tassert(stairsZone);\n\t\t\t\t\t\t\t\t\twhichDoor = 1;\n\t\t\t\t\t\t\t\t\tgarageDoorPos1 = Cams[ActiveCam].Source;\n\t\t\t\t\t\t\t\t\tgarageCenter = CVector((stairsZone->minx+stairsZone->maxx)/2.0f, (stairsZone->miny+stairsZone->maxy)/2.0f, 0.0f);\n\t\t\t\t\t\t\t\t\tif((garageCenter-garageDoorPos1).Magnitude() > 15.0f){\n\t\t\t\t\t\t\t\t\t\tbool bClearViewOutside = true;\n\t\t\t\t\t\t\t\t\t\tCVector dirOutside = pTargetEntity->GetPosition() - garageCenter;\n\t\t\t\t\t\t\t\t\t\tdirOutside.z = 0.0f;\n\t\t\t\t\t\t\t\t\t\tdirOutside.Normalise();\n\t\t\t\t\t\t\t\t\t\tfloat zoneDim = stairsZone->maxx - stairsZone->minx;\n\t\t\t\t\t\t\t\t\t\tif(zoneDim < stairsZone->maxy - stairsZone->miny)\n\t\t\t\t\t\t\t\t\t\t\tzoneDim = stairsZone->maxy - stairsZone->miny;\n\t\t\t\t\t\t\t\t\t\tzoneDim *= 2.0f;\n\t\t\t\t\t\t\t\t\t\tCVector posOutside = pTargetEntity->GetPosition() + zoneDim*dirOutside;\n\t\t\t\t\t\t\t\t\t\tif(!CWorld::GetIsLineOfSightClear(pTargetEntity->GetPosition(), posOutside, true, false, false, false, false, false, true)){\n\t\t\t\t\t\t\t\t\t\t\tposOutside = pTargetEntity->GetPosition() - zoneDim*dirOutside;\n\t\t\t\t\t\t\t\t\t\t\tif(!CWorld::GetIsLineOfSightClear(pTargetEntity->GetPosition(), posOutside, true, false, false, false, false, false, true))\n\t\t\t\t\t\t\t\t\t\t\t\tbClearViewOutside = false;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\tif(bClearViewOutside)\n\t\t\t\t\t\t\t\t\t\t\tgarageDoorPos1 = posOutside;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tif(pToGarageWeAreIn){\n\t\t\t\t\t\t\t\t\tgarageCenter.x = pToGarageWeAreIn->GetGarageCenterX();\n\t\t\t\t\t\t\t\t\tgarageCenter.y = pToGarageWeAreIn->GetGarageCenterY();\n\t\t\t\t\t\t\t\t\tgarageCenter.z = 0.0f;\n\t\t\t\t\t\t\t\t}else{\n\t\t\t\t\t\t\t\t\tgarageDoorPos1.z = 0.0f;\n\t\t\t\t\t\t\t\t\tif(stairsZone == nil)\t// how can this be true?\n\t\t\t\t\t\t\t\t\t\tgarageCenter = CVector(pTargetEntity->GetPosition().x, pTargetEntity->GetPosition().y, 0.0f);\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tif(whichDoor == 1)\n\t\t\t\t\t\t\t\t\tgarageCenterToDoor = garageDoorPos1 - garageCenter;\n\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\tgarageCenterToDoor = garageDoorPos2 - garageCenter;\n\t\t\t\t\t\t\t\ttargetPos = pTargetEntity->GetPosition();\n\t\t\t\t\t\t\t\tground = CWorld::FindGroundZFor3DCoord(targetPos.x, targetPos.y, targetPos.z, &foundGround);\n\t\t\t\t\t\t\t\tif(!foundGround)\n\t\t\t\t\t\t\t\t\tground = targetPos.z - 0.2f;\n\t\t\t\t\t\t\t\tgarageCenterToDoor.z = 0.0f;\n\t\t\t\t\t\t\t\tgarageCenterToDoor.Normalise();\n\t\t\t\t\t\t\t\tif(whichDoor == 1){\n\t\t\t\t\t\t\t\t\tif(pToGarageWeAreIn == nil && stairsZone){\n\t\t\t\t\t\t\t\t\t\tfloat zoneDim = stairsZone->maxx - stairsZone->minx;\n\t\t\t\t\t\t\t\t\t\tif(zoneDim < stairsZone->maxy - stairsZone->miny)\n\t\t\t\t\t\t\t\t\t\t\tzoneDim = stairsZone->maxy - stairsZone->miny;\n\t\t\t\t\t\t\t\t\t\tgarageCamPos = garageCenter + (0.7f*zoneDim + 3.75f)*garageCenterToDoor;\n\t\t\t\t\t\t\t\t\t}else\n\t\t\t\t\t\t\t\t\t\tgarageCamPos = garageDoorPos1 + 13.0f*garageCenterToDoor;\n\t\t\t\t\t\t\t\t}else\n\t\t\t\t\t\t\t\t\tgarageCamPos = garageDoorPos2 + 13.0f*garageCenterToDoor;\n\t\t\t\t\t\t\t\tgarageCamPos.z = ground + 3.1f;\n\t\t\t\t\t\t\t\tSetCamPositionForFixedMode(garageCamPos, CVector(0.0f, 0.0f, 0.0f));\n\t\t\t\t\t\t\t\tm_bGarageFixedCamPositionSet = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif(CGarages::CameraShouldBeOutside() && m_bGarageFixedCamPositionSet &&\n\t\t\t\t\t\t   (m_bLookingAtPlayer || WhoIsInControlOfTheCamera == CAMCONTROL_OBBE)){\n\t\t\t\t\t\t\tif(pToGarageWeAreIn){\n\t\t\t\t\t\t\t\tReqMode = CCam::MODE_FIXED;\n\t\t\t\t\t\t\t\tm_bPlayerIsInGarage = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}else{\n\t\t\t\t\t\t\tif(m_bPlayerIsInGarage){\n\t\t\t\t\t\t\t\tm_bJustCameOutOfGarage = true;\n\t\t\t\t\t\t\t\tm_bPlayerIsInGarage = false;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tReqMode = CCam::MODE_CAM_ON_A_STRING;\n\t\t\t\t\t\t}\n\t\t\t\t\t}else{\n\t\t\t\t\t\tif(m_bPlayerIsInGarage){\n\t\t\t\t\t\t\tm_bJustCameOutOfGarage = true;\n\t\t\t\t\t\t\tm_bPlayerIsInGarage = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tm_bGarageFixedCamPositionSet = false;\n\t\t\t\t\t\tReqMode = CCam::MODE_CAM_ON_A_STRING;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase VEHICLE_TYPE_BOAT:\n\t\t\t\t\tReqMode = CCam::MODE_BEHINDBOAT;\n\t\t\t\t\tbreak;\n\t\t\t\tdefault: break;\n\t\t\t\t}\n\n\t\t\t\tint vehApp = ((CVehicle*)pTargetEntity)->GetVehicleAppearance();\n\t\t\t\tint vehArrPos = 0;\n\t\t\t\tGetArrPosForVehicleType(vehApp, vehArrPos);\n\n\t\t\t\t// Car zoom value\n\t\t\t\tif (CarZoomIndicator == CAM_ZOOM_1STPRS && !m_bPlayerIsInGarage) {\n\t\t\t\t\tCarZoomValue = 0.0f;\n\t\t\t\t\tReqMode = CCam::MODE_1STPERSON;\n\t\t\t\t}\n#ifdef FREE_CAM\n\t\t\t\telse if (bFreeCam) {\n\t\t\t\t\tif (CarZoomIndicator == CAM_ZOOM_1)\n\t\t\t\t\t\tCarZoomValue = LCS_ZOOM_ONE_DISTANCE[vehArrPos];\n\t\t\t\t\telse if (CarZoomIndicator == CAM_ZOOM_2)\n\t\t\t\t\t\tCarZoomValue = LCS_ZOOM_TWO_DISTANCE[vehArrPos];\n\t\t\t\t\telse if (CarZoomIndicator == CAM_ZOOM_3)\n\t\t\t\t\t\tCarZoomValue = LCS_ZOOM_THREE_DISTANCE[vehArrPos];\n\t\t\t\t}\n#endif\n\t\t\t\telse if (CarZoomIndicator == CAM_ZOOM_1)\n\t\t\t\t\tCarZoomValue = ZOOM_ONE_DISTANCE[vehArrPos];\n\t\t\t\telse if(CarZoomIndicator == CAM_ZOOM_2)\n\t\t\t\t\tCarZoomValue = ZOOM_TWO_DISTANCE[vehArrPos];\n\t\t\t\telse if(CarZoomIndicator == CAM_ZOOM_3)\n\t\t\t\t\tCarZoomValue = ZOOM_THREE_DISTANCE[vehArrPos];\n\n\t\t\t\tif(CarZoomIndicator == CAM_ZOOM_TOPDOWN && !m_bPlayerIsInGarage){\n\t\t\t\t\tCarZoomValue = 1.0f;\n\t\t\t\t\tReqMode = CCam::MODE_TOPDOWN;\n\t\t\t\t}\n\n\t\t\t\t// Check if we have to go into first person\n\t\t\t\tif(vehType == VEHICLE_TYPE_CAR && !m_bPlayerIsInGarage){\n\t\t\t\t\tif(CCullZones::Cam1stPersonForPlayer() && \n\t\t\t\t\t   pTargetEntity->GetColModel()->boundingBox.GetSize().z >= 3.026f &&\n\t\t\t\t\t   pToGarageWeAreInForHackAvoidFirstPerson == nil){\n\t\t\t\t\t\tReqMode = CCam::MODE_1STPERSON;\n\t\t\t\t\t\tm_bInATunnelAndABigVehicle = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif(ReqMode == CCam::MODE_TOPDOWN &&\n\t\t\t\t   (CCullZones::Cam1stPersonForPlayer() || CCullZones::CamNoRain() || CCullZones::PlayerNoRain()))\n\t\t\t\t\tReqMode = CCam::MODE_1STPERSON;\n\n\t\t\t\t// Smooth zoom value - ugly code\n\t\t\t\tif(m_bUseScriptZoomValueCar){\n\t\t\t\t\tif(CarZoomValueSmooth < m_fCarZoomValueScript){\n\t\t\t\t\t\tCarZoomValueSmooth += 0.12f * CTimer::GetTimeStep();\n\t\t\t\t\t\tCarZoomValueSmooth = Min(CarZoomValueSmooth, m_fCarZoomValueScript);\n\t\t\t\t\t}else{\n\t\t\t\t\t\tCarZoomValueSmooth -= 0.12f * CTimer::GetTimeStep();\n\t\t\t\t\t\tCarZoomValueSmooth = Max(CarZoomValueSmooth, m_fCarZoomValueScript);\n\t\t\t\t\t}\n\t\t\t\t}else if(m_bFailedCullZoneTestPreviously){\n\t\t\t\t\tCloseInCarHeightTarget = 0.65f;\n\t\t\t\t\tif(CarZoomValueSmooth < -0.65f){\n\t\t\t\t\t\tCarZoomValueSmooth += 0.12f * CTimer::GetTimeStep();\n\t\t\t\t\t\tCarZoomValueSmooth = Min(CarZoomValueSmooth, -0.65f);\n\t\t\t\t\t}else{\n\t\t\t\t\t\tCarZoomValueSmooth -= 0.12f * CTimer::GetTimeStep();\n\t\t\t\t\t\tCarZoomValueSmooth = Max(CarZoomValueSmooth, -0.65f);\n\t\t\t\t\t}\n\t\t\t\t}else{\n\t\t\t\t\tif(CarZoomValueSmooth < CarZoomValue){\n\t\t\t\t\t\tCarZoomValueSmooth += 0.12f * CTimer::GetTimeStep();\n\t\t\t\t\t\tCarZoomValueSmooth = Min(CarZoomValueSmooth, CarZoomValue);\n\t\t\t\t\t}else{\n\t\t\t\t\t\tCarZoomValueSmooth -= 0.12f * CTimer::GetTimeStep();\n\t\t\t\t\t\tCarZoomValueSmooth = Max(CarZoomValueSmooth, CarZoomValue);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tWellBufferMe(CloseInCarHeightTarget, &Cams[ActiveCam].m_fCloseInCarHeightOffset, &Cams[ActiveCam].m_fCloseInCarHeightOffsetSpeed, 0.1f, 0.25f, false);\n\n\t\t\t\t// Fallen into water\n\t\t\t\tif(Cams[ActiveCam].IsTargetInWater(Cams[ActiveCam].Source) && !boatTarget &&\n\t\t\t\t   !Cams[ActiveCam].CamTargetEntity->IsPed() &&\n\t\t\t\t   pTargetEntity->GetModelIndex() != MI_SKIMMER && pTargetEntity->GetModelIndex() != MI_SEASPAR)\n\t\t\t\t\tReqMode = CCam::MODE_PLAYER_FALLEN_WATER;\n\t\t\t}\n\t\t}\n\n\t\t// Ped target\n\t\telse if(pTargetEntity->IsPed()){\n\t\t\t// Change user selected mode\n\t\t\tif(CPad::GetPad(0)->CycleCameraModeUpJustDown() && !CReplay::IsPlayingBack() &&\n\t\t\t   (m_bLookingAtPlayer || WhoIsInControlOfTheCamera == CAMCONTROL_OBBE) &&\n\t\t\t   !m_WideScreenOn && !m_bFailedCullZoneTestPreviously && !m_bFirstPersonBeingUsed){\n\t\t\t\tif(FrontEndMenuManager.m_ControlMethod == CONTROL_STANDARD){\n\t\t\t\t\tif(PedZoomIndicator == CAM_ZOOM_3)\n\t\t\t\t\t\tPedZoomIndicator = CAM_ZOOM_1;\n\t\t\t\t\telse\n\t\t\t\t\t\tPedZoomIndicator = CAM_ZOOM_3;\n\t\t\t\t}else\n\t\t\t\t\tPedZoomIndicator--;\n\t\t\t}\n\t\t\tif(CPad::GetPad(0)->CycleCameraModeDownJustDown() && !CReplay::IsPlayingBack() &&\n\t\t\t   (m_bLookingAtPlayer || WhoIsInControlOfTheCamera == CAMCONTROL_OBBE) &&\n\t\t\t   !m_WideScreenOn && !m_bFailedCullZoneTestPreviously && !m_bFirstPersonBeingUsed){\n\t\t\t\tif(FrontEndMenuManager.m_ControlMethod == CONTROL_STANDARD){\n\t\t\t\t\tif(PedZoomIndicator == CAM_ZOOM_3)\n\t\t\t\t\t\tPedZoomIndicator = CAM_ZOOM_1;\n\t\t\t\t\telse\n\t\t\t\t\t\tPedZoomIndicator = CAM_ZOOM_3;\n\t\t\t\t}else\n\t\t\t\t\tPedZoomIndicator++;\n\t\t\t}\n\t\t\t// disabled top down and obbe's cam here\n\t\t\tif(PedZoomIndicator < CAM_ZOOM_1) PedZoomIndicator = CAM_ZOOM_3;\n\t\t\telse if(PedZoomIndicator > CAM_ZOOM_3) PedZoomIndicator = CAM_ZOOM_1;\n\n\t\t\tReqMode = CCam::MODE_FOLLOWPED;\n\n\t\t\t// Check 1st person mode\n\t\t\tif((m_bLookingAtPlayer || m_bEnable1rstPersonCamCntrlsScript) && pTargetEntity->IsPed() &&\n\t\t\t   (!m_WideScreenOn || m_bEnable1rstPersonCamCntrlsScript) && !Cams[0].Using3rdPersonMouseCam()\n#ifdef FREE_CAM\n\t\t\t   && (!CCamera::bFreeCam || m_bEnable1rstPersonCamCntrlsScript)\n#endif\n\t\t\t   ){\n\t\t\t\t// See if we want to enter first person mode\n\t\t\t\tif(CPad::GetPad(0)->LookAroundLeftRight() || CPad::GetPad(0)->LookAroundUpDown()){\n\t\t\t\t\tm_uiFirstPersonCamLastInputTime = CTimer::GetTimeInMilliseconds();\n\t\t\t\t\tm_bFirstPersonBeingUsed = true;\n\t\t\t\t}\n\t\t\t\tif(m_bFirstPersonBeingUsed){\n\t\t\t\t\t// Or if we want to go back to 3rd person\n\t\t\t\t\tif(CPad::GetPad(0)->GetPedWalkLeftRight() || CPad::GetPad(0)->GetPedWalkUpDown() ||\n\t\t\t\t\t   CPad::GetPad(0)->GetSquare() || CPad::GetPad(0)->GetTriangle() ||\n\t\t\t\t\t   CPad::GetPad(0)->GetCross() || CPad::GetPad(0)->GetCircle() ||\n\t\t\t\t\t   CTimer::GetTimeInMilliseconds() - m_uiFirstPersonCamLastInputTime > 2850.0f){\n\t\t\t\t\t\tm_bFirstPersonBeingUsed = false;\n\t\t\t\t\t}else if(CPad::GetPad(0)->TargetJustDown()){\n\t\t\t\t\t\tm_bFirstPersonBeingUsed = false;\n\t\t\t\t\t\tm_bJustJumpedOutOf1stPersonBecauseOfTarget = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}else\n\t\t\t\tm_bFirstPersonBeingUsed = false;\n\n\t\t\tif(!FindPlayerPed()->IsPedInControl() || FindPlayerPed()->m_fMoveSpeed > 0.0f)\n\t\t\t\tm_bFirstPersonBeingUsed = false;\n\t\t\tif(m_bFirstPersonBeingUsed){\n\t\t\t\tReqMode = CCam::MODE_1STPERSON;\n\t\t\t\tCPad::GetPad(0)->DisablePlayerControls |= PLAYERCONTROL_CAMERA;\n\t\t\t}\n\n\t\t\t// Zoom value\n\t\t\tif(PedZoomIndicator == CAM_ZOOM_1)\n\t\t\t\tm_fPedZoomValue = 0.25f;\n\t\t\telse if(PedZoomIndicator == CAM_ZOOM_2)\n\t\t\t\tm_fPedZoomValue = 1.5f;\n\t\t\telse if(PedZoomIndicator == CAM_ZOOM_3)\n\t\t\t\tm_fPedZoomValue = 2.9f;\n\n\t\t\t// Smooth zoom value - ugly code\n\t\t\tif(m_bUseScriptZoomValuePed){\n\t\t\t\tif(m_fPedZoomValueSmooth < m_fPedZoomValueScript){\n\t\t\t\t\tm_fPedZoomValueSmooth += 0.12f * CTimer::GetTimeStep();\n\t\t\t\t\tm_fPedZoomValueSmooth = Min(m_fPedZoomValueSmooth, m_fPedZoomValueScript);\n\t\t\t\t}else{\n\t\t\t\t\tm_fPedZoomValueSmooth -= 0.12f * CTimer::GetTimeStep();\n\t\t\t\t\tm_fPedZoomValueSmooth = Max(m_fPedZoomValueSmooth, m_fPedZoomValueScript);\n\t\t\t\t}\n\t\t\t}else if(m_bFailedCullZoneTestPreviously){\n\t\t\t\tstatic float PedZoomedInVal = 0.5f;\n\t\t\t\tCloseInPedHeightTarget = 0.7f;\n\t\t\t\tif(m_fPedZoomValueSmooth < PedZoomedInVal){\n\t\t\t\t\tm_fPedZoomValueSmooth += 0.12f * CTimer::GetTimeStep();\n\t\t\t\t\tm_fPedZoomValueSmooth = Min(m_fPedZoomValueSmooth, PedZoomedInVal);\n\t\t\t\t}else{\n\t\t\t\t\tm_fPedZoomValueSmooth -= 0.12f * CTimer::GetTimeStep();\n\t\t\t\t\tm_fPedZoomValueSmooth = Max(m_fPedZoomValueSmooth, PedZoomedInVal);\n\t\t\t\t}\n\t\t\t}else{\n\t\t\t\tif(m_fPedZoomValueSmooth < m_fPedZoomValue){\n\t\t\t\t\tm_fPedZoomValueSmooth += 0.12f * CTimer::GetTimeStep();\n\t\t\t\t\tm_fPedZoomValueSmooth = Min(m_fPedZoomValueSmooth, m_fPedZoomValue);\n\t\t\t\t}else{\n\t\t\t\t\tm_fPedZoomValueSmooth -= 0.12f * CTimer::GetTimeStep();\n\t\t\t\t\tm_fPedZoomValueSmooth = Max(m_fPedZoomValueSmooth, m_fPedZoomValue);\n\t\t\t\t}\n\t\t\t\tif(PedZoomIndicator == CAM_ZOOM_3 && m_fPedZoomValue == 0.0f)\n\t\t\t\t\tm_fPedZoomValueSmooth = m_fPedZoomValue;\n\t\t\t}\n\n\t\t\tWellBufferMe(CloseInPedHeightTarget, &Cams[ActiveCam].m_fCloseInPedHeightOffset, &Cams[ActiveCam].m_fCloseInPedHeightOffsetSpeed, 0.1f, 0.025f, false);\n\n\t\t\t// Check if entering fight cam\n\t\t\tif(!m_bFirstPersonBeingUsed){\n\t\t\t\tif(FindPlayerPed()->GetPedState() == PED_FIGHT && !m_bUseMouse3rdPerson)\n\t\t\t\t\tReqMode = CCam::MODE_FIGHT_CAM;\n\t\t\t\tif(((CPed*)pTargetEntity)->GetWeapon()->m_eWeaponType == WEAPONTYPE_BASEBALLBAT &&\n\t\t\t\t   FindPlayerPed()->GetPedState() == PED_ATTACK && !m_bUseMouse3rdPerson)\n\t\t\t\t\tReqMode = CCam::MODE_FIGHT_CAM;\n\t\t\t}\n\n\t\t\t// Garage cam\n\t\t\tCAttributeZone *stairsZone = nil;\n\t\t\tif(CCullZones::CamStairsForPlayer()){\n\t\t\t\tstairsZone = CCullZones::FindZoneWithStairsAttributeForPlayer();\n\t\t\t\tif(stairsZone)\n\t\t\t\t\tstairs = true;\n\t\t\t}\n\t\t\tif(CGarages::IsPointInAGarageCameraZone(pTargetEntity->GetPosition()) && !m_bUseMouse3rdPerson || stairs){\n\t\t\t\tif(!m_bGarageFixedCamPositionSet && m_bLookingAtPlayer){\n\t\t\t\t\tif(pToGarageWeAreIn || stairs){\n\t\t\t\t\t\tfloat ground;\n\t\t\t\t\t\tbool foundGround;\n\n\t\t\t\t\t\tif(pToGarageWeAreIn){\n\t\t\t\t\t\t\t// targetPos = pTargetEntity->GetPosition();\t// unused\n\t\t\t\t\t\t\tif(pToGarageWeAreIn->m_pDoor1){\n\t\t\t\t\t\t\t\twhichDoor = 1;\n\t\t\t\t\t\t\t\tgarageDoorPos1.x = pToGarageWeAreIn->m_fDoor1X;\n\t\t\t\t\t\t\t\tgarageDoorPos1.y = pToGarageWeAreIn->m_fDoor1Y;\n\t\t\t\t\t\t\t\tgarageDoorPos1.z = 0.0f;\n\t\t\t\t\t\t\t\t// targetPos.z = 0.0f;\t// unused\n\t\t\t\t\t\t\t\t// (targetPos - doorPos1).Magnitude();\t// unused\n\t\t\t\t\t\t\t}else if(pToGarageWeAreIn->m_pDoor2){\n\t\t\t\t\t\t\t\twhichDoor = 2;\n#ifdef FIX_BUGS\n\t\t\t\t\t\t\t\tgarageDoorPos2.x = pToGarageWeAreIn->m_fDoor2X;\n\t\t\t\t\t\t\t\tgarageDoorPos2.y = pToGarageWeAreIn->m_fDoor2Y;\n\t\t\t\t\t\t\t\tgarageDoorPos2.z = 0.0f;\n#endif\n\t\t\t\t\t\t\t}else{\n\t\t\t\t\t\t\t\twhichDoor = 1;\n\t\t\t\t\t\t\t\tgarageDoorPos1.x = pTargetEntity->GetPosition().x;\n\t\t\t\t\t\t\t\tgarageDoorPos1.y = pTargetEntity->GetPosition().y;\n#ifdef FIX_BUGS\n\t\t\t\t\t\t\t\tgarageDoorPos1.z = 0.0f;\n#else\n\t\t\t\t\t\t\t\tgarageDoorPos2.z = 0.0f;\n#endif\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}else{\n\t\t\t\t\t\t\twhichDoor = 1;\n\t\t\t\t\t\t\tgarageDoorPos1 = Cams[ActiveCam].Source;\n\n\t\t\t\t\t\t\tif(stairsZone){\t// always true\n\t\t\t\t\t\t\t\tgarageCenter = CVector((stairsZone->minx+stairsZone->maxx)/2, (stairsZone->miny+stairsZone->maxy)/2, 0.0f);\n\t\t\t\t\t\t\t\tif(pTargetEntity->GetPosition().x > 376.0f && pTargetEntity->GetPosition().x < 383.0f &&\n\t\t\t\t\t\t\t\t   pTargetEntity->GetPosition().y > -496.0f && pTargetEntity->GetPosition().y < -489.0f &&\n\t\t\t\t\t\t\t\t   pTargetEntity->GetPosition().z > 11.6f && pTargetEntity->GetPosition().z < 13.6f){\n\t\t\t\t\t\t\t\t\tgarageDoorPos1 = CVector(382.6f, -489.6f, 13.1f);\n\t\t\t\t\t\t\t\t}else{\n\t\t\t\t\t\t\t\t\tbool bClearViewOutside = true;\n\t\t\t\t\t\t\t\t\tCVector dirOutside = pTargetEntity->GetPosition() - garageCenter;\n\t\t\t\t\t\t\t\t\tdirOutside.z = 0.0f;\n\t\t\t\t\t\t\t\t\tdirOutside.Normalise();\n\t\t\t\t\t\t\t\t\tfloat zoneDim = stairsZone->maxx - stairsZone->minx;\n\t\t\t\t\t\t\t\t\tif(zoneDim < stairsZone->maxy - stairsZone->miny)\n\t\t\t\t\t\t\t\t\t\tzoneDim = stairsZone->maxy - stairsZone->miny;\n\t\t\t\t\t\t\t\t\tzoneDim *= 2.0f;\n\t\t\t\t\t\t\t\t\tCVector posOutside = pTargetEntity->GetPosition() + zoneDim*dirOutside;\n\t\t\t\t\t\t\t\t\tif(!CWorld::GetIsLineOfSightClear(pTargetEntity->GetPosition(), posOutside, true, false, false, false, false, false, true)){\n\t\t\t\t\t\t\t\t\t\tposOutside = pTargetEntity->GetPosition() - zoneDim*dirOutside;\n\t\t\t\t\t\t\t\t\t\tif(!CWorld::GetIsLineOfSightClear(pTargetEntity->GetPosition(), posOutside, true, false, false, false, false, false, true))\n\t\t\t\t\t\t\t\t\t\t\tbClearViewOutside = false;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tif(bClearViewOutside)\n\t\t\t\t\t\t\t\t\t\tgarageDoorPos1 = posOutside;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif(pToGarageWeAreIn){\n\t\t\t\t\t\t\tgarageCenter.x = pToGarageWeAreIn->GetGarageCenterX();\n\t\t\t\t\t\t\tgarageCenter.y = pToGarageWeAreIn->GetGarageCenterY();\n\t\t\t\t\t\t\tgarageCenter.z = 0.0f;\n\t\t\t\t\t\t}else{\n\t\t\t\t\t\t\tgarageDoorPos1.z = 0.0f;\n\t\t\t\t\t\t\tif(!stairs)\t// how can this be true?\n\t\t\t\t\t\t\t\tgarageCenter = CVector(pTargetEntity->GetPosition().x, pTargetEntity->GetPosition().y, 0.0f);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif(whichDoor == 1)\n\t\t\t\t\t\t\tgarageCenterToDoor = garageDoorPos1 - garageCenter;\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tgarageCenterToDoor = garageDoorPos2 - garageCenter;\n\t\t\t\t\t\ttargetPos = pTargetEntity->GetPosition();\n\t\t\t\t\t\tground = CWorld::FindGroundZFor3DCoord(targetPos.x, targetPos.y, targetPos.z, &foundGround);\n\t\t\t\t\t\tif(!foundGround)\n\t\t\t\t\t\t\tground = targetPos.z - 0.2f;\n\t\t\t\t\t\tgarageCenterToDoor.z = 0.0f;\n\t\t\t\t\t\tgarageCenterToDoor.Normalise();\n\t\t\t\t\t\tif(whichDoor == 1){\n\t\t\t\t\t\t\tif(pToGarageWeAreIn == nil && stairs){\n\t\t\t\t\t\t\t\tif(stairsZone){\n\t\t\t\t\t\t\t\t\tfloat zoneDim = stairsZone->maxx - stairsZone->minx;\n\t\t\t\t\t\t\t\t\tif(zoneDim < stairsZone->maxy - stairsZone->miny)\n\t\t\t\t\t\t\t\t\t\tzoneDim = stairsZone->maxy - stairsZone->miny;\n\t\t\t\t\t\t\t\t\tgarageCamPos = garageCenter + (0.7f*zoneDim + 3.75f)*garageCenterToDoor;\n\t\t\t\t\t\t\t\t}else\t// how can this be true?\n\t\t\t\t\t\t\t\t\tgarageCamPos = garageDoorPos1 + 3.75f*garageCenterToDoor;\n\t\t\t\t\t\t\t}else\n\t\t\t\t\t\t\t\tgarageCamPos = garageDoorPos1 + 13.0f*garageCenterToDoor;\n\t\t\t\t\t\t}else{\n\t\t\t\t\t\t\tgarageCamPos = garageDoorPos2 + 13.0f*garageCenterToDoor;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif(PedZoomIndicator == CAM_ZOOM_TOPDOWN && !stairs){\n\t\t\t\t\t\t\tgarageCamPos = garageCenter;\n\t\t\t\t\t\t\tgarageCamPos.z += FindPlayerPed()->GetPosition().z + 2.1f;\n\t\t\t\t\t\t\tif(pToGarageWeAreIn && garageCamPos.z > pToGarageWeAreIn->m_fSupX)\t// What?\n\t\t\t\t\t\t\t\tgarageCamPos.z = pToGarageWeAreIn->m_fSupX;\n\t\t\t\t\t\t}else\n\t\t\t\t\t\t\tgarageCamPos.z = ground + 3.1f;\n\t\t\t\t\t\tSetCamPositionForFixedMode(garageCamPos, CVector(0.0f, 0.0f, 0.0f));\n\t\t\t\t\t\tm_bGarageFixedCamPositionSet = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif((CGarages::CameraShouldBeOutside() || stairs) && m_bLookingAtPlayer && m_bGarageFixedCamPositionSet){\n\t\t\t\t\tif(pToGarageWeAreIn || stairs){\n\t\t\t\t\t\tReqMode = CCam::MODE_FIXED;\n\t\t\t\t\t\tm_bPlayerIsInGarage = true;\n\t\t\t\t\t}\n\t\t\t\t}else{\n\t\t\t\t\tif(m_bPlayerIsInGarage){\n\t\t\t\t\t\tm_bJustCameOutOfGarage = true;\n\t\t\t\t\t\tm_bPlayerIsInGarage = false;\n\t\t\t\t\t}\n\t\t\t\t\tReqMode = CCam::MODE_FOLLOWPED;\n\t\t\t\t}\n\t\t\t}else{\n\t\t\t\tif(m_bPlayerIsInGarage){\n\t\t\t\t\tm_bJustCameOutOfGarage = true;\n\t\t\t\t\tm_bPlayerIsInGarage = false;\n\t\t\t\t}\n\t\t\t\tm_bGarageFixedCamPositionSet = false;\n\t\t\t}\n\n\t\t\t// Lighthouse\n\t\t\tif(!m_bFirstPersonBeingUsed && (pTargetEntity->GetPosition() - CVector(474.3f, -1717.6f, 0.0f)).Magnitude2D() < 6.0f)\n\t\t\t\tif((pTargetEntity->GetPosition() - CVector(474.3f, -1717.6f, 0.0f)).Magnitude2D() < 3.8f ||\n\t\t\t\t   pTargetEntity->GetPosition().z > 50.0f)\n\t\t\t\t\tif(!Cams[ActiveCam].Using3rdPersonMouseCam())\n\t\t\t\t\t\tReqMode = CCam::MODE_LIGHTHOUSE;\n\n\t\t\t// Fallen into water\n\t\t\tif(Cams[ActiveCam].IsTargetInWater(Cams[ActiveCam].Source) &&\n\t\t\t   Cams[ActiveCam].CamTargetEntity->IsPed())\n\t\t\t\tReqMode = CCam::MODE_PLAYER_FALLEN_WATER;\n\n\t\t\t// Set top down\n\t\t\tif(PedZoomIndicator == CAM_ZOOM_TOPDOWN &&\n\t\t\t   !CCullZones::Cam1stPersonForPlayer() &&\n\t\t\t   !CCullZones::CamNoRain() &&\n\t\t\t   !CCullZones::PlayerNoRain() &&\n\t\t\t   !m_bFirstPersonBeingUsed &&\n\t\t\t   !m_bPlayerIsInGarage)\n\t\t\t\tReqMode = CCam::MODE_TOP_DOWN_PED;\n\n\t\t\t// Weapon mode\n\t\t\tif(!CPad::GetPad(0)->GetTarget() && PlayerWeaponMode.Mode != CCam::MODE_HELICANNON_1STPERSON)\n\t\t\t\tClearPlayerWeaponMode();\n\t\t\tif(m_PlayerMode.Mode != CCam::MODE_NONE)\n\t\t\t\tReqMode = m_PlayerMode.Mode;\n\t\t\tif(PlayerWeaponMode.Mode != CCam::MODE_NONE && !stairs){\n\t\t\t\tif(PlayerWeaponMode.Mode == CCam::MODE_SNIPER ||\n\t\t\t\t   PlayerWeaponMode.Mode == CCam::MODE_ROCKETLAUNCHER ||\n\t\t\t\t\t// game also checks MODE_MODELVIEW here but that does make any sense...\n\t\t\t\t   PlayerWeaponMode.Mode == CCam::MODE_M16_1STPERSON ||\n\t\t\t\t   PlayerWeaponMode.Mode == CCam::MODE_HELICANNON_1STPERSON ||\n\t\t\t\t   PlayerWeaponMode.Mode == CCam::MODE_CAMERA ||\n\t\t\t\t   Cams[ActiveCam].GetWeaponFirstPersonOn()){\n\t\t\t\t\t// First person weapon mode\n\t\t\t\t\tif(PLAYER->GetPedState() == PED_SEEK_CAR){\n\t\t\t\t\t\tif(ReqMode == CCam::MODE_TOP_DOWN_PED || Cams[ActiveCam].GetWeaponFirstPersonOn())\n\t\t\t\t\t\t\tReqMode = PlayerWeaponMode.Mode;\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tReqMode = CCam::MODE_FOLLOWPED;\n\t\t\t\t\t}else\n\t\t\t\t\t\tReqMode = PlayerWeaponMode.Mode;\n\t\t\t\t}else if(ReqMode != CCam::MODE_TOP_DOWN_PED && PedZoomIndicator != CAM_ZOOM_3){\n\t\t\t\t\t// Syphon mode\n\t\t\t\t\tfloat playerTargetDist;\n\t\t\t\t\tfloat deadPedDist = 4.0f;\n\t\t\t\t\tstatic float alivePedDist = 2.0f;\t// original name lost\n\t\t\t\t\tfloat pedDist;\t\t// actually only used on dead target\n\t\t\t\t\tbool targetDead = false;\n\t\t\t\t\tfloat camAngle, targetAngle;\n\t\t\t\t\tCVector playerToTarget = m_cvecAimingTargetCoors - pTargetEntity->GetPosition();\n\t\t\t\t\tCVector playerToCam = Cams[ActiveCam].Source - pTargetEntity->GetPosition();\n\n\t\t\t\t\tif(PedZoomIndicator == CAM_ZOOM_1)\n\t\t\t\t\t\tdeadPedDist = 2.25f;\n\t\t\t\t\tif(FindPlayerPed()->m_pPointGunAt){\n\t\t\t\t\t\t// BUG: this need not be a ped!\n\t\t\t\t\t\tif(((CPed*)FindPlayerPed()->m_pPointGunAt)->DyingOrDead()){\n\t\t\t\t\t\t\ttargetDead = true;\n\t\t\t\t\t\t\tpedDist = deadPedDist;\n\t\t\t\t\t\t}else\n\t\t\t\t\t\t\tpedDist = alivePedDist;\n\t\t\t\t\t\tplayerTargetDist = playerToTarget.Magnitude2D();\n\t\t\t\t\t\tcamAngle = CGeneral::GetATanOfXY(playerToCam.x, playerToCam.y);\n\t\t\t\t\t\ttargetAngle = CGeneral::GetATanOfXY(playerToTarget.x, playerToTarget.y);\n\t\t\t\t\t\tReqMode = PlayerWeaponMode.Mode;\n\n\t\t\t\t\t\t// Check whether to start aiming in crim-in-front mode\n\t\t\t\t\t\tif(Cams[ActiveCam].Mode != CCam::MODE_SYPHON){\n\t\t\t\t\t\t\tfloat angleDiff = camAngle - targetAngle;\n\t\t\t\t\t\t\twhile(angleDiff >= PI) angleDiff -= 2*PI;\n\t\t\t\t\t\t\twhile(angleDiff < -PI) angleDiff += 2*PI;\n\t\t\t\t\t\t\tif(Abs(angleDiff) < HALFPI && playerTargetDist < 3.5f && playerToTarget.z > -1.0f)\n\t\t\t\t\t\t\t\tReqMode = CCam::MODE_SYPHON_CRIM_IN_FRONT;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Check whether to go to special fixed mode\n\t\t\t\t\t\tfloat fixedModeDist = 0.0f;\n\t\t\t\t\t\tif((ReqMode == CCam::MODE_SYPHON_CRIM_IN_FRONT || ReqMode == CCam::MODE_SYPHON) &&\n\t\t\t\t\t\t   (m_uiTransitionState == 0 || Cams[ActiveCam].Mode == CCam::MODE_SPECIAL_FIXED_FOR_SYPHON) &&\n\t\t\t\t\t\t   playerTargetDist < pedDist && targetDead){\n\t\t\t\t\t\t\tif(ReqMode == CCam::MODE_SYPHON_CRIM_IN_FRONT)\n\t\t\t\t\t\t\t\tfixedModeDist = 5.0f;\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\tfixedModeDist = 5.6f;\n\t\t\t\t\t\t\tReqMode = CCam::MODE_SPECIAL_FIXED_FOR_SYPHON;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif(ReqMode == CCam::MODE_SPECIAL_FIXED_FOR_SYPHON){\n\t\t\t\t\t\t\tif(!PlaceForFixedWhenSniperFound){\n\t\t\t\t\t\t\t\t// Find position\n\t\t\t\t\t\t\t\tCEntity *entity;\n\t\t\t\t\t\t\t\tCColPoint colPoint;\n\t\t\t\t\t\t\t\tCVector fixedPos = pTargetEntity->GetPosition();\n\t\t\t\t\t\t\t\tfixedPos.x += fixedModeDist*Cos(camAngle);\n\t\t\t\t\t\t\t\tfixedPos.y += fixedModeDist*Sin(camAngle);\n\t\t\t\t\t\t\t\tfixedPos.z += 1.15f;\n\t\t\t\t\t\t\t\tif(CWorld::ProcessLineOfSight(pTargetEntity->GetPosition(), fixedPos, colPoint, entity, true, false, false, true, false, true, true))\n\t\t\t\t\t\t\t\t\tSetCamPositionForFixedMode(colPoint.point, CVector(0.0f, 0.0f, 0.0f));\n\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\tSetCamPositionForFixedMode(fixedPos, CVector(0.0f, 0.0f, 0.0f));\n\t\t\t\t\t\t\t\tPlaceForFixedWhenSniperFound = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}else\n\t\t\t\t\t\t\tPlaceForFixedWhenSniperFound = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif(DebugCamMode)\n\t\tReqMode = DebugCamMode;\n\n\n\t// Process arrested player\n\tstatic int ThePickedArrestMode;\n\tstatic int LastPedState;\n\tbool startArrestCam = false;\n\tstatic bool beingArrested = false;\n\tbool stopArrestCam = false;\n\n\tif(PLAYER->GetPedState() == PED_ARRESTED)\n\t\tbeingArrested = true;\n\telse if(beingArrested){\n\t\tstopArrestCam = true;\n\t\tbeingArrested = false;\n\t}\n\tif(LastPedState != PED_ARRESTED && PLAYER->GetPedState() == PED_ARRESTED){\n\t\tif(CarZoomIndicator != CAM_ZOOM_1STPRS || !pTargetEntity->IsVehicle())\n\t\t\tstartArrestCam = true;\n\t}else\n\t\tstartArrestCam = false;\n\tLastPedState = PLAYER->GetPedState();\n\n\tif(startArrestCam){\n\t\tThePickedArrestMode = CCam::MODE_ARRESTCAM_ONE;\n\t\tReqMode = CCam::MODE_ARRESTCAM_ONE;\n\t\tCams[ActiveCam].ResetStatics = true;\n\t}else if(PLAYER->GetPedState() == PED_ARRESTED)\n\t\tReqMode = ThePickedArrestMode;\n\n\t// Process dead player\n\tif(PLAYER->GetPedState() == PED_DEAD){\n\t\tif(Cams[ActiveCam].Mode == CCam::MODE_PED_DEAD_BABY)\n\t\t\tReqMode = CCam::MODE_PED_DEAD_BABY;\n\t\telse{\n\t\t\tbool useArrestCam = false;\n\t\t\tif(pTargetEntity->IsPed()){\n\t\t\t\tfor(int i = 0; i < ((CPed*)pTargetEntity)->m_numNearPeds; i++){\n\t\t\t\t\tCPed *ped = ((CPed*)pTargetEntity)->m_nearPeds[i];\n\t\t\t\t\tif(ped && ped->GetPedState() == PED_ARREST_PLAYER)\n\t\t\t\t\t\tif((ped->GetPosition() - pTargetEntity->GetPosition()).Magnitude() < 4.0f){\n\t\t\t\t\t\t\tReqMode = CCam::MODE_ARRESTCAM_ONE;\n\t\t\t\t\t\t\tCams[ActiveCam].ResetStatics = true;\n\t\t\t\t\t\t\tuseArrestCam = true;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif(!useArrestCam){\n\t\t\t\tReqMode = CCam::MODE_PED_DEAD_BABY;\n\t\t\t\tCams[ActiveCam].ResetStatics = true;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Restore with a jump cut\n\tif(m_bRestoreByJumpCut){\n\t\tif(ReqMode != CCam::MODE_FOLLOWPED &&\n\t\t   ReqMode != CCam::MODE_BEHINDCAR &&\n\t\t   ReqMode != CCam::MODE_CAM_ON_A_STRING &&\n\t\t   ReqMode != CCam::MODE_M16_1STPERSON &&\n\t\t   ReqMode != CCam::MODE_SYPHON &&\n\t\t   ReqMode != CCam::MODE_SYPHON_CRIM_IN_FRONT &&\n\t\t   ReqMode != CCam::MODE_SPECIAL_FIXED_FOR_SYPHON &&\n\t\t   ReqMode != CCam::MODE_SNIPER &&\n\t\t   ReqMode != CCam::MODE_ROCKETLAUNCHER &&\n\t\t   ReqMode != CCam::MODE_CAMERA &&\n\t\t   !m_bUseMouse3rdPerson)\n\t\t\tSetCameraDirectlyBehindForFollowPed_CamOnAString();\n\n\t\tReqMode = m_iModeToGoTo;\n\t\tCams[ActiveCam].Mode = ReqMode;\n\t\tm_bJust_Switched = true;\n\t\tCams[ActiveCam].ResetStatics = true;\n\t\tCams[ActiveCam].m_cvecCamFixedModeVector = m_vecFixedModeVector;\n\t\tCams[ActiveCam].CamTargetEntity = pTargetEntity;\n\t\tCams[ActiveCam].m_cvecCamFixedModeSource = m_vecFixedModeSource;\n\t\tCams[ActiveCam].m_cvecCamFixedModeUpOffSet = m_vecFixedModeUpOffSet;\n\t\tCams[ActiveCam].m_bCamLookingAtVector = false;\n\t\tCams[ActiveCam].m_vecLastAboveWaterCamPosition = Cams[(ActiveCam+1)%2].m_vecLastAboveWaterCamPosition;\n\t\tm_bRestoreByJumpCut = false;\n\t\tCams[ActiveCam].ResetStatics = true;\n\t\tpTargetEntity->RegisterReference(&pTargetEntity);\n\t\tCams[ActiveCam].CamTargetEntity->RegisterReference(&Cams[ActiveCam].CamTargetEntity);\n\t\tCarZoomValueSmooth = CarZoomValue;\n\t\tm_fPedZoomValueSmooth = m_fPedZoomValue;\n\t\tm_uiTransitionState = 0;\n\t\tm_vecDoingSpecialInterPolation = false;\n\t}\n\n\tif(gbModelViewer)\n\t\tReqMode = CCam::MODE_MODELVIEW;\n\n\t// Turn on Obbe's cam\n\tbool canUseObbeCam = true;\n\tif(pTargetEntity){\n\t\tif(pTargetEntity->IsVehicle()){\n\t\t\tif(CarZoomIndicator == CAM_ZOOM_CINEMATIC)\n\t\t\t\tm_bObbeCinematicCarCamOn = true;\n\t\t}else{\n\t\t\tif(PedZoomIndicator == CAM_ZOOM_CINEMATIC)\n\t\t\t\tm_bObbeCinematicPedCamOn = true;\n\t\t}\n\t}\n\tif(m_bTargetJustBeenOnTrain ||\n\t   ReqMode == CCam::MODE_SYPHON || ReqMode == CCam::MODE_SYPHON_CRIM_IN_FRONT || ReqMode == CCam::MODE_SPECIAL_FIXED_FOR_SYPHON ||\n\t   ReqMode == CCam::MODE_PED_DEAD_BABY || ReqMode == CCam::MODE_ARRESTCAM_ONE || ReqMode == CCam::MODE_ARRESTCAM_TWO ||\n\t   ReqMode == CCam::MODE_FIGHT_CAM || ReqMode == CCam::MODE_PLAYER_FALLEN_WATER ||\n\t   ReqMode == CCam::MODE_SNIPER || ReqMode == CCam::MODE_ROCKETLAUNCHER || ReqMode == CCam::MODE_M16_1STPERSON ||\n\t   ReqMode == CCam::MODE_SNIPER_RUNABOUT || ReqMode == CCam::MODE_ROCKETLAUNCHER_RUNABOUT ||\n\t   ReqMode == CCam::MODE_1STPERSON_RUNABOUT || ReqMode == CCam::MODE_M16_1STPERSON_RUNABOUT ||\n\t   ReqMode == CCam::MODE_FIGHT_CAM_RUNABOUT || ReqMode == CCam::MODE_HELICANNON_1STPERSON || ReqMode == CCam::MODE_CAMERA ||\n\t   WhoIsInControlOfTheCamera == CAMCONTROL_SCRIPT ||\n\t   m_bJustCameOutOfGarage || m_bPlayerIsInGarage)\n\t\tcanUseObbeCam = false;\n\n\tif(m_bObbeCinematicPedCamOn && canUseObbeCam)\n\t\tProcessObbeCinemaCameraPed();\n\telse if(m_bObbeCinematicCarCamOn && canUseObbeCam){\n\t\tif(pTargetEntity->IsVehicle() && ((CVehicle*)pTargetEntity)->GetVehicleAppearance() == VEHICLE_APPEARANCE_HELI ||\n\t\t   ((CVehicle*)pTargetEntity)->IsBoat())\n\t\t\tProcessObbeCinemaCameraHeli();\n\t\telse\n\t\t\tProcessObbeCinemaCameraCar();\n\t}else{\n\t\tif(m_bPlayerIsInGarage && m_bObbeCinematicCarCamOn)\n\t\t\tswitchByJumpCut = true;\n\t\tcanUseObbeCam = false;\n\t\tDontProcessObbeCinemaCamera();\n\t}\n\n\t// Start the transition or do a jump cut\n\tif(m_bLookingAtPlayer){\n\t\t// Going into top down modes normally needs a jump cut (but see below)\n\t\tif(ReqMode == CCam::MODE_TOPDOWN || ReqMode == CCam::MODE_1STPERSON || ReqMode == CCam::MODE_TOP_DOWN_PED){\n\t\t\tswitchByJumpCut = true;\n\t\t}\n\t\t// Going from top down to vehicle\n\t\telse if(ReqMode == CCam::MODE_CAM_ON_A_STRING || ReqMode == CCam::MODE_BEHINDBOAT){\n\t\t\tif(Cams[ActiveCam].Mode == CCam::MODE_TOPDOWN ||\n\t\t\t   Cams[ActiveCam].Mode == CCam::MODE_1STPERSON ||\n\t\t\t   Cams[ActiveCam].Mode == CCam::MODE_TOP_DOWN_PED)\n\t\t\t\tswitchByJumpCut = true;\n\t\t}else if(ReqMode == CCam::MODE_FIXED){\n\t\t\tif(Cams[ActiveCam].Mode == CCam::MODE_TOPDOWN)\n\t\t\t\tswitchByJumpCut = true;\n\t\t}\n\n\t\t// Going into Syphon mode\n\t\tif(ReqMode == CCam::MODE_SYPHON || ReqMode == CCam::MODE_SYPHON_CRIM_IN_FRONT)\n\t\t\tswitchByJumpCut = true;\n\n\t\t// Top down modes can interpolate between each other\n\t\tif(ReqMode == CCam::MODE_TOPDOWN){\n\t\t\tif(Cams[ActiveCam].Mode == CCam::MODE_TOP_DOWN_PED || Cams[ActiveCam].Mode == CCam::MODE_PED_DEAD_BABY)\n\t\t\t\tswitchByJumpCut = false;\n\t\t}else if(ReqMode == CCam::MODE_TOP_DOWN_PED){\n\t\t\tif(Cams[ActiveCam].Mode == CCam::MODE_TOPDOWN || Cams[ActiveCam].Mode == CCam::MODE_PED_DEAD_BABY)\n\t\t\t\tswitchByJumpCut = false;\n\t\t}\n\n\t\tif(ReqMode == CCam::MODE_1STPERSON || ReqMode == CCam::MODE_M16_1STPERSON ||\n\t\t   ReqMode == CCam::MODE_SNIPER || ReqMode == CCam::MODE_ROCKETLAUNCHER ||\n\t\t   ReqMode == CCam::MODE_SNIPER_RUNABOUT || ReqMode == CCam::MODE_ROCKETLAUNCHER_RUNABOUT ||\n\t\t   ReqMode == CCam::MODE_1STPERSON_RUNABOUT || ReqMode == CCam::MODE_M16_1STPERSON_RUNABOUT ||\n\t\t   ReqMode == CCam::MODE_FIGHT_CAM_RUNABOUT ||\n\t\t   ReqMode == CCam::MODE_HELICANNON_1STPERSON || ReqMode == CCam::MODE_CAMERA ||\n\t\t   ReqMode == CCam::MODE_ARRESTCAM_ONE || ReqMode == CCam::MODE_ARRESTCAM_TWO){\n\t\t\t// Going into any 1st person mode is a jump cut\n\t\t\tif(pTargetEntity->IsPed())\n\t\t\t\tswitchByJumpCut = true;\n\t\t}else if(ReqMode == CCam::MODE_FIXED && m_bPlayerIsInGarage){\n\t\t\t// Going from 1st peron mode into garage\n\t\t\tif(Cams[ActiveCam].Mode == CCam::MODE_SNIPER ||\n\t\t\t   Cams[ActiveCam].Mode == CCam::MODE_HELICANNON_1STPERSON ||\n\t\t\t   Cams[ActiveCam].Mode == CCam::MODE_ROCKETLAUNCHER ||\n\t\t\t   Cams[ActiveCam].Mode == CCam::MODE_M16_1STPERSON ||\n\t\t\t   Cams[ActiveCam].Mode == CCam::MODE_TOP_DOWN_PED ||\n\t\t\t   stairs ||\n\t\t\t   Cams[ActiveCam].Mode == CCam::MODE_1STPERSON ||\n\t\t\t   Cams[ActiveCam].Mode == CCam::MODE_SNIPER_RUNABOUT ||\n\t\t\t   Cams[ActiveCam].Mode == CCam::MODE_ROCKETLAUNCHER_RUNABOUT ||\n\t\t\t   Cams[ActiveCam].Mode == CCam::MODE_M16_1STPERSON_RUNABOUT ||\n\t\t\t   Cams[ActiveCam].Mode == CCam::MODE_FIGHT_CAM_RUNABOUT ||\n\t\t\t   Cams[ActiveCam].Mode == CCam::MODE_1STPERSON_RUNABOUT ||\n\t\t\t   Cams[ActiveCam].Mode == CCam::MODE_CAMERA){\n\t\t\t\tif(pTargetEntity && pTargetEntity->IsVehicle())\n\t\t\t\t\tswitchByJumpCut = true;\n\t\t\t}\n\t\t}else if(ReqMode == CCam::MODE_FOLLOWPED){\n\t\t\tbool syphonJumpCut = false;\n\t\t\tif(Cams[ActiveCam].Mode == CCam::MODE_SYPHON || Cams[ActiveCam].Mode == CCam::MODE_SYPHON_CRIM_IN_FRONT)\n\t\t\t\tif(!((CPed*)pTargetEntity)->CanWeRunAndFireWithWeapon())\n\t\t\t\t\tsyphonJumpCut = true;\n\t\t\tif(Cams[ActiveCam].Mode == CCam::MODE_1STPERSON ||\n\t\t\t   Cams[ActiveCam].Mode == CCam::MODE_SNIPER ||\n\t\t\t   Cams[ActiveCam].Mode == CCam::MODE_ROCKETLAUNCHER ||\n\t\t\t   Cams[ActiveCam].Mode == CCam::MODE_ARRESTCAM_ONE ||\n\t\t\t   Cams[ActiveCam].Mode == CCam::MODE_ARRESTCAM_TWO ||\n\t\t\t   Cams[ActiveCam].Mode == CCam::MODE_M16_1STPERSON ||\n\t\t\t   Cams[ActiveCam].Mode == CCam::MODE_PED_DEAD_BABY ||\n\t\t\t   Cams[ActiveCam].Mode == CCam::MODE_PILLOWS_PAPS ||\n\t\t\t   Cams[ActiveCam].Mode == CCam::MODE_SNIPER_RUNABOUT ||\n\t\t\t   Cams[ActiveCam].Mode == CCam::MODE_ROCKETLAUNCHER_RUNABOUT ||\n\t\t\t   Cams[ActiveCam].Mode == CCam::MODE_1STPERSON_RUNABOUT ||\n\t\t\t   Cams[ActiveCam].Mode == CCam::MODE_M16_1STPERSON_RUNABOUT ||\n\t\t\t   Cams[ActiveCam].Mode == CCam::MODE_FIGHT_CAM_RUNABOUT ||\n\t\t\t   Cams[ActiveCam].Mode == CCam::MODE_HELICANNON_1STPERSON ||\n\t\t\t   Cams[ActiveCam].Mode == CCam::MODE_CAMERA ||\n\t\t\t   Cams[ActiveCam].Mode == CCam::MODE_TOPDOWN ||\n\t\t\t   Cams[ActiveCam].Mode == CCam::MODE_TOP_DOWN_PED ||\n\t\t\t   syphonJumpCut || stopArrestCam){\n\t\t\t\tif(!m_bJustCameOutOfGarage){\n\t\t\t\t\tif(Cams[ActiveCam].Mode == CCam::MODE_1STPERSON ||\n\t\t\t\t\t   Cams[ActiveCam].Mode == CCam::MODE_SNIPER ||\n\t\t\t\t\t   Cams[ActiveCam].Mode == CCam::MODE_ROCKETLAUNCHER ||\n\t\t\t\t\t   Cams[ActiveCam].Mode == CCam::MODE_M16_1STPERSON ||\n\t\t\t\t\t   Cams[ActiveCam].Mode == CCam::MODE_SNIPER_RUNABOUT ||\n\t\t\t\t\t   Cams[ActiveCam].Mode == CCam::MODE_ROCKETLAUNCHER_RUNABOUT ||\n\t\t\t\t\t   Cams[ActiveCam].Mode == CCam::MODE_1STPERSON_RUNABOUT ||\n\t\t\t\t\t   Cams[ActiveCam].Mode == CCam::MODE_M16_1STPERSON_RUNABOUT ||\n\t\t\t\t\t   Cams[ActiveCam].Mode == CCam::MODE_FIGHT_CAM_RUNABOUT ||\n\t\t\t\t\t   Cams[ActiveCam].Mode == CCam::MODE_HELICANNON_1STPERSON ||\n\t\t\t\t\t   Cams[ActiveCam].Mode == CCam::MODE_CAMERA){\n\t\t\t\t\t\tfloat angle = CGeneral::GetATanOfXY(Cams[ActiveCam].Front.x, Cams[ActiveCam].Front.y) - HALFPI;\n\t\t\t\t\t\t((CPed*)pTargetEntity)->m_fRotationCur = angle;\n\t\t\t\t\t\t((CPed*)pTargetEntity)->m_fRotationDest = angle;\n\t\t\t\t\t}\n\t\t\t\t\tm_bUseTransitionBeta = true;\n\t\t\t\t\tswitchByJumpCut = true;\n\t\t\t\t\tif(Cams[ActiveCam].Mode == CCam::MODE_TOP_DOWN_PED){\n\t\t\t\t\t\tCVector front = Cams[ActiveCam].Source - FindPlayerPed()->GetPosition();\n\t\t\t\t\t\tfront.z = 0.0f;\n\t\t\t\t\t\tfront.Normalise();\n#ifdef FIX_BUGS\n\t\t\t\t\t\t// this is almost as bad as the bugged code\n\t\t\t\t\t\tif(front.x == 0.001f && front.y == 0.001f)\n\t\t\t\t\t\t\tfront.y = 1.0f;\n#else\n\t\t\t\t\t\t// someone used = instead of == in the above check by accident\n\t\t\t\t\t\tfront.x = 0.001f;\n\t\t\t\t\t\tfront.y = 1.0f;\n#endif\n\t\t\t\t\t\tCams[ActiveCam].m_fTransitionBeta = CGeneral::GetATanOfXY(front.x, front.y);\n\t\t\t\t\t}else\n\t\t\t\t\t\tCams[ActiveCam].m_fTransitionBeta = CGeneral::GetATanOfXY(Cams[ActiveCam].Front.x, Cams[ActiveCam].Front.y) + PI;\n\t\t\t\t}\n\t\t\t}\n\t\t}else if(ReqMode == CCam::MODE_FIGHT_CAM){\n\t\t\tif(Cams[ActiveCam].Mode == CCam::MODE_1STPERSON)\n\t\t\t\tswitchByJumpCut = true;\n\t\t}else if(ReqMode == CCam::MODE_LIGHTHOUSE ||\n\t\t         ReqMode == CCam::MODE_ARRESTCAM_ONE || ReqMode == CCam::MODE_ARRESTCAM_TWO ||\n\t\t         ReqMode == CCam::MODE_PED_DEAD_BABY)\n\t\t\tswitchByJumpCut = true;\n\t\telse if(Cams[ActiveCam].Mode == CCam::MODE_PED_DEAD_BABY && ReqMode != CCam::MODE_PED_DEAD_BABY)\n\t\t\tswitchByJumpCut = true;\n\n\t\tif(ReqMode != Cams[ActiveCam].Mode && Cams[ActiveCam].CamTargetEntity == nil)\n\t\t\tswitchByJumpCut = true;\n\t\tif(m_bPlayerIsInGarage && pToGarageWeAreIn){\n\t\t\tif(pToGarageWeAreIn->m_eGarageType == GARAGE_BOMBSHOP1 ||\n\t\t\t   pToGarageWeAreIn->m_eGarageType == GARAGE_BOMBSHOP2 ||\n\t\t\t   pToGarageWeAreIn->m_eGarageType == GARAGE_BOMBSHOP3){\n\t\t\t\tif(pTargetEntity->IsVehicle() && pTargetEntity->GetModelIndex() == MI_MRWHOOP &&\n\t\t\t\t   ReqMode != Cams[ActiveCam].Mode)\n\t\t\t\t\tswitchByJumpCut = true;\n\t\t\t}\n\t\t}\n#ifdef GTA_SCENE_EDIT\n\t\tif(CSceneEdit::m_bEditOn)\n\t\t\tReqMode = CCam::MODE_EDITOR;\n#endif\n\n\t\tif((m_uiTransitionState == 0 || switchByJumpCut) && ReqMode != Cams[ActiveCam].Mode){\n\t\t\tif(switchByJumpCut){\n\t\t\t\tif(!m_bPlayerIsInGarage || m_bJustCameOutOfGarage){\n\t\t\t\t\tif(ReqMode != CCam::MODE_FOLLOWPED &&\n\t\t\t\t\t   ReqMode != CCam::MODE_M16_1STPERSON &&\n\t\t\t\t\t   ReqMode != CCam::MODE_SNIPER &&\n\t\t\t\t\t   ReqMode != CCam::MODE_ROCKETLAUNCHER &&\n\t\t\t\t\t   !m_bUseMouse3rdPerson)\n\t\t\t\t\t\tSetCameraDirectlyBehindForFollowPed_CamOnAString();\n\t\t\t\t}\n\t\t\t\tCams[ActiveCam].Mode = ReqMode;\n\t\t\t\tm_bJust_Switched = true;\n\t\t\t\tCams[ActiveCam].m_cvecCamFixedModeVector = m_vecFixedModeVector;\n\t\t\t\tCams[ActiveCam].CamTargetEntity = pTargetEntity;\n\t\t\t\tCams[ActiveCam].m_cvecCamFixedModeSource = m_vecFixedModeSource;\n\t\t\t\tCams[ActiveCam].m_cvecCamFixedModeUpOffSet = m_vecFixedModeUpOffSet;\n\t\t\t\tCams[ActiveCam].m_bCamLookingAtVector = m_bLookingAtVector;\n\t\t\t\tCams[ActiveCam].m_vecLastAboveWaterCamPosition = Cams[(ActiveCam+1)%2].m_vecLastAboveWaterCamPosition;\n\t\t\t\tCarZoomValueSmooth = CarZoomValue;\n\t\t\t\tm_fPedZoomValueSmooth = m_fPedZoomValue;\n\t\t\t\tm_uiTransitionState = 0;\n\t\t\t\tm_vecDoingSpecialInterPolation = false;\n\t\t\t\tm_bStartInterScript = false;\n\t\t\t\tCams[ActiveCam].ResetStatics = true;\n\n\t\t\t\tpTargetEntity->RegisterReference(&pTargetEntity);\n\t\t\t\tCams[ActiveCam].CamTargetEntity->RegisterReference(&Cams[ActiveCam].CamTargetEntity);\n\t\t\t}else if(!m_bWaitForInterpolToFinish){\n\t\t\t\tStartTransition(ReqMode);\n\t\t\t\tpTargetEntity->RegisterReference(&pTargetEntity);\n\t\t\t\tCams[ActiveCam].CamTargetEntity->RegisterReference(&Cams[ActiveCam].CamTargetEntity);\n\t\t\t}\n\t\t}else if(m_uiTransitionState != 0 && ReqMode != Cams[ActiveCam].Mode){\n\t\t\tbool startTransition = true;\n\n\t\t\tif(ReqMode == CCam::MODE_FIGHT_CAM || Cams[ActiveCam].Mode == CCam::MODE_FIGHT_CAM)\n\t\t\t\tstartTransition = false;\n\t\t\tif(ReqMode == CCam::MODE_FOLLOWPED && Cams[ActiveCam].Mode == CCam::MODE_FIGHT_CAM)\n\t\t\t\tstartTransition = false;\n\n\t\t\tif(!m_bWaitForInterpolToFinish && m_bLookingAtPlayer && m_uiTransitionState != 0){\n\t\t\t\tCVector playerDist;\n\t\t\t\tplayerDist.x = FindPlayerPed()->GetPosition().x - GetPosition().x;\n\t\t\t\tplayerDist.y = FindPlayerPed()->GetPosition().y - GetPosition().y;\n\t\t\t\tplayerDist.z = FindPlayerPed()->GetPosition().z - GetPosition().z;\n\t\t\t\t// if player is too far away, keep interpolating and don't transition\n\t\t\t\tif(pTargetEntity && pTargetEntity->IsPed()){\n\t\t\t\t\tif(playerDist.Magnitude() > 17.5f &&\n\t\t\t\t\t   (ReqMode == CCam::MODE_SYPHON || ReqMode == CCam::MODE_SYPHON_CRIM_IN_FRONT))\n\t\t\t\t\t\tm_bWaitForInterpolToFinish = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif(m_bWaitForInterpolToFinish)\n\t\t\t\tstartTransition = false;\n\n\t\t\tif(startTransition){\n\t\t\t\tStartTransitionWhenNotFinishedInter(ReqMode);\n\t\t\t\tpTargetEntity->RegisterReference(&pTargetEntity);\n\t\t\t\tCams[ActiveCam].CamTargetEntity->RegisterReference(&Cams[ActiveCam].CamTargetEntity);\n\t\t\t}\n\t\t}else if(ReqMode == CCam::MODE_FIXED && pTargetEntity != Cams[ActiveCam].CamTargetEntity && m_bPlayerIsInGarage){\n\t\t\tif(m_uiTransitionState != 0)\n\t\t\t\tStartTransitionWhenNotFinishedInter(ReqMode);\n\t\t\telse\n\t\t\t\tStartTransition(ReqMode);\n\t\t\tpTargetEntity->RegisterReference(&pTargetEntity);\n\t\t\tCams[ActiveCam].CamTargetEntity->RegisterReference(&Cams[ActiveCam].CamTargetEntity);\n\t\t}\n\t}else{\n\t\t// not following player\n\t\tbool useWeaponMode = false;\n\t\tbool jumpCutTo1stPrs = false;\n\t\tif(m_bEnable1rstPersonCamCntrlsScript || m_bAllow1rstPersonWeaponsCamera){\n\t\t\tif(ReqMode == CCam::MODE_1STPERSON){\n\t\t\t\tif(Cams[ActiveCam].Mode != ReqMode)\n\t\t\t\t\tjumpCutTo1stPrs = true;\n\t\t\t}else if((PlayerWeaponMode.Mode == CCam::MODE_SNIPER || PlayerWeaponMode.Mode == CCam::MODE_1STPERSON || PlayerWeaponMode.Mode == CCam::MODE_ROCKETLAUNCHER) &&\n\t\t\t         CPad::GetPad(0)->GetTarget() && m_bAllow1rstPersonWeaponsCamera){\n\t\t\t\tuseWeaponMode = true;\n\t\t\t\tjumpCutTo1stPrs = true;\n\t\t\t}else if(Cams[ActiveCam].Mode != m_iModeToGoTo){\n\t\t\t\tm_bStartInterScript = true;\n\t\t\t\tm_iTypeOfSwitch = JUMP_CUT;\n\t\t\t\tCPad::GetPad(0)->DisablePlayerControls &= ~PLAYERCONTROL_CAMERA;\n\t\t\t}\n\t\t}\n\n\t\tif(m_uiTransitionState == 0 && m_bStartInterScript && m_iTypeOfSwitch == INTERPOLATION){\n\t\t\tReqMode = m_iModeToGoTo;\n\t\t\tStartTransition(ReqMode);\n\t\t\tpTargetEntity->RegisterReference(&pTargetEntity);\n\t\t\tCams[ActiveCam].CamTargetEntity->RegisterReference(&Cams[ActiveCam].CamTargetEntity);\n\t\t}else if(m_uiTransitionState != 0 && m_bStartInterScript && m_iTypeOfSwitch == INTERPOLATION){\n\t\t\tReqMode = m_iModeToGoTo;\n\t\t\tStartTransitionWhenNotFinishedInter(ReqMode);\n\t\t\tpTargetEntity->RegisterReference(&pTargetEntity);\n\t\t\tCams[ActiveCam].CamTargetEntity->RegisterReference(&Cams[ActiveCam].CamTargetEntity);\n\t\t}else if(m_bStartInterScript && m_iTypeOfSwitch == JUMP_CUT || jumpCutTo1stPrs){\n\t\t\tm_uiTransitionState = 0;\n\t\t\tm_vecDoingSpecialInterPolation = false;\n\t\t\tif(m_bEnable1rstPersonCamCntrlsScript && ReqMode == CCam::MODE_1STPERSON)\n\t\t\t\tCams[ActiveCam].Mode = ReqMode;\n\t\t\telse if(useWeaponMode)\n\t\t\t\tCams[ActiveCam].Mode = PlayerWeaponMode.Mode;\n\t\t\telse\n\t\t\t\tCams[ActiveCam].Mode = m_iModeToGoTo;\n\t\t\tm_bJust_Switched = true;\n\t\t\tCams[ActiveCam].ResetStatics = true;\n\t\t\tCams[ActiveCam].m_cvecCamFixedModeVector = m_vecFixedModeVector;\n\t\t\tCams[ActiveCam].CamTargetEntity = pTargetEntity;\n\t\t\tCams[ActiveCam].m_cvecCamFixedModeSource = m_vecFixedModeSource;\n\t\t\tCams[ActiveCam].m_cvecCamFixedModeUpOffSet = m_vecFixedModeUpOffSet;\n\t\t\tCams[ActiveCam].m_bCamLookingAtVector = m_bLookingAtVector;\n\t\t\tCams[ActiveCam].m_vecLastAboveWaterCamPosition = Cams[(ActiveCam+1)%2].m_vecLastAboveWaterCamPosition;\n\t\t\tm_bJust_Switched = true;\n\t\t\tpTargetEntity->RegisterReference(&pTargetEntity);\n\t\t\tCams[ActiveCam].CamTargetEntity->RegisterReference(&Cams[ActiveCam].CamTargetEntity);\n\t\t\tCarZoomValueSmooth = CarZoomValue;\n\t\t\tm_fPedZoomValueSmooth = m_fPedZoomValue;\n\t\t}\n\t}\n\n\tm_bStartInterScript = false;\n\n\tif(Cams[ActiveCam].CamTargetEntity == nil)\n\t\tCams[ActiveCam].CamTargetEntity = pTargetEntity;\n\n\t// Ped visibility\n\tif((Cams[ActiveCam].Mode == CCam::MODE_1STPERSON ||\n\t    Cams[ActiveCam].Mode == CCam::MODE_SNIPER ||\n\t    Cams[ActiveCam].Mode == CCam::MODE_M16_1STPERSON ||\n\t    Cams[ActiveCam].Mode == CCam::MODE_ROCKETLAUNCHER ||\n\t    Cams[ActiveCam].Mode == CCam::MODE_HELICANNON_1STPERSON ||\n\t    Cams[ActiveCam].Mode == CCam::MODE_CAMERA) && pTargetEntity->IsPed() ||\n\t   Cams[ActiveCam].Mode == CCam::MODE_FLYBY)\n\t\tFindPlayerPed()->bIsVisible = false;\n\telse\n\t\tFindPlayerPed()->bIsVisible = true;\n\n\tbool switchedFromObbe = false;\n\tif(!canUseObbeCam && WhoIsInControlOfTheCamera == CAMCONTROL_OBBE){\n\t\tRestoreWithJumpCut();\n\t\tswitchedFromObbe = true;\n\t\tSetCameraDirectlyBehindForFollowPed_CamOnAString();\n\t}\n\n\tif(PrevMode != Cams[ActiveCam].Mode || switchedFromObbe ||\n\t   Cams[ActiveCam].Mode == CCam::MODE_FOLLOWPED || Cams[ActiveCam].Mode == CCam::MODE_CAM_ON_A_STRING)\n\t\tif(CPad::GetPad(0)->CycleCameraModeJustDown() &&\n\t\t   !CReplay::IsPlayingBack() &&\n\t\t   (m_bLookingAtPlayer || WhoIsInControlOfTheCamera == CAMCONTROL_OBBE) &&\n\t\t   !m_WideScreenOn &&\n\t\t   (WhoIsInControlOfTheCamera != CAMCONTROL_OBBE || bSwitchedToObbeCam))\n\t\t\tDMAudio.PlayFrontEndSound(SOUND_HUD, 0);\n}\n\n// What a mess!\nvoid\nCCamera::UpdateTargetEntity(void)\n{\n\tbool enteringCar = false;\n\tbool obbeCam = false;\n\n\tm_bPlayerWasOnBike = false;\n\tif(pTargetEntity && pTargetEntity->IsVehicle() && ((CVehicle*)pTargetEntity)->IsBike())\n\t\tm_bPlayerWasOnBike = true;\n\n\tif(WhoIsInControlOfTheCamera == CAMCONTROL_OBBE){\n\t\tobbeCam = true;\n\t\tif(m_iModeObbeCamIsInForCar == OBBE_COPCAR_WHEEL || m_iModeObbeCamIsInForCar == OBBE_COPCAR){\n\t\t\tif(FindPlayerPed()->GetPedState() != PED_ARRESTED)\n\t\t\t\tobbeCam = false;\n\t\t\tif(FindPlayerVehicle() == nil)\n\t\t\t\tpTargetEntity = FindPlayerPed();\n\t\t}\n\t}\n\n\tif((m_bLookingAtPlayer || obbeCam) && m_uiTransitionState == 0 ||\n\t   pTargetEntity == nil ||\n\t   m_bTargetJustBeenOnTrain){\n\t\tif(FindPlayerVehicle())\n\t\t\tpTargetEntity = FindPlayerVehicle();\n\t\telse{\n\t\t\tpTargetEntity = FindPlayerPed();\n\t\t\t// this keeps the camera on the player while entering cars\n\t\t\tif(PLAYER->GetPedState() == PED_ENTER_CAR ||\n\t\t\t   PLAYER->GetPedState() == PED_CARJACK ||\n\t\t\t   PLAYER->GetPedState() == PED_OPEN_DOOR)\n\t\t\t\tenteringCar = true;\n\n\t\t\tif(!enteringCar)\n\t\t\t\tif(Cams[ActiveCam].CamTargetEntity != pTargetEntity)\n\t\t\t\t\tCams[ActiveCam].CamTargetEntity = pTargetEntity;\n\t\t}\n\n\t\tbool cantOpen = true;\n\t\tif(PLAYER){\n\t\t\tif(PLAYER->m_pMyVehicle){\n\t\t\t\tif(FindPlayerPed()->m_pMyVehicle->CanPedOpenLocks(PLAYER))\n\t\t\t\t\tcantOpen = false;\n\t\t\t}else if(FindPlayerPed()->m_carInObjective &&\n\t\t\t         (FindPlayerPed()->GetPedState() == PED_ENTER_CAR ||\n\t\t\t          FindPlayerPed()->GetPedState() == PED_CARJACK ||\n\t\t\t          FindPlayerPed()->GetPedState() == PED_OPEN_DOOR)){\n\t\t\t\tif(FindPlayerPed()->m_carInObjective->CanPedOpenLocks(FindPlayerPed()))\n\t\t\t\t\tcantOpen = false;\n\t\t\t}\n\t\t}\n\n\t\tif(PLAYER->GetPedState() == PED_ENTER_CAR && !cantOpen){\n\t\t\tif(!enteringCar && CarZoomIndicator != CAM_ZOOM_1STPRS){\n\t\t\t\tpTargetEntity = PLAYER->m_pMyVehicle;\n\t\t\t\tif(PLAYER->m_pMyVehicle == nil)\n\t\t\t\t\tpTargetEntity = PLAYER;\n\t\t\t}\n\t\t}\n\n\t\tif((PLAYER->GetPedState() == PED_CARJACK || PLAYER->GetPedState() == PED_OPEN_DOOR) && !cantOpen){\n\t\t\tif(!enteringCar && CarZoomIndicator != CAM_ZOOM_1STPRS)\n\t\t\t\tpTargetEntity = PLAYER->m_pMyVehicle;\n\t\t\tif(PLAYER->m_pMyVehicle == nil)\n\t\t\t\tpTargetEntity = PLAYER;\n\t\t}\n\n\t\tif(PLAYER->GetPedState() == PED_EXIT_CAR)\n\t\t\tpTargetEntity = FindPlayerPed();\n\t\tif(PLAYER->GetPedState() == PED_DRAG_FROM_CAR)\n\t\t\tpTargetEntity = FindPlayerPed();\n\t\tif(pTargetEntity->IsVehicle() && CarZoomIndicator == CAM_ZOOM_1STPRS && FindPlayerPed()->GetPedState() == PED_ARRESTED)\n\t\t\tpTargetEntity = FindPlayerPed();\n\t}\n}\n\nconst float SOUND_DIST = 20.0f;\n\nvoid\nCCamera::UpdateSoundDistances(void)\n{\n\tCVector center, end;\n\tCEntity *entity;\n\tCColPoint colPoint;\n\tfloat f;\n\tint n;\n\n\tif((Cams[ActiveCam].Mode == CCam::MODE_1STPERSON ||\n\t    Cams[ActiveCam].Mode == CCam::MODE_SNIPER ||\n\t    Cams[ActiveCam].Mode == CCam::MODE_SNIPER_RUNABOUT ||\n\t    Cams[ActiveCam].Mode == CCam::MODE_ROCKETLAUNCHER_RUNABOUT ||\n\t    Cams[ActiveCam].Mode == CCam::MODE_1STPERSON_RUNABOUT ||\n\t    Cams[ActiveCam].Mode == CCam::MODE_M16_1STPERSON_RUNABOUT ||\n\t    Cams[ActiveCam].Mode == CCam::MODE_FIGHT_CAM_RUNABOUT ||\n\t    Cams[ActiveCam].Mode == CCam::MODE_HELICANNON_1STPERSON ||\n\t    Cams[ActiveCam].Mode == CCam::MODE_CAMERA ||\n\t    Cams[ActiveCam].Mode == CCam::MODE_M16_1STPERSON ||\n\t    Cams[ActiveCam].Mode == CCam::MODE_ROCKETLAUNCHER) &&\n\t   pTargetEntity->IsPed())\n\t\tcenter = GetPosition() + 0.5f*GetForward();\n\telse\n\t\tcenter = GetPosition() + 5.0f*GetForward();\n\n\t// check up\n\tn = CTimer::GetFrameCounter() % 12;\n\tif(n == 0){\n\t\tSoundDistUpAsReadOld = SoundDistUpAsRead;\n\t\tif(CWorld::ProcessVerticalLine(center, center.z+SOUND_DIST, colPoint, entity, true, false, false, false, true, false, nil))\n\t\t\tSoundDistUpAsRead = colPoint.point.z - center.z;\n\t\telse\n\t\t\tSoundDistUpAsRead = SOUND_DIST;\n\t}\n\tf = (n + 1) / 6.0f;\n\tSoundDistUp = (1.0f-f)*SoundDistUpAsReadOld + f*SoundDistUpAsRead;\n}\n\nvoid\nCCamera::InitialiseCameraForDebugMode(void)\n{\n\tif(FindPlayerVehicle())\n\t\tCams[2].Source = FindPlayerVehicle()->GetPosition();\n\telse if(FindPlayerPed())\n\t\tCams[2].Source = FindPlayerPed()->GetPosition();\n\tCams[2].Alpha = 0.0f;\n\tCams[2].Beta = 0.0f;\n\tCams[2].Mode = CCam::MODE_DEBUG;\n}\n\nvoid\nCCamera::CamShake(float strength, float x, float y, float z)\n{\n\tCVector Dist = Cams[ActiveCam].Source - CVector(x, y, z);\n\t// a bit complicated...\n\tfloat dist2d = Sqrt(SQR(Dist.x) + SQR(Dist.y));\n\tfloat dist3d = Sqrt(SQR(dist2d) + SQR(Dist.z));\n\tif(dist3d > 100.0f) dist3d = 100.0f;\n\tif(dist3d < 0.0f) dist3d = 0.0f;\n\tfloat mult = 1.0f - dist3d/100.0f;\n\n\tfloat curForce = mult*(m_fCamShakeForce - (CTimer::GetTimeInMilliseconds() - m_uiCamShakeStart)/1000.0f);\n\tstrength = mult*strength;\n\tif(clamp(curForce, 0.0f, 2.0f) < strength){\n\t\tm_fCamShakeForce = strength;\n\t\tm_uiCamShakeStart = CTimer::GetTimeInMilliseconds();\n\t}\n}\n\n// This seems to be CCamera::CamShake(float) on PS2\nvoid\nCamShakeNoPos(CCamera *cam, float strength)\n{\n\tfloat curForce = cam->m_fCamShakeForce - (CTimer::GetTimeInMilliseconds() - cam->m_uiCamShakeStart)/1000.0f;\n\tif(clamp(curForce, 0.0f, 2.0f) < strength){\n\t\tcam->m_fCamShakeForce = strength;\n\t\tcam->m_uiCamShakeStart = CTimer::GetTimeInMilliseconds();\n\t}\n}\n\nbool bAvoidTest1 = false;\nbool bAvoidTest2 = false;\t// unused\nbool bAvoidTest3 = false;\t// unused\nfloat fRangePlayerRadius = 0.5f;\nfloat fCloseNearClipLimit = 0.15f;\nfloat fAvoidTweakFOV = 1.15f;\nfloat fAvoidProbTimerDamp = 0.9f;\n\nvoid\nCCamera::AvoidTheGeometry(const CVector &Source, const CVector &TargetPos, CVector &NewSource, float FOV)\n{\n\tfloat Beta = 0.0f;\n\tfloat Alpha = 0.0f;\n\n\tCVector vDist = TargetPos - Source;\n\tm_vecClearGeometryVec = CVector(0.0f, 0.0f, 0.0f);\n\tfloat fDist = vDist.Magnitude();\n\tfloat fDistOnGround = vDist.Magnitude2D();\n\tif(vDist.x == 0.0f && vDist.y == 0.0f)\n\t\tBeta = CGeneral::GetATanOfXY(GetForward().x, GetForward().y);\n\telse\n\t\tBeta = CGeneral::GetATanOfXY(vDist.x, vDist.y);\n\tif(fDistOnGround != 0.0f || vDist.z != 0.0f)\n\t\tAlpha = CGeneral::GetATanOfXY(fDistOnGround, vDist.z);\n\tCVector Front(Cos(Alpha)*Cos(Beta), Cos(Alpha)*Sin(Beta), Sin(Alpha));\n\tNewSource = TargetPos - Front*fDist;\n\tFront.Normalise();\n\n\t// Clip camera source\n\tCColPoint point;\n\tCEntity *entity = nil;\n\tCWorld::pIgnoreEntity = pTargetEntity;\n\tif(CWorld::ProcessLineOfSight(TargetPos, NewSource, point, entity, true, false, false, true, false, false, true)){\n\t\tCVector ClipPoint1 = point.point;\n\t\tNewSource = point.point;\n\t\tif(!bAvoidTest1){\n\t\t\tif(CWorld::ProcessLineOfSight(NewSource, TargetPos, point, entity, false, true, true, true, false, false, true)){\n\t\t\t\tif((NewSource - point.point).Magnitude() < RwCameraGetNearClipPlane(Scene.camera))\n\t\t\t\t\tNewSource = point.point;\n\t\t\t\telse if((NewSource - ClipPoint1).Magnitude() < RwCameraGetNearClipPlane(Scene.camera))\n\t\t\t\t\tNewSource = ClipPoint1;\n\t\t\t}\n\t\t}\n\t}\n\tCWorld::pIgnoreEntity = nil;\n\n\n\tvDist = TargetPos - NewSource;\n\tfDist = vDist.Magnitude();\n\tif(FindPlayerPed())\n\t\tif(fDist - fRangePlayerRadius < RwCameraGetNearClipPlane(Scene.camera))\n\t\t\tRwCameraSetNearClipPlane(Scene.camera, Max(fDist - fRangePlayerRadius, fCloseNearClipLimit));\n\n\n\tstatic float fClearGeomAmount;\n\tstatic float fClearGeomAmountSpeed;\n\tfloat Near = RwCameraGetNearClipPlane(Scene.camera);\n\tfloat ViewPlaneHeight = Tan(DEGTORAD(FOV) / 2.0f);\n\tfloat ViewPlaneWidth = ViewPlaneHeight * CDraw::CalculateAspectRatio() * fAvoidTweakFOV;\n\tCVector Center = NewSource + Front*Near;\n\tfloat fClearGeomTarget = 0.0f;\n\tif(CWorld::TestSphereAgainstWorld(Center, ViewPlaneWidth, nil, true, false, false, true, false, true)){\n\t\tCVector CamToCol = gaTempSphereColPoints[0].point - NewSource;\n\t\tfloat FrontDist = DotProduct(CamToCol, Front);\n\t\tCVector CenterToCol = gaTempSphereColPoints[0].point - Center;\n\t\tif(FrontDist < DEFAULT_NEAR && FrontDist > fCloseNearClipLimit){\n\t\t\tif(FrontDist < RwCameraGetNearClipPlane(Scene.camera))\n\t\t\t\tRwCameraSetNearClipPlane(Scene.camera, FrontDist);\n\t\t}else if(FrontDist < fCloseNearClipLimit)\n\t\t\tRwCameraSetNearClipPlane(Scene.camera, fCloseNearClipLimit);\n\n\t\tfloat ColDepth = ViewPlaneWidth - CenterToCol.Magnitude();\t// amount of radius in collision\n\t\tCenterToCol.Normalise();\n\t\tCVector Normal = gaTempSphereColPoints[0].normal;\n\t\tNormal.Normalise();\n\t\tif(-DotProduct(CenterToCol, Normal) < 0.0f)\n\t\t\tNormal = -Normal;\t// always push away from col surface\n\t\tfloat DistToMove = DotProduct(-ColDepth*CenterToCol, Normal);\n\t\tm_vecClearGeometryVec = DistToMove*Normal;\t// move source so this point is out of collision\n\n\t\tif(pTargetEntity && pTargetEntity->IsPed() && RwCameraGetNearClipPlane(Scene.camera) < 2.0f*fCloseNearClipLimit){\n\t\t\tfloat TargetNormalDir = DotProduct(Normal, pTargetEntity->GetForward());\n\t\t\tif(TargetNormalDir < 0.0f){\n\t\t\t\t// target looking towards collision\n\t\t\t\tif(m_fAvoidTheGeometryProbsTimer < 0.0f)\n\t\t\t\t\tm_fAvoidTheGeometryProbsTimer = 0.0f;\n\t\t\t\tm_fAvoidTheGeometryProbsTimer += CTimer::GetTimeStep();\n\t\t\t}else if(TargetNormalDir > 0.5f){\n\t\t\t\t// target looking away from collision\n\t\t\t\tif(m_fAvoidTheGeometryProbsTimer > 0.0f)\n\t\t\t\t\tm_fAvoidTheGeometryProbsTimer = 0.0f;\n\t\t\t\tm_fAvoidTheGeometryProbsTimer -= CTimer::GetTimeStep();\n\t\t\t}\n\n\t\t\tif(m_nAvoidTheGeometryProbsDirn == 0){\n\t\t\t\tif(CrossProduct(pTargetEntity->GetPosition() - NewSource, Normal).z > 0.0f)\n\t\t\t\t\tm_nAvoidTheGeometryProbsDirn = -1;\n\t\t\t\telse\n\t\t\t\t\tm_nAvoidTheGeometryProbsDirn = 1;\n\t\t\t}\n\t\t}\n\n\t\tfClearGeomTarget = 1.0f;\n\t}\n\n\tm_fAvoidTheGeometryProbsTimer *= Pow(fAvoidProbTimerDamp, CTimer::GetTimeStep());\n\tWellBufferMe(fClearGeomTarget, &fClearGeomAmount, &fClearGeomAmountSpeed, 0.2f, 0.05f, false);\n\tm_vecClearGeometryVec *= fClearGeomAmount;\n\tm_bMoveCamToAvoidGeom = true;\n}\n\nvoid\nCCamera::GetArrPosForVehicleType(int apperance, int &index)\n{\n\tswitch(apperance){\n\tcase VEHICLE_APPEARANCE_CAR: index = 0; break;\n\tcase VEHICLE_APPEARANCE_BIKE: index = 1; break;\n\tcase VEHICLE_APPEARANCE_HELI: index = 2; break;\n\tcase VEHICLE_APPEARANCE_PLANE: index = 3; break;\n\tcase VEHICLE_APPEARANCE_BOAT: index = 4; break;\n\t}\n}\n\nvoid\nCCamera::GetScreenRect(CRect &rect)\n{\n\trect.left = 0.0f;\n\trect.right = SCREEN_WIDTH;\n\tif(m_WideScreenOn\n#ifdef CUTSCENE_BORDERS_SWITCH\n\t\t&& CMenuManager::m_PrefsCutsceneBorders\n#endif\n\t\t){\n\t\tfloat borderSize = (SCREEN_HEIGHT / 2) * (m_ScreenReductionPercentage / 100.f);\n\t\trect.top = borderSize - SCREEN_SCALE_Y(22.f);\n\t\trect.bottom = SCREEN_HEIGHT - borderSize - SCREEN_SCALE_Y(14.f);\n\t}else{\n\t\trect.top = 0.0f;\n\t\trect.bottom = SCREEN_HEIGHT;\n\t}\n}\n\n\nvoid\nCCamera::TakeControl(CEntity *target, int16 mode, int16 typeOfSwitch, int32 controller)\n{\n\tbool doSwitch = true;\n\tif(controller == CAMCONTROL_OBBE && WhoIsInControlOfTheCamera == CAMCONTROL_SCRIPT)\n\t\tdoSwitch = false;\n\tif(doSwitch){\n\t\tWhoIsInControlOfTheCamera = controller;\n\t\tif(target){\n\t\t\tif(mode == CCam::MODE_NONE){\n\t\t\t\t// Why are we checking the old entity?\n\t\t\t\tif(pTargetEntity->IsPed())\n\t\t\t\t\tmode = CCam::MODE_FOLLOWPED;\n\t\t\t\telse if(pTargetEntity->IsVehicle())\n\t\t\t\t\tmode = CCam::MODE_CAM_ON_A_STRING;\n\t\t\t}\n\t\t}else if(FindPlayerVehicle())\n\t\t\ttarget = FindPlayerVehicle();\n\t\telse\n\t\t\ttarget = PLAYER;\n\n\t\tm_bLookingAtVector = false;\n\t\tpTargetEntity = target;\n\t\tm_iModeToGoTo = mode;\n\t\tm_iTypeOfSwitch = typeOfSwitch;\n\t\tm_bLookingAtPlayer = false;\n\t\tm_bStartInterScript = true;\n\t}\n}\n\nvoid\nCCamera::TakeControlNoEntity(const CVector &position, int16 typeOfSwitch, int32 controller)\n{\n\tbool doSwitch = true;\n\tif(controller == CAMCONTROL_OBBE && WhoIsInControlOfTheCamera == CAMCONTROL_SCRIPT)\n\t\tdoSwitch = false;\n\tif(doSwitch){\n\t\tWhoIsInControlOfTheCamera = controller;\n\t\tm_bLookingAtVector = true;\n\t\tm_bLookingAtPlayer = false;\n\t\tm_iModeToGoTo = CCam::MODE_FIXED;\n\t\tm_vecFixedModeVector = position;\n\t\tm_iTypeOfSwitch = typeOfSwitch;\n\t\tm_bStartInterScript = true;\n\t}\n}\n\nvoid\nCCamera::TakeControlWithSpline(int16 typeOfSwitch)\n{\n\tm_iModeToGoTo = CCam::MODE_FLYBY;\n\tm_bLookingAtPlayer = false;\n\tm_bLookingAtVector = false;\n\tm_bcutsceneFinished = false;\n\tm_iTypeOfSwitch = typeOfSwitch;\n\tm_bStartInterScript = true;\n};\n\nvoid\nCCamera::Restore(void)\n{\n\tm_bLookingAtPlayer = true;\n\tm_bLookingAtVector = false;\n\tm_iTypeOfSwitch = INTERPOLATION;\n\tm_bUseNearClipScript = false;\n\tm_iModeObbeCamIsInForCar = OBBE_INVALID;\n\tm_fPositionAlongSpline = 0.0;\n\tm_bStartingSpline = false;\n\tm_bScriptParametersSetForInterPol = false;\n\tWhoIsInControlOfTheCamera = CAMCONTROL_GAME;\n\n\tif(FindPlayerVehicle()){\n\t\tm_iModeToGoTo = CCam::MODE_CAM_ON_A_STRING;\n\t\tpTargetEntity = FindPlayerVehicle();\n\t}else{\n\t\tm_iModeToGoTo = CCam::MODE_FOLLOWPED;\n\t\tpTargetEntity = PLAYER;\n\t}\n\n\tif(PLAYER->GetPedState() == PED_ENTER_CAR ||\n\t   PLAYER->GetPedState() == PED_CARJACK ||\n\t   PLAYER->GetPedState() == PED_OPEN_DOOR){\n\t\tm_iModeToGoTo = CCam::MODE_CAM_ON_A_STRING;\n\t\tpTargetEntity = PLAYER->m_pSeekTarget;\n\t}\n\tif(PLAYER->GetPedState() == PED_EXIT_CAR){\n\t\tm_iModeToGoTo = CCam::MODE_FOLLOWPED;\n\t\tpTargetEntity = PLAYER;\n\t}\n\n\tm_bEnable1rstPersonCamCntrlsScript = false;\n\tm_bAllow1rstPersonWeaponsCamera = false;\n\tm_bUseScriptZoomValuePed = false;\n\tm_bUseScriptZoomValueCar = false;\n\tm_bStartInterScript = true;\n\tm_bCameraJustRestored = true;\n\tm_fAvoidTheGeometryProbsTimer = 0.0f;\n}\n\nvoid\nCCamera::RestoreWithJumpCut(void)\n{\n\tm_bRestoreByJumpCut = true;\n\tm_bLookingAtPlayer = true;\n\tm_bLookingAtVector = false;\n\tm_iTypeOfSwitch = JUMP_CUT;\n\tm_bUseNearClipScript = false;\n\tm_iModeObbeCamIsInForCar = OBBE_INVALID;\n\tm_fPositionAlongSpline = 0.0;\n\tm_bStartingSpline = false;\n\tm_bScriptParametersSetForInterPol = false;\n\tWhoIsInControlOfTheCamera = CAMCONTROL_GAME;\n\tm_bCameraJustRestored = true;\n\tm_bEnable1rstPersonCamCntrlsScript = false;\n\tm_bAllow1rstPersonWeaponsCamera = false;\n\n\tif(FindPlayerVehicle()){\n\t\tm_iModeToGoTo = CCam::MODE_CAM_ON_A_STRING;\n\t\tpTargetEntity = FindPlayerVehicle();\n\t}else{\n\t\tm_iModeToGoTo = CCam::MODE_FOLLOWPED;\n\t\tpTargetEntity = PLAYER;\n\t}\n\n\tif(PLAYER->GetPedState() == PED_ENTER_CAR ||\n\t   PLAYER->GetPedState() == PED_CARJACK ||\n\t   PLAYER->GetPedState() == PED_OPEN_DOOR){\n\t\tm_iModeToGoTo = CCam::MODE_CAM_ON_A_STRING;\n\t\tpTargetEntity = PLAYER->m_pSeekTarget;\n\t}\n\tif(PLAYER->GetPedState() == PED_EXIT_CAR){\n\t\tm_iModeToGoTo = CCam::MODE_FOLLOWPED;\n\t\tpTargetEntity = PLAYER;\n\t}\n\n\tm_bUseScriptZoomValuePed = false;\n\tm_bUseScriptZoomValueCar = false;\n}\n\nvoid\nCCamera::SetCamPositionForFixedMode(const CVector &Source, const CVector &UpOffSet)\n{\n\tm_vecFixedModeSource = Source;\n\tm_vecFixedModeUpOffSet = UpOffSet;\n\tm_bGarageFixedCamPositionSet = false;\n}\n\n\nvoid\nCCamera::StartTransition(int16 newMode)\n{\n\tbool switchFromFixedSyphon = false;\n\tbool switchSyphonMode = false;\n\tbool switchPedMode = false;\n\tbool switchPedToCar = false;\n\tbool switchFromFight = false;\n\tbool switchBikeToPed = false;\n\tbool switchFromFixed = false;\n\tbool switch1stPersonToVehicle = false;\n\tfloat betaOffset, targetBeta, camBeta, deltaBeta;\n\tint door;\n\tbool vehicleVertical;\n\n\tm_bItsOkToLookJustAtThePlayer = false;\n\tm_fFractionInterToStopMoving = 0.25f;\n\tm_fFractionInterToStopCatchUp = 0.75f;\n\n\tif(Cams[ActiveCam].Mode == CCam::MODE_SYPHON_CRIM_IN_FRONT ||\n\t   Cams[ActiveCam].Mode == CCam::MODE_FOLLOWPED ||\n\t   Cams[ActiveCam].Mode == CCam::MODE_SYPHON ||\n\t   Cams[ActiveCam].Mode == CCam::MODE_SPECIAL_FIXED_FOR_SYPHON){\n\t\tif(newMode == CCam::MODE_SYPHON_CRIM_IN_FRONT ||\n\t\t   newMode == CCam::MODE_FOLLOWPED ||\n\t\t   newMode == CCam::MODE_SYPHON ||\n\t\t   newMode == CCam::MODE_SPECIAL_FIXED_FOR_SYPHON)\n\t\t\tswitchPedMode = true;\n\t\tif(newMode == CCam::MODE_CAM_ON_A_STRING)\n\t\t\tswitchPedToCar = true;\n\t}\n\n\tif(Cams[ActiveCam].Mode == CCam::MODE_SPECIAL_FIXED_FOR_SYPHON)\n\t\tswitchFromFixedSyphon = true;\n\tif(Cams[ActiveCam].Mode == CCam::MODE_CAM_ON_A_STRING && newMode == CCam::MODE_FOLLOWPED && m_bPlayerWasOnBike)\n\t\tswitchBikeToPed = true;\n\tif(Cams[ActiveCam].Mode == CCam::MODE_SYPHON_CRIM_IN_FRONT && newMode == CCam::MODE_SYPHON)\n\t\tswitchSyphonMode = true;\n\tif(Cams[ActiveCam].Mode == CCam::MODE_FIGHT_CAM && newMode == CCam::MODE_FOLLOWPED)\n\t\tswitchFromFight = true;\n\tif(Cams[ActiveCam].Mode == CCam::MODE_FIXED)\n\t\tswitchFromFixed = true;\n\n\tm_bUseTransitionBeta = false;\n\n\tif((Cams[ActiveCam].Mode == CCam::MODE_SNIPER ||\n\t    Cams[ActiveCam].Mode == CCam::MODE_ROCKETLAUNCHER ||\n\t    Cams[ActiveCam].Mode == CCam::MODE_M16_1STPERSON ||\n\t    Cams[ActiveCam].Mode == CCam::MODE_SNIPER_RUNABOUT ||\n\t    Cams[ActiveCam].Mode == CCam::MODE_ROCKETLAUNCHER_RUNABOUT ||\n\t    Cams[ActiveCam].Mode == CCam::MODE_M16_1STPERSON_RUNABOUT ||\n\t    Cams[ActiveCam].Mode == CCam::MODE_FIGHT_CAM_RUNABOUT ||\n\t    Cams[ActiveCam].Mode == CCam::MODE_HELICANNON_1STPERSON ||\n\t    Cams[ActiveCam].Mode == CCam::MODE_CAMERA ||\n\t    Cams[ActiveCam].Mode == CCam::MODE_1STPERSON_RUNABOUT) &&\n\t   pTargetEntity->IsPed()){\n\t\tfloat angle = CGeneral::GetATanOfXY(Cams[ActiveCam].Front.x, Cams[ActiveCam].Front.y) - HALFPI;\n\t\t((CPed*)pTargetEntity)->m_fRotationCur = angle;\n\t\t((CPed*)pTargetEntity)->m_fRotationDest = angle;\n\t}\n\n\tCams[ActiveCam].m_cvecCamFixedModeVector = m_vecFixedModeVector;\n\tCams[ActiveCam].CamTargetEntity = pTargetEntity;\n\tCams[ActiveCam].m_cvecCamFixedModeSource = m_vecFixedModeSource;\n\tCams[ActiveCam].m_cvecCamFixedModeUpOffSet = m_vecFixedModeUpOffSet;\n\tCams[ActiveCam].m_bCamLookingAtVector = m_bLookingAtVector;\n\n\tif(newMode == CCam::MODE_SNIPER ||\n\t   newMode == CCam::MODE_ROCKETLAUNCHER ||\n\t   newMode == CCam::MODE_M16_1STPERSON ||\n\t   newMode == CCam::MODE_SNIPER_RUNABOUT ||\n\t   newMode == CCam::MODE_ROCKETLAUNCHER_RUNABOUT ||\n\t   newMode == CCam::MODE_1STPERSON_RUNABOUT ||\n\t   newMode == CCam::MODE_M16_1STPERSON_RUNABOUT ||\n\t   newMode == CCam::MODE_FIGHT_CAM_RUNABOUT ||\n\t   newMode == CCam::MODE_HELICANNON_1STPERSON ||\n\t   newMode == CCam::MODE_CAMERA)\n\t\tCams[ActiveCam].Alpha = 0.0f;\n\n\tswitch(Cams[ActiveCam].Mode)\n\tcase CCam::MODE_SNIPER_RUNABOUT:\n\tcase CCam::MODE_ROCKETLAUNCHER_RUNABOUT:\n\tcase CCam::MODE_1STPERSON_RUNABOUT:\n\tcase CCam::MODE_M16_1STPERSON_RUNABOUT:\n\tcase CCam::MODE_FIGHT_CAM_RUNABOUT:\n\tcase CCam::MODE_CAMERA:\n\t\tif(newMode == CCam::MODE_CAM_ON_A_STRING || newMode == CCam::MODE_BEHINDBOAT)\n\t\t\tswitch1stPersonToVehicle = true;\n\n\tswitch(newMode){\n\tcase CCam::MODE_BEHINDCAR:\n\t\tCams[ActiveCam].BetaSpeed = 0.0f;\n\t\tbreak;\n\n\tcase CCam::MODE_BEHINDBOAT:\n\t\tCams[ActiveCam].BetaSpeed = 0.0f;\n\t\tbreak;\n\n\tcase CCam::MODE_FOLLOWPED:\n\t\t// Getting out of vehicle normally\n\t\tbetaOffset = DEGTORAD(55.0f);\n\t\tif(m_bJustCameOutOfGarage){\n\t\t\tm_bUseTransitionBeta = true;\n\t\t\tif(Cams[ActiveCam].Front.x != 0.0f || Cams[ActiveCam].Front.y != 0.0f)\n\t\t\t\tCams[ActiveCam].m_fTransitionBeta = CGeneral::GetATanOfXY(Cams[ActiveCam].Front.x, Cams[ActiveCam].Front.y) + PI;\n\t\t\telse\n\t\t\t\tCams[ActiveCam].m_fTransitionBeta = 0.0f;\n\t\t}\n\t\tif(m_bTargetJustCameOffTrain)\n\t\t\tm_bCamDirectlyInFront = true;\n\t\tif(Cams[ActiveCam].Mode != CCam::MODE_CAM_ON_A_STRING)\n\t\t\tbreak;\n\t\tm_bUseTransitionBeta = true;\n\t\tvehicleVertical = false;\n\t\tif(((CPed*)pTargetEntity)->m_carInObjective &&\n\t\t   ((CPed*)pTargetEntity)->m_carInObjective->GetForward().x == 0.0f &&\n\t\t   ((CPed*)pTargetEntity)->m_carInObjective->GetForward().y == 0.0f)\n\t\t\tvehicleVertical = true;\n\t\tif(vehicleVertical){\n\t\t\tCams[ActiveCam].m_fTransitionBeta = 0.0f;\n\t\t\tbreak;\n\t\t}\n\t\tcamBeta = CGeneral::GetATanOfXY(Cams[ActiveCam].Front.x, Cams[ActiveCam].Front.y);\n\t\tif(((CPed*)pTargetEntity)->m_carInObjective)\n\t\t\ttargetBeta = CGeneral::GetATanOfXY(((CPed*)pTargetEntity)->m_carInObjective->GetForward().x, ((CPed*)pTargetEntity)->m_carInObjective->GetForward().y);\n\t\telse\n\t\t\ttargetBeta = camBeta;\n\t\tdeltaBeta = targetBeta - camBeta;\n\t\twhile(deltaBeta >= PI) deltaBeta -= 2*PI;\n\t\twhile(deltaBeta < -PI) deltaBeta += 2*PI;\n\t\tdeltaBeta = Abs(deltaBeta);\n\n\t\tdoor = FindPlayerPed()->m_vehDoor;\n\t\tif(deltaBeta > HALFPI){\n\t\t\tif(((CPed*)pTargetEntity)->m_carInObjective){\n\t\t\t\tif(((CPed*)pTargetEntity)->m_carInObjective->IsUpsideDown()){\n\t\t\t\t\tif(door == CAR_DOOR_LF || door == CAR_DOOR_LR)\n\t\t\t\t\t\tbetaOffset = -DEGTORAD(95.0f);\n\t\t\t\t}else{\n\t\t\t\t\tif(door == CAR_DOOR_RF || door == CAR_DOOR_RR)\n\t\t\t\t\t\tbetaOffset = -DEGTORAD(95.0f);\n\t\t\t\t}\n\t\t\t}\n\t\t\tCams[ActiveCam].m_fTransitionBeta = targetBeta + betaOffset;\n\t\t}else{\n\t\t\tif(((CPed*)pTargetEntity)->m_carInObjective){\n\t\t\t\tif(((CPed*)pTargetEntity)->m_carInObjective->IsUpsideDown()){\n\t\t\t\t\tif(door == CAR_DOOR_RF || door == CAR_DOOR_RR)\n\t\t\t\t\t\tbetaOffset = -DEGTORAD(55.0f);\n\t\t\t\t\telse if(door == CAR_DOOR_LF || door == CAR_DOOR_LR)\n\t\t\t\t\t\tbetaOffset = DEGTORAD(95.0f);\n\t\t\t\t}else{\n\t\t\t\t\tif(door == CAR_DOOR_LF || door == CAR_DOOR_LR)\n\t\t\t\t\t\tbetaOffset = -DEGTORAD(55.0f);\n\t\t\t\t\telse if(door == CAR_DOOR_RF || door == CAR_DOOR_RR)\n\t\t\t\t\t\tbetaOffset = DEGTORAD(95.0f);\n\t\t\t\t}\n\t\t\t}\n\t\t\tCams[ActiveCam].m_fTransitionBeta = targetBeta + betaOffset + PI;\n\t\t}\n\t\tbreak;\n\n\tcase CCam::MODE_SNIPER:\n\tcase CCam::MODE_ROCKETLAUNCHER:\n\tcase CCam::MODE_M16_1STPERSON:\n\tcase CCam::MODE_SNIPER_RUNABOUT:\n\tcase CCam::MODE_ROCKETLAUNCHER_RUNABOUT:\n\tcase CCam::MODE_1STPERSON_RUNABOUT:\n\tcase CCam::MODE_M16_1STPERSON_RUNABOUT:\n\tcase CCam::MODE_FIGHT_CAM_RUNABOUT:\n\tcase CCam::MODE_HELICANNON_1STPERSON:\n\tcase CCam::MODE_CAMERA:\n\t\tif(FindPlayerVehicle())\n\t\t\tCams[ActiveCam].Beta = Atan2(FindPlayerVehicle()->GetForward().x, FindPlayerVehicle()->GetForward().y);\n\t\telse\n\t\t\tCams[ActiveCam].Beta = Atan2(PLAYER->GetForward().x, PLAYER->GetForward().y);\n\t\tbreak;\n\n\tcase CCam::MODE_SYPHON:\n\t\tCams[ActiveCam].Alpha = 0.0f;\n\t\tCams[ActiveCam].AlphaSpeed = 0.0f;\n\t\tbreak;\n\n\tcase CCam::MODE_CAM_ON_A_STRING:\n\t\t// Get into vehicle\n\t\tbetaOffset = DEGTORAD(57.0f);\n\t\tif(!m_bLookingAtPlayer || m_bJustCameOutOfGarage)\n\t\t\tbreak;\n\t\tm_bUseTransitionBeta = true;\n\t\tCams[ActiveCam].m_fTransitionBeta = CGeneral::GetATanOfXY(Cams[ActiveCam].Front.x, Cams[ActiveCam].Front.y);\n\t\tbreak;\n\n\tcase CCam::MODE_PED_DEAD_BABY:\n\t\tCams[ActiveCam].Alpha = DEGTORAD(15.0f);\n\t\tbreak;\n\n\tcase CCam::MODE_FIGHT_CAM:\n\t\tCams[ActiveCam].Beta = 0.0f;\n\t\tCams[ActiveCam].BetaSpeed = 0.0f;\n\t\tCams[ActiveCam].Alpha = 0.0f;\n\t\tCams[ActiveCam].AlphaSpeed = 0.0f;\n\t\tbreak;\n\t}\n\n\tCams[ActiveCam].Init();\n\tCams[ActiveCam].Mode = newMode;\n\n\tm_uiTransitionDuration = 1350;\n\tif(switchSyphonMode)\n\t\tm_uiTransitionDuration = 1800;\n\telse if(switchFromFight)\n\t\tm_uiTransitionDuration = 750;\n\telse if(switchPedToCar){\n\t\tm_fFractionInterToStopMoving = 0.1f;\n\t\tm_fFractionInterToStopCatchUp = 0.9f;\n\t\tm_uiTransitionDuration = 750;\n\t}else if(switchFromFixedSyphon){\n\t\tm_fFractionInterToStopMoving = 0.0f;\n\t\tm_fFractionInterToStopCatchUp = 1.0f;\n\t\tm_uiTransitionDuration = 600;\n\t}else if(switchFromFixed){\n\t\tm_fFractionInterToStopMoving = 0.05f;\n\t\tm_fFractionInterToStopCatchUp = 0.95f;\n\t}else if(switchBikeToPed){\n\t\tm_uiTransitionDuration = 800;\n\t}else if(switch1stPersonToVehicle){\n\t\tm_fFractionInterToStopMoving = 0.0f;\n\t\tm_fFractionInterToStopCatchUp = 1.0f;\n\t\tm_uiTransitionDuration = 1;\n\t}else if(switchPedMode){\n\t\tm_fFractionInterToStopMoving = 0.5f;\n\t\tm_fFractionInterToStopCatchUp = 0.5f;\n\t\tm_uiTransitionDuration = 350;\n\t}else\n\t\tm_uiTransitionDuration = 1350;\t// already set above\n\tm_uiTransitionState = 1;\n\tm_uiTimeTransitionStart = CTimer::GetTimeInMilliseconds();\n\tm_uiTransitionJUSTStarted = 1;\n\tif(m_vecDoingSpecialInterPolation){\n\t\tm_cvecStartingSourceForInterPol = SourceDuringInter;\n\t\tm_cvecStartingTargetForInterPol = TargetDuringInter;\n\t\tm_cvecStartingUpForInterPol = UpDuringInter;\n\t\tm_fStartingAlphaForInterPol = m_fAlphaDuringInterPol;\n\t\tm_fStartingBetaForInterPol = m_fBetaDuringInterPol;\n\t}else{\n\t\tm_cvecStartingSourceForInterPol = Cams[ActiveCam].Source;\n\t\tm_cvecStartingTargetForInterPol = Cams[ActiveCam].m_cvecTargetCoorsForFudgeInter;\n\t\tm_cvecStartingUpForInterPol = Cams[ActiveCam].Up;\n\t\tm_fStartingAlphaForInterPol = Cams[ActiveCam].m_fTrueAlpha;\n\t\tm_fStartingBetaForInterPol = Cams[ActiveCam].m_fTrueBeta;\n\t}\n\tCams[ActiveCam].m_bCamLookingAtVector = m_bLookingAtVector;\n\tCams[ActiveCam].m_cvecCamFixedModeVector = m_vecFixedModeVector;\n\tCams[ActiveCam].m_cvecCamFixedModeSource = m_vecFixedModeSource;\n\tCams[ActiveCam].m_cvecCamFixedModeUpOffSet = m_vecFixedModeUpOffSet;\n\tCams[ActiveCam].Mode = newMode;\t// already done above\n\tCams[ActiveCam].CamTargetEntity = pTargetEntity;\n\tm_uiTransitionState = 1;\t// these three already done above\n\tm_uiTimeTransitionStart = CTimer::GetTimeInMilliseconds();\n\tm_uiTransitionJUSTStarted = 1;\n\tm_fStartingFOVForInterPol = Cams[ActiveCam].FOV;\n\tm_cvecSourceSpeedAtStartInter = Cams[ActiveCam].m_cvecSourceSpeedOverOneFrame;\n\tm_cvecTargetSpeedAtStartInter = Cams[ActiveCam].m_cvecTargetSpeedOverOneFrame;\n\tm_cvecUpSpeedAtStartInter = Cams[ActiveCam].m_cvecUpOverOneFrame;\n\tm_fAlphaSpeedAtStartInter = Cams[ActiveCam].m_fAlphaSpeedOverOneFrame;\n\tm_fBetaSpeedAtStartInter = Cams[ActiveCam].m_fBetaSpeedOverOneFrame;\n\tm_fFOVSpeedAtStartInter = Cams[ActiveCam].m_fFovSpeedOverOneFrame;\n\tCams[ActiveCam].ResetStatics = true;\n\tif(m_bLookingAtPlayer){\n\t\tif(switchPedMode)\n\t\t\tm_uiTransitionDurationTargetCoors = 350;\n\t\telse\n\t\t\tm_uiTransitionDurationTargetCoors = 600;\n\t\tm_fFractionInterToStopMovingTarget = 0.0f;\n\t\tm_fFractionInterToStopCatchUpTarget = 1.0f;\n\t}else{\n\t\tif(m_bScriptParametersSetForInterPol){\n\t\t\tm_fFractionInterToStopMoving = m_fScriptPercentageInterToStopMoving;\n\t\t\tm_fFractionInterToStopCatchUp = m_fScriptPercentageInterToCatchUp;\n\t\t\tm_uiTransitionDuration = m_fScriptTimeForInterPolation;\n\t\t}\n\t\tm_uiTransitionDurationTargetCoors = m_uiTransitionDuration;\n\t\tm_fFractionInterToStopMovingTarget = m_fFractionInterToStopMoving;\n\t\tm_fFractionInterToStopCatchUpTarget = m_fFractionInterToStopCatchUp;\n\t}\n}\n\nvoid\nCCamera::StartTransitionWhenNotFinishedInter(int16 mode)\n{\n\tm_vecDoingSpecialInterPolation = true;\n\tStartTransition(mode);\n}\n\nvoid\nCCamera::StoreValuesDuringInterPol(CVector &source, CVector &target, CVector &up, float &FOV)\n{\n\tSourceDuringInter = source;\n\tTargetDuringInter = target;\n\tUpDuringInter = up;\n\tFOVDuringInter = FOV;\n\tCVector Dist = source - TargetDuringInter;\n\tfloat DistOnGround = Dist.Magnitude2D();\n\tm_fBetaDuringInterPol = CGeneral::GetATanOfXY(Dist.x, Dist.y);\n\tm_fAlphaDuringInterPol = CGeneral::GetATanOfXY(DistOnGround, Dist.z);\n}\n\n\n\nvoid\nCCamera::SetWideScreenOn(void)\n{\n\tm_WideScreenOn = true;\n}\n\nvoid\nCCamera::SetWideScreenOff(void)\n{\n\tm_bWantsToSwitchWidescreenOff = m_WideScreenOn;\n}\n\nvoid\nCCamera::ProcessWideScreenOn(void)\n{\n\tif(m_bWantsToSwitchWidescreenOff){\n\t\tm_bWantsToSwitchWidescreenOff = false;\n\t\tm_WideScreenOn = false;\n\t\tm_ScreenReductionPercentage = 0.0f;\n\t\tm_fFOV_Wide_Screen = 0.0f;\n\t\tm_fWideScreenReductionAmount = 0.0f;\n\t}else{\n\t\tm_fFOV_Wide_Screen = 0.3f*Cams[ActiveCam].FOV;\n\t\tm_fWideScreenReductionAmount = 1.0f;\n\t\tm_ScreenReductionPercentage = 30.0f;\n\t}\n}\n\nvoid\nCCamera::DrawBordersForWideScreen(void)\n{\n\tfloat bottom, top;\n\tif (m_WideScreenOn) {\n\t\tfloat borderSize = (SCREEN_HEIGHT / 2) * (m_ScreenReductionPercentage / 100.f);\n\t\ttop = borderSize - SCREEN_SCALE_Y(22.f);\n\t\tbottom = SCREEN_HEIGHT - borderSize - SCREEN_SCALE_Y(14.f);\n\t} else {\n\t\ttop = 0.f;\n\t\tbottom = SCREEN_HEIGHT;\n\t}\n\n\tif(m_BlurType == MOTION_BLUR_NONE || m_BlurType == MOTION_BLUR_LIGHT_SCENE)\n\t\tSetMotionBlurAlpha(80);\n\n\t// top border\n\tCSprite2d::DrawRect(CRect(0.0f, 0.0f, SCREEN_WIDTH, top), CRGBA(0, 0, 0, 255));\n\n\t// bottom border\n\tCSprite2d::DrawRect(CRect(0.0f, bottom, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(0, 0, 0, 255));\n}\n\n\n\nbool\nCCamera::IsItTimeForNewcam(int32 obbeMode, int32 time)\n{\n\tCVehicle *veh;\n\tuint32 t = time;\t// no annoying compiler warnings\n\tCVector fwd;\n\n\tif(obbeMode < 0)\n\t\treturn true;\n\tswitch(obbeMode){\n\tcase OBBE_WHEEL:\n\t\tveh = FindPlayerVehicle();\n\t\tif(veh){\n\t\t\tif(veh->IsBoat() && pTargetEntity->GetModelIndex() != MI_SKIMMER)\n\t\t\t\treturn true;\n\t\t\tif(veh->GetModelIndex() == MI_RHINO)\n\t\t\t\treturn true;\n\t\t\tif(!CWorld::GetIsLineOfSightClear(pTargetEntity->GetPosition(), Cams[ActiveCam].Source, true, false, false, false, false, false, false))\n\t\t\t\treturn true;\n\t\t}\n\t\tif(CTimer::GetTimeInMilliseconds() > t+5000)\n\t\t\treturn true;\n\t\tSetNearClipScript(0.6f);\n\t\treturn false;\n\tcase OBBE_1:\n\t\tif(FindPlayerVehicle() && FindPlayerVehicle()->IsBoat() && pTargetEntity->GetModelIndex() != MI_SKIMMER)\n\t\t\treturn true;\n\t\tif(!CWorld::GetIsLineOfSightClear(FindPlayerCoors(), m_vecFixedModeSource, true, false, false, false, false, false, false))\n\t\t\treturn true;\n\n\t\tfwd = FindPlayerCoors() - m_vecFixedModeSource;\n\t\tfwd.z = 0.0f;\n\n\t\t// too far and driving away from cam\n\t\tif(fwd.Magnitude() > 40.0f && DotProduct(FindPlayerSpeed(), fwd) > 0.0f)\n\t\t\treturn true;\n\t\t// too close\n\t\tif(fwd.Magnitude() < 1.6f)\n\t\t\treturn true;\n\t\treturn false;\n\tcase OBBE_2:\n\t\tif(FindPlayerVehicle() && FindPlayerVehicle()->IsBoat() && pTargetEntity->GetModelIndex() != MI_SKIMMER)\n\t\t\treturn true;\n\t\tif(!CWorld::GetIsLineOfSightClear(FindPlayerCoors(), m_vecFixedModeSource, true, false, false, false, false, false, false))\n\t\t\treturn true;\n\n\t\tfwd = FindPlayerCoors() - m_vecFixedModeSource;\n\t\tfwd.z = 0.0f;\n\n\t\tif(fwd.Magnitude() < 2.0f)\n\t\t\t// very close, fix near clip\n\t\t\tSetNearClipScript(Max(fwd.Magnitude()*0.5f, 0.05f));\n\t\t// too far and driving away from cam\n\t\tif(fwd.Magnitude() > 29.0f && DotProduct(FindPlayerSpeed(), fwd) > 0.0f)\n\t\t\treturn true;\n\t\t// too close\n\t\tif(fwd.Magnitude() < 2.0f)\n\t\t\treturn true;\n\t\treturn false;\n\tcase OBBE_3:\n\t\tif(!CWorld::GetIsLineOfSightClear(FindPlayerCoors(), m_vecFixedModeSource, true, false, false, false, false, false, false))\n\t\t\treturn true;\n\n\t\tfwd = FindPlayerCoors() - m_vecFixedModeSource;\n\t\tfwd.z = 0.0f;\n\n\t\t// too far and driving away from cam\n\t\tif(fwd.Magnitude() > 48.0f && DotProduct(FindPlayerSpeed(), fwd) > 0.0f)\n\t\t\treturn true;\n\t\treturn false;\n\tcase OBBE_1STPERSON:\n\t\treturn CTimer::GetTimeInMilliseconds() > t+3000;\n\tcase OBBE_5:\n\t\tif(FindPlayerVehicle() && FindPlayerVehicle()->IsBoat() && pTargetEntity->GetModelIndex() != MI_SKIMMER)\n\t\t\treturn true;\n\t\tif(!CWorld::GetIsLineOfSightClear(FindPlayerCoors(), m_vecFixedModeSource, true, false, false, false, false, false, false))\n\t\t\treturn true;\n\n\t\tfwd = FindPlayerCoors() - m_vecFixedModeSource;\n\t\tfwd.z = 0.0f;\n\n\t\t// too far and driving away from cam\n\t\tif(fwd.Magnitude() > 38.0f && DotProduct(FindPlayerSpeed(), fwd) > 0.0f)\n\t\t\treturn true;\n\t\treturn false;\n\tcase OBBE_ONSTRING:\n\t\treturn CTimer::GetTimeInMilliseconds() > t+3000;\n\tcase OBBE_COPCAR:\n\t\treturn CTimer::GetTimeInMilliseconds() > t+2000 && !FindPlayerVehicle()->GetIsOnScreen();\n\tcase OBBE_COPCAR_WHEEL:\n\t\tif(FindPlayerVehicle() && FindPlayerVehicle()->IsBoat())\n\t\t\treturn true;\n\t\tif(!CWorld::GetIsLineOfSightClear(pTargetEntity->GetPosition(), Cams[ActiveCam].Source, true, false, false, false, false, false, false))\n\t\t\treturn true;\n\t\tif(CTimer::GetTimeInMilliseconds() > t+1000)\n\t\t\treturn true;\n\t\tSetNearClipScript(0.6f);\n\t\treturn false;\n\n\t// Ped modes\n\tcase OBBE_9:\n\t\tif(!CWorld::GetIsLineOfSightClear(FindPlayerCoors(), m_vecFixedModeSource, true, false, false, false, false, false, false))\n\t\t\treturn true;\n\n\t\tfwd = FindPlayerCoors() - m_vecFixedModeSource;\n\t\tfwd.z = 0.0f;\n\n\t\t// too far and driving away from cam\n\t\tif(fwd.Magnitude() > 20.0f && DotProduct(FindPlayerSpeed(), fwd) > 0.0f)\n\t\t\treturn true;\n\t\treturn false;\n\tcase OBBE_10:\n\t\tif(!CWorld::GetIsLineOfSightClear(FindPlayerCoors(), m_vecFixedModeSource, true, false, false, false, false, false, false))\n\t\t\treturn true;\n\n\t\tfwd = FindPlayerCoors() - m_vecFixedModeSource;\n\t\tfwd.z = 0.0f;\n\n\t\t// too far and driving away from cam\n\t\tif(fwd.Magnitude() > 8.0f && DotProduct(FindPlayerSpeed(), fwd) > 0.0f)\n\t\t\treturn true;\n\t\treturn false;\n\tcase OBBE_11:\n\t\tif(!CWorld::GetIsLineOfSightClear(FindPlayerCoors(), m_vecFixedModeSource, true, false, false, false, false, false, false))\n\t\t\treturn true;\n\n\t\tfwd = FindPlayerCoors() - m_vecFixedModeSource;\n\t\tfwd.z = 0.0f;\n\n\t\t// too far and driving away from cam\n\t\tif(fwd.Magnitude() > 25.0f && DotProduct(FindPlayerSpeed(), fwd) > 0.0f)\n\t\t\treturn true;\n\t\treturn false;\n\tcase OBBE_12:\n\t\tif(!CWorld::GetIsLineOfSightClear(FindPlayerCoors(), m_vecFixedModeSource, true, false, false, false, false, false, false))\n\t\t\treturn true;\n\n\t\tfwd = FindPlayerCoors() - m_vecFixedModeSource;\n\t\tfwd.z = 0.0f;\n\n\t\t// too far and driving away from cam\n\t\tif(fwd.Magnitude() > 8.0f && DotProduct(FindPlayerSpeed(), fwd) > 0.0f)\n\t\t\treturn true;\n\t\treturn false;\n\tcase OBBE_13:\n\t\treturn CTimer::GetTimeInMilliseconds() > t+5000;\n\n\t// Heli modes\n\tcase OBBE_14:\n\t\tif(FindPlayerVehicle())\n\t\t\tif(!CWorld::GetIsLineOfSightClear(pTargetEntity->GetPosition(), Cams[ActiveCam].Source, true, false, false, false, false, false, false))\n\t\t\t\treturn true;\n\t\treturn CTimer::GetTimeInMilliseconds() > t+8000;\n\tcase OBBE_15:\n\t\tif(FindPlayerVehicle()){\n\t\t\tif(!CWorld::GetIsLineOfSightClear(FindPlayerCoors(), m_vecFixedModeSource, true, false, false, false, false, false, false))\n\t\t\t\treturn true;\n\t\t\tfwd = FindPlayerCoors() - m_vecFixedModeSource;\n\t\t\tfwd.z = 0.0f;\n\n\t\t\t// too far and driving away from cam\n\t\t\tif(fwd.Magnitude() > 44.0f && DotProduct(FindPlayerSpeed(), fwd) > 0.0f)\n\t\t\t\treturn true;\n\t\t\t// too close\n\t\t\tif(fwd.Magnitude() < 2.0f)\n\t\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\tcase OBBE_16:\n\t\tif(FindPlayerVehicle()){\n\t\t\tif(!CWorld::GetIsLineOfSightClear(FindPlayerCoors(), m_vecFixedModeSource, true, false, false, false, false, false, false))\n\t\t\t\treturn true;\n\t\t\tfwd = FindPlayerCoors() - m_vecFixedModeSource;\n\t\t\tfwd.z = 0.0f;\n\n\t\t\t// too far and driving away from cam\n\t\t\tif(fwd.Magnitude() > 50.0f && DotProduct(FindPlayerSpeed(), fwd) > 0.0f)\n\t\t\t\treturn true;\n\t\t\t// too close\n\t\t\tif(fwd.Magnitude() < 3.0f)\n\t\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\tcase OBBE_17:\n\t\tif(FindPlayerVehicle()){\n\t\t\tif(!CWorld::GetIsLineOfSightClear(FindPlayerCoors(), m_vecFixedModeSource, true, false, false, false, false, false, false))\n\t\t\t\treturn true;\n\t\t\tfwd = FindPlayerCoors() - m_vecFixedModeSource;\n\t\t\tfwd.z = 0.0f;\n\n\t\t\t// too far\n\t\t\tif(fwd.Magnitude() > 50.0f)\n\t\t\t\treturn true;\n\t\t\t// too close\n\t\t\tif(fwd.Magnitude() < 2.0f)\n\t\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\tcase OBBE_18:\n\t\tif(FindPlayerVehicle()){\n\t\t\tif(!CWorld::GetIsLineOfSightClear(FindPlayerCoors(), m_vecFixedModeSource, true, false, false, false, false, false, false))\n\t\t\t\treturn true;\n\t\t\tfwd = FindPlayerCoors() - m_vecFixedModeSource;\n\n\t\t\t// too far\n\t\t\tif(fwd.Magnitude() > 57.0f)\n\t\t\t\treturn true;\n\t\t\t// too close\n\t\t\tif(fwd.Magnitude() < 1.0f)\n\t\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\tcase OBBE_19:\n\t\tif(FindPlayerVehicle()){\n\t\t\tif(!CWorld::GetIsLineOfSightClear(FindPlayerCoors(), m_vecFixedModeSource, true, false, false, false, false, false, false))\n\t\t\t\treturn true;\n\t\t\tfwd = FindPlayerCoors() - m_vecFixedModeSource;\n\t\t\tfwd.z = 0.0f;\n\n\t\t\t// too far\n\t\t\tif(fwd.Magnitude() > 36.0f)\n\t\t\t\treturn true;\n\t\t\t// too close\n\t\t\tif(fwd.Magnitude() < 2.0f)\n\t\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\tcase OBBE_ONSTRING_HELI:\n\t\treturn CTimer::GetTimeInMilliseconds() > t+5000;\n\n\tdefault:\n\t\treturn false;\n\t}\n}\n\nbool\nCCamera::TryToStartNewCamMode(int obbeMode)\n{\n\tCVehicle *veh;\n\tCVector target, camPos, playerSpeed, fwd, fwd2;\n\tfloat angle;\n\tfloat ground;\n\tbool foundGround;\n\tint i;\n\n\tif(obbeMode < 0)\n\t\treturn true;\n\tswitch(obbeMode){\n\tcase OBBE_WHEEL:\n\t\tveh = FindPlayerVehicle();\n\t\tif(veh == nil || (veh->IsBoat() && pTargetEntity->GetModelIndex() != MI_SKIMMER) || veh->GetModelIndex() == MI_RHINO)\n\t\t\treturn false;\n\t\ttarget = Multiply3x3(FindPlayerVehicle()->GetMatrix(), CVector(-1.4f, -2.3f, 0.3f));\n\t\ttarget += FindPlayerVehicle()->GetPosition();\n\t\tif(!CWorld::GetIsLineOfSightClear(veh->GetPosition(), target, true, false, false, false, false, false, false))\n\t\t\treturn false;\n\t\tTakeControl(veh, CCam::MODE_WHEELCAM, JUMP_CUT, CAMCONTROL_OBBE);\n\t\treturn true;\n\tcase OBBE_1:\n\t\tcamPos = FindPlayerCoors();\n\t\tplayerSpeed = FindPlayerSpeed();\n\t\tplayerSpeed.z = 0.0f;\n\t\tplayerSpeed.Normalise();\n\t\tcamPos += 20.0f*playerSpeed;\n\t\tcamPos += 3.0f*CVector(playerSpeed.y, -playerSpeed.x, 0.0f);\n\t\tif(FindPlayerVehicle() && FindPlayerVehicle()->IsBoat() && pTargetEntity->GetModelIndex() != MI_SKIMMER)\n\t\t\treturn false;\n\n\t\tground = CWorld::FindGroundZFor3DCoord(camPos.x, camPos.y, camPos.z+5.0f, &foundGround);\n\t\tif(foundGround)\n\t\t\tcamPos.z = ground + 1.5f;\n\t\telse{\n\t\t\tground = CWorld::FindRoofZFor3DCoord(camPos.x, camPos.y, camPos.z-5.0f, &foundGround);\n\t\t\tif(foundGround)\n\t\t\t\tcamPos.z = ground + 1.5f;\n\t\t}\n\t\tif(!CWorld::GetIsLineOfSightClear(FindPlayerCoors(), camPos, true, false, false, false, false, false, false))\n\t\t\treturn false;\n\n\t\tfwd = FindPlayerCoors() - camPos;\n\t\tfwd.z = 0.0f;\n\t\t// too far and driving away from cam\n\t\tif(fwd.Magnitude() > 40.0f && DotProduct(FindPlayerSpeed(), fwd) > 0.0f)\n\t\t\treturn false;\n\t\t// too close\n\t\tif(fwd.Magnitude() < 2.5f)\n\t\t\treturn true;\n\n\t\tSetCamPositionForFixedMode(camPos, CVector(0.0f, 0.0f, 0.0f));\n\t\tTakeControl(FindPlayerEntity(), CCam::MODE_FIXED, JUMP_CUT, CAMCONTROL_OBBE);\n\t\treturn true;\n\tcase OBBE_2:\n\t\tif(FindPlayerVehicle() && FindPlayerVehicle()->IsBoat() && pTargetEntity->GetModelIndex() != MI_SKIMMER)\n\t\t\treturn false;\n\t\tcamPos = FindPlayerCoors();\n\t\tplayerSpeed = FindPlayerSpeed();\n\t\tplayerSpeed.z = 0.0f;\n\t\tplayerSpeed.Normalise();\n\t\tcamPos += 16.0f*playerSpeed;\n\t\tcamPos += 2.5f*CVector(playerSpeed.y, -playerSpeed.x, 0.0f);\n\n\t\tground = CWorld::FindGroundZFor3DCoord(camPos.x, camPos.y, camPos.z+5.0f, &foundGround);\n\t\tif(foundGround)\n\t\t\tcamPos.z = ground + 0.5f;\n\t\telse{\n\t\t\tground = CWorld::FindRoofZFor3DCoord(camPos.x, camPos.y, camPos.z-5.0f, &foundGround);\n\t\t\tif(foundGround)\n\t\t\t\tcamPos.z = ground + 0.5f;\n\t\t}\n\t\tif(!CWorld::GetIsLineOfSightClear(FindPlayerCoors(), camPos, true, false, false, false, false, false, false))\n\t\t\treturn false;\n\n\t\tfwd = FindPlayerCoors() - camPos;\n\t\tfwd.z = 0.0f;\n\t\t// too far and driving away from cam\n\t\tif(fwd.Magnitude() > 29.0f && DotProduct(FindPlayerSpeed(), fwd) > 0.0f)\n\t\t\treturn false;\n\t\t// too close\n\t\tif(fwd.Magnitude() < 2.0f)\n\t\t\treturn true;\n\n\t\tSetCamPositionForFixedMode(camPos, CVector(0.0f, 0.0f, 0.0f));\n\t\tTakeControl(FindPlayerEntity(), CCam::MODE_FIXED, JUMP_CUT, CAMCONTROL_OBBE);\n\t\treturn true;\n\tcase OBBE_3:\n\t\tcamPos = FindPlayerCoors();\n\t\tplayerSpeed = FindPlayerSpeed();\n\t\tplayerSpeed.z = 0.0f;\n\t\tplayerSpeed.Normalise();\n\t\tcamPos += 30.0f*playerSpeed;\n\t\tcamPos += 8.0f*CVector(playerSpeed.y, -playerSpeed.x, 0.0f);\n\n\t\tif(!CWorld::GetIsLineOfSightClear(FindPlayerCoors(), camPos, true, false, false, false, false, false, false))\n\t\t\treturn false;\n\n\t\tSetCamPositionForFixedMode(camPos, CVector(0.0f, 0.0f, 0.0f));\n\t\tTakeControl(FindPlayerEntity(), CCam::MODE_FIXED, JUMP_CUT, CAMCONTROL_OBBE);\n\t\treturn true;\n\tcase OBBE_1STPERSON:\n\t\tTakeControl(FindPlayerEntity(), CCam::MODE_FIXED, JUMP_CUT, CAMCONTROL_OBBE);\n\t\treturn true;\n\tcase OBBE_5:\n\t\tcamPos = FindPlayerCoors();\n\t\tplayerSpeed = FindPlayerSpeed();\n\t\tplayerSpeed.z = 0.0f;\n\t\tplayerSpeed.Normalise();\n\t\tcamPos += 30.0f*playerSpeed;\n\t\tcamPos += 6.0f*CVector(playerSpeed.y, -playerSpeed.x, 0.0f);\n\n\t\tground = CWorld::FindGroundZFor3DCoord(camPos.x, camPos.y, camPos.z+5.0f, &foundGround);\n\t\tif(foundGround)\n\t\t\tcamPos.z = ground + 3.5f;\n\t\telse{\n\t\t\tground = CWorld::FindRoofZFor3DCoord(camPos.x, camPos.y, camPos.z-5.0f, &foundGround);\n\t\t\tif(foundGround)\n\t\t\t\tcamPos.z = ground + 3.5f;\n\t\t}\n\t\tif(!CWorld::GetIsLineOfSightClear(FindPlayerCoors(), camPos, true, false, false, false, false, false, false))\n\t\t\treturn false;\n\n\t\tSetCamPositionForFixedMode(camPos, CVector(0.0f, 0.0f, 0.0f));\n\t\tTakeControl(FindPlayerEntity(), CCam::MODE_FIXED, JUMP_CUT, CAMCONTROL_OBBE);\n\t\treturn true;\n\tcase OBBE_ONSTRING:\n\t\tTakeControl(FindPlayerEntity(), CCam::MODE_CAM_ON_A_STRING, JUMP_CUT, CAMCONTROL_OBBE);\n\t\treturn true;\n\tcase OBBE_COPCAR:\n#ifdef FIX_BUGS\n\t\tif (CReplay::IsPlayingBack())\n\t\t\treturn false;\n#endif\n\t\tif(FindPlayerPed()->m_pWanted->GetWantedLevel() < 1)\n\t\t\treturn false;\n\t\tif(FindPlayerVehicle() == nil)\n\t\t\treturn false;\n\t\tif(FindPlayerVehicle() && FindPlayerVehicle()->IsBoat() && pTargetEntity->GetModelIndex() != MI_SKIMMER)\n\t\t\treturn false;\n\t\ti = CPools::GetVehiclePool()->GetSize();\n\t\twhile(--i >= 0){\n\t\t\tveh = CPools::GetVehiclePool()->GetSlot(i);\n\t\t\tif(veh && veh->IsCar() && veh != FindPlayerVehicle() && veh->bIsLawEnforcer){\n\t\t\t\tfloat dx = veh->GetPosition().x - FindPlayerCoors().x;\n\t\t\t\tfloat dy = veh->GetPosition().y - FindPlayerCoors().y;\n\t\t\t\tfloat dist = (veh->GetPosition() - FindPlayerCoors()).Magnitude();\n\t\t\t\tif(dist < 30.0f){\n\t\t\t\t\tif(dx*FindPlayerVehicle()->GetForward().x + dy*FindPlayerVehicle()->GetForward().y < 0.0f &&\n\t\t\t\t\t   veh->GetForward().x*FindPlayerVehicle()->GetForward().x + veh->GetForward().y*FindPlayerVehicle()->GetForward().y > 0.8f){\n\t\t\t\t\t\tTakeControl(veh, CCam::MODE_CAM_ON_A_STRING, JUMP_CUT, CAMCONTROL_OBBE);\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn false;\n\tcase OBBE_COPCAR_WHEEL:\n#ifdef FIX_BUGS\n\t\tif (CReplay::IsPlayingBack())\n\t\t\treturn false;\n#endif\n\t\tif(FindPlayerPed()->m_pWanted->GetWantedLevel() < 1)\n\t\t\treturn false;\n\t\tif(FindPlayerVehicle() == nil)\n\t\t\treturn false;\n\t\tif(FindPlayerVehicle() && FindPlayerVehicle()->IsBoat() && pTargetEntity->GetModelIndex() != MI_SKIMMER)\n\t\t\treturn false;\n\t\ti = CPools::GetVehiclePool()->GetSize();\n\t\twhile(--i >= 0){\n\t\t\tveh = CPools::GetVehiclePool()->GetSlot(i);\n\t\t\tif(veh && veh->IsCar() && veh != FindPlayerVehicle() && veh->bIsLawEnforcer){\n\t\t\t\tfloat dx = veh->GetPosition().x - FindPlayerCoors().x;\n\t\t\t\tfloat dy = veh->GetPosition().y - FindPlayerCoors().y;\n\t\t\t\tfloat dist = (veh->GetPosition() - FindPlayerCoors()).Magnitude();\n\t\t\t\tif(dist < 30.0f){\n\t\t\t\t\tif(dx*FindPlayerVehicle()->GetForward().x + dy*FindPlayerVehicle()->GetForward().y < 0.0f &&\n\t\t\t\t\t   veh->GetForward().x*FindPlayerVehicle()->GetForward().x + veh->GetForward().y*FindPlayerVehicle()->GetForward().y > 0.8f){\n\t\t\t\t\t\ttarget = Multiply3x3(veh->GetMatrix(), CVector(-1.4f, -2.3f, 0.3f));\n\t\t\t\t\t\ttarget += veh->GetPosition();\n\t\t\t\t\t\tif(!CWorld::GetIsLineOfSightClear(veh->GetPosition(), target, true, false, false, false, false, false, false))\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\tTakeControl(veh, CCam::MODE_WHEELCAM, JUMP_CUT, CAMCONTROL_OBBE);\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn false;\n\n\tcase OBBE_9:\n\t\tcamPos = FindPlayerCoors();\n\t\tplayerSpeed = FindPlayerSpeed();\n\t\tplayerSpeed.z = 0.0f;\n\t\tplayerSpeed.Normalise();\n\t\tcamPos += 15.0f*playerSpeed;\n\t\tcamPos += CVector(2.0f, 1.0f, 0.0f);\n\n\t\tground = CWorld::FindGroundZFor3DCoord(camPos.x, camPos.y, camPos.z+5.0f, &foundGround);\n\t\tif(foundGround)\n\t\t\tcamPos.z = ground + 0.5f;\n\t\telse{\n\t\t\tground = CWorld::FindRoofZFor3DCoord(camPos.x, camPos.y, camPos.z-5.0f, &foundGround);\n\t\t\tif(foundGround)\n\t\t\t\tcamPos.z = ground + 0.5f;\n\t\t}\n\t\tif(!CWorld::GetIsLineOfSightClear(FindPlayerCoors(), camPos, true, false, false, false, false, false, false))\n\t\t\treturn false;\n\n\t\tSetCamPositionForFixedMode(camPos, CVector(0.0f, 0.0f, 0.0f));\n\t\tTakeControl(FindPlayerEntity(), CCam::MODE_FIXED, JUMP_CUT, CAMCONTROL_OBBE);\n\t\treturn true;\n\tcase OBBE_10:\n\t\tcamPos = FindPlayerCoors();\n\t\tplayerSpeed = FindPlayerSpeed();\n\t\tplayerSpeed.z = 0.0f;\n\t\tplayerSpeed.Normalise();\n\t\tcamPos += 5.0f*playerSpeed;\n\t\tcamPos += CVector(2.0f, 1.0f, 0.5f);\n\n\t\tif(!CWorld::GetIsLineOfSightClear(FindPlayerCoors(), camPos, true, false, false, false, false, false, false))\n\t\t\treturn false;\n\n\t\tSetCamPositionForFixedMode(camPos, CVector(0.0f, 0.0f, 0.0f));\n\t\tTakeControl(FindPlayerEntity(), CCam::MODE_FIXED, JUMP_CUT, CAMCONTROL_OBBE);\n\t\treturn true;\n\tcase OBBE_11:\n\t\tcamPos = FindPlayerCoors();\n\t\tplayerSpeed = FindPlayerSpeed();\n\t\tplayerSpeed.z = 0.0f;\n\t\tplayerSpeed.Normalise();\n\t\tcamPos += 20.0f*playerSpeed;\n\t\tcamPos += CVector(2.0f, 1.0f, 20.0f);\n\n\t\tif(!CWorld::GetIsLineOfSightClear(FindPlayerCoors(), camPos, true, false, false, false, false, false, false))\n\t\t\treturn false;\n\n\t\tSetCamPositionForFixedMode(camPos, CVector(0.0f, 0.0f, 0.0f));\n\t\tTakeControl(FindPlayerEntity(), CCam::MODE_FIXED, JUMP_CUT, CAMCONTROL_OBBE);\n\t\treturn true;\n\tcase OBBE_12:\n\t\tcamPos = FindPlayerCoors();\n\t\tplayerSpeed = FindPlayerSpeed();\n\t\tplayerSpeed.z = 0.0f;\n\t\tplayerSpeed.Normalise();\n\t\tcamPos += 5.0f*playerSpeed;\n\t\tcamPos += CVector(2.0f, 1.0f, 10.5f);\n\n\t\tif(!CWorld::GetIsLineOfSightClear(FindPlayerCoors(), camPos, true, false, false, false, false, false, false))\n\t\t\treturn false;\n\n\t\tSetCamPositionForFixedMode(camPos, CVector(0.0f, 0.0f, 0.0f));\n\t\tTakeControl(FindPlayerEntity(), CCam::MODE_FIXED, JUMP_CUT, CAMCONTROL_OBBE);\n\t\treturn true;\n\tcase OBBE_13:\n#ifdef FIX_BUGS\n\t\tTakeControl(FindPlayerEntity(), CCam::MODE_TOP_DOWN_PED, JUMP_CUT, CAMCONTROL_OBBE);\n#else\n\t\tTakeControl(FindPlayerEntity(), CCam::MODE_TOPDOWN, JUMP_CUT, CAMCONTROL_OBBE);\n#endif\n\t\treturn true;\n\n\t// Heli modes\n\tcase OBBE_14:\n\t\tveh = FindPlayerVehicle();\n\t\tif(veh == nil)\n\t\t\treturn false;\n\t\ttarget = Multiply3x3(FindPlayerVehicle()->GetMatrix(), CVector(-1.4f, -2.3f, 0.3f));\n\t\ttarget += FindPlayerVehicle()->GetPosition();\n\t\tif(!veh->IsBoat() && !CWorld::GetIsLineOfSightClear(veh->GetPosition(), target, true, false, false, false, false, false, false))\n\t\t\treturn false;\n\t\tTakeControl(veh, CCam::MODE_WHEELCAM, JUMP_CUT, CAMCONTROL_OBBE);\n\t\treturn true;\n\tcase OBBE_15:\n\t\tif(FindPlayerVehicle() == nil)\n\t\t\treturn false;\n\t\tcamPos = FindPlayerCoors();\n\t\tplayerSpeed = FindPlayerSpeed();\n\t\tplayerSpeed.z = 0.0f;\n\t\tplayerSpeed.Normalise();\n\t\tcamPos += 34.0f*playerSpeed;\n\t\tcamPos.z = FindPlayerCoors().z + 0.5f;\n\t\tif(FindPlayerVehicle()->IsBoat())\n\t\t\tcamPos.z += 1.0f;\n\n\t\tif(!CWorld::GetIsLineOfSightClear(FindPlayerCoors(), camPos, true, false, false, false, false, false, false))\n\t\t\treturn false;\n\n\t\tfwd = FindPlayerCoors() - camPos;\n\t\tfwd2 = FindPlayerCoors() - camPos;\n\t\tfwd2.z = 0.0f;\n\t\t// too far and driving away from cam\n\t\tif(fwd.Magnitude() > 44.0f && DotProduct(FindPlayerSpeed(), fwd2) > 0.0f)\n\t\t\treturn false;\n\t\t// too close\n\t\tif(fwd.Magnitude() < 3.0f)\n\t\t\treturn true;\n\n\t\tSetCamPositionForFixedMode(camPos, CVector(0.0f, 0.0f, 0.0f));\n\t\tTakeControl(FindPlayerEntity(), CCam::MODE_FIXED, JUMP_CUT, CAMCONTROL_OBBE);\n\t\treturn true;\n\tcase OBBE_16:\n\t\tif(FindPlayerVehicle() == nil)\n\t\t\treturn false;\n\t\tcamPos = FindPlayerCoors();\n\t\tplayerSpeed = FindPlayerSpeed();\n\t\tplayerSpeed.z = 0.0f;\n\t\tplayerSpeed.Normalise();\n\t\tangle = CGeneral::GetATanOfXY(playerSpeed.x, playerSpeed.y) + DEGTORAD(60.0f);\n\t\tplayerSpeed += CVector(Cos(angle), Sin(angle), 0.0f);\n\t\tplayerSpeed.Normalise();\n\t\tcamPos += 30.0f*playerSpeed;\n\t\tcamPos.z = FindPlayerCoors().z - 5.5f;\n\n\t\tfoundGround = false;\n\t\tground = CWorld::FindRoofZFor3DCoord(camPos.x, camPos.y, camPos.z+5.0f, &foundGround);\n\t\tif(foundGround)\n\t\t\tcamPos.z = ground + 0.5f;\n\t\telse if(CWaterLevel::GetWaterLevelNoWaves(camPos.x, camPos.y, camPos.z, &ground)){\n\t\t\tfloat waterOffset = 1.0f;\n\t\t\tif(FindPlayerVehicle() && FindPlayerVehicle()->IsBoat())\n\t\t\t\twaterOffset = -2.0f;\n\t\t\tif(camPos.z < ground + waterOffset)\n\t\t\t\tcamPos.z = ground + waterOffset;\n\t\t}\n\t\tif(!CWorld::GetIsLineOfSightClear(FindPlayerCoors(), camPos, true, false, false, false, false, false, false))\n\t\t\treturn false;\n\n\t\tfwd = FindPlayerCoors() - camPos;\n\t\t// too far\n\t\tif(fwd.Magnitude() > 50.0f)\n\t\t\treturn false;\n\t\t// too close\n\t\tif(fwd.Magnitude() < 3.0f)\n\t\t\treturn true;\n\n\t\tSetCamPositionForFixedMode(camPos, CVector(0.0f, 0.0f, 0.0f));\n\t\tTakeControl(FindPlayerEntity(), CCam::MODE_FIXED, JUMP_CUT, CAMCONTROL_OBBE);\n\t\treturn true;\n\tcase OBBE_17:\n\t\tif(FindPlayerVehicle() == nil)\n\t\t\treturn false;\n\t\tcamPos = FindPlayerCoors();\n\t\tplayerSpeed = FindPlayerSpeed();\n\t\tplayerSpeed.z = 0.0f;\n\t\tplayerSpeed.Normalise();\n\t\tangle = CGeneral::GetATanOfXY(playerSpeed.x, playerSpeed.y) + DEGTORAD(190.0f);\n\t\tplayerSpeed += CVector(Cos(angle), Sin(angle), 0.0f);\n\t\tplayerSpeed.Normalise();\n\t\tcamPos += 25.0f*playerSpeed;\n\t\tcamPos.z = FindPlayerCoors().z - 1.0f;\n\n\t\tfoundGround = false;\n\t\tground = CWorld::FindRoofZFor3DCoord(camPos.x, camPos.y, camPos.z+5.0f, &foundGround);\n\t\tif(foundGround)\n\t\t\tcamPos.z = ground + 0.5f;\n\t\telse if(CWaterLevel::GetWaterLevelNoWaves(camPos.x, camPos.y, camPos.z, &ground)){\n\t\t\tfloat waterOffset = 1.0f;\n\t\t\tif(FindPlayerVehicle() && FindPlayerVehicle()->IsBoat())\n\t\t\t\twaterOffset = -2.0f;\n\t\t\tif(camPos.z < ground + waterOffset)\n\t\t\t\tcamPos.z = ground + waterOffset;\n\t\t}\n\t\tif(!CWorld::GetIsLineOfSightClear(FindPlayerCoors(), camPos, true, false, false, false, false, false, false))\n\t\t\treturn false;\n\n\t\tfwd = FindPlayerCoors() - camPos;\n\t\tfwd2 = FindPlayerCoors() - camPos;\n\t\tfwd2.z = 0.0f;\n\t\t// too far and driving away from cam\n\t\tif(fwd.Magnitude() > 50.0f && DotProduct(FindPlayerSpeed(), fwd2) > 0.0f)\n\t\t\treturn false;\n\t\t// too close\n\t\tif(fwd.Magnitude() < 2.0f)\n\t\t\treturn true;\n\n\t\tSetCamPositionForFixedMode(camPos, CVector(0.0f, 0.0f, 0.0f));\n\t\tTakeControl(FindPlayerEntity(), CCam::MODE_FIXED, JUMP_CUT, CAMCONTROL_OBBE);\n\t\treturn true;\n\tcase OBBE_18:\n\t\tcamPos = FindPlayerCoors();\n\t\tif(FindPlayerVehicle() && FindPlayerVehicle()->IsBoat())\n\t\t\tcamPos.z += 23.0f;\n\t\telse\n\t\t\tcamPos.z -= 23.0f;\n\t\tplayerSpeed = FindPlayerSpeed();\n\t\tangle = CGeneral::GetATanOfXY(playerSpeed.x, playerSpeed.y) + DEGTORAD(145.0f);\n\t\tplayerSpeed += CVector(Cos(angle), Sin(angle), 0.0f);\n\t\tplayerSpeed.Normalise();\n\t\tcamPos += 15.0f*playerSpeed;\n\n\t\tfoundGround = false;\n\t\tground = CWorld::FindGroundZFor3DCoord(camPos.x, camPos.y, camPos.z+5.0f, &foundGround);\n#ifdef FIX_BUGS\n\t\tif(foundGround)\n#else\n\t\tif(ground == true)\n#endif\n\t\t{\n\t\t\tif(camPos.z < ground)\n\t\t\t\tcamPos.z = ground + 0.5f;\n\t\t}else if(CWaterLevel::GetWaterLevelNoWaves(camPos.x, camPos.y, camPos.z, &ground)){\n\t\t\tfloat waterOffset = 1.0f;\n\t\t\tif(FindPlayerVehicle() && FindPlayerVehicle()->IsBoat())\n\t\t\t\twaterOffset = -2.0f;\n\t\t\tif(camPos.z < ground + waterOffset)\n\t\t\t\tcamPos.z = ground + waterOffset;\n\t\t}\n\t\tif(!CWorld::GetIsLineOfSightClear(FindPlayerCoors(), camPos, true, false, false, false, false, false, false))\n\t\t\treturn false;\n\n\t\tfwd = FindPlayerCoors() - camPos;\n\t\t// too far\n\t\tif(fwd.Magnitude() > 57.0f)\n\t\t\treturn false;\n\t\t// too close\n\t\tif(fwd.Magnitude() < 1.0f)\n\t\t\treturn true;\n\n\t\tSetCamPositionForFixedMode(camPos, CVector(0.0f, 0.0f, 0.0f));\n\t\tTakeControl(FindPlayerEntity(), CCam::MODE_FIXED, JUMP_CUT, CAMCONTROL_OBBE);\n\t\treturn true;\n\tcase OBBE_19:\n\t\tcamPos = FindPlayerCoors();\n\t\tif(FindPlayerVehicle() && FindPlayerVehicle()->IsBoat())\n\t\t\tcamPos.z += 4.0f;\n\t\telse\n\t\t\tcamPos.z -= 1.0f;\n\t\tplayerSpeed = FindPlayerSpeed();\n\t\tangle = CGeneral::GetATanOfXY(playerSpeed.x, playerSpeed.y) + DEGTORAD(28.0f);\n\t\tplayerSpeed += CVector(Cos(angle), Sin(angle), 0.0f);\n\t\tplayerSpeed.Normalise();\n\t\tcamPos += 12.5f*playerSpeed;\n\n\t\tfoundGround = false;\n\t\tground = CWorld::FindGroundZFor3DCoord(camPos.x, camPos.y, camPos.z+5.0f, &foundGround);\n#ifdef FIX_BUGS\n\t\tif(foundGround)\n#else\n\t\tif(ground == true)\n#endif\n\t\t{\n\t\t\tif(camPos.z < ground)\n\t\t\t\tcamPos.z = ground + 0.5f;\n\t\t}else if(CWaterLevel::GetWaterLevelNoWaves(camPos.x, camPos.y, camPos.z, &ground)){\n\t\t\tfloat waterOffset = 1.0f;\n\t\t\tif(FindPlayerVehicle() && FindPlayerVehicle()->IsBoat())\n\t\t\t\twaterOffset = -2.0f;\n\t\t\tif(camPos.z < ground + waterOffset)\n\t\t\t\tcamPos.z = ground + waterOffset;\n\t\t}\n\t\tif(!CWorld::GetIsLineOfSightClear(FindPlayerCoors(), camPos, true, false, false, false, false, false, false))\n\t\t\treturn false;\n\n\t\tfwd = FindPlayerCoors() - camPos;\n\t\t// too far\n\t\tif(fwd.Magnitude() > 36.0f)\n\t\t\treturn false;\n\t\t// too close\n\t\tif(fwd.Magnitude() < 2.0f)\n\t\t\treturn true;\n\n\t\tSetCamPositionForFixedMode(camPos, CVector(0.0f, 0.0f, 0.0f));\n\t\tTakeControl(FindPlayerEntity(), CCam::MODE_FIXED, JUMP_CUT, CAMCONTROL_OBBE);\n\t\treturn true;\n\tcase OBBE_ONSTRING_HELI:\n\t\tTakeControl(FindPlayerEntity(), CCam::MODE_CAM_ON_A_STRING, JUMP_CUT, CAMCONTROL_OBBE);\n\t\treturn true;\n\tdefault:\n\t\treturn false;\n\t}\n}\n\nint32 SequenceOfCarCams[16] = {\n\tOBBE_WHEEL, OBBE_COPCAR, OBBE_3, OBBE_1, OBBE_3, OBBE_COPCAR_WHEEL,\n\tOBBE_2, OBBE_3, OBBE_COPCAR_WHEEL, OBBE_COPCAR, OBBE_2, OBBE_3,\n\tOBBE_5, OBBE_3,\n\tOBBE_ONSTRING\t// actually unused...\n};\n\nvoid\nCCamera::ProcessObbeCinemaCameraCar(void)\n{\n\tstatic int OldMode = -1;\n\tstatic int32 TimeForNext = 0;\n\tint i = 0;\n\n\tif(!bDidWeProcessAnyCinemaCam){\n\t\tOldMode = -1;\n\t\tbSwitchedToObbeCam = true;\n\t}\n\n\tif(!bDidWeProcessAnyCinemaCam || IsItTimeForNewcam(SequenceOfCarCams[OldMode], TimeForNext)){\n\t\t// This is very strange code...\n\t\tfor(OldMode = (OldMode+1) % 14;\n\t\t    !TryToStartNewCamMode(SequenceOfCarCams[OldMode]) && i <= 14;\n\t\t    OldMode = (OldMode+1) % 14)\n\t\t\ti++;\n\t\tTimeForNext = CTimer::GetTimeInMilliseconds();\n\t\tif(i >= 14){\n\t\t\tOldMode = 14;\n\t\t\tTryToStartNewCamMode(SequenceOfCarCams[14]);\n\t\t}\n\t}\n\n\tm_iModeObbeCamIsInForCar = OldMode;\n\tbDidWeProcessAnyCinemaCam = true;\n}\n\nint32 SequenceOfHeliCams[6] = { OBBE_14, OBBE_15, OBBE_16, OBBE_17, OBBE_18, OBBE_19 };\n\nvoid\nCCamera::ProcessObbeCinemaCameraHeli(void)\n{\n\tstatic int OldMode = -1;\n\tstatic int32 TimeForNext = 0;\n\tint i = 0;\n\n\tif(!bDidWeProcessAnyCinemaCam){\n\t\tOldMode = -1;\n\t\tbSwitchedToObbeCam = true;\n\t}\n\n\tif(!bDidWeProcessAnyCinemaCam || IsItTimeForNewcam(SequenceOfHeliCams[OldMode], TimeForNext)){\n\t\t// This is very strange code...\n\t\tfor(OldMode = (OldMode+1) % 6;\n\t\t    !TryToStartNewCamMode(SequenceOfCarCams[OldMode]) && i <= 6;\n\t\t    OldMode = (OldMode+1) % 6)\n\t\t\ti++;\n\t\tif(i >= 6){\n\t\t\tOldMode = 6;\n\t\t\tif(Cams[ActiveCam].Mode != CCam::MODE_CAM_ON_A_STRING){\n\t\t\t\tTryToStartNewCamMode(OBBE_ONSTRING_HELI);\n\t\t\t\tTimeForNext = CTimer::GetTimeInMilliseconds();\n\t\t\t}\n\t\t}else\n\t\t\tTimeForNext = CTimer::GetTimeInMilliseconds();\n\t}\n\n\tm_iModeObbeCamIsInForCar = OldMode;\n\tbDidWeProcessAnyCinemaCam = true;\n}\n\nint32 SequenceOfPedCams[5] = { OBBE_9, OBBE_10, OBBE_11, OBBE_12, OBBE_13 };\n\nvoid\nCCamera::ProcessObbeCinemaCameraPed(void)\n{\n\t// static bool bObbePedProcessed = false;\t// unused\n\tstatic int PedOldMode = -1;\n\tstatic int32 PedTimeForNext = 0;\n\n\tif(!bDidWeProcessAnyCinemaCam)\n\t\tPedOldMode = -1;\n\n\tif(!bDidWeProcessAnyCinemaCam || IsItTimeForNewcam(SequenceOfPedCams[PedOldMode], PedTimeForNext)){\n\t\tfor(PedOldMode = (PedOldMode+1) % 5;\n\t\t    !TryToStartNewCamMode(SequenceOfPedCams[PedOldMode]);\n\t\t    PedOldMode = (PedOldMode+1) % 5);\n\t\tPedTimeForNext = CTimer::GetTimeInMilliseconds();\n\t}\n\tbDidWeProcessAnyCinemaCam = true;\n}\n\nvoid\nCCamera::DontProcessObbeCinemaCamera(void)\n{\n\tbDidWeProcessAnyCinemaCam = false;\n}\n\n#ifdef GTA_TRAIN\nvoid\nCCamera::LoadTrainCamNodes(char const *name)\n{\n\tCFileMgr::SetDir(\"data\");\n\n\tchar token[16] = { 0 };\n\tchar filename[16] = { 0 };\n\tuint8 *buf;\n\tssize_t bufpos = 0;\n\tint field = 0;\n\tint tokpos = 0;\n\tchar c;\n\tint i;\n\tssize_t len;\n\n\tstrcpy(filename, name);\n\tlen = (int)strlen(filename);\n\tfilename[len] = '.';\n\tfilename[len+1] = 'd';\n\tfilename[len+2] = 'a';\n\tfilename[len+3] = 't';\n\n\tm_uiNumberOfTrainCamNodes = 0;\n\n\tbuf = new uint8[20000];\n\tlen = CFileMgr::LoadFile(filename, buf, 20000, \"r\");\n\n\tfor(i = 0; i < MAX_NUM_OF_NODES; i++){\n\t\tm_arrTrainCamNode[i].m_cvecPointToLookAt = CVector(0.0f, 0.0f, 0.0f);\n\t\tm_arrTrainCamNode[i].m_cvecMinPointInRange = CVector(0.0f, 0.0f, 0.0f);\n\t\tm_arrTrainCamNode[i].m_cvecMaxPointInRange = CVector(0.0f, 0.0f, 0.0f);\n\t\tm_arrTrainCamNode[i].m_fDesiredFOV = 0.0f;\n\t\tm_arrTrainCamNode[i].m_fNearClip = 0.0f;\n\t}\n\n\twhile(bufpos <= len){\n\t\tc = buf[bufpos];\n\t\tswitch(c){\n\t\tcase '-':\n\t\tcase '.':\n\t\tcase '0': case '1': case '2': case '3': case '4':\n\t\tcase '5': case '6': case '7': case '8': case '9':\n//\t\tcase '10': case '11': case '12': case '13':\t// ahem...\n\t\t\ttoken[tokpos++] = c;\n\t\t\tbufpos++;\n\t\t\tbreak;\n\n\t\tcase ',':\n\t\tcase ';':\t// game has the code for this duplicated but we handle both under the same case\n\t\t\tswitch((field+14)%14){\n\t\t\tcase 0:\n\t\t\t\tm_arrTrainCamNode[m_uiNumberOfTrainCamNodes].m_cvecCamPosition.x = atof(token);\n\t\t\t\tbreak;\n\t\t\tcase 1:\n\t\t\t\tm_arrTrainCamNode[m_uiNumberOfTrainCamNodes].m_cvecCamPosition.y = atof(token);\n\t\t\t\tbreak;\n\t\t\tcase 2:\n\t\t\t\tm_arrTrainCamNode[m_uiNumberOfTrainCamNodes].m_cvecCamPosition.z = atof(token);\n\t\t\t\tbreak;\n\t\t\tcase 3:\n\t\t\t\tm_arrTrainCamNode[m_uiNumberOfTrainCamNodes].m_cvecPointToLookAt.x = atof(token);\n\t\t\t\tbreak;\n\t\t\tcase 4:\n\t\t\t\tm_arrTrainCamNode[m_uiNumberOfTrainCamNodes].m_cvecPointToLookAt.y = atof(token);\n\t\t\t\tbreak;\n\t\t\tcase 5:\n\t\t\t\tm_arrTrainCamNode[m_uiNumberOfTrainCamNodes].m_cvecPointToLookAt.z = atof(token);\n\t\t\t\tbreak;\n\t\t\tcase 6:\n\t\t\t\tm_arrTrainCamNode[m_uiNumberOfTrainCamNodes].m_cvecMinPointInRange.x = atof(token);\n\t\t\t\tbreak;\n\t\t\tcase 7:\n\t\t\t\tm_arrTrainCamNode[m_uiNumberOfTrainCamNodes].m_cvecMinPointInRange.y = atof(token);\n\t\t\t\tbreak;\n\t\t\tcase 8:\n\t\t\t\tm_arrTrainCamNode[m_uiNumberOfTrainCamNodes].m_cvecMinPointInRange.z = atof(token);\n\t\t\t\tbreak;\n\t\t\tcase 9:\n\t\t\t\tm_arrTrainCamNode[m_uiNumberOfTrainCamNodes].m_cvecMaxPointInRange.x = atof(token);\n\t\t\t\tbreak;\n\t\t\tcase 10:\n\t\t\t\tm_arrTrainCamNode[m_uiNumberOfTrainCamNodes].m_cvecMaxPointInRange.y = atof(token);\n\t\t\t\tbreak;\n\t\t\tcase 11:\n\t\t\t\tm_arrTrainCamNode[m_uiNumberOfTrainCamNodes].m_cvecMaxPointInRange.z = atof(token);\n\t\t\t\tbreak;\n\t\t\tcase 12:\n\t\t\t\tm_arrTrainCamNode[m_uiNumberOfTrainCamNodes].m_fDesiredFOV = atof(token);\n\t\t\t\tbreak;\n\t\t\tcase 13:\n\t\t\t\tm_arrTrainCamNode[m_uiNumberOfTrainCamNodes].m_fNearClip = atof(token);\n\t\t\t\tm_uiNumberOfTrainCamNodes++;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tfield++;\n\t\t\tbufpos++;\n\t\t\tmemset(token, 0, sizeof(token));\n\t\t\ttokpos = 0;\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tbufpos++;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tdelete[] buf;\n\tCFileMgr::SetDir(\"\");\n}\n\nvoid\nCCamera::Process_Train_Camera_Control(void)\n{\n\tbool found = false;\n\tCTrain *target = (CTrain*)pTargetEntity;\n\tm_bUseSpecialFovTrain = true;\n\tstatic bool OKtoGoBackToNodeCam = true;\t// only ever set to true\n\tuint32 i;\n\n\tif(target->m_nTrackId == TRACK_ELTRAIN && !m_bAboveGroundTrainNodesLoaded){\n\t\tm_bAboveGroundTrainNodesLoaded = true;\n\t\tm_bBelowGroundTrainNodesLoaded = false;\n\t\tLoadTrainCamNodes(\"Train\");\n\t\tm_uiTimeLastChange = CTimer::GetTimeInMilliseconds();\n\t\tOKtoGoBackToNodeCam = true;\n\t\tm_iCurrentTrainCamNode = 0;\n\t}\n\tif(target->m_nTrackId == TRACK_SUBWAY && !m_bBelowGroundTrainNodesLoaded){\n\t\tm_bBelowGroundTrainNodesLoaded = true;\n\t\tm_bAboveGroundTrainNodesLoaded = false;\n\t\tLoadTrainCamNodes(\"Train2\");\n\t\tm_uiTimeLastChange = CTimer::GetTimeInMilliseconds();\n\t\tOKtoGoBackToNodeCam = true;\n\t\tm_iCurrentTrainCamNode = 0;\n\t}\n\n\tm_bTargetJustBeenOnTrain = true;\n\tuint32 node = m_iCurrentTrainCamNode;\n\tfor(i = 0; i < m_uiNumberOfTrainCamNodes && !found; i++){\n\t\tif(target->IsWithinArea(m_arrTrainCamNode[node].m_cvecMinPointInRange.x,\n\t\t                        m_arrTrainCamNode[node].m_cvecMinPointInRange.y,\n\t\t                        m_arrTrainCamNode[node].m_cvecMinPointInRange.z,\n\t\t                        m_arrTrainCamNode[node].m_cvecMaxPointInRange.x,\n\t\t                        m_arrTrainCamNode[node].m_cvecMaxPointInRange.y,\n\t\t                        m_arrTrainCamNode[node].m_cvecMaxPointInRange.z)){\n\t\t\tm_iCurrentTrainCamNode = node;\n\t\t\tfound = true;\n\t\t}\n\t\tnode++;\n\t\tif(node >= m_uiNumberOfTrainCamNodes)\n\t\t\tnode = 0;\n\t}\n#ifdef FIX_BUGS\n\t// Not really a bug but be nice and respect the debug mode\n\tif(DebugCamMode){\n\t\tTakeControl(target, DebugCamMode, JUMP_CUT, CAMCONTROL_SCRIPT);\n\t\treturn;\n\t}\n#endif\n\n\tif(found){\n\t\tSetWideScreenOn();\n\t\tif(DotProduct(((CTrain*)pTargetEntity)->GetMoveSpeed(), pTargetEntity->GetForward()) < 0.001f){\n\t\t\tTakeControl(FindPlayerPed(), CCam::MODE_FOLLOWPED, JUMP_CUT, CAMCONTROL_SCRIPT);\n\t\t\tif(target->Doors[0].IsFullyOpen())\n\t\t\t\tSetWideScreenOff();\n\t\t}else{\n\t\t\tSetCamPositionForFixedMode(m_arrTrainCamNode[m_iCurrentTrainCamNode].m_cvecCamPosition, CVector(0.0f, 0.0f, 0.0f));\n\t\t\tif(m_arrTrainCamNode[m_iCurrentTrainCamNode].m_cvecPointToLookAt.x == 999.0f &&\n\t\t\t   m_arrTrainCamNode[m_iCurrentTrainCamNode].m_cvecPointToLookAt.y == 999.0f &&\n\t\t\t   m_arrTrainCamNode[m_iCurrentTrainCamNode].m_cvecPointToLookAt.z == 999.0f)\n\t\t\t\tTakeControl(target, CCam::MODE_FIXED, JUMP_CUT, CAMCONTROL_SCRIPT);\n\t\t\telse\n\t\t\t\tTakeControlNoEntity(m_arrTrainCamNode[m_iCurrentTrainCamNode].m_cvecPointToLookAt, JUMP_CUT, CAMCONTROL_SCRIPT);\n\t\t\tRwCameraSetNearClipPlane(Scene.camera, m_arrTrainCamNode[m_iCurrentTrainCamNode].m_fNearClip);\n\t\t}\n\t}else{\n\t\tif(DotProduct(((CTrain*)pTargetEntity)->GetMoveSpeed(), pTargetEntity->GetForward()) < 0.001f){\n\t\t\tTakeControl(FindPlayerPed(), CCam::MODE_FOLLOWPED, JUMP_CUT, CAMCONTROL_SCRIPT);\n\t\t\tif(target->Doors[0].IsFullyOpen())\n\t\t\t\tSetWideScreenOff();\n\t\t}\n\t}\n}\n#endif\n\n\nvoid\nCCamera::LoadPathSplines(int file)\n{\n\tbool reading = true;\n\tchar c, token[32] = { 0 };\n\tint i, j, n;\n\n\tn = 0;\n\n\tDeleteCutSceneCamDataMemory();\n\tfor(i = 0; i < MAX_NUM_OF_SPLINETYPES; i++)\n\t\tm_arrPathArray[i].m_arr_PathData = new float[CCamPathSplines::MAXPATHLENGTH];\n\n//\tWhy is this gone?\n//\tfor(i = 0; i < MAX_NUM_OF_SPLINETYPES; i++)\n//\t\tfor(j = 0; j < CCamPathSplines::MAXPATHLENGTH; j++)\n//\t\t\tm_arrPathArray[i].m_arr_PathData[j] = 0.0f;\n\n\tm_bStartingSpline = false;\n\n\ti = 0;\n\tj = 0;\n\twhile(reading){\n\t\tCFileMgr::Read(file, &c, 1);\n\t\tswitch(c){\n\t\tcase '\\0':\n\t\t\treading = false;\n\t\t\tbreak;\n\n\t\tcase '+': case '-': case '.':\n\t\tcase '0': case '1': case '2': case '3': case '4':\n\t\tcase '5': case '6': case '7': case '8': case '9':\n\t\tcase 'e': case 'E':\n\t\t\ttoken[n++] = c;\n\t\t\tbreak;\n\n\t\tcase ',':\n#ifdef FIX_BUGS\n\t\t\tif(i < MAX_NUM_OF_SPLINETYPES && j < CCamPathSplines::MAXPATHLENGTH)\n#endif\n\t\t\tm_arrPathArray[i].m_arr_PathData[j] = atof(token);\n\t\t\tj++;\n\t\t\tmemset(token, 0, 32);\n\t\t\tn = 0;\n\t\t\tbreak;\n\n\t\tcase ';':\n#ifdef FIX_BUGS\n\t\t\tif(i < MAX_NUM_OF_SPLINETYPES && j < CCamPathSplines::MAXPATHLENGTH)\n#endif\n\t\t\tm_arrPathArray[i].m_arr_PathData[j] = atof(token);\n\t\t\ti++;\n\t\t\tj = 0;\n\t\t\tif (i == MAX_NUM_OF_SPLINETYPES)\n\t\t\t\treading = false;\n\t\t\tmemset(token, 0, 32);\n\t\t\tn = 0;\n\t\t}\n\t}\n}\n\nvoid\nCCamera::DeleteCutSceneCamDataMemory(void)\n{\n\tint i;\n\tfor(i = 0; i < MAX_NUM_OF_SPLINETYPES; i++)\n\t\tif(m_arrPathArray[i].m_arr_PathData){\n\t\t\tdelete[] m_arrPathArray[i].m_arr_PathData;\n\t\t\tm_arrPathArray[i].m_arr_PathData = nil;\n\t\t}\n}\n\nvoid\nCCamera::FinishCutscene(void)\n{\n\tSetPercentAlongCutScene(100.0f);\n\tm_fPositionAlongSpline = 1.0f;\n\tm_bcutsceneFinished = true;\n}\n\nuint32\nCCamera::GetCutSceneFinishTime(void)\n{\n\tint cam = ActiveCam;\n\tif (Cams[cam].Mode == CCam::MODE_FLYBY)\n\t\treturn Cams[cam].m_uiFinishTime;\n\tcam = (cam + 1) % 2;\n\tif (Cams[cam].Mode == CCam::MODE_FLYBY)\n\t\treturn Cams[cam].m_uiFinishTime;\n\n\treturn 0;\n}\n\nvoid\nCCamera::SetCamCutSceneOffSet(const CVector &pos)\n{\n\tm_vecCutSceneOffset = pos;\n};\n\nvoid\nCCamera::SetPercentAlongCutScene(float percent)\n{\n\tif(Cams[ActiveCam].Mode == CCam::MODE_FLYBY)\n\t\tCams[ActiveCam].m_fTimeElapsedFloat = percent/100.0f * Cams[ActiveCam].m_uiFinishTime;\n\telse if(Cams[(ActiveCam+1)%2].Mode == CCam::MODE_FLYBY)\n\t\tCams[(ActiveCam+1)%2].m_fTimeElapsedFloat = percent/100.0f * Cams[(ActiveCam+1)%2].m_uiFinishTime;\n}\n\nvoid\nCCamera::SetParametersForScriptInterpolation(float stopMoving, float catchUp, int32 time)\n{\n\tm_fScriptPercentageInterToStopMoving = stopMoving * 0.01f;\n\tm_fScriptPercentageInterToCatchUp = catchUp * 0.01f;\n\tm_fScriptTimeForInterPolation = time;\n\tm_bScriptParametersSetForInterPol = true;\n}\n\nvoid\nCCamera::SetZoomValueFollowPedScript(int16 dist)\n{\n\tswitch (dist) {\n\tcase 0: m_fPedZoomValueScript = 0.25f; break;\n\tcase 1: m_fPedZoomValueScript = 1.5f; break;\n\tcase 2: m_fPedZoomValueScript = 2.9f; break;\n\tdefault: break;\n\t}\n\n\tm_bUseScriptZoomValuePed = true;\n}\n\nvoid\nCCamera::SetZoomValueCamStringScript(int16 dist)\n{\n\tif (Cams[ActiveCam].CamTargetEntity->IsVehicle()) {\n\t\tint vehApp = ((CVehicle*)Cams[ActiveCam].CamTargetEntity)->GetVehicleAppearance();\n\t\tint vehArrPos = 0;\n\t\tGetArrPosForVehicleType(vehApp, vehArrPos);\n\n#ifdef FREE_CAM\n\t\tif (bFreeCam) {\n\t\t\tswitch (dist) {\n\t\t\tcase 0: m_fCarZoomValueScript = LCS_ZOOM_ONE_DISTANCE[vehArrPos]; break;\n\t\t\tcase 1: m_fCarZoomValueScript = LCS_ZOOM_TWO_DISTANCE[vehArrPos]; break;\n\t\t\tcase 2: m_fCarZoomValueScript = LCS_ZOOM_THREE_DISTANCE[vehArrPos]; break;\n\t\t\tdefault: break;\n\t\t\t}\n\t\t}\n\t\telse\n#endif\n\t\t{\n\t\t\tswitch (dist) {\n\t\t\tcase 0: m_fCarZoomValueScript = ZOOM_ONE_DISTANCE[vehArrPos]; break;\n\t\t\tcase 1: m_fCarZoomValueScript = ZOOM_TWO_DISTANCE[vehArrPos]; break;\n\t\t\tcase 2: m_fCarZoomValueScript = ZOOM_THREE_DISTANCE[vehArrPos]; break;\n\t\t\tdefault: break;\n\t\t\t}\n\t\t}\n\n\t\tm_bUseScriptZoomValueCar = true;\n\t} else {\n\t\tswitch (dist) {\n\t\tcase 0: m_fPedZoomValueScript = 0.25f; break;\n\t\tcase 1: m_fPedZoomValueScript = 1.5f; break;\n\t\tcase 2: m_fPedZoomValueScript = 2.9f; break;\n\t\tdefault: break;\n\t\t}\n\n\t\tm_bUseScriptZoomValuePed = true;\n\t}\n}\n\nvoid\nCCamera::SetNearClipScript(float clip)\n{\n\tm_fNearClipScript = clip;\n\tm_bUseNearClipScript = true;\n}\n\n\n\nvoid\nCCamera::ProcessFade(void)\n{\n\tif(m_bFading){\n\t\tif(m_iFadingDirection == FADE_IN){\n\t\t\tif(m_fTimeToFadeOut != 0.0f)\n\t\t\t\tm_fFLOATingFade -= CTimer::GetTimeStepInSeconds() * 255.0f / m_fTimeToFadeOut;\n\t\t\telse\n\t\t\t\tm_fFLOATingFade = 0.0f;\n\t\t\tif (m_fFLOATingFade <= 0.0f) {\n\t\t\t\tm_bFading = false;\n\t\t\t\tm_fFLOATingFade = 0.0f;\n\t\t\t}\n\t\t}else if(m_iFadingDirection == FADE_OUT){\n\t\t\tif(m_fTimeToFadeOut != 0.0f)\n\t\t\t\tm_fFLOATingFade += CTimer::GetTimeStepInSeconds() * 255.0f / m_fTimeToFadeOut;\n\t\t\telse\n\t\t\t\tm_fFLOATingFade = 255.0f;\n\t\t\tif (m_fFLOATingFade >= 255.0f) {\n\t\t\t\tm_bFading = false;\n\t\t\t\tm_fFLOATingFade = 255.0f;\n\t\t\t}\n\t\t}\n\t\tCDraw::FadeValue = m_fFLOATingFade;\n\t}\n}\n\nvoid\nCCamera::ProcessMusicFade(void)\n{\n\tif(m_bMusicFading){\n\t\tif(m_iMusicFadingDirection == FADE_IN){\n\t\t\tif(m_fTimeToFadeMusic == 0.0f)\n\t\t\t\tm_fFLOATingFadeMusic = 0.0f;\n\t\t\telse\n\t\t\t\tm_fFLOATingFadeMusic -= 255.0f*CTimer::GetTimeStepInSeconds()/m_fTimeToFadeMusic;\n\t\t\tif(m_fFLOATingFadeMusic <= 0.0f){\n\t\t\t\tm_bMusicFading = false;\n\t\t\t\tm_fFLOATingFadeMusic = 0.0f;\n\t\t\t}\n\t\t}else if(m_iMusicFadingDirection == FADE_OUT){\n\t\t\tif(m_fTimeToFadeMusic == 0.0f)\n\t\t\t\tm_fFLOATingFadeMusic = 255.0f;\n\t\t\telse\n\t\t\t\tm_fFLOATingFadeMusic += 255.0f*CTimer::GetTimeStepInSeconds()/m_fTimeToFadeMusic;\n\t\t\tif(m_fFLOATingFadeMusic >= 255.0f){\n\t\t\t\tm_bMusicFading = false;\n\t\t\t\tm_fFLOATingFadeMusic = 255.0f;\n\t\t\t}\n\t\t}\n\t\tDMAudio.SetEffectsFadeVol(127 - m_fFLOATingFadeMusic/255.0f * 127);\n\t\tDMAudio.SetMusicFadeVol(127 - m_fFLOATingFadeMusic/255.0f * 127);\n\t}\n}\n\nvoid\nCCamera::Fade(float timeout, int16 direction)\n{\n\tm_bFading = true;\n\tm_iFadingDirection = direction;\n\tm_fTimeToFadeOut = timeout;\n\tm_uiFadeTimeStarted = CTimer::GetTimeInMilliseconds();\n\tif(!m_bIgnoreFadingStuffForMusic){\n\t\tm_bMusicFading = true;\n\t\tm_iMusicFadingDirection = direction;\n\t\tm_fTimeToFadeMusic = timeout;\n\t\tm_uiFadeTimeStartedMusic = CTimer::GetTimeInMilliseconds();\n\t}\n}\n\nvoid\nCCamera::SetFadeColour(uint8 r, uint8 g, uint8 b)\n{\n\tm_FadeTargetIsSplashScreen = r == 2 && g == 2 && b == 2;\n\tCDraw::FadeRed = r;\n\tCDraw::FadeGreen = g;\n\tCDraw::FadeBlue = b;\n}\n\nbool\nCCamera::GetFading(void)\n{\n\treturn m_bFading;\n}\n\nint\nCCamera::GetFadingDirection(void)\n{\n\tif(m_bFading)\n\t\treturn m_iFadingDirection == FADE_IN ? FADE_IN : FADE_OUT;\n\telse\n\t\treturn FADE_NONE;\n}\n\nint\nCCamera::GetScreenFadeStatus(void)\n{\n\tif(m_fFLOATingFade == 0.0f)\n\t\treturn FADE_0;\n\tif(m_fFLOATingFade == 255.0f)\n\t\treturn FADE_2;\n\treturn FADE_1;\n}\n\n\n\nvoid\nCCamera::RenderMotionBlur(void)\n{\n\tif(m_BlurType == 0)\n\t\treturn;\n\n\tCMBlur::MotionBlurRender(m_pRwCamera,\n\t\tm_BlurRed, m_BlurGreen, m_BlurBlue,\n\t\tm_motionBlur, m_BlurType, m_imotionBlurAddAlpha);\n}\n\nvoid\nCCamera::SetMotionBlur(int r, int g, int b, int a, int type)\n{\n\tm_BlurRed = r;\n\tm_BlurGreen = g;\n\tm_BlurBlue = b;\n\tm_motionBlur = a;\n\tm_BlurType = type;\n}\n\nvoid\nCCamera::SetMotionBlurAlpha(int a)\n{\n\tm_imotionBlurAddAlpha = a;\n}\n\n\n\nint\nCCamera::GetLookDirection(void)\n{\n\tif(Cams[ActiveCam].Mode == CCam::MODE_CAM_ON_A_STRING ||\n\t   Cams[ActiveCam].Mode == CCam::MODE_1STPERSON ||\n\t   Cams[ActiveCam].Mode == CCam::MODE_BEHINDBOAT ||\n\t   Cams[ActiveCam].Mode == CCam::MODE_FOLLOWPED)\n\t\treturn Cams[ActiveCam].DirectionWasLooking;\n\treturn LOOKING_FORWARD;\n}\n\nbool\nCCamera::GetLookingForwardFirstPerson(void)\n{\n\treturn Cams[ActiveCam].Mode == CCam::MODE_1STPERSON &&\n\t\tCams[ActiveCam].DirectionWasLooking == LOOKING_FORWARD;\n}\n\nbool\nCCamera::GetLookingLRBFirstPerson(void)\n{\n\treturn Cams[ActiveCam].Mode == CCam::MODE_1STPERSON && Cams[ActiveCam].DirectionWasLooking != LOOKING_FORWARD;\n}\n\nvoid\nCCamera::SetCameraDirectlyBehindForFollowPed_CamOnAString(void)\n{\n\tm_bCamDirectlyBehind = true;\n\tCPlayerPed *player = FindPlayerPed();\n\tif (player)\n\t\tm_PedOrientForBehindOrInFront = CGeneral::GetATanOfXY(player->GetForward().x, player->GetForward().y);\n}\n\nvoid\nCCamera::SetCameraDirectlyInFrontForFollowPed_CamOnAString(void)\n{\n\tm_bCamDirectlyInFront = true;\n\tCPlayerPed *player = FindPlayerPed();\n\tif (player)\n\t\tm_PedOrientForBehindOrInFront = CGeneral::GetATanOfXY(player->GetForward().x, player->GetForward().y);\n}\n\nvoid\nCCamera::SetNewPlayerWeaponMode(int16 mode, int16 minZoom, int16 maxZoom)\n{\n\tSetMotionBlur(CTimeCycle::GetBlurRed(), CTimeCycle::GetBlurGreen(), CTimeCycle::GetBlurBlue(), m_motionBlur, MOTION_BLUR_LIGHT_SCENE);\n\tPlayerWeaponMode.Mode = mode;\n\tPlayerWeaponMode.MaxZoom = maxZoom;\n\tPlayerWeaponMode.MinZoom = minZoom;\n\tPlayerWeaponMode.Duration = 0.0f;\n}\n\nvoid\nCCamera::ClearPlayerWeaponMode(void)\n{\n\tSetMotionBlur(CTimeCycle::GetBlurRed(), CTimeCycle::GetBlurGreen(), CTimeCycle::GetBlurBlue(), m_motionBlur, MOTION_BLUR_LIGHT_SCENE);\n\tPlayerWeaponMode.Mode = 0;\n\tPlayerWeaponMode.MaxZoom = 1;\n\tPlayerWeaponMode.MinZoom = -1;\n\tPlayerWeaponMode.Duration = 0.0f;\n}\n\nvoid\nCCamera::UpdateAimingCoors(CVector const &coors)\n{\n\tm_cvecAimingTargetCoors = coors;\n}\n\nbool\nCCamera::Find3rdPersonCamTargetVector(float dist, CVector pos, CVector &source, CVector &target)\n{\n\tif(CPad::GetPad(0)->GetLookBehindForPed()){\n\t\tsource = pos;\n\t\ttarget = dist*Cams[ActiveCam].CamTargetEntity->GetForward() + source;\n\t\treturn false;\n\t}else{\n\t\tfloat angleX = DEGTORAD((m_f3rdPersonCHairMultX-0.5f) * 1.8f * 0.5f * Cams[ActiveCam].FOV * CDraw::GetAspectRatio());\n\t\tfloat angleY = DEGTORAD((0.5f-m_f3rdPersonCHairMultY) * 1.8f * 0.5f * Cams[ActiveCam].FOV);\n\t\tsource = Cams[ActiveCam].Source;\n\t\ttarget = Cams[ActiveCam].Front;\n\t\ttarget += Cams[ActiveCam].Up * Tan(angleY);\n\t\ttarget += CrossProduct(Cams[ActiveCam].Front, Cams[ActiveCam].Up) * Tan(angleX);\n\t\ttarget.Normalise();\n\t\tsource += DotProduct(pos - source, target)*target;\n\t\ttarget = dist*target + source;\n\t\treturn true;\n\t}\n}\n\nfloat\nCCamera::Find3rdPersonQuickAimPitch(void)\n{\n\tfloat clampedFrontZ = clamp(Cams[ActiveCam].Front.z, -1.0f, 1.0f);\n\n\tfloat rot = Asin(clampedFrontZ);\n\n\treturn -(DEGTORAD(((0.5f - m_f3rdPersonCHairMultY) * 1.8f * 0.5f * Cams[ActiveCam].FOV)) + rot);\n}\n\nbool\nCCamera::Using1stPersonWeaponMode(void)\n{\n\tswitch(PlayerWeaponMode.Mode)\n\tcase CCam::MODE_SNIPER:\n\tcase CCam::MODE_M16_1STPERSON:\n\tcase CCam::MODE_ROCKETLAUNCHER:\n\tcase CCam::MODE_HELICANNON_1STPERSON:\n\tcase CCam::MODE_CAMERA:\n\t\treturn true;\n\treturn false;\n}\n\n\nvoid\nCCamera::SetRwCamera(RwCamera *cam)\n{\n\tm_pRwCamera = cam;\n\tm_viewMatrix.Attach(RwCameraGetViewMatrix(m_pRwCamera), false);\n\tCMBlur::MotionBlurOpen(m_pRwCamera);\n}\n\nvoid\nCCamera::CalculateDerivedValues(void)\n{\n\tm_cameraMatrix = Invert(m_matrix);\n\n\tfloat hfov = DEGTORAD(CDraw::GetScaledFOV()/2.0f);\n\tfloat c = Cos(hfov);\n\tfloat s = Sin(hfov);\n\n\t// right plane\n\tm_vecFrustumNormals[0] = CVector(c, -s, 0.0f);\n\t// left plane\n\tm_vecFrustumNormals[1] = CVector(-c, -s, 0.0f);\n\n\tCDraw::CalculateAspectRatio();\n\tc /= SCREEN_ASPECT_RATIO;\n\ts /= SCREEN_ASPECT_RATIO;\n\t// bottom plane\n\tm_vecFrustumNormals[2] = CVector(0.0f, -s, -c);\n\t// top plane\n\tm_vecFrustumNormals[3] = CVector(0.0f, -s, c);\n\n\tif(GetForward().x == 0.0f && GetForward().y == 0.0f)\n\t\tGetForward().x = 0.0001f;\n\telse\n\t\tOrientation = Atan2(GetForward().x, GetForward().y);\n\n\tCamFrontXNorm = GetForward().x;\n\tCamFrontYNorm = GetForward().y;\n\tfloat l = Sqrt(SQR(CamFrontXNorm) + SQR(CamFrontYNorm));\n\tif(l == 0.0f)\n\t\tCamFrontXNorm = 1.0f;\n\telse{\n\t\tCamFrontXNorm /= l;\n\t\tCamFrontYNorm /= l;\n\t}\n}\n\nbool\nCCamera::IsPointVisible(const CVector &center, const CMatrix *mat)\n{\n#ifdef GTA_PS2\n\tCVuVector c;\n\tTransformPoint(c, *mat, center);\n#else\n\tCVector c = center;\n\t#ifdef FIX_BUGS\n\t\tc = *mat * center;\n\t#else\n\t\tRwV3dTransformPoints(&c, &c, 1, (RwMatrix*)mat);\n\t#endif\n#endif\n\tif(c.y < CDraw::GetNearClipZ()) return false;\n\tif(c.y > CDraw::GetFarClipZ()) return false;\n\tif(c.x*m_vecFrustumNormals[0].x + c.y*m_vecFrustumNormals[0].y > 0.0f) return false;\n\tif(c.x*m_vecFrustumNormals[1].x + c.y*m_vecFrustumNormals[1].y > 0.0f) return false;\n\tif(c.y*m_vecFrustumNormals[2].y + c.z*m_vecFrustumNormals[2].z > 0.0f) return false;\n\tif(c.y*m_vecFrustumNormals[3].y + c.z*m_vecFrustumNormals[3].z > 0.0f) return false;\n\treturn true;\n}\n\nbool\nCCamera::IsSphereVisible(const CVector &center, float radius, const CMatrix *mat)\n{\n#ifdef GTA_PS2\n\tCVuVector c;\n\tTransformPoint(c, *mat, center);\n#else\n\tCVector c = center;\n\t#ifdef FIX_BUGS\n\t\tc = *mat * center;\n\t#else\n\t\tRwV3dTransformPoints(&c, &c, 1, (RwMatrix*)mat);\n\t#endif\n#endif\n\tif(c.y + radius < CDraw::GetNearClipZ()) return false;\n\tif(c.y - radius > CDraw::GetFarClipZ()) return false;\n\tif(c.x*m_vecFrustumNormals[0].x + c.y*m_vecFrustumNormals[0].y > radius) return false;\n\tif(c.x*m_vecFrustumNormals[1].x + c.y*m_vecFrustumNormals[1].y > radius) return false;\n\tif(c.y*m_vecFrustumNormals[2].y + c.z*m_vecFrustumNormals[2].z > radius) return false;\n\tif(c.y*m_vecFrustumNormals[3].y + c.z*m_vecFrustumNormals[3].z > radius) return false;\n\treturn true;\n}\n\nbool\nCCamera::IsSphereVisible(const CVector &center, float radius)\n{\n\tCMatrix mat = m_cameraMatrix;\n\treturn IsSphereVisible(center, radius, &mat);\n}\n\nbool\n#ifdef GTA_PS2\nCCamera::IsBoxVisible(CVuVector *box, const CMatrix *mat)\n#else\nCCamera::IsBoxVisible(CVector *box, const CMatrix *mat)\n#endif\n{\n\tint i;\n\tint frustumTests[6] = { 0 };\n#ifdef GTA_PS2\n\tTransformPoints(box, 8, *mat, box);\n#else\n\t#ifdef FIX_BUGS\n\t\tfor (i = 0; i < 8; i++)\n\t\t\tbox[i] = *mat * box[i];\n\t#else\n\t\tRwV3dTransformPoints(box, box, 8, (RwMatrix*)mat);\n\t#endif\n#endif\n\n\tfor(i = 0; i < 8; i++){\n\t\tif(box[i].y < CDraw::GetNearClipZ()) frustumTests[0]++;\n\t\tif(box[i].y > CDraw::GetFarClipZ()) frustumTests[1]++;\n\t\tif(box[i].x*m_vecFrustumNormals[0].x + box[i].y*m_vecFrustumNormals[0].y > 0.0f) frustumTests[2]++;\n\t\tif(box[i].x*m_vecFrustumNormals[1].x + box[i].y*m_vecFrustumNormals[1].y > 0.0f) frustumTests[3]++;\n//\tWhy not test z?\n//\t\tif(box[i].y*m_vecFrustumNormals[2].y + box[i].z*m_vecFrustumNormals[2].z > 0.0f) frustumTests[4]++;\n//\t\tif(box[i].y*m_vecFrustumNormals[3].y + box[i].z*m_vecFrustumNormals[3].z > 0.0f) frustumTests[5]++;\n\t}\n\tfor(i = 0; i < 6; i++)\n\t\tif(frustumTests[i] == 8)\n\t\t\treturn false;\t\t// Box is completely outside of one plane\n\treturn true;\n}\n\n\n\nCCamPathSplines::CCamPathSplines(void)\n{\n\tm_arr_PathData = nil;\n}\n"
  },
  {
    "path": "src/core/Camera.h",
    "content": "#pragma once\n#include \"Placeable.h\"\n\nclass CEntity;\nclass CPed;\nclass CAutomobile;\nclass CGarage;\n\nextern int16 DebugCamMode;\n\nenum\n{\n\tNUMBER_OF_VECTORS_FOR_AVERAGE = 2,\n\tMAX_NUM_OF_SPLINETYPES = 4,\n\tMAX_NUM_OF_NODES = 800\t// for trains\n};\n\n#define DEFAULT_NEAR (0.9f)\nenum\n{\n\tCAM_ZOOM_1STPRS,\n\tCAM_ZOOM_1,\n\tCAM_ZOOM_2,\n\tCAM_ZOOM_3,\n\tCAM_ZOOM_TOPDOWN,\n\tCAM_ZOOM_CINEMATIC,\n};\n\nconst float DefaultFOV = 70.0f; // beta: 80.0f\n\nclass CCam\n{\npublic:\n\tenum\n\t{\n\t\tMODE_NONE = 0,\n\t\tMODE_TOPDOWN,\n\t\tMODE_GTACLASSIC,\n\t\tMODE_BEHINDCAR,\n\t\tMODE_FOLLOWPED,\n\t\tMODE_AIMING,\n\t\tMODE_DEBUG,\n\t\tMODE_SNIPER,\n\t\tMODE_ROCKETLAUNCHER,\n\t\tMODE_MODELVIEW,\n\t\tMODE_BILL,\n\t\tMODE_SYPHON,\n\t\tMODE_CIRCLE,\n\t\tMODE_CHEESYZOOM,\n\t\tMODE_WHEELCAM,\n\t\tMODE_FIXED,\n\t\tMODE_1STPERSON,\n\t\tMODE_FLYBY,\n\t\tMODE_CAM_ON_A_STRING,\n\t\tMODE_REACTION,\n\t\tMODE_FOLLOW_PED_WITH_BIND,\n\t\tMODE_CHRIS,\n\t\tMODE_BEHINDBOAT,\n\t\tMODE_PLAYER_FALLEN_WATER,\n\t\tMODE_CAM_ON_TRAIN_ROOF,\n\t\tMODE_CAM_RUNNING_SIDE_TRAIN,\n\t\tMODE_BLOOD_ON_THE_TRACKS,\n\t\tMODE_IM_THE_PASSENGER_WOOWOO,\n\t\tMODE_SYPHON_CRIM_IN_FRONT,\n\t\tMODE_PED_DEAD_BABY,\n\t\tMODE_PILLOWS_PAPS,\n\t\tMODE_LOOK_AT_CARS,\n\t\tMODE_ARRESTCAM_ONE,\n\t\tMODE_ARRESTCAM_TWO,\n\t\tMODE_M16_1STPERSON,\n\t\tMODE_SPECIAL_FIXED_FOR_SYPHON,\n\t\tMODE_FIGHT_CAM,\n\t\tMODE_TOP_DOWN_PED,\n\t\tMODE_LIGHTHOUSE,\n\t\tMODE_SNIPER_RUNABOUT,\n\t\tMODE_ROCKETLAUNCHER_RUNABOUT,\n\t\tMODE_1STPERSON_RUNABOUT,\n\t\tMODE_M16_1STPERSON_RUNABOUT,\n\t\tMODE_FIGHT_CAM_RUNABOUT,\n\t\tMODE_EDITOR,\n\t\tMODE_HELICANNON_1STPERSON,\n\t\tMODE_CAMERA,\n\t};\n\n\tbool    bBelowMinDist; //used for follow ped mode\n\tbool    bBehindPlayerDesired; //used for follow ped mode\n\tbool    m_bCamLookingAtVector;\n\tbool    m_bCollisionChecksOn;\n\tbool    m_bFixingBeta; //used for camera on a string\n\tbool    m_bTheHeightFixerVehicleIsATrain;\n\tbool    LookBehindCamWasInFront;\n\tbool    LookingBehind;\n\tbool    LookingLeft;\n\tbool    LookingRight;\n\tbool    ResetStatics; //for interpolation type stuff to work\n\tbool    Rotating;\n\n\tint16   Mode;                   // CameraMode\n\tuint32  m_uiFinishTime;\n\n\tint     m_iDoCollisionChecksOnFrameNum; \n\tint     m_iDoCollisionCheckEveryNumOfFrames;\n\tint     m_iFrameNumWereAt;\n\tint     m_iRunningVectorArrayPos;\n\tint     m_iRunningVectorCounter;\n\tint     DirectionWasLooking;\n\n\tfloat   f_max_role_angle; //=DEGTORAD(5.0f);    \n\tfloat   f_Roll; //used for adding a slight roll to the camera in the\n\tfloat\tf_rollSpeed;\n\tfloat   m_fSyphonModeTargetZOffSet;\n\tfloat   m_fAmountFractionObscured;\n\tfloat   m_fAlphaSpeedOverOneFrame;\n\tfloat   m_fBetaSpeedOverOneFrame;\n\tfloat   m_fBufferedTargetBeta;\n\tfloat   m_fBufferedTargetOrientation;\n\tfloat   m_fBufferedTargetOrientationSpeed;\n\tfloat   m_fCamBufferedHeight;\n\tfloat   m_fCamBufferedHeightSpeed;\n\tfloat   m_fCloseInPedHeightOffset;\n\tfloat   m_fCloseInPedHeightOffsetSpeed;\n\tfloat   m_fCloseInCarHeightOffset;\n\tfloat   m_fCloseInCarHeightOffsetSpeed;\n\tfloat   m_fDimensionOfHighestNearCar;       \n\tfloat   m_fDistanceBeforeChanges;\n\tfloat   m_fFovSpeedOverOneFrame;\n\tfloat   m_fMinDistAwayFromCamWhenInterPolating;\n\tfloat   m_fPedBetweenCameraHeightOffset;\n\tfloat   m_fPlayerInFrontSyphonAngleOffSet;\n\tfloat   m_fRadiusForDead;\n\tfloat   m_fRealGroundDist; //used for follow ped mode\n\tfloat   m_fTargetBeta;\n\tfloat   m_fTimeElapsedFloat;  \n\tfloat   m_fTilt;\n\tfloat   m_fTiltSpeed;\n\tfloat   m_fTransitionBeta;\n\tfloat   m_fTrueBeta;\n\tfloat   m_fTrueAlpha;\n\tfloat   m_fInitialPlayerOrientation; //used for first person\n\n\tfloat   Alpha;\n\tfloat   AlphaSpeed;\n\tfloat   FOV;\n\tfloat   FOVSpeed;\n\tfloat   Beta;\n\tfloat   BetaSpeed;\n\tfloat   Distance;\n\tfloat   DistanceSpeed;\n\tfloat   CA_MIN_DISTANCE;\n\tfloat   CA_MAX_DISTANCE;\n\tfloat   SpeedVar;\n\n\tfloat m_fTargetZoomGroundOne;\n\tfloat m_fTargetZoomGroundTwo;\n\tfloat m_fTargetZoomGroundThree;\n\tfloat m_fTargetZoomOneZExtra;\n\tfloat m_fTargetZoomTwoZExtra;\n\tfloat m_fTargetZoomThreeZExtra;\n\tfloat m_fTargetZoomZCloseIn;\n\tfloat m_fMinRealGroundDist;\n\tfloat m_fTargetCloseInDist;\n\n\tCVector m_cvecSourceSpeedOverOneFrame;\n\tCVector m_cvecTargetSpeedOverOneFrame;\n\tCVector m_cvecUpOverOneFrame;\n\n\tCVector m_cvecTargetCoorsForFudgeInter;\n\tCVector m_cvecCamFixedModeVector;\n\tCVector m_cvecCamFixedModeSource;\n\tCVector m_cvecCamFixedModeUpOffSet;\n\tCVector m_vecLastAboveWaterCamPosition;  //helper for when the player has gone under the water\n\tCVector m_vecBufferedPlayerBodyOffset;\n\n\t// The three vectors that determine this camera for this frame\n\tCVector Front;                                                  // Direction of looking in\n\tCVector Source;                                                 // Coors in world space\n\tCVector SourceBeforeLookBehind;\n\tCVector Up;                                                     // Just that\n\tCVector m_arrPreviousVectors[NUMBER_OF_VECTORS_FOR_AVERAGE];    // used to average stuff\n\tCEntity *CamTargetEntity;\n\n\tfloat       m_fCameraDistance;\n\tfloat       m_fIdealAlpha;\n\tfloat       m_fPlayerVelocity;\n\tCAutomobile  *m_pLastCarEntered; // So interpolation works\n\tCPed         *m_pLastPedLookedAt;// So interpolation works \n\tbool        m_bFirstPersonRunAboutActive;\n\n\tCCam(void) { Init(); }\n\tvoid Init(void);\n\tvoid Process(void);\n\tvoid ProcessSpecialHeightRoutines(void);\n\tvoid GetVectorsReadyForRW(void);\n\tCVector DoAverageOnVector(const CVector &vec);\n\tvoid WorkOutCamHeight(const CVector &TargetCoors, float TargetOrientation, float TargetHeight);\n\tbool RotCamIfInFrontCar(CVector &TargetCoors, float TargetOrientation);\n\tvoid Cam_On_A_String_Unobscured(const CVector &TargetCoors, float BaseDist);\n\tvoid FixCamWhenObscuredByVehicle(const CVector &TargetCoors);\n\tbool GetBoatLook_L_R_HeightOffset(float &Offset);\n\tvoid LookBehind(void);\n\tvoid LookLeft(void);\n\tvoid LookRight(void);\n\tvoid ClipIfPedInFrontOfPlayer(void);\n\tvoid KeepTrackOfTheSpeed(const CVector &source, const CVector &target, const CVector &up, const float &alpha, const float &beta, const float &fov);\n\tbool Using3rdPersonMouseCam(void);\n\tbool GetWeaponFirstPersonOn(void);\n\tbool IsTargetInWater(const CVector &CamCoors);\n\tvoid AvoidWallsTopDownPed(const CVector &TargetCoors, const CVector &Offset, float *Adjuster, float *AdjusterSpeed, float yDistLimit);\n\tvoid PrintMode(void);\n\n\tvoid Process_Debug(const CVector&, float, float, float);\n#ifdef GTA_SCENE_EDIT\n\tvoid Process_Editor(const CVector&, float, float, float);\n#endif\n\tvoid Process_ModelView(const CVector &CameraTarget, float, float, float);\n\tvoid Process_FollowPed(const CVector &CameraTarget, float TargetOrientation, float, float);\n\tvoid Process_FollowPedWithMouse(const CVector &CameraTarget, float TargetOrientation, float, float);\n\tvoid Process_BehindCar(const CVector &CameraTarget, float TargetOrientation, float, float);\n\tvoid Process_Cam_On_A_String(const CVector &CameraTarget, float TargetOrientation, float, float);\n\tvoid Process_TopDown(const CVector &CameraTarget, float TargetOrientation, float SpeedVar, float TargetSpeedVar);\n\tvoid Process_TopDownPed(const CVector &CameraTarget, float TargetOrientation, float, float);\n\tvoid Process_Rocket(const CVector &CameraTarget, float, float, float);\n\tvoid Process_M16_1stPerson(const CVector &CameraTarget, float, float, float);\n\tvoid Process_1stPerson(const CVector &CameraTarget, float, float, float);\n\tvoid Process_1rstPersonPedOnPC(const CVector &CameraTarget, float TargetOrientation, float, float);\n\tvoid Process_Sniper(const CVector &CameraTarget, float, float, float);\n\tvoid Process_Syphon(const CVector &CameraTarget, float, float, float);\n\tvoid Process_Syphon_Crim_In_Front(const CVector &CameraTarget, float, float, float);\n\tvoid Process_BehindBoat(const CVector &CameraTarget, float TargetOrientation, float, float);\n\tvoid Process_Fight_Cam(const CVector &CameraTarget, float TargetOrientation, float, float);\n\tvoid Process_FlyBy(const CVector&, float, float, float);\n\tbool Process_WheelCam(const CVector&, float, float, float);\n\tvoid Process_Fixed(const CVector &CameraTarget, float, float, float);\n\tvoid Process_Player_Fallen_Water(const CVector &CameraTarget, float TargetOrientation, float, float);\n\tvoid Process_SpecialFixedForSyphon(const CVector &CameraTarget, float, float, float);\n\tvoid Process_LightHouse(const CVector &CameraTarget, float, float, float);\n\tvoid ProcessPedsDeadBaby(void);\n\tbool ProcessArrestCamOne(void);\n\tbool ProcessArrestCamTwo(void);\n\tbool GetLookAlongGroundPos(CEntity *Target, CPed *Cop, CVector &TargetCoors, CVector &SourceOut);\n\tbool GetLookFromLampPostPos(CEntity *Target, CPed *Cop, CVector &TargetCoors, CVector &SourceOut);\n\tbool GetLookOverShoulderPos(CEntity *Target, CPed *Cop, CVector &TargetCoors, CVector &SourceOut);\n\n\t// custom stuff\n\tvoid Process_FollowPed_Rotation(const CVector &CameraTarget, float TargetOrientation, float, float);\n\tvoid Process_FollowCar_SA(const CVector &CameraTarget, float TargetOrientation, float, float);\n};\n\nclass CCamPathSplines\n{\npublic:\n\tenum {MAXPATHLENGTH=800};\n//\tfloat m_arr_PathData[MAXPATHLENGTH];\n\tfloat *m_arr_PathData;\n\tCCamPathSplines(void);\n};\n\nstruct CTrainCamNode\n{\n\tCVector m_cvecCamPosition;\n\tCVector m_cvecPointToLookAt;\n\tCVector m_cvecMinPointInRange;\n\tCVector m_cvecMaxPointInRange;\n\tfloat m_fDesiredFOV;\n\tfloat m_fNearClip;\n};\n\nstruct CQueuedMode\n{\n\tint16 Mode;\n\tfloat Duration;\n\tint16 MinZoom;\n\tint16 MaxZoom;\n};\n\nenum\n{\n\tLOOKING_BEHIND,\n\tLOOKING_LEFT,\n\tLOOKING_RIGHT,\n\tLOOKING_FORWARD,\n};\n\nenum\n{\n\t// TODO: find better names\n\tFADE_0,\t// faded in\n\tFADE_1,\t// mid fade\n\tFADE_2,\t// faded out\n\n\t// Direction\n\tFADE_OUT = 0,\n\tFADE_IN,\n\tFADE_NONE\n};\n\nenum\n{\n\tMOTION_BLUR_NONE = 0,\n\tMOTION_BLUR_SNIPER,\n\tMOTION_BLUR_LIGHT_SCENE,\n\tMOTION_BLUR_SECURITY_CAM,\n\tMOTION_BLUR_CUT_SCENE,\n\tMOTION_BLUR_INTRO,\n\tMOTION_BLUR_INTRO2,\n\tMOTION_BLUR_SNIPER_ZOOM,\n\tMOTION_BLUR_INTRO3,\n\tMOTION_BLUR_INTRO4,\n};\n\nenum\n{\n\tNONE = 0,\n\tINTERPOLATION,\n\tJUMP_CUT\n};\n\nenum\n{\n\tCAMCONTROL_GAME,\n\tCAMCONTROL_SCRIPT,\n\tCAMCONTROL_OBBE\n};\n\nclass CCamera : public CPlaceable\n{\npublic:\n\tbool m_bAboveGroundTrainNodesLoaded;\n\tbool m_bBelowGroundTrainNodesLoaded;\n\tbool m_bCamDirectlyBehind;\n\tbool m_bCamDirectlyInFront;\n\tbool m_bCameraJustRestored;\n\tbool m_bcutsceneFinished;\n\tbool m_bCullZoneChecksOn;\n\tbool m_bFirstPersonBeingUsed;\n\tbool m_bJustJumpedOutOf1stPersonBecauseOfTarget;\n\tbool m_bIdleOn;\n\tbool m_bInATunnelAndABigVehicle;\n\tbool m_bInitialNodeFound;\n\tbool m_bInitialNoNodeStaticsSet;\n\tbool m_bIgnoreFadingStuffForMusic;\n\tbool m_bPlayerIsInGarage;\n\tbool m_bPlayerWasOnBike;\n\tbool m_bJustCameOutOfGarage;\n\tbool m_bJustInitalised;\n\tbool m_bJust_Switched;\n\tbool m_bLookingAtPlayer;\n\tbool m_bLookingAtVector;\n\tbool m_bMoveCamToAvoidGeom;\n\tbool m_bObbeCinematicPedCamOn;\n\tbool m_bObbeCinematicCarCamOn;\n\tbool m_bRestoreByJumpCut;\n\tbool m_bUseNearClipScript;\n\tbool m_bStartInterScript;\n\tbool m_bStartingSpline;\n\tbool m_bTargetJustBeenOnTrain;\n\tbool m_bTargetJustCameOffTrain;\n\tbool m_bUseSpecialFovTrain;\n\tbool m_bUseTransitionBeta;\n\tbool m_bUseScriptZoomValuePed;\n\tbool m_bUseScriptZoomValueCar;\n\tbool m_bWaitForInterpolToFinish;\n\tbool m_bItsOkToLookJustAtThePlayer;\n\tbool m_bWantsToSwitchWidescreenOff;\n\tbool m_WideScreenOn;\n\tbool m_1rstPersonRunCloseToAWall;\n\tbool m_bHeadBob;\n\tbool m_bVehicleSuspenHigh;\n\tbool m_bEnable1rstPersonCamCntrlsScript;\n\tbool m_bAllow1rstPersonWeaponsCamera;\n\tbool m_bFailedCullZoneTestPreviously;\n\n\tbool m_FadeTargetIsSplashScreen;\n\n\tbool WorldViewerBeingUsed;\n\tuint8 ActiveCam;\n\tuint32 m_uiCamShakeStart;\n\tuint32 m_uiFirstPersonCamLastInputTime;\n\n\tuint32 m_uiLongestTimeInMill;\n\tuint32 m_uiNumberOfTrainCamNodes;\n\tuint8   m_uiTransitionJUSTStarted;\n\tuint8   m_uiTransitionState;        // 0:one mode 1:transition\n\n\tuint32 m_uiTimeLastChange;\n\tuint32 m_uiTimeWeLeftIdle_StillNoInput;\n\tuint32 m_uiTimeWeEnteredIdle;\n\tuint32 m_uiTimeTransitionStart;\n\tuint32 m_uiTransitionDuration;\n\tuint32 m_uiTransitionDurationTargetCoors;\n\tint m_BlurBlue;\n\tint m_BlurGreen;\n\tint m_BlurRed;\n\tint m_BlurType;\n\n\tint m_iWorkOutSpeedThisNumFrames;\n\tint m_iNumFramesSoFar;\n\n\n\tint m_iCurrentTrainCamNode;\n\tint m_motionBlur;\n\tint m_imotionBlurAddAlpha;\n\tint m_iCheckCullZoneThisNumFrames;\n\tint m_iZoneCullFrameNumWereAt;\n\tint WhoIsInControlOfTheCamera;\n\n\tfloat CamFrontXNorm;\n\tfloat CamFrontYNorm;\n#ifdef FIX_BUGS\n\tint32 CarZoomIndicator;\n#else\n\tfloat CarZoomIndicator;\n#endif\n\tfloat CarZoomValue;\n\tfloat CarZoomValueSmooth;\n\n\tfloat DistanceToWater;\n\tfloat FOVDuringInter;\n\tfloat LODDistMultiplier;\n\tfloat GenerationDistMultiplier;\n\tfloat m_fAlphaSpeedAtStartInter;\n\tfloat m_fAlphaWhenInterPol;\n\tfloat m_fAlphaDuringInterPol;\n\tfloat m_fBetaDuringInterPol;\n\tfloat m_fBetaSpeedAtStartInter;\n\tfloat m_fBetaWhenInterPol;\n\tfloat m_fFOVWhenInterPol;\n\tfloat m_fFOVSpeedAtStartInter;\n\tfloat m_fStartingBetaForInterPol;\n\tfloat m_fStartingAlphaForInterPol;\n\tfloat m_PedOrientForBehindOrInFront;\n\tfloat m_CameraAverageSpeed;\n\tfloat m_CameraSpeedSoFar;\n\tfloat m_fCamShakeForce;\n\tfloat m_fCarZoomValueScript;\n\tfloat m_fFovForTrain;\n\tfloat m_fFOV_Wide_Screen;\n\tfloat m_fNearClipScript;\n\tfloat m_fOldBetaDiff;\n\tfloat m_fPedZoomValue;\n\n\tfloat m_fPedZoomValueScript;\n\tfloat m_fPedZoomValueSmooth;\n\tfloat m_fPositionAlongSpline;\n\tfloat m_ScreenReductionPercentage;\n\tfloat m_ScreenReductionSpeed;\n\tfloat m_AlphaForPlayerAnim1rstPerson;\n\tfloat Orientation;\n#ifdef FIX_BUGS\n\tint32 PedZoomIndicator;\n#else\n\tfloat PedZoomIndicator;\n#endif\n\tfloat PlayerExhaustion;\n\tfloat SoundDistUp;\n\tfloat SoundDistUpAsRead;\n\tfloat SoundDistUpAsReadOld;\n\tfloat m_fAvoidTheGeometryProbsTimer;\n\tint16 m_nAvoidTheGeometryProbsDirn;\n\tfloat m_fWideScreenReductionAmount;\n\tfloat m_fStartingFOVForInterPol;\n\n\tstatic float m_fMouseAccelHorzntl;// acceleration multiplier for 1st person controls\n\tstatic float m_fMouseAccelVertical;// acceleration multiplier for 1st person controls\n\tstatic float m_f3rdPersonCHairMultX;\n\tstatic float m_f3rdPersonCHairMultY;\n\n\n\tCCam Cams[3];\n\tCGarage *pToGarageWeAreIn;\n\tCGarage *pToGarageWeAreInForHackAvoidFirstPerson;\n\tCQueuedMode m_PlayerMode;\n\tCQueuedMode PlayerWeaponMode;\n\tCVector m_PreviousCameraPosition;\n\tCVector m_RealPreviousCameraPosition;\n\tCVector m_cvecAimingTargetCoors;\n\tCVector m_vecFixedModeVector;\n\tCVector m_vecFixedModeSource;\n\tCVector m_vecFixedModeUpOffSet;\n\tCVector m_vecCutSceneOffset;\n\n\tCVector m_cvecStartingSourceForInterPol;\n\tCVector m_cvecStartingTargetForInterPol;\n\tCVector m_cvecStartingUpForInterPol;\n\tCVector m_cvecSourceSpeedAtStartInter;\n\tCVector m_cvecTargetSpeedAtStartInter;\n\tCVector m_cvecUpSpeedAtStartInter;\n\tCVector m_vecSourceWhenInterPol;\n\tCVector m_vecTargetWhenInterPol;\n\tCVector m_vecUpWhenInterPol;\n\tCVector m_vecClearGeometryVec;\n\tCVector m_vecGameCamPos;\n\tCVector SourceDuringInter;\n\tCVector TargetDuringInter;\n\tCVector UpDuringInter;\n\tRwCamera *m_pRwCamera;\n\tCEntity *pTargetEntity;\n\tCCamPathSplines m_arrPathArray[MAX_NUM_OF_SPLINETYPES];\n#ifdef GTA_TRAIN\n\tCTrainCamNode m_arrTrainCamNode[MAX_NUM_OF_NODES];\n#endif\n\tCMatrix m_cameraMatrix;\n\tbool m_bGarageFixedCamPositionSet;\n\tbool m_vecDoingSpecialInterPolation;\n\tbool m_bScriptParametersSetForInterPol;\n\tbool m_bFading;\n\tbool m_bMusicFading;\n\tCMatrix m_viewMatrix;\n\tCVector m_vecFrustumNormals[4];\n\tCVector m_vecOldSourceForInter;\n\tCVector m_vecOldFrontForInter;\n\tCVector m_vecOldUpForInter;\n\tfloat m_vecOldFOVForInter;\n\tfloat m_fFLOATingFade;\n\tfloat m_fFLOATingFadeMusic;\n\tfloat m_fTimeToFadeOut;\n\tfloat m_fTimeToFadeMusic;\n\tfloat m_fFractionInterToStopMoving;\n\tfloat m_fFractionInterToStopCatchUp;\n\tfloat m_fFractionInterToStopMovingTarget;\n\tfloat m_fFractionInterToStopCatchUpTarget;\n\tfloat m_fGaitSwayBuffer;\n\tfloat m_fScriptPercentageInterToStopMoving;\n\tfloat m_fScriptPercentageInterToCatchUp;\n\n\tuint32  m_fScriptTimeForInterPolation;\n\n\n\tint16   m_iFadingDirection;\n\tint     m_iModeObbeCamIsInForCar;\n\tint16   m_iModeToGoTo;\n\tint16   m_iMusicFadingDirection;\n\tint16   m_iTypeOfSwitch;\n\n\tuint32 m_uiFadeTimeStarted;\n\tuint32 m_uiFadeTimeStartedMusic;\n\n\tstatic bool m_bUseMouse3rdPerson;\n#ifdef FREE_CAM\n\tstatic bool bFreeCam;\n#endif\n\n\t// High level and misc\n\tCCamera(void);\n\tvoid Init(void);\n\tvoid Process(void);\n\tvoid CamControl(void);\n\tvoid UpdateTargetEntity(void);\n\tvoid UpdateSoundDistances(void);\n\tvoid InitialiseCameraForDebugMode(void);\n\tvoid CamShake(float strength, float x, float y, float z);\n\tbool Get_Just_Switched_Status() { return m_bJust_Switched; }\n\tvoid AvoidTheGeometry(const CVector &Source, const CVector &TargetPos, CVector &NewSource, float FOV);\n\tvoid GetArrPosForVehicleType(int apperance, int &index);\n\tvoid GetScreenRect(CRect &rect);\n\n\t// Who's in control\n\tvoid TakeControl(CEntity *target, int16 mode, int16 typeOfSwitch, int32 controller);\n\tvoid TakeControlNoEntity(const CVector &position, int16 typeOfSwitch, int32 controller);\n\tvoid TakeControlWithSpline(int16 typeOfSwitch);\n\tvoid Restore(void);\n\tvoid RestoreWithJumpCut(void);\n\tvoid SetCamPositionForFixedMode(const CVector &Source, const CVector &UppOffSet);\n\n\t// Transition\n\tvoid StartTransition(int16 mode);\n\tvoid StartTransitionWhenNotFinishedInter(int16 mode);\n\tvoid StoreValuesDuringInterPol(CVector &source, CVector &target, CVector &up, float &FOV);\n\n\t// Widescreen borders\n\tvoid SetWideScreenOn(void);\n\tvoid SetWideScreenOff(void);\n\tvoid ProcessWideScreenOn(void);\n\tvoid DrawBordersForWideScreen(void);\n\n\t// Obbe's cam\n\tbool IsItTimeForNewcam(int32 obbeMode, int32 time);\n\tbool TryToStartNewCamMode(int32 obbeMode);\n\tvoid DontProcessObbeCinemaCamera(void);\n\tvoid ProcessObbeCinemaCameraCar(void);\n\tvoid ProcessObbeCinemaCameraHeli(void);\n\tvoid ProcessObbeCinemaCameraPed(void);\n\n\t// Train\n\tvoid LoadTrainCamNodes(char const *name);\n\tvoid Process_Train_Camera_Control(void);\n\n\t// Script\n\tvoid LoadPathSplines(int file);\n\tvoid DeleteCutSceneCamDataMemory(void);\n\tvoid FinishCutscene(void);\n\tfloat GetPositionAlongSpline(void) { return m_fPositionAlongSpline; }\n\tuint32 GetCutSceneFinishTime(void);\n\tvoid SetCamCutSceneOffSet(const CVector &pos);\n\tvoid SetPercentAlongCutScene(float percent);\n\tvoid SetParametersForScriptInterpolation(float stopMoving, float catchUp, int32 time);\n\tvoid SetZoomValueFollowPedScript(int16 dist);\n\tvoid SetZoomValueCamStringScript(int16 dist);\n\tvoid SetNearClipScript(float);\n\n\t// Fading\n\tvoid ProcessFade(void);\n\tvoid ProcessMusicFade(void);\n\tvoid Fade(float timeout, int16 direction);\n\tvoid SetFadeColour(uint8 r, uint8 g, uint8 b);\n\tbool GetFading(void);\n\tint GetFadingDirection(void);\n\tint GetScreenFadeStatus(void);\n\n\t// Motion blur\n\tvoid RenderMotionBlur(void);\n\tvoid SetMotionBlur(int r, int g, int b, int a, int type);\n\tvoid SetMotionBlurAlpha(int a);\n\n\t// Player looking and aiming\n\tint GetLookDirection(void);\n\tbool GetLookingForwardFirstPerson(void);\n\tbool GetLookingLRBFirstPerson(void);\n\tvoid SetCameraDirectlyInFrontForFollowPed_CamOnAString(void);\n\tvoid SetCameraDirectlyBehindForFollowPed_CamOnAString(void);\n\tvoid SetNewPlayerWeaponMode(int16 mode, int16 minZoom, int16 maxZoom);\n\tvoid ClearPlayerWeaponMode(void);\n\tvoid UpdateAimingCoors(CVector const &coors);\n\tbool Find3rdPersonCamTargetVector(float dist, CVector pos, CVector &source, CVector &target);\n\tfloat Find3rdPersonQuickAimPitch(void);\n\tbool Using1stPersonWeaponMode(void);\n\n\t// Physical camera\n\tvoid SetRwCamera(RwCamera *cam);\n\tconst CMatrix& GetCameraMatrix(void) { return m_cameraMatrix; }\n\tCVector &GetGameCamPosition(void) { return m_vecGameCamPos; }\n\tvoid CalculateDerivedValues(void);\n\tbool IsPointVisible(const CVector &center, const CMatrix *mat);\n\tbool IsSphereVisible(const CVector &center, float radius, const CMatrix *mat);\n\tbool IsSphereVisible(const CVector &center, float radius);\n#ifdef GTA_PS2\n\tbool IsBoxVisible(CVuVector *box, const CMatrix *mat);\n#else\n\tbool IsBoxVisible(CVector *box, const CMatrix *mat);\n#endif\n};\n\nVALIDATE_SIZE(CCamera, 0xE9D8);\n\nextern CCamera TheCamera;\n\nvoid CamShakeNoPos(CCamera*, float);\nvoid MakeAngleLessThan180(float &Angle);\nvoid WellBufferMe(float Target, float *CurrentValue, float *CurrentSpeed, float MaxSpeed, float Acceleration, bool IsAngle);\n"
  },
  {
    "path": "src/core/CdStream.cpp",
    "content": "#ifdef _WIN32\n#define WITHWINDOWS\n#include \"common.h\"\n\n#include \"CdStream.h\"\n#include \"rwcore.h\"\n#include \"RwHelper.h\"\n#include \"MemoryMgr.h\"\n\nstruct CdReadInfo\n{\n\tuint32 nSectorOffset;\n\tuint32 nSectorsToRead;\n\tvoid *pBuffer;\n\tchar field_C;\n\tbool bLocked;\n\tbool bReading;\n\tint32 nStatus;\n\tHANDLE pDoneSemaphore; // used for CdStreamSync\n\tHANDLE hFile;\n\tOVERLAPPED Overlapped;\n};\n\nVALIDATE_SIZE(CdReadInfo, 0x30);\n\nchar gCdImageNames[MAX_CDIMAGES+1][64];\nint32 gNumImages;\nint32 gNumChannels;\n\nHANDLE gImgFiles[MAX_CDIMAGES];\n\nHANDLE _gCdStreamThread;\nHANDLE gCdStreamSema; // released when we have new thing to read(so channel is set)\nDWORD _gCdStreamThreadId;\n\nCdReadInfo *gpReadInfo;\nQueue gChannelRequestQ;\n\nint32 lastPosnRead;\n\nBOOL _gbCdStreamOverlapped;\nBOOL _gbCdStreamAsync;\nDWORD _gdwCdStreamFlags;\n\nDWORD WINAPI CdStreamThread(LPVOID lpThreadParameter);\n\nvoid\nCdStreamInitThread(void)\n{\n\tSetLastError(0);\n\t\n\tif ( gNumChannels > 0 )\n\t{\n\t\tfor ( int32 i = 0; i < gNumChannels; i++ )\n\t\t{\n\t\t\tgpReadInfo[i].pDoneSemaphore = CreateSemaphore(nil, 0, 2, nil);\n\t\t\t\n\t\t\tif ( gpReadInfo[i].pDoneSemaphore == nil )\n\t\t\t{\n\t\t\t\tprintf(\"%s: failed to create sync semaphore\\n\", \"cdvd_stream\");\n\t\t\t\tASSERT(0);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t}\n\t\n\tgChannelRequestQ.items = (int32 *)LocalAlloc(LMEM_ZEROINIT, sizeof(int32) * (gNumChannels + 1));\n\tgChannelRequestQ.head = 0;\n\tgChannelRequestQ.tail = 0;\n\tgChannelRequestQ.size = gNumChannels + 1;\n\tASSERT(gChannelRequestQ.items != nil );\n\t\n#ifdef FIX_BUGS\n\tgCdStreamSema = CreateSemaphore(nil, 0, 5, nil);\n#else\n\tgCdStreamSema = CreateSemaphore(nil, 0, 5, \"CdStream\");\n#endif\n\t\n\tif ( gCdStreamSema == nil )\n\t{\n\t\tprintf(\"%s: failed to create stream semaphore\\n\", \"cdvd_stream\");\n\t\tASSERT(0);\n\t\treturn;\n\t}\n\t\n\t_gCdStreamThread = CreateThread(nil, 64*1024/*64KB*/, CdStreamThread, nil, CREATE_SUSPENDED, &_gCdStreamThreadId);\n\t\n\tif ( _gCdStreamThread == nil )\n\t{\n\t\tprintf(\"%s: failed to create streaming thread\\n\", \"cdvd_stream\");\n\t\tASSERT(0);\n\t\treturn;\n\t}\n\n\tSetThreadPriority(_gCdStreamThread, GetThreadPriority(GetCurrentThread()) - 1);\n\t\t\n\tResumeThread(_gCdStreamThread);\t\n}\n\nvoid\nCdStreamInit(int32 numChannels)\n{\n\tDWORD SectorsPerCluster;\n\tDWORD BytesPerSector;\n\tDWORD NumberOfFreeClusters;\n\tDWORD TotalNumberOfClusters;\n\n\tGetDiskFreeSpace(nil, &SectorsPerCluster, &BytesPerSector, &NumberOfFreeClusters, &TotalNumberOfClusters);\n\t\n\t_gdwCdStreamFlags = 0;\n\n#ifndef FIX_BUGS // this just slows down streaming\n\tif ( BytesPerSector <= CDSTREAM_SECTOR_SIZE )\n\t{\n\t\t_gdwCdStreamFlags |= FILE_FLAG_NO_BUFFERING;\n\t\tdebug(\"Using no buffered loading for streaming\\n\");\n\t}\n#endif\n\t\n\t_gbCdStreamOverlapped = TRUE;\n\n\t_gdwCdStreamFlags |= FILE_FLAG_OVERLAPPED;\n\t\n\t_gbCdStreamAsync = FALSE;\n\t\n\tvoid *pBuffer = (void *)RwMallocAlign(CDSTREAM_SECTOR_SIZE, BytesPerSector);\n\tASSERT( pBuffer != nil );\n\t\n\tSetLastError(0);\n\t\n\tgNumImages = 0;\n\t\n\tgNumChannels = numChannels;\n\t\n\tgpReadInfo = (CdReadInfo *)LocalAlloc(LMEM_ZEROINIT, sizeof(CdReadInfo) * numChannels);\n\tASSERT( gpReadInfo != nil );\n\t\n\tdebug(\"%s: read info %p\\n\", \"cdvd_stream\", gpReadInfo);\n\t\n\tCdStreamAddImage(\"MODELS\\\\GTA3.IMG\");\n\t\n\tint32 nStatus = CdStreamRead(0, pBuffer, 0, 1);\n\t\n\tCdStreamRemoveImages();\n\t\n\tif ( nStatus == STREAM_SUCCESS )\n\t{\n\t\t_gbCdStreamAsync = TRUE;\n\t\t\n\t\tdebug(\"Using async loading for streaming\\n\");\n\t}\n\telse\n\t{\n\t\t_gdwCdStreamFlags &= ~FILE_FLAG_OVERLAPPED;\n\t\t\n\t\t_gbCdStreamOverlapped = FALSE;\n\t\t\n\t\t_gbCdStreamAsync = TRUE;\n\t\t\n\t\tdebug(\"Using sync loading for streaming\\n\");\n\t}\n\t\n\tCdStreamInitThread();\n\t\n\tASSERT( pBuffer != nil );\n\tRwFreeAlign(pBuffer);\n}\n\nuint32\nGetGTA3ImgSize(void)\n{\n\tASSERT( gImgFiles[0] != nil );\n\treturn (uint32)GetFileSize(gImgFiles[0], nil);\n}\n\nvoid\nCdStreamShutdown(void)\n{\n\tif ( _gbCdStreamAsync )\n\t{\n\t\tLocalFree(gChannelRequestQ.items);\n\t\tCloseHandle(gCdStreamSema);\n\t\tCloseHandle(_gCdStreamThread);\n\t\t\n\t\tfor ( int32 i = 0; i < gNumChannels; i++ )\n\t\t\tCloseHandle(gpReadInfo[i].pDoneSemaphore);\n\t}\n\t\n\tLocalFree(gpReadInfo);\n}\n\n\n\nint32\nCdStreamRead(int32 channel, void *buffer, uint32 offset, uint32 size)\n{\n\tASSERT( channel < gNumChannels );\n\tASSERT( buffer != nil );\n\t\n\tlastPosnRead = size + offset;\n\t\n\tASSERT( _GET_INDEX(offset) < MAX_CDIMAGES );\n\tHANDLE hImage = gImgFiles[_GET_INDEX(offset)];\n\tASSERT( hImage != nil );\n\t\n\t\n\tCdReadInfo *pChannel = &gpReadInfo[channel];\n\tASSERT( pChannel != nil );\n\t\n\tpChannel->hFile = hImage;\n\t\n\tSetLastError(0);\n\t\n\tif ( _gbCdStreamAsync )\n\t{\n\t\tif ( pChannel->nSectorsToRead != 0 || pChannel->bReading )\n\t\t\treturn STREAM_NONE;\n\t\t\n\t\tpChannel->nStatus = STREAM_NONE;\n\t\tpChannel->nSectorOffset = _GET_OFFSET(offset);\n\t\tpChannel->nSectorsToRead = size;\n\t\tpChannel->pBuffer = buffer;\n\t\tpChannel->bLocked = 0;\n\t\t\n\t\tAddToQueue(&gChannelRequestQ, channel);\n\t\t\n\t\tif ( !ReleaseSemaphore(gCdStreamSema, 1, nil) )\n\t\t\tprintf(\"Signal Sema Error\\n\");\n\t\t\n\t\treturn STREAM_SUCCESS;\n\t}\n\t\n\tif ( _gbCdStreamOverlapped )\n\t{\n\t\tASSERT( channel < gNumChannels );\n\t\tCdReadInfo *pChannel = &gpReadInfo[channel];\n\t\tASSERT( pChannel != nil );\n\t\t\n\t\tpChannel->Overlapped.Offset = _GET_OFFSET(offset) * CDSTREAM_SECTOR_SIZE;\n\t\t\n\t\tif ( !ReadFile(hImage, buffer, size * CDSTREAM_SECTOR_SIZE, NULL, &pChannel->Overlapped)\n\t\t\t\t\t&& GetLastError() != ERROR_IO_PENDING )\n\t\t\treturn STREAM_NONE;\n\t\telse\n\t\t\treturn STREAM_SUCCESS;\n\t}\n\n#ifdef BIG_IMG\n\tLARGE_INTEGER liDistanceToMove;\n\tliDistanceToMove.QuadPart = _GET_OFFSET(offset);\n\tliDistanceToMove.QuadPart *= CDSTREAM_SECTOR_SIZE;\n\tSetFilePointerEx(hImage, liDistanceToMove, nil, FILE_BEGIN);\n#else\n\tSetFilePointer(hImage, _GET_OFFSET(offset) * CDSTREAM_SECTOR_SIZE, nil, FILE_BEGIN);\n#endif\n\t\n\tDWORD NumberOfBytesRead;\n\t\n\tif ( !ReadFile(hImage, buffer, size * CDSTREAM_SECTOR_SIZE, &NumberOfBytesRead, nil) )\n\t\treturn STREAM_NONE;\n\telse\n\t\treturn STREAM_SUCCESS;\n}\n\nint32\nCdStreamGetStatus(int32 channel)\n{\n\tASSERT( channel < gNumChannels );\n\tCdReadInfo *pChannel = &gpReadInfo[channel];\n\tASSERT( pChannel != nil );\n\t\n\tif ( _gbCdStreamAsync )\n\t{\n\t\tif ( pChannel->bReading )\n\t\t\treturn STREAM_READING;\n\t\t\n\t\tif ( pChannel->nSectorsToRead != 0 )\n\t\t\treturn STREAM_WAITING;\n\t\t\n\t\tif ( pChannel->nStatus != STREAM_NONE )\n\t\t{\n\t\t\tint32 status = pChannel->nStatus;\n\t\t\t\n\t\t\tpChannel->nStatus = STREAM_NONE;\n\t\t\t\n\t\t\treturn status;\n\t\t}\n\t\t\n\t\treturn STREAM_NONE;\n\t}\n\t\n\tif ( _gbCdStreamOverlapped )\n\t{\n\t\tASSERT( pChannel->hFile != nil );\n\t\tif ( WaitForSingleObjectEx(pChannel->hFile, 0, TRUE) == WAIT_OBJECT_0 )\n\t\t\treturn STREAM_NONE;\n\t\telse\n\t\t\treturn STREAM_READING;\n\t}\n\t\n\treturn STREAM_NONE;\n}\n\nint32\nCdStreamGetLastPosn(void)\n{\n\treturn lastPosnRead;\n}\n\n// wait for channel to finish reading\nint32\nCdStreamSync(int32 channel)\n{\n\tASSERT( channel < gNumChannels );\n\tCdReadInfo *pChannel = &gpReadInfo[channel];\n\tASSERT( pChannel != nil );\n\t\n\tif ( _gbCdStreamAsync )\n\t{\n\t\tif ( pChannel->nSectorsToRead != 0 )\n\t\t{\n\t\t\tpChannel->bLocked = true;\n\n\t\t\tASSERT( pChannel->pDoneSemaphore != nil );\n\n\t\t\t// Deadlock fix 1\n#ifdef FIX_BUGS\n\t\t\t// This is while loop on Posix streamer, for spurious wakeups\n\t\t\tif (pChannel->bLocked && pChannel->nSectorsToRead != 0){\n\t\t\t\tWaitForSingleObject(pChannel->pDoneSemaphore, INFINITE);\n\t\t\t}\n\t\t\tpChannel->bLocked = false;\n#else\n\t\t\tWaitForSingleObject(pChannel->pDoneSemaphore, INFINITE);\n#endif\n\t\t}\n\n\t\tpChannel->bReading = false;\n\t\t\n\t\treturn pChannel->nStatus;\n\t}\n\t\n\tDWORD NumberOfBytesTransferred;\n\n\tif ( _gbCdStreamOverlapped && pChannel->hFile )\n\t{\n\t\tASSERT(pChannel->hFile != nil );\n\t\t// Beware: This is blocking call (because of last parameter)\n\t\tif ( GetOverlappedResult(pChannel->hFile, &pChannel->Overlapped, &NumberOfBytesTransferred, TRUE) )\n\t\t\treturn STREAM_NONE;\n\t\telse\n\t\t\treturn STREAM_ERROR;\n\t}\n\t\n\treturn STREAM_NONE;\n}\n\nvoid\nAddToQueue(Queue *queue, int32 item)\n{\n\tASSERT( queue != nil );\n\tASSERT( queue->items != nil );\n\tqueue->items[queue->tail] = item;\n\t\n\tqueue->tail = (queue->tail + 1) % queue->size;\n\t\n\tif ( queue->head == queue->tail )\n\t\tdebug(\"Queue is full\\n\");\n}\n\nint32 \nGetFirstInQueue(Queue *queue)\n{\n\tASSERT( queue != nil );\n\tif ( queue->head == queue->tail )\n\t\treturn -1;\n\n\tASSERT( queue->items != nil );\n\treturn queue->items[queue->head];\n}\n\nvoid\nRemoveFirstInQueue(Queue *queue)\n{\t\n\tASSERT( queue != nil );\n\tif ( queue->head == queue->tail )\n\t{\n\t\tdebug(\"Queue is empty\\n\");\n\t\treturn;\n\t}\n\n\tqueue->head = (queue->head + 1) % queue->size;\n}\n\nDWORD\nWINAPI CdStreamThread(LPVOID lpThreadParameter)\n{\n\tdebug(\"Created cdstream thread\\n\");\n\t\n\twhile ( true )\n\t{\n\t\tWaitForSingleObject(gCdStreamSema, INFINITE);\n\t\t\n\t\tint32 channel = GetFirstInQueue(&gChannelRequestQ);\n\t\tASSERT( channel < gNumChannels );\n\t\t\n\t\tCdReadInfo *pChannel = &gpReadInfo[channel];\n\t\tASSERT( pChannel != nil );\n\t\t\n\t\tpChannel->bReading = true;\n\t\t\n\t\tif ( pChannel->nStatus == STREAM_NONE )\n\t\t{\n\t\t\tif ( _gbCdStreamOverlapped )\n\t\t\t{\n\t\t\t\tpChannel->Overlapped.Offset = pChannel->nSectorOffset * CDSTREAM_SECTOR_SIZE;\n\t\t\t\t\n\t\t\t\tASSERT(pChannel->hFile != nil );\n\t\t\t\tASSERT(pChannel->pBuffer != nil );\n\t\t\t\t\n\t\t\t\tDWORD NumberOfBytesTransferred;\n\t\t\t\t\n\t\t\t\tif ( ReadFile(pChannel->hFile,\n\t\t\t\t\t\tpChannel->pBuffer,\n\t\t\t\t\t\tpChannel->nSectorsToRead * CDSTREAM_SECTOR_SIZE,\n\t\t\t\t\t\tNULL,\n\t\t\t\t\t\t&pChannel->Overlapped) )\n\t\t\t\t{\n\t\t\t\t\tpChannel->nStatus = STREAM_NONE;\n\t\t\t\t}\n\t\t\t\t// Beware: This is blocking call (because of last parameter)\n\t\t\t\telse if ( GetLastError() == ERROR_IO_PENDING\n\t\t\t\t\t\t&& GetOverlappedResult(pChannel->hFile, &pChannel->Overlapped, &NumberOfBytesTransferred, TRUE) )\n\t\t\t\t{\n\t\t\t\t\tpChannel->nStatus = STREAM_NONE;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tpChannel->nStatus = STREAM_ERROR;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tASSERT(pChannel->hFile != nil );\n\t\t\t\tASSERT(pChannel->pBuffer != nil );\n\t\t\t\t\n\t\t\t\tSetFilePointer(pChannel->hFile, pChannel->nSectorOffset * CDSTREAM_SECTOR_SIZE, nil, FILE_BEGIN);\n\n\t\t\t\tDWORD NumberOfBytesRead;\n\t\t\t\tif ( ReadFile(pChannel->hFile,\n\t\t\t\t\t\tpChannel->pBuffer,\n\t\t\t\t\t\tpChannel->nSectorsToRead * CDSTREAM_SECTOR_SIZE,\n\t\t\t\t\t\t&NumberOfBytesRead,\n\t\t\t\t\t\tNULL) )\n\t\t\t\t{\n\t\t\t\t\tpChannel->nStatus = STREAM_NONE;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t\n\t\tRemoveFirstInQueue(&gChannelRequestQ);\n\t\t\n\t\tpChannel->nSectorsToRead = 0;\n\t\t\n\t\tif ( pChannel->bLocked )\n\t\t{\n\t\t\tASSERT( pChannel->pDoneSemaphore != nil );\n\t\t\t// Deadlock fix 2\n#ifdef FIX_BUGS\n\t\t\tpChannel->bLocked = 0;\n#endif\n\t\t\tReleaseSemaphore(pChannel->pDoneSemaphore, 1, NULL);\n\t\t}\n\t\t\n\t\tpChannel->bReading = false;\n\t}\n}\n\nbool\nCdStreamAddImage(char const *path)\n{\n\tASSERT(path != nil);\n\tASSERT(gNumImages < MAX_CDIMAGES);\n\t\n\tSetLastError(0);\n\t\n\tgImgFiles[gNumImages] = CreateFile(path,\n\t                                   GENERIC_READ,\n\t                                   FILE_SHARE_READ,\n\t                                   nil,\n\t                                   OPEN_EXISTING,\n\t                                   _gdwCdStreamFlags | FILE_FLAG_RANDOM_ACCESS | FILE_ATTRIBUTE_READONLY,\n\t                                   nil);\n\t\n\tASSERT( gImgFiles[gNumImages] != nil );\n\tif ( gImgFiles[gNumImages] == NULL )\n\t\treturn false;\n\t\n\tstrcpy(gCdImageNames[gNumImages], path);\n\t\n\tgNumImages++;\n\t\n\treturn true;\n}\n\nchar *\nCdStreamGetImageName(int32 cd)\n{\n\tASSERT(cd < MAX_CDIMAGES);\n\tif ( gImgFiles[cd] != nil )\n\t\treturn gCdImageNames[cd];\n\t\n\treturn nil;\n}\n\nvoid\nCdStreamRemoveImages(void)\n{\t\n\tfor ( int32 i = 0; i < gNumChannels; i++ )\n\t\tCdStreamSync(i);\n\t\n\tfor ( int32 i = 0; i < gNumImages; i++ )\n\t{\n\t\tSetLastError(0);\n\t\t\n\t\tCloseHandle(gImgFiles[i]);\n\t\tgImgFiles[i] = nil;\n\t}\n\t\n\tgNumImages = 0;\n}\n\nint32\nCdStreamGetNumImages(void)\n{\t\n\treturn gNumImages;\n}\n#endif\n"
  },
  {
    "path": "src/core/CdStream.h",
    "content": "#pragma once\n\n#define CDSTREAM_SECTOR_SIZE 2048\n\n#define _GET_INDEX(a) (a >> 24)\n#define _GET_OFFSET(a)  (a & 0xFFFFFF)\n\nenum\n{\n\tSTREAM_NONE            = uint8( 0),\n\tSTREAM_SUCCESS         = uint8( 1),\n\tSTREAM_READING         = uint8(-1), // 0xFF,\n\tSTREAM_ERROR           = uint8(-2), // 0xFE,\n\tSTREAM_ERROR_NOCD      = uint8(-3), // 0xFD,\n\tSTREAM_ERROR_WRONGCD   = uint8(-4), // 0xFC,\n\tSTREAM_ERROR_OPENCD    = uint8(-5), // 0xFB,\n\tSTREAM_WAITING         = uint8(-6)  // 0xFA,\n};\n\nstruct Queue\n{\n\tint32 *items;\n\tint32 head;\n\tint32 tail;\n\tint32 size;\n};\n\nVALIDATE_SIZE(Queue, 0x10);\n\nvoid CdStreamInitThread(void);\nvoid CdStreamInit(int32 numChannels);\nuint32 GetGTA3ImgSize(void);\nvoid CdStreamShutdown(void);\nint32 CdStreamRead(int32 channel, void *buffer, uint32 offset, uint32 size);\nint32 CdStreamGetStatus(int32 channel);\nint32 CdStreamGetLastPosn(void);\nint32 CdStreamSync(int32 channel);\nvoid AddToQueue(Queue *queue, int32 item);\nint32 GetFirstInQueue(Queue *queue);\nvoid RemoveFirstInQueue(Queue *queue);\nbool CdStreamAddImage(char const *path);\nchar *CdStreamGetImageName(int32 cd);\nvoid CdStreamRemoveImages(void);\nint32 CdStreamGetNumImages(void);\n\n#ifdef FLUSHABLE_STREAMING\nextern bool flushStream[MAX_CDCHANNELS];\n#endif\n"
  },
  {
    "path": "src/core/CdStreamPosix.cpp",
    "content": "#ifndef _WIN32\n#include \"common.h\"\n#include \"crossplatform.h\"\n#include <signal.h>\n#include <pthread.h>\n#include <semaphore.h>\n#include <sys/types.h>\n#include <unistd.h>\n#include <sys/time.h>\n#include <sys/statvfs.h>\n#include <sys/types.h>\n#include <sys/stat.h>\n#include <fcntl.h>\n#include <sys/resource.h>\n#include <stdarg.h>\n\n#ifdef __linux__\n#include <sys/syscall.h>\n#endif\n\n#include \"CdStream.h\"\n#include \"rwcore.h\"\n#include \"MemoryMgr.h\"\n\n#define CDDEBUG(f, ...)   debug (\"%s: \" f \"\\n\", \"cdvd_stream\", ## __VA_ARGS__)\n#define CDTRACE(f, ...)   printf(\"%s: \" f \"\\n\", \"cdvd_stream\", ## __VA_ARGS__)\n\n#ifdef FLUSHABLE_STREAMING\nbool flushStream[MAX_CDCHANNELS];\n#endif\n\n#ifdef USE_UNNAMED_SEM\n\n#define RE3_SEM_OPEN(name, ...) re3_sem_open()\nsem_t*\nre3_sem_open(void)\n{\n\tsem_t* sem = (sem_t*)malloc(sizeof(sem_t));\n\tif (sem_init(sem, 0, 1) == -1) {\n\t\tsem = SEM_FAILED;\n\t}\n\n\treturn sem;\n}\n\n#define RE3_SEM_CLOSE(sem, format, ...) re3_sem_close(sem)\nvoid\nre3_sem_close(sem_t* sem)\n{\n\tsem_destroy(sem);\n\tfree(sem);\n}\n\n#else\n\n#define RE3_SEM_OPEN re3_sem_open\nsem_t*\nre3_sem_open(const char* format, ...)\n{\n\tchar semName[21];\n\tva_list va;\n\tva_start(va, format);\n\tvsprintf(semName, format, va);\n\n\treturn sem_open(semName, O_CREAT, 0644, 1);\n}\n\n#define RE3_SEM_CLOSE re3_sem_close\nvoid\nre3_sem_close(sem_t* sem, const char* format, ...)\n{\n\tsem_close(sem);\n\n\tchar semName[21];\n\tva_list va;\n\tva_start(va, format);\n\tvsprintf(semName, format, va);\n\n\tsem_unlink(semName);\n}\n\n#endif\n\nstruct CdReadInfo\n{\n\tuint32 nSectorOffset;\n\tuint32 nSectorsToRead;\n\tvoid *pBuffer;\n\tbool bLocked;\n\tbool bReading;\n\tint32 nStatus;\n#ifdef ONE_THREAD_PER_CHANNEL\n\tint8 nThreadStatus; // 0: created 1:priority set up 2:abort now\n\tpthread_t pChannelThread;\n\tsem_t *pStartSemaphore;\n#endif\n\tsem_t *pDoneSemaphore; // used for CdStreamSync\n\tint32 hFile;\n};\n\nchar gCdImageNames[MAX_CDIMAGES+1][64];\nint32 gNumImages;\nint32 gNumChannels;\n\nint32 gImgFiles[MAX_CDIMAGES]; // -1: error 0:unused otherwise: fd\nchar *gImgNames[MAX_CDIMAGES];\n\n#ifndef ONE_THREAD_PER_CHANNEL\npthread_t _gCdStreamThread;\nsem_t *gCdStreamSema; // released when we have new thing to read(so channel is set)\nint8 gCdStreamThreadStatus; // 0: created 1:priority set up 2:abort now\nQueue gChannelRequestQ;\nbool _gbCdStreamOverlapped;\n#endif\n\nCdReadInfo *gpReadInfo;\n\nint32 lastPosnRead;\n\nint _gdwCdStreamFlags;\n\nvoid *CdStreamThread(void* channelId);\n\nvoid\nCdStreamInitThread(void)\n{\n\tint status;\n#ifndef ONE_THREAD_PER_CHANNEL\n\tgChannelRequestQ.items = (int32 *)calloc(gNumChannels + 1, sizeof(int32));\n\tgChannelRequestQ.head = 0;\n\tgChannelRequestQ.tail = 0;\n\tgChannelRequestQ.size = gNumChannels + 1;\n\tASSERT(gChannelRequestQ.items != nil );\n\tgCdStreamSema = RE3_SEM_OPEN(\"/semaphore_cd_stream\");\n\n\n\tif (gCdStreamSema == SEM_FAILED) {\n\t\tCDTRACE(\"failed to create stream semaphore\");\n\t\tASSERT(0);\n\t\treturn;\n\t}\n#endif\n\n\tif ( gNumChannels > 0 )\n\t{\n\t\tfor ( int32 i = 0; i < gNumChannels; i++ )\n\t\t{\n\t\t\tgpReadInfo[i].pDoneSemaphore = RE3_SEM_OPEN(\"/semaphore_done%d\", i);\n\n\t\t\tif (gpReadInfo[i].pDoneSemaphore == SEM_FAILED)\n\t\t\t{\n\t\t\t\tCDTRACE(\"failed to create sync semaphore\");\n\t\t\t\tASSERT(0);\n\t\t\t\treturn;\n\t\t\t}\n\n#ifdef ONE_THREAD_PER_CHANNEL\n\t\t\tgpReadInfo[i].pStartSemaphore = RE3_SEM_OPEN(\"/semaphore_start%d\", i);\n\n\t\t\tif (gpReadInfo[i].pStartSemaphore == SEM_FAILED)\n\t\t\t{\n\t\t\t\tCDTRACE(\"failed to create start semaphore\");\n\t\t\t\tASSERT(0);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tgpReadInfo[i].nThreadStatus = 0;\n\t\t\tint *channelI = (int*)malloc(sizeof(int));\n\t\t\t*channelI = i;\n\t\t\tstatus = pthread_create(&gpReadInfo[i].pChannelThread, NULL, CdStreamThread, (void*)channelI);\n\n\t\t\tif (status == -1)\n\t\t\t{\n\t\t\t\tCDTRACE(\"failed to create sync thread\");\n\t\t\t\tASSERT(0);\n\t\t\t\treturn;\n\t\t\t}\n#endif\n\t\t}\n\t}\n\n#ifndef ONE_THREAD_PER_CHANNEL\n\tdebug(\"Using one streaming thread for all channels\\n\");\n\tgCdStreamThreadStatus = 0;\n\tstatus = pthread_create(&_gCdStreamThread, NULL, CdStreamThread, nil);\n\n\tif (status == -1)\n\t{\n\t\tCDTRACE(\"failed to create sync thread\");\n\t\tASSERT(0);\n\t\treturn;\n\t}\n#else\n\tdebug(\"Using separate streaming threads for each channel\\n\");\n#endif\n}\n\nvoid\nCdStreamInit(int32 numChannels)\n{\n\tstruct statvfs fsInfo;\n\n\tif((statvfs(\"models/gta3.img\", &fsInfo)) < 0)\n\t{\n\t\tCDTRACE(\"can't get filesystem info\");\n\t\tASSERT(0);\n\t\treturn;\n\t}\n#ifdef __linux__\n\t_gdwCdStreamFlags = O_RDONLY | O_NOATIME;\n#else\n\t_gdwCdStreamFlags = O_RDONLY;\n#endif\n\t// People say it's slower\n/*\n\tif ( fsInfo.f_bsize <= CDSTREAM_SECTOR_SIZE )\n\t{\n\t\t_gdwCdStreamFlags |= O_DIRECT;\n\t\tdebug(\"Using no buffered loading for streaming\\n\");\n\t}\n*/\n\tvoid *pBuffer = (void *)RwMallocAlign(CDSTREAM_SECTOR_SIZE, (RwUInt32)fsInfo.f_bsize);\n\tASSERT( pBuffer != nil );\n\n\tgNumImages = 0;\n\n\tgNumChannels = numChannels;\n\tASSERT( gNumChannels != 0 );\n\n\tgpReadInfo = (CdReadInfo *)calloc(numChannels, sizeof(CdReadInfo));\n\tASSERT( gpReadInfo != nil );\n\n\tCDDEBUG(\"read info %p\", gpReadInfo);\n\n\tCdStreamInitThread();\n\n\tASSERT( pBuffer != nil );\n\tRwFreeAlign(pBuffer);\n}\n\nuint32\nGetGTA3ImgSize(void)\n{\n\tASSERT( gImgFiles[0] > 0 );\n\tstruct stat statbuf;\n\n\tchar path[PATH_MAX];\n\trealpath(gImgNames[0], path);\n\tif (stat(path, &statbuf) == -1) {\n\t\t// Try case-insensitivity\n\t\tchar* real = casepath(gImgNames[0], false);\n\t\tif (real)\n\t\t{\n\t\t\trealpath(real, path);\n\t\t\tfree(real);\n\t\t\tif (stat(path, &statbuf) != -1)\n\t\t\t\tgoto ok;\n\t\t}\n\n\t\tCDTRACE(\"can't get size of gta3.img\");\n\t\tASSERT(0);\n\t\treturn 0;\n\t}\n\tok:\n\treturn (uint32)statbuf.st_size;\n}\n\nvoid\nCdStreamShutdown(void)\n{\n    // Destroying semaphores and free(gpReadInfo) will be done at threads\n#ifndef ONE_THREAD_PER_CHANNEL\n\tgCdStreamThreadStatus = 2;\n\tsem_post(gCdStreamSema);\n\tpthread_join(_gCdStreamThread, nil);\n#else\n\tfor ( int32 i = 0; i < gNumChannels; i++ ) {\n\t\tgpReadInfo[i].nThreadStatus = 2;\n\t\tsem_post(gpReadInfo[i].pStartSemaphore);\n\t\tpthread_join(gpReadInfo[i].pChannelThread, nil);\n\t}\n#endif\n}\n\n\nint32\nCdStreamRead(int32 channel, void *buffer, uint32 offset, uint32 size)\n{\n\tASSERT( channel < gNumChannels );\n\tASSERT( buffer != nil );\n\n\tlastPosnRead = size + offset;\n\n\tASSERT( _GET_INDEX(offset) < MAX_CDIMAGES );\n\tint32 hImage = gImgFiles[_GET_INDEX(offset)];\n\tASSERT( hImage > 0 );\n\n\tCdReadInfo *pChannel = &gpReadInfo[channel];\n\tASSERT( pChannel != nil );\n\n\tif ( pChannel->nSectorsToRead != 0 || pChannel->bReading ) {\n\t\tif (pChannel->hFile == hImage - 1 && pChannel->nSectorOffset == _GET_OFFSET(offset) && pChannel->nSectorsToRead >= size)\n\t\t\treturn STREAM_SUCCESS;\n#ifdef FLUSHABLE_STREAMING\n\t\tflushStream[channel] = 1;\n\t\tCdStreamSync(channel);\n#else\n\t\treturn STREAM_NONE;\n#endif\n\t}\n\n\tpChannel->hFile = hImage - 1;\n\tpChannel->nStatus = STREAM_NONE;\n\tpChannel->nSectorOffset = _GET_OFFSET(offset);\n\tpChannel->nSectorsToRead = size;\n\tpChannel->pBuffer = buffer;\n\tpChannel->bLocked = 0;\n\n#ifndef ONE_THREAD_PER_CHANNEL\n\tAddToQueue(&gChannelRequestQ, channel);\n\tif ( sem_post(gCdStreamSema) != 0 )\n\t\tprintf(\"Signal Sema Error\\n\");\n#else\n\tif ( sem_post(pChannel->pStartSemaphore) != 0 )\n\t\tprintf(\"Signal Sema Error\\n\");\n#endif\n\n\treturn STREAM_SUCCESS;\n}\n\nint32\nCdStreamGetStatus(int32 channel)\n{\n\tASSERT( channel < gNumChannels );\n\tCdReadInfo *pChannel = &gpReadInfo[channel];\n\tASSERT( pChannel != nil );\n\n#ifdef ONE_THREAD_PER_CHANNEL\n\tif (pChannel->nThreadStatus == 2)\n\t\treturn STREAM_NONE;\n#else\n\tif (gCdStreamThreadStatus == 2)\n\t\treturn STREAM_NONE;\n#endif\n\n\tif ( pChannel->bReading )\n\t\treturn STREAM_READING;\n\n\tif ( pChannel->nSectorsToRead != 0 )\n\t\treturn STREAM_WAITING;\n\n\tif ( pChannel->nStatus != STREAM_NONE )\n\t{\n\t\tint32 status = pChannel->nStatus;\n\t\tpChannel->nStatus = STREAM_NONE;\n\n\t\treturn status;\n\t}\n\n\treturn STREAM_NONE;\n}\n\nint32\nCdStreamGetLastPosn(void)\n{\n\treturn lastPosnRead;\n}\n\n// wait for channel to finish reading\nint32\nCdStreamSync(int32 channel)\n{\n\tASSERT( channel < gNumChannels );\n\tCdReadInfo *pChannel = &gpReadInfo[channel];\n\tASSERT( pChannel != nil );\n\n#ifdef FLUSHABLE_STREAMING\n\tif (flushStream[channel]) {\n\t\tpChannel->nSectorsToRead = 0;\n#ifdef ONE_THREAD_PER_CHANNEL\n\t\tpthread_kill(pChannel->pChannelThread, SIGUSR1);\n\t\tif (pChannel->bReading) {\n\t\t\tpChannel->bLocked = true;\n#else\n\t\tif (pChannel->bReading) {\n\t\t\tpChannel->bLocked = true;\n\t\t\tpthread_kill(_gCdStreamThread, SIGUSR1);\n#endif\n\t\t\twhile (pChannel->bLocked)\n\t\t\t\tsem_wait(pChannel->pDoneSemaphore);\n\t\t}\n\t\tpChannel->bReading = false;\n\t\tflushStream[channel] = false;\n\t\treturn STREAM_NONE;\n\t}\n#endif\n\n\tif ( pChannel->nSectorsToRead != 0 )\n\t{\n\t\tpChannel->bLocked = true;\n\t\twhile (pChannel->bLocked && pChannel->nSectorsToRead != 0){\n\t\t\tsem_wait(pChannel->pDoneSemaphore);\n\t\t}\n\t\tpChannel->bLocked = false;\n\t}\n\n\tpChannel->bReading = false;\n\n\treturn pChannel->nStatus;\n}\n\nvoid\nAddToQueue(Queue *queue, int32 item)\n{\n\tASSERT( queue != nil );\n\tASSERT( queue->items != nil );\n\tqueue->items[queue->tail] = item;\n\n\tqueue->tail = (queue->tail + 1) % queue->size;\n\n\tif ( queue->head == queue->tail )\n\t\tdebug(\"Queue is full\\n\");\n}\n\nint32\nGetFirstInQueue(Queue *queue)\n{\n\tASSERT( queue != nil );\n\tif ( queue->head == queue->tail )\n\t\treturn -1;\n\n\tASSERT( queue->items != nil );\n\treturn queue->items[queue->head];\n}\n\nvoid\nRemoveFirstInQueue(Queue *queue)\n{\n\tASSERT( queue != nil );\n\tif ( queue->head == queue->tail )\n\t{\n\t\tdebug(\"Queue is empty\\n\");\n\t\treturn;\n\t}\n\n\tqueue->head = (queue->head + 1) % queue->size;\n}\n\nvoid *CdStreamThread(void *param)\n{\n\tdebug(\"Created cdstream thread\\n\");\n\n#ifndef ONE_THREAD_PER_CHANNEL\n\twhile (gCdStreamThreadStatus != 2) {\n\t\tsem_wait(gCdStreamSema);\n\n\t\tint32 channel = GetFirstInQueue(&gChannelRequestQ);\n\t\t\n\t\t// spurious wakeup\n\t\tif (channel == -1)\n\t\t\tcontinue;\n#else\n\tint channel = *((int*)param);\n\twhile (gpReadInfo[channel].nThreadStatus != 2){\n\t\tsem_wait(gpReadInfo[channel].pStartSemaphore);\n#endif\n\n\t\tCdReadInfo *pChannel = &gpReadInfo[channel];\n\t\tASSERT( pChannel != nil );\n\n\t\t// spurious wakeup or we sent interrupt signal for flushing\n\t\tif(pChannel->nSectorsToRead == 0)\n\t\t\tcontinue;\n\n\t\tpChannel->bReading = true;\n\n\t\t// Not standard POSIX :shrug:\n#ifdef __linux__\n#ifdef ONE_THREAD_PER_CHANNEL\n\t\tif (gpReadInfo[channel].nThreadStatus == 0){\n\t\t\tgpReadInfo[channel].nThreadStatus = 1;\n#else\n\t\tif (gCdStreamThreadStatus == 0){\n\t\t\tgCdStreamThreadStatus = 1;\n#endif\n\t\t\tpid_t tid = syscall(SYS_gettid);\n\t\t\tint ret = setpriority(PRIO_PROCESS, tid, getpriority(PRIO_PROCESS, getpid()) + 1);\n\t\t}\n#endif\n\t\tif ( pChannel->nStatus == STREAM_NONE )\n\t\t{\n\t\t\tASSERT(pChannel->hFile >= 0);\n\t\t\tASSERT(pChannel->pBuffer != nil );\n\n\t\t\tlseek(pChannel->hFile, (size_t)pChannel->nSectorOffset * (size_t)CDSTREAM_SECTOR_SIZE, SEEK_SET);\n\t\t\tif (read(pChannel->hFile, pChannel->pBuffer, pChannel->nSectorsToRead * CDSTREAM_SECTOR_SIZE) == -1) {\n\t\t\t\t// pChannel->nSectorsToRead == 0 at this point means we wanted to flush channel\n\t\t\t\t// STREAM_WAITING is a little hack to make CStreaming not process this data\n\t\t\t\tpChannel->nStatus = pChannel->nSectorsToRead == 0 ? STREAM_WAITING : STREAM_ERROR;\n\t\t\t} else {\n\t\t\t\tpChannel->nStatus = STREAM_NONE;\n\t\t\t}\n\t\t}\n\n#ifndef ONE_THREAD_PER_CHANNEL\n\t\tRemoveFirstInQueue(&gChannelRequestQ);\n#endif\n\n\t\tpChannel->nSectorsToRead = 0;\n\t\tif ( pChannel->bLocked )\n\t\t{\n\t\t\tpChannel->bLocked = 0;\n\t\t\tsem_post(pChannel->pDoneSemaphore);\n\t\t}\n\t\tpChannel->bReading = false;\n\t}\n\tchar semName[20];\n#ifndef ONE_THREAD_PER_CHANNEL\n\tfor ( int32 i = 0; i < gNumChannels; i++ )\n\t{\n\t\tRE3_SEM_CLOSE(gpReadInfo[i].pDoneSemaphore, \"/semaphore_done%d\", i);\n\t}\n\tRE3_SEM_CLOSE(gCdStreamSema, \"/semaphore_cd_stream\");\n\tfree(gChannelRequestQ.items);\n#else\n\tRE3_SEM_CLOSE(gpReadInfo[channel].pStartSemaphore, \"/semaphore_start%d\", channel);\n\n\tRE3_SEM_CLOSE(gpReadInfo[channel].pDoneSemaphore, \"/semaphore_done%d\", channel);\n#endif\n\tif (gpReadInfo)\n\t\tfree(gpReadInfo);\n\tgpReadInfo = nil;\n\tpthread_exit(nil);\n}\n\nbool\nCdStreamAddImage(char const *path)\n{\n\tASSERT(path != nil);\n\tASSERT(gNumImages < MAX_CDIMAGES);\n\n\tgImgFiles[gNumImages] = open(path, _gdwCdStreamFlags);\n\n\t// Fix case sensitivity and backslashes.\n\tif (gImgFiles[gNumImages] == -1) {\n\t\tchar* real = casepath(path, false);\n\t\tif (real)\n\t\t{\n\t\t\tgImgFiles[gNumImages] = open(real, _gdwCdStreamFlags);\n\t\t\tfree(real);\n\t\t}\n\t}\n\n\tif ( gImgFiles[gNumImages] == -1 ) {\n\t\tassert(false);\n\t\treturn false;\n\t}\n\n\tgImgNames[gNumImages] = strdup(path);\n\tgImgFiles[gNumImages]++; // because -1: error 0: not used\n\n\tstrcpy(gCdImageNames[gNumImages], path);\n\n\tgNumImages++;\n\n\treturn true;\n}\n\nchar *\nCdStreamGetImageName(int32 cd)\n{\n\tASSERT(cd < MAX_CDIMAGES);\n\tif ( gImgFiles[cd] > 0)\n\t\treturn gCdImageNames[cd];\n\n\treturn nil;\n}\n\nvoid\nCdStreamRemoveImages(void)\n{\n\tfor ( int32 i = 0; i < gNumChannels; i++ ) {\n#ifdef FLUSHABLE_STREAMING\n\t\tflushStream[i] = 1;\n#endif\n\t\tCdStreamSync(i);\n\t}\n\n\tfor ( int32 i = 0; i < gNumImages; i++ )\n\t{\n\t\tclose(gImgFiles[i] - 1);\n\t\tfree(gImgNames[i]);\n\t\tgImgFiles[i] = 0;\n\t}\n\n\tgNumImages = 0;\n}\n\nint32\nCdStreamGetNumImages(void)\n{\n\treturn gNumImages;\n}\n#endif\n"
  },
  {
    "path": "src/core/Clock.cpp",
    "content": "#include \"common.h\"\n\n#include \"Timer.h\"\n#include \"Pad.h\"\n#include \"Clock.h\"\n#include \"Stats.h\"\n#include \"VarConsole.h\"\n\n_TODO(\"gbFastTime\");\nbool gbFastTime;\n\nuint8  CClock::ms_nGameClockHours;\nuint8  CClock::ms_nGameClockMinutes;\nuint16 CClock::ms_nGameClockSeconds;\nuint8  CClock::ms_Stored_nGameClockHours;\nuint8  CClock::ms_Stored_nGameClockMinutes;\nuint16 CClock::ms_Stored_nGameClockSeconds;\nuint32 CClock::ms_nMillisecondsPerGameMinute;\nuint32  CClock::ms_nLastClockTick;\nbool   CClock::ms_bClockHasBeenStored;\n\n#ifndef MASTER\nbool gbFreezeTime;\n#endif\n\nvoid\nCClock::Initialise(uint32 scale)\n{\n\tdebug(\"Initialising CClock...\\n\");\n\tms_nGameClockHours = 12;\n\tms_nGameClockMinutes = 0;\n\tms_nGameClockSeconds = 0;\n\tms_nMillisecondsPerGameMinute = scale;\n\tms_nLastClockTick = CTimer::GetTimeInMilliseconds();\n\tms_bClockHasBeenStored = false;\n\tdebug(\"CClock ready\\n\");\n#ifndef MASTER\n\tVarConsole.Add(\"Time (hour of day)\", &ms_nGameClockHours, 1, 0, 23, true);\n\tVarConsole.Add(\"Freeze time\", &gbFreezeTime, true);\n#endif\n}\n\nvoid\nCClock::Update(void)\n{\n\tif(CPad::GetPad(1)->GetRightShoulder1())\n\t{\n\t\tms_nGameClockMinutes += 8;\n\t\tms_nLastClockTick = CTimer::GetTimeInMilliseconds();\n\t\t\n\t\tif(ms_nGameClockMinutes >= 60)\n\t\t{\n\t\t\tms_nGameClockHours++;\n\t\t\tms_nGameClockMinutes = 0;\n\t\t\tif(ms_nGameClockHours >= 24)\n\t\t\t\tms_nGameClockHours = 0;\n\t\t}\n\t\t\n\t}\n#ifndef MASTER\n\telse if (gbFreezeTime)\n\t\tms_nLastClockTick = CTimer::GetTimeInMilliseconds();\n#endif\n\telse if(CTimer::GetTimeInMilliseconds() - ms_nLastClockTick > ms_nMillisecondsPerGameMinute || gbFastTime)\n\t{\n\t\tms_nGameClockMinutes++;\n\t\tms_nLastClockTick += ms_nMillisecondsPerGameMinute;\n\t\t\n\t\tif ( gbFastTime )\n\t\t\tms_nLastClockTick = CTimer::GetTimeInMilliseconds();\n\t\t\n\t\tif(ms_nGameClockMinutes >= 60)\n\t\t{\n\t\t\tms_nGameClockHours++;\n\t\t\tms_nGameClockMinutes = 0;\n\t\t\tif(ms_nGameClockHours >= 24)\n\t\t\t{\n\t\t\t\tCStats::DaysPassed++;\n\t\t\t\tms_nGameClockHours = 0;\n\t\t\t}\n\t\t}\n\t}\n\tms_nGameClockSeconds = 60 * (CTimer::GetTimeInMilliseconds() - ms_nLastClockTick) / ms_nMillisecondsPerGameMinute;\n}\n\nvoid\nCClock::SetGameClock(uint8 h, uint8 m)\n{\n\twhile (m >= 60) {\n\t\tm -= 60;\n\t\th++;\n\t}\n\tms_nGameClockMinutes = m;\n\twhile (h >= 24)\n\t\th -= 24;\n\tms_nGameClockHours = h;\n\tms_nGameClockSeconds = 0;\n\tms_nLastClockTick = CTimer::GetTimeInMilliseconds();\n}\n\nint32\nCClock::GetGameClockMinutesUntil(uint8 h, uint8 m)\n{\n\tint32 now, then;\n\tnow = ms_nGameClockHours*60 + ms_nGameClockMinutes;\n\tthen = h*60 + m;\n\tif(then < now)\n\t\tthen += 24*60;\n\treturn then-now;\n}\n\nbool\nCClock::GetIsTimeInRange(uint8 h1, uint8 h2)\n{\n\tif(h1 > h2)\n\t\treturn ms_nGameClockHours >= h1 || ms_nGameClockHours < h2;\n\telse\n\t\treturn ms_nGameClockHours >= h1 && ms_nGameClockHours < h2;\n}\n\nvoid\nCClock::StoreClock(void)\n{\n\tms_Stored_nGameClockHours = ms_nGameClockHours;\n\tms_Stored_nGameClockMinutes = ms_nGameClockMinutes;\n\tms_Stored_nGameClockSeconds = ms_nGameClockSeconds;\n\tms_bClockHasBeenStored = true;\n}\n\nvoid\nCClock::RestoreClock(void)\n{\n\tms_nGameClockHours = ms_Stored_nGameClockHours;\n\tms_nGameClockMinutes = ms_Stored_nGameClockMinutes;\n\tms_nGameClockSeconds = ms_Stored_nGameClockSeconds;\n}\n"
  },
  {
    "path": "src/core/Clock.h",
    "content": "#pragma once\n\nclass CClock\n{\npublic:\n\tstatic uint8  ms_nGameClockHours;\n\tstatic uint8  ms_nGameClockMinutes;\n\tstatic uint16 ms_nGameClockSeconds;\n\tstatic uint8  ms_Stored_nGameClockHours;\n\tstatic uint8  ms_Stored_nGameClockMinutes;\n\tstatic uint16 ms_Stored_nGameClockSeconds;\n\tstatic uint32 ms_nMillisecondsPerGameMinute;\n\tstatic uint32 ms_nLastClockTick;\n\tstatic bool   ms_bClockHasBeenStored;\n\n\tstatic void Initialise(uint32 scale);\n\tstatic void Update(void);\n\tstatic void SetGameClock(uint8 h, uint8 m);\n\tstatic int32 GetGameClockMinutesUntil(uint8 h, uint8 m);\n\tstatic bool GetIsTimeInRange(uint8 h1, uint8 h2);\n\tstatic void StoreClock(void);\n\tstatic void RestoreClock(void);\n\n\tstatic uint8 GetHours(void) { return ms_nGameClockHours; }\n\tstatic uint8 GetMinutes(void) { return ms_nGameClockMinutes; }\n\tstatic int16 GetSeconds(void) { return ms_nGameClockSeconds; }\n\n\n\tstatic uint8 &GetHoursRef(void) { return ms_nGameClockHours; }\n\tstatic uint8 &GetMinutesRef(void) { return ms_nGameClockMinutes; }\n};\n"
  },
  {
    "path": "src/core/ControllerConfig.cpp",
    "content": "#define WITHDINPUT\n#include \"common.h\"\n#include \"platform.h\"\n#include \"crossplatform.h\"\n#include \"ControllerConfig.h\"\n#include \"Pad.h\"\n#include \"FileMgr.h\"\n#include \"Text.h\"\n#include \"Font.h\"\n#include \"Messages.h\"\n#include \"Frontend.h\"\n#include \"Ped.h\"\n#include \"PlayerPed.h\"\n#include \"Vehicle.h\"\n#include \"World.h\"\n#include \"ModelIndices.h\"\n#include \"Camera.h\"\n#include \"GenericGameStorage.h\"\n\nCControllerConfigManager ControlsManager;\n\nCControllerConfigManager::CControllerConfigManager()\n{\n\tm_bFirstCapture    = false;\n\tm_bMouseAssociated = false;\n\n\tMakeControllerActionsBlank();\n\tInitDefaultControlConfiguration();\n\tInitialiseControllerActionNameArray();\n}\n\nvoid CControllerConfigManager::MakeControllerActionsBlank()\n{\n#ifdef LOAD_INI_SETTINGS\n\tms_padButtonsInited = 0;\n#endif\n\tfor (int32 i = 0; i < MAX_CONTROLLERTYPES; i++)\n\t{\n\t\tfor (int32 j = 0; j < MAX_CONTROLLERACTIONS; j++)\n\t\t{\n\t\t\tClearSettingsAssociatedWithAction((e_ControllerAction)j, (eControllerType)i);\n\t\t}\n\t}\n}\n\n#ifdef RW_GL3\nint MapIdToButtonId(int mapId) {\n\tswitch (mapId) {\n\t\tcase GLFW_GAMEPAD_BUTTON_A: // Cross\n\t\t\treturn 2;\n\t\tcase GLFW_GAMEPAD_BUTTON_B: // Circle\n\t\t\treturn 1;\n\t\tcase GLFW_GAMEPAD_BUTTON_X: // Square\n\t\t\treturn 3;\n\t\tcase GLFW_GAMEPAD_BUTTON_Y: // Triangle\n\t\t\treturn 4;\n\t\tcase GLFW_GAMEPAD_BUTTON_LEFT_BUMPER:\n\t\t\treturn 7;\n\t\tcase GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER:\n\t\t\treturn 8;\n\t\tcase GLFW_GAMEPAD_BUTTON_BACK:\n\t\t\treturn 9;\n\t\tcase GLFW_GAMEPAD_BUTTON_START:\n\t\t\treturn 12;\n\t\tcase GLFW_GAMEPAD_BUTTON_LEFT_THUMB:\n\t\t\treturn 10;\n\t\tcase GLFW_GAMEPAD_BUTTON_RIGHT_THUMB:\n\t\t\treturn 11;\n\t\tcase GLFW_GAMEPAD_BUTTON_DPAD_UP:\n\t\t\treturn 13;\n\t\tcase GLFW_GAMEPAD_BUTTON_DPAD_RIGHT:\n\t\t\treturn 14;\n\t\tcase GLFW_GAMEPAD_BUTTON_DPAD_DOWN:\n\t\t\treturn 15;\n\t\tcase GLFW_GAMEPAD_BUTTON_DPAD_LEFT:\n\t\t\treturn 16;\n\t\t// GLFW sends those as axes, so I added them here manually.\n\t\tcase 15: // Left trigger\n\t\t\treturn 5;\n\t\tcase 16: // Right trigger\n\t\t\treturn 6;\n\t\tdefault:\n\t\t\treturn 0;\n\t}\n}\n#endif\n\nint32 CControllerConfigManager::GetJoyButtonJustDown()\n{\n#ifdef __DINPUT_INCLUDED__\n#ifdef FIX_BUGS\n\tfor (int32 i = 0; i < MAX_BUTTONS; i++)\n#else\n\tfor (int32 i = 0; i < JOY_BUTTONS; i++)\n#endif\n\t{\n\t\tif (m_NewState.rgbButtons[i] & 0x80 && !(m_OldState.rgbButtons[i] & 0x80))\n\t\t\treturn i + 1;\n\t}\n#elif defined RW_GL3\n\tif (m_NewState.isGamepad) {\n\t\tfor (int32 i = 0; i < MAX_BUTTONS; i++) {\n\t\t\tif (m_NewState.mappedButtons[i] && !(m_OldState.mappedButtons[i]))\n\t\t\t\treturn MapIdToButtonId(i);\n\t\t}\n\t} else {\n\t\tfor (int32 i = 0; i < Min(m_NewState.numButtons, MAX_BUTTONS); i++) {\n\t\t\tif (m_NewState.buttons[i] && !(m_OldState.buttons[i]))\n\t\t\t\treturn i + 1;\n\t\t}\n\t}\n#endif\n\treturn 0;\n}\n\nvoid CControllerConfigManager::SaveSettings(int32 file)\n{\n\tif (file)\n\t{\n\t\tfor (int32 i = 0; i < MAX_CONTROLLERTYPES; i++)\n\t\t{\n\t\t\tfor (int32 j = 0; j < MAX_CONTROLLERACTIONS; j++)\n\t\t\t{\n\t\t\t\tCFileMgr::Write(file, (char *)&ControlsManager.m_aSettings[j][i], sizeof(tControllerConfigBind));\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid CControllerConfigManager::LoadSettings(int32 file)\n{\n\tbool bValid = true;\n\tint nVersion = 0;\n#ifdef BIND_VEHICLE_FIREWEAPON\n\tbool skipVehicleFireWeapon = false;\n#endif\n\n\tif (file)\n\t{\n\t\tchar buff[29];\n\t\tCFileMgr::Read(file, buff, sizeof(buff));\n\n\t\tif (!strncmp(buff, TopLineEmptyFile, sizeof(TopLineEmptyFile)-1))\n\t\t\tbValid = false;\n\t\telse {\n\t\t\tCFileMgr::Seek(file, 0, 0);\n\t\t\tCFileMgr::Read(file, (char*)&nVersion, sizeof(nVersion));\n\t\t}\n\t}\n\n\tif (bValid && nVersion >= 3)\n\t{\n\t\tControlsManager.MakeControllerActionsBlank();\n#ifdef BIND_VEHICLE_FIREWEAPON\n\t\tskipVehicleFireWeapon = nVersion < 4;\n\t\t// Set the default settings of VEHICLE_FIREWEAPON\n\t\tif (skipVehicleFireWeapon) {\n\t\t\tSetControllerKeyAssociatedWithAction(VEHICLE_FIREWEAPON, rsPADINS, KEYBOARD);\n\t\t\tSetControllerKeyAssociatedWithAction(VEHICLE_FIREWEAPON, rsLCTRL, OPTIONAL_EXTRA);\n\t\t\tif (m_bMouseAssociated)\n\t\t\t\tSetMouseButtonAssociatedWithAction(VEHICLE_FIREWEAPON, 1);\n\t\t}\n#endif\n\n\t\tfor (int32 i = 0; i < MAX_CONTROLLERTYPES; i++)\n\t\t{\n\t\t\tfor (int32 j = 0; j < MAX_CONTROLLERACTIONS; j++)\n\t\t\t{\n#ifdef BIND_VEHICLE_FIREWEAPON\n\t\t\t\t// Skip file read\n\t\t\t\tif (skipVehicleFireWeapon && j == VEHICLE_FIREWEAPON)\n\t\t\t\t\tcontinue;\n#endif\n\t\t\t\tCFileMgr::Read(file, (char *)&ControlsManager.m_aSettings[j][i], sizeof(tControllerConfigBind));\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid CControllerConfigManager::InitDefaultControlConfiguration()\n{\n\tSetControllerKeyAssociatedWithAction    (VEHICLE_LOOKLEFT,                    rsPADEND,   KEYBOARD);\n\tSetControllerKeyAssociatedWithAction    (VEHICLE_LOOKLEFT,                    'Q',        OPTIONAL_EXTRA);\n\t\t\t\t\t\t\t\t\t\t    \t\t\t\t\t\t              \n\tSetControllerKeyAssociatedWithAction    (VEHICLE_LOOKRIGHT,                   rsPADDOWN,  KEYBOARD);\n\tSetControllerKeyAssociatedWithAction    (VEHICLE_LOOKRIGHT,                   'E',        OPTIONAL_EXTRA);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t              \n\tif ( _dwOperatingSystemVersion == OS_WIN98 )\t\t\t\t\t\t\t\t\t\t\t              \n\t\tSetControllerKeyAssociatedWithAction(VEHICLE_HORN,                        rsSHIFT,    OPTIONAL_EXTRA); // BUG: must be KEYBOARD ?\t\t\t\t\t\t\t\t\t\t\t              \n\telse\t\t\n\t{\n\t\tSetControllerKeyAssociatedWithAction(VEHICLE_HORN,                        rsLSHIFT,   OPTIONAL_EXTRA);\n\t\tSetControllerKeyAssociatedWithAction(VEHICLE_HORN,                        rsRSHIFT,   KEYBOARD);\n\t}\t\t\t\t\t\t\t\t\t\t\t\t\t              \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t              \n\tSetControllerKeyAssociatedWithAction    (VEHICLE_HANDBRAKE,                   rsRCTRL,    KEYBOARD);\n\tSetControllerKeyAssociatedWithAction    (VEHICLE_HANDBRAKE,                   ' ',        OPTIONAL_EXTRA);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t                      \n\tSetControllerKeyAssociatedWithAction    (VEHICLE_ENTER_EXIT,                  rsENTER,    KEYBOARD);\n\tSetControllerKeyAssociatedWithAction    (VEHICLE_ENTER_EXIT,                  'F',        OPTIONAL_EXTRA);\n\t\t\t\t\t\t\t\t\t\t    \t\t\t\t\t                  \n\tSetControllerKeyAssociatedWithAction    (VEHICLE_ACCELERATE,                  rsUP,       KEYBOARD);\n\tSetControllerKeyAssociatedWithAction    (VEHICLE_ACCELERATE,                  'W',        OPTIONAL_EXTRA);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t          \n\tSetControllerKeyAssociatedWithAction    (VEHICLE_CHANGE_RADIO_STATION,        rsINS,      KEYBOARD);\n\tSetControllerKeyAssociatedWithAction    (VEHICLE_CHANGE_RADIO_STATION,        'R',        OPTIONAL_EXTRA);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t          \n\tSetControllerKeyAssociatedWithAction    (VEHICLE_BRAKE,                       rsDOWN,     KEYBOARD);\n\tSetControllerKeyAssociatedWithAction    (VEHICLE_BRAKE,                       'S',        OPTIONAL_EXTRA);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t          \n\tSetControllerKeyAssociatedWithAction    (TOGGLE_SUBMISSIONS,                  rsPLUS,     KEYBOARD);\n\tSetControllerKeyAssociatedWithAction    (TOGGLE_SUBMISSIONS,                  rsCAPSLK,   OPTIONAL_EXTRA);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t          \n\tSetControllerKeyAssociatedWithAction    (GO_LEFT,                             rsLEFT,     KEYBOARD);\n\tSetControllerKeyAssociatedWithAction    (GO_LEFT,                             'A',        OPTIONAL_EXTRA);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t          \n\tSetControllerKeyAssociatedWithAction    (GO_RIGHT,                            rsRIGHT,    KEYBOARD);\n\tSetControllerKeyAssociatedWithAction    (GO_RIGHT,                            'D',        OPTIONAL_EXTRA);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t          \n\tSetControllerKeyAssociatedWithAction    (GO_FORWARD,                          rsUP,       KEYBOARD);\n\tSetControllerKeyAssociatedWithAction    (GO_FORWARD,                          'W',        OPTIONAL_EXTRA);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t          \n\tSetControllerKeyAssociatedWithAction    (GO_BACK,                             rsDOWN,     KEYBOARD);\n\tSetControllerKeyAssociatedWithAction    (GO_BACK,                             'S',        OPTIONAL_EXTRA);\n\n\tSetControllerKeyAssociatedWithAction    (NETWORK_TALK,                        'T',        KEYBOARD);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t          \n\tSetControllerKeyAssociatedWithAction    (PED_LOOKBEHIND,                      rsPADEND,   KEYBOARD);\n\tSetControllerKeyAssociatedWithAction    (PED_LOOKBEHIND,                      rsCAPSLK,   OPTIONAL_EXTRA);\n\n\tSetControllerKeyAssociatedWithAction    (PED_DUCK,                            'C',        KEYBOARD);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t          \n\tSetControllerKeyAssociatedWithAction    (PED_FIREWEAPON,                      rsPADINS,   KEYBOARD);\n\tSetControllerKeyAssociatedWithAction    (PED_FIREWEAPON,                      rsLCTRL,    OPTIONAL_EXTRA);\n#ifdef BIND_VEHICLE_FIREWEAPON\n\tSetControllerKeyAssociatedWithAction    (VEHICLE_FIREWEAPON,                  rsPADINS,   KEYBOARD);\n\tSetControllerKeyAssociatedWithAction    (VEHICLE_FIREWEAPON,                  rsLCTRL,    OPTIONAL_EXTRA);\n#endif\n\tSetControllerKeyAssociatedWithAction    (PED_CYCLE_WEAPON_LEFT,               rsPADDEL,   KEYBOARD);\n\n\tSetControllerKeyAssociatedWithAction    (PED_CYCLE_WEAPON_RIGHT,              rsPADENTER, OPTIONAL_EXTRA); // BUG: must be KEYBOARD ?\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t          \n\tSetControllerKeyAssociatedWithAction    (PED_LOCK_TARGET,                     rsDEL,      KEYBOARD);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t          \n\tSetControllerKeyAssociatedWithAction    (PED_JUMPING,                         rsRCTRL,    KEYBOARD);\n\tSetControllerKeyAssociatedWithAction    (PED_JUMPING,                         ' ',        OPTIONAL_EXTRA);\n\n\tSetControllerKeyAssociatedWithAction    (PED_ANSWER_PHONE,                    rsTAB,      KEYBOARD);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t              \n\tif ( _dwOperatingSystemVersion == OS_WIN98 )\t\t\t\t\t\t\t\t\t\t\t              \n\t\tSetControllerKeyAssociatedWithAction(PED_SPRINT,                          rsSHIFT,    OPTIONAL_EXTRA); // BUG: must be KEYBOARD ?\t\t\t\t\t\t\t\t\t\t\t              \n\telse\t\t\n\t{\n\t\tSetControllerKeyAssociatedWithAction(PED_SPRINT,                          rsLSHIFT,   OPTIONAL_EXTRA);\n#ifndef FIX_BUGS\n\t\tSetControllerKeyAssociatedWithAction(PED_SPRINT,                          rsRSHIFT,   OPTIONAL_EXTRA); // BUG: must be KEYBOARD\n#else\n\t\tSetControllerKeyAssociatedWithAction(PED_SPRINT,                          rsRSHIFT,   KEYBOARD);\n#endif\n\t}\n\n\tSetControllerKeyAssociatedWithAction    (PED_CYCLE_TARGET_LEFT,               '[',        KEYBOARD);\n\n\tSetControllerKeyAssociatedWithAction    (PED_CYCLE_TARGET_RIGHT,              ']',        OPTIONAL_EXTRA); // BUG: must be KEYBOARD ?\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t      \n\tSetControllerKeyAssociatedWithAction    (PED_CENTER_CAMERA_BEHIND_PLAYER,     '#',        KEYBOARD);\n\t\n\tSetControllerKeyAssociatedWithAction    (PED_SNIPER_ZOOM_IN,                  rsPGUP,     KEYBOARD);\n\tSetControllerKeyAssociatedWithAction    (PED_SNIPER_ZOOM_IN,                  'Z',        OPTIONAL_EXTRA);\n\t\t\t\t\t\t\t\t\t\t    \n\tSetControllerKeyAssociatedWithAction    (PED_SNIPER_ZOOM_OUT,                 rsPGDN,     KEYBOARD);\n\tSetControllerKeyAssociatedWithAction    (PED_SNIPER_ZOOM_OUT,                 'X',        OPTIONAL_EXTRA);\n\t\t\t\t\t\t\t\t\t\t    \n\tSetControllerKeyAssociatedWithAction    (PED_1RST_PERSON_LOOK_LEFT,           rsPADLEFT,  KEYBOARD);\n\n\tSetControllerKeyAssociatedWithAction    (PED_1RST_PERSON_LOOK_RIGHT,          rsPADRIGHT, KEYBOARD);\n\t\t\t\t\t\t\t\t\t\t    \n\tSetControllerKeyAssociatedWithAction    (PED_1RST_PERSON_LOOK_UP,             rsPADUP,    KEYBOARD);\n\n\tSetControllerKeyAssociatedWithAction    (PED_1RST_PERSON_LOOK_DOWN,           rsPAD5,     KEYBOARD);\n\t\t\t\t\t\t\t\t\t\t    \n\tSetControllerKeyAssociatedWithAction    (VEHICLE_TURRETLEFT,                  rsPADLEFT,  KEYBOARD);\n\n\tSetControllerKeyAssociatedWithAction    (VEHICLE_TURRETRIGHT,                 rsPAD5,     KEYBOARD);\n\t\t\t\t\t\t\t\t\t\t    \n\tSetControllerKeyAssociatedWithAction    (VEHICLE_TURRETUP,                    rsPADPGUP,  KEYBOARD);\n\n\tSetControllerKeyAssociatedWithAction    (VEHICLE_TURRETDOWN,                  rsPADRIGHT, KEYBOARD);\n\t\t\t\t\t\t\t\t\t\t    \n\tSetControllerKeyAssociatedWithAction    (CAMERA_CHANGE_VIEW_ALL_SITUATIONS,   rsHOME,     KEYBOARD);\n\tSetControllerKeyAssociatedWithAction    (CAMERA_CHANGE_VIEW_ALL_SITUATIONS,   'V',        OPTIONAL_EXTRA);\n\n\tfor (int32 i = 0; i < MAX_SIMS; i++)\n\t{\n\t\tm_aSimCheckers[i][KEYBOARD]       = false;\n\t\tm_aSimCheckers[i][OPTIONAL_EXTRA] = false;\n\t\tm_aSimCheckers[i][MOUSE]          = false;\n\t\tm_aSimCheckers[i][JOYSTICK]       = false;\n\t}\n}\n\nvoid CControllerConfigManager::InitDefaultControlConfigMouse(CMouseControllerState const &availableButtons)\n{\n\tif (availableButtons.LMB)\n\t{\n\t\tm_bMouseAssociated = true;\n\t\tSetMouseButtonAssociatedWithAction(PED_FIREWEAPON,               1);\n#ifdef BIND_VEHICLE_FIREWEAPON\t\n\t\tSetMouseButtonAssociatedWithAction(VEHICLE_FIREWEAPON,           1);\n#endif\n\t}\n\n\tif (availableButtons.RMB)\n\t{\n\t\tSetMouseButtonAssociatedWithAction(PED_LOCK_TARGET,              3);\n\n\t\tSetMouseButtonAssociatedWithAction(VEHICLE_HANDBRAKE,            3);\n\t}\n\n\tif (availableButtons.MMB)\n\t{\n\t\tSetMouseButtonAssociatedWithAction(VEHICLE_LOOKBEHIND,           2);\n\n\t\tSetMouseButtonAssociatedWithAction(PED_LOOKBEHIND,               2);\n\t}\n\n\tif (availableButtons.WHEELUP || availableButtons.WHEELDN)\n\t{\n\t\tSetMouseButtonAssociatedWithAction(PED_CYCLE_WEAPON_LEFT,        4);\n\n\t\tSetMouseButtonAssociatedWithAction(PED_CYCLE_WEAPON_RIGHT,       5);\n\n\t\tSetMouseButtonAssociatedWithAction(VEHICLE_CHANGE_RADIO_STATION, 4);\n\n\t\tSetMouseButtonAssociatedWithAction(PED_SNIPER_ZOOM_IN, 4);\n\n\t\tSetMouseButtonAssociatedWithAction(PED_SNIPER_ZOOM_OUT, 5);\n\t}\n}\n\n#ifdef LOAD_INI_SETTINGS\nuint32 CControllerConfigManager::ms_padButtonsInited = 0;\n#endif\n\nvoid CControllerConfigManager::InitDefaultControlConfigJoyPad(uint32 buttons)\n{\n#ifdef XINPUT\n\t// No manual bindings for you, honey.\n\treturn;\n#endif\n\n\tm_bFirstCapture = true;\n\n\tuint32 btn = buttons;\n\tif (buttons > 16)\n\t\tbtn = 16;\n\n#ifdef LOAD_INI_SETTINGS\n\tuint32 buttonMin = ms_padButtonsInited;\n\tif (buttonMin >= btn)\n\t\treturn;\n\n\tms_padButtonsInited = btn;\n\n\t#define IF_BTN_IN_RANGE(n) \\\n\t\tcase n: \\\n\t\tif (n <= buttonMin) \\\n\t\t\treturn;\n#else\n\t#define IF_BTN_IN_RANGE(n) \\\n\t\tcase n:\n#endif\n\n\t// Now we use SDL Game Controller DB\n#if defined RW_D3D9 || defined RWLIBS\n\tif (   AllValidWinJoys.m_aJoys[JOYSTICK1].m_nVendorID == 0x3427\n\t\t&& AllValidWinJoys.m_aJoys[JOYSTICK1].m_nProductID == 0x1190)\n#else\n\tif (0)\n#endif\n\t{\n\t\t//GIC USB Joystick, PS2 Gamepad ?\n\n\t\tswitch (btn)\n\t\t{\n\t\tIF_BTN_IN_RANGE(16)\n\t\t\tSetControllerKeyAssociatedWithAction(GO_LEFT,                           16, JOYSTICK);\n\t\tIF_BTN_IN_RANGE(15)\t\t\t\t\t\t\t\t\t\t\t                        \n\t\t\tSetControllerKeyAssociatedWithAction(GO_BACK,                           15, JOYSTICK);\n\t\tIF_BTN_IN_RANGE(14)\t\t\t\t\t\t\t\t\t\t\t                        \n\t\t\tSetControllerKeyAssociatedWithAction(GO_RIGHT,                          14, JOYSTICK);\n\t\tIF_BTN_IN_RANGE(13)\t\t\t\t\t\t\t\t\t\t\t                        \n\t\t\tSetControllerKeyAssociatedWithAction(GO_FORWARD,                        13, JOYSTICK);\n\t\tIF_BTN_IN_RANGE(12)\t\t\t\t\t\t\t\t\t\t\t\t\t                \n\t\tIF_BTN_IN_RANGE(11)\t\t\t\t\t\t\t\t\t\t\t\t\t                \n\t\t\tSetControllerKeyAssociatedWithAction(PED_LOOKBEHIND,                    11, JOYSTICK);\n\t\t\tSetControllerKeyAssociatedWithAction(TOGGLE_SUBMISSIONS,                11, JOYSTICK);\n\t\tIF_BTN_IN_RANGE(10)\n\t\t\tSetControllerKeyAssociatedWithAction(VEHICLE_HORN,                      10, JOYSTICK);\n\t\t\tSetControllerKeyAssociatedWithAction(PED_DUCK,                          10, JOYSTICK);\n\t\tIF_BTN_IN_RANGE(9)\n\t\t\tSetControllerKeyAssociatedWithAction(CAMERA_CHANGE_VIEW_ALL_SITUATIONS,  9, JOYSTICK);\n\t\tIF_BTN_IN_RANGE(8)\n\t\t\tSetControllerKeyAssociatedWithAction(VEHICLE_HANDBRAKE,                  8, JOYSTICK);\n\t\t\tSetControllerKeyAssociatedWithAction(PED_LOCK_TARGET,                    8, JOYSTICK);\n\t\tIF_BTN_IN_RANGE(7)\n\t\t\tSetControllerKeyAssociatedWithAction(PED_ANSWER_PHONE,                   7, JOYSTICK);\n\t\t\tSetControllerKeyAssociatedWithAction(VEHICLE_CHANGE_RADIO_STATION,       7, JOYSTICK);\n\t\tIF_BTN_IN_RANGE(6)\n\t\t\tSetControllerKeyAssociatedWithAction(PED_CYCLE_WEAPON_RIGHT,             6, JOYSTICK);\n\t\t\tSetControllerKeyAssociatedWithAction(VEHICLE_LOOKRIGHT,                  6, JOYSTICK);\n\t\tIF_BTN_IN_RANGE(5)\n\t\t\tSetControllerKeyAssociatedWithAction(PED_CYCLE_WEAPON_LEFT,              5, JOYSTICK);\n\t\t\tSetControllerKeyAssociatedWithAction(VEHICLE_LOOKLEFT,                   5, JOYSTICK);\n\t\t/*******************************************************************************************/\n\t\tIF_BTN_IN_RANGE(4)\n\t\t\tSetControllerKeyAssociatedWithAction(VEHICLE_BRAKE,                      4, JOYSTICK);\n\t\t\tSetControllerKeyAssociatedWithAction(PED_JUMPING,                        4, JOYSTICK);\n\t\t\tSetControllerKeyAssociatedWithAction(PED_SNIPER_ZOOM_IN,                 4, JOYSTICK);\n\t\tIF_BTN_IN_RANGE(3)\n\t\t\tSetControllerKeyAssociatedWithAction(VEHICLE_ACCELERATE,                 3, JOYSTICK);\n\t\t\tSetControllerKeyAssociatedWithAction(PED_SPRINT,                         3, JOYSTICK);\n\t\t\tSetControllerKeyAssociatedWithAction(PED_SNIPER_ZOOM_OUT,                3, JOYSTICK);\n\t\tIF_BTN_IN_RANGE(2)\n\t\t\tSetControllerKeyAssociatedWithAction(PED_FIREWEAPON,                     2, JOYSTICK);\n#ifdef BIND_VEHICLE_FIREWEAPON\t\n\t\t\tSetControllerKeyAssociatedWithAction(VEHICLE_FIREWEAPON,                 2, JOYSTICK);\n#endif\n\t\tIF_BTN_IN_RANGE(1)\n\t\t\tSetControllerKeyAssociatedWithAction(VEHICLE_ENTER_EXIT,                 1, JOYSTICK);\n\t\t/*******************************************************************************************/\n\t\t}\n\t}\n\telse\n\t{\n\t\tswitch (btn)\n\t\t{\n\t\tIF_BTN_IN_RANGE(16)\n\t\t\tSetControllerKeyAssociatedWithAction(GO_LEFT,                           16, JOYSTICK);\n\t\tIF_BTN_IN_RANGE(15)\n\t\t\tSetControllerKeyAssociatedWithAction(GO_BACK,                           15, JOYSTICK);\n\t\tIF_BTN_IN_RANGE(14)\n\t\t\tSetControllerKeyAssociatedWithAction(GO_RIGHT,                          14, JOYSTICK);\n\t\tIF_BTN_IN_RANGE(13)\n\t\t\tSetControllerKeyAssociatedWithAction(GO_FORWARD,                        13, JOYSTICK);\n\t\tIF_BTN_IN_RANGE(12)\n\t\tIF_BTN_IN_RANGE(11)\n\t\t\tSetControllerKeyAssociatedWithAction(PED_LOOKBEHIND,                    11, JOYSTICK);\n\t\t\tSetControllerKeyAssociatedWithAction(TOGGLE_SUBMISSIONS,                11, JOYSTICK);\n\t\tIF_BTN_IN_RANGE(10)\n\t\t\tSetControllerKeyAssociatedWithAction(VEHICLE_HORN,                      10, JOYSTICK);\n\t\t\tSetControllerKeyAssociatedWithAction(PED_DUCK,                          10, JOYSTICK);\n\t\tIF_BTN_IN_RANGE(9)\n\t\t\tSetControllerKeyAssociatedWithAction(CAMERA_CHANGE_VIEW_ALL_SITUATIONS,  9, JOYSTICK);\n\t\tIF_BTN_IN_RANGE(8)\n\t\t\tSetControllerKeyAssociatedWithAction(VEHICLE_HANDBRAKE,                  8, JOYSTICK);\n\t\t\tSetControllerKeyAssociatedWithAction(PED_LOCK_TARGET,                    8, JOYSTICK);\n\t\tIF_BTN_IN_RANGE(7)\n\t\t\tSetControllerKeyAssociatedWithAction(PED_ANSWER_PHONE,                   7, JOYSTICK);\n\t\t\tSetControllerKeyAssociatedWithAction(VEHICLE_CHANGE_RADIO_STATION,       7, JOYSTICK);\n\t\tIF_BTN_IN_RANGE(6)\n\t\t\tSetControllerKeyAssociatedWithAction(PED_CYCLE_WEAPON_RIGHT,             6, JOYSTICK);\n\t\t\tSetControllerKeyAssociatedWithAction(VEHICLE_LOOKRIGHT,                  6, JOYSTICK);\n\t\tIF_BTN_IN_RANGE(5)\n\t\t\tSetControllerKeyAssociatedWithAction(PED_CYCLE_WEAPON_LEFT,              5, JOYSTICK);\n\t\t\tSetControllerKeyAssociatedWithAction(VEHICLE_LOOKLEFT,                   5, JOYSTICK);\n\t\t/*******************************************************************************************/\n\t\tIF_BTN_IN_RANGE(4)\n\t\t\tSetControllerKeyAssociatedWithAction(VEHICLE_ENTER_EXIT,                 4, JOYSTICK);\n\t\tIF_BTN_IN_RANGE(3)\n\t\t\tSetControllerKeyAssociatedWithAction(VEHICLE_BRAKE,                      3, JOYSTICK);\n\t\t\tSetControllerKeyAssociatedWithAction(PED_JUMPING,                        3, JOYSTICK);\n\t\t\tSetControllerKeyAssociatedWithAction(PED_SNIPER_ZOOM_IN,                 3, JOYSTICK);\n\t\tIF_BTN_IN_RANGE(2)\n\t\t\tSetControllerKeyAssociatedWithAction(VEHICLE_ACCELERATE,                 2, JOYSTICK);\n\t\t\tSetControllerKeyAssociatedWithAction(PED_SPRINT,                         2, JOYSTICK);\n\t\t\tSetControllerKeyAssociatedWithAction(PED_SNIPER_ZOOM_OUT,                2, JOYSTICK);\n\t\tIF_BTN_IN_RANGE(1)\n\t\t\tSetControllerKeyAssociatedWithAction(PED_FIREWEAPON,                     1, JOYSTICK);\n#ifdef BIND_VEHICLE_FIREWEAPON\n\t\t\tSetControllerKeyAssociatedWithAction(VEHICLE_FIREWEAPON,                 1, JOYSTICK);\n#endif\n\t\t/*******************************************************************************************/\n\t\t}\n\t}\n}\n\nvoid CControllerConfigManager::InitialiseControllerActionNameArray()\n{\n\twchar buf[ACTIONNAME_LENGTH + 2];\n\n#define SETACTIONNAME(name) AsciiToUnicode(#name, buf); CMessages::WideStringCopy(m_aActionNames[name], buf, ACTIONNAME_LENGTH);\n\n\tSETACTIONNAME(PED_LOOKBEHIND);\n\tSETACTIONNAME(PED_CYCLE_WEAPON_LEFT);\n\tSETACTIONNAME(PED_CYCLE_WEAPON_RIGHT);\n\tSETACTIONNAME(PED_LOCK_TARGET);\n\tSETACTIONNAME(PED_JUMPING);\n\tSETACTIONNAME(PED_SPRINT);\n\tSETACTIONNAME(PED_CYCLE_TARGET_LEFT);\n\tSETACTIONNAME(PED_CYCLE_TARGET_RIGHT);\n\tSETACTIONNAME(PED_LOCK_TARGET); // duplicate\n\tSETACTIONNAME(PED_CENTER_CAMERA_BEHIND_PLAYER);\n\tSETACTIONNAME(VEHICLE_LOOKBEHIND);\n\tSETACTIONNAME(PED_DUCK);\n\tSETACTIONNAME(PED_ANSWER_PHONE);\n\tSETACTIONNAME(VEHICLE_LOOKLEFT);\n\tSETACTIONNAME(VEHICLE_LOOKRIGHT);\n\tSETACTIONNAME(VEHICLE_HORN);\n\tSETACTIONNAME(VEHICLE_HANDBRAKE);\n\tSETACTIONNAME(VEHICLE_ACCELERATE);\n\tSETACTIONNAME(VEHICLE_BRAKE);\n\tSETACTIONNAME(VEHICLE_CHANGE_RADIO_STATION);\n\tSETACTIONNAME(TOGGLE_SUBMISSIONS);\n\tSETACTIONNAME(PED_SNIPER_ZOOM_IN);\n\tSETACTIONNAME(PED_SNIPER_ZOOM_OUT);\n\tSETACTIONNAME(PED_1RST_PERSON_LOOK_LEFT);\n\tSETACTIONNAME(PED_1RST_PERSON_LOOK_RIGHT);\n\tSETACTIONNAME(PED_1RST_PERSON_LOOK_UP);\n\tSETACTIONNAME(PED_1RST_PERSON_LOOK_DOWN);\n\tSETACTIONNAME(SHOW_MOUSE_POINTER_TOGGLE);\n\tSETACTIONNAME(CAMERA_CHANGE_VIEW_ALL_SITUATIONS);\n\tSETACTIONNAME(PED_FIREWEAPON);\n#ifdef BIND_VEHICLE_FIREWEAPON\n\tSETACTIONNAME(VEHICLE_FIREWEAPON);\n#endif\n\tSETACTIONNAME(VEHICLE_ENTER_EXIT);\n\tSETACTIONNAME(GO_LEFT);\n\tSETACTIONNAME(GO_RIGHT);\n\tSETACTIONNAME(GO_FORWARD);\n\tSETACTIONNAME(GO_BACK);\n\tSETACTIONNAME(VEHICLE_TURRETLEFT);\n\tSETACTIONNAME(VEHICLE_TURRETRIGHT);\n\tSETACTIONNAME(VEHICLE_TURRETUP);\n\tSETACTIONNAME(VEHICLE_TURRETDOWN);\n\tSETACTIONNAME(NETWORK_TALK);\n\tSETACTIONNAME(TOGGLE_DPAD);\n\tSETACTIONNAME(SWITCH_DEBUG_CAM_ON);\n\tSETACTIONNAME(TAKE_SCREEN_SHOT);\n\n#undef SETACTIONNAME\n}\n\nvoid CControllerConfigManager::UpdateJoyInConfigMenus_ButtonDown(int32 button, int32 padnumber)\n{\n\tif (button != 0)\n\t{\n\t\tCPad *pad = CPad::GetPad(padnumber);\n\t\tif (pad != NULL)\n\t\t{\n\t\t\tswitch (button)\n\t\t\t{\n\t\t\tcase 16:\n\t\t\t\tpad->PCTempJoyState.DPadLeft = 255;\n\t\t\t\tbreak;\n\t\t\tcase 15:\n\t\t\t\tpad->PCTempJoyState.DPadDown = 255;\n\t\t\t\tbreak;\n\t\t\tcase 14:\n\t\t\t\tpad->PCTempJoyState.DPadRight = 255;\n\t\t\t\tbreak;\n\t\t\tcase 13:\n\t\t\t\tpad->PCTempJoyState.DPadUp = 255;\n\t\t\t\tbreak;\n\t\t\tcase 12:\n#ifndef REGISTER_START_BUTTON\n\t\t\t\tif (padnumber == 1)\n#endif\n\t\t\t\t\tpad->PCTempJoyState.Start = 255;\n\t\t\t\tbreak;\n\t\t\tcase 11:\n\t\t\t\tpad->PCTempJoyState.RightShock = 255;\n\t\t\t\tbreak;\n\t\t\tcase 10:\n\t\t\t\tpad->PCTempJoyState.LeftShock = 255;\n\t\t\t\tbreak;\n\t\t\tcase 9:\n\t\t\t\tpad->PCTempJoyState.Select = 255;\n\t\t\t\tbreak;\n\t\t\tcase 8:\n\t\t\t\tpad->PCTempJoyState.RightShoulder1 = 255;\n\t\t\t\tbreak;\n\t\t\tcase 7:\n\t\t\t\tpad->PCTempJoyState.LeftShoulder1 = 255;\n\t\t\t\tbreak;\n\t\t\tcase 6:\n\t\t\t\tpad->PCTempJoyState.RightShoulder2 = 255;\n\t\t\t\tbreak;\n\t\t\tcase 5:\n\t\t\t\tpad->PCTempJoyState.LeftShoulder2 = 255;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t// Now we use SDL Game Controller DB\n#if defined RW_D3D9 || defined RWLIBS\n\t\t\tif (AllValidWinJoys.m_aJoys[JOYSTICK1].m_nVendorID == 0x3427\n\t\t\t\t&& AllValidWinJoys.m_aJoys[JOYSTICK1].m_nProductID == 0x1190)\n#else\n\t\t\tif (0)\n#endif\n\t\t\t{\n\t\t\t\t//GIC USB Joystick, PS2 Gamepad ?\n\n\t\t\t\tswitch (button)\n\t\t\t\t{\n\t\t\t\tcase 4:\n\t\t\t\t\tpad->PCTempJoyState.Square = 255;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 3:\n\t\t\t\t\tpad->PCTempJoyState.Cross = 255;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 2:\n\t\t\t\t\tpad->PCTempJoyState.Circle = 255;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 1:\n\t\t\t\t\tpad->PCTempJoyState.Triangle = 255;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tswitch (button)\n\t\t\t\t{\n\t\t\t\tcase 4:\n\t\t\t\t\tpad->PCTempJoyState.Triangle = 255;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 3:\n\t\t\t\t\tpad->PCTempJoyState.Square = 255;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 2:\n\t\t\t\t\tpad->PCTempJoyState.Cross = 255;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 1:\n\t\t\t\t\tpad->PCTempJoyState.Circle = 255;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid CControllerConfigManager::AffectControllerStateOn_ButtonDown(int32 button, eControllerType type)\n{\n\tbool process = true;\n\t\n\tif ((type == KEYBOARD || type == OPTIONAL_EXTRA) && button == rsNULL)\n\t\tprocess = false;\n\tif (type == JOYSTICK && button == 0)\n\t\tprocess = false;\n\tif (type == MOUSE && button == 0)\n\t\tprocess = false;\n\n\tif (process)\n\t{\n\t\tCPad *pad = CPad::GetPad(PAD1);\n\n\t\tbool firstPerson = false;\n\t\tbool playerDriving = false;\n\n\t\tif (FindPlayerVehicle() != NULL)\n\t\t{\n\t\t\tCPlayerPed *plr = FindPlayerPed();\n\t\t\tif (plr != NULL)\n\t\t\t{\n\t\t\t\tif (plr->m_nPedState == PED_DRIVING)\n\t\t\t\t\tplayerDriving = true;\n\t\t\t}\n\t\t}\n\n\t\tint16 mode = TheCamera.Cams[TheCamera.ActiveCam].Mode;\n\t\tif (   mode == CCam::MODE_1STPERSON\n\t\t\t|| mode == CCam::MODE_SNIPER\n\t\t\t|| mode == CCam::MODE_ROCKETLAUNCHER\n\t\t\t|| mode == CCam::MODE_CAMERA\n\t\t\t|| mode == CCam::MODE_M16_1STPERSON)\n\t\t{\n\t\t\tfirstPerson = true;\n\t\t}\n\n\t\tCControllerState *state;\n\t\t\n\t\tswitch (type)\n\t\t{\n\t\tcase KEYBOARD:\n\t\tcase OPTIONAL_EXTRA:\n\t\t\tstate = &CPad::GetPad(PAD1)->PCTempKeyState;\n\t\t\tbreak;\n\t\tcase JOYSTICK:\n\t\t\tstate = &CPad::GetPad(PAD1)->PCTempJoyState;\n\t\t\tbreak;\n\t\tcase MOUSE:\n\t\t\tstate = &CPad::GetPad(PAD1)->PCTempMouseState;\n\t\t\tbreak;\n\t\tdefault: break;\n\t\t}\n\n\t\tif (pad != NULL)\n\t\t{\n\t\t\tif (playerDriving)\n\t\t\t{\n\t\t\t\tAffectControllerStateOn_ButtonDown_Driving(button, type, *state);\n\t\t\t\tAffectControllerStateOn_ButtonDown_VehicleAndThirdPersonOnly(button, type, *state);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tAffectControllerStateOn_ButtonDown_FirstAndThirdPersonOnly(button, type, *state);\n\t\t\t\tif (firstPerson)\n\t\t\t\t\tAffectControllerStateOn_ButtonDown_FirstPersonOnly(button, type, *state);\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tAffectControllerStateOn_ButtonDown_ThirdPersonOnly(button, type, *state);\n\t\t\t\t\tAffectControllerStateOn_ButtonDown_VehicleAndThirdPersonOnly(button, type, *state);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tAffectControllerStateOn_ButtonDown_AllStates(button, type, *state);\n\n#ifdef REGISTER_START_BUTTON\n\t\t\tif (button == 12)\n\t\t\t\tstate->Start = 255;\n#endif\n\t\t}\n\t}\n}\n\nvoid CControllerConfigManager::AffectControllerStateOn_ButtonDown_Driving(int32 button, eControllerType type, CControllerState &state)\n{\n#ifdef BIND_VEHICLE_FIREWEAPON\n\tif (button == GetControllerKeyAssociatedWithAction(VEHICLE_FIREWEAPON, type))\n\t\tstate.Circle = 255;\n#endif\n\tif (button == GetControllerKeyAssociatedWithAction(VEHICLE_LOOKBEHIND, type))\n\t{\n\t\tstate.LeftShoulder2 = 255;\n\t\tstate.RightShoulder2 = 255;\n\t}\n\n\tif (button == GetControllerKeyAssociatedWithAction(VEHICLE_LOOKLEFT, type))\n\t\tstate.LeftShoulder2 = 255;\n\tif (button == GetControllerKeyAssociatedWithAction(VEHICLE_LOOKRIGHT, type))\n\t\tstate.RightShoulder2 = 255;\n\tif (button == GetControllerKeyAssociatedWithAction(VEHICLE_HORN, type))\n\t\tstate.LeftShock = 255;\n\tif (button == GetControllerKeyAssociatedWithAction(VEHICLE_HANDBRAKE, type))\n\t\tstate.RightShoulder1 = 255;\n\tif (button == GetControllerKeyAssociatedWithAction(VEHICLE_ACCELERATE, type))\n\t\tstate.Cross = 255;\n\tif (button == GetControllerKeyAssociatedWithAction(VEHICLE_CHANGE_RADIO_STATION, type))\n\t\tstate.LeftShoulder1 = 255;\n\tif (button == GetControllerKeyAssociatedWithAction(VEHICLE_BRAKE, type))\n\t\tstate.Square = 255;\n\tif (button == GetControllerKeyAssociatedWithAction(TOGGLE_SUBMISSIONS, type))\n\t\tstate.RightShock = 255;\n\t\n\tif (button == GetControllerKeyAssociatedWithAction(VEHICLE_TURRETLEFT, type))\n\t{\n\t\tif (state.RightStickX == 128 || m_aSimCheckers[SIM_X2][type])\n\t\t{\n\t\t\tstate.RightStickX = 0;\n\t\t\tm_aSimCheckers[SIM_X2][type] = true;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tstate.RightStickX = -128;\n\t\t}\n\t}\n\n\tif (button == GetControllerKeyAssociatedWithAction(VEHICLE_TURRETRIGHT, type))\n\t{\n\t\tif (state.RightStickX == -128 || m_aSimCheckers[SIM_X2][type])\n\t\t{\n\t\t\tstate.RightStickX = 0;\n\t\t\tm_aSimCheckers[SIM_X2][type] = true;\n\t\t}\n\t\telse\n\t\t\tstate.RightStickX = 128;\n\t}\n\t\n\tbool isDodo = false;\n\tif (FindPlayerVehicle() && (FindPlayerVehicle()->IsVehicle() && (\n\t\tFindPlayerVehicle()->GetModelIndex() == MI_DODO\n#ifdef FIX_BUGS\n\t\t|| (CVehicle::bAllDodosCheat && !FindPlayerVehicle()->IsRealHeli())\n#endif\n\t\t)))\n\t{\n\t\tisDodo = true;\n\t}\n\n\t\n\tif (button == GetControllerKeyAssociatedWithAction(VEHICLE_TURRETUP, type))\n\t{\n\t\tif (isDodo == true)\n\t\t{\n\t\t\tif (state.LeftStickY == -128 || m_aSimCheckers[SIM_Y1][type]) // BUG: should be SIM_Y2. SIM_Y1 it's DPAD\n\t\t\t{\n\t\t\t\tstate.LeftStickY = 0;\n\t\t\t\tm_aSimCheckers[SIM_Y2][type] = true;\n\t\t\t}\n\t\t\telse\n\t\t\t\tstate.LeftStickY = 128;\n\t\t}\n\n\t\telse if (state.RightStickY == -128 || m_aSimCheckers[SIM_Y2][type])\n\t\t{\n\t\t\tstate.RightStickY = 0;\n\t\t\tm_aSimCheckers[SIM_Y2][type] = true;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tstate.RightStickY = 128;\n\t\t}\n\t}\n\t\n\tif (button == GetControllerKeyAssociatedWithAction(VEHICLE_TURRETDOWN, type))\n\t{\n\t\tif (isDodo == true)\n\t\t{\n\t\t\tif (state.LeftStickY == 128 || m_aSimCheckers[SIM_Y1][type]) // BUG: should be SIM_Y2. SIM_Y1 it's DPAD\n\t\t\t{\n\t\t\t\tstate.LeftStickY = 0;\n\t\t\t\tm_aSimCheckers[SIM_Y2][type] = true;\n\t\t\t}\n\t\t\telse\n\t\t\t\tstate.LeftStickY = -128;\n\t\t}\n\n\t\telse if (state.RightStickY == 128 || m_aSimCheckers[SIM_Y2][type])\n\t\t{\n\t\t\tstate.RightStickY = 0;\n\t\t\tm_aSimCheckers[SIM_Y2][type] = true;\n\t\t}\n\t\telse\n\t\t\tstate.RightStickY = -128;\n\t}\n}\n\nvoid CControllerConfigManager::AffectControllerStateOn_ButtonDown_FirstPersonOnly(int32 button, eControllerType type, CControllerState &state)\n{\n\tif (button == GetControllerKeyAssociatedWithAction(PED_SNIPER_ZOOM_IN, type))\n\t\tstate.Square = 255;\n\tif (button == GetControllerKeyAssociatedWithAction(PED_SNIPER_ZOOM_OUT, type))\n\t\tstate.Cross = 255;\n\tif (button == GetControllerKeyAssociatedWithAction(PED_DUCK, type))\n\t\tstate.LeftShock = 255;\n}\n\nvoid CControllerConfigManager::AffectControllerStateOn_ButtonDown_ThirdPersonOnly(int32 button, eControllerType type, CControllerState &state)\n{\n\tif (button == GetControllerKeyAssociatedWithAction(PED_LOOKBEHIND, type))\n\t\tstate.RightShock = 255;\n\tif (button == GetControllerKeyAssociatedWithAction(PED_JUMPING, type))\n\t\tstate.Square = 255;\n\tif (button == GetControllerKeyAssociatedWithAction(PED_ANSWER_PHONE, type))\n\t\tstate.LeftShoulder1 = 255;\n\tif (button == GetControllerKeyAssociatedWithAction(PED_CYCLE_WEAPON_LEFT, type))\n\t\tstate.LeftShoulder2 = 255;\n\tif (button == GetControllerKeyAssociatedWithAction(PED_CYCLE_WEAPON_RIGHT, type))\n\t\tstate.RightShoulder2 = 255;\n\tif (button == GetControllerKeyAssociatedWithAction(PED_SPRINT, type))\n\t\tstate.Cross = 255;\n\tif (button == GetControllerKeyAssociatedWithAction(PED_DUCK, type))\n\t\tstate.LeftShock = 255;\n\t\n\tif (FrontEndMenuManager.m_ControlMethod == CONTROL_CLASSIC)\n\t{\n\t\tif (button == GetControllerKeyAssociatedWithAction(PED_CYCLE_TARGET_LEFT, type))\n\t\t\tstate.LeftShoulder2 = 255;\n\t\tif (button == GetControllerKeyAssociatedWithAction(PED_CYCLE_TARGET_RIGHT, type))\n\t\t\tstate.RightShoulder2 = 255;\n\t\tif (button == GetControllerKeyAssociatedWithAction(PED_CENTER_CAMERA_BEHIND_PLAYER, type))\n\t\t\tstate.LeftShoulder1 = 255;\n\t}\n}\n\nvoid CControllerConfigManager::AffectControllerStateOn_ButtonDown_FirstAndThirdPersonOnly(int32 button, eControllerType type, CControllerState &state)\n{\n\tCPad *pad = CPad::GetPad(PAD1);\n\n#ifdef BIND_VEHICLE_FIREWEAPON\n\tif (button == GetControllerKeyAssociatedWithAction(PED_FIREWEAPON, type))\n\t\tstate.Circle = 255;\n#endif\n\tif (button == GetControllerKeyAssociatedWithAction(PED_LOCK_TARGET, type))\n\t\tstate.RightShoulder1 = 255;\n\n\tif (button == GetControllerKeyAssociatedWithAction(GO_FORWARD, type))\n\t{\n\t\tif (state.DPadDown || m_aSimCheckers[SIM_Y1][type])\n\t\t{\n\t\t\tm_aSimCheckers[SIM_Y1][type] = true;\n\t\t\tstate.DPadDown = 0;\n\t\t\tstate.DPadUp = 0;\n\t\t}\n\t\telse\n\t\t\tstate.DPadUp = 255;\n\t}\n\n\tif (button == GetControllerKeyAssociatedWithAction(GO_BACK, type))\n\t{\n\t\tif (state.DPadUp || m_aSimCheckers[SIM_Y1][type])\n\t\t{\n\t\t\tm_aSimCheckers[SIM_Y1][type] = true;\n\t\t\tstate.DPadDown = 0;\n\t\t\tstate.DPadUp = 0;\n\t\t}\n\t\telse\n\t\t\tstate.DPadDown = 255;\n\t}\n\n\tif (button == GetControllerKeyAssociatedWithAction(PED_1RST_PERSON_LOOK_LEFT, type))\n\t{\n\t\tif (state.RightStickX == 128 || m_aSimCheckers[SIM_X2][type])\n\t\t{\n\t\t\tstate.RightStickX = 0;\n\t\t\tm_aSimCheckers[SIM_X2][type] = true;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tstate.RightStickX = -128;\n\t\t}\n\t}\n\n\tif (button == GetControllerKeyAssociatedWithAction(PED_1RST_PERSON_LOOK_RIGHT, type))\n\t{\n\t\tif (state.RightStickX == -128 || m_aSimCheckers[SIM_X2][type])\n\t\t{\n\t\t\tstate.RightStickX = 0;\n\t\t\tm_aSimCheckers[SIM_X2][type] = true;\n\t\t}\n\t\telse\n\t\t\tstate.RightStickX = 128;\n\t}\n\n\tif (FrontEndMenuManager.m_ControlMethod == CONTROL_CLASSIC)\n\t{\n\t\tif (button == GetControllerKeyAssociatedWithAction(PED_1RST_PERSON_LOOK_UP, type))\n\t\t{\n\t\t\tif (state.RightStickY == -128 || m_aSimCheckers[SIM_Y2][type])\n\t\t\t{\n\t\t\t\tstate.RightStickY = 0;\n\t\t\t\tm_aSimCheckers[SIM_Y2][type] = true;\n\t\t\t}\n\t\t\telse\n\t\t\t\tstate.RightStickY = 128;\n\t\t}\n\n\t\tif (button == GetControllerKeyAssociatedWithAction(PED_1RST_PERSON_LOOK_DOWN, type))\n\t\t{\n\t\t\tif (state.RightStickY == 128 || m_aSimCheckers[SIM_Y2][type])\n\t\t\t{\n\t\t\t\tstate.RightStickY = 0;\n\t\t\t\tm_aSimCheckers[SIM_Y2][type] = true;\n\t\t\t}\n\t\t\telse\n\t\t\t\tstate.RightStickY = -128;\n\t\t}\n\t}\n}\n\nvoid CControllerConfigManager::AffectControllerStateOn_ButtonDown_AllStates(int32 button, eControllerType type, CControllerState &state)\n{\n\tif (button == GetControllerKeyAssociatedWithAction(CAMERA_CHANGE_VIEW_ALL_SITUATIONS, type))\n\t\tstate.Select = 255;\n\n#ifndef BIND_VEHICLE_FIREWEAPON\n\tif (button == GetControllerKeyAssociatedWithAction(PED_FIREWEAPON, type))\n\t\tstate.Circle = 255;\n#endif\n\n\tif (button == GetControllerKeyAssociatedWithAction(GO_LEFT, type))\n\t{\n\t\tif (state.DPadRight || m_aSimCheckers[SIM_X1][type])\n\t\t{\n\t\t\tm_aSimCheckers[SIM_X1][type] = true;\n\t\t\tstate.DPadLeft = 0;\n\t\t\tstate.DPadRight = 0;\n\t\t}\n\t\telse\n\t\t\tstate.DPadLeft = 255;\n\t}\n\n\tif (button == GetControllerKeyAssociatedWithAction(GO_RIGHT, type))\n\t{\n\t\tif (state.DPadLeft || m_aSimCheckers[SIM_X1][type])\n\t\t{\n\t\t\tm_aSimCheckers[SIM_X1][type] = true;\n\t\t\tstate.DPadLeft = 0;\n\t\t\tstate.DPadRight = 0;\n\t\t}\n\t\telse\n\t\t\tstate.DPadRight = 255;\n\t}\n\n\tif (button == GetControllerKeyAssociatedWithAction(NETWORK_TALK, type))\n\t\tstate.NetworkTalk = 255;\n}\n\nvoid CControllerConfigManager::AffectControllerStateOn_ButtonDown_VehicleAndThirdPersonOnly(int32 button, eControllerType type, CControllerState &state)\n{\n\tif (button == GetControllerKeyAssociatedWithAction(VEHICLE_ENTER_EXIT, type))\n\t\tstate.Triangle = 255;\n}\n\nvoid CControllerConfigManager::UpdateJoyInConfigMenus_ButtonUp(int32 button, int32 padnumber)\n{\n\tif (button!=0)\n\t{\n\t\tCPad *pad = CPad::GetPad(padnumber);\n\n\t\tif (pad != NULL)\n\t\t{\n\t\t\tswitch (button)\n\t\t\t{\n\t\t\tcase 16:\n\t\t\t\tpad->PCTempJoyState.DPadLeft = 0;\n\t\t\t\tbreak;\n\t\t\tcase 15:\n\t\t\t\tpad->PCTempJoyState.DPadDown = 0;\n\t\t\t\tbreak;\n\t\t\tcase 14:\n\t\t\t\tpad->PCTempJoyState.DPadRight = 0;\n\t\t\t\tbreak;\n\t\t\tcase 13:\n\t\t\t\tpad->PCTempJoyState.DPadUp = 0;\n\t\t\t\tbreak;\n#ifdef REGISTER_START_BUTTON\n\t\t\tcase 12:\n\t\t\t\tpad->PCTempJoyState.Start = 0;\n\t\t\t\tbreak;\n#endif\n\t\t\tcase 11:\n\t\t\t\tpad->PCTempJoyState.RightShock = 0;\n\t\t\t\tbreak;\n\t\t\tcase 10:\n\t\t\t\tpad->PCTempJoyState.LeftShock = 0;\n\t\t\t\tbreak;\n\t\t\tcase 9:\n\t\t\t\tpad->PCTempJoyState.Select = 0;\n\t\t\t\tbreak;\n\t\t\tcase 8:\n\t\t\t\tpad->PCTempJoyState.RightShoulder1 = 0;\n\t\t\t\tbreak;\n\t\t\tcase 7:\n\t\t\t\tpad->PCTempJoyState.LeftShoulder1 = 0;\n\t\t\t\tbreak;\n\t\t\tcase 6:\n\t\t\t\tpad->PCTempJoyState.RightShoulder2 = 0;\n\t\t\t\tbreak;\n\t\t\tcase 5:\n\t\t\t\tpad->PCTempJoyState.LeftShoulder2 = 0;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t// Now we use SDL Game Controller DB\n#if defined RW_D3D9 || defined RWLIBS\n\t\t\tif (AllValidWinJoys.m_aJoys[JOYSTICK1].m_nVendorID == 0x3427\n\t\t\t\t&& AllValidWinJoys.m_aJoys[JOYSTICK1].m_nProductID == 0x1190)\n#else\n\t\t\tif (0)\n#endif\n\t\t\t{\n\t\t\t\t//GIC USB Joystick, PS2 Gamepad ?\n\n\t\t\t\tswitch (button)\n\t\t\t\t{\n\t\t\t\tcase 4:\n\t\t\t\t\tpad->PCTempJoyState.Square = 0;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 3:\n\t\t\t\t\tpad->PCTempJoyState.Cross = 0;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 2:\n\t\t\t\t\tpad->PCTempJoyState.Circle = 0;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 1:\n\t\t\t\t\tpad->PCTempJoyState.Triangle = 0;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tswitch (button)\n\t\t\t\t{\n\t\t\t\tcase 4:\n\t\t\t\t\tpad->PCTempJoyState.Triangle = 0;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 3:\n\t\t\t\t\tpad->PCTempJoyState.Square = 0;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 2:\n\t\t\t\t\tpad->PCTempJoyState.Cross = 0;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 1:\n\t\t\t\t\tpad->PCTempJoyState.Circle = 0;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid CControllerConfigManager::AffectControllerStateOn_ButtonUp(int32 button, eControllerType type)\n{\n\tbool process = true;\n\n\tif ((type == KEYBOARD || type == OPTIONAL_EXTRA) && button == rsNULL)\n\t\tprocess = false;\n\tif (type == JOYSTICK && button == 0)\n\t\tprocess = false;\n\tif (type == MOUSE && button == 0)\n\t\tprocess = false;\n\n\tCControllerState *state;\n\n\tswitch (type)\n\t{\n\tcase KEYBOARD:\n\tcase OPTIONAL_EXTRA:\n\t\tstate = &CPad::GetPad(PAD1)->PCTempKeyState;\n\t\tbreak;\n\tcase MOUSE:\n\t\tstate = &CPad::GetPad(PAD1)->PCTempMouseState;\n\t\tbreak;\n\tcase JOYSTICK:\n\t\tstate = &CPad::GetPad(PAD1)->PCTempJoyState;\n\t\tbreak;\n\tdefault: break;\n\t}\n\n\tif (process)\n\t{\n\t\tCPad *pad = CPad::GetPad(PAD1);\n\t\t\n\t\tif (pad != NULL)\n\t\t{\n\t\t\tif (FrontEndMenuManager.GetIsMenuActive())\n\t\t\t\tAffectControllerStateOn_ButtonUp_All_Player_States(button, type, *state);\n\n#ifdef REGISTER_START_BUTTON\n\t\t\tif (button == 12)\n\t\t\t\tstate->Start = 0;\n#endif\n\t\t}\n\t}\n}\n\nvoid CControllerConfigManager::AffectControllerStateOn_ButtonUp_All_Player_States(int32 button, eControllerType type, CControllerState &state)\n{\n\tif (button == GetControllerKeyAssociatedWithAction(NETWORK_TALK, type))\n\t\tstate.NetworkTalk = 0;\n}\n\nvoid CControllerConfigManager::AffectPadFromKeyBoard()\n{\n\tRsKeyCodes kc;\n\t_InputTranslateShiftKeyUpDown(&kc);\n\n\tbool processdown = false;\n\tif (!CPad::m_bMapPadOneToPadTwo && !FrontEndMenuManager.GetIsMenuActive())\n\t\tprocessdown = true;\n\t\n\tfor (int32 i = 0; i < MAX_CONTROLLERACTIONS; i++)\n\t{\n\t\tint32 key = GetControllerKeyAssociatedWithAction((e_ControllerAction)i, KEYBOARD);\n\t\tif (GetIsKeyboardKeyDown((RsKeyCodes)key) && processdown)\n\t\t\tAffectControllerStateOn_ButtonDown(key, KEYBOARD);\n\n\t\tint32 extrakey = GetControllerKeyAssociatedWithAction((e_ControllerAction)i, OPTIONAL_EXTRA);\n\t\tif (GetIsKeyboardKeyDown((RsKeyCodes)extrakey) && processdown)\n\t\t\tAffectControllerStateOn_ButtonDown(extrakey, OPTIONAL_EXTRA);\n\n\t\tif (!GetIsKeyboardKeyDown((RsKeyCodes)key))\n\t\t\tAffectControllerStateOn_ButtonUp(key, KEYBOARD);\n\t\telse if ( !GetIsKeyboardKeyDown((RsKeyCodes)extrakey))\n\t\t\tAffectControllerStateOn_ButtonUp(key, OPTIONAL_EXTRA);\n\t}\n}\n\nvoid CControllerConfigManager::AffectPadFromMouse()\n{\n\tbool processdown = false;\n\tif (!CPad::m_bMapPadOneToPadTwo && !FrontEndMenuManager.GetIsMenuActive())\n\t\tprocessdown = true;\n\t\n\tfor (int32 i = 0; i < MAX_CONTROLLERACTIONS; i++)\n\t{\n\t\tint32 button = GetControllerKeyAssociatedWithAction((e_ControllerAction)i, MOUSE);\n\t\tif (GetIsMouseButtonDown((RsKeyCodes)button) && processdown)\n\t\t\tAffectControllerStateOn_ButtonDown(button, MOUSE);\n\t\tif (GetIsMouseButtonUp((RsKeyCodes)button))\n\t\t\tAffectControllerStateOn_ButtonUp(button, MOUSE);\n\t}\n}\n\nvoid CControllerConfigManager::ClearSimButtonPressCheckers()\n{\n\tfor (int32 i = 0; i < MAX_SIMS; i++)\n\t{\n\t\tm_aSimCheckers[i][KEYBOARD]       = false;\n\t\tm_aSimCheckers[i][OPTIONAL_EXTRA] = false;\n\t\tm_aSimCheckers[i][MOUSE]          = false;\n\t\tm_aSimCheckers[i][JOYSTICK]       = false;\n\t}\n}\n\nbool CControllerConfigManager::GetIsKeyboardKeyDown(RsKeyCodes keycode)\n{\n\tif (keycode < 255)\n\t{\n\t\tif (CPad::GetPad(PAD1)->GetChar(keycode))\n\t\t\treturn true;\n\t}\n\n\tfor (int32 i = 0; i < 12; i++)\n\t{\n\t\tif (i + rsF1 == keycode)\n\t\t{\n\t\t\tif (CPad::GetPad(PAD1)->GetF(i))\n\t\t\t\treturn true;\n\t\t}\n\t}\n\n\tswitch (keycode)\n\t{\n\tcase rsESC:\n\t\tif (CPad::GetPad(PAD1)->GetEscape())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsINS:\n\t\tif (CPad::GetPad(PAD1)->GetInsert())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsDEL:\n\t\tif (CPad::GetPad(PAD1)->GetDelete())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsHOME:\n\t\tif (CPad::GetPad(PAD1)->GetHome())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsEND:\n\t\tif (CPad::GetPad(PAD1)->GetEnd())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsPGUP:\n\t\tif (CPad::GetPad(PAD1)->GetPageUp())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsPGDN:\n\t\tif (CPad::GetPad(PAD1)->GetPageDown())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsUP:\n\t\tif (CPad::GetPad(PAD1)->GetUp())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsDOWN:\n\t\tif (CPad::GetPad(PAD1)->GetDown())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsLEFT:\n\t\tif (CPad::GetPad(PAD1)->GetLeft())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsRIGHT:\n\t\tif (CPad::GetPad(PAD1)->GetRight())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsSCROLL:\n\t\tif (CPad::GetPad(PAD1)->GetScrollLock())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsPAUSE:\n\t\tif (CPad::GetPad(PAD1)->GetPause())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsNUMLOCK:\n\t\tif (CPad::GetPad(PAD1)->GetNumLock())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsDIVIDE:\n\t\tif (CPad::GetPad(PAD1)->GetDivide())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsTIMES:\n\t\tif (CPad::GetPad(PAD1)->GetTimes())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsMINUS:\n\t\tif (CPad::GetPad(PAD1)->GetMinus())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsPLUS:\n\t\tif (CPad::GetPad(PAD1)->GetPlus())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsPADENTER:\n\t\tif (CPad::GetPad(PAD1)->GetPadEnter())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsPADDEL:\n\t\tif (CPad::GetPad(PAD1)->GetPadDel())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsPADEND:\n\t\tif (CPad::GetPad(PAD1)->GetPad1())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsPADDOWN:\n\t\tif (CPad::GetPad(PAD1)->GetPad2())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsPADPGDN:\n\t\tif (CPad::GetPad(PAD1)->GetPad3())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsPADLEFT:\n\t\tif (CPad::GetPad(PAD1)->GetPad4())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsPAD5:\n\t\tif (CPad::GetPad(PAD1)->GetPad5())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsPADRIGHT:\n\t\tif (CPad::GetPad(PAD1)->GetPad6())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsPADHOME:\n\t\tif (CPad::GetPad(PAD1)->GetPad7())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsPADUP:\n\t\tif (CPad::GetPad(PAD1)->GetPad8())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsPADPGUP:\n\t\tif (CPad::GetPad(PAD1)->GetPad9())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsPADINS:\n\t\tif (CPad::GetPad(PAD1)->GetPad0())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsBACKSP:\n\t\tif (CPad::GetPad(PAD1)->GetBackspace())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsTAB:\n\t\tif (CPad::GetPad(PAD1)->GetTab())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsCAPSLK:\n\t\tif (CPad::GetPad(PAD1)->GetCapsLock())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsENTER:\n\t\tif (CPad::GetPad(PAD1)->GetEnter())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsLSHIFT:\n\t\tif (CPad::GetPad(PAD1)->GetLeftShift())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsSHIFT:\n\t\tif (CPad::GetPad(PAD1)->GetShift())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsRSHIFT:\n\t\tif (CPad::GetPad(PAD1)->GetRightShift())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsLCTRL:\n\t\tif (CPad::GetPad(PAD1)->GetLeftCtrl())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsRCTRL:\n\t\tif (CPad::GetPad(PAD1)->GetRightCtrl())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsLALT:\n\t\tif (CPad::GetPad(PAD1)->GetLeftAlt())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsRALT:\n\t\tif (CPad::GetPad(PAD1)->GetRightAlt())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsLWIN:\n\t\tif (CPad::GetPad(PAD1)->GetLeftWin())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsRWIN:\n\t\tif (CPad::GetPad(PAD1)->GetRightWin())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsAPPS:\n\t\tif (CPad::GetPad(PAD1)->GetApps())\n\t\t\treturn true;\n\t\tbreak;\n\tdefault: break;\n\t}\n\n\treturn false;\n}\n\nbool CControllerConfigManager::GetIsKeyboardKeyJustDown(RsKeyCodes keycode)\n{\n\tif (keycode < 255)\n\t{\n\t\tif (CPad::GetPad(PAD1)->GetCharJustDown(keycode))\n\t\t\treturn true;\n\t}\n\n\tfor (int32 i = 0; i < 12; i++)\n\t{\n\t\tif (i + rsF1 == keycode)\n\t\t{\n\t\t\tif (CPad::GetPad(PAD1)->GetFJustDown(i))\n\t\t\t\treturn true;\n\t\t}\n\t}\n\n\tswitch (keycode)\n\t{\n\tcase rsESC:\n\t\tif (CPad::GetPad(PAD1)->GetEscapeJustDown())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsINS:\n\t\tif (CPad::GetPad(PAD1)->GetInsertJustDown())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsDEL:\n\t\tif (CPad::GetPad(PAD1)->GetDeleteJustDown())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsHOME:\n\t\tif (CPad::GetPad(PAD1)->GetHomeJustDown())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsEND:\n\t\tif (CPad::GetPad(PAD1)->GetEndJustDown())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsPGUP:\n\t\tif (CPad::GetPad(PAD1)->GetPageUpJustDown())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsPGDN:\n\t\tif (CPad::GetPad(PAD1)->GetPageDownJustDown())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsUP:\n\t\tif (CPad::GetPad(PAD1)->GetUpJustDown())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsDOWN:\n\t\tif (CPad::GetPad(PAD1)->GetDownJustDown())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsLEFT:\n\t\tif (CPad::GetPad(PAD1)->GetLeftJustDown())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsRIGHT:\n\t\tif (CPad::GetPad(PAD1)->GetRightJustDown())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsSCROLL:\n\t\tif (CPad::GetPad(PAD1)->GetScrollLockJustDown())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsPAUSE:\n\t\tif (CPad::GetPad(PAD1)->GetPauseJustDown())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsNUMLOCK:\n\t\tif (CPad::GetPad(PAD1)->GetNumLockJustDown())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsDIVIDE:\n\t\tif (CPad::GetPad(PAD1)->GetDivideJustDown())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsTIMES:\n\t\tif (CPad::GetPad(PAD1)->GetTimesJustDown())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsMINUS:\n\t\tif (CPad::GetPad(PAD1)->GetMinusJustDown())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsPLUS:\n\t\tif (CPad::GetPad(PAD1)->GetPlusJustDown())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsPADENTER:\n\t\tif (CPad::GetPad(PAD1)->GetPadEnterJustDown())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsPADDEL:\n\t\tif (CPad::GetPad(PAD1)->GetPadDelJustDown())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsPADEND:\n\t\tif (CPad::GetPad(PAD1)->GetPad1JustDown())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsPADDOWN:\n\t\tif (CPad::GetPad(PAD1)->GetPad2JustDown())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsPADPGDN:\n\t\tif (CPad::GetPad(PAD1)->GetPad3JustDown())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsPADLEFT:\n\t\tif (CPad::GetPad(PAD1)->GetPad4JustDown())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsPAD5:\n\t\tif (CPad::GetPad(PAD1)->GetPad5JustDown())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsPADRIGHT:\n\t\tif (CPad::GetPad(PAD1)->GetPad6JustDown())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsPADHOME:\n\t\tif (CPad::GetPad(PAD1)->GetPad7JustDown())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsPADUP:\n\t\tif (CPad::GetPad(PAD1)->GetPad8JustDown())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsPADPGUP:\n\t\tif (CPad::GetPad(PAD1)->GetPad9JustDown())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsPADINS:\n\t\tif (CPad::GetPad(PAD1)->GetPad0JustDown())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsBACKSP:\n\t\tif (CPad::GetPad(PAD1)->GetBackspaceJustDown())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsTAB:\n\t\tif (CPad::GetPad(PAD1)->GetTabJustDown())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsCAPSLK:\n\t\tif (CPad::GetPad(PAD1)->GetCapsLockJustDown())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsENTER:\n\t\tif (CPad::GetPad(PAD1)->GetReturnJustDown())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsLSHIFT:\n\t\tif (CPad::GetPad(PAD1)->GetLeftShiftJustDown())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsSHIFT:\n\t\tif (CPad::GetPad(PAD1)->GetShiftJustDown())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsRSHIFT:\n\t\tif (CPad::GetPad(PAD1)->GetRightShiftJustDown())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsLCTRL:\n\t\tif (CPad::GetPad(PAD1)->GetLeftCtrlJustDown())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsRCTRL:\n\t\tif (CPad::GetPad(PAD1)->GetRightCtrlJustDown())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsLALT:\n\t\tif (CPad::GetPad(PAD1)->GetLeftAltJustDown())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsRALT:\n\t\tif (CPad::GetPad(PAD1)->GetRightAltJustDown())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsLWIN:\n\t\tif (CPad::GetPad(PAD1)->GetLeftWinJustDown())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsRWIN:\n\t\tif (CPad::GetPad(PAD1)->GetRightWinJustDown())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsAPPS:\n\t\tif (CPad::GetPad(PAD1)->GetAppsJustDown())\n\t\t\treturn true;\n\t\tbreak;\n\tdefault: break;\n\t}\n\n\treturn false;\n}\n\nbool CControllerConfigManager::GetIsMouseButtonDown(RsKeyCodes keycode)\n{\n\tswitch (keycode)\n\t{\n\tcase rsMOUSELEFTBUTTON:\n\t\tif (CPad::GetPad(PAD1)->GetLeftMouse())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsMOUSMIDDLEBUTTON:\n\t\tif (CPad::GetPad(PAD1)->GetMiddleMouse())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsMOUSERIGHTBUTTON:\n\t\tif (CPad::GetPad(PAD1)->GetRightMouse())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsMOUSEWHEELUPBUTTON:\n\t\tif (CPad::GetPad(PAD1)->GetMouseWheelUp())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsMOUSEWHEELDOWNBUTTON:\n\t\tif (CPad::GetPad(PAD1)->GetMouseWheelDown())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsMOUSEX1BUTTON:\n\t\tif (CPad::GetPad(PAD1)->GetMouseX1())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsMOUSEX2BUTTON:\n\t\tif (CPad::GetPad(PAD1)->GetMouseX2())\n\t\t\treturn true;\n\t\tbreak;\n\tdefault: break;\n\t}\n\n\treturn false;\n}\n\nbool CControllerConfigManager::GetIsMouseButtonUp(RsKeyCodes keycode)\n{\n\tswitch (keycode)\n\t{\n\tcase rsMOUSELEFTBUTTON:\n\t\tif (CPad::GetPad(PAD1)->GetLeftMouseUp())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsMOUSMIDDLEBUTTON:\n\t\tif (CPad::GetPad(PAD1)->GetMiddleMouseUp())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsMOUSERIGHTBUTTON:\n\t\tif (CPad::GetPad(PAD1)->GetRightMouseUp())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsMOUSEWHEELUPBUTTON:\n\t\tif (CPad::GetPad(PAD1)->GetMouseWheelUpUp())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsMOUSEWHEELDOWNBUTTON:\n\t\tif (CPad::GetPad(PAD1)->GetMouseWheelDownUp())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsMOUSEX1BUTTON:\n\t\tif (CPad::GetPad(PAD1)->GetMouseX1Up())\n\t\t\treturn true;\n\t\tbreak;\n\tcase rsMOUSEX2BUTTON:\n\t\tif (CPad::GetPad(PAD1)->GetMouseX2Up())\n\t\t\treturn true;\n\t\tbreak;\n\tdefault: break;\n\t}\n\n\treturn false;\n}\n\n#define CLEAR_ACTION_IF_NEEDED(action) \\\nif (key == GetControllerKeyAssociatedWithAction(action, type))\\\n\tClearSettingsAssociatedWithAction(action, type);\n\nvoid CControllerConfigManager::DeleteMatchingCommonControls(e_ControllerAction action, int32 key, eControllerType type)\n{\n\tif (!GetIsKeyBlank(key, type))\n\t{\n#ifndef BIND_VEHICLE_FIREWEAPON\n\t\tCLEAR_ACTION_IF_NEEDED(PED_FIREWEAPON);\n#endif\n\t\tCLEAR_ACTION_IF_NEEDED(GO_LEFT);\n\t\tCLEAR_ACTION_IF_NEEDED(GO_RIGHT);\n\t\tCLEAR_ACTION_IF_NEEDED(CAMERA_CHANGE_VIEW_ALL_SITUATIONS);\n\t\tCLEAR_ACTION_IF_NEEDED(NETWORK_TALK);\n\t\tCLEAR_ACTION_IF_NEEDED(SWITCH_DEBUG_CAM_ON);\n\t\tCLEAR_ACTION_IF_NEEDED(TOGGLE_DPAD);\n\t\tCLEAR_ACTION_IF_NEEDED(TAKE_SCREEN_SHOT);\n\t\tCLEAR_ACTION_IF_NEEDED(SHOW_MOUSE_POINTER_TOGGLE);\n\t}\n}\n\nvoid CControllerConfigManager::DeleteMatching3rdPersonControls(e_ControllerAction action, int32 key, eControllerType type)\n{\n\tif (!GetIsKeyBlank(key, type))\n\t{\n\t\tCLEAR_ACTION_IF_NEEDED(PED_CYCLE_WEAPON_LEFT);\n\t\tCLEAR_ACTION_IF_NEEDED(PED_CYCLE_WEAPON_RIGHT);\n\t\tCLEAR_ACTION_IF_NEEDED(PED_JUMPING);\n\t\tCLEAR_ACTION_IF_NEEDED(PED_SPRINT);\n\t\tCLEAR_ACTION_IF_NEEDED(PED_LOOKBEHIND);\n\t\tCLEAR_ACTION_IF_NEEDED(PED_DUCK);\n\t\tCLEAR_ACTION_IF_NEEDED(PED_ANSWER_PHONE);\n\n\t\tif (FrontEndMenuManager.m_ControlMethod == CONTROL_CLASSIC)\n\t\t{\n\t\t\tCLEAR_ACTION_IF_NEEDED(PED_CYCLE_TARGET_LEFT);\n\t\t\tCLEAR_ACTION_IF_NEEDED(PED_CYCLE_TARGET_RIGHT);\n\t\t\tCLEAR_ACTION_IF_NEEDED(PED_CENTER_CAMERA_BEHIND_PLAYER);\n\t\t}\n\t}\n}\n\nvoid CControllerConfigManager::DeleteMatching1rst3rdPersonControls(e_ControllerAction action, int32 key, eControllerType type)\n{\n\tif (!GetIsKeyBlank(key, type))\n\t{\n#ifdef BIND_VEHICLE_FIREWEAPON\n\t\tCLEAR_ACTION_IF_NEEDED(PED_FIREWEAPON);\n#endif\n\t\tCLEAR_ACTION_IF_NEEDED(PED_LOCK_TARGET);\n\t\tCLEAR_ACTION_IF_NEEDED(GO_FORWARD);\n\t\tCLEAR_ACTION_IF_NEEDED(GO_BACK);\n\n\t\tif (FrontEndMenuManager.m_ControlMethod == CONTROL_CLASSIC)\n\t\t{\n\t\t\tCLEAR_ACTION_IF_NEEDED(PED_1RST_PERSON_LOOK_LEFT);\n\t\t\tCLEAR_ACTION_IF_NEEDED(PED_1RST_PERSON_LOOK_RIGHT);\n\t\t\tCLEAR_ACTION_IF_NEEDED(PED_1RST_PERSON_LOOK_DOWN);\n\t\t\tCLEAR_ACTION_IF_NEEDED(PED_1RST_PERSON_LOOK_UP);\n\t\t}\n\t}\n}\n\nvoid CControllerConfigManager::DeleteMatchingVehicleControls(e_ControllerAction action, int32 key, eControllerType type)\n{\n\tif (!GetIsKeyBlank(key, type))\n\t{\n#ifdef BIND_VEHICLE_FIREWEAPON\n\t\tCLEAR_ACTION_IF_NEEDED(VEHICLE_FIREWEAPON);\n#endif\n\t\tCLEAR_ACTION_IF_NEEDED(VEHICLE_ACCELERATE);\n\t\tCLEAR_ACTION_IF_NEEDED(VEHICLE_BRAKE);\n\t\tCLEAR_ACTION_IF_NEEDED(VEHICLE_CHANGE_RADIO_STATION);\n\t\tCLEAR_ACTION_IF_NEEDED(VEHICLE_HORN);\n\t\tCLEAR_ACTION_IF_NEEDED(TOGGLE_SUBMISSIONS);\n\t\tCLEAR_ACTION_IF_NEEDED(VEHICLE_HANDBRAKE);\n\t\tCLEAR_ACTION_IF_NEEDED(VEHICLE_LOOKLEFT);\n\t\tCLEAR_ACTION_IF_NEEDED(VEHICLE_LOOKRIGHT);\n\t\tCLEAR_ACTION_IF_NEEDED(VEHICLE_LOOKBEHIND);\n\t\tCLEAR_ACTION_IF_NEEDED(VEHICLE_TURRETLEFT);\n\t\tCLEAR_ACTION_IF_NEEDED(VEHICLE_TURRETRIGHT);\n\t\tCLEAR_ACTION_IF_NEEDED(VEHICLE_TURRETUP);\n\t\tCLEAR_ACTION_IF_NEEDED(VEHICLE_TURRETDOWN);\n\t}\n}\n\nvoid CControllerConfigManager::DeleteMatchingVehicle_3rdPersonControls(e_ControllerAction action, int32 key, eControllerType type)\n{\n\tif (!GetIsKeyBlank(key, type))\n\t{\n\t\tCLEAR_ACTION_IF_NEEDED(VEHICLE_ENTER_EXIT);\n\t}\n}\n\nvoid CControllerConfigManager::DeleteMatching1rstPersonControls(e_ControllerAction action, int32 key, eControllerType type)\n{\n\tif (!GetIsKeyBlank(key, type))\n\t{\n\t\tCLEAR_ACTION_IF_NEEDED(PED_SNIPER_ZOOM_IN);\n\t\tCLEAR_ACTION_IF_NEEDED(PED_SNIPER_ZOOM_OUT);\n\t}\n}\n\n#undef CLEAR_ACTION_IF_NEEDED\n\n#ifdef RADIO_SCROLL_TO_PREV_STATION\n#define CHECK_ACTION(action) \\\nif (key == GetControllerKeyAssociatedWithAction(action, type))\\\n\treturn true;\n\nbool CControllerConfigManager::IsAnyVehicleActionAssignedToMouseKey(int32 key)\n{\n\tconst eControllerType type = MOUSE;\n\tif (!GetIsKeyBlank(key, type))\n\t{\n#ifdef BIND_VEHICLE_FIREWEAPON\n\t\tCHECK_ACTION(VEHICLE_FIREWEAPON);\n#endif\n\t\tCHECK_ACTION(VEHICLE_LOOKBEHIND);\n\t\tCHECK_ACTION(VEHICLE_LOOKLEFT);\n\t\tCHECK_ACTION(VEHICLE_LOOKRIGHT);\n\t\tCHECK_ACTION(VEHICLE_HORN);\n\t\tCHECK_ACTION(VEHICLE_HANDBRAKE);\n\t\tCHECK_ACTION(VEHICLE_ACCELERATE);\n\t\tCHECK_ACTION(VEHICLE_BRAKE);\n\t\tCHECK_ACTION(VEHICLE_CHANGE_RADIO_STATION);\n\t\tCHECK_ACTION(TOGGLE_SUBMISSIONS);\n\t\tCHECK_ACTION(VEHICLE_TURRETLEFT);\n\t\tCHECK_ACTION(VEHICLE_TURRETRIGHT);\n\t\tCHECK_ACTION(VEHICLE_TURRETUP);\n\t\tCHECK_ACTION(VEHICLE_TURRETDOWN);\n\t\tCHECK_ACTION(VEHICLE_ENTER_EXIT);\n\t\tCHECK_ACTION(CAMERA_CHANGE_VIEW_ALL_SITUATIONS);\n#ifndef BIND_VEHICLE_FIREWEAPON\n\t\tCHECK_ACTION(PED_FIREWEAPON);\n#endif\n\t\tCHECK_ACTION(GO_LEFT);\n\t\tCHECK_ACTION(GO_RIGHT);\n\t\tCHECK_ACTION(NETWORK_TALK);\n\t\tCHECK_ACTION(SWITCH_DEBUG_CAM_ON);\n\t\tCHECK_ACTION(TOGGLE_DPAD);\n\t\tCHECK_ACTION(TAKE_SCREEN_SHOT);\n\t\tCHECK_ACTION(SHOW_MOUSE_POINTER_TOGGLE);\n\t}\n\treturn false;\n}\n\n#undef CHECK_ACTION\n#endif\n\nvoid CControllerConfigManager::DeleteMatchingActionInitiators(e_ControllerAction action, int32 key, eControllerType type)\n{\n\tif (!GetIsKeyBlank(key, type))\n\t{\n\t\tswitch (GetActionType(action))\n\t\t{\n\t\tcase ACTIONTYPE_1RSTPERSON:\n\t\t\tDeleteMatchingCommonControls           (action, key, type);\n\t\t\tDeleteMatching1rstPersonControls       (action, key, type);\n\t\t\tDeleteMatching1rst3rdPersonControls    (action, key, type);\n\t\t\tbreak;\n\t\tcase ACTIONTYPE_3RDPERSON:\n\t\t\tDeleteMatchingCommonControls           (action, key, type);\n\t\t\tDeleteMatching1rst3rdPersonControls    (action, key, type);\n\t\t\tDeleteMatching3rdPersonControls        (action, key, type);\n\t\t\tDeleteMatchingVehicle_3rdPersonControls(action, key, type);\n\t\t\tbreak;\n\t\tcase ACTIONTYPE_VEHICLE:\n\t\t\tDeleteMatchingCommonControls           (action, key, type);\n\t\t\tDeleteMatchingVehicleControls          (action, key, type);\n\t\t\tDeleteMatchingVehicle_3rdPersonControls(action, key, type);\n\t\t\tbreak;\n\t\tcase ACTIONTYPE_VEHICLE_3RDPERSON:\n\t\t\tDeleteMatchingCommonControls           (action, key, type);\n\t\t\tDeleteMatching1rst3rdPersonControls    (action, key, type);\n\t\t\tDeleteMatching3rdPersonControls        (action, key, type);\n\t\t\tDeleteMatchingVehicleControls          (action, key, type);\n\t\t\tbreak;\n\t\tcase ACTIONTYPE_COMMON:\n\t\t\tDeleteMatchingCommonControls           (action, key, type);\n\t\t\tDeleteMatching1rstPersonControls       (action, key, type);\n\t\t\tDeleteMatching1rst3rdPersonControls    (action, key, type);\n\t\t\tDeleteMatching3rdPersonControls        (action, key, type);\n\t\t\tDeleteMatchingVehicleControls          (action, key, type);\n\t\t\tDeleteMatchingVehicle_3rdPersonControls(action, key, type);\n\t\t\tbreak;\n\t\tcase ACTIONTYPE_1RST3RDPERSON:\n\t\t\tDeleteMatchingCommonControls           (action, key, type);\n\t\t\tDeleteMatching1rstPersonControls       (action, key, type);\n\t\t\tDeleteMatching1rst3rdPersonControls    (action, key, type);\n\t\t\tDeleteMatching3rdPersonControls        (action, key, type);\n\t\t\tDeleteMatchingVehicle_3rdPersonControls(action, key, type);\n\t\t\tbreak;\n\t\tdefault: break;\n\t\t}\n\t}\n}\n\nbool CControllerConfigManager::GetIsKeyBlank(int32 key, eControllerType type)\n{\n\tswitch (type)\n\t{\n\tcase KEYBOARD:\n\tcase OPTIONAL_EXTRA:\n\t\tif (key != rsNULL)\n\t\t\treturn false;\n\t\tbreak;\n\n\tcase JOYSTICK:\n\t\tif (key != 0)\n\t\t\treturn false;\n\t\tbreak;\n\n\tcase MOUSE:\n\t\tif (key != 0)\n\t\t\treturn false;\n\t\tbreak;\n\tdefault: break;\n\t}\n\n\treturn true;\n}\n\ne_ControllerActionType CControllerConfigManager::GetActionType(e_ControllerAction action)\n{\n\tswitch (action)\n\t{\n#ifndef BIND_VEHICLE_FIREWEAPON\n\tcase PED_FIREWEAPON:\n#endif\n\tcase GO_LEFT:\n\tcase GO_RIGHT:\n\tcase CAMERA_CHANGE_VIEW_ALL_SITUATIONS:\n\tcase NETWORK_TALK:\n\tcase TOGGLE_DPAD:\n\tcase SWITCH_DEBUG_CAM_ON:\n\tcase TAKE_SCREEN_SHOT:\n\tcase SHOW_MOUSE_POINTER_TOGGLE:\n\t\treturn ACTIONTYPE_COMMON;\n\t\tbreak;\n\n\tcase PED_CYCLE_WEAPON_RIGHT:\n\tcase PED_CYCLE_WEAPON_LEFT:\n\tcase PED_JUMPING:\n\tcase PED_SPRINT:\n\tcase PED_LOOKBEHIND:\n\tcase PED_DUCK:\n\tcase PED_ANSWER_PHONE:\n\tcase PED_CYCLE_TARGET_LEFT:\n\tcase PED_CYCLE_TARGET_RIGHT:\n\tcase PED_CENTER_CAMERA_BEHIND_PLAYER:\n\t\treturn ACTIONTYPE_3RDPERSON;\n\t\tbreak;\n\n#ifdef BIND_VEHICLE_FIREWEAPON\n\tcase VEHICLE_FIREWEAPON:\n#endif\n\tcase VEHICLE_ACCELERATE:\n\tcase VEHICLE_BRAKE:\n\tcase VEHICLE_CHANGE_RADIO_STATION:\n\tcase VEHICLE_HORN:\n\tcase TOGGLE_SUBMISSIONS:\n\tcase VEHICLE_HANDBRAKE:\n\tcase VEHICLE_LOOKLEFT:\n\tcase VEHICLE_LOOKRIGHT:\n\tcase VEHICLE_LOOKBEHIND:\n\tcase VEHICLE_TURRETLEFT:\n\tcase VEHICLE_TURRETRIGHT:\n\tcase VEHICLE_TURRETUP:\n\tcase VEHICLE_TURRETDOWN:\n\t\treturn ACTIONTYPE_VEHICLE;\n\t\tbreak;\n\n\tcase VEHICLE_ENTER_EXIT:\n\t\treturn ACTIONTYPE_VEHICLE_3RDPERSON;\n\t\tbreak;\n\n#ifdef BIND_VEHICLE_FIREWEAPON\n\tcase PED_FIREWEAPON:\n#endif\n\tcase GO_FORWARD:\n\tcase GO_BACK:\n\tcase PED_1RST_PERSON_LOOK_LEFT:\n\tcase PED_1RST_PERSON_LOOK_RIGHT:\n\tcase PED_LOCK_TARGET:\n\tcase PED_1RST_PERSON_LOOK_UP:\n\tcase PED_1RST_PERSON_LOOK_DOWN:\n\t\treturn ACTIONTYPE_1RST3RDPERSON;\n\t\tbreak;\n\n\tcase PED_SNIPER_ZOOM_IN:\n\tcase PED_SNIPER_ZOOM_OUT:\n\t\treturn ACTIONTYPE_1RSTPERSON;\n\t\tbreak;\n\tdefault: break;\n\t}\n\n\treturn ACTIONTYPE_NONE;\n}\n\nvoid CControllerConfigManager::ClearSettingsAssociatedWithAction(e_ControllerAction action, eControllerType type)\n{\n\tswitch (type)\n\t{\n\tcase KEYBOARD:\n\t\tm_aSettings[action][type].m_Key = rsNULL;\n\t\tm_aSettings[action][type].m_ContSetOrder = SETORDER_NONE;\n\t\tbreak;\n\tcase OPTIONAL_EXTRA:\n\t\tm_aSettings[action][type].m_Key = rsNULL;\n\t\tm_aSettings[action][type].m_ContSetOrder = SETORDER_NONE;\n\t\tbreak;\n\tcase MOUSE:\n\t\tm_aSettings[action][type].m_Key = 0;\n\t\tm_aSettings[action][type].m_ContSetOrder = SETORDER_NONE;\n\t\tbreak;\n\tcase JOYSTICK:\n\t\tm_aSettings[action][type].m_Key = 0;\n\t\tm_aSettings[action][type].m_ContSetOrder = SETORDER_NONE;\n\t\tbreak;\n\tdefault: break;\n\t}\n\n\tResetSettingOrder(action);\n}\n\nwchar *CControllerConfigManager::GetControllerSettingTextWithOrderNumber(e_ControllerAction action, eContSetOrder setorder)\n{\n\tfor (int i = 0; i < MAX_CONTROLLERTYPES; i++)\n\t{\n\t\tif (m_aSettings[action][i].m_ContSetOrder == setorder)\n\t\t{\n\t\t\tswitch (i)\n\t\t\t{\n\t\t\tcase KEYBOARD:\n\t\t\tcase OPTIONAL_EXTRA:\n\t\t\t\treturn GetControllerSettingTextKeyBoard(action, (eControllerType)i);\n\t\t\tcase MOUSE:\n\t\t\t\treturn GetControllerSettingTextMouse   (action);\n\t\t\tcase JOYSTICK:\n\t\t\t\treturn GetControllerSettingTextJoystick(action);\n\t\t\tdefault: break;\n\t\t\t}\n\t\t}\n\t}\n\t\n\treturn NULL;\n}\n\nwchar *CControllerConfigManager::GetControllerSettingTextKeyBoard(e_ControllerAction action, eControllerType type)\n{\n\tstatic wchar ActionText[50];\n\tstatic wchar NewStringWithNumber[30];\n\n\tfor (int32 i = 0; i < ARRAY_SIZE(ActionText); i++)\n\t\tActionText[i] = '\\0';\n\n\tif (GetControllerKeyAssociatedWithAction(action, type) != rsNULL)\n\t{\n\t\tif (   GetControllerKeyAssociatedWithAction(action, type) >= 0\n\t\t\t&& GetControllerKeyAssociatedWithAction(action, type) <= 255)\n\t\t{\n\t\t\tchar c = GetControllerKeyAssociatedWithAction(action, type);\n\t\t\tif (c == ' ')\n\t\t\t\treturn TheText.Get(\"FEC_SPC\"); // \"SPC\"\n\t\t\telse\n\t\t\t{\n\t\t\t\tActionText[0] = CFont::character_code(c);\n\t\t\t\tif (ActionText[0] == '\\0')\n\t\t\t\t\tActionText[0] = CFont::character_code('#');\n\t\t\t\tActionText[1] = '\\0';\n\t\t\t\treturn ActionText;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tswitch (GetControllerKeyAssociatedWithAction(action, type))\n\t\t\t{\n\t\t\t\tcase rsF1:\n\t\t\t\tcase rsF2:\n\t\t\t\tcase rsF3:\n\t\t\t\tcase rsF4:\n\t\t\t\tcase rsF5:\n\t\t\t\tcase rsF6:\n\t\t\t\tcase rsF7:\n\t\t\t\tcase rsF8:\n\t\t\t\tcase rsF9:\n\t\t\t\tcase rsF10:\n\t\t\t\tcase rsF11:\n\t\t\t\tcase rsF12:\n\t\t\t\t{\n\t\t\t\t\tCMessages::InsertNumberInString(TheText.Get(\"FEC_FNC\"), // \"F~1~\"\n\t\t\t\t\t\tGetControllerKeyAssociatedWithAction(action, type) - rsESC,\n\t\t\t\t\t\t-1, -1, -1, -1, -1,\n\t\t\t\t\t\tNewStringWithNumber);\n\t\t\t\t\treturn NewStringWithNumber;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase rsINS:\n\t\t\t\t{\n\t\t\t\t\treturn TheText.Get(\"FEC_IRT\"); // \"INS\"\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase rsDEL:\n\t\t\t\t{\n\t\t\t\t\treturn TheText.Get(\"FEC_DLL\"); // \"DEL\"\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase rsHOME:\n\t\t\t\t{\n\t\t\t\t\treturn TheText.Get(\"FEC_HME\"); // \"HOME\"\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase rsEND:\n\t\t\t\t{\n\t\t\t\t\treturn TheText.Get(\"FEC_END\"); // \"END\"\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase rsPGUP:\n\t\t\t\t{\n\t\t\t\t\treturn TheText.Get(\"FEC_PGU\"); // \"PGUP\"\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase rsPGDN:\n\t\t\t\t{\n\t\t\t\t\treturn TheText.Get(\"FEC_PGD\"); // \"PGDN\"\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase rsUP:\n\t\t\t\t{\n\t\t\t\t\treturn TheText.Get(\"FEC_UPA\"); // \"UP\"\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase rsDOWN:\n\t\t\t\t{\n\t\t\t\t\treturn TheText.Get(\"FEC_DWA\"); // \"DOWN\"\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase rsLEFT:\n\t\t\t\t{\n\t\t\t\t\treturn TheText.Get(\"FEC_LFA\"); // \"LEFT\"\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase rsRIGHT:\n\t\t\t\t{\n\t\t\t\t\treturn TheText.Get(\"FEC_RFA\"); // \"RIGHT\"\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase rsDIVIDE:\n\t\t\t\t{\n\t\t\t\t\treturn TheText.Get(\"FEC_FWS\"); // \"NUM /\"\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase rsTIMES:\n\t\t\t\t{\n\t\t\t\t\treturn TheText.Get(\"FEC_STR\"); // \"NUM STAR\"\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase rsPLUS:\n\t\t\t\t{\n\t\t\t\t\treturn TheText.Get(\"FEC_PLS\"); // \"NUM +\"\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase rsMINUS:\n\t\t\t\t{\n\t\t\t\t\treturn TheText.Get(\"FEC_MIN\"); // \"NUM -\"\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase rsPADDEL:\n\t\t\t\t{\n\t\t\t\t\treturn TheText.Get(\"FEC_DOT\"); // \"NUM .\"\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase rsPADEND:\n\t\t\t\t{\n\t\t\t\t\tCMessages::InsertNumberInString(TheText.Get(\"FEC_NMN\"), // \"NUM~1~\"\n\t\t\t\t\t\t1, -1, -1, -1, -1, -1, NewStringWithNumber);\n\t\t\t\t\treturn NewStringWithNumber;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase rsPADDOWN:\n\t\t\t\t{\n\t\t\t\t\tCMessages::InsertNumberInString(TheText.Get(\"FEC_NMN\"), // \"NUM~1~\"\n\t\t\t\t\t\t2, -1, -1, -1, -1, -1,\n\t\t\t\t\t\tNewStringWithNumber);\n\t\t\t\t\treturn NewStringWithNumber;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase rsPADPGDN:\n\t\t\t\t{\n\t\t\t\t\tCMessages::InsertNumberInString(TheText.Get(\"FEC_NMN\"), // \"NUM~1~\"\n\t\t\t\t\t\t3, -1, -1, -1, -1, -1,\n\t\t\t\t\t\tNewStringWithNumber);\n\t\t\t\t\treturn NewStringWithNumber;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase rsPADLEFT:\n\t\t\t\t{\n\t\t\t\t\tCMessages::InsertNumberInString(TheText.Get(\"FEC_NMN\"), // \"NUM~1~\"\n\t\t\t\t\t\t4, -1, -1, -1, -1, -1,\n\t\t\t\t\t\tNewStringWithNumber);\n\t\t\t\t\treturn NewStringWithNumber;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase rsPAD5:\n\t\t\t\t{\n\t\t\t\t\tCMessages::InsertNumberInString(TheText.Get(\"FEC_NMN\"), // \"NUM~1~\"\n\t\t\t\t\t\t5, -1, -1, -1, -1, -1,\n\t\t\t\t\t\tNewStringWithNumber);\n\t\t\t\t\treturn NewStringWithNumber;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase rsNUMLOCK:\n\t\t\t\t{\n\t\t\t\t\treturn TheText.Get(\"FEC_NLK\"); // \"NUMLOCK\"\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase rsPADRIGHT:\n\t\t\t\t{\n\t\t\t\t\tCMessages::InsertNumberInString(TheText.Get(\"FEC_NMN\"), // \"NUM~1~\"\n\t\t\t\t\t\t6, -1, -1, -1, -1, -1,\n\t\t\t\t\t\tNewStringWithNumber);\n\t\t\t\t\treturn NewStringWithNumber;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase rsPADHOME:\n\t\t\t\t{\n\t\t\t\t\tCMessages::InsertNumberInString(TheText.Get(\"FEC_NMN\"), // \"NUM~1~\"\n\t\t\t\t\t\t7, -1, -1, -1, -1, -1,\n\t\t\t\t\t\tNewStringWithNumber);\n\t\t\t\t\treturn NewStringWithNumber;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase rsPADUP:\n\t\t\t\t{\n\t\t\t\t\tCMessages::InsertNumberInString(TheText.Get(\"FEC_NMN\"), // \"NUM~1~\"\n\t\t\t\t\t\t8, -1, -1, -1, -1, -1,\n\t\t\t\t\t\tNewStringWithNumber);\n\t\t\t\t\treturn NewStringWithNumber;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase rsPADPGUP:\n\t\t\t\t{\n\t\t\t\t\tCMessages::InsertNumberInString(TheText.Get(\"FEC_NMN\"), // \"NUM~1~\"\n\t\t\t\t\t\t9, -1, -1, -1, -1, -1,\n\t\t\t\t\t\tNewStringWithNumber);\n\t\t\t\t\treturn NewStringWithNumber;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase rsPADINS:\n\t\t\t\t{\n\t\t\t\t\tCMessages::InsertNumberInString(TheText.Get(\"FEC_NMN\"), // \"NUM~1~\"\n\t\t\t\t\t\t0, -1, -1, -1, -1, -1,\n\t\t\t\t\t\tNewStringWithNumber);\n\t\t\t\t\treturn NewStringWithNumber;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase rsPADENTER:\n\t\t\t\t{\n\t\t\t\t\treturn TheText.Get(\"FEC_ETR\"); // \"ENT\"\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase rsSCROLL:\n\t\t\t\t{\n\t\t\t\t\treturn TheText.Get(\"FEC_SLK\"); // \"SCROLL LOCK\"\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase rsPAUSE:\n\t\t\t\t{\n\t\t\t\t\treturn TheText.Get(\"FEC_PSB\"); // \"BREAK\"\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase rsBACKSP:\n\t\t\t\t{\n\t\t\t\t\treturn TheText.Get(\"FEC_BSP\"); // \"BSPACE\"\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase rsTAB:\n\t\t\t\t{\n\t\t\t\t\treturn TheText.Get(\"FEC_TAB\"); // \"TAB\"\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase rsCAPSLK:\n\t\t\t\t{\n\t\t\t\t\treturn TheText.Get(\"FEC_CLK\"); // \"CAPSLOCK\"\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase rsENTER:\n\t\t\t\t{\n\t\t\t\t\treturn TheText.Get(\"FEC_RTN\"); // \"RET\"\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase rsLSHIFT:\n\t\t\t\t{\n\t\t\t\t\treturn TheText.Get(\"FEC_LSF\"); // \"LSHIFT\"\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase rsRSHIFT:\n\t\t\t\t{\n\t\t\t\t\treturn TheText.Get(\"FEC_RSF\"); // \"RSHIFT\"\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase rsLCTRL:\n\t\t\t\t{\n\t\t\t\t\treturn TheText.Get(\"FEC_LCT\"); // \"LCTRL\"\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase rsRCTRL:\n\t\t\t\t{\n\t\t\t\t\treturn TheText.Get(\"FEC_RCT\"); // \"RCTRL\"\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase rsLALT:\n\t\t\t\t{\n\t\t\t\t\treturn TheText.Get(\"FEC_LAL\"); // \"LALT\"\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase rsRALT:\n\t\t\t\t{\n\t\t\t\t\treturn TheText.Get(\"FEC_RAL\"); // \"RALT\"\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase rsLWIN:\n\t\t\t\t{\n\t\t\t\t\treturn TheText.Get(\"FEC_LWD\"); // \"LWIN\"\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase rsRWIN:\n\t\t\t\t{\n\t\t\t\t\treturn TheText.Get(\"FEC_RWD\"); // \"RWIN\"\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase rsAPPS:\n\t\t\t\t{\n\t\t\t\t\treturn TheText.Get(\"FEC_WRC\"); // \"WINCLICK\"\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase rsSHIFT:\n\t\t\t\t{\n\t\t\t\t\treturn TheText.Get(\"FEC_SFT\"); // \"SHIFT\"\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tdefault: break;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn NULL;\n}\n\nwchar *CControllerConfigManager::GetControllerSettingTextMouse(e_ControllerAction action)\n{\n\tswitch (m_aSettings[action][MOUSE].m_Key)\n\t{\n\tcase 1:\n\t\treturn TheText.Get(\"FEC_MSL\");\t// LMB\n\t\tbreak;\n\tcase 2:\n\t\treturn TheText.Get(\"FEC_MSM\");\t// MMB\n\t\tbreak;\n\tcase 3:\n\t\treturn TheText.Get(\"FEC_MSR\");\t// RMB\n\t\tbreak;\n\tcase 4:\n\t\treturn TheText.Get(\"FEC_MWF\");\t// WHEEL UP\n\t\tbreak;\n\tcase 5:\n\t\treturn TheText.Get(\"FEC_MWB\");\t// WHEEL DN\n\t\tbreak;\n\tcase 6:\n\t\treturn TheText.Get(\"FEC_MXO\");\t// MXB1\n\t\tbreak;\n\tcase 7:\n\t\treturn TheText.Get(\"FEC_MXT\");\t// MXB2\n\t\tbreak;\n\tdefault: break;\n\t}\n\n\treturn NULL;\n}\n\nwchar *CControllerConfigManager::GetControllerSettingTextJoystick(e_ControllerAction action)\n{\n\tif (m_aSettings[action][JOYSTICK].m_Key == 0) \n\t\treturn NULL;\n\n\tstatic wchar NewStringWithNumber[30];\n\n\tCMessages::InsertNumberInString(TheText.Get(\"FEC_JBO\"),\t\t// JOY ~1~\n\t\tm_aSettings[action][JOYSTICK].m_Key, -1, -1, -1, -1, -1,\n\t\tNewStringWithNumber);\n\n\treturn NewStringWithNumber;\n}\n\nint32 CControllerConfigManager::GetNumOfSettingsForAction(e_ControllerAction action)\n{\n\tint32 num = 0;\n\n\tif (m_aSettings[action][KEYBOARD].m_Key       != rsNULL) num++;\n\tif (m_aSettings[action][OPTIONAL_EXTRA].m_Key != rsNULL) num++;\n\tif (m_aSettings[action][MOUSE].m_Key          != 0)      num++;\n\tif (m_aSettings[action][JOYSTICK].m_Key       != 0)      num++;\n\n\treturn num;\n}\n\n#ifdef BIND_VEHICLE_FIREWEAPON\n#define VFB(b) b,\n#else\n#define VFB(b)\n#endif\n\n#define CONTROLLER_BUTTONS(T, O, X, Q, L1, L2, L3, R1, R2, R3, SELECT, RSU, RSD, RSL, RSR)                                                                                         \\\n\t{{                                                                                                                                                         \\\n\t     O,      /* PED_FIREWEAPON */                                                                                                                          \\\n\t     R2,     /* PED_CYCLE_WEAPON_RIGHT */                                                                                                                  \\\n\t     L2,     /* PED_CYCLE_WEAPON_LEFT */                                                                                                                   \\\n\t     nil,    /* GO_FORWARD */                                                                                                                              \\\n\t     nil,    /* GO_BACK */                                                                                                                                 \\\n\t     LEFT,    /* GO_LEFT */                                                                                                                                 \\\n\t     RIGHT,    /* GO_RIGHT */                                                                                                                                \\\n\t     Q,      /* PED_SNIPER_ZOOM_IN */                                                                                                                      \\\n\t     X,      /* PED_SNIPER_ZOOM_OUT */                                                                                                                     \\\n\t     T,      /* VEHICLE_ENTER_EXIT */                                                                                                                      \\\n\t     SELECT, /* CAMERA_CHANGE_VIEW_ALL_SITUATIONS */                                                                                                       \\\n\t     Q,      /* PED_JUMPING */                                                                                                                             \\\n\t     X,      /* PED_SPRINT */                                                                                                                              \\\n\t     R3,     /* PED_LOOKBEHIND */                                                                                                                          \\\n\t     L3,     /* PED_DUCK */                                                                                                                                \\\n\t     L1,     /* PED_ANSWER_PHONE */                                                                                                                        \\\n\t     VFB(O)  /* VEHICLE_FIREWEAPON */                                                                                                                      \\\n\t     X,      /* VEHICLE_ACCELERATE */                                                                                                                      \\\n\t     Q,      /* VEHICLE_BRAKE */                                                                                                                           \\\n\t     L1,     /* VEHICLE_CHANGE_RADIO_STATION */                                                                                                            \\\n\t     L3,     /* VEHICLE_HORN */                                                                                                                            \\\n\t     R3,     /* TOGGLE_SUBMISSIONS */                                                                                                                      \\\n\t     R1,     /* VEHICLE_HANDBRAKE */                                                                                                                       \\\n\t     nil,    /* PED_1RST_PERSON_LOOK_LEFT */                                                                                                               \\\n\t     nil,    /* PED_1RST_PERSON_LOOK_RIGHT */                                                                                                              \\\n\t     L2,     /* VEHICLE_LOOKLEFT */                                                                                                                        \\\n\t     R2,     /* VEHICLE_LOOKRIGHT */                                                                                                                       \\\n\t     nil,    /* VEHICLE_LOOKBEHIND */                                                                                                                      \\\n\t     RSL,    /* VEHICLE_TURRETLEFT */                                                                                                                      \\\n\t     RSR,    /* VEHICLE_TURRETRIGHT */                                                                                                                     \\\n\t     UP,    /* VEHICLE_TURRETUP */                                                                                                                        \\\n\t     DOWN,    /* VEHICLE_TURRETDOWN */                                                                                                                      \\\n\t     L2,     /* PED_CYCLE_TARGET_LEFT */                                                                                                                   \\\n\t     R2,     /* PED_CYCLE_TARGET_RIGHT */                                                                                                                  \\\n\t     L1,     /* PED_CENTER_CAMERA_BEHIND_PLAYER */                                                                                                         \\\n\t     R1,     /* PED_LOCK_TARGET */                                                                                                                         \\\n\t     nil,    /* NETWORK_TALK */                                                                                                                            \\\n\t     nil,    /* PED_1RST_PERSON_LOOK_UP */                                                                                                                 \\\n\t     nil,    /* PED_1RST_PERSON_LOOK_DOWN */                                                                                                               \\\n\t     nil,    /* _CONTROLLERACTION_36 */                                                                                                                    \\\n\t     nil,    /* TOGGLE_DPAD */                                                                                                                             \\\n\t     nil,    /* SWITCH_DEBUG_CAM_ON */                                                                                                                     \\\n\t     nil,    /* TAKE_SCREEN_SHOT */                                                                                                                        \\\n\t     nil,    /* UNKNOWN_ACTION */                                                                                                                          \\\n\t     nil,    /* SHOW_MOUSE_POINTER_TOGGLE */                                                                                                               \\\n\t },                                                                                                                                                        \\\n\t {                                                                                                                                                         \\\n\t     O,      /* PED_FIREWEAPON */                                                                                                                          \\\n\t     R2,     /* PED_CYCLE_WEAPON_RIGHT */                                                                                                                  \\\n\t     L2,     /* PED_CYCLE_WEAPON_LEFT */                                                                                                                   \\\n\t     nil,    /* GO_FORWARD */                                                                                                                              \\\n\t     nil,    /* GO_BACK */                                                                                                                                 \\\n\t     LEFT,   /* GO_LEFT */                                                                                                                                 \\\n\t     RIGHT,  /* GO_RIGHT */                                                                                                                                \\\n\t     Q,      /* PED_SNIPER_ZOOM_IN */                                                                                                                      \\\n\t     X,      /* PED_SNIPER_ZOOM_OUT */                                                                                                                     \\\n\t     T,      /* VEHICLE_ENTER_EXIT */                                                                                                                      \\\n\t     SELECT, /* CAMERA_CHANGE_VIEW_ALL_SITUATIONS */                                                                                                       \\\n\t     Q,      /* PED_JUMPING */                                                                                                                             \\\n\t     X,      /* PED_SPRINT */                                                                                                                              \\\n\t     R3,     /* PED_LOOKBEHIND */                                                                                                                          \\\n\t     L3,     /* PED_DUCK */                                                                                                                                \\\n\t     L1,     /* PED_ANSWER_PHONE */                                                                                                                        \\\n\t     VFB(O)  /* VEHICLE_FIREWEAPON */                                                                                                                      \\\n\t     X,      /* VEHICLE_ACCELERATE */                                                                                                                      \\\n\t     Q,      /* VEHICLE_BRAKE */                                                                                                                           \\\n\t     SELECT, /* VEHICLE_CHANGE_RADIO_STATION */                                                                                                            \\\n\t     L1,     /* VEHICLE_HORN */                                                                                                                            \\\n\t     R3,     /* TOGGLE_SUBMISSIONS */                                                                                                                      \\\n\t     R1,     /* VEHICLE_HANDBRAKE */                                                                                                                       \\\n\t     nil,    /* PED_1RST_PERSON_LOOK_LEFT */                                                                                                               \\\n\t     nil,    /* PED_1RST_PERSON_LOOK_RIGHT */                                                                                                              \\\n\t     L2,     /* VEHICLE_LOOKLEFT */                                                                                                                        \\\n\t     R2,     /* VEHICLE_LOOKRIGHT */                                                                                                                       \\\n\t     nil,    /* VEHICLE_LOOKBEHIND */                                                                                                                      \\\n\t     RSL,    /* VEHICLE_TURRETLEFT */                                                                                                                      \\\n\t     RSR,    /* VEHICLE_TURRETRIGHT */                                                                                                                     \\\n\t     UP,    /* VEHICLE_TURRETUP */                                                                                                                        \\\n\t     DOWN,    /* VEHICLE_TURRETDOWN */                                                                                                                      \\\n\t     L2,     /* PED_CYCLE_TARGET_LEFT */                                                                                                                   \\\n\t     R2,     /* PED_CYCLE_TARGET_RIGHT */                                                                                                                  \\\n\t     L1,     /* PED_CENTER_CAMERA_BEHIND_PLAYER */                                                                                                         \\\n\t     R1,     /* PED_LOCK_TARGET */                                                                                                                         \\\n\t     nil,    /* NETWORK_TALK */                                                                                                                            \\\n\t     nil,    /* PED_1RST_PERSON_LOOK_UP */                                                                                                                 \\\n\t     nil,    /* PED_1RST_PERSON_LOOK_DOWN */                                                                                                               \\\n\t     nil,    /* _CONTROLLERACTION_36 */                                                                                                                    \\\n\t     nil,    /* TOGGLE_DPAD */                                                                                                                             \\\n\t     nil,    /* SWITCH_DEBUG_CAM_ON */                                                                                                                     \\\n\t     nil,    /* TAKE_SCREEN_SHOT */                                                                                                                        \\\n\t     nil,    /* UNKNOWN_ACTION */                                                                                                                          \\\n\t     nil,    /* SHOW_MOUSE_POINTER_TOGGLE */                                                                                                               \\\n\t },                                                                                                                                                        \\\n\t {                                                                                                                                                         \\\n\t     X,      /* PED_FIREWEAPON */                                                                                                                          \\\n\t     R2,     /* PED_CYCLE_WEAPON_RIGHT */                                                                                                                  \\\n\t     L2,     /* PED_CYCLE_WEAPON_LEFT */                                                                                                                   \\\n\t     nil,    /* GO_FORWARD */                                                                                                                              \\\n\t     nil,    /* GO_BACK */                                                                                                                                 \\\n\t     LEFT,   /* GO_LEFT */                                                                                                                                 \\\n\t     RIGHT,  /* GO_RIGHT */                                                                                                                                \\\n\t     T,      /* PED_SNIPER_ZOOM_IN */                                                                                                                      \\\n\t     Q,      /* PED_SNIPER_ZOOM_OUT */                                                                                                                     \\\n\t     L1,     /* VEHICLE_ENTER_EXIT */                                                                                                                      \\\n\t     SELECT, /* CAMERA_CHANGE_VIEW_ALL_SITUATIONS */                                                                                                       \\\n\t     Q,      /* PED_JUMPING */                                                                                                                             \\\n\t     O,      /* PED_SPRINT */                                                                                                                              \\\n\t     R3,     /* PED_LOOKBEHIND */                                                                                                                          \\\n\t     L3,     /* PED_DUCK */                                                                                                                                \\\n\t     T,     /* PED_ANSWER_PHONE */                                                                                                                        \\\n\t     VFB(O)  /* VEHICLE_FIREWEAPON */                                                                                                                      \\\n\t     X,      /* VEHICLE_ACCELERATE */                                                                                                                      \\\n\t     Q,      /* VEHICLE_BRAKE */                                                                                                                           \\\n\t     L3,     /* VEHICLE_CHANGE_RADIO_STATION */                                                                                                            \\\n\t     R1,     /* VEHICLE_HORN */                                                                                                                            \\\n\t     R3,     /* TOGGLE_SUBMISSIONS */                                                                                                                      \\\n\t     T,      /* VEHICLE_HANDBRAKE */                                                                                                                       \\\n\t     nil,    /* PED_1RST_PERSON_LOOK_LEFT */                                                                                                               \\\n\t     nil,    /* PED_1RST_PERSON_LOOK_RIGHT */                                                                                                              \\\n\t     L2,     /* VEHICLE_LOOKLEFT */                                                                                                                        \\\n\t     R2,     /* VEHICLE_LOOKRIGHT */                                                                                                                       \\\n\t     nil,    /* VEHICLE_LOOKBEHIND */                                                                                                                      \\\n\t     RSL,    /* VEHICLE_TURRETLEFT */                                                                                                                      \\\n\t     RSR,    /* VEHICLE_TURRETRIGHT */                                                                                                                     \\\n\t     UP,    /* VEHICLE_TURRETUP */                                                                                                                        \\\n\t     DOWN,    /* VEHICLE_TURRETDOWN */                                                                                                                      \\\n\t     L2,     /* PED_CYCLE_TARGET_LEFT */                                                                                                                   \\\n\t     R2,     /* PED_CYCLE_TARGET_RIGHT */                                                                                                                  \\\n\t     T,      /* PED_CENTER_CAMERA_BEHIND_PLAYER */                                                                                                         \\\n\t     R1,     /* PED_LOCK_TARGET */                                                                                                                         \\\n\t     nil,    /* NETWORK_TALK */                                                                                                                            \\\n\t     nil,    /* PED_1RST_PERSON_LOOK_UP */                                                                                                                 \\\n\t     nil,    /* PED_1RST_PERSON_LOOK_DOWN */                                                                                                               \\\n\t     nil,    /* _CONTROLLERACTION_36 */                                                                                                                    \\\n\t     nil,    /* TOGGLE_DPAD */                                                                                                                             \\\n\t     nil,    /* SWITCH_DEBUG_CAM_ON */                                                                                                                     \\\n\t     nil,    /* TAKE_SCREEN_SHOT */                                                                                                                        \\\n\t     nil,    /* UNKNOWN_ACTION */                                                                                                                          \\\n\t     nil,    /* SHOW_MOUSE_POINTER_TOGGLE */                                                                                                               \\\n\t },                                                                                                                                                        \\\n\t {                                                                                                                                                         \\\n\t     R1,     /* PED_FIREWEAPON */                                                                                                                          \\\n\t     R2,     /* PED_CYCLE_WEAPON_RIGHT */                                                                                                                  \\\n\t     L2,     /* PED_CYCLE_WEAPON_LEFT */                                                                                                                   \\\n\t     nil,    /* GO_FORWARD */                                                                                                                              \\\n\t     nil,    /* GO_BACK */                                                                                                                                 \\\n\t     LEFT,   /* GO_LEFT */                                                                                                                                 \\\n\t     RIGHT,  /* GO_RIGHT */                                                                                                                                \\\n\t     Q,      /* PED_SNIPER_ZOOM_IN */                                                                                                                      \\\n\t     X,      /* PED_SNIPER_ZOOM_OUT */                                                                                                                     \\\n\t     T,      /* VEHICLE_ENTER_EXIT */                                                                                                                      \\\n\t     SELECT, /* CAMERA_CHANGE_VIEW_ALL_SITUATIONS */                                                                                                       \\\n\t     Q,      /* PED_JUMPING */                                                                                                                             \\\n\t     X,      /* PED_SPRINT */                                                                                                                              \\\n\t     R3,     /* PED_LOOKBEHIND */                                                                                                                          \\\n\t     L3,     /* PED_DUCK */                                                                                                                                \\\n\t     O,     /* PED_ANSWER_PHONE */                                                                                                                        \\\n\t     VFB(R1) /* VEHICLE_FIREWEAPON */                                                                                                                      \\\n\t     RSU,    /* VEHICLE_ACCELERATE */                                                                                                                      \\\n\t     RSD,    /* VEHICLE_BRAKE */                                                                                                                           \\\n\t     O,      /* VEHICLE_CHANGE_RADIO_STATION */                                                                                                            \\\n\t     L3,     /* VEHICLE_HORN */                                                                                                                            \\\n\t     Q,      /* TOGGLE_SUBMISSIONS */                                                                                                                      \\\n\t     L1,     /* VEHICLE_HANDBRAKE */                                                                                                                       \\\n\t     nil,    /* PED_1RST_PERSON_LOOK_LEFT */                                                                                                               \\\n\t     nil,    /* PED_1RST_PERSON_LOOK_RIGHT */                                                                                                              \\\n\t     L2,     /* VEHICLE_LOOKLEFT */                                                                                                                        \\\n\t     R2,     /* VEHICLE_LOOKRIGHT */                                                                                                                       \\\n\t     nil,    /* VEHICLE_LOOKBEHIND */                                                                                                                      \\\n\t     RSL,    /* VEHICLE_TURRETLEFT */                                                                                                                      \\\n\t     RSR,    /* VEHICLE_TURRETRIGHT */                                                                                                                     \\\n\t     UP,    /* VEHICLE_TURRETUP */                                                                                                                        \\\n\t     DOWN,    /* VEHICLE_TURRETDOWN */                                                                                                                      \\\n\t     L2,     /* PED_CYCLE_TARGET_LEFT */                                                                                                                   \\\n\t     R2,     /* PED_CYCLE_TARGET_RIGHT */                                                                                                                  \\\n\t     O,      /* PED_CENTER_CAMERA_BEHIND_PLAYER */                                                                                                         \\\n\t     L1,     /* PED_LOCK_TARGET */                                                                                                                         \\\n\t     nil,    /* NETWORK_TALK */                                                                                                                            \\\n\t     nil,    /* PED_1RST_PERSON_LOOK_UP */                                                                                                                 \\\n\t     nil,    /* PED_1RST_PERSON_LOOK_DOWN */                                                                                                               \\\n\t     nil,    /* _CONTROLLERACTION_36 */                                                                                                                    \\\n\t     nil,    /* TOGGLE_DPAD */                                                                                                                             \\\n\t     nil,    /* SWITCH_DEBUG_CAM_ON */                                                                                                                     \\\n\t     nil,    /* TAKE_SCREEN_SHOT */                                                                                                                        \\\n\t     nil,    /* UNKNOWN_ACTION */                                                                                                                          \\\n\t     nil,    /* SHOW_MOUSE_POINTER_TOGGLE */                                                                                                               \\\n\t }}\n\n#ifdef BUTTON_ICONS\n#define UP \"~U~\"\n#define DOWN \"~D~\"\n#define LEFT \"~<~\"\n#define RIGHT \"~>~\"\n#else\n#define UP \"UP\"\n#define DOWN \"DOWN\"\n#define LEFT \"LEFT\"\n#define RIGHT \"RIGHT\"\n#endif\n\nconst char *XboxButtons_noIcons[][MAX_CONTROLLERACTIONS] = CONTROLLER_BUTTONS(\"Y\", \"B\", \"A\", \"X\", \"LB\", \"LT\", \"LS\", \"RB\", \"RT\", \"RS\", \"BACK\", \"right stick up\", \"right stick down\", \"right stick left\", \"right stick right\");\n\n#ifdef BUTTON_ICONS\nconst char *XboxButtons[][MAX_CONTROLLERACTIONS] = CONTROLLER_BUTTONS(\"~T~\", \"~O~\", \"~X~\", \"~Q~\", \"~K~\", \"~M~\", \"~A~\", \"~J~\", \"~V~\", \"~C~\", \"BACK\", \"~H~\", \"~L~\", \"~(~\", \"~)~\");\n#endif\n\n\n#if 0 // set 1 for ps2 fonts\n#define PS2_TRIANGLE \"\\\"\"\n#define PS2_CIRCLE \"|\"\n#define PS2_CROSS \"/\"\n#define PS2_SQUARE \"^\"\n#else\n#define PS2_TRIANGLE \"TRIANGLE\"\n#define PS2_CIRCLE \"CIRCLE\"\n#define PS2_CROSS \"CROSS\"\n#define PS2_SQUARE \"SQUARE\"\n#endif\n\nconst char *PlayStationButtons_noIcons[][MAX_CONTROLLERACTIONS] =\n    CONTROLLER_BUTTONS(PS2_TRIANGLE, PS2_CIRCLE, PS2_CROSS, PS2_SQUARE, \"L1\", \"L2\", \"L3\", \"R1\", \"R2\", \"R3\", \"SELECT\", \"right stick up\", \"right stick down\", \"right stick left\", \"right stick right\");\n\n#ifdef BUTTON_ICONS\nconst char *PlayStationButtons[][MAX_CONTROLLERACTIONS] =\n    CONTROLLER_BUTTONS(\"~T~\", \"~O~\", \"~X~\", \"~Q~\", \"~K~\", \"~M~\", \"~A~\", \"~J~\", \"~V~\", \"~C~\", \"SELECT\", \"~H~\", \"~L~\", \"~(~\", \"~)~\");\n#endif\n\n#undef PS2_TRIANGLE\n#undef PS2_CIRCLE\n#undef PS2_CROSS\n#undef PS2_SQUARE\n\n#undef UP\n#undef DOWN\n#undef LEFT\n#undef RIGHT\n\n#undef CONTROLLER_BUTTONS\n#undef VFB\n\nvoid CControllerConfigManager::GetWideStringOfCommandKeys(uint16 action, wchar *text, uint16 leight)\n{\n#ifdef DETECT_PAD_INPUT_SWITCH\n\tif (CPad::GetPad(0)->IsAffectedByController) {\n\t\twchar wstr[16];\n\n\t\tconst char* (*Buttons)[MAX_CONTROLLERACTIONS];\n\n#ifdef BUTTON_ICONS\n\t#ifdef GAMEPAD_MENU\n\t\tswitch (FrontEndMenuManager.m_PrefsControllerType)\n\t\t{\n\t\tcase CMenuManager::CONTROLLER_DUALSHOCK2:\n\t\tcase CMenuManager::CONTROLLER_DUALSHOCK3:\n\t\tcase CMenuManager::CONTROLLER_DUALSHOCK4:\n\t\t\tButtons = CFont::ButtonsSlot != -1 ? PlayStationButtons : PlayStationButtons_noIcons;\n\t\t\tbreak;\n\t\tdefault:\n\t#endif\n\t\t\tButtons = CFont::ButtonsSlot != -1 ? XboxButtons : XboxButtons_noIcons;\n\t#ifdef GAMEPAD_MENU\n\t\t\tbreak;\n\t\t}\n\t#endif\n#else\n\t\tswitch (FrontEndMenuManager.m_PrefsControllerType)\n\t\t{\n\t\tcase CMenuManager::CONTROLLER_DUALSHOCK2:\n\t\tcase CMenuManager::CONTROLLER_DUALSHOCK3:\n\t\tcase CMenuManager::CONTROLLER_DUALSHOCK4:\n\t\t\tButtons = PlayStationButtons_noIcons;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tButtons = XboxButtons_noIcons;\n\t\t\tbreak;\n\t\t}\n#endif\n\n\t\tassert(Buttons[CPad::GetPad(0)->Mode][action] != nil); // we cannot use these\n\t\tAsciiToUnicode(Buttons[CPad::GetPad(0)->Mode][action], wstr);\n\n\t\tCMessages::WideStringCopy(text, wstr, leight);\n\t\treturn;\n\t}\n#endif\n\n\tint32 nums = GetNumOfSettingsForAction((e_ControllerAction)action);\n\n\tint32 sets = 0;\n\n\tfor (int32 i = SETORDER_1; i < MAX_SETORDERS; i++)\n\t{\n\t\twchar *textorder = ControlsManager.GetControllerSettingTextWithOrderNumber((e_ControllerAction)action, (eContSetOrder)i);\n\t\tif (textorder != NULL)\n\t\t{\n\t\t\tuint16 len = CMessages::GetWideStringLength(text);\n\t\t\tCMessages::WideStringCopy(&text[len], textorder, leight - len);\n\n\t\t\tif (++sets < nums)\n\t\t\t{\n\t\t\t\tif (sets == nums - 1)\n\t\t\t\t{\n\t\t\t\t\t// if last - text += ' or ';\n\t\t\t\t\tuint16 pos1 = CMessages::GetWideStringLength(text);\n\t\t\t\t\ttext[pos1] = ' ';\n\n\t\t\t\t\tCMessages::WideStringCopy(&text[pos1 + 1],\n\t\t\t\t\t\tTheText.Get(\"FEC_ORR\"),\t// \"or\"\n\t\t\t\t\t\tleight - (pos1 + 1));\n\t\t\t\t\t\n\t\t\t\t\tuint16 pos2 = CMessages::GetWideStringLength(text);\n\t\t\t\t\ttext[pos2 + 0] = ' ';\n\t\t\t\t\ttext[pos2 + 1] = '\\0';\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t// text += ', ';\n\t\t\t\t\tuint16 pos1 = CMessages::GetWideStringLength(text);\n\t\t\t\t\ttext[pos1 + 0] = ',';\n\t\t\t\t\ttext[pos1 + 1] = ' ';\n\t\t\t\t\ttext[pos1 + 2] = '\\0';\n\n\t\t\t\t\tuint16 pos2 = CMessages::GetWideStringLength(text);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nint32 CControllerConfigManager::GetControllerKeyAssociatedWithAction(e_ControllerAction action, eControllerType type)\n{\n\treturn m_aSettings[action][type].m_Key;\n}\n\nvoid CControllerConfigManager::UpdateJoyButtonState(int32 padnumber)\n{\n\tfor (int32 i = 0; i < MAX_BUTTONS; i++)\n\t\tm_aButtonStates[i] = false;\n\n#ifdef __DINPUT_INCLUDED__\n\tfor (int32 i = 0; i < MAX_BUTTONS; i++)\n\t{\n\t\tif (m_NewState.rgbButtons[i] & 0x80)\n\t\t\tm_aButtonStates[i] = true;\n\t\telse\n\t\t\tm_aButtonStates[i] = false;\n\t}\n#elif defined RW_GL3\n\tif (m_NewState.isGamepad) {\n\t\tfor (int32 i = 0; i < MAX_BUTTONS; i++) {\n\t\t\tif (i == GLFW_GAMEPAD_BUTTON_GUIDE)\n\t\t\t\tcontinue;\n\n\t\t\tm_aButtonStates[MapIdToButtonId(i)-1] = m_NewState.mappedButtons[i];\n\t\t}\n\t} else {\n\t\tfor (int32 i = 0; i < Min(m_NewState.numButtons, MAX_BUTTONS); i++) {\n\t\t\tm_aButtonStates[i] = m_NewState.buttons[i];\n\t\t}\n\t}\n#endif\n}\n\nbool CControllerConfigManager::GetIsActionAButtonCombo(e_ControllerAction action)\n{\n\tswitch (action)\n\t{\n\tcase VEHICLE_LOOKBEHIND:\n\tcase PED_CYCLE_TARGET_LEFT:\n\tcase PED_CYCLE_TARGET_RIGHT:\n\t\treturn true;\n\t\tbreak;\n\tdefault: break;\n\t}\n\n\treturn false;\n}\n\nwchar *CControllerConfigManager::GetButtonComboText(e_ControllerAction action)\n{\n\tswitch (action)\n\t{\n\tcase PED_CYCLE_TARGET_LEFT:\n\t\treturn TheText.Get(\"FEC_PTL\");\t// Use LockTarget with Weapon Switch Left.\n\t\tbreak;\n\t\n\tcase PED_CYCLE_TARGET_RIGHT:\n\t\treturn TheText.Get(\"FEC_PTR\");\t// Use LockTarget with Weapon Switch Right.\n\t\tbreak;\n\t\n\tcase VEHICLE_LOOKBEHIND:\n\t\treturn TheText.Get(\"FEC_LBC\");\t// Use Look Left With Look Right. \n\t\tbreak;\n\tdefault: break;\n\t}\n\n\treturn NULL;\n}\n\nvoid CControllerConfigManager::SetControllerKeyAssociatedWithAction(e_ControllerAction action, int32 key, eControllerType type)\n{\n\tResetSettingOrder(action);\n\tint numOfSettings = GetNumOfSettingsForAction(action);\n\t\n\tm_aSettings[action][type].m_Key = key;\n\tm_aSettings[action][type].m_ContSetOrder = numOfSettings + 1;\n}\n\nint32 CControllerConfigManager::GetMouseButtonAssociatedWithAction(e_ControllerAction action)\n{\n\treturn m_aSettings[action][MOUSE].m_Key;\n}\n\nvoid CControllerConfigManager::SetMouseButtonAssociatedWithAction(e_ControllerAction action, int32 button)\n{\n\tint numOfSettings = GetNumOfSettingsForAction(action);\n\t\n\tm_aSettings[action][MOUSE].m_Key = button;\n\tm_aSettings[action][MOUSE].m_ContSetOrder = numOfSettings + 1;\n}\n\nvoid CControllerConfigManager::ResetSettingOrder(e_ControllerAction action)\n{\n\tint32 conttype = KEYBOARD;\n\n\tfor (int32 i = SETORDER_1; i < MAX_SETORDERS; i++)\n\t{\n\t\tbool isexist = false;\n\t\tfor (int32 j = 0; j < MAX_CONTROLLERTYPES; j++)\n\t\t{\n\t\t\tif (m_aSettings[action][j].m_ContSetOrder == i)\n\t\t\t\tisexist = true;\n\t\t}\n\n\t\tbool init = false;\n\n\t\tif (!isexist)\n\t\t{\n\t\t\tfor (int32 k = 0; k < MAX_CONTROLLERTYPES; k++)\n\t\t\t{\n\t\t\t\tint32 setorder = m_aSettings[action][k].m_ContSetOrder;\n\t\t\t\tif (setorder > i && setorder != 0)\n\t\t\t\t{\n\t\t\t\t\tif (init)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (setorder < m_aSettings[action][conttype].m_ContSetOrder)\n\t\t\t\t\t\t\tconttype = k;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tinit = true;\n\t\t\t\t\t\tconttype = k;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (init)\n\t\t\t\tm_aSettings[action][conttype].m_ContSetOrder = i;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/core/ControllerConfig.h",
    "content": "#pragma once\n\n#if defined RW_D3D9 || defined RWLIBS\n#define DIRECTINPUT_VERSION 0x0800\n#include <dinput.h>\n#endif\n\n// based on x-gtasa\n\nenum eControllerType\n{\n\tKEYBOARD = 0,\n\tOPTIONAL_EXTRA,\n\tMOUSE,\n\tJOYSTICK,\n\tMAX_CONTROLLERTYPES,\n};\n\nenum e_ControllerAction\n{\n\tPED_FIREWEAPON = 0,\n\tPED_CYCLE_WEAPON_RIGHT,\n\tPED_CYCLE_WEAPON_LEFT,\n\tGO_FORWARD,\n\tGO_BACK,\n\tGO_LEFT,\n\tGO_RIGHT,\n\tPED_SNIPER_ZOOM_IN,\n\tPED_SNIPER_ZOOM_OUT,\n\tVEHICLE_ENTER_EXIT,\n\tCAMERA_CHANGE_VIEW_ALL_SITUATIONS,\n\tPED_JUMPING,\n\tPED_SPRINT,\n\tPED_LOOKBEHIND,\n\tPED_DUCK,\n\tPED_ANSWER_PHONE,\n#ifdef BIND_VEHICLE_FIREWEAPON\n\tVEHICLE_FIREWEAPON,\n#endif\n\tVEHICLE_ACCELERATE,\n\tVEHICLE_BRAKE,\n\tVEHICLE_CHANGE_RADIO_STATION,\n\tVEHICLE_HORN,\n\tTOGGLE_SUBMISSIONS,\n\tVEHICLE_HANDBRAKE,\n\tPED_1RST_PERSON_LOOK_LEFT,\n\tPED_1RST_PERSON_LOOK_RIGHT,\n\tVEHICLE_LOOKLEFT,\n\tVEHICLE_LOOKRIGHT,\n\tVEHICLE_LOOKBEHIND,\n\tVEHICLE_TURRETLEFT,\n\tVEHICLE_TURRETRIGHT,\n\tVEHICLE_TURRETUP,\n\tVEHICLE_TURRETDOWN,\n\tPED_CYCLE_TARGET_LEFT,\n\tPED_CYCLE_TARGET_RIGHT,\n\tPED_CENTER_CAMERA_BEHIND_PLAYER,\n\tPED_LOCK_TARGET,\n\tNETWORK_TALK,\n\tPED_1RST_PERSON_LOOK_UP,\n\tPED_1RST_PERSON_LOOK_DOWN,\n\t_CONTROLLERACTION_36,\t\t\t\t\t// Unused\n\tTOGGLE_DPAD,\n\tSWITCH_DEBUG_CAM_ON,\n\tTAKE_SCREEN_SHOT,\n\tSHOW_MOUSE_POINTER_TOGGLE,\n\tUNKNOWN_ACTION,\n\tMAX_CONTROLLERACTIONS,\n};\n\nenum e_ControllerActionType\n{\n\tACTIONTYPE_1RSTPERSON = 0,\n\tACTIONTYPE_3RDPERSON,\n\tACTIONTYPE_VEHICLE,\n\tACTIONTYPE_VEHICLE_3RDPERSON,\n\tACTIONTYPE_COMMON,\n\tACTIONTYPE_1RST3RDPERSON,\n\tACTIONTYPE_NONE,\n};\n\nenum eContSetOrder\n{\n\tSETORDER_NONE = 0,\n\tSETORDER_1,\n\tSETORDER_2,\n\tSETORDER_3,\n\tSETORDER_4,\n\tMAX_SETORDERS,\n};\n\nenum eSimCheckers\n{\n\tSIM_X1 = 0, SIM_Y1,\t// DPad\n\tSIM_X2, SIM_Y2,\t    // LeftStick\n\n\tMAX_SIMS\n};\n\nclass CMouseControllerState;\nclass CControllerState;\n\n\n#define JOY_BUTTONS 16\n#define MAX_BUTTONS (JOY_BUTTONS+1)\n\n#define ACTIONNAME_LENGTH 40\n\n#ifdef RW_GL3\nstruct GlfwJoyState {\n\tint8 id;\n\tbool isGamepad;\n\tuint8 numButtons;\n\tuint8* buttons;\n\tbool mappedButtons[17];\n};\n#endif\n\nclass CControllerConfigManager\n{\npublic:\n\tstruct tControllerConfigBind\n\t{\n\t\tint32      m_Key;\n\t\tint32      m_ContSetOrder;\n\n\t\ttControllerConfigBind()\n\t\t{\n\t\t\tm_Key = 0;\n\t\t\tm_ContSetOrder = 0;\n\t\t}\n\t};\n\n\tbool                  m_bFirstCapture;\n#if defined RW_GL3\n\tGlfwJoyState           m_OldState;\n\tGlfwJoyState           m_NewState;\n#else\n\tDIJOYSTATE2           m_OldState;\n\tDIJOYSTATE2           m_NewState;\n#endif\n\twchar                 m_aActionNames[MAX_CONTROLLERACTIONS][ACTIONNAME_LENGTH];\n\tbool                  m_aButtonStates[MAX_BUTTONS];\n\ttControllerConfigBind m_aSettings[MAX_CONTROLLERACTIONS][MAX_CONTROLLERTYPES];\n\tbool                  m_aSimCheckers[MAX_SIMS][MAX_CONTROLLERTYPES];\n\tbool                  m_bMouseAssociated;\n\n#ifdef LOAD_INI_SETTINGS\n\tstatic uint32 ms_padButtonsInited;\n#endif\n\t\n\tCControllerConfigManager();\n\n\tvoid  MakeControllerActionsBlank();\n\t\n\tint32 GetJoyButtonJustDown();\n\t\n\tvoid  SaveSettings(int32 file);\n\tvoid  LoadSettings(int32 file);\n\t\n\tvoid  InitDefaultControlConfiguration();\n\tvoid  InitDefaultControlConfigMouse(CMouseControllerState const &availableButtons);\n\tvoid  InitDefaultControlConfigJoyPad(uint32 buttons);\n\tvoid  InitialiseControllerActionNameArray();\n\n\tvoid  UpdateJoyInConfigMenus_ButtonDown                           (int32 button, int32 padnumber);\n\tvoid  AffectControllerStateOn_ButtonDown                          (int32 button, eControllerType type);\n\tvoid  AffectControllerStateOn_ButtonDown_Driving                  (int32 button, eControllerType type, CControllerState &state);\n\tvoid  AffectControllerStateOn_ButtonDown_FirstPersonOnly          (int32 button, eControllerType type, CControllerState &state);\n\tvoid  AffectControllerStateOn_ButtonDown_ThirdPersonOnly          (int32 button, eControllerType type, CControllerState &state);\n\tvoid  AffectControllerStateOn_ButtonDown_FirstAndThirdPersonOnly  (int32 button, eControllerType type, CControllerState &state);\n\tvoid  AffectControllerStateOn_ButtonDown_AllStates                (int32 button, eControllerType type, CControllerState &state);\n\tvoid  AffectControllerStateOn_ButtonDown_VehicleAndThirdPersonOnly(int32 button, eControllerType type, CControllerState &state);\n\n\tvoid  UpdateJoyInConfigMenus_ButtonUp(int32 button, int32 padnumber);\n\tvoid  AffectControllerStateOn_ButtonUp(int32 button, eControllerType type);\n\tvoid  AffectControllerStateOn_ButtonUp_All_Player_States(int32 button, eControllerType type, CControllerState &state);\n\t\n\tvoid  AffectPadFromKeyBoard();\n\tvoid  AffectPadFromMouse();\n\t\n\tvoid  ClearSimButtonPressCheckers();\n\n\tbool  GetIsKeyboardKeyDown    (RsKeyCodes keycode);\n\tbool  GetIsKeyboardKeyJustDown(RsKeyCodes keycode);\n\tbool  GetIsMouseButtonDown    (RsKeyCodes keycode);\n\tbool  GetIsMouseButtonUp      (RsKeyCodes keycode);\n\n\n\tvoid DeleteMatchingCommonControls           (e_ControllerAction action, int32 key, eControllerType type);\n\tvoid DeleteMatching3rdPersonControls        (e_ControllerAction action, int32 key, eControllerType type);\n\tvoid DeleteMatching1rst3rdPersonControls    (e_ControllerAction action, int32 key, eControllerType type);\n\tvoid DeleteMatchingVehicleControls          (e_ControllerAction action, int32 key, eControllerType type);\n\tvoid DeleteMatchingVehicle_3rdPersonControls(e_ControllerAction action, int32 key, eControllerType type);\n\tvoid DeleteMatching1rstPersonControls       (e_ControllerAction action, int32 key, eControllerType type);\n\tvoid DeleteMatchingActionInitiators         (e_ControllerAction action, int32 key, eControllerType type);\n\n#ifdef RADIO_SCROLL_TO_PREV_STATION\n\tbool IsAnyVehicleActionAssignedToMouseKey(int32 key);\n#endif \n\n\tbool GetIsKeyBlank(int32 key, eControllerType type);\n\te_ControllerActionType GetActionType(e_ControllerAction action);\n\n\tvoid ClearSettingsAssociatedWithAction        (e_ControllerAction action, eControllerType type);\n\twchar *GetControllerSettingTextWithOrderNumber(e_ControllerAction action, eContSetOrder setorder);\n\twchar *GetControllerSettingTextKeyBoard       (e_ControllerAction action, eControllerType type);\n\twchar *GetControllerSettingTextMouse          (e_ControllerAction action);\n\twchar *GetControllerSettingTextJoystick       (e_ControllerAction action);\n\n\tint32 GetNumOfSettingsForAction(e_ControllerAction action);\n\tvoid  GetWideStringOfCommandKeys(uint16 action, wchar *text, uint16 leight);\n\tint32 GetControllerKeyAssociatedWithAction(e_ControllerAction action, eControllerType type);\n\n\tvoid  UpdateJoyButtonState(int32 padnumber);\n\t\n\tbool  GetIsActionAButtonCombo             (e_ControllerAction action);\n\twchar *GetButtonComboText                 (e_ControllerAction action);\n\tvoid  SetControllerKeyAssociatedWithAction(e_ControllerAction action, int32 key, eControllerType type);\n\tint32 GetMouseButtonAssociatedWithAction  (e_ControllerAction action);\n\tvoid  SetMouseButtonAssociatedWithAction  (e_ControllerAction action, int32 button);\n\tvoid  ResetSettingOrder                   (e_ControllerAction action);\n};\n\n#ifndef RW_GL3\nVALIDATE_SIZE(CControllerConfigManager, 0x143C);\n#endif\n\nextern CControllerConfigManager ControlsManager;"
  },
  {
    "path": "src/core/Crime.h",
    "content": "#pragma once\n\nenum eCrimeType {\n\tCRIME_NONE,\n\tCRIME_POSSESSION_GUN,\n\tCRIME_HIT_PED,\n\tCRIME_HIT_COP,\n\tCRIME_SHOOT_PED,\n\tCRIME_SHOOT_COP,\n\tCRIME_STEAL_CAR,\n\tCRIME_RUN_REDLIGHT,\n\tCRIME_RECKLESS_DRIVING,\n\tCRIME_SPEEDING,\n\tCRIME_RUNOVER_PED,\n\tCRIME_RUNOVER_COP,\n\tCRIME_SHOOT_HELI,\n\tCRIME_PED_BURNED,\n\tCRIME_COP_BURNED,\n\tCRIME_VEHICLE_BURNED,\n\tCRIME_DESTROYED_CESSNA,\n\tCRIME_EXPLOSION,\n\tCRIME_HIT_PED_NASTYWEAPON,\n\tCRIME_HIT_COP_NASTYWEAPON,\n\tNUM_CRIME_TYPES\n};\n\nclass CCrimeBeingQd\n{\npublic:\n\teCrimeType m_nType;\n\tuint32 m_nId;\n\tuint32 m_nTime;\n\tCVector m_vecPosn;\n\tbool m_bReported;\n\tbool m_bPoliceDoesntCare;\n\n\tCCrimeBeingQd() { };\n\t~CCrimeBeingQd() { };\n};\n"
  },
  {
    "path": "src/core/Debug.cpp",
    "content": "#include \"common.h\"\n#include \"RwHelper.h\"\n#include \"Debug.h\"\n#include \"Lines.h\"\n#include \"Font.h\"\n#include \"main.h\"\n#include \"Text.h\"\n\nbool gbDebugStuffInRelease = false;\n\n#define DEBUG_X_POS (300)\n#define DEBUG_Y_POS (41)\n#define DEBUG_LINE_HEIGHT (22)\n\nint16 CDebug::ms_nCurrentTextLine;\nchar CDebug::ms_aTextBuffer[MAX_LINES][MAX_STR_LEN];\n\nvoid\nCDebug::DebugInitTextBuffer()\n{\n\tms_nCurrentTextLine = 0;\n}\n\nvoid\nCDebug::DebugAddText(const char *str)\n{\n\tint32 i = 0;\n\tif (*str != '\\0') {\n\t\twhile (i < MAX_STR_LEN - 1) {\n\t\t\tms_aTextBuffer[ms_nCurrentTextLine][i++] = *(str++);\n\t\t\tif (*str == '\\0')\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tms_aTextBuffer[ms_nCurrentTextLine++][i] = '\\0';\n\tif (ms_nCurrentTextLine >= MAX_LINES)\n\t\tms_nCurrentTextLine = 0;\n}\n\nvoid\nCDebug::DebugDisplayTextBuffer()\n{\n#ifndef MASTER\n\tif (gbDebugStuffInRelease)\n\t{\n\t\tint32 i = 0;\n\t\tint32 y = DEBUG_Y_POS;\n#ifdef FIX_BUGS\n\t\tCFont::SetPropOn();\n\t\tCFont::SetBackgroundOff();\n\t\tCFont::SetScale(1.0f, 1.0f);\n\t\tCFont::SetCentreOff();\n\t\tCFont::SetRightJustifyOff();\n\t\tCFont::SetJustifyOn();\n\t\tCFont::SetRightJustifyWrap(0.0f);\n\t\tCFont::SetBackGroundOnlyTextOff();\n\t\tCFont::SetFontStyle(FONT_STANDARD);\n#else\n\t\t// this is not even readable\n\t\tCFont::SetPropOff();\n\t\tCFont::SetBackgroundOff();\n\t\tCFont::SetScale(1.0f, 1.0f);\n\t\tCFont::SetCentreOff();\n\t\tCFont::SetRightJustifyOn();\n\t\tCFont::SetRightJustifyWrap(0.0f);\n\t\tCFont::SetBackGroundOnlyTextOff();\n\t\tCFont::SetFontStyle(FONT_STANDARD);\n\t\tCFont::SetPropOff();\n#endif\n\t\tdo {\n\t\t\tchar *line;\n\t\t\twhile (true) {\n\t\t\t\tline = ms_aTextBuffer[(ms_nCurrentTextLine + i++) % MAX_LINES];\n\t\t\t\tif (*line != '\\0')\n\t\t\t\t\tbreak;\n\t\t\t\ty += DEBUG_LINE_HEIGHT;\n\t\t\t\tif (i == MAX_LINES) {\n\t\t\t\t\tCFont::DrawFonts();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t\tAsciiToUnicode(line, gUString);\n\t\t\tCFont::SetColor(CRGBA(0, 0, 0, 255));\n\t\t\tCFont::PrintString(DEBUG_X_POS, y-1, gUString);\n\t\t\tCFont::SetColor(CRGBA(255, 128, 128, 255));\n\t\t\tCFont::PrintString(DEBUG_X_POS+1, y, gUString);\n\t\t\ty += DEBUG_LINE_HEIGHT;\n\t\t} while (i != MAX_LINES);\n\t\tCFont::DrawFonts();\n\t}\n#endif\n}\n\n\n// custom\n\nCDebug::ScreenStr CDebug::ms_aScreenStrs[MAX_SCREEN_STRS];\nint CDebug::ms_nScreenStrs;\n\nvoid\nCDebug::DisplayScreenStrings()\n{\n\tint i;\n\t\n\n\tCFont::SetPropOn();\n\tCFont::SetBackgroundOff();\n\tCFont::SetScale(1.0f, 1.0f);\n\tCFont::SetCentreOff();\n\tCFont::SetRightJustifyOff();\n\tCFont::SetJustifyOff();\n\tCFont::SetRightJustifyWrap(0.0f);\n\tCFont::SetWrapx(9999.0f);\n\tCFont::SetBackGroundOnlyTextOff();\n\tCFont::SetFontStyle(FONT_STANDARD);\n\n\tfor(i = 0; i < ms_nScreenStrs; i++){\n/*\n\t\tAsciiToUnicode(ms_aScreenStrs[i].str, gUString);\n\t\tCFont::SetColor(CRGBA(0, 0, 0, 255));\n\t\tCFont::PrintString(ms_aScreenStrs[i].x, ms_aScreenStrs[i].y, gUString);\n\t\tCFont::SetColor(CRGBA(255, 255, 255, 255));\n\t\tCFont::PrintString(ms_aScreenStrs[i].x+1, ms_aScreenStrs[i].y+1, gUString);\n*/\n\t\tObrsPrintfString(ms_aScreenStrs[i].str, ms_aScreenStrs[i].x, ms_aScreenStrs[i].y);\n\t}\n\tCFont::DrawFonts();\n\n\tms_nScreenStrs = 0;\n}\n\nvoid\nCDebug::PrintAt(const char *str, int x, int y)\n{\n\tif(ms_nScreenStrs >= MAX_SCREEN_STRS)\n\t\treturn;\n\tstrncpy(ms_aScreenStrs[ms_nScreenStrs].str, str, 256);\n\tms_aScreenStrs[ms_nScreenStrs].x = x;//*12;\n\tms_aScreenStrs[ms_nScreenStrs].y = y;//*22;\n\tms_nScreenStrs++;\n}\n\nCDebug::Line CDebug::ms_aLines[MAX_DEBUG_LINES];\nint CDebug::ms_nLines;\n\nvoid\nCDebug::AddLine(CVector p1, CVector p2, uint32 c1, uint32 c2)\n{\n\tif(ms_nLines >= MAX_DEBUG_LINES)\n\t\treturn;\n\tms_aLines[ms_nLines].p1 = p1;\n\tms_aLines[ms_nLines].p2 = p2;\n\tms_aLines[ms_nLines].c1 = c1;\n\tms_aLines[ms_nLines].c2 = c2;\n\tms_nLines++;\n}\n\nvoid\nCDebug::DrawLines(void)\n{\n\tint i;\n\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil);\n\tRwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE);\n\tfor(i = 0; i < ms_nLines; i++){\n\t\tLine *l = &ms_aLines[i];\n\t\tCLines::RenderLineWithClipping(l->p1.x, l->p1.y, l->p1.z, l->p2.x, l->p2.y, l->p2.z, l->c1, l->c2);\n\t}\n\tms_nLines = 0;\n}\n"
  },
  {
    "path": "src/core/Debug.h",
    "content": "#pragma once\n\nclass CDebug\n{\n\tenum\n\t{\n\t\tMAX_LINES = 15,\n\t\tMAX_STR_LEN = 80,\n\n\t\tMAX_SCREEN_STRS = 100,\n\t\tMAX_DEBUG_LINES = 100,\n\t};\n\n\tstatic int16 ms_nCurrentTextLine;\n\tstatic char ms_aTextBuffer[MAX_LINES][MAX_STR_LEN];\n\n\t// custom\n\tstruct ScreenStr {\n\t\tint x, y;\n\t\tchar str[256];\n\t};\n\tstatic ScreenStr ms_aScreenStrs[MAX_SCREEN_STRS];\n\tstatic int ms_nScreenStrs;\n\n\tstruct Line {\n\t\tCVector p1, p2;\n\t\tuint32 c1, c2;\n\t};\n\tstatic Line ms_aLines[MAX_DEBUG_LINES];\n\tstatic int ms_nLines;\n\npublic:\n\tstatic void DebugInitTextBuffer();\n\tstatic void DebugDisplayTextBuffer();\n\tstatic void DebugAddText(const char *str);\n\n\t// custom\n\tstatic void PrintAt(const char *str, int x, int y);\n\tstatic void DisplayScreenStrings();\n\n\tstatic void AddLine(CVector p1, CVector p2, uint32 c1, uint32 c2);\n\tstatic void DrawLines(void);\n};\n\nextern bool gbDebugStuffInRelease;\n"
  },
  {
    "path": "src/core/Directory.cpp",
    "content": "#include \"common.h\"\n\n#include \"General.h\"\n#include \"FileMgr.h\"\n#include \"Directory.h\"\n\nCDirectory::CDirectory(int32 maxEntries)\n : numEntries(0), maxEntries(maxEntries)\n{\n\tentries = new DirectoryInfo[maxEntries];\n}\n\nCDirectory::~CDirectory(void)\n{\n\tdelete[] entries;\n}\n\nvoid\nCDirectory::ReadDirFile(const char *filename)\n{\n\tint fd;\n\tDirectoryInfo dirinfo;\n\n\tfd = CFileMgr::OpenFile(filename, \"rb\");\n\twhile(CFileMgr::Read(fd, (char*)&dirinfo, sizeof(dirinfo)))\n\t\tAddItem(dirinfo);\n\tCFileMgr::CloseFile(fd);\n}\n\nbool\nCDirectory::WriteDirFile(const char *filename)\n{\n\tint fd;\n\tsize_t n;\n\tfd = CFileMgr::OpenFileForWriting(filename);\n\tn = CFileMgr::Write(fd, (char*)entries, numEntries*sizeof(DirectoryInfo));\n\tCFileMgr::CloseFile(fd);\n\treturn n == numEntries*sizeof(DirectoryInfo);\n}\n\nvoid\nCDirectory::AddItem(const DirectoryInfo &dirinfo)\n{\n\tassert(numEntries < maxEntries);\n#ifdef FIX_BUGS\n\t// don't add if already exists\n\tuint32 offset, size;\n\tif(FindItem(dirinfo.name, offset, size))\n\t\treturn;\n#endif\n\tentries[numEntries++] = dirinfo;\n}\n\nvoid\nCDirectory::AddItem(const DirectoryInfo &dirinfo, int32 imgId)\n{\n\tDirectoryInfo di = dirinfo;\n\tdi.offset |= imgId<<24;\n\tAddItem(di);\n}\n\nbool\nCDirectory::FindItem(const char *name, uint32 &offset, uint32 &size)\n{\n\tint i;\n\n\tfor(i = 0; i < numEntries; i++)\n\t\tif(!CGeneral::faststricmp(entries[i].name, name)){\n\t\t\toffset = entries[i].offset;\n\t\t\tsize = entries[i].size;\n\t\t\treturn true;\n\t\t}\n\treturn false;\n}\n"
  },
  {
    "path": "src/core/Directory.h",
    "content": "#pragma once\n\nclass CDirectory\n{\npublic:\n\tstruct DirectoryInfo {\n\t\tuint32 offset;\n\t\tuint32 size;\n\t\tchar name[24];\n\t};\n\tDirectoryInfo *entries;\n\tint32 maxEntries;\n\tint32 numEntries;\n\n\tCDirectory(int32 maxEntries);\n\t~CDirectory(void);\n\n\tvoid ReadDirFile(const char *filename);\n\tbool WriteDirFile(const char *filename);\n\tvoid AddItem(const DirectoryInfo &dirinfo);\n\tvoid AddItem(const DirectoryInfo &dirinfo, int32 imgId);\n\tbool FindItem(const char *name, uint32 &offset, uint32 &size);\n};\n"
  },
  {
    "path": "src/core/EventList.cpp",
    "content": "#include \"common.h\"\n\n#include \"Pools.h\"\n#include \"ModelIndices.h\"\n#include \"World.h\"\n#include \"Wanted.h\"\n#include \"EventList.h\"\n#include \"Messages.h\"\n#include \"Text.h\"\n#include \"main.h\"\n#include \"Accident.h\"\n\nint32 CEventList::ms_nFirstFreeSlotIndex;\nCEvent gaEvent[NUMEVENTS];\n\nenum\n{\n\tEVENT_STATE_0,\n\tEVENT_STATE_CANDELETE,\n\tEVENT_STATE_CLEAR,\n};\n\nvoid\nCEventList::Initialise(void)\n{\n\tint i;\n\n\tdebug(\"Initialising CEventList...\");\n\tfor(i = 0; i < NUMEVENTS; i++){\n\t\tgaEvent[i].type = EVENT_NULL;\n\t\tgaEvent[i].entityType = EVENT_ENTITY_NONE;\n\t\tgaEvent[i].entityRef = 0;\n\t\tgaEvent[i].posn.x = 0.0f;\n\t\tgaEvent[i].posn.y = 0.0f;\n\t\tgaEvent[i].posn.z = 0.0f;\n\t\tgaEvent[i].timeout = 0;\n\t\tgaEvent[i].state = EVENT_STATE_0;\n\t}\n\tms_nFirstFreeSlotIndex = 0;\n}\n\nvoid\nCEventList::Update(void)\n{\n\tint i;\n\n\tms_nFirstFreeSlotIndex = 0;\n\tfor(i = 0; i < NUMEVENTS; i++){\n\t\tif(gaEvent[i].type == EVENT_NULL)\n\t\t\tcontinue;\n\t\tif(CTimer::GetTimeInMilliseconds() > gaEvent[i].timeout || gaEvent[i].state == EVENT_STATE_CANDELETE){\n\t\t\tgaEvent[i].type = EVENT_NULL;\n\t\t\tgaEvent[i].state = EVENT_STATE_0;\n\t\t}\n\t\tif(gaEvent[i].state == EVENT_STATE_CLEAR)\n\t\t\tgaEvent[i].state = EVENT_STATE_CANDELETE;\n\t}\n}\n\nvoid\nCEventList::RegisterEvent(eEventType type, eEventEntity entityType, CEntity *ent, CPed *criminal, int32 timeout)\n{\n\tint i;\n\tint ref;\n\tbool copsDontCare;\n\n#ifdef SQUEEZE_PERFORMANCE\n\tif (type == EVENT_INJURED_PED) {\n\t\tgAccidentManager.ReportAccident((CPed*)ent);\n\t\treturn;\n\t}\n#endif\n\n\tcopsDontCare = false;\n\tswitch(entityType){\n\tcase EVENT_ENTITY_PED:\n\t\tref = CPools::GetPedRef((CPed*)ent);\n\t\tbreak;\n\tcase EVENT_ENTITY_VEHICLE:\n\t\tref = CPools::GetVehicleRef((CVehicle*)ent);\n\t\tbreak;\n\tcase EVENT_ENTITY_OBJECT:\n\t\tref = CPools::GetObjectRef((CObject*)ent);\n\t\tbreak;\n\tdefault:\n\t\tError(\"Undefined entity type, RegisterEvent, EventList.cpp\");\n\t\tref = 0;\n\t\tbreak;\n\t}\n\n\t// only update time if event exists already\n\tfor(i = 0; i < NUMEVENTS; i++)\n\t\tif(gaEvent[i].type == type &&\n\t\t   gaEvent[i].entityType == entityType &&\n\t\t   gaEvent[i].entityRef == ref){\n\t\t\tgaEvent[i].timeout = CTimer::GetTimeInMilliseconds() + timeout;\n\t\t\treturn;\n\t\t}\n\n\tfor(i = ms_nFirstFreeSlotIndex; i < NUMEVENTS; i++)\n\t\tif(gaEvent[i].type == EVENT_NULL){\n\t\t\tms_nFirstFreeSlotIndex = i;\n\t\t\tbreak;\n\t\t}\n\tif(i < NUMEVENTS){\n\t\tgaEvent[i].type = type;\n\t\tgaEvent[i].entityType = entityType;\n\t\tgaEvent[i].timeout = CTimer::GetTimeInMilliseconds() + timeout;\n\t\tgaEvent[i].entityRef = ref;\n\t\tgaEvent[i].posn = ent->GetPosition();\n\t\tgaEvent[i].criminal = criminal;\n\t\tif(gaEvent[i].criminal)\n\t\t\tgaEvent[i].criminal->RegisterReference((CEntity**)&gaEvent[i].criminal);\n\t\tif(type == EVENT_GUNSHOT)\n\t\t\tgaEvent[i].state = EVENT_STATE_CLEAR;\n\t\telse\n\t\t\tgaEvent[i].state = EVENT_STATE_0;\n\t}\n\n\tif(criminal == FindPlayerPed())\n\t\tReportCrimeForEvent(type, (intptr)ent, copsDontCare);\n}\n\nvoid\nCEventList::RegisterEvent(eEventType type, CVector posn, int32 timeout)\n{\n\tint i;\n\n\t// only update time if event exists already\n\tfor(i = 0; i < NUMEVENTS; i++)\n\t\tif(gaEvent[i].type == type &&\n\t\t   gaEvent[i].posn.x == posn.x &&\n\t\t   gaEvent[i].posn.y == posn.y &&\n\t\t   gaEvent[i].posn.z == posn.z &&\n\t\t   gaEvent[i].entityType == EVENT_ENTITY_NONE){\n\t\t\tgaEvent[i].timeout = CTimer::GetTimeInMilliseconds() + timeout;\n\t\t\treturn;\n\t\t}\n\n\tfor(i = ms_nFirstFreeSlotIndex; i < NUMEVENTS; i++)\n\t\tif(gaEvent[i].type == EVENT_NULL){\n\t\t\tms_nFirstFreeSlotIndex = i;\n\t\t\tbreak;\n\t\t}\n\tif(i < NUMEVENTS){\n\t\tgaEvent[i].type = type;\n\t\tgaEvent[i].entityType = EVENT_ENTITY_NONE;\n\t\tgaEvent[i].timeout = CTimer::GetTimeInMilliseconds() + timeout;\n\t\tgaEvent[i].posn = posn;\n\t\tgaEvent[i].entityRef = 0;\n\t\tif(type == EVENT_GUNSHOT)\n\t\t\tgaEvent[i].state = EVENT_STATE_CLEAR;\n\t\telse\n\t\t\tgaEvent[i].state = EVENT_STATE_0;\n\t}\n}\n\nbool\nCEventList::GetEvent(eEventType type, int32 *event)\n{\n\tint i;\n\tfor(i = 0; i < NUMEVENTS; i++)\n\t\tif(gaEvent[i].type == type){\n\t\t\t*event = i;\n\t\t\treturn true;\n\t\t}\n\treturn false;\n}\n\nvoid\nCEventList::ClearEvent(int32 event)\n{\n\tif(gaEvent[event].state != EVENT_STATE_CANDELETE)\n\t\tgaEvent[event].state = EVENT_STATE_CLEAR;\n}\n\nbool\nCEventList::FindClosestEvent(eEventType type, CVector posn, int32 *event)\n{\n\tint i;\n\tfloat dist;\n\tbool found = false;\n\tfloat mindist = 60.0f;\n\n\tfor(i = 0; i < NUMEVENTS; i++){\n\t\tif(gaEvent[i].type != type)\n\t\t\tcontinue;\n\t\tdist = (posn - gaEvent[i].posn).Magnitude();\n\t\tif(dist < mindist){\n\t\t\tmindist = dist;\n\t\t\tfound = true;\n\t\t\t*event = i;\n\t\t}\n\t}\n\treturn found;\n}\n\nvoid\nCEventList::ReportCrimeForEvent(eEventType type, intptr crimeId, bool copsDontCare)\n{\n\teCrimeType crime;\n\tswitch(type){\n\tcase EVENT_ASSAULT: crime = CRIME_HIT_PED; break;\n\tcase EVENT_RUN_REDLIGHT: crime = CRIME_RUN_REDLIGHT; break;\n\tcase EVENT_ASSAULT_POLICE: crime = CRIME_HIT_COP; break;\n\tcase EVENT_GUNSHOT: crime = CRIME_POSSESSION_GUN; break;\n\tcase EVENT_STEAL_CAR: crime = CRIME_STEAL_CAR; break;\n\tcase EVENT_HIT_AND_RUN: crime = CRIME_RUNOVER_PED; break;\n\tcase EVENT_HIT_AND_RUN_COP: crime = CRIME_RUNOVER_COP; break;\n\tcase EVENT_SHOOT_PED: crime = CRIME_SHOOT_PED; break;\n\tcase EVENT_SHOOT_COP: crime = CRIME_SHOOT_COP; break;\n\tcase EVENT_EXPLOSION: crime = CRIME_EXPLOSION; break;\n\tcase EVENT_PED_SET_ON_FIRE: crime = CRIME_PED_BURNED; break;\n\tcase EVENT_COP_SET_ON_FIRE: crime = CRIME_COP_BURNED; break;\n\tcase EVENT_CAR_SET_ON_FIRE: crime = CRIME_VEHICLE_BURNED; break;\n\tcase EVENT_ASSAULT_NASTYWEAPON: crime = CRIME_HIT_PED_NASTYWEAPON; break;\n\tcase EVENT_ASSAULT_NASTYWEAPON_POLICE: crime = CRIME_HIT_COP_NASTYWEAPON; break;\n\tdefault: crime = CRIME_NONE; break;\n\t}\n\t\n\tif (crime == CRIME_HIT_PED && IsPedPointerValid((CPed*)crimeId) && FindPlayerPed()->m_pWanted->GetWantedLevel() == 0 && ((CPed*)crimeId)->bBeingChasedByPolice) {\n\t\tif (!((CPed*)crimeId)->DyingOrDead()) {\n\t\t\tCMessages::AddBigMessage(TheText.Get(\"GOODBOY\"), 5000, 0);\n\t\t\tCWorld::Players[CWorld::PlayerInFocus].m_nMoney += 50;\n\t\t}\n\t\treturn;\n\t}\n\n\tif(crime == CRIME_NONE)\n\t\treturn;\n\n#ifdef FIX_BUGS\n\tCVector playerPedCoors = FindPlayerCoors();\n#else\n\tCVector playerPedCoors = FindPlayerPed()->GetPosition();\n#endif\n\tCVector playerCoors = FindPlayerCoors();\n\n\tif(CWanted::WorkOutPolicePresence(playerCoors, 14.0f) != 0 ||\n\t\tCGame::germanGame && (crime == CRIME_SHOOT_PED || crime == CRIME_SHOOT_COP || crime == CRIME_COP_BURNED || crime == CRIME_VEHICLE_BURNED)){\n\t\tFindPlayerPed()->m_pWanted->RegisterCrime_Immediately(crime, playerPedCoors, (uint32)crimeId, copsDontCare);\n\t\tFindPlayerPed()->m_pWanted->SetWantedLevelNoDrop(1);\n\t}else\n\t\tFindPlayerPed()->m_pWanted->RegisterCrime(crime, playerPedCoors, (uint32)crimeId, copsDontCare);\n\n\tif(type == EVENT_ASSAULT_POLICE)\n\t\tFindPlayerPed()->SetWantedLevelNoDrop(1);\n\tif(type == EVENT_SHOOT_COP || type == EVENT_ASSAULT_NASTYWEAPON_POLICE)\n\t\tFindPlayerPed()->SetWantedLevelNoDrop(2);\n\n}\n"
  },
  {
    "path": "src/core/EventList.h",
    "content": "#pragma once\n\nclass CEntity;\nclass CPed;\n\nenum eEventType\n{\n\tEVENT_NULL,\n\tEVENT_ASSAULT,\n\tEVENT_RUN_REDLIGHT,\n\tEVENT_ASSAULT_POLICE,\n\tEVENT_GUNSHOT,\n\tEVENT_INJURED_PED,\n\tEVENT_DEAD_PED,\n\tEVENT_FIRE,\n\tEVENT_STEAL_CAR,\n\tEVENT_HIT_AND_RUN,\n\tEVENT_HIT_AND_RUN_COP,\n\tEVENT_SHOOT_PED,\n\tEVENT_SHOOT_COP,\n\tEVENT_EXPLOSION,\n\tEVENT_PED_SET_ON_FIRE,\n\tEVENT_COP_SET_ON_FIRE,\n\tEVENT_CAR_SET_ON_FIRE,\n\tEVENT_ASSAULT_NASTYWEAPON,\n\tEVENT_ASSAULT_NASTYWEAPON_POLICE,\n\tEVENT_UNK, // Not on SA it seems\n\tEVENT_ICECREAM,\n\tEVENT_ATM,\n\tEVENT_SHOPSTALL,\n\tEVENT_SHOPWINDOW,\n\tEVENT_LAST_EVENT\n};\n\nenum eEventEntity\n{\n\tEVENT_ENTITY_NONE,\n\tEVENT_ENTITY_PED,\n\tEVENT_ENTITY_VEHICLE,\n\tEVENT_ENTITY_OBJECT\n};\n\nstruct CEvent\n{\n\teEventType type;\n\teEventEntity entityType;\n\tint32 entityRef;\n\tCPed *criminal;\n\tCVector posn;\n\tuint32 timeout;\n\tint32 state;\n};\n\nclass CEventList\n{\n\tstatic int32 ms_nFirstFreeSlotIndex;\npublic:\n\tstatic void Initialise(void);\n\tstatic void Update(void);\n\tstatic void RegisterEvent(eEventType type, eEventEntity entityType, CEntity *ent, CPed *criminal, int32 timeout);\n\tstatic void RegisterEvent(eEventType type, CVector posn, int32 timeout);\n\tstatic bool GetEvent(eEventType type, int32 *event);\n\tstatic void ClearEvent(int32 event);\n\tstatic bool FindClosestEvent(eEventType type, CVector posn, int32 *event);\n\tstatic void ReportCrimeForEvent(eEventType type, intptr, bool);\n};\n\nextern CEvent gaEvent[NUMEVENTS];"
  },
  {
    "path": "src/core/FileLoader.cpp",
    "content": "#include \"common.h\"\n#include <ctype.h>\n#include \"main.h\"\n\n#include \"General.h\"\n#include \"Quaternion.h\"\n#include \"ModelInfo.h\"\n#include \"ModelIndices.h\"\n#include \"TempColModels.h\"\n#include \"VisibilityPlugins.h\"\n#include \"FileMgr.h\"\n#include \"HandlingMgr.h\"\n#include \"CarCtrl.h\"\n#include \"PedType.h\"\n#include \"AnimManager.h\"\n#include \"Game.h\"\n#include \"RwHelper.h\"\n#include \"NodeName.h\"\n#include \"TxdStore.h\"\n#include \"PathFind.h\"\n#include \"ObjectData.h\"\n#include \"DummyObject.h\"\n#include \"World.h\"\n#include \"Zones.h\"\n#include \"ZoneCull.h\"\n#include \"CdStream.h\"\n#include \"FileLoader.h\"\n#include \"MemoryHeap.h\"\n#include \"Streaming.h\"\n#include \"ColStore.h\"\n#include \"Occlusion.h\"\n\nchar CFileLoader::ms_line[256];\n\nconst char*\nGetFilename(const char *filename)\n{\n\tchar *s = strrchr((char*)filename, '\\\\');\n\treturn s ? s+1 : filename;\n}\n\nvoid\nLoadingScreenLoadingFile(const char *filename)\n{\n\tsprintf(gString, \"Loading %s\", GetFilename(filename));\n\tLoadingScreen(\"Loading the Game\", gString, nil);\n}\n\nvoid\nCFileLoader::LoadLevel(const char *filename)\n{\n\tint fd;\n\tRwTexDictionary *savedTxd;\n\tbool objectsLoaded;\n\tchar *line;\n\tchar txdname[64];\n\n\tsavedTxd = RwTexDictionaryGetCurrent();\n\tobjectsLoaded = false;\n\tif(savedTxd == nil){\n\t\tsavedTxd = RwTexDictionaryCreate();\n\t\tRwTexDictionarySetCurrent(savedTxd);\n\t}\n\tfd = CFileMgr::OpenFile(filename, \"r\");\n\tassert(fd > 0);\n\n\tfor(line = LoadLine(fd); line; line = LoadLine(fd)){\n\t\tif(*line == '#')\n\t\t\tcontinue;\n\n\t\tif(strncmp(line, \"EXIT\", 4) == 0)\n\t\t\tbreak;\n\n\t\tif(strncmp(line, \"IMAGEPATH\", 9) == 0){\n\t\t\tRwImageSetPath(line + 10);\n\t\t}else if(strncmp(line, \"TEXDICTION\", 10) == 0){\n\t\t\tPUSH_MEMID(MEMID_TEXTURES);\n\t\t\tstrcpy(txdname, line+11);\n\t\t\tLoadingScreenLoadingFile(txdname);\n\t\t\tRwTexDictionary *txd = LoadTexDictionary(txdname);\n\t\t\tAddTexDictionaries(savedTxd, txd);\n\t\t\tRwTexDictionaryDestroy(txd);\n\t\t\tPOP_MEMID();\n\t\t}else if(strncmp(line, \"COLFILE\", 7) == 0){\n\t\t\tLoadingScreenLoadingFile(line+10);\n\t\t\tLoadCollisionFile(line+10, 0);\n\t\t}else if(strncmp(line, \"MODELFILE\", 9) == 0){\n\t\t\tLoadingScreenLoadingFile(line + 10);\n\t\t\tLoadModelFile(line + 10);\n\t\t}else if(strncmp(line, \"HIERFILE\", 8) == 0){\n\t\t\tLoadingScreenLoadingFile(line + 9);\n\t\t\tLoadClumpFile(line + 9);\n\t\t}else if(strncmp(line, \"IDE\", 3) == 0){\n\t\t\tLoadingScreenLoadingFile(line + 4);\n\t\t\tLoadObjectTypes(line + 4);\n\t\t}else if(strncmp(line, \"IPL\", 3) == 0){\n\t\t\tif(!objectsLoaded){\n\t\t\t\tLoadingScreenLoadingFile(\"Collision\");\n\t\t\t\tPUSH_MEMID(MEMID_WORLD);\n\t\t\t\tCObjectData::Initialise(\"DATA\\\\OBJECT.DAT\");\n\t\t\t\tCStreaming::Init();\n\t\t\t\tPOP_MEMID();\n\t\t\t\tPUSH_MEMID(MEMID_COLLISION);\n\t\t\t\tCColStore::LoadAllCollision();\n\t\t\t\tPOP_MEMID();\n\t\t\t\tfor(int i = 0; i < MODELINFOSIZE; i++)\n\t\t\t\t\tif(CModelInfo::GetModelInfo(i))\n\t\t\t\t\t\tCModelInfo::GetModelInfo(i)->ConvertAnimFileIndex();\n\t\t\t\tobjectsLoaded = true;\n\t\t\t}\n\t\t\tPUSH_MEMID(MEMID_WORLD);\n\t\t\tLoadingScreenLoadingFile(line + 4);\n\t\t\tLoadScene(line + 4);\n\t\t\tPOP_MEMID();\n\t\t}else if(strncmp(line, \"SPLASH\", 6) == 0){\n#ifndef DISABLE_LOADING_SCREEN\n\t\t\tLoadSplash(GetRandomSplashScreen());\n#endif\n#ifndef GTA_PS2\n\t\t}else if(strncmp(line, \"CDIMAGE\", 7) == 0){\n\t\t\tCdStreamAddImage(line + 8);\n#endif\n\t\t}\n\t}\n\n\tCFileMgr::CloseFile(fd);\n\tRwTexDictionarySetCurrent(savedTxd);\n\n\tint i;\n\tfor(i = 1; i < COLSTORESIZE; i++)\n\t\tif(CColStore::GetSlot(i))\n\t\t\tCColStore::GetBoundingBox(i).Grow(120.0f);\n\tCWorld::RepositionCertainDynamicObjects();\n\tCColStore::RemoveAllCollision();\n}\n\nchar*\nCFileLoader::LoadLine(int fd)\n{\n\tint i;\n\tchar *line;\n\n\tif(CFileMgr::ReadLine(fd, ms_line, 256) == false)\n\t\treturn nil;\n\tfor(i = 0; ms_line[i] != '\\0'; i++)\n\t\tif(ms_line[i] < ' ' || ms_line[i] == ',')\n\t\t\tms_line[i] = ' ';\n\tfor(line = ms_line; *line <= ' ' && *line != '\\0'; line++);\n\treturn line;\n}\n\nRwTexDictionary*\nCFileLoader::LoadTexDictionary(const char *filename)\n{\n\tRwTexDictionary *txd;\n\tRwStream *stream;\n\n\ttxd = nil;\n\tstream = RwStreamOpen(rwSTREAMFILENAME, rwSTREAMREAD, filename);\n\tdebug(\"Loading texture dictionary file %s\\n\", filename);\n\tif(stream){\n\t\tif(RwStreamFindChunk(stream, rwID_TEXDICTIONARY, nil, nil))\n\t\t\ttxd = RwTexDictionaryGtaStreamRead(stream);\n\t\tRwStreamClose(stream, nil);\n\t}\n\tif(txd == nil)\n\t\ttxd = RwTexDictionaryCreate();\n\treturn txd;\n}\n\nstruct ColHeader\n{\n\tuint32 ident;\n\tuint32 size;\n};\n\nvoid\nCFileLoader::LoadCollisionFile(const char *filename, uint8 colSlot)\n{\n\tint fd;\n\tchar modelname[24];\n\tCBaseModelInfo *mi;\n\tColHeader header;\n\n\tPUSH_MEMID(MEMID_COLLISION);\n\n\tdebug(\"Loading collision file %s\\n\", filename);\n\tfd = CFileMgr::OpenFile(filename, \"rb\");\n\tassert(fd > 0);\n\n\twhile(CFileMgr::Read(fd, (char*)&header, sizeof(header))){\n\t\tassert(header.ident == 'LLOC');\n\t\tCFileMgr::Read(fd, (char*)work_buff, header.size);\n\t\tmemcpy(modelname, work_buff, 24);\n\n\t\tmi = CModelInfo::GetModelInfo(modelname, nil);\n\t\tif(mi){\n\t\t\tif(mi->GetColModel() && mi->DoesOwnColModel()){\n\t\t\t\tLoadCollisionModel(work_buff+24, *mi->GetColModel(), modelname);\n\t\t\t}else{\n\t\t\t\tCColModel *model = new CColModel;\n\t\t\t\tmodel->level = colSlot;\n\t\t\t\tLoadCollisionModel(work_buff+24, *model, modelname);\n\t\t\t\tmi->SetColModel(model, true);\n\t\t\t}\n\t\t}else{\n\t\t\tdebug(\"colmodel %s can't find a modelinfo\\n\", modelname);\n\t\t}\n\t}\n\n\tCFileMgr::CloseFile(fd);\n\n\tPOP_MEMID();\n}\n\n\nbool\nCFileLoader::LoadCollisionFileFirstTime(uint8 *buffer, uint32 size, uint8 colSlot)\n{\n\tuint32 modelsize;\n\tchar modelname[24];\n\tCBaseModelInfo *mi;\n\tColHeader *header;\n\tint modelIndex;\n\n\twhile(size > 8){\n\t\theader = (ColHeader*)buffer;\n\t\tmodelsize = header->size;\n\t\tif(header->ident != 'LLOC')\n\t\t\treturn size-8 < CDSTREAM_SECTOR_SIZE;\n\t\tmemcpy(modelname, buffer+8, 24);\n\t\tmemcpy(work_buff, buffer+32, modelsize-24);\n\t\tsize -= 32 + (modelsize-24);\n\t\tbuffer += 32 + (modelsize-24);\n\t\tif(modelsize > 15*1024)\n\t\t\tdebug(\"colmodel %s is huge, size %d\\n\", modelname, modelsize);\n\n\t\tmi = CModelInfo::GetModelInfo(modelname, &modelIndex);\n\t\tif(mi){\n\t\t\tCColStore::IncludeModelIndex(colSlot, modelIndex);\n\t\t\tCColModel *model = new CColModel;\n\t\t\tmodel->level = colSlot;\n\t\t\tLoadCollisionModel(work_buff, *model, modelname);\n\t\t\tmi->SetColModel(model, true);\n\t\t}else{\n\t\t\tdebug(\"colmodel %s can't find a modelinfo\\n\", modelname);\n\t\t}\n\t}\n\treturn true;\n}\n\nbool\nCFileLoader::LoadCollisionFile(uint8 *buffer, uint32 size, uint8 colSlot)\n{\n\tuint32 modelsize;\n\tchar modelname[24];\n\tCBaseModelInfo *mi;\n\tColHeader *header;\n\n\twhile(size > 8){\n\t\theader = (ColHeader*)buffer;\n\t\tmodelsize = header->size;\n\t\tif(header->ident != 'LLOC')\n\t\t\treturn size-8 < CDSTREAM_SECTOR_SIZE;\n\t\tmemcpy(modelname, buffer+8, 24);\n\t\tmemcpy(work_buff, buffer+32, modelsize-24);\n\t\tsize -= 32 + (modelsize-24);\n\t\tbuffer += 32 + (modelsize-24);\n\t\tif(modelsize > 15*1024)\n\t\t\tdebug(\"colmodel %s is huge, size %d\\n\", modelname, modelsize);\n\n\t\tmi = CModelInfo::GetModelInfo(modelname, CColStore::GetSlot(colSlot)->minIndex, CColStore::GetSlot(colSlot)->maxIndex);\n\t\tif(mi){\n\t\t\tif(mi->GetColModel()){\n\t\t\t\tLoadCollisionModel(work_buff, *mi->GetColModel(), modelname);\n\t\t\t}else{\n\t\t\t\tCColModel *model = new CColModel;\n\t\t\t\tmodel->level = colSlot;\n\t\t\t\tLoadCollisionModel(work_buff, *model, modelname);\n\t\t\t\tmi->SetColModel(model, true);\n\t\t\t}\n\t\t}else{\n\t\t\tdebug(\"colmodel %s can't find a modelinfo\\n\", modelname);\n\t\t}\n\t}\n\treturn true;\n}\n\nvoid\nCFileLoader::LoadCollisionModel(uint8 *buf, CColModel &model, char *modelname)\n{\n\tint i;\n\n\tmodel.boundingSphere.radius = *(float*)(buf);\n\tmodel.boundingSphere.center.x = *(float*)(buf+4);\n\tmodel.boundingSphere.center.y = *(float*)(buf+8);\n\tmodel.boundingSphere.center.z = *(float*)(buf+12);\n\tmodel.boundingBox.min.x = *(float*)(buf+16);\n\tmodel.boundingBox.min.y = *(float*)(buf+20);\n\tmodel.boundingBox.min.z = *(float*)(buf+24);\n\tmodel.boundingBox.max.x = *(float*)(buf+28);\n\tmodel.boundingBox.max.y = *(float*)(buf+32);\n\tmodel.boundingBox.max.z = *(float*)(buf+36);\n\tmodel.numSpheres = *(int16*)(buf+40);\n\tbuf += 44;\n\tif(model.numSpheres > 0){\n\t\tmodel.spheres = (CColSphere*)RwMalloc(model.numSpheres*sizeof(CColSphere));\n\t\tREGISTER_MEMPTR(&model.spheres);\n\t\tfor(i = 0; i < model.numSpheres; i++){\n\t\t\tmodel.spheres[i].Set(*(float*)buf, *(CVector*)(buf+4), buf[16], buf[17]);\n\t\t\tbuf += 20;\n\t\t}\n\t}else\n\t\tmodel.spheres = nil;\n\n\tmodel.numLines = *(int16*)buf;\n\tbuf += 4;\n\tif(model.numLines > 0){\n\t\t//model.lines = (CColLine*)RwMalloc(model.numLines*sizeof(CColLine));\n\t\tREGISTER_MEMPTR(&model.lines);\n\t\tfor(i = 0; i < model.numLines; i++){\n\t\t\t//model.lines[i].Set(*(CVector*)buf, *(CVector*)(buf+12));\n\t\t\tbuf += 24;\n\t\t}\n\t}else\n\t\tmodel.lines = nil;\n\tmodel.numLines = 0;\n\tmodel.lines = nil;\n\n\tmodel.numBoxes = *(int16*)buf;\n\tbuf += 4;\n\tif(model.numBoxes > 0){\n\t\tmodel.boxes = (CColBox*)RwMalloc(model.numBoxes*sizeof(CColBox));\n\t\tREGISTER_MEMPTR(&model.boxes);\n\t\tfor(i = 0; i < model.numBoxes; i++){\n\t\t\tmodel.boxes[i].Set(*(CVector*)buf, *(CVector*)(buf+12), buf[24], buf[25]);\n\t\t\tbuf += 28;\n\t\t}\n\t}else\n\t\tmodel.boxes = nil;\n\n\tint32 numVertices = *(int16*)buf;\n\tbuf += 4;\n\tif(numVertices > 0){\n\t\tmodel.vertices = (CompressedVector*)RwMalloc(numVertices*sizeof(CompressedVector));\n\t\tREGISTER_MEMPTR(&model.vertices);\n\t\tfor(i = 0; i < numVertices; i++){\n\t\t\tmodel.vertices[i].Set(*(float*)buf, *(float*)(buf+4), *(float*)(buf+8));\n#if 0\n\t\t\tif(Abs(*(float*)buf) >= 256.0f ||\n\t\t\t   Abs(*(float*)(buf+4)) >= 256.0f ||\n\t\t\t   Abs(*(float*)(buf+8)) >= 256.0f)\n\t\t\t\tprintf(\"%s:Collision volume too big\\n\", modelname);\n#endif\n\t\t\tbuf += 12;\n\t\t}\n\t}else\n\t\tmodel.vertices = nil;\n\n\tmodel.numTriangles = *(int16*)buf;\n\tbuf += 4;\n\tif(model.numTriangles > 0){\n\t\tmodel.triangles = (CColTriangle*)RwMalloc(model.numTriangles*sizeof(CColTriangle));\n\t\tREGISTER_MEMPTR(&model.triangles);\n\t\tfor(i = 0; i < model.numTriangles; i++){\n\t\t\tmodel.triangles[i].Set(*(int32*)buf, *(int32*)(buf+4), *(int32*)(buf+8), buf[12]);\n\t\t\tbuf += 16;\n\t\t}\n\t}else\n\t\tmodel.triangles = nil;\n}\n\nstatic void\nGetNameAndLOD(char *nodename, char *name, int *n)\n{\n\tchar *underscore = nil;\n\tfor(char *s = nodename; *s != '\\0'; s++){\n\t\tif(s[0] == '_' && (s[1] == 'l' || s[1] == 'L') && isdigit(s[2]))\n\t\t\tunderscore = s;\n\t}\n\tif(underscore){\n\t\tstrncpy(name, nodename, underscore - nodename);\n\t\tname[underscore - nodename] = '\\0';\n\t\t*n = atoi(underscore + 2);\n\t}else{\n\t\tstrncpy(name, nodename, 24);\n\t\t*n = 0;\n\t}\n}\n\nRpAtomic*\nCFileLoader::FindRelatedModelInfoCB(RpAtomic *atomic, void *data)\n{\n\tCSimpleModelInfo *mi;\n\tchar *nodename, name[24];\n\tint n;\n\tRpClump *clump = (RpClump*)data;\n\n\tnodename = GetFrameNodeName(RpAtomicGetFrame(atomic));\n\tGetNameAndLOD(nodename, name, &n);\n\tmi = (CSimpleModelInfo*)CModelInfo::GetModelInfo(name, nil);\n\tif(mi){\n\t\tassert(mi->IsSimple());\n\t\tCVisibilityPlugins::SetAtomicRenderCallback(atomic, nil);\n\t\tmi->SetAtomic(n, atomic);\n\t\tRpClumpRemoveAtomic(clump, atomic);\n\t\tRpAtomicSetFrame(atomic, RwFrameCreate());\n\t\tCVisibilityPlugins::SetAtomicModelInfo(atomic, mi);\n\t}else{\n\t\tdebug(\"Can't find Atomic %s\\n\", name);\n\t}\n\n\treturn atomic;\n}\n\n#ifdef LIBRW\nvoid\nInitClump(RpClump *clump)\n{\n\tRpClumpForAllAtomics(clump, ConvertPlatformAtomic, nil);\n}\n#else\n#define InitClump(clump)\n#endif\n\nvoid\nCFileLoader::LoadModelFile(const char *filename)\n{\n\tRwStream *stream;\n\tRpClump *clump;\n\n\tdebug(\"Loading model file %s\\n\", filename);\n\tstream = RwStreamOpen(rwSTREAMFILENAME, rwSTREAMREAD, filename);\n\tif(RwStreamFindChunk(stream, rwID_CLUMP, nil, nil)){\n\t\tclump = RpClumpStreamRead(stream);\n\t\tif(clump){\n\t\t\tInitClump(clump);\n\t\t\tRpClumpForAllAtomics(clump, FindRelatedModelInfoCB, clump);\n\t\t\tRpClumpDestroy(clump);\n\t\t}\n\t}\n\tRwStreamClose(stream, nil);\n}\n\nvoid\nCFileLoader::LoadClumpFile(const char *filename)\n{\n\tRwStream *stream;\n\tRpClump *clump;\n\tchar *nodename, name[24];\n\tint n;\n\tCClumpModelInfo *mi;\n\n\tdebug(\"Loading model file %s\\n\", filename);\n\tstream = RwStreamOpen(rwSTREAMFILENAME, rwSTREAMREAD, filename);\n\twhile(RwStreamFindChunk(stream, rwID_CLUMP, nil, nil)){\n\t\tclump = RpClumpStreamRead(stream);\n\t\tif(clump){\n\t\t\tnodename = GetFrameNodeName(RpClumpGetFrame(clump));\n\t\t\tGetNameAndLOD(nodename, name, &n);\n\t\t\tmi = (CClumpModelInfo*)CModelInfo::GetModelInfo(name, nil);\n\t\t\tif(mi){\n\t\t\t\tInitClump(clump);\n\t\t\t\tassert(mi->IsClump());\n\t\t\t\tmi->SetClump(clump);\n\t\t\t}else\n\t\t\t\tRpClumpDestroy(clump);\n\t\t}\n\t}\n\tRwStreamClose(stream, nil);\n}\n\nbool\nCFileLoader::LoadClumpFile(RwStream *stream, uint32 id)\n{\n\tRpClump *clump;\n\tCClumpModelInfo *mi;\n\n\tif(!RwStreamFindChunk(stream, rwID_CLUMP, nil, nil))\n\t\treturn false;\n\tclump = RpClumpStreamRead(stream);\n\tif(clump == nil)\n\t\treturn false;\n\tInitClump(clump);\n\tmi = (CClumpModelInfo*)CModelInfo::GetModelInfo(id);\n\tmi->SetClump(clump);\n\treturn true;\n}\n\nbool\nCFileLoader::StartLoadClumpFile(RwStream *stream, uint32 id)\n{\n\tif(RwStreamFindChunk(stream, rwID_CLUMP, nil, nil)){\n\t\tprintf(\"Start loading %s\\n\", CModelInfo::GetModelInfo(id)->GetModelName());\n\t\treturn RpClumpGtaStreamRead1(stream);\n\t}else{\n\t\tprintf(\"FAILED\\n\");\n\t\treturn false;\n\t}\n}\n\nbool\nCFileLoader::FinishLoadClumpFile(RwStream *stream, uint32 id)\n{\n\tRpClump *clump;\n\tCClumpModelInfo *mi;\n\n\tprintf(\"Finish loading %s\\n\", CModelInfo::GetModelInfo(id)->GetModelName());\n\tclump = RpClumpGtaStreamRead2(stream);\n\n\tif(clump){\n\t\tInitClump(clump);\n\t\tmi = (CClumpModelInfo*)CModelInfo::GetModelInfo(id);\n\t\tmi->SetClump(clump);\n\t\treturn true;\n\t}else{\n\t\tprintf(\"FAILED\\n\");\n\t\treturn false;\n\t}\n}\n\nCSimpleModelInfo *gpRelatedModelInfo;\n\nbool\nCFileLoader::LoadAtomicFile(RwStream *stream, uint32 id)\n{\n\tRpClump *clump;\n\n\tif(RwStreamFindChunk(stream, rwID_CLUMP, nil, nil)){\n\t\tclump = RpClumpStreamRead(stream);\n\t\tif(clump == nil)\n\t\t\treturn false;\n\t\tInitClump(clump);\n\t\tgpRelatedModelInfo = (CSimpleModelInfo*)CModelInfo::GetModelInfo(id);\n\t\tRpClumpForAllAtomics(clump, SetRelatedModelInfoCB, clump);\n\t\tRpClumpDestroy(clump);\n\t}\n\treturn true;\n}\n\nRpAtomic*\nCFileLoader::SetRelatedModelInfoCB(RpAtomic *atomic, void *data)\n{\n\tchar *nodename, name[24];\n\tint n;\n\tRpClump *clump = (RpClump*)data;\n\n\tnodename = GetFrameNodeName(RpAtomicGetFrame(atomic));\n\tGetNameAndLOD(nodename, name, &n);\n\tCVisibilityPlugins::SetAtomicRenderCallback(atomic, nil);\n\tgpRelatedModelInfo->SetAtomic(n, atomic);\n\tRpClumpRemoveAtomic(clump, atomic);\n\tRpAtomicSetFrame(atomic, RwFrameCreate());\n\tCVisibilityPlugins::SetAtomicModelInfo(atomic, gpRelatedModelInfo);\n\treturn atomic;\n}\n\nRpClump*\nCFileLoader::LoadAtomicFile2Return(const char *filename)\n{\n\tRwStream *stream;\n\tRpClump *clump;\n\n\tclump = nil;\n\tdebug(\"Loading model file %s\\n\", filename);\n\tstream = RwStreamOpen(rwSTREAMFILENAME, rwSTREAMREAD, filename);\n\tif(RwStreamFindChunk(stream, rwID_CLUMP, nil, nil))\n\t\tclump = RpClumpStreamRead(stream);\n\tif(clump)\n\t\tInitClump(clump);\n\tRwStreamClose(stream, nil);\n\treturn clump;\n}\n\nstatic RwTexture*\nMoveTexturesCB(RwTexture *texture, void *pData)\n{\n\tRwTexDictionaryAddTexture((RwTexDictionary*)pData, texture);\n\treturn texture;\n}\n\nvoid\nCFileLoader::AddTexDictionaries(RwTexDictionary *dst, RwTexDictionary *src)\n{\n\tRwTexDictionaryForAllTextures(src, MoveTexturesCB, dst);\n}\n\n#define isLine3(l, a, b, c) ((l[0] == a) && (l[1] == b) && (l[2] == c))\n#define isLine4(l, a, b, c, d) ((l[0] == a) && (l[1] == b) && (l[2] == c) && (l[3] == d))\n\nvoid\nCFileLoader::LoadObjectTypes(const char *filename)\n{\n\tenum {\n\t\tNONE,\n\t\tOBJS,\n\t\tMLO,\t// unused but enum still has it\n\t\tTOBJ,\n\t\tWEAP,\n\t\tHIER,\n\t\tCARS,\n\t\tPEDS,\n\t\tPATH,\n\t\tTWODFX\n\t};\n\tchar *line;\n\tint fd;\n\tint section;\n\tint pathIndex;\n\tint id, pathType;\n\tint minID, maxID;\n\n\tsection = NONE;\n\tminID = INT32_MAX;\n\tmaxID = -1;\n\tpathIndex = -1;\n\tdebug(\"Loading object types from %s...\\n\", filename);\n\n\tfd = CFileMgr::OpenFile(filename, \"rb\");\n\tassert(fd > 0);\n\tfor(line = CFileLoader::LoadLine(fd); line; line = CFileLoader::LoadLine(fd)){\n\t\tif(*line == '\\0' || *line == '#')\n\t\t\tcontinue;\n\n\t\tif(section == NONE){\n\t\t\tif(isLine4(line, 'o','b','j','s')) section = OBJS;\n\t\t\telse if(isLine4(line, 't','o','b','j')) section = TOBJ;\n\t\t\telse if(isLine4(line, 'w','e','a','p')) section = WEAP;\n\t\t\telse if(isLine4(line, 'h','i','e','r')) section = HIER;\n\t\t\telse if(isLine4(line, 'c','a','r','s')) section = CARS;\n\t\t\telse if(isLine4(line, 'p','e','d','s')) section = PEDS;\n\t\t\telse if(isLine4(line, 'p','a','t','h')) section = PATH;\n\t\t\telse if(isLine4(line, '2','d','f','x')) section = TWODFX;\n\t\t}else if(isLine3(line, 'e','n','d')){\n\t\t\tsection = NONE;\n\t\t}else switch(section){\n\t\tcase OBJS:\n\t\t\tid = LoadObject(line);\n\t\t\tif(id > maxID) maxID = id;\n\t\t\tif(id < minID) minID = id;\n\t\t\tbreak;\n\t\tcase TOBJ:\n\t\t\tid = LoadTimeObject(line);\n\t\t\tif(id > maxID) maxID = id;\n\t\t\tif(id < minID) minID = id;\n\t\t\tbreak;\n\t\tcase WEAP:\n\t\t\tLoadWeaponObject(line);\n\t\t\tbreak;\n\t\tcase HIER:\n\t\t\tLoadClumpObject(line);\n\t\t\tbreak;\n\t\tcase CARS:\n\t\t\tLoadVehicleObject(line);\n\t\t\tbreak;\n\t\tcase PEDS:\n\t\t\tLoadPedObject(line);\n\t\t\tbreak;\n\t\tcase PATH:\n\t\t\tif(pathIndex == -1){\n\t\t\t\tid = LoadPathHeader(line, pathType);\n\t\t\t\tpathIndex = 0;\n\t\t\t}else{\n\t\t\t\tif(pathType == 0)\n\t\t\t\t\tLoadPedPathNode(line, id, pathIndex);\n\t\t\t\telse if (pathType == 1)\n\t\t\t\t\tLoadCarPathNode(line, id, pathIndex, false);\n\t\t\t\telse if (pathType == 2)\n\t\t\t\t\tLoadCarPathNode(line, id, pathIndex, true);\n\t\t\t\tpathIndex++;\n\t\t\t\tif(pathIndex == 12)\n\t\t\t\t\tpathIndex = -1;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase TWODFX:\n\t\t\tLoad2dEffect(line);\n\t\t\tbreak;\n\t\t}\n\t}\n\tCFileMgr::CloseFile(fd);\n\n\tfor(id = minID; id <= maxID; id++){\n\t\tCSimpleModelInfo *mi = (CSimpleModelInfo*)CModelInfo::GetModelInfo(id);\n\t\tif(mi && mi->IsBuilding())\n\t\t\tmi->SetupBigBuilding(minID, maxID);\n\t}\n}\n\nvoid\nSetModelInfoFlags(CSimpleModelInfo *mi, uint32 flags)\n{\n\tmi->m_wetRoadReflection =\t!!(flags & 1);\n\tmi->m_noFade =\t!!(flags & 2);\n\tmi->m_drawLast =\t!!(flags & (4|8));\n\tmi->m_additive =\t!!(flags & 8);\n\tmi->m_isSubway =\t!!(flags & 0x10);\n\tmi->m_ignoreLight =\t!!(flags & 0x20);\n\tmi->m_noZwrite =\t!!(flags & 0x40);\n\tmi->m_noShadows =\t!!(flags & 0x80);\n\tmi->m_ignoreDrawDist =\t!!(flags & 0x100);\n\tmi->m_isCodeGlass =\t!!(flags & 0x200);\n\tmi->m_isArtistGlass =\t!!(flags & 0x400);\n}\n\nint\nCFileLoader::LoadObject(const char *line)\n{\n\tint id, numObjs;\n\tchar model[24], txd[24];\n\tfloat dist[3];\n\tuint32 flags;\n\tint damaged;\n\tCSimpleModelInfo *mi;\n\n\tif(sscanf(line, \"%d %s %s %d\", &id, model, txd, &numObjs) != 4)\n\t\treturn 0;\t// game returns return value\n\n\tswitch(numObjs){\n\tcase 1:\n\t\tsscanf(line, \"%d %s %s %d %f %d\",\n\t\t\t&id, model, txd, &numObjs, &dist[0], &flags);\n\t\tdamaged = 0;\n\t\tbreak;\n\tcase 2:\n\t\tsscanf(line, \"%d %s %s %d %f %f %d\",\n\t\t\t&id, model, txd, &numObjs, &dist[0], &dist[1], &flags);\n\t\tdamaged = dist[0] < dist[1] ?\t// Are distances increasing?\n\t\t\t0 :\t// Yes, no damage model\n\t\t\t1;\t// No, 1 is damaged\n\t\tbreak;\n\tcase 3:\n\t\tsscanf(line, \"%d %s %s %d %f %f %f %d\",\n\t\t\t&id, model, txd, &numObjs, &dist[0], &dist[1], &dist[2], &flags);\n\t\tdamaged = dist[0] < dist[1] ?\t// Are distances increasing?\n\t\t\t\t(dist[1] < dist[2] ? 0 : 2) :\t// Yes, only 2 can still be a damage model\n\t\t\t1;\t// No, 1 and 2 are damaged\n\t\tbreak;\n\t}\n\n\tmi = CModelInfo::AddSimpleModel(id);\n\tmi->SetModelName(model);\n\tmi->SetNumAtomics(numObjs);\n\tmi->SetLodDistances(dist);\n\tSetModelInfoFlags(mi, flags);\n\tmi->m_firstDamaged = damaged;\n\tmi->SetTexDictionary(txd);\n\tMatchModelString(model, id);\n\n\treturn id;\n}\n\nint\nCFileLoader::LoadTimeObject(const char *line)\n{\n\tint id, numObjs;\n\tchar model[24], txd[24];\n\tfloat dist[3];\n\tuint32 flags;\n\tint timeOn, timeOff;\n\tint damaged;\n\tCTimeModelInfo *mi, *other;\n\n\tif(sscanf(line, \"%d %s %s %d\", &id, model, txd, &numObjs) != 4)\n\t\treturn 0;\t// game returns return value\n\n\tswitch(numObjs){\n\tcase 1:\n\t\tsscanf(line, \"%d %s %s %d %f %d %d %d\",\n\t\t\t&id, model, txd, &numObjs, &dist[0], &flags, &timeOn, &timeOff);\n\t\tdamaged = 0;\n\t\tbreak;\n\tcase 2:\n\t\tsscanf(line, \"%d %s %s %d %f %f %d %d %d\",\n\t\t\t&id, model, txd, &numObjs, &dist[0], &dist[1], &flags, &timeOn, &timeOff);\n\t\tdamaged = dist[0] < dist[1] ?\t// Are distances increasing?\n\t\t\t0 :\t// Yes, no damage model\n\t\t\t1;\t// No, 1 is damaged\n\t\tbreak;\n\tcase 3:\n\t\tsscanf(line, \"%d %s %s %d %f %f %f %d %d %d\",\n\t\t\t&id, model, txd, &numObjs, &dist[0], &dist[1], &dist[2], &flags, &timeOn, &timeOff);\n\t\tdamaged = dist[0] < dist[1] ?\t// Are distances increasing?\n\t\t\t\t(dist[1] < dist[2] ? 0 : 2) :\t// Yes, only 2 can still be a damage model\n\t\t\t1;\t// No, 1 and 2 are damaged\n\t\tbreak;\n\t}\n\n\tmi = CModelInfo::AddTimeModel(id);\n\tmi->SetModelName(model);\n\tmi->SetNumAtomics(numObjs);\n\tmi->SetLodDistances(dist);\n\tSetModelInfoFlags(mi, flags);\n\tmi->m_firstDamaged = damaged;\n\tmi->SetTimes(timeOn, timeOff);\n\tmi->SetTexDictionary(txd);\n\tother = mi->FindOtherTimeModel();\n\tif(other)\n\t\tother->SetOtherTimeModel(id);\n\tMatchModelString(model, id);\n\n\treturn id;\n}\n\nint\nCFileLoader::LoadWeaponObject(const char *line)\n{\n\tint id, numObjs;\n\tchar model[24], txd[24], animFile[16];\n\tfloat dist;\n\tCWeaponModelInfo *mi;\n\n\tsscanf(line, \"%d %s %s %s %d %f\", &id, model, txd, animFile, &numObjs, &dist);\n\n\tmi = CModelInfo::AddWeaponModel(id);\n\tmi->SetModelName(model);\n\tmi->SetNumAtomics(1);\n\tmi->m_lodDistances[0] = dist;\n\tmi->SetTexDictionary(txd);\n\tmi->SetAnimFile(animFile);\n\tmi->SetColModel(&CTempColModels::ms_colModelWeapon);\n\tMatchModelString(model, id);\n\treturn id;\n}\n\nvoid\nCFileLoader::LoadClumpObject(const char *line)\n{\n\tint id;\n\tchar model[24], txd[24];\n\tCClumpModelInfo *mi;\n\n\tif(sscanf(line, \"%d %s %s\", &id, model, txd) == 3){\n\t\tmi = CModelInfo::AddClumpModel(id);\n\t\tmi->SetModelName(model);\n\t\tmi->SetTexDictionary(txd);\n\t\tmi->SetColModel(&CTempColModels::ms_colModelBBox);\n\t}\n}\n\nvoid\nCFileLoader::LoadVehicleObject(const char *line)\n{\n\tint id;\n\tchar model[24], txd[24];\n\tchar type[8], handlingId[16], gamename[32], animFile[16], vehclass[12];\n\tuint32 frequency, comprules;\n\tint32 level, misc;\n\tfloat wheelScale;\n\tCVehicleModelInfo *mi;\n\tchar *p;\n\n\tsscanf(line, \"%d %s %s %s %s %s %s %s %d %d %x %d %f\",\n\t\t&id, model, txd,\n\t\ttype, handlingId, gamename, animFile, vehclass,\n\t\t&frequency, &level, &comprules, &misc, &wheelScale);\n\n\tmi = CModelInfo::AddVehicleModel(id);\n\tmi->SetModelName(model);\n\tmi->SetTexDictionary(txd);\n\tmi->SetAnimFile(animFile);\n\tfor(p = gamename; *p; p++)\n\t\tif(*p == '_') *p = ' ';\n\tstrcpy(mi->m_gameName, gamename);\n\tmi->m_level = level;\n\tmi->m_compRules = comprules;\n\n\tif(strcmp(type, \"car\") == 0){\n\t\tmi->m_wheelId = misc;\n\t\tmi->m_wheelScale = wheelScale;\n\t\tmi->m_vehicleType = VEHICLE_TYPE_CAR;\n\t}else if(strcmp(type, \"boat\") == 0){\n\t\tmi->m_vehicleType = VEHICLE_TYPE_BOAT;\n\t}else if(strcmp(type, \"train\") == 0){\n\t\tmi->m_vehicleType = VEHICLE_TYPE_TRAIN;\n\t}else if(strcmp(type, \"heli\") == 0){\n\t\tmi->m_vehicleType = VEHICLE_TYPE_HELI;\n\t}else if(strcmp(type, \"plane\") == 0){\n\t\tmi->m_planeLodId = misc;\n\t\tmi->m_wheelScale = 1.0f;\n\t\tmi->m_vehicleType = VEHICLE_TYPE_PLANE;\n\t}else if(strcmp(type, \"bike\") == 0){\n\t\tmi->m_bikeSteerAngle = misc;\n\t\tmi->m_wheelScale = wheelScale;\n\t\tmi->m_vehicleType = VEHICLE_TYPE_BIKE;\n\t}else\n\t\tassert(0);\n\n\tmi->m_handlingId = mod_HandlingManager.GetHandlingId(handlingId);\n\n\tif(strcmp(vehclass, \"normal\") == 0)\n\t\tmi->m_vehicleClass = CCarCtrl::NORMAL;\n\telse if(strcmp(vehclass, \"poorfamily\") == 0)\n\t\tmi->m_vehicleClass = CCarCtrl::POOR;\n\telse if(strcmp(vehclass, \"richfamily\") == 0)\n\t\tmi->m_vehicleClass = CCarCtrl::RICH;\n\telse if(strcmp(vehclass, \"executive\") == 0)\n\t\tmi->m_vehicleClass = CCarCtrl::EXEC;\n\telse if(strcmp(vehclass, \"worker\") == 0)\n\t\tmi->m_vehicleClass = CCarCtrl::WORKER;\n\telse if(strcmp(vehclass, \"big\") == 0)\n\t\tmi->m_vehicleClass = CCarCtrl::BIG;\n\telse if(strcmp(vehclass, \"taxi\") == 0)\n\t\tmi->m_vehicleClass = CCarCtrl::TAXI;\n\telse if(strcmp(vehclass, \"moped\") == 0)\n\t\tmi->m_vehicleClass = CCarCtrl::MOPED;\n\telse if(strcmp(vehclass, \"motorbike\") == 0)\n\t\tmi->m_vehicleClass = CCarCtrl::MOTORBIKE;\n\telse if(strcmp(vehclass, \"leisureboat\") == 0)\n\t\tmi->m_vehicleClass = CCarCtrl::LEISUREBOAT;\n\telse if(strcmp(vehclass, \"workerboat\") == 0)\n\t\tmi->m_vehicleClass = CCarCtrl::WORKERBOAT;\n\telse if(strcmp(vehclass, \"ignore\") == 0) {\n\t\tmi->m_vehicleClass = -1;\n\t\treturn;\n\t}\n\tCCarCtrl::AddToCarArray(id, mi->m_vehicleClass);\n\tmi->m_frequency = frequency;\n}\n\nvoid\nCFileLoader::LoadPedObject(const char *line)\n{\n\tint id;\n\tchar model[24], txd[24];\n\tchar pedType[24], pedStats[24], animGroup[24], animFile[16];\n\tint carsCanDrive;\n\tCPedModelInfo *mi;\n\tint animGroupId;\n\tint radio1, radio2;\n\n\tsscanf(line, \"%d %s %s %s %s %s %x %s %d %d\",\n\t          &id, model, txd,\n\t          pedType, pedStats, animGroup, &carsCanDrive,\n\t\t  animFile, &radio1, &radio2);\n\n\tmi = CModelInfo::AddPedModel(id);\n\tmi->SetModelName(model);\n\tmi->SetTexDictionary(txd);\n\tmi->SetAnimFile(animFile);\n\tmi->SetColModel(&CTempColModels::ms_colModelPed1);\n\tmi->m_pedType = CPedType::FindPedType(pedType);\n\tmi->m_pedStatType = CPedStats::GetPedStatType(pedStats);\n\tfor(animGroupId = 0; animGroupId < NUM_ANIM_ASSOC_GROUPS; animGroupId++)\n\t\tif(strcmp(animGroup, CAnimManager::GetAnimGroupName((AssocGroupId)animGroupId)) == 0)\n\t\t\tbreak;\n\tassert(animGroupId < NUM_ANIM_ASSOC_GROUPS);\n\tmi->m_animGroup = animGroupId;\n\tmi->m_carsCanDrive = carsCanDrive;\n\tmi->radio1 = radio1;\n\tmi->radio2 = radio2;\n}\n\nint\nCFileLoader::LoadPathHeader(const char *line, int &type)\n{\n\tint id;\n\tchar modelname[32];\n\n\tsscanf(line, \"%d %d %s\", &type, &id, modelname);\n\treturn id;\n}\n\nvoid\nCFileLoader::LoadPedPathNode(const char *line, int id, int node)\n{\n\tint type, next, cross, numLeft, numRight, speed, flags;\n\tfloat x, y, z, width, spawnRate;\n\n\tif(sscanf(line, \"%d %d %d %f %f %f %f %d %d %d %d %f\",\n\t\t\t&type, &next, &cross, &x, &y, &z, &width, &numLeft, &numRight,\n\t\t\t&speed, &flags, &spawnRate) != 12)\n\t\tspawnRate = 1.0f;\n\n\tif(id == -1)\n\t\tThePaths.StoreDetachedNodeInfoPed(node, type, next, x, y, z,\n\t\t\twidth, !!cross, !!(flags&1), !!(flags&4), spawnRate*15.0f);\n\telse\n\t\tThePaths.StoreNodeInfoPed(id, node, type, next, x, y, z,\n\t\t\twidth, !!cross, spawnRate*15.0f);\n}\n\nvoid\nCFileLoader::LoadCarPathNode(const char *line, int id, int node, bool waterPath)\n{\n\tint type, next, cross, numLeft, numRight, speed, flags;\n\tfloat x, y, z, width, spawnRate;\n\n\tif(sscanf(line, \"%d %d %d %f %f %f %f %d %d %d %d %f\",\n\t\t\t&type, &next, &cross, &x, &y, &z, &width, &numLeft, &numRight,\n\t\t\t&speed, &flags, &spawnRate) != 12)\n\t\tspawnRate = 1.0f;\n\n\tif(id == -1)\n\t\tThePaths.StoreDetachedNodeInfoCar(node, type, next, x, y, z, width, numLeft, numRight,\n\t\t\t!!(flags&1), !!(flags&4), speed, !!(flags&2), waterPath, spawnRate * 15, false);\n\telse\n\t\tThePaths.StoreNodeInfoCar(id, node, type, next, x, y, z, 0, numLeft, numRight,\n\t\t\t!!(flags&1), !!(flags&4), speed, !!(flags&2), waterPath, spawnRate * 15);\n}\n\n\nvoid\nCFileLoader::Load2dEffect(const char *line)\n{\n\tint id, r, g, b, a, type, ptype;\n\tfloat x, y, z;\n\tchar corona[32], shadow[32];\n\tint shadowIntens, lightType, roadReflection, flare, flags, probability;\n\tCBaseModelInfo *mi;\n\tC2dEffect *effect;\n\tchar *p;\n\n\tsscanf(line, \"%d %f %f %f %d %d %d %d %d\", &id, &x, &y, &z, &r, &g, &b, &a, &type);\n\n\tCTxdStore::PushCurrentTxd();\n\tCTxdStore::SetCurrentTxd(CTxdStore::FindTxdSlot(\"particle\"));\n\n\tmi = CModelInfo::GetModelInfo(id);\n\teffect = CModelInfo::Get2dEffectStore().Alloc();\n\tmi->Add2dEffect(effect);\n\teffect->pos = CVector(x, y, z);\n\teffect->col = CRGBA(r, g, b, a);\n\teffect->type = type;\n\n\tswitch(effect->type){\n\tcase EFFECT_LIGHT:\n\t\twhile(*line++ != '\"');\n\t\tp = corona;\n\t\twhile(*line != '\"') *p++ = *line++;\n\t\t*p = '\\0';\n\t\tline++;\n\n\t\twhile(*line++ != '\"');\n\t\tp = shadow;\n\t\twhile(*line != '\"') *p++ = *line++;\n\t\t*p = '\\0';\n\t\tline++;\n\n\t\tsscanf(line, \"%f %f %f %f %d %d %d %d %d\",\n\t\t\t&effect->light.dist,\n\t\t\t&effect->light.range,\n\t\t\t&effect->light.size,\n\t\t\t&effect->light.shadowSize,\n\t\t\t&shadowIntens, &lightType, &roadReflection, &flare, &flags);\n\t\teffect->light.corona = RwTextureRead(corona, nil);\n\t\teffect->light.shadow = RwTextureRead(shadow, nil);\n\t\teffect->light.shadowIntensity = shadowIntens;\n\t\teffect->light.lightType = lightType;\n\t\teffect->light.roadReflection = roadReflection;\n\t\teffect->light.flareType = flare;\n\n\t\tif(flags & LIGHTFLAG_FOG_ALWAYS)\n\t\t\tflags &= ~LIGHTFLAG_FOG_NORMAL;\n\t\teffect->light.flags = flags;\n\t\tbreak;\n\n\tcase EFFECT_PARTICLE:\n\t\tsscanf(line, \"%d %f %f %f %d %d %d %d %d %d %f %f %f %f\",\n\t\t\t&id, &x, &y, &z, &r, &g, &b, &a, &type,\n\t\t\t&effect->particle.particleType,\n\t\t\t&effect->particle.dir.x,\n\t\t\t&effect->particle.dir.y,\n\t\t\t&effect->particle.dir.z,\n\t\t\t&effect->particle.scale);\n\t\tbreak;\n\n\tcase EFFECT_ATTRACTOR:\n\t\tsscanf(line, \"%d %f %f %f %d %d %d %d %d %d %f %f %f %d\",\n\t\t\t&id, &x, &y, &z, &r, &g, &b, &a, &type,\n\t\t\t&flags,\n\t\t\t&effect->attractor.dir.x,\n\t\t\t&effect->attractor.dir.y,\n\t\t\t&effect->attractor.dir.z,\n\t\t\t&probability);\n\t\teffect->attractor.type = flags;\n#ifdef FIX_BUGS\n\t\teffect->attractor.probability = clamp(probability, 0, 255);\n#else\n\t\teffect->attractor.probability = probability;\n#endif\n\t\tbreak;\n\tcase EFFECT_PED_ATTRACTOR:\n\t\tsscanf(line, \"%d %f %f %f %d %d %d %d %d %d %f %f %f %f %f %f\",\n\t\t\t&id, &x, &y, &z, &r, &g, &b, &a, &type,\n\t\t\t&ptype,\n\t\t\t&effect->pedattr.queueDir.x,\n\t\t\t&effect->pedattr.queueDir.y,\n\t\t\t&effect->pedattr.queueDir.z,\n\t\t\t&effect->pedattr.useDir.x,\n\t\t\t&effect->pedattr.useDir.y,\n\t\t\t&effect->pedattr.useDir.z);\n\t\teffect->pedattr.type = ptype;\n\t\tbreak;\n\t}\n\n\tCTxdStore::PopCurrentTxd();\n}\n\nvoid\nCFileLoader::LoadScene(const char *filename)\n{\n\tenum {\n\t\tNONE,\n\t\tINST,\n\t\tZONE,\n\t\tCULL,\n\t\tOCCL,\n\t\tPICK,\n\t\tPATH,\n\t};\n\tchar *line;\n\tint fd;\n\tint section;\n\tint pathType, pathIndex;\n\n\tsection = NONE;\n\tpathIndex = -1;\n\tdebug(\"Creating objects from %s...\\n\", filename);\n\n\tfd = CFileMgr::OpenFile(filename, \"rb\");\n\tassert(fd > 0);\n\tfor(line = CFileLoader::LoadLine(fd); line; line = CFileLoader::LoadLine(fd)){\n\t\tif(*line == '\\0' || *line == '#')\n\t\t\tcontinue;\n\n\t\tif(section == NONE){\n\t\t\tif(isLine4(line, 'i','n','s','t')) section = INST;\n\t\t\telse if(isLine4(line, 'z','o','n','e')) section = ZONE;\n\t\t\telse if(isLine4(line, 'c','u','l','l')) section = CULL;\n\t\t\telse if(isLine4(line, 'p','i','c','k')) section = PICK;\n\t\t\telse if(isLine4(line, 'p','a','t','h')) section = PATH;\n\t\t\telse if(isLine4(line, 'o','c','c','l')) section = OCCL;\n\t\t}else if(isLine3(line, 'e','n','d')){\n\t\t\tsection = NONE;\n\t\t}else switch(section){\n\t\tcase INST:\n\t\t\tLoadObjectInstance(line);\n\t\t\tbreak;\n\t\tcase ZONE:\n\t\t\tLoadZone(line);\n\t\t\tbreak;\n\t\tcase CULL:\n\t\t\tLoadCullZone(line);\n\t\t\tbreak;\n\t\tcase OCCL:\n\t\t\tLoadOcclusionVolume(line);\n\t\t\tbreak;\n\t\tcase PICK:\n\t\t\t// unused\n\t\t\tLoadPickup(line);\n\t\t\tbreak;\n\t\tcase PATH:\n\t\t\tif(pathIndex == -1){\n\t\t\t\tLoadPathHeader(line, pathType);\n\t\t\t\tpathIndex = 0;\n\t\t\t}else{\n\t\t\t\tif(pathType == 0)\n\t\t\t\t\tLoadPedPathNode(line, -1, pathIndex);\n\t\t\t\telse if (pathType == 1)\n\t\t\t\t\tLoadCarPathNode(line, -1, pathIndex, false);\n\t\t\t\telse if (pathType == 2)\n\t\t\t\t\tLoadCarPathNode(line, -1, pathIndex, true);\n\t\t\t\tpathIndex++;\n\t\t\t\tif(pathIndex == 12)\n\t\t\t\t\tpathIndex = -1;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t}\n\tCFileMgr::CloseFile(fd);\n\n\tdebug(\"Finished loading IPL\\n\");\n}\n\nvoid\nCFileLoader::LoadObjectInstance(const char *line)\n{\n\tint id;\n\tchar name[24];\n\tRwV3d trans, scale, axis;\n\tfloat angle;\n\tCSimpleModelInfo *mi;\n\tRwMatrix *xform;\n\tCEntity *entity;\n\tfloat area;\n\n\tif(sscanf(line, \"%d %s %f %f %f %f %f %f %f %f %f %f %f\",\n\t          &id, name, &area,\n\t          &trans.x, &trans.y, &trans.z,\n\t          &scale.x, &scale.y, &scale.z,\n\t          &axis.x, &axis.y, &axis.z, &angle) != 13){\n\t\tif(sscanf(line, \"%d %s %f %f %f %f %f %f %f %f %f %f\",\n\t\t          &id, name,\n\t\t          &trans.x, &trans.y, &trans.z,\n\t\t          &scale.x, &scale.y, &scale.z,\n\t\t          &axis.x, &axis.y, &axis.z, &angle) != 12)\n\t\t\treturn;\n\t\tarea = 0;\n\t}\n\n\tmi = (CSimpleModelInfo*)CModelInfo::GetModelInfo(id);\n\tif(mi == nil)\n\t\treturn;\n\tassert(mi->IsSimple());\n\n\tif(!CStreaming::IsObjectInCdImage(id))\n\t\tdebug(\"Not in cdimage %s\\n\", mi->GetModelName());\n\n\tangle = -RADTODEG(2.0f * acosf(angle));\n\txform = RwMatrixCreate();\n\tRwMatrixRotate(xform, &axis, angle, rwCOMBINEREPLACE);\n\tRwMatrixTranslate(xform, &trans, rwCOMBINEPOSTCONCAT);\n\n\tif(mi->GetObjectID() == -1){\n\t\tif(ThePaths.IsPathObject(id)){\n\t\t\tentity = new CTreadable;\n\t\t\tThePaths.RegisterMapObject((CTreadable*)entity);\n\t\t}else\n\t\t\tentity = new CBuilding;\n\t\tentity->SetModelIndexNoCreate(id);\n\t\tentity->GetMatrix() = CMatrix(xform);\n\t\tentity->m_level = CTheZones::GetLevelFromPosition(&entity->GetPosition());\n\t\tentity->m_area = area;\n\t\tif(mi->IsBuilding()){\n\t\t\tif(mi->m_isBigBuilding)\n\t\t\t\tentity->SetupBigBuilding();\n\t\t\tif(mi->m_isSubway)\n\t\t\t\tentity->bIsSubway = true;\n\t\t}\n\t\tif(mi->GetLargestLodDistance() < 2.0f)\n\t\t\tentity->bIsVisible = false;\n\t\tCWorld::Add(entity);\n\n\t\tCColModel *col = entity->GetColModel();\n\t\tif(col->numSpheres || col->numBoxes || col->numTriangles){\n\t\t\tif(col->level != 0)\n\t\t\t\tCColStore::GetBoundingBox(col->level).ContainRect(entity->GetBoundRect());\n\t\t}else\n\t\t\tentity->bUsesCollision = false;\n\n\t\tif(entity->GetPosition().z + col->boundingBox.min.z < 6.0f)\n\t\t\tentity->bUnderwater = true;\n\t}else{\n\t\tentity = new CDummyObject;\n\t\tentity->SetModelIndexNoCreate(id);\n\t\tentity->GetMatrix() = CMatrix(xform);\n\t\tCWorld::Add(entity);\n\t\tif(IsGlass(entity->GetModelIndex()) && !mi->m_isArtistGlass)\n\t\t\tentity->bIsVisible = false;\n\t\tentity->m_level = CTheZones::GetLevelFromPosition(&entity->GetPosition());\n\t\tentity->m_area = area;\n\t}\n\n\tRwMatrixDestroy(xform);\n}\n\nvoid\nCFileLoader::LoadZone(const char *line)\n{\n\tchar name[24];\n\tint type, level;\n\tfloat minx, miny, minz;\n\tfloat maxx, maxy, maxz;\n\n\tif(sscanf(line, \"%s %d %f %f %f %f %f %f %d\", name, &type, &minx, &miny, &minz, &maxx, &maxy, &maxz, &level) == 9)\n\t\tCTheZones::CreateZone(name, (eZoneType)type, minx, miny, minz, maxx, maxy, maxz, (eLevelName)level);\n}\n\nvoid\nCFileLoader::LoadCullZone(const char *line)\n{\n\tCVector pos;\n\tfloat minx, miny, minz;\n\tfloat maxx, maxy, maxz;\n\tint flags;\n\tint wantedLevelDrop = 0;\n\n\tsscanf(line, \"%f %f %f %f %f %f %f %f %f %d %d\",\n\t\t&pos.x, &pos.y, &pos.z,\n\t\t&minx, &miny, &minz,\n\t\t&maxx, &maxy, &maxz,\n\t\t&flags, &wantedLevelDrop);\n\tCCullZones::AddCullZone(pos, minx, maxx, miny, maxy, minz, maxz, flags, wantedLevelDrop);\n}\n\n// unused\nvoid\nCFileLoader::LoadPickup(const char *line)\n{\n\tint id;\n\tfloat x, y, z;\n\n\tsscanf(line, \"%d %f %f %f\", &id, &x, &y, &z);\n}\n\nvoid\nCFileLoader::LoadOcclusionVolume(const char *line)\n{\n\tfloat x, y, z;\n\tfloat width, length, height;\n\tfloat angle;\n\n\tsscanf(line, \"%f %f %f %f %f %f %f\",\n\t\t&x, &y, &z,\n\t\t&width, &length, &height,\n\t\t&angle);\n\tCOcclusion::AddOne(x, y, z + height/2.0f, width, length, height, angle);\n}\n\n\n// unused\nvoid\nCFileLoader::ReloadPaths(const char *filename)\n{\n\tenum {\n\t\tNONE,\n\t\tPATH,\n\t};\n\tchar *line;\n\tint section = NONE;\n\tint id, pathType, pathIndex = -1;\n\tdebug(\"Reloading paths from %s...\\n\", filename);\n\n\tint fd = CFileMgr::OpenFile(filename, \"r\");\n\tassert(fd > 0);\n\tfor (line = CFileLoader::LoadLine(fd); line; line = CFileLoader::LoadLine(fd)) {\n\t\tif (*line == '\\0' || *line == '#')\n\t\t\tcontinue;\n\n\t\tif (section == NONE) {\n\t\t\tif (isLine4(line, 'p','a','t','h')) {\n\t\t\t\tsection = PATH;\n\t\t\t\tThePaths.AllocatePathFindInfoMem(4500);\n\t\t\t}\n\t\t} else if (isLine3(line, 'e','n','d')) {\n\t\t\tsection = NONE;\n\t\t} else {\n\t\t\tswitch (section) {\n\t\t\t\tcase PATH:\n\t\t\t\t\tif (pathIndex == -1) {\n\t\t\t\t\t\tid = LoadPathHeader(line, pathType);\n\t\t\t\t\t\tpathIndex = 0;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif(pathType == 0)\n\t\t\t\t\t\t\tLoadPedPathNode(line, id, pathIndex);\n\t\t\t\t\t\telse if (pathType == 1)\n\t\t\t\t\t\t\tLoadCarPathNode(line, id, pathIndex, false);\n\t\t\t\t\t\telse if (pathType == 2)\n\t\t\t\t\t\t\tLoadCarPathNode(line, id, pathIndex, true);\n\t\t\t\t\t\tpathIndex++;\n\t\t\t\t\t\tif (pathIndex == 12)\n\t\t\t\t\t\t\tpathIndex = -1;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\tCFileMgr::CloseFile(fd);\n}\n\nvoid\nCFileLoader::ReloadObjectTypes(const char *filename)\n{\n\tenum {\n\t\tNONE,\n\t\tOBJS,\n\t\tTOBJ,\n\t\tTWODFX\n\t};\n\tchar *line;\n\tint section = NONE;\n\tCModelInfo::ReInit2dEffects();\n\tdebug(\"Reloading object types from %s...\\n\", filename);\n\n\tCFileMgr::ChangeDir(\"\\\\DATA\\\\MAPS\\\\\");\n\tint fd = CFileMgr::OpenFile(filename, \"r\");\n\tassert(fd > 0);\n\tCFileMgr::ChangeDir(\"\\\\\");\n\tfor (line = CFileLoader::LoadLine(fd); line; line = CFileLoader::LoadLine(fd)) {\n\t\tif (*line == '\\0' || *line == '#')\n\t\t\tcontinue;\n\n\t\tif (section == NONE) {\n\t\t\tif (isLine4(line, 'o','b','j','s')) section = OBJS;\n\t\t\telse if (isLine4(line, 't','o','b','j')) section = TOBJ;\n\t\t\telse if (isLine4(line, '2','d','f','x')) section = TWODFX;\n\t\t} else if (isLine3(line, 'e','n','d')) {\n\t\t\tsection = NONE;\n\t\t} else {\n\t\t\tswitch (section) {\n\t\t\t\tcase OBJS:\n\t\t\t\tcase TOBJ:\n\t\t\t\t\tReloadObject(line);\n\t\t\t\t\tbreak;\n\t\t\t\tcase TWODFX:\n\t\t\t\t\tLoad2dEffect(line);\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\tCFileMgr::CloseFile(fd);\n}\n\nvoid\nCFileLoader::ReloadObject(const char *line)\n{\n\tint id, numObjs;\n\tchar model[24], txd[24];\n\tfloat dist[3];\n\tuint32 flags;\n\tCSimpleModelInfo *mi;\n\n\tif(sscanf(line, \"%d %s %s %d\", &id, model, txd, &numObjs) != 4)\n\t\treturn;\n\n\tswitch(numObjs){\n\tcase 1:\n\t\tsscanf(line, \"%d %s %s %d %f %d\",\n\t\t\t&id, model, txd, &numObjs, &dist[0], &flags);\n\t\tbreak;\n\tcase 2:\n\t\tsscanf(line, \"%d %s %s %d %f %f %d\",\n\t\t\t&id, model, txd, &numObjs, &dist[0], &dist[1], &flags);\n\t\tbreak;\n\tcase 3:\n\t\tsscanf(line, \"%d %s %s %d %f %f %f %d\",\n\t\t\t&id, model, txd, &numObjs, &dist[0], &dist[1], &dist[2], &flags);\n\t\tbreak;\n\t}\n\n\tmi = (CSimpleModelInfo*) CModelInfo::GetModelInfo(id);\n\tif (\n#ifdef FIX_BUGS\n\t\tmi &&\n#endif\n\t    mi->GetModelType() == MITYPE_SIMPLE && !strcmp(mi->GetModelName(), model) && mi->m_numAtomics == numObjs) {\n\t\tmi->SetLodDistances(dist);\n\t\tSetModelInfoFlags(mi, flags);\n\t} else {\n\t\tprintf(\"Can't reload %s\\n\", model);\n\t}\n}\n\n// unused mobile function - crashes\nvoid\nCFileLoader::ReLoadScene(const char *filename)\n{\n\tchar *line;\n\tCFileMgr::ChangeDir(\"\\\\DATA\\\\\");\n\tint fd = CFileMgr::OpenFile(filename, \"r\");\n\tassert(fd > 0);\n\tCFileMgr::ChangeDir(\"\\\\\");\n\n\tfor (line = CFileLoader::LoadLine(fd); line; line = CFileLoader::LoadLine(fd)) {\n\t\tif (*line == '#')\n\t\t\tcontinue;\n\n\t\tif (strncmp(line, \"EXIT\", 4) == 0)\n\t\t\tbreak;\n\n\t\tif (strncmp(line, \"IDE\", 3) == 0) {\n\t\t\tLoadObjectTypes(line + 4);\n\t\t}\n\t}\n\tCFileMgr::CloseFile(fd);\n}\n"
  },
  {
    "path": "src/core/FileLoader.h",
    "content": "#pragma once\n\nclass CFileLoader\n{\n\tstatic char ms_line[256];\npublic:\n\tstatic void LoadLevel(const char *filename);\n\tstatic char *LoadLine(int fd);\n\tstatic RwTexDictionary *LoadTexDictionary(const char *filename);\n\tstatic void LoadCollisionFile(const char *filename, uint8 colSlot);\n\tstatic bool LoadCollisionFileFirstTime(uint8 *buffer, uint32 size, uint8 colSlot);\n\tstatic bool LoadCollisionFile(uint8 *buffer, uint32 size, uint8 colSlot);\n\tstatic void LoadCollisionModel(uint8 *buf, struct CColModel &model, char *name);\n\tstatic void LoadModelFile(const char *filename);\n\tstatic RpAtomic *FindRelatedModelInfoCB(RpAtomic *atomic, void *data);\n\tstatic void LoadClumpFile(const char *filename);\n\tstatic bool LoadClumpFile(RwStream *stream, uint32 id);\n\tstatic bool StartLoadClumpFile(RwStream *stream, uint32 id);\n\tstatic bool FinishLoadClumpFile(RwStream *stream, uint32 id);\n\tstatic bool LoadAtomicFile(RwStream *stream, uint32 id);\n\tstatic RpAtomic *SetRelatedModelInfoCB(RpAtomic *atomic, void *data);\n\tstatic RpClump *LoadAtomicFile2Return(const char *filename);\n\tstatic void AddTexDictionaries(RwTexDictionary *dst, RwTexDictionary *src);\n\n\tstatic void LoadObjectTypes(const char *filename);\n\tstatic int LoadObject(const char *line);\n\tstatic int LoadTimeObject(const char *line);\n\tstatic int LoadWeaponObject(const char *line);\n\tstatic void LoadClumpObject(const char *line);\n\tstatic void LoadVehicleObject(const char *line);\n\tstatic void LoadPedObject(const char *line);\n\tstatic int LoadPathHeader(const char *line, int &type);\n\tstatic void LoadPedPathNode(const char *line, int id, int node);\n\tstatic void LoadCarPathNode(const char *line, int id, int node, bool waterPath);\n\tstatic void Load2dEffect(const char *line);\n\n\tstatic void LoadScene(const char *filename);\n\tstatic void LoadObjectInstance(const char *line);\n\tstatic void LoadZone(const char *line);\n\tstatic void LoadCullZone(const char *line);\n\tstatic void LoadPickup(const char *line);\n\tstatic void LoadOcclusionVolume(const char *line);\n\n\tstatic void ReloadPaths(const char *filename);\n\tstatic void ReloadObjectTypes(const char *filename);\n\tstatic void ReloadObject(const char *line);\n\tstatic void ReLoadScene(const char *filename); // unused mobile function\n};\n"
  },
  {
    "path": "src/core/FileMgr.cpp",
    "content": "#define _CRT_SECURE_NO_WARNINGS\n#include <fcntl.h>\n#ifdef _WIN32\n#include <direct.h>\n#endif\n#include \"common.h\"\n#include \"crossplatform.h\"\n\n#include \"FileMgr.h\"\n\nconst char *_psGetUserFilesFolder();\n\n/*\n * Windows FILE is BROKEN for GTA.\n *\n * We need to support mapping between LF and CRLF for text files\n * but we do NOT want to end the file at the first sight of a SUB character.\n * So here is a simple implementation of a FILE interface that works like GTA expects.\n */\n\nstruct myFILE\n{\n\tbool isText;\n\tFILE *file;\n};\n\n#define NUMFILES 20\nstatic myFILE myfiles[NUMFILES];\n\n\n#if !defined(_WIN32)\n#include <dirent.h>\n#include <errno.h>\n#include <unistd.h>\n#define _getcwd getcwd\n\n// Case-insensitivity on linux (from https://github.com/OneSadCookie/fcaseopen)\nvoid mychdir(char const *path)\n{\n\tchar* r = casepath(path, false);\n    if (r) {\n        chdir(r);\n\t\tfree(r);\n    } else {\n        errno = ENOENT;\n    }\n}\n#else\n#define mychdir chdir\n#endif\n\n/* Force file to open as binary but remember if it was text mode */\nstatic int\nmyfopen(const char *filename, const char *mode)\n{\n\tint fd;\n\tchar realmode[10], *p;\n\n\tfor(fd = 1; fd < NUMFILES; fd++)\n\t\tif(myfiles[fd].file == nil)\n\t\t\tgoto found;\n\treturn 0;\t// no free fd\nfound:\n\tmyfiles[fd].isText = strchr(mode, 'b') == nil;\n\tp = realmode;\n\twhile(*mode)\n\t\tif(*mode != 't' && *mode != 'b')\n\t\t\t*p++ = *mode++;\n\t\telse\n\t\t\tmode++;\n\t*p++ = 'b';\n\t*p = '\\0';\n\t\n\tmyfiles[fd].file = fcaseopen(filename, realmode);\n\tif(myfiles[fd].file == nil)\n\t\treturn 0;\n\treturn fd;\n}\n\nstatic int\nmyfclose(int fd)\n{\n\tint ret;\n\tassert(fd < NUMFILES);\n\tif(myfiles[fd].file){\n\t\tret = fclose(myfiles[fd].file);\n\t\tmyfiles[fd].file = nil;\n\t\treturn ret;\n\t}\n\treturn EOF;\n}\n\nstatic int\nmyfgetc(int fd)\n{\n\tint c;\n\tc = fgetc(myfiles[fd].file);\n\tif(myfiles[fd].isText && c == 015){\n\t\t/* translate CRLF to LF */\n\t\tc = fgetc(myfiles[fd].file);\n\t\tif(c == 012)\n\t\t\treturn c;\n\t\tungetc(c, myfiles[fd].file);\n\t\treturn 015;\n\t}\n\treturn c;\n}\n\nstatic int\nmyfputc(int c, int fd)\n{\n\t/* translate LF to CRLF */\n\tif(myfiles[fd].isText && c == 012)\n\t\tfputc(015, myfiles[fd].file);\n\treturn fputc(c, myfiles[fd].file);\n}\n\nstatic char*\nmyfgets(char *buf, int len, int fd)\n{\n\tint c;\n\tchar *p;\n\n\tp = buf;\n\tlen--;\t// NUL byte\n\twhile(len--){\n\t\tc = myfgetc(fd);\n\t\tif(c == EOF){\n\t\t\tif(p == buf)\n\t\t\t\treturn nil;\n\t\t\tbreak;\n\t\t}\n\t\t*p++ = c;\n\t\tif(c == '\\n')\n\t\t\tbreak;\n\t}\n\t*p = '\\0';\n\treturn buf;\n}\n\nstatic size_t\nmyfread(void *buf, size_t elt, size_t n, int fd)\n{\n\tif(myfiles[fd].isText){\n\t\tunsigned char *p;\n\t\tsize_t i;\n\t\tint c;\n\n\t\tn *= elt;\n\t\tp = (unsigned char*)buf;\n\t\tfor(i = 0; i < n; i++){\n\t\t\tc = myfgetc(fd);\n\t\t\tif(c == EOF)\n\t\t\t\tbreak;\n\t\t\t*p++ = (unsigned char)c;\n\t\t}\n\t\treturn i / elt;\n\t}\n\treturn fread(buf, elt, n, myfiles[fd].file);\n}\n\nstatic size_t\nmyfwrite(void *buf, size_t elt, size_t n, int fd)\n{\n\tif(myfiles[fd].isText){\n\t\tunsigned char *p;\n\t\tsize_t i;\n\t\tint c;\n\n\t\tn *= elt;\n\t\tp = (unsigned char*)buf;\n\t\tfor(i = 0; i < n; i++){\n\t\t\tc = *p++;\n\t\t\tmyfputc(c, fd);\n\t\t\tif(feof(myfiles[fd].file))\t// is this right?\n\t\t\t\tbreak;\n\t\t}\n\t\treturn i / elt;\n\t}\n\treturn fwrite(buf, elt, n, myfiles[fd].file);\n}\n\nstatic int\nmyfseek(int fd, long offset, int whence)\n{\n\treturn fseek(myfiles[fd].file, offset, whence);\n}\n\nstatic int\nmyfeof(int fd)\n{\n\treturn feof(myfiles[fd].file);\n//\treturn ferror(myfiles[fd].file);\n}\n\n\nchar CFileMgr::ms_rootDirName[128] = {'\\0'};\nchar CFileMgr::ms_dirName[128];\n\nvoid\nCFileMgr::Initialise(void)\n{\n\t_getcwd(ms_rootDirName, 128);\n\tstrcat(ms_rootDirName, \"\\\\\");\n}\n\nvoid\nCFileMgr::ChangeDir(const char *dir)\n{\n\tif(*dir == '\\\\'){\n\t\tstrcpy(ms_dirName, ms_rootDirName);\n\t\tdir++;\n\t}\n\tif(*dir != '\\0'){\n\t\tstrcat(ms_dirName, dir);\n\t\t// BUG in the game it seems, it's off by one\n\t\tif(dir[strlen(dir)-1] != '\\\\')\n\t\t\tstrcat(ms_dirName, \"\\\\\");\n\t}\n\tmychdir(ms_dirName);\n}\n\nvoid\nCFileMgr::SetDir(const char *dir)\n{\n\tstrcpy(ms_dirName, ms_rootDirName);\n\tif(*dir != '\\0'){\n\t\tstrcat(ms_dirName, dir);\n\t\t// BUG in the game it seems, it's off by one\n\t\tif(dir[strlen(dir)-1] != '\\\\')\n\t\t\tstrcat(ms_dirName, \"\\\\\");\n\t}\n\tmychdir(ms_dirName);\n}\n\nvoid\nCFileMgr::SetDirMyDocuments(void)\n{\n\tSetDir(\"\");\t// better start at the root if user directory is relative\n\tmychdir(_psGetUserFilesFolder());\n}\n\nssize_t\nCFileMgr::LoadFile(const char *file, uint8 *buf, int maxlen, const char *mode)\n{\n\tint fd;\n\tssize_t n, len;\n\n\tfd = myfopen(file, mode);\n\tif(fd == 0)\n\t\treturn -1;\n\tlen = 0;\n\tdo{\n\t\tn = myfread(buf + len, 1, 0x4000, fd);\n#ifndef FIX_BUGS\n\t\tif (n < 0)\n\t\t\treturn -1;\n#endif\n\t\tlen += n;\n\t\tassert(len < maxlen);\n\t}while(n == 0x4000);\n\tbuf[len] = 0;\n\tmyfclose(fd);\n\treturn len;\n}\n\nint\nCFileMgr::OpenFile(const char *file, const char *mode)\n{\n\treturn myfopen(file, mode);\n}\n\nint\nCFileMgr::OpenFileForWriting(const char *file)\n{\n\treturn OpenFile(file, \"wb\");\n}\n\nsize_t\nCFileMgr::Read(int fd, const char *buf, ssize_t len)\n{\n\treturn myfread((void*)buf, 1, len, fd);\n}\n\nsize_t\nCFileMgr::Write(int fd, const char *buf, ssize_t len)\n{\n\treturn myfwrite((void*)buf, 1, len, fd);\n}\n\nbool\nCFileMgr::Seek(int fd, int offset, int whence)\n{\n\treturn !!myfseek(fd, offset, whence);\n}\n\nbool\nCFileMgr::ReadLine(int fd, char *buf, int len)\n{\n\treturn myfgets(buf, len, fd) != nil;\n}\n\nint\nCFileMgr::CloseFile(int fd)\n{\n\treturn myfclose(fd);\n}\n\nint\nCFileMgr::GetErrorReadWrite(int fd)\n{\n\treturn myfeof(fd);\n}\n"
  },
  {
    "path": "src/core/FileMgr.h",
    "content": "#pragma once\n\nclass CFileMgr\n{\n\tstatic char ms_rootDirName[128];\n\tstatic char ms_dirName[128];\npublic:\n\tstatic void Initialise(void);\n\tstatic void ChangeDir(const char *dir);\n\tstatic void SetDir(const char *dir);\n\tstatic void SetDirMyDocuments(void);\n\tstatic ssize_t LoadFile(const char *file, uint8 *buf, int maxlen, const char *mode);\n\tstatic int OpenFile(const char *file, const char *mode);\n\tstatic int OpenFile(const char *file) { return OpenFile(file, \"rb\"); }\n\tstatic int OpenFileForWriting(const char *file);\n\tstatic size_t Read(int fd, const char *buf, ssize_t len);\n\tstatic size_t Write(int fd, const char *buf, ssize_t len);\n\tstatic bool Seek(int fd, int offset, int whence);\n\tstatic bool ReadLine(int fd, char *buf, int len);\n\tstatic int CloseFile(int fd);\n\tstatic int GetErrorReadWrite(int fd);\n\tstatic char *GetRootDirName() { return ms_rootDirName; }\n};\n"
  },
  {
    "path": "src/core/Fire.cpp",
    "content": "#include \"common.h\"\n\n#include \"Vector.h\"\n#include \"PlayerPed.h\"\n#include \"Entity.h\"\n#include \"PointLights.h\"\n#include \"Particle.h\"\n#include \"Timer.h\"\n#include \"Vehicle.h\"\n#include \"Shadows.h\"\n#include \"Automobile.h\"\n#include \"World.h\"\n#include \"General.h\"\n#include \"EventList.h\"\n#include \"DamageManager.h\"\n#include \"Ped.h\"\n#include \"Fire.h\"\n#include \"GameLogic.h\"\n#include \"CarAI.h\"\n\nCFireManager gFireManager;\n\nCFire::CFire()\n{\n\tm_bIsOngoing = false;\n\tm_bIsScriptFire = false;\n\tm_bPropagationFlag = true;\n\tm_bAudioSet = true;\n\tm_vecPos = CVector(0.0f, 0.0f, 0.0f);\n\tm_nExtinguishTime = 0;\n\tm_nStartTime = 0;\n\tm_pEntity = nil;\n\tm_pSource = nil;\n\tm_fStrength = 0.8f;\n\tm_fWaterExtinguishCountdown = 1.0f;\n  \tm_bExtinguishedWithWater = false;\n}\n\nCFire::~CFire() {}\n\nvoid\nCFire::ProcessFire(void)\n{\n\tfloat fDamagePlayer;\n\tfloat fDamagePeds;\n\tfloat fDamageVehicle;\n\tint16 nRandNumber;\n\tfloat fGreen;\n\tfloat fRed;\n\tCVector lightpos;\n\tCVector firePos;\n\tCPed *ped = (CPed *)m_pEntity;\n\tCVehicle *veh = (CVehicle*)m_pEntity;\n\n\tm_fWaterExtinguishCountdown = Min(1.0f, 0.002f * CTimer::GetTimeStep() + m_fWaterExtinguishCountdown);\n\n\tif (m_pEntity) {\n\t\tm_vecPos = m_pEntity->GetPosition();\n\n\t\tif (((CPed *)m_pEntity)->IsPed()) {\n\t\t\tif (ped->m_pFire != this) {\n\t\t\t\tExtinguish();\n\t\t\t\treturn;\n\t\t\t}\n#if defined GTAVC_JP_PATCH && !defined FIX_BUGS\n\t\t\tif (m_pEntity == CGameLogic::pShortCutTaxi && CGameLogic::ShortCutState == CGameLogic::SHORTCUT_TRANSITION) {\n\t\t\t\tExtinguish();\n\t\t\t\treturn;\n\t\t\t}\n#endif\n\t\t\tif (ped->m_nMoveState != PEDMOVE_RUN)\n\t\t\t\tm_vecPos.z -= 1.0f;\n\t\t\tif (ped->bInVehicle && ped->m_pMyVehicle) {\n\t\t\t\tif (ped->m_pMyVehicle->IsCar())\n\t\t\t\t\tped->m_pMyVehicle->m_fHealth = 75.0f;\n\t\t\t} else if (m_pEntity == (CPed *)FindPlayerPed()) {\n\t\t\t\tfDamagePlayer = 1.2f * CTimer::GetTimeStep();\n\n\t\t\t\t((CPlayerPed *)m_pEntity)->InflictDamage(\n\t\t\t\t\t(CPlayerPed *)m_pSource, WEAPONTYPE_FLAMETHROWER,\n\t\t\t\t\t\tfDamagePlayer, PEDPIECE_TORSO, 0);\n\t\t\t} else {\n\t\t\t\tfDamagePeds = 1.2f * CTimer::GetTimeStep();\n\n\t\t\t\tif (((CPlayerPed *)m_pEntity)->InflictDamage(\n\t\t\t\t\t(CPlayerPed *)m_pSource, WEAPONTYPE_FLAMETHROWER,\n\t\t\t\t\tfDamagePeds, PEDPIECE_TORSO, 0)) {\n\t\t\t\t\tm_pEntity->bRenderScorched = true;\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (m_pEntity->IsVehicle()) {\n\t\t\tif (veh->m_pCarFire != this) {\n\t\t\t\tExtinguish();\n\t\t\t\treturn;\n\t\t\t}\n#ifdef FIX_BUGS\n\t\t\tif (m_pEntity == CGameLogic::pShortCutTaxi && CGameLogic::ShortCutState == CGameLogic::SHORTCUT_TRANSITION) {\n\t\t\t\tExtinguish();\n\t\t\t\treturn;\n\t\t\t}\n#endif\n\t\t\tif (!m_bIsScriptFire) {\n\t\t\t\tfDamageVehicle = 1.2f * CTimer::GetTimeStep();\n\t\t\t\tveh->InflictDamage((CVehicle *)m_pSource, WEAPONTYPE_FLAMETHROWER, fDamageVehicle);\n\t\t\t}\n\t\t}\n\t}\n\tif (!FindPlayerVehicle() &&\n#ifdef FIX_BUGS\n\t\tFindPlayerPed() &&\n#endif\n\t\t!FindPlayerPed()->m_pFire && !(FindPlayerPed()->bFireProof)\n\t\t&& ((FindPlayerPed()->GetPosition() - m_vecPos).MagnitudeSqr() < 2.0f)) {\n\t\tFindPlayerPed()->DoStuffToGoOnFire();\n\t\tgFireManager.StartFire(FindPlayerPed(), m_pSource, 0.8f, 1);\n\t}\n\tif (CTimer::GetTimeInMilliseconds() > m_nNextTimeToAddFlames) {\n\t\tm_nNextTimeToAddFlames = CTimer::GetTimeInMilliseconds() + (m_fWaterExtinguishCountdown < 0.3f ? 400 : (m_fWaterExtinguishCountdown < 0.7f ? 200 : 80));\n\t\tfirePos = m_vecPos;\n\n\t\tif (veh && veh->IsVehicle() && veh->IsCar()) {\n\t\t\tCVehicleModelInfo *mi = ((CVehicleModelInfo*)CModelInfo::GetModelInfo(veh->GetModelIndex()));\n\t\t\tCVector ModelInfo = mi->m_positions[CAR_POS_HEADLIGHTS];\n\t\t\tModelInfo = m_pEntity->GetMatrix() * ModelInfo;\n\n\t\t\tfirePos.x = ModelInfo.x;\n\t\t\tfirePos.y = ModelInfo.y;\n\t\t\tfirePos.z = ModelInfo.z + 0.15f;\n\t\t}\n\n\t\tCParticle::AddParticle(PARTICLE_CARFLAME, firePos,\n\t\t\tCVector(0.0f, 0.0f, CGeneral::GetRandomNumberInRange(0.0125f, 0.1f) * m_fStrength),\n\t\t\t\t0, m_fStrength, 0, 0, 0, 0);\n\n\t\tCGeneral::GetRandomNumber(); CGeneral::GetRandomNumber(); CGeneral::GetRandomNumber(); /* unsure why these three rands are called */\n\n\t\tCParticle::AddParticle(PARTICLE_CARFLAME_SMOKE, firePos,\n\t\t\tCVector(0.0f, 0.0f, 0.0f), 0, 0.0f, 0, 0, 0, 0);\n\t}\n\tif (CTimer::GetTimeInMilliseconds() < m_nExtinguishTime || m_bIsScriptFire) {\n\t\tif (CTimer::GetTimeInMilliseconds() > m_nStartTime)\n\t\t\tm_nStartTime = CTimer::GetTimeInMilliseconds() + 400;\n\n\t\tnRandNumber = CGeneral::GetRandomNumber() & 127;\n\t\tlightpos.x = m_vecPos.x;\n\t\tlightpos.y = m_vecPos.y;\n\t\tlightpos.z = m_vecPos.z + 5.0f;\n\n\t\tif (!m_pEntity) {\n\t\t\tCShadows::StoreStaticShadow((uintptr)this, SHADOWTYPE_ADDITIVE, gpShadowExplosionTex, &lightpos, 7.0f, 0.0f, 0.0f, -7.0f, 0, nRandNumber / 2,\n\t\t\t                            nRandNumber / 2, 0, 10.0f, 1.0f, 40.0f, 0, 0.0f);\n\t\t}\n\t\tfGreen = nRandNumber / 128.f;\n\t\tfRed = nRandNumber / 128.f;\n\n\t\tCPointLights::AddLight(CPointLights::LIGHT_POINT, m_vecPos, CVector(0.0f, 0.0f, 0.0f), 12.0f, fRed, fGreen, 0.0f, 0, 0);\n\t} else {\n\t\tExtinguish();\n\t}\n}\n\nvoid\nCFire::ReportThisFire(void)\n{\n\tgFireManager.m_nTotalFires++;\n\tCEventList::RegisterEvent(EVENT_FIRE, m_vecPos, 1000);\n}\n\nvoid\nCFire::Extinguish(void)\n{\n\tif (m_bIsOngoing) {\n\t\tif (!m_bIsScriptFire)\n\t\t\tgFireManager.m_nTotalFires--;\n\n\t\tm_nExtinguishTime = 0;\n\t\tm_bIsOngoing = false;\n\t\tm_bExtinguishedWithWater = false;\n\n\t\tif (m_pEntity) {\n\t\t\tif (m_pEntity->IsPed()) {\n\t\t\t\tCPed *ped = (CPed*)m_pEntity;\n\t\t\t\tif (ped->CanSetPedState()) {\n\t\t\t\t\tif (ped->m_nPedState != PED_DRIVING && ped->m_nPedState != PED_FALL) {\n\t\t\t\t\t\tif (ped->IsPlayer()) {\n\t\t\t\t\t\t\tped->SetIdle();\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tped->m_nLastPedState = PED_NONE;\n\t\t\t\t\t\t\tped->SetWanderPath(0);\n\t\t\t\t\t\t\tped->SetWaitState(WAITSTATE_FINISH_FLEE, 0);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tped->m_pFire = nil;\n\t\t\t} else if (m_pEntity->IsVehicle()) {\n\t\t\t\t((CVehicle *)m_pEntity)->m_pCarFire = nil;\n\t\t\t}\n\t\t\tm_pEntity = nil;\n\t\t}\n\t}\n}\n\nvoid\nCFireManager::StartFire(CVector pos, float size, uint8 propagation)\n{\n\tCFire *fire = GetNextFreeFire();\n\n\tif (fire) {\n\t\tfire->m_bIsOngoing = true;\n\t\tfire->m_bIsScriptFire = false;\n\t\tfire->m_bPropagationFlag = propagation;\n\t\tfire->m_bAudioSet = true;\n\t\tfire->m_vecPos = pos;\n\t\tfire->m_nExtinguishTime = CTimer::GetTimeInMilliseconds() + 10000;\n\t\tfire->m_nStartTime = CTimer::GetTimeInMilliseconds() + 400;\n\t\tfire->m_pEntity = nil;\n\t\tfire->m_pSource = nil;\n\t\tfire->m_nNextTimeToAddFlames = 0;\n\t\tfire->ReportThisFire();\n\t\tfire->m_fStrength = size;\n\t\tfire->m_bExtinguishedWithWater = false;\n\t}\n}\n\nCFire *\nCFireManager::StartFire(CEntity *entityOnFire, CEntity *fleeFrom, float strength, uint8 propagation)\n{\n\tCPed *ped = (CPed *)entityOnFire;\n\tCVehicle *veh = (CVehicle *)entityOnFire;\n\n\tif (entityOnFire->IsPed()) {\n\t\tif (ped->m_pFire)\n\t\t\treturn nil;\n\t\tif (!ped->IsPedInControl())\n\t\t\treturn nil;\n\t} else if (entityOnFire->IsVehicle()) {\n\t\tif (veh->m_pCarFire)\n\t\t\treturn nil;\n\t\tif (veh->IsCar() &&  ((CAutomobile *)veh)->Damage.GetEngineStatus() >= 225)\n\t\t\treturn nil;\n\t}\n\tCFire *fire = GetNextFreeFire();\n\n\tif (fire) {\n\t\tif (entityOnFire->IsPed()) {\n\t\t\tped->m_pFire = fire;\n\t\t\tif (ped != FindPlayerPed()) {\n\t\t\t\tif (fleeFrom) {\n\t\t\t\t\tped->SetFlee(fleeFrom, 10000);\n\t\t\t\t} else {\n\t\t\t\t\tCVector2D pos = entityOnFire->GetPosition();\n\t\t\t\t\tped->SetFlee(pos, 10000);\n\t\t\t\t\tped->m_fleeFrom = nil;\n\t\t\t\t}\n\t\t\t\tped->m_fleeTimer = CTimer::GetTimeInMilliseconds() + 10000;\n\t\t\t\tped->bDrawLast = false;\n\t\t\t\tped->SetMoveState(PEDMOVE_SPRINT);\n\t\t\t\tped->SetMoveAnim();\n\t\t\t\tped->SetPedState(PED_ON_FIRE);\n\t\t\t}\n\t\t\tif (fleeFrom) {\n\t\t\t\tif (ped->m_nPedType == PEDTYPE_COP) {\n\t\t\t\t\tCEventList::RegisterEvent(EVENT_COP_SET_ON_FIRE, EVENT_ENTITY_PED,\n\t\t\t\t\t\tentityOnFire, (CPed *)fleeFrom, 10000);\n\t\t\t\t} else {\n\t\t\t\t\tCEventList::RegisterEvent(EVENT_PED_SET_ON_FIRE, EVENT_ENTITY_PED,\n\t\t\t\t\t\tentityOnFire, (CPed *)fleeFrom, 10000);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tif (entityOnFire->IsVehicle()) {\n\t\t\t\tveh->m_pCarFire = fire;\n\t\t\t\tif (CModelInfo::IsBikeModel(veh->GetModelIndex()) || CModelInfo::IsCarModel(veh->GetModelIndex()))\n        \t\t\t\tCCarAI::TellOccupantsToFleeCar(veh);\n\n\t\t\t\tif (fleeFrom) {\n\t\t\t\t\tCEventList::RegisterEvent(EVENT_CAR_SET_ON_FIRE, EVENT_ENTITY_VEHICLE,\n\t\t\t\t\t\tentityOnFire, (CPed *)fleeFrom, 10000);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfire->m_bIsOngoing = true;\n\t\tfire->m_bExtinguishedWithWater = false;\n\t\tfire->m_bIsScriptFire = false;\n\t\tfire->m_vecPos = entityOnFire->GetPosition();\n\n\t\tif (entityOnFire && entityOnFire->IsPed() && ped->IsPlayer()) {\n\t\t\tfire->m_nExtinguishTime = CTimer::GetTimeInMilliseconds() + 3333;\n\t\t} else if (entityOnFire->IsVehicle()) {\n\t\t\tfire->m_nExtinguishTime = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(4000, 5000);\n\t\t} else {\n\t\t\tfire->m_nExtinguishTime = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(10000, 11000);\n\t\t}\n\t\tfire->m_nStartTime = CTimer::GetTimeInMilliseconds() + 400;\n\t\tfire->m_pEntity = entityOnFire;\n\n\t\tentityOnFire->RegisterReference(&fire->m_pEntity);\n\t\tfire->m_pSource = fleeFrom;\n\n\t\tif (fleeFrom)\n\t\t\tfleeFrom->RegisterReference(&fire->m_pSource);\n\t\tfire->ReportThisFire();\n\t\tfire->m_nNextTimeToAddFlames = 0;\n\t\tfire->m_fStrength = strength;\n\t\tfire->m_bPropagationFlag = propagation;\n\t\tfire->m_bAudioSet = true;\n\t}\n\treturn fire;\n}\n\nvoid\nCFireManager::Update(void)\n{\n\tfor (int i = 0; i < NUM_FIRES; i++) {\n\t\tif (m_aFires[i].m_bIsOngoing)\n\t\t\tm_aFires[i].ProcessFire();\n\t}\n}\n\nCFire* CFireManager::FindNearestFire(CVector vecPos, float *pDistance)\n{\n\tint fireId = -1;\n\tfloat minDistance = 999999;\n\tfor (int j = 0; j < NUM_FIRES; j++) {\n\t\tif (!m_aFires[j].m_bIsOngoing)\n\t\t\tcontinue;\n\t\tif (m_aFires[j].m_bIsScriptFire)\n\t\t\tcontinue;\n\t\tfloat distance = (m_aFires[j].m_vecPos - vecPos).Magnitude2D();\n\t\tif (distance < minDistance) {\n\t\t\tminDistance = distance;\n\t\t\tfireId = j;\n\t\t}\n\t}\n\t*pDistance = minDistance;\n\tif (fireId != -1)\n\t\treturn &m_aFires[fireId];\n\n\treturn nil;\n}\n\nCFire *\nCFireManager::FindFurthestFire_NeverMindFireMen(CVector coords, float minRange, float maxRange)\n{\n\tint furthestFire = -1;\n\tfloat lastFireDist = 0.0f;\n\tfloat fireDist;\n\n\tfor (int i = 0; i < NUM_FIRES; i++) {\n\t\tif (m_aFires[i].m_bIsOngoing && !m_aFires[i].m_bIsScriptFire) {\n\t\t\tfireDist = (m_aFires[i].m_vecPos - coords).Magnitude2D();\n\t\t\tif (fireDist > minRange && fireDist < maxRange && fireDist > lastFireDist) {\n\t\t\t\tlastFireDist = fireDist;\n\t\t\t\tfurthestFire = i;\n\t\t\t}\n\t\t}\n\t}\n\tif (furthestFire == -1)\n\t\treturn nil;\n\telse\n\t\treturn &m_aFires[furthestFire];\n}\n\nCFire *\nCFireManager::GetNextFreeFire(void)\n{\n\tfor (int i = 0; i < NUM_FIRES; i++) {\n\t\tif (!m_aFires[i].m_bIsOngoing && !m_aFires[i].m_bIsScriptFire)\n\t\t\treturn &m_aFires[i];\n\t}\n\treturn nil;\n}\n\nuint32\nCFireManager::GetTotalActiveFires(void) const\n{\n\treturn m_nTotalFires;\n}\n\nvoid\nCFireManager::ExtinguishPoint(CVector point, float range)\n{\n\tfor (int i = 0; i < NUM_FIRES; i++) {\n\t\tif (m_aFires[i].m_bIsOngoing) {\n\t\t\tif ((point - m_aFires[i].m_vecPos).MagnitudeSqr() < sq(range))\n\t\t\t\tm_aFires[i].Extinguish();\n\t\t}\n\t}\n}\n\nbool\nCFireManager::ExtinguishPointWithWater(CVector point, float range)\n{\n    int i;\n    for (i = 0; i < NUM_FIRES;) {\n        if (m_aFires[i].m_bIsOngoing && (point - m_aFires[i].m_vecPos).MagnitudeSqr() < sq(range)) {\n                break;\n        }\n        if (++i >= NUM_FIRES)\n          return false;\n    }\n    \n\tCFire *fireToExtinguish = &m_aFires[i];\n\tfireToExtinguish->m_fWaterExtinguishCountdown -= 0.012f * CTimer::GetTimeStep();\n\tCVector steamPos = fireToExtinguish->m_vecPos +\n\t\tCVector((CGeneral::GetRandomNumber() - 128) * 3.1f / 200.f,\n\t\t\t(CGeneral::GetRandomNumber() - 128) * 3.1f / 200.f,\n\t\t\tCGeneral::GetRandomNumber() / 200.f);\n\n\tCParticle::AddParticle(PARTICLE_STEAM_NY_SLOWMOTION, steamPos, CVector(0.f, 0.f, 0.2f), nil, 0.5f);\n\tCParticle::AddParticle(PARTICLE_STEAM_NY_SLOWMOTION, steamPos, CVector(0.f, 0.f, 0.1f), nil, 0.8f);\n\tfireToExtinguish->m_bExtinguishedWithWater = true;\n\tif (fireToExtinguish->m_fWaterExtinguishCountdown < 0.0f )\n\t  fireToExtinguish->Extinguish();\n\n\treturn true;\n}\n\nint32\nCFireManager::StartScriptFire(const CVector &pos, CEntity *target, float strength, uint8 propagation)\n{\n\tCFire *fire;\n\tCPed *ped = (CPed *)target;\n\tCVehicle *veh = (CVehicle *)target;\n\n\tif (target) {\n\t\tif (target->IsPed()) {\n\t\t\tif (ped->m_pFire)\n\t\t\t\tped->m_pFire->Extinguish();\n\t\t} else if (target->IsVehicle()) {\n\t\t\tif (veh->m_pCarFire)\n\t\t\t\tveh->m_pCarFire->Extinguish();\n\t\t\tif (veh->IsCar() && ((CAutomobile *)veh)->Damage.GetEngineStatus() >= 225) {\n\t\t\t\t((CAutomobile *)veh)->Damage.SetEngineStatus(215);\n\t\t\t}\n\t\t}\n\t}\n\n\tfire = GetNextFreeFire();\n\tfire->m_bIsOngoing = true;\n\tfire->m_bIsScriptFire = true;\n\tfire->m_bPropagationFlag = propagation;\n\tfire->m_bAudioSet = true;\n\tfire->m_vecPos = pos;\n\tfire->m_nStartTime = CTimer::GetTimeInMilliseconds() + 400;\n\tfire->m_pEntity = target;\n\tfire->m_bExtinguishedWithWater = false;\n\n\tif (target)\n\t\ttarget->RegisterReference(&fire->m_pEntity);\n\tfire->m_pSource = nil;\n\tfire->m_nNextTimeToAddFlames = 0;\n\tfire->m_fStrength = strength;\n\tfire->m_fWaterExtinguishCountdown = 1.0f;\n\n\tif (target) {\n\t\tif (target->IsPed()) {\n\t\t\tped->m_pFire = fire;\n\t\t\tif (target != (CVehicle *)FindPlayerPed()) {\n\t\t\t\tCVector2D pos = target->GetPosition();\n\t\t\t\tped->SetFlee(pos, 10000);\n\t\t\t\tped->SetMoveAnim();\n\t\t\t\tped->SetPedState(PED_ON_FIRE);\n\t\t\t}\n\t\t} else if (target->IsVehicle()) {\n\t\t\tveh->m_pCarFire = fire;\n\t\t}\n\t}\n\treturn fire - m_aFires;\n}\n\nbool\nCFireManager::IsScriptFireExtinguish(int16 index)\n{\n\treturn !m_aFires[index].m_bIsOngoing;\n}\n\nvoid\nCFireManager::RemoveAllScriptFires(void)\n{\n\tfor (int i = 0; i < NUM_FIRES; i++) {\n\t\tif (m_aFires[i].m_bIsScriptFire) {\n\t\t\tRemoveScriptFire(i);\n\t\t}\n\t}\n}\n\nvoid\nCFireManager::RemoveScriptFire(int16 index)\n{\n\tm_aFires[index].Extinguish();\n\tm_aFires[index].m_bIsScriptFire = false;\n}\n\nvoid\nCFireManager::SetScriptFireAudio(int16 index, bool state)\n{\n\tm_aFires[index].m_bAudioSet = state;\n}\n"
  },
  {
    "path": "src/core/Fire.h",
    "content": "#pragma once\n\nclass CEntity;\n\nclass CFire\n{\npublic:\n\tbool m_bIsOngoing;\n\tbool m_bIsScriptFire;\n\tbool m_bPropagationFlag;\n\tbool m_bAudioSet;\n\tCVector m_vecPos;\n\tCEntity *m_pEntity;\n\tCEntity *m_pSource;\n\tuint32 m_nExtinguishTime;\n\tuint32 m_nStartTime;\n\tuint32 m_nNextTimeToAddFlames;\n\tfloat m_fStrength;\n\tfloat m_fWaterExtinguishCountdown;\n\tbool m_bExtinguishedWithWater;\n\n\tCFire();\n\t~CFire();\n\tvoid ProcessFire(void);\n\tvoid ReportThisFire(void);\n\tvoid Extinguish(void);\n};\n\nclass CFireManager\n{\n\tenum {\n\t\tMAX_FIREMEN_ATTENDING = 2,\n\t};\npublic:\n\tuint32 m_nTotalFires;\n\tCFire m_aFires[NUM_FIRES];\n\n\tvoid StartFire(CVector pos, float size, uint8 propagation);\n\tCFire *StartFire(CEntity *entityOnFire, CEntity *fleeFrom, float strength, uint8 propagation);\n\tvoid Update(void);\n\tCFire *FindFurthestFire_NeverMindFireMen(CVector coords, float minRange, float maxRange);\n\tCFire *FindNearestFire(CVector vecPos, float *pDistance);\n\tCFire *GetNextFreeFire(void);\n\tuint32 GetTotalActiveFires() const;\n\tvoid ExtinguishPoint(CVector point, float range);\n\tbool ExtinguishPointWithWater(CVector point, float range);\n\tint32 StartScriptFire(const CVector &pos, CEntity *target, float strength, uint8 propagation);\n\tbool IsScriptFireExtinguish(int16 index);\n\tvoid RemoveAllScriptFires(void);\n\tvoid RemoveScriptFire(int16 index);\n\tvoid SetScriptFireAudio(int16 index, bool state);\n};\nextern CFireManager gFireManager;\n"
  },
  {
    "path": "src/core/FrontEndControls.cpp",
    "content": "#include \"common.h\"\n#include \"main.h\"\n#include \"Timer.h\"\n#include \"Sprite2d.h\"\n#include \"Text.h\"\n#include \"Font.h\"\n#include \"FrontEndControls.h\"\n\n#define X SCREEN_SCALE_X\n#define Y(x) SCREEN_SCALE_Y(float(x)*(float(DEFAULT_SCREEN_HEIGHT)/float(SCREEN_HEIGHT_PAL)))\n\nvoid\nCPlaceableShText::Draw(float x, float y)\n{\n\tif(m_text == nil)\n\t\treturn;\n\n\tif(m_bRightJustify)\n\t\tCFont::SetRightJustifyOn();\n\tif(m_bDropShadow){\n\t\tCFont::SetDropShadowPosition(m_shadowOffset.x);\n\t\tCFont::SetDropColor(m_shadowColor);\n\t}\n\tCFont::SetColor(m_color);\n\tCFont::PrintString(x+m_position.x, y+m_position.y, m_text);\n\tif(m_bDropShadow)\n\t\tCFont::SetDropShadowPosition(0);\n\tif(m_bRightJustify)\n\t\tCFont::SetRightJustifyOff();\n}\n\nvoid\nCPlaceableShText::Draw(const CRGBA &color, float x, float y)\n{\n\tif(m_text == nil)\n\t\treturn;\n\n\tif(m_bRightJustify)\n\t\tCFont::SetRightJustifyOn();\n\tif(m_bDropShadow){\n\t\tCFont::SetDropShadowPosition(m_shadowOffset.x);\n\t\tCFont::SetDropColor(m_shadowColor);\n\t}\n\tCFont::SetColor(color);\n\tCFont::PrintString(x+m_position.x, y+m_position.y, m_text);\n\tif(m_bDropShadow)\n\t\tCFont::SetDropShadowPosition(0);\n\tif(m_bRightJustify)\n\t\tCFont::SetRightJustifyOff();\n}\n\nvoid\nCPlaceableShTextTwoLines::Draw(float x, float y)\n{\n\tif(m_line1.m_text == nil && m_line2.m_text == nil)\n\t\treturn;\n\n\tif(m_bRightJustify)\n\t\tCFont::SetRightJustifyOn();\n\tif(m_bDropShadow){\n\t\tCFont::SetDropShadowPosition(m_shadowOffset.x);\n\t\tCFont::SetDropColor(m_shadowColor);\n\t}\n\n\tif(m_line1.m_text){\n\t\tCFont::SetColor(m_line1.m_color);\n\t\tCFont::PrintString(x+m_line1.m_position.x, y+m_line1.m_position.y, m_line1.m_text);\n\t}\n\tif(m_line2.m_text){\n\t\tCFont::SetColor(m_line2.m_color);\n\t\tCFont::PrintString(x+m_line2.m_position.x, y+m_line2.m_position.y, m_line2.m_text);\n\t}\n\n\tif(m_bDropShadow)\n\t\tCFont::SetDropShadowPosition(0);\n\tif(m_bRightJustify)\n\t\tCFont::SetRightJustifyOff();\n}\n\nvoid\nCPlaceableShTextTwoLines::Draw(const CRGBA &color, float x, float y)\n{\n\tif(m_line1.m_text == nil && m_line2.m_text == nil)\n\t\treturn;\n\n\tif(m_bRightJustify)\n\t\tCFont::SetRightJustifyOn();\n\tif(m_bDropShadow){\n\t\tCFont::SetDropShadowPosition(m_shadowOffset.x);\n\t\tCFont::SetDropColor(m_shadowColor);\n\t}\n\n\tif(m_line1.m_text){\n\t\tCFont::SetColor(color);\n\t\tCFont::PrintString(x+m_line1.m_position.x, y+m_line1.m_position.y, m_line1.m_text);\n\t}\n\tif(m_line2.m_text){\n\t\tCFont::SetColor(color);\n\t\tCFont::PrintString(x+m_line2.m_position.x, y+m_line2.m_position.y, m_line2.m_text);\n\t}\n\n\tif(m_bDropShadow)\n\t\tCFont::SetDropShadowPosition(0);\n\tif(m_bRightJustify)\n\t\tCFont::SetRightJustifyOff();\n}\n\nvoid\nCPlaceableShOption::Draw(const CRGBA &highlightColor, float x, float y, bool bHighlight)\n{\n\tif(bHighlight)\n\t\tCPlaceableShText::Draw(highlightColor, x, y);\n\telse if(m_bSelected)\n\t\tCPlaceableShText::Draw(m_selectedColor, x, y);\n\telse\n\t\tCPlaceableShText::Draw(x, y);\n}\n\nvoid\nCPlaceableShOptionTwoLines::Draw(const CRGBA &highlightColor, float x, float y, bool bHighlight)\n{\n\tif(bHighlight)\n\t\tCPlaceableShTextTwoLines::Draw(highlightColor, x, y);\n\telse if(m_bSelected)\n\t\tCPlaceableShTextTwoLines::Draw(m_selectedColor, x, y);\n\telse\n\t\tCPlaceableShTextTwoLines::Draw(x, y);\n}\n\nvoid\nCPlaceableSprite::Draw(float x, float y)\n{\n\tDraw(m_color, x, y);\n}\n\nvoid\nCPlaceableSprite::Draw(const CRGBA &color, float x, float y)\n{\n\tif(m_pSprite)\n\t\tm_pSprite->Draw(CRect(m_position.x+x, m_position.y+y,\n\t\t                      m_position.x+x + m_size.x, m_position.y+y + m_size.y),\n\t\t                color);\n}\n\nvoid\nCPlaceableShSprite::Draw(float x, float y)\n{\n\tif(m_bDropShadow)\n\t\tm_shadow.Draw(m_shadow.m_color, m_sprite.m_position.x+x, m_sprite.m_position.y+y);\n\tm_sprite.Draw(x, y);\n}\n\n\n/*\n * CMenuPictureAndText\n */\n\nvoid\nCMenuPictureAndText::SetNewOldShadowWrapX(bool bWrapX, float newWrapX, float oldWrapX)\n{\n\tm_bWrap = bWrapX;\n\tm_wrapX = newWrapX;\n\tm_oldWrapx = oldWrapX;\n}\n\nvoid\nCMenuPictureAndText::SetNewOldTextScale(bool bTextScale, const CVector2D &newScale, const CVector2D &oldScale)\n{\n\tm_bSetTextScale = bTextScale;\n\tm_textScale = newScale;\n\tm_oldTextScale = oldScale;\n}\n\nvoid\nCMenuPictureAndText::SetTextsColor(CRGBA const &color)\n{\n\tint i;\n\tfor(i = 0; i < m_numTexts; i++)\n\t\tm_texts[i].m_color = color;\n}\n\nvoid\nCMenuPictureAndText::AddText(wchar *text, float positionX, float positionY, CRGBA const &color, bool bRightJustify)\n{\n\tint i;\n\tif(m_numTexts >= 20)\n\t\treturn;\n\ti = m_numTexts++;\n\tm_texts[i].m_text = text;\n\tm_texts[i].m_position.x = positionX;\n\tm_texts[i].m_position.y = positionY;\n\tm_texts[i].m_color = color;\n\tm_texts[i].m_bRightJustify = bRightJustify;\n}\n\nvoid\nCMenuPictureAndText::AddPicture(CSprite2d *sprite, CSprite2d *shadow, float positionX, float positionY, float width, float height, CRGBA const &color)\n{\n\tint i;\n\tif(m_numSprites >= 5)\n\t\treturn;\n\ti = m_numSprites++;\n\tm_sprites[i].m_sprite.m_pSprite = sprite;\n\tm_sprites[i].m_shadow.m_pSprite = shadow;\n\tm_sprites[i].m_sprite.m_position.x = positionX;\n\tm_sprites[i].m_sprite.m_position.y = positionY;\n\tm_sprites[i].m_sprite.m_size.x = width;\n\tm_sprites[i].m_sprite.m_size.y = height;\n\tm_sprites[i].m_shadow.m_size.x = width;\n\tm_sprites[i].m_shadow.m_size.y = height;\n\tm_sprites[i].m_sprite.m_color = color;\n}\n\nvoid\nCMenuPictureAndText::AddPicture(CSprite2d *sprite, float positionX, float positionY, float width, float height, CRGBA const &color)\n{\n\tint i;\n\tif(m_numSprites >= 5)\n\t\treturn;\n\ti = m_numSprites++;\n\tm_sprites[i].m_sprite.m_pSprite = sprite;\n\tm_sprites[i].m_shadow.m_pSprite = nil;\n\tm_sprites[i].m_sprite.m_position.x = positionX;\n\tm_sprites[i].m_sprite.m_position.y = positionY;\n\tm_sprites[i].m_sprite.m_size.x = width;\n\tm_sprites[i].m_sprite.m_size.y = height;\n\tm_sprites[i].m_shadow.m_size.x = width;\n\tm_sprites[i].m_shadow.m_size.y = height;\n\tm_sprites[i].m_sprite.m_color = color;\n}\n\nvoid\nCMenuPictureAndText::Draw(CRGBA const &,CRGBA const &, float x, float y)\n{\n\tint i;\n\n\tfor(i = 0; i < m_numSprites; i++)\n\t\tm_sprites[i].Draw(m_position.x+x, m_position.y+y);\n\n\tif(m_bSetTextScale)\n\t\tCFont::SetScale(m_textScale.x, m_textScale.y);\n\tfor(i = 0; i < m_numTexts; i++)\n\t\tif(m_bWrap)\n\t\t\tm_texts[i].DrawShWrap(m_position.x+x, m_position.y+y, m_wrapX, m_oldWrapx);\n\t\telse\n\t\t\tm_texts[i].Draw(m_position.x+x, m_position.y+y);\n\tif(m_bSetTextScale)\n\t\tCFont::SetScale(m_oldTextScale.x, m_oldTextScale.y);\n}\n\nvoid\nCMenuPictureAndText::SetAlpha(uint8 alpha)\n{\n\tint i;\n\n\tfor(i = 0; i < m_numSprites; i++)\n\t\tm_sprites[i].SetAlpha(alpha);\n\tfor(i = 0; i < m_numTexts; i++)\n\t\tm_texts[i].SetAlpha(alpha);\n}\n\nvoid\nCMenuPictureAndText::SetShadows(bool bDropShadows, const CRGBA &shadowColor, const CVector2D &shadowOffset)\n{\n\tint i;\n\n\tfor(i = 0; i < 5; i++)\n\t\tm_sprites[i].SetShadows(bDropShadows, shadowColor, shadowOffset);\n\tfor(i = 0; i < 20; i++)\n\t\tm_texts[i].SetShadows(bDropShadows, shadowColor, shadowOffset);\n}\n\n/*\n * CMenuMultiChoice\n */\n\nvoid\nCMenuMultiChoice::AddTitle(wchar *text, float positionX, float positionY, bool bRightJustify)\n{\n\tm_title.m_text = text;\n\tm_title.SetPosition(positionX, positionY, bRightJustify);\n}\n\nCPlaceableShOption*\nCMenuMultiChoice::AddOption(wchar *text, float positionX, float positionY, bool bSelected, bool bRightJustify)\n{\n\tif(m_numOptions == NUM_MULTICHOICE_OPTIONS)\n\t\treturn nil;\n\tm_options[m_numOptions].m_text = text;\n\tm_options[m_numOptions].SetPosition(positionX, positionY);\n\tm_options[m_numOptions].m_bSelected = bSelected;\n\tm_options[m_numOptions].m_bRightJustify = bRightJustify;\n\treturn &m_options[m_numOptions++];\n}\n\nvoid\nCMenuMultiChoice::SetColors(const CRGBA &title, const CRGBA &normal, const CRGBA &selected)\n{\n\tint i;\n\tm_title.SetColor(title);\n\tfor(i = 0; i < NUM_MULTICHOICE_OPTIONS; i++)\n\t\tm_options[i].SetColors(normal, selected);\n}\n\nvoid\nCMenuMultiChoice::SetNewOldTextScale(bool bTextScale, const CVector2D &newScale, const CVector2D &oldScale, bool bTitleTextScale)\n{\n\tm_bSetTextScale = bTextScale;\n\tm_textScale = newScale;\n\tm_oldTextScale = oldScale;\n\tm_bSetTitleTextScale = bTitleTextScale;\n}\n\nvoid\nCMenuMultiChoice::Draw(CRGBA const &optionHighlight ,CRGBA const &titleHighlight, float x, float y)\n{\n\tint i;\n\n\tif(m_bSetTextScale && m_bSetTitleTextScale)\n\t\tCFont::SetScale(m_textScale.x, m_textScale.y);\n\tif(m_cursor == -1)\n\t\tm_title.Draw(m_position.x+x, m_position.y+y);\n\telse\n\t\tm_title.Draw(titleHighlight, m_position.x+x, m_position.y+y);\n\n\tif(m_bSetTextScale)\n\t\tCFont::SetScale(m_textScale.x, m_textScale.y);\n\n\tif(m_cursor == -1)\n\t\tfor(i = 0; i < m_numOptions; i++)\n\t\t\tm_options[i].Draw(CRGBA(0,0,0,0), m_position.x+x, m_position.y+y, false);\n\telse\n\t\tfor(i = 0; i < m_numOptions; i++){\n\t\t\tif(i == m_cursor)\n\t\t\t\tm_options[i].Draw(optionHighlight, m_position.x+x, m_position.y+y);\n\t\t\telse\n\t\t\t\tm_options[i].Draw(CRGBA(0,0,0,0), m_position.x+x, m_position.y+y, false);\n\t\t}\n\n\tif(m_bSetTextScale){\n\t\tCFont::DrawFonts();\n\t\tCFont::SetScale(m_oldTextScale.x, m_oldTextScale.y);\n\t}\n}\n\nvoid\nCMenuMultiChoice::DrawNormal(float x, float y)\n{\n\tint i;\n\n\tif(m_bSetTextScale && m_bSetTitleTextScale)\n\t\tCFont::SetScale(m_textScale.x, m_textScale.y);\n\tm_title.Draw(m_position.x+x, m_position.y+y);\n\n\tif(m_bSetTextScale)\n\t\tCFont::SetScale(m_textScale.x, m_textScale.y);\n\n\tfor(i = 0; i < m_numOptions; i++)\n\t\tm_options[i].Draw(CRGBA(0,0,0,0), m_position.x+x, m_position.y+y, false);\n\n\tif(m_bSetTextScale){\n\t\tCFont::DrawFonts();\n\t\tCFont::SetScale(m_oldTextScale.x, m_oldTextScale.y);\n\t}\n}\n\nvoid\nCMenuMultiChoice::DrawHighlighted(CRGBA const &titleHighlight, float x, float y)\n{\n\tint i;\n\n\tif(m_bSetTextScale && m_bSetTitleTextScale)\n\t\tCFont::SetScale(m_textScale.x, m_textScale.y);\n\tif(m_cursor == -1)\n\t\tm_title.Draw(m_position.x+x, m_position.y+y);\n\telse\n\t\tm_title.Draw(titleHighlight, m_position.x+x, m_position.y+y);\n\n\tif(m_bSetTextScale)\n\t\tCFont::SetScale(m_textScale.x, m_textScale.y);\n\n\tfor(i = 0; i < m_numOptions; i++)\n\t\tm_options[i].Draw(CRGBA(0,0,0,0), m_position.x+x, m_position.y+y, false);\n\n\tif(m_bSetTextScale){\n\t\tCFont::DrawFonts();\n\t\tCFont::SetScale(m_oldTextScale.x, m_oldTextScale.y);\n\t}\n}\n\nvoid\nCMenuMultiChoice::SetAlpha(uint8 alpha)\n{\n\tint i;\n\tm_title.SetAlpha(alpha);\n\tfor(i = 0; i < NUM_MULTICHOICE_OPTIONS; i++)\n\t\tm_options[i].SetAlpha(alpha);\n}\n\nvoid\nCMenuMultiChoice::SetShadows(bool bDropShadows, CRGBA const &shadowColor, CVector2D const &shadowOffset)\n{\n\tint i;\n\tm_title.SetShadows(bDropShadows, shadowColor, shadowOffset);\n\tfor(i = 0; i < NUM_MULTICHOICE_OPTIONS; i++)\n\t\tm_options[i].SetShadows(bDropShadows, shadowColor, shadowOffset);\n}\n\n\nbool\nCMenuMultiChoice::GoNext(void)\n{\n\tif(m_cursor == m_numOptions-1){\n\t\tm_cursor = -1;\n\t\treturn false;\n\t}else{\n\t\tm_cursor++;\n\t\treturn true;\n\t}\n}\n\nbool\nCMenuMultiChoice::GoPrev(void)\n{\n\tif(m_cursor == 0){\n\t\tm_cursor = -1;\n\t\treturn false;\n\t}else{\n\t\tm_cursor--;\n\t\treturn true;\n\t}\n}\n\nvoid\nCMenuMultiChoice::SelectCurrentOptionUnderCursor(void)\n{\n\tint i;\n\tif(m_cursor == -1)\n\t\treturn;\n\tfor(i = 0; i < NUM_MULTICHOICE_OPTIONS; i++)\n\t\tm_options[i].m_bSelected = false;\n\tm_options[m_cursor].m_bSelected = true;\n}\n\nint\nCMenuMultiChoice::GetMenuSelection(void)\n{\n\tint i;\n\tfor(i = 0; i < NUM_MULTICHOICE_OPTIONS; i++)\n\t\tif(m_options[i].m_bSelected)\n\t\t\treturn i;\n\treturn -1;\n}\n\nvoid\nCMenuMultiChoice::SetMenuSelection(int selection)\n{\n\tint i;\n\tfor(i = 0; i < NUM_MULTICHOICE_OPTIONS; i++)\n\t\tm_options[i].m_bSelected = false;\n\tm_options[selection%NUM_MULTICHOICE_OPTIONS].m_bSelected = true;\n}\n\n/*\n * CMenuMultiChoiceTriggered\n */\n\nvoid\nCMenuMultiChoiceTriggered::Initialise(void)\n{\n\tint i;\n\tfor(i = 0; i < NUM_MULTICHOICE_OPTIONS; i++)\n\t\tm_triggers[i] = nil;\n\tm_defaultCancel = nil;\n}\n\nCPlaceableShOption*\nCMenuMultiChoiceTriggered::AddOption(wchar *text, float positionX, float positionY, Trigger trigger, bool bSelected, bool bRightJustify)\n{\n\tCPlaceableShOption *option;\n\toption = CMenuMultiChoice::AddOption(text, positionX, positionY, bSelected, bRightJustify);\n\tif(option)\n\t\tm_triggers[m_numOptions-1] = trigger;\n\treturn option;\n}\n\nvoid\nCMenuMultiChoiceTriggered::SelectCurrentOptionUnderCursor(void)\n{\n\tCMenuMultiChoice::SelectCurrentOptionUnderCursor();\n\tif(m_cursor != -1 && m_triggers[m_cursor] != nil )\n\t\tm_triggers[m_cursor](this);\n}\n\nvoid\nCMenuMultiChoiceTriggered::SelectDefaultCancelAction(void)\n{\n\tif(m_defaultCancel)\n\t\tm_defaultCancel(this);\n}\n\n/*\n * CMenuMultiChoiceTriggeredAlways\n */\n\nvoid\nCMenuMultiChoiceTriggeredAlways::Draw(CRGBA const &optionHighlight, CRGBA const &titleHighlight, float x, float y)\n{\n\tif(m_alwaysTrigger)\n\t\tm_alwaysTrigger(this);\n\tCMenuMultiChoiceTriggered::Draw(optionHighlight, titleHighlight, x, y);\n}\n\nvoid\nCMenuMultiChoiceTriggeredAlways::DrawNormal(float x, float y)\n{\n\tif(m_alwaysNormalTrigger)\n\t\tm_alwaysNormalTrigger(this);\n\tCMenuMultiChoiceTriggered::DrawNormal(x, y);\n}\n\nvoid\nCMenuMultiChoiceTriggeredAlways::DrawHighlighted(CRGBA const &titleHighlight, float x, float y)\n{\n\tif(m_alwaysHighlightTrigger)\n\t\tm_alwaysHighlightTrigger(this);\n\tCMenuMultiChoiceTriggered::DrawHighlighted(titleHighlight, x, y);\n}\n\n/*\n * CMenuMultiChoicePictured\n */\n\nvoid\nCMenuMultiChoicePictured::Initialise(void)\n{\n\tint i;\n\tfor(i = 0; i < NUM_MULTICHOICE_OPTIONS; i++)\n\t\tm_bHasSprite[i] = false;\n\tfor(i = 0; i < NUM_MULTICHOICE_OPTIONS; i++)\n\t\tm_sprites[i].m_pSprite = nil;\n}\n\nCPlaceableShOption*\nCMenuMultiChoicePictured::AddOption(CSprite2d *sprite, float positionX, float positionY, const CVector2D &size, bool bSelected)\n{\n\tCPlaceableShOption *option;\n\toption = CMenuMultiChoice::AddOption(nil, 0.0f, 0.0f, bSelected, false);\n\tif(option){\n\t\tm_sprites[m_numOptions-1].m_pSprite = sprite;\n\t\tm_sprites[m_numOptions-1].SetPosition(positionX, positionY);\n\t\tm_sprites[m_numOptions-1].m_size = size;\n\t\tm_bHasSprite[m_numOptions-1] = true;\n\t}\n\treturn option;\n}\n\nvoid\nCMenuMultiChoicePictured::Draw(const CRGBA &optionHighlight, const CRGBA &titleHighlight, float x, float y)\n{\n\tint i;\n\n\t// The title and all the text\n\tCMenuMultiChoice::Draw(optionHighlight, titleHighlight, x, y);\n\n\tCRGBA selectedColor = m_options[0].GetSelectedColor();\n\tCRGBA color = m_options[0].GetColor();\n\n\t// The sprites\n\tif(m_cursor == -1){\n\t\tfor(i = 0; i < m_numOptions; i++)\n\t\t\tif(m_bHasSprite[i]){\n\t\t\t\tif(m_options[i].m_bSelected)\n\t\t\t\t\tm_sprites[i].Draw(selectedColor, m_position.x+x, m_position.y+y);\n\t\t\t\telse\n\t\t\t\t\tm_sprites[i].Draw(color, m_position.x+x, m_position.y+y);\n\t\t\t}\n\t}else{\n\t\tfor(i = 0; i < m_numOptions; i++)\n\t\t\tif(i == m_cursor){\n\t\t\t\tif(m_bHasSprite[i])\n\t\t\t\t{\n\t\t\t\t\tuint8 color = Max(Max(optionHighlight.r, optionHighlight.g), optionHighlight.b);\n\t\t\t\t\tm_sprites[i].Draw(CRGBA(color, color, color, optionHighlight.a), m_position.x+x, m_position.y+y);\n\t\t\t\t}\n\t\t\t}else{\n\t\t\t\tif(m_bHasSprite[i]){\n\t\t\t\t\tif(m_options[i].m_bSelected)\n\t\t\t\t\t\tm_sprites[i].Draw(selectedColor, m_position.x+x, m_position.y+y);\n\t\t\t\t\telse\n\t\t\t\t\t\tm_sprites[i].Draw(color, m_position.x+x, m_position.y+y);\n\t\t\t\t}\n\t\t\t}\n\t}\n}\n\nvoid\nCMenuMultiChoicePictured::DrawNormal(float x, float y)\n{\n\tint i;\n\n\t// The title and all the text\n\tCMenuMultiChoice::DrawNormal(x, y);\n\n\tCRGBA selectedColor = m_options[0].GetSelectedColor();\n\tCRGBA color = m_options[0].GetColor();\n\n\t// The sprites\n\tfor(i = 0; i < m_numOptions; i++)\n\t\tif(m_bHasSprite[i]){\n\t\t\tif(m_options[i].m_bSelected)\n\t\t\t\tm_sprites[i].Draw(selectedColor, m_position.x+x, m_position.y+y);\n\t\t\telse\n\t\t\t\tm_sprites[i].Draw(color, m_position.x+x, m_position.y+y);\n\t\t}\n}\n\nvoid\nCMenuMultiChoicePictured::DrawHighlighted(const CRGBA &titleHighlight, float x, float y)\n{\n\tint i;\n\n\t// The title and all the text\n\tCMenuMultiChoice::DrawHighlighted(titleHighlight, x, y);\n\n\tCRGBA selectedColor = m_options[0].GetSelectedColor();\n\tCRGBA color = m_options[0].GetColor();\n\n\t// The sprites\n\tfor(i = 0; i < m_numOptions; i++)\n\t\tif(m_bHasSprite[i]){\n\t\t\tif(m_options[i].m_bSelected)\n\t\t\t\tm_sprites[i].Draw(selectedColor, m_position.x+x, m_position.y+y);\n\t\t\telse\n\t\t\t\tm_sprites[i].Draw(color, m_position.x+x, m_position.y+y);\n\t\t}\n}\n\nvoid\nCMenuMultiChoicePictured::SetAlpha(uint8 alpha)\n{\n\tint i;\n\tCMenuMultiChoice::SetAlpha(alpha);\n\tfor(i = 0; i < NUM_MULTICHOICE_OPTIONS; i++)\n\t\tm_sprites[i].SetAlpha(alpha);\n\n}\n\n\n/*\n * CMenuMultiChoicePicturedTriggered\n */\n\nvoid\nCMenuMultiChoicePicturedTriggered::Initialise(void)\n{\n\tint i;\n\tfor(i = 0; i < NUM_MULTICHOICE_OPTIONS; i++)\n\t\tm_triggers[i] = nil;\n\tm_defaultCancel = nil;\t// missing on PS2\n}\n\nCPlaceableShOption*\nCMenuMultiChoicePicturedTriggered::AddOption(CSprite2d *sprite, float positionX, float positionY, const CVector2D &size, Trigger trigger, bool bSelected)\n{\n\tCPlaceableShOption *option;\n\toption = CMenuMultiChoicePictured::AddOption(sprite, positionX, positionY, size, bSelected);\n\tif(option)\n\t\tm_triggers[m_numOptions-1] = trigger;\n\treturn option;\n}\n\nvoid\nCMenuMultiChoicePicturedTriggered::SelectCurrentOptionUnderCursor(void)\n{\n\tCMenuMultiChoice::SelectCurrentOptionUnderCursor();\n\tif(m_cursor != -1)\n\t\tm_triggers[m_cursor](this);\n}\n\nvoid\nCMenuMultiChoicePicturedTriggered::SelectDefaultCancelAction(void)\n{\n\tif(m_defaultCancel)\n\t\tm_defaultCancel(this);\n}\n\n/*\n * CMenuMultiChoicePicturedTriggeredAnyMove\n */\n\nvoid\nCMenuMultiChoicePicturedTriggeredAnyMove::Initialise(void)\n{\n\tint i;\n\tCMenuMultiChoicePicturedTriggered::Initialise();\n\tfor(i = 0; i < NUM_MULTICHOICE_OPTIONS; i++){\n\t\tm_moveTab[i].right = -1;\n\t\tm_moveTab[i].left = -1;\n\t\tm_moveTab[i].down = -1;\n\t\tm_moveTab[i].up = -1;\n\t}\n}\n\nCPlaceableShOption*\nCMenuMultiChoicePicturedTriggeredAnyMove::AddOption(CSprite2d *sprite, FEC_MOVETAB *moveTab, float positionX, float positionY, const CVector2D &size, Trigger trigger, bool bSelected)\n{\n\tCPlaceableShOption *option;\n\toption = CMenuMultiChoicePicturedTriggered::AddOption(sprite, positionX, positionY, size, trigger, bSelected);\n\tif(option && moveTab)\n\t\tm_moveTab[m_numOptions-1] = *moveTab;\n\treturn option;\n}\n\nbool\nCMenuMultiChoicePicturedTriggeredAnyMove::GoDown(void)\n{\n\tint move = m_moveTab[m_cursor].down;\n\tif(move == -1)\n\t\treturn GoNext();\n\tm_cursor = move;\n\treturn true;\n}\n\nbool\nCMenuMultiChoicePicturedTriggeredAnyMove::GoUp(void)\n{\n\tint move = m_moveTab[m_cursor].up;\n\tif(move == -1)\n\t\treturn GoPrev();\n\tm_cursor = move;\n\treturn true;\n}\n\nbool\nCMenuMultiChoicePicturedTriggeredAnyMove::GoLeft(void)\n{\n\tint move = m_moveTab[m_cursor].left;\n\tif(move == -1)\n\t\treturn GoPrev();\n\tm_cursor = move;\n\treturn true;\n}\n\nbool\nCMenuMultiChoicePicturedTriggeredAnyMove::GoRight(void)\n{\n\tint move = m_moveTab[m_cursor].right;\n\tif(move == -1)\n\t\treturn GoNext();\n\tm_cursor = move;\n\treturn true;\n}\n\n\n/*\n * CMenuMultiChoiceTwoLines\n */\n\nvoid\nCMenuMultiChoiceTwoLines::AddTitle(wchar *text, float positionX, float positionY, bool bRightJustify)\n{\n\tm_title.m_text = text;\n\tm_title.SetPosition(positionX, positionY, bRightJustify);\n}\n\nCPlaceableShOptionTwoLines*\nCMenuMultiChoiceTwoLines::AddOption(wchar *text, float positionX, float positionY, bool bSelected, bool bRightJustify)\n{\n\treturn AddOption(text, positionX, positionY, nil, 0.0f, 0.0f, bSelected, bRightJustify);\n}\n\nCPlaceableShOptionTwoLines*\nCMenuMultiChoiceTwoLines::AddOption(wchar *text1, float positionX1, float positionY1, wchar *text2, float positionX2, float positionY2, bool bSelected, bool bRightJustify)\n{\n\tif(m_numOptions == NUM_MULTICHOICE_OPTIONS)\n\t\treturn nil;\n\tm_options[m_numOptions].m_line1.m_text = text1;\n\tm_options[m_numOptions].m_line2.m_text = text2;\n\tm_options[m_numOptions].m_line1.SetPosition(positionX1, positionY1);\n\tm_options[m_numOptions].m_line2.SetPosition(positionX2, positionY2);\n\tm_options[m_numOptions].m_bSelected = bSelected;\n\tm_options[m_numOptions].m_bRightJustify = bRightJustify;\n\treturn &m_options[m_numOptions++];\n}\n\n\nvoid\nCMenuMultiChoiceTwoLines::SetColors(const CRGBA &title, const CRGBA &normal, const CRGBA &selected)\n{\n\tint i;\n\tm_title.SetColor(title);\n\tfor(i = 0; i < NUM_MULTICHOICE_OPTIONS; i++)\n\t\tm_options[i].SetColors(normal, selected);\n}\n\nvoid\nCMenuMultiChoiceTwoLines::SetNewOldTextScale(bool bTextScale, const CVector2D &newScale, const CVector2D &oldScale, bool bTitleTextScale)\n{\n\tm_bSetTextScale = bTextScale;\n\tm_textScale = newScale;\n\tm_oldTextScale = oldScale;\n\tm_bSetTitleTextScale = bTitleTextScale;\n}\n\nvoid\nCMenuMultiChoiceTwoLines::Draw(CRGBA const &optionHighlight ,CRGBA const &titleHighlight, float x, float y)\n{\n\tint i;\n\n\tif(m_bSetTextScale && m_bSetTitleTextScale)\n\t\tCFont::SetScale(m_textScale.x, m_textScale.y);\n\tif(m_cursor == -1)\n\t\tm_title.Draw(m_position.x+x, m_position.y+y);\n\telse\n\t\tm_title.Draw(titleHighlight, m_position.x+x, m_position.y+y);\n\n\tif(m_bSetTextScale)\n\t\tCFont::SetScale(m_textScale.x, m_textScale.y);\n\n\tif(m_cursor == -1)\n\t\tfor(i = 0; i < m_numOptions; i++)\n\t\t\tm_options[i].Draw(CRGBA(0,0,0,0), m_position.x+x, m_position.y+y, false);\n\telse\n\t\tfor(i = 0; i < m_numOptions; i++){\n\t\t\tif(i == m_cursor)\n\t\t\t\tm_options[i].Draw(optionHighlight, m_position.x+x, m_position.y+y);\n\t\t\telse\n\t\t\t\tm_options[i].Draw(CRGBA(0,0,0,0), m_position.x+x, m_position.y+y, false);\n\t\t}\n\n\tif(m_bSetTextScale){\n\t\tCFont::DrawFonts();\n\t\tCFont::SetScale(m_oldTextScale.x, m_oldTextScale.y);\n\t}\n}\n\nvoid\nCMenuMultiChoiceTwoLines::DrawNormal(float x, float y)\n{\n\tint i;\n\n\tif(m_bSetTextScale && m_bSetTitleTextScale)\n\t\tCFont::SetScale(m_textScale.x, m_textScale.y);\n\tm_title.Draw(m_position.x+x, m_position.y+y);\n\n\tif(m_bSetTextScale)\n\t\tCFont::SetScale(m_textScale.x, m_textScale.y);\n\n\tfor(i = 0; i < m_numOptions; i++)\n\t\tm_options[i].Draw(CRGBA(0,0,0,0), m_position.x+x, m_position.y+y, false);\n\n\tif(m_bSetTextScale){\n\t\tCFont::DrawFonts();\n\t\tCFont::SetScale(m_oldTextScale.x, m_oldTextScale.y);\n\t}\n}\n\nvoid\nCMenuMultiChoiceTwoLines::DrawHighlighted(CRGBA const &titleHighlight, float x, float y)\n{\n\tint i;\n\n\tif(m_bSetTextScale && m_bSetTitleTextScale)\n\t\tCFont::SetScale(m_textScale.x, m_textScale.y);\n\tif(m_cursor == -1)\n\t\tm_title.Draw(m_position.x+x, m_position.y+y);\n\telse\n\t\tm_title.Draw(titleHighlight, m_position.x+x, m_position.y+y);\n\n\tif(m_bSetTextScale)\n\t\tCFont::SetScale(m_textScale.x, m_textScale.y);\n\n\tfor(i = 0; i < m_numOptions; i++)\n\t\tm_options[i].Draw(CRGBA(0,0,0,0), m_position.x+x, m_position.y+y, false);\n\n\tif(m_bSetTextScale){\n\t\tCFont::DrawFonts();\n\t\tCFont::SetScale(m_oldTextScale.x, m_oldTextScale.y);\n\t}\n}\n\nvoid\nCMenuMultiChoiceTwoLines::SetAlpha(uint8 alpha)\n{\n\tint i;\n\tm_title.SetAlpha(alpha);\n\tfor(i = 0; i < NUM_MULTICHOICE_OPTIONS; i++)\n\t\tm_options[i].SetAlpha(alpha);\n}\n\nvoid\nCMenuMultiChoiceTwoLines::SetShadows(bool bDropShadows, CRGBA const &shadowColor, CVector2D const &shadowOffset)\n{\n\tint i;\n\tm_title.SetShadows(bDropShadows, shadowColor, shadowOffset);\n\tfor(i = 0; i < NUM_MULTICHOICE_OPTIONS; i++)\n\t\tm_options[i].SetShadows(bDropShadows, shadowColor, shadowOffset);\n}\n\n\nbool\nCMenuMultiChoiceTwoLines::GoNext(void)\n{\n\tif(m_cursor == m_numOptions-1){\n\t\tm_cursor = -1;\n\t\treturn false;\n\t}else{\n\t\tm_cursor++;\n\t\treturn true;\n\t}\n}\n\nbool\nCMenuMultiChoiceTwoLines::GoPrev(void)\n{\n\tif(m_cursor == 0){\n\t\tm_cursor = -1;\n\t\treturn false;\n\t}else{\n\t\tm_cursor--;\n\t\treturn true;\n\t}\n}\n\nvoid\nCMenuMultiChoiceTwoLines::SelectCurrentOptionUnderCursor(void)\n{\n\tint i;\n\tif(m_cursor == -1)\n\t\treturn;\n\tfor(i = 0; i < NUM_MULTICHOICE_OPTIONS; i++)\n\t\tm_options[i].m_bSelected = false;\n\tm_options[m_cursor].m_bSelected = true;\n}\n\nint\nCMenuMultiChoiceTwoLines::GetMenuSelection(void)\n{\n\tint i;\n\tfor(i = 0; i < NUM_MULTICHOICE_OPTIONS; i++)\n\t\tif(m_options[i].m_bSelected)\n\t\t\treturn i;\n\treturn -1;\n}\n\nvoid\nCMenuMultiChoiceTwoLines::SetMenuSelection(int selection)\n{\n\tint i;\n\tfor(i = 0; i < NUM_MULTICHOICE_OPTIONS; i++)\n\t\tm_options[i].m_bSelected = false;\n\tm_options[selection%NUM_MULTICHOICE_OPTIONS].m_bSelected = true;\n}\n\n/*\n * CMenuMultiChoiceTwoLinesTriggered\n */\n\nvoid\nCMenuMultiChoiceTwoLinesTriggered::Initialise(void)\n{\n\tint i;\n\tfor(i = 0; i < NUM_MULTICHOICE_OPTIONS; i++)\n\t\tm_triggers[i] = nil;\n\tm_defaultCancel = nil;\n}\n\nCPlaceableShOptionTwoLines*\nCMenuMultiChoiceTwoLinesTriggered::AddOption(wchar *text, float positionX, float positionY, Trigger trigger, bool bSelected, bool bRightJustify)\n{\n\tCPlaceableShOptionTwoLines *option;\n\toption = CMenuMultiChoiceTwoLines::AddOption(text, positionX, positionY, bSelected, bRightJustify);\n\tif(option)\n\t\tm_triggers[m_numOptions-1] = trigger;\n\treturn option;\n}\n\nCPlaceableShOptionTwoLines*\nCMenuMultiChoiceTwoLinesTriggered::AddOption(wchar *text1, float positionX1, float positionY1, wchar *text2, float positionX2, float positionY2, Trigger trigger, bool bSelected, bool bRightJustify)\n{\n\tCPlaceableShOptionTwoLines *option;\n\toption = CMenuMultiChoiceTwoLines::AddOption(text1, positionX1, positionY1, text2, positionX2, positionY2, bSelected, bRightJustify);\n\tif(option)\n\t\tm_triggers[m_numOptions-1] = trigger;\n\treturn option;\n}\n\nvoid\nCMenuMultiChoiceTwoLinesTriggered::SelectCurrentOptionUnderCursor(void)\n{\n\tCMenuMultiChoiceTwoLines::SelectCurrentOptionUnderCursor();\n\tif(m_cursor != -1)\n\t\tm_triggers[m_cursor](this);\n}\n\nvoid\nCMenuMultiChoiceTwoLinesTriggered::SelectDefaultCancelAction(void)\n{\n\tif(m_defaultCancel)\n\t\tm_defaultCancel(this);\n}\n\n\n/*\n * CMenuOnOff\n */\n\nvoid\nCMenuOnOff::SetColors(const CRGBA &title, const CRGBA &options)\n{\n\tm_title.SetColors(title, title);\n\tm_options[0].SetColor(options);\n\tm_options[1].SetColor(options);\n}\n\nvoid\nCMenuOnOff::SetNewOldTextScale(bool bTextScale, const CVector2D &newScale, const CVector2D &oldScale, bool bTitleTextScale)\n{\n\tm_bSetTextScale = bTextScale;\n\tm_textScale = newScale;\n\tm_oldTextScale = oldScale;\n\tm_bSetTitleTextScale = bTitleTextScale;\n}\n\nvoid\nCMenuOnOff::SetOptionPosition(float x, float y, bool bRightJustify)\n{\n\tm_options[0].SetPosition(x, y, bRightJustify);\n\tm_options[1].SetPosition(x, y, bRightJustify);\n}\n\nvoid\nCMenuOnOff::AddTitle(wchar *text, bool bSelected, float positionX, float positionY, bool bRightJustify)\n{\n\tm_title.m_text = text;\n\tm_title.m_bSelected = bSelected;\n\tm_title.SetPosition(positionX, positionY, bRightJustify);\n}\n\nvoid\nCMenuOnOff::Draw(CRGBA const &optionHighlight, CRGBA const &titleHighlight, float x, float y)\n{\n\tif(m_type == 1){\n\t\tm_options[0].m_text = TheText.Get(\"FEM_NO\");\n\t\tm_options[1].m_text = TheText.Get(\"FEM_YES\");\n\t}else if(m_type == 0){\n\t\tm_options[0].m_text = TheText.Get(\"FEM_OFF\");\n\t\tm_options[1].m_text = TheText.Get(\"FEM_ON\");\n\t}\n\n\tif(m_bSetTextScale && m_bSetTitleTextScale)\n\t\tCFont::SetScale(m_textScale.x, m_textScale.y);\n\tif(m_bActive)\n\t\tm_title.Draw(titleHighlight, m_position.x+x, m_position.y+y);\n\telse\n\t\tm_title.Draw(CRGBA(0,0,0,0), m_position.x+x, m_position.y+y, false);\n\n\tif(m_bSetTextScale)\n\t\tCFont::SetScale(m_textScale.x, m_textScale.y);\n\n\tif(m_bActive){\n\t\tif(m_title.m_bSelected)\n\t\t\tm_options[1].Draw(optionHighlight, m_position.x+x, m_position.y+y);\n\t\telse\n\t\t\tm_options[0].Draw(optionHighlight, m_position.x+x, m_position.y+y);\n\t}else{\n\t\tif(m_title.m_bSelected)\n\t\t\tm_options[1].Draw(m_position.x+x, m_position.y+y);\n\t\telse\n\t\t\tm_options[0].Draw(m_position.x+x, m_position.y+y);\n\t}\n\n\tif(m_bSetTextScale)\n\t\tCFont::SetScale(m_oldTextScale.x, m_oldTextScale.y);\n}\n\nvoid\nCMenuOnOff::DrawNormal(float x, float y)\n{\n\tif(m_type == 1){\n\t\tm_options[0].m_text = TheText.Get(\"FEM_NO\");\n\t\tm_options[1].m_text = TheText.Get(\"FEM_YES\");\n\t}else if(m_type == 0){\n\t\tm_options[0].m_text = TheText.Get(\"FEM_OFF\");\n\t\tm_options[1].m_text = TheText.Get(\"FEM_ON\");\n\t}\n\n\tif(m_bSetTextScale && m_bSetTitleTextScale)\n\t\tCFont::SetScale(m_textScale.x, m_textScale.y);\n\tm_title.Draw(CRGBA(0,0,0,0), m_position.x+x, m_position.y+y, false);\n\n\tif(m_bSetTextScale)\n\t\tCFont::SetScale(m_textScale.x, m_textScale.y);\n\n\tif(m_title.m_bSelected)\n\t\tm_options[1].Draw(m_position.x+x, m_position.y+y);\n\telse\n\t\tm_options[0].Draw(m_position.x+x, m_position.y+y);\n\n\tif(m_bSetTextScale)\n\t\tCFont::SetScale(m_oldTextScale.x, m_oldTextScale.y);\n}\n\nvoid\nCMenuOnOff::DrawHighlighted(CRGBA const &titleHighlight, float x, float y)\n{\n\tif(m_type == 1){\n\t\tm_options[0].m_text = TheText.Get(\"FEM_NO\");\n\t\tm_options[1].m_text = TheText.Get(\"FEM_YES\");\n\t}else if(m_type == 0){\n\t\tm_options[0].m_text = TheText.Get(\"FEM_OFF\");\n\t\tm_options[1].m_text = TheText.Get(\"FEM_ON\");\n\t}\n\n\tif(m_bSetTextScale && m_bSetTitleTextScale)\n\t\tCFont::SetScale(m_textScale.x, m_textScale.y);\n\tif(m_bActive)\n\t\tm_title.Draw(titleHighlight, m_position.x+x, m_position.y+y);\n\telse\n\t\tm_title.Draw(CRGBA(0,0,0,0), m_position.x+x, m_position.y+y, false);\n\n\tif(m_bSetTextScale)\n\t\tCFont::SetScale(m_textScale.x, m_textScale.y);\n\n\tif(m_title.m_bSelected)\n\t\tm_options[1].Draw(m_position.x+x, m_position.y+y);\n\telse\n\t\tm_options[0].Draw(m_position.x+x, m_position.y+y);\n\n\tif(m_bSetTextScale)\n\t\tCFont::SetScale(m_oldTextScale.x, m_oldTextScale.y);\n}\n\nvoid\nCMenuOnOff::SetAlpha(uint8 alpha)\n{\n\tm_title.SetAlpha(alpha);\n\tm_options[0].SetAlpha(alpha);\n\tm_options[1].SetAlpha(alpha);\n}\n\nvoid\nCMenuOnOff::SetShadows(bool bDropShadows, CRGBA const &shadowColor, CVector2D const &shadowOffset)\n{\n\tm_title.SetShadows(bDropShadows, shadowColor, shadowOffset);\n\tm_options[0].SetShadows(bDropShadows, shadowColor, shadowOffset);\n\tm_options[1].SetShadows(bDropShadows, shadowColor, shadowOffset);\n}\n\n/*\n * CMenuOnOffTriggered\n */\n\nvoid\nCMenuOnOffTriggered::SetOptionPosition(float x, float y, Trigger trigger, bool bRightJustify)\n{\n\tCMenuOnOff::SetOptionPosition(x, y, bRightJustify);\n\tif(trigger)\n\t\tm_trigger = trigger;\n}\n\nvoid\nCMenuOnOffTriggered::SelectCurrentOptionUnderCursor(void)\n{\n\tCMenuOnOff::SelectCurrentOptionUnderCursor();\n\tif(m_trigger)\n\t\tm_trigger(this);\n}\n\n\n\n/*\n * CMenuSlider\n */\n\nchar CMenuSlider::Buf8[8];\nwchar CMenuSlider::Buf16[8];\n\nvoid\nCMenuSlider::SetColors(const CRGBA &title, const CRGBA &percentage, const CRGBA &left, const CRGBA &right)\n{\n\tm_title.SetColor(title);\n\tm_percentageText.SetColor(percentage);\n\tm_colors[0] = left;\n\tm_colors[1] = right;\n}\n\n\nvoid\nCMenuSlider::AddTickBox(float positionX, float positionY, float width, float heightLeft, float heightRight)\n{\n\tm_box.SetPosition(positionX, positionY);\n\tm_size[0].x = width;\n\tm_size[0].y = heightLeft;\n\tm_size[1].x = width;\n\tm_size[1].y = heightRight;\n}\n\nvoid\nCMenuSlider::AddTitle(wchar *text, float positionX, float positionY)\n{\n\tm_title.m_text = text;\n\tm_title.SetPosition(positionX, positionY);\n}\n\nstatic CRGBA SELECTED_TEXT_COLOR_0(255, 182, 48, 255);\n\nvoid\nCMenuSlider::Draw(const CRGBA &optionHighlight, const CRGBA &titleHighlight, float x, float y)\n{\n\tif(m_bActive){\n\t\tCRGBA selectionCol = m_colors[0];\n\t\tif(optionHighlight.red == SELECTED_TEXT_COLOR_0.red &&\n\t\t   optionHighlight.green == SELECTED_TEXT_COLOR_0.green &&\n\t\t   optionHighlight.blue == SELECTED_TEXT_COLOR_0.blue &&\n\t\t   optionHighlight.alpha == SELECTED_TEXT_COLOR_0.alpha)\n\t\t\tselectionCol = m_colors[1];\n\n\t\tif(m_style == 1){\n\t\t\t// solid bar\n\t\t\tCRGBA shadowCol = m_box.GetShadowColor();\n\t\t\tfloat f = m_value/1000.0f;\n\t\t\tCVector2D boxPos = m_box.m_position + m_position + CVector2D(x,y);\n\t\t\tif(m_box.m_bDropShadow)\n\t\t\t\tCSprite2d::DrawRect(\n\t\t\t\t\tCRect(boxPos.x + X(m_box.m_shadowOffset.x),\n\t\t\t\t\t      boxPos.y + Y(m_box.m_shadowOffset.y),\n\t\t\t\t\t      boxPos.x + X(m_box.m_shadowOffset.x) + m_size[0].x,\n\t\t\t\t\t      boxPos.y + Y(m_box.m_shadowOffset.y) + m_size[0].y),\n\t\t\t\t\tshadowCol);\n\t\t\tCSprite2d::DrawRect(\n\t\t\t\tCRect(boxPos.x, boxPos.y,\n\t\t\t\t      boxPos.x + m_size[0].x, boxPos.y + m_size[0].y),\n\t\t\t\tm_colors[1]);\n\t\t\tCSprite2d::DrawRect(\n\t\t\t\tCRect(boxPos.x, boxPos.y,\n\t\t\t\t      boxPos.x + m_size[0].x*f, boxPos.y + m_size[0].y),\n\t\t\t\tselectionCol);\n\t\t}else if(m_style == 0){\n\t\t\t// ticks...\n\t\t\tCVector2D boxPos = m_box.m_position + m_position + CVector2D(x,y);\n\t\t\tDrawTicks(boxPos, m_size[0], m_size[1].y,\n\t\t\t\tm_value/1000.0f, m_colors[0], selectionCol, m_colors[1],\n\t\t\t\tm_box.m_bDropShadow, m_box.m_shadowOffset, m_box.GetShadowColor());\n\t\t}\n\n\t\tm_title.Draw(titleHighlight, m_position.x+x, m_position.y+y);\n\n\t\tif(m_bDrawPercentage){\n\t\t\tsprintf(Buf8, \"%d%%\", m_value/10);\n\t\t\tAsciiToUnicode(Buf8, Buf16);\n\t\t\tm_percentageText.m_text = Buf16;\n\t\t\tm_percentageText.Draw(optionHighlight, m_position.x+x, m_position.y+y);\n\t\t}\n\t}else\n\t\tCMenuSlider::DrawNormal(x, y);\n}\n\nvoid\nCMenuSlider::DrawNormal(float x, float y)\n{\n\tif(m_style == 1){\n\t\t// solid bar\n\t\tCRGBA shadowCol = m_box.GetShadowColor();\n\t\tfloat f = m_value/1000.0f;\n\t\tCVector2D boxPos = m_box.m_position + m_position + CVector2D(x,y);\n\t\tif(m_box.m_bDropShadow)\n\t\t\tCSprite2d::DrawRect(\n\t\t\t\tCRect(boxPos.x + X(m_box.m_shadowOffset.x),\n\t\t\t\t      boxPos.y + Y(m_box.m_shadowOffset.y),\n\t\t\t\t      boxPos.x + X(m_box.m_shadowOffset.x) + m_size[0].x,\n\t\t\t\t      boxPos.y + Y(m_box.m_shadowOffset.y) + m_size[0].y),\n\t\t\t\tshadowCol);\n\t\tCSprite2d::DrawRect(\n\t\t\tCRect(boxPos.x, boxPos.y,\n\t\t\t      boxPos.x + m_size[0].x, boxPos.y + m_size[0].y),\n\t\t\tm_colors[1]);\n\t\tCSprite2d::DrawRect(\n\t\t\tCRect(boxPos.x, boxPos.y,\n\t\t\t      boxPos.x + m_size[0].x*f, boxPos.y + m_size[0].y),\n\t\t\tm_colors[0]);\n\t}else if(m_style == 0){\n\t\t// ticks...\n\t\tCVector2D boxPos = m_box.m_position + m_position + CVector2D(x,y);\n\t\tDrawTicks(boxPos, m_size[0], m_size[1].y,\n\t\t\tm_value/1000.0f, m_colors[0], m_colors[1],\n\t\t\tm_box.m_bDropShadow, m_box.m_shadowOffset, m_box.GetShadowColor());\n\t}\n\n\tm_title.Draw(m_position.x+x, m_position.y+y);\n\n\tif(m_bDrawPercentage){\n\t\tsprintf(Buf8, \"%d%%\", m_value/10);\n\t\tAsciiToUnicode(Buf8, Buf16);\n\t\tm_percentageText.m_text = Buf16;\n\t\tm_percentageText.Draw(m_percentageText.GetColor(), m_position.x+x, m_position.y+y);\n\t}\n}\n\nvoid\nCMenuSlider::DrawHighlighted(const CRGBA &titleHighlight, float x, float y)\n{\n\tif(m_bActive)\n\t\tm_title.Draw(titleHighlight, m_position.x+x, m_position.y+y);\n\telse\n\t\tm_title.Draw(m_position.x+x, m_position.y+y);\n\n\tif(m_style == 1){\n\t\t// solid bar\n\t\tCRGBA shadowCol = m_box.GetShadowColor();\n\t\tfloat f = m_value/1000.0f;\n\t\tCVector2D boxPos = m_box.m_position + m_position + CVector2D(x,y);\n\t\tif(m_box.m_bDropShadow)\n\t\t\tCSprite2d::DrawRect(\n\t\t\t\tCRect(boxPos.x + X(m_box.m_shadowOffset.x),\n\t\t\t\t      boxPos.y + Y(m_box.m_shadowOffset.y),\n\t\t\t\t      boxPos.x + X(m_box.m_shadowOffset.x) + m_size[0].x,\n\t\t\t\t      boxPos.y + Y(m_box.m_shadowOffset.y) + m_size[0].y),\n\t\t\t\tshadowCol);\n\t\tCSprite2d::DrawRect(\n\t\t\tCRect(boxPos.x, boxPos.y,\n\t\t\t      boxPos.x + m_size[0].x, boxPos.y + m_size[0].y),\n\t\t\tm_colors[1]);\n\t\tCSprite2d::DrawRect(\n\t\t\tCRect(boxPos.x, boxPos.y,\n\t\t\t      boxPos.x + m_size[0].x*f, boxPos.y + m_size[0].y),\n\t\t\tm_colors[0]);\n\t}else if(m_style == 0){\n\t\t// ticks...\n\t\tCVector2D boxPos = m_box.m_position + m_position + CVector2D(x,y);\n\t\tDrawTicks(boxPos, m_size[0], m_size[1].y,\n\t\t\tm_value/1000.0f, m_colors[0], m_colors[1],\n\t\t\tm_box.m_bDropShadow, m_box.m_shadowOffset, m_box.GetShadowColor());\n\t}\n\n\tif(m_bDrawPercentage){\n\t\tsprintf(Buf8, \"%d%%\", m_value/10);\n\t\tAsciiToUnicode(Buf8, Buf16);\n\t\tm_percentageText.m_text = Buf16;\n\t\tm_percentageText.Draw(m_percentageText.GetColor(), m_position.x+x, m_position.y+y);\n\t}\n}\n\nvoid\nCMenuSlider::DrawTicks(const CVector2D &position, const CVector2D &size, float heightRight, float level, const CRGBA &leftCol, const CRGBA &selCol, const CRGBA &rightCol, bool bShadow, const CVector2D &shadowOffset, const CRGBA &shadowColor)\n{\n\tint i;\n\tint numTicks = size.x / X(8.0f);\n\tfloat dy = heightRight - size.y;\n\tfloat stepy = dy / numTicks;\n\tint left = level*numTicks;\n\tint drewSelection = 0;\n\tfor(i = 0; i < numTicks; i++){\n\t\tCRect rect(position.x + X(8.0f)*i, position.y + dy - stepy*i,\n\t\t           position.x + X(8.0f)*i + X(4.0f), position.y + dy + size.y);\n\t\tif(bShadow){\n\t\t\tCRect shadowRect = rect;\n\t\t\tshadowRect.left += X(shadowOffset.x);\n\t\t\tshadowRect.right += X(shadowOffset.x);\n\t\t\tshadowRect.top += Y(shadowOffset.y);\n\t\t\tshadowRect.bottom += Y(shadowOffset.y);\n\t\t\tCSprite2d::DrawRect(shadowRect, shadowColor);\n\t\t}\n\t\tif(i < left)\n\t\t\tCSprite2d::DrawRect(rect, leftCol);\n\t\telse if(!drewSelection){\n\t\t\tCSprite2d::DrawRect(rect, selCol);\n\t\t\tdrewSelection = 1;\n\t\t}else\n\t\t\tCSprite2d::DrawRect(rect, rightCol);\n\t}\n}\n\nvoid\nCMenuSlider::DrawTicks(const CVector2D &position, const CVector2D &size, float heightRight, float level, const CRGBA &leftCol, const CRGBA &rightCol, bool bShadow, const CVector2D &shadowOffset, const CRGBA &shadowColor)\n{\n\tint i;\n\tint numTicks = size.x / X(8.0f);\n\tfloat dy = heightRight - size.y;\n\tfloat stepy = dy / numTicks;\n\tint left = level*numTicks;\n\tfor(i = 0; i < numTicks; i++){\n\t\tCRect rect(position.x + X(8.0f)*i, position.y + dy - stepy*i,\n\t\t           position.x + X(8.0f)*i + X(4.0f), position.y + dy + size.y);\n\t\tif(bShadow){\n\t\t\tCRect shadowRect = rect;\n\t\t\tshadowRect.left += X(shadowOffset.x);\n\t\t\tshadowRect.right += X(shadowOffset.x);\n\t\t\tshadowRect.top += Y(shadowOffset.y);\n\t\t\tshadowRect.bottom += Y(shadowOffset.y);\n\t\t\tCSprite2d::DrawRect(shadowRect, shadowColor);\n\t\t}\n\t\tif(i < left)\n\t\t\tCSprite2d::DrawRect(rect, leftCol);\n\t\telse\n\t\t\tCSprite2d::DrawRect(rect, rightCol);\n\t}\n}\n\nvoid\nCMenuSlider::SetAlpha(uint8 alpha)\n{\n\tm_title.SetAlpha(alpha);\n\tm_box.SetAlpha(alpha);\n\tm_someAlpha = alpha;\n\tm_percentageText.SetAlpha(alpha);\n\tm_colors[0].alpha = alpha;\n\tm_colors[1].alpha = alpha;\n}\n\nvoid\nCMenuSlider::SetShadows(bool bDropShadows, const CRGBA &shadowColor, const CVector2D &shadowOffset)\n{\n\tm_title.SetShadows(bDropShadows, shadowColor, shadowOffset);\n\tm_box.SetShadows(bDropShadows, shadowColor, shadowOffset);\n\tm_percentageText.SetShadows(bDropShadows, shadowColor, shadowOffset);\n}\n\n/*\n * CMenuSliderTriggered\n */\n\t\nvoid\nCMenuSliderTriggered::AddTickBox(float positionX, float positionY, float width, float heightLeft, float heightRight, Trigger trigger, Trigger alwaysTrigger)\n{\n\tCMenuSlider::AddTickBox(positionX, positionY, width, heightLeft, heightRight);\n\tm_trigger = trigger;\n\tm_alwaysTrigger = alwaysTrigger;\n}\n\nvoid\nCMenuSliderTriggered::Draw(const CRGBA &optionHighlight, const CRGBA &titleHighlight, float x, float y)\n{\n\tCMenuSlider::Draw(optionHighlight, titleHighlight, x, y);\n\tif(m_alwaysTrigger)\n\t\tm_alwaysTrigger(this);\n}\n\nbool\nCMenuSliderTriggered::GoLeft(void)\n{\n\tCMenuSlider::GoLeft();\n\tif(m_trigger)\n\t\tm_trigger(this);\n\treturn true;\n}\n\nbool\nCMenuSliderTriggered::GoRight(void)\n{\n\tCMenuSlider::GoRight();\n\tif(m_trigger)\n\t\tm_trigger(this);\n\treturn true;\n}\n\nbool\nCMenuSliderTriggered::GoLeftStill(void)\n{\n\tCMenuSlider::GoLeftStill();\n\tif(m_trigger)\n\t\tm_trigger(this);\n\treturn true;\n}\n\nbool\nCMenuSliderTriggered::GoRightStill(void)\n{\n\tCMenuSlider::GoRightStill();\n\tif(m_trigger)\n\t\tm_trigger(this);\n\treturn true;\n}\n\n/*\n * CMenuLineLister\n */\n\nCMenuLineLister::CMenuLineLister(void)\n : m_numLines(0), m_width(0.0f), m_height(0.0f),\n   m_scrollPosition(0.0f), m_scrollSpeed(1.0f), m_lineSpacing(15.0f), field_10E8(0)\n{\n\tint i;\n\tfor(i = 0; i < NUM_LINELISTER_LINES_TOTAL; i++){\n\t\tm_lineAlphas[i] = 0;\n\t\tm_lineFade[i] = 0;\n\t}\n}\n\n\nvoid\nCMenuLineLister::SetLinesColor(const CRGBA &color)\n{\n\tint i;\n\tfor(i = 0; i < NUM_LINELISTER_LINES_TOTAL; i++){\n\t\tm_linesLeft[i].SetColor(color);\n\t\tm_linesRight[i].SetColor(color);\n\t}\n}\n\nvoid\nCMenuLineLister::ResetNumberOfTextLines(void)\n{\n\tint i;\n\tm_numLines = 0;\n\tfor(i = 0; i < NUM_LINELISTER_LINES_TOTAL; i++){\n\t\tm_lineAlphas[i] = 0;\n\t\tm_lineFade[i] = 0;\n\t}\n\tfor(i = 0; i < NUM_LINELISTER_LINES_TOTAL; i++){\n\t\t// note this doesn't clear lines 0-14, probably an oversight\n\t\tGetLeftLine(i)->m_text = nil;\n\t\tGetRightLine(i)->m_text = nil;\n\t}\n}\n\nbool\nCMenuLineLister::AddTextLine(wchar *left, wchar *right)\n{\n\tCPlaceableShText *leftLine, *rightLine;\n\tif(m_numLines == NUM_LINELISTER_LINES)\n\t\treturn false;\n\tleftLine = GetLeftLine(m_numLines);\n\tleftLine->m_text = left;\n\tleftLine->SetPosition(0.0f, m_lineSpacing*(m_numLines+15));\n\trightLine = GetRightLine(m_numLines);\n\trightLine->m_text = right;\n\trightLine->SetPosition(leftLine->m_position.x, leftLine->m_position.y);\n\tm_numLines++;\n\treturn true;\n}\n\nvoid\nCMenuLineLister::Draw(const CRGBA &optionHighlight, const CRGBA &titleHighlight, float x, float y)\n{\n\tint i, n;\n\n\tm_scrollPosition += m_scrollSpeed;\n\tn = m_numLines + 15;\n\tif(m_scrollSpeed > 0.0f){\n\t\tif(m_scrollPosition > n*m_lineSpacing)\n\t\t\tm_scrollPosition = 0.0f;\n\t}else{\n\t\tif(m_scrollPosition < 0.0f)\n\t\t\tm_scrollPosition = n*m_lineSpacing;\n\t}\n\t// this is a weird condition....\n\tfor(i = 0;\n\t    m_scrollPosition < i*m_lineSpacing || m_scrollPosition >= (i+1)*m_lineSpacing;\n\t    i++);\n\n\tfloat screenPos = 0.0f;\n\tfor(; i < n; i++){\n\t\tCVector2D linePos = m_linesLeft[i].m_position;\n\n\t\tif(linePos.y+m_position.y - (m_scrollPosition+m_position.y) < Y(64.0f))\n\t\t\tm_lineFade[i] = -4.0f*Abs(m_scrollSpeed);\n\t\telse\n\t\t\tm_lineFade[i] = 4.0f*Abs(m_scrollSpeed);\n\t\tint newAlpha = m_lineAlphas[i] + m_lineFade[i];\n\t\tif(newAlpha < 0) newAlpha = 0;\n\t\tif(newAlpha > 255) newAlpha = 255;\n\t\tm_lineAlphas[i] = newAlpha;\n\n\t\tuint8 alpha = m_linesLeft[i].m_shadowColor.alpha;\n\n\t\t// apply alpha\n\t\tm_linesLeft[i].SetAlpha((alpha*m_lineAlphas[i])>>8);\n\t\tm_linesRight[i].SetAlpha((alpha*m_lineAlphas[i])>>8);\n\n\t\tm_linesLeft[i].Draw(m_position.x+x, m_position.y+y - m_scrollPosition);\n\t\tCFont::SetRightJustifyOn();\n\t\tm_linesRight[i].Draw(m_position.x+x + m_width, m_position.y+y - m_scrollPosition);\n\t\tCFont::SetRightJustifyOff();\n\n\t\t// restore alpha\n\t\tm_linesLeft[i].SetAlpha(alpha);\n\t\tm_linesRight[i].SetAlpha(alpha);\n\n\t\tscreenPos += m_lineSpacing;\n\t\tif(screenPos >= m_height)\n\t\t\tbreak;\n\t}\n\n\tm_scrollSpeed = 1.0f;\n}\n\nvoid\nCMenuLineLister::SetAlpha(uint8 alpha)\n{\n\tint i;\n\tfor(i = 0; i < NUM_LINELISTER_LINES_TOTAL; i++){\n\t\tm_linesLeft[i].SetAlpha(alpha);\n\t\tm_linesRight[i].SetAlpha(alpha);\n\t}\n}\n\nvoid\nCMenuLineLister::SetShadows(bool bDropShadows, const CRGBA &shadowColor, const CVector2D &shadowOffset)\n{\n\tint i;\n\tfor(i = 0; i < NUM_LINELISTER_LINES_TOTAL; i++){\n\t\tm_linesLeft[i].SetShadows(bDropShadows, shadowColor, shadowOffset);\n\t\tm_linesRight[i].SetShadows(bDropShadows, shadowColor, shadowOffset);\n\t}\n}\n\n\n/*\n * CMenuPage\n */\n\nvoid\nCMenuPage::Initialise(void)\n{\n\tint i;\n\tm_numControls = 0;\n\tm_pCurrentControl = nil;\n\tm_cursor = 0;\n\tfor(i = 0; i < NUM_PAGE_WIDGETS; i++)\n\t\tm_controls[i] = nil;\n}\n\nbool\nCMenuPage::AddMenu(CMenuBase *widget)\n{\n\tif(m_numControls >= NUM_PAGE_WIDGETS)\n\t\treturn false;\n\tm_controls[m_numControls] = widget;\n\tif(m_numControls == 0){\n\t\tm_pCurrentControl = widget;\n\t\tm_cursor = 0;\n\t}\n\tm_numControls++;\n\treturn true;\n}\n\nbool\nCMenuPage::IsActiveMenuTwoState(void)\n{\n\treturn m_pCurrentControl && m_pCurrentControl->m_bTwoState;\n}\n\nvoid\nCMenuPage::ActiveMenuTwoState_SelectNextPosition(void)\n{\n\tint sel;\n\tif(m_pCurrentControl == nil || !m_pCurrentControl->m_bTwoState)\n\t\treturn;\n\tm_pCurrentControl->GoFirst();\n\tsel = m_pCurrentControl->GetMenuSelection();\n\tif(sel == 1)\n\t\tm_pCurrentControl->SelectCurrentOptionUnderCursor();\n\telse if(sel == 0){\n\t\tif ( m_pCurrentControl )\n\t\t{\n\t\t\tif ( !m_pCurrentControl->GoNext() )\n\t\t\t\tm_pCurrentControl->GoFirst();\n\t\t}\n\n\t\tm_pCurrentControl->SelectCurrentOptionUnderCursor();\n\t}\n}\n\nvoid\nCMenuPage::Draw(const CRGBA &optionHighlight, const CRGBA &titleHighlight, float x, float y)\n{\n\tint i;\n\tfor(i = 0; i < m_numControls; i++)\n\t\tif(m_controls[i]){\n\t\t\tif(i == m_cursor)\n\t\t\t\tm_controls[i]->Draw(optionHighlight, titleHighlight, x, y);\n\t\t\telse\n\t\t\t\tm_controls[i]->DrawNormal(x, y);\n\t\t}\n}\n\nvoid\nCMenuPage::DrawHighlighted(const CRGBA &titleHighlight, float x, float y)\n{\n\tint i;\n\tfor(i = 0; i< m_numControls; i++)\n\t\tif(m_controls[i]){\n\t\t\tif(i == m_cursor)\n\t\t\t\tm_controls[i]->DrawHighlighted(titleHighlight, x, y);\n\t\t\telse\n\t\t\t\tm_controls[i]->DrawNormal(x, y);\n\t\t}\n}\n\nvoid\nCMenuPage::DrawNormal(float x, float y)\n{\n\tint i;\n\tfor(i = 0; i< m_numControls; i++)\n\t\tif(m_controls[i])\n\t\t\tm_controls[i]->DrawNormal(x, y);\n}\n\nvoid\nCMenuPage::ActivatePage(void)\n{\n\tm_cursor = 0;\n\tif(m_numControls == 0)\n\t\treturn;\n\tfor(;;){\n\t\tm_pCurrentControl = m_controls[m_cursor];\n\t\tif(m_pCurrentControl->GoFirst())\n\t\t\treturn;\n\t\tif(m_cursor == m_numControls-1)\n\t\t\tm_cursor = 0;\n\t\telse\n\t\t\tm_cursor++;\n\t}\n}\n\nvoid\nCMenuPage::SetAlpha(uint8 alpha)\n{\n\tint i;\n\tfor(i = 0; i< m_numControls; i++)\n\t\tif(m_controls[i])\n\t\t\tm_controls[i]->SetAlpha(alpha);\n}\n\nvoid\nCMenuPage::SetShadows(bool bDropShadows, const CRGBA &shadowColor, const CVector2D &shadowOffset)\n{\n\tint i;\n\tfor(i = 0; i< m_numControls; i++)\n\t\tif(m_controls[i])\n\t\t\tm_controls[i]->SetShadows(bDropShadows, shadowColor, shadowOffset);\n}\n\nvoid\nCMenuPage::GoUpMenuOnPage(void)\n{\n\tif(m_pCurrentControl == nil)\n\t\treturn;\n\tm_pCurrentControl->DeactivateMenu();\n\tdo{\n\t\tif(m_cursor == 0)\n\t\t\tm_cursor = m_numControls-1;\n\t\telse\n\t\t\tm_cursor--;\n\t\tm_pCurrentControl = m_controls[m_cursor];\n\t}while(!m_pCurrentControl->GoLast());\n}\n\nvoid\nCMenuPage::GoDownMenuOnPage(void)\n{\n\tif(m_pCurrentControl == nil)\n\t\treturn;\n\tm_pCurrentControl->DeactivateMenu();\n\tdo{\n\t\tif(m_cursor == m_numControls-1)\n\t\t\tm_cursor = 0;\n\t\telse\n\t\t\tm_cursor++;\n\t\tm_pCurrentControl = m_controls[m_cursor];\n\t}while(!m_pCurrentControl->GoFirst());\n}\n\nvoid\nCMenuPage::GoLeftMenuOnPage(void)\n{\n\t// same as up\n\tif(m_pCurrentControl == nil)\n\t\treturn;\n\tm_pCurrentControl->DeactivateMenu();\n\tdo{\n\t\tif(m_cursor == 0)\n\t\t\tm_cursor = m_numControls-1;\n\t\telse\n\t\t\tm_cursor--;\n\t\tm_pCurrentControl = m_controls[m_cursor];\n\t}while(!m_pCurrentControl->GoLast());\n}\n\nvoid\nCMenuPage::GoRightMenuOnPage(void)\n{\n\t// same as right\n\tif(m_pCurrentControl == nil)\n\t\treturn;\n\tm_pCurrentControl->DeactivateMenu();\n\tdo{\n\t\tif(m_cursor == m_numControls-1)\n\t\t\tm_cursor = 0;\n\t\telse\n\t\t\tm_cursor++;\n\t\tm_pCurrentControl = m_controls[m_cursor];\n\t}while(!m_pCurrentControl->GoFirst());\n}\n\n/*\n * CMenuPageAnyMove\n */\n\nvoid\nCMenuPageAnyMove::Initialise(void)\n{\n\tint i;\n\tCMenuPage::Initialise();\n\tfor(i = 0; i < NUM_PAGE_WIDGETS; i++){\n\t\tm_moveTab[i].left = -1;\n\t\tm_moveTab[i].right = -1;\n\t\tm_moveTab[i].up = -1;\n\t\tm_moveTab[i].down = -1;\n\t}\n}\n\nbool\nCMenuPageAnyMove::AddMenu(CMenuBase *widget, FEC_MOVETAB *moveTab)\n{\n\tif(AddMenu(widget)){\n\t\tm_moveTab[m_numControls-1] = *moveTab;\n\t\treturn true;\n\t}\n\treturn false;\n}\n\nvoid\nCMenuPageAnyMove::GoUpMenuOnPage(void)\n{\n\tif(m_pCurrentControl == nil)\n\t\treturn;\n\tm_pCurrentControl->DeactivateMenu();\n\tint move = m_moveTab[m_cursor].up;\n\tif(move == -1)\n\t\tCMenuPage::GoUpMenuOnPage();\n\telse{\t// BUG: no else in original code\n\t\tm_cursor = move;\n\t\tm_pCurrentControl = m_controls[m_cursor];\n\t\tm_pCurrentControl->GoLast();\n\t}\n}\n\nvoid\nCMenuPageAnyMove::GoDownMenuOnPage(void)\n{\n\tif(m_pCurrentControl == nil)\n\t\treturn;\n\tm_pCurrentControl->DeactivateMenu();\n\tint move = m_moveTab[m_cursor].down;\n\tif(move == -1)\n\t\tCMenuPage::GoDownMenuOnPage();\n\telse{\t// BUG: no else in original code\n\t\tm_cursor = move;\n\t\tm_pCurrentControl = m_controls[m_cursor];\n\t\tm_pCurrentControl->GoLast();\n\t}\n}\n\nvoid\nCMenuPageAnyMove::GoLeftMenuOnPage(void)\n{\n\tif(m_pCurrentControl == nil)\n\t\treturn;\n\tm_pCurrentControl->DeactivateMenu();\n\tint move = m_moveTab[m_cursor].left;\n\tif(move == -1)\n\t\tCMenuPage::GoLeftMenuOnPage();\n\telse{\t// BUG: no else in original code\n\t\tm_cursor = move;\n\t\tm_pCurrentControl = m_controls[m_cursor];\n\t\tm_pCurrentControl->GoLast();\n\t}\n}\n\nvoid\nCMenuPageAnyMove::GoRightMenuOnPage(void)\n{\n\tif(m_pCurrentControl == nil)\n\t\treturn;\n\tm_pCurrentControl->DeactivateMenu();\n\tint move = m_moveTab[m_cursor].right;\n\tif(move == -1)\n\t\tCMenuPage::GoRightMenuOnPage();\n\telse{\t// BUG: no else in original code\n\t\tm_cursor = move;\n\t\tm_pCurrentControl = m_controls[m_cursor];\n\t\tm_pCurrentControl->GoLast();\n\t}\n}\n"
  },
  {
    "path": "src/core/FrontEndControls.h",
    "content": "#pragma once\n\nenum {\n\tNUM_MULTICHOICE_OPTIONS = 16,\n\t// 50 actual lines and 15 for spacing\n\tNUM_LINELISTER_LINES = 50,\n\tNUM_LINELISTER_LINES_TOTAL = NUM_LINELISTER_LINES + 15,\n\tNUM_PAGE_WIDGETS = 10,\n};\n\nclass CTriggerCaller\n{\n\tbool bHasTrigger;\n\tvoid *pTrigger;\n\tvoid (*pFunc)(void *);\n\tint field_C;\npublic:\n\t\n\tCTriggerCaller() : bHasTrigger(false), pFunc(nil)\n\t{}\n\t\n\tvoid SetTrigger(void *func, void *trigger)\n\t{\n\t\tif ( !bHasTrigger )\n\t\t{\n\t\t\tpFunc = (void (*)(void *))func;\n\t\t\tpTrigger = trigger;\n\t\t\tbHasTrigger = true;\n\t\t}\n\t}\n\t\n\tvoid CallTrigger(void)\n\t{\n\t\tif ( bHasTrigger && pFunc != nil )\n\t\t\tpFunc(pTrigger);\n\t\t\n\t\tbHasTrigger = false;\n\t\tpFunc = nil;\n\t}\n\t\n\tbool CanCall()\n\t{\n\t\treturn bHasTrigger;\n\t}\n};\n\nclass CPlaceableText\n{\npublic:\n\tCVector2D m_position;\n\tCRGBA m_color;\n\twchar *m_text;\n\n\tCPlaceableText(void)\n\t : m_position(0.0f, 0.0f), m_color(255, 255, 255, 255), m_text(nil) {}\n\tvoid SetPosition(float x, float y) { m_position.x = x; m_position.y = y; }\n\tvoid SetColor(const CRGBA &color) { m_color = color; }\n\tCRGBA GetColor(void) { return m_color; }\n\tvoid SetAlpha(uint8 alpha) { m_color.alpha = alpha; }\n};\n\n// No trace of this in the game but it makes the other classes simpler\nclass CPlaceableTextTwoLines\n{\npublic:\n\tCPlaceableText m_line1;\n\tCPlaceableText m_line2;\n\n\tvoid SetColor(const CRGBA &color) { m_line1.SetColor(color); m_line2.SetColor(color); }\n\tvoid SetAlpha(uint8 alpha) { m_line1.SetAlpha(alpha); m_line2.SetAlpha(alpha); }\n};\n\n// No trace of this in the game but it makes the other classes simpler\nclass CShadowInfo\n{\npublic:\n\tbool m_bRightJustify;\n\tbool m_bDropShadow;\n\tCRGBA m_shadowColor;\n\tCVector2D m_shadowOffset;\n\n\tCShadowInfo(void)\n\t : m_bRightJustify(false), m_bDropShadow(false),\n\t   m_shadowColor(255, 255, 255, 255),\n\t   m_shadowOffset(-1.0f, -1.0f) {}\n\tCRGBA GetShadowColor(void) { return m_shadowColor; }\n\tvoid SetShadows(bool bDropShadows, const CRGBA &shadowColor, const CVector2D &shadowOffset){\n\t\tm_bDropShadow = bDropShadows;\n\t\tm_shadowColor = shadowColor;\n\t\tm_shadowOffset = shadowOffset;\n\t}\n};\n\n// No trace of this in the game but it makes the other classes simpler\nclass CSelectable\n{\npublic:\n\tbool m_bSelected;\n\tCRGBA m_selectedColor;\n\n\tCSelectable(void) : m_bSelected(false) {}\n\tCRGBA GetSelectedColor(void) { return m_selectedColor; }\n};\n\nclass CPlaceableShText : public CPlaceableText, public CShadowInfo\n{\npublic:\n\tusing CPlaceableText::SetPosition;\n\tvoid SetPosition(float x, float y, bool bRightJustify) { SetPosition(x, y); m_bRightJustify = bRightJustify; }\n\tvoid SetAlpha(uint8 alpha)  { m_shadowColor.alpha = alpha; CPlaceableText::SetAlpha(alpha); }\n\n\tvoid Draw(float x, float y);\n\tvoid Draw(const CRGBA &color, float x, float y);\n\t// unused arguments it seems\n\tvoid DrawShWrap(float x, float y, float wrapX, float wrapY) { Draw(x, y); }\n};\n\nclass CPlaceableShTextTwoLines : public CPlaceableTextTwoLines, public CShadowInfo\n{\npublic:\n\tvoid SetAlpha(uint8 alpha)  { m_shadowColor.alpha = alpha; CPlaceableTextTwoLines::SetAlpha(alpha); }\n\n\tvoid Draw(float x, float y);\n\tvoid Draw(const CRGBA &color, float x, float y);\n};\n\nclass CPlaceableShOption : public CPlaceableShText, public CSelectable\n{\npublic:\n\tvoid SetColors(const CRGBA &normal, const CRGBA &selection) { CPlaceableShText::SetColor(normal); m_selectedColor = selection; }\n\tvoid SetAlpha(uint8 alpha)  { m_selectedColor.alpha = alpha; CPlaceableShText::SetAlpha(alpha); }\n\n\tusing CPlaceableShText::Draw;\n\tvoid Draw(const CRGBA &highlightColor, float x, float y, bool bHighlight);\n};\n\nclass CPlaceableShOptionTwoLines : public CPlaceableShTextTwoLines, public CSelectable\n{\npublic:\n\tvoid SetColors(const CRGBA &normal, const CRGBA &selection) { CPlaceableShTextTwoLines::SetColor(normal); m_selectedColor = selection; }\n\tvoid SetAlpha(uint8 alpha)  { m_selectedColor.alpha = alpha; CPlaceableShTextTwoLines::SetAlpha(alpha); }\n\n\tusing CPlaceableShTextTwoLines::Draw;\n\tvoid Draw(const CRGBA &highlightColor, float x, float y, bool bHighlight);\n};\n\nclass CPlaceableSprite\n{\npublic:\n\tCSprite2d *m_pSprite;\n\tCVector2D m_position;\n\tCVector2D m_size;\n\tCRGBA m_color;\n\n\tCPlaceableSprite(void)\n\t : m_pSprite(nil), m_position(0.0f, 0.0f),\n\t   m_size(0.0f, 0.0f), m_color(255, 255, 255, 255) {}\n\n\tvoid SetPosition(float x, float y) { m_position.x = x; m_position.y = y; }\n\tvoid SetAlpha(uint8 alpha) { m_color.alpha = alpha; }\n\n\tvoid Draw(float x, float y);\n\tvoid Draw(const CRGBA &color, float x, float y);\n};\n\nclass CPlaceableShSprite\n{\npublic:\n\tCPlaceableSprite m_sprite;\n\tCPlaceableSprite m_shadow;\n\tbool m_bDropShadow;\n\n\tCPlaceableShSprite(void) : m_bDropShadow(false) {}\n\n\tvoid SetShadows(bool bDropShadows, const CRGBA &shadowColor, const CVector2D &shadowOffset){\n\t\tm_bDropShadow = bDropShadows;\n\t\tm_shadow.m_color = shadowColor;\n\t\tm_shadow.m_position = shadowOffset;\n\t}\n\tvoid SetAlpha(uint8 alpha)  { m_sprite.SetAlpha(alpha); m_shadow.SetAlpha(alpha); }\n\n\tvoid Draw(float x, float y);\n};\n\n\nclass CMenuBase\n{\npublic:\n\tCVector2D m_position;\n\tbool m_bTwoState;\n\n\tCMenuBase(void)\n\t : m_position(0.0f, 0.0f), m_bTwoState(false) {}\n\tvoid SetPosition(float x, float y) { m_position.x = x; m_position.y = y; }\n\n\tvirtual void Draw(const CRGBA &optionHighlight, const CRGBA &titleHighlight, float x, float y) = 0;\n\tvirtual void DrawNormal(float x, float y) = 0;\n\tvirtual void DrawHighlighted(const CRGBA &titleHighlight, float x, float y) = 0;\n\tvirtual void SetAlpha(uint8 alpha) = 0;\n\tvirtual void SetShadows(bool bDropShadows, const CRGBA &shadowColor, const CVector2D &shadowOffset) = 0;\n\tvirtual bool GoNext(void) = 0;\n\tvirtual bool GoPrev(void) = 0;\n\tvirtual bool GoDown(void) = 0;\n\tvirtual bool GoUp(void) = 0;\n\tvirtual bool GoDownStill(void) = 0;\n\tvirtual bool GoUpStill(void) = 0;\n\tvirtual bool GoLeft(void) = 0;\n\tvirtual bool GoRight(void) = 0;\n\tvirtual bool GoLeftStill(void) = 0;\n\tvirtual bool GoRightStill(void) = 0;\n\tvirtual bool GoFirst(void) = 0;\n\tvirtual bool GoLast(void) = 0;\n\tvirtual void SelectCurrentOptionUnderCursor(void) = 0;\n\tvirtual void SelectDefaultCancelAction(void) = 0;\n\tvirtual void ActivateMenu(bool first) = 0;\n\tvirtual void DeactivateMenu(void) = 0;\n\tvirtual int GetMenuSelection(void) = 0;\n\tvirtual void SetMenuSelection(int selection) = 0;\n};\n\nclass CMenuDummy : public CMenuBase\n{\npublic:\n\tbool m_bActive;\n\n\tvirtual void Draw(const CRGBA &, const CRGBA &, float x, float y) {}\n\tvirtual void DrawNormal(float x, float y) {}\n\tvirtual void DrawHighlighted(const CRGBA &, float x, float y) {}\n\tvirtual void SetAlpha(uint8 alpha) {}\n\tvirtual void SetShadows(bool bDropShadows, const CRGBA &shadowColor, const CVector2D &shadowOffset) {}\n\tvirtual bool GoNext(void) { DeactivateMenu(); return false; }\n\tvirtual bool GoPrev(void) { DeactivateMenu(); return false; }\n\tvirtual bool GoDown(void) { return GoNext(); }\n\tvirtual bool GoUp(void) { return GoPrev(); }\n\tvirtual bool GoDownStill(void) { return false; }\n\tvirtual bool GoUpStill(void) { return false; }\n\tvirtual bool GoLeft(void) { return true; }\n\tvirtual bool GoRight(void) { return true; }\n\tvirtual bool GoLeftStill(void) { return true; }\n\tvirtual bool GoRightStill(void) { return true; }\n\tvirtual bool GoFirst(void) { ActivateMenu(true); return true; }\n\tvirtual bool GoLast(void) { ActivateMenu(true); return true; }\n\tvirtual void SelectCurrentOptionUnderCursor(void) {}\n\tvirtual void SelectDefaultCancelAction(void) {}\n\tvirtual void ActivateMenu(bool first) { m_bActive = true; }\n\tvirtual void DeactivateMenu(void) { m_bActive = false; }\n\tvirtual int GetMenuSelection(void) { return -1; }\n\tvirtual void SetMenuSelection(int) {}\n};\n\nclass CMenuPictureAndText : public CMenuBase\n{\npublic:\n\tint m_numSprites;\n\tCPlaceableShSprite m_sprites[5];\n\tint m_numTexts;\n\tCPlaceableShText m_texts[20];\n\n\tCVector2D m_oldTextScale;\n\tCVector2D m_textScale;\n\tbool m_bSetTextScale;\n\n\tfloat m_wrapX;\n\tfloat m_oldWrapx;\n\tbool m_bWrap;\n\t// missing some?\n\n\n\tCMenuPictureAndText(void)\n\t : m_numSprites(0), m_numTexts(0),\n\t   m_bSetTextScale(false), m_bWrap(false) {}\n\n\tvoid SetNewOldShadowWrapX(bool bWrapX, float newWrapX, float oldWrapX);\n\tvoid SetNewOldTextScale(bool bTextScale, const CVector2D &newScale, const CVector2D &oldScale);\n\tvoid SetTextsColor(const CRGBA &color);\n\tvoid AddText(wchar *text, float positionX, float positionY, const CRGBA &color, bool bRightJustify);\n\tvoid AddPicture(CSprite2d *sprite, CSprite2d *shadow, float positionX, float positionY, float width, float height, const CRGBA &color);\n\tvoid AddPicture(CSprite2d *sprite, float positionX, float positionY, float width, float height, const CRGBA &color);\n\n\tvirtual void Draw(const CRGBA &, const CRGBA &, float x, float y);\n\tvirtual void DrawNormal(float x, float y) { Draw(CRGBA(0,0,0,0), CRGBA(0,0,0,0), x, y); }\n\tvirtual void DrawHighlighted(const CRGBA &, float x, float y) { Draw(CRGBA(0,0,0,0), CRGBA(0,0,0,0), x, y); }\n\tvirtual void SetAlpha(uint8 alpha);\n\tvirtual void SetShadows(bool bDropShadows, const CRGBA &shadowColor, const CVector2D &shadowOffset);\n\tvirtual bool GoNext(void) { return false; }\n\tvirtual bool GoPrev(void) { return false; }\n\tvirtual bool GoDown(void) { return GoNext(); }\n\tvirtual bool GoUp(void) { return GoPrev(); }\n\tvirtual bool GoDownStill(void) { return false; }\n\tvirtual bool GoUpStill(void) { return false; }\n\tvirtual bool GoLeft(void) { return true; }\n\tvirtual bool GoRight(void) { return true; }\n\tvirtual bool GoLeftStill(void) { return true; }\n\tvirtual bool GoRightStill(void) { return true; }\n\tvirtual bool GoFirst(void) { return false; }\n\tvirtual bool GoLast(void) { return false; }\n\tvirtual void SelectCurrentOptionUnderCursor(void) {}\n\tvirtual void SelectDefaultCancelAction(void) {}\n\tvirtual void ActivateMenu(bool first) {}\n\tvirtual void DeactivateMenu(void) {}\n\tvirtual int GetMenuSelection(void) { return -1; }\n\tvirtual void SetMenuSelection(int) {}\n};\n\nclass CMenuMultiChoice : public CMenuBase\n{\npublic:\n\tint m_numOptions;\n\tCPlaceableShText m_title;\n\tCPlaceableShOption m_options[NUM_MULTICHOICE_OPTIONS];\n\tint m_cursor;\n\tCVector2D m_oldTextScale;\n\tCVector2D m_textScale;\n\tbool m_bSetTextScale;\n\tbool m_bSetTitleTextScale;\n\n\tCMenuMultiChoice(void)\n\t : m_numOptions(0), m_cursor(-1),\n\t   m_bSetTextScale(false), m_bSetTitleTextScale(false) {}\n\n\tvoid AddTitle(wchar *text, float positionX, float positionY, bool bRightJustify);\n\tCPlaceableShOption *AddOption(wchar *text, float positionX, float positionY, bool bSelected, bool bRightJustify);\n\tvoid SetColors(const CRGBA &title, const CRGBA &normal, const CRGBA &selected);\n\tvoid SetNewOldTextScale(bool bTextScale, const CVector2D &newScale, const CVector2D &oldScale, bool bTitleTextScale);\n\n\tvirtual void Draw(const CRGBA &optionHighlight, const CRGBA &titleHighlight, float x, float y);\n\tvirtual void DrawNormal(float x, float y);\n\tvirtual void DrawHighlighted(const CRGBA &titleHighlight, float x, float y);\n\tvirtual void SetAlpha(uint8 alpha);\n\tvirtual void SetShadows(bool bDropShadows, const CRGBA &shadowColor, const CVector2D &shadowOffset);\n\tvirtual bool GoNext(void);\n\tvirtual bool GoPrev(void);\n\tvirtual bool GoDown(void) { return GoNext(); }\n\tvirtual bool GoUp(void) { return GoPrev(); }\n\tvirtual bool GoDownStill(void) { return false; }\n\tvirtual bool GoUpStill(void) { return false; }\n\tvirtual bool GoLeft(void) { return GoPrev(); }\n\tvirtual bool GoRight(void) { return GoNext(); }\n\tvirtual bool GoLeftStill(void) { return true; }\n\tvirtual bool GoRightStill(void) { return true; }\n\tvirtual bool GoFirst(void) { m_cursor = 0; return true; }\n\tvirtual bool GoLast(void) { m_cursor = m_numOptions-1; return true; }\n\tvirtual void SelectCurrentOptionUnderCursor(void);\n\tvirtual void SelectDefaultCancelAction(void) {}\n\tvirtual void ActivateMenu(bool first) { m_cursor = first ? 0 : m_numOptions-1; }\n\tvirtual void DeactivateMenu(void) { m_cursor = -1; }\n\tvirtual int GetMenuSelection(void);\n\tvirtual void SetMenuSelection(int selection);\n};\n\nclass CMenuMultiChoiceTriggered : public CMenuMultiChoice\n{\npublic:\n\ttypedef void (*Trigger)(CMenuMultiChoiceTriggered *);\n\n\tTrigger m_triggers[NUM_MULTICHOICE_OPTIONS];\n\tTrigger m_defaultCancel;\n\n\tCMenuMultiChoiceTriggered(void) { Initialise(); }\n\n\tvoid Initialise(void);\n\tCPlaceableShOption *AddOption(wchar *text, float positionX, float positionY, Trigger trigger, bool bSelected, bool bRightJustify);\n\n\tvirtual void SelectCurrentOptionUnderCursor(void);\n\tvirtual void SelectDefaultCancelAction(void);\n};\n\nclass CMenuMultiChoiceTriggeredAlways : public CMenuMultiChoiceTriggered\n{\npublic:\n\tTrigger m_alwaysNormalTrigger;\n\tTrigger m_alwaysHighlightTrigger;\n\tTrigger m_alwaysTrigger;\n\n\tCMenuMultiChoiceTriggeredAlways(void)\n\t : m_alwaysNormalTrigger(nil), m_alwaysHighlightTrigger(nil), m_alwaysTrigger(nil) {}\n\n\tvirtual void Draw(const CRGBA &optionHighlight, const CRGBA &titleHighlight, float x, float y);\n\tvirtual void DrawNormal(float x, float y);\n\tvirtual void DrawHighlighted(const CRGBA &titleHighlight, float x, float y);\n};\n\nclass CMenuMultiChoicePictured : public CMenuMultiChoice\n{\npublic:\n\tCPlaceableSprite m_sprites[NUM_MULTICHOICE_OPTIONS];\n\tbool m_bHasSprite[NUM_MULTICHOICE_OPTIONS];\n\n\tCMenuMultiChoicePictured(void) { Initialise(); }\n\tvoid Initialise(void);\n\tusing CMenuMultiChoice::AddOption;\n\tCPlaceableShOption *AddOption(CSprite2d *sprite, float positionX, float positionY, const CVector2D &size, bool bSelected);\n\n\tvirtual void Draw(const CRGBA &optionHighlight, const CRGBA &titleHighlight, float x, float y);\n\tvirtual void DrawNormal(float x, float y);\n\tvirtual void DrawHighlighted(const CRGBA &titleHighlight, float x, float y);\n\tvirtual void SetAlpha(uint8 alpha);\n\t// unnecessary - same as base class\n//\tvirtual void SetShadows(bool bDropShadows, const CRGBA &shadowColor, const CVector2D &shadowOffset);\n};\n\nclass CMenuMultiChoicePicturedTriggered : public CMenuMultiChoicePictured\n{\npublic:\n\ttypedef void (*Trigger)(CMenuMultiChoicePicturedTriggered *);\n\n\tTrigger m_triggers[NUM_MULTICHOICE_OPTIONS];\n\tTrigger m_defaultCancel;\n\n\tCMenuMultiChoicePicturedTriggered(void) { Initialise(); }\n\n\tvoid Initialise(void);\n\tusing CMenuMultiChoicePictured::AddOption;\n\tCPlaceableShOption *AddOption(CSprite2d *sprite, float positionX, float positionY, const CVector2D &size, Trigger trigger, bool bSelected);\n\n\tvirtual void SelectCurrentOptionUnderCursor(void);\n\tvirtual void SelectDefaultCancelAction(void);\n};\n\nstruct FEC_MOVETAB\n{\n\tint8 right;\n\tint8 left;\n\tint8 down;\n\tint8 up;\n};\n\nclass CMenuMultiChoicePicturedTriggeredAnyMove : public CMenuMultiChoicePicturedTriggered\n{\npublic:\n\tFEC_MOVETAB m_moveTab[NUM_MULTICHOICE_OPTIONS];\n\n\tCMenuMultiChoicePicturedTriggeredAnyMove(void) { Initialise(); }\n\n\tvoid Initialise(void);\n\tusing CMenuMultiChoicePicturedTriggered::AddOption;\n\tCPlaceableShOption *AddOption(CSprite2d *sprite, FEC_MOVETAB *moveTab, float positionX, float positionY, const CVector2D &size, Trigger trigger, bool bSelected);\n\n\tvirtual bool GoDown(void);\n\tvirtual bool GoUp(void);\n\tvirtual bool GoLeft(void);\n\tvirtual bool GoRight(void);\n};\n\n// copy of CMenuMultiChoice pretty much except for m_options type\nclass CMenuMultiChoiceTwoLines : public CMenuBase\n{\npublic:\n\tint m_numOptions;\n\tCPlaceableShText m_title;\n\tCPlaceableShOptionTwoLines m_options[NUM_MULTICHOICE_OPTIONS];\n\tint m_cursor;\n\tCVector2D m_oldTextScale;\n\tCVector2D m_textScale;\n\tbool m_bSetTextScale;\n\tbool m_bSetTitleTextScale;\n\n\tCMenuMultiChoiceTwoLines(void)\n\t : m_numOptions(0), m_cursor(-1),\n\t   m_bSetTextScale(false), m_bSetTitleTextScale(false) {}\n\n\tvoid AddTitle(wchar *text, float positionX, float positionY, bool bRightJustify);\n\tCPlaceableShOptionTwoLines *AddOption(wchar *text, float positionX, float positionY, bool bSelected, bool bRightJustify);\n\tCPlaceableShOptionTwoLines *AddOption(wchar *text1, float positionX1, float positionY1, wchar *text2, float positionX2, float positionY2, bool bSelected, bool bRightJustify);\n\tvoid SetColors(const CRGBA &title, const CRGBA &normal, const CRGBA &selected);\n\tvoid SetNewOldTextScale(bool bTextScale, const CVector2D &newScale, const CVector2D &oldScale, bool bTitleTextScale);\n\n\tvirtual void Draw(const CRGBA &optionHighlight, const CRGBA &titleHighlight, float x, float y);\n\tvirtual void DrawNormal(float x, float y);\n\tvirtual void DrawHighlighted(const CRGBA &titleHighlight, float x, float y);\n\tvirtual void SetAlpha(uint8 alpha);\n\tvirtual void SetShadows(bool bDropShadows, const CRGBA &shadowColor, const CVector2D &shadowOffset);\n\tvirtual bool GoNext(void);\n\tvirtual bool GoPrev(void);\n\tvirtual bool GoDown(void) { return GoNext(); }\n\tvirtual bool GoUp(void) { return GoPrev(); }\n\tvirtual bool GoDownStill(void) { return true; }\n\tvirtual bool GoUpStill(void) { return true; }\n\tvirtual bool GoLeft(void) { return GoPrev(); }\n\tvirtual bool GoRight(void) { return GoNext(); }\n\tvirtual bool GoLeftStill(void) { return true; }\n\tvirtual bool GoRightStill(void) { return true; }\n\tvirtual bool GoFirst(void) { m_cursor = 0; return true; }\n\tvirtual bool GoLast(void) { m_cursor = m_numOptions-1; return true; }\n\tvirtual void SelectCurrentOptionUnderCursor(void);\n\tvirtual void SelectDefaultCancelAction(void) {}\n\tvirtual void ActivateMenu(bool first) { m_cursor = first ? 0 : m_numOptions-1; }\n\tvirtual void DeactivateMenu(void) { m_cursor = -1; }\n\tvirtual int GetMenuSelection(void);\n\tvirtual void SetMenuSelection(int selection);\n};\n\n// copy of CMenuMultiChoiceTriggered except for m_options\nclass CMenuMultiChoiceTwoLinesTriggered : public CMenuMultiChoiceTwoLines\n{\npublic:\n\ttypedef void (*Trigger)(CMenuMultiChoiceTwoLinesTriggered *);\n\n\tTrigger m_triggers[NUM_MULTICHOICE_OPTIONS];\n\tTrigger m_defaultCancel;\n\n\tCMenuMultiChoiceTwoLinesTriggered(void) { Initialise(); }\n\n\tvoid Initialise(void);\n\tCPlaceableShOptionTwoLines *AddOption(wchar *text, float positionX, float positionY, Trigger trigger, bool bSelected, bool bRightJustify);\n\tCPlaceableShOptionTwoLines *AddOption(wchar *text1, float positionX1, float positionY1, wchar *text2, float positionX2, float positionY2, Trigger trigger, bool bSelected, bool bRightJustify);\n\n\tvirtual void SelectCurrentOptionUnderCursor(void);\n\tvirtual void SelectDefaultCancelAction(void);\n};\n\n\nclass CMenuOnOff : public CMenuBase\n{\npublic:\n\tCPlaceableShOption m_title;\n\tCPlaceableShText m_options[2];\n\tbool m_bActive;\n\tbool m_bSetTextScale;\n\tbool m_bSetTitleTextScale;\n\tCVector2D m_textScale;\n\tCVector2D m_oldTextScale;\n\tint m_type;\t// 0: on/off 1: yes/no\n\n\tvoid SetColors(const CRGBA &title, const CRGBA &options);\n\tvoid SetNewOldTextScale(bool bTextScale, const CVector2D &newScale, const CVector2D &oldScale, bool bTitleTextScale);\n\tvoid SetOptionPosition(float x, float y, bool bRightJustify);\n\tvoid AddTitle(wchar *text, bool bSelected, float positionX, float positionY, bool bRightJustify);\n\n\tvirtual void Draw(const CRGBA &optionHighlight, const CRGBA &titleHighlight, float x, float y);\n\tvirtual void DrawNormal(float x, float y);\n\tvirtual void DrawHighlighted(const CRGBA &titleHighlight, float x, float y);\n\tvirtual void SetAlpha(uint8 alpha);\n\tvirtual void SetShadows(bool bDropShadows, const CRGBA &shadowColor, const CVector2D &shadowOffset);\n\tvirtual bool GoNext(void) { DeactivateMenu(); return false; }\n\tvirtual bool GoPrev(void) { DeactivateMenu(); return false; }\n\tvirtual bool GoDown(void) { return GoNext(); }\n\tvirtual bool GoUp(void) { return GoPrev(); }\n\tvirtual bool GoDownStill(void) { return false; }\n\tvirtual bool GoUpStill(void) { return false; }\n\tvirtual bool GoLeft(void) { SelectCurrentOptionUnderCursor(); return true; }\n\tvirtual bool GoRight(void) { SelectCurrentOptionUnderCursor(); return true; }\n\tvirtual bool GoLeftStill(void) { return true; }\n\tvirtual bool GoRightStill(void) { return true; }\n\tvirtual bool GoFirst(void) { ActivateMenu(true); return true; }\n\tvirtual bool GoLast(void) { ActivateMenu(true); return true; }\n\tvirtual void SelectCurrentOptionUnderCursor(void) { m_title.m_bSelected ^= 1; }\n\tvirtual void SelectDefaultCancelAction(void) {}\n\tvirtual void ActivateMenu(bool first) { m_bActive = true; }\n\tvirtual void DeactivateMenu(void) { m_bActive = false; }\n\tvirtual int GetMenuSelection(void) { return m_title.m_bSelected; }\n\tvirtual void SetMenuSelection(int selection) { m_title.m_bSelected = selection; }\n};\n\nclass CMenuOnOffTriggered : public CMenuOnOff\n{\npublic:\n\ttypedef void (*Trigger)(CMenuOnOffTriggered *);\n\n\tTrigger m_trigger;\n\n\tvoid SetOptionPosition(float x, float y, Trigger trigger, bool bRightJustify);\n\n\tvirtual void SelectCurrentOptionUnderCursor(void);\n};\n\nclass CMenuSlider : public CMenuBase\n{\npublic:\n\tCPlaceableShText m_title;\n\tCPlaceableShText m_box;\t// not really a text\n\tCRGBA m_colors[2];\t// left and right\n\tCVector2D m_size[2];\t// left and right\n\tint m_value;\n\tCPlaceableShText m_percentageText;\n\tbool m_bDrawPercentage;\n//\tchar field_8D;\n//\tchar field_8E;\n//\tchar field_8F;\n\tuint8 m_someAlpha;\n//\tchar field_91;\n//\tchar field_92;\n//\tchar field_93;\n\tbool m_bActive;\n\tint m_style;\n\n\tstatic char Buf8[8];\n\tstatic wchar Buf16[8];\n\n\tCMenuSlider(void)\n\t : m_value(0), m_bDrawPercentage(false), m_bActive(false), m_style(0)\n\t{\n\t\tAddTickBox(0.0f, 0.0f, 100.0f, 10.0f, 10.0f); //todo\n\t}\n\n\tvoid SetColors(const CRGBA &title, const CRGBA &percentage, const CRGBA &left, const CRGBA &right);\n\tvoid DrawTicks(const CVector2D &position, const CVector2D &size, float heightRight, float level, const CRGBA &leftCol, const CRGBA &selCol, const CRGBA &rightCol, bool bShadow, const CVector2D &shadowOffset, const CRGBA &shadowColor);\n\tvoid DrawTicks(const CVector2D &position, const CVector2D &size, float heightRight, float level, const CRGBA &leftCol, const CRGBA &rightCol,                      bool bShadow, const CVector2D &shadowOffset, const CRGBA &shadowColor);\n\tvoid AddTickBox(float positionX, float positionY, float width, float heigthLeft, float heightRight);\n\tvoid AddTitle(wchar *text, float positionX, float positionY);\n\n\tvirtual void Draw(const CRGBA &optionHighlight, const CRGBA &titleHighlight, float x, float y);\n\tvirtual void DrawNormal(float x, float y);\n\tvirtual void DrawHighlighted(const CRGBA &titleHighlight, float x, float y);\n\tvirtual void SetAlpha(uint8 alpha);\n\tvirtual void SetShadows(bool bDropShadows, const CRGBA &shadowColor, const CVector2D &shadowOffset);\n\tvirtual bool GoNext(void) { DeactivateMenu(); return false; }\n\tvirtual bool GoPrev(void) { DeactivateMenu(); return false; }\n\tvirtual bool GoDown(void) { return GoNext(); }\n\tvirtual bool GoUp(void) { return GoPrev(); }\n\tvirtual bool GoDownStill(void) { return false; }\n\tvirtual bool GoUpStill(void) { return false; }\n\tvirtual bool GoLeft(void) { if(m_value < 0) m_value = 0; return true; }\n\tvirtual bool GoRight(void) { if(m_value > 1000) m_value = 1000; return true; }\n\tvirtual bool GoLeftStill(void) { m_value -= 8; if(m_value < 0) m_value = 0; return true; }\n\tvirtual bool GoRightStill(void) { m_value += 8; if(m_value > 1000) m_value = 1000; return true; }\n\tvirtual bool GoFirst(void) { ActivateMenu(true); return true; }\n\tvirtual bool GoLast(void) { ActivateMenu(true); return true; }\n\tvirtual void SelectCurrentOptionUnderCursor(void) {}\n\tvirtual void SelectDefaultCancelAction(void) {}\n\tvirtual void ActivateMenu(bool first) { m_bActive = true; }\n\tvirtual void DeactivateMenu(void) { m_bActive = false; }\n\tvirtual int GetMenuSelection(void) { return m_value/10; }\n\tvirtual void SetMenuSelection(int selection) { m_value = selection*10; }\n};\n\nclass CMenuSliderTriggered : public CMenuSlider\n{\npublic:\n\ttypedef void (*Trigger)(CMenuSliderTriggered *);\n\n\tTrigger m_trigger;\n\tTrigger m_alwaysTrigger;\n\n\tCMenuSliderTriggered(void)\n\t : m_trigger(nil), m_alwaysTrigger(nil) {}\n\n\tvoid AddTickBox(float positionX, float positionY, float width, float heigthLeft, float heightRight, Trigger trigger, Trigger alwaysTrigger);\n\n\tvirtual void Draw(const CRGBA &optionHighlight, const CRGBA &titleHighlight, float x, float y);\n\tvirtual bool GoLeft(void);\n\tvirtual bool GoRight(void);\n\tvirtual bool GoLeftStill(void);\n\tvirtual bool GoRightStill(void);\n};\n\n\nclass CMenuLineLister : public CMenuBase\n{\npublic:\n\tfloat m_width;\n\tfloat m_height;\n\tint m_numLines;\n\tCPlaceableShText m_linesLeft[NUM_LINELISTER_LINES_TOTAL];\n\tCPlaceableShText m_linesRight[NUM_LINELISTER_LINES_TOTAL];\n\tuint8 m_lineAlphas[NUM_LINELISTER_LINES_TOTAL];\n\tint8 m_lineFade[NUM_LINELISTER_LINES_TOTAL];\n\tfloat m_scrollPosition;\n\tfloat m_scrollSpeed;\n\tint field_10E8;\n\tfloat m_lineSpacing;\n\n\tCMenuLineLister(void);\n\n\tvoid SetLinesColor(const CRGBA &color);\n\tvoid ResetNumberOfTextLines(void);\n\tbool AddTextLine(wchar *left, wchar *right);\n\n\tCPlaceableShText *GetLeftLine(int i) { return &m_linesLeft[(i%NUM_LINELISTER_LINES) + 15]; };\n\tCPlaceableShText *GetRightLine(int i) { return &m_linesRight[(i%NUM_LINELISTER_LINES) + 15]; };\n\n\tvirtual void Draw(const CRGBA &optionHighlight, const CRGBA &titleHighlight, float x, float y);\n\tvirtual void DrawNormal(float x, float y) { Draw(CRGBA(0,0,0,0), CRGBA(0,0,0,0), x, y); }\n\tvirtual void DrawHighlighted(const CRGBA &titleHighlight, float x, float y) { Draw(CRGBA(0,0,0,0), CRGBA(0,0,0,0), x, y); }\n\tvirtual void SetAlpha(uint8 alpha);\n\tvirtual void SetShadows(bool bDropShadows, const CRGBA &shadowColor, const CVector2D &shadowOffset);\n\tvirtual bool GoNext(void) { return false; }\n\tvirtual bool GoPrev(void) { return false; }\n\tvirtual bool GoDown(void) { return GoNext(); }\n\tvirtual bool GoUp(void) { return GoPrev(); }\n\tvirtual bool GoDownStill(void) { m_scrollSpeed = 0.0f; return true; }\n\tvirtual bool GoUpStill(void) { m_scrollSpeed *= 6.0f; return true; }\n\tvirtual bool GoLeft(void) { return true; }\n\tvirtual bool GoRight(void) { return true; }\n\tvirtual bool GoLeftStill(void) { return true; }\n\tvirtual bool GoRightStill(void) { return true; }\n\tvirtual bool GoFirst(void) { return true; }\n\tvirtual bool GoLast(void) { return true; }\n\tvirtual void SelectCurrentOptionUnderCursor(void) {}\n\tvirtual void SelectDefaultCancelAction(void) {}\n\tvirtual void ActivateMenu(bool first) {}\n\tvirtual void DeactivateMenu(void) {}\n\tvirtual int GetMenuSelection(void) { return -1; }\n\tvirtual void SetMenuSelection(int selection) {}\n};\n\nclass CMenuPage\n{\npublic:\n\tCMenuBase *m_controls[NUM_PAGE_WIDGETS];\n\tint m_numControls;\n\tCMenuBase *m_pCurrentControl;\n\tint m_cursor;\n\n\tCMenuPage(void) { Initialise(); }\n\tvoid Initialise(void);\n\tbool AddMenu(CMenuBase *widget);\n\n\tbool IsActiveMenuTwoState(void);\n\tvoid ActiveMenuTwoState_SelectNextPosition(void);\n\tvoid Draw(const CRGBA &,const CRGBA &, float, float);\n\tvoid DrawHighlighted(const CRGBA &titleHighlight, float x, float y);\n\tvoid DrawNormal(float x, float y);\n\tvoid ActivatePage(void);\n\tvoid SetAlpha(uint8 alpha);\n\tvoid SetShadows(bool, const CRGBA &, const CVector2D &);\n\tvoid GoPrev(void) { if(m_pCurrentControl) { if(!m_pCurrentControl->GoPrev()) m_pCurrentControl->GoLast(); } }\n\tvoid GoNext(void) { if(m_pCurrentControl) { if(!m_pCurrentControl->GoNext()) m_pCurrentControl->GoFirst(); } }\n\tvoid GoLeft(void) { if(m_pCurrentControl) { if(!m_pCurrentControl->GoLeft()) m_pCurrentControl->GoLast(); } }\n\tvoid GoRight(void) { if(m_pCurrentControl) { if(!m_pCurrentControl->GoRight()) m_pCurrentControl->GoFirst(); } }\n\tvoid GoUp(void) { if(m_pCurrentControl) { if(!m_pCurrentControl->GoUp()) m_pCurrentControl->GoLast(); } }\n\tvoid GoDown(void) { if(m_pCurrentControl) { if(!m_pCurrentControl->GoDown()) m_pCurrentControl->GoFirst(); } }\n\tvoid GoLeftStill(void) { if(m_pCurrentControl) m_pCurrentControl->GoLeftStill(); }\n\tvoid GoRightStill(void) { if(m_pCurrentControl) m_pCurrentControl->GoRightStill(); }\n\tvoid GoUpStill(void) { if(m_pCurrentControl) m_pCurrentControl->GoUpStill(); }\n\tvoid GoDownStill(void) { if(m_pCurrentControl) m_pCurrentControl->GoDownStill(); }\n\tvoid SelectDefaultCancelAction(void) { if(m_pCurrentControl) m_pCurrentControl->SelectDefaultCancelAction(); }\n\tvoid SelectCurrentOptionUnderCursor(void) { if(m_pCurrentControl) m_pCurrentControl->SelectCurrentOptionUnderCursor(); }\n\n\tvirtual void GoUpMenuOnPage(void);\n\tvirtual void GoDownMenuOnPage(void);\n\tvirtual void GoLeftMenuOnPage(void);\n\tvirtual void GoRightMenuOnPage(void);\n};\n\nclass CMenuPageAnyMove : public CMenuPage\n{\npublic:\n\tFEC_MOVETAB m_moveTab[NUM_PAGE_WIDGETS];\n\n\tCMenuPageAnyMove(void) { Initialise(); }\n\tvoid Initialise(void);\n\tusing CMenuPage::AddMenu;\n\tbool AddMenu(CMenuBase *widget, FEC_MOVETAB *moveTab);\n\n\tvirtual void GoUpMenuOnPage(void);\n\tvirtual void GoDownMenuOnPage(void);\n\tvirtual void GoLeftMenuOnPage(void);\n\tvirtual void GoRightMenuOnPage(void);\n};"
  },
  {
    "path": "src/core/Frontend.cpp",
    "content": "#define FORCE_PC_SCALING\n#define WITHWINDOWS\n#define WITHDINPUT\n#include \"common.h\"\n#ifndef PS2_MENU\n#include \"crossplatform.h\"\n#include \"platform.h\"\n#include \"Frontend.h\"\n#include \"Font.h\"\n#include \"Pad.h\"\n#include \"Text.h\"\n#include \"main.h\"\n#include \"RwHelper.h\"\n#include \"Timer.h\"\n#include \"Game.h\"\n#include \"DMAudio.h\"\n#include \"FileMgr.h\"\n#include \"Streaming.h\"\n#include \"TxdStore.h\"\n#include \"General.h\"\n#include \"GenericGameStorage.h\"\n#include \"Script.h\"\n#include \"Camera.h\"\n#include \"ControllerConfig.h\"\n#include \"Vehicle.h\"\n#include \"MBlur.h\"\n#include \"PlayerSkin.h\"\n#include \"PlayerInfo.h\"\n#include \"World.h\"\n#include \"Renderer.h\"\n#include \"CdStream.h\"\n#include \"Radar.h\"\n#include \"Stats.h\"\n#include \"Messages.h\"\n#include \"FileLoader.h\"\n#include \"User.h\"\n#include \"sampman.h\"\n\n// Similar story to Hud.cpp:\n// Game has colors inlined in code.\n// For easier modification we collect them here:\nconst CRGBA LABEL_COLOR(255, 150, 225, 255);\nconst CRGBA SELECTIONBORDER_COLOR(25, 130, 70, 255);\nconst CRGBA MENUOPTION_COLOR = LABEL_COLOR;\nconst CRGBA SELECTEDMENUOPTION_COLOR = LABEL_COLOR;\nconst CRGBA HEADER_COLOR = LABEL_COLOR;\nconst CRGBA DARKMENUOPTION_COLOR(195, 90, 165, 255);\nconst CRGBA SLIDERON_COLOR(97, 194, 247, 255);\nconst CRGBA SLIDEROFF_COLOR(27, 89, 130, 255);\nconst CRGBA LIST_BACKGROUND_COLOR(49, 101, 148, 130);\nconst CRGBA LIST_OPTION_COLOR(155, 155, 155, 255);\nconst CRGBA RADIO_SELECTOR_COLOR = SLIDEROFF_COLOR;\nconst CRGBA INACTIVE_RADIO_COLOR(100, 100, 255, 100);\nconst CRGBA SCROLLBAR_COLOR = LABEL_COLOR;\n\n#define MAP_MIN_SIZE 162.f\n#define MAP_SIZE_TO_ALLOW_X_MOVE 297.f\n\n#define MAX_VISIBLE_LIST_ROW 30\n#define SCROLLBAR_MAX_HEIGHT 263.0f // not in end result\n#define SCROLLABLE_PAGES\n\n#define hasNativeList(screen) (screen == MENUPAGE_SKIN_SELECT || screen == MENUPAGE_KEYBOARD_CONTROLS)\n\n#ifdef SCROLLABLE_PAGES\n#define MAX_VISIBLE_OPTION 12\n#define MAX_VISIBLE_OPTION_ON_SCREEN (hasNativeList(m_nCurrScreen) ? MAX_VISIBLE_LIST_ROW : MAX_VISIBLE_OPTION)\n#define SCREEN_HAS_AUTO_SCROLLBAR (m_nTotalListRow > MAX_VISIBLE_OPTION && !hasNativeList(m_nCurrScreen))\n\nint GetOptionCount(int screen)\n{\n\tint i = 0;\n\tfor (; i < NUM_MENUROWS && aScreens[screen].m_aEntries[i].m_Action != MENUACTION_NOTHING; i++);\n\treturn i;\n}\n\n#define SETUP_SCROLLING(screen) \\\n\t\tif (!hasNativeList(screen)) { \\\n\t\t\tm_nTotalListRow = GetOptionCount(screen); \\\n\t\t\tif (m_nTotalListRow > MAX_VISIBLE_OPTION) { \\\n\t\t\t\tm_nSelectedListRow = 0; \\\n\t\t\t\tm_nFirstVisibleRowOnList = 0; \\\n\t\t\t\tm_nScrollbarTopMargin = 0; \\\n\t\t\t} \\\n\t\t}\n\n#define MINUS_SCROLL_OFFSET - scrollOffset\n#else\n#define MAX_VISIBLE_OPTION_ON_SCREEN MAX_VISIBLE_LIST_ROW\n#define SETUP_SCROLLING(screen)\n#define MINUS_SCROLL_OFFSET\n#endif\n\n#ifdef TRIANGLE_BACK_BUTTON\n#define GetBackJustUp GetTriangleJustUp\n#define GetBackJustDown GetTriangleJustDown\n#elif defined(CIRCLE_BACK_BUTTON)\n#define GetBackJustUp GetCircleJustUp\n#define GetBackJustDown GetCircleJustDown\n#else\n#define GetBackJustUp GetSquareJustUp\n#define GetBackJustDown GetSquareJustDown\n#endif\n\n#ifdef MAP_ENHANCEMENTS\nCVector2D mapCrosshair;\n#endif\n\n#ifdef CUTSCENE_BORDERS_SWITCH\nbool CMenuManager::m_PrefsCutsceneBorders = true;\n#endif\n\nbool holdingScrollBar; // *(bool*)0x7039B9; // not original name\n\nCMenuManager FrontEndMenuManager;\nMenuTrapezoid menuBg(CGeneral::GetRandomNumber() % 40 + 65, CGeneral::GetRandomNumber() % 40 + 21,\n\tCGeneral::GetRandomNumber() % 40 + 568, CGeneral::GetRandomNumber() % 40 + 44,\n\tCGeneral::GetRandomNumber() % 40 + 36, CGeneral::GetRandomNumber() % 40 + 352,\n\tCGeneral::GetRandomNumber() % 40 + 593, CGeneral::GetRandomNumber() % 40 + 312);\n\nMenuTrapezoid menuOptionHighlight(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f);\n\n#ifndef MASTER\nbool CMenuManager::m_PrefsMarketing = false;\nbool CMenuManager::m_PrefsDisableTutorials = false;\n#endif // !MASTER\n\n#ifdef GAMEPAD_MENU\nuint32 TimeToStopPadShaking;\n#endif\n\nconst char* FrontendFilenames[][2] = {\n\t{\"background\", \"\"},\n\t{\"vc_logo\", \"vc_logom\"},\n\t{\"mouse\", \"mousea\"},\n\t{\"mapTop01\", \"mapTop01A\"},\n\t{\"mapTop02\", \"mapTop02A\"},\n\t{\"mapTop03\", \"mapTop03A\"},\n\t{\"mapMid01\", \"mapMid01A\"},\n\t{\"mapMid02\", \"mapMid02A\"},\n\t{\"mapMid03\", \"mapMid03A\"},\n\t{\"mapBot01\", \"mapBot01A\"},\n\t{\"mapBot02\", \"mapBot02A\"},\n\t{\"mapBot03\", \"mapBot03A\"},\n\t{\"wildstyle\", \"wildstyleA\"},\n\t{\"flash\", \"flashA\"},\n\t{\"kchat\", \"kchatA\"},\n\t{\"fever\", \"feverA\"},\n\t{\"vrock\", \"vrockA\"},\n\t{\"vcpr\", \"vcprA\"},\n\t{\"espantoso\", \"espantosoA\"},\n\t{\"emotion\", \"emotionA\"},\n\t{\"wave103\", \"wave103A\"},\n\t{\"mp3\", \"mp3A\"},\n\t{\"downOff\", \"buttonA\"},\n\t{\"downOn\", \"buttonA\"},\n\t{\"upOff\", \"buttonA\"},\n\t{\"upOn\", \"buttonA\"},\n#ifdef GAMEPAD_MENU\n\t{\"fe_controller\", \"\" },\n\t{\"fe_arrows1\", \"\" },\n\t{\"fe_arrows2\", \"\" },\n\t{\"fe_arrows3\", \"\" },\n\t{\"fe_arrows4\", \"\" },\n#endif\n};\n\n#define MENU_X_RIGHT_ALIGNED(x) SCALE_AND_CENTER_X(DEFAULT_SCREEN_WIDTH - (x))\n\n#ifdef ASPECT_RATIO_SCALE\n// All of the defines below replace the StretchX function. Otherwise use SCREEN_SCALE_X.\n#define MENU_X_LEFT_ALIGNED(x) SCALE_AND_CENTER_X(x)\n#define MENU_X(x) SCREEN_SCALE_X(x)\n#define MENU_Y(y) SCREEN_SCALE_Y(y)\n#else\n#define MENU_X_LEFT_ALIGNED(x) StretchX(x)\n#define MENU_X(x) StretchX(x)\n#define MENU_Y(y) StretchY(y)\n#endif\n\n#ifdef XBOX_MESSAGE_SCREEN\nbool CMenuManager::m_bDialogOpen = false;\nuint32 CMenuManager::m_nDialogHideTimer = 0;\nPauseModeTime CMenuManager::m_nDialogHideTimerPauseMode = 0;\nbool CMenuManager::m_bSaveWasSuccessful = false;\nwchar* CMenuManager::m_pDialogText = nil;\n#endif\n\n#define SET_FONT_FOR_MENU_HEADER \\\n\tCFont::SetRightJustifyOn(); \\\n\tCFont::SetFontStyle(FONT_LOCALE(FONT_HEADING)); \\\n\tCFont::SetScale(MENU_X(MENUHEADER_WIDTH), MENU_Y(MENUHEADER_HEIGHT)); \\\n\tCFont::SetDropShadowPosition(0);\n\n#define SET_FONT_FOR_LIST_ITEM \\\n\tCFont::SetRightJustifyOff(); \\\n\tCFont::SetScale(MENU_X(LISTITEM_X_SCALE), MENU_Y(LISTITEM_Y_SCALE)); \\\n\tCFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD));\n\n#define RESET_FONT_FOR_NEW_PAGE \\\n\tCFont::SetBackgroundOff(); \\\n\tCFont::SetScale(MENU_X(MENUACTION_SCALE_MULT), MENU_Y(MENUACTION_SCALE_MULT)); \\\n\tCFont::SetPropOn(); \\\n\tCFont::SetCentreOff(); \\\n\tCFont::SetJustifyOn(); \\\n\tCFont::SetRightJustifyOff(); \\\n\tCFont::SetBackGroundOnlyTextOn(); \\\n\tCFont::SetWrapx(MENU_X_RIGHT_ALIGNED(MENU_X_MARGIN)); \\\n\tCFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(MENU_X_MARGIN));\n\n#define ProcessSlider(value, origY, increaseAction, decreaseAction, hoverEndX, onlyWhenHoveringRow) \\\n\tdo { \\\n\t\tfloat y = origY MINUS_SCROLL_OFFSET; \\\n\t\tlastActiveBarX = DisplaySlider(MENU_X_LEFT_ALIGNED(MENUSLIDER_X), MENU_Y(y), MENU_Y(MENUSLIDER_SMALLEST_BAR), MENU_Y(MENUSLIDER_BIGGEST_BAR), MENU_X(MENUSLIDER_UNK), value, MENU_X(3.0f)); \\\n\t\tif (i != m_nCurrOption || !itemsAreSelectable) \\\n\t\t\tbreak; \\\n\t\t \\\n\t\tif (CheckHover(0, lastActiveBarX - MENU_X(3.0f), MENU_Y(y), MENU_Y(MENUSLIDER_BIGGEST_BAR + y))) { \\\n\t\t\tm_nHoverOption = decreaseAction; \\\n\t\t\tbreak; \\\n\t\t} \\\n\t\tif (!CheckHover(MENU_X(3.0f) + lastActiveBarX, hoverEndX, MENU_Y(y), MENU_Y(MENUSLIDER_BIGGEST_BAR + y))) { \\\n\t\t\tm_nHoverOption = HOVEROPTION_NOT_HOVERING; \\\n\t\t\tbreak; \\\n\t\t} \\\n\t\tm_nHoverOption = increaseAction; \\\n\t\tif (m_nMousePosX < MENU_X_LEFT_ALIGNED(MENUSLIDER_X)) \\\n\t\t\tm_nHoverOption = HOVEROPTION_NOT_HOVERING; \\\n\t\t\\\n\t\tif (onlyWhenHoveringRow && (m_nMousePosY < MENU_Y(y) || m_nMousePosY > MENU_Y(MENUSLIDER_BIGGEST_BAR + y))) \\\n\t\t\tm_nHoverOption = HOVEROPTION_NOT_HOVERING; \\\n\t} while(0)\n\n// --- Functions not in the game/inlined starts\n\ninline void\nCMenuManager::ScrollUpListByOne() \n{\n\tif (m_nSelectedListRow == m_nFirstVisibleRowOnList) {\n\t\tif (m_nFirstVisibleRowOnList > 0) {\n\t\t\tm_nSelectedListRow--;\n\t\t\tm_nFirstVisibleRowOnList--;\n\t\t\tm_nScrollbarTopMargin -= SCROLLBAR_MAX_HEIGHT / m_nTotalListRow;\n\t\t}\n\t} else {\n\t\tm_nSelectedListRow--;\n\t}\n}\n\ninline void\nCMenuManager::ScrollDownListByOne()\n{\n\tif (m_nSelectedListRow == m_nFirstVisibleRowOnList + MAX_VISIBLE_OPTION_ON_SCREEN - 1) {\n\t\tif (m_nFirstVisibleRowOnList < m_nTotalListRow - MAX_VISIBLE_OPTION_ON_SCREEN) {\n\t\t\tm_nSelectedListRow++;\n\t\t\tm_nFirstVisibleRowOnList++;\n\t\t\tm_nScrollbarTopMargin += SCROLLBAR_MAX_HEIGHT / m_nTotalListRow;\n\t\t}\n\t} else {\n\t\tif (m_nSelectedListRow < m_nTotalListRow - 1) {\n\t\t\tm_nSelectedListRow++;\n\t\t}\n\t}\n}\n\ninline void\nCMenuManager::PageUpList(bool playSoundOnSuccess)\n{\n\tif (m_nTotalListRow > MAX_VISIBLE_OPTION_ON_SCREEN) {\n\t\tif (m_nFirstVisibleRowOnList > 0) {\n\t\t\tif(playSoundOnSuccess)\n\t\t\t\tDMAudio.PlayFrontEndSound(SOUND_FRONTEND_HIGHLIGHT_OPTION, 0);\n\n\t\t\tm_nFirstVisibleRowOnList = Max(0, m_nFirstVisibleRowOnList - MAX_VISIBLE_OPTION_ON_SCREEN);\n\t\t\tm_nSelectedListRow = Min(m_nSelectedListRow, m_nFirstVisibleRowOnList + MAX_VISIBLE_OPTION_ON_SCREEN - 1);\n\t\t} else {\n\t\t\tm_nFirstVisibleRowOnList = 0;\n\t\t\tm_nSelectedListRow = 0;\n\t\t}\n\t\tm_nScrollbarTopMargin = (SCROLLBAR_MAX_HEIGHT / m_nTotalListRow) * m_nFirstVisibleRowOnList;\n\t}\n}\n\ninline void\nCMenuManager::PageDownList(bool playSoundOnSuccess)\n{\n\tif (m_nTotalListRow > MAX_VISIBLE_OPTION_ON_SCREEN) {\n\t\tif (m_nFirstVisibleRowOnList < m_nTotalListRow - MAX_VISIBLE_OPTION_ON_SCREEN) {\n\t\t\tif(playSoundOnSuccess)\n\t\t\t\tDMAudio.PlayFrontEndSound(SOUND_FRONTEND_HIGHLIGHT_OPTION, 0);\n\n\t\t\tm_nFirstVisibleRowOnList = Min(m_nFirstVisibleRowOnList + MAX_VISIBLE_OPTION_ON_SCREEN, m_nTotalListRow - MAX_VISIBLE_OPTION_ON_SCREEN);\n\t\t\tm_nSelectedListRow = Max(m_nSelectedListRow, m_nFirstVisibleRowOnList);\n\t\t} else {\n\t\t\tm_nFirstVisibleRowOnList = m_nTotalListRow - MAX_VISIBLE_OPTION_ON_SCREEN;\n\t\t\tm_nSelectedListRow = m_nTotalListRow - 1;\n\t\t}\n\t\tm_nScrollbarTopMargin = (SCROLLBAR_MAX_HEIGHT / m_nTotalListRow) * m_nFirstVisibleRowOnList;\n\t}\n}\n\n#ifdef CUSTOM_FRONTEND_OPTIONS\n#define PLUS_LINE_HEIGHT_ON_SCREEN + (aScreens[m_nCurrScreen].layout ? aScreens[m_nCurrScreen].layout->lineHeight : MENU_DEFAULT_LINE_HEIGHT)\nbool ScreenHasOption(int screen, const char* gxtKey)\n{\n\tfor (int i = 0; i < NUM_MENUROWS; i++) {\n\t\tif (strcmp(gxtKey, aScreens[screen].m_aEntries[i].m_EntryName) == 0)\n\t\t\treturn true;\n\t}\n\treturn false;\n}\n\ninline void\nCMenuManager::ThingsToDoBeforeLeavingPage()\n{\n\tif ((m_nCurrScreen == MENUPAGE_SKIN_SELECT) && strcmp(m_aSkinName, m_PrefsSkinFile) != 0) {\n\t\tCWorld::Players[0].SetPlayerSkin(m_PrefsSkinFile);\n\n\t} else if (m_nCurrScreen == MENUPAGE_SOUND_SETTINGS) {\n\t\tif (m_nPrefsAudio3DProviderIndex != NO_AUDIO_PROVIDER)\n\t\t\tm_nPrefsAudio3DProviderIndex = DMAudio.GetCurrent3DProviderIndex();\n\n\t\tDMAudio.StopFrontEndTrack();\n\t\tOutputDebugString(\"FRONTEND AUDIO TRACK STOPPED\");\n\n\t} else if (ScreenHasOption(m_nCurrScreen, \"FED_RES\")) {\n\t\tm_nDisplayVideoMode = m_nPrefsVideoMode;\n\t}\n\n\tif (m_nCurrScreen == MENUPAGE_SKIN_SELECT) {\n\t\tCPlayerSkin::EndFrontendSkinEdit();\n\t}\n\n#ifdef SCROLLABLE_PAGES\n\tif (SCREEN_HAS_AUTO_SCROLLBAR) {\n\t\tm_nSelectedListRow = 0;\n\t\tm_nFirstVisibleRowOnList = 0;\n\t\tm_nScrollbarTopMargin = 0;\n\t}\n#endif\n\n\tCMenuScreenCustom::CMenuEntry &option = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption];\n\n\tif (option.m_Action == MENUACTION_CFO_DYNAMIC)\n\t\tif(option.m_CFODynamic->buttonPressFunc)\n\t\t\toption.m_CFODynamic->buttonPressFunc(FEOPTION_ACTION_FOCUSLOSS);\n\n\tif (option.m_Action == MENUACTION_CFO_SELECT && option.m_CFOSelect->onlyApplyOnEnter && option.m_CFOSelect->lastSavedValue != option.m_CFOSelect->displayedValue)\n\t\toption.m_CFOSelect->displayedValue = *option.m_CFO->value = option.m_CFOSelect->lastSavedValue;\n\n\tif (aScreens[m_nCurrScreen].returnPrevPageFunc) {\n\t\taScreens[m_nCurrScreen].returnPrevPageFunc();\n\t}\n}\n\ninline int8\nCMenuManager::GetPreviousPageOption()\n{\n\tint8 prevPage = !m_bGameNotLoaded ? aScreens[m_nCurrScreen].m_PreviousPage :\n\t\t(m_nCurrScreen == MENUPAGE_NEW_GAME || m_nCurrScreen == MENUPAGE_OPTIONS || m_nCurrScreen == MENUPAGE_EXIT ? MENUPAGE_START_MENU : aScreens[m_nCurrScreen].m_PreviousPage);\n\n\tif (prevPage == -1) // Game also does same\n\t\treturn 0;\n\n\tprevPage = prevPage == MENUPAGE_NONE ? (!m_bGameNotLoaded ? MENUPAGE_PAUSE_MENU : MENUPAGE_START_MENU) : prevPage;\n\n\tfor (int i = 0; i < NUM_MENUROWS; i++) {\n\t\tif (aScreens[prevPage].m_aEntries[i].m_Action >= MENUACTION_NOTHING) { // CFO check\n\t\t\tif (aScreens[prevPage].m_aEntries[i].m_TargetMenu == m_nCurrScreen) {\n\t\t\t\treturn i;\n\t\t\t}\n\t\t}\n\t}\n\t\n\t// This shouldn't happen\n\treturn 0;\n}\n\n#else\n#define PLUS_LINE_HEIGHT_ON_SCREEN + MENU_DEFAULT_LINE_HEIGHT\ninline void\nCMenuManager::ThingsToDoBeforeLeavingPage()\n{\n\tswitch (m_nCurrScreen) {\n\t\tcase MENUPAGE_SOUND_SETTINGS:\n\t\t\tif (m_nPrefsAudio3DProviderIndex != NO_AUDIO_PROVIDER)\n\t\t\t\tm_nPrefsAudio3DProviderIndex = DMAudio.GetCurrent3DProviderIndex();\n\n\t\t\tDMAudio.StopFrontEndTrack();\n\t\t\tOutputDebugString(\"FRONTEND AUDIO TRACK STOPPED\");\n\t\t\tbreak;\n\t\tcase MENUPAGE_DISPLAY_SETTINGS:\n\t\t\tm_nDisplayVideoMode = m_nPrefsVideoMode;\n\t\t\tbreak;\n\t\tcase MENUPAGE_SKIN_SELECT:\n\t\t\tif (strcmp(m_aSkinName, m_PrefsSkinFile) != 0)\n\t\t\t\tCWorld::Players[0].SetPlayerSkin(m_PrefsSkinFile);\n\n\t\t\tCPlayerSkin::EndFrontendSkinEdit();\n\t\t\tbreak;\n\t}\n\n#ifdef SCROLLABLE_PAGES\n\tif (SCREEN_HAS_AUTO_SCROLLBAR) {\n\t\tm_nSelectedListRow = 0;\n\t\tm_nFirstVisibleRowOnList = 0;\n\t\tm_nScrollbarTopMargin = 0;\n\t}\n#endif\n}\n\ninline int8\nCMenuManager::GetPreviousPageOption()\n{\n\treturn (!m_bGameNotLoaded ? aScreens[m_nCurrScreen].m_ParentEntry :\n\t\t(m_nCurrScreen == MENUPAGE_NEW_GAME ? 0 : (m_nCurrScreen == MENUPAGE_OPTIONS ? 1 : (m_nCurrScreen == MENUPAGE_EXIT ? 2 : aScreens[m_nCurrScreen].m_ParentEntry))));\n}\n#endif\n\n// ------ Functions not in the game/inlined ends\n\nbool DoRWStuffStartOfFrame(int16 TopRed, int16 TopGreen, int16 TopBlue, int16 BottomRed, int16 BottomGreen, int16 BottomBlue, int16 Alpha);\nvoid DoRWStuffEndOfFrame(void);\n\nvoid\nCMenuManager::SwitchToNewScreen(int8 screen)\n{\n\tbMenuChangeOngoing = true;\n\tDoRWStuffStartOfFrame(0, 0, 0, 0, 0, 0, 255);\n\tDrawBackground(true);\n\tDoRWStuffEndOfFrame();\n\tDoRWStuffStartOfFrame(0, 0, 0, 0, 0, 0, 255);\n\tDrawBackground(true);\n\tDoRWStuffEndOfFrame();\n\tm_nPrevScreen = m_nCurrScreen;\n\tm_ShowEmptyBindingError = false;\n\tResetHelperText();\n\n\tThingsToDoBeforeLeavingPage();\n\n\tif (screen == -2) {\n\t\tint oldScreen = aScreens[m_nCurrScreen].m_PreviousPage;\n\t\tint oldOption = GetPreviousPageOption();\n\n\t\tm_nCurrOption = oldOption;\n\t\tm_nCurrScreen = oldScreen;\n\t} else if (screen == 0) {\n\t\tm_nCurrScreen = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu;\n\t\tm_nCurrOption = 0;\n\t} else {\n\t\tm_nCurrOption = 0;\n\t\tm_nCurrScreen = screen;\n\t}\n\tSETUP_SCROLLING(m_nCurrScreen)\n\t\n\tif (hasNativeList(m_nPrevScreen))\n\t\tm_nTotalListRow = 0;\n\n\tif (m_nCurrScreen == MENUPAGE_CHOOSE_SAVE_SLOT)\n\t\tm_nCurrOption = 8;\n\tm_nMenuFadeAlpha = 0;\n\tm_nOptionHighlightTransitionBlend = 0;\n\tm_LastScreenSwitch = CTimer::GetTimeInMillisecondsPauseMode();\n}\n\nCMenuManager::CMenuManager()\n{\n\tm_StatsScrollSpeed = 150.0f;\n\tm_StatsScrollDirection = 1;\n\tm_PrefsSfxVolume = 49;\n\tm_PrefsMusicVolume = 49;\n\tm_PrefsRadioStation = 0;\n\tm_PrefsStereoMono = 1;\n\tm_PrefsBrightness = 256;\n\tm_PrefsLOD = CRenderer::ms_lodDistScale;\n\tm_KeyPressedCode = -1;\n\tm_bFrontEnd_ReloadObrTxtGxt = false;\n\tm_PrefsMP3BoostVolume = 0;\n\tm_PrefsShowSubtitles = 0;\n\tm_PrefsShowLegends = 1;\n#ifdef ASPECT_RATIO_SCALE\n\tm_PrefsUseWideScreen = AR_AUTO;\n#else\n\tm_PrefsUseWideScreen = 0;\n#endif\n\tm_PrefsVsync = 0;\n\tm_PrefsVsyncDisp = 1;\n\tm_PrefsFrameLimiter = 1;\n\tm_PrefsLanguage = 0;\n\tfield_54 = 0;\n\tm_PrefsAllowNastyGame = 1;\n\tm_PrefsSpeakers = 0;\n\tfield_8 = 0;\n\tm_PrefsUseVibration = 0;\n\tm_PrefsShowHud = 1;\n\tm_PrefsRadarMode = 0;\n\tm_DisplayControllerOnFoot = false;\n\tm_bShutDownFrontEndRequested = false;\n\tm_bStartUpFrontEndRequested = false;\n\tpEditString = nil;\n\tpControlEdit = nil;\n\tDisplayComboButtonErrMsg = false;\n\tm_PrefsDMA = 1;\n\tOS_Language = LANG_ENGLISH;\n\tm_ControlMethod = CONTROL_STANDARD;\n#ifdef PC_PLAYER_CONTROLS\n\tCCamera::m_bUseMouse3rdPerson = true;\n#else\n\tCCamera::m_bUseMouse3rdPerson = false;\n#endif\n\tm_lastWorking3DAudioProvider = 0;\n\tm_nFirstVisibleRowOnList = 0;\n\tm_nScrollbarTopMargin = 0.0f;\n\tm_nSelectedListRow = 0;\n\tm_nSkinsTotal = 0;\n\tm_nPrefsAudio3DProviderIndex = AUDIO_PROVIDER_NOT_DETERMINED;\n\tm_bGameNotLoaded = true;\n\tm_nMousePosX = m_nMouseTempPosX;\n\tm_nMousePosY = m_nMouseTempPosY;\n\tm_nMouseOldPosX = m_nMousePosX;\n\tm_nMouseOldPosY = m_nMousePosY;\n\tm_bShowMouse = true;\n\tm_nHoverOption = HOVEROPTION_NOT_HOVERING;\n\n\tDMAudio.SetMP3BoostVolume(m_PrefsMP3BoostVolume);\n\tm_bMenuActive = false;\n\tm_bActivateSaveMenu = false;\n\tm_bWantToLoad = false;\n\tm_nMenuFadeAlpha = 0;\n\tm_OnlySaveMenu = false;\n\tm_fMapSize = MENU_Y(162.0f); // Y because of HOR+\n\tm_fMapCenterX = MENU_X_LEFT_ALIGNED(320.0f);\n\tm_fMapCenterY = MENU_Y(225.0f);\n\tDMAudio.SetMusicMasterVolume(m_PrefsMusicVolume);\n\tDMAudio.SetEffectsMasterVolume(m_PrefsSfxVolume);\n\n#ifdef NO_ISLAND_LOADING\n\tm_PrefsIslandLoading = ISLAND_LOADING_LOW;\n#endif\n\n#ifdef GAMEPAD_MENU\n\tm_PrefsControllerType = CONTROLLER_XBOXONE;\n#endif\n}\n\nvoid\nCMenuManager::SetFrontEndRenderStates(void)\n{\n\tRwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR);\n\tRwRenderStateSet(rwRENDERSTATETEXTUREADDRESS, (void*)rwTEXTUREADDRESSCLAMP);\n\tRwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE);\n\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);\n\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);\n\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);\n\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);\n}\n\nvoid\nCMenuManager::Initialise(void)\n{\n\tDoRWStuffStartOfFrame(0, 0, 0, 0, 0, 0, 255);\n\tDoRWStuffEndOfFrame();\n\tm_AllowNavigation = false;\n\tm_firstStartCounter = -50; // to start from black\n\tm_nMenuFadeAlpha = 0;\n\tm_nCurrOption = 0;\n\tm_nOptionHighlightTransitionBlend = 0;\n\tCentreMousePointer();\n\tm_bShowMouse = true;\n\tm_fMapSize = MENU_Y(162.0f); // Y because of HOR+\n\tm_fMapCenterX = MENU_X_LEFT_ALIGNED(320.0f);\n\tm_fMapCenterY = MENU_Y(225.0f);\n\tCPad::StopPadsShaking();\n\tif (!m_OnlySaveMenu)\n\t\tm_nCurrScreen = MENUPAGE_NONE;\n\tDMAudio.ChangeMusicMode(MUSICMODE_FRONTEND);\n\tDMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_STARTING, 0);\n\tDMAudio.Service();\n\tDMAudio.SetMusicMasterVolume(m_PrefsMusicVolume);\n\tDMAudio.SetEffectsMasterVolume(m_PrefsSfxVolume);\n#ifdef FIX_BUGS\n\tstatic bool firstTime = true;\n\tif (firstTime) {\n\t\tDMAudio.SetRadioInCar(m_PrefsRadioStation);\n\t\tfirstTime = false;\n\t} else\n#endif\n\tm_PrefsRadioStation = DMAudio.GetRadioInCar();\n\n\tDMAudio.SetMP3BoostVolume(m_PrefsMP3BoostVolume);\n\tif (DMAudio.IsMP3RadioChannelAvailable()) {\n\t\tif (m_PrefsRadioStation < WILDSTYLE || m_PrefsRadioStation > USERTRACK)\n\t\t\tm_PrefsRadioStation = CGeneral::GetRandomNumber() % (USERTRACK + 1);\n\t} else if (m_PrefsRadioStation < WILDSTYLE || m_PrefsRadioStation > WAVE)\n\t\tm_PrefsRadioStation = CGeneral::GetRandomNumber() % (WAVE + 1);\n\n\tCFileMgr::SetDir(\"\");\n\t//CFileMgr::SetDir(\"\");\n\tPcSaveHelper.PopulateSlotInfo();\n\tCTimer::StartUserPause();\n}\n\nvoid\nCMenuManager::CentreMousePointer()\n{\n\tif (SCREEN_WIDTH * 0.5f != 0.0f && 0.0f != SCREEN_HEIGHT * 0.5f) {\n#if defined RW_D3D9 || defined RWLIBS\n\t\ttagPOINT Point;\n\t\tPoint.x = SCREEN_WIDTH / 2;\n\t\tPoint.y = SCREEN_HEIGHT / 2;\n\t\tClientToScreen(PSGLOBAL(window), &Point);\n\t\tSetCursorPos(Point.x, Point.y);\n#elif defined RW_GL3\n\t\tglfwSetCursorPos(PSGLOBAL(window), SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2);\n#endif\n\n\t\tPSGLOBAL(lastMousePos.x) = SCREEN_WIDTH / 2;\n\t\tPSGLOBAL(lastMousePos.y) = SCREEN_HEIGHT / 2;\n\t}\n}\n\nvoid\nCMenuManager::CheckCodesForControls(int typeOfControl)\n{\n\tDisplayComboButtonErrMsg = false;\n\tbool invalidKey = false;\n\tbool escPressed = false;\n\teControllerType typeToSave;\n\t// GetStartOptionsCntrlConfigScreens();\n\te_ControllerAction action = (e_ControllerAction) m_CurrCntrlAction;\n\n\tif (typeOfControl == KEYBOARD) {\n\t\tif (*pControlEdit == rsESC) {\n\t\t\tescPressed = true;\n\t\t} else if (*pControlEdit != rsF1 && *pControlEdit != rsF2 && *pControlEdit != rsF3 && *pControlEdit != rsF9 &&\n\t\t\t*pControlEdit != rsLWIN && *pControlEdit != rsRWIN && *pControlEdit != rsRALT) {\n\t\t\ttypeToSave = KEYBOARD;\n\t\t\tif (ControlsManager.GetControllerKeyAssociatedWithAction(action, KEYBOARD) != rsNULL &&\n\t\t\t\t*pControlEdit != ControlsManager.GetControllerKeyAssociatedWithAction(action, KEYBOARD)) {\n\t\t\t\ttypeToSave = OPTIONAL_EXTRA;\n\t\t\t}\n\t\t} else {\n\t\t\tinvalidKey = true;\n\t\t}\n\t} else if (typeOfControl == MOUSE) {\n\t\ttypeToSave = MOUSE;\n\t} else if (typeOfControl == JOYSTICK) {\n\t\ttypeToSave = JOYSTICK;\n\t\tif (ControlsManager.GetIsActionAButtonCombo(action))\n\t\t\tDisplayComboButtonErrMsg = true;\n\t}\n\n#ifdef FIX_BUGS\n\tif(!escPressed && !invalidKey)\n#endif\n\t\tControlsManager.ClearSettingsAssociatedWithAction(action, typeToSave);\n\n\tif (!DisplayComboButtonErrMsg && !escPressed && !invalidKey) {\n\t\tif (typeOfControl == KEYBOARD) {\n\t\t\tControlsManager.DeleteMatchingActionInitiators(action, *pControlEdit, KEYBOARD);\n\t\t\tControlsManager.DeleteMatchingActionInitiators(action, *pControlEdit, OPTIONAL_EXTRA);\n\t\t} else if (typeOfControl == MOUSE) {\n\t\t\tControlsManager.DeleteMatchingActionInitiators(action, MouseButtonJustClicked, MOUSE);\n\t\t} else if (typeOfControl == JOYSTICK) {\n\t\t\tControlsManager.DeleteMatchingActionInitiators(action, JoyButtonJustClicked, JOYSTICK);\n\t\t}\n\n\t\tif (typeOfControl == KEYBOARD) {\n\t\t\tControlsManager.SetControllerKeyAssociatedWithAction(action, *pControlEdit, typeToSave);\n\t\t} else if (typeOfControl == MOUSE) {\n\t\t\tControlsManager.SetControllerKeyAssociatedWithAction(action, MouseButtonJustClicked, typeToSave);\n\t\t} else if (typeOfControl == JOYSTICK) {\n\t\t\tControlsManager.SetControllerKeyAssociatedWithAction(action, JoyButtonJustClicked, typeToSave);\n\t\t}\n\t\tpControlEdit = nil;\n\t\tm_bWaitingForNewKeyBind = false;\n\t\tm_KeyPressedCode = -1;\n\t\tm_bStartWaitingForKeyBind = false;\n#ifdef LOAD_INI_SETTINGS\n\t\tSaveINIControllerSettings();\n#else\n\t\tSaveSettings();\n#endif\n\t}\n}\n\nbool\nCMenuManager::CheckHover(int x1, int x2, int y1, int y2)\n{\n\treturn m_nMousePosX > x1 && m_nMousePosX < x2 &&\n\t       m_nMousePosY > y1 && m_nMousePosY < y2;\n}\n\nvoid\nCMenuManager::CheckSliderMovement(int value)\n{\n\tswitch (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action) {\n\tcase MENUACTION_BRIGHTNESS:\n\t\tm_PrefsBrightness += value * 24.19f;\n\t\tm_PrefsBrightness = clamp(m_PrefsBrightness, 0, 384);\n\t\tbreak;\n\tcase MENUACTION_DRAWDIST:\n\t\tif(value > 0)\n\t\t\tm_PrefsLOD += ((1.8f - 0.925f) / 16.0f);\n\t\telse\n\t\t\tm_PrefsLOD -= ((1.8f - 0.925f) / 16.0f);\n\t\tm_PrefsLOD = clamp(m_PrefsLOD, 0.925f, 1.8f);\n\t\tCRenderer::ms_lodDistScale = m_PrefsLOD;\n\t\tbreak;\n\tcase MENUACTION_MUSICVOLUME:\n\t\tif (m_nPrefsAudio3DProviderIndex != NO_AUDIO_PROVIDER) {\n\t\t\tm_PrefsMusicVolume += value * (128 / 32);\n\t\t\tm_PrefsMusicVolume = clamp(m_PrefsMusicVolume, 0, 65);\n\t\t\tDMAudio.SetMusicMasterVolume(m_PrefsMusicVolume);\n\t\t}\n\t\tbreak;\n\tcase MENUACTION_SFXVOLUME:\n\t\tif (m_nPrefsAudio3DProviderIndex != NO_AUDIO_PROVIDER) {\n\t\t\tm_PrefsSfxVolume += value * (128 / 32);\n\t\t\tm_PrefsSfxVolume = clamp(m_PrefsSfxVolume, 0, 65);\n\t\t\tDMAudio.SetEffectsMasterVolume(m_PrefsSfxVolume);\n\t\t}\n\t\tbreak;\n\tcase MENUACTION_MP3VOLUMEBOOST:\n\t\tif (m_nPrefsAudio3DProviderIndex != NO_AUDIO_PROVIDER) {\n\t\t\tif (DMAudio.IsMP3RadioChannelAvailable()) {\n\t\t\t\tm_PrefsMP3BoostVolume += value * (128 / 32);\n\t\t\t\tm_PrefsMP3BoostVolume = clamp(m_PrefsMP3BoostVolume, 0, 65);\n\t\t\t\tDMAudio.SetMP3BoostVolume(m_PrefsMP3BoostVolume);\n\t\t\t}\n\t\t}\n\t\tbreak;\n\tcase MENUACTION_MOUSESENS:\n\t\tTheCamera.m_fMouseAccelHorzntl += value * 1.0f/200.0f/15.0f;\t// ???\n\t\tTheCamera.m_fMouseAccelHorzntl = clamp(TheCamera.m_fMouseAccelHorzntl, 1.0f/3200.0f, 1.0f/200.0f);\n#ifdef FIX_BUGS\n\t\tTheCamera.m_fMouseAccelVertical = TheCamera.m_fMouseAccelHorzntl + 0.0005f;\n#endif\n\t\tbreak;\n\tdefault:\n\t\treturn;\n\t}\n\tSaveSettings();\n}\n\nvoid\nCMenuManager::DisplayHelperText(char *text)\n{\n\tif (m_nMenuFadeAlpha != 255)\n\t\treturn;\n\n\t// there was a unused static bool\n\tstatic PauseModeTime LastFlash = 0;\n\tint32 alpha = 255;\n\n\tCFont::SetRightJustifyOn();\n\tCFont::SetScale(SCREEN_SCALE_X(SMALLESTTEXT_X_SCALE), SCREEN_SCALE_Y(SMALLESTTEXT_Y_SCALE));\n\tCFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD));\n\tCFont::SetDropShadowPosition(0);\n\n\t// We're using SCREEN_STRETCH_FROM_RIGHT, because we also stretch black borders\n\tif (text) {\n\t\tCFont::SetColor(CRGBA(255, 255, 255, 255));\n\t\tCFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(HELPER_TEXT_RIGHT_MARGIN), SCREEN_SCALE_FROM_BOTTOM(HELPER_TEXT_BOTTOM_MARGIN), TheText.Get(text));\n\t\treturn;\n\t}\n\n\tif (m_nHelperTextMsgId != 0 && m_nHelperTextMsgId != 1) {\n\t\tif (CTimer::GetTimeInMillisecondsPauseMode() - LastFlash > 10) {\n\t\t\tLastFlash = CTimer::GetTimeInMillisecondsPauseMode();\n\t\t\tm_nHelperTextAlpha -= 2;\n\t\t}\n\n\t\tif (m_nHelperTextAlpha < 1)\n\t\t\tResetHelperText();\n\n\t\talpha = m_nHelperTextAlpha > 255 ? 255 : m_nHelperTextAlpha;\n\t}\n\n\tCFont::SetColor(CRGBA(255, 255, 255, alpha));\n\t// TODO: name this cases?\n\tswitch (m_nHelperTextMsgId) {\n\t\tcase 1:\n\t\t\tCFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(HELPER_TEXT_RIGHT_MARGIN), SCREEN_SCALE_FROM_BOTTOM(HELPER_TEXT_BOTTOM_MARGIN), TheText.Get(\"FET_APP\"));\n\t\t\tbreak;\n\t\tcase 2:\n\t\t\tCFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(HELPER_TEXT_RIGHT_MARGIN), SCREEN_SCALE_FROM_BOTTOM(HELPER_TEXT_BOTTOM_MARGIN), TheText.Get(\"FET_HRD\"));\n\t\t\tbreak;\n\t\tcase 3:\n\t\t\tCFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(HELPER_TEXT_RIGHT_MARGIN), SCREEN_SCALE_FROM_BOTTOM(HELPER_TEXT_BOTTOM_MARGIN), TheText.Get(\"FET_RSO\"));\n\t\t\tbreak;\n\t\tcase 4:\n\t\t\tCFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(HELPER_TEXT_RIGHT_MARGIN), SCREEN_SCALE_FROM_BOTTOM(HELPER_TEXT_BOTTOM_MARGIN), TheText.Get(\"FET_STS\"));\n\t\t\tbreak;\n\t\tcase 5:\n\t\t\tCFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(HELPER_TEXT_RIGHT_MARGIN), SCREEN_SCALE_FROM_BOTTOM(HELPER_TEXT_BOTTOM_MARGIN), TheText.Get(\"FET_RSC\"));\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tif (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action == MENUACTION_NO)\n\t\t\t\treturn;\n\n\t\t\tif (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action == MENUACTION_MUSICVOLUME ||\n\t\t\t\taScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action == MENUACTION_SFXVOLUME) {\n\n\t\t\t\tCFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(HELPER_TEXT_RIGHT_MARGIN), SCREEN_SCALE_FROM_BOTTOM(HELPER_TEXT_BOTTOM_MARGIN),\n\t\t\t\t\tm_nPrefsAudio3DProviderIndex == NO_AUDIO_PROVIDER ? TheText.Get(\"FEH_NA\") : TheText.Get(\"FET_MIG\"));\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action == MENUACTION_KEYBOARDCTRLS)\n\t\t\t\treturn;\n\n\t\t\tif (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action == MENUACTION_SCREENRES) {\n\t\t\t\tCFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(HELPER_TEXT_RIGHT_MARGIN), SCREEN_SCALE_FROM_BOTTOM(HELPER_TEXT_BOTTOM_MARGIN),\n\t\t\t\t\tm_bGameNotLoaded ? TheText.Get(\"FET_MIG\") : TheText.Get(\"FEH_NA\"));\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action == MENUACTION_AUDIOHW ||\n\t\t\t\taScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action == MENUACTION_SPEAKERCONF) {\n\n\t\t\t\tCFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(HELPER_TEXT_RIGHT_MARGIN), SCREEN_SCALE_FROM_BOTTOM(HELPER_TEXT_BOTTOM_MARGIN),\n\t\t\t\t\tm_nPrefsAudio3DProviderIndex == NO_AUDIO_PROVIDER ? TheText.Get(\"FEH_NA\") : TheText.Get(\"FET_MIG\"));\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action == MENUACTION_RESTOREDEF)\n\t\t\t\treturn;\n\n\t\t\tif (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action == MENUACTION_MP3VOLUMEBOOST) {\n\t\t\t\tCFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(HELPER_TEXT_RIGHT_MARGIN), SCREEN_SCALE_FROM_BOTTOM(HELPER_TEXT_BOTTOM_MARGIN),\n\t\t\t\t\tm_nPrefsAudio3DProviderIndex == NO_AUDIO_PROVIDER ? TheText.Get(\"FEH_NA\") : TheText.Get(\"FET_MIG\"));\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tCFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(HELPER_TEXT_RIGHT_MARGIN), SCREEN_SCALE_FROM_BOTTOM(HELPER_TEXT_BOTTOM_MARGIN),\n\t\t\t\tm_nCurrScreen != MENUPAGE_STATS ? TheText.Get(\"FET_MIG\") : TheText.Get(\"FEH_SSA\"));\n\n\t\t\tbreak;\n\t}\n}\n\nint\nCMenuManager::DisplaySlider(float x, float y, float mostLeftBarSize, float mostRightBarSize, float rectSize, float progress, float spacing) \n{\n\tCRGBA color;\n\tfloat maxBarHeight;\n\n\tint lastActiveBarX = 0;\n\tfloat curBarX = 0.0f;\n\tfor (int i = 0; i < 16; i++) {\n\t\tcurBarX = i * rectSize/16.0f + x;\n\n\t\tif (i / 16.0f + 1 / 32.0f < progress) {\n\t\t\tcolor = CRGBA(SLIDERON_COLOR.r, SLIDERON_COLOR.g, SLIDERON_COLOR.b, FadeIn(255));\n\t\t\tlastActiveBarX = curBarX;\n\t\t} else\n\t\t\tcolor = CRGBA(SLIDEROFF_COLOR.r, SLIDEROFF_COLOR.g, SLIDEROFF_COLOR.b, FadeIn(255));\n\n\t\tmaxBarHeight = Max(mostLeftBarSize, mostRightBarSize);\n\n\t\tfloat curBarFreeSpace = ((16 - i) * mostLeftBarSize + i * mostRightBarSize) / 16.0f;\n\t\tfloat left = curBarX;\n\t\tfloat top = y + maxBarHeight - curBarFreeSpace;\n\t\tfloat right = spacing + curBarX;\n\t\tfloat bottom = y + maxBarHeight;\n\t\tfloat shadowOffset = SCREEN_SCALE_X(2.0f);\n\t\tCSprite2d::DrawRect(CRect(left + shadowOffset, top + shadowOffset, right + shadowOffset, bottom + shadowOffset), CRGBA(0, 0, 0, FadeIn(200))); // Shadow\n\t\tCSprite2d::DrawRect(CRect(left, top, right, bottom), color);\n\t}\n\treturn lastActiveBarX;\n}\n\nvoid\nCMenuManager::DoSettingsBeforeStartingAGame()\n{\n#ifdef LEGACY_MENU_OPTIONS\n\tif (m_PrefsVsyncDisp != m_PrefsVsync)\n\t\tm_PrefsVsync = m_PrefsVsyncDisp;\n#endif\n\tDMAudio.DestroyAllGameCreatedEntities();\n\tDMAudio.Service();\n\tm_bShutDownFrontEndRequested = true;\n\tm_bWantToRestart = true;\n\tDMAudio.SetEffectsFadeVol(0);\n\tDMAudio.SetMusicFadeVol(0);\n\tfor (int i = 0; i < NUM_RADIOS; i++)\n\t\tCStats::FavoriteRadioStationList[i] = 0.0f;\n\n\tSwitchMenuOnAndOff();\n\tDMAudio.ResetTimers(CTimer::GetTimeInMilliseconds());\n}\n\nvoid\nCMenuManager::DrawStandardMenus(bool activeScreen)\n{\n\tfloat nextYToUse = 0.0f; // III leftover, set but unused in VC\n\tbool itemsAreSelectable = true;\n\tCFont::SetBackgroundOff();\n\tCFont::SetPropOn();\n\tCFont::SetCentreOff();\n\tCFont::SetJustifyOn();\n\tCFont::SetBackGroundOnlyTextOff();\n\n#ifdef CUSTOM_FRONTEND_OPTIONS\n\tconst int xMargin = aScreens[m_nCurrScreen].layout && aScreens[m_nCurrScreen].layout->xMargin != 0 ? aScreens[m_nCurrScreen].layout->xMargin : MENU_X_MARGIN;\n#else\n\tconst int xMargin = MENU_X_MARGIN;\n#endif\n\n\tCFont::SetWrapx(MENU_X_RIGHT_ALIGNED(xMargin));\n\tCFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(xMargin));\n#ifdef ASPECT_RATIO_SCALE\n\tCFont::SetCentreSize(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH));\n#else\n\tCFont::SetCentreSize(SCREEN_WIDTH);\n#endif\n\n\tswitch (m_nCurrScreen) {\n\t\tcase MENUPAGE_CHOOSE_LOAD_SLOT:\n\t\tcase MENUPAGE_CHOOSE_DELETE_SLOT:\n\t\tcase MENUPAGE_CHOOSE_SAVE_SLOT:\n\t\t\tCSprite2d::Draw2DPolygon(MENU_X_LEFT_ALIGNED(38.0f), MENU_Y(85.0f),\n\t\t\t\tMENU_X_LEFT_ALIGNED(615.0f), MENU_Y(75.0f),\n\t\t\t\tMENU_X_LEFT_ALIGNED(30.0f), MENU_Y(320.0f), \n\t\t\t\tMENU_X_LEFT_ALIGNED(605.0f), MENU_Y(330.0f), CRGBA(LIST_BACKGROUND_COLOR.r, LIST_BACKGROUND_COLOR.g, LIST_BACKGROUND_COLOR.b, FadeIn(LIST_BACKGROUND_COLOR.a)));\n\t\t\tbreak;\n\t\tcase MENUPAGE_SOUND_SETTINGS:\n\t\t\tPrintRadioSelector();\n\t\t\tbreak;\n\t\tcase MENUPAGE_STATS:\n\t\t\tPrintStats();\n\t\t\tbreak;\n\t\tcase MENUPAGE_BRIEFS:\n\t\t\tPrintBriefs();\n\t\t\tbreak;\n\t}\n\n\t// Page name\n\tif (aScreens[m_nCurrScreen].m_ScreenName[0] != '\\0') {\n\n\t\tSET_FONT_FOR_MENU_HEADER\n\t\tCFont::SetColor(CRGBA(30, 30, 30, FadeIn(255)));\n\t\tCFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(MENUHEADER_POS_X) - MENU_X(7.f), SCREEN_SCALE_Y(MENUHEADER_POS_Y + 7.f), TheText.Get(aScreens[m_nCurrScreen].m_ScreenName));\n\n\t\tCFont::SetColor(CRGBA(HEADER_COLOR.r, HEADER_COLOR.g, HEADER_COLOR.b, FadeIn(255)));\n\t\tCFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(MENUHEADER_POS_X), SCREEN_SCALE_Y(MENUHEADER_POS_Y), TheText.Get(aScreens[m_nCurrScreen].m_ScreenName));\n\t}\n\n\t// Label\n\twchar *str;\n\tif (aScreens[m_nCurrScreen].m_aEntries[0].m_Action == MENUACTION_LABEL) {\n\t\tCFont::SetWrapx(MENU_X_RIGHT_ALIGNED(MENULABEL_X_MARGIN));\n\t\tCFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(MENULABEL_X_MARGIN));\n\t\tCFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD));\n\t\tCFont::SetScale(MENU_X(BIGTEXT2_X_SCALE), MENU_Y(BIGTEXT2_Y_SCALE));\n\t\tCFont::SetRightJustifyOff();\n\t\tCFont::SetDropShadowPosition(2);\n\t\tCFont::SetDropColor(CRGBA(0, 0, 0, FadeIn(255)));\n\t\tCFont::SetColor(CRGBA(LABEL_COLOR.r, LABEL_COLOR.g, LABEL_COLOR.b, FadeIn(255)));\n\n\t\tswitch (m_nCurrScreen) {\n\t\tcase MENUPAGE_LOAD_SLOT_CONFIRM:\n\t\t\tif (m_bGameNotLoaded)\n\t\t\t\tstr = TheText.Get(\"FES_LCG\");\n\t\t\telse\n\t\t\t\tstr = TheText.Get(aScreens[m_nCurrScreen].m_aEntries[0].m_EntryName);\n\t\t\tbreak;\n\t\tcase MENUPAGE_DELETE_SLOT_CONFIRM:\n\t\t\tstr = TheText.Get(aScreens[MENUPAGE_DELETE_SLOT_CONFIRM].m_aEntries[0].m_EntryName);\n\t\t\tbreak;\n\t\tcase MENUPAGE_SAVE_OVERWRITE_CONFIRM:\n\t\t\tif (Slots[m_nCurrSaveSlot] == SLOT_OK)\n\t\t\t\tstr = TheText.Get(\"FESZ_QO\");\n\t\t\telse if (Slots[m_nCurrSaveSlot] == SLOT_CORRUPTED)\n\t\t\t\tstr = TheText.Get(\"FESZ_QZ\");\n\t\t\telse\n\t\t\t\tstr = TheText.Get(aScreens[m_nCurrScreen].m_aEntries[0].m_EntryName);\n\t\t\tbreak;\n\t\tcase MENUPAGE_EXIT:\n\t\t\tif (m_bGameNotLoaded)\n\t\t\t\tstr = TheText.Get(\"FEQ_SRW\");\n\t\t\telse\n\t\t\t\tstr = TheText.Get(aScreens[m_nCurrScreen].m_aEntries[0].m_EntryName);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tstr = TheText.Get(aScreens[m_nCurrScreen].m_aEntries[0].m_EntryName);\n\t\t\tbreak;\n\t\t}\n\n\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(100.0f), MENU_Y(97.0f), str);\n\t\tCFont::SetWrapx(MENU_X_RIGHT_ALIGNED(xMargin));\n\t\tCFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(xMargin));\n\t}\n\n\tif (m_nCurrScreen == MENUPAGE_KEYBOARD_CONTROLS) {\n\t\tif (m_bWaitingForNewKeyBind)\n\t\t\titemsAreSelectable = false;\n\n\t\tDrawControllerScreenExtraText(-8.0f, MENU_X_LEFT_ALIGNED(350), MENU_DEFAULT_LINE_HEIGHT);\n\t}\n\n\twchar unicodeTemp[64];\n#ifdef ASPECT_RATIO_SCALE\n\tchar asciiTemp[32];\n#endif\n\n\tbool weHaveLabel = aScreens[m_nCurrScreen].m_aEntries[0].m_Action == MENUACTION_LABEL;\n\tuint8 section = 0; // 0: highlight trapezoid  1: texts\n\n\twhile (section < 2) {\n#endif\n\n#ifdef SCROLLABLE_PAGES\n\t\tint firstOption = SCREEN_HAS_AUTO_SCROLLBAR ? m_nFirstVisibleRowOnList : 0;\n\t\tint scrollOffset = aScreens[m_nCurrScreen].m_aEntries[firstOption].m_Y - aScreens[m_nCurrScreen].m_aEntries[0].m_Y;\n\t\tfor (int i = firstOption; i < firstOption + MAX_VISIBLE_OPTION && i < NUM_MENUROWS; ++i) {\n#else\n\t\tfor (int i = 0; i < NUM_MENUROWS; ++i) {\n#endif\n\t\t\twchar* rightText = nil;\n\t\t\twchar* leftText;\n\t\t\tif (aScreens[m_nCurrScreen].m_aEntries[i].m_SaveSlot >= SAVESLOT_1 && aScreens[m_nCurrScreen].m_aEntries[i].m_SaveSlot <= SAVESLOT_8) {\n\t\t\t\tCFont::SetColor(CRGBA(0, 0, 0, FadeIn(255)));\n\t\t\t\tCFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD));\n\t\t\t\tCFont::SetScale(MENU_X(MEDIUMTEXT_X_SCALE), MENU_Y(MEDIUMTEXT_Y_SCALE));\n\t\t\t\tCFont::SetDropShadowPosition(0);\n\t\t\t} else {\n\t\t\t\tCFont::SetFontStyle(FONT_LOCALE(FONT_HEADING));\n\t\t\t\tCFont::SetScale(MENU_X(BIGTEXT_X_SCALE), MENU_Y(BIGTEXT_Y_SCALE));\n\t\t\t\tCFont::SetDropShadowPosition(2);\n\t\t\t\tCFont::SetDropColor(CRGBA(0, 0, 0, FadeIn(255)));\n\t\t\t\tCFont::SetColor(CRGBA(MENUOPTION_COLOR.r, MENUOPTION_COLOR.g, MENUOPTION_COLOR.b, FadeIn(255)));\n\t\t\t}\n\t\t\tif (aScreens[m_nCurrScreen].m_aEntries[i].m_Align == MENUALIGN_LEFT) {\n\t\t\t\tCFont::SetCentreOff();\n\t\t\t\tCFont::SetRightJustifyOff();\n\t\t\t} else if (aScreens[m_nCurrScreen].m_aEntries[i].m_Align == MENUALIGN_RIGHT) {\n\t\t\t\tCFont::SetCentreOff();\n\t\t\t\tCFont::SetRightJustifyOn();\n\t\t\t} else {\n\t\t\t\tCFont::SetRightJustifyOff();\n\t\t\t\tCFont::SetCentreOn();\n\t\t\t}\n\t\t\tif (aScreens[m_nCurrScreen].m_aEntries[i].m_X == 0 && aScreens[m_nCurrScreen].m_aEntries[i].m_Y == 0) {\n\t\t\t\tif (i == 0 || (i == 1 && weHaveLabel)) {\n#ifdef CUSTOM_FRONTEND_OPTIONS\n\t\t\t\t\taScreens[m_nCurrScreen].m_aEntries[i].m_X = (aScreens[m_nCurrScreen].layout ? aScreens[m_nCurrScreen].layout->startX : MENU_DEFAULT_CONTENT_X);\n\t\t\t\t\taScreens[m_nCurrScreen].m_aEntries[i].m_Y = (aScreens[m_nCurrScreen].layout ? aScreens[m_nCurrScreen].layout->startY : MENU_DEFAULT_CONTENT_Y);\n#else\n\t\t\t\t\taScreens[m_nCurrScreen].m_aEntries[i].m_X = MENU_DEFAULT_CONTENT_X;\n\t\t\t\t\taScreens[m_nCurrScreen].m_aEntries[i].m_Y = MENU_DEFAULT_CONTENT_Y;\n#endif\n\t\t\t\t\t\n\t\t\t\t} else {\n\t\t\t\t\taScreens[m_nCurrScreen].m_aEntries[i].m_X = aScreens[m_nCurrScreen].m_aEntries[i-1].m_X;\n\t\t\t\t\taScreens[m_nCurrScreen].m_aEntries[i].m_Y = aScreens[m_nCurrScreen].m_aEntries[i-1].m_Y PLUS_LINE_HEIGHT_ON_SCREEN;\n\t\t\t\t}\n\t\t\t}\n#ifdef CUSTOM_FRONTEND_OPTIONS\n\t\t\telse if (aScreens[m_nCurrScreen].m_aEntries[i].m_Y == 0) {\n\t\t\t\taScreens[m_nCurrScreen].m_aEntries[i].m_Y = aScreens[m_nCurrScreen].m_aEntries[i-1].m_Y PLUS_LINE_HEIGHT_ON_SCREEN;\n\t\t\t}\n#endif\n\n\t\t\tif (aScreens[m_nCurrScreen].m_aEntries[i].m_Action != MENUACTION_LABEL && aScreens[m_nCurrScreen].m_aEntries[i].m_EntryName[0] != '\\0') {\n\n\t\t\t\tif (aScreens[m_nCurrScreen].m_aEntries[i].m_SaveSlot >= SAVESLOT_1 && aScreens[m_nCurrScreen].m_aEntries[i].m_SaveSlot <= SAVESLOT_8) {\n\t\t\t\t\tCFont::SetRightJustifyOff();\n\n\t\t\t\t\tleftText = nil;\n\t\t\t\t\tif (Slots[i] == SLOT_OK) {\n\t\t\t\t\t\tleftText = GetNameOfSavedGame(i);\n\t\t\t\t\t\trightText = GetSavedGameDateAndTime(i);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (!leftText || leftText[0] == '\\0') {\n\t\t\t\t\t\tsprintf(gString, \"FEM_SL%d\", i + 1);\n\t\t\t\t\t\tleftText = TheText.Get(gString);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tleftText = TheText.Get(aScreens[m_nCurrScreen].m_aEntries[i].m_EntryName);\n\t\t\t\t}\n\n\t\t\t\tif (m_nPrefsAudio3DProviderIndex == NO_AUDIO_PROVIDER) {\n\t\t\t\t\tif (strcmp(aScreens[m_nCurrScreen].m_aEntries[i].m_EntryName, \"FEO_AUD\") == 0) {\n\t\t\t\t\t\tCFont::SetColor(CRGBA(DARKMENUOPTION_COLOR.r, DARKMENUOPTION_COLOR.g, DARKMENUOPTION_COLOR.b, FadeIn(255)));\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tswitch (aScreens[m_nCurrScreen].m_aEntries[i].m_Action) {\n#ifdef GAMEPAD_MENU\n\t\t\t\tcase MENUACTION_CTRLVIBRATION:\n\t\t\t\t\tif (m_PrefsUseVibration)\n\t\t\t\t\t\trightText = TheText.Get(\"FEM_ON\");\n\t\t\t\t\telse\n\t\t\t\t\t\trightText = TheText.Get(\"FEM_OFF\");\n\t\t\t\t\tbreak;\n\t\t\t\tcase MENUACTION_CTRLCONFIG:\n\t\t\t\t\tswitch (CPad::GetPad(0)->Mode) {\n\t\t\t\t\tcase 0:\n\t\t\t\t\t\trightText = TheText.Get(\"FEC_CF1\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 1:\n\t\t\t\t\t\trightText = TheText.Get(\"FEC_CF2\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 2:\n\t\t\t\t\t\trightText = TheText.Get(\"FEC_CF3\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 3:\n\t\t\t\t\t\trightText = TheText.Get(\"FEC_CF4\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t// This one is still in enum and ProcessOnOffMenuOptions, but removed from other places\n\t\t\t\tcase MENUACTION_CTRLDISPLAY:\n\t\t\t\t\tif (m_DisplayControllerOnFoot)\n\t\t\t\t\t\trightText = TheText.Get(\"FEC_ONF\");\n\t\t\t\t\telse\n\t\t\t\t\t\trightText = TheText.Get(\"FEC_INC\");\n\t\t\t\t\tbreak;\n#endif\n\t\t\t\tcase MENUACTION_FRAMESYNC:\n\t\t\t\t\trightText = TheText.Get(m_PrefsVsyncDisp ? \"FEM_ON\" : \"FEM_OFF\");\n\t\t\t\t\tbreak;\n\t\t\t\tcase MENUACTION_FRAMELIMIT:\n\t\t\t\t\trightText = TheText.Get(m_PrefsFrameLimiter ? \"FEM_ON\" : \"FEM_OFF\");\n\t\t\t\t\tbreak;\n\t\t\t\tcase MENUACTION_TRAILS:\n\t\t\t\t\trightText = TheText.Get(CMBlur::BlurOn ? \"FEM_ON\" : \"FEM_OFF\");\n\t\t\t\t\tbreak;\n\t\t\t\tcase MENUACTION_SUBTITLES:\n\t\t\t\t\trightText = TheText.Get(m_PrefsShowSubtitles ? \"FEM_ON\" : \"FEM_OFF\");\n\t\t\t\t\tbreak;\n\t\t\t\tcase MENUACTION_WIDESCREEN:\n#ifndef ASPECT_RATIO_SCALE\n\t\t\t\t\trightText = TheText.Get(m_PrefsUseWideScreen ? \"FEM_ON\" : \"FEM_OFF\");\n#else\n\t\t\t\t\tswitch (m_PrefsUseWideScreen) {\n\t\t\t\t\tcase AR_AUTO:\n\t\t\t\t\t\trightText = TheText.Get(\"FEM_AUT\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase AR_4_3:\n\t\t\t\t\t\tsprintf(asciiTemp, \"4:3\");\n\t\t\t\t\t\tAsciiToUnicode(asciiTemp, unicodeTemp);\n\t\t\t\t\t\trightText = unicodeTemp;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase AR_5_4:\n\t\t\t\t\t\tsprintf(asciiTemp, \"5:4\");\n\t\t\t\t\t\tAsciiToUnicode(asciiTemp, unicodeTemp);\n\t\t\t\t\t\trightText = unicodeTemp;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase AR_16_10:\n\t\t\t\t\t\tsprintf(asciiTemp, \"16:10\");\n\t\t\t\t\t\tAsciiToUnicode(asciiTemp, unicodeTemp);\n\t\t\t\t\t\trightText = unicodeTemp;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase AR_16_9:\n\t\t\t\t\t\tsprintf(asciiTemp, \"16:9\");\n\t\t\t\t\t\tAsciiToUnicode(asciiTemp, unicodeTemp);\n\t\t\t\t\t\trightText = unicodeTemp;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase AR_21_9:\n\t\t\t\t\t\tsprintf(asciiTemp, \"21:9\");\n\t\t\t\t\t\tAsciiToUnicode(asciiTemp, unicodeTemp);\n\t\t\t\t\t\trightText = unicodeTemp;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n#endif\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase MENUACTION_MUSICVOLUME:\n\t\t\t\tcase MENUACTION_SFXVOLUME:\n\t\t\t\t\tif (m_nPrefsAudio3DProviderIndex == NO_AUDIO_PROVIDER)\n\t\t\t\t\t\trightText = TheText.Get(\"FEA_NAH\");\n\n\t\t\t\t\tbreak;\n\t\t\t\tcase MENUACTION_RADIO:\n\t\t\t\t\tswitch (m_PrefsRadioStation) {\n\t\t\t\t\t\tcase WILDSTYLE:\n\t\t\t\t\t\t\trightText = TheText.Get(\"FEA_FM0\");\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase FLASH_FM:\n\t\t\t\t\t\t\trightText = TheText.Get(\"FEA_FM1\");\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase KCHAT:\n\t\t\t\t\t\t\trightText = TheText.Get(\"FEA_FM2\");\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase FEVER:\n\t\t\t\t\t\t\trightText = TheText.Get(\"FEA_FM3\");\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase V_ROCK:\n\t\t\t\t\t\t\trightText = TheText.Get(\"FEA_FM4\");\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase VCPR:\n\t\t\t\t\t\t\trightText = TheText.Get(\"FEA_FM5\");\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase RADIO_ESPANTOSO:\n\t\t\t\t\t\t\trightText = TheText.Get(\"FEA_FM6\");\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase EMOTION:\n\t\t\t\t\t\t\trightText = TheText.Get(\"FEA_FM7\");\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase WAVE:\n\t\t\t\t\t\t\trightText = TheText.Get(\"FEA_FM8\");\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase USERTRACK:\n\t\t\t\t\t\t\trightText = TheText.Get(\"FEA_MP3\");\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase MENUACTION_LEGENDS:\n\t\t\t\t\trightText = TheText.Get(m_PrefsShowLegends ? \"FEM_ON\" : \"FEM_OFF\");\n\t\t\t\t\tbreak;\n\t\t\t\tcase MENUACTION_RADARMODE:\n\t\t\t\t\tswitch (m_PrefsRadarMode) {\n\t\t\t\t\t\tcase 0:\n\t\t\t\t\t\t\trightText = TheText.Get(\"FED_RDM\");\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 1:\n\t\t\t\t\t\t\trightText = TheText.Get(\"FED_RDB\");\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 2:\n\t\t\t\t\t\t\trightText = TheText.Get(\"FEM_OFF\");\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase MENUACTION_HUD:\n\t\t\t\t\trightText = TheText.Get(m_PrefsShowHud ? \"FEM_ON\" : \"FEM_OFF\");\n\t\t\t\t\tbreak;\n#ifdef LEGACY_MENU_OPTIONS\n\t\t\t\tcase MENUACTION_SETDBGFLAG:\n\t\t\t\t\trightText = TheText.Get(CTheScripts::IsDebugOn() ? \"FEM_ON\" : \"FEM_OFF\");\n\t\t\t\t\tbreak;\n\t\t\t\tcase MENUACTION_SWITCHBIGWHITEDEBUGLIGHT:\n\t\t\t\t\trightText = TheText.Get(gbBigWhiteDebugLightSwitchedOn ? \"FEM_ON\" : \"FEM_OFF\");\n\t\t\t\t\tbreak;\n\t\t\t\tcase MENUACTION_COLLISIONPOLYS:\n\t\t\t\t\trightText = TheText.Get(gbShowCollisionPolys ? \"FEM_ON\" : \"FEM_OFF\");\n\t\t\t\t\tbreak;\n#endif\n\t\t\t\tcase MENUACTION_SHOWHEADBOB:\n\t\t\t\t\trightText = TheText.Get(TheCamera.m_bHeadBob ? \"FEM_ON\" : \"FEM_OFF\");\n\t\t\t\t\tbreak;\n\t\t\t\tcase MENUACTION_INVVERT:\n\t\t\t\t\trightText = TheText.Get(MousePointerStateHelper.bInvertVertically ? \"FEM_OFF\" : \"FEM_ON\");\n\t\t\t\t\tbreak;\n\t\t\t\tcase MENUACTION_SCREENRES:\n\t\t\t\t\tAsciiToUnicode(_psGetVideoModeList()[m_nDisplayVideoMode], unicodeTemp);\n\t\t\t\t\trightText = unicodeTemp;\n\n\t\t\t\t\tif (!m_bGameNotLoaded) {\n\t\t\t\t\t\tCFont::SetColor(CRGBA(DARKMENUOPTION_COLOR.r, DARKMENUOPTION_COLOR.g, DARKMENUOPTION_COLOR.b, FadeIn(255)));\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase MENUACTION_AUDIOHW:\n\t\t\t\t\tif (m_nPrefsAudio3DProviderIndex == NO_AUDIO_PROVIDER)\n\t\t\t\t\t\trightText = TheText.Get(\"FEA_NAH\");\n\t\t\t\t\telse if (m_nPrefsAudio3DProviderIndex == -1)\n\t\t\t\t\t\trightText = TheText.Get(\"FEA_ADP\");\n\t\t\t\t\telse {\n\t\t\t\t\t\tchar *rawProvider = DMAudio.Get3DProviderName(m_nPrefsAudio3DProviderIndex);\n\t\t\t\t\t\tAsciiToUnicode(rawProvider, unicodeTemp);\n\t\t\t\t\t\tchar *provider = UnicodeToAscii(unicodeTemp); // genius\n\t\t\t\t\t\tstrupr(provider);\n\t\t\t\t\t\tif (!strcmp(provider, \"DIRECTSOUND3D HARDWARE SUPPORT\")) {\n\t\t\t\t\t\t\tstrcpy(provider, \"DSOUND3D HARDWARE SUPPORT\");\n\t\t\t\t\t\t} else if (!strcmp(provider, \"DIRECTSOUND3D SOFTWARE EMULATION\")) {\n\t\t\t\t\t\t\tstrcpy(provider, \"DSOUND3D SOFTWARE EMULATION\");\n\t\t\t\t\t\t}\n\t\t\t\t\t\tAsciiToUnicode(provider, unicodeTemp);\n\t\t\t\t\t\trightText = unicodeTemp;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase MENUACTION_SPEAKERCONF: {\n\t\t\t\t\tif (m_nPrefsAudio3DProviderIndex == NO_AUDIO_PROVIDER)\n\t\t\t\t\t\trightText = TheText.Get(\"FEA_NAH\");\n\t\t\t\t\telse {\n\t\t\t\t\t\tswitch (m_PrefsSpeakers) {\n\t\t\t\t\t\tcase 0:\n\t\t\t\t\t\t\trightText = TheText.Get(\"FEA_2SP\");\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 1:\n\t\t\t\t\t\t\trightText = TheText.Get(\"FEA_EAR\");\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 2:\n\t\t\t\t\t\t\trightText = TheText.Get(\"FEA_4SP\");\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase MENUACTION_CTRLMETHOD: {\n\t\t\t\t\tswitch (m_ControlMethod) {\n\t\t\t\t\tcase CONTROL_STANDARD:\n\t\t\t\t\t\tleftText = TheText.Get(\"FET_STI\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase CONTROL_CLASSIC:\n\t\t\t\t\t\tleftText = TheText.Get(\"FET_CTI\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase MENUACTION_DYNAMICACOUSTIC:\n\t\t\t\t\trightText = TheText.Get(m_PrefsDMA ? \"FEM_ON\" : \"FEM_OFF\");\n\t\t\t\t\tbreak;\n\t\t\t\tcase MENUACTION_MOUSESTEER:\n\t\t\t\t\trightText = TheText.Get(CVehicle::m_bDisableMouseSteering ? \"FEM_OFF\" : \"FEM_ON\");\n\t\t\t\t\tif (m_ControlMethod == CONTROL_CLASSIC) {\n\t\t\t\t\t\tCFont::SetColor(CRGBA(DARKMENUOPTION_COLOR.r, DARKMENUOPTION_COLOR.g, DARKMENUOPTION_COLOR.b, FadeIn(255)));\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase MENUACTION_MP3VOLUMEBOOST:\n\t\t\t\t\tif (!DMAudio.IsMP3RadioChannelAvailable()) {\n\t\t\t\t\t\trightText = TheText.Get(\"FEA_NM3\");\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n#ifdef CUSTOM_FRONTEND_OPTIONS\n\t\t\t\tcase MENUACTION_CFO_DYNAMIC:\n\t\t\t\tcase MENUACTION_CFO_SELECT:\n\t\t\t\t\tCMenuScreenCustom::CMenuEntry &option = aScreens[m_nCurrScreen].m_aEntries[i];\n\t\t\t\t\tif (option.m_Action == MENUACTION_CFO_SELECT) {\n\t\t\t\t\t\tif (option.m_CFOSelect->disableIfGameLoaded && !m_bGameNotLoaded)\n\t\t\t\t\t\t\tCFont::SetColor(CRGBA(DARKMENUOPTION_COLOR.r, DARKMENUOPTION_COLOR.g, DARKMENUOPTION_COLOR.b, FadeIn(255)));\n\n\t\t\t\t\t\t// To whom manipulate option.m_CFO->value of static options externally (like RestoreDef functions)\n\t\t\t\t\t\tif (*option.m_CFO->value != option.m_CFOSelect->lastSavedValue)\n\t\t\t\t\t\t\toption.m_CFOSelect->displayedValue = option.m_CFOSelect->lastSavedValue = *option.m_CFO->value;\n\n\t\t\t\t\t\tif (option.m_CFOSelect->displayedValue >= option.m_CFOSelect->numRightTexts || option.m_CFOSelect->displayedValue < 0)\n\t\t\t\t\t\t\toption.m_CFOSelect->displayedValue = 0;\n\n\t\t\t\t\t\trightText = TheText.Get(option.m_CFOSelect->rightTexts[option.m_CFOSelect->displayedValue]);\n\n\t\t\t\t\t} else if (option.m_Action == MENUACTION_CFO_DYNAMIC) {\n\t\t\t\t\t\tif (option.m_CFODynamic->drawFunc) {\n\t\t\t\t\t\t\tbool isOptionDisabled = false;\n\t\t\t\t\t\t\trightText = option.m_CFODynamic->drawFunc(&isOptionDisabled, m_nCurrOption == i);\n\t\t\t\t\t\t\tif (isOptionDisabled)\n\t\t\t\t\t\t\t\tCFont::SetColor(CRGBA(DARKMENUOPTION_COLOR.r, DARKMENUOPTION_COLOR.g, DARKMENUOPTION_COLOR.b, FadeIn(255)));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n#endif\n\t\t\t\t}\n\n\t\t\t\t// Highlight trapezoid\n\t\t\t\tif (activeScreen && i == m_nCurrOption && itemsAreSelectable && section == 0) {\n\n\t\t\t\t\tint leftXMax, rightXMin;\n\n\t\t\t\t\t// FIX: Let's don't scale those so GetStringWidth can give us unscaled width, which will be handy to other calculations below that's done without scaling in mind,\n\t\t\t\t\t//\t\tand scaling will be done eventually.\n\t\t\t\t\t// CFont::SetScale(MENU_X(BIGTEXT_X_SCALE), MENU_Y(BIGTEXT_Y_SCALE));\n\t\t\t\t\tCFont::SetScale(BIGTEXT_X_SCALE, BIGTEXT_Y_SCALE);\n\t\t\t\t\t\n\t\t\t\t\twchar *curOptionName = TheText.Get(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName);\n\t\t\t\t\tfloat curOptionWidth = CFont::GetStringWidth(curOptionName, true);\n\n\t\t\t\t\tif (CFont::Details.centre) {\n\t\t\t\t\t\tleftXMax = Max(0, aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_X - curOptionWidth / 2.f);\n\t\t\t\t\t\trightXMin = Min(DEFAULT_SCREEN_WIDTH, curOptionWidth / 2.f + aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_X);\n\n\t\t\t\t\t} else if (!CFont::Details.rightJustify) {\n\t\t\t\t\t\tleftXMax = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_X;\n\t\t\t\t\t\trightXMin = Min(DEFAULT_SCREEN_WIDTH, curOptionWidth + aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_X);\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tleftXMax = Max(0, aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_X - curOptionWidth);\n\t\t\t\t\t\trightXMin = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_X;\n\t\t\t\t\t}\n\t\t\t\t\tCFont::SetScale(MENU_X(BIGTEXT_X_SCALE), MENU_Y(BIGTEXT_Y_SCALE));\n\n\t\t\t\t\tint action = aScreens[m_nCurrScreen].m_aEntries[i].m_Action;\n\t\t\t\t\tint saveSlot = aScreens[m_nCurrScreen].m_aEntries[i].m_SaveSlot;\n\t\t\t\t\tif (rightText || action == MENUACTION_DRAWDIST || action == MENUACTION_BRIGHTNESS || action == MENUACTION_MUSICVOLUME ||\n\t\t\t\t\t\taction == MENUACTION_SFXVOLUME || action == MENUACTION_MP3VOLUMEBOOST || action == MENUACTION_MOUSESENS ||\n\t\t\t\t\t\tsaveSlot >= SAVESLOT_1 && saveSlot <= SAVESLOT_8) {\n\t\t\t\t\t\trightXMin = 600;\n\t\t\t\t\t\tleftXMax = 40;\n\t\t\t\t\t}\n\n\t\t\t\t\tint y = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Y MINUS_SCROLL_OFFSET;\n\t\t\t\t\tint topYMax = y;\n\t\t\t\t\tuint32 bottomYMin = y + MENU_DEFAULT_LINE_HEIGHT - 7; // Decreasing is not recommended. Because this actually is dependent to font scale, not line height.\n\n\t\t\t\t\t// Actually bottomRight and bottomLeft should be exchanged here(although this is original code).\n\t\t\t\t\t// So this shows us either R* didn't use same struct for menu BG and highlight, or they just kept fields as x1,y1 etc. Yikes.\n\n\t\t\t\t\tif (m_nOptionHighlightTransitionBlend == 0) {\n\t\t\t\t\t\tif (m_firstStartCounter == 255 && m_nMenuFadeAlpha == 255 && !bMenuChangeOngoing) {\n\t\t\t\t\t\t\tCSprite2d::Draw2DPolygon(MENU_X_LEFT_ALIGNED(menuOptionHighlight.topLeft_x), MENU_Y(menuOptionHighlight.topLeft_y),\n\t\t\t\t\t\t\t\tMENU_X_LEFT_ALIGNED(menuOptionHighlight.topRight_x), MENU_Y(menuOptionHighlight.topRight_y),\n\t\t\t\t\t\t\t\tMENU_X_LEFT_ALIGNED(menuOptionHighlight.bottomRight_x), MENU_Y(menuOptionHighlight.bottomRight_y),\n\t\t\t\t\t\t\t\tMENU_X_LEFT_ALIGNED(menuOptionHighlight.bottomLeft_x), MENU_Y(menuOptionHighlight.bottomLeft_y), SELECTIONBORDER_COLOR);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tmenuOptionHighlight.SaveCurrentCoors();\n\t\t\t\t\t\tmenuOptionHighlight.topLeft_x = leftXMax - 5 - CGeneral::GetRandomNumber() % 10;\n\t\t\t\t\t\tmenuOptionHighlight.topLeft_y = topYMax - CGeneral::GetRandomNumber() % 7;\n\t\t\t\t\t\tmenuOptionHighlight.topRight_x = rightXMin + 5 + CGeneral::GetRandomNumber() % 10;\n\t\t\t\t\t\tmenuOptionHighlight.topRight_y = topYMax - CGeneral::GetRandomNumber() % 7;\n\t\t\t\t\t\tmenuOptionHighlight.bottomLeft_x = rightXMin + 5 + CGeneral::GetRandomNumber() % 10;\n\t\t\t\t\t\tmenuOptionHighlight.bottomLeft_y = bottomYMin + CGeneral::GetRandomNumber() % 7;\n\t\t\t\t\t\tmenuOptionHighlight.bottomRight_x = leftXMax - 5 - CGeneral::GetRandomNumber() % 10;\n\t\t\t\t\t\tmenuOptionHighlight.bottomRight_y = bottomYMin + CGeneral::GetRandomNumber() % 7;\n\t\t\t\t\t\tmenuOptionHighlight.UpdateMultipliers();\n\t\t\t\t\t\tmenuOptionHighlight.Translate(m_nOptionHighlightTransitionBlend);\n\n\t\t\t\t\t} else if (m_nOptionHighlightTransitionBlend < 255) {\n\t\t\t\t\t\tmenuOptionHighlight.Translate(m_nOptionHighlightTransitionBlend);\n\t\t\t\t\t\tif (m_firstStartCounter == 255 && m_nMenuFadeAlpha == 255 && !bMenuChangeOngoing) {\n\t\t\t\t\t\t\tCSprite2d::Draw2DPolygon(MENU_X_LEFT_ALIGNED(menuOptionHighlight.topLeft_x), MENU_Y(menuOptionHighlight.topLeft_y),\n\t\t\t\t\t\t\t\tMENU_X_LEFT_ALIGNED(menuOptionHighlight.topRight_x), MENU_Y(menuOptionHighlight.topRight_y),\n\t\t\t\t\t\t\t\tMENU_X_LEFT_ALIGNED(menuOptionHighlight.bottomRight_x), MENU_Y(menuOptionHighlight.bottomRight_y),\n\t\t\t\t\t\t\t\tMENU_X_LEFT_ALIGNED(menuOptionHighlight.bottomLeft_x), MENU_Y(menuOptionHighlight.bottomLeft_y), SELECTIONBORDER_COLOR);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tm_nOptionHighlightTransitionBlend = 255;\n\t\t\t\t\t\tmenuOptionHighlight.Translate(m_nOptionHighlightTransitionBlend);\n\t\t\t\t\t\tif (m_firstStartCounter == 255 && m_nMenuFadeAlpha == 255 && !bMenuChangeOngoing) {\n\t\t\t\t\t\t\tCSprite2d::Draw2DPolygon(MENU_X_LEFT_ALIGNED(menuOptionHighlight.topLeft_x), MENU_Y(menuOptionHighlight.topLeft_y),\n\t\t\t\t\t\t\t\tMENU_X_LEFT_ALIGNED(menuOptionHighlight.topRight_x), MENU_Y(menuOptionHighlight.topRight_y),\n\t\t\t\t\t\t\t\tMENU_X_LEFT_ALIGNED(menuOptionHighlight.bottomRight_x), MENU_Y(menuOptionHighlight.bottomRight_y),\n\t\t\t\t\t\t\t\tMENU_X_LEFT_ALIGNED(menuOptionHighlight.bottomLeft_x), MENU_Y(menuOptionHighlight.bottomLeft_y), SELECTIONBORDER_COLOR);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tstatic PauseModeTime lastBlendChange = 0;\n\t\t\t\t\tif (m_nOptionHighlightTransitionBlend <= 255) {\n\t\t\t\t\t\tstatic uint32 blendChangeCounter = 0;\n\t\t\t\t\t\tif (CTimer::GetTimeInMillisecondsPauseMode() - lastBlendChange > 20\n#ifndef FIX_HIGH_FPS_BUGS_ON_FRONTEND // Dirty dirty hack\n\t\t\t\t\t\t\t|| blendChangeCounter > 20\n#endif\n\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tm_nOptionHighlightTransitionBlend += 50;\n\t\t\t\t\t\t\tlastBlendChange = CTimer::GetTimeInMillisecondsPauseMode();\n\t\t\t\t\t\t\tblendChangeCounter = 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t++blendChangeCounter;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (section == 1) {\n\t\t\t\t\tif (leftText) {\n\t\t\t\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(aScreens[m_nCurrScreen].m_aEntries[i].m_X), MENU_Y(aScreens[m_nCurrScreen].m_aEntries[i].m_Y MINUS_SCROLL_OFFSET), leftText);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (rightText) {\n\t\t\t\t\t\tCFont::SetCentreOff();\n\t\t\t\t\t\tCFont::SetRightJustifyOn();\n\t\t\t\t\t\tif (aScreens[m_nCurrScreen].m_aEntries[i].m_SaveSlot >= SAVESLOT_1 && aScreens[m_nCurrScreen].m_aEntries[i].m_SaveSlot <= SAVESLOT_8) {\n\t\t\t\t\t\t\tCFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD));\n\t\t\t\t\t\t\tCFont::SetScale(MENU_X(MEDIUMTEXT_X_SCALE), MENU_Y(MEDIUMTEXT_Y_SCALE));\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tCFont::SetFontStyle(FONT_LOCALE(FONT_HEADING));\n\t\t\t\t\t\t\tCFont::SetScale(MENU_X(BIGTEXT_X_SCALE), MENU_Y(BIGTEXT_Y_SCALE));\n\t\t\t\t\t\t}\n\t\t\t\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(DEFAULT_SCREEN_WIDTH - RIGHT_ALIGNED_TEXT_RIGHT_MARGIN(xMargin)), MENU_Y(aScreens[m_nCurrScreen].m_aEntries[i].m_Y MINUS_SCROLL_OFFSET), rightText);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (m_nPrefsAudio3DProviderIndex == DMAudio.GetCurrent3DProviderIndex()) {\n\t\t\t\t\t\tif (!strcmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, \"FEA_3DH\") && m_nHelperTextMsgId == 1)\n\t\t\t\t\t\t\tResetHelperText();\n\t\t\t\t\t}\n\t\t\t\t\tif (m_nDisplayVideoMode == m_nPrefsVideoMode) {\n\t\t\t\t\t\tif (!strcmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, \"FED_RES\") && m_nHelperTextMsgId == 1)\n\t\t\t\t\t\t\tResetHelperText();\n\t\t\t\t\t}\n\t\t\t\t\tif (m_nPrefsAudio3DProviderIndex != DMAudio.GetCurrent3DProviderIndex()) {\n\t\t\t\t\t\tif (!strcmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, \"FEA_3DH\"))\n\t\t\t\t\t\t\tSetHelperText(1);\n\t\t\t\t\t}\n\t\t\t\t\tif (m_nDisplayVideoMode != m_nPrefsVideoMode) {\n\t\t\t\t\t\tif (!strcmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, \"FED_RES\"))\n\t\t\t\t\t\t\tSetHelperText(1);\n\t\t\t\t\t}\n\t\t\t\t\tif (m_nPrefsAudio3DProviderIndex != DMAudio.GetCurrent3DProviderIndex()) {\n\t\t\t\t\t\tif (strcmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, \"FEA_3DH\") != 0\n#ifdef CUSTOM_FRONTEND_OPTIONS\n\t\t\t\t\t\t\t&& ScreenHasOption(m_nCurrScreen, \"FEA_3DH\")\n#else\n\t\t\t\t\t\t\t&& m_nCurrScreen == MENUPAGE_SOUND_SETTINGS\n#endif\n\t\t\t\t\t\t\t&& m_nPrefsAudio3DProviderIndex != NO_AUDIO_PROVIDER) {\n\n\t\t\t\t\t\t\tm_nPrefsAudio3DProviderIndex = DMAudio.GetCurrent3DProviderIndex();\n\t\t\t\t\t\t\tSetHelperText(3);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (m_nDisplayVideoMode != m_nPrefsVideoMode) {\n\t\t\t\t\t\tif (strcmp(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_EntryName, \"FED_RES\") != 0\n#ifdef CUSTOM_FRONTEND_OPTIONS\n\t\t\t\t\t\t\t&& ScreenHasOption(m_nCurrScreen, \"FED_RES\")) {\n#else\n\t\t\t\t\t\t\t&& m_nCurrScreen == MENUPAGE_DISPLAY_SETTINGS) {\n#endif\n\t\t\t\t\t\t\tm_nDisplayVideoMode = m_nPrefsVideoMode;\n\t\t\t\t\t\t\tSetHelperText(3);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Sliders\n\t\t\t\t\tint lastActiveBarX;\n\t\t\t\t\tswitch (aScreens[m_nCurrScreen].m_aEntries[i].m_Action) {\n\t\t\t\t\t\tcase MENUACTION_BRIGHTNESS:\n\t\t\t\t\t\t\tProcessSlider(m_PrefsBrightness / 384.0f, 70.0f, HOVEROPTION_INCREASE_BRIGHTNESS, HOVEROPTION_DECREASE_BRIGHTNESS, SCREEN_WIDTH, true);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase MENUACTION_DRAWDIST:\n\t\t\t\t\t\t\tProcessSlider((m_PrefsLOD - 0.925f) / 0.875f, 99.0f, HOVEROPTION_INCREASE_DRAWDIST, HOVEROPTION_DECREASE_DRAWDIST, SCREEN_WIDTH, true);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase MENUACTION_MUSICVOLUME:\n\t\t\t\t\t\t\tif(m_nPrefsAudio3DProviderIndex != NO_AUDIO_PROVIDER)\n\t\t\t\t\t\t\t\tProcessSlider(m_PrefsMusicVolume / 64.0f, 70.0f, HOVEROPTION_INCREASE_MUSICVOLUME, HOVEROPTION_DECREASE_MUSICVOLUME, SCREEN_WIDTH, true);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase MENUACTION_SFXVOLUME:\n\t\t\t\t\t\t\tif (m_nPrefsAudio3DProviderIndex != NO_AUDIO_PROVIDER)\n\t\t\t\t\t\t\t\tProcessSlider(m_PrefsSfxVolume / 64.0f, 99.0f, HOVEROPTION_INCREASE_SFXVOLUME, HOVEROPTION_DECREASE_SFXVOLUME, SCREEN_WIDTH, true);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase MENUACTION_MOUSESENS:\n\t\t\t\t\t\t\tProcessSlider(TheCamera.m_fMouseAccelHorzntl * 200.0f, 170.0f, HOVEROPTION_INCREASE_MOUSESENS, HOVEROPTION_DECREASE_MOUSESENS, SCREEN_WIDTH, false);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase MENUACTION_MP3VOLUMEBOOST:\n\t\t\t\t\t\t\tif(m_nPrefsAudio3DProviderIndex != NO_AUDIO_PROVIDER && DMAudio.IsMP3RadioChannelAvailable())\n\t\t\t\t\t\t\t\tProcessSlider(m_PrefsMP3BoostVolume / 64.f, 128.0f, HOVEROPTION_INCREASE_MP3BOOST, HOVEROPTION_DECREASE_MP3BOOST, SCREEN_WIDTH, true);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\t// Not just unused, but also collides with the bug fix in Font.cpp. Yikes.\n#ifndef FIX_BUGS\n\t\t\t\t\tnextYToUse += MENU_DEFAULT_LINE_HEIGHT * CFont::GetNumberLines(MENU_X_LEFT_ALIGNED(60.0f), MENU_Y(nextYToUse), leftText);\n#endif\n\n\t\t\t\t\tif (aScreens[m_nCurrScreen].m_aEntries[i].m_Action == MENUACTION_RADIO) {\n\t\t\t\t\t\tnextYToUse += MENURADIO_SELECTOR_HEIGHT + 5.f; // unused\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tsection++;\n\t}\n\n#ifdef SCROLLABLE_PAGES\n\t#define SCROLLBAR_BOTTOM_Y 105.0f // only for background, scrollbar's itself is calculated\n\t#define SCROLLBAR_RIGHT_X 26.0f\n\t#define SCROLLBAR_WIDTH 9.5f\n\t#define SCROLLBAR_TOP_Y 84\n\n\tif (activeScreen && SCREEN_HAS_AUTO_SCROLLBAR) {\n\t\t// Scrollbar background\n\t\tCSprite2d::DrawRect(CRect(MENU_X_RIGHT_ALIGNED(SCROLLBAR_RIGHT_X - 2), MENU_Y(SCROLLBAR_TOP_Y),\n\t\t\tMENU_X_RIGHT_ALIGNED(SCROLLBAR_RIGHT_X - 2 - SCROLLBAR_WIDTH), SCREEN_SCALE_FROM_BOTTOM(SCROLLBAR_BOTTOM_Y)), CRGBA(30, 30, 30, FadeIn(150)));\n\t\t\n\t\tfloat scrollbarHeight = SCROLLBAR_MAX_HEIGHT / (m_nTotalListRow / (float) MAX_VISIBLE_OPTION);\n\t\tfloat scrollbarBottom, scrollbarTop;\n\n\t\tscrollbarBottom = MENU_Y(SCROLLBAR_TOP_Y - 6 + m_nScrollbarTopMargin + scrollbarHeight);\n\t\tscrollbarTop = MENU_Y(SCROLLBAR_TOP_Y + 2 + m_nScrollbarTopMargin);\n\t\t// Scrollbar shadow\n\t\tCSprite2d::DrawRect(CRect(MENU_X_RIGHT_ALIGNED(SCROLLBAR_RIGHT_X - 4), scrollbarTop,\n\t\t\tMENU_X_RIGHT_ALIGNED(SCROLLBAR_RIGHT_X - 1 - SCROLLBAR_WIDTH), scrollbarBottom + MENU_Y(1.0f)),\n\t\t\tCRGBA(50, 50, 50, FadeIn(255)));\n\n\t\t// Scrollbar\n\t\tCSprite2d::DrawRect(CRect(MENU_X_RIGHT_ALIGNED(SCROLLBAR_RIGHT_X - 4), scrollbarTop,\n\t\t\tMENU_X_RIGHT_ALIGNED(SCROLLBAR_RIGHT_X - SCROLLBAR_WIDTH), scrollbarBottom),\n\t\t\tCRGBA(SCROLLBAR_COLOR.r, SCROLLBAR_COLOR.g, SCROLLBAR_COLOR.b, FadeIn(255)));\n\t\t\t\n\t}\n#endif\n\n\tswitch (m_nCurrScreen) {\n#ifdef GAMEPAD_MENU\n\t\tcase MENUPAGE_CONTROLLER_SETTINGS:\n\t\t\tPrintController();\n\t\t\tbreak;\n#endif\n\t\tcase MENUPAGE_STATS:\n\t\tcase MENUPAGE_CONTROLLER_PC:\n\t\tcase MENUPAGE_SOUND_SETTINGS:\n\t\tcase MENUPAGE_DISPLAY_SETTINGS:\n\t\tcase MENUPAGE_MOUSE_CONTROLS:\n\t\t\tDisplayHelperText(nil);\n\t\t\tbreak;\n\t\tcase MENUPAGE_OPTIONS:\n\t\t\tif (m_nPrefsAudio3DProviderIndex == NO_AUDIO_PROVIDER && aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action == MENUACTION_LOADRADIO)\n\t\t\t\tDisplayHelperText(\"FEA_NAH\");\n\t\t\tbreak;\n#ifdef CUSTOM_FRONTEND_OPTIONS\n\t\tdefault:\n\t\t\tif (aScreens[m_nCurrScreen].layout) {\n\t\t\t\tif (aScreens[m_nCurrScreen].layout->showLeftRightHelper) {\n\t\t\t\t\tDisplayHelperText(nil);\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n#endif\n\t}\n\n\tif (m_nCurrScreen == MENUPAGE_DELETING_IN_PROGRESS) {\n\t\tSmallMessageScreen(\"FEDL_WR\");\n\t}\n#ifndef XBOX_MESSAGE_SCREEN\n\telse if (m_nCurrScreen == MENUPAGE_SAVING_IN_PROGRESS) {\n\t\tSmallMessageScreen(\"FESZ_WR\");\n\t}\n#endif\n}\n\nint\nCMenuManager::GetNumOptionsCntrlConfigScreens(void)\n{\n\tint number = 0;\n\tswitch (m_nCurrScreen) {\n#ifdef LEGACY_MENU_OPTIONS\n\t\tcase MENUPAGE_CONTROLLER_PC_OLD3:\n\t\t\tnumber = 2;\n\t\t\tbreak;\n\t\tcase MENUPAGE_CONTROLLER_DEBUG:\n\t\t\tnumber = 4;\n\t\t\tbreak;\n#endif\n\t\tcase MENUPAGE_KEYBOARD_CONTROLS:\n\t\t\tswitch (m_ControlMethod) {\n\t\t\t\tcase CONTROL_STANDARD:\n\t\t\t\t\tnumber = 27;\n\t\t\t\t\tbreak;\n\t\t\t\tcase CONTROL_CLASSIC:\n\t\t\t\t\tnumber = 32;\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tbreak;\n\t}\n\treturn number;\n}\n\nvoid\nCMenuManager::DrawControllerBound(int32 yStart, int32 xStart, int32 unused, int8 column)\n{\n\tint controllerAction = PED_FIREWEAPON;\n\t// GetStartOptionsCntrlConfigScreens();\n\tint numOptions = GetNumOptionsCntrlConfigScreens();\n\tint nextY = MENU_Y(yStart);\n\tint bindingMargin = MENU_X(3.0f);\n\tfloat rowHeight;\n\tswitch (m_ControlMethod) {\n\t\tcase CONTROL_STANDARD:\n\t\t\trowHeight = CONTSETUP_STANDARD_ROW_HEIGHT;\n\t\t\tbreak;\n\t\tcase CONTROL_CLASSIC:\n\t\t\trowHeight = CONTSETUP_CLASSIC_ROW_HEIGHT;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\n\tfor (int optionIdx = 0; optionIdx < numOptions; nextY = MENU_Y(++optionIdx * rowHeight + yStart)) {\n\t\tint nextX = xStart;\n\t\tint bindingsForThisOpt = 0;\n\t\tint contSetOrder = SETORDER_1;\n\t\tCFont::SetColor(CRGBA(255, 255, 255, FadeIn(255)));\n\n\t\tif (column == CONTSETUP_PED_COLUMN) {\n\t\t\tswitch (optionIdx) {\n\t\t\t\tcase 0:\n\t\t\t\t\tcontrollerAction = PED_FIREWEAPON;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 1:\n\t\t\t\t\tcontrollerAction = PED_CYCLE_WEAPON_RIGHT;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 2:\n\t\t\t\t\tcontrollerAction = PED_CYCLE_WEAPON_LEFT;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 3:\n\t\t\t\t\tcontrollerAction = GO_FORWARD;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 4:\n\t\t\t\t\tcontrollerAction = GO_BACK;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 5:\n\t\t\t\t\tcontrollerAction = GO_LEFT;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 6:\n\t\t\t\t\tcontrollerAction = GO_RIGHT;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 7:\n\t\t\t\t\tcontrollerAction = PED_SNIPER_ZOOM_IN;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 8:\n\t\t\t\t\tcontrollerAction = PED_SNIPER_ZOOM_OUT;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 9:\n\t\t\t\t\tcontrollerAction = VEHICLE_ENTER_EXIT;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 10:\n\t\t\t\tcase 11:\n\t\t\t\tcase 12:\n\t\t\t\tcase 16:\n\t\t\t\tcase 20:\n\t\t\t\tcase 21:\n\t\t\t\tcase 22:\n\t\t\t\tcase 23:\n\t\t\t\t\tcontrollerAction = -1;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 13:\n\t\t\t\t\tcontrollerAction = CAMERA_CHANGE_VIEW_ALL_SITUATIONS;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 14:\n\t\t\t\t\tcontrollerAction = PED_JUMPING;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 15:\n\t\t\t\t\tcontrollerAction = PED_SPRINT;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 17:\n\t\t\t\t\tcontrollerAction = PED_LOCK_TARGET;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 18:\n\t\t\t\t\tcontrollerAction = PED_DUCK;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 19:\n\t\t\t\t\tcontrollerAction = PED_ANSWER_PHONE;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 24:\n\t\t\t\t\tcontrollerAction = PED_LOOKBEHIND;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 25:\n\t\t\t\t\tif (m_ControlMethod == CONTROL_STANDARD)\n\t\t\t\t\t\tcontrollerAction = -1;\n\t\t\t\t\telse\n\t\t\t\t\t\tcontrollerAction = PED_1RST_PERSON_LOOK_LEFT;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 26:\n\t\t\t\t\tif (m_ControlMethod == CONTROL_STANDARD)\n\t\t\t\t\t\tcontrollerAction = -1;\n\t\t\t\t\telse\n\t\t\t\t\t\tcontrollerAction = PED_1RST_PERSON_LOOK_RIGHT;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 27:\n\t\t\t\t\tcontrollerAction = PED_1RST_PERSON_LOOK_UP;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 28:\n\t\t\t\t\tcontrollerAction = PED_1RST_PERSON_LOOK_DOWN;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 29:\n\t\t\t\t\tcontrollerAction = PED_CYCLE_TARGET_LEFT;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 30:\n\t\t\t\t\tcontrollerAction = PED_CYCLE_TARGET_RIGHT;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 31:\n\t\t\t\t\tcontrollerAction = PED_CENTER_CAMERA_BEHIND_PLAYER;\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t} else if (column == CONTSETUP_VEHICLE_COLUMN) {\n\t\t\tswitch (optionIdx) {\n\t\t\t\tcase 0:\n#ifdef BIND_VEHICLE_FIREWEAPON\n \t\t\t\t\tcontrollerAction = VEHICLE_FIREWEAPON;\n#else\n \t\t\t\t\tcontrollerAction = PED_FIREWEAPON;\n#endif\n\t\t\t\t\tbreak;\n\t\t\t\tcase 1:\n\t\t\t\tcase 2:\n\t\t\t\tcase 7:\n\t\t\t\tcase 8:\n\t\t\t\tcase 14:\n\t\t\t\tcase 15:\n\t\t\t\tcase 17:\n\t\t\t\tcase 18:\n\t\t\t\tcase 19:\n\t\t\t\tcase 27:\n\t\t\t\tcase 28:\n\t\t\t\tcase 29:\n\t\t\t\tcase 30:\n\t\t\t\tcase 31:\n\t\t\t\t\tcontrollerAction = -1;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 3:\n\t\t\t\t\tcontrollerAction = VEHICLE_ACCELERATE;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 4:\n\t\t\t\t\tcontrollerAction = VEHICLE_BRAKE;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 5:\n\t\t\t\t\tcontrollerAction = GO_LEFT;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 6:\n\t\t\t\t\tcontrollerAction = GO_RIGHT;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 9:\n\t\t\t\t\tcontrollerAction = VEHICLE_ENTER_EXIT;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 10:\n\t\t\t\t\tcontrollerAction = VEHICLE_CHANGE_RADIO_STATION;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 11:\n\t\t\t\t\tcontrollerAction = VEHICLE_HORN;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 12:\n\t\t\t\t\tcontrollerAction = TOGGLE_SUBMISSIONS;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 13:\n\t\t\t\t\tcontrollerAction = CAMERA_CHANGE_VIEW_ALL_SITUATIONS;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 16:\n\t\t\t\t\tcontrollerAction = VEHICLE_HANDBRAKE;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 20:\n\t\t\t\t\tcontrollerAction = VEHICLE_TURRETLEFT;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 21:\n\t\t\t\t\tcontrollerAction = VEHICLE_TURRETRIGHT;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 22:\n\t\t\t\t\tcontrollerAction = VEHICLE_TURRETUP;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 23:\n\t\t\t\t\tcontrollerAction = VEHICLE_TURRETDOWN;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 24:\n\t\t\t\t\tcontrollerAction = -2;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 25:\n\t\t\t\t\tcontrollerAction = VEHICLE_LOOKLEFT;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 26:\n\t\t\t\t\tcontrollerAction = VEHICLE_LOOKRIGHT;\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t// Highlight selected column(and make its text black)\n\t\tif (m_nSelectedListRow == optionIdx) {\n\t\t\tint bgY = m_nSelectedListRow * rowHeight + yStart + 1.0f;\n\t\t\tif (m_nCurrExLayer == HOVEROPTION_LIST) {\n\n\t\t\t\tif (column == CONTSETUP_PED_COLUMN && m_nSelectedContSetupColumn == CONTSETUP_PED_COLUMN) {\n#ifdef FIX_BUGS\n\t\t\t\t\tCSprite2d::DrawRect(CRect(nextX, MENU_Y(bgY), nextX + MENU_X(CONTSETUP_BOUND_COLUMN_WIDTH),\n\t\t\t\t\t\tMENU_Y(bgY + CONTSETUP_BOUND_HIGHLIGHT_HEIGHT)), CRGBA(SELECTIONBORDER_COLOR.r, SELECTIONBORDER_COLOR.g, SELECTIONBORDER_COLOR.b, FadeIn(255)));\n#else\n\t\t\t\t\tCSprite2d::DrawRect(CRect(MENU_X_LEFT_ALIGNED(210.0f), MENU_Y(bgY),\n\t\t\t\t\t\tMENU_X_LEFT_ALIGNED(400.0f), MENU_Y(bgY + CONTSETUP_BOUND_HIGHLIGHT_HEIGHT)),\n\t\t\t\t\t\tCRGBA(SELECTIONBORDER_COLOR.r, SELECTIONBORDER_COLOR.g, SELECTIONBORDER_COLOR.b, FadeIn(255)));\n#endif\n\t\t\t\t\tCFont::SetColor(CRGBA(255, 255, 255, FadeIn(255)));\n\n\t\t\t\t} else if (column == CONTSETUP_VEHICLE_COLUMN && m_nSelectedContSetupColumn == CONTSETUP_VEHICLE_COLUMN) {\n#ifdef FIX_BUGS\n\t\t\t\t\tCSprite2d::DrawRect(CRect(nextX, MENU_Y(bgY), nextX + MENU_X(CONTSETUP_BOUND_COLUMN_WIDTH),\n\t\t\t\t\t\tMENU_Y(bgY + CONTSETUP_BOUND_HIGHLIGHT_HEIGHT)), CRGBA(SELECTIONBORDER_COLOR.r, SELECTIONBORDER_COLOR.g, SELECTIONBORDER_COLOR.b, FadeIn(255)));\n#else\n\t\t\t\t\tCSprite2d::DrawRect(CRect(MENU_X_LEFT_ALIGNED(410.0f), MENU_Y(bgY), MENU_X_LEFT_ALIGNED(600.0f), MENU_Y(bgY + CONTSETUP_BOUND_HIGHLIGHT_HEIGHT)),\n\t\t\t\t\t\tCRGBA(SELECTIONBORDER_COLOR.r, SELECTIONBORDER_COLOR.g, SELECTIONBORDER_COLOR.b, FadeIn(255)));\n#endif\n\t\t\t\t\tCFont::SetColor(CRGBA(255, 255, 255, FadeIn(255)));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Print bindings, including seperator (-) between them\n\n\t\tCFont::SetScale(MENU_X(0.25f), MENU_Y(LISTITEM_Y_SCALE));\n#ifdef FIX_BUGS\n\t\tfor (; contSetOrder < MAX_SETORDERS && controllerAction >= 0; contSetOrder++) {\n#else\n\t\tfor (; contSetOrder < MAX_SETORDERS && controllerAction != -1; contSetOrder++) {\n#endif\n\t\t\twchar *settingText = ControlsManager.GetControllerSettingTextWithOrderNumber((e_ControllerAction)controllerAction, (eContSetOrder)contSetOrder);\n\t\t\tif (settingText) {\n\t\t\t\t++bindingsForThisOpt;\n\t\t\t\tif (bindingsForThisOpt > 1) {\n\t\t\t\t\twchar *seperator = TheText.Get(\"FEC_IBT\");\n\t\t\t\t\tCFont::SetColor(CRGBA(255, 255, 255, FadeIn(255)));\n\t\t\t\t\tCFont::PrintString(nextX, nextY, seperator);\n\t\t\t\t\tnextX += CFont::GetStringWidth(seperator, true) + bindingMargin;\n\t\t\t\t}\n\t\t\t\tCFont::PrintString(nextX, nextY, settingText);\n#ifdef MORE_LANGUAGES\n\t\t\t\tif (CFont::IsJapanese())\n\t\t\t\t\tnextX += CFont::GetStringWidth_Jap(settingText) + bindingMargin;\n\t\t\t\telse\n#endif\n\t\t\t\t\tnextX += CFont::GetStringWidth(settingText, true) + bindingMargin;\n\t\t\t}\n\t\t}\n\t\tif (controllerAction == -1) {\n\t\t\tCFont::SetColor(CRGBA(0, 0, 0, FadeIn(255)));\n\t\t\tCFont::PrintString(nextX, nextY, TheText.Get(\"FEC_NUS\")); // not used\n\n\t\t} else if (controllerAction == -2) {\n\t\t\tCFont::SetColor(CRGBA(0, 0, 0, FadeIn(255)));\n\t\t\tCFont::PrintString(nextX, nextY, TheText.Get(\"FEC_CMP\")); // combo: l+r\n\n\t\t} else if (bindingsForThisOpt == 0) {\n\t\t\tm_NoEmptyBinding = false;\n\t\t\tif (m_nSelectedListRow != optionIdx) {\n\t\t\t\tCFont::SetColor(CRGBA(0, 0, 0, FadeIn(255)));\n\t\t\t\tCFont::PrintString(nextX, nextY, TheText.Get(\"FEC_UNB\")); // unbound\n\n\t\t\t} else if (m_bWaitingForNewKeyBind) {\n\t\t\t\tif (column != m_nSelectedContSetupColumn) {\n\t\t\t\t\tCFont::SetColor(CRGBA(0, 0, 0, FadeIn(255)));\n\t\t\t\t\tCFont::PrintString(nextX, nextY, TheText.Get(\"FEC_UNB\")); // unbound\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (column != m_nSelectedContSetupColumn) {\n\t\t\t\t\tCFont::SetColor(CRGBA(0, 0, 0, FadeIn(255)));\n\t\t\t\t}\n\t\t\t\tCFont::PrintString(nextX, nextY, TheText.Get(\"FEC_UNB\")); // unbound\n\t\t\t}\n\t\t}\n\n\t\tif (column == CONTSETUP_PED_COLUMN && m_nSelectedContSetupColumn == CONTSETUP_PED_COLUMN ||\n\t\t\tcolumn == CONTSETUP_VEHICLE_COLUMN && m_nSelectedContSetupColumn == CONTSETUP_VEHICLE_COLUMN) {\n\n\t\t\tif (optionIdx == m_nSelectedListRow && controllerAction != -1 && controllerAction != -2) {\n\t\t\t\tm_CurrCntrlAction = controllerAction; \n\t\t\t\tif (m_bWaitingForNewKeyBind) {\n\t\t\t\t\tstatic bool showWaitingText = false;\n\t\t\t\t\tif (bindingsForThisOpt > 0) {\n\t\t\t\t\t\twchar *seperator = TheText.Get(\"FEC_IBT\");\n\t\t\t\t\t\tCFont::PrintString(nextX, nextY, seperator);\n\t\t\t\t\t\tnextX += CFont::GetStringWidth(seperator, true) + bindingMargin;\n\t\t\t\t\t}\n\t\t\t\t\tstatic PauseModeTime lastWaitingTextFlash = 0;\n\t\t\t\t\tif (CTimer::GetTimeInMillisecondsPauseMode() - lastWaitingTextFlash > 150) {\n\t\t\t\t\t\tshowWaitingText = !showWaitingText;\n\t\t\t\t\t\tlastWaitingTextFlash = CTimer::GetTimeInMillisecondsPauseMode();\n\t\t\t\t\t}\n\t\t\t\t\tif (showWaitingText) {\n\t\t\t\t\t\tCFont::SetColor(CRGBA(255, 255, 255, FadeIn(255)));\n\t\t\t\t\t\tCFont::PrintString(nextX, nextY, TheText.Get(\"FEC_QUE\")); // \"???\"\n\t\t\t\t\t}\n\t\t\t\t\tif (m_bKeyChangeNotProcessed)\n\t\t\t\t\t\tDisplayHelperText(\"FET_CIG\");\n\t\t\t\t\telse\n\t\t\t\t\t\tDisplayHelperText(\"FET_RIG\");\n\n\t\t\t\t\tSET_FONT_FOR_LIST_ITEM\n\n\t\t\t\t\tm_bKeyIsOK = true;\n\t\t\t\t} else {\n\t\t\t\t\tDisplayHelperText(\"FET_CIG\");\n\t\t\t\t\tSET_FONT_FOR_LIST_ITEM\n\n\t\t\t\t\tm_bKeyIsOK = false;\n\t\t\t\t\tm_bKeyChangeNotProcessed = false;\n\t\t\t\t}\n\t\t\t} else if (optionIdx == m_nSelectedListRow) {\n\t\t\t\tDisplayHelperText(\"FET_EIG\");\n\t\t\t\tSET_FONT_FOR_LIST_ITEM\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nCMenuManager::DrawControllerScreenExtraText(int yStart, int xStart, int lineHeight)\n{\n\tint extraTextStart = GetStartOptionsCntrlConfigScreens();\n\tint numOpts = GetNumOptionsCntrlConfigScreens();\n\tint spacing = MENU_X(10.0f);\n\tfor (int i = extraTextStart; i < extraTextStart + numOpts; i++) {\n\t\tint numTextsPrinted = 0;\n\t\tint nextX = xStart;\n\t\tfor (int j = 1; j < 5; j++) {\n\t\t\twchar *text = ControlsManager.GetControllerSettingTextWithOrderNumber((e_ControllerAction)i, (eContSetOrder)j);\n\t\t\tif (text)\n\t\t\t\t++numTextsPrinted;\n\n\t\t\tif (text) {\n\t\t\t\t// Seperator\n\t\t\t\tif (numTextsPrinted > 1) {\n\t\t\t\t\tCFont::PrintString(nextX, MENU_Y(yStart), TheText.Get(\"FEC_IBT\"));\n\t\t\t\t\tnextX = CFont::GetStringWidth(TheText.Get(\"FEC_IBT\"), true) + spacing + nextX;\n\t\t\t\t}\n\t\t\t\tCFont::PrintString(nextX, MENU_Y(yStart), text);\n\t\t\t}\n\t\t\tif (text)\n\t\t\t\tnextX = CFont::GetStringWidth(text, true) + spacing + nextX;\n\t\t}\n\t\tif (m_nCurrOption == i - extraTextStart && m_bWaitingForNewKeyBind) {\n\t\t\tstatic bool waitingTextVisible = false;\n\n\t\t\t// Seperator\n\t\t\tif (numTextsPrinted > 0) {\n\t\t\t\tCFont::PrintString(nextX, MENU_Y(yStart), TheText.Get(\"FEC_IBT\"));\n\t\t\t\tnextX = CFont::GetStringWidth(TheText.Get(\"FEC_IBT\"), true) + spacing + nextX;\n\t\t\t}\n\t\t\tstatic PauseModeTime lastStateChange = 0;\n\t\t\tif (CTimer::GetTimeInMillisecondsPauseMode() - lastStateChange > 150) {\n\t\t\t\twaitingTextVisible = !waitingTextVisible;\n\t\t\t\tlastStateChange = CTimer::GetTimeInMillisecondsPauseMode();\n\t\t\t}\n\t\t\tif (waitingTextVisible) {\n\t\t\t\tCFont::SetColor(CRGBA(255, 255, 0, FadeIn(255)));\n\t\t\t\tCFont::PrintString(nextX, MENU_Y(yStart), TheText.Get(\"FEC_QUE\"));\n\t\t\t\tCFont::SetColor(CRGBA(LABEL_COLOR.r, LABEL_COLOR.g, LABEL_COLOR.b, FadeIn(255)));\n\t\t\t}\n\t\t}\n\t\tyStart += lineHeight;\n\t}\n\twchar *error = nil;\n\tif (DisplayComboButtonErrMsg)\n\t\terror = ControlsManager.GetButtonComboText((e_ControllerAction)(m_nCurrOption + extraTextStart));\n\n\tif (error) {\n\t\tCFont::SetColor(CRGBA(233, 22, 159, 255));\n\t\tCFont::PrintString(xStart, MENU_Y(yStart + 10), error);\n\t}\n}\n\nvoid\nCMenuManager::DrawControllerSetupScreen()\n{\n\tfloat rowHeight;\n\tswitch (m_ControlMethod) {\n\t\tcase CONTROL_STANDARD:\n\t\t\trowHeight = CONTSETUP_STANDARD_ROW_HEIGHT;\n\t\t\tbreak;\n\t\tcase CONTROL_CLASSIC:\n\t\t\trowHeight = CONTSETUP_CLASSIC_ROW_HEIGHT;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\tRESET_FONT_FOR_NEW_PAGE\n\tSET_FONT_FOR_MENU_HEADER\n\n\t// Shadow\n\tCFont::SetColor(CRGBA(30, 30, 30, FadeIn(255)));\n\n\tif (m_ControlMethod == CONTROL_STANDARD)\n\t\tCFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(MENUHEADER_POS_X) - MENU_X(7.f), SCREEN_SCALE_Y(MENUHEADER_POS_Y + 7.f), TheText.Get(\"FET_STI\"));\n\telse if (m_ControlMethod == CONTROL_CLASSIC)\n\t\tCFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(MENUHEADER_POS_X) - MENU_X(7.f), SCREEN_SCALE_Y(MENUHEADER_POS_Y + 7.f), TheText.Get(\"FET_CTI\"));\n\n\t// Real header\n\tCFont::SetColor(CRGBA(HEADER_COLOR.r, HEADER_COLOR.g, HEADER_COLOR.b, FadeIn(255)));\n\n\tif (m_ControlMethod == CONTROL_STANDARD)\n\t\tCFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(MENUHEADER_POS_X), SCREEN_SCALE_Y(MENUHEADER_POS_Y), TheText.Get(\"FET_STI\"));\n\telse if (m_ControlMethod == CONTROL_CLASSIC)\n\t\tCFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(MENUHEADER_POS_X), SCREEN_SCALE_Y(MENUHEADER_POS_Y), TheText.Get(\"FET_CTI\"));\n\n\twchar *actionTexts[33];\n\tactionTexts[0] = TheText.Get(\"FEC_FIR\");\n\tactionTexts[1] = TheText.Get(\"FEC_NWE\");\n\tactionTexts[2] = TheText.Get(\"FEC_PWE\");\n\tactionTexts[3] = TheText.Get(\"FEC_FOR\");\n\tactionTexts[4] = TheText.Get(\"FEC_BAC\");\n\tactionTexts[5] = TheText.Get(\"FEC_LEF\");\n\tactionTexts[6] = TheText.Get(\"FEC_RIG\");\n\tactionTexts[7] = TheText.Get(\"FEC_ZIN\");\n\tactionTexts[8] = TheText.Get(\"FEC_ZOT\");\n\tactionTexts[9] = TheText.Get(\"FEC_EEX\");\n\tactionTexts[10] = TheText.Get(\"FEC_RAD\");\n\tactionTexts[11] = TheText.Get(\"FEC_HRN\");\n\tactionTexts[12] = TheText.Get(\"FEC_SUB\");\n\tactionTexts[13] = TheText.Get(\"FEC_CMR\");\n\tactionTexts[14] = TheText.Get(\"FEC_JMP\");\n\tactionTexts[15] = TheText.Get(\"FEC_SPN\");\n\tactionTexts[16] = TheText.Get(\"FEC_HND\");\n\tactionTexts[17] = TheText.Get(\"FEC_TAR\");\n\tactionTexts[18] = TheText.Get(\"FEC_CRO\");\n\tactionTexts[19] = TheText.Get(\"FEC_ANS\");\n\tif (m_ControlMethod == CONTROL_CLASSIC) {\n\t\tactionTexts[20] = TheText.Get(\"FEC_TFL\");\n\t\tactionTexts[21] = TheText.Get(\"FEC_TFR\");\n\t\tactionTexts[22] = TheText.Get(\"FEC_TFU\");\n\t\tactionTexts[23] = TheText.Get(\"FEC_TFD\");\n\t\tactionTexts[24] = TheText.Get(\"FEC_LBA\");\n\t\tactionTexts[25] = TheText.Get(\"FEC_LOL\");\n\t\tactionTexts[26] = TheText.Get(\"FEC_LOR\");\n\t\tactionTexts[27] = TheText.Get(\"FEC_LUD\");\n\t\tactionTexts[28] = TheText.Get(\"FEC_LDU\");\n\t\tactionTexts[29] = TheText.Get(\"FEC_NTR\");\n\t\tactionTexts[30] = TheText.Get(\"FEC_PTT\");\n\t\tactionTexts[31] = TheText.Get(\"FEC_CEN\");\n\t\tactionTexts[32] = nil;\n\t} else {\n\t\tactionTexts[20] = TheText.Get(\"FEC_TFL\");\n\t\tactionTexts[21] = TheText.Get(\"FEC_TFR\");\n\t\tactionTexts[22] = TheText.Get(\"FEC_TFU\");\n\t\tactionTexts[23] = TheText.Get(\"FEC_TFD\");\n\t\tactionTexts[24] = TheText.Get(\"FEC_LBA\");\n\t\tactionTexts[25] = TheText.Get(\"FEC_LOL\");\n\t\tactionTexts[26] = TheText.Get(\"FEC_LOR\");\n\t\tactionTexts[27] = nil;\n\t}\n\n\t// Blue panel background\n\tCSprite2d::DrawRect(CRect(MENU_X_LEFT_ALIGNED(CONTSETUP_LIST_LEFT), MENU_Y(CONTSETUP_LIST_TOP),\n\t\tMENU_X_RIGHT_ALIGNED(CONTSETUP_LIST_RIGHT), SCREEN_SCALE_FROM_BOTTOM(CONTSETUP_LIST_BOTTOM)),\n\t\tCRGBA(LIST_BACKGROUND_COLOR.r, LIST_BACKGROUND_COLOR.g, LIST_BACKGROUND_COLOR.b, FadeIn(LIST_BACKGROUND_COLOR.a)));\n\n\tif (m_nCurrExLayer == HOVEROPTION_LIST)\n\t\tCFont::SetColor(CRGBA(SELECTEDMENUOPTION_COLOR.r, SELECTEDMENUOPTION_COLOR.g, SELECTEDMENUOPTION_COLOR.b, FadeIn(255)));\n\telse\n\t\tCFont::SetColor(CRGBA(MENUOPTION_COLOR.r, MENUOPTION_COLOR.g, MENUOPTION_COLOR.b, FadeIn(255)));\n\n\t// List header\n\tCFont::SetFontStyle(FONT_LOCALE(FONT_HEADING));\n\tCFont::SetScale(MENU_X(MENUACTION_SCALE_MULT), MENU_Y(MENUACTION_SCALE_MULT));\n\tCFont::SetRightJustifyOff();\n\tCFont::SetDropShadowPosition(2);\n\tCFont::SetDropColor(CRGBA(0, 0, 0, FadeIn(255)));\n\tCFont::PrintString(MENU_X_LEFT_ALIGNED(CONTSETUP_COLUMN_2_X), MENU_Y(CONTSETUP_LIST_TOP), TheText.Get(\"FET_CFT\"));\n\tCFont::PrintString(MENU_X_LEFT_ALIGNED(CONTSETUP_COLUMN_3_X), MENU_Y(CONTSETUP_LIST_TOP), TheText.Get(\"FET_CCR\"));\n\tCFont::SetDropShadowPosition(0);\n\tSET_FONT_FOR_LIST_ITEM\n\n\tint yStart;\n\tif (m_ControlMethod == CONTROL_CLASSIC)\n\t\tyStart = CONTSETUP_LIST_TOP + 18;\n\telse\n\t\tyStart = CONTSETUP_LIST_TOP + 21;\n\n\tfloat optionYBottom = yStart + rowHeight;\n\tfor (int i = 0; i < ARRAY_SIZE(actionTexts); ++i) {\n\t\twchar *actionText = actionTexts[i];\n\t\tif (!actionText)\n\t\t\tbreak;\n\n\t\tif (!m_bWaitingForNewKeyBind) {\n\t\t\tif (m_nMousePosX > MENU_X_LEFT_ALIGNED(CONTSETUP_LIST_LEFT - 10.0f) &&\n\t\t\t\tm_nMousePosX < MENU_X_LEFT_ALIGNED(CONTSETUP_COLUMN_3_X + CONTSETUP_BOUND_COLUMN_WIDTH)) {\n\n\t\t\t\tif (m_nMousePosY > MENU_Y(i * rowHeight + yStart) && m_nMousePosY < MENU_Y(i * rowHeight + optionYBottom)) {\n\t\t\t\t\t\tm_nOptionMouseHovering = i;\n\t\t\t\t\t\tif (m_nMouseOldPosX != m_nMousePosX || m_nMouseOldPosY != m_nMousePosY) {\n\t\t\t\t\t\t\tm_nCurrExLayer = HOVEROPTION_LIST;\n\t\t\t\t\t\t\tm_nSelectedListRow = i;\n\n\t\t\t\t\t\t\t// why different number for 3rd column hovering X?? this function is a mess\n#ifdef FIX_BUGS\n\t\t\t\t\t\t\tif (m_nMousePosX > MENU_X_LEFT_ALIGNED(0.0f) && m_nMousePosX < MENU_X_LEFT_ALIGNED(CONTSETUP_COLUMN_2_X + CONTSETUP_BOUND_COLUMN_WIDTH)) {\n#else\n\t\t\t\t\t\t\tif (m_nMousePosX > MENU_X_LEFT_ALIGNED(0.0f) && m_nMousePosX < MENU_X_LEFT_ALIGNED(370.0f)) {\n#endif\n\t\t\t\t\t\t\t\tm_nSelectedContSetupColumn = CONTSETUP_PED_COLUMN;\n#ifdef FIX_BUGS\n\t\t\t\t\t\t\t} else if (m_nMousePosX > MENU_X_LEFT_ALIGNED(CONTSETUP_COLUMN_2_X + CONTSETUP_BOUND_COLUMN_WIDTH) && m_nMousePosX < SCREEN_WIDTH) {\n#else\n\t\t\t\t\t\t\t} else if (m_nMousePosX > MENU_X_LEFT_ALIGNED(370.0f) && m_nMousePosX < SCREEN_WIDTH) {\n#endif\n\t\t\t\t\t\t\t\tm_nSelectedContSetupColumn = CONTSETUP_VEHICLE_COLUMN;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// what??\n\t\t\t\t\t\tif (m_nHoverOption == HOVEROPTION_SKIN) {\n\t\t\t\t\t\t\tif (i == m_nSelectedListRow) {\n\t\t\t\t\t\t\t\tm_nHoverOption = HOVEROPTION_NOT_HOVERING;\n\t\t\t\t\t\t\t\tm_bWaitingForNewKeyBind = true;\n\t\t\t\t\t\t\t\tm_bStartWaitingForKeyBind = true;\n\t\t\t\t\t\t\t\tpControlEdit = &m_KeyPressedCode;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else\n\t\t\t\t\t\t\tm_nHoverOption = HOVEROPTION_NOT_HOVERING;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (m_nSelectedListRow != i)\n\t\t\tCFont::SetColor(CRGBA(MENUOPTION_COLOR.r, MENUOPTION_COLOR.g, MENUOPTION_COLOR.b, FadeIn(255)));\n\t\telse if (m_nCurrExLayer == HOVEROPTION_LIST)\n\t\t\tCFont::SetColor(CRGBA(SELECTEDMENUOPTION_COLOR.r, SELECTEDMENUOPTION_COLOR.g, SELECTEDMENUOPTION_COLOR.b, FadeIn(255)));\n\n\t\tCFont::SetRightJustifyOff();\n\t\tif (m_PrefsLanguage == LANGUAGE_GERMAN && (i == 20 || i == 21 || i == 22 || i == 23))\n\t\t\tCFont::SetScale(MENU_X(0.32f), MENU_Y(LISTITEM_Y_SCALE));\n\t\telse\n\t\t\tCFont::SetScale(MENU_X(LISTITEM_X_SCALE), MENU_Y(LISTITEM_Y_SCALE));\n\n\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(CONTSETUP_COLUMN_1_X), MENU_Y(i * rowHeight + yStart), actionText);\n\t}\n\tDrawControllerBound(yStart, MENU_X_LEFT_ALIGNED(CONTSETUP_COLUMN_2_X), rowHeight, CONTSETUP_PED_COLUMN);\n\tDrawControllerBound(yStart, MENU_X_LEFT_ALIGNED(CONTSETUP_COLUMN_3_X), rowHeight, CONTSETUP_VEHICLE_COLUMN);\n\n\tif (!m_bWaitingForNewKeyBind) {\n\t\tCFont::SetScale(MENU_X(BIGTEXT_X_SCALE), MENU_Y(BIGTEXT_Y_SCALE));\n\n\t\tif ((m_nMousePosX > MENU_X_RIGHT_ALIGNED(CONTSETUP_BACK_RIGHT) - CFont::GetStringWidth(TheText.Get(\"FEDS_TB\"), true)\n\t\t\t&& m_nMousePosX < MENU_X_RIGHT_ALIGNED(CONTSETUP_BACK_RIGHT) && m_nMousePosY > SCREEN_SCALE_FROM_BOTTOM(CONTSETUP_BACK_BOTTOM)\n\t\t\t&& m_nMousePosY < SCREEN_SCALE_FROM_BOTTOM(CONTSETUP_BACK_BOTTOM - CONTSETUP_BACK_HEIGHT)) || m_nCurrExLayer == HOVEROPTION_BACK) {\n\t\t\tm_nHoverOption = HOVEROPTION_BACK;\n\n\t\t} else if (m_nMousePosX > MENU_X_LEFT_ALIGNED(CONTSETUP_LIST_LEFT - 10.0f) && m_nMousePosX < MENU_X_LEFT_ALIGNED(CONTSETUP_COLUMN_3_X + CONTSETUP_BOUND_COLUMN_WIDTH)\n\t\t\t&& m_nMousePosY > MENU_Y(CONTSETUP_LIST_TOP - 10.0f) && m_nMousePosY < SCREEN_SCALE_FROM_BOTTOM(CONTSETUP_LIST_BOTTOM)) {\n\t\t\tm_nHoverOption = HOVEROPTION_LIST;\n\n\t\t} else {\n\t\t\tm_nHoverOption = HOVEROPTION_NOT_HOVERING;\n\t\t}\n\t}\n\n\t// Back button and it's shadow\n\tCFont::SetFontStyle(FONT_LOCALE(FONT_HEADING));\n\tCFont::SetScale(MENU_X(BIGTEXT_X_SCALE), MENU_Y(BIGTEXT_Y_SCALE));\n\tCFont::SetRightJustifyOn();\n\tCFont::SetDropShadowPosition(2);\n\tCFont::SetDropColor(CRGBA(0, 0, 0, FadeIn(255)));\n\tCFont::SetColor(CRGBA(MENUOPTION_COLOR.r, MENUOPTION_COLOR.g, MENUOPTION_COLOR.b, FadeIn(255)));\n\tCFont::PrintString(MENU_X_RIGHT_ALIGNED(CONTSETUP_BACK_RIGHT - 2.0f), SCREEN_SCALE_FROM_BOTTOM(CONTSETUP_BACK_BOTTOM - 4.0f), TheText.Get(\"FEDS_TB\"));\n}\n\nvoid\nCMenuManager::DrawFrontEnd()\n{\n\tCFont::SetAlphaFade(255.0f);\n\tCSprite2d::InitPerFrame();\n\tCFont::InitPerFrame();\n\tSetFrontEndRenderStates();\n\tm_NoEmptyBinding = true;\n\n\tif (m_nCurrScreen == MENUPAGE_NONE) {\n\t\tif (m_bGameNotLoaded) {\n\t\t\tm_nCurrScreen = MENUPAGE_START_MENU;\n\t\t} else {\n\t\t\tm_nCurrScreen = MENUPAGE_PAUSE_MENU;\n\t\t}\n\t\tSETUP_SCROLLING(m_nCurrScreen)\n\t}\n\n\tif (m_nCurrOption == 0 && aScreens[m_nCurrScreen].m_aEntries[0].m_Action == MENUACTION_LABEL)\n\t\tm_nCurrOption = 1;\n\n\tif (m_firstStartCounter == 255 && m_nMenuFadeAlpha == 255)\n\t\tbMenuChangeOngoing = false;\n\n\tDrawBackground(false);\n}\n\nvoid\nCMenuManager::DrawBackground(bool transitionCall)\n{\n\tif (!m_bSpritesLoaded)\n\t\treturn;\n\n\tSetFrontEndRenderStates();\n\n\tif (m_firstStartCounter < 255) {\n\t\tCSprite2d::DrawRect(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(0, 0, 0, 255));\n\t}\n\n\tif (m_nMenuFadeAlpha != 0) {\n\n\t\tif (m_nMenuFadeAlpha < 255) {\n\n\t\t\tmenuBg.Translate(m_nMenuFadeAlpha);\n\t\t\tSetFrontEndRenderStates();\n\t\t\tm_aFrontEndSprites[MENUSPRITE_BACKGROUND].Draw(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(255, 255, 255, FadeIn(255)));\n\t\t\tif (m_nCurrScreen == MENUPAGE_MAP)\n\t\t\t\tPrintMap();\n\n\t\t\t// Left border\n\t\t\tCSprite2d::Draw2DPolygon(SCREEN_STRETCH_X(menuBg.bottomLeft_x), SCREEN_STRETCH_Y(menuBg.bottomLeft_y), 0.0f, SCREEN_HEIGHT,\n\t\t\t\tSCREEN_STRETCH_X(menuBg.topLeft_x), SCREEN_STRETCH_Y(menuBg.topLeft_y), 0.0f, 0.0f, CRGBA(0, 0, 0, 255));\n\n\t\t\t// Top border\n\t\t\tCSprite2d::Draw2DPolygon(SCREEN_STRETCH_X(menuBg.topRight_x), SCREEN_STRETCH_Y(menuBg.topRight_y), \n\t\t\t\tSCREEN_STRETCH_X(menuBg.topLeft_x), SCREEN_STRETCH_Y(menuBg.topLeft_y), SCREEN_WIDTH, 0.0f, 0.0f, 0.0f, CRGBA(0, 0, 0, 255));\n\n\t\t\t// Bottom border\n\t\t\tCSprite2d::Draw2DPolygon(SCREEN_WIDTH, SCREEN_HEIGHT, 0.0f, SCREEN_HEIGHT, SCREEN_STRETCH_X(menuBg.bottomRight_x), SCREEN_STRETCH_Y(menuBg.bottomRight_y),\n\t\t\t\tSCREEN_STRETCH_X(menuBg.bottomLeft_x), SCREEN_STRETCH_Y(menuBg.bottomLeft_y), CRGBA(0, 0, 0, 255));\n\n\t\t\t// Right border\n\t\t\tCSprite2d::Draw2DPolygon(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_STRETCH_X(menuBg.bottomRight_x), SCREEN_STRETCH_Y(menuBg.bottomRight_y),\n\t\t\t\tSCREEN_WIDTH, 0.0f, SCREEN_STRETCH_X(menuBg.topRight_x), SCREEN_STRETCH_Y(menuBg.topRight_y), CRGBA(0, 0, 0, 255));\n\t\t} else {\n\t\t\tm_nMenuFadeAlpha = 255;\n\t\t\tm_firstStartCounter = 255;\n\t\t\tm_aFrontEndSprites[MENUSPRITE_BACKGROUND].Draw(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(255, 255, 255, FadeIn(255)));\n\t\t\tif (m_nCurrScreen == MENUPAGE_MAP)\n\t\t\t\tPrintMap();\n\n\t\t\t// Left border\n\t\t\tCSprite2d::Draw2DPolygon(SCREEN_STRETCH_X(menuBg.bottomLeft_x), SCREEN_STRETCH_Y(menuBg.bottomLeft_y), 0.0f, SCREEN_HEIGHT,\n\t\t\t\tSCREEN_STRETCH_X(menuBg.topLeft_x), SCREEN_STRETCH_Y(menuBg.topLeft_y), 0.0f, 0.0f, CRGBA(0, 0, 0, 255));\n\n\t\t\t// Top border\n\t\t\tCSprite2d::Draw2DPolygon(SCREEN_STRETCH_X(menuBg.topRight_x), SCREEN_STRETCH_Y(menuBg.topRight_y),\n\t\t\t\tSCREEN_STRETCH_X(menuBg.topLeft_x), SCREEN_STRETCH_Y(menuBg.topLeft_y), SCREEN_WIDTH, 0.0f, 0.0f, 0.0f, CRGBA(0, 0, 0, 255));\n\n\t\t\t// Bottom border\n\t\t\tCSprite2d::Draw2DPolygon(SCREEN_WIDTH, SCREEN_HEIGHT, 0.0f, SCREEN_HEIGHT, SCREEN_STRETCH_X(menuBg.bottomRight_x), SCREEN_STRETCH_Y(menuBg.bottomRight_y),\n\t\t\t\tSCREEN_STRETCH_X(menuBg.bottomLeft_x), SCREEN_STRETCH_Y(menuBg.bottomLeft_y), CRGBA(0, 0, 0, 255));\n\n\t\t\t// Right border\n\t\t\tCSprite2d::Draw2DPolygon(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_STRETCH_X(menuBg.bottomRight_x), SCREEN_STRETCH_Y(menuBg.bottomRight_y),\n\t\t\t\tSCREEN_WIDTH, 0.0f, SCREEN_STRETCH_X(menuBg.topRight_x), SCREEN_STRETCH_Y(menuBg.topRight_y), CRGBA(0, 0, 0, 255));\n\t\t}\n\t} else {\n\t\tmenuBg.SaveCurrentCoors();\n\t\tswitch (m_nCurrScreen) {\n\t\t\tcase MENUPAGE_STATS:\n\t\t\t\tmenuBg.topLeft_x = 70.0f;\n\t\t\t\tmenuBg.topLeft_y = 75.0f;\n\t\t\t\tmenuBg.topRight_x = 550.0f;\n\t\t\t\tmenuBg.topRight_y = 16.0f;\n\t\t\t\tmenuBg.bottomLeft_x = 74.0f;\n\t\t\t\tmenuBg.bottomLeft_y = 354.0f;\n\t\t\t\tmenuBg.bottomRight_x = 581.0f;\n\t\t\t\tmenuBg.bottomRight_y = 340.0f;\n\t\t\t\tbreak;\n\t\t\tcase MENUPAGE_SOUND_SETTINGS:\n\t\t\t\tmenuBg.topLeft_x = 26.0f;\n\t\t\t\tmenuBg.topLeft_y = 59.0f;\n\t\t\t\tmenuBg.topRight_x = 629.0f;\n\t\t\t\tmenuBg.topRight_y = 29.0f;\n\t\t\t\tmenuBg.bottomLeft_x = 15.0f;\n\t\t\t\tmenuBg.bottomLeft_y = 438.0f;\n\t\t\t\tmenuBg.bottomRight_x = 610.0f;\n\t\t\t\tmenuBg.bottomRight_y = 410.0f;\n\t\t\t\tbreak;\n\t\t\tcase MENUPAGE_SKIN_SELECT:\n\t\t\tcase MENUPAGE_KEYBOARD_CONTROLS:\n\t\t\t\tmenuBg.topLeft_x = 14.0f;\n\t\t\t\tmenuBg.topLeft_y = 39.0f;\n\t\t\t\tmenuBg.topRight_x = 636.0f;\n\t\t\t\tmenuBg.topRight_y = 29.0f;\n\t\t\t\tmenuBg.bottomLeft_x = 15.0f;\n\t\t\t\tmenuBg.bottomLeft_y = 426.0f;\n\t\t\t\tmenuBg.bottomRight_x = 630.0f;\n\t\t\t\tmenuBg.bottomRight_y = 398.0f;\n\t\t\t\tbreak;\n\t\t\tcase MENUPAGE_BRIEFS:\n\t\t\tcase MENUPAGE_DISPLAY_SETTINGS:\n\t\t\tcase MENUPAGE_MAP:\n\t\t\tcase MENUPAGE_CHOOSE_LOAD_SLOT:\n\t\t\tcase MENUPAGE_CHOOSE_DELETE_SLOT:\n\t\t\tcase MENUPAGE_CHOOSE_SAVE_SLOT:\n\t\t\tcase MENUPAGE_MOUSE_CONTROLS:\n\t\t\t\tmenuBg.topLeft_x = 26.0f;\n\t\t\t\tmenuBg.topLeft_y = 59.0f;\n\t\t\t\tmenuBg.topRight_x = 629.0f;\n\t\t\t\tmenuBg.topRight_y = 29.0f;\n\t\t\t\tmenuBg.bottomLeft_x = 15.0f;\n\t\t\t\tmenuBg.bottomLeft_y = 426.0f;\n\t\t\t\tmenuBg.bottomRight_x = 610.0f;\n\t\t\t\tmenuBg.bottomRight_y = 398.0f;\n\t\t\t\tbreak;\n\t\t\tdefault:\n#ifdef CUSTOM_FRONTEND_OPTIONS\n\t\t\t\tif (aScreens[m_nCurrScreen].layout && aScreens[m_nCurrScreen].layout->noInvasiveBorders) {\n\t\t\t\t\t// Taken from the case above\n\t\t\t\t\tmenuBg.topLeft_x = 26.0f;\n\t\t\t\t\tmenuBg.topLeft_y = 59.0f;\n\t\t\t\t\tmenuBg.topRight_x = 629.0f;\n\t\t\t\t\tmenuBg.topRight_y = 29.0f;\n\t\t\t\t\tmenuBg.bottomLeft_x = 15.0f;\n\t\t\t\t\tmenuBg.bottomLeft_y = 426.0f;\n\t\t\t\t\tmenuBg.bottomRight_x = 610.0f;\n\t\t\t\t\tmenuBg.bottomRight_y = 398.0f;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n#endif\n\t\t\t\tmenuBg.topLeft_x = CGeneral::GetRandomNumber() % 40 + 65;\n\t\t\t\tmenuBg.topLeft_y = CGeneral::GetRandomNumber() % 40 + 21;\n\t\t\t\tmenuBg.topRight_x = CGeneral::GetRandomNumber() % 40 + 568;\n\t\t\t\tmenuBg.topRight_y = CGeneral::GetRandomNumber() % 40 + 44;\n\t\t\t\tmenuBg.bottomLeft_x = CGeneral::GetRandomNumber() % 40 + 36;\n\t\t\t\tmenuBg.bottomLeft_y = CGeneral::GetRandomNumber() % 40 + 382;\n\t\t\t\tmenuBg.bottomRight_x = CGeneral::GetRandomNumber() % 40 + 593;\n\t\t\t\tmenuBg.bottomRight_y = CGeneral::GetRandomNumber() % 40 + 342;\n\t\t\t\tbreak;\n\t\t}\n\n\t\tmenuBg.UpdateMultipliers();\n\t\tif (m_firstStartCounter == 255)\n\t\t\tm_nOptionHighlightTransitionBlend = 0;\n\t}\n\n\tstatic PauseModeTime LastFade = 0;\n\n\tif (m_nMenuFadeAlpha < 255) {\n\t\tstatic uint8 forceFadeInCounter = 0;\t\n\t\tif (CTimer::GetTimeInMillisecondsPauseMode() - LastFade > 30\n#ifndef FIX_HIGH_FPS_BUGS_ON_FRONTEND // Dirty dirty hack\n\t\t\t|| forceFadeInCounter > 30\n#endif\n\t\t\t) {\n\t\t\tm_nMenuFadeAlpha += 20;\n\t\t\tif (m_firstStartCounter < 255) {\n\t\t\t\tm_firstStartCounter = Min(m_firstStartCounter + 20, 255);\n\t\t\t}\n\t\t\tLastFade = CTimer::GetTimeInMillisecondsPauseMode();\n\t\t}\n\t\tforceFadeInCounter++;\n\t} else if (m_nMenuFadeAlpha > 255)\n\t\tm_nMenuFadeAlpha = 255;\n\n\tif (!transitionCall && m_firstStartCounter == 255) {\n\t\tint actualAlpha = m_nMenuFadeAlpha;\n\t\tif (actualAlpha < 255) {\n\t\t\tint actualScreen = m_nCurrScreen;\n\t\t\tSetFrontEndRenderStates();\n\t\t\tm_nCurrScreen = m_nPrevScreen;\n\t\t\tm_nMenuFadeAlpha = 255 - m_nMenuFadeAlpha;\n\t\t\tswitch (m_nCurrScreen) {\n\t\t\t\tcase MENUPAGE_SKIN_SELECT:\n\t\t\t\t\tDrawPlayerSetupScreen(false);\n\t\t\t\t\tbreak;\n\t\t\t\tcase MENUPAGE_KEYBOARD_CONTROLS:\n\t\t\t\t\tDrawControllerSetupScreen();\n\t\t\t\t\tbreak;\n\t\t\t\tcase MENUPAGE_OUTRO:\n\t\t\t\t\tDrawQuitGameScreen();\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tDrawStandardMenus(false);\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tm_nCurrScreen = actualScreen;\n\t\t\tm_nMenuFadeAlpha = actualAlpha;\n\t\t}\n\t}\n\n\tswitch (m_nCurrScreen) {\n\t\tcase MENUPAGE_SKIN_SELECT:\n\t\t\tDrawPlayerSetupScreen(true);\n\t\t\tbreak;\n\t\tcase MENUPAGE_KEYBOARD_CONTROLS:\n\t\t\tDrawControllerSetupScreen();\n\t\t\tbreak;\n\t\tcase MENUPAGE_OUTRO:\n\t\t\tDrawQuitGameScreen();\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tDrawStandardMenus(true);\n\t\t\tbreak;\n\t}\n\n\tCFont::DrawFonts();\n\tSetFrontEndRenderStates();\n\n\tif (m_nCurrScreen != MENUPAGE_OUTRO)\n\t\tif (m_firstStartCounter == 255) {\n\t\t\tm_aFrontEndSprites[MENUSPRITE_VCLOGO].Draw(CRect(SCREEN_STRETCH_X(27.0f), MENU_Y(8.0f), SCREEN_STRETCH_X(27.0f) + MENU_X(130.f), MENU_Y(138.0f)), CRGBA(255, 255, 255, 255));\n\t\t} else {\n\t\t\tm_aFrontEndSprites[MENUSPRITE_VCLOGO].Draw(CRect(SCREEN_STRETCH_X(27.0f), MENU_Y(8.0f), SCREEN_STRETCH_X(27.0f) + MENU_X(130.f), MENU_Y(138.0f)), CRGBA(255, 255, 255, FadeIn(255)));\n\t\t}\n\n\tif (m_ShowEmptyBindingError) {\n\t\tstatic PauseModeTime lastBindingError = CTimer::GetTimeInMillisecondsPauseMode();\n\t\tstatic bool bindingErrorShown = false;\n\t\tif (bindingErrorShown) {\n\t\t\tlastBindingError = CTimer::GetTimeInMillisecondsPauseMode();\n\t\t\tbindingErrorShown = false;\n\t\t}\n\t\tSmallMessageScreen(\"FEC_ERI\");\n\t\tCFont::DrawFonts();\n\t\tif (CTimer::GetTimeInMillisecondsPauseMode() - lastBindingError > 4000) {\n\t\t\tm_ShowEmptyBindingError = false;\n\t\t\tbindingErrorShown = true;\n\t\t}\n\t}\n\n\tif (m_bShowMouse) {\n\t\tCRect mouse(0.0f, 0.0f, MENU_X(35.0f), MENU_Y(35.0f));\n\t\tCRect shad(MENU_X(10.0f), MENU_Y(3.0f), MENU_X(45.0f), MENU_Y(38.0f));\n\n\t\tmouse.Translate(m_nMousePosX, m_nMousePosY);\n\t\tshad.Translate(m_nMousePosX, m_nMousePosY);\n\t\tm_aFrontEndSprites[MENUSPRITE_MOUSE].Draw(shad, CRGBA(100, 100, 100, 50));\n\t\tm_aFrontEndSprites[MENUSPRITE_MOUSE].Draw(mouse, CRGBA(255, 255, 255, 255));\n\t}\n}\n\nvoid\nCMenuManager::DrawPlayerSetupScreen(bool activeScreen)\n{\n\tRESET_FONT_FOR_NEW_PAGE\n\n\t// lstrcpy's changed with strcpy\n\tif (!m_bSkinsEnumerated) {\n\t\tOutputDebugString(\"Enumerating skin filenames from skins...\");\n\t\tm_pSkinListHead.nextSkin = nil;\n\t\tm_pSelectedSkin = &m_pSkinListHead;\n\t\tm_pSelectedSkin->nextSkin = new tSkinInfo;\n\t\tm_pSelectedSkin = m_pSelectedSkin->nextSkin;\n\t\tm_pSelectedSkin->skinId = 0;\n\t\tstrcpy(m_pSelectedSkin->skinNameOriginal, DEFAULT_SKIN_NAME);\n\t\tstrcpy(m_pSelectedSkin->skinNameDisplayed, UnicodeToAscii(TheText.Get(\"FET_DSN\")));\n\t\tint nextSkinId = 1;\n\t\tm_pSelectedSkin->nextSkin = nil;\n\n\t\tWIN32_FIND_DATA FindFileData;\n\t\tSYSTEMTIME SystemTime;\n\t\tHANDLE handle = FindFirstFile(\"skins\\\\*.bmp\", &FindFileData);\n\t\tfor (int i = 1; handle != INVALID_HANDLE_VALUE && i; i = FindNextFile(handle, &FindFileData)) {\n\t\t\tif (strcmp(FindFileData.cFileName, DEFAULT_SKIN_NAME) != 0) {\n\t\t\t\tm_pSelectedSkin->nextSkin = new tSkinInfo;\n\t\t\t\tm_pSelectedSkin = m_pSelectedSkin->nextSkin;\n\t\t\t\tm_pSelectedSkin->skinId = nextSkinId;\n\t\t\t\tstrcpy(m_pSelectedSkin->skinNameOriginal, FindFileData.cFileName);\n\t\t\t\tstrcpy(m_pSelectedSkin->skinNameDisplayed, FindFileData.cFileName);\n\t\t\t\tFileTimeToSystemTime(&FindFileData.ftLastWriteTime, &SystemTime);\n\t\t\t\tGetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &SystemTime, 0, m_pSelectedSkin->date, 255);\n\t\t\t\t++nextSkinId;\n\t\t\t\tm_pSelectedSkin->nextSkin = nil;\n\t\t\t}\n\t\t}\n\t\tFindClose(handle);\n\t\tm_nSkinsTotal = nextSkinId;\n\t\tchar nameTemp[256];\n\t\tfor (m_pSelectedSkin = m_pSkinListHead.nextSkin; m_pSelectedSkin; m_pSelectedSkin = m_pSelectedSkin->nextSkin) {\n\t\t\t// Drop extension\n\t\t\tint oldLength = (int)strlen(m_pSelectedSkin->skinNameDisplayed);\n\t\t\tm_pSelectedSkin->skinNameDisplayed[oldLength - 4] = '\\0';\n\t\t\tm_pSelectedSkin->skinNameOriginal[oldLength - 4] = '\\0';\n\n\t\t\t// Fill to 40 bytes-39 chars, idk why. This is done in sepearate function in game.\n\t\t\tstrncpy(nameTemp, m_pSelectedSkin->skinNameDisplayed, 39); // game doesn't do that, but in our day strncpy to same string is forbidden\n\t\t\tstrncpy(m_pSelectedSkin->skinNameDisplayed, nameTemp, 39);\n\t\t\tif (oldLength - 4 > 39)\n\t\t\t\tm_pSelectedSkin->skinNameDisplayed[39] = '\\0';\n\n\t\t\t// Make string lowercase, except first letter\n\t\t\tstrlwr(m_pSelectedSkin->skinNameDisplayed);\n\t\t\tstrncpy(nameTemp, m_pSelectedSkin->skinNameDisplayed, 1);\n\t\t\tstrupr(nameTemp);\n\t\t\tstrncpy(m_pSelectedSkin->skinNameDisplayed, nameTemp, 1);\n\n\t\t\t// Change some chars\n#ifdef FIX_BUGS\n\t\t\tfor (int k = 0; m_pSelectedSkin->skinNameDisplayed[k] != '\\0'; ++k) {\n#else\n\t\t\tfor (int k = 0; m_pSelectedSkin->skinNameOriginal[k] != '\\0'; ++k) {\n#endif\n\t\t\t\tif (!strncmp(&m_pSelectedSkin->skinNameDisplayed[k], \"_\", 1))\n\t\t\t\t\tstrncpy(&m_pSelectedSkin->skinNameDisplayed[k], \" \", 1);\n\t\t\t\tif (!strncmp(&m_pSelectedSkin->skinNameDisplayed[k], \"@\", 1))\n\t\t\t\t\tstrncpy(&m_pSelectedSkin->skinNameDisplayed[k], \" \", 1);\n\t\t\t\tif (!strncmp(&m_pSelectedSkin->skinNameDisplayed[k], \"{\", 1))\n\t\t\t\t\tstrncpy(&m_pSelectedSkin->skinNameDisplayed[k], \"(\", 1);\n\t\t\t\tif (!strncmp(&m_pSelectedSkin->skinNameDisplayed[k], \"}\", 1))\n\t\t\t\t\tstrncpy(&m_pSelectedSkin->skinNameDisplayed[k], \")\", 1);\n\t\t\t\tif (!strncmp(&m_pSelectedSkin->skinNameDisplayed[k], \"£\", 1))\n\t\t\t\t\tstrncpy(&m_pSelectedSkin->skinNameDisplayed[k], \"$\", 1);\n\t\t\t}\n\n\t\t\t// Make letters after whitespace uppercase\n\t\t\tfor (int l = 0; m_pSelectedSkin->skinNameDisplayed[l] != '\\0'; ++l) {\n\t\t\t\tif (!strncmp(&m_pSelectedSkin->skinNameDisplayed[l], \" \", 1)) {\n\t\t\t\t\tif (m_pSelectedSkin->skinNameDisplayed[l + 1]) {\n\t\t\t\t\t\tstrncpy(nameTemp, &m_pSelectedSkin->skinNameDisplayed[l + 1], 1);\n\t\t\t\t\t\tstrupr(nameTemp);\n\t\t\t\t\t\tstrncpy(&m_pSelectedSkin->skinNameDisplayed[l + 1], nameTemp, 1);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tOutputDebugString(\"Finished enumerating skin files.\");\n\t\tm_bSkinsEnumerated = true;\n\t}\n\tCSprite2d::DrawRect(CRect(MENU_X_LEFT_ALIGNED(PLAYERSETUP_LIST_LEFT), MENU_Y(PLAYERSETUP_LIST_TOP),\n\t\tMENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT), SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM)), CRGBA(LIST_BACKGROUND_COLOR.r, LIST_BACKGROUND_COLOR.g, LIST_BACKGROUND_COLOR.b, FadeIn(LIST_BACKGROUND_COLOR.a)));\n\n\tSET_FONT_FOR_MENU_HEADER\n\tCFont::SetColor(CRGBA(30, 30, 30, FadeIn(255)));\n\tCFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(MENUHEADER_POS_X) - MENU_X(7.f), SCREEN_SCALE_Y(MENUHEADER_POS_Y + 7.f), TheText.Get(\"FET_PS\"));\n\n\tCFont::SetColor(CRGBA(HEADER_COLOR.r, HEADER_COLOR.g, HEADER_COLOR.b, FadeIn(255)));\n\tCFont::PrintString(SCREEN_STRETCH_FROM_RIGHT(MENUHEADER_POS_X), SCREEN_SCALE_Y(MENUHEADER_POS_Y), TheText.Get(\"FET_PS\"));\n\n\t// Header (Skin - Date)\n\tif (m_nCurrExLayer == HOVEROPTION_LIST) {\n\t\tCFont::SetColor(CRGBA(SELECTEDMENUOPTION_COLOR.r, SELECTEDMENUOPTION_COLOR.g, SELECTEDMENUOPTION_COLOR.b, FadeIn(255)));\n\t} else {\n\t\tCFont::SetColor(CRGBA(MENUOPTION_COLOR.r, MENUOPTION_COLOR.g, MENUOPTION_COLOR.b, FadeIn(255)));\n\t}\n\tCFont::SetDropShadowPosition(2);\n\tCFont::SetDropColor(CRGBA(0, 0, 0, 255));\n\tCFont::SetScale(MENU_X(MENUACTION_SCALE_MULT), MENU_Y(MENUACTION_SCALE_MULT));\n\tCFont::SetRightJustifyOn();\n\tCFont::PrintString(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_DATE_COLUMN_RIGHT), MENU_Y(PLAYERSETUP_LIST_TOP), TheText.Get(\"FES_DAT\"));\n\tswitch (m_PrefsLanguage) {\n\t\tcase LANGUAGE_FRENCH:\n\t\tcase LANGUAGE_SPANISH:\n\t\t\tCFont::SetScale(MENU_X(0.6f), MENU_Y(MENUACTION_SCALE_MULT));\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tCFont::SetScale(MENU_X(MENUACTION_SCALE_MULT), MENU_Y(MENUACTION_SCALE_MULT));\n\t\t\tbreak;\n\t}\n\tCFont::SetRightJustifyOff();\n\tCFont::PrintString(MENU_X_LEFT_ALIGNED(PLAYERSETUP_SKIN_COLUMN_LEFT), MENU_Y(PLAYERSETUP_LIST_TOP), TheText.Get(\"FES_SKN\"));\n\tCFont::SetDropShadowPosition(0);\n\n\t// Skin list\n\tSET_FONT_FOR_LIST_ITEM\n\tif (m_nSkinsTotal > 0) {\n\t\tfor (m_pSelectedSkin = m_pSkinListHead.nextSkin; m_pSelectedSkin->skinId != m_nFirstVisibleRowOnList;\n\t\t\tm_pSelectedSkin = m_pSelectedSkin->nextSkin);\n\n\t\tint rowTextY = PLAYERSETUP_LIST_BODY_TOP - 1;\n\t\tint orderInVisibles = 0;\n\t\tint rowEndY = PLAYERSETUP_LIST_BODY_TOP + PLAYERSETUP_ROW_HEIGHT + 1;\n\t\tint rowStartY = PLAYERSETUP_LIST_BODY_TOP;\n\t\tfor (int rowIdx = m_nFirstVisibleRowOnList; \n\t\t\trowIdx < m_nFirstVisibleRowOnList + MAX_VISIBLE_LIST_ROW && m_pSelectedSkin; ) {\n\n\t\t\tif (m_nMousePosX > MENU_X_LEFT_ALIGNED(PLAYERSETUP_LIST_LEFT) && m_nMousePosX < MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT)) {\n\t\t\t\tif (m_nMousePosY > MENU_Y(rowStartY) && m_nMousePosY < MENU_Y(rowEndY)) {\n\t\t\t\t\tm_nOptionMouseHovering = rowIdx;\n\t\t\t\t\tif (m_nMouseOldPosX != m_nMousePosX || m_nMouseOldPosY != m_nMousePosY) {\n\t\t\t\t\t\tm_nCurrExLayer = HOVEROPTION_LIST;\n\t\t\t\t\t}\n\t\t\t\t\tif (m_nHoverOption == HOVEROPTION_SKIN) {\n\t\t\t\t\t\tif (rowIdx == m_nSelectedListRow) {\n\t\t\t\t\t\t\tm_nHoverOption = HOVEROPTION_NOT_HOVERING;\n\t\t\t\t\t\t\tif (m_nSkinsTotal > 0) {\n\t\t\t\t\t\t\t\tstrcpy(m_PrefsSkinFile, m_aSkinName);\n\t\t\t\t\t\t\t\tCWorld::Players[0].SetPlayerSkin(m_PrefsSkinFile);\n\t\t\t\t\t\t\t\tSaveSettings();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tm_nCurrExLayer = HOVEROPTION_LIST;\n\t\t\t\t\t\t\tm_nSelectedListRow = rowIdx;\n\t\t\t\t\t\t\tm_nHoverOption = HOVEROPTION_NOT_HOVERING;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Preview skin/change color of row when we focused on another row.\n\t\t\tif (orderInVisibles == m_nSelectedListRow - m_nFirstVisibleRowOnList) {\n\t\t\t\tCFont::SetColor(CRGBA(255, 255, 255, FadeIn(255)));\n\t\t\t\tstatic int lastSelectedSkin = -1;\n\t\t\t\tif (m_nSelectedListRow != lastSelectedSkin) {\n\t\t\t\t\tstrcpy(m_aSkinName, m_pSelectedSkin->skinNameOriginal);\n\t\t\t\t\tCWorld::Players[0].SetPlayerSkin(m_aSkinName);\n\t\t\t\t}\n\t\t\t\tlastSelectedSkin = m_nSelectedListRow;\n\t\t\t} else if (!strcmp(m_PrefsSkinFile, m_pSelectedSkin->skinNameOriginal)) {\n\t\t\t\tCFont::SetColor(CRGBA(255, 255, 155, FadeIn(255)));\n\t\t\t} else {\n\t\t\t\tCFont::SetColor(CRGBA(LIST_OPTION_COLOR.r, LIST_OPTION_COLOR.g, LIST_OPTION_COLOR.b, FadeIn(LIST_OPTION_COLOR.a)));\n\t\t\t}\n\t\t\twchar unicodeTemp[80];\n\t\t\tAsciiToUnicode(m_pSelectedSkin->skinNameDisplayed, unicodeTemp);\n\t\t\tCFont::SetRightJustifyOff();\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(PLAYERSETUP_SKIN_COLUMN_LEFT), MENU_Y(rowTextY), unicodeTemp);\n\n\t\t\t// If not \"Default skin\" option\n\t\t\tif (rowIdx != 0) {\n\t\t\t\tchar dateTemp[32];\n\t\t\t\tsprintf(dateTemp, \"%s\", m_pSelectedSkin->date);\n\t\t\t\tAsciiToUnicode(dateTemp, unicodeTemp);\n\t\t\t\tCFont::SetRightJustifyOn();\n\t\t\t\tCFont::PrintString(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_DATE_COLUMN_RIGHT), MENU_Y(rowTextY), unicodeTemp);\n\t\t\t}\n\t\t\t++orderInVisibles;\n\t\t\trowEndY += PLAYERSETUP_ROW_HEIGHT;\n\t\t\trowStartY += PLAYERSETUP_ROW_HEIGHT;\n\t\t\trowTextY += PLAYERSETUP_ROW_HEIGHT;\n\t\t\t++rowIdx;\n\t\t\tm_pSelectedSkin = m_pSelectedSkin->nextSkin;\n\t\t}\n\t\t// Scrollbar background - it's unchanged since III and still yellowish...\n\t\tCSprite2d::DrawRect(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2), MENU_Y(PLAYERSETUP_LIST_TOP),\n\t\t\tMENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2 - PLAYERSETUP_SCROLLBAR_WIDTH), SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM)), CRGBA(100, 100, 66, FadeIn(205)));\n\t\t\n\t\tfloat scrollbarHeight = SCROLLBAR_MAX_HEIGHT / (m_nSkinsTotal / (float) MAX_VISIBLE_LIST_ROW);\n\t\tfloat scrollbarBottom, scrollbarTop;\n\t\tif (m_nSkinsTotal <= MAX_VISIBLE_LIST_ROW) {\n\t\t\tscrollbarBottom = SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM + PLAYERSETUP_SCROLLBUTTON_HEIGHT + 4.0f);\n\t\t\tscrollbarTop = MENU_Y(PLAYERSETUP_LIST_BODY_TOP);\n\n\t\t\t// Scrollbar shadow\n\t\t\tCSprite2d::DrawRect(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 4), scrollbarTop,\n\t\t\t\tMENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 1 - PLAYERSETUP_SCROLLBAR_WIDTH), scrollbarBottom + MENU_Y(1.0f)), CRGBA(50, 50, 50, FadeIn(255)));\n\t\t} else {\n#ifdef FIX_BUGS\n\t\t\tscrollbarBottom = MENU_Y(PLAYERSETUP_LIST_BODY_TOP - 8 + m_nScrollbarTopMargin + scrollbarHeight);\n\t\t\tscrollbarTop = MENU_Y(PLAYERSETUP_LIST_BODY_TOP + m_nScrollbarTopMargin);\n#else\n\t\t\tscrollbarBottom = MENU_Y(PLAYERSETUP_LIST_BODY_TOP - 4 + m_nScrollbarTopMargin + scrollbarHeight - SCROLLBAR_MAX_HEIGHT / m_nSkinsTotal);\n\t\t\tscrollbarTop = MENU_Y(SCROLLBAR_MAX_HEIGHT / m_nSkinsTotal + PLAYERSETUP_LIST_BODY_TOP - 3 + m_nScrollbarTopMargin);\n#endif\n\t\t\t// Scrollbar shadow\n\t\t\tCSprite2d::DrawRect(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 4), scrollbarTop,\n\t\t\t\tMENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 1 - PLAYERSETUP_SCROLLBAR_WIDTH), scrollbarBottom + MENU_Y(1.0f)),\n\t\t\t\tCRGBA(50, 50, 50, FadeIn(255)));\n\n\t\t}\n\t\t// Scrollbar\n\t\tCSprite2d::DrawRect(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 4), scrollbarTop,\n\t\t\tMENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - PLAYERSETUP_SCROLLBAR_WIDTH), scrollbarBottom),\n\t\t\tCRGBA(SCROLLBAR_COLOR.r, SCROLLBAR_COLOR.g, SCROLLBAR_COLOR.b, FadeIn(255)));\n\n\t\t// FIX: Scroll button dimensions are buggy, because:\n\t\t//\t\t1 - stretches the original image\n\t\t//\t\t2 - leaves gap between button and scrollbar\n\t\tif (m_nHoverOption == HOVEROPTION_CLICKED_SCROLL_UP) {\n#ifdef FIX_BUGS\n\t\t\tm_aFrontEndSprites[MENUSPRITE_UPON].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2), MENU_Y(PLAYERSETUP_LIST_TOP),\n\t\t\t\tMENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2 - PLAYERSETUP_SCROLLBUTTON_TXD_DIMENSION), MENU_Y(PLAYERSETUP_LIST_TOP + PLAYERSETUP_SCROLLBUTTON_TXD_DIMENSION)),\n\t\t\t\tCRGBA(255, 255, 255, FadeIn(255)));\n#else\n\t\t\tm_aFrontEndSprites[MENUSPRITE_UPON].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2), MENU_Y(PLAYERSETUP_LIST_TOP),\n\t\t\t\tMENU_X_RIGHT_ALIGNED(-20.0f), MENU_Y(PLAYERSETUP_LIST_TOP + 58)),\n\t\t\t\tCRGBA(255, 255, 255, FadeIn(255)));\n#endif\n\t\t} else {\n#ifdef FIX_BUGS\n\t\t\tm_aFrontEndSprites[MENUSPRITE_UPOFF].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 3), MENU_Y(PLAYERSETUP_LIST_TOP),\n\t\t\t\tMENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 3 - PLAYERSETUP_SCROLLBUTTON_TXD_DIMENSION), MENU_Y(PLAYERSETUP_LIST_TOP + PLAYERSETUP_SCROLLBUTTON_TXD_DIMENSION)),\n\t\t\t\tCRGBA(255, 255, 255, FadeIn(255)));\n#else\n\t\t\tm_aFrontEndSprites[MENUSPRITE_UPOFF].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 3), MENU_Y(PLAYERSETUP_LIST_TOP),\n\t\t\t\tMENU_X_RIGHT_ALIGNED(-21.0f), MENU_Y(PLAYERSETUP_LIST_TOP + 58)),\n\t\t\t\tCRGBA(255, 255, 255, FadeIn(255)));\n#endif\n\t\t}\n\n\t\tif (m_nHoverOption == HOVEROPTION_CLICKED_SCROLL_DOWN) {\n#ifdef FIX_BUGS\n\t\t\tm_aFrontEndSprites[MENUSPRITE_DOWNON].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2), SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM + PLAYERSETUP_SCROLLBUTTON_HEIGHT + 1),\n\t\t\t\tMENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2 - PLAYERSETUP_SCROLLBUTTON_TXD_DIMENSION), SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM + PLAYERSETUP_SCROLLBUTTON_HEIGHT + 1 - PLAYERSETUP_SCROLLBUTTON_TXD_DIMENSION)),\n\t\t\t\tCRGBA(255, 255, 255, FadeIn(255)));\n#else\n\t\t\tm_aFrontEndSprites[MENUSPRITE_DOWNON].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2), SCREEN_SCALE_FROM_BOTTOM(141.0f),\n\t\t\t\t\tMENU_X_RIGHT_ALIGNED(-20.0f), SCREEN_SCALE_FROM_BOTTOM(83.0f)),\n\t\t\t\tCRGBA(255, 255, 255, FadeIn(255)));\n#endif\n\t\t} else {\n#ifdef FIX_BUGS\n\t\t\tm_aFrontEndSprites[MENUSPRITE_DOWNOFF].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 3), SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM + PLAYERSETUP_SCROLLBUTTON_HEIGHT + 1),\n\t\t\t\tMENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 3 - PLAYERSETUP_SCROLLBUTTON_TXD_DIMENSION), SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM + PLAYERSETUP_SCROLLBUTTON_HEIGHT + 1 - PLAYERSETUP_SCROLLBUTTON_TXD_DIMENSION)),\n\t\t\t\tCRGBA(255, 255, 255, FadeIn(255)));\n#else\n\t\t\tm_aFrontEndSprites[MENUSPRITE_DOWNOFF].Draw(CRect(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 3), SCREEN_SCALE_FROM_BOTTOM(141.0f),\n\t\t\t\tMENU_X_RIGHT_ALIGNED(-21.0f), SCREEN_SCALE_FROM_BOTTOM(83.0f)),\n\t\t\t\tCRGBA(255, 255, 255, FadeIn(255)));\n#endif\n\n\t\t}\n\t\tif (activeScreen)\n\t\t\tCPlayerSkin::RenderFrontendSkinEdit();\n\n\t\t// Big apply button\n\t\tif (strcmp(m_aSkinName, m_PrefsSkinFile) != 0) {\n\t\t\tCFont::SetFontStyle(FONT_LOCALE(FONT_HEADING));\n\t\t\tswitch (m_PrefsLanguage) {\n\t\t\t\tcase LANGUAGE_FRENCH:\n\t\t\t\t\tCFont::SetScale(MENU_X(1.1f), MENU_Y(1.9f));\n\t\t\t\t\tbreak;\n\t\t\t\tcase LANGUAGE_GERMAN:\n\t\t\t\t\tCFont::SetScale(MENU_X(0.85f), MENU_Y(1.9f));\n\t\t\t\t\tbreak;\n\t\t\t\tcase LANGUAGE_ITALIAN:\n\t\t\t\tcase LANGUAGE_SPANISH:\n\t\t\t\t\tCFont::SetScale(MENU_X(1.4f), MENU_Y(1.9f));\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tCFont::SetScale(MENU_X(1.9f), MENU_Y(1.9f));\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tCFont::SetColor(CRGBA(MENUOPTION_COLOR.r, MENUOPTION_COLOR.g, MENUOPTION_COLOR.b, FadeIn(120)));\n\t\t\tCFont::SetRightJustifyOff();\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(24.0f), MENU_Y(220.0f), TheText.Get(\"FET_APP\"));\n\t\t}\n\t\tCFont::SetFontStyle(FONT_LOCALE(FONT_HEADING));\n\n\t\tCFont::SetScale(MENU_X(BIGTEXT_X_SCALE), MENU_Y(BIGTEXT_Y_SCALE));\n\n\t\tif ((m_nMousePosX > MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 1) - CFont::GetStringWidth(TheText.Get(\"FEDS_TB\"), true)\n\t\t\t&& m_nMousePosX < MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 1)\n\t\t\t&& m_nMousePosY > SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM - 3)\n\t\t\t&& m_nMousePosY < SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM - 26))\n\t\t\t|| m_nCurrExLayer == HOVEROPTION_BACK) {\n\n\t\t\tm_nHoverOption = HOVEROPTION_BACK;\n\t\t} else if ((strcmp(m_aSkinName, m_PrefsSkinFile) != 0\n\t\t\t&& m_nMousePosX > MENU_X_LEFT_ALIGNED(PLAYERSETUP_LIST_LEFT)\n\t\t\t&& m_nMousePosX < MENU_X_LEFT_ALIGNED(PLAYERSETUP_LIST_LEFT) + CFont::GetStringWidth(TheText.Get(\"FES_SET\"), true)\n\t\t\t&& m_nMousePosY > SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM - 3)\n\t\t\t&& m_nMousePosY < SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM - 26))\n\t\t\t|| m_nCurrExLayer == HOVEROPTION_USESKIN) {\n\n\t\t\tm_nHoverOption = HOVEROPTION_USESKIN;\n\t\t} else if (m_nMousePosX > MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2)\n\t\t\t&& m_nMousePosX < MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - PLAYERSETUP_SCROLLBAR_WIDTH - 2)\n\t\t\t&& m_nMousePosY > MENU_Y(PLAYERSETUP_LIST_TOP)\n\t\t\t&& m_nMousePosY < MENU_Y(PLAYERSETUP_LIST_BODY_TOP - 3)) {\n\t\t\tif (m_nHoverOption != HOVEROPTION_CLICKED_SCROLL_UP && m_nHoverOption != HOVEROPTION_CLICKED_SCROLL_DOWN)\n\t\t\t\tm_nHoverOption = HOVEROPTION_OVER_SCROLL_UP;\n\n\t\t} else if (m_nMousePosX > MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2)\n\t\t\t&& m_nMousePosX < MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - PLAYERSETUP_SCROLLBAR_WIDTH - 2)\n\t\t\t&& m_nMousePosY > SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM + PLAYERSETUP_SCROLLBUTTON_HEIGHT + 1)\n\t\t\t&& m_nMousePosY < SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM)) {\n\t\t\tif (m_nHoverOption != HOVEROPTION_CLICKED_SCROLL_UP && m_nHoverOption != HOVEROPTION_CLICKED_SCROLL_DOWN)\n\t\t\t\tm_nHoverOption = HOVEROPTION_OVER_SCROLL_DOWN;\n\n\t\t} else if (m_nMousePosX > MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2)\n\t\t\t&& m_nMousePosX < MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - PLAYERSETUP_SCROLLBAR_WIDTH - 2)\n\t\t\t\t&& m_nMousePosY > MENU_Y(PLAYERSETUP_LIST_BODY_TOP - 3)\n#ifdef FIX_BUGS\n\t\t\t\t&& m_nMousePosY < MENU_Y(PLAYERSETUP_LIST_BODY_TOP + m_nScrollbarTopMargin)) {\n#else\n\t\t\t\t&& m_nMousePosY < MENU_Y(SCROLLBAR_MAX_HEIGHT / m_nTotalListRow + PLAYERSETUP_LIST_BODY_TOP - 3 + m_nScrollbarTopMargin)) {\n#endif\n\t\t\tm_nHoverOption = HOVEROPTION_PAGEUP;\n\n\t\t} else if (m_nMousePosX > MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 2)\n\t\t\t&& m_nMousePosX < MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - PLAYERSETUP_SCROLLBAR_WIDTH - 2)\n#ifdef FIX_BUGS\n\t\t\t&& m_nMousePosY > MENU_Y(PLAYERSETUP_LIST_BODY_TOP - 8 + m_nScrollbarTopMargin + scrollbarHeight)\n#else\n\t\t\t&& m_nMousePosY > MENU_Y(PLAYERSETUP_LIST_BODY_TOP - 3 + m_nScrollbarTopMargin + scrollbarHeight - SCROLLBAR_MAX_HEIGHT / m_nTotalListRow)\n#endif\n\t\t\t&& m_nMousePosY < SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM + PLAYERSETUP_SCROLLBUTTON_HEIGHT + 1)) {\n\t\t\tm_nHoverOption = HOVEROPTION_PAGEDOWN;\n\n\t\t} else if (m_nMousePosX > MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 4)\n\t\t\t&& m_nMousePosX < MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - PLAYERSETUP_SCROLLBAR_WIDTH)\n#ifdef FIX_BUGS\n\t\t\t&& m_nMousePosY > MENU_Y(PLAYERSETUP_LIST_BODY_TOP + m_nScrollbarTopMargin)\n\t\t\t&& m_nMousePosY < MENU_Y(PLAYERSETUP_LIST_BODY_TOP - 8 + m_nScrollbarTopMargin + scrollbarHeight)) {\n#else\n\t\t\t&& m_nMousePosY > MENU_Y(SCROLLBAR_MAX_HEIGHT / m_nTotalListRow + PLAYERSETUP_LIST_BODY_TOP - 3 + m_nScrollbarTopMargin)\n\t\t\t&& m_nMousePosY < MENU_Y(PLAYERSETUP_LIST_BODY_TOP - 3 + m_nScrollbarTopMargin + scrollbarHeight - SCROLLBAR_MAX_HEIGHT / m_nTotalListRow)) {\n#endif\n\t\t\tm_nHoverOption = HOVEROPTION_HOLDING_SCROLLBAR;\n\n\t\t} else if (m_nMousePosX > MENU_X_LEFT_ALIGNED(PLAYERSETUP_LIST_LEFT) && m_nMousePosX < MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT)\n\t\t\t&& m_nMousePosY > MENU_Y(PLAYERSETUP_LIST_BODY_TOP + 1) && m_nMousePosY < SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM)) {\n\t\t\tm_nHoverOption = HOVEROPTION_LIST;\n\n\t\t} else {\n\t\t\tm_nHoverOption = HOVEROPTION_NOT_HOVERING;\n\t\t}\n\t}\n\tCFont::SetFontStyle(FONT_LOCALE(FONT_HEADING));\n\tCFont::SetScale(MENU_X(BIGTEXT_X_SCALE), MENU_Y(BIGTEXT_Y_SCALE));\n\tCFont::SetRightJustifyOn();\n\tCFont::SetColor(CRGBA(MENUOPTION_COLOR.r, MENUOPTION_COLOR.g, MENUOPTION_COLOR.b, FadeIn(255)));\n\tCFont::SetDropShadowPosition(2);\n\tCFont::SetDropColor(CRGBA(0, 0, 0, FadeIn(255)));\n\n\t// Back button\n\tCFont::PrintString(MENU_X_RIGHT_ALIGNED(PLAYERSETUP_LIST_RIGHT - 3), SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM - 5), TheText.Get(\"FEDS_TB\"));\n\tCFont::SetRightJustifyOff();\n\n\tif (!strcmp(m_aSkinName, m_PrefsSkinFile)) {\n\t\tCFont::SetColor(CRGBA(DARKMENUOPTION_COLOR.r, DARKMENUOPTION_COLOR.g, DARKMENUOPTION_COLOR.b, FadeIn(255)));\n\t} else {\n\t\tCFont::SetColor(CRGBA(MENUOPTION_COLOR.r, MENUOPTION_COLOR.g, MENUOPTION_COLOR.b, FadeIn(255)));\n\t}\n\n\t// Use skin button\n\tCFont::PrintString(MENU_X_LEFT_ALIGNED(PLAYERSETUP_LIST_LEFT), SCREEN_SCALE_FROM_BOTTOM(PLAYERSETUP_LIST_BOTTOM - 5), TheText.Get(\"FES_SET\"));\n\tCFont::SetDropShadowPosition(0);\n}\n\nint\nCMenuManager::FadeIn(int alpha)\n{\n\treturn Min(m_nMenuFadeAlpha, alpha);\n}\n\nint\nCMenuManager::GetStartOptionsCntrlConfigScreens()\n{\n\tint number = 0;\n\tswitch (m_nCurrScreen) {\n#ifdef LEGACY_MENU_OPTIONS\n\t\tcase MENUPAGE_CONTROLLER_PC_OLD3:\n\t\t\tnumber = 34;\n\t\t\tbreak;\n\t\tcase MENUPAGE_CONTROLLER_DEBUG:\n\t\t\tnumber = 35;\n\t\t\tbreak;\n#endif\n\t\tcase MENUPAGE_KEYBOARD_CONTROLS:\n\t\t\tnumber = 0;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\treturn number;\n}\n\nvoid\nCMenuManager::InitialiseChangedLanguageSettings()\n{\n\tif (m_bFrontEnd_ReloadObrTxtGxt) {\n\t\tm_bFrontEnd_ReloadObrTxtGxt = false;\n\t\tCTimer::Stop();\n\t\tTheText.Unload();\n\t\tTheText.Load();\n\t\tCTimer::Update();\n\t\tCGame::frenchGame = false;\n\t\tCGame::germanGame = false;\n#ifdef MORE_LANGUAGES\n\t\tCGame::russianGame = false;\n\t\tCGame::japaneseGame = false;\n\t\tswitch (m_PrefsLanguage) {\n\t\tcase LANGUAGE_POLISH:\n\t\t\tCFont::ReloadFonts(FONT_LANGSET_POLISH);\n\t\t\tbreak;\n\t\tcase LANGUAGE_RUSSIAN:\n\t\t\tCFont::ReloadFonts(FONT_LANGSET_RUSSIAN);\n\t\t\tbreak;\n\t\tcase LANGUAGE_JAPANESE:\n\t\t\tCFont::ReloadFonts(FONT_LANGSET_JAPANESE);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tCFont::ReloadFonts(FONT_LANGSET_EFIGS);\n\t\t\tbreak;\n\t\t}\n#endif\n\n\t\tswitch (m_PrefsLanguage) {\n\t\tcase LANGUAGE_FRENCH:\n\t\t\tCGame::frenchGame = true;\n\t\t\tbreak;\n\t\tcase LANGUAGE_GERMAN:\n\t\t\tCGame::germanGame = true;\n\t\t\tbreak;\n#ifdef MORE_LANGUAGES\n\t\tcase LANGUAGE_RUSSIAN:\n\t\t\tCGame::russianGame = true;\n\t\t\tbreak;\n\t\tcase LANGUAGE_JAPANESE:\n\t\t\tCGame::japaneseGame = true;\n\t\t\tbreak;\n#endif\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\n\t}\n}\n\nvoid\nCMenuManager::LoadAllTextures()\n{\n\tif (m_bSpritesLoaded)\n\t\treturn;\n\n\t// First icon is hidden behind arrow\n\tm_LeftMostRadioX = MENU_X_LEFT_ALIGNED(MENURADIO_ICON_FIRST_X - MENURADIO_ICON_SIZE);\n\tCTimer::Stop();\n\n\tCStreaming::MakeSpaceFor(350 * CDSTREAM_SECTOR_SIZE); // twice of it in mobile\n\tCStreaming::ImGonnaUseStreamingMemory();\n\tCGame::TidyUpMemory(false, true);\n\tCTxdStore::PushCurrentTxd();\n\tint frontendTxdSlot1 = CTxdStore::FindTxdSlot(\"frontend1\");\n\n\tif(frontendTxdSlot1 == -1)\n\t\tfrontendTxdSlot1 = CTxdStore::AddTxdSlot(\"frontend1\");\n\n\tprintf(\"LOAD frontend1\\n\");\n\tCTxdStore::LoadTxd(frontendTxdSlot1, \"MODELS/FRONTEN1.TXD\");\n\tCTxdStore::AddRef(frontendTxdSlot1);\n\tCTxdStore::SetCurrentTxd(frontendTxdSlot1);\n\n\tfor (int i = 0; i < 3; i++) {\n\t\tm_aFrontEndSprites[i].SetTexture(FrontendFilenames[i][0], FrontendFilenames[i][1]);\n\t\tm_aFrontEndSprites[i].SetAddressing(rwTEXTUREADDRESSBORDER);\n\t}\n\n\tCTxdStore::PopCurrentTxd();\n\tCStreaming::IHaveUsedStreamingMemory();\n\n\tif (!m_OnlySaveMenu) {\n\t\tCStreaming::MakeSpaceFor(692 * CDSTREAM_SECTOR_SIZE); // twice of it in mobile\n\t\tCStreaming::ImGonnaUseStreamingMemory();\n\t\tCTxdStore::PushCurrentTxd();\n\n\t\tint frontendTxdSlot2 = CTxdStore::FindTxdSlot(\"frontend2\");\n\n\t\tif (frontendTxdSlot2 == -1)\n\t\t\tfrontendTxdSlot2 = CTxdStore::AddTxdSlot(\"frontend2\");\n\n\t\tprintf(\"LOAD frontend2\\n\");\n\t\tCTxdStore::LoadTxd(frontendTxdSlot2, \"MODELS/FRONTEN2.TXD\");\n\t\tCTxdStore::AddRef(frontendTxdSlot2);\n\t\tCTxdStore::SetCurrentTxd(frontendTxdSlot2);\n\n#ifdef GAMEPAD_MENU\n\t\tfor (int i = 3; i < MENUSPRITE_CONTROLLER; i++) {\n#else\n\t\tfor (int i = 3; i < NUM_MENU_SPRITES; i++) {\n#endif\n\t\t\tm_aFrontEndSprites[i].SetTexture(FrontendFilenames[i][0], FrontendFilenames[i][1]);\n\t\t\tm_aFrontEndSprites[i].SetAddressing(rwTEXTUREADDRESSBORDER);\n\t\t}\n\n\t\tCTxdStore::PopCurrentTxd();\n#ifdef GAMEPAD_MENU\n\t\tLoadController(m_PrefsControllerType);\n#endif\n\t\tCStreaming::IHaveUsedStreamingMemory();\n\t}\n\n\tm_bSpritesLoaded = true;\n\tCTimer::Update();\n}\n\nvoid\nCMenuManager::LoadSettings()\n{\n\tCFileMgr::SetDirMyDocuments();\n\tint fileHandle = CFileMgr::OpenFile(\"gta_vc.set\", \"r\");\n\n\tint32 prevLang = m_PrefsLanguage;\n\tMousePointerStateHelper.bInvertVertically = true;\n\tCMBlur::BlurOn = false;\n\n\t// 50 is silly\n\tchar headerText[50];\n\tint someVersion = 0;\n\tbool fileIsValid = true;\n\n\tif (fileHandle) {\n\t\tCFileMgr::Read(fileHandle, headerText, 29);\n\n\t\tif (strncmp(headerText, TopLineEmptyFile, sizeof(TopLineEmptyFile) - 1) == 0) {\n\t\t\tfileIsValid = false;\n\t\t} else {\n\t\t\tCFileMgr::Seek(fileHandle, 0, 0);\n\t\t\tCFileMgr::Read(fileHandle, (char*)&someVersion, sizeof(someVersion));\n\t\t}\n\t\tif (fileIsValid && someVersion >= 3) {\n\t\t\tControlsManager.LoadSettings(fileHandle);\n#ifdef IMPROVED_VIDEOMODE\n\t\t\tCFileMgr::Read(fileHandle, (char*)&m_nPrefsWidth, sizeof(m_nPrefsWidth));\n\t\t\tCFileMgr::Read(fileHandle, (char*)&m_nPrefsHeight, sizeof(m_nPrefsHeight));\n\t\t\tCFileMgr::Read(fileHandle, (char*)&m_nPrefsDepth, sizeof(m_nPrefsDepth));\n\t\t\tCFileMgr::Read(fileHandle, (char*)&m_nPrefsWindowed, sizeof(m_nPrefsWindowed));\n\t\t\tCFileMgr::Read(fileHandle, (char*)&m_nPrefsSubsystem, sizeof(m_nPrefsSubsystem));\n\t\t\tif(m_nPrefsWindowed != 0 && m_nPrefsWindowed != 1){\n\t\t\t\t// garbage data from vanilla settings file\n\t\t\t\t// let skeleton find something\n\t\t\t\tm_nPrefsWidth = 0;\n\t\t\t\tm_nPrefsHeight = 0;\n\t\t\t\tm_nPrefsDepth = 0;\n\t\t\t\tm_nPrefsWindowed = 0;\n\t\t\t\tm_nPrefsSubsystem = 0;\n\t\t\t}\n\t\t\tm_nSelectedScreenMode = m_nPrefsWindowed;\n#else\n\t\t\tCFileMgr::Read(fileHandle, gString, 20);\n#endif\n\t\t\tCFileMgr::Read(fileHandle, gString, 20);\n\t\t\tCFileMgr::Read(fileHandle, gString, 4);\n\t\t\tCFileMgr::Read(fileHandle, gString, 4);\n\t\t\tCFileMgr::Read(fileHandle, gString, 1);\n#ifdef LEGACY_MENU_OPTIONS\n\t\t\tCFileMgr::Read(fileHandle, (char*)&m_PrefsVsyncDisp, 1);\n\t\t\tCFileMgr::Read(fileHandle, (char*)&CMBlur::BlurOn, 1);\n#else\n\t\t\tCFileMgr::Read(fileHandle, gString, 1);\n\t\t\tCFileMgr::Read(fileHandle, gString, 1);\n#endif\n\t\t\tCFileMgr::Read(fileHandle, (char*)&TheCamera.m_bHeadBob, 1);\n\t\t\tCFileMgr::Read(fileHandle, (char*)&TheCamera.m_fMouseAccelHorzntl, 4);\n\t\t\tCFileMgr::Read(fileHandle, (char*)&MousePointerStateHelper.bInvertVertically, 1);\n\t\t\tCFileMgr::Read(fileHandle, (char*)&CVehicle::m_bDisableMouseSteering, 1);\n\t\t\tCFileMgr::Read(fileHandle, (char*)&m_PrefsSfxVolume, 1);\n\t\t\tCFileMgr::Read(fileHandle, (char*)&m_PrefsMusicVolume, 1);\n\t\t\tCFileMgr::Read(fileHandle, (char*)&m_PrefsMP3BoostVolume, 1);\n\t\t\tCFileMgr::Read(fileHandle, (char*)&m_PrefsRadioStation, 1);\n\t\t\tCFileMgr::Read(fileHandle, (char*)&m_PrefsSpeakers, 1);\n\t\t\tCFileMgr::Read(fileHandle, (char*)&m_nPrefsAudio3DProviderIndex, 1);\n\t\t\tCFileMgr::Read(fileHandle, (char*)&m_PrefsDMA, 1);\n\t\t\tCFileMgr::Read(fileHandle, (char*)&m_PrefsBrightness, 2);\n\t\t\tCFileMgr::Read(fileHandle, (char*)&m_PrefsLOD, sizeof(m_PrefsLOD));\n\t\t\tCFileMgr::Read(fileHandle, (char*)&m_PrefsShowSubtitles, 1);\n\t\t\tCFileMgr::Read(fileHandle, (char*)&m_PrefsUseWideScreen, 1);\n\t\t\tCFileMgr::Read(fileHandle, (char*)&m_PrefsFrameLimiter, 1);\n\t\t\tCFileMgr::Read(fileHandle, (char*)&m_nDisplayVideoMode, 1);\n\t\t\tCFileMgr::Read(fileHandle, m_PrefsSkinFile, 256);\n\t\t\tCFileMgr::Read(fileHandle, (char*)&m_ControlMethod, 1);\n\t\t\tCFileMgr::Read(fileHandle, (char*)&m_PrefsLanguage, 1);\n\t\t\tCFileMgr::Read(fileHandle, (char*)&m_PrefsShowHud, 1);\n\t\t\tCFileMgr::Read(fileHandle, (char*)&m_PrefsRadarMode, 1);\n\t\t\tCFileMgr::Read(fileHandle, (char*)&m_PrefsShowLegends, 1);\n\t\t}\n\t}\n\n\tCFileMgr::CloseFile(fileHandle);\n\tCFileMgr::SetDir(\"\");\n\n#ifdef LOAD_INI_SETTINGS\n\tif (LoadINISettings()) {\n\t\tLoadINIControllerSettings();\n\t}\n\t// if no reVC.ini, create it, or update it with new values\n\tSaveINISettings();\n\tSaveINIControllerSettings();\n#endif\n\n#ifdef FIX_BUGS\n\tTheCamera.m_fMouseAccelVertical = TheCamera.m_fMouseAccelHorzntl + 0.0005f;\n#endif\n#ifdef PC_PLAYER_CONTROLS\n\tCCamera::m_bUseMouse3rdPerson = m_ControlMethod == CONTROL_STANDARD;\n#endif\n#ifdef LEGACY_MENU_OPTIONS\n\tm_PrefsVsync = m_PrefsVsyncDisp;\n#endif\n\tCRenderer::ms_lodDistScale = m_PrefsLOD;\n\n\tif (m_nPrefsAudio3DProviderIndex == NO_AUDIO_PROVIDER)\n\t\tm_nPrefsAudio3DProviderIndex = -2;\n\n\tm_lastWorking3DAudioProvider = m_nPrefsAudio3DProviderIndex;\n\n\tif (m_PrefsLanguage == prevLang)\n\t\tm_bLanguageLoaded = false;\n\telse {\n\t\tm_bLanguageLoaded = true;\n\t\tTheText.Unload();\n\t\tTheText.Load();\n\t\tm_bFrontEnd_ReloadObrTxtGxt = true;\n\t\tInitialiseChangedLanguageSettings();\n\n\t\tOutputDebugString(\"The previously saved language is now in use\");\n\t}\n\n\tWIN32_FIND_DATA FindFileData;\n\tchar skinfile[256+16];\t// Stack analysis shows 16 bits gap, but I don't trust it. It may very well be MAX_PATH(260).\n\tbool SkinFound = false;\n\tHANDLE handle = FindFirstFile(\"skins\\\\*.bmp\", &FindFileData);\n\tfor (int i = 1; handle != INVALID_HANDLE_VALUE && i; i = FindNextFile(handle, &FindFileData)) {\n\t\tstrcpy(skinfile, m_PrefsSkinFile);\n\t\tstrcat(skinfile, \".bmp\");\n\t\tif (strcmp(FindFileData.cFileName, skinfile) == 0)\n\t\t\tSkinFound = true;\n\t}\n\tFindClose(handle);\n\n\tif (!SkinFound) {\n\t\tOutputDebugString(\"Default skin set as no other skins are available OR saved skin not found!\");\n\t\tstrcpy(m_PrefsSkinFile, DEFAULT_SKIN_NAME);\n\t\tstrcpy(m_aSkinName, DEFAULT_SKIN_NAME);\n\t}\n}\n\nvoid\nCMenuManager::SaveSettings()\n{\n#ifndef LOAD_INI_SETTINGS\n\tstatic char RubbishString[48] = \"stuffmorestuffevenmorestuff                 etc\";\n#ifdef BIND_VEHICLE_FIREWEAPON\n\tstatic int SomeVersion = 4;\n#else\n\tstatic int SomeVersion = 3;\n#endif\n\n\tCFileMgr::SetDirMyDocuments();\n\n\tint fileHandle = CFileMgr::OpenFile(\"gta_vc.set\", \"w+\");\n\tif (fileHandle) {\n\t\tCFileMgr::Write(fileHandle, (char*)&SomeVersion, sizeof(SomeVersion));\n\t\tControlsManager.SaveSettings(fileHandle);\n#ifdef IMPROVED_VIDEOMODE\n\t\tCFileMgr::Write(fileHandle, (char*)&m_nPrefsWidth, sizeof(m_nPrefsWidth));\n\t\tCFileMgr::Write(fileHandle, (char*)&m_nPrefsHeight, sizeof(m_nPrefsHeight));\n\t\tCFileMgr::Write(fileHandle, (char*)&m_nPrefsDepth, sizeof(m_nPrefsDepth));\n\t\tCFileMgr::Write(fileHandle, (char*)&m_nPrefsWindowed, sizeof(m_nPrefsWindowed));\n\t\tCFileMgr::Write(fileHandle, (char*)&m_nPrefsSubsystem, sizeof(m_nPrefsSubsystem));\n#else\n\t\tCFileMgr::Write(fileHandle, RubbishString, 20);\n#endif\n\t\tCFileMgr::Write(fileHandle, RubbishString, 20);\n\t\tCFileMgr::Write(fileHandle, RubbishString, 4);\n\t\tCFileMgr::Write(fileHandle, RubbishString, 4);\n\t\tCFileMgr::Write(fileHandle, RubbishString, 1);\n#ifdef LEGACY_MENU_OPTIONS\n\t\tCFileMgr::Write(fileHandle, (char*)&m_PrefsVsyncDisp, 1);\n\t\tCFileMgr::Write(fileHandle, (char*)&CMBlur::BlurOn, 1);\n#else\n\t\tCFileMgr::Write(fileHandle, RubbishString, 1);\n\t\tCFileMgr::Write(fileHandle, RubbishString, 1);\n#endif\n\t\tCFileMgr::Write(fileHandle, (char*)&TheCamera.m_bHeadBob, 1);\n\t\tCFileMgr::Write(fileHandle, (char*)&TheCamera.m_fMouseAccelHorzntl, 4);\n\t\tCFileMgr::Write(fileHandle, (char*)&MousePointerStateHelper.bInvertVertically, 1);\n\t\tCFileMgr::Write(fileHandle, (char*)&CVehicle::m_bDisableMouseSteering, 1);\n\t\tCFileMgr::Write(fileHandle, (char*)&m_PrefsSfxVolume, 1);\n\t\tCFileMgr::Write(fileHandle, (char*)&m_PrefsMusicVolume, 1);\n\t\tCFileMgr::Write(fileHandle, (char*)&m_PrefsMP3BoostVolume, 1);\n\t\tCFileMgr::Write(fileHandle, (char*)&m_PrefsRadioStation, 1);\n\t\tCFileMgr::Write(fileHandle, (char*)&m_PrefsSpeakers, 1);\n\t\tCFileMgr::Write(fileHandle, (char*)&m_nPrefsAudio3DProviderIndex, 1);\n\t\tCFileMgr::Write(fileHandle, (char*)&m_PrefsDMA, 1);\n\t\tCFileMgr::Write(fileHandle, (char*)&m_PrefsBrightness, 2);\n\t\tCFileMgr::Write(fileHandle, (char*)&m_PrefsLOD, sizeof(m_PrefsLOD));\n\t\tCFileMgr::Write(fileHandle, (char*)&m_PrefsShowSubtitles, 1);\n\t\tCFileMgr::Write(fileHandle, (char*)&m_PrefsUseWideScreen, 1);\n\t\tCFileMgr::Write(fileHandle, (char*)&m_PrefsFrameLimiter, 1);\n\t\tCFileMgr::Write(fileHandle, (char*)&m_nPrefsVideoMode, 1);\n\t\tCFileMgr::Write(fileHandle, m_PrefsSkinFile, 256);\n\t\tCFileMgr::Write(fileHandle, (char*)&m_ControlMethod, 1);\n\t\tCFileMgr::Write(fileHandle, (char*)&m_PrefsLanguage, 1);\n\t\tCFileMgr::Write(fileHandle, (char*)&m_PrefsShowHud, 1);\n\t\tCFileMgr::Write(fileHandle, (char*)&m_PrefsRadarMode, 1);\n\t\tCFileMgr::Write(fileHandle, (char*)&m_PrefsShowLegends, 1);\n\t}\n\tm_lastWorking3DAudioProvider = m_nPrefsAudio3DProviderIndex;\n\n\tCFileMgr::CloseFile(fileHandle);\n\tCFileMgr::SetDir(\"\");\n\t\n#else\n\tm_lastWorking3DAudioProvider = m_nPrefsAudio3DProviderIndex;\n\tSaveINISettings();\n#endif\n}\n\nvoid\nCMenuManager::MessageScreen(const char *text, bool blackBg)\n{\n\tCSprite2d *splash = LoadSplash(nil);\n\tif (!DoRWStuffStartOfFrame(0, 0, 0, 0, 0, 0, 255))\n\t\treturn;\n\n\tCSprite2d::SetRecipNearClip();\n\tCSprite2d::InitPerFrame();\n\tCFont::InitPerFrame();\n\tDefinedState();\n\t// CRGBA unused(255, 255, 255, 255);\n\tif (blackBg) {\n\t\tCSprite2d::DrawRect(CRect(0, SCREEN_HEIGHT, SCREEN_WIDTH, 0), CRGBA(0, 0, 0, 255));\n\t}\n\n\tm_nMenuFadeAlpha = 255;\n\tSmallMessageScreen(text);\n\tCFont::DrawFonts();\n\tDoRWStuffEndOfFrame();\n}\n\nvoid\nCMenuManager::SmallMessageScreen(const char* text)\n{\n\tCFont::SetBackgroundOff();\n\tCFont::SetPropOn();\n\tCFont::SetJustifyOn();\n\tCFont::SetBackGroundOnlyTextOn();\n\tCSprite2d::DrawRect(CRect(SCREEN_STRETCH_X(95.0f), SCREEN_SCALE_FROM_BOTTOM(165.0f), SCREEN_STRETCH_FROM_RIGHT(95.0f), SCREEN_SCALE_Y(115.0f)), CRGBA(50, 50, 50, FadeIn(210)));\n\tCFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD));\n\tCFont::SetCentreSize(SCREEN_SCALE_X(430.0f));\n\tCFont::SetCentreOn();\n\tCFont::SetColor(CRGBA(LABEL_COLOR.r, LABEL_COLOR.g, LABEL_COLOR.b, FadeIn(255)));\n\tCFont::SetDropShadowPosition(2);\n\tCFont::SetDropColor(CRGBA(0, 0, 0, 255));\n\tCFont::SetScale(SCREEN_SCALE_X(SMALLTEXT_X_SCALE), SCREEN_SCALE_Y(SMALLTEXT_Y_SCALE));\n\t\n\tint numOfLines = CFont::GetNumberLines(SCREEN_WIDTH / 2.f, SCREEN_SCALE_Y(135.f), TheText.Get(text));\n\tfloat y;\n\tif (numOfLines > 1)\n\t\ty = SCREEN_SCALE_Y(192.f) - numOfLines * SCREEN_SCALE_Y(8.f);\n\telse\n\t\ty = SCREEN_SCALE_Y(182.f);\n\n\tCFont::PrintString(SCREEN_WIDTH / 2.f, y, TheText.Get(text));\n}\n\nvoid\nCMenuManager::PrintBriefs()\n{\n\tCFont::SetColor(CRGBA(0, 0, 0, FadeIn(255)));\n\tCFont::SetRightJustifyOff();\n\tCFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD));\n\tCFont::SetScale(MENU_X(MEDIUMTEXT_X_SCALE), MENU_Y(MEDIUMTEXT_Y_SCALE));\n\tCFont::SetWrapx(MENU_X_RIGHT_ALIGNED(80.0f));\n\tCFont::SetDropShadowPosition(0);\n\n\tfloat nextY = BRIEFS_BOTTOM_MARGIN;\n\tfor (int i = 4; i >= 0; i--) {\n\t\tif (nextY < BRIEFS_TOP_MARGIN)\n\t\t\tbreak;\n\n\t\ttPreviousBrief &brief = CMessages::PreviousBriefs[i];\n\t\tif (brief.m_pText) {\n\t\t\tCMessages::InsertNumberInString(brief.m_pText,\n\t\t\t\tbrief.m_nNumber[0], brief.m_nNumber[1],\n\t\t\t\tbrief.m_nNumber[2], brief.m_nNumber[3],\n\t\t\t\tbrief.m_nNumber[4], brief.m_nNumber[5], gUString);\n\t\t\tCMessages::InsertStringInString(gUString, brief.m_pString);\n\t\t\tCMessages::InsertPlayerControlKeysInString(gUString);\n\t\t\tCFont::FilterOutTokensFromString(gUString);\n\n\t\t\tnextY -= CFont::GetNumberLines(MENU_X_LEFT_ALIGNED(BRIEFS_LINE_X), nextY, gUString) * BRIEFS_LINE_HEIGHT + BRIEFS_LINE_SPACING;\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(BRIEFS_LINE_X), MENU_Y(nextY), gUString);\n\t\t}\n\t}\n}\n\nvoid\nCMenuManager::PrintStats()\n{\n#ifdef SECUROM\n\tstatic uint8 statsPirateCheck = 0;\n#endif\n\tstatic float scrollY = 0;\n\n\tint rowNum = CStats::ConstructStatLine(99999);\n\tCSprite2d::Draw2DPolygon(MENU_X_LEFT_ALIGNED(90.0f), MENU_Y(142.0f),\n\t\tMENU_X_LEFT_ALIGNED(543.0f), MENU_Y(142.f),\n\t\tMENU_X_LEFT_ALIGNED(107.0f), MENU_Y(316.f),\n\t\tMENU_X_LEFT_ALIGNED(531.f), MENU_Y(299.f), CRGBA(LIST_BACKGROUND_COLOR.r, LIST_BACKGROUND_COLOR.g, LIST_BACKGROUND_COLOR.b, FadeIn(LIST_BACKGROUND_COLOR.a)));\n\n\tCFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD));\n\tCFont::SetPropOn();\n\tCFont::SetDropShadowPosition(0);\n\n#ifdef SECUROM\n\tif (statsPirateCheck == 0)\n\t\t// if not pirated game\n\t\t// statsPirateCheck = 46;\n\t\t// else\n\t\tstatsPirateCheck = 45;\n#endif\n\n\tif (m_PrefsLanguage == LANGUAGE_AMERICAN)\n\t\tCFont::SetScale(MENU_X(0.43f), MENU_Y(0.75f));\n\telse\n\t\tCFont::SetScale(MENU_X(0.37f), MENU_Y(0.75f));\n\n\tstatic PauseModeTime lastCheck = 0;\n\n\tif (CTimer::GetTimeInMillisecondsPauseMode() - lastCheck > 40) {\n\n\t\tif (m_StatsScrollSpeed > 0.f) {\n\t\t\tif (m_StatsScrollDirection == 0)\n\t\t\t\tscrollY -= MENU_Y(100.f) / m_StatsScrollSpeed;\n\t\t\telse\n\t\t\t\tscrollY += MENU_Y(100.f) / m_StatsScrollSpeed;\n\t\t}\n\t\tlastCheck = CTimer::GetTimeInMillisecondsPauseMode();\n\t}\n\n#ifdef SECUROM\n\tif (statsPirateCheck == 45)\n\t\treturn;\n#endif\n\n\tfloat nextYChange, y, alpha;\n\n\tfloat totalHeight = (rowNum + 7) * STATS_ROW_HEIGHT;\n\tfor (int row = 0; row < rowNum; ++row) {\n\t\t// Put faded away text at the top back to the bottom, in circular fashion\n\t\tfor (y = MENU_Y(STATS_ROW_HEIGHT) * row + MENU_Y(100.f) - scrollY; MENU_Y(STATS_FADING_AREA_LENGTH) > y; y += nextYChange) {\n\t\t\tnextYChange = MENU_Y(totalHeight);\n\t\t}\n\n\t\t// Put faded away text at the bottom back to the top\n\t\twhile (SCREEN_SCALE_FROM_BOTTOM(STATS_FADING_AREA_LENGTH) < y) {\n\t\t\ty -= MENU_Y(totalHeight);\n\t\t}\n\t\talpha = 0.f;\n\n\t\t// If it's still on screen\n\t\tif (y > MENU_Y(STATS_VISIBLE_START_Y) && y < MENU_Y(STATS_VISIBLE_END_Y)) {\n\t\t\tCStats::ConstructStatLine(row);\n\n\t\t\t// But about to dim from bottom\n\t\t\tif (y < MENU_Y(STATS_BOTTOM_Y)) {\n\t\t\t\tif (y > MENU_Y(STATS_BOTTOM_Y - STATS_FADING_AREA_LENGTH))\n\t\t\t\t\talpha = (MENU_Y(STATS_BOTTOM_Y) - y) * 5.f;\n\t\t\t}\n\n\t\t\t// About to dim from top\n\t\t\tif (y > MENU_Y(STATS_TOP_Y)) {\n\t\t\t\tif (y < MENU_Y(STATS_TOP_Y + STATS_FADING_AREA_LENGTH))\n\t\t\t\t\talpha = (y - MENU_Y(STATS_TOP_Y)) * 5.f;\n\t\t\t}\n\n\t\t\t// Content\n\t\t\tif (y >= MENU_Y(STATS_TOP_Y + STATS_FADING_AREA_LENGTH) && y <= MENU_Y(STATS_BOTTOM_Y - STATS_FADING_AREA_LENGTH))\n\t\t\t\talpha = 255.0f;\n\n\t\t\tCFont::SetColor(CRGBA(0, 0, 0, FadeIn(Min(255.f, alpha))));\n\t\t\tCFont::SetRightJustifyOff();\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(STATS_ROW_LEFT_MARGIN), y, gUString);\n\t\t\tCFont::SetRightJustifyOn();\n\t\t\tCFont::PrintString(MENU_X_RIGHT_ALIGNED(STATS_ROW_RIGHT_MARGIN), y, gUString2);\n\t\t}\n\t}\n\tCFont::SetColor(CRGBA(MENUOPTION_COLOR.r, MENUOPTION_COLOR.g, MENUOPTION_COLOR.b, FadeIn(255)));\n\tCFont::SetDropShadowPosition(2);\n\tCFont::SetDropColor(CRGBA(0, 0, 0, FadeIn(255)));\n\tCFont::SetCentreOn();\n\tCFont::SetFontStyle(FONT_LOCALE(FONT_HEADING));\n\tCFont::SetScale(MENU_X(0.65f), MENU_Y(1.05f));\n\tCFont::PrintString(MENU_X_LEFT_ALIGNED(STATS_RATING_X), MENU_Y(STATS_RATING_Y_1), TheText.Get(\"CRIMRA\"));\n\n\tCFont::SetCentreOff();\n\tCFont::SetRightJustifyOff();\n\n\t// FIX: Game does that in a weird way, alignment and spacing is now ok\n\n\tsprintf(gString, \"(%d)\", CStats::FindCriminalRatingNumber());\n\tAsciiToUnicode(gString, gUString);\n\n\tUnicodeStrcpy(gUString2, CStats::FindCriminalRatingString());\n\tUnicodeStrcat(gUString2, gUString);\n\n\tCFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD));\n#ifndef FIX_BUGS\n\tCFont::SetScale(MENU_X(0.5f), MENU_Y(0.9f));\n#else\n\tCFont::SetScale(MENU_X(SMALLTEXT_X_SCALE), MENU_Y(SMALLTEXT_Y_SCALE));\n#endif\n\tCFont::SetColor(CRGBA(0, 0, 0, FadeIn(255)));\n\tCFont::SetDropShadowPosition(0);\n\n\tCFont::PrintString(MENU_X_LEFT_ALIGNED(STATS_RATING_X) - CFont::GetStringWidth(gUString2, true) / 2.f, MENU_Y(STATS_RATING_Y_2), gUString2);\n}\n\nvoid\nCMenuManager::Process(void)\n{\n#ifdef XBOX_MESSAGE_SCREEN\n\tProcessDialogTimer();\n#endif\n\n\tif (TheCamera.GetScreenFadeStatus() != FADE_0)\n\t\treturn;\n\n\tInitialiseChangedLanguageSettings();\n\n\tif (m_bMenuActive) {\n\t\tUserInput();\n\t\tProcessFileActions();\n\t\tDMAudio.Service();\n#ifdef USE_TEXTURE_POOL\n\t\t// TODO\n#endif\n\t}\n\n\tSwitchMenuOnAndOff();\n}\n\n#ifdef MAP_ENHANCEMENTS\n#define ZOOM(x, y, in) \\\n\tdo { \\\n\t\tif(m_fMapSize >= MENU_Y(1000.0f) && in) \\\n\t\t\tbreak; \\\n\t\tfloat z2 = in? 1.1f : 1.f/1.1f; \\\n\t\tm_fMapCenterX += (x - m_fMapCenterX) * (1.0f - z2); \\\n\t\tm_fMapCenterY += (y - m_fMapCenterY) * (1.0f - z2); \\\n\t\t\\\n\t\tif (m_fMapSize <= MENU_Y(MAP_MIN_SIZE) && !in) \\\n\t\t\tbreak; \\\n\t\t\\\n\t\tm_fMapSize *= z2; \\\n\t\tm_fMapCenterX = clamp(m_fMapCenterX, SCREEN_WIDTH/2 - (m_fMapSize - MENU_X(MAP_MIN_SIZE)), m_fMapSize - MENU_X(MAP_MIN_SIZE) + SCREEN_WIDTH/2); \\\n\t\tm_fMapCenterY = clamp(m_fMapCenterY, SCREEN_HEIGHT/2 - (m_fMapSize - MENU_Y(MAP_MIN_SIZE)), m_fMapSize - MENU_Y(MAP_MIN_SIZE) + SCREEN_HEIGHT/2); \\\n\t} while(0)\n\n#endif\n\n// Handles Map, Audio and Stats\nvoid\nCMenuManager::AdditionalOptionInput(bool &goBack)\n{\n\tswitch (m_nCurrScreen) {\n\t\tcase MENUPAGE_MAP:\n\t\t{\n\t\t\tstatic PauseModeTime lastMapTick = 0;\n\n\t\t\t// FIX: All those macros were hardcoded values originally.\n\n#ifndef MAP_ENHANCEMENTS\n\t\t\tif (CPad::GetPad(0)->GetMouseWheelUpJustDown() || CPad::GetPad(0)->GetMouseWheelUpJustUp() || CPad::GetPad(0)->GetPageUp() || CPad::GetPad(0)->GetRightShoulder1()) {\n\t\t\t\tif (CTimer::GetTimeInMillisecondsPauseMode() - lastMapTick > 10) {\n\t\t\t\t\tm_fMapSize = Min(MENU_Y(1000.0f), m_fMapSize + MENU_Y(15.f));\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (CPad::GetPad(0)->GetMouseWheelDownJustDown() || CPad::GetPad(0)->GetMouseWheelDownJustUp() || CPad::GetPad(0)->GetPageDown() || CPad::GetPad(0)->GetRightShoulder2()) {\n\t\t\t\tif (CTimer::GetTimeInMillisecondsPauseMode() - lastMapTick > 10) {\n\t\t\t\t\tif (m_fMapSize > MENU_Y(MAP_MIN_SIZE)) {\n\t\t\t\t\t\tif (m_fMapCenterY > SCREEN_HEIGHT/2)\n\t\t\t\t\t\t\tm_fMapCenterY -= (m_fMapCenterY - SCREEN_HEIGHT/2) / ((m_fMapSize - MENU_Y(MAP_MIN_SIZE)) * 1/15.f);\n\n\t\t\t\t\t\tif (m_fMapCenterY < SCREEN_HEIGHT/2)\n\t\t\t\t\t\t\tm_fMapCenterY += (SCREEN_HEIGHT/2 - m_fMapCenterY) / ((m_fMapSize - MENU_Y(MAP_MIN_SIZE)) * 1/15.f);\n\n\t\t\t\t\t\tif (m_fMapCenterX > SCREEN_WIDTH/2)\n\t\t\t\t\t\t\tm_fMapCenterX -= (m_fMapCenterX - SCREEN_WIDTH/2) / ((m_fMapSize - MENU_X(MAP_MIN_SIZE)) * 1/15.f);\n\n\t\t\t\t\t\tif (m_fMapCenterX < SCREEN_WIDTH/2)\n\t\t\t\t\t\t\tm_fMapCenterX += (SCREEN_WIDTH/2 - m_fMapCenterX) / ((m_fMapSize - MENU_X(MAP_MIN_SIZE)) * 1/15.f);\n\n\t\t\t\t\t\tm_fMapSize = Max(MENU_Y(MAP_MIN_SIZE), m_fMapSize - MENU_Y(15.f));\n\t\t\t\t\t\tm_fMapCenterX = clamp(m_fMapCenterX, SCREEN_WIDTH/2 - (m_fMapSize - MENU_X(MAP_MIN_SIZE)), m_fMapSize - MENU_X(MAP_MIN_SIZE) + SCREEN_WIDTH/2);\n\t\t\t\t\t\tm_fMapCenterY = clamp(m_fMapCenterY, SCREEN_HEIGHT/2 - (m_fMapSize - MENU_Y(MAP_MIN_SIZE)), m_fMapSize - MENU_Y(MAP_MIN_SIZE) + SCREEN_HEIGHT/2);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tm_fMapSize = MENU_Y(MAP_MIN_SIZE);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n#else\n\t\t\t// Adding marker\n\t\t\tif (m_nMenuFadeAlpha == 255) {\n\t\t\t\tif (CPad::GetPad(0)->GetRightMouseJustDown() || CPad::GetPad(0)->GetCrossJustDown()) {\n\t\t\t\t\tif (mapCrosshair.y > m_fMapCenterY - m_fMapSize && mapCrosshair.y < m_fMapCenterY + m_fMapSize &&\n\t\t\t\t\t\tmapCrosshair.x > m_fMapCenterX - m_fMapSize && mapCrosshair.x < m_fMapCenterX + m_fMapSize) {\n\n\t\t\t\t\t\t// Don't ask me the meanings, I don't know. Found them by trying\n\t\t\t\t\t\tfloat diffX = m_fMapCenterX - m_fMapSize, diffY = m_fMapCenterY - m_fMapSize;\n\t\t\t\t\t\tfloat x = ((mapCrosshair.x - diffX) / (m_fMapSize * 2)) * (WORLD_SIZE_X / MENU_MAP_WIDTH_SCALE) - (WORLD_SIZE_X / 2 + MENU_MAP_LEFT_OFFSET * MENU_MAP_LENGTH_UNIT);\n\t\t\t\t\t\tfloat y = (WORLD_SIZE_Y / 2 - MENU_MAP_TOP_OFFSET * MENU_MAP_LENGTH_UNIT) - ((mapCrosshair.y - diffY) / (m_fMapSize * 2)) * (WORLD_SIZE_Y / MENU_MAP_HEIGHT_SCALE);\n\t\t\t\t\t\tCRadar::ToggleTargetMarker(x, y);\n\t\t\t\t\t\tDMAudio.PlayFrontEndSound(SOUND_FRONTEND_ENTER_OR_ADJUST, 0);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (CPad::GetPad(0)->GetMouseWheelDown() || CPad::GetPad(0)->GetPageDown() || CPad::GetPad(0)->GetRightShoulder2()) {\n\t\t\t\tif (CPad::GetPad(0)->GetMouseWheelDown() && m_fMapSize > MENU_X(MAP_SIZE_TO_ALLOW_X_MOVE))\n\t\t\t\t\tZOOM(mapCrosshair.x, mapCrosshair.y, false);\n\t\t\t\telse\n\t\t\t\t\tZOOM(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, false);\n\n\t\t\t} else if (CPad::GetPad(0)->GetMouseWheelUp() || CPad::GetPad(0)->GetPageUp() || CPad::GetPad(0)->GetRightShoulder1()) {\n\t\t\t\tif (CPad::GetPad(0)->GetMouseWheelUp())\n\t\t\t\t\tZOOM(mapCrosshair.x, mapCrosshair.y, true);\n\t\t\t\telse\n\t\t\t\t\tZOOM(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, true);\n\t\t\t}\n\t\t\t\n\t\t\tstatic bool justResetPointer = false;\n\t\t\tif (CPad::GetPad(0)->GetLeftMouse()) {\n\t\t\t\tif (!justResetPointer) {\n\t\t\t\t\tm_fMapCenterX += m_nMousePosX - m_nMouseOldPosX;\n\t\t\t\t\tm_fMapCenterY += m_nMousePosY - m_nMouseOldPosY;\n\t\t\t\t\tm_fMapCenterX = clamp(m_fMapCenterX, SCREEN_WIDTH/2 - (m_fMapSize - MENU_X(MAP_MIN_SIZE)), m_fMapSize - MENU_X(MAP_MIN_SIZE) + SCREEN_WIDTH/2);\n\t\t\t\t\tm_fMapCenterY = clamp(m_fMapCenterY, SCREEN_HEIGHT/2 - (m_fMapSize - MENU_Y(MAP_MIN_SIZE)), m_fMapSize - MENU_Y(MAP_MIN_SIZE) + SCREEN_HEIGHT/2);\n\t\t\t\t}\n\t\t\t\tjustResetPointer = false;\n\n\t\t\t} else\n#undef ZOOM\n#endif\n\n\t\t\t{\n\t\t\t\t// This is else block of GetLeftMouse() if MAP_ENHANCEMENTS defined, so all of GetLeftMouse() conditions below being rendered useless. \n\n\t\t\t\tif (CPad::GetPad(0)->GetLeftMouse() && m_nMousePosY < m_nMouseOldPosY || CPad::GetPad(0)->GetUp() ||\n\t\t\t\t\tCPad::GetPad(0)->GetDPadUp() || CPad::GetPad(0)->GetAnalogueUpDown() < 0) {\n\t\t\t\t\tif (CTimer::GetTimeInMillisecondsPauseMode() - lastMapTick > 10) {\n\t\t\t\t\t\tif ((m_fMapSize - MENU_Y(MAP_MIN_SIZE)) + SCREEN_HEIGHT/2 > m_fMapCenterY)\n\t\t\t\t\t\t\tm_fMapCenterY += MENU_Y(15.f);\n\t\t\t\t\t\tm_bShowMouse = false;\n\t\t\t\t\t}\t\t\t\t\n\t\t\t\t}\n\n\t\t\t\tif (CPad::GetPad(0)->GetLeftMouse() && m_nMousePosY > m_nMouseOldPosY || CPad::GetPad(0)->GetDown() ||\n\t\t\t\t\tCPad::GetPad(0)->GetDPadDown() || CPad::GetPad(0)->GetAnalogueUpDown() > 0) {\n\t\t\t\t\tif (CTimer::GetTimeInMillisecondsPauseMode() - lastMapTick > 10) {\n\t\t\t\t\t\tif (SCREEN_HEIGHT/2 - (m_fMapSize - MENU_Y(MAP_MIN_SIZE)) < m_fMapCenterY)\n\t\t\t\t\t\t\tm_fMapCenterY -= MENU_Y(15.f);\n\t\t\t\t\t\tm_bShowMouse = false;\n\t\t\t\t\t}\t\t\t\t\n\t\t\t\t}\n\n\t\t\t\tif (CPad::GetPad(0)->GetLeftMouse() && m_nMousePosX < m_nMouseOldPosX || CPad::GetPad(0)->GetLeft() ||\n\t\t\t\t\tCPad::GetPad(0)->GetDPadLeft() || CPad::GetPad(0)->GetAnalogueLeftRight() < 0) {\n\t\t\t\t\tif (CTimer::GetTimeInMillisecondsPauseMode() - lastMapTick > 10) {\n\t\t\t\t\t\tif (m_fMapSize > MENU_X(MAP_SIZE_TO_ALLOW_X_MOVE) && m_fMapSize - MENU_X(MAP_MIN_SIZE) + SCREEN_WIDTH/2 > m_fMapCenterX)\n\t\t\t\t\t\t\tm_fMapCenterX += MENU_X(15.f);\n\t\t\t\t\t\tm_bShowMouse = false;\n\t\t\t\t\t}\t\t\t\t\n\t\t\t\t}\n\n\t\t\t\tif (CPad::GetPad(0)->GetLeftMouseJustUp()) {\n\t\t\t\t\t// The coordinates in aScreens->MENUPAGE_MAP.\n\t\t\t\t\tif (m_nMousePosX > MENU_X_LEFT_ALIGNED(60.0f) && m_nMousePosX < MENU_X_LEFT_ALIGNED(140.0f)) {\n\t\t\t\t\t\tif (m_nMousePosY > MENU_Y(375.0f) && m_nMousePosY < MENU_Y(400.0f)) {\n\t\t\t\t\t\t\t\tm_nHoverOption = HOVEROPTION_RANDOM_ITEM;\n\t\t\t\t\t\t\t\tgoBack = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (CPad::GetPad(0)->GetLeftMouse() && m_nMousePosX > m_nMouseOldPosX || CPad::GetPad(0)->GetRight() ||\n\t\t\t\t\tCPad::GetPad(0)->GetDPadRight() || CPad::GetPad(0)->GetAnalogueLeftRight() > 0) {\n\t\t\t\t\tif (CTimer::GetTimeInMillisecondsPauseMode() - lastMapTick > 10) {\n\t\t\t\t\t\tif (m_fMapSize > MENU_X(MAP_SIZE_TO_ALLOW_X_MOVE) && SCREEN_WIDTH/2 - (m_fMapSize - MENU_X(MAP_MIN_SIZE)) < m_fMapCenterX)\n\t\t\t\t\t\t\tm_fMapCenterX -= MENU_X(15.f);\n\t\t\t\t\t\tm_bShowMouse = false;\n\t\t\t\t\t}\t\t\t\t\n\t\t\t\t}\n\t\t\t}\n\n\n\t\t\tif (CTimer::GetTimeInMillisecondsPauseMode() - lastMapTick > 10)\n\t\t\t\tlastMapTick = CTimer::GetTimeInMillisecondsPauseMode();\n\n#ifndef MAP_ENHANCEMENTS\n\t\t\tif (CPad::GetPad(0)->GetLeftMouseJustUp())\n\t\t\t\tCentreMousePointer();\n#endif\n\n\t\t\tif (CPad::GetPad(0)->GetLeftMouse()) {\n\t\t\t\tif (m_nMousePosX < SCREEN_STRETCH_X(20.0f) || m_nMousePosX > SCREEN_STRETCH_X(620.0f) || m_nMousePosY < SCREEN_STRETCH_Y(20.0f) || m_nMousePosY > SCREEN_STRETCH_Y(428.0f)) {\n#ifdef MAP_ENHANCEMENTS\n\t\t\t\t\tjustResetPointer = true;\n#endif\n\t\t\t\t\tCentreMousePointer();\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!CPad::GetPad(0)->GetLeftMouse() && !m_bShowMouse && (m_nMouseOldPosX != m_nMousePosX || m_nMouseOldPosY != m_nMousePosY)) {\n\t\t\t\tm_bShowMouse = true;\n\t\t\t}\n\n\t\t\tstatic bool pressedL = false;\n\n\t\t\tif (!CPad::GetPad(0)->GetChar('L') && !CPad::GetPad(0)->GetChar('l')) {\n\t\t\t\tpressedL = false;\n\t\t\t}\n\n\t\t\tif (!pressedL) {\n\t\t\t\tif (CPad::GetPad(0)->GetChar('L') || CPad::GetPad(0)->GetChar('l')) {\n\t\t\t\t\tm_PrefsShowLegends = !m_PrefsShowLegends;\n\t\t\t\t\tpressedL = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tcase MENUPAGE_SOUND_SETTINGS:\n\t\t\tif (CheckHover(MENU_X_LEFT_ALIGNED(177.f), MENU_X_LEFT_ALIGNED(238.f), MENU_Y(MENURADIO_SELECTOR_START_Y - 13.f), MENU_Y(MENURADIO_SELECTOR_START_Y + MENURADIO_SELECTOR_HEIGHT - 8.f))) {\n\t\t\t\t\tm_nHoverOption = HOVEROPTION_PREV_RADIO;\n\t\t\t}\n\n\t\t\tif (CheckHover(MENU_X_LEFT_ALIGNED(422.f), MENU_X_LEFT_ALIGNED(491.f), MENU_Y(MENURADIO_SELECTOR_START_Y - 13.f), MENU_Y(MENURADIO_SELECTOR_START_Y + MENURADIO_SELECTOR_HEIGHT - 8.f))) {\n\t\t\t\t\tm_nHoverOption = HOVEROPTION_NEXT_RADIO;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase MENUPAGE_STATS:\n\t\t{\n\t\t\tif (CPad::GetPad(0)->GetMouseWheelUpJustDown() || CPad::GetPad(0)->GetMouseWheelUpJustUp() || CPad::GetPad(0)->GetUp() ||\n\t\t\t\tCPad::GetPad(0)->GetDPadUp() || CPad::GetPad(0)->GetAnalogueUpDown() < 0) {\n\n\t\t\t\tm_StatsScrollSpeed = 20.0f;\n\t\t\t\tm_StatsScrollDirection = 0;\n\n\t\t\t} else if (CPad::GetPad(0)->GetMouseWheelDownJustDown() || CPad::GetPad(0)->GetMouseWheelDownJustUp() || CPad::GetPad(0)->GetDown() ||\n\t\t\t\tCPad::GetPad(0)->GetDPadDown() || CPad::GetPad(0)->GetAnalogueUpDown() > 0) {\n\t\t\t\t\n\t\t\t\tm_StatsScrollSpeed = 20.0f;\n\t\t\t\tm_StatsScrollDirection = 1;\n\n\t\t\t} else if (CPad::GetPad(0)->GetChar(' ')) {\n\t\t\t\tm_StatsScrollSpeed = 0.0f;\n\t\t\t} else\n\t\t\t\tm_StatsScrollSpeed = 150.0f;\n\n\t\t\tstatic bool pressedS = false;\n\n\t\t\tif (!CPad::GetPad(0)->GetChar('S') && !CPad::GetPad(0)->GetChar('s')) {\n\t\t\t\tpressedS = false;\n\t\t\t}\n\n\t\t\tif (!pressedS) {\n\t\t\t\tif (CPad::GetPad(0)->GetChar('S') || CPad::GetPad(0)->GetChar('s')) {\n\t\t\t\t\tExportStats();\n\t\t\t\t\tm_nHelperTextMsgId = 4;\n\t\t\t\t\tm_nHelperTextAlpha = 300;\n\t\t\t\t\tpressedS = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\n// Not original name\nvoid\nCMenuManager::ExportStats()\n{\n\tchar date[10];\n\tCFileMgr::SetDirMyDocuments();\n\t_strdate(date);\n\twchar *lastMission = TheText.Get(CStats::LastMissionPassedName[0] == '\\0' ? \"ITBEG\" : CStats::LastMissionPassedName);\n\tFILE *txtFile = fopen(\"stats.txt\", \"w\");\n\n\tif (txtFile) {\n\t\tint statLines = CStats::ConstructStatLine(99999);\n\t\tfprintf(txtFile, \"-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\\n\");\n\t\tfprintf(txtFile, \"\\t\\t\\tGTA VICE CITY %s\\n\", UnicodeToAscii(TheText.Get(\"FEH_STA\")));\n\t\tfprintf(txtFile, \"-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\\n\\n\\n\");\n\t\tfprintf(txtFile, \"%s: \", UnicodeToAscii(TheText.Get(\"FES_CMI\")));\n\t\tfprintf(txtFile, \"%s\\n\", UnicodeToAscii(lastMission));\n\t\tfprintf(txtFile, \"%s: \", UnicodeToAscii(TheText.Get(\"FES_DAT\")));\n\t\tfprintf(txtFile, \"%s\\n\\n\\n\", date);\n\t\tfprintf(txtFile, \"%s  \", UnicodeToAscii(TheText.Get(\"CRIMRA\")));\n\t\tUnicodeStrcpy(gUString, CStats::FindCriminalRatingString());\n\t\tfprintf(txtFile, \"%s (%d)\\n\\n\\n\", UnicodeToAscii(gUString), CStats::FindCriminalRatingNumber());\n\t\tfor (int i = 0; i < statLines; ++i) {\n\t\t\tCStats::ConstructStatLine(i);\n\t\t\tchar *statKey = UnicodeToAscii(gUString);\n\t\t\tif (statKey[0] != '\\0')\n\t\t\t\tfprintf(txtFile, \"- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\\n%s\\n\", statKey);\n\n\t\t\tchar *statValue = UnicodeToAscii(gUString2);\n\t\t\tfor (int j = 0; statValue[j] != '\\0'; ++j) {\n\t\t\t\tif (statValue[j] == '_')\n\t\t\t\t\tstatValue[j] = '\\xBA'; // This is degree symbol, but my editors keeps messing up with it so I wrote hex representation\n\t\t\t}\n\t\t\tif (statValue)\n\t\t\t\tfprintf(txtFile, \"%s\\n\\n\", statValue);\n\t\t}\n\t\tfprintf(txtFile, \"-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\\n\\n\");\n\t}\n\tfclose(txtFile);\n\tFILE *htmlFile = fopen(\"stats.html\", \"w\");\n\tif (htmlFile) {\n\t\tint statLines = CStats::ConstructStatLine(99999);\n\t\tfprintf(htmlFile, \"<title>Grand Theft Auto Vice City Stats</title>\\n\");\n\t\tfprintf(htmlFile, \"<body bgcolor=\\\"#FF00CC\\\" leftmargin=\\\"10\\\" topmargin=\\\"10\\\" marginwidth=\\\"10\\\" marginheight=\\\"10\\\">\\n\");\n\t\tfprintf(htmlFile, \"<table width=\\\"560\\\" align=\\\"center\\\" border=\\\"0\\\" cellpadding=\\\"5\\\" cellspacing=\\\"0\\\">\\n\");\n\t\tfprintf(htmlFile, \"<tr align=\\\"center\\\" valign=\\\"top\\\"> \\n\");\n\t\tfprintf(htmlFile, \"<td height=\\\"59\\\" colspan=\\\"2\\\" bgcolor=\\\"#FFCCFF\\\"><div align=\\\"center\\\"><font color=\\\"#FF00CC\\\" size=\\\"3\\\" \"\n\t\t\t\"face=\\\"Arial, \\n\");\n\t\tfprintf(htmlFile, \"Helvetica, sans-serif\\\">-------------------------------------------------------------------------</font><font \\n\");\n\t\tfprintf(htmlFile, \"size=\\\"3\\\" face=\\\"Arial, Helvetica, sans-serif\\\"><br>\\n\");\n\t\tfprintf(htmlFile, \"<strong><font color=\\\"#000000\\\">GRAND THEFT AUTO VICE CITY \");\n\t\tfprintf(htmlFile, \"%s</font></strong><br><font\\n\", UnicodeToAscii(TheText.Get(\"FEH_STA\")));\n\t\tfprintf(htmlFile, \"color=\\\"#FF00CC\\\">-------------------------------------------------------------------------</font></font></div></td> </tr>\\n\");\n\t\tfprintf(htmlFile, \"<tr align=\\\"left\\\" valign=\\\"top\\\" bgcolor=\\\"#FFFFFF\\\">     <td height=\\\"22\\\" colspan=\\\"2\\\">&nbsp;</td>  </tr>\\n\");\n\t\tfprintf(htmlFile, \"<tr align=\\\"left\\\" valign=\\\"top\\\" bgcolor=\\\"#FFFFFF\\\"> \\n\");\n\t\tfprintf(htmlFile,\n\t\t\t\"<td height=\\\"40\\\" colspan=\\\"2\\\"> <p><font color=\\\"#00CC00\\\" size=\\\"2\\\" face=\\\"Arial, Helvetica, sans-serif\\\">\"\n\t\t\t\"<strong><font color=\\\"#009900\\\" size=\\\"1\\\">%s: \\n\", UnicodeToAscii(TheText.Get(\"FES_DAT\")));\n\t\tfprintf(htmlFile, \"%s</font><br>        %s: </strong>\", date, UnicodeToAscii(TheText.Get(\"FES_CMI\")));\n\t\tfprintf(htmlFile, \"%s<strong><br></strong> </font></p></td></tr>\\n\", UnicodeToAscii(lastMission));\n\t\tfprintf(htmlFile, \"<tr align=\\\"left\\\" valign=\\\"top\\\" bgcolor=\\\"#CCCCCC\\\"> <td height=\\\"5\\\" colspan=\\\"2\\\"></td> </tr> <tr align=\\\"\"\n\t\t\t\"left\\\" valign=\\\"top\\\" bgcolor=\\\"#FFFFFF\\\"> \\n\");\n\t\tfprintf(htmlFile, \"<td height=\\\"10\\\" colspan=\\\"2\\\"></td> </tr> <tr align=\\\"left\\\" valign=\\\"top\\\" bgcolor=\\\"#FFFFFF\\\"> \\n\");\n\t\tfprintf(htmlFile, \"<td height=\\\"20\\\" colspan=\\\"2\\\"><font color=\\\"#FF00CC\\\" size=\\\"2\\\" face=\\\"Arial, Helvetica, sans-serif\\\"><str\"\n\t\t\t\"ong>%s</strong>\\n\", UnicodeToAscii(TheText.Get(\"CRIMRA\")));\n\n\t\tUnicodeStrcpy(gUString, CStats::FindCriminalRatingString());\n\t\tchar *statKey = UnicodeToAscii(gUString);\n\t\tint rating = CStats::FindCriminalRatingNumber();\n\t\tfprintf(htmlFile, \"%s (%d)</font></td>  </tr>  <tr align=\\\"left\\\" valign=\\\"top\\\" bgcolor=\\\"#FFFFFF\\\"><td height=\\\"10\\\" colspan=\\\"\"\n\t\t\t\"2\\\"></td>  </tr>\\n\", statKey, rating);\n\n\t\tfor (int k = 0; k < statLines; ++k) {\n\t\t\tCStats::ConstructStatLine(k);\n\t\t\tstatKey = UnicodeToAscii(gUString);\n\t\t\tif (statKey[0] != '\\0')\n\t\t\t\tfprintf(htmlFile, \"</font></strong></div></td> </tr> <tr align=\\\"left\\\" valign=\\\"top\\\" bgcolor=\\\"#FFFFFF\\\">  <td height=\\\"10\"\n\t\t\t\t\t\"\\\" colspan=\\\"2\\\"></td> </tr>\\n\");\n\n\t\t\tfprintf(htmlFile, \"<tr align=\\\"left\\\" valign=\\\"top\\\"><td width=\\\"500\\\" height=\\\"22\\\" bgcolor=\\\"#FFCCFF\\\"><font color=\\\"#FF00CC\"\n\t\t\t\t\"\\\" size=\\\"2\\\" face=\\\"Arial, Helvetica, sans-serif\\\"><strong>\\n\");\n\n\t\t\tif (statKey[0] != '\\0')\n\t\t\t\tfprintf(htmlFile, \"%s\", statKey);\n\t\t\telse\n\t\t\t\tfprintf(htmlFile, \" \");\n\n\t\t\tfprintf(htmlFile, \"</strong></font></td> <td width=\\\"500\\\" align=\\\"right\\\" valign=\\\"middle\\\" bgcolor=\\\"#FFCCFF\\\"> <div align=\\\"\"\n\t\t\t\t\"right\\\"><strong><font color=\\\"#FF00CC\\\">\\n\");\n\n\t\t\tchar *statValue = UnicodeToAscii(gUString2);\n\t\t\tfor (int l = 0; statValue[l] != '\\0'; ++l) {\n\t\t\t\tif (statValue[l] == '_')\n\t\t\t\t\tstatValue[l] = '\\xBA'; // This is degree symbol, but my editors keeps messing up with it so I wrote hex representation\n\t\t\t}\n\t\t\tif (statValue)\n\t\t\t\tfprintf(htmlFile, \"%s\", statValue);\n\t\t\telse\n\t\t\t\tfprintf(htmlFile, \" \");\n\t\t}\n\t\tfprintf(htmlFile, \"</font></strong></div></td> </tr> <tr align=\\\"left\\\" valign=\\\"top\\\" bgcolor=\\\"#FFFFFF\\\">  <td height=\\\"10\\\" c\"\n\t\t\t\"olspan=\\\"2\\\"></td> </tr>\\n\");\n\t\tfprintf(htmlFile, \"</table><br><table width=\\\"560\\\" border=\\\"0\\\"  align=\\\"center\\\" cellspacing=\\\"0\\\" cellpadding=\\\"5\\\"><tr align\"\n\t\t\t\"=\\\"center\\\" valign=\\\"middle\\\" bgcolor=\\\"#FFCCFF\\\">\");\n\t\tfprintf(htmlFile, \"<td><font color=\\\"#000000\\\" size=\\\"2\\\" face=\\\"Arial, Helvetica, sans-serif\\\"><a href=\\\"http://www.rockstargam\"\n\t\t\t\"es.com/vicecity\\\">rockstargames.com/vicecity</a></font></td>\\n\");\n\t\tfprintf(htmlFile, \"<td><font color=\\\"#000000\\\" size=\\\"2\\\" face=\\\"Arial, Helvetica, sans-serif\\\"><a href=\\\"http://www.rockstargam\"\n\t\t\t\"es.com\\\">rockstargames.com</a></font></td>\\n\");\n\t\tfprintf(htmlFile, \"<td><font color=\\\"#000000\\\" size=\\\"2\\\" face=\\\"Arial, Helvetica, sans-serif\\\">&nbsp;<a href=\\\"http://www.rocks\"\n\t\t\t\"tarnorth.com\\\">rockstarnorth.com</a></font></td></tr>\\n\");\n\t\tfprintf(htmlFile, \"</table>\\n</body>\\n\");\n\t}\n\tfclose(htmlFile);\n\tCFileMgr::SetDir(\"\");\n}\n\n// Original name is unknown\nvoid\nCMenuManager::PrintRadioSelector(void)\n{\n\tstatic PauseModeTime lastRadioChange = 0;\n\n\tCSprite2d::Draw2DPolygon(MENU_X_LEFT_ALIGNED(418.f), MENU_Y(MENURADIO_SELECTOR_START_Y + MENURADIO_SELECTOR_HEIGHT),\n\t\tMENU_X_LEFT_ALIGNED(228.f), MENU_Y(MENURADIO_SELECTOR_START_Y + MENURADIO_SELECTOR_HEIGHT),\n\t\tMENU_X_LEFT_ALIGNED(428.f), MENU_Y(MENURADIO_SELECTOR_START_Y),\n\t\tMENU_X_LEFT_ALIGNED(238.f), MENU_Y(MENURADIO_SELECTOR_START_Y), CRGBA(RADIO_SELECTOR_COLOR.r, RADIO_SELECTOR_COLOR.g, RADIO_SELECTOR_COLOR.b, FadeIn(180)));\n\n\tint rightMostSprite, rightMostStation;\n\tif (DMAudio.IsMP3RadioChannelAvailable()) {\n\t\trightMostSprite = MENUSPRITE_MP3;\n\t\trightMostStation = USERTRACK;\n\t} else {\n\t\trightMostSprite = MENUSPRITE_WAVE;\n\t\trightMostStation = WAVE;\n\t}\n #ifdef THIS_IS_STUPID\n\n\t// First radio\n\tif (m_ScrollRadioBy == 1) {\n\t\tif (m_PrefsRadioStation == 1) {\n\t\t\tm_aFrontEndSprites[rightMostSprite].Draw(m_LeftMostRadioX, MENU_Y(MENURADIO_ICON_Y), MENU_X(MENURADIO_ICON_SIZE), MENU_Y(MENURADIO_ICON_SIZE),\n\t\t\t\tCRGBA(INACTIVE_RADIO_COLOR.r, INACTIVE_RADIO_COLOR.g, INACTIVE_RADIO_COLOR.b, FadeIn(INACTIVE_RADIO_COLOR.a)));\n\t\t} else if ( m_PrefsRadioStation == 0) {\n\t\t\tm_aFrontEndSprites[rightMostSprite - 1].Draw(m_LeftMostRadioX, MENU_Y(MENURADIO_ICON_Y), MENU_X(MENURADIO_ICON_SIZE), MENU_Y(MENURADIO_ICON_SIZE),\n\t\t\t\tCRGBA(INACTIVE_RADIO_COLOR.r, INACTIVE_RADIO_COLOR.g, INACTIVE_RADIO_COLOR.b, FadeIn(INACTIVE_RADIO_COLOR.a)));\n\t\t} else {\n\t\t\tm_aFrontEndSprites[m_PrefsRadioStation + MENUSPRITE_WILDSTYLE - 2].Draw(m_LeftMostRadioX, MENU_Y(MENURADIO_ICON_Y), MENU_X(MENURADIO_ICON_SIZE), MENU_Y(MENURADIO_ICON_SIZE),\n\t\t\t\tCRGBA(INACTIVE_RADIO_COLOR.r, INACTIVE_RADIO_COLOR.g, INACTIVE_RADIO_COLOR.b, FadeIn(INACTIVE_RADIO_COLOR.a)));\n\t\t}\n\t}\n\n\t// Second\n\tif (m_PrefsRadioStation == 0) {\n\t\tm_aFrontEndSprites[rightMostSprite].Draw(m_LeftMostRadioX + MENU_X(MENURADIO_ICON_SIZE), MENU_Y(MENURADIO_ICON_Y), MENU_X(MENURADIO_ICON_SIZE), MENU_Y(MENURADIO_ICON_SIZE),\n\t\t\tCRGBA(INACTIVE_RADIO_COLOR.r, INACTIVE_RADIO_COLOR.g, INACTIVE_RADIO_COLOR.b, FadeIn(INACTIVE_RADIO_COLOR.a)));\n\t} else {\n\t\tm_aFrontEndSprites[m_PrefsRadioStation + MENUSPRITE_WILDSTYLE - 1].Draw(m_LeftMostRadioX + MENU_X(MENURADIO_ICON_SIZE), MENU_Y(MENURADIO_ICON_Y), MENU_X(MENURADIO_ICON_SIZE),\n\t\t\tMENU_Y(MENURADIO_ICON_SIZE), CRGBA(INACTIVE_RADIO_COLOR.r, INACTIVE_RADIO_COLOR.g, INACTIVE_RADIO_COLOR.b, FadeIn(INACTIVE_RADIO_COLOR.a)));\n\t}\n\n\t// Third (middle)\n\tint prevStation = m_PrefsRadioStation - 1;\n\tif (prevStation == rightMostStation) {\n\t\tm_aFrontEndSprites[MENUSPRITE_WILDSTYLE + 1].Draw(m_LeftMostRadioX + MENU_X(MENURADIO_ICON_SIZE * 3), MENU_Y(MENURADIO_ICON_Y), MENU_X(MENURADIO_ICON_SIZE), MENU_Y(MENURADIO_ICON_SIZE),\n\t\t\tCRGBA(INACTIVE_RADIO_COLOR.r, INACTIVE_RADIO_COLOR.g, INACTIVE_RADIO_COLOR.b, FadeIn(INACTIVE_RADIO_COLOR.a)));\n\t} else if ( prevStation == rightMostStation - 1) {\n\t\tm_aFrontEndSprites[MENUSPRITE_WILDSTYLE].Draw(m_LeftMostRadioX + MENU_X(MENURADIO_ICON_SIZE * 3), MENU_Y(MENURADIO_ICON_Y), MENU_X(MENURADIO_ICON_SIZE), MENU_Y(MENURADIO_ICON_SIZE),\n\t\t\tCRGBA(INACTIVE_RADIO_COLOR.r, INACTIVE_RADIO_COLOR.g, INACTIVE_RADIO_COLOR.b, FadeIn(INACTIVE_RADIO_COLOR.a)));\n\t} else {\n\t\tm_aFrontEndSprites[m_PrefsRadioStation + MENUSPRITE_WILDSTYLE + 1].Draw(m_LeftMostRadioX + MENU_X(MENURADIO_ICON_SIZE * 3), MENU_Y(MENURADIO_ICON_Y), MENU_X(MENURADIO_ICON_SIZE), MENU_Y(MENURADIO_ICON_SIZE),\n\t\t\tCRGBA(INACTIVE_RADIO_COLOR.r, INACTIVE_RADIO_COLOR.g, INACTIVE_RADIO_COLOR.b, FadeIn(INACTIVE_RADIO_COLOR.a)));\n\t}\n\n\t// Fifth\n\tif (m_ScrollRadioBy == -1) {\n\t\tint prevStation = m_PrefsRadioStation - 1;\n\t\tif (prevStation == rightMostStation) {\n\t\t\tm_aFrontEndSprites[MENUSPRITE_WILDSTYLE + 4].Draw(m_LeftMostRadioX + MENU_X(MENURADIO_ICON_SIZE * 4), MENU_Y(MENURADIO_ICON_Y), MENU_X(MENURADIO_ICON_SIZE), MENU_Y(MENURADIO_ICON_SIZE),\n\t\t\t\tCRGBA(INACTIVE_RADIO_COLOR.r, INACTIVE_RADIO_COLOR.g, INACTIVE_RADIO_COLOR.b, FadeIn(INACTIVE_RADIO_COLOR.a)));\n\t\t} else if (prevStation == rightMostStation - 1) {\n\t\t\tm_aFrontEndSprites[MENUSPRITE_WILDSTYLE + 1].Draw(m_LeftMostRadioX + MENU_X(MENURADIO_ICON_SIZE * 4), MENU_Y(MENURADIO_ICON_Y), MENU_X(MENURADIO_ICON_SIZE), MENU_Y(MENURADIO_ICON_SIZE),\n\t\t\t\tCRGBA(INACTIVE_RADIO_COLOR.r, INACTIVE_RADIO_COLOR.g, INACTIVE_RADIO_COLOR.b, FadeIn(INACTIVE_RADIO_COLOR.a)));\n\t\t} else if ( prevStation == rightMostStation - 2) {\n\t\t\tm_aFrontEndSprites[MENUSPRITE_WILDSTYLE].Draw(m_LeftMostRadioX + MENU_X(MENURADIO_ICON_SIZE * 4), MENU_Y(MENURADIO_ICON_Y), MENU_X(MENURADIO_ICON_SIZE), MENU_Y(MENURADIO_ICON_SIZE),\n\t\t\t\tCRGBA(INACTIVE_RADIO_COLOR.r, INACTIVE_RADIO_COLOR.g, INACTIVE_RADIO_COLOR.b, FadeIn(INACTIVE_RADIO_COLOR.a)));\n\t\t} else {\n\t\t\tm_aFrontEndSprites[m_PrefsRadioStation + MENUSPRITE_WILDSTYLE + 2].Draw(m_LeftMostRadioX + MENU_X(MENURADIO_ICON_SIZE * 4), MENU_Y(MENURADIO_ICON_Y), MENU_X(MENURADIO_ICON_SIZE), MENU_Y(MENURADIO_ICON_SIZE),\n\t\t\t\tCRGBA(INACTIVE_RADIO_COLOR.r, INACTIVE_RADIO_COLOR.g, INACTIVE_RADIO_COLOR.b, FadeIn(INACTIVE_RADIO_COLOR.a)));\n\t\t}\n\t}\n\n\t// Fourth\n\tif (m_ScrollRadioBy == 0) {\n\t\tm_aFrontEndSprites[m_PrefsRadioStation + MENUSPRITE_WILDSTYLE].Draw(m_LeftMostRadioX + MENU_X(MENURADIO_ICON_SIZE * 2 - 10.f), MENU_Y(MENURADIO_ICON_Y - 10.f), MENU_X(MENURADIO_ICON_SIZE) + MENU_X(20.f), MENU_Y(MENURADIO_ICON_SIZE) + MENU_Y(20.f),\n\t\t\tCRGBA(255, 255, 255, FadeIn(255)));\n\t} else {\t\n\t\tif (m_PrefsRadioStation - 1 == rightMostStation) {\n\t\t\tm_aFrontEndSprites[MENUSPRITE_WILDSTYLE].Draw(m_LeftMostRadioX + MENU_X(MENURADIO_ICON_SIZE * 2), MENU_Y(MENURADIO_ICON_Y), MENU_X(MENURADIO_ICON_SIZE), MENU_Y(MENURADIO_ICON_SIZE),\n\t\t\t\tCRGBA(INACTIVE_RADIO_COLOR.r, INACTIVE_RADIO_COLOR.g, INACTIVE_RADIO_COLOR.b, FadeIn(INACTIVE_RADIO_COLOR.a)));\n\t\t} else {\n\t\t\tm_aFrontEndSprites[m_PrefsRadioStation + MENUSPRITE_WILDSTYLE].Draw(m_LeftMostRadioX + MENU_X(MENURADIO_ICON_SIZE * 2), MENU_Y(MENURADIO_ICON_Y), MENU_X(MENURADIO_ICON_SIZE), MENU_Y(MENURADIO_ICON_SIZE),\n\t\t\t\tCRGBA(INACTIVE_RADIO_COLOR.r, INACTIVE_RADIO_COLOR.g, INACTIVE_RADIO_COLOR.b, FadeIn(INACTIVE_RADIO_COLOR.a)));\n\t\t}\n\t}\n#else\n\tint first = ((m_PrefsRadioStation - 2) + rightMostStation + 1) % (rightMostStation + 1);\n\tint second = ((m_PrefsRadioStation - 1) + rightMostStation + 1) % (rightMostStation + 1);\n\tint third = ((m_PrefsRadioStation) + rightMostStation + 1) % (rightMostStation + 1);\n\tint fourth = ((m_PrefsRadioStation + 1) + rightMostStation + 1) % (rightMostStation + 1);\n\tint fifth = ((m_PrefsRadioStation + 2) + rightMostStation + 1) % (rightMostStation + 1);\n\n\t// First one is only drawn on transition to next\n\tif (m_ScrollRadioBy == 1) {\n\t\tm_aFrontEndSprites[first + MENUSPRITE_WILDSTYLE].Draw(m_LeftMostRadioX, MENU_Y(MENURADIO_ICON_Y), MENU_X(MENURADIO_ICON_SIZE), MENU_Y(MENURADIO_ICON_SIZE),\n\t\t\tCRGBA(INACTIVE_RADIO_COLOR.r, INACTIVE_RADIO_COLOR.g, INACTIVE_RADIO_COLOR.b, FadeIn(INACTIVE_RADIO_COLOR.a)));\n\t}\n\n\t// Second\n\tm_aFrontEndSprites[second + MENUSPRITE_WILDSTYLE].Draw(m_LeftMostRadioX + MENU_X(MENURADIO_ICON_SIZE), MENU_Y(MENURADIO_ICON_Y), MENU_X(MENURADIO_ICON_SIZE), MENU_Y(MENURADIO_ICON_SIZE),\n\t\tCRGBA(INACTIVE_RADIO_COLOR.r, INACTIVE_RADIO_COLOR.g, INACTIVE_RADIO_COLOR.b, FadeIn(INACTIVE_RADIO_COLOR.a)));\n\n\t// Fourth\n\tm_aFrontEndSprites[fourth + MENUSPRITE_WILDSTYLE].Draw(m_LeftMostRadioX + MENU_X(MENURADIO_ICON_SIZE * 3), MENU_Y(MENURADIO_ICON_Y), MENU_X(MENURADIO_ICON_SIZE), MENU_Y(MENURADIO_ICON_SIZE),\n\t\tCRGBA(INACTIVE_RADIO_COLOR.r, INACTIVE_RADIO_COLOR.g, INACTIVE_RADIO_COLOR.b, FadeIn(INACTIVE_RADIO_COLOR.a)));\n\n\t// Fifth one is only drawn on transition to prev.\n\tif (m_ScrollRadioBy == -1) {\n\t\tm_aFrontEndSprites[fifth + MENUSPRITE_WILDSTYLE].Draw(m_LeftMostRadioX + MENU_X(MENURADIO_ICON_SIZE * 4), MENU_Y(MENURADIO_ICON_Y), MENU_X(MENURADIO_ICON_SIZE), MENU_Y(MENURADIO_ICON_SIZE),\n\t\t\tCRGBA(INACTIVE_RADIO_COLOR.r, INACTIVE_RADIO_COLOR.g, INACTIVE_RADIO_COLOR.b, FadeIn(INACTIVE_RADIO_COLOR.a)));\n\t}\n\n\t// Middle one(third) is colored differently depending on if it's in transition.\n\t// If not in transition then this icon indicates selected radio, and should be on top of all icons. thus drawn last\n\tif (m_ScrollRadioBy != 0) {\n\t\tm_aFrontEndSprites[third + MENUSPRITE_WILDSTYLE].Draw(m_LeftMostRadioX + MENU_X(MENURADIO_ICON_SIZE * 2), MENU_Y(MENURADIO_ICON_Y), MENU_X(MENURADIO_ICON_SIZE), MENU_Y(MENURADIO_ICON_SIZE),\n\t\t\tCRGBA(INACTIVE_RADIO_COLOR.r, INACTIVE_RADIO_COLOR.g, INACTIVE_RADIO_COLOR.b, FadeIn(INACTIVE_RADIO_COLOR.a)));\t\t\n\t} else {\n\t\tm_aFrontEndSprites[third + MENUSPRITE_WILDSTYLE].Draw(m_LeftMostRadioX + MENU_X(MENURADIO_ICON_SIZE * 2 - 10.f), MENU_Y(MENURADIO_ICON_Y - 10.f), MENU_X(MENURADIO_ICON_SIZE) + MENU_X(20.f), MENU_Y(MENURADIO_ICON_SIZE) + MENU_Y(20.f),\n\t\t\tCRGBA(255, 255, 255, FadeIn(255)));\n\t}\n#endif\n\n\tstatic bool radioChangeRequested = false;\n\tstatic PauseModeTime lastScrollCheck = 0;\n\tif (CTimer::GetTimeInMillisecondsPauseMode() - lastScrollCheck > 17) {\n\t\tif (m_ScrollRadioBy == 1) {\n\t\t\tif (m_LeftMostRadioX > MENU_X_LEFT_ALIGNED(MENURADIO_ICON_FIRST_X - MENURADIO_ICON_SIZE)) {\n\t\t\t\tm_LeftMostRadioX -= MENU_X(6.f);\n\t\t\t} else {\n\t\t\t\tm_ScrollRadioBy = 0;\n\t\t\t\tlastRadioChange = CTimer::GetTimeInMillisecondsPauseMode();\n\t\t\t\tradioChangeRequested = true;\n\t\t\t}\n\t\t}\n\t\tif (m_ScrollRadioBy == -1) {\n\t\t\tif (m_LeftMostRadioX < MENU_X_LEFT_ALIGNED(MENURADIO_ICON_FIRST_X - MENURADIO_ICON_SIZE)) {\n\t\t\t\tm_LeftMostRadioX += MENU_X(6.f);\n\t\t\t} else {\n\t\t\t\tm_ScrollRadioBy = 0;\n\t\t\t\tlastRadioChange = CTimer::GetTimeInMillisecondsPauseMode();\n\t\t\t\tradioChangeRequested = true;\n\t\t\t}\n\t\t}\n\t\tlastScrollCheck = CTimer::GetTimeInMillisecondsPauseMode();\n\t}\n\t// Background behind arrows\n\tCSprite2d::Draw2DPolygon(MENU_X_LEFT_ALIGNED(228.f), MENU_Y(MENURADIO_SELECTOR_START_Y + MENURADIO_SELECTOR_HEIGHT),\n\t\tMENU_X_LEFT_ALIGNED(168.f), MENU_Y(MENURADIO_SELECTOR_START_Y + MENURADIO_SELECTOR_HEIGHT),\n\t\tMENU_X_LEFT_ALIGNED(238.f), MENU_Y(MENURADIO_SELECTOR_START_Y),\n\t\tMENU_X_LEFT_ALIGNED(178.f), MENU_Y(MENURADIO_SELECTOR_START_Y),\n\t\tCRGBA(RADIO_SELECTOR_COLOR.r, RADIO_SELECTOR_COLOR.g, RADIO_SELECTOR_COLOR.b, FadeIn(255)));\n\t\n\tCSprite2d::Draw2DPolygon(MENU_X_LEFT_ALIGNED(478.f), MENU_Y(MENURADIO_SELECTOR_START_Y + MENURADIO_SELECTOR_HEIGHT),\n\t\tMENU_X_LEFT_ALIGNED(418.f), MENU_Y(MENURADIO_SELECTOR_START_Y + MENURADIO_SELECTOR_HEIGHT),\n\t\tMENU_X_LEFT_ALIGNED(488.f), MENU_Y(MENURADIO_SELECTOR_START_Y),\n\t\tMENU_X_LEFT_ALIGNED(428.f), MENU_Y(MENURADIO_SELECTOR_START_Y),\n\t\tCRGBA(RADIO_SELECTOR_COLOR.r, RADIO_SELECTOR_COLOR.g, RADIO_SELECTOR_COLOR.b, FadeIn(255)));\n\t\n\t// Arrows and their shadows\n\tCSprite2d::Draw2DPolygon(MENU_X_LEFT_ALIGNED(216.f), MENU_Y(MENURADIO_SELECTOR_START_Y + 48.f), MENU_X_LEFT_ALIGNED(196.f), MENU_Y(MENURADIO_SELECTOR_START_Y + 36.f), MENU_X_LEFT_ALIGNED(216.f), MENU_Y(MENURADIO_SELECTOR_START_Y + 22.f), MENU_X_LEFT_ALIGNED(196.f), MENU_Y(MENURADIO_SELECTOR_START_Y + 36.f), CRGBA(0, 0, 0, FadeIn(255)));\n\tCSprite2d::Draw2DPolygon(MENU_X_LEFT_ALIGNED(213.f), MENU_Y(MENURADIO_SELECTOR_START_Y + 45.f), MENU_X_LEFT_ALIGNED(193.f), MENU_Y(MENURADIO_SELECTOR_START_Y + 33.f), MENU_X_LEFT_ALIGNED(213.f), MENU_Y(MENURADIO_SELECTOR_START_Y + 19.f), MENU_X_LEFT_ALIGNED(193.f), MENU_Y(MENURADIO_SELECTOR_START_Y + 33.f), CRGBA(97, 194, 247, FadeIn(255)));\n\tCSprite2d::Draw2DPolygon(MENU_X_LEFT_ALIGNED(440.f), MENU_Y(MENURADIO_SELECTOR_START_Y + 48.f), MENU_X_LEFT_ALIGNED(460.f), MENU_Y(MENURADIO_SELECTOR_START_Y + 36.f), MENU_X_LEFT_ALIGNED(440.f), MENU_Y(MENURADIO_SELECTOR_START_Y + 22.f), MENU_X_LEFT_ALIGNED(460.f), MENU_Y(MENURADIO_SELECTOR_START_Y + 36.f), CRGBA(0, 0, 0, FadeIn(255)));\n\tCSprite2d::Draw2DPolygon(MENU_X_LEFT_ALIGNED(443.f), MENU_Y(MENURADIO_SELECTOR_START_Y + 45.f), MENU_X_LEFT_ALIGNED(463.f), MENU_Y(MENURADIO_SELECTOR_START_Y + 33.f), MENU_X_LEFT_ALIGNED(443.f), MENU_Y(MENURADIO_SELECTOR_START_Y + 19.f), MENU_X_LEFT_ALIGNED(463.f), MENU_Y(MENURADIO_SELECTOR_START_Y + 33.f), CRGBA(97, 194, 247, FadeIn(255)));\n\tif (radioChangeRequested) {\n\t\tif (CTimer::GetTimeInMillisecondsPauseMode() - lastRadioChange > 50) {\n\t\t\tDMAudio.SetRadioInCar(m_PrefsRadioStation);\n\t\t\tDMAudio.PlayFrontEndTrack(m_PrefsRadioStation, 1);\n\t\t\tOutputDebugString(\"FRONTEND RADIO STATION CHANGED\");\n\t\t\tlastRadioChange = CTimer::GetTimeInMillisecondsPauseMode();\n\t\t\tradioChangeRequested = false;\n\t\t}\n\t}\n}\n\n// Original name is unknown\nvoid\nCMenuManager::ProcessList(bool &optionSelected, bool &goBack)\n{\n\tif (m_bWaitingForNewKeyBind)\n\t\treturn;\n\n\tif (m_nCurrScreen == MENUPAGE_SKIN_SELECT) {\n\t\tm_nTotalListRow = m_nSkinsTotal;\n\t}\n\tif (m_nCurrScreen == MENUPAGE_KEYBOARD_CONTROLS) {\n\t\t// GetNumOptionsCntrlConfigScreens would have been a better choice\n\t\tm_nTotalListRow = m_ControlMethod == CONTROL_CLASSIC ? 32 : 27;\n\t\tif (m_nSelectedListRow > m_nTotalListRow)\n\t\t\tm_nSelectedListRow = m_nTotalListRow - 1;\n\t}\n\n\tif (CPad::GetPad(0)->GetEnterJustDown() || CPad::GetPad(0)->GetCrossJustDown()) {\n\t\tm_bShowMouse = 0;\n\t\toptionSelected = true;\n\t}\n\tif (CPad::GetPad(0)->GetBackspaceJustDown() && m_nCurrScreen == MENUPAGE_KEYBOARD_CONTROLS && !field_159) {\n\t\tif (m_nCurrExLayer == HOVEROPTION_LIST) {\n\t\t\tm_nHoverOption = HOVEROPTION_NOT_HOVERING;\n\t\t\tm_bWaitingForNewKeyBind = true;\n\t\t\tm_bStartWaitingForKeyBind = true;\n\t\t\tm_bKeyChangeNotProcessed = true;\n\t\t\tpControlEdit = &m_KeyPressedCode;\n\t\t}\n\t} else {\n\t\tfield_159 = false;\n\t}\n\n\tstatic PauseModeTime lastTimeClickedScrollButton = 0;\n\n\tif (CTimer::GetTimeInMillisecondsPauseMode() - lastTimeClickedScrollButton >= 200) {\n\t\tm_bPressedPgUpOnList = false;\n\t\tm_bPressedPgDnOnList = false;\n\t\tm_bPressedUpOnList = false;\n\t\tm_bPressedDownOnList = false;\n\t\tm_bPressedScrollButton = false;\n\t\tlastTimeClickedScrollButton = CTimer::GetTimeInMillisecondsPauseMode();\n\t}\n\n\tif (CPad::GetPad(0)->GetTabJustDown()) {\n\t\tDMAudio.PlayFrontEndSound(SOUND_FRONTEND_HIGHLIGHT_OPTION, 0);\n\t\tm_bShowMouse = false;\n\t\tswitch (m_nCurrExLayer) {\n\t\tcase HOVEROPTION_BACK:\n\t\tdefault:\n\t\t\tm_nCurrExLayer = HOVEROPTION_LIST;\n\t\t\tbreak;\n\t\tcase HOVEROPTION_LIST:\n\t\t\tm_nCurrExLayer = HOVEROPTION_USESKIN;\n\t\t\tbreak;\n\t\tcase HOVEROPTION_USESKIN:\n\t\t\tm_nCurrExLayer = HOVEROPTION_BACK;\n\t\t}\n\t\tif (((m_nCurrScreen == MENUPAGE_SKIN_SELECT) && (m_nCurrExLayer == HOVEROPTION_USESKIN)) && strcmp(m_aSkinName, m_PrefsSkinFile) == 0) {\n\t\t\tm_nCurrExLayer = HOVEROPTION_BACK;\n\t\t}\n\t\tif ((m_nCurrScreen == MENUPAGE_KEYBOARD_CONTROLS) && (m_nCurrExLayer == HOVEROPTION_USESKIN)) {\n\t\t\tm_nCurrExLayer = HOVEROPTION_BACK;\n\t\t}\n\t}\n\n\tbool pressed = false;\n\tif (CPad::GetPad(0)->GetUp() || CPad::GetPad(0)->GetAnaloguePadUp() || CPad::GetPad(0)->GetDPadUpJustDown()) {\n\t\tm_bShowMouse = false;\n\t\tpressed = true;\n\t} else if (CPad::GetPad(0)->GetMouseWheelUpJustUp()) {\n\t\tm_bShowMouse = true;\n\t\tpressed = true;\n\t}\n\n\t// Up\n\tif (pressed) {\n\t\tm_nCurrExLayer = HOVEROPTION_LIST;\n\t\tif (!m_bPressedUpOnList) {\n\t\t\tm_bPressedUpOnList = true;\n\t\t\tlastTimeClickedScrollButton = CTimer::GetTimeInMillisecondsPauseMode();\n\t\t\tDMAudio.PlayFrontEndSound(SOUND_FRONTEND_HIGHLIGHT_OPTION, 0);\n\t\t\tScrollUpListByOne();\n\t\t}\n\t} else {\n\t\tm_bPressedUpOnList = false;\n\t}\n\n\tpressed = false;\n\tif (CPad::GetPad(0)->GetDown() || CPad::GetPad(0)->GetAnaloguePadDown() || CPad::GetPad(0)->GetDPadDownJustDown()) {\n\t\tm_bShowMouse = false;\n\t\tpressed = true;\n\t} else if (CPad::GetPad(0)->GetMouseWheelDownJustDown()) {\n\t\tm_bShowMouse = true;\n\t\tpressed = true;\n\t}\n\n\t// Down\n\tif (pressed) {\n\t\tm_nCurrExLayer = HOVEROPTION_LIST;\n\t\tif (!m_bPressedDownOnList) {\n\t\t\tm_bPressedDownOnList = true;\n\t\t\tlastTimeClickedScrollButton = CTimer::GetTimeInMillisecondsPauseMode();\n\t\t\tDMAudio.PlayFrontEndSound(SOUND_FRONTEND_HIGHLIGHT_OPTION, 0);\n\t\t\tScrollDownListByOne();\n\t\t}\n\t} else {\n\t\tm_bPressedDownOnList = false;\n\t}\n\n\tif (m_nCurrScreen != MENUPAGE_KEYBOARD_CONTROLS) {\n\t\tif (!CPad::GetPad(0)->GetPageUp()) {\n\t\t\tm_bPressedPgUpOnList = false;\n\t\t} else {\n\t\t\tm_nCurrExLayer = HOVEROPTION_LIST;\n\t\t\tif (!m_bPressedPgUpOnList) {\n\t\t\t\tm_bPressedPgUpOnList = true;\n\t\t\t\tlastTimeClickedScrollButton = CTimer::GetTimeInMillisecondsPauseMode();\n\t\t\t\tm_bShowMouse = false;\n\t\t\t\tDMAudio.PlayFrontEndSound(SOUND_FRONTEND_HIGHLIGHT_OPTION, 0);\n\t\t\t\tPageUpList(false);\n\t\t\t}\n\t\t}\n\t\tif (!CPad::GetPad(0)->GetPageDown()) {\n\t\t\tm_bPressedPgDnOnList = false;\n\t\t} else {\n\t\t\tm_nCurrExLayer = HOVEROPTION_LIST;\n\t\t\tif (!m_bPressedPgDnOnList) {\n\t\t\t\tm_bPressedPgDnOnList = true;\n\t\t\t\tlastTimeClickedScrollButton = CTimer::GetTimeInMillisecondsPauseMode();\n\t\t\t\tm_bShowMouse = false;\n\t\t\t\tDMAudio.PlayFrontEndSound(SOUND_FRONTEND_HIGHLIGHT_OPTION, 0);\n\t\t\t\tPageDownList(false);\n\t\t\t}\n\t\t}\n\t\tif (CPad::GetPad(0)->GetHome()) {\n\t\t\tm_nCurrExLayer = HOVEROPTION_LIST;\n\t\t\tm_bShowMouse = false;\n\t\t\tDMAudio.PlayFrontEndSound(SOUND_FRONTEND_HIGHLIGHT_OPTION, 0);\n\t\t\tif (m_nTotalListRow >= MAX_VISIBLE_OPTION_ON_SCREEN) {\n\t\t\t\tm_nFirstVisibleRowOnList = 0;\n\t\t\t}\n\t\t\tm_nSelectedListRow = 0;\n\t\t\tm_nScrollbarTopMargin = (SCROLLBAR_MAX_HEIGHT / m_nTotalListRow) * m_nFirstVisibleRowOnList;\n\t\t}\n\t\tif (CPad::GetPad(0)->GetEnd()) {\n\t\t\tm_nCurrExLayer = HOVEROPTION_LIST;\n\t\t\tm_bShowMouse = false;\n\t\t\tDMAudio.PlayFrontEndSound(SOUND_FRONTEND_HIGHLIGHT_OPTION, 0);\n\t\t\tif (m_nTotalListRow >= MAX_VISIBLE_OPTION_ON_SCREEN) {\n\t\t\t\tm_nFirstVisibleRowOnList = m_nTotalListRow - MAX_VISIBLE_OPTION_ON_SCREEN;\n\t\t\t}\n\t\t\tm_nSelectedListRow = m_nTotalListRow - 1;\n\t\t\tm_nScrollbarTopMargin = (SCROLLBAR_MAX_HEIGHT / m_nTotalListRow) * m_nFirstVisibleRowOnList;\n\t\t}\n\t}\n\n\tif (CPad::GetPad(0)->GetEscapeJustDown() || CPad::GetPad(0)->GetBackJustDown()) {\n\t\tm_bShowMouse = false;\n\t\tgoBack = true;\n\t}\n\n\tif (CPad::GetPad(0)->GetLeftMouseJustDown()) {\n\t\tswitch (m_nHoverOption) {\n\t\tcase HOVEROPTION_BACK:\n\t\t\tgoBack = true;\n\t\t\tbreak;\n\t\tcase HOVEROPTION_PAGEUP:\n\t\t\tPageUpList(true);\n\t\t\tbreak;\n\t\tcase HOVEROPTION_PAGEDOWN:\n\t\t\tPageDownList(true);\n\t\t\tbreak;\n\t\tcase HOVEROPTION_USESKIN:\n\t\t\tif (m_nSkinsTotal > 0) {\n\t\t\t\tm_pSelectedSkin = m_pSkinListHead.nextSkin;\n\t\t\t\tstrcpy(m_PrefsSkinFile, m_aSkinName);\n\t\t\t\tCWorld::Players[0].SetPlayerSkin(m_PrefsSkinFile);\n\t\t\t\tSaveSettings();\n\t\t\t}\n\t\t}\n\t}\n\n\tif (CPad::GetPad(0)->GetLeftMouseJustDown()) {\n\t\tswitch (m_nHoverOption) {\n\t\tcase HOVEROPTION_OVER_SCROLL_UP:\n\t\t\tm_nHoverOption = HOVEROPTION_CLICKED_SCROLL_UP;\n\t\t\tbreak;\n\t\tcase HOVEROPTION_OVER_SCROLL_DOWN:\n\t\t\tm_nHoverOption = HOVEROPTION_CLICKED_SCROLL_DOWN;\n\t\t\tbreak;\n\t\tcase HOVEROPTION_LIST:\n\t\t\tm_nHoverOption = HOVEROPTION_SKIN;\n\t\t}\n\t} else if ((CPad::GetPad(0)->GetLeftMouseJustUp())\n\t\t&& ((m_nHoverOption == HOVEROPTION_CLICKED_SCROLL_UP || (m_nHoverOption == HOVEROPTION_CLICKED_SCROLL_DOWN)))) {\n\t\tm_nHoverOption = HOVEROPTION_NOT_HOVERING;\n\t}\n\n\tif (!CPad::GetPad(0)->GetLeftMouse()) {\n\t\tholdingScrollBar = false;\n\t} else {\n\t\tif ((m_nHoverOption == HOVEROPTION_HOLDING_SCROLLBAR) || holdingScrollBar) {\n\t\t\tholdingScrollBar = true;\n\t\t\t// TODO: This part is a bit hard to reverse. Not much code tho\n\t\t\tassert(0 && \"Holding scrollbar isn't done yet\");\n\t\t} else {\n\t\t\tswitch (m_nHoverOption) {\n\t\t\tcase HOVEROPTION_OVER_SCROLL_UP:\n\t\t\tcase HOVEROPTION_CLICKED_SCROLL_UP:\n\t\t\t\tif (!m_bPressedScrollButton) {\n\t\t\t\t\tm_bPressedScrollButton = true;\n\t\t\t\t\tlastTimeClickedScrollButton = CTimer::GetTimeInMillisecondsPauseMode();\n\t\t\t\t\tScrollUpListByOne();\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase HOVEROPTION_OVER_SCROLL_DOWN:\n\t\t\tcase HOVEROPTION_CLICKED_SCROLL_DOWN:\n\t\t\t\tif (!m_bPressedScrollButton) {\n\t\t\t\t\tm_bPressedScrollButton = true;\n\t\t\t\t\tlastTimeClickedScrollButton = CTimer::GetTimeInMillisecondsPauseMode();\n\t\t\t\t\tScrollDownListByOne();\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tm_bPressedScrollButton = false;\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nCMenuManager::UserInput(void)\n{\n\tbool goBack = false;\n\tbool optionSelected = false;\n\tbool goUp = false;\n\tbool goDown = false;\n\tint8 changeValueBy;\n\n\tif (!m_AllowNavigation && m_firstStartCounter == 255)\n\t\tm_AllowNavigation = true;\n\tif (!m_bShowMouse && m_nCurrScreen != MENUPAGE_MAP && (m_nMouseOldPosX != m_nMousePosX || m_nMouseOldPosY != m_nMousePosY)) {\n\t\tm_bShowMouse = true;\n\t}\n\n\tstatic int oldOption = -99;\n\toldOption = m_nCurrOption;\n#ifdef SCROLLABLE_PAGES\n\tint firstOption = SCREEN_HAS_AUTO_SCROLLBAR ? m_nFirstVisibleRowOnList : 0;\n\tint scrollOffset = aScreens[m_nCurrScreen].m_aEntries[firstOption].m_Y - aScreens[m_nCurrScreen].m_aEntries[0].m_Y;\n\tfor (int rowToCheck = firstOption; rowToCheck < firstOption + MAX_VISIBLE_OPTION && rowToCheck < NUM_MENUROWS; ++rowToCheck) {\n#else\n\tfor (int rowToCheck = 0; rowToCheck < NUM_MENUROWS; ++rowToCheck) {\n#endif\n\t\tif (aScreens[m_nCurrScreen].m_aEntries[rowToCheck].m_Action == MENUACTION_NOTHING || \n\t\t\taScreens[m_nCurrScreen].m_aEntries[rowToCheck].m_Action == MENUACTION_LABEL)\n\t\t\tcontinue;\n\n\t\t// unused: CFont::GetStringWidth(TheText.Get(aScreens[m_nCurrScreen].m_aEntries[rowToCheck].m_EntryName), true);\n\t\t// So they also wanted the compare X, but they abandoned the idea later on\n\n\t\tif (m_nMousePosY > MENU_Y(aScreens[m_nCurrScreen].m_aEntries[rowToCheck].m_Y MINUS_SCROLL_OFFSET) &&\n\t\t\tm_nMousePosY < MENU_Y(aScreens[m_nCurrScreen].m_aEntries[rowToCheck].m_Y MINUS_SCROLL_OFFSET PLUS_LINE_HEIGHT_ON_SCREEN)) {\n\t\t\tstatic int oldScreen = m_nCurrScreen;\n\n\t\t\tm_nOptionMouseHovering = rowToCheck;\n\t\t\tif (m_nMouseOldPosX != m_nMousePosX || m_nMouseOldPosY != m_nMousePosY) {\n\t\t\t\tm_nCurrOption = rowToCheck;\n\t\t\t\tm_bShowMouse = true;\n\t\t\t}\n\n\t\t\tint action = aScreens[m_nCurrScreen].m_aEntries[rowToCheck].m_Action;\n\t\t\tif (action != MENUACTION_BRIGHTNESS && action != MENUACTION_DRAWDIST && action != MENUACTION_MUSICVOLUME\n\t\t\t\t&& action != MENUACTION_SFXVOLUME && action != MENUACTION_MOUSESENS && action != MENUACTION_MP3VOLUMEBOOST)\n\t\t\t\tm_nHoverOption = HOVEROPTION_RANDOM_ITEM;\n\n\t\t\tbreak;\n\t\t}\n\t\tif (m_bShowMouse && m_nMenuFadeAlpha == 255) {\n\t\t\tm_nOptionMouseHovering = oldOption;\n\t\t\tm_nCurrOption = oldOption;\n\t\t}\n\t}\n\n\tif (m_bShowMouse) {\n\t\tif (oldOption != m_nCurrOption) {\n\t\t\tif (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action == MENUACTION_LABEL) {\n\t\t\t\t++m_nCurrOption;\n\t\t\t\t++m_nOptionMouseHovering;\n\t\t\t}\n\t\t\tm_nOptionHighlightTransitionBlend = 0;\n\t\t\tDMAudio.PlayFrontEndSound(SOUND_FRONTEND_HIGHLIGHT_OPTION, 0);\n\t\t}\n\t}\n\n\tm_nMouseOldPosX = m_nMousePosX;\n\tm_nMouseOldPosY = m_nMousePosY;\n\tm_nMousePosX = m_nMouseTempPosX;\n\tm_nMousePosY = m_nMouseTempPosY;\n\n\tif (m_nMousePosX < 0) m_nMousePosX = 0;\n\tif (m_nMousePosX > SCREEN_WIDTH) m_nMousePosX = SCREEN_WIDTH;\n\tif (m_nMousePosY < 0) m_nMousePosY = 0;\n\tif (m_nMousePosY > SCREEN_HEIGHT) m_nMousePosY = SCREEN_HEIGHT;\n\n\tchangeValueBy = 0;\n\tif (hasNativeList(m_nCurrScreen)) {\n\t\tProcessList(optionSelected, goBack);\n\t} else {\n\t\tAdditionalOptionInput(goBack);\n\n\t\tif (m_AllowNavigation &&\n\t\t\t(CPad::GetPad(0)->GetDownJustDown() || CPad::GetPad(0)->GetAnaloguePadDown() || CPad::GetPad(0)->GetDPadDownJustDown())) {\n\t\t\tm_bShowMouse = false;\n\t\t\tgoDown = true;\n\t\t\tm_nOptionHighlightTransitionBlend = 0;\n\n\t\t} else if (m_AllowNavigation &&\n\t\t\t(CPad::GetPad(0)->GetUpJustDown() || CPad::GetPad(0)->GetAnaloguePadUp() || CPad::GetPad(0)->GetDPadUpJustDown())) {\n\t\t\tm_bShowMouse = false;\n\t\t\tgoUp = true;\n\t\t\tm_nOptionHighlightTransitionBlend = 0;\n\t\t}\n\n\t\tif ((m_nCurrOption == 0) && (m_nCurrScreen == MENUPAGE_PAUSE_MENU)) {\n\t\t\tif (CPad::GetPad(0)->GetEnterJustUp() || CPad::GetPad(0)->GetCrossJustUp()) {\n\t\t\t\tm_bShowMouse = false;\n\t\t\t\toptionSelected = true;\n\t\t\t}\n\t\t} else {\n\t\t\tif (CPad::GetPad(0)->GetEnterJustDown() || CPad::GetPad(0)->GetCrossJustDown()) {\n\t\t\t\tm_bShowMouse = false;\n\t\t\t\toptionSelected = true;\n\t\t\t}\n\t\t}\n\n\t\tif (CPad::GetPad(0)->GetLeftMouseJustUp() && m_nCurrScreen != MENUPAGE_MAP) {\n\t\t\tif (m_nHoverOption == HOVEROPTION_RANDOM_ITEM)\n\t\t\t\toptionSelected = true;\n\t\t\telse if (m_nHoverOption == HOVEROPTION_NEXT_RADIO)\n\t\t\t\tChangeRadioStation(1);\n\t\t\telse if (m_nHoverOption == HOVEROPTION_PREV_RADIO)\n\t\t\t\tChangeRadioStation(-1);\n\t\t}\n\n\t\tif (CPad::GetPad(0)->GetLeftMouse()) {\n\t\t\tswitch (m_nHoverOption) {\n\t\t\tcase HOVEROPTION_INCREASE_BRIGHTNESS:\n\t\t\tcase HOVEROPTION_INCREASE_MP3BOOST:\n\t\t\tcase HOVEROPTION_INCREASE_DRAWDIST:\n\t\t\tcase HOVEROPTION_INCREASE_MUSICVOLUME:\n\t\t\tcase HOVEROPTION_INCREASE_SFXVOLUME:\n\t\t\tcase HOVEROPTION_INCREASE_MOUSESENS:\n\t\t\t\tCheckSliderMovement(1);\n\t\t\t\tbreak;\n\t\t\tcase HOVEROPTION_DECREASE_BRIGHTNESS:\n\t\t\tcase HOVEROPTION_DECREASE_MP3BOOST:\n\t\t\tcase HOVEROPTION_DECREASE_DRAWDIST:\n\t\t\tcase HOVEROPTION_DECREASE_MUSICVOLUME:\n\t\t\tcase HOVEROPTION_DECREASE_SFXVOLUME:\n\t\t\tcase HOVEROPTION_DECREASE_MOUSESENS:\n\t\t\t\tCheckSliderMovement(-1);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n#ifdef SCROLLABLE_PAGES\n\t\tif (m_nTotalListRow > MAX_VISIBLE_OPTION) {\n\t\t\tbool temp = false;\n\t\t\t\n\t\t\tm_nSelectedListRow = m_nCurrOption;\n\t\t\t\n\t\t\t// ignore detected back/select states, it's our screen's job\n\t\t\tProcessList(temp, temp);\n\t\t\t\n\t\t\t// and ignore our screen's goUp/Down, now it's ProcessList's job\n\t\t\tgoUp = false;\n\t\t\tgoDown = false;\n\t\t\tm_nCurrOption = m_nSelectedListRow;\n\t\n\t\t\tif (oldOption != m_nCurrOption)\n\t\t\t\tm_nOptionHighlightTransitionBlend = 0;\n\t\t}\n\t\t\n\t\t// Prevent sound on scroll. Mouse wheel is now belongs to us!\n\t\tif (!(m_nTotalListRow > MAX_VISIBLE_OPTION && (CPad::GetPad(0)->GetMouseWheelUpJustDown() || CPad::GetPad(0)->GetMouseWheelDownJustDown())))\n#endif\n\t\tif (CPad::GetPad(0)->GetLeftMouseJustUp() || CPad::GetPad(0)->GetLeftJustUp() || CPad::GetPad(0)->GetRightJustUp()\n\t\t\t|| CPad::GetPad(0)->GetDPadLeftJustUp() || CPad::GetPad(0)->GetDPadRightJustUp()\n\t\t\t|| CPad::GetPad(0)->GetAnaloguePadLeftJustUp() || CPad::GetPad(0)->GetAnaloguePadRightJustUp()\n\t\t\t|| CPad::GetPad(0)->GetMouseWheelUpJustDown() || CPad::GetPad(0)->GetMouseWheelDownJustDown()) {\n\t\t\tint option = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action;\n\t\t\tif (option == MENUACTION_BRIGHTNESS)\n\t\t\t\tDMAudio.PlayFrontEndSound(SOUND_FRONTEND_ENTER_OR_ADJUST, 0);\n\t\t\telse if (option == MENUACTION_SFXVOLUME)\n\t\t\t\tDMAudio.PlayFrontEndSound(SOUND_FRONTEND_AUDIO_TEST, 0);\n\t\t\telse if (option == MENUACTION_DRAWDIST || option == MENUACTION_MOUSESENS)\n\t\t\t\tDMAudio.PlayFrontEndSound(SOUND_FRONTEND_ENTER_OR_ADJUST, 0);\n\n\t\t}\n\t\tif (CPad::GetPad(0)->GetBackJustDown() || CPad::GetPad(0)->GetEscapeJustDown()) {\n\t\t\tif (m_nCurrScreen != MENUPAGE_START_MENU && m_nCurrScreen != MENUPAGE_PAUSE_MENU && m_nCurrScreen != MENUPAGE_CHOOSE_SAVE_SLOT\n\t\t\t\t&& m_nCurrScreen != MENUPAGE_SAVE_CHEAT_WARNING && m_nCurrScreen != MENUPAGE_SAVING_IN_PROGRESS\n\t\t\t\t&& m_nCurrScreen != MENUPAGE_DELETING_IN_PROGRESS && m_nCurrScreen != MENUPAGE_OUTRO)\n\t\t\t{\n\t\t\t\tm_bShowMouse = false;\n\t\t\t\tgoBack = true;\n\t\t\t}\n\t\t}\n\n\t\tif (((goDown) || (goUp)) || (optionSelected)) {\n\t\t\tgoBack = false;\n\t\t}\n\n\t}\n\n\tint curAction = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action;\n\tif (CPad::GetPad(0)->GetLeft() || CPad::GetPad(0)->GetPedWalkLeftRight() < 0 || CPad::GetPad(0)->GetDPadLeft()) {\n\t\tstatic PauseModeTime lastSliderDecrease = 0;\n\t\tif (CTimer::GetTimeInMillisecondsPauseMode() - lastSliderDecrease > 150) {\n\t\t\tif (curAction == MENUACTION_BRIGHTNESS || curAction == MENUACTION_MUSICVOLUME ||\n\t\t\t\tcurAction == MENUACTION_SFXVOLUME || curAction == MENUACTION_RADIO ||\n\t\t\t\tcurAction == MENUACTION_DRAWDIST || curAction == MENUACTION_MOUSESENS ||\n\t\t\t\tcurAction == MENUACTION_MP3VOLUMEBOOST)\n\t\t\t\tchangeValueBy = -1;\n\n\t\t\tlastSliderDecrease = CTimer::GetTimeInMillisecondsPauseMode();\n\t\t}\n\t} else if (CPad::GetPad(0)->GetRight() || CPad::GetPad(0)->GetPedWalkLeftRight() > 0 || CPad::GetPad(0)->GetDPadRight()) {\n\t\tstatic PauseModeTime lastSliderIncrease = 0;\n\t\tif (CTimer::GetTimeInMillisecondsPauseMode() - lastSliderIncrease > 150) {\n\t\t\tif (curAction == MENUACTION_BRIGHTNESS || curAction == MENUACTION_MUSICVOLUME ||\n\t\t\t\tcurAction == MENUACTION_SFXVOLUME || curAction == MENUACTION_RADIO ||\n\t\t\t\tcurAction == MENUACTION_DRAWDIST || curAction == MENUACTION_MOUSESENS ||\n\t\t\t\tcurAction == MENUACTION_MP3VOLUMEBOOST)\n\t\t\t\tchangeValueBy = 1;\n\t\t\tlastSliderIncrease = CTimer::GetTimeInMillisecondsPauseMode();\n\t\t}\n\t}\n\n#ifdef SCROLLABLE_PAGES\n\tif (!SCREEN_HAS_AUTO_SCROLLBAR)\n#endif\n\t{\n\t\tif (CPad::GetPad(0)->GetMouseWheelUpJustDown()) {\n\t\t\tchangeValueBy = 1;\n\t\t} else if (CPad::GetPad(0)->GetMouseWheelDownJustDown()) {\n\t\t\tchangeValueBy = -1;\n\t\t}\n\t}\n\t\n\tif (m_AllowNavigation) {\n\t\tif (CPad::GetPad(0)->GetRightJustDown() || CPad::GetPad(0)->GetAnaloguePadRight() || CPad::GetPad(0)->GetDPadRightJustDown()) {\n\t\t\tm_bShowMouse = false;\n\t\t\tchangeValueBy = 1;\n\t\t}\n\t}\n\n\tif (m_AllowNavigation) {\n\t\tif (CPad::GetPad(0)->GetLeftJustDown() || CPad::GetPad(0)->GetAnaloguePadLeft() || CPad::GetPad(0)->GetDPadLeftJustDown()) {\n\t\t\tm_bShowMouse = false;\n\t\t\tchangeValueBy = -1;\n\t\t}\n\t}\n\tif (changeValueBy != 0) {\n\t\tif ((m_nCurrScreen == MENUPAGE_SOUND_SETTINGS || m_nCurrScreen == MENUPAGE_DISPLAY_SETTINGS || m_nCurrScreen == MENUPAGE_CONTROLLER_PC || m_nCurrScreen == MENUPAGE_MOUSE_CONTROLS)\n\t\t\t&& aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action != MENUACTION_NOTHING\n\t\t\t&& aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action != MENUACTION_LABEL\n\t\t\t&& aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action != MENUACTION_YES\n\t\t\t&& aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action != MENUACTION_NO\n\t\t\t&& aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action != MENUACTION_CHANGEMENU\n\t\t\t&& aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action != MENUACTION_KEYBOARDCTRLS\n\t\t\t&& aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action != MENUACTION_GOBACK\n\t\t\t&& aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action != MENUACTION_RESTOREDEF\n\t\t\t&& aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action != MENUACTION_DRAWDIST\n\t\t\t&& aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action != MENUACTION_MOUSESENS\n\t\t\t&& aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action != MENUACTION_MP3VOLUMEBOOST) {\n\t\t\tDMAudio.PlayFrontEndSound(SOUND_FRONTEND_ENTER_OR_ADJUST, 0);\n\t\t}\n\t}\n\tProcessUserInput(goDown, goUp, optionSelected, goBack, changeValueBy);\n#ifdef CUSTOM_FRONTEND_OPTIONS\n\tif (aScreens[m_nCurrScreen].m_aEntries[oldOption].m_Action < MENUACTION_NOTHING) {  // CFO check\n\t\tCMenuScreenCustom::CMenuEntry &oldEntry = aScreens[m_nCurrScreen].m_aEntries[oldOption];\n\t\tif (m_nCurrOption != oldOption) {\n\t\t\tif (oldEntry.m_Action == MENUACTION_CFO_DYNAMIC)\n\t\t\t\tif(oldEntry.m_CFODynamic->buttonPressFunc)\n\t\t\t\t\toldEntry.m_CFODynamic->buttonPressFunc(FEOPTION_ACTION_FOCUSLOSS);\n\n\t\t\tif (oldEntry.m_Action == MENUACTION_CFO_SELECT && oldEntry.m_CFOSelect->onlyApplyOnEnter) {\n\t\t\t\tif (oldEntry.m_CFOSelect->displayedValue != oldEntry.m_CFOSelect->lastSavedValue)\n\t\t\t\t\tSetHelperText(3); // Restored original value\n\n\t\t\t\toldEntry.m_CFOSelect->displayedValue = oldEntry.m_CFOSelect->lastSavedValue = *oldEntry.m_CFO->value;\n\t\t\t}\n\t\t} else if (oldEntry.m_Action == MENUACTION_CFO_SELECT && oldEntry.m_CFOSelect->onlyApplyOnEnter) {\n\t\t\tif (oldEntry.m_CFOSelect->displayedValue != *oldEntry.m_CFO->value)\n\t\t\t\tSetHelperText(1); // Enter to apply\n\t\t\telse if (m_nHelperTextMsgId == 1)\n\t\t\t\tResetHelperText(); // Applied\n\t\t}\n\t}\n#endif\n}\n\nvoid\nCMenuManager::ProcessUserInput(uint8 goDown, uint8 goUp, uint8 optionSelected, uint8 goBack, int8 changeAmount)\n{\n\tif (m_nCurrScreen == MENUPAGE_OUTRO)\n\t\treturn;\n\n\tif (m_bWaitingForNewKeyBind) {\n\t\tif (m_bStartWaitingForKeyBind)\n\t\t\tm_bStartWaitingForKeyBind = false;\n\t\telse {\n\t\t\tpControlEdit = CPad::EditCodesForControls(pControlEdit, 1);\n\t\t\tJoyButtonJustClicked = false;\n\t\t\tMouseButtonJustClicked = false;\n\n\t\t\tif (CPad::GetPad(0)->GetLeftMouseJustDown())\n\t\t\t\tMouseButtonJustClicked = rsMOUSELEFTBUTTON;\n\t\t\telse if (CPad::GetPad(0)->GetRightMouseJustUp())\n\t\t\t\tMouseButtonJustClicked = rsMOUSERIGHTBUTTON;\n\t\t\telse if (CPad::GetPad(0)->GetMiddleMouseJustUp())\n\t\t\t\tMouseButtonJustClicked = rsMOUSMIDDLEBUTTON;\n\t\t\telse if (CPad::GetPad(0)->GetMouseWheelUpJustUp())\n\t\t\t\tMouseButtonJustClicked = rsMOUSEWHEELUPBUTTON;\n\t\t\telse if (CPad::GetPad(0)->GetMouseWheelDownJustUp())\n\t\t\t\tMouseButtonJustClicked = rsMOUSEWHEELDOWNBUTTON;\n\t\t\telse if (CPad::GetPad(0)->GetMouseX1JustUp())\n\t\t\t\tMouseButtonJustClicked = rsMOUSEX1BUTTON;\n\t\t\telse if (CPad::GetPad(0)->GetMouseX2JustUp())\n\t\t\t\tMouseButtonJustClicked = rsMOUSEX2BUTTON;\n\n\t\t\tJoyButtonJustClicked = ControlsManager.GetJoyButtonJustDown();\n\n\t\t\tint32 TypeOfControl = KEYBOARD;\n\t\t\tif (JoyButtonJustClicked)\n\t\t\t\tTypeOfControl = JOYSTICK;\n\t\t\tif (MouseButtonJustClicked)\n\t\t\t\tTypeOfControl = MOUSE;\n\t\t\tif (*pControlEdit != rsNULL)\n\t\t\t\tTypeOfControl = KEYBOARD;\n\n\t\t\tif (!m_bKeyIsOK) {\n\t\t\t\tpControlEdit = nil;\n\t\t\t\tm_bWaitingForNewKeyBind = false;\n\t\t\t\tm_KeyPressedCode = -1;\n\t\t\t\tm_bStartWaitingForKeyBind = false;\n\t\t\t} else if (!m_bKeyChangeNotProcessed) {\n\t\t\t\tif (*pControlEdit != rsNULL || MouseButtonJustClicked || JoyButtonJustClicked)\n\t\t\t\t\tCheckCodesForControls(TypeOfControl);\n\n\t\t\t\tfield_159 = true;\n\t\t\t} else {\n\t\t\t\tfor (int i = 0; i < 4; i++)\n\t\t\t\t\tControlsManager.ClearSettingsAssociatedWithAction((e_ControllerAction)m_CurrCntrlAction, (eControllerType)i);\n\t\t\t\tm_bKeyIsOK = false;\n\t\t\t\tm_bKeyChangeNotProcessed = false;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (pEditString || pControlEdit)\n\t\treturn;\n\n#ifdef USE_DEBUG_SCRIPT_LOADER\n\tif (m_nCurrScreen == MENUPAGE_START_MENU || m_nCurrScreen == MENUPAGE_NEW_GAME || m_nCurrScreen == MENUPAGE_NEW_GAME_RELOAD) {\n#ifdef RW_GL3\n\t\tif (glfwGetKey(PSGLOBAL(window), GLFW_KEY_R) == GLFW_PRESS) {\n\t\t\tscriptToLoad = 1;\n\t\t\tDoSettingsBeforeStartingAGame();\n\t\t\treturn;\n\t\t}\n#elif defined _WIN32\n\t\tif (GetAsyncKeyState('R') & 0x8000) {\n\t\t\tscriptToLoad = 1;\n\t\t\tDoSettingsBeforeStartingAGame();\n\t\t\treturn;\n\t\t}\n#endif\n\t}\n#endif\n\n\tint oldOption = m_nCurrOption;\n\tif (goDown) {\n\t\tif (m_nCurrScreen != MENUPAGE_MAP)\n\t\t\tDMAudio.PlayFrontEndSound(SOUND_FRONTEND_HIGHLIGHT_OPTION, 0);\n\n\t\tm_nCurrOption++;\n\t\tif (m_nCurrOption == NUM_MENUROWS || (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action == MENUACTION_NOTHING)) {\n\t\t\tm_nCurrOption = 0;\n\t\t}\n\t\tif (oldOption != m_nCurrOption)\n\t\t\tm_nOptionHighlightTransitionBlend = 0;\n\t}\n\tif (goUp) {\n\t\tif (m_nCurrScreen != MENUPAGE_MAP)\n\t\t\tDMAudio.PlayFrontEndSound(SOUND_FRONTEND_HIGHLIGHT_OPTION, 0);\n\n\t\tif (m_nCurrOption == (aScreens[m_nCurrScreen].m_aEntries[0].m_Action == MENUACTION_LABEL)) {\n\t\t\twhile (m_nCurrOption != NUM_MENUROWS - 1\n\t\t\t\t&& aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption + 1].m_Action != MENUACTION_NOTHING) {\n\t\t\t\tm_nCurrOption++;\n\t\t\t}\n\t\t} else {\n\t\t\tm_nCurrOption--;\n\t\t}\n\t\tif (oldOption != m_nCurrOption)\n\t\t\tm_nOptionHighlightTransitionBlend = 0;\n\t}\n\n\tif (optionSelected && m_nMenuFadeAlpha == 255) {\n\t\tif (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu == MENUPAGE_NEW_GAME_RELOAD && m_bGameNotLoaded) {\n\t\t\tDoSettingsBeforeStartingAGame();\n\t\t} else if (hasNativeList(m_nCurrScreen)) {\n\t\t\tswitch (m_nCurrExLayer) {\n\t\t\tcase HOVEROPTION_LIST:\n\t\t\t\tif (m_nCurrScreen == MENUPAGE_KEYBOARD_CONTROLS) {\n\t\t\t\t\tm_bWaitingForNewKeyBind = true;\n\t\t\t\t\tm_bStartWaitingForKeyBind = true;\n\t\t\t\t\tpControlEdit = &m_KeyPressedCode;\n\t\t\t\t}\n\t\t\t\tif (m_nCurrScreen == MENUPAGE_SKIN_SELECT) {\n\t\t\t\t\tstrcpy(m_PrefsSkinFile, m_aSkinName);\n\t\t\t\t\tCWorld::Players[0].SetPlayerSkin(m_PrefsSkinFile);\n\t\t\t\t\tm_nCurrExLayer = HOVEROPTION_BACK;\n\t\t\t\t\tSaveSettings();\n\t\t\t\t}\n\t\t\t\tm_nHoverOption = HOVEROPTION_NOT_HOVERING;\n\t\t\t\tbreak;\n\t\t\tcase HOVEROPTION_USESKIN:\n\t\t\t\tm_nHoverOption = HOVEROPTION_NOT_HOVERING;\n\t\t\t\tstrcpy(m_PrefsSkinFile, m_aSkinName);\n\t\t\t\tCWorld::Players[0].SetPlayerSkin(m_PrefsSkinFile);\n\t\t\t\tm_nCurrExLayer = HOVEROPTION_BACK;\n\t\t\t\tSaveSettings();\n\t\t\t\tbreak;\n\t\t\tcase HOVEROPTION_BACK:\n\t\t\tdefault:\n\t\t\t\tgoBack = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (m_nSkinsTotal > 0) {\n\t\t\t\tm_pSelectedSkin = m_pSkinListHead.nextSkin;\n\t\t\t\tstrcpy(m_PrefsSkinFile, m_aSkinName);\n\t\t\t\tCWorld::Players[0].SetPlayerSkin(m_PrefsSkinFile);\n\t\t\t\tSaveSettings();\n\t\t\t}\n\t\t}\n\n\t\tint option = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action;\n#ifdef FIX_BUGS\n\t\tint currScreen = m_nCurrScreen;\n\t\tint currOption = m_nCurrOption;\n#endif\n\t\tswitch (option) {\n\t\t\tcase MENUACTION_CHANGEMENU:\n\t\t\tcase MENUACTION_YES:\n\t\t\tcase MENUACTION_NO:\n\t\t\t\tSwitchToNewScreen(aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu);\n\t\t\t\tbreak;\n\t\t\tcase MENUACTION_RADIO:\n\t\t\t\tChangeRadioStation(1);\n\t\t\t\tbreak;\n\t\t\tcase MENUACTION_LANG_ENG:\n\t\t\t\tm_PrefsLanguage = LANGUAGE_AMERICAN;\n\t\t\t\tm_bFrontEnd_ReloadObrTxtGxt = true;\n\t\t\t\tInitialiseChangedLanguageSettings();\n\t\t\t\tSaveSettings();\n\t\t\t\tbreak;\n\t\t\tcase MENUACTION_LANG_FRE:\n\t\t\t\tm_PrefsLanguage = LANGUAGE_FRENCH;\n\t\t\t\tm_bFrontEnd_ReloadObrTxtGxt = true;\n\t\t\t\tInitialiseChangedLanguageSettings();\n\t\t\t\tSaveSettings();\n\t\t\t\tbreak;\n\t\t\tcase MENUACTION_LANG_GER:\n\t\t\t\tm_PrefsLanguage = LANGUAGE_GERMAN;\n\t\t\t\tm_bFrontEnd_ReloadObrTxtGxt = true;\n\t\t\t\tInitialiseChangedLanguageSettings();\n\t\t\t\tSaveSettings();\n\t\t\t\tbreak;\n\t\t\tcase MENUACTION_LANG_ITA:\n\t\t\t\tm_PrefsLanguage = LANGUAGE_ITALIAN;\n\t\t\t\tm_bFrontEnd_ReloadObrTxtGxt = true;\n\t\t\t\tInitialiseChangedLanguageSettings();\n\t\t\t\tSaveSettings();\n\t\t\t\tbreak;\n\t\t\tcase MENUACTION_LANG_SPA:\n\t\t\t\tm_PrefsLanguage = LANGUAGE_SPANISH;\n\t\t\t\tm_bFrontEnd_ReloadObrTxtGxt = true;\n\t\t\t\tInitialiseChangedLanguageSettings();\n\t\t\t\tSaveSettings();\n\t\t\t\tbreak;\n\t\t\tcase MENUACTION_CHECKSAVE:\n\t\t\t{\n\t\t\t\tint saveSlot = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_SaveSlot;\n\n\t\t\t\tif (saveSlot >= SAVESLOT_1 && saveSlot <= SAVESLOT_8) {\n\t\t\t\t\tm_nCurrSaveSlot = saveSlot - SAVESLOT_1;\n\t\t\t\t\tif (Slots[m_nCurrSaveSlot] != SLOT_EMPTY && Slots[m_nCurrSaveSlot] != SLOT_CORRUPTED) {\n\t\t\t\t\t\tif (m_nCurrScreen == MENUPAGE_CHOOSE_LOAD_SLOT) {\n\t\t\t\t\t\t\tSwitchToNewScreen(MENUPAGE_LOAD_SLOT_CONFIRM);\n\t\t\t\t\t\t} else if (m_nCurrScreen == MENUPAGE_CHOOSE_DELETE_SLOT) {\n\t\t\t\t\t\t\tSwitchToNewScreen(MENUPAGE_DELETE_SLOT_CONFIRM);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase MENUACTION_NEWGAME:\n\t\t\t\tDoSettingsBeforeStartingAGame();\n\t\t\t\tbreak;\n#ifdef LEGACY_MENU_OPTIONS\n\t\t\tcase MENUACTION_RELOADIDE:\n\t\t\t\tCFileLoader::ReloadObjectTypes(\"GTA3.IDE\");\n\t\t\t\tbreak;\n#endif\n\t\t\tcase MENUACTION_RESUME_FROM_SAVEZONE:\n\t\t\t\tRequestFrontEndShutDown();\n\t\t\t\tbreak;\n\t\t\tcase MENUACTION_LOADRADIO:\n\t\t\t\tif (m_nPrefsAudio3DProviderIndex != NO_AUDIO_PROVIDER) {\n\t\t\t\t\tSwitchToNewScreen(MENUPAGE_SOUND_SETTINGS);\n\t\t\t\t\tDMAudio.PlayFrontEndTrack(m_PrefsRadioStation, 1);\n\t\t\t\t\tOutputDebugString(\"STARTED PLAYING FRONTEND AUDIO TRACK\");\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase MENUACTION_SAVEGAME:\n\t\t\t{\n\t\t\t\tint saveSlot = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_SaveSlot;\n\n\t\t\t\tif (saveSlot >= 2 && saveSlot <= 9) {\n\t\t\t\t\tm_nCurrSaveSlot = m_nCurrOption;\n\t\t\t\t\tSwitchToNewScreen(MENUPAGE_SAVE_OVERWRITE_CONFIRM);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase MENUACTION_RADARMODE:\n\t\t\t\tif (++m_PrefsRadarMode > 2)\n\t\t\t\t\tm_PrefsRadarMode = 0;\n\t\t\t\tSaveSettings();\n\t\t\t\tbreak;\n\t\t\tcase MENUACTION_GOBACK:\n\t\t\t\tgoBack = true;\n\t\t\t\tbreak;\n\t\t\tcase MENUACTION_KEYBOARDCTRLS:\n\t\t\t\tSwitchToNewScreen(MENUPAGE_KEYBOARD_CONTROLS);\n\t\t\t\tm_nSelectedListRow = 0;\n\t\t\t\tm_nCurrExLayer = HOVEROPTION_LIST;\n\t\t\t\tbreak;\n\t\t\tcase MENUACTION_GETKEY:\n\t\t\t\tm_CurrCntrlAction = GetStartOptionsCntrlConfigScreens() + m_nCurrOption;\n\t\t\t\tm_bKeyIsOK = true;\n\t\t\t\tm_bWaitingForNewKeyBind = true;\n\t\t\t\tm_bStartWaitingForKeyBind = true;\n\t\t\t\tpControlEdit = &m_KeyPressedCode;\n\t\t\t\tbreak;\n\t\t\tcase MENUACTION_CANCELGAME:\n\t\t\t\tDMAudio.Service();\n\t\t\t\tSwitchToNewScreen(MENUPAGE_OUTRO);\n\t\t\t\tbreak;\n\t\t\tcase MENUACTION_RESUME:\n#ifdef LEGACY_MENU_OPTIONS\n\t\t\t\tif (m_PrefsVsyncDisp != m_PrefsVsync) {\n\t\t\t\t\tm_PrefsVsync = m_PrefsVsyncDisp;\n\t\t\t\t}\n#endif\n\t\t\t\tRequestFrontEndShutDown();\n\t\t\t\tbreak;\n\t\t\tcase MENUACTION_DONTCANCEL:\n\t\t\t\tSwitchToNewScreen(-2);\n\t\t\t\tbreak;\n\t\t\tcase MENUACTION_SCREENRES:\n\t\t\t\tif (m_nDisplayVideoMode != m_nPrefsVideoMode) {\n\t\t\t\t\tm_nPrefsVideoMode = m_nDisplayVideoMode;\n\t\t\t\t\t_psSelectScreenVM(m_nPrefsVideoMode);\n\t\t\t\t\tDMAudio.ChangeMusicMode(MUSICMODE_FRONTEND);\n\t\t\t\t\tDMAudio.Service();\n\t\t\t\t\tCentreMousePointer();\n\t\t\t\t\tm_bShowMouse = true;\n\t\t\t\t\tm_nCurrOption = 5; // TODO(Miami): Because selected option is resetted after res. change. We'll need to revisit that.\n\t\t\t\t\tm_nOptionHighlightTransitionBlend = 0;\n\t\t\t\t\tSaveSettings();\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase MENUACTION_AUDIOHW:\n\t\t\t{\n\t\t\t\tint selectedProvider = m_nPrefsAudio3DProviderIndex;\n\t\t\t\tif (selectedProvider != NO_AUDIO_PROVIDER) {\n\t\t\t\t\tif (selectedProvider == -1)\n\t\t\t\t\t\tselectedProvider = m_nPrefsAudio3DProviderIndex = DMAudio.AutoDetect3DProviders();\n\n\t\t\t\t\tm_nPrefsAudio3DProviderIndex = DMAudio.SetCurrent3DProvider(m_nPrefsAudio3DProviderIndex);\n\t\t\t\t\tif (selectedProvider != m_nPrefsAudio3DProviderIndex) {\n\t\t\t\t\t\tSetHelperText(5);\n\t\t\t\t\t}\n\t\t\t\t\tSaveSettings();\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase MENUACTION_SPEAKERCONF:\n\t\t\t\tif (m_nPrefsAudio3DProviderIndex != NO_AUDIO_PROVIDER) {\n\t\t\t\t\tif (--m_PrefsSpeakers < 0)\n\t\t\t\t\t\tm_PrefsSpeakers = 2;\n\t\t\t\t\tDMAudio.SetSpeakerConfig(m_PrefsSpeakers);\n\t\t\t\t\tSaveSettings();\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase MENUACTION_PLAYERSETUP:\n\t\t\t\tCPlayerSkin::BeginFrontendSkinEdit();\n\t\t\t\tSwitchToNewScreen(MENUPAGE_SKIN_SELECT);\n\t\t\t\tm_bSkinsEnumerated = false;\n\t\t\t\tm_nCurrExLayer = HOVEROPTION_LIST;\n\t\t\t\tbreak;\n\t\t\tcase MENUACTION_RESTOREDEF:\n\t\t\t\tif (m_nCurrScreen == MENUPAGE_SOUND_SETTINGS) {\n\t\t\t\t\tm_nPrefsAudio3DProviderIndex = DMAudio.AutoDetect3DProviders();\n\t\t\t\t\tDMAudio.SetCurrent3DProvider(m_nPrefsAudio3DProviderIndex);\n\t\t\t\t\tm_PrefsSfxVolume = 49;\n\t\t\t\t\tm_PrefsMusicVolume = 49;\n\t\t\t\t\tm_PrefsRadioStation = EMOTION;\n\t\t\t\t\tm_PrefsMP3BoostVolume = 0;\n\t\t\t\t\tm_PrefsStereoMono = 1;\n\t\t\t\t\tm_PrefsSpeakers = 0;\n\t\t\t\t\tDMAudio.SetMP3BoostVolume(m_PrefsMP3BoostVolume);\n\t\t\t\t\tDMAudio.SetMusicMasterVolume(m_PrefsMusicVolume);\n\t\t\t\t\tDMAudio.SetEffectsMasterVolume(m_PrefsSfxVolume);\n\t\t\t\t\tDMAudio.SetRadioInCar(m_PrefsRadioStation);\n\t\t\t\t\tDMAudio.PlayFrontEndTrack(m_PrefsRadioStation, 1);\n\t\t\t\t\tSaveSettings();\n\t\t\t\t} else if (m_nCurrScreen == MENUPAGE_DISPLAY_SETTINGS) {\n\t\t\t\t\tm_PrefsBrightness = 256;\n\t\t\t\t\tm_PrefsLOD = 1.2f;\n#ifdef LEGACY_MENU_OPTIONS\n\t\t\t\t\tm_PrefsVsync = true;\n#endif\n\t\t\t\t\tCRenderer::ms_lodDistScale = m_PrefsLOD;\n\t\t\t\t\tm_PrefsShowSubtitles = false;\n#ifdef ASPECT_RATIO_SCALE\n\t\t\t\t\tm_PrefsUseWideScreen = AR_AUTO;\n#else\n\t\t\t\t\tm_PrefsUseWideScreen = false;\n#endif\n\t\t\t\t\tm_PrefsShowLegends = true;\n\t\t\t\t\tm_PrefsVsyncDisp = true;\n\t\t\t\t\tm_PrefsFrameLimiter = true;\n\t\t\t\t\tm_PrefsRadarMode = 0;\n\t\t\t\t\tm_PrefsShowHud = true;\n\t\t\t\t\tm_nDisplayVideoMode = m_nPrefsVideoMode;\n\t\t\t\t\tCMBlur::BlurOn = false;\n#ifdef CUSTOM_FRONTEND_OPTIONS\n\t\t\t\t\textern void RestoreDefGraphics(int8);\n\t\t\t\t\textern void RestoreDefDisplay(int8);\n\n\t\t\t\t\tRestoreDefGraphics(FEOPTION_ACTION_SELECT);\n\t\t\t\t\tRestoreDefDisplay(FEOPTION_ACTION_SELECT);\n#endif\n\t\t\t\t\tSaveSettings();\n\t\t\t\t} else if (m_nCurrScreen == MENUPAGE_CONTROLLER_PC) {\n\t\t\t\t\tControlsManager.MakeControllerActionsBlank();\n\t\t\t\t\tControlsManager.InitDefaultControlConfiguration();\n\t\t\t\t\tControlsManager.InitDefaultControlConfigMouse(MousePointerStateHelper.GetMouseSetUp());\n#if !defined RW_GL3\n\t\t\t\t\tif (AllValidWinJoys.m_aJoys[JOYSTICK1].m_bInitialised) {\n\t\t\t\t\t\tDIDEVCAPS devCaps;\n\t\t\t\t\t\tdevCaps.dwSize = sizeof(DIDEVCAPS);\n\t\t\t\t\t\tPSGLOBAL(joy1)->GetCapabilities(&devCaps);\n\t\t\t\t\t\tControlsManager.InitDefaultControlConfigJoyPad(devCaps.dwButtons);\n\t\t\t\t\t}\n#else\n\t\t\t\t\tif (PSGLOBAL(joy1id) != -1 && glfwJoystickPresent(PSGLOBAL(joy1id))) {\n\t\t\t\t\t\tint count;\n\t\t\t\t\t\tglfwGetJoystickButtons(PSGLOBAL(joy1id), &count);\n\t\t\t\t\t\tControlsManager.InitDefaultControlConfigJoyPad(count);\n\t\t\t\t\t}\n#endif\n\t\t\t\t\tMousePointerStateHelper.bInvertVertically = true;\n\t\t\t\t\tTheCamera.m_bHeadBob = false;\n#ifdef FIX_BUGS\n\t\t\t\t\tTheCamera.m_fMouseAccelVertical = 0.003f;\n#endif\n\t\t\t\t\tTheCamera.m_fMouseAccelHorzntl = 0.0025f;\n\t\t\t\t\tCVehicle::m_bDisableMouseSteering = true;\n\t\t\t\t\tm_ControlMethod = CONTROL_STANDARD;\n#ifdef PC_PLAYER_CONTROLS\n\t\t\t\t\tTheCamera.m_bUseMouse3rdPerson = true;\n#else\n\t\t\t\t\tTheCamera.m_bUseMouse3rdPerson = false;\n#endif\n\t\t\t\t\tSaveSettings();\n#ifdef LOAD_INI_SETTINGS\n\t\t\t\t\tSaveINIControllerSettings();\n#endif\n\t\t\t\t}\n\t\t\t\tSetHelperText(2);\n\t\t\t\tbreak;\n\t\t\tcase MENUACTION_CTRLMETHOD:\n\t\t\t\tif (m_ControlMethod == CONTROL_CLASSIC) {\n\t\t\t\t\tCCamera::m_bUseMouse3rdPerson = true;\n\t\t\t\t\tm_ControlMethod = CONTROL_STANDARD;\n\t\t\t\t} else {\n\t\t\t\t\tCCamera::m_bUseMouse3rdPerson = false;\n\t\t\t\t\tm_ControlMethod = CONTROL_CLASSIC;\n\t\t\t\t}\n\t\t\t\tSaveSettings();\n\t\t\t\tbreak;\n#ifdef CUSTOM_FRONTEND_OPTIONS\n\t\t\tcase MENUACTION_CFO_SELECT:\n\t\t\tcase MENUACTION_CFO_DYNAMIC:\n\t\t\t\tCMenuScreenCustom::CMenuEntry &option = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption];\n\t\t\t\tif (option.m_Action == MENUACTION_CFO_SELECT) {\n\t\t\t\t\tif (option.m_CFOSelect->disableIfGameLoaded && !m_bGameNotLoaded)\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tif (!option.m_CFOSelect->onlyApplyOnEnter) {\n\t\t\t\t\t\toption.m_CFOSelect->displayedValue++;\n\t\t\t\t\t\tif (option.m_CFOSelect->displayedValue >= option.m_CFOSelect->numRightTexts || option.m_CFOSelect->displayedValue < 0)\n\t\t\t\t\t\t\toption.m_CFOSelect->displayedValue = 0;\n\t\t\t\t\t}\n\t\t\t\t\tint8 oldValue = *option.m_CFO->value;\n\n\t\t\t\t\t*option.m_CFO->value = option.m_CFOSelect->lastSavedValue = option.m_CFOSelect->displayedValue;\n\n\t\t\t\t\t// Now everything is saved in .ini, and LOAD_INI_SETTINGS is fundamental for CFO\n\t\t\t\t\t// if (option.m_CFOSelect->save)\n\t\t\t\t\t\tSaveSettings();\n\n\t\t\t\t\tif (option.m_CFOSelect->displayedValue != oldValue && option.m_CFOSelect->changeFunc)\n\t\t\t\t\t\toption.m_CFOSelect->changeFunc(oldValue, option.m_CFOSelect->displayedValue);\n\n\t\t\t\t} else if (option.m_Action == MENUACTION_CFO_DYNAMIC) {\n\t\t\t\t\tif (option.m_CFODynamic->buttonPressFunc)\n\t\t\t\t\t\toption.m_CFODynamic->buttonPressFunc(FEOPTION_ACTION_SELECT);\n\t\t\t\t}\n\n\t\t\t\tbreak;\n#endif\n\t\t}\n\t\tProcessOnOffMenuOptions();\n\t\tif (!goBack) {\n#ifdef FIX_BUGS\n\t\t\tint saveSlot = aScreens[currScreen].m_aEntries[currOption].m_SaveSlot;\n\t\t\tif (saveSlot >= SAVESLOT_1 && saveSlot <= SAVESLOT_8 && Slots[currOption] != SLOT_OK)\n#else\n\t\t\tint saveSlot = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_SaveSlot;\n\t\t\tif (saveSlot >= SAVESLOT_1 && saveSlot <= SAVESLOT_8 && Slots[m_nCurrOption] != SLOT_OK)\n#endif\n\t\t\t\tDMAudio.PlayFrontEndSound(SOUND_FRONTEND_FAIL, 0);\n\t\t\telse\n\t\t\t\tDMAudio.PlayFrontEndSound(SOUND_FRONTEND_ENTER_OR_ADJUST, 0);\n\t\t}\n\t}\n\n\tif (goBack) {\n\t\tif (m_NoEmptyBinding) {\n\t\t\tDMAudio.PlayFrontEndSound(SOUND_FRONTEND_BACK, 0);\n\t\t\tSwitchToNewScreen(-2);\n\t\t\tif (hasNativeList(m_nCurrScreen)) {\n\t\t\t\tm_nTotalListRow = 0;\n\t\t\t}\n\t\t} else {\n\t\t\tDMAudio.PlayFrontEndSound(SOUND_FRONTEND_FAIL, 0);\n\t\t\tm_ShowEmptyBindingError = true;\n\t\t}\n\t}\n\n\tif (changeAmount != 0) {\n\t\tswitch (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action) {\n#ifdef GAMEPAD_MENU\n\t\t\tcase MENUACTION_CTRLCONFIG:\n\t\t\t\tCPad::GetPad(0)->Mode += changeAmount;\n\t\t\t\tif (CPad::GetPad(0)->Mode > 3)\n\t\t\t\t\tCPad::GetPad(0)->Mode = 0;\n\t\t\t\telse if (CPad::GetPad(0)->Mode < 0)\n\t\t\t\t\tCPad::GetPad(0)->Mode = 3;\n\t\t\t\tSaveSettings();\n\t\t\t\tbreak;\n#endif\n\t\t\tcase MENUACTION_RADIO:\n\t\t\t\tChangeRadioStation(changeAmount);\n\t\t\t\tbreak;\n\t\t\tcase MENUACTION_RADARMODE:\n\t\t\t\tm_PrefsRadarMode += changeAmount;\n\t\t\t\tif (m_PrefsRadarMode < 0)\n\t\t\t\t\tm_PrefsRadarMode = 2;\n\t\t\t\tif (m_PrefsRadarMode > 2)\n\t\t\t\t\tm_PrefsRadarMode = 0;\n\t\t\t\tbreak;\n#ifdef ASPECT_RATIO_SCALE\n\t\t\tcase MENUACTION_WIDESCREEN:\n\t\t\t\tif (changeAmount > 0) {\n\t\t\t\t\tm_PrefsUseWideScreen++;\n\t\t\t\t\tif (m_PrefsUseWideScreen > AR_MAX - 1)\n\t\t\t\t\t\tm_PrefsUseWideScreen = 0;\n\t\t\t\t} else {\n\t\t\t\t\tm_PrefsUseWideScreen--;\n\t\t\t\t\tif (m_PrefsUseWideScreen < 0)\n\t\t\t\t\t\tm_PrefsUseWideScreen = AR_MAX - 1;\n\t\t\t\t}\n\t\t\t\tSaveSettings();\n\t\t\t\tbreak;\n#endif\n\t\t\tcase MENUACTION_SCREENRES:\n\t\t\t\tif (m_bGameNotLoaded) {\n\t\t\t\t\tRwChar** videoMods = _psGetVideoModeList();\n\t\t\t\t\tif (changeAmount > 0) {\n\t\t\t\t\t\tdo {\n\t\t\t\t\t\t\t++m_nDisplayVideoMode;\n\n\t\t\t\t\t\t\tif (m_nDisplayVideoMode >= _psGetNumVideModes())\n\t\t\t\t\t\t\t\tm_nDisplayVideoMode = 0;\n\t\t\t\t\t\t} while (!videoMods[m_nDisplayVideoMode]);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tdo {\n\t\t\t\t\t\t\t--m_nDisplayVideoMode;\n\n\t\t\t\t\t\t\tif (m_nDisplayVideoMode < 0)\n\t\t\t\t\t\t\t\tm_nDisplayVideoMode = _psGetNumVideModes() - 1;\n\t\t\t\t\t\t} while (!videoMods[m_nDisplayVideoMode]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase MENUACTION_AUDIOHW:\n\t\t\t\tif (m_nPrefsAudio3DProviderIndex != NO_AUDIO_PROVIDER) {\n\t\t\t\t\tm_nPrefsAudio3DProviderIndex += changeAmount;\n\n\t\t\t\t\tbool checkIfForbidden = true;\n\t\t\t\t\twhile (checkIfForbidden) {\n\t\t\t\t\t\tcheckIfForbidden = false;\n\n\t\t\t\t\t\tif (m_nPrefsAudio3DProviderIndex < -1)\n\t\t\t\t\t\t\tm_nPrefsAudio3DProviderIndex = DMAudio.GetNum3DProvidersAvailable() - 1;\n\t\t\t\t\t\telse if (m_nPrefsAudio3DProviderIndex > DMAudio.GetNum3DProvidersAvailable() - 1)\n\t\t\t\t\t\t\tm_nPrefsAudio3DProviderIndex = -1;\n\n\t\t\t\t\t\t// what a retarded move...\n\t\t\t\t\t\tif (m_nPrefsAudio3DProviderIndex != -1) {\n\t\t\t\t\t\t\tchar* provider = DMAudio.Get3DProviderName(m_nPrefsAudio3DProviderIndex);\n\t\t\t\t\t\t\tstrupr(provider);\n\t\t\t\t\t\t\tif (!strcmp(provider, \"MILES FAST 2D POSITIONAL AUDIO\")) {\n\t\t\t\t\t\t\t\tm_nPrefsAudio3DProviderIndex += changeAmount;\n\t\t\t\t\t\t\t\tcheckIfForbidden = true;\n\n\t\t\t\t\t\t\t} else if (!strcmp(provider, \"AUREAL A3D 2.0 (TM)\")) {\n\t\t\t\t\t\t\t\tm_nPrefsAudio3DProviderIndex += changeAmount;\n\t\t\t\t\t\t\t\tcheckIfForbidden = true;\n\n\t\t\t\t\t\t\t} else if (!strcmp(provider, \"AUREAL A3D INTERACTIVE (TM)\")) {\n\t\t\t\t\t\t\t\tm_nPrefsAudio3DProviderIndex += changeAmount;\n\t\t\t\t\t\t\t\tcheckIfForbidden = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase MENUACTION_SPEAKERCONF:\n\t\t\t\tif (m_nPrefsAudio3DProviderIndex != NO_AUDIO_PROVIDER) {\n\t\t\t\t\tm_PrefsSpeakers -= changeAmount;\n\t\t\t\t\tm_PrefsSpeakers = clamp(m_PrefsSpeakers, 0, 2);\n\t\t\t\t\tDMAudio.SetSpeakerConfig(m_PrefsSpeakers);\n\t\t\t\t\tSaveSettings();\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase MENUACTION_CTRLMETHOD:\n\t\t\t\tm_ControlMethod = !m_ControlMethod;\n\t\t\t\tCCamera::m_bUseMouse3rdPerson = !m_ControlMethod;\n\t\t\t\tSaveSettings();\n\t\t\t\tbreak;\n#ifdef CUSTOM_FRONTEND_OPTIONS\n\t\t\tcase MENUACTION_CFO_SELECT:\n\t\t\tcase MENUACTION_CFO_DYNAMIC:\n\t\t\t\tCMenuScreenCustom::CMenuEntry &option = aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption];\n\t\t\t\tif (option.m_Action == MENUACTION_CFO_SELECT) {\n\t\t\t\t\tif (option.m_CFOSelect->disableIfGameLoaded && !m_bGameNotLoaded)\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t\n\t\t\t\t\tif (changeAmount > 0) {\n\t\t\t\t\t\toption.m_CFOSelect->displayedValue++;\n\t\t\t\t\t\tif (option.m_CFOSelect->displayedValue >= option.m_CFOSelect->numRightTexts)\n\t\t\t\t\t\t\toption.m_CFOSelect->displayedValue = 0;\n\t\t\t\t\t} else {\n\t\t\t\t\t\toption.m_CFOSelect->displayedValue--;\n\t\t\t\t\t\tif (option.m_CFOSelect->displayedValue < 0)\n\t\t\t\t\t\t\toption.m_CFOSelect->displayedValue = option.m_CFOSelect->numRightTexts - 1;\n\t\t\t\t\t}\n\t\t\t\t\tif (!option.m_CFOSelect->onlyApplyOnEnter) {\n\t\t\t\t\t\tint8 oldValue = *option.m_CFO->value;\n\n\t\t\t\t\t\t*option.m_CFO->value = option.m_CFOSelect->lastSavedValue = option.m_CFOSelect->displayedValue;\n\n\t\t\t\t\t\t// Now everything is saved in .ini, and LOAD_INI_SETTINGS is fundamental for CFO\n\t\t\t\t\t\t// if (option.m_CFOSelect->save)\n\t\t\t\t\t\t\tSaveSettings();\n\n\t\t\t\t\t\tif (option.m_CFOSelect->displayedValue != oldValue && option.m_CFOSelect->changeFunc)\n\t\t\t\t\t\t\toption.m_CFOSelect->changeFunc(oldValue, option.m_CFOSelect->displayedValue);\n\t\t\t\t\t}\n\t\t\t\t} else if (option.m_Action == MENUACTION_CFO_DYNAMIC && option.m_CFODynamic->buttonPressFunc) {\n\t\t\t\t\toption.m_CFODynamic->buttonPressFunc(changeAmount > 0 ? FEOPTION_ACTION_RIGHT : FEOPTION_ACTION_LEFT);\n\t\t\t\t}\n\t\t\t\tbreak;\n#endif\n\t\t}\n\t\tCheckSliderMovement(changeAmount);\n\t\tProcessOnOffMenuOptions();\n\t\tif (m_nCurrScreen == MENUPAGE_KEYBOARD_CONTROLS) {\n\t\t\tif (changeAmount < 1) {\n\t\t\t\tm_nSelectedContSetupColumn = CONTSETUP_PED_COLUMN;\n\t\t\t} else {\n\t\t\t\tm_nSelectedContSetupColumn = CONTSETUP_VEHICLE_COLUMN;\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nCMenuManager::ProcessOnOffMenuOptions()\n{\n\tswitch (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_Action) {\n#ifdef GAMEPAD_MENU\n\tcase MENUACTION_CTRLVIBRATION:\n\t\tm_PrefsUseVibration = !m_PrefsUseVibration;\n\t\tif (m_PrefsUseVibration) {\n\t\t\tCPad::GetPad(0)->StartShake(350, 150);\n\t\t\tTimeToStopPadShaking = CTimer::GetTimeInMillisecondsPauseMode() + 500;\n\t\t}\n\t\tSaveSettings();\n\t\tbreak;\n#endif\n\tcase MENUACTION_INVERTPADY:\n\t\tCPad::bInvertLook4Pad = !CPad::bInvertLook4Pad;\n\t\tSaveSettings(); // FIX: Why don't SaveSettings? Because of it's an hidden option? :(\n\t\tbreak;\n\tcase MENUACTION_CTRLDISPLAY:\n\t\tm_DisplayControllerOnFoot = !m_DisplayControllerOnFoot;\n\t\tbreak;\n\tcase MENUACTION_FRAMESYNC:\n\t\tm_PrefsVsyncDisp = !m_PrefsVsyncDisp;\n\t\tSaveSettings(); // FIX: Again... This makes me very unhappy\n\t\tbreak;\n\tcase MENUACTION_FRAMELIMIT:\n\t\tm_PrefsFrameLimiter = !m_PrefsFrameLimiter;\n\t\tSaveSettings();\n\t\tbreak;\n\tcase MENUACTION_TRAILS:\n\t\tCMBlur::BlurOn = !CMBlur::BlurOn;\n\t\tSaveSettings();\n\t\tbreak;\n\tcase MENUACTION_SUBTITLES:\n\t\tm_PrefsShowSubtitles = !m_PrefsShowSubtitles;\n\t\tSaveSettings();\n\t\tbreak;\n#ifndef ASPECT_RATIO_SCALE\n\tcase MENUACTION_WIDESCREEN:\n\t\tm_PrefsUseWideScreen = !m_PrefsUseWideScreen;\n\t\tSaveSettings();\n\t\tbreak;\n#endif\n\tcase MENUACTION_LEGENDS:\n\t\tm_PrefsShowLegends = !m_PrefsShowLegends;\n\t\tbreak;\n\tcase MENUACTION_HUD:\n\t\tm_PrefsShowHud = !m_PrefsShowHud;\n\t\tSaveSettings();\n\t\tbreak;\n#ifdef LEGACY_MENU_OPTIONS\n\tcase MENUACTION_SETDBGFLAG:\n\t\tCTheScripts::InvertDebugFlag();\n\t\tbreak;\n\tcase MENUACTION_SWITCHBIGWHITEDEBUGLIGHT:\n\t\tgbBigWhiteDebugLightSwitchedOn = !gbBigWhiteDebugLightSwitchedOn;\n\t\tbreak;\n\tcase MENUACTION_COLLISIONPOLYS:\n\t\tgbShowCollisionPolys = !gbShowCollisionPolys;\n\t\tbreak;\n#endif\n\tcase MENUACTION_SHOWHEADBOB:\n\t\tTheCamera.m_bHeadBob = !TheCamera.m_bHeadBob;\n\t\tSaveSettings();\n\t\tbreak;\n\tcase MENUACTION_INVVERT:\n\t\tMousePointerStateHelper.bInvertVertically = !MousePointerStateHelper.bInvertVertically;\n\t\tSaveSettings();\n\t\tbreak;\n\tcase MENUACTION_DYNAMICACOUSTIC:\n\t\tm_PrefsDMA = !m_PrefsDMA;\n\t\tDMAudio.SetDynamicAcousticModelingStatus(m_PrefsDMA);\n\t\tSaveSettings();\n\t\tbreak;\n\tcase MENUACTION_MOUSESTEER:\n\t\tif (m_ControlMethod == CONTROL_STANDARD) {\n\t\t\tCVehicle::m_bDisableMouseSteering = !CVehicle::m_bDisableMouseSteering;\n\t\t\tSaveSettings();\n\t\t}\n\t\tbreak;\n\t}\n}\n\nvoid\nCMenuManager::RequestFrontEndShutDown()\n{\n\tm_bShutDownFrontEndRequested = true;\n}\n\nvoid\nCMenuManager::RequestFrontEndStartUp()\n{\n\tm_bStartUpFrontEndRequested = true;\n}\n\nvoid\nCMenuManager::ResetHelperText() \n{\n\tm_nHelperTextMsgId = 0;\n\tm_nHelperTextAlpha = 300;\n}\n\nvoid\nCMenuManager::SetHelperText(int text)\n{\n\tm_nHelperTextMsgId = text;\n\tm_nHelperTextAlpha = 300;\n}\n\nfloat\nCMenuManager::StretchX(float x)\n{\n\tif (SCREEN_WIDTH == DEFAULT_SCREEN_WIDTH)\n\t\treturn x;\n\telse\n\t\t// We won't make this SCREEN_SCALE, because many cases relies on stretching and we want the code to be portable.\n\t\t// Instead we will use MENU_X_LEFT_ALIGNED or SCREEN_SCALE_X when needed.\n\t\treturn SCREEN_STRETCH_X(x);\n}\n\nfloat CMenuManager::StretchY(float y)\n{\n\tif (SCREEN_HEIGHT == DEFAULT_SCREEN_HEIGHT)\n\t\treturn y;\n\telse\n\t\treturn SCREEN_STRETCH_Y(y);\n}\n\n#ifdef XBOX_MESSAGE_SCREEN\nvoid\nCMenuManager::CloseDialog(void)\n{\n\t// We don't have this on PC GXT :shrug:\n\tstatic wchar* gameSaved = AllocUnicode(\"Game saved successfully!\");\n\n\tif (m_bSaveWasSuccessful && DialogTextCmp(\"FESZ_WR\")) {\n\t\tm_bSaveWasSuccessful = false; // i don't know where XBOX resets that\n\t\tm_pDialogText = gameSaved;\n\t\tSetDialogTimer(1000);\n\t    ProcessDialogTimer();\n\t} else {\n\t\tToggleDialog(false);\n\t}\n\n}\n\nvoid\nCMenuManager::ProcessDialogTimer(void)\n{\n\tif (!m_bDialogOpen || m_nDialogHideTimer == 0)\n\t\treturn;\n\n\t// Also XBOX has unified time source for in-game/menu, but we don't have that\n\tif (m_bMenuActive && CTimer::GetTimeInMilliseconds() > m_nDialogHideTimer || !m_bMenuActive && CTimer::GetTimeInMillisecondsPauseMode() > m_nDialogHideTimerPauseMode) {\n\n\t\t// This is originally activePage.funcs->closePage()\n\t\tCloseDialog();\n\t}\n}\n\nvoid\nCMenuManager::SetDialogTimer(uint32 timer)\n{\n\t// XBOX iterates some page list(actives?) and then sets timer variable of specified page to specified value. We only have dialog right now.\n\t// Also XBOX has unified time source for in-game/menu, but we don't have that, thus 2 timer variables...\n\n\tm_nDialogHideTimer = CTimer::GetTimeInMilliseconds() + timer;\n\tm_nDialogHideTimerPauseMode = CTimer::GetTimeInMillisecondsPauseMode() + timer;\n}\n\nvoid\nCMenuManager::SetDialogText(const char* key)\n{\n\t// There are many things going around here, idk why\n\tm_pDialogText = TheText.Get(key);\n}\n\nbool\nCMenuManager::DialogTextCmp(const char* key)\n{\n\twchar *value = TheText.Get(key);\n\twchar *i = m_pDialogText;\n\tfor (; *i != '\\0' && *value != '\\0'; i++, value++) {\n\t\tif (*i != *value)\n\t\t\treturn false;\n\t}\n\treturn *i == '\\0' && *value == '\\0';\n}\n\nvoid\nCMenuManager::ToggleDialog(bool toggle)\n{\n\t// This originally calls some mysterious function on enable and close CB on disable, along with decreasing some counter. Which is no use for dialog\n\n\t// XBOX doesn't do that\n\tif (toggle)\n\t\tm_nDialogHideTimer = 0;\n\n\tm_bDialogOpen = toggle;\n}\n\nvoid\nDrawDialogBg(float offset, uint8 alpha)\n{\n\tCSprite2d::Draw2DPolygon(SCALE_AND_CENTER_X(84.f + offset), MENU_Y(126.f + offset),\n\t\tSCALE_AND_CENTER_X(512.f + offset), MENU_Y(109.f + offset),\n\t\tSCALE_AND_CENTER_X(100.f + offset), MENU_Y(303.f + offset),\n\t\tSCALE_AND_CENTER_X(474.f + offset), MENU_Y(311.f + offset), CRGBA(107, 193, 236, alpha));\n\tCSprite2d::Draw2DPolygon(SCALE_AND_CENTER_X(523.f + offset), MENU_Y(108.f + offset),\n\t\tSCALE_AND_CENTER_X(542.f + offset), MENU_Y(107.f + offset),\n\t\tSCALE_AND_CENTER_X(485.f + offset), MENU_Y(310.f + offset),\n\t\tSCALE_AND_CENTER_X(516.f + offset), MENU_Y(311.f + offset), CRGBA(107, 193, 236, alpha));\n}\n\nvoid\nCMenuManager::DrawOverlays(void)\n{\n\t// This is stripped to show only Dialog box, XBOX does much more in here.\n\n\tif (!m_bDialogOpen)\n\t\treturn;\n\n\tDefinedState();\n\n\tCSprite2d::DrawRect(CRect(0, SCREEN_HEIGHT, SCREEN_WIDTH, 0), CRGBA(0, 0, 0, 160));\n\n\t// Ofc this is not hardcoded like that on Xbox, it should be a texture\n\tDrawDialogBg(20.f, 160); // shadow\n\tDrawDialogBg(0.f, 255);\n\n\tCFont::SetBackgroundOff();\n\tCFont::SetPropOn();\n\tCFont::SetJustifyOn();\n\tCFont::SetBackGroundOnlyTextOn();\n\tCFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD));\n\tCFont::SetCentreSize(SCREEN_SCALE_X(380.0f));\n\tCFont::SetCentreOn();\n\tCFont::SetColor(CRGBA(LABEL_COLOR.r, LABEL_COLOR.g, LABEL_COLOR.b, 255));\n\tCFont::SetDropShadowPosition(2);\n\tCFont::SetDropColor(CRGBA(0, 0, 0, 255));\n\t// Both of those are 0.9 on Xbox, which is ofcouse wrong...\n\tCFont::SetScale(SCREEN_SCALE_X(BIGTEXT_X_SCALE), SCREEN_SCALE_Y(BIGTEXT_Y_SCALE));\n\t\n\tint x = SCREEN_WIDTH / 2.f - SCREEN_SCALE_X(30.0f);\n\tint y = SCREEN_HEIGHT / 2.f - SCREEN_SCALE_Y(30.0f);\n\tint numOfLines = CFont::GetNumberLines(x, y, m_pDialogText);\n\tCFont::PrintString(x, y - SCREEN_SCALE_Y(numOfLines / 2.f), m_pDialogText);\n\tCFont::DrawFonts();\n}\n#endif\n\nvoid\nCMenuManager::ProcessFileActions()\n{\n\tswitch (m_nCurrScreen) {\n\t\tcase MENUPAGE_LOADING_IN_PROGRESS:\n\t\t\tif (CheckSlotDataValid(m_nCurrSaveSlot)) {\n#ifdef USE_DEBUG_SCRIPT_LOADER\n\t\t\t\tscriptToLoad = 0;\n#endif\n\n#ifdef XBOX_MESSAGE_SCREEN\n\t\t\t\tSetDialogText(\"FELD_WR\");\n\t\t\t\tToggleDialog(true);\n#else\n\t\t\t\tif (!m_bGameNotLoaded)\n\t\t\t\t\tMessageScreen(\"FELD_WR\", true);\n#endif\n\t\t\t\tDoSettingsBeforeStartingAGame();\n\t\t\t\tm_bWantToLoad = true;\n\t\t\t} else\n\t\t\t\tSwitchToNewScreen(MENUPAGE_NEW_GAME);\n\n\t\t\tbreak;\n\t\tcase MENUPAGE_DELETING_IN_PROGRESS:\n\t\t{\n\t\t\tstatic bool waitedForScreen = false;\n\n\t\t\tif (waitedForScreen) {\n\t\t\t\tbool SlotPopulated = false;\n\t\t\t\tif (PcSaveHelper.DeleteSlot(m_nCurrSaveSlot)) {\n\t\t\t\t\tPcSaveHelper.PopulateSlotInfo();\n\t\t\t\t\tSlotPopulated = true;\n\t\t\t\t}\n\n\t\t\t\tif (SlotPopulated) {\n\t\t\t\t\tSwitchToNewScreen(MENUPAGE_DELETE_SUCCESSFUL);\n\t\t\t\t} else {\n\t\t\t\t\tSwitchToNewScreen(MENUPAGE_SAVE_CUSTOM_WARNING);\n\t\t\t\t\tstrncpy(aScreens[m_nCurrScreen].m_ScreenName, \"FES_DEL\", 8);\n\t\t\t\t\tstrncpy(aScreens[m_nCurrScreen].m_aEntries[0].m_EntryName, \"FES_DEE\", 8);\n\t\t\t\t}\n\t\t\t\twaitedForScreen = false;\n\t\t\t} else if (m_nMenuFadeAlpha >= 255)\n\t\t\t\twaitedForScreen = true;\n\n\t\t\tbreak;\n\t\t}\n\t\tcase MENUPAGE_SAVING_IN_PROGRESS:\n\t\t{\n#ifdef XBOX_MESSAGE_SCREEN\n\t\t\tif (m_bDialogOpen && DialogTextCmp(\"FESZ_WR\")) {\n\t\t\t\tPauseModeTime startTime = CTimer::GetTimeInMillisecondsPauseMode();\n\t\t\t\tint8 SaveSlot = PcSaveHelper.SaveSlot(m_nCurrSaveSlot);\n\t\t\t\tPcSaveHelper.PopulateSlotInfo();\n\n\t\t\t\t// Original code, but we don't want redundant saving text if it doesn't\n#if 0\n\t\t\t\tCTimer::Update(); // not on Xbox, who updates it?\n\n\t\t\t\t// it compensates the lag to show saving text always one second... how cute\n\t\t\t\tint dialogDur = Max(1, startTime - CTimer::GetTimeInMillisecondsPauseMode() + 1000);\n#else\n\t\t\t\tint dialogDur = 1;\n#endif\n\n\t\t\t\tif (SaveSlot) {\n\t\t\t\t\t// error. PC code\n\t\t\t\t\tToggleDialog(false);\n\t\t\t\t\tSwitchToNewScreen(MENUPAGE_SAVE_CUSTOM_WARNING);\n\t\t\t\t\tstrncpy(aScreens[m_nCurrScreen].m_ScreenName, \"FET_SG\", 8);\n\t\t\t\t\tstrncpy(aScreens[m_nCurrScreen].m_aEntries[0].m_EntryName, \"FES_CMP\", 8);\n\n\t\t\t\t} else {\n\t\t\t\t\tm_bSaveWasSuccessful = true;\n\t\t\t\t\tSetDialogTimer(dialogDur);\n\t\t\t\t\tProcessDialogTimer();\n\t\t\t\t\tRequestFrontEndShutDown();\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\tSetDialogText(\"FESZ_WR\");\n\t\t\t\tToggleDialog(true);\n\t\t\t}\n#else\n\t\t\tstatic bool waitedForScreen = false;\n\n\t\t\tif (waitedForScreen) {\n\t\t\t\tint8 SaveSlot = PcSaveHelper.SaveSlot(m_nCurrSaveSlot);\n\t\t\t\tPcSaveHelper.PopulateSlotInfo();\n\t\t\t\tif (SaveSlot) {\n\t\t\t\t\tSwitchToNewScreen(MENUPAGE_SAVE_CUSTOM_WARNING);\n\t\t\t\t\tstrncpy(aScreens[m_nCurrScreen].m_ScreenName, \"FET_SG\", 8);\n\t\t\t\t\tstrncpy(aScreens[m_nCurrScreen].m_aEntries[0].m_EntryName, \"FES_CMP\", 8);\n\t\t\t\t} else\n\t\t\t\t\tSwitchToNewScreen(MENUPAGE_SAVE_SUCCESSFUL);\n\n\t\t\t\twaitedForScreen = false;\n\t\t\t} else if (m_nMenuFadeAlpha >= 255)\n\t\t\t\twaitedForScreen = true;\n#endif\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\nvoid\nCMenuManager::SwitchMenuOnAndOff()\n{\n\tif (!TheCamera.m_WideScreenOn) {\n\n\t\t// Reminder: You need REGISTER_START_BUTTON defined to make it work.\n\t\tif ((CPad::GetPad(0)->GetStartJustDown() || CPad::GetPad(0)->GetEscapeJustDown())\n\t\t\t&& (!m_bMenuActive || m_nCurrScreen == MENUPAGE_PAUSE_MENU || m_nCurrScreen == MENUPAGE_CHOOSE_SAVE_SLOT || m_nCurrScreen == MENUPAGE_SAVE_CHEAT_WARNING)\n\t\t\t|| m_bShutDownFrontEndRequested || m_bStartUpFrontEndRequested\n#ifdef REGISTER_START_BUTTON\n\t\t\t|| CPad::GetPad(0)->GetStartJustDown() && !m_bGameNotLoaded\n#endif\n\t\t\t) {\n\n\t\t\tif (m_nCurrScreen != MENUPAGE_LOADING_IN_PROGRESS\n#ifdef XBOX_MESSAGE_SCREEN\n\t\t\t\t&& m_nCurrScreen != MENUPAGE_SAVING_IN_PROGRESS\n#endif\n\t\t\t\t) {\n\t\t\t\tDoRWStuffStartOfFrame(0, 0, 0, 0, 0, 0, 255);\n\t\t\t\tDoRWStuffEndOfFrame();\n\t\t\t\tDoRWStuffStartOfFrame(0, 0, 0, 0, 0, 0, 255);\n\t\t\t\tDoRWStuffEndOfFrame();\n\t\t\t}\n\n\t\t\tif (m_bShutDownFrontEndRequested)\n\t\t\t\tm_bMenuActive = false;\n\t\t\telse if (m_bStartUpFrontEndRequested)\n\t\t\t\tm_bMenuActive = true;\n\t\t\telse\n\t\t\t\tm_bMenuActive = !m_bMenuActive;\n\n\t\t\tif (m_bMenuActive) {\n\t\t\t\tif (_InputMouseNeedsExclusive()) {\n\t\t\t\t\t_InputShutdownMouse();\n\t\t\t\t\t_InputInitialiseMouse(false);\n\t\t\t\t}\n\t\t\t\tInitialise();\n\t\t\t\tLoadAllTextures();\n#ifdef FIX_BUGS\n\t\t\t\tCPad::StopPadsShaking();\n#endif\n\t\t\t} else {\n#ifdef EXTENDED_COLOURFILTER\n\t\t\t\t// we always expect CPostFX to be open\n\t\t\t\tCMBlur::BlurOn = true;\n#endif\n\t\t\t\tif (CMBlur::BlurOn)\n\t\t\t\t\tCMBlur::MotionBlurOpen(Scene.camera);\n\t\t\t\telse\n\t\t\t\t\tCMBlur::MotionBlurClose();\n\t\t\t\tDoRWStuffStartOfFrame(0, 0, 0, 0, 0, 0, 255);\n\t\t\t\tDoRWStuffEndOfFrame();\n\t\t\t\tDoRWStuffStartOfFrame(0, 0, 0, 0, 0, 0, 255);\n\t\t\t\tDoRWStuffEndOfFrame();\n\t\t\t\tif (_InputMouseNeedsExclusive()) {\n\t\t\t\t\t_InputShutdownMouse();\n\t\t\t\t\t_InputInitialiseMouse(true);\n\t\t\t\t}\n\n\t\t\t\tm_StatsScrollSpeed = 150.0f;\n#ifdef FIX_BUGS\n\t\t\t\tThingsToDoBeforeLeavingPage();\n#endif\n\t\t\t\tSaveSettings();\n#ifdef LOAD_INI_SETTINGS\n\t\t\t\tSaveINIControllerSettings();\n#endif\n\t\t\t\tpControlEdit = nil;\n\t\t\t\tpEditString = nil;\n\t\t\t\tDisplayComboButtonErrMsg = false;\n\t\t\t\tm_bShutDownFrontEndRequested = false;\n\t\t\t\tm_bStartUpFrontEndRequested = false;\n\t\t\t\tm_bWaitingForNewKeyBind = false;\n\n#ifdef REGISTER_START_BUTTON\n\t\t\t\tint16 start1 = CPad::GetPad(0)->PCTempJoyState.Start, start2 = CPad::GetPad(0)->PCTempKeyState.Start,\n\t\t\t\t\tstart3 = CPad::GetPad(0)->OldState.Start, start4 = CPad::GetPad(0)->NewState.Start;\n#endif\n\t\t\t\tCPad::GetPad(0)->Clear(false);\n\t\t\t\tCPad::GetPad(1)->Clear(false);\n#ifdef REGISTER_START_BUTTON\n\t\t\t\tCPad::GetPad(0)->PCTempJoyState.Start = start1;\n\t\t\t\tCPad::GetPad(0)->PCTempKeyState.Start = start2;\n\t\t\t\tCPad::GetPad(0)->OldState.Start = start3;\n\t\t\t\tCPad::GetPad(0)->NewState.Start = start4;\n#endif\n\t\t\t\tUnloadTextures();\n\t\t\t\tCTimer::EndUserPause();\n\t\t\t\tCTimer::Update();\n\t\t\t\tm_OnlySaveMenu = false;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Just entered the save/safe zone\n\tif (m_bActivateSaveMenu) {\n\t\tDoRWStuffStartOfFrame(0, 0, 0, 0, 0, 0, 255);\n\t\tDoRWStuffEndOfFrame();\n\t\tDoRWStuffStartOfFrame(0, 0, 0, 0, 0, 0, 255);\n\t\tDoRWStuffEndOfFrame();\n\t\tm_bActivateSaveMenu = false;\n\t\tm_bMenuActive = true;\n\t\tm_OnlySaveMenu = true;\n\n\t\tif (_InputMouseNeedsExclusive()) {\n\t\t\t_InputShutdownMouse();\n\t\t\t_InputInitialiseMouse(false);\n\t\t}\n\n\t\tInitialise();\n\t\tLoadAllTextures();\n\n\t\tif (CPad::bHasPlayerCheated) {\n\t\t\tm_nCurrScreen = MENUPAGE_SAVE_CHEAT_WARNING;\n\t\t\tm_nCurrOption = 0;\n\t\t} else {\n\t\t\tm_nCurrScreen = MENUPAGE_CHOOSE_SAVE_SLOT;\n\t\t\tm_nCurrOption = 8;\n\t\t}\n\t}\n\n\tm_bStartUpFrontEndRequested = false;\n\tm_bShutDownFrontEndRequested = false;\n\n#ifdef GAMEPAD_MENU\n\t// Reset pad shaking.\n\tif (TimeToStopPadShaking && TimeToStopPadShaking < CTimer::GetTimeInMillisecondsPauseMode()) {\n\t\tCPad::StopPadsShaking();\n\t\tTimeToStopPadShaking = 0;\n\t}\n#endif\n}\n\nvoid\nCMenuManager::UnloadTextures()\n{\n\tif (m_nCurrScreen == MENUPAGE_SOUND_SETTINGS)\n\t\tDMAudio.StopFrontEndTrack();\n\n\tDMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_STARTING, 0);\n\tDMAudio.ChangeMusicMode(MUSICMODE_GAME);\n\tif (m_bSpritesLoaded) {\n\t\tprintf(\"REMOVE frontend\\n\");\n\t\tint frontend = CTxdStore::FindTxdSlot(\"frontend1\");\n\t\tfor (int i = 0; i < 3; ++i)\n\t\t\tm_aFrontEndSprites[i].Delete();\n\n\t\tCTxdStore::RemoveTxd(frontend);\n\n\t\tif (!m_OnlySaveMenu) {\n\t\t\tint frontend2 = CTxdStore::FindTxdSlot(\"frontend2\");\n\t\t\tfor (int i = 3; i < NUM_MENU_SPRITES; ++i)\n\t\t\t\tm_aFrontEndSprites[i].Delete();\n\n\t\t\tCTxdStore::RemoveTxd(frontend2);\n\n#ifdef GAMEPAD_MENU\n\t\t\t// Unload controller txd\n\t\t\tint frontend_controller = CTxdStore::FindTxdSlot(\"frontend_controller\");\n\t\t\tif (frontend_controller != -1)\n\t\t\t\tCTxdStore::RemoveTxd(frontend_controller);\n#endif\n\t\t}\n\n\t\tm_bSpritesLoaded = false;\n\t}\n\tm_OnlySaveMenu = false;\n\tCUserDisplay::PlaceName.ProcessAfterFrontEndShutDown();\n}\n\nvoid\nCMenuManager::WaitForUserCD()\n{\n\tCSprite2d *splash;\n\tchar *splashscreen = nil;\n\n\tsplash = LoadSplash(splashscreen);\n\n\tif (RsGlobal.quit)\n\t\treturn;\n\n\tHandleExit();\n\tCPad::UpdatePads();\n\tMessageScreen(\"NO_PCCD\", true);\n\n\tif (CPad::GetPad(0)->GetEscapeJustDown()) {\n\t\tm_bQuitGameNoCD = true;\n\t\tRsEventHandler(rsQUITAPP, nil);\n\t}\n}\n\nvoid\nCMenuManager::DrawQuitGameScreen(void)\n{\n\tstatic int32 exitSignalTimer = 0;\n\n#ifdef FIX_BUGS\n\tint alpha = clamp(m_nMenuFadeAlpha, 0, 255);\n#else\n\tint alpha = m_nMenuFadeAlpha;\n#endif\n\n#ifndef MUCH_SHORTER_OUTRO_SCREEN\n\tstatic PauseModeTime lastTickIncrease = 0;\n\tif (alpha == 255 && CTimer::GetTimeInMillisecondsPauseMode() - lastTickIncrease > 10) {\n\t\texitSignalTimer++;\n\t\tlastTickIncrease = CTimer::GetTimeInMillisecondsPauseMode();\n\t}\n#else\n\tstatic PauseModeTime firstTick = CTimer::GetTimeInMillisecondsPauseMode();\n\tif (alpha == 255 && CTimer::GetTimeInMillisecondsPauseMode() - firstTick > 750) {\n\t\texitSignalTimer = 150;\n\t}\n#endif\n\tstatic CSprite2d *splash = nil;\n\n\tif (splash == nil)\n\t\tsplash = LoadSplash(\"OUTRO\");\n\n\tm_aFrontEndSprites[MENUSPRITE_VCLOGO].Draw(CRect(SCREEN_STRETCH_X(28.0f), MENU_Y(8.0f), SCREEN_STRETCH_X(27.0f) + MENU_X(130.f), MENU_Y(138.0f)), CRGBA(255, 255, 255, 255 - alpha));\n\n\t// Or we can see menu background from sides\n#ifdef ASPECT_RATIO_SCALE\n\tCSprite2d::DrawRect(CRect(0, 0, MENU_X_LEFT_ALIGNED(0.f), SCREEN_HEIGHT), CRGBA(0, 0, 0, alpha));\n\tCSprite2d::DrawRect(CRect(MENU_X_RIGHT_ALIGNED(0.f), 0, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(0, 0, 0, alpha));\n#endif\n\n\tsplash->Draw(CRect(MENU_X_LEFT_ALIGNED(0.f), 0, MENU_X_RIGHT_ALIGNED(0.f), SCREEN_HEIGHT), CRGBA(255, 255, 255, alpha));\n\tif (alpha == 255 && exitSignalTimer == 150)\n\t\tRsEventHandler(rsQUITAPP, nil);\n\n\tm_bShowMouse = false;\n\tm_AllowNavigation = false;\n}\n\nvoid\nCMenuManager::PrintMap(void)\n{\n\tm_bMenuMapActive = true;\n\tCRadar::InitFrontEndMap();\n\n\t// Because m_fMapSize is half of the map length(hence * 2), and map consists of 3x3 tiles(hence / 3).\n\tfloat halfTile = m_fMapSize * 2.f / 3.f / 2.f;\n\n\tRwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR);\n\n\tif (SCREEN_WIDTH >= m_fMapCenterX - m_fMapSize || SCREEN_HEIGHT >= m_fMapCenterY - m_fMapSize) {\n\t\tm_aFrontEndSprites[MENUSPRITE_MAPTOP01].Draw(CRect(m_fMapCenterX - m_fMapSize, m_fMapCenterY - m_fMapSize,\n\t\t\tm_fMapCenterX - halfTile, m_fMapCenterY - halfTile), CRGBA(255, 255, 255, FadeIn(255)));\n\t}\n\n\tif (SCREEN_WIDTH >= m_fMapCenterX - halfTile || SCREEN_HEIGHT >= m_fMapCenterY - m_fMapSize) {\n\t\tm_aFrontEndSprites[MENUSPRITE_MAPTOP02].Draw(CRect(m_fMapCenterX - halfTile, m_fMapCenterY - m_fMapSize,\n\t\t\tm_fMapCenterX + halfTile, m_fMapCenterY - halfTile), CRGBA(255, 255, 255, FadeIn(255)));\n\t}\n\n\tif (SCREEN_WIDTH >= m_fMapCenterX + halfTile || SCREEN_HEIGHT >= m_fMapCenterY - m_fMapSize) {\n\t\tm_aFrontEndSprites[MENUSPRITE_MAPTOP03].Draw(CRect(m_fMapCenterX + halfTile, m_fMapCenterY - m_fMapSize,\n\t\t\tm_fMapCenterX + m_fMapSize, m_fMapCenterY - halfTile), CRGBA(255, 255, 255, FadeIn(255)));\n\t}\n\n\tif (SCREEN_WIDTH >= m_fMapCenterX - m_fMapSize || SCREEN_HEIGHT >= m_fMapCenterY - halfTile) {\n\t\tm_aFrontEndSprites[MENUSPRITE_MAPMID01].Draw(CRect(m_fMapCenterX - m_fMapSize, m_fMapCenterY - halfTile,\n\t\t\tm_fMapCenterX - halfTile, m_fMapCenterY + halfTile), CRGBA(255, 255, 255, FadeIn(255)));\n\t}\n\n\tif (SCREEN_WIDTH >= m_fMapCenterX - halfTile || SCREEN_HEIGHT >= m_fMapCenterY - halfTile) {\n\t\tm_aFrontEndSprites[MENUSPRITE_MAPMID02].Draw(CRect(m_fMapCenterX - halfTile, m_fMapCenterY - halfTile,\n\t\t\tm_fMapCenterX + halfTile, m_fMapCenterY + halfTile), CRGBA(255, 255, 255, FadeIn(255)));\n\t}\n\n\tif (SCREEN_WIDTH >= m_fMapCenterX + halfTile || SCREEN_HEIGHT >= m_fMapCenterY - halfTile) {\n\t\tm_aFrontEndSprites[MENUSPRITE_MAPMID03].Draw(CRect(m_fMapCenterX + halfTile, m_fMapCenterY - halfTile,\n\t\t\tm_fMapCenterX + m_fMapSize, m_fMapCenterY + halfTile), CRGBA(255, 255, 255, FadeIn(255)));\n\t}\n\n\tif (SCREEN_WIDTH >= m_fMapCenterX - m_fMapSize || SCREEN_HEIGHT >= m_fMapCenterY + halfTile) {\n\t\tm_aFrontEndSprites[MENUSPRITE_MAPBOT01].Draw(CRect(m_fMapCenterX - m_fMapSize, m_fMapCenterY + halfTile,\n\t\t\tm_fMapCenterX - halfTile, m_fMapCenterY + m_fMapSize), CRGBA(255, 255, 255, FadeIn(255)));\n\t}\n\n\tif (SCREEN_WIDTH >= m_fMapCenterX - halfTile || SCREEN_HEIGHT >= m_fMapCenterY + halfTile) {\n\t\tm_aFrontEndSprites[MENUSPRITE_MAPBOT02].Draw(CRect(m_fMapCenterX - halfTile, m_fMapCenterY + halfTile,\n\t\t\tm_fMapCenterX + halfTile, m_fMapCenterY + m_fMapSize), CRGBA(255, 255, 255, FadeIn(255)));\n\t}\n\n\tif (SCREEN_WIDTH >= m_fMapCenterX + halfTile || SCREEN_HEIGHT >= m_fMapCenterY + halfTile) {\n\t\tm_aFrontEndSprites[MENUSPRITE_MAPBOT03].Draw(CRect(m_fMapCenterX + halfTile, m_fMapCenterY + halfTile,\n\t\t\tm_fMapCenterX + m_fMapSize, m_fMapCenterY + m_fMapSize), CRGBA(255, 255, 255, FadeIn(255)));\n\t}\n\n\tCRadar::DrawBlips();\n\tif (m_PrefsShowLegends) {\n\t\tCFont::SetWrapx(MENU_X_RIGHT_ALIGNED(40.0f));\n\t\tCFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(84.0f));\n\t\tCFont::SetBackGroundOnlyTextOff();\n\t\tCFont::SetColor(CRGBA(LABEL_COLOR.r, LABEL_COLOR.g, LABEL_COLOR.b, FadeIn(255)));\n\t\tCFont::SetDropShadowPosition(2);\n\t\tCFont::SetDropColor(CRGBA(0, 0, 0, FadeIn(255)));\n\t\tCFont::SetCentreOn();\n\t\tCFont::SetFontStyle(FONT_LOCALE(FONT_HEADING));\n\t\tCFont::SetScale(SCREEN_SCALE_X(0.65f), SCREEN_SCALE_Y(0.95f));\n\n\t\tint secondColumnStart = (CRadar::MapLegendCounter - 1) / 2;\n\t\tint boxBottom = MENU_Y(100.0f);\n\n\t\t// + 3, because we want 19*3 px padding\n\t\tfor (int i = 0; i < secondColumnStart + 3; i++) {\n\t\t\tboxBottom += MENU_Y(19.f);\n\t\t}\n\n\t\tCSprite2d::DrawRect(CRect(MENU_X_LEFT_ALIGNED(95.0f), MENU_Y(100.0f), MENU_X_LEFT_ALIGNED(555.f), boxBottom),\n\t\t\tCRGBA(0, 0, 0, FadeIn(190)));\n\n\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(320.0f), MENU_Y(102.0f), TheText.Get(\"FE_MLG\"));\n\t\tCFont::SetRightJustifyOff();\n\t\tCFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD));\n\t\tif (m_PrefsLanguage == LANGUAGE_AMERICAN)\n\t\t\tCFont::SetScale(SCREEN_SCALE_X(0.55f), SCREEN_SCALE_Y(0.55f));\n\t\telse\n\t\t\tCFont::SetScale(SCREEN_SCALE_X(0.45f), SCREEN_SCALE_Y(0.55f));\n\n\t\tCFont::SetColor(CRGBA(225, 225, 225, FadeIn(255)));\n\t\tCFont::SetDropShadowPosition(0);\n\n\t\tint y = MENU_Y(127.0f);\n\t\tint x = MENU_X_LEFT_ALIGNED(160.0f);\n\n\t\tfor (int16 i = 0; i < CRadar::MapLegendCounter; i++) {\n\t\t\tCRadar::DrawLegend(x, y, CRadar::MapLegendList[i]);\n\n\t\t\tif (i == secondColumnStart) {\n\t\t\t\tx = MENU_X_LEFT_ALIGNED(350.0f);\n\t\t\t\ty = MENU_Y(127.0f);\n\t\t\t} else {\n\t\t\t\ty += MENU_Y(19.0f);\n\t\t\t}\n\t\t}\n\t}\n\n#ifdef MAP_ENHANCEMENTS\n\tif (m_nMenuFadeAlpha != 255 && !m_bShowMouse) {\n\t\tmapCrosshair.x = SCREEN_WIDTH / 2;\n\t\tmapCrosshair.y = SCREEN_HEIGHT / 2;\n\t} else if (m_bShowMouse) {\n\t\tmapCrosshair.x = m_nMousePosX;\n\t\tmapCrosshair.y = m_nMousePosY;\n\t}\n\n\tCSprite2d::DrawRect(CRect(mapCrosshair.x - MENU_X(1.0f), 0.0f,\n\t\tmapCrosshair.x + MENU_X(1.0f), SCREEN_HEIGHT),\n\t\tCRGBA(0, 0, 0, 150));\n\tCSprite2d::DrawRect(CRect(0.0f, mapCrosshair.y + MENU_X(1.0f),\n\t\tSCREEN_WIDTH, mapCrosshair.y - MENU_X(1.0f)),\n\t\tCRGBA(0, 0, 0, 150));\n\n#endif\n\tm_bMenuMapActive = false;\n\n\tCFont::SetWrapx(MENU_X_RIGHT_ALIGNED(MENU_X_MARGIN));\n\tCFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(MENU_X_MARGIN));\n\tDisplayHelperText(\"FEH_MPH\");\n}\n\nvoid\nCMenuManager::ChangeRadioStation(int8 increaseBy)\n{\n\tif (m_ScrollRadioBy != 0)\n\t\treturn;\n\n\tm_PrefsRadioStation += increaseBy;\n\tm_ScrollRadioBy = increaseBy;\n\tif (m_ScrollRadioBy == 1) {\n\t\tDMAudio.PlayFrontEndSound(SOUND_FRONTEND_ENTER_OR_ADJUST, 0);\n\t\tm_LeftMostRadioX = MENU_X_LEFT_ALIGNED(MENURADIO_ICON_FIRST_X);\n\t} else {\n\t\tDMAudio.PlayFrontEndSound(SOUND_FRONTEND_ENTER_OR_ADJUST, 0);\n\t\tm_LeftMostRadioX = MENU_X_LEFT_ALIGNED(MENURADIO_ICON_FIRST_X - (2 * MENURADIO_ICON_SIZE));\n\t}\n\n\tif (DMAudio.IsMP3RadioChannelAvailable()) {\n\t\tif (m_PrefsRadioStation < WILDSTYLE)\n\t\t\tm_PrefsRadioStation = USERTRACK;\n\t\tif (m_PrefsRadioStation > USERTRACK)\n\t\t\tm_PrefsRadioStation = WILDSTYLE;\n\t} else {\n\t\tif (m_PrefsRadioStation < WILDSTYLE)\n\t\t\tm_PrefsRadioStation = WAVE;\n\t\tif (m_PrefsRadioStation > WAVE)\n\t\t\tm_PrefsRadioStation = WILDSTYLE;\n\t}\n\tDMAudio.StopFrontEndTrack();\n\tDMAudio.PlayFrontEndSound(SOUND_RADIO_CHANGE, 0);\n}\n\n#if 0\nuint8 CMenuManager::GetNumberOfMenuOptions()\n{\n\tuint8 Rows = -1;\n\tfor (int i = 0; i < NUM_MENUROWS; i++) {\n\t\tif (aScreens[m_nCurrScreen].m_aEntries[i].m_Action == MENUACTION_NOTHING)\n\t\t\tbreak;\n\n\t\t++Rows;\n\t}\n\treturn Rows;\n}\n#endif\n\n#ifdef GAMEPAD_MENU\nconst char* controllerTypesPaths[] = {\n\t\"MODELS/FRONTEND_DS2.TXD\",\n\t\"MODELS/FRONTEND_DS3.TXD\",\n\t\"MODELS/FRONTEND_DS4.TXD\",\n\t\"MODELS/FRONTEND_X360.TXD\",\n\t\"MODELS/FRONTEND_XONE.TXD\",\n};\n\nvoid\nCMenuManager::PrintController(void)\n{\n\t// Don't print anything if controller texture is missing\n\tif (!m_aFrontEndSprites[MENUSPRITE_CONTROLLER].m_pTexture) return;\n\n\tconst float scale = 0.9f;\n\tconst float CONTROLLER_SIZE_X = 235.2f;\n\tconst float CONTROLLER_SIZE_Y = 175.2f;\n\tconst float CONTROLLER_POS_X = (DEFAULT_SCREEN_WIDTH - CONTROLLER_SIZE_X) / 2.0f;\n\tconst float CONTROLLER_POS_Y = 220.0f;\n\n\tfloat centerX = CONTROLLER_POS_X + CONTROLLER_SIZE_X / 2;\n\tfloat centerY = CONTROLLER_POS_Y + CONTROLLER_SIZE_Y / 2;\n\n#define X(f) ((f)*scale + centerX)\n#define Y(f) ((f)*scale + centerY)\n\n\tm_aFrontEndSprites[MENUSPRITE_CONTROLLER].Draw(MENU_X_LEFT_ALIGNED(X(-CONTROLLER_SIZE_X / 2)), MENU_Y(Y(-CONTROLLER_SIZE_Y / 2)), MENU_X(CONTROLLER_SIZE_X * scale), MENU_Y(CONTROLLER_SIZE_Y * scale), CRGBA(255, 255, 255, FadeIn(255)));\n\tif (m_DisplayControllerOnFoot) {\n\t\tif ((int)CTimer::GetTimeInMillisecondsPauseMode() & 0x400)\n\t\t\tm_aFrontEndSprites[MENUSPRITE_ARROWS1].Draw(MENU_X_LEFT_ALIGNED(X(-CONTROLLER_SIZE_X / 2)), MENU_Y(Y(-CONTROLLER_SIZE_Y / 2)), MENU_X(CONTROLLER_SIZE_X * scale), MENU_Y(CONTROLLER_SIZE_Y * scale), CRGBA(255, 255, 255, FadeIn(255)));\n\t\telse\n\t\t\tm_aFrontEndSprites[MENUSPRITE_ARROWS3].Draw(MENU_X_LEFT_ALIGNED(X(-CONTROLLER_SIZE_X / 2)), MENU_Y(Y(-CONTROLLER_SIZE_Y / 2)), MENU_X(CONTROLLER_SIZE_X * scale), MENU_Y(CONTROLLER_SIZE_Y * scale), CRGBA(255, 255, 255, FadeIn(255)));\n\t}\n\telse {\n\t\tif ((int)CTimer::GetTimeInMillisecondsPauseMode() & 0x400)\n\t\t\tm_aFrontEndSprites[MENUSPRITE_ARROWS2].Draw(MENU_X_LEFT_ALIGNED(X(-CONTROLLER_SIZE_X / 2)), MENU_Y(Y(-CONTROLLER_SIZE_Y / 2)), MENU_X(CONTROLLER_SIZE_X * scale), MENU_Y(CONTROLLER_SIZE_Y * scale), CRGBA(255, 255, 255, FadeIn(255)));\n\t\telse\n\t\t\tm_aFrontEndSprites[MENUSPRITE_ARROWS4].Draw(MENU_X_LEFT_ALIGNED(X(-CONTROLLER_SIZE_X / 2)), MENU_Y(Y(-CONTROLLER_SIZE_Y / 2)), MENU_X(CONTROLLER_SIZE_X * scale), MENU_Y(CONTROLLER_SIZE_Y * scale), CRGBA(255, 255, 255, FadeIn(255)));\n\t}\n\n\tCFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD));\n\n\tCFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE * 2 * scale * 0.9f), MENU_Y(SMALLESTTEXT_Y_SCALE * scale * 0.9f)); // X\n\n\tCFont::SetDropColor(CRGBA(0, 0, 0, FadeIn(255)));\n\tCFont::SetDropShadowPosition(0);\n\tCFont::SetColor(CRGBA(0, 0, 0, FadeIn(255)));\n\tCFont::SetWrapx(SCREEN_WIDTH);\n\n\tfloat TEXT_L2_X = 85.0f + CONTROLLER_POS_X - centerX, TEXT_L2_Y = -14.0f + CONTROLLER_POS_Y - centerY;\n\tfloat TEXT_L1_X = -4.0f + CONTROLLER_POS_X - centerX, TEXT_L1_Y = 27.0f + CONTROLLER_POS_Y - centerY, TEXT_L1_Y_VEH = 3.0f + TEXT_L1_Y;\n\tfloat TEXT_DPAD_X = -4.0f + CONTROLLER_POS_X - centerX, TEXT_DPAD_Y = 67.0f + CONTROLLER_POS_Y - centerY;\n\tfloat TEXT_LSTICK_X = -4.0f + CONTROLLER_POS_X - centerX, TEXT_LSTICK_Y = 97.0f + CONTROLLER_POS_Y - centerY;\n\tfloat TEXT_SELECT_X = 170.0f + CONTROLLER_POS_X - centerX, TEXT_SELECT_Y = 141.0f + CONTROLLER_POS_Y - centerY;\n\tfloat TEXT_START_X = 130.0f + CONTROLLER_POS_X - centerX, TEXT_START_Y = 128.0f + CONTROLLER_POS_Y - centerY;\n\tfloat TEXT_R2_X = 164.0f + CONTROLLER_POS_X - centerX, TEXT_R2_Y = -14.0f + CONTROLLER_POS_Y - centerY;\n\tfloat TEXT_R1_X = 242.0f + CONTROLLER_POS_X - centerX, TEXT_R1_Y = 27.0f + CONTROLLER_POS_Y - centerY;\n\n\tfloat TEXT_SQUARE_X = 147.0f + CONTROLLER_POS_X - centerX, TEXT_SQUARE_Y = 30.0f + CONTROLLER_POS_Y - centerY;\n\tfloat TEXT_TRIANGLE_X = 242.0f + CONTROLLER_POS_X - centerX, TEXT_TRIANGLE_Y = 55.0f + CONTROLLER_POS_Y - centerY;\n\tfloat TEXT_CIRCLE_X = 242.0f + CONTROLLER_POS_X - centerX, TEXT_CIRCLE_Y = 67.0f + CONTROLLER_POS_Y - centerY;\n\tfloat TEXT_CROSS_X = 242.0f + CONTROLLER_POS_X - centerX, TEXT_CROSS_Y = 80.0f + CONTROLLER_POS_Y - centerY;\n\tfloat TEXT_RSTICK_X = 242.0f + CONTROLLER_POS_X - centerX, TEXT_RSTICK_Y = 97.0f + CONTROLLER_POS_Y - centerY;\n\tfloat TEXT_R3_X = 242.0f + CONTROLLER_POS_X - centerX, TEXT_R3_Y = 110.0f + CONTROLLER_POS_Y - centerY;\n\tfloat TEXT_L3_X = 94.0f + CONTROLLER_POS_X - centerX, TEXT_L3_Y = 162.0f + CONTROLLER_POS_Y - centerY;\n\tfloat TEXT_L2R2_X = 120.0f + CONTROLLER_POS_X - centerX, TEXT_L2R2_Y = -4.0f + CONTROLLER_POS_Y - centerY;\n\n\tswitch (m_PrefsControllerType)\n\t{\n\tcase CONTROLLER_DUALSHOCK4:\n\t\tTEXT_L1_Y += 7.0f;\n\t\tTEXT_L1_Y_VEH = TEXT_L1_Y;\n\t\tTEXT_R1_Y += 7.0f;\n\t\tTEXT_TRIANGLE_Y -= 1.0f;\n\t\tTEXT_CIRCLE_Y -= 1.0f;\n\t\tTEXT_CROSS_Y -= 1.0f;\n\t\tTEXT_RSTICK_Y -= 4.0f;\n\t\tTEXT_R3_Y -= 4.0f;\n\t\tTEXT_DPAD_Y -= 2.0f;\n\t\tTEXT_LSTICK_Y -= 6.0f;\n\t\tTEXT_L3_X -= 2.0f;\n\t\tbreak;\n\tcase CONTROLLER_XBOXONE:\n\t\tTEXT_L2_X -= 2.0f;\n\t\tTEXT_R2_X += 2.0f;\n\t\tTEXT_L1_Y += 15.0f;\n\t\tTEXT_L1_Y_VEH = TEXT_L1_Y;\n\t\tTEXT_R1_Y += 15.0f;\n\t\tTEXT_TRIANGLE_Y += 4.0f;\n\t\tTEXT_CIRCLE_Y += 4.0f;\n\t\tTEXT_CROSS_Y += 4.0f;\n\t\tTEXT_RSTICK_Y += 1.0f;\n\t\tTEXT_R3_Y += 1.0f;\n\t\tTEXT_DPAD_Y += 29.0f;\n\t\tTEXT_LSTICK_Y -= 20.0f;\n\t\tTEXT_L3_X -= 36.0f;\n\t\tTEXT_L2R2_Y += 5.0f;\n\t\tTEXT_SELECT_X += 4.0f;\n\t\tbreak;\n\tcase CONTROLLER_XBOX360:\n\t\tTEXT_L2_X += 8.0f;\n\t\tTEXT_R2_X -= 8.0f;\n\t\tTEXT_L1_Y += 15.0f;\n\t\tTEXT_L1_Y_VEH = TEXT_L1_Y;\n\t\tTEXT_R1_Y += 15.0f;\n\t\tTEXT_TRIANGLE_Y += 4.0f;\n\t\tTEXT_CIRCLE_Y += 4.0f;\n\t\tTEXT_CROSS_Y += 4.0f;\n\t\tTEXT_RSTICK_Y += 4.0f;\n\t\tTEXT_R3_Y += 4.0f;\n\t\tTEXT_DPAD_Y += 30.0f;\n\t\tTEXT_LSTICK_Y -= 19.0f;\n\t\tTEXT_L3_X -= 36.0f;\n\t\tTEXT_L2R2_Y += 5.0f;\n\t\tTEXT_SELECT_X += 3.0f;\n\t\tbreak;\n\t};\n\n\tif (m_DisplayControllerOnFoot) {\n\t\tswitch (CPad::GetPad(0)->Mode) {\n\t\tcase 0:\n\t\t\tCFont::SetRightJustifyOn();\n\t\t\tswitch (m_PrefsLanguage)\n\t\t\t{\n\t\t\tcase LANGUAGE_FRENCH:\n\t\t\tcase LANGUAGE_SPANISH:\n\t\t\t\tTEXT_L2_X -= 45.0f;\n\t\t\t\tCFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(X(TEXT_L1_X)) - SCREEN_SCALE_X(85));\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tCFont::SetRightJustifyWrap(0);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L2_X)), MENU_Y(Y(TEXT_L2_Y)), TheText.Get(\"FEC_CWL\"));\n\t\t\tCFont::SetRightJustifyWrap(0);\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L1_X)), MENU_Y(Y(TEXT_L1_Y)), TheText.Get(\"FEC_LOF\"));\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_DPAD_X)), MENU_Y(Y(TEXT_DPAD_Y)), TheText.Get(\"FEC_MOV\"));\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_LSTICK_X)), MENU_Y(Y(TEXT_LSTICK_Y)), TheText.Get(\"FEC_MOV\"));\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_LSTICK_X)), MENU_Y(Y(TEXT_R3_Y)), TheText.Get(\"FEC_CR3\"));\n\t\t\tCFont::SetRightJustifyOn();\n\t\t\tswitch (m_PrefsLanguage)\n\t\t\t{\n\t\t\tcase LANGUAGE_GERMAN:\n\t\t\t\tTEXT_SELECT_X += 20.0f;\n\t\t\t\tbreak;\n\t\t\tcase LANGUAGE_SPANISH:\n\t\t\t\tTEXT_SELECT_X += 15.0f;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_SELECT_X)), MENU_Y(Y(TEXT_SELECT_Y)), TheText.Get(\"FEC_CAM\"));\n\t\t\tCFont::SetJustifyOn();\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_START_X)), MENU_Y(Y(TEXT_START_Y)), TheText.Get(\"FEC_PAU\"));\n\t\t\tswitch (m_PrefsLanguage)\n\t\t\t{\n\t\t\tcase LANGUAGE_FRENCH:\n\t\t\tcase LANGUAGE_SPANISH:\n\t\t\t\tTEXT_R2_X += 30.0f;\n\t\t\t\tCFont::SetJustifyOff();\n\t\t\t\tCFont::SetWrapx(MENU_X_LEFT_ALIGNED(X(TEXT_R2_X)) + SCREEN_SCALE_X(120));\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R2_X)), MENU_Y(Y(TEXT_R2_Y)), TheText.Get(\"FEC_CWR\"));\n\t\t\tCFont::SetJustifyOn();\n\t\t\tCFont::SetWrapx(SCREEN_WIDTH);\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R1_X)), MENU_Y(Y(TEXT_R1_Y)), TheText.Get(\"FEC_TAR\"));\n\t\t\tCFont::SetRightJustifyOn();\n\t\t\tCFont::PrintStringFromBottom(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)), MENU_Y(Y(TEXT_SQUARE_Y)), TheText.Get(\"FEC_JUM\"));\n\t\t\tCFont::SetJustifyOn();\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_TRIANGLE_X)), MENU_Y(Y(TEXT_TRIANGLE_Y)), TheText.Get(\"FEC_ENV\"));\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CIRCLE_X)), MENU_Y(Y(TEXT_CIRCLE_Y)), TheText.Get(\"FEC_ATT\"));\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CROSS_X)), MENU_Y(Y(TEXT_CROSS_Y)), TheText.Get(\"FEC_RUN\"));\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_RSTICK_X)), MENU_Y(Y(TEXT_RSTICK_Y)), TheText.Get(\"FEC_FPC\"));\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R3_X)), MENU_Y(Y(TEXT_R3_Y)), TheText.Get(\"FEC_LB3\"));\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R3_X)), MENU_Y(Y(TEXT_R3_Y + 13.0f)), TheText.Get(\"FEC_R3\"));\n\t\t\tbreak;\n\t\tcase 1:\n\t\t\tCFont::SetRightJustifyOn();\n\t\t\tswitch (m_PrefsLanguage)\n\t\t\t{\n\t\t\tcase LANGUAGE_FRENCH:\n\t\t\tcase LANGUAGE_SPANISH:\n\t\t\t\tTEXT_L2_X -= 45.0f;\n\t\t\t\tCFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(X(TEXT_L1_X)) - SCREEN_SCALE_X(85));\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tCFont::SetRightJustifyWrap(0);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L2_X)), MENU_Y(Y(TEXT_L2_Y)), TheText.Get(\"FEC_CWL\"));\n\t\t\tCFont::SetRightJustifyWrap(0);\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L1_X)), MENU_Y(Y(TEXT_L1_Y)), TheText.Get(\"FEC_LOF\"));\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_DPAD_X)), MENU_Y(Y(TEXT_DPAD_Y)), TheText.Get(\"FEC_CAM\"));\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_LSTICK_X)), MENU_Y(Y(TEXT_LSTICK_Y)), TheText.Get(\"FEC_MOV\"));\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_LSTICK_X)), MENU_Y(Y(TEXT_R3_Y)), TheText.Get(\"FEC_CR3\"));\n\t\t\tswitch (m_PrefsLanguage)\n\t\t\t{\n\t\t\tcase LANGUAGE_GERMAN:\n\t\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_SELECT_X)), MENU_Y(Y(TEXT_SELECT_Y)), TheText.Get(\"FEC_NA\"));\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_SELECT_X - 50)), MENU_Y(Y(TEXT_SELECT_Y)), TheText.Get(\"FEC_NA\"));\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tCFont::SetJustifyOn();\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_START_X)), MENU_Y(Y(TEXT_START_Y)), TheText.Get(\"FEC_PAU\"));\n\t\t\tswitch (m_PrefsLanguage)\n\t\t\t{\n\t\t\tcase LANGUAGE_FRENCH:\n\t\t\tcase LANGUAGE_SPANISH:\n\t\t\t\tTEXT_R2_X += 30.0f;\n\t\t\t\tCFont::SetJustifyOff();\n\t\t\t\tCFont::SetWrapx(MENU_X_LEFT_ALIGNED(X(TEXT_R2_X)) + SCREEN_SCALE_X(120));\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R2_X)), MENU_Y(Y(TEXT_R2_Y)), TheText.Get(\"FEC_CWR\"));\n\t\t\tCFont::SetJustifyOn();\n\t\t\tCFont::SetWrapx(SCREEN_WIDTH);\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R1_X)), MENU_Y(Y(TEXT_R1_Y)), TheText.Get(\"FEC_TAR\"));\n\t\t\tCFont::SetRightJustifyOn();\n\t\t\tCFont::PrintStringFromBottom(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)), MENU_Y(Y(TEXT_SQUARE_Y)), TheText.Get(\"FEC_JUM\"));\n\t\t\tCFont::SetJustifyOn();\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_TRIANGLE_X)), MENU_Y(Y(TEXT_TRIANGLE_Y)), TheText.Get(\"FEC_ENV\"));\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CIRCLE_X)), MENU_Y(Y(TEXT_CIRCLE_Y)), TheText.Get(\"FEC_ATT\"));\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CROSS_X)), MENU_Y(Y(TEXT_CROSS_Y)), TheText.Get(\"FEC_RUN\"));\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_RSTICK_X)), MENU_Y(Y(TEXT_RSTICK_Y)), TheText.Get(\"FEC_FPC\"));\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R3_X)), MENU_Y(Y(TEXT_R3_Y)), TheText.Get(\"FEC_LB3\"));\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R3_X)), MENU_Y(Y(TEXT_R3_Y + 13.0f)), TheText.Get(\"FEC_R3\"));\n\t\t\tbreak;\n\t\tcase 2:\n\t\t\tCFont::SetRightJustifyOn();\n\t\t\tswitch (m_PrefsLanguage)\n\t\t\t{\n\t\t\tcase LANGUAGE_FRENCH:\n\t\t\tcase LANGUAGE_SPANISH:\n\t\t\t\tTEXT_L2_X -= 45.0f;\n\t\t\t\tCFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(X(TEXT_L1_X)) - SCREEN_SCALE_X(85));\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tCFont::SetRightJustifyWrap(0);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L2_X)), MENU_Y(Y(TEXT_L2_Y)), TheText.Get(\"FEC_CWL\"));\n\t\t\tCFont::SetRightJustifyWrap(0);\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L1_X)), MENU_Y(Y(TEXT_L1_Y)), TheText.Get(\"FEC_ENV\"));\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_DPAD_X)), MENU_Y(Y(TEXT_DPAD_Y)), TheText.Get(\"FEC_MOV\"));\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_LSTICK_X)), MENU_Y(Y(TEXT_LSTICK_Y)), TheText.Get(\"FEC_MOV\"));\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_LSTICK_X)), MENU_Y(Y(TEXT_R3_Y)), TheText.Get(\"FEC_CR3\"));\n\t\t\tCFont::SetRightJustifyOn();\n\t\t\tswitch (m_PrefsLanguage)\n\t\t\t{\n\t\t\tcase LANGUAGE_GERMAN:\n\t\t\t\tTEXT_SELECT_X += 20.0f;\n\t\t\t\tbreak;\n\t\t\tcase LANGUAGE_SPANISH:\n\t\t\t\tTEXT_SELECT_X += 15.0f;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_SELECT_X)), MENU_Y(Y(TEXT_SELECT_Y)), TheText.Get(\"FEC_CAM\"));\n\t\t\tCFont::SetJustifyOn();\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_START_X)), MENU_Y(Y(TEXT_START_Y)), TheText.Get(\"FEC_PAU\"));\n\t\t\tswitch (m_PrefsLanguage)\n\t\t\t{\n\t\t\tcase LANGUAGE_FRENCH:\n\t\t\tcase LANGUAGE_SPANISH:\n\t\t\t\tTEXT_R2_X += 30.0f;\n\t\t\t\tCFont::SetJustifyOff();\n\t\t\t\tCFont::SetWrapx(MENU_X_LEFT_ALIGNED(X(TEXT_R2_X)) + SCREEN_SCALE_X(120));\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R2_X)), MENU_Y(Y(TEXT_R2_Y)), TheText.Get(\"FEC_CWR\"));\n\t\t\tCFont::SetJustifyOn();\n\t\t\tCFont::SetWrapx(SCREEN_WIDTH);\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R1_X)), MENU_Y(Y(TEXT_R1_Y)), TheText.Get(\"FEC_TAR\"));\n\t\t\tCFont::SetRightJustifyOn();\n\t\t\tCFont::PrintStringFromBottom(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)), MENU_Y(Y(TEXT_SQUARE_Y)), TheText.Get(\"FEC_JUM\"));\n\t\t\tCFont::SetJustifyOn();\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_TRIANGLE_X)), MENU_Y(Y(TEXT_TRIANGLE_Y)), TheText.Get(\"FEC_LOF\"));\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CIRCLE_X)), MENU_Y(Y(TEXT_CIRCLE_Y)), TheText.Get(\"FEC_RUN\"));\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CROSS_X)), MENU_Y(Y(TEXT_CROSS_Y)), TheText.Get(\"FEC_ATT\"));\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_RSTICK_X)), MENU_Y(Y(TEXT_RSTICK_Y)), TheText.Get(\"FEC_FPC\"));\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R3_X)), MENU_Y(Y(TEXT_R3_Y)), TheText.Get(\"FEC_LB3\"));\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R3_X)), MENU_Y(Y(TEXT_R3_Y + 13.0f)), TheText.Get(\"FEC_R3\"));\n\t\t\tbreak;\n\t\tcase 3:\n\t\t\tCFont::SetRightJustifyOn();\n\t\t\tswitch (m_PrefsLanguage)\n\t\t\t{\n\t\t\tcase LANGUAGE_FRENCH:\n\t\t\tcase LANGUAGE_SPANISH:\n\t\t\t\tTEXT_L2_X -= 45.0f;\n\t\t\t\tCFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(X(TEXT_L1_X)) - SCREEN_SCALE_X(85));\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tCFont::SetRightJustifyWrap(0);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L2_X)), MENU_Y(Y(TEXT_L2_Y)), TheText.Get(\"FEC_CWL\"));\n\t\t\tCFont::SetRightJustifyWrap(0);\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L1_X)), MENU_Y(Y(TEXT_L1_Y)), TheText.Get(\"FEC_TAR\"));\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_DPAD_X)), MENU_Y(Y(TEXT_DPAD_Y)), TheText.Get(\"FEC_NA\"));\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_LSTICK_X)), MENU_Y(Y(TEXT_LSTICK_Y)), TheText.Get(\"FEC_MOV\"));\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_LSTICK_X)), MENU_Y(Y(TEXT_R3_Y)), TheText.Get(\"FEC_CR3\"));\n\t\t\tCFont::SetRightJustifyOn();\n\t\t\tswitch (m_PrefsLanguage)\n\t\t\t{\n\t\t\tcase LANGUAGE_GERMAN:\n\t\t\t\tTEXT_SELECT_X += 20.0f;\n\t\t\t\tbreak;\n\t\t\tcase LANGUAGE_SPANISH:\n\t\t\t\tTEXT_SELECT_X += 15.0f;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_SELECT_X)), MENU_Y(Y(TEXT_SELECT_Y)), TheText.Get(\"FEC_CAM\"));\n\t\t\tCFont::SetJustifyOn();\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_START_X)), MENU_Y(Y(TEXT_START_Y)), TheText.Get(\"FEC_PAU\"));\n\t\t\tswitch (m_PrefsLanguage)\n\t\t\t{\n\t\t\tcase LANGUAGE_FRENCH:\n\t\t\tcase LANGUAGE_SPANISH:\n\t\t\t\tTEXT_R2_X += 30.0f;\n\t\t\t\tCFont::SetJustifyOff();\n\t\t\t\tCFont::SetWrapx(MENU_X_LEFT_ALIGNED(X(TEXT_R2_X)) + SCREEN_SCALE_X(120));\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R2_X)), MENU_Y(Y(TEXT_R2_Y)), TheText.Get(\"FEC_CWR\"));\n\t\t\tCFont::SetJustifyOn();\n\t\t\tCFont::SetWrapx(SCREEN_WIDTH);\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R1_X)), MENU_Y(Y(TEXT_R1_Y)), TheText.Get(\"FEC_ATT\"));\n\t\t\tCFont::SetRightJustifyOn();\n\t\t\tCFont::PrintStringFromBottom(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)), MENU_Y(Y(TEXT_SQUARE_Y)), TheText.Get(\"FEC_JUM\"));\n\t\t\tCFont::SetJustifyOn();\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_TRIANGLE_X)), MENU_Y(Y(TEXT_TRIANGLE_Y)), TheText.Get(\"FEC_ENV\"));\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CIRCLE_X)), MENU_Y(Y(TEXT_CIRCLE_Y)), TheText.Get(\"FEC_LOF\"));\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CROSS_X)), MENU_Y(Y(TEXT_CROSS_Y)), TheText.Get(\"FEC_RUN\"));\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_RSTICK_X)), MENU_Y(Y(TEXT_RSTICK_Y)), TheText.Get(\"FEC_FPC\"));\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R3_X)), MENU_Y(Y(TEXT_R3_Y)), TheText.Get(\"FEC_LB3\"));\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R3_X)), MENU_Y(Y(TEXT_R3_Y + 13.0f)), TheText.Get(\"FEC_R3\"));\n\t\t\tbreak;\n\t\tdefault:\n\t\t\treturn;\n\t\t}\n\t}\n\telse {\n\t\tCFont::SetCentreOn();\n\t\tswitch (m_PrefsLanguage)\n\t\t{\n\t\tcase LANGUAGE_ITALIAN:\n\t\t\tif (m_PrefsControllerType != CONTROLLER_XBOX360)\n\t\t\t\tbreak;\n\t\tcase LANGUAGE_FRENCH:\n\t\tcase LANGUAGE_GERMAN:\n\t\t\tCFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE * 2 * scale * 0.65f), MENU_Y(SMALLESTTEXT_Y_SCALE * scale * 0.65f));\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(0.0f)), MENU_Y(Y(TEXT_L2R2_Y)), TheText.Get(\"FEC_LB\"));\n\t\tCFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE * 2 * scale * 0.9f), MENU_Y(SMALLESTTEXT_Y_SCALE* scale * 0.9f));\n\t\tswitch (CPad::GetPad(0)->Mode) {\n\t\tcase 0:\n\t\t\tCFont::SetRightJustifyOn();\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L2_X)), MENU_Y(Y(TEXT_L2_Y)), TheText.Get(\"FEC_LL\"));\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L1_X)), MENU_Y(Y(TEXT_L1_Y_VEH)), TheText.Get(\"FEC_RSC\"));\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_DPAD_X)), MENU_Y(Y(TEXT_DPAD_Y)), TheText.Get(\"FEC_VES\"));\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_LSTICK_X)), MENU_Y(Y(TEXT_LSTICK_Y)), TheText.Get(\"FEC_VES\"));\n\t\t\tCFont::SetRightJustifyOn();\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L3_X)), MENU_Y(Y(TEXT_L3_Y)), TheText.Get(\"FEC_HO3\"));\n\t\t\tswitch (m_PrefsLanguage)\n\t\t\t{\n\t\t\tcase LANGUAGE_FRENCH:\n\t\t\t\tTEXT_SELECT_X -= 5.0f;\n\t\t\t\tbreak;\n\t\t\tcase LANGUAGE_GERMAN:\n\t\t\t\tTEXT_SELECT_X += 20.0f;\n\t\t\t\tbreak;\n\t\t\tcase LANGUAGE_SPANISH:\n\t\t\t\tTEXT_SELECT_X += 15.0f;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tCFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(X(TEXT_SELECT_X)) - SCREEN_SCALE_X(80));\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_SELECT_X)), MENU_Y(Y(TEXT_SELECT_Y)), TheText.Get(\"FEC_CAM\"));\n\t\t\tCFont::SetJustifyOn();\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_START_X)), MENU_Y(Y(TEXT_START_Y)), TheText.Get(\"FEC_PAU\"));\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R2_X)), MENU_Y(Y(TEXT_R2_Y)), TheText.Get(\"FEC_LR\"));\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R1_X)), MENU_Y(Y(TEXT_R1_Y)), TheText.Get(\"FEC_HAB\"));\n\t\t\tCFont::SetJustifyOn();\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_TRIANGLE_X)), MENU_Y(Y(TEXT_TRIANGLE_Y)), TheText.Get(\"FEC_EXV\"));\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CIRCLE_X)), MENU_Y(Y(TEXT_CIRCLE_Y)), TheText.Get(\"FEC_CAW\"));\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CROSS_X)), MENU_Y(Y(TEXT_CROSS_Y)), TheText.Get(\"FEC_ACC\"));\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_RSTICK_X)), MENU_Y(Y(TEXT_RSTICK_Y)), TheText.Get(\"FEC_TUC\"));\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R3_X)), MENU_Y(Y(TEXT_R3_Y)), TheText.Get(\"FEC_SM3\"));\n\t\t\tCFont::SetRightJustifyOn();\n\t\t\tswitch (m_PrefsControllerType)\n\t\t\t{\n\t\t\tcase CONTROLLER_XBOXONE:\n\t\t\tcase CONTROLLER_XBOX360:\n\t\t\t\tCFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE * 2 * scale * 0.65f), MENU_Y(SMALLESTTEXT_Y_SCALE * scale * 0.65f));\n\t\t\t\tswitch (m_PrefsLanguage)\n\t\t\t\t{\n\t\t\t\tcase LANGUAGE_FRENCH:\n\t\t\t\t\tTEXT_SQUARE_X += 3.0f;\n\t\t\t\t\tCFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)) - SCREEN_SCALE_X(90));\n\t\t\t\t\tbreak;\n\t\t\t\tcase LANGUAGE_GERMAN:\n\t\t\t\tcase LANGUAGE_SPANISH:\n\t\t\t\t\tTEXT_SQUARE_X += 18.0f;\n\t\t\t\t\tCFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)) - SCREEN_SCALE_X(90));\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tCFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)) - SCREEN_SCALE_X(60));\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tswitch (m_PrefsLanguage)\n\t\t\t\t{\n\t\t\t\tcase LANGUAGE_FRENCH:\n\t\t\t\t\tTEXT_SQUARE_X -= 15.0f;\n\t\t\t\t\tTEXT_SQUARE_Y += 5.0f;\n\t\t\t\t\tCFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE * 2 * scale * 0.65f), MENU_Y(SMALLESTTEXT_Y_SCALE * scale * 0.65f));\n\t\t\t\t\tCFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)) - SCREEN_SCALE_X(60));\n\t\t\t\t\tbreak;\n\t\t\t\tcase LANGUAGE_GERMAN:\n\t\t\t\t\tTEXT_SQUARE_X -= 15.0f;\n\t\t\t\t\tTEXT_SQUARE_Y += 10.0f;\n\t\t\t\t\tCFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE * 2 * scale * 0.65f), MENU_Y(SMALLESTTEXT_Y_SCALE* scale * 0.65f));\n\t\t\t\t\tCFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)) - SCREEN_SCALE_X(60));\n\t\t\t\t\tbreak;\n\t\t\t\tcase LANGUAGE_SPANISH:\n\t\t\t\t\tTEXT_SQUARE_X += 15.0f;\n\t\t\t\tcase LANGUAGE_ITALIAN:\n\t\t\t\t\tCFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE * 2 * scale * 0.65f), MENU_Y(SMALLESTTEXT_Y_SCALE * scale * 0.65f));\n\t\t\t\tdefault:\n\t\t\t\t\tCFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)) - SCREEN_SCALE_X(100));\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tCFont::PrintStringFromBottom(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)), MENU_Y(Y(TEXT_SQUARE_Y)), TheText.Get(\"FEC_BRA\"));\n\t\t\tbreak;\n\t\tcase 1:\n\t\t\tCFont::SetRightJustifyOn();\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L2_X)), MENU_Y(Y(TEXT_L2_Y)), TheText.Get(\"FEC_LL\"));\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L1_X)), MENU_Y(Y(TEXT_L1_Y_VEH)), TheText.Get(\"FEC_HOR\"));\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_DPAD_X)), MENU_Y(Y(TEXT_DPAD_Y)), TheText.Get(\"FEC_CAM\"));\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_LSTICK_X)), MENU_Y(Y(TEXT_LSTICK_Y)), TheText.Get(\"FEC_VES\"));\n\t\t\tCFont::SetRightJustifyOn();\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L3_X)), MENU_Y(Y(TEXT_L3_Y)), TheText.Get(\"FEC_NA\"));\n\t\t\tswitch (m_PrefsLanguage)\n\t\t\t{\n\t\t\tcase LANGUAGE_GERMAN:\n\t\t\t\tTEXT_SELECT_X += 20.0f;\n\t\t\t\tbreak;\n\t\t\tcase LANGUAGE_SPANISH:\n\t\t\t\tTEXT_SELECT_X += 12.0f;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tCFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(X(TEXT_SELECT_X)) - SCREEN_SCALE_X(80));\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_SELECT_X)), MENU_Y(Y(TEXT_SELECT_Y)), TheText.Get(\"FEC_RSC\"));\n\t\t\tCFont::SetJustifyOn();\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_START_X)), MENU_Y(Y(TEXT_START_Y)), TheText.Get(\"FEC_PAU\"));\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R2_X)), MENU_Y(Y(TEXT_R2_Y)), TheText.Get(\"FEC_LR\"));\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R1_X)), MENU_Y(Y(TEXT_R1_Y)), TheText.Get(\"FEC_HAB\"));\n\t\t\tCFont::SetJustifyOn();\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_TRIANGLE_X)), MENU_Y(Y(TEXT_TRIANGLE_Y)), TheText.Get(\"FEC_EXV\"));\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CIRCLE_X)), MENU_Y(Y(TEXT_CIRCLE_Y)), TheText.Get(\"FEC_CAW\"));\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CROSS_X)), MENU_Y(Y(TEXT_CROSS_Y)), TheText.Get(\"FEC_ACC\"));\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_RSTICK_X)), MENU_Y(Y(TEXT_RSTICK_Y)), TheText.Get(\"FEC_TUC\"));\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R3_X)), MENU_Y(Y(TEXT_R3_Y)), TheText.Get(\"FEC_SM3\"));\n\t\t\tCFont::SetRightJustifyOn();\n\t\t\tswitch (m_PrefsControllerType)\n\t\t\t{\n\t\t\tcase CONTROLLER_XBOXONE:\n\t\t\tcase CONTROLLER_XBOX360:\n\t\t\t\tCFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE * 2 * scale * 0.65f), MENU_Y(SMALLESTTEXT_Y_SCALE * scale * 0.65f));\n\t\t\t\tswitch (m_PrefsLanguage)\n\t\t\t\t{\n\t\t\t\tcase LANGUAGE_FRENCH:\n\t\t\t\t\tTEXT_SQUARE_X += 3.0f;\n\t\t\t\t\tCFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)) - SCREEN_SCALE_X(90));\n\t\t\t\t\tbreak;\n\t\t\t\tcase LANGUAGE_GERMAN:\n\t\t\t\tcase LANGUAGE_SPANISH:\n\t\t\t\t\tTEXT_SQUARE_X += 18.0f;\n\t\t\t\t\tCFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)) - SCREEN_SCALE_X(90));\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tCFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)) - SCREEN_SCALE_X(60));\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tswitch (m_PrefsLanguage)\n\t\t\t\t{\n\t\t\t\tcase LANGUAGE_FRENCH:\n\t\t\t\t\tTEXT_SQUARE_X -= 15.0f;\n\t\t\t\t\tTEXT_SQUARE_Y += 5.0f;\n\t\t\t\t\tCFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE * 2 * scale * 0.65f), MENU_Y(SMALLESTTEXT_Y_SCALE * scale * 0.65f));\n\t\t\t\t\tCFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)) - SCREEN_SCALE_X(60));\n\t\t\t\t\tbreak;\n\t\t\t\tcase LANGUAGE_GERMAN:\n\t\t\t\t\tTEXT_SQUARE_X -= 15.0f;\n\t\t\t\t\tTEXT_SQUARE_Y += 10.0f;\n\t\t\t\t\tCFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE * 2 * scale * 0.65f), MENU_Y(SMALLESTTEXT_Y_SCALE * scale * 0.65f));\n\t\t\t\t\tCFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)) - SCREEN_SCALE_X(60));\n\t\t\t\t\tbreak;\n\t\t\t\tcase LANGUAGE_SPANISH:\n\t\t\t\t\tTEXT_SQUARE_X += 15.0f;\n\t\t\t\tcase LANGUAGE_ITALIAN:\n\t\t\t\t\tCFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE * 2 * scale * 0.65f), MENU_Y(SMALLESTTEXT_Y_SCALE * scale * 0.65f));\n\t\t\t\tdefault:\n\t\t\t\t\tCFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)) - SCREEN_SCALE_X(100));\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tCFont::PrintStringFromBottom(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)), MENU_Y(Y(TEXT_SQUARE_Y)), TheText.Get(\"FEC_BRA\"));\n\t\t\tbreak;\n\t\tcase 2:\n\t\t\tCFont::SetRightJustifyOn();\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L2_X)), MENU_Y(Y(TEXT_L2_Y)), TheText.Get(\"FEC_LL\"));\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L1_X)), MENU_Y(Y(TEXT_L1_Y_VEH)), TheText.Get(\"FEC_EXV\"));\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_DPAD_X)), MENU_Y(Y(TEXT_DPAD_Y)), TheText.Get(\"FEC_VES\"));\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_LSTICK_X)), MENU_Y(Y(TEXT_LSTICK_Y)), TheText.Get(\"FEC_VES\"));\n\t\t\tCFont::SetRightJustifyOn();\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L3_X)), MENU_Y(Y(TEXT_L3_Y)), TheText.Get(\"FEC_RS3\"));\n\t\t\tswitch (m_PrefsLanguage)\n\t\t\t{\n\t\t\tcase LANGUAGE_FRENCH:\n\t\t\t\tTEXT_SELECT_X -= 5.0f;\n\t\t\t\tbreak;\n\t\t\tcase LANGUAGE_GERMAN:\n\t\t\t\tTEXT_SELECT_X += 20.0f;\n\t\t\t\tbreak;\n\t\t\tcase LANGUAGE_SPANISH:\n\t\t\t\tTEXT_SELECT_X += 15.0f;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tCFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(X(TEXT_SELECT_X)) - SCREEN_SCALE_X(80));\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_SELECT_X)), MENU_Y(Y(TEXT_SELECT_Y)), TheText.Get(\"FEC_CAM\"));\n\t\t\tCFont::SetJustifyOn();\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_START_X)), MENU_Y(Y(TEXT_START_Y)), TheText.Get(\"FEC_PAU\"));\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R2_X)), MENU_Y(Y(TEXT_R2_Y)), TheText.Get(\"FEC_LR\"));\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R1_X)), MENU_Y(Y(TEXT_R1_Y)), TheText.Get(\"FEC_HOR\"));\n\t\t\tCFont::SetJustifyOn();\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_TRIANGLE_X)), MENU_Y(Y(TEXT_TRIANGLE_Y)), TheText.Get(\"FEC_HAB\"));\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CIRCLE_X)), MENU_Y(Y(TEXT_CIRCLE_Y)), TheText.Get(\"FEC_CAW\"));\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CROSS_X)), MENU_Y(Y(TEXT_CROSS_Y)), TheText.Get(\"FEC_ACC\"));\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_RSTICK_X)), MENU_Y(Y(TEXT_RSTICK_Y)), TheText.Get(\"FEC_TUC\"));\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R3_X)), MENU_Y(Y(TEXT_R3_Y)), TheText.Get(\"FEC_SM3\"));\n\t\t\tCFont::SetRightJustifyOn();\n\t\t\tswitch (m_PrefsControllerType)\n\t\t\t{\n\t\t\tcase CONTROLLER_XBOXONE:\n\t\t\tcase CONTROLLER_XBOX360:\n\t\t\t\tCFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE * 2 * scale * 0.65f), MENU_Y(SMALLESTTEXT_Y_SCALE * scale * 0.65f));\n\t\t\t\tswitch (m_PrefsLanguage)\n\t\t\t\t{\n\t\t\t\tcase LANGUAGE_FRENCH:\n\t\t\t\t\tTEXT_SQUARE_X += 3.0f;\n\t\t\t\t\tCFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)) - SCREEN_SCALE_X(90));\n\t\t\t\t\tbreak;\n\t\t\t\tcase LANGUAGE_GERMAN:\n\t\t\t\tcase LANGUAGE_SPANISH:\n\t\t\t\t\tTEXT_SQUARE_X += 18.0f;\n\t\t\t\t\tCFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)) - SCREEN_SCALE_X(90));\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tCFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)) - SCREEN_SCALE_X(60));\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tswitch (m_PrefsLanguage)\n\t\t\t\t{\n\t\t\t\tcase LANGUAGE_FRENCH:\n\t\t\t\t\tTEXT_SQUARE_X -= 15.0f;\n\t\t\t\t\tTEXT_SQUARE_Y += 5.0f;\n\t\t\t\t\tCFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE * 2 * scale * 0.65f), MENU_Y(SMALLESTTEXT_Y_SCALE * scale * 0.65f));\n\t\t\t\t\tCFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)) - SCREEN_SCALE_X(60));\n\t\t\t\t\tbreak;\n\t\t\t\tcase LANGUAGE_GERMAN:\n\t\t\t\t\tTEXT_SQUARE_X -= 15.0f;\n\t\t\t\t\tTEXT_SQUARE_Y += 10.0f;\n\t\t\t\t\tCFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE * 2 * scale * 0.65f), MENU_Y(SMALLESTTEXT_Y_SCALE * scale * 0.65f));\n\t\t\t\t\tCFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)) - SCREEN_SCALE_X(60));\n\t\t\t\t\tbreak;\n\t\t\t\tcase LANGUAGE_SPANISH:\n\t\t\t\t\tTEXT_SQUARE_X += 15.0f;\n\t\t\t\tcase LANGUAGE_ITALIAN:\n\t\t\t\t\tCFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE * 2 * scale * 0.65f), MENU_Y(SMALLESTTEXT_Y_SCALE * scale * 0.65f));\n\t\t\t\tdefault:\n\t\t\t\t\tCFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)) - SCREEN_SCALE_X(100));\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tCFont::PrintStringFromBottom(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)), MENU_Y(Y(TEXT_SQUARE_Y)), TheText.Get(\"FEC_BRA\"));\n\t\t\tbreak;\n\t\tcase 3:\n\t\t\tCFont::SetRightJustifyOn();\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L2_X)), MENU_Y(Y(TEXT_L2_Y)), TheText.Get(\"FEC_LL\"));\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L1_X)), MENU_Y(Y(TEXT_L1_Y_VEH)), TheText.Get(\"FEC_HAB\"));\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_DPAD_X)), MENU_Y(Y(TEXT_DPAD_Y)), TheText.Get(\"FEC_TUC\"));\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_LSTICK_X)), MENU_Y(Y(TEXT_LSTICK_Y)), TheText.Get(\"FEC_VES\"));\n\t\t\tCFont::SetRightJustifyOn();\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L3_X)), MENU_Y(Y(TEXT_L3_Y)), TheText.Get(\"FEC_HO3\"));\n\t\t\tswitch (m_PrefsLanguage)\n\t\t\t{\n\t\t\tcase LANGUAGE_FRENCH:\n\t\t\t\tTEXT_SELECT_X -= 5.0f;\n\t\t\t\tbreak;\n\t\t\tcase LANGUAGE_GERMAN:\n\t\t\t\tTEXT_SELECT_X += 20.0f;\n\t\t\t\tbreak;\n\t\t\tcase LANGUAGE_SPANISH:\n\t\t\t\tTEXT_SELECT_X += 15.0f;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tCFont::SetRightJustifyWrap(MENU_X_LEFT_ALIGNED(X(TEXT_SELECT_X)) - SCREEN_SCALE_X(80));\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_SELECT_X)), MENU_Y(Y(TEXT_SELECT_Y)), TheText.Get(\"FEC_CAM\"));\n\t\t\tCFont::SetJustifyOn();\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_START_X)), MENU_Y(Y(TEXT_START_Y)), TheText.Get(\"FEC_PAU\"));\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R2_X)), MENU_Y(Y(TEXT_R2_Y)), TheText.Get(\"FEC_LR\"));\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R1_X)), MENU_Y(Y(TEXT_R1_Y)), TheText.Get(\"FEC_CAW\"));\n\t\t\tCFont::SetJustifyOn();\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_TRIANGLE_X)), MENU_Y(Y(TEXT_TRIANGLE_Y)), TheText.Get(\"FEC_EXV\"));\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CIRCLE_X)), MENU_Y(Y(TEXT_CIRCLE_Y)), TheText.Get(\"FEC_RSC\"));\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CROSS_X)), MENU_Y(Y(TEXT_CROSS_Y)), TheText.Get(\"FEC_NA\"));\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_RSTICK_X)), MENU_Y(Y(TEXT_RSTICK_Y)), TheText.Get(\"FEC_ACC\"));\n\t\t\tCFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R3_X)), MENU_Y(Y(TEXT_R3_Y)), TheText.Get(\"FEC_BRA\"));\n\t\t\tCFont::SetRightJustifyOn();\n\t\t\tCFont::SetRightJustifyWrap(0);\n\t\t\tswitch (m_PrefsControllerType)\n\t\t\t{\n\t\t\tcase CONTROLLER_XBOXONE:\n\t\t\tcase CONTROLLER_XBOX360:\n\t\t\t\tCFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE * 2 * scale * 0.65f), MENU_Y(SMALLESTTEXT_Y_SCALE * scale * 0.65f));\n\t\t\t\tCFont::PrintStringFromBottom(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)), MENU_Y(Y(TEXT_SQUARE_Y)), TheText.Get(\"FEC_SMT\"));\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tswitch (m_PrefsLanguage)\n\t\t\t\t{\n\t\t\t\tcase LANGUAGE_GERMAN:\n\t\t\t\t\tTEXT_SQUARE_X += 5.0f;\n\t\t\t\tcase LANGUAGE_FRENCH:\n\t\t\t\tcase LANGUAGE_ITALIAN:\n\t\t\t\t\tCFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE * 2 * scale * 0.65f), MENU_Y(SMALLESTTEXT_Y_SCALE * scale * 0.65f));\n\t\t\t\t\tCFont::PrintStringFromBottom(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)), MENU_Y(Y(TEXT_SQUARE_Y)), TheText.Get(\"FEC_SMT\"));\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tCFont::PrintStringFromBottom(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X + 16.0f)), MENU_Y(Y(TEXT_SQUARE_Y)), TheText.Get(\"FEC_SMT\"));\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tbreak;\n\t\tdefault:\n\t\t\treturn;\n\t\t}\n\t}\n\n\tCFont::SetDropShadowPosition(0); // X\n\n#undef X\n#undef Y\n}\n\n\nvoid\nCMenuManager::LoadController(int8 type)\n{\n\tswitch (type)\n\t{\n\tcase CONTROLLER_DUALSHOCK2:\n\tcase CONTROLLER_DUALSHOCK3:\n\tcase CONTROLLER_DUALSHOCK4:\n\t\tCFont::LoadButtons(\"MODELS/PS3BTNS.TXD\");\n\t\tbreak;\n\tdefault:\n\t\tCFont::LoadButtons(\"MODELS/X360BTNS.TXD\");\n\t\tbreak;\n\t}\n\n\t// Unload current textures\n\tfor (int i = MENUSPRITE_CONTROLLER; i <= MENUSPRITE_ARROWS4; i++)\n\t\tm_aFrontEndSprites[i].Delete();\n\n\t// Unload txd\n\tint frontend_controller = CTxdStore::FindTxdSlot(\"frontend_controller\");\n\tif (frontend_controller != -1)\n\t\tCTxdStore::RemoveTxd(frontend_controller);\n\n\t// Find the new txd to load\n\tbool bTxdMissing = true;\n\tif (controllerTypesPaths[type])\n\t\tif (int file = CFileMgr::OpenFile(controllerTypesPaths[type])) {\n\t\t\tCFileMgr::CloseFile(file);\n\t\t\tbTxdMissing = false;\n\t\t}\n\n\tint txdSlot = -1;\n\n\tif (bTxdMissing)\n\t\t// Not found, fall back to original textures\n\t\ttxdSlot = CTxdStore::FindTxdSlot(\"frontend2\");\n\telse {\n\t\t// Found, load txd\n\t\ttxdSlot = frontend_controller;\n\t\tif (txdSlot == -1)\n\t\t\ttxdSlot = CTxdStore::AddTxdSlot(\"frontend_controller\");\n\t\tCTxdStore::LoadTxd(txdSlot, controllerTypesPaths[type]);\n\t\tCTxdStore::AddRef(txdSlot);\n\t}\n\n\tassert(txdSlot != -1);\n\t// Load new textures\n\tCTxdStore::SetCurrentTxd(txdSlot);\n\tfor (int i = MENUSPRITE_CONTROLLER; i <= MENUSPRITE_ARROWS4; i++) {\n\t\tm_aFrontEndSprites[i].SetTexture(FrontendFilenames[i][0], FrontendFilenames[i][1]);\n\t\tm_aFrontEndSprites[i].SetAddressing(rwTEXTUREADDRESSBORDER);\n\t}\n}\n#endif // GAMEPAD_MENU\n\n#undef GetBackJustUp\n#undef GetBackJustDown\n"
  },
  {
    "path": "src/core/Frontend.h",
    "content": "#pragma once\n#ifdef PS2_MENU\n#include \"Frontend_PS2.h\"\n#else\n\n#include \"Sprite2d.h\"\n#include \"Timer.h\"\n\n#define MENUHEADER_POS_X 10.0f\n#define MENUHEADER_POS_Y 10.0f\n#define MENUHEADER_HEIGHT 2.0f\n#define MENUHEADER_WIDTH 1.0f\n\n#define MENU_X_MARGIN 10.0f\n\n#define MENUACTION_SCALE_MULT 0.9f\n\n#define MENULABEL_X_MARGIN 80.0f\n#define MENULABEL_POS_X 100.0f\n#define MENULABEL_POS_Y 97.0f\n\n#define MENU_DEFAULT_CONTENT_X 320\n#define MENU_DEFAULT_CONTENT_Y 100\n#define MENU_DEFAULT_LINE_HEIGHT 29\n\n#define RIGHT_ALIGNED_TEXT_RIGHT_MARGIN(xMargin) (xMargin + 30.0f)\n\n#define MENURADIO_ICON_FIRST_X 238.f\n#define MENURADIO_ICON_Y 288.0f\n#define MENURADIO_ICON_SIZE 60.0f\n#define MENURADIO_SELECTOR_START_Y 285.f // other options should leave room on the screen\n#define MENURADIO_SELECTOR_HEIGHT 65.f\n\n#define MENUSLIDER_X 500.0f\n#define MENUSLIDER_UNK 100.0f\n#define MENUSLIDER_SMALLEST_BAR 8.0f\n#define MENUSLIDER_BIGGEST_BAR 25.0f\n\n#define BIGTEXT2_X_SCALE 0.6f // For FONT_STANDARD\n#define BIGTEXT2_Y_SCALE 1.2f\n#define BIGTEXT_X_SCALE 0.6f // For FONT_HEADING\n#define BIGTEXT_Y_SCALE 1.0f\n#define MEDIUMTEXT_X_SCALE 0.48f // For FONT_STANDARD\n#define MEDIUMTEXT_Y_SCALE 1.0f\n#define SMALLTEXT_X_SCALE 0.42f // For FONT_STANDARD\n#define SMALLTEXT_Y_SCALE 0.9f\n#define SMALLESTTEXT_X_SCALE 0.3f // For FONT_STANDARD\n#define SMALLESTTEXT_Y_SCALE 0.7f\n\n#define LISTITEM_X_SCALE 0.4f // Only unproportional and commonly used scale for FONT_STANDARD\n#define LISTITEM_Y_SCALE 0.6f\n\n#define HELPER_TEXT_RIGHT_MARGIN MENU_X_MARGIN\n#define HELPER_TEXT_BOTTOM_MARGIN 18.f\n\n#define PLAYERSETUP_LIST_TOP 58.0f\n#define PLAYERSETUP_LIST_BOTTOM 95.0f\n#define PLAYERSETUP_LIST_LEFT 200.0f\n#define PLAYERSETUP_LIST_RIGHT 36.0f\n#ifdef FIX_BUGS // See the scrollbar button drawing code\n#define PLAYERSETUP_SCROLLBAR_WIDTH 19.0f\n#else\n#define PLAYERSETUP_SCROLLBAR_WIDTH 16.0f\n#endif\n#define PLAYERSETUP_SCROLLBUTTON_HEIGHT 17.0f\n#define PLAYERSETUP_SCROLLBUTTON_TXD_DIMENSION 64\n#define PLAYERSETUP_SKIN_COLUMN_LEFT 220.0f\n#define PLAYERSETUP_DATE_COLUMN_RIGHT 56.0f\n#define PLAYERSETUP_LIST_BODY_TOP 77\n#define PLAYERSETUP_ROW_HEIGHT 9\n\n#define STATS_ROW_HEIGHT 17.0f\n#define STATS_ROW_LEFT_MARGIN 110.0f\n#define STATS_ROW_RIGHT_MARGIN 113.0f\n#define STATS_TOP_Y 135.0f // Just faded in\n#define STATS_BOTTOM_Y 300.0f // Starts to fade out after that\n#define STATS_FADING_AREA_LENGTH 50.0f\n#define STATS_VISIBLE_START_Y (STATS_TOP_Y - 10.f)\n#define STATS_VISIBLE_END_Y (STATS_BOTTOM_Y + 21.f)\n#define STATS_RATING_X 320.0f\n#define STATS_RATING_Y_1 85.0f\n#define STATS_RATING_Y_2 110.0f\n\n#define BRIEFS_TOP_MARGIN 140.0f\n#define BRIEFS_BOTTOM_MARGIN 280.0f\n#define BRIEFS_LINE_X 100.0f\n#define BRIEFS_LINE_HEIGHT 20.0f\n#define BRIEFS_LINE_SPACING 10.0f\n\n#define CONTSETUP_STANDARD_ROW_HEIGHT 10.7f\n#define CONTSETUP_CLASSIC_ROW_HEIGHT 9.0f\n#define CONTSETUP_BOUND_HIGHLIGHT_HEIGHT 10\n#define CONTSETUP_BOUND_COLUMN_WIDTH 190.0f\n#define CONTSETUP_LIST_TOP 58.0f\n#define CONTSETUP_LIST_RIGHT 18.0f\n#define CONTSETUP_LIST_BOTTOM 78.0f\n#define CONTSETUP_LIST_LEFT 30.0f\n#define CONTSETUP_COLUMN_1_X 40.0f\n#define CONTSETUP_COLUMN_2_X 210.0f\n#define CONTSETUP_COLUMN_3_X (CONTSETUP_COLUMN_2_X + CONTSETUP_BOUND_COLUMN_WIDTH + 10.0f)\n#define CONTSETUP_BACK_RIGHT 35.0f\n#define CONTSETUP_BACK_BOTTOM 82.0f\n#define CONTSETUP_BACK_HEIGHT 25.0f\n\nenum\n{\n\tMENUALIGN_LEFT = 1,\n\tMENUALIGN_RIGHT,\n\tMENUALIGN_CENTER,\n};\n\nenum eMenuSprites\n{\n\tMENUSPRITE_BACKGROUND,\n\tMENUSPRITE_VCLOGO,\n\tMENUSPRITE_MOUSE,\n\tMENUSPRITE_MAPTOP01,\n\tMENUSPRITE_MAPTOP02,\n\tMENUSPRITE_MAPTOP03,\n\tMENUSPRITE_MAPMID01,\n\tMENUSPRITE_MAPMID02,\n\tMENUSPRITE_MAPMID03,\n\tMENUSPRITE_MAPBOT01,\n\tMENUSPRITE_MAPBOT02,\n\tMENUSPRITE_MAPBOT03,\n\tMENUSPRITE_WILDSTYLE,\n\tMENUSPRITE_FLASH,\n\tMENUSPRITE_KCHAT,\n\tMENUSPRITE_FEVER,\n\tMENUSPRITE_VROCK,\n\tMENUSPRITE_VCPR,\n\tMENUSPRITE_ESPANTOSO,\n\tMENUSPRITE_EMOTION,\n\tMENUSPRITE_WAVE,\n\tMENUSPRITE_MP3,\n\tMENUSPRITE_DOWNOFF,\n\tMENUSPRITE_DOWNON,\n\tMENUSPRITE_UPOFF,\n\tMENUSPRITE_UPON,\n#ifdef GAMEPAD_MENU\n\tMENUSPRITE_CONTROLLER,\n\tMENUSPRITE_ARROWS1,\n\tMENUSPRITE_ARROWS2,\n\tMENUSPRITE_ARROWS3,\n\tMENUSPRITE_ARROWS4,\n#endif\n\tNUM_MENU_SPRITES\n};\n\nenum eSaveSlot\n{\n\tSAVESLOT_NONE,\n\tSAVESLOT_0,\n\tSAVESLOT_1,\n\tSAVESLOT_2,\n\tSAVESLOT_3,\n\tSAVESLOT_4,\n\tSAVESLOT_5,\n\tSAVESLOT_6,\n\tSAVESLOT_7,\n\tSAVESLOT_8,\n\tSAVESLOT_LABEL = 36\n};\n\nenum eMenuScreen\n{\n\tMENUPAGE_DISABLED = -1,\n\tMENUPAGE_STATS = 0,\n\tMENUPAGE_NEW_GAME = 1,\n\tMENUPAGE_BRIEFS = 2,\n\tMENUPAGE_SOUND_SETTINGS = 3,\n\tMENUPAGE_DISPLAY_SETTINGS = 4,\n\tMENUPAGE_LANGUAGE_SETTINGS = 5,\n\tMENUPAGE_MAP = 6,\n\tMENUPAGE_NEW_GAME_RELOAD = 7,\n\tMENUPAGE_CHOOSE_LOAD_SLOT = 8,\n\tMENUPAGE_CHOOSE_DELETE_SLOT = 9,\n\tMENUPAGE_LOAD_SLOT_CONFIRM = 10,\n\tMENUPAGE_DELETE_SLOT_CONFIRM = 11,\n\tMENUPAGE_LOADING_IN_PROGRESS = 12,\n\tMENUPAGE_DELETING_IN_PROGRESS = 13,\n\tMENUPAGE_DELETE_SUCCESSFUL = 14,\n\tMENUPAGE_CHOOSE_SAVE_SLOT = 15,\n\tMENUPAGE_SAVE_OVERWRITE_CONFIRM = 16,\n\tMENUPAGE_SAVING_IN_PROGRESS = 17,\n\tMENUPAGE_SAVE_SUCCESSFUL = 18,\n\tMENUPAGE_SAVE_CUSTOM_WARNING = 19,\n\tMENUPAGE_SAVE_CHEAT_WARNING = 20,\n\tMENUPAGE_SKIN_SELECT = 21,\n\tMENUPAGE_SAVE_UNUSED = 22,\n\tMENUPAGE_SAVE_FAILED = 23,\n\tMENUPAGE_SAVE_FAILED_2 = 24,\n\tMENUPAGE_LOAD_FAILED = 25,\n\tMENUPAGE_CONTROLLER_PC = 26,\n\tMENUPAGE_OPTIONS = 27,\n\tMENUPAGE_EXIT = 28,\n\tMENUPAGE_START_MENU = 29,\n\tMENUPAGE_KEYBOARD_CONTROLS = 30,\n\tMENUPAGE_MOUSE_CONTROLS = 31,\n\tMENUPAGE_PAUSE_MENU = 32,\n\tMENUPAGE_NONE = 33, // Then chooses main menu or pause menu \n#ifdef GAMEPAD_MENU\n\tMENUPAGE_CONTROLLER_SETTINGS,\n#endif\n#ifdef LEGACY_MENU_OPTIONS\n\tMENUPAGE_DEBUG_MENU,\n\tMENUPAGE_CONTROLLER_PC_OLD1,\n\tMENUPAGE_CONTROLLER_PC_OLD2,\n\tMENUPAGE_CONTROLLER_PC_OLD3,\n\tMENUPAGE_CONTROLLER_PC_OLD4,\n\tMENUPAGE_CONTROLLER_DEBUG,\n#endif\n#ifdef CUSTOM_FRONTEND_OPTIONS\n\n#ifdef GRAPHICS_MENU_OPTIONS\n\tMENUPAGE_GRAPHICS_SETTINGS,\n#endif\n#ifdef DETECT_JOYSTICK_MENU\n\tMENUPAGE_DETECT_JOYSTICK,\n#endif\n\n#endif\n\tMENUPAGE_OUTRO, // Originally 34, but CFO needs last screen to be empty to count number of menu pages\n\tMENUPAGES\n};\n\nenum eMenuAction\n{\n#ifdef CUSTOM_FRONTEND_OPTIONS\n\tMENUACTION_CFO_SELECT = -2,\n\tMENUACTION_CFO_DYNAMIC = -1,\n#endif\n\tMENUACTION_NOTHING,\n\tMENUACTION_LABEL,\n\tMENUACTION_YES,\n\tMENUACTION_NO,\n\tMENUACTION_CHANGEMENU,\n\tMENUACTION_INVERTPADY,\n\tMENUACTION_CTRLDISPLAY,\n\tMENUACTION_FRAMESYNC,\n\tMENUACTION_FRAMELIMIT,\n\tMENUACTION_TRAILS,\n\tMENUACTION_SUBTITLES,\n\tMENUACTION_WIDESCREEN,\n\tMENUACTION_BRIGHTNESS,\n\tMENUACTION_MUSICVOLUME,\n\tMENUACTION_SFXVOLUME,\n\tMENUACTION_RADIO,\n\tMENUACTION_LANG_ENG,\n\tMENUACTION_LANG_FRE,\n\tMENUACTION_LANG_GER,\n\tMENUACTION_LANG_ITA,\n\tMENUACTION_LANG_SPA,\n\tMENUACTION_POPULATESLOTS_CHANGEMENU,\n\tMENUACTION_CHECKSAVE,\n\tMENUACTION_NEWGAME,\n\tMENUACTION_RESUME_FROM_SAVEZONE,\n\tMENUACTION_RELOADIDE,\n\tMENUACTION_SETDBGFLAG,\n\tMENUACTION_LOADRADIO,\n\tMENUACTION_SAVEGAME,\n\tMENUACTION_SWITCHBIGWHITEDEBUGLIGHT,\n\tMENUACTION_COLLISIONPOLYS,\n\tMENUACTION_LEGENDS,\n\tMENUACTION_RADARMODE,\n\tMENUACTION_HUD,\n\tMENUACTION_GOBACK,\n\tMENUACTION_KEYBOARDCTRLS,\n\tMENUACTION_GETKEY,\n\tMENUACTION_SHOWHEADBOB,\n\tMENUACTION_UNK38, // MENUACTION_PARSEHEAP? MENUACTION_DEBUGSTREAM? MENUACTION_MEMCARDSAVECONFIRM?\n\tMENUACTION_INVVERT,\n\tMENUACTION_CANCELGAME,\n\tMENUACTION_RESUME,\n\tMENUACTION_DONTCANCEL,\n\tMENUACTION_SCREENRES,\n\tMENUACTION_AUDIOHW,\n\tMENUACTION_SPEAKERCONF,\n\tMENUACTION_PLAYERSETUP,\n\tMENUACTION_RESTOREDEF,\n\tMENUACTION_CTRLMETHOD,\n\tMENUACTION_DYNAMICACOUSTIC,\n\tMENUACTION_MOUSESTEER,\n\tMENUACTION_DRAWDIST,\n\tMENUACTION_MOUSESENS,\n\tMENUACTION_MP3VOLUMEBOOST,\n#ifdef GAMEPAD_MENU\n\tMENUACTION_CTRLVIBRATION,\n\tMENUACTION_CTRLCONFIG,\n#endif\n};\n\nenum eCheckHover\n{\n\tHOVEROPTION_0,\n\tHOVEROPTION_1,\n\tHOVEROPTION_RANDOM_ITEM,\n\tHOVEROPTION_3,\n\tHOVEROPTION_4,\n\tHOVEROPTION_5,\n\tHOVEROPTION_6,\n\tHOVEROPTION_7,\n\tHOVEROPTION_8,\n\tHOVEROPTION_BACK,\t// also layer in controller setup and skin menu\n\tHOVEROPTION_10,\n\tHOVEROPTION_11,\n\tHOVEROPTION_OVER_SCROLL_UP,\n\tHOVEROPTION_OVER_SCROLL_DOWN,\n\tHOVEROPTION_CLICKED_SCROLL_UP,\n\tHOVEROPTION_CLICKED_SCROLL_DOWN,\n\tHOVEROPTION_HOLDING_SCROLLBAR,\n\tHOVEROPTION_PAGEUP,\n\tHOVEROPTION_PAGEDOWN,\n\tHOVEROPTION_LIST, // also layer in controller setup and skin menu\n\tHOVEROPTION_SKIN,\n\tHOVEROPTION_USESKIN, // also layer in controller setup and skin menu\n\tHOVEROPTION_NEXT_RADIO,\n\tHOVEROPTION_PREV_RADIO,\n\tHOVEROPTION_INCREASE_BRIGHTNESS,\n\tHOVEROPTION_DECREASE_BRIGHTNESS,\n\tHOVEROPTION_INCREASE_DRAWDIST,\n\tHOVEROPTION_DECREASE_DRAWDIST,\n\tHOVEROPTION_INCREASE_MUSICVOLUME,\n\tHOVEROPTION_DECREASE_MUSICVOLUME,\n\tHOVEROPTION_INCREASE_SFXVOLUME,\n\tHOVEROPTION_DECREASE_SFXVOLUME,\n\tHOVEROPTION_INCREASE_MOUSESENS,\n\tHOVEROPTION_DECREASE_MOUSESENS,\n\tHOVEROPTION_INCREASE_MP3BOOST,\n\tHOVEROPTION_DECREASE_MP3BOOST,\n\tHOVEROPTION_NOT_HOVERING,\n};\n\nenum\n{\n#if defined LEGACY_MENU_OPTIONS || defined CUSTOM_FRONTEND_OPTIONS\n\tNUM_MENUROWS = 18,\n#else\n\tNUM_MENUROWS = 12,\n#endif\n};\n\nenum eControlMethod\n{\n\tCONTROL_STANDARD = 0,\n\tCONTROL_CLASSIC,\n};\n\n// Why??\nenum ControllerSetupColumn\n{\n\tCONTSETUP_PED_COLUMN = 0,\n\tCONTSETUP_VEHICLE_COLUMN = 16,\n};\n\nstruct tSkinInfo\n{\n\tint32 skinId;\n\tchar skinNameDisplayed[256];\n\tchar skinNameOriginal[256];\n\tchar date[256];\n\ttSkinInfo *nextSkin;\n};\n\nstruct BottomBarOption\n{\n\tchar name[8];\n\tint32 screenId;\n};\n\n#ifndef CUSTOM_FRONTEND_OPTIONS\nstruct CMenuScreen\n{\n\tchar m_ScreenName[8];\n\tint32 m_PreviousPage; // eMenuScreen\n\tint32 m_ParentEntry; // row\n\n\tstruct CMenuEntry\n\t{\n\t\tint32 m_Action; // eMenuAction\n\t\tchar m_EntryName[8];\n\t\tint32 m_SaveSlot; // eSaveSlot\n\t\tint32 m_TargetMenu; // eMenuScreen\n\t\tuint16 m_X;\n\t\tuint16 m_Y;\n\t\tuint8 m_Align;\n\t} m_aEntries[NUM_MENUROWS];\n};\nextern CMenuScreen aScreens[MENUPAGES];\n#else\n#include \"frontendoption.h\"\nstruct CCustomScreenLayout {\n\tint startX; // not used at all if first entry has X and Y values\n\tint startY; // not used at all if first entry has X and Y values\n\tint lineHeight; // used to determine next entry's Y coordinate, if it has 0-0 as coordinates\n\tbool showLeftRightHelper;\n\tbool noInvasiveBorders; // not needed on pages already handled by game\n\tint xMargin; // useful for two part texts - 0/empty = MENU_X_MARGIN\n};\n\nstruct CCFO\n{\n\tint8 *value;\n\tconst char *saveCat;\n\tconst char *save;\n};\n\nstruct CCFOSelect : CCFO\n{\n\tchar** rightTexts;\n\tint8 numRightTexts;\n\tbool onlyApplyOnEnter;\n\tint8 displayedValue; // only if onlyApplyOnEnter enabled for now\n\tint8 lastSavedValue; // only if onlyApplyOnEnter enabled\n\tChangeFunc changeFunc;\n\tbool disableIfGameLoaded;\n\n\tCCFOSelect() {};\n\tCCFOSelect(int8* value, const char* saveCat, const char* save, const char** rightTexts, int8 numRightTexts, bool onlyApplyOnEnter, ChangeFunc changeFunc = nil, bool disableIfGameLoaded = false){\n\t\tthis->value = value;\n\t\tif (value)\n\t\t\tthis->lastSavedValue = this->displayedValue = *value;\n\n\t\tthis->saveCat = saveCat;\n\t\tthis->save = save;\n\t\tthis->rightTexts = (char**)rightTexts;\n\t\tthis->numRightTexts = numRightTexts;\n\t\tthis->onlyApplyOnEnter = onlyApplyOnEnter;\n\t\tthis->changeFunc = changeFunc;\n\t\tthis->disableIfGameLoaded = disableIfGameLoaded;\n\t}\n};\n\nstruct CCFODynamic : CCFO\n{\n\tDrawFunc drawFunc;\n\tButtonPressFunc buttonPressFunc;\n\n\tCCFODynamic() {};\n\tCCFODynamic(int8* value, const char* saveCat, const char* save, DrawFunc drawFunc, ButtonPressFunc buttonPressFunc){\n\t\tthis->value = value;\n\t\tthis->saveCat = saveCat;\n\t\tthis->save = save;\n\t\tthis->drawFunc = drawFunc;\n\t\tthis->buttonPressFunc = buttonPressFunc;\n\t}\n};\n\nstruct CMenuScreenCustom\n{\n\tchar m_ScreenName[8];\n\tint32 m_PreviousPage; // eMenuScreen\n\tCCustomScreenLayout *layout;\n\tReturnPrevPageFunc returnPrevPageFunc;\n\t\n\tstruct CMenuEntry\n\t{\n\t\tint32 m_Action; // eMenuAction - below zero is CFO\n\t\tchar m_EntryName[8];\n\t\tstruct {\n\t\t\tunion {\n\t\t\t\tCCFO *m_CFO; // for initializing\n\t\t\t\tCCFOSelect *m_CFOSelect;\n\t\t\t\tCCFODynamic *m_CFODynamic;\n\t\t\t};\n\t\t\tint32 m_SaveSlot; // eSaveSlot\n\t\t\tint32 m_TargetMenu; // eMenuScreen\n\t\t};\n\t\tuint16 m_X;\n\t\tuint16 m_Y;\n\t\tuint8 m_Align;\n\t} m_aEntries[NUM_MENUROWS];\n};\nextern CMenuScreenCustom aScreens[MENUPAGES];\n#endif\n\nstruct MenuTrapezoid\n{\n\tfloat topLeft_x;\n\tfloat topLeft_y;\n\tfloat topRight_x;\n\tfloat topRight_y;\n\tfloat bottomLeft_x;\n\tfloat bottomLeft_y;\n\tfloat bottomRight_x;\n\tfloat bottomRight_y;\n\tfloat old_topRight_x;\n\tfloat old_topRight_y;\n\tfloat old_topLeft_x;\n\tfloat old_topLeft_y;\n\tfloat old_bottomLeft_x;\n\tfloat old_bottomLeft_y;\n\tfloat old_bottomRight_x;\n\tfloat old_bottomRight_y;\n\tfloat mult_topRight_x;\n\tfloat mult_topRight_y;\n\tfloat mult_topLeft_x;\n\tfloat mult_topLeft_y;\n\tfloat mult_bottomLeft_x;\n\tfloat mult_bottomLeft_y;\n\tfloat mult_bottomRight_x;\n\tfloat mult_bottomRight_y;\n\n\tMenuTrapezoid(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4) {\n\t\ttopLeft_x = x1;\n\t\ttopLeft_y = y1;\n\t\ttopRight_x = x2;\n\t\ttopRight_y = y2;\n\t\tbottomLeft_x = x3;\n\t\tbottomLeft_y = y3;\n\t\tbottomRight_x = x4;\n\t\tbottomRight_y = y4;\n\t};\n\n\tvoid SaveCurrentCoors() {\n\t\told_topLeft_x = topLeft_x;\n\t\told_topLeft_y = topLeft_y;\n\t\told_topRight_x = topRight_x;\n\t\told_topRight_y = topRight_y;\n\t\told_bottomLeft_x = bottomLeft_x;\n\t\told_bottomLeft_y = bottomLeft_y;\n\t\told_bottomRight_x = bottomRight_x;\n\t\told_bottomRight_y = bottomRight_y;\n\t}\n\n\tvoid Translate(int delta) {\n\t\tbottomRight_x = delta * mult_bottomRight_x + old_bottomRight_x;\n\t\tbottomRight_y = delta * mult_bottomRight_y + old_bottomRight_y;\n\t\tbottomLeft_x = delta * mult_bottomLeft_x + old_bottomLeft_x;\n\t\tbottomLeft_y = delta * mult_bottomLeft_y + old_bottomLeft_y;\n\t\ttopRight_x = delta * mult_topRight_x + old_topRight_x;\n\t\ttopRight_y = delta * mult_topRight_y + old_topRight_y;\n\t\ttopLeft_x = delta * mult_topLeft_x + old_topLeft_x;\n\t\ttopLeft_y = delta * mult_topLeft_y + old_topLeft_y;\n\t}\n\n\tvoid UpdateMultipliers() {\n\t\tmult_bottomRight_x = (bottomRight_x - old_bottomRight_x) / 255.0f;\n\t\tmult_bottomRight_y = (bottomRight_y - old_bottomRight_y) / 255.0f;\n\t\tmult_bottomLeft_x = (bottomLeft_x - old_bottomLeft_x) / 255.0f;\n\t\tmult_bottomLeft_y = (bottomLeft_y - old_bottomLeft_y) / 255.0f;\n\t\tmult_topRight_x = (topRight_x - old_topRight_x) / 255.0f;\n\t\tmult_topRight_y = (topRight_y - old_topRight_y) / 255.0f;\n\t\tmult_topLeft_x = (topLeft_x - old_topLeft_x) / 255.0f;\n\t\tmult_topLeft_y = (topLeft_y - old_topLeft_y) / 255.0f;\n\t}\n};\n\nclass CMenuManager\n{\npublic:\n\tint8 m_StatsScrollDirection;\n\tfloat m_StatsScrollSpeed;\n\tuint8 field_8;\n\tbool m_PrefsUseVibration;\n\tbool m_PrefsShowHud;\n\tint32 m_PrefsRadarMode;\n\tbool m_DisplayControllerOnFoot;\n\tbool m_bShutDownFrontEndRequested;\n\tbool m_bStartUpFrontEndRequested;\n\tint32 m_KeyPressedCode;\n\tint32 m_PrefsBrightness;\n\tfloat m_PrefsLOD;\n\tint8 m_PrefsShowSubtitles;\n\tint8 m_PrefsShowLegends;\n\tint8 m_PrefsUseWideScreen;\n\tint8 m_PrefsVsync;\n\tint8 m_PrefsVsyncDisp;\n\tint8 m_PrefsFrameLimiter;\n\tint8 m_nPrefsAudio3DProviderIndex;\n\tint8 m_PrefsSpeakers;\n\tint8 m_PrefsDMA;\n\tint8 m_PrefsSfxVolume;\n\tint8 m_PrefsMusicVolume;\n\tint8 m_PrefsRadioStation;\n\tuint8 m_PrefsStereoMono; // unused except restore settings\n\tint32 m_nCurrOption;\n\tbool m_bQuitGameNoCD;\n\tbool m_bMenuMapActive;\n\tbool m_AllowNavigation;\n\tuint8 field_37;\n\tbool m_bMenuActive;\n\tbool m_bWantToRestart;\n\tbool m_bFirstTime;\n\tbool m_bActivateSaveMenu;\n\tbool m_bWantToLoad;\n\tfloat m_fMapSize;\n\tfloat m_fMapCenterX;\n\tfloat m_fMapCenterY;\n\tuint32 OS_Language;\n\tint32 m_PrefsLanguage;\n\tint32 field_54;\n\tint8 m_bLanguageLoaded;\n\tuint8 m_PrefsAllowNastyGame;\n\tint8 m_PrefsMP3BoostVolume;\n\tint8 m_ControlMethod;\n\tint32 m_nPrefsVideoMode;\n\tint32 m_nDisplayVideoMode;\n\tint32 m_nMouseTempPosX;\n\tint32 m_nMouseTempPosY;\n\tbool m_bGameNotLoaded;\n\tint8 m_lastWorking3DAudioProvider;\n\tbool m_bFrontEnd_ReloadObrTxtGxt;\n\tint32 *pEditString;\n\tuint8 field_74[4];\n\tint32 *pControlEdit;\n\tbool m_OnlySaveMenu;\n\tint32 m_firstStartCounter;\n\tCSprite2d m_aFrontEndSprites[NUM_MENU_SPRITES];\n\tbool m_bSpritesLoaded;\n\tint32 m_LeftMostRadioX;\n\tint32 m_ScrollRadioBy;\n\tint32 m_nCurrScreen;\n\tint32 m_nPrevScreen;\n\tint32 m_nCurrSaveSlot;\n\tuint32 m_LastScreenSwitch;\n\tint32 m_nMenuFadeAlpha;\n\tint32 m_nOptionHighlightTransitionBlend;\n\tbool bMenuChangeOngoing;\n\tint32 MouseButtonJustClicked;\n\tint32 JoyButtonJustClicked;\n\tbool DisplayComboButtonErrMsg;\n\tbool m_NoEmptyBinding;\n\tbool m_ShowEmptyBindingError;\n\tint32 m_nHelperTextAlpha;\n\tbool m_bPressedPgUpOnList;\n\tbool m_bPressedPgDnOnList;\n\tbool m_bPressedUpOnList;\n\tbool m_bPressedDownOnList;\n\tbool m_bPressedScrollButton;\n\tuint8 field_129;\n\tuint8 field_12A;\n\tuint8 field_12B;\n\tint32 m_nMousePosX;\n\tint32 m_nMousePosY;\n\tint32 m_nMouseOldPosX;\n\tint32 m_nMouseOldPosY;\n\tint32 m_nHoverOption;\n\tbool m_bShowMouse;\n\tint32 m_nOptionMouseHovering;\n\tbool m_bStartWaitingForKeyBind;\n\tbool m_bWaitingForNewKeyBind;\n\tbool m_bKeyChangeNotProcessed;\n\tint32 m_CurrCntrlAction;\n\tuint8 field_150;\n\tuint8 field_151;\n\tuint8 field_152;\n\tuint8 field_153;\n\tint32 m_nSelectedContSetupColumn;\n\tbool m_bKeyIsOK;\n\tbool field_159;\n\tuint8 m_nCurrExLayer;\n\tchar m_PrefsSkinFile[256];\n\tchar m_aSkinName[256];\n\tuint8 field_35B;\n\tint32 m_nHelperTextMsgId;\n\ttSkinInfo m_pSkinListHead;\n\ttSkinInfo *m_pSelectedSkin;\n\tint32 m_nFirstVisibleRowOnList;\n\tfloat m_nScrollbarTopMargin;\n\tint32 m_nTotalListRow;\n\tint32 m_nSkinsTotal;\n\tuint8 field_67C[4];\n\tint32 m_nSelectedListRow;\n\tbool m_bSkinsEnumerated;\n\n#ifdef IMPROVED_VIDEOMODE\n\tint32 m_nPrefsWidth;\n\tint32 m_nPrefsHeight;\n\tint32 m_nPrefsDepth;\n\tint32 m_nPrefsWindowed;\n\tint32 m_nPrefsSubsystem;\n\tint32 m_nSelectedScreenMode;\n#endif\n#ifdef MULTISAMPLING\n\tint8 m_nPrefsMSAALevel;\n\tint8 m_nDisplayMSAALevel;\n#endif\n\n#ifdef GAMEPAD_MENU\n\tenum\n\t{\n\t\tCONTROLLER_DUALSHOCK2 = 0,\n\t\tCONTROLLER_DUALSHOCK3,\n\t\tCONTROLLER_DUALSHOCK4,\n\t\tCONTROLLER_XBOX360,\n\t\tCONTROLLER_XBOXONE,\n\t};\n\n\tint8 m_PrefsControllerType;\n#endif\n\tenum LANGUAGE\n\t{\n\t\tLANGUAGE_AMERICAN,\n\t\tLANGUAGE_FRENCH,\n\t\tLANGUAGE_GERMAN,\n\t\tLANGUAGE_ITALIAN,\n\t\tLANGUAGE_SPANISH,\n#ifdef MORE_LANGUAGES\n\t\tLANGUAGE_POLISH,\n\t\tLANGUAGE_RUSSIAN,\n\t\tLANGUAGE_JAPANESE,\n#endif\n\t};\n\tbool GetIsMenuActive() {return !!m_bMenuActive;}\n\n#ifdef CUTSCENE_BORDERS_SWITCH\n\tstatic bool m_PrefsCutsceneBorders;\n#endif\n\n#ifndef MASTER\n\tstatic bool m_PrefsMarketing;\n\tstatic bool m_PrefsDisableTutorials;\n#endif // !MASTER\n\n\tCMenuManager(void);\n\t~CMenuManager(void) { UnloadTextures(); }\n\n#ifdef NO_ISLAND_LOADING\n\tenum\n\t{\n\t\tISLAND_LOADING_LOW = 0,\n\t\tISLAND_LOADING_MEDIUM,\n\t\tISLAND_LOADING_HIGH\n\t};\n\n\tint8 m_PrefsIslandLoading;\n\n\t#define ISLAND_LOADING_IS(p) if (FrontEndMenuManager.m_PrefsIslandLoading == CMenuManager::ISLAND_LOADING_##p)\n\t#define ISLAND_LOADING_ISNT(p) if (FrontEndMenuManager.m_PrefsIslandLoading != CMenuManager::ISLAND_LOADING_##p)\n#else\n\t#define ISLAND_LOADING_IS(p)\n\t#define ISLAND_LOADING_ISNT(p)\n#endif\n\n#ifdef XBOX_MESSAGE_SCREEN\n\tstatic uint32 m_nDialogHideTimer;\n\tstatic PauseModeTime m_nDialogHideTimerPauseMode;\n\tstatic bool m_bDialogOpen;\n\tstatic wchar *m_pDialogText;\n\tstatic bool m_bSaveWasSuccessful;\n\n\tstatic void SetDialogText(const char*);\n\tstatic bool DialogTextCmp(const char*);\n\tstatic void ToggleDialog(bool);\n\tstatic void SetDialogTimer(uint32);\n\tvoid ProcessDialogTimer(void);\n\tvoid DrawOverlays(void);\n\tvoid CloseDialog(void);\n#endif\n\n\tvoid Initialise();\n\tvoid PrintMap();\n\tvoid SetFrontEndRenderStates();\n\tstatic void CentreMousePointer();\n\tvoid CheckCodesForControls(int);\n\tbool CheckHover(int x1, int x2, int y1, int y2);\n\tvoid CheckSliderMovement(int);\n\tvoid DisplayHelperText(char*);\n\tint DisplaySlider(float, float, float, float, float, float, float);\n\tvoid DoSettingsBeforeStartingAGame();\n\tvoid DrawStandardMenus(bool);\n\tvoid DrawControllerBound(int32, int32, int32, int8);\n\tvoid DrawControllerScreenExtraText(int, int, int);\n\tvoid DrawControllerSetupScreen();\n\tvoid DrawQuitGameScreen();\n\tvoid DrawFrontEnd();\n\tvoid DrawBackground(bool transitionCall);\n\tvoid DrawPlayerSetupScreen(bool);\n\tint FadeIn(int alpha);\n\tint GetStartOptionsCntrlConfigScreens();\n\tvoid InitialiseChangedLanguageSettings();\n\tvoid LoadAllTextures();\n\tvoid LoadSettings();\n\tvoid MessageScreen(const char *str, bool);\n\tvoid SmallMessageScreen(const char *str);\n\tvoid PrintBriefs();\n\tstatic void PrintErrorMessage();\n\tvoid PrintStats();\n\tvoid Process();\n\tvoid ProcessList(bool &optionSelected, bool &goBack);\n\tvoid UserInput();\n\tvoid ProcessUserInput(uint8, uint8, uint8, uint8, int8);\n\tvoid ChangeRadioStation(int8);\n\tvoid ProcessFileActions();\n\tvoid ProcessOnOffMenuOptions();\n\tvoid RequestFrontEndShutDown();\n\tvoid RequestFrontEndStartUp();\n\tvoid ResetHelperText();\n\tvoid SaveSettings();\n\tvoid SetHelperText(int text);\n\tfloat StretchX(float);\n\tfloat StretchY(float);\n\tvoid SwitchMenuOnAndOff();\n\tvoid UnloadTextures();\n\tvoid WaitForUserCD();\n\tint GetNumOptionsCntrlConfigScreens();\n\tvoid SwitchToNewScreen(int8);\n\tvoid AdditionalOptionInput(bool &goBack);\n\tvoid ExportStats(void);\n\tvoid PrintRadioSelector(void);\n\n\t// New (not in function or inlined in the game)\n\tvoid ThingsToDoBeforeLeavingPage();\n\tvoid ScrollUpListByOne();\n\tvoid ScrollDownListByOne();\n\tvoid PageUpList(bool);\n\tvoid PageDownList(bool);\n\tint8 GetPreviousPageOption();\n\t\n\t// uint8 GetNumberOfMenuOptions();\n#ifdef GAMEPAD_MENU\n\tvoid LoadController(int8 type);\n\tvoid PrintController(void);\n#endif\n};\n\n#ifndef IMPROVED_VIDEOMODE\nVALIDATE_SIZE(CMenuManager, 0x688);\n#endif\n\nextern CMenuManager FrontEndMenuManager;\n\n#endif\n"
  },
  {
    "path": "src/core/FrontendTriggers.h",
    "content": "CTriggerCaller MemCardAccessTriggerCaller;\n\nvoid InitialiseTextsInMenuControllerInCar(CMenuPictureAndText *widget, CMenuManager::CONTRCONFIG cont);\nvoid InitialiseTextsInMenuControllerOnFoot(CMenuPictureAndText *widget, CMenuManager::CONTRCONFIG cont);\nvoid TriggerSave_BackToMainMenu(CMenuMultiChoiceTriggered *widget);\nvoid TriggerSave_BackToMainMenuTwoLines(CMenuMultiChoiceTwoLinesTriggered *widget);\nvoid TriggerSave_LoadGameLoadGameSelect(CMenuMultiChoiceTwoLinesTriggered *widget);\nvoid TriggerSave_DeleteGameDeleteGameSelect(CMenuMultiChoiceTwoLinesTriggered *widget);\nvoid TriggerSaveZone_BackToMainMenuTwoLines(CMenuMultiChoiceTwoLinesTriggered *widget);\nvoid TriggerSaveZone_BackToMainMenuTwoLines(CMenuMultiChoiceTwoLinesTriggered *widget);\nvoid TriggerSaveZone_SaveSlots(CMenuMultiChoiceTwoLinesTriggered *widget);\n\nvoid\nDisplayWarningControllerMsg()\n{\n\tif ( CPad::bDisplayNoControllerMessage )\n\t{\n\t\tCSprite2d::DrawRect(CRect(X(20.0f), Y(140.0f), X(620.0f), Y(328.0)), CRGBA(64, 16, 16, 224)); // CRect(20.0f, 160.0f, 620.0f, 374.857117f)\n\t\t\n\t\tCFont::SetFontStyle(FONT_BANK);\n\t\tCFont::SetBackgroundOff();\n\t\tCFont::SetScale(X(0.84f), Y(1.26f)); // 1.440000\n\t\tCFont::SetPropOn();\n\t\tCFont::SetCentreOff();\n\t\tCFont::SetJustifyOn();\n\t\tCFont::SetRightJustifyOff();\n\t\tCFont::SetBackGroundOnlyTextOn();\n\t\tCFont::SetWrapx(SCRW-X(40.0f)); // 600.0f\n\t\t\n\t\tCPlaceableShText text;\n\t\ttext.SetPosition(X(60.0f), Y(180.0f), false); // 205.714294\n\t\ttext.SetColor(CRGBA(152, 152, 152, 255));\n\t\ttext.m_text = TheText.Get(\"NOCONTE\"); // Please re-insert the analog controller (DUALSHOCK@) or analog controller (DUALSHOCK@2) in controller port 1 to continue\n\t\ttext.SetShadows(true, TEXT_SHADOW_COLOR, SHADOW_VECTOR*2.0f);\n\t\ttext.SetAlpha(255);\n\t\ttext.DrawShWrap(0.0f, 0.0f, X(600.0f+SHADOW_VECTOR.x), YF(600.0f)); //TODO check\n\t\t\n\t\tCFont::DrawFonts();\n\t}\n\telse if ( CPad::bObsoleteControllerMessage )\n\t{\n\t\tCSprite2d::DrawRect(CRect(X(20.0f), Y(140.0f), X(620.0f), Y(328.0)), CRGBA(64, 16, 16, 224)); // CRect(20.0f, 160.0f, 620.0f, 374.857117f)\n\t\tCFont::SetFontStyle(FONT_BANK);\n\t\tCFont::SetBackgroundOff();\n\t\tCFont::SetScale(X(0.84f), Y(1.26f)); // 1.440000\n\t\tCFont::SetPropOn();\n\t\tCFont::SetCentreOff();\n\t\tCFont::SetJustifyOn();\n\t\tCFont::SetRightJustifyOff();\n\t\tCFont::SetBackGroundOnlyTextOn();\n\t\tCFont::SetWrapx(SCRW-X(40.0f)); // 600.0f\n\t\t\n\t\tCPlaceableShText text;\n\t\ttext.SetPosition(X(60.0f), Y(180.0f), false); // 205.714294\n\t\ttext.SetColor(CRGBA(152, 152, 152, 255));\n\t\ttext.m_text = TheText.Get(\"WRCONTE\"); // Please re-insert the analog controller (DUALSHOCK@) or analog controller (DUALSHOCK@2) in controller port 1 to continue\n\t\ttext.SetShadows(true, TEXT_SHADOW_COLOR, SHADOW_VECTOR*2.0f);\n\t\ttext.SetAlpha(255);\n\t\ttext.DrawShWrap(0.0f, 0.0f, X(600.0f+SHADOW_VECTOR.x), YF(600.0f)); //TODO check\n\t\t\n\t\tCFont::DrawFonts();\n\t}\n\t\n}\n\nvoid\nTriggerMCSUM_Yes(CMenuMultiChoiceTriggered *widget)\t\n{\n\tif ( widget )\n\t\tbMemoryCardStartUpMenus_ExitNow = true;\n}\n\nint32 nStatLinesIndex;\nwchar aStatLines[50+1][50];\nwchar *PrintStatLine(char const *text, void *stat, unsigned char itsFloat, void *stat2)\n{\n\tif (text && stat && nStatLinesIndex < 50)\n\t{\n\t\tchar  line [64];\n\t\twchar uline[64];\n\t\t\n\t\tmemset(line, 0, sizeof(line));\n\t\tmemset(uline, 0, sizeof(uline));\n\n\t\tif (stat2)\n\t\t{\n\t\t\tif ( itsFloat )\n\t\t\t\tsprintf(line, \"  %.2f %s %.2f\", *(float*)stat, UnicodeToAscii(TheText.Get(\"FEST_OO\")), *(float*)stat2);\n\t\t\telse\n\t\t\t\tsprintf(line, \"  %d %s %d\", *(int32*)stat, UnicodeToAscii(TheText.Get(\"FEST_OO\")), *(int32*)stat2);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif (itsFloat)\n\t\t\t\tsprintf(line, \"  %.2f\", *(float*)stat);\n\t\t\telse\n\t\t\t\tsprintf(line, \"  %d\", *(int32*)stat);\n\t\t}\n\t\t\n\t\twchar *pStatLine = aStatLines[nStatLinesIndex++];\n\t\t\n\t\tAsciiToUnicode(line, uline);\n\t\tUnicodeStrcpy(pStatLine, uline);\n\t\t\n\t\treturn pStatLine;\n\t}\n\n\treturn nil;\n}\n\nvoid\nDisplayMemoryCardAccessMsg(wchar *msg, CRGBA const &color)\t\n{\t\n\tCSprite2d::DrawRect(CRect(X(70.0f), Y(100.0f), X(570.0f), Y(270.0f)), color);\n\t\n\tCFont::SetFontStyle(FONT_BANK);\n\tCFont::SetBackgroundOff();\n\tCFont::SetScale(X(MEMCARD_ACCESS_MSG_SIZE_X), Y(MEMCARD_ACCESS_MSG_SIZE_Y));\n\tCFont::SetPropOn();\n\tCFont::SetJustifyOn();\n\tCFont::SetRightJustifyOff();\n\tCFont::SetBackGroundOnlyTextOn();\n\tCFont::SetWrapx(SCRW-X(90.0f)); // 550.0f\n\tCFont::SetCentreOn();\n\tCFont::SetCentreSize(SCRW-X(180.0f)); // 460.0f\n\t\n\tCPlaceableShText text;\n\t\n\ttext.SetPosition(X(320.0f), Y(120.0f), false); // 137.142868\n\ttext.SetColor(CRGBA(200, 200, 200, 255));\n\ttext.m_text = msg;\n\t\t\n\ttext.SetShadows(true, TEXT_SHADOW_COLOR, SHADOW_VECTOR);\n\ttext.SetAlpha(255);\n\ttext.Draw(0.0f, 0.0f);\n\t\n\tCFont::DrawFonts();\n\tDoRWStuffEndOfFrame();\n}\n\nvoid\nFillMenuWithMemCardFileListing(CMenuMultiChoiceTwoLinesTriggered *widget, void (*cancelTrigger)(CMenuMultiChoiceTwoLinesTriggered *), void (*selectTrigger)(CMenuMultiChoiceTwoLinesTriggered *), wchar *text, int32 y, int32 height, int32 offset)\n{\n\tif ( widget )\n\t{\n\t\tint32 selected = 0;\n\t\tif ( bMemoryCardSpecialZone )\n\t\t\tselected = widget->m_cursor != -1 ? widget->m_cursor : 0;\n\t\t\n\t\twidget->DeactivateMenu(); // TODO check\n\t\twidget->m_numOptions = 0;\n\t\twidget->AddTitle(nil, 0.0f, 0.0f, 0);\n\t\t\n\t\tTheMemoryCard.PopulateSlotInfo(CARD_ONE);\n\t\t\n\t\tif ( TheMemoryCard.GetError() == CMemoryCard::NO_ERR_SUCCESS)\n\t\t{\n\t\t\twidget->AddOption(TheText.Get(\"FES_CAN\"), 0.0f, YF(y), cancelTrigger, 0, 0);\n\t\t\t\n\t\t\tFrontEndMenuManager.field_3C = 0;\n\t\t\t\n\t\t\ty += offset;\n\t\t\t\n\t\t\tchar buff[100];\n\t\t\t\n\t\t\tfor ( int32 i = 0; i < CMemoryCard::MAX_SLOTS; i++ )\n\t\t\t{\n\t\t\t\t// SAVE FILE\n\t\t\t\tsprintf(buff, \"%s %d \", UnicodeToAscii(TheText.Get(\"FES_SLO\")), i+1);\n\t\t\t\tAsciiToUnicode(buff, MemoryCard_FileNames[i]);\n\t\t\t\t\n\t\t\t\twchar *datetime = nil;\n\t\t\t\t\n\t\t\t\tswitch ( TheMemoryCard.GetInfoOnSpecificSlot(i) )\n\t\t\t\t{\n\t\t\t\t\tcase CMemoryCard::SLOT_CORRUPTED:\n\t\t\t\t\t{\n\t\t\t\t\t\tUnicodeStrcat(MemoryCard_FileNames[i], TheText.Get(\"FES_ISC\")); // IS CORRUPTED\n\t\t\t\t\t\tdatetime = TheMemoryCard.GetDateAndTimeOfSavedGame(i);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase CMemoryCard::SLOT_PRESENT:\n\t\t\t\t\t{\n\t\t\t\t\t\tif ( TheMemoryCard.GetNameOfSavedGame(i) != nil )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tUnicodeStrcpy(MemoryCard_FileNames[i], TheMemoryCard.GetNameOfSavedGame(i));\n\t\t\t\t\t\t\tdatetime = TheMemoryCard.GetDateAndTimeOfSavedGame(i);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tUnicodeStrcpy(MemoryCard_FileNames[i], TheText.Get(\"FES_SAG\")); // PRESENT\n\t\t\t\t\t\t\tdatetime = TheMemoryCard.GetDateAndTimeOfSavedGame(i);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase CMemoryCard::SLOT_NOTPRESENT:\n\t\t\t\t\t{\n\t\t\t\t\t\tUnicodeStrcat(MemoryCard_FileNames[i], TheText.Get(\"FES_ISF\"));\n\t\t\t\t\t\tdatetime = TheMemoryCard.GetDateAndTimeOfSavedGame(i);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\twidget->AddOption(MemoryCard_FileNames[i], 0.0f, YF(y), datetime, 0.0f, YF(float(y)+(0.44f*height)), selectTrigger, 0, 0);\n\t\t\t\ty += height;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif ( !gErrorSampleTriggered )\n\t\t\t{\n\t\t\t\tDMAudio.PlayFrontEndSound(SOUND_FRONTEND_FAIL, 0);\n\t\t\t\tgErrorSampleTriggered = true;\n\t\t\t}\n\t\t\t\n\t\t\t// Cancel\n\t\t\twidget->AddOption(TheText.Get(\"FES_CAN\"), 0.0f, YF(y+(height*2)), cancelTrigger, 0, 0);\n\t\t\t\n\t\t\tFrontEndMenuManager.field_3C = 1;\n\t\t\t\n\t\t\ty += height;\n\t\t\t\n\t\t\tTheMemoryCard.PopulateErrorMessage();\n\t\t\t\n\t\t\t// Error Reading Memory Card (PS2) in MEMORY CARD slot 1 please check and try again.\n\t\t\tif ( TheMemoryCard.GetErrorMessage())\n\t\t\t\twidget->AddTitle(TheMemoryCard.GetErrorMessage(), 0.0f, YF(y), 0);\n\t\t\telse\n\t\t\t\twidget->AddTitle(TheText.Get(\"FES_GME\"), 0.0f, YF(y), 0);\n\t\t}\n\t\t\n\t\twidget->SetMenuSelection(0);\n\t\twidget->ActivateMenu(1);\n\t\t\n\t\tif ( bMemoryCardSpecialZone )\n\t\t{\n\t\t\twidget->GoFirst();\n\t\t\t\n\t\t\tfor ( int32 i = 0; i < selected; i++ )\n\t\t\t\twidget->GoNext();\n\t\t}\n\t}\n}\n\nvoid\nTriggerSaveZone_FormatFailedOK(CMenuMultiChoiceTriggered *widget)\n{\n\tif ( widget )\n\t\tpActiveMenuPage = &MenuPageSaveZone_SaveGame;\n}\n\nvoid\nTriggerSaveZone_BackToMainMenu(CMenuMultiChoiceTriggered *widget)\n{\n\tbMemoryCardSpecialZone = false;\n\tbIgnoreTriangleButton = false;\n\tpActiveMenuPage = &MenuPageSaveZone_SaveGame;\n}\n\nvoid\nTriggerSaveZone_QuitMenu(CMenuMultiChoiceTriggered *widget)\n{\n\tif ( widget )\n\t{\n\t\tFrontEndMenuManager.m_bMenuActive = false;\n\t\tFrontEndMenuManager.m_bInSaveZone = false;\n\t\tCTimer::EndUserPause();\n\t}\n}\n\nvoid\nTriggerSaveZone_FormatCard(CMenuMultiChoiceTriggered *widget)\n{\n\tif ( widget )\n\t{\n\t\tFillMenuWithMemCardFileListing(&MenuSaveZoneSSL_1, TriggerSaveZone_BackToMainMenuTwoLines, TriggerSaveZone_SaveSlots, nil, 0, 34, 22);\n\t\t\n\t\tif ( TheMemoryCard.GetError() == CMemoryCard::NO_ERR_SUCCESS)\n\t\t{\n\t\t\tMenuSaveZoneMSG_1.m_numTexts = 0;\n\t\t\tMenuSaveZoneMSG_1.AddText(TheText.Get(\"FES_AFO\"), X(-80.0f), 0.0f, TEXT_COLOR, 0);\n\t\t\t\n\t\t\tMenuSaveZoneMSG_2.m_numOptions = 0;\n\t\t\tMenuSaveZoneMSG_2.AddOption(TheText.Get(\"FESZ_OK\"), X(100.0f), YF(5.0f), TriggerSaveZone_BackToMainMenu, 0, 0);\n\t\t\t\n\t\t\tMenuPageSaveZone_Message.ActivatePage();\n\t\t\tpActiveMenuPage = &MenuPageSaveZone_Message;\n\t\t}\n\t\telse if ( TheMemoryCard.GetError() != CMemoryCard::ERR_NOFORMAT)\n\t\t{\n\t\t\tMenuSaveZoneMSG_1.m_numTexts = 0;\n\t\t\tMenuSaveZoneMSG_1.AddText(TheMemoryCard.GetErrorMessage(), X(-80.0f), 0.0f, TEXT_COLOR, 0);\n\t\t\t\n\t\t\tMenuSaveZoneMSG_2.m_numOptions = 0;\n\t\t\tMenuSaveZoneMSG_2.AddOption(TheText.Get(\"FESZ_OK\"), X(100.0f), YF(15.0f), TriggerSaveZone_BackToMainMenu, 0, 0);\n\t\t\t\n\t\t\tMenuPageSaveZone_Message.ActivatePage();\n\t\t\tpActiveMenuPage = &MenuPageSaveZone_Message;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif ( !MemCardAccessTriggerCaller.CanCall() )\n\t\t\t\tMemCardAccessTriggerCaller.SetTrigger(TriggerSaveZone_FormatCard, widget);\n\t\t\telse\n\t\t\t{\n\t\t\t\t// Formatting Memory Card (PS2) in MEMORY CARD slot 1.  Please do not remove the Memory Card (PS2), reset or switch off the console.\n\t\t\t\tDisplayMemoryCardAccessMsg(TheText.Get(\"FEFD_WR\"), CRGBA(200, 50, 50, 192));\n\t\t\t\tTheMemoryCard.FormatCard(CARD_ONE);\n\t\t\t\t\n\t\t\t\tif ( TheMemoryCard.GetError() == CMemoryCard::NO_ERR_SUCCESS )\n\t\t\t\t\tpActiveMenuPage = &MenuPageSaveZone_SaveGame;\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tTheMemoryCard.PopulateErrorMessage();\n\t\t\t\t\t\n\t\t\t\t\twchar *error = TheText.Get(\"FESZ_FF\"); // Format Failed! Check Memory Card (PS2) in MEMORY CARD slot 1 and please try again.\n\t\t\t\t\t\n\t\t\t\t\t// missing switch\n\t\t\t\t\t\n\t\t\t\t\tif ( !error ) error = TheText.Get(\"FES_GME\"); // Error Reading Memory Card (PS2) in MEMORY CARD slot 1 please check and try again.\n\t\t\t\t\t\n\t\t\t\t\tMenuSaveZoneMSG_1.m_numTexts = 0;\n\t\t\t\t\tMenuSaveZoneMSG_1.AddText(error, X(-80.0f), 0.0f, TEXT_COLOR, 0);\n\t\t\t\t\t\n\t\t\t\t\tMenuSaveZoneMSG_2.m_numOptions = 0;\n\t\t\t\t\tMenuSaveZoneMSG_2.AddOption(TheText.Get(\"FESZ_OK\"), X(100.0f), YF(20.0f), TriggerSaveZone_BackToMainMenu, 0, 0);\n\t\t\t\t\t\n\t\t\t\t\tMenuPageSaveZone_Message.ActivatePage();\n\t\t\t\t\tpActiveMenuPage = &MenuPageSaveZone_Message;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif ( TheMemoryCard.GetError() == CMemoryCard::NO_ERR_SUCCESS )\n\t\t\t\t{\n\t\t\t\t\tFillMenuWithMemCardFileListing(&MenuSaveZoneSSL_1, TriggerSaveZone_BackToMainMenuTwoLines, TriggerSaveZone_SaveSlots, nil, 0, 34, 22);\n\t\t\t\t\tpActiveMenuPage = &MenuPageSaveZone_SaveSlots;\n\t\t\t\t\tbMemoryCardSpecialZone = true;\n\t\t\t\t\tbIgnoreTriangleButton = true;\n\t\t\t\t\tpActiveMenuPage->ActivatePage();\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tTheMemoryCard.PopulateErrorMessage();\n\t\t\t\t\t\n\t\t\t\t\t// Format Failed! Check Memory Card (PS2) in MEMORY CARD slot 1 and please try again.\n\t\t\t\t\twchar *error = TheText.Get(\"FESZ_FF\");\n\t\t\t\t\t\n\t\t\t\t\tswitch ( TheMemoryCard.GetError() )\n\t\t\t\t\t{\n\t\t\t\t\t\tcase CMemoryCard::ERR_WRITEFULLDEVICE:\n\t\t\t\t\t\tcase CMemoryCard::ERR_DIRFULLDEVICE:\n\t\t\t\t\t\tcase CMemoryCard::ERR_SAVEFAILED:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\terror = TheMemoryCard.GetErrorMessage();\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\t// Error Reading Memory Card (PS2) in MEMORY CARD slot 1 please check and try again.\n\t\t\t\t\tif ( !error ) error = TheText.Get(\"FES_GME\");\n\t\t\t\t\t\n\t\t\t\t\tMenuSaveZoneMSG_1.m_numTexts = 0;\n\t\t\t\t\tMenuSaveZoneMSG_1.AddText(error, X(-80.0f), 0.0f, TEXT_COLOR, 0);\n\t\t\t\t\t\n\t\t\t\t\tMenuSaveZoneMSG_2.m_numOptions = 0;\n\t\t\t\t\tMenuSaveZoneMSG_2.AddOption(TheText.Get(\"FESZ_OK\"), X(100.0f), YF(20.0f), TriggerSaveZone_BackToMainMenu, 0, 0);\n\t\t\t\t\t\n\t\t\t\t\tMenuPageSaveZone_Message.ActivatePage();\n\t\t\t\t\tpActiveMenuPage = &MenuPageSaveZone_Message;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nTriggerSaveZone_FormatCardSelect(CMenuMultiChoiceTriggered *widget)\n{\n\tif ( widget )\n\t{\n\t\tFillMenuWithMemCardFileListing(&MenuSaveZoneSSL_1, TriggerSaveZone_BackToMainMenuTwoLines, TriggerSaveZone_SaveSlots, nil, 0, 34, 22);\n\t\t\n\t\tif ( TheMemoryCard.GetError() == CMemoryCard::NO_ERR_SUCCESS )\n\t\t{\n\t\t\t// This Memory Card (PS2) is already formatted.\n\t\t\tMenuSaveZoneMSG_1.m_numTexts = 0;\n\t\t\tMenuSaveZoneMSG_1.AddText(TheText.Get(\"FES_AFO\"), X(-80.0f), 0.0f, TEXT_COLOR, 0);\n\t\t\t\n\t\t\tMenuSaveZoneMSG_2.m_numOptions = 0;\n\t\t\tMenuSaveZoneMSG_2.AddOption(TheText.Get(\"FESZ_OK\"), X(100.0f), YF(5.0f), TriggerSaveZone_BackToMainMenu, 0, 0);\n\t\t\t\n\t\t\tMenuPageSaveZone_Message.ActivatePage();\n\t\t\tpActiveMenuPage = &MenuPageSaveZone_Message;\n\t\t}\n\t\telse if ( TheMemoryCard.GetError() != CMemoryCard::ERR_NOFORMAT )\n\t\t{\n\t\t\tMenuSaveZoneMSG_1.m_numTexts = 0;\n\t\t\tMenuSaveZoneMSG_1.AddText(TheMemoryCard.GetErrorMessage(), X(-80.0f), 0.0f, TEXT_COLOR, 0);\n\t\t\t\n\t\t\tMenuSaveZoneMSG_2.m_numOptions = 0;\n\t\t\tMenuSaveZoneMSG_2.AddOption(TheText.Get(\"FESZ_OK\"), X(100.0f), YF(15.0f), TriggerSaveZone_BackToMainMenu, 0, 0);\n\t\t\t\n\t\t\tMenuPageSaveZone_Message.ActivatePage();\n\t\t\tpActiveMenuPage = &MenuPageSaveZone_Message;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// Are you sure you wish to format the Memory Card (PS2) in MEMORY CARD slot 1? \n\t\t\tMenuSaveZoneQYN_1.m_numTexts = 0;\n\t\t\tMenuSaveZoneQYN_1.AddText(TheText.Get(\"FESZ_QF\"), X(-40.0f), 0.0f, TEXT_COLOR, 0);\n\t\t\t\n\t\t\tMenuSaveZoneQYN_2.m_numOptions = 0;\n\t\t\tMenuSaveZoneQYN_2.AddOption(TheText.Get(\"FEM_NO\"),  X(80.0f), YF(20.0f), TriggerSaveZone_BackToMainMenu, 0, 0);\n\t\t\tMenuSaveZoneQYN_2.AddOption(TheText.Get(\"FEM_YES\"), X(80.0f), 0.0f,  TriggerSaveZone_FormatCard,     0, 0);\n\t\t\t\n\t\t\tMenuPageSaveZone_QuestionYesNo.ActivatePage();\n\t\t\tpActiveMenuPage = &MenuPageSaveZone_QuestionYesNo;\n\t\t}\n\t}\n}\n\nvoid\nTriggerSaveZone_DeleteSaveGame(CMenuMultiChoiceTriggered *widget)\n{\t\n\tif ( widget )\n\t{\n\t\tbMemoryCardSpecialZone = false;\n\t\tbIgnoreTriangleButton = false;\n\t\t\n\t\tif ( !MemCardAccessTriggerCaller.CanCall() )\n\t\t\tMemCardAccessTriggerCaller.SetTrigger(TriggerSaveZone_DeleteSaveGame, widget);\n\t\telse\n\t\t{\n\t\t\t// Overwriting data. Please do not remove the Memory Card (PS2) in MEMORY CARD slot 1, reset or switch off the console.\n\t\t\tDisplayMemoryCardAccessMsg(TheText.Get(\"FESZ_OW\"), CRGBA(200, 50, 50, 192));\n\t\t\t\n\t\t\tTheMemoryCard.DeleteSlot(MemoryCardSlotSelected);\n\t\t\t\n\t\t\tif ( TheMemoryCard.GetError() != CMemoryCard::NO_ERR_SUCCESS )\n\t\t\t{\n\t\t\t\tTheMemoryCard.PopulateErrorMessage();\n\t\t\t\t\n\t\t\t\twchar *error = TheText.Get(\"FES_DEE\"); // Deleting Failed! Check Memory Card (PS2) in MEMORY CARD slot 1 and please try again.\n\t\t\t\t\n\t\t\t\t// switch missing\n\t\t\t\t\n\t\t\t\tif ( !error ) error = TheText.Get(\"FES_GME\"); // Error Reading Memory Card (PS2) in MEMORY CARD slot 1 please check and try again.\n\t\t\t\t\n\t\t\t\tMenuSaveZoneMSG_1.m_numTexts = 0;\n\t\t\t\tMenuSaveZoneMSG_1.AddText(error, X(-80.0f), 0.0f, TEXT_COLOR, 0);\n\t\t\t\t\n\t\t\t\tMenuSaveZoneMSG_2.m_numOptions = 0;\n\t\t\t\tMenuSaveZoneMSG_2.AddOption(TheText.Get(\"FESZ_OK\"), X(100.0f), YF(20.0f), TriggerSaveZone_BackToMainMenu, 0, 0);\n\t\t\t\t\n\t\t\t\tMenuPageSaveZone_Message.ActivatePage();\n\t\t\t\tpActiveMenuPage = &MenuPageSaveZone_Message;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tTheMemoryCard.SaveSlot(MemoryCardSlotSelected);\n\t\t\t\t\n\t\t\t\tif ( TheMemoryCard.GetError() == CMemoryCard::NO_ERR_SUCCESS )\n\t\t\t\t{\n\t\t\t\t\t// Game saved successfully!\n\t\t\t\t\tMenuSaveZoneMSG_1.m_numTexts = 0;\n\t\t\t\t\tMenuSaveZoneMSG_1.AddText(TheText.Get(\"FESZ_L1\"), X(-20.0f), YF(10.0f), TEXT_COLOR, 0);\n\t\t\t\t\t\n\t\t\t\t\tMenuSaveZoneMSG_2.m_numOptions = 0;\n\t\t\t\t\tMenuSaveZoneMSG_2.AddOption(TheText.Get(\"FESZ_OK\"), X(110.0f), 0.0f, TriggerSaveZone_QuitMenu, 0, 0);\n\t\t\t\t\t\n\t\t\t\t\tMenuPageSaveZone_Message.ActivatePage();\n\t\t\t\t\tpActiveMenuPage = &MenuPageSaveZone_Message;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tTheMemoryCard.PopulateErrorMessage();\n\t\t\t\t\t\n\t\t\t\t\twchar *error = TheText.Get(\"FESZ_SR\"); // Save Failed! Check Memory Card (PS2) in MEMORY CARD slot 1 and please try again.\n\t\t\t\t\t\n\t\t\t\t\tswitch ( TheMemoryCard.GetError() )\n\t\t\t\t\t{\n\t\t\t\t\t\tcase CMemoryCard::ERR_WRITEFULLDEVICE:\n\t\t\t\t\t\tcase CMemoryCard::ERR_DIRFULLDEVICE:\n\t\t\t\t\t\tcase CMemoryCard::ERR_SAVEFAILED:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\terror = TheMemoryCard.GetErrorMessage();\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tif ( !error ) error = TheText.Get(\"FES_GME\"); // Error Reading Memory Card (PS2) in MEMORY CARD slot 1 please check and try again.\n\t\t\t\t\t\n\t\t\t\t\tMenuSaveZoneMSG_1.m_numTexts = 0;\n\t\t\t\t\tMenuSaveZoneMSG_1.AddText(error, X(-80.0f), 0.0f, TEXT_COLOR, 0);\n\t\t\t\t\t\n\t\t\t\t\tMenuSaveZoneMSG_2.m_numOptions = 0;\n\t\t\t\t\tMenuSaveZoneMSG_2.AddOption(TheText.Get(\"FESZ_OK\"), X(120.0f), YF(30.0f), TriggerSaveZone_BackToMainMenu, 0, 0);\n\t\t\t\t\t\n\t\t\t\t\tMenuPageSaveZone_Message.ActivatePage();\n\t\t\t\t\tpActiveMenuPage = &MenuPageSaveZone_Message;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nTriggerSaveZone_SaveGame(CMenuMultiChoiceTriggered *widget)\n{\t\n\tif ( widget )\n\t{\n\t\tbMemoryCardSpecialZone = false;\n\t\tbIgnoreTriangleButton  = false;\n\t\tif ( !MemCardAccessTriggerCaller.CanCall() )\n\t\t\tMemCardAccessTriggerCaller.SetTrigger(TriggerSaveZone_SaveGame, widget);\n\t\telse\n\t\t{\n\t\t\tDisplayMemoryCardAccessMsg(TheText.Get(\"FESZ_WR\"), CRGBA(200, 50, 50, 192));\n\t\t\t\n\t\t\tTheMemoryCard.SaveSlot(MemoryCardSlotSelected);\n\t\t\t\n\t\t\tif ( TheMemoryCard.GetError() == CMemoryCard::NO_ERR_SUCCESS )\n\t\t\t{\n\t\t\t\t// Game saved successfully!\n\t\t\t\tMenuSaveZoneMSG_1.m_numTexts = 0;\n\t\t\t\tMenuSaveZoneMSG_1.AddText(TheText.Get(\"FESZ_L1\"), X(-20.0f), YF(10.0f), TEXT_COLOR, 0);\n\t\t\t\t\n\t\t\t\tMenuSaveZoneMSG_2.m_numOptions = 0;\n\t\t\t\tMenuSaveZoneMSG_2.AddOption(TheText.Get(\"FESZ_OK\"), X(110.0f), 0.0f, TriggerSaveZone_QuitMenu, 0, 0);\n\t\t\t\t\n\t\t\t\tMenuPageSaveZone_Message.ActivatePage();\n\t\t\t\tpActiveMenuPage = &MenuPageSaveZone_Message;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tTheMemoryCard.PopulateErrorMessage();\n\t\t\t\t\n\t\t\t\twchar *error = TheText.Get(\"FESZ_SR\"); // Save Failed! Check Memory Card (PS2) in MEMORY CARD slot 1 and please try again.\n\t\t\t\t\n\t\t\t\tswitch ( TheMemoryCard.GetError() )\n\t\t\t\t{\n\t\t\t\t\tcase CMemoryCard::ERR_WRITEFULLDEVICE:\n\t\t\t\t\tcase CMemoryCard::ERR_DIRFULLDEVICE:\n\t\t\t\t\tcase CMemoryCard::ERR_SAVEFAILED:\n\t\t\t\t\t{\n\t\t\t\t\t\terror = TheMemoryCard.GetErrorMessage();\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif ( !error ) error = TheText.Get(\"FES_GME\"); // Error Reading Memory Card (PS2) in MEMORY CARD slot 1 please check and try again.\n\t\t\t\t\n\t\t\t\tMenuSaveZoneMSG_1.m_numTexts = 0;\n\t\t\t\tMenuSaveZoneMSG_1.AddText(error, X(-80.0f), 0.0f, TEXT_COLOR, 0);\n\t\t\t\t\n\t\t\t\tMenuSaveZoneMSG_2.m_numOptions = 0;\n\t\t\t\tMenuSaveZoneMSG_2.AddOption(TheText.Get(\"FESZ_OK\"), X(120.0f), YF(30.0f), TriggerSaveZone_BackToMainMenu, 0, 0);\n\t\t\t\t\n\t\t\t\tMenuPageSaveZone_Message.ActivatePage();\n\t\t\t\tpActiveMenuPage = &MenuPageSaveZone_Message;\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nTriggerSaveZone_SaveSlots(CMenuMultiChoiceTwoLinesTriggered *widget)\n{\n\tif ( widget )\n\t{\n\t\tif ( widget->GetMenuSelection() > 0 )\n\t\t{\n\t\t\tMemoryCardSlotSelected = widget->GetMenuSelection() - 1;\n\t\t\t\n\t\t\tswitch ( TheMemoryCard.GetInfoOnSpecificSlot(MemoryCardSlotSelected) )\n\t\t\t{\n\t\t\t\tcase CMemoryCard::SLOT_PRESENT:\n\t\t\t\tcase CMemoryCard::SLOT_CORRUPTED:\n\t\t\t\t{\n\t\t\t\t\t// Proceed with overwriting this saved game? \n\t\t\t\t\tMenuSaveZoneQYN_1.m_numTexts = 0;\n\t\t\t\t\tMenuSaveZoneQYN_1.AddText(TheText.Get(\"FESZ_QO\"), X(-40.0f), 0.0f, TEXT_COLOR, 0);\n\t\t\t\t\t\n\t\t\t\t\tMenuSaveZoneQYN_2.m_numOptions = 0;\n\t\t\t\t\tMenuSaveZoneQYN_2.AddOption(TheText.Get(\"FEM_NO\"),  X(80.0f), YF(20.0f), TriggerSaveZone_BackToMainMenu, 0, 0);\n\t\t\t\t\tMenuSaveZoneQYN_2.AddOption(TheText.Get(\"FEM_YES\"), X(80.0f), 0.0f,  TriggerSaveZone_DeleteSaveGame, 0, 0);\n\t\t\t\t\t\n\t\t\t\t\tMenuPageSaveZone_QuestionYesNo.ActivatePage();\n\t\t\t\t\tbMemoryCardSpecialZone = false;\n\t\t\t\t\tpActiveMenuPage = &MenuPageSaveZone_QuestionYesNo;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tcase CMemoryCard::SLOT_NOTPRESENT:\n\t\t\t\t{\n\t\t\t\t\t// PROCEED WITH SAVE ?\n\t\t\t\t\tMenuSaveZoneQYN_1.m_numTexts = 0;\n\t\t\t\t\tMenuSaveZoneQYN_1.AddText(TheText.Get(\"FESZ_QS\"), X(-40.0f), 0.0f, TEXT_COLOR, 0);\n\t\t\t\t\t\n\t\t\t\t\tMenuSaveZoneQYN_2.m_numOptions = 0;\n\t\t\t\t\tMenuSaveZoneQYN_2.AddOption(TheText.Get(\"FEM_NO\"),  X(80.0f), YF(20.0f), TriggerSaveZone_BackToMainMenu, 0, 0);\n\t\t\t\t\tMenuSaveZoneQYN_2.AddOption(TheText.Get(\"FEM_YES\"), X(80.0f), 0.0f,  TriggerSaveZone_SaveGame,       0, 0);\n\t\t\t\t\t\n\t\t\t\t\tMenuPageSaveZone_QuestionYesNo.ActivatePage();\n\t\t\t\t\tbMemoryCardSpecialZone = false;\n\t\t\t\t\tpActiveMenuPage = &MenuPageSaveZone_QuestionYesNo;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nTriggerSaveZone_SaveGameSelect(CMenuMultiChoiceTriggered *widget)\n{\t\n\tif ( widget )\n\t{\n\t\tFillMenuWithMemCardFileListing(&MenuSaveZoneSSL_1, TriggerSaveZone_BackToMainMenuTwoLines, TriggerSaveZone_SaveSlots, nil, 0, 34, 22);\n\t\t\n\t\tif ( TheMemoryCard.GetError() == CMemoryCard::ERR_NOFORMAT)\n\t\t{\n\t\t\tgErrorSampleTriggered = false;\n\t\t\tpActiveMenuPage = &MenuPageSaveZone_FormatCard;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tbMemoryCardSpecialZone = true;\n\t\t\tbIgnoreTriangleButton  = true;\n\t\t\tpActiveMenuPage = &MenuPageSaveZone_SaveSlots;\n\t\t}\n\t\t\n\t\tpActiveMenuPage->ActivatePage();\n\t}\n}\n\nvoid\nTriggerControls_Vibrations(CMenuOnOffTriggered *widget)\n{\n\tif ( widget )\n\t{\n\t\tCMenuManager::m_PrefsUseVibration = widget->GetMenuSelection();\n\t\tif ( CMenuManager::m_PrefsUseVibration )\n\t\t{\n\t\t\tCPad::GetPad(0)->StartShake(300, 150);\n\t\t\tTimeToStopPadShaking = CTimer::GetTimeInMillisecondsPauseMode() + 500;\n\t\t}\n\t}\n}\n\nvoid\nTriggerControls_ContrDisplay(CMenuMultiChoiceTriggeredAlways *widget)\n{\n\tif ( widget )\n\t{\n\t\tint32 conf = MenuControls_1.GetMenuSelection();\n\t\tint32 i  = MenuControls_2.GetMenuSelection();\n\t\tif ( i == 1 )\n\t\t{\n\t\t\tif ( conf == CMenuManager::CONFIG_2 )\n\t\t\t\tMenuPage_Controls.m_controls[0] = &MenuControls_7;\n\t\t\telse\n\t\t\t\tMenuPage_Controls.m_controls[0] = &MenuControls_4;\n\t\t}\n\t\telse if ( i == 0 )\n\t\t{\n\t\t\tif ( conf == CMenuManager::CONFIG_2 )\n\t\t\t\tMenuPage_Controls.m_controls[0] = &MenuControls_6;\n\t\t\telse\n\t\t\t\tMenuPage_Controls.m_controls[0] = &MenuControls_3;\n\t\t}\n\t}\n}\n\nvoid\nTriggerControls_DrawHNContrConfig(CMenuMultiChoiceTriggeredAlways *widget)\n{\n\tif ( widget )\n\t{\n\t\tint32 conf = widget->GetMenuSelection();\n\t\t\n\t\tInitialiseTextsInMenuControllerOnFoot(&MenuControls_3, (CMenuManager::CONTRCONFIG)conf);\n\t\tInitialiseTextsInMenuControllerInCar (&MenuControls_4, (CMenuManager::CONTRCONFIG)conf);\n\t\t\n\t\tint32 i = MenuControls_2.GetMenuSelection();\n\t\tif ( i == 1 )\n\t\t{\n\t\t\tif ( conf == CMenuManager::CONFIG_2 )\n\t\t\t\tMenuPage_Controls.m_controls[0] = &MenuControls_7;\n\t\t\telse\n\t\t\t\tMenuPage_Controls.m_controls[0] = &MenuControls_4;\n\t\t}\n\t\telse if ( i == 0 )\n\t\t{\n\t\t\tif ( conf == CMenuManager::CONFIG_2 )\n\t\t\t\tMenuPage_Controls.m_controls[0] = &MenuControls_6;\n\t\t\telse\n\t\t\t\tMenuPage_Controls.m_controls[0] = &MenuControls_3;\n\t\t}\n\t}\n}\n\nvoid\nTriggerControls_DrawContrConfig(CMenuMultiChoiceTriggeredAlways *widget)\n{\n\tif ( widget )\n\t{\n\t\tint32 conf = widget->GetMenuSelection();\n\t\tif ( widget->m_cursor != -1 )\n\t\t\tconf = widget->m_cursor;\n\t\t\n\t\tInitialiseTextsInMenuControllerOnFoot(&MenuControls_3, (CMenuManager::CONTRCONFIG)conf);\n\t\tInitialiseTextsInMenuControllerInCar(&MenuControls_4, (CMenuManager::CONTRCONFIG)conf);\n\t\t\n\t\tint32 i = MenuControls_2.GetMenuSelection();\n\t\tif ( i == 1 )\n\t\t{\n\t\t\tif ( conf == CMenuManager::CONFIG_2 )\n\t\t\t\tMenuPage_Controls.m_controls[0] = &MenuControls_7;\n\t\t\telse\n\t\t\t\tMenuPage_Controls.m_controls[0] = &MenuControls_4;\n\t\t}\n\t\telse if ( i == 0 )\n\t\t{\n\t\t\tif ( conf == CMenuManager::CONFIG_2 )\n\t\t\t\tMenuPage_Controls.m_controls[0] = &MenuControls_6;\n\t\t\telse\n\t\t\t\tMenuPage_Controls.m_controls[0] = &MenuControls_3;\n\t\t}\n\t}\n}\n\nvoid\nTriggerControls_ContrConfig(CMenuMultiChoiceTriggered *widget)\n{\n\tif ( widget )\n\t{\n\t\tint32 conf = widget->GetMenuSelection();\n\t\t\n\t\tInitialiseTextsInMenuControllerOnFoot(&MenuControls_3, (CMenuManager::CONTRCONFIG)conf);\n\t\tInitialiseTextsInMenuControllerInCar(&MenuControls_4, (CMenuManager::CONTRCONFIG)conf);\n\t\t\n\t\tint32 i = MenuControls_2.GetMenuSelection();\n\t\tif ( i == 1 )\n\t\t{\n\t\t\tif ( conf == CMenuManager::CONFIG_2 )\n\t\t\t\tMenuPage_Controls.m_controls[0] = &MenuControls_7;\n\t\t\telse\n\t\t\t\tMenuPage_Controls.m_controls[0] = &MenuControls_4;\n\t\t}\n\t\telse if ( i == 0 )\n\t\t{\n\t\t\tif ( conf == CMenuManager::CONFIG_2 )\n\t\t\t\tMenuPage_Controls.m_controls[0] = &MenuControls_6;\n\t\t\telse\n\t\t\t\tMenuPage_Controls.m_controls[0] = &MenuControls_3;\n\t\t}\n\t}\n}\n\nvoid\nTriggerLanguage_Language(CMenuMultiChoiceTriggered *widget)\n{\t\n\tif ( widget )\n\t{\n\t\tif ( CMenuManager::m_PrefsLanguage != widget->GetMenuSelection() )\n\t\t{\n\t\t\tCMenuManager::m_PrefsLanguage = widget->GetMenuSelection();\n\t\t\tFrontEndMenuManager.m_bInitialised = false;\n\t\t\tbFrontEnd_ReloadObrTxtGxt = true;\n\t\t}\n\t}\n}\n\nvoid\nTriggerAudio_RadioStation(CMenuMultiChoicePicturedTriggered *widget)\n{\n\tif ( widget )\n\t{\n\t\tif ( CMenuManager::m_PrefsRadioStation != widget->GetMenuSelection() )\n\t\t{\n\t\t\tCMenuManager::m_PrefsRadioStation = widget->GetMenuSelection();\n\t\t\tDMAudio.PlayFrontEndTrack(CMenuManager::m_PrefsRadioStation, 1);\n\t\t\tDMAudio.SetRadioInCar(CMenuManager::m_PrefsRadioStation);\n\t\t}\n\t}\n}\n\nvoid\nTriggerAudio_StereoMono(CMenuMultiChoiceTriggered *widget)\n{\n\tif ( widget )\n\t{\t\n\t\tif (widget->GetMenuSelection() == 1)\n\t\t{\n\t\t\tDMAudio.SetMonoMode(true);\n\t\t\tDMAudio.PlayFrontEndSound(SOUND_FRONTEND_MONO, 0);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tDMAudio.SetMonoMode(false);\n\t\t\tDMAudio.PlayFrontEndSound(SOUND_FRONTEND_STEREO, 0);\n\t\t}\n\t}\n}\n\nvoid\nTriggerAudio_MusicVolumeAlways(CMenuSliderTriggered *widget)\n{\n\t;\n}\n\nvoid\nTriggerAudio_SfxVolumeAlways(CMenuSliderTriggered *widget)\n{\n\tif ( widget )\n\t{\n\t\tstatic bool bTriggerTest = false;\n\t\t\n\t\tCMenuManager::m_PrefsSfxVolume = float(widget->GetMenuSelection()) / 100.0f * 127.0f + 0.5f;\n\t\t\n\t\tif ( CMenuManager::m_PrefsSfxVolume == 102 && !CPad::GetPad(0)->GetDPadLeft()&& !CPad::GetPad(0)->GetDPadRight() )\n\t\t{\n\t\t\tif ( bTriggerTest )\n\t\t\t{\n\t\t\t\tDMAudio.PlayFrontEndSound(SOUND_FRONTEND_AUDIO_TEST, 0);\n\t\t\t\tbTriggerTest = false;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t\tbTriggerTest = true;\n\t\t\n\t\tFrontEndMenuManager.SetSoundLevelsForMusicMenu();\n\t}\n}\n\nvoid\nTriggerAudio_MusicVolume(CMenuSliderTriggered *widget)\n{\t\n\tif ( widget )\n\t{\n\t\tCMenuManager::m_PrefsMusicVolume = float(widget->GetMenuSelection()) / 100.0f * 127.0f + 0.5f;\n\t\tFrontEndMenuManager.SetSoundLevelsForMusicMenu();\n\t}\n}\n\nvoid\nTriggerAudio_SfxVolume(CMenuSliderTriggered *widget)\n{\n\t;\n}\n\nvoid\nTriggerSave_NewGameNewGame(CMenuMultiChoiceTriggered *widget)\n{\t\n\tFrontEndMenuManager.m_bWantToRestart = true;\n\tFrontEndMenuManager.m_bMenuActive    = false;\n\tFrontEndMenuManager.m_bInSaveZone    = false;\n\tbIgnoreTriangleButton = false;\n\t\n\tCTimer::EndUserPause();\n\t\n\tFrontEndMenuManager.AnaliseMenuContents();\n\t\n\tDMAudio.SetEffectsFadeVol(0);\n\tDMAudio.SetMusicFadeVol(0);\n\tDMAudio.ResetTimers(CTimer::GetTimeInMilliseconds());\n}\n\nvoid\nTriggerSave_NewGameSelectYes(CMenuMultiChoiceTriggered *widget)\n{\n\t// Are you sure you want to start a new game? All progress since the last save game will be lost. Proceed?\n\tMenuSaveZoneQYN_1.m_numTexts = 0;\n\tMenuSaveZoneQYN_1.AddText(TheText.Get(\"FESZ_QR\"), X(-100.0f), 0.0f, TEXT_COLOR, 0);\n\t\n\tMenuSaveZoneQYN_2.m_numOptions = 0;\n\tMenuSaveZoneQYN_2.AddOption(TheText.Get(\"FEM_NO\"),  X(80.0f), YF(30.0f), TriggerSave_BackToMainMenu, 0, 0);\n\tMenuSaveZoneQYN_2.AddOption(TheText.Get(\"FEM_YES\"), X(80.0f), YF(10.0f), TriggerSave_NewGameNewGame, 0, 0);\n\t\n\tMenuPageSaveZone_QuestionYesNo.ActivatePage();\n\tpMenuSave = &MenuPageSaveZone_QuestionYesNo;\n\tbIgnoreTriangleButton = true;\n}\n\nvoid\nTriggerSave_DeleteGameDeleteGame(CMenuMultiChoiceTriggered *widget)\n{\n\tif ( widget )\n\t{\n\t\tbMemoryCardSpecialZone = false;\n\t\tbIgnoreTriangleButton  = false;\n\t\t\n\t\tif ( !MemCardAccessTriggerCaller.CanCall() )\n\t\t\tMemCardAccessTriggerCaller.SetTrigger(TriggerSave_DeleteGameDeleteGame, widget);\n\t\telse\n\t\t{\n\t\t\t// Deleting data. Please do not remove the Memory Card (PS2) in MEMORY CARD slot 1, reset or switch off the console.\n\t\t\tDisplayMemoryCardAccessMsg(TheText.Get(\"FEDL_WR\"), CRGBA(200, 50, 50, 192));\n\t\t\t\n\t\t\tTheMemoryCard.DeleteSlot(MemoryCardSlotSelected);\n\t\t\t\n\t\t\tif ( TheMemoryCard.GetError() != CMemoryCard::NO_ERR_SUCCESS)\n\t\t\t{\n\t\t\t\t// Deleting Failed! Check Memory Card (PS2) in MEMORY CARD slot 1 and please try again.\n\t\t\t\tMenuSaveZoneMSG_1.m_numTexts = 0;\n\t\t\t\tMenuSaveZoneMSG_1.AddText(TheText.Get(\"FES_DEE\"), X(-80.0f), YF(20.0f), TEXT_COLOR, 0);\n\t\t\t\t\n\t\t\t\tMenuSaveZoneMSG_2.m_numOptions = 0;\n\t\t\t\tMenuSaveZoneMSG_2.AddOption(TheText.Get(\"FESZ_OK\"), X(100.0f), YF(15.0f), TriggerSave_BackToMainMenu, 0, 0);\n\t\t\t\t\n\t\t\t\tMenuPageSaveZone_Message.ActivatePage();\n\t\t\t\tpMenuSave = &MenuPageSaveZone_Message;\n\t\t\t\t\n\t\t\t\tbMemoryCardSpecialZone = false;\n\t\t\t\tbIgnoreTriangleButton  = true;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tFillMenuWithMemCardFileListing(&MenuSaveLG_2, TriggerSave_BackToMainMenuTwoLines, TriggerSave_LoadGameLoadGameSelect,     nil, 0, 34, 22);\n\t\t\t\tFillMenuWithMemCardFileListing(&MenuSaveDG_2, TriggerSave_BackToMainMenuTwoLines, TriggerSave_DeleteGameDeleteGameSelect, nil, 0, 34, 22);\n\t\t\t\t\n\t\t\t\tpMenuSave = &MenuPage_SaveBasic;\n\t\t\t\tpMenuSave->ActivatePage();\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nTriggerSave_DeleteGameDeleteGameSelect(CMenuMultiChoiceTwoLinesTriggered *widget)\n{\n\tif ( widget )\n\t{\n\t\tif ( widget->GetMenuSelection() > 0 )\n\t\t{\n\t\t\tMemoryCardSlotSelected = widget->GetMenuSelection() - 1;\n\t\t\t\n\t\t\tswitch ( TheMemoryCard.GetInfoOnSpecificSlot(MemoryCardSlotSelected) )\n\t\t\t{\n\t\t\t\tcase CMemoryCard::SLOT_NOTPRESENT:\n\t\t\t\t{\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase CMemoryCard::SLOT_CORRUPTED:\n\t\t\t\tcase CMemoryCard::SLOT_PRESENT:\n\t\t\t\t{\n\t\t\t\t\t// Proceed with deleting this saved game? \n\t\t\t\t\tMenuSaveZoneQYN_1.m_numTexts = 0;\n\t\t\t\t\tMenuSaveZoneQYN_1.AddText(TheText.Get(\"FESZ_QD\"), X(-40.0f), 0.0f, TEXT_COLOR, 0);\n\t\t\t\t\t\n\t\t\t\t\tMenuSaveZoneQYN_2.m_numOptions = 0;\n\t\t\t\t\tMenuSaveZoneQYN_2.AddOption(TheText.Get(\"FEM_NO\"), X(80.0f), YF(20.0f), TriggerSave_BackToMainMenu, 0, 0);\n\t\t\t\t\tMenuSaveZoneQYN_2.AddOption(TheText.Get(\"FEM_YES\"), X(80.0f), 0.0f, TriggerSave_DeleteGameDeleteGame, 0, 0);\n\t\t\t\t\t\n\t\t\t\t\tMenuPageSaveZone_QuestionYesNo.ActivatePage();\n\t\t\t\t\tpMenuSave = &MenuPageSaveZone_QuestionYesNo;\n\t\t\t\t\tbMemoryCardSpecialZone = false;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nTriggerSave_DeleteGameSelect(CMenuMultiChoiceTriggered *widget)\n{\t\n\tFillMenuWithMemCardFileListing(&MenuSaveDG_2, TriggerSave_BackToMainMenuTwoLines, TriggerSave_DeleteGameDeleteGameSelect, nil, 0, 34, 22);\n\tFillMenuWithMemCardFileListing(&MenuSaveLG_2, TriggerSave_BackToMainMenuTwoLines, TriggerSave_LoadGameLoadGameSelect,     nil, 0, 34, 22);\n\t\n\tpMenuSave = &MenuPage_SaveDeleteGame;\n\tpMenuSave->ActivatePage();\n\t\n\tgErrorSampleTriggered  = false;\n\tbMemoryCardSpecialZone = true;\n\tbIgnoreTriangleButton  = true;\n}\n\nvoid\nTriggerSave_LoadGameLoadGame(CMenuMultiChoiceTriggered *widget)\n{\t\n\tif ( widget )\n\t{\n\t\tbMemoryCardSpecialZone = false;\n\t\tbIgnoreTriangleButton  = false;\n\t\t\n\t\tif ( !MemCardAccessTriggerCaller.CanCall() )\n\t\t\tMemCardAccessTriggerCaller.SetTrigger(TriggerSave_LoadGameLoadGame, widget);\n\t\telse\n\t\t{\n\t\t\t// Loading data. Please do not remove the Memory Card (PS2) in MEMORY CARD slot 1, reset or switch off the console.\n\t\t\tDisplayMemoryCardAccessMsg(TheText.Get(\"FELD_WR\"), CRGBA(200, 50, 50, 192));\n\t\t\tTheMemoryCard.LoadSlotToBuffer(MemoryCardSlotSelected);\n\t\t\t\n\t\t\tif ( TheMemoryCard.GetError() == CMemoryCard::NO_ERR_SUCCESS)\n\t\t\t{\n\t\t\t\tFrontEndMenuManager.m_bWantToRestart = true;\n\t\t\t\tFrontEndMenuManager.AnaliseMenuContents();\n\t\t\t\tFrontEndMenuManager.m_bMenuActive = false;\n\t\t\t\tFrontEndMenuManager.m_bInSaveZone = false;\n\t\t\t\t\n\t\t\t\tCTimer::EndUserPause();\n\t\t\t\t\n\t\t\t\tTheMemoryCard.m_bWantToLoad = true;\n\t\t\t\t\n\t\t\t\tDMAudio.SetEffectsFadeVol(0);\n\t\t\t\tDMAudio.SetMusicFadeVol(0);\n\t\t\t\tDMAudio.ResetTimers(CTimer::GetTimeInMilliseconds());\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// Load Failed! Check Memory Card (PS2) in MEMORY CARD slot 1 and please try again.\n\t\t\t\tMenuSaveZoneMSG_1.m_numTexts = 0;\n\t\t\t\tMenuSaveZoneMSG_1.AddText(TheText.Get(\"FES_LOE\"), X(-80.0f), YF(20.0f), TEXT_COLOR, 0);\n\t\t\t\t\n\t\t\t\tMenuSaveZoneMSG_2.m_numOptions = 0;\n\t\t\t\tMenuSaveZoneMSG_2.AddOption(TheText.Get(\"FESZ_OK\"), X(100.0f), YF(25.0f), TriggerSave_BackToMainMenu, 0, 0);\n\t\t\t\t\n\t\t\t\tpMenuSave = &MenuPageSaveZone_Message;\n\t\t\t\tpMenuSave->ActivatePage();\n\t\t\t\t\n\t\t\t\tbMemoryCardSpecialZone = false;\n\t\t\t\tbIgnoreTriangleButton = true;\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nTriggerSave_LoadGameLoadGameSelect(CMenuMultiChoiceTwoLinesTriggered *widget)\n{\t\n\tif ( widget )\n\t{\n\t\tif ( widget->GetMenuSelection() > 0 )\n\t\t{\n\t\t\tMemoryCardSlotSelected = widget->GetMenuSelection() - 1;\n\t\t\t\n\t\t\tswitch ( TheMemoryCard.GetInfoOnSpecificSlot(MemoryCardSlotSelected) )\n\t\t\t{\n\t\t\t\tcase CMemoryCard::SLOT_NOTPRESENT:\n\t\t\t\t{\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase CMemoryCard::SLOT_CORRUPTED:\n\t\t\t\t{\n\t\t\t\t\t// Load Failed.\n\t\t\t\t\tMenuSaveZoneMSG_1.m_numTexts = 0;\n\t\t\t\t\tMenuSaveZoneMSG_1.AddText(TheText.Get(\"FES_LOF\"), X(50.0f), YF(20.0f), TEXT_COLOR, 0);\n\t\t\t\t\t\n\t\t\t\t\tMenuSaveZoneMSG_2.m_numOptions = 0;\n\t\t\t\t\tMenuSaveZoneMSG_2.AddOption(TheText.Get(\"FESZ_OK\"), X(100.0f), 0.0f, TriggerSave_BackToMainMenu, 0, 0);\n\t\t\t\t\t\n\t\t\t\t\tMenuPageSaveZone_Message.ActivatePage();\n\t\t\t\t\tpMenuSave = &MenuPageSaveZone_Message;\n\t\t\t\t\tbMemoryCardSpecialZone = false;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase CMemoryCard::SLOT_PRESENT:\n\t\t\t\t{\n\t\t\t\t\t// All unsaved progress in your current game will be lost. Proceed with loading? \n\t\t\t\t\tMenuSaveZoneQYN_1.m_numTexts = 0;\n\t\t\t\t\tMenuSaveZoneQYN_1.AddText(TheText.Get(\"FESZ_QL\"), X(-40.0f), 0.0f, TEXT_COLOR, 0);\n\t\t\t\t\t\n\t\t\t\t\tMenuSaveZoneQYN_2.m_numOptions = 0;\n\t\t\t\t\tMenuSaveZoneQYN_2.AddOption(TheText.Get(\"FEM_NO\"),  X(80.0f), YF(20.0f), TriggerSave_BackToMainMenu,   0, 0);\n\t\t\t\t\tMenuSaveZoneQYN_2.AddOption(TheText.Get(\"FEM_YES\"), X(80.0f), 0.0f,  TriggerSave_LoadGameLoadGame, 0, 0);\n\t\t\t\t\t\n\t\t\t\t\tMenuPageSaveZone_QuestionYesNo.ActivatePage();\n\t\t\t\t\tpMenuSave = &MenuPageSaveZone_QuestionYesNo;\n\t\t\t\t\tbMemoryCardSpecialZone = false;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nTriggerSave_LoadGameSelect(CMenuMultiChoiceTriggered *widget)\n{\n\tFillMenuWithMemCardFileListing(&MenuSaveLG_2, TriggerSave_BackToMainMenuTwoLines, TriggerSave_LoadGameLoadGameSelect,     nil, 0, 34, 22);\n\tFillMenuWithMemCardFileListing(&MenuSaveDG_2, TriggerSave_BackToMainMenuTwoLines, TriggerSave_DeleteGameDeleteGameSelect, nil, 0, 34, 22);\n\t\n\tpMenuSave = &MenuPage_SaveLoadGame;\n\tpMenuSave->ActivatePage();\n\t\n\tgErrorSampleTriggered  = false;\n\tbMemoryCardSpecialZone = true;\n\tbIgnoreTriangleButton  = true;\n}\n\nvoid\nTriggerSave_BackToMainMenu(CMenuMultiChoiceTriggered *widget)\n{\n\tpMenuSave = &MenuPage_SaveBasic;\n\tpMenuSave->ActivatePage();\n\tbMemoryCardSpecialZone = false;\n\tbIgnoreTriangleButton  = false;\n}\n\nvoid InitialiseTextsInMenuControllerInCar(CMenuPictureAndText *widget, CMenuManager::CONTRCONFIG cont)\n{\n\tif ( widget )\n\t{\n\t\twidget->m_numTexts = 0;\n\t\t\n\t\tswitch ( cont )\n\t\t{\n\t\t\tcase CMenuManager::CONFIG_1:\n\t\t\t{\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_LL\"),  X(50.0f),  Y(-14.0f), PAD_TEXT_COLOR, true);  // -16.0f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_RSC\"), X(-4.0f),  Y(29.0f),  PAD_TEXT_COLOR, true);  // 33.142860f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_VES\"), X(-4.0f),  Y(65.0f),  PAD_TEXT_COLOR, true);  // 74.285721f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_VES\"), X(-4.0f),  Y(97.0f),  PAD_TEXT_COLOR, true);  // 110.857147f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_HO3\"), X(84.0f),  Y(162.0f), PAD_TEXT_COLOR, false); // 185.142868f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_CAM\"), X(103.0f), Y(141.0f), PAD_TEXT_COLOR, false); // 161.142868f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_PAU\"), X(130.0f), Y(128.0f), PAD_TEXT_COLOR, false); // 146.285721f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_LB\"),  X(68.0f),  Y(-6.0f),  PAD_TEXT_COLOR, false); // -6.857143f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_LR\"),  X(184.0f), Y(-14.0f), PAD_TEXT_COLOR, false); // -16.0f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_HAB\"), X(238.0f), Y(25.0f),  PAD_TEXT_COLOR, false); // 28.571430f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_BRA\"), X(155.0f), Y(18.0f),  PAD_TEXT_COLOR, true);  //  20.571430f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_EXV\"), X(238.0f), Y(52.0f),  PAD_TEXT_COLOR, false); // 59.428574f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_CAW\"), X(238.0f), Y(65.0f),  PAD_TEXT_COLOR, false); //  74.285721f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_ACC\"), X(238.0f), Y(78.0f),  PAD_TEXT_COLOR, false); // 89.142860f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_TUC\"), X(238.0f), Y(94.0f),  PAD_TEXT_COLOR, false); // 107.428574f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_SM3\"), X(238.0f), Y(109.0f), PAD_TEXT_COLOR, false); // 124.571434f\n\t\t\t\t\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t\n\t\t\tcase CMenuManager::CONFIG_2:\n\t\t\t{\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_LL\"),  X(50.0f),  Y(-14.0f), PAD_TEXT_COLOR, true);  // -16.0f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_HOR\"), X(-4.0f),  Y(29.0f),  PAD_TEXT_COLOR, true);  // 33.142860f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_CAM\"), X(-4.0f),  Y(65.0f),  PAD_TEXT_COLOR, true);  // 74.285721f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_VES\"), X(-4.0f),  Y(97.0f),  PAD_TEXT_COLOR, true);  // 110.857147f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_NA\"),  X(84.0f),  Y(162.0f), PAD_TEXT_COLOR, false); // 185.142868f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_RSC\"), X(103.0f), Y(141.0f), PAD_TEXT_COLOR, false); // 161.142868f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_PAU\"), X(130.0f), Y(128.0f), PAD_TEXT_COLOR, false); // 146.285721f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_LB\"),  X(68.0f),  Y(-6.0f),  PAD_TEXT_COLOR, false); // -6.857143f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_LR\"),  X(184.0f), Y(-14.0f), PAD_TEXT_COLOR, false); // -16.0f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_HAB\"), X(238.0f), Y(25.0f),  PAD_TEXT_COLOR, false); // 28.571430f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_BRA\"), X(155.0f), Y(18.0f),  PAD_TEXT_COLOR, true);  //  20.571430f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_EXV\"), X(238.0f), Y(52.0f),  PAD_TEXT_COLOR, false); // 59.428574f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_CAW\"), X(238.0f), Y(65.0f),  PAD_TEXT_COLOR, false); //  74.285721f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_ACC\"), X(238.0f), Y(78.0f),  PAD_TEXT_COLOR, false); // 89.142860f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_TUC\"), X(238.0f), Y(94.0f),  PAD_TEXT_COLOR, false); // 107.428574f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_SM3\"), X(238.0f), Y(109.0f), PAD_TEXT_COLOR, false); // 124.571434f\n\t\t\t\t\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t\n\t\t\tcase CMenuManager::CONFIG_3:\n\t\t\t{\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_LL\"),  X(50.0f),  Y(-14.0f), PAD_TEXT_COLOR, true);  // -16.0f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_EXV\"), X(-4.0f),  Y(29.0f),  PAD_TEXT_COLOR, true);  // 33.142860f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_VES\"), X(-4.0f),  Y(65.0f),  PAD_TEXT_COLOR, true);  // 74.285721f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_VES\"), X(-4.0f),  Y(97.0f),  PAD_TEXT_COLOR, true);  // 110.857147f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_RS3\"), X(84.0f),  Y(162.0f), PAD_TEXT_COLOR, false); // 185.142868f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_CAM\"), X(103.0f), Y(141.0f), PAD_TEXT_COLOR, false); // 161.142868f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_PAU\"), X(130.0f), Y(128.0f), PAD_TEXT_COLOR, false); // 146.285721f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_LB\"),  X(68.0f),  Y(-6.0f),  PAD_TEXT_COLOR, false); // -6.857143f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_LR\"),  X(184.0f), Y(-14.0f), PAD_TEXT_COLOR, false); // -16.0f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_HOR\"), X(238.0f), Y(25.0f),  PAD_TEXT_COLOR, false); // 28.571430f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_BRA\"), X(155.0f), Y(18.0f),  PAD_TEXT_COLOR, true);  //  20.571430f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_HAB\"), X(238.0f), Y(52.0f),  PAD_TEXT_COLOR, false); // 59.428574f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_CAW\"), X(238.0f), Y(65.0f),  PAD_TEXT_COLOR, false); //  74.285721f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_ACC\"), X(238.0f), Y(78.0f),  PAD_TEXT_COLOR, false); // 89.142860f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_TUC\"), X(238.0f), Y(94.0f),  PAD_TEXT_COLOR, false); // 107.428574f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_SM3\"), X(238.0f), Y(109.0f), PAD_TEXT_COLOR, false); // 124.571434f\n\t\t\t\t\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t\n\t\t\tcase CMenuManager::CONFIG_4:\n\t\t\t{\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_LL\"),  X(50.0f),  Y(-14.0f), PAD_TEXT_COLOR, true);  // -16.0f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_HAB\"), X(-4.0f),  Y(29.0f),  PAD_TEXT_COLOR, true);  // 33.142860f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_TUC\"), X(-4.0f),  Y(65.0f),  PAD_TEXT_COLOR, true);  // 74.285721f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_VES\"), X(-4.0f),  Y(97.0f),  PAD_TEXT_COLOR, true);  // 110.857147f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_HO3\"), X(84.0f),  Y(162.0f), PAD_TEXT_COLOR, false); //  185.142868f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_CAM\"), X(103.0f), Y(141.0f), PAD_TEXT_COLOR, false); //  161.142868f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_PAU\"), X(130.0f), Y(128.0f), PAD_TEXT_COLOR, false); // 146.285721f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_LB\"),  X(68.0f),  Y(-6.0f),  PAD_TEXT_COLOR, false); //  -6.857143f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_LR\"),  X(184.0f), Y(-14.0f), PAD_TEXT_COLOR, false); // -16.0f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_CAW\"), X(238.0f), Y(25.0f),  PAD_TEXT_COLOR, false); //  28.571430f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_SMT\"), X(155.0f), Y(18.0f),  PAD_TEXT_COLOR, true);  //  20.571430f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_EXV\"), X(238.0f), Y(52.0f),  PAD_TEXT_COLOR, false); // 59.428574f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_RSC\"), X(238.0f), Y(65.0f),  PAD_TEXT_COLOR, false); //  74.285721f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_NA\"),  X(238.0f), Y(78.0f),  PAD_TEXT_COLOR, false); // 89.142860f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_ACC\"), X(238.0f), Y(94.0f),  PAD_TEXT_COLOR, false); // 107.428574f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_BRA\"), X(238.0f), Y(109.0f), PAD_TEXT_COLOR, false); // 124.571434f\n\t\t\t\t\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid InitialiseTextsInMenuControllerOnFoot(CMenuPictureAndText *widget, CMenuManager::CONTRCONFIG cont)\n{\n\tif ( widget )\n\t{\n\t\twidget->m_numTexts = 0;\n\t\t\n\t\t\n\t\tswitch ( cont )\n\t\t{\n\t\t\tcase CMenuManager::CONFIG_1:\n\t\t\t{\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_CWL\"),  X(50.0f),   Y(-14.0f), PAD_TEXT_COLOR, true);  // -16.0f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_LOF\"),  X(-4.0f),   Y(25.0f),  PAD_TEXT_COLOR, true);  // 28.571430f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_MOV\"),  X(-4.0f),   Y(65.0f),  PAD_TEXT_COLOR, true);  // 74.285721f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_MOV\"),  X(-4.0f),   Y(97.0f),  PAD_TEXT_COLOR, true);  // 110.857147f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_CAM\"),  X(103.0f),  Y(141.0f), PAD_TEXT_COLOR, false); // 161.142868f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_PAU\"),  X(130.0f),  Y(128.0f), PAD_TEXT_COLOR, false); // 146.285721f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_CWR\"),  X(184.0f),  Y(-14.0f), PAD_TEXT_COLOR, false); // -16.0f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_TAR\"),  X(238.0f),  Y(25.0f),  PAD_TEXT_COLOR, false); // 28.571430f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_JUM\"),  X(144.0f),  Y(18.0f),  PAD_TEXT_COLOR, true);  // 20.571430f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_ENV\"),  X(238.0f),  Y(52.0f),  PAD_TEXT_COLOR, false); // 59.428574f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_ATT\"),  X(238.0f),  Y(65.0f),  PAD_TEXT_COLOR, false); // 74.285721f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_RUN\"),  X(238.0f),  Y(78.0f),  PAD_TEXT_COLOR, false); // 89.142860f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_FPC\"),  X(238.0f),  Y(94.0f),  PAD_TEXT_COLOR, false); // 107.428574f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_LB3\"),  X(238.0f),  Y(109.0f), PAD_TEXT_COLOR, false); // 124.571434f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_R3\"),   X(238.0f),  Y(122.0f), PAD_TEXT_COLOR, false); // 139.428574f\n\t\t\t\t\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\n\t\t\tcase CMenuManager::CONFIG_2:\n\t\t\t{\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_CWL\"),  X(50.0f),   Y(-14.0f), PAD_TEXT_COLOR, true);  // -16.0f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_LOF\"),  X(-4.0f),   Y(25.0f),  PAD_TEXT_COLOR, true);  // 28.571430f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_CAM\"),  X(-4.0f),   Y(65.0f),  PAD_TEXT_COLOR, true);  // 74.285721f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_MOV\"),  X(-4.0f),   Y(97.0f),  PAD_TEXT_COLOR, true);  // 110.857147f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_NA\"),   X(103.0f),  Y(141.0f), PAD_TEXT_COLOR, false); // 161.142868f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_PAU\"),  X(130.0f),  Y(128.0f), PAD_TEXT_COLOR, false); // 146.285721f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_CWR\"),  X(184.0f),  Y(-14.0f), PAD_TEXT_COLOR, false); // -16.0f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_TAR\"),  X(238.0f),  Y(25.0f),  PAD_TEXT_COLOR, false); // 28.571430f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_JUM\"),  X(144.0f),  Y(18.0f),  PAD_TEXT_COLOR, true);  // 20.571430f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_ENV\"),  X(238.0f),  Y(52.0f),  PAD_TEXT_COLOR, false); // 59.428574f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_ATT\"),  X(238.0f),  Y(65.0f),  PAD_TEXT_COLOR, false); // 74.285721f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_RUN\"),  X(238.0f),  Y(78.0f),  PAD_TEXT_COLOR, false); // 89.142860f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_FPC\"),  X(238.0f),  Y(94.0f),  PAD_TEXT_COLOR, false); // 107.428574f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_LB3\"),  X(238.0f),  Y(109.0f), PAD_TEXT_COLOR, false); // 124.571434f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_R3\"),   X(238.0f),  Y(122.0f), PAD_TEXT_COLOR, false); // 139.428574f\n\t\t\t\t\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\n\t\t\tcase CMenuManager::CONFIG_3:\n\t\t\t{\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_CWL\"),  X(50.0f),   Y(-14.0f), PAD_TEXT_COLOR, true);  // -16.0f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_ENV\"),  X(-4.0f),   Y(25.0f),  PAD_TEXT_COLOR, true);  // 28.571430f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_MOV\"),  X(-4.0f),   Y(65.0f),  PAD_TEXT_COLOR, true);  // 74.285721f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_MOV\"),  X(-4.0f),   Y(97.0f),  PAD_TEXT_COLOR, true);  // 110.857147f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_CAM\"),  X(103.0f),  Y(141.0f), PAD_TEXT_COLOR, false); // 161.142868f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_PAU\"),  X(130.0f),  Y(128.0f), PAD_TEXT_COLOR, false); // 146.285721f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_CWR\"),  X(184.0f),  Y(-14.0f), PAD_TEXT_COLOR, false); // -16.0f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_TAR\"),  X(238.0f),  Y(25.0f),  PAD_TEXT_COLOR, false); // 28.571430f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_JUM\"),  X(144.0f),  Y(18.0f),  PAD_TEXT_COLOR, true);  // 20.571430f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_LOF\"),  X(238.0f),  Y(52.0f),  PAD_TEXT_COLOR, false); // 59.428574f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_RUN\"),  X(238.0f),  Y(65.0f),  PAD_TEXT_COLOR, false); // 74.285721f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_ATT\"),  X(238.0f),  Y(78.0f),  PAD_TEXT_COLOR, false); // 89.142860f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_FPC\"),  X(238.0f),  Y(94.0f),  PAD_TEXT_COLOR, false); // 107.428574f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_LB3\"),  X(238.0f),  Y(109.0f), PAD_TEXT_COLOR, false); // 124.571434f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_R3\"),   X(238.0f),  Y(122.0f), PAD_TEXT_COLOR, false); // 139.428574f\n\t\t\t\t\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t\n\t\t\tcase CMenuManager::CONFIG_4:\n\t\t\t{\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_CWL\"),  X(50.0f),   Y(-14.0f), PAD_TEXT_COLOR, true);  // -16.0f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_TAR\"),  X(-4.0f),   Y(25.0f),  PAD_TEXT_COLOR, true);  // 28.571430f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_NA\"),   X(-4.0f),   Y(65.0f),  PAD_TEXT_COLOR, true);  // 74.285721f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_MOV\"),  X(-4.0f),   Y(97.0f),  PAD_TEXT_COLOR, true);  // 110.857147f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_CAM\"),  X(103.0f),  Y(141.0f), PAD_TEXT_COLOR, false); // 161.142868f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_PAU\"),  X(130.0f),  Y(128.0f), PAD_TEXT_COLOR, false); // 146.285721f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_CWR\"),  X(184.0f),  Y(-14.0f), PAD_TEXT_COLOR, false); // -16.0f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_ATT\"),  X(238.0f),  Y(25.0f),  PAD_TEXT_COLOR, false); // 28.571430f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_JUM\"),  X(144.0f),  Y(18.0f),  PAD_TEXT_COLOR, true);  // 20.571430f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_ENV\"),  X(238.0f),  Y(52.0f),  PAD_TEXT_COLOR, false); // 59.428574f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_LOF\"),  X(238.0f),  Y(65.0f),  PAD_TEXT_COLOR, false); // 74.285721f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_RUN\"),  X(238.0f),  Y(78.0f),  PAD_TEXT_COLOR, false); // 89.142860f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_FPC\"),  X(238.0f),  Y(94.0f),  PAD_TEXT_COLOR, false); // 107.428574f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_LB3\"),  X(238.0f),  Y(109.0f), PAD_TEXT_COLOR, false); // 124.571434f\n\t\t\t\twidget->AddText(TheText.Get(\"FEC_R3\"),   X(238.0f),  Y(122.0f), PAD_TEXT_COLOR, false); // 139.428574f\n\t\t\t\t\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nTriggerSaveZone_BackToMainMenuTwoLines(CMenuMultiChoiceTwoLinesTriggered *widget)\n{\n\tbMemoryCardSpecialZone = false;\n\tbIgnoreTriangleButton = false;\n\tpActiveMenuPage = &MenuPageSaveZone_SaveGame;\n}\n\nvoid\nTriggerSave_BackToMainMenuTwoLines(CMenuMultiChoiceTwoLinesTriggered *widget)\n{\n\tpMenuSave = &MenuPage_SaveBasic;\n\tpMenuSave->ActivatePage();\n\tbMemoryCardSpecialZone = false;\n\tbIgnoreTriangleButton = false;\n}\n\nvoid\nSetRandomActiveTextlineColor(uint8 bText)\n{\n\tif ( bMemoryCardSpecialZone )\n\t\trgbaATC = SELECTED_TEXT_COLOR;\n\telse\n\t{\n\t\tbool bSelected = false;\n\t\tbool bHighlignted = false;\n\t\t\n\t\tswitch ( FrontEndMenuManager.m_pageState )\n\t\t{\n\t\t\tcase PAGESTATE_NORMAL:\n\t\t\t\tbreak;\n\t\t\tcase PAGESTATE_HIGHLIGHTED:\n\t\t\t\tbHighlignted = true;\n\t\t\t\tbreak;\n\t\t\tcase PAGESTATE_SELECTED:\n\t\t\t\tbSelected = true;\n\t\t\t\tbreak;\n\t\t}\n\t\t\n\t\tif ( FrontEndMenuManager.m_bInSaveZone )\n\t\t\tbSelected = true;\n\t\t\n\t\tif ( bSelected || bText )\n\t\t{\n\t\t\tstatic uint32 delayTime = 0;\n\t\t\tstatic bool bAddVal = true;\n\t\t\t\n\t\t\tif ( delayTime < CTimer::GetTimeInMillisecondsPauseMode() )\n\t\t\t{\n\t\t\t\tdelayTime = CTimer::GetTimeInMillisecondsPauseMode() + 200;\n\t\t\t\t\n\t\t\t\tif ( bAddVal )\n\t\t\t\t\trgbaATC = TEXT_COLOR;\n\t\t\t\telse\n\t\t\t\t\trgbaATC = SELECTED_TEXT_COLOR;\n\t\t\t\t\n\t\t\t\tbAddVal = !bAddVal;\n\t\t\t}\n\t\t}\n\t\t\n\t\tif ( bHighlignted )\n\t\t{\n\t\t\tstatic uint32 delayTime = 0;\n\t\t\tstatic bool bAddVal = true;\n\t\t\t\n\t\t\tif ( delayTime < CTimer::GetTimeInMillisecondsPauseMode() )\n\t\t\t{\n\t\t\t\tdelayTime = CTimer::GetTimeInMillisecondsPauseMode() + 200;\n\t\t\t\t\n\t\t\t\tif ( bAddVal )\n\t\t\t\t\trgbaATC = TITLE_TEXT_COLOR;\n\t\t\t\telse\n\t\t\t\t\trgbaATC = MENU_SELECTED_COLOR;\n\t\t\t\t\n\t\t\t\tbAddVal = !bAddVal;\n\t\t\t}\n\t\t}\n\t}\n}\n\n#ifdef GTA_PC\n\nvoid\nTriggerDisplay_Trails(CMenuOnOffTriggered *widget)\n{\n\tif ( widget )\n\t{\n\t\tCMenuManager::m_PrefsShowTrails = widget->GetMenuSelection();\n\t\tCMBlur::BlurOn = CMenuManager::m_PrefsShowTrails;\n\t\t\n\t\tif ( CMBlur::BlurOn )\n\t\t\tCMBlur::MotionBlurOpen(Scene.camera);\n\t\telse\n\t\t\tCMBlur::MotionBlurClose();\n\t}\n}\n\n#endif"
  },
  {
    "path": "src/core/Frontend_PS2.cpp",
    "content": "#include \"common.h\"\n#ifdef PS2_MENU\n#include \"platform.h\"\n#include \"main.h\"\n#include \"Timer.h\"\n#include \"Pad.h\"\n#include \"Sprite2d.h\"\n#include \"Text.h\"\n#include \"Font.h\"\n#include \"Hud.h\"\n#include \"MBlur.h\"\n#include \"DMAudio.h\"\n#include \"Streaming.h\"\n#include \"Camera.h\"\n#include \"Credits.h\"\n#include \"General.h\"\n#include \"TxdStore.h\"\n#include \"FileMgr.h\"\n#include \"Messages.h\"\n#include \"Frontend_PS2.h\"\n#include \"Stats.h\"\n#include \"Game.h\"\n#include \"World.h\"\n#include \"PlayerInfo.h\"\n#include \"FrontEndControls.h\"\n#include \"MemoryCard.h\"\n\n#define CRect_SZ(x, y, w, h) CRect(x, y, x+w, y+h)\n\nwchar MemoryCard_FileNames[8][100+1];\nCMenuManager FrontEndMenuManager;\n\n// TEMP: put into header\nbool DoRWStuffStartOfFrame_Horizon(int16 TopRed, int16 TopGreen, int16 TopBlue, int16 BottomRed, int16 BottomGreen, int16 BottomBlue, int16 Alpha);\nbool DoRWStuffStartOfFrame(int16 TopRed, int16 TopGreen, int16 TopBlue, int16 BottomRed, int16 BottomGreen, int16 BottomBlue, int16 Alpha);\nvoid DoRWStuffEndOfFrame(void);\n\n\n#define SCRW SCREEN_WIDTH\n#define SCRH SCREEN_HEIGHT\n//#define X SCREEN_STRETCH_X\n//#define Y SCREEN_STRETCH_Y\n#define X SCREEN_SCALE_X\n#define Y SCREEN_SCALE_Y\n\n#define YF(x) Y(float(x)*(float(DEFAULT_SCREEN_HEIGHT)/float(SCREEN_HEIGHT_PAL)))\n//#define X(x) ((x)/640.0f*SCRW)\n//#define Y(y) ((y)/448.0f*SCRH)\n\n\nstatic float MENU_TEXT_SIZE_X = 0.644f;\nstatic float MENU_TEXT_SIZE_Y = 0.84f;\t//0.96f;\nfloat BUTTONTAB_TEXT_SIZE_X = 0.35f;\nfloat BUTTONTAB_TEXT_SIZE_Y = 0.7f; //0.8f;\nfloat PANEL_TEXT_SIZE_X = 0.8f;\nfloat PANEL_TEXT_SIZE_Y = 1.2f;\t//0.96f/0.7f;\t//??\nfloat MEMCARD_ACCESS_MSG_SIZE_X = 0.84f;\nfloat MEMCARD_ACCESS_MSG_SIZE_Y = 1.12f;\t//1.28f;\n\nCRGBA SELECTED_TEXT_COLOR(255, 182, 48, 255);\nCRGBA BACKGROUND_SPLASH_COLOR(48, 48, 48, 255);\n\nCVector2D CONTR_DESCR_NEW_TEXTSCALE(0.4564f, 0.63f);\t// 0.72\nCVector2D CONFIGS_NEW_TEXTSCALE(0.49f, 0.7f);\t// 0.8\nCVector2D AUDIO_OUTPUT_POS(0.0f, 0.0f);\nCVector2D AUDIO_RSTATION_POS(154.0f, 0.0f);\nCVector2D DISPLAY_BRIGHTNESS_POS(0.0f, 0.0f);\n\nCRGBA TEXT_COLOR(150, 110, 30, 255);\nCRGBA PAD_TEXT_COLOR(200, 200, 200, 255);\nCRGBA CRIM_RATING_TEXT_COLOR(255, 182, 48, 255);\nCRGBA SCROLL_TEXT_COLOR(150, 110, 30, 255);\nCRGBA TITLE_TEXT_COLOR(170, 130, 50, 255);\nCRGBA TEXT_SHADOW_COLOR(0, 0, 0, 255);\nCVector2D SHADOW_VECTOR(1.0f, 1.0f);\nCRGBA SLIDER_RIGHT_COLOR(20, 94, 136, 255);\nCRGBA SLIDER_LEFT_COLOR(86, 196, 255, 255);\nCRGBA MENU_SELECTED_COLOR(255, 212, 88, 255);\nCRGBA rgbaATC(96, 96, 96, 255);\t// active text color. not constant\n\nfloat BUTTONTAB_TEXT_X_SCALES[NUM_PAGES] = { 1.0f };\nfloat PANEL_TEXT_X_SCALES[NUM_PAGES] = { 1.0f };\n\nint32 MemoryCardSlotSelected;\nuint32 TimeToStopPadShaking;\nbool bFrontEnd_ReloadObrTxtGxt;\n\nbool bMemoryCardStartUpMenus_ExitNow;\n\nextern CMenuPage MenuPage_SaveBasic;\nCMenuPage *pActiveMenuPage;\nCMenuPage *pMenuSave = &MenuPage_SaveBasic;\nbool bMemoryCardSpecialZone;\nbool bIgnoreTriangleButton;\nbool gErrorSampleTriggered;\n\nbool gMusicPlaying;\n\nCMenuPage MenuPage_Stats;\n CMenuLineLister MenuStats_1;\n CMenuPictureAndText MenuStats_2;\t// criminal rating\nCMenuPage MenuPage_Briefs;\n CMenuPictureAndText MenuBriefs_1;\n CMenuDummy MenuBriefs_2;\nCMenuPage MenuPage_SaveBasic;\n CMenuMultiChoiceTriggered MenuSaveB_1;\t// \"Load Game\", \"Delete Game\", \"New Game\"\nCMenuPage MenuPage_SaveNewGame;\n CMenuPictureAndText MenuSaveNG_1;\t// \"Load Game\", \"Delete Game\", \"New Game\"\n CMenuMultiChoiceTriggered MenuSaveNG_2;\t// \"No\", \"Yes\"\nCMenuPage MenuPage_SaveLoadGame;\n CMenuPictureAndText MenuSaveLG_1;\t// \"Load Game\", \"Delete Game\", \"New Game\"\n CMenuMultiChoiceTwoLinesTriggered MenuSaveLG_2;\t// save games\nCMenuPage MenuPage_SaveDeleteGame;\n CMenuPictureAndText MenuSaveDG_1;\t// \"Load Game\", \"Delete Game\", \"New Game\"\n CMenuMultiChoiceTwoLinesTriggered MenuSaveDG_2;\t// save games\nCMenuPage MenuPage_Controls;\n CMenuPictureAndText MenuControls_3; // controller images\n CMenuPictureAndText MenuControls_6;\n CMenuPictureAndText MenuControls_4;\n CMenuPictureAndText MenuControls_7;\n CMenuMultiChoiceTriggeredAlways MenuControls_1; // \"Configuration:\" \"Setup1\", \"Setup2\", \"Setup3\", \"Setup4\"\n CMenuMultiChoiceTriggered MenuControls_2; // \"Controller Display:\" \"On Foot\", \"In Car\"\n CMenuOnOffTriggered MenuControls_5; // \"Vibration:\"\nCMenuPageAnyMove MenuPage_Audio;\n CMenuSliderTriggered MenuAudio_1;\t// \"Music Volume\"\n CMenuMultiChoiceTriggered MenuAudio_4;\t// \"Output:\" \"Stereo\", \"Mono\"\n CMenuSliderTriggered MenuAudio_2;\t// \"SFX Volume\"\n CMenuMultiChoicePicturedTriggeredAnyMove MenuAudio_3; // \"Radio station select:\"\nCMenuPage MenuPage_Display;\n CMenuSlider MenuDisplay_1;\t// \"Brightness\"\n#ifdef GTA_PC\n CMenuOnOffTriggered MenuDisplay_2;\t// \"Trails:\"\n#else\n CMenuOnOff MenuDisplay_2;\t// \"Trails:\"\n#endif\n CMenuOnOff MenuDisplay_3;\t// \"Subtitles:\"\n CMenuOnOff MenuDisplay_4;\t// \"Wide Screen:\"\nCMenuPage MenuPage_Language;\n CMenuMultiChoiceTriggered MenuLanguage_1;\t// \"English\", \"French\", \"German\", \"Italian\", \"Spanish\"\n\nCMenuPage MenuPageSaveZone_SaveGame;\n CMenuMultiChoiceTriggered MenuSaveZoneSG_1;\t// \"Save game\", \"Cancel\"\nCMenuPage MenuPageSaveZone_SaveSlots;\n CMenuMultiChoiceTwoLinesTriggered MenuSaveZoneSSL_1;\t// \"Cancel\"\nCMenuPage MenuPageSaveZone_SavedSuccessfully;\n CMenuPictureAndText MenuSaveZoneSS_1;\t// \"Game saved successfully!\" \"Your saved filename is:\"\n CMenuMultiChoiceTriggered MenuSaveZoneSS_2;\t// \"Quit\"\nCMenuPage MenuPageSaveZone_Message;\n CMenuPictureAndText MenuSaveZoneMSG_1;\t// \"Save Failed! Check memory card (PS2) in MEMORY CARD slot 1 and please try again.\"\n CMenuMultiChoiceTriggered MenuSaveZoneMSG_2;\t// \"OK\"\nCMenuPage MenuPageSaveZone_QuestionYesNo;\n CMenuPictureAndText MenuSaveZoneQYN_1;\t// \"Save Failed! Check memory card (PS2) in MEMORY CARD slot 1 and please try again.\"\n CMenuMultiChoiceTriggered MenuSaveZoneQYN_2;\t// \"Yes\", \"No\"\nCMenuPage MenuPageSaveZone_FormatCard;\n CMenuMultiChoiceTriggered MenuSaveZoneFC_1;\t// \"Memory card (PS2) in MEMORY CARD slot 1 is unformatted. Would you like to format memory card (PS2) in MEMORY CARD slot 1?\" \"No\" \"Yes\"\nCMenuPage MenuPageSaveZone_ErrorFormat;\n CMenuMultiChoiceTriggered MenuSaveZoneEF_1;\t// \"Format Failed! Check memory card (PS2) in MEMORY CARD slot 1 and please try again.\" \"OK\"\n\n\nVALIDATE_SIZE(CPlaceableText, 0x10);\nVALIDATE_SIZE(CPlaceableShText, 0x20);\nVALIDATE_SIZE(CPlaceableShTextTwoLines, 0x30);\nVALIDATE_SIZE(CPlaceableShOption, 0x28);\nVALIDATE_SIZE(CPlaceableShOptionTwoLines, 0x38);\nVALIDATE_SIZE(CPlaceableSprite, 0x18);\nVALIDATE_SIZE(CPlaceableShSprite, 0x34);\nVALIDATE_SIZE(CMenuMultiChoice, 0x2CC);\nVALIDATE_SIZE(CMenuMultiChoiceTriggered, 0x310);\nVALIDATE_SIZE(CMenuMultiChoiceTwoLines, 0x3CC);\nVALIDATE_SIZE(CMenuOnOff, 0x90);\n\n#include \"FrontendTriggers.h\"\n\nstatic const char* FrontendFilenames[][2] =\n{\n\t{\"fe2_mainpanel_ul\",  \"\" },\n\t{\"fe2_mainpanel_ur\",  \"\" },\n\t{\"fe2_mainpanel_dl\",  \"\" },\n\t{\"fe2_mainpanel_dr\",  \"\" },\n\t{\"fe2_mainpanel_dr2\", \"\" },\n\t{\"fe2_tabactive\",     \"\" },\n\t{\"fe_iconbrief\",      \"\" },\n\t{\"fe_iconstats\",      \"\" },\n\t{\"fe_iconcontrols\",   \"\" },\n\t{\"fe_iconsave\",       \"\" },\n\t{\"fe_iconaudio\",      \"\" },\n\t{\"fe_icondisplay\",    \"\" },\n\t{\"fe_iconlanguage\",   \"\" },\n\t{\"fe_controller\",     \"\" },\n\t{\"fe_controllersh\",   \"\" },\n\t{\"fe_arrows1\",        \"\" },\n\t{\"fe_arrows2\",        \"\" },\n\t{\"fe_arrows3\",        \"\" },\n\t{\"fe_arrows4\",        \"\" },\n\t{\"fe_radio1\",         \"\" },\n\t{\"fe_radio2\",         \"\" },\n\t{\"fe_radio3\",         \"\" },\n\t{\"fe_radio4\",         \"\" },\n\t{\"fe_radio5\",         \"\" },\n\t{\"fe_radio6\",         \"\" },\n\t{\"fe_radio7\",         \"\" },\n\t{\"fe_radio8\",         \"\" },\n\t{\"fe_radio9\",         \"\" },\n};\n\n#ifdef CUTSCENE_BORDERS_SWITCH\nbool CMenuManager::m_PrefsCutsceneBorders = true;\n#endif\n\nint32 CMenuManager::m_PrefsSfxVolume = 102;\nint32 CMenuManager::m_PrefsMusicVolume = 102;\nint32 CMenuManager::m_PrefsBrightness = 256;\nbool CMenuManager::m_PrefsShowTrails = true;\nbool CMenuManager::m_PrefsShowSubtitles = true;\nbool CMenuManager::m_PrefsAllowNastyGame = true;\n\nint32 CMenuManager::m_PrefsRadioStation = 0;\nint32 CMenuManager::m_PrefsStereoMono = 0;\nint8 CMenuManager::m_PrefsUseWideScreen = 0;\nint32 CMenuManager::m_PrefsLanguage = 0;\nCMenuManager::CONTRCONFIG CMenuManager::m_PrefsControllerConfig = CONFIG_1;\nbool CMenuManager::m_PrefsUseVibration = false;\n\n\n#ifdef GTA_PC\n#include \"PlayerSkin.h\"\nint32 CMenuManager::OS_Language = 0;\nint8 CMenuManager::m_PrefsVsync = 1;\nint8 CMenuManager::m_PrefsVsyncDisp = 1;\nint8 CMenuManager::m_PrefsFrameLimiter = 1;\nint8 CMenuManager::m_PrefsSpeakers;\nint32 CMenuManager::m_ControlMethod = CONTROL_CLASSIC;\nint8 CMenuManager::m_PrefsDMA = 1;\nfloat CMenuManager::m_PrefsLOD = 1.0f;\nchar CMenuManager::m_PrefsSkinFile[256] = DEFAULT_SKIN_NAME;\n\n#ifndef MASTER\nbool CMenuManager::m_PrefsMarketing;\nbool CMenuManager::m_PrefsDisableTutorials;\n#endif // !MASTER\n\n#ifdef MENU_MAP\nbool  CMenuManager::bMenuMapActive;\nfloat CMenuManager::fMapSize;\nfloat CMenuManager::fMapCenterY;\nfloat CMenuManager::fMapCenterX;\n#endif\n\n#endif\n\n\nCMenuManager::CMenuManager(void)\n{\n\tint32 i;\n\n\tSetSoundLevelsForMusicMenu();\n\n\tm_pageState = PAGESTATE_NORMAL;\n\tm_currentPage = PAGE_FIRST;\n\tm_newPage = PAGE_FIRST;\n\tm_bMenuActive = false;\n\tm_bSaveMenuActive = false;\n\tm_bRenderGameInMenu = false;\n\tm_bTexturesLoaded = false;\n\tm_nPageLeftTimer = 0;\n\tm_nPageRightTimer = 0;\n\tm_nChangePageTimer = 0;\n\tfield_18 = 0;\n\tm_fade = 255;\n\tm_someAlpha = 255;\n\tm_position.x = 0.0f;\n\tm_position.y = 0.0f;\n\tm_nSlidingDir = SLIDE_TO_BOTTOM;\n\tm_nStartPauseTimer = 0;\n\tm_nEndPauseTimer = 0;\n\tm_bInitialised = false;\n\tm_bWantToUpdateContent = false;\n\tfield_3C = 0;\n\tm_bInSaveZone = false;\n\n\tfor(i = 0; i < NUM_PAGES; i++){\n\t\tBUTTONTAB_TEXT_X_SCALES[i] = 1.0f;\n\t\tPANEL_TEXT_X_SCALES[i] = 1.0f;\n\t}\n\n#ifdef GTA_PC\n\tTheCamera.m_bUseMouse3rdPerson = m_ControlMethod == CONTROL_STANDARD;\n\tCMBlur::BlurOn = m_PrefsShowTrails;\n#endif\n}\n\nvoid\nCMenuManager::LoadAllTextures(void)\n{\n\tint32 i;\n\n\tif(m_bTexturesLoaded)\n\t\treturn;\n\n\tDMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_STARTING, 0);\n\tDMAudio.Service();\n\tDoRWStuffStartOfFrame(0, 0, 0, 0, 0, 0, 255);\n\tRwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR);\n\tCSprite2d *splash = LoadSplash(nil);\n\tif(splash)\n\t\tsplash->Draw(CRect(0.0f, 0.0f, SCRW, SCRH), BACKGROUND_SPLASH_COLOR);\n\telse // doesn't exist!!\n\t\tCHud::Sprites[19].Draw(CRect(0.0f, 0.0f, SCRW, SCRH), BACKGROUND_SPLASH_COLOR);\n\tRwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERMIPNEAREST);\n\tDoRWStuffEndOfFrame();\n\n\tCFileMgr::SetDir(\"\");\n\tCFileMgr::SetDir(\"\");\n\n\tCTimer::Stop();\n\tCStreaming::MakeSpaceFor(60*1024);\n\tCStreaming::ImGonnaUseStreamingMemory();\n\tCGame::TidyUpMemory(false, true);\n\tint32 slot = CTxdStore::FindTxdSlot(\"frontend\");\n\tif(slot == -1)\n\t\tslot = CTxdStore::AddTxdSlot(\"frontend\");\n\tprintf(\"LOAD frontend\\n\");\n\tCTxdStore::LoadTxd(slot, \"MODELS/FRONTEND.TXD\");\n\tCTxdStore::SetCurrentTxd(slot);\n\tCStreaming::IHaveUsedStreamingMemory();\n\tCTimer::Update();\n\n\tfor(i = 0; i < NUM_SPRIRES; i++)\n\t{\n\t\tm_sprites[i].SetTexture(FrontendFilenames[i][0], FrontendFilenames[i][1]);\n\t\tm_sprites[i].SetAddressing(rwTEXTUREADDRESSBORDER);\n\t}\n\n\tm_bTexturesLoaded = true;\n}\n\nvoid\nCMenuManager::UnloadTextures(void)\n{\n\tint32 slot;\n\tint32 i;\n\n\tif ( !m_bTexturesLoaded )\n\t\treturn;\n\n\tslot = CTxdStore::FindTxdSlot(\"frontend\");\n#ifdef FIX_BUGS\n\tfor(i = 0; i < NUM_SPRIRES; i++)\n\t\tm_sprites[i].Delete();\n#endif\n\n\tprintf(\"REMOVE frontend\\n\");\n\tCTxdStore::RemoveTxd(slot);\n\tm_bTexturesLoaded = false;\n}\n\nvoid\nCMenuManager::InitialiseMenusOnce(void)\n{\n\tif(m_bInitialised)\n\t\treturn;\n\tm_bInitialised = true;\n\n\tInitialiseChangedLanguageSettings();\n\n\t// Normal menu\n\tMenuPage_Stats.Initialise();\n\tMenuPage_Briefs.Initialise();\n\tMenuPage_SaveBasic.Initialise();\n\tMenuPage_SaveNewGame.Initialise();\n\tMenuPage_SaveLoadGame.Initialise();\n\tMenuPage_SaveDeleteGame.Initialise();\n\tMenuPage_Controls.Initialise();\n\tMenuPage_Audio.Initialise();\n\tMenuPage_Display.Initialise();\n\tMenuPage_Language.Initialise();\n\n\t// Save menu\n\tMenuPageSaveZone_SaveGame.Initialise();\n\tMenuPageSaveZone_SaveSlots.Initialise();\n\tMenuPageSaveZone_SavedSuccessfully.Initialise();\n\tMenuPageSaveZone_Message.Initialise();\n\tMenuPageSaveZone_QuestionYesNo.Initialise();\n\tMenuPageSaveZone_FormatCard.Initialise();\n\tMenuPageSaveZone_ErrorFormat.Initialise();\n\n\t/* Stats */\n\n\tMenuStats_1.ResetNumberOfTextLines();\n\tMenuStats_1.SetPosition(X(75.0f), Y(70.0f));\n\tMenuStats_1.m_width = X(480.0f);\n\tMenuStats_1.m_height = Y(274.0f);\n\tMenuStats_1.field_10E8 = 0;\t// unknown\n\tMenuStats_1.m_lineSpacing = Y(20.0f);\n\tMenuStats_1.m_scrollSpeed = 1.0f;\n\tMenuStats_1.SetLinesColor(SCROLL_TEXT_COLOR);\n\tMenuStats_1.ResetNumberOfTextLines();\n\tMenuPage_Stats.AddMenu(&MenuStats_1);\n\tMenuStats_2.SetPosition(X(75.0f), Y(50.0f));\n\tMenuStats_2.SetTextsColor(CRIM_RATING_TEXT_COLOR);\n\tMenuPage_Stats.AddMenu(&MenuStats_2);\n\tMenuPage_Stats.SetShadows(true, TEXT_SHADOW_COLOR, SHADOW_VECTOR);\n\tMenuPage_Stats.ActivatePage();\n\n\n\tCVector2D saveGameTextScale(X(0.49f), Y(0.7f));\n\tCVector2D defaultTextScale(X(MENU_TEXT_SIZE_X), Y(MENU_TEXT_SIZE_Y));\n\n\t/* Basic Load/Delete/New Game */\n\n\tMenuSaveB_1.m_numOptions = 0;\n\tMenuSaveB_1.SetPosition(X(220.0f), Y(110.0f));\n\tMenuSaveB_1.AddOption(TheText.Get(\"FES_LGA\"), 0.0f, Y(20.0f), TriggerSave_LoadGameSelect, false, true);\n\tMenuSaveB_1.AddOption(TheText.Get(\"FES_DGA\"), 0.0f, Y(40.0f), TriggerSave_DeleteGameSelect, false, true);\n\tMenuSaveB_1.AddOption(TheText.Get(\"FES_NGA\"), 0.0f, Y(60.0f), TriggerSave_NewGameSelectYes, false, true);\n\tMenuSaveB_1.SetColors(TITLE_TEXT_COLOR, TEXT_COLOR, TEXT_COLOR);\n\tMenuPage_SaveBasic.AddMenu(&MenuSaveB_1);\n\tMenuPage_SaveBasic.SetShadows(true, TEXT_SHADOW_COLOR, SHADOW_VECTOR);\n\tMenuPage_SaveBasic.ActivatePage();\n\n\t/* New Game - but unused */\n\n\tMenuSaveNG_1.m_numTexts = 0;\n\tMenuSaveNG_1.SetPosition(X(220.0f), Y(110.0f));\n\tMenuSaveNG_1.AddText(TheText.Get(\"FES_LGA\"), 0.0f, Y(20.0f), TEXT_COLOR, true);\n\tMenuSaveNG_1.AddText(TheText.Get(\"FES_DGA\"), 0.0f, Y(40.0f), TEXT_COLOR, true);\n\tMenuSaveNG_1.AddText(TheText.Get(\"FES_NGA\"), 0.0f, Y(60.0f), SELECTED_TEXT_COLOR, true);\n\tMenuPage_SaveNewGame.AddMenu(&MenuSaveNG_1);\n\tMenuSaveNG_2.m_numOptions = 0;\n\tMenuSaveNG_2.SetPosition(X(250.0f), Y(170.0f));\n\tMenuSaveNG_2.AddOption(TheText.Get(\"FEM_NO\"), 0.0f, 0.0f, TriggerSave_BackToMainMenu, false, false);\n\tMenuSaveNG_2.AddOption(TheText.Get(\"FEM_YES\"), 0.0f, Y(20.0f), TriggerSave_NewGameSelectYes, false, false);\n\tMenuSaveNG_2.SetColors(TITLE_TEXT_COLOR, TEXT_COLOR, TEXT_COLOR);\n\tMenuSaveNG_2.m_defaultCancel = TriggerSave_BackToMainMenu;\n\tMenuPage_SaveNewGame.AddMenu(&MenuSaveNG_2);\n\tMenuPage_SaveNewGame.SetShadows(true, TEXT_SHADOW_COLOR, SHADOW_VECTOR);\n\tMenuPage_SaveNewGame.ActivatePage();\n\n\t/* Load Game */\n\n\tMenuSaveLG_1.m_numTexts = 0;\n\tMenuSaveLG_1.SetPosition(X(220.0f),  Y(110.0f));\n\tMenuSaveLG_1.AddText(TheText.Get(\"FES_LGA\"), 0.0f, Y(20.0f), SELECTED_TEXT_COLOR, true);\n\tMenuSaveLG_1.AddText(TheText.Get(\"FES_DGA\"), 0.0f, Y(40.0f), TEXT_COLOR, true);\n\tMenuSaveLG_1.AddText(TheText.Get(\"FES_NGA\"), 0.0f, Y(60.0f), TEXT_COLOR, true);\n\tMenuPage_SaveLoadGame.AddMenu(&MenuSaveLG_1);\n\tMenuSaveLG_2.m_numOptions = 0;\n\tMenuSaveLG_2.SetPosition(X(250.0f),  Y(60.0f));\n\tMenuSaveLG_2.SetColors(TITLE_TEXT_COLOR, TEXT_COLOR, TEXT_COLOR);\n\tMenuSaveLG_2.m_defaultCancel = TriggerSave_BackToMainMenuTwoLines;\n\tMenuSaveLG_2.SetNewOldTextScale(true, saveGameTextScale, defaultTextScale, false);\n\tMenuPage_SaveLoadGame.AddMenu(&MenuSaveLG_2);\n\tMenuPage_SaveLoadGame.SetShadows(true, TEXT_SHADOW_COLOR, SHADOW_VECTOR);\n\tMenuPage_SaveLoadGame.ActivatePage();\n\n\t/* Delete Game */\n\n\tMenuSaveDG_1.m_numTexts = 0;\n\tMenuSaveDG_1.SetPosition(X(220.0f),  Y(110.0f));\n\tMenuSaveDG_1.AddText(TheText.Get(\"FES_LGA\"), 0.0f, Y(20.0f), TEXT_COLOR, true);\n\tMenuSaveDG_1.AddText(TheText.Get(\"FES_DGA\"), 0.0f, Y(40.0f), SELECTED_TEXT_COLOR, true);\n\tMenuSaveDG_1.AddText(TheText.Get(\"FES_NGA\"), 0.0f, Y(60.0f), TEXT_COLOR, true);\n\tMenuPage_SaveDeleteGame.AddMenu(&MenuSaveDG_1);\n\tMenuSaveDG_2.m_numOptions = 0;\n\tMenuSaveDG_2.SetPosition(X(250.0f),  Y(60.0f));\n\tMenuSaveDG_2.SetColors(TITLE_TEXT_COLOR, TEXT_COLOR, TEXT_COLOR);\n\tMenuSaveDG_2.m_defaultCancel = TriggerSave_BackToMainMenuTwoLines;\n\tMenuSaveDG_2.SetNewOldTextScale(true, saveGameTextScale, defaultTextScale, false);\n\tMenuPage_SaveDeleteGame.AddMenu(&MenuSaveDG_2);\n\tMenuPage_SaveDeleteGame.SetShadows(true, TEXT_SHADOW_COLOR, SHADOW_VECTOR);\n\tMenuPage_SaveDeleteGame.ActivatePage();\n\n\n\tCVector2D briefsTextScale(X(0.525f), Y(0.7f));\n\tCVector2D defaultTextScale1(X(MENU_TEXT_SIZE_X), Y(MENU_TEXT_SIZE_Y));\n\n\t/* Briefs */\n\n\tMenuBriefs_1.m_numTexts = 0;\n\tMenuBriefs_1.SetPosition(X(60.0f), Y(60.0f));\n\tMenuBriefs_1.SetTextsColor(TEXT_COLOR);\n\tMenuBriefs_1.SetNewOldTextScale(true, briefsTextScale, defaultTextScale1);\n\tMenuBriefs_1.SetNewOldShadowWrapX(true, X(600.0f+SHADOW_VECTOR.x), X(600.0f));\n\tMenuPage_Briefs.AddMenu(&MenuBriefs_1);\n\tMenuPage_Briefs.AddMenu(&MenuBriefs_2);\n\tMenuPage_Briefs.SetShadows(true, TEXT_SHADOW_COLOR, SHADOW_VECTOR);\n\tMenuPage_Briefs.ActivatePage();\n\n\n\tCVector2D defaultTextScale2(X(MENU_TEXT_SIZE_X), Y(MENU_TEXT_SIZE_Y));\n\tCVector2D defaultTextScale3(X(MENU_TEXT_SIZE_X), Y(MENU_TEXT_SIZE_Y));\n\tCVector2D CONTR_DESCR_NEW_TEXTSCALE_scaled(X(CONTR_DESCR_NEW_TEXTSCALE.x), Y(CONTR_DESCR_NEW_TEXTSCALE.y));\n\tCVector2D CONFIGS_NEW_TEXTSCALE_scaled(X(CONFIGS_NEW_TEXTSCALE.x), Y(CONFIGS_NEW_TEXTSCALE.y));\n\n\t/* Controls */\n\n\tMenuControls_3.m_numTexts = 0;\n\tMenuControls_3.m_numSprites = 0;\n\tMenuControls_3.SetPosition(X(170.0f), Y(88.0f));\n\tMenuControls_3.AddPicture(&m_sprites[FE_CONTROLLER],\n\t\t&m_sprites[FE_CONTROLLERSH],\n\t\t0.0f, 0.0f, X(235.2f), Y(175.2), CRGBA(255, 255, 255, 255));\n\tMenuControls_3.AddPicture(&m_sprites[FE_ARROWS1],\n\t\t0.0f, 0.0f, X(235.2f), Y(175.2), CRGBA(255, 255, 255, 255));\n\tMenuControls_3.SetNewOldTextScale(true, CONTR_DESCR_NEW_TEXTSCALE_scaled, defaultTextScale2);\n\tInitialiseTextsInMenuControllerOnFoot(&MenuControls_3, CMenuManager::m_PrefsControllerConfig);\n\tMenuControls_3.SetShadows(true, TEXT_SHADOW_COLOR, SHADOW_VECTOR);\n\tMenuControls_3.SetNewOldShadowWrapX(true, X(600.0f+SHADOW_VECTOR.x), X(600.0f));\n\tMenuPage_Controls.AddMenu(&MenuControls_3);\n\n\tMenuControls_6.m_numTexts = 0;\n\tMenuControls_6.m_numSprites = 0;\n\tMenuControls_6.SetPosition(X(170.0f), Y(88.0f));\n\tMenuControls_6.AddPicture(&m_sprites[FE_CONTROLLER],\n\t\t&m_sprites[FE_CONTROLLERSH],\n\t\t0.0f, 0.0f, X(235.2f), Y(175.2), CRGBA(255, 255, 255, 255));\n\tMenuControls_6.AddPicture(&m_sprites[FE_ARROWS3],\n\t\t0.0f, 0.0f, X(235.2f), Y(175.2), CRGBA(255, 255, 255, 255));\n\tMenuControls_6.SetNewOldTextScale(true, CONTR_DESCR_NEW_TEXTSCALE_scaled, defaultTextScale2);\n\tInitialiseTextsInMenuControllerOnFoot(&MenuControls_6, CMenuManager::CONFIG_2);\n\tMenuControls_6.SetShadows(true, TEXT_SHADOW_COLOR, SHADOW_VECTOR);\n\tMenuControls_6.SetNewOldShadowWrapX(true, X(600.0f+SHADOW_VECTOR.x), X(600.0f));\n\n\tMenuControls_4.m_numTexts = 0;\n\tMenuControls_4.m_numSprites = 0;\n\tMenuControls_4.SetPosition(X(170.0f), Y(88.0f));\n\tMenuControls_4.AddPicture(&m_sprites[FE_CONTROLLER],\n\t\t&m_sprites[FE_CONTROLLERSH],\n\t\t0.0f, 0.0f, X(235.2f), Y(175.2), CRGBA(255, 255, 255, 255));\n\tMenuControls_4.AddPicture(&m_sprites[FE_ARROWS2],\n\t\t0.0f, 0.0f, X(235.2f), Y(175.2), CRGBA(255, 255, 255, 255));\n\tMenuControls_4.SetNewOldTextScale(true, CONTR_DESCR_NEW_TEXTSCALE_scaled, defaultTextScale2);\n\tInitialiseTextsInMenuControllerInCar(&MenuControls_4, CMenuManager::m_PrefsControllerConfig);\n\tMenuControls_4.SetShadows(true, TEXT_SHADOW_COLOR, SHADOW_VECTOR);\n\tMenuControls_4.SetNewOldShadowWrapX(true, X(600.0f+SHADOW_VECTOR.x), X(600.0f));\n\n\tMenuControls_7.m_numTexts = 0;\n\tMenuControls_7.m_numSprites = 0;\n\tMenuControls_7.SetPosition(X(170.0f), Y(88.0f));\n\tMenuControls_7.AddPicture(&m_sprites[FE_CONTROLLER],\n\t\t&m_sprites[FE_CONTROLLERSH],\n\t\t0.0f, 0.0f, X(235.2f), Y(175.2), CRGBA(255, 255, 255, 255));\n\tMenuControls_7.AddPicture(&m_sprites[FE_ARROWS4],\n\t\t0.0f, 0.0f, X(235.2f), Y(175.2), CRGBA(255, 255, 255, 255));\n\tMenuControls_7.SetNewOldTextScale(true, CONTR_DESCR_NEW_TEXTSCALE_scaled, defaultTextScale2);\n\tInitialiseTextsInMenuControllerInCar(&MenuControls_7, CMenuManager::CONFIG_2);\n\tMenuControls_7.SetShadows(true, TEXT_SHADOW_COLOR, SHADOW_VECTOR);\n\tMenuControls_7.SetNewOldShadowWrapX(true, X(600.0f+SHADOW_VECTOR.x), X(600.0f));\n\n\tMenuControls_1.m_numOptions = 0;\n\tMenuControls_1.SetPosition(X(284.0f), Y(290.0f));\n\tMenuControls_1.SetColors(TITLE_TEXT_COLOR, TEXT_COLOR, SELECTED_TEXT_COLOR);\n\tMenuControls_1.SetNewOldTextScale(true, CONFIGS_NEW_TEXTSCALE_scaled, defaultTextScale3, false);\n\tMenuControls_1.AddTitle(TheText.Get(\"FEC_CCF\"), 0.0f, 0.0f, true);\n\tMenuControls_1.AddOption(TheText.Get(\"FEC_CF1\"), X(15.0f), Y(2.0f), TriggerControls_ContrConfig, false, false);\n\tMenuControls_1.AddOption(TheText.Get(\"FEC_CF2\"), X(85.0f), Y(2.0f), TriggerControls_ContrConfig, false, false);\n\tMenuControls_1.AddOption(TheText.Get(\"FEC_CF3\"), X(155.0f), Y(2.0f), TriggerControls_ContrConfig, false, false);\n\tMenuControls_1.AddOption(TheText.Get(\"FEC_CF4\"), X(225.0f), Y(2.0f), TriggerControls_ContrConfig, false, false);\n\tMenuPage_Controls.AddMenu(&MenuControls_1);\n\tMenuControls_1.m_alwaysTrigger = (CMenuMultiChoiceTriggered::Trigger)TriggerControls_DrawContrConfig;\n\tMenuControls_1.m_alwaysHighlightTrigger = (CMenuMultiChoiceTriggered::Trigger)TriggerControls_DrawHNContrConfig;\n\tMenuControls_1.m_alwaysNormalTrigger = (CMenuMultiChoiceTriggered::Trigger)TriggerControls_DrawHNContrConfig;\n\n\tMenuControls_2.m_numOptions = 0;\n\tMenuControls_2.SetPosition(X(284.0f), Y(310.0f));\n\tMenuControls_2.SetColors(TITLE_TEXT_COLOR, TEXT_COLOR, SELECTED_TEXT_COLOR);\n\tMenuControls_2.SetNewOldTextScale(true, CONFIGS_NEW_TEXTSCALE_scaled, defaultTextScale3, false);\n\tMenuControls_2.AddTitle(TheText.Get(\"FEC_CDP\"), 0.0f, 0.0f, true);\n\tMenuControls_2.AddOption(TheText.Get(\"FEC_ONF\"), X(15.0f), Y(2.0f), (CMenuMultiChoiceTriggered::Trigger)TriggerControls_ContrDisplay, false, false);\n\tMenuControls_2.AddOption(TheText.Get(\"FEC_INC\"), X(105.0f), Y(2.0f), (CMenuMultiChoiceTriggered::Trigger)TriggerControls_ContrDisplay, false, false);\n\tMenuPage_Controls.AddMenu(&MenuControls_2);\n\tMenuControls_2.m_bTwoState = true;\n\tMenuControls_2.SetMenuSelection(0);\n\n\tMenuControls_5.SetPosition(X(284.0f), Y(330.0f));\n\tMenuControls_5.SetColors(TITLE_TEXT_COLOR, TEXT_COLOR);\n\tMenuControls_5.SetNewOldTextScale(true, CONFIGS_NEW_TEXTSCALE_scaled, defaultTextScale3, false);\n\tMenuControls_5.AddTitle(TheText.Get(\"FEC_VIB\"), false, 0.0f, 0.0f, true);\n\tMenuControls_5.SetOptionPosition(X(15.0f), Y(2.0f), TriggerControls_Vibrations, false);\n\tMenuPage_Controls.AddMenu(&MenuControls_5);\n\tMenuPage_Controls.SetShadows(true, TEXT_SHADOW_COLOR, SHADOW_VECTOR);\n\tMenuPage_Controls.ActivatePage();\n\n\n\t/* Audio */\n\n\tCVector2D audioOutputScale(X(0.49f), Y(0.63f));\n\tCVector2D defaultTextScale4(X(MENU_TEXT_SIZE_X), Y(MENU_TEXT_SIZE_Y));\n\n\tFEC_MOVETAB movetab;\n\tMenuAudio_1.SetPosition(X(70.0f), Y(80.0f));\n\tMenuAudio_1.SetColors(TEXT_COLOR, TEXT_COLOR, SLIDER_LEFT_COLOR, SLIDER_RIGHT_COLOR);\n\tMenuAudio_1.AddTitle(TheText.Get(\"FEA_MUS\"), 0.0f, 0.0f);\n\tMenuAudio_1.AddTickBox(X(15.0f), Y(20.0f), X(150.0f), Y(5.0f), Y(45.0f), TriggerAudio_MusicVolume, TriggerAudio_MusicVolumeAlways);\n\tmovetab.right = 1;\n\tmovetab.left = 2;\n\tmovetab.down = 3;\n\tmovetab.up = 3;\n\tMenuPage_Audio.AddMenu(&MenuAudio_1, &movetab);\n\n\tMenuAudio_4.m_numOptions = 0;\n\tMenuAudio_4.SetPosition(X(280.0f), Y(80.0f));\n\tMenuAudio_4.SetColors(TITLE_TEXT_COLOR, TEXT_COLOR, SELECTED_TEXT_COLOR);\n\tMenuAudio_4.SetNewOldTextScale(true, audioOutputScale, defaultTextScale4, false);\n\tMenuAudio_4.AddTitle(TheText.Get(\"FEA_OUT\"), X(AUDIO_OUTPUT_POS.x), Y(AUDIO_OUTPUT_POS.y), false);\n\tMenuAudio_4.AddOption(TheText.Get(\"FEA_ST\"), X(-15.0f), Y(30.0f), TriggerAudio_StereoMono, false, false);\n\tMenuAudio_4.AddOption(TheText.Get(\"FEA_MNO\"), X(55.0f), Y(30.0f), TriggerAudio_StereoMono, false, false);\n\tmovetab.right = 2;\n\tmovetab.left = 0;\n\tmovetab.down = 3;\n\tmovetab.up = 3;\n\tMenuPage_Audio.AddMenu(&MenuAudio_4, &movetab);\n\tMenuAudio_4.m_bTwoState = true;\n\n\tMenuAudio_2.SetPosition(X(410.0f), Y(80.0f));\n\tMenuAudio_2.SetColors(TEXT_COLOR, TEXT_COLOR, SLIDER_LEFT_COLOR, SLIDER_RIGHT_COLOR);\n\tMenuAudio_2.AddTitle(TheText.Get(\"FEA_SFX\"), 0.0f, 0.0f);\n\tMenuAudio_2.AddTickBox(X(5.0f), Y(20.0f), X(150.0f), Y(5.0f), Y(45.0f), TriggerAudio_SfxVolume, TriggerAudio_SfxVolumeAlways);\n\tmovetab.right = 0;\n\tmovetab.left = 1;\n\tmovetab.down = 3;\n\tmovetab.up = 3;\n\tMenuPage_Audio.AddMenu(&MenuAudio_2, &movetab);\n\n\tMenuAudio_3.m_numOptions = 0;\n\tMenuAudio_3.SetPosition(X(50.0f), Y(170.0f));\n\tMenuAudio_3.SetColors(TITLE_TEXT_COLOR, CRGBA(64, 64, 64, 255), CRGBA(250, 250, 250, 255));\n\tMenuAudio_3.AddTitle(TheText.Get(\"FEA_RSS\"), X(AUDIO_RSTATION_POS.x), Y(AUDIO_RSTATION_POS.y), false);\n\t// first row\n\tmovetab.right = 1;\n\tmovetab.left = 4;\n\tmovetab.down = 5;\n\tmovetab.up = 5;\n\tMenuAudio_3.AddOption(&m_sprites[FE_RADIO1], &movetab, 0.0f, Y(18.0f),\n\t\tCVector2D(X(96.0f), YF(72.0f)), TriggerAudio_RadioStation, false);\n\tmovetab.right = 2;\n\tmovetab.left = 0;\n\tmovetab.down = 6;\n\tmovetab.up = 6;\n\tMenuAudio_3.AddOption(&m_sprites[FE_RADIO2], &movetab, X(106.0f), Y(20.0f),\n\t\tCVector2D(X(79.2f), YF(81.0f)), TriggerAudio_RadioStation, false);\n\tmovetab.right = 3;\n\tmovetab.left = 1;\n\tmovetab.down = 7;\n\tmovetab.up = 7;\n\tMenuAudio_3.AddOption(&m_sprites[FE_RADIO5], &movetab, X(210.0f), Y(20.0f),\n\t\tCVector2D(X(86.4f), YF(72.0f)), TriggerAudio_RadioStation, false);\n\tmovetab.right = 4;\n\tmovetab.left = 2;\n\tmovetab.down = 8;\n\tmovetab.up = 8;\n\tMenuAudio_3.AddOption(&m_sprites[FE_RADIO7], &movetab, X(324.0f), Y(5.0f),\n\t\tCVector2D(X(115.2f), YF(102.0f)), TriggerAudio_RadioStation, false);\n\tmovetab.right = 0;\n\tmovetab.left = 3;\n\tmovetab.down = 8;\n\tmovetab.up = 8;\n\tMenuAudio_3.AddOption(&m_sprites[FE_RADIO8], &movetab, X(446.0f), Y(5.0f),\n\t\tCVector2D(X(102.96f), YF(101.4f)), TriggerAudio_RadioStation, false);\n\t// second row\n\tmovetab.right = 6;\n\tmovetab.left = 8;\n\tmovetab.down = 0;\n\tmovetab.up = 0;\n\tMenuAudio_3.AddOption(&m_sprites[FE_RADIO3], &movetab, X(60.0f), Y(96.0f),\n\t\tCVector2D(X(87.36f), YF(85.8f)), TriggerAudio_RadioStation, false);\n\tmovetab.right = 7;\n\tmovetab.left = 5;\n\tmovetab.down = 1;\n\tmovetab.up = 1;\n\tMenuAudio_3.AddOption(&m_sprites[FE_RADIO4], &movetab, X(130.0f), Y(72.0f),\n\t\tCVector2D(X(129.6f), YF(129.0f)), TriggerAudio_RadioStation, false);\n\tmovetab.right = 8;\n\tmovetab.left = 6;\n\tmovetab.down = 2;\n\tmovetab.up = 2;\n\tMenuAudio_3.AddOption(&m_sprites[FE_RADIO6], &movetab, X(284.0f), Y(108.0f),\n\t\tCVector2D(X(60.0f), YF(60.0f)), TriggerAudio_RadioStation, false);\n\tmovetab.right = 5;\n\tmovetab.left = 7;\n\tmovetab.down = 3;\n\tmovetab.up = 3;\n\tMenuAudio_3.AddOption(&m_sprites[FE_RADIO9], &movetab, X(404.0f), Y(85.0f),\n\t\tCVector2D(X(81.12f), YF(101.4f)), TriggerAudio_RadioStation, false);\n\tmovetab.right = 2;\n\tmovetab.left = 0;\n\tmovetab.down = 1;\n\tmovetab.up = 1;\n\tMenuPage_Audio.AddMenu(&MenuAudio_3, &movetab);\n\tMenuPage_Audio.SetShadows(true, TEXT_SHADOW_COLOR, SHADOW_VECTOR);\n\tMenuPage_Audio.ActivatePage();\n\n\n\t/* Display */\n\n\tMenuDisplay_1.SetPosition(X(240.0f), Y(140.0f));\n\tMenuDisplay_1.SetColors(TEXT_COLOR, TEXT_COLOR, SLIDER_LEFT_COLOR, SLIDER_RIGHT_COLOR);\n\tMenuDisplay_1.m_style = 0;\t// ticks\n\tMenuDisplay_1.AddTitle(TheText.Get(\"FED_BRI\"), X(DISPLAY_BRIGHTNESS_POS.x), Y(DISPLAY_BRIGHTNESS_POS.y));\n\tMenuDisplay_1.AddTickBox(X(-30.0f), Y(20.0f), X(200.0f), Y(40.0f), Y(40.0f));\n\tMenuPage_Display.AddMenu(&MenuDisplay_1);\n\tMenuDisplay_2.SetPosition(X(290.0f), Y(240.0f));\n\tMenuDisplay_2.SetColors(TITLE_TEXT_COLOR, TEXT_COLOR);\n\tMenuDisplay_2.AddTitle(TheText.Get(\"FED_TRA\"), false, 0.0f, 0.0f, true);\n#ifdef GTA_PC\n\tMenuDisplay_2.SetOptionPosition(X(40.0f), 0.0f, TriggerDisplay_Trails, false);\n#else\n\tMenuDisplay_2.SetOptionPosition(X(40.0f), 0.0f, false);\n#endif\n\tMenuDisplay_2.m_bTwoState = true;\n\tMenuPage_Display.AddMenu(&MenuDisplay_2);\n\tMenuDisplay_3.SetPosition(X(290.0f), Y(260.0f));\n\tMenuDisplay_3.SetColors(TITLE_TEXT_COLOR, TEXT_COLOR);\n\tMenuDisplay_3.AddTitle(TheText.Get(\"FED_SUB\"), false, 0.0f, 0.0f, true);\n\tMenuDisplay_3.SetOptionPosition(X(40.0f), 0.0f, false);\n\tMenuDisplay_3.m_bTwoState = true;\n\tMenuPage_Display.AddMenu(&MenuDisplay_3);\n\tMenuDisplay_4.SetPosition(X(290.0f), Y(280.0f));\n\tMenuDisplay_4.SetColors(TITLE_TEXT_COLOR, TEXT_COLOR);\n\tMenuDisplay_4.AddTitle(TheText.Get(\"FED_WIS\"), false, 0.0f, 0.0f, true);\n\tMenuDisplay_4.SetOptionPosition(X(40.0f), 0.0f, false);\n\tMenuDisplay_4.m_bTwoState = true;\n\tMenuPage_Display.AddMenu(&MenuDisplay_4);\n\tMenuPage_Display.SetShadows(true, TEXT_SHADOW_COLOR, SHADOW_VECTOR);\n\tMenuPage_Display.ActivatePage();\n\n\n\t/* Language */\n\tMenuLanguage_1.m_numOptions = 0;\n\tMenuLanguage_1.SetPosition(X(288.0f), Y(160.0f));\n\tMenuLanguage_1.SetColors(TITLE_TEXT_COLOR, TEXT_COLOR, SELECTED_TEXT_COLOR);\n\tMenuLanguage_1.AddOption(TheText.Get(\"FEL_ENG\"), 0.0f, 0.0f, TriggerLanguage_Language, false, false);\n\tMenuLanguage_1.AddOption(TheText.Get(\"FEL_FRE\"), 0.0f, Y(20.0f), TriggerLanguage_Language, false, false);\n\tMenuLanguage_1.AddOption(TheText.Get(\"FEL_GER\"), 0.0f, Y(40.0f), TriggerLanguage_Language, false, false);\n\tMenuLanguage_1.AddOption(TheText.Get(\"FEL_ITA\"), 0.0f, Y(60.0f), TriggerLanguage_Language, false, false);\n\tMenuLanguage_1.AddOption(TheText.Get(\"FEL_SPA\"), 0.0f, Y(80.0f), TriggerLanguage_Language, false, false);\n\tMenuPage_Language.AddMenu(&MenuLanguage_1);\n\tMenuPage_Language.SetShadows(true, TEXT_SHADOW_COLOR, SHADOW_VECTOR);\n\tMenuPage_Language.ActivatePage();\n\n\n\t/*\n\t * Save zone menu\n\t */\n\n\tCVector2D saveGameTextScale2(X(0.49f), Y(0.7f));\n\tCVector2D defaultTextScale5(X(MENU_TEXT_SIZE_X), Y(MENU_TEXT_SIZE_Y));\n\n\t/* Save game */\n\n\tMenuSaveZoneSG_1.m_numOptions = 0;\n\tMenuSaveZoneSG_1.SetPosition(X(200.0f), Y(100.0f));\n\tMenuSaveZoneSG_1.SetColors(TITLE_TEXT_COLOR, TEXT_COLOR, TEXT_COLOR);\n\tMenuSaveZoneSG_1.AddOption(TheText.Get(\"FESZ_SA\"), 0.0f, Y(20.0f), TriggerSaveZone_SaveGameSelect, false, false);\n\tMenuSaveZoneSG_1.AddOption(TheText.Get(\"FESZ_CA\"), 0.0f, Y(40.0f), TriggerSaveZone_QuitMenu, false, false);\n\tMenuSaveZoneSG_1.m_defaultCancel = TriggerSaveZone_QuitMenu;\n\tMenuPageSaveZone_SaveGame.AddMenu(&MenuSaveZoneSG_1);\n\tMenuSaveZoneSG_1.SetMenuSelection(1);\n\tMenuPageSaveZone_SaveGame.SetShadows(true, TEXT_SHADOW_COLOR, SHADOW_VECTOR);\n\tMenuPageSaveZone_SaveGame.ActivatePage();\n\n\t/* Select slot */\n\n\tMenuSaveZoneSSL_1.m_numOptions = 0;\n\tMenuSaveZoneSSL_1.SetPosition(X(160.0f), Y(100.0f));\n\tMenuSaveZoneSSL_1.SetColors(TITLE_TEXT_COLOR, TEXT_COLOR, TEXT_COLOR);\n\tMenuSaveZoneSSL_1.AddOption(TheText.Get(\"FESZ_CA\"), 0.0f, 0.0f, TriggerSaveZone_BackToMainMenuTwoLines, false, false);\n\tMenuSaveZoneSSL_1.SetNewOldTextScale(true, saveGameTextScale2, defaultTextScale5, true);\n\tMenuPageSaveZone_SaveSlots.AddMenu(&MenuSaveZoneSSL_1);\n\tMenuSaveZoneSSL_1.SetMenuSelection(0);\n\tMenuPageSaveZone_SaveSlots.SetShadows(true, TEXT_SHADOW_COLOR, SHADOW_VECTOR);\n\tMenuPageSaveZone_SaveSlots.ActivatePage();\n\n\t/* Save successful */\n\n\tMenuSaveZoneSS_1.m_numTexts = 0;\n\tMenuSaveZoneSS_1.SetPosition(X(200.0f), Y(100.0f));\n\tMenuSaveZoneSS_1.AddText(TheText.Get(\"FESZ_L1\"), X(-40.0f), 0.0f, TITLE_TEXT_COLOR, false);\n\tMenuSaveZoneSS_1.AddText(TheText.Get(\"FESZ_L2\"), X(-40.0f), Y(20.0f), TITLE_TEXT_COLOR, false);\n\t// twice this line?\n\tMenuSaveZoneSS_1.AddText(TheText.Get(\"FESZ_L2\"), X(-40.0f), Y(40.0f), TEXT_COLOR, false);\n\tMenuPageSaveZone_SavedSuccessfully.AddMenu(&MenuSaveZoneSS_1);\n\tMenuSaveZoneSS_2.m_numOptions = 0;\n\tMenuSaveZoneSS_2.SetPosition(X(200.0f), Y(170.0f));\n\tMenuSaveZoneSS_2.SetColors(TITLE_TEXT_COLOR, TEXT_COLOR, TEXT_COLOR);\n\tMenuSaveZoneSS_2.AddOption(TheText.Get(\"FESZ_QU\"), X(60.0f), 0.0f, TriggerSaveZone_QuitMenu, false, false);\n\tMenuPageSaveZone_SavedSuccessfully.AddMenu(&MenuSaveZoneSS_2);\n\tMenuPageSaveZone_SavedSuccessfully.SetShadows(true, TEXT_SHADOW_COLOR, SHADOW_VECTOR);\n\tMenuPageSaveZone_SavedSuccessfully.ActivatePage();\n\n\n\tMenuSaveZoneMSG_1.m_numTexts = 0;\n\tMenuSaveZoneMSG_1.SetPosition(X(170.0f), Y(130.0f));\n\tMenuSaveZoneMSG_1.AddText(TheText.Get(\"FESZ_SR\"), X(-40.0f), 0.0f, TEXT_COLOR, false);\n\tMenuSaveZoneMSG_1.SetTextsColor(TEXT_COLOR);\n\tMenuSaveZoneMSG_1.SetNewOldShadowWrapX(true, X(600.0f+SHADOW_VECTOR.x-20.0f), X(580.0f));\n\tMenuPageSaveZone_Message.AddMenu(&MenuSaveZoneMSG_1);\n\tMenuSaveZoneMSG_2.m_numOptions = 0;\n\tMenuSaveZoneMSG_2.SetPosition(X(170.0f), Y(180.0f));\n\tMenuSaveZoneMSG_2.SetColors(TITLE_TEXT_COLOR, TEXT_COLOR, TEXT_COLOR);\n\tMenuSaveZoneMSG_2.AddOption(TheText.Get(\"FESZ_OK\"), X(40.0f), 0.0f, TriggerSaveZone_QuitMenu, false, false);\n\tMenuPageSaveZone_Message.AddMenu(&MenuSaveZoneMSG_2);\n\tMenuPageSaveZone_Message.SetShadows(true, TEXT_SHADOW_COLOR, SHADOW_VECTOR);\n\tMenuPageSaveZone_Message.ActivatePage();\n\n\n\tMenuSaveZoneQYN_1.m_numTexts = 0;\n\tMenuSaveZoneQYN_1.SetPosition(X(170.0f), Y(130.0f));\n\tMenuSaveZoneQYN_1.AddText(TheText.Get(\"FESZ_SR\"), X(-40.0f), 0.0f, TEXT_COLOR, false);\n\tMenuSaveZoneQYN_1.SetTextsColor(TEXT_COLOR);\n\tMenuSaveZoneQYN_1.SetNewOldShadowWrapX(true, X(600.0f+SHADOW_VECTOR.x-20.0f), X(580.0f));\n\tMenuPageSaveZone_QuestionYesNo.AddMenu(&MenuSaveZoneQYN_1);\n\tMenuSaveZoneQYN_2.m_numOptions = 0;\n\tMenuSaveZoneQYN_2.SetPosition(X(170.0f), Y(180.0f));\n\tMenuSaveZoneQYN_2.SetColors(TITLE_TEXT_COLOR, TEXT_COLOR, TEXT_COLOR);\n\tMenuSaveZoneQYN_2.AddOption(TheText.Get(\"FEM_YES\"), X(80.0f), 0.0f, TriggerSaveZone_QuitMenu, false, false);\n\tMenuSaveZoneQYN_2.AddOption(TheText.Get(\"FEM_NO\"), X(80.0f), Y(20.0f), TriggerSaveZone_QuitMenu, false, false);\n\tMenuPageSaveZone_QuestionYesNo.AddMenu(&MenuSaveZoneQYN_2);\n\tMenuPageSaveZone_QuestionYesNo.SetShadows(true, TEXT_SHADOW_COLOR, SHADOW_VECTOR);\n\tMenuPageSaveZone_QuestionYesNo.ActivatePage();\n\n\t/* Format card */\n\n\tMenuSaveZoneFC_1.m_numOptions = 0;\n\tMenuSaveZoneFC_1.SetPosition(X(200.0f), Y(100.0f));\n\tMenuSaveZoneFC_1.SetColors(TITLE_TEXT_COLOR, TEXT_COLOR, TEXT_COLOR);\n\tMenuSaveZoneFC_1.AddTitle(TheText.Get(\"FESZ_FM\"), X(-100.0f), 0.0f, false);\n\tMenuSaveZoneFC_1.AddOption(TheText.Get(\"FEM_NO\"), X(40.0f), Y(95.0f), TriggerSaveZone_BackToMainMenu, false, false);\n\tMenuSaveZoneFC_1.AddOption(TheText.Get(\"FEM_YES\"), X(40.0f), Y(75.0f), TriggerSaveZone_FormatCardSelect, false, false);\n\tMenuSaveZoneFC_1.m_defaultCancel = TriggerSaveZone_FormatCardSelect;\n\tMenuPageSaveZone_FormatCard.AddMenu(&MenuSaveZoneFC_1);\n\tMenuPageSaveZone_FormatCard.SetShadows(true, TEXT_SHADOW_COLOR, SHADOW_VECTOR);\n\tMenuPageSaveZone_FormatCard.ActivatePage();\n\n\t/* Format error */\n\n\tMenuSaveZoneEF_1.m_numOptions = 0;\n\tMenuSaveZoneEF_1.SetPosition(X(200.0f), Y(100.0f));\n\tMenuSaveZoneEF_1.SetColors(TITLE_TEXT_COLOR, TEXT_COLOR, TEXT_COLOR);\n\tMenuSaveZoneEF_1.AddTitle(TheText.Get(\"FESZ_FF\"), X(-40.0f), 0.0f, false);\n\tMenuSaveZoneEF_1.AddOption(TheText.Get(\"FESZ_OK\"), X(70.0f), Y(20.0f), TriggerSaveZone_FormatFailedOK, false, false);\n\tMenuPageSaveZone_ErrorFormat.AddMenu(&MenuSaveZoneEF_1);\n\tMenuPageSaveZone_ErrorFormat.SetShadows(true, TEXT_SHADOW_COLOR, SHADOW_VECTOR);\n\tMenuPageSaveZone_ErrorFormat.ActivatePage();\n\n\tpActiveMenuPage = &MenuPage_Stats;\n\tpActiveMenuPage->ActivatePage();\n\n\tInitialiseMenuContents();\n\n\tm_bWantToUpdateContent = false;\n}\n\nvoid\nCMenuManager::InitialiseChangedLanguageSettings(void)\n{\n\tif ( bFrontEnd_ReloadObrTxtGxt )\n\t{\n\t\tbFrontEnd_ReloadObrTxtGxt = false;\n\n\t\tCTimer::Stop();\n\t\tTheText.Unload();\n\t\tTheText.Load();\n\t\tCTimer::Update();\n\n\t\tFrontEndMenuManager.AnaliseMenuContents();\n\t\tCGame::frenchGame = false;\n\t\tCGame::germanGame = false;\n\t\tif ( m_PrefsAllowNastyGame )\n\t\t\tCGame::nastyGame = true;\n\n\t\tfor ( int32 i = 0; i < NUM_PAGES; i++ )\n\t\t{\n\t\t\tBUTTONTAB_TEXT_X_SCALES[i] = 1.0f;\n\t\t\tPANEL_TEXT_X_SCALES[i] = 1.0f;\n\t\t}\n\n\t\tswitch ( m_PrefsLanguage )\n\t\t{\n\t\t\tcase LANGUAGE_AMERICAN:\n\t\t\t{\n\t\t\t\tMENU_TEXT_SIZE_X = 0.644f;\n\t\t\t\tMENU_TEXT_SIZE_Y = 0.84f;//0.96f;\n\n\t\t\t\tBUTTONTAB_TEXT_SIZE_X = 0.35f;\n\t\t\t\tBUTTONTAB_TEXT_SIZE_Y = 0.7f;//0.8f;\n\n\t\t\t\tBUTTONTAB_TEXT_X_SCALES[6] = 0.94f;\n\n\t\t\t\tCONTR_DESCR_NEW_TEXTSCALE.x = 0.4564f;\n\t\t\t\tCONTR_DESCR_NEW_TEXTSCALE.y = 0.63f;//0.72f;\n\n\t\t\t\tCONFIGS_NEW_TEXTSCALE.x = 0.49f;\n\t\t\t\tCONFIGS_NEW_TEXTSCALE.y = 0.7f;//0.8f;\n\n\t\t\t\tAUDIO_OUTPUT_POS.x = 0.0f;\n\t\t\t\tAUDIO_OUTPUT_POS.y = 0.0f;\n\n\t\t\t\tAUDIO_RSTATION_POS.x = 154.0f;\n\t\t\t\tAUDIO_RSTATION_POS.y = 0.0f;\n\n\t\t\t\tDISPLAY_BRIGHTNESS_POS.x = 0.0f;\n\t\t\t\tDISPLAY_BRIGHTNESS_POS.y = 0.0f;\n\n\t\t\t\tMEMCARD_ACCESS_MSG_SIZE_X = 0.84f;\n\t\t\t\tMEMCARD_ACCESS_MSG_SIZE_Y = 1.12f;//1.28f;\n\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase LANGUAGE_FRENCH:\n\t\t\t{\n\t\t\t\tCGame::frenchGame = true;\n\t\t\t\tif ( m_PrefsAllowNastyGame )\n\t\t\t\t\tCGame::nastyGame = false;\n\n\t\t\t\tMENU_TEXT_SIZE_X = 0.504f;\n\t\t\t\tMENU_TEXT_SIZE_Y = 0.84f;//0.96f;\n\n\t\t\t\tBUTTONTAB_TEXT_SIZE_X = 0.32f;\n\t\t\t\tBUTTONTAB_TEXT_SIZE_Y = 0.7f;//0.8f;\n\n\t\t\t\tBUTTONTAB_TEXT_X_SCALES[0] = 0.84f;\n\t\t\t\tBUTTONTAB_TEXT_X_SCALES[3] = 0.84f;\n\t\t\t\tPANEL_TEXT_X_SCALES[1] = 0.8f;\n\n\t\t\t\tCONTR_DESCR_NEW_TEXTSCALE.x = 0.385f;\n\t\t\t\tCONTR_DESCR_NEW_TEXTSCALE.y = 0.63f;//0.72f;\n\n\t\t\t\tCONFIGS_NEW_TEXTSCALE.x = 0.455f;\n\t\t\t\tCONFIGS_NEW_TEXTSCALE.y = 0.7f;//0.8f;\n\n\t\t\t\tAUDIO_OUTPUT_POS.x = -15.0f;\n\t\t\t\tAUDIO_OUTPUT_POS.y = 0.0f;\n\n\t\t\t\tAUDIO_RSTATION_POS.x = 184.0f;\n\t\t\t\tAUDIO_RSTATION_POS.y = 0.0f;\n\n\t\t\t\tDISPLAY_BRIGHTNESS_POS.x = 20.0f;\n\t\t\t\tDISPLAY_BRIGHTNESS_POS.y = 0.0f;\n\n\t\t\t\tMEMCARD_ACCESS_MSG_SIZE_X = 0.84f;\n\t\t\t\tMEMCARD_ACCESS_MSG_SIZE_Y = 1.12f;//1.28f;\n\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase LANGUAGE_GERMAN:\n\t\t\t{\n\t\t\t\tCGame::germanGame = true;\n\t\t\t\tif ( m_PrefsAllowNastyGame )\n\t\t\t\t\tCGame::nastyGame = false;\n\n\t\t\t\tMENU_TEXT_SIZE_X = 0.546f;\n\t\t\t\tMENU_TEXT_SIZE_Y = 0.84f;//0.96f;\n\n\t\t\t\tBUTTONTAB_TEXT_SIZE_X = 0.32f;\n\t\t\t\tBUTTONTAB_TEXT_SIZE_Y = 0.7f;//0.8f;\n\n\t\t\t\tCONTR_DESCR_NEW_TEXTSCALE.x = 0.35f;\n\t\t\t\tCONTR_DESCR_NEW_TEXTSCALE.y = 0.63f;//0.72f;\n\n\t\t\t\tCONFIGS_NEW_TEXTSCALE.x = 0.434f;\n\t\t\t\tCONFIGS_NEW_TEXTSCALE.y = 0.7f;//0.8f;\n\n\t\t\t\tAUDIO_OUTPUT_POS.x = -15.0f;\n\t\t\t\tAUDIO_OUTPUT_POS.y = 0.0f;\n\n\t\t\t\tAUDIO_RSTATION_POS.x = 154.0f;\n\t\t\t\tAUDIO_RSTATION_POS.y = 0.0f;\n\n\t\t\t\tDISPLAY_BRIGHTNESS_POS.x = 20.0f;\n\t\t\t\tDISPLAY_BRIGHTNESS_POS.y = 0.0f;\n\n\t\t\t\tMEMCARD_ACCESS_MSG_SIZE_X = 0.7f;\n\t\t\t\tMEMCARD_ACCESS_MSG_SIZE_Y = 1.12f;//1.28f;\n\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase LANGUAGE_ITALIAN:\n\t\t\t{\n\t\t\t\tMENU_TEXT_SIZE_X = 0.574f;\n\t\t\t\tMENU_TEXT_SIZE_Y = 0.84f;//0.96f;\n\n\t\t\t\tBUTTONTAB_TEXT_SIZE_X = 0.32f;\n\t\t\t\tBUTTONTAB_TEXT_SIZE_Y = 0.7f;//0.8f;\n\n\t\t\t\tBUTTONTAB_TEXT_X_SCALES[0] = 0.86f;\n\t\t\t\tPANEL_TEXT_X_SCALES[1] = 0.9f;\n\n\t\t\t\tCONTR_DESCR_NEW_TEXTSCALE.x = 0.385f;\n\t\t\t\tCONTR_DESCR_NEW_TEXTSCALE.y = 0.63f;//0.72f;\n\n\t\t\t\tCONFIGS_NEW_TEXTSCALE.x = 0.42f;\n\t\t\t\tCONFIGS_NEW_TEXTSCALE.y = 0.7f;//0.8f;\n\n\t\t\t\tAUDIO_OUTPUT_POS.x = 10.0f;\n\t\t\t\tAUDIO_OUTPUT_POS.y = 0.0f;\n\n\t\t\t\tAUDIO_RSTATION_POS.x = 194.0f;\n\t\t\t\tAUDIO_RSTATION_POS.y = 0.0f;\n\n\t\t\t\tDISPLAY_BRIGHTNESS_POS.x = 10.0f;\n\t\t\t\tDISPLAY_BRIGHTNESS_POS.y = 0.0f;\n\n\t\t\t\tMEMCARD_ACCESS_MSG_SIZE_X = 0.84f;\n\t\t\t\tMEMCARD_ACCESS_MSG_SIZE_Y = 1.12f;//1.28f;\n\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase LANGUAGE_SPANISH:\n\t\t\t{\n\t\t\t\tMENU_TEXT_SIZE_X = 0.546f;\n\t\t\t\tMENU_TEXT_SIZE_Y = 0.84f;//0.96f;\n\n\t\t\t\tBUTTONTAB_TEXT_SIZE_X = 0.35f;\n\t\t\t\tBUTTONTAB_TEXT_SIZE_Y = 0.7f;//0.8f;\n\n\t\t\t\tBUTTONTAB_TEXT_X_SCALES[0] = 0.78f;\n\t\t\t\tPANEL_TEXT_X_SCALES[1] = 0.95f;\n\n\t\t\t\tCONTR_DESCR_NEW_TEXTSCALE.x = 0.364f;\n\t\t\t\tCONTR_DESCR_NEW_TEXTSCALE.y = 0.63f;//0.72f;\n\n\t\t\t\tCONFIGS_NEW_TEXTSCALE.x = 0.455f;\n\t\t\t\tCONFIGS_NEW_TEXTSCALE.y = 0.7f;//0.8f;\n\n\t\t\t\tAUDIO_OUTPUT_POS.x = 10.0f;\n\t\t\t\tAUDIO_OUTPUT_POS.y = 0.0f;\n\n\t\t\t\tAUDIO_RSTATION_POS.x = 124.0f;\n\t\t\t\tAUDIO_RSTATION_POS.y = 0.0f;\n\n\t\t\t\tDISPLAY_BRIGHTNESS_POS.x = 30.0f;\n\t\t\t\tDISPLAY_BRIGHTNESS_POS.y = 0.0f;\n\n\t\t\t\tMEMCARD_ACCESS_MSG_SIZE_X = 0.84f;\n\t\t\t\tMEMCARD_ACCESS_MSG_SIZE_Y = 1.12f;//1.28f;\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nCMenuManager::InitialiseMenuContents(void)\n{\n\tif ( m_bWantToUpdateContent == false )\n\t{\n\t\tm_bWantToUpdateContent = true;\n\n\t\tm_pageState = PAGESTATE_NORMAL;\n\n\t\tswitch ( CPad::GetPad(0)->GetMode() )\n\t\t{\n\t\t\tcase 3: m_PrefsControllerConfig = CONFIG_4; break;\n\t\t\tcase 2: m_PrefsControllerConfig = CONFIG_3; break;\n\t\t\tcase 1: m_PrefsControllerConfig = CONFIG_2; break;\n\t\t\tcase 0: m_PrefsControllerConfig = CONFIG_1; break;\n\t\t}\n\n\t\tMenuControls_1.SetMenuSelection(m_PrefsControllerConfig);\n\t\tMenuControls_5.SetMenuSelection(m_PrefsUseVibration);\n\n\t\tMenuAudio_1.SetMenuSelection(m_PrefsMusicVolume / 127.0f * 100.0f + 0.5f);\n\t\tMenuAudio_2.SetMenuSelection(m_PrefsSfxVolume   / 127.0f * 100.0f + 0.5f);\n\t\tMenuAudio_3.SetMenuSelection(m_PrefsRadioStation);\n\t\tMenuAudio_4.SetMenuSelection(m_PrefsStereoMono);\n\n\t\tMenuDisplay_1.SetMenuSelection(m_PrefsBrightness / 512.0f * 100.0f + 0.5f);\n#ifdef PS2\n\t\tm_PrefsShowTrails = BlurOn;\n#else\n\t\tm_PrefsShowTrails = CMBlur::BlurOn;\n#endif\n\t\tMenuDisplay_2.SetMenuSelection(m_PrefsShowTrails);\n\t\tMenuDisplay_3.SetMenuSelection(m_PrefsShowSubtitles);\n\t\tMenuDisplay_4.SetMenuSelection(m_PrefsUseWideScreen);\n\n\t\tMenuLanguage_1.SetMenuSelection(m_PrefsLanguage);\n\n\t\tFillMenuWithMemCardFileListing(&MenuSaveLG_2, TriggerSave_BackToMainMenuTwoLines, TriggerSave_LoadGameLoadGameSelect,     nil, 0, 34, 22);\n\t\tFillMenuWithMemCardFileListing(&MenuSaveDG_2, TriggerSave_BackToMainMenuTwoLines, TriggerSave_DeleteGameDeleteGameSelect, nil, 0, 34, 22);\n\n\t\tMenuBriefs_1.m_numTexts = 0;\n\t\tMenuBriefs_1.AddText(TheText.Get(\"FEB_PMB\"), 0.0f, 0.0f, TITLE_TEXT_COLOR, 0); // Previous Mission Briefs:\n\n\t\tstatic wchar StringsToDisplay[NUMPREVIOUSBRIEFS][256];\n\n\t\tCRGBA newColor;\n\t\tint32 brierY = 36;\n\n\t\tfor ( int32 i = NUMPREVIOUSBRIEFS-1; i >= 0; i-- )\n\t\t{\n\t\t\ttPreviousBrief &brief = CMessages::PreviousBriefs[i];\n\t\t\tif (brief.m_pText)\n\t\t\t{\n\t\t\t\tCMessages::InsertNumberInString(brief.m_pText,\n\t\t\t\t\tbrief.m_nNumber[0], brief.m_nNumber[1],\n\t\t\t\t\tbrief.m_nNumber[2], brief.m_nNumber[3],\n\t\t\t\t\tbrief.m_nNumber[4], brief.m_nNumber[5], StringsToDisplay[i]);\n\t\t\t\tCMessages::InsertStringInString(StringsToDisplay[i], brief.m_pString);\n\n\t\t\t\tnewColor = TEXT_COLOR;\n\t\t\t\tFilterOutColorMarkersFromString(StringsToDisplay[i], newColor);\n\n\t\t\t\tif (newColor != TEXT_COLOR)\n\t\t\t\t{\n\t\t\t\t\tnewColor.r /= 2;\n\t\t\t\t\tnewColor.g /= 2;\n\t\t\t\t\tnewColor.b /= 2;\n\t\t\t\t}\n\t\t\t\tMenuBriefs_1.AddText(StringsToDisplay[i], 0.0f, YF((float)brierY), newColor, 0);\n\t\t\t\tbrierY += 54;\n\t\t\t}\n\t\t}\n\n\t\tMenuStats_1.m_scrollPosition = 0.0f;\n\t\tMenuStats_1.ResetNumberOfTextLines();\n\n\t\tnStatLinesIndex = 0;\n\n\t\t#define STAT_HEADER(str) do { MenuStats_1.AddTextLine(TheText.Get(str), nil); } while(0)\n\t\t#define STAT_PARAM(str) do { MenuStats_1.AddTextLine(nil, TheText.Get(str)); } while(0)\n\t\t#define STAT_LINE(str, left, isFloat, right) do { MenuStats_1.AddTextLine(TheText.Get(str), PrintStatLine(str, left, isFloat, right)); } while(0)\n\n\t\tint32 nTemp;\n\n\t\tSTAT_HEADER(\"PL_STAT\");\n\n\t\tint32 percentCompleted = (CStats::TotalProgressInGame == 0 ? 0 : CStats::ProgressMade * 100.0f / (CGame::nastyGame ? CStats::TotalProgressInGame : CStats::TotalProgressInGame - 1));\n\t\tpercentCompleted = Min(percentCompleted, 100);\n\n\t\tSTAT_LINE(\"PER_COM\", &percentCompleted,       0, nil);\n\n\t\tSTAT_LINE(\"NMISON\",  &CStats::MissionsGiven,  0, nil);\n\n\t\tSTAT_LINE(\"FEST_MP\", &CStats::MissionsPassed, 0, &CStats::TotalNumberMissions);\n\n\t\tif ( CGame::nastyGame )\n\t\t\tSTAT_LINE(\"FEST_RP\", &CStats::NumberKillFrenziesPassed, 0, &CStats::TotalNumberKillFrenzies);\n\n\t\tCPlayerInfo &player = CWorld::Players[CWorld::PlayerInFocus];\n\t\tfloat packagesPercent = 0.0f;\n\t\tif (player.m_nTotalPackages != 0)\n\t\t\tpackagesPercent = player.m_nCollectedPackages * 100.0f / player.m_nTotalPackages;\n\t\tint32 nPackagesPercent = packagesPercent;\n\t\tnTemp = 100;\n\n\t\tSTAT_LINE(\"PERPIC\", &nPackagesPercent,       0, &nTemp);\n\n\t\tSTAT_LINE(\"NOUNIF\", &CStats::NumberOfUniqueJumpsFound, 0, &CStats::TotalNumberOfUniqueJumps);\n\n\t\tSTAT_LINE(\"DAYSPS\", &CStats::DaysPassed, 0, nil);\n\n\t\tif ( CGame::nastyGame )\n\t\t{\n\t\t\tSTAT_LINE(\"PE_WAST\", &CStats::PeopleKilledByPlayer, 0, nil);\n\t\t\tSTAT_LINE(\"PE_WSOT\", &CStats::PeopleKilledByOthers, 0, nil);\n\t\t}\n\n\t\tSTAT_LINE(\"CAR_EXP\", &CStats::CarsExploded, 0, nil);\n\n\t\tSTAT_LINE(\"TM_BUST\", &CStats::TimesArrested, 0, nil);\n\n\t\tSTAT_LINE(\"TM_DED\", &CStats::TimesDied, 0, nil);\n\n\t\tnTemp = CStats::PedsKilledOfThisType[PEDTYPE_GANG9] + CStats::PedsKilledOfThisType[PEDTYPE_GANG8]\n\t\t\t+ CStats::PedsKilledOfThisType[PEDTYPE_GANG7] + CStats::PedsKilledOfThisType[PEDTYPE_GANG6]\n\t\t\t+ CStats::PedsKilledOfThisType[PEDTYPE_GANG5] + CStats::PedsKilledOfThisType[PEDTYPE_GANG4]\n\t\t\t+ CStats::PedsKilledOfThisType[PEDTYPE_GANG3] + CStats::PedsKilledOfThisType[PEDTYPE_GANG2]\n\t\t\t+ CStats::PedsKilledOfThisType[PEDTYPE_GANG1];\n\t\tSTAT_LINE(\"GNG_WST\", &nTemp, 0, nil);\n\n\t\tnTemp = CStats::PedsKilledOfThisType[PEDTYPE_CRIMINAL];\n\t\tSTAT_LINE(\"DED_CRI\", &nTemp, 0, nil);\n\n\t\tSTAT_LINE(\"HEL_DST\", &CStats::HelisDestroyed, 0, nil);\n\n\t\tSTAT_LINE(\"KGS_EXP\", &CStats::KgsOfExplosivesUsed, 0, nil);\n\n\t\tif (CStats::LongestFlightInDodo > 0)\n\t\t\tSTAT_LINE(\"FEST_LF\", &CStats::LongestFlightInDodo, 0, nil);\n\n\t\tSTAT_LINE(\"CAR_CRU\", &CStats::CarsCrushed, 0, nil);\n\n\t\tif (CStats::HighestScores[0] > 0)\n\t\t{\n\t\t\tSTAT_HEADER(\"FEST_BB\");\n\t\t\tSTAT_LINE(\"FEST_H0\", &CStats::HighestScores[0], 0, nil);\n\t\t}\n\n\t\tint32 hs = 0;\n\t\tfor ( int32 i = 1; i < 5; i++ )\n\t\t\ths += CStats::HighestScores[i];\n\n\t\tif (hs > 0)\n\t\t\tSTAT_HEADER(\"FEST_GC\");\n\n\t\tif (CStats::HighestScores[1] > 0)\n\t\t\tSTAT_LINE(\"FEST_H1\", &CStats::HighestScores[1], 0, nil);\n\n\t\tif (CStats::HighestScores[2] > 0)\n\t\t\tSTAT_LINE(\"FEST_H2\", &CStats::HighestScores[2], 0, nil);\n\n\t\tif (CStats::HighestScores[3] > 0)\n\t\t\tSTAT_LINE(\"FEST_H3\", &CStats::HighestScores[3], 0, nil);\n\n\t\tif (CStats::HighestScores[4] > 0)\n\t\t\tSTAT_LINE(\"FEST_H4\", &CStats::HighestScores[4], 0, nil);\n\n\t\tSTAT_LINE(\"FESTDFM\", &CStats::DistanceTravelledOnFoot, 0, nil);\n\t\tSTAT_LINE(\"FESTDCM\", &CStats::DistanceTravelledByCar, 0, nil);\n\t\tSTAT_LINE(\"DISTBIM\", &CStats::DistanceTravelledByBike, 0, nil);\n\t\tSTAT_LINE(\"DISTBOM\", &CStats::DistanceTravelledByBoat, 0, nil);\n\t\tSTAT_LINE(\"DISTGOM\", &CStats::DistanceTravelledByGolfCart, 0, nil);\n\t\tSTAT_LINE(\"DISTHEM\", &CStats::DistanceTravelledByHelicoptor, 0, nil);\n\t\tSTAT_LINE(\"MMRAIN\", &CStats::mmRain, 0, nil);\n\t\tnTemp = (int32)CStats::MaximumJumpDistance;\n\t\tSTAT_LINE(\"MXCARDM\", &nTemp, 0, nil);\n\t\tnTemp = (int32)CStats::MaximumJumpHeight;\n\t\tSTAT_LINE(\"MXCARJM\", &nTemp, 0, nil);\n\n\t\tSTAT_LINE(\"MXFLIP\", &CStats::MaximumJumpFlips, 0, nil);\n\t\tSTAT_LINE(\"MXJUMP\", &CStats::MaximumJumpSpins, 0, nil);\n\n\t\tSTAT_HEADER(\"BSTSTU\");\n\n\t\tswitch (CStats::BestStuntJump)\n\t\t{\n\t\t\tcase 1:  STAT_PARAM(\"INSTUN\"); break;\n\t\t\tcase 2:  STAT_PARAM(\"PRINST\"); break;\n\t\t\tcase 3:  STAT_PARAM(\"DBINST\"); break;\n\t\t\tcase 4:  STAT_PARAM(\"DBPINS\"); break;\n\t\t\tcase 5:  STAT_PARAM(\"TRINST\"); break;\n\t\t\tcase 6:  STAT_PARAM(\"PRTRST\"); break;\n\t\t\tcase 7:  STAT_PARAM(\"QUINST\"); break;\n\t\t\tcase 8:  STAT_PARAM(\"PQUINS\"); break;\n\t\t\tdefault: STAT_PARAM(\"NOSTUC\"); break;\n\t\t}\n\n\t\tSTAT_LINE(\"PASDRO\", &CStats::PassengersDroppedOffWithTaxi, 0, nil);\n\t\tSTAT_LINE(\"MONTAX\", &CStats::MoneyMadeWithTaxi, 0, nil);\n\t\tSTAT_LINE(\"FEST_LS\", &CStats::LivesSavedWithAmbulance, 0, nil);\n\t\tSTAT_LINE(\"FEST_HA\", &CStats::HighestLevelAmbulanceMission, 0, nil);\n\t\tSTAT_LINE(\"FEST_CC\", &CStats::CriminalsCaught, 0, nil);\n\t\tSTAT_LINE(\"FEST_FE\", &CStats::FiresExtinguished, 0, nil);\n\t\tint32 rnd = ((CGeneral::GetRandomNumber() & 255) + 100) * 2384;\n\t\tSTAT_LINE(\"DAYPLC\", &rnd, 0, nil);\n\n\t\t#undef STAT_LINE\n\n\t\tMenuStats_2.m_numTexts = 0;\n\t\tMenuStats_2.AddText(TheText.Get(\"CRIMRA\"), 0.0f, 0.0f, CRIM_RATING_TEXT_COLOR, 0);\n\n\t\tchar rating[16];\n\t\twchar urating[16];\n\t\tsprintf(rating, \"  %d\", CStats::FindCriminalRatingNumber());\n\t\tAsciiToUnicode(rating, urating);\n\n\t\twchar *pStatLine = aStatLines[nStatLinesIndex++];\n\t\tUnicodeStrcpy(pStatLine, CStats::FindCriminalRatingString());\n\t\tUnicodeStrcat(pStatLine, urating);\n\n\t\tMenuStats_2.AddText(pStatLine, X(MenuStats_1.m_width), 0.0f, CRIM_RATING_TEXT_COLOR, 1);\n\n\t\tMenuSaveZoneSG_1.SetMenuSelection(1);\n\t\tMenuSaveZoneFC_1.SetMenuSelection(1);\n\t}\n}\n\n\nvoid\nCMenuManager::AnaliseMenuContents(void)\n{\n\tif ( m_bWantToUpdateContent )\n\t{\n\t\tm_bWantToUpdateContent = false;\n\n\t\tm_PrefsControllerConfig = (CONTRCONFIG)MenuControls_1.GetMenuSelection();\n\t\tswitch ( m_PrefsControllerConfig )\n\t\t{\n\t\t\tcase CONFIG_4: CPad::GetPad(0)->SetMode(3); break;\n\t\t\tcase CONFIG_3: CPad::GetPad(0)->SetMode(2); break;\n\t\t\tcase CONFIG_2: CPad::GetPad(0)->SetMode(1); break;\n\t\t\tcase CONFIG_1: CPad::GetPad(0)->SetMode(0); break;\n\t\t}\n\n\t\tm_PrefsUseVibration = MenuControls_5.m_title.m_bSelected;\n\n\t\tm_PrefsMusicVolume   = float(MenuAudio_1.GetMenuSelection())/100.0f*127.0f+0.5f;\n\t\tm_PrefsSfxVolume     = float(MenuAudio_2.GetMenuSelection())/100.0f*127.0f+0.5f;\n\t\tm_PrefsRadioStation  = MenuAudio_3.GetMenuSelection();\n\t\tm_PrefsStereoMono    = MenuAudio_4.GetMenuSelection();\n\t\tm_PrefsBrightness    = float(MenuDisplay_1.GetMenuSelection()) / 100.0f*512.0f + 0.5f;\n\t\tm_PrefsShowTrails    = MenuDisplay_2.GetMenuSelection();\n\t\tm_PrefsShowSubtitles = MenuDisplay_3.GetMenuSelection();\n\t\tm_PrefsUseWideScreen = MenuDisplay_4.GetMenuSelection();\n#ifdef PS2\n\t\tBlurOn               = m_PrefsShowTrails;\n#else\n\t\tCMBlur::BlurOn       = m_PrefsShowTrails;\n#endif\n\n\t\tif ( m_PrefsLanguage != MenuLanguage_1.GetMenuSelection() )\n\t\t{\n\t\t\tm_PrefsLanguage = MenuLanguage_1.GetMenuSelection();\n\t\t\tm_bInitialised = false;\n\t\t\tbFrontEnd_ReloadObrTxtGxt = true;\n\t\t}\n\t}\n}\n\nvoid\nCMenuManager::InitialiseMenuContentsAfterLoadingGame(void)\n{\n\tif ( MenuLanguage_1.GetMenuSelection() != m_PrefsLanguage )\n\t{\n\t\tm_bInitialised = false;\n\t\tbFrontEnd_ReloadObrTxtGxt = true;\n\t}\n}\n\nvoid\nCMenuManager::DrawFrontEnd(void)\n{\n\tCFont::SetAlphaFade(255.0f);\n\tif(m_bInSaveZone)\n\t\tDrawFrontEndSaveZone();\n\telse\n\t\tDrawFrontEndNormal();\n\n\tif ( MemCardAccessTriggerCaller.CanCall() )\n\t\tMemCardAccessTriggerCaller.CallTrigger();\n\n\tDisplayWarningControllerMsg();\n}\n\nvoid\nCMenuManager::DrawFrontEndNormal(void)\n{\n\tCSprite2d::InitPerFrame();\n\tCFont::InitPerFrame();\n\n\tif ( bMemoryCardSpecialZone )\n\t{\n\t\tstatic uint8 counter = 0;\n\n\t\tcounter++;\n\n\t\tif ( (counter & 63 ) == 0 )\n\t\t{\n\t\t\tFillMenuWithMemCardFileListing(&MenuSaveLG_2, TriggerSave_BackToMainMenuTwoLines, TriggerSave_LoadGameLoadGameSelect, nil, 0, 34, 22);\n\t\t\tFillMenuWithMemCardFileListing(&MenuSaveDG_2, TriggerSave_BackToMainMenuTwoLines, TriggerSave_DeleteGameDeleteGameSelect, nil, 0, 34, 22);\n\t\t}\n\t}\n\n\tm_fade = 255;\n\tif ( m_nChangePageTimer != 0 && m_nChangePageTimer >= CTimer::GetTimeInMillisecondsPauseMode() )\n\t\tm_fade = uint32(float(m_nChangePageTimer - CTimer::GetTimeInMillisecondsPauseMode()) / 250.0f * 255.0f);\n\n\tm_someAlpha = 255;\n\n\tm_position.x = 0.0f;\n\tm_position.y = 0.0f;\n\n\tif ( m_nStartPauseTimer != 0 && m_nStartPauseTimer >= CTimer::GetTimeInMillisecondsPauseMode() )\n\t{\n\t\tfloat slide = float(m_nStartPauseTimer - CTimer::GetTimeInMillisecondsPauseMode()) / 800.0f;\n\t\tfloat alpha = 1.0f;\n\n\t\tif ((m_nStartPauseTimer - CTimer::GetTimeInMillisecondsPauseMode()) <= 1600)\n\t\t\talpha = float(m_nStartPauseTimer - CTimer::GetTimeInMillisecondsPauseMode()) / 400.0f;\n\n\t\tm_someAlpha = 255 - clamp(alpha, 0.0f, 1.0f) * 255.0f;\n\n\t\tswitch ( m_nSlidingDir )\n\t\t{\n\t\t\tcase SLIDE_TO_RIGHT:  m_position.x =   slide * X(700.0f);  break;\n\t\t\tcase SLIDE_TO_TOP:    m_position.y = -(slide * Y(500.0f)); break;\n\t\t\tcase SLIDE_TO_LEFT:   m_position.x = -(slide * X(700.0f)); break;\n\t\t\tcase SLIDE_TO_BOTTOM: m_position.y =   slide * Y(500.0f);  break;\n\t\t\tdefault:              m_position.y =   slide * Y(500.0f);  break;\n\t\t}\n\t}\n\n\tif ( m_nEndPauseTimer != 0 && m_nEndPauseTimer >= CTimer::GetTimeInMillisecondsPauseMode() )\n\t{\n\t\tfloat slide = float(m_nEndPauseTimer - CTimer::GetTimeInMillisecondsPauseMode()) / 800.0f;\n\t\tfloat alpha = float((int32)(m_nEndPauseTimer - CTimer::GetTimeInMillisecondsPauseMode()) + -266) / 533.0f;\n\n\t\tm_someAlpha = clamp(alpha, 0.0f, 1.0f) * 255.0f;\n\n\t\tswitch ( m_nSlidingDir )\n\t\t{\n\t\t\tcase SLIDE_TO_TOP:    m_position.y =   (1.0f - slide) * Y(500.0f);  break;\n\t\t\tcase SLIDE_TO_RIGHT:  m_position.x =   (1.0f - slide) * X(700.0f);  break;\n\t\t\tcase SLIDE_TO_LEFT:   m_position.x =   (1.0f - slide) * X(700.0f);  break;\n\t\t\tcase SLIDE_TO_BOTTOM: m_position.y = -((1.0f - slide) * Y(500.0f)); break;\n\t\t\tdefault:              m_position.y = -((1.0f - slide) * Y(500.0f)); break;\n\t\t}\n\t}\n\n\tif ( m_someAlpha < 255 )\n\t\tm_fade = m_someAlpha;\n\n\tfloat posX, posY;\n\n\t/* Draw splash */\n\tRwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR);\n\tCSprite2d *splash = LoadSplash(nil);\n\tif(splash)\n\t\tsplash->Draw(CRect(0.0f, 0.0f, SCRW, SCRH), BACKGROUND_SPLASH_COLOR);\n\telse\n\t\t// doesn't exist!!\n\t\tCHud::Sprites[19].Draw(CRect(0.0f, 0.0f, SCRW, SCRH), BACKGROUND_SPLASH_COLOR);\n\tRwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERMIPNEAREST);\n\n\t/* Draw main panel */\n\tRwRenderStateSet(rwRENDERSTATETEXTUREADDRESS, (void*)rwTEXTUREADDRESSCLAMP);\n\tCRGBA panelColor(255, 255, 255, m_someAlpha);\n\tm_sprites[FE2_MAINPANEL_UL].Draw(\n\t\tCRect(m_position.x, m_position.y, m_position.x+SCRW/2.0f, m_position.y+SCRH/2.0f),\n\t\tpanelColor);\n\tm_sprites[FE2_MAINPANEL_UR].Draw(\n\t\tCRect(m_position.x+SCRW/2.0f, m_position.y, m_position.x+SCRW, m_position.y+SCRH/2.0f),\n\t\tpanelColor);\n\tm_sprites[FE2_MAINPANEL_DL].Draw(\n\t\tCRect(m_position.x, m_position.y+SCRH/2.0f, m_position.x+SCRW/2.0f, m_position.y+SCRH),\n\t\tpanelColor);\n\tm_sprites[FE2_MAINPANEL_DR].Draw(\n\t\tCRect(m_position.x+SCRW/2.0f, m_position.y+SCRH/2.0f, m_position.x+SCRW, m_position.y+SCRH),\n\t\tpanelColor);\n\n\t/* Draw icon backdrop */\n\tCRGBA iconColor(255, 255, 255, m_fade*0.75f);\n\tfloat iconX = 48.0f;\n\tfloat iconY = 54.0f;\n\tfloat iconWidth = 540.0f;\n\tfloat iconHeight = 296.0f;\n\tint32 sprite = FE_ICONBRIEF;\n\n#ifdef PS2_MENU_USEALLPAGEICONS\n\tswitch(m_currentPage)\n\t{\n\tcase PAGE_STATS:\n\t\tsprite = FE_ICONSTATS;\n\t\tbreak;\n\tcase PAGE_LOAD:\n\t\tsprite = FE_ICONSAVE;\n\t\tbreak;\n\tcase PAGE_CONTROLS:\n\t\tsprite = FE_ICONCONTROLS;\n\t\tbreak;\n\tcase PAGE_BRIEFS:\n\t\tsprite = FE_ICONBRIEF;\n\t\tbreak;\n\tcase PAGE_AUDIO:\n\t\tsprite = FE_ICONAUDIO;\n\t\tbreak;\n\tcase PAGE_DISPLAY:\n\t\tsprite = FE_ICONDISPLAY;\n\t\tbreak;\n\tcase PAGE_LANGUAGE:\n\t\tsprite = FE_ICONLANGUAGE;\n\t\tbreak;\n\t}\n#else\n\tswitch(m_currentPage)\n\t{\n\tcase PAGE_STATS:\n\tcase PAGE_LOAD:\n\tcase PAGE_CONTROLS:\n\t\tsprite = FE_ICONSTATS;\t// PS2 has the same texture for stats and brief\n\t\t//sprite = FE_ICONBRIEF;\n\t\tbreak;\n\tcase PAGE_BRIEFS:\n\t\tsprite = FE_ICONBRIEF;\n\t\tbreak;\n\tcase PAGE_AUDIO:\n\t\tsprite = FE_ICONAUDIO;\n\t\tbreak;\n\tcase PAGE_DISPLAY:\n\t\tsprite = FE_ICONDISPLAY;\n\t\tbreak;\n\tcase PAGE_LANGUAGE:\n\t\tsprite = FE_ICONLANGUAGE;\n\t\tbreak;\n\t}\n#endif\n\tm_sprites[sprite].Draw(\n\t\tCRect_SZ(m_position.x+X(iconX), m_position.y+Y(iconY), X(iconWidth), Y(iconHeight)),\n\t\ticonColor);\n\n\t/* Overwrite tab buttons if entered page */\n\tbool bOverwriteTab = false;\n\n\tswitch ( m_pageState )\n\t{\n\t\tcase PAGESTATE_NORMAL:\n\t\tcase PAGESTATE_HIGHLIGHTED:\n\t\t\tbreak;\n\n\t\tcase PAGESTATE_SELECTED:\n\t\t\tbOverwriteTab = true;\n\t\t\tbreak;\n\t}\n\n\tif( bOverwriteTab )\n\t{\n\t\tCRGBA shadow(41, 101, 102, m_someAlpha);\n\t\tCRGBA green(40, 48, 57, m_someAlpha);\n\t\tCSprite2d::DrawRect(\n\t\t\tCRect_SZ(m_position.x+X(82.0f), m_position.y+Y(408.0f), X(476.0f), Y(18.0f)),\n\t\t\tshadow);\n\t\tCSprite2d::DrawRect(\n\t\t\tCRect_SZ(m_position.x+X(82.0f), m_position.y+Y(408.0f), X(476.0f), Y(5.0f)),\n\t\t\tgreen);\n\t}\n// stats, load, briefs, controls, audio, display, language\n\n\t/* Shadow of panel on top of tab buttons */\n\tCRGBA panelShadow(96, 96, 96, m_someAlpha*0.375f);\n\tCSprite2d::DrawRect(CRect_SZ(m_position.x+X(87.0f), m_position.y+Y(408.0f), X(464.0f), Y(3.0f)), panelShadow);\n\t/* Draw second shadow - seems unused */\n\tif ( m_nChangePageTimer != 0 && CTimer::GetTimeInMillisecondsPauseMode() < m_nChangePageTimer )\n\t{\n\t\tposX = 0.0f;\n\t\tswitch(field_18)\n\t\t{\n\t\tcase PAGE_STATS: posX = 88.0f; break;\n\t\tcase PAGE_LOAD: posX = 286.0f; break;\t// actually controls\n\t\tcase PAGE_BRIEFS: posX = 154.0f; break;\t// actually load\n\t\tcase PAGE_CONTROLS: posX = 220.0f; break;\t// actually briefs\n\t\tcase PAGE_AUDIO: posX = 352.0f; break;\n\t\tcase PAGE_DISPLAY: posX = 418.0f; break;\n\t\tcase PAGE_LANGUAGE: posX = 484.0f; break;\n\t\t}\n\t\tCSprite2d::DrawRect(CRect_SZ(m_position.x+X(posX), m_position.y+Y(411.0f), X(65.0f), Y(3.0f)), panelShadow);\n\t}\n\n\t/* Active tab */\n\tposX = 0.0f;\n\tswitch(m_currentPage)\n\t{\n\tcase PAGE_STATS: posX = 88.0f; break;\n\tcase PAGE_LOAD: posX = 154.0f; break;\n\tcase PAGE_BRIEFS: posX = 220.0f; break;\n\tcase PAGE_CONTROLS: posX = 286.0f; break;\n\tcase PAGE_AUDIO: posX = 352.0f; break;\n\tcase PAGE_DISPLAY: posX = 418.0f; break;\n\tcase PAGE_LANGUAGE: posX = 484.0f; break;\n\t}\n\t// PAL has 465 for 407 here - and actually 406 seems right\n\tm_sprites[FE2_TABACTIVE].Draw(CRect_SZ(m_position.x+X(posX), m_position.y+YF(465.0f), X(128.0f), Y(32.0f)), CRGBA(255, 255, 255, m_someAlpha));\n\n\t/* Draw page title */\n\tposX = m_position.x + X(592.0f);\n\tposY = m_position.y + Y(376.0f);\n\tCRGBA fontCol1(255, 193, 71, m_someAlpha);\n\tCRGBA fontCol2(0, 0, 0, m_someAlpha);\n\tCFont::SetFontStyle(FONT_HEADING);\n\tCFont::SetBackgroundOff();\n\tCFont::SetScale(X(PANEL_TEXT_SIZE_X), Y(PANEL_TEXT_SIZE_Y));\n\tCFont::SetPropOn();\n\tCFont::SetCentreOff();\n\tCFont::SetJustifyOn();\n\tCFont::SetRightJustifyWrap(0.0f);\n\tCFont::SetRightJustifyOn();\n\tCFont::SetBackGroundOnlyTextOn();\n\tCFont::SetWrapx(SCRW-X(40.0f)); // 600.0f\n\tconst char *key = nil;\n\tswitch(m_currentPage)\n\t{\n\tcase PAGE_STATS:    key = \"FEP_STA\"; break;\n\tcase PAGE_LOAD:     key = \"FEP_SAV\"; break;\n\tcase PAGE_BRIEFS:   key = \"FEP_BRI\"; break;\n\tcase PAGE_CONTROLS: key = \"FEP_CON\"; break;\n\tcase PAGE_AUDIO:    key = \"FEP_AUD\"; break;\n\tcase PAGE_DISPLAY:  key = \"FEP_DIS\"; break;\n\tcase PAGE_LANGUAGE: key = \"FEP_LAN\"; break;\n\t}\n\tCFont::SetScale(X(PANEL_TEXT_SIZE_X*PANEL_TEXT_X_SCALES[m_currentPage]), Y(PANEL_TEXT_SIZE_Y));\n\tCFont::SetColor(fontCol1);\n\tCFont::PrintString(posX, posY, TheText.Get(key));\n\tCFont::SetColor(fontCol2);\n\tCFont::PrintString(posX-X(1.0f), posY-Y(1.0f), TheText.Get(key));\n\tCFont::DrawFonts();\n\n\t/* Draw controller buttons */\n\tCFont::SetFontStyle(FONT_BANK);\n\tCFont::SetBackgroundOff();\n\tCFont::SetScale(X(0.35f), Y(0.64f));\n\tCFont::SetPropOn();\n\tCFont::SetCentreOff();\n\tCFont::SetJustifyOn();\n\tCFont::SetRightJustifyOff();\n\tCFont::SetBackGroundOnlyTextOn();\n\tCFont::SetWrapx(SCRW-X(40.0f)); // 600.0f\n\tCFont::SetColor(CRGBA(16, 16, 16, m_someAlpha));\n\tswitch(m_currentPage)\n\t{\n\t\tcase PAGE_STATS:\n\t\t\tCFont::PrintString(m_position.x+X(52.0f), m_position.y+Y(360.0f), TheText.Get(\"FEDS_ST\"));\n\t\t\tCFont::PrintString(m_position.x+X(52.0f), m_position.y+Y(372.0f), TheText.Get(\"FEDS_AM\"));\n\t\t\tCFont::PrintString(m_position.x+X(242.0f), m_position.y+Y(360.0f), TheText.Get(\"FEDSSC1\"));\n\t\t\tCFont::PrintString(m_position.x+X(242.0f), m_position.y+Y(372.0f), TheText.Get(\"FEDSSC2\"));\n\t\t\tbreak;\n\n\t\tcase PAGE_BRIEFS:\n\t\t\tCFont::PrintString(m_position.x+X(52.0f), m_position.y+Y(360.0f), TheText.Get(\"FEDS_ST\"));\n\t\t\tCFont::PrintString(m_position.x+X(52.0f), m_position.y+Y(372.0f), TheText.Get(\"FEDS_AM\"));\n\t\t\tbreak;\n\n\t\tcase PAGE_LOAD:\n\t\tcase PAGE_CONTROLS:\n\t\tcase PAGE_AUDIO:\n\t\tcase PAGE_DISPLAY:\n\t\tcase PAGE_LANGUAGE:\n\t\t{\n\t\t\tCFont::PrintString(m_position.x+X(52.0f), m_position.y+Y(360.0f), TheText.Get(\"FEDS_SE\"));\n\t\t\tCFont::PrintString(m_position.x+X(52.0f), m_position.y+Y(372.0f), TheText.Get(\"FEDS_BA\"));\n\t\t\tCFont::PrintString(m_position.x+X(52.0f), m_position.y+Y(384.0f), TheText.Get(\"FEDS_ST\"));\n\n\t\t\tswitch ( m_pageState )\n\t\t\t{\n\t\t\t\tcase PAGESTATE_NORMAL:\n\t\t\t\t\tCFont::PrintString(m_position.x+X(242.0f), m_position.y+Y(372.0f), TheText.Get(\"FEDS_AM\")); // <>-CHANGE MENU\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase PAGESTATE_HIGHLIGHTED:\n\t\t\t\tcase PAGESTATE_SELECTED:\n\t\t\t\t{\n\t\t\t\t\tCFont::PrintString(m_position.x+X(242.0f), m_position.y+Y(360.0f+3.5f), TheText.Get(\"FEA_UP\")); // ;\n\t\t\t\t\tCFont::PrintString(m_position.x+X(242.0f), m_position.y+Y(384.0f-3.5f), TheText.Get(\"FEA_DO\")); // =\n\t\t\t\t\tCFont::PrintString(m_position.x+X(242.0f-10.0f), m_position.y+Y(372.0f), TheText.Get(\"FEA_LE\")); // <\n\t\t\t\t\tCFont::PrintString(m_position.x+X(242.0f+11.0f), m_position.y+Y(372.0f), TheText.Get(\"FEA_RI\")); // >\n\t\t\t\t\tCFont::PrintString(m_position.x+X(242.0f+20.0f), m_position.y+Y(372.0f), TheText.Get(\"FEDSAS3\")); // - CHANGE SELECTION\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tCFont::DrawFonts();\n\n\t/* Draw tab button texts */\n\tCFont::SetFontStyle(FONT_BANK);\n\tCFont::SetBackgroundOff();\n\tCFont::SetScale(X(BUTTONTAB_TEXT_SIZE_X), Y(BUTTONTAB_TEXT_SIZE_Y));\n\tCFont::SetPropOn();\n\tCFont::SetCentreOn();\n\tCFont::SetRightJustifyOff();\n\tCFont::SetBackGroundOnlyTextOn();\n\tCFont::SetWrapx(SCRW-X(40.0f)); // 600.0f\n\n\tswitch ( m_pageState )\n\t{\n\t\tcase PAGESTATE_NORMAL:\n\t\t{\n\t\t\tCFont::SetColor(CRGBA(16, 16, 16, m_someAlpha));\n\t\t\tCFont::SetScale(X(BUTTONTAB_TEXT_SIZE_X*BUTTONTAB_TEXT_X_SCALES[PAGE_STATS]), Y(BUTTONTAB_TEXT_SIZE_Y));\n\t\t\tCFont::PrintString(m_position.x+X(92.0f), m_position.y+Y(408.0f), TheText.Get(\"FEB_STA\"));\n\t\t\tCFont::SetScale(X(BUTTONTAB_TEXT_SIZE_X*BUTTONTAB_TEXT_X_SCALES[PAGE_LOAD]), Y(BUTTONTAB_TEXT_SIZE_Y));\n\t\t\tCFont::PrintString(m_position.x+X(158.0f), m_position.y+Y(408.0f), TheText.Get(\"FEB_SAV\"));\n\t\t\tCFont::SetScale(X(BUTTONTAB_TEXT_SIZE_X*BUTTONTAB_TEXT_X_SCALES[PAGE_BRIEFS]), Y(BUTTONTAB_TEXT_SIZE_Y));\n\t\t\tCFont::PrintString(m_position.x+X(224.0f), m_position.y+Y(408.0f), TheText.Get(\"FEB_BRI\"));\n\t\t\tCFont::SetScale(X(BUTTONTAB_TEXT_SIZE_X*BUTTONTAB_TEXT_X_SCALES[PAGE_CONTROLS]), Y(BUTTONTAB_TEXT_SIZE_Y));\n\t\t\tCFont::PrintString(m_position.x+X(290.0f), m_position.y+Y(408.0f), TheText.Get(\"FEB_CON\"));\n\t\t\tCFont::SetScale(X(BUTTONTAB_TEXT_SIZE_X*BUTTONTAB_TEXT_X_SCALES[PAGE_AUDIO]), Y(BUTTONTAB_TEXT_SIZE_Y));\n\t\t\tCFont::PrintString(m_position.x+X(356.0f), m_position.y+Y(408.0f), TheText.Get(\"FEB_AUD\"));\n\t\t\tCFont::SetScale(X(BUTTONTAB_TEXT_SIZE_X*BUTTONTAB_TEXT_X_SCALES[PAGE_DISPLAY]), Y(BUTTONTAB_TEXT_SIZE_Y));\n\t\t\tCFont::PrintString(m_position.x+X(422.0f), m_position.y+Y(408.0f), TheText.Get(\"FEB_DIS\"));\n\t\t\tCFont::SetScale(X(BUTTONTAB_TEXT_SIZE_X*BUTTONTAB_TEXT_X_SCALES[PAGE_LANGUAGE]), Y(BUTTONTAB_TEXT_SIZE_Y));\n\t\t\tCFont::PrintString(m_position.x+X(488.0f), m_position.y+Y(408.0f), TheText.Get(\"FEB_LAN\"));\n\n\t\t\tbreak;\n\t\t}\n\n\t\tcase PAGESTATE_HIGHLIGHTED:\n\t\tcase PAGESTATE_SELECTED:\n\t\t{\n\t\t\tCFont::SetColor(CRGBA(16, 16, 16, m_someAlpha));\n\t\t\tswitch(m_currentPage)\n\t\t\t{\n\t\t\t// PAL has 466 for 408...probably rounded?\n\t\t\tcase PAGE_STATS:\n\t\t\t\tCFont::SetScale(X(BUTTONTAB_TEXT_SIZE_X*BUTTONTAB_TEXT_X_SCALES[PAGE_STATS]), Y(BUTTONTAB_TEXT_SIZE_Y));\n\t\t\t\tCFont::PrintString(m_position.x+X(92.0f), m_position.y+Y(408.0f), TheText.Get(\"FEB_STA\"));\n\t\t\t\tbreak;\n\t\t\tcase PAGE_LOAD:\n\t\t\t\tCFont::SetScale(X(BUTTONTAB_TEXT_SIZE_X*BUTTONTAB_TEXT_X_SCALES[PAGE_LOAD]), Y(BUTTONTAB_TEXT_SIZE_Y));\n\t\t\t\tCFont::PrintString(m_position.x+X(158.0f), m_position.y+Y(408.0f), TheText.Get(\"FEB_SAV\"));\n\t\t\t\tbreak;\n\t\t\tcase PAGE_BRIEFS:\n\t\t\t\tCFont::SetScale(X(BUTTONTAB_TEXT_SIZE_X*BUTTONTAB_TEXT_X_SCALES[PAGE_BRIEFS]), Y(BUTTONTAB_TEXT_SIZE_Y));\n\t\t\t\tCFont::PrintString(m_position.x+X(224.0f), m_position.y+Y(408.0f), TheText.Get(\"FEB_BRI\"));\n\t\t\t\tbreak;\n\t\t\tcase PAGE_CONTROLS:\n\t\t\t\tCFont::SetScale(X(BUTTONTAB_TEXT_SIZE_X*BUTTONTAB_TEXT_X_SCALES[PAGE_CONTROLS]), Y(BUTTONTAB_TEXT_SIZE_Y));\n\t\t\t\tCFont::PrintString(m_position.x+X(290.0f), m_position.y+Y(408.0f), TheText.Get(\"FEB_CON\"));\n\t\t\t\tbreak;\n\t\t\tcase PAGE_AUDIO:\n\t\t\t\tCFont::SetScale(X(BUTTONTAB_TEXT_SIZE_X*BUTTONTAB_TEXT_X_SCALES[PAGE_AUDIO]), Y(BUTTONTAB_TEXT_SIZE_Y));\n\t\t\t\tCFont::PrintString(m_position.x+X(356.0f), m_position.y+Y(408.0f), TheText.Get(\"FEB_AUD\"));\n\t\t\t\tbreak;\n\t\t\tcase PAGE_DISPLAY:\n\t\t\t\tCFont::SetScale(X(BUTTONTAB_TEXT_SIZE_X*BUTTONTAB_TEXT_X_SCALES[PAGE_DISPLAY]), Y(BUTTONTAB_TEXT_SIZE_Y));\n\t\t\t\tCFont::PrintString(m_position.x+X(422.0f), m_position.y+Y(408.0f), TheText.Get(\"FEB_DIS\"));\n\t\t\t\tbreak;\n\t\t\tcase PAGE_LANGUAGE:\n\t\t\t\tCFont::SetScale(X(BUTTONTAB_TEXT_SIZE_X*BUTTONTAB_TEXT_X_SCALES[PAGE_LANGUAGE]), Y(BUTTONTAB_TEXT_SIZE_Y));\n\t\t\t\tCFont::PrintString(m_position.x+X(488.0f), m_position.y+Y(408.0f), TheText.Get(\"FEB_LAN\"));\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tCFont::DrawFonts();\n\n\tpActiveMenuPage = nil;\n\tswitch(m_currentPage)\n\t{\n\t\tcase PAGE_STATS:\tpActiveMenuPage = &MenuPage_Stats; break;\n\t\tcase PAGE_LOAD:\t    pActiveMenuPage = pMenuSave; break;\n\t\tcase PAGE_BRIEFS:\tpActiveMenuPage = &MenuPage_Briefs; break;\n\t\tcase PAGE_CONTROLS:\tpActiveMenuPage = &MenuPage_Controls; break;\n\t\tcase PAGE_AUDIO:\tpActiveMenuPage = &MenuPage_Audio; break;\n\t\tcase PAGE_DISPLAY:\tpActiveMenuPage = &MenuPage_Display; break;\n\t\tcase PAGE_LANGUAGE:\tpActiveMenuPage = &MenuPage_Language; break;\n\t}\n\n\tCFont::SetFontStyle(FONT_BANK);\n\tCFont::SetBackgroundOff();\n\tCFont::SetScale(X(MENU_TEXT_SIZE_X), Y(MENU_TEXT_SIZE_Y));\n\tCFont::SetPropOn();\n\tCFont::SetCentreOff();\n\tCFont::SetJustifyOn();\n\tCFont::SetRightJustifyOff();\n\tCFont::SetBackGroundOnlyTextOn();\n\tCFont::SetWrapx(SCRW-X(40.0f)); // 600.0f\n\tCFont::SetRightJustifyWrap(X(38.0f));\n\n\tif(m_currentPage == PAGE_LANGUAGE)\n\t{\n\t\tCFont::SetCentreOn();\n\t\tCFont::SetCentreSize(SCRW-X(40.0f)); // 600.0f\n\t}\n\n\tif ( m_nEndPauseTimer != 0 )\n\t{\n\t\tswitch ( m_currentPage )\n\t\t{\n\t\t\tcase PAGE_LOAD:\n\t\t\tcase PAGE_BRIEFS:\n\t\t\tcase PAGE_CONTROLS:\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tCFont::SetWrapx(X(1200.0f));\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tif(pActiveMenuPage)\n\t{\n\t\tpActiveMenuPage->SetAlpha(m_fade);\n\n\t\tswitch ( m_pageState )\n\t\t{\n\t\t\tcase PAGESTATE_NORMAL:\n\t\t\t\tpActiveMenuPage->DrawNormal(m_position.x, m_position.y);\n\t\t\t\tbreak;\n\n\t\t\tcase PAGESTATE_HIGHLIGHTED:\n\t\t\t\tpActiveMenuPage->DrawHighlighted(CRGBA(rgbaATC.r, rgbaATC.g, rgbaATC.b, m_fade), m_position.x, m_position.y);\n\t\t\t\tbreak;\n\n\t\t\tcase PAGESTATE_SELECTED:\n\t\t\t\tpActiveMenuPage->Draw(CRGBA(rgbaATC.r, rgbaATC.g, rgbaATC.b, m_fade), CRGBA(MENU_SELECTED_COLOR.r, MENU_SELECTED_COLOR.g, MENU_SELECTED_COLOR.b, m_fade), m_position.x, m_position.y);\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tCFont::DrawFonts();\n\tCFont::DrawFonts();\n\tRwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR);\n\tRwRenderStateSet(rwRENDERSTATETEXTUREADDRESS, (void*)rwTEXTUREADDRESSWRAP);\n}\n\nvoid\nCMenuManager::DrawFrontEndSaveZone(void)\n{\n\tif ( bMemoryCardSpecialZone )\n\t{\n\t\tstatic uint8 counter = 0;\n\t\tcounter++;\n\t\tif ( counter & 63 )\n\t\t{\n\t\t\tFillMenuWithMemCardFileListing(&MenuSaveZoneSSL_1, TriggerSaveZone_BackToMainMenuTwoLines, TriggerSaveZone_SaveSlots, nil, 0, 34, 22);\n\n\t\t\tif ( TheMemoryCard.GetError() == CMemoryCard::ERR_NOFORMAT )\n\t\t\t{\n\t\t\t\tpActiveMenuPage = &MenuPageSaveZone_FormatCard;\n\t\t\t\tpActiveMenuPage->ActivatePage();\n\t\t\t\tbMemoryCardSpecialZone = false;\n\t\t\t}\n\t\t}\n\t}\n\n\tCSprite2d::InitPerFrame();\n\tCFont::InitPerFrame();\n\n\tRwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERNEAREST);\n\n\tm_fade = 255;\n\n\tCSprite2d::DrawRect(CRect(X(50.0f), Y(50.0f), X(590.0f), Y(398.0f)), CRGBA(0, 0, 0, 175)); //CRect(50.0f, 57.142f, 590.0f, 454.857147f)\n\n\tCFont::SetFontStyle(FONT_BANK);\n\tCFont::SetBackgroundOff();\n\tCFont::SetScale(X(MENU_TEXT_SIZE_X), Y(MENU_TEXT_SIZE_Y));\n\tCFont::SetPropOn();\n\tCFont::SetCentreOff();\n\tCFont::SetJustifyOn();\n\tCFont::SetRightJustifyOff();\n\tCFont::SetBackGroundOnlyTextOn();\n\tCFont::SetRightJustifyWrap(X(70.0f));\n\tCFont::SetWrapx(SCRW-X(70.0f)); // 570.0f\n\n\tif ( pActiveMenuPage )\n\t{\n\t\tpActiveMenuPage->SetAlpha(m_fade);\n\t\tpActiveMenuPage->Draw(CRGBA(rgbaATC.r, rgbaATC.g, rgbaATC.b, m_fade), TITLE_TEXT_COLOR, 0.0f, 0.0f);\n\t}\n\n\n\tCFont::DrawFonts();\n\tCFont::SetFontStyle(FONT_BANK);\n\tCFont::SetBackgroundOff();\n\tCFont::SetScale(X(0.44f), Y(0.68f)); // 0.44f, 0.777143f\n\tCFont::SetPropOn();\n\tCFont::SetCentreOff();\n\tCFont::SetJustifyOn();\n\tCFont::SetRightJustifyOff();\n\tCFont::SetBackGroundOnlyTextOn();\n\tCFont::SetWrapx(SCRW-X(40.0f)); //600.0f\n\tCFont::SetColor(TEXT_COLOR);\n\n\twchar *text;\n\tif ( pActiveMenuPage == &MenuPageSaveZone_FormatCard\n\t\t|| pActiveMenuPage == &MenuPageSaveZone_SaveSlots\n\t\t|| pActiveMenuPage == &MenuPageSaveZone_SaveGame )\n\t{\n\t\ttext = TheText.Get(\"FEDS_SB\"); // / button - SELECT \" button - BACK\n\t}\n\telse\n\t{\n\t\ttext = TheText.Get(\"FEDS_SE\"); // / button - SELECT\n\t}\n\n\tCFont::PrintString(X(180.0f), Y(376.0f), text); // 180.0f, 429.714294f\n\tCFont::DrawFonts();\n\n\tRwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR);\n}\n\nvoid\nCMenuManager::DrawMemoryCardStartUpMenus()\n{\n\tCFont::SetAlphaFade(255.0f);\n\tbMemoryCardStartUpMenus_ExitNow = false;\n\n\tCMenuPage page; // + 0x40 data\n\tCMenuMultiChoiceTriggered MCMenu;\n\tMCMenu.SetPosition(X(320.0f), Y(150.0f)); //171.428574f\n\n\tswitch ( TheMemoryCard.CheckCardStateAtGameStartUp(CARD_ONE) )\n\t{\n\t\tcase CMemoryCard::MCSTATE_NEED_200KB: // 200KB\n\t\t{\n\t\t\t// There is insufficient space on the Memory Card (PS2) in MEMORY CARD slot 1. At least 200KB is needed to save this application data. Do you wish to start? (YES or NO)\n\t\t\tMCMenu.AddTitle(TheText.Get(\"MCGNSP\"), 0.0f, 0.0f, 0);\n\t\t\tbreak;\n\t\t}\n\n\t\tcase CMemoryCard::MCSTATE_NEED_500KB: // 500KB\n\t\t{\n\t\t\t// There is insufficient space on the Memory Card (PS2) in MEMORY CARD slot 1. At least 500KB is needed to save this application data. Do you wish to start? (YES or NO)\n\t\t\tMCMenu.AddTitle(TheText.Get(\"MCDNSP\"), 0.0f, 0.0f, 0);\n\t\t\tbreak;\n\t\t}\n\n\t\tcase CMemoryCard::MCSTATE_OK:\n\t\tcase CMemoryCard::MCSTATE_NOCARD:\n\t\t{\n\t\t\treturn;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tMCMenu.AddOption(TheText.Get(\"FEM_NO\"),  X(30.0f),  Y(110.0f), nil, 0, 0);// 125.714294f\n\tMCMenu.AddOption(TheText.Get(\"FEM_YES\"), X(-30.0f), Y(110.0f), TriggerMCSUM_Yes, 0, 0);// 125.714294f\n\tMCMenu.SetColors(TITLE_TEXT_COLOR, TEXT_COLOR, TEXT_COLOR);\n\tpage.AddMenu(&MCMenu);\n\n\tMCMenu.GoFirst();\n\n\tpage.SetShadows(true, TEXT_SHADOW_COLOR, SHADOW_VECTOR);\n\n\tCTimer::Initialise();\n\tCTimer::StartUserPause();\n\n\twhile ( !bMemoryCardStartUpMenus_ExitNow )\n\t{\n#ifdef GTA_PC\n\t\tHandleExit();\n\n\t\tif(RsGlobal.quit)\n\t\t\treturn;\n#endif\n\n#ifdef GTA_PC\n\t\tif ( CPad::GetPad(0)->GetDPadLeftJustDown() )\n\t\t\tpage.GoLeft();\n\t\tif ( CPad::GetPad(0)->GetDPadRightJustDown() )\n\t\t\tpage.GoRight();\n\t\tif ( CPad::GetPad(0)->GetDPadUpJustDown() )\n\t\t\tpage.GoDown();\n\t\tif ( CPad::GetPad(0)->GetDPadDownJustDown() )\n\t\t\tpage.GoUp();\n\t\tif ( CPad::GetPad(0)->GetCrossJustDown() || CPad::GetPad(0)->GetEnterJustDown() || CPad::GetPad(0)->GetRightMouseJustDown() )\n\t\t\tpage.SelectCurrentOptionUnderCursor();\n\n\t\tif ( CPad::GetPad(0)->GetCircleJustDown() || CPad::GetPad(0)->GetEscapeJustDown() )\n\t\t\t;\n#else\n\t\tif ( CPad::GetPad(0)->GetDPadLeftJustDown() )\n\t\t\tpage.GoLeft();\n\t\tif ( CPad::GetPad(0)->GetDPadRightJustDown() )\n\t\t\tpage.GoRight();\n\t\tif ( CPad::GetPad(0)->GetDPadUpJustDown() )\n\t\t\tpage.GoDown();\n\t\tif ( CPad::GetPad(0)->GetDPadDownJustDown() )\n\t\t\tpage.GoUp();\n\t\tif ( CPad::GetPad(0)->GetCrossJustDown() )\n\t\t\tpage.SelectCurrentOptionUnderCursor();\n\t\tif ( CPad::GetPad(0)->GetCircleJustDown() )\n\t\t\t;\n#endif\n\n\t\tstatic int32 MemCardStatusWaiter = 0;\n\n\t\tMemCardStatusWaiter++;\n\n\t\tif ( MemCardStatusWaiter > 120 )\n\t\t{\n\t\t\tMemCardStatusWaiter = 0;\n\n\t\t\tswitch ( TheMemoryCard.CheckCardStateAtGameStartUp(CARD_ONE) )\n\t\t\t{\n\t\t\t\tcase CMemoryCard::MCSTATE_NEED_200KB:\n\t\t\t\t{\n\t\t\t\t\t// There is insufficient space on the Memory Card (PS2) in MEMORY CARD slot 1. At least 200KB is needed to save this application data. Do you wish to start? (YES or NO)\n\t\t\t\t\tMCMenu.AddTitle(TheText.Get(\"MCGNSP\"), 0.0f, 0.0f, 0);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase CMemoryCard::MCSTATE_NEED_500KB:\n\t\t\t\t{\n\t\t\t\t\t// There is insufficient space on the Memory Card (PS2) in MEMORY CARD slot 1. At least 500KB is needed to save this application data. Do you wish to start? (YES or NO)\n\t\t\t\t\tMCMenu.AddTitle(TheText.Get(\"MCDNSP\"), 0.0f, 0.0f, 0);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase CMemoryCard::MCSTATE_NOCARD:\n\t\t\t\t{\n\t\t\t\t\t// There is no Memory Card (PS2) in MEMORY CARD slot 1. Do you wish to start? (YES or NO)\n\t\t\t\t\tMCMenu.AddTitle(TheText.Get(\"MCSTNS\"), 0.0f, 0.0f, 0);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase CMemoryCard::MCSTATE_OK:\n\t\t\t\t{\n\t\t\t\t\tbMemoryCardStartUpMenus_ExitNow = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tDoRWStuffStartOfFrame(0, 0, 0, 0, 0, 0, 255);\n\t\tCFont::InitPerFrame();\n\n\t\tRwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR);\n\t\tCSprite2d *splash = LoadSplash(\"splash1\");\n\t\tsplash->Draw(CRect(0.0f, 0.0f, SCRW, SCRH), BACKGROUND_SPLASH_COLOR);\n\t\tRwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERNEAREST);\n\n\t\tSetRandomActiveTextlineColor(1);\n\n\t\tCRGBA col(rgbaATC.r, rgbaATC.g, rgbaATC.b, 255);\n\t\tCFont::SetFontStyle(FONT_BANK);\n\t\tCFont::SetBackgroundOff();\n\t\tCFont::SetScale(X(MENU_TEXT_SIZE_X), Y(MENU_TEXT_SIZE_Y));\n\t\tCFont::SetPropOn();\n\t\tCFont::SetJustifyOn();\n\t\tCFont::SetRightJustifyOff();\n\t\tCFont::SetBackGroundOnlyTextOn();\n\t\tCFont::SetWrapx(SCRW-X(60.0f)); // 580.0f\n\t\tCFont::SetCentreOn();\n\t\tCFont::SetCentreSize(SCRW-X(120.0f)); // 520.0f\n\n\t\tMCMenu.Draw(col, TITLE_TEXT_COLOR, 0.0f, 0.0f);\n\t\tCFont::DrawFonts();\n\n\t\tCFont::SetFontStyle(FONT_BANK);\n\t\tCFont::SetScale(X(0.4f), Y(0.64f)); // 0.731429\n\t\tCFont::SetPropOn();\n\t\tCFont::SetCentreOff();\n\t\tCFont::SetJustifyOn();\n\t\tCFont::SetRightJustifyOff();\n\t\tCFont::SetBackGroundOnlyTextOn();\n\t\tCFont::SetWrapx(SCRW-X(60.0f)); // 580.0f\n\t\tCFont::SetColor(TEXT_COLOR);\n\n\n\t\tCPlaceableShText text;\n\t\ttext.SetPosition(X(240.0f), Y(378.0f), false); // 432.000000\n\t\ttext.SetColor(TEXT_COLOR);\n\t\ttext.m_text = TheText.Get(\"FEDS_SE\"); // / button - SELECT\n\t\ttext.SetShadows(true, TEXT_SHADOW_COLOR, SHADOW_VECTOR);\n\t\ttext.Draw(0.0f, 0.0f);\n\n\t\tCFont::DrawFonts();\n\t\tDisplayWarningControllerMsg();\n\t\tDoRWStuffEndOfFrame();\n\t\tCPad::UpdatePads();\n\t\tCTimer::Update();\n\t}\n\n\tCTimer::EndUserPause();\n\tCTimer::Stop();\n\n\tfor ( int32 i = 0; i < 100; i++ )\n\t{\n#ifdef GTA_PC\n\t\tHandleExit();\n#endif\n\t\tDoRWStuffStartOfFrame(0, 0, 0, 0, 0, 0, 255);\n\n\t\tRwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR);\n\t\tCSprite2d *splash = LoadSplash(\"splash1\");\n\t\tsplash->Draw(CRect(0.0f, 0.0f, SCRW, SCRH), BACKGROUND_SPLASH_COLOR);\n\t\tRwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERNEAREST);\n\n\t\tDoRWStuffEndOfFrame();\n\t}\n}\n\nvoid\nCMenuManager::Process(void)\n{\n\tif ( m_bSaveMenuActive || m_bInSaveZone || TheCamera.GetScreenFadeStatus() == FADE_0 )\n\t{\n\t\tInitialiseMenusOnce();\n\t\tm_bWantToRestart = false;\n\t\tWorkOutMenuState(false);\n\n\t\tif ( m_bMenuActive )\n\t\t{\n\t\t\tif ( !m_bInSaveZone )\n\t\t\t\tLoadAllTextures();\n\t\t\tInitialiseMenuContents();\n\t\t\tSetRandomActiveTextlineColor(0);\n\t\t\tProcessControllerInput();\n\t\t}\n\t\telse\n\t\t{\n\t\t\tAnaliseMenuContents();\n\t\t\tpMenuSave = &MenuPage_SaveBasic;\n\t\t\tm_pageState = PAGESTATE_NORMAL;\n\t\t\tbMemoryCardSpecialZone = false;\n\t\t\tbIgnoreTriangleButton = false;\n\t\t\tUnloadTextures();\n\t\t\tm_bInSaveZone = false;\n\t\t\tm_bRenderGameInMenu = false;\n\t\t\tgErrorSampleTriggered = true;\n\t\t}\n\t}\n}\n\nvoid\nCMenuManager::WorkOutMenuState(uint8 bExit)\n{\n#ifdef GTA_PC\n\tbool bIsStartPressed = CPad::GetPad(0)->GetStartJustDown() || (m_pageState == PAGESTATE_NORMAL && CPad::GetPad(0)->GetEscapeJustDown());\n#else\n\tbool bIsStartPressed = CPad::GetPad(0)->GetStartJustDown();\n#endif\n\tbool bIsCreditsOrDraw      = CCredits::AreCreditsDone() || m_bMenuActive;\n\tbool bIsDemoOrDraw         = m_bMenuActive || CGame::bDemoMode;\n\n\tif ( (bIsStartPressed && bIsCreditsOrDraw) || bExit || (!bIsDemoOrDraw && CPad::IsNoOrObsolete()) )\n\t{\n\t\tif ( m_nStartPauseTimer == 0 && m_nEndPauseTimer == 0 )\n\t\t{\n\t\t\tm_bMenuActive = !m_bMenuActive;\n\n\t\t\tif ( !m_bMenuActive )\n\t\t\t{\n\t\t\t\tDMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_STARTING, 0);\n\t\t\t\tDMAudio.ChangeMusicMode(MUSICMODE_GAME);\n\t\t\t\tgMusicPlaying = false;\n\t\t\t\tbMemoryCardSpecialZone = false;\n\t\t\t\tbIgnoreTriangleButton = false;\n\n\t\t\t\tm_bMenuActive = true;\n\n\t\t\t\tm_nEndPauseTimer = CTimer::GetTimeInMillisecondsPauseMode() + 800;\n\n\t\t\t\tif ( m_currentPage == PAGE_CONTROLS || m_currentPage == PAGE_BRIEFS || m_currentPage == PAGE_LOAD )\n\t\t\t\t{\n\t\t\t\t\tm_nSlidingDir = CGeneral::GetRandomNumber() & (SLIDE_MAX-1);\n\n\t\t\t\t\tswitch ( m_nSlidingDir ) //m_nSlidingDir &= ~1;\n\t\t\t\t\t{\n\t\t\t\t\t\tcase SLIDE_TO_LEFT:  m_nSlidingDir = SLIDE_TO_TOP;    break;\n\t\t\t\t\t\tcase SLIDE_TO_RIGHT: m_nSlidingDir = SLIDE_TO_BOTTOM; break;\n\t\t\t\t\t}\n\n\t\t\t\t\tm_position.y = Y(500.0f); // 571.428589f;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tDMAudio.ChangeMusicMode(MUSICMODE_FRONTEND);\n\n\t\t\t\tif ( DMAudio.GetRadioInCar() < 9 )\n\t\t\t\t\tm_PrefsRadioStation = DMAudio.GetRadioInCar();\n\t\t\t\telse\n\t\t\t\t\tm_PrefsRadioStation = CGeneral::GetRandomNumber() % 9;\n\n\t\t\t\tCTimer::StartUserPause();\n\t\t\t\tCPad::StopPadsShaking();\n\t\t\t\tm_nStartPauseTimer = CTimer::GetTimeInMillisecondsPauseMode() + 800;\n\t\t\t\tm_nSlidingDir = CGeneral::GetRandomNumber() & (SLIDE_MAX-1);\n\n\t\t\t\tswitch ( m_nSlidingDir )\n\t\t\t\t{\n\t\t\t\t\tcase SLIDE_TO_RIGHT:  m_position.y = Y(612.5f); break;\n\t\t\t\t\tcase SLIDE_TO_LEFT:   m_position.y = Y(612.5f); break;\n\t\t\t\t\tcase SLIDE_TO_BOTTOM: m_position.y = Y(500.0f); break;\n\t\t\t\t\tcase SLIDE_TO_TOP:    m_position.y = Y(500.0f); break;\n\t\t\t\t\tdefault:              m_position.y = Y(500.0f); break;\n\t\t\t\t}\n\n\t\t\t\tif ( m_currentPage == PAGE_CONTROLS || m_currentPage == PAGE_BRIEFS )\n\t\t\t\t{\n\t\t\t\t\tm_nSlidingDir = CGeneral::GetRandomNumber() & (SLIDE_MAX-1);\n\n\t\t\t\t\tswitch ( m_nSlidingDir ) //m_nSlidingDir &= ~1;\n\t\t\t\t\t{\n\t\t\t\t\t\tcase SLIDE_TO_LEFT:  m_nSlidingDir = SLIDE_TO_TOP;    break;\n\t\t\t\t\t\tcase SLIDE_TO_RIGHT: m_nSlidingDir = SLIDE_TO_BOTTOM; break;\n\t\t\t\t\t}\n\n\t\t\t\t\tm_position.y = Y(500.0f); //571.428589f\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif ( m_bSaveMenuActive && !m_bInSaveZone && !TheMemoryCard._bunk2)\n\t{\n\t\tm_bSaveMenuActive = false;\n\t\tm_bInSaveZone = true;\n\t\tm_bRenderGameInMenu = true;\n\t\tm_bMenuActive = true;\n\t\tCTimer::StartUserPause();\n\t\tpActiveMenuPage = &MenuPageSaveZone_SaveGame;\n\t}\n\n\tif ( m_pageState == PAGESTATE_NORMAL && gMusicPlaying )\n\t{\n\t\tDMAudio.StopFrontEndTrack();\n\t\tgMusicPlaying = false;\n\t}\n\n\tif ( m_nChangePageTimer != 0 && CTimer::GetTimeInMillisecondsPauseMode() >= m_nChangePageTimer )\n\t{\n\t\tm_nChangePageTimer = 0;\n\t\tpMenuSave = &MenuPage_SaveBasic;\n\t\tm_currentPage = m_newPage;\n\t}\n\n\tif ( m_nPageLeftTimer != 0 && CTimer::GetTimeInMillisecondsPauseMode() >= m_nPageLeftTimer )\n\t\tm_nPageLeftTimer = 0;\n\n\tif ( m_nPageRightTimer != 0 && CTimer::GetTimeInMillisecondsPauseMode() >= m_nPageRightTimer )\n\t\tm_nPageRightTimer = 0;\n\n\tif ( m_nStartPauseTimer != 0 && CTimer::GetTimeInMillisecondsPauseMode() >= m_nStartPauseTimer )\n\t\tm_nStartPauseTimer = 0;\n\n\tif ( m_nEndPauseTimer != 0 && CTimer::GetTimeInMillisecondsPauseMode() >= m_nEndPauseTimer )\n\t{\n\t\tm_nEndPauseTimer = 0;\n\t\tm_bMenuActive = false;\n\t\tm_bMenuActive = false;\n\t\tm_bInSaveZone = false;\n\t\tCTimer::EndUserPause();\n\t}\n}\n\nvoid\nCMenuManager::ProcessControllerInput(void)\n{\n\tif ( TimeToStopPadShaking != 0 && TimeToStopPadShaking < CTimer::GetTimeInMillisecondsPauseMode() )\n\t{\n\t\tCPad::StopPadsShaking();\n\t\tTimeToStopPadShaking = 0;\n\t}\n\n#ifdef GTA_PC\n\tif ( CPad::GetPad(0)->GetDPadLeft() || CPad::GetPad(0)->GetLeft() )\n#else\n\tif ( CPad::GetPad(0)->GetDPadLeft() )\n#endif\n\t{\n\t\tswitch ( m_pageState )\n\t\t{\n\t\t\tcase PAGESTATE_NORMAL:\n\t\t\tcase PAGESTATE_HIGHLIGHTED:\n\t\t\t\tbreak;\n\n\t\t\tcase PAGESTATE_SELECTED:\n\t\t\t{\n\t\t\t\tif ( pActiveMenuPage )\n\t\t\t\t\tpActiveMenuPage->GoLeftStill();\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n#ifdef GTA_PC\n\tif ( CPad::GetPad(0)->GetDPadRight() || CPad::GetPad(0)->GetRight() )\n#else\n\tif ( CPad::GetPad(0)->GetDPadRight() )\n#endif\n\t{\n\t\tswitch ( m_pageState )\n\t\t{\n\t\t\tcase PAGESTATE_NORMAL:\n\t\t\tcase PAGESTATE_HIGHLIGHTED:\n\t\t\t\tbreak;\n\n\t\t\tcase PAGESTATE_SELECTED:\n\t\t\t{\n\t\t\t\tif ( pActiveMenuPage )\n\t\t\t\t\tpActiveMenuPage->GoRightStill();\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n#ifdef GTA_PC\n\tif ( CPad::GetPad(0)->GetDPadLeftJustDown() || CPad::GetPad(0)->GetLeftJustDown() )\n#else\n\tif ( CPad::GetPad(0)->GetDPadLeftJustDown() )\n#endif\n\t\tProcessDPadLeftJustDown();\n\n#ifdef GTA_PC\n\tif ( CPad::GetPad(0)->GetDPadRightJustDown() || CPad::GetPad(0)->GetRightJustDown() )\n#else\n\tif ( CPad::GetPad(0)->GetDPadRightJustDown() )\n#endif\n\t\tProcessDPadRightJustDown();\n\n#ifdef GTA_PC\n\tif ( CPad::GetPad(0)->GetDPadUp() || CPad::GetPad(0)->GetUp() )\n#else\n\tif ( CPad::GetPad(0)->GetDPadUp() )\n#endif\n\t{\n\t\tswitch ( m_pageState )\n\t\t{\n\t\t\tcase PAGESTATE_NORMAL:\n\t\t\t{\n\t\t\t\tif ( m_currentPage == PAGE_STATS )\n\t\t\t\t{\n\t\t\t\t\tif ( pActiveMenuPage )\n\t\t\t\t\t\tpActiveMenuPage->GoUpStill();\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase PAGESTATE_HIGHLIGHTED:\n\t\t\t\tbreak;\n\n\t\t\tcase PAGESTATE_SELECTED:\n\t\t\t{\n\t\t\t\tif ( pActiveMenuPage )\n\t\t\t\t\tpActiveMenuPage->GoUpStill();\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n#ifdef GTA_PC\n\tif ( CPad::GetPad(0)->GetDPadDown() || CPad::GetPad(0)->GetDown() )\n#else\n\tif ( CPad::GetPad(0)->GetDPadDown() )\n#endif\n\t{\n\t\tswitch ( m_pageState )\n\t\t{\n\t\t\tcase PAGESTATE_NORMAL:\n\t\t\t{\n\t\t\t\tif ( m_currentPage == PAGE_STATS )\n\t\t\t\t{\n\t\t\t\t\tif ( pActiveMenuPage )\n\t\t\t\t\t\tpActiveMenuPage->GoDownStill();\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase PAGESTATE_HIGHLIGHTED:\n\t\t\t\tbreak;\n\n\t\t\tcase PAGESTATE_SELECTED:\n\t\t\t{\n\t\t\t\tif ( pActiveMenuPage )\n\t\t\t\t\tpActiveMenuPage->GoDownStill();\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n#ifdef GTA_PC\n\tif ( CPad::GetPad(0)->GetDPadUpJustDown() || CPad::GetPad(0)->GetUpJustDown() )\n#else\n\tif ( CPad::GetPad(0)->GetDPadUpJustDown() )\n#endif\n\t\tProcessDPadUpJustDown();\n\n#ifdef GTA_PC\n\tif ( CPad::GetPad(0)->GetDPadDownJustDown() || CPad::GetPad(0)->GetDownJustDown() )\n#else\n\tif ( CPad::GetPad(0)->GetDPadDownJustDown() )\n#endif\n\t\tProcessDPadDownJustDown();\n\n\tif ( CPad::GetPad(0)->GetLeftShoulder1JustDown() )\n\t{\n\t\tswitch ( m_pageState )\n\t\t{\n\t\t\tcase PAGESTATE_NORMAL:\n\t\t\t\tProcessDPadLeftJustDown();\n\t\t\t\tbreak;\n\n\t\t\tcase PAGESTATE_HIGHLIGHTED:\n\t\t\tcase PAGESTATE_SELECTED:\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tif ( CPad::GetPad(0)->GetRightShoulder1JustDown() )\n\t{\n\t\tswitch ( m_pageState )\n\t\t{\n\t\t\tcase PAGESTATE_NORMAL:\n\t\t\t\tProcessDPadRightJustDown();\n\t\t\t\tbreak;\n\n\t\t\tcase PAGESTATE_HIGHLIGHTED:\n\t\t\tcase PAGESTATE_SELECTED:\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n#ifdef GTA_PC\n\tif ( CPad::GetPad(0)->GetCrossJustDown() || CPad::GetPad(0)->GetEnterJustDown() || CPad::GetPad(0)->GetRightMouseJustDown() )\n#else\n\tif ( CPad::GetPad(0)->GetCrossJustDown() )\n#endif\n\t\tProcessDPadCrossJustDown();\n\n#ifdef GTA_PC\n\tif ( CPad::GetPad(0)->GetTriangleJustDown() || CPad::GetPad(0)->GetBackspaceJustDown() || (m_pageState != PAGESTATE_NORMAL && CPad::GetPad(0)->GetEscapeJustDown()) )\n#else\n\tif ( CPad::GetPad(0)->GetTriangleJustDown() )\n#endif\n\t\tProcessDPadTriangleJustDown();\n}\n\n\nvoid\nCMenuManager::ProcessDPadLeftJustDown(void)\n{\n\tif ( m_bInSaveZone )\n\t{\n\t\tif ( pActiveMenuPage )\n\t\t{\n\t\t\tpActiveMenuPage->GoLeft();\n\n\t\t\tif ( pActiveMenuPage->m_pCurrentControl == &MenuSaveZoneSSL_1 )\n\t\t\t{\n\t\t\t\tif ( MenuSaveZoneSSL_1.m_numOptions < 2 )\n\t\t\t\t\t;\n\t\t\t\telse\n\t\t\t\t\tDMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0);\n\t\t\t}\n\t\t\telse\n\t\t\t\tDMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0);\n\t\t}\n\t}\n\telse\n\t{\n\t\tswitch ( m_pageState )\n\t\t{\n\t\t\tcase PAGESTATE_NORMAL:\n\t\t\t{\n\t\t\t\tif ( !bMemoryCardSpecialZone && !m_bInSaveZone )\n\t\t\t\t{\n\t\t\t\t\tif ( m_nChangePageTimer == 0 )\n\t\t\t\t\t{\n\t\t\t\t\t\tif ( --m_newPage < PAGE_FIRST ) m_newPage = PAGE_LAST;\n\n\t\t\t\t\t\tm_nPageLeftTimer   = CTimer::GetTimeInMillisecondsPauseMode() + 300;\n\t\t\t\t\t\tm_nPageRightTimer  = 0;\n\t\t\t\t\t\tm_nChangePageTimer = CTimer::GetTimeInMillisecondsPauseMode() + 250;\n\t\t\t\t\t\tfield_18 = m_newPage;\n\t\t\t\t\t\tDMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NEW_PAGE, 0);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase PAGESTATE_HIGHLIGHTED:\n\t\t\t{\n\t\t\t\tif ( pActiveMenuPage )\n\t\t\t\t\tpActiveMenuPage->GoLeftMenuOnPage();\n\n\t\t\t\tDMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0);\n\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase PAGESTATE_SELECTED:\n\t\t\t{\n\t\t\t\tif ( pActiveMenuPage )\n\t\t\t\t{\n\t\t\t\t\tpActiveMenuPage->GoLeft();\n\n\t\t\t\t\tif ( m_currentPage == PAGE_AUDIO)\n\t\t\t\t\t{\n\t\t\t\t\t\tif ( pActiveMenuPage->m_pCurrentControl == &MenuAudio_1 )\n\t\t\t\t\t\t\t;\n\t\t\t\t\t\telse if ( pActiveMenuPage->m_pCurrentControl == &MenuAudio_2 )\n\t\t\t\t\t\t\t;\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tDMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0);\n\t\t\t\t\t}\n\t\t\t\t\telse if ( m_currentPage == PAGE_DISPLAY)\n\t\t\t\t\t{\n\t\t\t\t\t\tif ( pActiveMenuPage->m_pCurrentControl == &MenuDisplay_1 )\n\t\t\t\t\t\t\t;\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tDMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tif ( pActiveMenuPage->m_pCurrentControl == &MenuSaveDG_2 )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif ( MenuSaveDG_2.m_numOptions < 2 )\n\t\t\t\t\t\t\t\t;\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\tDMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if ( pActiveMenuPage->m_pCurrentControl == &MenuSaveLG_2 )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif ( MenuSaveLG_2.m_numOptions < 2 )\n\t\t\t\t\t\t\t\t;\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\tDMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tDMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nCMenuManager::ProcessDPadRightJustDown(void)\n{\n\tif ( m_bInSaveZone )\n\t{\n\t\tif ( pActiveMenuPage )\n\t\t{\n\t\t\tpActiveMenuPage->GoRight();\n\n\t\t\tif ( pActiveMenuPage->m_pCurrentControl == &MenuSaveZoneSSL_1 )\n\t\t\t{\n\t\t\t\tif ( MenuSaveZoneSSL_1.m_numOptions < 2 )\n\t\t\t\t\t;\n\t\t\t\telse\n\t\t\t\t\tDMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0);\n\t\t\t}\n\t\t\telse\n\t\t\t\tDMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0);\n\t\t}\n\t}\n\telse\n\t{\n\t\tswitch ( m_pageState )\n\t\t{\n\t\t\tcase PAGESTATE_NORMAL:\n\t\t\t{\n\t\t\t\tif ( !bMemoryCardSpecialZone && !m_bInSaveZone )\n\t\t\t\t{\n\t\t\t\t\tif ( m_nChangePageTimer == 0 )\n\t\t\t\t\t{\n\t\t\t\t\t\tif ( ++m_newPage > PAGE_LAST ) m_newPage = PAGE_FIRST;\n\n\t\t\t\t\t\tm_nPageLeftTimer   = 0;\n\t\t\t\t\t\tm_nPageRightTimer  = CTimer::GetTimeInMillisecondsPauseMode() + 300;\n\t\t\t\t\t\tm_nChangePageTimer = CTimer::GetTimeInMillisecondsPauseMode() + 250;\n\t\t\t\t\t\tfield_18 = m_newPage;\n\t\t\t\t\t\tDMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NEW_PAGE, 0);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase PAGESTATE_HIGHLIGHTED:\n\t\t\t{\n\t\t\t\tif ( pActiveMenuPage )\n\t\t\t\t\tpActiveMenuPage->GoRightMenuOnPage();\n\n\t\t\t\tDMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0);\n\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase PAGESTATE_SELECTED:\n\t\t\t{\n\t\t\t\tif ( pActiveMenuPage )\n\t\t\t\t{\n\t\t\t\t\tpActiveMenuPage->GoRight();\n\n\t\t\t\t\tif ( m_currentPage == PAGE_AUDIO)\n\t\t\t\t\t{\n\t\t\t\t\t\tif ( pActiveMenuPage->m_pCurrentControl == &MenuAudio_1 )\n\t\t\t\t\t\t\t;\n\t\t\t\t\t\telse if ( pActiveMenuPage->m_pCurrentControl == &MenuAudio_2 )\n\t\t\t\t\t\t\t;\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tDMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0);\n\t\t\t\t\t}\n\t\t\t\t\telse if ( m_currentPage == PAGE_DISPLAY)\n\t\t\t\t\t{\n\t\t\t\t\t\tif ( pActiveMenuPage->m_pCurrentControl == &MenuDisplay_1 )\n\t\t\t\t\t\t\t;\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tDMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tif ( pActiveMenuPage->m_pCurrentControl == &MenuSaveDG_2 )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif ( MenuSaveDG_2.m_numOptions < 2 )\n\t\t\t\t\t\t\t\t;\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\tDMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if ( pActiveMenuPage->m_pCurrentControl == &MenuSaveLG_2 )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif ( MenuSaveLG_2.m_numOptions < 2 )\n\t\t\t\t\t\t\t\t;\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\tDMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tDMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nCMenuManager::ProcessDPadUpJustDown(void)\n{\n\tif ( m_bInSaveZone )\n\t{\n\t\tif ( pActiveMenuPage )\n\t\t{\n\t\t\tpActiveMenuPage->GoUp();\n\n\t\t\tif ( pActiveMenuPage->m_pCurrentControl == &MenuSaveZoneSSL_1 )\n\t\t\t{\n\t\t\t\tif ( MenuSaveZoneSSL_1.m_numOptions < 2 )\n\t\t\t\t\t;\n\t\t\t\telse\n\t\t\t\t\tDMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0);\n\t\t\t}\n\t\t\telse\n\t\t\t\tDMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0);\n\t\t}\n\t}\n\telse\n\t{\n\t\tswitch ( m_pageState )\n\t\t{\n\t\t\tcase PAGESTATE_NORMAL:\n\t\t\t\tbreak;\n\n\t\t\tcase PAGESTATE_HIGHLIGHTED:\n\t\t\t{\n\t\t\t\tif ( pActiveMenuPage )\n\t\t\t\t\tpActiveMenuPage->GoUpMenuOnPage();\n\n\t\t\t\tDMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase PAGESTATE_SELECTED:\n\t\t\t{\n\t\t\t\tif ( pActiveMenuPage )\n\t\t\t\t{\n\t\t\t\t\tpActiveMenuPage->GoUp();\n\n\t\t\t\t\tif ( pActiveMenuPage->m_pCurrentControl == &MenuSaveDG_2 )\n\t\t\t\t\t{\n\t\t\t\t\t\tif ( MenuSaveDG_2.m_numOptions < 2 )\n\t\t\t\t\t\t\t;\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tDMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0);\n\t\t\t\t\t}\n\t\t\t\t\telse if ( pActiveMenuPage->m_pCurrentControl == &MenuSaveLG_2 )\n\t\t\t\t\t{\n\t\t\t\t\t\tif ( MenuSaveLG_2.m_numOptions < 2 )\n\t\t\t\t\t\t\t;\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tDMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t\tDMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0);\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nCMenuManager::ProcessDPadDownJustDown(void)\n{\n\tif ( m_bInSaveZone )\n\t{\n\t\tif ( pActiveMenuPage )\n\t\t{\n\t\t\tpActiveMenuPage->GoDown();\n\n\t\t\tif ( pActiveMenuPage->m_pCurrentControl == &MenuSaveZoneSSL_1 )\n\t\t\t{\n\t\t\t\tif ( MenuSaveZoneSSL_1.m_numOptions < 2 )\n\t\t\t\t\t;\n\t\t\t\telse\n\t\t\t\t\tDMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0);\n\t\t\t}\n\t\t\telse\n\t\t\t\tDMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0);\n\t\t}\n\t}\n\telse\n\t{\n\t\tswitch ( m_pageState )\n\t\t{\n\t\t\tcase PAGESTATE_NORMAL:\n\t\t\t\tbreak;\n\n\t\t\tcase PAGESTATE_HIGHLIGHTED:\n\t\t\t{\n\t\t\t\tif ( pActiveMenuPage )\n\t\t\t\t\tpActiveMenuPage->GoDownMenuOnPage();\n\n\t\t\t\tDMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0);\n\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase PAGESTATE_SELECTED:\n\t\t\t{\n\t\t\t\tif ( pActiveMenuPage )\n\t\t\t\t{\n\t\t\t\t\tpActiveMenuPage->GoDown();\n\n\t\t\t\t\tif ( pActiveMenuPage->m_pCurrentControl == &MenuSaveDG_2 )\n\t\t\t\t\t{\n\t\t\t\t\t\tif ( MenuSaveDG_2.m_numOptions < 2 )\n\t\t\t\t\t\t\t;\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tDMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0);\n\t\t\t\t\t}\n\t\t\t\t\telse if ( pActiveMenuPage->m_pCurrentControl == &MenuSaveLG_2 )\n\t\t\t\t\t{\n\t\t\t\t\t\tif ( MenuSaveLG_2.m_numOptions < 2 )\n\t\t\t\t\t\t\t;\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tDMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t\tDMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NAVIGATION, 0);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nCMenuManager::ProcessDPadTriangleJustDown(void)\n{\n\tif ( pActiveMenuPage )\n\t{\n\t\tpActiveMenuPage->SelectDefaultCancelAction();\n\n\t\tif ( m_bMenuActive || m_bInSaveZone )\n\t\t{\n\t\t\tif ( bIgnoreTriangleButton )\n\t\t\t{\n\t\t\t\tif ( m_bInSaveZone )\n\t\t\t\t\tDMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_BACK, 0);\n\t\t\t\telse if ( pActiveMenuPage->m_pCurrentControl == &MenuSaveDG_2 || pActiveMenuPage->m_pCurrentControl == &MenuSaveLG_2 )\n\t\t\t\t\tDMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_BACK, 0);\n\t\t\t}\n\t\t\telse if ( !bIgnoreTriangleButton )\n\t\t\t{\n\t\t\t\tswitch ( m_pageState )\n\t\t\t\t{\n\t\t\t\t\tcase PAGESTATE_NORMAL:\n\t\t\t\t\t\tWorkOutMenuState(true);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase PAGESTATE_HIGHLIGHTED:\n\t\t\t\t\t\tm_pageState = PAGESTATE_NORMAL;\n\t\t\t\t\t\tDMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NEW_PAGE, 0);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase PAGESTATE_SELECTED:\n\t\t\t\t\t{\n\t\t\t\t\t\tm_pageState = PAGESTATE_HIGHLIGHTED;\n\t\t\t\t\t\tif ( pActiveMenuPage )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif ( pActiveMenuPage->m_numControls == 1 )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tm_pageState = PAGESTATE_NORMAL;\n\t\t\t\t\t\t\t\tDMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NEW_PAGE, 0);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\tDMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_BACK, 0);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\telse\n\t{\n\t\tif ( !bIgnoreTriangleButton )\n\t\t{\n\t\t\tswitch ( m_pageState )\n\t\t\t{\n\t\t\t\tcase PAGESTATE_NORMAL:\n\t\t\t\t\tWorkOutMenuState(false);\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase PAGESTATE_HIGHLIGHTED:\n\t\t\t\t\tm_pageState = PAGESTATE_NORMAL;\n\t\t\t\t\tDMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NEW_PAGE, 0);\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase PAGESTATE_SELECTED:\n\t\t\t\t{\n\t\t\t\t\tm_pageState = PAGESTATE_HIGHLIGHTED;\n\t\t\t\t\tif ( pActiveMenuPage )\n\t\t\t\t\t{\n\t\t\t\t\t\tif ( pActiveMenuPage->m_numControls == 1 )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tm_pageState = PAGESTATE_NORMAL;\n\t\t\t\t\t\t\tDMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_NEW_PAGE, 0);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tDMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_BACK, 0);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nCMenuManager::ProcessDPadCrossJustDown(void)\n{\n\tif ( m_bInSaveZone )\n\t{\n\t\tif ( pActiveMenuPage )\n\t\t\tpActiveMenuPage->SelectCurrentOptionUnderCursor();\n\n\t\tDMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0);\n\t}\n\telse\n\t{\n\t\tif ( m_currentPage != PAGE_STATS && m_currentPage != PAGE_BRIEFS)\n\t\t{\n\t\t\tswitch ( m_pageState )\n\t\t\t{\n\t\t\t\tcase PAGESTATE_NORMAL:\n\t\t\t\t{\n\t\t\t\t\tm_pageState = PAGESTATE_HIGHLIGHTED;\n\t\t\t\t\tif ( pActiveMenuPage )\n\t\t\t\t\t{\n\t\t\t\t\t\tif ( pActiveMenuPage->m_numControls == 1 )\n\t\t\t\t\t\t\tm_pageState = PAGESTATE_SELECTED;\n\t\t\t\t\t}\n\n\t\t\t\t\tswitch ( m_currentPage )\n\t\t\t\t\t{\n\t\t\t\t\t\tcase PAGE_AUDIO:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (   pActiveMenuPage->m_pCurrentControl == &MenuAudio_1\n\t\t\t\t\t\t\t\t|| pActiveMenuPage->m_pCurrentControl == &MenuAudio_2\n\t\t\t\t\t\t\t\t|| pActiveMenuPage->m_pCurrentControl == &MenuAudio_3\n\t\t\t\t\t\t\t\t|| pActiveMenuPage->m_pCurrentControl == &MenuAudio_4 )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tif ( !gMusicPlaying )\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tDMAudio.PlayFrontEndTrack(m_PrefsRadioStation, 1);\n\t\t\t\t\t\t\t\t\tgMusicPlaying = true;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tDMAudio.StopFrontEndTrack();\n\t\t\t\t\t\t\t\tgMusicPlaying = false;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tDMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase PAGESTATE_HIGHLIGHTED:\n\t\t\t\t{\n\t\t\t\t\tm_pageState = PAGESTATE_SELECTED;\n\t\t\t\t\tDoHackingMenusAtPageBrowse();\n\t\t\t\t\tif ( pActiveMenuPage )\n\t\t\t\t\t{\n\t\t\t\t\t\tif ( pActiveMenuPage->IsActiveMenuTwoState())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tm_pageState = PAGESTATE_HIGHLIGHTED;\n\t\t\t\t\t\t\tpActiveMenuPage->ActiveMenuTwoState_SelectNextPosition();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tswitch ( m_currentPage )\n\t\t\t\t\t{\n\t\t\t\t\t\tcase PAGE_AUDIO:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif ( pActiveMenuPage->m_pCurrentControl != &MenuAudio_4 )\n\t\t\t\t\t\t\t\tDMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0);\n\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tDMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0);\n\t\t\t\t\t\t\tDMAudio.StopFrontEndTrack();\n\t\t\t\t\t\t\tgMusicPlaying = false;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase PAGESTATE_SELECTED:\n\t\t\t\t{\n\t\t\t\t\tif ( pActiveMenuPage )\n\t\t\t\t\t{\n\t\t\t\t\t\tpActiveMenuPage->SelectCurrentOptionUnderCursor();\n\n\t\t\t\t\t\tswitch ( m_currentPage )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcase PAGE_AUDIO:\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tif ( pActiveMenuPage->m_pCurrentControl != &MenuAudio_3 )\n\t\t\t\t\t\t\t\t\tm_pageState = PAGESTATE_HIGHLIGHTED;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tcase PAGE_LOAD:\n\t\t\t\t\t\t\tcase PAGE_LANGUAGE:\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\tm_pageState = PAGESTATE_HIGHLIGHTED;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tDMAudio.PlayFrontEndSound(SOUND_FRONTEND_MENU_SETTING_CHANGE, 0);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nCMenuManager::DoHackingMenusAtPageBrowse(void)\n{\n\tif ( pActiveMenuPage )\n\t{\n\t\tswitch ( m_currentPage )\n\t\t{\n\t\t\tcase PAGE_CONTROLS:\n\t\t\t{\n\t\t\t\tif ( pActiveMenuPage->m_pCurrentControl == &MenuControls_1  )\n\t\t\t\t{\n\t\t\t\t\tint32 sel = MenuControls_1.GetMenuSelection();\n\t\t\t\t\tMenuControls_1.GoFirst();\n\n\t\t\t\t\tfor ( int32 i = 0; i < sel; i++ )\n\t\t\t\t\t\tMenuControls_1.GoNext();\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase PAGE_AUDIO:\n\t\t\t{\n\t\t\t\tif ( pActiveMenuPage->m_pCurrentControl == &MenuAudio_3  )\n\t\t\t\t{\n\t\t\t\t\tint32 sel = MenuAudio_3.GetMenuSelection();\n\t\t\t\t\tMenuAudio_3.GoFirst();\n\n\t\t\t\t\tfor ( int32 i = 0; i < sel; i++ )\n\t\t\t\t\t\tMenuAudio_3.GoNext();\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nCMenuManager::SetSoundLevelsForMusicMenu(void)\n{\n\tDMAudio.SetMusicMasterVolume(m_PrefsMusicVolume);\n\tDMAudio.SetEffectsMasterVolume(m_PrefsSfxVolume);\n}\n\nvoid\nCMenuManager::FilterOutColorMarkersFromString(wchar *string, CRGBA &color)\n{\n\twchar buf[300];\n\tUnicodeStrcpy(buf, string);\n\n\twchar *src = buf;\n\twchar *dst = string;\n\twhile ( *src != '\\0' )\n\t{\n\t\tif ( *src == '~' )\n\t\t{\n\t\t\tsrc++;\n\n\t\t\tif ( *src == 'l' )      color = CRGBA(0, 0, 0, 255);\n\t\t\telse if ( *src == 'p' ) color = CRGBA(255, 0, 255, 255);\n\t\t\telse if ( *src == 'y' ) color = CRGBA(255, 255, 0, 255);\n\t\t\telse if ( *src == 'w' ) color = CRGBA(255, 255, 255, 255);\n\t\t\telse if ( *src == 'b' ) color = CRGBA(40, 40, 255, 255);\n\t\t\telse if ( *src == 'g' ) color = CRGBA(40, 235, 40, 255);\n\t\t\telse if ( *src == 'r' ) color = CRGBA(255, 0, 0, 255);\n\n\t\t\twhile ( *src++ != '~' )\n\t\t\t\t;\n\t\t}\n\t\telse\n\t\t\t*dst++ = *src++;\n\t}\n\n\t*dst = '\\0';\n}\n\n#endif\n"
  },
  {
    "path": "src/core/Frontend_PS2.h",
    "content": "#pragma once\n#include \"Sprite2d.h\"\n\nenum\n{\n\tPAGE_STATS,\n\tPAGE_LOAD,\n\tPAGE_BRIEFS,\n\tPAGE_CONTROLS,\n\tPAGE_AUDIO,\n\tPAGE_DISPLAY,\n\tPAGE_LANGUAGE,\n\n\tNUM_PAGES,\n\tPAGE_FIRST = PAGE_STATS,\n\tPAGE_LAST = PAGE_LANGUAGE,\n};\n\nenum \n{\n\tPAGESTATE_NORMAL = 0,\n\tPAGESTATE_HIGHLIGHTED,\n\tPAGESTATE_SELECTED\n};\n\n\nenum eFrontendSprites\n{\n\tFE2_MAINPANEL_UL,\n\tFE2_MAINPANEL_UR,\n\tFE2_MAINPANEL_DL,\n\tFE2_MAINPANEL_DR,\n\tFE2_MAINPANEL_DR2,\n\tFE2_TABACTIVE,\n\tFE_ICONBRIEF,\n\tFE_ICONSTATS,\n\tFE_ICONCONTROLS,\n\tFE_ICONSAVE,\n\tFE_ICONAUDIO,\n\tFE_ICONDISPLAY,\n\tFE_ICONLANGUAGE,\n\tFE_CONTROLLER,\n\tFE_CONTROLLERSH,\n\tFE_ARROWS1,\n\tFE_ARROWS2,\n\tFE_ARROWS3,\n\tFE_ARROWS4,\n\tFE_RADIO1,\n\tFE_RADIO2,\n\tFE_RADIO3,\n\tFE_RADIO4,\n\tFE_RADIO5,\n\tFE_RADIO6,\n\tFE_RADIO7,\n\tFE_RADIO8,\n\tFE_RADIO9,\n\n\tNUM_FE_SPRITES\n};\n\n\nclass CSprite2d;\nclass CVector2D;\n\n#ifdef GTA_PC\nenum eControlMethod\n{\n\tCONTROL_STANDARD = 0,\n\tCONTROL_CLASSIC,\n};\n#endif\n\nclass CMenuManager\n{\npublic:\n\tenum LANGUAGE\n\t{\n\t\tLANGUAGE_AMERICAN,\n\t\tLANGUAGE_FRENCH,\n\t\tLANGUAGE_GERMAN,\n\t\tLANGUAGE_ITALIAN,\n\t\tLANGUAGE_SPANISH,\n#ifdef MORE_LANGUAGES\n\t\tLANGUAGE_POLISH,\n\t\tLANGUAGE_RUSSIAN,\n\t\tLANGUAGE_JAPANESE,\n#endif\n\t};\n\t\n\tenum CONTRCONFIG\n\t{\n\t\tCONFIG_1 = 0,\n\t\tCONFIG_2,\n\t\tCONFIG_3,\n\t\tCONFIG_4,\n\t};\n\n\tenum\n\t{\n\t\tNUM_SPRIRES = 28,\n\t};\n\t\n\tenum\n\t{\n\t\tPAGESTATE_NORMAL = 0,\n\t\tPAGESTATE_HIGHLIGHTED = 1,\n\t\tPAGESTATE_SELELECTED = 2,\n\t};\n\t\n\tenum\n\t{\n\t\tSLIDE_TO_BOTTOM = 0,\n\t\tSLIDE_TO_RIGHT,\n\t\tSLIDE_TO_TOP,\n\t\tSLIDE_TO_LEFT,\n\t\tSLIDE_MAX\n\t};\n\t\n\tint32 m_currentPage;\n\tint32 m_newPage;\n\tint32 m_pageState;\n\tuint32 m_nPageLeftTimer;\n\tuint32 m_nPageRightTimer;\n\tuint32 m_nChangePageTimer;\n\tint field_18;\n\tuint8 m_fade;\n\tuint8 m_someAlpha;\n\t//char field_1E; // unused ?\n\t//char field_1F; // unused ?\n\tuint32 m_nStartPauseTimer;\n\tuint32 m_nEndPauseTimer;\n\tCVector2D m_position;\n\tuint8 m_nSlidingDir;\n\t//char field_31; // unused ?\n\t//char field_32; // unused ?\n\t//char field_33; // unused ?\n\tbool m_bInitialised;\n\tbool m_bWantToUpdateContent;\n\tbool m_bMenuActive;\n\tbool m_bWantToRestart;\n\t//char field_38; //unused ?\n\tbool m_bRenderGameInMenu;\n\tbool m_bSaveMenuActive;\n\tbool m_bInSaveZone;\n\tchar field_3C;\n\tbool m_bTexturesLoaded;\n\t//char field_3E; //unused ?\n\t//char field_3F; //unused ?\n\tCSprite2d m_sprites[NUM_SPRIRES];\n\t\n\tstatic int32 m_PrefsSfxVolume;\n\tstatic int32 m_PrefsMusicVolume;\n\tstatic int32 m_PrefsBrightness;\n\tstatic bool m_PrefsShowTrails;\n\tstatic bool m_PrefsShowSubtitles;\n\tstatic bool m_PrefsAllowNastyGame;\n\tstatic int32 m_PrefsRadioStation;\n\tstatic int32 m_PrefsStereoMono;\n\tstatic int8 m_PrefsUseWideScreen;\n\tstatic int32 m_PrefsLanguage;\n\tstatic CONTRCONFIG m_PrefsControllerConfig;\n\tstatic bool m_PrefsUseVibration;\n\n#ifdef CUTSCENE_BORDERS_SWITCH\n\tstatic bool m_PrefsCutsceneBorders;\n#endif\n\n#ifdef GTA_PC\n\tbool m_bQuitGameNoCD;\n\t\n\tint32 m_nMouseTempPosX;\n\tint32 m_nMouseTempPosY;\n\tint32 m_nPrefsVideoMode;\n\tint32 m_nDisplayVideoMode;\n\tint8 m_nPrefsAudio3DProviderIndex;\n\t\n\tstatic int32 OS_Language;\n\tstatic int8 m_PrefsVsync;\n\tstatic int8 m_PrefsVsyncDisp;\n\tstatic int8 m_PrefsFrameLimiter;\n\tstatic int8 m_PrefsSpeakers;\n\tstatic int32 m_ControlMethod;\n\tstatic int8 m_PrefsDMA;\n\tstatic float m_PrefsLOD;\n\tstatic char m_PrefsSkinFile[256];\n\n#ifndef MASTER\n\tstatic bool m_PrefsMarketing;\n\tstatic bool m_PrefsDisableTutorials;\n#endif // !MASTER\n\n#ifdef MENU_MAP\n\tstatic bool bMenuMapActive;\n\tstatic float fMapSize;\n\tstatic float fMapCenterY;\n\tstatic float fMapCenterX;\n#endif\n\n#ifdef IMPROVED_VIDEOMODE\t\n\tint32 m_nPrefsWidth = 640;\n\tint32 m_nPrefsHeight = 480;\n\tint32 m_nPrefsDepth = 32;\n\tint32 m_nPrefsWindowed = 1;\n\tint32 m_nPrefsSubsystem;\n\tint32 m_nSelectedScreenMode;\n#endif\n\n\tvoid WaitForUserCD() { }\n#endif\n\n\tbool GetIsMenuActive() {return !!m_bMenuActive;}\n\n\tCMenuManager(void);\n#ifdef FIX_BUGS\n\t~CMenuManager(void)\n\t{\n\t\tUnloadTextures();\n\t}\n#endif\n\t\n\tvoid LoadAllTextures(void);\n\tvoid UnloadTextures(void);\n\t\n\tvoid InitialiseMenusOnce(void);\n\tvoid InitialiseChangedLanguageSettings(void);\n\tvoid InitialiseMenuContents(void);\n\tvoid AnaliseMenuContents(void);\n\tvoid InitialiseMenuContentsAfterLoadingGame(void);\n\tvoid DrawFrontEnd(void);\n\tvoid DrawFrontEndNormal(void);\n\tvoid DrawFrontEndSaveZone(void);\n\tvoid DrawMemoryCardStartUpMenus(void);\n\tvoid Process(void);\n\tvoid WorkOutMenuState(uint8 bExit);\n\tvoid ProcessControllerInput(void);\n\tvoid ProcessDPadLeftJustDown(void);\n\tvoid ProcessDPadRightJustDown(void);\n\tvoid ProcessDPadUpJustDown(void);\n\tvoid ProcessDPadDownJustDown(void);\n\tvoid ProcessDPadTriangleJustDown(void);\n\tvoid ProcessDPadCrossJustDown(void);\n\tvoid DoHackingMenusAtPageBrowse(void);\n\tvoid SetSoundLevelsForMusicMenu(void);\n\tvoid FilterOutColorMarkersFromString(wchar *string, CRGBA &color);\n};\n\nextern CMenuManager FrontEndMenuManager;"
  },
  {
    "path": "src/core/Game.cpp",
    "content": "#include \"common.h\"\n#include \"platform.h\"\n\n#include \"Game.h\"\n#include \"main.h\"\n#include \"RwHelper.h\"\n#include \"Accident.h\"\n#include \"Antennas.h\"\n#include \"Bridge.h\"\n#include \"CarCtrl.h\"\n#include \"CarGen.h\"\n#include \"CdStream.h\"\n#include \"Clock.h\"\n#include \"Clouds.h\"\n#include \"Collision.h\"\n#include \"Console.h\"\n#include \"Coronas.h\"\n#include \"Cranes.h\"\n#include \"Credits.h\"\n#include \"CutsceneMgr.h\"\n#include \"DMAudio.h\"\n#include \"Darkel.h\"\n#include \"Debug.h\"\n#include \"EventList.h\"\n#include \"FileLoader.h\"\n#include \"FileMgr.h\"\n#include \"Fire.h\"\n#include \"Fluff.h\"\n#include \"Font.h\"\n#include \"Frontend.h\"\n#include \"frontendoption.h\"\n#include \"GameLogic.h\"\n#include \"Garages.h\"\n#include \"GenericGameStorage.h\"\n#include \"Glass.h\"\n#include \"HandlingMgr.h\"\n#include \"Heli.h\"\n#include \"Hud.h\"\n#include \"IniFile.h\"\n#include \"Lights.h\"\n#include \"MBlur.h\"\n#include \"Messages.h\"\n#include \"MemoryCard.h\"\n#include \"MemoryHeap.h\"\n#include \"Pad.h\"\n#include \"Particle.h\"\n#include \"ParticleObject.h\"\n#include \"PedRoutes.h\"\n#include \"Phones.h\"\n#include \"Pickups.h\"\n#include \"Plane.h\"\n#include \"PlayerSkin.h\"\n#include \"Population.h\"\n#include \"Radar.h\"\n#include \"Record.h\"\n#include \"References.h\"\n#include \"Renderer.h\"\n#include \"Replay.h\"\n#include \"Restart.h\"\n#include \"RoadBlocks.h\"\n#include \"Rubbish.h\"\n#include \"SceneEdit.h\"\n#include \"Script.h\"\n#include \"Shadows.h\"\n#include \"Skidmarks.h\"\n#include \"SetPieces.h\"\n#include \"SpecialFX.h\"\n#include \"Stats.h\"\n#include \"Streaming.h\"\n#include \"SurfaceTable.h\"\n#include \"TempColModels.h\"\n#include \"Timecycle.h\"\n#include \"TrafficLights.h\"\n#include \"Train.h\"\n#include \"TxdStore.h\"\n#include \"User.h\"\n#include \"VisibilityPlugins.h\"\n#include \"WaterCannon.h\"\n#include \"WaterLevel.h\"\n#include \"Weapon.h\"\n#include \"WeaponEffects.h\"\n#include \"Weather.h\"\n#include \"World.h\"\n#include \"ZoneCull.h\"\n#include \"Zones.h\"\n#include \"Occlusion.h\"\n#include \"debugmenu.h\"\n#include \"Ropes.h\"\n#include \"WindModifiers.h\"\n#include \"WaterCreatures.h\"\n#include \"postfx.h\"\n#include \"custompipes.h\"\n#include \"screendroplets.h\"\n#include \"VarConsole.h\"\n#ifdef USE_TEXTURE_POOL\n#include \"TexturePools.h\"\n#endif\n\neLevelName CGame::currLevel;\nint32 CGame::currArea;\nbool CGame::bDemoMode = true;\nbool CGame::nastyGame = true;\nbool CGame::frenchGame;\nbool CGame::germanGame;\nbool CGame::noProstitutes;\nbool CGame::playingIntro;\nchar CGame::aDatFile[32];\n#ifdef MORE_LANGUAGES\nbool CGame::russianGame = false;\nbool CGame::japaneseGame = false;\n#endif\n#ifndef MASTER\nCVector CGame::PlayerCoords;\nbool8 CGame::VarUpdatePlayerCoords;\n#endif\n\nint gameTxdSlot;\n\n#ifdef SECUROM\nuint8 gameProcessPirateCheck = 0;\n#endif\n\nbool DoRWStuffStartOfFrame(int16 TopRed, int16 TopGreen, int16 TopBlue, int16 BottomRed, int16 BottomGreen, int16 BottomBlue, int16 Alpha);\nvoid DoRWStuffEndOfFrame(void);\n#ifdef PS2_MENU\nvoid MessageScreen(char *msg)\n{\n\t//TODO: stretch_screen\n\t\n\tCRect rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);\n\tCRGBA color(255, 255, 255, 255);\n\n\tDoRWStuffStartOfFrame(50, 50, 50, 0, 0, 0, 255);\n\t\n\tCSprite2d::InitPerFrame();\n\tCFont::InitPerFrame();\n\tDefinedState();\n\n\tCSprite2d *splash = LoadSplash(NULL);\n\tsplash->Draw(rect, color, color, color, color);\n\tsplash->DrawRect(CRect(SCREEN_SCALE_X(20.0f), SCREEN_SCALE_Y(110.0f), SCREEN_SCALE_X(620.0f), SCREEN_SCALE_Y(300.0f)), CRGBA(50, 50, 50, 192));\n\t\n\tCFont::SetFontStyle(FONT_BANK);\n\tCFont::SetBackgroundOff();\n\tCFont::SetWrapx(SCREEN_SCALE_FROM_RIGHT(190.0f)); // 450.0f\n\tCFont::SetScale(SCREEN_SCALE_X(1.0f), SCREEN_SCALE_Y(1.0f));\n\tCFont::SetCentreOn();\n\tCFont::SetCentreSize(SCREEN_SCALE_X(450.0f));\n\tCFont::SetJustifyOff();\n\tCFont::SetColor(CRGBA(255, 255, 255, 255));\n\tCFont::SetDropColor(CRGBA(32, 32, 32, 255));\n\tCFont::SetDropShadowPosition(3);\n\tCFont::SetPropOn();\n\tCFont::PrintString(SCREEN_SCALE_X(320.0f), SCREEN_SCALE_Y(130.0f), TheText.Get(msg));\n\tCFont::DrawFonts();\n\t\n\tDoRWStuffEndOfFrame();\n}\n#endif\n\nbool\nCGame::InitialiseOnceBeforeRW(void)\n{\n\tCFileMgr::Initialise();\n\tCdStreamInit(MAX_CDCHANNELS);\n\tdebug(\"size of matrix %d\\n\", sizeof(CMatrix));\n\tdebug(\"size of placeable %d\\n\", sizeof(CPlaceable));\n\tdebug(\"size of entity %d\\n\", sizeof(CEntity));\n\tdebug(\"size of building %d\\n\", sizeof(CBuilding));\n\tdebug(\"size of dummy %d\\n\", sizeof(CDummy));\n#ifdef EXTENDED_COLOURFILTER\n\tCPostFX::InitOnce();\n#endif\n#ifdef CUSTOM_FRONTEND_OPTIONS\n\t// Not needed here but may be needed in future\n\t// if (numCustomFrontendOptions == 0 && numCustomFrontendScreens == 0)\n\tCustomFrontendOptionsPopulate();\n#endif\n\treturn true;\n}\n\n#ifndef LIBRW\n#ifdef PS2_MATFX\nvoid ReplaceMatFxCallback();\n#endif // PS2_MATFX\n#ifdef PS2_ALPHA_TEST\nvoid ReplaceAtomicPipeCallback();\n#endif // PS2_ALPHA_TEST\n#endif // !LIBRW\n\nbool\nCGame::InitialiseRenderWare(void)\n{\n\tValidateVersion();\n#ifdef USE_TEXTURE_POOL\n\t_TexturePoolsInitialise();\n#endif\n\n\tCTxdStore::Initialise();\n\tCVisibilityPlugins::Initialise();\n\n#ifdef GTA_PS2\n\tRpSkySelectTrueTSClipper(TRUE);\n\tRpSkySelectTrueTLClipper(TRUE);\n\n\t// PS2ManagerApplyDirectionalLightingCB() uploads the GTA lights\n\t// directly without going through RpWorld and all that\n\tSetupPS2ManagerDefaultLightingCallback();\n\tPreAllocateRwObjects();\n#endif\n\n\t/* Create camera */\n\tScene.camera = CameraCreate(SCREEN_WIDTH, SCREEN_HEIGHT, TRUE);\n\tASSERT(Scene.camera != nil);\n\tif (!Scene.camera)\n\t{\n\t\treturn (false);\n\t}\n\t\n\tRwCameraSetFarClipPlane(Scene.camera, 2000.0f);\n\tRwCameraSetNearClipPlane(Scene.camera, 0.9f);\n\t\n\tCameraSize(Scene.camera, nil, DEFAULT_VIEWWINDOW, DEFAULT_ASPECT_RATIO);\n\t\n\t/* Create a world */\n\tRwBBox  bbox;\n\t\n\tbbox.sup.x = bbox.sup.y = bbox.sup.z = 10000.0f;\n\tbbox.inf.x = bbox.inf.y = bbox.inf.z = -10000.0f;\n\n\tScene.world = RpWorldCreate(&bbox);\n\tASSERT(Scene.world != nil);\n\tif (!Scene.world)\n\t{\n\t\tCameraDestroy(Scene.camera);\n\t\tScene.camera = nil;\n\t\treturn (false);\n\t}\n\t\n\t/* Add the camera to the world */\n\tRpWorldAddCamera(Scene.world, Scene.camera);\n\tLightsCreate(Scene.world);\n\n\tCreateDebugFont();\n\n#ifdef LIBRW\n#ifdef PS2_MATFX\n\trw::MatFX::modulateEnvMap = true;\n#else\n\trw::MatFX::modulateEnvMap = false;\n#endif\n#else\n#ifdef PS2_MATFX\n\tReplaceMatFxCallback();\n#endif // PS2_MATFX\n#ifdef PS2_ALPHA_TEST\n\tReplaceAtomicPipeCallback();\n#endif // PS2_ALPHA_TEST\n#endif // LIBRW\n\n\tPUSH_MEMID(MEMID_TEXTURES);\n\tCFont::Initialise();\n\tCHud::Initialise();\n\tCPlayerSkin::Initialise();\n\tPOP_MEMID();\n\n#ifdef EXTENDED_PIPELINES\n\tCustomPipes::CustomPipeInit();\t// need Scene.world for this\n#endif\n#ifdef SCREEN_DROPLETS\n\tScreenDroplets::InitDraw();\n#endif\n\n\treturn (true);\n}\n\nvoid CGame::ShutdownRenderWare(void)\n{\n#ifdef SCREEN_DROPLETS\n\tScreenDroplets::Shutdown();\n#endif\n#ifdef EXTENDED_PIPELINES\n\tCustomPipes::CustomPipeShutdown();\n#endif\n\n\tDestroySplashScreen();\n\tCHud::Shutdown();\n\tCFont::Shutdown();\n\t\n\tfor ( int32 i = 0; i < NUMPLAYERS; i++ )\n\t\tCWorld::Players[i].DeletePlayerSkin();\n\n\tCPlayerSkin::Shutdown();\n\t\n\tDestroyDebugFont();\n\t\n\t/* Destroy world */\n\tLightsDestroy(Scene.world);\n\tRpWorldRemoveCamera(Scene.world, Scene.camera);\n\tRpWorldDestroy(Scene.world);\n\t\n\t/* destroy camera */\n\tCameraDestroy(Scene.camera);\n\t\n\tScene.world = nil;\n\tScene.camera = nil;\n\t\n\tCVisibilityPlugins::Shutdown();\n\t\n#ifdef USE_TEXTURE_POOL\n\t_TexturePoolsShutdown();\n#endif\n}\n\nbool CGame::InitialiseOnceAfterRW(void)\n{\n\tTheText.Load();\n\tCTimer::Initialise();\n\tCTempColModels::Initialise();\n\tmod_HandlingManager.Initialise();\n\tCSurfaceTable::Initialise(\"DATA\\\\SURFACE.DAT\");\n\tCPedStats::Initialise();\n\tCTimeCycle::Initialise();\n#ifdef GTA_PS2\n\tLoadingScreen(\"Loading the Game\", \"Initialising audio\", GetRandomSplashScreen());\n#endif\n\tDMAudio.Initialise();\n\n#ifndef GTA_PS2\n\tif ( DMAudio.GetNum3DProvidersAvailable() == 0 )\n\t\tFrontEndMenuManager.m_nPrefsAudio3DProviderIndex = NO_AUDIO_PROVIDER;\n\n\tif ( FrontEndMenuManager.m_nPrefsAudio3DProviderIndex == AUDIO_PROVIDER_NOT_DETERMINED || FrontEndMenuManager.m_nPrefsAudio3DProviderIndex == -2 )\n\t{\n\t\tFrontEndMenuManager.m_PrefsSpeakers = 0;\n\t\tFrontEndMenuManager.m_nPrefsAudio3DProviderIndex = DMAudio.AutoDetect3DProviders();\n\t}\n\n\tDMAudio.SetCurrent3DProvider(FrontEndMenuManager.m_nPrefsAudio3DProviderIndex);\n\tDMAudio.SetSpeakerConfig(FrontEndMenuManager.m_PrefsSpeakers);\n\tDMAudio.SetDynamicAcousticModelingStatus(FrontEndMenuManager.m_PrefsDMA);\n\tDMAudio.SetMusicMasterVolume(FrontEndMenuManager.m_PrefsMusicVolume);\n\tDMAudio.SetEffectsMasterVolume(FrontEndMenuManager.m_PrefsSfxVolume);\n\tDMAudio.SetEffectsFadeVol(127);\n\tDMAudio.SetMusicFadeVol(127);\n#endif\n\treturn true;\n}\n\nvoid\nCGame::FinalShutdown(void)\n{\t\n\tCTxdStore::Shutdown();\n\tCPedStats::Shutdown();\n\tCdStreamShutdown();\n}\n\nbool CGame::Initialise(const char* datFile)\n{\n\tResetLoadingScreenBar();\n\tstrcpy(aDatFile, datFile);\n\n#ifdef GTA_PS2\n\t// TODO: upload VU0 collision code here\n#endif\n\n\tCPools::Initialise();\n\n#ifndef GTA_PS2\n\tCIniFile::LoadIniFile();\n#endif\n#ifdef USE_TEXTURE_POOL\n\t_TexturePoolsUnknown(false);\n#endif\n\tcurrLevel = LEVEL_BEACH;\n\tcurrArea = AREA_MAIN_MAP;\n\n\tPUSH_MEMID(MEMID_TEXTURES);\n\tLoadingScreen(\"Loading the Game\", \"Loading generic textures\", GetRandomSplashScreen());\n\tgameTxdSlot = CTxdStore::AddTxdSlot(\"generic\");\n\tCTxdStore::Create(gameTxdSlot);\n\tCTxdStore::AddRef(gameTxdSlot);\n\n#ifdef EXTENDED_PIPELINES\n\t// for generic fallback\n\tCustomPipes::SetTxdFindCallback();\n#endif\n\n\tLoadingScreen(\"Loading the Game\", \"Loading particles\", nil);\n\tint particleTxdSlot = CTxdStore::AddTxdSlot(\"particle\");\n\tCTxdStore::LoadTxd(particleTxdSlot, \"MODELS/PARTICLE.TXD\");\n\tCTxdStore::AddRef(particleTxdSlot);\n\tCTxdStore::SetCurrentTxd(gameTxdSlot);\n\tLoadingScreen(\"Loading the Game\", \"Setup game variables\", nil);\n\tPOP_MEMID();\n\n#ifdef GTA_PS2\n\tCDma::SyncChannel(0, true);\n#endif\n\n\tCGameLogic::InitAtStartOfGame();\n\tCReferences::Init();\n\tTheCamera.Init();\n\tTheCamera.SetRwCamera(Scene.camera);\n\tCDebug::DebugInitTextBuffer();\n\tThePaths.Init();\n\tThePaths.AllocatePathFindInfoMem(4500);\n\tCScriptPaths::Init();\n\tCWeather::Init();\n\tCCullZones::Init();\n\tCOcclusion::Init();\n\tCCollision::Init();\n\tCSetPieces::Init();\n\tCTheZones::Init();\n\tCUserDisplay::Init();\n\tCMessages::Init();\n\tCMessages::ClearAllMessagesDisplayedByGame();\n\tCRecordDataForGame::Init();\n\tCRestart::Initialise();\n\n\tPUSH_MEMID(MEMID_WORLD);\n\tCWorld::Initialise();\n\tPOP_MEMID();\n\n\tPUSH_MEMID(MEMID_TEXTURES);\n\tCParticle::Initialise();\n\tPOP_MEMID();\n\n\tPUSH_MEMID(MEMID_ANIMATION);\n\tCAnimManager::Initialise();\n\tCCutsceneMgr::Initialise();\n\tPOP_MEMID();\n\n\tPUSH_MEMID(MEMID_CARS);\n\tCCarCtrl::Init();\n\tPOP_MEMID();\n\n\tPUSH_MEMID(MEMID_DEF_MODELS);\n\tInitModelIndices();\n\tCModelInfo::Initialise();\n\tCPickups::Init();\n\tCTheCarGenerators::Init();\n\n\tCdStreamAddImage(\"MODELS\\\\GTA3.IMG\");\n\n\tCFileLoader::LoadLevel(\"DATA\\\\DEFAULT.DAT\");\n\tCFileLoader::LoadLevel(datFile);\n\n\tLoadingScreen(\"Loading the Game\", \"Add Particles\", nil);\n\tCWorld::AddParticles();\n\tCVehicleModelInfo::LoadVehicleColours();\n\tCVehicleModelInfo::LoadEnvironmentMaps();\n\tCTheZones::PostZoneCreation();\n\tPOP_MEMID();\n\n\tLoadingScreen(\"Loading the Game\", \"Setup paths\", nil);\n\tThePaths.PreparePathData();\n\tfor (int i = 0; i < NUMPLAYERS; i++)\n\t\tCWorld::Players[i].Clear();\n\tCWorld::Players[0].LoadPlayerSkin();\n\tTestModelIndices();\n\n\tLoadingScreen(\"Loading the Game\", \"Setup water\", nil);\n\tCWaterLevel::Initialise(\"DATA\\\\WATER.DAT\");\n\tTheConsole.Init();\n\tCDraw::SetFOV(120.0f);\n\tCDraw::ms_fLODDistance = 500.0f;\n\n\tLoadingScreen(\"Loading the Game\", \"Setup streaming\", nil);\n\tCStreaming::LoadInitialVehicles();\n\tCStreaming::LoadInitialPeds();\n\tCStreaming::RequestBigBuildings(LEVEL_GENERIC);\n\tCStreaming::LoadAllRequestedModels(false);\n\tCStreaming::RemoveIslandsNotUsed(currLevel);\n\tprintf(\"Streaming uses %zuK of its memory\", CStreaming::ms_memoryUsed / 1024); // original modifier was %d\n\n\tLoadingScreen(\"Loading the Game\", \"Load animations\", GetRandomSplashScreen());\n\tPUSH_MEMID(MEMID_ANIMATION);\n\tCAnimManager::LoadAnimFiles();\n\tPOP_MEMID();\n\n\tCStreaming::LoadInitialWeapons();\n\tCStreaming::LoadAllRequestedModels(0);\n\tCPed::Initialise();\n\tCRouteNode::Initialise();\n\tCEventList::Initialise();\n#ifdef SCREEN_DROPLETS\n\tScreenDroplets::Initialise();\n#endif\n\tLoadingScreen(\"Loading the Game\", \"Find big buildings\", nil);\n\tCRenderer::Init();\n\n\tLoadingScreen(\"Loading the Game\", \"Setup game variables\", nil);\n\tCRadar::Initialise();\n\tCRadar::LoadTextures();\n\tCWeapon::InitialiseWeapons();\n\n\tLoadingScreen(\"Loading the Game\", \"Setup traffic lights\", nil);\n\tCTrafficLights::ScanForLightsOnMap();\n\tCRoadBlocks::Init();\n\n\tLoadingScreen(\"Loading the Game\", \"Setup game variables\", nil);\n\tCPopulation::Initialise();\n\tCWorld::PlayerInFocus = 0;\n\tCCoronas::Init();\n\tCShadows::Init();\n\tCWeaponEffects::Init();\n\tCSkidmarks::Init();\n\tCAntennas::Init();\n\tCGlass::Init();\n\tgPhoneInfo.Initialise();\n#ifdef GTA_SCENE_EDIT\n\tCSceneEdit::Initialise();\n#endif\n\n\tLoadingScreen(\"Loading the Game\", \"Load scripts\", nil);\n\tPUSH_MEMID(MEMID_SCRIPT);\n\tCTheScripts::Init();\n\tCGangs::Initialise();\n\tPOP_MEMID();\n\n\tLoadingScreen(\"Loading the Game\", \"Setup game variables\", nil);\n\tCClock::Initialise(1000);\n\tCHeli::InitHelis();\n\tCCranes::InitCranes();\n\tCMovingThings::Init();\n\tCDarkel::Init();\n\tCStats::Init();\n\tCPacManPickups::Init();\n\tCRubbish::Init();\n\tCClouds::Init();\n\tCSpecialFX::Init();\n\tCRopes::Init();\n\tCWaterCannons::Init();\n\tCBridge::Init();\n\tCGarages::Init();\n\n\tLoadingScreen(\"Loading the Game\", \"Position dynamic objects\", nil);\n\tLoadingScreen(\"Loading the Game\", \"Initialise vehicle paths\", nil);\n\n\tCTrain::InitTrains();\n\tCPlane::InitPlanes();\n\tCCredits::Init();\n\tCRecordDataForChase::Init();\n\tCReplay::Init();\n\n\tLoadingScreen(\"Loading the Game\", \"Start script\", nil);\n#ifdef PS2_MENU\n\tif ( !TheMemoryCard.m_bWantToLoad )\n#endif\n\t{\n\t\tCTheScripts::StartTestScript();\n\t\tCTheScripts::Process();\n\t\tTheCamera.Process();\n\t}\n\n\tLoadingScreen(\"Loading the Game\", \"Load scene\", nil);\n\tCCollision::ms_collisionInMemory = currLevel;\n\tfor (int i = 0; i < MAX_PADS; i++)\n\t\tCPad::GetPad(i)->Clear(true);\n#ifdef USE_TEXTURE_POOL\n\t_TexturePoolsUnknown(true);\n#endif\n\n#ifndef MASTER\n\tPlayerCoords = FindPlayerCoors();\n\tVarConsole.Add(\"X PLAYER COORD\", &PlayerCoords.x, 10.0f, -10000.0f, 10000.0f, true);\n\tVarConsole.Add(\"Y PLAYER COORD\", &PlayerCoords.y, 10.0f, -10000.0f, 10000.0f, true);\n\tVarConsole.Add(\"Z PLAYER COORD\", &PlayerCoords.z, 10.0f, -10000.0f, 10000.0f, true);\n\tVarConsole.Add(\"UPDATE PLAYER COORD\", &VarUpdatePlayerCoords, true);\n#endif\n\n\n\tDMAudio.SetStartingTrackPositions(true);\n\tDMAudio.ChangeMusicMode(MUSICMODE_GAME);\n\treturn true;\n}\n\nbool CGame::ShutDown(void)\n{\n#ifdef USE_TEXTURE_POOL\n\t_TexturePoolsUnknown(false);\n#endif\n\tCReplay::FinishPlayback();\n\tCReplay::EmptyReplayBuffer();\n\tCPlane::Shutdown();\n\tCTrain::Shutdown();\n\tCScriptPaths::Shutdown();\n\tCWaterCreatures::RemoveAll();\n\tCSpecialFX::Shutdown();\n\tCGarages::Shutdown();\n\tCMovingThings::Shutdown();\n\tgPhoneInfo.Shutdown();\n\tCWeapon::ShutdownWeapons();\n\tCPedType::Shutdown();\n\t\n\tfor (int32 i = 0; i < NUMPLAYERS; i++)\n\t{\n\t\tif ( CWorld::Players[i].m_pPed )\n\t\t{\n\t\t\tCWorld::Remove(CWorld::Players[i].m_pPed);\n\t\t\tdelete CWorld::Players[i].m_pPed;\n\t\t\tCWorld::Players[i].m_pPed = nil;\n\t\t}\n\t\t\n\t\tCWorld::Players[i].Clear();\n\t}\n\t\n\tCRenderer::Shutdown();\n\tCWorld::ShutDown();\n\tDMAudio.DestroyAllGameCreatedEntities();\n\tCModelInfo::ShutDown();\n\tCAnimManager::Shutdown();\n\tCCutsceneMgr::Shutdown();\n\tCVehicleModelInfo::DeleteVehicleColourTextures();\n\tCVehicleModelInfo::ShutdownEnvironmentMaps();\n\tCRadar::Shutdown();\n\tCStreaming::Shutdown();\n\tCTxdStore::GameShutdown();\n\tCCollision::Shutdown();\n\tCWaterLevel::Shutdown();\n\tCRubbish::Shutdown();\n\tCClouds::Shutdown();\n\tCShadows::Shutdown();\n\tCCoronas::Shutdown();\n\tCSkidmarks::Shutdown();\n\tCWeaponEffects::Shutdown();\n\tCParticle::Shutdown();\n\tCPools::ShutDown();\n\tCHud::ReInitialise();\n\tCTxdStore::RemoveTxdSlot(gameTxdSlot);\n\tCMBlur::MotionBlurClose();\n\tCdStreamRemoveImages();\n#ifdef USE_TEXTURE_POOL\n\t_TexturePoolsFinalShutdown();\n#endif\n\treturn true;\n}\n\nvoid CGame::ReInitGameObjectVariables(void)\n{\n\tCGameLogic::InitAtStartOfGame();\n#ifdef PS2_MENU\n\tif ( !TheMemoryCard.m_bWantToLoad )\n#endif\n\t{\n\t\tTheCamera.Init();\n\t\tTheCamera.SetRwCamera(Scene.camera);\n\t}\n\tCDebug::DebugInitTextBuffer();\n\tCWeather::Init();\n\tCUserDisplay::Init();\n\tCMessages::Init();\n\tCRestart::Initialise();\n\tCWorld::bDoingCarCollisions = false;\n\tCHud::ReInitialise();\n\tCRadar::Initialise();\n\tCCarCtrl::ReInit();\n\tCTimeCycle::Initialise();\n\tCDraw::SetFOV(120.0f);\n\tCDraw::ms_fLODDistance = 500.0f;\n\tCStreaming::RequestBigBuildings(LEVEL_GENERIC);\n\tCStreaming::RemoveIslandsNotUsed(LEVEL_BEACH);\n\tCStreaming::RemoveIslandsNotUsed(LEVEL_MAINLAND);\n\tCStreaming::LoadAllRequestedModels(false);\n\tcurrArea = AREA_MAIN_MAP;\n\tCPed::Initialise();\n\tCEventList::Initialise();\n#ifdef SCREEN_DROPLETS\n\tScreenDroplets::Initialise();\n#endif\n\tCWeapon::InitialiseWeapons();\n\tCPopulation::Initialise();\n\t\n\tfor (int i = 0; i < NUMPLAYERS; i++)\n\t\tCWorld::Players[i].Clear();\n\t\n\tCWorld::PlayerInFocus = 0;\n\tCAntennas::Init();\n\tCGlass::Init();\n\tgPhoneInfo.Initialise();\n\n\tPUSH_MEMID(MEMID_SCRIPT);\n\tCTheScripts::Init();\n\tCGangs::Initialise();\n\tPOP_MEMID();\n\n\tCTimer::Initialise();\n\tCClock::Initialise(1000);\n\tCTheCarGenerators::Init();\n\tCHeli::InitHelis();\n\tCMovingThings::Init();\n\tCDarkel::Init();\n\tCStats::Init();\n\tCPickups::Init();\n\tCPacManPickups::Init();\n\tCGarages::Init();\n\tCSpecialFX::Init();\n\tCRopes::Init();\n\tCWaterCannons::Init();\n\tCScriptPaths::Init();\n\tCParticle::ReloadConfig();\n\n#ifdef PS2_MENU\n\tif ( !TheMemoryCard.m_bWantToLoad )\n#else\n\tif ( !FrontEndMenuManager.m_bWantToLoad )\n#endif\n\t{\n\t\tCCranes::InitCranes();\n\t\tCTheScripts::StartTestScript();\n\t\tCTheScripts::Process();\n\t\tTheCamera.Process();\n\t\tCTrain::InitTrains();\n\t\tCPlane::InitPlanes();\n\t}\n\t\n\tfor (int32 i = 0; i < MAX_PADS; i++)\n\t\tCPad::GetPad(i)->Clear(true);\n}\n\nvoid CGame::ReloadIPLs(void)\n{\n\t// Empty and unused\n}\n\nvoid CGame::ShutDownForRestart(void)\n{\n#ifdef USE_TEXTURE_POOL\n\t_TexturePoolsUnknown(false);\n#endif\n\tCReplay::FinishPlayback();\n\tCReplay::EmptyReplayBuffer();\n\tDMAudio.DestroyAllGameCreatedEntities();\n\tCMovingThings::Shutdown();\n\t\n\tfor (int i = 0; i < NUMPLAYERS; i++)\n\t\tCWorld::Players[i].Clear();\n\n\tCGarages::SetAllDoorsBackToOriginalHeight();\n\tCTheScripts::UndoBuildingSwaps();\n\tCTheScripts::UndoEntityInvisibilitySettings();\n\tCWorld::ClearForRestart();\n\tCGameLogic::ClearShortCut();\n\tCTimer::Shutdown();\n\tCStreaming::ReInit();\n\tCRadar::RemoveRadarSections();\n\tFrontEndMenuManager.UnloadTextures();\n\tCParticleObject::RemoveAllExpireableParticleObjects();\n\tCWaterCreatures::RemoveAll(); \n\tCSetPieces::Init();\n\tCPedType::Shutdown();\n\tCSpecialFX::Shutdown();\n}\n\nvoid CGame::InitialiseWhenRestarting(void)\n{\n\tCRect rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);\n\tCRGBA color(255, 255, 255, 255);\n\t\n\tCTimer::Initialise();\n\tCSprite2d::SetRecipNearClip();\n\n\tif (b_FoundRecentSavedGameWantToLoad || FrontEndMenuManager.m_bWantToLoad)\n\t{\n\t\tLoadSplash(\"splash1\");\n#ifndef XBOX_MESSAGE_SCREEN\n\t\tif (FrontEndMenuManager.m_bWantToLoad)\n\t\t\tFrontEndMenuManager.MessageScreen(\"FELD_WR\", true);\n#endif\n\t}\n\n\tb_FoundRecentSavedGameWantToLoad = false;\n\t\n\tTheCamera.Init();\n\t\n\tif ( FrontEndMenuManager.m_bWantToLoad == true )\n\t{\n#ifdef XBOX_MESSAGE_SCREEN\n\t\tFrontEndMenuManager.SetDialogTimer(1000);\n\t\tDoRWStuffStartOfFrame(0, 0, 0, 0, 0, 0, 0);\n\t\tCSprite2d::InitPerFrame();\n\t\tCFont::InitPerFrame();\n\t\tFrontEndMenuManager.DrawOverlays();\n\t\tDoRWStuffEndOfFrame();\n#endif\n\t\tRestoreForStartLoad();\n\t}\n\t\n\tReInitGameObjectVariables();\n\t\n\tif ( FrontEndMenuManager.m_bWantToLoad == true )\n\t{\n\t\tFrontEndMenuManager.m_bWantToLoad = false;\n\t\tInitRadioStationPositionList();\n\t\tif ( GenericLoad() == true )\n\t\t{\n\t\t\tDMAudio.ResetTimers(CTimer::GetTimeInMilliseconds());\n\t\t\tCTrain::InitTrains();\n\t\t\tCPlane::InitPlanes();\n\t\t}\n\t\telse\n\t\t{\n\t\t\tfor ( int32 i = 0; i < 50; i++ )\n\t\t\t{\n\t\t\t\tHandleExit();\n\t\t\t\tFrontEndMenuManager.MessageScreen(\"FED_LFL\", true); // Loading save game has failed. The game will restart now. \n\t\t\t}\n\t\t\t\n\t\t\tTheCamera.SetFadeColour(0, 0, 0);\n\t\t\tShutDownForRestart();\n\t\t\tCTimer::Stop();\n\t\t\tCTimer::Initialise();\n\t\t\tFrontEndMenuManager.m_bWantToLoad = false;\n\t\t\tReInitGameObjectVariables();\n\t\t\tcurrLevel = LEVEL_GENERIC;\n\t\t\tCCollision::SortOutCollisionAfterLoad();\n\t\t}\n#ifdef XBOX_MESSAGE_SCREEN\n\t\tFrontEndMenuManager.ProcessDialogTimer();\n#endif\n\t}\n\t\n\tCTimer::Update();\n\t\n\tDMAudio.ChangeMusicMode(MUSICMODE_GAME);\n#ifdef USE_TEXTURE_POOL\n\t_TexturePoolsUnknown(true);\n#endif\n}\n\nvoid CGame::Process(void) \n{\n\tCPad::UpdatePads();\n#ifdef USE_CUSTOM_ALLOCATOR\n\tProcessTidyUpMemory();\n#endif\n#ifdef DEBUGMENU\n\tDebugMenuProcess();\n#endif\n\tCCutsceneMgr::Update();\n\n\tif (!CCutsceneMgr::IsCutsceneProcessing() && !CTimer::GetIsCodePaused())\n\t\tFrontEndMenuManager.Process();\n\n\tCTheZones::Update();\n#ifdef SECUROM\n\tif (CTimer::GetTimeInMilliseconds() >= (35 * 60 * 1000) && gameProcessPirateCheck == 0){\n\t\t// if game not pirated\n\t\t// gameProcessPirateCheck = 1;\n\t\t// else\n\t\tgameProcessPirateCheck = 2;\n\t}\n#endif\n\tuint32 startTime = CTimer::GetCurrentTimeInCycles() / CTimer::GetCyclesPerMillisecond();\n\tCStreaming::Update();\n\tuint32 processTime = CTimer::GetCurrentTimeInCycles() / CTimer::GetCyclesPerMillisecond() - startTime;\n\tCWindModifiers::Number = 0;\n\tif (!CTimer::GetIsPaused())\n\t{\n#ifndef MASTER\n\t\tif (VarUpdatePlayerCoords) {\n\t\t\tFindPlayerPed()->Teleport(PlayerCoords);\n\t\t\tVarUpdatePlayerCoords = false;\n\t\t}\n#endif\n\t\tCSprite2d::SetRecipNearClip();\n\t\tCSprite2d::InitPerFrame();\n\t\tCFont::InitPerFrame();\n\t\tCRecordDataForGame::SaveOrRetrieveDataForThisFrame();\n\t\tCRecordDataForChase::SaveOrRetrieveDataForThisFrame();\n\t\tCPad::DoCheats();\n\t\tCClock::Update();\n\t\tCWeather::Update();\n\n\t\tPUSH_MEMID(MEMID_SCRIPT);\n\t\tCTheScripts::Process();\n\t\tPOP_MEMID();\n\n\t\tCCollision::Update();\n\t\tCScriptPaths::Update();\n\t\tCTrain::UpdateTrains();\n\t\tCPlane::UpdatePlanes();\n\t\tCHeli::UpdateHelis();\n\t\tCDarkel::Update();\n\t\tCSkidmarks::Update();\n\t\tCAntennas::Update();\n\t\tCGlass::Update();\n#ifdef GTA_SCENE_EDIT\n\t\tCSceneEdit::Update();\n#endif\n\t\tCSetPieces::Update();\n\t\tCEventList::Update();\n\t\tCParticle::Update();\n\t\tgFireManager.Update();\n\t\tif (processTime >= 2) {\n\t\t\tCPopulation::Update(false);\n\t\t} else {\n\t\t\tuint32 startTime = CTimer::GetCurrentTimeInCycles() / CTimer::GetCyclesPerMillisecond();\n\t\t\tCPopulation::Update(true);\n\t\t\tprocessTime = CTimer::GetCurrentTimeInCycles() / CTimer::GetCyclesPerMillisecond() - startTime;\n\t\t}\n\t\tCWeapon::UpdateWeapons();\n\t\tif (!CCutsceneMgr::IsRunning())\n\t\t\tCTheCarGenerators::Process();\n\t\tif (!CReplay::IsPlayingBack())\n\t\t\tCCranes::UpdateCranes();\n\t\tCClouds::Update();\n\t\tCMovingThings::Update();\n\t\tCWaterCannons::Update();\n\t\tCUserDisplay::Process();\n\t\tCReplay::Update();\n\n\t\tPUSH_MEMID(MEMID_WORLD);\n\t\tCWorld::Process();\n\t\tPOP_MEMID();\n\n\t\tgAccidentManager.Update();\n\t\tCPacManPickups::Update();\n\t\tCPickups::Update();\n\t\tCGarages::Update();\n\t\tCRubbish::Update();\n\t\tCSpecialFX::Update();\n\t\tCRopes::Update();\n\t\tCTimeCycle::Update();\n\t\tif (CReplay::ShouldStandardCameraBeProcessed())\n\t\t\tTheCamera.Process();\n\t\tCCullZones::Update();\n\t\tif (!CReplay::IsPlayingBack())\n\t\t\tCGameLogic::Update();\n\t\tCBridge::Update();\n\t\tCCoronas::DoSunAndMoon();\n\t\tCCoronas::Update();\n\t\tCShadows::UpdateStaticShadows();\n\t\tCShadows::UpdatePermanentShadows();\n\t\tgPhoneInfo.Update();\n\t\tif (!CReplay::IsPlayingBack())\n\t\t{\n\t\t\tPUSH_MEMID(MEMID_CARS);\n\t\t\tif (processTime < 2)\n\t\t\t\tCCarCtrl::GenerateRandomCars();\n\t\t\tCRoadBlocks::GenerateRoadBlocks();\n\t\t\tCCarCtrl::RemoveDistantCars();\n\t\t\tCCarCtrl::RemoveCarsIfThePoolGetsFull();\n\t\t\tPOP_MEMID();\n\t\t}\n\t}\n#ifdef GTA_PS2\n\tCMemCheck::DoTest();\n#endif\n}\n\n#ifdef USE_CUSTOM_ALLOCATOR\n\n// TODO(MIAMI)\n\nint32 gNumMemMoved;\n\nbool\nMoveMem(void** ptr)\n{\n\tif (*ptr) {\n\t\tgNumMemMoved++;\n\t\tvoid* newPtr = gMainHeap.MoveMemory(*ptr);\n\t\tif (*ptr != newPtr) {\n\t\t\t*ptr = newPtr;\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n\n// Some convenience structs\nstruct SkyDataPrefix\n{\n\tuint32 pktSize1;\n\tuint32 data;\t// pointer to data as read from TXD\n\tuint32 pktSize2;\n\tuint32 unused;\n};\n\nstruct DMAGIFUpload\n{\n\tuint32 tag1_qwc, tag1_addr;\t// dmaref\n\tuint32 nop1, vif_direct1;\n\n\tuint32 giftag[4];\n\tuint32 gs_bitbltbuf[4];\n\n\tuint32 tag2_qwc, tag2_addr;\t// dmaref\n\tuint32 nop2, vif_direct2;\n};\n\n// This is very scary. it depends on the exact memory layout of the DMA chains and whatnot\nRwTexture*\nMoveTextureMemoryCB(RwTexture* texture, void* pData)\n{\n#ifdef GTA_PS2\n\tbool* pRet = (bool*)pData;\n\tRwRaster* raster = RwTextureGetRaster(texture);\n\t_SkyRasterExt* rasterExt = RASTEREXTFROMRASTER(raster);\n\tif (raster->originalPixels == nil ||\t// the raw data\n\t\traster->cpPixels == raster->originalPixels ||\t// old format, can't handle it\n\t\trasterExt->dmaRefCount != 0 && rasterExt->dmaClrCount != 0)\n\t\treturn texture;\n\n\t// this is the allocated pointer we will move\n\tSkyDataPrefix* prefix = (SkyDataPrefix*)raster->originalPixels;\n\tDMAGIFUpload* uploads = (DMAGIFUpload*)(prefix + 1);\n\n\t// We have 4qw for each upload,\n\t// i.e. for each buffer width of mip levels,\n\t// and the palette if there is one.\n\t// NB: this code does NOT support mipmaps!\n\t// so we assume two uploads (pixels and palette)\n\t//\n\t// each upload looks like this:\n\t//    (DMAcnt; NOP; VIF DIRECT(2))\n\t//     giftag (1, A+D)\n\t//      GS_BITBLTBUF\n\t//    (DMAref->pixel data; NOP; VIF DIRECT(5))\n\t// the DMArefs are what we have to adjust\n\tuintptr dataDiff, upload1Diff, upload2Diff, pixelDiff, paletteDiff;\n\tdataDiff = prefix->data - (uintptr)raster->originalPixels;\n\tupload1Diff = uploads[0].tag2_addr - (uintptr)raster->originalPixels;\n\tif (raster->palette)\n\t\tupload2Diff = uploads[1].tag2_addr - (uintptr)raster->originalPixels;\n\tpixelDiff = (uintptr)raster->cpPixels - (uintptr)raster->originalPixels;\n\tif (raster->palette)\n\t\tpaletteDiff = (uintptr)raster->palette - (uintptr)raster->originalPixels;\n\tuint8* newptr = (uint8*)gMainHeap.MoveMemory(raster->originalPixels);\n\tif (newptr != raster->originalPixels) {\n\t\t// adjust everything\n\t\tprefix->data = (uintptr)newptr + dataDiff;\n\t\tuploads[0].tag2_addr = (uintptr)newptr + upload1Diff;\n\t\tif (raster->palette)\n\t\t\tuploads[1].tag2_addr = (uintptr)newptr + upload2Diff;\n\t\traster->originalPixels = newptr;\n\t\traster->cpPixels = newptr + pixelDiff;\n\t\tif (raster->palette)\n\t\t\traster->palette = newptr + paletteDiff;\n\n\t\tif (pRet) {\n\t\t\t*pRet = true;\n\t\t\treturn nil;\n\t\t}\n\t}\n#else\n\t// nothing to do here really, everything should be in videomemory\n#endif\n\treturn texture;\n}\n\nbool\nMoveAtomicMemory(RpAtomic* atomic, bool onlyOne)\n{\n\tRpGeometry* geo = RpAtomicGetGeometry(atomic);\n\n#if THIS_IS_COMPATIBLE_WITH_GTA3_RW31\n\tif (MoveMem((void**)&geo->triangles) && onlyOne)\n\t\treturn true;\n\tif (MoveMem((void**)&geo->matList.materials) && onlyOne)\n\t\treturn true;\n\tif (MoveMem((void**)&geo->preLitLum) && onlyOne)\n\t\treturn true;\n\tif (MoveMem((void**)&geo->texCoords[0]) && onlyOne)\n\t\treturn true;\n\tif (MoveMem((void**)&geo->texCoords[1]) && onlyOne)\n\t\treturn true;\n\n\t// verts and normals of morph target are allocated together\n\tint vertDiff;\n\tif (geo->morphTarget->normals)\n\t\tvertDiff = geo->morphTarget->normals - geo->morphTarget->verts;\n\tif (MoveMem((void**)&geo->morphTarget->verts)) {\n\t\tif (geo->morphTarget->normals)\n\t\t\tgeo->morphTarget->normals = geo->morphTarget->verts + vertDiff;\n\t\tif (onlyOne)\n\t\t\treturn true;\n\t}\n\n\tRpMeshHeader* oldmesh = geo->mesh;\n\tif (MoveMem((void**)&geo->mesh)) {\n\t\t// index pointers are allocated together with meshes,\n\t\t// have to relocate those too\n\t\tRpMesh* mesh = (RpMesh*)(geo->mesh + 1);\n\t\tuintptr reloc = (uintptr)geo->mesh - (uintptr)oldmesh;\n\t\tfor (int i = 0; i < geo->mesh->numMeshes; i++)\n\t\t\tmesh[i].indices = (RxVertexIndex*)((uintptr)mesh[i].indices + reloc);\n\t\tif (onlyOne)\n\t\t\treturn true;\n\t}\n#else\n\t// we could do something in librw here\n#endif\n\treturn false;\n}\n\nbool\nMoveColModelMemory(CColModel& colModel, bool onlyOne)\n{\n#if GTA_VERSION >= GTA3_PS2_160\n\t// hm...should probably only do this if ownsCollisionVolumes\n\t// but it doesn't exist on PS2...\n\tif (!colModel.ownsCollisionVolumes)\n\t\treturn false;\n#endif\n\n\tif (MoveMem((void**)&colModel.spheres) && onlyOne)\n\t\treturn true;\n\tif (MoveMem((void**)&colModel.lines) && onlyOne)\n\t\treturn true;\n\tif (MoveMem((void**)&colModel.boxes) && onlyOne)\n\t\treturn true;\n\tif (MoveMem((void**)&colModel.vertices) && onlyOne)\n\t\treturn true;\n\tif (MoveMem((void**)&colModel.triangles) && onlyOne)\n\t\treturn true;\n\tif (MoveMem((void**)&colModel.trianglePlanes) && onlyOne)\n\t\treturn true;\n\treturn false;\n}\n\nRpAtomic*\nMoveAtomicMemoryCB(RpAtomic* atomic, void* pData)\n{\n\tbool* pRet = (bool*)pData;\n\tif (pRet == nil)\n\t\tMoveAtomicMemory(atomic, false);\n\telse if (MoveAtomicMemory(atomic, true)) {\n\t\t*pRet = true;\n\t\treturn nil;\n\t}\n\treturn atomic;\n}\n\nbool\nTidyUpModelInfo(CBaseModelInfo* modelInfo, bool onlyone)\n{\n\tif (modelInfo->GetColModel() && modelInfo->DoesOwnColModel())\n\t\tif (MoveColModelMemory(*modelInfo->GetColModel(), onlyone))\n\t\t\treturn true;\n\n\tRwObject* rwobj = modelInfo->GetRwObject();\n\tif (RwObjectGetType(rwobj) == rpATOMIC)\n\t\tif (MoveAtomicMemory((RpAtomic*)rwobj, onlyone))\n\t\t\treturn true;\n\tif (RwObjectGetType(rwobj) == rpCLUMP) {\n\t\tbool ret = false;\n\t\tif (onlyone)\n\t\t\tRpClumpForAllAtomics((RpClump*)rwobj, MoveAtomicMemoryCB, &ret);\n\t\telse\n\t\t\tRpClumpForAllAtomics((RpClump*)rwobj, MoveAtomicMemoryCB, nil);\n\t\tif (ret)\n\t\t\treturn true;\n\t}\n\n\tif (modelInfo->GetModelType() == MITYPE_PED && ((CPedModelInfo*)modelInfo)->m_hitColModel)\n\t\tif (MoveColModelMemory(*((CPedModelInfo*)modelInfo)->m_hitColModel, onlyone))\n\t\t\treturn true;\n\n\treturn false;\n}\n#endif\n\n\nvoid CGame::DrasticTidyUpMemory(bool flushDraw)\n{\n#ifdef USE_CUSTOM_ALLOCATOR\n\tbool removedCol = false;\n\n\tTidyUpMemory(true, flushDraw);\n\n\tif (gMainHeap.GetLargestFreeBlock() < 200000 && !playingIntro) {\n\t\tCStreaming::RemoveIslandsNotUsed(LEVEL_INDUSTRIAL);\n\t\tCStreaming::RemoveIslandsNotUsed(LEVEL_COMMERCIAL);\n\t\tCStreaming::RemoveIslandsNotUsed(LEVEL_SUBURBAN);\n\t\tTidyUpMemory(true, flushDraw);\n\t}\n\n\tif (gMainHeap.GetLargestFreeBlock() < 200000 && !playingIntro) {\n\t\tCModelInfo::RemoveColModelsFromOtherLevels(LEVEL_GENERIC);\n\t\tTidyUpMemory(true, flushDraw);\n\t\tremovedCol = true;\n\t}\n\n\tif (gMainHeap.GetLargestFreeBlock() < 200000 && !playingIntro) {\n\t\tCStreaming::RemoveBigBuildings(LEVEL_INDUSTRIAL);\n\t\tCStreaming::RemoveBigBuildings(LEVEL_COMMERCIAL);\n\t\tCStreaming::RemoveBigBuildings(LEVEL_SUBURBAN);\n\t\tTidyUpMemory(true, flushDraw);\n\t}\n\n\tif (removedCol) {\n\t\t// different on PS2\n\t\tCFileLoader::LoadCollisionFromDatFile(CCollision::ms_collisionInMemory);\n\t}\n\n\tif (!playingIntro)\n\t\tCStreaming::RequestBigBuildings(currLevel);\n\n\tCStreaming::LoadAllRequestedModels(true);\n#endif\n}\n\nvoid CGame::TidyUpMemory(bool moveTextures, bool flushDraw)\n{\n#ifdef USE_CUSTOM_ALLOCATOR\n\tprintf(\"Largest free block before tidy %d\\n\", gMainHeap.GetLargestFreeBlock());\n\n\tif (moveTextures) {\n\t\tif (flushDraw) {\n#ifdef GTA_PS2\n\t\t\tfor (int i = 0; i < sweMaxFlips + 1; i++) {\n#else\n\t\t\tfor (int i = 0; i < 5; i++) {\t// probably more than needed\n#endif\n\t\t\t\tRwCameraBeginUpdate(Scene.camera);\n\t\t\t\tRwCameraEndUpdate(Scene.camera);\n\t\t\t\tRwCameraShowRaster(Scene.camera, nil, 0);\n\t\t\t}\n\t\t\t}\n\t\tint fontSlot = CTxdStore::FindTxdSlot(\"fonts\");\n\n\t\tfor (int i = 0; i < TXDSTORESIZE; i++) {\n\t\t\tif (i == fontSlot ||\n\t\t\t\tCTxdStore::GetSlot(i) == nil)\n\t\t\t\tcontinue;\n\t\t\tRwTexDictionary* txd = CTxdStore::GetSlot(i)->texDict;\n\t\t\tif (txd)\n\t\t\t\tRwTexDictionaryForAllTextures(txd, MoveTextureMemoryCB, nil);\n\t\t}\n\t\t}\n\n\t// animations\n\tfor (int i = 0; i < NUMANIMATIONS; i++) {\n\t\tCAnimBlendHierarchy* anim = CAnimManager::GetAnimation(i);\n\t\tif (anim == nil)\n\t\t\tcontinue;\t// cannot happen\n\t\tanim->MoveMemory();\n\t}\n\n\t// model info\n\tfor (int i = 0; i < MODELINFOSIZE; i++) {\n\t\tCBaseModelInfo* mi = CModelInfo::GetModelInfo(i);\n\t\tif (mi == nil)\n\t\t\tcontinue;\n\t\tTidyUpModelInfo(mi, false);\n\t}\n\n\tprintf(\"Largest free block after tidy %d\\n\", gMainHeap.GetLargestFreeBlock());\n#endif\n\t}\n\nvoid CGame::ProcessTidyUpMemory(void)\n{\n#ifdef USE_CUSTOM_ALLOCATOR\n\tstatic int32 modelIndex = 0;\n\tstatic int32 animIndex = 0;\n\tstatic int32 txdIndex = 0;\n\tbool txdReturn = false;\n\tRwTexDictionary* txd = nil;\n\tgNumMemMoved = 0;\n\n\t// model infos\n\tfor (int numCleanedUp = 0; numCleanedUp < 10; numCleanedUp++) {\n\t\tCBaseModelInfo* mi;\n\t\tdo {\n\t\t\tmi = CModelInfo::GetModelInfo(modelIndex);\n\t\t\tmodelIndex++;\n\t\t\tif (modelIndex >= MODELINFOSIZE)\n\t\t\t\tmodelIndex = 0;\n\t\t} while (mi == nil);\n\n\t\tif (TidyUpModelInfo(mi, true))\n\t\t\treturn;\n\t}\n\n\t// tex dicts\n\tfor (int numCleanedUp = 0; numCleanedUp < 3; numCleanedUp++) {\n\t\tif (gNumMemMoved > 80)\n\t\t\tbreak;\n\n\t\tdo {\n#ifdef FIX_BUGS\n\t\t\ttxd = nil;\n#endif\n\t\t\tif (CTxdStore::GetSlot(txdIndex))\n\t\t\t\ttxd = CTxdStore::GetSlot(txdIndex)->texDict;\n\t\t\ttxdIndex++;\n\t\t\tif (txdIndex >= TXDSTORESIZE)\n\t\t\t\ttxdIndex = 0;\n\t\t} while (txd == nil);\n\n\t\tRwTexDictionaryForAllTextures(txd, MoveTextureMemoryCB, &txdReturn);\n\t\tif (txdReturn)\n\t\t\treturn;\n\t\t}\n\n\t// animations\n\tCAnimBlendHierarchy* anim;\n\tdo {\n\t\tanim = CAnimManager::GetAnimation(animIndex);\n\t\tanimIndex++;\n\t\tif (animIndex >= NUMANIMATIONS)\n\t\t\tanimIndex = 0;\n\t} while (anim == nil);\t// always != nil\n\tanim->MoveMemory(true);\n#endif\n}\n\nvoid\nCGame::InitAfterFocusLoss()\n{\n\tFrontEndMenuManager.m_nPrefsAudio3DProviderIndex = FrontEndMenuManager.m_lastWorking3DAudioProvider;\n\tDMAudio.SetCurrent3DProvider(FrontEndMenuManager.m_lastWorking3DAudioProvider);\n\n\tif (!FrontEndMenuManager.m_bGameNotLoaded && !FrontEndMenuManager.m_bMenuActive)\n\t\tFrontEndMenuManager.m_bStartUpFrontEndRequested = true;\n}\n\nbool\nCGame::CanSeeWaterFromCurrArea(void)\n{\n\treturn currArea == AREA_MAIN_MAP || currArea == AREA_MANSION\n\t\t|| currArea == AREA_HOTEL;\n}\n\nbool\nCGame::CanSeeOutSideFromCurrArea(void)\n{\n\treturn currArea == AREA_MAIN_MAP || currArea == AREA_MALL ||\n\t\tcurrArea == AREA_MANSION || currArea == AREA_HOTEL;\n}\n"
  },
  {
    "path": "src/core/Game.h",
    "content": "#pragma once\n\nenum eLevelName {\n\tLEVEL_IGNORE = -1, // beware, this is only used in CPhysical's m_nZoneLevel\n\tLEVEL_GENERIC = 0,\n\tLEVEL_BEACH,\n\tLEVEL_MAINLAND,\n\n\tNUM_LEVELS\n};\n\nenum eAreaName {\n\tAREA_MAIN_MAP,\n\tAREA_HOTEL,\n\tAREA_MANSION,\n\tAREA_BANK,\n\tAREA_MALL,\n\tAREA_STRIP_CLUB,\n\tAREA_LAWYERS,\n\tAREA_COFFEE_SHOP,\n\tAREA_CONCERT_HALL,\n\tAREA_STUDIO,\n\tAREA_RIFLE_RANGE,\n\tAREA_BIKER_BAR,\n\tAREA_POLICE_STATION,\n\tAREA_EVERYWHERE,\n\tAREA_DIRT,\n\tAREA_BLOOD,\n\tAREA_OVALRING,\n\tAREA_MALIBU_CLUB,\n\tAREA_PRINT_WORKS\n};\n\nclass CGame\n{\npublic:\n\tstatic eLevelName currLevel;\n\tstatic int32 currArea;\n\tstatic bool bDemoMode;\n\tstatic bool nastyGame;\n\tstatic bool frenchGame;\n\tstatic bool germanGame;\n#ifdef MORE_LANGUAGES\n\tstatic bool russianGame;\n\tstatic bool japaneseGame;\n#endif\n\tstatic bool noProstitutes;\n\tstatic bool playingIntro;\n\tstatic char aDatFile[32];\n\n#ifndef MASTER\n\tstatic CVector PlayerCoords;\n\tstatic bool8 VarUpdatePlayerCoords;\n#endif\n\n\tstatic bool InitialiseOnceBeforeRW(void);\n\tstatic bool InitialiseRenderWare(void);\n\tstatic void ShutdownRenderWare(void);\n\tstatic bool InitialiseOnceAfterRW(void);\n\tstatic void FinalShutdown(void);\n\tstatic bool Initialise(const char *datFile);\n\tstatic bool ShutDown(void);\n\tstatic void ReInitGameObjectVariables(void);\n\tstatic void ReloadIPLs(void);\n\tstatic void ShutDownForRestart(void);\n\tstatic void InitialiseWhenRestarting(void);\n\tstatic void Process(void);\n\n\tstatic void InitAfterFocusLoss(void);\n\n\tstatic bool IsInInterior(void) { return currArea != AREA_MAIN_MAP; }\n\tstatic bool CanSeeWaterFromCurrArea(void);\n\tstatic bool CanSeeOutSideFromCurrArea(void);\n\t\n\t// NB: these do something on PS2\n\tstatic void TidyUpMemory(bool, bool);\n\tstatic void DrasticTidyUpMemory(bool);\n\tstatic void ProcessTidyUpMemory(void);\n};\n\ninline bool IsAreaVisible(int area) { return area == CGame::currArea || area == AREA_EVERYWHERE; }\n"
  },
  {
    "path": "src/core/General.h",
    "content": "#pragma once\n\n#include <ctype.h>\n\nclass CGeneral\n{\npublic:\n\tstatic float GetATanOfXY(float x, float y){\n\t\tif(x == 0.0f && y == 0.0f)\n\t\t\treturn 0.0f;\n\t\tfloat xabs = Abs(x);\n\t\tfloat yabs = Abs(y);\n\n\t\tif(xabs < yabs){\n\t\t\tif(y > 0.0f){\n\t\t\t\tif(x > 0.0f)\n\t\t\t\t\treturn 0.5f*PI - Atan2(x / y, 1.0f);\n\t\t\t\telse\n\t\t\t\t\treturn 0.5f*PI + Atan2(-x / y, 1.0f);\n\t\t\t}else{\n\t\t\t\tif(x > 0.0f)\n\t\t\t\t\treturn 1.5f*PI + Atan2(x / -y, 1.0f);\n\t\t\t\telse\n\t\t\t\t\treturn 1.5f*PI - Atan2(-x / -y, 1.0f);\n\t\t\t}\n\t\t}else{\n\t\t\tif(y > 0.0f){\n\t\t\t\tif(x > 0.0f)\n\t\t\t\t\treturn Atan2(y / x, 1.0f);\n\t\t\t\telse\n\t\t\t\t\treturn PI - Atan2(y / -x, 1.0f);\n\t\t\t}else{\n\t\t\t\tif(x > 0.0f)\n\t\t\t\t\treturn 2.0f*PI - Atan2(-y / x, 1.0f);\n\t\t\t\telse\n\t\t\t\t\treturn PI + Atan2(-y / -x, 1.0f);\n\t\t\t}\n\t\t}\n\t}\n\n\tstatic float LimitAngle(float angle)\n\t{\n\t\tfloat result = angle;\n\n\t\twhile (result >= 180.0f) {\n\t\t\tresult -= 2 * 180.0f;\n\t\t}\n\n\t\twhile (result < -180.0f) {\n\t\t\tresult += 2 * 180.0f;\n\t\t}\n\n\t\treturn result;\n\t}\n\n\n\tstatic float LimitRadianAngle(float angle)\n\t{\n\t\tfloat result = clamp(angle, -25.0f, 25.0f);\n\n\t\twhile (result >= PI) {\n\t\t\tresult -= 2 * PI;\n\t\t}\n\n\t\twhile (result < -PI) {\n\t\t\tresult += 2 * PI;\n\t\t}\n\t\n\t\treturn result;\n\t}\n\n\t// Returns an angle such that x2/y2 looks at x1/y1 with its forward vector if rotated by that angle\n\tstatic float GetRadianAngleBetweenPoints(float x1, float y1, float x2, float y2)\n\t{\n\t\tfloat x = x2 - x1;\n\t\tfloat y = y2 - y1;\n\n\t\tif (y == 0.0f)\n\t\t\ty = 0.0001f;\n\n\t\tif (x > 0.0f) {\n\t\t\tif (y > 0.0f)\n\t\t\t\treturn PI - Atan2(x / y, 1.0f);\n\t\t\telse\n\t\t\t\treturn -Atan2(x / y, 1.0f);\n\t\t} else {\n\t\t\tif (y > 0.0f)\n\t\t\t\treturn -(PI + Atan2(x / y, 1.0f));\n\t\t\telse\n\t\t\t\treturn -Atan2(x / y, 1.0f);\n\t\t}\n\t}\n\t\n\tstatic float GetAngleBetweenPoints(float x1, float y1, float x2, float y2)\n\t{\n\t\treturn RADTODEG(GetRadianAngleBetweenPoints(x1, y1, x2, y2));\n\t}\n\n\t// should return direction in 0-8 range. fits perfectly to peds' path directions.\n\tstatic int GetNodeHeadingFromVector(float x, float y)\n\t{\n\t\tfloat angle = CGeneral::GetRadianAngleBetweenPoints(x, y, 0.0f, 0.0f);\n\t\tif (angle < 0.0f)\n\t\t\tangle += TWOPI;\n\n\t\tangle = DEGTORAD(22.5f) + TWOPI - angle;\n\n\t\tif (angle >= TWOPI)\n\t\t\tangle -= TWOPI;\n\n\t\treturn (int)Floor(angle / DEGTORAD(45.0f));\n\t}\n\n\t// Unlike usual string comparison functions, these don't care about greater or lesser\n\tstatic bool faststrcmp(const char *str1, const char *str2)\n\t{\n\t\tfor (; *str1; str1++, str2++) {\n\t\t\tif (*str1 != *str2)\n\t\t\t\treturn true;\n\t\t}\n\t\treturn *str2 != '\\0';\n\t}\n\n\tstatic bool faststrncmp(const char *str1, const char *str2, uint32 count)\n\t{\n\t\tfor(uint32 i = 0; *str1 && i < count; str1++, str2++, i++) {\n\t\t\tif (*str1 != *str2)\n\t\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\tstatic bool faststricmp(const char *str1, const char *str2)\n\t{\n\t\tfor (; *str1; str1++, str2++) {\n#ifndef ASCII_STRCMP\n\t\t\tif (toupper(*str1) != toupper(*str2))\n#else\n\t\t\tif (__ascii_toupper(*str1) != __ascii_toupper(*str2))\n#endif\n\t\t\t\treturn true;\n\t\t}\n\t\treturn *str2 != '\\0';\n\t}\n\n\tstatic bool SolveQuadratic(float a, float b, float c, float &root1, float &root2)\n\t{\n\t\tfloat discriminant = b * b - 4.f * a * c;\n\t\tif (discriminant < 0.f)\n\t\t\treturn false;\n\n\t\tfloat discriminantSqrt = Sqrt(discriminant);\n\t\troot2 = (-b + discriminantSqrt) / (2.f * a);\n\t\troot1 = (-b - discriminantSqrt) / (2.f * a);\n\t\treturn true;\n\t}\n\n\t// not too sure about all these...\n\tstatic uint16 GetRandomNumber(void)\n\t\t{ return myrand() & MYRAND_MAX; }\n\tstatic bool GetRandomTrueFalse(void)\n\t\t{ return GetRandomNumber() < MYRAND_MAX / 2; }\n\t// Probably don't want to ever reach high\n\tstatic float GetRandomNumberInRange(float low, float high)\n\t\t{ return low + (high - low)*(GetRandomNumber()/float(MYRAND_MAX + 1)); }\n\t\t\n\tstatic int32 GetRandomNumberInRange(int32 low, int32 high)\n\t\t{ return low + (high - low)*(GetRandomNumber()/float(MYRAND_MAX + 1)); }\n\tstatic void SetRandomSeed(int32 seed)\n\t\t{ mysrand(seed); }\n};\n"
  },
  {
    "path": "src/core/IniFile.cpp",
    "content": "#include \"common.h\"\n\n#include \"IniFile.h\"\n\n#include \"CarCtrl.h\"\n#include \"FileMgr.h\"\n#include \"main.h\"\n#include \"Population.h\"\n\nfloat CIniFile::PedNumberMultiplier = 0.6f;\nfloat CIniFile::CarNumberMultiplier = 0.6f;\n\nvoid CIniFile::LoadIniFile()\n{\n\tCFileMgr::SetDir(\"\");\n\tint f = CFileMgr::OpenFile(\"gta3.ini\", \"r\");\n\tif (f){\n\t\tCFileMgr::ReadLine(f, gString, 200);\n\t\tsscanf(gString, \"%f\", &PedNumberMultiplier);\n\t\tPedNumberMultiplier = Min(3.0f, Max(0.5f, PedNumberMultiplier));\n\t\tCFileMgr::ReadLine(f, gString, 200);\n\t\tsscanf(gString, \"%f\", &CarNumberMultiplier);\n\t\tCarNumberMultiplier = Min(3.0f, Max(0.5f, CarNumberMultiplier));\n\t\tCFileMgr::CloseFile(f);\n\t}\n\tCPopulation::MaxNumberOfPedsInUse = 25.0f * PedNumberMultiplier;\n\tCPopulation::MaxNumberOfPedsInUseInterior = 40.0f * PedNumberMultiplier;\n\tCCarCtrl::MaxNumberOfCarsInUse = 12.0f * CarNumberMultiplier;\n}"
  },
  {
    "path": "src/core/IniFile.h",
    "content": "#pragma once\n\nclass CIniFile\n{\npublic:\n\tstatic void LoadIniFile();\n\n\tstatic float PedNumberMultiplier;\n\tstatic float CarNumberMultiplier;\n};\n"
  },
  {
    "path": "src/core/Lists.cpp",
    "content": "#include \"common.h\"\n#include \"Pools.h\"\n#include \"Lists.h\"\n\nvoid*\nCPtrNode::operator new(size_t){\n\tCPtrNode *node = CPools::GetPtrNodePool()->New();\n\tassert(node);\n\treturn node;\n}\n\nvoid\nCPtrNode::operator delete(void *p, size_t){\n\tCPools::GetPtrNodePool()->Delete((CPtrNode*)p);\n}\n\nvoid*\nCEntryInfoNode::operator new(size_t){\n\tCEntryInfoNode *node = CPools::GetEntryInfoNodePool()->New();\n\tassert(node);\n\treturn node;\n}\nvoid\nCEntryInfoNode::operator delete(void *p, size_t){\n\tCPools::GetEntryInfoNodePool()->Delete((CEntryInfoNode*)p);\n}\n"
  },
  {
    "path": "src/core/Lists.h",
    "content": "#pragma once\n\nclass CPtrNode\n{\npublic:\n\tvoid *item;\n\tCPtrNode *prev;\n\tCPtrNode *next;\n\n\tvoid *operator new(size_t);\n\tvoid operator delete(void *p, size_t);\n};\n\nclass CPtrList\n{\npublic:\n\tCPtrNode *first;\n\n\tCPtrList(void) { first = nil; }\n\t~CPtrList(void) { Flush(); }\n\tCPtrNode *FindItem(void *item){\n\t\tCPtrNode *node;\n\t\tfor(node = first; node; node = node->next)\n\t\t\tif(node->item == item)\n\t\t\t\treturn node;\n\t\treturn nil;\n\t}\n\tCPtrNode *InsertNode(CPtrNode *node){\n\t\tnode->prev = nil;\n\t\tnode->next = first;\n\t\tif(first)\n\t\t\tfirst->prev = node;\n\t\tfirst = node;\n\t\treturn node;\n\t}\n\tCPtrNode *InsertItem(void *item){\n\t\tCPtrNode *node = new CPtrNode;\n\t\tnode->item = item;\n\t\tInsertNode(node);\n\t\treturn node;\n\t}\n\tvoid RemoveNode(CPtrNode *node){\n\t\tif(node == first)\n\t\t\tfirst = node->next;\n\t\tif(node->prev)\n\t\t\tnode->prev->next = node->next;\n\t\tif(node->next)\n\t\t\tnode->next->prev = node->prev;\n\t}\n\tvoid DeleteNode(CPtrNode *node){\n\t\tRemoveNode(node);\n\t\tdelete node;\n\t}\n\tvoid RemoveItem(void *item){\n\t\tCPtrNode *node, *next;\n\t\tfor(node = first; node; node = next){\n\t\t\tnext = node->next;\n\t\t\tif(node->item == item)\n\t\t\t\tDeleteNode(node);\n\t\t}\n\t}\n\tvoid Flush(void){\n\t\tCPtrNode *node, *next;\n\t\tfor(node = first; node; node = next){\n\t\t\tnext = node->next;\n\t\t\tDeleteNode(node);\n\t\t}\n\t}\n};\n\nclass CSector;\n\n// This records in which sector list a Physical is\nclass CEntryInfoNode\n{\npublic:\n\tCPtrList *list;\t\t// list in sector\n\tCPtrNode *listnode;\t// node in list\n\tCSector *sector;\n\n\tCEntryInfoNode *prev;\n\tCEntryInfoNode *next;\n\n\tvoid *operator new(size_t);\n\tvoid operator delete(void *p, size_t);\n};\n\nclass CEntryInfoList\n{\npublic:\n\tCEntryInfoNode *first;\n\n\tCEntryInfoList(void) { first = nil; }\n\t~CEntryInfoList(void) { Flush(); }\n\tCEntryInfoNode *InsertNode(CEntryInfoNode *node){\n\t\tnode->prev = nil;\n\t\tnode->next = first;\n\t\tif(first)\n\t\t\tfirst->prev = node;\n\t\tfirst = node;\n\t\treturn node;\n\t}\n\tCEntryInfoNode *InsertItem(CPtrList *list, CPtrNode *listnode, CSector *sect){\n\t\tCEntryInfoNode *node = new CEntryInfoNode;\n\t\tnode->list = list;\n\t\tnode->listnode = listnode;\n\t\tnode->sector = sect;\n\t\tInsertNode(node);\n\t\treturn node;\n\t}\n\tvoid RemoveNode(CEntryInfoNode *node){\n\t\tif(node == first)\n\t\t\tfirst = node->next;\n\t\tif(node->prev)\n\t\t\tnode->prev->next = node->next;\n\t\tif(node->next)\n\t\t\tnode->next->prev = node->prev;\n\t}\n\tvoid DeleteNode(CEntryInfoNode *node){\n\t\tRemoveNode(node);\n\t\tdelete node;\n\t}\n\tvoid Flush(void){\n\t\tCEntryInfoNode *node, *next;\n\t\tfor(node = first; node; node = next){\n\t\t\tnext = node->next;\n\t\t\tDeleteNode(node);\n\t\t}\n\t}\n};\n"
  },
  {
    "path": "src/core/MenuScreens.cpp",
    "content": "#include \"common.h\"\n#include \"Frontend.h\"\n#ifdef PC_MENU\n\n// Please don't touch this file, except for bug fixing or ports.\n// Check MenuScreensCustom.cpp\n\n#ifndef CUSTOM_FRONTEND_OPTIONS\nCMenuScreen aScreens[] = {\n\t// MENUPAGE_STATS = 0\n\t{ \"FEH_STA\", MENUPAGE_NONE, 3,\n\t\tMENUACTION_GOBACK, \"FEDS_TB\", SAVESLOT_NONE, MENUPAGE_NONE, 190, 320, MENUALIGN_RIGHT,\n\t},\n\n\t// MENUPAGE_NEW_GAME = 1\n\t{ \"FEP_STG\", MENUPAGE_NONE, 1,\n\t\tMENUACTION_CHANGEMENU, \"FES_NGA\", SAVESLOT_NONE, MENUPAGE_NEW_GAME_RELOAD, 320, 155, MENUALIGN_CENTER,\n\t\tMENUACTION_CHANGEMENU, \"FES_LOA\",  SAVESLOT_NONE, MENUPAGE_CHOOSE_LOAD_SLOT, 0, 0, MENUALIGN_CENTER,\n\t\tMENUACTION_CHANGEMENU, \"FES_DEL\", SAVESLOT_NONE, MENUPAGE_CHOOSE_DELETE_SLOT, 0, 0, MENUALIGN_CENTER,\n\t\tMENUACTION_GOBACK, \"FEDS_TB\", SAVESLOT_NONE, 0, 0, 0, MENUALIGN_CENTER,\n\t},\n\n\t// MENUPAGE_BRIEFS = 2\n\t{ \"FEH_BRI\", MENUPAGE_NONE, 4,\n\t\tMENUACTION_GOBACK, \"FEDS_TB\", SAVESLOT_NONE, MENUPAGE_NONE, 190, 320, MENUALIGN_RIGHT,\n\t},\n\n\t// MENUPAGE_SOUND_SETTINGS = 3\n\t{ \"FEH_AUD\", MENUPAGE_OPTIONS, 1,\n\t\tMENUACTION_MUSICVOLUME,\t\t\"FEA_MUS\", SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS, 40, 76, MENUALIGN_LEFT,\n\t\tMENUACTION_SFXVOLUME,\t\t\"FEA_SFX\", SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS, 0, 0, MENUALIGN_LEFT,\n\t\tMENUACTION_MP3VOLUMEBOOST,\t\"FEA_MPB\", SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS, 0, 0, MENUALIGN_LEFT,\n\t\tMENUACTION_AUDIOHW,\t\t\t\"FEA_3DH\", SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS, 0, 0, MENUALIGN_LEFT,\n\t\tMENUACTION_SPEAKERCONF,\t\t\"FEA_SPK\", SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS, 0, 0, MENUALIGN_LEFT,\n\t\tMENUACTION_DYNAMICACOUSTIC,\t\"FET_DAM\", SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS, 0, 0, MENUALIGN_LEFT,\n\t\tMENUACTION_RADIO,\t\t\t\"FEA_RSS\", SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS, 0, 0, MENUALIGN_LEFT,\n\t\tMENUACTION_RESTOREDEF,\t\t\"FET_DEF\", SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS, 320, 367, MENUALIGN_CENTER,\n\t\tMENUACTION_GOBACK,\t\t\t\"FEDS_TB\", SAVESLOT_NONE, MENUPAGE_NONE, 0, 0, MENUALIGN_CENTER,\n\t},\n\n\t// MENUPAGE_DISPLAY_SETTINGS = 4\n#ifdef LEGACY_MENU_OPTIONS\n\t#define Y_OFFSET 50\n#else\n\t#define Y_OFFSET 0\n#endif\n\n\t{ \"FEH_DIS\", MENUPAGE_OPTIONS, 2,\n\t\tMENUACTION_BRIGHTNESS,\t\"FED_BRI\", SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS, 40, 78, MENUALIGN_LEFT,\n\t\tMENUACTION_DRAWDIST,\t\"FEM_LOD\", SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS, 40, 103, MENUALIGN_LEFT,\n#ifdef LEGACY_MENU_OPTIONS\n\t\tMENUACTION_FRAMESYNC,\t\"FEM_VSC\", SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS, 40, 128, MENUALIGN_LEFT,\n#endif\n\t\tMENUACTION_FRAMELIMIT,\t\"FEM_FRM\", SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS, 40, 128 + Y_OFFSET/2, MENUALIGN_LEFT,\n#ifdef LEGACY_MENU_OPTIONS\n\t\tMENUACTION_TRAILS,\t\t\"FED_TRA\", SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS, 40, 178, MENUALIGN_LEFT,\n#endif\n\t\tMENUACTION_SUBTITLES,\t\"FED_SUB\", SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS, 40, 153 + Y_OFFSET, MENUALIGN_LEFT,\n\t\tMENUACTION_WIDESCREEN,\t\"FED_WIS\", SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS, 40, 178 + Y_OFFSET, MENUALIGN_LEFT,\n\t\tMENUACTION_LEGENDS,\t\t\"MAP_LEG\", SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS, 40, 202 + Y_OFFSET, MENUALIGN_LEFT,\n\t\tMENUACTION_RADARMODE,\t\"FED_RDR\", SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS, 40, 228 + Y_OFFSET, MENUALIGN_LEFT,\n\t\tMENUACTION_HUD,\t\t\t\"FED_HUD\", SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS, 40, 253 + Y_OFFSET, MENUALIGN_LEFT,\n\t\tMENUACTION_SCREENRES,\t\"FED_RES\", SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS, 40, 278 + Y_OFFSET, MENUALIGN_LEFT,\n\t\tMENUACTION_RESTOREDEF,\t\"FET_DEF\", SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS, 320, 303 + Y_OFFSET, MENUALIGN_CENTER,\n\t\tMENUACTION_GOBACK,\t\t\"FEDS_TB\", SAVESLOT_NONE, MENUPAGE_NONE, 320, 328 + Y_OFFSET, MENUALIGN_CENTER,\n\t},\n\n#undef Y_OFFSET\n\n\t// MENUPAGE_LANGUAGE_SETTINGS = 5\n\t{ \"FEH_LAN\", MENUPAGE_OPTIONS, 3,\n\t\tMENUACTION_LANG_ENG,\t\"FEL_ENG\", SAVESLOT_NONE, MENUPAGE_LANGUAGE_SETTINGS, 320, 132, MENUALIGN_CENTER,\n\t\tMENUACTION_LANG_FRE,\t\"FEL_FRE\", SAVESLOT_NONE, MENUPAGE_LANGUAGE_SETTINGS, 0, 0, MENUALIGN_CENTER,\n\t\tMENUACTION_LANG_GER,\t\"FEL_GER\", SAVESLOT_NONE, MENUPAGE_LANGUAGE_SETTINGS, 0, 0, MENUALIGN_CENTER,\n\t\tMENUACTION_LANG_ITA,\t\"FEL_ITA\", SAVESLOT_NONE, MENUPAGE_LANGUAGE_SETTINGS, 0, 0, MENUALIGN_CENTER,\n\t\tMENUACTION_LANG_SPA,    \"FEL_SPA\", SAVESLOT_NONE, MENUPAGE_LANGUAGE_SETTINGS, 0, 0, MENUALIGN_CENTER,\n\t\tMENUACTION_GOBACK,\t\t\"FEDS_TB\", SAVESLOT_NONE, MENUPAGE_NONE, 0, 0, MENUALIGN_CENTER,\n\t},\n\n\t// MENUPAGE_MAP = 6\n\t{ \"FEH_MAP\", MENUPAGE_NONE, 2,\n\t\t MENUACTION_GOBACK,\t\"FEDS_TB\", SAVESLOT_NONE, MENUPAGE_NONE, 70, 380, MENUALIGN_CENTER,\n\t},\n\n\t// MENUPAGE_NEW_GAME_RELOAD = 7\n\t{ \"FES_NGA\", MENUPAGE_NEW_GAME, 0,\n\t\tMENUACTION_LABEL,\t\t\"FESZ_QR\",\tSAVESLOT_NONE,\t0, 0, 0, 0,\n\t\tMENUACTION_NO,\t\t\t\"FEM_NO\",\tSAVESLOT_NONE,\tMENUPAGE_NEW_GAME, 320, 200, MENUALIGN_CENTER,\n\t\tMENUACTION_NEWGAME,\t\t\"FEM_YES\",\tSAVESLOT_NONE,\tMENUPAGE_NEW_GAME_RELOAD, 320, 225, MENUALIGN_CENTER,\n\t},\n\n\t// MENUPAGE_CHOOSE_LOAD_SLOT = 8\n\t{ \"FET_LG\", MENUPAGE_NEW_GAME, 1,\n\t\tMENUACTION_CHECKSAVE,\t\"FEM_SL1\", SAVESLOT_1,\t\t0, 40, 90, MENUALIGN_LEFT,\n\t\tMENUACTION_CHECKSAVE,\t\"FEM_SL2\", SAVESLOT_2,\t\t0, 0, 0, MENUALIGN_LEFT,\n\t\tMENUACTION_CHECKSAVE,\t\"FEM_SL3\", SAVESLOT_3,\t\t0, 0, 0, MENUALIGN_LEFT,\n\t\tMENUACTION_CHECKSAVE,\t\"FEM_SL4\", SAVESLOT_4,\t\t0, 0, 0, MENUALIGN_LEFT,\n\t\tMENUACTION_CHECKSAVE,\t\"FEM_SL5\", SAVESLOT_5,\t\t0, 0, 0, MENUALIGN_LEFT,\n\t\tMENUACTION_CHECKSAVE,\t\"FEM_SL6\", SAVESLOT_6,\t\t0, 0, 0, MENUALIGN_LEFT,\n\t\tMENUACTION_CHECKSAVE,\t\"FEM_SL7\", SAVESLOT_7,\t\t0, 0, 0, MENUALIGN_LEFT,\n\t\tMENUACTION_CHECKSAVE,\t\"FEM_SL8\", SAVESLOT_8,\t\t0, 0, 0, MENUALIGN_LEFT,\n\t\tMENUACTION_GOBACK,\t\t\"FEDS_TB\", SAVESLOT_NONE,\t0, 320, 345, MENUALIGN_CENTER,\n\t},\n\n\t// MENUPAGE_CHOOSE_DELETE_SLOT = 9\n\t{ \"FES_DEL\", MENUPAGE_NEW_GAME, 2,\n\t\tMENUACTION_CHECKSAVE,\t\"FEM_SL1\",\tSAVESLOT_1,\t\t0, 40, 90, MENUALIGN_LEFT,\n\t\tMENUACTION_CHECKSAVE,\t\"FEM_SL2\",\tSAVESLOT_2,\t\t0, 0, 0, MENUALIGN_LEFT,\n\t\tMENUACTION_CHECKSAVE,\t\"FEM_SL3\",\tSAVESLOT_3,\t\t0, 0, 0, MENUALIGN_LEFT,\n\t\tMENUACTION_CHECKSAVE,\t\"FEM_SL4\",\tSAVESLOT_4,\t\t0, 0, 0, MENUALIGN_LEFT,\n\t\tMENUACTION_CHECKSAVE,\t\"FEM_SL5\",\tSAVESLOT_5,\t\t0, 0, 0, MENUALIGN_LEFT,\n\t\tMENUACTION_CHECKSAVE,\t\"FEM_SL6\",\tSAVESLOT_6,\t\t0, 0, 0, MENUALIGN_LEFT,\n\t\tMENUACTION_CHECKSAVE,\t\"FEM_SL7\",\tSAVESLOT_7,\t\t0, 0, 0, MENUALIGN_LEFT,\n\t\tMENUACTION_CHECKSAVE,\t\"FEM_SL8\",\tSAVESLOT_8,\t\t0, 0, 0, MENUALIGN_LEFT,\n\t\tMENUACTION_GOBACK,\t\t\"FEDS_TB\",\tSAVESLOT_NONE,\t0, 320, 345, MENUALIGN_CENTER,\n\t},\n\n\t// MENUPAGE_LOAD_SLOT_CONFIRM = 10\n\t{ \"FET_LG\", MENUPAGE_CHOOSE_LOAD_SLOT, 0,\n\t\t MENUACTION_LABEL,\t\t\"FESZ_QL\",\tSAVESLOT_NONE,\t0, 0, 0, 0,\n\t\t MENUACTION_NO,\t\t\t\"FEM_NO\",\tSAVESLOT_NONE,\tMENUPAGE_CHOOSE_LOAD_SLOT, 320, 200, MENUALIGN_CENTER,\n\t\t MENUACTION_YES,\t\t\"FEM_YES\",\tSAVESLOT_NONE,\tMENUPAGE_LOADING_IN_PROGRESS, 320, 225, MENUALIGN_CENTER,\n\t},\n\n\t// MENUPAGE_DELETE_SLOT_CONFIRM = 11\n\t{ \"FES_DEL\", MENUPAGE_CHOOSE_DELETE_SLOT, 0,\n\t\t MENUACTION_LABEL,\t\t\"FESZ_QD\",\tSAVESLOT_NONE,  MENUPAGE_NONE, 0, 0, 0,\n\t\t MENUACTION_NO,\t\t\t\"FEM_NO\",\tSAVESLOT_NONE,  MENUPAGE_CHOOSE_DELETE_SLOT, 320, 200, MENUALIGN_CENTER,\n\t\t MENUACTION_YES,\t\t\"FEM_YES\",\tSAVESLOT_NONE,\tMENUPAGE_DELETING_IN_PROGRESS, 320, 225, MENUALIGN_CENTER,\n\t},\n\n\t// MENUPAGE_LOADING_IN_PROGRESS = 12\n\t{ \"FET_LG\", MENUPAGE_CHOOSE_LOAD_SLOT, 0,\n\t},\n\n\t// MENUPAGE_DELETING_IN_PROGRESS = 13\n\t{ \"FES_DEL\", MENUPAGE_CHOOSE_DELETE_SLOT, 0,\n\t},\n\n\t// MENUPAGE_DELETE_SUCCESSFUL = 14\n\t{ \"FES_DEL\", MENUPAGE_NEW_GAME, 0,\n\t\t MENUACTION_LABEL,\t\t\"FES_DSC\",\tSAVESLOT_NONE,\t0, 0, 0, 0,\n\t\t MENUACTION_CHANGEMENU,\t\"FEM_OK\",\tSAVESLOT_NONE,\tMENUPAGE_NEW_GAME, 320, 225, MENUALIGN_CENTER,\n\t},\n\n\t// MENUPAGE_CHOOSE_SAVE_SLOT = 15\n\t{ \"FET_SG\", MENUPAGE_DISABLED, 0,\n\t\tMENUACTION_SAVEGAME,\t\t\t\"FEM_SL1\", SAVESLOT_1,\t\tMENUPAGE_SAVE_OVERWRITE_CONFIRM, 40, 90, MENUALIGN_LEFT,\n\t\tMENUACTION_SAVEGAME,\t\t\t\"FEM_SL2\", SAVESLOT_2,\t\tMENUPAGE_SAVE_OVERWRITE_CONFIRM, 0, 0, MENUALIGN_LEFT,\n\t\tMENUACTION_SAVEGAME,\t\t\t\"FEM_SL3\", SAVESLOT_3,\t\tMENUPAGE_SAVE_OVERWRITE_CONFIRM, 0, 0, MENUALIGN_LEFT,\n\t\tMENUACTION_SAVEGAME,\t\t\t\"FEM_SL4\", SAVESLOT_4,\t\tMENUPAGE_SAVE_OVERWRITE_CONFIRM, 0, 0, MENUALIGN_LEFT,\n\t\tMENUACTION_SAVEGAME,\t\t\t\"FEM_SL5\", SAVESLOT_5,\t\tMENUPAGE_SAVE_OVERWRITE_CONFIRM, 0, 0, MENUALIGN_LEFT,\n\t\tMENUACTION_SAVEGAME,\t\t\t\"FEM_SL6\", SAVESLOT_6,\t\tMENUPAGE_SAVE_OVERWRITE_CONFIRM, 0, 0, MENUALIGN_LEFT,\n\t\tMENUACTION_SAVEGAME,\t\t\t\"FEM_SL7\", SAVESLOT_7,\t\tMENUPAGE_SAVE_OVERWRITE_CONFIRM, 0, 0, MENUALIGN_LEFT,\n\t\tMENUACTION_SAVEGAME,\t\t\t\"FEM_SL8\", SAVESLOT_8,\t\tMENUPAGE_SAVE_OVERWRITE_CONFIRM, 0, 0, MENUALIGN_LEFT,\n\t\tMENUACTION_RESUME_FROM_SAVEZONE,\"FESZ_CA\", SAVESLOT_NONE,\t0, 320, 345, MENUALIGN_CENTER,\n\t},\n\n\t// MENUPAGE_SAVE_OVERWRITE_CONFIRM = 16\n\t{ \"FET_SG\", MENUPAGE_CHOOSE_SAVE_SLOT, 0,\n\t\tMENUACTION_LABEL,\t\t\"FESZ_QZ\", SAVESLOT_NONE, MENUPAGE_NONE, 0, 0, 0,\n\t\tMENUACTION_NO,\t\t\t\"FEM_NO\", SAVESLOT_NONE, MENUPAGE_CHOOSE_SAVE_SLOT, 320, 200, MENUALIGN_CENTER,\n\t\tMENUACTION_YES,\t\t\t\"FEM_YES\",  SAVESLOT_NONE, MENUPAGE_SAVING_IN_PROGRESS, 320, 225, MENUALIGN_CENTER,\n\t},\n\n\t// MENUPAGE_SAVING_IN_PROGRESS = 17\n\t{ \"FET_SG\", MENUPAGE_CHOOSE_SAVE_SLOT, 0,\n\t},\n\n\t// MENUPAGE_SAVE_SUCCESSFUL = 18\n\t{ \"FET_SG\", MENUPAGE_CHOOSE_SAVE_SLOT, 0,\n\t\tMENUACTION_LABEL,\t\t\t\t\t\"FES_SSC\",\tSAVESLOT_LABEL,\tMENUPAGE_NONE, 0, 0, 0,\n\t\tMENUACTION_RESUME_FROM_SAVEZONE,\t\"FEM_OK\",\tSAVESLOT_NONE,\tMENUPAGE_CHOOSE_SAVE_SLOT, 320, 225, MENUALIGN_CENTER,\n\t},\n\n\t// MENUPAGE_SAVE_CUSTOM_WARNING = 19\n\t{ \"FET_SG\", MENUPAGE_NONE, 0,\n\t\tMENUACTION_LABEL,\t\t\"\",\t\t\tSAVESLOT_NONE, 0, 0, 0, 0,\n\t\tMENUACTION_CHANGEMENU,\t\"FEM_OK\",\tSAVESLOT_NONE, MENUPAGE_CHOOSE_SAVE_SLOT, 320, 225, MENUALIGN_CENTER,\n\t},\n\n\t// MENUPAGE_SAVE_CHEAT_WARNING = 20\n\t{ \"FET_SG\", MENUPAGE_NEW_GAME, 0,\n\t\tMENUACTION_LABEL,\t\t\"FES_CHE\",\tSAVESLOT_NONE,\tMENUPAGE_NONE, 0, 0, 0,\n\t\tMENUACTION_CHANGEMENU,\t\"FEM_OK\",\tSAVESLOT_NONE,\tMENUPAGE_CHOOSE_SAVE_SLOT, 320, 225, MENUALIGN_CENTER,\n\t},\n\n\t// MENUPAGE_SKIN_SELECT = 21\n\t{ \"FET_PS\", MENUPAGE_OPTIONS, 4,\n\t\t MENUACTION_GOBACK,\t\t\"FEDS_TB\",\tSAVESLOT_NONE, MENUPAGE_OPTIONS, 0, 0, 0,\n\t},\n\n\t// MENUPAGE_SAVE_UNUSED = 22\n\t{ \"FET_SG\", MENUPAGE_NEW_GAME, 0,\n\t\t MENUACTION_LABEL,\t\t\"FED_LWR\",\tSAVESLOT_NONE,\t0, 0, 0, 0,\n\t\t MENUACTION_CHANGEMENU,\t\"FEC_OKK\",\tSAVESLOT_NONE,\tMENUPAGE_CHOOSE_SAVE_SLOT, 0, 0, 0,\n\t},\n\n\t// MENUPAGE_SAVE_FAILED = 23\n\t{ \"FET_SG\", MENUPAGE_CHOOSE_SAVE_SLOT, 0,\n\t\t MENUACTION_LABEL,\t\t\"FEC_SVU\",\tSAVESLOT_NONE,\t0, 0, 0, 0,\n\t\t MENUACTION_CHANGEMENU,\t\"FEC_OKK\",\tSAVESLOT_NONE,\tMENUPAGE_CHOOSE_SAVE_SLOT, 0, 0, 0,\n\t},\n\n\t// MENUPAGE_SAVE_FAILED_2 = 24\n\t{ \"FET_LG\", MENUPAGE_CHOOSE_SAVE_SLOT, 0,\n\t\t MENUACTION_LABEL,\t\t\"FEC_SVU\",\tSAVESLOT_NONE,\t0, 0, 0, 0,\n\t},\n\n\t// MENUPAGE_LOAD_FAILED = 25\n\t{ \"FET_LG\", MENUPAGE_NEW_GAME, 0,\n\t\t MENUACTION_LABEL,\t\t\"FEC_LUN\",\tSAVESLOT_NONE,  0, 0, 0, 0,\n\t\t MENUACTION_GOBACK,\t\t\"FEDS_TB\",\tSAVESLOT_NONE,  MENUPAGE_NEW_GAME, 0, 0, 0,\n\t},\n\n\t// MENUPAGE_CONTROLLER_PC = 26\n\t{ \"FET_CTL\", MENUPAGE_OPTIONS, 0,\n#ifdef PC_PLAYER_CONTROLS\n\t\tMENUACTION_CTRLMETHOD,\t\"FET_STI\", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC, 320, 150, MENUALIGN_CENTER,\n\t\tMENUACTION_KEYBOARDCTRLS,\"FEC_RED\", SAVESLOT_NONE, MENUPAGE_KEYBOARD_CONTROLS, 0, 0, MENUALIGN_CENTER,\n#else\n\t\tMENUACTION_KEYBOARDCTRLS,\"FEC_RED\", SAVESLOT_NONE, MENUPAGE_KEYBOARD_CONTROLS, 320, 150, MENUALIGN_CENTER,\n#endif\n\t\tMENUACTION_CHANGEMENU,\t\"FEC_MOU\", SAVESLOT_NONE, MENUPAGE_MOUSE_CONTROLS, 0, 0, MENUALIGN_CENTER,\n\t\tMENUACTION_RESTOREDEF,\t\"FET_DEF\", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC, 0, 0, MENUALIGN_CENTER,\n\t\tMENUACTION_GOBACK,\t\t\"FEDS_TB\", SAVESLOT_NONE, 0, 0, 0, MENUALIGN_CENTER,\n\t},\n\n\t// MENUPAGE_OPTIONS = 27\n\t{ \"FET_OPT\", MENUPAGE_NONE, 5,\n\t\t MENUACTION_CHANGEMENU,\t\t\"FEO_CON\", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC, 320, 132, MENUALIGN_CENTER,\n\t\t MENUACTION_LOADRADIO,\t\t\"FEO_AUD\", SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS, 0, 0, MENUALIGN_CENTER,\n\t\t MENUACTION_CHANGEMENU,\t\t\"FEO_DIS\", SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS, 0, 0, MENUALIGN_CENTER,\n\t\t MENUACTION_CHANGEMENU,\t\t\"FEO_LAN\", SAVESLOT_NONE, MENUPAGE_LANGUAGE_SETTINGS, 0, 0, MENUALIGN_CENTER,\n\t\t MENUACTION_PLAYERSETUP,\t\"FET_PS\", SAVESLOT_NONE, MENUPAGE_SKIN_SELECT, 0, 0, MENUALIGN_CENTER,\n\t\t MENUACTION_GOBACK,\t\t\t\"FEDS_TB\", SAVESLOT_NONE, 0, 0, 0, MENUALIGN_CENTER,\n\t},\n\n\t// MENUPAGE_EXIT = 28\n\t{ \"FET_QG\", MENUPAGE_NONE, 6,\n\t\tMENUACTION_LABEL,\t\t\"FEQ_SRE\",\tSAVESLOT_NONE, 0, 0, 0, 0,\n\t\tMENUACTION_DONTCANCEL,\t\"FEM_NO\",\tSAVESLOT_NONE, MENUPAGE_NONE, 320, 200, MENUALIGN_CENTER,\n\t\tMENUACTION_CANCELGAME,\t\"FEM_YES\",\tSAVESLOT_NONE, MENUPAGE_NONE, 320, 225, MENUALIGN_CENTER,\n\t},\n\n\t// MENUPAGE_START_MENU = 29\n\t{ \"FEM_MM\", MENUPAGE_DISABLED, 0,\n\t\t  MENUACTION_CHANGEMENU,\t\"FEP_STG\",\tSAVESLOT_NONE,\tMENUPAGE_NEW_GAME, 320, 170, MENUALIGN_CENTER,\n\t\t  MENUACTION_CHANGEMENU,\t\"FEP_OPT\",\tSAVESLOT_NONE,\tMENUPAGE_OPTIONS, 0, 0, MENUALIGN_CENTER,\n\t\t  MENUACTION_CHANGEMENU,\t\"FEP_QUI\",\tSAVESLOT_NONE,\tMENUPAGE_EXIT, 0, 0, MENUALIGN_CENTER,\n\t},\n\t\n\t// MENUPAGE_KEYBOARD_CONTROLS = 30\n\t{ \"FET_STI\", MENUPAGE_CONTROLLER_PC, 1,\n\t},\n\n\t// MENUPAGE_MOUSE_CONTROLS = 31\n\t{ \"FEC_MOU\", MENUPAGE_CONTROLLER_PC, 2,\n\t\tMENUACTION_MOUSESENS,\t\"FEC_MSH\",\tSAVESLOT_NONE, MENUPAGE_MOUSE_CONTROLS, 40, 170, MENUALIGN_LEFT,\n\t\tMENUACTION_INVVERT,\t\t\"FEC_IVV\",\tSAVESLOT_NONE, MENUPAGE_MOUSE_CONTROLS, 0, 0, MENUALIGN_LEFT,\n\t\tMENUACTION_MOUSESTEER,\t\"FET_MST\",\tSAVESLOT_NONE, MENUPAGE_MOUSE_CONTROLS, 0, 0, MENUALIGN_LEFT,\n\t\tMENUACTION_GOBACK,\t\t\"FEDS_TB\",\tSAVESLOT_NONE, 0, 320, 260, MENUALIGN_CENTER,\n\t},\n\n\t// MENUPAGE_PAUSE_MENU = 32\n\t{ \"FET_PAU\", MENUPAGE_DISABLED, 0,\n\t\tMENUACTION_RESUME,\t\t\"FEP_RES\",\tSAVESLOT_NONE, 0, 320, 120, MENUALIGN_CENTER,\n\t\tMENUACTION_CHANGEMENU,\t\"FEH_SGA\",\tSAVESLOT_NONE, MENUPAGE_NEW_GAME, 0, 0, MENUALIGN_CENTER,\n\t\tMENUACTION_CHANGEMENU,\t\"FEH_MAP\",\tSAVESLOT_NONE, MENUPAGE_MAP, 0, 0, MENUALIGN_CENTER,\n\t\tMENUACTION_CHANGEMENU,\t\"FEP_STA\",\tSAVESLOT_NONE, MENUPAGE_STATS, 0, 0, MENUALIGN_CENTER,\n\t\tMENUACTION_CHANGEMENU,\t\"FEH_BRI\",\tSAVESLOT_NONE, MENUPAGE_BRIEFS, 0, 0, MENUALIGN_CENTER,\n\t\tMENUACTION_CHANGEMENU,\t\"FET_OPT\",\tSAVESLOT_NONE, MENUPAGE_OPTIONS, 0, 0, MENUALIGN_CENTER,\n\t\tMENUACTION_CHANGEMENU,\t\"FEP_QUI\",\tSAVESLOT_NONE, MENUPAGE_EXIT, 0, 0, MENUALIGN_CENTER,\n\t},\n\n\t// MENUPAGE_NONE = 33\n\t{ \"\", 0, 0, },\n\n#ifdef LEGACY_MENU_OPTIONS\n\t// MENUPAGE_DEBUG_MENU\n\t{ \"FED_DBG\", MENUPAGE_NONE, 0,\n\t\tMENUACTION_RELOADIDE,\t\"FED_RID\", SAVESLOT_NONE, MENUPAGE_NONE, 0, 0, 0,\n\t\tMENUACTION_SETDBGFLAG,\t\"FED_DFL\", SAVESLOT_NONE, MENUPAGE_NONE, 0, 0, 0,\n\t\tMENUACTION_SWITCHBIGWHITEDEBUGLIGHT,\t\"FED_DLS\", SAVESLOT_NONE, MENUPAGE_NONE, 0, 0, 0,\n\t\tMENUACTION_COLLISIONPOLYS,\t\"FED_SCP\", SAVESLOT_NONE, MENUPAGE_NONE, 0, 0, 0,\n\t\tMENUACTION_GOBACK,\t\t\"FEDS_TB\", SAVESLOT_NONE, MENUPAGE_NONE, 0, 0, 0,\n\t},\n\t\n\t// MENUPAGE_CONTROLLER_PC_OLD1\n\t{ \"FET_CTL\", MENUPAGE_CONTROLLER_PC, 0,\n\t\tMENUACTION_GETKEY,\t\"FEC_PLB\", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1, 0, 0, 0,\n\t\tMENUACTION_GETKEY,\t\"FEC_CWL\", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1, 0, 0, 0,\n\t\tMENUACTION_GETKEY,\t\"FEC_CWR\", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1, 0, 0, 0,\n\t\tMENUACTION_GETKEY,\t\"FEC_LKT\", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1, 0, 0, 0,\n\t\tMENUACTION_GETKEY,\t\"FEC_PJP\", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1, 0, 0, 0,\n\t\tMENUACTION_GETKEY,\t\"FEC_PSP\", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1, 0, 0, 0,\n\t\tMENUACTION_GETKEY,\t\"FEC_TLF\", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1, 0, 0, 0,\n\t\tMENUACTION_GETKEY,\t\"FEC_TRG\", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1, 0, 0, 0,\n\t\tMENUACTION_GETKEY,\t\"FEC_CCM\", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1, 0, 0, 0,\n\t\tMENUACTION_GOBACK,\t\t\"FEDS_TB\", SAVESLOT_NONE, MENUPAGE_NONE, 0, 0, 0,\n\t},\n\n\t// MENUPAGE_CONTROLLER_PC_OLD2\n\t{ \"FET_CTL\", MENUPAGE_CONTROLLER_PC, 1,\n\n\t},\n\n\t// MENUPAGE_CONTROLLER_PC_OLD3\n\t{ \"FET_CTL\", MENUPAGE_CONTROLLER_PC, 2,\n\t\t MENUACTION_GETKEY,\t\"FEC_LUP\", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD3, 0, 0, 0,\n\t\t MENUACTION_GETKEY,\t\"FEC_LDN\", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD3, 0, 0, 0,\n\t\t MENUACTION_GETKEY,\t\"FEC_SMS\", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD3, 0, 0, 0,\n\t\t MENUACTION_SHOWHEADBOB,\t\"FEC_GSL\", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD3, 0, 0, 0,\n\t\t MENUACTION_GOBACK,\t\t\"FEDS_TB\", SAVESLOT_NONE, MENUPAGE_NONE, 0, 0, 0,\n\t},\n\n\t// MENUPAGE_CONTROLLER_PC_OLD4\n\t{ \"FET_CTL\", MENUPAGE_CONTROLLER_PC, 3,\n\n\t},\n\n\t// MENUPAGE_CONTROLLER_DEBUG\n\t{ \"FEC_DBG\", MENUPAGE_CONTROLLER_PC, 3,\n\t\t MENUACTION_GETKEY,\t\"FEC_TGD\",\tSAVESLOT_NONE, MENUPAGE_CONTROLLER_DEBUG, 0, 0, 0,\n\t\t MENUACTION_GETKEY,\t\"FEC_TDO\",\tSAVESLOT_NONE, MENUPAGE_CONTROLLER_DEBUG, 0, 0, 0,\n\t\t MENUACTION_GETKEY,\t\"FEC_TSS\",\tSAVESLOT_NONE, MENUPAGE_CONTROLLER_DEBUG, 0, 0, 0,\n\t\t MENUACTION_GETKEY,\t\"FEC_SMS\",\tSAVESLOT_NONE, MENUPAGE_CONTROLLER_DEBUG, 0, 0, 0,\n\t\t MENUACTION_GOBACK,\t\"FEDS_TB\",\tSAVESLOT_NONE, MENUPAGE_NONE, 0, 0, 0,\n\t},\n#endif\n\n\t// MENUPAGE_OUTRO - Originally 34\n\t{ \"\", 0, 0, },\n};\n\n#endif\n#endif\n"
  },
  {
    "path": "src/core/MenuScreensCustom.cpp",
    "content": "#include \"common.h\"\n#if defined DETECT_JOYSTICK_MENU && defined XINPUT\n#include <windows.h>\n#include <xinput.h>\n#if !defined(PSAPI_VERSION) || (PSAPI_VERSION > 1)\n#pragma comment( lib, \"Xinput9_1_0.lib\" )\n#else\n#pragma comment( lib, \"Xinput.lib\" )\n#endif\n#endif\n#include \"platform.h\"\n#include \"crossplatform.h\"\n#include \"Renderer.h\"\n#include \"Frontend.h\"\n#include \"Font.h\"\n#include \"Camera.h\"\n#include \"main.h\"\n#include \"MBlur.h\"\n#include \"postfx.h\"\n#include \"custompipes.h\"\n#include \"RwHelper.h\"\n#include \"Text.h\"\n#include \"Streaming.h\"\n#include \"FileLoader.h\"\n#include \"Collision.h\"\n#include \"ModelInfo.h\"\n#include \"Pad.h\"\n#include \"ControllerConfig.h\"\n\n// Menu screens array is at the bottom of the file.\n\n#ifdef PC_MENU\n\n#ifdef CUSTOM_FRONTEND_OPTIONS\n\n#ifdef IMPROVED_VIDEOMODE\n\t#define VIDEOMODE_SELECTOR MENUACTION_CFO_SELECT, \"FEM_SCF\", { new CCFOSelect((int8*)&FrontEndMenuManager.m_nPrefsWindowed, \"VideoMode\", \"Windowed\", screenModes, 2, true, ScreenModeAfterChange, true) }, 0, 0, MENUALIGN_LEFT,\n#else\n\t#define VIDEOMODE_SELECTOR\n#endif\n\n#ifdef MULTISAMPLING\n\t#define MULTISAMPLING_SELECTOR MENUACTION_CFO_DYNAMIC, \"FED_AAS\", { new CCFODynamic((int8*)&FrontEndMenuManager.m_nPrefsMSAALevel, \"Graphics\", \"MultiSampling\", MultiSamplingDraw, MultiSamplingButtonPress) }, 0, 0, MENUALIGN_LEFT,\n#else\n\t#define MULTISAMPLING_SELECTOR\n#endif\n\n#ifdef CUTSCENE_BORDERS_SWITCH\n\t#define CUTSCENE_BORDERS_TOGGLE MENUACTION_CFO_SELECT, \"FEM_CSB\", { new CCFOSelect((int8 *)&FrontEndMenuManager.m_PrefsCutsceneBorders, \"Display\", \"CutsceneBorders\", off_on, 2, false) }, 0, 0, MENUALIGN_LEFT,\n#else\n\t#define CUTSCENE_BORDERS_TOGGLE\n#endif\n\n#ifdef FREE_CAM\n\t#define FREE_CAM_TOGGLE MENUACTION_CFO_SELECT, \"FEC_FRC\", { new CCFOSelect((int8*)&TheCamera.bFreeCam, \"Display\", \"FreeCam\", off_on, 2, false) }, 0, 0, MENUALIGN_LEFT,\n#else\n\t#define FREE_CAM_TOGGLE\n#endif\n\n#ifdef PS2_ALPHA_TEST\n\t#define DUALPASS_SELECTOR MENUACTION_CFO_SELECT, \"FEM_2PR\", { new CCFOSelect((int8*)&gPS2alphaTest, \"Graphics\", \"PS2AlphaTest\", off_on, 2, false) }, 0, 0, MENUALIGN_LEFT,\n#else\n\t#define DUALPASS_SELECTOR \n#endif\n\n#ifdef NO_ISLAND_LOADING\n\t#define ISLAND_LOADING_SELECTOR MENUACTION_CFO_SELECT, \"FEM_ISL\", { new CCFOSelect((int8*)&FrontEndMenuManager.m_PrefsIslandLoading, \"Graphics\", \"IslandLoading\", islandLoadingOpts, ARRAY_SIZE(islandLoadingOpts), true, IslandLoadingAfterChange) }, 0, 0, MENUALIGN_LEFT,\n#else\n\t#define ISLAND_LOADING_SELECTOR \n#endif\n\n#ifdef EXTENDED_COLOURFILTER\n\t#define POSTFX_SELECTORS \\\n\t\tMENUACTION_CFO_SELECT, \"FED_CLF\", { new CCFOSelect((int8*)&CPostFX::EffectSwitch, \"Graphics\", \"ColourFilter\", filterNames, ARRAY_SIZE(filterNames), false) }, 0, 0, MENUALIGN_LEFT, \\\n\t\tMENUACTION_CFO_SELECT, \"FED_MBL\", { new CCFOSelect((int8*)&CPostFX::MotionBlurOn, \"Graphics\", \"MotionBlur\", off_on, 2, false) }, 0, 0, MENUALIGN_LEFT,\n#else\n\t#define POSTFX_SELECTORS\n#endif\t\n\n#ifdef INVERT_LOOK_FOR_PAD\n\t#define INVERT_PAD_SELECTOR MENUACTION_CFO_SELECT, \"FEC_ILU\", { new CCFOSelect((int8*)&CPad::bInvertLook4Pad, \"Controller\", \"InvertPad\", off_on, 2, false) }, 0, 0, MENUALIGN_LEFT,\n#else\n\t#define INVERT_PAD_SELECTOR\n#endif\n\n#ifdef GAMEPAD_MENU\n\t#define SELECT_CONTROLLER_TYPE  MENUACTION_CFO_SELECT, \"FEC_TYP\", { new CCFOSelect((int8*)&FrontEndMenuManager.m_PrefsControllerType, \"Controller\", \"Type\", controllerTypes, ARRAY_SIZE(controllerTypes), false, ControllerTypeAfterChange) }, 0, 0, MENUALIGN_LEFT,\n#else\n\t#define SELECT_CONTROLLER_TYPE\n#endif\n\nconst char *filterNames[] = { \"FEM_NON\", \"FEM_SIM\", \"FEM_NRM\", \"FEM_MOB\" };\nconst char *off_on[] = { \"FEM_OFF\", \"FEM_ON\" };\n\nvoid RestoreDefGraphics(int8 action) {\n\tif (action != FEOPTION_ACTION_SELECT)\n\t\treturn;\n\n\t#ifdef PS2_ALPHA_TEST\n\t\tgPS2alphaTest = false;\n\t#endif\n\t#ifdef MULTISAMPLING\n\t\tFrontEndMenuManager.m_nPrefsMSAALevel = FrontEndMenuManager.m_nDisplayMSAALevel = 0;\n\t#endif\n\t#ifdef NO_ISLAND_LOADING\n\t    \tif (!FrontEndMenuManager.m_bGameNotLoaded) {\n\t    \t\tFrontEndMenuManager.m_PrefsIslandLoading = FrontEndMenuManager.ISLAND_LOADING_LOW;\n\t\t\t\tCStreaming::RemoveUnusedBigBuildings(CGame::currLevel);\n\t\t\t\tCStreaming::RemoveUnusedBuildings(CGame::currLevel);\n\t\t\t\tCStreaming::RequestIslands(CGame::currLevel);\n\t\t        CStreaming::LoadAllRequestedModels(true);\n\t    \t} else\n\t    \t\tFrontEndMenuManager.m_PrefsIslandLoading = FrontEndMenuManager.ISLAND_LOADING_LOW;\n\t#endif\n\t#ifdef GRAPHICS_MENU_OPTIONS // otherwise Frontend will handle those\n\t\tFrontEndMenuManager.m_PrefsFrameLimiter = true;\n\t\tFrontEndMenuManager.m_PrefsVsyncDisp = true;\n\t\t#ifdef LEGACY_MENU_OPTIONS\n\t\t\tFrontEndMenuManager.m_PrefsVsync = true;\n\t\t#endif\n\t\tFrontEndMenuManager.m_PrefsUseWideScreen = false;\n\t\tFrontEndMenuManager.m_nDisplayVideoMode = FrontEndMenuManager.m_nPrefsVideoMode;\n\t\tCMBlur::BlurOn = false;\n\t\tFrontEndMenuManager.SaveSettings();\n\t#endif\n}\n\nvoid RestoreDefDisplay(int8 action) {\n\tif (action != FEOPTION_ACTION_SELECT)\n\t\treturn;\n\n\t#ifdef CUTSCENE_BORDERS_SWITCH\n\t\tFrontEndMenuManager.m_PrefsCutsceneBorders = true;\n\t#endif\n\t#ifdef FREE_CAM\n\t\tTheCamera.bFreeCam = false;\n\t#endif\n\t#ifdef GRAPHICS_MENU_OPTIONS // otherwise Frontend will handle those\n\t\tFrontEndMenuManager.m_PrefsBrightness = 256;\n\t\tFrontEndMenuManager.m_PrefsLOD = 1.2f;\n\t\tCRenderer::ms_lodDistScale = 1.2f;\n\t\tFrontEndMenuManager.m_PrefsShowSubtitles = false;\n\t\tFrontEndMenuManager.m_PrefsShowLegends = true;\n\t\tFrontEndMenuManager.m_PrefsRadarMode = 0;\n\t\tFrontEndMenuManager.m_PrefsShowHud = true;\n\t\tFrontEndMenuManager.SaveSettings();\n\t#endif\n}\n\n#ifdef NO_ISLAND_LOADING\nconst char *islandLoadingOpts[] = { \"FEM_LOW\", \"FEM_MED\", \"FEM_HIG\" };\nvoid IslandLoadingAfterChange(int8 before, int8 after) {\n\tif (!FrontEndMenuManager.m_bGameNotLoaded) {\n\t\tif (after > FrontEndMenuManager.ISLAND_LOADING_LOW) {\n\t\t    FrontEndMenuManager.m_PrefsIslandLoading = before; // calls below needs previous mode :shrug:\n\t\t    \n\t\t    if (after == FrontEndMenuManager.ISLAND_LOADING_HIGH) {\n\t\t\t    CStreaming::RemoveIslandsNotUsed(LEVEL_BEACH);\n\t\t\t    CStreaming::RemoveIslandsNotUsed(LEVEL_MAINLAND);\n\t\t\t}\n\t\t    if (before == FrontEndMenuManager.ISLAND_LOADING_LOW) {\n\t\t\t    FrontEndMenuManager.m_PrefsIslandLoading = after;\n\t\t\t    CStreaming::RequestBigBuildings(CGame::currLevel);\n\t\t\t    \n\t\t    } else if (before == FrontEndMenuManager.ISLAND_LOADING_HIGH) {\n\t\t\t    FrontEndMenuManager.m_PrefsIslandLoading = after;\n\t\t\t    CStreaming::RequestIslands(CGame::currLevel);\n\t\t    } else\n\t\t    \t    FrontEndMenuManager.m_PrefsIslandLoading = after;\n\t\t    \t    \n\t\t} else { // low\n\t\t    CStreaming::RemoveUnusedBigBuildings(CGame::currLevel);\n\t\t    CStreaming::RemoveUnusedBuildings(CGame::currLevel);\n\t\t    CStreaming::RequestIslands(CGame::currLevel);\n\t\t}\n\n\t\tCStreaming::LoadAllRequestedModels(true);\n\t}\n\n\tFrontEndMenuManager.SetHelperText(0);\n}\n#endif\n\n#ifndef MULTISAMPLING\nvoid GraphicsGoBack() {\n}\n#else\nvoid GraphicsGoBack() {\n\tFrontEndMenuManager.m_nDisplayMSAALevel = FrontEndMenuManager.m_nPrefsMSAALevel;\n}\n\nvoid MultiSamplingButtonPress(int8 action) {\n\tif (action == FEOPTION_ACTION_SELECT) {\n\t\tif (FrontEndMenuManager.m_nDisplayMSAALevel != FrontEndMenuManager.m_nPrefsMSAALevel) {\n\t\t\tFrontEndMenuManager.m_nPrefsMSAALevel = FrontEndMenuManager.m_nDisplayMSAALevel;\n\t\t\t_psSelectScreenVM(FrontEndMenuManager.m_nPrefsVideoMode);\n\t\t\tFrontEndMenuManager.SetHelperText(0);\n\t\t\tFrontEndMenuManager.SaveSettings();\n\t\t}\n\t} else if (action == FEOPTION_ACTION_LEFT || action == FEOPTION_ACTION_RIGHT) {\n\t\tif (FrontEndMenuManager.m_bGameNotLoaded) {\n\t\t\tFrontEndMenuManager.m_nDisplayMSAALevel += (action == FEOPTION_ACTION_RIGHT ? 1 : -1);\n\n\t\t\tint i = 0;\n\t\t\tint maxAA = RwD3D8EngineGetMaxMultiSamplingLevels();\n\t\t\twhile (maxAA != 1) {\n\t\t\t\ti++;\n\t\t\t\tmaxAA >>= 1;\n\t\t\t}\n\n\t\t\tif (FrontEndMenuManager.m_nDisplayMSAALevel < 0)\n\t\t\t\tFrontEndMenuManager.m_nDisplayMSAALevel = i;\n\t\t\telse if (FrontEndMenuManager.m_nDisplayMSAALevel > i)\n\t\t\t\tFrontEndMenuManager.m_nDisplayMSAALevel = 0;\n\t\t}\n\t} else if (action == FEOPTION_ACTION_FOCUSLOSS) {\n\t\tif (FrontEndMenuManager.m_nDisplayMSAALevel != FrontEndMenuManager.m_nPrefsMSAALevel) {\n\t\t\tFrontEndMenuManager.m_nDisplayMSAALevel = FrontEndMenuManager.m_nPrefsMSAALevel;\n\t\t\tFrontEndMenuManager.SetHelperText(3);\n\t\t}\n\t}\n}\n\nwchar* MultiSamplingDraw(bool *disabled, bool userHovering) {\n\tstatic wchar unicodeTemp[64];\n\tif (userHovering) {\n\t\tif (FrontEndMenuManager.m_nDisplayMSAALevel == FrontEndMenuManager.m_nPrefsMSAALevel) {\n\t\t\tif (FrontEndMenuManager.m_nHelperTextMsgId == 1) // Press enter to apply\n\t\t\t\tFrontEndMenuManager.ResetHelperText();\n\t\t} else {\n\t\t\tFrontEndMenuManager.SetHelperText(1);\n\t\t}\n\t} else {\n\t\tif (FrontEndMenuManager.m_nDisplayMSAALevel != FrontEndMenuManager.m_nPrefsMSAALevel) {\n\t\t\tFrontEndMenuManager.m_nDisplayMSAALevel = FrontEndMenuManager.m_nPrefsMSAALevel;\n\t\t}\n\t}\n\n\tif (!FrontEndMenuManager.m_bGameNotLoaded)\n\t\t*disabled = true;\n\n\tswitch (FrontEndMenuManager.m_nDisplayMSAALevel) {\n\t\tcase 0:\n\t\t\treturn TheText.Get(\"FEM_OFF\");\n\t\tdefault:\n\t\t\tsprintf(gString, \"%iX\", 1 << (FrontEndMenuManager.m_nDisplayMSAALevel));\n\t\t\tAsciiToUnicode(gString, unicodeTemp);\n\t\t\treturn unicodeTemp;\n\t}\n}\n#endif\n\n#ifdef IMPROVED_VIDEOMODE\nconst char* screenModes[] = { \"FED_FLS\", \"FED_WND\" };\nvoid ScreenModeAfterChange(int8 before, int8 after)\n{\n\t_psSelectScreenVM(FrontEndMenuManager.m_nPrefsVideoMode); // apply same resolution\n\tFrontEndMenuManager.SetHelperText(0);\n}\n\n#endif\n\n#ifdef DETECT_JOYSTICK_MENU\nwchar selectedJoystickUnicode[128];\nint cachedButtonNum = -1;\n\nwchar* DetectJoystickDraw(bool* disabled, bool userHovering) {\n\n#if defined RW_GL3 && !defined LIBRW_SDL2\n\tint numButtons;\n\tint found = -1;\n\tconst char *joyname;\n\tif (userHovering) {\n\t\tfor (int i = 0; i <= GLFW_JOYSTICK_LAST; i++) {\n\t\t\tif ((joyname = glfwGetJoystickName(i))) {\n\t\t\t\tconst uint8* buttons = glfwGetJoystickButtons(i, &numButtons);\n\t\t\t\tfor (int j = 0; j < numButtons; j++) {\n\t\t\t\t\tif (buttons[j]) {\n\t\t\t\t\t\tfound = i;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (found != -1)\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif (found != -1 && PSGLOBAL(joy1id) != found) {\n\t\t\tif (PSGLOBAL(joy1id) != -1 && PSGLOBAL(joy1id) != found)\n\t\t\t\tPSGLOBAL(joy2id) = PSGLOBAL(joy1id);\n\t\t\telse\n\t\t\t\tPSGLOBAL(joy2id) = -1;\n\n\t\t\tstrcpy(gSelectedJoystickName, joyname);\n\t\t\tPSGLOBAL(joy1id) = found;\n\t\t\tcachedButtonNum = numButtons;\n\t\t}\n\t}\n\tif (PSGLOBAL(joy1id) == -1)\n#elif defined XINPUT\n\tint found = -1;\n\tXINPUT_STATE xstate;\n\tmemset(&xstate, 0, sizeof(XINPUT_STATE));\n\tif (userHovering) {\n\t\tfor (int i = 0; i <= 3; i++) {\n\t\t\tif (XInputGetState(i, &xstate) == ERROR_SUCCESS) {\n\t\t\t\tif (xstate.Gamepad.bLeftTrigger || xstate.Gamepad.bRightTrigger) {\n\t\t\t\t\tfound = i;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tfor (int j = XINPUT_GAMEPAD_DPAD_UP; j != XINPUT_GAMEPAD_Y << 1; j = (j << 1)) {\n\t\t\t\t\tif (xstate.Gamepad.wButtons & j) {\n\t\t\t\t\t\tfound = i;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (found != -1)\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (found != -1 && CPad::XInputJoy1 != found) {\n\t\t\t// We should never leave pads -1, so we can process them when they're connected and kinda support hotplug.\n\t\t\tCPad::XInputJoy2 = (CPad::XInputJoy1 == -1 ? (found + 1) % 4 : CPad::XInputJoy1);\n\t\t\tCPad::XInputJoy1 = found;\n\t\t\tcachedButtonNum = 0; // fake too, because xinput bypass CControllerConfig\n\t\t}\n\t}\n\tsprintf(gSelectedJoystickName, \"%d\", CPad::XInputJoy1); // fake, on xinput we only store gamepad ids(thanks MS) so this is a temp variable to be used below\n\tif (CPad::XInputJoy1 == -1)\n#endif\n\t\tAsciiToUnicode(\"Not found\", selectedJoystickUnicode);\n\telse\n\t\tAsciiToUnicode(gSelectedJoystickName, selectedJoystickUnicode);\n\n\treturn selectedJoystickUnicode;\n}\n\nvoid DetectJoystickGoBack() {\n\tif (cachedButtonNum != -1) {\n#ifdef LOAD_INI_SETTINGS\n\t\tControlsManager.InitDefaultControlConfigJoyPad(cachedButtonNum);\n\t\tSaveINIControllerSettings();\n#else\n\t\t// Otherwise no way to save gSelectedJoystickName or ms_padButtonsInited anyway :shrug: Why do you even use this config.??\n#endif\n\t\tcachedButtonNum = -1;\n\t}\n}\n#endif\n\n#ifdef GAMEPAD_MENU\nconst char* controllerTypes[] = { \"FEC_DS2\", \"FEC_DS3\", \"FEC_DS4\", \"FEC_360\", \"FEC_ONE\" };\nvoid ControllerTypeAfterChange(int8 before, int8 after)\n{\n\tFrontEndMenuManager.LoadController(after);\n}\n#endif\n\nCMenuScreenCustom aScreens[] = {\n\t// MENUPAGE_STATS = 0\n\t{ \"FEH_STA\", MENUPAGE_NONE, nil, nil,\n\t\tMENUACTION_GOBACK, \"FEDS_TB\", {nil, SAVESLOT_NONE, MENUPAGE_NONE}, 190, 320, MENUALIGN_RIGHT,\n\t},\n\n\t// MENUPAGE_NEW_GAME = 1\n\t{ \"FEP_STG\", MENUPAGE_NONE, nil, nil,\n\t\tMENUACTION_CHANGEMENU, \"FES_NGA\", {nil, SAVESLOT_NONE, MENUPAGE_NEW_GAME_RELOAD}, 320, 155, MENUALIGN_CENTER,\n\t\tMENUACTION_CHANGEMENU, \"FES_LOA\",  {nil, SAVESLOT_NONE, MENUPAGE_CHOOSE_LOAD_SLOT}, 0, 0, MENUALIGN_CENTER,\n\t\tMENUACTION_CHANGEMENU, \"FES_DEL\", {nil, SAVESLOT_NONE, MENUPAGE_CHOOSE_DELETE_SLOT}, 0, 0, MENUALIGN_CENTER,\n\t\tMENUACTION_GOBACK, \"FEDS_TB\", {nil, SAVESLOT_NONE, 0}, 0, 0, MENUALIGN_CENTER,\n\t},\n\n\t// MENUPAGE_BRIEFS = 2\n\t{ \"FEH_BRI\", MENUPAGE_NONE, nil, nil,\n\t\tMENUACTION_GOBACK, \"FEDS_TB\", {nil, SAVESLOT_NONE, MENUPAGE_NONE}, 190, 320, MENUALIGN_RIGHT,\n\t},\n\n\t// MENUPAGE_SOUND_SETTINGS = 3\n\t{ \"FEH_AUD\", MENUPAGE_OPTIONS, nil, nil,\n\t\tMENUACTION_MUSICVOLUME,\t\t\"FEA_MUS\", {nil, SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS}, 40, 76, MENUALIGN_LEFT,\n\t\tMENUACTION_SFXVOLUME,\t\t\"FEA_SFX\", {nil, SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS}, 0, 0, MENUALIGN_LEFT,\n\t\tMENUACTION_MP3VOLUMEBOOST,\t\"FEA_MPB\", {nil, SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS}, 0, 0, MENUALIGN_LEFT,\n\t\tMENUACTION_AUDIOHW,\t\t\t\"FEA_3DH\", {nil, SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS}, 0, 0, MENUALIGN_LEFT,\n\t\tMENUACTION_SPEAKERCONF,\t\t\"FEA_SPK\", {nil, SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS}, 0, 0, MENUALIGN_LEFT,\n\t\tMENUACTION_DYNAMICACOUSTIC,\t\"FET_DAM\", {nil, SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS}, 0, 0, MENUALIGN_LEFT,\n\t\tMENUACTION_RADIO,\t\t\t\"FEA_RSS\", {nil, SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS}, 0, 0, MENUALIGN_LEFT,\n\t\tMENUACTION_RESTOREDEF,\t\t\"FET_DEF\", {nil, SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS}, 320, 367, MENUALIGN_CENTER,\n\t\tMENUACTION_GOBACK,\t\t\t\"FEDS_TB\", {nil, SAVESLOT_NONE, MENUPAGE_NONE}, 0, 0, MENUALIGN_CENTER,\n\t},\n\n\t// MENUPAGE_DISPLAY_SETTINGS = 4\n#ifndef GRAPHICS_MENU_OPTIONS\n\t{ \"FEH_DIS\", MENUPAGE_OPTIONS, new CCustomScreenLayout({40, 78, 25, true}), nil,\n\t\tMENUACTION_BRIGHTNESS,\t\"FED_BRI\", {nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS}, 0, 0, MENUALIGN_LEFT,\n\t\tMENUACTION_DRAWDIST,\t\"FEM_LOD\", {nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS}, 0, 0, MENUALIGN_LEFT,\n#ifdef LEGACY_MENU_OPTIONS\n\t\tMENUACTION_FRAMESYNC,\t\"FEM_VSC\", {nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS}, 0, 0, MENUALIGN_LEFT,\n#endif\n\t\tMENUACTION_FRAMELIMIT,\t\"FEM_FRM\", {nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS}, 0, 0, MENUALIGN_LEFT,\n#if defined LEGACY_MENU_OPTIONS && !defined EXTENDED_COLOURFILTER\n\t\tMENUACTION_TRAILS,\t\t\"FED_TRA\", {nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS}, 0, 0, MENUALIGN_LEFT,\n#endif\n\t\tMENUACTION_SUBTITLES,\t\"FED_SUB\", {nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS}, 0, 0, MENUALIGN_LEFT,\n\t\tMENUACTION_WIDESCREEN,\t\"FED_WIS\", {nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS}, 0, 0, MENUALIGN_LEFT,\n\t\tMENUACTION_LEGENDS,\t\t\"MAP_LEG\", {nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS}, 0, 0, MENUALIGN_LEFT,\n\t\tMENUACTION_RADARMODE,\t\"FED_RDR\", {nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS}, 0, 0, MENUALIGN_LEFT,\n\t\tMENUACTION_HUD,\t\t\t\"FED_HUD\", {nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS}, 0, 0, MENUALIGN_LEFT,\n\t\tMENUACTION_SCREENRES,\t\"FED_RES\", {nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS}, 0, 0, MENUALIGN_LEFT,\n\t\tVIDEOMODE_SELECTOR\n\t\tMULTISAMPLING_SELECTOR\n\t\tISLAND_LOADING_SELECTOR\n\t\tDUALPASS_SELECTOR\n\t\tCUTSCENE_BORDERS_TOGGLE\n\t\tFREE_CAM_TOGGLE\n\t\tPOSTFX_SELECTORS\n\t\t// re3.cpp inserts here pipeline selectors if neo/neo.txd exists and EXTENDED_PIPELINES defined\n\t\tMENUACTION_RESTOREDEF,\t\"FET_DEF\", {nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS}, 320, 0, MENUALIGN_CENTER,\n\t\tMENUACTION_GOBACK,\t\t\"FEDS_TB\", {nil, SAVESLOT_NONE, MENUPAGE_NONE}, 320, 0, MENUALIGN_CENTER,\n\t},\n#else\n\t{ \"FEH_DIS\", MENUPAGE_OPTIONS, new CCustomScreenLayout({40, 78, 25, true}), nil,\n\t\tMENUACTION_BRIGHTNESS,\t\"FED_BRI\", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS }, 0, 0, MENUALIGN_LEFT,\n\t\tMENUACTION_DRAWDIST,\t\"FEM_LOD\", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS }, 0, 0, MENUALIGN_LEFT,\n\t\tCUTSCENE_BORDERS_TOGGLE\n\t\tFREE_CAM_TOGGLE\n\t\tMENUACTION_LEGENDS,\t\t\"MAP_LEG\", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS }, 0, 0, MENUALIGN_LEFT,\n\t\tMENUACTION_RADARMODE,\t\"FED_RDR\", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS }, 0, 0, MENUALIGN_LEFT,\n\t\tMENUACTION_HUD,\t\t\t\"FED_HUD\", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS }, 0, 0, MENUALIGN_LEFT,\n\t\tMENUACTION_SUBTITLES,\t\"FED_SUB\", { nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS }, 0, 0, MENUALIGN_LEFT,\n\t\tMENUACTION_CFO_DYNAMIC,\t\"FET_DEF\", { new CCFODynamic(nil, nil, nil, nil, RestoreDefDisplay) }, 320, 0, MENUALIGN_CENTER,\n\t\tMENUACTION_GOBACK,\t\t\"FEDS_TB\", { nil, SAVESLOT_NONE, MENUPAGE_NONE}, 320, 0, MENUALIGN_CENTER,\n\t},\n#endif\n\n\t// MENUPAGE_LANGUAGE_SETTINGS = 5\n\t{ \"FEH_LAN\", MENUPAGE_OPTIONS, nil, nil,\n\t\tMENUACTION_LANG_ENG,\t\"FEL_ENG\", {nil, SAVESLOT_NONE, MENUPAGE_LANGUAGE_SETTINGS}, 320, 132, MENUALIGN_CENTER,\n\t\tMENUACTION_LANG_FRE,\t\"FEL_FRE\", {nil, SAVESLOT_NONE, MENUPAGE_LANGUAGE_SETTINGS}, 0, 0, MENUALIGN_CENTER,\n\t\tMENUACTION_LANG_GER,\t\"FEL_GER\", {nil, SAVESLOT_NONE, MENUPAGE_LANGUAGE_SETTINGS}, 0, 0, MENUALIGN_CENTER,\n\t\tMENUACTION_LANG_ITA,\t\"FEL_ITA\", {nil, SAVESLOT_NONE, MENUPAGE_LANGUAGE_SETTINGS}, 0, 0, MENUALIGN_CENTER,\n\t\tMENUACTION_LANG_SPA,    \"FEL_SPA\", {nil, SAVESLOT_NONE, MENUPAGE_LANGUAGE_SETTINGS}, 0, 0, MENUALIGN_CENTER,\n\t\tMENUACTION_GOBACK,\t\t\"FEDS_TB\", {nil, SAVESLOT_NONE, MENUPAGE_NONE}, 0, 0, MENUALIGN_CENTER,\n\t},\n\n\t// MENUPAGE_MAP = 6\n\t{ \"FEH_MAP\", MENUPAGE_NONE, nil, nil,\n\t\t MENUACTION_GOBACK,\t\"FEDS_TB\", {nil, SAVESLOT_NONE, MENUPAGE_NONE}, 70, 380, MENUALIGN_CENTER,\n\t},\n\n\t// MENUPAGE_NEW_GAME_RELOAD = 7\n\t{ \"FES_NGA\", MENUPAGE_NEW_GAME, nil, nil,\n\t\tMENUACTION_LABEL,\t\t\"FESZ_QR\",\t{nil, SAVESLOT_NONE,\t0}, 0, 0, 0,\n\t\tMENUACTION_NO,\t\t\t\"FEM_NO\",\t{nil, SAVESLOT_NONE,\tMENUPAGE_NEW_GAME}, 320, 200, MENUALIGN_CENTER,\n\t\tMENUACTION_NEWGAME,\t\t\"FEM_YES\",\t{nil, SAVESLOT_NONE,\tMENUPAGE_NEW_GAME_RELOAD}, 320, 225, MENUALIGN_CENTER,\n\t},\n\n\t// MENUPAGE_CHOOSE_LOAD_SLOT = 8\n\t{ \"FET_LG\", MENUPAGE_NEW_GAME, nil, nil,\n\t\tMENUACTION_CHECKSAVE,\t\"FEM_SL1\", {nil, SAVESLOT_1,\t\t0}, 40, 90, MENUALIGN_LEFT,\n\t\tMENUACTION_CHECKSAVE,\t\"FEM_SL2\", {nil, SAVESLOT_2,\t\t0}, 0, 0, MENUALIGN_LEFT,\n\t\tMENUACTION_CHECKSAVE,\t\"FEM_SL3\", {nil, SAVESLOT_3,\t\t0}, 0, 0, MENUALIGN_LEFT,\n\t\tMENUACTION_CHECKSAVE,\t\"FEM_SL4\", {nil, SAVESLOT_4,\t\t0}, 0, 0, MENUALIGN_LEFT,\n\t\tMENUACTION_CHECKSAVE,\t\"FEM_SL5\", {nil, SAVESLOT_5,\t\t0}, 0, 0, MENUALIGN_LEFT,\n\t\tMENUACTION_CHECKSAVE,\t\"FEM_SL6\", {nil, SAVESLOT_6,\t\t0}, 0, 0, MENUALIGN_LEFT,\n\t\tMENUACTION_CHECKSAVE,\t\"FEM_SL7\", {nil, SAVESLOT_7,\t\t0}, 0, 0, MENUALIGN_LEFT,\n\t\tMENUACTION_CHECKSAVE,\t\"FEM_SL8\", {nil, SAVESLOT_8,\t\t0}, 0, 0, MENUALIGN_LEFT,\n\t\tMENUACTION_GOBACK,\t\t\"FEDS_TB\", {nil, SAVESLOT_NONE,\t0}, 320, 345, MENUALIGN_CENTER,\n\t},\n\n\t// MENUPAGE_CHOOSE_DELETE_SLOT = 9\n\t{ \"FES_DEL\", MENUPAGE_NEW_GAME, nil, nil,\n\t\tMENUACTION_CHECKSAVE,\t\"FEM_SL1\",\t{nil, SAVESLOT_1,\t\t0}, 40, 90, MENUALIGN_LEFT,\n\t\tMENUACTION_CHECKSAVE,\t\"FEM_SL2\",\t{nil, SAVESLOT_2,\t\t0}, 0, 0, MENUALIGN_LEFT,\n\t\tMENUACTION_CHECKSAVE,\t\"FEM_SL3\",\t{nil, SAVESLOT_3,\t\t0}, 0, 0, MENUALIGN_LEFT,\n\t\tMENUACTION_CHECKSAVE,\t\"FEM_SL4\",\t{nil, SAVESLOT_4,\t\t0}, 0, 0, MENUALIGN_LEFT,\n\t\tMENUACTION_CHECKSAVE,\t\"FEM_SL5\",\t{nil, SAVESLOT_5,\t\t0}, 0, 0, MENUALIGN_LEFT,\n\t\tMENUACTION_CHECKSAVE,\t\"FEM_SL6\",\t{nil, SAVESLOT_6,\t\t0}, 0, 0, MENUALIGN_LEFT,\n\t\tMENUACTION_CHECKSAVE,\t\"FEM_SL7\",\t{nil, SAVESLOT_7,\t\t0}, 0, 0, MENUALIGN_LEFT,\n\t\tMENUACTION_CHECKSAVE,\t\"FEM_SL8\",\t{nil, SAVESLOT_8,\t\t0}, 0, 0, MENUALIGN_LEFT,\n\t\tMENUACTION_GOBACK,\t\t\"FEDS_TB\",\t{nil, SAVESLOT_NONE,\t0}, 320, 345, MENUALIGN_CENTER,\n\t},\n\n\t// MENUPAGE_LOAD_SLOT_CONFIRM = 10\n\t{ \"FET_LG\", MENUPAGE_CHOOSE_LOAD_SLOT, nil, nil,\n\t\t MENUACTION_LABEL,\t\t\"FESZ_QL\",\t{nil, SAVESLOT_NONE,\t0}, 0, 0, 0,\n\t\t MENUACTION_NO,\t\t\t\"FEM_NO\",\t{nil, SAVESLOT_NONE,\tMENUPAGE_CHOOSE_LOAD_SLOT}, 320, 200, MENUALIGN_CENTER,\n\t\t MENUACTION_YES,\t\t\"FEM_YES\",\t{nil, SAVESLOT_NONE,\tMENUPAGE_LOADING_IN_PROGRESS}, 320, 225, MENUALIGN_CENTER,\n\t},\n\n\t// MENUPAGE_DELETE_SLOT_CONFIRM = 11\n\t{ \"FES_DEL\", MENUPAGE_CHOOSE_DELETE_SLOT, nil, nil,\n\t\t MENUACTION_LABEL,\t\t\"FESZ_QD\",\t{nil, SAVESLOT_NONE,  MENUPAGE_NONE}, 0, 0, 0,\n\t\t MENUACTION_NO,\t\t\t\"FEM_NO\",\t{nil, SAVESLOT_NONE,  MENUPAGE_CHOOSE_DELETE_SLOT}, 320, 200, MENUALIGN_CENTER,\n\t\t MENUACTION_YES,\t\t\"FEM_YES\",\t{nil, SAVESLOT_NONE,\tMENUPAGE_DELETING_IN_PROGRESS}, 320, 225, MENUALIGN_CENTER,\n\t},\n\n\t// MENUPAGE_LOADING_IN_PROGRESS = 12\n\t{ \"FET_LG\", MENUPAGE_CHOOSE_LOAD_SLOT, nil, nil,\n\t},\n\n\t// MENUPAGE_DELETING_IN_PROGRESS = 13\n\t{ \"FES_DEL\", MENUPAGE_CHOOSE_DELETE_SLOT, nil, nil,\n\t},\n\n\t// MENUPAGE_DELETE_SUCCESSFUL = 14\n\t{ \"FES_DEL\", MENUPAGE_NEW_GAME, nil, nil,\n\t\t MENUACTION_LABEL,\t\t\"FES_DSC\",\t{nil, SAVESLOT_NONE,\t0}, 0, 0, 0,\n\t\t MENUACTION_CHANGEMENU,\t\"FEM_OK\",\t{nil, SAVESLOT_NONE,\tMENUPAGE_NEW_GAME}, 320, 225, MENUALIGN_CENTER,\n\t},\n\n\t// MENUPAGE_CHOOSE_SAVE_SLOT = 15\n\t{ \"FET_SG\", MENUPAGE_DISABLED, nil, nil,\n\t\tMENUACTION_SAVEGAME,\t\t\t\"FEM_SL1\", {nil, SAVESLOT_1,\t\tMENUPAGE_SAVE_OVERWRITE_CONFIRM}, 40, 90, MENUALIGN_LEFT,\n\t\tMENUACTION_SAVEGAME,\t\t\t\"FEM_SL2\", {nil, SAVESLOT_2,\t\tMENUPAGE_SAVE_OVERWRITE_CONFIRM}, 0, 0, MENUALIGN_LEFT,\n\t\tMENUACTION_SAVEGAME,\t\t\t\"FEM_SL3\", {nil, SAVESLOT_3,\t\tMENUPAGE_SAVE_OVERWRITE_CONFIRM}, 0, 0, MENUALIGN_LEFT,\n\t\tMENUACTION_SAVEGAME,\t\t\t\"FEM_SL4\", {nil, SAVESLOT_4,\t\tMENUPAGE_SAVE_OVERWRITE_CONFIRM}, 0, 0, MENUALIGN_LEFT,\n\t\tMENUACTION_SAVEGAME,\t\t\t\"FEM_SL5\", {nil, SAVESLOT_5,\t\tMENUPAGE_SAVE_OVERWRITE_CONFIRM}, 0, 0, MENUALIGN_LEFT,\n\t\tMENUACTION_SAVEGAME,\t\t\t\"FEM_SL6\", {nil, SAVESLOT_6,\t\tMENUPAGE_SAVE_OVERWRITE_CONFIRM}, 0, 0, MENUALIGN_LEFT,\n\t\tMENUACTION_SAVEGAME,\t\t\t\"FEM_SL7\", {nil, SAVESLOT_7,\t\tMENUPAGE_SAVE_OVERWRITE_CONFIRM}, 0, 0, MENUALIGN_LEFT,\n\t\tMENUACTION_SAVEGAME,\t\t\t\"FEM_SL8\", {nil, SAVESLOT_8,\t\tMENUPAGE_SAVE_OVERWRITE_CONFIRM}, 0, 0, MENUALIGN_LEFT,\n\t\tMENUACTION_RESUME_FROM_SAVEZONE,\"FESZ_CA\", {nil, SAVESLOT_NONE,\t0}, 320, 345, MENUALIGN_CENTER,\n\t},\n\n\t// MENUPAGE_SAVE_OVERWRITE_CONFIRM = 16\n\t{ \"FET_SG\", MENUPAGE_CHOOSE_SAVE_SLOT, nil, nil,\n\t\tMENUACTION_LABEL,\t\t\"FESZ_QZ\", {nil, SAVESLOT_NONE, MENUPAGE_NONE}, 0, 0, 0,\n\t\tMENUACTION_NO,\t\t\t\"FEM_NO\", {nil, SAVESLOT_NONE, MENUPAGE_CHOOSE_SAVE_SLOT}, 320, 200, MENUALIGN_CENTER,\n\t\tMENUACTION_YES,\t\t\t\"FEM_YES\",  {nil, SAVESLOT_NONE, MENUPAGE_SAVING_IN_PROGRESS}, 320, 225, MENUALIGN_CENTER,\n\t},\n\n\t// MENUPAGE_SAVING_IN_PROGRESS = 17\n\t{ \"FET_SG\", MENUPAGE_CHOOSE_SAVE_SLOT, nil, nil,\n\t},\n\n\t// MENUPAGE_SAVE_SUCCESSFUL = 18\n\t{ \"FET_SG\", MENUPAGE_CHOOSE_SAVE_SLOT, nil, nil,\n\t\tMENUACTION_LABEL,\t\t\t\t\t\"FES_SSC\",\t{nil, SAVESLOT_LABEL,\tMENUPAGE_NONE}, 0, 0, 0,\n\t\tMENUACTION_RESUME_FROM_SAVEZONE,\t\"FEM_OK\",\t{nil, SAVESLOT_NONE,\tMENUPAGE_CHOOSE_SAVE_SLOT}, 320, 225, MENUALIGN_CENTER,\n\t},\n\n\t// MENUPAGE_SAVE_CUSTOM_WARNING = 19\n\t{ \"FET_SG\", MENUPAGE_NONE, nil, nil,\n\t\tMENUACTION_LABEL,\t\t\"\",\t\t\t{nil, SAVESLOT_NONE, 0}, 0, 0, 0,\n\t\tMENUACTION_CHANGEMENU,\t\"FEM_OK\",\t{nil, SAVESLOT_NONE, MENUPAGE_CHOOSE_SAVE_SLOT}, 320, 225, MENUALIGN_CENTER,\n\t},\n\n\t// MENUPAGE_SAVE_CHEAT_WARNING = 20\n\t{ \"FET_SG\", MENUPAGE_NEW_GAME, nil, nil,\n\t\tMENUACTION_LABEL,\t\t\"FES_CHE\",\t{nil, SAVESLOT_NONE,\tMENUPAGE_NONE}, 0, 0, 0,\n\t\tMENUACTION_CHANGEMENU,\t\"FEM_OK\",\t{nil, SAVESLOT_NONE,\tMENUPAGE_CHOOSE_SAVE_SLOT}, 320, 225, MENUALIGN_CENTER,\n\t},\n\n\t// MENUPAGE_SKIN_SELECT = 21\n\t{ \"FET_PS\", MENUPAGE_OPTIONS, nil, nil,\n\t\t MENUACTION_GOBACK,\t\t\"FEDS_TB\",\t{nil, SAVESLOT_NONE, MENUPAGE_OPTIONS}, 0, 0, 0,\n\t},\n\n\t// MENUPAGE_SAVE_UNUSED = 22\n\t{ \"FET_SG\", MENUPAGE_NEW_GAME, nil, nil,\n\t\t MENUACTION_LABEL,\t\t\"FED_LWR\",\t{nil, SAVESLOT_NONE,\t0}, 0, 0, 0,\n\t\t MENUACTION_CHANGEMENU,\t\"FEC_OKK\",\t{nil, SAVESLOT_NONE,\tMENUPAGE_CHOOSE_SAVE_SLOT}, 0, 0, 0,\n\t},\n\n\t// MENUPAGE_SAVE_FAILED = 23\n\t{ \"FET_SG\", MENUPAGE_CHOOSE_SAVE_SLOT, nil, nil,\n\t\t MENUACTION_LABEL,\t\t\"FEC_SVU\",\t{nil, SAVESLOT_NONE,\t0}, 0, 0, 0,\n\t\t MENUACTION_CHANGEMENU,\t\"FEC_OKK\",\t{nil, SAVESLOT_NONE,\tMENUPAGE_CHOOSE_SAVE_SLOT}, 0, 0, 0,\n\t},\n\n\t// MENUPAGE_SAVE_FAILED_2 = 24\n\t{ \"FET_LG\", MENUPAGE_CHOOSE_SAVE_SLOT, nil, nil,\n\t\t MENUACTION_LABEL,\t\t\"FEC_SVU\",\t{nil, SAVESLOT_NONE,\t0}, 0, 0, 0,\n\t},\n\n\t// MENUPAGE_LOAD_FAILED = 25\n\t{ \"FET_LG\", MENUPAGE_NEW_GAME, nil, nil,\n\t\t MENUACTION_LABEL,\t\t\"FEC_LUN\",\t{nil, SAVESLOT_NONE,  0}, 0, 0, 0,\n\t\t MENUACTION_GOBACK,\t\t\"FEDS_TB\",\t{nil, SAVESLOT_NONE,  MENUPAGE_NEW_GAME}, 0, 0, 0,\n\t},\n\n\t// MENUPAGE_CONTROLLER_PC = 26\n\t{ \"FET_CTL\", MENUPAGE_OPTIONS, new CCustomScreenLayout({0, 0, MENU_DEFAULT_LINE_HEIGHT, false, false, 150}), nil,\n#ifdef PC_PLAYER_CONTROLS\n\t\tMENUACTION_CTRLMETHOD,\t\"FET_STI\", {nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC}, 320, 150, MENUALIGN_CENTER,\n\t\tMENUACTION_KEYBOARDCTRLS,\"FEC_RED\", {nil, SAVESLOT_NONE, MENUPAGE_KEYBOARD_CONTROLS}, 0, 0, MENUALIGN_CENTER,\n#else\n\t\tMENUACTION_KEYBOARDCTRLS,\"FEC_RED\", {nil, SAVESLOT_NONE, MENUPAGE_KEYBOARD_CONTROLS}, 320, 150, MENUALIGN_CENTER,\n#endif\n#ifdef GAMEPAD_MENU\n\t\tMENUACTION_CHANGEMENU,\t\"FET_AGS\", {nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_SETTINGS}, 0, 0, MENUALIGN_CENTER,\n#endif\n#ifdef DETECT_JOYSTICK_MENU\n\t\tMENUACTION_CHANGEMENU,\t\"FEC_JOD\", {nil, SAVESLOT_NONE, MENUPAGE_DETECT_JOYSTICK}, 0, 0, MENUALIGN_CENTER,\n#endif\n\t\tMENUACTION_CHANGEMENU,\t\"FEC_MOU\", {nil, SAVESLOT_NONE, MENUPAGE_MOUSE_CONTROLS}, 0, 0, MENUALIGN_CENTER,\n\t\tMENUACTION_RESTOREDEF,\t\"FET_DEF\", {nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC}, 320, 0, MENUALIGN_CENTER,\n\t\tMENUACTION_GOBACK,\t\t\"FEDS_TB\", {nil, SAVESLOT_NONE, 0}, 320, 0, MENUALIGN_CENTER,\n   },\n\n\t// MENUPAGE_OPTIONS = 27\n\t{ \"FET_OPT\", MENUPAGE_NONE, nil, nil,\n\t\t MENUACTION_CHANGEMENU,\t\t\"FEO_CON\", {nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC}, 320, 132, MENUALIGN_CENTER,\n\t\t MENUACTION_LOADRADIO,\t\t\"FEO_AUD\", {nil, SAVESLOT_NONE, MENUPAGE_SOUND_SETTINGS}, 0, 0, MENUALIGN_CENTER,\n\t\t MENUACTION_CHANGEMENU,\t\t\"FEO_DIS\", {nil, SAVESLOT_NONE, MENUPAGE_DISPLAY_SETTINGS}, 0, 0, MENUALIGN_CENTER,\n#ifdef GRAPHICS_MENU_OPTIONS\n\t\t MENUACTION_CHANGEMENU,\t\t\"FET_GFX\", {nil, SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS}, 0, 0, MENUALIGN_CENTER,\n#endif\n\t\t MENUACTION_CHANGEMENU,\t\t\"FEO_LAN\", {nil, SAVESLOT_NONE, MENUPAGE_LANGUAGE_SETTINGS}, 0, 0, MENUALIGN_CENTER,\n\t\t MENUACTION_PLAYERSETUP,\t\"FET_PS\", {nil, SAVESLOT_NONE, MENUPAGE_SKIN_SELECT}, 0, 0, MENUALIGN_CENTER,\n\t\t MENUACTION_GOBACK,\t\t\t\"FEDS_TB\", {nil, SAVESLOT_NONE, 0}, 0, 0, MENUALIGN_CENTER,\n   },\n\n\t// MENUPAGE_EXIT = 28\n\t{ \"FET_QG\", MENUPAGE_NONE, nil, nil,\n\t\tMENUACTION_LABEL,\t\t\"FEQ_SRE\",\t{nil, SAVESLOT_NONE, 0}, 0, 0, 0,\n\t\tMENUACTION_DONTCANCEL,\t\"FEM_NO\",\t{nil, SAVESLOT_NONE, MENUPAGE_NONE}, 320, 200, MENUALIGN_CENTER,\n\t\tMENUACTION_CANCELGAME,\t\"FEM_YES\",\t{nil, SAVESLOT_NONE, MENUPAGE_NONE}, 320, 225, MENUALIGN_CENTER,\n   },\n\n\t// MENUPAGE_START_MENU = 29\n\t{ \"FEM_MM\", MENUPAGE_DISABLED, nil, nil,\n\t\t  MENUACTION_CHANGEMENU,\t\"FEP_STG\",\t{nil, SAVESLOT_NONE,\tMENUPAGE_NEW_GAME}, 320, 170, MENUALIGN_CENTER,\n\t\t  MENUACTION_CHANGEMENU,\t\"FEP_OPT\",\t{nil, SAVESLOT_NONE,\tMENUPAGE_OPTIONS}, 0, 0, MENUALIGN_CENTER,\n\t\t  MENUACTION_CHANGEMENU,\t\"FEP_QUI\",\t{nil, SAVESLOT_NONE,\tMENUPAGE_EXIT}, 0, 0, MENUALIGN_CENTER,\n   },\n\n\t// MENUPAGE_KEYBOARD_CONTROLS = 30\n\t{ \"FET_STI\", MENUPAGE_CONTROLLER_PC, nil, nil,\n   },\n\n\t// MENUPAGE_MOUSE_CONTROLS = 31\n\t{ \"FEC_MOU\", MENUPAGE_CONTROLLER_PC, nil, nil,\n\t\tMENUACTION_MOUSESENS,\t\"FEC_MSH\",\t{nil, SAVESLOT_NONE, MENUPAGE_MOUSE_CONTROLS}, 40, 170, MENUALIGN_LEFT,\n\t\tMENUACTION_INVVERT,\t\t\"FEC_IVV\",\t{nil, SAVESLOT_NONE, MENUPAGE_MOUSE_CONTROLS}, 0, 0, MENUALIGN_LEFT,\n#ifndef GAMEPAD_MENU\n\t   INVERT_PAD_SELECTOR\n#endif\n\t\tMENUACTION_MOUSESTEER,\t\"FET_MST\",\t{nil, SAVESLOT_NONE, MENUPAGE_MOUSE_CONTROLS}, 0, 0, MENUALIGN_LEFT,\n\t\tMENUACTION_GOBACK,\t\t\"FEDS_TB\",\t{nil, SAVESLOT_NONE, 0}, 320, 0, MENUALIGN_CENTER,\n\t\t//MENUACTION_GOBACK,\t\t\"FEDS_TB\",\t{nil, SAVESLOT_NONE, 0}, 320, 260, MENUALIGN_CENTER, // original y\n   },\n\n\t// MENUPAGE_PAUSE_MENU = 32\n\t{ \"FET_PAU\", MENUPAGE_DISABLED, nil, nil,\n\t\tMENUACTION_RESUME,\t\t\"FEP_RES\",\t{nil, SAVESLOT_NONE, 0}, 320, 120, MENUALIGN_CENTER,\n\t\tMENUACTION_CHANGEMENU,\t\"FEH_SGA\",\t{nil, SAVESLOT_NONE, MENUPAGE_NEW_GAME}, 0, 0, MENUALIGN_CENTER,\n\t\tMENUACTION_CHANGEMENU,\t\"FEH_MAP\",\t{nil, SAVESLOT_NONE, MENUPAGE_MAP}, 0, 0, MENUALIGN_CENTER,\n\t\tMENUACTION_CHANGEMENU,\t\"FEP_STA\",\t{nil, SAVESLOT_NONE, MENUPAGE_STATS}, 0, 0, MENUALIGN_CENTER,\n\t\tMENUACTION_CHANGEMENU,\t\"FEH_BRI\",\t{nil, SAVESLOT_NONE, MENUPAGE_BRIEFS}, 0, 0, MENUALIGN_CENTER,\n\t\tMENUACTION_CHANGEMENU,\t\"FET_OPT\",\t{nil, SAVESLOT_NONE, MENUPAGE_OPTIONS}, 0, 0, MENUALIGN_CENTER,\n\t\tMENUACTION_CHANGEMENU,\t\"FEP_QUI\",\t{nil, SAVESLOT_NONE, MENUPAGE_EXIT}, 0, 0, MENUALIGN_CENTER,\n   },\n\n\t// MENUPAGE_NONE = 33\n\t{ \"\", 0, nil, nil, },\n\n#ifdef GAMEPAD_MENU\n\t{ \"FET_AGS\", MENUPAGE_CONTROLLER_PC, new CCustomScreenLayout({40, 78, 25, true, true}), nil,\n\t\tMENUACTION_CTRLCONFIG,\t\t\"FEC_CCF\", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_SETTINGS }, 40, 76, MENUALIGN_LEFT,\n\t\tMENUACTION_CTRLDISPLAY,\t\t\"FEC_CDP\", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_SETTINGS }, 0, 0, MENUALIGN_LEFT,\n\t\tINVERT_PAD_SELECTOR\n\t\tMENUACTION_CTRLVIBRATION,\t\"FEC_VIB\", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_SETTINGS }, 0, 0, MENUALIGN_LEFT,\n\t\tSELECT_CONTROLLER_TYPE\n\t\tMENUACTION_GOBACK,\t\t\"FEDS_TB\", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, 0, 0, MENUALIGN_LEFT,\n\t},\n#endif\n#ifdef LEGACY_MENU_OPTIONS\n\t// MENUPAGE_DEBUG_MENU = 18\n\t{ \"FED_DBG\", MENUPAGE_NONE, nil, nil,\n\t\tMENUACTION_RELOADIDE,\t\"FED_RID\", {nil, SAVESLOT_NONE, MENUPAGE_NONE}, 0, 0, 0,\n\t\tMENUACTION_SETDBGFLAG,\t\"FED_DFL\", {nil, SAVESLOT_NONE, MENUPAGE_NONE}, 0, 0, 0,\n\t\tMENUACTION_SWITCHBIGWHITEDEBUGLIGHT,\t\"FED_DLS\", {nil, SAVESLOT_NONE, MENUPAGE_NONE}, 0, 0, 0,\n\t\tMENUACTION_COLLISIONPOLYS,\t\"FED_SCP\", {nil, SAVESLOT_NONE, MENUPAGE_NONE}, 0, 0, 0,\n\t\tMENUACTION_GOBACK,\t\t\"FEDS_TB\", {nil, SAVESLOT_NONE, MENUPAGE_NONE}, 0, 0, 0,\n   },\n\n\t// MENUPAGE_CONTROLLER_PC_OLD1 = 36\n\t{ \"FET_CTL\", MENUPAGE_CONTROLLER_PC, nil, nil,\n\t\tMENUACTION_GETKEY,\t\"FEC_PLB\", {nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1}, 0, 0, 0,\n\t\tMENUACTION_GETKEY,\t\"FEC_CWL\", {nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1}, 0, 0, 0,\n\t\tMENUACTION_GETKEY,\t\"FEC_CWR\", {nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1}, 0, 0, 0,\n\t\tMENUACTION_GETKEY,\t\"FEC_LKT\", {nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1}, 0, 0, 0,\n\t\tMENUACTION_GETKEY,\t\"FEC_PJP\", {nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1}, 0, 0, 0,\n\t\tMENUACTION_GETKEY,\t\"FEC_PSP\", {nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1}, 0, 0, 0,\n\t\tMENUACTION_GETKEY,\t\"FEC_TLF\", {nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1}, 0, 0, 0,\n\t\tMENUACTION_GETKEY,\t\"FEC_TRG\", {nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1}, 0, 0, 0,\n\t\tMENUACTION_GETKEY,\t\"FEC_CCM\", {nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD1}, 0, 0, 0,\n\t\tMENUACTION_GOBACK,\t\t\"FEDS_TB\", {nil, SAVESLOT_NONE, MENUPAGE_NONE}, 0, 0, 0,\n   },\n\n\t// MENUPAGE_CONTROLLER_PC_OLD2 = 37\n\t{ \"FET_CTL\", MENUPAGE_CONTROLLER_PC, nil, nil,\n\n\t},\n\n\t// MENUPAGE_CONTROLLER_PC_OLD3 = 38\n\t{ \"FET_CTL\", MENUPAGE_CONTROLLER_PC, nil, nil,\n\t\t MENUACTION_GETKEY,\t\"FEC_LUP\", {nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD3}, 0, 0, 0,\n\t\t MENUACTION_GETKEY,\t\"FEC_LDN\", {nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD3}, 0, 0, 0,\n\t\t MENUACTION_GETKEY,\t\"FEC_SMS\", {nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD3}, 0, 0, 0,\n\t\t MENUACTION_SHOWHEADBOB,\t\"FEC_GSL\", {nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC_OLD3}, 0, 0, 0,\n\t\t MENUACTION_GOBACK,\t\t\"FEDS_TB\", {nil, SAVESLOT_NONE, MENUPAGE_NONE}, 0, 0, 0,\n   },\n\n\t// MENUPAGE_CONTROLLER_PC_OLD4 = 39\n\t{ \"FET_CTL\", MENUPAGE_CONTROLLER_PC, nil, nil,\n\n\t},\n\n\t// MENUPAGE_CONTROLLER_DEBUG = 40\n\t{ \"FEC_DBG\", MENUPAGE_CONTROLLER_PC, nil, nil,\n\t\t MENUACTION_GETKEY,\t\"FEC_TGD\",\t{nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_DEBUG}, 0, 0, 0,\n\t\t MENUACTION_GETKEY,\t\"FEC_TDO\",\t{nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_DEBUG}, 0, 0, 0,\n\t\t MENUACTION_GETKEY,\t\"FEC_TSS\",\t{nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_DEBUG}, 0, 0, 0,\n\t\t MENUACTION_GETKEY,\t\"FEC_SMS\",\t{nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_DEBUG}, 0, 0, 0,\n\t\t MENUACTION_GOBACK,\t\"FEDS_TB\",\t{nil, SAVESLOT_NONE, MENUPAGE_NONE}, 0, 0, 0,\n   },\n#endif\n\n#ifdef GRAPHICS_MENU_OPTIONS\n\t// MENUPAGE_GRAPHICS_SETTINGS\n\t{ \"FET_GFX\", MENUPAGE_OPTIONS, new CCustomScreenLayout({40, 78, 25, true, true}), GraphicsGoBack,\n\n\t\tMENUACTION_SCREENRES,\t\"FED_RES\", { nil, SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS }, 0, 0, MENUALIGN_LEFT,\n\t\tMENUACTION_WIDESCREEN,\t\"FED_WIS\", { nil, SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS }, 0, 0, MENUALIGN_LEFT,\n\t\tVIDEOMODE_SELECTOR\n#ifdef LEGACY_MENU_OPTIONS\n\t\tMENUACTION_FRAMESYNC,\t\"FEM_VSC\", {nil, SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS}, 0, 0, MENUALIGN_LEFT,\n#endif\n\t\tMENUACTION_FRAMELIMIT,\t\"FEM_FRM\", { nil, SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS }, 0, 0, MENUALIGN_LEFT,\n\t\tMULTISAMPLING_SELECTOR\n\t\tISLAND_LOADING_SELECTOR\n\t\tDUALPASS_SELECTOR\n#ifdef EXTENDED_COLOURFILTER\n\t\tPOSTFX_SELECTORS\n#elif defined LEGACY_MENU_OPTIONS\n\t\tMENUACTION_TRAILS,\t\t\"FED_TRA\", { nil, SAVESLOT_NONE, MENUPAGE_GRAPHICS_SETTINGS }, 0, 0, MENUALIGN_LEFT,\n#endif\n\t\t// re3.cpp inserts here pipeline selectors if neo/neo.txd exists and EXTENDED_PIPELINES defined\n\t\tMENUACTION_CFO_DYNAMIC,\t\"FET_DEF\", { new CCFODynamic(nil, nil, nil, nil, RestoreDefGraphics) }, 320, 0, MENUALIGN_CENTER,\n\t\tMENUACTION_GOBACK,\t\t\"FEDS_TB\", {nil, SAVESLOT_NONE, MENUPAGE_NONE}, 320, 0, MENUALIGN_CENTER,\n\t},\n#endif\n\n#ifdef DETECT_JOYSTICK_MENU\n\t// MENUPAGE_DETECT_JOYSTICK\n\t{ \"FEC_JOD\", MENUPAGE_CONTROLLER_PC, new CCustomScreenLayout({0, 0, 0, false, false, 30}), DetectJoystickGoBack,\n\t\tMENUACTION_LABEL,\t\"FEC_JPR\", { nil, SAVESLOT_NONE, MENUPAGE_NONE }, 0, 0, 0,\n\t\tMENUACTION_CFO_DYNAMIC,\t\"FEC_JDE\", { new CCFODynamic(nil, nil, nil, DetectJoystickDraw, nil) }, 80, 200, MENUALIGN_LEFT,\n\t\tMENUACTION_GOBACK,\t\t\"FEDS_TB\", {nil, SAVESLOT_NONE, MENUPAGE_NONE}, 320, 225, MENUALIGN_CENTER,\n\t},\n#endif\n\n\t// MENUPAGE_OUTRO = 34\n\t{ \"\", 0, nil, nil, },\n};\n\n#endif\n#endif\n"
  },
  {
    "path": "src/core/Pad.cpp",
    "content": "#define WITHDINPUT\n#include \"common.h\"\n#include \"crossplatform.h\"\n#include \"platform.h\"\n#ifdef XINPUT\n#include <xinput.h>\n#if !defined(PSAPI_VERSION) || (PSAPI_VERSION > 1)\n#pragma comment( lib, \"Xinput9_1_0.lib\" )\n#else\n#pragma comment( lib, \"Xinput.lib\" )\n#endif\n#endif\n\n#include \"Pad.h\"\n#include \"ControllerConfig.h\"\n#include \"Timer.h\"\n#include \"Frontend.h\"\n#include \"Camera.h\"\n#include \"Game.h\"\n#include \"CutsceneMgr.h\"\n#include \"Font.h\"\n#include \"Hud.h\"\n#include \"Text.h\"\n#include \"Timer.h\"\n#include \"Record.h\"\n#include \"World.h\"\n#include \"Vehicle.h\"\n#include \"Ped.h\"\n#include \"Population.h\"\n#include \"Record.h\"\n#include \"Replay.h\"\n#include \"Weather.h\"\n#include \"Streaming.h\"\n#include \"PathFind.h\"\n#include \"Wanted.h\"\n#include \"WaterLevel.h\"\n#include \"General.h\"\n#include \"Fluff.h\"\n#include \"Gangs.h\"\n#include \"platform.h\"\n#include \"Stats.h\"\n#include \"CarCtrl.h\"\n#include \"TrafficLights.h\"\n\n#ifdef GTA_PS2\n#include \"eetypes.h\"\n#include \"libpad.h\"\n#endif\n\nCPad Pads[MAX_PADS];\n#ifdef GTA_PS2\nu_long128 pad_dma_buf[scePadDmaBufferMax] __attribute__((aligned(64)));\nu_long128 pad2_dma_buf[scePadDmaBufferMax] __attribute__((aligned(64)));\n#endif\n\nCMousePointerStateHelper MousePointerStateHelper;\n\nbool CPad::bDisplayNoControllerMessage;\nbool CPad::bObsoleteControllerMessage;\nbool CPad::bOldDisplayNoControllerMessage;\nbool CPad::m_bMapPadOneToPadTwo;\nbool CPad::m_bDebugCamPCOn;\nbool CPad::bHasPlayerCheated;\nbool CPad::bInvertLook4Pad;\n#ifdef GTA_PS2\nunsigned char act_direct[6];\nunsigned char act_align[6];\n#endif\n\nCKeyboardState CPad::OldKeyState;\nCKeyboardState CPad::NewKeyState;\nCKeyboardState CPad::TempKeyState;\n\nchar CPad::KeyBoardCheatString[30];\n\nCMouseControllerState CPad::OldMouseControllerState;\nCMouseControllerState CPad::NewMouseControllerState;\nCMouseControllerState CPad::PCTempMouseControllerState;\n\n#ifdef DETECT_PAD_INPUT_SWITCH\nbool CPad::IsAffectedByController = false;\n#endif\n\n_TODO(\"gbFastTime\");\nextern bool gbFastTime;\n\n#ifdef WALLCLIMB_CHEAT\nextern bool gGravityCheat;\n#endif\n\nvoid SpecialCarCheats()\n{\n\tif ( !CVehicle::bCheat9 )\n\t{\n\t\t((CVehicleModelInfo*)CModelInfo::GetModelInfo(MI_INFERNUS))->m_wheelScale *= 1.3f;\n\t\t((CVehicleModelInfo*)CModelInfo::GetModelInfo(MI_CHEETAH))->m_wheelScale *= 1.3f;\n\t\t((CVehicleModelInfo*)CModelInfo::GetModelInfo(MI_PHEONIX))->m_wheelScale *= 1.3f;\n\t\t((CVehicleModelInfo*)CModelInfo::GetModelInfo(MI_DELUXO))->m_wheelScale *= 1.3f;\n\t\tmod_HandlingManager.GetHandlingData(HANDLING_LANDSTAL)->Transmission.fEngineAcceleration *= 2.0f;\n\t\tmod_HandlingManager.GetHandlingData(HANDLING_PATRIOT)->Transmission.fEngineAcceleration *= 2.0f;\n\t\tmod_HandlingManager.GetHandlingData(HANDLING_BOBCAT)->Transmission.fEngineAcceleration *= 2.0f;\n\t\tmod_HandlingManager.GetHandlingData(HANDLING_BFINJECT)->Transmission.fEngineAcceleration *= 2.0f;\n\t\tmod_HandlingManager.GetHandlingData(HANDLING_RANCHER)->Transmission.fEngineAcceleration *= 2.0f;\n\t\tmod_HandlingManager.GetHandlingData(HANDLING_DESPERAD)->Transmission.fEngineAcceleration *= 2.0f;\n\t\tmod_HandlingManager.GetHandlingData(HANDLING_DELUXO)->Transmission.fEngineAcceleration *= 2.0f;\n\n\t\tmod_HandlingManager.GetHandlingData(HANDLING_BAGGAGE)->Transmission.fEngineAcceleration *= 2.0f;\n\t\tmod_HandlingManager.GetHandlingData(HANDLING_BAGGAGE)->Transmission.fMaxVelocity *= 2.0f;\n\t\tmod_HandlingManager.GetHandlingData(HANDLING_BAGGAGE)->Transmission.InitGearRatios();\n\n\t\tmod_HandlingManager.GetHandlingData(HANDLING_GOLFCART)->Transmission.fEngineAcceleration *= 2.0f;\n\t\tmod_HandlingManager.GetHandlingData(HANDLING_GOLFCART)->Transmission.fMaxVelocity *= 2.0f;\n\t\tmod_HandlingManager.GetHandlingData(HANDLING_GOLFCART)->Transmission.InitGearRatios();\n\n\t\tmod_HandlingManager.GetHandlingData(HANDLING_STINGER)->fCollisionDamageMultiplier *= 0.25f;\n\t\tmod_HandlingManager.GetHandlingData(HANDLING_STINGER)->fMass *= 2.5f;\n\t\tmod_HandlingManager.GetHandlingData(HANDLING_STINGER)->fTurnMass *= 4.0f;\n\n\t\tmod_HandlingManager.GetHandlingData(HANDLING_BANSHEE)->fCollisionDamageMultiplier *= 0.25f;\n\t\tmod_HandlingManager.GetHandlingData(HANDLING_BANSHEE)->fMass *= 2.5f;\n\t\tmod_HandlingManager.GetHandlingData(HANDLING_BANSHEE)->fTurnMass *= 4.0f;\n\n\t\tmod_HandlingManager.GetHandlingData(HANDLING_SABRETUR)->fCollisionDamageMultiplier *= 0.25f;\n\t\tmod_HandlingManager.GetHandlingData(HANDLING_SABRETUR)->fMass *= 2.5f;\n\t\tmod_HandlingManager.GetHandlingData(HANDLING_SABRETUR)->fTurnMass *= 4.0f;\n\n\t\tmod_HandlingManager.GetHandlingData(HANDLING_COMET)->fCollisionDamageMultiplier *= 0.25f;\n\t\tmod_HandlingManager.GetHandlingData(HANDLING_COMET)->fMass *= 2.5f;\n\t\tmod_HandlingManager.GetHandlingData(HANDLING_COMET)->fTurnMass *= 4.0f;\n\n\t\tmod_HandlingManager.GetHandlingData(HANDLING_DELUXO)->fCollisionDamageMultiplier *= 0.25f;\n\t\tmod_HandlingManager.GetHandlingData(HANDLING_DELUXO)->fMass *= 2.5f;\n\t\tmod_HandlingManager.GetHandlingData(HANDLING_DELUXO)->fTurnMass *= 4.0f;\n\t\tCHud::SetHelpMessage(TheText.Get(\"CHEAT1\"), true);\n\t\tCVehicle::bCheat9 = true;\n\t\tCPad::bHasPlayerCheated = true;\n\t}\n}\n\nvoid PickUpChicksCheat()\n{\n\tif ( FindPlayerVehicle() && (FindPlayerVehicle()->IsCar() || FindPlayerVehicle()->IsBike()) )\n\t{\n\t\tCVehicle *vehicle = FindPlayerVehicle();\n\t\tif ( FindPlayerVehicle()->IsBike() )\n\t\t{\n\t\t\tif ( vehicle->pPassengers[0] )\n\t\t\t\tvehicle->pPassengers[0]->SetObjective(OBJECTIVE_LEAVE_CAR, vehicle);\n\t\t}\n\t\tCPed* someoneElse = (CPed*)CWorld::TestSphereAgainstWorld(vehicle->GetPosition(), 6.0f, FindPlayerPed(), false, false, true, false, false, false);\n\t\tif ( someoneElse && someoneElse->m_nPedState != PED_DRIVING )\n\t\t{\n\t\t\tCHud::SetHelpMessage(TheText.Get(\"CHEAT1\"), true);\n\t\t\tsomeoneElse->SetObjective(OBJECTIVE_ENTER_CAR_AS_PASSENGER, vehicle);\n\t\t}\n\t}\n}\n\nvoid WeaponCheat1()\n{\n\tCHud::SetHelpMessage(TheText.Get(\"CHEAT2\"), true);\n\n\tCStreaming::RequestModel(MI_BRASS_KNUCKLES, STREAMFLAGS_DONT_REMOVE);\n\tCStreaming::RequestModel(MI_BASEBALL_BAT, STREAMFLAGS_DONT_REMOVE);\n\tCStreaming::RequestModel(MI_MOLOTOV, STREAMFLAGS_DONT_REMOVE);\n\tCStreaming::RequestModel(MI_COLT45, STREAMFLAGS_DONT_REMOVE);\n\tCStreaming::RequestModel(MI_SHOTGUN, STREAMFLAGS_DONT_REMOVE);\n\tCStreaming::RequestModel(MI_TEC9, STREAMFLAGS_DONT_REMOVE);\n\tCStreaming::RequestModel(MI_RUGER, STREAMFLAGS_DONT_REMOVE);\n\tCStreaming::RequestModel(MI_SNIPERRIFLE, STREAMFLAGS_DONT_REMOVE);\n\tCStreaming::RequestModel(MI_FLAMETHROWER, STREAMFLAGS_DONT_REMOVE);\n\tCStreaming::LoadAllRequestedModels(false);\n\n\tFindPlayerPed()->GiveWeapon(WEAPONTYPE_BRASSKNUCKLE, 1);\n\tFindPlayerPed()->GiveWeapon(WEAPONTYPE_BASEBALLBAT, 1);\n\tFindPlayerPed()->GiveWeapon(WEAPONTYPE_MOLOTOV, 10);\n\tFindPlayerPed()->GiveWeapon(WEAPONTYPE_COLT45, 100);\n\tFindPlayerPed()->GiveWeapon(WEAPONTYPE_SHOTGUN, 50);\n\tFindPlayerPed()->GiveWeapon(WEAPONTYPE_TEC9, 150);\n\tFindPlayerPed()->GiveWeapon(WEAPONTYPE_RUGER, 120);\n\tFindPlayerPed()->GiveWeapon(WEAPONTYPE_SNIPERRIFLE, 25);\n\tFindPlayerPed()->GiveWeapon(WEAPONTYPE_FLAMETHROWER, 200);\n\n\tCStreaming::SetModelIsDeletable(MI_BRASS_KNUCKLES);\n\tCStreaming::SetModelIsDeletable(MI_BASEBALL_BAT);\n\tCStreaming::SetModelIsDeletable(MI_MOLOTOV);\n\tCStreaming::SetModelIsDeletable(MI_COLT45);\n\tCStreaming::SetModelIsDeletable(MI_SHOTGUN);\n\tCStreaming::SetModelIsDeletable(MI_TEC9);\n\tCStreaming::SetModelIsDeletable(MI_RUGER);\n\tCStreaming::SetModelIsDeletable(MI_SNIPERRIFLE);\n\tCStreaming::SetModelIsDeletable(MI_FLAMETHROWER);\n#ifdef MOBILE_IMPROVEMENTS\n\tif (FindPlayerVehicle()) {\n\t\tFindPlayerPed()->RemoveWeaponWhenEnteringVehicle();\n\t}\n#endif\n}\n\nvoid WeaponCheat2()\n{\n\tCHud::SetHelpMessage(TheText.Get(\"CHEAT2\"), true);\n\n\tCStreaming::RequestModel(MI_KATANA, STREAMFLAGS_DONT_REMOVE);\n\tCStreaming::RequestModel(MI_GRENADE, STREAMFLAGS_DONT_REMOVE);\n\tCStreaming::RequestModel(MI_BOMB, STREAMFLAGS_DONT_REMOVE);\n\tCStreaming::RequestModel(MI_PYTHON, STREAMFLAGS_DONT_REMOVE);\n\tCStreaming::RequestModel(MI_STUBBY_SHOTGUN, STREAMFLAGS_DONT_REMOVE);\n\tCStreaming::RequestModel(MI_SILENCEDINGRAM, STREAMFLAGS_DONT_REMOVE);\n\tCStreaming::RequestModel(MI_M4, STREAMFLAGS_DONT_REMOVE);\n\tCStreaming::RequestModel(MI_LASERSCOPE, STREAMFLAGS_DONT_REMOVE);\n\tCStreaming::RequestModel(MI_ROCKETLAUNCHER, STREAMFLAGS_DONT_REMOVE);\n\tCStreaming::LoadAllRequestedModels(false);\n\n#ifdef FIX_BUGS\n\tFindPlayerPed()->GiveWeapon(WEAPONTYPE_KATANA, 1);\n#else\n\tFindPlayerPed()->GiveWeapon(WEAPONTYPE_KATANA, 0);\n#endif\n\tFindPlayerPed()->GiveWeapon(WEAPONTYPE_DETONATOR_GRENADE, 10);\n\tFindPlayerPed()->GiveWeapon(WEAPONTYPE_PYTHON, 40);\n\tFindPlayerPed()->GiveWeapon(WEAPONTYPE_STUBBY_SHOTGUN, 25);\n\tFindPlayerPed()->GiveWeapon(WEAPONTYPE_SILENCED_INGRAM, 100);\n\tFindPlayerPed()->GiveWeapon(WEAPONTYPE_M4, 150);\n\tFindPlayerPed()->GiveWeapon(WEAPONTYPE_LASERSCOPE, 21);\n\tFindPlayerPed()->GiveWeapon(WEAPONTYPE_ROCKETLAUNCHER, 5);\n\n\tCStreaming::SetModelIsDeletable(MI_KATANA);\n\tCStreaming::SetModelIsDeletable(MI_GRENADE);\n\tCStreaming::SetModelIsDeletable(MI_BOMB);\n\tCStreaming::SetModelIsDeletable(MI_PYTHON);\n\tCStreaming::SetModelIsDeletable(MI_STUBBY_SHOTGUN);\n\tCStreaming::SetModelIsDeletable(MI_SILENCEDINGRAM);\n\tCStreaming::SetModelIsDeletable(MI_M4);\n\tCStreaming::SetModelIsDeletable(MI_LASERSCOPE);\n\tCStreaming::SetModelIsDeletable(MI_ROCKETLAUNCHER);\n#ifdef MOBILE_IMPROVEMENTS\n\tif (FindPlayerVehicle()) {\n\t\tFindPlayerPed()->RemoveWeaponWhenEnteringVehicle();\n\t}\n#endif\n}\n\nvoid WeaponCheat3()\n{\n\tCHud::SetHelpMessage(TheText.Get(\"CHEAT2\"), true);\n\n\tCStreaming::RequestModel(MI_CHAINSAW, STREAMFLAGS_DONT_REMOVE);\n\tCStreaming::RequestModel(MI_GRENADE, STREAMFLAGS_DONT_REMOVE);\n\tCStreaming::RequestModel(MI_PYTHON, STREAMFLAGS_DONT_REMOVE);\n\tCStreaming::RequestModel(MI_SPAS12_SHOTGUN, STREAMFLAGS_DONT_REMOVE);\n\tCStreaming::RequestModel(MI_MP5, STREAMFLAGS_DONT_REMOVE);\n\tCStreaming::RequestModel(MI_M4, STREAMFLAGS_DONT_REMOVE);\n\tCStreaming::RequestModel(MI_LASERSCOPE, STREAMFLAGS_DONT_REMOVE);\n\tCStreaming::RequestModel(MI_MINIGUN, STREAMFLAGS_DONT_REMOVE);\n\tCStreaming::RequestModel(MI_MINIGUN2, STREAMFLAGS_DONT_REMOVE);\n\tCStreaming::LoadAllRequestedModels(false);\n\n#ifdef FIX_BUGS\n\tFindPlayerPed()->GiveWeapon(WEAPONTYPE_CHAINSAW, 1);\n#else\n\tFindPlayerPed()->GiveWeapon(WEAPONTYPE_CHAINSAW, 0);\n#endif\n\tFindPlayerPed()->GiveWeapon(WEAPONTYPE_GRENADE, 10);\n\tFindPlayerPed()->GiveWeapon(WEAPONTYPE_PYTHON, 40);\n\tFindPlayerPed()->GiveWeapon(WEAPONTYPE_SPAS12_SHOTGUN, 30);\n\tFindPlayerPed()->GiveWeapon(WEAPONTYPE_MP5, 100);\n\tFindPlayerPed()->GiveWeapon(WEAPONTYPE_M4, 150);\n\tFindPlayerPed()->GiveWeapon(WEAPONTYPE_LASERSCOPE, 21);\n\tFindPlayerPed()->GiveWeapon(WEAPONTYPE_MINIGUN, 500);\n\n\tCStreaming::SetModelIsDeletable(MI_CHAINSAW);\n\tCStreaming::SetModelIsDeletable(MI_GRENADE);\n\tCStreaming::SetModelIsDeletable(MI_PYTHON);\n\tCStreaming::SetModelIsDeletable(MI_SPAS12_SHOTGUN);\n\tCStreaming::SetModelIsDeletable(MI_MP5);\n\tCStreaming::SetModelIsDeletable(MI_M4);\n\tCStreaming::SetModelIsDeletable(MI_LASERSCOPE);\n\tCStreaming::SetModelIsDeletable(MI_MINIGUN);\n\tCStreaming::SetModelIsDeletable(MI_MINIGUN2);\n\n#ifdef MOBILE_IMPROVEMENTS\n\tif (FindPlayerVehicle()) {\n\t\tFindPlayerPed()->RemoveWeaponWhenEnteringVehicle();\n\t}\n#endif\n}\n\nvoid HealthCheat()\n{\n\tCHud::SetHelpMessage(TheText.Get(\"CHEAT3\"), true);\n\tFindPlayerPed()->m_fHealth = CWorld::Players[0].m_nMaxHealth;\n\tif (FindPlayerVehicle()) {\n\t\tFindPlayerVehicle()->m_fHealth = 1000.0f;\n\t\tif (FindPlayerVehicle()->m_vehType == VEHICLE_TYPE_CAR) {\n\t\t\t((CAutomobile*)FindPlayerVehicle())->Damage.SetEngineStatus(0);\n\t\t\tfor (int32 i = 0; i < 4; i++)\n\t\t\t\t((CAutomobile*)FindPlayerVehicle())->Damage.SetWheelStatus(i, WHEEL_STATUS_OK);\n\t\t}\n\t}\n}\n\n// TODO(Miami): this is HELLA different on mobile, although it mostly has debug oriented things like player exiting it's current car and enters spawned one etc.\nvoid VehicleCheat(int model)\n{\n\tCHud::SetHelpMessage(TheText.Get(\"CHEAT1\"), true);\n\tCStreaming::RequestModel(model, STREAMFLAGS_DONT_REMOVE);\n\tCStreaming::LoadAllRequestedModels(false);\n\tif (CStreaming::ms_aInfoForModel[model].m_loadState == STREAMSTATE_LOADED) {\n\t\tCHud::SetHelpMessage(TheText.Get(\"CHEAT1\"), true);\n\n\t\tif (!(CStreaming::ms_aInfoForModel[model].m_loadState & STREAMFLAGS_DONT_REMOVE)) {\n\t\t\tCStreaming::SetModelIsDeletable(model);\n\t\t\tCStreaming::SetModelTxdIsDeletable(model);\n\t\t}\n\n\t\tint32 node = ThePaths.FindNodeClosestToCoors(FindPlayerCoors(), PATH_CAR, 100.0f);\n\t\tif (node < 0) return;\n\n#ifdef FIX_BUGS\n\t\tCAutomobile* vehicle = new CAutomobile(model, RANDOM_VEHICLE);\n#else\n\t\tCAutomobile* vehicle = new CAutomobile(model, MISSION_VEHICLE);\n#endif\n\t\tif (vehicle != nil) {\n\t\t\tCVector pos = ThePaths.m_pathNodes[node].GetPosition();\n\t\t\tpos.z += 4.0f;\n\t\t\tvehicle->SetPosition(pos);\n\t\t\tvehicle->SetOrientation(0.0f, 0.0f, DEGTORAD(200.0f));\n\n\t\t\tvehicle->SetStatus(STATUS_ABANDONED);\n\t\t\tvehicle->m_nDoorLock = CARLOCK_UNLOCKED;\n\t\t\tCWorld::Add(vehicle);\n\t\t}\n\t}\n\tCStats::CheatedCount += 1000;\n\tCPad::bHasPlayerCheated = true;\n}\n\n\nvoid BlowUpCarsCheat()\n{\n\tCHud::SetHelpMessage(TheText.Get(\"CHEAT1\"), true);\n\n\tint i = CPools::GetVehiclePool()->GetSize();\n\twhile (i-- > 0) {\n\t\tif (CVehicle *veh = CPools::GetVehiclePool()->GetSlot(i))\n\t\t\tveh->BlowUpCar(nil);\n\t}\n}\n\nvoid ChangePlayerCheat()\n{\n\t// I don't know wtf is going on in here...\n\tint modelId, anotherModelId;\n\n\tif (FindPlayerPed()->IsPedInControl() && CModelInfo::GetModelInfo(\"player\", nil)) {\n\t\tCHud::SetHelpMessage(TheText.Get(\"CHEAT1\"), true);\n\t\tCPlayerPed *ped = FindPlayerPed();\n\t\tAssocGroupId AnimGrp = ped->m_animGroup;\n\t\tdo\n\t\t{\n\t\t\tdo {\n\t\t\t\tmodelId = CGeneral::GetRandomNumberInRange(0, MI_PGA);\n\t\t\t\tanotherModelId = modelId+1;\n\t\t\t} while (!CModelInfo::GetModelInfo(anotherModelId));\n\t\t} while (anotherModelId >= MI_SPECIAL01 && anotherModelId <= MI_SPECIAL04 || modelId == MI_TAXI_D);\n\n\t\tuint8 flags = CStreaming::ms_aInfoForModel[anotherModelId].m_flags;\n\t\tped->DeleteRwObject();\n\t\tCStreaming::RequestModel(anotherModelId, STREAMFLAGS_DEPENDENCY| STREAMFLAGS_DONT_REMOVE);\n\t\tCStreaming::LoadAllRequestedModels(false);\n\t\tped->m_modelIndex = -1;\n\t\tped->SetModelIndex(anotherModelId);\n\t\tped->m_animGroup = AnimGrp;\n\t\tif (modelId != -1) {\n\t\t\tif (!(flags & STREAMFLAGS_DONT_REMOVE))\n\t\t\t\tCStreaming::SetModelIsDeletable(anotherModelId);\n\t\t}\n\t}\n}\n\nvoid ChangePlayerModel(const char* name) {\n\tif (!FindPlayerVehicle()) {\n\t\tFindPlayerPed()->Undress(name);\n\t\tCStreaming::LoadAllRequestedModels(0);\n\t\tFindPlayerPed()->Dress();\n\t}\n}\n\nvoid MayhemCheat()\n{\n\tCHud::SetHelpMessage(TheText.Get(\"CHEAT1\"), true);\n\tfor (int i = PEDTYPE_CIVMALE; i < PEDTYPE_SPECIAL; i++)\n\t\tCPedType::SetThreats(i, PED_FLAG_PLAYER1 | PED_FLAG_PLAYER2 | PED_FLAG_PLAYER3 | PED_FLAG_PLAYER4 |\n\t\t\tPED_FLAG_CIVMALE | PED_FLAG_CIVFEMALE | PED_FLAG_COP | PED_FLAG_GANG1 |\n\t\t\tPED_FLAG_GANG2 | PED_FLAG_GANG3 | PED_FLAG_GANG4 | PED_FLAG_GANG5 |\n\t\t\tPED_FLAG_GANG6 | PED_FLAG_GANG7 | PED_FLAG_GANG8 | PED_FLAG_GANG9 |\n\t\t\tPED_FLAG_EMERGENCY | PED_FLAG_PROSTITUTE | PED_FLAG_CRIMINAL | PED_FLAG_SPECIAL );\n\tCStats::CheatedCount += 1000;\n\tCPad::bHasPlayerCheated = true;\n}\n\nvoid EverybodyAttacksPlayerCheat()\n{\n\tCHud::SetHelpMessage(TheText.Get(\"CHEAT1\"), true);\n\tfor (int i = PEDTYPE_CIVMALE; i < PEDTYPE_SPECIAL; i++)\n\t\tCPedType::AddThreat(i, PED_FLAG_PLAYER1);\n\n\tCStats::CheatedCount += 1000;\n\tCPad::bHasPlayerCheated = true;\n}\n\nvoid WeaponsForAllCheat()\n{\n\tCHud::SetHelpMessage(TheText.Get(\"CHEAT1\"), true);\n\tCPopulation::ms_bGivePedsWeapons = !CPopulation::ms_bGivePedsWeapons;\n\tCStats::CheatedCount += 1000;\n\tCPad::bHasPlayerCheated = true;\n}\n\nvoid FastTimeCheat()\n{\n\tCHud::SetHelpMessage(TheText.Get(\"CHEAT1\"), true);\n\tif (CTimer::GetTimeScale() < 4.0f)\n\t\tCTimer::SetTimeScale(CTimer::GetTimeScale() * 2.0f);\n}\n\nvoid SlowTimeCheat()\n{\n\tCHud::SetHelpMessage(TheText.Get(\"CHEAT1\"), true);\n\tif (CTimer::GetTimeScale() > 0.25f)\n\t\tCTimer::SetTimeScale(CTimer::GetTimeScale() * 0.5f);\n}\n\nvoid MoneyCheat()\n{\n\tCWorld::Players[CWorld::PlayerInFocus].m_nMoney += 250000;\n\tCHud::SetHelpMessage(TheText.Get(\"CHEAT6\"), true);\n}\n\nvoid ArmourCheat()\n{\n\tCHud::SetHelpMessage(TheText.Get(\"CHEAT4\"), true);\n\tFindPlayerPed()->m_fArmour = CWorld::Players[0].m_nMaxArmour;\n}\n\nvoid WantedLevelUpCheat()\n{\n\tCHud::SetHelpMessage(TheText.Get(\"CHEAT5\"), true);\n\tFindPlayerPed()->m_pWanted->CheatWantedLevel(Min(FindPlayerPed()->m_pWanted->GetWantedLevel() + 2, 6));\n}\n\nvoid WantedLevelDownCheat()\n{\n\tCHud::SetHelpMessage(TheText.Get(\"CHEAT5\"), true);\n\tFindPlayerPed()->m_pWanted->CheatWantedLevel(0);\n}\n\nvoid SunnyWeatherCheat()\n{\n\tCHud::SetHelpMessage(TheText.Get(\"CHEAT7\"), true);\n\tCWeather::ForceWeatherNow(WEATHER_SUNNY);\n}\n\nvoid ExtraSunnyWeatherCheat()\n{\n\tCHud::SetHelpMessage(TheText.Get(\"CHEAT7\"), true);\n\tCWeather::ForceWeatherNow(WEATHER_EXTRA_SUNNY);\n}\n\nvoid CloudyWeatherCheat()\n{\n\tCHud::SetHelpMessage(TheText.Get(\"CHEAT7\"), true);\n\tCWeather::ForceWeatherNow(WEATHER_CLOUDY);\n}\n\nvoid RainyWeatherCheat()\n{\n\tCHud::SetHelpMessage(TheText.Get(\"CHEAT7\"), true);\n\tCWeather::ForceWeatherNow(WEATHER_RAINY);\n}\n\nvoid FoggyWeatherCheat()\n{\n\tCHud::SetHelpMessage(TheText.Get(\"CHEAT7\"), true);\n\tCWeather::ForceWeatherNow(WEATHER_FOGGY);\n}\n\nvoid FastWeatherCheat()\n{\n\tCHud::SetHelpMessage(TheText.Get(\"CHEAT1\"), true);\n\tgbFastTime = !gbFastTime;\n}\n\nvoid OnlyRenderWheelsCheat()\n{\n\tCHud::SetHelpMessage(TheText.Get(\"CHEAT1\"), true);\n\tCVehicle::bWheelsOnlyCheat = !CVehicle::bWheelsOnlyCheat;\n\tCStats::CheatedCount += 1000;\n\tCPad::bHasPlayerCheated = true;\n}\n\nvoid ChittyChittyBangBangCheat()\n{\n#ifdef BETTER_ALLCARSAREDODO_CHEAT\n\tCHud::SetHelpMessage(TheText.Get(!CVehicle::bAllDodosCheat ? \"CHEAT1\" : \"CHEATOF\"), true);\n#else\n\tCHud::SetHelpMessage(TheText.Get(\"CHEAT1\"), true);\n#endif\n\tCVehicle::bAllDodosCheat = !CVehicle::bAllDodosCheat;\n\tCStats::CheatedCount += 1000;\n\tCPad::bHasPlayerCheated = true;\n}\n\nvoid StrongGripCheat()\n{\n\tCHud::SetHelpMessage(TheText.Get(\"CHEAT1\"), true);\n\tCVehicle::bCheat3 = !CVehicle::bCheat3;\n\tCStats::CheatedCount += 1000;\n\tCPad::bHasPlayerCheated = true;\n}\n\nvoid FannyMagnetCheat()\n{\n\tCHud::SetHelpMessage(TheText.Get(\"CHEAT1\"), true);\n\tCPed::bFannyMagnetCheat = !CPed::bFannyMagnetCheat;\n\tCPad::bHasPlayerCheated = true;\n}\n\nvoid BlackCarsCheat()\n{\n\tCHud::SetHelpMessage(TheText.Get(\"CHEAT1\"), true);\n\tgbBlackCars = true;\n\tgbPinkCars = false;\n}\n\nvoid PinkCarsCheat()\n{\n\tCHud::SetHelpMessage(TheText.Get(\"CHEAT1\"), true);\n\tgbBlackCars = false;\n\tgbPinkCars = true;\n}\n\nvoid TrafficLightsCheat()\n{\n\tCHud::SetHelpMessage(TheText.Get(\"CHEAT1\"), true);\n\tCTrafficLights::bGreenLightsCheat = true;\n}\n\nvoid MadCarsCheat()\n{\n\tCHud::SetHelpMessage(TheText.Get(\"CHEAT1\"), true);\n\tCCarCtrl::bMadDriversCheat = true;\n}\n\nvoid NoSeaBedCheat(void)\n{\n\tCHud::SetHelpMessage(TheText.Get(\"CHEAT1\"), true);\n\tCWaterLevel::m_bRenderSeaBed = !CWaterLevel::m_bRenderSeaBed;\n}\n\nvoid RenderWaterLayersCheat(void)\n{\n\tCHud::SetHelpMessage(TheText.Get(\"CHEAT1\"), true);\n\tif ( ++CWaterLevel::m_nRenderWaterLayers > 5 )\n\t\t\tCWaterLevel::m_nRenderWaterLayers = 0;\n}\n\nvoid BackToTheFuture(void)\n{\n\tCHud::SetHelpMessage(TheText.Get(\"CHEAT1\"), true);\n\tCVehicle::bHoverCheat = !CVehicle::bHoverCheat;\n\tCPad::bHasPlayerCheated = true;\n}\n\nvoid SuicideCheat(void) {\n\tCHud::SetHelpMessage(TheText.Get(\"CHEAT1\"), true);\n\tFindPlayerPed()->InflictDamage(nil, WEAPONTYPE_UNARMED, 1000.0f, PEDPIECE_TORSO, 0);\n}\n\nvoid DoChicksWithGunsCheat(void) {\n\tCHud::SetHelpMessage(TheText.Get(\"CHEAT1\"), true);\n\tCStreaming::SetModelIsDeletable(CGangs::GetGangPedModel1(GANG_PLAYER));\n\tCStreaming::SetModelIsDeletable(CGangs::GetGangPedModel2(GANG_PLAYER));\n\tCStreaming::SetModelTxdIsDeletable(CGangs::GetGangPedModel1(GANG_PLAYER));\n\tCStreaming::SetModelTxdIsDeletable(CGangs::GetGangPedModel2(GANG_PLAYER));\n\tCStreaming::RemoveCurrentZonesModels();\n\tCGangs::SetGangPedModels(GANG_PLAYER, MI_HFYBE, MI_WFYBE);\n\tCGangs::SetGangWeapons(GANG_PLAYER, WEAPONTYPE_M4, WEAPONTYPE_M4);\n\tCStats::CheatedCount += 1000;\n\tCPad::bHasPlayerCheated = true;\n}\n\n//////////////////////////////////////////////////////////////////////////\n\n#ifdef KANGAROO_CHEAT\nvoid KangarooCheat()\n{\n\twchar *string;\n\tCPed *playerPed = FindPlayerPed();\n\tint m_fMass;\n\n\tif (playerPed->m_ped_flagI80) {\n\t\tstring = TheText.Get(\"CHEATOF\");\n\t\tm_fMass = 70.0f;\n\t} else {\n\t\tstring = TheText.Get(\"CHEAT1\");\n\t\tm_fMass = 15.0f;\n\t}\n\tCHud::SetHelpMessage(string, true);\n\tplayerPed->m_ped_flagI80 = !playerPed->m_ped_flagI80;\n\n\tplayerPed->m_fMass = m_fMass;\n\tplayerPed->m_fAirResistance = 0.4f / m_fMass;\n}\n#endif\n\n#ifdef RESTORE_ALLCARSHELI_CHEAT\nvoid AllCarsHeliCheat(void)\n{\n\twchar* string;\n\tif (bAllCarCheat) {\n\t\tstring = TheText.Get(\"CHEATOF\");\n\t\tbAllCarCheat = false;\n\t}\n\telse {\n\t\tstring = TheText.Get(\"CHEAT1\");\n\t\tbAllCarCheat = true;\n\t}\n\tCHud::SetHelpMessage(string, true);\n}\n#endif\n\n#ifdef WALLCLIMB_CHEAT\nvoid WallClimbingCheat(void)\n{\n\twchar* string;\n\tif (gGravityCheat) {\n\t\tstring = TheText.Get(\"CHEATOF\");\n\t\tgGravityCheat = false;\n\t}\n\telse {\n\t\tstring = TheText.Get(\"CHEAT1\");\n\t\tgGravityCheat = true;\n\t}\n\tCHud::SetHelpMessage(string, true);\n}\n#endif\n\nvoid FlyingFishCheat(void)\n{\n\tCHud::SetHelpMessage(TheText.Get(\"CHEAT1\"), true);\n\tCVehicle::bCheat8 = !CVehicle::bCheat8;\n\tCPad::bHasPlayerCheated = true;\n}\n\nvoid DoShowChaseStatCheat(void) {\n\tCHud::SetHelpMessage(TheText.Get(\"CHEAT1\"), true);\n\tCStats::ShowChaseStatOnScreen = 1;\n}\n\nbool\nCControllerState::CheckForInput(void)\n{\n\treturn !!RightStickX || !!RightStickY || !!LeftStickX || !!LeftStickY\n\t\t|| !!DPadUp || !!DPadDown || !!DPadLeft || !!DPadRight\n\t\t|| !!Triangle || !!Cross || !!Circle || !!Square\n\t\t|| !!Start || !!Select\n\t\t|| !!LeftShoulder1 || !!LeftShoulder2 || !!RightShoulder1 || !!RightShoulder2\n\t\t|| !!LeftShock || !!RightShock;\n}\n\nvoid\nCControllerState::Clear(void)\n{\n\tLeftStickX = LeftStickY = RightStickX = RightStickY = 0;\n\tLeftShoulder1 = LeftShoulder2 = RightShoulder1 = RightShoulder2 = 0;\n\tDPadUp = DPadDown = DPadLeft = DPadRight = 0;\n\tStart = Select = 0;\n\tSquare = Triangle = Cross = Circle = 0;\n\tLeftShock = RightShock = 0;\n\tNetworkTalk = 0;\n}\n\nvoid CKeyboardState::Clear()\n{\n\tfor ( int32 i = 0; i < ARRAY_SIZE(F); i++\t)\n\t\tF[i] = 0;\n\n\tfor ( int32 i = 0; i < ARRAY_SIZE(VK_KEYS); i++\t )\n\t\tVK_KEYS[i] = 0;\n\n\tESC = INS = DEL = HOME = END = PGUP = PGDN = 0;\n\n\tUP = DOWN = LEFT = RIGHT = 0;\n\n\tNUMLOCK = 0;\n\n\tDIV = MUL = SUB = ADD = 0;\n\n\tDECIMAL = NUM1 = NUM2 = NUM3 = NUM4 = 0;\n\n\tNUM5 = NUM6 = NUM7 = NUM8 = 0;\n\n\tNUM9 = NUM0 = SCROLLLOCK = PAUSE = 0;\n\n\tBACKSP = TAB = CAPSLOCK = EXTENTER = 0;\n\n\tLSHIFT = SHIFT = RSHIFT = LCTRL = RCTRL = LALT = RALT = 0;\n\n\tLWIN = RWIN = APPS = 0;\n}\n\n#ifdef GTA_PS2_STUFF\nvoid CPad::Initialise(void)\n{\n#ifdef GTA_PS2\n\tscePadInit(0);\n\n\tscePadPortOpen(0, 0, pad_dma_buf );\n\tscePadPortOpen(1, 0, pad2_dma_buf );\n#endif\n\tfor (int i = 0; i < MAX_PADS; i++)\n\t{\n\t\tCPad::GetPad(i)->Clear(true);\n\t\tCPad::GetPad(i)->Mode = 0;\n\t}\n\n\tbObsoleteControllerMessage\t   = false;\n\tbOldDisplayNoControllerMessage = false;\n\tbDisplayNoControllerMessage\t   = false;\n\tm_bMapPadOneToPadTwo = false;\n\tm_bDebugCamPCOn = false;\n}\n#endif\n\nvoid CPad::Clear(bool bResetPlayerControls)\n{\n\tNewState.Clear();\n\tOldState.Clear();\n\n\tPCTempKeyState.Clear();\n\tPCTempJoyState.Clear();\n\tPCTempMouseState.Clear();\n\n\tNewKeyState.Clear();\n\tOldKeyState.Clear();\n\tTempKeyState.Clear();\n\n\tNewMouseControllerState.Clear();\n\tOldMouseControllerState.Clear();\n\tPCTempMouseControllerState.Clear();\n\n\tPhase = 0;\n\tShakeFreq = 0;\n\tShakeDur = 0;\n\n\tfor (int32 i = 0; i < DRUNK_STEERING_BUFFER_SIZE; i++)\n\t\tSteeringLeftRightBuffer[i] = 0;\n\n\tDrunkDrivingBufferUsed = 0;\n\n\tif ( bResetPlayerControls )\n\t\tDisablePlayerControls = PLAYERCONTROL_ENABLED;\n\n\tJustOutOfFrontend = 0;\n\tbApplyBrakes = false;\n\n\tfor ( int32 i = 0; i < HORNHISTORY_SIZE; i++ )\n\t\tbHornHistory[i] = false;\n\n\tiCurrHornHistory = 0;\n\n\tfor ( int32 i = 0; i < ARRAY_SIZE(CheatString); i++ )\n\t\tCheatString[i] = ' ';\n\n\tLastTimeTouched = CTimer::GetTimeInMilliseconds();\n\tAverageWeapon = 0;\n\tAverageEntries = 0;\n}\n\nuint32 CPad::InputHowLongAgo()\n{\n\treturn CTimer::GetTimeInMilliseconds() - LastTimeTouched;\n}\n\nvoid CPad::ClearMouseHistory()\n{\n\tPCTempMouseControllerState.Clear();\n\tNewMouseControllerState.Clear();\n\tOldMouseControllerState.Clear();\n}\n\n// unused\nvoid CPad::ClearKeyBoardHistory()\n{\n\tNewKeyState.Clear();\n\tOldKeyState.Clear();\n\tTempKeyState.Clear();\n}\n\nCMouseControllerState::CMouseControllerState()\n{\n\tLMB = 0;\n\tRMB = 0;\n\tMMB = 0;\n\tWHEELUP = 0;\n\tWHEELDN = 0;\n\tMXB1 = 0;\n\tMXB2 = 0;\n\n\tx = 0.0f;\n\ty = 0.0f;\n}\n\nvoid CMouseControllerState::Clear()\n{\n\tLMB = 0;\n\tRMB = 0;\n\tMMB = 0;\n\tWHEELUP = 0;\n\tWHEELDN = 0;\n\tMXB1 = 0;\n\tMXB2 = 0;\n}\n\nCMouseControllerState CMousePointerStateHelper::GetMouseSetUp()\n{\n\tCMouseControllerState state;\n\n#if defined RW_D3D9 || defined RWLIBS\n\tif ( PSGLOBAL(mouse) == nil )\n\t\t_InputInitialiseMouse(!FrontEndMenuManager.m_bMenuActive && _InputMouseNeedsExclusive());\n\n\tif ( PSGLOBAL(mouse) != nil )\n\t{\n\t\tDIDEVCAPS devCaps;\n\t\tdevCaps.dwSize = sizeof(DIDEVCAPS);\n\n\t\tPSGLOBAL(mouse)->GetCapabilities(&devCaps);\n\t\tswitch ( devCaps.dwButtons )\n\t\t{\n\t\t\tcase 3:\n\t\t\tcase 4:\n\t\t\tcase 5:\n\t\t\tcase 6:\n\t\t\tcase 7:\n\t\t\tcase 8:\n\t\t\t\tstate.MMB = true;\n\n\t\t\tcase 2:\n\t\t\t\tstate.RMB = true;\n\n\t\t\tcase 1:\n\t\t\t\tstate.LMB = true;\n\t\t}\n\n\t\tif ( devCaps.dwAxes == 3 )\n\t\t{\n\t\t\tstate.WHEELDN = true;\n\t\t\tstate.WHEELUP = true;\n\t\t}\n\t}\n#else\n\t// It seems there is no way to get number of buttons on mouse, so assign all buttons if we have mouse.\n\tdouble xpos = 1.0f, ypos;\n\tglfwGetCursorPos(PSGLOBAL(window), &xpos, &ypos);\n\n\tif (xpos != 0.f) {\n\t\tstate.MMB = true;\n\t\tstate.RMB = true;\n\t\tstate.LMB = true;\n\t\tstate.WHEELDN = true;\n\t\tstate.WHEELUP = true;\n\t}\n#endif\n\n\treturn state;\n}\n\nvoid CPad::UpdateMouse()\n{\n#if defined RW_D3D9 || defined RWLIBS\n\tif ( IsForegroundApp() )\n\t{\n\t\tif ( PSGLOBAL(mouse) == nil )\n\t\t\t_InputInitialiseMouse(!FrontEndMenuManager.m_bMenuActive && _InputMouseNeedsExclusive());\n\n\t\tDIMOUSESTATE2 state;\n\n\t\tif ( PSGLOBAL(mouse) != nil && SUCCEEDED(_InputGetMouseState(&state)) )\n\t\t{\n\t\t\tint32 signX = 1;\n\t\t\tint32 signy = 1;\n\n\t\t\tif ( !FrontEndMenuManager.m_bMenuActive )\n\t\t\t{\n\t\t\t\tif ( MousePointerStateHelper.bInvertVertically )\n\t\t\t\t\tsigny = -1;\n\t\t\t\tif ( MousePointerStateHelper.bInvertHorizontally )\n\t\t\t\t\tsignX = -1;\n\t\t\t}\n\n\t\t\tPCTempMouseControllerState.Clear();\n\n\t\t\tPCTempMouseControllerState.x = (float)(signX * state.lX);\n\t\t\tPCTempMouseControllerState.y = (float)(signy * state.lY);\n\t\t\tPCTempMouseControllerState.LMB = state.rgbButtons[0] & 128;\n\t\t\tPCTempMouseControllerState.RMB = state.rgbButtons[1] & 128;\n\t\t\tPCTempMouseControllerState.MMB = state.rgbButtons[2] & 128;\n\t\t\tPCTempMouseControllerState.MXB1 = state.rgbButtons[3] & 128;\n\t\t\tPCTempMouseControllerState.MXB2 = state.rgbButtons[4] & 128;\n\n\t\t\tif ( state.lZ > 0 )\n\t\t\t\tPCTempMouseControllerState.WHEELUP = 1;\n\t\t\telse if ( state.lZ < 0 )\n\t\t\t\tPCTempMouseControllerState.WHEELDN = 1;\n\n\t\t\tOldMouseControllerState = NewMouseControllerState;\n\t\t\tNewMouseControllerState = PCTempMouseControllerState;\n\t\t}\n\t}\n#else\n\tif ( IsForegroundApp() && PSGLOBAL(cursorIsInWindow) )\n\t{\n\t\tdouble xpos = 1.0f, ypos;\n\t\tglfwGetCursorPos(PSGLOBAL(window), &xpos, &ypos);\n\t\tif (xpos == 0.f)\n\t\t\treturn;\n\n\t\tint32 signX = 1;\n\t\tint32 signy = 1;\n\n\t\tif (!FrontEndMenuManager.m_bMenuActive)\n\t\t{\n\t\t\tif (MousePointerStateHelper.bInvertVertically)\n\t\t\t\tsigny = -1;\n\t\t\tif (MousePointerStateHelper.bInvertHorizontally)\n\t\t\t\tsignX = -1;\n\t\t}\n\n\t\tPCTempMouseControllerState.Clear();\n\n\t\tPCTempMouseControllerState.x = (float)(signX * (xpos - PSGLOBAL(lastMousePos.x)));\n\t\tPCTempMouseControllerState.y = (float)(signy * (ypos - PSGLOBAL(lastMousePos.y)));\n\t\tPCTempMouseControllerState.LMB = glfwGetMouseButton(PSGLOBAL(window), GLFW_MOUSE_BUTTON_LEFT);\n\t\tPCTempMouseControllerState.RMB = glfwGetMouseButton(PSGLOBAL(window), GLFW_MOUSE_BUTTON_RIGHT);\n\t\tPCTempMouseControllerState.MMB = glfwGetMouseButton(PSGLOBAL(window), GLFW_MOUSE_BUTTON_MIDDLE);\n\t\tPCTempMouseControllerState.MXB1 = glfwGetMouseButton(PSGLOBAL(window), GLFW_MOUSE_BUTTON_4);\n\t\tPCTempMouseControllerState.MXB2 = glfwGetMouseButton(PSGLOBAL(window), GLFW_MOUSE_BUTTON_5);\n\n\t\tif (PSGLOBAL(mouseWheel) > 0)\n\t\t\tPCTempMouseControllerState.WHEELUP = 1;\n\t\telse if (PSGLOBAL(mouseWheel) < 0)\n\t\t\tPCTempMouseControllerState.WHEELDN = 1;\n\n\t\tPSGLOBAL(lastMousePos.x) = xpos;\n\t\tPSGLOBAL(lastMousePos.y) = ypos;\n\t\tPSGLOBAL(mouseWheel) = 0.0f;\n\n\t\tOldMouseControllerState = NewMouseControllerState;\n\t\tNewMouseControllerState = PCTempMouseControllerState;\n\t}\n#endif\n}\n\nCControllerState CPad::ReconcileTwoControllersInput(CControllerState const &State1, CControllerState const &State2)\n{\n\tstatic CControllerState ReconState;\n\n\tReconState.Clear();\n\n#define _RECONCILE_BUTTON(button) \\\n\t{ if ( State1.button || State2.button ) ReconState.button = 255; }\n\n#define _RECONCILE_AXIS_POSITIVE(axis) \\\n\t{ if ( State1.axis >= 0 && State2.axis >= 0 ) ReconState.axis = Max(State1.axis, State2.axis); }\n\n#define _RECONCILE_AXIS_NEGATIVE(axis) \\\n\t{ if ( State1.axis <= 0 && State2.axis <= 0 ) ReconState.axis = Min(State1.axis, State2.axis); }\n\n#define _RECONCILE_AXIS(axis) \\\n\t{ _RECONCILE_AXIS_POSITIVE(axis); _RECONCILE_AXIS_NEGATIVE(axis); }\n\n#define _FIX_AXIS_DIR(axis) \\\n\t{ if ( State1.axis > 0 && State2.axis < 0 || State1.axis < 0 && State2.axis > 0 ) ReconState.axis = 0; }\n\n#define _FIX_RECON_DIR(pos, neg, axis) \\\n\t{ if ( (ReconState.pos || ReconState.axis < 0) && (ReconState.neg || ReconState.axis > 0) ) { ReconState.pos = 0; ReconState.neg = 0; ReconState.axis = 0; } }\n\n\t_RECONCILE_BUTTON(LeftShoulder1);\n\t_RECONCILE_BUTTON(LeftShoulder2);\n\t_RECONCILE_BUTTON(RightShoulder1);\n\t_RECONCILE_BUTTON(RightShoulder2);\n\t_RECONCILE_BUTTON(Start);\n\t_RECONCILE_BUTTON(Select);\n\t_RECONCILE_BUTTON(Square);\n\t_RECONCILE_BUTTON(Triangle);\n\t_RECONCILE_BUTTON(Cross);\n\t_RECONCILE_BUTTON(Circle);\n\t_RECONCILE_BUTTON(LeftShock);\n\t_RECONCILE_BUTTON(RightShock);\n\t_RECONCILE_BUTTON(NetworkTalk);\n\t_RECONCILE_AXIS(LeftStickX);\n\t_RECONCILE_AXIS(LeftStickY);\n\t_FIX_AXIS_DIR(LeftStickX);\n\t_FIX_AXIS_DIR(LeftStickY);\n\t_RECONCILE_AXIS(RightStickX);\n\t_RECONCILE_AXIS(RightStickY);\n\t_FIX_AXIS_DIR(RightStickX);\n\t_FIX_AXIS_DIR(RightStickY);\n\t_RECONCILE_BUTTON(DPadUp);\n\t_RECONCILE_BUTTON(DPadDown);\n\t_RECONCILE_BUTTON(DPadLeft);\n\t_RECONCILE_BUTTON(DPadRight);\n\t_FIX_RECON_DIR(DPadUp, DPadDown, LeftStickY);\n\t_FIX_RECON_DIR(DPadLeft, DPadRight, LeftStickX);\n\n\treturn ReconState;\n\n#undef _RECONCILE_BUTTON\n#undef _RECONCILE_AXIS_POSITIVE\n#undef _RECONCILE_AXIS_NEGATIVE\n#undef _RECONCILE_AXIS\n#undef _FIX_AXIS_DIR\n#undef _FIX_RECON_DIR\n}\n\nvoid CPad::StartShake(int16 nDur, uint8 nFreq)\n{\n\tif ( !FrontEndMenuManager.m_PrefsUseVibration )\n\t\treturn;\n\n\tif ( CCutsceneMgr::IsRunning() || CGame::playingIntro )\n\t\treturn;\n\n\tif ( nFreq == 0 )\n\t{\n\t\tShakeDur = 0;\n\t\tShakeFreq = 0;\n\t\treturn;\n\t}\n\n\tif ( nDur > ShakeDur )\n\t{\n\t\tShakeDur = nDur;\n\t\tShakeFreq = nFreq;\n\t}\n}\n\nvoid CPad::StartShake_Distance(int16 nDur, uint8 nFreq, float fX, float fY, float fZ)\n{\n\tif ( !FrontEndMenuManager.m_PrefsUseVibration )\n\t\treturn;\n\n\tif ( CCutsceneMgr::IsRunning() || CGame::playingIntro )\n\t\treturn;\n\n\tfloat fDist = ( TheCamera.GetPosition() - CVector(fX, fY, fZ) ).Magnitude();\n\n\tif ( fDist < 70.0f )\n\t{\n\t\tif ( nFreq == 0 )\n\t\t{\n\t\t\tShakeDur = 0;\n\t\t\tShakeFreq = 0;\n\t\t\treturn;\n\t\t}\n\n\t\tif ( nDur > ShakeDur )\n\t\t{\n\t\t\tShakeDur = nDur;\n\t\t\tShakeFreq = nFreq;\n\t\t}\n\t}\n}\n\nvoid CPad::StartShake_Train(float fX, float fY)\n{\n\tif ( !FrontEndMenuManager.m_PrefsUseVibration )\n\t\treturn;\n\n\tif ( CCutsceneMgr::IsRunning() || CGame::playingIntro )\n\t\treturn;\n\n\tif (FindPlayerVehicle() != nil && FindPlayerVehicle()->IsTrain() )\n\t\treturn;\n\n\tfloat fDist = ( TheCamera.GetPosition() - CVector(fX, fY, 0.0f) ).Magnitude2D();\n\n\tif ( fDist < 70.0f )\n\t{\n\t\tint32 freq = (int32)((70.0f - fDist) * 70.0f / 70.0f + 30.0f);\n\n\t\tif ( ShakeDur < 100 )\n\t\t{\n\t\t\tShakeDur = 100;\n\t\t\tShakeFreq = freq;\n\t\t}\n\t}\n}\n\n#ifdef GTA_PS2_STUFF\nvoid CPad::AddToCheatString(char c)\n{\n\tfor ( int32 i = ARRAY_SIZE(CheatString) - 2; i >= 0; i-- )\n\t\tCheatString[i + 1] = CheatString[i];\n\n\tCheatString[0] = c;\n\n#define _CHEATCMP(str)\tstrncmp(str, CheatString, sizeof(str)-1)\n\t// \"4414LDRULDRU\"\t-\tR2 R2 L1 R2 LEFT DOWN RIGHT UP LEFT DOWN RIGHT UP\n\tif ( !_CHEATCMP(\"URDLURDL4144\") )\n\t\tWeaponCheat1();\n\n\t// \"4411LDRULDRU\"\t-\tR2 R2 L1 L1 LEFT DOWN RIGHT UP LEFT DOWN RIGHT UP\n\telse if ( !_CHEATCMP(\"URDLURDL1144\") )\n\t\tMoneyCheat();\n\n\t// \"4412LDRULDRU\"\t-\tR2 R2 L1 L2 LEFT DOWN RIGHT UP LEFT DOWN RIGHT UP\n\telse if ( !_CHEATCMP(\"URDLURDL2144\") )\n\t\tArmourCheat();\n\n\t// \"4413LDRULDRU\"\t-\tR2 R2 L1 R1 LEFT DOWN RIGHT UP LEFT DOWN RIGHT UP\n\telse if ( !_CHEATCMP(\"URDLURDL3144\") )\n\t\tHealthCheat();\n\n\t// \"4414LRLRLR\"\t\t-\tR2 R2 L1 R2 LEFT RIGHT LEFT RIGHT LEFT RIGHT\n\telse if ( !_CHEATCMP(\"RLRLRL4144\") )\n\t\tWantedLevelUpCheat();\n\n\t// \"4414UDUDUD\"\t\t-\tR2 R2 L1 R2 UP DOWN UP DOWN UP DOWN\n\telse if ( !_CHEATCMP(\"DUDUDU4144\") )\n\t\tWantedLevelDownCheat();\n\n\t// \"1234432T\"\t\t-\tL1 L2 R1 R2 R2 R1 L2 TRIANGLE\n\telse if ( !_CHEATCMP(\"T2344321\") )\n\t\tSunnyWeatherCheat();\n\n\t// \"1234432S\"\t\t-\tL1 L2 R1 R2 R2 R1 L2 SQUARE\n\telse if ( !_CHEATCMP(\"S2344321\") )\n\t\tCloudyWeatherCheat();\n\n\t// \"1234432C\"\t\t-\tL1 L2 R1 R2 R2 R1 L2 CIRCLE\n\telse if ( !_CHEATCMP(\"C2344321\") )\n\t\tRainyWeatherCheat();\n\n\t// \"1234432X\"\t\t-\tL1 L2 R1 R2 R2 R1 L2 CROSS\n\telse if ( !_CHEATCMP(\"X2344321\") )\n\t\tFoggyWeatherCheat();\n\n\t// \"CCCCCC321TCT\"\t-\tCIRCLE CIRCLE CIRCLE CIRCLE CIRCLE CIRCLE R1 L2 L1 TRIANGLE CIRCLE TRIANGLE\n\telse if ( !_CHEATCMP(\"TCT123CCCCCC\") )\n\t\tVehicleCheat(MI_RHINO);\n\n\t// \"CCCSSSSS1TCT\"\t-\tCIRCLE CIRCLE CIRCLE SQUARE SQUARE SQUARE SQUARE SQUARE L1 TRIANGLE CIRCLE TRIANGLE\n\telse if ( !_CHEATCMP(\"TCT1SSSSSCCC\") )\n\t\tFastWeatherCheat();\n\n\t// \"241324TSCT21\"\t-\tL2 R2 L1 R1 L2 R2 TRIANGLE SQUARE CIRCLE TRIANGLE L2 L1\n\telse if ( !_CHEATCMP(\"12TCST423142\") )\n\t\tBlowUpCarsCheat();\n\n\t// \"RDLU12ULDR\"\t\t-\tRIGHT DOWN LEFT UP L1 L2 UP LEFT DOWN RIGHT\n\telse if ( !_CHEATCMP(\"RDLU21ULDR\") )\n\t\tChangePlayerCheat();\n\n\t// \"DULUX3421\"\t\t-\tDOWN UP LEFT UP CROSS R1 R2 L2 L1\n\telse if ( !_CHEATCMP(\"1243XULUD\") )\n\t\tMayhemCheat();\n\n\t// \"DULUX3412\"\t\t-\tDOWN UP LEFT UP CROSS R1 R2 L1 L2\n\telse if ( !_CHEATCMP(\"2143XULUD\") )\n\t\tEverybodyAttacksPlayerCheat();\n\n\t// \"43TX21UD\"\t\t-\tR2 R1 TRIANGLE CROSS L2 L1 UP DOWN\n\telse if ( !_CHEATCMP(\"DU12XT34\") )\n\t\tWeaponsForAllCheat();\n\n\t// \"TURDS12\"\t\t-\tTRIANGLE UP RIGHT DOWN SQUARE L1 L2\n\telse if ( !_CHEATCMP(\"21SDRUT\") )\n\t\tFastTimeCheat();\n\n\t// \"TURDS34\"\t\t-\tTRIANGLE UP RIGHT DOWN SQUARE R1 R2\n\telse if ( !_CHEATCMP(\"43SDRUT\") )\n\t\tSlowTimeCheat();\n\n\t// \"11S4T1T\"\t\t-\tL1 L1 SQUARE R2 TRIANGLE L1 TRIANGLE\n\telse if ( !_CHEATCMP(\"T1T4S11\") )\n\t\tOnlyRenderWheelsCheat();\n\n\t// \"R4C32D13\"\t\t-\tRIGHT R2 CIRCLE R1 L2 DOWN L1 R1\n\telse if ( !_CHEATCMP(\"31D23C4R\") )\n\t\tChittyChittyBangBangCheat();\n\n\t// \"3141L33T\"\t\t-\tR1 L1 R2 L1 LEFT R1 R1 TRIANGLE\n\telse if ( !_CHEATCMP(\"T33L1413\") )\n\t\tStrongGripCheat();\n\n#undef _CHEATCMP\n}\n#endif\n\nint Cheat_strncmp(char* sourceStr, char* origCheatStr)\n{\n#define ccmp(n) if((uint8)sourceStr[i] != (uint8)origCheatStr[i] - n) return 1;\n\tint i = 0;\n\twhile(origCheatStr[i])\n\t{\n\t\tswitch(i)\n\t\t{\n\t\tcase 0: ccmp(3); break;\n\t\tcase 1: ccmp(5); break;\n\t\tcase 2: ccmp(7); break;\n\t\tcase 3: ccmp(1); break;\n\t\tcase 4: ccmp(13); break;\n\t\tcase 5: ccmp(27); break;\n\t\tcase 6: ccmp(3); break;\n\t\tcase 7: ccmp(7); break;\n\t\tcase 8: ccmp(1); break;\n\t\tcase 9: ccmp(11); break;\n\t\tcase 10: ccmp(13); break;\n\t\tcase 11: ccmp(8); break;\n\t\tcase 12: ccmp(7); break;\n\t\tcase 13: ccmp(32); break;\n\t\tcase 14: ccmp(13); break;\n\t\tcase 15: ccmp(6); break;\n\t\tcase 16: ccmp(28); break;\n\t\tcase 17: ccmp(19); break;\n\t\tcase 18: ccmp(10); break;\n\t\tcase 19: ccmp(3); break;\n\t\tcase 20: ccmp(3); break;\n\t\tcase 21: ccmp(5); break;\n\t\tcase 22: ccmp(7); break;\n\t\tcase 23: ccmp(1); break;\n\t\tcase 24: ccmp(13); break;\n\t\tcase 25: ccmp(27); break;\n\t\tcase 26: ccmp(3); break;\n\t\tcase 27: ccmp(7); break;\n\t\tdefault: return 1;\n\t\t}\n\t\ti++;\n\t}\n\treturn 0;\n#undef ccmp\n}\n\n// TODO(Miami): Mobile has changed some of the cheats to include debugging things\nvoid CPad::AddToPCCheatString(char c)\n{\n\tfor (int32 i = ARRAY_SIZE(KeyBoardCheatString) - 2; i >= 0; i--)\n\t\tKeyBoardCheatString[i + 1] = KeyBoardCheatString[i];\n\n\tKeyBoardCheatString[0] = c;\n\n#define _CHEATCMP(str) strncmp(str, KeyBoardCheatString, sizeof(str)-1)\n\n\t// \"THUGSTOOLS\"\n\tif (!Cheat_strncmp(KeyBoardCheatString, \"VQVPanJ\\\\I_\")) {\n\t\tKeyBoardCheatString[0] = ' ';\n\t\tWeaponCheat1();\n\t}\n\t// \"PROFESSIONALTOOLS\"\n\telse if (!Cheat_strncmp(KeyBoardCheatString, \"VQVPagDUPT`[Lf\\\\Xl\")) {\n\t\tKeyBoardCheatString[0] = ' ';\n\t\tWeaponCheat2();\n\t}\n\t// \"NUTTERTOOLS\"\n\telse if (!Cheat_strncmp(KeyBoardCheatString, \"VQVPamH[U`[\")) {\n\t\tKeyBoardCheatString[0] = ' ';\n\t\tWeaponCheat3();\n\t}\n\t// \"PRECIOUSPROTECTION\"\n\telse if (!Cheat_strncmp(KeyBoardCheatString, \"QTPUP`WVS[`]ViPKnc\")) {\n\t\tKeyBoardCheatString[0] = ' ';\n\t\tArmourCheat();\n\t}\n\t// \"ASPIRINE\"\n\telse if (!Cheat_strncmp(KeyBoardCheatString, \"HSPSVkVH\")) {\n\t\tKeyBoardCheatString[0] = ' ';\n\t\tHealthCheat();\n\t}\n\t// \"YOUWONTTAKEMEALIVE\"\n\telse if (!Cheat_strncmp(KeyBoardCheatString, \"H[PMN`PLLLa\\\\Uod[kl\")) {\n\t\tKeyBoardCheatString[0] = ' ';\n\t\tWantedLevelUpCheat();\n\t}\n\t// \"LEAVEMEALONE\"\n\telse if (!Cheat_strncmp(KeyBoardCheatString, \"HSVMN`PLWLRT\")) {\n\t\tKeyBoardCheatString[0] = ' ';\n\t\tWantedLevelDownCheat();\n\t}\n\t// \"APLEASANTDAY\"\n\telse if (!Cheat_strncmp(KeyBoardCheatString, \"\\\\FKU[\\\\VHFW]I\")) {\n\t\tKeyBoardCheatString[0] = ' ';\n\t\tSunnyWeatherCheat();\n\t}\n\t// \"ALOVELYDAY\"\n\telse if (!Cheat_strncmp(KeyBoardCheatString, \"\\\\FKZY`YVML\")) {\n\t\tKeyBoardCheatString[0] = ' ';\n\t\tExtraSunnyWeatherCheat();\n\t}\n\t// \"ABITDRIEG\"\n\telse if (!Cheat_strncmp(KeyBoardCheatString, \"JJPSQoLIB\")) {\n\t\tKeyBoardCheatString[0] = ' ';\n\t\tCloudyWeatherCheat();\n\t}\n\t// \"CATSANDDOGS\"\n\telse if (!Cheat_strncmp(KeyBoardCheatString, \"VLVEQiDZULP\")) {\n\t\tKeyBoardCheatString[0] = ' ';\n\t\tRainyWeatherCheat();\n\t}\n\t// \"CANTSEEATHING\"\n\telse if (!Cheat_strncmp(KeyBoardCheatString, \"JSPIa\\\\HLT_[IJ\")) {\n\t\tKeyBoardCheatString[0] = ' ';\n\t\tFoggyWeatherCheat();\n\t}\n\t// \"PANZER\"\n\telse if (!Cheat_strncmp(KeyBoardCheatString, \"UJaONk\")) {\n\t\tKeyBoardCheatString[0] = ' ';\n\t\tVehicleCheat(MI_RHINO);\n\t}\n\t// \"LIFEISPASSINGMEBY\"\n\telse if (!Cheat_strncmp(KeyBoardCheatString, \"\\\\GLNTiLZTL][PeSOh\")) {\n\t\tKeyBoardCheatString[0] = ' ';\n\t\tFastWeatherCheat();\n\t}\n\t// \"BIGBANG\"\n\telse if (!Cheat_strncmp(KeyBoardCheatString, \"JSHCTdE\")) {\n\t\tKeyBoardCheatString[0] = ' ';\n\t\tBlowUpCarsCheat();\n\t}\n\t// \"STILLLIKEDRESSINGUP\"\n\telse if (!Cheat_strncmp(KeyBoardCheatString, \"SZNOVnVLSORSPlYReg]\")) {\n\t\tKeyBoardCheatString[0] = ' ';\n\t\tChangePlayerCheat();\n\t}\n\t// \"FIGHTFIGHTFIGHT\"\n\telse if (!Cheat_strncmp(KeyBoardCheatString, \"WMNJSoKNJQaPNiS\")) {\n\t\tKeyBoardCheatString[0] = ' ';\n\t\tMayhemCheat();\n\t}\n\t// \"NOBODYLIKESME\"\n\telse if (!Cheat_strncmp(KeyBoardCheatString, \"HRZFXdO`EZOWU\")) {\n\t\tKeyBoardCheatString[0] = ' ';\n\t\tEverybodyAttacksPlayerCheat();\n\t}\n\t// \"OURGODGIVENRIGHTTOBEARARMS\"\n\telse if (!Cheat_strncmp(KeyBoardCheatString, \"VRYB_\\\\HIP_aPNi_TaiSJGTNSbj\")) {\n\t\tKeyBoardCheatString[0] = ' ';\n\t\tWeaponsForAllCheat();\n\t}\n\t// \"ONSPEED\"\n\telse if (!Cheat_strncmp(KeyBoardCheatString, \"GJLQ`iR\")) {\n\t\tKeyBoardCheatString[0] = ' ';\n\t\tFastTimeCheat();\n\t}\n\t// \"BOOOOOORING\"\n\telse if (!Cheat_strncmp(KeyBoardCheatString, \"JSPS\\\\jRVPZO\")) {\n\t\tKeyBoardCheatString[0] = ' ';\n\t\tSlowTimeCheat();\n\t}\n\t// \"WHEELSAREALLINEED\"\n\telse if (!Cheat_strncmp(KeyBoardCheatString, \"GJLOVgOHF]N[SeRNs\")) {\n\t\tKeyBoardCheatString[0] = ' ';\n\t\tOnlyRenderWheelsCheat();\n\t}\n\t//COMEFLYWITHME\n\telse if (!Cheat_strncmp(KeyBoardCheatString, \"HROUVr\\\\SGPZWJ\")) {\n\t\tKeyBoardCheatString[0] = ' ';\n\t\tChittyChittyBangBangCheat();\n\t}\n\t// \"GRIPISEVERYTHING\"\n\telse if (!Cheat_strncmp(KeyBoardCheatString, \"JSPIatULWP`QWi_M\")) {\n\t\tKeyBoardCheatString[0] = ' ';\n\t\tStrongGripCheat();\n\t}\n\t// \"CHASESTAT\"\n\telse if (!Cheat_strncmp(KeyBoardCheatString, \"WF[TRnDOD\")) {\n\t\tKeyBoardCheatString[0] = ' ';\n\t\tDoShowChaseStatCheat();\n\t}\n\t// \"CHICKSWITHGUNS\"\n\telse if (!Cheat_strncmp(KeyBoardCheatString, \"VS\\\\HUoL^TVPQOc\")) {\n\t\tKeyBoardCheatString[0] = ' ';\n\t\tDoChicksWithGunsCheat();\n\t}\n\t// \"ICANTTAKEITANYMORE\"\n\telse if (!Cheat_strncmp(KeyBoardCheatString, \"HWVNfiD[JPXI[t[G_\\\\\")) {\n\t\tKeyBoardCheatString[0] = ' ';\n\t\tSuicideCheat();\n\t}\n\t// \"GREENLIGHT\"\n\telse if (!Cheat_strncmp(KeyBoardCheatString, \"WMNJYiHLSR\")) {\n\t\tKeyBoardCheatString[0] = ' ';\n\t\tTrafficLightsCheat();\n\t}\n\t// \"MIAMITRAFFIC\"\n\telse if (!Cheat_strncmp(KeyBoardCheatString, \"FNMGNmWPNLVU\")) {\n\t\tKeyBoardCheatString[0] = ' ';\n\t\tMadCarsCheat();\n\t}\n\t// \"AHAIRDRESSERSCAR\"\n\telse if (!Cheat_strncmp(KeyBoardCheatString, \"UFJT_`VZF]QZPaUG\")) {\n\t\tKeyBoardCheatString[0] = ' ';\n\t\tPinkCarsCheat();\n\t}\n\t// \"IWANTITPAINTEDBLACK\"\n\telse if (!Cheat_strncmp(KeyBoardCheatString, \"NHHMO_H[OTNX[iaT]jS\")) {\n\t\tKeyBoardCheatString[0] = ' ';\n\t\tBlackCarsCheat();\n\t}\n\t// \"TRAVELINSTYLE\"\n\telse if (!Cheat_strncmp(KeyBoardCheatString, \"HQ`U`iLSFaNZ[\")) {\n\t\tKeyBoardCheatString[0] = ' ';\n\t\tVehicleCheat(MI_BLOODRA);\n\t}\n\t// \"THELASTRIDE\"\n\telse if (!Cheat_strncmp(KeyBoardCheatString, \"HIPSanDSFSa\")) {\n\t\tKeyBoardCheatString[0] = ' ';\n\t\tVehicleCheat(MI_ROMERO);\n\t}\n\t// \"ROCKANDROLLCAR\"\n\telse if (!Cheat_strncmp(KeyBoardCheatString, \"UFJMYjUKOLXKVr\")) {\n\t\tKeyBoardCheatString[0] = ' ';\n\t\tVehicleCheat(MI_LOVEFIST);\n\t}\n\t// \"RUBBISHCAR\"\n\telse if (!Cheat_strncmp(KeyBoardCheatString, \"UFJI`dEIV]\")) {\n\t\tKeyBoardCheatString[0] = ' ';\n\t\tVehicleCheat(MI_TRASH);\n\t}\n\t// \"GETTHEREQUICKLY\"\n\telse if (!Cheat_strncmp(KeyBoardCheatString, \"\\\\QRDVpTLSPU\\\\[eT\")) {\n\t\tKeyBoardCheatString[0] = ' ';\n\t\tVehicleCheat(MI_BLOODRB);\n\t}\n\t// \"GETTHEREFAST\"\n\telse if (!Cheat_strncmp(KeyBoardCheatString, \"WXHGRmHOU_RO\")) {\n\t\tKeyBoardCheatString[0] = ' ';\n\t\tVehicleCheat(MI_SABRETUR);\n\t}\n\t// \"BETTERTHANWALKING\"\n\telse if (!Cheat_strncmp(KeyBoardCheatString, \"JSPLY\\\\ZUBSaZLtaK^\")) {\n\t\tKeyBoardCheatString[0] = ' ';\n\t\tVehicleCheat(MI_CADDY);\n\t}\n\t// \"GETTHEREFASTINDEED\"\n\telse if (!Cheat_strncmp(KeyBoardCheatString, \"GJLE[dWZBQfZLvRXa[^WHL\")) {\n\t\tKeyBoardCheatString[0] = ' ';\n\t\tVehicleCheat(MI_HOTRINA);\n\t}\n\t// \"GETTHEREAMAZINGLYFAST\"\n\telse if (!Cheat_strncmp(KeyBoardCheatString, \"WXHGfgJUJeNUHe_Kdg^HJ\")) {\n\t\tKeyBoardCheatString[0] = ' ';\n\t\tVehicleCheat(MI_HOTRINB);\n\t}\n\t// LOOKLIKELANCE\n\telse if (!Cheat_strncmp(KeyBoardCheatString, \"HHUBY`NPMV\\\\WS\")) {\n\t\tKeyBoardCheatString[0] = ' ';\n\t\tChangePlayerModel(\"igbuddy\");\n\t}\n\t// IWANTBIGTITS\n\telse if (!Cheat_strncmp(KeyBoardCheatString, \"VYPUTdE[OLdQ\")) {\n\t\tKeyBoardCheatString[0] = ' ';\n\t\tChangePlayerModel(\"igcandy\");\n\t}\n\t// MYSONISALAWYER\n\telse if (!Cheat_strncmp(KeyBoardCheatString, \"UJ`XNgDZJY\\\\[`m\")) {\n\t\tKeyBoardCheatString[0] = ' ';\n\t\tChangePlayerModel(\"igken\");\n\t}\n\t// ILOOKLIKEHILARY\n\telse if (!Cheat_strncmp(KeyBoardCheatString, \"\\\\WHMVcHRJWXWVlV\")) {\n\t\tKeyBoardCheatString[0] = ' ';\n\t\tChangePlayerModel(\"ighlary\");\n\t}\n\t// ROCKANDROLLMAN\n\telse if (!Cheat_strncmp(KeyBoardCheatString, \"QFTMYjUKOLXKVr\")) {\n\t\tKeyBoardCheatString[0] = ' ';\n\t\tChangePlayerModel(\"igjezz\");\n\t}\n\t// ONEARMEDBANDIT\n\telse if (!Cheat_strncmp(KeyBoardCheatString, \"WNKON]GLN]NMUo\")) {\n\t\tKeyBoardCheatString[0] = ' ';\n\t\tChangePlayerModel(\"igphil\");\n\t}\n\t// IDONTHAVETHEMONEYSONNY\n\telse if (!Cheat_strncmp(KeyBoardCheatString, \"\\\\SUP`tHUPXRP[ecGdgXRGN\")) {\n\t\tKeyBoardCheatString[0] = ' ';\n\t\tChangePlayerModel(\"igsonny\");\n\t}\n\t// FOXYLITTLETHING\n\telse if (!Cheat_strncmp(KeyBoardCheatString, \"JSPIa`O[UTYa_oS\")) {\n\t\tKeyBoardCheatString[0] = ' ';\n\t\tChangePlayerModel(\"igmerc\");\n\t}\n\t// WELOVEOURDICK\n\telse if (!Cheat_strncmp(KeyBoardCheatString, \"NHPE_pRLWZYM^\")) {\n\t\tKeyBoardCheatString[0] = ' ';\n\t\tChangePlayerModel(\"igdick\");\n\t}\n\t// CHEATSHAVEBEENCRACKED\n\telse if (!Cheat_strncmp(KeyBoardCheatString, \"GJRDNmFUFPOM]aUYpTOKF\")) {\n\t\tKeyBoardCheatString[0] = ' ';\n\t\tChangePlayerModel(\"igdiaz\");\n\t}\n\t// DEEPFRIEDMARSBARS\n\telse if (!Cheat_strncmp(KeyBoardCheatString, \"VWHC`mDTEPVZMpRK\")) {\n\t\tKeyBoardCheatString[0] = ' ';\n\t\tgfTommyFatness = 0.26f;\n\t}\n\t// PROGRAMMER\n\telse if (!Cheat_strncmp(KeyBoardCheatString, \"UJTNNmJVS[\")) {\n\t\tKeyBoardCheatString[0] = ' ';\n\t\tgfTommyFatness = -0.3f;\n\t}\n\t// SEAWAYS\n\telse if (!Cheat_strncmp(KeyBoardCheatString, \"V^HXN`V\")) {\n\t\tKeyBoardCheatString[0] = ' ';\n\t\tBackToTheFuture();\n\t}\n\t// LOADSOFLITTLETHINGS\n\telse if (!Cheat_strncmp(KeyBoardCheatString, \"VLUJUoHSU_VTMo`J]bV\")) {\n\t\tKeyBoardCheatString[0] = ' ';\n\t\tSpecialCarCheats();\n\t}\n\t// HOPINGIRL\n\telse if (!Cheat_strncmp(KeyBoardCheatString, \"OWPH[dSVI\")) {\n\t\tKeyBoardCheatString[0] = ' ';\n\t\tPickUpChicksCheat();\n\t}\n\t//CERTAINDEATH\n\telse if (!Cheat_strncmp(KeyBoardCheatString, \"KYHFQiLHU]RK\")) {\n\t\tKeyBoardCheatString[0] = ' ';\n\t\tCSmokeTrails::CigOn = !CSmokeTrails::CigOn;\n\t}\n\t//AIRSHIP\n\telse if (!Cheat_strncmp(KeyBoardCheatString, \"SNOT_dD\")) {\n\t\tKeyBoardCheatString[0] = ' ';\n\t\tFlyingFishCheat();\n\t}\n\t//FANNYMAGNET\n\telse if (!Cheat_strncmp(KeyBoardCheatString, \"WJUHNh\\\\UOLS\")) {\n\t\tKeyBoardCheatString[0] = ' ';\n\t\tFannyMagnetCheat();\n\t}\n\n#ifdef KANGAROO_CHEAT\n\t// \"KANGAROO\"\n\tif (!_CHEATCMP(\"OORAGNAK\"))\n\t\tKangarooCheat();\n#endif\n\n#ifndef MASTER\n\t// \"PEDDEBUG\"\n\tif (!_CHEATCMP(\"GUBEDDEP\"))\n\t\tCPed::SwitchDebugDisplay();\n#endif\n\n#ifdef RESTORE_ALLCARSHELI_CHEAT\n\t// \"CARSAREHELI\"\n\tif (!_CHEATCMP(\"ILEHERASRAC\"))\n\t\tAllCarsHeliCheat();\n#endif\n\n#ifdef WALLCLIMB_CHEAT\n\t// \"SPIDERCAR\"\n\tif (!_CHEATCMP(\"RACREDIPS\"))\n\t\tWallClimbingCheat();\n#endif\n\n#if !defined(PC_WATER) && defined(WATER_CHEATS)\n\t// SEABEDCHEAT\n\tif (!_CHEATCMP(\"TAEHCDEBAESON\"))\n\t\tNoSeaBedCheat();\n\n\t// WATERLAYERSCHEAT\n\tif (!_CHEATCMP(\"TAEHCSREYALRETAW\"))\n\t\tRenderWaterLayersCheat();\n#endif\n\n#undef _CHEATCMP\n}\n\n#ifdef XINPUT\nint CPad::XInputJoy1 = 0;\nint CPad::XInputJoy2 = 1;\nvoid CPad::AffectFromXinput(uint32 pad)\n{\n\tpad = pad == 0 ? XInputJoy1 : XInputJoy2;\n\tif (pad == -1) // LoadINIControllerSettings can set it to -1\n\t\treturn;\n\n\tXINPUT_STATE xstate;\n\tmemset(&xstate, 0, sizeof(XINPUT_STATE));\n\tif (XInputGetState(pad, &xstate) == ERROR_SUCCESS)\n\t{\n\t\tPCTempJoyState.Circle = (xstate.Gamepad.wButtons & XINPUT_GAMEPAD_B) ? 255 : 0;\n\t\tPCTempJoyState.Cross = (xstate.Gamepad.wButtons & XINPUT_GAMEPAD_A) ? 255 : 0;\n\t\tPCTempJoyState.Square = (xstate.Gamepad.wButtons & XINPUT_GAMEPAD_X) ? 255 : 0;\n\t\tPCTempJoyState.Triangle = (xstate.Gamepad.wButtons & XINPUT_GAMEPAD_Y) ? 255 : 0;\n\t\tPCTempJoyState.DPadDown = (xstate.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN) ? 255 : 0;\n\t\tPCTempJoyState.DPadLeft = (xstate.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT) ? 255 : 0;\n\t\tPCTempJoyState.DPadRight = (xstate.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT) ? 255 : 0;\n\t\tPCTempJoyState.DPadUp = (xstate.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP) ? 255 : 0;\n\t\tPCTempJoyState.LeftShock = (xstate.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_THUMB) ? 255 : 0;\n\t\tPCTempJoyState.LeftShoulder1 = (xstate.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_SHOULDER) ? 255 : 0;\n\t\tPCTempJoyState.LeftShoulder2 = xstate.Gamepad.bLeftTrigger;\n\t\tPCTempJoyState.RightShock = (xstate.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_THUMB) ? 255 : 0;\n\t\tPCTempJoyState.RightShoulder1 = (xstate.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_SHOULDER) ? 255 : 0;\n\t\tPCTempJoyState.RightShoulder2 = xstate.Gamepad.bRightTrigger;\n\n\t\tPCTempJoyState.Select = (xstate.Gamepad.wButtons & XINPUT_GAMEPAD_BACK) ? 255 : 0;\n#ifdef REGISTER_START_BUTTON\n\t\tPCTempJoyState.Start = (xstate.Gamepad.wButtons & XINPUT_GAMEPAD_START) ? 255 : 0;\n#endif\n\t\tfloat lx = (float)xstate.Gamepad.sThumbLX / (float)0x7FFF;\n\t\tfloat ly = (float)xstate.Gamepad.sThumbLY / (float)0x7FFF;\n\t\tfloat rx = (float)xstate.Gamepad.sThumbRX / (float)0x7FFF;\n\t\tfloat ry = (float)xstate.Gamepad.sThumbRY / (float)0x7FFF;\n\n\t\tif (Abs(lx) > 0.3f || Abs(ly) > 0.3f) {\n\t\t\tPCTempJoyState.LeftStickX = (int32)(lx * 128.0f);\n\t\t\tPCTempJoyState.LeftStickY = (int32)(-ly * 128.0f);\n\t\t}\n\n\t\tif (Abs(rx) > 0.3f || Abs(ry) > 0.3f) {\n\t\t\tPCTempJoyState.RightStickX = (int32)(rx * 128.0f);\n\t\t\tPCTempJoyState.RightStickY = (int32)(-ry * 128.0f);\n\t\t}\n\n\t\tXINPUT_VIBRATION VibrationState;\n\n\t\tmemset(&VibrationState, 0, sizeof(XINPUT_VIBRATION));\n\n\t\tuint16 iLeftMotor = (uint16)((float)ShakeFreq / 255.0f * (float)0xffff);\n\t\tuint16 iRightMotor = (uint16)((float)ShakeFreq / 255.0f * (float)0xffff);\n\n\t\tif (ShakeDur < CTimer::GetTimeStepInMilliseconds())\n\t\t\tShakeDur = 0;\n\t\telse\n\t\t\tShakeDur -= CTimer::GetTimeStepInMilliseconds();\n\t\tif (ShakeDur == 0) ShakeFreq = 0;\n\n\t\tVibrationState.wLeftMotorSpeed = iLeftMotor;\n\t\tVibrationState.wRightMotorSpeed = iRightMotor;\n\n\t\tXInputSetState(pad, &VibrationState);\n\t}\n}\n#endif\n\nvoid CPad::UpdatePads(void)\n{\n\tbool bUpdate = true;\n\n\tGetPad(0)->UpdateMouse();\n#ifdef XINPUT\n\tGetPad(0)->AffectFromXinput(m_bMapPadOneToPadTwo ? 1 : 0);\n\tGetPad(1)->AffectFromXinput(m_bMapPadOneToPadTwo ? 0 : 1);\n#else\n\tCapturePad(0);\n#endif\n\n\t// Improve keyboard input latency part 1\n#ifdef FIX_BUGS\n\tOldKeyState = NewKeyState;\n\tNewKeyState = TempKeyState;\n#endif\n\n#ifdef DETECT_PAD_INPUT_SWITCH\n\tif (GetPad(0)->PCTempJoyState.CheckForInput())\n\t\tIsAffectedByController = true;\n\telse {\n#endif\n\t\tControlsManager.ClearSimButtonPressCheckers();\n\t\tControlsManager.AffectPadFromKeyBoard();\n\t\tControlsManager.AffectPadFromMouse();\n\n#ifdef DETECT_PAD_INPUT_SWITCH\n\t}\n\tif (IsAffectedByController && (GetPad(0)->PCTempKeyState.CheckForInput() || GetPad(0)->PCTempMouseState.CheckForInput()))\n\t\tIsAffectedByController = false;\n#endif\n\n\tif ( CReplay::IsPlayingBackFromFile() && !FrontEndMenuManager.m_bMenuActive )\n\t\tbUpdate = false;\n\n\tif ( bUpdate )\n\t\tGetPad(0)->Update(0);\n\n#ifndef MASTER\n\tGetPad(1)->Update(1);\n#else\n\tGetPad(1)->NewState.Clear();\n\tGetPad(1)->OldState.Clear();\n#endif\n\n\t// Improve keyboard input latency part 2\n#ifndef FIX_BUGS\n\tOldKeyState = NewKeyState;\n\tNewKeyState = TempKeyState;\n#endif\n}\n\nvoid CPad::ProcessPCSpecificStuff(void)\n{\n\t;\n}\n\nvoid CPad::Update(int16 pad)\n{\n\tOldState = NewState;\n\n#ifdef GTA_PS2\n\tbObsoleteControllerMessage = false;\n\n\t//int iPressureBtn;\n\tint id;\n\tint ext_id=0;\n\tint state;\n\tint rterm_id = 0;\n\tunsigned short paddata, tpad;\n\tunsigned char rdata[32];\n\n\tstate = scePadGetState(pad, 0);\n\n\tswitch(Phase)\n\t{\n\tcase 0:\n\t\tif (state != scePadStateStable && state != scePadStateFindCTP1)\n\t\t\tbreak;\n\t\tid = scePadInfoMode(pad, 0, InfoModeCurID, 0);\n\t\tif (id==0) break;\n\n\t\text_id = scePadInfoMode(pad, 0, InfoModeCurExID, 0);\n\t\tif (ext_id>0) id = ext_id;\n\n\t\tswitch(id)\n\t\t{\n\t\tcase 4: // Digital controller\n\t\t\tPhase = 40; // Try for analog(dualshock)\n\t\t\tbreak;\n\t\tcase 7: // Dualshock2 controller\n\t\t\tPhase = 50;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tPhase = 99;\n\t\t\tbreak;\n\t\t}\n\t\tbreak;\n\n\t\t// Analog Controller (old dualshock)\n\tcase 40: // Analog Contoller check valid (otherwise fail phase)\n\t\tif (scePadInfoMode(pad, 0, InfoModeIdTable, -1)==0)\n\t\t{\n\t\t\tPhase = 99;\n\t\t\tbreak;\n\t\t}\n\t\tPhase++;\n\n\tcase 41: // Analog controller: Request Lock analog mode (asynchronous)\n\t\tif (scePadSetMainMode(pad, 0, 1, 3)==1) Phase++;\n\t\tbreak;\n\n\tcase 42: // Analog controller: Check state of previous request\n\t\tif (scePadGetReqState(pad, 0)==scePadReqStateFaild)\n\t\t{\n\t\t\tPhase--;\n\t\t}\n\n\t\tif (scePadGetReqState(pad, 0)==scePadReqStateComplete)\n\t\t{\n\t\t\t// Lock mode complete\n\t\t\tPhase=0; // Accept normal dualshock\n\t\t}\n\t\tbreak;\n\n\t\t// DualShock 2 Controller\n\tcase 50: // Analog Contoller check valid (otherwise fail phase)\n\t\tif (scePadInfoMode(pad, 0, InfoModeIdTable, -1)==0)\n\t\t{\n\t\t\tPhase = 99;\n\t\t\tbreak;\n\t\t}\n\t\tPhase++;\n\n\tcase 51: // Analog controller: Request Lock analog mode (asynchronous)\n\t\tif (scePadSetMainMode(pad, 0, 1, 3)==1) Phase++;\n\t\tbreak;\n\n\tcase 52: // Analog controller: Check state of previous request\n\t\tif (scePadGetReqState(pad, 0)==scePadReqStateFaild)\n\t\t{\n\t\t\tPhase--;\n\t\t}\n\n\t\tif (scePadGetReqState(pad, 0)==scePadReqStateComplete)\n\t\t{\n\t\t\t// Lock mode complete\n\t\t\tPhase=0; // Accept normal dualshock\n\t\t}\n\t\tbreak;\n\n\tcase 70: // DualShock 2 check pressure sensitive possible\n\t\tif (scePadInfoPressMode(pad, 0)==1)\n\t\t{\n\t\t\tPhase = 76;\n\t\t\tbreak;\n\t\t}\n\t\tPhase = 99;\n\t\tbreak;\n\n\tcase 76: // DualShock2 enable pressure sensitive mode (asynchronous function)\n\t\tif (scePadEnterPressMode(pad, 0)==1) Phase++;\n\t\tbreak;\n\n\tcase 77: // Dualshock2 check status of request pressure sensitive mode\n\t\tif (scePadGetReqState(pad, 0)==scePadReqStateFaild) Phase--;\n\t\tif (scePadGetReqState(pad, 0)==scePadReqStateComplete)\n\t\t{\n\t\t\tPhase=80;\n\t\t}\n\t\tbreak;\n\n\t\t// DualShock 2 Controller\n\tcase 80: // Set motors\n\t\tif (scePadInfoAct(pad, 0, -1, 0)==0)\n\t\t{\n\t\t\tPhase = 99;\n\t\t}\n\n\t\tact_align[0] = 0; // Offset 0 for motor0\n\t\tact_align[1] = 1; // Offset 1 for motor1\n\n\t\tact_align[2] = 0xff;\n\t\tact_align[3] = 0xff;\n\t\tact_align[4] = 0xff;\n\t\tact_align[5] = 0xff;\n\n\t\t// Asynchronous function\n\t\tif (scePadSetActAlign(pad, 0, act_align)==0) break;\n\t\tPhase++;\n\t\tbreak;\n\n\n\tcase 81:\n\t\tif ( scePadGetState(pad, 0) != scePadStateExecCmd )\n\t\t{\n\t\t\tPhase = 99;\n\t\t}\n\n\t\tbreak;\n\n\tdefault:\n\t\tif ( state == scePadStateError ) break;\n\n\t\tif ( state == scePadStateStable || state == scePadStateFindCTP1 )\n\t\t{\n\t\t\tif ( ShakeDur )\n\t\t\t{\n\t\t\t\tShakeDur = Max(ShakeDur - (int32)CTimer::GetTimeStepInMilliseconds(), 0);\n\n\t\t\t\tif ( ShakeDur == 0 )\n\t\t\t\t{\n\t\t\t\t\tact_direct[0] = 0;\n\t\t\t\t\tact_direct[1] = 0;\n\t\t\t\t\tscePadSetActDirect(pad, 0, act_direct);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tact_direct[0] = 0;\n\t\t\t\t\tact_direct[1] = (unsigned char) ShakeFreq;\n\t\t\t\t\tscePadSetActDirect(pad, 0, act_direct);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (scePadRead( pad, 0, rdata )==0)\n\t\t\t{\n\t\t\t\tNewState.Clear();\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tif ((rdata[0] == 0))\n\t\t\t{\n\t\t\t\tpaddata = (unsigned short) ( 0xffff ^ ((rdata[2]<<8)|rdata[3]) );\n\t\t\t\trterm_id = (rdata[1]);\n\n\t\t\t\tif ( (rterm_id>>4) == 7 ) // DUALSHOCK\n\t\t\t\t{\n\t\t\t\t\tif (!CRecordDataForGame::IsPlayingBack() && !CRecordDataForChase::ShouldThisPadBeLeftAlone(pad))\n\t\t\t\t\t{\n\t\t\t\t\t\ttpad = paddata;\n\n\t\t\t\t\t\tNewState.DPadUp\t\t\t= ( tpad & SCE_PADLup )\t   ? 255 : 0;\n\t\t\t\t\t\tNewState.DPadDown\t\t= ( tpad & SCE_PADLdown )  ? 255 : 0;\n\t\t\t\t\t\tNewState.DPadLeft\t\t= ( tpad & SCE_PADLleft )  ? 255 : 0;\n\t\t\t\t\t\tNewState.DPadRight\t\t= ( tpad & SCE_PADLright ) ? 255 : 0;\n\t\t\t\t\t\tNewState.Triangle\t\t= ( tpad & SCE_PADRup )\t   ? 255 : 0;\n\t\t\t\t\t\tNewState.Cross\t\t\t= ( tpad & SCE_PADRdown )  ? 255 : 0;\n\t\t\t\t\t\tNewState.Square\t\t\t= ( tpad & SCE_PADRleft )  ? 255 : 0;\n\t\t\t\t\t\tNewState.Circle\t\t\t= ( tpad & SCE_PADRright ) ? 255 : 0;\n\t\t\t\t\t\tNewState.Start\t\t\t= ( tpad & SCE_PADstart )  ? 255 : 0;\n\t\t\t\t\t\tNewState.Select\t\t\t= ( tpad & SCE_PADselect ) ? 255 : 0;\n\t\t\t\t\t\tNewState.LeftShoulder1\t= ( tpad & SCE_PADL1 )\t   ? 255 : 0;\n\t\t\t\t\t\tNewState.LeftShoulder2\t= ( tpad & SCE_PADL2 )\t   ? 255 : 0;\n\t\t\t\t\t\tNewState.RightShoulder1 = ( tpad & SCE_PADR1 )\t   ? 255 : 0;\n\t\t\t\t\t\tNewState.RightShoulder2 = ( tpad & SCE_PADR2 )\t   ? 255 : 0;\n\t\t\t\t\t\tNewState.LeftShock\t\t= ( tpad & SCE_PADi )\t   ? 255 : 0;\n\t\t\t\t\t\tNewState.RightShock\t\t= ( tpad & SCE_PADj )\t   ? 255 : 0;\n\t\t\t\t\t\tNewState.RightStickX\t= (short)rdata[4];\n\t\t\t\t\t\tNewState.RightStickY\t= (short)rdata[5];\n\t\t\t\t\t\tNewState.LeftStickX\t\t= (short)rdata[6];\n\t\t\t\t\t\tNewState.LeftStickY\t\t= (short)rdata[7];\n\n\t\t\t\t\t\t#define CLAMP_AXIS(x) (((x) < 43 && (x) >= -42) ? 0 : (((x) > 0) ? (Max((x)-42, 0)*127/85) : Min((x)+42, 0)*127/85))\n\t\t\t\t\t\t#define FIX_AXIS(x) CLAMP_AXIS((x)-128)\n\n\t\t\t\t\t\tNewState.RightStickX = FIX_AXIS(NewState.RightStickX);\n\t\t\t\t\t\tNewState.RightStickY = FIX_AXIS(NewState.RightStickY);\n\t\t\t\t\t\tNewState.LeftStickX\t = FIX_AXIS(NewState.LeftStickX);\n\t\t\t\t\t\tNewState.LeftStickY\t = FIX_AXIS(NewState.LeftStickY);\n\n\t\t\t\t\t\t#undef FIX_AXIS\n\t\t\t\t\t\t#undef CLAMP_AXIS\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if ( (rterm_id>>4) == 4 ) // Controller (digital)\n\t\t\t\t{\n\t\t\t\t\tif ( pad == 0 )\n\t\t\t\t\t\tbObsoleteControllerMessage = true;\n\t\t\t\t\tNewState.Clear();\n\t\t\t\t}\n\n\t\t\t\tif ( NewState.IsAnyButtonPressed() )\n\t\t\t\t\tLastTimeTouched = CTimer::GetTimeInMilliseconds();\n\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tif ( ++iCurrHornHistory >= HORNHISTORY_SIZE )\n\t\t\t\tiCurrHornHistory = 0;\n\n\t\t\tbHornHistory[iCurrHornHistory] = GetHorn();\n\t\t\tNewState.Clear();\n\t\t\treturn;\n\t\t}\n\t\tbreak;\n\t}\n\n\tif ( pad == 0 )\n\t{\n\t\tbOldDisplayNoControllerMessage = bDisplayNoControllerMessage;\n\t\tif ( state == scePadStateDiscon )\n\t\t{\n\t\t\tbDisplayNoControllerMessage = true;\n\t\t\tPhase = 0;\n\t\t}\n\t\telse\n\t\t\tbDisplayNoControllerMessage = false;\n\t}\n\n\tif ( ++iCurrHornHistory >= HORNHISTORY_SIZE )\n\t\tiCurrHornHistory = 0;\n\n\tbHornHistory[iCurrHornHistory] = GetHorn();\n\n\tif ( !bDisplayNoControllerMessage )\n\t\tCGame::bDemoMode = false;\n#endif\n\n#if (defined GTA_PS2 || defined FIX_BUGS)\n\tif (!CRecordDataForGame::IsPlayingBack() && !CRecordDataForChase::ShouldThisPadBeLeftAlone(pad))\n#endif\n\t{\n\t\tNewState = ReconcileTwoControllersInput(PCTempKeyState, PCTempJoyState);\n\t\tNewState = ReconcileTwoControllersInput(PCTempMouseState, NewState);\n\t}\n\n\tPCTempJoyState.Clear();\n\tPCTempKeyState.Clear();\n\tPCTempMouseState.Clear();\n\n\tProcessPCSpecificStuff();\n\n\tif (NewState.CheckForInput())\n\t\tLastTimeTouched = CTimer::GetTimeInMilliseconds();\n\t\n\tif ( ++iCurrHornHistory >= HORNHISTORY_SIZE )\n\t\tiCurrHornHistory = 0;\n\n\tbHornHistory[iCurrHornHistory] = GetHorn();\n\n\tfor (int32 i = DRUNK_STEERING_BUFFER_SIZE - 2; i >= 0; i--) {\n\t\tSteeringLeftRightBuffer[i + 1] = SteeringLeftRightBuffer[i];\n\t}\n\n\tif ( !bDisplayNoControllerMessage )\n\t\tCGame::bDemoMode = false;\n\n\tif ( JustOutOfFrontend != 0 )\n\t\t--JustOutOfFrontend;\n}\n\nvoid CPad::DoCheats(void)\n{\n#ifdef DETECT_PAD_INPUT_SWITCH\n\tif (IsAffectedByController)\n#endif\n\t\tGetPad(0)->DoCheats(0);\n}\n\nvoid CPad::DoCheats(int16 unk)\n{\n#ifdef GTA_PS2_STUFF\n\tif ( GetTriangleJustDown() )\n\t\tAddToCheatString('T');\n\n\tif ( GetCircleJustDown() )\n\t\tAddToCheatString('C');\n\n\tif ( GetCrossJustDown() )\n\t\tAddToCheatString('X');\n\n\tif ( GetSquareJustDown() )\n\t\tAddToCheatString('S');\n\n\tif ( GetDPadUpJustDown() )\n\t\tAddToCheatString('U');\n\n\tif ( GetDPadDownJustDown() )\n\t\tAddToCheatString('D');\n\n\tif ( GetDPadLeftJustDown() )\n\t\tAddToCheatString('L');\n\n\tif ( GetDPadRightJustDown() )\n\t\tAddToCheatString('R');\n\n\tif ( GetLeftShoulder1JustDown() )\n\t\tAddToCheatString('1');\n\n\tif ( GetLeftShoulder2JustDown() )\n\t\tAddToCheatString('2');\n\n\tif ( GetRightShoulder1JustDown() )\n\t\tAddToCheatString('3');\n\n\tif ( GetRightShoulder2JustDown() )\n\t\tAddToCheatString('4');\n#endif\n}\n\nvoid CPad::StopPadsShaking(void)\n{\n\tGetPad(0)->StopShaking(0);\n}\n\nvoid CPad::StopShaking(int16 pad)\n{\n#ifdef GTA_PS2_STUFF\n\tShakeFreq = 0;\n\tShakeDur = 0;\n\n#ifdef GTA_PS2\n\tif ( Phase == 99 )\n\t{\n\t\tact_direct[0] = 0;\n\t\tact_direct[1] = 0;\n\t\tscePadSetActDirect(pad, 0, act_direct);\n\t}\n#endif\n\n#endif\n}\n\nCPad *CPad::GetPad(int32 pad)\n{\n\treturn &Pads[pad];\n}\n#ifdef DETECT_PAD_INPUT_SWITCH\n#define CURMODE (IsAffectedByController ? Mode : 0)\n#else\n#define CURMODE (Mode)\n#endif\n\nint16 CPad::GetSteeringLeftRight(void)\n{\n\tif ( ArePlayerControlsDisabled() )\n\t\treturn 0;\n\n\tint16 value;\n\tswitch (CURMODE)\n\t{\n\t\tcase 0:\n\t\tcase 2:\n\t\t{\n\t\t\tint16 axis = NewState.LeftStickX;\n\t\t\tint16 dpad = (NewState.DPadRight - NewState.DPadLeft) / 2;\n\n\t\t\tif ( Abs(axis) > Abs(dpad) )\n\t\t\t\tvalue = axis;\n\t\t\telse\n\t\t\t\tvalue = dpad;\n\n\t\t\tSteeringLeftRightBuffer[0] = value;\n\t\t\tvalue = SteeringLeftRightBuffer[DrunkDrivingBufferUsed];\n\n\t\t\tbreak;\n\t\t}\n\n\t\tcase 1:\n\t\tcase 3:\n\t\t{\n\t\t\tSteeringLeftRightBuffer[0] = NewState.LeftStickX;\n\t\t\tvalue = SteeringLeftRightBuffer[DrunkDrivingBufferUsed];\n\t\t\tbreak;\n\t\t}\n\t\tdefault:\n\t\t{\n\t\t\tvalue = 0;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn value;\n}\n\nint16 CPad::GetSteeringUpDown(void)\n{\n\tif ( ArePlayerControlsDisabled() )\n\t\treturn 0;\n\n\tswitch (CURMODE)\n\t{\n\t\tcase 0:\n\t\tcase 2:\n\t\t{\n\t\t\tint16 axis = NewState.LeftStickY;\n\t\t\tint16 dpad = (NewState.DPadDown - NewState.DPadUp) / 2;\n\n\t\t\tif ( Abs(axis) > Abs(dpad) )\n\t\t\t\treturn axis;\n\t\t\telse\n\t\t\t\treturn dpad;\n\n\t\t\tbreak;\n\t\t}\n\n\t\tcase 1:\n\t\tcase 3:\n\t\t{\n\t\t\treturn NewState.LeftStickY;\n\n\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn 0;\n}\n\nint16 CPad::GetCarGunUpDown(void)\n{\n\tif ( ArePlayerControlsDisabled() )\n\t\treturn 0;\n\n\tswitch (CURMODE)\n\t{\n\t\tcase 0:\n\t\tcase 1:\n\t\tcase 2:\n\t\t{\n\t\t\treturn NewState.RightStickY;\n\n\t\t\tbreak;\n\t\t}\n\n\t\tcase 3:\n\t\t{\n\t\t\treturn (NewState.DPadUp - NewState.DPadDown) / 2;\n\n\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn 0;\n}\n\nint16 CPad::GetCarGunLeftRight(void)\n{\n\tif ( ArePlayerControlsDisabled() )\n\t\treturn 0;\n\n\tswitch (CURMODE)\n\t{\n\t\tcase 0:\n\t\tcase 1:\n\t\tcase 2:\n\t\t{\n\t\t\treturn NewState.RightStickX;\n\n\t\t\tbreak;\n\t\t}\n\n\t\tcase 3:\n\t\t{\n\t\t\treturn (NewState.DPadRight - NewState.DPadLeft) / 2;\n\n\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn 0;\n}\n\nint16 CPad::GetPedWalkLeftRight(void)\n{\n\tif ( ArePlayerControlsDisabled() )\n\t\treturn 0;\n\n\tswitch (CURMODE)\n\t{\n\t\tcase 0:\n\t\tcase 2:\n\t\t{\n\t\t\tint16 axis = NewState.LeftStickX;\n\t\t\tint16 dpad = (NewState.DPadRight - NewState.DPadLeft) / 2;\n\n\t\t\tif ( Abs(axis) > Abs(dpad) )\n\t\t\t\treturn axis;\n\t\t\telse\n\t\t\t\treturn dpad;\n\n\t\t\tbreak;\n\t\t}\n\n\t\tcase 1:\n\t\tcase 3:\n\t\t{\n\t\t\treturn NewState.LeftStickX;\n\n\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn 0;\n}\n\nint16 CPad::GetPedWalkUpDown(void)\n{\n\tif ( ArePlayerControlsDisabled() )\n\t\treturn 0;\n\n\tswitch (CURMODE)\n\t{\n\t\tcase 0:\n\t\tcase 2:\n\t\t{\n\t\t\tint16 axis = NewState.LeftStickY;\n\t\t\tint16 dpad = (NewState.DPadDown - NewState.DPadUp) / 2;\n\n\t\t\tif ( Abs(axis) > Abs(dpad) )\n\t\t\t\treturn axis;\n\t\t\telse\n\t\t\t\treturn dpad;\n\n\t\t\tbreak;\n\t\t}\n\n\t\tcase 1:\n\t\tcase 3:\n\t\t{\n\t\t\treturn NewState.LeftStickY;\n\n\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn 0;\n}\n\nint16 CPad::GetAnalogueUpDown(void)\n{\n\tswitch (CURMODE)\n\t{\n\t\tcase 0:\n\t\tcase 2:\n\t\t{\n\t\t\tint16 axis = NewState.LeftStickY;\n\t\t\tint16 dpad = (NewState.DPadDown - NewState.DPadUp) / 2;\n\n\t\t\tif ( Abs(axis) > Abs(dpad) )\n\t\t\t\treturn axis;\n\t\t\telse\n\t\t\t\treturn dpad;\n\n\t\t\tbreak;\n\t\t}\n\n\t\tcase 1:\n\t\tcase 3:\n\t\t{\n\t\t\treturn NewState.LeftStickY;\n\n\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn 0;\n}\n\nint16 CPad::GetAnalogueLeftRight(void)\n{\n\tswitch (CURMODE)\n\t{\n\t\tcase 0:\n\t\tcase 2:\n\t\t{\n\t\t\tint16 axis = NewState.LeftStickX;\n\t\t\tint16 dpad = (NewState.DPadRight - NewState.DPadLeft) / 2;\n\n\t\t\tif ( Abs(axis) > Abs(dpad) )\n\t\t\t\treturn axis;\n\t\t\telse\n\t\t\t\treturn dpad;\n\n\t\t\tbreak;\n\t\t}\n\n\t\tcase 1:\n\t\tcase 3:\n\t\t{\n\t\t\treturn NewState.LeftStickX;\n\n\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn 0;\n}\n\nbool CPad::GetLookLeft(void)\n{\n\tif ( ArePlayerControlsDisabled() )\n\t\treturn false;\n\n\treturn !!(NewState.LeftShoulder2 && !NewState.RightShoulder2);\n}\n\nbool CPad::GetLookRight(void)\n{\n\tif ( ArePlayerControlsDisabled() )\n\t\treturn false;\n\n\treturn !!(NewState.RightShoulder2 && !NewState.LeftShoulder2);\n}\n\n\nbool CPad::GetLookBehindForCar(void)\n{\n\tif ( ArePlayerControlsDisabled() )\n\t\treturn false;\n\n\treturn !!(NewState.RightShoulder2 && NewState.LeftShoulder2);\n}\n\nbool CPad::GetLookBehindForPed(void)\n{\n\tif ( ArePlayerControlsDisabled() )\n\t\treturn false;\n\n\treturn !!NewState.RightShock;\n}\n\nbool CPad::GetHorn(void)\n{\n\tif ( ArePlayerControlsDisabled() )\n\t\treturn false;\n\n\tswitch (CURMODE)\n\t{\n\t\tcase 0:\n\t\t{\n\t\t\treturn !!NewState.LeftShock;\n\n\t\t\tbreak;\n\t\t}\n\n\t\tcase 1:\n\t\t{\n\t\t\treturn !!NewState.LeftShoulder1;\n\n\t\t\tbreak;\n\t\t}\n\n\t\tcase 2:\n\t\t{\n\t\t\treturn !!NewState.RightShoulder1;\n\n\t\t\tbreak;\n\t\t}\n\n\t\tcase 3:\n\t\t{\n\t\t\treturn !!NewState.LeftShock;\n\n\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn false;\n}\n\nbool CPad::HornJustDown(void)\n{\n\tif ( ArePlayerControlsDisabled() )\n\t\treturn false;\n\n\tswitch (CURMODE)\n\t{\n\t\tcase 0:\n\t\t{\n\t\t\treturn !!(NewState.LeftShock && !OldState.LeftShock);\n\n\t\t\tbreak;\n\t\t}\n\n\t\tcase 1:\n\t\t{\n\t\t\treturn !!(NewState.LeftShoulder1 && !OldState.LeftShoulder1);\n\n\t\t\tbreak;\n\t\t}\n\n\t\tcase 2:\n\t\t{\n\t\t\treturn !!(NewState.RightShoulder1 && !OldState.RightShoulder1);\n\n\t\t\tbreak;\n\t\t}\n\n\t\tcase 3:\n\t\t{\n\t\t\treturn !!(NewState.LeftShock && !OldState.LeftShock);\n\n\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn false;\n}\n\nbool CPad::GetCarGunFired(void)\n{\n\tif ( ArePlayerControlsDisabled() )\n\t\treturn false;\n\n\tswitch (CURMODE)\n\t{\n\t\tcase 0:\n\t\tcase 1:\n\t\tcase 2:\n\t\t{\n\t\t\treturn !!NewState.Circle;\n\n\t\t\tbreak;\n\t\t}\n\n\t\tcase 3:\n\t\t{\n\t\t\treturn !!NewState.RightShoulder1;\n\n\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn false;\n}\n\nbool CPad::CarGunJustDown(void)\n{\n\tif ( ArePlayerControlsDisabled() )\n\t\treturn false;\n\n\tswitch (CURMODE)\n\t{\n\t\tcase 0:\n\t\tcase 1:\n\t\tcase 2:\n\t\t{\n\t\t\treturn !!(NewState.Circle && !OldState.Circle);\n\n\t\t\tbreak;\n\t\t}\n\n\t\tcase 3:\n\t\t{\n\t\t\treturn !!(NewState.RightShoulder1 && !OldState.RightShoulder1);\n\n\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn false;\n}\n\nint16 CPad::GetHandBrake(void)\n{\n\tif ( ArePlayerControlsDisabled() )\n\t\treturn 0;\n\n\tswitch (CURMODE)\n\t{\n\t\tcase 0:\n\t\tcase 1:\n\t\t{\n\t\t\treturn NewState.RightShoulder1;\n\n\t\t\tbreak;\n\t\t}\n\n\t\tcase 2:\n\t\t{\n\t\t\treturn NewState.Triangle;\n\n\t\t\tbreak;\n\t\t}\n\n\t\tcase 3:\n\t\t{\n\t\t\treturn NewState.LeftShoulder1;\n\n\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn 0;\n}\n\nint16 CPad::GetBrake(void)\n{\n\tif ( ArePlayerControlsDisabled() )\n\t\treturn 0;\n\n\tswitch (CURMODE)\n\t{\n\t\tcase 0:\n\t\tcase 2:\n\t\t{\n\t\t\treturn NewState.Square;\n\n\t\t\tbreak;\n\t\t}\n\n\t\tcase 1:\n\t\t{\n\t\t\treturn NewState.Square;\n\n\t\t\tbreak;\n\t\t}\n\n\t\tcase 3:\n\t\t{\n\t\t\tint16 axis = 2 * NewState.RightStickY;\n\n\t\t\tif ( axis < 0 )\n\t\t\t\treturn 0;\n\t\t\telse\n\t\t\t\treturn axis;\n\n\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn 0;\n}\n\nbool CPad::GetExitVehicle(void)\n{\n\tif ( ArePlayerControlsDisabled() )\n\t\treturn false;\n\n\n\tif ( JustOutOfFrontend != 0 )\n\t\treturn false;\n\n\tswitch (CURMODE)\n\t{\n\t\tcase 0:\n\t\tcase 1:\n\t\tcase 3:\n\t\t{\n\t\t\treturn !!NewState.Triangle;\n\n\t\t\tbreak;\n\t\t}\n\n\t\tcase 2:\n\t\t{\n\t\t\treturn !!NewState.LeftShoulder1;\n\n\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn false;\n}\n\nbool CPad::ExitVehicleJustDown(void)\n{\n\tif ( ArePlayerControlsDisabled() )\n\t\treturn false;\n\n\tif ( JustOutOfFrontend != 0 )\n\t\treturn false;\n\n\tswitch (CURMODE)\n\t{\n\t\tcase 0:\n\t\tcase 1:\n\t\tcase 3:\n\t\t{\n\t\t\treturn !!(NewState.Triangle && !OldState.Triangle);\n\n\t\t\tbreak;\n\t\t}\n\n\t\tcase 2:\n\t\t{\n\t\t\treturn !!(NewState.LeftShoulder1 && !OldState.LeftShoulder1);\n\n\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn false;\n}\n\nint32 CPad::GetWeapon(void)\n{\n\tif ( ArePlayerControlsDisabled() )\n\t\treturn false;\n\n\tswitch (CURMODE)\n\t{\n\t\tcase 0:\n\t\tcase 1:\n\t\t{\n\t\t\treturn NewState.Circle;\n\n\t\t\tbreak;\n\t\t}\n\n\t\tcase 2:\n\t\t{\n\t\t\treturn NewState.Cross;\n\n\t\t\tbreak;\n\t\t}\n\n\t\tcase 3:\n\t\t{\n\t\t\treturn NewState.RightShoulder1;\n\n\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn false;\n}\n\nbool CPad::WeaponJustDown(void)\n{\n\tif ( ArePlayerControlsDisabled() )\n\t\treturn false;\n\n\tswitch (CURMODE)\n\t{\n\t\tcase 0:\n\t\tcase 1:\n\t\t{\n\t\t\treturn !!(NewState.Circle && !OldState.Circle);\n\n\t\t\tbreak;\n\t\t}\n\n\t\tcase 2:\n\t\t{\n\t\t\treturn !!(NewState.Cross && !OldState.Cross);\n\n\t\t\tbreak;\n\t\t}\n\n\t\tcase 3:\n\t\t{\n\t\t\treturn !!(NewState.RightShoulder1 && !OldState.RightShoulder1);\n\n\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn false;\n}\n\nint16 CPad::GetAccelerate(void)\n{\n\tif ( ArePlayerControlsDisabled() )\n\t\treturn 0;\n\n\tswitch (CURMODE)\n\t{\n\t\tcase 0:\n\t\tcase 2:\n\t\t{\n\t\t\treturn NewState.Cross;\n\n\t\t\tbreak;\n\t\t}\n\n\t\tcase 1:\n\t\t{\n\t\t\treturn NewState.Cross;\n\n\t\t\tbreak;\n\t\t}\n\n\t\tcase 3:\n\t\t{\n\t\t\tint16 axis = -2 * NewState.RightStickY;\n\n\t\t\tif ( axis < 0 )\n\t\t\t\treturn 0;\n\t\t\telse\n\t\t\t\treturn axis;\n\n\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn 0;\n}\n\nbool CPad::CycleCameraModeJustDown(void)\n{\n\tbool result;\n\tswitch (CURMODE)\n\t{\n\t\tcase 0:\n\t\tcase 2:\n\t\tcase 3:\n\t\t{\n\t\t\tresult = !!(NewState.Select && !OldState.Select);\n\n\t\t\tbreak;\n\t\t}\n\n\t\tcase 1:\n\t\t{\n\t\t\tresult = !!(NewState.DPadUp && !OldState.DPadUp);\n\n\t\t\tbreak;\n\t\t}\n\t\tdefault:\n\t\t{\n\t\t\tresult = false;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tif (!result)\n\t{\n\t\tswitch (CURMODE)\n\t\t{\n\t\t\tcase 1:\n\t\t\t{\n\t\t\t\tresult = !!(NewState.DPadDown && !OldState.DPadDown);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tdefault:\n\t\t\t{\n\t\t\t\tresult = false;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn result;\n}\n\nbool CPad::CycleCameraModeUpJustDown(void)\n{\n\tswitch (CURMODE)\n\t{\n\t\tcase 0:\n\t\tcase 2:\n\t\tcase 3:\n\t\t{\n\t\t\treturn !!(NewState.Select && !OldState.Select);\n\n\t\t\tbreak;\n\t\t}\n\n\t\tcase 1:\n\t\t{\n\t\t\treturn !!(NewState.DPadUp && !OldState.DPadUp);\n\n\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn false;\n}\n\nbool CPad::CycleCameraModeDownJustDown(void)\n{\n\tswitch (CURMODE)\n\t{\n\t\tcase 0:\n\t\tcase 2:\n\t\tcase 3:\n\t\t{\n\t\t\treturn false;\n\n\t\t\tbreak;\n\t\t}\n\n\t\tcase 1:\n\t\t{\n\t\t\treturn !!(NewState.DPadDown && !OldState.DPadDown);\n\n\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn false;\n}\n\nbool CPad::ChangeStationJustDown(void)\n{\n\tif ( ArePlayerControlsDisabled() )\n\t\treturn false;\n\n\tswitch (CURMODE)\n\t{\n\t\tcase 0:\n\t\t{\n\t\t\treturn !!(NewState.LeftShoulder1 && !OldState.LeftShoulder1);\n\n\t\t\tbreak;\n\t\t}\n\n\t\tcase 1:\n\t\t{\n\t\t\treturn !!(NewState.Select && !OldState.Select);\n\n\t\t\tbreak;\n\t\t}\n\n\t\tcase 2:\n\t\t{\n\t\t\treturn !!(NewState.LeftShock && !OldState.LeftShock);\n\n\t\t\tbreak;\n\t\t}\n\n\t\tcase 3:\n\t\t{\n\t\t\treturn !!(NewState.Circle && !OldState.Circle);\n\n\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn false;\n}\n\nbool CPad::CycleWeaponLeftJustDown(void)\n{\n\tif ( ArePlayerControlsDisabled() )\n\t\treturn false;\n\n\treturn !!(NewState.LeftShoulder2 && !OldState.LeftShoulder2);\n}\n\nbool CPad::CycleWeaponRightJustDown(void)\n{\n\tif ( ArePlayerControlsDisabled() )\n\t\treturn false;\n\n\treturn !!(NewState.RightShoulder2 && !OldState.RightShoulder2);\n}\n\nbool CPad::GetTarget(void)\n{\n\tif ( ArePlayerControlsDisabled() )\n\t\treturn false;\n\n\tswitch (CURMODE)\n\t{\n\t\tcase 0:\n\t\tcase 1:\n\t\tcase 2:\n\t\t{\n\t\t\treturn !!NewState.RightShoulder1;\n\n\t\t\tbreak;\n\t\t}\n\n\t\tcase 3:\n\t\t{\n\t\t\treturn !!NewState.LeftShoulder1;\n\n\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn false;\n}\n\nbool CPad::TargetJustDown(void)\n{\n\tif ( ArePlayerControlsDisabled() )\n\t\treturn false;\n\n\tswitch (CURMODE)\n\t{\n\t\tcase 0:\n\t\tcase 1:\n\t\tcase 2:\n\t\t{\n\t\t\treturn !!(NewState.RightShoulder1 && !OldState.RightShoulder1);\n\n\t\t\tbreak;\n\t\t}\n\n\t\tcase 3:\n\t\t{\n\t\t\treturn !!(NewState.LeftShoulder1 && !OldState.LeftShoulder1);\n\n\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn false;\n}\n\nbool CPad::CollectPickupJustDown(void)\n{\n\tif ( ArePlayerControlsDisabled() )\n\t\treturn false;\n\n\tswitch (CURMODE)\n\t{\n\t\tcase 0:\n\t\tcase 1:\n\t\t{\n\t\t\treturn !!(NewState.LeftShoulder1 && !OldState.LeftShoulder1);\n\n\t\t\tbreak;\n\t\t}\n\t\tcase 2:\n\t\t{\n\t\t\treturn !!(NewState.Triangle && !OldState.Triangle);\n\n\t\t\tbreak;\n\t\t}\n\n\t\tcase 3:\n\t\t{\n\t\t\treturn !!(NewState.Circle && !OldState.Circle);\n\n\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn false;\n}\n\nbool CPad::DuckJustDown(void)\n{\n\tif (ArePlayerControlsDisabled())\n\t\treturn false;\n\n\treturn !!(NewState.LeftShock && !OldState.LeftShock);\n}\n\nbool CPad::JumpJustDown(void)\n{\n\tif ( ArePlayerControlsDisabled() )\n\t\treturn false;\n\n\treturn !!(NewState.Square && !OldState.Square);\n}\n\nbool CPad::GetSprint(void)\n{\n\tif ( ArePlayerControlsDisabled() )\n\t\treturn false;\n\n\tswitch (CURMODE)\n\t{\n\t\tcase 0:\n\t\tcase 1:\n\t\tcase 3:\n\t\t{\n\t\t\treturn !!NewState.Cross;\n\n\t\t\tbreak;\n\t\t}\n\n\t\tcase 2:\n\t\t{\n\t\t\treturn !!NewState.Circle;\n\n\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn false;\n}\n\nbool CPad::ShiftTargetLeftJustDown(void)\n{\n\tif ( ArePlayerControlsDisabled() )\n\t\treturn false;\n\n\treturn !!(NewState.LeftShoulder2 && !OldState.LeftShoulder2);\n}\n\nbool CPad::ShiftTargetRightJustDown(void)\n{\n\tif ( ArePlayerControlsDisabled() )\n\t\treturn false;\n\n\treturn !!(NewState.LeftShoulder1 && !OldState.LeftShoulder1) || !!(NewState.RightShoulder2 && !OldState.RightShoulder2);\n}\n\nbool CPad::GetAnaloguePadUp(void)\n{\n\tstatic int16 oldfStickY = 0;\n\n\tint16 leftStickY = CPad::GetPad(0)->GetLeftStickY();\n\n\tif ( leftStickY < -15 && oldfStickY >= -5 )\n\t{\n\t\toldfStickY = leftStickY;\n\t\treturn true;\n\t}\n\telse\n\t{\n\t\toldfStickY = leftStickY;\n\t\treturn false;\n\t}\n}\n\nbool CPad::GetAnaloguePadDown(void)\n{\n\tstatic int16 oldfStickY = 0;\n\n\tint16 leftStickY = CPad::GetPad(0)->GetLeftStickY();\n\n\tif ( leftStickY > 15 && oldfStickY <= 5 )\n\t{\n\t\toldfStickY = leftStickY;\n\t\treturn true;\n\t}\n\telse\n\t{\n\t\toldfStickY = leftStickY;\n\t\treturn false;\n\t}\n}\n\nbool CPad::GetAnaloguePadLeft(void)\n{\n\tstatic int16 oldfStickX = 0;\n\n\tint16 leftStickX = CPad::GetPad(0)->GetLeftStickX();\n\n\tif ( leftStickX < -15 && oldfStickX >= -5 )\n\t{\n\t\toldfStickX = leftStickX;\n\t\treturn true;\n\t}\n\telse\n\t{\n\t\toldfStickX = leftStickX;\n\t\treturn false;\n\t}\n}\n\nbool CPad::GetAnaloguePadRight(void)\n{\n\tstatic int16 oldfStickX = 0;\n\n\tint16 leftStickX = CPad::GetPad(0)->GetLeftStickX();\n\n\tif ( leftStickX > 15 && oldfStickX <= 5 )\n\t{\n\t\toldfStickX = leftStickX;\n\t\treturn true;\n\t}\n\telse\n\t{\n\t\toldfStickX = leftStickX;\n\t\treturn false;\n\t}\n}\n\nbool CPad::GetAnaloguePadLeftJustUp(void)\n{\n\tstatic int16 oldfStickX = 0;\n\n\tint16 X = GetPad(0)->GetPedWalkLeftRight();\n\n\tif ( X == 0 && oldfStickX < 0 )\n\t{\n\t\toldfStickX = 0;\n\n\t\treturn true;\n\t}\n\telse\n\t{\n\t\toldfStickX = X;\n\n\t\treturn false;\n\t}\n}\n\nbool CPad::GetAnaloguePadRightJustUp(void)\n{\n\tstatic int16 oldfStickX = 0;\n\n\tint16 X = GetPad(0)->GetPedWalkLeftRight();\n\n\tif ( X == 0 && oldfStickX > 0 )\n\t{\n\t\toldfStickX = 0;\n\n\t\treturn true;\n\t}\n\telse\n\t{\n\t\toldfStickX = X;\n\n\t\treturn false;\n\t}\n}\n\nbool CPad::ForceCameraBehindPlayer(void)\n{\n\tif ( ArePlayerControlsDisabled() )\n\t\treturn false;\n\n\tswitch (CURMODE)\n\t{\n\t\tcase 0:\n\t\tcase 1:\n\t\t{\n\t\t\treturn !!NewState.LeftShoulder1;\n\n\t\t\tbreak;\n\t\t}\n\n\t\tcase 2:\n\t\t{\n\t\t\treturn !!NewState.Triangle;\n\n\t\t\tbreak;\n\t\t}\n\n\t\tcase 3:\n\t\t{\n\t\t\treturn !!NewState.Circle;\n\n\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn false;\n}\n\nbool CPad::SniperZoomIn(void)\n{\n\tif ( ArePlayerControlsDisabled() )\n\t\treturn false;\n\n\tswitch (CURMODE)\n\t{\n\t\tcase 0:\n\t\tcase 1:\n\t\tcase 3:\n\t\t{\n\t\t\treturn !!NewState.Square;\n\n\t\t\tbreak;\n\t\t}\n\n\t\tcase 2:\n\t\t{\n\t\t\treturn !!NewState.Triangle;\n\n\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn false;\n}\n\nbool CPad::SniperZoomOut(void)\n{\n\tif ( ArePlayerControlsDisabled() )\n\t\treturn false;\n\n\tswitch (CURMODE)\n\t{\n\t\tcase 0:\n\t\tcase 1:\n\t\tcase 3:\n\t\t{\n\t\t\treturn !!NewState.Cross;\n\n\t\t\tbreak;\n\t\t}\n\n\t\tcase 2:\n\t\t{\n\t\t\treturn !!NewState.Square;\n\n\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn false;\n}\n\n#undef CURMODE\n\nint16 CPad::SniperModeLookLeftRight(void)\n{\n\tint16 axis = NewState.LeftStickX;\n\tint16 dpad = (NewState.DPadRight - NewState.DPadLeft) / 2;\n\n\tif ( Abs(axis) > Abs(dpad) ) {\n\t\tif ( Abs(axis) > 35.0f ) {\n\t\t  return (axis > 0.f ? axis - 35.f : axis + 35.f) * (128.f / (128 - 35));\n\t\t} else {\n\t\t  return 0;\n\t\t}\n\t} else\n\t\treturn dpad;\n}\n\nint16 CPad::SniperModeLookUpDown(void)\n{\n\tint16 axis = NewState.LeftStickY;\n\tint16 dpad;\n\n#ifdef FIX_BUGS\n\taxis = -axis;\n#endif\n\tif (CPad::bInvertLook4Pad) {\n\t\taxis = -axis;\n\t\tdpad = (NewState.DPadDown - NewState.DPadUp) / 2;\n\t} else {\n\t\tdpad = (NewState.DPadUp - NewState.DPadDown) / 2;\n\t}\n\n\tif ( Abs(axis) > Abs(dpad) ) {\n\t    if ( Abs(axis) > 35.0f ) {\n\t      return (axis > 0.f ? axis - 35.f : axis + 35.f) * (128.f / (128 - 35));\n\t    } else {\n\t      return 0;\n\t    }\n\t} else\n\t\treturn dpad;\n}\n\nint16 CPad::LookAroundLeftRight(void)\n{\n\tfloat axis = GetPad(0)->NewState.RightStickX;\n\n\tif ( Abs(axis) > 85 && !GetLookBehindForPed() )\n\t\treturn (int16) ( (axis + ( ( axis > 0 ) ? -85 : 85) )\n\t\t\t\t\t\t\t* (127.0f / 32.0f) ); // 3.96875f\n\n\telse if ( TheCamera.Cams[0].Using3rdPersonMouseCam() && Abs(axis) > 10 )\n\t\treturn (int16) ( (axis + ( ( axis > 0 ) ? -10 : 10) )\n\t\t\t\t\t\t\t* (127.0f / 64.0f) ); // 1.984375f\n\n\treturn 0;\n}\n\nint16 CPad::LookAroundUpDown(void)\n{\n\tint16 axis = GetPad(0)->NewState.RightStickY;\n#ifdef FIX_BUGS\n\taxis = -axis;\n#endif\n\tif (CPad::bInvertLook4Pad)\n\t\taxis = -axis;\n\n\tif ( Abs(axis) > 85 && !GetLookBehindForPed() )\n\t\treturn (int16) ( (axis + ( ( axis > 0 ) ? -85 : 85) )\n\t\t\t\t\t\t\t* (127.0f / 32.0f) ); // 3.96875f\n\n\telse if ( TheCamera.Cams[0].Using3rdPersonMouseCam() && Abs(axis) > 40 )\n\t\treturn (int16) ( (axis + ( ( axis > 0 ) ? -40 : 40) )\n\t\t\t\t\t\t\t* (127.0f / 64.0f) ); // 1.984375f\n\n\treturn 0;\n}\n\nvoid CPad::ResetAverageWeapon(void)\n{\n\tAverageWeapon = GetWeapon();\n\tAverageEntries = 1;\n}\n\nvoid CPad::PrintErrorMessage(void)\n{\n\tif (TheCamera.m_WideScreenOn)\n\t\treturn;\n\n\tif ( bDisplayNoControllerMessage && !CGame::playingIntro && !FrontEndMenuManager.m_bMenuActive )\n\t{\n\t\tCSprite2d::DrawRect(CRect(SCREEN_STRETCH_X(20.0f), SCREEN_SCALE_FROM_BOTTOM(130.0f), SCREEN_STRETCH_FROM_RIGHT(20.0f), SCREEN_SCALE_Y(140.0f)), CRGBA(50, 50, 50, 210));\n#ifdef FIX_BUGS\n\t\tCFont::SetScale(SCREEN_SCALE_X(0.85f), SCREEN_SCALE_Y(1.0f));\n#else\n\t\tCFont::SetScale(0.85f, 1.0f);\n#endif\n\t\tCFont::SetJustifyOff();\n\t\tCFont::SetBackgroundOff();\n#ifdef FIX_BUGS\n\t\tCFont::SetCentreSize(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH - 20));\n#else\n\t\tCFont::SetCentreSize(SCREEN_WIDTH - 20);\n#endif\n\t\tCFont::SetCentreOn();\n\t\tCFont::SetPropOn();\n\t\tCFont::SetColor(CRGBA(255, 255, 200, 200));\n\t\tCFont::SetFontStyle(FONT_STANDARD);\n\t\tCFont::PrintString\n\t\t(\n\t\t\tSCREEN_WIDTH  / 2,\n\t\t\tSCREEN_HEIGHT / 2 - SCREEN_SCALE_Y(40.0f),\n\t\t\tTheText.Get(\"NOCONT\") // Please reconnect an analog controller (DUALSHOCK@) or analog controller (DUALSHOCK@2). to controller port 1 to continue\n\t\t);\n\t}\n\telse if ( bObsoleteControllerMessage )\n\t{\n\t\tCSprite2d::DrawRect(CRect(SCREEN_STRETCH_X(20.0f), SCREEN_SCALE_FROM_BOTTOM(130.0f), SCREEN_STRETCH_FROM_RIGHT(20.0f), SCREEN_SCALE_Y(140.0f)), CRGBA(50, 50, 50, 210));\n#ifdef FIX_BUGS\n\t\tCFont::SetScale(SCREEN_SCALE_X(0.85f), SCREEN_SCALE_Y(1.0f));\n#else\n\t\tCFont::SetScale(0.85f, 1.0f);\n#endif\n\t\tCFont::SetJustifyOff();\n\t\tCFont::SetBackgroundOff();\n#ifdef FIX_BUGS\n\t\tCFont::SetCentreSize(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH - 20));\n#else\n\t\tCFont::SetCentreSize(SCREEN_WIDTH - 20);\n#endif\n\t\tCFont::SetCentreOn();\n\t\tCFont::SetPropOn();\n\t\tCFont::SetColor(CRGBA(255, 255, 200, 200));\n\t\tCFont::SetFontStyle(FONT_STANDARD);\n\t\tCFont::PrintString\n\t\t(\n\t\t\tSCREEN_WIDTH  / 2,\n\t\t\tSCREEN_HEIGHT / 2 - SCREEN_SCALE_Y(40.0f),\n\t\t\tTheText.Get(\"WRCONT\") // The controller connected to controller port 1 is an unsupported controller. Grand Theft Auto III requires an analog controller (DUALSHOCK@) or analog controller (DUALSHOCK@2).\n\t\t);\n\t}\n\n}\n\nvoid LittleTest(void)\n{\n\tstatic int32 Cunt = 0;\n\n\tCunt++; // ???\n}\n\nvoid CPad::ResetCheats(void)\n{\n\tCWeather::ReleaseWeather();\n\n\tgbFastTime = false;\n\tCPopulation::ms_bGivePedsWeapons = false;\n\tCTimer::SetTimeScale(1.0f);\n\n\tCVehicle::bWheelsOnlyCheat = false;\n\tCVehicle::bAllDodosCheat = false;\n\tCVehicle::bCheat3 = false;\n\tCVehicle::bCheat4 = false;\n\tCVehicle::bCheat5 = false;\n\tCVehicle::bAllTaxisHaveNitro = false;\n\tCVehicle::bHoverCheat = false;\n\tCVehicle::bCheat8 = false;\n\tCVehicle::bCheat9 = false;\n\tCVehicle::bCheat10 = false;\n#ifdef RESTORE_ALLCARSHELI_CHEAT\n\tbAllCarCheat = false;\n#endif\n\tgbBlackCars = false;\n\tgbPinkCars = false;\n\n\tCCarCtrl::bMadDriversCheat = false;\n\tCTrafficLights::bGreenLightsCheat = false;\n\tCStats::ShowChaseStatOnScreen = 0;\n\tCPed::bNastyLimbsCheat = false;\n\tCPed::bFannyMagnetCheat = false;\n\tCPed::bPedCheat3 = false;\n\n}\n\nchar *CPad::EditString(char *pStr, int32 nSize)\n{\n\tint32 pos = (int32)strlen(pStr);\n\n\t// letters\n\tfor ( int32 i = 0; i < ('Z' - 'A' + 1); i++ )\n\t{\n\t\tif ( GetPad(0)->GetCharJustDown(i + 'A') && pos < nSize - 1 )\n\t\t{\n\t\t\tpStr[pos++] = i + 'A';\n\t\t\tpStr[pos] = '\\0';\n\t\t}\n\n\t\tif ( GetPad(0)->GetCharJustDown(i + 'a') && pos < nSize - 1 )\n\t\t{\n\t\t\tpStr[pos++] = i + 'a';\n\t\t\tpStr[pos] = '\\0';\n\t\t}\n\t}\n\n\t// numbers\n\tfor ( int32 i = 0; i < ('9' - '0' + 1); i++ )\n\t{\n\t\tif ( GetPad(0)->GetCharJustDown(i + '0') && pos < nSize - 1 )\n\t\t{\n\t\t\tpStr[pos++] = i + '0';\n\t\t\tpStr[pos] = '\\0';\n\t\t}\n\t}\n\n\t// space\n\tif ( GetPad(0)->GetCharJustDown(' ') && pos < nSize - 1 )\n\t{\n\t\tpStr[pos++] = ' ';\n\t\tpStr[pos] = '\\0';\n\t}\n\n\n\t// del\n\tif ( GetPad(0)->GetDeleteJustDown() || GetPad(0)->GetBackspaceJustDown() )\n\t{\n\t\tif ( pos > 0 )\n\t\t\tpStr[pos - 1] = '\\0';\n\t}\n\n\t// extenter/up/down\n\tif ( GetPad(0)->GetReturnJustDown() || GetPad(0)->GetUpJustDown() || GetPad(0)->GetDownJustDown() )\n\t\treturn nil;\n\n\treturn pStr;\n}\n\nint32 *CPad::EditCodesForControls(int32 *pRsKeys, int32 nSize)\n{\n\t*pRsKeys = rsNULL;\n\n\tfor ( int32 i = 0; i < 255; i++ )\n\t{\n\t\tif ( GetPad(0)->GetCharJustDown(i) )\n\t\t\t*pRsKeys = i;\n\t}\n\n\tfor ( int32 i = 0; i < 12; i++ )\n\t{\n\t\tif ( GetPad(0)->GetFJustDown(i) )\n\t\t\t*pRsKeys = i + rsF1;\n\t}\n\n\tif ( GetPad(0)->GetEscapeJustDown() )\n\t\t*pRsKeys = rsESC;\n\n\tif ( GetPad(0)->GetInsertJustDown() )\n\t\t*pRsKeys = rsINS;\n\n\tif ( GetPad(0)->GetDeleteJustDown() )\n\t\t*pRsKeys = rsDEL;\n\n\tif ( GetPad(0)->GetHomeJustDown() )\n\t\t*pRsKeys = rsHOME;\n\n\tif ( GetPad(0)->GetEndJustDown() )\n\t\t*pRsKeys = rsEND;\n\n\tif ( GetPad(0)->GetPageUpJustDown() )\n\t\t*pRsKeys = rsPGUP;\n\n\tif ( GetPad(0)->GetPageDownJustDown() )\n\t\t*pRsKeys = rsPGDN;\n\n\tif ( GetPad(0)->GetUpJustDown() )\n\t\t*pRsKeys = rsUP;\n\n\tif ( GetPad(0)->GetDownJustDown() )\n\t\t*pRsKeys = rsDOWN;\n\n\tif ( GetPad(0)->GetLeftJustDown() )\n\t\t*pRsKeys = rsLEFT;\n\n\tif ( GetPad(0)->GetRightJustDown() )\n\t\t*pRsKeys = rsRIGHT;\n\n\tif ( GetPad(0)->GetScrollLockJustDown() )\n\t\t*pRsKeys = rsSCROLL;\n\n\tif ( GetPad(0)->GetPauseJustDown() )\n\t\t*pRsKeys = rsPAUSE;\n\n\tif ( GetPad(0)->GetNumLockJustDown() )\n\t\t*pRsKeys = rsNUMLOCK;\n\n\tif ( GetPad(0)->GetDivideJustDown() )\n\t\t*pRsKeys = rsDIVIDE;\n\n\tif ( GetPad(0)->GetTimesJustDown() )\n\t\t*pRsKeys = rsTIMES;\n\n\tif ( GetPad(0)->GetMinusJustDown() )\n\t\t*pRsKeys = rsMINUS;\n\n\tif ( GetPad(0)->GetPlusJustDown() )\n\t\t*pRsKeys = rsPLUS;\n\n\tif ( GetPad(0)->GetPadEnterJustDown() )\n\t\t*pRsKeys = rsPADENTER;\n\n\tif ( GetPad(0)->GetPadDelJustDown() )\n\t\t*pRsKeys = rsPADDEL;\n\n\tif ( GetPad(0)->GetPad1JustDown() )\n\t\t*pRsKeys = rsPADEND;\n\n\tif ( GetPad(0)->GetPad2JustDown() )\n\t\t*pRsKeys = rsPADDOWN;\n\n\tif ( GetPad(0)->GetPad3JustDown() )\n\t\t*pRsKeys = rsPADPGDN;\n\n\tif ( GetPad(0)->GetPad4JustDown() )\n\t\t*pRsKeys = rsPADLEFT;\n\n\tif ( GetPad(0)->GetPad5JustDown() )\n\t\t*pRsKeys = rsPAD5;\n\n\tif ( GetPad(0)->GetPad6JustDown() )\n\t\t*pRsKeys = rsPADRIGHT;\n\n\tif ( GetPad(0)->GetPad7JustDown() )\n\t\t*pRsKeys = rsPADHOME;\n\n\tif ( GetPad(0)->GetPad8JustDown() )\n\t\t*pRsKeys = rsPADUP;\n\n\tif ( GetPad(0)->GetPad9JustDown() )\n\t\t*pRsKeys = rsPADPGUP;\n\n\tif ( GetPad(0)->GetPad0JustDown() )\n\t\t*pRsKeys = rsPADINS;\n\n\tif ( GetPad(0)->GetBackspaceJustDown() )\n\t\t*pRsKeys = rsBACKSP;\n\n\tif ( GetPad(0)->GetTabJustDown() )\n\t\t*pRsKeys = rsTAB;\n\n\tif ( GetPad(0)->GetCapsLockJustDown() )\n\t\t*pRsKeys = rsCAPSLK;\n\n\tif ( GetPad(0)->GetReturnJustDown() )\n\t\t*pRsKeys = rsENTER;\n\n\tif ( GetPad(0)->GetLeftShiftJustDown() )\n\t\t*pRsKeys = rsLSHIFT;\n\n\tif ( GetPad(0)->GetShiftJustDown() )\n\t\t*pRsKeys = rsSHIFT;\n\n\tif ( GetPad(0)->GetRightShiftJustDown() )\n\t\t*pRsKeys = rsRSHIFT;\n\n\tif ( GetPad(0)->GetLeftCtrlJustDown() )\n\t\t*pRsKeys = rsLCTRL;\n\n\tif ( GetPad(0)->GetRightCtrlJustDown() )\n\t\t*pRsKeys = rsRCTRL;\n\n\tif ( GetPad(0)->GetLeftAltJustDown() )\n\t\t*pRsKeys = rsLALT;\n\n\tif ( GetPad(0)->GetRightAltJustDown() )\n\t\t*pRsKeys = rsRALT;\n\n\tif ( GetPad(0)->GetLeftWinJustDown() )\n\t\t*pRsKeys = rsLWIN;\n\n\tif ( GetPad(0)->GetRightWinJustDown() )\n\t\t*pRsKeys = rsRWIN;\n\n\tif ( GetPad(0)->GetAppsJustDown() )\n\t\t*pRsKeys = rsAPPS;\n\n\treturn pRsKeys;\n}\n\nvoid CPad::FixPadsAfterSave(void)\n{\n\tUpdatePads();\n\tif ( bObsoleteControllerMessage )\n\t{\n\t\tbObsoleteControllerMessage = false;\n\t\tGetPad(0)->Phase = 0;\n\t}\n}\n"
  },
  {
    "path": "src/core/Pad.h",
    "content": "#pragma once\n\nenum {\n\tPLAYERCONTROL_ENABLED = 0,\n\tPLAYERCONTROL_CAMERA = 1,\n\tPLAYERCONTROL_UNK2 = 2,\n\tPLAYERCONTROL_GARAGE = 4,\n\tPLAYERCONTROL_UNK8 = 8,\n\tPLAYERCONTROL_UNK10 = 16,\n\tPLAYERCONTROL_PLAYERINFO = 32,\n\tPLAYERCONTROL_PHONE = 64,\n\tPLAYERCONTROL_CUTSCENE = 128,\n\tPLAYERCONTROL_SHORTCUT_TAXI = 256,\n};\n\nclass CControllerState\n{\npublic:\n\tint16 LeftStickX, LeftStickY;\n\tint16 RightStickX, RightStickY;\n\tint16 LeftShoulder1, LeftShoulder2;\n\tint16 RightShoulder1, RightShoulder2;\n\tint16 DPadUp, DPadDown, DPadLeft, DPadRight;\n\tint16 Start, Select;\n\tint16 Square, Triangle, Cross, Circle;\n\tint16 LeftShock, RightShock;\n\tint16 NetworkTalk;\n\tfloat GetLeftStickX(void) { return LeftStickX/32767.0f; };\n\tfloat GetLeftStickY(void) { return LeftStickY/32767.0f; };\n\tfloat GetRightStickX(void) { return RightStickX/32767.0f; };\n\tfloat GetRightStickY(void) { return RightStickY/32767.0f; };\n\n\tbool CheckForInput();\n\tvoid Clear(void);\n};\nVALIDATE_SIZE(CControllerState, 0x2A);\n\nclass CMouseControllerState\n{\npublic:\n\t//uint32 btns;\t// bit 0-2 button 1-3\n\n\tbool LMB;\n\tbool RMB;\n\tbool MMB;\n\tbool WHEELUP;\n\tbool WHEELDN;\n\tbool MXB1;\n\tbool MXB2;\n\tchar _pad0;\n\t\n\tfloat x, y;\n\t\n\tCMouseControllerState();\n\tvoid Clear();\n};\n\nVALIDATE_SIZE(CMouseControllerState, 0x10);\n\nclass CMousePointerStateHelper\n{\npublic:\n\tbool bInvertHorizontally;\n\tbool bInvertVertically;\n\t\n\tCMouseControllerState GetMouseSetUp();\n};\n\nVALIDATE_SIZE(CMousePointerStateHelper, 0x2);\n\nextern CMousePointerStateHelper MousePointerStateHelper;\n\n\nclass CKeyboardState\n{\npublic:\n\tint16 F[12];\n\tint16 VK_KEYS[256];\n\tint16 ESC;\n\tint16 INS;\n\tint16 DEL;\n\tint16 HOME;\n\tint16 END;\n\tint16 PGUP;\n\tint16 PGDN;\n\tint16 UP;\n\tint16 DOWN;\n\tint16 LEFT;\n\tint16 RIGHT;\n\tint16 SCROLLLOCK;\n\tint16 PAUSE;\n\tint16 NUMLOCK;\n\tint16 DIV;\n\tint16 MUL;\n\tint16 SUB;\n\tint16 ADD;\n\tint16 ENTER;\n\tint16 DECIMAL;\n\tint16 NUM1;\n\tint16 NUM2;\n\tint16 NUM3;\n\tint16 NUM4;\n\tint16 NUM5;\n\tint16 NUM6;\n\tint16 NUM7;\n\tint16 NUM8;\n\tint16 NUM9;\n\tint16 NUM0;\n\tint16 BACKSP;\n\tint16 TAB;\n\tint16 CAPSLOCK;\n\tint16 EXTENTER;\n\tint16 LSHIFT;\n\tint16 RSHIFT;\n\tint16 SHIFT;\n\tint16 LCTRL;\n\tint16 RCTRL;\n\tint16 LALT;\n\tint16 RALT;\n\tint16 LWIN;\n\tint16 RWIN;\n\tint16 APPS;\n\t\n\tvoid Clear();\n};\n\nVALIDATE_SIZE(CKeyboardState, 0x270);\n\nenum\n{\n\t// taken from miss2\n\tPAD1 = 0,\n\tPAD2,\n\t\n\tMAX_PADS\n};\n\nclass CPad\n{\npublic:\n\tenum\n\t{\n\t\tHORNHISTORY_SIZE = 5,\n\t\tDRUNK_STEERING_BUFFER_SIZE = 10,\n\t};\n\tCControllerState NewState;\n\tCControllerState OldState;\n\tint16 SteeringLeftRightBuffer[DRUNK_STEERING_BUFFER_SIZE];\n\tint32 DrunkDrivingBufferUsed;\n\tCControllerState PCTempKeyState;\n\tCControllerState PCTempJoyState;\n\tCControllerState PCTempMouseState;\n\t// straight out of my IDB\n\tint16 Phase;\n\tint16 Mode;\n\tint16 ShakeDur;\n\tuint16 DisablePlayerControls;\n\tuint8 ShakeFreq;\n\tbool bHornHistory[HORNHISTORY_SIZE];\n\tuint8 iCurrHornHistory;\n\tint8 JustOutOfFrontend;\n\tint8 bApplyBrakes;\n\tchar CheatString[12];\n\tint32 LastTimeTouched;\n\tint32 AverageWeapon;\n\tint32 AverageEntries;\n\n#ifdef DETECT_PAD_INPUT_SWITCH\n\tstatic bool IsAffectedByController;\n#endif\n\tCPad() { }\n\t~CPad() { }\n\n\tstatic bool bDisplayNoControllerMessage;\n\tstatic bool bObsoleteControllerMessage;\n\tstatic bool bOldDisplayNoControllerMessage;\n\tstatic bool m_bMapPadOneToPadTwo;\n\tstatic bool m_bDebugCamPCOn;\n\tstatic bool bHasPlayerCheated;\n\tstatic bool bInvertLook4Pad;\n\t\n\tstatic CKeyboardState OldKeyState;\n\tstatic CKeyboardState NewKeyState;\n\tstatic CKeyboardState TempKeyState;\n\tstatic char KeyBoardCheatString[30];\n\tstatic CMouseControllerState OldMouseControllerState;\n\tstatic CMouseControllerState NewMouseControllerState;\n\tstatic CMouseControllerState PCTempMouseControllerState;\n\t\n\t\n#ifdef GTA_PS2_STUFF\n\tstatic void Initialise(void);\n#endif\n\tvoid Clear(bool bResetPlayerControls);\n\tvoid ClearMouseHistory();\n\tvoid ClearKeyBoardHistory();\n\tvoid UpdateMouse();\n\tCControllerState ReconcileTwoControllersInput(CControllerState const &State1, CControllerState const &State2);\n\tvoid StartShake(int16 nDur, uint8 nFreq);\n\tvoid StartShake_Distance(int16 nDur, uint8 nFreq, float fX, float fY, float fz);\n\tvoid StartShake_Train(float fX, float fY);\n#ifdef GTA_PS2_STUFF\n\tvoid AddToCheatString(char c);\n#endif\n\tvoid AddToPCCheatString(char c);\n\n\tstatic void UpdatePads(void);\n\tvoid ProcessPCSpecificStuff(void);\n\tvoid Update(int16 pad);\n\t\n\tstatic void DoCheats(void);\n\tvoid DoCheats(int16 unk);\n\t\n\tstatic void StopPadsShaking(void);\n\tvoid StopShaking(int16 pad);\n\t\n\tstatic CPad *GetPad(int32 pad);\n\t\n\tint16 GetSteeringLeftRight(void);\n\tint16 GetSteeringUpDown(void);\n\tint16 GetCarGunUpDown(void);\n\tint16 GetCarGunLeftRight(void);\n\tint16 GetPedWalkLeftRight(void);\n\tint16 GetPedWalkUpDown(void);\n\tint16 GetAnalogueUpDown(void);\n\tint16 GetAnalogueLeftRight(void);\n\tbool GetLookLeft(void);\n\tbool GetLookRight(void);\n\tbool GetLookBehindForCar(void);\n\tbool GetLookBehindForPed(void);\n\tbool GetHorn(void);\n\tbool HornJustDown(void);\n\tbool GetCarGunFired(void);\n\tbool CarGunJustDown(void);\n\tint16 GetHandBrake(void);\n\tint16 GetBrake(void);\n\tbool GetExitVehicle(void);\n\tbool ExitVehicleJustDown(void);\n\tint32 GetWeapon(void);\n\tbool WeaponJustDown(void);\n\tint16 GetAccelerate(void);\n\tbool CycleCameraModeJustDown(void);\n\tbool CycleCameraModeUpJustDown(void);\n\tbool CycleCameraModeDownJustDown(void);\n\tbool ChangeStationJustDown(void);\n\tbool CycleWeaponLeftJustDown(void);\n\tbool CycleWeaponRightJustDown(void);\n\tbool GetTarget(void);\n\tbool TargetJustDown(void);\n\tbool DuckJustDown(void);\n\tbool CollectPickupJustDown(void);\n\tbool JumpJustDown(void);\n\tbool GetSprint(void);\n\tbool ShiftTargetLeftJustDown(void);\n\tbool ShiftTargetRightJustDown(void);\n\tbool GetAnaloguePadUp(void);\n\tbool GetAnaloguePadDown(void);\n\tbool GetAnaloguePadLeft(void);\n\tbool GetAnaloguePadRight(void);\n\tbool GetAnaloguePadLeftJustUp(void);\n\tbool GetAnaloguePadRightJustUp(void);\n\tbool ForceCameraBehindPlayer(void);\n\tbool SniperZoomIn(void);\n\tbool SniperZoomOut(void);\n\tint16 SniperModeLookLeftRight(void);\n\tint16 SniperModeLookUpDown(void);\n\tint16 LookAroundLeftRight(void);\n\tint16 LookAroundUpDown(void);\n\tvoid ResetAverageWeapon(void);\n\tstatic void FixPadsAfterSave(void);\n\tstatic void PrintErrorMessage(void);\n\tstatic void ResetCheats(void);\n\tstatic char *EditString(char *pStr, int32 nSize);\n\tstatic int32 *EditCodesForControls(int32 *pRsKeys, int32 nSize);\n\tuint32 InputHowLongAgo(void);\n\tvoid SetDrunkInputDelay(int32 delay) { DrunkDrivingBufferUsed = delay; }\n\n#ifdef XINPUT\n\tstatic int XInputJoy1;\n\tstatic int XInputJoy2;\n\tvoid AffectFromXinput(uint32 pad);\n#endif\n\n\t// mouse\n\tbool GetLeftMouseJustDown()           { return !!(NewMouseControllerState.LMB && !OldMouseControllerState.LMB); }\n\tbool GetRightMouseJustDown()          { return !!(NewMouseControllerState.RMB && !OldMouseControllerState.RMB); }\n\tbool GetMiddleMouseJustDown()         { return !!(NewMouseControllerState.MMB && !OldMouseControllerState.MMB); }\n\tbool GetMouseWheelUpJustDown()        { return !!(NewMouseControllerState.WHEELUP && !OldMouseControllerState.WHEELUP); }\n\tbool GetMouseWheelDownJustDown()      { return !!(NewMouseControllerState.WHEELDN && !OldMouseControllerState.WHEELDN);}\n\tbool GetMouseX1JustDown()             { return !!(NewMouseControllerState.MXB1    && !OldMouseControllerState.MXB1); }\n\tbool GetMouseX2JustDown()             { return !!(NewMouseControllerState.MXB2    && !OldMouseControllerState.MXB2); }\n\n\tbool GetLeftMouseJustUp() { return !!(!NewMouseControllerState.LMB && OldMouseControllerState.LMB); }\n\tbool GetRightMouseJustUp() { return !!(!NewMouseControllerState.RMB && OldMouseControllerState.RMB); }\n\tbool GetMiddleMouseJustUp() { return !!(!NewMouseControllerState.MMB && OldMouseControllerState.MMB); }\n\tbool GetMouseWheelUpJustUp() { return !!(!NewMouseControllerState.WHEELUP && OldMouseControllerState.WHEELUP); }\n\tbool GetMouseWheelDownJustUp() { return !!(!NewMouseControllerState.WHEELDN && OldMouseControllerState.WHEELDN); }\n\tbool GetMouseX1JustUp() { return !!(!NewMouseControllerState.MXB1 && OldMouseControllerState.MXB1); }\n\tbool GetMouseX2JustUp() { return !!(!NewMouseControllerState.MXB2 && OldMouseControllerState.MXB2); }\n\n\tbool GetLeftMouse()         { return NewMouseControllerState.LMB; }\n\tbool GetRightMouse()        { return NewMouseControllerState.RMB; }\n\tbool GetMiddleMouse()       { return NewMouseControllerState.MMB; }\n\tbool GetMouseWheelUp()      { return NewMouseControllerState.WHEELUP; }\n\tbool GetMouseWheelDown()    { return NewMouseControllerState.WHEELDN; }\n\tbool GetMouseX1()           { return NewMouseControllerState.MXB1; }\n\tbool GetMouseX2()           { return NewMouseControllerState.MXB2; }\n\n\tbool GetLeftMouseUp()       { return !OldMouseControllerState.LMB; }\n\tbool GetRightMouseUp()      { return !OldMouseControllerState.RMB; }\n\tbool GetMiddleMouseUp()     { return !OldMouseControllerState.MMB; }\n\tbool GetMouseWheelUpUp()    { return !OldMouseControllerState.WHEELUP; }\n\tbool GetMouseWheelDownUp()  { return !OldMouseControllerState.WHEELDN; }\n\tbool GetMouseX1Up()         { return !OldMouseControllerState.MXB1; }\n\tbool GetMouseX2Up()         { return !OldMouseControllerState.MXB2; }\n\n\n\tfloat GetMouseX() { return NewMouseControllerState.x; }\n\tfloat GetMouseY() { return NewMouseControllerState.y; }\n\n\t// keyboard\n\t\n\tbool GetCharJustDown(int32 c) { return !!(NewKeyState.VK_KEYS[c] && !OldKeyState.VK_KEYS[c]); }\n\tbool GetFJustDown(int32 n)    { return !!(NewKeyState.F[n] && !OldKeyState.F[n]); }\n\tbool GetEscapeJustDown()      { return !!(NewKeyState.ESC && !OldKeyState.ESC); }\n\tbool GetInsertJustDown()      { return !!(NewKeyState.INS && !OldKeyState.INS); }\n\tbool GetDeleteJustDown()      { return !!(NewKeyState.DEL && !OldKeyState.DEL); }\n\tbool GetHomeJustDown()        { return !!(NewKeyState.HOME && !OldKeyState.HOME); }\n\tbool GetEndJustDown()         { return !!(NewKeyState.END && !OldKeyState.END); }\n\tbool GetPageUpJustDown()      { return !!(NewKeyState.PGUP && !OldKeyState.PGUP); }\n\tbool GetPageDownJustDown()    { return !!(NewKeyState.PGDN && !OldKeyState.PGDN); }\n\tbool GetUpJustDown()          { return !!(NewKeyState.UP && !OldKeyState.UP); }\n\tbool GetDownJustDown()        { return !!(NewKeyState.DOWN && !OldKeyState.DOWN); }\n\tbool GetLeftJustDown()        { return !!(NewKeyState.LEFT && !OldKeyState.LEFT); }\n\tbool GetRightJustDown()       { return !!(NewKeyState.RIGHT && !OldKeyState.RIGHT); }\n\tbool GetScrollLockJustDown()  { return !!(NewKeyState.SCROLLLOCK && !OldKeyState.SCROLLLOCK); }\n\tbool GetPauseJustDown()       { return !!(NewKeyState.PAUSE && !OldKeyState.PAUSE); }\n\tbool GetNumLockJustDown()     { return !!(NewKeyState.NUMLOCK && !OldKeyState.NUMLOCK); }\n\tbool GetDivideJustDown()      { return !!(NewKeyState.DIV && !OldKeyState.DIV); }\n\tbool GetTimesJustDown()       { return !!(NewKeyState.MUL && !OldKeyState.MUL); }\n\tbool GetMinusJustDown()       { return !!(NewKeyState.SUB && !OldKeyState.SUB); }\n\tbool GetPlusJustDown()        { return !!(NewKeyState.ADD && !OldKeyState.ADD); }\n\tbool GetPadEnterJustDown()    { return !!(NewKeyState.ENTER && !OldKeyState.ENTER); }\n\tbool GetPadDelJustDown()      { return !!(NewKeyState.DECIMAL && !OldKeyState.DECIMAL); }\n\tbool GetPad1JustDown()        { return !!(NewKeyState.NUM1 && !OldKeyState.NUM1); }\n\tbool GetPad2JustDown()        { return !!(NewKeyState.NUM2 && !OldKeyState.NUM2); }\n\tbool GetPad3JustDown()        { return !!(NewKeyState.NUM3 && !OldKeyState.NUM3); }\n\tbool GetPad4JustDown()        { return !!(NewKeyState.NUM4 && !OldKeyState.NUM4); }\n\tbool GetPad5JustDown()        { return !!(NewKeyState.NUM5 && !OldKeyState.NUM5); }\n\tbool GetPad6JustDown()        { return !!(NewKeyState.NUM6 && !OldKeyState.NUM6); }\n\tbool GetPad7JustDown()        { return !!(NewKeyState.NUM7 && !OldKeyState.NUM7); }\n\tbool GetPad8JustDown()        { return !!(NewKeyState.NUM8 && !OldKeyState.NUM8); }\n\tbool GetPad9JustDown()        { return !!(NewKeyState.NUM9 && !OldKeyState.NUM9); }\n\tbool GetPad0JustDown()        { return !!(NewKeyState.NUM0 && !OldKeyState.NUM0); }\n\tbool GetBackspaceJustDown()   { return !!(NewKeyState.BACKSP && !OldKeyState.BACKSP); }\n\tbool GetTabJustDown()         { return !!(NewKeyState.TAB && !OldKeyState.TAB); }\n\tbool GetCapsLockJustDown()    { return !!(NewKeyState.CAPSLOCK && !OldKeyState.CAPSLOCK); }\n\tbool GetReturnJustDown()       { return !!(NewKeyState.EXTENTER && !OldKeyState.EXTENTER); }\n\tbool GetLeftShiftJustDown()   { return !!(NewKeyState.LSHIFT && !OldKeyState.LSHIFT); }\n\tbool GetShiftJustDown()       { return !!(NewKeyState.SHIFT && !OldKeyState.SHIFT); }\n\tbool GetRightShiftJustDown()  { return !!(NewKeyState.RSHIFT && !OldKeyState.RSHIFT); }\n\tbool GetLeftCtrlJustDown()    { return !!(NewKeyState.LCTRL && !OldKeyState.LCTRL); }\n\tbool GetRightCtrlJustDown()   { return !!(NewKeyState.RCTRL && !OldKeyState.RCTRL); }\n\tbool GetLeftAltJustDown()     { return !!(NewKeyState.LALT && !OldKeyState.LALT); }\n\tbool GetRightAltJustDown()    { return !!(NewKeyState.RALT && !OldKeyState.RALT); }\n\tbool GetLeftWinJustDown()     { return !!(NewKeyState.LWIN && !OldKeyState.LWIN); }\n\tbool GetRightWinJustDown()    { return !!(NewKeyState.RWIN && !OldKeyState.RWIN); }\n\tbool GetAppsJustDown()        { return !!(NewKeyState.APPS && !OldKeyState.APPS); }\n\tbool GetEnterJustDown()       { return GetPadEnterJustDown() || GetReturnJustDown(); }\n\tbool GetAltJustDown()         { return GetLeftAltJustDown() || GetRightAltJustDown(); }\n\t\t\t\t\t\t\t\t  \n\tbool GetLeftJustUp() { return !!(!NewKeyState.LEFT && OldKeyState.LEFT); }\n\tbool GetRightJustUp() { return !!(!NewKeyState.RIGHT && OldKeyState.RIGHT); }\n\tbool GetEnterJustUp() { return GetPadEnterJustUp() || GetReturnJustUp(); }\n\tbool GetReturnJustUp() { return !!(!NewKeyState.EXTENTER && OldKeyState.EXTENTER); }\n\tbool GetPadEnterJustUp() { return !!(!NewKeyState.ENTER && OldKeyState.ENTER); }\n\n\tbool GetChar(int32 c)         { return NewKeyState.VK_KEYS[c]; }\n\tbool GetF(int32 n)            { return NewKeyState.F[n]; }\n\tbool GetEscape()              { return NewKeyState.ESC; }\n\tbool GetInsert()              { return NewKeyState.INS; }\n\tbool GetDelete()              { return NewKeyState.DEL; }\n\tbool GetHome()                { return NewKeyState.HOME; }\n\tbool GetEnd()                 { return NewKeyState.END; }\n\tbool GetPageUp()              { return NewKeyState.PGUP; }\n\tbool GetPageDown()            { return NewKeyState.PGDN; }\n\tbool GetUp()                  { return NewKeyState.UP; }\n\tbool GetDown()                { return NewKeyState.DOWN; }\n\tbool GetLeft()                { return NewKeyState.LEFT; }\n\tbool GetRight()               { return NewKeyState.RIGHT; }\n\tbool GetScrollLock()          { return NewKeyState.SCROLLLOCK; }\n\tbool GetPause()               { return NewKeyState.PAUSE; }\n\tbool GetNumLock()             { return NewKeyState.NUMLOCK; }\n\tbool GetDivide()              { return NewKeyState.DIV; }\n\tbool GetTimes()               { return NewKeyState.MUL; }\n\tbool GetMinus()               { return NewKeyState.SUB; }\n\tbool GetPlus()                { return NewKeyState.ADD; }\n\tbool GetPadEnter()            { return NewKeyState.ENTER; } //  GetEnterJustDown\n\tbool GetPadDel()              { return NewKeyState.DECIMAL; }\n\tbool GetPad1()                { return NewKeyState.NUM1; }\n\tbool GetPad2()                { return NewKeyState.NUM2; }\n\tbool GetPad3()                { return NewKeyState.NUM3; }\n\tbool GetPad4()                { return NewKeyState.NUM4; }\n\tbool GetPad5()                { return NewKeyState.NUM5; }\n\tbool GetPad6()                { return NewKeyState.NUM6; }\n\tbool GetPad7()                { return NewKeyState.NUM7; }\n\tbool GetPad8()                { return NewKeyState.NUM8; }\n\tbool GetPad9()                { return NewKeyState.NUM9; }\n\tbool GetPad0()                { return NewKeyState.NUM0; }\n\tbool GetBackspace()           { return NewKeyState.BACKSP; }\n\tbool GetTab()                 { return NewKeyState.TAB; }\n\tbool GetCapsLock()            { return NewKeyState.CAPSLOCK; }\n\tbool GetEnter()               { return NewKeyState.EXTENTER; }\n\tbool GetLeftShift()           { return NewKeyState.LSHIFT; }\n\tbool GetShift()               { return NewKeyState.SHIFT; }\n\tbool GetRightShift()          { return NewKeyState.RSHIFT; }\n\tbool GetLeftCtrl()            { return NewKeyState.LCTRL; }\n\tbool GetRightCtrl()           { return NewKeyState.RCTRL; }\n\tbool GetLeftAlt()             { return NewKeyState.LALT; }\n\tbool GetRightAlt()            { return NewKeyState.RALT; }\n\tbool GetLeftWin()             { return NewKeyState.LWIN; }\n\tbool GetRightWin()            { return NewKeyState.RWIN; }\n\tbool GetApps()                { return NewKeyState.APPS; }\n\t// pad\n\n\tbool GetTriangleJustDown()       { return !!(NewState.Triangle && !OldState.Triangle); }\n\tbool GetCircleJustDown()         { return !!(NewState.Circle && !OldState.Circle); }\n\tbool GetCrossJustDown()          { return !!(NewState.Cross && !OldState.Cross); }\n\tbool GetSquareJustDown()         { return !!(NewState.Square && !OldState.Square); }\n\tbool GetDPadUpJustDown()         { return !!(NewState.DPadUp && !OldState.DPadUp); }\n\tbool GetDPadDownJustDown()       { return !!(NewState.DPadDown && !OldState.DPadDown); }\n\tbool GetDPadLeftJustDown()       { return !!(NewState.DPadLeft && !OldState.DPadLeft); }\n\tbool GetDPadRightJustDown()      { return !!(NewState.DPadRight && !OldState.DPadRight); }\n\tbool GetLeftShoulder1JustDown()  { return !!(NewState.LeftShoulder1 && !OldState.LeftShoulder1); }\n\tbool GetLeftShoulder2JustDown()  { return !!(NewState.LeftShoulder2 && !OldState.LeftShoulder2); }\n\tbool GetRightShoulder1JustDown() { return !!(NewState.RightShoulder1 && !OldState.RightShoulder1); }\n\tbool GetRightShoulder2JustDown() { return !!(NewState.RightShoulder2 && !OldState.RightShoulder2); }\n\tbool GetLeftShockJustDown()      { return !!(NewState.LeftShock && !OldState.LeftShock); }\n\tbool GetRightShockJustDown()     { return !!(NewState.RightShock && !OldState.RightShock); }\n\tbool GetStartJustDown()          { return !!(NewState.Start && !OldState.Start); }\n\tbool GetSelectJustDown()          { return !!(NewState.Select && !OldState.Select); }\n\tbool GetLeftStickXJustDown() { return !!(NewState.LeftStickX && !OldState.LeftStickX); }\n\tbool GetLeftStickYJustDown() { return !!(NewState.LeftStickY && !OldState.LeftStickY); }\n  \n\tbool GetTriangleJustUp() { return !!(!NewState.Triangle && OldState.Triangle); }\n\tbool GetCircleJustUp() { return !!(!NewState.Circle && OldState.Circle); }\n\tbool GetCrossJustUp() { return !!(!NewState.Cross && OldState.Cross); }\n\tbool GetSquareJustUp() { return !!(!NewState.Square && OldState.Square); }\n\tbool GetDPadUpJustUp() { return !!(!NewState.DPadUp && OldState.DPadUp); }\n\tbool GetDPadDownJustUp() { return !!(!NewState.DPadDown && OldState.DPadDown); }\n\tbool GetDPadLeftJustUp() { return !!(!NewState.DPadLeft && OldState.DPadLeft); }\n\tbool GetDPadRightJustUp() { return !!(!NewState.DPadRight && OldState.DPadRight); }\n\n\tbool GetTriangle()           { return !!NewState.Triangle; }\n\tbool GetCircle()             { return !!NewState.Circle; }\n\tbool GetCross()              { return !!NewState.Cross; }\n\tbool GetSquare()             { return !!NewState.Square; }\n\tbool GetDPadUp()             { return !!NewState.DPadUp; }\n\tbool GetDPadDown()           { return !!NewState.DPadDown; }\n\tbool GetDPadLeft()           { return !!NewState.DPadLeft; }\n\tbool GetDPadRight()          { return !!NewState.DPadRight; }\n\tbool GetLeftShoulder1(void)  { return !!NewState.LeftShoulder1; }\n\tbool GetLeftShoulder2(void)  { return !!NewState.LeftShoulder2; }\n\tbool GetRightShoulder1(void) { return !!NewState.RightShoulder1; }\n\tbool GetRightShoulder2(void) { return !!NewState.RightShoulder2; }\n\tbool GetStart()              { return !!NewState.Start; }\n\tbool GetSelect()              { return !!NewState.Select; }\n\tint16 GetLeftStickX(void)    { return NewState.LeftStickX; }\n\tint16 GetLeftStickY(void)    { return NewState.LeftStickY; }\n\tint16 GetRightStickX(void)    { return NewState.RightStickX; }\n\tint16 GetRightStickY(void)    { return NewState.RightStickY; }\n\n\tbool ArePlayerControlsDisabled(void) { return DisablePlayerControls != PLAYERCONTROL_ENABLED; }\n\tvoid SetDisablePlayerControls(uint16 who) { DisablePlayerControls |= who; }\n\tvoid SetEnablePlayerControls(uint16 who) { DisablePlayerControls &= ~who; }\n\tbool IsPlayerControlsDisabledBy(uint16 who) { return DisablePlayerControls & who; }\n\t\n\tint16 GetMode() { return Mode; }\n\tvoid SetMode(int16 mode) { Mode = mode; }\n\t\n\tstatic bool IsNoOrObsolete() { return bDisplayNoControllerMessage || bObsoleteControllerMessage; }\n};\n\nVALIDATE_SIZE(CPad, 0xFC);\nextern CPad Pads[MAX_PADS];\n"
  },
  {
    "path": "src/core/Placeable.cpp",
    "content": "#include \"common.h\"\n#include \"Placeable.h\"\n\n\nCPlaceable::CPlaceable(void)\n{\n\tm_matrix.SetScale(1.0f);\n}\n\nvoid\nCPlaceable::SetHeading(float angle)\n{\n\tCVector pos = GetMatrix().GetPosition();\n\tm_matrix.SetRotateZ(angle);\n\tGetMatrix().Translate(pos);\n}\n\nbool\nCPlaceable::IsWithinArea(float x1, float y1, float x2, float y2)\n{\n\tfloat tmp;\n\n\tif(x1 > x2){\n\t\ttmp = x1;\n\t\tx1 = x2;\n\t\tx2 = tmp;\n\t}\n\tif(y1 > y2){\n\t\ttmp = y1;\n\t\ty1 = y2;\n\t\ty2 = tmp;\n\t}\n\n\treturn x1 <= GetPosition().x && GetPosition().x <= x2 &&\n\t       y1 <= GetPosition().y && GetPosition().y <= y2;\n}\n\nbool\nCPlaceable::IsWithinArea(float x1, float y1, float z1, float x2, float y2, float z2)\n{\n\tfloat tmp;\n\n\tif(x1 > x2){\n\t\ttmp = x1;\n\t\tx1 = x2;\n\t\tx2 = tmp;\n\t}\n\tif(y1 > y2){\n\t\ttmp = y1;\n\t\ty1 = y2;\n\t\ty2 = tmp;\n\t}\n\tif(z1 > z2){\n\t\ttmp = z1;\n\t\tz1 = z2;\n\t\tz2 = tmp;\n\t}\n\n\treturn x1 <= GetPosition().x && GetPosition().x <= x2 &&\n\t       y1 <= GetPosition().y && GetPosition().y <= y2 &&\n\t       z1 <= GetPosition().z && GetPosition().z <= z2;\n}\n"
  },
  {
    "path": "src/core/Placeable.h",
    "content": "#pragma once\n\nclass CPlaceable\n{\npublic:\n\t// disable allocation\n\tstatic void *operator new(size_t);\n\n\tCMatrix m_matrix;\n\n\tCPlaceable(void);\n\tconst CVector &GetPosition(void) { return m_matrix.GetPosition(); }\n\tvoid SetPosition(float x, float y, float z) {\n\t\tm_matrix.GetPosition().x = x;\n\t\tm_matrix.GetPosition().y = y;\n\t\tm_matrix.GetPosition().z = z;\n\t}\n\tvoid SetPosition(const CVector &pos) { m_matrix.GetPosition() = pos; }\n\tCVector &GetRight(void) { return m_matrix.GetRight(); }\n\tCVector &GetForward(void) { return m_matrix.GetForward(); }\n\tCVector &GetUp(void) { return m_matrix.GetUp(); }\n\tCMatrix &GetMatrix(void) { return m_matrix; }\n\tvoid SetTransform(RwMatrix *m) { m_matrix = CMatrix(m, false); }\n\tvoid SetHeading(float angle);\n\tvoid SetOrientation(float x, float y, float z){\n\t\tCVector pos = m_matrix.GetPosition();\n\t\tm_matrix.SetRotate(x, y, z);\n\t\tm_matrix.Translate(pos);\n\t}\n\tbool IsWithinArea(float x1, float y1, float x2, float y2);\n\tbool IsWithinArea(float x1, float y1, float z1, float x2, float y2, float z2);\n};\n\nVALIDATE_SIZE(CPlaceable, 0x4C);\n"
  },
  {
    "path": "src/core/PlayerInfo.cpp",
    "content": "#include \"common.h\"\n\n#include \"Automobile.h\"\n#include \"Bridge.h\"\n#include \"Camera.h\"\n#include \"CarCtrl.h\"\n#include \"Cranes.h\"\n#include \"Darkel.h\"\n#include \"Explosion.h\"\n#include \"Fire.h\"\n#include \"Frontend.h\"\n#include \"General.h\"\n#include \"HandlingMgr.h\"\n#include \"Messages.h\"\n#include \"Pad.h\"\n#include \"PathFind.h\"\n#include \"PlayerInfo.h\"\n#include \"PlayerPed.h\"\n#include \"PlayerSkin.h\"\n#include \"ProjectileInfo.h\"\n#include \"Remote.h\"\n#include \"Renderer.h\"\n#include \"Replay.h\"\n#include \"Script.h\"\n#include \"SpecialFX.h\"\n#include \"Stats.h\"\n#include \"Streaming.h\"\n#include \"Text.h\"\n#include \"Wanted.h\"\n#include \"WaterLevel.h\"\n#include \"World.h\"\n#include \"ZoneCull.h\"\n#include \"main.h\"\n#include \"Bike.h\"\n#include \"Automobile.h\"\n#include \"GameLogic.h\"\n\nCVector lastPlayerPos;\n\nvoid\nCPlayerInfo::Clear(void)\n{\n\tm_pPed = nil;\n\tm_pRemoteVehicle = nil;\n\tif (m_pVehicleEx) {\n\t\tm_pVehicleEx->bUsingSpecialColModel = false;\n\t\tm_pVehicleEx = nil;\n\t}\n\tm_nVisibleMoney = 0;\n\tm_nMoney = m_nVisibleMoney;\n\tm_WBState = WBSTATE_PLAYING;\n\tm_nWBTime = 0;\n\tm_nTrafficMultiplier = 0;\n\tm_fRoadDensity = 1.0f;\n\tm_bInRemoteMode = false;\n\tfield_D5 = false;\n\tfield_D6 = false;\n\tm_bUnusedTaxiThing = false;\n\tm_nUnusedTaxiTimer = 0;\n\tm_nCollectedPackages = 0;\n\tm_nTotalPackages = 3;\n\tm_nTimeLastHealthLoss = 0;\n\tm_nTimeLastArmourLoss = 0;\n\tm_nNextSexFrequencyUpdateTime = 0;\n\tm_nNextSexMoneyUpdateTime = 0;\n\tm_nSexFrequency = 0;\n\tm_pHooker = nil;\n\tm_nTimeTankShotGun = 0;\n\tfield_EC = 0;\n\tm_nUpsideDownCounter = 0;\n\tm_nTimeCarSpentOnTwoWheels = 0;\n\tm_nDistanceCarTravelledOnTwoWheels = 0;\n\tm_nTimeNotFullyOnGround = 0;\n\tm_nTimeSpentOnWheelie = 0;\n\tm_nDistanceTravelledOnWheelie = 0.0f;\n\tm_nTimeSpentOnStoppie = 0;\n\tm_nDistanceTravelledOnStoppie = 0.0f;\n\tm_nCancelWheelStuntTimer = 0;\n\tm_nLastTimeCarSpentOnTwoWheels = 0;\n\tm_nLastDistanceCarTravelledOnTwoWheels = 0;\n\tm_nLastTimeSpentOnWheelie = 0;\n\tm_nLastDistanceTravelledOnWheelie = 0;\n\tm_nLastTimeSpentOnStoppie = 0;\n\tm_nLastDistanceTravelledOnStoppie = 0;\n\tm_bInfiniteSprint = false;\n\tm_bFastReload = false;\n\tm_bFireproof = false;\n\tm_nMaxHealth = m_nMaxArmour = 100;\n\tm_bGetOutOfJailFree = false;\n\tm_bGetOutOfHospitalFree = false;\n\tm_bDriveByAllowed = true;\n\tm_nPreviousTimeRewardedForExplosion = 0;\n\tm_nExplosionsSinceLastReward = 0;\n\tm_nHavocLevel = 0;\n\tm_fMediaAttention = 0.0f;\n\tm_nCurrentBustedAudio = 1;\n\tm_nBustedAudioStatus = BUSTEDAUDIO_NONE;\n}\n\nvoid\nCPlayerInfo::Process(void)\n{\n#ifdef FIX_BUGS\n\tif (CReplay::IsPlayingBack())\n\t\treturn;\n#endif\n\t// Unused taxi feature. Gives you a dollar for every second with a passenger. Can be toggled via 0x29A opcode.\n\tbool startTaxiTimer = true;\n\tif (m_bUnusedTaxiThing && m_pPed->bInVehicle) {\n\t\tCVehicle *veh = m_pPed->m_pMyVehicle;\n\t\tif (veh->IsTaxi()\n\t\t\t&& veh->pDriver == m_pPed && veh->m_nNumPassengers != 0) {\n\t\t\tfor (uint32 timePassed = CTimer::GetTimeInMilliseconds() - m_nUnusedTaxiTimer; timePassed >= 1000; m_nUnusedTaxiTimer += 1000) {\n\t\t\t\ttimePassed -= 1000;\n\t\t\t\t++m_nMoney;\n\t\t\t}\n\t\t\tstartTaxiTimer = false;\n\t\t}\n\t}\n\tif (startTaxiTimer)\n\t\tm_nUnusedTaxiTimer = CTimer::GetTimeInMilliseconds();\n\n\tif (!m_pPed->InVehicle()) {\n\t\tm_nTimeCarSpentOnTwoWheels = 0;\n\t\tm_nTimeNotFullyOnGround = 0;\n\t\tm_nTimeSpentOnWheelie = 0;\n\t\tm_nTimeSpentOnStoppie = 0;\n\t\tm_nCancelWheelStuntTimer = 0;\n\t} else if (m_pPed->m_pMyVehicle->IsCar()) {\n\t\tCAutomobile *car = (CAutomobile*)m_pPed->m_pMyVehicle;\n\n\t\tif (car->m_nWheelsOnGround < 3)\n\t\t\tm_nTimeNotFullyOnGround += CTimer::GetTimeStepInMilliseconds();\n\t\telse\n\t\t\tm_nTimeNotFullyOnGround = 0;\n\n\t\tif (car->m_aSuspensionSpringRatioPrev[2] == 1.f && car->m_aSuspensionSpringRatioPrev[3] == 1.f) {\n\t\t\tif (car->m_aSuspensionSpringRatioPrev[0] < 1.0f && car->m_aSuspensionSpringRatioPrev[1] < 1.0f && car->m_fDamageImpulse == 0.0f) {\n\t\t\t\tm_nTimeCarSpentOnTwoWheels += CTimer::GetTimeStepInMilliseconds();\n\t\t\t\tm_nDistanceCarTravelledOnTwoWheels += car->m_fDistanceTravelled;\n\t\t\t\tm_nCancelWheelStuntTimer = Max(0.0f, m_nCancelWheelStuntTimer - CTimer::GetTimeStepInMilliseconds() * 0.5f);\n\n\t\t\t} else {\n\t\t\t\tif (m_nTimeCarSpentOnTwoWheels != 0 && m_nCancelWheelStuntTimer < 500) {\n\t\t\t\t\tm_nCancelWheelStuntTimer += CTimer::GetTimeStepInMilliseconds();\n\t\t\t\t} else {\n\t\t\t\t\tif (m_nTimeCarSpentOnTwoWheels >= 2000) {\n\t\t\t\t\t\tm_nLastTimeCarSpentOnTwoWheels = m_nTimeCarSpentOnTwoWheels;\n\t\t\t\t\t\tm_nLastDistanceCarTravelledOnTwoWheels = m_nDistanceCarTravelledOnTwoWheels;\n\t\t\t\t\t\tif (CStats::Longest2Wheel < m_nTimeCarSpentOnTwoWheels / 1000)\n\t\t\t\t\t\t\tCStats::Longest2Wheel = m_nTimeCarSpentOnTwoWheels / 1000;\n\t\t\t\t\t\tif (CStats::Longest2WheelDist < m_nDistanceCarTravelledOnTwoWheels)\n\t\t\t\t\t\t\tCStats::Longest2WheelDist = m_nDistanceCarTravelledOnTwoWheels;\n\t\t\t\t\t}\n\t\t\t\t\tm_nTimeCarSpentOnTwoWheels = 0;\n\t\t\t\t\tm_nDistanceCarTravelledOnTwoWheels = 0;\n\t\t\t\t\tm_nCancelWheelStuntTimer = 0;\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (car->m_aSuspensionSpringRatioPrev[0] == 1.0f && car->m_aSuspensionSpringRatioPrev[1] == 1.0f) {\n#ifdef FIX_BUGS\n\t\t\tif (car->m_aSuspensionSpringRatioPrev[2] < 1.f\n#else\n\t\t\tif (car->m_aSuspensionSpringRatioPrev[1] < 1.f\n#endif\n\t\t\t\t&& car->m_aSuspensionSpringRatioPrev[3] < 1.f && 0.0f == car->m_fDamageImpulse) {\n\t\t\t\tm_nTimeCarSpentOnTwoWheels += CTimer::GetTimeStepInMilliseconds();\n\t\t\t\tm_nDistanceCarTravelledOnTwoWheels += car->m_fDistanceTravelled;\n\t\t\t\tm_nCancelWheelStuntTimer = Max(0.0f, m_nCancelWheelStuntTimer - CTimer::GetTimeStepInMilliseconds() * 0.2f);\n\n\t\t\t} else if (m_nTimeCarSpentOnTwoWheels != 0 && m_nCancelWheelStuntTimer < 500) {\n\t\t\t\tm_nCancelWheelStuntTimer += CTimer::GetTimeStepInMilliseconds();\n\n\t\t\t} else {\n\t\t\t\tif (m_nTimeCarSpentOnTwoWheels >= 2000) {\n\t\t\t\t\tm_nLastTimeCarSpentOnTwoWheels = m_nTimeCarSpentOnTwoWheels;\n\t\t\t\t\tm_nLastDistanceCarTravelledOnTwoWheels = m_nDistanceCarTravelledOnTwoWheels;\n\t\t\t\t\tif (CStats::Longest2Wheel < m_nTimeCarSpentOnTwoWheels / 1000)\n\t\t\t\t\t\tCStats::Longest2Wheel = m_nTimeCarSpentOnTwoWheels / 1000;\n\t\t\t\t\tif (CStats::Longest2WheelDist < m_nDistanceCarTravelledOnTwoWheels)\n\t\t\t\t\t\tCStats::Longest2WheelDist = m_nDistanceCarTravelledOnTwoWheels;\n\t\t\t\t}\n\t\t\t\tm_nTimeCarSpentOnTwoWheels = 0;\n\t\t\t\tm_nDistanceCarTravelledOnTwoWheels = 0;\n\t\t\t\tm_nCancelWheelStuntTimer = 0;\n\t\t\t}\n\t\t} else if (m_nTimeCarSpentOnTwoWheels != 0) {\n\t\t\tif (m_nTimeCarSpentOnTwoWheels >= 2000) {\n\t\t\t\tm_nLastTimeCarSpentOnTwoWheels = m_nTimeCarSpentOnTwoWheels;\n\t\t\t\tm_nLastDistanceCarTravelledOnTwoWheels = m_nDistanceCarTravelledOnTwoWheels;\n\t\t\t\tif (CStats::Longest2Wheel < m_nTimeCarSpentOnTwoWheels / 1000)\n\t\t\t\t\tCStats::Longest2Wheel = m_nTimeCarSpentOnTwoWheels / 1000;\n\t\t\t\tif (CStats::Longest2WheelDist < m_nDistanceCarTravelledOnTwoWheels)\n\t\t\t\t\tCStats::Longest2WheelDist = m_nDistanceCarTravelledOnTwoWheels;\n\t\t\t}\n\t\t\tm_nTimeCarSpentOnTwoWheels = 0;\n\t\t\tm_nDistanceCarTravelledOnTwoWheels = 0;\n\t\t\tm_nCancelWheelStuntTimer = 0;\n\t\t}\n\t\tm_nTimeSpentOnWheelie = 0;\n\t\tm_nTimeSpentOnStoppie = 0;\n\t} else if (m_pPed->m_pMyVehicle->IsBike()) {\n\t\tCBike *bike = (CBike*)m_pPed->m_pMyVehicle;\n\t\tif (bike->m_aSuspensionSpringRatioPrev[0] == 1.0f && bike->m_aSuspensionSpringRatioPrev[1] == 1.0f) {\n\t\t\tif (bike->m_aSuspensionSpringRatioPrev[2] < 1.0f\n\t\t\t\t|| (bike->m_aSuspensionSpringRatioPrev[3] < 1.0f && 0.0f == bike->m_fDamageImpulse)) {\n\t\t\t\tm_nTimeSpentOnWheelie += CTimer::GetTimeStepInMilliseconds();\n\t\t\t\tm_nDistanceTravelledOnWheelie += bike->m_fDistanceTravelled;\n\t\t\t\tm_nCancelWheelStuntTimer = Max(0.0f, m_nCancelWheelStuntTimer - CTimer::GetTimeStepInMilliseconds() * 0.2f);\n\n\t\t\t} else {\n\t\t\t\tif (m_nTimeSpentOnWheelie != 0 && m_nCancelWheelStuntTimer < 500) {\n\t\t\t\t\tm_nCancelWheelStuntTimer += CTimer::GetTimeStepInMilliseconds();\n\t\t\t\t} else {\n\t\t\t\t\tif (m_nTimeSpentOnWheelie >= 5000) {\n\t\t\t\t\t\tm_nLastTimeSpentOnWheelie = m_nTimeSpentOnWheelie;\n\t\t\t\t\t\tm_nLastDistanceTravelledOnWheelie = m_nDistanceTravelledOnWheelie;\n\t\t\t\t\t\tif (CStats::LongestWheelie < m_nTimeSpentOnWheelie / 1000)\n\t\t\t\t\t\t\tCStats::LongestWheelie = m_nTimeSpentOnWheelie / 1000;\n\t\t\t\t\t\tif (CStats::LongestWheelieDist < m_nDistanceTravelledOnWheelie)\n\t\t\t\t\t\t\tCStats::LongestWheelieDist = m_nDistanceTravelledOnWheelie;\n\t\t\t\t\t}\n\t\t\t\t\tm_nTimeSpentOnWheelie = 0;\n\t\t\t\t\tm_nDistanceTravelledOnWheelie = 0;\n\t\t\t\t\tm_nCancelWheelStuntTimer = 0;\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (m_nTimeSpentOnWheelie != 0) {\n\t\t\tif (m_nTimeSpentOnWheelie >= 5000) {\n\t\t\t\tm_nLastTimeSpentOnWheelie = m_nTimeSpentOnWheelie;\n\t\t\t\tm_nLastDistanceTravelledOnWheelie = m_nDistanceTravelledOnWheelie;\n\t\t\t\tif (CStats::LongestWheelie < m_nTimeSpentOnWheelie / 1000)\n\t\t\t\t\tCStats::LongestWheelie = m_nTimeSpentOnWheelie / 1000;\n\t\t\t\tif (CStats::LongestWheelieDist < m_nDistanceTravelledOnWheelie)\n\t\t\t\t\tCStats::LongestWheelieDist = m_nDistanceTravelledOnWheelie;\n\t\t\t}\n\t\t\tm_nTimeSpentOnWheelie = 0;\n\t\t\tm_nDistanceTravelledOnWheelie = 0;\n\t\t\tm_nCancelWheelStuntTimer = 0;\n\n\t\t} else if (bike->m_aSuspensionSpringRatioPrev[2] == 1.0f && bike->m_aSuspensionSpringRatioPrev[3] == 1.0f\n\t\t\t&& 0.0f == bike->m_fDamageImpulse) {\n\t\t\tm_nTimeSpentOnStoppie += CTimer::GetTimeStepInMilliseconds();\n\t\t\tm_nDistanceTravelledOnStoppie += bike->m_fDistanceTravelled;\n\t\t\tm_nCancelWheelStuntTimer = Max(0.0f, m_nCancelWheelStuntTimer - CTimer::GetTimeStepInMilliseconds() * 0.2f);\n\n\t\t} else {\n\t\t\tif (m_nTimeSpentOnStoppie != 0 && m_nCancelWheelStuntTimer < 500) {\n\t\t\t\tm_nCancelWheelStuntTimer += CTimer::GetTimeStepInMilliseconds();\n\t\t\t} else {\n\t\t\t\tif (m_nTimeSpentOnStoppie >= 2000) {\n\t\t\t\t\tm_nLastTimeSpentOnStoppie = m_nTimeSpentOnStoppie;\n\t\t\t\t\tm_nLastDistanceTravelledOnStoppie = m_nDistanceTravelledOnStoppie;\n\t\t\t\t\tif (CStats::LongestStoppie < m_nTimeSpentOnStoppie / 1000)\n\t\t\t\t\t\tCStats::LongestStoppie = m_nTimeSpentOnStoppie / 1000;\n\t\t\t\t\tif (CStats::LongestStoppieDist < m_nDistanceTravelledOnStoppie)\n\t\t\t\t\t\tCStats::LongestStoppieDist = m_nDistanceTravelledOnStoppie;\n\t\t\t\t}\n\t\t\t\tm_nTimeSpentOnStoppie = 0;\n\t\t\t\tm_nDistanceTravelledOnStoppie = 0;\n\t\t\t\tm_nCancelWheelStuntTimer = 0;\n\t\t\t}\n\t\t}\n\t\tm_nTimeCarSpentOnTwoWheels = 0;\n\t\tm_nTimeNotFullyOnGround = 0;\n\t} else {\n\t\tm_nTimeCarSpentOnTwoWheels = 0;\n\t\tm_nTimeNotFullyOnGround = 0;\n\t\tm_nTimeSpentOnWheelie = 0;\n\t\tm_nTimeSpentOnStoppie = 0;\n\t\tm_nCancelWheelStuntTimer = 0;\n\t}\n\n\t// The effect that makes money counter does while earning/losing money\n\tif (m_nVisibleMoney != m_nMoney) {\n\t\tint diff = m_nMoney - m_nVisibleMoney;\n\t\tint diffAbs = Abs(diff);\n\t\tint changeBy;\n\n\t\tif (diffAbs > 100000)\n\t\t\tchangeBy = 12345;\n\t\telse if (diffAbs > 10000)\n\t\t\tchangeBy = 1234;\n\t\telse if (diffAbs > 1000)\n\t\t\tchangeBy = 123;\n\t\telse if (diffAbs > 50)\n\t\t\tchangeBy = 42;\n\t\telse\n\t\t\tchangeBy = 1;\n\n\t\tif (diff < 0)\n\t\t\tm_nVisibleMoney -= changeBy;\n\t\telse\n\t\t\tm_nVisibleMoney += changeBy;\n\t}\n\n\tif (!(CTimer::GetFrameCounter() & 15)) {\n\t\tCVector2D playerPos = m_pPed->bInVehicle ? m_pPed->m_pMyVehicle->GetPosition() : m_pPed->GetPosition();\n\t\tm_fRoadDensity = ThePaths.CalcRoadDensity(playerPos.x, playerPos.y);\n\t}\n\n\tm_fRoadDensity = clamp(m_fRoadDensity, 0.5f, 1.45f);\n\n\t// Because vehicle enter/exit use same key binding.\n\tbool enterOrExitVeh;\n\tif (m_pPed->bVehExitWillBeInstant && m_pPed->bInVehicle)\n\t\tenterOrExitVeh = CPad::GetPad(0)->ExitVehicleJustDown();\n\telse\n\t\tenterOrExitVeh = CPad::GetPad(0)->GetExitVehicle();\n\n\tif (enterOrExitVeh && m_pPed->m_nPedState != PED_ANSWER_MOBILE && m_pPed->m_nPedState != PED_SNIPER_MODE && m_pPed->m_nPedState != PED_ROCKET_MODE) {\n\t\tif (m_pPed->bInVehicle) {\n\t\t\tif (!m_pRemoteVehicle) {\n\t\t\t\tCEntity *surfaceBelowVeh = m_pPed->m_pMyVehicle->m_pCurGroundEntity;\n\t\t\t\tif (!surfaceBelowVeh || !CBridge::ThisIsABridgeObjectMovingUp(surfaceBelowVeh->GetModelIndex())) {\n\t\t\t\t\tCVehicle *veh = m_pPed->m_pMyVehicle;\n\t\t\t\t\tif (!veh->IsBoat() || veh->m_nDoorLock == CARLOCK_LOCKED_PLAYER_INSIDE) {\n\t\t\t\t\t\tif (veh->GetStatus() != STATUS_WRECKED && veh->GetStatus() != STATUS_TRAIN_MOVING && veh->m_nDoorLock != CARLOCK_LOCKED_PLAYER_INSIDE) {\n\t\t\t\t\t\t\tbool canJumpOff = false;\n\t\t\t\t\t\t\tif (veh->m_vehType == VEHICLE_TYPE_BIKE) {\n\t\t\t\t\t\t\t\tcanJumpOff = veh->CanPedJumpOffBike();\n\t\t\t\t\t\t\t} else if (veh->pDriver == m_pPed) {\n\t\t\t\t\t\t\t\tcanJumpOff = veh->CanPedJumpOutCar();\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (canJumpOff || veh->m_vecMoveSpeed.Magnitude() < 0.1f) {\n\t\t\t\t\t\t\t\tif (!veh->bIsInWater)\n\t\t\t\t\t\t\t\t\tm_pPed->SetObjective(OBJECTIVE_LEAVE_CAR, veh);\n\n\t\t\t\t\t\t\t} else if (veh->GetStatus() != STATUS_PLAYER && veh != CGameLogic::pShortCutTaxi) {\n\t\t\t\t\t\t\t\tveh->AutoPilot.m_nTempAction = TEMPACT_WAIT;\n\t\t\t\t\t\t\t\tveh->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 1000;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tm_pPed->SetExitBoat(veh);\n\t\t\t\t\t\tm_pPed->bTryingToReachDryLand = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\t// Enter vehicle\n\t\t\tif (CPad::GetPad(0)->ExitVehicleJustDown()) {\n\t\t\t\tbool weAreOnBoat = false;\n\t\t\t\tfloat lastCloseness = 0.0f;\n\t\t\t\tCVehicle *carBelow = nil;\n\t\t\t\tCEntity *surfaceBelow = m_pPed->m_pCurrentPhysSurface;\n\t\t\t\tif (surfaceBelow && surfaceBelow->IsVehicle()) {\n\t\t\t\t\tcarBelow = (CVehicle*)surfaceBelow;\n\t\t\t\t\tif (carBelow->IsBoat() && carBelow->m_modelIndex != MI_SKIMMER) {\n\t\t\t\t\t\tweAreOnBoat = true;\n\t\t\t\t\t\tm_pPed->bOnBoat = true;\n\t\t\t\t\t\tif (carBelow->GetStatus() != STATUS_WRECKED && carBelow->GetUp().z > 0.3f)\n\t\t\t\t\t\t\tm_pPed->SetSeekBoatPosition(carBelow);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// Find closest car\n\t\t\t\tif (!weAreOnBoat) {\n\t\t\t\t\tfloat minX = m_pPed->GetPosition().x - 10.0f;\n\t\t\t\t\tfloat maxX = 10.0f + m_pPed->GetPosition().x;\n\t\t\t\t\tfloat minY = m_pPed->GetPosition().y - 10.0f;\n\t\t\t\t\tfloat maxY = 10.0f + m_pPed->GetPosition().y;\n\n\t\t\t\t\tint minXSector = CWorld::GetSectorIndexX(minX);\n\t\t\t\t\tif (minXSector < 0) minXSector = 0;\n\t\t\t\t\tint minYSector = CWorld::GetSectorIndexY(minY);\n\t\t\t\t\tif (minYSector < 0) minYSector = 0;\n\t\t\t\t\tint maxXSector = CWorld::GetSectorIndexX(maxX);\n\t\t\t\t\tif (maxXSector > NUMSECTORS_X - 1) maxXSector = NUMSECTORS_X - 1;\n\t\t\t\t\tint maxYSector = CWorld::GetSectorIndexY(maxY);\n\t\t\t\t\tif (maxYSector > NUMSECTORS_Y - 1) maxYSector = NUMSECTORS_Y - 1;\n\n\t\t\t\t\tCWorld::AdvanceCurrentScanCode();\n\n\t\t\t\t\tfor (int curY = minYSector; curY <= maxYSector; curY++) {\n\t\t\t\t\t\tfor (int curX = minXSector; curX <= maxXSector; curX++) {\n\t\t\t\t\t\t\tCSector *sector = CWorld::GetSector(curX, curY);\n\t\t\t\t\t\t\tFindClosestCarSectorList(sector->m_lists[ENTITYLIST_VEHICLES], m_pPed,\n\t\t\t\t\t\t\t\tminX, minY, maxX, maxY, &lastCloseness, &carBelow);\n\t\t\t\t\t\t\tFindClosestCarSectorList(sector->m_lists[ENTITYLIST_VEHICLES_OVERLAP], m_pPed,\n\t\t\t\t\t\t\t\tminX, minY, maxX, maxY, &lastCloseness, &carBelow);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// carBelow is now closest vehicle\n\t\t\t\tif (carBelow && !weAreOnBoat) {\n\t\t\t\t\tif (carBelow->GetStatus() == STATUS_TRAIN_NOT_MOVING) {\n\t\t\t\t\t\tm_pPed->SetObjective(OBJECTIVE_ENTER_CAR_AS_PASSENGER, carBelow);\n\t\t\t\t\t} else if (carBelow->IsBoat()) {\n\t\t\t\t\t\tif (!carBelow->pDriver) {\n\t\t\t\t\t\t\tm_pPed->m_vehDoor = 0;\n\t\t\t\t\t\t\tm_pPed->SetEnterCar(carBelow, m_pPed->m_vehDoor);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tm_pPed->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, carBelow);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (m_bInRemoteMode) {\n\t\tuint32 timeWithoutRemoteCar = CTimer::GetTimeInMilliseconds() - m_nTimeLostRemoteCar;\n\t\tif (CTimer::GetPreviousTimeInMilliseconds() - m_nTimeLostRemoteCar < 1000 && timeWithoutRemoteCar >= 1000 && m_WBState == WBSTATE_PLAYING && field_D6) {\n\t\t\tTheCamera.SetFadeColour(0, 0, 0);\n\t\t\tTheCamera.Fade(1.0f, FADE_OUT);\n\t\t}\n\t\tif (timeWithoutRemoteCar > 2000) {\n\t\t\tif (m_WBState == WBSTATE_PLAYING && field_D6) {\n\t\t\t\tTheCamera.RestoreWithJumpCut();\n\t\t\t\tTheCamera.SetFadeColour(0, 0, 0);\n\t\t\t\tTheCamera.Fade(1.0f, FADE_IN);\n\t\t\t\tTheCamera.Process();\n\t\t\t\tCTimer::Stop();\n\t\t\t\tCCullZones::ForceCullZoneCoors(TheCamera.GetPosition());\n\t\t\t\tCRenderer::RequestObjectsInFrustum();\n\t\t\t\tCStreaming::LoadAllRequestedModels(false);\n\t\t\t\tCTimer::Update();\n\t\t\t}\n\t\t\tm_bInRemoteMode = false;\n\t\t\tCWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle->bRemoveFromWorld = true;\n\t\t\tCWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle = nil;\n\t\t\tif (FindPlayerVehicle()) {\n\t\t\t\tFindPlayerVehicle()->SetStatus(STATUS_PLAYER);\n\t\t\t}\n\t\t}\n\t}\n\tif (!(CTimer::GetFrameCounter() & 31)) {\n\t\tCVehicle *veh = FindPlayerVehicle();\n\t\tif (veh && m_pPed->bInVehicle && veh->GetUp().z < 0.0f\n\t\t\t&& veh->m_vecMoveSpeed.Magnitude() < 0.05f && (veh->IsCar() || veh->IsBoat()) && !veh->bIsInWater) {\n\n\t\t\tif (veh->GetUp().z < -0.5f) {\n\t\t\t\tm_nUpsideDownCounter += 2;\n\t\t\t} else {\n\t\t\t\tm_nUpsideDownCounter++;\n\t\t\t}\n\t\t} else {\n\t\t\tm_nUpsideDownCounter = 0;\n\t\t}\n\n\t\tif (m_nUpsideDownCounter > 6 && veh->bCanBeDamaged) {\n\t\t\tveh->m_fHealth = 249.0f < veh->m_fHealth ? 249.0f : veh->m_fHealth;\n\t\t\tif (veh->IsCar()) {\n\t\t\t\tCAutomobile* car = (CAutomobile*)veh;\n\t\t\t\tcar->Damage.SetEngineStatus(225);\n\t\t\t\tcar->m_pSetOnFireEntity = nil;\n\t\t\t}\n\t\t}\n\t}\n\tif (FindPlayerVehicle()) {\n\t\tCVehicle *veh = FindPlayerVehicle();\n\t\tveh->m_nZoneLevel = LEVEL_IGNORE;\n\t\tfor (int i = 0; i < ARRAY_SIZE(veh->pPassengers); i++) {\n\t\t\tif (veh->pPassengers[i])\n\t\t\t\tveh->pPassengers[i]->m_nZoneLevel = LEVEL_GENERIC;\n\t\t}\n\t\tif(veh->m_modelIndex == MI_CADDY)\n\t\t\tCStats::DistanceTravelledByGolfCart += veh->m_fDistanceTravelled;\n\t\telse {\n\t\t\tif(veh->GetVehicleAppearance() == VEHICLE_APPEARANCE_HELI)\n\t\t\t\tCStats::DistanceTravelledByHelicoptor += veh->m_fDistanceTravelled;\n\t\t\tif (veh->GetVehicleAppearance() == VEHICLE_APPEARANCE_PLANE)\n\t\t\t\tCStats::DistanceTravelledByPlane += veh->m_fDistanceTravelled;\n\t\t\tif (veh->GetVehicleAppearance() == VEHICLE_APPEARANCE_CAR)\n\t\t\t\tCStats::DistanceTravelledByCar += veh->m_fDistanceTravelled;\n\t\t\tif (veh->GetVehicleAppearance() == VEHICLE_APPEARANCE_BIKE)\n\t\t\t\tCStats::DistanceTravelledByBike += veh->m_fDistanceTravelled;\n\t\t\tif (veh->GetVehicleAppearance() == VEHICLE_APPEARANCE_BOAT)\n\t\t\t\tCStats::DistanceTravelledByBoat += veh->m_fDistanceTravelled;\n\n\t\t\tif (veh->GetVehicleAppearance() == VEHICLE_APPEARANCE_PLANE) {\n\t\t\t\tif (veh->m_vecMoveSpeed.Magnitude() > 0.2f) {\n\t\t\t\t\tCStats::FlightTime += CTimer::GetTimeStep() * 16.f; // what a weird choice\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} else {\n\t\tCStats::DistanceTravelledOnFoot += FindPlayerPed()->m_fDistanceTravelled;\n\t}\n\n\tif (m_pPed->m_pWanted->GetWantedLevel() && !CTheScripts::IsPlayerOnAMission()) {\n\t\tfloat maxDelta = 0.0f;\n\t\tstatic bool movedSignificantly = true;\n\t\tstatic bool thereIsACarPathNear = true;\n\t\t// there was one more guard without variable's itself???\n\n\t\tif (CTimer::GetTimeInMilliseconds() / 20000 != CTimer::GetPreviousTimeInMilliseconds() / 20000) {\n\t\t\tfloat posChange = (lastPlayerPos - FindPlayerCoors()).Magnitude();\n\t\t\tmovedSignificantly = posChange >= 10.0f;\n\t\t\tlastPlayerPos = FindPlayerCoors();\n\t\t\tthereIsACarPathNear = ThePaths.FindNodeClosestToCoors(FindPlayerCoors(), PATH_CAR, 60.0f, true, false, false, false) != 0;\n\t\t}\n\t\tswitch (m_pPed->m_pWanted->GetWantedLevel()) {\n\t\t\tcase 1:\n\t\t\t\tmaxDelta = 31.f;\n\t\t\t\tbreak;\n\t\t\tcase 2:\n\t\t\t\tmaxDelta = 62.f;\n\t\t\t\tbreak;\n\t\t\tcase 3:\n\t\t\t\tmaxDelta = 125.f;\n\t\t\t\tbreak;\n\t\t\tcase 4:\n\t\t\t\tmaxDelta = 250.f;\n\t\t\t\tbreak;\n\t\t\tcase 5:\n\t\t\t\tmaxDelta = 500.f;\n\t\t\t\tbreak;\n\t\t\tcase 6:\n\t\t\t\tmaxDelta = 1000.f;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t\tfloat increaseDelta = maxDelta - m_fMediaAttention;\n\t\tfloat increaseAttentionBy = CTimer::GetTimeStep() * 0.0001f * increaseDelta;\n\t\tif (increaseAttentionBy < 0.0f\n\t\t\t|| movedSignificantly && thereIsACarPathNear && !CCullZones::NoPolice() && !CCullZones::PoliceAbandonCars() && CGame::currArea == AREA_MAIN_MAP) {\n\t\t\tm_fMediaAttention += increaseAttentionBy;\n\t\t}\n\t} else {\n\t\tm_fMediaAttention = 0.0f;\n\t}\n\tCStats::HighestChaseValue = Max(m_fMediaAttention, CStats::HighestChaseValue);\n\tm_nMoney = Min(999999999, m_nMoney);\n\tm_nVisibleMoney = Min(999999999, m_nVisibleMoney);\n}\n\nbool\nCPlayerInfo::IsPlayerInRemoteMode()\n{\n\treturn m_pRemoteVehicle || m_bInRemoteMode;\n}\n\nvoid\nCPlayerInfo::SavePlayerInfo(uint8 *buf, uint32 *size)\n{\n\t// Interesting\n\t*size = sizeof(CPlayerInfo);\n\n#define CopyToBuf(buf, data) memcpy(buf, &data, sizeof(data)); buf += sizeof(data);\n\tCopyToBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nMoney);\n\tCopyToBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_WBState);\n\tCopyToBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nWBTime);\n\tCopyToBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nTrafficMultiplier);\n\tCopyToBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_fRoadDensity);\n\tCopyToBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nVisibleMoney);\n\tCopyToBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nCollectedPackages);\n\tCopyToBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nTotalPackages);\n\tCopyToBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_bInfiniteSprint);\n\tCopyToBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_bFastReload);\n\tCopyToBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_bFireproof);\n\tCopyToBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nMaxHealth);\n\tCopyToBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nMaxArmour);\n\tCopyToBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_bGetOutOfJailFree);\n\tCopyToBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_bGetOutOfHospitalFree);\n\tCopyToBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_bDriveByAllowed);\n\tCopyToBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_aPlayerName);\n\tCopyToBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nBustedAudioStatus);\n\tCopyToBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nCurrentBustedAudio);\n#undef CopyToBuf\n}\n\nvoid\nCPlayerInfo::LoadPlayerInfo(uint8 *buf, uint32 size)\n{\n#define CopyFromBuf(buf, data) memcpy(&data, buf, sizeof(data)); buf += sizeof(data);\n\tCopyFromBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nMoney);\n\tCopyFromBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_WBState);\n\tCopyFromBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nWBTime);\n\tCopyFromBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nTrafficMultiplier);\n\tCopyFromBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_fRoadDensity);\n\tCopyFromBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nVisibleMoney);\n\tCopyFromBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nCollectedPackages);\n\tCopyFromBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nTotalPackages);\n\tCopyFromBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_bInfiniteSprint);\n\tCopyFromBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_bFastReload);\n\tCopyFromBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_bFireproof);\n\tCopyFromBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nMaxHealth);\n\tCopyFromBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nMaxArmour);\n\tCopyFromBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_bGetOutOfJailFree);\n\tCopyFromBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_bGetOutOfHospitalFree);\n\tCopyFromBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_bDriveByAllowed);\n\tCopyFromBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_aPlayerName);\n\tCopyFromBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nBustedAudioStatus);\n\tCopyFromBuf(buf, CWorld::Players[CWorld::PlayerInFocus].m_nCurrentBustedAudio)\n#undef CopyFromBuf\n}\n\nvoid\nCPlayerInfo::FindClosestCarSectorList(CPtrList& carList, CPed* ped, float unk1, float unk2, float unk3, float unk4, float* lastCloseness, CVehicle** closestCarOutput)\n{\n\tfor (CPtrNode* node = carList.first; node; node = node->next) {\n\t\tCVehicle *car = (CVehicle*)node->item;\n\t\tif(car->m_scanCode != CWorld::GetCurrentScanCode()) {\n\t\t\tif (!car->bUsesCollision || !car->IsVehicle())\n\t\t\t\tcontinue;\n\n\t\t\tcar->m_scanCode = CWorld::GetCurrentScanCode();\n\t\t\tif (car->GetStatus() != STATUS_WRECKED && car->GetStatus() != STATUS_TRAIN_MOVING\n\t\t\t\t&& (car->GetUp().z > 0.3f || (car->IsVehicle() && ((CVehicle*)car)->m_vehType == VEHICLE_TYPE_BIKE))) {\n\t\t\t\tCVector carCentre = car->GetBoundCentre();\n\n\t\t\t\tif (Abs(ped->GetPosition().z - carCentre.z) < 2.0f || car->IsCar() && carCentre.z < ped->GetPosition().z && ped->GetPosition().z - 4.f < carCentre.z) {\n\t\t\t\t\tfloat dist = (ped->GetPosition() - carCentre).Magnitude2D();\n\t\t\t\t\tif (dist <= 10.0f && !CCranes::IsThisCarBeingCarriedByAnyCrane(car)) {\n\t\t\t\t\t\tEvaluateCarPosition(car, ped, dist, lastCloseness, closestCarOutput);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n// lastCloseness is passed to other calls of this function\nvoid\nCPlayerInfo::EvaluateCarPosition(CEntity *carToTest, CPed *player, float carBoundCentrePedDist, float *lastCloseness, CVehicle **closestCarOutput)\n{\n\t// This dist used for determining the angle to face\n\tCVector2D dist(carToTest->GetPosition() - player->GetPosition());\n\tfloat neededTurn = CGeneral::GetATanOfXY(player->GetForward().x, player->GetForward().y) - CGeneral::GetATanOfXY(dist.x, dist.y);\n\twhile (neededTurn >= PI) {\n\t\tneededTurn -= 2 * PI;\n\t}\n\n\twhile (neededTurn < -PI) {\n\t\tneededTurn += 2 * PI;\n\t}\n\n\t// This dist used for evaluating cars' distances, weird...\n\t// Accounts inverted needed turn (or needed turn in long way) and car dist.\n\tfloat closeness = (1.0f - Abs(neededTurn) / TWOPI) * (10.0f - carBoundCentrePedDist);\n\tif (closeness > *lastCloseness) {\n\t\t*lastCloseness = closeness;\n\t\t*closestCarOutput = (CVehicle*)carToTest;\n\t}\n}\n\nconst CVector &\nCPlayerInfo::GetPos()\n{\n#ifdef FIX_BUGS\n\tif (!m_pPed)\n\t\treturn TheCamera.GetPosition();\n#endif\n\tif (m_pPed->InVehicle())\n\t\treturn m_pPed->m_pMyVehicle->GetPosition();\n\treturn m_pPed->GetPosition();\n}\n\nCVector\nFindPlayerCoors(void)\n{\n#ifdef FIX_BUGS\n\tif (CReplay::IsPlayingBack())\n\t\treturn TheCamera.GetPosition();\n#endif\n\tCPlayerPed *ped = FindPlayerPed();\n\tif(ped->InVehicle())\n\t\treturn ped->m_pMyVehicle->GetPosition();\n\telse\n\t\treturn ped->GetPosition();\n}\n\nconst CVector &\nFindPlayerSpeed(void)\n{\n#ifdef FIX_BUGS\n\tstatic CVector vecTmpVector(0.0f, 0.0f, 0.0f);\n\tif (CReplay::IsPlayingBack())\n\t\treturn vecTmpVector;\n#endif\n\tCPlayerPed *ped = FindPlayerPed();\n\tif(ped->InVehicle())\n\t\treturn ped->m_pMyVehicle->m_vecMoveSpeed;\n\telse\n\t\treturn ped->m_vecMoveSpeed;\n}\n\nCVehicle *\nFindPlayerVehicle(void)\n{\n\tCPlayerPed *ped = FindPlayerPed();\n\tif(ped && ped->InVehicle()) return ped->m_pMyVehicle;\n\treturn nil;\n}\n\nCEntity *\nFindPlayerEntity(void)\n{\n\tCPlayerPed *ped = FindPlayerPed();\n\tif(ped->InVehicle())\n\t\treturn ped->m_pMyVehicle;\n\telse\n\t\treturn ped;\n}\n\nCVehicle *\nFindPlayerTrain(void)\n{\n\tif(FindPlayerVehicle() && FindPlayerVehicle()->IsTrain())\n\t\treturn FindPlayerVehicle();\n\telse\n\t\treturn nil;\n}\n\nCPlayerPed *\nFindPlayerPed(void)\n{\n\treturn CWorld::Players[CWorld::PlayerInFocus].m_pPed;\n}\n\nconst CVector &\nFindPlayerCentreOfWorld(int32 player)\n{\n#ifdef FIX_BUGS\n\tif(CReplay::IsPlayingBack()) return TheCamera.GetPosition();\n#endif\n\tif(CCarCtrl::bCarsGeneratedAroundCamera) return TheCamera.GetPosition();\n\tif(CWorld::Players[player].m_pRemoteVehicle) return CWorld::Players[player].m_pRemoteVehicle->GetPosition();\n\tif(FindPlayerVehicle()) return FindPlayerVehicle()->GetPosition();\n\treturn CWorld::Players[player].m_pPed->GetPosition();\n}\n\nconst CVector &\nFindPlayerCentreOfWorld_NoSniperShift(void)\n{\n#ifdef FIX_BUGS\n\tif (CReplay::IsPlayingBack()) return TheCamera.GetPosition();\n#endif\n\tif(CCarCtrl::bCarsGeneratedAroundCamera) return TheCamera.GetPosition();\n\tif(CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle)\n\t\treturn CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle->GetPosition();\n\tif(FindPlayerVehicle()) return FindPlayerVehicle()->GetPosition();\n\treturn FindPlayerPed()->GetPosition();\n}\n\nfloat\nFindPlayerHeading(void)\n{\n\tif(CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle)\n\t\treturn CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle->GetForward().Heading();\n\tif(FindPlayerVehicle()) return FindPlayerVehicle()->GetForward().Heading();\n\treturn FindPlayerPed()->GetForward().Heading();\n}\n\nbool\nCPlayerInfo::IsRestartingAfterDeath()\n{\n\treturn m_WBState == WBSTATE_WASTED;\n}\n\nbool\nCPlayerInfo::IsRestartingAfterArrest()\n{\n\treturn m_WBState == WBSTATE_BUSTED;\n}\n\nvoid\nCPlayerInfo::KillPlayer()\n{\n\tif (m_WBState != WBSTATE_PLAYING) return;\n\n\tm_WBState = WBSTATE_WASTED;\n\tm_nWBTime = CTimer::GetTimeInMilliseconds();\n\tCDarkel::ResetOnPlayerDeath();\n\tCMessages::AddBigMessage(TheText.Get(\"DEAD\"), 4000, 2);\n\tCStats::TimesDied++;\n}\n\nvoid\nCPlayerInfo::ArrestPlayer()\n{\n\tif (m_WBState != WBSTATE_PLAYING) return;\n\n\tm_WBState = WBSTATE_BUSTED;\n\tm_nWBTime = CTimer::GetTimeInMilliseconds();\n\tm_nBustedAudioStatus = BUSTEDAUDIO_NONE;\n\tCDarkel::ResetOnPlayerDeath();\n\tCMessages::AddBigMessage(TheText.Get(\"BUSTED\"), 5000, 2);\n\tCStats::TimesArrested++;\n}\n\nvoid\nCPlayerInfo::PlayerFailedCriticalMission()\n{\n\tif (m_WBState != WBSTATE_PLAYING)\n\t\treturn;\n\tm_WBState = WBSTATE_FAILED_CRITICAL_MISSION;\n\tm_nWBTime = CTimer::GetTimeInMilliseconds();\n\tCDarkel::ResetOnPlayerDeath();\n}\n\nvoid\nCPlayerInfo::CancelPlayerEnteringCars(CVehicle *car)\n{\n\tif (!car || car == m_pPed->m_pMyVehicle) {\n\t\tif (m_pPed->EnteringCar())\n\t\t\tm_pPed->QuitEnteringCar();\n\t}\n\tif (m_pPed->m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER || m_pPed->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER)\n\t\tm_pPed->ClearObjective();\n}\n\nvoid\nCPlayerInfo::MakePlayerSafe(bool toggle)\n{\n\tif (toggle) {\n\t\tm_pPed->m_pWanted->m_bIgnoredByEveryone = true;\n\t\tCWorld::StopAllLawEnforcersInTheirTracks();\n\t\tCPad::GetPad(0)->SetDisablePlayerControls(PLAYERCONTROL_PLAYERINFO);\n\t\tCPad::StopPadsShaking();\n\t\tm_pPed->bBulletProof = true;\n\t\tm_pPed->bFireProof = true;\n\t\tm_pPed->bCollisionProof = true;\n\t\tm_pPed->bMeleeProof = true;\n\t\tm_pPed->bOnlyDamagedByPlayer = true;\n\t\tm_pPed->bExplosionProof = true;\n\t\tm_pPed->m_bCanBeDamaged = false;\n\t\t((CPlayerPed*)m_pPed)->ClearAdrenaline();\n\t\tCancelPlayerEnteringCars(nil);\n\t\tgFireManager.ExtinguishPoint(GetPos(), 4000.0f);\n\t\tCExplosion::RemoveAllExplosionsInArea(GetPos(), 4000.0f);\n\t\tCProjectileInfo::RemoveAllProjectiles();\n\t\tCWorld::SetAllCarsCanBeDamaged(false);\n\t\tCWorld::ExtinguishAllCarFiresInArea(GetPos(), 4000.0f);\n\t\tCReplay::DisableReplays();\n\n\t} else {\n\t\tm_pPed->m_pWanted->m_bIgnoredByEveryone = false;\n\t\tCPad::GetPad(0)->SetEnablePlayerControls(PLAYERCONTROL_PLAYERINFO);\n\t\tm_pPed->bBulletProof = false;\n\t\tm_pPed->bFireProof = false;\n\t\tm_pPed->bCollisionProof = false;\n\t\tm_pPed->bMeleeProof = false;\n\t\tm_pPed->bOnlyDamagedByPlayer = false;\n\t\tm_pPed->bExplosionProof = false;\n\t\tm_pPed->m_bCanBeDamaged = true;\n\t\tCWorld::SetAllCarsCanBeDamaged(true);\n\t\tCReplay::EnableReplays();\n\t}\n}\n\nvoid\nCPlayerInfo::BlowUpRCBuggy(bool actually)\n{\n\tif (!m_pRemoteVehicle || m_pRemoteVehicle->bRemoveFromWorld)\n\t\treturn;\n\n\tCRemote::TakeRemoteControlledCarFromPlayer(actually);\n\tif (actually)\n\t\tm_pRemoteVehicle->BlowUpCar(FindPlayerPed());\n}\n\n#ifdef GTA_PC\nvoid\nCPlayerInfo::SetPlayerSkin(const char *skin)\n{\n\tstrncpy(m_aSkinName, skin, 32);\n\tLoadPlayerSkin();\n}\n\nvoid\nCPlayerInfo::LoadPlayerSkin()\n{\n\tDeletePlayerSkin();\n\n\tm_pSkinTexture = CPlayerSkin::GetSkinTexture(m_aSkinName);\n}\n\nvoid\nCPlayerInfo::DeletePlayerSkin()\n{\n\tif (m_pSkinTexture) {\n\t\tRwTextureDestroy(m_pSkinTexture);\n\t\tm_pSkinTexture = nil;\n\t}\n}\n#endif\n"
  },
  {
    "path": "src/core/PlayerInfo.h",
    "content": "#pragma once\n\n#include \"ColModel.h\"\n\nenum eWastedBustedState\n{\n\tWBSTATE_PLAYING,\n\tWBSTATE_WASTED,\n\tWBSTATE_BUSTED,\n\tWBSTATE_FAILED_CRITICAL_MISSION,\n};\n\nenum eBustedAudioState\n{\n\tBUSTEDAUDIO_NONE,\n\tBUSTEDAUDIO_LOADING,\n\tBUSTEDAUDIO_DONE\n};\n\nclass CEntity;\nclass CPed;\nclass CVehicle;\nclass CPlayerPed;\nclass CCivilianPed;\n\nclass CPlayerInfo\n{\npublic:\n\tCPlayerPed *m_pPed;\n\tCVehicle *m_pRemoteVehicle;\n\tCColModel m_ColModel;\n\tCVehicle *m_pVehicleEx;\t// vehicle using the col model above\n\tchar m_aPlayerName[70];\n\tint32 m_nMoney;\n\tint32 m_nVisibleMoney;\n\tint32 m_nCollectedPackages;\n\tint32 m_nTotalPackages;\n\tuint32 m_nLastBumpPlayerCarTimer;\n\tuint32 m_nUnusedTaxiTimer;\n\tbool m_bUnusedTaxiThing;\n\tuint32 m_nNextSexFrequencyUpdateTime;\n\tuint32 m_nNextSexMoneyUpdateTime;\n\tint32 m_nSexFrequency;\n\tCCivilianPed *m_pHooker;\n\tint8 m_WBState; // eWastedBustedState\n\tuint32 m_nWBTime;\n\tbool m_bInRemoteMode;\n\tbool field_D5;\n\tbool field_D6;\n\tuint32 m_nTimeLostRemoteCar;\n\tuint32 m_nTimeLastHealthLoss;\n\tuint32 m_nTimeLastArmourLoss;\n\tuint32 m_nTimeTankShotGun;\n\tint32 m_nUpsideDownCounter;\n\tint32 field_EC;\n\tint32 m_nTimeCarSpentOnTwoWheels;\n\tint32 m_nDistanceCarTravelledOnTwoWheels;\n\tint32 m_nTimeNotFullyOnGround;\n\tint32 m_nTimeSpentOnWheelie;\n\tfloat m_nDistanceTravelledOnWheelie;\n\tint32 m_nTimeSpentOnStoppie;\n\tfloat m_nDistanceTravelledOnStoppie;\n\tint32 m_nCancelWheelStuntTimer;\n\tint32 m_nLastTimeCarSpentOnTwoWheels;\n\tint32 m_nLastDistanceCarTravelledOnTwoWheels;\n\tint32 m_nLastTimeSpentOnWheelie;\n\tint32 m_nLastDistanceTravelledOnWheelie;\n\tint32 m_nLastTimeSpentOnStoppie;\n\tint32 m_nLastDistanceTravelledOnStoppie;\n\tint16 m_nTrafficMultiplier;\n\tint16 field_12A;\n\tfloat m_fRoadDensity;\n\tuint32 m_nPreviousTimeRewardedForExplosion;\n\tuint32 m_nExplosionsSinceLastReward;\n\tuint32 m_nHavocLevel;\n\tfloat m_fMediaAttention;\n\tbool m_bInfiniteSprint;\n\tbool m_bFastReload;\n\tbool m_bFireproof;\n\tuint8 m_nMaxHealth;\n\tuint8 m_nMaxArmour;\n\tbool m_bGetOutOfJailFree;\n\tbool m_bGetOutOfHospitalFree;\n\tbool m_bDriveByAllowed;\n\tuint8 m_nBustedAudioStatus;\n\tint16 m_nCurrentBustedAudio;\n#ifdef GTA_PC\n\tchar m_aSkinName[32];\n\tRwTexture *m_pSkinTexture;\n#endif\n\n\tvoid MakePlayerSafe(bool);\n\tconst CVector &GetPos();\n\tvoid Process(void);\n\tvoid KillPlayer(void);\n\tvoid ArrestPlayer(void);\n\tbool IsPlayerInRemoteMode(void);\n\tvoid PlayerFailedCriticalMission(void);\n\tvoid Clear(void);\n\tvoid BlowUpRCBuggy(bool);\n\tvoid CancelPlayerEnteringCars(CVehicle*);\n\tbool IsRestartingAfterDeath(void);\n\tbool IsRestartingAfterArrest(void);\n\tvoid EvaluateCarPosition(CEntity*, CPed*, float, float*, CVehicle**);\n\tvoid LoadPlayerInfo(uint8 *buf, uint32 size);\n\tvoid SavePlayerInfo(uint8 *buf, uint32* size);\n\tvoid FindClosestCarSectorList(CPtrList&, CPed*, float, float, float, float, float*, CVehicle**);\n\n#ifdef GTA_PC\n\tvoid LoadPlayerSkin();\n\tvoid SetPlayerSkin(const char *skin);\n\tvoid DeletePlayerSkin();\n#endif\n};\n\nCPlayerPed *FindPlayerPed(void);\nCVehicle *FindPlayerVehicle(void);\nCVehicle *FindPlayerTrain(void);\nCEntity *FindPlayerEntity(void);\nCVector FindPlayerCoors(void);\nconst CVector &FindPlayerSpeed(void);\nconst CVector &FindPlayerCentreOfWorld(int32 player);\nconst CVector &FindPlayerCentreOfWorld_NoSniperShift(void);\nfloat FindPlayerHeading(void);"
  },
  {
    "path": "src/core/Pools.cpp",
    "content": "#include \"common.h\"\n\n#include \"Pools.h\"\n\n#include \"Bike.h\"\n#include \"Boat.h\"\n#include \"CarCtrl.h\"\n#ifdef MISSION_REPLAY\n#include \"GenericGameStorage.h\"\n#endif\n#include \"Population.h\"\n#include \"ProjectileInfo.h\"\n#include \"Streaming.h\"\n#include \"Wanted.h\"\n#include \"World.h\"\n#include \"MemoryHeap.h\"\n\nCCPtrNodePool *CPools::ms_pPtrNodePool;\nCEntryInfoNodePool *CPools::ms_pEntryInfoNodePool;\nCPedPool *CPools::ms_pPedPool;\nCVehiclePool *CPools::ms_pVehiclePool;\nCBuildingPool *CPools::ms_pBuildingPool;\nCTreadablePool *CPools::ms_pTreadablePool;\nCObjectPool *CPools::ms_pObjectPool;\nCDummyPool *CPools::ms_pDummyPool;\nCAudioScriptObjectPool *CPools::ms_pAudioScriptObjectPool;\nCColModelPool *CPools::ms_pColModelPool;\n\n#if defined GTA_PS2 && !defined MASTER\t// or USE_CUSTOM_ALLOCATOR\n// not in VC. perhaps ifdef'ed away\n#define CHECKMEM(msg) CMemCheck::AllocateMemCheckBlock(msg)\n#else\n#define CHECKMEM(msg)\n#endif\n\nvoid\nCPools::Initialise(void)\n{\n\tPUSH_MEMID(MEMID_POOLS);\n\tCHECKMEM(\"before pools\");\n\tms_pPtrNodePool = new CCPtrNodePool(NUMPTRNODES, \"PtrNode\");\n\tCHECKMEM(\"after CPtrNodePool\");\n\tms_pEntryInfoNodePool = new CEntryInfoNodePool(NUMENTRYINFOS, \"EntryInfoNode\");\n\tCHECKMEM(\"after CEntryInfoNodePool\");\n\tms_pPedPool = new CPedPool(NUMPEDS, \"Peds\");\n\tCHECKMEM(\"after CPedPool\");\n\tms_pVehiclePool = new CVehiclePool(NUMVEHICLES, \"Vehicles\");\n\tCHECKMEM(\"after CVehiclePool\");\n\tms_pBuildingPool = new CBuildingPool(NUMBUILDINGS, \"Buildings\");\n\tCHECKMEM(\"after CBuildingPool\");\n\tms_pTreadablePool = new CTreadablePool(NUMTREADABLES, \"Treadables\");\n\tCHECKMEM(\"after CTreadablePool\");\n\tms_pObjectPool = new CObjectPool(NUMOBJECTS, \"Objects\");\n\tCHECKMEM(\"after CObjectPool\");\n\tms_pDummyPool = new CDummyPool(NUMDUMMIES, \"Dummys\");\n\tCHECKMEM(\"after CDummyPool\");\n\tms_pAudioScriptObjectPool = new CAudioScriptObjectPool(NUMAUDIOSCRIPTOBJECTS, \"AudioScriptObj\");\n\tCHECKMEM(\"after cAudioScriptObjectPool\");\n\tms_pColModelPool = new CColModelPool(NUMCOLMODELS, \"ColModel\");\n\tCHECKMEM(\"after pools\");\n\tPOP_MEMID();\n}\n\nvoid\nCPools::ShutDown(void)\n{\n\tdebug(\"PtrNodes left %d\\n\", ms_pPtrNodePool->GetNoOfUsedSpaces());\n\tdebug(\"EntryInfoNodes left %d\\n\", ms_pEntryInfoNodePool->GetNoOfUsedSpaces());\n\tdebug(\"Peds left %d\\n\", ms_pPedPool->GetNoOfUsedSpaces());\n\tdebug(\"Vehicles left %d\\n\", ms_pVehiclePool->GetNoOfUsedSpaces());\n\tdebug(\"Buildings left %d\\n\", ms_pBuildingPool->GetNoOfUsedSpaces());\n\tdebug(\"Treadables left %d\\n\", ms_pTreadablePool->GetNoOfUsedSpaces());\n\tdebug(\"Objects left %d\\n\", ms_pObjectPool->GetNoOfUsedSpaces());\n\tdebug(\"Dummys left %d\\n\", ms_pDummyPool->GetNoOfUsedSpaces());\n\tdebug(\"AudioScriptObjects left %d\\n\", ms_pAudioScriptObjectPool->GetNoOfUsedSpaces());\n\tdebug(\"ColModels left %d\\n\", ms_pColModelPool->GetNoOfUsedSpaces());\n\tprintf(\"Shutdown pool started\\n\");\n\n\tdelete ms_pPtrNodePool;\n\tdelete ms_pEntryInfoNodePool;\n\tdelete ms_pPedPool;\n\tdelete ms_pVehiclePool;\n\tdelete ms_pBuildingPool;\n\tdelete ms_pTreadablePool;\n\tdelete ms_pObjectPool;\n\tdelete ms_pDummyPool;\n\tdelete ms_pAudioScriptObjectPool;\n\tdelete ms_pColModelPool;\n\n\tprintf(\"Shutdown pool done\\n\");\n}\n\nint32 CPools::GetPedRef(CPed *ped) { return ms_pPedPool->GetIndex(ped); }\nCPed *CPools::GetPed(int32 handle) { return ms_pPedPool->GetAt(handle); }\nint32 CPools::GetVehicleRef(CVehicle *vehicle) { return ms_pVehiclePool->GetIndex(vehicle); }\nCVehicle *CPools::GetVehicle(int32 handle) { return ms_pVehiclePool->GetAt(handle); }\nint32 CPools::GetObjectRef(CObject *object) { return ms_pObjectPool->GetIndex(object); }\nCObject *CPools::GetObject(int32 handle) { return ms_pObjectPool->GetAt(handle); }\n\nvoid\nCPools::CheckPoolsEmpty()\n{\n\tassert(ms_pPedPool->GetNoOfUsedSpaces() == 0);\n\tassert(ms_pVehiclePool->GetNoOfUsedSpaces() == 0);\n\tprintf(\"pools have been cleared\\n\");\n}\n\n\nvoid\nCPools::MakeSureSlotInObjectPoolIsEmpty(int32 slot)\n{\n\tif (ms_pObjectPool->GetIsFree(slot)) return;\n\n\tCObject *object = ms_pObjectPool->GetSlot(slot);\n\tif (object->ObjectCreatedBy == TEMP_OBJECT) {\n\t\tCWorld::Remove(object);\n\t\tdelete object;\n\t} else if (!CProjectileInfo::RemoveIfThisIsAProjectile(object)) {\n\t\t// relocate to another slot??\n\t\tCObject *newObject = new CObject(object->GetModelIndex(), false);\n\t\tCWorld::Remove(object);\n#if 0 // todo better\n\t\t*newObject = *object;\n#else\n\t\tmemcpy(newObject, object, ms_pObjectPool->GetMaxEntrySize());\n#endif\n\t\tCWorld::Add(newObject);\n\t\tobject->m_rwObject = nil;\n\t\tdelete object;\n\t\tnewObject->m_pFirstReference = nil;\n\t}\n}\n\n#define CopyFromBuf(buf, data) memcpy(&data, buf, sizeof(data)); SkipSaveBuf(buf, sizeof(data));\n#define CopyToBuf(buf, data) memcpy(buf, &data, sizeof(data)); SkipSaveBuf(buf, sizeof(data));\n\nvoid CPools::LoadVehiclePool(uint8* buf, uint32 size)\n{\nINITSAVEBUF\n\tint nNumCars = ReadSaveBuf<int>(buf);\n\tint nNumBoats = ReadSaveBuf<int>(buf);\n\tint nNumBikes = ReadSaveBuf<int>(buf);\n\tfor (int i = 0; i < nNumCars + nNumBoats + nNumBikes; i++) {\n\t\tuint32 type = ReadSaveBuf<uint32>(buf);\n\t\tint16 model = ReadSaveBuf<int16>(buf);\n\t\tCStreaming::RequestModel(model, STREAMFLAGS_DEPENDENCY);\n\t\tCStreaming::LoadAllRequestedModels(false);\n\t\tint32 slot = ReadSaveBuf<int32>(buf);\n\t\tCVehicle* pVehicle;\n#ifdef COMPATIBLE_SAVES\n\t\tif (type == VEHICLE_TYPE_BOAT)\n\t\t\tpVehicle = new(slot) CBoat(model, RANDOM_VEHICLE);\n\t\telse if (type == VEHICLE_TYPE_CAR)\n\t\t\tpVehicle = new(slot) CAutomobile(model, RANDOM_VEHICLE);\n\t\telse if (type == VEHICLE_TYPE_BIKE)\n\t\t\tpVehicle = new(slot) CBike(model, RANDOM_VEHICLE);\n\t\telse\n\t\t\tassert(0);\n\t\t--CCarCtrl::NumRandomCars;\n\t\tpVehicle->Load(buf);\n\t\tCWorld::Add(pVehicle);\n#else\n\t\tchar* vbuf = new char[Max(CBike::nSaveStructSize, Max(CAutomobile::nSaveStructSize, CBoat::nSaveStructSize))];\n\t\tif (type == VEHICLE_TYPE_BOAT) {\n\t\t\tmemcpy(vbuf, buf, sizeof(CBoat));\n\t\t\tSkipSaveBuf(buf, sizeof(CBoat));\n\t\t\tCBoat* pBoat = new(slot) CBoat(model, RANDOM_VEHICLE);\n\t\t\tpVehicle = pBoat;\n\t\t\t--CCarCtrl::NumRandomCars;\n\t\t}\n\t\telse if (type == VEHICLE_TYPE_CAR) {\n\t\t\tmemcpy(vbuf, buf, sizeof(CAutomobile));\n\t\t\tSkipSaveBuf(buf, sizeof(CAutomobile));\n\t\t\tCStreaming::RequestModel(model, 0); // is it needed?\n\t\t\tCStreaming::LoadAllRequestedModels(false);\n\t\t\tCAutomobile* pAutomobile = new(slot) CAutomobile(model, RANDOM_VEHICLE);\n\t\t\tpVehicle = pAutomobile;\n\t\t\tCCarCtrl::NumRandomCars--; // why?\n\t\t\tpAutomobile->Damage = ((CAutomobile*)vbuf)->Damage;\n\t\t\tpAutomobile->SetupDamageAfterLoad();\n\t\t}\n\t\telse if (type == VEHICLE_TYPE_BIKE) {\n#ifdef FIX_BUGS\n\t\t\tmemcpy(vbuf, buf, sizeof(CBike));\n#else\n\t\t\tmemcpy(vbuf, buf, sizeof(CAutomobile));\n#endif\n\t\t\tSkipSaveBuf(buf, sizeof(CBike));\n\t\t\tCBike* pBike = new(slot) CBike(model, RANDOM_VEHICLE);\n\t\t\tpVehicle = pBike;\n\t\t\t--CCarCtrl::NumRandomCars;\n\t\t}\n\t\telse\n\t\t\tassert(0);\n\t\tCVehicle* pBufferVehicle = (CVehicle*)vbuf;\n\t\tpVehicle->GetMatrix() = pBufferVehicle->GetMatrix();\n\t\tpVehicle->VehicleCreatedBy = pBufferVehicle->VehicleCreatedBy;\n\t\tpVehicle->m_currentColour1 = pBufferVehicle->m_currentColour1;\n\t\tpVehicle->m_currentColour2 = pBufferVehicle->m_currentColour2;\n\t\tpVehicle->m_nAlarmState = pBufferVehicle->m_nAlarmState;\n\t\tpVehicle->m_nNumMaxPassengers = pBufferVehicle->m_nNumMaxPassengers;\n\t\tpVehicle->field_1D0[0] = pBufferVehicle->field_1D0[0];\n\t\tpVehicle->field_1D0[1] = pBufferVehicle->field_1D0[1];\n\t\tpVehicle->field_1D0[2] = pBufferVehicle->field_1D0[2];\n\t\tpVehicle->field_1D0[3] = pBufferVehicle->field_1D0[3];\n\t\tpVehicle->m_fSteerAngle = pBufferVehicle->m_fSteerAngle;\n\t\tpVehicle->m_fGasPedal = pBufferVehicle->m_fGasPedal;\n\t\tpVehicle->m_fBrakePedal = pBufferVehicle->m_fBrakePedal;\n\t\tpVehicle->bIsLawEnforcer = pBufferVehicle->bIsLawEnforcer;\n\t\tpVehicle->bIsLocked = pBufferVehicle->bIsLocked;\n\t\tpVehicle->bEngineOn = pBufferVehicle->bEngineOn;\n\t\tpVehicle->bIsHandbrakeOn = pBufferVehicle->bIsHandbrakeOn;\n\t\tpVehicle->bLightsOn = pBufferVehicle->bLightsOn;\n\t\tpVehicle->bFreebies = pBufferVehicle->bFreebies;\n\t\tpVehicle->m_fHealth = pBufferVehicle->m_fHealth;\n\t\tpVehicle->m_nCurrentGear = pBufferVehicle->m_nCurrentGear;\n\t\tpVehicle->m_fChangeGearTime = pBufferVehicle->m_fChangeGearTime;\n\t\tpVehicle->m_nTimeOfDeath = pBufferVehicle->m_nTimeOfDeath;\n#ifdef FIX_BUGS //must be copypaste\n\t\tpVehicle->m_nBombTimer = pBufferVehicle->m_nBombTimer;\n#else\n\t\tpVehicle->m_nTimeOfDeath = pBufferVehicle->m_nTimeOfDeath;\n#endif\n\t\tpVehicle->m_nDoorLock = pBufferVehicle->m_nDoorLock;\n\t\tpVehicle->SetStatus(pBufferVehicle->GetStatus());\n\t\tpVehicle->SetType(pBufferVehicle->GetType());\n\t\t(pVehicle->GetAddressOfEntityProperties())[0] = (pBufferVehicle->GetAddressOfEntityProperties())[0];\n\t\t(pVehicle->GetAddressOfEntityProperties())[1] = (pBufferVehicle->GetAddressOfEntityProperties())[1];\n\t\tpVehicle->AutoPilot = pBufferVehicle->AutoPilot;\n\t\tCCarCtrl::UpdateCarCount(pVehicle, false);\n\t\tCWorld::Add(pVehicle);\n\t\tdelete[] vbuf;\n#endif\n\t}\nVALIDATESAVEBUF(size)\n}\n\nvoid CPools::SaveVehiclePool(uint8* buf, uint32* size)\n{\nINITSAVEBUF\n\tint nNumCars = 0;\n\tint nNumBoats = 0;\n\tint nNumBikes = 0;\n\tint nPoolSize = GetVehiclePool()->GetSize();\n\tfor (int i = 0; i < nPoolSize; i++) {\n\t\tCVehicle* pVehicle = GetVehiclePool()->GetSlot(i);\n\t\tif (!pVehicle)\n\t\t\tcontinue;\n\t\tbool bHasPassenger = false;\n\t\tfor (int j = 0; j < ARRAY_SIZE(pVehicle->pPassengers); j++) {\n\t\t\tif (pVehicle->pPassengers[j])\n\t\t\t\tbHasPassenger = true;\n\t\t}\n#ifdef MISSION_REPLAY\n\t\tbool bForceSaving = CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_pMyVehicle == pVehicle && IsQuickSave;\n#ifdef FIX_BUGS\n\t\tif ((!pVehicle->pDriver && !bHasPassenger) || bForceSaving) {\n#else\n\t\tif (!pVehicle->pDriver && !bHasPassenger) {\n#endif\n\t\t\tif (pVehicle->IsCar() && (pVehicle->VehicleCreatedBy == MISSION_VEHICLE || bForceSaving))\n\t\t\t\t++nNumCars;\n\t\t\tif (pVehicle->IsBoat() && (pVehicle->VehicleCreatedBy == MISSION_VEHICLE || bForceSaving))\n\t\t\t\t++nNumBoats;\n\t\t\tif (pVehicle->IsBike() && (pVehicle->VehicleCreatedBy == MISSION_VEHICLE || bForceSaving))\n\t\t\t\t++nNumBoats;\n#else\n\t\tif (!pVehicle->pDriver && !bHasPassenger) {\n\t\t\tif (pVehicle->IsCar() && pVehicle->VehicleCreatedBy == MISSION_VEHICLE)\n\t\t\t\t++nNumCars;\n\t\t\tif (pVehicle->IsBoat() && pVehicle->VehicleCreatedBy == MISSION_VEHICLE)\n\t\t\t\t++nNumBoats;\n\t\t\tif (pVehicle->IsBike() && pVehicle->VehicleCreatedBy == MISSION_VEHICLE)\n\t\t\t\t++nNumBoats;\n#endif\n\t\t}\n\t}\n\t*size = nNumCars * (sizeof(uint32) + sizeof(int16) + sizeof(int32) + CAutomobile::nSaveStructSize) + sizeof(int) +\n\t\tnNumBoats * (sizeof(uint32) + sizeof(int16) + sizeof(int32) + CBoat::nSaveStructSize) + sizeof(int) +\n\t\tnNumBikes * (sizeof(uint32) + sizeof(int16) + sizeof(int32) + CBike::nSaveStructSize) + sizeof(int);\n\tWriteSaveBuf(buf, nNumCars);\n\tWriteSaveBuf(buf, nNumBoats);\n\tWriteSaveBuf(buf, nNumBikes);\n\tfor (int i = 0; i < nPoolSize; i++) {\n\t\tCVehicle* pVehicle = GetVehiclePool()->GetSlot(i);\n\t\tif (!pVehicle)\n\t\t\tcontinue;\n\t\tbool bHasPassenger = false;\n\t\tfor (int j = 0; j < ARRAY_SIZE(pVehicle->pPassengers); j++) {\n\t\t\tif (pVehicle->pPassengers[j])\n\t\t\t\tbHasPassenger = true;\n\t\t}\n#ifdef MISSION_REPLAY\n\t\tbool bForceSaving = CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_pMyVehicle == pVehicle && IsQuickSave;\n#endif\n#if defined FIX_BUGS && defined MISSION_REPLAY\n\t\tif ((!pVehicle->pDriver && !bHasPassenger) || bForceSaving) {\n#else\n\t\tif (!pVehicle->pDriver && !bHasPassenger) {\n#endif\n#ifdef COMPATIBLE_SAVES\n#ifdef MISSION_REPLAY\n\t\t\tif ((pVehicle->IsCar() || pVehicle->IsBoat() || pVehicle->IsBike()) && (pVehicle->VehicleCreatedBy == MISSION_VEHICLE || bForceSaving)) {\n#else\n\t\t\tif ((pVehicle->IsCar() || pVehicle->IsBoat() || pVehicle->IsBike()) && pVehicle->VehicleCreatedBy == MISSION_VEHICLE) {\n#endif\n\t\t\t\tWriteSaveBuf<uint32>(buf, pVehicle->m_vehType);\n\t\t\t\tWriteSaveBuf<int16>(buf, pVehicle->GetModelIndex());\n\t\t\t\tWriteSaveBuf<int32>(buf, GetVehicleRef(pVehicle));\n\t\t\t\tpVehicle->Save(buf);\n\t\t\t}\n#else\n#ifdef MISSION_REPLAY\n\t\t\tif (pVehicle->IsCar() && (pVehicle->VehicleCreatedBy == MISSION_VEHICLE || bForceSaving)) {\n#else\n\t\t\tif (pVehicle->IsCar() && pVehicle->VehicleCreatedBy == MISSION_VEHICLE) {\n#endif\n\t\t\t\tWriteSaveBuf(buf, (uint32)pVehicle->m_vehType);\n\t\t\t\tWriteSaveBuf(buf, pVehicle->GetModelIndex());\n\t\t\t\tWriteSaveBuf(buf, GetVehicleRef(pVehicle));\n\t\t\t\tmemcpy(buf, pVehicle, sizeof(CAutomobile));\n\t\t\t\tSkipSaveBuf(buf, sizeof(CAutomobile));\n\t\t\t}\n#ifdef MISSION_REPLAY\n\t\t\tif (pVehicle->IsBoat() && (pVehicle->VehicleCreatedBy == MISSION_VEHICLE || bForceSaving)) {\n#else\n\t\t\tif (pVehicle->IsBoat() && pVehicle->VehicleCreatedBy == MISSION_VEHICLE) {\n#endif\n\t\t\t\tWriteSaveBuf(buf, (uint32)pVehicle->m_vehType);\n\t\t\t\tWriteSaveBuf(buf, pVehicle->GetModelIndex());\n\t\t\t\tWriteSaveBuf(buf, GetVehicleRef(pVehicle));\n\t\t\t\tmemcpy(buf, pVehicle, sizeof(CBoat));\n\t\t\t\tSkipSaveBuf(buf, sizeof(CBoat));\n\t\t\t}\n#ifdef MISSION_REPLAY\n\t\t\tif (pVehicle->IsBike() && (pVehicle->VehicleCreatedBy == MISSION_VEHICLE || bForceSaving)) {\n#else\n\t\t\tif (pVehicle->IsBike() && pVehicle->VehicleCreatedBy == MISSION_VEHICLE) {\n#endif\n\t\t\t\tWriteSaveBuf(buf, (uint32)pVehicle->m_vehType);\n\t\t\t\tWriteSaveBuf(buf, pVehicle->GetModelIndex());\n\t\t\t\tWriteSaveBuf(buf, GetVehicleRef(pVehicle));\n\t\t\t\tmemcpy(buf, pVehicle, sizeof(CBike));\n\t\t\t\tSkipSaveBuf(buf, sizeof(CBike));\n\t\t\t}\n#endif\n\t\t}\n\t}\nVALIDATESAVEBUF(*size)\n}\n\nvoid CPools::SaveObjectPool(uint8* buf, uint32* size)\n{\nINITSAVEBUF\n\tCProjectileInfo::RemoveAllProjectiles();\n\tCObject::DeleteAllTempObjects();\n\tint nObjects = 0;\n\tint nPoolSize = GetObjectPool()->GetSize();\n\tfor (int i = 0; i < nPoolSize; i++) {\n\t\tCObject* pObject = GetObjectPool()->GetSlot(i);\n\t\tif (!pObject)\n\t\t\tcontinue;\n\t\tif (pObject->ObjectCreatedBy == MISSION_OBJECT)\n\t\t\t++nObjects;\n\t}\n\t*size = nObjects * (sizeof(int16) + sizeof(int) + sizeof(CCompressedMatrix) +\n\t\tsizeof(float) + sizeof(CCompressedMatrix) + sizeof(int8) + 7 * sizeof(bool) + sizeof(int16) +\n\t\t+ sizeof(int8) * 2 + sizeof(float) + sizeof(int8) + sizeof(int8) +\n\t\tsizeof(uint32) + 2 * sizeof(uint32)) + sizeof(int);\n\tCopyToBuf(buf, nObjects);\n\tfor (int i = 0; i < nPoolSize; i++) {\n\t\tCObject* pObject = GetObjectPool()->GetSlot(i);\n\t\tif (!pObject)\n\t\t\tcontinue;\n\t\tif (pObject->ObjectCreatedBy == MISSION_OBJECT) {\n\t\t\tbool bIsPickup = pObject->bIsPickup;\n\t\t\tbool bPickupObjWithMessage = pObject->bPickupObjWithMessage;\n\t\t\tbool bOutOfStock = pObject->bOutOfStock;\n\t\t\tbool bGlassCracked = pObject->bGlassCracked;\n\t\t\tbool bGlassBroken = pObject->bGlassBroken;\n\t\t\tbool bHasBeenDamaged = pObject->bHasBeenDamaged;\n\t\t\tbool bUseVehicleColours = pObject->bUseVehicleColours;\n\t\t\tCCompressedMatrix tmp;\n\t\t\tCopyToBuf(buf, pObject->m_modelIndex);\n\t\t\tint32 ref = GetObjectRef(pObject);\n\t\t\tCopyToBuf(buf, ref);\n\t\t\ttmp.CompressFromFullMatrix(pObject->GetMatrix());\n\t\t\tCopyToBuf(buf, tmp);\n\t\t\tCopyToBuf(buf, pObject->m_fUprootLimit);\n\t\t\ttmp.CompressFromFullMatrix(pObject->m_objectMatrix);\n\t\t\tCopyToBuf(buf, tmp);\n\t\t\tCopyToBuf(buf, pObject->ObjectCreatedBy);\n\t\t\tCopyToBuf(buf, bIsPickup);\n\t\t\tCopyToBuf(buf, bPickupObjWithMessage);\n\t\t\tCopyToBuf(buf, bOutOfStock);\n\t\t\tCopyToBuf(buf, bGlassCracked);\n\t\t\tCopyToBuf(buf, bGlassBroken);\n\t\t\tCopyToBuf(buf, bHasBeenDamaged);\n\t\t\tCopyToBuf(buf, bUseVehicleColours);\n\t\t\tCopyToBuf(buf, pObject->m_nCostValue);\n\t\t\tCopyToBuf(buf, pObject->m_nBonusValue);\n\t\t\tSkipSaveBuf(buf, 1);\n\t\t\tCopyToBuf(buf, pObject->m_fCollisionDamageMultiplier);\n\t\t\tCopyToBuf(buf, pObject->m_nCollisionDamageEffect);\n\t\t\tCopyToBuf(buf, pObject->m_nSpecialCollisionResponseCases);\n\t\t\tCopyToBuf(buf, pObject->m_nEndOfLifeTime);\n#ifdef COMPATIBLE_SAVES\n\t\t\tpObject->SaveEntityFlags(buf);\n#else\n\t\t\tCopyToBuf(buf, (pObject->GetAddressOfEntityProperties())[0]);\n\t\t\tCopyToBuf(buf, (pObject->GetAddressOfEntityProperties())[1]);\n#endif\n\t\t}\n\t}\nVALIDATESAVEBUF(*size)\n}\n\nvoid CPools::LoadObjectPool(uint8* buf, uint32 size)\n{\nINITSAVEBUF\n\tint nObjects;\n\tCopyFromBuf(buf, nObjects);\n\tfor (int i = 0; i < nObjects; i++) {\n\t\tint16 mi;\n\t\tCopyFromBuf(buf, mi);\n\t\tint ref;\n\t\tCopyFromBuf(buf, ref);\n\t\tchar* obuf = new char[sizeof(CObject)];\n\t\tCObject* pBufferObject = (CObject*)obuf;\n\t\tCCompressedMatrix tmp;\n\t\tCopyFromBuf(buf, tmp);\n\t\ttmp.DecompressIntoFullMatrix(pBufferObject->GetMatrix());\n\t\tCopyFromBuf(buf, pBufferObject->m_fUprootLimit);\n\t\tCopyFromBuf(buf, tmp);\n\t\ttmp.DecompressIntoFullMatrix(pBufferObject->m_objectMatrix);\n\t\tCopyFromBuf(buf, pBufferObject->ObjectCreatedBy);\n\t\tint8 bitFlag;\n\t\tCopyFromBuf(buf, bitFlag);\n\t\tpBufferObject->bIsPickup = bitFlag;\n\t\tCopyFromBuf(buf, bitFlag);\n\t\tpBufferObject->bPickupObjWithMessage = bitFlag;\n\t\tCopyFromBuf(buf, bitFlag);\n\t\tpBufferObject->bOutOfStock = bitFlag;\n\t\tCopyFromBuf(buf, bitFlag);\n\t\tpBufferObject->bGlassCracked = bitFlag;\n\t\tCopyFromBuf(buf, bitFlag);\n\t\tpBufferObject->bGlassBroken = bitFlag;\n\t\tCopyFromBuf(buf, bitFlag);\n\t\tpBufferObject->bHasBeenDamaged = bitFlag;\n\t\tCopyFromBuf(buf, bitFlag);\n\t\tpBufferObject->bUseVehicleColours = bitFlag;\n\t\tCopyFromBuf(buf, pBufferObject->m_nCostValue);\n\t\tCopyFromBuf(buf, pBufferObject->m_nBonusValue);\n\t\tSkipSaveBuf(buf, 1);\n\t\tCopyFromBuf(buf, pBufferObject->m_fCollisionDamageMultiplier);\n\t\tCopyFromBuf(buf, pBufferObject->m_nCollisionDamageEffect);\n\t\tCopyFromBuf(buf, pBufferObject->m_nSpecialCollisionResponseCases);\n\t\tCopyFromBuf(buf, pBufferObject->m_nEndOfLifeTime);\n#ifndef COMPATIBLE_SAVES\n\t\tCopyFromBuf(buf, (pBufferObject->GetAddressOfEntityProperties())[0]);\n\t\tCopyFromBuf(buf, (pBufferObject->GetAddressOfEntityProperties())[1]);\n#endif\n\t\tif (GetObjectPool()->GetSlot(ref >> 8))\n\t\t\tCPopulation::ConvertToDummyObject(GetObjectPool()->GetSlot(ref >> 8));\n\t\tCObject* pObject = new(ref) CObject(mi, false);\n\t\tpObject->GetMatrix() = pBufferObject->GetMatrix();\n#ifdef COMPATIBLE_SAVES\n\t\tpObject->LoadEntityFlags(buf);\n#endif\n\t\tpObject->m_fUprootLimit = pBufferObject->m_fUprootLimit;\n\t\tpObject->m_objectMatrix = pBufferObject->m_objectMatrix;\n\t\tpObject->ObjectCreatedBy = pBufferObject->ObjectCreatedBy;\n\t\tpObject->bIsPickup = pBufferObject->bIsPickup;\n\t\tpObject->bPickupObjWithMessage = pBufferObject->bPickupObjWithMessage;\n\t\tpObject->bOutOfStock = pBufferObject->bOutOfStock;\n\t\tpObject->bGlassCracked = pBufferObject->bGlassCracked;\n\t\tpObject->bGlassBroken = pBufferObject->bGlassBroken;\n\t\tpObject->bHasBeenDamaged = pBufferObject->bHasBeenDamaged;\n\t\tpObject->bUseVehicleColours = pBufferObject->bUseVehicleColours;\n\t\tpObject->m_fCollisionDamageMultiplier = pBufferObject->m_fCollisionDamageMultiplier;\n\t\tpObject->m_nCollisionDamageEffect = pBufferObject->m_nCollisionDamageEffect;\n\t\tpObject->m_nSpecialCollisionResponseCases = pBufferObject->m_nSpecialCollisionResponseCases;\n\t\tpObject->m_nEndOfLifeTime = pBufferObject->m_nEndOfLifeTime;\n#ifndef COMPATIBLE_SAVES\n\t\t(pObject->GetAddressOfEntityProperties())[0] = (pBufferObject->GetAddressOfEntityProperties())[0];\n\t\t(pObject->GetAddressOfEntityProperties())[1] = (pBufferObject->GetAddressOfEntityProperties())[1];\n#endif\n\t\tpObject->bHasCollided = false;\n\t\tpObject->m_nCostValue = pBufferObject->m_nCostValue;\n\t\tpObject->m_nBonusValue = pBufferObject->m_nBonusValue;\n\t\tCWorld::Add(pObject);\n\t\tdelete[] obuf;\n\t}\nVALIDATESAVEBUF(size)\n}\n\nvoid CPools::SavePedPool(uint8* buf, uint32* size)\n{\nINITSAVEBUF\n\tint nNumPeds = 0;\n\tint nPoolSize = GetPedPool()->GetSize();\n\tfor (int i = 0; i < nPoolSize; i++) {\n\t\tCPed* pPed = GetPedPool()->GetSlot(i);\n\t\tif (!pPed)\n\t\t\tcontinue;\n#ifdef MISSION_REPLAY\n\t\tif ((!pPed->bInVehicle || (pPed == CWorld::Players[CWorld::PlayerInFocus].m_pPed && IsQuickSave)) && pPed->m_nPedType == PEDTYPE_PLAYER1)\n#else\n\t\tif (!pPed->bInVehicle && pPed->m_nPedType == PEDTYPE_PLAYER1)\n#endif\n\t\t\tnNumPeds++;\n\t}\n\t*size = sizeof(int) + nNumPeds * (sizeof(uint32) + sizeof(int16) + sizeof(int) + CPlayerPed::nSaveStructSize +\n\t\tsizeof(CWanted::MaximumWantedLevel) + sizeof(CWanted::nMaximumWantedLevel) + MAX_MODEL_NAME);\n\tCopyToBuf(buf, nNumPeds);\n\tfor (int i = 0; i < nPoolSize; i++) {\n\t\tCPed* pPed = GetPedPool()->GetSlot(i);\n\t\tif (!pPed)\n\t\t\tcontinue;\n#ifdef MISSION_REPLAY\n\t\tif ((!pPed->bInVehicle || (pPed == CWorld::Players[CWorld::PlayerInFocus].m_pPed && IsQuickSave)) && pPed->m_nPedType == PEDTYPE_PLAYER1) {\n#else\n\t\tif (!pPed->bInVehicle && pPed->m_nPedType == PEDTYPE_PLAYER1) {\n#endif\n\t\t\tCopyToBuf(buf, pPed->m_nPedType);\n\t\t\tCopyToBuf(buf, pPed->m_modelIndex);\n\t\t\tint32 ref = GetPedRef(pPed);\n\t\t\tCopyToBuf(buf, ref);\n#ifdef COMPATIBLE_SAVES\n\t\t\tpPed->Save(buf);\n#else\n\t\t\tmemcpy(buf, pPed, sizeof(CPlayerPed));\n\t\t\tSkipSaveBuf(buf, sizeof(CPlayerPed));\n#endif\n\t\t\tCopyToBuf(buf, CWanted::MaximumWantedLevel);\n\t\t\tCopyToBuf(buf, CWanted::nMaximumWantedLevel);\n\t\t\tmemcpy(buf, CModelInfo::GetModelInfo(pPed->GetModelIndex())->GetModelName(), MAX_MODEL_NAME);\n\t\t\tSkipSaveBuf(buf, MAX_MODEL_NAME);\n\t\t}\n\t}\nVALIDATESAVEBUF(*size);\n#undef CopyToBuf\n}\n\nvoid CPools::LoadPedPool(uint8* buf, uint32 size)\n{\nINITSAVEBUF\n\tint nPeds;\n\tCopyFromBuf(buf, nPeds);\n\tfor (int i = 0; i < nPeds; i++) {\n\t\tuint32 pedtype;\n\t\tint16 model;\n\t\tint ref;\n\n\t\tCopyFromBuf(buf, pedtype);\n\t\tCopyFromBuf(buf, model);\n\t\tCopyFromBuf(buf, ref);\n#ifdef COMPATIBLE_SAVES\n\t\tCPed* pPed;\n\n\t\tchar name[MAX_MODEL_NAME];\n\t\t// Unfortunate hack: player model is stored after ped structure.\n\t\t// It could be avoided by just using \"player\" because in practice it is always true.\n\t\tmemcpy(name, buf + CPlayerPed::nSaveStructSize + 2 * sizeof(int32), MAX_MODEL_NAME);\n\t\tCStreaming::RequestSpecialModel(model, name, STREAMFLAGS_DONT_REMOVE);\n\t\tCStreaming::LoadAllRequestedModels(false);\n\n\t\tif (pedtype == PEDTYPE_PLAYER1)\n\t\t\tpPed = new(ref) CPlayerPed();\n\t\telse\n\t\t\tassert(0);\n\n\t\tpPed->Load(buf);\n\t\tif (pedtype == PEDTYPE_PLAYER1) {\n\t\t\tCopyFromBuf(buf, CWanted::MaximumWantedLevel);\n\t\t\tCopyFromBuf(buf, CWanted::nMaximumWantedLevel);\n\t\t\tSkipSaveBuf(buf, MAX_MODEL_NAME);\n\t\t}\n\n\t\tif (pedtype == PEDTYPE_PLAYER1) {\n\t\t\tpPed->m_wepAccuracy = 100;\n\t\t\tCWorld::Players[0].m_pPed = (CPlayerPed*)pPed;\n\t\t}\n\t\tCWorld::Add(pPed);\n#else\n\t\tchar* pbuf = new char[sizeof(CPlayerPed)];\n\t\tCPlayerPed* pBufferPlayer = (CPlayerPed*)pbuf;\n\t\tCPed* pPed;\n\t\tchar name[MAX_MODEL_NAME];\n\t\t// the code implies that there was idea to load non-player ped\n\t\tif (pedtype == PEDTYPE_PLAYER1) { // always true\n\t\t\tmemcpy(pbuf, buf, sizeof(CPlayerPed));\n\t\t\tSkipSaveBuf(buf, sizeof(CPlayerPed));\n\t\t\tCopyFromBuf(buf, CWanted::MaximumWantedLevel);\n\t\t\tCopyFromBuf(buf, CWanted::nMaximumWantedLevel);\n\t\t\tCopyFromBuf(buf, name);\n\t\t}\n\t\tCStreaming::RequestSpecialModel(model, name, STREAMFLAGS_DONT_REMOVE);\n\t\tCStreaming::LoadAllRequestedModels(false);\n\t\tif (pedtype == PEDTYPE_PLAYER1) {\n\t\t\tCPlayerPed* pPlayerPed = new(ref) CPlayerPed();\n\t\t\tfor (int i = 0; i < ARRAY_SIZE(pPlayerPed->m_nTargettableObjects); i++)\n\t\t\t\tpPlayerPed->m_nTargettableObjects[i] = pBufferPlayer->m_nTargettableObjects[i];\n\t\t\tpPlayerPed->m_fMaxStamina = pBufferPlayer->m_fMaxStamina;\n\t\t\tpPed = pPlayerPed;\n\t\t}\n\t\tpPed->SetPosition(pBufferPlayer->GetPosition());\n\t\tpPed->m_fHealth = pBufferPlayer->m_fHealth;\n\t\tpPed->m_fArmour = pBufferPlayer->m_fArmour;\n\t\tpPed->CharCreatedBy = pBufferPlayer->CharCreatedBy;\n\t\tpPed->m_currentWeapon = 0;\n\t\tpPed->m_maxWeaponTypeAllowed = pBufferPlayer->m_maxWeaponTypeAllowed;\n\t\tfor (int i = 0; i < TOTAL_WEAPON_SLOTS; i++) {\n\t\t\tif (pBufferPlayer->HasWeaponSlot(i)) {\n\t\t\t\tint modelId = CWeaponInfo::GetWeaponInfo(pBufferPlayer->GetWeapon(i).m_eWeaponType)->m_nModelId;\n\t\t\t\tif (modelId != -1) {\n\t\t\t\t\tCStreaming::RequestModel(modelId, STREAMFLAGS_DEPENDENCY);\n\t\t\t\t\tint modelId2 = CWeaponInfo::GetWeaponInfo(pBufferPlayer->GetWeapon(i).m_eWeaponType)->m_nModel2Id;\n\t\t\t\t\tif (modelId2 != -1)\n\t\t\t\t\t\tCStreaming::RequestModel(modelId2, STREAMFLAGS_DEPENDENCY);\n\n\t\t\t\t\tCStreaming::LoadAllRequestedModels(false);\n\t\t\t\t}\n\t\t\t\tpPed->GiveWeapon(pBufferPlayer->GetWeapon(i).m_eWeaponType, pBufferPlayer->GetWeapon(i).m_nAmmoTotal, false);\n\t\t\t}\n\t\t}\n\n\t\tif (pedtype == PEDTYPE_PLAYER1) {\n\t\t\tpPed->m_wepAccuracy = 100;\n\t\t\tCWorld::Players[0].m_pPed = (CPlayerPed*)pPed;\n\t\t}\n\t\tCWorld::Add(pPed);\n\t\tdelete[] pbuf;\n#endif\n\t}\nVALIDATESAVEBUF(size)\n}\n\n#undef CopyFromBuf\n#undef CopyToBuf"
  },
  {
    "path": "src/core/Pools.h",
    "content": "#pragma once\n\n#include \"templates.h\"\n#include \"Lists.h\"\n#include \"Treadable.h\"\n#include \"Object.h\"\n#include \"CutsceneObject.h\"\n#include \"PlayerPed.h\"\n#include \"Automobile.h\"\n#include \"DummyPed.h\"\n#include \"AudioScriptObject.h\"\n\ntypedef CPool<CPtrNode> CCPtrNodePool;\ntypedef CPool<CEntryInfoNode> CEntryInfoNodePool;\ntypedef CPool<CPed,CPlayerPed> CPedPool;\ntypedef CPool<CVehicle,CAutomobile> CVehiclePool;\ntypedef CPool<CBuilding> CBuildingPool;\ntypedef CPool<CTreadable> CTreadablePool;\ntypedef CPool<CObject, CCutsceneObject> CObjectPool;\ntypedef CPool<CDummy, CDummyPed> CDummyPool;\ntypedef CPool<cAudioScriptObject> CAudioScriptObjectPool;\ntypedef CPool<CColModel> CColModelPool;\n\nclass CPools\n{\n\tstatic CCPtrNodePool *ms_pPtrNodePool;\n\tstatic CEntryInfoNodePool *ms_pEntryInfoNodePool;\n\tstatic CPedPool *ms_pPedPool;\n\tstatic CVehiclePool *ms_pVehiclePool;\n\tstatic CBuildingPool *ms_pBuildingPool;\n\tstatic CTreadablePool *ms_pTreadablePool;\n\tstatic CObjectPool *ms_pObjectPool;\n\tstatic CDummyPool *ms_pDummyPool;\n\tstatic CAudioScriptObjectPool *ms_pAudioScriptObjectPool;\n\tstatic CColModelPool *ms_pColModelPool;\npublic:\n\tstatic CCPtrNodePool *GetPtrNodePool(void) { return ms_pPtrNodePool; }\n\tstatic CEntryInfoNodePool *GetEntryInfoNodePool(void) { return ms_pEntryInfoNodePool; }\n\tstatic CPedPool *GetPedPool(void) { return ms_pPedPool; }\n\tstatic CVehiclePool *GetVehiclePool(void) { return ms_pVehiclePool; }\n\tstatic CBuildingPool *GetBuildingPool(void) { return ms_pBuildingPool; }\n\tstatic CTreadablePool *GetTreadablePool(void) { return ms_pTreadablePool; }\n\tstatic CObjectPool *GetObjectPool(void) { return ms_pObjectPool; }\n\tstatic CDummyPool *GetDummyPool(void) { return ms_pDummyPool; }\n\tstatic CAudioScriptObjectPool *GetAudioScriptObjectPool(void) { return ms_pAudioScriptObjectPool; }\n\tstatic CColModelPool *GetColModelPool(void) { return ms_pColModelPool; }\n\n\tstatic void Initialise(void);\n\tstatic void ShutDown(void);\n\tstatic int32 GetPedRef(CPed *ped);\n\tstatic CPed *GetPed(int32 handle);\n\tstatic int32 GetVehicleRef(CVehicle *vehicle);\n\tstatic CVehicle *GetVehicle(int32 handle);\n\tstatic int32 GetObjectRef(CObject *object);\n\tstatic CObject *GetObject(int32 handle);\n\tstatic void CheckPoolsEmpty();\n\tstatic void MakeSureSlotInObjectPoolIsEmpty(int32 slot);\n\tstatic void LoadObjectPool(uint8 *buf, uint32 size);\n\tstatic void LoadPedPool(uint8 *buf, uint32 size);\n\tstatic void LoadVehiclePool(uint8 *buf, uint32 size);\n\tstatic void SaveObjectPool(uint8 *buf, uint32 *size);\n\tstatic void SavePedPool(uint8 *buf, uint32 *size);\n\tstatic void SaveVehiclePool(uint8 *buf, uint32 *size);\n};\n"
  },
  {
    "path": "src/core/Profile.cpp",
    "content": "#include \"common.h\"\n#include \"Profile.h\"\n\n#ifndef MASTER\nfloat CProfile::ms_afStartTime[NUM_PROFILES];\nfloat CProfile::ms_afCumulativeTime[NUM_PROFILES];\nfloat CProfile::ms_afEndTime[NUM_PROFILES];\nfloat CProfile::ms_afMaxEndTime[NUM_PROFILES];\nfloat CProfile::ms_afMaxCumulativeTime[NUM_PROFILES];\nConst char *CProfile::ms_pProfileString[NUM_PROFILES];\nRwRGBA CProfile::ms_aBarColours[NUM_PROFILES];\n\nvoid CProfile::Initialise()\n{\n\tms_afMaxEndTime[PROFILE_FRAME_RATE] = 0.0f;\n\tms_afMaxEndTime[PROFILE_PHYSICS] = 0.0f;\n\tms_afMaxEndTime[PROFILE_COLLISION] = 0.0f;\n\tms_afMaxEndTime[PROFILE_PED_AI] = 0.0f;\n\tms_afMaxEndTime[PROFILE_PROCESSING_TIME] = 0.0f;\n\tms_afMaxEndTime[PROFILE_RENDERING_TIME] = 0.0f;\n\tms_afMaxEndTime[PROFILE_TOTAL] = 0.0f;\n\n\tms_pProfileString[PROFILE_FRAME_RATE] = \"Frame rate\";\n\tms_pProfileString[PROFILE_PHYSICS] = \"Physics\";\n\tms_pProfileString[PROFILE_COLLISION] = \"Collision\";\n\tms_pProfileString[PROFILE_PED_AI] = \"Ped AI\";\n\tms_pProfileString[PROFILE_PROCESSING_TIME] = \"Processing time\";\n\tms_pProfileString[PROFILE_RENDERING_TIME] = \"Rendering time\";\n\tms_pProfileString[PROFILE_TOTAL] = \"Total\";\n\n\tms_afMaxCumulativeTime[PROFILE_FRAME_RATE] = 0.0f;\n\tms_afMaxCumulativeTime[PROFILE_PHYSICS] = 0.0f;\n\tms_afMaxCumulativeTime[PROFILE_COLLISION] = 0.0f;\n\tms_afMaxCumulativeTime[PROFILE_PED_AI] = 0.0f;\n\tms_afMaxCumulativeTime[PROFILE_PROCESSING_TIME] = 0.0f;\n\tms_afMaxCumulativeTime[PROFILE_RENDERING_TIME] = 0.0f;\n\tms_afMaxCumulativeTime[PROFILE_TOTAL] = 0.0f;\n\n\tms_aBarColours[PROFILE_PHYSICS] = { 0, 127, 255, 255 };\n\tms_aBarColours[PROFILE_COLLISION] = { 0, 255, 255, 255 };\n\tms_aBarColours[PROFILE_PED_AI] = { 255, 0, 0, 255 };\n\tms_aBarColours[PROFILE_PROCESSING_TIME] = { 0, 255, 0, 255 };\n\tms_aBarColours[PROFILE_RENDERING_TIME] = { 0, 0, 255, 255 };\n\tms_aBarColours[PROFILE_TOTAL] = { 255, 255, 255, 255 };\n}\n\nvoid CProfile::SuspendProfile(eProfile profile)\n{\n\tms_afEndTime[profile] = -ms_afStartTime[profile];\n\tms_afCumulativeTime[profile] -= ms_afStartTime[profile];\n}\n\nvoid CProfile::ShowResults()\n{\n\tms_afMaxEndTime[PROFILE_FRAME_RATE] = Max(ms_afMaxEndTime[PROFILE_FRAME_RATE], ms_afEndTime[PROFILE_FRAME_RATE]);\n\tms_afMaxEndTime[PROFILE_PHYSICS] = Max(ms_afMaxEndTime[PROFILE_PHYSICS], ms_afEndTime[PROFILE_PHYSICS]);\n\tms_afMaxEndTime[PROFILE_COLLISION] = Max(ms_afMaxEndTime[PROFILE_COLLISION], ms_afEndTime[PROFILE_COLLISION]);\n\tms_afMaxEndTime[PROFILE_PED_AI] = Max(ms_afMaxEndTime[PROFILE_PED_AI], ms_afEndTime[PROFILE_PED_AI]);\n\tms_afMaxEndTime[PROFILE_PROCESSING_TIME] = Max(ms_afMaxEndTime[PROFILE_PROCESSING_TIME], ms_afEndTime[PROFILE_PROCESSING_TIME]);\n\tms_afMaxEndTime[PROFILE_RENDERING_TIME] = Max(ms_afMaxEndTime[PROFILE_RENDERING_TIME], ms_afEndTime[PROFILE_RENDERING_TIME]);\n\tms_afMaxEndTime[PROFILE_TOTAL] = Max(ms_afMaxEndTime[PROFILE_TOTAL], ms_afEndTime[PROFILE_TOTAL]);\n\n\tms_afMaxCumulativeTime[PROFILE_FRAME_RATE] = Max(ms_afMaxCumulativeTime[PROFILE_FRAME_RATE], ms_afCumulativeTime[PROFILE_FRAME_RATE]);\n\tms_afMaxCumulativeTime[PROFILE_PHYSICS] = Max(ms_afMaxCumulativeTime[PROFILE_PHYSICS], ms_afCumulativeTime[PROFILE_PHYSICS]);\n\tms_afMaxCumulativeTime[PROFILE_COLLISION] = Max(ms_afMaxCumulativeTime[PROFILE_COLLISION], ms_afCumulativeTime[PROFILE_COLLISION]);\n\tms_afMaxCumulativeTime[PROFILE_PED_AI] = Max(ms_afMaxCumulativeTime[PROFILE_PED_AI], ms_afCumulativeTime[PROFILE_PED_AI]);\n\tms_afMaxCumulativeTime[PROFILE_PROCESSING_TIME] = Max(ms_afMaxCumulativeTime[PROFILE_PROCESSING_TIME], ms_afCumulativeTime[PROFILE_PROCESSING_TIME]);\n\tms_afMaxCumulativeTime[PROFILE_RENDERING_TIME] = Max(ms_afMaxCumulativeTime[PROFILE_RENDERING_TIME], ms_afCumulativeTime[PROFILE_RENDERING_TIME]);\n\tms_afMaxCumulativeTime[PROFILE_TOTAL] = Max(ms_afMaxCumulativeTime[PROFILE_TOTAL], ms_afCumulativeTime[PROFILE_TOTAL]);\n}\n#endif\n"
  },
  {
    "path": "src/core/Profile.h",
    "content": "#pragma once\n\nenum eProfile\n{\n\tPROFILE_FRAME_RATE,\n\tPROFILE_PHYSICS,\n\tPROFILE_COLLISION,\n\tPROFILE_PED_AI,\n\tPROFILE_PROCESSING_TIME,\n\tPROFILE_RENDERING_TIME,\n\tPROFILE_TOTAL,\n\tNUM_PROFILES,\n};\n\nclass CProfile\n{\n\tstatic float ms_afStartTime[NUM_PROFILES];\n\tstatic float ms_afCumulativeTime[NUM_PROFILES];\n\tstatic float ms_afEndTime[NUM_PROFILES];\n\tstatic float ms_afMaxEndTime[NUM_PROFILES];\n\tstatic float ms_afMaxCumulativeTime[NUM_PROFILES];\n\tstatic Const char *ms_pProfileString[NUM_PROFILES];\n\tstatic RwRGBA ms_aBarColours[NUM_PROFILES];\npublic:\n\tstatic void Initialise();\n\tstatic void SuspendProfile(eProfile profile);\n\tstatic void ShowResults();\n};\n"
  },
  {
    "path": "src/core/Radar.cpp",
    "content": "#if (!defined(GTA_PS2_STUFF) && defined(RWLIBS)) || defined(__MWERKS__)\n#define WITHD3D\n#endif\n#include \"config.h\"\n#include \"common.h\"\n\n#include \"RwHelper.h\"\n#include \"Radar.h\"\n#include \"Camera.h\"\n#include \"Hud.h\"\n#include \"World.h\"\n#include \"Frontend.h\"\n#include \"General.h\"\n#include \"Vehicle.h\"\n#include \"Pools.h\"\n#include \"Script.h\"\n#include \"TxdStore.h\"\n#include \"World.h\"\n#include \"Streaming.h\"\n#include \"SpecialFX.h\"\n#include \"Font.h\"\n\nfloat CRadar::m_radarRange;\nsRadarTrace CRadar::ms_RadarTrace[NUMRADARBLIPS];\nCVector2D vec2DRadarOrigin;\nint32 gRadarTxdIds[64];\n\nCSprite2d CRadar::CentreSprite;\nCSprite2d CRadar::MapHereSprite;\nCSprite2d CRadar::NorthSprite;\nCSprite2d CRadar::AverySprite;\nCSprite2d CRadar::BikerSprite;\nCSprite2d CRadar::CortezSprite;\nCSprite2d CRadar::DiazSprite;\nCSprite2d CRadar::KentSprite;\nCSprite2d CRadar::LawyerSprite;\nCSprite2d CRadar::PhilSprite;\nCSprite2d CRadar::BikersSprite;\nCSprite2d CRadar::BoatyardSprite;\nCSprite2d CRadar::MalibuClubSprite;\nCSprite2d CRadar::CubansSprite;\nCSprite2d CRadar::FilmSprite;\nCSprite2d CRadar::GunSprite;\nCSprite2d CRadar::HaitiansSprite;\nCSprite2d CRadar::HardwareSprite;\nCSprite2d CRadar::SaveHouseSprite;\nCSprite2d CRadar::StripSprite;\nCSprite2d CRadar::IceSprite;\nCSprite2d CRadar::KCabsSprite;\nCSprite2d CRadar::LovefistSprite;\nCSprite2d CRadar::PrintworksSprite;\nCSprite2d CRadar::PropertySprite;\nCSprite2d CRadar::SunYardSprite;\nCSprite2d CRadar::SpraySprite;\nCSprite2d CRadar::TShirtSprite;\nCSprite2d CRadar::TommySprite;\nCSprite2d CRadar::PhoneSprite;\nCSprite2d CRadar::RadioWildstyleSprite;\nCSprite2d CRadar::RadioFlashSprite;\nCSprite2d CRadar::RadioKChatSprite;\nCSprite2d CRadar::RadioFeverSprite;\nCSprite2d CRadar::RadioVRockSprite;\nCSprite2d CRadar::RadioVCPRSprite;\nCSprite2d CRadar::RadioEspantosoSprite;\nCSprite2d CRadar::RadioEmotionSprite;\nCSprite2d CRadar::RadioWaveSprite;\n\nCSprite2d *CRadar::RadarSprites[RADAR_SPRITE_COUNT] = { \n\tnil,\n\t&CentreSprite,\n\t&MapHereSprite,\n\t&NorthSprite,\n\t&AverySprite,\n\t&BikerSprite,\n\t&CortezSprite,\n\t&DiazSprite,\n\t&KentSprite,\n\t&LawyerSprite,\n\t&PhilSprite,\n\t&BikersSprite,\n\t&BoatyardSprite,\n\t&MalibuClubSprite,\n\t&CubansSprite,\n\t&FilmSprite,\n\t&GunSprite,\n\t&HaitiansSprite,\n\t&HardwareSprite,\n\t&SaveHouseSprite,\n\t&StripSprite,\n\t&IceSprite,\n\t&KCabsSprite,\n\t&LovefistSprite,\n\t&PrintworksSprite,\n\t&PropertySprite,\n\t&SunYardSprite,\n\t&SpraySprite,\n\t&TShirtSprite,\n\t&TommySprite,\n\t&PhoneSprite,\n\t&RadioWildstyleSprite,\n\t&RadioFlashSprite,\n\t&RadioKChatSprite,\n\t&RadioFeverSprite,\n\t&RadioVRockSprite,\n\t&RadioVCPRSprite,\n\t&RadioEspantosoSprite,\n\t&RadioEmotionSprite,\n\t&RadioWaveSprite\n};\n\n// Why this doesn't coincide with world coordinates i don't know\n#define RADAR_MIN_X (-2000.0f)\n#define RADAR_MIN_Y (-2000.0f)\n#define RADAR_MAX_X (2000.0f)\n#define RADAR_MAX_Y (2000.0f)\n#define RADAR_SIZE_X (RADAR_MAX_X - RADAR_MIN_X)\n#define RADAR_SIZE_Y (RADAR_MAX_Y - RADAR_MIN_Y)\n\n#define RADAR_NUM_TILES (8)\n#define RADAR_TILE_SIZE (RADAR_SIZE_X / RADAR_NUM_TILES)\nstatic_assert(RADAR_TILE_SIZE == (RADAR_SIZE_Y / RADAR_NUM_TILES), \"CRadar: not a square\");\n\n#define RADAR_MIN_RANGE (120.0f)\n#define RADAR_MAX_RANGE (350.0f)\n#define RADAR_MIN_SPEED (0.3f)\n#define RADAR_MAX_SPEED (0.9f)\n\nCRGBA CRadar::ArrowBlipColour1;\nCRGBA CRadar::ArrowBlipColour2;\nint16 CRadar::MapLegendCounter;\nint16 CRadar::MapLegendList[NUM_MAP_LEGENDS];\n#ifdef MAP_ENHANCEMENTS\nint CRadar::TargetMarkerId = -1;\nCVector CRadar::TargetMarkerPos;\n#endif\n\nfloat CRadar::cachedCos;\nfloat CRadar::cachedSin;\n\nvoid ClipRadarTileCoords(int32 &x, int32 &y)\n{\n\tif (x < 0)\n\t\tx = 0;\n\tif (x > RADAR_NUM_TILES-1)\n\t\tx = RADAR_NUM_TILES-1;\n\tif (y < 0)\n\t\ty = 0;\n\tif (y > RADAR_NUM_TILES-1)\n\t\ty = RADAR_NUM_TILES-1;\n}\n\nvoid RequestMapSection(int32 x, int32 y)\n{\n\tClipRadarTileCoords(x, y);\n\tCStreaming::RequestTxd(gRadarTxdIds[x + RADAR_NUM_TILES * y], STREAMFLAGS_DONT_REMOVE | STREAMFLAGS_DEPENDENCY);\n}\n\nvoid RemoveMapSection(int32 x, int32 y)\n{\n\tif (x >= 0 && x <= RADAR_NUM_TILES - 1 && y >= 0 && y <= RADAR_NUM_TILES - 1)\n\t\tCStreaming::RemoveTxd(gRadarTxdIds[x + RADAR_NUM_TILES * y]);\n}\n\n// Transform from section indices to world coordinates\nvoid GetTextureCorners(int32 x, int32 y, CVector2D *out)\n{\n\tx =   x - RADAR_NUM_TILES/2;\n\ty = -(y - RADAR_NUM_TILES/2);\n\n\t// bottom left\n\tout[0].x = RADAR_TILE_SIZE * (x);\n\tout[0].y = RADAR_TILE_SIZE * (y - 1);\n\n\t// bottom right\n\tout[1].x = RADAR_TILE_SIZE * (x + 1);\n\tout[1].y = RADAR_TILE_SIZE * (y - 1);\n\n\t// top right\n\tout[2].x = RADAR_TILE_SIZE * (x + 1);\n\tout[2].y = RADAR_TILE_SIZE * (y);\n\n\t// top left\n\tout[3].x = RADAR_TILE_SIZE * (x);\n\tout[3].y = RADAR_TILE_SIZE * (y);\n}\n\n\nbool IsPointInsideRadar(const CVector2D &point)\n{\n\tif (point.x < -1.0f || point.x > 1.0f) return false;\n\tif (point.y < -1.0f || point.y > 1.0f) return false;\n\treturn true;\n}\n\n// clip line p1,p2 against (-1.0, 1.0) in x and y, set out to clipped point closest to p1\nint LineRadarBoxCollision(CVector2D &out, const CVector2D &p1, const CVector2D &p2)\n{\n\tfloat d1, d2;\n\tfloat t;\n\tfloat x, y;\n\tfloat shortest = 1.0f;\n\tint edge = -1;\n\n\t// clip against left edge, x = -1.0\n\td1 = -1.0f - p1.x;\n\td2 = -1.0f - p2.x;\n\tif (d1 * d2 < 0.0f) {\n\t\t// they are on opposite sides, get point of intersection\n\t\tt = d1 / (d1 - d2);\n\t\ty = (p2.y - p1.y)*t + p1.y;\n\t\tif (y >= -1.0f && y <= 1.0f && t <= shortest) {\n\t\t\tout.x = -1.0f;\n\t\t\tout.y = y;\n\t\t\tedge = 3;\n\t\t\tshortest = t;\n\t\t}\n\t}\n\n\t// clip against right edge, x = 1.0\n\td1 = p1.x - 1.0f;\n\td2 = p2.x - 1.0f;\n\tif (d1 * d2 < 0.0f) {\n\t\t// they are on opposite sides, get point of intersection\n\t\tt = d1 / (d1 - d2);\n\t\ty = (p2.y - p1.y)*t + p1.y;\n\t\tif (y >= -1.0f && y <= 1.0f && t <= shortest) {\n\t\t\tout.x = 1.0f;\n\t\t\tout.y = y;\n\t\t\tedge = 1;\n\t\t\tshortest = t;\n\t\t}\n\t}\n\n\t// clip against top edge, y = -1.0\n\td1 = -1.0f - p1.y;\n\td2 = -1.0f - p2.y;\n\tif (d1 * d2 < 0.0f) {\n\t\t// they are on opposite sides, get point of intersection\n\t\tt = d1 / (d1 - d2);\n\t\tx = (p2.x - p1.x)*t + p1.x;\n\t\tif (x >= -1.0f && x <= 1.0f && t <= shortest) {\n\t\t\tout.y = -1.0f;\n\t\t\tout.x = x;\n\t\t\tedge = 0;\n\t\t\tshortest = t;\n\t\t}\n\t}\n\n\t// clip against bottom edge, y = 1.0\n\td1 = p1.y - 1.0f;\n\td2 = p2.y - 1.0f;\n\tif (d1 * d2 < 0.0f) {\n\t\t// they are on opposite sides, get point of intersection\n\t\tt = d1 / (d1 - d2);\n\t\tx = (p2.x - p1.x)*t + p1.x;\n\t\tif (x >= -1.0f && x <= 1.0f && t <= shortest) {\n\t\t\tout.y = 1.0f;\n\t\t\tout.x = x;\n\t\t\tedge = 2;\n\t\t\tshortest = t;\n\t\t}\n\t}\n\n\treturn edge;\n}\n\nuint8 CRadar::CalculateBlipAlpha(float dist)\n{\n\tif (FrontEndMenuManager.m_bMenuMapActive)\n\t\treturn 255;\n\n\tif (dist <= 1.0f)\n\t\treturn 255;\n\n\tif (dist <= 10.0f)\n\t\treturn (128.0f * ((dist - 1.0f) / 9.0f)) + ((1.0f - (dist - 1.0f) / 9.0f) * 255.0f);\n\n\treturn 128;\n}\n\nvoid CRadar::ChangeBlipBrightness(int32 i, int32 bright)\n{\n\tint index = GetActualBlipArrayIndex(i);\n\tif (index != -1)\n\t\tms_RadarTrace[index].m_bDim = bright != 1;\n}\n\nvoid CRadar::ChangeBlipColour(int32 i, int32 color)\n{\n\tint index = GetActualBlipArrayIndex(i);\n\tif (index != -1)\n\t\tms_RadarTrace[index].m_nColor = color;\n}\n\nvoid CRadar::ChangeBlipDisplay(int32 i, eBlipDisplay display)\n{\n\tint index = GetActualBlipArrayIndex(i);\n\tif (index != -1)\n\t\tms_RadarTrace[index].m_eBlipDisplay = display;\n}\n\nvoid CRadar::ChangeBlipScale(int32 i, int32 scale)\n{\n\tint index = GetActualBlipArrayIndex(i);\n\tif (index != -1)\n\t\tms_RadarTrace[index].m_wScale = scale;\n}\n\nvoid CRadar::ClearBlip(int32 i)\n{\n\tint index = GetActualBlipArrayIndex(i);\n\tif (index != -1) {\n\t\tSetRadarMarkerState(index, false);\n\t\tms_RadarTrace[index].m_bInUse = false;\n\t\tms_RadarTrace[index].m_eBlipType = BLIP_NONE;\n\t\tms_RadarTrace[index].m_eBlipDisplay = BLIP_DISPLAY_NEITHER;\n\t\tms_RadarTrace[index].m_eRadarSprite = RADAR_SPRITE_NONE;\n\t}\n}\n\nvoid CRadar::ClearBlipForEntity(eBlipType type, int32 id)\n{\n\tfor (int i = 0; i < NUMRADARBLIPS; i++) {\n\t\tif (type == ms_RadarTrace[i].m_eBlipType && id == ms_RadarTrace[i].m_nEntityHandle) {\n\t\t\tSetRadarMarkerState(i, false);\n\t\t\tms_RadarTrace[i].m_bInUse = false;\n\t\t\tms_RadarTrace[i].m_eBlipType = BLIP_NONE;\n\t\t\tms_RadarTrace[i].m_eBlipDisplay = BLIP_DISPLAY_NEITHER;\n\t\t\tms_RadarTrace[i].m_eRadarSprite = RADAR_SPRITE_NONE;\n\t\t}\n\t};\n}\n\n// Why not a proper clipping algorithm?\nint CRadar::ClipRadarPoly(CVector2D *poly, const CVector2D *rect)\n{\n\tCVector2D corners[4] = {\n\t\tCVector2D(  1.0f, -1.0f ),\t// top right\n\t\tCVector2D(  1.0f,  1.0f ),\t// bottom right\n\t\tCVector2D( -1.0f,  1.0f ),\t// bottom left\n\t\tCVector2D( -1.0f, -1.0f ),\t// top left\n\t};\n\tCVector2D tmp;\n\tint i, j, n;\n\tint laste, e, e1, e2;;\n\tbool inside[4];\n\n\tfor (i = 0; i < 4; i++)\n\t\tinside[i] = IsPointInsideRadar(rect[i]);\n\n\tlaste = -1;\n\tn = 0;\n\tfor (i = 0; i < 4; i++)\n\t\tif (inside[i]) {\n\t\t\t// point is inside, just add\n\t\t\tpoly[n++] = rect[i];\n\t\t}\n\t\telse {\n\t\t\t// point is outside but line to this point might be clipped\n\t\t\te1 = LineRadarBoxCollision(poly[n], rect[i], rect[(i + 4 - 1) % 4]);\n\t\t\tif (e1 != -1) {\n\t\t\t\tlaste = e1;\n\t\t\t\tn++;\n\t\t\t}\n\t\t\t// and line from this point might be clipped as well\n\t\t\te2 = LineRadarBoxCollision(poly[n], rect[i], rect[(i + 1) % 4]);\n\t\t\tif (e2 != -1) {\n\t\t\t\tif (e1 == -1) {\n\t\t\t\t\t// if other line wasn't clipped, i.e. it was complete outside,\n\t\t\t\t\t// we may have to insert another vertex if last clipped line\n\t\t\t\t\t// was on a different edge\n\n\t\t\t\t\t// find the last intersection if we haven't seen it yet\n\t\t\t\t\tif (laste == -1)\n\t\t\t\t\t\tfor (j = 3; j >= i; j--) {\n\t\t\t\t\t\t\t// game uses an if here for j == 0\n\t\t\t\t\t\t\te = LineRadarBoxCollision(tmp, rect[j], rect[(j + 4 - 1) % 4]);\n\t\t\t\t\t\t\tif (e != -1) {\n\t\t\t\t\t\t\t\tlaste = e;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\tassert(laste != -1);\n\n\t\t\t\t\t// insert corners that were skipped\n\t\t\t\t\ttmp = poly[n];\n\t\t\t\t\tfor (e = laste; e != e2; e = (e + 1) % 4)\n\t\t\t\t\t\tpoly[n++] = corners[e];\n\t\t\t\t\tpoly[n] = tmp;\n\t\t\t\t}\n\t\t\t\tn++;\n\t\t\t}\n\t\t}\n\n\tif (n == 0) {\n\t\t// If no points, either the rectangle is completely outside or completely surrounds the radar\n\t\t// no idea what's going on here...\n\t\tfloat m = (rect[0].y - rect[1].y) / (rect[0].x - rect[1].x);\n\t\tif ((m*rect[3].x - rect[3].y) * (m*rect[0].x - rect[0].y) < 0.0f) {\n\t\t\tm = (rect[0].y - rect[3].y) / (rect[0].x - rect[3].x);\n\t\t\tif ((m*rect[1].x - rect[1].y) * (m*rect[0].x - rect[0].y) < 0.0f) {\n\t\t\t\tpoly[0] = corners[0];\n\t\t\t\tpoly[1] = corners[1];\n\t\t\t\tpoly[2] = corners[2];\n\t\t\t\tpoly[3] = corners[3];\n\t\t\t\tn = 4;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn n;\n}\n\nbool CRadar::DisplayThisBlip(int32 counter)\n{\n\tswitch (ms_RadarTrace[counter].m_eRadarSprite) {\n\tcase RADAR_SPRITE_SPRAY:\n\tcase RADAR_SPRITE_GUN:\n\t\treturn true;\n\tdefault:\n\t\treturn false;\n\t}\n}\n\nvoid CRadar::Draw3dMarkers()\n{\n\tfor (int i = 0; i < NUMRADARBLIPS; i++) {\n\t\tif (ms_RadarTrace[i].m_bInUse) {\n\t\t\tswitch (ms_RadarTrace[i].m_eBlipType) {\n\t\t\tcase BLIP_CAR:\n\t\t\t{\n\t\t\t\tCEntity *entity = CPools::GetVehiclePool()->GetAt(ms_RadarTrace[i].m_nEntityHandle);\n\t\t\t\tif (ms_RadarTrace[i].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[i].m_eBlipDisplay == BLIP_DISPLAY_MARKER_ONLY) {\n\t\t\t\t\tCVector pos = entity->GetPosition();\n\t\t\t\t\tpos.z += 1.2f * CModelInfo::GetModelInfo(entity->GetModelIndex())->GetColModel()->boundingBox.max.z + 2.5f;\n\t\t\t\t\tC3dMarkers::PlaceMarker(i | (ms_RadarTrace[i].m_BlipIndex << 16), 1, pos, 2.5f, CARBLIP_MARKER_COLOR_R, CARBLIP_MARKER_COLOR_G, CARBLIP_MARKER_COLOR_B, CARBLIP_MARKER_COLOR_A, 1024, 0.2f, 5);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase BLIP_CHAR:\n\t\t\t{\n\t\t\t\tCEntity *entity = CPools::GetPedPool()->GetAt(ms_RadarTrace[i].m_nEntityHandle);\n\t\t\t\tif (entity != nil) {\n\t\t\t\t\tif (((CPed*)entity)->InVehicle())\n\t\t\t\t\t\tentity = ((CPed * )entity)->m_pMyVehicle;\n\t\t\t\t}\n\t\t\t\tif (ms_RadarTrace[i].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[i].m_eBlipDisplay == BLIP_DISPLAY_MARKER_ONLY) {\n\t\t\t\t\tCVector pos = entity->GetPosition();\n\t\t\t\t\tpos.z += 3.0f;\n\t\t\t\t\tC3dMarkers::PlaceMarker(i | (ms_RadarTrace[i].m_BlipIndex << 16), 1, pos, 1.5f, CHARBLIP_MARKER_COLOR_R, CHARBLIP_MARKER_COLOR_G, CHARBLIP_MARKER_COLOR_B, CHARBLIP_MARKER_COLOR_A, 1024, 0.2f, 5);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase BLIP_OBJECT:\n\t\t\t{\n\t\t\t\tCEntity *entity = CPools::GetObjectPool()->GetAt(ms_RadarTrace[i].m_nEntityHandle);\n\t\t\t\tif (ms_RadarTrace[i].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[i].m_eBlipDisplay == BLIP_DISPLAY_MARKER_ONLY) {\n\t\t\t\t\tCVector pos = entity->GetPosition();\n\t\t\t\t\tpos.z += CModelInfo::GetModelInfo(entity->GetModelIndex())->GetColModel()->boundingBox.max.z + 1.0f + 1.0f;\n\t\t\t\t\tC3dMarkers::PlaceMarker(i | (ms_RadarTrace[i].m_BlipIndex << 16), 1, pos, 1.0f, OBJECTBLIP_MARKER_COLOR_R, OBJECTBLIP_MARKER_COLOR_G, OBJECTBLIP_MARKER_COLOR_B, OBJECTBLIP_MARKER_COLOR_A, 1024, 0.2f, 5);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase BLIP_COORD:\n\t\t\t\tbreak;\n\t\t\tcase BLIP_CONTACT_POINT:\n\t\t\t\tif (!CTheScripts::IsPlayerOnAMission()) {\n\t\t\t\t\tif (ms_RadarTrace[i].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[i].m_eBlipDisplay == BLIP_DISPLAY_MARKER_ONLY)\n\t\t\t\t\t\tC3dMarkers::PlaceMarkerSet(i | (ms_RadarTrace[i].m_BlipIndex << 16), 4, ms_RadarTrace[i].m_vecPos, 2.0f, COORDBLIP_MARKER_COLOR_R, COORDBLIP_MARKER_COLOR_G, COORDBLIP_MARKER_COLOR_B, COORDBLIP_MARKER_COLOR_A, 2048, 0.2f, 0);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid CRadar::DrawBlips()\n{\n\tif (!TheCamera.m_WideScreenOn && CHud::m_Wants_To_Draw_Hud) {\n#ifdef SECUROM\n\t\textern uint8 roadBlocksPirateCheck;\n\t\tif (roadBlocksPirateCheck == 2) return;\n#endif\n\t\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);\n\t\tRwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE);\n\t\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);\n\t\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);\n\t\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);\n\t\tRwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE);\n\n\t\tCVector2D out;\n\t\tCVector2D in = CVector2D(0.0f, 0.0f);\n\t\tTransformRadarPointToScreenSpace(out, in);\n\n\t\tif (!FrontEndMenuManager.m_bMenuMapActive) {\n\t\t\tfloat angle;\n\t\t\tif (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOPDOWN)\n\t\t\t\tangle = PI + FindPlayerHeading();\n#ifdef FIX_BUGS\n\t\t\telse if (TheCamera.GetLookDirection() != LOOKING_FORWARD)\n\t\t\t\tangle = FindPlayerHeading() - (PI + (TheCamera.Cams[TheCamera.ActiveCam].CamTargetEntity->GetPosition() - TheCamera.Cams[TheCamera.ActiveCam].SourceBeforeLookBehind).Heading());\n#endif\n\t\t\telse\n\t\t\t\tangle = FindPlayerHeading() - (PI + TheCamera.GetForward().Heading());\n\n\t\t\tDrawRotatingRadarSprite(&CentreSprite, out.x, out.y, angle, 255);\n\n\t\t\tCVector2D vec2d;\n\t\t\tvec2d.x = vec2DRadarOrigin.x;\n\t\t\tvec2d.y = M_SQRT2 * m_radarRange + vec2DRadarOrigin.y;\n\t\t\tTransformRealWorldPointToRadarSpace(in, vec2d);\n\t\t\tLimitRadarPoint(in);\n\t\t\tTransformRadarPointToScreenSpace(out, in);\n\t\t\tDrawRadarSprite(RADAR_SPRITE_NORTH, out.x, out.y, 255);\n\t\t}\n\n\t\tfor(int blipId = 0; blipId < NUMRADARBLIPS; blipId++) {\n\t\t\tif (!ms_RadarTrace[blipId].m_bInUse)\n\t\t\t\tcontinue;\n\n\t\t\tswitch (ms_RadarTrace[blipId].m_eBlipType) {\n\t\t\t\tcase BLIP_CAR:\n\t\t\t\tcase BLIP_CHAR:\n\t\t\t\tcase BLIP_OBJECT:\n\t\t\t\t\tif (ms_RadarTrace[blipId].m_eRadarSprite == RADAR_SPRITE_PROPERTY\n\t\t\t\t\t\t&& (!CTheScripts::bPlayerIsInTheStatium || !FrontEndMenuManager.m_bMenuMapActive))\n\t\t\t\t\t\tDrawEntityBlip(blipId);\n\n\t\t\t\t\tbreak;\n\t\t\t\tcase BLIP_COORD:\n\t\t\t\tcase BLIP_CONTACT_POINT:\n\t\t\t\t\tif (ms_RadarTrace[blipId].m_eRadarSprite == RADAR_SPRITE_PHONE\n\t\t\t\t\t\t&& (!CTheScripts::bPlayerIsInTheStatium || !FrontEndMenuManager.m_bMenuMapActive))\n\t\t\t\t\t\tDrawCoordBlip(blipId);\n\t\t\t\t\t\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t// New in VC: Always draw Hardware/gun/pay'n spray/save blips\n\t\tfor(int blipId = 0; blipId < NUMRADARBLIPS; blipId++) {\n\t\t\tif (!ms_RadarTrace[blipId].m_bInUse)\n\t\t\t\tcontinue;\n\n\t\t\tif (ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_SAVE && ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_HARDWARE\n\t\t\t\t\t&& ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_SPRAY && ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_GUN)\n\t\t\t\tcontinue;\n\n\t\t\tswitch (ms_RadarTrace[blipId].m_eBlipType) {\n\t\t\t\tcase BLIP_CAR:\n\t\t\t\tcase BLIP_CHAR:\n\t\t\t\tcase BLIP_OBJECT:\n\t\t\t\t\tif (!CTheScripts::bPlayerIsInTheStatium || !FrontEndMenuManager.m_bMenuMapActive)\n\t\t\t\t\t\tDrawEntityBlip(blipId);\n\n\t\t\t\t\tbreak;\n\t\t\t\tcase BLIP_COORD:\n\t\t\t\tcase BLIP_CONTACT_POINT:\n\t\t\t\t\tif (!CTheScripts::bPlayerIsInTheStatium || !FrontEndMenuManager.m_bMenuMapActive)\n\t\t\t\t\t\tDrawCoordBlip(blipId);\n\t\t\t\t\t\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tfor(int blipId = 0; blipId < NUMRADARBLIPS; blipId++) {\n\t\t\tif (!ms_RadarTrace[blipId].m_bInUse)\n\t\t\t\tcontinue;\n\n\t\t\tswitch (ms_RadarTrace[blipId].m_eBlipType) {\n\t\t\t\tcase BLIP_CAR:\n\t\t\t\tcase BLIP_CHAR:\n\t\t\t\tcase BLIP_OBJECT:\n\t\t\t\t\tif (ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_SAVE && ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_HARDWARE\n\t\t\t\t\t\t&& ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_SPRAY && ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_PROPERTY\n\t\t\t\t\t\t&& ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_GUN\n\t\t\t\t\t\t&& (!CTheScripts::bPlayerIsInTheStatium || !FrontEndMenuManager.m_bMenuMapActive))\n\n\t\t\t\t\t\tDrawEntityBlip(blipId);\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tfor (int blipId = 0; blipId < NUMRADARBLIPS; blipId++) {\n\t\t\tif (!ms_RadarTrace[blipId].m_bInUse)\n\t\t\t\tcontinue;\n\n\t\t\tswitch (ms_RadarTrace[blipId].m_eBlipType) {\n\t\t\t\tcase BLIP_COORD:\n\t\t\t\tcase BLIP_CONTACT_POINT:\n\t\t\t\t\tif (ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_SAVE && ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_HARDWARE\n\t\t\t\t\t\t&& ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_SPRAY && ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_PROPERTY\n\t\t\t\t\t\t&& ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_GUN && ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_PHONE\n\t\t\t\t\t\t&& (!CTheScripts::bPlayerIsInTheStatium || !FrontEndMenuManager.m_bMenuMapActive))\n\n\t\t\t\t\t\tDrawCoordBlip(blipId);\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (FrontEndMenuManager.m_bMenuMapActive) {\n\t\t\tCVector2D in, out;\n\t\t\tif (!CTheScripts::bPlayerIsInTheStatium)\n\t\t\t\tTransformRealWorldPointToRadarSpace(in, FindPlayerCentreOfWorld_NoSniperShift());\n\t\t\telse\n\t\t\t\tTransformRealWorldPointToRadarSpace(in, CVector2D(-1302.5f, 1332.8f));\n\n\t\t\tLimitRadarPoint(in);\n\t\t\tTransformRadarPointToScreenSpace(out, in);\n\t\t\tDrawYouAreHereSprite(out.x, out.y);\n\t\t}\n\t}\n}\n\nvoid CRadar::DrawMap()\n{\n\tif (!TheCamera.m_WideScreenOn && CHud::m_Wants_To_Draw_Hud) {\n\t\tCalculateCachedSinCos();\n\t\tif (FindPlayerVehicle()) {\n\t\t\tfloat speed = FindPlayerSpeed().Magnitude();\n\t\t\tif (speed < RADAR_MIN_SPEED)\n\t\t\t\tm_radarRange = RADAR_MIN_RANGE;\n\t\t\telse if (speed < RADAR_MAX_SPEED)\n\t\t\t\tm_radarRange = (speed - RADAR_MIN_SPEED)/(RADAR_MAX_SPEED-RADAR_MIN_SPEED) * (RADAR_MAX_RANGE-RADAR_MIN_RANGE) + RADAR_MIN_RANGE;\n\t\t\telse\n\t\t\t\tm_radarRange = RADAR_MAX_RANGE;\n\t\t}\n\t\telse\n\t\t\tm_radarRange = RADAR_MIN_RANGE;\n\n\t\tvec2DRadarOrigin = CVector2D(FindPlayerCentreOfWorld_NoSniperShift());\n\t\tif (FrontEndMenuManager.m_PrefsRadarMode != 1)\n\t\t\tDrawRadarMap();\n\t}\n}\n\nvoid CRadar::DrawRadarMap()\n{\n\tDrawRadarMask();\n\n\t// top left ist (0, 0)\n\tint x = Floor((vec2DRadarOrigin.x - RADAR_MIN_X) / RADAR_TILE_SIZE);\n\tint y = Ceil((RADAR_NUM_TILES - 1) - (vec2DRadarOrigin.y - RADAR_MIN_Y) / RADAR_TILE_SIZE);\n\tStreamRadarSections(x, y);\n\n\tRwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE);\n\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);\n\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);\n\tRwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR);\n\tRwRenderStateSet(rwRENDERSTATESHADEMODE, (void*)rwSHADEMODEFLAT);\n\tRwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);\n\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);\n\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);\n\tRwRenderStateSet(rwRENDERSTATETEXTUREADDRESS, (void*)rwTEXTUREADDRESSCLAMP);\n\tRwRenderStateSet(rwRENDERSTATETEXTUREPERSPECTIVE, (void*)FALSE);\n\n\tDrawRadarSection(x - 1, y - 1);\n\tDrawRadarSection(x, y - 1);\n\tDrawRadarSection(x + 1, y - 1);\n\tDrawRadarSection(x - 1, y);\n\tDrawRadarSection(x, y);\n\tDrawRadarSection(x + 1, y);\n\tDrawRadarSection(x - 1, y + 1);\n\tDrawRadarSection(x, y + 1);\n\tDrawRadarSection(x + 1, y + 1);\n}\n\nvoid CRadar::DrawRadarMask() \n{ \n\tCVector2D corners[4] = {\n\t\tCVector2D(1.0f, -1.0f),\n\t\tCVector2D(1.0f, 1.0f),\n\t\tCVector2D(-1.0f, 1.0f),\n\t\tCVector2D(-1.0, -1.0f)\n\t};\n\n\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void*)nil);\n\tRwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE);\n\tRwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR);\n\tRwRenderStateSet(rwRENDERSTATESHADEMODE, (void*)rwSHADEMODEFLAT);\n\tRwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE);\n\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);\n\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);\n#if !defined(GTA_PS2_STUFF) && defined(RWLIBS)\n\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);\n\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);\n\tRwD3D8SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_ALWAYS);\n#else\n\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDZERO);\n\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE);\n#endif\n\n\tCVector2D out[8];\n\tCVector2D in;\n\n\t// Draw the shape we want to mask out from the radar in four segments\n\tfor (int i = 0; i < 4; i++) {\n\t\t// First point is always the corner itself\n\t\tin.x = corners[i].x;\n\t\tin.y = corners[i].y;\n\t\tTransformRadarPointToScreenSpace(out[0], in);\n\n\t\t// Then generate a quarter of the circle\n\t\tfor (int j = 0; j < 7; j++) {\n\t\t\tin.x = corners[i].x * Cos(j * (PI / 2.0f / 6.0f));\n\t\t\tin.y = corners[i].y * Sin(j * (PI / 2.0f / 6.0f));\n\t\t\tTransformRadarPointToScreenSpace(out[j + 1], in);\n\t\t};\n\n\t\tCSprite2d::SetMaskVertices(8, (float *)out);\n\t\tRwIm2DRenderPrimitive(rwPRIMTYPETRIFAN, CSprite2d::GetVertices(), 8);\n\t}\n#if !defined(GTA_PS2_STUFF) && defined(RWLIBS)\n\tRwD3D8SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATER);\n#endif\n\n}\n\nvoid CRadar::DrawRadarSection(int32 x, int32 y)\n{\n\tint i;\n\tRwTexDictionary *txd;\n\tCVector2D worldPoly[8];\n\tCVector2D radarCorners[4];\n\tCVector2D radarPoly[8];\n\tCVector2D texCoords[8];\n\tCVector2D screenPoly[8];\n\tint numVertices;\n\tRwTexture *texture = nil;\n\n\tGetTextureCorners(x, y, worldPoly);\n\tClipRadarTileCoords(x, y);\n\n\tif (!CTheScripts::bPlayerIsInTheStatium &&\n\t\t(!(txd = CTxdStore::GetSlot(gRadarTxdIds[x + RADAR_NUM_TILES * y])->texDict) || !(texture = GetFirstTexture(txd))))\n\t\treturn;\n\n\tfor (i = 0; i < 4; i++)\n\t\tTransformRealWorldPointToRadarSpace(radarCorners[i], worldPoly[i]);\n\n\tnumVertices = ClipRadarPoly(radarPoly, radarCorners);\n\n\t// FIX: can return earlier here\n//\tif(numVertices == 0)\n\tif (numVertices < 3)\n\t\treturn;\n\n\tfor (i = 0; i < numVertices; i++) {\n\t\tTransformRadarPointToRealWorldSpace(worldPoly[i], radarPoly[i]);\n\t\tTransformRealWorldToTexCoordSpace(texCoords[i], worldPoly[i], x, y);\n\t\tTransformRadarPointToScreenSpace(screenPoly[i], radarPoly[i]);\n\t}\n\n\tif (CTheScripts::bPlayerIsInTheStatium) {\n\t\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil);\n\t\tCSprite2d::SetVertices(numVertices, (float*)screenPoly, (float*)texCoords, CRGBA(204, 204, 204, 255));\n\t} else {\n\t\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(texture));\n\t\tCSprite2d::SetVertices(numVertices, (float*)screenPoly, (float*)texCoords, CRGBA(255, 255, 255, 255));\n\t}\n\n\t// check done above now\n//\tif(numVertices > 2)\n\tRwIm2DRenderPrimitive(rwPRIMTYPETRIFAN, CSprite2d::GetVertices(), numVertices);\n}\n\nvoid CRadar::DrawRadarSprite(uint16 sprite, float x, float y, uint8 alpha)\n{\n\tRadarSprites[sprite]->Draw(CRect(x - SCREEN_SCALE_X(8.0f), y - SCREEN_SCALE_Y(8.0f), x + SCREEN_SCALE_X(8.0f), y + SCREEN_SCALE_Y(8.0f)), CRGBA(255, 255, 255, alpha));\n\n\tif (FrontEndMenuManager.m_bMenuMapActive) {\n\t\tbool alreadyThere = false;\n\t\tfor (int i = 0; i < NUM_MAP_LEGENDS; i++) {\n\t\t\tif (MapLegendList[i] == sprite)\n\t\t\t\talreadyThere = true;\n\t\t}\n\t\tif (!alreadyThere) {\n\t\t\tMapLegendList[MapLegendCounter] = sprite;\n\t\t\tMapLegendCounter++;\n\t\t}\n\t}\n}\n\nvoid CRadar::DrawRotatingRadarSprite(CSprite2d* sprite, float x, float y, float angle, int32 alpha)\n{\n\tCVector curPosn[4];\n\tconst float sizeX = SCREEN_SCALE_X(8.0f);\n\tconst float correctedAngle = angle - PI / 4.f;\n\tconst float sizeY = SCREEN_SCALE_Y(8.0f);\n\n\tfor (uint32 i = 0; i < 4; i++) {\n\t\tconst float cornerAngle = i * HALFPI + correctedAngle;\n\t\tcurPosn[i].x = x + (0.0f * Cos(cornerAngle) + 1.0f * Sin(cornerAngle)) * sizeX;\n\t\tcurPosn[i].y = y - (0.0f * Sin(cornerAngle) - 1.0f * Cos(cornerAngle)) * sizeY;\n\t}\n\n\tsprite->Draw(curPosn[3].x, curPosn[3].y, curPosn[2].x, curPosn[2].y, curPosn[0].x, curPosn[0].y, curPosn[1].x, curPosn[1].y, CRGBA(255, 255, 255, alpha));\n}\n\nint32 CRadar::GetActualBlipArrayIndex(int32 i)\n{\n\tif (i == -1)\n\t\treturn -1;\n\telse if ((i & 0xFFFF0000) >> 16 != ms_RadarTrace[(uint16)i].m_BlipIndex)\n\t\treturn -1;\n\telse\n\t\treturn (uint16)i;\n}\n\nint32 CRadar::GetNewUniqueBlipIndex(int32 i)\n{\n\tif (ms_RadarTrace[i].m_BlipIndex >= UINT16_MAX - 1)\n\t\tms_RadarTrace[i].m_BlipIndex = 1;\n\telse\n\t\tms_RadarTrace[i].m_BlipIndex++;\n\treturn i | (ms_RadarTrace[i].m_BlipIndex << 16);\n}\n\nuint32 CRadar::GetRadarTraceColour(uint32 color, bool bright)\n{\n\tuint32 c;\n\tswitch (color) {\n\tcase RADAR_TRACE_RED:\n\t\tif (bright)\n\t\t\tc = 0x712B49FF;\n\t\telse\n\t\t\tc = 0x7F0000FF;\n\t\tbreak;\n\tcase RADAR_TRACE_GREEN:\n\t\tif (bright)\n\t\t\tc = 0x5FA06AFF;\n\t\telse\n\t\t\tc = 0x007F00FF;\n\t\tbreak;\n\tcase RADAR_TRACE_LIGHT_BLUE:\n\t\tif (bright)\n\t\t\tc = 0x80A7F3FF;\n\t\telse\n\t\t\tc = 0x00007FFF;\n\t\tbreak;\n\tcase RADAR_TRACE_GRAY:\n\t\tif (bright)\n\t\t\tc = 0xE1E1E1FF;\n\t\telse\n\t\t\tc = 0x7F7F7FFF;\n\t\tbreak;\n\tcase RADAR_TRACE_YELLOW:\n\t\tif (bright)\n\t\t\tc = 0xFFFF00FF;\n\t\telse\n\t\t\tc = 0x7F7F00FF;\n\t\tbreak;\n\tcase RADAR_TRACE_MAGENTA:\n\t\tif (bright)\n\t\t\tc = 0xFF00FFFF;\n\t\telse\n\t\t\tc = 0x7F007FFF;\n\t\tbreak;\n\tcase RADAR_TRACE_CYAN:\n\t\tif (bright)\n\t\t\tc = 0x00FFFFFF;\n\t\telse\n\t\t\tc = 0x007F7FFF;\n\t\tbreak;\n\tdefault:\n\t\tc = color;\n\t\tbreak;\n\t};\n\treturn c;\n}\n\nconst char* gRadarTexNames[] = {\n\t\"radar00\", \"radar01\", \"radar02\", \"radar03\", \"radar04\", \"radar05\", \"radar06\", \"radar07\",\n\t\"radar08\", \"radar09\", \"radar10\", \"radar11\", \"radar12\", \"radar13\", \"radar14\", \"radar15\",\n\t\"radar16\", \"radar17\", \"radar18\", \"radar19\", \"radar20\", \"radar21\", \"radar22\", \"radar23\",\n\t\"radar24\", \"radar25\", \"radar26\", \"radar27\", \"radar28\", \"radar29\", \"radar30\", \"radar31\",\n\t\"radar32\", \"radar33\", \"radar34\", \"radar35\", \"radar36\", \"radar37\", \"radar38\", \"radar39\",\n\t\"radar40\", \"radar41\", \"radar42\", \"radar43\", \"radar44\", \"radar45\", \"radar46\", \"radar47\",\n\t\"radar48\", \"radar49\", \"radar50\", \"radar51\", \"radar52\", \"radar53\", \"radar54\", \"radar55\",\n\t\"radar56\", \"radar57\", \"radar58\", \"radar59\", \"radar60\", \"radar61\", \"radar62\", \"radar63\",\n};\n\nvoid\nCRadar::Initialise()\n{\n\tfor (int i = 0; i < NUMRADARBLIPS; i++) {\n\t\tms_RadarTrace[i].m_BlipIndex = 1;\n\t\tSetRadarMarkerState(i, false);\n\t\tms_RadarTrace[i].m_bInUse = false;\n\t\tms_RadarTrace[i].m_bShortRange = false;\n\t\tms_RadarTrace[i].m_eBlipType = BLIP_NONE;\n\t\tms_RadarTrace[i].m_eBlipDisplay = BLIP_DISPLAY_NEITHER;\n\t\tms_RadarTrace[i].m_eRadarSprite = RADAR_SPRITE_NONE;\n\t}\n\n\tm_radarRange = 350.0f;\n\tfor (int i = 0; i < 64; i++) \n\t\tgRadarTxdIds[i] = CTxdStore::FindTxdSlot(gRadarTexNames[i]);\n}\n\nfloat CRadar::LimitRadarPoint(CVector2D &point)\n{\n\tfloat dist, invdist;\n\n\tdist = point.Magnitude();\n\n\tif (FrontEndMenuManager.m_bMenuMapActive)\n\t\treturn dist;\n\n\tif (dist > 1.0f) {\n\t\tinvdist = 1.0f / dist;\n\t\tpoint.x *= invdist;\n\t\tpoint.y *= invdist;\n\t}\n\treturn dist;\n}\n\nvoid CRadar::LoadAllRadarBlips(uint8 *buf, uint32 size)\n{\n\tInitialise();\nINITSAVEBUF\n\tCheckSaveHeader(buf, 'R', 'D', 'R', '\\0', size - SAVE_HEADER_SIZE);\n\n\tfor (int i = 0; i < NUMRADARBLIPS; i++) {\n\t\tms_RadarTrace[i].m_nColor = ReadSaveBuf<uint32>(buf);\n\t\tms_RadarTrace[i].m_Radius = ReadSaveBuf<float>(buf);\n\t\tms_RadarTrace[i].m_eBlipType = ReadSaveBuf<uint32>(buf);\n\t\tms_RadarTrace[i].m_nEntityHandle = ReadSaveBuf<int32>(buf);\n\t\tms_RadarTrace[i].m_vec2DPos.x = ReadSaveBuf<float>(buf); // CVector2D\n\t\tms_RadarTrace[i].m_vec2DPos.y = ReadSaveBuf<float>(buf);\n\t\tms_RadarTrace[i].m_vecPos = ReadSaveBuf<CVector>(buf);\n\t\tms_RadarTrace[i].m_BlipIndex = ReadSaveBuf<uint16>(buf);\n\t\tms_RadarTrace[i].m_bDim = ReadSaveBuf<bool>(buf);\n\t\tms_RadarTrace[i].m_bInUse = ReadSaveBuf<bool>(buf);\n\t\tms_RadarTrace[i].m_bShortRange = ReadSaveBuf<bool>(buf);\n\t\tms_RadarTrace[i].m_unused = ReadSaveBuf<bool>(buf);\n\t\tms_RadarTrace[i].m_wScale = ReadSaveBuf<int16>(buf);\n\t\tms_RadarTrace[i].m_eBlipDisplay = ReadSaveBuf<uint16>(buf);\n\t\tms_RadarTrace[i].m_eRadarSprite = ReadSaveBuf<uint16>(buf);\n\t}\n\nVALIDATESAVEBUF(size);\n}\n\nvoid CRadar::SaveAllRadarBlips(uint8 *buf, uint32 *size)\n{\n\t*size = SAVE_HEADER_SIZE + NUMRADARBLIPS * sizeof(sRadarTraceSave);\n\nINITSAVEBUF\n\tWriteSaveHeader(buf, 'R', 'D', 'R', '\\0', *size - SAVE_HEADER_SIZE);\n\n#ifdef MAP_ENHANCEMENTS\n\tif (TargetMarkerId != -1) {\n\t\tClearBlip(TargetMarkerId);\n\t\tTargetMarkerId = -1;\n\t}\n#endif\n\n\tfor (int i = 0; i < NUMRADARBLIPS; i++) {\n\t\tsRadarTraceSave *saveStruct = (sRadarTraceSave*) buf;\n\n\t\tsaveStruct->m_nColor = ms_RadarTrace[i].m_nColor;\n\t\tsaveStruct->m_Radius = ms_RadarTrace[i].m_Radius;\n\t\tsaveStruct->m_eBlipType = ms_RadarTrace[i].m_eBlipType;\n\t\tsaveStruct->m_nEntityHandle = ms_RadarTrace[i].m_nEntityHandle;\n\t\tsaveStruct->m_vec2DPos = ms_RadarTrace[i].m_vec2DPos;\n\t\tsaveStruct->m_vecPos = ms_RadarTrace[i].m_vecPos;\n\t\tsaveStruct->m_BlipIndex = ms_RadarTrace[i].m_BlipIndex;\n\t\tsaveStruct->m_bDim = ms_RadarTrace[i].m_bDim;\n\t\tsaveStruct->m_bInUse = ms_RadarTrace[i].m_bInUse;\n\t\tsaveStruct->m_bShortRange = ms_RadarTrace[i].m_bShortRange;\n\t\tsaveStruct->m_unused = ms_RadarTrace[i].m_unused;\n\t\tsaveStruct->m_wScale = ms_RadarTrace[i].m_wScale;\n\t\tsaveStruct->m_eBlipDisplay = ms_RadarTrace[i].m_eBlipDisplay;\n\t\tsaveStruct->m_eRadarSprite = ms_RadarTrace[i].m_eRadarSprite;\n\n\t\tSkipSaveBuf(buf, sizeof(sRadarTraceSave));\n\t}\n\nVALIDATESAVEBUF(*size);\n}\n\nvoid\nCRadar::LoadTextures()\n{\n\tCTxdStore::PushCurrentTxd();\n\tCTxdStore::SetCurrentTxd(CTxdStore::FindTxdSlot(\"hud\"));\n\tCentreSprite.SetTexture(\"radar_centre\");\n\tMapHereSprite.SetTexture(\"arrow\");\n\tNorthSprite.SetTexture(\"radar_north\");\n\tAverySprite.SetTexture(\"radar_avery\");\n\tBikerSprite.SetTexture(\"radar_biker\");\n\tCortezSprite.SetTexture(\"radar_cortez\");\n\tDiazSprite.SetTexture(\"radar_diaz\");\n\tKentSprite.SetTexture(\"radar_kent\");\n\tLawyerSprite.SetTexture(\"radar_lawyer\");\n\tPhilSprite.SetTexture(\"radar_phil\");\n\tBikersSprite.SetTexture(\"bikers\");\n\tBoatyardSprite.SetTexture(\"boatyard\");\n\tMalibuClubSprite.SetTexture(\"club\");\n\tCubansSprite.SetTexture(\"cubans\");\n\tFilmSprite.SetTexture(\"filmstudio\");\n\tGunSprite.SetTexture(\"gun\");\n\tHaitiansSprite.SetTexture(\"haitians\");\n\tHardwareSprite.SetTexture(\"hardware\");\n\tSaveHouseSprite.SetTexture(\"radar_save\");\n\tStripSprite.SetTexture(\"radar_strip\");\n\tIceSprite.SetTexture(\"icecream\");\n\tKCabsSprite.SetTexture(\"kcabs\");\n\tLovefistSprite.SetTexture(\"lovefist\");\n\tPrintworksSprite.SetTexture(\"printworks\");\n\tPropertySprite.SetTexture(\"property\");\n\tSunYardSprite.SetTexture(\"SunYard\");\n\tSpraySprite.SetTexture(\"spray\");\n\tTShirtSprite.SetTexture(\"tshirt\");\n\tTommySprite.SetTexture(\"tommy\");\n\tPhoneSprite.SetTexture(\"phone\");\n\tRadioWildstyleSprite.SetTexture(\"RWildstyle\");\n\tRadioFlashSprite.SetTexture(\"RFlash\");\n\tRadioKChatSprite.SetTexture(\"RKchat\");\n\tRadioFeverSprite.SetTexture(\"RFever\");\n\tRadioVRockSprite.SetTexture(\"RVRock\");\n\tRadioVCPRSprite.SetTexture(\"RVCPR\");\n\tRadioEspantosoSprite.SetTexture(\"REspantoso\");\n\tRadioEmotionSprite.SetTexture(\"REmotion\");\n\tRadioWaveSprite.SetTexture(\"RWave\");\n\tCTxdStore::PopCurrentTxd();\n}\n\nvoid CRadar::RemoveRadarSections()\n{\n\tfor (int i = 0; i < 8; i++)\n\t\tfor (int j = 0; j < 8; j++)\n\t\t\tRemoveMapSection(i, j);\n}\n\nvoid CRadar::SetBlipSprite(int32 i, int32 icon)\n{\n\tint index = CRadar::GetActualBlipArrayIndex(i);\n\tif (index != -1) {\n\t\tms_RadarTrace[index].m_eRadarSprite = icon;\n\t}\n}\n\nint CRadar::SetCoordBlip(eBlipType type, CVector pos, uint32 color, eBlipDisplay display)\n{\n\tint nextBlip;\n\tfor (nextBlip = 0; nextBlip < NUMRADARBLIPS; nextBlip++) {\n\t\tif (!ms_RadarTrace[nextBlip].m_bInUse)\n\t\t\tbreak;\n\t}\n#ifdef FIX_BUGS\n\tif (nextBlip == NUMRADARBLIPS)\n\t\treturn -1;\n#endif\n\tms_RadarTrace[nextBlip].m_eBlipType = type;\n\tms_RadarTrace[nextBlip].m_nColor = RADAR_TRACE_MAGENTA;\n\tms_RadarTrace[nextBlip].m_bDim = true;\n\tms_RadarTrace[nextBlip].m_bInUse = true;\n\tms_RadarTrace[nextBlip].m_bShortRange = false;\n\tms_RadarTrace[nextBlip].m_Radius = 1.0f;\n\tms_RadarTrace[nextBlip].m_vec2DPos = pos;\n\tms_RadarTrace[nextBlip].m_vecPos = pos;\n\tms_RadarTrace[nextBlip].m_nEntityHandle = 0;\n\tms_RadarTrace[nextBlip].m_wScale = 1;\n\tms_RadarTrace[nextBlip].m_eBlipDisplay = display;\n\tms_RadarTrace[nextBlip].m_eRadarSprite = RADAR_SPRITE_NONE;\n\treturn CRadar::GetNewUniqueBlipIndex(nextBlip);\n}\n\nint CRadar::SetShortRangeCoordBlip(eBlipType type, CVector pos, uint32 color, eBlipDisplay display)\n{\n\tint index = SetCoordBlip(type, pos, color, display);\n\tif (index == -1)\n\t\treturn -1;\n\tms_RadarTrace[GetActualBlipArrayIndex(index)].m_bShortRange = true;\n\treturn index;\n}\n\nint CRadar::SetEntityBlip(eBlipType type, int32 handle, uint32 color, eBlipDisplay display)\n{\n\tint nextBlip;\n\tfor (nextBlip = 0; nextBlip < NUMRADARBLIPS; nextBlip++) {\n\t\tif (!ms_RadarTrace[nextBlip].m_bInUse)\n\t\t\tbreak;\n\t}\n#ifdef FIX_BUGS\n\tif (nextBlip == NUMRADARBLIPS)\n\t\treturn -1;\n#endif\n\tms_RadarTrace[nextBlip].m_eBlipType = type;\n\tms_RadarTrace[nextBlip].m_nColor = RADAR_TRACE_YELLOW;\n\tms_RadarTrace[nextBlip].m_bDim = true;\n\tms_RadarTrace[nextBlip].m_bInUse = true;\n\tms_RadarTrace[nextBlip].m_bShortRange = false;\n\tms_RadarTrace[nextBlip].m_Radius = 1.0f;\n\tms_RadarTrace[nextBlip].m_nEntityHandle = handle;\n\tms_RadarTrace[nextBlip].m_wScale = 1;\n\tms_RadarTrace[nextBlip].m_eBlipDisplay = display;\n\tms_RadarTrace[nextBlip].m_eRadarSprite = RADAR_SPRITE_NONE;\n\treturn GetNewUniqueBlipIndex(nextBlip);\n}\n\nvoid CRadar::SetRadarMarkerState(int32 counter, bool flag)\n{\n\tCEntity *e;\n\tswitch (ms_RadarTrace[counter].m_eBlipType) {\n\tcase BLIP_CAR:\n\t\te = CPools::GetVehiclePool()->GetAt(ms_RadarTrace[counter].m_nEntityHandle);\n\t\tbreak;\n\tcase BLIP_CHAR:\n\t\te = CPools::GetPedPool()->GetAt(ms_RadarTrace[counter].m_nEntityHandle);\n\t\tbreak;\n\tcase BLIP_OBJECT:\n\t\te = CPools::GetObjectPool()->GetAt(ms_RadarTrace[counter].m_nEntityHandle);\n\t\tbreak;\n\tdefault:\n\t\treturn;\n\t}\n\n\tif (e)\n\t\te->bHasBlip = flag;\n}\n\nvoid CRadar::ShowRadarMarker(CVector pos, uint32 color, float radius) {\n\tfloat f1 = radius * 1.4f;\n\tfloat f2 = radius * 0.5f;\n\tCVector p1, p2;\n\n\tp1 = pos + TheCamera.GetUp()*f1;\n\tp2 = pos + TheCamera.GetUp()*f2;\n\tCTheScripts::ScriptDebugLine3D(p1.x, p1.y, p1.z, p2.x, p2.y, p2.z, color, color);\n\n\tp1 = pos - TheCamera.GetUp()*f1;\n\tp2 = pos - TheCamera.GetUp()*f2;\n\tCTheScripts::ScriptDebugLine3D(p1.x, p1.y, p1.z, p2.x, p2.y, p2.z, color, color);\n\n\tp1 = pos + TheCamera.GetRight()*f1;\n\tp2 = pos + TheCamera.GetRight()*f2;\n\tCTheScripts::ScriptDebugLine3D(p1.x, p1.y, p1.z, p2.x, p2.y, p2.z, color, color);\n\n\tp1 = pos - TheCamera.GetRight()*f1;\n\tp2 = pos - TheCamera.GetRight()*f2;\n\tCTheScripts::ScriptDebugLine3D(p1.x, p1.y, p1.z, p2.x, p2.y, p2.z, color, color);\n}\n\nvoid CRadar::ShowRadarTrace(float x, float y, uint32 size, uint8 red, uint8 green, uint8 blue, uint8 alpha)\n{\n\tif (!CHud::m_Wants_To_Draw_Hud || TheCamera.m_WideScreenOn)\n\t\treturn;\n\n\tCSprite2d::DrawRect(CRect(x - SCREEN_SCALE_X(size + 1.0f), y - SCREEN_SCALE_Y(size + 1.0f), SCREEN_SCALE_X(size + 1.0f) + x, SCREEN_SCALE_Y(size + 1.0f) + y), CRGBA(0, 0, 0, alpha));\n\tCSprite2d::DrawRect(CRect(x - SCREEN_SCALE_X(size), y - SCREEN_SCALE_Y(size), SCREEN_SCALE_X(size) + x, SCREEN_SCALE_Y(size) + y), CRGBA(red, green, blue, alpha));\n}\n\nvoid CRadar::ShowRadarTraceWithHeight(float x, float y, uint32 size, uint8 red, uint8 green, uint8 blue, uint8 alpha, uint8 mode)\n{\n\tif (!CHud::m_Wants_To_Draw_Hud || TheCamera.m_WideScreenOn)\n\t\treturn;\n\n\tswitch (mode)\n\t{\n\tcase BLIP_MODE_TRIANGULAR_UP:\n\t\tsize++;\n\t\tCSprite2d::Draw2DPolygon(x + SCREEN_SCALE_X(size + 3.0f), y + SCREEN_SCALE_Y(size + 2.0f), x - (SCREEN_SCALE_X(size + 3.0f)), y + SCREEN_SCALE_Y(size + 2.0f), x, y - (SCREEN_SCALE_Y(size + 3.0f)), x, y - (SCREEN_SCALE_Y(size + 3.0f)), CRGBA(0, 0, 0, alpha));\n\t\tCSprite2d::Draw2DPolygon(x + SCREEN_SCALE_X(size + 1.0f), y + SCREEN_SCALE_Y(size + 1.0f), x - (SCREEN_SCALE_X(size + 1.0f)), y + SCREEN_SCALE_Y(size + 1.0f), x, y - (SCREEN_SCALE_Y(size + 1.0f)), x, y - (SCREEN_SCALE_Y(size + 1.0f)), CRGBA(red, green, blue, alpha));\n\t\tbreak;\n\tcase BLIP_MODE_TRIANGULAR_DOWN:\n\t\tsize++;\n\t\tCSprite2d::Draw2DPolygon(x, y + SCREEN_SCALE_Y(size + 2.0f), x, y + SCREEN_SCALE_Y(size + 3.0f), x + SCREEN_SCALE_X(size + 3.0f), y - (SCREEN_SCALE_Y(size + 2.0f)), x - (SCREEN_SCALE_X(size + 3.0f)), y - (SCREEN_SCALE_Y(size + 2.0f)), CRGBA(0, 0, 0, alpha));\n\t\tCSprite2d::Draw2DPolygon(x, y + SCREEN_SCALE_Y(size + 1.0f), x, y + SCREEN_SCALE_Y(size + 1.0f), x + SCREEN_SCALE_X(size + 1.0f), y - (SCREEN_SCALE_Y(size + 1.0f)), x - (SCREEN_SCALE_X(size + 1.0f)), y - (SCREEN_SCALE_Y(size + 1.0f)), CRGBA(red, green, blue, alpha));\n\t\tbreak;\n\tcase BLIP_MODE_SQUARE:\n\t\tCSprite2d::DrawRect(CRect(x - SCREEN_SCALE_X(size + 1.0f), y - SCREEN_SCALE_Y(size + 1.0f), SCREEN_SCALE_X(size + 1.0f) + x, SCREEN_SCALE_Y(size + 1.0f) + y), CRGBA(0, 0, 0, alpha));\n\t\tCSprite2d::DrawRect(CRect(x - SCREEN_SCALE_X(size), y - SCREEN_SCALE_Y(size), SCREEN_SCALE_X(size) + x, SCREEN_SCALE_Y(size) + y), CRGBA(red, green, blue, alpha));\n\t\tbreak;\n\t}\n}\n\nvoid CRadar::Shutdown()\n{\n\tCentreSprite.Delete();\n\tMapHereSprite.Delete();\n\tNorthSprite.Delete();\n\tAverySprite.Delete();\n\tBikerSprite.Delete();\n\tCortezSprite.Delete();\n\tDiazSprite.Delete();\n\tKentSprite.Delete();\n\tLawyerSprite.Delete();\n\tPhilSprite.Delete();\n\tBikersSprite.Delete();\n\tBoatyardSprite.Delete();\n\tMalibuClubSprite.Delete();\n\tCubansSprite.Delete();\n\tFilmSprite.Delete();\n\tGunSprite.Delete();\n\tHaitiansSprite.Delete();\n\tHardwareSprite.Delete();\n\tSaveHouseSprite.Delete();\n\tStripSprite.Delete();\n\tIceSprite.Delete();\n\tKCabsSprite.Delete();\n\tLovefistSprite.Delete();\n\tPrintworksSprite.Delete();\n\tPropertySprite.Delete();\n\tSunYardSprite.Delete();\n\tSpraySprite.Delete();\n\tTShirtSprite.Delete();\n\tTommySprite.Delete();\n\tPhoneSprite.Delete();\n\tRadioWildstyleSprite.Delete();\n\tRadioFlashSprite.Delete();\n\tRadioKChatSprite.Delete();\n\tRadioFeverSprite.Delete();\n\tRadioVRockSprite.Delete();\n\tRadioVCPRSprite.Delete();\n\tRadioEspantosoSprite.Delete();\n\tRadioEmotionSprite.Delete();\n\tRadioWaveSprite.Delete();\n\tRemoveRadarSections();\n}\n\nvoid CRadar::StreamRadarSections(const CVector &posn)\n{\n\tif (!CStreaming::ms_disableStreaming)\n\t\tStreamRadarSections(Floor((RADAR_MAX_X + posn.x) / RADAR_TILE_SIZE), Ceil((RADAR_NUM_TILES - 1) - (RADAR_MAX_Y + posn.y) / RADAR_TILE_SIZE));\n}\n\nvoid CRadar::StreamRadarSections(int32 x, int32 y)\n{\n\tfor (int i = 0; i < RADAR_NUM_TILES; ++i) {\n\t\tfor (int j = 0; j < RADAR_NUM_TILES; ++j) {\n\t\t\tif ((i >= x - 1 && i <= x + 1) && (j >= y - 1 && j <= y + 1))\n\t\t\t\tRequestMapSection(i, j);\n\t\t\telse\n\t\t\t\tRemoveMapSection(i, j);\n\t\t};\n\t};\n}\n\nvoid CRadar::TransformRealWorldToTexCoordSpace(CVector2D &out, const CVector2D &in, int32 x, int32 y)\n{\n\tout.x = in.x - (x * RADAR_TILE_SIZE + RADAR_MIN_X);\n\tout.y = -(in.y - ((RADAR_NUM_TILES - y) * RADAR_TILE_SIZE + RADAR_MIN_Y));\n\tout.x /= RADAR_TILE_SIZE;\n\tout.y /= RADAR_TILE_SIZE;\n}\n\nvoid CRadar::TransformRadarPointToRealWorldSpace(CVector2D &out, const CVector2D &in)\n{\n\tfloat s, c;\n\ts = -cachedSin;\n\tc = cachedCos;\n\n\tout.x = s * in.y + c * in.x;\n\tout.y = c * in.y - s * in.x;\n\n\tout = out * m_radarRange + vec2DRadarOrigin;\n}\n\n// Radar space goes from -1.0 to 1.0 in x and y, top right is (1.0, 1.0)\nvoid CRadar::TransformRadarPointToScreenSpace(CVector2D &out, const CVector2D &in)\n{\n\tif (FrontEndMenuManager.m_bMenuMapActive) {\n\t\tout.x = (FrontEndMenuManager.m_fMapCenterX - FrontEndMenuManager.m_fMapSize) + (MENU_MAP_LENGTH / 2 + MENU_MAP_LEFT_OFFSET + in.x) * FrontEndMenuManager.m_fMapSize * MENU_MAP_WIDTH_SCALE * 2.0f / MENU_MAP_LENGTH;\n\t\tout.y = (FrontEndMenuManager.m_fMapCenterY - FrontEndMenuManager.m_fMapSize) + (MENU_MAP_LENGTH / 2 - MENU_MAP_TOP_OFFSET - in.y) * FrontEndMenuManager.m_fMapSize * MENU_MAP_HEIGHT_SCALE * 2.0f / MENU_MAP_LENGTH;\n\t} else {\n#ifdef FIX_BUGS\n\t\tout.x = (in.x + 1.0f) * 0.5f * SCREEN_SCALE_X(RADAR_WIDTH) + SCREEN_SCALE_X(RADAR_LEFT);\n#else\n\t\tout.x = (in.x + 1.0f) * 0.5f * SCREEN_SCALE_X(RADAR_WIDTH) + RADAR_LEFT;\n#endif\n\t\tout.y = (1.0f - in.y) * 0.5f * SCREEN_SCALE_Y(RADAR_HEIGHT) + SCREEN_SCALE_FROM_BOTTOM(RADAR_BOTTOM + RADAR_HEIGHT);\n\t}\n}\n\nvoid CRadar::TransformRealWorldPointToRadarSpace(CVector2D &out, const CVector2D &in)\n{\n\tfloat s, c;\n\ts = cachedSin;\n\tc = cachedCos;\n\n\tfloat x = (in.x - vec2DRadarOrigin.x) * (1.0f / m_radarRange);\n\tfloat y = (in.y - vec2DRadarOrigin.y) * (1.0f / m_radarRange);\n\n\tout.x = s * y + c * x;\n\tout.y = c * y - s * x;\n}\n\nvoid\nCRadar::CalculateCachedSinCos()\n{\n\tif (/*TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOPDOWN || TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOP_DOWN_PED || */\n\t\tFrontEndMenuManager.m_bMenuMapActive ) {\n\t\tcachedSin = 0.0f;\n\t\tcachedCos = 1.0f;\n\t} else if (TheCamera.GetLookDirection() == LOOKING_FORWARD) {\n\t\tcachedSin = Sin(TheCamera.GetForward().Heading());\n\t\tcachedCos = Cos(TheCamera.GetForward().Heading());\n\t} else {\n\t\tCVector forward;\n\n\t\tif (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_1STPERSON) {\n\t\t\tforward = TheCamera.Cams[TheCamera.ActiveCam].CamTargetEntity->GetForward();\n\t\t\tforward.Normalise();\t// a bit useless...\n\t\t}\n\t\telse\n\t\t\tforward = TheCamera.Cams[TheCamera.ActiveCam].CamTargetEntity->GetPosition() - TheCamera.Cams[TheCamera.ActiveCam].SourceBeforeLookBehind;\n\n\t\tcachedSin = Sin(forward.Heading());\n\t\tcachedCos = Cos(forward.Heading());\n\t}\n}\n\nvoid\nCRadar::InitFrontEndMap()\n{\n\tCalculateCachedSinCos();\n\tvec2DRadarOrigin.x = 0.0f;\n\tvec2DRadarOrigin.y = 0.0f;\n\tm_radarRange = MENU_MAP_LENGTH_UNIT; // just affects the multiplier in TransformRadarPointToScreenSpace\n\tfor (int i = 0; i < NUM_MAP_LEGENDS; i++) {\n\t\tMapLegendList[i] = RADAR_SPRITE_NONE;\n\t}\n\tMapLegendCounter = 0;\n\tArrowBlipColour1 = CRGBA(0, 0, 0, 0);\n\tArrowBlipColour2 = CRGBA(0, 0, 0, 0);\n}\n\nvoid\nCRadar::DrawYouAreHereSprite(float x, float y)\n{\n\tstatic PauseModeTime lastChange = 0;\n\tstatic bool show = true;\n\n\tif (show) {\n\t\tif (CTimer::GetTimeInMillisecondsPauseMode() - lastChange > 500) {\n\t\t\tlastChange = CTimer::GetTimeInMillisecondsPauseMode();\n\t\t\tshow = !show;\n\t\t}\n\t} else {\n\t\tif (CTimer::GetTimeInMillisecondsPauseMode() - lastChange > 200) {\n\t\t\tlastChange = CTimer::GetTimeInMillisecondsPauseMode();\n\t\t\tshow = !show;\n\t\t}\n\t}\n\n\tif (show) {\n\t\tconst float left = x - SCREEN_SCALE_X(8.0f);\n\t\tconst float top = y - SCREEN_SCALE_Y(40.0f);\n\t\tconst float right = x + SCREEN_SCALE_X(40.0);\n\t\tconst float bottom = y + SCREEN_SCALE_Y(8.0f);\n\t\tMapHereSprite.Draw(CRect(left + SCREEN_SCALE_X(2.f), top + SCREEN_SCALE_Y(2.f), right + SCREEN_SCALE_X(2.f), bottom + SCREEN_SCALE_Y(2.f)),\n\t\t\tCRGBA(0, 0, 0, 255));\n\n\t\tMapHereSprite.Draw(CRect(left, top, right, bottom), CRGBA(255, 255, 255, 255));\n\n\t\tCFont::SetWrapx(right + SCREEN_SCALE_X(28.0f));\n\t\tCFont::SetRightJustifyWrap(right);\n\t\tCFont::SetBackGroundOnlyTextOff();\n\t\tCFont::SetColor(CRGBA(255, 150, 225, 255));\n\t\tCFont::SetDropShadowPosition(2);\n\t\tCFont::SetDropColor(CRGBA(0, 0, 0, 255));\n\t\tCFont::SetCentreOff();\n\t\tCFont::SetRightJustifyOff();\n\t\tCFont::SetFontStyle(FONT_LOCALE(FONT_HEADING));\n\t\tCFont::SetScale(SCREEN_SCALE_X(0.65f), SCREEN_SCALE_Y(0.95f));\n\t\tCFont::PrintString(right, top, TheText.Get(\"MAP_YAH\"));\n\t\tCFont::SetDropShadowPosition(0);\n\t\tCFont::DrawFonts();\n\t}\n\tMapLegendList[MapLegendCounter++] = RADAR_SPRITE_MAP_HERE;\n}\n\n#ifdef MAP_ENHANCEMENTS\nvoid\nCRadar::ToggleTargetMarker(float x, float y)\n{\n\tif (TargetMarkerId == -1) {\n\t\tint nextBlip;\n\t\tfor (nextBlip = 0; nextBlip < NUMRADARBLIPS; nextBlip++) {\n\t\t\tif (!ms_RadarTrace[nextBlip].m_bInUse)\n\t\t\t\tbreak;\n\t\t}\n\t\t\n\t\tif (nextBlip == NUMRADARBLIPS)\n\t\t\treturn;\n\t\t\t\n\t\tms_RadarTrace[nextBlip].m_eBlipType = BLIP_COORD;\n\t\tms_RadarTrace[nextBlip].m_nColor = RADAR_TRACE_GRAY;\n\t\tms_RadarTrace[nextBlip].m_bDim = 0;\n\t\tms_RadarTrace[nextBlip].m_bInUse = 1;\n\t\tms_RadarTrace[nextBlip].m_Radius = 1.0f;\n\t\tCVector pos(x, y, CWorld::FindGroundZForCoord(x,y));\n\t\tTargetMarkerPos = pos;\n\t\tms_RadarTrace[nextBlip].m_vec2DPos = pos;\n\t\tms_RadarTrace[nextBlip].m_vecPos = pos;\n\t\tms_RadarTrace[nextBlip].m_nEntityHandle = 0;\n\t\tms_RadarTrace[nextBlip].m_wScale = 5;\n\t\tms_RadarTrace[nextBlip].m_eBlipDisplay = BLIP_DISPLAY_BLIP_ONLY;\n\t\tms_RadarTrace[nextBlip].m_eRadarSprite = RADAR_SPRITE_NONE;\n\t\tTargetMarkerId = CRadar::GetNewUniqueBlipIndex(nextBlip);\n\t} else {\n\t\tClearBlip(TargetMarkerId);\n\t\tTargetMarkerId = -1;\n\t}\n}\n#endif\n\nvoid\nCRadar::DrawEntityBlip(int32 blipId)\n{\n\tCVector2D out;\n\tCVector2D in;\n\tCEntity *blipEntity;\n\tswitch (ms_RadarTrace[blipId].m_eBlipType) {\n\t\tcase BLIP_CAR:\n\t\t\tblipEntity = CPools::GetVehiclePool()->GetAt(ms_RadarTrace[blipId].m_nEntityHandle);\n\t\t\tbreak;\n\t\tcase BLIP_CHAR:\n\t\t\tblipEntity = CPools::GetPedPool()->GetAt(ms_RadarTrace[blipId].m_nEntityHandle);\n\t\t\tif (blipEntity != nil) {\n\t\t\t\tif (((CPed*)blipEntity)->InVehicle())\n\t\t\t\t\tblipEntity = ((CPed*)blipEntity)->m_pMyVehicle;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase BLIP_OBJECT:\n\t\t\tblipEntity = CPools::GetObjectPool()->GetAt(ms_RadarTrace[blipId].m_nEntityHandle);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\tif (blipEntity) {\n\t\tuint32 color = GetRadarTraceColour(ms_RadarTrace[blipId].m_nColor, ms_RadarTrace[blipId].m_bDim);\n\t\tif (ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_MARKER_ONLY) {\n\t\t\tif (CTheScripts::IsDebugOn()) {\n\t\t\t\tShowRadarMarker(blipEntity->GetPosition(), color, ms_RadarTrace[blipId].m_Radius);\n\t\t\t\tms_RadarTrace[blipId].m_Radius = ms_RadarTrace[blipId].m_Radius - 0.1f;\n\t\t\t\tif (ms_RadarTrace[blipId].m_Radius < 1.0f)\n\t\t\t\t\tms_RadarTrace[blipId].m_Radius = 5.0f;\n\t\t\t}\n\t\t}\n\t\tif (ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_BLIP_ONLY) {\n\t\t\tTransformRealWorldPointToRadarSpace(in, blipEntity->GetPosition());\n\t\t\tfloat dist = LimitRadarPoint(in);\n\t\t\tTransformRadarPointToScreenSpace(out, in);\n\t\t\tif (!ms_RadarTrace[blipId].m_bShortRange || dist <= 1.0f || FrontEndMenuManager.m_bMenuMapActive) {\n\t\t\t\tif (ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_NONE) {\n\t\t\t\t\tDrawRadarSprite(ms_RadarTrace[blipId].m_eRadarSprite, out.x, out.y, CalculateBlipAlpha(dist));\n\t\t\t\t} else {\n\t\t\t\t\tconst CVector& pos = FindPlayerCentreOfWorld_NoSniperShift();\n\t\t\t\t\tconst CVector& blipPos = blipEntity->GetPosition();\n\t\t\t\t\tuint8 mode = BLIP_MODE_TRIANGULAR_UP;\n\t\t\t\t\tif (blipPos.z - pos.z <= 2.0f) {\n\t\t\t\t\t\tif (blipPos.z - pos.z < -4.0f) mode = BLIP_MODE_TRIANGULAR_DOWN;\n\t\t\t\t\t\telse mode = BLIP_MODE_SQUARE;\n\t\t\t\t\t}\n\t\t\t\t\tShowRadarTraceWithHeight(out.x, out.y, ms_RadarTrace[blipId].m_wScale, (uint8)(color >> 24), (uint8)(color >> 16), (uint8)(color >> 8), 255, mode);\n\n\t\t\t\t\tif (FrontEndMenuManager.m_bMenuMapActive) {\n\t\t\t\t\t\tbool alreadyThere = false;\n\t\t\t\t\t\tfor (int i = 0; i < NUM_MAP_LEGENDS; i++) {\n\t\t\t\t\t\t\tif (MapLegendList[i] == -2)\n\t\t\t\t\t\t\t\talreadyThere = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!alreadyThere) {\n\t\t\t\t\t\t\tMapLegendList[MapLegendCounter] = -2;\n\t\t\t\t\t\t\tMapLegendCounter++;\n\t\t\t\t\t\t\tArrowBlipColour2 = CRGBA((uint8)(color >> 24), (uint8)(color >> 16), (uint8)(color >> 8), 255);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nCRadar::DrawCoordBlip(int32 blipId)\n{\n\tCVector2D out;\n\tCVector2D in;\n\tif (ms_RadarTrace[blipId].m_eBlipType != BLIP_CONTACT_POINT || !CTheScripts::IsPlayerOnAMission()) {\n\n\t\tuint32 color = GetRadarTraceColour(ms_RadarTrace[blipId].m_nColor, ms_RadarTrace[blipId].m_bDim);\n\t\tif (ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_MARKER_ONLY) {\n\t\t\tif (CTheScripts::IsDebugOn()) {\n\t\t\t\tShowRadarMarker(ms_RadarTrace[blipId].m_vecPos, color, ms_RadarTrace[blipId].m_Radius);\n\t\t\t\tms_RadarTrace[blipId].m_Radius = ms_RadarTrace[blipId].m_Radius - 0.1f;\n\t\t\t\tif (ms_RadarTrace[blipId].m_Radius < 1.0f)\n\t\t\t\t\tms_RadarTrace[blipId].m_Radius = 5.0f;\n\t\t\t}\n\t\t}\n\t\tif (ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_BOTH || ms_RadarTrace[blipId].m_eBlipDisplay == BLIP_DISPLAY_BLIP_ONLY) {\n\t\t\tTransformRealWorldPointToRadarSpace(in, ms_RadarTrace[blipId].m_vec2DPos);\n\t\t\tfloat dist = LimitRadarPoint(in);\n\t\t\tTransformRadarPointToScreenSpace(out, in);\n\t\t\tif (!ms_RadarTrace[blipId].m_bShortRange || dist <= 1.0f || FrontEndMenuManager.m_bMenuMapActive) {\n\t\t\t\tif (ms_RadarTrace[blipId].m_eRadarSprite != RADAR_SPRITE_NONE) {\n\t\t\t\t\tDrawRadarSprite(ms_RadarTrace[blipId].m_eRadarSprite, out.x, out.y, CalculateBlipAlpha(dist));\n\t\t\t\t} else {\n\t\t\t\t\tconst CVector& pos = FindPlayerCentreOfWorld_NoSniperShift();\n\t\t\t\t\tconst CVector& blipPos = ms_RadarTrace[blipId].m_vecPos;\n\t\t\t\t\tuint8 mode = BLIP_MODE_TRIANGULAR_UP;\n\t\t\t\t\tif (blipPos.z - pos.z <= 2.0f) {\n\t\t\t\t\t\tif (blipPos.z - pos.z < -4.0f) mode = BLIP_MODE_TRIANGULAR_DOWN;\n\t\t\t\t\t\telse mode = BLIP_MODE_SQUARE;\n\t\t\t\t\t}\n\t\t\t\t\tShowRadarTraceWithHeight(out.x, out.y, ms_RadarTrace[blipId].m_wScale, (uint8)(color >> 24), (uint8)(color >> 16), (uint8)(color >> 8), 255, mode);\n\n\t\t\t\t\tif (FrontEndMenuManager.m_bMenuMapActive) {\n\t\t\t\t\t\tbool alreadyThere = false;\n\t\t\t\t\t\tfor (int i = 0; i < NUM_MAP_LEGENDS; i++) {\n\t\t\t\t\t\t\tif (MapLegendList[i] == -1)\n\t\t\t\t\t\t\t\talreadyThere = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!alreadyThere) {\n\t\t\t\t\t\t\tMapLegendList[MapLegendCounter] = -1;\n\t\t\t\t\t\t\tMapLegendCounter++;\n\t\t\t\t\t\t\tArrowBlipColour1 = CRGBA((uint8)(color >> 24), (uint8)(color >> 16), (uint8)(color >> 8), 255);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nCRadar::DrawLegend(int32 x, int32 y, int32 sprite)\n{\n\tif (sprite < 0) {\n\t\tstatic PauseModeTime lastChange = 0;\n\t\tstatic int8 blipMode = 0;\n\n\t\tCRGBA color;\n\t\tif (sprite == -1) {\n\t\t\tcolor = ArrowBlipColour1;\n\t\t} else {\n\t\t\tcolor = ArrowBlipColour2;\n\t\t}\n\n\t\tif (CTimer::GetTimeInMillisecondsPauseMode() - lastChange > 600) {\n\t\t\tlastChange = CTimer::GetTimeInMillisecondsPauseMode();\n\t\t\tif ( blipMode == 2 )\n\t\t\t\tblipMode = 0;\n\t\t\telse\n\t\t\t\t++blipMode;\n\t\t}\n\n\t\tswitch (blipMode) {\n\t\t\tcase BLIP_MODE_TRIANGULAR_UP:\n\t\t\t\tCSprite2d::Draw2DPolygon(x + SCREEN_SCALE_X(14.0f), y + SCREEN_SCALE_Y(13.0f), x + SCREEN_SCALE_X(2.0f), y + SCREEN_SCALE_Y(13.0f), x + SCREEN_SCALE_X(8.f), y + SCREEN_SCALE_Y(2.0f), x + SCREEN_SCALE_X(8.f), y + SCREEN_SCALE_Y(2.0f), CRGBA(0, 0, 0, 255));\n\t\t\t\tCSprite2d::Draw2DPolygon(x + SCREEN_SCALE_X(12.0f), y + SCREEN_SCALE_Y(12.0f), x + SCREEN_SCALE_X(4.0f), y + SCREEN_SCALE_Y(12.0f), x + SCREEN_SCALE_X(8.f), y + SCREEN_SCALE_Y(4.0f), x + SCREEN_SCALE_X(8.f), y + SCREEN_SCALE_Y(4.0f), color);\n\t\t\t\tbreak;\n\t\t\tcase BLIP_MODE_TRIANGULAR_DOWN:\n\t\t\t\tCSprite2d::Draw2DPolygon(x + SCREEN_SCALE_X(8.0f), y + SCREEN_SCALE_Y(14.0f), x + SCREEN_SCALE_X(8.0f), y + SCREEN_SCALE_Y(14.0f), x + SCREEN_SCALE_X(2.f), y + SCREEN_SCALE_Y(3.0f), x + SCREEN_SCALE_X(2.f), y + SCREEN_SCALE_Y(3.0f), CRGBA(0, 0, 0, 255));\n\t\t\t\tCSprite2d::Draw2DPolygon(x + SCREEN_SCALE_X(8.0f), y + SCREEN_SCALE_Y(12.0f), x + SCREEN_SCALE_X(8.0f), y + SCREEN_SCALE_Y(12.0f), x + SCREEN_SCALE_X(12.f), y + SCREEN_SCALE_Y(4.0f), x + SCREEN_SCALE_X(4.f), y + SCREEN_SCALE_Y(4.0f), color);\n\t\t\t\tbreak;\n\t\t\tcase BLIP_MODE_SQUARE:\n\t\t\t\tCSprite2d::DrawRect(CRect(x + SCREEN_SCALE_X(4.0f), y + SCREEN_SCALE_Y(3.0f), SCREEN_SCALE_X(12.0f) + x, SCREEN_SCALE_Y(12.0f) + y), CRGBA(0, 0, 0, 255));\n\t\t\t\tCSprite2d::DrawRect(CRect(x + SCREEN_SCALE_X(5.0f), y + SCREEN_SCALE_Y(4.0f), SCREEN_SCALE_X(11.0f) + x, SCREEN_SCALE_Y(11.0f) + y), color);\n\t\t\t\tbreak;\n\t\t}\n\n\t} else {\n\t\tRadarSprites[sprite]->Draw(CRect(x, y, x + SCREEN_SCALE_X(16.f), y + SCREEN_SCALE_X(16.f)), CRGBA(255, 255, 255, 255));\n\t}\n\n\twchar *text;\n\tswitch ( sprite ) {\n\t\tcase RADAR_SPRITE_ENTITY_BLIP:\n\t\t\ttext = TheText.Get(\"LG_38\");\n\t\tbreak;\n\t\tcase RADAR_SPRITE_COORD_BLIP:\n\t\t\ttext = TheText.Get(\"LG_35\");\n\t\tbreak;\n\t\tcase RADAR_SPRITE_MAP_HERE:\n\t\t\ttext = TheText.Get(\"LG_01\");\n\t\tbreak;\n\t\tcase RADAR_SPRITE_AVERY:\n\t\t\ttext = TheText.Get(\"LG_02\");\n\t\tbreak;\n\t\tcase RADAR_SPRITE_BIKER:\n\t\t\ttext = TheText.Get(\"LG_03\");\n\t\tbreak;\n\t\tcase RADAR_SPRITE_CORTEZ:\n\t\t\ttext = TheText.Get(\"LG_04\");\n\t\tbreak;\n\t\tcase RADAR_SPRITE_DIAZ:\n\t\t\ttext = TheText.Get(\"LG_05\");\n\t\tbreak;\n\t\tcase RADAR_SPRITE_KENT:\n\t\t\ttext = TheText.Get(\"LG_06\");\n\t\tbreak;\n\t\tcase RADAR_SPRITE_LAWYER:\n\t\t\ttext = TheText.Get(\"LG_07\");\n\t\tbreak;\n\t\tcase RADAR_SPRITE_PHIL:\n\t\t\ttext = TheText.Get(\"LG_08\");\n\t\tbreak;\n\t\tcase RADAR_SPRITE_BIKERS:\n\t\t\ttext = TheText.Get(\"LG_03\");\n\t\tbreak;\n\t\tcase RADAR_SPRITE_BOATYARD:\n\t\t\ttext = TheText.Get(\"LG_09\");\n\t\tbreak;\n\t\tcase RADAR_SPRITE_MALIBU_CLUB:\n\t\t\ttext = TheText.Get(\"LG_10\");\n\t\tbreak;\n\t\tcase RADAR_SPRITE_CUBANS:\n\t\t\ttext = TheText.Get(\"LG_11\");\n\t\tbreak;\n\t\tcase RADAR_SPRITE_FILM:\n\t\t\ttext = TheText.Get(\"LG_12\");\n\t\tbreak;\n\t\tcase RADAR_SPRITE_GUN:\n\t\t\ttext = TheText.Get(\"LG_13\");\n\t\tbreak;\n\t\tcase RADAR_SPRITE_HAITIANS:\n\t\t\ttext = TheText.Get(\"LG_14\");\n\t\tbreak;\n\t\tcase RADAR_SPRITE_HARDWARE:\n\t\t\ttext = TheText.Get(\"LG_15\");\n\t\tbreak;\n\t\tcase RADAR_SPRITE_SAVE:\n\t\t\ttext = TheText.Get(\"LG_16\");\n\t\tbreak;\n\t\tcase RADAR_SPRITE_STRIP:\n\t\t\ttext = TheText.Get(\"LG_37\");\n\t\tbreak;\n\t\tcase RADAR_SPRITE_ICE:\n\t\t\ttext = TheText.Get(\"LG_17\");\n\t\tbreak;\n\t\tcase RADAR_SPRITE_KCABS:\n\t\t\ttext = TheText.Get(\"LG_18\");\n\t\tbreak;\n\t\tcase RADAR_SPRITE_LOVEFIST:\n\t\t\ttext = TheText.Get(\"LG_19\");\n\t\tbreak;\n\t\tcase RADAR_SPRITE_PRINTWORKS:\n\t\t\ttext = TheText.Get(\"LG_20\");\n\t\tbreak;\n\t\tcase RADAR_SPRITE_PROPERTY:\n\t\t\ttext = TheText.Get(\"LG_21\");\n\t\tbreak;\n\t\tcase RADAR_SPRITE_SUNYARD:\n\t\t\ttext = TheText.Get(\"LG_36\");\n\t\tbreak;\n\t\tcase RADAR_SPRITE_SPRAY:\n\t\t\ttext = TheText.Get(\"LG_22\");\n\t\tbreak;\n\t\tcase RADAR_SPRITE_TSHIRT:\n\t\t\ttext = TheText.Get(\"LG_23\");\n\t\tbreak;\n\t\tcase RADAR_SPRITE_TOMMY:\n\t\t\ttext = TheText.Get(\"LG_24\");\n\t\tbreak;\n\t\tcase RADAR_SPRITE_PHONE:\n\t\t\ttext = TheText.Get(\"LG_25\");\n\t\tbreak;\n\t\tcase RADAR_SPRITE_RADIO_WILDSTYLE:\n\t\t\ttext = TheText.Get(\"LG_26\");\n\t\tbreak;\n\t\tcase RADAR_SPRITE_RADIO_FLASH:\n\t\t\ttext = TheText.Get(\"LG_27\");\n\t\tbreak;\n\t\tcase RADAR_SPRITE_RADIO_KCHAT:\n\t\t\ttext = TheText.Get(\"LG_28\");\n\t\tbreak;\n\t\tcase RADAR_SPRITE_RADIO_FEVER:\n\t\t\ttext = TheText.Get(\"LG_29\");\n\t\tbreak;\n\t\tcase RADAR_SPRITE_RADIO_VROCK:\n\t\t\ttext = TheText.Get(\"LG_30\");\n\t\tbreak;\n\t\tcase RADAR_SPRITE_RADIO_VCPR:\n\t\t\ttext = TheText.Get(\"LG_31\");\n\t\tbreak;\n\t\tcase RADAR_SPRITE_RADIO_ESPANTOSO:\n\t\t\ttext = TheText.Get(\"LG_32\");\n\t\tbreak;\n\t\tcase RADAR_SPRITE_RADIO_EMOTION:\n\t\t\ttext = TheText.Get(\"LG_33\");\n\t\tbreak;\n\t\tcase RADAR_SPRITE_RADIO_WAVE:\n\t\t\ttext = TheText.Get(\"LG_34\");\n\t\tbreak;\n\t\tdefault:\n\t\tbreak;\n\t}\n\tCFont::PrintString(SCREEN_SCALE_X(20.f) + x, SCREEN_SCALE_Y(3.0f) + y, text);\n}\n"
  },
  {
    "path": "src/core/Radar.h",
    "content": "#pragma once\n#include \"Sprite2d.h\"\n\n#define CARBLIP_MARKER_COLOR_R 252\n#define CARBLIP_MARKER_COLOR_G 138\n#define CARBLIP_MARKER_COLOR_B 242\n#define CARBLIP_MARKER_COLOR_A 255\n\n#define CHARBLIP_MARKER_COLOR_R 252\n#define CHARBLIP_MARKER_COLOR_G 138\n#define CHARBLIP_MARKER_COLOR_B 242\n#define CHARBLIP_MARKER_COLOR_A 255\n\n#define OBJECTBLIP_MARKER_COLOR_R 252\n#define OBJECTBLIP_MARKER_COLOR_G 138\n#define OBJECTBLIP_MARKER_COLOR_B 242\n#define OBJECTBLIP_MARKER_COLOR_A 255\n\n#define COORDBLIP_MARKER_COLOR_R 252\n#define COORDBLIP_MARKER_COLOR_G 138\n#define COORDBLIP_MARKER_COLOR_B 242\n#define COORDBLIP_MARKER_COLOR_A 228\n\n#define NUM_MAP_LEGENDS 75\n\n#define MENU_MAP_LENGTH_UNIT 1190.0f // in game unit\n#define MENU_MAP_WIDTH_SCALE 1.112f // in game unit (originally 1.112494151260504f)\n#define MENU_MAP_HEIGHT_SCALE 1.119f // in game unit (originally 1.118714268907563f)\n#define MENU_MAP_TOP_OFFSET 0.28f // in length unit defined above - ~333 game unit\n#define MENU_MAP_LEFT_OFFSET 0.185f // in length unit defined above - ~220 game unit\n#define MENU_MAP_LENGTH (4000.f / MENU_MAP_LENGTH_UNIT)\n\nenum eBlipType\n{\n\tBLIP_NONE,\n\tBLIP_CAR,\n\tBLIP_CHAR,\n\tBLIP_OBJECT,\n\tBLIP_COORD,\n\tBLIP_CONTACT_POINT\n};\n\nenum eBlipDisplay\n{\n\tBLIP_DISPLAY_NEITHER = 0,\n\tBLIP_DISPLAY_MARKER_ONLY = 1,\n\tBLIP_DISPLAY_BLIP_ONLY = 2,\n\tBLIP_DISPLAY_BOTH = 3,\n};\n\nenum eRadarSprite\n{\n\tRADAR_SPRITE_ENTITY_BLIP = -2,\n\tRADAR_SPRITE_COORD_BLIP = -1,\n\tRADAR_SPRITE_NONE = 0,\n\tRADAR_SPRITE_CENTRE,\n\tRADAR_SPRITE_MAP_HERE,\n\tRADAR_SPRITE_NORTH,\n\tRADAR_SPRITE_AVERY,\n\tRADAR_SPRITE_BIKER,\n\tRADAR_SPRITE_CORTEZ,\n\tRADAR_SPRITE_DIAZ,\n\tRADAR_SPRITE_KENT,\n\tRADAR_SPRITE_LAWYER,\n\tRADAR_SPRITE_PHIL,\n\tRADAR_SPRITE_BIKERS,\n\tRADAR_SPRITE_BOATYARD,\n\tRADAR_SPRITE_MALIBU_CLUB,\n\tRADAR_SPRITE_CUBANS,\n\tRADAR_SPRITE_FILM,\n\tRADAR_SPRITE_GUN,\n\tRADAR_SPRITE_HAITIANS,\n\tRADAR_SPRITE_HARDWARE,\n\tRADAR_SPRITE_SAVE,\n\tRADAR_SPRITE_STRIP,\n\tRADAR_SPRITE_ICE,\n\tRADAR_SPRITE_KCABS,\n\tRADAR_SPRITE_LOVEFIST,\n\tRADAR_SPRITE_PRINTWORKS,\n\tRADAR_SPRITE_PROPERTY,\n\tRADAR_SPRITE_SUNYARD,\n\tRADAR_SPRITE_SPRAY,\n\tRADAR_SPRITE_TSHIRT,\n\tRADAR_SPRITE_TOMMY,\n\tRADAR_SPRITE_PHONE,\n\tRADAR_SPRITE_RADIO_WILDSTYLE,\n\tRADAR_SPRITE_RADIO_FLASH,\n\tRADAR_SPRITE_RADIO_KCHAT,\n\tRADAR_SPRITE_RADIO_FEVER,\n\tRADAR_SPRITE_RADIO_VROCK,\n\tRADAR_SPRITE_RADIO_VCPR,\n\tRADAR_SPRITE_RADIO_ESPANTOSO,\n\tRADAR_SPRITE_RADIO_EMOTION,\n\tRADAR_SPRITE_RADIO_WAVE,\n\n\tRADAR_SPRITE_COUNT\n};\n\nenum\n{\n\tRADAR_TRACE_RED,\n\tRADAR_TRACE_GREEN,\n\tRADAR_TRACE_LIGHT_BLUE,\n\tRADAR_TRACE_GRAY,\n\tRADAR_TRACE_YELLOW,\n\tRADAR_TRACE_MAGENTA,\n\tRADAR_TRACE_CYAN\n};\n\nenum\n{\n\tBLIP_MODE_TRIANGULAR_UP = 0,\n\tBLIP_MODE_TRIANGULAR_DOWN,\n\tBLIP_MODE_SQUARE,\n};\n\nstruct sRadarTrace\n{\n\tuint32 m_nColor;\n\tuint32 m_eBlipType; // eBlipType\n\tint32 m_nEntityHandle;\n\tCVector m_vec2DPos;\n\tCVector m_vecPos;\n\tuint16 m_BlipIndex;\n\tbool m_bDim;\n\tbool m_bInUse;\n\tbool m_bShortRange;\n\tbool m_unused;\n\tfloat m_Radius;\n\tint16 m_wScale;\n\tuint16 m_eBlipDisplay; // eBlipDisplay\n\tuint16 m_eRadarSprite; // eRadarSprite\n};\n\n// Either that was a thing while saving/loading blips, or they added sizes of each field one by one. I want to do the former.\n#pragma pack(push,1)\nstruct sRadarTraceSave\n{\n\tuint32 m_nColor;\n\tfloat m_Radius;\n\tuint32 m_eBlipType; // eBlipType\n\tint32 m_nEntityHandle;\n\tCVector2D m_vec2DPos;\n\tCVector m_vecPos;\n\tuint16 m_BlipIndex;\n\tbool m_bDim;\n\tbool m_bInUse;\n\tbool m_bShortRange;\n\tbool m_unused;\n\tint16 m_wScale;\n\tuint16 m_eBlipDisplay; // eBlipDisplay\n\tuint16 m_eRadarSprite; // eRadarSprite\n};\n#pragma pack(pop)\n\n// Values for screen space\n#define RADAR_LEFT (40.0f)\n#define RADAR_BOTTOM (40.0f)\n\n#ifdef FIX_RADAR\n/*\n\tThe values are from an early screenshot taken before R* broke radar\n\t\t#define RADAR_WIDTH (82.0f)\n\t\t#define RADAR_HEIGHT (82.0f)\n*/\n#define RADAR_WIDTH ((CDraw::ms_bFixRadar)  ? (82.0f) : (94.0f))\t\n#define RADAR_HEIGHT ((CDraw::ms_bFixRadar) ? (82.0f) : (76.0f))\n#else\n/*\n\tbroken since forever, someone tried to fix size for 640x512(PAL)\n\t\thttp://aap.rockstarvision.com/pics/gta3/ps2screens/gta3_interface.jpg\n\tbut failed:\n\t\thttp://aap.rockstarvision.com/pics/gta3/artwork/gta3_artwork_16.jpg\n\tmost likely the guy used something like this:\n\t\tint y = 82 * (640.0/512.0)/(640.0/480.0);\n\t\tint x = y * (640.0/512.0);\n*/\n#define RADAR_WIDTH (94.0f)\n#define RADAR_HEIGHT (76.0f)\n#endif\n\nclass CRadar\n{\npublic:\n\tstatic float m_radarRange;\n\tstatic sRadarTrace ms_RadarTrace[NUMRADARBLIPS];\n\tstatic CSprite2d CentreSprite;\n\tstatic CSprite2d MapHereSprite;\n\tstatic CSprite2d NorthSprite;\n\tstatic CSprite2d AverySprite;\n\tstatic CSprite2d BikerSprite;\n\tstatic CSprite2d CortezSprite;\n\tstatic CSprite2d DiazSprite;\n\tstatic CSprite2d KentSprite;\n\tstatic CSprite2d LawyerSprite;\n\tstatic CSprite2d PhilSprite;\n\tstatic CSprite2d BikersSprite;\n\tstatic CSprite2d BoatyardSprite;\n\tstatic CSprite2d MalibuClubSprite;\n\tstatic CSprite2d CubansSprite;\n\tstatic CSprite2d FilmSprite;\n\tstatic CSprite2d GunSprite;\n\tstatic CSprite2d HaitiansSprite;\n\tstatic CSprite2d HardwareSprite;\n\tstatic CSprite2d SaveHouseSprite;\n\tstatic CSprite2d StripSprite;\n\tstatic CSprite2d IceSprite;\n\tstatic CSprite2d KCabsSprite;\n\tstatic CSprite2d LovefistSprite;\n\tstatic CSprite2d PrintworksSprite;\n\tstatic CSprite2d PropertySprite;\n\tstatic CSprite2d SunYardSprite;\n\tstatic CSprite2d SpraySprite;\n\tstatic CSprite2d TShirtSprite;\n\tstatic CSprite2d TommySprite;\n\tstatic CSprite2d PhoneSprite;\n\tstatic CSprite2d RadioWildstyleSprite;\n\tstatic CSprite2d RadioFlashSprite;\n\tstatic CSprite2d RadioKChatSprite;\n\tstatic CSprite2d RadioFeverSprite;\n\tstatic CSprite2d RadioVRockSprite;\n\tstatic CSprite2d RadioVCPRSprite;\n\tstatic CSprite2d RadioEspantosoSprite;\n\tstatic CSprite2d RadioEmotionSprite;\n\tstatic CSprite2d RadioWaveSprite;\n\tstatic CSprite2d *RadarSprites[RADAR_SPRITE_COUNT];\n\tstatic float cachedCos;\n\tstatic float cachedSin;\n\tstatic CRGBA ArrowBlipColour1;\n\tstatic CRGBA ArrowBlipColour2;\n\tstatic int16 MapLegendList[NUM_MAP_LEGENDS];\n\tstatic int16 MapLegendCounter;\n\n#ifdef MAP_ENHANCEMENTS\n\tstatic int TargetMarkerId;\n\tstatic CVector TargetMarkerPos;\n#endif\n\n\tstatic void InitFrontEndMap();\n\tstatic void DrawYouAreHereSprite(float, float);\n#ifdef MAP_ENHANCEMENTS\n\tstatic void ToggleTargetMarker(float, float);\n#endif\n\tstatic uint8 CalculateBlipAlpha(float dist);\n\tstatic void ChangeBlipBrightness(int32 i, int32 bright);\n\tstatic void ChangeBlipColour(int32 i, int32);\n\tstatic void ChangeBlipDisplay(int32 i, eBlipDisplay display);\n\tstatic void ChangeBlipScale(int32 i, int32 scale);\n\tstatic void ClearBlip(int32 i);\n\tstatic void ClearBlipForEntity(eBlipType type, int32 id);\n\tstatic int ClipRadarPoly(CVector2D *out, const CVector2D *in);\n\tstatic bool DisplayThisBlip(int32 i);\n\tstatic void Draw3dMarkers();\n\tstatic void DrawBlips();\n\tstatic void DrawMap();\n\tstatic void DrawRadarMap();\n\tstatic void DrawRadarMask();\n\tstatic void DrawRadarSection(int32 x, int32 y);\n\tstatic void DrawRadarSprite(uint16 sprite, float x, float y, uint8 alpha);\n\tstatic void DrawRotatingRadarSprite(CSprite2d* sprite, float x, float y, float angle, int32 alpha);\n\tstatic int32 GetActualBlipArrayIndex(int32 i);\n\tstatic int32 GetNewUniqueBlipIndex(int32 i);\n\tstatic uint32 GetRadarTraceColour(uint32 color, bool bright);\n\tstatic void Initialise();\n\tstatic float LimitRadarPoint(CVector2D &point);\n\tstatic void LoadAllRadarBlips(uint8 *buf, uint32 size);\n\tstatic void LoadTextures();\n\tstatic void RemoveRadarSections();\n\tstatic void SaveAllRadarBlips(uint8*, uint32*);\n\tstatic void SetBlipSprite(int32 i, int32 icon);\n\tstatic int32 SetCoordBlip(eBlipType type, CVector pos, uint32, eBlipDisplay);\n\tstatic int32 SetEntityBlip(eBlipType type, int32, uint32, eBlipDisplay);\n\tstatic int32 SetShortRangeCoordBlip(eBlipType type, CVector pos, uint32, eBlipDisplay);\n\tstatic void SetRadarMarkerState(int32 i, bool flag);\n\tstatic void ShowRadarMarker(CVector pos, uint32 color, float radius);\n\tstatic void ShowRadarTrace(float x, float y, uint32 size, uint8 red, uint8 green, uint8 blue, uint8 alpha);\n\tstatic void ShowRadarTraceWithHeight(float x, float y, uint32 size, uint8 red, uint8 green, uint8 blue, uint8 alpha, uint8 mode);\n\tstatic void Shutdown();\n\tstatic void StreamRadarSections(const CVector &posn);\n\tstatic void StreamRadarSections(int32 x, int32 y);\n\tstatic void TransformRealWorldToTexCoordSpace(CVector2D &out, const CVector2D &in, int32 x, int32 y);\n\tstatic void TransformRadarPointToRealWorldSpace(CVector2D &out, const CVector2D &in);\n\tstatic void TransformRadarPointToScreenSpace(CVector2D &out, const CVector2D &in);\n\tstatic void TransformRealWorldPointToRadarSpace(CVector2D &out, const CVector2D &in);\n\tstatic void CalculateCachedSinCos();\n\tstatic void DrawEntityBlip(int32 blipId);\n\tstatic void DrawCoordBlip(int32 blipId);\n\tstatic void DrawLegend(int32, int32, int32);\n};\n"
  },
  {
    "path": "src/core/Range2D.cpp",
    "content": "#include \"common.h\"\n#include \"Range2D.h\"\n#include \"General.h\"\n\nCRange2D::CRange2D(CVector2D _min, CVector2D _max) : min(_min), max(_max) {}\n\nbool\nCRange2D::IsInRange(CVector2D vec)\n{\n\treturn min.x < vec.x && max.x > vec.x && min.y < vec.y && max.y > vec.y;\n}\n\nvoid\nCRange2D::DebugShowRange(float, int)\n{\n}\n\nCVector2D\nCRange2D::GetRandomPointInRange()\n{\n\tint distX = Abs(max.x - min.x);\n\tint distY = Abs(max.y - min.y);\n\n\tfloat outX = CGeneral::GetRandomNumber() % distX + min.x;\n\tfloat outY = CGeneral::GetRandomNumber() % distY + min.y;\n\n\treturn CVector2D(outX, outY);\n}\n"
  },
  {
    "path": "src/core/Range2D.h",
    "content": "#pragma once\n\nclass CRange2D\n{\n\tCVector2D min, max;\npublic:\n\tCRange2D(CVector2D _min, CVector2D _max);\n\tbool IsInRange(CVector2D vec);\n\tvoid DebugShowRange(float, int);\n\tCVector2D GetRandomPointInRange();\n};"
  },
  {
    "path": "src/core/Range3D.cpp",
    "content": "#include \"common.h\"\n#include \"Range3D.h\"\n#include \"General.h\"\n\nCRange3D::CRange3D(CVector _min, CVector _max) : min(_min), max(_max) {}\n\nbool\nCRange3D::IsInRange(CVector vec)\n{\n\treturn min.x < vec.x && max.x > vec.x && min.y < vec.y && max.y > vec.y && min.z < vec.z && max.z > vec.z;\n}\n\nvoid\nCRange3D::DebugShowRange(float, int)\n{\n}\n\nCVector\nCRange3D::GetRandomPointInRange()\n{\n\tint distX = Abs(max.x - min.x);\n\tint distY = Abs(max.y - min.y);\n\tint distZ = Abs(max.z - min.z);\n\n\tfloat outX = CGeneral::GetRandomNumber() % distX + min.x;\n\tfloat outY = CGeneral::GetRandomNumber() % distY + min.y;\n\tfloat outZ = CGeneral::GetRandomNumber() % distZ + min.z;\n\n\treturn CVector(outX, outY, outZ);\n}\n"
  },
  {
    "path": "src/core/Range3D.h",
    "content": "#pragma once\n\nclass CRange3D\n{\n\tCVector min, max;\npublic:\n\tCRange3D(CVector _min, CVector _max);\n\tbool IsInRange(CVector vec);\n\tvoid DebugShowRange(float, int);\n\tCVector GetRandomPointInRange();\n};"
  },
  {
    "path": "src/core/References.cpp",
    "content": "#include \"common.h\"\n\n#include \"World.h\"\n#include \"Vehicle.h\"\n#include \"PlayerPed.h\"\n#include \"Pools.h\"\n#include \"References.h\"\n\nCReference CReferences::aRefs[NUMREFERENCES];\nCReference *CReferences::pEmptyList;\n\nvoid\nCReferences::Init(void)\n{\n\tint i;\n\tpEmptyList = &aRefs[0];\n\tfor(i = 0; i < NUMREFERENCES; i++){\n\t\taRefs[i].pentity = nil;\n\t\taRefs[i].next = &aRefs[i+1];\n\t}\n\taRefs[NUMREFERENCES-1].next = nil;\n}\n\nvoid\nCEntity::RegisterReference(CEntity **pent)\n{\n\tif(IsBuilding())\n\t\treturn;\n\tCReference *ref;\n\t// check if already registered\n\tfor(ref = m_pFirstReference; ref; ref = ref->next)\n\t\tif(ref->pentity == pent)\n\t\t\treturn;\n\t// have to allocate new reference\n\tref = CReferences::pEmptyList;\n\tif(ref){\n\t\tCReferences::pEmptyList = ref->next;\n\n\t\tref->pentity = pent;\n\t\tref->next = m_pFirstReference;\n\t\tm_pFirstReference = ref;\n\t\treturn;\n\t}\n\treturn;\n}\n\n// Clean up the reference from *pent -> 'this'\nvoid\nCEntity::CleanUpOldReference(CEntity **pent)\n{\n\tCReference* ref, ** lastnextp;\n\tlastnextp = &m_pFirstReference;\n\tfor (ref = m_pFirstReference; ref; ref = ref->next) {\n\t\tif (ref->pentity == pent) {\n\t\t\t*lastnextp = ref->next;\n\t\t\tref->next = CReferences::pEmptyList;\n\t\t\tCReferences::pEmptyList = ref;\n\t\t\tbreak;\n\t\t}\n\t\tlastnextp = &ref->next;\n\t}\n}\n\n// Clear all references to this entity\nvoid\nCEntity::ResolveReferences(void)\n{\n\tCReference *ref;\n\t// clear pointers to this entity\n\tfor(ref = m_pFirstReference; ref; ref = ref->next)\n\t\tif(*ref->pentity == this)\n\t\t\t*ref->pentity = nil;\n\t// free list\n\tif(m_pFirstReference){\n\t\tfor(ref = m_pFirstReference; ref->next; ref = ref->next)\n\t\t\t;\n\t\tref->next = CReferences::pEmptyList;\n\t\tCReferences::pEmptyList = m_pFirstReference;\n\t\tm_pFirstReference = nil;\n\t}\n}\n\n// Free all references that no longer point to this entity\nvoid\nCEntity::PruneReferences(void)\n{\n\tCReference *ref, *next, **lastnextp;\n\tlastnextp = &m_pFirstReference;\n\tfor(ref = m_pFirstReference; ref; ref = next){\n\t\tnext = ref->next;\n\t\tif(*ref->pentity == this)\n\t\t\tlastnextp = &ref->next;\n\t\telse{\n\t\t\t*lastnextp = ref->next;\n\t\t\tref->next = CReferences::pEmptyList;\n\t\t\tCReferences::pEmptyList = ref;\n\t\t}\n\t}\n}\n\nvoid\nCReferences::RemoveReferencesToPlayer(void)\n{\n\tif(FindPlayerVehicle())\n\t\tFindPlayerVehicle()->ResolveReferences();\n#ifdef FIX_BUGS\n\tif (FindPlayerPed()) {\n\t\tCPlayerPed* pPlayerPed = FindPlayerPed();\n\t\tFindPlayerPed()->ResolveReferences();\n\t\tCWorld::Players[CWorld::PlayerInFocus].m_pPed = pPlayerPed;\n\t\tpPlayerPed->RegisterReference((CEntity**)&CWorld::Players[CWorld::PlayerInFocus].m_pPed);\n\t}\n#else\n\tif(FindPlayerPed())\n\t\tFindPlayerPed()->ResolveReferences();\n#endif\n}\n\nvoid\nCReferences::PruneAllReferencesInWorld(void)\n{\n\tint i;\n\tCEntity *e;\n\n\ti = CPools::GetPedPool()->GetSize();\n\twhile(--i >= 0){\n\t\te = CPools::GetPedPool()->GetSlot(i);\n\t\tif(e)\n\t\t\te->PruneReferences();\n\t}\n\n\ti = CPools::GetVehiclePool()->GetSize();\n\twhile(--i >= 0){\n\t\te = CPools::GetVehiclePool()->GetSlot(i);\n\t\tif(e)\n\t\t\te->PruneReferences();\n\t}\n\n\ti = CPools::GetObjectPool()->GetSize();\n\twhile(--i >= 0){\n\t\te = CPools::GetObjectPool()->GetSlot(i);\n\t\tif(e)\n\t\t\te->PruneReferences();\n\t}\n}\n"
  },
  {
    "path": "src/core/References.h",
    "content": "#pragma once\n\nclass CEntity;\n\nstruct CReference\n{\n\tCReference *next;\n\tCEntity **pentity;\n};\n\nclass CReferences\n{\npublic:\n\tstatic CReference aRefs[NUMREFERENCES];\n\tstatic CReference *pEmptyList;\n\n\tstatic void Init(void);\n\tstatic void RemoveReferencesToPlayer(void);\n\tstatic void PruneAllReferencesInWorld(void);\n};\n"
  },
  {
    "path": "src/core/Ropes.cpp",
    "content": "#include \"common.h\"\n\n#include \"main.h\"\n#include \"Timer.h\"\n#include \"ModelIndices.h\"\n#include \"Streaming.h\"\n#include \"CopPed.h\"\n#include \"Population.h\"\n#include \"RenderBuffer.h\"\n#include \"Camera.h\"\n#include \"Ropes.h\"\n\nCRope CRopes::aRopes[8];\n\nRwImVertexIndex RopeIndices[64] = {\n\t0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7,\n\t7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15,\n\t15, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23,\n\t23, 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 30, 30, 31,\n\t31, 32\t// unused\n};\n\nvoid\nCRope::Update(void)\n{\n\tint i;\n\tfloat step = Pow(0.85f, CTimer::GetTimeStep());\n\tif(!m_bWasRegistered && CTimer::GetTimeInMilliseconds() > m_updateTimer){\n\t\tm_speed[0].z -= 0.0015f*CTimer::GetTimeStep();\n\t\tm_pos[0] += m_speed[0]*CTimer::GetTimeStep();\n\t}\n\tfor(i = 1; i < ARRAY_SIZE(m_pos); i++){\n\t\tCVector prevPos = m_pos[i];\n\t\tm_pos[i] += m_speed[i]*step*CTimer::GetTimeStep();\n\t\tm_pos[i].z -= 0.05f*CTimer::GetTimeStep();\n\t\tCVector dist = m_pos[i] - m_pos[i-1];\n\t\tm_pos[i] = m_pos[i-1] + (0.625f/dist.Magnitude())*dist;\n\t\tm_speed[i] = (m_pos[i] - prevPos)/CTimer::GetTimeStep();\n\t}\n\tif(!m_bWasRegistered && m_pos[0].z < 0.0f)\n\t\tm_bActive = false;\n\tm_bWasRegistered = false;\n}\n\nvoid\nCRope::Render(void)\n{\n\tint i;\n\tint numVerts = 0;\n\tif(!TheCamera.IsSphereVisible(m_pos[16], 20.0f))\n\t\treturn;\n\n\tfor(i = 0; i < ARRAY_SIZE(m_pos); i++){\n\t\tRwIm3DVertexSetRGBA(&TempBufferRenderVertices[i], 128, 128, 128, 100);\n\t\tRwIm3DVertexSetPos(&TempBufferRenderVertices[i], m_pos[i].x, m_pos[i].y, m_pos[i].z);\n\t}\n\n\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);\n\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);\n\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);\n\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil);\n\n\tif(RwIm3DTransform(TempBufferRenderVertices, ARRAY_SIZE(m_pos), nil, rwIM3D_VERTEXXYZ|rwIM3D_VERTEXRGBA)){\n#ifdef FIX_BUGS\n\t\tRwIm3DRenderIndexedPrimitive(rwPRIMTYPELINELIST, RopeIndices, 2*(ARRAY_SIZE(m_pos)-1));\n#else\n\t\tRwIm3DRenderIndexedPrimitive(rwPRIMTYPEPOLYLINE, RopeIndices, 2*(ARRAY_SIZE(m_pos)-1));\n#endif\n\t\tRwIm3DEnd();\n\t}\n}\n\n\nvoid\nCRopes::Init(void)\n{\n\tint i;\n\tfor(i = 0; i < ARRAY_SIZE(aRopes); i++)\n\t\taRopes[i].m_bActive = false;\n}\n\nvoid\nCRopes::Update(void)\n{\n\tint i;\n\tfor(i = 0; i < ARRAY_SIZE(aRopes); i++)\n\t\tif(aRopes[i].m_bActive)\n\t\t\taRopes[i].Update();\n}\n\nvoid\nCRopes::Render(void)\n{\n\tint i;\n\tPUSH_RENDERGROUP(\"CRopes::Render\");\n\tfor(i = 0; i < ARRAY_SIZE(aRopes); i++)\n\t\tif(aRopes[i].m_bActive)\n\t\t\taRopes[i].Render();\n\tPOP_RENDERGROUP();\n}\n\nbool\nCRopes::RegisterRope(uintptr id, CVector pos, bool setUpdateTimer)\n{\n\tint i, j;\n\tfor(i = 0; i < ARRAY_SIZE(aRopes); i++){\n\t\tif(aRopes[i].m_bActive && aRopes[i].m_id == id){\n\t\t\taRopes[i].m_pos[0] = pos;\n\t\t\taRopes[i].m_speed[0] = CVector(0.0f, 0.0f, 0.0f);\n\t\t\taRopes[i].m_bWasRegistered = true;\n\t\t\treturn true;\n\t\t}\n\t}\n\tfor(i = 0; i < ARRAY_SIZE(aRopes); i++)\n\t\tif(!aRopes[i].m_bActive){\n\t\t\taRopes[i].m_id = id;\n\t\t\taRopes[i].m_pos[0] = pos;\n\t\t\taRopes[i].m_speed[0] = CVector(0.0f, 0.0f, 0.0f);\n\t\t\taRopes[i].m_unk = false;\n\t\t\taRopes[i].m_bWasRegistered = true;\n\t\t\taRopes[i].m_updateTimer = setUpdateTimer ? CTimer::GetTimeInMilliseconds() + 20000 : 0;\n\t\t\tfor(j = 1; j < ARRAY_SIZE(aRopes[0].m_pos); j++){\n\t\t\t\tif(j & 1)\n\t\t\t\t\taRopes[i].m_pos[j] = aRopes[i].m_pos[j-1] + CVector(0.0f, 0.0f, 0.625f);\n\t\t\t\telse\n\t\t\t\t\taRopes[i].m_pos[j] = aRopes[i].m_pos[j-1] - CVector(0.0f, 0.0f, 0.625f);\n\t\t\t\taRopes[i].m_speed[j] = CVector(0.0f, 0.0f, 0.0f);\n\t\t\t}\n\t\t\taRopes[i].m_bActive = true;\n\t\t\treturn true;\n\t\t}\n\treturn false;\n}\n\nvoid\nCRopes::SetSpeedOfTopNode(uintptr id, CVector speed)\n{\n\tint i;\n\tfor(i = 0; i < ARRAY_SIZE(aRopes); i++)\n\t\tif(aRopes[i].m_bActive && aRopes[i].m_id == id){\n\t\t\taRopes[i].m_speed[0] = speed;\n\t\t\treturn;\n\t\t}\n}\n\nbool\nCRopes::FindCoorsAlongRope(uintptr id, float t, CVector *coors)\n{\n\tint i, j;\n\tfloat f;\n\tfor(i = 0; i < ARRAY_SIZE(aRopes); i++)\n\t\tif(aRopes[i].m_bActive && aRopes[i].m_id == id){\n\t\t\tt = (ARRAY_SIZE(aRopes[0].m_pos)-1)*clamp(t, 0.0f, 0.999f);\n\t\t\tj = t;\n\t\t\tf = t - j; \n\t\t\t*coors = (1.0f-f)*aRopes[i].m_pos[j] + f*aRopes[i].m_pos[j+1];\n\t\t\treturn true;\n\t\t}\n\treturn false;\n}\n\nbool\nCRopes::CreateRopeWithSwatComingDown(CVector pos)\n{\n\tstatic uint32 ropeId = 0;\n\n\tif(!CStreaming::HasModelLoaded(MI_SWAT) || !RegisterRope(ropeId+100, pos, true))\n\t\treturn false;\n\tCCopPed *swat = (CCopPed*)CPopulation::AddPed(PEDTYPE_COP, COP_HELI_SWAT, pos);\n\tswat->bUsesCollision = false;\n\tswat->m_pRopeEntity = (CEntity*)1;\n\tswat->m_nRopeID = 100 + ropeId;\n\tCAnimManager::BlendAnimation(swat->GetClump(), ASSOCGRP_STD, ANIM_STD_ABSEIL, 4.0f);\n\tropeId++;\n\treturn true;\n}\n"
  },
  {
    "path": "src/core/Ropes.h",
    "content": "#pragma once\n\nclass CRope\n{\npublic:\n\tbool m_bActive;\n\tbool m_bWasRegistered;\n\tbool m_unk;\n\tuintptr m_id;\n\tuint32 m_updateTimer;\n\tCVector m_pos[32];\n\tCVector m_speed[32];\n\n\tvoid Update(void);\n\tvoid Render(void);\n};\n\nclass CRopes\n{\n\tstatic CRope aRopes[8];\n\npublic:\n\n\tstatic void Init(void);\n\tstatic void Update(void);\n\tstatic void Render(void);\n\tstatic bool RegisterRope(uintptr id, CVector pos, bool setUpdateTimer);\n\tstatic void SetSpeedOfTopNode(uintptr id, CVector speed);\n\tstatic bool FindCoorsAlongRope(uintptr id, float t, CVector *coors);\n\tstatic bool CreateRopeWithSwatComingDown(CVector pos);\n};\n"
  },
  {
    "path": "src/core/Stats.cpp",
    "content": "#include \"common.h\"\n\n#include \"Stats.h\"\n#include \"Text.h\"\n#include \"World.h\"\n#include \"Pad.h\"\n#include \"DMAudio.h\"\n#include \"main.h\"\n#include \"Font.h\"\n#include \"Frontend.h\"\n#include \"audio_enums.h\"\n\n#include <climits>\n\n#ifdef USE_PRECISE_MEASUREMENT_CONVERTION\n#define MILES_IN_METER 0.000621371192f\n#define FEET_IN_METER 3.28084f\n#else\n#define MILES_IN_METER (1 / 1670.f)\n#define FEET_IN_METER 3.33f\n#endif\n\nint32 CStats::SeagullsKilled;\nint32 CStats::BoatsExploded;\nint32 CStats::WantedStarsAttained;\nint32 CStats::WantedStarsEvaded;\nint32 CStats::DaysPassed;\nint32 CStats::HeadsPopped;\nint32 CStats::CommercialPassed;\nint32 CStats::IndustrialPassed;\nint32 CStats::SuburbanPassed;\nint32 CStats::NumberKillFrenziesPassed;\nint32 CStats::PeopleKilledByOthers;\nint32 CStats::HelisDestroyed;\nint32 CStats::PedsKilledOfThisType[NUM_PEDTYPES];\nint32 CStats::TimesDied;\nint32 CStats::TimesArrested;\nint32 CStats::KillsSinceLastCheckpoint;\nfloat CStats::DistanceTravelledByCar;\nfloat CStats::DistanceTravelledByHelicoptor;\nfloat CStats::DistanceTravelledByBike;\nfloat CStats::DistanceTravelledByBoat;\nfloat CStats::DistanceTravelledByPlane;\nfloat CStats::DistanceTravelledByGolfCart;\nfloat CStats::DistanceTravelledOnFoot;\nint32 CStats::FlightTime;\nint32 CStats::TimesDrowned;\nint32 CStats::PhotosTaken;\nfloat CStats::LoanSharks;\nfloat CStats::StoresKnockedOff;\nfloat CStats::MovieStunts;\nfloat CStats::Assassinations;\nfloat CStats::PizzasDelivered;\nfloat CStats::GarbagePickups;\nfloat CStats::IceCreamSold;\nfloat CStats::TopShootingRangeScore;\nfloat CStats::ShootingRank;\nfloat CStats::ProgressMade;\nfloat CStats::TotalProgressInGame;\nint32 CStats::CarsExploded;\nint32 CStats::PeopleKilledByPlayer;\nfloat CStats::MaximumJumpDistance;\nfloat CStats::MaximumJumpHeight;\nint32 CStats::MaximumJumpFlips;\nint32 CStats::MaximumJumpSpins;\nint32 CStats::BestStuntJump;\nint32 CStats::NumberOfUniqueJumpsFound;\nint32 CStats::TotalNumberOfUniqueJumps;\nint32 CStats::PassengersDroppedOffWithTaxi;\nint32 CStats::MoneyMadeWithTaxi;\nint32 CStats::MissionsGiven;\nint32 CStats::MissionsPassed;\nchar CStats::LastMissionPassedName[8];\nint32 CStats::TotalLegitimateKills;\nint32 CStats::LivesSavedWithAmbulance;\nint32 CStats::CriminalsCaught;\nint32 CStats::HighestLevelAmbulanceMission;\nint32 CStats::HighestLevelVigilanteMission;\nint32 CStats::HighestLevelFireMission;\nint32 CStats::FiresExtinguished;\nint32 CStats::TotalNumberKillFrenzies;\nint32 CStats::TotalNumberMissions;\nint32 CStats::RoundsFiredByPlayer;\nint32 CStats::KgsOfExplosivesUsed;\nint32 CStats::BulletsThatHit;\nint32 CStats::BestTimeBombDefusal;\nint32 CStats::FastestTimes[CStats::TOTAL_FASTEST_TIMES];\nint32 CStats::HighestScores[CStats::TOTAL_HIGHEST_SCORES];\nint32 CStats::BestPositions[CStats::TOTAL_BEST_POSITIONS];\nbool CStats::PropertyOwned[CStats::TOTAL_PROPERTIES];\nint32 CStats::NumPropertyOwned;\nint32 CStats::PropertyDestroyed;\nfloat CStats::HighestChaseValue;\nint32 CStats::CheatedCount;\nint32 CStats::ShowChaseStatOnScreen;\nint32 CStats::PamphletMissionPassed;\nbool CStats::abSonyCDs[1];\nint32 CStats::BloodRingKills;\nint32 CStats::BloodRingTime;\nfloat CStats::FavoriteRadioStationList[NUM_RADIOS];\n\nint32 CStats::Sprayings;\nfloat CStats::AutoPaintingBudget;\nint32 CStats::NoMoreHurricanes;\nfloat CStats::FashionBudget;\nfloat CStats::PropertyBudget;\nfloat CStats::WeaponBudget;\nint32 CStats::SafeHouseVisits;\nint32 CStats::TyresPopped;\n\nint32 CStats::LongestWheelie;\nint32 CStats::LongestStoppie;\nint32 CStats::Longest2Wheel;\nfloat CStats::LongestWheelieDist;\nfloat CStats::LongestStoppieDist;\nfloat CStats::Longest2WheelDist;\n\nvoid CStats::Init()\n{\n\tPeopleKilledByOthers = 0;\n\tPeopleKilledByPlayer = 0;\n\tCarsExploded = 0;\n\tBoatsExploded = 0;\n\tRoundsFiredByPlayer = 0;\n\tfor (int i = 0; i < NUM_PEDTYPES; i++)\n\t\tPedsKilledOfThisType[i] = 0;\n\tHelisDestroyed = 0;\n\tProgressMade = 0.0f;\n\tKgsOfExplosivesUsed = 0;\n\tBulletsThatHit = 0;\n\tTyresPopped = 0;\n\tHeadsPopped = 0;\n\tWantedStarsAttained = 0;\n\tWantedStarsEvaded = 0;\n\tTimesArrested = 0;\n\tTimesDied = 0;\n\tDaysPassed = 0;\n\tSafeHouseVisits = 0;\n\tSprayings = 0;\n\tMaximumJumpDistance = 0;\n\tMaximumJumpHeight = 0;\n\tMaximumJumpFlips = 0;\n\tMaximumJumpSpins = 0;\n\tBestStuntJump = 0;\n\tNumberOfUniqueJumpsFound = 0;\n\tTotalNumberOfUniqueJumps = 0;\n\tMissionsGiven = 0;\n\tMissionsPassed = 0;\n\tPassengersDroppedOffWithTaxi = 0;\n\tMoneyMadeWithTaxi = 0;\n\tDistanceTravelledOnFoot = 0;\n\tDistanceTravelledByCar = 0;\n\tDistanceTravelledByBike = 0;\n\tDistanceTravelledByBoat = 0;\n\tDistanceTravelledByGolfCart = 0;\n\tDistanceTravelledByHelicoptor = 0;\n#ifdef FIX_BUGS\n\tDistanceTravelledByPlane = 0;\n#endif\n\tLivesSavedWithAmbulance = 0;\n\tCriminalsCaught = 0;\n\tHighestLevelVigilanteMission = 0;\n\tHighestLevelAmbulanceMission = 0;\n\tHighestLevelFireMission = 0;\n\tFiresExtinguished = 0;\n\tPhotosTaken = 0;\n\tNumberKillFrenziesPassed = 0;\n\tTotalNumberKillFrenzies = 0;\n\tTotalNumberMissions = 0;\n\tFlightTime = 0;\n\tTimesDrowned = 0;\n\tSeagullsKilled = 0;\n\tWeaponBudget = 0.0f;\n\tFashionBudget = 0.0f;\n\tLoanSharks = 0.0f;\n\tStoresKnockedOff = 0.0f;\n\tMovieStunts = 0.0f;\n\tAssassinations = 0.0f;\n\tPizzasDelivered = 0.0f;\n\tGarbagePickups = 0.0f;\n\tIceCreamSold = 0.0f;\n\tTopShootingRangeScore = 0.0f;\n\tShootingRank = 0.0f;\n\tLongestWheelie = 0;\n\tLongestStoppie = 0;\n\tLongest2Wheel = 0;\n\tLongestWheelieDist = 0.0f;\n\tLongestStoppieDist = 0.0f;\n\tLongest2WheelDist = 0.0f;\n\tPropertyBudget = 0.0f;\n\tAutoPaintingBudget = 0.0f;\n\tPropertyDestroyed = 0;\n\tHighestChaseValue = 0.0f;\n\tCheatedCount = 0;\n\n\tfor (int i = 0; i < TOTAL_FASTEST_TIMES; i++)\n\t\tFastestTimes[i] = 0;\n\tfor (int i = 0; i < TOTAL_HIGHEST_SCORES; i++)\n\t\tHighestScores[i] = 0;\n\tfor (int i = 0; i < TOTAL_BEST_POSITIONS; i++)\n\t\tBestPositions[i] = INT_MAX;\n\n\tKillsSinceLastCheckpoint = 0;\n\tTotalLegitimateKills = 0;\n\n\tfor (int i = 0; i < ARRAY_SIZE(LastMissionPassedName); i++)\n\t\tLastMissionPassedName[i] = 0;\n\n\tIndustrialPassed = 0;\n\tCommercialPassed = 0;\n\tSuburbanPassed = 0;\n\tPamphletMissionPassed = 0;\n\tNoMoreHurricanes = 0;\n\tShowChaseStatOnScreen = 0;\n\tfor (int i = 0; i < ARRAY_SIZE(abSonyCDs); i++)\n\t\tabSonyCDs[i] = 0;\n\tPopulateFavoriteRadioStationList();\n\n\tNumPropertyOwned = 0;\n\tfor (int i = 0; i < TOTAL_PROPERTIES; i++)\n\t\tPropertyOwned[i] = false;\n\n\tBloodRingKills = 0;\n\tBloodRingTime = 0;\n}\n\nvoid CStats::RegisterFastestTime(int32 index, int32 time)\n{\n\tassert(index >= 0 && index < TOTAL_FASTEST_TIMES);\n\tif (FastestTimes[index] == 0)\n\t\tFastestTimes[index] = time;\n\telse\n\t\tFastestTimes[index] = Min(FastestTimes[index], time);\n}\n\nvoid CStats::RegisterHighestScore(int32 index, int32 score)\n{\n\tassert(index >= 0 && index < TOTAL_HIGHEST_SCORES);\n\tHighestScores[index] = Max(HighestScores[index], score);\n}\n\nvoid CStats::RegisterBestPosition(int32 index, int32 position)\n{\n\tassert(index >= 0 && index < TOTAL_BEST_POSITIONS);\n\tBestPositions[index] = Min(BestPositions[index], position);\n}\n\nvoid CStats::AnotherLifeSavedWithAmbulance()\n{\n\t++LivesSavedWithAmbulance;\n}\n\nvoid CStats::AnotherCriminalCaught()\n{\n\t++CriminalsCaught;\n}\n\nvoid CStats::RegisterLevelAmbulanceMission(int32 level)\n{\n\tHighestLevelAmbulanceMission = Max(HighestLevelAmbulanceMission, level);\n}\n\nvoid CStats::RegisterLevelVigilanteMission(int32 level)\n{\n\tHighestLevelVigilanteMission = Max(HighestLevelVigilanteMission, level);\n}\n\nvoid CStats::RegisterLevelFireMission(int32 level)\n{\n\tHighestLevelFireMission = Max(HighestLevelFireMission, level);\n}\n\nvoid CStats::AnotherFireExtinguished()\n{\n\t++FiresExtinguished;\n}\n\nvoid CStats::AnotherKillFrenzyPassed()\n{\n\t++NumberKillFrenziesPassed;\n}\n\nvoid CStats::SetTotalNumberKillFrenzies(int32 total)\n{\n\tTotalNumberKillFrenzies = total;\n}\n\nvoid CStats::SetTotalNumberMissions(int32 total)\n{\n\tTotalNumberMissions = total;\n}\n\nwchar *CStats::FindCriminalRatingString()\n{\n\tint rating = FindCriminalRatingNumber();\n\n\tif (rating < 0) {\n\t\tif (rating > -500) return TheText.Get(\"RATNG53\");\n\t\tif (rating > -2000) return TheText.Get(\"RATNG54\");\n\t\tif (rating > -4000) return TheText.Get(\"RATNG55\");\n\t\tif (rating > -6000) return TheText.Get(\"RATNG56\");\n\t\treturn TheText.Get(\"RATNG57\");\n\t}\n\tif (rating < 20) return TheText.Get(\"RATNG1\");\n\tif (rating < 50) return TheText.Get(\"RATNG2\");\n\tif (rating < 75) return TheText.Get(\"RATNG3\");\n\tif (rating < 100) return TheText.Get(\"RATNG4\");\n\tif (rating < 120) return TheText.Get(\"RATNG5\");\n\tif (rating < 150) return TheText.Get(\"RATNG6\");\n\tif (rating < 200) return TheText.Get(\"RATNG7\");\n\tif (rating < 240) return TheText.Get(\"RATNG8\");\n\tif (rating < 270) return TheText.Get(\"RATNG9\");\n\tif (rating < 300) return TheText.Get(\"RATNG10\");\n\tif (rating < 335) return TheText.Get(\"RATNG11\");\n\tif (rating < 370) return TheText.Get(\"RATNG12\");\n\tif (rating < 400) return TheText.Get(\"RATNG13\");\n\tif (rating < 450) return TheText.Get(\"RATNG14\");\n\tif (rating < 500) return TheText.Get(\"RATNG15\");\n\tif (rating < 550) return TheText.Get(\"RATNG16\");\n\tif (rating < 600) return TheText.Get(\"RATNG17\");\n\tif (rating < 610) return TheText.Get(\"RATNG18\");\n\tif (rating < 650) return TheText.Get(\"RATNG19\");\n\tif (rating < 700) return TheText.Get(\"RATNG20\");\n\tif (rating < 850) return TheText.Get(\"RATNG21\");\n\tif (rating < 1000) return TheText.Get(\"RATNG22\");\n\tif (rating < 1005) return TheText.Get(\"RATNG23\");\n\tif (rating < 1150) return TheText.Get(\"RATNG24\");\n\tif (rating < 1300) return TheText.Get(TimesArrested > 0 ? \"RATNG25\" : \"RATNG24\");\n\tif (rating < 1500) return TheText.Get(\"RATNG26\");\n\tif (rating < 1700) return TheText.Get(\"RATNG27\");\n\tif (rating < 2000) return TheText.Get(\"RATNG28\");\n\tif (rating < 2100) return TheText.Get(\"RATNG29\");\n\tif (rating < 2300) return TheText.Get(\"RATNG30\");\n\tif (rating < 2500) return TheText.Get(\"RATNG31\");\n\tif (rating < 2750) return TheText.Get(\"RATNG32\");\n\tif (rating < 3000) return TheText.Get(\"RATNG33\");\n\tif (rating < 3500) return TheText.Get(\"RATNG34\");\n\tif (rating < 4000) return TheText.Get(\"RATNG35\");\n\tif (rating < 5000) return TheText.Get(\"RATNG36\");\n\tif (rating < 7500) return TheText.Get(\"RATNG37\");\n\tif (rating < 10000) return TheText.Get(\"RATNG38\");\n\tif (rating < 20000) return TheText.Get(\"RATNG39\");\n\tif (rating < 30000) return TheText.Get(\"RATNG40\");\n\tif (rating < 40000) return TheText.Get(\"RATNG41\");\n\tif (rating < 50000) return TheText.Get(\"RATNG42\");\n\tif (rating < 65000) return TheText.Get(\"RATNG43\");\n\tif (rating < 80000) return TheText.Get(\"RATNG44\");\n\tif (rating < 100000) return TheText.Get(\"RATNG45\");\n\tif (rating < 150000) return TheText.Get(\"RATNG46\");\n\tif (rating < 200000) return TheText.Get(\"RATNG47\");\n\tif (rating < 300000) return TheText.Get(\"RATNG48\");\n\tif (rating < 375000) return TheText.Get(\"RATNG49\");\n\tif (rating < 500000) return TheText.Get(FlightTime / 60000 / 60 > 10 ? \"RATNG50\" : \"RATNG49\");\n\tif (rating < 1000000) return TheText.Get(\"RATNG51\");\n\treturn TheText.Get(CWorld::Players[CWorld::PlayerInFocus].m_nVisibleMoney > 10000000 ? \"RATNG52\" : \"RATNG51\");\n}\n\nwchar *CStats::FindChaseString(float fMediaLevel) {\n\tif (fMediaLevel < 20.0f) return TheText.Get(\"CHASE1\");\n\tif (fMediaLevel < 50.0f) return TheText.Get(\"CHASE2\");\n\tif (fMediaLevel < 75.0f) return TheText.Get(\"CHASE3\");\n\tif (fMediaLevel < 100.0f) return TheText.Get(\"CHASE4\");\n\tif (fMediaLevel < 150.0f) return TheText.Get(\"CHASE5\");\n\tif (fMediaLevel < 200.0f) return TheText.Get(\"CHASE6\");\n\tif (fMediaLevel < 250.0f) return TheText.Get(\"CHASE7\");\n\tif (fMediaLevel < 300.0f) return TheText.Get(\"CHASE8\");\n\tif (fMediaLevel < 350.0f) return TheText.Get(\"CHASE9\");\n\tif (fMediaLevel < 400.0f) return TheText.Get(\"CHASE10\");\n\tif (fMediaLevel < 500.0f) return TheText.Get(\"CHASE11\");\n\tif (fMediaLevel < 600.0f) return TheText.Get(\"CHASE12\");\n\tif (fMediaLevel < 700.0f) return TheText.Get(\"CHASE13\");\n\tif (fMediaLevel < 800.0f) return TheText.Get(\"CHASE14\");\n\tif (fMediaLevel < 900.0f) return TheText.Get(\"CHASE15\");\n\tif (fMediaLevel < 1000.0f) return TheText.Get(\"CHASE16\");\n\tif (fMediaLevel < 1200.0f) return TheText.Get(\"CHASE17\");\n\tif (fMediaLevel < 1400.0f) return TheText.Get(\"CHASE18\");\n\tif (fMediaLevel < 1600.0f) return TheText.Get(\"CHASE19\");\n\tif (fMediaLevel < 1800.0f) return TheText.Get(\"CHASE20\");\n\treturn TheText.Get(\"CHASE21\");\n}\n\nint32 CStats::FindCriminalRatingNumber()\n{\n\tint32 rating;\n\n\trating = FiresExtinguished + 10 * HighestLevelFireMission + 10 * HighestLevelAmbulanceMission\n\t\t+ CriminalsCaught + LivesSavedWithAmbulance\n\t\t+ 30 * HelisDestroyed + TotalLegitimateKills - 3 * TimesArrested - 3 * TimesDied\n\t\t+ CWorld::Players[CWorld::PlayerInFocus].m_nMoney / 5000;\n\tif (CPad::bHasPlayerCheated || CheatedCount > 0) {\n\t\trating -= CheatedCount;\n\t\tif (rating <= -10000)\n\t\t\trating = -10000;\n\n\t} else if (rating <= 0) {\n\t\trating = 0;\n\t}\n\n\tif (RoundsFiredByPlayer > 100)\n\t\trating += (float)BulletsThatHit / (float)RoundsFiredByPlayer * 500.0f;\n\tif (TotalProgressInGame)\n\t\trating += ProgressMade / TotalProgressInGame * 1000.0f;\n\treturn rating;\n}\n\nfloat CStats::GetPercentageProgress()\n{\n\tfloat percentCompleted = (TotalProgressInGame == 0.f ? 0.f :\n\t\t100.0f * ProgressMade / (CGame::nastyGame ? TotalProgressInGame : TotalProgressInGame - 1.0f));\n\n\treturn Min(percentCompleted, 100.0f);\n}\n\nvoid CStats::MoneySpentOnWeapons(int32 money)\n{\n\tWeaponBudget += money;\n}\n\nvoid CStats::MoneySpentOnProperty(int32 money)\n{\n\tPropertyBudget += money;\n}\n\nvoid CStats::MoneySpentOnAutoPainting(int32 money)\n{\n\tAutoPaintingBudget += money;\n}\n\nvoid CStats::MoneySpentOnFashion(int32 money)\n{\n\tFashionBudget += money;\n}\n\nvoid CStats::NumOfVisitsFromLoanSharks(int32 num)\n{\n\tLoanSharks += num;\n}\n\nvoid CStats::NumOfStoresKnockedOff(int32 num)\n{\n\tStoresKnockedOff += num;\n}\n\nvoid CStats::NumOfMovieStunts(int32 num)\n{\n\tMovieStunts += num;\n}\n\nvoid CStats::NumOfAssassinations(int32 num)\n{\n\tAssassinations += num;\n}\n\nvoid CStats::NumOfPizzasDelivered(int32 num)\n{\n\tPizzasDelivered += num;\n}\n\nvoid CStats::NumOfGarbagePickups(int32 num)\n{\n\tGarbagePickups += num;\n}\n\nvoid CStats::NumOfIceCreamSold(int32 num)\n{\n\tIceCreamSold += num;\n}\n\nvoid CStats::AddNumBloodRingKills(int32 num)\n{\n\tBloodRingKills += num;\n}\n\nvoid CStats::LongestTimeInBloodRing(int32 time)\n{\n\tif (BloodRingTime < time)\n\t\tBloodRingTime = time;\n}\n\nvoid CStats::AddPropertyAsOwned(int32 id)\n{\n\tif (!PropertyOwned[id]) {\n\t\tPropertyOwned[id] = true;\n\t\t++NumPropertyOwned;\n\t}\n}\n\nfloat CStats::GetFavoriteRadioStationList(int32 station)\n{\n\treturn FavoriteRadioStationList[station];\n}\n\nvoid CStats::SaveStats(uint8 *buf, uint32 *size)\n{\n\tCheckPointReachedSuccessfully();\n\tuint8 *buf_start = buf;\n\t*size = sizeof(PeopleKilledByPlayer) +\n\t\tsizeof(PeopleKilledByOthers) +\n\t\tsizeof(CarsExploded) +\n\t\tsizeof(BoatsExploded) +\n\t\tsizeof(TyresPopped) +\n\t\tsizeof(RoundsFiredByPlayer) +\n\t\tsizeof(PedsKilledOfThisType) +\n\t\tsizeof(HelisDestroyed) +\n\t\tsizeof(ProgressMade) +\n\t\tsizeof(TotalProgressInGame) +\n\t\tsizeof(KgsOfExplosivesUsed) +\n\t\tsizeof(BulletsThatHit) +\n\t\tsizeof(HeadsPopped) +\n\t\tsizeof(WantedStarsAttained) +\n\t\tsizeof(WantedStarsEvaded) +\n\t\tsizeof(TimesArrested) +\n\t\tsizeof(TimesDied) +\n\t\tsizeof(DaysPassed) +\n\t\tsizeof(SafeHouseVisits) +\n\t\tsizeof(Sprayings) +\n\t\tsizeof(MaximumJumpDistance) +\n\t\tsizeof(MaximumJumpHeight) +\n\t\tsizeof(MaximumJumpFlips) +\n\t\tsizeof(MaximumJumpSpins) +\n\t\tsizeof(BestStuntJump) +\n\t\tsizeof(NumberOfUniqueJumpsFound) +\n\t\tsizeof(TotalNumberOfUniqueJumps) +\n\t\tsizeof(MissionsGiven) +\n\t\tsizeof(PassengersDroppedOffWithTaxi) +\n\t\tsizeof(MoneyMadeWithTaxi) +\n\t\tsizeof(IndustrialPassed) +\n\t\tsizeof(CommercialPassed) +\n\t\tsizeof(SuburbanPassed) +\n\t\tsizeof(PamphletMissionPassed) +\n\t\tsizeof(NoMoreHurricanes) +\n\t\tsizeof(DistanceTravelledOnFoot) +\n\t\tsizeof(DistanceTravelledByCar) +\n\t\tsizeof(DistanceTravelledByBike) +\n\t\tsizeof(DistanceTravelledByBoat) +\n\t\tsizeof(DistanceTravelledByGolfCart) +\n\t\tsizeof(DistanceTravelledByHelicoptor) +\n\t\tsizeof(DistanceTravelledByPlane) +\n\t\tsizeof(LivesSavedWithAmbulance) +\n\t\tsizeof(CriminalsCaught) +\n\t\tsizeof(FiresExtinguished) +\n\t\tsizeof(HighestLevelVigilanteMission) +\n\t\tsizeof(HighestLevelAmbulanceMission) +\n\t\tsizeof(HighestLevelFireMission) +\n\t\tsizeof(PhotosTaken) +\n\t\tsizeof(NumberKillFrenziesPassed) +\n\t\tsizeof(TotalNumberKillFrenzies) +\n\t\tsizeof(TotalNumberMissions) +\n\t\tsizeof(FlightTime) +\n\t\tsizeof(TimesDrowned) +\n\t\tsizeof(SeagullsKilled) +\n\t\tsizeof(WeaponBudget) +\n\t\tsizeof(FashionBudget) +\n\t\tsizeof(LoanSharks) +\n\t\tsizeof(StoresKnockedOff) +\n\t\tsizeof(MovieStunts) +\n\t\tsizeof(Assassinations) +\n\t\tsizeof(PizzasDelivered) +\n\t\tsizeof(GarbagePickups) +\n\t\tsizeof(IceCreamSold) +\n\t\tsizeof(TopShootingRangeScore) +\n\t\tsizeof(ShootingRank) +\n\t\tsizeof(LongestWheelie) +\n\t\tsizeof(LongestStoppie) +\n\t\tsizeof(Longest2Wheel) +\n\t\tsizeof(LongestWheelieDist) +\n\t\tsizeof(LongestStoppieDist) +\n\t\tsizeof(Longest2WheelDist) +\n\t\tsizeof(PropertyBudget) +\n\t\tsizeof(AutoPaintingBudget) +\n\t\tsizeof(PropertyDestroyed) +\n\t\tsizeof(NumPropertyOwned) +\n\t\tsizeof(BloodRingKills) +\n\t\tsizeof(BloodRingTime) +\n\t\tsizeof(PropertyOwned) +\n\t\tsizeof(HighestChaseValue) +\n\t\tsizeof(FastestTimes) +\n\t\tsizeof(HighestScores) +\n\t\tsizeof(BestPositions) +\n\t\tsizeof(KillsSinceLastCheckpoint) +\n\t\tsizeof(TotalLegitimateKills) +\n\t\tsizeof(LastMissionPassedName) +\n\t\tsizeof(CheatedCount) +\n\t\tsizeof(FavoriteRadioStationList);\n\n#define CopyToBuf(buf, data) memcpy(buf, &data, sizeof(data)); buf += sizeof(data);\n\tCopyToBuf(buf, PeopleKilledByPlayer);\n\tCopyToBuf(buf, PeopleKilledByOthers);\n\tCopyToBuf(buf, CarsExploded);\n\tCopyToBuf(buf, BoatsExploded);\n\tCopyToBuf(buf, TyresPopped);\n\tCopyToBuf(buf, RoundsFiredByPlayer);\n\tCopyToBuf(buf, PedsKilledOfThisType);\n\tCopyToBuf(buf, HelisDestroyed);\n\tCopyToBuf(buf, ProgressMade);\n\tCopyToBuf(buf, TotalProgressInGame);\n\tCopyToBuf(buf, KgsOfExplosivesUsed);\n\tCopyToBuf(buf, BulletsThatHit);\n\tCopyToBuf(buf, HeadsPopped);\n\tCopyToBuf(buf, WantedStarsAttained);\n\tCopyToBuf(buf, WantedStarsEvaded);\n\tCopyToBuf(buf, TimesArrested);\n\tCopyToBuf(buf, TimesDied);\n\tCopyToBuf(buf, DaysPassed);\n\tCopyToBuf(buf, SafeHouseVisits);\n\tCopyToBuf(buf, Sprayings);\n\tCopyToBuf(buf, MaximumJumpDistance);\n\tCopyToBuf(buf, MaximumJumpHeight);\n\tCopyToBuf(buf, MaximumJumpFlips);\n\tCopyToBuf(buf, MaximumJumpSpins);\n\tCopyToBuf(buf, BestStuntJump);\n\tCopyToBuf(buf, NumberOfUniqueJumpsFound);\n\tCopyToBuf(buf, TotalNumberOfUniqueJumps);\n\tCopyToBuf(buf, MissionsGiven);\n\tCopyToBuf(buf, PassengersDroppedOffWithTaxi);\n\tCopyToBuf(buf, MoneyMadeWithTaxi);\n\tCopyToBuf(buf, IndustrialPassed);\n\tCopyToBuf(buf, CommercialPassed);\n\tCopyToBuf(buf, SuburbanPassed);\n\tCopyToBuf(buf, PamphletMissionPassed);\n\tCopyToBuf(buf, NoMoreHurricanes);\n\tCopyToBuf(buf, DistanceTravelledOnFoot);\n\tCopyToBuf(buf, DistanceTravelledByCar);\n\tCopyToBuf(buf, DistanceTravelledByBike);\n\tCopyToBuf(buf, DistanceTravelledByBoat);\n\tCopyToBuf(buf, DistanceTravelledByGolfCart);\n\tCopyToBuf(buf, DistanceTravelledByHelicoptor);\n\tCopyToBuf(buf, DistanceTravelledByPlane);\n\tCopyToBuf(buf, LivesSavedWithAmbulance);\n\tCopyToBuf(buf, CriminalsCaught);\n\tCopyToBuf(buf, FiresExtinguished);\n\tCopyToBuf(buf, HighestLevelVigilanteMission);\n\tCopyToBuf(buf, HighestLevelAmbulanceMission);\n\tCopyToBuf(buf, HighestLevelFireMission);\n\tCopyToBuf(buf, PhotosTaken);\n\tCopyToBuf(buf, NumberKillFrenziesPassed);\n\tCopyToBuf(buf, TotalNumberKillFrenzies);\n\tCopyToBuf(buf, TotalNumberMissions);\n\tCopyToBuf(buf, FlightTime);\n\tCopyToBuf(buf, TimesDrowned);\n\tCopyToBuf(buf, SeagullsKilled);\n\tCopyToBuf(buf, WeaponBudget);\n\tCopyToBuf(buf, FashionBudget);\n\tCopyToBuf(buf, LoanSharks);\n\tCopyToBuf(buf, StoresKnockedOff);\n\tCopyToBuf(buf, MovieStunts);\n\tCopyToBuf(buf, Assassinations);\n\tCopyToBuf(buf, PizzasDelivered);\n\tCopyToBuf(buf, GarbagePickups);\n\tCopyToBuf(buf, IceCreamSold);\n\tCopyToBuf(buf, TopShootingRangeScore);\n\tCopyToBuf(buf, ShootingRank);\n\tCopyToBuf(buf, LongestWheelie);\n\tCopyToBuf(buf, LongestStoppie);\n\tCopyToBuf(buf, Longest2Wheel);\n\tCopyToBuf(buf, LongestWheelieDist);\n\tCopyToBuf(buf, LongestStoppieDist);\n\tCopyToBuf(buf, Longest2WheelDist);\n\tCopyToBuf(buf, PropertyBudget);\n\tCopyToBuf(buf, AutoPaintingBudget);\n\tCopyToBuf(buf, PropertyDestroyed);\n\tCopyToBuf(buf, NumPropertyOwned);\n\tCopyToBuf(buf, BloodRingKills);\n\tCopyToBuf(buf, BloodRingTime);\n\tCopyToBuf(buf, PropertyOwned);\n\tCopyToBuf(buf, HighestChaseValue);\n\tCopyToBuf(buf, FastestTimes);\n\tCopyToBuf(buf, HighestScores);\n\tCopyToBuf(buf, BestPositions);\n\tCopyToBuf(buf, KillsSinceLastCheckpoint);\n\tCopyToBuf(buf, TotalLegitimateKills);\n\tCopyToBuf(buf, LastMissionPassedName);\n\tCopyToBuf(buf, CheatedCount);\n\tPopulateFavoriteRadioStationList();\n\tCopyToBuf(buf, FavoriteRadioStationList);\n\n\tassert(buf - buf_start == *size);\n#undef CopyToBuf\n}\n\nvoid CStats::LoadStats(uint8 *buf, uint32 size)\n{\n\tuint8* buf_start = buf;\n\n#define CopyFromBuf(buf, data) memcpy(&data, buf, sizeof(data)); buf += sizeof(data);\n\n\tCopyFromBuf(buf, PeopleKilledByPlayer);\n\tCopyFromBuf(buf, PeopleKilledByOthers);\n\tCopyFromBuf(buf, CarsExploded);\n\tCopyFromBuf(buf, BoatsExploded);\n\tCopyFromBuf(buf, TyresPopped);\n\tCopyFromBuf(buf, RoundsFiredByPlayer);\n\tCopyFromBuf(buf, PedsKilledOfThisType);\n\tCopyFromBuf(buf, HelisDestroyed);\n\tCopyFromBuf(buf, ProgressMade);\n\tCopyFromBuf(buf, TotalProgressInGame);\n\tCopyFromBuf(buf, KgsOfExplosivesUsed);\n\tCopyFromBuf(buf, BulletsThatHit);\n\tCopyFromBuf(buf, HeadsPopped);\n\tCopyFromBuf(buf, WantedStarsAttained);\n\tCopyFromBuf(buf, WantedStarsEvaded);\n\tCopyFromBuf(buf, TimesArrested);\n\tCopyFromBuf(buf, TimesDied);\n\tCopyFromBuf(buf, DaysPassed);\n\tCopyFromBuf(buf, SafeHouseVisits);\n\tCopyFromBuf(buf, Sprayings);\n\tCopyFromBuf(buf, MaximumJumpDistance);\n\tCopyFromBuf(buf, MaximumJumpHeight);\n\tCopyFromBuf(buf, MaximumJumpFlips);\n\tCopyFromBuf(buf, MaximumJumpSpins);\n\tCopyFromBuf(buf, BestStuntJump);\n\tCopyFromBuf(buf, NumberOfUniqueJumpsFound);\n\tCopyFromBuf(buf, TotalNumberOfUniqueJumps);\n\tCopyFromBuf(buf, MissionsGiven);\n\tCopyFromBuf(buf, PassengersDroppedOffWithTaxi);\n\tCopyFromBuf(buf, MoneyMadeWithTaxi);\n\tCopyFromBuf(buf, IndustrialPassed);\n\tCopyFromBuf(buf, CommercialPassed);\n\tCopyFromBuf(buf, SuburbanPassed);\n\tCopyFromBuf(buf, PamphletMissionPassed);\n\tCopyFromBuf(buf, NoMoreHurricanes);\n\tCopyFromBuf(buf, DistanceTravelledOnFoot);\n\tCopyFromBuf(buf, DistanceTravelledByCar);\n\tCopyFromBuf(buf, DistanceTravelledByBike);\n\tCopyFromBuf(buf, DistanceTravelledByBoat);\n\tCopyFromBuf(buf, DistanceTravelledByGolfCart);\n\tCopyFromBuf(buf, DistanceTravelledByHelicoptor);\n\tCopyFromBuf(buf, DistanceTravelledByPlane);\n\tCopyFromBuf(buf, LivesSavedWithAmbulance);\n\tCopyFromBuf(buf, CriminalsCaught);\n\tCopyFromBuf(buf, FiresExtinguished);\n\tCopyFromBuf(buf, HighestLevelVigilanteMission);\n\tCopyFromBuf(buf, HighestLevelAmbulanceMission);\n\tCopyFromBuf(buf, HighestLevelFireMission);\n\tCopyFromBuf(buf, PhotosTaken);\n\tCopyFromBuf(buf, NumberKillFrenziesPassed);\n\tCopyFromBuf(buf, TotalNumberKillFrenzies);\n\tCopyFromBuf(buf, TotalNumberMissions);\n\tCopyFromBuf(buf, FlightTime);\n\tCopyFromBuf(buf, TimesDrowned);\n\tCopyFromBuf(buf, SeagullsKilled);\n\tCopyFromBuf(buf, WeaponBudget);\n\tCopyFromBuf(buf, FashionBudget);\n\tCopyFromBuf(buf, LoanSharks);\n\tCopyFromBuf(buf, StoresKnockedOff);\n\tCopyFromBuf(buf, MovieStunts);\n\tCopyFromBuf(buf, Assassinations);\n\tCopyFromBuf(buf, PizzasDelivered);\n\tCopyFromBuf(buf, GarbagePickups);\n\tCopyFromBuf(buf, IceCreamSold);\n\tCopyFromBuf(buf, TopShootingRangeScore);\n\tCopyFromBuf(buf, ShootingRank);\n\tCopyFromBuf(buf, LongestWheelie);\n\tCopyFromBuf(buf, LongestStoppie);\n\tCopyFromBuf(buf, Longest2Wheel);\n\tCopyFromBuf(buf, LongestWheelieDist);\n\tCopyFromBuf(buf, LongestStoppieDist);\n\tCopyFromBuf(buf, Longest2WheelDist);\n\tCopyFromBuf(buf, PropertyBudget);\n\tCopyFromBuf(buf, AutoPaintingBudget);\n\tCopyFromBuf(buf, PropertyDestroyed);\n\tCopyFromBuf(buf, NumPropertyOwned);\n\tCopyFromBuf(buf, BloodRingKills);\n\tCopyFromBuf(buf, BloodRingTime);\n\tCopyFromBuf(buf, PropertyOwned);\n\tCopyFromBuf(buf, HighestChaseValue);\n\tCopyFromBuf(buf, FastestTimes);\n\tCopyFromBuf(buf, HighestScores);\n\tCopyFromBuf(buf, BestPositions);\n\tCopyFromBuf(buf, KillsSinceLastCheckpoint);\n\tCopyFromBuf(buf, TotalLegitimateKills);\n\tCopyFromBuf(buf, LastMissionPassedName);\n\tCopyFromBuf(buf, CheatedCount);\n\tCopyFromBuf(buf, FavoriteRadioStationList);\n\n\tassert(buf - buf_start == size);\n#undef CopyFromBuf\n}\n\nvoid\nCStats::PopulateFavoriteRadioStationList()\n{\n\tfloat* pListenTimeArray = DMAudio.GetListenTimeArray();\n\tfor (int i = 0; i < NUM_RADIOS; i++)\n\t\tFavoriteRadioStationList[i] = pListenTimeArray[i];\n}\n\nvoid\nCStats::BuildStatLine(Const char *text, void *stat, int displayType, void *stat2, int isTime)\n{\n#define STAT_D *(int*)stat\n#define STAT_F *(float*)stat\n#define STAT2_D *(int*)stat2\n#define STAT2_F *(float*)stat2\n\tif (!text)\n\t\treturn;\n\n\tgString2[0] = '\\0';\n\tif (isTime == 1) {\n\t\tif (*((int*)stat2) >= 10)\n\t\t\tsprintf(gString2, \" %d:%d\", STAT_D, STAT2_D);\n\t\telse\n\t\t\tsprintf(gString2, \" %d:0%d\", STAT_D, STAT2_D);\n\n\t} else if (stat2) {\n#ifdef MORE_LANGUAGES\n\t\tif (CFont::IsJapanese()) {\n\t\t\tswitch (displayType) {\n\t\t\t\tcase 0:\n\t\t\t\tcase 4:\n\t\t\t\tsprintf(gString2, \"  %d/%d\", STAT_D, STAT2_D);\n\t\t\t\tbreak;\n\t\t\t\tcase 1:\n\t\t\t\tsprintf(gString2, \"  %.2f/%.2f\", STAT_F, STAT2_F);\n\t\t\t\tbreak;\n\t\t\t\tcase 2:\n\t\t\t\tsprintf(gString2, \"  %d%%/%d%%\", STAT_D, STAT2_D);\n\t\t\t\tbreak;\n\t\t\t\tcase 3:\n\t\t\t\tsprintf(gString2, \"  $%.2f/$%.2f\", STAT_F, STAT2_F);\n\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t\t}\n\t\t} else\n#endif\n\t\t{\n\t\t\tswitch (displayType) {\n\t\t\t\tcase 0:\n\t\t\t\tsprintf(gString2, \"  %d %s %d\", STAT_D, UnicodeToAscii(TheText.Get(\"FEST_OO\")), STAT2_D);\n\t\t\t\tbreak;\n\t\t\t\tcase 1:\n\t\t\t\tsprintf(gString2, \"  %.2f %s %.2f\", STAT_F, UnicodeToAscii(TheText.Get(\"FEST_OO\")), STAT2_F);\n\t\t\t\tbreak;\n\t\t\t\tcase 2:\n\t\t\t\tsprintf(gString2, \"  %d%% %s %d%%\", STAT_D, UnicodeToAscii(TheText.Get(\"FEST_OO\")), STAT2_D);\n\t\t\t\tbreak;\n\t\t\t\tcase 3:\n\t\t\t\tsprintf(gString2, \"  $%.2f %s $%.2f\", STAT_F, UnicodeToAscii(TheText.Get(\"FEST_OO\")), STAT2_F);\n\t\t\t\tbreak;\n\t\t\t\tcase 4:\n\t\t\t\tsprintf(gString2, \"  %d_ %s %d_\", STAT_D, UnicodeToAscii(TheText.Get(\"FEST_OO\")), STAT2_D);\n\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t} else if (stat) {\n\t\tswitch (displayType) {\n\t\t\tcase 0:\n\t\t\tsprintf(gString2, \"%d\", STAT_D);\n\t\t\tbreak;\n\t\t\tcase 1:\n\t\t\tsprintf(gString2, \"%.2f\", STAT_F);\n\t\t\tbreak;\n\t\t\tcase 2:\n\t\t\tsprintf(gString2, \"%d%%\", STAT_D);\n\t\t\tbreak;\n\t\t\tcase 3:\n\t\t\tsprintf(gString2, \"$%.2f\", STAT_F);\n\t\t\tbreak;\n\t\t\tcase 4:\n#ifdef MORE_LANGUAGES\n\t\t\tif (CFont::IsJapanese())\n\t\t\t\tsprintf(gString2, \"%d\", STAT_D);\n\t\t\telse\n#endif\n\t\t\t\tsprintf(gString2, \"%d_\", STAT_D);\n\t\t\tbreak;\n\t\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\t}\n\tUnicodeStrcpy(gUString, TheText.Get(text));\n\tCFont::FilterOutTokensFromString(gUString);\n\tAsciiToUnicode(gString2, gUString2);\n#undef STAT_D\n#undef STAT_F\n#undef STAT2_D\n#undef STAT2_F\n}\n\n// rowIdx 99999 returns total numbers of rows. otherwise it returns 0.\nint\nCStats::ConstructStatLine(int rowIdx)\n{\n\n#define STAT_LINE_1(varType, left, right1, type) \\\n\tdo { \\\n\t\tif(counter == rowIdx){ \\\n\t\t\tvarType a = right1; \\\n\t\t\tBuildStatLine(left, &a, type, nil, 0); \\\n\t\t\treturn 0; \\\n\t\t} counter++; \\\n\t} while(0)\n\n#define STAT_LINE_2(varType, left, right1, type, right2, time) \\\n\tdo { \\\n\t\tif(counter == rowIdx){ \\\n\t\t\tvarType a = right1; \\\n\t\t\tvarType b = right2; \\\n\t\t\tBuildStatLine(left, &a, type, &b, time); \\\n\t\t\treturn 0; \\\n\t\t} counter++; \\\n\t} while(0)\n\n#define TEXT_ON_LEFT_GXT(name) \\\n\tdo { \\\n\t\tif(counter == rowIdx){ \\\n\t\t\tBuildStatLine(name, nil, 0, nil, 0); \\\n\t\t\treturn 0; \\\n\t\t} counter++; \\\n\t} while(0)\n\n#define TEXT_ON_RIGHT(text) \\\n\tdo { \\\n\t\tif(counter == rowIdx){ \\\n\t\t\tgUString[0] = '\\0'; \\\n\t\t\tUnicodeStrcpy(gUString2, text); \\\n\t\t\treturn 0; \\\n\t\t} counter++; \\\n\t} while(0)\n\n#define FASTEST_TIME(id, str) \\\n\tdo { \\\n\t\tif(FastestTimes[id]) { \\\n\t\t\tif(counter == rowIdx){ \\\n\t\t\t\tint hour = 0, minute; \\\n\t\t\t\tfor (int i = FastestTimes[id]; i > 59; i -= 60) hour++; \\\n\t\t\t\tfor (minute = FastestTimes[id]; minute > 59; minute -= 60); \\\n\t\t\t\tif (minute < 0) minute = -minute; \\\n\t\t\t\tBuildStatLine(str, &hour, 0, &minute, 1); \\\n\t\t\t\treturn 0; \\\n\t\t\t} \\\n\t\t\tcounter++; \\\n\t\t} \\\n\t} while(0)\n\n\tswitch (rowIdx) {\n\t\tcase 0: {\n\t\t\tint percentCompleted = GetPercentageProgress();\n\t\t\tBuildStatLine(\"PER_COM\", &percentCompleted, 2, nil, 0);\n\t\t\treturn 0;\n\t\t}\n\t\tcase 1: {\n\t\t\tBuildStatLine(\"NMISON\", &MissionsGiven, 0, nil, 0);\n\t\t\treturn 0;\n\t\t}\n\t\tcase 2: {\n\t\t\tint hour = (CTimer::GetTimeInMilliseconds() / 60000) / 60;\n\t\t\tint minute = (CTimer::GetTimeInMilliseconds() / 60000) % 60;\n\t\t\tBuildStatLine(\"ST_TIME\", &hour, 0, &minute, 1);\n\t\t\treturn 0;\n\t\t}\n\t\tcase 3: {\n\t\t\tBuildStatLine(\"DAYSPS\", &DaysPassed, 0, nil, 0);\n\t\t\treturn 0;\n\t\t}\n\t\tcase 4: {\n\t\t\tBuildStatLine(\"NUMSHV\", &SafeHouseVisits, 0, nil, 0);\n\t\t\treturn 0;\n\t\t}\n\t}\n\tint counter = 5;\n\t\n\tif (CGame::nastyGame) {\n\t\tSTAT_LINE_2(int, \"FEST_RP\", NumberKillFrenziesPassed, 0, TotalNumberKillFrenzies, 0);\n\t}\n\t\n\tCPlayerInfo &player = CWorld::Players[CWorld::PlayerInFocus];\n\n\t// Hidden packages shouldn't be shown with percent\n#ifdef FIX_BUGS\n\tSTAT_LINE_2(int, \"PERPIC\", player.m_nCollectedPackages, 0, player.m_nTotalPackages, 0);\n#else\n\tfloat fPackagesPercent = 0.0f;\n\tif (player.m_nTotalPackages != 0)\n\t\tfPackagesPercent = player.m_nCollectedPackages * 100.0f / player.m_nTotalPackages;\n\n\tSTAT_LINE_2(int, \"PERPIC\", fPackagesPercent, 0, 100, 0);\n#endif\n\n\tif (CGame::nastyGame) {\n\t\tSTAT_LINE_1(int, \"PE_WAST\", PeopleKilledByPlayer, 0);\n\t\tSTAT_LINE_1(int, \"PE_WSOT\", PeopleKilledByOthers, 0);\n\t}\n\tSTAT_LINE_1(int, \"CAR_EXP\", CarsExploded, 0);\n\tSTAT_LINE_1(int, \"BOA_EXP\", BoatsExploded, 0);\n\tSTAT_LINE_1(int, \"HEL_DST\", HelisDestroyed, 0);\n\tSTAT_LINE_1(int, \"TYREPOP\", TyresPopped, 0);\n\tSTAT_LINE_1(int, \"ST_STAR\", WantedStarsAttained, 0);\n\tSTAT_LINE_1(int, \"ST_STGN\", WantedStarsEvaded, 0);\n\tSTAT_LINE_1(int, \"TM_BUST\", TimesArrested, 0);\n\tSTAT_LINE_1(int, \"TM_DED\", TimesDied, 0);\n\n#ifdef MORE_LANGUAGES\n\t// JP version removed it altogether actually\n\tif (!CFont::IsJapanese())\n#endif\n\tSTAT_LINE_1(int, \"ST_HEAD\", HeadsPopped, 0);\n\n\tstatic uint32 lastProcessedDay = UINT32_MAX;\n\tstatic uint32 lastPoliceSpending = 0;\n\n\t// What a random stat...\n\tif (lastProcessedDay != DaysPassed) {\n\t\tlastProcessedDay = DaysPassed;\n\t\tlastPoliceSpending = (CTimer::GetTimeInMilliseconds() & 255 + 80) * 255.44f;\n\t}\n\tSTAT_LINE_1(float, \"DAYPLC\", lastPoliceSpending, 3);\n\n\tint mostPatheticGang = 0;\n\tint mostKill = 0;\n\tfor (int i = PEDTYPE_GANG1; i < PEDTYPE_GANG9; ++i) {\n\t\tif (CStats::PedsKilledOfThisType[i] > mostKill) {\n\t\t\tmostKill = CStats::PedsKilledOfThisType[i];\n\t\t\tmostPatheticGang = i;\n\t\t}\n\t}\n\tif (mostPatheticGang > 0) {\n\t\tTEXT_ON_LEFT_GXT(\"ST_GANG\");\n\n\t\tswitch (mostPatheticGang) {\n\t\t\tcase PEDTYPE_GANG1:\n\t\t\t\tTEXT_ON_RIGHT(TheText.Get(\"ST_GNG1\"));\n\t\t\t\tbreak;\n\t\t\tcase PEDTYPE_GANG2:\n\t\t\t\tTEXT_ON_RIGHT(TheText.Get(\"ST_GNG2\"));\n\t\t\t\tbreak;\n\t\t\tcase PEDTYPE_GANG3:\n\t\t\t\tTEXT_ON_RIGHT(TheText.Get(\"ST_GNG3\"));\n\t\t\t\tbreak;\n\t\t\tcase PEDTYPE_GANG4:\n\t\t\t\tTEXT_ON_RIGHT(TheText.Get(\"ST_GNG4\"));\n\t\t\t\tbreak;\n\t\t\tcase PEDTYPE_GANG5:\n\t\t\t\tTEXT_ON_RIGHT(TheText.Get(\"ST_GNG5\"));\n\t\t\t\tbreak;\n\t\t\tcase PEDTYPE_GANG6:\n\t\t\t\tTEXT_ON_RIGHT(TheText.Get(\"ST_GNG6\"));\n\t\t\t\tbreak;\n\t\t\tcase PEDTYPE_GANG7:\n\t\t\t\tTEXT_ON_RIGHT(TheText.Get(\"ST_GNG7\"));\n\t\t\t\tbreak;\n\t\t\tcase PEDTYPE_GANG8:\n\t\t\t\tTEXT_ON_RIGHT(TheText.Get(\"ST_GNG8\"));\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tSTAT_LINE_1(int, \"GNG_WST\", PedsKilledOfThisType[PEDTYPE_GANG9] + PedsKilledOfThisType[PEDTYPE_GANG8]\n\t\t\t+ PedsKilledOfThisType[PEDTYPE_GANG7] + PedsKilledOfThisType[PEDTYPE_GANG6]\n\t\t\t+ PedsKilledOfThisType[PEDTYPE_GANG5] + PedsKilledOfThisType[PEDTYPE_GANG4]\n\t\t\t+ PedsKilledOfThisType[PEDTYPE_GANG3] + PedsKilledOfThisType[PEDTYPE_GANG2]\n\t\t\t+ PedsKilledOfThisType[PEDTYPE_GANG1], 0);\n\n\tSTAT_LINE_1(int, \"DED_CRI\", PedsKilledOfThisType[PEDTYPE_CRIMINAL], 0);\n\tSTAT_LINE_1(int, \"KGS_EXP\", KgsOfExplosivesUsed, 0);\n\tSTAT_LINE_1(int, \"BUL_FIR\", RoundsFiredByPlayer, 0);\n\tSTAT_LINE_1(int, \"BUL_HIT\", BulletsThatHit, 0);\n;\n\tSTAT_LINE_1(int, \"ACCURA\", RoundsFiredByPlayer == 0 ? 0 : (BulletsThatHit * 100.0f / (float)RoundsFiredByPlayer), 2);\n\n\tswitch (FrontEndMenuManager.m_PrefsLanguage) {\n\t\tcase CMenuManager::LANGUAGE_AMERICAN:\n#ifndef USE_MEASUREMENTS_IN_METERS\n\t\t\tSTAT_LINE_1(float, \"FEST_DF\", DistanceTravelledOnFoot * MILES_IN_METER, 1);\n\t\t\tSTAT_LINE_1(float, \"FEST_DC\", DistanceTravelledByCar * MILES_IN_METER, 1);\n\t\t\tSTAT_LINE_1(float, \"DISTBIK\", DistanceTravelledByBike * MILES_IN_METER, 1);\n\t\t\tSTAT_LINE_1(float, \"DISTBOA\", DistanceTravelledByBoat * MILES_IN_METER, 1);\n\t\t\tSTAT_LINE_1(float, \"DISTGOL\", DistanceTravelledByGolfCart * MILES_IN_METER, 1);\n\t\t\tSTAT_LINE_1(float, \"DISTHEL\", DistanceTravelledByHelicoptor * MILES_IN_METER, 1);\n#ifdef FIX_BUGS\n\t\t\tSTAT_LINE_1(float, \"TOT_DIS\", (DistanceTravelledOnFoot + DistanceTravelledByCar + DistanceTravelledByBoat + DistanceTravelledByBike\n\t\t\t\t+ DistanceTravelledByGolfCart + DistanceTravelledByHelicoptor + DistanceTravelledByPlane) * MILES_IN_METER, 1);\n\t\t\tSTAT_LINE_1(float, \"MXCARD\", MaximumJumpDistance * FEET_IN_METER, 1);\n\t\t\tSTAT_LINE_1(float, \"MXCARJ\", MaximumJumpHeight * FEET_IN_METER, 1);\n#else\n\t\t\tSTAT_LINE_1(float, \"TOT_DIS\", (DistanceTravelledOnFoot + DistanceTravelledByCar + DistanceTravelledByBoat + DistanceTravelledByBike\n\t\t\t\t+ DistanceTravelledByGolfCart + DistanceTravelledByHelicoptor) * MILES_IN_METER, 1);\n#endif\n\t\t\tbreak;\n#endif\n\t\tcase CMenuManager::LANGUAGE_FRENCH:\n\t\tcase CMenuManager::LANGUAGE_GERMAN:\n\t\tcase CMenuManager::LANGUAGE_ITALIAN:\n\t\tcase CMenuManager::LANGUAGE_SPANISH:\n#ifdef MORE_LANGUAGES\n\t\tcase CMenuManager::LANGUAGE_POLISH:\n\t\tcase CMenuManager::LANGUAGE_RUSSIAN:\n\t\tcase CMenuManager::LANGUAGE_JAPANESE:\n#endif\n\t\t\tSTAT_LINE_1(float, \"FESTDFM\", DistanceTravelledOnFoot, 1);\n\t\t\tSTAT_LINE_1(float, \"FESTDCM\", DistanceTravelledByCar, 1);\n\t\t\tSTAT_LINE_1(float, \"DISTBIM\", DistanceTravelledByBike, 1);\n\t\t\tSTAT_LINE_1(float, \"DISTBOM\", DistanceTravelledByBoat, 1);\n\t\t\tSTAT_LINE_1(float, \"DISTGOM\", DistanceTravelledByGolfCart, 1);\n\t\t\tSTAT_LINE_1(float, \"DISTHEM\", DistanceTravelledByHelicoptor, 1);\n#ifdef FIX_BUGS\n\t\t\tSTAT_LINE_1(float, \"TOTDISM\", DistanceTravelledOnFoot + DistanceTravelledByCar + DistanceTravelledByBoat\n\t\t\t\t+ DistanceTravelledByBike + DistanceTravelledByGolfCart + DistanceTravelledByHelicoptor + DistanceTravelledByPlane, 1);\n\t\t\tSTAT_LINE_1(float, \"MXCARDM\", MaximumJumpDistance, 1);\n\t\t\tSTAT_LINE_1(float, \"MXCARJM\", MaximumJumpHeight, 1);\n#else\n\t\t\tSTAT_LINE_1(float, \"TOTDISM\", DistanceTravelledOnFoot + DistanceTravelledByCar + DistanceTravelledByBoat\n\t\t\t\t+ DistanceTravelledByGolfCart + DistanceTravelledByHelicoptor, 1);\n#endif\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\n\t// They were selecting the unit according to language in III, but they deleted the feet code in VC. Weird\n#ifndef FIX_BUGS\n\tSTAT_LINE_1(float, \"MXCARDM\", MaximumJumpDistance, 1);\n\tSTAT_LINE_1(float, \"MXCARJM\", MaximumJumpHeight, 1);\n#endif\n\tSTAT_LINE_1(int, \"MXFLIP\", MaximumJumpFlips, 0);\n\tSTAT_LINE_2(int, \"NOUNIF\", NumberOfUniqueJumpsFound, 0, TotalNumberOfUniqueJumps, 0);\n\tSTAT_LINE_1(int, \"MXJUMP\", MaximumJumpSpins, 4);\n\n\tTEXT_ON_LEFT_GXT(\"BSTSTU\");\n\tswitch (BestStuntJump) {\n\t\tcase 1:\n\t\t\tTEXT_ON_RIGHT(TheText.Get(\"INSTUN\"));\n\t\t\tbreak;\n\t\tcase 2:\n\t\t\tTEXT_ON_RIGHT(TheText.Get(\"PRINST\"));\n\t\t\tbreak;\n\t\tcase 3:\n\t\t\tTEXT_ON_RIGHT(TheText.Get(\"DBINST\"));\n\t\t\tbreak;\n\t\tcase 4:\n\t\t\tTEXT_ON_RIGHT(TheText.Get(\"DBPINS\"));\n\t\t\tbreak;\n\t\tcase 5:\n\t\t\tTEXT_ON_RIGHT(TheText.Get(\"TRINST\"));\n\t\t\tbreak;\n\t\tcase 6:\n\t\t\tTEXT_ON_RIGHT(TheText.Get(\"PRTRST\"));\n\t\t\tbreak;\n\t\tcase 7:\n\t\t\tTEXT_ON_RIGHT(TheText.Get(\"QUINST\"));\n\t\t\tbreak;\n\t\tcase 8:\n\t\t\tTEXT_ON_RIGHT(TheText.Get(\"PQUINS\"));\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tTEXT_ON_RIGHT(TheText.Get(\"NOSTUC\"));\n\t\t\tbreak;\n\t}\n\tSTAT_LINE_1(int, \"ST_WHEE\", LongestWheelie, 0);\n\tSTAT_LINE_1(float, \"ST_WHED\", LongestWheelieDist, 1);\n\tSTAT_LINE_1(int, \"ST_STOP\", LongestStoppie, 0);\n\tSTAT_LINE_1(float, \"ST_STOD\", LongestStoppieDist, 1);\n\tSTAT_LINE_1(int, \"ST_2WHE\", Longest2Wheel, 0);\n\tSTAT_LINE_1(float, \"ST_2WHD\", Longest2WheelDist, 1);\n\n\tif (LoanSharks > 0.0f)\n\t\tSTAT_LINE_1(int, \"ST_LOAN\", LoanSharks, 0);\n\n\tSTAT_LINE_1(int, \"FEST_CC\", CriminalsCaught, 0);\n\tSTAT_LINE_1(int, \"FEST_HV\", HighestLevelVigilanteMission, 0);\n\tSTAT_LINE_1(int, \"PASDRO\", PassengersDroppedOffWithTaxi, 0);\n\tSTAT_LINE_1(float, \"MONTAX\", MoneyMadeWithTaxi, 3);\n\tSTAT_LINE_1(int, \"FEST_LS\", LivesSavedWithAmbulance, 0);\n\tSTAT_LINE_1(int, \"FEST_HA\", HighestLevelAmbulanceMission, 0);\n\tSTAT_LINE_1(int, \"FEST_FE\", FiresExtinguished, 0);\n\tSTAT_LINE_1(int, \"FIRELVL\", HighestLevelFireMission, 0);\n\n\tSTAT_LINE_2(int, \"ST_STOR\", StoresKnockedOff, 0, 15, 0);\n\n\tif (MovieStunts > 0.0f)\n\t\tSTAT_LINE_1(int, \"ST_MOVI\", MovieStunts, 0);\n\n\tSTAT_LINE_2(int, \"ST_ASSI\", Assassinations, 0, 5, 0);\n\n\tif (PhotosTaken > 0)\n\t\tSTAT_LINE_1(int, \"ST_PHOT\", PhotosTaken, 0);\n\n\tif (PizzasDelivered > 0.0f)\n\t\tSTAT_LINE_1(int, \"ST_PIZZ\", PizzasDelivered, 0);\n\n\tif (GarbagePickups > 0.0f)\n\t\tSTAT_LINE_1(int, \"ST_GARB\", GarbagePickups, 0);\n\n\tif (IceCreamSold > 0.0f)\n\t\tSTAT_LINE_1(int, \"ST_ICEC\", IceCreamSold, 0);\n\n\tif (HighestScores[1])\n\t\tSTAT_LINE_1(int, \"STHC_02\", HighestScores[1], 0);\n\n\tFASTEST_TIME(0, \"STFT_01\");\n\tFASTEST_TIME(1, \"STFT_02\");\n\tFASTEST_TIME(2, \"STFT_03\");\n\tFASTEST_TIME(3, \"STFT_04\");\n\tFASTEST_TIME(4, \"STFT_05\");\n\tFASTEST_TIME(5, \"STFT_06\");\n\tFASTEST_TIME(6, \"STFT_07\");\n\tFASTEST_TIME(7, \"STFT_08\");\n\tFASTEST_TIME(8, \"STFT_09\");\n\tFASTEST_TIME(9, \"STFT_10\");\n\tFASTEST_TIME(10, \"STFT_11\");\n\tFASTEST_TIME(11, \"STFT_12\");\n\tFASTEST_TIME(12, \"STFT_13\");\n\tFASTEST_TIME(13, \"STFT_14\");\n\tFASTEST_TIME(14, \"STFT_15\");\n\tFASTEST_TIME(15, \"STFT_16\");\n\tFASTEST_TIME(16, \"STFT_17\");\n\tFASTEST_TIME(17, \"STFT_18\");\n\tFASTEST_TIME(18, \"STFT_19\");\n\tFASTEST_TIME(19, \"STFT_20\");\n\tFASTEST_TIME(22, \"STFT_23\");\n\n\tif (HighestScores[0])\n\t\tSTAT_LINE_1(int, \"STHC_01\", HighestScores[0], 0);\n\n\tif (HighestScores[3])\n\t\tSTAT_LINE_1(int, \"STHC_04\", HighestScores[3], 0);\n\n\tif (HighestScores[2])\n\t\tSTAT_LINE_1(int, \"STHC_03\", HighestScores[2], 0);\n\n\tif (BestPositions[0] != INT_MAX)\n\t\tSTAT_LINE_1(int, \"STHC_05\", BestPositions[0], 0);\n\n\tFASTEST_TIME(20, \"STFT_21\");\n\n\tif (FastestTimes[21])\n\t\tSTAT_LINE_1(float, \"STFT_22\", FastestTimes[21] / 1000, 1);\n\n\tif (TopShootingRangeScore > 0.0f)\n\t\tSTAT_LINE_1(int, \"TOP_SHO\", TopShootingRangeScore, 0);\n\n\tif (ShootingRank > 0.0f)\n\t\tSTAT_LINE_1(int, \"SHO_RAN\", ShootingRank, 0);\n\n\tint flightMinute = (FlightTime / 60000) % 60;\n\tint flightHour = (FlightTime / 60000) / 60;\n\tSTAT_LINE_2(int, \"ST_FTIM\", flightHour, 0, flightMinute, 1);\n\n\t// We always have pilot rank if we flew more then 5 minutes\n#ifndef FIX_BUGS\n\tif (flightHour != 0)\n\t\tTEXT_ON_LEFT_GXT(\"ST_PRAN\");\n#endif\n\n#ifdef FIX_BUGS\n#define FL_TIME_MORE_THAN(hour, minute) (flightHour > hour || (flightHour == hour && flightMinute >= minute))\n#else\n#define FL_TIME_MORE_THAN(hour, minute) (flightHour > hour || flightMinute >= minute)\n#endif\n\n\tif (FL_TIME_MORE_THAN(0,5)) {\n\n#ifdef FIX_BUGS\n\t\tTEXT_ON_LEFT_GXT(\"ST_PRAN\");\n#endif\n\t\tif (!FL_TIME_MORE_THAN(0,10)) TEXT_ON_RIGHT(TheText.Get(\"ST_PR01\"));\n\t\telse if (!FL_TIME_MORE_THAN(0,20)) TEXT_ON_RIGHT(TheText.Get(\"ST_PR02\"));\n\t\telse if (!FL_TIME_MORE_THAN(0,30)) TEXT_ON_RIGHT(TheText.Get(\"ST_PR03\"));\n\t\telse if (!FL_TIME_MORE_THAN(1,0)) TEXT_ON_RIGHT(TheText.Get(\"ST_PR04\"));\n\t\telse if (!FL_TIME_MORE_THAN(1,30)) TEXT_ON_RIGHT(TheText.Get(\"ST_PR05\"));\n\t\telse if (!FL_TIME_MORE_THAN(2,0)) TEXT_ON_RIGHT(TheText.Get(\"ST_PR06\"));\n\t\telse if (!FL_TIME_MORE_THAN(2,30)) TEXT_ON_RIGHT(TheText.Get(\"ST_PR07\"));\n\t\telse if (!FL_TIME_MORE_THAN(3,0)) TEXT_ON_RIGHT(TheText.Get(\"ST_PR08\"));\n\t\telse if (!FL_TIME_MORE_THAN(3,30)) TEXT_ON_RIGHT(TheText.Get(\"ST_PR09\"));\n\t\telse if (!FL_TIME_MORE_THAN(4,0)) TEXT_ON_RIGHT(TheText.Get(\"ST_PR10\"));\n\t\telse if (!FL_TIME_MORE_THAN(5,0)) TEXT_ON_RIGHT(TheText.Get(\"ST_PR11\"));\n\t\telse if (!FL_TIME_MORE_THAN(10,0)) TEXT_ON_RIGHT(TheText.Get(\"ST_PR12\"));\n\t\telse if (!FL_TIME_MORE_THAN(20,0)) TEXT_ON_RIGHT(TheText.Get(\"ST_PR13\"));\n\t\telse if (!FL_TIME_MORE_THAN(25,0)) TEXT_ON_RIGHT(TheText.Get(\"ST_PR14\"));\n\t\telse if (!FL_TIME_MORE_THAN(30,0)) TEXT_ON_RIGHT(TheText.Get(\"ST_PR15\"));\n\t\telse if (!FL_TIME_MORE_THAN(49,2)) TEXT_ON_RIGHT(TheText.Get(\"ST_PR16\"));\n\t\telse if (!FL_TIME_MORE_THAN(50,0)) TEXT_ON_RIGHT(TheText.Get(\"ST_PR17\"));\n\t\telse if (!FL_TIME_MORE_THAN(100,0)) TEXT_ON_RIGHT(TheText.Get(\"ST_PR18\"));\n\t\telse TEXT_ON_RIGHT(TheText.Get(\"ST_PR19\"));\n\t}\n#undef FL_TIME_MORE_THAN\n\n\tif (BloodRingKills > 0)\n\t\tSTAT_LINE_1(int, \"ST_BRK\", BloodRingKills, 0);\n\n\tif (BloodRingTime > 0)\n\t\tSTAT_LINE_1(int, \"ST_LTBR\", BloodRingTime, 0);\n\n\tSTAT_LINE_1(int, \"ST_DRWN\", TimesDrowned, 0);\n\n\tif (SeagullsKilled > 0)\n\t\tSTAT_LINE_1(int, \"SEAGULL\", SeagullsKilled, 0);\n\n\tbool playerHatesRadio = true;\n\tfloat* pListenTimeArray = DMAudio.GetListenTimeArray();\n\tfor (int i = 0; i < NUM_RADIOS; i++) {\n\t\tFavoriteRadioStationList[i] = pListenTimeArray[i];\n\t\tif (FavoriteRadioStationList[i] != 0.0) // double\n\t\t\tplayerHatesRadio = false;\n\t}\n\n\tif (!playerHatesRadio) {\n\t\t// Most listened\n\t\tTEXT_ON_LEFT_GXT(\"FST_MFR\");\n\t\tfloat mostListenTime = FavoriteRadioStationList[0];\n\t\tint mostListenedRadio = 0;\n\t\tfor (int i = 0; i < NUM_RADIOS; i++) {\n\t\t\tif (FavoriteRadioStationList[i] > mostListenTime) {\n\t\t\t\tmostListenTime = FavoriteRadioStationList[i];\n\t\t\t\tmostListenedRadio = i;\n\t\t\t}\n\t\t}\n\t\tswitch (mostListenedRadio) {\n\t\t\tcase WILDSTYLE:\n\t\t\t\tTEXT_ON_RIGHT(TheText.Get(\"FEA_FM0\"));\n\t\t\t\tbreak;\n\t\t\tcase FLASH_FM:\n\t\t\t\tTEXT_ON_RIGHT(TheText.Get(\"FEA_FM1\"));\n\t\t\t\tbreak;\n\t\t\tcase KCHAT:\n\t\t\t\tTEXT_ON_RIGHT(TheText.Get(\"FEA_FM2\"));\n\t\t\t\tbreak;\n\t\t\tcase FEVER:\n\t\t\t\tTEXT_ON_RIGHT(TheText.Get(\"FEA_FM3\"));\n\t\t\t\tbreak;\n\t\t\tcase V_ROCK:\n\t\t\t\tTEXT_ON_RIGHT(TheText.Get(\"FEA_FM4\"));\n\t\t\t\tbreak;\n\t\t\tcase VCPR:\n\t\t\t\tTEXT_ON_RIGHT(TheText.Get(\"FEA_FM5\"));\n\t\t\t\tbreak;\n\t\t\tcase RADIO_ESPANTOSO:\n\t\t\t\tTEXT_ON_RIGHT(TheText.Get(\"FEA_FM6\"));\n\t\t\t\tbreak;\n\t\t\tcase EMOTION:\n\t\t\t\tTEXT_ON_RIGHT(TheText.Get(\"FEA_FM7\"));\n\t\t\t\tbreak;\n\t\t\tcase WAVE:\n\t\t\t\tTEXT_ON_RIGHT(TheText.Get(\"FEA_FM8\"));\n\t\t\t\tbreak;\n\t\t\tcase USERTRACK:\n\t\t\t\tTEXT_ON_RIGHT(TheText.Get(\"FEA_MP3\"));\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tTEXT_ON_RIGHT(TheText.Get(\"FEA_FM8\")); // heh\n\t\t\t\tbreak;\n\t\t}\n\n\t\t// Least listened\n\t\tTEXT_ON_LEFT_GXT(\"FST_LFR\");\n\t\tfloat leastListenTime = FavoriteRadioStationList[0];\n\t\tint leastListenedRadio = 0;\n\t\tfor (int i = 0; i < NUM_RADIOS; i++) {\n#ifdef FIX_BUGS\n\t\t\tif (!DMAudio.IsMP3RadioChannelAvailable() && i == USERTRACK)\n\t\t\t\tcontinue;\n#endif\n\t\t\tif (FavoriteRadioStationList[i] < leastListenTime) {\n\t\t\t\tleastListenTime = FavoriteRadioStationList[i];\n\t\t\t\tleastListenedRadio = i;\n\t\t\t}\n\t\t}\n#ifndef FIX_BUGS\n\t\tif (!DMAudio.IsMP3RadioChannelAvailable() && leastListenedRadio == USERTRACK)\n\t\t\tleastListenedRadio = WAVE;\n#endif\n\n\t\tswitch (leastListenedRadio) {\n\t\t\tcase WILDSTYLE:\n\t\t\t\tTEXT_ON_RIGHT(TheText.Get(\"FEA_FM0\"));\n\t\t\t\tbreak;\n\t\t\tcase FLASH_FM:\n\t\t\t\tTEXT_ON_RIGHT(TheText.Get(\"FEA_FM1\"));\n\t\t\t\tbreak;\n\t\t\tcase KCHAT:\n\t\t\t\tTEXT_ON_RIGHT(TheText.Get(\"FEA_FM2\"));\n\t\t\t\tbreak;\n\t\t\tcase FEVER:\n\t\t\t\tTEXT_ON_RIGHT(TheText.Get(\"FEA_FM3\"));\n\t\t\t\tbreak;\n\t\t\tcase V_ROCK:\n\t\t\t\tTEXT_ON_RIGHT(TheText.Get(\"FEA_FM4\"));\n\t\t\t\tbreak;\n\t\t\tcase VCPR:\n\t\t\t\tTEXT_ON_RIGHT(TheText.Get(\"FEA_FM5\"));\n\t\t\t\tbreak;\n\t\t\tcase RADIO_ESPANTOSO:\n\t\t\t\tTEXT_ON_RIGHT(TheText.Get(\"FEA_FM6\"));\n\t\t\t\tbreak;\n\t\t\tcase EMOTION:\n\t\t\t\tTEXT_ON_RIGHT(TheText.Get(\"FEA_FM7\"));\n\t\t\t\tbreak;\n\t\t\tcase WAVE:\n\t\t\t\tTEXT_ON_RIGHT(TheText.Get(\"FEA_FM8\"));\n\t\t\t\tbreak;\n\t\t\tcase USERTRACK:\n\t\t\t\tTEXT_ON_RIGHT(TheText.Get(\"FEA_MP3\"));\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tTEXT_ON_RIGHT(TheText.Get(\"FEA_FM8\")); // heh\n\t\t\t\tbreak;\n\t\t}\n\t}\n\tSTAT_LINE_1(int, \"SPRAYIN\", Sprayings, 0);\n\tSTAT_LINE_1(float, \"ST_WEAP\", WeaponBudget, 3);\n\tSTAT_LINE_1(float, \"ST_FASH\", FashionBudget, 3);\n\tSTAT_LINE_1(float, \"ST_PROP\", PropertyBudget, 3);\n\tSTAT_LINE_1(float, \"ST_AUTO\", AutoPaintingBudget, 3);\n\tSTAT_LINE_1(float, \"ST_DAMA\", PropertyBudget, 3);\n\n\tif (NumPropertyOwned > 0) {\n\t\tSTAT_LINE_1(int, \"PROPOWN\", NumPropertyOwned, 0);\n\t\tif (PropertyOwned[0]) TEXT_ON_RIGHT(TheText.Get(\"STPR_1\"));\n\t\tif (PropertyOwned[1]) TEXT_ON_RIGHT(TheText.Get(\"STPR_2\"));\n\t\tif (PropertyOwned[2]) TEXT_ON_RIGHT(TheText.Get(\"STPR_3\"));\n\t\tif (PropertyOwned[3]) TEXT_ON_RIGHT(TheText.Get(\"STPR_4\"));\n\t\tif (PropertyOwned[4]) TEXT_ON_RIGHT(TheText.Get(\"STPR_5\"));\n\t\tif (PropertyOwned[5]) TEXT_ON_RIGHT(TheText.Get(\"STPR_6\"));\n\t\tif (PropertyOwned[6]) TEXT_ON_RIGHT(TheText.Get(\"STPR_7\"));\n\t\tif (PropertyOwned[7]) TEXT_ON_RIGHT(TheText.Get(\"STPR_8\"));\n\t\tif (PropertyOwned[8]) TEXT_ON_RIGHT(TheText.Get(\"STPR_9\"));\n\t\tif (PropertyOwned[9]) TEXT_ON_RIGHT(TheText.Get(\"STPR_10\"));\n\t\tif (PropertyOwned[10]) TEXT_ON_RIGHT(TheText.Get(\"STPR_11\"));\n\t\tif (PropertyOwned[11]) TEXT_ON_RIGHT(TheText.Get(\"STPR_12\"));\n\t\tif (PropertyOwned[12]) TEXT_ON_RIGHT(TheText.Get(\"STPR_13\"));\n\t\tif (PropertyOwned[13]) TEXT_ON_RIGHT(TheText.Get(\"STPR_14\"));\n\t\tif (PropertyOwned[14]) TEXT_ON_RIGHT(TheText.Get(\"STPR_15\"));\n\t}\n\tSTAT_LINE_1(int, \"CHASE\", HighestChaseValue, 0);\n\tTEXT_ON_RIGHT(FindChaseString(HighestChaseValue));\n\n\treturn counter;\n\n#undef STAT_LINE_1\n#undef STAT_LINE_2\n#undef TEXT_ON_LEFT_GXT\n#undef TEXT_ON_RIGHT\n#undef FASTEST_TIME\n}\n"
  },
  {
    "path": "src/core/Stats.h",
    "content": "#pragma once\n\n#include \"PedType.h\"\n#include \"audio_enums.h\"\n\nclass CStats\n{\npublic:\n\tenum {\n\t\tTOTAL_FASTEST_TIMES = 23,\n\t\tTOTAL_HIGHEST_SCORES = 5,\n\t\tTOTAL_BEST_POSITIONS = 1,\n\t\tTOTAL_PROPERTIES = 15\n\t};\n\tstatic int32 SeagullsKilled;\n\tstatic int32 DaysPassed;\n\tstatic int32 HeadsPopped;\n\tstatic int32 CommercialPassed;\n\tstatic int32 IndustrialPassed;\n\tstatic int32 SuburbanPassed;\n\tstatic int32 NumberKillFrenziesPassed;\n\tstatic int32 PeopleKilledByOthers;\n\tstatic int32 HelisDestroyed;\n\tstatic int32 PedsKilledOfThisType[NUM_PEDTYPES];\n\tstatic int32 TimesDied;\n\tstatic int32 TimesArrested;\n\tstatic int32 KillsSinceLastCheckpoint;\n\tstatic float DistanceTravelledByCar;\n\tstatic float DistanceTravelledByHelicoptor;\n\tstatic float DistanceTravelledByBike;\n\tstatic float DistanceTravelledByBoat;\n\tstatic float DistanceTravelledByPlane;\n\tstatic float DistanceTravelledByGolfCart;\n\tstatic float DistanceTravelledOnFoot;\n\tstatic int32 FlightTime;\n\tstatic int32 TimesDrowned;\n\tstatic int32 PhotosTaken;\n\tstatic float LoanSharks;\n\tstatic float StoresKnockedOff;\n\tstatic float MovieStunts;\n\tstatic float Assassinations;\n\tstatic float PizzasDelivered;\n\tstatic float GarbagePickups;\n\tstatic float IceCreamSold;\n\tstatic float TopShootingRangeScore;\n\tstatic float ShootingRank;\n\tstatic int32 CarsExploded;\n\tstatic int32 BoatsExploded;\n\tstatic int32 WantedStarsAttained;\n\tstatic int32 WantedStarsEvaded;\n\tstatic int32 PeopleKilledByPlayer;\n\tstatic float ProgressMade;\n\tstatic float TotalProgressInGame;\n\tstatic float MaximumJumpDistance;\n\tstatic float MaximumJumpHeight;\n\tstatic int32 MaximumJumpFlips;\n\tstatic int32 MaximumJumpSpins;\n\tstatic int32 BestStuntJump;\n\tstatic int32 NumberOfUniqueJumpsFound;\n\tstatic int32 TotalNumberOfUniqueJumps;\n\tstatic int32 PassengersDroppedOffWithTaxi;\n\tstatic int32 MoneyMadeWithTaxi;\n\tstatic int32 MissionsGiven;\n\tstatic int32 MissionsPassed;\n\tstatic char  LastMissionPassedName[8];\n\tstatic int32 TotalLegitimateKills;\n\tstatic int32 LivesSavedWithAmbulance;\n\tstatic int32 CriminalsCaught;\n\tstatic int32 HighestLevelAmbulanceMission;\n\tstatic int32 HighestLevelVigilanteMission;\n\tstatic int32 HighestLevelFireMission;\n\tstatic int32 FiresExtinguished;\n\tstatic int32 TotalNumberKillFrenzies;\n\tstatic int32 TotalNumberMissions;\n\tstatic int32 RoundsFiredByPlayer;\n\tstatic int32 KgsOfExplosivesUsed;\n\tstatic int32 BulletsThatHit;\n\tstatic int32 BestTimeBombDefusal;\n\tstatic int32 FastestTimes[TOTAL_FASTEST_TIMES];\n\tstatic int32 HighestScores[TOTAL_HIGHEST_SCORES];\n\tstatic int32 BestPositions[TOTAL_BEST_POSITIONS];\n\tstatic bool PropertyOwned[TOTAL_PROPERTIES];\n\tstatic int32 NumPropertyOwned;\n\tstatic int32 PropertyDestroyed;\n\tstatic float HighestChaseValue;\n\tstatic int32 CheatedCount;\n\tstatic int32 ShowChaseStatOnScreen;\n\tstatic int32 PamphletMissionPassed;\n\tstatic bool abSonyCDs[1];\n\tstatic int32 BloodRingKills;\n\tstatic int32 BloodRingTime;\n\tstatic float FavoriteRadioStationList[NUM_RADIOS];\n\tstatic int32 Sprayings;\n\tstatic float AutoPaintingBudget;\n\tstatic int32 NoMoreHurricanes;\n\tstatic float FashionBudget;\n\tstatic float PropertyBudget;\n\tstatic float WeaponBudget;\n\tstatic int32 SafeHouseVisits;\n\tstatic int32 TyresPopped;\n\n\tstatic int32 LongestWheelie;\n\tstatic int32 LongestStoppie;\n\tstatic int32 Longest2Wheel;\n\tstatic float LongestWheelieDist;\n\tstatic float LongestStoppieDist;\n\tstatic float Longest2WheelDist;\n\npublic:\n\tstatic void Init(void);\n\tstatic void RegisterFastestTime(int32, int32);\n\tstatic void RegisterHighestScore(int32, int32);\n\tstatic void RegisterBestPosition(int32, int32);\n\tstatic void AnotherLifeSavedWithAmbulance();\n\tstatic void AnotherCriminalCaught();\n\tstatic void RegisterLevelAmbulanceMission(int32);\n\tstatic void RegisterLevelVigilanteMission(int32);\n\tstatic void RegisterLevelFireMission(int32);\n\tstatic void AnotherFireExtinguished();\n\tstatic wchar *FindCriminalRatingString();\n\tstatic wchar *FindChaseString(float fMediaLevel);\n\tstatic void AnotherKillFrenzyPassed();\n\tstatic void SetTotalNumberKillFrenzies(int32);\n\tstatic void SetTotalNumberMissions(int32);\n\tstatic void CheckPointReachedSuccessfully() { TotalLegitimateKills += KillsSinceLastCheckpoint; KillsSinceLastCheckpoint = 0; };\n\tstatic void CheckPointReachedUnsuccessfully() { KillsSinceLastCheckpoint = 0; };\n\tstatic int32 FindCriminalRatingNumber();\n\tstatic void SaveStats(uint8 *buf, uint32 *size);\n\tstatic void LoadStats(uint8 *buf, uint32 size);\n\tstatic float GetPercentageProgress();\n\n\tstatic void MoneySpentOnWeapons(int32);\n\tstatic void MoneySpentOnProperty(int32);\n\tstatic void MoneySpentOnAutoPainting(int32);\n\tstatic void MoneySpentOnFashion(int32);\n\n\tstatic void NumOfVisitsFromLoanSharks(int32);\n\tstatic void NumOfStoresKnockedOff(int32);\n\tstatic void NumOfMovieStunts(int32);\n\tstatic void NumOfAssassinations(int32);\n\tstatic void NumOfPizzasDelivered(int32);\n\tstatic void NumOfGarbagePickups(int32);\n\tstatic void NumOfIceCreamSold(int32);\n\tstatic void AddNumBloodRingKills(int32);\n\n\tstatic void LongestTimeInBloodRing(int32);\n\tstatic void AddPropertyAsOwned(int32);\n\tstatic void PopulateFavoriteRadioStationList();\n\tstatic float GetFavoriteRadioStationList(int32);\n\tstatic void BuildStatLine(Const char *, void *, int, void *, int);\n\tstatic int ConstructStatLine(int);\n};\n"
  },
  {
    "path": "src/core/Streaming.cpp",
    "content": "#include \"common.h\"\n\n#include \"General.h\"\n#include \"Pad.h\"\n#include \"Hud.h\"\n#include \"Text.h\"\n#include \"Clock.h\"\n#include \"Renderer.h\"\n#include \"ModelInfo.h\"\n#include \"TxdStore.h\"\n#include \"ModelIndices.h\"\n#include \"Pools.h\"\n#include \"Wanted.h\"\n#include \"Directory.h\"\n#include \"RwHelper.h\"\n#include \"World.h\"\n#include \"Entity.h\"\n#include \"FileMgr.h\"\n#include \"FileLoader.h\"\n#include \"Zones.h\"\n#include \"Radar.h\"\n#include \"Camera.h\"\n#include \"Record.h\"\n#include \"CarCtrl.h\"\n#include \"Population.h\"\n#include \"Gangs.h\"\n#include \"CutsceneMgr.h\"\n#include \"CdStream.h\"\n#include \"Streaming.h\"\n#include \"Replay.h\"\n#include \"main.h\"\n#include \"ColStore.h\"\n#include \"DMAudio.h\"\n#include \"Script.h\"\n#include \"MemoryMgr.h\"\n#include \"MemoryHeap.h\"\n#include \"Font.h\"\n#include \"Frontend.h\"\n#include \"VarConsole.h\"\n\nbool CStreaming::ms_disableStreaming;\nbool CStreaming::ms_bLoadingBigModel;\nint32 CStreaming::ms_numModelsRequested;\nCStreamingInfo CStreaming::ms_aInfoForModel[NUMSTREAMINFO];\nCStreamingInfo CStreaming::ms_startLoadedList;\nCStreamingInfo CStreaming::ms_endLoadedList;\nCStreamingInfo CStreaming::ms_startRequestedList;\nCStreamingInfo CStreaming::ms_endRequestedList;\nint32 CStreaming::ms_oldSectorX;\nint32 CStreaming::ms_oldSectorY;\nint32 CStreaming::ms_streamingBufferSize;\n#ifndef ONE_THREAD_PER_CHANNEL\nint8 *CStreaming::ms_pStreamingBuffer[2];\n#else\nint8 *CStreaming::ms_pStreamingBuffer[4];\n#endif\nsize_t CStreaming::ms_memoryUsed;\nCStreamingChannel CStreaming::ms_channel[2];\nint32 CStreaming::ms_channelError;\nint32 CStreaming::ms_numVehiclesLoaded;\nint32 CStreaming::ms_numPedsLoaded;\nint32 CStreaming::ms_vehiclesLoaded[MAXVEHICLESLOADED];\nint32 CStreaming::ms_lastVehicleDeleted;\nbool CStreaming::ms_bIsPedFromPedGroupLoaded[NUMMODELSPERPEDGROUP];\nCDirectory *CStreaming::ms_pExtraObjectsDir;\nint32 CStreaming::ms_numPriorityRequests;\nint32 CStreaming::ms_currentPedGrp;\nint32 CStreaming::ms_currentPedLoading;\nint32 CStreaming::ms_lastCullZone;\nuint16 CStreaming::ms_loadedGangs;\nuint16 CStreaming::ms_loadedGangCars;\nint32 CStreaming::ms_imageOffsets[NUMCDIMAGES];\nint32 CStreaming::ms_lastImageRead;\nint32 CStreaming::ms_imageSize;\nsize_t CStreaming::ms_memoryAvailable;\n\nint32 desiredNumVehiclesLoaded = 12;\n\nCEntity *pIslandLODmainlandEntity;\nCEntity *pIslandLODbeachEntity;\nint32 islandLODmainland;\nint32 islandLODbeach;\n\n#ifndef MASTER\nbool gbPrintStats;\nbool gbPrintVehiclesInMemory;  // TODO\nbool gbPrintStreamingBuffer; // TODO\n#endif\n\nbool\nCStreamingInfo::GetCdPosnAndSize(uint32 &posn, uint32 &size)\n{\n\tif(m_size == 0)\n\t\treturn false;\n\tposn = m_position;\n\tsize = m_size;\n\treturn true;\n}\n\nvoid\nCStreamingInfo::SetCdPosnAndSize(uint32 posn, uint32 size)\n{\n\tm_position = posn;\n\tm_size = size;\n}\n\nvoid\nCStreamingInfo::AddToList(CStreamingInfo *link)\n{\n\t// Insert this after link\n\tm_next = link->m_next;\n\tm_prev = link;\n\tlink->m_next = this;\n\tm_next->m_prev = this;\n}\n\nvoid\nCStreamingInfo::RemoveFromList(void)\n{\n\tm_next->m_prev = m_prev;\n\tm_prev->m_next = m_next;\n\tm_next = nil;\n\tm_prev = nil;\n}\n\nvoid\nCStreaming::Init2(void)\n{\n\tint i;\n\n\tfor(i = 0; i < NUMSTREAMINFO; i++){\n\t\tms_aInfoForModel[i].m_loadState = STREAMSTATE_NOTLOADED;\n\t\tms_aInfoForModel[i].m_next = nil;\n\t\tms_aInfoForModel[i].m_prev = nil;\n\t\tms_aInfoForModel[i].m_nextID = -1;\n\t\tms_aInfoForModel[i].m_size = 0;\n\t\tms_aInfoForModel[i].m_position = 0;\n\t}\n\n\tms_channelError = -1;\n\n\t// init lists\n\n\tms_startLoadedList.m_next = &ms_endLoadedList;\n\tms_startLoadedList.m_prev = nil;\n\tms_endLoadedList.m_prev = &ms_startLoadedList;\n\tms_endLoadedList.m_next = nil;\n\n\tms_startRequestedList.m_next = &ms_endRequestedList;\n\tms_startRequestedList.m_prev = nil;\n\tms_endRequestedList.m_prev = &ms_startRequestedList;\n\tms_endRequestedList.m_next = nil;\n\n\t// init misc\n\n\tms_oldSectorX = 0;\n\tms_oldSectorY = 0;\n\tms_streamingBufferSize = 0;\n\tms_disableStreaming = false;\n\tms_memoryUsed = 0;\n\tms_bLoadingBigModel = false;\n\n\t// init channels\n\n\tms_channel[0].state = CHANNELSTATE_IDLE;\n\tms_channel[1].state = CHANNELSTATE_IDLE;\n\tfor(i = 0; i < 4; i++){\n\t\tms_channel[0].streamIds[i] = -1;\n\t\tms_channel[0].offsets[i] = -1;\n\t\tms_channel[1].streamIds[i] = -1;\n\t\tms_channel[1].offsets[i] = -1;\n\t}\n\n\t// init stream info, mark things that are already loaded\n\n\tfor(i = 0; i < MODELINFOSIZE; i++){\n\t\tCBaseModelInfo *mi = CModelInfo::GetModelInfo(i);\n\t\tif(mi && mi->GetRwObject()){\n\t\t\tms_aInfoForModel[i].m_loadState = STREAMSTATE_LOADED;\n\t\t\tms_aInfoForModel[i].m_flags = STREAMFLAGS_DONT_REMOVE;\n\t\t\tif(mi->IsSimple())\n\t\t\t\t((CSimpleModelInfo*)mi)->m_alpha = 255;\n\t\t}\n\t}\n\n\tfor(i = 0; i < TXDSTORESIZE; i++)\n\t\tif(CTxdStore::GetSlot(i) && CTxdStore::GetSlot(i)->texDict)\n\t\t\tms_aInfoForModel[i + STREAM_OFFSET_TXD].m_loadState = STREAMSTATE_LOADED;\n\n\n\tfor(i = 0; i < MAXVEHICLESLOADED; i++)\n\t\tms_vehiclesLoaded[i] = -1;\n\tms_numVehiclesLoaded = 0;\n\tms_numPedsLoaded = 8;\n\n\tfor(i = 0; i < ARRAY_SIZE(ms_bIsPedFromPedGroupLoaded); i++)\n\t\tms_bIsPedFromPedGroupLoaded[i] = false;\n\n\tms_pExtraObjectsDir = new CDirectory(EXTRADIRSIZE);\n\tms_numPriorityRequests = 0;\n\tms_currentPedGrp = -1;\n\tms_lastCullZone = -1;\t\t// unused because RemoveModelsNotVisibleFromCullzone is gone\n\tms_loadedGangs = 0;\n\tms_currentPedLoading = NUMMODELSPERPEDGROUP;\t// unused, whatever it is\n\n\tLoadCdDirectory();\n\n\t// allocate streaming buffers\n\tif(ms_streamingBufferSize & 1) ms_streamingBufferSize++;\n#ifndef ONE_THREAD_PER_CHANNEL\n\tms_pStreamingBuffer[0] = (int8*)RwMallocAlign(ms_streamingBufferSize*CDSTREAM_SECTOR_SIZE, CDSTREAM_SECTOR_SIZE);\n\tms_streamingBufferSize /= 2;\n\tms_pStreamingBuffer[1] = ms_pStreamingBuffer[0] + ms_streamingBufferSize*CDSTREAM_SECTOR_SIZE;\n#else\n\tms_pStreamingBuffer[0] = (int8*)RwMallocAlign(ms_streamingBufferSize*2*CDSTREAM_SECTOR_SIZE, CDSTREAM_SECTOR_SIZE);\n\tms_streamingBufferSize /= 2;\n\tms_pStreamingBuffer[1] = ms_pStreamingBuffer[0] + ms_streamingBufferSize*CDSTREAM_SECTOR_SIZE;\n\tms_pStreamingBuffer[2] = ms_pStreamingBuffer[1] + ms_streamingBufferSize*CDSTREAM_SECTOR_SIZE;\n\tms_pStreamingBuffer[3] = ms_pStreamingBuffer[2] + ms_streamingBufferSize*CDSTREAM_SECTOR_SIZE;\n#endif\n\tdebug(\"Streaming buffer size is %d sectors\", ms_streamingBufferSize);\n\n\t// PC only, figure out how much memory we got\n#ifdef GTA_PC\n#define MB (1024*1024)\n#ifdef FIX_BUGS\n\t// do what gta3 does\n\textern size_t _dwMemAvailPhys;\n\tms_memoryAvailable = (_dwMemAvailPhys - 10*MB)/2;\n\tif(ms_memoryAvailable < 65*MB)\n\t\tms_memoryAvailable = 65*MB;\n\tdesiredNumVehiclesLoaded = (int32)((ms_memoryAvailable / MB - 65) / 3 + 12);\n\tif(desiredNumVehiclesLoaded > MAXVEHICLESLOADED)\n\t\tdesiredNumVehiclesLoaded = MAXVEHICLESLOADED;\n#else\n\tms_memoryAvailable = 65 * MB;\n\tdesiredNumVehiclesLoaded = 25;\n\tdebug(\"Memory allocated to Streaming is %zuMB\", ms_memoryAvailable/MB); // original modifier was %d\n#endif\n#undef MB\n#endif\n\n\t// find island LODs\n\n\tpIslandLODmainlandEntity = nil;\n\tpIslandLODbeachEntity = nil;\n\tislandLODmainland = -1;\n\tislandLODbeach = -1;\n\tCModelInfo::GetModelInfo(\"IslandLODmainland\", &islandLODmainland);\n\tCModelInfo::GetModelInfo(\"IslandLODbeach\", &islandLODbeach);\n\n#ifndef MASTER\n\tVarConsole.Add(\"Streaming Debug\", &gbPrintStats, true);\n\tVarConsole.Add(\"Streaming Vehicle Debug\", &gbPrintVehiclesInMemory, true);\n\tVarConsole.Add(\"Printf Streaming Buffer contents\", &gbPrintStreamingBuffer, true);\n#endif\n}\n\nvoid\nCStreaming::Init(void)\n{\n#ifdef USE_TXD_CDIMAGE\n\tif(!CanVideoCardDoDXT()){\n\t\tint txdHandle = CFileMgr::OpenFile(\"MODELS\\\\TXD.IMG\", \"r\");\n\t\tif (txdHandle)\n\t\t\tCFileMgr::CloseFile(txdHandle);\n\t\tif (!CheckVideoCardCaps() && txdHandle) {\n\t\t\tCdStreamAddImage(\"MODELS\\\\TXD.IMG\");\n\t\t\tCStreaming::Init2();\n\t\t} else {\n\t\t\tCStreaming::Init2();\n\t\t\tif (CreateTxdImageForVideoCard()) {\n\t\t\t\tCStreaming::Shutdown();\n\t\t\t\tCdStreamAddImage(\"MODELS\\\\TXD.IMG\");\n\t\t\t\tCStreaming::Init2();\n\t\t\t}\n\t\t}\n\t} else\n\t\tCStreaming::Init2();\n#else\n\tCStreaming::Init2();\n#endif\n}\n\nvoid\nCStreaming::ReInit(void)\n{\n\tint i;\n\tCStreaming::FlushRequestList();\n\tCStreaming::DeleteAllRwObjects();\n\tCStreaming::RemoveAllUnusedModels();\n\tfor(i = 0; i < MODELINFOSIZE; i++)\n\t\tif(CModelInfo::GetModelInfo(i) && ms_aInfoForModel[i].m_flags & STREAMFLAGS_SCRIPTOWNED)\n\t\t\tSetMissionDoesntRequireModel(i);\n\tCStreaming::ms_disableStreaming = false;\n}\n\nvoid\nCStreaming::Shutdown(void)\n{\n\tRwFreeAlign(ms_pStreamingBuffer[0]);\n\tms_streamingBufferSize = 0;\n\tif(ms_pExtraObjectsDir) {\n\t\tdelete ms_pExtraObjectsDir;\n#ifdef FIX_BUGS\n\t\tms_pExtraObjectsDir = nil;\n#endif\n\t}\n}\n\n#ifndef MASTER\nuint64 timeProcessingTXD;\nuint64 timeProcessingDFF;\n#endif\n\nvoid\nCStreaming::Update(void)\n{\n\tCStreamingInfo *si, *prev;\n\tbool requestedSubway = false;\n\n#ifndef MASTER\n\ttimeProcessingTXD = 0;\n\ttimeProcessingDFF = 0;\n#endif\n\n\tUpdateMemoryUsed();\n\n\tif(ms_channelError != -1){\n\t\tRetryLoadFile(ms_channelError);\n\t\treturn;\n\t}\n\n\tif(CTimer::GetIsPaused())\n\t\treturn;\n\n\tLoadBigBuildingsWhenNeeded();\n\tif(!ms_disableStreaming && TheCamera.GetPosition().z < 55.0f)\n\t\tAddModelsToRequestList(TheCamera.GetPosition(), 0);\n\n\tDeleteFarAwayRwObjects(TheCamera.GetPosition());\n\n\tif(!ms_disableStreaming &&\n\t   !CCutsceneMgr::IsCutsceneProcessing() &&\n\t   ms_numModelsRequested < 5 &&\n\t   !CRenderer::m_loadingPriority &&\n\t   CGame::currArea == AREA_MAIN_MAP &&\n\t   !CReplay::IsPlayingBack()){\n\t\tStreamVehiclesAndPeds();\n\t\tStreamZoneModels(FindPlayerCoors());\n\t}\n\n\tLoadRequestedModels();\n\n\tif(CWorld::Players[0].m_pRemoteVehicle){\n\t\tCColStore::AddCollisionNeededAtPosn(FindPlayerCoors());\n\t\tCColStore::LoadCollision(CWorld::Players[0].m_pRemoteVehicle->GetPosition());\n\t\tCColStore::EnsureCollisionIsInMemory(CWorld::Players[0].m_pRemoteVehicle->GetPosition());\n\t}else{\n\t\tCColStore::LoadCollision(FindPlayerCoors());\n\t\tCColStore::EnsureCollisionIsInMemory(FindPlayerCoors());\n\t}\n\n\t// TODO: PrintRequestList\n\t//if (CPad::GetPad(1)->GetLeftShoulder2JustDown() && CPad::GetPad(1)->GetRightShoulder1() && CPad::GetPad(1)->GetRightShoulder2())\n\t//\tPrintRequestList();\n\n\tfor(si = ms_endRequestedList.m_prev; si != &ms_startRequestedList; si = prev){\n\t\tprev = si->m_prev;\n\t\tif((si->m_flags & (STREAMFLAGS_KEEP_IN_MEMORY|STREAMFLAGS_PRIORITY)) == 0)\n\t\t\tRemoveModel(si - ms_aInfoForModel);\n\t}\n}\n\nvoid\nCStreaming::LoadCdDirectory(void)\n{\n\tchar dirname[132];\n\tint i;\n\n#ifdef GTA_PC\n\tms_imageOffsets[0] = 0;\n\tms_imageOffsets[1] = -1;\n\tms_imageOffsets[2] = -1;\n\tms_imageOffsets[3] = -1;\n\tms_imageOffsets[4] = -1;\n\tms_imageOffsets[5] = -1;\n\tms_imageSize = GetGTA3ImgSize();\n\t// PS2 uses CFileMgr::GetCdFile on all IMG files to fill the array\n#endif\n\n\ti = CdStreamGetNumImages();\n\twhile(i-- >= 1){\n\t\tstrcpy(dirname, CdStreamGetImageName(i));\n\t\tstrncpy(strrchr(dirname, '.') + 1, \"DIR\", 3);\n\t\tLoadCdDirectory(dirname, i);\n\t}\n\n\tms_lastImageRead = 0;\n\tms_imageSize /= CDSTREAM_SECTOR_SIZE;\n}\n\nvoid\nCStreaming::LoadCdDirectory(const char *dirname, int n)\n{\n\tint fd, lastID, imgSelector;\n\tint modelId;\n\tCDirectory::DirectoryInfo direntry;\n\tchar *dot;\n\n\tlastID = -1;\n\tfd = CFileMgr::OpenFile(dirname, \"rb\");\n\tassert(fd > 0);\n\n\timgSelector = n<<24;\n\tassert(sizeof(direntry) == 32);\n\twhile(CFileMgr::Read(fd, (char*)&direntry, sizeof(direntry))){\n\t\tbool bAddToStreaming = false;\n\n\t\tif(direntry.size > (uint32)ms_streamingBufferSize)\n\t\t\tms_streamingBufferSize = direntry.size;\n\t\tdirentry.name[23] = '\\0';\n\t\tdot = strchr(direntry.name, '.');\n\t\tif(dot == nil || dot-direntry.name > 20){\n\t\t\tdebug(\"%s is too long\\n\", direntry.name);\n\t\t\tlastID = -1;\n\t\t\tcontinue;\n\t\t}\n\n\t\t*dot = '\\0';\n\n\t\tif(strncasecmp(dot+1, \"DFF\", 3) == 0){\n\t\t\tif(CModelInfo::GetModelInfo(direntry.name, &modelId)){\n\t\t\t\tbAddToStreaming = true;\n\t\t\t}else{\n#ifdef FIX_BUGS\n\t\t\t\t// remember which cdimage this came from\n\t\t\t\tms_pExtraObjectsDir->AddItem(direntry, n);\n#else\n\t\t\t\tms_pExtraObjectsDir->AddItem(direntry);\n#endif\n\t\t\t\tlastID = -1;\n\t\t\t}\n\t\t}else if(strncasecmp(dot+1, \"TXD\", 3) == 0){\n\t\t\tmodelId = CTxdStore::FindTxdSlot(direntry.name);\n\t\t\tif(modelId == -1)\n\t\t\t\tmodelId = CTxdStore::AddTxdSlot(direntry.name);\n\t\t\tmodelId += STREAM_OFFSET_TXD;\n\t\t\tbAddToStreaming = true;\n\t\t}else if(strncasecmp(dot+1, \"COL\", 3) == 0){\n\t\t\tmodelId = CColStore::FindColSlot(direntry.name);\n\t\t\tif(modelId == -1)\n\t\t\t\tmodelId = CColStore::AddColSlot(direntry.name);\n\t\t\tmodelId += STREAM_OFFSET_COL;\n\t\t\tbAddToStreaming = true;\n\t\t}else if(strncasecmp(dot+1, \"IFP\", 3) == 0){\n\t\t\tmodelId = CAnimManager::RegisterAnimBlock(direntry.name);\n\t\t\tmodelId += STREAM_OFFSET_ANIM;\n\t\t\tbAddToStreaming = true;\n\t\t}else{\n\t\t\t*dot = '.';\n\t\t\tlastID = -1;\n\t\t}\n\n\t\tif(bAddToStreaming){\n\t\t\tif(ms_aInfoForModel[modelId].GetCdSize()){\n\t\t\t\tdebug(\"%s.%s appears more than once in %s\\n\", direntry.name, dot+1, dirname);\n\t\t\t\tlastID = -1;\n\t\t\t}else{\n\t\t\t\tdirentry.offset |= imgSelector;\n\t\t\t\tms_aInfoForModel[modelId].SetCdPosnAndSize(direntry.offset, direntry.size);\n\t\t\t\tif(lastID != -1)\n\t\t\t\t\tms_aInfoForModel[lastID].m_nextID = modelId;\n\t\t\t\tlastID = modelId;\n\t\t\t}\n\t\t}\n\t}\n\n\tCFileMgr::CloseFile(fd);\n}\n\nstatic char*\nGetObjectName(int streamId)\n{\n\tstatic char objname[32];\n\tif(streamId < STREAM_OFFSET_TXD)\n\t\tsprintf(objname, \"%s.dff\", CModelInfo::GetModelInfo(streamId)->GetModelName());\n\telse if(streamId >= STREAM_OFFSET_TXD && streamId < STREAM_OFFSET_COL)\n\t\tsprintf(objname, \"%s.txd\", CTxdStore::GetTxdName(streamId-STREAM_OFFSET_TXD));\n\telse if(streamId >= STREAM_OFFSET_COL && streamId < STREAM_OFFSET_ANIM)\n\t\tsprintf(objname, \"%s.col\", CColStore::GetColName(streamId-STREAM_OFFSET_COL));\n\telse{\n\t\tassert(streamId < NUMSTREAMINFO);\n\t\tsprintf(objname, \"%s.ifp\", CAnimManager::GetAnimationBlock(streamId-STREAM_OFFSET_ANIM)->name);\n\t}\n\treturn objname;\n}\n\n#ifdef USE_CUSTOM_ALLOCATOR\nRpAtomic*\nRegisterAtomicMemPtrsCB(RpAtomic *atomic, void *data)\n{\n\t// empty because we expect models to be pre-instanced\n\treturn atomic;\n}\n#endif\n\nbool\nCStreaming::ConvertBufferToObject(int8 *buf, int32 streamId)\n{\n\tRwMemory mem;\n\tRwStream *stream;\n\tint cdsize;\n\tuint32 startTime, endTime, timeDiff;\n\tCBaseModelInfo *mi;\n\tbool success;\n\n\tstartTime = CTimer::GetCurrentTimeInCycles() / CTimer::GetCyclesPerMillisecond();\n\n\tcdsize = ms_aInfoForModel[streamId].GetCdSize();\n\tmem.start = (uint8*)buf;\n\tmem.length = cdsize * CDSTREAM_SECTOR_SIZE;\n\tstream = RwStreamOpen(rwSTREAMMEMORY, rwSTREAMREAD, &mem);\n\n\tif(streamId < STREAM_OFFSET_TXD){\n\t\t// Model\n\t\tmi = CModelInfo::GetModelInfo(streamId);\n\n\t\t// Txd and anim have to be loaded\n\t\tint animId = mi->GetAnimFileIndex();\n#ifdef FIX_BUGS\n\t\tif(!HasTxdLoaded(mi->GetTxdSlot()) ||\n#else\n\t\t// texDict will exist even if only first part has loaded\n\t\tif(CTxdStore::GetSlot(mi->GetTxdSlot())->texDict == nil ||\n#endif\n\t\t   animId != -1 && !CAnimManager::GetAnimationBlock(animId)->isLoaded){\n\t\t\tRemoveModel(streamId);\n\t\t\tReRequestModel(streamId);\n\t\t\tRwStreamClose(stream, &mem);\n\t\t\treturn false;\n\t\t}\n\n\t\t// Set Txd and anims to use\n\t\tCTxdStore::AddRef(mi->GetTxdSlot());\n#if GTA_VERSION > GTAVC_PS2\n\t\tif(animId != -1)\n\t\t\tCAnimManager::AddAnimBlockRef(animId);\n#endif\n\n\t\tPUSH_MEMID(MEMID_STREAM_MODELS);\n\t\tCTxdStore::SetCurrentTxd(mi->GetTxdSlot());\n\t\tif(mi->IsSimple()){\n\t\t\tsuccess = CFileLoader::LoadAtomicFile(stream, streamId);\n\t\t\t// TODO(MIAMI)? complain if file is not pre-instanced. we hardly are interested in that\n\t\t} else if (mi->GetModelType() == MITYPE_VEHICLE) {\n\t\t\t// load vehicles in two parts\n\t\t\tCModelInfo::GetModelInfo(streamId)->AddRef();\n\t\t\tsuccess = CFileLoader::StartLoadClumpFile(stream, streamId);\n\t\t\tif(success)\n\t\t\t\tms_aInfoForModel[streamId].m_loadState = STREAMSTATE_STARTED;\n\t\t}else{\n\t\t\tsuccess = CFileLoader::LoadClumpFile(stream, streamId);\n#ifdef USE_CUSTOM_ALLOCATOR\n\t\t\tif(success)\n\t\t\t\tRpClumpForAllAtomics((RpClump*)mi->GetRwObject(), RegisterAtomicMemPtrsCB, nil);\n#endif\n\t\t}\n\t\tPOP_MEMID();\n\t\tUpdateMemoryUsed();\n\n\t\t// Txd and anims no longer needed unless we only read part of the file\n\t\tif(ms_aInfoForModel[streamId].m_loadState != STREAMSTATE_STARTED){\n\t\t\tCTxdStore::RemoveRefWithoutDelete(mi->GetTxdSlot());\n#if GTA_VERSION > GTAVC_PS2\n\t\t\tif(animId != -1)\n\t\t\t\tCAnimManager::RemoveAnimBlockRefWithoutDelete(animId);\n#endif\n\t\t}\n\n\t\tif(!success){\n\t\t\tdebug(\"Failed to load %s\\n\", CModelInfo::GetModelInfo(streamId)->GetModelName());\n\t\t\tRemoveModel(streamId);\n\t\t\tReRequestModel(streamId);\n\t\t\tRwStreamClose(stream, &mem);\n\t\t\treturn false;\n\t\t}\n\t}else if(streamId >= STREAM_OFFSET_TXD && streamId < STREAM_OFFSET_COL){\n\t\t// Txd\n\t\tif((ms_aInfoForModel[streamId].m_flags & STREAMFLAGS_KEEP_IN_MEMORY) == 0 &&\n\t\t   !IsTxdUsedByRequestedModels(streamId - STREAM_OFFSET_TXD)){\n\t\t\tRemoveModel(streamId);\n\t\t\tRwStreamClose(stream, &mem);\n\t\t\treturn false;\n\t\t}\n\n\t\tPUSH_MEMID(MEMID_STREAM_TEXUTRES);\n\t\tif(ms_bLoadingBigModel || cdsize > 200){\n\t\t\tsuccess = CTxdStore::StartLoadTxd(streamId - STREAM_OFFSET_TXD, stream);\n\t\t\tif(success)\n\t\t\t\tms_aInfoForModel[streamId].m_loadState = STREAMSTATE_STARTED;\n\t\t}else\n\t\t        success = CTxdStore::LoadTxd(streamId - STREAM_OFFSET_TXD, stream);\n\t\tPOP_MEMID();\n\t\tUpdateMemoryUsed();\n\n\t\tif(!success){\n\t\t\tdebug(\"Failed to load %s.txd\\n\", CTxdStore::GetTxdName(streamId - STREAM_OFFSET_TXD));\n\t\t\tRemoveModel(streamId);\n\t\t\tReRequestModel(streamId);\n\t\t\tRwStreamClose(stream, &mem);\n\t\t\treturn false;\n\t\t}\n\t}else if(streamId >= STREAM_OFFSET_COL && streamId < STREAM_OFFSET_ANIM){\n\t\tPUSH_MEMID(MEMID_STREAM_COLLISION);\n\t\tbool success = CColStore::LoadCol(streamId-STREAM_OFFSET_COL, mem.start, mem.length);\n\t\tPOP_MEMID();\n\t\tif(!success){\n\t\t\tdebug(\"Failed to load %s.col\\n\", CColStore::GetColName(streamId - STREAM_OFFSET_COL));\n\t\t\tRemoveModel(streamId);\n\t\t\tReRequestModel(streamId);\n\t\t\tRwStreamClose(stream, &mem);\n\t\t\treturn false;\n\t\t}\n\t}else if(streamId >= STREAM_OFFSET_ANIM){\n\t\tassert(streamId < NUMSTREAMINFO);\n\t\tif((ms_aInfoForModel[streamId].m_flags & STREAMFLAGS_KEEP_IN_MEMORY) == 0 &&\n\t\t   !AreAnimsUsedByRequestedModels(streamId - STREAM_OFFSET_ANIM)){\n\t\t\tRemoveModel(streamId);\n\t\t\tRwStreamClose(stream, &mem);\n\t\t\treturn false;\n\t\t}\n\t\tPUSH_MEMID(MEMID_STREAM_ANIMATION);\n\t\tCAnimManager::LoadAnimFile(stream, true, nil);\n\t\tCAnimManager::CreateAnimAssocGroups();\n\t\tPOP_MEMID();\n\t}\n\n\tRwStreamClose(stream, &mem);\n\n\tif(streamId < STREAM_OFFSET_TXD){\n\t\t// Model\n\t\t// Vehicles and Peds not in loaded list\n\t\tif (mi->GetModelType() != MITYPE_VEHICLE && mi->GetModelType() != MITYPE_PED) {\n\t\t\tCSimpleModelInfo *smi = (CSimpleModelInfo*)mi;\n\n\t\t\t// Set fading for some objects\n\t\t\tif(mi->IsSimple() && !smi->m_isBigBuilding){\n\t\t\t\tif(ms_aInfoForModel[streamId].m_flags & STREAMFLAGS_NOFADE)\n\t\t\t\t\tsmi->m_alpha = 255;\n\t\t\t\telse\n\t\t\t\t\tsmi->m_alpha = 0;\n\t\t\t}\n\n\t\t\tif(CanRemoveModel(streamId))\n\t\t\t\tms_aInfoForModel[streamId].AddToList(&ms_startLoadedList);\n\t\t}\n\t}else if(streamId >= STREAM_OFFSET_TXD && streamId < STREAM_OFFSET_COL ||\n\t         streamId >= STREAM_OFFSET_ANIM){\n\t\tassert(streamId < NUMSTREAMINFO);\n\t\t// Txd and anims\n\t\tif(CanRemoveModel(streamId))\n\t\t\tms_aInfoForModel[streamId].AddToList(&ms_startLoadedList);\n\t}\n\n\t// Mark objects as loaded\n\tif(ms_aInfoForModel[streamId].m_loadState != STREAMSTATE_STARTED){\n\t\tms_aInfoForModel[streamId].m_loadState = STREAMSTATE_LOADED;\n#ifndef USE_CUSTOM_ALLOCATOR\n\t\tms_memoryUsed += ms_aInfoForModel[streamId].GetCdSize() * CDSTREAM_SECTOR_SIZE;\n#endif\n\t}\n\n\tendTime = CTimer::GetCurrentTimeInCycles() / CTimer::GetCyclesPerMillisecond();\n\ttimeDiff = endTime - startTime;\n\tif(timeDiff > 5)\n\t\tdebug(\"%s took %d ms\\n\", GetObjectName(streamId), timeDiff);\n\n\treturn true;\n}\n\nbool\nCStreaming::FinishLoadingLargeFile(int8 *buf, int32 streamId)\n{\n\tRwMemory mem;\n\tRwStream *stream;\n\tuint32 startTime, endTime, timeDiff;\n\tCBaseModelInfo *mi;\n\tbool success;\n\n\tstartTime = CTimer::GetCurrentTimeInCycles() / CTimer::GetCyclesPerMillisecond();\n\n\tif(ms_aInfoForModel[streamId].m_loadState != STREAMSTATE_STARTED){\n\t\tif(streamId < STREAM_OFFSET_TXD)\n\t\t\tCModelInfo::GetModelInfo(streamId)->RemoveRef();\n\t\treturn false;\n\t}\n\n\tmem.start = (uint8*)buf;\n\tmem.length = ms_aInfoForModel[streamId].GetCdSize() * CDSTREAM_SECTOR_SIZE;\n\tstream = RwStreamOpen(rwSTREAMMEMORY, rwSTREAMREAD, &mem);\n\n\tif(streamId < STREAM_OFFSET_TXD){\n\t\t// Model\n\t\tmi = CModelInfo::GetModelInfo(streamId);\n\t\tPUSH_MEMID(MEMID_STREAM_MODELS);\n\t\tCTxdStore::SetCurrentTxd(mi->GetTxdSlot());\n\t\tsuccess = CFileLoader::FinishLoadClumpFile(stream, streamId);\n\t\tif(success){\n#ifdef USE_CUSTOM_ALLOCATOR\n\t\t\tRpClumpForAllAtomics((RpClump*)mi->GetRwObject(), RegisterAtomicMemPtrsCB, nil);\n#endif\n\t\t\tsuccess = AddToLoadedVehiclesList(streamId);\n\t\t}\n\t\tPOP_MEMID();\n\t\tmi->RemoveRef();\n\t\tCTxdStore::RemoveRefWithoutDelete(mi->GetTxdSlot());\n#if GTA_VERSION > GTAVC_PS2\n\t\tif(mi->GetAnimFileIndex() != -1)\n\t\t\tCAnimManager::RemoveAnimBlockRefWithoutDelete(mi->GetAnimFileIndex());\n#endif\n\t}else if(streamId >= STREAM_OFFSET_TXD && streamId < STREAM_OFFSET_COL){\n\t\t// Txd\n\t\tCTxdStore::AddRef(streamId - STREAM_OFFSET_TXD);\n\t\tPUSH_MEMID(MEMID_STREAM_TEXUTRES);\n\t\tsuccess = CTxdStore::FinishLoadTxd(streamId - STREAM_OFFSET_TXD, stream);\n\t\tPOP_MEMID();\n\t\tCTxdStore::RemoveRefWithoutDelete(streamId - STREAM_OFFSET_TXD);\n\t}else{\n\t\tassert(0 && \"invalid streamId\");\n\t}\n\n\tRwStreamClose(stream, &mem);\n\n\tms_aInfoForModel[streamId].m_loadState = STREAMSTATE_LOADED;\n#ifndef USE_CUSTOM_ALLOCATOR\n\tms_memoryUsed += ms_aInfoForModel[streamId].GetCdSize() * CDSTREAM_SECTOR_SIZE;\n#endif\n\n\tif(!success){\n\t\tRemoveModel(streamId);\n\t\tReRequestModel(streamId);\n\t\tUpdateMemoryUsed();\n\t\treturn false;\n\t}\n\n\tUpdateMemoryUsed();\n\n\tendTime = CTimer::GetCurrentTimeInCycles() / CTimer::GetCyclesPerMillisecond();\n\ttimeDiff = endTime - startTime;\n\tif(timeDiff > 5)\n\t\tdebug(\"%s took %d ms\\n\", GetObjectName(streamId), timeDiff);\n\n\treturn true;\n}\n\nvoid\nCStreaming::RequestModel(int32 id, int32 flags)\n{\n\tCSimpleModelInfo *mi;\n\n\tif(ms_aInfoForModel[id].m_loadState == STREAMSTATE_INQUEUE){\n\t\t// updgrade to priority\n\t\tif(flags & STREAMFLAGS_PRIORITY && !ms_aInfoForModel[id].IsPriority()){\n\t\t\tms_numPriorityRequests++;\n\t\t\tms_aInfoForModel[id].m_flags |= STREAMFLAGS_PRIORITY;\n\t\t}\n\t}else if(ms_aInfoForModel[id].m_loadState != STREAMSTATE_NOTLOADED){\n\t\tflags &= ~STREAMFLAGS_PRIORITY;\n\t}\n\tms_aInfoForModel[id].m_flags |= flags;\n\n\tif(ms_aInfoForModel[id].m_loadState == STREAMSTATE_LOADED){\n\t\t// Already loaded, only check changed flags\n\n\t\tif(ms_aInfoForModel[id].m_flags & STREAMFLAGS_NOFADE && id < STREAM_OFFSET_TXD){\n\t\t\tmi = (CSimpleModelInfo*)CModelInfo::GetModelInfo(id);\n\t\t\tif(mi->IsSimple())\n\t\t\t\tmi->m_alpha = 255;\n\t\t}\n\n\t\t// reinsert into list\n\t\tif(ms_aInfoForModel[id].m_next){\n\t\t\tms_aInfoForModel[id].RemoveFromList();\n\t\t\tif(CanRemoveModel(id))\n\t\t\t\tms_aInfoForModel[id].AddToList(&ms_startLoadedList);\n\t\t}\n\t}else if(ms_aInfoForModel[id].m_loadState == STREAMSTATE_NOTLOADED ||\n\t         ms_aInfoForModel[id].m_loadState == STREAMSTATE_LOADED){\t// how can this be true again?\n\n\t\tif(ms_aInfoForModel[id].m_loadState == STREAMSTATE_NOTLOADED){\n\t\t\tif(id < STREAM_OFFSET_TXD){\n\t\t\t\tmi = (CSimpleModelInfo*)CModelInfo::GetModelInfo(id);\n\t\t\t\tRequestTxd(mi->GetTxdSlot(), flags);\n\t\t\t\tint anim = mi->GetAnimFileIndex();\n\t\t\t\tif(anim != -1)\n\t\t\t\t\tRequestAnim(anim, STREAMFLAGS_DEPENDENCY);\n\t\t\t}\n\t\t\tms_aInfoForModel[id].AddToList(&ms_startRequestedList);\n\t\t\tms_numModelsRequested++;\n\t\t\tif(flags & STREAMFLAGS_PRIORITY)\n\t\t\t\tms_numPriorityRequests++;\n\t\t}\n\n\t\tms_aInfoForModel[id].m_loadState = STREAMSTATE_INQUEUE;\n\t\tms_aInfoForModel[id].m_flags = flags;\n\t}\n}\n\n#define BIGBUILDINGFLAGS STREAMFLAGS_DONT_REMOVE\n\nvoid\nCStreaming::RequestBigBuildings(eLevelName level)\n{\n\tint i, n;\n\tCBuilding *b;\n\n\tn = CPools::GetBuildingPool()->GetSize()-1;\n\tfor(i = n; i >= 0; i--){\n\t\tb = CPools::GetBuildingPool()->GetSlot(i);\n\t\tif(b && b->bIsBIGBuilding\n#ifdef NO_ISLAND_LOADING\n\t\t   && (((FrontEndMenuManager.m_PrefsIslandLoading != CMenuManager::ISLAND_LOADING_LOW) && (b != pIslandLODmainlandEntity) &&\n\t\t        (b != pIslandLODbeachEntity)) ||\n\t\t       (b->m_level == level))\n#else\n\t\t   && b->m_level == level\n#endif\n\t\t\t)\n\t\t\tif(!b->bStreamBIGBuilding)\n\t\t\t\tRequestModel(b->GetModelIndex(), BIGBUILDINGFLAGS);\n\t}\n\tRequestIslands(level);\n}\n\nvoid\nCStreaming::RequestBigBuildings(eLevelName level, const CVector &pos)\n{\n\tint i, n;\n\tCBuilding *b;\n\n\tn = CPools::GetBuildingPool()->GetSize()-1;\n\tfor(i = n; i >= 0; i--){\n\t\tb = CPools::GetBuildingPool()->GetSlot(i);\n\t\tif(b && b->bIsBIGBuilding\n#ifdef NO_ISLAND_LOADING\n\t\t    && (((FrontEndMenuManager.m_PrefsIslandLoading != CMenuManager::ISLAND_LOADING_LOW) && (b != pIslandLODmainlandEntity) && (b != pIslandLODbeachEntity)\n\t\t\t\t) || (b->m_level == level))\n#else\n\t\t   && b->m_level == level\n#endif\n\t\t)\n\t\t\tif(b->bStreamBIGBuilding){\n\t\t\t\tif(CRenderer::ShouldModelBeStreamed(b, pos))\n\t\t\t\t\tRequestModel(b->GetModelIndex(), 0);\n\t\t\t}else\n\t\t\t\tRequestModel(b->GetModelIndex(), BIGBUILDINGFLAGS);\n\t}\n\tRequestIslands(level);\n}\n\nvoid\nCStreaming::InstanceBigBuildings(eLevelName level, const CVector &pos)\n{\n\tint i, n;\n\tCBuilding *b;\n\n\tn = CPools::GetBuildingPool()->GetSize()-1;\n\tfor(i = n; i >= 0; i--){\n\t\tb = CPools::GetBuildingPool()->GetSlot(i);\n\t\tif(b && b->bIsBIGBuilding && b->m_level == level &&\n\t\t   b->bStreamBIGBuilding && b->m_rwObject == nil)\n\t\t\tif(CRenderer::ShouldModelBeStreamed(b, pos))\n\t\t\t\tb->CreateRwObject();\n\t}\n}\n\nvoid\nCStreaming::InstanceLoadedModelsInSectorList(CPtrList &list)\n{\n\tCPtrNode *node;\n\tCEntity *e;\n\tfor(node = list.first; node; node = node->next) {\n\t\te = (CEntity *)node->item;\n\t\tif(IsAreaVisible(e->m_area) && e->m_rwObject == nil)\n\t\t\te->CreateRwObject();\n\t}\n}\n\nvoid\nCStreaming::InstanceLoadedModels(const CVector &pos)\n{\n\tint minX = CWorld::GetSectorIndexX(pos.x - 80.0f);\n\tif(minX <= 0) minX = 0;\n\n\tint minY = CWorld::GetSectorIndexY(pos.y - 80.0f);\n\tif(minY <= 0) minY = 0;\n\n\tint maxX = CWorld::GetSectorIndexX(pos.x + 80.0f);\n\tif(maxX >= NUMSECTORS_X) maxX = NUMSECTORS_X - 1;\n\n\tint maxY = CWorld::GetSectorIndexY(pos.y + 80.0f);\n\tif(maxY >= NUMSECTORS_Y) maxY = NUMSECTORS_Y - 1;\n\n\tint x, y;\n\tfor(y = minY; y <= maxY; y++){\n\t\tfor(x = minX; x <= maxX; x++){\n\t\t\tCSector *sector = CWorld::GetSector(x, y);\n\t\t\tInstanceLoadedModelsInSectorList(sector->m_lists[ENTITYLIST_BUILDINGS]);\n\t\t\tInstanceLoadedModelsInSectorList(sector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP]);\n\t\t\tInstanceLoadedModelsInSectorList(sector->m_lists[ENTITYLIST_OBJECTS]);\n\t\t\tInstanceLoadedModelsInSectorList(sector->m_lists[ENTITYLIST_DUMMIES]);\n\t\t}\n\t}\n}\n\nvoid\nCStreaming::RequestIslands(eLevelName level)\n{\n\tISLAND_LOADING_ISNT(HIGH)\n\tswitch(level){\n\tcase LEVEL_MAINLAND:\n\t\tif(islandLODbeach != -1)\n\t\t\tRequestModel(islandLODbeach, BIGBUILDINGFLAGS);\n\t\tbreak;\n\tcase LEVEL_BEACH:\n\t\tif(islandLODmainland != -1)\n\t\t\tRequestModel(islandLODmainland, BIGBUILDINGFLAGS);\n\t\tbreak;\n\tdefault: break;\n\t}\n}\n\nstatic char *IGnames[] = {\n\t\"player\",\n\t\"player2\",\n\t\"player3\",\n\t\"player4\",\n\t\"player5\",\n\t\"player6\",\n\t\"player7\",\n\t\"player8\",\n\t\"player9\",\n\t\"play10\",\n\t\"play11\",\n\t\"igken\",\n\t\"igcandy\",\n\t\"igsonny\",\n\t\"igbuddy\",\n\t\"igjezz\",\n\t\"ighlary\",\n\t\"igphil\",\n\t\"igmerc\",\n\t\"igdick\",\n\t\"igdiaz\",\n\t\"\"\n};\n\nstatic char *CSnames[] = {\n\t\"csplay\",\n\t\"csplay2\",\n\t\"csplay3\",\n\t\"csplay4\",\n\t\"csplay5\",\n\t\"csplay6\",\n\t\"csplay7\",\n\t\"csplay8\",\n\t\"csplay9\",\n\t\"csplay10\",\n\t\"csplay11\",\n\t\"csken\",\n\t\"cscandy\",\n\t\"cssonny\",\n\t\"csbuddy\",\n\t\"csjezz\",\n\t\"cshlary\",\n\t\"csphil\",\n\t\"csmerc\",\n\t\"csdick\",\n\t\"csdiaz\",\n\t\"\"\n};\n\nvoid\nCStreaming::RequestSpecialModel(int32 modelId, const char *modelName, int32 flags)\n{\n\tCBaseModelInfo *mi;\n\tint txdId;\n\tchar oldName[48];\n\tuint32 pos, size;\n\tint i, n;\n\n\tmi = CModelInfo::GetModelInfo(modelId);\n\tif(strncasecmp(\"CSPlay\", modelName, 6) == 0){\n\t\tchar *curname = CModelInfo::GetModelInfo(MI_PLAYER)->GetModelName();\n\t\tfor(int i = 0; CSnames[i][0]; i++){\n\t\t\tif(strcasecmp(curname, IGnames[i]) == 0){\n\t\t\t\tmodelName = CSnames[i];\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\tif(!CGeneral::faststrcmp(mi->GetModelName(), modelName)){\n\t\t// Already have the correct name, just request it\n\t\tRequestModel(modelId, flags);\n\t\treturn;\n\t}\n\n\tif(mi->GetNumRefs() > 0){\n\t\tn = CPools::GetPedPool()->GetSize()-1;\n\t\tfor(i = n; i >= 0 && mi->GetNumRefs() > 0; i--){\n\t\t\tCPed *ped = CPools::GetPedPool()->GetSlot(i);\n\t\t\tif(ped && ped->GetModelIndex() == modelId &&\n\t\t\t   !ped->IsPlayer() && ped->CanBeDeletedEvenInVehicle())\n\t\t\t\tCTheScripts::RemoveThisPed(ped);\n\t\t}\n\t\tn = CPools::GetObjectPool()->GetSize()-1;\n\t\tfor(i = n; i >= 0 && mi->GetNumRefs() > 0; i--){\n\t\t\tCObject *obj = CPools::GetObjectPool()->GetSlot(i);\n\t\t\tif(obj && obj->GetModelIndex() == modelId && obj->CanBeDeleted()){\n\t\t\t\tCWorld::Remove(obj);\n\t\t\t\tCWorld::RemoveReferencesToDeletedObject(obj);\n\t\t\t\tdelete obj;\n\t\t\t}\n\t\t}\n\t}\n\n\tstrcpy(oldName, mi->GetModelName());\n\tmi->SetModelName(modelName);\n\n\t// What exactly is going on here?\n\tif(CModelInfo::GetModelInfo(oldName, nil)){\n\t\ttxdId = CTxdStore::FindTxdSlot(oldName);\n\t\tif(txdId != -1 && CTxdStore::GetSlot(txdId)->texDict){\n\t\t\tCTxdStore::AddRef(txdId);\n\t\t\tRemoveModel(modelId);\n\t\t\tCTxdStore::RemoveRefWithoutDelete(txdId);\n\t\t}else\n\t\t\tRemoveModel(modelId);\n\t}else\n\t\tRemoveModel(modelId);\n\n\tbool found = ms_pExtraObjectsDir->FindItem(modelName, pos, size);\n\tassert(found);\n\tmi->ClearTexDictionary();\n\tif(CTxdStore::FindTxdSlot(modelName) == -1)\n\t\tmi->SetTexDictionary(\"generic\");\n\telse\n\t\tmi->SetTexDictionary(modelName);\n\tms_aInfoForModel[modelId].SetCdPosnAndSize(pos, size);\n\tRequestModel(modelId, flags);\n}\n\nvoid\nCStreaming::RequestSpecialChar(int32 charId, const char *modelName, int32 flags)\n{\n\tRequestSpecialModel(charId + MI_SPECIAL01, modelName, flags);\n}\n\nbool\nCStreaming::HasSpecialCharLoaded(int32 id)\n{\n\treturn HasModelLoaded(id + MI_SPECIAL01);\n}\n\nvoid\nCStreaming::SetMissionDoesntRequireSpecialChar(int32 id)\n{\n\treturn SetMissionDoesntRequireModel(id + MI_SPECIAL01);\n}\n\nvoid\nCStreaming::DecrementRef(int32 id)\n{\n\tms_numModelsRequested--;\n\tif(ms_aInfoForModel[id].IsPriority()){\n\t\tms_aInfoForModel[id].m_flags &= ~STREAMFLAGS_PRIORITY;\n\t\tms_numPriorityRequests--;\n\t}\n}\n\nvoid\nCStreaming::RemoveModel(int32 id)\n{\n\tint i;\n\n\tif(ms_aInfoForModel[id].m_loadState == STREAMSTATE_NOTLOADED)\n\t\treturn;\n\n\tif(ms_aInfoForModel[id].m_loadState == STREAMSTATE_LOADED){\n\t\tif(id < STREAM_OFFSET_TXD)\n\t\t\tCModelInfo::GetModelInfo(id)->DeleteRwObject();\n\t\telse if(id >= STREAM_OFFSET_TXD && id < STREAM_OFFSET_COL)\n\t\t\tCTxdStore::RemoveTxd(id - STREAM_OFFSET_TXD);\n\t\telse if(id >= STREAM_OFFSET_COL && id < STREAM_OFFSET_ANIM)\n\t\t\tCColStore::RemoveCol(id - STREAM_OFFSET_COL);\n\t\telse if(id >= STREAM_OFFSET_ANIM){\n\t\t\tassert(id < NUMSTREAMINFO);\n\t\t\tCAnimManager::RemoveAnimBlock(id - STREAM_OFFSET_ANIM);\n\t\t}\n\t\tms_memoryUsed -= ms_aInfoForModel[id].GetCdSize()*CDSTREAM_SECTOR_SIZE;\n\t}\n\n\tif(ms_aInfoForModel[id].m_next){\n\t\t// Remove from list, model is neither loaded nor requested\n\t\tif(ms_aInfoForModel[id].m_loadState == STREAMSTATE_INQUEUE)\n\t\t\tDecrementRef(id);\n\t\tms_aInfoForModel[id].RemoveFromList();\n\t}else if(ms_aInfoForModel[id].m_loadState == STREAMSTATE_READING){\n\t\tfor(i = 0; i < 4; i++){\n\t\t\tif(ms_channel[0].streamIds[i] == id)\n\t\t\t\tms_channel[0].streamIds[i] = -1;\n\t\t\tif(ms_channel[1].streamIds[i] == id)\n\t\t\t\tms_channel[1].streamIds[i] = -1;\n\t\t}\n\t}\n\n\tif(ms_aInfoForModel[id].m_loadState == STREAMSTATE_STARTED){\n\t\tif(id < STREAM_OFFSET_TXD)\n\t\t\tRpClumpGtaCancelStream();\n\t\telse if(id >= STREAM_OFFSET_TXD && id < STREAM_OFFSET_COL)\n\t\t\tCTxdStore::RemoveTxd(id - STREAM_OFFSET_TXD);\n\t\telse if(id >= STREAM_OFFSET_COL && id < STREAM_OFFSET_ANIM)\n\t\t\tCColStore::RemoveCol(id - STREAM_OFFSET_COL);\n\t\telse if(id >= STREAM_OFFSET_ANIM){\n\t\t\tassert(id < NUMSTREAMINFO);\n\t\t\tCAnimManager::RemoveAnimBlock(id - STREAM_OFFSET_ANIM);\n\t\t}\n\t}\n\n\tms_aInfoForModel[id].m_loadState = STREAMSTATE_NOTLOADED;\n}\n\nvoid\nCStreaming::RemoveUnusedBuildings(eLevelName level)\n{\n\tif(level != LEVEL_BEACH)\n\t\tRemoveBuildings(LEVEL_BEACH);\n\tif(level != LEVEL_MAINLAND)\n\t\tRemoveBuildings(LEVEL_MAINLAND);\n}\n\nvoid\nCStreaming::RemoveBuildings(eLevelName level)\n{\n\tint i, n;\n\tCEntity *e;\n\tCBaseModelInfo *mi;\n\n\tn = CPools::GetBuildingPool()->GetSize()-1;\n\tfor(i = n; i >= 0; i--){\n\t\te = CPools::GetBuildingPool()->GetSlot(i);\n\t\tif(e && e->m_level == level){\n\t\t\tmi = CModelInfo::GetModelInfo(e->GetModelIndex());\n\t\t\tif(!e->bImBeingRendered){\n\t\t\t\te->DeleteRwObject();\n\t\t\t\tif (mi->GetNumRefs() == 0)\n\t\t\t\t\tRemoveModel(e->GetModelIndex());\n\t\t\t}\n\t\t}\n\t}\n\n\tn = CPools::GetTreadablePool()->GetSize()-1;\n\tfor(i = n; i >= 0; i--){\n\t\te = CPools::GetTreadablePool()->GetSlot(i);\n\t\tif(e && e->m_level == level){\n\t\t\tmi = CModelInfo::GetModelInfo(e->GetModelIndex());\n\t\t\tif(!e->bImBeingRendered){\n\t\t\t\te->DeleteRwObject();\n\t\t\t\tif (mi->GetNumRefs() == 0)\n\t\t\t\t\tRemoveModel(e->GetModelIndex());\n\t\t\t}\n\t\t}\n\t}\n\n\tn = CPools::GetObjectPool()->GetSize()-1;\n\tfor(i = n; i >= 0; i--){\n\t\te = CPools::GetObjectPool()->GetSlot(i);\n\t\tif(e && e->m_level == level){\n\t\t\tmi = CModelInfo::GetModelInfo(e->GetModelIndex());\n\t\t\tif(!e->bImBeingRendered && ((CObject*)e)->ObjectCreatedBy == GAME_OBJECT){\n\t\t\t\te->DeleteRwObject();\n\t\t\t\tif (mi->GetNumRefs() == 0)\n\t\t\t\t\tRemoveModel(e->GetModelIndex());\n\t\t\t}\n\t\t}\n\t}\n\n\tn = CPools::GetDummyPool()->GetSize()-1;\n\tfor(i = n; i >= 0; i--){\n\t\te = CPools::GetDummyPool()->GetSlot(i);\n\t\tif(e && e->m_level == level){\n\t\t\tmi = CModelInfo::GetModelInfo(e->GetModelIndex());\n\t\t\tif(!e->bImBeingRendered){\n\t\t\t\te->DeleteRwObject();\n\t\t\t\tif (mi->GetNumRefs() == 0)\n\t\t\t\t\tRemoveModel(e->GetModelIndex());\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nCStreaming::RemoveBuildingsNotInArea(int32 area)\n{\n\tint i, n;\n\tCEntity *e;\n\n\tn = CPools::GetBuildingPool()->GetSize()-1;\n\tfor(i = n; i >= 0; i--){\n\t\te = CPools::GetBuildingPool()->GetSlot(i);\n\t\tif(e && e->m_rwObject && !IsAreaVisible(area) &&\n\t\t   (!e->bIsBIGBuilding || e->bStreamBIGBuilding)){\n\t\t\tif(e->bIsBIGBuilding)\n\t\t\t\tRequestModel(e->GetModelIndex(), 0);\n\t\t\tif(!e->bImBeingRendered)\n\t\t\t\te->DeleteRwObject();\n\t\t}\n\t}\n\n\tn = CPools::GetTreadablePool()->GetSize()-1;\n\tfor(i = n; i >= 0; i--){\n\t\te = CPools::GetTreadablePool()->GetSlot(i);\n\t\tif(e && e->m_rwObject && !IsAreaVisible(area) &&\n\t\t   (!e->bIsBIGBuilding || e->bStreamBIGBuilding)){\n\t\t\tif(e->bIsBIGBuilding)\n\t\t\t\tRequestModel(e->GetModelIndex(), 0);\n\t\t\tif(!e->bImBeingRendered)\n\t\t\t\te->DeleteRwObject();\n\t\t}\n\t}\n\n\tn = CPools::GetObjectPool()->GetSize()-1;\n\tfor(i = n; i >= 0; i--){\n\t\te = CPools::GetObjectPool()->GetSlot(i);\n\t\tif(e && e->m_rwObject && !IsAreaVisible(area) &&\n\t\t   (!e->bIsBIGBuilding || e->bStreamBIGBuilding)){\n\t\t\tif(e->bIsBIGBuilding)\n\t\t\t\tRequestModel(e->GetModelIndex(), 0);\n\t\t\tif(!e->bImBeingRendered)\n\t\t\t\te->DeleteRwObject();\n\t\t}\n\t}\n\n\tn = CPools::GetDummyPool()->GetSize()-1;\n\tfor(i = n; i >= 0; i--){\n\t\te = CPools::GetDummyPool()->GetSlot(i);\n\t\tif(e && e->m_rwObject && !IsAreaVisible(area) &&\n\t\t   (!e->bIsBIGBuilding || e->bStreamBIGBuilding)){\n\t\t\tif(e->bIsBIGBuilding)\n\t\t\t\tRequestModel(e->GetModelIndex(), 0);\n\t\t\tif(!e->bImBeingRendered)\n\t\t\t\te->DeleteRwObject();\n\t\t}\n\t}\n}\n\nvoid\nCStreaming::RemoveUnusedBigBuildings(eLevelName level)\n{\n\tISLAND_LOADING_IS(LOW)\n\t{\n\tif(level != LEVEL_BEACH)\n\t\tRemoveBigBuildings(LEVEL_BEACH);\n\tif(level != LEVEL_MAINLAND)\n\t\tRemoveBigBuildings(LEVEL_MAINLAND);\n\t}\n\tRemoveIslandsNotUsed(level);\n}\n\nvoid\nDeleteIsland(CEntity *island)\n{\n\tif(island == nil)\n\t\treturn;\n\tif(island->bImBeingRendered)\n\t\tdebug(\"Didn't delete island because it was being rendered\\n\");\n\telse{\n\t\tisland->DeleteRwObject();\n\t\tCStreaming::RemoveModel(island->GetModelIndex());\n\t}\n}\n\nvoid\nCStreaming::RemoveIslandsNotUsed(eLevelName level)\n{\n\tint i;\n\tif(pIslandLODmainlandEntity == nil)\n\tfor(i = CPools::GetBuildingPool()->GetSize()-1; i >= 0; i--){\n\t\tCBuilding *building = CPools::GetBuildingPool()->GetSlot(i);\n\t\tif(building == nil)\n\t\t\tcontinue;\n\t\tif(building->GetModelIndex() == islandLODmainland)\n\t\t\tpIslandLODmainlandEntity = building;\n\t\tif(building->GetModelIndex() == islandLODbeach)\n\t\t\tpIslandLODbeachEntity = building;\n\t}\n#ifdef NO_ISLAND_LOADING\n\tif(FrontEndMenuManager.m_PrefsIslandLoading == CMenuManager::ISLAND_LOADING_HIGH) {\n\t\tDeleteIsland(pIslandLODmainlandEntity);\n\t\tDeleteIsland(pIslandLODbeachEntity);\n\t} else\n#endif\n\tswitch(level){\n\tcase LEVEL_MAINLAND:\n\t\tDeleteIsland(pIslandLODmainlandEntity);\n\t\tbreak;\n\tcase LEVEL_BEACH:\n\t\tDeleteIsland(pIslandLODbeachEntity);\n\n\t\tbreak;\n\t}\n}\n\nvoid\nCStreaming::RemoveBigBuildings(eLevelName level)\n{\n\tint i, n;\n\tCEntity *e;\n\tCBaseModelInfo *mi;\n\n\tn = CPools::GetBuildingPool()->GetSize()-1;\n\tfor(i = n; i >= 0; i--){\n\t\te = CPools::GetBuildingPool()->GetSlot(i);\n\t\tif(e && e->bIsBIGBuilding && e->m_level == level){\n\t\t\tmi = CModelInfo::GetModelInfo(e->GetModelIndex());\n\t\t\tif(!e->bImBeingRendered){\n\t\t\t\te->DeleteRwObject();\n\t\t\t\tif (mi->GetNumRefs() == 0)\n\t\t\t\t\tRemoveModel(e->GetModelIndex());\n\t\t\t}\n\t\t}\n\t}\n}\n\nbool\nCStreaming::RemoveLoadedVehicle(void)\n{\n\tint i, id;\n\n\tfor(i = 0; i < MAXVEHICLESLOADED; i++){\n\t\tms_lastVehicleDeleted++;\n\t\tif(ms_lastVehicleDeleted == MAXVEHICLESLOADED)\n\t\t\tms_lastVehicleDeleted = 0;\n\t\tid = ms_vehiclesLoaded[ms_lastVehicleDeleted];\n\t\tif(id != -1 && CanRemoveModel(id) && CModelInfo::GetModelInfo(id)->GetNumRefs() == 0 &&\n\t\t   ms_aInfoForModel[id].m_loadState == STREAMSTATE_LOADED)\n\t\t\tgoto found;\n\t}\n\treturn false;\nfound:\n\tRemoveModel(ms_vehiclesLoaded[ms_lastVehicleDeleted]);\n\tms_numVehiclesLoaded--;\n\tms_vehiclesLoaded[ms_lastVehicleDeleted] = -1;\n\tCVehicleModelInfo* pVehicleInfo = (CVehicleModelInfo*)CModelInfo::GetModelInfo(id);\n\tif (pVehicleInfo->m_vehicleClass != -1)\n\t\tCCarCtrl::RemoveFromLoadedVehicleArray(id, pVehicleInfo->m_vehicleClass);\n\treturn true;\n}\n\nbool\nCStreaming::RemoveLeastUsedModel(uint32 excludeMask)\n{\n\tCStreamingInfo *si;\n\tint streamId;\n\n\tfor(si = ms_endLoadedList.m_prev; si != &ms_startLoadedList; si = si->m_prev){\n\t\tif(si->m_flags & excludeMask)\n\t\t\tcontinue;\n\t\tstreamId = si - ms_aInfoForModel;\n\t\tif(streamId < STREAM_OFFSET_TXD){\n\t\t\tif (CModelInfo::GetModelInfo(streamId)->GetNumRefs() == 0) {\n\t\t\t\tRemoveModel(streamId);\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}else if(streamId >= STREAM_OFFSET_TXD && streamId < STREAM_OFFSET_COL){\n\t\t\tif(CTxdStore::GetNumRefs(streamId - STREAM_OFFSET_TXD) == 0 &&\n\t\t\t   !IsTxdUsedByRequestedModels(streamId - STREAM_OFFSET_TXD)){\n\t\t\t\tRemoveModel(streamId);\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}else if(streamId >= STREAM_OFFSET_ANIM){\n\t\t\tassert(streamId < NUMSTREAMINFO);\n\t\t\tif(CAnimManager::GetNumRefsToAnimBlock(streamId - STREAM_OFFSET_ANIM) == 0 &&\n\t\t\t   !AreAnimsUsedByRequestedModels(streamId - STREAM_OFFSET_ANIM)){\n\t\t\t\tRemoveModel(streamId);\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t}\n\treturn (ms_numVehiclesLoaded > 7 || CGame::currArea != AREA_MAIN_MAP && ms_numVehiclesLoaded > 4) && RemoveLoadedVehicle();\n}\n\nvoid\nCStreaming::RemoveAllUnusedModels(void)\n{\n\tint i;\n\n\tfor(i = 0; i < MAXVEHICLESLOADED; i++)\n\t\tRemoveLoadedVehicle();\n\n\tfor(i = NUM_DEFAULT_MODELS; i < MODELINFOSIZE; i++){\n\t\tif(ms_aInfoForModel[i].m_loadState == STREAMSTATE_LOADED &&\n\t\t    CModelInfo::GetModelInfo(i)->GetNumRefs() == 0) {\n\t\t\tRemoveModel(i);\n\t\t\tms_aInfoForModel[i].m_loadState = STREAMSTATE_NOTLOADED;\n\t\t}\n\t}\n}\n\nvoid\nCStreaming::RemoveUnusedModelsInLoadedList(void)\n{\n\t// empty\n}\n\nbool\nCStreaming::RemoveLoadedZoneModel(void)\n{\n\tint i;\n\n\tif(ms_currentPedGrp == -1)\n\t\treturn false;\n\n\tfor(i = 0; i < NUMMODELSPERPEDGROUP; i++){\n\t\tint mi = CPopulation::ms_pPedGroups[ms_currentPedGrp].models[i];\n\t\tif(mi != -1 && ms_bIsPedFromPedGroupLoaded[i] &&\n\t\t   HasModelLoaded(mi) &&  CanRemoveModel(mi) &&\n\t\t   CModelInfo::GetModelInfo(mi)->GetNumRefs() == 0){\n\t\t\tRemoveModel(CPopulation::ms_pPedGroups[ms_currentPedGrp].models[i]);\n\t\t\tms_numPedsLoaded--;\n\t\t\tms_bIsPedFromPedGroupLoaded[i] = false;\n\t\t\treturn true;\n\t\t}\n\t}\n\n\treturn false;\n}\n\nbool\nCStreaming::IsTxdUsedByRequestedModels(int32 txdId)\n{\n\tCStreamingInfo *si;\n\tint streamId;\n\tint i;\n\n\tfor(si = ms_startRequestedList.m_next; si != &ms_endRequestedList; si = si->m_next){\n\t\tstreamId = si - ms_aInfoForModel;\n\t\tif(streamId < STREAM_OFFSET_TXD &&\n\t\t   CModelInfo::GetModelInfo(streamId)->GetTxdSlot() == txdId)\n\t\t\treturn true;\n\t}\n\n\tfor(i = 0; i < 4; i++){\n\t\tstreamId = ms_channel[0].streamIds[i];\n\t\tif(streamId != -1 && streamId < STREAM_OFFSET_TXD &&\n\t\t   CModelInfo::GetModelInfo(streamId)->GetTxdSlot() == txdId)\n\t\t\treturn true;\n\t\tstreamId = ms_channel[1].streamIds[i];\n\t\tif(streamId != -1 && streamId < STREAM_OFFSET_TXD &&\n\t\t   CModelInfo::GetModelInfo(streamId)->GetTxdSlot() == txdId)\n\t\t\treturn true;\n\t}\n\n\treturn false;\n}\n\nbool\nCStreaming::AreAnimsUsedByRequestedModels(int32 animId)\n{\n\tCStreamingInfo *si;\n\tint streamId;\n\tint i;\n\n\tfor(si = ms_startRequestedList.m_next; si != &ms_endRequestedList; si = si->m_next){\n\t\tstreamId = si - ms_aInfoForModel;\n\t\tif(streamId < STREAM_OFFSET_TXD &&\n\t\t   CModelInfo::GetModelInfo(streamId)->GetAnimFileIndex() == animId)\n\t\t\treturn true;\n\t}\n\n\tfor(i = 0; i < 4; i++){\n\t\tstreamId = ms_channel[0].streamIds[i];\n\t\tif(streamId != -1 && streamId < STREAM_OFFSET_TXD &&\n\t\t   CModelInfo::GetModelInfo(streamId)->GetAnimFileIndex() == animId)\n\t\t\treturn true;\n\t\tstreamId = ms_channel[1].streamIds[i];\n\t\tif(streamId != -1 && streamId < STREAM_OFFSET_TXD &&\n\t\t   CModelInfo::GetModelInfo(streamId)->GetAnimFileIndex() == animId)\n\t\t\treturn true;\n\t}\n\n\treturn false;\n}\n\nint32\nCStreaming::GetAvailableVehicleSlot(void)\n{\n\tint i;\n\tfor(i = 0; i < MAXVEHICLESLOADED; i++)\n\t\tif(ms_vehiclesLoaded[i] == -1)\n\t\t\treturn i;\n\treturn -1;\n}\n\nbool\nCStreaming::AddToLoadedVehiclesList(int32 modelId)\n{\n\tint i;\n\tint id;\n\n\tif(ms_numVehiclesLoaded < desiredNumVehiclesLoaded){\n\t\t// still room for vehicles\n\t\tfor(i = 0; i < MAXVEHICLESLOADED; i++){\n\t\t\tif(ms_vehiclesLoaded[ms_lastVehicleDeleted] == -1)\n\t\t\t\tbreak;\n\t\t\tms_lastVehicleDeleted++;\n\t\t\tif(ms_lastVehicleDeleted == MAXVEHICLESLOADED)\n\t\t\t\tms_lastVehicleDeleted = 0;\n\t\t}\n\t\tassert(ms_vehiclesLoaded[ms_lastVehicleDeleted] == -1);\n\t\tms_numVehiclesLoaded++;\n\t}else{\n\t\t// find vehicle we can remove\n\t\tfor(i = 0; i < MAXVEHICLESLOADED; i++){\n\t\t\tid = ms_vehiclesLoaded[ms_lastVehicleDeleted];\n\t\t\tif(id != -1 && CanRemoveModel(id) &&\n\t\t\t   CModelInfo::GetModelInfo(id)->GetNumRefs() == 0)\n\t\t\t\tgoto found;\n\t\t\tms_lastVehicleDeleted++;\n\t\t\tif(ms_lastVehicleDeleted == MAXVEHICLESLOADED)\n\t\t\t\tms_lastVehicleDeleted = 0;\n\t\t}\n\t\tid = -1;\nfound:\n\t\tif(id == -1){\n\t\t\t// didn't find anything, try a free slot\n\t\t\tid = GetAvailableVehicleSlot();\n\t\t\tif(id == -1)\n\t\t\t\treturn false;\t// still no luck\n\t\t\tms_lastVehicleDeleted = id;\n\t\t\t// this is more than we wanted actually\n\t\t\tms_numVehiclesLoaded++;\n\t\t}\n\t\telse{\n\t\t\tRemoveModel(id);\n\t\t\tCVehicleModelInfo* pVehicleInfo = (CVehicleModelInfo*)CModelInfo::GetModelInfo(id);\n\t\t\tif (pVehicleInfo->m_vehicleClass != -1)\n\t\t\t\tCCarCtrl::RemoveFromLoadedVehicleArray(id, pVehicleInfo->m_vehicleClass);\n\t\t}\n\t}\n\n\tms_vehiclesLoaded[ms_lastVehicleDeleted++] = modelId;\n\tif(ms_lastVehicleDeleted == MAXVEHICLESLOADED)\n\t\tms_lastVehicleDeleted = 0;\n\tCVehicleModelInfo* pVehicleInfo = (CVehicleModelInfo*)CModelInfo::GetModelInfo(modelId);\n\tif (pVehicleInfo->m_vehicleClass != -1)\n\t\tCCarCtrl::AddToLoadedVehicleArray(modelId, pVehicleInfo->m_vehicleClass, pVehicleInfo->m_frequency);\n\treturn true;\n}\n\nbool\nCStreaming::IsObjectInCdImage(int32 id)\n{\n\tuint32 posn, size;\n\treturn ms_aInfoForModel[id].GetCdPosnAndSize(posn, size);\n}\n\nvoid\nCStreaming::SetModelIsDeletable(int32 id)\n{\n\tms_aInfoForModel[id].m_flags &= ~STREAMFLAGS_DONT_REMOVE;\n\tif ((id >= STREAM_OFFSET_TXD && id < STREAM_OFFSET_COL || CModelInfo::GetModelInfo(id)->GetModelType() != MITYPE_VEHICLE) &&\n\t   (ms_aInfoForModel[id].m_flags & STREAMFLAGS_SCRIPTOWNED) == 0){\n\t\tif(ms_aInfoForModel[id].m_loadState != STREAMSTATE_LOADED)\n\t\t\tRemoveModel(id);\n\t\telse if(ms_aInfoForModel[id].m_next == nil)\n\t\t\tms_aInfoForModel[id].AddToList(&ms_startLoadedList);\n\t}\n}\n\nvoid\nCStreaming::SetModelTxdIsDeletable(int32 id)\n{\n\tSetModelIsDeletable(CModelInfo::GetModelInfo(id)->GetTxdSlot() + STREAM_OFFSET_TXD);\n}\n\nvoid\nCStreaming::SetMissionDoesntRequireModel(int32 id)\n{\n\tms_aInfoForModel[id].m_flags &= ~STREAMFLAGS_SCRIPTOWNED;\n\tif ((id >= STREAM_OFFSET_TXD || CModelInfo::GetModelInfo(id)->GetModelType() != MITYPE_VEHICLE) &&\n\t   (ms_aInfoForModel[id].m_flags & STREAMFLAGS_DONT_REMOVE) == 0){\n\t\tif(ms_aInfoForModel[id].m_loadState != STREAMSTATE_LOADED)\n\t\t\tRemoveModel(id);\n\t\telse if(ms_aInfoForModel[id].m_next == nil)\n\t\t\tms_aInfoForModel[id].AddToList(&ms_startLoadedList);\n\t}\n}\n\nvoid\nCStreaming::LoadInitialPeds(void)\n{\n\tRequestModel(MI_COP, STREAMFLAGS_DONT_REMOVE);\n\tRequestModel(MI_MALE01, STREAMFLAGS_DONT_REMOVE);\n\tRequestModel(MI_TAXI_D, STREAMFLAGS_DONT_REMOVE);\n}\n\nvoid\nCStreaming::LoadInitialWeapons(void)\n{\n\tCStreaming::RequestModel(MI_NIGHTSTICK, STREAMFLAGS_DONT_REMOVE);\n\tCStreaming::RequestModel(MI_MISSILE, STREAMFLAGS_DONT_REMOVE);\n}\n\nvoid\nCStreaming::LoadInitialVehicles(void)\n{\n\tms_numVehiclesLoaded = 0;\n\tms_lastVehicleDeleted = 0;\n\n\tRequestModel(MI_POLICE, STREAMFLAGS_DONT_REMOVE);\n}\n\nvoid\nCStreaming::StreamVehiclesAndPeds(void)\n{\n\tint i, model;\n\tstatic int timeBeforeNextLoad = 0;\n\tstatic int modelQualityClass = 0;\n\n\tif(CRecordDataForGame::IsRecording() ||\n\t   CRecordDataForGame::IsPlayingBack()\n#ifdef FIX_BUGS\n\t   || CReplay::IsPlayingBack()\n#endif\n\t\t)\n\t\treturn;\n\n\tif(FindPlayerPed()->m_pWanted->AreSwatRequired()){\n\t\tRequestModel(MI_ENFORCER, STREAMFLAGS_DONT_REMOVE);\n\t\tRequestModel(MI_SWAT, STREAMFLAGS_DONT_REMOVE);\n\t}else{\n\t\tSetModelIsDeletable(MI_ENFORCER);\n\t\tif(!HasModelLoaded(MI_ENFORCER))\n\t\t\tSetModelIsDeletable(MI_SWAT);\n\t}\n\n\tif(FindPlayerPed()->m_pWanted->AreFbiRequired()){\n\t\tRequestModel(MI_FBIRANCH, STREAMFLAGS_DONT_REMOVE);\n\t\tRequestModel(MI_FBI, STREAMFLAGS_DONT_REMOVE);\n\t}else{\n\t\tSetModelIsDeletable(MI_FBIRANCH);\n\t\tif(!HasModelLoaded(MI_FBIRANCH))\n\t\t\tSetModelIsDeletable(MI_FBI);\n\t}\n\n\tif(FindPlayerPed()->m_pWanted->AreArmyRequired()){\n\t\tRequestModel(MI_RHINO, STREAMFLAGS_DONT_REMOVE);\n\t\tRequestModel(MI_BARRACKS, STREAMFLAGS_DONT_REMOVE);\n\t\tRequestModel(MI_ARMY, STREAMFLAGS_DONT_REMOVE);\n\t}else{\n\t\tSetModelIsDeletable(MI_RHINO);\n\t\tSetModelIsDeletable(MI_BARRACKS);\n\t\tif(!HasModelLoaded(MI_RHINO) && !HasModelLoaded(MI_BARRACKS))\n\t\t\tSetModelIsDeletable(MI_ARMY);\n\t}\n\n\tif(FindPlayerPed()->m_pWanted->NumOfHelisRequired() > 0)\n\t\tRequestModel(MI_CHOPPER, STREAMFLAGS_DONT_REMOVE);\n\telse\n\t\tSetModelIsDeletable(MI_CHOPPER);\n\n\tif (FindPlayerPed()->m_pWanted->AreMiamiViceRequired()) {\n\t\tSetModelIsDeletable(MI_VICE1);\n\t\tSetModelIsDeletable(MI_VICE2);\n\t\tSetModelIsDeletable(MI_VICE3);\n\t\tSetModelIsDeletable(MI_VICE4);\n\t\tSetModelIsDeletable(MI_VICE5);\n\t\tSetModelIsDeletable(MI_VICE6);\n\t\tSetModelIsDeletable(MI_VICE7);\n\t\tSetModelIsDeletable(MI_VICE8);\n\t\tRequestModel(MI_VICECHEE, STREAMFLAGS_DONT_REMOVE);\n\t\tif(CPopulation::NumMiamiViceCops == 0)\n\t\t\tswitch (CCarCtrl::MiamiViceCycle) {\n\t\t\tcase 0:\n\t\t\t\tRequestModel(MI_VICE1, STREAMFLAGS_DONT_REMOVE);\n\t\t\t\tRequestModel(MI_VICE2, STREAMFLAGS_DONT_REMOVE);\n\t\t\t\tbreak;\n\t\t\tcase 1:\n\t\t\t\tRequestModel(MI_VICE3, STREAMFLAGS_DONT_REMOVE);\n\t\t\t\tRequestModel(MI_VICE4, STREAMFLAGS_DONT_REMOVE);\n\t\t\t\tbreak;\n\t\t\tcase 2:\n\t\t\t\tRequestModel(MI_VICE5, STREAMFLAGS_DONT_REMOVE);\n\t\t\t\tRequestModel(MI_VICE6, STREAMFLAGS_DONT_REMOVE);\n\t\t\t\tbreak;\n\t\t\tcase 3:\n\t\t\t\tRequestModel(MI_VICE7, STREAMFLAGS_DONT_REMOVE);\n\t\t\t\tRequestModel(MI_VICE8, STREAMFLAGS_DONT_REMOVE);\n\t\t\t\tbreak;\n\t\t\t}\n\t}\n\telse {\n\t\tSetModelIsDeletable(MI_VICECHEE);\n\t\tSetModelIsDeletable(MI_VICE1);\n\t\tSetModelIsDeletable(MI_VICE2);\n\t\tSetModelIsDeletable(MI_VICE3);\n\t\tSetModelIsDeletable(MI_VICE4);\n\t\tSetModelIsDeletable(MI_VICE5);\n\t\tSetModelIsDeletable(MI_VICE6);\n\t\tSetModelIsDeletable(MI_VICE7);\n\t\tSetModelIsDeletable(MI_VICE8);\n\t}\n\n\tif(timeBeforeNextLoad >= 0)\n\t\ttimeBeforeNextLoad--;\n\telse if(ms_numVehiclesLoaded <= desiredNumVehiclesLoaded){\n\t\tCZoneInfo zone;\n\t\tCVector coors = FindPlayerCoors();\n\t\tCTheZones::GetZoneInfoForTimeOfDay(&coors, &zone);\n\t\tint32 maxReq = -1;\n\t\tint32 mostRequestedRating = 0;\n\t\tfor(i = 0; i < CCarCtrl::TOTAL_CUSTOM_CLASSES; i++){\n\t\t\tif(CCarCtrl::NumRequestsOfCarRating[i] > maxReq &&\n\t\t\t\t((i == 0 && zone.carThreshold[0] != 0) ||\n\t\t\t\t(i != 0 && zone.carThreshold[i] != zone.carThreshold[i-1]))) {\n\t\t\t\tmaxReq = CCarCtrl::NumRequestsOfCarRating[i];\n\t\t\t\tmostRequestedRating = i;\n\t\t\t}\n\t\t}\n\t\tmodel = CCarCtrl::ChooseCarModelToLoad(mostRequestedRating);\n\t\tif(!HasModelLoaded(model)){\n\t\t\tRequestModel(model, STREAMFLAGS_DEPENDENCY);\n\t\t\ttimeBeforeNextLoad = 350;\n\t\t}\n\t\tCCarCtrl::NumRequestsOfCarRating[mostRequestedRating] = 0;\n\t}\n}\n\nvoid\nCStreaming::StreamZoneModels(const CVector &pos)\n{\n\tint i, j;\n\tuint16 gangsToLoad, gangCarsToLoad, bit;\n\tCZoneInfo info;\n\tstatic int timeBeforeNextLoad = 0;\n\n\tCTheZones::GetZoneInfoForTimeOfDay(&pos, &info);\n\n\tif(info.pedGroup != ms_currentPedGrp){\n\n\t\t// unload pevious group\n\t\tif(ms_currentPedGrp != -1)\n\t\t\tfor(i = 0; i < NUMMODELSPERPEDGROUP; i++){\n\t\t\t\tms_bIsPedFromPedGroupLoaded[i] = false;\n\t\t\t\tif(CPopulation::ms_pPedGroups[ms_currentPedGrp].models[i] != -1){\n\t\t\t\t\tSetModelIsDeletable(CPopulation::ms_pPedGroups[ms_currentPedGrp].models[i]);\n\t\t\t\t\tSetModelTxdIsDeletable(CPopulation::ms_pPedGroups[ms_currentPedGrp].models[i]);\n\t\t\t\t}\n\t\t\t}\n\n\t\tms_currentPedGrp = info.pedGroup;\n\n\t\tfor(i = 0; i < MAXZONEPEDSLOADED; i++){\n\t\t\tdo\n\t\t\t\tj = CGeneral::GetRandomNumberInRange(0, NUMMODELSPERPEDGROUP);\n\t\t\twhile(ms_bIsPedFromPedGroupLoaded[j]);\n\t\t\tms_bIsPedFromPedGroupLoaded[j] = true;\n\t\t\tif(CPopulation::ms_pPedGroups[ms_currentPedGrp].models[j] != -1)\n\t\t\t\tRequestModel(CPopulation::ms_pPedGroups[ms_currentPedGrp].models[j], STREAMFLAGS_DEPENDENCY);\n\t\t}\n\t\tms_numPedsLoaded = MAXZONEPEDSLOADED;\n\t\ttimeBeforeNextLoad = 300;\n\t}\n\n\tif(timeBeforeNextLoad >= 0)\n\t\ttimeBeforeNextLoad--;\n\telse{\n\t\t// Switch a ped\n\t\tint oldMI;\n\t\t// Find a ped to unload\n\t\tfor(i = 0; i < NUMMODELSPERPEDGROUP; i++)\n\t\t\tif(ms_bIsPedFromPedGroupLoaded[i]){\n\t\t\t\toldMI = CPopulation::ms_pPedGroups[ms_currentPedGrp].models[i];\n\t\t\t\tif(oldMI != -1 && CModelInfo::GetModelInfo(oldMI)->GetNumRefs() == 0)\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t// And load a new one\n\t\tif(i != NUMMODELSPERPEDGROUP || ms_numPedsLoaded < MAXZONEPEDSLOADED){\n\t\t\tdo\n\t\t\t\tj = CGeneral::GetRandomNumberInRange(0, NUMMODELSPERPEDGROUP);\n\t\t\twhile(ms_bIsPedFromPedGroupLoaded[j]);\n\t\t\tif(ms_numPedsLoaded == MAXZONEPEDSLOADED)\n\t\t\t\tms_bIsPedFromPedGroupLoaded[i] = false;\n\t\t\tms_bIsPedFromPedGroupLoaded[j] = true;\n\t\t\tint newMI = CPopulation::ms_pPedGroups[ms_currentPedGrp].models[j];\n\t\t\tif(newMI != oldMI){\n\t\t\t\tRequestModel(newMI, STREAMFLAGS_DEPENDENCY);\n\t\t\t\tdebug(\"Request Ped %s\\n\", CModelInfo::GetModelInfo(newMI)->GetModelName());\n\t\t\t\tif(ms_numPedsLoaded == MAXZONEPEDSLOADED){\n\t\t\t\t\tSetModelIsDeletable(oldMI);\n\t\t\t\t\tSetModelTxdIsDeletable(oldMI);\n\t\t\t\t\tdebug(\"Remove Ped %s\\n\", CModelInfo::GetModelInfo(oldMI)->GetModelName());\n\t\t\t\t}else\n\t\t\t\t\tms_numPedsLoaded++;\n\t\t\t\ttimeBeforeNextLoad = 300;\n\t\t\t}\n\t\t}\n\t}\n\n\tRequestModel(MI_MALE01, STREAMFLAGS_DONT_REMOVE);\n\tRequestModel(MI_TAXI_D, STREAMFLAGS_DONT_REMOVE);\n\n\tgangsToLoad = 0;\n\tgangCarsToLoad = 0;\n\tif(info.gangPedThreshold[0] != info.copPedThreshold)\n\t\tgangsToLoad = 1;\n\tfor(i = 1; i < NUM_GANGS; i++)\n\t\tif(info.gangPedThreshold[i] != info.gangPedThreshold[i-1])\n\t\t\tgangsToLoad |= 1<<i;\n\tif(info.gangThreshold[0] != info.copThreshold)\n\t\tgangCarsToLoad = 1;\n\tfor(i = 1; i < NUM_GANGS; i++)\n\t\tif(info.gangThreshold[i] != info.gangThreshold[i-1])\n\t\t\tgangCarsToLoad |= 1<<i;\n\n\tif(gangsToLoad == ms_loadedGangs && gangCarsToLoad == ms_loadedGangCars)\n\t\treturn;\n\n\tint gangModelsToload = gangsToLoad | gangCarsToLoad;\n\n\tif(gangsToLoad != ms_loadedGangs || gangCarsToLoad != ms_loadedGangCars){\n\t\tfor(i = 0; i < NUM_GANGS; i++){\n\t\t\tbit = 1<<i;\n\n\t\t\tif(gangModelsToload & bit && (ms_loadedGangs & bit) == 0){\n\t\t\t\tRequestModel(CGangs::GetGangPedModel1(i), STREAMFLAGS_DEPENDENCY);\n\t\t\t\tRequestModel(CGangs::GetGangPedModel2(i), STREAMFLAGS_DEPENDENCY);\n\t\t\t\tms_loadedGangs |= bit;\n\t\t\t}else if((gangModelsToload & bit) == 0 && ms_loadedGangs & bit){\n\t\t\t\tSetModelIsDeletable(CGangs::GetGangPedModel1(i));\n\t\t\t\tSetModelIsDeletable(CGangs::GetGangPedModel2(i));\n\t\t\t\tSetModelTxdIsDeletable(CGangs::GetGangPedModel1(i));\n\t\t\t\tSetModelTxdIsDeletable(CGangs::GetGangPedModel2(i));\n\t\t\t\tms_loadedGangs &= ~bit;\n\t\t\t}\n\n\t\t\tif(CGangs::GetGangVehicleModel(i) != -1){\n\t\t\t\tif((gangCarsToLoad & bit) && (ms_loadedGangCars & bit) == 0){\n\t\t\t\t\tRequestModel(CGangs::GetGangVehicleModel(i), STREAMFLAGS_DEPENDENCY);\n\t\t\t\t}else if((gangCarsToLoad & bit) == 0 && ms_loadedGangCars & bit){\n\t\t\t\t\tSetModelIsDeletable(CGangs::GetGangVehicleModel(i));\n\t\t\t\t\tSetModelTxdIsDeletable(CGangs::GetGangVehicleModel(i));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tms_loadedGangCars = gangCarsToLoad;\n\t}\n}\n\nvoid\nCStreaming::RemoveCurrentZonesModels(void)\n{\n\tint i;\n\n\tif (ms_currentPedGrp != -1)\n\t\tfor (i = 0; i < NUMMODELSPERPEDGROUP; i++) {\n\t\t\tms_bIsPedFromPedGroupLoaded[i] = false;\n\t\t\tif (CPopulation::ms_pPedGroups[ms_currentPedGrp].models[i] != -1 &&\n\t\t\t    CPopulation::ms_pPedGroups[ms_currentPedGrp].models[i] != MI_MALE01) {\n\t\t\t\tSetModelIsDeletable(CPopulation::ms_pPedGroups[ms_currentPedGrp].models[i]);\n\t\t\t\tSetModelTxdIsDeletable(CPopulation::ms_pPedGroups[ms_currentPedGrp].models[i]);\n\t\t\t}\n\t\t}\n\n\tCStreaming::RequestModel(MI_MALE01, STREAMFLAGS_DONT_REMOVE);\n\tCStreaming::RequestModel(MI_TAXI_D, STREAMFLAGS_DONT_REMOVE);\n\n\tfor (i = 0; i < NUM_GANGS; i++) {\n\t\tif (CGangs::GetGangPedModel1(i) != -1) {\n\t\t\tSetModelIsDeletable(CGangs::GetGangPedModel1(i));\n\t\t\tSetModelTxdIsDeletable(CGangs::GetGangPedModel1(i));\n\t\t}\n\t\tif (CGangs::GetGangPedModel2(i) != -1) {\n\t\t\tSetModelIsDeletable(CGangs::GetGangPedModel2(i));\n\t\t\tSetModelTxdIsDeletable(CGangs::GetGangPedModel2(i));\n\t\t}\n\t\tif (CGangs::GetGangVehicleModel(i) != -1) {\n\t\t\tSetModelIsDeletable(CGangs::GetGangVehicleModel(i));\n\t\t\tSetModelTxdIsDeletable(CGangs::GetGangVehicleModel(i));\n\t\t}\n\t}\n\n\tms_currentPedGrp = -1;\n\tms_loadedGangs = 0;\n\tms_loadedGangCars = 0;\n}\n\nvoid\nCStreaming::LoadBigBuildingsWhenNeeded(void)\n{\n\t// Very much like CCollision::Update and CCollision::LoadCollisionWhenINeedIt\n\tif(CCutsceneMgr::IsCutsceneProcessing())\n\t\treturn;\n\n\tif(CTheZones::m_CurrLevel == LEVEL_GENERIC || \n\t   CTheZones::m_CurrLevel == CGame::currLevel)\n\t\treturn;\n\n\tCTimer::Suspend();\n\tCGame::currLevel = CTheZones::m_CurrLevel;\n\tISLAND_LOADING_IS(LOW)\n\t{\n\t\tDMAudio.SetEffectsFadeVol(0);\n\t\tCPad::StopPadsShaking();\n\t\tCCollision::LoadCollisionScreen(CGame::currLevel);\n\t\tDMAudio.Service();\n\n\t\tRemoveUnusedBigBuildings(CGame::currLevel);\n\t\tRemoveUnusedBuildings(CGame::currLevel);\n\t\tRemoveUnusedModelsInLoadedList();\n\t\tCGame::TidyUpMemory(true, true);\n\t}\n\tCReplay::EmptyReplayBuffer();\n\tif(CGame::currLevel != LEVEL_GENERIC)\n\t\tLoadSplash(GetLevelSplashScreen(CGame::currLevel));\n\n\tISLAND_LOADING_IS(LOW)\n\t\tCStreaming::RequestBigBuildings(CGame::currLevel, TheCamera.GetPosition());\n#ifdef NO_ISLAND_LOADING\n\telse if(FrontEndMenuManager.m_PrefsIslandLoading == CMenuManager::ISLAND_LOADING_MEDIUM) {\n\t\tRemoveIslandsNotUsed(CGame::currLevel);\n\t\tCStreaming::RequestIslands(CGame::currLevel);\n\t}\n#endif\n\n\tCStreaming::LoadAllRequestedModels(false);\n\n\tCGame::TidyUpMemory(true, true);\n\tCTimer::Resume();\n\n\tISLAND_LOADING_IS(LOW)\n\t\tDMAudio.SetEffectsFadeVol(127);\n}\n\n\n// Find starting offset of the cdimage we next want to read\n// Not useful at all on PC...\nint32\nCStreaming::GetCdImageOffset(int32 lastPosn)\n{\n\tint offset, off;\n\tint i, img;\n\tint dist, mindist;\n\n\timg = -1;\n\tmindist = INT32_MAX;\n\toffset = ms_imageOffsets[ms_lastImageRead];\n\tif(lastPosn <= offset || lastPosn > offset + ms_imageSize){\n\t\t// last read position is not in last image\n\t\tfor(i = 0; i < NUMCDIMAGES; i++){\n\t\t\toff = ms_imageOffsets[i];\n\t\t\tif(off == -1) continue;\n\t\t\tif((uint32)lastPosn > (uint32)off)\n\t\t\t\t// after start of image, get distance from end\n\t\t\t\t// negative if before end!\n\t\t\t\tdist = lastPosn - (off + ms_imageSize);\n\t\t\telse\n\t\t\t\t// before image, get offset to start\n\t\t\t\t// this will never be negative\n\t\t\t\tdist = off - lastPosn;\n\t\t\tif(dist < mindist){\n\t\t\t\timg = i;\n\t\t\t\tmindist = dist;\n\t\t\t}\n\t\t}\n\t\tassert(img >= 0);\n\t\toffset = ms_imageOffsets[img];\n\t\tms_lastImageRead = img;\n\t}\n\treturn offset;\n}\n\ninline bool\nModelNotLoaded(int32 modelId)\n{\n\tCStreamingInfo *si = &CStreaming::ms_aInfoForModel[modelId];\n\treturn si->m_loadState != STREAMSTATE_LOADED && si->m_loadState != STREAMSTATE_READING;\n}\n\ninline bool TxdNotLoaded(int32 txdId) { return ModelNotLoaded(txdId + STREAM_OFFSET_TXD); }\ninline bool AnimNotLoaded(int32 animId) { return animId != -1 && ModelNotLoaded(animId + STREAM_OFFSET_ANIM); }\n\n// Find stream id of next requested file in cdimage\nint32\nCStreaming::GetNextFileOnCd(int32 lastPosn, bool priority)\n{\n\tCStreamingInfo *si, *next;\n\tint streamId;\n\tuint32 posn, size;\n\tint streamIdFirst, streamIdNext;\n\tuint32 posnFirst, posnNext;\n\n\tstreamIdFirst = -1;\n\tstreamIdNext = -1;\n\tposnFirst = UINT32_MAX;\n\tposnNext = UINT32_MAX;\n\n\tfor(si = ms_startRequestedList.m_next; si != &ms_endRequestedList; si = next){\n\t\tnext = si->m_next;\n\t\tstreamId = si - ms_aInfoForModel;\n\n\t\t// only priority requests if there are any\n\t\tif(priority && ms_numPriorityRequests != 0 && !si->IsPriority())\n\t\t\tcontinue;\n\n\t\t// request Txds or anims if necessary\n\t\tif(streamId < STREAM_OFFSET_TXD){\n\t\t\tint txdId = CModelInfo::GetModelInfo(streamId)->GetTxdSlot();\n\t\t\tif(TxdNotLoaded(txdId)){\n\t\t\t\tReRequestTxd(txdId);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tint animId = CModelInfo::GetModelInfo(streamId)->GetAnimFileIndex();\n\t\t\tif(AnimNotLoaded(animId)){\n\t\t\t\tReRequestAnim(animId);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}else if(streamId >= STREAM_OFFSET_ANIM && CCutsceneMgr::IsCutsceneProcessing())\n\t\t\tcontinue;\n\n\t\tif(ms_aInfoForModel[streamId].GetCdPosnAndSize(posn, size)){\n\t\t\tif(posn < posnFirst){\n\t\t\t\t// find first requested file in image\n\t\t\t\tstreamIdFirst = streamId;\n\t\t\t\tposnFirst = posn;\n\t\t\t}\n\t\t\tif(posn < posnNext && posn >= (uint32)lastPosn){\n\t\t\t\t// find first requested file after last read position\n\t\t\t\tstreamIdNext = streamId;\n\t\t\t\tposnNext = posn;\n\t\t\t}\n\t\t}else{\n\t\t\t// empty file\n\t\t\tDecrementRef(streamId);\n\t\t\tsi->RemoveFromList();\n\t\t\tsi->m_loadState = STREAMSTATE_LOADED;\n\t\t}\n\t}\n\n\t// wrap around\n\tif(streamIdNext == -1)\n\t\tstreamIdNext = streamIdFirst;\n\n\tif(streamIdNext == -1 && ms_numPriorityRequests != 0){\n\t\t// try non-priority files\n\t\tms_numPriorityRequests = 0;\n\t\tstreamIdNext = GetNextFileOnCd(lastPosn, false);\n\t}\n\n\treturn streamIdNext;\n}\n\n/*\n * Streaming buffer size is half of the largest file.\n * Files larger than the buffer size can only be loaded by channel 0,\n * which then uses both buffers, while channel 1 is idle.\n * ms_bLoadingBigModel is set to true to indicate this state.\n */\n\n// Make channel read from disc\nvoid\nCStreaming::RequestModelStream(int32 ch)\n{\n\tint lastPosn, imgOffset, streamId;\n\tint totalSize;\n\tuint32 posn, size, unused;\n\tint i;\n\tint haveBigFile, havePed;\n\n\tlastPosn = CdStreamGetLastPosn();\n\timgOffset = GetCdImageOffset(lastPosn);\n\tstreamId = GetNextFileOnCd(lastPosn - imgOffset, true);\n\n\t// remove Txds and Anims that aren't requested anymore\n\twhile(streamId != -1){\n\t\tif(ms_aInfoForModel[streamId].m_flags & STREAMFLAGS_KEEP_IN_MEMORY)\n\t\t\tbreak;\n\t\tif(streamId >= STREAM_OFFSET_TXD && streamId < STREAM_OFFSET_COL){\n\t\t\tif(IsTxdUsedByRequestedModels(streamId - STREAM_OFFSET_TXD))\n\t\t\t\tbreak;\n\t\t}else if(streamId >= STREAM_OFFSET_ANIM){\n\t\t\tassert(streamId < NUMSTREAMINFO);\n\t\t\tif(AreAnimsUsedByRequestedModels(streamId - STREAM_OFFSET_ANIM))\n\t\t\t\tbreak;\n\t\t}else\n\t\t\tbreak;\n\t\tRemoveModel(streamId);\n\t\t// so try next file\n\t\tms_aInfoForModel[streamId].GetCdPosnAndSize(posn, size);\n\t\tstreamId = GetNextFileOnCd(posn + size, true);\n\t}\n\n\tif(streamId == -1)\n\t\treturn;\n\n\tms_aInfoForModel[streamId].GetCdPosnAndSize(posn, size);\n\tif(size > (uint32)ms_streamingBufferSize){\n\t\t// Can only load big models on channel 0, and 1 has to be idle\n\t\tif(ch == 1 || ms_channel[1].state != CHANNELSTATE_IDLE)\n\t\t\treturn;\n\t\tms_bLoadingBigModel = true;\n\t}\n\n\t// Load up to 4 adjacent files\n\thaveBigFile = 0;\n\thavePed = 0;\n\ttotalSize = 0;\n\tfor(i = 0; i < 4; i++){\n\t\t// no more files we can read\n\t\tif(streamId == -1 || ms_aInfoForModel[streamId].m_loadState != STREAMSTATE_INQUEUE)\n\t\t\tbreak;\n\n\t\t// also stop at non-priority files\n\t\tms_aInfoForModel[streamId].GetCdPosnAndSize(unused, size);\n\t\tif(ms_numPriorityRequests != 0 && !ms_aInfoForModel[streamId].IsPriority())\n\t\t\tbreak;\n\n\t\t// Can't load certain combinations of files together\n\t\tif(streamId < STREAM_OFFSET_TXD){\n\t\t\tif (havePed && CModelInfo::GetModelInfo(streamId)->GetModelType() == MITYPE_PED ||\n\t\t\t    haveBigFile && CModelInfo::GetModelInfo(streamId)->GetModelType() == MITYPE_VEHICLE ||\n\t\t\t    TxdNotLoaded(CModelInfo::GetModelInfo(streamId)->GetTxdSlot()) ||\n\t\t\t    AnimNotLoaded(CModelInfo::GetModelInfo(streamId)->GetAnimFileIndex()))\n\t\t\t\tbreak;\n\t\t}else{\n\t\t\tif(haveBigFile && size > 200)\n\t\t\t\tbreak;\n\t\t}\n\n\t\t// Now add the file\n\t\tms_channel[ch].streamIds[i] = streamId;\n\t\tms_channel[ch].offsets[i] = totalSize;\n\t\ttotalSize += size;\n\n\t\t// To big for buffer, remove again\n\t\tif(totalSize > ms_streamingBufferSize && i > 0){\n\t\t\ttotalSize -= size;\n\t\t\tbreak;\n\t\t}\n\t\tif(streamId < STREAM_OFFSET_TXD){\n\t\t\tif (CModelInfo::GetModelInfo(streamId)->GetModelType() == MITYPE_PED)\n\t\t\t\thavePed = 1;\n\t\t\tif (CModelInfo::GetModelInfo(streamId)->GetModelType() == MITYPE_VEHICLE)\n\t\t\t\thaveBigFile = 1;\n\t\t}else{\n\t\t\tif(size > 200)\n\t\t\t\thaveBigFile = 1;\n\t\t}\n\t\tms_aInfoForModel[streamId].m_loadState = STREAMSTATE_READING;\n\t\tms_aInfoForModel[streamId].RemoveFromList();\n\t\tDecrementRef(streamId);\n\n\t\tstreamId = ms_aInfoForModel[streamId].m_nextID;\n\t}\n\n\t// clear remaining slots\n\tfor(; i < 4; i++)\n\t\tms_channel[ch].streamIds[i] = -1;\n\t// Now read the data\n\tassert(!(ms_bLoadingBigModel && ch == 1));\t// this would clobber the buffer\n\tif(CdStreamRead(ch, ms_pStreamingBuffer[ch], imgOffset+posn, totalSize) == STREAM_NONE)\n\t\tdebug(\"FUCKFUCKFUCK\\n\");\n\tms_channel[ch].state = CHANNELSTATE_READING;\n\tms_channel[ch].field24 = 0;\n\tms_channel[ch].size = totalSize;\n\tms_channel[ch].position = imgOffset+posn;\n\tms_channel[ch].numTries = 0;\n}\n\n// Load data previously read from disc\nbool\nCStreaming::ProcessLoadingChannel(int32 ch)\n{\n\tint status;\n\tint i, id, cdsize;\n\n\tstatus = CdStreamGetStatus(ch);\n\tif(status != STREAM_NONE){\n\t\t// busy\n\t\tif(status != STREAM_READING && status != STREAM_WAITING){\n\t\t\tms_channelError = ch;\n\t\t\tms_channel[ch].state = CHANNELSTATE_ERROR;\n\t\t\tms_channel[ch].status = status;\n\t\t}\n\t\treturn false;\n\t}\n\n\tif(ms_channel[ch].state == CHANNELSTATE_STARTED){\n\t\tms_channel[ch].state = CHANNELSTATE_IDLE;\n\t\tFinishLoadingLargeFile(&ms_pStreamingBuffer[ch][ms_channel[ch].offsets[0]*CDSTREAM_SECTOR_SIZE],\n\t\t\tms_channel[ch].streamIds[0]);\n\t\tms_channel[ch].streamIds[0] = -1;\n\t}else{\n\t\tms_channel[ch].state = CHANNELSTATE_IDLE;\n\t\tfor(i = 0; i < 4; i++){\n\t\t\tid = ms_channel[ch].streamIds[i];\n\t\t\tif(id == -1)\n\t\t\t\tcontinue;\n\n\t\t\tcdsize = ms_aInfoForModel[id].GetCdSize();\n\t\t\tif(id < STREAM_OFFSET_TXD && CModelInfo::GetModelInfo(id)->GetModelType() == MITYPE_VEHICLE &&\n\t\t\t   ms_numVehiclesLoaded >= desiredNumVehiclesLoaded &&\n\t\t\t   !RemoveLoadedVehicle() &&\n\t\t\t   (CanRemoveModel(id) || GetAvailableVehicleSlot() == -1)){\n\t\t\t\t// can't load vehicle\n\t\t\t\tRemoveModel(id);\n\t\t\t\tif(!CanRemoveModel(id))\n\t\t\t\t\tReRequestModel(id);\n\t\t\t\telse if(CTxdStore::GetNumRefs(CModelInfo::GetModelInfo(id)->GetTxdSlot()) == 0)\n\t\t\t\t\tRemoveTxd(CModelInfo::GetModelInfo(id)->GetTxdSlot());\n\t\t\t}else{\n\t\t\t\tMakeSpaceFor(cdsize * CDSTREAM_SECTOR_SIZE);\n\t\t\t\tConvertBufferToObject(&ms_pStreamingBuffer[ch][ms_channel[ch].offsets[i]*CDSTREAM_SECTOR_SIZE],\n\t\t\t\t\tid);\n\t\t\t\tif(ms_aInfoForModel[id].m_loadState == STREAMSTATE_STARTED){\n\t\t\t\t\t// queue for second part\n\t\t\t\t\tms_channel[ch].state = CHANNELSTATE_STARTED;\n\t\t\t\t\tms_channel[ch].offsets[0] = ms_channel[ch].offsets[i];\n\t\t\t\t\tms_channel[ch].streamIds[0] = id;\n\t\t\t\t\tif(i != 0)\n\t\t\t\t\t\tms_channel[ch].streamIds[i] = -1;\n\t\t\t\t}else\n\t\t\t\t\tms_channel[ch].streamIds[i] = -1;\n\t\t\t}\n\t\t}\n\t}\n\n\tif(ms_bLoadingBigModel && ms_channel[ch].state != CHANNELSTATE_STARTED){\n\t\tms_bLoadingBigModel = false;\n\t\t// reset channel 1 after loading a big model\n\t\tfor(i = 0; i < 4; i++)\n\t\t\tms_channel[1].streamIds[i] = -1;\n\t\tms_channel[1].state = CHANNELSTATE_IDLE;\n\t}\n\n\treturn true;\n}\n\nvoid\nCStreaming::RetryLoadFile(int32 ch)\n{\n\tConst char *key;\n\n\tCPad::StopPadsShaking();\n\n\tif(ms_channel[ch].numTries >= 3){\n\t\tswitch(ms_channel[ch].status){\n\t\tcase STREAM_ERROR_NOCD: key = \"NOCD\"; break;\n\t\tcase STREAM_ERROR_OPENCD: key = \"OPENCD\"; break;\n\t\tcase STREAM_ERROR_WRONGCD: key = \"WRONGCD\"; break;\n\t\tdefault: key = \"CDERROR\"; break;\n\t\t}\n\t\tCHud::SetMessage(TheText.Get(key));\n\t\tCTimer::SetCodePause(true);\n\t}\n\n\tswitch(ms_channel[ch].state){\n\tcase CHANNELSTATE_ERROR:\n\t\tms_channel[ch].numTries++;\n\t\tif (CdStreamGetStatus(ch) == STREAM_READING || CdStreamGetStatus(ch) == STREAM_WAITING) break;\n\tcase CHANNELSTATE_IDLE:\n\t\tCdStreamRead(ch, ms_pStreamingBuffer[ch], ms_channel[ch].position, ms_channel[ch].size);\n\t\tms_channel[ch].state = CHANNELSTATE_READING;\n\t\tms_channel[ch].field24 = -600;\n\t\tbreak;\n\tcase CHANNELSTATE_READING:\n\t\tif(ProcessLoadingChannel(ch)){\n\t\t\tms_channelError = -1;\n\t\t\tCTimer::SetCodePause(false);\n\t\t}\n\t\tbreak;\n\t}\n}\n\nvoid\nCStreaming::LoadRequestedModels(void)\n{\n\tstatic int currentChannel = 0;\n\n\t// We can't read with channel 1 while channel 0 is using its buffer\n\tif(ms_bLoadingBigModel)\n\t\tcurrentChannel = 0;\n\n\t// We have data, load\n\tif(ms_channel[currentChannel].state == CHANNELSTATE_READING ||\n\t   ms_channel[currentChannel].state == CHANNELSTATE_STARTED)\n\t\tProcessLoadingChannel(currentChannel);\n\n\tif(ms_channelError == -1){\n\t\t// Channel is idle, read more data\n\t\tif(ms_channel[currentChannel].state == CHANNELSTATE_IDLE)\n\t\t\tRequestModelStream(currentChannel);\n\t\t// Switch channel\n\t\tif(ms_channel[currentChannel].state != CHANNELSTATE_STARTED)\n\t\t\tcurrentChannel = 1 - currentChannel;\n\t}\n}\n\n\n// Let's load models in 4 threads; when one of them becomes idle, process the file, and fill thread with another file. Unfortunately processing models are still single-threaded.\n// Currently only supported on POSIX streamer.\n// WIP - some files are loaded swapped (CdStreamPosix problem?)\n#if 0 //def ONE_THREAD_PER_CHANNEL\nvoid\nCStreaming::LoadAllRequestedModels(bool priority)\n{\n\tstatic bool bInsideLoadAll = false;\n\tint imgOffset, streamId, status;\n\tint i;\n\tuint32 posn, size;\n\n\tif(bInsideLoadAll)\n\t\treturn;\n\tbInsideLoadAll = true;\n\n\tFlushChannels();\n\timgOffset = GetCdImageOffset(CdStreamGetLastPosn());\n\n\tint streamIds[ARRAY_SIZE(ms_pStreamingBuffer)];\n\tint streamSizes[ARRAY_SIZE(ms_pStreamingBuffer)];\n\tint streamPoses[ARRAY_SIZE(ms_pStreamingBuffer)];\n\tint readOrder[4] = {-1}; // Channel IDs ordered by read time\n\tint readI = 0;\n\tint processI = 0;\n\tbool first = true;\n\n\t// All those \"first\" checks are because of variables aren't initialized in first pass.\n\n\twhile (true) {\n\t\tfor (int i=0; i<ARRAY_SIZE(ms_pStreamingBuffer); i++) {\n\n\t\t\t// Channel has file to load\n\t\t\tif (!first && streamIds[i] != -1) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif(ms_endRequestedList.m_prev != &ms_startRequestedList){\n\t\t\t\tstreamId = GetNextFileOnCd(0, priority);\n\t\t\t\tif(streamId == -1){\n\t\t\t\t\tstreamIds[i] = -1;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif (ms_aInfoForModel[streamId].GetCdPosnAndSize(posn, size)) {\n\t\t\t\t\tstreamIds[i] = -1;\n\n\t\t\t\t\t// Big file, needs 2 buffer\n\t\t\t\t\tif (size > (uint32)ms_streamingBufferSize) {\n\t\t\t\t\t\tif (i + 1 == ARRAY_SIZE(ms_pStreamingBuffer))\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\telse if (!first && streamIds[i+1] != -1)\n\t\t\t\t\t\t\tcontinue;\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Buffer of current channel is part of a \"big file\", pass\n\t\t\t\t\t\tif (i != 0 && streamIds[i-1] != -1 && streamSizes[i-1] > (uint32)ms_streamingBufferSize)\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tms_aInfoForModel[streamId].RemoveFromList();\n\t\t\t\t\tDecrementRef(streamId);\n\n\t\t\t\t\tstreamIds[i] = streamId;\n\t\t\t\t\tstreamSizes[i] = size;\n\t\t\t\t\tstreamPoses[i] = posn;\n\n\t\t\t\t\tif (!first)\n\t\t\t\t\t\tassert(readOrder[readI] == -1);\n\n\t\t\t\t\t//printf(\"read: order %d, ch %d, id %d, size %d\\n\", readI, i, streamId, size);\n\n\t\t\t\t\tCdStreamRead(i, ms_pStreamingBuffer[i], imgOffset+posn, size);\n\t\t\t\t\treadOrder[readI] = i;\n\t\t\t\t\tif (first && readI+1 != ARRAY_SIZE(readOrder))\n\t\t\t\t\t\treadOrder[readI+1] = -1;\n\n\t\t\t\t\treadI = (readI + 1) % ARRAY_SIZE(readOrder);\n\t\t\t\t} else {\n\t\t\t\t\tms_aInfoForModel[streamId].RemoveFromList();\n\t\t\t\t\tDecrementRef(streamId);\n\n\t\t\t\t\tms_aInfoForModel[streamId].m_loadState = STREAMSTATE_LOADED;\n\t\t\t\t\tstreamIds[i] = -1;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tstreamIds[i] = -1;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tfirst = false;\n\t\tint nextChannel = readOrder[processI];\n\n\t\t// Now start processing\n\t\tif (nextChannel == -1 || streamIds[nextChannel] == -1)\n\t\t\tbreak;\n\n\t\t//printf(\"process: order %d, ch %d, id %d\\n\", processI, nextChannel, streamIds[nextChannel]);\n\n\t\t// Try again on error\n\t\twhile (CdStreamSync(nextChannel) != STREAM_NONE) {\n\t\t\tCdStreamRead(nextChannel, ms_pStreamingBuffer[nextChannel], imgOffset+streamPoses[nextChannel], streamSizes[nextChannel]);\n\t\t}\n\t\tms_aInfoForModel[streamIds[nextChannel]].m_loadState = STREAMSTATE_READING;\n\n\t\tMakeSpaceFor(streamSizes[nextChannel] * CDSTREAM_SECTOR_SIZE);\n\t\tConvertBufferToObject(ms_pStreamingBuffer[nextChannel], streamIds[nextChannel]);\n\t\tif(ms_aInfoForModel[streamIds[nextChannel]].m_loadState == STREAMSTATE_STARTED)\n\t\t\tFinishLoadingLargeFile(ms_pStreamingBuffer[nextChannel], streamIds[nextChannel]);\n\n\t\tif(streamIds[nextChannel] < STREAM_OFFSET_TXD){\n\t\t\tCSimpleModelInfo *mi = (CSimpleModelInfo*)CModelInfo::GetModelInfo(streamIds[nextChannel]);\n\t\t\tif(mi->IsSimple())\n\t\t\t\tmi->m_alpha = 255;\n\t\t}\n\t\tstreamIds[nextChannel] = -1;\n\t\treadOrder[processI] = -1;\n\t\tprocessI = (processI + 1) % ARRAY_SIZE(readOrder);\n\t}\n\n\tms_bLoadingBigModel = false;\n\tfor(i = 0; i < 4; i++){\n\t\tms_channel[1].streamIds[i] = -1;\n\t\tms_channel[1].offsets[i] = -1;\n\t}\n\tms_channel[1].state = CHANNELSTATE_IDLE;\n\tbInsideLoadAll = false;\n}\n#else\nvoid\nCStreaming::LoadAllRequestedModels(bool priority)\n{\n\tstatic bool bInsideLoadAll = false;\n\tint imgOffset, streamId, status;\n\tint i;\n\tuint32 posn, size;\n\n\tint numRequests = 4*ms_numModelsRequested;\n\n\tif(bInsideLoadAll)\n\t\treturn;\n\tbInsideLoadAll = true;\n\n\tif(priority)\n\t\tnumRequests = ms_numPriorityRequests;\n\n\tFlushChannels();\n\timgOffset = GetCdImageOffset(CdStreamGetLastPosn());\n\n\twhile(ms_endRequestedList.m_prev != &ms_startRequestedList && numRequests > 0){\n\t\tnumRequests--;\n\t\tstreamId = GetNextFileOnCd(0, priority);\n\t\tif(streamId == -1)\n\t\t\tbreak;\n\n\t\tms_aInfoForModel[streamId].RemoveFromList();\n\t\tms_channel[0].streamIds[0] = streamId;\n\t\tDecrementRef(streamId);\n\n\t\tif(ms_aInfoForModel[streamId].GetCdPosnAndSize(posn, size)){\n\t\t\tdo\n\t\t\t\tstatus = CdStreamRead(0, ms_pStreamingBuffer[0], imgOffset+posn, size);\n\t\t\twhile(CdStreamSync(0) || status == STREAM_NONE);\n\t\t\tms_aInfoForModel[streamId].m_loadState = STREAMSTATE_READING;\n\n\t\t\tMakeSpaceFor(size * CDSTREAM_SECTOR_SIZE);\n\t\t\tConvertBufferToObject(ms_pStreamingBuffer[0], streamId);\n\t\t\tif(ms_aInfoForModel[streamId].m_loadState == STREAMSTATE_STARTED)\n\t\t\t\tFinishLoadingLargeFile(ms_pStreamingBuffer[0], streamId);\n\n\t\t\tif(streamId < STREAM_OFFSET_TXD){\n\t\t\t\tCSimpleModelInfo *mi = (CSimpleModelInfo*)CModelInfo::GetModelInfo(streamId);\n\t\t\t\tif(mi->IsSimple())\n\t\t\t\t\tmi->m_alpha = 255;\n\t\t\t}\n\t\t}else{\n\t\t\t// empty\n\t\t\tms_aInfoForModel[streamId].m_loadState = STREAMSTATE_LOADED;\n\t\t}\n\t}\n\n\tms_bLoadingBigModel = false;\n\tfor(i = 0; i < 4; i++){\n\t\tms_channel[1].streamIds[i] = -1;\n\t\tms_channel[1].offsets[i] = -1;\n\t}\n\tms_channel[1].state = CHANNELSTATE_IDLE;\n\tbInsideLoadAll = false;\n}\n#endif\n\nvoid\nCStreaming::FlushChannels(void)\n{\n\tif(ms_channel[1].state == CHANNELSTATE_STARTED)\n\t\tProcessLoadingChannel(1);\n\n\tif(ms_channel[0].state == CHANNELSTATE_READING){\n\t\tCdStreamSync(0);\n\t\tProcessLoadingChannel(0);\n\t}\n\tif(ms_channel[0].state == CHANNELSTATE_STARTED)\n\t\tProcessLoadingChannel(0);\n\n\tif(ms_channel[1].state == CHANNELSTATE_READING){\n\t\tCdStreamSync(1);\n\t\tProcessLoadingChannel(1);\n\t}\n\tif(ms_channel[1].state == CHANNELSTATE_STARTED)\n\t\tProcessLoadingChannel(1);\n}\n\nvoid\nCStreaming::FlushRequestList(void)\n{\n\tCStreamingInfo *si, *next;\n\n\tfor(si = ms_startRequestedList.m_next; si != &ms_endRequestedList; si = next){\n\t\tnext = si->m_next;\n\t\tRemoveModel(si - ms_aInfoForModel);\n\t}\n#ifdef FLUSHABLE_STREAMING\n\tif(ms_channel[0].state == CHANNELSTATE_READING) {\n\t\tflushStream[0] = 1;\n\t}\n\tif(ms_channel[1].state == CHANNELSTATE_READING) {\n\t\tflushStream[1] = 1;\n\t}\n#endif\n\tFlushChannels();\n}\n\n\nvoid\nCStreaming::ImGonnaUseStreamingMemory(void)\n{\n\tPUSH_MEMID(MEMID_STREAM);\n}\n\nvoid\nCStreaming::IHaveUsedStreamingMemory(void)\n{\n\tPOP_MEMID();\n\tUpdateMemoryUsed();\n}\n\nvoid\nCStreaming::UpdateMemoryUsed(void)\n{\n#ifdef USE_CUSTOM_ALLOCATOR\n\tms_memoryUsed =\n\t\tgMainHeap.GetMemoryUsed(MEMID_STREAM) +\n\t\tgMainHeap.GetMemoryUsed(MEMID_STREAM_MODELS) +\n\t\tgMainHeap.GetMemoryUsed(MEMID_STREAM_TEXUTRES) +\n\t\tgMainHeap.GetMemoryUsed(MEMID_STREAM_COLLISION) +\n\t\tgMainHeap.GetMemoryUsed(MEMID_STREAM_ANIMATION);\n#endif\n}\n\n#define STREAM_DIST 80.0f\n\nvoid\nCStreaming::AddModelsToRequestList(const CVector &pos, int32 flags)\n{\n\tfloat xmin, xmax, ymin, ymax;\n\tint ixmin, ixmax, iymin, iymax;\n\tint ix, iy;\n\tint dx, dy, d;\n\tCSector *sect;\n\n\txmin = pos.x - STREAM_DIST;\n\tymin = pos.y - STREAM_DIST;\n\txmax = pos.x + STREAM_DIST;\n\tymax = pos.y + STREAM_DIST;\n\n\tixmin = CWorld::GetSectorIndexX(xmin);\n\tif(ixmin < 0) ixmin = 0;\n\tixmax = CWorld::GetSectorIndexX(xmax);\n\tif(ixmax >= NUMSECTORS_X) ixmax = NUMSECTORS_X-1;\n\tiymin = CWorld::GetSectorIndexY(ymin);\n\tif(iymin < 0) iymin = 0;\n\tiymax = CWorld::GetSectorIndexY(ymax);\n\tif(iymax >= NUMSECTORS_Y) iymax = NUMSECTORS_Y-1;\n\n\tCWorld::AdvanceCurrentScanCode();\n\n\tfor(iy = iymin; iy <= iymax; iy++){\n\t\tdy = iy - CWorld::GetSectorIndexY(pos.y);\n\t\tfor(ix = ixmin; ix <= ixmax; ix++){\n\n\t\t\tif(CRenderer::m_loadingPriority && ms_numModelsRequested > 5)\n\t\t\t\treturn;\n\n\t\t\tdx = ix - CWorld::GetSectorIndexX(pos.x);\n\t\t\td = dx*dx + dy*dy;\n\t\t\tsect = CWorld::GetSector(ix, iy);\n\t\t\tif(d <= 0){\n\t\t\t\tProcessEntitiesInSectorList(sect->m_lists[ENTITYLIST_BUILDINGS], flags);\n\t\t\t\tProcessEntitiesInSectorList(sect->m_lists[ENTITYLIST_BUILDINGS_OVERLAP], flags);\n\t\t\t\tProcessEntitiesInSectorList(sect->m_lists[ENTITYLIST_OBJECTS], flags);\n\t\t\t\tProcessEntitiesInSectorList(sect->m_lists[ENTITYLIST_DUMMIES], flags);\n\t\t\t}else if(d <= 3*3){\n\t\t\t\tProcessEntitiesInSectorList(sect->m_lists[ENTITYLIST_BUILDINGS], pos.x, pos.y, xmin, ymin, xmax, ymax, flags);\n\t\t\t\tProcessEntitiesInSectorList(sect->m_lists[ENTITYLIST_BUILDINGS_OVERLAP], pos.x, pos.y, xmin, ymin, xmax, ymax, flags);\n\t\t\t\tProcessEntitiesInSectorList(sect->m_lists[ENTITYLIST_OBJECTS], pos.x, pos.y, xmin, ymin, xmax, ymax, flags);\n\t\t\t\tProcessEntitiesInSectorList(sect->m_lists[ENTITYLIST_DUMMIES], pos.x, pos.y, xmin, ymin, xmax, ymax, flags);\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nCStreaming::ProcessEntitiesInSectorList(CPtrList &list, float x, float y, float xmin, float ymin, float xmax, float ymax, int32 flags)\n{\n\tCPtrNode *node;\n\tCEntity *e;\n\tfloat lodDistSq;\n\tCVector2D pos;\n\n\tfor(node = list.first; node; node = node->next){\n\t\te = (CEntity*)node->item;\n\n\t\tif(e->m_scanCode == CWorld::GetCurrentScanCode())\n\t\t\tcontinue;\n\n\t\te->m_scanCode = CWorld::GetCurrentScanCode();\n\t\tif(!e->bStreamingDontDelete && IsAreaVisible(e->m_area) && !e->bDontStream && e->bIsVisible){\n\t\t\tCTimeModelInfo *mi = (CTimeModelInfo*)CModelInfo::GetModelInfo(e->GetModelIndex());\n\t\t\tif (mi->GetModelType() != MITYPE_TIME || CClock::GetIsTimeInRange(mi->GetTimeOn(), mi->GetTimeOff())) {\n\t\t\t\tlodDistSq = sq(mi->GetLargestLodDistance());\n\t\t\t\tlodDistSq = Min(lodDistSq, sq(STREAM_DIST));\n\t\t\t\tpos = CVector2D(e->GetPosition());\n\t\t\t\tif(xmin < pos.x && pos.x < xmax &&\n\t\t\t\t   ymin < pos.y && pos.y < ymax &&\n\t\t\t\t   (CVector2D(x, y) - pos).MagnitudeSqr() < lodDistSq)\n\t\t\t\t\tRequestModel(e->GetModelIndex(), flags);\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nCStreaming::ProcessEntitiesInSectorList(CPtrList &list, int32 flags)\n{\n\tCPtrNode *node;\n\tCEntity *e;\n\n\tfor(node = list.first; node; node = node->next){\n\t\te = (CEntity*)node->item;\n\n\t\tif(e->m_scanCode == CWorld::GetCurrentScanCode())\n\t\t\tcontinue;\n\n\t\te->m_scanCode = CWorld::GetCurrentScanCode();\n\t\tif(!e->bStreamingDontDelete && IsAreaVisible(e->m_area) && !e->bDontStream && e->bIsVisible){\n\t\t\tCTimeModelInfo *mi = (CTimeModelInfo*)CModelInfo::GetModelInfo(e->GetModelIndex());\n\t\t\tif (mi->GetModelType() != MITYPE_TIME || CClock::GetIsTimeInRange(mi->GetTimeOn(), mi->GetTimeOff()))\n\t\t\t\tRequestModel(e->GetModelIndex(), flags);\n\t\t}\n\t}\n}\n\nvoid\nCStreaming::DeleteFarAwayRwObjects(const CVector &pos)\n{\n\tint posx, posy;\n\tint x, y;\n\tint r, i;\n\tCSector *sect;\n\n\tposx = CWorld::GetSectorIndexX(pos.x);\n\tposy = CWorld::GetSectorIndexY(pos.y);\n\n\t// Move oldSectorX/Y to new sector and delete RW objects in its \"wake\" for every step:\n\t// O is the old sector, <- is the direction in which we move it,\n\t// X are the sectors we delete RW objects from (except we go up to 10)\n\t//            X\n\t//          X X\n\t//        X X X\n\t//        X X X\n\t// <- O   X X X\n\t//        X X X\n\t//        X X X\n\t//          X X\n\t//            X\n\n\twhile(posx != ms_oldSectorX){\n\t\tif(posx < ms_oldSectorX){\n\t\t\tfor(r = 2; r <= 10; r++){\n\t\t\t\tx = ms_oldSectorX + r;\n\t\t\t\tif(x < 0)\n\t\t\t\t\tcontinue;\n\t\t\t\tif(x >= NUMSECTORS_X)\n\t\t\t\t\tbreak;\n\n\t\t\t\tfor(i = -r; i <= r; i++){\n\t\t\t\t\ty = ms_oldSectorY + i;\n\t\t\t\t\tif(y < 0)\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\tif(y >= NUMSECTORS_Y)\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tsect = CWorld::GetSector(x, y);\n\t\t\t\t\tDeleteRwObjectsInSectorList(sect->m_lists[ENTITYLIST_BUILDINGS]);\n\t\t\t\t\tDeleteRwObjectsInOverlapSectorList(sect->m_lists[ENTITYLIST_BUILDINGS_OVERLAP], ms_oldSectorX, ms_oldSectorY);\n\t\t\t\t\tDeleteRwObjectsInSectorList(sect->m_lists[ENTITYLIST_OBJECTS]);\n\t\t\t\t\tDeleteRwObjectsInSectorList(sect->m_lists[ENTITYLIST_DUMMIES]);\n\t\t\t\t}\n\t\t\t}\n\t\t\tms_oldSectorX--;\n\t\t}else{\n\t\t\tfor(r = 2; r <= 10; r++){\n\t\t\t\tx = ms_oldSectorX - r;\n\t\t\t\tif(x < 0)\n\t\t\t\t\tbreak;\n\t\t\t\tif(x >= NUMSECTORS_X)\n\t\t\t\t\tcontinue;\n\n\t\t\t\tfor(i = -r; i <= r; i++){\n\t\t\t\t\ty = ms_oldSectorY + i;\n\t\t\t\t\tif(y < 0)\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\tif(y >= NUMSECTORS_Y)\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tsect = CWorld::GetSector(x, y);\n\t\t\t\t\tDeleteRwObjectsInSectorList(sect->m_lists[ENTITYLIST_BUILDINGS]);\n\t\t\t\t\tDeleteRwObjectsInOverlapSectorList(sect->m_lists[ENTITYLIST_BUILDINGS_OVERLAP], ms_oldSectorX, ms_oldSectorY);\n\t\t\t\t\tDeleteRwObjectsInSectorList(sect->m_lists[ENTITYLIST_OBJECTS]);\n\t\t\t\t\tDeleteRwObjectsInSectorList(sect->m_lists[ENTITYLIST_DUMMIES]);\n\t\t\t\t}\n\t\t\t}\n\t\t\tms_oldSectorX++;\n\t\t}\n\t}\n\n\twhile(posy != ms_oldSectorY){\n\t\tif(posy < ms_oldSectorY){\n\t\t\tfor(r = 2; r <= 10; r++){\n\t\t\t\ty = ms_oldSectorY + r;\n\t\t\t\tif(y < 0)\n\t\t\t\t\tcontinue;\n\t\t\t\tif(y >= NUMSECTORS_Y)\n\t\t\t\t\tbreak;\n\n\t\t\t\tfor(i = -r; i <= r; i++){\n\t\t\t\t\tx = ms_oldSectorX + i;\n\t\t\t\t\tif(x < 0)\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\tif(x >= NUMSECTORS_X)\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tsect = CWorld::GetSector(x, y);\n\t\t\t\t\tDeleteRwObjectsInSectorList(sect->m_lists[ENTITYLIST_BUILDINGS]);\n\t\t\t\t\tDeleteRwObjectsInOverlapSectorList(sect->m_lists[ENTITYLIST_BUILDINGS_OVERLAP], ms_oldSectorX, ms_oldSectorY);\n\t\t\t\t\tDeleteRwObjectsInSectorList(sect->m_lists[ENTITYLIST_OBJECTS]);\n\t\t\t\t\tDeleteRwObjectsInSectorList(sect->m_lists[ENTITYLIST_DUMMIES]);\n\t\t\t\t}\n\t\t\t}\n\t\t\tms_oldSectorY--;\n\t\t}else{\n\t\t\tfor(r = 2; r <= 10; r++){\n\t\t\t\ty = ms_oldSectorY - r;\n\t\t\t\tif(y < 0)\n\t\t\t\t\tbreak;\n\t\t\t\tif(y >= NUMSECTORS_Y)\n\t\t\t\t\tcontinue;\n\n\t\t\t\tfor(i = -r; i <= r; i++){\n\t\t\t\t\tx = ms_oldSectorX + i;\n\t\t\t\t\tif(x < 0)\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\tif(x >= NUMSECTORS_X)\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tsect = CWorld::GetSector(x, y);\n\t\t\t\t\tDeleteRwObjectsInSectorList(sect->m_lists[ENTITYLIST_BUILDINGS]);\n\t\t\t\t\tDeleteRwObjectsInOverlapSectorList(sect->m_lists[ENTITYLIST_BUILDINGS_OVERLAP], ms_oldSectorX, ms_oldSectorY);\n\t\t\t\t\tDeleteRwObjectsInSectorList(sect->m_lists[ENTITYLIST_OBJECTS]);\n\t\t\t\t\tDeleteRwObjectsInSectorList(sect->m_lists[ENTITYLIST_DUMMIES]);\n\t\t\t\t}\n\t\t\t}\n\t\t\tms_oldSectorY++;\n\t\t}\n\t}\n}\n\nvoid\nCStreaming::DeleteAllRwObjects(void)\n{\n\tint x, y;\n\tCSector *sect;\n\n\tfor(x = 0; x < NUMSECTORS_X; x++)\n\t\tfor(y = 0; y < NUMSECTORS_Y; y++){\n\t\t\tsect = CWorld::GetSector(x, y);\n\t\t\tDeleteRwObjectsInSectorList(sect->m_lists[ENTITYLIST_BUILDINGS]);\n\t\t\tDeleteRwObjectsInSectorList(sect->m_lists[ENTITYLIST_BUILDINGS_OVERLAP]);\n\t\t\tDeleteRwObjectsInSectorList(sect->m_lists[ENTITYLIST_OBJECTS]);\n\t\t\tDeleteRwObjectsInSectorList(sect->m_lists[ENTITYLIST_OBJECTS_OVERLAP]);\n\t\t\tDeleteRwObjectsInSectorList(sect->m_lists[ENTITYLIST_DUMMIES]);\n\t\t\tDeleteRwObjectsInSectorList(sect->m_lists[ENTITYLIST_DUMMIES_OVERLAP]);\n\t\t}\n}\n\nvoid\nCStreaming::DeleteRwObjectsAfterDeath(const CVector &pos)\n{\n\tint ix, iy;\n\tint x, y;\n\tCSector *sect;\n\n\tix = CWorld::GetSectorIndexX(pos.x);\n\tiy = CWorld::GetSectorIndexY(pos.y);\n\n\tfor(x = 0; x < NUMSECTORS_X; x++)\n\t\tfor(y = 0; y < NUMSECTORS_Y; y++)\n\t\t\tif(Abs(ix - x) > 3.0f &&\n\t\t\t   Abs(iy - y) > 3.0f){\n\t\t\t\tsect = CWorld::GetSector(x, y);\n\t\t\t\tDeleteRwObjectsInSectorList(sect->m_lists[ENTITYLIST_BUILDINGS]);\n\t\t\t\tDeleteRwObjectsInSectorList(sect->m_lists[ENTITYLIST_BUILDINGS_OVERLAP]);\n\t\t\t\tDeleteRwObjectsInSectorList(sect->m_lists[ENTITYLIST_OBJECTS]);\n\t\t\t\tDeleteRwObjectsInSectorList(sect->m_lists[ENTITYLIST_OBJECTS_OVERLAP]);\n\t\t\t\tDeleteRwObjectsInSectorList(sect->m_lists[ENTITYLIST_DUMMIES]);\n\t\t\t\tDeleteRwObjectsInSectorList(sect->m_lists[ENTITYLIST_DUMMIES_OVERLAP]);\n\t\t\t}\n}\n\nvoid\nCStreaming::DeleteRwObjectsBehindCamera(size_t mem)\n{\n\tint ix, iy;\n\tint x, y;\n\tint xmin, xmax, ymin, ymax;\n\tint inc;\n\tCSector *sect;\n\n\tif(ms_memoryUsed < mem)\n\t\treturn;\n\n\tix = CWorld::GetSectorIndexX(TheCamera.GetPosition().x);\n\tiy = CWorld::GetSectorIndexY(TheCamera.GetPosition().y);\n\n\tif(Abs(TheCamera.GetForward().x) > Abs(TheCamera.GetForward().y)){\n\t\t// looking west/east\n\n\t\tymin = Max(iy - 10, 0);\n\t\tymax = Min(iy + 10, NUMSECTORS_Y - 1);\n\t\tassert(ymin <= ymax);\n\n\t\t// Delete a block of sectors that we know is behind the camera\n\t\tif(TheCamera.GetForward().x > 0.0f){\n\t\t\t// looking east\n\t\t\txmax = Max(ix - 2, 0);\n\t\t\txmin = Max(ix - 10, 0);\n\t\t\tinc = 1;\n\t\t}else{\n\t\t\t// looking west\n\t\t\txmax = Min(ix + 2, NUMSECTORS_X - 1);\n\t\t\txmin = Min(ix + 10, NUMSECTORS_X - 1);\n\t\t\tinc = -1;\n\t\t}\n\t\tfor(y = ymin; y <= ymax; y++){\n\t\t\tfor(x = xmin; x != xmax; x += inc){\n\t\t\t\tsect = CWorld::GetSector(x, y);\n\t\t\t\tif(DeleteRwObjectsBehindCameraInSectorList(sect->m_lists[ENTITYLIST_BUILDINGS], mem) ||\n\t\t\t\t   DeleteRwObjectsBehindCameraInSectorList(sect->m_lists[ENTITYLIST_DUMMIES], mem) ||\n\t\t\t\t   DeleteRwObjectsBehindCameraInSectorList(sect->m_lists[ENTITYLIST_OBJECTS], mem))\n\t\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t\n\t\twhile(RemoveLoadedZoneModel())\n\t\t\tif(ms_memoryUsed < mem)\n\t\t\t\treturn;\n\n\t\t// Now a block that intersects with the camera's frustum\n\t\tif(TheCamera.GetForward().x > 0.0f){\n\t\t\t// looking east\n\t\t\txmax = Max(ix + 10, 0);\n\t\t\txmin = Max(ix - 2, 0);\n\t\t\tinc = 1;\n\t\t}else{\n\t\t\t// looking west\n\t\t\txmax = Min(ix - 10, NUMSECTORS_X - 1);\n\t\t\txmin = Min(ix + 2, NUMSECTORS_X - 1);\n\t\t\tinc = -1;\n\t\t}\n\t\tfor(y = ymin; y <= ymax; y++){\n\t\t\tfor(x = xmin; x != xmax; x += inc){\n\t\t\t\tsect = CWorld::GetSector(x, y);\n\t\t\t\tif(DeleteRwObjectsNotInFrustumInSectorList(sect->m_lists[ENTITYLIST_BUILDINGS], mem) ||\n\t\t\t\t   DeleteRwObjectsNotInFrustumInSectorList(sect->m_lists[ENTITYLIST_DUMMIES], mem) ||\n\t\t\t\t   DeleteRwObjectsNotInFrustumInSectorList(sect->m_lists[ENTITYLIST_OBJECTS], mem))\n\t\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t// As last resort, delete objects from the last step more aggressively\n\t\tfor(y = ymin; y <= ymax; y++){\n\t\t\tfor(x = xmax; x != xmin; x -= inc){\n\t\t\t\tsect = CWorld::GetSector(x, y);\n\t\t\t\tif(DeleteRwObjectsBehindCameraInSectorList(sect->m_lists[ENTITYLIST_BUILDINGS], mem) ||\n\t\t\t\t   DeleteRwObjectsBehindCameraInSectorList(sect->m_lists[ENTITYLIST_DUMMIES], mem) ||\n\t\t\t\t   DeleteRwObjectsBehindCameraInSectorList(sect->m_lists[ENTITYLIST_OBJECTS], mem))\n\t\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t}else{\n\t\t// looking north/south\n\n\t\txmin = Max(ix - 10, 0);\n\t\txmax = Min(ix + 10, NUMSECTORS_X - 1);\n\t\tassert(xmin <= xmax);\n\n\t\t// Delete a block of sectors that we know is behind the camera\n\t\tif(TheCamera.GetForward().y > 0.0f){\n\t\t\t// looking north\n\t\t\tymax = Max(iy - 2, 0);\n\t\t\tymin = Max(iy - 10, 0);\n\t\t\tinc = 1;\n\t\t}else{\n\t\t\t// looking south\n\t\t\tymax = Min(iy + 2, NUMSECTORS_Y - 1);\n\t\t\tymin = Min(iy + 10, NUMSECTORS_Y - 1);\n\t\t\tinc = -1;\n\t\t}\n\t\tfor(x = xmin; x <= xmax; x++){\n\t\t\tfor(y = ymin; y != ymax; y += inc){\n\t\t\t\tsect = CWorld::GetSector(x, y);\n\t\t\t\tif(DeleteRwObjectsBehindCameraInSectorList(sect->m_lists[ENTITYLIST_BUILDINGS], mem) ||\n\t\t\t\t   DeleteRwObjectsBehindCameraInSectorList(sect->m_lists[ENTITYLIST_DUMMIES], mem) ||\n\t\t\t\t   DeleteRwObjectsBehindCameraInSectorList(sect->m_lists[ENTITYLIST_OBJECTS], mem))\n\t\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\twhile(RemoveLoadedZoneModel())\n\t\t\tif(ms_memoryUsed < mem)\n\t\t\t\treturn;\n\n\t\t// Now a block that intersects with the camera's frustum\n\t\tif(TheCamera.GetForward().y > 0.0f){\n\t\t\t// looking north\n\t\t\tymax = Max(iy + 10, 0);\n\t\t\tymin = Max(iy - 2, 0);\n\t\t\tinc = 1;\n\t\t}else{\n\t\t\t// looking south\n\t\t\tymax = Min(iy - 10, NUMSECTORS_Y - 1);\n\t\t\tymin = Min(iy + 2, NUMSECTORS_Y - 1);\n\t\t\tinc = -1;\n\t\t}\n\t\tfor(x = xmin; x <= xmax; x++){\n\t\t\tfor(y = ymin; y != ymax; y += inc){\n\t\t\t\tsect = CWorld::GetSector(x, y);\n\t\t\t\tif(DeleteRwObjectsNotInFrustumInSectorList(sect->m_lists[ENTITYLIST_BUILDINGS], mem) ||\n\t\t\t\t   DeleteRwObjectsNotInFrustumInSectorList(sect->m_lists[ENTITYLIST_DUMMIES], mem) ||\n\t\t\t\t   DeleteRwObjectsNotInFrustumInSectorList(sect->m_lists[ENTITYLIST_OBJECTS], mem))\n\t\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n// this is gone in mobile together with RemoveReferencedTxds\n//\t\tif(RemoveReferencedTxds(mem))\n//\t\t\treturn;\n\n\t\t// As last resort, delete objects from the last step more aggressively\n\t\tfor(x = xmin; x <= xmax; x++){\n\t\t\tfor(y = ymax; y != ymin; y -= inc){\n\t\t\t\tsect = CWorld::GetSector(x, y);\n\t\t\t\tif(DeleteRwObjectsBehindCameraInSectorList(sect->m_lists[ENTITYLIST_BUILDINGS], mem) ||\n\t\t\t\t   DeleteRwObjectsBehindCameraInSectorList(sect->m_lists[ENTITYLIST_DUMMIES], mem) ||\n\t\t\t\t   DeleteRwObjectsBehindCameraInSectorList(sect->m_lists[ENTITYLIST_OBJECTS], mem))\n\t\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t}\n\n\twhile(ms_memoryUsed >= mem && RemoveLeastUsedModel(0));\n}\n\nvoid\nCStreaming::DeleteRwObjectsInSectorList(CPtrList &list)\n{\n\tCPtrNode *node;\n\tCEntity *e;\n\n\tfor(node = list.first; node; node = node->next){\n\t\te = (CEntity*)node->item;\n\t\tif(!e->bStreamingDontDelete && !e->bImBeingRendered)\n\t\t\te->DeleteRwObject();\n\t}\n}\n\nvoid\nCStreaming::DeleteRwObjectsInOverlapSectorList(CPtrList &list, int32 x, int32 y)\n{\n\tCPtrNode *node;\n\tCEntity *e;\n\n\tfor(node = list.first; node; node = node->next){\n\t\te = (CEntity*)node->item;\n\t\tif(e->m_rwObject && !e->bStreamingDontDelete && !e->bImBeingRendered){\n\t\t\t// Now this is pretty weird...\n\t\t\tif(Abs(CWorld::GetSectorIndexX(e->GetPosition().x) - x) >= 1.6f)\n//\t\t\t{\n\t\t\t\te->DeleteRwObject();\n//\t\t\t\treturn;\t\t// BUG?\n//\t\t\t}\n\t\t\telse\t// FIX?\n\t\t\tif(Abs(CWorld::GetSectorIndexY(e->GetPosition().y) - y) >= 1.6f)\n\t\t\t\te->DeleteRwObject();\n\t\t}\n\t}\n}\n\nbool\nCStreaming::DeleteRwObjectsBehindCameraInSectorList(CPtrList &list, size_t mem)\n{\n\tCPtrNode *node;\n\tCEntity *e;\n\n\tfor(node = list.first; node; node = node->next){\n\t\te = (CEntity*)node->item;\n\t\tif(!e->bStreamingDontDelete && !e->bImBeingRendered &&\n\t\t   e->m_rwObject && ms_aInfoForModel[e->GetModelIndex()].m_next &&\n\t\t   FindPlayerPed()->m_pCurSurface != e){\n\t\t\te->DeleteRwObject();\n\t\t\tif (CModelInfo::GetModelInfo(e->GetModelIndex())->GetNumRefs() == 0) {\n\t\t\t\tRemoveModel(e->GetModelIndex());\n\t\t\t\tif(ms_memoryUsed < mem)\n\t\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t}\n\treturn false;\n}\n\nbool\nCStreaming::DeleteRwObjectsNotInFrustumInSectorList(CPtrList &list, size_t mem)\n{\n\tCPtrNode *node;\n\tCEntity *e;\n\n\tfor(node = list.first; node; node = node->next){\n\t\te = (CEntity*)node->item;\n\t\tif(!e->bStreamingDontDelete && !e->bImBeingRendered &&\n\t\t   e->m_rwObject && (!e->IsVisible() || e->bOffscreen) && ms_aInfoForModel[e->GetModelIndex()].m_next){\n\t\t\te->DeleteRwObject();\n\t\t\tif (CModelInfo::GetModelInfo(e->GetModelIndex())->GetNumRefs() == 0) {\n\t\t\t\tRemoveModel(e->GetModelIndex());\n\t\t\t\tif(ms_memoryUsed < mem)\n\t\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t}\n\treturn false;\n}\n\nvoid\nCStreaming::MakeSpaceFor(int32 size)\n{\n#ifdef FIX_BUGS\n#define MB (1024 * 1024)\n\tif(ms_memoryAvailable == 0) {\n\t\textern size_t _dwMemAvailPhys;\n\t\tms_memoryAvailable = (_dwMemAvailPhys - 10 * MB) / 2;\n\t\tif(ms_memoryAvailable < 65 * MB) ms_memoryAvailable = 65 * MB;\n\t}\n#undef MB\n#endif\n\twhile(ms_memoryUsed >= ms_memoryAvailable - size)\n\t\tif(!RemoveLeastUsedModel(STREAMFLAGS_20)){\n\t\t\tDeleteRwObjectsBehindCamera(ms_memoryAvailable - size);\n\t\t\treturn;\n\t\t}\n}\n\nvoid\nCStreaming::LoadScene(const CVector &pos)\n{\n\tCStreamingInfo *si, *prev;\n\teLevelName level;\n\n\tlevel = CTheZones::GetLevelFromPosition(&pos);\n\tdebug(\"Start load scene\\n\");\n\tfor(si = ms_endRequestedList.m_prev; si != &ms_startRequestedList; si = prev){\n\t\tprev = si->m_prev;\n\t\tif((si->m_flags & (STREAMFLAGS_KEEP_IN_MEMORY|STREAMFLAGS_PRIORITY)) == 0)\n\t\t\tRemoveModel(si - ms_aInfoForModel);\n\t}\n\tCRenderer::m_loadingPriority = false;\n\tDeleteAllRwObjects();\n\tif(level == LEVEL_GENERIC)\n\t\tlevel = CGame::currLevel;\n\tCGame::currLevel = level;\n\tRemoveUnusedBigBuildings(level);\n\tRequestBigBuildings(level, pos);\n\tRequestBigBuildings(LEVEL_GENERIC, pos);\n\tRemoveIslandsNotUsed(level);\n\tLoadAllRequestedModels(false);\n\tInstanceBigBuildings(level, pos);\n\tInstanceBigBuildings(LEVEL_GENERIC, pos);\n\tAddModelsToRequestList(pos, STREAMFLAGS_20);\n\tCRadar::StreamRadarSections(pos);\n\n\tif (!CGame::IsInInterior()) {\n\t\tfor (int i = 0; i < 5; i++) {\n\t\t\tCZoneInfo zone;\n\t\t\tCTheZones::GetZoneInfoForTimeOfDay(&pos, &zone);\n\t\t\tint32 model = CCarCtrl::ChooseCarModelToLoad(CCarCtrl::ChooseCarRating(&zone));\n\t\t\tCStreaming::RequestModel(model, STREAMFLAGS_DEPENDENCY);\n\t\t}\n\t}\n\tLoadAllRequestedModels(false);\n\tInstanceLoadedModels(pos);\n\n\tfor(int i = 0; i < NUMSTREAMINFO; i++)\n\t\tms_aInfoForModel[i].m_flags &= ~STREAMFLAGS_20;\n\tdebug(\"End load scene\\n\");\n}\n\nvoid\nCStreaming::LoadSceneCollision(const CVector &pos)\n{\n\tCColStore::LoadCollision(pos);\n\tCStreaming::LoadAllRequestedModels(false);\n}\n\nvoid\nCStreaming::MemoryCardSave(uint8 *buf, uint32 *size)\n{\n\tint i;\n\n\t*size = NUM_DEFAULT_MODELS;\n\tfor(i = 0; i < NUM_DEFAULT_MODELS; i++)\n\t\tif(ms_aInfoForModel[i].m_loadState == STREAMSTATE_LOADED)\n\t\t\tbuf[i] = ms_aInfoForModel[i].m_flags;\n\t\telse\n\t\t\tbuf[i] = 0xFF;\n}\n\nvoid \nCStreaming::MemoryCardLoad(uint8 *buf, uint32 size)\n{\n\tuint32 i;\n\n\tassert(size == NUM_DEFAULT_MODELS);\n\tfor(i = 0; i < size; i++)\n\t\tif(ms_aInfoForModel[i].m_loadState == STREAMSTATE_LOADED)\n\t\t\tif(buf[i] != 0xFF)\n\t\t\t\tms_aInfoForModel[i].m_flags = buf[i];\n}\n\nvoid\nCStreaming::UpdateForAnimViewer(void)\n{\n\tif (CStreaming::ms_channelError == -1) {\n\t\tCStreaming::AddModelsToRequestList(CVector(0.0f, 0.0f, 0.0f), 0);\n\t\tCStreaming::LoadRequestedModels();\n\t\t// original modifier was %d\n\t\tsprintf(gString, \"Requested %d, memory size %zuK\\n\", CStreaming::ms_numModelsRequested, 2 * CStreaming::ms_memoryUsed);\n\t}\n\telse {\n\t\tCStreaming::RetryLoadFile(CStreaming::ms_channelError);\n\t}\n}\n\n\nvoid\nCStreaming::PrintStreamingBufferState()\n{\n\tchar str[128];\n\twchar wstr[128];\n\tuint32 offset, size;\n\n\tCTimer::Stop();\n\tint i = 0;\n\twhile (i < NUMSTREAMINFO) {\n\t\twhile (true) {\n\t\t\tint j = 0;\n\t\t\tDoRWStuffStartOfFrame(50, 50, 50, 0, 0, 0, 255);\n\t\t\tCPad::UpdatePads();\n\t\t\tCSprite2d::InitPerFrame();\n\t\t\tCFont::InitPerFrame();\n\t\t\tDefinedState();\n\n\t\t\tCRect unusedRect(0, 0, RsGlobal.maximumWidth, RsGlobal.maximumHeight);\n\t\t\tCRGBA unusedColor(255, 255, 255, 255);\n\t\t\tCFont::SetFontStyle(FONT_BANK);\n\t\t\tCFont::SetBackgroundOff();\n\t\t\tCFont::SetWrapx(DEFAULT_SCREEN_WIDTH);\n\t\t\tCFont::SetScale(0.5f, 0.75f);\n\t\t\tCFont::SetCentreOff();\n\t\t\tCFont::SetCentreSize(DEFAULT_SCREEN_WIDTH);\n\t\t\tCFont::SetJustifyOff();\n\t\t\tCFont::SetColor(CRGBA(200, 200, 200, 200));\n\t\t\tCFont::SetBackGroundOnlyTextOff();\n\t\t\tint modelIndex = i;\n\t\t\tif (modelIndex < NUMSTREAMINFO) {\n\t\t\t\tint y = 24;\n\t\t\t\tfor ( ; j < 34 && modelIndex < NUMSTREAMINFO; modelIndex++) {\n\t\t\t\t\tCStreamingInfo *streamingInfo = &ms_aInfoForModel[modelIndex];\n\t\t\t\t\tCBaseModelInfo *modelInfo = CModelInfo::GetModelInfo(modelIndex);\n\t\t\t\t\tif (streamingInfo->m_loadState != STREAMSTATE_LOADED || !streamingInfo->GetCdPosnAndSize(offset, size))\n\t\t\t\t\t\tcontinue;\n\n\t\t\t\t\tif (modelIndex >= STREAM_OFFSET_TXD)\n\t\t\t\t\t\tsprintf(str, \"txd %s, refs %d, size %dK, flags 0x%x\", CTxdStore::GetTxdName(modelIndex - STREAM_OFFSET_TXD),\n\t\t\t\t\t\t        CTxdStore::GetNumRefs(modelIndex - STREAM_OFFSET_TXD), 2 * size, streamingInfo->m_flags);\n\t\t\t\t\telse\n\t\t\t\t\t\tsprintf(str, \"model %d,%s, refs%d, size%dK, flags%x\", modelIndex, modelInfo->GetModelName(), modelInfo->GetNumRefs(), 2 * size,\n\t\t\t\t\t\t        streamingInfo->m_flags);\n\t\t\t\t\tAsciiToUnicode(str, wstr);\n\t\t\t\t\tCFont::PrintString(24.0f, y, wstr);\n\t\t\t\t\ty += 12;\n\t\t\t\t\tj++;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (CPad::GetPad(1)->GetCrossJustDown())\n\t\t\t\ti = modelIndex;\n\n\t\t\tif (!CPad::GetPad(1)->GetTriangleJustDown())\n\t\t\t\tbreak;\n\n\t\t\ti = 0;\n\t\t\tCFont::DrawFonts();\n\t\t\tDoRWStuffEndOfFrame();\n\t\t}\n\t\tCFont::DrawFonts();\n\t\tDoRWStuffEndOfFrame();\n\t}\n\tCTimer::Update();\n}\n"
  },
  {
    "path": "src/core/Streaming.h",
    "content": "#pragma once\n\n#include \"Game.h\"\n\nenum {\n\tSTREAM_OFFSET_TXD = MODELINFOSIZE,\n\tSTREAM_OFFSET_COL = STREAM_OFFSET_TXD+TXDSTORESIZE,\n\tSTREAM_OFFSET_ANIM = STREAM_OFFSET_COL+COLSTORESIZE,\n\tNUMSTREAMINFO = STREAM_OFFSET_ANIM+NUMANIMBLOCKS\n};\n\nenum StreamFlags\n{\n\tSTREAMFLAGS_DONT_REMOVE = 0x01,\n\tSTREAMFLAGS_SCRIPTOWNED = 0x02,\n\tSTREAMFLAGS_DEPENDENCY  = 0x04,\t// Is this right?\n\tSTREAMFLAGS_PRIORITY    = 0x08,\n\tSTREAMFLAGS_NOFADE      = 0x10,\n\tSTREAMFLAGS_20          = 0x20,\t// TODO(MIAMI): what's this\n\n\tSTREAMFLAGS_CANT_REMOVE = STREAMFLAGS_DONT_REMOVE|STREAMFLAGS_SCRIPTOWNED,\n\tSTREAMFLAGS_KEEP_IN_MEMORY = STREAMFLAGS_DONT_REMOVE|STREAMFLAGS_SCRIPTOWNED|STREAMFLAGS_DEPENDENCY,\n};\n\nenum StreamLoadState\n{\n\tSTREAMSTATE_NOTLOADED = 0,\n\tSTREAMSTATE_LOADED    = 1,\n\tSTREAMSTATE_INQUEUE   = 2,\n\tSTREAMSTATE_READING   = 3,\t// channel is reading\n\tSTREAMSTATE_STARTED   = 4,\t// first part loaded\n};\n\nenum ChannelState\n{\n\tCHANNELSTATE_IDLE = 0,\n\tCHANNELSTATE_READING = 1,\n\tCHANNELSTATE_STARTED = 2,\n\tCHANNELSTATE_ERROR = 3,\n};\n\nclass CStreamingInfo\n{\npublic:\n\tCStreamingInfo *m_next;\n\tCStreamingInfo *m_prev;\n\tuint8 m_loadState;\n\tuint8 m_flags;\n\n\tint16  m_nextID;\n\tuint32 m_position;\n\tuint32 m_size;\n\n\tbool GetCdPosnAndSize(uint32 &posn, uint32 &size);\n\tvoid SetCdPosnAndSize(uint32 posn, uint32 size);\n\tvoid AddToList(CStreamingInfo *link);\n\tvoid RemoveFromList(void);\n\tuint32 GetCdSize(void) { return m_size; }\n\tbool IsPriority(void) { return !!(m_flags & STREAMFLAGS_PRIORITY); }\n};\n\nstruct CStreamingChannel\n{\n\tint32 streamIds[4];\n\tint32 offsets[4];\n\tint32 state;\n\tint32 field24;\n\tint32 position;\n\tint32 size;\n\tint32 numTries;\n\tint32 status;\t// from CdStream\n};\n\nclass CDirectory;\nclass CPtrList;\n\nclass CStreaming\n{\npublic:\n\tstatic bool ms_disableStreaming;\n\tstatic bool ms_bLoadingBigModel;\n\tstatic int32 ms_numModelsRequested;\n\tstatic CStreamingInfo ms_aInfoForModel[NUMSTREAMINFO];\n\tstatic CStreamingInfo ms_startLoadedList;\n\tstatic CStreamingInfo ms_endLoadedList;\n\tstatic CStreamingInfo ms_startRequestedList;\n\tstatic CStreamingInfo ms_endRequestedList;\n\tstatic int32 ms_oldSectorX;\n\tstatic int32 ms_oldSectorY;\n\tstatic int32 ms_streamingBufferSize;\n#ifndef ONE_THREAD_PER_CHANNEL\n\tstatic int8 *ms_pStreamingBuffer[2];\n#else\n\tstatic int8 *ms_pStreamingBuffer[4];\n#endif\n\tstatic size_t ms_memoryUsed;\n\tstatic CStreamingChannel ms_channel[2];\n\tstatic int32 ms_channelError;\n\tstatic int32 ms_numVehiclesLoaded;\n\tstatic int32 ms_numPedsLoaded;\n\tstatic int32 ms_vehiclesLoaded[MAXVEHICLESLOADED];\n\tstatic int32 ms_lastVehicleDeleted;\n\tstatic bool ms_bIsPedFromPedGroupLoaded[NUMMODELSPERPEDGROUP];\n\tstatic CDirectory *ms_pExtraObjectsDir;\n\tstatic int32 ms_numPriorityRequests;\n\tstatic int32 ms_currentPedGrp;\n\tstatic int32 ms_lastCullZone;\n\tstatic uint16 ms_loadedGangs;\n\tstatic uint16 ms_loadedGangCars;\n\tstatic int32 ms_currentPedLoading;\n\tstatic int32 ms_imageOffsets[NUMCDIMAGES];\n\tstatic int32 ms_lastImageRead;\n\tstatic int32 ms_imageSize;\n\tstatic size_t ms_memoryAvailable;\n\n\tstatic void Init(void);\n\tstatic void Init2(void);\n\tstatic void ReInit(void);\n\tstatic void Shutdown(void);\n\tstatic void Update(void);\n\tstatic void LoadCdDirectory(void);\n\tstatic void LoadCdDirectory(const char *dirname, int32 n);\n\tstatic bool ConvertBufferToObject(int8 *buf, int32 streamId);\n\tstatic bool FinishLoadingLargeFile(int8 *buf, int32 streamId);\n\tstatic bool HasModelLoaded(int32 id) { return ms_aInfoForModel[id].m_loadState == STREAMSTATE_LOADED; }\n\tstatic bool HasTxdLoaded(int32 id) { return HasModelLoaded(id+STREAM_OFFSET_TXD); }\n\tstatic bool HasColLoaded(int32 id) { return HasModelLoaded(id+STREAM_OFFSET_COL); }\n\tstatic bool HasAnimLoaded(int32 id) { return HasModelLoaded(id+STREAM_OFFSET_ANIM); }\n\tstatic bool CanRemoveModel(int32 id) { return (ms_aInfoForModel[id].m_flags & STREAMFLAGS_CANT_REMOVE) == 0; }\n\tstatic bool CanRemoveTxd(int32 id) { return CanRemoveModel(id+STREAM_OFFSET_TXD); }\n\tstatic bool CanRemoveCol(int32 id) { return CanRemoveModel(id+STREAM_OFFSET_COL); }\n\tstatic bool CanRemoveAnim(int32 id) { return CanRemoveModel(id+STREAM_OFFSET_ANIM); }\n\tstatic void RequestModel(int32 model, int32 flags);\n\tstatic void ReRequestModel(int32 model) { RequestModel(model, ms_aInfoForModel[model].m_flags); }\n\tstatic void RequestTxd(int32 txd, int32 flags) { RequestModel(txd + STREAM_OFFSET_TXD, flags); }\n\tstatic void ReRequestTxd(int32 txd) { ReRequestModel(txd + STREAM_OFFSET_TXD); }\n\tstatic void RequestCol(int32 col, int32 flags) { RequestModel(col + STREAM_OFFSET_COL, flags); }\n\tstatic void ReRequestCol(int32 col) { ReRequestModel(col + STREAM_OFFSET_COL); }\n\tstatic void RequestAnim(int32 col, int32 flags) { RequestModel(col + STREAM_OFFSET_ANIM, flags); }\n\tstatic void ReRequestAnim(int32 col) { ReRequestModel(col + STREAM_OFFSET_ANIM); }\n\tstatic void RequestBigBuildings(eLevelName level);\n\tstatic void RequestBigBuildings(eLevelName level, const CVector &pos);\n\tstatic void InstanceBigBuildings(eLevelName level, const CVector &pos);\n\tstatic void InstanceLoadedModelsInSectorList(CPtrList &list);\n\tstatic void InstanceLoadedModels(const CVector &pos);\n\tstatic void RequestIslands(eLevelName level);\n\tstatic void RequestSpecialModel(int32 modelId, const char *modelName, int32 flags);\n\tstatic void RequestSpecialChar(int32 charId, const char *modelName, int32 flags);\n\tstatic bool HasSpecialCharLoaded(int32 id);\n\tstatic void SetMissionDoesntRequireSpecialChar(int32 id);\n\tstatic void DecrementRef(int32 id);\n\tstatic void RemoveModel(int32 id);\n\tstatic void RemoveTxd(int32 id) { RemoveModel(id + STREAM_OFFSET_TXD); }\n\tstatic void RemoveCol(int32 id) { RemoveModel(id + STREAM_OFFSET_COL); }\n\tstatic void RemoveAnim(int32 id) { RemoveModel(id + STREAM_OFFSET_ANIM); }\n\tstatic void RemoveUnusedBuildings(eLevelName level);\n\tstatic void RemoveBuildings(eLevelName level);\n\tstatic void RemoveBuildingsNotInArea(int32 area);\n\tstatic void RemoveUnusedBigBuildings(eLevelName level);\n\tstatic void RemoveIslandsNotUsed(eLevelName level);\n\tstatic void RemoveBigBuildings(eLevelName level);\n\tstatic bool RemoveLoadedVehicle(void);\n\tstatic bool RemoveLeastUsedModel(uint32 excludeMask);\n\tstatic void RemoveAllUnusedModels(void);\n\tstatic void RemoveUnusedModelsInLoadedList(void);\n\tstatic bool RemoveLoadedZoneModel(void);\n\tstatic int32 GetAvailableVehicleSlot(void);\n\tstatic bool IsTxdUsedByRequestedModels(int32 txdId);\n\tstatic bool AreAnimsUsedByRequestedModels(int32 animId);\n\tstatic bool AddToLoadedVehiclesList(int32 modelId);\n\tstatic bool IsObjectInCdImage(int32 id);\n\tstatic void SetModelIsDeletable(int32 id);\n\tstatic void SetModelTxdIsDeletable(int32 id);\n\tstatic void SetMissionDoesntRequireModel(int32 id);\n\tstatic void LoadInitialPeds(void);\n\tstatic void LoadInitialWeapons(void);\n\tstatic void LoadInitialVehicles(void);\n\tstatic void StreamVehiclesAndPeds(void);\n\tstatic void StreamZoneModels(const CVector &pos);\n\tstatic void RemoveCurrentZonesModels(void);\n\tstatic void LoadBigBuildingsWhenNeeded(void);\n\n\tstatic int32 GetCdImageOffset(int32 lastPosn);\n\tstatic int32 GetNextFileOnCd(int32 position, bool priority);\n\tstatic void RequestModelStream(int32 ch);\n\tstatic bool ProcessLoadingChannel(int32 ch);\n\tstatic void RetryLoadFile(int32 ch);\n\tstatic void LoadRequestedModels(void);\n\tstatic void LoadAllRequestedModels(bool priority);\n\tstatic void FlushChannels(void);\n\tstatic void FlushRequestList(void);\n\n\tstatic void MakeSpaceFor(int32 size);\n\tstatic void ImGonnaUseStreamingMemory(void);\n\tstatic void IHaveUsedStreamingMemory(void);\n\tstatic void UpdateMemoryUsed(void);\n\n\tstatic void AddModelsToRequestList(const CVector &pos, int32 flags);\n\tstatic void ProcessEntitiesInSectorList(CPtrList &list, float x, float y, float xmin, float ymin, float xmax, float ymax, int32 flags);\n\tstatic void ProcessEntitiesInSectorList(CPtrList &list, int32 flags);\n\tstatic void DeleteFarAwayRwObjects(const CVector &pos);\n\tstatic void DeleteAllRwObjects(void);\n\tstatic void DeleteRwObjectsAfterDeath(const CVector &pos);\n\tstatic void DeleteRwObjectsBehindCamera(size_t mem); // originally signed\n\tstatic void DeleteRwObjectsInSectorList(CPtrList &list);\n\tstatic void DeleteRwObjectsInOverlapSectorList(CPtrList &list, int32 x, int32 y);\n\tstatic bool DeleteRwObjectsBehindCameraInSectorList(CPtrList &list, size_t mem); // originally signed\n\tstatic bool DeleteRwObjectsNotInFrustumInSectorList(CPtrList &list, size_t mem); // originally signed\n\n\tstatic void LoadScene(const CVector &pos);\n\tstatic void LoadSceneCollision(const CVector &pos);\n\n\tstatic void MemoryCardSave(uint8 *buffer, uint32 *length);\n\tstatic void MemoryCardLoad(uint8 *buffer, uint32 length);\n\n\tstatic void UpdateForAnimViewer(void);\n\n\tstatic void PrintStreamingBufferState();\n};\n"
  },
  {
    "path": "src/core/SurfaceTable.cpp",
    "content": "#include \"common.h\"\n\n#include \"main.h\"\n#include \"FileMgr.h\"\n#include \"Weather.h\"\n#include \"Collision.h\"\n#include \"SurfaceTable.h\"\n\nfloat CSurfaceTable::ms_aAdhesiveLimitTable[NUMADHESIVEGROUPS][NUMADHESIVEGROUPS];\n\nvoid\nCSurfaceTable::Initialise(Const char *filename)\n{\n\tint lineno, fieldno;\n\tchar *line;\n\tchar surfname[256];\n\tfloat adhesiveLimit;\n\n\tCFileMgr::SetDir(\"\");\n\tCFileMgr::LoadFile(filename, work_buff, sizeof(work_buff), \"r\");\n\n\tline = (char*)work_buff;\n\tfor(lineno = 0; lineno < NUMADHESIVEGROUPS; lineno++){\n\t\t// skip white space and comments\n\t\twhile(*line == ' ' || *line == '\\t' || *line == '\\n' || *line == '\\r' || *line == ';'){\n\t\t\tif(*line == ';'){\n\t\t\t\twhile(*line != '\\n' && *line != '\\r')\n\t\t\t\t\tline++;\n\t\t\t}else\n\t\t\t\tline++;\n\t\t}\n\n\t\tsscanf(line, \"%s\", surfname);\n\t\t// skip what we just read\n\t\twhile(!(*line == ' ' || *line == '\\t' || *line == ','))\n\t\t\tline++;\n\n\t\tfor(fieldno = 0; fieldno <= lineno; fieldno++){\n\t\t\t// skip white space\n\t\t\twhile(*line == ' ' || *line == '\\t' || *line == ',')\n\t\t\t\tline++;\n\t\t\tadhesiveLimit = 0.0f;\n\t\t\tif(*line != '-')\n\t\t\t\tsscanf(line, \"%f\", &adhesiveLimit);\n\t\t\t// skip what we just read\n\t\t\twhile(!(*line == ' ' || *line == '\\t' || *line == ',' || *line == '\\n'))\n\t\t\t\tline++;\n\n\t\t\tms_aAdhesiveLimitTable[lineno][fieldno] = adhesiveLimit;\n\t\t\tms_aAdhesiveLimitTable[fieldno][lineno] = adhesiveLimit;\n\t\t}\n\t}\n}\n\nint\nCSurfaceTable::GetAdhesionGroup(uint8 surfaceType)\n{\n\tswitch(surfaceType){\n\tcase SURFACE_DEFAULT:\t\treturn ADHESIVE_ROAD;\n\tcase SURFACE_TARMAC:\t\treturn ADHESIVE_ROAD;\n\tcase SURFACE_GRASS:\t\treturn ADHESIVE_LOOSE;\n\tcase SURFACE_GRAVEL:\t\treturn ADHESIVE_LOOSE;\n\tcase SURFACE_MUD_DRY:\t\treturn ADHESIVE_HARD;\n\tcase SURFACE_PAVEMENT:\t\treturn ADHESIVE_ROAD;\n\tcase SURFACE_CAR:\t\treturn ADHESIVE_HARD;\n\tcase SURFACE_GLASS:\t\treturn ADHESIVE_HARD;\n\tcase SURFACE_TRANSPARENT_CLOTH:\treturn ADHESIVE_HARD;\n\tcase SURFACE_GARAGE_DOOR:\treturn ADHESIVE_HARD;\n\tcase SURFACE_CAR_PANEL:\t\treturn ADHESIVE_HARD;\n\tcase SURFACE_THICK_METAL_PLATE:\treturn ADHESIVE_HARD;\n\tcase SURFACE_SCAFFOLD_POLE:\treturn ADHESIVE_HARD;\n\tcase SURFACE_LAMP_POST:\t\treturn ADHESIVE_HARD;\n\tcase SURFACE_FIRE_HYDRANT:\treturn ADHESIVE_HARD;\n\tcase SURFACE_GIRDER:\t\treturn ADHESIVE_HARD;\n\tcase SURFACE_METAL_CHAIN_FENCE:\treturn ADHESIVE_HARD;\n\tcase SURFACE_PED:\t\treturn ADHESIVE_RUBBER;\n\tcase SURFACE_SAND:\t\treturn ADHESIVE_SAND;\n\tcase SURFACE_WATER:\t\treturn ADHESIVE_WET;\n\tcase SURFACE_WOOD_CRATES:\treturn ADHESIVE_ROAD;\n\tcase SURFACE_WOOD_BENCH:\treturn ADHESIVE_ROAD;\n\tcase SURFACE_WOOD_SOLID:\treturn ADHESIVE_ROAD;\n\tcase SURFACE_RUBBER:\t\treturn ADHESIVE_RUBBER;\n\tcase SURFACE_PLASTIC:\t\treturn ADHESIVE_HARD;\n\tcase SURFACE_HEDGE:\t\treturn ADHESIVE_LOOSE;\n\tcase SURFACE_STEEP_CLIFF:\treturn ADHESIVE_LOOSE;\n\tcase SURFACE_CONTAINER:\t\treturn ADHESIVE_HARD;\n\tcase SURFACE_NEWS_VENDOR:\treturn ADHESIVE_HARD;\n\tcase SURFACE_WHEELBASE:\t\treturn ADHESIVE_RUBBER;\n\tcase SURFACE_CARDBOARDBOX:\treturn ADHESIVE_LOOSE;\n\tcase SURFACE_TRANSPARENT_STONE:\treturn ADHESIVE_HARD;\n\tcase SURFACE_METAL_GATE:\treturn ADHESIVE_HARD;\n\tcase SURFACE_SAND_BEACH:\treturn ADHESIVE_SAND;\n\tcase SURFACE_CONCRETE_BEACH:\treturn ADHESIVE_ROAD;\n\tdefault:\t\t\treturn ADHESIVE_ROAD;\n\t}\n}\n\nfloat\nCSurfaceTable::GetWetMultiplier(uint8 surfaceType)\n{\n\tswitch(surfaceType){\n\tcase SURFACE_DEFAULT:\n\tcase SURFACE_TARMAC:\n\tcase SURFACE_MUD_DRY:\n\tcase SURFACE_PAVEMENT:\n\tcase SURFACE_TRANSPARENT_CLOTH:\n\tcase SURFACE_WOOD_CRATES:\n\tcase SURFACE_WOOD_BENCH:\n\tcase SURFACE_WOOD_SOLID:\n\tcase SURFACE_HEDGE:\n\tcase SURFACE_CARDBOARDBOX:\n\tcase SURFACE_TRANSPARENT_STONE:\n\tcase SURFACE_CONCRETE_BEACH:\n\t\treturn 1.0f - CWeather::WetRoads*0.25f;\n\n\tcase SURFACE_GRASS:\n\tcase SURFACE_CAR:\n\tcase SURFACE_GLASS:\n\tcase SURFACE_GARAGE_DOOR:\n\tcase SURFACE_CAR_PANEL:\n\tcase SURFACE_THICK_METAL_PLATE:\n\tcase SURFACE_SCAFFOLD_POLE:\n\tcase SURFACE_LAMP_POST:\n\tcase SURFACE_FIRE_HYDRANT:\n\tcase SURFACE_GIRDER:\n\tcase SURFACE_METAL_CHAIN_FENCE:\n\tcase SURFACE_PED:\n\tcase SURFACE_RUBBER:\n\tcase SURFACE_PLASTIC:\n\tcase SURFACE_STEEP_CLIFF:\n\tcase SURFACE_CONTAINER:\n\tcase SURFACE_NEWS_VENDOR:\n\tcase SURFACE_WHEELBASE:\n\tcase SURFACE_METAL_GATE:\n\t\treturn 1.0f - CWeather::WetRoads*0.4f;\n\n\tcase SURFACE_SAND:\n\tcase SURFACE_SAND_BEACH:\n\t\treturn 1.0f + CWeather::WetRoads*0.5f;\n\n\tdefault:\n\t\treturn 1.0f;\n\t}\n}\n\nfloat\nCSurfaceTable::GetAdhesiveLimit(CColPoint &colpoint)\n{\n\treturn ms_aAdhesiveLimitTable[GetAdhesionGroup(colpoint.surfaceB)][GetAdhesionGroup(colpoint.surfaceA)];\n}\n\nbool\nCSurfaceTable::IsSoftLanding(uint8 surf)\n{\n\treturn surf == SURFACE_GRASS || surf == SURFACE_SAND || surf == SURFACE_SAND_BEACH;\n}\n"
  },
  {
    "path": "src/core/SurfaceTable.h",
    "content": "#pragma once\n\nenum eSurfaceType\n{\n\tSURFACE_DEFAULT,\n\tSURFACE_TARMAC,\n\tSURFACE_GRASS,\n\tSURFACE_GRAVEL,\n\tSURFACE_MUD_DRY,\n\tSURFACE_PAVEMENT,\n\tSURFACE_CAR,\n\tSURFACE_GLASS,\n\tSURFACE_TRANSPARENT_CLOTH,\n\tSURFACE_GARAGE_DOOR,\n\tSURFACE_CAR_PANEL,\n\tSURFACE_THICK_METAL_PLATE,\n\tSURFACE_SCAFFOLD_POLE,\n\tSURFACE_LAMP_POST,\n\tSURFACE_FIRE_HYDRANT,\n\tSURFACE_GIRDER,\n\tSURFACE_METAL_CHAIN_FENCE,\n\tSURFACE_PED,\n\tSURFACE_SAND,\n\tSURFACE_WATER,\n\tSURFACE_WOOD_CRATES,\n\tSURFACE_WOOD_BENCH,\n\tSURFACE_WOOD_SOLID,\n\tSURFACE_RUBBER,\n\tSURFACE_PLASTIC,\n\tSURFACE_HEDGE,\n\tSURFACE_STEEP_CLIFF,\n\tSURFACE_CONTAINER,\n\tSURFACE_NEWS_VENDOR,\n\tSURFACE_WHEELBASE,\n\tSURFACE_CARDBOARDBOX,\n\tSURFACE_TRANSPARENT_STONE,\n\tSURFACE_METAL_GATE,\n\tSURFACE_SAND_BEACH,\n\tSURFACE_CONCRETE_BEACH,\n};\n\nenum\n{\n\tADHESIVE_RUBBER,\n\tADHESIVE_HARD,\n\tADHESIVE_ROAD,\n\tADHESIVE_LOOSE,\n\tADHESIVE_SAND,\n\tADHESIVE_WET,\n\n\tNUMADHESIVEGROUPS\n};\n\nstruct CColPoint;\n\ninline bool\nIsSeeThrough(uint8 surfType)\n{\n\tswitch(surfType)\n\tcase SURFACE_GLASS:\n\tcase SURFACE_TRANSPARENT_CLOTH:\n\tcase SURFACE_METAL_CHAIN_FENCE:\n\tcase SURFACE_TRANSPARENT_STONE:\n\tcase SURFACE_SCAFFOLD_POLE:\n\t\treturn true;\n\treturn false;\n}\n\n// I think the necessity of this function is really a bug\ninline bool\nIsSeeThroughVertical(uint8 surfType)\n{\n\tswitch(surfType)\n\tcase SURFACE_GLASS:\n\tcase SURFACE_TRANSPARENT_CLOTH:\n\t\treturn true;\n\treturn false;\n}\n\ninline bool\nIsShootThrough(uint8 surfType)\n{\n\tswitch(surfType)\n\tcase SURFACE_TRANSPARENT_CLOTH:\n\tcase SURFACE_METAL_CHAIN_FENCE:\n\tcase SURFACE_TRANSPARENT_STONE:\n\tcase SURFACE_SCAFFOLD_POLE:\n\t\treturn true;\n\treturn false;\n}\n\nclass CSurfaceTable\n{\n\tstatic float ms_aAdhesiveLimitTable[NUMADHESIVEGROUPS][NUMADHESIVEGROUPS];\npublic:\n\tstatic void Initialise(Const char *filename);\n\tstatic int GetAdhesionGroup(uint8 surfaceType);\n\tstatic float GetWetMultiplier(uint8 surfaceType);\n\tstatic float GetAdhesiveLimit(CColPoint &colpoint);\n\tstatic bool IsSoftLanding(uint8 surf);\n};\n"
  },
  {
    "path": "src/core/TimeStep.cpp",
    "content": "#include \"TimeStep.h\"\n\nfloat CTimeStep::ms_fTimeScale = 1.0f;\nfloat CTimeStep::ms_fFramesPerUpdate = 1.0f;\nfloat CTimeStep::ms_fTimeStep = 1.0f;\n"
  },
  {
    "path": "src/core/TimeStep.h",
    "content": "#pragma once\n\n// Pretty sure this class is not used by the game\nclass CTimeStep\n{\npublic:\n\tstatic float ms_fTimeScale;\n\tstatic float ms_fFramesPerUpdate;\n\tstatic float ms_fTimeStep;\n};\n"
  },
  {
    "path": "src/core/Timer.cpp",
    "content": "#define WITHWINDOWS\n#include \"common.h\"\n#include \"crossplatform.h\"\n\n#include \"DMAudio.h\"\n#include \"Record.h\"\n#include \"Timer.h\"\n#include \"SpecialFX.h\"\n\nuint32 CTimer::m_snTimeInMilliseconds;\nPauseModeTime CTimer::m_snTimeInMillisecondsPauseMode = 1;\n\nuint32 CTimer::m_snTimeInMillisecondsNonClipped;\nuint32 CTimer::m_snPreviousTimeInMilliseconds;\nuint32 CTimer::m_FrameCounter;\nfloat CTimer::ms_fTimeScale;\nfloat CTimer::ms_fTimeStep;\nfloat CTimer::ms_fTimeStepNonClipped;\nbool  CTimer::m_UserPause;\nbool  CTimer::m_CodePause;\n\nuint32 _nCyclesPerMS = 1;\n\n#ifdef _WIN32\nLARGE_INTEGER _oldPerfCounter;\nLARGE_INTEGER perfSuspendCounter;\n#define RsTimerType uint32\n#else\n#define RsTimerType double\n#endif\n\nRsTimerType oldPcTimer;\n\nRsTimerType suspendPcTimer;\n\nuint32 suspendDepth;\n\n#ifdef FIX_HIGH_FPS_BUGS_ON_FRONTEND\ndouble frameTime;\n#endif\n\nvoid CTimer::Initialise(void)\n{\n\tdebug(\"Initialising CTimer...\\n\");\n\t\n\tms_fTimeScale = 1.0f;\n\tms_fTimeStep = 1.0f;\n\tsuspendDepth = 0;\n\tm_UserPause = false;\n\tm_CodePause = false;\n\tm_snTimeInMillisecondsNonClipped = 0;\n\tm_snPreviousTimeInMilliseconds = 0;\n\tm_snTimeInMilliseconds = 1;\n\t\n#ifdef _WIN32\n\tLARGE_INTEGER perfFreq;\n\tif ( QueryPerformanceFrequency(&perfFreq) )\n\t{\n\t\tOutputDebugString(\"Performance counter available\\n\");\n\t\t_nCyclesPerMS = uint32(perfFreq.QuadPart / 1000);\n\t\tQueryPerformanceCounter(&_oldPerfCounter);\n\t}\n\telse\n#endif\n\t{\n\t\tOutputDebugString(\"Performance counter not available, using millesecond timer\\n\");\n\t\t_nCyclesPerMS = 0;\n\t\toldPcTimer = RsTimer();\n\t}\n\t\n\tm_snTimeInMilliseconds = m_snPreviousTimeInMilliseconds;\n\t\n\tm_FrameCounter = 0;\n\t\n\tDMAudio.ResetTimers(m_snPreviousTimeInMilliseconds);\n\t\n\tdebug(\"CTimer ready\\n\");\n}\n\nvoid CTimer::Shutdown(void)\n{\n\t;\n}\n\nvoid CTimer::Update(void)\n{\n\tm_snPreviousTimeInMilliseconds = m_snTimeInMilliseconds;\n\t\n#ifdef _WIN32\n\tif ( (double)_nCyclesPerMS != 0.0 )\n\t{\n\t\tLARGE_INTEGER pc;\n\t\tQueryPerformanceCounter(&pc);\n\t\t\n\t\tint32 updInCycles = (pc.LowPart - _oldPerfCounter.LowPart); // & 0x7FFFFFFF; pointless\n\t\t\n\t\t_oldPerfCounter = pc;\n\t\t\n\t\tfloat updInCyclesScaled = GetIsPaused() ? updInCycles : updInCycles * ms_fTimeScale;\n\t\t\n\t\t// We need that real frame time to fix transparent menu bug.\n#ifndef FIX_HIGH_FPS_BUGS_ON_FRONTEND\n\t\tdouble\n#endif\n\t\tframeTime = updInCyclesScaled / (double)_nCyclesPerMS;\n\n\t\tm_snTimeInMillisecondsPauseMode = m_snTimeInMillisecondsPauseMode + frameTime;\n\t\t\n\t\tif ( GetIsPaused() )\n\t\t\tms_fTimeStep = 0.0f;\n\t\telse\n\t\t{\n\t\t\tm_snTimeInMilliseconds = m_snTimeInMilliseconds + frameTime;\n\t\t\tm_snTimeInMillisecondsNonClipped = m_snTimeInMillisecondsNonClipped + frameTime;\n\t\t\tms_fTimeStep = frameTime / 1000.0f * 50.0f;\n\t\t}\n\t}\n\telse\n#endif\n\t{\n\t\tRsTimerType timer = RsTimer();\n\t\t\n\t\tRsTimerType updInMs = timer - oldPcTimer;\n\t\t\n\t\t// We need that real frame time to fix transparent menu bug.\n#ifndef FIX_HIGH_FPS_BUGS_ON_FRONTEND\n\t\tdouble\n#endif\n\t\tframeTime = (double)updInMs * ms_fTimeScale;\n\t\t\n\t\toldPcTimer = timer;\n\t\t\n\t\tm_snTimeInMillisecondsPauseMode = m_snTimeInMillisecondsPauseMode + frameTime;\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \n\t\tif ( GetIsPaused() )\n\t\t\tms_fTimeStep = 0.0f;\n\t\telse\n\t\t{\n\t\t\tm_snTimeInMilliseconds = m_snTimeInMilliseconds + frameTime;\n\t\t\tm_snTimeInMillisecondsNonClipped = m_snTimeInMillisecondsNonClipped + frameTime;\n\t\t\tms_fTimeStep = frameTime / 1000.0f * 50.0f;\n\t\t}\n\t}\n\t\n\tif ( ms_fTimeStep < 0.01f && !GetIsPaused() && !CSpecialFX::bSnapShotActive)\n\t\tms_fTimeStep = 0.01f;\n\n\tms_fTimeStepNonClipped = ms_fTimeStep;\n\t\n\tif ( !CRecordDataForGame::IsPlayingBack() )\n\t{\n\t\tms_fTimeStep = Min(3.0f, ms_fTimeStep);\n\n\t\tif ( (m_snTimeInMilliseconds - m_snPreviousTimeInMilliseconds) > 60 )\n\t\t\tm_snTimeInMilliseconds = m_snPreviousTimeInMilliseconds + 60;\n\t}\n  \n\tif ( CRecordDataForChase::IsRecording() )\n\t{\n\t\tms_fTimeStep = 1.0f;\n\t\tm_snTimeInMilliseconds = m_snPreviousTimeInMilliseconds + 16;\n\t}\n  \n\tm_FrameCounter++;\n}\n\nvoid CTimer::Suspend(void)\n{\n\tif ( ++suspendDepth > 1 )\n\t\treturn;\n\t\n#ifdef _WIN32\n\tif ( (double)_nCyclesPerMS != 0.0 )\n\t\tQueryPerformanceCounter(&perfSuspendCounter);\n\telse\n#endif\n\t\tsuspendPcTimer = RsTimer();\n}\n\nvoid CTimer::Resume(void)\n{\n\tif ( --suspendDepth != 0 )\n\t\treturn;\n\n#ifdef _WIN32\n\tif ( (double)_nCyclesPerMS != 0.0 )\n\t{\n\t\tLARGE_INTEGER pc;\n\t\tQueryPerformanceCounter(&pc);\n\n\t\t_oldPerfCounter.LowPart += pc.LowPart - perfSuspendCounter.LowPart;\n\t}\n\telse\n#endif\n\t\toldPcTimer += RsTimer() - suspendPcTimer;\n}\n\nuint32 CTimer::GetCyclesPerMillisecond(void)\n{\n#ifdef _WIN32\n\tif (_nCyclesPerMS != 0)\n\t\treturn _nCyclesPerMS;\n\telse \n#endif\n\t\treturn 1;\n}\n\nuint32 CTimer::GetCurrentTimeInCycles(void)\n{\n#ifdef _WIN32\n\tif ( _nCyclesPerMS != 0 )\n\t{\n\t\tLARGE_INTEGER pc;\n\t\tQueryPerformanceCounter(&pc);\n\t\treturn (pc.LowPart - _oldPerfCounter.LowPart); // & 0x7FFFFFFF; pointless\n\t}\n\telse\n#endif\n\t\treturn RsTimer() - oldPcTimer;\n}\n\nbool CTimer::GetIsSlowMotionActive(void)\n{\n\treturn ms_fTimeScale < 1.0f;\n}\n\nvoid CTimer::Stop(void)\n{\n\tm_snPreviousTimeInMilliseconds = m_snTimeInMilliseconds;\n}\n\nvoid CTimer::StartUserPause(void)\n{\n\tm_UserPause = true;\n}\n\nvoid CTimer::EndUserPause(void)\n{\n\tm_UserPause = false;\n}\n\nuint32 CTimer::GetCyclesPerFrame()\n{\n\treturn 20;\n}\n\n"
  },
  {
    "path": "src/core/Timer.h",
    "content": "#pragma once\n\n#ifdef FIX_HIGH_FPS_BUGS_ON_FRONTEND\n#define PauseModeTime double\n#else\n#define PauseModeTime uint32\n#endif\n\nclass CTimer\n{\n\n\tstatic uint32 m_snTimeInMilliseconds;\n\tstatic PauseModeTime m_snTimeInMillisecondsPauseMode;\n\tstatic uint32 m_snTimeInMillisecondsNonClipped;\n\tstatic uint32 m_snPreviousTimeInMilliseconds;\n\tstatic uint32 m_FrameCounter;\n\tstatic float ms_fTimeScale;\n\tstatic float ms_fTimeStep;\n\tstatic float ms_fTimeStepNonClipped;\npublic:\n\tstatic bool  m_UserPause;\n\tstatic bool  m_CodePause;\n\n\tstatic const float &GetTimeStep(void) { return ms_fTimeStep; }\n\tstatic void SetTimeStep(float ts) { ms_fTimeStep = ts; }\n\tstatic float GetTimeStepInSeconds() { return ms_fTimeStep / 50.0f; }\n\tstatic uint32 GetTimeStepInMilliseconds() { return ms_fTimeStep / 50.0f * 1000.0f; }\n\tstatic const float &GetTimeStepNonClipped(void) { return ms_fTimeStepNonClipped; }\n\tstatic float GetTimeStepNonClippedInSeconds(void) { return ms_fTimeStepNonClipped / 50.0f; }\n\tstatic float GetTimeStepNonClippedInMilliseconds(void) { return ms_fTimeStepNonClipped / 50.0f * 1000.0f; }\n\tstatic void SetTimeStepNonClipped(float ts) { ms_fTimeStepNonClipped = ts; }\n\tstatic const uint32 &GetFrameCounter(void) { return m_FrameCounter; }\n\tstatic void SetFrameCounter(uint32 fc) { m_FrameCounter = fc; }\n\tstatic const uint32 &GetTimeInMilliseconds(void) { return m_snTimeInMilliseconds; }\n\tstatic void SetTimeInMilliseconds(uint32 t) { m_snTimeInMilliseconds = t; }\n\tstatic uint32 GetTimeInMillisecondsNonClipped(void) { return m_snTimeInMillisecondsNonClipped; }\n\tstatic void SetTimeInMillisecondsNonClipped(uint32 t) { m_snTimeInMillisecondsNonClipped = t; }\n\tstatic PauseModeTime GetTimeInMillisecondsPauseMode(void) { return m_snTimeInMillisecondsPauseMode; }\n\tstatic void SetTimeInMillisecondsPauseMode(uint32 t) { m_snTimeInMillisecondsPauseMode = t; }\n\tstatic uint32 GetPreviousTimeInMilliseconds(void) { return m_snPreviousTimeInMilliseconds; }\n\tstatic void SetPreviousTimeInMilliseconds(uint32 t) { m_snPreviousTimeInMilliseconds = t; }\n\tstatic const float &GetTimeScale(void) { return ms_fTimeScale; }\n\tstatic void SetTimeScale(float ts) { ms_fTimeScale = ts; }\n\tstatic uint32 GetCyclesPerFrame();\n\n\tstatic bool GetIsPaused() { return m_UserPause || m_CodePause; }\n\tstatic bool GetIsUserPaused() { return m_UserPause; }\n\tstatic bool GetIsCodePaused() { return m_CodePause; }\n\tstatic void SetCodePause(bool pause) { m_CodePause = pause; }\n\t\n\tstatic void Initialise(void);\n\tstatic void Shutdown(void);\n\tstatic void Update(void);\n\tstatic void Suspend(void);\n\tstatic void Resume(void);\n\tstatic uint32 GetCyclesPerMillisecond(void);\n\tstatic uint32 GetCurrentTimeInCycles(void);\n\tstatic bool GetIsSlowMotionActive(void);\n\tstatic void Stop(void);\n\tstatic void StartUserPause(void);\n\tstatic void EndUserPause(void);\n\n\tfriend bool GenericLoad(void);\n\tfriend bool GenericSave(int file);\n\tfriend class CMemoryCard;\n\n#ifdef FIX_BUGS\n\tstatic float GetDefaultTimeStep(void) { return 50.0f / 30.0f; }\n\tstatic float GetTimeStepFix(void) { return GetTimeStep() / GetDefaultTimeStep(); }\n#endif\n};\n\n#ifdef FIX_HIGH_FPS_BUGS_ON_FRONTEND\nextern double frameTime;\n#endif\n"
  },
  {
    "path": "src/core/User.cpp",
    "content": "#include \"common.h\"\n\n#include \"GameLogic.h\"\n#include \"Hud.h\"\n#include \"PlayerPed.h\"\n#include \"Replay.h\"\n#include \"Text.h\"\n#include \"User.h\"\n#include \"Vehicle.h\"\n#include \"World.h\"\n#include \"Zones.h\"\n\nCPlaceName CUserDisplay::PlaceName;\nCOnscreenTimer CUserDisplay::OnscnTimer;\nCPager CUserDisplay::Pager;\nCCurrentVehicle CUserDisplay::CurrentVehicle;\n\nCPlaceName::CPlaceName()\n{\n\tInit();\n}\n\nvoid\nCPlaceName::Init()\n{\n\tm_pZone = nil;\n\tm_pZone2 = nil;\n\tm_nAdditionalTimer = 0;\n}\n\nvoid\nCPlaceName::Process()\n{\n\tCVector pos = CWorld::Players[CWorld::PlayerInFocus].GetPos();\n\tCZone *navigZone = CTheZones::FindSmallestNavigationZoneForPosition(&pos, false, true);\n\tCZone *defaultZone = CTheZones::FindSmallestNavigationZoneForPosition(&pos, true, false);\n\n\tif (navigZone == nil) m_pZone = nil;\n\tif (defaultZone == nil) m_pZone2 = nil;\n\n\tif (navigZone == m_pZone) {\n\t\tif (defaultZone == m_pZone2 || m_pZone != nil) {\n\t\t\tif (navigZone != nil || defaultZone != nil) {\n\t\t\t\tif (m_nAdditionalTimer != 0)\n\t\t\t\t\tm_nAdditionalTimer--;\n\t\t\t} else {\n\t\t\t\tm_nAdditionalTimer = 0;\n\t\t\t\tm_pZone = nil;\n\t\t\t\tm_pZone2 = nil;\n\t\t\t}\n\t\t} else {\n\t\t\tm_pZone2 = defaultZone;\n\t\t\tm_nAdditionalTimer = 250;\n\t\t}\n\t} else {\n\t\tm_pZone = navigZone;\n\t\tm_nAdditionalTimer = 250;\n\t}\n\tDisplay();\n}\n\nvoid\nCPlaceName::Display()\n{\n\twchar *text;\n\tif (m_pZone != nil)\n\t\ttext = m_pZone->GetTranslatedName();\n\telse if (m_pZone2 != nil)\n\t\ttext = m_pZone2->GetTranslatedName();\n#ifdef FIX_BUGS\n\telse\n\t\ttext = nil;\n#endif\n\tCHud::SetZoneName(text);\n}\n\nvoid\nCPlaceName::ProcessAfterFrontEndShutDown(void)\n{\n\tCHud::m_pLastZoneName = nil;\n\tCHud::m_ZoneState = 0;\n\tm_nAdditionalTimer = 250;\n}\n\nCCurrentVehicle::CCurrentVehicle()\n{\n\tInit();\n}\n\nvoid\nCCurrentVehicle::Init()\n{\n\tm_pCurrentVehicle = nil;\n}\n\nvoid\nCCurrentVehicle::Process()\n{\n\tif (CWorld::Players[CWorld::PlayerInFocus].m_pPed->InVehicle())\n\t\tm_pCurrentVehicle = CWorld::Players[CWorld::PlayerInFocus].m_pPed->m_pMyVehicle;\n\telse\n\t\tm_pCurrentVehicle = nil;\n\tDisplay();\n}\n\nvoid\nCCurrentVehicle::Display()\n{\n\twchar *text = nil;\n\tif (m_pCurrentVehicle != nil && m_pCurrentVehicle != CGameLogic::pShortCutTaxi)\n\t\ttext = TheText.Get(((CVehicleModelInfo*)CModelInfo::GetModelInfo(m_pCurrentVehicle->GetModelIndex()))->m_gameName);\n\tCHud::SetVehicleName(text);\n}\n\nvoid\nCUserDisplay::Init()\n{\n\tPlaceName.Init();\n\tOnscnTimer.Init();\n\tPager.Init();\n\tCurrentVehicle.Init();\n}\n\nvoid\nCUserDisplay::Process()\n{\n#ifdef FIX_BUGS\n\tif (CReplay::IsPlayingBack())\n\t\treturn;\n#endif\n\tPlaceName.Process();\n\tOnscnTimer.Process();\n\tPager.Process();\n\tCurrentVehicle.Process();\n}\n"
  },
  {
    "path": "src/core/User.h",
    "content": "#pragma once\n\n#include \"Pager.h\"\n#include \"OnscreenTimer.h\"\n\nclass CZone;\nclass CVehicle;\n\nclass CPlaceName\n{\n\tCZone *m_pZone;\n\tCZone *m_pZone2;\n\tint16 m_nAdditionalTimer;\npublic:\n\tCPlaceName();\n\tvoid Init();\n\tvoid Process();\n\tvoid Display();\n\tvoid ProcessAfterFrontEndShutDown();\n};\n\nclass CCurrentVehicle\n{\n\tCVehicle *m_pCurrentVehicle;\npublic:\n\tCCurrentVehicle();\n\tvoid Init();\n\tvoid Process();\n\tvoid Display();\n};\n\nclass CUserDisplay\n{\npublic:\n\tstatic CPlaceName PlaceName;\n\tstatic COnscreenTimer OnscnTimer;\n\tstatic CPager Pager;\n\tstatic CCurrentVehicle CurrentVehicle;\n\n\tstatic void Init();\n\tstatic void Process();\n};\n"
  },
  {
    "path": "src/core/Wanted.cpp",
    "content": "#include \"common.h\"\n\n#include \"Pools.h\"\n#include \"ModelIndices.h\"\n#include \"Timer.h\"\n#include \"World.h\"\n#include \"ZoneCull.h\"\n#include \"Darkel.h\"\n#include \"DMAudio.h\"\n#include \"CopPed.h\"\n#include \"Wanted.h\"\n#include \"General.h\"\n#include \"Stats.h\"\n\nint32 CWanted::MaximumWantedLevel = 6;\nint32 CWanted::nMaximumWantedLevel = 9600;\n\nvoid\nCWanted::Initialise()\n{\n\tm_nChaos = 0;\n\tm_nMinChaos = 0;\n\tm_nLastUpdateTime = 0;\n\tm_nLastWantedLevelChange = 0;\n\tm_nLastTimeSuspended = 0;\n\tm_CurrentCops = 0;\n\tm_MaxCops = 0;\n\tm_MaximumLawEnforcerVehicles = 0;\n\tm_RoadblockDensity = 0;\n\tm_bIgnoredByCops = false;\n\tm_bIgnoredByEveryone = false;\n\tm_bSwatRequired = false;\n\tm_bFbiRequired = false;\n\tm_bArmyRequired = false;\n\tm_fCrimeSensitivity = 1.0f;\n\tm_nWantedLevel = 0;\n\tm_nMinWantedLevel = 0;\n\tm_CopsBeatingSuspect = 0;\n\n\tfor (int i = 0; i < ARRAY_SIZE(m_pCops); i++)\n\t\tm_pCops[i] = nil;\n\n\tClearQdCrimes();\n}\n\nbool\nCWanted::AreMiamiViceRequired()\n{\n\treturn m_nWantedLevel >= 3;\n}\n\nbool\nCWanted::AreSwatRequired()\n{\n\treturn m_nWantedLevel == 4 || m_bSwatRequired;\n}\n\nbool\nCWanted::AreFbiRequired()\n{\n\treturn m_nWantedLevel == 5 || m_bFbiRequired;\n}\n\nbool\nCWanted::AreArmyRequired()\n{\n\treturn m_nWantedLevel == 6 || m_bArmyRequired;\n}\n\nint32\nCWanted::NumOfHelisRequired()\n{\n\tif (m_bIgnoredByCops || m_bIgnoredByEveryone)\n\t\treturn 0;\n\n\tswitch (m_nWantedLevel) {\n\tcase 3:\n\tcase 4:\n\t\treturn 1;\n\tcase 5:\n\tcase 6:\n\t\treturn 1;\n\tdefault:\n\t\treturn 0;\n\t}\n}\n\nvoid\nCWanted::SetWantedLevel(int32 level)\n{\n\tif (level > MaximumWantedLevel)\n\t\tlevel = MaximumWantedLevel;\n\n\tClearQdCrimes();\n\tswitch (level) {\n\tcase 0:\n\t\tm_nChaos = 0;\n\t\tbreak;\n\tcase 1:\n\t\tm_nChaos = 70;\n\t\tbreak;\n\tcase 2:\n\t\tm_nChaos = 200;\n\t\tbreak;\n\tcase 3:\n\t\tm_nChaos = 570;\n\t\tbreak;\n\tcase 4:\n\t\tm_nChaos = 1220;\n\t\tbreak;\n\tcase 5:\n\t\tm_nChaos = 2420;\n\t\tbreak;\n\tcase 6:\n\t\tm_nChaos = 4820;\n\t\tbreak;\n\tdefault:\n\t\tbreak;\n\t}\n\tUpdateWantedLevel();\n}\n\nvoid\nCWanted::SetWantedLevelNoDrop(int32 level)\n{\n\tif (m_nWantedLevel < m_nMinWantedLevel)\n\t\tSetWantedLevel(m_nMinWantedLevel);\n\n\tif (level > m_nWantedLevel)\n\t\tSetWantedLevel(level);\n}\n\nvoid\nCWanted::CheatWantedLevel(int32 level)\n{\n\tSetWantedLevel(level);\n\tUpdateWantedLevel();\n}\n\nvoid\nCWanted::SetMaximumWantedLevel(int32 level)\n{\n\tswitch(level){\n\tcase 0:\n\t\tnMaximumWantedLevel = 0;\n\t\tMaximumWantedLevel = 0;\n\t\tbreak;\n\tcase 1:\n\t\tnMaximumWantedLevel = 115;\n\t\tMaximumWantedLevel = 1;\n\t\tbreak;\n\tcase 2:\n\t\tnMaximumWantedLevel = 365;\n\t\tMaximumWantedLevel = 2;\n\t\tbreak;\n\tcase 3:\n\t\tnMaximumWantedLevel = 875;\n\t\tMaximumWantedLevel = 3;\n\t\tbreak;\n\tcase 4:\n\t\tnMaximumWantedLevel = 1800;\n\t\tMaximumWantedLevel = 4;\n\t\tbreak;\n\tcase 5:\n\t\tnMaximumWantedLevel = 3600;\n\t\tMaximumWantedLevel = 5;\n\t\tbreak;\n\tcase 6:\n\t\tnMaximumWantedLevel = 7200;\n\t\tMaximumWantedLevel = 6;\n\t\tbreak;\n\t}\n}\n\nvoid\nCWanted::RegisterCrime(eCrimeType type, const CVector &coors, uint32 id, bool policeDoesntCare)\n{\n\tAddCrimeToQ(type, id, coors, false, policeDoesntCare);\n}\n\nvoid\nCWanted::RegisterCrime_Immediately(eCrimeType type, const CVector &coors, uint32 id, bool policeDoesntCare)\n{\n#ifdef FIX_SIGNIFICANT_BUGS\n\tif(!AddCrimeToQ(type, id, coors, true, policeDoesntCare))\n#else\n\tif(!AddCrimeToQ(type, id, coors, false, policeDoesntCare))\n#endif\n\t\tReportCrimeNow(type, coors, policeDoesntCare);\n}\n\nvoid\nCWanted::ClearQdCrimes()\n{\n\tfor (int i = 0; i < 16; i++)\n\t\tm_aCrimes[i].m_nType = CRIME_NONE;\n}\n\n// returns whether the crime had been reported already\nbool\nCWanted::AddCrimeToQ(eCrimeType type, int32 id, const CVector &coors, bool reported, bool policeDoesntCare)\n{\n\tint i;\n\n\tfor(i = 0; i < 16; i++)\n\t\tif(m_aCrimes[i].m_nType == type && m_aCrimes[i].m_nId == id){\n\t\t\tif(m_aCrimes[i].m_bReported)\n\t\t\t\treturn true;\n\t\t\tif(reported)\n\t\t\t\tm_aCrimes[i].m_bReported = reported;\n\t\t\treturn false;\n\t\t}\n\n\tfor(i = 0; i < 16; i++)\n\t\tif(m_aCrimes[i].m_nType == CRIME_NONE)\n\t\t\tbreak;\n\tif(i < 16){\n\t\tm_aCrimes[i].m_nType = type;\n\t\tm_aCrimes[i].m_nId = id;\n\t\tm_aCrimes[i].m_vecPosn = coors;\n\t\tm_aCrimes[i].m_nTime = CTimer::GetTimeInMilliseconds();\n\t\tm_aCrimes[i].m_bReported = reported;\n\t\tm_aCrimes[i].m_bPoliceDoesntCare = policeDoesntCare;\n\t}\n\treturn false;\n}\n\nvoid\nCWanted::ReportCrimeNow(eCrimeType type, const CVector &coors, bool policeDoesntCare)\n{\n\tfloat sensitivity, chaos;\n\tint wantedLevelDrop;\n\n\tif(CDarkel::FrenzyOnGoing())\n\t\tsensitivity = m_fCrimeSensitivity*0.3f;\n\telse\n\t\tsensitivity = m_fCrimeSensitivity;\n\n\twantedLevelDrop = Min(CCullZones::GetWantedLevelDrop(), 100);\n\n\tchaos = (1.0f - wantedLevelDrop/100.0f) * sensitivity;\n\tif (policeDoesntCare)\n\t\tchaos *= 0.333f;\n\tswitch(type){\n\tcase CRIME_POSSESSION_GUN:\n\t\tbreak;\n\tcase CRIME_HIT_PED:\n\t\tm_nChaos += 5.0f*chaos;\n\t\tbreak;\n\tcase CRIME_HIT_COP:\n\t\tm_nChaos += 45.0f*chaos;\n\t\tbreak;\n\tcase CRIME_SHOOT_PED:\n\t\tm_nChaos += 30.0f*chaos;\n\t\tbreak;\n\tcase CRIME_SHOOT_COP:\n\t\tm_nChaos += 80.0f*chaos;\n\t\tbreak;\n\tcase CRIME_STEAL_CAR:\n\t\tm_nChaos += 15.0f*chaos;\n\t\tbreak;\n\tcase CRIME_RUN_REDLIGHT:\n\t\tm_nChaos += 10.0f*chaos;\n\t\tbreak;\n\tcase CRIME_RECKLESS_DRIVING:\n\t\tm_nChaos += 5.0f*chaos;\n\t\tbreak;\n\tcase CRIME_SPEEDING:\n\t\tm_nChaos += 5.0f*chaos;\n\t\tbreak;\n\tcase CRIME_RUNOVER_PED:\n\t\tm_nChaos += 18.0f*chaos;\n\t\tbreak;\n\tcase CRIME_RUNOVER_COP:\n\t\tm_nChaos += 80.0f*chaos;\n\t\tbreak;\n\tcase CRIME_SHOOT_HELI:\n\t\tm_nChaos += 400.0f*chaos;\n\t\tbreak;\n\tcase CRIME_PED_BURNED:\n\t\tm_nChaos += 20.0f*chaos;\n\t\tbreak;\n\tcase CRIME_COP_BURNED:\n\t\tm_nChaos += 80.0f*chaos;\n\t\tbreak;\n\tcase CRIME_VEHICLE_BURNED:\n\t\tm_nChaos += 20.0f*chaos;\n\t\tbreak;\n\tcase CRIME_DESTROYED_CESSNA:\n\t\tm_nChaos += 500.0f*chaos;\n\t\tbreak;\n\tcase CRIME_EXPLOSION:\n\t\tm_nChaos += 25.0f * chaos;\n\t\tbreak;\n\tcase CRIME_HIT_PED_NASTYWEAPON:\n\t\tm_nChaos += 35.0f * chaos;\n\t\tbreak;\n\tcase CRIME_HIT_COP_NASTYWEAPON:\n\t\tm_nChaos += 100.0f * chaos;\n\t\tbreak;\n\tdefault:\n\t//\tError(\"Undefined crime type, RegisterCrime, Crime.cpp\");\t// different file for some reason\n\t\tError(\"Undefined crime type, RegisterCrime, Wanted.cpp\");\n\t}\n\tm_nChaos = Max(m_nChaos, m_nMinChaos);\n\tDMAudio.ReportCrime(type, coors);\n\tUpdateWantedLevel();\n}\n\nvoid\nCWanted::UpdateWantedLevel()\n{\n\tint32 CurrWantedLevel = m_nWantedLevel;\n\n\tif (m_nChaos > nMaximumWantedLevel)\n\t\tm_nChaos = nMaximumWantedLevel;\n\n\tif (m_nChaos >= 0 && m_nChaos < 50) {\n\t\tif (m_nWantedLevel == 1)\n\t\t\t++CStats::WantedStarsEvaded;\n\t\tm_nWantedLevel = 0;\n\t\tm_MaximumLawEnforcerVehicles = 0;\n\t\tm_MaxCops = 0;\n\t\tm_RoadblockDensity = 0;\n\t} else if (m_nChaos >= 50 && m_nChaos < 180) {\n\t\tCStats::WantedStarsAttained += 1 - m_nWantedLevel;\n\t\tm_nWantedLevel = 1;\n\t\tm_MaximumLawEnforcerVehicles = 1;\n\t\tm_MaxCops = 1;\n\t\tm_RoadblockDensity = 0;\n\t} else if (m_nChaos >= 180 && m_nChaos < 550) {\n\t\tCStats::WantedStarsAttained += 2 - m_nWantedLevel;\n\t\tm_nWantedLevel = 2;\n\t\tm_MaximumLawEnforcerVehicles = 2;\n\t\tm_MaxCops = 3;\n\t\tm_RoadblockDensity = 0;\n\t} else if (m_nChaos >= 550 && m_nChaos < 1200) {\n\t\tCStats::WantedStarsAttained += 3 - m_nWantedLevel;\n\t\tm_nWantedLevel = 3;\n\t\tm_MaximumLawEnforcerVehicles = 2;\n\t\tm_MaxCops = 4;\n\t\tm_RoadblockDensity = 12;\n\t} else if (m_nChaos >= 1200 && m_nChaos < 2400) {\n\t\tCStats::WantedStarsAttained += 4 - m_nWantedLevel;\n\t\tm_nWantedLevel = 4;\n\t\tm_MaximumLawEnforcerVehicles = 2;\n\t\tm_MaxCops = 6;\n\t\tm_RoadblockDensity = 18;\n\t} else if (m_nChaos >= 2400 && m_nChaos < 4800) {\n\t\tCStats::WantedStarsAttained += 5 - m_nWantedLevel;\n\t\tm_nWantedLevel = 5;\n\t\tm_MaximumLawEnforcerVehicles = 3;\n\t\tm_MaxCops = 8;\n\t\tm_RoadblockDensity = 24;\n\t} else if (m_nChaos >= 4800) {\n\t\tCStats::WantedStarsAttained += 6 - m_nWantedLevel;\n\t\tm_nWantedLevel = 6;\n\t\tm_MaximumLawEnforcerVehicles = 3;\n\t\tm_MaxCops = 10;\n\t\tm_RoadblockDensity = 30;\n\t}\n\n\tif (CurrWantedLevel != m_nWantedLevel)\n\t\tm_nLastWantedLevelChange = CTimer::GetTimeInMilliseconds();\n}\n\nint32\nCWanted::WorkOutPolicePresence(CVector posn, float radius)\n{\n\tint i;\n\tCPed *ped;\n\tCVehicle *vehicle;\n\tint numPolice = 0;\n\n\ti = CPools::GetPedPool()->GetSize();\n\twhile(--i >= 0){\n\t\tped = CPools::GetPedPool()->GetSlot(i);\n\t\tif(ped &&\n\t\t   IsPolicePedModel(ped->GetModelIndex()) &&\n\t\t   (posn - ped->GetPosition()).Magnitude() < radius)\n\t\t\tnumPolice++;\n\t}\n\n\ti = CPools::GetVehiclePool()->GetSize();\n\twhile(--i >= 0){\n\t\tvehicle = CPools::GetVehiclePool()->GetSlot(i);\n\t\tif(vehicle &&\n\t\t   vehicle->bIsLawEnforcer &&\n\t\t   IsPoliceVehicleModel(vehicle->GetModelIndex()) &&\n\t\t   vehicle != FindPlayerVehicle() &&\n\t\t   vehicle->GetStatus() != STATUS_ABANDONED && vehicle->GetStatus() != STATUS_WRECKED &&\n\t\t   (posn - vehicle->GetPosition()).Magnitude() < radius)\n\t\t\tnumPolice++;\n\t}\n\n\treturn numPolice;\n}\n\nvoid\nCWanted::Update(void)\n{\n\tif (CTimer::GetTimeInMilliseconds() > m_nLastTimeSuspended + 20000) {\n\t\tm_nMinChaos = 0;\n\t\tm_nMinWantedLevel = 0;\n\t}\n\tif (CTimer::GetTimeInMilliseconds() - m_nLastUpdateTime > 1000) {\n\t\tif (m_nWantedLevel > 1) {\n\t\t\tm_nLastUpdateTime = CTimer::GetTimeInMilliseconds();\n\t\t} else {\n\t\t\tfloat radius = 18.0f;\n\t\t\tCVector playerPos = FindPlayerCoors();\n\t\t\tif (WorkOutPolicePresence(playerPos, radius) == 0) {\n\t\t\t\tm_nLastUpdateTime = CTimer::GetTimeInMilliseconds();\n\t\t\t\tm_nChaos = Max(0, m_nChaos - 1);\n\t\t\t\tUpdateWantedLevel();\n\t\t\t}\n\t\t}\n\t\tUpdateCrimesQ();\n\t\tbool orderMessedUp = false;\n\t\tint currCopNum = 0;\n\t\tbool foundEmptySlot = false;\n\t\tfor (int i = 0; i < ARRAY_SIZE(m_pCops); i++) {\n\t\t\tif (m_pCops[i]) {\n\t\t\t\t++currCopNum;\n\t\t\t\tif (foundEmptySlot)\n\t\t\t\t\torderMessedUp = true;\n\t\t\t} else {\n\t\t\t\tfoundEmptySlot = true;\n\t\t\t}\n\t\t}\n\t\tif (currCopNum != m_CurrentCops) {\n\t\t\tprintf(\"CopPursuit total messed up: re-setting\\n\");\n\t\t\tm_CurrentCops = currCopNum;\n\t\t}\n\t\tif (orderMessedUp) {\n\t\t\tprintf(\"CopPursuit pointer list messed up: re-sorting\\n\");\n\t\t\tbool fixed = true;\n\t\t\tfor (int i = 0; i < ARRAY_SIZE(m_pCops); i++) {\n\t\t\t\tif (!m_pCops[i]) {\n\t\t\t\t\tfor (int j = i; j < ARRAY_SIZE(m_pCops); j++) {\n\t\t\t\t\t\tif (m_pCops[j]) {\n\t\t\t\t\t\t\tm_pCops[i] = m_pCops[j];\n\t\t\t\t\t\t\tm_pCops[j] = nil;\n\t\t\t\t\t\t\tfixed = false;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (fixed)\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nCWanted::ResetPolicePursuit(void)\n{\n\tfor(int i = 0; i < ARRAY_SIZE(m_pCops); i++) {\n\t\tCCopPed *cop = m_pCops[i];\n\t\tif (!cop)\n\t\t\tcontinue;\n\n\t\tcop->m_bIsInPursuit = false;\n\t\tcop->m_objective = OBJECTIVE_NONE;\n\t\tcop->m_prevObjective = OBJECTIVE_NONE;\n\t\tcop->m_nLastPedState = PED_NONE;\n\t\tif (!cop->DyingOrDead()) {\n\t\t\tcop->SetWanderPath(CGeneral::GetRandomNumberInRange(0.0f, 8.0f));\n\t\t}\n\t\tm_pCops[i] = nil;\n\t}\n\tm_CurrentCops = 0;\n}\n\nvoid\nCWanted::Reset(void)\n{\n\tResetPolicePursuit();\n\tInitialise();\n}\n\nvoid\nCWanted::UpdateCrimesQ(void)\n{\n\tfor(int i = 0; i < ARRAY_SIZE(m_aCrimes); i++) {\n\n\t\tCCrimeBeingQd &crime = m_aCrimes[i];\n\t\tif (crime.m_nType != CRIME_NONE) {\n\t\t\tif (CTimer::GetTimeInMilliseconds() > crime.m_nTime + 500 && !crime.m_bReported) {\n\t\t\t\tReportCrimeNow(crime.m_nType, crime.m_vecPosn, crime.m_bPoliceDoesntCare);\n\t\t\t\tcrime.m_bReported = true;\n\t\t\t}\n\t\t\tif (CTimer::GetTimeInMilliseconds() > crime.m_nTime + 10000)\n\t\t\t\tcrime.m_nType = CRIME_NONE;\n\t\t}\n\t}\n}\n\nvoid\nCWanted::Suspend(void)\n{\n\tCStats::WantedStarsEvaded += m_nWantedLevel;\n\tm_nMinChaos = m_nChaos;\n\tm_nMinWantedLevel = m_nWantedLevel;\n\tm_nLastTimeSuspended = CTimer::GetTimeInMilliseconds();\n\tm_nChaos = 0;\n\tm_nWantedLevel = 0;\n\tResetPolicePursuit();\n}\n"
  },
  {
    "path": "src/core/Wanted.h",
    "content": "#pragma once\n\n#include \"Crime.h\"\n\nclass CEntity;\nclass CCopPed;\n\nclass CWanted\n{\npublic:\n\tint32 m_nChaos;\n\tint32 m_nMinChaos;\n\tint32 m_nLastUpdateTime;\n\tuint32 m_nLastWantedLevelChange;\n\tuint32 m_nLastTimeSuspended;\n\tfloat m_fCrimeSensitivity;\n\tuint8 m_CurrentCops;\n\tuint8 m_MaxCops;\n\tuint8 m_MaximumLawEnforcerVehicles;\n\tuint8 m_CopsBeatingSuspect;\n\tint16 m_RoadblockDensity;\n\tuint8 m_bIgnoredByCops : 1;\n\tuint8 m_bIgnoredByEveryone : 1;\n\tuint8 m_bSwatRequired : 1;\n\tuint8 m_bFbiRequired : 1;\n\tuint8 m_bArmyRequired : 1;\n\tint32 m_nWantedLevel;\n\tint32 m_nMinWantedLevel;\n\tCCrimeBeingQd m_aCrimes[16];\n\tCCopPed *m_pCops[10];\n\n\tstatic int32 MaximumWantedLevel;\n\tstatic int32 nMaximumWantedLevel;\n\npublic:\n\tvoid Initialise();\n\tbool AreMiamiViceRequired();\n\tbool AreSwatRequired();\n\tbool AreFbiRequired();\n\tbool AreArmyRequired();\n\tint32 NumOfHelisRequired();\n\tvoid SetWantedLevel(int32);\n\tvoid SetWantedLevelNoDrop(int32 level);\n\tint32 GetWantedLevel() { return m_nWantedLevel; }\n\tvoid CheatWantedLevel(int32 level);\n\tvoid RegisterCrime(eCrimeType type, const CVector &coors, uint32 id, bool policeDoesntCare);\n\tvoid RegisterCrime_Immediately(eCrimeType type, const CVector &coors, uint32 id, bool policeDoesntCare);\n\tvoid ClearQdCrimes();\n\tbool AddCrimeToQ(eCrimeType type, int32 id, const CVector &pos, bool reported, bool policeDoesntCare);\n\tvoid ReportCrimeNow(eCrimeType type, const CVector &coors, bool policeDoesntCare);\n\tvoid UpdateWantedLevel();\n\tvoid Reset();\n\tvoid ResetPolicePursuit();\n\tvoid UpdateCrimesQ();\n\tvoid Update();\n\n\tvoid Suspend();\n\n\tbool IsIgnored(void) { return m_bIgnoredByCops || m_bIgnoredByEveryone; }\n\n\tstatic int32 WorkOutPolicePresence(CVector posn, float radius);\n\tstatic void SetMaximumWantedLevel(int32 level);\n};\n\nVALIDATE_SIZE(CWanted, 0x204);\n"
  },
  {
    "path": "src/core/World.cpp",
    "content": "#include \"common.h\"\n#include \"Camera.h\"\n#include \"CarCtrl.h\"\n#include \"CopPed.h\"\n#include \"CutsceneMgr.h\"\n#include \"DMAudio.h\"\n#include \"EventList.h\"\n#include \"Explosion.h\"\n#include \"Fire.h\"\n#include \"Garages.h\"\n#include \"Glass.h\"\n#include \"Messages.h\"\n#include \"ModelIndices.h\"\n#include \"ParticleObject.h\"\n#include \"Pickups.h\"\n#include \"Population.h\"\n#include \"ProjectileInfo.h\"\n#include \"Record.h\"\n#include \"References.h\"\n#include \"Replay.h\"\n#include \"RpAnimBlend.h\"\n#include \"Shadows.h\"\n#include \"TempColModels.h\"\n#include \"WaterLevel.h\"\n#include \"World.h\"\n\n#define OBJECT_REPOSITION_OFFSET_Z 2.0f\n\nCColPoint gaTempSphereColPoints[MAX_COLLISION_POINTS];\n\nCPtrList CWorld::ms_bigBuildingsList[NUM_LEVELS];\nCPtrList CWorld::ms_listMovingEntityPtrs;\nCSector CWorld::ms_aSectors[NUMSECTORS_Y][NUMSECTORS_X];\nuint16 CWorld::ms_nCurrentScanCode;\n\nuint8 CWorld::PlayerInFocus;\nCPlayerInfo CWorld::Players[NUMPLAYERS];\nbool CWorld::bNoMoreCollisionTorque;\nCEntity *CWorld::pIgnoreEntity;\nbool CWorld::bIncludeDeadPeds;\nbool CWorld::bSecondShift;\nbool CWorld::bForceProcessControl;\nbool CWorld::bProcessCutsceneOnly;\n\nbool CWorld::bDoingCarCollisions;\nbool CWorld::bIncludeCarTyres;\nbool CWorld::bIncludeBikers;\n\nCColPoint CWorld::m_aTempColPts[MAX_COLLISION_POINTS];\n\nvoid\nCWorld::Initialise()\n{\n\tpIgnoreEntity = nil;\n\tbDoingCarCollisions = false;\n\tbSecondShift = false;\n\tbNoMoreCollisionTorque = false;\n\tbProcessCutsceneOnly = false;\n\tbIncludeDeadPeds = false;\n\tbForceProcessControl = false;\n\tbIncludeCarTyres = false;\n\tbIncludeBikers = false;\n}\n\nvoid\nCWorld::Add(CEntity *ent)\n{\n\tif(ent->IsVehicle() || ent->IsPed()) DMAudio.SetEntityStatus(((CPhysical *)ent)->m_audioEntityId, true);\n\n\tif(ent->bIsBIGBuilding)\n\t\tms_bigBuildingsList[ent->m_level].InsertItem(ent);\n\telse\n\t\tent->Add();\n\n\tif(ent->IsBuilding() || ent->IsDummy()) return;\n\n\tif(!ent->GetIsStatic()) ((CPhysical *)ent)->AddToMovingList();\n}\n\nvoid\nCWorld::Remove(CEntity *ent)\n{\n\tif(ent->IsVehicle() || ent->IsPed()) DMAudio.SetEntityStatus(((CPhysical *)ent)->m_audioEntityId, false);\n\n\tif(ent->bIsBIGBuilding)\n\t\tms_bigBuildingsList[ent->m_level].RemoveItem(ent);\n\telse\n\t\tent->Remove();\n\n\tif(ent->IsBuilding() || ent->IsDummy()) return;\n\n\tif(!ent->GetIsStatic()) ((CPhysical *)ent)->RemoveFromMovingList();\n}\n\nvoid\nCWorld::ClearScanCodes(void)\n{\n\tCPtrNode *node;\n\tfor(int i = 0; i < NUMSECTORS_Y; i++)\n\t\tfor(int j = 0; j < NUMSECTORS_X; j++) {\n\t\t\tCSector *s = &ms_aSectors[i][j];\n\t\t\tfor(node = s->m_lists[ENTITYLIST_BUILDINGS].first; node; node = node->next)\n\t\t\t\t((CEntity *)node->item)->m_scanCode = 0;\n\t\t\tfor(node = s->m_lists[ENTITYLIST_VEHICLES].first; node; node = node->next)\n\t\t\t\t((CEntity *)node->item)->m_scanCode = 0;\n\t\t\tfor(node = s->m_lists[ENTITYLIST_PEDS].first; node; node = node->next)\n\t\t\t\t((CEntity *)node->item)->m_scanCode = 0;\n\t\t\tfor(node = s->m_lists[ENTITYLIST_OBJECTS].first; node; node = node->next)\n\t\t\t\t((CEntity *)node->item)->m_scanCode = 0;\n\t\t\tfor(node = s->m_lists[ENTITYLIST_DUMMIES].first; node; node = node->next)\n\t\t\t\t((CEntity *)node->item)->m_scanCode = 0;\n\t\t}\n}\n\nvoid\nCWorld::ClearExcitingStuffFromArea(const CVector &pos, float radius, bool bRemoveProjectilesAndTidyUpShadows)\n{\n\tCPedPool *pedPool = CPools::GetPedPool();\n\tfor(int32 i = 0; i < pedPool->GetSize(); i++) {\n\t\tCPed *pPed = pedPool->GetSlot(i);\n\t\tif(pPed && !pPed->IsPlayer() && pPed->CanBeDeleted() &&\n\t\t   CVector2D(pPed->GetPosition() - pos).MagnitudeSqr() < SQR(radius)) {\n\t\t\tCPopulation::RemovePed(pPed);\n\t\t}\n\t}\n\tCVehiclePool *VehiclePool = CPools::GetVehiclePool();\n\tfor(int32 i = 0; i < VehiclePool->GetSize(); i++) {\n\t\tCVehicle *pVehicle = VehiclePool->GetSlot(i);\n\t\tif(pVehicle && CVector2D(pVehicle->GetPosition() - pos).MagnitudeSqr() < SQR(radius) &&\n\t\t   !pVehicle->bIsLocked && pVehicle->CanBeDeleted()) {\n\t\t\tif(pVehicle->pDriver) {\n\t\t\t\tCPopulation::RemovePed(pVehicle->pDriver);\n\t\t\t\tpVehicle->pDriver = nil;\n\t\t\t}\n\t\t\tfor(int32 j = 0; j < pVehicle->m_nNumMaxPassengers; ++j) {\n\t\t\t\tif(pVehicle->pPassengers[j]) {\n\t\t\t\t\tCPopulation::RemovePed(pVehicle->pPassengers[j]);\n\t\t\t\t\tpVehicle->pPassengers[j] = nil;\n\t\t\t\t\t--pVehicle->m_nNumPassengers;\n\t\t\t\t}\n\t\t\t}\n\t\t\tCCarCtrl::RemoveFromInterestingVehicleList(pVehicle);\n\t\t\tRemove(pVehicle);\n\t\t\tdelete pVehicle;\n\t\t}\n\t}\n\tCObject::DeleteAllTempObjectsInArea(pos, radius);\n\tgFireManager.ExtinguishPoint(pos, radius);\n\tExtinguishAllCarFiresInArea(pos, radius);\n\tCExplosion::RemoveAllExplosionsInArea(pos, radius);\n\tif(bRemoveProjectilesAndTidyUpShadows) {\n\t\tCProjectileInfo::RemoveAllProjectiles();\n\t\tCShadows::TidyUpShadows();\n\t}\n\tCPickups::RemoveUnnecessaryPickups(pos, radius);\n}\n\nbool\nCWorld::CameraToIgnoreThisObject(CEntity *ent)\n{\n\tif(CGarages::IsModelIndexADoor(ent->GetModelIndex())) return false;\n\treturn ((CObject *)ent)->m_bCameraToAvoidThisObject != 1;\n}\n\nbool\nCWorld::ProcessLineOfSight(const CVector &point1, const CVector &point2, CColPoint &point, CEntity *&entity,\n                           bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects,\n                           bool checkDummies, bool ignoreSeeThrough, bool ignoreSomeObjects, bool ignoreShootThrough)\n{\n\tint x, xstart, xend;\n\tint y, ystart, yend;\n\tint y1, y2;\n\tfloat dist;\n\n\tAdvanceCurrentScanCode();\n\n\tentity = nil;\n\tdist = 1.0f;\n\n\txstart = GetSectorIndexX(point1.x);\n\tystart = GetSectorIndexY(point1.y);\n\txend = GetSectorIndexX(point2.x);\n\tyend = GetSectorIndexY(point2.y);\n\n#define LOSARGS                                                                                                        \\\n\tCColLine(point1, point2), point, dist, entity, checkBuildings, checkVehicles, checkPeds, checkObjects,         \\\n\t    checkDummies, ignoreSeeThrough, ignoreSomeObjects, ignoreShootThrough\n\n\tif(xstart == xend && ystart == yend) {\n\t\t// Only one sector\n\t\treturn ProcessLineOfSightSector(*GetSector(xstart, ystart), LOSARGS);\n\t} else if(xstart == xend) {\n\t\t// Only step in y\n\t\tif(ystart < yend)\n\t\t\tfor(y = ystart; y <= yend; y++) ProcessLineOfSightSector(*GetSector(xstart, y), LOSARGS);\n\t\telse\n\t\t\tfor(y = ystart; y >= yend; y--) ProcessLineOfSightSector(*GetSector(xstart, y), LOSARGS);\n\t\treturn dist < 1.0f;\n\t} else if(ystart == yend) {\n\t\t// Only step in x\n\t\tif(xstart < xend)\n\t\t\tfor(x = xstart; x <= xend; x++) ProcessLineOfSightSector(*GetSector(x, ystart), LOSARGS);\n\t\telse\n\t\t\tfor(x = xstart; x >= xend; x--) ProcessLineOfSightSector(*GetSector(x, ystart), LOSARGS);\n\t\treturn dist < 1.0f;\n\t} else {\n\t\tif(point1.x < point2.x) {\n\t\t\t// Step from left to right\n\t\t\tfloat m = (point2.y - point1.y) / (point2.x - point1.x);\n\n\t\t\ty1 = ystart;\n\t\t\ty2 = GetSectorIndexY((GetWorldX(xstart + 1) - point1.x) * m + point1.y);\n\t\t\tif(y1 < y2)\n\t\t\t\tfor(y = y1; y <= y2; y++) ProcessLineOfSightSector(*GetSector(xstart, y), LOSARGS);\n\t\t\telse\n\t\t\t\tfor(y = y1; y >= y2; y--) ProcessLineOfSightSector(*GetSector(xstart, y), LOSARGS);\n\n\t\t\tfor(x = xstart + 1; x < xend; x++) {\n\t\t\t\ty1 = y2;\n\t\t\t\ty2 = GetSectorIndexY((GetWorldX(x + 1) - point1.x) * m + point1.y);\n\t\t\t\tif(y1 < y2)\n\t\t\t\t\tfor(y = y1; y <= y2; y++) ProcessLineOfSightSector(*GetSector(x, y), LOSARGS);\n\t\t\t\telse\n\t\t\t\t\tfor(y = y1; y >= y2; y--) ProcessLineOfSightSector(*GetSector(x, y), LOSARGS);\n\t\t\t}\n\n\t\t\ty1 = y2;\n\t\t\ty2 = yend;\n\t\t\tif(y1 < y2)\n\t\t\t\tfor(y = y1; y <= y2; y++) ProcessLineOfSightSector(*GetSector(xend, y), LOSARGS);\n\t\t\telse\n\t\t\t\tfor(y = y1; y >= y2; y--) ProcessLineOfSightSector(*GetSector(xend, y), LOSARGS);\n\t\t} else {\n\t\t\t// Step from right to left\n\t\t\tfloat m = (point2.y - point1.y) / (point2.x - point1.x);\n\n\t\t\ty1 = ystart;\n\t\t\ty2 = GetSectorIndexY((GetWorldX(xstart) - point1.x) * m + point1.y);\n\t\t\tif(y1 < y2)\n\t\t\t\tfor(y = y1; y <= y2; y++) ProcessLineOfSightSector(*GetSector(xstart, y), LOSARGS);\n\t\t\telse\n\t\t\t\tfor(y = y1; y >= y2; y--) ProcessLineOfSightSector(*GetSector(xstart, y), LOSARGS);\n\n\t\t\tfor(x = xstart - 1; x > xend; x--) {\n\t\t\t\ty1 = y2;\n\t\t\t\ty2 = GetSectorIndexY((GetWorldX(x) - point1.x) * m + point1.y);\n\t\t\t\tif(y1 < y2)\n\t\t\t\t\tfor(y = y1; y <= y2; y++) ProcessLineOfSightSector(*GetSector(x, y), LOSARGS);\n\t\t\t\telse\n\t\t\t\t\tfor(y = y1; y >= y2; y--) ProcessLineOfSightSector(*GetSector(x, y), LOSARGS);\n\t\t\t}\n\n\t\t\ty1 = y2;\n\t\t\ty2 = yend;\n\t\t\tif(y1 < y2)\n\t\t\t\tfor(y = y1; y <= y2; y++) ProcessLineOfSightSector(*GetSector(xend, y), LOSARGS);\n\t\t\telse\n\t\t\t\tfor(y = y1; y >= y2; y--) ProcessLineOfSightSector(*GetSector(xend, y), LOSARGS);\n\t\t}\n\t\treturn dist < 1.0f;\n\t}\n\n#undef LOSARGS\n}\n\nbool\nCWorld::ProcessLineOfSightSector(CSector &sector, const CColLine &line, CColPoint &point, float &dist, CEntity *&entity,\n                                 bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects,\n                                 bool checkDummies, bool ignoreSeeThrough, bool ignoreSomeObjects, bool ignoreShootThrough)\n{\n\tfloat mindist = dist;\n\tbool deadPeds = !!bIncludeDeadPeds;\n\tbool bikers = !!bIncludeBikers;\n\tbIncludeDeadPeds = false;\n\tbIncludeBikers = false;\n\n\tif(checkBuildings) {\n\t\tProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_BUILDINGS], line, point, mindist, entity,\n\t\t                             ignoreSeeThrough, false, ignoreShootThrough);\n\t\tProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_BUILDINGS_OVERLAP], line, point, mindist, entity,\n\t\t                             ignoreSeeThrough, false, ignoreShootThrough);\n\t}\n\n\tif(checkVehicles) {\n\t\tProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_VEHICLES], line, point, mindist, entity,\n\t\t                             ignoreSeeThrough, false, ignoreShootThrough);\n\t\tProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_VEHICLES_OVERLAP], line, point, mindist, entity,\n\t\t                             ignoreSeeThrough, false, ignoreShootThrough);\n\t}\n\n\tif(checkPeds) {\n\t\tif(deadPeds) bIncludeDeadPeds = true;\n\t\tif(bikers) bIncludeBikers = true;\n\t\tProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_PEDS], line, point, mindist, entity,\n\t\t                             ignoreSeeThrough, false, ignoreShootThrough);\n\t\tProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_PEDS_OVERLAP], line, point, mindist, entity,\n\t\t                             ignoreSeeThrough, false, ignoreShootThrough);\n\t\tbIncludeDeadPeds = false;\n\t\tbIncludeBikers = false;\n\t}\n\n\tif(checkObjects) {\n\t\tProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_OBJECTS], line, point, mindist, entity,\n\t\t                             ignoreSeeThrough, ignoreSomeObjects, ignoreShootThrough);\n\t\tProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_OBJECTS_OVERLAP], line, point, mindist, entity,\n\t\t                             ignoreSeeThrough, ignoreSomeObjects, ignoreShootThrough);\n\t}\n\n\tif(checkDummies) {\n\t\tProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_DUMMIES], line, point, mindist, entity,\n\t\t                             ignoreSeeThrough, false, ignoreShootThrough);\n\t\tProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_DUMMIES_OVERLAP], line, point, mindist, entity,\n\t\t                             ignoreSeeThrough, false, ignoreShootThrough);\n\t}\n\n\tbIncludeDeadPeds = deadPeds;\n\tbIncludeBikers = bikers;\n\n\tif(mindist < dist) {\n\t\tdist = mindist;\n\t\treturn true;\n\t} else\n\t\treturn false;\n}\n\nbool\nCWorld::ProcessLineOfSightSectorList(CPtrList &list, const CColLine &line, CColPoint &point, float &dist,\n                                     CEntity *&entity, bool ignoreSeeThrough, bool ignoreSomeObjects, bool ignoreShootThrough)\n{\n\tbool deadPeds = false;\n\tbool bikers = false;\n\tbool carTyres = false;\n\tfloat mindist = dist;\n\tCPtrNode *node;\n\tCEntity *e;\n\tCColModel *colmodel;\n\tCColModel tyreCol;\n\tCColSphere tyreSpheres[6];\n\tCColPoint tyreColPoint;\n\tfloat tyreDist;\n\n\tif(bIncludeCarTyres && list.first && ((CEntity*)list.first->item)->IsVehicle()){\n\t\tcarTyres = true;\n\t\ttyreCol.numTriangles = 0;\n\t\ttyreCol.numBoxes = 0;\n\t\ttyreCol.numLines = 0;\n\t\ttyreCol.spheres = tyreSpheres;\n\t\ttyreCol.numSpheres = ARRAY_SIZE(tyreSpheres);\n\t}\n\tif(list.first && bIncludeDeadPeds && ((CEntity *)list.first->item)->IsPed()) deadPeds = true;\n\tif(list.first && bIncludeBikers && ((CEntity *)list.first->item)->IsPed()) bikers = true;\n\n\tfor(node = list.first; node; node = node->next) {\n\t\te = (CEntity *)node->item;\n\t\tif(e->m_scanCode != GetCurrentScanCode() && e != pIgnoreEntity && (e->bUsesCollision || deadPeds || bikers) &&\n\t\t   !(ignoreSomeObjects && CameraToIgnoreThisObject(e))) {\n\t\t\tcolmodel = nil;\n\t\t\ttyreDist = mindist;\n\t\t\te->m_scanCode = GetCurrentScanCode();\n\n\t\t\tif(e->IsPed()) {\n\t\t\t\tif(e->bUsesCollision || deadPeds && ((CPed *)e)->m_nPedState == PED_DEAD || bikers && ((CPed*)e)->InVehicle() && (((CPed*)e)->m_pMyVehicle->IsBike() || ((CPed*)e)->m_pMyVehicle->IsBoat())) {\n\t\t\t\t\tcolmodel = ((CPedModelInfo *)CModelInfo::GetModelInfo(e->GetModelIndex()))->AnimatePedColModelSkinned(e->GetClump());\n\t\t\t\t} else\n\t\t\t\t\tcolmodel = nil;\n\n\t\t\t} else if(e->bUsesCollision)\n\t\t\t\tcolmodel = CModelInfo::GetModelInfo(e->GetModelIndex())->GetColModel();\n\n\t\t\tif(colmodel && CCollision::ProcessLineOfSight(line, e->GetMatrix(), *colmodel, point, mindist,\n\t\t\t                                              ignoreSeeThrough, ignoreShootThrough))\n\t\t\t\tentity = e;\n\t\t\tif(carTyres && ((CVehicle*)e)->SetUpWheelColModel(&tyreCol) && CCollision::ProcessLineOfSight(line, e->GetMatrix(), tyreCol, tyreColPoint, tyreDist, false, ignoreShootThrough)){\n\t\t\t\tfloat dp1 = DotProduct(line.p1 - line.p0, e->GetRight());\n\t\t\t\tfloat dp2 = DotProduct(point.point - e->GetPosition(), e->GetRight());\n\t\t\t\tif(tyreDist < mindist || dp1 < -0.85f && dp2 > 0.0f || dp1 > 0.85f && dp2 < 0.0f){\n\t\t\t\t\tmindist = tyreDist;\n\t\t\t\t\tpoint = tyreColPoint;\n\t\t\t\t\tentity = e;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\ttyreCol.spheres = nil;\n\n\tif(mindist < dist) {\n\t\tdist = mindist;\n\t\treturn true;\n\t} else\n\t\treturn false;\n}\n\nbool\nCWorld::ProcessVerticalLine(const CVector &point1, float z2, CColPoint &point, CEntity *&entity, bool checkBuildings,\n                            bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies,\n                            bool ignoreSeeThrough, CStoredCollPoly *poly)\n{\n\tAdvanceCurrentScanCode();\n\tCVector point2(point1.x, point1.y, z2);\n\tint secX = GetSectorIndexX(point1.x);\n\tint secY = GetSectorIndexY(point1.y);\n\tsecX = clamp(secX, 0, NUMSECTORS_X-1);\n\tsecY = clamp(secY, 0, NUMSECTORS_Y-1);\n\treturn ProcessVerticalLineSector(*GetSector(secX, secY),\n\t                                 CColLine(point1, point2), point, entity, checkBuildings, checkVehicles,\n\t                                 checkPeds, checkObjects, checkDummies, ignoreSeeThrough, poly);\n}\n\nbool\nCWorld::ProcessVerticalLineSector(CSector &sector, const CColLine &line, CColPoint &point, CEntity *&entity,\n                                  bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects,\n                                  bool checkDummies, bool ignoreSeeThrough, CStoredCollPoly *poly)\n{\n\tfloat mindist = 1.0f;\n\n\tif(checkBuildings) {\n\t\tProcessVerticalLineSectorList(sector.m_lists[ENTITYLIST_BUILDINGS], line, point, mindist, entity,\n\t\t                              ignoreSeeThrough, poly);\n\t\tProcessVerticalLineSectorList(sector.m_lists[ENTITYLIST_BUILDINGS_OVERLAP], line, point, mindist,\n\t\t                              entity, ignoreSeeThrough, poly);\n\t}\n\n\tif(checkVehicles) {\n\t\tProcessVerticalLineSectorList(sector.m_lists[ENTITYLIST_VEHICLES], line, point, mindist, entity,\n\t\t                              ignoreSeeThrough, poly);\n\t\tProcessVerticalLineSectorList(sector.m_lists[ENTITYLIST_VEHICLES_OVERLAP], line, point, mindist, entity,\n\t\t                              ignoreSeeThrough, poly);\n\t}\n\n\tif(checkPeds) {\n\t\tProcessVerticalLineSectorList(sector.m_lists[ENTITYLIST_PEDS], line, point, mindist, entity,\n\t\t                              ignoreSeeThrough, poly);\n\t\tProcessVerticalLineSectorList(sector.m_lists[ENTITYLIST_PEDS_OVERLAP], line, point, mindist, entity,\n\t\t                              ignoreSeeThrough, poly);\n\t}\n\n\tif(checkObjects) {\n\t\tProcessVerticalLineSectorList(sector.m_lists[ENTITYLIST_OBJECTS], line, point, mindist, entity,\n\t\t                              ignoreSeeThrough, poly);\n\t\tProcessVerticalLineSectorList(sector.m_lists[ENTITYLIST_OBJECTS_OVERLAP], line, point, mindist, entity,\n\t\t                              ignoreSeeThrough, poly);\n\t}\n\n\tif(checkDummies) {\n\t\tProcessVerticalLineSectorList(sector.m_lists[ENTITYLIST_DUMMIES], line, point, mindist, entity,\n\t\t                              ignoreSeeThrough, poly);\n\t\tProcessVerticalLineSectorList(sector.m_lists[ENTITYLIST_DUMMIES_OVERLAP], line, point, mindist, entity,\n\t\t                              ignoreSeeThrough, poly);\n\t}\n\n\treturn mindist < 1.0f;\n}\n\nbool\nCWorld::ProcessVerticalLineSectorList(CPtrList &list, const CColLine &line, CColPoint &point, float &dist,\n                                      CEntity *&entity, bool ignoreSeeThrough, CStoredCollPoly *poly)\n{\n\tfloat mindist = dist;\n\tCPtrNode *node;\n\tCEntity *e;\n\tCColModel *colmodel;\n\n\tfor(node = list.first; node; node = node->next) {\n\t\te = (CEntity *)node->item;\n\t\tif(e->m_scanCode != GetCurrentScanCode() && e->bUsesCollision) {\n\t\t\te->m_scanCode = GetCurrentScanCode();\n\n\t\t\tcolmodel = CModelInfo::GetModelInfo(e->GetModelIndex())->GetColModel();\n\t\t\tif(CCollision::ProcessVerticalLine(line, e->GetMatrix(), *colmodel, point, mindist,\n\t\t\t                                   ignoreSeeThrough, false, poly))\n\t\t\t\tentity = e;\n\t\t}\n\t}\n\n\tif(mindist < dist) {\n\t\tdist = mindist;\n\t\treturn true;\n\t} else\n\t\treturn false;\n}\n\nbool\nCWorld::GetIsLineOfSightClear(const CVector &point1, const CVector &point2, bool checkBuildings, bool checkVehicles,\n                              bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSeeThrough,\n                              bool ignoreSomeObjects)\n{\n\tint x, xstart, xend;\n\tint y, ystart, yend;\n\tint y1, y2;\n\n\tAdvanceCurrentScanCode();\n\n\txstart = GetSectorIndexX(point1.x);\n\tystart = GetSectorIndexY(point1.y);\n\txend = GetSectorIndexX(point2.x);\n\tyend = GetSectorIndexY(point2.y);\n\n#define LOSARGS                                                                                                        \\\n\tCColLine(point1, point2), checkBuildings, checkVehicles, checkPeds, checkObjects, checkDummies,                \\\n\t    ignoreSeeThrough, ignoreSomeObjects\n\n\tif(xstart == xend && ystart == yend) {\n\t\t// Only one sector\n\t\treturn GetIsLineOfSightSectorClear(*GetSector(xstart, ystart), LOSARGS);\n\t} else if(xstart == xend) {\n\t\t// Only step in y\n\t\tif(ystart < yend) {\n\t\t\tfor(y = ystart; y <= yend; y++)\n\t\t\t\tif(!GetIsLineOfSightSectorClear(*GetSector(xstart, y), LOSARGS)) return false;\n\t\t} else {\n\t\t\tfor(y = ystart; y >= yend; y--)\n\t\t\t\tif(!GetIsLineOfSightSectorClear(*GetSector(xstart, y), LOSARGS)) return false;\n\t\t}\n\t} else if(ystart == yend) {\n\t\t// Only step in x\n\t\tif(xstart < xend) {\n\t\t\tfor(x = xstart; x <= xend; x++)\n\t\t\t\tif(!GetIsLineOfSightSectorClear(*GetSector(x, ystart), LOSARGS)) return false;\n\t\t} else {\n\t\t\tfor(x = xstart; x >= xend; x--)\n\t\t\t\tif(!GetIsLineOfSightSectorClear(*GetSector(x, ystart), LOSARGS)) return false;\n\t\t}\n\t} else {\n\t\tif(point1.x < point2.x) {\n\t\t\t// Step from left to right\n\t\t\tfloat m = (point2.y - point1.y) / (point2.x - point1.x);\n\n\t\t\ty1 = ystart;\n\t\t\ty2 = GetSectorIndexY((GetWorldX(xstart + 1) - point1.x) * m + point1.y);\n\t\t\tif(y1 < y2) {\n\t\t\t\tfor(y = y1; y <= y2; y++)\n\t\t\t\t\tif(!GetIsLineOfSightSectorClear(*GetSector(xstart, y), LOSARGS)) return false;\n\t\t\t} else {\n\t\t\t\tfor(y = y1; y >= y2; y--)\n\t\t\t\t\tif(!GetIsLineOfSightSectorClear(*GetSector(xstart, y), LOSARGS)) return false;\n\t\t\t}\n\n\t\t\tfor(x = xstart + 1; x < xend; x++) {\n\t\t\t\ty1 = y2;\n\t\t\t\ty2 = GetSectorIndexY((GetWorldX(x + 1) - point1.x) * m + point1.y);\n\t\t\t\tif(y1 < y2) {\n\t\t\t\t\tfor(y = y1; y <= y2; y++)\n\t\t\t\t\t\tif(!GetIsLineOfSightSectorClear(*GetSector(x, y), LOSARGS))\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t} else {\n\t\t\t\t\tfor(y = y1; y >= y2; y--)\n\t\t\t\t\t\tif(!GetIsLineOfSightSectorClear(*GetSector(x, y), LOSARGS))\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\ty1 = y2;\n\t\t\ty2 = yend;\n\t\t\tif(y1 < y2) {\n\t\t\t\tfor(y = y1; y <= y2; y++)\n\t\t\t\t\tif(!GetIsLineOfSightSectorClear(*GetSector(xend, y), LOSARGS)) return false;\n\t\t\t} else {\n\t\t\t\tfor(y = y1; y >= y2; y--)\n\t\t\t\t\tif(!GetIsLineOfSightSectorClear(*GetSector(xend, y), LOSARGS)) return false;\n\t\t\t}\n\t\t} else {\n\t\t\t// Step from right to left\n\t\t\tfloat m = (point2.y - point1.y) / (point2.x - point1.x);\n\n\t\t\ty1 = ystart;\n\t\t\ty2 = GetSectorIndexY((GetWorldX(xstart) - point1.x) * m + point1.y);\n\t\t\tif(y1 < y2) {\n\t\t\t\tfor(y = y1; y <= y2; y++)\n\t\t\t\t\tif(!GetIsLineOfSightSectorClear(*GetSector(xstart, y), LOSARGS)) return false;\n\t\t\t} else {\n\t\t\t\tfor(y = y1; y >= y2; y--)\n\t\t\t\t\tif(!GetIsLineOfSightSectorClear(*GetSector(xstart, y), LOSARGS)) return false;\n\t\t\t}\n\n\t\t\tfor(x = xstart - 1; x > xend; x--) {\n\t\t\t\ty1 = y2;\n\t\t\t\ty2 = GetSectorIndexY((GetWorldX(x) - point1.x) * m + point1.y);\n\t\t\t\tif(y1 < y2) {\n\t\t\t\t\tfor(y = y1; y <= y2; y++)\n\t\t\t\t\t\tif(!GetIsLineOfSightSectorClear(*GetSector(x, y), LOSARGS))\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t} else {\n\t\t\t\t\tfor(y = y1; y >= y2; y--)\n\t\t\t\t\t\tif(!GetIsLineOfSightSectorClear(*GetSector(x, y), LOSARGS))\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\ty1 = y2;\n\t\t\ty2 = yend;\n\t\t\tif(y1 < y2) {\n\t\t\t\tfor(y = y1; y <= y2; y++)\n\t\t\t\t\tif(!GetIsLineOfSightSectorClear(*GetSector(xend, y), LOSARGS)) return false;\n\t\t\t} else {\n\t\t\t\tfor(y = y1; y >= y2; y--)\n\t\t\t\t\tif(!GetIsLineOfSightSectorClear(*GetSector(xend, y), LOSARGS)) return false;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn true;\n\n#undef LOSARGS\n}\n\nbool\nCWorld::GetIsLineOfSightSectorClear(CSector &sector, const CColLine &line, bool checkBuildings, bool checkVehicles,\n                                    bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSeeThrough,\n                                    bool ignoreSomeObjects)\n{\n\tif(checkBuildings) {\n\t\tif(!GetIsLineOfSightSectorListClear(sector.m_lists[ENTITYLIST_BUILDINGS], line, ignoreSeeThrough))\n\t\t\treturn false;\n\t\tif(!GetIsLineOfSightSectorListClear(sector.m_lists[ENTITYLIST_BUILDINGS_OVERLAP], line,\n\t\t                                    ignoreSeeThrough))\n\t\t\treturn false;\n\t}\n\n\tif(checkVehicles) {\n\t\tif(!GetIsLineOfSightSectorListClear(sector.m_lists[ENTITYLIST_VEHICLES], line, ignoreSeeThrough))\n\t\t\treturn false;\n\t\tif(!GetIsLineOfSightSectorListClear(sector.m_lists[ENTITYLIST_VEHICLES_OVERLAP], line,\n\t\t                                    ignoreSeeThrough))\n\t\t\treturn false;\n\t}\n\n\tif(checkPeds) {\n\t\tif(!GetIsLineOfSightSectorListClear(sector.m_lists[ENTITYLIST_PEDS], line, ignoreSeeThrough))\n\t\t\treturn false;\n\t\tif(!GetIsLineOfSightSectorListClear(sector.m_lists[ENTITYLIST_PEDS_OVERLAP], line, ignoreSeeThrough))\n\t\t\treturn false;\n\t}\n\n\tif(checkObjects) {\n\t\tif(!GetIsLineOfSightSectorListClear(sector.m_lists[ENTITYLIST_OBJECTS], line, ignoreSeeThrough,\n\t\t                                    ignoreSomeObjects))\n\t\t\treturn false;\n\t\tif(!GetIsLineOfSightSectorListClear(sector.m_lists[ENTITYLIST_OBJECTS_OVERLAP], line, ignoreSeeThrough,\n\t\t                                    ignoreSomeObjects))\n\t\t\treturn false;\n\t}\n\n\tif(checkDummies) {\n\t\tif(!GetIsLineOfSightSectorListClear(sector.m_lists[ENTITYLIST_DUMMIES], line, ignoreSeeThrough))\n\t\t\treturn false;\n\t\tif(!GetIsLineOfSightSectorListClear(sector.m_lists[ENTITYLIST_DUMMIES_OVERLAP], line, ignoreSeeThrough))\n\t\t\treturn false;\n\t}\n\n\treturn true;\n}\n\nbool\nCWorld::GetIsLineOfSightSectorListClear(CPtrList &list, const CColLine &line, bool ignoreSeeThrough,\n                                        bool ignoreSomeObjects)\n{\n\tCPtrNode *node;\n\tCEntity *e;\n\tCColModel *colmodel;\n\n\tfor(node = list.first; node; node = node->next) {\n\t\te = (CEntity *)node->item;\n\t\tif(e->m_scanCode != GetCurrentScanCode() && e->bUsesCollision) {\n\n\t\t\te->m_scanCode = GetCurrentScanCode();\n\n\t\t\tif(e != pIgnoreEntity && !(ignoreSomeObjects && CameraToIgnoreThisObject(e))) {\n\n\t\t\t\tcolmodel = CModelInfo::GetModelInfo(e->GetModelIndex())->GetColModel();\n\n\t\t\t\tif(CCollision::TestLineOfSight(line, e->GetMatrix(), *colmodel, ignoreSeeThrough, false))\n\t\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn true;\n}\n\nvoid\nCWorld::FindObjectsInRangeSectorList(CPtrList &list, Const CVector &centre, float radius, bool ignoreZ, int16 *numObjects,\n                                     int16 lastObject, CEntity **objects)\n{\n\tfloat radiusSqr = radius * radius;\n\tfloat objDistSqr;\n\n\tfor(CPtrNode *node = list.first; node; node = node->next) {\n\t\tCEntity *object = (CEntity *)node->item;\n\t\tif(object->m_scanCode != GetCurrentScanCode()) {\n\t\t\tobject->m_scanCode = GetCurrentScanCode();\n\n\t\t\tCVector diff = centre - object->GetPosition();\n\t\t\tif(ignoreZ)\n\t\t\t\tobjDistSqr = diff.MagnitudeSqr2D();\n\t\t\telse\n\t\t\t\tobjDistSqr = diff.MagnitudeSqr();\n\n\t\t\tif(objDistSqr < radiusSqr && *numObjects < lastObject) {\n\t\t\t\tif(objects) { objects[*numObjects] = object; }\n\t\t\t\t(*numObjects)++;\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nCWorld::FindObjectsInRange(Const CVector &centre, float radius, bool ignoreZ, int16 *numObjects, int16 lastObject,\n                           CEntity **objects, bool checkBuildings, bool checkVehicles, bool checkPeds,\n                           bool checkObjects, bool checkDummies)\n{\n\tint minX = GetSectorIndexX(centre.x - radius);\n\tif(minX <= 0) minX = 0;\n\n\tint minY = GetSectorIndexY(centre.y - radius);\n\tif(minY <= 0) minY = 0;\n\n\tint maxX = GetSectorIndexX(centre.x + radius);\n\tif(maxX >= NUMSECTORS_X) maxX = NUMSECTORS_X - 1;\n\n\tint maxY = GetSectorIndexY(centre.y + radius);\n\tif(maxY >= NUMSECTORS_Y) maxY = NUMSECTORS_Y - 1;\n\n\tAdvanceCurrentScanCode();\n\n\t*numObjects = 0;\n\tfor(int curY = minY; curY <= maxY; curY++) {\n\t\tfor(int curX = minX; curX <= maxX; curX++) {\n\t\t\tCSector *sector = GetSector(curX, curY);\n\t\t\tif(checkBuildings) {\n\t\t\t\tFindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_BUILDINGS], centre, radius,\n\t\t\t\t                             ignoreZ, numObjects, lastObject, objects);\n\t\t\t\tFindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP], centre,\n\t\t\t\t                             radius, ignoreZ, numObjects, lastObject, objects);\n\t\t\t}\n\t\t\tif(checkVehicles) {\n\t\t\t\tFindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_VEHICLES], centre, radius,\n\t\t\t\t                             ignoreZ, numObjects, lastObject, objects);\n\t\t\t\tFindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_VEHICLES_OVERLAP], centre,\n\t\t\t\t                             radius, ignoreZ, numObjects, lastObject, objects);\n\t\t\t}\n\t\t\tif(checkPeds) {\n\t\t\t\tFindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_PEDS], centre, radius, ignoreZ,\n\t\t\t\t                             numObjects, lastObject, objects);\n\t\t\t\tFindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_PEDS_OVERLAP], centre, radius,\n\t\t\t\t                             ignoreZ, numObjects, lastObject, objects);\n\t\t\t}\n\t\t\tif(checkObjects) {\n\t\t\t\tFindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_OBJECTS], centre, radius,\n\t\t\t\t                             ignoreZ, numObjects, lastObject, objects);\n\t\t\t\tFindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_OBJECTS_OVERLAP], centre,\n\t\t\t\t                             radius, ignoreZ, numObjects, lastObject, objects);\n\t\t\t}\n\t\t\tif(checkDummies) {\n\t\t\t\tFindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_DUMMIES], centre, radius,\n\t\t\t\t                             ignoreZ, numObjects, lastObject, objects);\n\t\t\t\tFindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_DUMMIES_OVERLAP], centre,\n\t\t\t\t                             radius, ignoreZ, numObjects, lastObject, objects);\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nCWorld::FindObjectsOfTypeInRangeSectorList(uint32 modelId, CPtrList &list, const CVector &position, float radius,\n                                           bool bCheck2DOnly, int16 *nEntitiesFound, int16 maxEntitiesToFind,\n                                           CEntity **aEntities)\n{\n\tfor(CPtrNode *pNode = list.first; pNode; pNode = pNode->next) {\n\t\tCEntity *pEntity = (CEntity *)pNode->item;\n\t\tif(pEntity->m_scanCode != GetCurrentScanCode()) {\n\t\t\tpEntity->m_scanCode = GetCurrentScanCode();\n\t\t\tif (modelId == pEntity->GetModelIndex()) {\n\t\t\t\tfloat fMagnitude = 0.0f;\n\t\t\t\tif(bCheck2DOnly)\n\t\t\t\t\tfMagnitude = (position - pEntity->GetPosition()).MagnitudeSqr2D();\n\t\t\t\telse\n\t\t\t\t\tfMagnitude = (position - pEntity->GetPosition()).MagnitudeSqr();\n\t\t\t\tif(fMagnitude < radius * radius && *nEntitiesFound < maxEntitiesToFind) {\n\t\t\t\t\tif(aEntities) aEntities[*nEntitiesFound] = pEntity;\n\t\t\t\t\t++*nEntitiesFound;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nCWorld::FindObjectsOfTypeInRange(uint32 modelId, const CVector &position, float radius, bool bCheck2DOnly,\n                                 int16 *nEntitiesFound, int16 maxEntitiesToFind, CEntity **aEntities, bool bBuildings,\n                                 bool bVehicles, bool bPeds, bool bObjects, bool bDummies)\n{\n\tAdvanceCurrentScanCode();\n\t*nEntitiesFound = 0;\n\tconst CVector2D vecSectorStartPos(position.x - radius, position.y - radius);\n\tconst CVector2D vecSectorEndPos(position.x + radius, position.y + radius);\n\tconst int32 nStartX = Max(GetSectorIndexX(vecSectorStartPos.x), 0);\n\tconst int32 nStartY = Max(GetSectorIndexY(vecSectorStartPos.y), 0);\n#ifdef FIX_BUGS\n\tconst int32 nEndX = Min(GetSectorIndexX(vecSectorEndPos.x), NUMSECTORS_X - 1);\n\tconst int32 nEndY = Min(GetSectorIndexY(vecSectorEndPos.y), NUMSECTORS_Y - 1);\n#else\n\tconst int32 nEndX = Min(GetSectorIndexX(vecSectorEndPos.x), NUMSECTORS_X);\n\tconst int32 nEndY = Min(GetSectorIndexY(vecSectorEndPos.y), NUMSECTORS_Y);\n#endif\n\tfor(int32 y = nStartY; y <= nEndY; y++) {\n\t\tfor(int32 x = nStartX; x <= nEndX; x++) {\n\t\t\tCSector *pSector = GetSector(x, y);\n\t\t\tif(bBuildings) {\n\t\t\t\tFindObjectsOfTypeInRangeSectorList(\n\t\t\t\t    modelId, pSector->m_lists[ENTITYLIST_BUILDINGS], position, radius, bCheck2DOnly,\n\t\t\t\t    nEntitiesFound, maxEntitiesToFind, aEntities);\n\t\t\t\tFindObjectsOfTypeInRangeSectorList(\n\t\t\t\t    modelId, pSector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP], position, radius,\n\t\t\t\t    bCheck2DOnly, nEntitiesFound, maxEntitiesToFind, aEntities);\n\t\t\t}\n\t\t\tif(bVehicles) {\n\t\t\t\tFindObjectsOfTypeInRangeSectorList(\n\t\t\t\t    modelId, pSector->m_lists[ENTITYLIST_VEHICLES], position, radius, bCheck2DOnly,\n\t\t\t\t    nEntitiesFound, maxEntitiesToFind, aEntities);\n\t\t\t\tFindObjectsOfTypeInRangeSectorList(\n\t\t\t\t    modelId, pSector->m_lists[ENTITYLIST_VEHICLES_OVERLAP], position, radius,\n\t\t\t\t    bCheck2DOnly, nEntitiesFound, maxEntitiesToFind, aEntities);\n\t\t\t}\n\t\t\tif(bPeds) {\n\t\t\t\tFindObjectsOfTypeInRangeSectorList(\n\t\t\t\t    modelId, pSector->m_lists[ENTITYLIST_PEDS], position, radius, bCheck2DOnly,\n\t\t\t\t    nEntitiesFound, maxEntitiesToFind, aEntities);\n\t\t\t\tFindObjectsOfTypeInRangeSectorList(\n\t\t\t\t    modelId, pSector->m_lists[ENTITYLIST_PEDS_OVERLAP], position, radius, bCheck2DOnly,\n\t\t\t\t    nEntitiesFound, maxEntitiesToFind, aEntities);\n\t\t\t}\n\t\t\tif(bObjects) {\n\t\t\t\tFindObjectsOfTypeInRangeSectorList(\n\t\t\t\t    modelId, pSector->m_lists[ENTITYLIST_OBJECTS], position, radius, bCheck2DOnly,\n\t\t\t\t    nEntitiesFound, maxEntitiesToFind, aEntities);\n\t\t\t\tFindObjectsOfTypeInRangeSectorList(\n\t\t\t\t    modelId, pSector->m_lists[ENTITYLIST_OBJECTS_OVERLAP], position, radius,\n\t\t\t\t    bCheck2DOnly, nEntitiesFound, maxEntitiesToFind, aEntities);\n\t\t\t}\n\t\t\tif(bDummies) {\n\t\t\t\tFindObjectsOfTypeInRangeSectorList(\n\t\t\t\t    modelId, pSector->m_lists[ENTITYLIST_DUMMIES], position, radius, bCheck2DOnly,\n\t\t\t\t    nEntitiesFound, maxEntitiesToFind, aEntities);\n\t\t\t\tFindObjectsOfTypeInRangeSectorList(\n\t\t\t\t    modelId, pSector->m_lists[ENTITYLIST_DUMMIES_OVERLAP], position, radius,\n\t\t\t\t    bCheck2DOnly, nEntitiesFound, maxEntitiesToFind, aEntities);\n\t\t\t}\n\t\t}\n\t}\n}\n\nCEntity *\nCWorld::TestSphereAgainstWorld(CVector centre, float radius, CEntity *entityToIgnore, bool checkBuildings,\n                               bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies,\n                               bool ignoreSomeObjects)\n{\n\tCEntity *foundE = nil;\n\n\tint minX = GetSectorIndexX(centre.x - radius);\n\tif(minX <= 0) minX = 0;\n\n\tint minY = GetSectorIndexY(centre.y - radius);\n\tif(minY <= 0) minY = 0;\n\n\tint maxX = GetSectorIndexX(centre.x + radius);\n#ifdef FIX_BUGS\n\tif(maxX >= NUMSECTORS_X) maxX = NUMSECTORS_X - 1;\n#else\n\tif(maxX >= NUMSECTORS_X) maxX = NUMSECTORS_X;\n#endif\n\n\tint maxY = GetSectorIndexY(centre.y + radius);\n#ifdef FIX_BUGS\n\tif(maxY >= NUMSECTORS_Y) maxY = NUMSECTORS_Y - 1;\n#else\n\tif(maxY >= NUMSECTORS_Y) maxY = NUMSECTORS_Y;\n#endif\n\n\tAdvanceCurrentScanCode();\n\n\tfor(int curY = minY; curY <= maxY; curY++) {\n\t\tfor(int curX = minX; curX <= maxX; curX++) {\n\t\t\tCSector *sector = GetSector(curX, curY);\n\t\t\tif(checkBuildings) {\n\t\t\t\tfoundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_BUILDINGS], centre,\n\t\t\t\t                                     radius, entityToIgnore, false);\n\t\t\t\tif(foundE) return foundE;\n\n\t\t\t\tfoundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP],\n\t\t\t\t                                     centre, radius, entityToIgnore, false);\n\t\t\t\tif(foundE) return foundE;\n\t\t\t}\n\t\t\tif(checkVehicles) {\n\t\t\t\tfoundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_VEHICLES], centre,\n\t\t\t\t                                     radius, entityToIgnore, false);\n\t\t\t\tif(foundE) return foundE;\n\n\t\t\t\tfoundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_VEHICLES_OVERLAP],\n\t\t\t\t                                     centre, radius, entityToIgnore, false);\n\t\t\t\tif(foundE) return foundE;\n\t\t\t}\n\t\t\tif(checkPeds) {\n\t\t\t\tfoundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_PEDS], centre, radius,\n\t\t\t\t                                     entityToIgnore, false);\n\t\t\t\tif(foundE) return foundE;\n\n\t\t\t\tfoundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_PEDS_OVERLAP], centre,\n\t\t\t\t                                     radius, entityToIgnore, false);\n\t\t\t\tif(foundE) return foundE;\n\t\t\t}\n\t\t\tif(checkObjects) {\n\t\t\t\tfoundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_OBJECTS], centre,\n\t\t\t\t                                     radius, entityToIgnore, ignoreSomeObjects);\n\t\t\t\tif(foundE) return foundE;\n\n\t\t\t\tfoundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_OBJECTS_OVERLAP],\n\t\t\t\t                                     centre, radius, entityToIgnore, ignoreSomeObjects);\n\t\t\t\tif(foundE) return foundE;\n\t\t\t}\n\t\t\tif(checkDummies) {\n\t\t\t\tfoundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_DUMMIES], centre,\n\t\t\t\t                                     radius, entityToIgnore, false);\n\t\t\t\tif(foundE) return foundE;\n\n\t\t\t\tfoundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_DUMMIES_OVERLAP],\n\t\t\t\t                                     centre, radius, entityToIgnore, false);\n\t\t\t\tif(foundE) return foundE;\n\t\t\t}\n\t\t}\n\t}\n\treturn foundE;\n}\n\nCEntity *\nCWorld::TestSphereAgainstSectorList(CPtrList &list, CVector spherePos, float radius, CEntity *entityToIgnore,\n                                    bool ignoreSomeObjects)\n{\n\tstatic CColModel OurColModel;\n\tCColSphere sphere;\n\n\tOurColModel.boundingSphere.center.x = 0.0f;\n\tOurColModel.boundingSphere.center.y = 0.0f;\n\tOurColModel.boundingSphere.center.z = 0.0f;\n\tOurColModel.boundingSphere.radius = radius;\n\tOurColModel.boundingBox.min.x = -radius;\n\tOurColModel.boundingBox.min.y = -radius;\n\tOurColModel.boundingBox.min.z = -radius;\n\tOurColModel.boundingBox.max.x = radius;\n\tOurColModel.boundingBox.max.y = radius;\n\tOurColModel.boundingBox.max.z = radius;\n\tOurColModel.numSpheres = 1;\n\tsphere.Set(radius, CVector(0.0f, 0.0f, 0.0f));\n\tOurColModel.spheres = &sphere;\n\tOurColModel.numLines = 0;\n\tOurColModel.numBoxes = 0;\n\tOurColModel.numTriangles = 0;\n\tOurColModel.ownsCollisionVolumes = false;\n\n\tCMatrix sphereMat;\n\tsphereMat.SetTranslate(spherePos);\n\n\tfor(CPtrNode *node = list.first; node; node = node->next) {\n\t\tCEntity *e = (CEntity *)node->item;\n\n\t\tif(e->m_scanCode != GetCurrentScanCode()) {\n\t\t\te->m_scanCode = GetCurrentScanCode();\n\n\t\t\tif(e != entityToIgnore && e->bUsesCollision &&\n\t\t\t   !(ignoreSomeObjects && CameraToIgnoreThisObject(e))) {\n\t\t\t\tCVector diff = spherePos - e->GetBoundCentre();\n\t\t\t\tfloat distance = diff.Magnitude();\n\n\t\t\t\tif(e->GetBoundRadius() + radius > distance) {\n\t\t\t\t\tCColModel *eCol = CModelInfo::GetModelInfo(e->GetModelIndex())->GetColModel();\n\t\t\t\t\tint collidedSpheres =\n\t\t\t\t\t    CCollision::ProcessColModels(sphereMat, OurColModel, e->GetMatrix(), *eCol,\n\t\t\t\t\t                                 gaTempSphereColPoints, nil, nil);\n\n\t\t\t\t\tif(collidedSpheres != 0 ||\n\t\t\t\t\t   (e->IsVehicle() && ((CVehicle *)e)->m_vehType == VEHICLE_TYPE_CAR && e->GetModelIndex() != MI_DODO &&\n\t\t\t\t\t    radius + eCol->boundingBox.max.x > distance)) {\n\t\t\t\t\t\treturn e;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn nil;\n}\n\nfloat\nCWorld::FindGroundZForCoord(float x, float y)\n{\n\tCColPoint point;\n\tCEntity *ent;\n\tif(ProcessVerticalLine(CVector(x, y, 1000.0f), -1000.0f, point, ent, true, false, false, false, true, false,\n\t                       nil))\n\t\treturn point.point.z;\n\telse\n\t\treturn 20.0f;\n}\n\nfloat\nCWorld::FindGroundZFor3DCoord(float x, float y, float z, bool *found)\n{\n\tCColPoint point;\n\tCEntity *ent;\n\tif(ProcessVerticalLine(CVector(x, y, z), -1000.0f, point, ent, true, false, false, false, false, false, nil)) {\n\t\tif(found) *found = true;\n\t\treturn point.point.z;\n\t} else {\n\t\tif(found) *found = false;\n\t\treturn 0.0f;\n\t}\n}\n\nfloat\nCWorld::FindRoofZFor3DCoord(float x, float y, float z, bool *found)\n{\n\tCColPoint point;\n\tCEntity *ent;\n\tif(ProcessVerticalLine(CVector(x, y, z), 1000.0f, point, ent, true, false, false, false, true, false, nil)) {\n\t\tif(found) *found = true;\n\t\treturn point.point.z;\n\t} else {\n\t\tif(found == nil)\n\t\t\tprintf(\"THERE IS NO MAP BELOW THE FOLLOWING COORS:%f %f %f. (FindGroundZFor3DCoord)\\n\", x, y,\n\t\t\t       z);\n\t\tif(found) *found = false;\n\t\treturn 20.0f;\n\t}\n}\n\nvoid\nCWorld::RemoveReferencesToDeletedObject(CEntity *pDeletedObject)\n{\n\tint32 i = CPools::GetPedPool()->GetSize();\n\twhile(--i >= 0) {\n\t\tCPed *pPed = CPools::GetPedPool()->GetSlot(i);\n\t\tif(pPed && pPed != pDeletedObject) {\n\t\t\tpPed->RemoveRefsToEntity(pDeletedObject);\n\t\t\tif(pPed->m_pCurrentPhysSurface == pDeletedObject) pPed->m_pCurrentPhysSurface = nil;\n\t\t}\n\t}\n\ti = CPools::GetVehiclePool()->GetSize();\n\twhile(--i >= 0) {\n\t\tCVehicle *pVehicle = CPools::GetVehiclePool()->GetSlot(i);\n\t\tif(pVehicle && pVehicle != pDeletedObject) {\n\t\t\tpVehicle->RemoveRefsToEntity(pDeletedObject);\n\t\t\tpVehicle->RemoveRefsToVehicle(pDeletedObject);\n\t\t}\n\t}\n\ti = CPools::GetObjectPool()->GetSize();\n\twhile(--i >= 0) {\n\t\tCObject *pObject = CPools::GetObjectPool()->GetSlot(i);\n\t\tif(pObject && pObject != pDeletedObject) { pObject->RemoveRefsToEntity(pDeletedObject); }\n\t}\n}\n\nvoid\nCWorld::FindObjectsKindaColliding(const CVector &position, float radius, bool bCheck2DOnly, int16 *nCollidingEntities,\n                                  int16 maxEntitiesToFind, CEntity **aEntities, bool bBuildings, bool bVehicles,\n                                  bool bPeds, bool bObjects, bool bDummies)\n{\n\tAdvanceCurrentScanCode();\n\t*nCollidingEntities = 0;\n\tconst CVector2D vecSectorStartPos(position.x - radius, position.y - radius);\n\tconst CVector2D vecSectorEndPos(position.x + radius, position.y + radius);\n\tconst int32 nStartX = Max(GetSectorIndexX(vecSectorStartPos.x), 0);\n\tconst int32 nStartY = Max(GetSectorIndexY(vecSectorStartPos.y), 0);\n#ifdef FIX_BUGS\n\tconst int32 nEndX = Min(GetSectorIndexX(vecSectorEndPos.x), NUMSECTORS_X - 1);\n\tconst int32 nEndY = Min(GetSectorIndexY(vecSectorEndPos.y), NUMSECTORS_Y - 1);\n#else\n\tconst int32 nEndX = Min(GetSectorIndexX(vecSectorEndPos.x), NUMSECTORS_X);\n\tconst int32 nEndY = Min(GetSectorIndexY(vecSectorEndPos.y), NUMSECTORS_Y);\n#endif\n\tfor(int32 y = nStartY; y <= nEndY; y++) {\n\t\tfor(int32 x = nStartX; x <= nEndX; x++) {\n\t\t\tCSector *pSector = GetSector(x, y);\n\t\t\tif(bBuildings) {\n\t\t\t\tFindObjectsKindaCollidingSectorList(\n\t\t\t\t    pSector->m_lists[ENTITYLIST_BUILDINGS], position, radius, bCheck2DOnly,\n\t\t\t\t    nCollidingEntities, maxEntitiesToFind, aEntities);\n\t\t\t\tFindObjectsKindaCollidingSectorList(\n\t\t\t\t    pSector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP], position, radius, bCheck2DOnly,\n\t\t\t\t    nCollidingEntities, maxEntitiesToFind, aEntities);\n\t\t\t}\n\t\t\tif(bVehicles) {\n\t\t\t\tFindObjectsKindaCollidingSectorList(\n\t\t\t\t    pSector->m_lists[ENTITYLIST_VEHICLES], position, radius, bCheck2DOnly,\n\t\t\t\t    nCollidingEntities, maxEntitiesToFind, aEntities);\n\t\t\t\tFindObjectsKindaCollidingSectorList(\n\t\t\t\t    pSector->m_lists[ENTITYLIST_VEHICLES_OVERLAP], position, radius, bCheck2DOnly,\n\t\t\t\t    nCollidingEntities, maxEntitiesToFind, aEntities);\n\t\t\t}\n\t\t\tif(bPeds) {\n\t\t\t\tFindObjectsKindaCollidingSectorList(pSector->m_lists[ENTITYLIST_PEDS], position,\n\t\t\t\t                                            radius, bCheck2DOnly, nCollidingEntities,\n\t\t\t\t                                            maxEntitiesToFind, aEntities);\n\t\t\t\tFindObjectsKindaCollidingSectorList(\n\t\t\t\t    pSector->m_lists[ENTITYLIST_PEDS_OVERLAP], position, radius, bCheck2DOnly,\n\t\t\t\t    nCollidingEntities, maxEntitiesToFind, aEntities);\n\t\t\t}\n\t\t\tif(bObjects) {\n\t\t\t\tFindObjectsKindaCollidingSectorList(\n\t\t\t\t    pSector->m_lists[ENTITYLIST_OBJECTS], position, radius, bCheck2DOnly,\n\t\t\t\t    nCollidingEntities, maxEntitiesToFind, aEntities);\n\t\t\t\tFindObjectsKindaCollidingSectorList(\n\t\t\t\t    pSector->m_lists[ENTITYLIST_OBJECTS_OVERLAP], position, radius, bCheck2DOnly,\n\t\t\t\t    nCollidingEntities, maxEntitiesToFind, aEntities);\n\t\t\t}\n\t\t\tif(bDummies) {\n\t\t\t\tFindObjectsKindaCollidingSectorList(\n\t\t\t\t    pSector->m_lists[ENTITYLIST_DUMMIES], position, radius, bCheck2DOnly,\n\t\t\t\t    nCollidingEntities, maxEntitiesToFind, aEntities);\n\t\t\t\tFindObjectsKindaCollidingSectorList(\n\t\t\t\t    pSector->m_lists[ENTITYLIST_DUMMIES_OVERLAP], position, radius, bCheck2DOnly,\n\t\t\t\t    nCollidingEntities, maxEntitiesToFind, aEntities);\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nCWorld::FindObjectsKindaCollidingSectorList(CPtrList &list, const CVector &position, float radius, bool bCheck2DOnly,\n                                            int16 *nCollidingEntities, int16 maxEntitiesToFind, CEntity **aEntities)\n{\n\tfor(CPtrNode *pNode = list.first; pNode; pNode = pNode->next) {\n\t\tCEntity *pEntity = (CEntity *)pNode->item;\n\t\tif(pEntity->m_scanCode != GetCurrentScanCode()) {\n\t\t\tpEntity->m_scanCode = GetCurrentScanCode();\n\t\t\tfloat fMagnitude = 0.0f;\n\t\t\tif(bCheck2DOnly)\n\t\t\t\tfMagnitude = (position - pEntity->GetPosition()).Magnitude2D();\n\t\t\telse\n\t\t\t\tfMagnitude = (position - pEntity->GetPosition()).Magnitude();\n\t\t\tif(pEntity->GetBoundRadius() + radius > fMagnitude && *nCollidingEntities < maxEntitiesToFind) {\n\t\t\t\tif(aEntities) aEntities[*nCollidingEntities] = pEntity;\n\t\t\t\t++*nCollidingEntities;\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nCWorld::FindObjectsIntersectingCube(const CVector &vecStartPos, const CVector &vecEndPos, int16 *nIntersecting,\n                                    int16 maxEntitiesToFind, CEntity **aEntities, bool bBuildings, bool bVehicles,\n                                    bool bPeds, bool bObjects, bool bDummies)\n{\n\tAdvanceCurrentScanCode();\n\t*nIntersecting = 0;\n\tconst int32 nStartX = Max(GetSectorIndexX(vecStartPos.x), 0);\n\tconst int32 nStartY = Max(GetSectorIndexY(vecStartPos.y), 0);\n#ifdef FIX_BUGS\n\tconst int32 nEndX = Min(GetSectorIndexX(vecStartPos.x), NUMSECTORS_X - 1);\n\tconst int32 nEndY = Min(GetSectorIndexY(vecStartPos.y), NUMSECTORS_Y - 1);\n#else\n\tconst int32 nEndX = Min(GetSectorIndexX(vecStartPos.x), NUMSECTORS_X);\n\tconst int32 nEndY = Min(GetSectorIndexY(vecStartPos.y), NUMSECTORS_Y);\n#endif\n\tfor(int32 y = nStartY; y <= nEndY; y++) {\n\t\tfor(int32 x = nStartX; x <= nEndX; x++) {\n\t\t\tCSector *pSector = GetSector(x, y);\n\t\t\tif(bBuildings) {\n\t\t\t\tFindObjectsIntersectingCubeSectorList(pSector->m_lists[ENTITYLIST_BUILDINGS],\n\t\t\t\t                                              vecStartPos, vecEndPos, nIntersecting,\n\t\t\t\t                                              maxEntitiesToFind, aEntities);\n\t\t\t\tFindObjectsIntersectingCubeSectorList(\n\t\t\t\t    pSector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP], vecStartPos, vecEndPos,\n\t\t\t\t    nIntersecting, maxEntitiesToFind, aEntities);\n\t\t\t}\n\t\t\tif(bVehicles) {\n\t\t\t\tFindObjectsIntersectingCubeSectorList(pSector->m_lists[ENTITYLIST_VEHICLES],\n\t\t\t\t                                              vecStartPos, vecEndPos, nIntersecting,\n\t\t\t\t                                              maxEntitiesToFind, aEntities);\n\t\t\t\tFindObjectsIntersectingCubeSectorList(\n\t\t\t\t    pSector->m_lists[ENTITYLIST_VEHICLES_OVERLAP], vecStartPos, vecEndPos,\n\t\t\t\t    nIntersecting, maxEntitiesToFind, aEntities);\n\t\t\t}\n\t\t\tif(bPeds) {\n\t\t\t\tFindObjectsIntersectingCubeSectorList(pSector->m_lists[ENTITYLIST_PEDS],\n\t\t\t\t                                              vecStartPos, vecEndPos, nIntersecting,\n\t\t\t\t                                              maxEntitiesToFind, aEntities);\n\t\t\t\tFindObjectsIntersectingCubeSectorList(pSector->m_lists[ENTITYLIST_PEDS_OVERLAP],\n\t\t\t\t                                              vecStartPos, vecEndPos, nIntersecting,\n\t\t\t\t                                              maxEntitiesToFind, aEntities);\n\t\t\t}\n\t\t\tif(bObjects) {\n\t\t\t\tFindObjectsIntersectingCubeSectorList(pSector->m_lists[ENTITYLIST_OBJECTS],\n\t\t\t\t                                              vecStartPos, vecEndPos, nIntersecting,\n\t\t\t\t                                              maxEntitiesToFind, aEntities);\n\t\t\t\tFindObjectsIntersectingCubeSectorList(\n\t\t\t\t    pSector->m_lists[ENTITYLIST_OBJECTS_OVERLAP], vecStartPos, vecEndPos, nIntersecting,\n\t\t\t\t    maxEntitiesToFind, aEntities);\n\t\t\t}\n\t\t\tif(bDummies) {\n\t\t\t\tFindObjectsIntersectingCubeSectorList(pSector->m_lists[ENTITYLIST_DUMMIES],\n\t\t\t\t                                              vecStartPos, vecEndPos, nIntersecting,\n\t\t\t\t                                              maxEntitiesToFind, aEntities);\n\t\t\t\tFindObjectsIntersectingCubeSectorList(\n\t\t\t\t    pSector->m_lists[ENTITYLIST_DUMMIES_OVERLAP], vecStartPos, vecEndPos, nIntersecting,\n\t\t\t\t    maxEntitiesToFind, aEntities);\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nCWorld::FindObjectsIntersectingCubeSectorList(CPtrList &list, const CVector &vecStartPos, const CVector &vecEndPos,\n                                              int16 *nIntersecting, int16 maxEntitiesToFind, CEntity **aEntities)\n{\n\tfor(CPtrNode *pNode = list.first; pNode; pNode = pNode->next) {\n\t\tCEntity *pEntity = (CEntity *)pNode->item;\n\t\tif(pEntity->m_scanCode != GetCurrentScanCode()) {\n\t\t\tpEntity->m_scanCode = GetCurrentScanCode();\n\t\t\tfloat fRadius = pEntity->GetBoundRadius();\n\t\t\tconst CVector &entityPos = pEntity->GetPosition();\n\t\t\tif(fRadius + entityPos.x >= vecStartPos.x && entityPos.x - fRadius <= vecEndPos.x &&\n\t\t\t   fRadius + entityPos.y >= vecStartPos.y && entityPos.y - fRadius <= vecEndPos.y &&\n\t\t\t   fRadius + entityPos.z >= vecStartPos.z && entityPos.z - fRadius <= vecEndPos.z &&\n\t\t\t   *nIntersecting < maxEntitiesToFind) {\n\t\t\t\tif(aEntities) aEntities[*nIntersecting] = pEntity;\n\t\t\t\t++*nIntersecting;\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nCWorld::FindObjectsIntersectingAngledCollisionBox(const CBox &boundingBox, const CMatrix &matrix,\n                                                  const CVector &position, float fStartX, float fStartY, float fEndX,\n                                                  float fEndY, int16 *nEntitiesFound, int16 maxEntitiesToFind,\n                                                  CEntity **aEntities, bool bBuildings, bool bVehicles, bool bPeds,\n                                                  bool bObjects, bool bDummies)\n{\n\tAdvanceCurrentScanCode();\n\t*nEntitiesFound = 0;\n\tconst int32 nStartX = Max(GetSectorIndexX(fStartX), 0);\n\tconst int32 nStartY = Max(GetSectorIndexY(fStartY), 0);\n#ifdef FIX_BUGS\n\tconst int32 nEndX = Min(GetSectorIndexX(fEndX), NUMSECTORS_X - 1);\n\tconst int32 nEndY = Min(GetSectorIndexY(fEndY), NUMSECTORS_Y - 1);\n#else\n\tconst int32 nEndX = Min(GetSectorIndexX(fEndX), NUMSECTORS_X);\n\tconst int32 nEndY = Min(GetSectorIndexY(fEndY), NUMSECTORS_Y);\n#endif\n\tfor(int32 y = nStartY; y <= nEndY; y++) {\n\t\tfor(int32 x = nStartX; x <= nEndX; x++) {\n\t\t\tCSector *pSector = GetSector(x, y);\n\t\t\tif(bBuildings) {\n\t\t\t\tFindObjectsIntersectingAngledCollisionBoxSectorList(\n\t\t\t\t    pSector->m_lists[ENTITYLIST_BUILDINGS], boundingBox, matrix, position,\n\t\t\t\t    nEntitiesFound, maxEntitiesToFind, aEntities);\n\t\t\t\tFindObjectsIntersectingAngledCollisionBoxSectorList(\n\t\t\t\t    pSector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP], boundingBox, matrix, position,\n\t\t\t\t    nEntitiesFound, maxEntitiesToFind, aEntities);\n\t\t\t}\n\t\t\tif(bVehicles) {\n\t\t\t\tFindObjectsIntersectingAngledCollisionBoxSectorList(\n\t\t\t\t    pSector->m_lists[ENTITYLIST_VEHICLES], boundingBox, matrix, position,\n\t\t\t\t    nEntitiesFound, maxEntitiesToFind, aEntities);\n\t\t\t\tFindObjectsIntersectingAngledCollisionBoxSectorList(\n\t\t\t\t    pSector->m_lists[ENTITYLIST_VEHICLES_OVERLAP], boundingBox, matrix, position,\n\t\t\t\t    nEntitiesFound, maxEntitiesToFind, aEntities);\n\t\t\t}\n\t\t\tif(bPeds) {\n\t\t\t\tFindObjectsIntersectingAngledCollisionBoxSectorList(\n\t\t\t\t    pSector->m_lists[ENTITYLIST_PEDS], boundingBox, matrix, position, nEntitiesFound,\n\t\t\t\t    maxEntitiesToFind, aEntities);\n\t\t\t\tFindObjectsIntersectingAngledCollisionBoxSectorList(\n\t\t\t\t    pSector->m_lists[ENTITYLIST_PEDS_OVERLAP], boundingBox, matrix, position,\n\t\t\t\t    nEntitiesFound, maxEntitiesToFind, aEntities);\n\t\t\t}\n\t\t\tif(bObjects) {\n\t\t\t\tFindObjectsIntersectingAngledCollisionBoxSectorList(\n\t\t\t\t    pSector->m_lists[ENTITYLIST_OBJECTS], boundingBox, matrix, position, nEntitiesFound,\n\t\t\t\t    maxEntitiesToFind, aEntities);\n\t\t\t\tFindObjectsIntersectingAngledCollisionBoxSectorList(\n\t\t\t\t    pSector->m_lists[ENTITYLIST_OBJECTS_OVERLAP], boundingBox, matrix, position,\n\t\t\t\t    nEntitiesFound, maxEntitiesToFind, aEntities);\n\t\t\t}\n\t\t\tif(bDummies) {\n\t\t\t\tFindObjectsIntersectingAngledCollisionBoxSectorList(\n\t\t\t\t    pSector->m_lists[ENTITYLIST_DUMMIES], boundingBox, matrix, position, nEntitiesFound,\n\t\t\t\t    maxEntitiesToFind, aEntities);\n\t\t\t\tFindObjectsIntersectingAngledCollisionBoxSectorList(\n\t\t\t\t    pSector->m_lists[ENTITYLIST_DUMMIES_OVERLAP], boundingBox, matrix, position,\n\t\t\t\t    nEntitiesFound, maxEntitiesToFind, aEntities);\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nCWorld::FindObjectsIntersectingAngledCollisionBoxSectorList(CPtrList &list, const CBox &boundingBox,\n                                                            const CMatrix &matrix, const CVector &position,\n                                                            int16 *nEntitiesFound, int16 maxEntitiesToFind,\n                                                            CEntity **aEntities)\n{\n\tfor(CPtrNode *pNode = list.first; pNode; pNode = pNode->next) {\n\t\tCEntity *pEntity = (CEntity *)pNode->item;\n\t\tif(pEntity->m_scanCode != GetCurrentScanCode()) {\n\t\t\tpEntity->m_scanCode = GetCurrentScanCode();\n\t\t\tCColSphere sphere;\n\t\t\tCVector vecDistance = pEntity->GetPosition() - position;\n\t\t\tsphere.radius = pEntity->GetBoundRadius();\n\t\t\tsphere.center = Multiply3x3(vecDistance, matrix);\n\t\t\tif(CCollision::TestSphereBox(sphere, boundingBox) && *nEntitiesFound < maxEntitiesToFind) {\n\t\t\t\tif(aEntities) aEntities[*nEntitiesFound] = pEntity;\n\t\t\t\t++*nEntitiesFound;\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nCWorld::FindMissionEntitiesIntersectingCube(const CVector &vecStartPos, const CVector &vecEndPos, int16 *nIntersecting,\n                                            int16 maxEntitiesToFind, CEntity **aEntities, bool bVehicles, bool bPeds,\n                                            bool bObjects)\n{\n\tAdvanceCurrentScanCode();\n\t*nIntersecting = 0;\n\tconst int32 nStartX = Max(GetSectorIndexX(vecStartPos.x), 0);\n\tconst int32 nStartY = Max(GetSectorIndexY(vecStartPos.y), 0);\n#ifdef FIX_BUGS\n\tconst int32 nEndX = Min(GetSectorIndexX(vecEndPos.x), NUMSECTORS_X - 1);\n\tconst int32 nEndY = Min(GetSectorIndexY(vecEndPos.y), NUMSECTORS_Y - 1);\n#else\n\tconst int32 nEndX = Min(GetSectorIndexX(vecEndPos.x), NUMSECTORS_X);\n\tconst int32 nEndY = Min(GetSectorIndexY(vecEndPos.y), NUMSECTORS_Y);\n#endif\n\tfor(int32 y = nStartY; y <= nEndY; y++) {\n\t\tfor(int32 x = nStartX; x <= nEndX; x++) {\n\t\t\tCSector *pSector = GetSector(x, y);\n\t\t\tif(bVehicles) {\n\t\t\t\tFindMissionEntitiesIntersectingCubeSectorList(\n\t\t\t\t    pSector->m_lists[ENTITYLIST_VEHICLES], vecStartPos, vecEndPos, nIntersecting,\n\t\t\t\t    maxEntitiesToFind, aEntities, true, false);\n\t\t\t\tFindMissionEntitiesIntersectingCubeSectorList(\n\t\t\t\t    pSector->m_lists[ENTITYLIST_VEHICLES_OVERLAP], vecStartPos, vecEndPos,\n\t\t\t\t    nIntersecting, maxEntitiesToFind, aEntities, true, false);\n\t\t\t}\n\t\t\tif(bPeds) {\n\t\t\t\tFindMissionEntitiesIntersectingCubeSectorList(\n\t\t\t\t    pSector->m_lists[ENTITYLIST_PEDS], vecStartPos, vecEndPos, nIntersecting,\n\t\t\t\t    maxEntitiesToFind, aEntities, false, true);\n\t\t\t\tFindMissionEntitiesIntersectingCubeSectorList(\n\t\t\t\t    pSector->m_lists[ENTITYLIST_PEDS_OVERLAP], vecStartPos, vecEndPos, nIntersecting,\n\t\t\t\t    maxEntitiesToFind, aEntities, false, true);\n\t\t\t}\n\t\t\tif(bObjects) {\n\t\t\t\tFindMissionEntitiesIntersectingCubeSectorList(\n\t\t\t\t    pSector->m_lists[ENTITYLIST_OBJECTS], vecStartPos, vecEndPos, nIntersecting,\n\t\t\t\t    maxEntitiesToFind, aEntities, false, false);\n\t\t\t\tFindMissionEntitiesIntersectingCubeSectorList(\n\t\t\t\t    pSector->m_lists[ENTITYLIST_OBJECTS_OVERLAP], vecStartPos, vecEndPos, nIntersecting,\n\t\t\t\t    maxEntitiesToFind, aEntities, false, false);\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nCWorld::FindMissionEntitiesIntersectingCubeSectorList(CPtrList &list, const CVector &vecStartPos,\n                                                      const CVector &vecEndPos, int16 *nIntersecting,\n                                                      int16 maxEntitiesToFind, CEntity **aEntities, bool bIsVehicleList,\n                                                      bool bIsPedList)\n{\n\tfor(CPtrNode *pNode = list.first; pNode; pNode = pNode->next) {\n\t\tCEntity *pEntity = (CEntity *)pNode->item;\n\t\tif(pEntity->m_scanCode != GetCurrentScanCode()) {\n\t\t\tpEntity->m_scanCode = GetCurrentScanCode();\n\t\t\tbool bIsMissionEntity = false;\n\t\t\tif(bIsVehicleList)\n\t\t\t\tbIsMissionEntity = ((CVehicle *)pEntity)->VehicleCreatedBy == MISSION_VEHICLE;\n\t\t\telse if(bIsPedList)\n\t\t\t\tbIsMissionEntity = ((CPed *)pEntity)->CharCreatedBy == MISSION_CHAR;\n\t\t\telse\n\t\t\t\tbIsMissionEntity = ((CObject *)pEntity)->ObjectCreatedBy == MISSION_OBJECT;\n\t\t\tfloat fRadius = pEntity->GetBoundRadius();\n\t\t\tconst CVector &entityPos = pEntity->GetPosition();\n\t\t\tif(bIsMissionEntity && fRadius + entityPos.x >= vecStartPos.x &&\n\t\t\t   entityPos.x - fRadius <= vecEndPos.x && fRadius + entityPos.y >= vecStartPos.y &&\n\t\t\t   entityPos.y - fRadius <= vecEndPos.y && fRadius + entityPos.z >= vecStartPos.z &&\n\t\t\t   entityPos.z - fRadius <= vecEndPos.z && *nIntersecting < maxEntitiesToFind) {\n\t\t\t\tif(aEntities) aEntities[*nIntersecting] = pEntity;\n\t\t\t\t++*nIntersecting;\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nCWorld::ClearCarsFromArea(float x1, float y1, float z1, float x2, float y2, float z2)\n{\n\tCVehiclePool *pVehiclePool = CPools::GetVehiclePool();\n\tfor(int32 i = 0; i < pVehiclePool->GetSize(); i++) {\n\t\tCVehicle *pVehicle = CPools::GetVehiclePool()->GetSlot(i);\n\t\tif(pVehicle) {\n\t\t\tconst CVector &position = pVehicle->GetPosition();\n\t\t\tif(position.x >= x1 && position.x <= x2 && position.y >= y1 && position.y <= y2 &&\n\t\t\t   position.z >= z1 && position.z <= z2 && !pVehicle->bIsLocked && pVehicle->CanBeDeleted()) {\n\t\t\t\tif(pVehicle->pDriver) {\n\t\t\t\t\tCPopulation::RemovePed(pVehicle->pDriver);\n\t\t\t\t\tpVehicle->pDriver = nil;\n\t\t\t\t}\n\t\t\t\tfor(int32 j = 0; j < pVehicle->m_nNumMaxPassengers; ++j) {\n\t\t\t\t\tif(pVehicle->pPassengers[j]) {\n\t\t\t\t\t\tCPopulation::RemovePed(pVehicle->pPassengers[j]);\n\t\t\t\t\t\tpVehicle->pPassengers[j] = nil;\n\t\t\t\t\t\t--pVehicle->m_nNumPassengers;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tCCarCtrl::RemoveFromInterestingVehicleList(pVehicle);\n\t\t\t\tRemove(pVehicle);\n\t\t\t\tdelete pVehicle;\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nCWorld::ClearPedsFromArea(float x1, float y1, float z1, float x2, float y2, float z2)\n{\n\tCPedPool *pPedPool = CPools::GetPedPool();\n\tfor(int32 i = 0; i < pPedPool->GetSize(); i++) {\n\t\tCPed *pPed = CPools::GetPedPool()->GetSlot(i);\n\t\tif(pPed) {\n\t\t\tconst CVector &position = pPed->GetPosition();\n\t\t\tif(!pPed->IsPlayer() && pPed->CanBeDeleted() && position.x >= x1 && position.x <= x2 &&\n\t\t\t   position.y >= y1 && position.y <= y2 && position.z >= z1 && position.z <= z2) {\n\t\t\t\tCPopulation::RemovePed(pPed);\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nCWorld::CallOffChaseForArea(float x1, float y1, float x2, float y2)\n{\n\tAdvanceCurrentScanCode();\n\tfloat fStartX = x1 - 10.0f;\n\tfloat fStartY = y1 - 10.0f;\n\tfloat fEndX = x2 + 10.0f;\n\tfloat fEndY = y2 + 10.0f;\n\tconst int32 nStartX = Max(GetSectorIndexX(fStartX), 0);\n\tconst int32 nStartY = Max(GetSectorIndexY(fStartY), 0);\n#ifdef FIX_BUGS\n\tconst int32 nEndX = Min(GetSectorIndexX(fEndX), NUMSECTORS_X - 1);\n\tconst int32 nEndY = Min(GetSectorIndexY(fEndY), NUMSECTORS_Y - 1);\n#else\n\tconst int32 nEndX = Min(GetSectorIndexX(fEndX), NUMSECTORS_X);\n\tconst int32 nEndY = Min(GetSectorIndexY(fEndY), NUMSECTORS_Y);\n#endif\n\tfor(int32 y = nStartY; y <= nEndY; y++) {\n\t\tfor(int32 x = nStartX; x <= nEndX; x++) {\n\t\t\tCSector *pSector = GetSector(x, y);\n\t\t\tCallOffChaseForAreaSectorListVehicles(pSector->m_lists[ENTITYLIST_VEHICLES], x1, y1, x2,\n\t\t\t                                              y2, fStartX, fStartY, fEndX, fEndY);\n\t\t\tCallOffChaseForAreaSectorListVehicles(pSector->m_lists[ENTITYLIST_VEHICLES_OVERLAP], x1,\n\t\t\t                                              y1, x2, y2, fStartX, fStartY, fEndX, fEndY);\n\t\t\tCallOffChaseForAreaSectorListPeds(pSector->m_lists[ENTITYLIST_PEDS], x1, y1, x2, y2);\n\t\t\tCallOffChaseForAreaSectorListPeds(pSector->m_lists[ENTITYLIST_PEDS_OVERLAP], x1, y1, x2,\n\t\t\t                                          y2);\n\t\t}\n\t}\n}\n\nvoid\nCWorld::CallOffChaseForAreaSectorListVehicles(CPtrList &list, float x1, float y1, float x2, float y2, float fStartX,\n                                              float fStartY, float fEndX, float fEndY)\n{\n\tfor(CPtrNode *pNode = list.first; pNode; pNode = pNode->next) {\n\t\tCVehicle *pVehicle = (CVehicle *)pNode->item;\n\t\tif(pVehicle->m_scanCode != GetCurrentScanCode()) {\n\t\t\tpVehicle->m_scanCode = GetCurrentScanCode();\n\t\t\tconst CVector &vehiclePos = pVehicle->GetPosition();\n\t\t\tuint8 carMission = pVehicle->AutoPilot.m_nCarMission;\n\t\t\tif(pVehicle != FindPlayerVehicle() && vehiclePos.x > fStartX && vehiclePos.x < fEndX &&\n\t\t\t   vehiclePos.y > fStartY && vehiclePos.y < fEndY && pVehicle->bIsLawEnforcer &&\n\t\t\t   (carMission == MISSION_RAMPLAYER_FARAWAY || carMission == MISSION_RAMPLAYER_CLOSE ||\n\t\t\t    carMission == MISSION_BLOCKPLAYER_FARAWAY || carMission == MISSION_BLOCKPLAYER_CLOSE)) {\n\t\t\t\tpVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 2000;\n\t\t\t\tCColModel *pColModel = pVehicle->GetColModel();\n\t\t\t\tbool bInsideSphere = false;\n\t\t\t\tfor(int32 i = 0; i < pColModel->numSpheres; i++) {\n\t\t\t\t\tCVector pos = pVehicle->m_matrix * pColModel->spheres[i].center;\n\t\t\t\t\tfloat fRadius = pColModel->spheres[i].radius;\n\t\t\t\t\tif(pos.x + fRadius > x1 && pos.x - fRadius < x2 && pos.y + fRadius > y1 &&\n\t\t\t\t\t   pos.y - fRadius < y2)\n\t\t\t\t\t\tbInsideSphere = true;\n\t\t\t\t\t// Maybe break the loop when bInsideSphere is set to true?\n\t\t\t\t}\n\t\t\t\tif(bInsideSphere) {\n\t\t\t\t\tif(pVehicle->GetPosition().x <= (x1 + x2) * 0.5f)\n\t\t\t\t\t\tpVehicle->m_vecMoveSpeed.x = Min(pVehicle->m_vecMoveSpeed.x, 0.0f);\n\t\t\t\t\telse\n\t\t\t\t\t\tpVehicle->m_vecMoveSpeed.x = Max(pVehicle->m_vecMoveSpeed.x, 0.0f);\n\t\t\t\t\tif(pVehicle->GetPosition().y <= (y1 + y2) * 0.5f)\n\t\t\t\t\t\tpVehicle->m_vecMoveSpeed.y = Min(pVehicle->m_vecMoveSpeed.y, 0.0f);\n\t\t\t\t\telse\n\t\t\t\t\t\tpVehicle->m_vecMoveSpeed.y = Max(pVehicle->m_vecMoveSpeed.y, 0.0f);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nCWorld::CallOffChaseForAreaSectorListPeds(CPtrList &list, float x1, float y1, float x2, float y2)\n{\n\tfor(CPtrNode *pNode = list.first; pNode; pNode = pNode->next) {\n\t\tCPed *pPed = (CPed *)pNode->item;\n\t\tconst CVector &pedPos = pPed->GetPosition();\n\t\tif(pPed->m_scanCode != GetCurrentScanCode()) {\n\t\t\tpPed->m_scanCode = GetCurrentScanCode();\n\t\t\tif(pPed != FindPlayerPed() && pPed->m_leader != FindPlayerPed() && pedPos.x > x1 &&\n\t\t\t   pedPos.x < x2 && pedPos.y > y1 && pedPos.y < y2 &&\n\t\t\t   (pPed->m_pedInObjective == FindPlayerPed() ||\n\t\t\t    pPed->m_carInObjective && pPed->m_carInObjective == FindPlayerVehicle()) &&\n\t\t\t   pPed->m_nPedState != PED_DEAD && pPed->m_nPedState != PED_DIE &&\n\t\t\t   (pPed->m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT ||\n\t\t\t    pPed->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER ||\n\t\t\t    pPed->m_objective == OBJECTIVE_KILL_CHAR_ANY_MEANS)) {\n\t\t\t\tif(pPed->IsPedInControl()) {\n\t\t\t\t\tif(pPed->m_nPedType == PEDTYPE_COP)\n\t\t\t\t\t\t((CCopPed *)pPed)->ClearPursuit();\n\t\t\t\t\telse\n\t\t\t\t\t\tpPed->SetIdle();\n\t\t\t\t\tpPed->SetObjective(OBJECTIVE_NONE);\n\t\t\t\t} else {\n\t\t\t\t\tpPed->m_prevObjective = OBJECTIVE_NONE;\n\t\t\t\t\tpPed->m_nLastPedState = PED_IDLE;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nCWorld::RemoveEntityInsteadOfProcessingIt(CEntity *ent)\n{\n\tif(ent->IsPed()) {\n\t\tif(FindPlayerPed() == ent)\n\t\t\tRemove(ent);\n\t\telse\n\t\t\tCPopulation::RemovePed((CPed *)ent);\n\t} else {\n\t\tRemove(ent);\n\t\tdelete ent;\n\t}\n}\n\nvoid\nCWorld::RemoveFallenPeds(void)\n{\n\tint poolSize = CPools::GetPedPool()->GetSize();\n\tfor(int poolIndex = poolSize - 1; poolIndex >= 0; poolIndex--) {\n\t\tCPed *ped = CPools::GetPedPool()->GetSlot(poolIndex);\n\t\tif(ped) {\n\t\t\tif(ped->GetPosition().z < MAP_Z_LOW_LIMIT) {\n\t\t\t\tif(ped->CharCreatedBy != RANDOM_CHAR || ped->IsPlayer()) {\n\t\t\t\t\tint closestNode = ThePaths.FindNodeClosestToCoors(ped->GetPosition(), PATH_PED,\n\t\t\t\t\t                                                  999999.9f, false, false);\n\t\t\t\t\tCVector newPos = ThePaths.m_pathNodes[closestNode].GetPosition();\n\t\t\t\t\tnewPos.z += 2.0f;\n\t\t\t\t\tped->Teleport(newPos);\n\t\t\t\t\tped->m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);\n\t\t\t\t} else {\n\t\t\t\t\tCPopulation::RemovePed(ped);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nCWorld::RemoveFallenCars(void)\n{\n\tint poolSize = CPools::GetVehiclePool()->GetSize();\n\tfor(int poolIndex = poolSize - 1; poolIndex >= 0; poolIndex--) {\n\t\tCVehicle *veh = CPools::GetVehiclePool()->GetSlot(poolIndex);\n\t\tif(veh) {\n\t\t\tif(veh->GetPosition().z < MAP_Z_LOW_LIMIT) {\n\t\t\t\tif(veh->VehicleCreatedBy == MISSION_VEHICLE && !veh->bRenderScorched || veh == FindPlayerVehicle() ||\n\t\t\t\t   (veh->pDriver && veh->pDriver->IsPlayer())) {\n\t\t\t\t\tint closestNode = ThePaths.FindNodeClosestToCoors(veh->GetPosition(), PATH_CAR,\n\t\t\t\t\t                                                  999999.9f, false, false);\n\t\t\t\t\tCVector newPos = ThePaths.m_pathNodes[closestNode].GetPosition();\n\t\t\t\t\tnewPos.z += 3.0f;\n\t\t\t\t\tveh->Teleport(newPos);\n\t\t\t\t\tveh->m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);\n\t\t\t\t} else if(veh->VehicleCreatedBy == RANDOM_VEHICLE ||\n\t\t\t\t          veh->VehicleCreatedBy == PARKED_VEHICLE) {\n\t\t\t\t\tRemove(veh);\n\t\t\t\t\tdelete veh;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nCWorld::StopAllLawEnforcersInTheirTracks(void)\n{\n\tint poolSize = CPools::GetVehiclePool()->GetSize();\n\tfor(int poolIndex = poolSize - 1; poolIndex >= 0; poolIndex--) {\n\t\tCVehicle *veh = CPools::GetVehiclePool()->GetSlot(poolIndex);\n\t\tif(veh) {\n\t\t\tif(veh->bIsLawEnforcer) veh->SetMoveSpeed(0.0f, 0.0f, 0.0f);\n\t\t}\n\t}\n}\n\nvoid\nCWorld::SetAllCarsCanBeDamaged(bool toggle)\n{\n\tint poolSize = CPools::GetVehiclePool()->GetSize();\n\tfor(int poolIndex = 0; poolIndex < poolSize; poolIndex++) {\n\t\tCVehicle *veh = CPools::GetVehiclePool()->GetSlot(poolIndex);\n\t\tif(veh) veh->bCanBeDamaged = toggle;\n\t}\n}\n\nvoid\nCWorld::ExtinguishAllCarFiresInArea(CVector point, float range)\n{\n\tint poolSize = CPools::GetVehiclePool()->GetSize();\n\tfor(int poolIndex = 0; poolIndex < poolSize; poolIndex++) {\n\t\tCVehicle *veh = CPools::GetVehiclePool()->GetSlot(poolIndex);\n\t\tif(veh) {\n\t\t\tif((point - veh->GetPosition()).MagnitudeSqr() < sq(range)) veh->ExtinguishCarFire();\n\t\t}\n\t}\n}\n\ninline void\nAddSteamsFromGround(CPtrList& list)\n{\n\tCPtrNode* pNode = list.first;\n\twhile (pNode) {\n\t\t((CEntity*)pNode->item)->AddSteamsFromGround(nil);\n\t\tpNode = pNode->next;\n\t}\n}\n\nvoid\nCWorld::AddParticles(void)\n{\n\tfor(int32 y = 0; y < NUMSECTORS_Y; y++) {\n\t\tfor(int32 x = 0; x < NUMSECTORS_X; x++) {\n\t\t\tCSector *pSector = GetSector(x, y);\n\t\t\tAddSteamsFromGround(pSector->m_lists[ENTITYLIST_BUILDINGS]);\n\t\t\tAddSteamsFromGround(pSector->m_lists[ENTITYLIST_DUMMIES]);\n\t\t}\n\t}\n}\n\nvoid\nCWorld::ShutDown(void)\n{\n\tfor(int i = 0; i < NUMSECTORS_X * NUMSECTORS_Y; i++) {\n\t\tCSector *pSector = GetSector(i % NUMSECTORS_X, i / NUMSECTORS_Y);\n\t\tfor(CPtrNode *pNode = pSector->m_lists[ENTITYLIST_BUILDINGS].first; pNode; pNode = pNode->next) {\n\t\t\tCEntity *pEntity = (CEntity *)pNode->item;\n\t\t\tRemove(pEntity);\n\t\t\tdelete pEntity;\n\t\t}\n\t\tfor(CPtrNode *pNode = pSector->m_lists[ENTITYLIST_VEHICLES].first; pNode; pNode = pNode->next) {\n\t\t\tCEntity *pEntity = (CEntity *)pNode->item;\n\t\t\tRemove(pEntity);\n\t\t\tdelete pEntity;\n\t\t}\n\t\tfor(CPtrNode *pNode = pSector->m_lists[ENTITYLIST_PEDS].first; pNode; pNode = pNode->next) {\n\t\t\tCEntity *pEntity = (CEntity *)pNode->item;\n\t\t\tRemove(pEntity);\n\t\t\tdelete pEntity;\n\t\t}\n\t\tfor(CPtrNode *pNode = pSector->m_lists[ENTITYLIST_OBJECTS].first; pNode; pNode = pNode->next) {\n\t\t\tCEntity *pEntity = (CEntity *)pNode->item;\n\t\t\tRemove(pEntity);\n\t\t\tdelete pEntity;\n\t\t}\n\t\tfor(CPtrNode *pNode = pSector->m_lists[ENTITYLIST_DUMMIES].first; pNode; pNode = pNode->next) {\n\t\t\tCEntity *pEntity = (CEntity *)pNode->item;\n\t\t\tRemove(pEntity);\n\t\t\tdelete pEntity;\n\t\t}\n#ifndef FIX_BUGS\n\t\tpSector->m_lists[ENTITYLIST_BUILDINGS].Flush();\n\t\tpSector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP].Flush();\n\t\tpSector->m_lists[ENTITYLIST_DUMMIES].Flush();\n\t\tpSector->m_lists[ENTITYLIST_DUMMIES_OVERLAP].Flush();\n#endif\n\t}\n\tfor(int32 i = 0; i < NUM_LEVELS; i++) {\n\t\tfor(CPtrNode *pNode = ms_bigBuildingsList[i].first; pNode; pNode = pNode->next) {\n\t\t\tCEntity *pEntity = (CEntity *)pNode->item;\n\t\t\t// Maybe remove from world here?\n\t\t\tdelete pEntity;\n\t\t}\n\t\tms_bigBuildingsList[i].Flush();\n\t}\n\tfor(int i = 0; i < NUMSECTORS_X * NUMSECTORS_Y; i++) {\n\t\tCSector *pSector = GetSector(i % NUMSECTORS_X, i / NUMSECTORS_Y);\n#ifdef FIX_BUGS\n\t\tpSector->m_lists[ENTITYLIST_BUILDINGS].Flush();\n\t\tpSector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP].Flush();\n\t\tpSector->m_lists[ENTITYLIST_DUMMIES].Flush();\n\t\tpSector->m_lists[ENTITYLIST_DUMMIES_OVERLAP].Flush();\n#endif\n\t\tif(pSector->m_lists[ENTITYLIST_BUILDINGS].first) {\n\t\t\tsprintf(gString, \"Building list %d,%d not empty\\n\", i % NUMSECTORS_X, i / NUMSECTORS_Y);\n\t\t\tpSector->m_lists[ENTITYLIST_BUILDINGS].Flush();\n\t\t}\n\t\tif(pSector->m_lists[ENTITYLIST_DUMMIES].first) {\n\t\t\tsprintf(gString, \"Dummy list %d,%d not empty\\n\", i % NUMSECTORS_X, i / NUMSECTORS_Y);\n\t\t\tpSector->m_lists[ENTITYLIST_DUMMIES].Flush();\n\t\t}\n\t\tif(pSector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP].first) {\n\t\t\tsprintf(gString, \"Building overlap list %d,%d not empty\\n\", i % NUMSECTORS_X, i / NUMSECTORS_Y);\n\t\t\tpSector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP].Flush();\n\t\t}\n\t\tif(pSector->m_lists[ENTITYLIST_VEHICLES_OVERLAP].first) {\n\t\t\tsprintf(gString, \"Vehicle overlap list %d,%d not empty\\n\", i % NUMSECTORS_X, i / NUMSECTORS_Y);\n\t\t\tpSector->m_lists[ENTITYLIST_VEHICLES_OVERLAP].Flush();\n\t\t}\n\t\tif(pSector->m_lists[ENTITYLIST_PEDS_OVERLAP].first) {\n\t\t\tsprintf(gString, \"Ped overlap list %d,%d not empty\\n\", i % NUMSECTORS_X, i / NUMSECTORS_Y);\n\t\t\tpSector->m_lists[ENTITYLIST_PEDS_OVERLAP].Flush();\n\t\t}\n\t\tif(pSector->m_lists[ENTITYLIST_OBJECTS_OVERLAP].first) {\n\t\t\tsprintf(gString, \"Object overlap list %d,%d not empty\\n\", i % NUMSECTORS_X, i / NUMSECTORS_Y);\n\t\t\tpSector->m_lists[ENTITYLIST_OBJECTS_OVERLAP].Flush();\n\t\t}\n\t\tif(pSector->m_lists[ENTITYLIST_DUMMIES_OVERLAP].first) {\n\t\t\tsprintf(gString, \"Dummy overlap list %d,%d not empty\\n\", i % NUMSECTORS_X, i / NUMSECTORS_Y);\n\t\t\tpSector->m_lists[ENTITYLIST_DUMMIES_OVERLAP].Flush();\n\t\t}\n\t}\n\tms_listMovingEntityPtrs.Flush();\n}\n\nvoid\nCWorld::ClearForRestart(void)\n{\n\tif(CCutsceneMgr::HasLoaded()) CCutsceneMgr::DeleteCutsceneData();\n\tCProjectileInfo::RemoveAllProjectiles();\n\tCObject::DeleteAllTempObjects();\n\tCObject::DeleteAllMissionObjects();\n\tCPopulation::ConvertAllObjectsToDummyObjects();\n\tfor(int i = 0; i < NUMSECTORS_X * NUMSECTORS_Y; i++) {\n\t\tCSector *pSector = GetSector(i % NUMSECTORS_X, i / NUMSECTORS_Y);\n\t\tfor(CPtrNode *pNode = pSector->m_lists[ENTITYLIST_PEDS].first; pNode; pNode = pNode->next) {\n\t\t\tCEntity *pEntity = (CEntity *)pNode->item;\n\t\t\tRemove(pEntity);\n\t\t\tdelete pEntity;\n\t\t}\n\t\tfor(CPtrNode *pNode = GetBigBuildingList(LEVEL_GENERIC).first; pNode; pNode = pNode->next) {\n\t\t\tCVehicle *pVehicle = (CVehicle *)pNode->item;\n\t\t\tif(pVehicle && pVehicle->IsVehicle() && pVehicle->IsPlane()) {\n\t\t\t\tRemove(pVehicle);\n\t\t\t\tdelete pVehicle;\n\t\t\t}\n\t\t}\n\t\tfor(CPtrNode *pNode = pSector->m_lists[ENTITYLIST_VEHICLES].first; pNode; pNode = pNode->next) {\n\t\t\tCEntity *pEntity = (CEntity *)pNode->item;\n\t\t\tRemove(pEntity);\n\t\t\tdelete pEntity;\n\t\t}\n\t}\n\tCPools::CheckPoolsEmpty();\n}\n\nvoid\nCWorld::RepositionCertainDynamicObjects()\n{\n\tint32 i = CPools::GetDummyPool()->GetSize();\n\twhile(--i >= 0) {\n\t\tCDummy *dummy = CPools::GetDummyPool()->GetSlot(i);\n\t\tif(dummy) { RepositionOneObject(dummy); }\n\t}\n}\n\nvoid\nCWorld::RepositionOneObject(CEntity *pEntity)\n{\n\tint16 modelId = pEntity->GetModelIndex();\n\tif (modelId == MI_PARKINGMETER || modelId == MI_PHONEBOOTH1 || modelId == MI_WASTEBIN ||\n\t\tmodelId == MI_BIN || modelId == MI_POSTBOX1 || modelId == MI_NEWSSTAND || modelId == MI_TRAFFICCONE ||\n\t\tmodelId == MI_DUMP1 || modelId == MI_ROADWORKBARRIER1 || modelId == MI_BUSSIGN1 || modelId == MI_NOPARKINGSIGN1 ||\n\t\tmodelId == MI_PHONESIGN || modelId == MI_FIRE_HYDRANT || modelId == MI_BOLLARDLIGHT ||\n\t\tmodelId == MI_PARKTABLE || modelId == MI_PARKINGMETER2 || modelId == MI_TELPOLE02 ||\n\t\tmodelId == MI_PARKBENCH || modelId == MI_BARRIER1 || IsTreeModel(modelId)\n\t\t) {\n\t\tCVector& position = pEntity->GetMatrix().GetPosition();\n\t\tCColModel* pColModel = pEntity->GetColModel();\n\t\tfloat fBoundingBoxMinZ = pColModel->boundingBox.min.z;\n\t\tfloat fHeight = pColModel->boundingBox.max.z - pColModel->boundingBox.min.z;\n\t\tif (fHeight < OBJECT_REPOSITION_OFFSET_Z) fHeight = OBJECT_REPOSITION_OFFSET_Z;\n\t\tposition.z = FindGroundZFor3DCoord(position.x, position.y,\n\t\t\tposition.z + fHeight, nil) -\n\t\t\tfBoundingBoxMinZ;\n\t\tpEntity->m_matrix.UpdateRW();\n\t\tpEntity->UpdateRwFrame();\n\t} else if(IsLightThatNeedsRepositioning(modelId)) {\n\t\tCVector position = pEntity->GetMatrix().GetPosition();\n\t\tCColModel* pColModel = pEntity->GetColModel();\n\t\tfloat fBoundingBoxMinZ = pColModel->boundingBox.min.z;\n\t\tfloat fHeight = pColModel->boundingBox.max.z - pColModel->boundingBox.min.z;\n\t\tif (fHeight < OBJECT_REPOSITION_OFFSET_Z) fHeight = OBJECT_REPOSITION_OFFSET_Z;\n\t\tif (pColModel->numBoxes == 1)\n\t\t\tposition = pEntity->GetMatrix() * CVector(\n\t\t\t\t(pColModel->boxes[0].min.x + pColModel->boxes[0].max.x) / 2,\n\t\t\t\t(pColModel->boxes[0].min.y + pColModel->boxes[0].max.y) / 2,\n\t\t\t\tpColModel->boxes[0].min.z);\n\t\telse if (pColModel->numSpheres > 0) {\n\t\t\tposition.z = 1000.0f;\n\t\t\tfor (int i = 0; i < pColModel->numSpheres; i++) {\n\t\t\t\tif (pColModel->spheres[i].center.z < position.z)\n\t\t\t\t\tposition = pColModel->spheres[i].center;\n\t\t\t}\n\t\t\tif (position.z < 1000.0f)\n\t\t\t\tposition = pEntity->GetMatrix() * position;\n\t\t}\n\t\tpEntity->GetMatrix().GetPosition().z = FindGroundZFor3DCoord(position.x, position.y, pEntity->GetMatrix().GetPosition().z + fHeight, nil) - fBoundingBoxMinZ;\n\t\tpEntity->GetMatrix().UpdateRW();\n\t\tpEntity->UpdateRwFrame();\n\t\t\n\t}\n\tif(modelId == MI_BUOY) {\n\t\tbool bFound = true;\n\t\tconst CVector &position = pEntity->GetPosition();\n\t\tfloat fGroundZ = FindGroundZFor3DCoord(position.x, position.y,\n\t\t                                               position.z + OBJECT_REPOSITION_OFFSET_Z, &bFound);\n\t\tCColModel *pColModel = pEntity->GetColModel();\n\t\tfloat fHeight = pColModel->boundingBox.max.z - pColModel->boundingBox.min.z;\n\t\tpEntity->GetMatrix().GetPosition().z = 0.2f * fHeight + 6.0f - 0.5f * fHeight;\n\t}\n}\n\nvoid\nCWorld::SetCarsOnFire(float x, float y, float z, float radius, CEntity *reason)\n{\n\tint poolSize = CPools::GetVehiclePool()->GetSize();\n\tfor(int poolIndex = poolSize - 1; poolIndex >= 0; poolIndex--) {\n\t\tCVehicle *veh = CPools::GetVehiclePool()->GetSlot(poolIndex);\n\t\tif(veh && veh->GetStatus() != STATUS_WRECKED && !veh->m_pCarFire && !veh->bFireProof) {\n\t\t\tif(Abs(veh->GetPosition().z - z) < 5.0f && Abs(veh->GetPosition().x - x) < radius &&\n\t\t\t   Abs(veh->GetPosition().y - y) < radius)\n\t\t\t\tgFireManager.StartFire(veh, reason, 0.8f, true);\n\t\t}\n\t}\n}\n\nvoid\nCWorld::SetPedsChoking(float x, float y, float z, float radius, CEntity* reason)\n{\n\tint32 poolSize = CPools::GetPedPool()->GetSize();\n\tfor (int32 i = poolSize - 1; i >= 0; i--) {\n\t\tCPed* pPed = CPools::GetPedPool()->GetSlot(i);\n\t\t// suspicious copypaste\n\t\tif (pPed && pPed->m_nPedState != PED_DEAD && !pPed->bInVehicle && !pPed->m_pFire && !pPed->bFireProof && pPed->CharCreatedBy != MISSION_CHAR) {\n\t\t\tif (Abs(pPed->GetPosition().z - z) < 5.0f && Abs(pPed->GetPosition().x - x) < radius &&\n\t\t\t\tAbs(pPed->GetPosition().y - y) < radius) {\n\t\t\t\tif (!pPed->IsPlayer())\n\t\t\t\t\tpPed->SetFlee(CVector2D(x, y), 10000);\n#ifdef FIX_BUGS\n\t\t\t\tpPed->InflictDamage(reason, WEAPONTYPE_TEARGAS, 1.0f, PEDPIECE_TORSO, 0);\n#else\n\t\t\t\tpPed->InflictDamage(nil, WEAPONTYPE_TEARGAS, 1.0f, PEDPIECE_TORSO, 0);\n#endif\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nCWorld::SetPedsOnFire(float x, float y, float z, float radius, CEntity *reason)\n{\n\tint32 poolSize = CPools::GetPedPool()->GetSize();\n\tfor(int32 i = poolSize - 1; i >= 0; i--) {\n\t\tCPed *pPed = CPools::GetPedPool()->GetSlot(i);\n\t\tif(pPed && pPed->m_nPedState != PED_DEAD && !pPed->bInVehicle && !pPed->m_pFire && !pPed->bFireProof) {\n\t\t\tif(Abs(pPed->GetPosition().z - z) < 5.0f && Abs(pPed->GetPosition().x - x) < radius &&\n\t\t\t   Abs(pPed->GetPosition().y - y) < radius)\n\t\t\t\tgFireManager.StartFire(pPed, reason, 0.8f, true);\n\t\t}\n\t}\n}\n\nvoid\nCWorld::RemoveStaticObjects()\n{\n\tfor(int i = 0; i < NUMSECTORS_X * NUMSECTORS_Y; i++) {\n\t\tCSector *pSector = GetSector(i % NUMSECTORS_X, i / NUMSECTORS_Y);\n\t\tfor(CPtrNode *pNode = pSector->m_lists[ENTITYLIST_BUILDINGS].first; pNode; pNode = pNode->next) {\n\t\t\tCEntity *pEntity = (CEntity *)pNode->item;\n\t\t\tRemove(pEntity);\n\t\t\tdelete pEntity;\n\t\t}\n\t\tfor(CPtrNode *pNode = pSector->m_lists[ENTITYLIST_OBJECTS].first; pNode; pNode = pNode->next) {\n\t\t\tCEntity *pEntity = (CEntity *)pNode->item;\n\t\t\tRemove(pEntity);\n\t\t\tdelete pEntity;\n\t\t}\n\t\tfor(CPtrNode *pNode = pSector->m_lists[ENTITYLIST_DUMMIES].first; pNode; pNode = pNode->next) {\n\t\t\tCEntity *pEntity = (CEntity *)pNode->item;\n\t\t\tRemove(pEntity);\n\t\t\tdelete pEntity;\n\t\t}\n\t\tpSector->m_lists[ENTITYLIST_BUILDINGS].Flush();\n\t\tpSector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP].Flush();\n\t\tpSector->m_lists[ENTITYLIST_DUMMIES].Flush();\n\t\tpSector->m_lists[ENTITYLIST_DUMMIES_OVERLAP].Flush();\n\t}\n}\n\nvoid\nCWorld::Process(void)\n{\n\tif(!(CTimer::GetFrameCounter() & 63)) CReferences::PruneAllReferencesInWorld();\n\n\tif(bProcessCutsceneOnly) {\n\t\tfor(int i = 0; i < NUMCUTSCENEOBJECTS; i++) {\n\t\t\tCCutsceneObject *csObj = CCutsceneMgr::GetCutsceneObject(i);\n\t\t\tif(csObj && csObj->m_entryInfoList.first) {\n\t\t\t\tif(csObj->m_rwObject && RwObjectGetType(csObj->m_rwObject) == rpCLUMP &&\n\t\t\t\t   RpAnimBlendClumpGetFirstAssociation(csObj->GetClump())) {\n\t\t\t\t\tif (csObj->IsObject())\n\t\t\t\t\t\tRpAnimBlendClumpUpdateAnimations(csObj->GetClump(), CTimer::GetTimeStepNonClippedInSeconds());\n\t\t\t\t\telse {\n\t\t\t\t\t\tif (!csObj->bOffscreen)\n\t\t\t\t\t\t\tcsObj->bOffscreen = !csObj->GetIsOnScreen();\n\t\t\t\t\t\tRpAnimBlendClumpUpdateAnimations(csObj->GetClump(), CTimer::GetTimeStepInSeconds(), !csObj->bOffscreen);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tcsObj->ProcessControl();\n\t\t\t\tcsObj->ProcessCollision();\n\t\t\t\tcsObj->GetMatrix().UpdateRW();\n\t\t\t\tcsObj->UpdateRwFrame();\n\t\t\t}\n\t\t}\n\t\tCRecordDataForChase::ProcessControlCars();\n\t\tCRecordDataForChase::SaveOrRetrieveCarPositions();\n\t} else {\n\t\tfor(CPtrNode *node = ms_listMovingEntityPtrs.first; node; node = node->next) {\n\t\t\tCEntity *movingEnt = (CEntity *)node->item;\n\t\t\tif(!movingEnt->bRemoveFromWorld && movingEnt->m_rwObject && RwObjectGetType(movingEnt->m_rwObject) == rpCLUMP &&\n\t\t\t   RpAnimBlendClumpGetFirstAssociation(movingEnt->GetClump())) {\n\t\t\t\tif (movingEnt->IsObject())\n\t\t\t\t\tRpAnimBlendClumpUpdateAnimations(movingEnt->GetClump(), CTimer::GetTimeStepNonClippedInSeconds());\n\t\t\t\telse {\n\t\t\t\t\tif (!movingEnt->bOffscreen)\n\t\t\t\t\t\tmovingEnt->bOffscreen = !movingEnt->GetIsOnScreen();\n\t\t\t\t\tRpAnimBlendClumpUpdateAnimations(movingEnt->GetClump(), CTimer::GetTimeStepInSeconds(), !movingEnt->bOffscreen);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tfor(CPtrNode *node = ms_listMovingEntityPtrs.first; node; node = node->next) {\n\t\t\tCPhysical *movingEnt = (CPhysical *)node->item;\n\t\t\tif(movingEnt->bRemoveFromWorld) {\n\t\t\t\tRemoveEntityInsteadOfProcessingIt(movingEnt);\n\t\t\t} else {\n\t\t\t\tmovingEnt->ProcessControl();\n\t\t\t\tif(movingEnt->GetIsStatic()) { movingEnt->RemoveFromMovingList(); }\n\t\t\t}\n\t\t}\n\t\tbForceProcessControl = true;\n\t\tfor(CPtrNode *node = ms_listMovingEntityPtrs.first; node; node = node->next) {\n\t\t\tCPhysical *movingEnt = (CPhysical *)node->item;\n\t\t\tif(movingEnt->bWasPostponed) {\n\t\t\t\tif(movingEnt->bRemoveFromWorld) {\n\t\t\t\t\tRemoveEntityInsteadOfProcessingIt(movingEnt);\n\t\t\t\t} else {\n\t\t\t\t\tmovingEnt->ProcessControl();\n\t\t\t\t\tif(movingEnt->GetIsStatic()) { movingEnt->RemoveFromMovingList(); }\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tbForceProcessControl = false;\n\t\tif(CReplay::IsPlayingBack()) {\n\t\t\tfor(CPtrNode *node = ms_listMovingEntityPtrs.first; node; node = node->next) {\n\t\t\t\tCEntity *movingEnt = (CEntity *)node->item;\n\t\t\t\tmovingEnt->bIsInSafePosition = true;\n\t\t\t\tmovingEnt->GetMatrix().UpdateRW();\n\t\t\t\tmovingEnt->UpdateRwFrame();\n\t\t\t}\n\t\t} else {\n\t\t\tbNoMoreCollisionTorque = false;\n\t\t\tfor(CPtrNode *node = ms_listMovingEntityPtrs.first; node; node = node->next) {\n\t\t\t\tCEntity *movingEnt = (CEntity *)node->item;\n\t\t\t\tif(!movingEnt->bIsInSafePosition) {\n\t\t\t\t\tmovingEnt->ProcessCollision();\n\t\t\t\t\tmovingEnt->GetMatrix().UpdateRW();\n\t\t\t\t\tmovingEnt->UpdateRwFrame();\n\t\t\t\t}\n\t\t\t}\n\t\t\tbNoMoreCollisionTorque = true;\n\t\t\tfor(int i = 0; i < 4; i++) {\n\t\t\t\tfor(CPtrNode *node = ms_listMovingEntityPtrs.first; node; node = node->next) {\n\t\t\t\t\tCEntity *movingEnt = (CEntity *)node->item;\n\t\t\t\t\tif(!movingEnt->bIsInSafePosition) {\n\t\t\t\t\t\tmovingEnt->ProcessCollision();\n\t\t\t\t\t\tmovingEnt->GetMatrix().UpdateRW();\n\t\t\t\t\t\tmovingEnt->UpdateRwFrame();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor(CPtrNode *node = ms_listMovingEntityPtrs.first; node; node = node->next) {\n\t\t\t\tCEntity *movingEnt = (CEntity *)node->item;\n\t\t\t\tif(!movingEnt->bIsInSafePosition) {\n\t\t\t\t\tmovingEnt->bIsStuck = true;\n\t\t\t\t\tmovingEnt->ProcessCollision();\n\t\t\t\t\tmovingEnt->GetMatrix().UpdateRW();\n\t\t\t\t\tmovingEnt->UpdateRwFrame();\n\t\t\t\t\tif(!movingEnt->bIsInSafePosition) { movingEnt->bIsStuck = true; }\n\t\t\t\t}\n\t\t\t}\n\t\t\tbSecondShift = false;\n\t\t\tfor(CPtrNode *node = ms_listMovingEntityPtrs.first; node; node = node->next) {\n\t\t\t\tCEntity *movingEnt = (CEntity *)node->item;\n\t\t\t\tif(!movingEnt->bIsInSafePosition) {\n\t\t\t\t\tmovingEnt->ProcessShift();\n\t\t\t\t\tmovingEnt->GetMatrix().UpdateRW();\n\t\t\t\t\tmovingEnt->UpdateRwFrame();\n\t\t\t\t\tif(!movingEnt->bIsInSafePosition) { movingEnt->bIsStuck = true; }\n\t\t\t\t}\n\t\t\t}\n\t\t\tbSecondShift = true;\n\t\t\tfor(CPtrNode *node = ms_listMovingEntityPtrs.first; node; node = node->next) {\n\t\t\t\tCPhysical *movingEnt = (CPhysical *)node->item;\n\t\t\t\tif(!movingEnt->bIsInSafePosition) {\n\t\t\t\t\tmovingEnt->ProcessShift();\n\t\t\t\t\tmovingEnt->GetMatrix().UpdateRW();\n\t\t\t\t\tmovingEnt->UpdateRwFrame();\n\t\t\t\t\tif(!movingEnt->bIsInSafePosition) {\n\t\t\t\t\t\tmovingEnt->bIsStuck = true;\n\t\t\t\t\t\tif(movingEnt->GetStatus() == STATUS_PLAYER) {\n\t\t\t\t\t\t\tprintf(\"STUCK: Final Step: Player Entity %d Is Stuck\\n\", movingEnt->GetModelIndex());\n\t\t\t\t\t\t\tmovingEnt->m_vecMoveSpeed *= Pow(0.707f, CTimer::GetTimeStep());\n\t\t\t\t\t\t\tmovingEnt->ApplyMoveSpeed();\n\t\t\t\t\t\t\tmovingEnt->ApplyTurnSpeed();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tfor(CPtrNode *node = ms_listMovingEntityPtrs.first; node; node = node->next) {\n\t\t\tCPed *movingPed = (CPed *)node->item;\n\t\t\tif(movingPed->IsPed()) {\n\t\t\t\tif(movingPed->bInVehicle && movingPed->m_nPedState != PED_EXIT_TRAIN ||\n\t\t\t\t   movingPed->EnteringCar()) {\n\t\t\t\t\tCVehicle *movingCar = movingPed->m_pMyVehicle;\n\t\t\t\t\tif(movingCar) {\n#ifdef GTA_TRAIN\n\t\t\t\t\t\tif(movingCar->IsTrain()) {\n\t\t\t\t\t\t\tmovingPed->SetPedPositionInTrain();\n\t\t\t\t\t\t} else\n#endif\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tswitch(movingPed->m_nPedState) {\n\t\t\t\t\t\t\tcase PED_ENTER_CAR:\n\t\t\t\t\t\t\tcase PED_CARJACK: movingPed->EnterCar(); break;\n\t\t\t\t\t\t\tcase PED_DRAG_FROM_CAR: movingPed->BeingDraggedFromCar(); break;\n\t\t\t\t\t\t\tcase PED_EXIT_CAR: movingPed->ExitCar(); break;\n\t\t\t\t\t\t\tcase PED_ARRESTED:\n\t\t\t\t\t\t\t\tif(movingPed->m_nLastPedState == PED_DRAG_FROM_CAR) {\n\t\t\t\t\t\t\t\t\tmovingPed->BeingDraggedFromCar();\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t// fall through\n\t\t\t\t\t\t\tdefault: movingPed->SetPedPositionInCar(); break;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tmovingPed->GetMatrix().UpdateRW();\n\t\t\t\t\t\tmovingPed->UpdateRwFrame();\n\t\t\t\t\t} else {\n\t\t\t\t\t\tmovingPed->bInVehicle = false;\n\t\t\t\t\t\tmovingPed->QuitEnteringCar();\n\t\t\t\t\t}\n\t\t\t\t} else if (movingPed->m_attachedTo) {\n\t\t\t\t\tmovingPed->PositionAttachedPed();\n\t\t\t\t\tmovingPed->GetMatrix().UpdateRW();\n\t\t\t\t\tmovingPed->UpdateRwFrame();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tCMessages::Process();\n\t\tPlayers[PlayerInFocus].Process();\n\t\tCRecordDataForChase::SaveOrRetrieveCarPositions();\n\t\tif((CTimer::GetFrameCounter() & 7) == 1) {\n\t\t\tRemoveFallenPeds();\n\t\t} else if((CTimer::GetFrameCounter() & 7) == 5) {\n\t\t\tRemoveFallenCars();\n\t\t}\n\t}\n}\n\nvoid\nCWorld::TriggerExplosion(const CVector &position, float fRadius, float fPower, CEntity *pCreator,\n                         bool bProcessVehicleBombTimer)\n{\n\tCVector2D vecStartPos(position.x - fRadius, position.y - fRadius);\n\tCVector2D vecEndPos(position.x + fRadius, position.y + fRadius);\n\tconst int32 nStartX = Max(GetSectorIndexX(vecStartPos.x), 0);\n\tconst int32 nStartY = Max(GetSectorIndexY(vecStartPos.y), 0);\n\tconst int32 nEndX = Min(GetSectorIndexX(vecEndPos.x), NUMSECTORS_X - 1);\n\tconst int32 nEndY = Min(GetSectorIndexY(vecEndPos.y), NUMSECTORS_Y - 1);\n\tfor(int32 y = nStartY; y <= nEndY; y++) {\n\t\tfor(int32 x = nStartX; x <= nEndX; x++) {\n\t\t\tCSector *pSector = GetSector(x, y);\n\t\t\tTriggerExplosionSectorList(pSector->m_lists[ENTITYLIST_VEHICLES], position, fRadius,\n\t\t\t                                   fPower, pCreator, bProcessVehicleBombTimer);\n\t\t\tTriggerExplosionSectorList(pSector->m_lists[ENTITYLIST_PEDS], position, fRadius, fPower,\n\t\t\t                                   pCreator, bProcessVehicleBombTimer);\n\t\t\tTriggerExplosionSectorList(pSector->m_lists[ENTITYLIST_OBJECTS], position, fRadius,\n\t\t\t                                   fPower, pCreator, bProcessVehicleBombTimer);\n\t\t}\n\t}\n}\n\nvoid\nCWorld::TriggerExplosionSectorList(CPtrList &list, const CVector &position, float fRadius, float fPower,\n                                   CEntity *pCreator, bool bProcessVehicleBombTimer)\n{\n\tfor(CPtrNode *pNode = list.first; pNode; pNode = pNode->next) {\n\t\tCPhysical *pEntity = (CPhysical *)pNode->item;\n\t\tCVector vecDistance = pEntity->GetPosition() - position;\n\t\tfloat fMagnitude = vecDistance.Magnitude();\n\t\tif(fRadius > fMagnitude) {\n\t\t\tCWeapon::BlowUpExplosiveThings(pEntity);\n\t\t\tCPed *pPed = (CPed *)pEntity;\n\t\t\tCObject *pObject = (CObject *)pEntity;\n\t\t\tCVehicle *pVehicle = (CVehicle *)pEntity;\n\t\t\tif(!pEntity->bExplosionProof && (!pEntity->IsPed() || !pPed->bInVehicle)) {\n\t\t\t\tif(pEntity->GetIsStatic()) {\n\t\t\t\t\tif(pEntity->IsObject()) {\n\t\t\t\t\t\tif (fPower > pObject->m_fUprootLimit || IsFence(pObject->GetModelIndex())) {\n\t\t\t\t\t\t\tif (IsGlass(pObject->GetModelIndex())) {\n\t\t\t\t\t\t\t\tCGlass::WindowRespondsToExplosion(pObject, position);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tpObject->SetIsStatic(false);\n\t\t\t\t\t\t\t\tpObject->AddToMovingList();\n\t\t\t\t\t\t\t\tint16 modelId = pEntity->GetModelIndex();\n\t\t\t\t\t\t\t\tif(modelId != MI_FIRE_HYDRANT ||\n\t\t\t\t\t\t\t\t   pObject->bHasBeenDamaged) {\n\t\t\t\t\t\t\t\t\tif(pEntity->IsObject() &&\n\t\t\t\t\t\t\t\t\t   modelId != MI_EXPLODINGBARREL &&\n\t\t\t\t\t\t\t\t\t   modelId != MI_PETROLPUMP && modelId != MI_PETROLPUMP2)\n\t\t\t\t\t\t\t\t\t\tpObject->bHasBeenDamaged = true;\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tCVector pos = pEntity->GetPosition();\n\t\t\t\t\t\t\t\t\tpos.z -= 0.5f;\n\t\t\t\t\t\t\t\t\tCParticleObject::AddObject(POBJECT_FIRE_HYDRANT,\n\t\t\t\t\t\t\t\t\t                           pos, true);\n\t\t\t\t\t\t\t\t\tpObject->bHasBeenDamaged = true;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif(pEntity->GetIsStatic()) {\n\t\t\t\t\t\t\tfloat fDamageMultiplier =\n\t\t\t\t\t\t\t    (fRadius - fMagnitude) * 2.0f / fRadius;\n\t\t\t\t\t\t\tfloat fDamage = 300.0f * Min(fDamageMultiplier, 1.0f);\n\t\t\t\t\t\t\tpObject->ObjectDamage(fDamage);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tpEntity->SetIsStatic(false);\n\t\t\t\t\t\tpEntity->AddToMovingList();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif(!pEntity->GetIsStatic()) {\n\t\t\t\t\tfloat fDamageMultiplier = Min((fRadius - fMagnitude) * 2.0f / fRadius, 1.0f);\n\t\t\t\t\tCVector vecForceDir =\n\t\t\t\t\t    vecDistance * (fPower * pEntity->m_fMass / 1400.0f * fDamageMultiplier /\n\t\t\t\t\t                   Max(fMagnitude, 0.01f));\n\t\t\t\t\tvecForceDir.z = Max(vecForceDir.z, 0.0f);\n\t\t\t\t\tif(pEntity == FindPlayerPed()) vecForceDir.z = Min(vecForceDir.z, 1.0f);\n\t\t\t\t\tpEntity->ApplyMoveForce(vecForceDir);\n\t\t\t\t\tif(!pEntity->bPedPhysics) {\n\t\t\t\t\t\tfloat fBoundRadius = pEntity->GetBoundRadius();\n\t\t\t\t\t\tfloat fDistanceZ = position.z - pEntity->GetPosition().z;\n\t\t\t\t\t\tfloat fPointZ = fBoundRadius;\n\t\t\t\t\t\tif(Max(fDistanceZ, -fBoundRadius) < fBoundRadius) {\n\t\t\t\t\t\t\tif(fDistanceZ <= -fBoundRadius)\n\t\t\t\t\t\t\t\tfPointZ = -fBoundRadius;\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\tfPointZ = fDistanceZ;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tpEntity->ApplyTurnForce(vecForceDir.x, vecForceDir.y, vecForceDir.z,\n\t\t\t\t\t\t                        0.0f, 0.0f, fPointZ);\n\t\t\t\t\t}\n\t\t\t\t\tswitch(pEntity->GetType()) {\n\t\t\t\t\tcase ENTITY_TYPE_VEHICLE:\n\t\t\t\t\t\tif(pEntity->GetStatus() == STATUS_SIMPLE) {\n\t\t\t\t\t\t\tpEntity->SetStatus(STATUS_PHYSICS);\n\t\t\t\t\t\t\tCCarCtrl::SwitchVehicleToRealPhysics(pVehicle);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tpVehicle->InflictDamage(pCreator, WEAPONTYPE_EXPLOSION,\n\t\t\t\t\t\t                        1100.0f * fDamageMultiplier);\n\t\t\t\t\t\tif(bProcessVehicleBombTimer) {\n\t\t\t\t\t\t\tif(pVehicle->m_nBombTimer) pVehicle->m_nBombTimer /= 10;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase ENTITY_TYPE_PED: {\n\t\t\t\t\t\tint8 direction = pPed->GetLocalDirection(-vecForceDir);\n\t\t\t\t\t\tpPed->bIsStanding = false;\n\t\t\t\t\t\tpPed->ApplyMoveForce(0.0, 0.0, 2.0f);\n\t\t\t\t\t\tfloat fDamage = 250.0f * fDamageMultiplier;\n\t\t\t\t\t\tpPed->InflictDamage(pCreator, WEAPONTYPE_EXPLOSION, fDamage,\n\t\t\t\t\t\t                    PEDPIECE_TORSO, direction);\n\t\t\t\t\t\tif(pPed->m_nPedState != PED_DIE)\n\t\t\t\t\t\t\tpPed->SetFall(2000,\n\t\t\t\t\t\t\t              (AnimationId)(direction + ANIM_STD_HIGHIMPACT_FRONT), 0);\n\t\t\t\t\t\tif(pCreator && pCreator->IsPed()) {\n\t\t\t\t\t\t\teEventType eventType = EVENT_SHOOT_PED;\n\t\t\t\t\t\t\tif(pPed->m_nPedType == PEDTYPE_COP) eventType = EVENT_SHOOT_COP;\n\t\t\t\t\t\t\tCEventList::RegisterEvent(eventType, EVENT_ENTITY_PED, pEntity,\n\t\t\t\t\t\t\t                          (CPed *)pCreator, 10000);\n\t\t\t\t\t\t\tpPed->RegisterThreatWithGangPeds(pCreator);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase ENTITY_TYPE_OBJECT:\n\t\t\t\t\t\tpObject->ObjectDamage(300.0f * fDamageMultiplier);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault: break;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nCWorld::UseDetonator(CEntity *pEntity)\n{\n\tint32 i = CPools::GetVehiclePool()->GetSize();\n\twhile(--i >= 0) {\n#ifdef FIX_BUGS\n\t\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetSlot(i);\n#else\n\t\tCAutomobile *pVehicle = (CAutomobile *)CPools::GetVehiclePool()->GetSlot(i);\n#endif\n\t\tif(pVehicle && pVehicle->m_bombType == CARBOMB_REMOTE &&\n\t\t   pVehicle->m_pBombRigger == pEntity) {\n\t\t\tpVehicle->m_bombType = CARBOMB_NONE;\n\t\t\tpVehicle->m_nBombTimer = 500;\n\t\t\tpVehicle->m_pBlowUpEntity = pVehicle->m_pBombRigger;\n\t\t\tif(pVehicle->m_pBlowUpEntity)\n\t\t\t\tpVehicle->m_pBlowUpEntity->RegisterReference(&pVehicle->m_pBlowUpEntity);\n\t\t}\n\t}\n\tCProjectileInfo::RemoveDetonatorProjectiles();\n}\n\nbool\nCWorld::IsWanderPathClear(CVector const& point1, CVector const& point2, float distance, int maxSteps)\n{\n\tif (Abs(point1.z - point2.z) > distance)\n\t\treturn false;\n\tif (!GetIsLineOfSightClear(point1, point2, true, false, false, false, false, false, false))\n\t\treturn false;\n\tCVector vecBetween = point2 - point1;\n\tuint32 nSteps = Max(vecBetween.Magnitude(), maxSteps);\n\tif (nSteps == 0)\n\t\treturn true;\n\tvecBetween.Normalise();\n\tuint32 step = 1;\n\tfor (step = 1; step < nSteps; step++) {\n\t\tCVector posThisStep = point1 + vecBetween * step;\n\t\tfloat level;\n\t\tif (!CWaterLevel::GetWaterLevel(posThisStep, &level, false))\n\t\t\tcontinue;\n\t\tposThisStep.z = level;\n\t\tAdvanceCurrentScanCode();\n\n\t\tCVector vecCheckedPos(posThisStep.x, posThisStep.y, Max(point1.z, point2.z));\n\t\tCColPoint colpoint;\n\t\tCEntity* entity;\n\t\tif (!ProcessVerticalLineSector(*GetSector(GetSectorIndexX(posThisStep.x), GetSectorIndexY(posThisStep.y)),\n\t\t\tCColLine(posThisStep, vecCheckedPos), colpoint, entity, true, false, false, false, false, false, nil))\n\t\t\treturn false;\n\t}\n\n\tCVector posThisStep = point1;\n\tAdvanceCurrentScanCode();\n\tCVector vecCheckedPos(posThisStep.x, posThisStep.y, point1.z - 5.0f);\n\n\tCColPoint colpoint;\n\tCEntity* entity;\n\tif (!ProcessVerticalLineSector(*GetSector(GetSectorIndexX(posThisStep.x), GetSectorIndexY(posThisStep.y)),\n\t\tCColLine(posThisStep, vecCheckedPos), colpoint, entity, true, false, false, false, false, false, nil))\n\t\treturn false;\n\n\tfloat heightNextStep = colpoint.point.z + 0.5f;\n\tfor (step = 1; step < nSteps; step++) {\n\t\tCVector posThisStep = point1 + vecBetween * step;\n\t\tposThisStep.z = heightNextStep;\n\t\tAdvanceCurrentScanCode();\n\t\tCVector vecCheckedPos(posThisStep.x, posThisStep.y, heightNextStep - 2.0f);\n\t\tif (!ProcessVerticalLineSector(*GetSector(GetSectorIndexX(posThisStep.x), GetSectorIndexY(posThisStep.y)),\n\t\t\tCColLine(posThisStep, vecCheckedPos), colpoint, entity, true, false, false, false, false, false, nil))\n\t\t\treturn false;\n\t\tif (Abs(colpoint.point.z - heightNextStep) > 1.0f)\n\t\t\treturn false;\n\t\theightNextStep = colpoint.point.z + 0.5f;\n\t}\n\treturn true;\n}\n"
  },
  {
    "path": "src/core/World.h",
    "content": "#pragma once\n\n#include \"Game.h\"\n#include \"Lists.h\"\n#include \"PlayerInfo.h\"\n#include \"Collision.h\"\n\n/* Sectors span from -2400 to 1600 in x and -2000 to 2000 y.\n * With 80x80 sectors, each is 50x50 units. */\n\n#define SECTOR_SIZE_X (50.0f)\n#define SECTOR_SIZE_Y (50.0f)\n\n#define NUMSECTORS_X (80)\n#define NUMSECTORS_Y (80)\n\n#define WORLD_SIZE_X (NUMSECTORS_X * SECTOR_SIZE_X)\n#define WORLD_SIZE_Y (NUMSECTORS_Y * SECTOR_SIZE_Y)\n\n#define WORLD_MIN_X (-2400.0f)\n#define WORLD_MIN_Y (-2000.0f)\n\n#define WORLD_MAX_X (WORLD_MIN_X + WORLD_SIZE_X)\n#define WORLD_MAX_Y (WORLD_MIN_Y + WORLD_SIZE_Y)\n\n#define MAP_Z_LOW_LIMIT -100.0f\n\nenum\n{\n\tENTITYLIST_BUILDINGS,\n\tENTITYLIST_BUILDINGS_OVERLAP,\n\tENTITYLIST_OBJECTS,\n\tENTITYLIST_OBJECTS_OVERLAP,\n\tENTITYLIST_VEHICLES,\n\tENTITYLIST_VEHICLES_OVERLAP,\n\tENTITYLIST_PEDS,\n\tENTITYLIST_PEDS_OVERLAP,\n\tENTITYLIST_DUMMIES,\n\tENTITYLIST_DUMMIES_OVERLAP,\n\n\tNUMSECTORENTITYLISTS\n};\n\nclass CSector\n{\npublic:\n\tCPtrList m_lists[NUMSECTORENTITYLISTS];\n};\n\nVALIDATE_SIZE(CSector, 0x28);\n\nclass CWorld\n{\n\tstatic CPtrList ms_bigBuildingsList[NUM_LEVELS];\n\tstatic CPtrList ms_listMovingEntityPtrs;\n\tstatic CSector ms_aSectors[NUMSECTORS_Y][NUMSECTORS_X];\n\tstatic uint16 ms_nCurrentScanCode;\n\npublic:\n\tstatic uint8 PlayerInFocus;\n\tstatic CPlayerInfo Players[NUMPLAYERS];\n\tstatic CEntity *pIgnoreEntity;\n\tstatic bool bIncludeDeadPeds;\n\tstatic bool bNoMoreCollisionTorque;\n\tstatic bool bSecondShift;\n\tstatic bool bForceProcessControl;\n\tstatic bool bProcessCutsceneOnly;\n\tstatic bool bDoingCarCollisions;\n\tstatic bool bIncludeCarTyres;\n\tstatic bool bIncludeBikers;\n\tstatic CColPoint m_aTempColPts[MAX_COLLISION_POINTS];\n\n\tstatic void Remove(CEntity *entity);\n\tstatic void Add(CEntity *entity);\n\n\tstatic CSector *GetSector(int x, int y) { if (x > NUMSECTORS_X - 1 || y > NUMSECTORS_Y - 1) return &ms_aSectors[0][0]; return &ms_aSectors[y][x]; }\n\tstatic CPtrList &GetBigBuildingList(eLevelName i) { return ms_bigBuildingsList[i]; }\n\tstatic CPtrList &GetMovingEntityList(void) { return ms_listMovingEntityPtrs; }\n\tstatic uint16 GetCurrentScanCode(void) { return ms_nCurrentScanCode; }\n\tstatic void AdvanceCurrentScanCode(void){\n\t\tif(++CWorld::ms_nCurrentScanCode == 0){\n\t\t\tCWorld::ClearScanCodes();\n\t\t\tCWorld::ms_nCurrentScanCode = 1;\n\t\t}\n\t}\n\tstatic void ClearScanCodes(void);\n\tstatic void ClearExcitingStuffFromArea(const CVector &pos, float radius, bool bRemoveProjectilesAndTidyUpShadows);\n\n\tstatic bool CameraToIgnoreThisObject(CEntity *ent);\n\n\tstatic bool ProcessLineOfSight(const CVector &point1, const CVector &point2, CColPoint &point, CEntity *&entity, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSeeThrough, bool ignoreSomeObjects = false, bool ignoreShootThrough = false);\n\tstatic bool ProcessLineOfSightSector(CSector &sector, const CColLine &line, CColPoint &point, float &dist, CEntity *&entity, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSeeThrough, bool ignoreSomeObjects, bool ignoreShootThrough);\n\tstatic bool ProcessLineOfSightSectorList(CPtrList &list, const CColLine &line, CColPoint &point, float &dist, CEntity *&entity, bool ignoreSeeThrough, bool ignoreSomeObjects, bool ignoreShootThrough);\n\tstatic bool ProcessVerticalLine(const CVector &point1, float z2, CColPoint &point, CEntity *&entity, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSeeThrough, CStoredCollPoly *poly);\n\tstatic bool ProcessVerticalLineSector(CSector &sector, const CColLine &line, CColPoint &point, CEntity *&entity, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSeeThrough, CStoredCollPoly *poly);\n\tstatic bool ProcessVerticalLineSectorList(CPtrList &list, const CColLine &line, CColPoint &point, float &dist, CEntity *&entity, bool ignoreSeeThrough, CStoredCollPoly *poly);\n\tstatic bool GetIsLineOfSightClear(const CVector &point1, const CVector &point2, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSeeThrough, bool ignoreSomeObjects = false);\n\tstatic bool GetIsLineOfSightSectorClear(CSector &sector, const CColLine &line, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSeeThrough, bool ignoreSomeObjects = false);\n\tstatic bool GetIsLineOfSightSectorListClear(CPtrList &list, const CColLine &line, bool ignoreSeeThrough, bool ignoreSomeObjects = false);\n\t\n\tstatic CEntity *TestSphereAgainstWorld(CVector centre, float radius, CEntity *entityToIgnore, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSomeObjects);\n\tstatic CEntity *TestSphereAgainstSectorList(CPtrList&, CVector, float, CEntity*, bool);\n\tstatic void FindObjectsInRangeSectorList(CPtrList &list, Const CVector &centre, float radius, bool ignoreZ, int16 *numObjects, int16 lastObject, CEntity **objects);\n\tstatic void FindObjectsInRange(Const CVector &centre, float radius, bool ignoreZ, int16 *numObjects, int16 lastObject, CEntity **objects, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies);\n\tstatic void FindObjectsOfTypeInRangeSectorList(uint32 modelId, CPtrList& list, const CVector& position, float radius, bool bCheck2DOnly, int16* nEntitiesFound, int16 maxEntitiesToFind, CEntity** aEntities);\n\tstatic void FindObjectsOfTypeInRange(uint32 modelId, const CVector& position, float radius, bool bCheck2DOnly, int16* nEntitiesFound, int16 maxEntitiesToFind, CEntity** aEntities, bool bBuildings, bool bVehicles, bool bPeds, bool bObjects, bool bDummies);\n\tstatic float FindGroundZForCoord(float x, float y);\n\tstatic float FindGroundZFor3DCoord(float x, float y, float z, bool *found);\n\tstatic float FindRoofZFor3DCoord(float x, float y, float z, bool *found);\n\tstatic void RemoveReferencesToDeletedObject(CEntity*);\n\tstatic void FindObjectsKindaColliding(const CVector& position, float radius, bool bCheck2DOnly, int16* nCollidingEntities, int16 maxEntitiesToFind, CEntity** aEntities, bool bBuildings, bool bVehicles, bool bPeds, bool bObjects, bool bDummies);\n\tstatic void FindObjectsKindaCollidingSectorList(CPtrList& list, const CVector& position, float radius, bool bCheck2DOnly, int16* nCollidingEntities, int16 maxEntitiesToFind, CEntity** aEntities);\n\tstatic void FindObjectsIntersectingCube(const CVector& vecStartPos, const CVector& vecEndPos, int16* nIntersecting, int16 maxEntitiesToFind, CEntity** aEntities, bool bBuildings, bool bVehicles, bool bPeds, bool bObjects, bool bDummies);\n\tstatic void FindObjectsIntersectingCubeSectorList(CPtrList& list, const CVector& vecStartPos, const CVector& vecEndPos, int16* nIntersecting, int16 maxEntitiesToFind, CEntity** aEntities);\n\tstatic void FindObjectsIntersectingAngledCollisionBox(const CBox &, const CMatrix &, const CVector &, float, float, float, float, int16*, int16, CEntity **, bool, bool, bool, bool, bool);\n\tstatic void FindObjectsIntersectingAngledCollisionBoxSectorList(CPtrList& list, const CBox& boundingBox, const CMatrix& matrix, const CVector& position, int16* nEntitiesFound, int16 maxEntitiesToFind, CEntity** aEntities);\n\tstatic void FindMissionEntitiesIntersectingCube(const CVector& vecStartPos, const CVector& vecEndPos, int16* nIntersecting, int16 maxEntitiesToFind, CEntity** aEntities, bool bVehicles, bool bPeds, bool bObjects);\n\tstatic void FindMissionEntitiesIntersectingCubeSectorList(CPtrList& list, const CVector& vecStartPos, const CVector& vecEndPos, int16* nIntersecting, int16 maxEntitiesToFind, CEntity** aEntities, bool bIsVehicleList, bool bIsPedList);\n\n\tstatic void ClearCarsFromArea(float x1, float y1, float z1, float x2, float y2, float z2);\n\tstatic void ClearPedsFromArea(float x1, float y1, float z1, float x2, float y2, float z2);\n\tstatic void CallOffChaseForArea(float x1, float y1, float x2, float y2);\n\tstatic void CallOffChaseForAreaSectorListVehicles(CPtrList& list, float x1, float y1, float x2, float y2, float fStartX, float fStartY, float fEndX, float fEndY);\n\tstatic void CallOffChaseForAreaSectorListPeds(CPtrList& list, float x1, float y1, float x2, float y2);\n\n\tstatic bool IsWanderPathClear(CVector const&, CVector const&, float, int);\n\n\tstatic float GetSectorX(float f) { return ((f - WORLD_MIN_X)/SECTOR_SIZE_X); }\n\tstatic float GetSectorY(float f) { return ((f - WORLD_MIN_Y)/SECTOR_SIZE_Y); }\n\tstatic int GetSectorIndexX(float f) { return (int)GetSectorX(f); }\n\tstatic int GetSectorIndexY(float f) { return (int)GetSectorY(f); }\n\tstatic float GetWorldX(int x) { return x*SECTOR_SIZE_X + WORLD_MIN_X; }\n\tstatic float GetWorldY(int y) { return y*SECTOR_SIZE_Y + WORLD_MIN_Y; }\n\n\tstatic void RemoveEntityInsteadOfProcessingIt(CEntity* ent);\n\tstatic void RemoveFallenPeds();\n\tstatic void RemoveFallenCars();\n\n\tstatic void StopAllLawEnforcersInTheirTracks();\n\tstatic void SetAllCarsCanBeDamaged(bool);\n\tstatic void ExtinguishAllCarFiresInArea(CVector, float);\n\tstatic void SetCarsOnFire(float x, float y, float z, float radius, CEntity* reason);\n\tstatic void SetPedsChoking(float x, float y, float z, float radius, CEntity* reason);\n\tstatic void SetPedsOnFire(float x, float y, float z, float radius, CEntity* reason);\n\n\tstatic void Initialise();\n\tstatic void AddParticles();\n\tstatic void ShutDown();\n\tstatic void ClearForRestart(void);\n\tstatic void RepositionCertainDynamicObjects();\n\tstatic void RepositionOneObject(CEntity* pEntity);\n\tstatic void RemoveStaticObjects();\n\tstatic void Process();\n\tstatic void TriggerExplosion(const CVector& position, float fRadius, float fPower, CEntity* pCreator, bool bProcessVehicleBombTimer);\n\tstatic void TriggerExplosionSectorList(CPtrList& list, const CVector& position, float fRadius, float fPower, CEntity* pCreator, bool bProcessVehicleBombTimer);\n\tstatic void UseDetonator(CEntity *pEntity);\n\n\t// NB: following functions are unused (TODO?)\n\tstatic void CastShadow(float, float, float, float);\n\tstatic void CastShadowSectorList(CPtrList&, float, float, float, float);\n\tstatic void FindLowestZForCoord(float, float);\n\tstatic void CheckBlockListIntegrity(void);\n\tstatic void ProcessVerticalLineSectorList_FillGlobeColPoints(CPtrList&, const CColLine&, CEntity*&, bool, CStoredCollPoly*);\n\tstatic void ProcessVerticalLineSector_FillGlobeColPoints(CSector&, const CColLine&, CEntity*&, bool, bool, bool, bool, bool, bool, CStoredCollPoly*);\n\tstatic void ProcessVerticalLine_FillGlobeColPoints(const CVector&, float, CEntity*&, bool, bool, bool, bool, bool, bool, CStoredCollPoly*);\n\tstatic void PrintCarChanges(void);\n\tstatic void TestForBuildingsOnTopOfEachOther(CPtrList&);\n\tstatic void TestForBuildingsOnTopOfEachOther(void);\n\tstatic void TestForUnusedModels(CPtrList&, int*);\n\tstatic void TestForUnusedModels(void);\n\tstatic void HandleCollisionZoneChange(eLevelName, eLevelName);\n\tstatic void DoZoneTestForChaser(class CPhysical*);\n\tstatic void FindPlayerSlotWithPedPointer(void*);\n};\n\nextern CColPoint gaTempSphereColPoints[MAX_COLLISION_POINTS];\n"
  },
  {
    "path": "src/core/ZoneCull.cpp",
    "content": "#include \"common.h\"\n\n#include \"Building.h\"\n#include \"Treadable.h\"\n#include \"Train.h\"\n#include \"Pools.h\"\n#include \"Timer.h\"\n#include \"Camera.h\"\n#include \"World.h\"\n#include \"FileMgr.h\"\n#include \"ZoneCull.h\"\n#include \"Zones.h\"\n\nint32     CCullZones::NumAttributeZones;\nCAttributeZone CCullZones::aAttributeZones[NUMATTRIBZONES];\n\nint32 CCullZones::CurrentWantedLevelDrop_Player;\nint32 CCullZones::CurrentFlags_Camera;\nint32 CCullZones::CurrentFlags_Player;\nbool CCullZones::bCurrentSubwayIsInvisible;\nbool CCullZones::bAtBeachForAudio;\n\nvoid\nCCullZones::Init(void)\n{\n\tNumAttributeZones = 0;\n\tCurrentWantedLevelDrop_Player = 0;\n\tCurrentFlags_Camera = 0;\n\tCurrentFlags_Player = 0;\n\tbCurrentSubwayIsInvisible = false;\n}\n\nvoid\nCCullZones::Update(void)\n{\n\tbool invisible;\n\n\tswitch(CTimer::GetFrameCounter() & 7){\n\tcase 0:\n\tcase 4:\n\t\tUpdateAtBeachForAudio();\n\t\tbreak;\n\n\tcase 2:\n\t\t/* Update camera attributes */\n\t\tCurrentFlags_Camera = FindAttributesForCoors(TheCamera.GetGameCamPosition(), nil);\n\t\tinvisible = (CurrentFlags_Camera & ATTRZONE_SUBWAYVISIBLE) == 0;\n\t\tif(invisible != bCurrentSubwayIsInvisible){\n\t\t\tMarkSubwayAsInvisible(!invisible);\n\t\t\tbCurrentSubwayIsInvisible = invisible;\n\t\t}\n\t\tbreak;\n\n\tcase 6:\n\t\t/* Update player attributes */\n\t\tCurrentFlags_Player = FindAttributesForCoors(FindPlayerCoors(),\n\t\t\t&CurrentWantedLevelDrop_Player);\n\t\tbreak;\n\t}\n}\n\n// TODO? put somewhere else?\nbool\nIsPointWithinArbitraryArea(float px, float py, float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4)\n{\n\tif((px-x1)*(x2-x1) - (py-y1)*(y2-y1) < 0.0f) return false;\n\tif((px-x2)*(x3-x2) - (py-y2)*(y3-y2) < 0.0f) return false;\n\tif((px-x3)*(x4-x3) - (py-y3)*(y4-y3) < 0.0f) return false;\n\tif((px-x4)*(x1-x4) - (py-y4)*(y1-y4) < 0.0f) return false;\n\treturn true;\n}\n\nvoid\nCCullZones::UpdateAtBeachForAudio(void)\n{\n\tbAtBeachForAudio = IsPointWithinArbitraryArea(TheCamera.GetPosition().x, TheCamera.GetPosition().y,\n\t\t400.0f, -1644.4f,\n\t\t751.9f, 1267.8f,\n\t\t971.9f, 1216.2f,\n\t\t840.0f, -1744.0f);\n}\n\nvoid\nCCullZones::ForceCullZoneCoors(CVector coors)\n{\n}\n\nint32\nCCullZones::FindAttributesForCoors(CVector coors, int32 *wantedLevel)\n{\n\tint i;\n\tint32 attribs;\n\n\tif (wantedLevel)\n\t\t*wantedLevel = 0;\n\tattribs = 0;\n\tfor(i = 0; i < NumAttributeZones; i++)\n\t\tif(coors.x >= aAttributeZones[i].minx && coors.x <= aAttributeZones[i].maxx &&\n\t\t   coors.y >= aAttributeZones[i].miny && coors.y <= aAttributeZones[i].maxy &&\n\t\t   coors.z >= aAttributeZones[i].minz && coors.z <= aAttributeZones[i].maxz){\n\t\t\tattribs |= aAttributeZones[i].attributes;\n\t\t\tif(wantedLevel)\n\t\t\t\t*wantedLevel = Max(*wantedLevel, aAttributeZones[i].wantedLevel);\n\t\t}\n\treturn attribs;\n}\n\nCAttributeZone*\nCCullZones::FindZoneWithStairsAttributeForPlayer(void)\n{\n\tint i;\n\tCVector coors;\n\n\tcoors = FindPlayerCoors();\n\tfor(i = 0; i < NumAttributeZones; i++)\n\t\tif(aAttributeZones[i].attributes & ATTRZONE_STAIRS &&\n\t\t   coors.x >= aAttributeZones[i].minx && coors.x <= aAttributeZones[i].maxx &&\n\t\t   coors.y >= aAttributeZones[i].miny && coors.y <= aAttributeZones[i].maxy &&\n\t\t   coors.z >= aAttributeZones[i].minz && coors.z <= aAttributeZones[i].maxz)\n\t\t\treturn &aAttributeZones[i];\n\treturn nil;\n}\n\nvoid\nCCullZones::MarkSubwayAsInvisible(bool visible)\n{\n\tint i, n;\n\tCEntity *e;\n\tCVehicle *v;\n\n\tn = CPools::GetBuildingPool()->GetSize()-1;\n\tfor(i = n; i >= 0; i--){\n\t\te = CPools::GetBuildingPool()->GetSlot(i);\n\t\tif(e && e->bIsSubway)\n\t\t\te->bIsVisible = visible;\n\t}\n\n\tn = CPools::GetTreadablePool()->GetSize()-1;\n\tfor(i = n; i >= 0; i--){\n\t\te = CPools::GetTreadablePool()->GetSlot(i);\n\t\tif(e && e->bIsSubway)\n\t\t\te->bIsVisible = visible;\n\t}\n\n\tn = CPools::GetVehiclePool()->GetSize()-1;\n\tfor(i = n; i >= 0; i--){\n\t\tv = CPools::GetVehiclePool()->GetSlot(i);\n\t\tif(v && v->IsTrain() && ((CTrain*)v)->m_nTrackId != TRACK_ELTRAIN)\n\t\t\tv->bIsVisible = visible;\n\t}\n}\n\nvoid\nCCullZones::AddCullZone(CVector const &position,\n                        float minx, float maxx,\n                        float miny, float maxy,\n                        float minz, float maxz,\n                        uint16 flag, int16 wantedLevel)\n{\n\tCAttributeZone *attrib;\n\n\tassert(NumAttributeZones < NUMATTRIBZONES);\n\tattrib = &aAttributeZones[NumAttributeZones++];\n\tattrib->minx = minx;\n\tattrib->maxx = maxx;\n\tattrib->miny = miny;\n\tattrib->maxy = maxy;\n\tattrib->minz = minz;\n\tattrib->maxz = maxz;\n\tattrib->attributes = flag;\n\tattrib->wantedLevel = wantedLevel;\n}\n"
  },
  {
    "path": "src/core/ZoneCull.h",
    "content": "class CEntity;\n\nenum eZoneAttribs\n{\n\tATTRZONE_CAMCLOSEIN\t\t= 1,\n\tATTRZONE_STAIRS\t\t\t= 2,\n\tATTRZONE_1STPERSON\t\t= 4,\n\tATTRZONE_NORAIN\t\t\t= 8,\n\tATTRZONE_NOPOLICE\t\t= 0x10,\n\tATTRZONE_NOTCULLZONE\t\t= 0x20,\n\tATTRZONE_DOINEEDCOLLISION\t= 0x40,\n\tATTRZONE_SUBWAYVISIBLE\t\t= 0x80,\n\tATTRZONE_POLICEABANDONCARS\t= 0x100,\n\tATTRZONE_ROOMFORAUDIO\t\t= 0x200,\n\tATTRZONE_WATERFUDGE\t\t= 0x400,\n};\n\nstruct CAttributeZone\n{\n\tint16 minx;\n\tint16 maxx;\n\tint16 miny;\n\tint16 maxy;\n\tint16 minz;\n\tint16 maxz;\n\tint16 attributes;\n\tint16 wantedLevel;\n};\n\nclass CCullZones\n{\npublic:\n\tstatic int32     NumAttributeZones;\n\tstatic CAttributeZone aAttributeZones[NUMATTRIBZONES];\n\n\tstatic int32 CurrentWantedLevelDrop_Player;\n\tstatic int32 CurrentFlags_Camera;\n\tstatic int32 CurrentFlags_Player;\n\tstatic bool bCurrentSubwayIsInvisible;\n\tstatic bool bAtBeachForAudio;\n\n\tstatic void Init(void);\n\tstatic void Update(void);\n\tstatic void UpdateAtBeachForAudio(void);\n\tstatic void ForceCullZoneCoors(CVector coors);\n\tstatic int32 FindAttributesForCoors(CVector coors, int32 *wantedLevel);\n\tstatic CAttributeZone *FindZoneWithStairsAttributeForPlayer(void);\n\tstatic void MarkSubwayAsInvisible(bool visible);\n\tstatic void AddCullZone(CVector const &position,\n\t\tfloat minx, float maxx,\n\t\tfloat miny, float maxy,\n\t\tfloat minz, float maxz,\n\t\tuint16 flag, int16 wantedLevel);\n\tstatic bool CamCloseInForPlayer(void) { return (CurrentFlags_Player & ATTRZONE_CAMCLOSEIN) != 0; }\n\tstatic bool CamStairsForPlayer(void) { return (CurrentFlags_Player & ATTRZONE_STAIRS) != 0; }\n\tstatic bool Cam1stPersonForPlayer(void) { return (CurrentFlags_Player & ATTRZONE_1STPERSON) != 0; }\n\tstatic bool NoPolice(void) { return (CurrentFlags_Player & ATTRZONE_NOPOLICE) != 0; }\n\tstatic bool DoINeedToLoadCollision(void) { return (CurrentFlags_Player & ATTRZONE_DOINEEDCOLLISION) != 0; }\n\tstatic bool PlayerNoRain(void) { return (CurrentFlags_Player & ATTRZONE_NORAIN) != 0; }\n\tstatic bool CamNoRain(void) { return (CurrentFlags_Camera & ATTRZONE_NORAIN) != 0; }\n\tstatic bool PoliceAbandonCars(void) { return (CurrentFlags_Camera & ATTRZONE_POLICEABANDONCARS) != 0; }\n\tstatic bool InRoomForAudio(void) { return (CurrentFlags_Camera & ATTRZONE_ROOMFORAUDIO) != 0; }\n\tstatic bool WaterFudge(void) { return (CurrentFlags_Camera & ATTRZONE_WATERFUDGE) != 0; }\n\tstatic int32 GetWantedLevelDrop(void) { return CurrentWantedLevelDrop_Player; }\n};\n"
  },
  {
    "path": "src/core/Zones.cpp",
    "content": "#include \"common.h\"\n\n#include <ctype.h>\n\n#include \"Zones.h\"\n\n#include \"Clock.h\"\n#include \"Text.h\"\n#include \"World.h\"\n#include \"Timer.h\"\n\neLevelName CTheZones::m_CurrLevel;\nint16 CTheZones::FindIndex;\n\nuint16 CTheZones::NumberOfAudioZones;\nint16 CTheZones::AudioZoneArray[NUMAUDIOZONES];\nuint16 CTheZones::TotalNumberOfMapZones;\nuint16 CTheZones::TotalNumberOfInfoZones;\nuint16 CTheZones::TotalNumberOfNavigationZones;\nCZone CTheZones::InfoZoneArray[NUMINFOZONES];\nCZone CTheZones::MapZoneArray[NUMMAPZONES];\nCZone CTheZones::NavigationZoneArray[NUMNAVIGZONES];\nuint16 CTheZones::TotalNumberOfZoneInfos;\nCZoneInfo CTheZones::ZoneInfoArray[2*NUMINFOZONES];\n\n\n#define SWAPF(a, b) { float t; t = a; a = b; b = t; }\n\nwchar*\nCZone::GetTranslatedName(void)\n{\n\treturn TheText.Get(name);\n}\n\nvoid\nCTheZones::Init(void)\n{\n\tint i, j;\n\tfor(i = 0; i < NUMAUDIOZONES; i++)\n\t\tAudioZoneArray[i] = -1;\n\tNumberOfAudioZones = 0;\n\n\tfor(i = 0; i < NUMNAVIGZONES; i++)\n\t\tmemset(&NavigationZoneArray[i], 0, sizeof(CZone));\n\n\tfor(i = 0; i < NUMINFOZONES; i++)\n\t\tmemset(&InfoZoneArray[i], 0, sizeof(CZone));\n\n\tint x = 1000/9;\n\tfor(i = 0; i < 2*NUMINFOZONES; i++){\n\t\t// Cars\n\n\t\tZoneInfoArray[i].carDensity = 10;\n\t\tZoneInfoArray[i].carThreshold[0] = x;\n\t\tZoneInfoArray[i].carThreshold[1] = ZoneInfoArray[i].carThreshold[0] + x;\n\t\tZoneInfoArray[i].carThreshold[2] = ZoneInfoArray[i].carThreshold[1] + x;\n\t\tZoneInfoArray[i].carThreshold[3] = ZoneInfoArray[i].carThreshold[2] + x;\n\t\tZoneInfoArray[i].carThreshold[4] = ZoneInfoArray[i].carThreshold[3] + x;\n\t\tZoneInfoArray[i].carThreshold[5] = ZoneInfoArray[i].carThreshold[4] + x;\n\t\tZoneInfoArray[i].carThreshold[6] = ZoneInfoArray[i].carThreshold[5] + x;\n\t\tZoneInfoArray[i].carThreshold[7] = ZoneInfoArray[i].carThreshold[6] + x;\n\t\tZoneInfoArray[i].carThreshold[8] = 1000;\n\n\t\tZoneInfoArray[i].boatThreshold[0] = 500;\n\t\tZoneInfoArray[i].boatThreshold[1] = 1000;\n\n\t\t// What's going on here? this looks more like density\n\t\tZoneInfoArray[i].copThreshold = 50;\n\t\tfor(j = 0; j < NUM_GANGS; j++)\n\t\t\tZoneInfoArray[i].gangThreshold[j] = ZoneInfoArray[i].copThreshold;\n\n\t\t// Peds\n\n\t\tZoneInfoArray[i].pedDensity = 12;\n\n\t\t// What's going on here? this looks more like density\n\t\tZoneInfoArray[i].copPedThreshold = 50;\n\t\tfor(j = 0; j < NUM_GANGS; j++)\n\t\t\tZoneInfoArray[i].gangPedThreshold[j] = ZoneInfoArray[i].copPedThreshold;\n\n\t\tZoneInfoArray[i].pedGroup = 0;\n\t}\n\n\tTotalNumberOfZoneInfos = 1;\t// why 1?\n\tTotalNumberOfNavigationZones = 1;\n\tTotalNumberOfInfoZones = 1;\n\n\tstrcpy(InfoZoneArray[0].name, \"CITYINF\");\n\tInfoZoneArray[0].minx = -2400.0f;\n\tInfoZoneArray[0].miny = -2000.0f;\n\tInfoZoneArray[0].minz = -500.0f;\n\tInfoZoneArray[0].maxx =  1600.0f;\n\tInfoZoneArray[0].maxy =  2000.0f;\n\tInfoZoneArray[0].maxz =  500.0f;\n\tInfoZoneArray[0].level = LEVEL_GENERIC;\n\tInfoZoneArray[0].type = ZONE_INFO;\n\n\tstrcpy(NavigationZoneArray[0].name, \"VICE_C\");\n\tNavigationZoneArray[0].minx = -2400.0f;\n\tNavigationZoneArray[0].miny = -2000.0f;\n\tNavigationZoneArray[0].minz = -500.0f;\n\tNavigationZoneArray[0].maxx =  1600.0f;\n\tNavigationZoneArray[0].maxy =  2000.0f;\n\tNavigationZoneArray[0].maxz =  500.0f;\n\tNavigationZoneArray[0].level = LEVEL_GENERIC;\n\tNavigationZoneArray[0].type = ZONE_DEFAULT;\n\n\tm_CurrLevel = LEVEL_GENERIC;\n\n\tfor(i = 0; i < NUMMAPZONES; i++){\n\t\tmemset(&MapZoneArray[i], 0, sizeof(CZone));\n\t\tMapZoneArray[i].type = ZONE_MAPZONE;\n\t}\n\tTotalNumberOfMapZones = 1;\n\tstrcpy(MapZoneArray[0].name, \"THEMAP\");\n\tMapZoneArray[0].minx = -2400.0f;\n\tMapZoneArray[0].miny = -2000.0f;\n\tMapZoneArray[0].minz = -500.0f;\n\tMapZoneArray[0].maxx =  1600.0f;\n\tMapZoneArray[0].maxy =  2000.0f;\n\tMapZoneArray[0].maxz =  500.0f;\n\tMapZoneArray[0].level = LEVEL_GENERIC;\n}\n\nvoid\nCTheZones::Update(void)\n{\n#ifdef SQUEEZE_PERFORMANCE\n\tif (CTimer::GetFrameCounter() % 5 != 0)\n\t\treturn;\n#endif\n\tCVector pos;\n\tpos = FindPlayerCoors();\n\tm_CurrLevel = GetLevelFromPosition(&pos);\n}\n\nvoid\nCTheZones::CreateZone(char *name, eZoneType type,\n\t              float minx, float miny, float minz,\n\t              float maxx, float maxy, float maxz,\n\t              eLevelName level)\n{\n\tchar tmpname[24];\n\tchar *p;\n\n\tif(minx > maxx) SWAPF(minx, maxx);\n\tif(miny > maxy) SWAPF(miny, maxy);\n\tif(minz > maxz) SWAPF(minz, maxz);\n\n\t// make upper case\n\tfor(p = name; *p; p++) if(islower(*p)) *p = toupper(*p);\n\n\tstrncpy(tmpname, name, 7);\n\ttmpname[7] = '\\0';\n\n\t// add zone\n\tswitch(type){\n\tcase ZONE_DEFAULT:\n\tcase ZONE_NAVIG:\n\t\tassert(TotalNumberOfNavigationZones < NUMNAVIGZONES);\n\t\tstrcpy(NavigationZoneArray[TotalNumberOfNavigationZones].name, tmpname);\n\t\tNavigationZoneArray[TotalNumberOfNavigationZones].type = type;\n\t\tNavigationZoneArray[TotalNumberOfNavigationZones].minx = minx;\n\t\tNavigationZoneArray[TotalNumberOfNavigationZones].miny = miny;\n\t\tNavigationZoneArray[TotalNumberOfNavigationZones].minz = minz;\n\t\tNavigationZoneArray[TotalNumberOfNavigationZones].maxx = maxx;\n\t\tNavigationZoneArray[TotalNumberOfNavigationZones].maxy = maxy;\n\t\tNavigationZoneArray[TotalNumberOfNavigationZones].maxz = maxz;\n\t\tNavigationZoneArray[TotalNumberOfNavigationZones].level = level;\n\t\tTotalNumberOfNavigationZones++;\n\t\tbreak;\n\tcase ZONE_INFO:\n\t\tassert(TotalNumberOfInfoZones < NUMINFOZONES);\n\t\tstrcpy(InfoZoneArray[TotalNumberOfInfoZones].name, tmpname);\n\t\tInfoZoneArray[TotalNumberOfInfoZones].type = type;\n\t\tInfoZoneArray[TotalNumberOfInfoZones].minx = minx;\n\t\tInfoZoneArray[TotalNumberOfInfoZones].miny = miny;\n\t\tInfoZoneArray[TotalNumberOfInfoZones].minz = minz;\n\t\tInfoZoneArray[TotalNumberOfInfoZones].maxx = maxx;\n\t\tInfoZoneArray[TotalNumberOfInfoZones].maxy = maxy;\n\t\tInfoZoneArray[TotalNumberOfInfoZones].maxz = maxz;\n\t\tInfoZoneArray[TotalNumberOfInfoZones].level = level;\n\t\tInfoZoneArray[TotalNumberOfInfoZones].zoneinfoDay = TotalNumberOfZoneInfos++;\n\t\tInfoZoneArray[TotalNumberOfInfoZones].zoneinfoNight = TotalNumberOfZoneInfos++;\n\t\tTotalNumberOfInfoZones++;\n\t\tbreak;\n\tcase ZONE_MAPZONE:\n\t\tassert(TotalNumberOfMapZones < NUMMAPZONES);\n\t\tstrcpy(MapZoneArray[TotalNumberOfMapZones].name, tmpname);\n\t\tMapZoneArray[TotalNumberOfMapZones].type = type;\n\t\tMapZoneArray[TotalNumberOfMapZones].minx = minx;\n\t\tMapZoneArray[TotalNumberOfMapZones].miny = miny;\n\t\tMapZoneArray[TotalNumberOfMapZones].minz = minz;\n\t\tMapZoneArray[TotalNumberOfMapZones].maxx = maxx;\n\t\tMapZoneArray[TotalNumberOfMapZones].maxy = maxy;\n\t\tMapZoneArray[TotalNumberOfMapZones].maxz = maxz;\n\t\tMapZoneArray[TotalNumberOfMapZones].level = level;\n\t\tTotalNumberOfMapZones++;\n\t\tbreak;\n\t}\n}\n\nvoid\nCTheZones::PostZoneCreation(void)\n{\n\tint i;\n\tfor(i = 1; i < TotalNumberOfNavigationZones; i++)\n\t\tInsertZoneIntoZoneHierarchy(&NavigationZoneArray[i]);\n\tInitialiseAudioZoneArray();\n#ifndef MASTER\n\tCheckZonesForOverlap();\n#endif\n}\n\nvoid\nCTheZones::CheckZonesForOverlap(void)\n{\n\tint i, j;\n\tchar str[116];\n\n\tfor(i = 1; i < TotalNumberOfInfoZones; i++){\n\t\tZoneIsEntirelyContainedWithinOtherZone(&InfoZoneArray[i], &InfoZoneArray[0]);\n\t\t\n\t\tfor(j = 1; j < TotalNumberOfInfoZones; j++)\n\t\t\tif(i != j && ZoneIsEntirelyContainedWithinOtherZone(&InfoZoneArray[i], &InfoZoneArray[j]))\n\t\t\t\tsprintf(str, \"Info zone %s contains %s\\n\", InfoZoneArray[j].name, InfoZoneArray[i].name);\n\t}\n}\n\nvoid\nCTheZones::InsertZoneIntoZoneHierarchy(CZone *zone)\n{\n\tzone->child = nil;\n\tzone->parent = nil;\n\tzone->next = nil;\n\tInsertZoneIntoZoneHierRecursive(zone, &NavigationZoneArray[0]);\n}\n\nbool\nCTheZones::InsertZoneIntoZoneHierRecursive(CZone *inner, CZone *outer)\n{\n\tint n;\n\tCZone *child, *next, *insert;\n\n\t// return false if inner was not inserted into outer\n\tif(outer == nil ||\n\t   !ZoneIsEntirelyContainedWithinOtherZone(inner, outer))\n\t\treturn false;\n\n\t// try to insert inner into children of outer\n\tfor(child = outer->child; child; child = child->next)\n\t\tif(InsertZoneIntoZoneHierRecursive(inner, child))\n\t\t\treturn true;\n\n\t// insert inner as child of outer\n\t// count number of outer's children contained within inner\n\tn = 0;\n\tfor(child = outer->child; child; child = child->next)\n\t\tif(ZoneIsEntirelyContainedWithinOtherZone(child, inner))\n\t\t\tn++;\n\tinner->next = outer->child;\n\tinner->parent = outer;\n\touter->child = inner;\n\t// move children from outer to inner\n\tif(n){\n\t\tinsert = inner;\n\t\tfor(child = inner->next; child; child = next){\n\t\t\tnext = child->next;\n\t\t\tif(ZoneIsEntirelyContainedWithinOtherZone(child,inner)){\n\t\t\t\tinsert->next = child->next;\n\t\t\t\tchild->parent = inner;\n\t\t\t\tchild->next = inner->child;\n\t\t\t\tinner->child = child;\n\t\t\t}else\n\t\t\t\tinsert = child;\n\t\t}\n\t}\n\n\treturn true;\n}\n\nbool\nCTheZones::ZoneIsEntirelyContainedWithinOtherZone(CZone *inner, CZone *outer)\n{\n\tchar tmp[100];\n\n\tif(inner->minx < outer->minx ||\n\t   inner->maxx > outer->maxx ||\n\t   inner->miny < outer->miny ||\n\t   inner->maxy > outer->maxy ||\n\t   inner->minz < outer->minz ||\n\t   inner->maxz > outer->maxz){\n\t\tCVector vmin(inner->minx, inner->miny, inner->minz);\n\t\tif(PointLiesWithinZone(&vmin, outer))\n\t\t\tsprintf(tmp, \"Overlapping zones %s and %s\\n\",\n\t\t\t      inner->name, outer->name);\n\t\tCVector vmax(inner->maxx, inner->maxy, inner->maxz);\n\t\tif(PointLiesWithinZone(&vmax, outer))\n\t\t\tsprintf(tmp, \"Overlapping zones %s and %s\\n\",\n\t\t\t      inner->name, outer->name);\n\t\treturn false;\n\t}\n\treturn true;\n}\n\nbool\nCTheZones::PointLiesWithinZone(const CVector *v, CZone *zone)\n{\n\treturn zone->minx <= v->x && v->x <= zone->maxx &&\n\t       zone->miny <= v->y && v->y <= zone->maxy &&\n\t       zone->minz <= v->z && v->z <= zone->maxz;\n}\n\neLevelName\nCTheZones::GetLevelFromPosition(CVector const *v)\n{\n\tint i;\n//\tchar tmp[116];\n//\tif(!PointLiesWithinZone(v, &MapZoneArray[0]))\n//\t\tsprintf(tmp, \"x = %.3f y= %.3f z = %.3f\\n\", v.x, v.y, v.z);\n\tfor(i = 1; i < TotalNumberOfMapZones; i++)\n\t\tif(PointLiesWithinZone(v, &MapZoneArray[i]))\n\t\t\treturn MapZoneArray[i].level;\n\treturn MapZoneArray[0].level;\n}\n\nCZone*\nCTheZones::FindInformationZoneForPosition(const CVector *v)\n{\n\tint i;\n//\tchar tmp[116];\n//\tif(!PointLiesWithinZone(v, &InfoZoneArray[0]))\n//\t\tsprintf(tmp, \"x = %.3f y= %.3f z = %.3f\\n\", v.x, v.y, v.z);\n\tfor(i = 1; i < TotalNumberOfInfoZones; i++)\n\t\tif(PointLiesWithinZone(v, &InfoZoneArray[i]))\n\t\t\treturn &InfoZoneArray[i];\n\treturn &InfoZoneArray[0];\n}\n\nCZone*\nCTheZones::FindSmallestNavigationZoneForPosition(const CVector *v, bool findDefault, bool findNavig)\n{\n\tCZone *best = nil;\n\tif(findDefault && NavigationZoneArray[0].type == ZONE_DEFAULT ||\n\t   findNavig && NavigationZoneArray[0].type == ZONE_NAVIG)\n\t\tbest = &NavigationZoneArray[0];\n\t// zone to test next\n\tCZone *zone = NavigationZoneArray[0].child;\n\twhile(zone)\n\t\t// if in zone, descent into children\n\t\tif(PointLiesWithinZone(v, zone)){\n\t\t\tif(findDefault && zone->type == ZONE_DEFAULT ||\n\t\t\t   findNavig && zone->type == ZONE_NAVIG)\n\t\t\t\tbest = zone;\n\t\t\tzone = zone->child;\n\t\t// otherwise try next zone\n\t\t}else\n\t\t\tzone = zone->next;\n\treturn best;\n}\n\nint16\nCTheZones::FindZoneByLabelAndReturnIndex(char *name, eZoneType type)\n{\n\tchar str[8];\n\tmemset(str, 0, 8);\n\tstrncpy(str, name, 8);\n\tswitch(type){\n\tcase ZONE_DEFAULT:\n\tcase ZONE_NAVIG:\n\t\tfor(FindIndex = 0; FindIndex < TotalNumberOfNavigationZones; FindIndex++)\n\t\t\tif(strcmp(GetNavigationZone(FindIndex)->name, name) == 0)\n\t\t\t\treturn FindIndex;\n\t\tbreak;\n\n\tcase ZONE_INFO:\n\t\tfor(FindIndex = 0; FindIndex < TotalNumberOfInfoZones; FindIndex++)\n\t\t\tif(strcmp(GetInfoZone(FindIndex)->name, name) == 0)\n\t\t\t\treturn FindIndex;\n\t\tbreak;\n\n\tcase ZONE_MAPZONE:\n\t\tfor(FindIndex = 0; FindIndex < TotalNumberOfMapZones; FindIndex++)\n\t\t\tif(strcmp(GetMapZone(FindIndex)->name, name) == 0)\n\t\t\t\treturn FindIndex;\n\t\tbreak;\n\t}\n\treturn -1;\n}\n\nint16\nCTheZones::FindNextZoneByLabelAndReturnIndex(char *name, eZoneType type)\n{\n\tchar str[8];\n\t++FindIndex;\n\tmemset(str, 0, 8);\n\tstrncpy(str, name, 8);\n\tswitch(type){\n\tcase ZONE_DEFAULT:\n\tcase ZONE_NAVIG:\n\t\tfor(; FindIndex < TotalNumberOfNavigationZones; FindIndex++)\n\t\t\tif(strcmp(GetNavigationZone(FindIndex)->name, name) == 0)\n\t\t\t\treturn FindIndex;\n\t\tbreak;\n\n\tcase ZONE_INFO:\n\t\tfor(; FindIndex < TotalNumberOfInfoZones; FindIndex++)\n\t\t\tif(strcmp(GetInfoZone(FindIndex)->name, name) == 0)\n\t\t\t\treturn FindIndex;\n\t\tbreak;\n\n\tcase ZONE_MAPZONE:\n\t\tfor(; FindIndex < TotalNumberOfMapZones; FindIndex++)\n\t\t\tif(strcmp(GetMapZone(FindIndex)->name, name) == 0)\n\t\t\t\treturn FindIndex;\n\t\tbreak;\n\t}\n\treturn -1;\n}\n\nCZoneInfo*\nCTheZones::GetZoneInfo(const CVector *v, uint8 day)\n{\n\tCZone *zone;\n\tzone = FindInformationZoneForPosition(v);\n\tif(zone == nil)\n\t\treturn &ZoneInfoArray[0];\n\treturn &ZoneInfoArray[day ? zone->zoneinfoDay : zone->zoneinfoNight];\n}\n\nvoid\nCTheZones::GetZoneInfoForTimeOfDay(const CVector *pos, CZoneInfo *info)\n{\n\tCZoneInfo *day, *night;\n\tfloat d, n;\n\tint i;\n\n\tday = GetZoneInfo(pos, 1);\n\tnight = GetZoneInfo(pos, 0);\n\n\tif(CClock::GetIsTimeInRange(8, 19))\n\t\t*info = *day;\n\telse if(CClock::GetIsTimeInRange(22, 5))\n\t\t*info = *night;\n\telse{\n\t\tif(CClock::GetIsTimeInRange(19, 22)){\n\t\t\tn = (CClock::GetHours() - 19) / 3.0f;\n\t\t\tassert(n >= 0.0f && n <= 1.0f);\n\t\t\td = 1.0f - n;\n\t\t}else{\n\t\t\td = (CClock::GetHours() - 5) / 3.0f;\n\t\t\tassert(d >= 0.0f && d <= 1.0f);\n\t\t\tn = 1.0f - d;\n\t\t}\n\t\tinfo->carDensity = day->carDensity * d + night->carDensity * n;\n\t\tfor(i = 0; i < ARRAY_SIZE(info->carThreshold); i++)\n\t\t\tinfo->carThreshold[i] = day->carThreshold[i] * d + night->carThreshold[i] * n;\n\t\tfor(i = 0; i < ARRAY_SIZE(info->boatThreshold); i++)\n\t\t\tinfo->boatThreshold[i] = day->boatThreshold[i] * d + night->boatThreshold[i] * n;\n\t\tfor(i = 0; i < ARRAY_SIZE(info->gangThreshold); i++)\n\t\t\tinfo->gangThreshold[i] = day->gangThreshold[i] * d + night->gangThreshold[i] * n;\n\n\t\tinfo->copThreshold = day->copThreshold * d + night->copThreshold * n;\n\t\tinfo->pedDensity = day->pedDensity * d + night->pedDensity * n;\n\t\tinfo->copPedThreshold = day->copPedThreshold * d + night->copPedThreshold * n;\n\t\tfor(i = 0; i < ARRAY_SIZE(info->gangPedThreshold); i++)\n\t\t\tinfo->gangPedThreshold[i] = day->gangPedThreshold[i] * d + night->gangPedThreshold[i] * n;\n\t}\n\tif(CClock::GetIsTimeInRange(5, 19))\n\t\tinfo->pedGroup = day->pedGroup;\n\telse\n\t\tinfo->pedGroup = night->pedGroup;\n}\n\nvoid\nCTheZones::SetZoneCarInfo(uint16 zoneid, uint8 day, int16 carDensity,\n\tint16 copCarDensity, const int16 *gangCarDensities)\n{\n\tCZone *zone;\n\tCZoneInfo *info;\n\tzone = GetInfoZone(zoneid);\n\tinfo = &ZoneInfoArray[day ? zone->zoneinfoDay : zone->zoneinfoNight];\n\n\tinfo->carDensity = carDensity;\n\tinfo->copThreshold = copCarDensity;\n\tinfo->gangThreshold[0] = gangCarDensities[0] + copCarDensity;\n\tinfo->gangThreshold[1] = gangCarDensities[1] + info->gangThreshold[0];\n\tinfo->gangThreshold[2] = gangCarDensities[2] + info->gangThreshold[1];\n\tinfo->gangThreshold[3] = gangCarDensities[3] + info->gangThreshold[2];\n\tinfo->gangThreshold[4] = gangCarDensities[4] + info->gangThreshold[3];\n\tinfo->gangThreshold[5] = gangCarDensities[5] + info->gangThreshold[4];\n\tinfo->gangThreshold[6] = gangCarDensities[6] + info->gangThreshold[5];\n\tinfo->gangThreshold[7] = gangCarDensities[7] + info->gangThreshold[6];\n\tinfo->gangThreshold[8] = gangCarDensities[8] + info->gangThreshold[7];\n}\n\nvoid CTheZones::SetZoneCivilianCarInfo(uint16 zoneid, uint8 day,\n\tconst int16* carDensities, const int16* boatDensities)\n{\n\tCZone* zone;\n\tCZoneInfo* info;\n\tzone = GetInfoZone(zoneid);\n\tinfo = &ZoneInfoArray[day ? zone->zoneinfoDay : zone->zoneinfoNight];\n\tinfo->carThreshold[0] = carDensities[0];\n\tfor (int i = 1; i < CCarCtrl::NUM_CAR_CLASSES; i++)\n\t\tinfo->carThreshold[i] = carDensities[i] + info->carThreshold[i-1];\n\tinfo->boatThreshold[0] = boatDensities[0];\n\tfor (int i = 1; i < CCarCtrl::NUM_BOAT_CLASSES; i++)\n\t\tinfo->boatThreshold[i] = boatDensities[i] + info->boatThreshold[i - 1];\n}\n\nvoid\nCTheZones::SetZonePedInfo(uint16 zoneid, uint8 day, int16 pedDensity,\n\tint16 gang0Density, int16 gang1Density, int16 gang2Density, int16 gang3Density,\n\tint16 gang4Density, int16 gang5Density, int16 gang6Density, int16 gang7Density,\n\tint16 gang8Density, int16 copDensity)\n{\n\tCZone *zone;\n\tCZoneInfo *info;\n\tzone = GetInfoZone(zoneid);\n\tinfo = &ZoneInfoArray[day ? zone->zoneinfoDay : zone->zoneinfoNight];\n\tinfo->pedDensity = pedDensity;\n\tinfo->copPedThreshold = copDensity;\n\tinfo->gangPedThreshold[0] = gang0Density;\n\tinfo->gangPedThreshold[1] = gang1Density;\n\tinfo->gangPedThreshold[2] = gang2Density;\n\tinfo->gangPedThreshold[3] = gang3Density;\n\tinfo->gangPedThreshold[4] = gang4Density;\n\tinfo->gangPedThreshold[5] = gang5Density;\n\tinfo->gangPedThreshold[6] = gang6Density;\n\tinfo->gangPedThreshold[7] = gang7Density;\n\tinfo->gangPedThreshold[8] = gang8Density;\n\n\tinfo->gangPedThreshold[0] += info->copPedThreshold;\n\tinfo->gangPedThreshold[1] += info->gangPedThreshold[0];\n\tinfo->gangPedThreshold[2] += info->gangPedThreshold[1];\n\tinfo->gangPedThreshold[3] += info->gangPedThreshold[2];\n\tinfo->gangPedThreshold[4] += info->gangPedThreshold[3];\n\tinfo->gangPedThreshold[5] += info->gangPedThreshold[4];\n\tinfo->gangPedThreshold[6] += info->gangPedThreshold[5];\n\tinfo->gangPedThreshold[7] += info->gangPedThreshold[6];\n\tinfo->gangPedThreshold[8] += info->gangPedThreshold[7];\n}\n\n// unused\nvoid\nCTheZones::SetCarDensity(uint16 zoneid, uint8 day, uint16 cardensity)\n{\n\tCZone *zone;\n\tzone = GetInfoZone(zoneid);\n\tZoneInfoArray[day ? zone->zoneinfoDay : zone->zoneinfoNight].carDensity = cardensity;\n}\n\n// unused\nvoid\nCTheZones::SetPedDensity(uint16 zoneid, uint8 day, uint16 peddensity)\n{\n\tCZone *zone;\n\tzone = GetInfoZone(zoneid);\n\tZoneInfoArray[day ? zone->zoneinfoDay : zone->zoneinfoNight].pedDensity = peddensity;\n}\n\nvoid\nCTheZones::SetPedGroup(uint16 zoneid, uint8 day, uint16 pedgroup)\n{\n\tCZone *zone;\n\tzone = GetInfoZone(zoneid);\n\tZoneInfoArray[day ? zone->zoneinfoDay : zone->zoneinfoNight].pedGroup = pedgroup;\n}\n\nint16\nCTheZones::FindAudioZone(CVector *pos)\n{\n\tint i;\n\n\tfor(i = 0; i < NumberOfAudioZones; i++)\n\t\tif(PointLiesWithinZone(pos, GetAudioZone(i)))\n\t\t\treturn i;\n\treturn -1;\n}\n\nvoid\nCTheZones::AddZoneToAudioZoneArray(CZone *zone)\n{\n\tint i, z;\n\n\tif(zone->type != ZONE_DEFAULT)\n\t\treturn;\n\n\t/* This is a bit stupid */\n\tz = -1;\n\tfor(i = 0; i < NUMNAVIGZONES; i++)\n\t\tif(&NavigationZoneArray[i] == zone)\n\t\t\tz = i;\n\tassert(NumberOfAudioZones < NUMAUDIOZONES);\n\tAudioZoneArray[NumberOfAudioZones++] = z;\n}\n\nvoid\nCTheZones::InitialiseAudioZoneArray(void)\n{\n\tbool gonext;\n\tCZone *zone;\n\n\tgonext = false;\n\tzone = &NavigationZoneArray[0];\n\t// Go deep first,\n\t// set gonext when backing up a level to visit the next child\n\twhile(zone)\n\t\tif(gonext){\n\t\t\tAddZoneToAudioZoneArray(zone);\n\t\t\tif(zone->next){\n\t\t\t\tgonext = false;\n\t\t\t\tzone = zone->next;\n\t\t\t}else\n\t\t\t\tzone = zone->parent;\n\t\t}else if(zone->child)\n\t\t\tzone = zone->child;\n\t\telse{\n\t\t\tAddZoneToAudioZoneArray(zone);\n\t\t\tif(zone->next)\n\t\t\t\tzone = zone->next;\n\t\t\telse{\n\t\t\t\tgonext = true;\n\t\t\t\tzone = zone->parent;\n\t\t\t}\n\t\t}\n}\n\nvoid\nCTheZones::SaveAllZones(uint8 *buffer, uint32 *size)\n{\n\tINITSAVEBUF\n\tint i;\n\n#define CZONE_SAVE_SIZE (sizeof(char)*8+sizeof(float)+sizeof(float)+sizeof(float)+sizeof(float)+sizeof(float)+sizeof(float)+sizeof(eZoneType)+sizeof(eLevelName)+sizeof(int16)+sizeof(int16)+sizeof(int32)+sizeof(int32)+sizeof(int32))\n\n\t*size = SAVE_HEADER_SIZE\n\t\t+ sizeof(m_CurrLevel) + sizeof(FindIndex)\n\t\t+ sizeof(int16) // padding\n\t\t+ CZONE_SAVE_SIZE * ARRAY_SIZE(NavigationZoneArray) + CZONE_SAVE_SIZE * ARRAY_SIZE(InfoZoneArray) + sizeof(ZoneInfoArray)\n\t\t+ sizeof(TotalNumberOfNavigationZones) + sizeof(TotalNumberOfInfoZones) + sizeof(TotalNumberOfZoneInfos)\n\t\t+ sizeof(int16) // padding\n\t\t+ CZONE_SAVE_SIZE * ARRAY_SIZE(MapZoneArray) + sizeof(AudioZoneArray)\n\t\t+ sizeof(TotalNumberOfMapZones) + sizeof(NumberOfAudioZones);\n#undef CZONE_SAVE_SIZE\n\n\tuint32 length = 0;\n\tWriteSaveHeaderWithLength(buffer, length, 'Z', 'N', 'S', '\\0', *size - SAVE_HEADER_SIZE);\n\n\tWriteSaveBuf(buffer, length, m_CurrLevel);\n\tWriteSaveBuf(buffer, length, FindIndex);\n\tWriteSaveBuf(buffer, length, (int16)0); // padding\n\n\tfor(i = 0; i < ARRAY_SIZE(NavigationZoneArray); i++)\n\t\tSaveOneZone(&NavigationZoneArray[i], &buffer, &length, ZONE_NAVIG);\n\n\tfor(i = 0; i < ARRAY_SIZE(InfoZoneArray); i++)\n\t\tSaveOneZone(&InfoZoneArray[i], &buffer, &length, ZONE_INFO);\n\n\tfor(i = 0; i < ARRAY_SIZE(ZoneInfoArray); i++)\n\t\tWriteSaveBuf(buffer, length, ZoneInfoArray[i]);\n\n\tWriteSaveBuf(buffer, length, TotalNumberOfNavigationZones);\n\tWriteSaveBuf(buffer, length, TotalNumberOfInfoZones);\n\tWriteSaveBuf(buffer, length, TotalNumberOfZoneInfos);\n\tWriteSaveBuf(buffer, length, (int16)0); // padding\n\n\tfor(i = 0; i < ARRAY_SIZE(MapZoneArray); i++)\n\t\tSaveOneZone(&MapZoneArray[i], &buffer, &length, ZONE_MAPZONE);\n\n\tfor(i = 0; i < ARRAY_SIZE(AudioZoneArray); i++)\n\t\tWriteSaveBuf(buffer, length, AudioZoneArray[i]);\n\n\tWriteSaveBuf(buffer, length, TotalNumberOfMapZones);\n\tWriteSaveBuf(buffer, length, NumberOfAudioZones);\n\n\tVALIDATESAVEBUF(*size)\n}\n\nvoid\nCTheZones::SaveOneZone(CZone *zone, uint8 **buffer, uint32 *length, eZoneType zoneType)\n{\n\tWriteSaveBuf(*buffer, *length, *(uint32*)&zone->name[0]);\n\tWriteSaveBuf(*buffer, *length, *(uint32*)&zone->name[4]);\n\n\tWriteSaveBuf(*buffer, *length, zone->minx);\n\tWriteSaveBuf(*buffer, *length, zone->miny);\n\tWriteSaveBuf(*buffer, *length, zone->minz);\n\tWriteSaveBuf(*buffer, *length, zone->maxx);\n\tWriteSaveBuf(*buffer, *length, zone->maxy);\n\tWriteSaveBuf(*buffer, *length, zone->maxz);\n\n\tWriteSaveBuf(*buffer, *length, zone->type);\n\tWriteSaveBuf(*buffer, *length, zone->level);\n\tWriteSaveBuf(*buffer, *length, zone->zoneinfoDay);\n\tWriteSaveBuf(*buffer, *length, zone->zoneinfoNight);\n\n\tint32 zoneId;\n\tzoneId = GetIndexForZonePointer(zone->child);\n\tWriteSaveBuf(*buffer, *length, zoneId);\n\tzoneId = GetIndexForZonePointer(zone->parent);\n\tWriteSaveBuf(*buffer, *length, zoneId);\n\tzoneId = GetIndexForZonePointer(zone->next);\n\tWriteSaveBuf(*buffer, *length, zoneId);\n}\n\nvoid\nCTheZones::LoadAllZones(uint8 *buffer, uint32 size)\n{\n\tINITSAVEBUF\n\tint i;\n\n\tuint32 length = 0;\n\tCheckSaveHeaderWithLength(buffer, length, 'Z', 'N', 'S', '\\0', size - SAVE_HEADER_SIZE);\n\n\tm_CurrLevel = ReadSaveBuf<eLevelName>(buffer, length);\n\tFindIndex = ReadSaveBuf<int16>(buffer, length);\n\tReadSaveBuf<int16>(buffer, length);\n\n\tfor(i = 0; i < ARRAY_SIZE(NavigationZoneArray); i++)\n\t\tLoadOneZone(&NavigationZoneArray[i], &buffer, &length, ZONE_NAVIG);\n\n\tfor (i = 0; i < ARRAY_SIZE(InfoZoneArray); i++)\n\t\tLoadOneZone(&InfoZoneArray[i], &buffer, &length, ZONE_INFO);\n\n\tfor(i = 0; i < ARRAY_SIZE(ZoneInfoArray); i++)\n\t\tZoneInfoArray[i] = ReadSaveBuf<CZoneInfo>(buffer, length);\n\n\tTotalNumberOfNavigationZones = ReadSaveBuf<int16>(buffer, length);\n\tTotalNumberOfInfoZones = ReadSaveBuf<int16>(buffer, length);\n\tTotalNumberOfZoneInfos = ReadSaveBuf<int16>(buffer, length);\n\tReadSaveBuf<int16>(buffer, length);\n\n\tfor(i = 0; i < ARRAY_SIZE(MapZoneArray); i++)\n\t\tLoadOneZone(&MapZoneArray[i], &buffer, &length, ZONE_MAPZONE);\n\n\tfor(i = 0; i < ARRAY_SIZE(AudioZoneArray); i++)\n\t\tAudioZoneArray[i] = ReadSaveBuf<int16>(buffer, length);\n\n\tTotalNumberOfMapZones = ReadSaveBuf<uint16>(buffer, length);\n\tNumberOfAudioZones = ReadSaveBuf<uint16>(buffer, length);\n\n\tVALIDATESAVEBUF(size)\n}\n\nvoid\nCTheZones::LoadOneZone(CZone *zone, uint8 **buffer, uint32 *length, eZoneType zoneType)\n{\n\t*(uint32*)&zone->name[0] = ReadSaveBuf<uint32>(*buffer, *length);\n\t*(uint32*)&zone->name[4] = ReadSaveBuf<uint32>(*buffer, *length);\n\n\tzone->minx = ReadSaveBuf<float>(*buffer, *length);\n\tzone->miny = ReadSaveBuf<float>(*buffer, *length);\n\tzone->minz = ReadSaveBuf<float>(*buffer, *length);\n\tzone->maxx = ReadSaveBuf<float>(*buffer, *length);\n\tzone->maxy = ReadSaveBuf<float>(*buffer, *length);\n\tzone->maxz = ReadSaveBuf<float>(*buffer, *length);\n\n\tzone->type = ReadSaveBuf<eZoneType>(*buffer, *length);\n\tzone->level = ReadSaveBuf<eLevelName>(*buffer, *length);\n\tzone->zoneinfoDay = ReadSaveBuf<int16>(*buffer, *length);\n\tzone->zoneinfoNight = ReadSaveBuf<int16>(*buffer, *length);\n\n\tint32 zoneId;\n\tzoneId = ReadSaveBuf<int32>(*buffer, *length);\n\tzone->child = GetPointerForZoneIndex(zoneId);\n\tzoneId = ReadSaveBuf<int32>(*buffer, *length);\n\tzone->parent = GetPointerForZoneIndex(zoneId);\n\tzoneId = ReadSaveBuf<int32>(*buffer, *length);\n\tzone->next = GetPointerForZoneIndex(zoneId);\n}"
  },
  {
    "path": "src/core/Zones.h",
    "content": "#pragma once\n\n#include \"Game.h\"\n#include \"Gangs.h\"\n#include \"CarCtrl.h\"\n\nenum eZoneType\n{\n\tZONE_DEFAULT,\n\tZONE_NAVIG,\n\tZONE_INFO,\n\tZONE_MAPZONE,\n};\n\nclass CZone\n{\npublic:\n\tchar       name[8];\n\tfloat      minx;\n\tfloat      miny;\n\tfloat      minz;\n\tfloat      maxx;\n\tfloat      maxy;\n\tfloat      maxz;\n\teZoneType  type;\n\teLevelName level;\n\tint16      zoneinfoDay;\n\tint16      zoneinfoNight;\n\tCZone     *child;\n\tCZone     *parent;\n\tCZone     *next;\n\n\twchar *GetTranslatedName(void);\n};\n\nclass CZoneInfo\n{\npublic:\n\t// Car data\n\tint16 carDensity;\n\tint16 carThreshold[CCarCtrl::NUM_CAR_CLASSES];\n\tint16 boatThreshold[CCarCtrl::NUM_BOAT_CLASSES];\n\tint16 gangThreshold[NUM_GANGS];\n\tint16 copThreshold;\n\n\t// Ped data\n\tuint16 pedDensity;\n\tuint16 gangPedThreshold[NUM_GANGS];\n\tuint16 copPedThreshold;\n\tuint16 pedGroup;\n};\n\n\nclass CTheZones\n{\n\tstatic int16 FindIndex;\n\n\tstatic uint16 NumberOfAudioZones;\n\tstatic int16 AudioZoneArray[NUMAUDIOZONES];\n\tstatic uint16 TotalNumberOfMapZones;\n\tstatic uint16 TotalNumberOfInfoZones;\n\tstatic uint16 TotalNumberOfNavigationZones;\n\tstatic CZone InfoZoneArray[NUMINFOZONES];\n\tstatic CZone MapZoneArray[NUMMAPZONES];\n\tstatic CZone NavigationZoneArray[NUMNAVIGZONES];\n\tstatic uint16 TotalNumberOfZoneInfos;\n\tstatic CZoneInfo ZoneInfoArray[2*NUMINFOZONES];\npublic:\n\tstatic eLevelName m_CurrLevel;\n\n\tstatic void Init(void);\n\tstatic void Update(void);\n\tstatic void CreateZone(char *name, eZoneType type,\n\t                       float minx, float miny, float minz,\n\t                       float maxx, float maxy, float maxz,\n\t                       eLevelName level);\n\tstatic CZone *GetInfoZone(uint16 i) { return &InfoZoneArray[i]; }\n\tstatic CZone *GetNavigationZone(uint16 i) { return &NavigationZoneArray[i]; }\n\tstatic CZone *GetMapZone(uint16 i) { return &MapZoneArray[i]; }\n\tstatic CZone *GetAudioZone(uint16 i) { return &NavigationZoneArray[AudioZoneArray[i]]; }\n\tstatic void PostZoneCreation(void);\n\tstatic void CheckZonesForOverlap(void);\n\tstatic void InsertZoneIntoZoneHierarchy(CZone *zone);\n\tstatic bool InsertZoneIntoZoneHierRecursive(CZone *z1, CZone *z2);\n\tstatic bool ZoneIsEntirelyContainedWithinOtherZone(CZone *z1, CZone *z2);\n\tstatic bool PointLiesWithinZone(const CVector *v, CZone *zone);\n\tstatic eLevelName GetLevelFromPosition(const CVector *v);\n\tstatic CZone *FindInformationZoneForPosition(const CVector *v);\n\tstatic CZone *FindSmallestNavigationZoneForPosition(const CVector *v, bool findDefault, bool findNavig);\n\tstatic int16 FindZoneByLabelAndReturnIndex(char *name, eZoneType type);\n\tstatic int16 FindNextZoneByLabelAndReturnIndex(char *name, eZoneType type);\n\tstatic CZoneInfo *GetZoneInfo(const CVector *v, uint8 day);\n\tstatic void GetZoneInfoForTimeOfDay(const CVector *pos, CZoneInfo *info);\n\tstatic void SetZoneCarInfo(uint16 zoneid, uint8 day, int16 carDensity,\n\t\tint16 copCarDensity, const int16 *gangCarDensities /*[NUMGANGS]*/);\n\tstatic void SetZoneCivilianCarInfo(uint16 zoneid, uint8 day,\n\t\tconst int16* carDensities, const int16* boatDensities);\n\tstatic void SetZonePedInfo(uint16 zoneid, uint8 day, int16 pedDensity,\n\t\tint16 gang0Density, int16 gang1Density, int16 gang2Density, int16 gang3Density,\n\t\tint16 gang4Density, int16 gang5Density, int16 gang6Density, int16 gang7Density,\n\t\tint16 gang8Density, int16 copDensity);\n\tstatic void SetCarDensity(uint16 zoneid, uint8 day, uint16 cardensity);\n\tstatic void SetPedDensity(uint16 zoneid, uint8 day, uint16 peddensity);\n\tstatic void SetPedGroup(uint16 zoneid, uint8 day, uint16 pedgroup);\n\tstatic int16 FindAudioZone(CVector *pos);\n\tstatic CZone *GetPointerForZoneIndex(ssize_t i) { return i == -1 ? nil : &NavigationZoneArray[i]; }\n\tstatic ssize_t GetIndexForZonePointer(CZone *zone) { return zone == nil ? -1 : zone - NavigationZoneArray; }\n\tstatic void AddZoneToAudioZoneArray(CZone *zone);\n\tstatic void InitialiseAudioZoneArray(void);\n\tstatic void SaveAllZones(uint8 *buffer, uint32 *length);\n\tstatic void SaveOneZone(CZone *zone, uint8 **buffer, uint32 *length, eZoneType zoneType);\n\tstatic void LoadAllZones(uint8 *buffer, uint32 length);\n\tstatic void LoadOneZone(CZone *zone, uint8 **buffer, uint32 *length, eZoneType zoneType);\n};\n"
  },
  {
    "path": "src/core/common.h",
    "content": "#pragma once\n\n#define _CRT_SECURE_NO_WARNINGS\n#define _USE_MATH_DEFINES\n#pragma warning(disable: 4244)\t// int to float\n#pragma warning(disable: 4800)\t// int to bool\n#pragma warning(disable: 4838)  // narrowing conversion\n#pragma warning(disable: 4996)  // POSIX names\n\n#ifdef __MWERKS__\n#define __STDC_LIMIT_MACROS // so we get UINT32_MAX etc\n#endif\n\n#include <stdint.h>\n#include <string.h>\n#include <math.h>\n\n#ifdef __MWERKS__\n#define AUDIO_MSS\n#define RWLIBS // codewarrior doesn't support project level defines - so not even this is enough, but still catches most ifdefs\n#endif\n\n#if !defined RW_D3D9 && defined LIBRW\n#undef WITHD3D\n#undef WITHDINPUT\n#endif\n\n#if (defined WITHD3D && !defined LIBRW)\n#define WITHWINDOWS\n#endif\n\n#if defined _WIN32 && defined WITHWINDOWS && !defined _INC_WINDOWS\n#include <windows.h>\n#endif\n\n#ifdef WITHD3D\n\t#ifdef LIBRW\n\t\t#define WITH_D3D // librw includes d3d9 itself via this right now\n\t#else\n\t\t#ifndef USE_D3D9\n\t\t#include <d3d8.h>\n\t\t#else\n\t\t#include <d3d9.h>\n\t\t#endif\n\t#endif\n#endif\n\n#ifdef WITHDINPUT\n#define DIRECTINPUT_VERSION 0x0800\n#include <dinput.h>\n#endif\n\n#include <rwcore.h>\n#include <rpworld.h>\n\n// gotta put this somewhere\n#ifdef LIBRW\n#define STREAMPOS(str) ((str)->tell())\n#define STREAMFILE(str) (((rw::StreamFile*)(str))->file)\n#define HIERNODEINFO(hier) ((hier)->nodeInfo)\n#define HIERNODEID(hier, i) ((hier)->nodeInfo[i].id)\n#define HANIMFRAME(anim, i) ((RwUInt8*)(anim)->keyframes + (i)*(anim)->interpInfo->animKeyFrameSize)\n#else\n#define RWHALFPIXEL\t// always d3d\n#define STREAMPOS(str) ((str)->Type.memory.position)\n#define STREAMFILE(str) ((str)->Type.file.fpFile)\n#define HIERNODEINFO(hier) ((hier)->pNodeInfo)\n#define HIERNODEID(hier, i) ((hier)->pNodeInfo[i].nodeID)\n#define HANIMFRAME(anim, i) ((RwUInt8*)(anim)->pFrames + (i)*(anim)->interpInfo->keyFrameSize)\n#define RpHAnimStdInterpFrame RpHAnimStdKeyFrame\n#endif\n\n#ifdef RWHALFPIXEL\n#define HALFPX (0.5f)\n#else\n#define HALFPX (0.0f)\n#endif\n\n#define rwVENDORID_ROCKSTAR 0x0253F2\n\n#define Max(a,b) ((a) > (b) ? (a) : (b))\n#define Min(a,b) ((a) < (b) ? (a) : (b))\n\n// Use this to add const that wasn't there in the original code\n#define Const const\n\ntypedef uint8_t uint8;\ntypedef int8_t int8;\ntypedef uint16_t uint16;\ntypedef int16_t int16;\n#ifndef __MWERKS__\ntypedef uint32_t uint32;\ntypedef int32_t int32;\n#else\ntypedef unsigned int uint32;\ntypedef int int32;\n#endif\ntypedef uintptr_t uintptr;\ntypedef intptr_t intptr;\ntypedef uint64_t uint64;\ntypedef int64_t int64;\n// hardcode ucs-2\ntypedef uint16_t wchar;\n\ntypedef uint8 bool8;\ntypedef uint16 bool16;\ntypedef uint32 bool32;\n\n#if defined(_MSC_VER) || defined (__MWERKS__)\ntypedef ptrdiff_t ssize_t;\n#endif\n\n#ifndef nil\n#define nil NULL\n#endif\n\n#include \"config.h\"\n\n#include <rphanim.h>\n#include <rpskin.h>\n\n#ifdef __GNUC__\n#define TYPEALIGN(n) __attribute__ ((aligned (n)))\n#else\n#ifdef _MSC_VER\n#define TYPEALIGN(n) __declspec(align(n))\n#else\n#define TYPEALIGN(n)\t// unknown compiler...ignore\n#endif\n#endif\n\n#define ALIGNPTR(p) (void*)((((uintptr)(void*)p) + sizeof(void*)-1) & ~(sizeof(void*)-1))\n\n// PDP-10 like byte functions\n#define MASK(p, s) (((1<<(s))-1) << (p))\ninline uint32 dpb(uint32 b, uint32 p, uint32 s, uint32 w)\n{\n\tuint32 m = MASK(p,s);\n\treturn (w & ~m) | ((b<<p) & m);\n}\ninline uint32 ldb(uint32 p, uint32 s, uint32 w)\n{\n\treturn w>>p & (1<<s)-1;\n}\n\n#include \"skeleton.h\"\n#include \"Draw.h\"\n\n#if defined(PROPER_SCALING)\n\t#ifdef FORCE_PC_SCALING\n\t\t#define DEFAULT_SCREEN_WIDTH  (640)\n\t\t#define DEFAULT_SCREEN_HEIGHT (448)\n\t#else\n\t\t#define DEFAULT_SCREEN_WIDTH  (640)\n\t\t#define DEFAULT_SCREEN_HEIGHT (480)\n\t#endif\n#elif defined(GTA_PS2)\n\t\t#define DEFAULT_SCREEN_WIDTH  (640)\n\t\t#define DEFAULT_SCREEN_HEIGHT (480)\n#else //elif defined(GTA_PC)\n\t\t#define DEFAULT_SCREEN_WIDTH  (640)\n\t\t#define DEFAULT_SCREEN_HEIGHT (448)\n#endif\n\n#define DEFAULT_ASPECT_RATIO (4.0f/3.0f)\n#define DEFAULT_VIEWWINDOW (0.7f)\n\n// game uses maximumWidth/Height, but this probably won't work\n// with RW windowed mode\n#ifdef GTA_PS2\n\t#ifdef GTA_PAL\n\t\t#define SCREEN_WIDTH  ((float)640)\n\t\t#define SCREEN_HEIGHT ((float)512)\n\t#else\n\t\t#define SCREEN_WIDTH  ((float)640)\n\t\t#define SCREEN_HEIGHT ((float)448)\n\t#endif\n#else\n#define SCREEN_WIDTH  ((float)RsGlobal.width)\n#define SCREEN_HEIGHT ((float)RsGlobal.height)\n#endif\n\n#define SCREEN_HEIGHT_PAL ((float)512)\n#define SCREEN_HEIGHT_NTSC ((float)448)\n\n#define SCREEN_ASPECT_RATIO (CDraw::GetAspectRatio())\n#define SCREEN_VIEWWINDOW (Tan(DEGTORAD(CDraw::GetScaledFOV() * 0.5f)))\n\n// This scales from PS2 pixel coordinates to the real resolution\n#define SCREEN_STRETCH_X(a)   ((a) * (float) SCREEN_WIDTH / DEFAULT_SCREEN_WIDTH)\n#define SCREEN_STRETCH_Y(a)   ((a) * (float) SCREEN_HEIGHT / DEFAULT_SCREEN_HEIGHT)\n#define SCREEN_STRETCH_FROM_RIGHT(a)  (SCREEN_WIDTH - SCREEN_STRETCH_X(a))\n#define SCREEN_STRETCH_FROM_BOTTOM(a) (SCREEN_HEIGHT - SCREEN_STRETCH_Y(a))\n\n// This scales from PS2 pixel coordinates while optionally maintaining the aspect ratio\n#define SCREEN_SCALE_X(a) SCREEN_SCALE_AR(SCREEN_STRETCH_X(a))\n#define SCREEN_SCALE_Y(a) SCREEN_STRETCH_Y(a)\n#define SCREEN_SCALE_FROM_RIGHT(a) (SCREEN_WIDTH - SCREEN_SCALE_X(a))\n#define SCREEN_SCALE_FROM_BOTTOM(a) (SCREEN_HEIGHT - SCREEN_SCALE_Y(a))\n\n#ifdef ASPECT_RATIO_SCALE\n#define SCREEN_SCALE_AR(a) ((a) * DEFAULT_ASPECT_RATIO / SCREEN_ASPECT_RATIO)\n#define SCALE_AND_CENTER_X(x) ((SCREEN_WIDTH == DEFAULT_SCREEN_WIDTH) ? (x) : (SCREEN_WIDTH - SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH)) / 2 + SCREEN_SCALE_X((x)))\n#ifdef PROPER_SCALING\n\t#ifndef FORCE_PC_SCALING\t\t\t\n\t\t#undef SCREEN_SCALE_Y\t\n\t\t#define SCREEN_SCALE_Y(a) CDraw::ScaleY(SCREEN_STRETCH_Y(a))\t\n\t#endif\n#endif\n#else\n#define SCREEN_SCALE_AR(a) (a)\n#define SCALE_AND_CENTER_X(x) SCREEN_STRETCH_X(x)\n#endif\n\n#include \"maths.h\"\n#include \"Vector.h\"\n#include \"Vector2D.h\"\n#include \"Matrix.h\"\n#include \"Rect.h\"\n\nclass CRGBA\n{\npublic:\n\tunion\n\t{\n\t    uint32 color32;\n\t\tstruct { uint8 r, g, b, a; };\n\t\tstruct { uint8 red, green, blue, alpha; };\n#ifdef RWCORE_H\n\t\tstruct  { RwRGBA rwRGBA; };\n#endif\n\t};\n\t\n\tCRGBA(void) { }\n\tCRGBA(uint8 r, uint8 g, uint8 b, uint8 a) : r(r), g(g), b(b), a(a) { }\n\t\n\tbool operator ==(const CRGBA &right)\n\t{\n\t\treturn this->r == right.r && this->g == right.g && this->b == right.b && this->a == right.a;\n\t}\n\t\n\tbool operator !=(const CRGBA &right)\n\t{\n\t\treturn !(*this == right);\n\t}\n\t\n\tCRGBA &operator =(const CRGBA &right)\n\t{\n\t\tthis->r = right.r;\n\t\tthis->g = right.g;\n\t\tthis->b = right.b;\n\t\tthis->a = right.a;\n\t\treturn *this;\n\t}\n#ifdef RWCORE_H\n\toperator RwRGBA &(void) {\n\t\treturn rwRGBA;\n\t}\n\t\n\toperator RwRGBA *(void) {\n\t\treturn &rwRGBA;\n\t}\n\t\n\toperator RwRGBA (void) const {\n\t\treturn rwRGBA;\n\t}\n\n\tCRGBA &operator =(const RwRGBA &right)\n\t{\n\t\tthis->r = right.red;\n\t\tthis->g = right.green;\n\t\tthis->b = right.blue;\n\t\tthis->a = right.alpha;\n\t\treturn *this;\n\t}\n#endif\n};\n\n#if (defined(_MSC_VER))\nextern int strcasecmp(const char *str1, const char *str2);\nextern int strncasecmp(const char *str1, const char *str2, size_t len);\n#endif\n\nextern wchar *AllocUnicode(const char*src);\n\n#define clamp(v, low, high) ((v)<(low) ? (low) : (v)>(high) ? (high) : (v))\n\n#define clamp2(v, center, radius) ((v) < (center) ? Max(v, center - radius) : Min(v, center + radius))\n\ninline float sq(float x) { return x*x; }\n#define SQR(x) ((x) * (x))\n\n#ifdef __MWERKS__\n#define M_E        2.71828182845904523536   // e\n#define M_LOG2E    1.44269504088896340736   // log2(e)\n#define M_LOG10E   0.434294481903251827651  // log10(e)\n#define M_LN2      0.693147180559945309417  // ln(2)\n#define M_LN10     2.30258509299404568402   // ln(10)\n#define M_PI       3.14159265358979323846   // pi\n#define M_PI_2     1.57079632679489661923   // pi/2\n#define M_PI_4     0.785398163397448309616  // pi/4\n#define M_1_PI     0.318309886183790671538  // 1/pi\n#define M_2_PI     0.636619772367581343076  // 2/pi\n#define M_2_SQRTPI 1.12837916709551257390   // 2/sqrt(pi)\n#define M_SQRT2    1.41421356237309504880   // sqrt(2)\n#define M_SQRT1_2  0.707106781186547524401  // 1/sqrt(2)\n#endif\n\n#define PI (float)M_PI\n#define TWOPI (PI*2)\n#define HALFPI (PI/2)\n#define DEGTORAD(x) ((x) * PI / 180.0f)\n#define RADTODEG(x) ((x) * 180.0f / PI)\n\n#ifdef USE_PS2_RAND\n#define MYRAND_MAX\t\t65535\n#else\n#define MYRAND_MAX\t\t32767\n#endif\n\nint myrand(void);\nvoid mysrand(unsigned int seed);\n\nvoid re3_debug(const char *format, ...);\nvoid re3_trace(const char *filename, unsigned int lineno, const char *func, const char *format, ...);\nvoid re3_assert(const char *expr, const char *filename, unsigned int lineno, const char *func);\nvoid re3_usererror(const char *format, ...);\n\n#define DEBUGBREAK() __debugbreak();\n\n// Switch to enable development messages.\n#if 1 \n#define DEV(f, ...)\n#else\n#define DEV(f, ...)   re3_debug(\"[DEV]: \" f, ## __VA_ARGS__)\n#endif\n\n#ifdef __MWERKS__\nvoid debug(char *f, ...);\nvoid Error(char *f, ...);\n__inline__ void TRACE(char *f, ...) { } // this is re3 only, and so the function needs to be inline - this way no call actually gets placed\n// USERERROR only gets used in oal builds ... once\n#else\n#define debug(f, ...) re3_debug(\"[DBG]: \" f, ## __VA_ARGS__)\n#define Error(f, ...) re3_debug(\"[ERROR]: \" f, ## __VA_ARGS__)\n#ifndef MASTER\n#define TRACE(f, ...) re3_trace(__FILE__, __LINE__, __FUNCTION__, f, ## __VA_ARGS__)\n#define USERERROR(f, ...) re3_usererror(f, ## __VA_ARGS__)\n#else\n#define TRACE(f, ...)\n#define USERERROR(f, ...)\n#endif\n#endif\n\n#ifndef MASTER\n#define assert(_Expression) (void)( (!!(_Expression)) || (re3_assert(#_Expression, __FILE__, __LINE__, __FUNCTION__), 0) )\n#else\n#define assert(_Expression) (_Expression)\n#endif\n#define ASSERT assert\n\n#ifdef __MWERKS__\n#define static_assert(bool_constexpr, message)\n#endif\n\n#define _TODO(x)\n#define _TODOCONST(x) (x)\n\n#ifdef CHECK_STRUCT_SIZES \n#define VALIDATE_SIZE(struc, size) static_assert(sizeof(struc) == size, \"Invalid structure size of \" #struc)\n#else\n#define VALIDATE_SIZE(struc, size)\n#endif\n#define VALIDATE_OFFSET(struc, member, offset) static_assert(offsetof(struc, member) == offset, \"The offset of \" #member \" in \" #struc \" is not \" #offset \"...\")\n\n#define PERCENT(x, p)                    ((float(x) * (float(p) / 100.0f)))\n#define ARRAY_SIZE(array)                (sizeof(array) / sizeof(array[0]))\n#define BIT(num)                         (1<<(num))\n\n#define ABS(a)  (((a) < 0) ? (-(a)) : (a))\n#define norm(value, min, max) (((value) < (min)) ? 0 : (((value) > (max)) ? 1 : (((value) - (min)) / ((max) - (min)))))\n#define lerp(norm, min, max) ( (norm) * ((max) - (min)) + (min) )\n\n#define STRINGIFY(x)                    #x\n#define STR(x)                          STRINGIFY(x)\n#define CONCAT_(x,y) x##y\n#define CONCAT(x,y) CONCAT_(x,y)\n\n#ifdef DEBUGMENU\n// Tweaking stuff for debugmenu\n#define TWEAKPATH                                   ___tw___TWEAKPATH\n#define SETTWEAKPATH(path)\t                        static const char *___tw___TWEAKPATH = path;\n#define TWEAKFUNC(v)                                static CTweakFunc   CONCAT(___tw___tweak, __COUNTER__)(&v, STR(v), TWEAKPATH);\n#define TWEAKFUNCN(v, name)                         static CTweakFunc   CONCAT(___tw___tweak, __COUNTER__)(&v, name, TWEAKPATH);\n#define TWEAKBOOL(v)                                static CTweakBool   CONCAT(___tw___tweak, __COUNTER__)(&v, STR(v), TWEAKPATH);\n#define TWEAKBOOLN(v, name)                         static CTweakBool   CONCAT(___tw___tweak, __COUNTER__)(&v, name, TWEAKPATH);\n#define TWEAKINT32(v, lower, upper, step)           static CTweakInt32  CONCAT(___tw___tweak, __COUNTER__)(&v, STR(v), lower, upper, step, TWEAKPATH);\n#define TWEAKINT32N(v, lower, upper, step, name)    static CTweakInt32  CONCAT(___tw___tweak, __COUNTER__)(&v, name, lower, upper, step, TWEAKPATH);\n#define TWEAKUINT32(v, lower, upper, step)          static CTweakUInt32 CONCAT(___tw___tweak, __COUNTER__)(&v, STR(v), lower, upper, step, TWEAKPATH);\n#define TWEAKUINT32N(v, lower, upper, step, name)   static CTweakUInt32 CONCAT(___tw___tweak, __COUNTER__)(&v, name, lower, upper, step, TWEAKPATH);\n#define TWEAKINT16(v, lower, upper, step)           static CTweakInt16  CONCAT(___tw___tweak, __COUNTER__)(&v, STR(v), lower, upper, step, TWEAKPATH);\n#define TWEAKINT16N(v, lower, upper, step, name)    static CTweakInt16  CONCAT(___tw___tweak, __COUNTER__)(&v, name, lower, upper, step, TWEAKPATH);\n#define TWEAKUINT16(v, lower, upper, step)          static CTweakUInt16 CONCAT(___tw___tweak, __COUNTER__)(&v, STR(v), lower, upper, step, TWEAKPATH);\n#define TWEAKUINT16N(v, lower, upper, step, name)   static CTweakUInt16 CONCAT(___tw___tweak, __COUNTER__)(&v, name, lower, upper, step, TWEAKPATH);\n#define TWEAKINT8(v, lower, upper, step)            static CTweakInt8   CONCAT(___tw___tweak, __COUNTER__)(&v, STR(v), lower, upper, step, TWEAKPATH);\n#define TWEAKINT8N(v, lower, upper, step, name)     static CTweakInt8   CONCAT(___tw___tweak, __COUNTER__)(&v, name, lower, upper, step, TWEAKPATH);\n#define TWEAKUINT8(v, lower, upper, step)           static CTweakUInt8  CONCAT(___tw___tweak, __COUNTER__)(&v, STR(v), lower, upper, step, TWEAKPATH);\n#define TWEAKUINT8N(v, lower, upper, step, name)    static CTweakUInt8  CONCAT(___tw___tweak, __COUNTER__)(&v, name, lower, upper, step, TWEAKPATH);\n#define TWEAKFLOAT(v, lower, upper, step)           static CTweakFloat  CONCAT(___tw___tweak, __COUNTER__)(&v, STR(v), lower, upper, step, TWEAKPATH);\n#define TWEAKFLOATN(v, lower, upper, step, name)    static CTweakFloat  CONCAT(___tw___tweak, __COUNTER__)(&v, name, lower, upper, step, TWEAKPATH);\n#define TWEAKSWITCH(v, lower, upper, str, f)        static CTweakSwitch CONCAT(___tw___tweak, __COUNTER__)(&v, STR(v), lower, upper, str, f, TWEAKPATH);\n#define TWEAKSWITCHN(v, lower, upper, str, f, name) static CTweakSwitch CONCAT(___tw___tweak, __COUNTER__)(&v, name, lower, upper, str, f, TWEAKPATH);\n\n// interface\nclass CTweakVar\n{\npublic:\n\tvirtual void AddDBG(const char *path) = 0;\n};\n\nclass CTweakVars\n{\npublic:\n\tstatic void Add(CTweakVar *var);\n\tstatic void AddDBG(const char *path);\n};\n\nclass CTweakFunc : public CTweakVar\n{\n\tconst char *m_pPath, *m_pVarName;\n\tvoid (*m_pFunc)();\npublic:\n\tCTweakFunc(void (*pFunc)(), const char *strName, const char *strPath) :\n\t\tm_pPath(strPath), m_pVarName(strName), m_pFunc(pFunc)\n\t{\n\t\tCTweakVars::Add(this);\n\t}\n\t\n\tvoid AddDBG(const char *path);\n};\n\nclass CTweakBool : public CTweakVar\n{\n\tconst char *m_pPath, *m_pVarName;\n\tbool *m_pBoolVar;\npublic:\n\tCTweakBool(bool *pBool, const char *strName, const char *strPath) :\n\t\tm_pPath(strPath), m_pVarName(strName), m_pBoolVar(pBool)\n\t{\n\t\tCTweakVars::Add(this);\n\t}\n\t\n\tvoid AddDBG(const char *path);\n};\n\nclass CTweakSwitch : public CTweakVar\n{\n\tconst char *m_pPath, *m_pVarName;\n\tvoid *m_pIntVar;\n\tint32 m_nMin, m_nMax;\n\tconst char **m_aStr;\n\tvoid (*m_pFunc)();\npublic:\n\tCTweakSwitch(void *pInt, const char *strName, int32 nMin, int32 nMax, const char **aStr,\n\t             void (*pFunc)(), const char *strPath)\n\t    : m_pPath(strPath), m_pVarName(strName), m_pIntVar(pInt), m_nMin(nMin), m_nMax(nMax),\n\t      m_aStr(aStr)\n\t{\n\t\tCTweakVars::Add(this);\n\t}\n\n\tvoid AddDBG(const char *path);\n};\n\n#define _TWEEKCLASS(name, type)                                                                    \\\n\tclass name : public CTweakVar                                                              \\\n\t{                                                                                          \\\n\tpublic:                                                                                    \\\n\t\tconst char *m_pPath, *m_pVarName;                                                  \\\n\t\ttype *m_pIntVar, m_nLoawerBound, m_nUpperBound, m_nStep;                           \\\n                                                                                                   \\\n\t\tname(type *pInt, const char *strName, type nLower, type nUpper, type nStep,        \\\n\t\t     const char *strPath)                                                          \\\n\t\t    : m_pPath(strPath), m_pVarName(strName), m_pIntVar(pInt),                      \\\n\t\t      m_nLoawerBound(nLower), m_nUpperBound(nUpper), m_nStep(nStep)                \\\n                                                                                                   \\\n\t\t{                                                                                  \\\n\t\t\tCTweakVars::Add(this);                                                     \\\n\t\t}                                                                                  \\\n                                                                                                   \\\n\t\tvoid AddDBG(const char *path);                                                     \\\n\t};\n\n_TWEEKCLASS(CTweakInt8, int8);\n_TWEEKCLASS(CTweakUInt8, uint8);\n_TWEEKCLASS(CTweakInt16, int16);\n_TWEEKCLASS(CTweakUInt16, uint16);\n_TWEEKCLASS(CTweakInt32, int32);\n_TWEEKCLASS(CTweakUInt32, uint32);\n_TWEEKCLASS(CTweakFloat, float);\n\n#undef _TWEEKCLASS\n#endif\n\n#ifdef VALIDATE_SAVE_SIZE\nextern int32 _saveBufCount;\n#define INITSAVEBUF _saveBufCount = 0;\n#define VALIDATESAVEBUF(b) assert(_saveBufCount == b);\n#else\n#define INITSAVEBUF\n#define VALIDATESAVEBUF(b)\n#endif\n\ninline void SkipSaveBuf(uint8 *&buf, int32 skip)\n{\n\tbuf += skip;\n#ifdef VALIDATE_SAVE_SIZE\n\t_saveBufCount += skip;\n#endif\n}\n\ninline void SkipSaveBuf(uint8*& buf, uint32 &length, int32 skip)\n{\n\tbuf += skip;\n\tlength += skip;\n#ifdef VALIDATE_SAVE_SIZE\n\t_saveBufCount += skip;\n#endif\n}\n\ntemplate<typename T>\ninline const T ReadSaveBuf(uint8 *&buf)\n{\n\tT &value = *(T*)buf;\n\tSkipSaveBuf(buf, sizeof(T));\n\treturn value;\n}\n\ntemplate<typename T>\ninline const T ReadSaveBuf(uint8 *&buf, uint32 &length)\n{\n\tT &value = *(T*)buf;\n\tSkipSaveBuf(buf, length, sizeof(T));\n\treturn value;\n}\n\ntemplate<typename T>\ninline T *WriteSaveBuf(uint8 *&buf, const T &value)\n{\n\tT *p = (T*)buf;\n\t*p = value;\n\tSkipSaveBuf(buf, sizeof(T));\n\treturn p;\n}\n\ntemplate<typename T>\ninline T *WriteSaveBuf(uint8 *&buf, uint32 &length, const T &value)\n{\n\tT *p = (T*)buf;\n\t*p = value;\n\tSkipSaveBuf(buf, length, sizeof(T));\n\treturn p;\n}\n\n\n#define SAVE_HEADER_SIZE (4*sizeof(char)+sizeof(uint32))\n\n#define WriteSaveHeader(buf,a,b,c,d,size) \\\n\tWriteSaveBuf(buf, a);\\\n\tWriteSaveBuf(buf, b);\\\n\tWriteSaveBuf(buf, c);\\\n\tWriteSaveBuf(buf, d);\\\n\tWriteSaveBuf<uint32>(buf, size);\n\n#define WriteSaveHeaderWithLength(buf,len,a,b,c,d,size) \\\n\tWriteSaveBuf(buf, len, a);\\\n\tWriteSaveBuf(buf, len, b);\\\n\tWriteSaveBuf(buf, len, c);\\\n\tWriteSaveBuf(buf, len, d);\\\n\tWriteSaveBuf<uint32>(buf, len, size);\n\n#define CheckSaveHeader(buf,a,b,c,d,size)\\\n\tassert(ReadSaveBuf<char>(buf) == a);\\\n\tassert(ReadSaveBuf<char>(buf) == b);\\\n\tassert(ReadSaveBuf<char>(buf) == c);\\\n\tassert(ReadSaveBuf<char>(buf) == d);\\\n\tassert(ReadSaveBuf<uint32>(buf) == size);\n\n#define CheckSaveHeaderWithLength(buf,len,a,b,c,d,size)\\\n\tassert(ReadSaveBuf<char>(buf,len) == a);\\\n\tassert(ReadSaveBuf<char>(buf,len) == b);\\\n\tassert(ReadSaveBuf<char>(buf,len) == c);\\\n\tassert(ReadSaveBuf<char>(buf,len) == d);\\\n\tassert(ReadSaveBuf<uint32>(buf,len) == size);\n\n\nvoid cprintf(char*, ...);\n"
  },
  {
    "path": "src/core/config.h",
    "content": "#pragma once\n\n// disables (most) stuff that wasn't in original gta-vc.exe - check section at the bottom of this file\n//#define VANILLA_DEFINES\n\nenum Config {\n\tNUMPLAYERS = 1,\n\n\tNUMCDIMAGES = 6, // gta3.img duplicates (not used on PC)\n\tMAX_CDIMAGES = 8, // additional cdimages\n\tMAX_CDCHANNELS = 5,\n\n\tMODELINFOSIZE = 6500,\t// 4900 on PS2\n\tTXDSTORESIZE = 1385,\n\tCOLSTORESIZE = 31,\n\tEXTRADIRSIZE = 256,\n\tCUTSCENEDIRSIZE = 512,\n\n\tSIMPLEMODELSIZE = 3885,\n\tTIMEMODELSIZE = 385,\n\tCLUMPMODELSIZE = 5,\n\tWEAPONMODELSIZE = 37,\n\tPEDMODELSIZE = 130,\n\tVEHICLEMODELSIZE = 110,\n\tTWODFXSIZE = 1210,\n\n\tMAXVEHICLESLOADED = 50, // 70 on mobile\n\n\tNUMOBJECTINFO = 210,\n\n\t// Pool sizes\n\tNUMPTRNODES = 50000,\n\tNUMENTRYINFOS = 3200,\n\tNUMPEDS = 140,\n\tNUMVEHICLES = 110,\n\tNUMBUILDINGS = 7000,\n\tNUMTREADABLES = 1,\n\tNUMOBJECTS = 460,\n\tNUMDUMMIES = 2340,\n\tNUMAUDIOSCRIPTOBJECTS = 192,\n\tNUMCOLMODELS = 4400,\n\tNUMCUTSCENEOBJECTS = 50,\t// not a pool in VC\n\n\tNUMANIMBLOCKS = 35,\n\tNUMANIMATIONS = 450,\n\n\tNUMTEMPOBJECTS = 40,\n\n\t// Path data\n\tNUM_PATHNODES = 9650,\n\tNUM_CARPATHLINKS = 3500,\n\tNUM_MAPOBJECTS = 1250,\n\tNUM_PATHCONNECTIONS = 20400,\n\n\t// Link list lengths\n\tNUMALPHALIST = 20,\n\tNUMBOATALPHALIST = 20,\n\tNUMALPHAENTITYLIST = 200,\n\tNUMALPHAUNTERWATERENTITYLIST = 30,\n\tNUMCOLCACHELINKS = 50,\n\tNUMREFERENCES = 800,\n\n\t// Zones\n\tNUMAUDIOZONES = 14,\n\tNUMINFOZONES = 169,\n\tNUMMAPZONES = 39,\n\tNUMNAVIGZONES = 20,\n\n\t// Cull zones\n\tNUMATTRIBZONES = 704,\n\n\tNUMOCCLUSIONVOLUMES = 350,\n\tNUMACTIVEOCCLUDERS = 48,\n\n\tPATHNODESIZE = 4500,\n\n\tNUMWEATHERS = 7,\n\tNUMHOURS = 24,\n\n\tNUMEXTRADIRECTIONALS = 4,\n\tNUMANTENNAS = 8,\n\tNUMCORONAS = 56,\n\tNUMPOINTLIGHTS = 32,\n\tNUM3DMARKERS = 32,\n\tNUMBRIGHTLIGHTS = 32,\n\tNUMSHINYTEXTS = 32,\n\tNUMMONEYMESSAGES = 16,\n\tNUMPICKUPMESSAGES = 16,\n\tNUMBULLETTRACES = 16,\n\tNUMMBLURSTREAKS = 4,\n\tNUMSKIDMARKS = 32,\n\n\tNUMONSCREENCLOCKS = 1,\n\tNUMONSCREENCOUNTERS = 3,\n\tNUMRADARBLIPS = 75,\n\tNUMGENERALPICKUPS = 320,\n\tNUMSCRIPTEDPICKUPS = 16,\n\tNUMPICKUPS = NUMGENERALPICKUPS + NUMSCRIPTEDPICKUPS,\n\tNUMCOLLECTEDPICKUPS = 20,\n\tNUMPACMANPICKUPS = 256,\n\tNUMEVENTS = 64,\n\n\tNUM_CARGENS = 185,\n\n\tNUM_PATH_NODES_IN_AUTOPILOT = 8,\n\n\tNUM_ACCIDENTS = 20,\n\tNUM_FIRES = 40,\n\tNUM_GARAGES = 32,\n\tNUM_PROJECTILES = 32,\n\n\tNUM_GLASSPANES = 45,\n\tNUM_GLASSENTITIES = 32,\n\tNUM_WATERCANNONS = 3,\n\n\tNUMPEDROUTES = 200,\n\tNUMPHONES = 50,\n\tNUMPEDGROUPS = 67,\n\tNUMMODELSPERPEDGROUP = 16,\n\tMAXZONEPEDSLOADED = 8,\n\tNUMSHOTINFOS = 100,\n\n\tNUMROADBLOCKS = 300,\n\tNUM_SCRIPT_ROADBLOCKS = 16,\n\n\tNUMVISIBLEENTITIES = 2000,\n\tNUMINVISIBLEENTITIES = 150,\n\n\tNUM_AUDIOENTITY_EVENTS = 4,\n\tNUM_PED_COMMENTS_BANKS = 2,\n\tNUM_PED_COMMENTS_SLOTS = 20,\n\n\tNUM_SOUNDS_SAMPLES_BANKS = 2,\n\tNUM_SOUNDS_SAMPLES_SLOTS = 27,\n\tNUM_AUDIOENTITIES = 250,\n\n\tNUM_AUDIO_REFLECTIONS = 8,\n\tNUM_SCRIPT_MAX_ENTITIES = 40,\n\n\tNUM_GARAGE_STORED_CARS = 4,\n\n\tNUM_CRANES = 8,\n\tNUM_ESCALATORS = 22,\n\tNUM_WATER_CREATURES = 8,\n\n\tNUM_EXPLOSIONS = 48,\n\n\tNUM_SETPIECES = 96,\n\tNUM_SHORTCUT_START_POINTS = 16\n};\n\n// We don't expect to compile for PS2 or Xbox\n// but it might be interesting for documentation purposes\n#define GTA_PC\n//#define GTA_PS2\n//#define GTA_XBOX\n\n// This enables things from the PS2 version on PC\n#define GTA_PS2_STUFF\n\n// This is enabled for all released games.\n// any debug stuff that isn't left in any game is not in FINAL\n//#define FINAL\n\n// This is enabled for all released games except mobile\n// any debug stuff that is only left in mobile, is not in MASTER\n//#define MASTER\n\n// once and for all:\n// pc: FINAL & MASTER\n// mobile: FINAL\n\n// MASTER builds must be FINAL\n#ifdef MASTER\n#define FINAL\n#endif\n\n// Version defines\n#define GTAVC_PS2\t400\n#define GTAVC_PC_10\t410\n#define GTAVC_PC_11\t411\n#define GTAVC_PC_JAP\t412\n// TODO? maybe something for xbox or android?\n\n#define GTA_VERSION\tGTAVC_PC_11\n\n// TODO(MIAMI): someone ought to find and check out uses of these defines:\n//#define GTA3_STEAM_PATCH\n//#define GTAVC_JP_PATCH\n\n// quality of life fixes that should also be in FINAL\n#define NASTY_GAME\t// nasty game for all languages\n#define NO_CDCHECK\n\n// those infamous texts\n#define DRAW_GAME_VERSION_TEXT\n#ifdef DRAW_GAME_VERSION_TEXT\n\t// unlike R* development builds, ours has runtime switch on debug menu & .ini, and disabled as default.\n\t#define USE_OUR_VERSIONING // If you disable this then game will fetch version from peds.col, as R* did while in development\n#endif\n\n// Memory allocation and compression\n// #define USE_CUSTOM_ALLOCATOR\t\t// use CMemoryHeap for allocation. use with care, not finished yet\n//#define COMPRESSED_COL_VECTORS\t// use compressed vectors for collision vertices\n//#define ANIM_COMPRESSION\t// only keep most recently used anims uncompressed\n\n#if defined GTA_PS2\n#\tdefine GTA_PS2_STUFF\n#\tdefine RANDOMSPLASH\n//#\tdefine USE_CUSTOM_ALLOCATOR\n#\tdefine VU_COLLISION\n#elif defined GTA_PC\n#\tifdef GTA_PS2_STUFF\n#\t\tdefine USE_PS2_RAND\n#\t\tdefine RANDOMSPLASH\t// use random splash as on PS2\n#\t\tdefine PS2_MATFX\n#\tendif\n#\tdefine PC_PLAYER_CONTROLS\t// mouse player/cam mode\n#\tdefine GTA_REPLAY\n#\tdefine GTA_SCENE_EDIT\n#elif defined GTA_XBOX\n#endif\n\n#ifdef VU_COLLISION\n#define COMPRESSED_COL_VECTORS\t// currently need compressed vectors in this code\n#endif\n\n#ifdef MASTER\n\t// only in master builds\n\t#undef DRAW_GAME_VERSION_TEXT\n#else\n\t// not in master builds\n\t#define VALIDATE_SAVE_SIZE\n\n\t#define DEBUGMENU\n#endif\n\n#ifdef FINAL\n\t// in all games\n#\tdefine USE_MY_DOCUMENTS\t// use my documents directory for user files\n#else\n\t// not in any game\n#\tdefine CHATTYSPLASH\t// print what the game is loading\n#\tdefine TIMEBARS\t\t// print debug timers\n#endif\n\n#define FIX_BUGS\t\t// fixes bugs that we've came across during reversing. You can undefine this only on release builds.\n#define MORE_LANGUAGES\t\t// Add more translations to the game\n#define COMPATIBLE_SAVES // this allows changing structs while keeping saves compatible\n#define LOAD_INI_SETTINGS // as the name suggests. fundamental for CUSTOM_FRONTEND_OPTIONS\n#define FIX_HIGH_FPS_BUGS_ON_FRONTEND\n\n#define NO_MOVIES\t// add option to disable intro videos\n\n#if defined(__LP64__) || defined(_WIN64)\n#define FIX_BUGS_64 // Must have fixes to be able to run 64 bit build\n#endif\n\n#define ASCII_STRCMP // use faster ascii str comparisons\n\n#if !defined _WIN32 || defined __MWERKS__ || defined __MINGW32__ || defined VANILLA_DEFINES\n#undef ASCII_STRCMP\n#endif\n\n// Just debug menu entries\n#ifdef DEBUGMENU\n#define RELOADABLES\t\t\t// some debug menu options to reload TXD files\n#define MISSION_SWITCHER // from debug menu\n#endif\n\n// Rendering/display\n#define ASPECT_RATIO_SCALE\t// Not just makes everything scale with aspect ratio, also adds support for all aspect ratios\n#define PROPER_SCALING\t\t// use original DEFAULT_SCREEN_WIDTH/DEFAULT_SCREEN_HEIGHT from PS2 instead of PC(R* changed HEIGHT here to make radar look better, but broke other hud elements aspect ratio).\n#define DEFAULT_NATIVE_RESOLUTION\t// Set default video mode to your native resolution (fixes Windows 10 launch)\n#define USE_TXD_CDIMAGE\t\t// generate and load textures from txd.img\n#define PS2_ALPHA_TEST\t\t// emulate ps2 alpha test \n#define IMPROVED_VIDEOMODE\t// save and load videomode parameters instead of a magic number\n#define DISABLE_LOADING_SCREEN // disable the loading screen which vastly improves the loading time\n#define DISABLE_VSYNC_ON_TEXTURE_CONVERSION // make texture conversion work faster by disabling vsync\n#define ANISOTROPIC_FILTERING\t// set all textures to max anisotropic filtering\n//#define USE_TEXTURE_POOL\n#ifdef LIBRW\n#define EXTENDED_COLOURFILTER\t\t// more options for colour filter (replaces mblur)\n#define EXTENDED_PIPELINES\t\t// custom render pipelines (includes Neo)\n#define SCREEN_DROPLETS\t\t\t// neo water droplets\n#define NEW_RENDERER\t\t// leeds-like world rendering, needs librw\n#endif\n\n#define FIX_SPRITES\t// fix sprites aspect ratio(moon, coronas, particle etc)\n\n#ifndef EXTENDED_COLOURFILTER\n#undef SCREEN_DROPLETS\t\t// we need the backbuffer for this effect\n#endif\n\n// Water & Particle\n// #define PC_WATER\n#define WATER_CHEATS\n\n//#define USE_CUTSCENE_SHADOW_FOR_PED\n#define DISABLE_CUTSCENE_SHADOWS\n\n// Pad\n#if !defined(RW_GL3) && defined(_WIN32)\n#define XINPUT\n#endif\n#if defined XINPUT || (defined RW_GL3 && !defined LIBRW_SDL2 && !defined __SWITCH__)\n#define DETECT_JOYSTICK_MENU // Then we'll expect user to enter Controller->Detect joysticks if his joystick isn't detected at the start.\n#endif\n#define DETECT_PAD_INPUT_SWITCH // Adds automatic switch of pad related stuff between controller and kb/m\n#define KANGAROO_CHEAT\n#define RESTORE_ALLCARSHELI_CHEAT\n#define BETTER_ALLCARSAREDODO_CHEAT\n#define WALLCLIMB_CHEAT\n#define REGISTER_START_BUTTON\n#define BIND_VEHICLE_FIREWEAPON // Adds ability to rebind fire key for 'in vehicle' controls\n#define BUTTON_ICONS // use textures to show controller buttons\n\n// Hud, frontend and radar\n#define PC_MENU\n#define FIX_RADAR\t\t\t// use radar size from early version before R* broke it\n#define RADIO_OFF_TEXT\t\t// Won't work without FIX_BUGS\n\n#ifndef PC_MENU\n#\tdefine PS2_MENU\n//#\tdefine PS2_MENU_USEALLPAGEICONS\n#else\n#\tdefine MAP_ENHANCEMENTS\t\t\t// Adding waypoint and better mouse support\n#\tifdef XINPUT\n#\t\tdefine GAMEPAD_MENU\t\t// Add gamepad menu\n#\tendif\n#\tdefine TRIANGLE_BACK_BUTTON\n//#\tdefine CIRCLE_BACK_BUTTON\n#define LEGACY_MENU_OPTIONS\t\t\t// i.e. frame sync(vsync)\n#define MUCH_SHORTER_OUTRO_SCREEN\n// #define XBOX_MESSAGE_SCREEN\t\t\t// Blue background, no \"saved successfully press OK\" screen etc.\n#\tdefine CUSTOM_FRONTEND_OPTIONS\n\n#\tifdef CUSTOM_FRONTEND_OPTIONS\n#\t\tdefine GRAPHICS_MENU_OPTIONS // otherwise Display settings will be scrollable\n#\t\tdefine NO_ISLAND_LOADING  // disable loadscreen between islands via loading all island data at once, consumes more memory and CPU\n#\t\tdefine CUTSCENE_BORDERS_SWITCH\n#\t\tdefine MULTISAMPLING\t\t// adds MSAA option\n#\t\tdefine INVERT_LOOK_FOR_PAD // enable the hidden option\n#\tendif\n#endif\n\n// Script\n#define USE_DEBUG_SCRIPT_LOADER\t// Loads main.scm by default. Hold R for main_freeroam.scm and D for main_d.scm\n#define USE_MEASUREMENTS_IN_METERS // makes game use meters instead of feet in script\n#define USE_PRECISE_MEASUREMENT_CONVERTION // makes game convert feet to meeters more precisely\n#define SUPPORT_JAPANESE_SCRIPT\n//#define SUPPORT_XBOX_SCRIPT\n//#define SUPPORT_MOBILE_SCRIPT\n#if (defined SUPPORT_XBOX_SCRIPT && defined SUPPORT_MOBILE_SCRIPT)\nstatic_assert(false, \"SUPPORT_XBOX_SCRIPT and SUPPORT_MOBILE_SCRIPT are mutually exclusive\");\n#endif\n#ifdef PC_MENU\n//#define MISSION_REPLAY // mobile feature\n#endif\n//#define SIMPLIER_MISSIONS // apply simplifications from mobile\n#define USE_ADVANCED_SCRIPT_DEBUG_OUTPUT\n#define SCRIPT_LOG_FILE_LEVEL 0 // 0 == no log, 1 == overwrite every frame, 2 == full log\n\n#if SCRIPT_LOG_FILE_LEVEL == 0\n#undef USE_ADVANCED_SCRIPT_DEBUG_OUTPUT\n#endif\n\n#ifndef USE_ADVANCED_SCRIPT_DEBUG_OUTPUT\n#define USE_BASIC_SCRIPT_DEBUG_OUTPUT\n#endif\n\n#ifdef MASTER\n#undef USE_ADVANCED_SCRIPT_DEBUG_OUTPUT\n#undef USE_BASIC_SCRIPT_DEBUG_OUTPUT\n#endif\n\n// Replay\n//#define DONT_FIX_REPLAY_BUGS // keeps various bugs in CReplay, some of which are fairly cool!\n//#define USE_BETA_REPLAY_MODE // adds another replay mode, a few seconds slomo (caution: buggy!)\n\n// Vehicles\n#define EXPLODING_AIRTRAIN\t// can blow up jumbo jet with rocket launcher\n#define CPLANE_ROTORS\t\t// make the rotors of the NPC police heli rotate\n\n// Pickups\n//#define MONEY_MESSAGES\n#define CAMERA_PICKUP\n\n// Peds\n#define CANCELLABLE_CAR_ENTER\n\n// Camera\n#define IMPROVED_CAMERA\t\t// Better Debug cam, and maybe more in the future\n#define FREE_CAM\t\t// Rotating cam\n\n// Audio\n#define RADIO_SCROLL_TO_PREV_STATION // Won't work without FIX_BUGS\n#define AUDIO_CACHE // cache sound lengths to speed up the cold boot\n//#define PS2_AUDIO_PATHS // changes audio paths for cutscenes and radio to PS2 paths (needs vbdec on MSS builds)\n//#define AUDIO_OAL_USE_SNDFILE // use libsndfile to decode WAVs instead of our internal decoder\n#define AUDIO_OAL_USE_MPG123 // use mpg123 to support mp3 files\n\n#ifdef AUDIO_OPUS\n#define AUDIO_OAL_USE_OPUS // enable support of opus files\n//#define OPUS_AUDIO_PATHS // (not supported on VC yet) changes audio paths to opus paths (doesn't work if AUDIO_OAL_USE_OPUS isn't enabled)\n//#define OPUS_SFX  // enable if your sfx.raw is encoded with opus (doesn't work if AUDIO_OAL_USE_OPUS isn't enabled)\n\n#ifndef AUDIO_OAL_USE_OPUS\n#undef OPUS_AUDIO_PATHS\n#undef OPUS_SFX\n#endif\n\n#endif\n\n// Streaming\n#if !defined(_WIN32) && !defined(__SWITCH__)\n\t//#define ONE_THREAD_PER_CHANNEL // Don't use if you're not on SSD/Flash - also not utilized too much right now(see commented LoadAllRequestedModels in Streaming.cpp)\n\t#define FLUSHABLE_STREAMING // Make it possible to interrupt reading when processing file isn't needed anymore.\n#endif\n#define BIG_IMG // Not complete - allows to read larger img files\n\n//#define SQUEEZE_PERFORMANCE\n#ifdef SQUEEZE_PERFORMANCE\n\t#undef PS2_ALPHA_TEST\n\t#undef NO_ISLAND_LOADING\n#endif\n\n// -------\n\n#if defined __MWERKS__ || defined VANILLA_DEFINES\n#define FINAL\n#undef CHATTYSPLASH\n#undef TIMEBARS\n\n#define MASTER\n#undef VALIDATE_SAVE_SIZE\n#undef NO_MOVIES\n#undef DEBUGMENU\n\n#undef DRAW_GAME_VERSION_TEXT\n\n//#undef NASTY_GAME\n//#undef NO_CDCHECK\n\n#undef GTA_PS2_STUFF\n#undef USE_PS2_RAND\n#undef RANDOMSPLASH\n#undef PS2_MATFX\n\n#undef FIX_BUGS\n#define THIS_IS_STUPID\n#undef MORE_LANGUAGES\n#undef COMPATIBLE_SAVES\n#undef LOAD_INI_SETTINGS\n#undef FIX_HIGH_FPS_BUGS_ON_FRONTEND\n\n#undef ASPECT_RATIO_SCALE\n#undef PROPER_SCALING\n//#undef DEFAULT_NATIVE_RESOLUTION\n#undef PS2_ALPHA_TEST\n#undef IMPROVED_VIDEOMODE\n#undef DISABLE_LOADING_SCREEN\n#undef DISABLE_VSYNC_ON_TEXTURE_CONVERSION\n\n#undef FIX_SPRITES\n\n#define PC_WATER\n#undef WATER_CHEATS\n\n#undef USE_CUTSCENE_SHADOW_FOR_PED\n#undef DISABLE_CUTSCENE_SHADOWS\n\n#undef XINPUT\n#undef DETECT_PAD_INPUT_SWITCH\n#undef KANGAROO_CHEAT\n#undef RESTORE_ALLCARSHELI_CHEAT\n#undef BETTER_ALLCARSAREDODO_CHEAT\n#undef WALLCLIMB_CHEAT\n#undef REGISTER_START_BUTTON\n#undef BIND_VEHICLE_FIREWEAPON\n#undef BUTTON_ICONS\n\n#undef FIX_RADAR\n#undef RADIO_OFF_TEXT\n\n#undef MAP_ENHANCEMENTS\n#undef GAMEPAD_MENU\n#undef MUCH_SHORTER_OUTRO_SCREEN\n#undef CUSTOM_FRONTEND_OPTIONS\n\n#undef GRAPHICS_MENU_OPTIONS\n#undef NO_ISLAND_LOADING\n#undef CUTSCENE_BORDERS_SWITCH\n#undef MULTISAMPLING\n#undef INVERT_LOOK_FOR_PAD\n\n#undef USE_DEBUG_SCRIPT_LOADER\n#undef USE_MEASUREMENTS_IN_METERS\n#undef USE_PRECISE_MEASUREMENT_CONVERTION\n#undef SUPPORT_JAPANESE_SCRIPT\n#undef MISSION_REPLAY\n#undef USE_ADVANCED_SCRIPT_DEBUG_OUTPUT\n#undef USE_BASIC_SCRIPT_DEBUG_OUTPUT\n\n#define DONT_FIX_REPLAY_BUGS\n\n#undef EXPLODING_AIRTRAIN\n#undef CPLANE_ROTORS\n#undef CAMERA_PICKUP\n#undef CANCELLABLE_CAR_ENTER\n#undef IMPROVED_CAMERA\n#undef FREE_CAM\n#undef BIG_IMG\n\n#undef RADIO_SCROLL_TO_PREV_STATION\n#endif\n"
  },
  {
    "path": "src/core/main.cpp",
    "content": "#include \"common.h\"\n#include <time.h>\n#include \"rpmatfx.h\"\n#include \"rphanim.h\"\n#include \"rpskin.h\"\n#include \"rtbmp.h\"\n#include \"rtpng.h\"\n#ifdef ANISOTROPIC_FILTERING\n#include \"rpanisot.h\"\n#endif\n\n#include \"main.h\"\n#include \"CdStream.h\"\n#include \"General.h\"\n#include \"RwHelper.h\"\n#include \"Clouds.h\"\n#include \"Draw.h\"\n#include \"Sprite2d.h\"\n#include \"Renderer.h\"\n#include \"Coronas.h\"\n#include \"WaterLevel.h\"\n#include \"Weather.h\"\n#include \"Glass.h\"\n#include \"WaterCannon.h\"\n#include \"SpecialFX.h\"\n#include \"Shadows.h\"\n#include \"Skidmarks.h\"\n#include \"Antennas.h\"\n#include \"Rubbish.h\"\n#include \"Particle.h\"\n#include \"Pickups.h\"\n#include \"WeaponEffects.h\"\n#include \"PointLights.h\"\n#include \"Fluff.h\"\n#include \"Replay.h\"\n#include \"Camera.h\"\n#include \"World.h\"\n#include \"Ped.h\"\n#include \"Font.h\"\n#include \"Pad.h\"\n#include \"Hud.h\"\n#include \"User.h\"\n#include \"Messages.h\"\n#include \"Darkel.h\"\n#include \"Garages.h\"\n#include \"MusicManager.h\"\n#include \"VisibilityPlugins.h\"\n#include \"NodeName.h\"\n#include \"DMAudio.h\"\n#include \"CutsceneMgr.h\"\n#include \"Lights.h\"\n#include \"Credits.h\"\n#include \"ZoneCull.h\"\n#include \"Timecycle.h\"\n#include \"TxdStore.h\"\n#include \"FileMgr.h\"\n#include \"Text.h\"\n#include \"RpAnimBlend.h\"\n#include \"Frontend.h\"\n#include \"AnimViewer.h\"\n#include \"Script.h\"\n#include \"PathFind.h\"\n#include \"Debug.h\"\n#include \"Console.h\"\n#include \"timebars.h\"\n#include \"GenericGameStorage.h\"\n#include \"MemoryCard.h\"\n#include \"MemoryHeap.h\"\n#include \"SceneEdit.h\"\n#include \"debugmenu.h\"\n#include \"Clock.h\"\n#include \"Occlusion.h\"\n#include \"Ropes.h\"\n#include \"postfx.h\"\n#include \"custompipes.h\"\n#include \"screendroplets.h\"\n#include \"VarConsole.h\"\n#ifdef USE_OUR_VERSIONING\n#include \"GitSHA1.h\"\n#endif\n\nGlobalScene Scene;\n\nuint8 work_buff[55000];\nchar gString[256];\nchar gString2[512];\nwchar gUString[256];\nwchar gUString2[256];\n\nfloat FramesPerSecond = 30.0f;\n\nbool gbPrintShite = false;\nbool gbModelViewer;\n#ifdef TIMEBARS\nbool gbShowTimebars;\n#endif\n#ifdef DRAW_GAME_VERSION_TEXT\nbool gbDrawVersionText; // Our addition, we think it was always enabled on !MASTER builds\n#endif\n#ifdef NO_MOVIES\nbool gbNoMovies;\n#endif\n\nvolatile int32 frameCount;\n\nRwRGBA gColourTop;\n\nbool gameAlreadyInitialised;\n\nfloat NumberOfChunksLoaded;\n#define TOTALNUMCHUNKS 95.0f\n\nbool g_SlowMode = false;\nchar version_name[64];\n\n\nvoid GameInit(void);\nvoid SystemInit(void);\nvoid TheGame(void);\n\n#ifdef DEBUGMENU\nvoid DebugMenuPopulate(void);\n#endif\n\n#ifndef FINAL\nbool gbPrintMemoryUsage;\n#endif\n\n#ifdef GTA_PS2\n#define WANT_TO_LOAD TheMemoryCard.m_bWantToLoad\n#define FOUND_GAME_TO_LOAD TheMemoryCard.b_FoundRecentSavedGameWantToLoad\n#else\n#define WANT_TO_LOAD FrontEndMenuManager.m_bWantToLoad\n#define FOUND_GAME_TO_LOAD b_FoundRecentSavedGameWantToLoad\n#endif\n\n#ifdef NEW_RENDERER\nbool gbNewRenderer;\n#endif\n#ifdef FIX_BUGS\n// need to clear stencil for mblur fx. no idea why it works in the original game\n// also for clearing out water rects in new renderer\n#define CLEARMODE (rwCAMERACLEARZ | rwCAMERACLEARSTENCIL)\n#else\n#define CLEARMODE (rwCAMERACLEARZ)\n#endif\n\nbool bDisplayNumOfAtomicsRendered = false;\nbool bDisplayPosn = false;\n\n#ifdef __MWERKS__\nvoid\ndebug(char *fmt, ...)\n{\n#ifndef MASTER\n\t// TODO put something here\n#endif\n}\n\nvoid\nError(char *fmt, ...)\n{\n#ifndef MASTER\n\t// TODO put something here\n#endif\n}\n#endif\n\nvoid\nValidateVersion()\n{\n\tint32 file = CFileMgr::OpenFile(\"models\\\\coll\\\\peds.col\", \"rb\");\n\tchar buff[128];\n\n\tif ( file != -1 )\n\t{\n\t\tCFileMgr::Seek(file, 100, SEEK_SET);\n\t\t\n\t\tfor ( int i = 0; i < 128; i++ )\n\t\t{\n\t\t\tCFileMgr::Read(file, &buff[i], sizeof(char));\n\t\t\tbuff[i] -= 23;\n\t\t\tif ( buff[i] == '\\0' )\n\t\t\t\tbreak;\n\t\t\tCFileMgr::Seek(file, 99, SEEK_CUR);\n\t\t}\n\t\t\n\t\tif ( !strncmp(buff, \"grandtheftauto3\", 15) )\n\t\t{\n\t\t\tstrncpy(version_name, &buff[15], 64);\n\t\t\tCFileMgr::CloseFile(file);\n\t\t\treturn;\n\t\t}\n\t}\n\n\tLoadingScreen(\"Invalid version\", NULL, NULL);\n\t\n\twhile(true)\n\t{\n\t\t;\n\t}\n}\n\nbool\nDoRWStuffStartOfFrame(int16 TopRed, int16 TopGreen, int16 TopBlue, int16 BottomRed, int16 BottomGreen, int16 BottomBlue, int16 Alpha)\n{\n\tCRGBA TopColor(TopRed, TopGreen, TopBlue, Alpha);\n\tCRGBA BottomColor(BottomRed, BottomGreen, BottomBlue, Alpha);\n\n\tCDraw::CalculateAspectRatio();\n\tCameraSize(Scene.camera, nil, SCREEN_VIEWWINDOW, SCREEN_ASPECT_RATIO);\n\tCVisibilityPlugins::SetRenderWareCamera(Scene.camera);\n\tRwCameraClear(Scene.camera, &TopColor.rwRGBA, CLEARMODE);\n\n\tif(!RsCameraBeginUpdate(Scene.camera))\n\t\treturn false;\n\n\tCSprite2d::InitPerFrame();\n\n\tif(Alpha != 0)\n\t\tCSprite2d::DrawRect(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), BottomColor, BottomColor, TopColor, TopColor);\n\n\treturn true;\n}\n\nbool\nDoRWStuffStartOfFrame_Horizon(int16 TopRed, int16 TopGreen, int16 TopBlue, int16 BottomRed, int16 BottomGreen, int16 BottomBlue, int16 Alpha)\n{\n\tCDraw::CalculateAspectRatio();\n\tCameraSize(Scene.camera, nil, SCREEN_VIEWWINDOW, SCREEN_ASPECT_RATIO);\n\tCVisibilityPlugins::SetRenderWareCamera(Scene.camera);\n\tRwCameraClear(Scene.camera, &gColourTop, CLEARMODE);\n\n\tif(!RsCameraBeginUpdate(Scene.camera))\n\t\treturn false;\n\n\tTheCamera.m_viewMatrix.Update();\n\tCClouds::RenderBackground(TopRed, TopGreen, TopBlue, BottomRed, BottomGreen, BottomBlue, Alpha);\n\n\treturn true;\n}\n\n// This is certainly a very useful function\nvoid\nDoRWRenderHorizon(void)\n{\n\tCClouds::RenderHorizon();\n}\n\nvoid\nDoFade(void)\n{\n\tif(CTimer::GetIsPaused())\n\t\treturn;\n\n#ifdef PS2_MENU\n\tif(TheMemoryCard.JustLoadedDontFadeInYet){\n\t\tTheMemoryCard.JustLoadedDontFadeInYet = false;\n\t\tTheMemoryCard.TimeStartedCountingForFade = CTimer::GetTimeInMilliseconds();\n\t}\n#else\n\tif(JustLoadedDontFadeInYet){\n\t\tJustLoadedDontFadeInYet = false;\n\t\tTimeStartedCountingForFade = CTimer::GetTimeInMilliseconds();\n\t}\n#endif\n\n#ifdef PS2_MENU\n\tif(TheMemoryCard.StillToFadeOut){\n\t\tif(CTimer::GetTimeInMilliseconds() - TheMemoryCard.TimeStartedCountingForFade > TheMemoryCard.TimeToStayFadedBeforeFadeOut){\n\t\t\tTheMemoryCard.StillToFadeOut = false;\n#else\n\tif(StillToFadeOut){\n\t\tif(CTimer::GetTimeInMilliseconds() - TimeStartedCountingForFade > TimeToStayFadedBeforeFadeOut){\n\t\t\tStillToFadeOut = false;\n#endif\n\t\t\tTheCamera.Fade(3.0f, FADE_IN);\n\t\t\tTheCamera.ProcessFade();\n\t\t\tTheCamera.ProcessMusicFade();\n\t\t}else{\n\t\t\tTheCamera.SetFadeColour(0, 0, 0);\n\t\t\tTheCamera.Fade(0.0f, FADE_OUT);\n\t\t\tTheCamera.ProcessFade();\n\t\t}\n\t}\n\n\tif(CDraw::FadeValue != 0 || FrontEndMenuManager.m_PrefsBrightness < 256){\n\t\tCSprite2d *splash = LoadSplash(nil);\n\n\t\tCRGBA fadeColor;\n\t\tCRect rect;\n\t\tint fadeValue = CDraw::FadeValue;\n\t\tfloat brightness = Min(FrontEndMenuManager.m_PrefsBrightness, 256);\n\t\tif(brightness <= 50)\n\t\t\tbrightness = 50;\n\t\tif(FrontEndMenuManager.m_bMenuActive)\n\t\t\tbrightness = 256;\n\n\t\tif(TheCamera.m_FadeTargetIsSplashScreen)\n\t\t\tfadeValue = 0;\n\n\t\tfloat fade = fadeValue + 256 - brightness;\n\t\tif(fade == 0){\n\t\t\tfadeColor.r = 0;\n\t\t\tfadeColor.g = 0;\n\t\t\tfadeColor.b = 0;\n\t\t\tfadeColor.a = 0;\n\t\t}else{\n\t\t\tfadeColor.r = fadeValue * CDraw::FadeRed / fade;\n\t\t\tfadeColor.g = fadeValue * CDraw::FadeGreen / fade;\n\t\t\tfadeColor.b = fadeValue * CDraw::FadeBlue / fade;\n\t\t\tint alpha = 255 - brightness*(256 - fadeValue)/256;\n\t\t\tif(alpha < 0)\n\t\t\t\talpha = 0;\n\t\t\tfadeColor.a = alpha;\n\t\t}\n\n\t\tTheCamera.GetScreenRect(rect);\n\t\tCSprite2d::DrawRect(rect, fadeColor);\n\n\t\tif(CDraw::FadeValue != 0 && TheCamera.m_FadeTargetIsSplashScreen){\n\t\t\tRwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR);\n\t\t\tfadeColor.r = 255;\n\t\t\tfadeColor.g = 255;\n\t\t\tfadeColor.b = 255;\n\t\t\tfadeColor.a = CDraw::FadeValue;\n\t\t\tsplash->Draw(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), fadeColor, fadeColor, fadeColor, fadeColor);\n\t\t}\n\t}\n}\n\nbool\nRwGrabScreen(RwCamera *camera, RwChar *filename)\n{\n\tchar temp[255];\n\tRwImage *pImage = RsGrabScreen(camera);\n\tbool result = true;\n\n\tif (pImage == nil)\n\t\treturn false;\n\n\tstrcpy(temp, CFileMgr::GetRootDirName());\n\tstrcat(temp, filename);\n\n#ifndef LIBRW\n\tif (RtBMPImageWrite(pImage, &temp[0]) == nil)\n#else\n\tif (RtPNGImageWrite(pImage, &temp[0]) == nil)\n#endif\n\t\tresult = false;\n\tRwImageDestroy(pImage);\n\treturn result;\n}\n\n#define TILE_WIDTH 576\n#define TILE_HEIGHT 432\n\nvoid\nDoRWStuffEndOfFrame(void)\n{\n\tCDebug::DisplayScreenStrings();\t// custom\n\tCDebug::DebugDisplayTextBuffer();\n\tFlushObrsPrintfs();\n\tRwCameraEndUpdate(Scene.camera);\n\tRsCameraShowRaster(Scene.camera);\n#ifndef MASTER\n\tchar s[48];\n#ifdef THIS_IS_STUPID\n\tif (CPad::GetPad(1)->GetLeftShockJustDown()) {\n\t\t// try using both controllers for this thing... crazy bastards\n\t\tif (CPad::GetPad(0)->GetRightStickY() > 0) {\n\t\t\tsprintf(s, \"screen%d%d.ras\", CClock::ms_nGameClockHours, CClock::ms_nGameClockMinutes);\n\t\t\t// TODO\n\t\t\t//RtTileRender(Scene.camera, TILE_WIDTH * 2, TILE_HEIGHT * 2, TILE_WIDTH, TILE_HEIGHT, &NewTileRendererCB, nil, s);\n\t\t} else {\n\t\t\tsprintf(s, \"screen%d%d.bmp\", CClock::ms_nGameClockHours, CClock::ms_nGameClockMinutes);\n\t\t\tRwGrabScreen(Scene.camera, s);\n\t\t}\n\t}\n#else\n\tif (CPad::GetPad(1)->GetLeftShockJustDown() || CPad::GetPad(0)->GetFJustDown(11)) {\n\t\tsprintf(s, \"screen_%11lld.png\", time(nil));\n\t\tRwGrabScreen(Scene.camera, s);\n\t}\n#endif\n#endif // !MASTER\n}\n\nstatic RwBool \nPluginAttach(void)\n{\n\tif( !RpWorldPluginAttach() )\n\t{\n\t\tprintf(\"Couldn't attach world plugin\\n\");\n\t\t\n\t\treturn FALSE;\n\t}\n\t\n\tif( !RpSkinPluginAttach() )\n\t{\n\t\tprintf(\"Couldn't attach RpSkin plugin\\n\");\n\t\t\n\t\treturn FALSE;\n\t}\n#ifndef LIBRW\n\tif (!RtAnimInitialize())\n\t{\n\t\treturn FALSE;\n\t}\n#endif\n\tif( !RpHAnimPluginAttach() )\n\t{\n\t\tprintf(\"Couldn't attach RpHAnim plugin\\n\");\n\t\t\n\t\treturn FALSE;\n\t}\n\t\n\tif( !NodeNamePluginAttach() )\n\t{\n\t\tprintf(\"Couldn't attach node name plugin\\n\");\n\t\t\n\t\treturn FALSE;\n\t}\n\t\n\tif( !CVisibilityPlugins::PluginAttach() )\n\t{\n\t\tprintf(\"Couldn't attach visibility plugins\\n\");\n\t\t\n\t\treturn FALSE;\n\t}\n\t\n\tif( !RpAnimBlendPluginAttach() )\n\t{\n\t\tprintf(\"Couldn't attach RpAnimBlend plugin\\n\");\n\t\t\n\t\treturn FALSE;\n\t}\n\t\n\tif( !RpMatFXPluginAttach() )\n\t{\n\t\tprintf(\"Couldn't attach RpMatFX plugin\\n\");\n\t\t\n\t\treturn FALSE;\n\t}\n#ifdef ANISOTROPIC_FILTERING\n\tRpAnisotPluginAttach();\n#endif\n#ifdef EXTENDED_PIPELINES\n\tCustomPipes::CustomPipeRegister();\n#endif\n\n\treturn TRUE;\n}\n\n#ifdef GTA_PS2\n#define NUM_PREALLOC_ATOMICS 1800\n#define NUM_PREALLOC_CLUMPS 80\n#define NUM_PREALLOC_FRAMES 2600\n#define NUM_PREALLOC_GEOMETRIES 850\n#define NUM_PREALLOC_TEXDICTS 121\n#define NUM_PREALLOC_TEXTURES 1700\n#define NUM_PREALLOC_MATERIALS 2600\nbool preAlloc;\n\nvoid\nPreAllocateRwObjects(void)\n{\n\tint i;\n\n\tPUSH_MEMID(MEMID_PRE_ALLOC);\n\tvoid **tmp = new void*[0x8000];\n\tpreAlloc = true;\n\n\tfor(i = 0; i < NUM_PREALLOC_ATOMICS; i++)\n\t\ttmp[i] = RpAtomicCreate();\n\tfor(i = 0; i < NUM_PREALLOC_ATOMICS; i++)\n\t\tRpAtomicDestroy((RpAtomic*)tmp[i]);\n\n\tfor(i = 0; i < NUM_PREALLOC_CLUMPS; i++)\n\t\ttmp[i] = RpClumpCreate();\n\tfor(i = 0; i < NUM_PREALLOC_CLUMPS; i++)\n\t\tRpClumpDestroy((RpClump*)tmp[i]);\n\n\tfor(i = 0; i < NUM_PREALLOC_FRAMES; i++)\n\t\ttmp[i] = RwFrameCreate();\n\tfor(i = 0; i < NUM_PREALLOC_FRAMES; i++)\n\t\tRwFrameDestroy((RwFrame*)tmp[i]);\n\n\tfor(i = 0; i < NUM_PREALLOC_GEOMETRIES; i++)\n\t\ttmp[i] = RpGeometryCreate(0, 0, 0);\n\tfor(i = 0; i < NUM_PREALLOC_GEOMETRIES; i++)\n\t\tRpGeometryDestroy((RpGeometry*)tmp[i]);\n\n\tfor(i = 0; i < NUM_PREALLOC_TEXDICTS; i++)\n\t\ttmp[i] = RwTexDictionaryCreate();\n\tfor(i = 0; i < NUM_PREALLOC_TEXDICTS; i++)\n\t\tRwTexDictionaryDestroy((RwTexDictionary*)tmp[i]);\n\n\tfor(i = 0; i < NUM_PREALLOC_TEXTURES; i++)\n\t\ttmp[i] = RwTextureCreate(RwRasterCreate(0, 0, 0, 0));\n\tfor(i = 0; i < NUM_PREALLOC_TEXDICTS; i++)\n\t\tRwTextureDestroy((RwTexture*)tmp[i]);\n\n\tfor(i = 0; i < NUM_PREALLOC_MATERIALS; i++)\n\t\ttmp[i] = RpMaterialCreate();\n\tfor(i = 0; i < NUM_PREALLOC_MATERIALS; i++)\n\t\tRpMaterialDestroy((RpMaterial*)tmp[i]);\n\n\tdelete[] tmp;\n\tpreAlloc = false;\n\tPOP_MEMID();\n}\n#endif\n\nstatic RwBool \nInitialise3D(void *param)\n{\n\tPUSH_MEMID(MEMID_RENDER);\n\n#ifndef MASTER\n\tVarConsole.Add(\"Display number of atomics rendered\", &bDisplayNumOfAtomicsRendered, true);\n\tVarConsole.Add(\"Display posn and framerate\", &bDisplayPosn, true);\n#endif\n\n\tif (RsRwInitialize(param))\n\t{\n\t\tPOP_MEMID();\n\n#ifdef DEBUGMENU\n\t\tDebugMenuInit();\n\t\tDebugMenuPopulate();\n#endif // !DEBUGMENU\n\t\treturn CGame::InitialiseRenderWare();\n\t}\n\tPOP_MEMID();\n\n\treturn (FALSE);\n}\n\nstatic void \nTerminate3D(void)\n{\n\tCGame::ShutdownRenderWare();\n#ifdef DEBUGMENU\n\tDebugMenuShutdown();\n#endif // !DEBUGMENU\n\t\n\tRsRwTerminate();\n\n\treturn;\n}\n\nCSprite2d splash;\nint splashTxdId = -1;\n\nCSprite2d*\nLoadSplash(const char *name)\n{\n\tRwTexDictionary *txd;\n\tchar filename[140];\n\tRwTexture *tex = nil;\n\n\tif(name == nil)\n\t\treturn &splash;\n\tif(splashTxdId == -1)\n\t\tsplashTxdId = CTxdStore::AddTxdSlot(\"splash\");\n\n\ttxd = CTxdStore::GetSlot(splashTxdId)->texDict;\n\tif(txd)\n\t\ttex = RwTexDictionaryFindNamedTexture(txd, name);\n\t// if texture is found, splash was already set up below\n\n\tif(tex == nil){\n\t\tCFileMgr::SetDir(\"TXD\\\\\");\n\t\tsprintf(filename, \"%s.txd\", name);\n\t\tif(splash.m_pTexture)\n\t\t\tsplash.Delete();\n\t\tif(txd)\n\t\t\tCTxdStore::RemoveTxd(splashTxdId);\n\t\tCTxdStore::LoadTxd(splashTxdId, filename);\n\t\tCTxdStore::AddRef(splashTxdId);\n\t\tCTxdStore::PushCurrentTxd();\n\t\tCTxdStore::SetCurrentTxd(splashTxdId);\n\t\tsplash.SetTexture(name);\n\t\tCTxdStore::PopCurrentTxd();\n\t\tCFileMgr::SetDir(\"\");\n\t}\n\n\treturn &splash;\n}\n\nvoid\nDestroySplashScreen(void)\n{\n\tsplash.Delete();\n\tif(splashTxdId != -1)\n\t\tCTxdStore::RemoveTxdSlot(splashTxdId);\n\tsplashTxdId = -1;\n}\n\nConst char*\nGetRandomSplashScreen(void)\n{\n\tint index;\n\tstatic int index2 = 0;\n\tstatic char splashName[128];\n\tstatic int splashIndex[12] = {\n\t\t1, 2,\n\t\t3, 4,\n\t\t5, 11,\n\t\t6, 8,\n\t\t9, 10,\n\t\t7, 12\n\t};\n\n\tindex = splashIndex[2*index2 + CGeneral::GetRandomNumberInRange(0, 2)];\n\tindex2++;\n\tif(index2 == 6)\n\t\tindex2 = 0;\n\tsprintf(splashName, \"loadsc%d\", index);\n\treturn splashName;\n}\n\nConst char*\nGetLevelSplashScreen(int level)\n{\n\tstatic Const char *splashScreens[4] = {\n\t\tnil,\n\t\t\"splash1\",\n\t\t\"splash2\",\n\t\t\"splash3\",\n\t};\n\n\treturn splashScreens[level];\n}\n\nvoid\nResetLoadingScreenBar()\n{\n\tNumberOfChunksLoaded = 0.0f;\n}\n\nvoid\nLoadingScreen(const char *str1, const char *str2, const char *splashscreen)\n{\n\tCSprite2d *splash;\n\n#ifdef DISABLE_LOADING_SCREEN\n\tif (str1 && str2)\n\t\treturn;\n#endif\n\n#ifndef RANDOMSPLASH\n\tsplashscreen = \"LOADSC0\";\n#endif\n\n\tsplash = LoadSplash(splashscreen);\n\n#ifndef GTA_PS2\n\tif(RsGlobal.quit)\n\t\treturn;\n#endif\n\n\tif(DoRWStuffStartOfFrame(0, 0, 0, 0, 0, 0, 255)){\n\t\tCSprite2d::SetRecipNearClip();\n\t\tCSprite2d::InitPerFrame();\n\t\tCFont::InitPerFrame();\n\t\tDefinedState();\n\t\tRwRenderStateSet(rwRENDERSTATETEXTUREADDRESS, (void*)rwTEXTUREADDRESSCLAMP);\n\t\tsplash->Draw(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(255, 255, 255, 255));\n\n\t\tif(str1){\n\t\t\tNumberOfChunksLoaded += 1;\n\n#ifndef RANDOMSPLASH\n\t\t\tfloat hpos = SCREEN_SCALE_X(40);\n\t\t\tfloat length = SCREEN_WIDTH - SCREEN_SCALE_X(80);\n\t\t\tfloat top = SCREEN_HEIGHT - SCREEN_SCALE_Y(14);\n\t\t\tfloat bottom = top + SCREEN_SCALE_Y(5);\n#else\n\t\t\tfloat hpos = SCREEN_STRETCH_X(40);\n\t\t\tfloat length = SCREEN_STRETCH_X(440);\n\t\t\t// this is rather weird\n\t\t\tfloat top = SCREEN_STRETCH_Y(407.4f - 7.0f/3.0f);\n\t\t\tfloat bottom = SCREEN_STRETCH_Y(407.4f + 7.0f/3.0f);\n#endif\n\n\t\t\tCSprite2d::DrawRect(CRect(hpos-1.0f, top-1.0f, hpos+length+1.0f, bottom+1.0f), CRGBA(40, 53, 68, 255));\n\n\t\t\tCSprite2d::DrawRect(CRect(hpos, top, hpos+length, bottom), CRGBA(155, 50, 125, 255));\n\n\t\t\tlength *= NumberOfChunksLoaded/TOTALNUMCHUNKS;\n\t\t\tCSprite2d::DrawRect(CRect(hpos, top, hpos+length, bottom), CRGBA(255, 150, 225, 255));\n\n\t\t\t// this is done by the game but is unused\n\t\t\tCFont::SetBackgroundOff();\n\t\t\tCFont::SetScale(SCREEN_SCALE_X(2), SCREEN_SCALE_Y(2));\n\t\t\tCFont::SetPropOn();\n\t\t\tCFont::SetRightJustifyOn();\n\t\t\tCFont::SetDropShadowPosition(1);\n\t\t\tCFont::SetDropColor(CRGBA(0, 0, 0, 255));\n\t\t\tCFont::SetFontStyle(FONT_HEADING);\n\n#ifdef CHATTYSPLASH\n\t\t\t// my attempt\n\t\t\tstatic wchar tmpstr[80];\n\t\t\tfloat yscale = SCREEN_SCALE_Y(0.9f);\n\t\t\ttop -= 45*yscale;\n\t\t\tCFont::SetScale(SCREEN_SCALE_X(0.75f), yscale);\n\t\t\tCFont::SetPropOn();\n\t\t\tCFont::SetRightJustifyOff();\n\t\t\tCFont::SetFontStyle(FONT_STANDARD);\n\t\t\tCFont::SetColor(CRGBA(255, 255, 255, 255));\n\t\t\tAsciiToUnicode(str1, tmpstr);\n\t\t\tCFont::PrintString(hpos, top, tmpstr);\n\t\t\ttop += 22*yscale;\n\t\t\tif (str2) {\n\t\t\t\tAsciiToUnicode(str2, tmpstr);\n\t\t\t\tCFont::PrintString(hpos, top, tmpstr);\n\t\t\t}\n#endif\n\t\t}\n\n\t\tCFont::DrawFonts();\n \t\tDoRWStuffEndOfFrame();\n\t}\n}\n\nvoid\nLoadingIslandScreen(const char *levelName)\n{\n\tCSprite2d *splash;\n\n\tsplash = LoadSplash(nil);\n\tif(!DoRWStuffStartOfFrame(0, 0, 0, 0, 0, 0, 255))\n\t\treturn;\n\n\tCSprite2d::SetRecipNearClip();\n\tCSprite2d::InitPerFrame();\n\tCFont::InitPerFrame();\n\tDefinedState();\n\tCRGBA col = CRGBA(255, 255, 255, 255);\n\tCRGBA col2 = CRGBA(0, 0, 0, 255);\n\tCSprite2d::DrawRect(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), col2);\n\tsplash->Draw(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), col, col, col, col);\n\tCFont::DrawFonts();\n\tDoRWStuffEndOfFrame();\n}\n\nvoid\nProcessSlowMode(void)\n{  \n\tint16 lX = CPad::GetPad(0)->NewState.LeftStickX;\n\tint16 lY = CPad::GetPad(0)->NewState.LeftStickY;\n\tint16 rX = CPad::GetPad(0)->NewState.RightStickX;\n\tint16 rY = CPad::GetPad(0)->NewState.RightStickY;\n\tint16 L1 = CPad::GetPad(0)->NewState.LeftShoulder1;\n\tint16 L2 = CPad::GetPad(0)->NewState.LeftShoulder2;\n\tint16 R1 = CPad::GetPad(0)->NewState.RightShoulder1;\n\tint16 R2 = CPad::GetPad(0)->NewState.RightShoulder2;\n\tint16 up = CPad::GetPad(0)->NewState.DPadUp;\n\tint16 down = CPad::GetPad(0)->NewState.DPadDown;\n\tint16 left = CPad::GetPad(0)->NewState.DPadLeft;\n\tint16 right = CPad::GetPad(0)->NewState.DPadRight;\n\tint16 start = CPad::GetPad(0)->NewState.Start;\n\tint16 select = CPad::GetPad(0)->NewState.Select;\n\tint16 square = CPad::GetPad(0)->NewState.Square;\n\tint16 triangle = CPad::GetPad(0)->NewState.Triangle;\n\tint16 cross = CPad::GetPad(0)->NewState.Cross;\n\tint16 circle = CPad::GetPad(0)->NewState.Circle;\n\tint16 L3 = CPad::GetPad(0)->NewState.LeftShock;\n\tint16 R3 = CPad::GetPad(0)->NewState.RightShock;\n\tint16 networktalk = CPad::GetPad(0)->NewState.NetworkTalk;\n\tint16 stop = true;\n\t\n\tdo\n\t{\n\t\tif ( CPad::GetPad(1)->GetSelectJustDown() || CPad::GetPad(1)->GetStart() )\n\t\t\tbreak;\n\t\t\n\t\tif ( stop )\n\t\t{\n\t\t\tCTimer::Stop();\n\t\t\tstop = false;\n\t\t}\n\t\t\n\t\tCPad::UpdatePads();\n\t\t\n\t\tRwCameraBeginUpdate(Scene.camera);\n\t\tRwCameraEndUpdate(Scene.camera);\n\t\t\n\t} while (!CPad::GetPad(1)->GetSelectJustDown() && !CPad::GetPad(1)->GetStart());\n\t\n\t\n\tCPad::GetPad(0)->OldState.LeftStickX = lX;\n\tCPad::GetPad(0)->OldState.LeftStickY = lY;\n\tCPad::GetPad(0)->OldState.RightStickX = rX;\n\tCPad::GetPad(0)->OldState.RightStickY = rY;\n\tCPad::GetPad(0)->OldState.LeftShoulder1 = L1;\n\tCPad::GetPad(0)->OldState.LeftShoulder2 = L2;\n\tCPad::GetPad(0)->OldState.RightShoulder1 = R1;\n\tCPad::GetPad(0)->OldState.RightShoulder2 = R2;\n\tCPad::GetPad(0)->OldState.DPadUp = up;\n\tCPad::GetPad(0)->OldState.DPadDown = down;\n\tCPad::GetPad(0)->OldState.DPadLeft = left;\n\tCPad::GetPad(0)->OldState.DPadRight = right;\n\tCPad::GetPad(0)->OldState.Start = start;\n\tCPad::GetPad(0)->OldState.Select = select;\n\tCPad::GetPad(0)->OldState.Square = square;\n\tCPad::GetPad(0)->OldState.Triangle = triangle;\n\tCPad::GetPad(0)->OldState.Cross = cross;\n\tCPad::GetPad(0)->OldState.Circle = circle;\n\tCPad::GetPad(0)->OldState.LeftShock = L3;\n\tCPad::GetPad(0)->OldState.RightShock = R3;\n\tCPad::GetPad(0)->OldState.NetworkTalk = networktalk;\n\tCPad::GetPad(0)->NewState.LeftStickX = lX;\n\tCPad::GetPad(0)->NewState.LeftStickY = lY;\n\tCPad::GetPad(0)->NewState.RightStickX = rX;\n\tCPad::GetPad(0)->NewState.RightStickY = rY;\n\tCPad::GetPad(0)->NewState.LeftShoulder1 = L1;\n\tCPad::GetPad(0)->NewState.LeftShoulder2 = L2;\n\tCPad::GetPad(0)->NewState.RightShoulder1 = R1;\n\tCPad::GetPad(0)->NewState.RightShoulder2 = R2;\n\tCPad::GetPad(0)->NewState.DPadUp = up;\n\tCPad::GetPad(0)->NewState.DPadDown = down;\n\tCPad::GetPad(0)->NewState.DPadLeft = left;\n\tCPad::GetPad(0)->NewState.DPadRight = right;\n\tCPad::GetPad(0)->NewState.Start = start;\n\tCPad::GetPad(0)->NewState.Select = select;\n\tCPad::GetPad(0)->NewState.Square = square;\n\tCPad::GetPad(0)->NewState.Triangle = triangle;\n\tCPad::GetPad(0)->NewState.Cross = cross;\n\tCPad::GetPad(0)->NewState.Circle = circle;\n\tCPad::GetPad(0)->NewState.LeftShock = L3;\n\tCPad::GetPad(0)->NewState.RightShock = R3;\n\tCPad::GetPad(0)->NewState.NetworkTalk = networktalk;\n}\n\n\nfloat FramesPerSecondCounter;\nint32 FrameSamples;\n\n#ifndef MASTER\nstruct tZonePrint\n{\n\tchar name[11];\n\tchar area[5];\n\tCRect rect;\n};\n\ntZonePrint ZonePrint[] =\n{\n\t{ \"DOWNTOWN\", \"GM\", CRect(-1500.0f, 1500.0f, -300.0f, 980.0f)},\n\t{ \"DOWNTOWS\", \"KB\", CRect(-1200.0f, 980.0f, -300.0f, 435.0f)},\n\t{ \"GOLF\", \"NT\", CRect(-300.0f, 660.0f, 320.0f, -255.0f)},\n\t{ \"LITTLEHA\", \"AG\", CRect(-1250.0f, -310.0f, -746.0f, -926.0f)},\n\t{ \"HAITI\", \"CJ\", CRect(-1355.0f, 30.0f, -637.0f, -304.0f)},\n\t{ \"HAITIN\", \"SM\", CRect(-1355.0f, 435.0f, -637.0f, 30.0f)},\n\t{ \"DOCKS\", \"AW\", CRect(-1122.0f, -926.0f, -609.0f, -1575.0f)},\n\t{ \"AIRPORT\", \"NT\", CRect(-2000.0f, 200.0f, -871.0f, -2000.0f)},\n\t{ \"STARISL\", \"CJ\", CRect(-724.0f, -320.0f, -40.0f, -380.0f)},\n\t{ \"CENT.ISLA\", \"NT\", CRect(-163.0f, 1260.0f,  120.0f, 830.0f)},\n\t{ \"MALL\", \"AW\", CRect( 300.0f, 1266.0f,  483.0f, 995.0f)},\n\t{ \"MANSION\", \"KB\", CRect(-724.0f, -500.0f, -40.0f, -670.0f)},\n\t{ \"NBEACH\", \"AS\", CRect( 120.0f,  1340.0f,  900.0f,  600.0f)},\n\t{ \"NBEACHBT\", \"AS\", CRect( 200.0f, 680.0f,  660.0f, -50.0f)},\n\t{ \"NBEACHW\", \"AS\", CRect(-93.0f, 80.0f,  410.0f, -680.0f)},\n\t{ \"OCEANDRV\", \"AC\", CRect( 200.0f, -964.0f,  955.0f, -1797.0f)},\n\t{ \"OCEANDN\", \"WS\", CRect( 400.0f, 50.0f,  955.0f,  -964.0f)},\n\t{ \"WASHINGTN\", \"AC\", CRect(-320.0f, -487.0f,  500.0f, -1200.0f)},\n\t{ \"WASHINBTM\", \"AC\", CRect(-255.0f, -1200.0f,  500.0f, -1690.0f)}\n};\n\nvoid\nPrintMemoryUsage(void)\n{\n// little hack\nif(CPools::GetPtrNodePool() == nil)\nreturn;\n\n\t// Style taken from LCS, modified for III\n//\tCFont::SetFontStyle(FONT_PAGER);\n\tCFont::SetFontStyle(FONT_BANK);\n\tCFont::SetBackgroundOff();\n\tCFont::SetWrapx(640.0f);\n//\tCFont::SetScale(0.5f, 0.75f);\n\tCFont::SetScale(0.4f, 0.75f);\n\tCFont::SetCentreOff();\n\tCFont::SetCentreSize(640.0f);\n\tCFont::SetJustifyOff();\n\tCFont::SetPropOn();\n\tCFont::SetColor(CRGBA(200, 200, 200, 200));\n\tCFont::SetBackGroundOnlyTextOff();\n\tCFont::SetDropShadowPosition(0);\n\n\tfloat y;\n\n#ifdef USE_CUSTOM_ALLOCATOR\n\ty = 24.0f;\n\tsprintf(gString, \"Total: %d blocks, %d bytes\", gMainHeap.m_totalBlocksUsed, gMainHeap.m_totalMemUsed);\n\tAsciiToUnicode(gString, gUString);\n\tCFont::PrintString(24.0f, y, gUString);\n\ty += 12.0f;\n\n\tsprintf(gString, \"Game: %d blocks, %d bytes\", gMainHeap.GetBlocksUsed(MEMID_GAME), gMainHeap.GetMemoryUsed(MEMID_GAME));\n\tAsciiToUnicode(gString, gUString);\n\tCFont::PrintString(24.0f, y, gUString);\n\ty += 12.0f;\n\n\tsprintf(gString, \"World: %d blocks, %d bytes\", gMainHeap.GetBlocksUsed(MEMID_WORLD), gMainHeap.GetMemoryUsed(MEMID_WORLD));\n\tAsciiToUnicode(gString, gUString);\n\tCFont::PrintString(24.0f, y, gUString);\n\ty += 12.0f;\n\n\tsprintf(gString, \"Render: %d blocks, %d bytes\", gMainHeap.GetBlocksUsed(MEMID_RENDER), gMainHeap.GetMemoryUsed(MEMID_RENDER));\n\tAsciiToUnicode(gString, gUString);\n\tCFont::PrintString(24.0f, y, gUString);\n\ty += 12.0f;\n\n\tsprintf(gString, \"PreAlloc: %d blocks, %d bytes\", gMainHeap.GetBlocksUsed(MEMID_PRE_ALLOC), gMainHeap.GetMemoryUsed(MEMID_PRE_ALLOC));\n\tAsciiToUnicode(gString, gUString);\n\tCFont::PrintString(24.0f, y, gUString);\n\ty += 12.0f;\n\n\tsprintf(gString, \"Default Models: %d blocks, %d bytes\", gMainHeap.GetBlocksUsed(MEMID_DEF_MODELS), gMainHeap.GetMemoryUsed(MEMID_DEF_MODELS));\n\tAsciiToUnicode(gString, gUString);\n\tCFont::PrintString(24.0f, y, gUString);\n\ty += 12.0f;\n\n\tsprintf(gString, \"Textures: %d blocks, %d bytes\", gMainHeap.GetBlocksUsed(MEMID_TEXTURES), gMainHeap.GetMemoryUsed(MEMID_TEXTURES));\n\tAsciiToUnicode(gString, gUString);\n\tCFont::PrintString(24.0f, y, gUString);\n\ty += 12.0f;\n\n\tsprintf(gString, \"Streaming: %d blocks, %d bytes\", gMainHeap.GetBlocksUsed(MEMID_STREAM), gMainHeap.GetMemoryUsed(MEMID_STREAM));\n\tAsciiToUnicode(gString, gUString);\n\tCFont::PrintString(24.0f, y, gUString);\n\ty += 12.0f;\n\n\tsprintf(gString, \"Streamed Models: %d blocks, %d bytes\", gMainHeap.GetBlocksUsed(MEMID_STREAM_MODELS), gMainHeap.GetMemoryUsed(MEMID_STREAM_MODELS));\n\tAsciiToUnicode(gString, gUString);\n\tCFont::PrintString(24.0f, y, gUString);\n\ty += 12.0f;\n\n\tsprintf(gString, \"Streamed LODs: %d blocks, %d bytes\", gMainHeap.GetBlocksUsed(MEMID_STREAM_LODS), gMainHeap.GetMemoryUsed(MEMID_STREAM_LODS));\n\tAsciiToUnicode(gString, gUString);\n\tCFont::PrintString(24.0f, y, gUString);\n\ty += 12.0f;\n\n\tsprintf(gString, \"Streamed Textures: %d blocks, %d bytes\", gMainHeap.GetBlocksUsed(MEMID_STREAM_TEXUTRES), gMainHeap.GetMemoryUsed(MEMID_STREAM_TEXUTRES));\n\tAsciiToUnicode(gString, gUString);\n\tCFont::PrintString(24.0f, y, gUString);\n\ty += 12.0f;\n\n\tsprintf(gString, \"Streamed Collision: %d blocks, %d bytes\", gMainHeap.GetBlocksUsed(MEMID_STREAM_COLLISION), gMainHeap.GetMemoryUsed(MEMID_STREAM_COLLISION));\n\tAsciiToUnicode(gString, gUString);\n\tCFont::PrintString(24.0f, y, gUString);\n\ty += 12.0f;\n\n\tsprintf(gString, \"Streamed Animation: %d blocks, %d bytes\", gMainHeap.GetBlocksUsed(MEMID_STREAM_ANIMATION), gMainHeap.GetMemoryUsed(MEMID_STREAM_ANIMATION));\n\tAsciiToUnicode(gString, gUString);\n\tCFont::PrintString(24.0f, y, gUString);\n\ty += 12.0f;\n\n\tsprintf(gString, \"Ped Attr: %d blocks, %d bytes\", gMainHeap.GetBlocksUsed(MEMID_PED_ATTR), gMainHeap.GetMemoryUsed(MEMID_PED_ATTR));\n\tAsciiToUnicode(gString, gUString);\n\tCFont::PrintString(24.0f, y, gUString);\n\ty += 12.0f;\n\n\tsprintf(gString, \"Animation: %d blocks, %d bytes\", gMainHeap.GetBlocksUsed(MEMID_ANIMATION), gMainHeap.GetMemoryUsed(MEMID_ANIMATION));\n\tAsciiToUnicode(gString, gUString);\n\tCFont::PrintString(24.0f, y, gUString);\n\ty += 12.0f;\n\n\tsprintf(gString, \"Pools: %d blocks, %d bytes\", gMainHeap.GetBlocksUsed(MEMID_POOLS), gMainHeap.GetMemoryUsed(MEMID_POOLS));\n\tAsciiToUnicode(gString, gUString);\n\tCFont::PrintString(24.0f, y, gUString);\n\ty += 12.0f;\n\n\tsprintf(gString, \"Collision: %d blocks, %d bytes\", gMainHeap.GetBlocksUsed(MEMID_COLLISION), gMainHeap.GetMemoryUsed(MEMID_COLLISION));\n\tAsciiToUnicode(gString, gUString);\n\tCFont::PrintString(24.0f, y, gUString);\n\ty += 12.0f;\n\n\tsprintf(gString, \"Game Process: %d blocks, %d bytes\", gMainHeap.GetBlocksUsed(MEMID_GAME_PROCESS), gMainHeap.GetMemoryUsed(MEMID_GAME_PROCESS));\n\tAsciiToUnicode(gString, gUString);\n\tCFont::PrintString(24.0f, y, gUString);\n\ty += 12.0f;\n\n\tsprintf(gString, \"Script: %d blocks, %d bytes\", gMainHeap.GetBlocksUsed(MEMID_SCRIPT), gMainHeap.GetMemoryUsed(MEMID_SCRIPT));\n\tAsciiToUnicode(gString, gUString);\n\tCFont::PrintString(24.0f, y, gUString);\n\ty += 12.0f;\n\n\tsprintf(gString, \"Cars: %d blocks, %d bytes\", gMainHeap.GetBlocksUsed(MEMID_CARS), gMainHeap.GetMemoryUsed(MEMID_CARS));\n\tAsciiToUnicode(gString, gUString);\n\tCFont::PrintString(24.0f, y, gUString);\n\ty += 12.0f;\n#endif\n\n\ty = 132.0f;\n\tAsciiToUnicode(\"Pools usage:\", gUString);\n\tCFont::PrintString(400.0f, y, gUString);\n\ty += 12.0f;\n\n\tsprintf(gString, \"PtrNode: %d/%d\", CPools::GetPtrNodePool()->GetNoOfUsedSpaces(), CPools::GetPtrNodePool()->GetSize());\n\tAsciiToUnicode(gString, gUString);\n\tCFont::PrintString(400.0f, y, gUString);\n\ty += 12.0f;\n\n\tsprintf(gString, \"EntryInfoNode: %d/%d\", CPools::GetEntryInfoNodePool()->GetNoOfUsedSpaces(), CPools::GetEntryInfoNodePool()->GetSize());\n\tAsciiToUnicode(gString, gUString);\n\tCFont::PrintString(400.0f, y, gUString);\n\ty += 12.0f;\n\n\tsprintf(gString, \"Ped: %d/%d\", CPools::GetPedPool()->GetNoOfUsedSpaces(), CPools::GetPedPool()->GetSize());\n\tAsciiToUnicode(gString, gUString);\n\tCFont::PrintString(400.0f, y, gUString);\n\ty += 12.0f;\n\n\tsprintf(gString, \"Vehicle: %d/%d\", CPools::GetVehiclePool()->GetNoOfUsedSpaces(), CPools::GetVehiclePool()->GetSize());\n\tAsciiToUnicode(gString, gUString);\n\tCFont::PrintString(400.0f, y, gUString);\n\ty += 12.0f;\n\n\tsprintf(gString, \"Building: %d/%d\", CPools::GetBuildingPool()->GetNoOfUsedSpaces(), CPools::GetBuildingPool()->GetSize());\n\tAsciiToUnicode(gString, gUString);\n\tCFont::PrintString(400.0f, y, gUString);\n\ty += 12.0f;\n\n\tsprintf(gString, \"Treadable: %d/%d\", CPools::GetTreadablePool()->GetNoOfUsedSpaces(), CPools::GetTreadablePool()->GetSize());\n\tAsciiToUnicode(gString, gUString);\n\tCFont::PrintString(400.0f, y, gUString);\n\ty += 12.0f;\n\n\tsprintf(gString, \"Object: %d/%d\", CPools::GetObjectPool()->GetNoOfUsedSpaces(), CPools::GetObjectPool()->GetSize());\n\tAsciiToUnicode(gString, gUString);\n\tCFont::PrintString(400.0f, y, gUString);\n\ty += 12.0f;\n\n\tsprintf(gString, \"Dummy: %d/%d\", CPools::GetDummyPool()->GetNoOfUsedSpaces(), CPools::GetDummyPool()->GetSize());\n\tAsciiToUnicode(gString, gUString);\n\tCFont::PrintString(400.0f, y, gUString);\n\ty += 12.0f;\n\n\tsprintf(gString, \"AudioScriptObjects: %d/%d\", CPools::GetAudioScriptObjectPool()->GetNoOfUsedSpaces(), CPools::GetAudioScriptObjectPool()->GetSize());\n\tAsciiToUnicode(gString, gUString);\n\tCFont::PrintString(400.0f, y, gUString);\n\ty += 12.0f;\n}\n\nvoid\nDisplayGameDebugText()\n{\n\tstatic bool bDisplayCheatStr = false; // custom\n\n#ifndef FINAL\n\t{\n\t\tSETTWEAKPATH(\"Debug\");\n\t\tTWEAKBOOL(bDisplayPosn);\n\t\tTWEAKBOOL(bDisplayCheatStr);\n\t}\n\n\tif(gbPrintMemoryUsage)\n\t\tPrintMemoryUsage();\n#endif\n\n\tchar str[200];\n\twchar ustr[200];\n\n#ifdef DRAW_GAME_VERSION_TEXT\n\twchar ver[200];\n\n\tif(gbDrawVersionText) // This realtime switch is our thing\n\t{\n\n#ifdef USE_OUR_VERSIONING\n\tchar verA[200];\n\tsprintf(verA,\n#if defined _WIN32\n\t\t\t\"Win \"\n#elif defined __linux__\n\t\t    \"Linux \"\n#elif defined __APPLE__\n\t\t    \"Mac OS X \"\n#elif defined __FreeBSD__\n\t\t    \"FreeBSD \"\n#else\n\t\t    \"Posix-compliant \"\n#endif\n#if defined __LP64__ || defined _WIN64\n\t\t\t\"64-bit \"\n#else\n\t\t\t\"32-bit \"\n#endif\n#if defined RW_D3D9\n\t\t    \"D3D9 \"\n#elif defined RWLIBS\n\t\t    \"D3D8 \"\n#elif defined RW_GL3\n\t\t    \"OpenGL \"\n#endif\n#if defined AUDIO_OAL\n\t\t    \"OAL \"\n#elif defined AUDIO_MSS\n\t\t    \"MSS \"\n#endif\n#if defined _DEBUG || defined DEBUG\n\t\t    \"DEBUG \"\n#endif\n\t\t    \"%.8s\",\n\t\t    g_GIT_SHA1);\n\tAsciiToUnicode(verA, ver);\n\tCFont::SetScale(SCREEN_SCALE_X(0.5f), SCREEN_SCALE_Y(0.7f));\n#else\n\tAsciiToUnicode(version_name, ver);\n\tCFont::SetScale(SCREEN_SCALE_X(0.5f), SCREEN_SCALE_Y(0.5f));\n#endif\n\n\tCFont::SetPropOn();\n\tCFont::SetBackgroundOff();\n\tCFont::SetFontStyle(FONT_STANDARD);\n\tCFont::SetCentreOff();\n\tCFont::SetRightJustifyOff();\n\tCFont::SetWrapx(SCREEN_WIDTH);\n\tCFont::SetJustifyOff();\n\tCFont::SetBackGroundOnlyTextOff();\n\tCFont::SetColor(CRGBA(255, 108, 0, 255));\n\tCFont::PrintString(SCREEN_SCALE_X(10.0f), SCREEN_SCALE_Y(10.0f), ver);\n\t}\n#endif // #ifdef DRAW_GAME_VERSION_TEXT\n\n\tFrameSamples++;\n#ifdef FIX_HIGH_FPS_BUGS_ON_FRONTEND\n\tFramesPerSecondCounter += frameTime / 1000.f; // convert to seconds\n\tFramesPerSecond = FrameSamples / FramesPerSecondCounter;\n#else\n\tFramesPerSecondCounter += 1000.0f / (CTimer::GetTimeStepNonClippedInSeconds() * 1000.0f);\t\n\tFramesPerSecond = FramesPerSecondCounter / FrameSamples;\n#endif\n\t\n\tif ( FrameSamples > 30 )\n\t{\n\t\tFramesPerSecondCounter = 0.0f;\n\t\tFrameSamples = 0;\n\t}\n\n\tif ( bDisplayPosn )\n\t{\n\t\tCVector pos = FindPlayerCoors();\n\t\tint32 ZoneId = ARRAY_SIZE(ZonePrint)-1; // no zone\n\t\t\n\t\tfor ( int32 i = 0; i < ARRAY_SIZE(ZonePrint)-1; i++ )\n\t\t{\n\t\t\tif ( pos.x > ZonePrint[i].rect.left\n\t\t\t\t&& pos.x < ZonePrint[i].rect.right\n\t\t\t\t&& pos.y > ZonePrint[i].rect.bottom\n\t\t\t\t&& pos.y < ZonePrint[i].rect.top )\n\t\t\t{\n\t\t\t\tZoneId = i;\n\t\t\t}\n\t\t}\n\n\t\t//NOTE: fps should be 30, but its 29 due to different fp2int conversion \n\t\tsprintf(str, \"X:%4.0f Y:%4.0f Z:%4.0f F-%d %s-%s\", pos.x, pos.y, pos.z, (int32)FramesPerSecond,\n\t\t\tZonePrint[ZoneId].name, ZonePrint[ZoneId].area);\n\n\t\tAsciiToUnicode(str, ustr);\n\t\t\n\t\tCFont::SetPropOn();\n\t\tCFont::SetBackgroundOff();\n\t\tCFont::SetScale(SCREEN_SCALE_X(0.6f), SCREEN_SCALE_Y(0.8f));\n\t\tCFont::SetCentreOff();\n\t\tCFont::SetRightJustifyOff();\n\t\tCFont::SetJustifyOff();\n\t\tCFont::SetBackGroundOnlyTextOff();\n\t\tCFont::SetWrapx(SCREEN_STRETCH_X(DEFAULT_SCREEN_WIDTH));\n\t\tCFont::SetFontStyle(FONT_STANDARD);\n\t\tCFont::SetDropColor(CRGBA(0, 0, 0, 255));\n\t\tCFont::SetDropShadowPosition(2);\n\t\tCFont::SetColor(CRGBA(0, 0, 0, 255));\n\t\tCFont::PrintString(41.0f, 41.0f, ustr);\n\t\t\n\t\tCFont::SetColor(CRGBA(205, 205, 0, 255));\n\t\tCFont::PrintString(40.0f, 40.0f, ustr);\n\t}\n\n\t// custom\n\tif (bDisplayCheatStr)\n\t{\n\t\tsprintf(str, \"%s\", CPad::KeyBoardCheatString);\n\t\tAsciiToUnicode(str, ustr);\n\n\t\tCFont::SetPropOn();\n\t\tCFont::SetBackgroundOff();\n\t\tCFont::SetScale(SCREEN_SCALE_X(0.6f), SCREEN_SCALE_Y(0.8f));\n\t\tCFont::SetCentreOn();\n\t\tCFont::SetBackGroundOnlyTextOff();\n\t\tCFont::SetWrapx(SCREEN_STRETCH_X(DEFAULT_SCREEN_WIDTH));\n\t\tCFont::SetFontStyle(FONT_STANDARD);\n\n\t\tCFont::SetColor(CRGBA(0, 0, 0, 255));\n\t\tCFont::PrintString(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH * 0.5f)+2.f, SCREEN_SCALE_FROM_BOTTOM(20.0f)+2.f, ustr);\n\n\t\tCFont::SetColor(CRGBA(255, 150, 225, 255));\n\t\tCFont::PrintString(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH * 0.5f), SCREEN_SCALE_FROM_BOTTOM(20.0f), ustr);\n\t}\n}\n#endif\n\n#ifdef NEW_RENDERER\nbool gbRenderRoads = true;\nbool gbRenderEverythingBarRoads = true;\nbool gbRenderFadingInUnderwaterEntities = true;\nbool gbRenderFadingInEntities = true;\nbool gbRenderWater = true;\nbool gbRenderBoats = true;\nbool gbRenderVehicles = true;\nbool gbRenderWorld0 = true;\nbool gbRenderWorld1 = true;\nbool gbRenderWorld2 = true;\n\nvoid\nMattRenderScene(void)\n{\n\t// this calls CMattRenderer::Render\n\t/// CWorld::AdvanceCurrentScanCode();\n\t// CMattRenderer::ResetRenderStates\n\t/// CRenderer::ClearForFrame();\t\t// before ConstructRenderList\n\t// CClock::CalcEnvMapTimeMultiplicator\n\tRwRenderStateSet(rwRENDERSTATECULLMODE, (void*)rwCULLMODECULLNONE);\n\tCWaterLevel::RenderWater();\t// actually CMattRenderer::RenderWater\n\t// CClock::ms_EnvMapTimeMultiplicator = 1.0f;\n\t// cWorldStream::ClearDynamics\n\t/// CRenderer::ConstructRenderList();\t// before PreRender\nif(gbRenderWorld0)\n\tCRenderer::RenderWorld(0);\t// roads\n\t// CMattRenderer::ResetRenderStates\n\t/// CRenderer::PreRender();\t// has to be called before BeginUpdate because of cutscene shadows\n\tCCoronas::RenderReflections();\nif(gbRenderWorld1)\n\tCRenderer::RenderWorld(1);\t// opaque\nif(gbRenderRoads)\n\tCRenderer::RenderRoads();\n\n\tCRenderer::RenderPeds();\n\n\t// not sure where to put these since LCS has no underwater entities\nif(gbRenderBoats)\n\tCRenderer::RenderBoats();\nif(gbRenderFadingInUnderwaterEntities)\n\tCRenderer::RenderFadingInUnderwaterEntities();\n\tRwRenderStateSet(rwRENDERSTATECULLMODE, (void*)rwCULLMODECULLNONE);\nif(gbRenderWater)\n\tCRenderer::RenderTransparentWater();\n\nif(gbRenderEverythingBarRoads)\n\tCRenderer::RenderEverythingBarRoads();\n\t// seam fixer\n\t// moved this:\n\t// CRenderer::RenderFadingInEntities();\n}\n\nvoid\nRenderScene_new(void)\n{\n\tPUSH_RENDERGROUP(\"RenderScene_new\");\n\tCClouds::Render();\n\tDoRWRenderHorizon();\n\n\tMattRenderScene();\n\tDefinedState();\n\t// CMattRenderer::ResetRenderStates\n\t// moved CRenderer::RenderBoats to before transparent water\n\tPOP_RENDERGROUP();\n}\n\n// TODO\nbool FredIsInFirstPersonCam(void) { return false; }\nvoid\nRenderEffects_new(void)\n{\n\tPUSH_RENDERGROUP(\"RenderEffects_new\");\n\tCShadows::RenderStaticShadows();\n\t// CRenderer::GenerateEnvironmentMap\n\tCShadows::RenderStoredShadows();\n\tCSkidmarks::Render();\n\tCRubbish::Render();\n\n\t// these aren't really effects\n\tDefinedState();\n\tif(FredIsInFirstPersonCam()){\n\t\tDefinedState();\n\t\tC3dMarkers::Render();\t// normally rendered in CSpecialFX::Render()\nif(gbRenderWorld2)\n\t\tCRenderer::RenderWorld(2);\t// transparent\nif(gbRenderVehicles)\n\t\tCRenderer::RenderVehicles();\n\t}else{\n\t\t// flipped these two, seems to give the best result\nif(gbRenderWorld2)\n\t\tCRenderer::RenderWorld(2);\t// transparent\nif(gbRenderVehicles)\n\t\tCRenderer::RenderVehicles();\n\t}\n\t// better render these after transparent world\nif(gbRenderFadingInEntities)\n\tCRenderer::RenderFadingInEntities();\n\n\t// actual effects here\n\tCGlass::Render();\n\t// CMattRenderer::ResetRenderStates\n\tDefinedState();\n\tCCoronas::RenderSunReflection();\n\tCWeather::RenderRainStreaks();\n\t// CWeather::AddSnow\n\tCWaterCannons::Render();\n\tCAntennas::Render();\n\tCSpecialFX::Render();\n\tCRopes::Render();\n\tCCoronas::Render();\n\tCParticle::Render();\n\tCPacManPickups::Render();\n\tCWeaponEffects::Render();\n\tCPointLights::RenderFogEffect();\n\tCMovingThings::Render();\n\tCRenderer::RenderFirstPersonVehicle();\n\tPOP_RENDERGROUP();\n}\n#endif\n\nvoid\nRenderScene(void)\n{\n#ifdef NEW_RENDERER\n\tif(gbNewRenderer){\n\t\tRenderScene_new();\n\t\treturn;\n\t}\n#endif\n\tPUSH_RENDERGROUP(\"RenderScene\");\n\tCClouds::Render();\n\tDoRWRenderHorizon();\n\tCRenderer::RenderRoads();\n\tCCoronas::RenderReflections();\n\tCRenderer::RenderEverythingBarRoads();\n\tRwRenderStateSet(rwRENDERSTATECULLMODE, (void*)rwCULLMODECULLNONE);\n\tCWaterLevel::RenderWater();\n\tCRenderer::RenderBoats();\n\tCRenderer::RenderFadingInUnderwaterEntities();\n\tRwRenderStateSet(rwRENDERSTATECULLMODE, (void*)rwCULLMODECULLNONE);\n\tCWaterLevel::RenderTransparentWater();\n\tCRenderer::RenderFadingInEntities();\n\tRwRenderStateSet(rwRENDERSTATECULLMODE, (void*)rwCULLMODECULLNONE);\n\tCWeather::RenderRainStreaks();\n\tCCoronas::RenderSunReflection();\n\tPOP_RENDERGROUP();\n}\n\nvoid\nRenderDebugShit(void)\n{\n\tPUSH_RENDERGROUP(\"RenderDebugShit\");\n\tCTheScripts::RenderTheScriptDebugLines();\n#ifndef FINAL\n\tif(gbShowCollisionLines)\n\t\tCRenderer::RenderCollisionLines();\n\tThePaths.DisplayPathData();\n\tCDebug::DrawLines();\n\tDefinedState();\n#endif\n\tPOP_RENDERGROUP();\n}\n\nvoid\nRenderEffects(void)\n{\n#ifdef NEW_RENDERER\n\tif(gbNewRenderer){\n\t\tRenderEffects_new();\n\t\treturn;\n\t}\n#endif\n\tPUSH_RENDERGROUP(\"RenderEffects\");\n\tCGlass::Render();\n\tCWaterCannons::Render();\n\tCSpecialFX::Render();\n\tCRopes::Render();\n\tCShadows::RenderStaticShadows();\n\tCShadows::RenderStoredShadows();\n\tCSkidmarks::Render();\n\tCAntennas::Render();\n\tCRubbish::Render();\n\tCCoronas::Render();\n\tCParticle::Render();\n\tCPacManPickups::Render();\n\tCWeaponEffects::Render();\n\tCPointLights::RenderFogEffect();\n\tCMovingThings::Render();\n\tCRenderer::RenderFirstPersonVehicle();\n\tPOP_RENDERGROUP();\n}\n\nvoid\nRender2dStuff(void)\n{\n\tPUSH_RENDERGROUP(\"Render2dStuff\");\n\tRwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE);\n\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);\n\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);\n\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);\n\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);\n\tRwRenderStateSet(rwRENDERSTATECULLMODE, (void*)rwCULLMODECULLNONE);\n\n\tCReplay::Display();\n\tCPickups::RenderPickUpText();\n\n\tif(TheCamera.m_WideScreenOn\n#ifdef CUTSCENE_BORDERS_SWITCH\n\t\t&& CMenuManager::m_PrefsCutsceneBorders\n#endif\n\t\t)\n\t\tTheCamera.DrawBordersForWideScreen();\n\n\tCPed *player = FindPlayerPed();\n\tint weaponType = 0;\n\tif(player)\n\t\tweaponType = player->GetWeapon()->m_eWeaponType;\n\n\tbool firstPersonWeapon = false;\n\tint cammode = TheCamera.Cams[TheCamera.ActiveCam].Mode;\n\tif(cammode == CCam::MODE_SNIPER ||\n\t   cammode == CCam::MODE_SNIPER_RUNABOUT ||\n\t   cammode == CCam::MODE_ROCKETLAUNCHER ||\n\t   cammode == CCam::MODE_ROCKETLAUNCHER_RUNABOUT ||\n\t   cammode == CCam::MODE_CAMERA)\n\t\tfirstPersonWeapon = true;\n\n\t// Draw black border for sniper and rocket launcher\n\tif((weaponType == WEAPONTYPE_SNIPERRIFLE || weaponType == WEAPONTYPE_ROCKETLAUNCHER || weaponType == WEAPONTYPE_LASERSCOPE) && firstPersonWeapon){\n\t\tCRGBA black(0, 0, 0, 255);\n\n\t\t// top and bottom strips\n\t\tif (weaponType == WEAPONTYPE_ROCKETLAUNCHER) {\n\t\t\tCSprite2d::DrawRect(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT / 2 - SCREEN_SCALE_Y(180)), black);\n\t\t\tCSprite2d::DrawRect(CRect(0.0f, SCREEN_HEIGHT / 2 + SCREEN_SCALE_Y(170), SCREEN_WIDTH, SCREEN_HEIGHT), black);\n\t\t}\n\t\telse {\n\t\t\tCSprite2d::DrawRect(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT / 2 - SCREEN_SCALE_Y(210)), black);\n\t\t\tCSprite2d::DrawRect(CRect(0.0f, SCREEN_HEIGHT / 2 + SCREEN_SCALE_Y(210), SCREEN_WIDTH, SCREEN_HEIGHT), black);\n\t\t}\n\t\tCSprite2d::DrawRect(CRect(0.0f, 0.0f, SCREEN_WIDTH / 2 - SCREEN_SCALE_X(210), SCREEN_HEIGHT), black);\n\t\tCSprite2d::DrawRect(CRect(SCREEN_WIDTH / 2 + SCREEN_SCALE_X(210), 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), black);\n\t}\n\n\tMusicManager.DisplayRadioStationName();\n\tTheConsole.Display();\n#ifdef GTA_SCENE_EDIT\n\tif(CSceneEdit::m_bEditOn)\n\t\tCSceneEdit::Draw();\n\telse\n#endif\n\t\tCHud::Draw();\n\n\tCSpecialFX::Render2DFXs();\n\tCUserDisplay::OnscnTimer.ProcessForDisplay();\n\tCMessages::Display();\n\tCDarkel::DrawMessages();\n\tCGarages::PrintMessages();\n\tCPad::PrintErrorMessage();\n\tCFont::DrawFonts();\n#ifndef MASTER\n\tCOcclusion::Render();\n#endif\n\n#ifdef DEBUGMENU\n\tDebugMenuRender();\n#endif\n\tPOP_RENDERGROUP();\n}\n\nvoid\nRenderMenus(void)\n{\n\tif (FrontEndMenuManager.m_bMenuActive)\n\t{\n\t\tPUSH_RENDERGROUP(\"RenderMenus\");\n\t\tFrontEndMenuManager.DrawFrontEnd();\n\t\tPOP_RENDERGROUP();\n\t}\n#ifndef MASTER\n\telse\n\t\tVarConsole.Check();\n#endif\n}\n\nvoid\nRender2dStuffAfterFade(void)\n{\n\tPUSH_RENDERGROUP(\"Render2dStuffAfterFade\");\n#ifndef MASTER\n\tDisplayGameDebugText();\n#endif\n\n#ifdef MOBILE_IMPROVEMENTS\n\tif (CDraw::FadeValue != 0)\n#endif\n\tCHud::DrawAfterFade();\n\tCFont::DrawFonts();\n\tCCredits::Render();\n\tPOP_RENDERGROUP();\n}\n\nvoid\nIdle(void *arg)\n{\n\tCTimer::Update();\n\n\ttbInit();\n\n\tCSprite2d::InitPerFrame();\n\tCFont::InitPerFrame();\n\n\tPUSH_MEMID(MEMID_GAME_PROCESS);\n\tCPointLights::InitPerFrame();\n\n\ttbStartTimer(0, \"CGame::Process\");\n\tCGame::Process();\n\ttbEndTimer(\"CGame::Process\");\n\tPOP_MEMID();\n\n\ttbStartTimer(0, \"DMAudio.Service\");\n\tDMAudio.Service();\n\ttbEndTimer(\"DMAudio.Service\");\n\n\tif(CGame::bDemoMode && CTimer::GetTimeInMilliseconds() > (3*60 + 30)*1000 && !CCutsceneMgr::IsCutsceneProcessing()){\n\t\tWANT_TO_LOAD = false;\n\t\tFrontEndMenuManager.m_bWantToRestart = true;\n\t\treturn;\n\t}\n\n\tif(FrontEndMenuManager.m_bWantToRestart || FOUND_GAME_TO_LOAD)\n\t{\n\t\treturn;\n\t}\n\t\n\tSetLightsWithTimeOfDayColour(Scene.world);\n\n\tif(arg == nil)\n\t\treturn;\n\n\tPUSH_MEMID(MEMID_RENDER);\n\n\tif(!FrontEndMenuManager.m_bMenuActive && TheCamera.GetScreenFadeStatus() != FADE_2)\n\t{\n\t\t// This is from SA, but it's nice for windowed mode\n#if defined(GTA_PC) && !defined(RW_GL3)\n\t\tRwV2d pos;\n\t\tpos.x = SCREEN_WIDTH / 2.0f;\n\t\tpos.y = SCREEN_HEIGHT / 2.0f;\n\t\tRsMouseSetPos(&pos);\n#endif\n\n\t\ttbStartTimer(0, \"CnstrRenderList\");\n#ifdef PC_WATER\n\t\tCWaterLevel::PreCalcWaterGeometry();\n#endif\n#ifdef NEW_RENDERER\n\t\tif(gbNewRenderer){\n\t\t\tCWorld::AdvanceCurrentScanCode();\t// don't think this is even necessary\n\t\t\tCRenderer::ClearForFrame();\n\t\t}\n#endif\n\t\tCRenderer::ConstructRenderList();\n\t\ttbEndTimer(\"CnstrRenderList\");\n\n\t\ttbStartTimer(0, \"PreRender\");\n\t\tCRenderer::PreRender();\n\t\ttbEndTimer(\"PreRender\");\n\n#ifdef FIX_BUGS\n\t\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void *)FALSE); // TODO: temp? this fixes OpenGL render but there should be a better place for this\n\t\t// This has to be done BEFORE RwCameraBeginUpdate\n\t\tRwCameraSetFarClipPlane(Scene.camera, CTimeCycle::GetFarClip());\n\t\tRwCameraSetFogDistance(Scene.camera, CTimeCycle::GetFogStart());\n#endif\n\n\t\tif(CWeather::LightningFlash && !CCullZones::CamNoRain()){\n\t\t\tif(!DoRWStuffStartOfFrame_Horizon(255, 255, 255, 255, 255, 255, 255))\n\t\t\t\tgoto popret;\n\t\t}else{\n\t\t\tif(!DoRWStuffStartOfFrame_Horizon(CTimeCycle::GetSkyTopRed(), CTimeCycle::GetSkyTopGreen(), CTimeCycle::GetSkyTopBlue(),\n\t\t\t\t\t\tCTimeCycle::GetSkyBottomRed(), CTimeCycle::GetSkyBottomGreen(), CTimeCycle::GetSkyBottomBlue(),\n\t\t\t\t\t\t255))\n\t\t\t\tgoto popret;\n\t\t}\n\n\t\tDefinedState();\n\n#ifndef FIX_BUGS\n\t\tRwCameraSetFarClipPlane(Scene.camera, CTimeCycle::GetFarClip());\n\t\tRwCameraSetFogDistance(Scene.camera, CTimeCycle::GetFogStart());\n#endif\n\n\t\ttbStartTimer(0, \"RenderScene\");\n\t\tRenderScene();\n\t\ttbEndTimer(\"RenderScene\");\n\n#ifdef EXTENDED_PIPELINES\n\t\tCustomPipes::EnvMapRender();\n#endif\n\n\t\tRenderDebugShit();\n\t\tRenderEffects();\n\n\t\tif((TheCamera.m_BlurType == MOTION_BLUR_NONE || TheCamera.m_BlurType == MOTION_BLUR_LIGHT_SCENE) &&\n\t\t   TheCamera.m_ScreenReductionPercentage > 0.0f)\n\t\t        TheCamera.SetMotionBlurAlpha(150);\n\n#ifdef SCREEN_DROPLETS\n\t\tCPostFX::GetBackBuffer(Scene.camera);\n\t\tScreenDroplets::Process();\n\t\tScreenDroplets::Render();\n#endif\n\n\t\ttbStartTimer(0, \"RenderMotionBlur\");\n\t\tTheCamera.RenderMotionBlur();\n\t\ttbEndTimer(\"RenderMotionBlur\");\n\n\t\ttbStartTimer(0, \"Render2dStuff\");\n\t\tRender2dStuff();\n\t\ttbEndTimer(\"Render2dStuff\");\n\t}else{\n\t\tCDraw::CalculateAspectRatio();\n#ifdef ASPECT_RATIO_SCALE\n\t\tCameraSize(Scene.camera, nil, SCREEN_VIEWWINDOW, SCREEN_ASPECT_RATIO);\n#else\n\t\tCameraSize(Scene.camera, nil, SCREEN_VIEWWINDOW, DEFAULT_ASPECT_RATIO);\n#endif\n\t\tCVisibilityPlugins::SetRenderWareCamera(Scene.camera);\n\t\tRwCameraClear(Scene.camera, &gColourTop, CLEARMODE);\n\t\tif(!RsCameraBeginUpdate(Scene.camera))\n\t\t\tgoto popret;\n\t}\n\n\ttbStartTimer(0, \"RenderMenus\");\n\tRenderMenus();\n\ttbEndTimer(\"RenderMenus\");\n\n#ifdef PS2_MENU\n\tif ( TheMemoryCard.m_bWantToLoad )\n\t\tgoto popret;\n#endif\n\n\ttbStartTimer(0, \"DoFade\");\n\tDoFade();\n\ttbEndTimer(\"DoFade\");\n\n\ttbStartTimer(0, \"Render2dStuff-Fade\");\n\tRender2dStuffAfterFade();\n\ttbEndTimer(\"Render2dStuff-Fade\");\n\t// CCredits::Render(); // They added it to function above and also forgot it here\n#ifdef XBOX_MESSAGE_SCREEN\n\tFrontEndMenuManager.DrawOverlays();\n#endif\n\n\tif (gbShowTimebars)\n\t\ttbDisplay();\n\n\tDoRWStuffEndOfFrame();\n\n\tPOP_MEMID();\t// MEMID_RENDER\n\n\tif(g_SlowMode) \n\t\tProcessSlowMode();\n\treturn;\n\npopret:\tPOP_MEMID();\t// MEMID_RENDER\n}\n\nvoid\nFrontendIdle(void)\n{\n\tCDraw::CalculateAspectRatio();\n\tCTimer::Update();\n\tCSprite2d::SetRecipNearClip(); // this should be on InitialiseRenderWare according to PS2 asm. seems like a bug fix\n\tCSprite2d::InitPerFrame();\n\tCFont::InitPerFrame();\n\tCPad::UpdatePads();\n\tFrontEndMenuManager.Process();\n\n\tif(RsGlobal.quit)\n\t\treturn;\n\n\tCameraSize(Scene.camera, nil, SCREEN_VIEWWINDOW, SCREEN_ASPECT_RATIO);\n\tCVisibilityPlugins::SetRenderWareCamera(Scene.camera);\n\tRwCameraClear(Scene.camera, &gColourTop, CLEARMODE);\n\tif(!RsCameraBeginUpdate(Scene.camera))\n\t\treturn;\n\n\tDefinedState(); // seems redundant, but breaks resolution change.\n\tRenderMenus();\n#ifdef XBOX_MESSAGE_SCREEN\n\tFrontEndMenuManager.DrawOverlays();\n#endif\n\tDoFade();\n\tRender2dStuffAfterFade();\n\tCFont::DrawFonts();\n\tDoRWStuffEndOfFrame();\n}\n\nvoid\nInitialiseGame(void)\n{\n\tLoadingScreen(nil, nil, \"loadsc0\");\n\tCGame::Initialise(\"DATA\\\\GTA_VC.DAT\");\n}\n\nRsEventStatus\nAppEventHandler(RsEvent event, void *param)\n{\n\tswitch( event )\n\t{\n\t\tcase rsINITIALIZE:\n\t\t{\n\t\t\tCGame::InitialiseOnceBeforeRW();\n\t\t\treturn RsInitialize() ? rsEVENTPROCESSED : rsEVENTERROR;\n\t\t}\n\n\t\tcase rsCAMERASIZE:\n\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\n\t\t\tCameraSize(Scene.camera, (RwRect *)param,\n\t\t\t\tSCREEN_VIEWWINDOW, DEFAULT_ASPECT_RATIO);\n\t\t\t\n\t\t\treturn rsEVENTPROCESSED;\n\t\t}\n\n\t\tcase rsRWINITIALIZE:\n\t\t{\n\t\t\treturn Initialise3D(param) ? rsEVENTPROCESSED : rsEVENTERROR;\n\t\t}\n\n\t\tcase rsRWTERMINATE:\n\t\t{\n\t\t\tTerminate3D();\n\n\t\t\treturn rsEVENTPROCESSED;\n\t\t}\n\n\t\tcase rsTERMINATE:\n\t\t{\n\t\t\tCGame::FinalShutdown();\n\n\t\t\treturn rsEVENTPROCESSED;\n\t\t}\n\n\t\tcase rsPLUGINATTACH:\n\t\t{\n\t\t\treturn PluginAttach() ? rsEVENTPROCESSED : rsEVENTERROR;\n\t\t}\n\n\t\tcase rsINPUTDEVICEATTACH:\n\t\t{\n\t\t\tAttachInputDevices();\n\n\t\t\treturn rsEVENTPROCESSED;\n\t\t}\n\n\t\tcase rsIDLE:\n\t\t{\n\t\t\tIdle(param);\n\n\t\t\treturn rsEVENTPROCESSED;\n\t\t}\n\n\t\tcase rsFRONTENDIDLE:\n\t\t{\n\t\t\tFrontendIdle();\n\n\t\t\treturn rsEVENTPROCESSED;\n\t\t}\n\n\t\tcase rsACTIVATE:\n\t\t{\n\t\t\tparam ? DMAudio.ReacquireDigitalHandle() : DMAudio.ReleaseDigitalHandle();\n\n\t\t\treturn rsEVENTPROCESSED;\n\t\t}\n\n\t\tdefault:\n\t\t{\n\t\t\treturn rsEVENTNOTPROCESSED;\n\t\t}\n\t}\n}\n\n#ifndef MASTER\nvoid\nTheModelViewer(void)\n{\n#if (defined(GTA_PS2) || defined(GTA_XBOX))\n\t//TODO\n#else\n\n\t// This is not original. Because;\n\t// 1- We want 2D things to be initalized, whereas original AnimViewer doesn't use them. my additions marked with X\n\t// 2- VC Mobile code run it like main function(as opposed to III and LCS), so it has it's own loop inside it, but our func. already called in a loop.\n\n\tCDraw::CalculateAspectRatio(); // X\n\tCAnimViewer::Update();\n\tSetLightsWithTimeOfDayColour(Scene.world);\n\tCRenderer::ConstructRenderList();\n\tDoRWStuffStartOfFrame(CTimeCycle::GetSkyTopRed()*0.5f, CTimeCycle::GetSkyTopGreen()*0.5f, CTimeCycle::GetSkyTopBlue()*0.5f,\n\t\tCTimeCycle::GetSkyBottomRed(), CTimeCycle::GetSkyBottomGreen(), CTimeCycle::GetSkyBottomBlue(),\n\t\t255);\n\n\tCSprite2d::SetRecipNearClip(); // X\n\tCSprite2d::InitPerFrame(); // X\n\tCFont::InitPerFrame(); // X\n\tDefinedState();\n\tCVisibilityPlugins::InitAlphaEntityList();\n\tCAnimViewer::Render();\n\tRender2dStuff(); // X\n\tDoRWStuffEndOfFrame();\n\tCTimer::Update();\n#endif\n}\n#endif\n\n\n#ifdef GTA_PS2\nvoid TheGame(void)\n{\n\tprintf(\"Into TheGame!!!\\n\");\n\n\tPUSH_MEMID(MEMID_GAME);\t// NB: not popped\n\n\tCTimer::Initialise();\n\n\tCGame::Initialise(\"DATA\\\\GTA3.DAT\");\n\n\tConst char *splash = GetRandomSplashScreen(); // inlined here\n\n\tLoadingScreen(\"Starting Game\", NULL, splash);\n\n#ifdef GTA_PS2\n\t// TODO(MIAMI): not checked yet\n\tif (   TheMemoryCard.CheckCardInserted(CARD_ONE) == CMemoryCard::NO_ERR_SUCCESS\n\t\t&& TheMemoryCard.ChangeDirectory(CARD_ONE, TheMemoryCard.Cards[CARD_ONE].dir)\n\t\t&& TheMemoryCard.FindMostRecentFileName(CARD_ONE, TheMemoryCard.MostRecentFile) == true\n\t\t&& TheMemoryCard.CheckDataNotCorrupt(TheMemoryCard.MostRecentFile))\n\t{\n\t\tstrcpy(TheMemoryCard.LoadFileName, TheMemoryCard.MostRecentFile);\n\t\tTheMemoryCard.b_FoundRecentSavedGameWantToLoad = true;\n\n\t\tif (FrontEndMenuManager.m_PrefsLanguage != TheMemoryCard.GetLanguageToLoad())\n\t\t{\n\t\t\tFrontEndMenuManager.m_PrefsLanguage = TheMemoryCard.GetLanguageToLoad();\n\t\t\tTheText.Unload();\n\t\t\tTheText.Load();\n\t\t}\n\n\t\tCGame::currLevel = TheMemoryCard.GetLevelToLoad();\n\t}\n#else\n\t//TODO\n#endif\n\n\twhile (true)\n\t{\n\t\tif (FOUND_GAME_TO_LOAD)\n\t\t{\n\t\t\tConst char *splash1 = GetLevelSplashScreen(CGame::currLevel);\n\t\t\tLoadSplash(splash1);\n\t\t}\n\n\t\tWANT_TO_LOAD = false;\n\n\t\tCTimer::Update();\n\n\t\twhile (!(FrontEndMenuManager.m_bWantToRestart || FOUND_GAME_TO_LOAD))\n\t\t{\n\t\t\tCSprite2d::InitPerFrame();\n\t\t\tCFont::InitPerFrame();\n\n\t\t\tPUSH_MEMID(MEMID_GAME_PROCESS)\n\t\t\tCPointLights::InitPerFrame();\n\t\t\tCGame::Process();\n\t\t\tPOP_MEMID();\n\n\t\t\tDMAudio.Service();\n\n\t\t\tif (CGame::bDemoMode && CTimer::GetTimeInMilliseconds() > (3*60 + 30)*1000 && !CCutsceneMgr::IsCutsceneProcessing())\n\t\t\t{\n\t\t\t\tWANT_TO_LOAD = false;\n\t\t\t\tFrontEndMenuManager.m_bWantToRestart = true;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tif (FrontEndMenuManager.m_bWantToRestart || FOUND_GAME_TO_LOAD)\n\t\t\t\tbreak;\n\n\t\t\tSetLightsWithTimeOfDayColour(Scene.world);\n\n\t\t\tPUSH_MEMID(MEMID_RENDER);\n\n\t\t\tCRenderer::ConstructRenderList();\n\n\t\t\tif ((!FrontEndMenuManager.m_bMenuActive || FrontEndMenuManager.m_bRenderGameInMenu == true) && TheCamera.GetScreenFadeStatus() != FADE_2 )\n\t\t\t{\n\t\t\t\tCRenderer::PreRender();\n\t\t\t\t// TODO(MIAMI): something ps2all specific\n\n#ifdef FIX_BUGS\n\t\t\t\t// This has to be done BEFORE RwCameraBeginUpdate\n\t\t\t\tRwCameraSetFarClipPlane(Scene.camera, CTimeCycle::GetFarClip());\n\t\t\t\tRwCameraSetFogDistance(Scene.camera, CTimeCycle::GetFogStart());\n#endif\n\n\t\t\t\tif (CWeather::LightningFlash && !CCullZones::CamNoRain())\n\t\t\t\t\tDoRWStuffStartOfFrame_Horizon(255, 255, 255, 255, 255, 255, 255);\n\t\t\t\telse\n\t\t\t\t\tDoRWStuffStartOfFrame_Horizon(CTimeCycle::GetSkyTopRed(), CTimeCycle::GetSkyTopGreen(), CTimeCycle::GetSkyTopBlue(), CTimeCycle::GetSkyBottomRed(), CTimeCycle::GetSkyBottomGreen(), CTimeCycle::GetSkyBottomBlue(), 255);\n\n\t\t\t\tDefinedState();\n#ifndef FIX_BUGS\n\t\t\t\tRwCameraSetFarClipPlane(Scene.camera, CTimeCycle::GetFarClip());\n\t\t\t\tRwCameraSetFogDistance(Scene.camera, CTimeCycle::GetFogStart());\n#endif\n\n\t\t\t\tRenderScene();\n\t\t\t\tRenderDebugShit();\n\t\t\t\tRenderEffects();\n\n\t\t\t\tif ((TheCamera.m_BlurType == MOTION_BLUR_NONE || TheCamera.m_BlurType == MOTION_BLUR_LIGHT_SCENE) && TheCamera.m_ScreenReductionPercentage > 0.0f)\n\t\t\t\t\tTheCamera.SetMotionBlurAlpha(150);\n\t\t\t\tTheCamera.RenderMotionBlur();\n\n\t\t\t\tRender2dStuff();\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tCameraSize(Scene.camera, NULL, SCREEN_VIEWWINDOW, SCREEN_ASPECT_RATIO);\n\t\t\t\tCVisibilityPlugins::SetRenderWareCamera(Scene.camera);\n\t\t\t\tRwCameraClear(Scene.camera, &gColourTop, CLEARMODE);\n\t\t\t\tRsCameraBeginUpdate(Scene.camera);\n\t\t\t}\n\n\t\t\tRenderMenus();\n\n\t\t\tif (WANT_TO_LOAD)\n\t\t\t{\n\t\t\t\tPOP_MEMID();\t// MEMID_RENDER\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tDoFade();\n\t\t\tRender2dStuffAfterFade();\n\t\t\tCCredits::Render();\n\n\t\t\tDoRWStuffEndOfFrame();\n\n\t\t\twhile (frameCount < 2)\n\t\t\t\t;\n\n\t\t\tframeCount = 0;\n\n\t\t\tCTimer::Update();\n\n\t\t\tPOP_MEMID():\t// MEMID_RENDER\n\n\t\t\tif (g_SlowMode)\n\t\t\t\tProcessSlowMode();\n\t\t}\n\n\t\tCPad::ResetCheats();\n\t\tCPad::StopPadsShaking();\n\t\tDMAudio.ChangeMusicMode(MUSICMODE_DISABLE);\n\t\tCGame::ShutDownForRestart();\n\t\tCTimer::Stop();\n\n\t\tif (FrontEndMenuManager.m_bWantToRestart || FOUND_GAME_TO_LOAD)\n\t\t{\n\t\t\tif (FOUND_GAME_TO_LOAD)\n\t\t\t{\n\t\t\t\tFrontEndMenuManager.m_bWantToRestart = true;\n\t\t\t\tWANT_TO_LOAD = true;\n\t\t\t}\n\n\t\t\tCGame::InitialiseWhenRestarting();\n\t\t\tDMAudio.ChangeMusicMode(MUSICMODE_GAME);\n\t\t\tFrontEndMenuManager.m_bWantToRestart = false;\n\n\t\t\tcontinue;\n\t\t}\n\n\t\tbreak;\n\t}\n\n\tDMAudio.Terminate();\n}\n\n\nvoid SystemInit()\n{\n#ifdef USE_CUSTOM_ALLOCATOR\n\tInitMemoryMgr();\n#endif\n\t\n#ifdef GTA_PS2\n\tCFileMgr::InitCdSystem();\n\t\n\tchar path[256];\n\t\n\tsprintf(path, \"cdrom0:\\\\%s%s;1\", \"SYSTEM\\\\\", \"IOPRP241.IMG\");\n\t\n\tsceSifInitRpc(0);\n\t\n\twhile ( !sceSifRebootIop(path) )\n\t\t;\n\twhile( !sceSifSyncIop() )\n\t\t;\n\t\n\tsceSifInitRpc(0);\n\t\n\tCFileMgr::InitCdSystem();\n\t\n\tsceFsReset();\n\n\tCFileMgr::InitCd();\n\t\n\tchar modulepath[256];\n\t\n\tstrcpy(modulepath, \"cdrom0:\\\\\");\n\tstrcat(modulepath, \"SYSTEM\\\\\");\n\tstrcat(modulepath, \"SIO2MAN.IRX\");\n\tLoadModule(modulepath);\n\t\n\tstrcpy(modulepath, \"cdrom0:\\\\\");\n\tstrcat(modulepath, \"SYSTEM\\\\\");\n\tstrcat(modulepath, \"PADMAN.IRX\");\n\tLoadModule(modulepath);\n\t\n\tstrcpy(modulepath, \"cdrom0:\\\\\");\n\tstrcat(modulepath, \"SYSTEM\\\\\");\n\tstrcat(modulepath, \"LIBSD.IRX\");\n\tLoadModule(modulepath);\n\t\n\tstrcpy(modulepath, \"cdrom0:\\\\\");\n\tstrcat(modulepath, \"SYSTEM\\\\\");\n\tstrcat(modulepath, \"SDRDRV.IRX\");\n\tLoadModule(modulepath);\n\t\n\tstrcpy(modulepath, \"cdrom0:\\\\\");\n\tstrcat(modulepath, \"SYSTEM\\\\\");\n\tstrcat(modulepath, \"MCMAN.IRX\");\n\tLoadModule(modulepath);\n\t\n\tstrcpy(modulepath, \"cdrom0:\\\\\");\n\tstrcat(modulepath, \"SYSTEM\\\\\");\n\tstrcat(modulepath, \"MCSERV.IRX\");\n\tLoadModule(modulepath);\n\n\tstrcpy(modulepath, \"cdrom0:\\\\\");\n\tstrcat(modulepath, \"SYSTEM\\\\\");\n\tstrcat(modulepath, \"CDSTREAM.IRX\");\n\tLoadModule(modulepath);\n\n\tstrcpy(modulepath, \"cdrom0:\\\\\");\n\tstrcat(modulepath, \"SYSTEM\\\\\");\n\tstrcat(modulepath, \"SAMPMAN2.IRX\");\n\tLoadModule(modulepath);\n#endif\n\t\n\n#ifdef GTA_PS2\n\tThreadParam param;\n\t\n\tparam.entry = &IdleThread;\n\tparam.stack = idleThreadStack;\n\tparam.stackSize = 2048;\n\tparam.initPriority = 127;\n\tparam.gpReg = &_gp;\n\t\n\tint thread = CreateThread(&param);\n\tStartThread(thread, NULL);\n#else\n\t//\n#endif\n\t\n#ifdef GTA_PS2_STUFF\n\tCPad::Initialise();\n#endif\n\tCPad::GetPad(0)->Mode = 0;\n\t\n\tCGame::frenchGame = false;\n\tCGame::germanGame = false;\n\tCGame::nastyGame = true;\n\tFrontEndMenuManager.m_PrefsAllowNastyGame = true;\n\t\n#ifdef GTA_PS2\n\t// TODO(MIAMI): this code probably went elsewhere?\n\tint32 lang = sceScfGetLanguage();\n\tif ( lang  == SCE_ITALIAN_LANGUAGE )\n\t\tFrontEndMenuManager.m_PrefsLanguage = LANGUAGE_ITALIAN;\n\telse if ( lang  == SCE_SPANISH_LANGUAGE )\n\t\tFrontEndMenuManager.m_PrefsLanguage = LANGUAGE_SPANISH;\n\telse if ( lang  == SCE_GERMAN_LANGUAGE )\n\t{\n\t\tCGame::germanGame = true;\n\t\tCGame::nastyGame = false;\n\t\tFrontEndMenuManager.m_PrefsAllowNastyGame = false;\n\t\tFrontEndMenuManager.m_PrefsLanguage = LANGUAGE_GERMAN;\n\t}\n\telse if ( lang  == SCE_FRENCH_LANGUAGE )\n\t{\n\t\tCGame::frenchGame = true;\n\t\tCGame::nastyGame = false;\n\t\tFrontEndMenuManager.m_PrefsAllowNastyGame = false;\n\t\tFrontEndMenuManager.m_PrefsLanguage = LANGUAGE_FRENCH;\n\t}\n\telse\n\t\tFrontEndMenuManager.m_PrefsLanguage = LANGUAGE_AMERICAN;\n\t\n\tFrontEndMenuManager.InitialiseMenuContentsAfterLoadingGame();\n#else\n\t//\n#endif\n\t\n#ifdef GTA_PS2\n\tTheMemoryCard.Init();\n#endif\n}\n\nint VBlankCounter(int ca)\n{\n\tframeCount++;\n\tExitHandler();\n\treturn 0;\n}\n\n// linked against by RW!\nextern \"C\" void WaitVBlank(void)\n{\n\tint32 startFrame = frameCount;\n\twhile(startFrame == frameCount);\n}\n\nvoid GameInit(bool onlyRW)\n{\n\tif(onlyRW)\n\t{\n#ifdef GTA_PS2\n\t\tInitialise3D(nil);\n#else\n\t\tInitialise3D(nil);\t//TODO: window parameter\n#endif\n\t\tgameAlreadyInitialised = true;\n\t}\n\telse\n\t{\n\t\tif ( !gameAlreadyInitialised )\n#ifdef GTA_PS2\n\t\t\tInitialise3D(nil);\n#else\n\t\t\tInitialise3D(nil);\t//TODO: window parameter\n#endif\n\t\t}\n\n#ifdef GTA_PS2\n\t\tchar *files[] =\n\t\t{\n\t\t\t\"\\\\ANIM\\\\CUTS.IMG;1\",\n\t\t\t\"\\\\ANIM\\\\CUTS.DIR;1\",\n\t\t\t\"\\\\ANIM\\\\PED.IFP;1\",\n\t\t\t\"\\\\MODELS\\\\FRONTEN1.TXD;1\",\n\t\t\t\"\\\\MODELS\\\\FRONTEN2.TXD;1\",\n\t\t\t\"\\\\MODELS\\\\FONTS.TXD;1\",\n\t\t\t\"\\\\MODELS\\\\HUD.TXD;1\",\n\t\t\t\"\\\\MODELS\\\\PARTICLE.TXD;1\",\n\t\t\t\"\\\\MODELS\\\\MISC.TXD;1\",\n\t\t\t\"\\\\MODELS\\\\GENERIC.TXD;1\",\n\t\t\t\"\\\\MODELS\\\\GTA3.DIR;1\",\n\t\t\t// TODO: japanese?\n#ifdef GTA_PAL\n\t\t\t\"\\\\TEXT\\\\ENGLISH.GXT;1\",\n\t\t\t\"\\\\TEXT\\\\FRENCH.GXT;1\",\n\t\t\t\"\\\\TEXT\\\\GERMAN.GXT;1\",\n\t\t\t\"\\\\TEXT\\\\ITALIAN.GXT;1\",\n\t\t\t\"\\\\TEXT\\\\SPANISH.GXT;1\",\n#else\n\t\t\t\"\\\\TEXT\\\\AMERICAN.GXT;1\",\n#endif\n\t\t\t\"\\\\MODELS\\\\COLL\\\\GENERIC.COL;1\",\n\t\t\t\"\\\\MODELS\\\\COLL\\\\VEHICLES.COL;1\",\n\t\t\t\"\\\\MODELS\\\\COLL\\\\PEDS.COL;1\",\n\t\t\t\"\\\\MODELS\\\\COLL\\\\WEAPONS.COL;1\",\n\t\t\t\"\\\\MODELS\\\\GENERIC\\\\AIR_VLO.DFF;1\",\n\t\t\t\"\\\\MODELS\\\\GENERIC\\\\WHEELS.DFF;1\",\n\t\t\t\"\\\\MODELS\\\\GENERIC\\\\ARROW.DFF;1\",\n\t\t\t\"\\\\MODELS\\\\GENERIC\\\\ZONECYLB.DFF;1\",\n\t\t\t\"\\\\DATA\\\\HANDLING.CFG;1\",\n\t\t\t\"\\\\DATA\\\\SURFACE.DAT;1\",\n\t\t\t\"\\\\DATA\\\\PEDSTATS.DAT;1\",\n\t\t\t\"\\\\DATA\\\\TIMECYC.DAT;1\",\n\t\t\t\"\\\\DATA\\\\PARTICLE.CFG;1\",\n\t\t\t\"\\\\DATA\\\\DEFAULT.DAT;1\",\n\t\t\t\"\\\\DATA\\\\DEFAULT.IDE;1\",\n\t\t\t\"\\\\DATA\\\\GTA_VC.DAT;1\",\n\t\t\t\"\\\\DATA\\\\OBJECT.DAT;1\",\n\t\t\t\"\\\\DATA\\\\MAP.ZON;1\",\n\t\t\t\"\\\\DATA\\\\NAVIG.ZON;1\",\n\t\t\t\"\\\\DATA\\\\INFO.ZON;1\",\n\t\t\t\"\\\\DATA\\\\WATERPRO.DAT;1\",\n\t\t\t\"\\\\DATA\\\\MAIN.SCM;1\",\n\t\t\t\"\\\\DATA\\\\CARCOLS.DAT;1\",\n\t\t\t\"\\\\DATA\\\\PED.DAT;1\",\n\t\t\t\"\\\\DATA\\\\FISTFITE.DAT;1\",\n\t\t\t\"\\\\DATA\\\\WEAPON.DAT;1\",\n\t\t\t\"\\\\DATA\\\\PEDGRP.DAT;1\",\n\t\t\t\"\\\\DATA\\\\PATHS\\\\FLIGHT.DAT;1\",\n\t\t\t\"\\\\DATA\\\\PATHS\\\\FLIGHT2.DAT;1\",\n\t\t\t\"\\\\DATA\\\\PATHS\\\\FLIGHT3.DAT;1\",\n\t\t\t\"\\\\DATA\\\\PATHS\\\\SPATH0.DAT;1\",\n\t\t\t\"\\\\DATA\\\\MAPS\\\\LITTLEHA\\\\LITTLEHA.IDE;1\",\n\t\t\t\"\\\\DATA\\\\MAPS\\\\DOWNTOWN\\\\DOWNTOWN.IDE;1\",\n\t\t\t\"\\\\DATA\\\\MAPS\\\\DOWNTOWS\\\\DOWNTOWS.IDE;1\",\n\t\t\t\"\\\\DATA\\\\MAPS\\\\DOCKS\\\\DOCKS.IDE;1\",\n\t\t\t\"\\\\DATA\\\\MAPS\\\\WASHINTN\\\\WASHINTN.IDE;1\",\n\t\t\t\"\\\\DATA\\\\MAPS\\\\WASHINTS\\\\WASHINTS.IDE;1\",\n\t\t\t\"\\\\DATA\\\\MAPS\\\\OCEANDRV\\\\OCEANDRV.IDE;1\",\n\t\t\t\"\\\\DATA\\\\MAPS\\\\OCEANDN\\\\OCEANDN.IDE;1\",\n\t\t\t\"\\\\DATA\\\\MAPS\\\\GOLF\\\\GOLF.IDE;1\",\n\t\t\t\"\\\\DATA\\\\MAPS\\\\BRIDGE\\\\BRIDGE.IDE;1\",\n\t\t\t\"\\\\DATA\\\\MAPS\\\\STARISL\\\\STARISL.IDE;1\",\n\t\t\t\"\\\\DATA\\\\MAPS\\\\NBEACHBT\\\\NBEACHBT.IDE;1\",\n\t\t\t\"\\\\DATA\\\\MAPS\\\\NBEACHW\\\\NBEACHW.IDE;1\",\n\t\t\t\"\\\\DATA\\\\MAPS\\\\NBEACH\\\\NBEACH.IDE;1\",\n\t\t\t\"\\\\DATA\\\\MAPS\\\\BANK\\\\BANK.IDE;1\",\n\t\t\t\"\\\\DATA\\\\MAPS\\\\MALL\\\\MALL.IDE;1\",\n\t\t\t\"\\\\DATA\\\\MAPS\\\\YACHT\\\\YACHT.IDE;1\",\n\t\t\t\"\\\\DATA\\\\MAPS\\\\CISLAND\\\\CISLAND.IDE;1\",\n\t\t\t\"\\\\DATA\\\\MAPS\\\\CLUB\\\\CLUB.IDE;1\",\n\t\t\t\"\\\\DATA\\\\MAPS\\\\HOTEL\\\\HOTEL.IDE;1\",\n\t\t\t\"\\\\DATA\\\\MAPS\\\\LAWYERS\\\\LAWYERS.IDE;1\",\n\t\t\t\"\\\\DATA\\\\MAPS\\\\STRIPCLB\\\\STRIPCLB.IDE;1\",\n\t\t\t\"\\\\DATA\\\\MAPS\\\\AIRPORT\\\\AIRPORT.IDE;1\",\n\t\t\t\"\\\\DATA\\\\MAPS\\\\HAITI\\\\HAITI.IDE;1\",\n\t\t\t\"\\\\DATA\\\\MAPS\\\\HAITIN\\\\HAITIN.IDE;1\",\n\t\t\t\"\\\\DATA\\\\MAPS\\\\CONCERTH\\\\CONCERTH.IDE;1\",\n\t\t\t\"\\\\DATA\\\\MAPS\\\\MANSION\\\\MANSION.IDE;1\",\n\t\t\t\"\\\\DATA\\\\MAPS\\\\ISLANDSF\\\\ISLANDSF.IDE;1\",\n\t\t\t\"\\\\DATA\\\\MAPS\\\\LITTLEHA\\\\LITTLEHA.IPL;1\",\n\t\t\t\"\\\\DATA\\\\MAPS\\\\DOWNTOWN\\\\DOWNTOWN.IPL;1\",\n\t\t\t\"\\\\DATA\\\\MAPS\\\\DOWNTOWS\\\\DOWNTOWS.IPL;1\",\n\t\t\t\"\\\\DATA\\\\MAPS\\\\DOCKS\\\\DOCKS.IPL;1\",\n\t\t\t\"\\\\DATA\\\\MAPS\\\\WASHINTN\\\\WASHINTN.IPL;1\",\n\t\t\t\"\\\\DATA\\\\MAPS\\\\WASHINTS\\\\WASHINTS.IPL;1\",\n\t\t\t\"\\\\DATA\\\\MAPS\\\\OCEANDRV\\\\OCEANDRV.IPL;1\",\n\t\t\t\"\\\\DATA\\\\MAPS\\\\OCEANDN\\\\OCEANDN.IPL;1\",\n\t\t\t\"\\\\DATA\\\\MAPS\\\\GOLF\\\\GOLF.IPL;1\",\n\t\t\t\"\\\\DATA\\\\MAPS\\\\BRIDGE\\\\BRIDGE.IPL;1\",\n\t\t\t\"\\\\DATA\\\\MAPS\\\\STARISL\\\\STARISL.IPL;1\",\n\t\t\t\"\\\\DATA\\\\MAPS\\\\NBEACHBT\\\\NBEACHBT.IPL;1\",\n\t\t\t\"\\\\DATA\\\\MAPS\\\\NBEACH\\\\NBEACH.IPL;1\",\n\t\t\t\"\\\\DATA\\\\MAPS\\\\NBEACHW\\\\NBEACHW.IPL;1\",\n\t\t\t\"\\\\DATA\\\\MAPS\\\\CISLAND\\\\CISLAND.IPL;1\",\n\t\t\t\"\\\\DATA\\\\MAPS\\\\AIRPORT\\\\AIRPORT.IPL;1\",\n\t\t\t\"\\\\DATA\\\\MAPS\\\\HAITI\\\\HAITI.IPL;1\",\n\t\t\t\"\\\\DATA\\\\MAPS\\\\HAITIN\\\\HAITIN.IPL;1\",\n\t\t\t\"\\\\DATA\\\\MAPS\\\\ISLANDSF\\\\ISLANDSF.IPL;1\",\n\t\t\t\"\\\\DATA\\\\MAPS\\\\BANK\\\\BANK.IPL;1\",\n\t\t\t\"\\\\DATA\\\\MAPS\\\\MALL\\\\MALL.IPL;1\",\n\t\t\t\"\\\\DATA\\\\MAPS\\\\YACHT\\\\YACHT.IPL;1\",\n\t\t\t\"\\\\DATA\\\\MAPS\\\\CLUB\\\\CLUB.IPL;1\",\n\t\t\t\"\\\\DATA\\\\MAPS\\\\HOTEL\\\\HOTEL.IPL;1\",\n\t\t\t\"\\\\DATA\\\\MAPS\\\\LAWYERS\\\\LAWYERS.IPL;1\",\n\t\t\t\"\\\\DATA\\\\MAPS\\\\STRIPCLB\\\\STRIPCLB.IPL;1\",\n\t\t\t\"\\\\DATA\\\\MAPS\\\\CONCERTH\\\\CONCERTH.IPL;1\",\n\t\t\t\"\\\\DATA\\\\MAPS\\\\MANSION\\\\MANSION.IPL;1\",\n\t\t\t\"\\\\DATA\\\\MAPS\\\\GENERIC.IDE;1\",\n\t\t\t\"\\\\DATA\\\\OCCLU.IPL;1\",\n\t\t\t\"\\\\DATA\\\\MAPS\\\\PATHS.IPL;1\",\n\t\t\t\"\\\\TXD\\\\LOADSC0.TXD;1\",\n\t\t\t\"\\\\TXD\\\\LOADSC1.TXD;1\",\n\t\t\t\"\\\\TXD\\\\LOADSC2.TXD;1\",\n\t\t\t\"\\\\TXD\\\\LOADSC3.TXD;1\",\n\t\t\t\"\\\\TXD\\\\LOADSC4.TXD;1\",\n\t\t\t\"\\\\TXD\\\\LOADSC5.TXD;1\",\n\t\t\t\"\\\\TXD\\\\LOADSC6.TXD;1\",\n\t\t\t\"\\\\TXD\\\\LOADSC7.TXD;1\",\n\t\t\t\"\\\\TXD\\\\LOADSC8.TXD;1\",\n\t\t\t\"\\\\TXD\\\\LOADSC9.TXD;1\",\n\t\t\t\"\\\\TXD\\\\LOADSC10.TXD;1\",\n\t\t\t\"\\\\TXD\\\\LOADSC11.TXD;1\",\n\t\t\t\"\\\\TXD\\\\LOADSC12.TXD;1\",\n\t\t\t\"\\\\TXD\\\\LOADSC13.TXD;1\",\n\t\t\t\"\\\\TXD\\\\SPLASH1.TXD;1\"\n\t\t};\n\t\t\n\t\tfor ( int32 i = 0; i < ARRAY_SIZE(files); i++ )\n\t\t\tSkyRegisterFileOnCd([i]);\n#endif\n\t\t\n#ifdef GTA_PS2\n\t\tAddIntcHandler(INTC_VBLANK_S, VBlankCounter, 0);\n#endif\n\t\t\n#ifdef GTA_PS2\n\t\tsceCdCLOCK rtc;\n\t\tsceCdReadClock(&rtc);\n\t\tuint32 seed = rtc.minute + rtc.day;\n\t\tuint32 seed2 = (seed << 4)-seed;\n\t\tuint32 seed3 = (seed2 << 4)-seed2;\n\t\tsrand ((seed3<<4)+rtc.second);\n#else\n\t\t//TODO: mysrand();\n#endif\n\t\t\n\t\t// gameAlreadyInitialised = true;\t// why is this gone?\n\t}\n}\n\nint32 SkipAllMPEGs;\nint32 gMemoryStickLoadOK;\n\nvoid PlayIntroMPEGs()\n{\n#ifdef GTA_PS2\n\tif (gameAlreadyInitialised)\n\t\tRpSkySuspend();\n\n\tInitMPEGPlayer();\n\n\tfloat skipTime;\t\t// wrong type, should be int\n#ifdef GTA_PAL\n\tif(gMemoryStickLoadOK)\n\t\tskipTime = 2500000;\n\telse\n\t\tskipTime = 5300000;\n\n\tif(!SkipAllMPEGs)\n\t\tPlayMPEG(\"cdrom0:\\\\MOVIES\\\\VCPAL.PSS;1\", false, unk);\n\n\tif(!SkipAllMPEGs){\n\t\tSkipAllMPEGs = true;\n\t\tPlayMPEG(\"cdrom0:\\\\MOVIES\\\\VICEPAL.PSS;1\", true, 0);\n\t}\n#else\n\tif(gMemoryStickLoadOK)\n\t\tskipTime = 2750000;\n\telse\n\t\tskipTime = 5500000;\n\n\tif(!SkipAllMPEGs)\n\t\tPlayMPEG(\"cdrom0:\\\\MOVIES\\\\VCNTSC.PSS;1\", false, unk);\n\n\tif(!SkipAllMPEGs){\n\t\tSkipAllMPEGs = true;\n\t\tPlayMPEG(\"cdrom0:\\\\MOVIES\\\\VICE.PSS;1\", true, 0);\n\t}\n#endif\n\n\tShutdownMPEGPlayer();\n\n\tif ( gameAlreadyInitialised )\n\t\tRpSkyResume();\n#else\n\t//TODO\n#endif\n}\n\nint\nmain(int argc, char *argv[])\n{\n#ifdef __MWERKS__\n\tmwInit(); // metrowerks initialisation\n#endif\n\n\tSystemInit();\n\n\tif(RsEventHandler(rsINITIALIZE, nil) == rsEVENTERROR)\n\t\treturn 0;\n\n#ifdef GTA_PS2\n\tint32 r = TheMemoryCard.CheckCardStateAtGameStartUp(CARD_ONE);\n\t\t\n\tif ( r == CMemoryCard::ERR_DIRNOENTRY  || r == CMemoryCard::ERR_NOFORMAT )\n\t{\n\t\tGameInit(true);\n\t\t\n\t\tTheText.Unload();\n\t\tTheText.Load();\n\t\t\n\t\tCFont::Initialise();\n\t\t\n\t\tFrontEndMenuManager.DrawMemoryCardStartUpMenus();\n\t}else if(r == CMemoryCard::ERR_OPENNOENTRY)\n\t\tgMemoryStickLoadOK = false;\n\telse if(r == CMemoryCard::ERR_NONE)\n\t\tgMemoryStickLoadOK = true;\n#endif\n\n\tPlayIntroMPEGs();\n\n\tGameInit(false);\n\n\tframeCount = 0;\n\twhile(frameCount < 100);\n\n\tCGame::InitialiseOnceAfterRW();\n\n\tTheGame();\n\n#if 0\t// maybe ifndef FINAL or MASTER?\n\tCGame::ShutDown();\n\t\n\tRwEngineStop();\n\tRwEngineClose();\n\tRwEngineTerm();\n\t\n#ifdef __MWERKS__\n\tmwExit(); // metrowerks shutdown\n#endif\n#endif\n\treturn 0;\n}\n#endif\n"
  },
  {
    "path": "src/core/main.h",
    "content": "#pragma once\n\n#ifndef FINAL\n// defined in RwHelpder.cpp\nvoid PushRendergroup(const char *name);\nvoid PopRendergroup(void);\n#define PUSH_RENDERGROUP(str) PushRendergroup(str)\n#define POP_RENDERGROUP() PopRendergroup()\n#else\n#define PUSH_RENDERGROUP(str)\n#define POP_RENDERGROUP()\n#endif\n\nstruct GlobalScene\n{\n\tRpWorld *world;\n\tRwCamera *camera;\n};\nextern GlobalScene Scene;\n\nextern uint8 work_buff[55000];\nextern char gString[256];\nextern char gString2[512];\nextern wchar gUString[256];\nextern wchar gUString2[256];\nextern bool gbPrintShite;\nextern bool gbModelViewer;\n#ifdef TIMEBARS\nextern bool gbShowTimebars;\n#else\n#define gbShowTimebars false\n#endif\n\n#ifndef FINAL\nextern bool gbPrintMemoryUsage;\n#endif\n\nclass CSprite2d;\n\nbool DoRWStuffStartOfFrame(int16 TopRed, int16 TopGreen, int16 TopBlue, int16 BottomRed, int16 BottomGreen, int16 BottomBlue, int16 Alpha);\nbool DoRWStuffStartOfFrame_Horizon(int16 TopRed, int16 TopGreen, int16 TopBlue, int16 BottomRed, int16 BottomGreen, int16 BottomBlue, int16 Alpha);\nvoid DoRWStuffEndOfFrame(void);\nvoid PreAllocateRwObjects(void);\nvoid InitialiseGame(void);\nvoid LoadingScreen(const char *str1, const char *str2, const char *splashscreen);\nvoid LoadingIslandScreen(const char *levelName);\nCSprite2d *LoadSplash(const char *name);\nvoid DestroySplashScreen(void);\nConst char *GetLevelSplashScreen(int level);\nConst char *GetRandomSplashScreen(void);\nvoid LittleTest(void);\nvoid ValidateVersion();\nvoid ResetLoadingScreenBar(void);\n#ifndef MASTER\nvoid TheModelViewer(void);\n#endif\n\n#ifdef LOAD_INI_SETTINGS\nbool LoadINISettings();\nvoid SaveINISettings();\nvoid LoadINIControllerSettings();\nvoid SaveINIControllerSettings();\n#endif\n\n#ifdef NEW_RENDERER\nextern bool gbNewRenderer;\nbool FredIsInFirstPersonCam(void);\n#endif\n\n#ifdef DRAW_GAME_VERSION_TEXT\nextern bool gbDrawVersionText;\n#endif\n\n#ifdef NO_MOVIES\nextern bool gbNoMovies;\n#endif\n"
  },
  {
    "path": "src/core/obrstr.cpp",
    "content": "#include \"common.h\"\n#include \"Debug.h\"\n#include \"obrstr.h\"\n\nchar obrstr[128];\nchar obrstr2[128];\n\nvoid ObrInt(int32 n1)\n{\n\tIntToStr(n1, obrstr);\n\tCDebug::DebugAddText(obrstr);\n}\n\nvoid ObrInt2(int32 n1, int32 n2)\n{\n\tIntToStr(n1, obrstr);\n\tstrcat(obrstr, \"  \");\n\tIntToStr(n2, obrstr2);\n\tstrcat(obrstr, obrstr2);\n\tCDebug::DebugAddText(obrstr);\n}\n\nvoid ObrInt3(int32 n1, int32 n2, int32 n3)\n{\n\tIntToStr(n1, obrstr);\n\tstrcat(obrstr, \"  \");\n\tIntToStr(n2, obrstr2);\n\tstrcat(obrstr, obrstr2);\n\tstrcat(obrstr, \"  \");\n\tIntToStr(n3, obrstr2);\n\tstrcat(obrstr, obrstr2);\n\tCDebug::DebugAddText(obrstr);\n}\n\nvoid ObrInt4(int32 n1, int32 n2, int32 n3, int32 n4)\n{\n\tIntToStr(n1, obrstr);\n\tstrcat(obrstr, \"  \");\n\tIntToStr(n2, obrstr2);\n\tstrcat(obrstr, obrstr2);\n\tstrcat(obrstr, \"  \");\n\tIntToStr(n3, obrstr2);\n\tstrcat(obrstr, obrstr2);\n\tstrcat(obrstr, \"  \");\n\tIntToStr(n4, obrstr2);\n\tstrcat(obrstr, obrstr2);\n\tCDebug::DebugAddText(obrstr);\n}\n\nvoid ObrInt5(int32 n1, int32 n2, int32 n3, int32 n4, int32 n5)\n{\n\tIntToStr(n1, obrstr);\n\tstrcat(obrstr, \"  \");\n\tIntToStr(n2, obrstr2);\n\tstrcat(obrstr, obrstr2);\n\tstrcat(obrstr, \"  \");\n\tIntToStr(n3, obrstr2);\n\tstrcat(obrstr, obrstr2);\n\tstrcat(obrstr, \"  \");\n\tIntToStr(n4, obrstr2);\n\tstrcat(obrstr, obrstr2);\n\tstrcat(obrstr, \"  \");\n\tIntToStr(n5, obrstr2);\n\tstrcat(obrstr, obrstr2);\n\tCDebug::DebugAddText(obrstr);\n}\n\nvoid ObrInt6(int32 n1, int32 n2, int32 n3, int32 n4, int32 n5, int32 n6)\n{\n\tIntToStr(n1, obrstr);\n\tstrcat(obrstr, \"  \");\n\tIntToStr(n2, obrstr2);\n\tstrcat(obrstr, obrstr2);\n\tstrcat(obrstr, \"  \");\n\tIntToStr(n3, obrstr2);\n\tstrcat(obrstr, obrstr2);\n\tstrcat(obrstr, \"  \");\n\tIntToStr(n4, obrstr2);\n\tstrcat(obrstr, obrstr2);\n\tstrcat(obrstr, \"  \");\n\tIntToStr(n5, obrstr2);\n\tstrcat(obrstr, obrstr2);\n\tstrcat(obrstr, \"  \");\n\tIntToStr(n6, obrstr2);\n\tstrcat(obrstr, obrstr2);\n\tCDebug::DebugAddText(obrstr);\n}\n\nvoid IntToStr(int32 inNum, char *outStr)\n{\n\tbool isNeg = inNum < 0;\n\n\tif (isNeg) {\n\t\tinNum = -inNum;\n\t\t*outStr = '-';\n\t}\n\n\tint16 digits = 1;\n\n\tif (inNum > 9) {\n\t\tint32 _inNum = inNum;\n\t\tdo {\n\t\t\tdigits++;\n\t\t\t_inNum /= 10;\n\t\t} while (_inNum > 9);\n\t}\n\n\tint32 strSize = digits;\n\tif (isNeg)\n\t\tstrSize++;\n\n\tchar *pStr = &outStr[strSize];\n\tint32 i = 0;\n\tdo {\n\t\t*(pStr-- - 1) = (inNum % 10) + '0';\n\t\tinNum /= 10;\n\t} while (++i < strSize);\n\toutStr[strSize] = '\\0';\n}"
  },
  {
    "path": "src/core/obrstr.h",
    "content": "#pragma once\n\nvoid ObrInt(int32 n1);\nvoid ObrInt2(int32 n1, int32 n2);\nvoid ObrInt3(int32 n1, int32 n2, int32 n3);\nvoid ObrInt4(int32 n1, int32 n2, int32 n3, int32 n4);\nvoid ObrInt5(int32 n1, int32 n2, int32 n3, int32 n4, int32 n5);\nvoid ObrInt6(int32 n1, int32 n2, int32 n3, int32 n4, int32 n5, int32 n6);\nvoid IntToStr(int32 inNum, char *outStr);"
  },
  {
    "path": "src/core/re3.cpp",
    "content": "#include <csignal>\n#define WITHWINDOWS\n#include \"common.h\"\n#if defined DETECT_JOYSTICK_MENU && defined XINPUT\n#include <xinput.h>\n#if !defined(PSAPI_VERSION) || (PSAPI_VERSION > 1)\n#pragma comment( lib, \"Xinput9_1_0.lib\" )\n#else\n#pragma comment( lib, \"Xinput.lib\" )\n#endif\n#endif\n#include \"Renderer.h\"\n#include \"Occlusion.h\"\n#include \"Credits.h\"\n#include \"Camera.h\"\n#include \"Weather.h\"\n#include \"Timecycle.h\"\n#include \"Clock.h\"\n#include \"World.h\"\n#include \"Vehicle.h\"\n#include \"ModelIndices.h\"\n#include \"Streaming.h\"\n#include \"Boat.h\"\n#include \"Heli.h\"\n#include \"Automobile.h\"\n#include \"Bike.h\"\n#include \"Console.h\"\n#include \"Debug.h\"\n#include \"Hud.h\"\n#include \"SceneEdit.h\"\n#include \"Pad.h\"\n#include \"PlayerPed.h\"\n#include \"Radar.h\"\n#include \"debugmenu.h\"\n#include \"Frontend.h\"\n#include \"WaterLevel.h\"\n#include \"main.h\"\n#include \"Script.h\"\n#include \"MBlur.h\"\n#include \"postfx.h\"\n#include \"custompipes.h\"\n#include \"MemoryHeap.h\"\n#include \"FileMgr.h\"\n#include \"Camera.h\"\n#include \"MBlur.h\"\n#include \"ControllerConfig.h\"\n\n#ifdef DETECT_JOYSTICK_MENU\n#include \"crossplatform.h\"\n#endif\n\n#ifndef _WIN32\n#include \"assert.h\"\n#include <stdarg.h>\n#endif\n\n#include <list>\n\n#ifdef RWLIBS\nextern \"C\" int vsprintf(char* const _Buffer, char const* const _Format, va_list  _ArgList);\n#endif\n\n\n#ifdef USE_PS2_RAND\nunsigned long long myrand_seed = 1;\n#else\nunsigned long int myrand_seed = 1;\n#endif\n\nint\nmyrand(void)\n{\n#ifdef USE_PS2_RAND\n\t// Use our own implementation of rand, stolen from PS2\n\tmyrand_seed = 0x5851F42D4C957F2D * myrand_seed + 1;\n\treturn ((myrand_seed >> 32) & 0x7FFFFFFF);\n#else\n\t// or original codewarrior rand\n\tmyrand_seed = myrand_seed * 1103515245 + 12345;\n\treturn((myrand_seed >> 16) & 0x7FFF);\n#endif\n}\n\nvoid\nmysrand(unsigned int seed)\n{\n\tmyrand_seed = seed;\n}\n\n#ifdef CUSTOM_FRONTEND_OPTIONS\n#include \"frontendoption.h\"\n\n\n\n#ifdef MORE_LANGUAGES\nvoid LangPolSelect(int8 action)\n{\n\tif (action == FEOPTION_ACTION_SELECT) {\n\t\tFrontEndMenuManager.m_PrefsLanguage = CMenuManager::LANGUAGE_POLISH;\n\t\tFrontEndMenuManager.m_bFrontEnd_ReloadObrTxtGxt = true;\n\t\tFrontEndMenuManager.InitialiseChangedLanguageSettings();\n\t\tFrontEndMenuManager.SaveSettings();\n\t}\n}\n\nvoid LangRusSelect(int8 action)\n{\n\tif (action == FEOPTION_ACTION_SELECT) {\n\t\tFrontEndMenuManager.m_PrefsLanguage = CMenuManager::LANGUAGE_RUSSIAN;\n\t\tFrontEndMenuManager.m_bFrontEnd_ReloadObrTxtGxt = true;\n\t\tFrontEndMenuManager.InitialiseChangedLanguageSettings();\n\t\tFrontEndMenuManager.SaveSettings();\n\t}\n}\n\nvoid LangJapSelect(int8 action)\n{\n\tif (action == FEOPTION_ACTION_SELECT) {\n\t\tFrontEndMenuManager.m_PrefsLanguage = CMenuManager::LANGUAGE_JAPANESE;\n\t\tFrontEndMenuManager.m_bFrontEnd_ReloadObrTxtGxt = true;\n\t\tFrontEndMenuManager.InitialiseChangedLanguageSettings();\n\t\tFrontEndMenuManager.SaveSettings();\n\t}\n}\n#endif\n\nvoid\nCustomFrontendOptionsPopulate(void)\n{\n\t// Moved to an array in MenuScreensCustom.cpp, but APIs are still available. see frontendoption.h\n\n\tint fd;\n\t// These work only if we have neo folder, so they're dynamically added\n#ifdef EXTENDED_PIPELINES\n\tconst char *vehPipelineNames[] = { \"FED_MFX\", \"FED_NEO\" };\n\tconst char *off_on[] = { \"FEM_OFF\", \"FEM_ON\" };\n\tfd = CFileMgr::OpenFile(\"neo/neo.txd\",\"r\");\n\tif (fd) {\n#ifdef GRAPHICS_MENU_OPTIONS\n\t\tFrontendOptionSetCursor(MENUPAGE_GRAPHICS_SETTINGS, -3, false);\n\t\tFrontendOptionAddSelect(\"FED_VPL\", 0, 0, MENUALIGN_LEFT, vehPipelineNames, ARRAY_SIZE(vehPipelineNames), (int8*)&CustomPipes::VehiclePipeSwitch, false, nil, \"Graphics\", \"VehiclePipeline\");\n\t\tFrontendOptionAddSelect(\"FED_PRM\", 0, 0, MENUALIGN_LEFT, off_on, 2, (int8*)&CustomPipes::RimlightEnable, false, nil, \"Graphics\", \"NeoRimLight\");\n\t\tFrontendOptionAddSelect(\"FED_WLM\", 0, 0, MENUALIGN_LEFT, off_on, 2, (int8*)&CustomPipes::LightmapEnable, false, nil, \"Graphics\", \"NeoLightMaps\");\n\t\tFrontendOptionAddSelect(\"FED_RGL\", 0, 0, MENUALIGN_LEFT, off_on, 2, (int8*)&CustomPipes::GlossEnable, false, nil, \"Graphics\", \"NeoRoadGloss\");\n#else\n\t\tFrontendOptionSetCursor(MENUPAGE_DISPLAY_SETTINGS, -3, false);\n\t\tFrontendOptionAddSelect(\"FED_VPL\", 0, 0, MENUALIGN_LEFT, vehPipelineNames, ARRAY_SIZE(vehPipelineNames), (int8*)&CustomPipes::VehiclePipeSwitch, false, nil, \"Graphics\", \"VehiclePipeline\");\n\t\tFrontendOptionAddSelect(\"FED_PRM\", 0, 0, MENUALIGN_LEFT, off_on, 2, (int8*)&CustomPipes::RimlightEnable, false, nil, \"Graphics\", \"NeoRimLight\");\n\t\tFrontendOptionAddSelect(\"FED_WLM\", 0, 0, MENUALIGN_LEFT, off_on, 2, (int8*)&CustomPipes::LightmapEnable, false, nil, \"Graphics\", \"NeoLightMaps\");\n\t\tFrontendOptionAddSelect(\"FED_RGL\", 0, 0, MENUALIGN_LEFT, off_on, 2, (int8*)&CustomPipes::GlossEnable, false, nil, \"Graphics\", \"NeoRoadGloss\");\n#endif\n\t\tCFileMgr::CloseFile(fd);\n\t}\n#endif\n\t// Add outsourced language translations, if files are found\n#ifdef MORE_LANGUAGES\n\tint fd2;\n\tFrontendOptionSetCursor(MENUPAGE_LANGUAGE_SETTINGS, 5, false);\n#if 0\n\tif (fd = CFileMgr::OpenFile(\"text/polish.gxt\")) {\n\t\tif (fd2 = CFileMgr::OpenFile(\"models/fonts_p.txd\")) {\n\t\t\tFrontendOptionAddDynamic(\"FEL_POL\", 0, 0, MENUALIGN_CENTER, nil, nil, LangPolSelect, nil, nil);\n\t\t\tCFileMgr::CloseFile(fd2);\n\t\t}\n\t\tCFileMgr::CloseFile(fd);\n\t}\n#endif\n\n\tif (fd = CFileMgr::OpenFile(\"text/russian.gxt\")) {\n\t\tif (fd2 = CFileMgr::OpenFile(\"models/fonts_r.txd\")) {\n\t\t\tFrontendOptionAddDynamic(\"FEL_RUS\", 0, 0, MENUALIGN_CENTER, nil, nil, LangRusSelect, nil, nil);\n\t\t\tCFileMgr::CloseFile(fd2);\n\t\t}\n\t\tCFileMgr::CloseFile(fd);\n\t}\n\n#if 0\n\tif (fd = CFileMgr::OpenFile(\"text/japanese.gxt\")) {\n\t\tif (fd2 = CFileMgr::OpenFile(\"models/fonts_j.txd\")) {\n\t\t\tFrontendOptionAddDynamic(\"FEL_JAP\", 0, 0, MENUALIGN_CENTER, nil, nil, LangJapSelect, nil, nil);\n\t\t\tCFileMgr::CloseFile(fd2);\n\t\t}\n\t\tCFileMgr::CloseFile(fd);\n\t}\n#endif\n#endif\n\n}\n#endif\n\n#ifdef LOAD_INI_SETTINGS\n#include \"ini_parser.hpp\"\n\nlinb::ini cfg;\nbool ReadIniIfExists(const char *cat, const char *key, uint32 *out)\n{\n\tstd::string strval = cfg.get(cat, key, \"\\xBA\");\n\tconst char *value = strval.c_str();\n\tchar *endPtr;\n\tif (value && value[0] != '\\xBA') {\n\t\t*out = strtoul(value, &endPtr, 0);\n\t\treturn true;\n\t}\n\treturn false;\n}\n\nbool ReadIniIfExists(const char *cat, const char *key, bool *out)\n{\n\tstd::string strval = cfg.get(cat, key, \"\\xBA\");\n\tconst char *value = strval.c_str();\n\tchar *endPtr;\n\tif (value && value[0] != '\\xBA') {\n\t\t*out = strtoul(value, &endPtr, 0);\n\t\treturn true;\n\t}\n\treturn false;\n}\n\nbool ReadIniIfExists(const char *cat, const char *key, int32 *out)\n{\n\tstd::string strval = cfg.get(cat, key, \"\\xBA\");\n\tconst char *value = strval.c_str();\n\tchar *endPtr;\n\tif (value && value[0] != '\\xBA') {\n\t\t*out = strtol(value, &endPtr, 0);\n\t\treturn true;\n\t}\n\treturn false;\n}\n\nbool ReadIniIfExists(const char *cat, const char *key, int8 *out)\n{\n\tstd::string strval = cfg.get(cat, key, \"\\xBA\");\n\tconst char *value = strval.c_str();\n\tchar *endPtr;\n\tif (value && value[0] != '\\xBA') {\n\t\t*out = strtol(value, &endPtr, 0);\n\t\treturn true;\n\t}\n\treturn false;\n}\n\nbool ReadIniIfExists(const char *cat, const char *key, float *out)\n{\n\tstd::string strval = cfg.get(cat, key, \"\\xBA\");\n\tconst char *value = strval.c_str();\n\tif (value && value[0] != '\\xBA') {\n\t\t*out = atof(value);\n\t\treturn true;\n\t}\n\treturn false;\n}\n\nbool ReadIniIfExists(const char *cat, const char *key, char *out, int size)\n{\n\tstd::string strval = cfg.get(cat, key, \"\\xBA\");\n\tconst char *value = strval.c_str();\n\tif (value && value[0] != '\\xBA') {\n\t\tstrncpy(out, value, size);\n\t\treturn true;\n\t}\n\treturn false;\n}\n\nvoid StoreIni(const char *cat, const char *key, uint32 val)\n{\n\tchar temp[10];\nsprintf(temp, \"%u\", val);\n\tcfg.set(cat, key, temp);\n}\n\nvoid StoreIni(const char *cat, const char *key, uint8 val)\n{\n\tchar temp[10];\n\tsprintf(temp, \"%u\", (uint32)val);\n\tcfg.set(cat, key, temp);\n}\n\nvoid StoreIni(const char *cat, const char *key, int32 val)\n{\n\tchar temp[10];\n\tsprintf(temp, \"%d\", val);\n\tcfg.set(cat, key, temp);\n}\n\nvoid StoreIni(const char *cat, const char *key, int8 val)\n{\n\tchar temp[10];\n\tsprintf(temp, \"%d\", (int32)val);\n\tcfg.set(cat, key, temp);\n}\n\nvoid StoreIni(const char *cat, const char *key, float val)\n{\n\tchar temp[10];\n\tsprintf(temp, \"%f\", val);\n\tcfg.set(cat, key, temp);\n}\n\nvoid StoreIni(const char *cat, const char *key, char *val, int size)\n{\n\tcfg.set(cat, key, val);\n}\n\nconst char *iniControllerActions[] = { \"PED_FIREWEAPON\", \"PED_CYCLE_WEAPON_RIGHT\", \"PED_CYCLE_WEAPON_LEFT\", \"GO_FORWARD\", \"GO_BACK\", \"GO_LEFT\", \"GO_RIGHT\", \"PED_SNIPER_ZOOM_IN\",\n\t\"PED_SNIPER_ZOOM_OUT\", \"VEHICLE_ENTER_EXIT\", \"CAMERA_CHANGE_VIEW_ALL_SITUATIONS\", \"PED_JUMPING\", \"PED_SPRINT\", \"PED_LOOKBEHIND\", \"PED_DUCK\", \"PED_ANSWER_PHONE\", \n#ifdef BIND_VEHICLE_FIREWEAPON\n\t\"VEHICLE_FIREWEAPON\",\n#endif\n\t\"VEHICLE_ACCELERATE\", \"VEHICLE_BRAKE\", \"VEHICLE_CHANGE_RADIO_STATION\", \"VEHICLE_HORN\", \"TOGGLE_SUBMISSIONS\", \"VEHICLE_HANDBRAKE\", \"PED_1RST_PERSON_LOOK_LEFT\",\n\t\"PED_1RST_PERSON_LOOK_RIGHT\", \"VEHICLE_LOOKLEFT\", \"VEHICLE_LOOKRIGHT\", \"VEHICLE_LOOKBEHIND\", \"VEHICLE_TURRETLEFT\", \"VEHICLE_TURRETRIGHT\", \"VEHICLE_TURRETUP\", \"VEHICLE_TURRETDOWN\",\n\t\"PED_CYCLE_TARGET_LEFT\", \"PED_CYCLE_TARGET_RIGHT\", \"PED_CENTER_CAMERA_BEHIND_PLAYER\", \"PED_LOCK_TARGET\", \"NETWORK_TALK\", \"PED_1RST_PERSON_LOOK_UP\", \"PED_1RST_PERSON_LOOK_DOWN\",\n\t\"_CONTROLLERACTION_36\", \"TOGGLE_DPAD\", \"SWITCH_DEBUG_CAM_ON\", \"TAKE_SCREEN_SHOT\", \"SHOW_MOUSE_POINTER_TOGGLE\", \"UNKNOWN_ACTION\" };\n\nconst char *iniControllerTypes[] = { \"kbd:\", \"2ndKbd:\", \"mouse:\", \"joy:\" };\n\nconst char *iniMouseButtons[] = {\"LEFT\",\"MIDDLE\",\"RIGHT\",\"WHLUP\",\"WHLDOWN\",\"X1\",\"X2\"};\n\nconst char *iniKeyboardButtons[] = {\"ESC\",\"F1\",\"F2\",\"F3\",\"F4\",\"F5\",\"F6\",\"F7\",\"F8\",\"F9\",\"F10\",\"F11\",\"F12\",\n\t\"INS\",\"DEL\",\"HOME\",\"END\",\"PGUP\",\"PGDN\",\"UP\",\"DOWN\",\"LEFT\",\"RIGHT\",\"DIVIDE\",\"TIMES\",\"PLUS\",\"MINUS\",\"PADDEL\",\n\t\"PADEND\",\"PADDOWN\",\"PADPGDN\",\"PADLEFT\",\"PAD5\",\"NUMLOCK\",\"PADRIGHT\",\"PADHOME\",\"PADUP\",\"PADPGUP\",\"PADINS\",\n\t\"PADENTER\", \"SCROLL\",\"PAUSE\",\"BACKSP\",\"TAB\",\"CAPSLK\",\"ENTER\",\"LSHIFT\",\"RSHIFT\",\"SHIFT\",\"LCTRL\",\"RCTRL\",\"LALT\",\n\t\"RALT\", \"LWIN\", \"RWIN\", \"APPS\", \"NULL\"};\n\nvoid LoadINIControllerSettings()\n{\n#ifdef DETECT_JOYSTICK_MENU\n#ifdef XINPUT\n\tint storedJoy1 = -1;\n\tif (ReadIniIfExists(\"Controller\", \"JoystickName\", &storedJoy1)) {\n\t\tCPad::XInputJoy1 = -1;\n\t\tCPad::XInputJoy2 = -1;\n\t\tXINPUT_STATE xstate;\n\t\tmemset(&xstate, 0, sizeof(XINPUT_STATE));\n\n\t\t// Firstly confirm & set joy 1\n\t\tif (XInputGetState(storedJoy1, &xstate) == ERROR_SUCCESS) {\n\t\t\tCPad::XInputJoy1 = storedJoy1;\n\t\t}\n\n\t\tfor (int i = 0; i <= 3; i++) {\n\t\t\tif (XInputGetState(i, &xstate) == ERROR_SUCCESS) {\n\t\t\t\tif (CPad::XInputJoy1 == -1)\n\t\t\t\t\tCPad::XInputJoy1 = i;\n\t\t\t\telse if (CPad::XInputJoy2 == -1 && i != CPad::XInputJoy1)\n\t\t\t\t\tCPad::XInputJoy2 = i;\n\t\t\t}\n\t\t}\n\n\t\t// There is no plug event on XInput, so let's leave XInputJoy1/2 as 0/1 respectively, and hotplug will be possible.\n\t\tif (CPad::XInputJoy1 == -1) {\n\t\t\tCPad::XInputJoy1 = 0;\n\t\t\tCPad::XInputJoy2 = 1;\n\t\t} else if (CPad::XInputJoy2 == -1) {\n\t\t\tCPad::XInputJoy2 = (CPad::XInputJoy1 + 1) % 4;\n\t\t}\n\t}\n#else\n\tReadIniIfExists(\"Controller\", \"JoystickName\", gSelectedJoystickName, 128);\n#endif\n#endif\n\t// force to default GTA behaviour (never overwrite bindings on joy change/initialization) if user init'ed/set bindings before we introduced that\n\tif (!ReadIniIfExists(\"Controller\", \"PadButtonsInited\", &ControlsManager.ms_padButtonsInited)) {\n\t\tControlsManager.ms_padButtonsInited = cfg.category_size(\"Bindings\") != 0 ? 16 : 0;\n\t}\n\n\tfor (int32 i = 0; i < MAX_CONTROLLERACTIONS; i++) {\n\t\tchar value[128];\n\t\tif (ReadIniIfExists(\"Bindings\", iniControllerActions[i], value, 128)) {\n\t\t\tfor (int32 j = 0; j < MAX_CONTROLLERTYPES; j++){\n\t\t\t\tControlsManager.ClearSettingsAssociatedWithAction((e_ControllerAction)i, (eControllerType)j);\n\t\t\t}\n\n\t\t\tfor (char *binding = strtok(value,\", \"); binding != nil; binding = strtok(nil, \", \")) {\n\t\t\t\tint contType = -1;\n\t\t\t\tfor (int32 k = 0; k < ARRAY_SIZE(iniControllerTypes); k++) {\n\t\t\t\t\tint len = strlen(iniControllerTypes[k]);\n\t\t\t\t\tif (strncmp(binding, iniControllerTypes[k], len) == 0) {\n\t\t\t\t\t\tcontType = k;\n\t\t\t\t\t\tbinding += len;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (contType == -1)\n\t\t\t\t\tcontinue;\n\n\t\t\t\tint contKey;\n\t\t\t\tif (contType == JOYSTICK) {\n\t\t\t\t\tchar *temp;\n\t\t\t\t\tcontKey = strtol(binding, &temp, 0);\n\n\t\t\t\t} else if (contType == KEYBOARD || contType == OPTIONAL_EXTRA) {\n\t\t\t\t\tif (strlen(binding) == 1) {\n\t\t\t\t\t\tcontKey = binding[0];\n\t\t\t\t\t} else if(strcmp(binding, \"SPC\") == 0) {\n\t\t\t\t\t\tcontKey = ' ';\n\t\t\t\t\t} else {\n\t\t\t\t\t\tfor (int32 k = 0; k < ARRAY_SIZE(iniKeyboardButtons); k++) {\n\t\t\t\t\t\t\tif(strcmp(binding, iniKeyboardButtons[k]) == 0) {\n\t\t\t\t\t\t\t\tcontKey = 1000 + k;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else if (contType == MOUSE) {\n\t\t\t\t\tfor (int32 k = 0; k < ARRAY_SIZE(iniMouseButtons); k++) {\n\t\t\t\t\t\tif(strcmp(binding, iniMouseButtons[k]) == 0) {\n\t\t\t\t\t\t\tcontKey = 1 + k;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tControlsManager.SetControllerKeyAssociatedWithAction((e_ControllerAction)i, contKey, (eControllerType)contType);\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid SaveINIControllerSettings()\n{\n\tfor (int32 i = 0; i < MAX_CONTROLLERACTIONS; i++) {\n\t\tchar value[128] = { '\\0' };\n\n\t\t// upper limit should've been GetNumOfSettingsForAction(i), but sadly even R* doesn't use it's own system correctly, and there are gaps between orders.\n\t\tfor (int32 j = SETORDER_1; j < MAX_SETORDERS; j++){\n\n\t\t\t// We respect the m_ContSetOrder, and join/implode/order the bindings according to that; using comma as seperator.\n\t\t\tfor (int32 k = 0; k < MAX_CONTROLLERTYPES; k++){\n\t\t\t\tif (ControlsManager.m_aSettings[i][k].m_ContSetOrder == j) {\n\t\t\t\t\tchar next[32];\n\t\t\t\t\tif (k == JOYSTICK) {\n\t\t\t\t\t\tsnprintf(next, 32, \"%s%d,\", iniControllerTypes[k], ControlsManager.m_aSettings[i][k].m_Key);\n\n\t\t\t\t\t} else if (k == KEYBOARD || k == OPTIONAL_EXTRA) {\n\t\t\t\t\t\tif (ControlsManager.m_aSettings[i][k].m_Key == ' ')\n\t\t\t\t\t\t\tsnprintf(next, 32, \"%sSPC,\", iniControllerTypes[k]);\n\t\t\t\t\t\telse if (ControlsManager.m_aSettings[i][k].m_Key < 256)\n\t\t\t\t\t\t\tsnprintf(next, 32, \"%s%c,\", iniControllerTypes[k], ControlsManager.m_aSettings[i][k].m_Key);\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tsnprintf(next, 32, \"%s%s,\", iniControllerTypes[k], iniKeyboardButtons[ControlsManager.m_aSettings[i][k].m_Key - 1000]);\n\n\t\t\t\t\t} else if (k == MOUSE) {\n\t\t\t\t\t\tsnprintf(next, 32, \"%s%s,\", iniControllerTypes[k], iniMouseButtons[ControlsManager.m_aSettings[i][k].m_Key - 1]);\n\t\t\t\t\t}\n\t\t\t\t\tstrcat(value, next);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tint len = strlen(value);\n\t\tif (len > 0)\n\t\t\tvalue[len - 1] = '\\0'; // to remove comma\n\n\t\tStoreIni(\"Bindings\", iniControllerActions[i], value, 128);\n\t}\n\n#ifdef DETECT_JOYSTICK_MENU\n#ifdef XINPUT\n\tStoreIni(\"Controller\", \"JoystickName\", CPad::XInputJoy1);\n#else\n\tStoreIni(\"Controller\", \"JoystickName\", gSelectedJoystickName, 128);\n#endif\n#endif\n\tStoreIni(\"Controller\", \"PadButtonsInited\", ControlsManager.ms_padButtonsInited);\n\tcfg.write_file(\"reVC.ini\");\n}\n\nbool LoadINISettings()\n{\n\tif (!cfg.load_file(\"reVC.ini\"))\n\t\treturn false;\n\n#ifdef IMPROVED_VIDEOMODE\n\tReadIniIfExists(\"VideoMode\", \"Width\", &FrontEndMenuManager.m_nPrefsWidth);\n\tReadIniIfExists(\"VideoMode\", \"Height\", &FrontEndMenuManager.m_nPrefsHeight);\n\tReadIniIfExists(\"VideoMode\", \"Depth\", &FrontEndMenuManager.m_nPrefsDepth);\n\tReadIniIfExists(\"VideoMode\", \"Subsystem\", &FrontEndMenuManager.m_nPrefsSubsystem);\n\t// Windowed mode is loaded below in CUSTOM_FRONTEND_OPTIONS section\n#else\n\tReadIniIfExists(\"Graphics\", \"VideoMode\", &FrontEndMenuManager.m_nDisplayVideoMode);\n#endif\n\tReadIniIfExists(\"Controller\", \"HeadBob1stPerson\", &TheCamera.m_bHeadBob);\n\tReadIniIfExists(\"Controller\", \"HorizantalMouseSens\", &TheCamera.m_fMouseAccelHorzntl);\n\tReadIniIfExists(\"Controller\", \"InvertMouseVertically\", &MousePointerStateHelper.bInvertVertically);\n\tReadIniIfExists(\"Controller\", \"DisableMouseSteering\", &CVehicle::m_bDisableMouseSteering);\n\tReadIniIfExists(\"Controller\", \"Vibration\", &FrontEndMenuManager.m_PrefsUseVibration);\n\tReadIniIfExists(\"Audio\", \"SfxVolume\", &FrontEndMenuManager.m_PrefsSfxVolume);\n\tReadIniIfExists(\"Audio\", \"MusicVolume\", &FrontEndMenuManager.m_PrefsMusicVolume);\n\tReadIniIfExists(\"Audio\", \"MP3BoostVolume\", &FrontEndMenuManager.m_PrefsMP3BoostVolume);\n\tReadIniIfExists(\"Audio\", \"Radio\", &FrontEndMenuManager.m_PrefsRadioStation);\n\tReadIniIfExists(\"Audio\", \"SpeakerType\", &FrontEndMenuManager.m_PrefsSpeakers);\n\tReadIniIfExists(\"Audio\", \"Provider\", &FrontEndMenuManager.m_nPrefsAudio3DProviderIndex);\n\tReadIniIfExists(\"Audio\", \"DynamicAcoustics\", &FrontEndMenuManager.m_PrefsDMA);\n\tReadIniIfExists(\"Display\", \"Brightness\", &FrontEndMenuManager.m_PrefsBrightness);\n\tReadIniIfExists(\"Display\", \"DrawDistance\", &FrontEndMenuManager.m_PrefsLOD);\n\tReadIniIfExists(\"Display\", \"Subtitles\", &FrontEndMenuManager.m_PrefsShowSubtitles);\n\tReadIniIfExists(\"Graphics\", \"AspectRatio\", &FrontEndMenuManager.m_PrefsUseWideScreen);\n\tReadIniIfExists(\"Graphics\", \"FrameLimiter\", &FrontEndMenuManager.m_PrefsFrameLimiter);\n#ifdef LEGACY_MENU_OPTIONS\n\tReadIniIfExists(\"Graphics\", \"VSync\", &FrontEndMenuManager.m_PrefsVsyncDisp);\n\tReadIniIfExists(\"Graphics\", \"Trails\", &CMBlur::BlurOn);\n#endif\n\tReadIniIfExists(\"General\", \"SkinFile\", FrontEndMenuManager.m_PrefsSkinFile, 256);\n\tReadIniIfExists(\"Controller\", \"Method\", &FrontEndMenuManager.m_ControlMethod);\n\tReadIniIfExists(\"General\", \"Language\", &FrontEndMenuManager.m_PrefsLanguage);\n\tReadIniIfExists(\"Display\", \"ShowHud\", &FrontEndMenuManager.m_PrefsShowHud);\n\tReadIniIfExists(\"Display\", \"RadarMode\", &FrontEndMenuManager.m_PrefsRadarMode);\n\tReadIniIfExists(\"Display\", \"ShowLegends\", &FrontEndMenuManager.m_PrefsShowLegends);\n\n#ifdef EXTENDED_COLOURFILTER\n\tReadIniIfExists(\"CustomPipesValues\", \"PostFXIntensity\", &CPostFX::Intensity);\n#endif\n#ifdef EXTENDED_PIPELINES\n\tReadIniIfExists(\"CustomPipesValues\", \"NeoVehicleShininess\", &CustomPipes::VehicleShininess);\n\tReadIniIfExists(\"CustomPipesValues\", \"NeoVehicleSpecularity\", &CustomPipes::VehicleSpecularity);\n\tReadIniIfExists(\"CustomPipesValues\", \"RimlightMult\", &CustomPipes::RimlightMult);\n\tReadIniIfExists(\"CustomPipesValues\", \"LightmapMult\", &CustomPipes::LightmapMult);\n\tReadIniIfExists(\"CustomPipesValues\", \"GlossMult\", &CustomPipes::GlossMult);\n#endif\n\tReadIniIfExists(\"Rendering\", \"BackfaceCulling\", &gBackfaceCulling);\n#ifdef NEW_RENDERER\n\tReadIniIfExists(\"Rendering\", \"NewRenderer\", &gbNewRenderer);\n#endif\n\n#ifdef PROPER_SCALING\n\tReadIniIfExists(\"Draw\", \"ProperScaling\", &CDraw::ms_bProperScaling);\t\n#endif\n#ifdef FIX_RADAR\n\tReadIniIfExists(\"Draw\", \"FixRadar\", &CDraw::ms_bFixRadar);\t\n#endif\n#ifdef FIX_SPRITES\n\tReadIniIfExists(\"Draw\", \"FixSprites\", &CDraw::ms_bFixSprites);\t\n#endif\n#ifdef DRAW_GAME_VERSION_TEXT\n\tReadIniIfExists(\"General\", \"DrawVersionText\", &gbDrawVersionText);\n#endif\n#ifdef NO_MOVIES\n\tReadIniIfExists(\"General\", \"NoMovies\", &gbNoMovies);\n#endif\n\n#ifdef CUSTOM_FRONTEND_OPTIONS\n\tbool migrate = cfg.category_size(\"FrontendOptions\") != 0;\n\tfor (int i = 0; i < MENUPAGES; i++) {\n\t\tfor (int j = 0; j < NUM_MENUROWS; j++) {\n\t\t\tCMenuScreenCustom::CMenuEntry &option = aScreens[i].m_aEntries[j];\n\t\t\tif (option.m_Action == MENUACTION_NOTHING)\n\t\t\t\tbreak;\n\t\t\t\t\n\t\t\t// CFO check\n\t\t\tif (option.m_Action < MENUACTION_NOTHING && option.m_CFO->save) {\n\t\t\t\t// CFO only supports saving uint8 right now\n\n\t\t\t\t// Migrate from old .ini to new .ini\n\t\t\t\tif (migrate && ReadIniIfExists(\"FrontendOptions\", option.m_CFO->save, option.m_CFO->value))\n\t\t\t\t\tcfg.remove(\"FrontendOptions\", option.m_CFO->save);\n\t\t\t\telse\n\t\t\t\t\tReadIniIfExists(option.m_CFO->saveCat, option.m_CFO->save, option.m_CFO->value);\n\n\t\t\t\tif (option.m_Action == MENUACTION_CFO_SELECT) {\n\t\t\t\t\toption.m_CFOSelect->lastSavedValue = option.m_CFOSelect->displayedValue = *option.m_CFO->value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n#endif\n\n\treturn true;\n}\n\nvoid SaveINISettings()\n{\n#ifdef IMPROVED_VIDEOMODE\n\tStoreIni(\"VideoMode\", \"Width\", FrontEndMenuManager.m_nPrefsWidth);\n\tStoreIni(\"VideoMode\", \"Height\", FrontEndMenuManager.m_nPrefsHeight);\n\tStoreIni(\"VideoMode\", \"Depth\", FrontEndMenuManager.m_nPrefsDepth);\n\tStoreIni(\"VideoMode\", \"Subsystem\", FrontEndMenuManager.m_nPrefsSubsystem);\n\t// Windowed mode is loaded below in CUSTOM_FRONTEND_OPTIONS section\n#else\n\tStoreIni(\"Graphics\", \"VideoMode\", FrontEndMenuManager.m_nDisplayVideoMode);\n#endif\n\tStoreIni(\"Controller\", \"HeadBob1stPerson\", TheCamera.m_bHeadBob);\n\tStoreIni(\"Controller\", \"HorizantalMouseSens\", TheCamera.m_fMouseAccelHorzntl);\n\tStoreIni(\"Controller\", \"InvertMouseVertically\", MousePointerStateHelper.bInvertVertically);\n\tStoreIni(\"Controller\", \"DisableMouseSteering\", CVehicle::m_bDisableMouseSteering);\n\tStoreIni(\"Controller\", \"Vibration\", FrontEndMenuManager.m_PrefsUseVibration);\n\tStoreIni(\"Audio\", \"SfxVolume\", FrontEndMenuManager.m_PrefsSfxVolume);\n\tStoreIni(\"Audio\", \"MusicVolume\", FrontEndMenuManager.m_PrefsMusicVolume);\n\tStoreIni(\"Audio\", \"MP3BoostVolume\", FrontEndMenuManager.m_PrefsMP3BoostVolume);\n\tStoreIni(\"Audio\", \"Radio\", FrontEndMenuManager.m_PrefsRadioStation);\n\tStoreIni(\"Audio\", \"SpeakerType\", FrontEndMenuManager.m_PrefsSpeakers);\n\tStoreIni(\"Audio\", \"Provider\", FrontEndMenuManager.m_nPrefsAudio3DProviderIndex);\n\tStoreIni(\"Audio\", \"DynamicAcoustics\", FrontEndMenuManager.m_PrefsDMA);\n\tStoreIni(\"Display\", \"Brightness\", FrontEndMenuManager.m_PrefsBrightness);\n\tStoreIni(\"Display\", \"DrawDistance\", FrontEndMenuManager.m_PrefsLOD);\n\tStoreIni(\"Display\", \"Subtitles\", FrontEndMenuManager.m_PrefsShowSubtitles);\n\tStoreIni(\"Graphics\", \"AspectRatio\", FrontEndMenuManager.m_PrefsUseWideScreen);\n#ifdef LEGACY_MENU_OPTIONS\n\tStoreIni(\"Graphics\", \"VSync\", FrontEndMenuManager.m_PrefsVsyncDisp);\n\tStoreIni(\"Graphics\", \"Trails\", CMBlur::BlurOn);\n#endif\n\tStoreIni(\"Graphics\", \"FrameLimiter\", FrontEndMenuManager.m_PrefsFrameLimiter);\n\tStoreIni(\"General\", \"SkinFile\", FrontEndMenuManager.m_PrefsSkinFile, 256);\n\tStoreIni(\"Controller\", \"Method\", FrontEndMenuManager.m_ControlMethod);\n\tStoreIni(\"General\", \"Language\", FrontEndMenuManager.m_PrefsLanguage);\n\tStoreIni(\"Display\", \"ShowHud\", FrontEndMenuManager.m_PrefsShowHud);\n\tStoreIni(\"Display\", \"RadarMode\", FrontEndMenuManager.m_PrefsRadarMode);\n\tStoreIni(\"Display\", \"ShowLegends\", FrontEndMenuManager.m_PrefsShowLegends);\n\n#ifdef EXTENDED_COLOURFILTER\n\tStoreIni(\"CustomPipesValues\", \"PostFXIntensity\", CPostFX::Intensity);\n#endif\n#ifdef EXTENDED_PIPELINES\n\tStoreIni(\"CustomPipesValues\", \"NeoVehicleShininess\", CustomPipes::VehicleShininess);\n\tStoreIni(\"CustomPipesValues\", \"NeoVehicleSpecularity\", CustomPipes::VehicleSpecularity);\n\tStoreIni(\"CustomPipesValues\", \"RimlightMult\", CustomPipes::RimlightMult);\n\tStoreIni(\"CustomPipesValues\", \"LightmapMult\", CustomPipes::LightmapMult);\n\tStoreIni(\"CustomPipesValues\", \"GlossMult\", CustomPipes::GlossMult);\n#endif\n\tStoreIni(\"Rendering\", \"BackfaceCulling\", gBackfaceCulling);\n#ifdef NEW_RENDERER\n\tStoreIni(\"Rendering\", \"NewRenderer\", gbNewRenderer);\n#endif\n\n#ifdef PROPER_SCALING\t\n\tStoreIni(\"Draw\", \"ProperScaling\", CDraw::ms_bProperScaling);\t\n#endif\n#ifdef FIX_RADAR\n\tStoreIni(\"Draw\", \"FixRadar\", CDraw::ms_bFixRadar);\n#endif\n#ifdef FIX_SPRITES\n\tStoreIni(\"Draw\", \"FixSprites\", CDraw::ms_bFixSprites);\t\n#endif\n#ifdef DRAW_GAME_VERSION_TEXT\n\tStoreIni(\"General\", \"DrawVersionText\", gbDrawVersionText);\n#endif\n#ifdef NO_MOVIES\n\tStoreIni(\"General\", \"NoMovies\", gbNoMovies);\n#endif\n#ifdef CUSTOM_FRONTEND_OPTIONS\n\tfor (int i = 0; i < MENUPAGES; i++) {\n\t\tfor (int j = 0; j < NUM_MENUROWS; j++) {\n\t\t\tCMenuScreenCustom::CMenuEntry &option = aScreens[i].m_aEntries[j];\n\t\t\tif (option.m_Action == MENUACTION_NOTHING)\n\t\t\t\tbreak;\n\t\t\t\t\n\t\t\tif (option.m_Action < MENUACTION_NOTHING && option.m_CFO->save) {\n\t\t\t\t// Beware: CFO only supports saving uint8 right now\n\t\t\t\tStoreIni(option.m_CFO->saveCat, option.m_CFO->save, *option.m_CFO->value);\n\t\t\t}\n\t\t}\n\t}\n#endif\n\n\tcfg.write_file(\"reVC.ini\");\n}\n\n#endif\n\n#ifdef DEBUGMENU\nvoid WeaponCheat1();\nvoid WeaponCheat2();\nvoid WeaponCheat3();\nvoid HealthCheat();\nvoid VehicleCheat(int model);\nvoid BlowUpCarsCheat();\nvoid ChangePlayerCheat();\nvoid MayhemCheat();\nvoid EverybodyAttacksPlayerCheat();\nvoid WeaponsForAllCheat();\nvoid FastTimeCheat();\nvoid SlowTimeCheat();\nvoid MoneyCheat();\nvoid ArmourCheat();\nvoid WantedLevelUpCheat();\nvoid WantedLevelDownCheat();\nvoid SunnyWeatherCheat();\nvoid CloudyWeatherCheat();\nvoid RainyWeatherCheat();\nvoid FoggyWeatherCheat();\nvoid FastWeatherCheat();\nvoid OnlyRenderWheelsCheat();\nvoid ChittyChittyBangBangCheat();\nvoid StrongGripCheat();\nvoid SpecialCarCheats();\nvoid PickUpChicksCheat();\n\nDebugMenuEntry *carCol1;\nDebugMenuEntry *carCol2;\n\nvoid\nSpawnCar(int id)\n{\n\tCVector playerpos;\n\tCStreaming::RequestModel(id, 0);\n\tCStreaming::LoadAllRequestedModels(false);\n\tif(CStreaming::HasModelLoaded(id)){\n\t\tplayerpos = FindPlayerCoors();\n\t\tint node;\n\t\tif(!CModelInfo::IsBoatModel(id)){\n\t\t\tnode = ThePaths.FindNodeClosestToCoors(playerpos, 0, 100.0f, false, false);\n\t\t\tif(node < 0)\n\t\t\t\treturn;\n\t\t}\n\n\t\tCVehicle *v;\n\t\tif(CModelInfo::IsBoatModel(id))\n\t\t\tv = new CBoat(id, RANDOM_VEHICLE);\n\t\telse if(CModelInfo::IsBikeModel(id))\n\t\t\tv = new CBike(id, RANDOM_VEHICLE);\n\t\telse\n\t\t\tv = new CAutomobile(id, RANDOM_VEHICLE);\n\n\t\tv->bHasBeenOwnedByPlayer = true;\n\t\tif(carCol1)\n\t\t\tDebugMenuEntrySetAddress(carCol1, &v->m_currentColour1);\n\t\tif(carCol2)\n\t\t\tDebugMenuEntrySetAddress(carCol2, &v->m_currentColour2);\n\n\t\tif(CModelInfo::IsBoatModel(id))\n\t\t\tv->SetPosition(TheCamera.GetPosition() + TheCamera.GetForward()*15.0f);\n\t\telse\n\t\t\tv->SetPosition(ThePaths.m_pathNodes[node].GetPosition());\n\n\t\tv->GetMatrix().GetPosition().z += 4.0f;\n\t\tv->SetOrientation(0.0f, 0.0f, 3.49f);\n\t\tv->SetStatus(STATUS_ABANDONED);\n\t\tv->m_nDoorLock = CARLOCK_UNLOCKED;\n\t\tCWorld::Add(v);\n\t}\n}\n\nstatic void\nFixCar(void)\n{\n\tCVehicle *veh = FindPlayerVehicle();\n\tif(veh == nil)\n\t\treturn;\n\tveh->m_fHealth = 1000.0f;\n\tif(veh->IsCar()){\n\t\t((CAutomobile*)veh)->Damage.SetEngineStatus(0);\n\t\t((CAutomobile*)veh)->Fix();\n\t}else if(veh->IsBike()){\n\t\t((CBike*)veh)->Fix();\n\t}\n}\n\n#ifdef MAP_ENHANCEMENTS\nstatic void\nTeleportToWaypoint(void)\n{\n\tif (FindPlayerVehicle()) {\n\t\tif (CRadar::TargetMarkerId != -1)\n\t\t\tFindPlayerVehicle()->Teleport(CRadar::TargetMarkerPos + CVector(0.0f, 0.0f, FindPlayerVehicle()->GetColModel()->boundingSphere.center.z));\n\t} else\n\t\tif(CRadar::TargetMarkerId != -1)\n\t\t\tFindPlayerPed()->Teleport(CRadar::TargetMarkerPos + CVector(0.0f, 0.0f, FEET_OFFSET));\n}\n#endif\n\nstatic void\nSwitchCarCollision(void)\n{\n\tif (FindPlayerVehicle() && FindPlayerVehicle()->IsCar())\n\t\tFindPlayerVehicle()->bUsesCollision = !FindPlayerVehicle()->bUsesCollision;\n}\n\nstatic void\nToggleComedy(void)\n{\n\tCVehicle *veh = FindPlayerVehicle();\n\tif(veh == nil)\n\t\treturn;\n\tveh->bComedyControls = !veh->bComedyControls;\n}\n\nstatic void\nPlaceOnRoad(void)\n{\n\tCVehicle *veh = FindPlayerVehicle();\n\tif(veh == nil)\n\t\treturn;\n\n\tif(veh->IsCar())\n\t\t((CAutomobile*)veh)->PlaceOnRoadProperly();\n}\n\nstatic void\nResetCamStatics(void)\n{\n\tTheCamera.Cams[TheCamera.ActiveCam].ResetStatics = true;\n}\n\n#ifdef MISSION_SWITCHER\nint8 nextMissionToSwitch = 0;\nstatic void\nSwitchToMission(void)\n{\n\tCTheScripts::SwitchToMission(nextMissionToSwitch);\n}\n#endif\n\nstatic const char *carnames[] = {\n\t\"landstal\", \"idaho\", \"stinger\", \"linerun\", \"peren\", \"sentinel\", \"rio\", \"firetruk\", \"trash\", \"stretch\", \"manana\",\n\t\"infernus\", \"voodoo\", \"pony\", \"mule\", \"cheetah\", \"ambulan\", \"fbicar\", \"moonbeam\", \"esperant\", \"taxi\", \"washing\",\n\t\"bobcat\", \"mrwhoop\", \"bfinject\", \"hunter\", \"police\", \"enforcer\", \"securica\", \"banshee\", \"predator\", \"bus\",\n\t\"rhino\", \"barracks\", \"cuban\", \"chopper\", \"angel\", \"coach\", \"cabbie\", \"stallion\", \"rumpo\", \"rcbandit\", \"romero\",\n\t\"packer\", \"sentxs\", \"admiral\", \"squalo\", \"seaspar\", \"pizzaboy\", \"gangbur\", \"airtrain\", \"deaddodo\", \"speeder\",\n\t\"reefer\", \"tropic\", \"flatbed\", \"yankee\", \"caddy\", \"zebra\", \"topfun\", \"skimmer\", \"pcj600\", \"faggio\", \"freeway\",\n\t\"rcbaron\", \"rcraider\", \"glendale\", \"oceanic\", \"sanchez\", \"sparrow\", \"patriot\", \"lovefist\", \"coastg\", \"dinghy\",\n\t\"hermes\", \"sabre\", \"sabretur\", \"pheonix\", \"walton\", \"regina\", \"comet\", \"deluxo\", \"burrito\", \"spand\", \"marquis\",\n\t\"baggage\", \"kaufman\", \"maverick\", \"vcnmav\", \"rancher\", \"fbiranch\", \"virgo\", \"greenwoo\", \"jetmax\", \"hotring\",\n\t\"sandking\", \"blistac\", \"polmav\", \"boxville\", \"benson\", \"mesa\", \"rcgoblin\", \"hotrina\", \"hotrinb\",\n\t\"bloodra\", \"bloodrb\", \"vicechee\"\n};\n\nstatic CTweakVar** TweakVarsList;\nstatic int TweakVarsListSize = -1;\nstatic bool bAddTweakVarsNow = false;\nstatic const char *pTweakVarsDefaultPath = NULL;\n\nvoid CTweakVars::Add(CTweakVar *var)\n{\n\tif(TweakVarsListSize == -1) {\n\t\tTweakVarsList = (CTweakVar**)malloc(64 * sizeof(CTweakVar*));\n\t\tTweakVarsListSize = 0;\n\t}\n\tif(TweakVarsListSize > 63)\n\t\tTweakVarsList = (CTweakVar**) realloc(TweakVarsList, (TweakVarsListSize + 1) * sizeof(CTweakVar*));\n\n\tTweakVarsList[TweakVarsListSize++] = var;\n//\tTweakVarsList.push_back(var);\n\t\n\tif ( bAddTweakVarsNow )\n\t\tvar->AddDBG(pTweakVarsDefaultPath);\n}\n\nvoid CTweakVars::AddDBG(const char *path)\n{\n\tpTweakVarsDefaultPath = path;\n\n\tfor(int i = 0; i < TweakVarsListSize; ++i)\n\t\tTweakVarsList[i]->AddDBG(pTweakVarsDefaultPath);\n\t\n\tbAddTweakVarsNow = true;\n}\n\nvoid CTweakSwitch::AddDBG(const char *path)\n{\t\t\n\tDebugMenuEntry *e = DebugMenuAddVar(m_pPath == NULL ? path : m_pPath, m_pVarName, (int32_t *)m_pIntVar, m_pFunc, 1, m_nMin, m_nMax, m_aStr);\n\tDebugMenuEntrySetWrap(e, true);\n}\n\t\nvoid CTweakFunc::AddDBG  (const char *path) { DebugMenuAddCmd     (m_pPath == NULL ? path : m_pPath, m_pVarName, m_pFunc); }\nvoid CTweakBool::AddDBG  (const char *path) { DebugMenuAddVarBool8(m_pPath == NULL ? path : m_pPath, m_pVarName, (int8_t *)m_pBoolVar,  NULL); }\nvoid CTweakInt8::AddDBG  (const char *path) { DebugMenuAddVar     (m_pPath == NULL ? path : m_pPath, m_pVarName, (int8_t *)m_pIntVar,   NULL, m_nStep, m_nLoawerBound, m_nUpperBound, NULL); }\nvoid CTweakUInt8::AddDBG (const char *path) { DebugMenuAddVar     (m_pPath == NULL ? path : m_pPath, m_pVarName, (uint8_t *)m_pIntVar,  NULL, m_nStep, m_nLoawerBound, m_nUpperBound, NULL); }\nvoid CTweakInt16::AddDBG (const char *path) { DebugMenuAddVar     (m_pPath == NULL ? path : m_pPath, m_pVarName, (int16_t *)m_pIntVar,  NULL, m_nStep, m_nLoawerBound, m_nUpperBound, NULL); }\nvoid CTweakUInt16::AddDBG(const char *path) { DebugMenuAddVar     (m_pPath == NULL ? path : m_pPath, m_pVarName, (uint16_t *)m_pIntVar, NULL, m_nStep, m_nLoawerBound, m_nUpperBound, NULL); }\nvoid CTweakInt32::AddDBG (const char *path) { DebugMenuAddVar     (m_pPath == NULL ? path : m_pPath, m_pVarName, (int32_t *)m_pIntVar,  NULL, m_nStep, m_nLoawerBound, m_nUpperBound, NULL); }\nvoid CTweakUInt32::AddDBG(const char *path) { DebugMenuAddVar     (m_pPath == NULL ? path : m_pPath, m_pVarName, (uint32_t *)m_pIntVar, NULL, m_nStep, m_nLoawerBound, m_nUpperBound, NULL); }\nvoid CTweakFloat::AddDBG (const char *path) { DebugMenuAddVar     (m_pPath == NULL ? path : m_pPath, m_pVarName, (float *)m_pIntVar,    NULL, m_nStep, m_nLoawerBound, m_nUpperBound); }\n\n/*\nstatic const char *wt[] = {\n\t\t\t\"Sunny\", \"Cloudy\", \"Rainy\", \"Foggy\"\n\t\t};\n\nSETTWEAKPATH(\"TEST\");\t\t\nTWEAKSWITCH(CWeather::NewWeatherType, 0, 3, wt, NULL);\n*/\n\nvoid\nswitchWeather(void)\n{\n\tCWeather::StreamAfterRainTimer = 0;\n}\n\nvoid\nDebugMenuPopulate(void)\n{\n\tif(1){\n\t\tstatic const char *weathers[] = {\n\t\t\t\"Sunny\", \"Cloudy\", \"Rainy\", \"Foggy\", \"Extrasunny\", \"Stormy\"\n\t\t};\n\t\tstatic const char *extracols[] = {\n\t\t\t\"1 - Malibu club\",\n\t\t\t\"2 - Strib club\",\n\t\t\t\"3 - Hotel\",\n\t\t\t\"4 - Bank\",\n\t\t\t\"5 - Police HQ\",\n\t\t\t\"6 - Mall\",\n\t\t\t\"7 - Rifle Range\",\n\t\t\t\"8 - Mansion\",\n\t\t\t\"9 - Dirt ring\",\n\t\t\t\"10 - Blood ring\",\n\t\t\t\"11 - Hot ring\",\n\t\t\t\"12 - Concert hall\",\n\t\t\t\"13 - Auntie Poulets\",\n\t\t\t\"14 - Intro at docks\",\n\t\t\t\"15 - Biker bar\",\n\t\t\t\"16 - Intro cafe\",\n\t\t\t\"17 - Studio\",\n\t\t\t\"18\", \"19\", \"20\", \"21\", \"22\", \"23\", \"24\"\n\t\t};\n\t\tDebugMenuEntry *e;\n\t\te = DebugMenuAddVar(\"Time & Weather\", \"Current Hour\", &CClock::GetHoursRef(), nil, 1, 0, 23, nil);\n\t\tDebugMenuEntrySetWrap(e, true);\n\t\te = DebugMenuAddVar(\"Time & Weather\", \"Current Minute\", &CClock::GetMinutesRef(),\n\t\t\t[](){ CWeather::InterpolationValue = CClock::GetMinutes()/60.0f; }, 1, 0, 59, nil);\n\t\t\tDebugMenuEntrySetWrap(e, true);\n\t\te = DebugMenuAddVar(\"Time & Weather\", \"Old Weather\", (int16*)&CWeather::OldWeatherType, switchWeather, 1, 0, 5, weathers);\n\t\tDebugMenuEntrySetWrap(e, true);\n\t\te = DebugMenuAddVar(\"Time & Weather\", \"New Weather\", (int16*)&CWeather::NewWeatherType, switchWeather, 1, 0, 5, weathers);\n\t\tDebugMenuEntrySetWrap(e, true);\n\t\tDebugMenuAddVarBool32(\"Time & Weather\", \"Extracolours On\", &CTimeCycle::m_bExtraColourOn, nil);\n\t\tDebugMenuAddVar(\"Time & Weather\", \"Extracolour\", &CTimeCycle::m_ExtraColour, nil, 1, 0, 23, extracols);\n\t\tDebugMenuAddVar(\"Time & Weather\", \"Time scale\", (float*)&CTimer::GetTimeScale(), nil, 0.1f, 0.0f, 10.0f);\n\n\t\tDebugMenuAddCmd(\"Cheats\", \"Weapon set 1\", WeaponCheat1);\n\t\tDebugMenuAddCmd(\"Cheats\", \"Weapon set 2\", WeaponCheat2);\n\t\tDebugMenuAddCmd(\"Cheats\", \"Weapon set 3\", WeaponCheat3);\n\t\tDebugMenuAddCmd(\"Cheats\", \"Money\", MoneyCheat);\n\t\tDebugMenuAddCmd(\"Cheats\", \"Health\", HealthCheat);\n\t\tDebugMenuAddCmd(\"Cheats\", \"Wanted level up\", WantedLevelUpCheat);\n\t\tDebugMenuAddCmd(\"Cheats\", \"Wanted level down\", WantedLevelDownCheat);\n\t\tDebugMenuAddCmd(\"Cheats\", \"Tank\", []() { VehicleCheat(MI_TAXI); });\n\t\tDebugMenuAddCmd(\"Cheats\", \"Blow up cars\", BlowUpCarsCheat);\n\t\tDebugMenuAddCmd(\"Cheats\", \"Change player\", ChangePlayerCheat);\n\t\tDebugMenuAddCmd(\"Cheats\", \"Mayhem\", MayhemCheat);\n\t\tDebugMenuAddCmd(\"Cheats\", \"Everybody attacks player\", EverybodyAttacksPlayerCheat);\n\t\tDebugMenuAddCmd(\"Cheats\", \"Weapons for all\", WeaponsForAllCheat);\n\t\tDebugMenuAddCmd(\"Cheats\", \"Fast time\", FastTimeCheat);\n\t\tDebugMenuAddCmd(\"Cheats\", \"Slow time\", SlowTimeCheat);\n\t\tDebugMenuAddCmd(\"Cheats\", \"Armour\", ArmourCheat);\n\t\tDebugMenuAddCmd(\"Cheats\", \"Sunny weather\", SunnyWeatherCheat);\n\t\tDebugMenuAddCmd(\"Cheats\", \"Cloudy weather\", CloudyWeatherCheat);\n\t\tDebugMenuAddCmd(\"Cheats\", \"Rainy weather\", RainyWeatherCheat);\n\t\tDebugMenuAddCmd(\"Cheats\", \"Foggy weather\", FoggyWeatherCheat);\n\t\tDebugMenuAddCmd(\"Cheats\", \"Fast weather\", FastWeatherCheat);\n\t\tDebugMenuAddCmd(\"Cheats\", \"Only render wheels\", OnlyRenderWheelsCheat);\n\t\tDebugMenuAddCmd(\"Cheats\", \"Chitty chitty bang bang\", ChittyChittyBangBangCheat);\n\t\tDebugMenuAddCmd(\"Cheats\", \"Strong grip\", StrongGripCheat);\n\t\tDebugMenuAddCmd(\"Cheats\", \"Special car\", SpecialCarCheats);\n\t\tDebugMenuAddCmd(\"Cheats\", \"Pickup chicks\", PickUpChicksCheat);\n\n\t\tstatic int spawnCarId = MI_LANDSTAL;\n\t\te = DebugMenuAddVar(\"Spawn\", \"Spawn Car ID\", &spawnCarId, nil, 1, MI_LANDSTAL, MI_VICECHEE, carnames);\n\t\tDebugMenuEntrySetWrap(e, true);\n\t\tDebugMenuAddCmd(\"Spawn\", \"Spawn Car\", [](){\n\t\t\tif(spawnCarId == MI_CHOPPER ||\n\t\t\t   spawnCarId == MI_AIRTRAIN ||\n\t\t\t   spawnCarId == MI_DEADDODO)\n\t\t\t\treturn;\n\t\t\tSpawnCar(spawnCarId);\n\t\t});\n\t\tstatic uint8 dummy;\n\t\tcarCol1 = DebugMenuAddVar(\"Spawn\", \"First colour\", &dummy, nil, 1, 0, 255, nil);\n\t\tcarCol2 = DebugMenuAddVar(\"Spawn\", \"Second colour\", &dummy, nil, 1, 0, 255, nil);\n\t\tDebugMenuAddCmd(\"Spawn\", \"Spawn Stinger\", [](){ SpawnCar(MI_STINGER); });\n\t\tDebugMenuAddCmd(\"Spawn\", \"Spawn Infernus\", [](){ SpawnCar(MI_INFERNUS); });\n\t\tDebugMenuAddCmd(\"Spawn\", \"Spawn Cheetah\", [](){ SpawnCar(MI_CHEETAH); });\n\t\tDebugMenuAddCmd(\"Spawn\", \"Spawn Phoenix\", [](){ SpawnCar(MI_PHEONIX); });\n\t\tDebugMenuAddCmd(\"Spawn\", \"Spawn Banshee\", [](){ SpawnCar(MI_BANSHEE); });\n\t\tDebugMenuAddCmd(\"Spawn\", \"Spawn Esperanto\", [](){ SpawnCar(MI_ESPERANT); });\n\t\tDebugMenuAddCmd(\"Spawn\", \"Spawn Stallion\", [](){ SpawnCar(MI_STALLION); });\n\t\tDebugMenuAddCmd(\"Spawn\", \"Spawn Admiral\", [](){ SpawnCar(MI_ADMIRAL); });\n\t\tDebugMenuAddCmd(\"Spawn\", \"Spawn Washington\", [](){ SpawnCar(MI_WASHING); });\n\t\tDebugMenuAddCmd(\"Spawn\", \"Spawn Taxi\", [](){ SpawnCar(MI_TAXI); });\n\t\tDebugMenuAddCmd(\"Spawn\", \"Spawn Police\", [](){ SpawnCar(MI_POLICE); });\n\t\tDebugMenuAddCmd(\"Spawn\", \"Spawn Enforcer\", [](){ SpawnCar(MI_ENFORCER); });\n\t\tDebugMenuAddCmd(\"Spawn\", \"Spawn Cuban\", [](){ SpawnCar(MI_CUBAN); });\n\t\tDebugMenuAddCmd(\"Spawn\", \"Spawn Voodoo\", [](){ SpawnCar(MI_VOODOO); });\n\t\tDebugMenuAddCmd(\"Spawn\", \"Spawn BF injection\", [](){ SpawnCar(MI_BFINJECT); });\n\t\tDebugMenuAddCmd(\"Spawn\", \"Spawn Maverick\", [](){ SpawnCar(MI_MAVERICK); });\n\t\tDebugMenuAddCmd(\"Spawn\", \"Spawn VCN Maverick\", [](){ SpawnCar(MI_VCNMAV); });\n\t\tDebugMenuAddCmd(\"Spawn\", \"Spawn Sparrow\", [](){ SpawnCar(MI_SPARROW); });\n\t\tDebugMenuAddCmd(\"Spawn\", \"Spawn Sea Sparrow\", [](){ SpawnCar(MI_SEASPAR); });\n\t\tDebugMenuAddCmd(\"Spawn\", \"Spawn Hunter\", [](){ SpawnCar(MI_HUNTER); });\n\t\tDebugMenuAddCmd(\"Spawn\", \"Spawn Rhino\", [](){ SpawnCar(MI_RHINO); });\n\t\tDebugMenuAddCmd(\"Spawn\", \"Spawn Firetruck\", [](){ SpawnCar(MI_FIRETRUCK); });\n\t\tDebugMenuAddCmd(\"Spawn\", \"Spawn Predator\", [](){ SpawnCar(MI_PREDATOR); });\n\t\tDebugMenuAddCmd(\"Spawn\", \"Spawn PCJ 600\", [](){ SpawnCar(MI_PCJ600); });\n\t\tDebugMenuAddCmd(\"Spawn\", \"Spawn Faggio\", [](){ SpawnCar(MI_FAGGIO); });\n\t\tDebugMenuAddCmd(\"Spawn\", \"Spawn Freeway\", [](){ SpawnCar(MI_FREEWAY); });\n\t\tDebugMenuAddCmd(\"Spawn\", \"Spawn Squalo\", [](){ SpawnCar(MI_SQUALO); });\n\t\tDebugMenuAddCmd(\"Spawn\", \"Spawn Skimmer\", [](){ SpawnCar(MI_SKIMMER); });\n\n\t\tDebugMenuAddVarBool8(\"Render\", \"Draw hud\", &CHud::m_Wants_To_Draw_Hud, nil);\n#ifdef PROPER_SCALING\t\n\t\tDebugMenuAddVarBool8(\"Render\", \"Proper Scaling\", &CDraw::ms_bProperScaling, nil);\n#endif\n#ifdef FIX_RADAR\n\t\tDebugMenuAddVarBool8(\"Render\", \"Fix Radar\", &CDraw::ms_bFixRadar, nil);\n#endif\n#ifdef FIX_SPRITES\n\t\tDebugMenuAddVarBool8(\"Render\", \"Fix Sprites\", &CDraw::ms_bFixSprites, nil);\n#endif\n\t\tDebugMenuAddVarBool8(\"Render\", \"Backface Culling\", &gBackfaceCulling, nil);\n\t\tDebugMenuAddVarBool8(\"Render\", \"PS2 Alpha test Emu\", &gPS2alphaTest, nil);\n\t\tDebugMenuAddVarBool8(\"Render\", \"Frame limiter\", &FrontEndMenuManager.m_PrefsFrameLimiter, nil);\n\t\tDebugMenuAddVarBool8(\"Render\", \"VSynch\", &FrontEndMenuManager.m_PrefsVsync, nil);\n\t\tDebugMenuAddVar(\"Render\", \"Max FPS\", &RsGlobal.maxFPS, nil, 1, 1, 1000, nil);\n#ifdef NEW_RENDERER\n\t\tDebugMenuAddVarBool8(\"Render\", \"New Renderer\", &gbNewRenderer, nil);\nextern bool gbRenderRoads;\nextern bool gbRenderEverythingBarRoads;\nextern bool gbRenderFadingInUnderwaterEntities;\nextern bool gbRenderFadingInEntities;\nextern bool gbRenderWater;\nextern bool gbRenderBoats;\nextern bool gbRenderVehicles;\nextern bool gbRenderWorld0;\nextern bool gbRenderWorld1;\nextern bool gbRenderWorld2;\n\t\tDebugMenuAddVarBool8(\"Debug Render\", \"gbRenderRoads\", &gbRenderRoads, nil);\n\t\tDebugMenuAddVarBool8(\"Debug Render\", \"gbRenderEverythingBarRoads\", &gbRenderEverythingBarRoads, nil);\n\t\tDebugMenuAddVarBool8(\"Debug Render\", \"gbRenderFadingInUnderwaterEntities\", &gbRenderFadingInUnderwaterEntities, nil);\n\t\tDebugMenuAddVarBool8(\"Debug Render\", \"gbRenderFadingInEntities\", &gbRenderFadingInEntities, nil);\n\t\tDebugMenuAddVarBool8(\"Debug Render\", \"gbRenderWater\", &gbRenderWater, nil);\n\t\tDebugMenuAddVarBool8(\"Debug Render\", \"gbRenderBoats\", &gbRenderBoats, nil);\n\t\tDebugMenuAddVarBool8(\"Debug Render\", \"gbRenderVehicles\", &gbRenderVehicles, nil);\n\t\tDebugMenuAddVarBool8(\"Debug Render\", \"gbRenderWorld0\", &gbRenderWorld0, nil);\n\t\tDebugMenuAddVarBool8(\"Debug Render\", \"gbRenderWorld1\", &gbRenderWorld1, nil);\n\t\tDebugMenuAddVarBool8(\"Debug Render\", \"gbRenderWorld2\", &gbRenderWorld2, nil);\n#endif\n\n#ifdef EXTENDED_COLOURFILTER\n\t\tstatic const char *filternames[] = { \"None\", \"Simple\", \"Normal\", \"Mobile\" };\n\t\te = DebugMenuAddVar(\"Render\", \"Colourfilter\", &CPostFX::EffectSwitch, nil, 1, CPostFX::POSTFX_OFF, CPostFX::POSTFX_MOBILE, filternames);\n\t\tDebugMenuEntrySetWrap(e, true);\n\t\tDebugMenuAddVar(\"Render\", \"Intensity\", &CPostFX::Intensity, nil, 0.05f, 0, 10.0f);\n\t\tDebugMenuAddVarBool8(\"Render\", \"Blur\", &CPostFX::BlurOn, nil);\n\t\tDebugMenuAddVarBool8(\"Render\", \"Motion Blur\", &CPostFX::MotionBlurOn, nil);\n#endif\n\t\tDebugMenuAddVar(\"Render\", \"Drunkness\", &CMBlur::Drunkness, nil, 0.05f, 0, 1.0f);\n#ifndef MASTER\n\t\tDebugMenuAddVarBool8(\"Render\", \"Occlusion debug\", &bDispayOccDebugStuff, nil);\n#endif\n#ifdef EXTENDED_PIPELINES\n\t\tstatic const char *vehpipenames[] = { \"MatFX\", \"Neo\" };\n\t\te = DebugMenuAddVar(\"Render\", \"Vehicle Pipeline\", &CustomPipes::VehiclePipeSwitch, nil,\n\t\t\t1, CustomPipes::VEHICLEPIPE_MATFX, CustomPipes::VEHICLEPIPE_NEO, vehpipenames);\n\t\tDebugMenuEntrySetWrap(e, true);\n\t\tDebugMenuAddVar(\"Render\", \"Neo Vehicle Shininess\", &CustomPipes::VehicleShininess, nil, 0.1f, 0, 1.0f);\n\t\tDebugMenuAddVar(\"Render\", \"Neo Vehicle Specularity\", &CustomPipes::VehicleSpecularity, nil, 0.1f, 0, 1.0f);\n\t\tDebugMenuAddVarBool8(\"Render\", \"Neo Ped Rim light enable\", &CustomPipes::RimlightEnable, nil);\n\t\tDebugMenuAddVar(\"Render\", \"Mult\", &CustomPipes::RimlightMult, nil, 0.1f, 0, 1.0f);\n\t\tDebugMenuAddVarBool8(\"Render\", \"Neo World Lightmaps enable\", &CustomPipes::LightmapEnable, nil);\n\t\tDebugMenuAddVar(\"Render\", \"Mult\", &CustomPipes::LightmapMult, nil, 0.1f, 0, 1.0f);\n\t\tDebugMenuAddVarBool8(\"Render\", \"Neo Road Gloss enable\", &CustomPipes::GlossEnable, nil);\n\t\tDebugMenuAddVar(\"Render\", \"Mult\", &CustomPipes::GlossMult, nil, 0.1f, 0, 1.0f);\n#endif\n\t\tDebugMenuAddVarBool8(\"Debug Render\", \"Show Ped Paths\", &gbShowPedPaths, nil);\n\t\tDebugMenuAddVarBool8(\"Debug Render\", \"Show Car Paths\", &gbShowCarPaths, nil);\n\t\tDebugMenuAddVarBool8(\"Debug Render\", \"Show Car Path Links\", &gbShowCarPathsLinks, nil);\n\t\tDebugMenuAddVarBool8(\"Debug Render\", \"Show Collision Lines\", &gbShowCollisionLines, nil);\n\t\tDebugMenuAddVarBool8(\"Debug Render\", \"Show Collision Polys\", &gbShowCollisionPolys, nil);\n\t\tDebugMenuAddVarBool8(\"Debug Render\", \"Don't render Buildings\", &gbDontRenderBuildings, nil);\n\t\tDebugMenuAddVarBool8(\"Debug Render\", \"Don't render Big Buildings\", &gbDontRenderBigBuildings, nil);\n\t\tDebugMenuAddVarBool8(\"Debug Render\", \"Don't render Peds\", &gbDontRenderPeds, nil);\n\t\tDebugMenuAddVarBool8(\"Debug Render\", \"Don't render Vehicles\", &gbDontRenderVehicles, nil);\n\t\tDebugMenuAddVarBool8(\"Debug Render\", \"Don't render Objects\", &gbDontRenderObjects, nil);\n\t\tDebugMenuAddVarBool8(\"Debug Render\", \"Don't Render Water\", &gbDontRenderWater, nil);\n\t\t\n\t\t\n#ifdef DRAW_GAME_VERSION_TEXT\n\t\tDebugMenuAddVarBool8(\"Debug\", \"Version Text\", &gbDrawVersionText, nil);\n#endif\n\t\tDebugMenuAddVarBool8(\"Debug\", \"Show DebugStuffInRelease\", &gbDebugStuffInRelease, nil);\n#ifdef TIMEBARS\n\t\tDebugMenuAddVarBool8(\"Debug\", \"Show Timebars\", &gbShowTimebars, nil);\n#endif\n#ifndef FINAL\n\t\tDebugMenuAddVarBool8(\"Debug\", \"Use debug render groups\", &bDebugRenderGroups, nil);\n\t\tDebugMenuAddVarBool8(\"Debug\", \"Print Memory Usage\", &gbPrintMemoryUsage, nil);\n#ifdef USE_CUSTOM_ALLOCATOR\n\t\tDebugMenuAddCmd(\"Debug\", \"Parse Heap\", ParseHeap);\n#endif\n#endif\n\n\t\tDebugMenuAddVarBool8(\"Debug\", \"pad 1 -> pad 2\", &CPad::m_bMapPadOneToPadTwo, nil);\n#ifdef GTA_SCENE_EDIT\n\t\tDebugMenuAddVarBool8(\"Debug\", \"Edit on\", &CSceneEdit::m_bEditOn, nil);\n#endif\n\t\t//DebugMenuAddCmd(\"Debug\", \"Start Credits\", CCredits::Start);\n\t\t//DebugMenuAddCmd(\"Debug\", \"Stop Credits\", CCredits::Stop);\n\n#ifdef RELOADABLES\n// maybe put it back if we have more to reload \n//\t\tDebugMenuAddCmd(\"Reload\", \"HUD.TXD\", CHud::ReloadTXD);\n#endif\n\n#ifdef MAP_ENHANCEMENTS\n\t\tDebugMenuAddCmd(\"Game\", \"Teleport to map waypoint\", TeleportToWaypoint);\n#endif\n\t\tDebugMenuAddCmd(\"Game\", \"Fix Car\", FixCar);\n\t\tDebugMenuAddCmd(\"Game\", \"Place Car on Road\", PlaceOnRoad);\n\t\tDebugMenuAddCmd(\"Game\", \"Switch car collision\", SwitchCarCollision);\n\t\tDebugMenuAddCmd(\"Game\", \"Toggle Comedy Controls\", ToggleComedy);\n\n\n#ifdef MISSION_SWITCHER\n\t\tDebugMenuEntry *missionEntry;\n\t\tstatic const char* missions[] = {\n\t\t\t\"Initial\", \"Intro\", \"An Old Friend\", \"The Party\", \"Back Alley Brawl\", \"Jury Fury\", \"Riot\",\n\t\t\t\"Treacherous Swine\", \"Mall Shootout\", \"Guardian Angels\", \"Sir, Yes Sir!\", \"All Hands On Deck!\",\n\t\t\t\"The Chase\", \"Phnom Penh '86\", \"The Fastest Boat\", \"Supply & Demand\", \"Rub Out\", \"Death Row\",\n\t\t\t\"Four Iron\", \"Demolition Man\", \"Two Bit Hit\", \"No Escape?\", \"The Shootist\", \"The Driver\",\n\t\t\t\"The Job\", \"Gun Runner\", \"Boomshine Saigon\", \"Recruitment Drive\", \"Dildo Dodo\", \"Martha's Mug Shot\",\n\t\t\t\"G-spotlight\", \"Shakedown\", \"Bar Brawl\", \"Cop Land\", \"Spilling the Beans\", \"Hit the Courier\",\n\t\t\t\"Printworks Buy\", \"Sunshine Autos\", \"Interglobal Films Buy\", \"Cherry Popper Icecreams Buy\",\n\t\t\t\"Kaufman Cabs Buy\", \"Malibu Club Buy\", \"The Boatyard Buy\", \"Pole Position Club Buy\", \"El Swanko Casa Buy\",\n\t\t\t\"Links View Apartment Buy\", \"Hyman Condo Buy\", \"Ocean Heighs Aprt. Buy\", \"1102 Washington Street Buy\",\n\t\t\t\"Vice Point Buy\", \"Skumole Shack Buy\", \"Cap the Collector\", \"Keep your Friends Close...\",\n\t\t\t\"Alloy Wheels of Steel\", \"Messing with the Man\", \"Hog Tied\", \"Stunt Boat Challenge\", \"Cannon Fodder\",\n\t\t\t\"Naval Engagement\", \"Trojan Voodoo\", \"Juju Scramble\", \"Bombs Away!\", \"Dirty Lickin's\", \"Love Juice\",\n\t\t\t\"Psycho Killer\", \"Publicity Tour\", \"Weapon Range\", \"Road Kill\", \"Waste the Wife\", \"Autocide\",\n\t\t\t\"Check Out at the Check In\", \"Loose Ends\", \"V.I.P.\", \"Friendly Rivalry\", \"Cabmaggedon\", \"TAXI DRIVER\",\n\t\t\t\"PARAMEDIC\", \"FIREFIGHTER\", \"VIGILANTE\", \"HOTRING\", \"BLOODRING\", \"DIRTRING\", \"Sunshine Autos Races\",\n\t\t\t\"Distribution\", \"Downtown Chopper Checkpoint\", \"Ocean Beach Chopper Checkpoint\", \"Vice Point Chopper Checkpoint\",\n\t\t\t\"Little Haiti Chopper Checkpoint\", \"Trial by Dirt\", \"Test Track\", \"PCJ Playground\", \"Cone Crazy\",\n\t\t\t\"PIZZA BOY\", \"RC Raider Pickup\", \"RC Bandit Race\", \"RC Baron Race\", \"Checkpoint Charlie\"\n\t\t};\n\n\t\tmissionEntry = DebugMenuAddVar(\"Game\", \"Select mission\", &nextMissionToSwitch, nil, 1, 0, ARRAY_SIZE(missions) - 1, missions);\n\t\tDebugMenuEntrySetWrap(missionEntry, true);\n\t\tDebugMenuAddCmd(\"Game\", \"Start selected mission \", SwitchToMission);\n#endif\n\t\textern bool PrintDebugCode;\n\t\textern int16 DebugCamMode;\n\t\tDebugMenuAddVarBool8(\"Cam\", \"Use mouse Cam\", &CCamera::m_bUseMouse3rdPerson, nil);\n#ifdef FREE_CAM\n\t\tDebugMenuAddVarBool8(\"Cam\", \"Free Cam\", &CCamera::bFreeCam, nil);\n#endif\n\t\tDebugMenuAddVarBool8(\"Cam\", \"Print Debug Code\", &PrintDebugCode, nil);\n\t\tDebugMenuAddVar(\"Cam\", \"Cam Mode\", &DebugCamMode, nil, 1, 0, CCam::MODE_EDITOR, nil);\n\t\tDebugMenuAddCmd(\"Cam\", \"Normal\", []() { DebugCamMode = 0; });\n\t\tDebugMenuAddCmd(\"Cam\", \"Reset Statics\", ResetCamStatics);\n\n\t\tCTweakVars::AddDBG(\"Debug\");\n\t}\n}\n#endif\n\n#ifndef __MWERKS__\n#ifndef MASTER\nconst int   re3_buffsize = 1024;\nstatic char re3_buff[re3_buffsize];\n#endif\n\n#ifndef MASTER\nvoid re3_assert(const char *expr, const char *filename, unsigned int lineno, const char *func)\n{\n#ifdef _WIN32\n\tint nCode;\n\n\tstrcpy_s(re3_buff, re3_buffsize, \"Assertion failed!\" );\n\tstrcat_s(re3_buff, re3_buffsize, \"\\n\" );\t\n\t\n\tstrcat_s(re3_buff, re3_buffsize, \"File: \");\n\tstrcat_s(re3_buff, re3_buffsize, filename );\n\tstrcat_s(re3_buff, re3_buffsize, \"\\n\" );\t\n\n\tstrcat_s(re3_buff, re3_buffsize, \"Line: \" );\n\t_itoa_s( lineno, re3_buff + strlen(re3_buff), re3_buffsize - strlen(re3_buff), 10 );\n\tstrcat_s(re3_buff, re3_buffsize, \"\\n\");\n\t\n\tstrcat_s(re3_buff, re3_buffsize, \"Function: \");\n\tstrcat_s(re3_buff, re3_buffsize, func );\n\tstrcat_s(re3_buff, re3_buffsize, \"\\n\" );\t\n\t\n\tstrcat_s(re3_buff, re3_buffsize, \"Expression: \");\n\tstrcat_s(re3_buff, re3_buffsize, expr);\n\tstrcat_s(re3_buff, re3_buffsize, \"\\n\");\n\n\tstrcat_s(re3_buff, re3_buffsize, \"\\n\" );\n\tstrcat_s(re3_buff, re3_buffsize, \"(Press Retry to debug the application)\");\n\n\n\tnCode = ::MessageBoxA(nil, re3_buff, \"REVC Assertion Failed!\",\n\t\tMB_ABORTRETRYIGNORE|MB_ICONHAND|MB_SETFOREGROUND|MB_TASKMODAL);\n\n\tif (nCode == IDABORT)\n\t{\n\t\traise(SIGABRT);\n\t\t_exit(3);\n\t}\n\n\tif (nCode == IDRETRY)\n\t{\n\t\t__debugbreak();\n\t\treturn;\n\t}\n\n\tif (nCode == IDIGNORE)\n\t\treturn;\n\n\tabort();\n#else\n\t// TODO\n\tprintf(\"\\nREVC ASSERT FAILED\\n\\tFile: %s\\n\\tLine: %d\\n\\tFunction: %s\\n\\tExpression: %s\\n\",filename,lineno,func,expr);\n\tassert(false);\n#endif\n}\n#endif\n\nvoid re3_debug(const char *format, ...)\n{\n#ifndef MASTER\n\tva_list va;\n\tva_start(va, format);\n#ifdef _WIN32\n\tvsprintf_s(re3_buff, re3_buffsize, format, va);\n#else\n\tvsprintf(re3_buff, format, va);\n#endif\n\tva_end(va);\n\n\tprintf(\"%s\", re3_buff);\n\tCDebug::DebugAddText(re3_buff);\n#endif\n}\n\n#ifndef MASTER\nvoid re3_trace(const char *filename, unsigned int lineno, const char *func, const char *format, ...)\n{\n\tchar buff[re3_buffsize *2];\n\tva_list va;\n\tva_start(va, format);\n#ifdef _WIN32\n\tvsprintf_s(re3_buff, re3_buffsize, format, va);\n\tva_end(va);\n\t\n\tsprintf_s(buff, re3_buffsize * 2, \"[%s.%s:%d]: %s\", filename, func, lineno, re3_buff);\n#else\n\tvsprintf(re3_buff, format, va);\n\tva_end(va);\n\t\n\tsprintf(buff, \"[%s.%s:%d]: %s\", filename, func, lineno, re3_buff);\n#endif\n\n\tOutputDebugString(buff);\n}\n\nvoid re3_usererror(const char *format, ...)\n{\n\tva_list va;\n\tva_start(va, format);\n#ifdef _WIN32\n\tvsprintf_s(re3_buff, re3_buffsize, format, va);\n\tva_end(va);\n\t\n\t::MessageBoxA(nil, re3_buff, \"REVC Error!\",\n\t\tMB_OK|MB_ICONHAND|MB_SETFOREGROUND|MB_TASKMODAL);\n\n\traise(SIGABRT);\n\t_exit(3);\n#else\n\tvsprintf(re3_buff, format, va);\n\tprintf(\"\\nREVC Error!\\n\\t%s\\n\",re3_buff);\n\tassert(false);\n#endif\n}\n#endif\n#endif\n\n#ifdef VALIDATE_SAVE_SIZE\nint32 _saveBufCount;\n#endif\n"
  },
  {
    "path": "src/core/templates.h",
    "content": "#pragma once\n\ntemplate<typename T, int32 n>\nclass CStore\n{\npublic:\n\tint32 allocPtr;\n\tT store[n];\n\n\tT *Alloc(void){\n\t\tif(allocPtr >= n){\n\t\t\tprintf(\"Size of this thing:%d needs increasing\\n\", n);\n\t\t\tassert(0);\n\t\t}\n\t\treturn &store[allocPtr++];\n\t}\n\tvoid Clear(void){\n\t\tallocPtr = 0;\n\t}\n\tint32 GetIndex(T *item){\n\t\tassert(item >= &store[0]);\n\t\tassert(item < &store[n]);\n\t\treturn item - store;\n\t}\n\tT *GetItem(int32 index){\n\t\tassert(index >= 0);\n\t\tassert(index < n);\n\t\treturn &store[index];\n\t}\n};\n\n#define POOLFLAG_ID     0x7f\n#define POOLFLAG_ISFREE 0x80\n\ntemplate<typename T, typename U = T>\nclass CPool\n{\n\tU     *m_entries;\n\tuint8 *m_flags;\n\tint32  m_size;\n\tint32  m_allocPtr;\n\npublic:\n\tCPool(int32 size, const char *name){\n\t\tm_entries = (U*)new uint8[sizeof(U)*size];\n\t\tm_flags = new uint8[size];\n\t\tm_size = size;\n\t\tm_allocPtr = -1;\n\t\tfor(int i = 0; i < size; i++){\n\t\t\tSetId(i, 0);\n\t\t\tSetIsFree(i, true);\n\t\t}\n\t}\n\n\tint GetId(int i) const\n\t{\n\t\treturn m_flags[i] & POOLFLAG_ID;\n\t}\n\n\tbool GetIsFree(int i) const\n\t{\n\t\treturn !!(m_flags[i] & POOLFLAG_ISFREE);\n\t}\n\n\tvoid SetId(int i, int id)\n\t{\n\t\tm_flags[i] = (m_flags[i] & POOLFLAG_ISFREE) | (id & POOLFLAG_ID);\n\t}\n\n\tvoid SetIsFree(int i, bool isFree)\n\t{\n\t\tif (isFree)\n\t\t\tm_flags[i] |= POOLFLAG_ISFREE;\n\t\telse\n\t\t\tm_flags[i] &= ~POOLFLAG_ISFREE;\n\t}\n\t~CPool() {\n\t\tFlush();\n\t}\n\tvoid Flush() {\n\t\tif (m_size > 0) {\n\t\t\tdelete[] (uint8*)m_entries;\n\t\t\tdelete[] m_flags;\n\t\t\tm_entries = nil;\n\t\t\tm_flags = nil;\n\t\t\tm_size = 0;\n\t\t\tm_allocPtr = 0;\n\t\t}\n\t}\n\tint32 GetSize(void) const { return m_size; }\n\tT *New(void){\n\t\tbool wrapped = false;\n\t\tdo\n#ifdef FIX_BUGS\n\t\t\tif (++m_allocPtr >= m_size) {\n\t\t\t\tm_allocPtr = 0;\n\t\t\t\tif (wrapped)\n\t\t\t\t\treturn nil;\n\t\t\t\twrapped = true;\n\t\t\t}\n#else\n\t\t\tif(++m_allocPtr == m_size){\n\t\t\t\tif(wrapped)\n\t\t\t\t\treturn nil;\n\t\t\t\twrapped = true;\n\t\t\t\tm_allocPtr = 0;\n\t\t\t}\n#endif\n\t\twhile(!GetIsFree(m_allocPtr));\n\t\tSetIsFree(m_allocPtr, false);\n\t\tSetId(m_allocPtr, GetId(m_allocPtr)+1);\n\t\treturn (T*)&m_entries[m_allocPtr];\n\t}\n\tT *New(int32 handle){\n\t\tT *entry = (T*)&m_entries[handle>>8];\n\t\tSetNotFreeAt(handle);\n\t\treturn entry;\n\t}\n\tvoid SetNotFreeAt(int32 handle){\n\t\tint idx = handle>>8;\n\t\tSetIsFree(idx, false);\n\t\tSetId(idx, handle & POOLFLAG_ID);\n\t\tfor(m_allocPtr = 0; m_allocPtr < m_size; m_allocPtr++)\n\t\t\tif(GetIsFree(m_allocPtr))\n\t\t\t\treturn;\n\t}\n\tvoid Delete(T *entry){\n\t\tint i = GetJustIndex(entry);\n\t\tSetIsFree(i, true);\n\t\tif(i < m_allocPtr)\n\t\t\tm_allocPtr = i;\n\t}\n\tT *GetSlot(int i){\n\t\treturn GetIsFree(i) ? nil : (T*)&m_entries[i];\n\t}\n\tT *GetAt(int handle){\n#ifdef FIX_BUGS\n\t\tif (handle == -1)\n\t\t\treturn nil;\n#endif\n\t\treturn m_flags[handle>>8] == (handle & 0xFF) ?\n\t\t       (T*)&m_entries[handle >> 8] : nil;\n\t}\n\tint32 GetIndex(T* entry) {\n\t\tint i = GetJustIndex_NoFreeAssert(entry);\n\t\treturn m_flags[i] + (i<<8);\n\t}\n\tint32 GetJustIndex(T* entry) {\n\t\tint index = GetJustIndex_NoFreeAssert(entry);\n\t\tassert((U*)entry == (U*)&m_entries[index]); // cast is unsafe - check required\n\t\tassert(!GetIsFree(index));\n\t\treturn index;\n\t}\n\tint32 GetJustIndex_NoFreeAssert(T* entry) {\n\t\tint index = ((U*)entry - m_entries);\n\t\t// Please don't add unsafe assert here, because at least one func. use this to check if entity is ped or vehicle.\n\t\treturn index;\n\t}\n\tint32 GetNoOfUsedSpaces(void) const {\n\t\tint i;\n\t\tint n = 0;\n\t\tfor(i = 0; i < m_size; i++)\n\t\t\tif(!GetIsFree(i))\n\t\t\t\tn++;\n\t\treturn n;\n\t}\n\tvoid ClearStorage(uint8 *&flags, U *&entries){\n\t\tdelete[] flags;\n\t\tdelete[] (uint8*)entries;\n\t\tflags = nil;\n\t\tentries = nil;\n\t}\n\tuint32 GetMaxEntrySize() const { return sizeof(U); }\n\tvoid CopyBack(uint8 *&flags, U *&entries){\n\t\tmemcpy(m_flags, flags, sizeof(uint8)*m_size);\n\t\tmemcpy(m_entries, entries, sizeof(U)*m_size);\n\t\tdebug(\"Size copied:%d (%d)\\n\", sizeof(U)*m_size, m_size);\n\t\tm_allocPtr = 0;\n\t\tClearStorage(flags, entries);\n\t\tdebug(\"CopyBack:%d (/%d)\\n\", GetNoOfUsedSpaces(), m_size); /* Assumed inlining */\n\t}\n\tvoid Store(uint8 *&flags, U *&entries){\n\t\tflags = (uint8*)new uint8[sizeof(uint8)*m_size];\n\t\tentries = (U*)new uint8[sizeof(U)*m_size];\n\t\tmemcpy(flags, m_flags, sizeof(uint8)*m_size);\n\t\tmemcpy(entries, m_entries, sizeof(U)*m_size);\n\t\tdebug(\"Stored:%d (/%d)\\n\", GetNoOfUsedSpaces(), m_size); /* Assumed inlining */\n\t}\n\tint32 GetNoOfFreeSpaces() const { return GetSize() - GetNoOfUsedSpaces(); }\n};\n\ntemplate<typename T>\nclass CLink\n{\npublic:\n\tT item;\n\tCLink<T> *prev;\n\tCLink<T> *next;\n\n\tvoid Insert(CLink<T> *link){\n\t\tlink->next = this->next;\n\t\tthis->next->prev = link;\n\t\tlink->prev = this;\n\t\tthis->next = link;\n\t}\n\tvoid Remove(void){\n\t\tthis->prev->next = this->next;\n\t\tthis->next->prev = this->prev;\n\t}\n};\n\ntemplate<typename T>\nclass CLinkList\n{\npublic:\n\tCLink<T> head, tail;\n\tCLink<T> freeHead, freeTail;\n\tCLink<T> *links;\n\n\tvoid Init(int n){\n\t\tlinks = new CLink<T>[n];\n\t\thead.next = &tail;\n\t\ttail.prev = &head;\n\t\tfreeHead.next = &freeTail;\n\t\tfreeTail.prev = &freeHead;\n\t\twhile(n--)\n\t\t\tfreeHead.Insert(&links[n]);\n\t}\n\tvoid Shutdown(void){\n\t\tdelete[] links;\n\t\tlinks = nil;\n\t}\n\tvoid Clear(void){\n\t\twhile(head.next != &tail)\n\t\t\tRemove(head.next);\n\t}\n\tCLink<T> *Insert(T const &item){\n\t\tCLink<T> *node = freeHead.next;\n\t\tif(node == &freeTail)\n\t\t\treturn nil;\n\t\tnode->item = item;\n\t\tnode->Remove();\t\t// remove from free list\n\t\thead.Insert(node);\n\t\treturn node;\n\t}\n\tCLink<T> *InsertSorted(T const &item){\n\t\tCLink<T> *sort;\n\t\tfor(sort = head.next; sort != &tail; sort = sort->next)\n\t\t\tif(sort->item.sort >= item.sort)\n\t\t\t\tbreak;\n\t\tCLink<T> *node = freeHead.next;\n\t\tif(node == &freeTail)\n\t\t\treturn nil;\n\t\tnode->item = item;\n\t\tnode->Remove();\t\t// remove from free list\n\t\tsort->prev->Insert(node);\n\t\treturn node;\n\t}\n\tvoid Remove(CLink<T> *link){\n\t\tlink->Remove();\t\t// remove from list\n\t\tfreeHead.Insert(link);\t// insert into free list\n\t}\n\tint32 Count(void){\n\t\tint n = 0;\n\t\tCLink<T> *lnk;\n\t\tfor(lnk = head.next; lnk != &tail; lnk = lnk->next)\n\t\t\tn++;\n\t\treturn n;\n\t}\n};\n"
  },
  {
    "path": "src/core/timebars.cpp",
    "content": "#include \"common.h\"\n#ifndef MASTER\n#include \"Font.h\"\n#include \"Frontend.h\"\n#include \"Timer.h\"\n#include \"Text.h\"\n\n#define MAX_TIMERS (50)\n#define MAX_MS_COLLECTED (40)\n\n// enables frame time output\n#define FRAMETIME\n\nstruct sTimeBar\n{\n\tchar name[20];\n\tfloat startTime;\n\tfloat endTime;\n\tint32 unk;\n};\n\nstruct\n{\n\tsTimeBar Timers[MAX_TIMERS];\n\tuint32 count;\n} TimerBar;\nfloat MaxTimes[MAX_TIMERS];\nfloat MaxFrameTime;\n\nuint32 curMS;\nuint32 msCollected[MAX_MS_COLLECTED];\n#ifdef FRAMETIME\nfloat FrameInitTime;\n#endif\n\nvoid tbInit()\n{\n\tTimerBar.count = 0;\n\tuint32 i = CTimer::GetFrameCounter() & 0x7F;\n\tif (i == 0) {\n\t\tdo\n\t\t\tMaxTimes[i++] = 0.0f;\n\t\twhile (i != MAX_TIMERS);\n#ifdef FRAMETIME\n\t\tMaxFrameTime = 0.0f;\n#endif\n\t}\n#ifdef FRAMETIME\n\tFrameInitTime = (float)CTimer::GetCurrentTimeInCycles() / (float)CTimer::GetCyclesPerFrame();\n#endif\n}\n\nvoid tbStartTimer(int32 unk, Const char *name)\n{\n\tstrcpy(TimerBar.Timers[TimerBar.count].name, name);\n\tTimerBar.Timers[TimerBar.count].unk = unk;\n\tTimerBar.Timers[TimerBar.count].startTime = (float)CTimer::GetCurrentTimeInCycles() / (float)CTimer::GetCyclesPerFrame();\n\tTimerBar.count++;\n}\n\nvoid tbEndTimer(Const char* name)\n{\n\tuint32 n = 1500;\n\tfor (uint32 i = 0; i < TimerBar.count; i++) {\n\t\tif (strcmp(name, TimerBar.Timers[i].name) == 0)\n\t\t\tn = i;\n\t}\n\tassert(n != 1500);\n\tTimerBar.Timers[n].endTime = (float)CTimer::GetCurrentTimeInCycles() / (float)CTimer::GetCyclesPerFrame();\n}\n\nfloat Diag_GetFPS()\n{\n\treturn 39000.0f / (msCollected[(curMS - 1) % MAX_MS_COLLECTED] - msCollected[curMS % MAX_MS_COLLECTED]);\n}\n\nvoid tbDisplay()\n{\n\tchar temp[200];\n\twchar wtemp[200];\n\n#ifdef FRAMETIME\n\tfloat FrameEndTime = (float)CTimer::GetCurrentTimeInCycles() / (float)CTimer::GetCyclesPerFrame();\n#endif\n\n\tmsCollected[(curMS++) % MAX_MS_COLLECTED] = RsTimer();\n\tCFont::SetBackgroundOff();\n\tCFont::SetBackgroundColor(CRGBA(0, 0, 0, 128));\n\tCFont::SetScale(0.48f, 1.12f);\n\tCFont::SetCentreOff();\n\tCFont::SetJustifyOff();\n\tCFont::SetWrapx(SCREEN_STRETCH_X(DEFAULT_SCREEN_WIDTH));\n\tCFont::SetRightJustifyOff();\n\tCFont::SetPropOn();\n\tCFont::SetFontStyle(FONT_STANDARD);\n\tsprintf(temp, \"FPS: %.2f\", Diag_GetFPS());\n\tAsciiToUnicode(temp, wtemp);\n\tCFont::SetColor(CRGBA(255, 255, 255, 255));\n\tif (!CMenuManager::m_PrefsMarketing || !CMenuManager::m_PrefsDisableTutorials) {\n\t\tCFont::PrintString(RsGlobal.maximumWidth * (4.0f / DEFAULT_SCREEN_WIDTH), RsGlobal.maximumHeight * (4.0f / DEFAULT_SCREEN_HEIGHT), wtemp);\n\n#ifndef FINAL\n\t\t// Timers output (my own implementation)\n\t\tfor (uint32 i = 0; i < TimerBar.count; i++) {\n\t\t\tMaxTimes[i] = Max(MaxTimes[i], TimerBar.Timers[i].endTime - TimerBar.Timers[i].startTime);\n\t\t\tsprintf(temp, \"%s: %.2f\", &TimerBar.Timers[i].name[0], MaxTimes[i]);\n\t\t\tAsciiToUnicode(temp, wtemp);\n\t\t\tCFont::PrintString(RsGlobal.maximumWidth * (4.0f / DEFAULT_SCREEN_WIDTH), RsGlobal.maximumHeight * ((8.0f * (i + 2)) / DEFAULT_SCREEN_HEIGHT), wtemp);\n\t\t}\n\n#ifdef FRAMETIME\n\t\tMaxFrameTime = Max(MaxFrameTime, FrameEndTime - FrameInitTime);\n\t\tsprintf(temp, \"Frame Time: %.2f\", MaxFrameTime);\n\t\tAsciiToUnicode(temp, wtemp);\n\n\t\tCFont::PrintString(RsGlobal.maximumWidth * (4.0f / DEFAULT_SCREEN_WIDTH), RsGlobal.maximumHeight * ((8.0f * (TimerBar.count + 4)) / DEFAULT_SCREEN_HEIGHT), wtemp);\n#endif // FRAMETIME\n#endif // !FINAL\n\t}\n}\n#endif // !MASTER"
  },
  {
    "path": "src/core/timebars.h",
    "content": "#pragma once\n\n#ifdef TIMEBARS\nvoid tbInit();\nvoid tbStartTimer(int32, Const char*);\nvoid tbEndTimer(Const char*);\nvoid tbDisplay();\n#else\n#define tbInit()\n#define tbStartTimer(a, b)\n#define tbEndTimer(a)\n#define tbDisplay()\n#endif\n"
  },
  {
    "path": "src/entities/Dummy.cpp",
    "content": "#include \"common.h\"\n\n#include \"Pools.h\"\n#include \"World.h\"\n#include \"Dummy.h\"\n\nvoid *CDummy::operator new(size_t sz) { return CPools::GetDummyPool()->New();  }\nvoid CDummy::operator delete(void *p, size_t sz) { CPools::GetDummyPool()->Delete((CDummy*)p); }\n\nvoid\nCDummy::Add(void)\n{\n\tint x, xstart, xmid, xend;\n\tint y, ystart, ymid, yend;\n\tCSector *s;\n\tCPtrList *list;\n\n\tCRect bounds = GetBoundRect();\n\txstart = CWorld::GetSectorIndexX(bounds.left);\n\txend   = CWorld::GetSectorIndexX(bounds.right);\n\txmid   = CWorld::GetSectorIndexX((bounds.left + bounds.right)/2.0f);\n\tystart = CWorld::GetSectorIndexY(bounds.top);\n\tyend   = CWorld::GetSectorIndexY(bounds.bottom);\n\tymid   = CWorld::GetSectorIndexY((bounds.top + bounds.bottom)/2.0f);\n\tassert(xstart >= 0);\n\tassert(xend < NUMSECTORS_X);\n\tassert(ystart >= 0);\n\tassert(yend < NUMSECTORS_Y);\n\n\tfor(y = ystart; y <= yend; y++)\n\t\tfor(x = xstart; x <= xend; x++){\n\t\t\ts = CWorld::GetSector(x, y);\n\t\t\tif(x == xmid && y == ymid)\n\t\t\t\tlist = &s->m_lists[ENTITYLIST_DUMMIES];\n\t\t\telse\n\t\t\t\tlist = &s->m_lists[ENTITYLIST_DUMMIES_OVERLAP];\n\t\t\tCPtrNode *node = list->InsertItem(this);\n\t\t\tassert(node);\n\t\t\tm_entryInfoList.InsertItem(list, node, s);\n\t\t}\n}\n\nvoid\nCDummy::Remove(void)\n{\n\tCEntryInfoNode *node, *next;\n\tfor(node = m_entryInfoList.first; node; node = next){\n\t\tnext = node->next;\n\t\tnode->list->DeleteNode(node->listnode);\n\t\tm_entryInfoList.DeleteNode(node);\n\t}\n}\n\nbool\nIsDummyPointerValid(CDummy* pDummy)\n{\n\tif (!pDummy)\n\t\treturn false;\n\tint index = CPools::GetDummyPool()->GetJustIndex_NoFreeAssert(pDummy);\n#ifdef FIX_BUGS\n\tif (index < 0 || index >= CPools::GetDummyPool()->GetSize())\n#else\n\tif (index < 0 || index > CPools::GetDummyPool()->GetSize())\n#endif\n\t\treturn false;\n\treturn pDummy->m_entryInfoList.first;\n}\n"
  },
  {
    "path": "src/entities/Dummy.h",
    "content": "#pragma once\n\n#include \"Lists.h\"\n#include \"Entity.h\"\n\nclass CDummy : public CEntity\n{\npublic:\n\tCEntryInfoList m_entryInfoList;\n\n\tCDummy(void) { m_type = ENTITY_TYPE_DUMMY; }\n\tvoid Add(void);\n\tvoid Remove(void);\n\n\tstatic void *operator new(size_t);\n\tstatic void operator delete(void*, size_t);\n};\n\nbool IsDummyPointerValid(CDummy* pDummy);\n"
  },
  {
    "path": "src/entities/Entity.cpp",
    "content": "#include \"common.h\"\n\n#include \"General.h\"\n#include \"RwHelper.h\"\n#include \"ModelIndices.h\"\n#include \"Timer.h\"\n#include \"Entity.h\"\n#include \"Object.h\"\n#include \"World.h\"\n#include \"Camera.h\"\n#include \"Glass.h\"\n#include \"Weather.h\"\n#include \"Timecycle.h\"\n#include \"TrafficLights.h\"\n#include \"Coronas.h\"\n#include \"PointLights.h\"\n#include \"Shadows.h\"\n#include \"Pickups.h\"\n#include \"SpecialFX.h\"\n#include \"TxdStore.h\"\n#include \"Zones.h\"\n#include \"MemoryHeap.h\"\n#include \"Bones.h\"\n#include \"Debug.h\"\n#include \"Ped.h\"\n#include \"Dummy.h\"\n#include \"WindModifiers.h\"\n\nint gBuildings;\n\nCEntity::CEntity(void)\n{\n\tm_type = ENTITY_TYPE_NOTHING;\n\tm_status = STATUS_ABANDONED;\n\n\tbUsesCollision = false;\n\tbCollisionProcessed = false;\n\tbIsStatic = false;\n\tbHasContacted = false;\n\tbPedPhysics = false;\n\tbIsStuck = false;\n\tbIsInSafePosition = false;\n\tbUseCollisionRecords = false;\n\n\tbWasPostponed = false;\n\tbExplosionProof = false;\n\tbIsVisible = true;\n\tbHasCollided = false;\n\tbRenderScorched = false;\n\tbHasBlip = false;\n\tbIsBIGBuilding = false;\n\tbStreamBIGBuilding = false;\n\n\tbRenderDamaged = false;\n\tbBulletProof = false;\n\tbFireProof = false;\n\tbCollisionProof = false;\n\tbMeleeProof = false;\n\tbOnlyDamagedByPlayer = false;\n\tbStreamingDontDelete = false;\n\tbRemoveFromWorld = false;\n\n\tbHasHitWall = false;\n\tbImBeingRendered = false;\n\tbTouchingWater = false;\n\tbIsSubway = false;\n\tbDrawLast = false;\n\tbNoBrightHeadLights = false;\n\tbDoNotRender = false;\n\tbDistanceFade = false;\n\n\tm_flagE1 = false;\n\tm_flagE2 = false;\n\tbOffscreen = false;\n\tbIsStaticWaitingForCollision = false;\n\tbDontStream = false;\n\tbUnderwater = false;\n\tbHasPreRenderEffects = false;\n\n\tm_scanCode = 0;\n\tm_modelIndex = -1;\n\tm_rwObject = nil;\n\tm_area = AREA_MAIN_MAP;\n\tm_randomSeed = CGeneral::GetRandomNumber();\n\tm_pFirstReference = nil;\n}\n\nCEntity::~CEntity(void)\n{\n\tDeleteRwObject();\n\tResolveReferences();\n}\n\nvoid\nCEntity::SetModelIndex(uint32 id)\n{\n\tm_modelIndex = id;\n\tbHasPreRenderEffects = HasPreRenderEffects();\n\tCreateRwObject();\n}\n\nvoid\nCEntity::SetModelIndexNoCreate(uint32 id)\n{\n\tm_modelIndex = id;\n\tbHasPreRenderEffects = HasPreRenderEffects();\n}\n\nvoid\nCEntity::CreateRwObject(void)\n{\n\tCBaseModelInfo *mi;\n\n\tmi = CModelInfo::GetModelInfo(m_modelIndex);\n\n\tPUSH_MEMID(MEMID_WORLD);\n\tm_rwObject = mi->CreateInstance();\n\tPOP_MEMID();\n\n\tif(m_rwObject){\n\t\tif(IsBuilding())\n\t\t\tgBuildings++;\n\t\tif(RwObjectGetType(m_rwObject) == rpATOMIC)\n\t\t\tm_matrix.AttachRW(RwFrameGetMatrix(RpAtomicGetFrame((RpAtomic*)m_rwObject)), false);\n\t\telse if(RwObjectGetType(m_rwObject) == rpCLUMP)\n\t\t\tm_matrix.AttachRW(RwFrameGetMatrix(RpClumpGetFrame((RpClump*)m_rwObject)), false);\n\n\t\tmi->AddRef();\n\t}\n}\n\nvoid\nCEntity::AttachToRwObject(RwObject *obj)\n{\n\tm_rwObject = obj;\n\tif(m_rwObject){\n\t\tif(RwObjectGetType(m_rwObject) == rpATOMIC)\n\t\t\tm_matrix.Attach(RwFrameGetMatrix(RpAtomicGetFrame((RpAtomic*)m_rwObject)), false);\n\t\telse if(RwObjectGetType(m_rwObject) == rpCLUMP)\n\t\t\tm_matrix.Attach(RwFrameGetMatrix(RpClumpGetFrame((RpClump*)m_rwObject)), false);\n\n\t\tCModelInfo::GetModelInfo(m_modelIndex)->AddRef();\n\t}\n}\n\nvoid\nCEntity::DetachFromRwObject(void)\n{\n\tif(m_rwObject)\n\t\tCModelInfo::GetModelInfo(m_modelIndex)->RemoveRef();\n\tm_rwObject = nil;\n\tm_matrix.Detach();\n}\n\nRpAtomic*\nAtomicRemoveAnimFromSkinCB(RpAtomic *atomic, void *data)\n{\n\tif(RpSkinGeometryGetSkin(RpAtomicGetGeometry(atomic))){\n\t\tRpHAnimHierarchy *hier = RpSkinAtomicGetHAnimHierarchy(atomic);\n#ifdef LIBRW\n\t\tif(hier && hier->interpolator->currentAnim){\n\t\t\tRpHAnimAnimationDestroy(hier->interpolator->currentAnim);\n\t\t\thier->interpolator->currentAnim = nil;\n\t\t}\n#else\n\t\tif(hier && hier->currentAnim){\n\t\t\tRpHAnimAnimationDestroy(hier->currentAnim->pCurrentAnim);\n\t\t\thier->currentAnim = nil;\n\t\t}\n#endif\n\t}\n\treturn atomic;\n}\n\nvoid\nCEntity::DeleteRwObject(void)\n{\n\tRwFrame *f;\n\n\tm_matrix.Detach();\n\tif(m_rwObject){\n\t\tif(RwObjectGetType(m_rwObject) == rpATOMIC){\n\t\t\tf = RpAtomicGetFrame((RpAtomic*)m_rwObject);\n\t\t\tRpAtomicDestroy((RpAtomic*)m_rwObject);\n\t\t\tRwFrameDestroy(f);\n\t\t}else if(RwObjectGetType(m_rwObject) == rpCLUMP){\n\t\t\tif(IsClumpSkinned((RpClump*)m_rwObject))\n\t\t\t\tRpClumpForAllAtomics((RpClump*)m_rwObject, AtomicRemoveAnimFromSkinCB, nil);\n\t\t\tRpClumpDestroy((RpClump*)m_rwObject);\n\t\t}\n\t\tm_rwObject = nil;\n\t\tCModelInfo::GetModelInfo(m_modelIndex)->RemoveRef();\n\t\tif(IsBuilding())\n\t\t\tgBuildings--;\n\t}\n}\n\nCRect\nCEntity::GetBoundRect(void)\n{\n\tCRect rect;\n\tCVector v;\n\tCColModel *col = CModelInfo::GetModelInfo(m_modelIndex)->GetColModel();\n\n\trect.ContainPoint(m_matrix * col->boundingBox.min);\n\trect.ContainPoint(m_matrix * col->boundingBox.max);\n\n\tv = col->boundingBox.min;\n\tv.x = col->boundingBox.max.x;\n\trect.ContainPoint(m_matrix * v);\n\n\tv = col->boundingBox.max;\n\tv.x = col->boundingBox.min.x;\n\trect.ContainPoint(m_matrix * v);\n\n\treturn rect;\n}\n\nCVector\nCEntity::GetBoundCentre(void)\n{\n\tCVector v;\n\tGetBoundCentre(v);\n\treturn v;\n}\n\nvoid\nCEntity::GetBoundCentre(CVector &out)\n{\n\tout = m_matrix * CModelInfo::GetModelInfo(m_modelIndex)->GetColModel()->boundingSphere.center;\n}\n\nfloat\nCEntity::GetBoundRadius(void)\n{\n\treturn CModelInfo::GetModelInfo(m_modelIndex)->GetColModel()->boundingSphere.radius;\n}\n\nvoid\nCEntity::UpdateRwFrame(void)\n{\n\tif(m_rwObject)\n\t\tRwFrameUpdateObjects((RwFrame*)rwObjectGetParent(m_rwObject));\n}\n\nvoid\nCEntity::UpdateRpHAnim(void)\n{\n\tif(IsClumpSkinned(GetClump())){\n\t\tRpHAnimHierarchy *hier = GetAnimHierarchyFromSkinClump(GetClump());\n\t\tRpHAnimHierarchyUpdateMatrices(hier);\n#if 0\n\tint i;\n\tchar buf[256];\n\tif(this == (CEntity*)FindPlayerPed())\n\tfor(i = 0; i < hier->numNodes; i++){\n\t\tRpHAnimStdInterpFrame *kf = (RpHAnimStdInterpFrame*)rpHANIMHIERARCHYGETINTERPFRAME(hier, i);\n\t\tsprintf(buf, \"%6.3f %6.3f %6.3f %6.3f  %6.3f %6.3f %6.3f  %d %s\",\n\t\t\tkf->q.imag.x, kf->q.imag.y, kf->q.imag.z, kf->q.real,\n\t\t\tkf->t.x, kf->t.y, kf->t.z,\n\t\t\tHIERNODEID(hier, i),\n\t\t\tConvertBoneTag2BoneName(HIERNODEID(hier, i)));\n\t\tCDebug::PrintAt(buf, 10, 1+i*3);\n\n\t\tRwMatrix *m = &RpHAnimHierarchyGetMatrixArray(hier)[i];\n\t\tsprintf(buf, \"%6.3f %6.3f %6.3f %6.3f\",\n\t\t\tm->right.x, m->up.x, m->at.x, m->pos.x);\n\t\tCDebug::PrintAt(buf, 80, 1+i*3+0);\n\t\tsprintf(buf, \"%6.3f %6.3f %6.3f %6.3f\",\n\t\t\tm->right.y, m->up.y, m->at.y, m->pos.y);\n\t\tCDebug::PrintAt(buf, 80, 1+i*3+1);\n\t\tsprintf(buf, \"%6.3f %6.3f %6.3f %6.3f\",\n\t\t\tm->right.z, m->up.z, m->at.z, m->pos.z);\n\t\tCDebug::PrintAt(buf, 80, 1+i*3+2);\n\t}\n\n\tvoid RenderSkeleton(RpHAnimHierarchy *hier);\n\tRenderSkeleton(hier);\n#endif\n\t}\n}\n\nbool\nCEntity::HasPreRenderEffects(void)\n{\n\treturn IsTreeModel(GetModelIndex()) ||\n\t   GetModelIndex() == MI_COLLECTABLE1 ||\n\t   GetModelIndex() == MI_MONEY ||\n\t   GetModelIndex() == MI_CARMINE ||\n\t   GetModelIndex() == MI_NAUTICALMINE ||\n\t   GetModelIndex() == MI_BRIEFCASE ||\n\t   GetModelIndex() == MI_GRENADE ||\n\t   GetModelIndex() == MI_MOLOTOV ||\n\t   GetModelIndex() == MI_MISSILE ||\n\t   GetModelIndex() == MI_BEACHBALL ||\n\t   IsGlass(GetModelIndex()) ||\n\t   IsObject() && ((CObject*)this)->bIsPickup ||\n\t   IsLightWithPreRenderEffects(GetModelIndex());\n}\n\nvoid\nCEntity::PreRender(void)\n{\n\tif (CModelInfo::GetModelInfo(GetModelIndex())->GetNum2dEffects() != 0)\n\t\tProcessLightsForEntity();\n\n\tif(!bHasPreRenderEffects)\n\t\treturn;\n\n\tswitch(m_type){\n\tcase ENTITY_TYPE_BUILDING:\n\t\tif(IsTreeModel(GetModelIndex())){\n\t\t\tfloat dist = (TheCamera.GetPosition() - GetPosition()).Magnitude2D();\n\t\t\tCObject::fDistToNearestTree = Min(CObject::fDistToNearestTree, dist);\n\t\t\tModifyMatrixForTreeInWind();\n\t\t}\n\t\tbreak;\n\tcase ENTITY_TYPE_OBJECT:\n\t\tif(GetModelIndex() == MI_COLLECTABLE1){\n\t\t\tCPickups::DoCollectableEffects(this);\n\t\t\tGetMatrix().UpdateRW();\n\t\t\tUpdateRwFrame();\n\t\t}else if(GetModelIndex() == MI_MONEY){\n\t\t\tCPickups::DoMoneyEffects(this);\n\t\t\tGetMatrix().UpdateRW();\n\t\t\tUpdateRwFrame();\n\t\t}else if(GetModelIndex() == MI_NAUTICALMINE ||\n\t\t         GetModelIndex() == MI_CARMINE ||\n\t\t         GetModelIndex() == MI_BRIEFCASE){\n\t\t\tif(((CObject*)this)->bIsPickup){\n\t\t\t\tCPickups::DoMineEffects(this);\n\t\t\t\tGetMatrix().UpdateRW();\n\t\t\t\tUpdateRwFrame();\n\t\t\t}\n\t\t}else if(GetModelIndex() == MI_MISSILE){\n\t\t\tCVector pos = GetPosition();\n\t\t\tfloat flicker = (CGeneral::GetRandomNumber() & 0xF)/(float)0x10;\n\t\t\tCShadows::StoreShadowToBeRendered(SHADOWTYPE_ADDITIVE,\n\t\t\t\tgpShadowExplosionTex, &pos,\n\t\t\t\t8.0f, 0.0f, 0.0f, -8.0f,\n\t\t\t\t255, 200.0f*flicker, 160.0f*flicker, 120.0f*flicker,\n\t\t\t\t20.0f, false, 1.0f, nil, false);\n\t\t\tCPointLights::AddLight(CPointLights::LIGHT_POINT,\n\t\t\t\tpos, CVector(0.0f, 0.0f, 0.0f),\n\t\t\t\t8.0f,\n\t\t\t\t1.0f*flicker,\n\t\t\t\t0.8f*flicker,\n\t\t\t\t0.6f*flicker,\n\t\t\t\tCPointLights::FOG_NONE, true);\n\t\t\tCCoronas::RegisterCorona((uintptr)this,\n\t\t\t\t255.0f*flicker, 220.0f*flicker, 190.0f*flicker, 255,\n\t\t\t\tpos, 6.0f*flicker, 80.0f, gpCoronaTexture[CCoronas::TYPE_STAR],\n\t\t\t\tCCoronas::FLARE_NONE, CCoronas::REFLECTION_ON,\n\t\t\t\tCCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);\n\t\t}else if(IsGlass(GetModelIndex())){\n\t\t\tPreRenderForGlassWindow();\n\t\t}else if (((CObject*)this)->bIsPickup) {\n\t\t\tCPickups::DoPickUpEffects(this);\n\t\t\tGetMatrix().UpdateRW();\n\t\t\tUpdateRwFrame();\n\t\t} else if (GetModelIndex() == MI_GRENADE) {\n\t\t\tCMotionBlurStreaks::RegisterStreak((uintptr)this,\n\t\t\t\t100, 100, 100,\n\t\t\t\tGetPosition() - 0.07f * TheCamera.GetRight(),\n\t\t\t\tGetPosition() + 0.07f * TheCamera.GetRight());\n\t\t} else if (GetModelIndex() == MI_MOLOTOV) {\n\t\t\tCMotionBlurStreaks::RegisterStreak((uintptr)this,\n\t\t\t\t0, 100, 0,\n\t\t\t\tGetPosition() - 0.07f * TheCamera.GetRight(),\n\t\t\t\tGetPosition() + 0.07f * TheCamera.GetRight());\n\t\t}else if(GetModelIndex() == MI_BEACHBALL){\n\t\t\tCVector pos = GetPosition();\n\t\t\tCShadows::StoreShadowToBeRendered(SHADOWTYPE_DARK,\n\t\t\t\tgpShadowPedTex, &pos,\n\t\t\t\t0.4f, 0.0f, 0.0f, -0.4f,\n\t\t\t\tCTimeCycle::GetShadowStrength(),\n\t\t\t\tCTimeCycle::GetShadowStrength(),\n\t\t\t\tCTimeCycle::GetShadowStrength(),\n\t\t\t\tCTimeCycle::GetShadowStrength(),\n\t\t\t\t20.0f, false, 1.0f, nil, false);\n\t\t}\n\t\t// fall through\n\tcase ENTITY_TYPE_DUMMY:\n\t\tif(GetModelIndex() == MI_TRAFFICLIGHTS){\n\t\t\tCTrafficLights::DisplayActualLight(this);\n\t\t\tCShadows::StoreShadowForPole(this, 2.957f, 0.147f, 0.0f, 16.0f, 0.4f, 0);\n\t\t}else if(GetModelIndex() == MI_TRAFFICLIGHTS_VERTICAL){\n\t\t\tCTrafficLights::DisplayActualLight(this);\n\t\t}else if(GetModelIndex() == MI_TRAFFICLIGHTS_MIAMI){\n\t\t\tCTrafficLights::DisplayActualLight(this);\n\t\t\tCShadows::StoreShadowForPole(this, 4.819f, 1.315f, 0.0f, 16.0f, 0.4f, 0);\n\t\t}else if(GetModelIndex() == MI_TRAFFICLIGHTS_TWOVERTICAL){\n\t\t\tCTrafficLights::DisplayActualLight(this);\n\t\t\tCShadows::StoreShadowForPole(this, 7.503f, 0.0f, 0.0f, 16.0f, 0.4f, 0);\n\t\t}else if(GetModelIndex() == MI_SINGLESTREETLIGHTS1)\n\t\t\tCShadows::StoreShadowForPole(this, 0.744f, 0.0f, 0.0f, 16.0f, 0.4f, 0);\n\t\telse if(GetModelIndex() == MI_SINGLESTREETLIGHTS2)\n\t\t\tCShadows::StoreShadowForPole(this, 0.043f, 0.0f, 0.0f, 16.0f, 0.4f, 0);\n\t\telse if(GetModelIndex() == MI_SINGLESTREETLIGHTS3)\n\t\t\tCShadows::StoreShadowForPole(this, 1.143f, 0.145f, 0.0f, 16.0f, 0.4f, 0);\n\t\telse if(GetModelIndex() == MI_DOUBLESTREETLIGHTS)\n\t\t\tCShadows::StoreShadowForPole(this, 0.0f, -0.048f, 0.0f, 16.0f, 0.4f, 0);\n\t\tbreak;\n\t}\n}\n\nvoid\nCEntity::Render(void)\n{\n\tif(m_rwObject){\n\t\tbImBeingRendered = true;\n\t\tif(RwObjectGetType(m_rwObject) == rpATOMIC)\n\t\t\tRpAtomicRender((RpAtomic*)m_rwObject);\n\t\telse\n\t\t\tRpClumpRender((RpClump*)m_rwObject);\n\t\tbImBeingRendered = false;\n\t}\n}\n\nbool\nCEntity::GetIsTouching(CVector const &center, float radius)\n{\n\treturn sq(GetBoundRadius()+radius) > (GetBoundCentre()-center).MagnitudeSqr();\n}\n\nbool\nCEntity::IsVisible(void)\n{\n\treturn m_rwObject && bIsVisible && GetIsOnScreen();\n}\n\nbool\nCEntity::IsVisibleComplex(void)\n{\n\treturn m_rwObject && bIsVisible && GetIsOnScreenComplex();\n}\n\nbool\nCEntity::GetIsOnScreen(void)\n{\n\treturn TheCamera.IsSphereVisible(GetBoundCentre(), GetBoundRadius(),\n\t\t&TheCamera.GetCameraMatrix());\n}\n\nbool\nCEntity::GetIsOnScreenComplex(void)\n{\n#ifdef GTA_PS2\n\tCVuVector boundBox[8];\n#else\n\tCVector boundBox[8];\n#endif\n\n\tif(TheCamera.IsPointVisible(GetBoundCentre(), &TheCamera.GetCameraMatrix()))\n\t\treturn true;\n\n\tCRect rect = GetBoundRect();\n\tCColModel *colmodel = CModelInfo::GetModelInfo(m_modelIndex)->GetColModel();\n\tfloat z = GetPosition().z;\n\tfloat minz = z + colmodel->boundingBox.min.z;\n\tfloat maxz = z + colmodel->boundingBox.max.z;\n\tboundBox[0].x = rect.left;\n\tboundBox[0].y = rect.bottom;\n\tboundBox[0].z = minz;\n\tboundBox[1].x = rect.left;\n\tboundBox[1].y = rect.top;\n\tboundBox[1].z = minz;\n\tboundBox[2].x = rect.right;\n\tboundBox[2].y = rect.bottom;\n\tboundBox[2].z = minz;\n\tboundBox[3].x = rect.right;\n\tboundBox[3].y = rect.top;\n\tboundBox[3].z = minz;\n\tboundBox[4].x = rect.left;\n\tboundBox[4].y = rect.bottom;\n\tboundBox[4].z = maxz;\n\tboundBox[5].x = rect.left;\n\tboundBox[5].y = rect.top;\n\tboundBox[5].z = maxz;\n\tboundBox[6].x = rect.right;\n\tboundBox[6].y = rect.bottom;\n\tboundBox[6].z = maxz;\n\tboundBox[7].x = rect.right;\n\tboundBox[7].y = rect.top;\n\tboundBox[7].z = maxz;\n\n\treturn TheCamera.IsBoxVisible(boundBox, &TheCamera.GetCameraMatrix());\n}\n\nvoid\nCEntity::Add(void)\n{\n\tint x, xstart, xmid, xend;\n\tint y, ystart, ymid, yend;\n\tCSector *s;\n\tCPtrList *list;\n\n\tCRect bounds = GetBoundRect();\n\txstart = CWorld::GetSectorIndexX(bounds.left);\n\txend   = CWorld::GetSectorIndexX(bounds.right);\n\txmid   = CWorld::GetSectorIndexX((bounds.left + bounds.right)/2.0f);\n\tystart = CWorld::GetSectorIndexY(bounds.top);\n\tyend   = CWorld::GetSectorIndexY(bounds.bottom);\n\tymid   = CWorld::GetSectorIndexY((bounds.top + bounds.bottom)/2.0f);\n\tassert(xstart >= 0);\n\tassert(xend < NUMSECTORS_X);\n\tassert(ystart >= 0);\n\tassert(yend < NUMSECTORS_Y);\n\n\tfor(y = ystart; y <= yend; y++)\n\t\tfor(x = xstart; x <= xend; x++){\n\t\t\ts = CWorld::GetSector(x, y);\n\t\t\tif(x == xmid && y == ymid) switch(m_type){\n\t\t\tcase ENTITY_TYPE_BUILDING:\n\t\t\t\tlist = &s->m_lists[ENTITYLIST_BUILDINGS];\n\t\t\t\tbreak;\n\t\t\tcase ENTITY_TYPE_VEHICLE:\n\t\t\t\tlist = &s->m_lists[ENTITYLIST_VEHICLES];\n\t\t\t\tbreak;\n\t\t\tcase ENTITY_TYPE_PED:\n\t\t\t\tlist = &s->m_lists[ENTITYLIST_PEDS];\n\t\t\t\tbreak;\n\t\t\tcase ENTITY_TYPE_OBJECT:\n\t\t\t\tlist = &s->m_lists[ENTITYLIST_OBJECTS];\n\t\t\t\tbreak;\n\t\t\tcase ENTITY_TYPE_DUMMY:\n\t\t\t\tlist = &s->m_lists[ENTITYLIST_DUMMIES];\n\t\t\t\tbreak;\n\t\t\t}else switch(m_type){\n\t\t\tcase ENTITY_TYPE_BUILDING:\n\t\t\t\tlist = &s->m_lists[ENTITYLIST_BUILDINGS_OVERLAP];\n\t\t\t\tbreak;\n\t\t\tcase ENTITY_TYPE_VEHICLE:\n\t\t\t\tlist = &s->m_lists[ENTITYLIST_VEHICLES_OVERLAP];\n\t\t\t\tbreak;\n\t\t\tcase ENTITY_TYPE_PED:\n\t\t\t\tlist = &s->m_lists[ENTITYLIST_PEDS_OVERLAP];\n\t\t\t\tbreak;\n\t\t\tcase ENTITY_TYPE_OBJECT:\n\t\t\t\tlist = &s->m_lists[ENTITYLIST_OBJECTS_OVERLAP];\n\t\t\t\tbreak;\n\t\t\tcase ENTITY_TYPE_DUMMY:\n\t\t\t\tlist = &s->m_lists[ENTITYLIST_DUMMIES_OVERLAP];\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tlist->InsertItem(this);\n\t\t}\n}\n\nvoid\nCEntity::Remove(void)\n{\n\tint x, xstart, xmid, xend;\n\tint y, ystart, ymid, yend;\n\tCSector *s;\n\tCPtrList *list;\n\n\tCRect bounds = GetBoundRect();\n\txstart = CWorld::GetSectorIndexX(bounds.left);\n\txend   = CWorld::GetSectorIndexX(bounds.right);\n\txmid   = CWorld::GetSectorIndexX((bounds.left + bounds.right)/2.0f);\n\tystart = CWorld::GetSectorIndexY(bounds.top);\n\tyend   = CWorld::GetSectorIndexY(bounds.bottom);\n\tymid   = CWorld::GetSectorIndexY((bounds.top + bounds.bottom)/2.0f);\n\tassert(xstart >= 0);\n\tassert(xend < NUMSECTORS_X);\n\tassert(ystart >= 0);\n\tassert(yend < NUMSECTORS_Y);\n\n\tfor(y = ystart; y <= yend; y++)\n\t\tfor(x = xstart; x <= xend; x++){\n\t\t\ts = CWorld::GetSector(x, y);\n\t\t\tif(x == xmid && y == ymid) switch(m_type){\n\t\t\tcase ENTITY_TYPE_BUILDING:\n\t\t\t\tlist = &s->m_lists[ENTITYLIST_BUILDINGS];\n\t\t\t\tbreak;\n\t\t\tcase ENTITY_TYPE_VEHICLE:\n\t\t\t\tlist = &s->m_lists[ENTITYLIST_VEHICLES];\n\t\t\t\tbreak;\n\t\t\tcase ENTITY_TYPE_PED:\n\t\t\t\tlist = &s->m_lists[ENTITYLIST_PEDS];\n\t\t\t\tbreak;\n\t\t\tcase ENTITY_TYPE_OBJECT:\n\t\t\t\tlist = &s->m_lists[ENTITYLIST_OBJECTS];\n\t\t\t\tbreak;\n\t\t\tcase ENTITY_TYPE_DUMMY:\n\t\t\t\tlist = &s->m_lists[ENTITYLIST_DUMMIES];\n\t\t\t\tbreak;\n\t\t\t}else switch(m_type){\n\t\t\tcase ENTITY_TYPE_BUILDING:\n\t\t\t\tlist = &s->m_lists[ENTITYLIST_BUILDINGS_OVERLAP];\n\t\t\t\tbreak;\n\t\t\tcase ENTITY_TYPE_VEHICLE:\n\t\t\t\tlist = &s->m_lists[ENTITYLIST_VEHICLES_OVERLAP];\n\t\t\t\tbreak;\n\t\t\tcase ENTITY_TYPE_PED:\n\t\t\t\tlist = &s->m_lists[ENTITYLIST_PEDS_OVERLAP];\n\t\t\t\tbreak;\n\t\t\tcase ENTITY_TYPE_OBJECT:\n\t\t\t\tlist = &s->m_lists[ENTITYLIST_OBJECTS_OVERLAP];\n\t\t\t\tbreak;\n\t\t\tcase ENTITY_TYPE_DUMMY:\n\t\t\t\tlist = &s->m_lists[ENTITYLIST_DUMMIES_OVERLAP];\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tlist->RemoveItem(this);\n\t\t}\n}\n\nfloat\nCEntity::GetDistanceFromCentreOfMassToBaseOfModel(void)\n{\n\treturn -CModelInfo::GetModelInfo(m_modelIndex)->GetColModel()->boundingBox.min.z;\n}\n\nvoid\nCEntity::SetupBigBuilding(void)\n{\n\tCSimpleModelInfo *mi;\n\n\tmi = (CSimpleModelInfo*)CModelInfo::GetModelInfo(m_modelIndex);\n\tbIsBIGBuilding = true;\n\tbStreamingDontDelete = true;\n\tbUsesCollision = false;\n\tm_level = CTheZones::GetLevelFromPosition(&GetPosition());\n\tif(mi->m_lodDistances[0] <= 2000.0f)\n\t\tbStreamBIGBuilding = true;\n\tif(mi->m_lodDistances[0] > 2500.0f || mi->m_ignoreDrawDist)\n\t\tm_level = LEVEL_GENERIC;\n\telse if(m_level == LEVEL_GENERIC)\n\t\tprintf(\"%s isn't in a level\\n\", mi->GetModelName());\n}\n\nfloat WindTabel[] = {\n\t1.0f, 0.5f, 0.2f, 0.7f, 0.4f, 1.0f, 0.5f, 0.3f,\n\t0.2f, 0.1f, 0.7f, 0.6f, 0.3f, 1.0f, 0.5f, 0.2f,\n};\n\nvoid\nCEntity::ModifyMatrixForTreeInWind(void)\n{\n\tuint16 t;\n\tfloat f;\n\tfloat strength, flutter;\n\n\tif(CTimer::GetIsPaused())\n\t\treturn;\n\n\tCMatrix mat(GetMatrix().m_attachment);\n\n\tif(CWeather::Wind >= 0.5){\n\t\tt = m_randomSeed + 8*CTimer::GetTimeInMilliseconds();\n\t\tf = (t & 0xFFF)/(float)0x1000;\n\t\tflutter = f * WindTabel[(t>>12)+1 & 0xF] +\n\t\t\t(1.0f - f) * WindTabel[(t>>12) & 0xF] +\n\t\t\t1.0f;\n\t\tstrength = -0.015f*CWeather::Wind;\n\t}else if(CWeather::Wind >= 0.2){\n\t\tt = (uintptr)this + CTimer::GetTimeInMilliseconds();\n\t\tf = (t & 0xFFF)/(float)0x1000;\n\t\tflutter = Sin(f * 6.28f);\n\t\tstrength = -0.008f;\n\t}else{\n\t\tt = (uintptr)this + CTimer::GetTimeInMilliseconds();\n\t\tf = (t & 0xFFF)/(float)0x1000;\n\t\tflutter = Sin(f * 6.28f);\n\t\tstrength = -0.005f;\n\t}\n\n\tmat.GetUp().x = strength * flutter;\n\tif(IsPalmTreeModel(GetModelIndex()))\n\t\tmat.GetUp().x += -0.07f*CWeather::Wind;\n\tmat.GetUp().y = mat.GetUp().x;\n\n\tCWindModifiers::FindWindModifier(GetPosition(), &mat.GetUp().x, &mat.GetUp().y);\n\n\tmat.UpdateRW();\n\tUpdateRwFrame();\n}\n\nfloat BannerWindTabel[] = {\n\t0.0f, 0.3f, 0.6f, 0.85f, 0.99f, 0.97f, 0.65f, 0.15f,\n\t-0.1f, 0.0f, 0.35f, 0.57f, 0.55f, 0.35f, 0.45f, 0.67f,\n\t0.73f, 0.45f, 0.25f, 0.35f, 0.35f, 0.11f, 0.13f, 0.21f,\n\t0.28f, 0.28f, 0.22f, 0.1f, 0.0f, -0.1f, -0.17f, -0.12f\n};\n\n// unused\nvoid\nCEntity::ModifyMatrixForBannerInWind(void)\n{\n\tuint16 t;\n\tfloat f;\n\tfloat strength, flutter;\n\tCVector right, up;\n\n\tif(CTimer::GetIsPaused())\n\t\treturn;\n\n\tif(CWeather::Wind < 0.1f)\n\t\tstrength = 0.2f;\n\telse if(CWeather::Wind < 0.8f)\n\t\tstrength = 0.43f;\n\telse\n\t\tstrength = 0.66f;\n\n\tt = ((int)(GetMatrix().GetPosition().x + GetMatrix().GetPosition().y) << 10) + 16*CTimer::GetTimeInMilliseconds();\n\tf = (t & 0x7FF)/(float)0x800;\n\tflutter = f * BannerWindTabel[(t>>11)+1 & 0x1F] +\n\t\t(1.0f - f) * BannerWindTabel[(t>>11) & 0x1F];\n\tflutter *= strength;\n\n\tright = CrossProduct(GetForward(), GetUp());\n\tright.z = 0.0f;\n\tright.Normalise();\n\tup = right * flutter;\n\tup.z = Sqrt(sq(1.0f) - sq(flutter));\n\tGetRight() = CrossProduct(GetForward(), up);\n\tGetUp() = up;\n\n\tGetMatrix().UpdateRW();\n\tUpdateRwFrame();\n}\n\nvoid\nCEntity::PreRenderForGlassWindow(void)\n{\n\tif(((CSimpleModelInfo*)CModelInfo::GetModelInfo(m_modelIndex))->m_isArtistGlass)\n\t\treturn;\n\tCGlass::AskForObjectToBeRenderedInGlass(this);\n\tbIsVisible = false;\n}\n\n/*\n0x487A10 - SetAtomicAlphaCB\n0x4879E0 - SetClumpAlphaCB\n*/\n\nRpMaterial*\nSetAtomicAlphaCB(RpMaterial *material, void *data)\n{\n\t((RwRGBA*)RpMaterialGetColor(material))->alpha = (uint8)(uintptr)data;\n\treturn material;\n}\n\nRpAtomic*\nSetClumpAlphaCB(RpAtomic *atomic, void *data)\n{\n\tRpGeometry *geometry = RpAtomicGetGeometry(atomic);\n\tRpGeometrySetFlags(geometry, RpGeometryGetFlags(geometry) | rpGEOMETRYMODULATEMATERIALCOLOR);\n\tRpGeometryForAllMaterials(geometry, SetAtomicAlphaCB, (void*)data);\n\treturn atomic;\n}\n\nvoid\nCEntity::SetRwObjectAlpha(int32 alpha)\n{\n\tif (m_rwObject != nil) {\n\t\tswitch (RwObjectGetType(m_rwObject)) {\n\t\tcase rpATOMIC: {\n\t\t\tRpGeometry *geometry = RpAtomicGetGeometry((RpAtomic*)m_rwObject);\n\t\t\tRpGeometrySetFlags(geometry, RpGeometryGetFlags(geometry) | rpGEOMETRYMODULATEMATERIALCOLOR);\n\t\t\tRpGeometryForAllMaterials(geometry, SetAtomicAlphaCB, (void*)alpha);\n\t\t\tbreak;\n\t\t}\n\t\tcase rpCLUMP:\n\t\t\tRpClumpForAllAtomics((RpClump*)m_rwObject, SetClumpAlphaCB, (void*)alpha);\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\nbool IsEntityPointerValid(CEntity* pEntity)\n{\n\tif (!pEntity)\n\t\treturn false;\n\tswitch (pEntity->GetType()) {\n\tcase ENTITY_TYPE_NOTHING: return false;\n\tcase ENTITY_TYPE_BUILDING: return IsBuildingPointerValid((CBuilding*)pEntity);\n\tcase ENTITY_TYPE_VEHICLE: return IsVehiclePointerValid((CVehicle*)pEntity);\n\tcase ENTITY_TYPE_PED: return IsPedPointerValid((CPed*)pEntity);\n\tcase ENTITY_TYPE_OBJECT: return IsObjectPointerValid((CObject*)pEntity);\n\tcase ENTITY_TYPE_DUMMY: return IsDummyPointerValid((CDummy*)pEntity);\n\t}\n\treturn false;\n}\n\n#ifdef COMPATIBLE_SAVES\nvoid\nCEntity::SaveEntityFlags(uint8*& buf)\n{\n\tuint32 tmp = 0;\n\ttmp |= (m_type & (BIT(3) - 1));\n\ttmp |= (m_status & (BIT(5) - 1)) << 3;\n\n\tif (bUsesCollision) tmp |= BIT(8);\n\tif (bCollisionProcessed) tmp |= BIT(9);\n\tif (bIsStatic)  tmp |= BIT(10);\n\tif (bHasContacted) tmp |= BIT(11);\n\tif (bPedPhysics) tmp |= BIT(12);\n\tif (bIsStuck) tmp |= BIT(13);\n\tif (bIsInSafePosition) tmp |= BIT(14);\n\tif (bUseCollisionRecords) tmp |= BIT(15);\n\n\tif (bWasPostponed) tmp |= BIT(16);\n\tif (bExplosionProof) tmp |= BIT(17);\n\tif (bIsVisible)  tmp |= BIT(18);\n\tif (bHasCollided) tmp |= BIT(19);\n\tif (bRenderScorched) tmp |= BIT(20);\n\tif (bHasBlip) tmp |= BIT(21);\n\tif (bIsBIGBuilding) tmp |= BIT(22);\n\tif (bStreamBIGBuilding) tmp |= BIT(23);\n\n\tif (bRenderDamaged) tmp |= BIT(24);\n\tif (bBulletProof) tmp |= BIT(25);\n\tif (bFireProof) tmp |= BIT(26);\n\tif (bCollisionProof)  tmp |= BIT(27);\n\tif (bMeleeProof) tmp |= BIT(28);\n\tif (bOnlyDamagedByPlayer) tmp |= BIT(29);\n\tif (bStreamingDontDelete) tmp |= BIT(30);\n\tif (bRemoveFromWorld) tmp |= BIT(31);\n\n\tWriteSaveBuf<uint32>(buf, tmp);\n\n\ttmp = 0;\n\n\tif (bHasHitWall) tmp |= BIT(0);\n\tif (bImBeingRendered)  tmp |= BIT(1);\n\tif (bTouchingWater) tmp |= BIT(2);\n\tif (bIsSubway) tmp |= BIT(3);\n\tif (bDrawLast) tmp |= BIT(4);\n\tif (bNoBrightHeadLights) tmp |= BIT(5);\n\tif (bDoNotRender) tmp |= BIT(6);\n\tif (bDistanceFade) tmp |= BIT(7);\n\n\tif (m_flagE1) tmp |= BIT(8);\n\tif (m_flagE2) tmp |= BIT(9);\n\tif (bOffscreen) tmp |= BIT(10);\n\tif (bIsStaticWaitingForCollision) tmp |= BIT(11);\n\tif (bDontStream) tmp |= BIT(12);\n\tif (bUnderwater) tmp |= BIT(13);\n\tif (bHasPreRenderEffects) tmp |= BIT(14);\n\n\tWriteSaveBuf<uint32>(buf, tmp);\n}\n\nvoid\nCEntity::LoadEntityFlags(uint8*& buf)\n{\n\tuint32 tmp = ReadSaveBuf<uint32>(buf);\n\tm_type = (tmp & ((BIT(3) - 1)));\n\tm_status = ((tmp >> 3) & (BIT(5) - 1));\n\n\tbUsesCollision = !!(tmp & BIT(8));\n\tbCollisionProcessed = !!(tmp & BIT(9));\n\tbIsStatic = !!(tmp & BIT(10));\n\tbHasContacted = !!(tmp & BIT(11));\n\tbPedPhysics = !!(tmp & BIT(12));\n\tbIsStuck = !!(tmp & BIT(13));\n\tbIsInSafePosition = !!(tmp & BIT(14));\n\tbUseCollisionRecords = !!(tmp & BIT(15));\n\n\tbWasPostponed = !!(tmp & BIT(16));\n\tbExplosionProof = !!(tmp & BIT(17));\n\tbIsVisible = !!(tmp & BIT(18));\n\tbHasCollided = !!(tmp & BIT(19));\n\tbRenderScorched = !!(tmp & BIT(20));\n\tbHasBlip = !!(tmp & BIT(21));\n\tbIsBIGBuilding = !!(tmp & BIT(22));\n\tbStreamBIGBuilding = !!(tmp & BIT(23));\n\n\tbRenderDamaged = !!(tmp & BIT(24));\n\tbBulletProof = !!(tmp & BIT(25));\n\tbFireProof = !!(tmp & BIT(26));\n\tbCollisionProof = !!(tmp & BIT(27));\n\tbMeleeProof = !!(tmp & BIT(28));\n\tbOnlyDamagedByPlayer = !!(tmp & BIT(29));\n\tbStreamingDontDelete = !!(tmp & BIT(30));\n\tbRemoveFromWorld = !!(tmp & BIT(31));\n\n\ttmp = ReadSaveBuf<uint32>(buf);\n\n\tbHasHitWall = !!(tmp & BIT(0));\n\tbImBeingRendered = !!(tmp & BIT(1));\n\tbTouchingWater = !!(tmp & BIT(2));\n\tbIsSubway = !!(tmp & BIT(3));\n\tbDrawLast = !!(tmp & BIT(4));\n\tbNoBrightHeadLights = !!(tmp & BIT(5));\n\tbDoNotRender = !!(tmp & BIT(6));\n\tbDistanceFade = !!(tmp & BIT(7));\n\n\tm_flagE1 = !!(tmp & BIT(8));\n\tm_flagE2 = !!(tmp & BIT(9));\n\tbOffscreen = !!(tmp & BIT(10));\n\tbIsStaticWaitingForCollision = !!(tmp & BIT(11));\n\tbDontStream = !!(tmp & BIT(12));\n\tbUnderwater = !!(tmp & BIT(13));\n\tbHasPreRenderEffects = !!(tmp & BIT(14));\n}\n\n#endif\n"
  },
  {
    "path": "src/entities/Entity.h",
    "content": "#pragma once\n\n#include \"ModelInfo.h\"\n#include \"Placeable.h\"\n\nstruct CReference;\nclass CPtrList;\n\nenum eEntityType\n{\n\tENTITY_TYPE_NOTHING = 0,\n\tENTITY_TYPE_BUILDING,\n\tENTITY_TYPE_VEHICLE,\n\tENTITY_TYPE_PED,\n\tENTITY_TYPE_OBJECT,\n\tENTITY_TYPE_DUMMY,\n};\n\nenum eEntityStatus\n{\n\tSTATUS_PLAYER,\n\tSTATUS_PLAYER_PLAYBACKFROMBUFFER,\n\tSTATUS_SIMPLE,\n\tSTATUS_PHYSICS,\n\tSTATUS_ABANDONED,\n\tSTATUS_WRECKED,\n\tSTATUS_TRAIN_MOVING,\n\tSTATUS_TRAIN_NOT_MOVING,\n\tSTATUS_HELI,\n\tSTATUS_PLANE,\n\tSTATUS_PLAYER_REMOTE,\n\tSTATUS_PLAYER_DISABLED,\n\tSTATUS_GHOST\n};\n\nclass CEntity : public CPlaceable\n{\npublic:\n\tRwObject *m_rwObject;\nprotected:\n\tuint32 m_type : 3;\nprivate:\n\tuint32 m_status : 5;\npublic:\n\t// flagsA\n\tuint32 bUsesCollision : 1;\t\t\t// does entity use collision\n\tuint32 bCollisionProcessed : 1;\t\t// has object been processed by a ProcessEntityCollision function\n\tuint32 bIsStatic : 1;\t\t\t\t// is entity static\n\tuint32 bHasContacted : 1;\t\t\t// has entity processed some contact forces\n\tuint32 bPedPhysics : 1;\n\tuint32 bIsStuck : 1;\t\t\t\t// is entity stuck\n\tuint32 bIsInSafePosition : 1;\t\t// is entity in a collision free safe position\n\tuint32 bUseCollisionRecords : 1;\n\n\t// flagsB\n\tuint32 bWasPostponed : 1;\t\t\t// was entity control processing postponed\n\tuint32 bExplosionProof : 1;\n\tuint32 bIsVisible : 1;\t\t\t\t//is the entity visible\n\tuint32 bHasCollided : 1;\n\tuint32 bRenderScorched : 1;\n\tuint32 bHasBlip : 1;\n\tuint32 bIsBIGBuilding : 1;\t\t\t// Set if this entity is a big building\n\tuint32 bStreamBIGBuilding : 1;\t// set when draw dist <= 2000\n\n\t// flagsC\n\tuint32 bRenderDamaged : 1;\t\t\t// use damaged LOD models for objects with applicable damage\n\tuint32 bBulletProof : 1;\n\tuint32 bFireProof : 1;\n\tuint32 bCollisionProof : 1;\n\tuint32 bMeleeProof : 1;\n\tuint32 bOnlyDamagedByPlayer : 1;\n\tuint32 bStreamingDontDelete : 1;\t// Dont let the streaming remove this \n\tuint32 bRemoveFromWorld : 1;\t\t// remove this entity next time it should be processed\n\n\t// flagsD\n\tuint32 bHasHitWall : 1;\t\t\t\t// has collided with a building (changes subsequent collisions)\n\tuint32 bImBeingRendered : 1;\t\t// don't delete me because I'm being rendered\n\tuint32 bTouchingWater : 1;\t// used by cBuoyancy::ProcessBuoyancy\n\tuint32 bIsSubway : 1;\t// set when subway, but maybe different meaning?\n\tuint32 bDrawLast : 1;\t\t\t\t// draw object last\n\tuint32 bNoBrightHeadLights : 1;\n\tuint32 bDoNotRender : 1;\t//-- only applies to CObjects apparently\n\tuint32 bDistanceFade : 1;\t\t\t// Fade entity because it is far away\n\n\t// flagsE\n\tuint32 m_flagE1 : 1;\n\tuint32 m_flagE2 : 1;\n\tuint32 bOffscreen : 1;               // offscreen flag. This can only be trusted when it is set to true\n\tuint32 bIsStaticWaitingForCollision : 1; // this is used by script created entities - they are static until the collision is loaded below them\n\tuint32 bDontStream : 1;              // tell the streaming not to stream me\n\tuint32 bUnderwater : 1;              // this object is underwater change drawing order\n\tuint32 bHasPreRenderEffects : 1; // Object has a prerender effects attached to it\n\n\tuint16 m_scanCode;\n\tuint16 m_randomSeed;\n\tint16 m_modelIndex;\n\tint8 m_level;\n\tint8 m_area;\n\tCReference *m_pFirstReference;\n\npublic:\n\tuint8 GetType() const { return m_type; }\n\tvoid SetType(uint8 type) { m_type = type; }\n\tuint8 GetStatus() const { return m_status; }\n\tvoid SetStatus(uint8 status) { m_status = status; }\n\tCColModel *GetColModel(void) { return CModelInfo::GetModelInfo(m_modelIndex)->GetColModel(); }\n\tbool GetIsStatic(void) const { return bIsStatic || bIsStaticWaitingForCollision; }\n\tvoid SetIsStatic(bool state) { bIsStatic = state; }\n#ifdef COMPATIBLE_SAVES\n\tvoid SaveEntityFlags(uint8*& buf);\n\tvoid LoadEntityFlags(uint8*& buf);\n#else\n\tuint32* GetAddressOfEntityProperties() { /* AWFUL */ return (uint32*)((char*)&m_rwObject + sizeof(m_rwObject)); }\n#endif\n\n\tCEntity(void);\n\tvirtual ~CEntity(void);\n\n\tvirtual void Add(void);\n\tvirtual void Remove(void);\n\tvirtual void SetModelIndex(uint32 id);\n\tvirtual void SetModelIndexNoCreate(uint32 id);\n\tvirtual void CreateRwObject(void);\n\tvirtual void DeleteRwObject(void);\n\tvirtual CRect GetBoundRect(void);\n\tvirtual void ProcessControl(void) {}\n\tvirtual void ProcessCollision(void) {}\n\tvirtual void ProcessShift(void) {}\n\tvirtual void Teleport(CVector v) {}\n\tvirtual void PreRender(void);\n\tvirtual void Render(void);\n\tvirtual bool SetupLighting(void);\n\tvirtual void RemoveLighting(bool);\n\tvirtual void FlagToDestroyWhenNextProcessed(void) {}\n\n\tbool IsBuilding(void) { return m_type == ENTITY_TYPE_BUILDING; }\n\tbool IsVehicle(void) { return m_type == ENTITY_TYPE_VEHICLE; }\n\tbool IsPed(void) { return m_type == ENTITY_TYPE_PED; }\n\tbool IsObject(void) { return m_type == ENTITY_TYPE_OBJECT; }\n\tbool IsDummy(void) { return m_type == ENTITY_TYPE_DUMMY; }\n\n\tRpAtomic *GetAtomic(void) {\n\t\tassert(RwObjectGetType(m_rwObject) == rpATOMIC);\n\t\treturn (RpAtomic*)m_rwObject;\n\t}\n\tRpClump *GetClump(void) {\n\t\tassert(RwObjectGetType(m_rwObject) == rpCLUMP);\n\t\treturn (RpClump*)m_rwObject;\n\t}\n\n\tvoid GetBoundCentre(CVector &out);\n\tCVector GetBoundCentre(void);\n\tfloat GetBoundRadius(void);\n\tfloat GetDistanceFromCentreOfMassToBaseOfModel(void);\n\tbool GetIsTouching(CVector const &center, float r);\n\tbool GetIsOnScreen(void);\n\tbool GetIsOnScreenComplex(void);\n\tbool IsVisible(void);\n\tbool IsVisibleComplex(void);\n\tbool IsEntityOccluded(void);\n\tint16 GetModelIndex(void) const { return m_modelIndex; }\n\tvoid UpdateRwFrame(void);\n\tvoid SetupBigBuilding(void);\n\tbool HasPreRenderEffects(void);\n\n\tvoid AttachToRwObject(RwObject *obj);\n\tvoid DetachFromRwObject(void);\n\n\tvoid RegisterReference(CEntity **pent);\n\tvoid ResolveReferences(void);\n\tvoid PruneReferences(void);\n\tvoid CleanUpOldReference(CEntity **pent);\n\n\tvoid UpdateRpHAnim(void);\n\n\tvoid PreRenderForGlassWindow(void);\n\tvoid AddSteamsFromGround(CVector *unused);\n\tvoid ModifyMatrixForTreeInWind(void);\n\tvoid ModifyMatrixForBannerInWind(void);\n\tvoid ProcessLightsForEntity(void);\n\tvoid SetRwObjectAlpha(int32 alpha);\n};\n\nbool IsEntityPointerValid(CEntity*);\n"
  },
  {
    "path": "src/entities/Physical.cpp",
    "content": "#include \"common.h\"\n\n#include \"World.h\"\n#include \"General.h\"\n#include \"Timer.h\"\n#include \"Stats.h\"\n#include \"ModelIndices.h\"\n#include \"Treadable.h\"\n#include \"Vehicle.h\"\n#include \"Ped.h\"\n#include \"Object.h\"\n#include \"Glass.h\"\n#include \"ParticleObject.h\"\n#include \"Particle.h\"\n#include \"SurfaceTable.h\"\n#include \"PathFind.h\"\n#include \"CarCtrl.h\"\n#include \"DMAudio.h\"\n#include \"Automobile.h\"\n#include \"Bike.h\"\n#include \"Pickups.h\"\n#include \"Physical.h\"\n\n#ifdef WALLCLIMB_CHEAT\nbool gGravityCheat;\n#endif\n\n\nCPhysical::CPhysical(void)\n{\n\tint i;\n\n#ifdef FIX_BUGS\n\tm_nLastTimeCollided = 0;\n#endif\n\n\tm_fForceMultiplier = 1.0f;\n\tm_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);\n\tm_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f);\n\tm_vecMoveFriction = CVector(0.0f, 0.0f, 0.0f);\n\tm_vecTurnFriction = CVector(0.0f, 0.0f, 0.0f);\n\tm_vecMoveSpeedAvg = CVector(0.0f, 0.0f, 0.0f);\n\tm_vecTurnSpeedAvg = CVector(0.0f, 0.0f, 0.0f);\n\n\tm_movingListNode = nil;\n\tm_nStaticFrames = 0;\n\n\tm_nCollisionRecords = 0;\n\tfor(i = 0; i < 6; i++)\n\t\tm_aCollisionRecords[i] = nil;\n\n\tm_bIsVehicleBeingShifted = false;\n\tbJustCheckCollision = false;\n\n\tm_nDamagePieceType = 0;\n\tm_fDamageImpulse = 0.0f;\n\tm_pDamageEntity = nil;\n\tm_vecDamageNormal = CVector(0.0f, 0.0f, 0.0f);\n\n\tbUsesCollision = true;\n\tm_audioEntityId = -5;\n\tm_phys_unused1 = 100.0f;\n\tm_vecCentreOfMass = CVector(0.0f, 0.0f, 0.0f);\n\tm_phys_unused2 = 0;\n\n\tbIsHeavy = false;\n\tbAffectedByGravity = true;\n\tbInfiniteMass = false;\n\tm_phy_flagA08 = false;\n\tbIsInWater = false;\n\tbHitByTrain = false;\n\tbSkipLineCol = false;\n\n\tm_fDistanceTravelled = 0.0f;\n\n\tm_phy_flagA20 = false;\n\n#ifdef FIX_BUGS\n\tm_nSurfaceTouched = SURFACE_DEFAULT;\n#endif\n\tm_nZoneLevel = LEVEL_GENERIC;\n\n\tbIsFrozen = false;\n\tbDontLoadCollision = false;\n}\n\nCPhysical::~CPhysical(void)\n{\n\tm_entryInfoList.Flush();\n}\n\nvoid\nCPhysical::Add(void)\n{\n\tint x, xstart, xmid, xend;\n\tint y, ystart, ymid, yend;\n\tCSector *s;\n\tCPtrList *list;\n\n\tCRect bounds = GetBoundRect();\n\txstart = CWorld::GetSectorIndexX(bounds.left);\n\txend   = CWorld::GetSectorIndexX(bounds.right);\n\txmid   = CWorld::GetSectorIndexX((bounds.left + bounds.right)/2.0f);\n\tystart = CWorld::GetSectorIndexY(bounds.top);\n\tyend   = CWorld::GetSectorIndexY(bounds.bottom);\n\tymid   = CWorld::GetSectorIndexY((bounds.top + bounds.bottom)/2.0f);\n\tassert(xstart >= 0);\n\tassert(xend < NUMSECTORS_X);\n\tassert(ystart >= 0);\n\tassert(yend < NUMSECTORS_Y);\n\n\tfor(y = ystart; y <= yend; y++)\n\t\tfor(x = xstart; x <= xend; x++){\n\t\t\ts = CWorld::GetSector(x, y);\n\t\t\tif(x == xmid && y == ymid) switch(m_type){\n\t\t\tcase ENTITY_TYPE_VEHICLE:\n\t\t\t\tlist = &s->m_lists[ENTITYLIST_VEHICLES];\n\t\t\t\tbreak;\n\t\t\tcase ENTITY_TYPE_PED:\n\t\t\t\tlist = &s->m_lists[ENTITYLIST_PEDS];\n\t\t\t\tbreak;\n\t\t\tcase ENTITY_TYPE_OBJECT:\n\t\t\t\tlist = &s->m_lists[ENTITYLIST_OBJECTS];\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tassert(0);\n\t\t\t}else switch(m_type){\n\t\t\tcase ENTITY_TYPE_VEHICLE:\n\t\t\t\tlist = &s->m_lists[ENTITYLIST_VEHICLES_OVERLAP];\n\t\t\t\tbreak;\n\t\t\tcase ENTITY_TYPE_PED:\n\t\t\t\tlist = &s->m_lists[ENTITYLIST_PEDS_OVERLAP];\n\t\t\t\tbreak;\n\t\t\tcase ENTITY_TYPE_OBJECT:\n\t\t\t\tlist = &s->m_lists[ENTITYLIST_OBJECTS_OVERLAP];\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tassert(0);\n\t\t\t}\n\t\t\tCPtrNode *node = list->InsertItem(this);\n\t\t\tassert(node);\n\t\t\tm_entryInfoList.InsertItem(list, node, s);\n\t\t}\n}\n\nvoid\nCPhysical::Remove(void)\n{\n\tCEntryInfoNode *node, *next;\n\tfor(node = m_entryInfoList.first; node; node = next){\n\t\tnext = node->next;\n\t\tnode->list->DeleteNode(node->listnode);\n\t\tm_entryInfoList.DeleteNode(node);\n\t}\n}\n\nvoid\nCPhysical::RemoveAndAdd(void)\n{\n\tint x, xstart, xmid, xend;\n\tint y, ystart, ymid, yend;\n\tCSector *s;\n\tCPtrList *list;\n\n\tCRect bounds = GetBoundRect();\n\txstart = CWorld::GetSectorIndexX(bounds.left);\n\txend   = CWorld::GetSectorIndexX(bounds.right);\n\txmid   = CWorld::GetSectorIndexX((bounds.left + bounds.right)/2.0f);\n\tystart = CWorld::GetSectorIndexY(bounds.top);\n\tyend   = CWorld::GetSectorIndexY(bounds.bottom);\n\tymid   = CWorld::GetSectorIndexY((bounds.top + bounds.bottom)/2.0f);\n\tassert(xstart >= 0);\n\tassert(xend < NUMSECTORS_X);\n\tassert(ystart >= 0);\n\tassert(yend < NUMSECTORS_Y);\n\n\t// we'll try to recycle nodes from here\n\tCEntryInfoNode *next = m_entryInfoList.first;\n\n\tfor(y = ystart; y <= yend; y++)\n\t\tfor(x = xstart; x <= xend; x++){\n\t\t\ts = CWorld::GetSector(x, y);\n\t\t\tif(x == xmid && y == ymid) switch(m_type){\n\t\t\tcase ENTITY_TYPE_VEHICLE:\n\t\t\t\tlist = &s->m_lists[ENTITYLIST_VEHICLES];\n\t\t\t\tbreak;\n\t\t\tcase ENTITY_TYPE_PED:\n\t\t\t\tlist = &s->m_lists[ENTITYLIST_PEDS];\n\t\t\t\tbreak;\n\t\t\tcase ENTITY_TYPE_OBJECT:\n\t\t\t\tlist = &s->m_lists[ENTITYLIST_OBJECTS];\n\t\t\t\tbreak;\n\t\t\t}else switch(m_type){\n\t\t\tcase ENTITY_TYPE_VEHICLE:\n\t\t\t\tlist = &s->m_lists[ENTITYLIST_VEHICLES_OVERLAP];\n\t\t\t\tbreak;\n\t\t\tcase ENTITY_TYPE_PED:\n\t\t\t\tlist = &s->m_lists[ENTITYLIST_PEDS_OVERLAP];\n\t\t\t\tbreak;\n\t\t\tcase ENTITY_TYPE_OBJECT:\n\t\t\t\tlist = &s->m_lists[ENTITYLIST_OBJECTS_OVERLAP];\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif(next){\n\t\t\t\t// If we still have old nodes, use them\n\t\t\t\tnext->list->RemoveNode(next->listnode);\n\t\t\t\tlist->InsertNode(next->listnode);\n\t\t\t\tnext->list = list;\n\t\t\t\tnext->sector = s;\n\t\t\t\tnext = next->next;\n\t\t\t}else{\n\t\t\t\tCPtrNode *node = list->InsertItem(this);\n\t\t\t\tm_entryInfoList.InsertItem(list, node, s);\n\t\t\t}\n\t\t}\n\n\t// Remove old nodes we no longer need\n\tCEntryInfoNode *node;\n\tfor(node = next; node; node = next){\n\t\tnext = node->next;\n\t\tnode->list->DeleteNode(node->listnode);\n\t\tm_entryInfoList.DeleteNode(node);\n\t}\n}\n\nCRect\nCPhysical::GetBoundRect(void)\n{\n\tCVector center;\n\tfloat radius;\n\tGetBoundCentre(center);\n\tradius = GetBoundRadius();\n\treturn CRect(center.x-radius, center.y-radius, center.x+radius, center.y+radius);\n}\n\n// --MIAMI: Proof-read once\nvoid\nCPhysical::AddToMovingList(void)\n{\n\tif (!bIsStaticWaitingForCollision)\n\t\tm_movingListNode = CWorld::GetMovingEntityList().InsertItem(this);\n}\n\n// --MIAMI: Proof-read once\nvoid\nCPhysical::RemoveFromMovingList(void)\n{\n\tif(m_movingListNode){\n\t\tCWorld::GetMovingEntityList().DeleteNode(m_movingListNode);\n\t\tm_movingListNode = nil;\n\t}\n}\n\nvoid\nCPhysical::SetDamagedPieceRecord(uint16 piece, float impulse, CEntity *entity, CVector dir)\n{\n\tm_nDamagePieceType = piece;\n\tm_fDamageImpulse = impulse;\n\tm_pDamageEntity = entity;\n\tentity->RegisterReference(&m_pDamageEntity);\n\tm_vecDamageNormal = dir;\n}\n\n// --MIAMI: Proof-read once\nvoid\nCPhysical::AddCollisionRecord(CEntity *ent)\n{\n\tAddCollisionRecord_Treadable(ent);\n\tthis->bHasCollided = true;\n\tent->bHasCollided = true;\n\tthis->m_nLastTimeCollided = CTimer::GetTimeInMilliseconds();\n\tif(IsVehicle() && ent->IsVehicle()){\n\t\tif(((CVehicle*)this)->m_nAlarmState == -1)\n\t\t\t((CVehicle*)this)->m_nAlarmState = 15000;\n\t\tif(((CVehicle*)ent)->m_nAlarmState == -1)\n\t\t\t((CVehicle*)ent)->m_nAlarmState = 15000;\n\t}\n\tif(bUseCollisionRecords){\n\t\tint i;\n\t\tfor(i = 0; i < m_nCollisionRecords; i++)\n\t\t\tif(m_aCollisionRecords[i] == ent)\n\t\t\t\treturn;\n\t\tif(m_nCollisionRecords < PHYSICAL_MAX_COLLISIONRECORDS)\n\t\t\tm_aCollisionRecords[m_nCollisionRecords++] = ent;\n\t}\n}\n\n// --MIAMI: Proof-read once\nvoid\nCPhysical::AddCollisionRecord_Treadable(CEntity *ent)\n{\n\tif(ent->IsBuilding() && ((CBuilding*)ent)->GetIsATreadable()){\n\t}\n}\n\n// --MIAMI: Proof-read once\nbool\nCPhysical::GetHasCollidedWith(CEntity *ent)\n{\n\tint i;\n\tif(bUseCollisionRecords)\n\t\tfor(i = 0; i < m_nCollisionRecords; i++)\n\t\t\tif(m_aCollisionRecords[i] == ent)\n\t\t\t\treturn true;\n\treturn false;\n}\n\n// --MIAMI: Proof-read once\nvoid\nCPhysical::RemoveRefsToEntity(CEntity *ent)\n{\n\tint i = 0, j;\n\n\twhile (i < m_nCollisionRecords){\n\t\tif(m_aCollisionRecords[i] == ent){\n\t\t\tfor(j = i; j < m_nCollisionRecords-1; j++)\n\t\t\t\tm_aCollisionRecords[j] = m_aCollisionRecords[j+1];\n\t\t\tm_nCollisionRecords--;\n\t\t} else\n\t\t\ti++;\n\t}\n}\n\n// --MIAMI: Proof-read once\nvoid\nCPhysical::PlacePhysicalRelativeToOtherPhysical(CPhysical *other, CPhysical *phys, CVector localPos)\n{\n\tCVector worldPos = other->GetMatrix() * localPos;\n\tfloat step = 0.9f * CTimer::GetTimeStep();\n\tCVector pos = other->m_vecMoveSpeed*step + worldPos;\n\n\tCWorld::Remove(phys);\n\tphys->GetMatrix() = other->GetMatrix();\n\tphys->SetPosition(pos);\n\tphys->m_vecMoveSpeed = other->m_vecMoveSpeed;\n\tphys->GetMatrix().UpdateRW();\n\tphys->UpdateRwFrame();\n\tCWorld::Add(phys);\n}\n\n// --MIAMI: Proof-read once\nint32\nCPhysical::ProcessEntityCollision(CEntity *ent, CColPoint *colpoints)\n{\n\tint32 numSpheres = CCollision::ProcessColModels(\n\t\tGetMatrix(), *GetColModel(),\n\t\tent->GetMatrix(), *ent->GetColModel(),\n\t\tcolpoints,\n\t\tnil, nil);\t// No Lines allowed!\n\tif(numSpheres > 0){\n\t\tAddCollisionRecord(ent);\n\t\tif(!ent->IsBuilding())\t// Can't this catch dummies too?\n\t\t\t((CPhysical*)ent)->AddCollisionRecord(this);\n\t\tif(ent->IsBuilding() || ent->GetIsStatic())\n\t\t\tthis->bHasHitWall = true;\n\t}\n\treturn numSpheres;\n}\n\n// --MIAMI: Proof-read once\nvoid\nCPhysical::ProcessControl(void)\n{\n\tif(!IsPed())\n\t\tbIsInWater = false;\n\tbHasContacted = false;\n\tbIsInSafePosition = false;\n\tbWasPostponed = false;\n\tbHasHitWall = false;\n\n\tif(GetStatus() == STATUS_SIMPLE)\n\t\treturn;\n\n\tm_nCollisionRecords = 0;\n\tbHasCollided = false;\n\tm_nDamagePieceType = 0;\n\tm_fDamageImpulse = 0.0f;\n\tm_pDamageEntity = nil;\n\n\tif(!bIsStuck){\n\t\tif(IsObject() ||\n\t\t   IsPed() && !bPedPhysics){\n\t\t\tm_vecMoveSpeedAvg = (m_vecMoveSpeedAvg + m_vecMoveSpeed)/2.0f;\n\t\t\tm_vecTurnSpeedAvg = (m_vecTurnSpeedAvg + m_vecTurnSpeed)/2.0f;\n\t\t\tfloat step = CTimer::GetTimeStep() * 0.003f;\n\t\t\tif(m_vecMoveSpeedAvg.MagnitudeSqr() < step*step &&\n\t\t\t   m_vecTurnSpeedAvg.MagnitudeSqr() < step*step){\n\t\t\t\tm_nStaticFrames++;\n\t\t\t\tif(m_nStaticFrames > 10){\n\t\t\t\t\tm_nStaticFrames = 10;\n\t\t\t\t\tSetIsStatic(true);\n\t\t\t\t\tm_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);\n\t\t\t\t\tm_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f);\n\t\t\t\t\tm_vecMoveFriction = m_vecMoveSpeed;\n\t\t\t\t\tm_vecTurnFriction = m_vecTurnSpeed;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}else \n\t\t\t\tm_nStaticFrames = 0;\n\t\t}\n\t}\n\tApplyGravity();\n\tApplyFriction();\n\tApplyAirResistance();\n}\n\n/*\n * Some quantities (german in parens):\n *\n * acceleration: distance/time^2: a\n * velocity: distance/time: v\t(GTA: speed)\n * momentum (impuls): velocity*mass: p\n * impulse (kraftstoss): delta momentum, force*time: J\n *\n * angular equivalents:\n * velocity -> angular velocity\t(GTA: turn speed)\n * momentum -> angular momentum (drehimpuls): L = r cross p\n * force -> torque (drehmoment): tau = r cross F\n * mass -> moment of inertia, angular mass (drehmoment, drehmasse): I = L/omega\t(GTA: turn mass)\n */\n\nCVector\nCPhysical::GetSpeed(const CVector &r)\n{\n\treturn m_vecMoveSpeed + m_vecMoveFriction + CrossProduct(m_vecTurnFriction + m_vecTurnSpeed, r);\n}\n\n// --MIAMI: Proof-read once\nvoid\nCPhysical::ApplyMoveSpeed(void)\n{\n\tif(bIsFrozen)\n\t\tm_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);\n\telse\n\t\tGetMatrix().Translate(m_vecMoveSpeed * CTimer::GetTimeStep());\n}\n\n// --MIAMI: Proof-read once\nvoid\nCPhysical::ApplyTurnSpeed(void)\n{\n\tif(bIsFrozen){\n\t\tm_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f);\n\t}else{\n\t\t// Move the coordinate axes by their speed\n\t\t// Note that this denormalizes the matrix\n\t\tCVector turnvec = m_vecTurnSpeed*CTimer::GetTimeStep();\n\t\tGetRight() += CrossProduct(turnvec, GetRight());\n\t\tGetForward() += CrossProduct(turnvec, GetForward());\n\t\tGetUp() += CrossProduct(turnvec, GetUp());\n\t}\n}\n\n// --MIAMI: Proof-read once\nvoid\nCPhysical::ApplyMoveForce(float jx, float jy, float jz)\n{\n\tm_vecMoveSpeed += CVector(jx, jy, jz)*(1.0f/m_fMass);\n}\n\n// --MIAMI: Proof-read once\nvoid\nCPhysical::ApplyTurnForce(float jx, float jy, float jz, float px, float py, float pz)\n{\n\tCVector com = Multiply3x3(m_matrix, m_vecCentreOfMass);\n\tCVector turnimpulse = CrossProduct(CVector(px, py, pz)-com, CVector(jx, jy, jz));\n\tm_vecTurnSpeed += turnimpulse*(1.0f/m_fTurnMass);\n}\n\nvoid\nCPhysical::ApplyFrictionMoveForce(float jx, float jy, float jz)\n{\n\tm_vecMoveFriction += CVector(jx, jy, jz)*(1.0f/m_fMass);\n}\n\n// --MIAMI: Proof-read once\nvoid\nCPhysical::ApplyFrictionTurnForce(float jx, float jy, float jz, float px, float py, float pz)\n{\n\tCVector com = Multiply3x3(m_matrix, m_vecCentreOfMass);\n\tCVector turnimpulse = CrossProduct(CVector(px, py, pz)-com, CVector(jx, jy, jz));\n\tm_vecTurnFriction += turnimpulse*(1.0f/m_fTurnMass);\n}\n\n// --MIAMI: Proof-read once\nbool\nCPhysical::ApplySpringCollision(float springConst, CVector &springDir, CVector &point, float springRatio, float bias)\n{\n\tfloat compression = 1.0f - springRatio;\n\tif(compression > 0.0f){\n\t\tfloat step = Min(CTimer::GetTimeStep(), 3.0f);\n\t\tfloat impulse = -GRAVITY*m_fMass*step * springConst * compression * bias*2.0f;\n\t\tApplyMoveForce(springDir*impulse);\n\t\tApplyTurnForce(springDir*impulse, point);\n\t}\n\treturn true;\n}\n\n// --MIAMI: Proof-read once\nbool\nCPhysical::ApplySpringCollisionAlt(float springConst, CVector &springDir, CVector &point, float springRatio, float bias, CVector &forceDir)\n{\n\tfloat compression = 1.0f - springRatio;\n\tif(compression > 0.0f){\n\t\tif(DotProduct(springDir, forceDir) > 0.0f)\n\t\t\tforceDir *= -1.0f;\n\t\tfloat step = Min(CTimer::GetTimeStep(), 3.0f);\n\t\tfloat impulse = GRAVITY*m_fMass*step * springConst * compression * bias*2.0f;\n\t\tif(bIsHeavy)\n\t\t\timpulse *= 0.75f;\n\t\tApplyMoveForce(forceDir*impulse);\n\t\tApplyTurnForce(forceDir*impulse, point);\n\t}\n\treturn true;\n}\n\n// --MIAMI: Proof-read once\n// What exactly is speed?\nbool\nCPhysical::ApplySpringDampening(float damping, CVector &springDir, CVector &point, CVector &speed)\n{\n\tfloat speedA = DotProduct(speed, springDir);\n\tfloat speedB = DotProduct(GetSpeed(point), springDir);\n\tfloat step = Min(CTimer::GetTimeStep(), 3.0f);\n\tfloat impulse = -damping * (speedA + speedB)/2.0f * m_fMass * step * 0.53f;\n\tif(bIsHeavy)\n\t\timpulse *= 2.0f;\n\n\t// what is this?\n\tfloat a = m_fTurnMass / ((point.MagnitudeSqr() + 1.0f) * 2.0f * m_fMass);\n\ta = Min(a, 1.0f);\n\tfloat b = Abs(impulse / (speedB * m_fMass));\n\tif(a < b)\n\t\timpulse *= a/b;\n\n\tApplyMoveForce(springDir*impulse);\n\tApplyTurnForce(springDir*impulse, point);\n\treturn true;\n}\n\nvoid\nCPhysical::ApplyGravity(void)\n{\n\tif (!bAffectedByGravity)\n\t\treturn;\n#ifdef WALLCLIMB_CHEAT\n\tif (gGravityCheat && this == FindPlayerVehicle()) {\n\t\tstatic CVector gravityUp(0.0f, 0.0f, 1.0f), surfaceUp(0.0f, 0.0f, 1.0f);\n\t\tCVector belowCar = GetPosition() - 2.0f*GetUp();\n\t\tCColPoint point;\n\t\tCEntity* entity;\n\t\tif (CWorld::ProcessLineOfSight(GetPosition(), belowCar, point, entity, true, false, false, false, false, false))\n\t\t\tsurfaceUp = point.normal;\n\t\telse\n\t\t\tsurfaceUp = CVector(0.0f, 0.0f, 1.0f);\n\t\tfloat t = clamp(CTimer::GetTimeStep() * 0.5f, 0.05f, 0.8f);\n\t\tgravityUp = gravityUp * (1.0f - t) + surfaceUp * t;\n\t\tif (gravityUp.MagnitudeSqr() < 0.1f)\n\t\t\tgravityUp = CVector(0.0f, 0.0f, 1.0f);\n\t\telse\n\t\t\tgravityUp.Normalise();\n\t\tm_vecMoveSpeed -= GRAVITY * CTimer::GetTimeStep() * gravityUp;\n\t\treturn;\n\t}\n#endif\n\tm_vecMoveSpeed.z -= GRAVITY * CTimer::GetTimeStep();\n}\n\nvoid\nCPhysical::ApplyFriction(void)\n{\n\tm_vecMoveSpeed += m_vecMoveFriction;\n\tm_vecTurnSpeed += m_vecTurnFriction;\n\tm_vecMoveFriction = CVector(0.0f, 0.0f, 0.0f);\n\tm_vecTurnFriction = CVector(0.0f, 0.0f, 0.0f);\n}\n\n// --MIAMI: Proof-read once\nvoid\nCPhysical::ApplyAirResistance(void)\n{\n\tif(m_fAirResistance > 0.1f){\n\t\tfloat f = Pow(m_fAirResistance, CTimer::GetTimeStep());\n\t\tm_vecMoveSpeed *= f;\n\t\tm_vecTurnSpeed *= f;\n\t}else if(GetStatus() != STATUS_GHOST){ \n\t\tfloat f = Pow(1.0f/Abs(1.0f + m_fAirResistance*0.5f*m_vecMoveSpeed.MagnitudeSqr()), CTimer::GetTimeStep());\n\t\tm_vecMoveSpeed *= f;\n\t\tm_vecTurnSpeed *= 0.99f;\n\t}\n}\n\nbool\nCPhysical::ApplyCollision(CPhysical *B, CColPoint &colpoint, float &impulseA, float &impulseB)\n{\n\tfloat eA, eB;\n\tCPhysical *A = this;\n\tCObject *Bobj = (CObject*)B;\n\n\tbool foo = false;\t// TODO: what does this mean?\n\tbool ispedcontactA = false;\n\tbool ispedcontactB = false;\n\n\tfloat massFactorA;\n\tif(B->bPedPhysics){\n\t\tmassFactorA = 10.0f;\n\t\tif(B->IsPed() && ((CPed*)B)->m_pCurrentPhysSurface == A)\n\t\t\tispedcontactA = true;\n\t}else\n\t\tmassFactorA = A->bIsHeavy ? 2.0f : 1.0f;\n\n\tfloat massFactorB;\n\tif(A->bPedPhysics){\n\t\tif(A->IsPed() && ((CPed*)A)->IsPlayer() && B->IsVehicle() &&\n\t\t   (B->GetStatus() == STATUS_ABANDONED || B->GetStatus() == STATUS_WRECKED || A->bHasHitWall))\n\t\t\tmassFactorB = 1.0f/(Max(B->m_fMass - 2000.0f, 0.0f)/5000.0f + 1.0f);\n\t\telse\n\t\t\tmassFactorB = 10.0f;\n\n\t\tif(A->IsPed() && ((CPed*)A)->m_pCurrentPhysSurface == B)\n\t\t\tispedcontactB = true;\n\t}else\n\t\tmassFactorB = B->bIsHeavy ? 2.0f : 1.0f;\n\n\tif(B->bInfiniteMass && !B->m_phy_flagA08){\n\t\tispedcontactB = false;\n\t\tfoo = true;\n\t}\n\n\tfloat speedA, speedB;\n\tif(B->GetIsStatic() && !foo){\n\t\tif(A->bPedPhysics){\n\t\t\tspeedA = DotProduct(A->m_vecMoveSpeed, colpoint.normal);\n\t\t\tif(speedA < 0.0f){\n\t\t\t\tif(B->IsObject()){\n\t\t\t\t\timpulseA = -speedA * A->m_fMass;\n\t\t\t\t\timpulseB = impulseA;\n\t\t\t\t\tif(impulseA > Bobj->m_fUprootLimit){\n\t\t\t\t\t\tif(IsGlass(B->GetModelIndex()))\n\t\t\t\t\t\t\tCGlass::WindowRespondsToCollision(B, impulseA, A->m_vecMoveSpeed, colpoint.point, false);\n\t\t\t\t\t\telse if(!B->bInfiniteMass){\n\t\t\t\t\t\t\tB->SetIsStatic(false);\n\t\t\t\t\t\t\tCWorld::Players[CWorld::PlayerInFocus].m_nHavocLevel += 2;\n\t\t\t\t\t\t\tCStats::PropertyDestroyed += CGeneral::GetRandomNumberInRange(30, 60);\n\t\t\t\t\t\t}\n\t\t\t\t\t}else{\n\t\t\t\t\t\tif(IsGlass(B->GetModelIndex()))\n\t\t\t\t\t\t\tCGlass::WindowRespondsToSoftCollision(B, impulseA);\n\t\t\t\t\t\tif(!A->bInfiniteMass)\n\t\t\t\t\t\t\tA->ApplyMoveForce(colpoint.GetNormal() * (1.0f + A->m_fElasticity) * impulseA);\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}else if(!B->bInfiniteMass)\n\t\t\t\t\tB->SetIsStatic(false);\n\t\n\t\t\t\tif(B->bInfiniteMass){\n\t\t\t\t\timpulseA = -speedA * A->m_fMass;\n\t\t\t\t\timpulseB = 0.0f;\n\t\t\t\t\tif(!A->bInfiniteMass)\n\t\t\t\t\t\tA->ApplyMoveForce(colpoint.normal*(1.0f + A->m_fElasticity)*impulseA);\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t}else{\n\t\t\tCVector pointposA = colpoint.point - A->GetPosition();\n\t\t\tspeedA = DotProduct(A->GetSpeed(pointposA), colpoint.normal);\n\t\t\tif(speedA < 0.0f){\n\t\t\t\tif(B->IsObject()){\n\t\t\t\t\tif(A->bHasHitWall)\n\t\t\t\t\t\teA = -1.0f;\n\t\t\t\t\telse\n\t\t\t\t\t\teA = -(1.0f + A->m_fElasticity);\n\t\t\t\t\timpulseA = eA * speedA * A->GetMass(pointposA, colpoint.normal);\n\t\t\t\t\timpulseB = impulseA;\n\n\t\t\t\t\tif(Bobj->m_nCollisionDamageEffect && impulseA > 20.0f){\n\t\t\t\t\t\tBobj->ObjectDamage(impulseA);\n\t\t\t\t\t\tif(!B->bUsesCollision){\n\t\t\t\t\t\t\tif(!A->bInfiniteMass){\n\t\t\t\t\t\t\t\tA->ApplyMoveForce(colpoint.normal*0.2f*impulseA);\n\t\t\t\t\t\t\t\tA->ApplyTurnForce(colpoint.normal*0.2f*impulseA, pointposA);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif((impulseA > Bobj->m_fUprootLimit || A->bIsStuck) &&\n\t\t\t\t\t   !B->bInfiniteMass){\n\t\t\t\t\t\tif(IsGlass(B->GetModelIndex()))\n\t\t\t\t\t\t\tCGlass::WindowRespondsToCollision(B, impulseA, A->m_vecMoveSpeed, colpoint.point, false);\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tB->SetIsStatic(false);\n\t\t\t\t\t\tint16 model = B->GetModelIndex();\n\t\t\t\t\t\tif(model == MI_FIRE_HYDRANT && !Bobj->bHasBeenDamaged){\n\t\t\t\t\t\t\tCParticleObject::AddObject(POBJECT_FIRE_HYDRANT, B->GetPosition() - CVector(0.0f, 0.0f, 0.5f), true);\n\t\t\t\t\t\t\tBobj->bHasBeenDamaged = true;\n\t\t\t\t\t\t}else if(model == MI_PARKINGMETER || model == MI_PARKINGMETER2){\n\t\t\t\t\t\t\tCPickups::CreateSomeMoney(GetPosition(), CGeneral::GetRandomNumber()%100);\n\t\t\t\t\t\t\tBobj->bHasBeenDamaged = true;\n\t\t\t\t\t\t}else if(B->IsObject() && !IsExplosiveThingModel(model))\n\t\t\t\t\t\t\tBobj->bHasBeenDamaged = true;\n\t\t\t\t\t}else{\n\t\t\t\t\t\tif(IsGlass(B->GetModelIndex()))\n\t\t\t\t\t\t\tCGlass::WindowRespondsToSoftCollision(B, impulseA);\n\t\t\t\t\t\tCVector f = colpoint.GetNormal() * impulseA;\n\t\t\t\t\t\tif(A->IsVehicle() && colpoint.normal.z < 0.7f)\n\t\t\t\t\t\t\tf.z *= 0.3f;\n\t\t\t\t\t\tif(!A->bInfiniteMass){\n\t\t\t\t\t\t\tA->ApplyMoveForce(f);\n\t\t\t\t\t\t\tif(!A->IsVehicle() || !CWorld::bNoMoreCollisionTorque)\n\t\t\t\t\t\t\t\tA->ApplyTurnForce(f, pointposA);\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}else if(!B->bInfiniteMass)\n\t\t\t\t\tB->SetIsStatic(false);\n\t\t\t}\n\t\t}\n\t\n\t\tif(B->GetIsStatic())\n\t\t\treturn false;\n\t\tif(!B->bInfiniteMass && !B->m_phy_flagA08)\n\t\t\tB->AddToMovingList();\n\t}\n\n\t// B is not static\n\n\tif(A->bPedPhysics && B->bPedPhysics){\n\t\t// negative if A is moving towards B\n\t\tspeedA = DotProduct(A->m_vecMoveSpeed, colpoint.normal);\n\t\t// positive if B is moving towards A\n\t\tfloat speedB = DotProduct(B->m_vecMoveSpeed, colpoint.normal);\n\n\t\tbool affectB = false;\n\t\tfloat mA = A->m_fMass;;\n\t\tfloat mB = B->m_fMass;;\n\t\tfloat speedSum;\n\t\tif(((CPed*)A)->GetPedState() == PED_FOLLOW_PATH){\n\t\t\taffectB = true;\t\n\t\t\tspeedSum = (2.0f*mA*speedA + mB*speedB)/(2.0f*mA + mB);\n\t\t}else{\n\t\t\tspeedSum = Max(speedB, 0.0f);\n\t\t}\n\n\t\tif(speedA < speedSum){\n\t\t\tif(A->bHasHitWall)\n\t\t\t\teA = speedSum;\n\t\t\telse\n\t\t\t\teA = speedSum - (speedA - speedSum) * (A->m_fElasticity+B->m_fElasticity)/2.0f;\n\t\t\timpulseA = (eA-speedA) * mA;\n\t\t\tif(!A->bInfiniteMass)\n\t\t\t\tA->ApplyMoveForce(colpoint.normal*impulseA);\n\t\t\tif(affectB && speedB < speedSum){\n\t\t\t\tif(B->bHasHitWall)\n\t\t\t\t\teB = speedSum;\n\t\t\t\telse\n\t\t\t\t\teB = speedSum - (speedB - speedSum) * (A->m_fElasticity+B->m_fElasticity)/2.0f;\n\t\t\t\timpulseB = -(eB-speedB) * mB;\n\t\t\t\tif(!B->bInfiniteMass)\n\t\t\t\t\tB->ApplyMoveForce(colpoint.normal*-impulseB);\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\t}else if(A->bPedPhysics){\n\t\tCVector pointposB = colpoint.point - B->GetPosition();\n\t\tspeedA = DotProduct(A->m_vecMoveSpeed, colpoint.normal);\n\t\tspeedB = DotProduct(B->GetSpeed(pointposB), colpoint.normal);\n\n\t\tfloat mA = A->m_fMass*massFactorA;\n\t\tfloat mB = B->GetMassTweak(pointposB, colpoint.normal, massFactorB);\n\t\tfloat speedSum;\n\t\tif(foo)\n\t\t\tspeedSum = speedB;\n\t\telse\n\t\t\tspeedSum = (mB*speedB + mA*speedA)/(mA + mB);\n\t\tif(speedA < speedSum){\n\t\t\tif(A->bHasHitWall)\n\t\t\t\teA = speedSum;\n\t\t\telse\n\t\t\t\teA = speedSum - (speedA - speedSum) * (A->m_fElasticity+B->m_fElasticity)/2.0f;\n\t\t\tif(B->bHasHitWall)\n\t\t\t\teB = speedSum;\n\t\t\telse\n\t\t\t\teB = speedSum - (speedB - speedSum) * (A->m_fElasticity+B->m_fElasticity)/2.0f;\n\t\t\timpulseA = (eA - speedA) * mA;\n\t\t\timpulseB = -(eB - speedB) * mB;\n\t\t\tCVector fA = colpoint.normal*(impulseA/massFactorA);\n\t\t\tCVector fB = colpoint.normal*(-impulseB/massFactorB);\n\t\t\tif(!A->bInfiniteMass){\n\t\t\t\tif(fA.z < 0.0f) fA.z = 0.0f;\n\t\t\t\tif(ispedcontactB){\n\t\t\t\t\tfA.x *= 2.0f;\n\t\t\t\t\tfA.y *= 2.0f;\n\t\t\t\t}\n\t\t\t\tA->ApplyMoveForce(fA);\n\t\t\t}\n\t\t\tif(!B->bInfiniteMass && !ispedcontactB){\n\t\t\t\tB->ApplyMoveForce(fB);\n\t\t\t\tB->ApplyTurnForce(fB, pointposB);\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\t}else if(B->bPedPhysics){\n\t\tCVector pointposA = colpoint.point - A->GetPosition();\n\t\tspeedA = DotProduct(A->GetSpeed(pointposA), colpoint.normal);\n\t\tspeedB = DotProduct(B->m_vecMoveSpeed, colpoint.normal);\n\n\t\tfloat mA = A->GetMassTweak(pointposA, colpoint.normal, massFactorA);\n\t\tfloat mB = B->m_fMass*massFactorB;\n\t\tfloat speedSum = (mB*speedB + mA*speedA)/(mA + mB);\n\t\tif(speedA < speedSum){\n\t\t\tif(A->bHasHitWall)\n\t\t\t\teA = speedSum;\n\t\t\telse\n\t\t\t\teA = speedSum - (speedA - speedSum) * (A->m_fElasticity+B->m_fElasticity)/2.0f;\n\t\t\tif(B->bHasHitWall)\n\t\t\t\teB = speedSum;\n\t\t\telse\n\t\t\t\teB = speedSum - (speedB - speedSum) * (A->m_fElasticity+B->m_fElasticity)/2.0f;\n\t\t\timpulseA = (eA - speedA) * mA;\n\t\t\timpulseB = -(eB - speedB) * mB;\n\t\t\tCVector fA = colpoint.normal*(impulseA/massFactorA);\n\t\t\tCVector fB = colpoint.normal*(-impulseB/massFactorB);\n\t\t\tif(!A->bInfiniteMass && !ispedcontactA){\n\t\t\t\tif(fA.z < 0.0f) fA.z = 0.0f;\n\t\t\t\tA->ApplyMoveForce(fA);\n\t\t\t\tA->ApplyTurnForce(fA, pointposA);\n\t\t\t}\n\t\t\tif(!B->bInfiniteMass){\n\t\t\t\tif(fB.z < 0.0f){\n\t\t\t\t\tfB.z = 0.0f;\n\t\t\t\t\tif(Abs(speedA) < 0.01f)\n\t\t\t\t\t\tfB *= 0.5f;\n\t\t\t\t}\n\t\t\t\tif(ispedcontactA){\n\t\t\t\t\tfB.x *= 2.0f;\n\t\t\t\t\tfB.y *= 2.0f;\n\t\t\t\t}\n\t\t\t\tB->ApplyMoveForce(fB);\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\t}else{\n\t\tCVector pointposA = colpoint.point - A->GetPosition();\n\t\tCVector pointposB = colpoint.point - B->GetPosition();\n\t\tspeedA = DotProduct(A->GetSpeed(pointposA), colpoint.normal);\n\t\tspeedB = DotProduct(B->GetSpeed(pointposB), colpoint.normal);\n\t\tfloat mA = A->GetMassTweak(pointposA, colpoint.normal, massFactorA);\n\t\tfloat mB = B->GetMassTweak(pointposB, colpoint.normal, massFactorB);\n\t\tfloat speedSum = (mB*speedB + mA*speedA)/(mA + mB);\n\t\tif(speedA < speedSum){\n\t\t\tif(A->bHasHitWall)\n\t\t\t\teA = speedSum;\n\t\t\telse\n\t\t\t\teA = speedSum - (speedA - speedSum) * (A->m_fElasticity+B->m_fElasticity)/2.0f;\n\t\t\tif(B->bHasHitWall)\n\t\t\t\teB = speedSum;\n\t\t\telse\n\t\t\t\teB = speedSum - (speedB - speedSum) * (A->m_fElasticity+B->m_fElasticity)/2.0f;\n\t\t\timpulseA = (eA - speedA) * mA;\n\t\t\timpulseB = -(eB - speedB) * mB;\n\t\t\tCVector fA = colpoint.normal*(impulseA/massFactorA);\n\t\t\tCVector fB = colpoint.normal*(-impulseB/massFactorB);\n\t\t\tif(A->IsVehicle() && !A->bHasHitWall){\n\t\t\t\tfA.x *= 1.4f;\n\t\t\t\tfA.y *= 1.4f;\n\t\t\t\tif(colpoint.normal.z < 0.7f)\n\t\t\t\t\tfA.z *= 0.3f;\n\t\t\t\tif(A->GetStatus() == STATUS_PLAYER)\n\t\t\t\t\tpointposA *= 0.8f;\n\t\t\t\tif(CWorld::bNoMoreCollisionTorque){\n\t\t\t\t\tA->ApplyFrictionMoveForce(fA*-0.3f);\n\t\t\t\t\tA->ApplyFrictionTurnForce(fA*-0.3f, pointposA);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif(B->IsVehicle() && !B->bHasHitWall){\n\t\t\t\tfB.x *= 1.4f;\n\t\t\t\tfB.y *= 1.4f;\n\t\t\t\tif(-colpoint.normal.z < 0.7f)\n\t\t\t\t\tfB.z *= 0.3f;\n\t\t\t\tif(B->GetStatus() == STATUS_PLAYER)\n\t\t\t\t\tpointposB *= 0.8f;\n\t\t\t\tif(CWorld::bNoMoreCollisionTorque){\n#ifdef FIX_BUGS\n\t\t\t\t\tB->ApplyFrictionMoveForce(fB*-0.3f);\n\t\t\t\t\tB->ApplyFrictionTurnForce(fB*-0.3f, pointposB);\n#else\n\t\t\t\t\tA->ApplyFrictionMoveForce(fB*-0.3f);\n\t\t\t\t\tA->ApplyFrictionTurnForce(fB*-0.3f, pointposB);\n#endif\n\t\t\t\t}\n\t\t\t}\n\t\t\tif(!A->bInfiniteMass){\n\t\t\t\tA->ApplyMoveForce(fA);\n\t\t\t\tA->ApplyTurnForce(fA, pointposA);\n\t\t\t}\n\t\t\tif(!B->bInfiniteMass){\n\t\t\t\tif(B->bIsInSafePosition)\n\t\t\t\t\tB->UnsetIsInSafePosition();\n\t\t\t\tB->ApplyMoveForce(fB);\n\t\t\t\tB->ApplyTurnForce(fB, pointposB);\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n\nbool\nCPhysical::ApplyCollision(CColPoint &colpoint, float &impulse)\n{\n\tfloat speed;\n\tif(bPedPhysics){\n\t\tspeed = DotProduct(m_vecMoveSpeed, colpoint.normal);\n\t\tif(speed < 0.0f){\n\t\t\timpulse = -speed * m_fMass;\n\t\t\tApplyMoveForce(colpoint.normal*impulse);\n\t\t\treturn true;\n\t\t}\n\t}else{\n\t\tCVector pointpos = colpoint.point - GetPosition();\n\t\tspeed = DotProduct(GetSpeed(pointpos), colpoint.normal);\n\n\t\tif(speed < 0.0f){\n\t\t\tfloat mass = GetMass(pointpos, colpoint.normal);\n\t\t\timpulse = -(m_fElasticity + 1.0f) * speed * mass;\n\t\t\tCVector f = colpoint.normal*impulse;\n\t\t\tif(IsVehicle()){\n\t\t\t\tf.x *= 1.4f;\n\t\t\t\tf.y *= 1.4f;\n\t\t\t\tif(colpoint.normal.z < 0.7f)\n\t\t\t\t\tf.z *= 0.3f;\n\t\t\t}\n\t\t\tif(!bInfiniteMass){\n\t\t\t\tApplyMoveForce(f);\n\t\t\t\tif(!IsVehicle() || !CWorld::bNoMoreCollisionTorque)\n\t\t\t\t\tApplyTurnForce(f, pointpos);\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\t}\n\n\treturn false;\n}\n\nbool\nCPhysical::ApplyCollisionAlt(CEntity *B, CColPoint &colpoint, float &impulse, CVector &moveSpeed, CVector &turnSpeed)\n{\n\tfloat normalSpeed;\n\tCVector speed;\n\tCVector vImpulse;\n\n\tif(GetModelIndex() == MI_BEACHBALL && B != (CEntity*)FindPlayerPed())\n\t\t((CObject*)this)->m_nBeachballBounces = 0;\n\n\tif(bPedPhysics){\n\t\tnormalSpeed = DotProduct(m_vecMoveSpeed, colpoint.normal);\n\t\tif(normalSpeed < 0.0f){\n\t\t\timpulse = -normalSpeed * m_fMass;\n\t\t\tApplyMoveForce(colpoint.normal * impulse);\n\t\t\treturn true;\n\t\t}\n\t}else{\n\t\tCVector pointpos = colpoint.point - GetPosition();\n\t\tspeed = GetSpeed(pointpos);\n\t\tnormalSpeed = DotProduct(speed, colpoint.normal);\n\t\tif(normalSpeed < 0.0f){\n\t\t\tint16 elasticityType = 0;\n\t\t\tfloat mass = GetMass(pointpos, colpoint.normal);\n\t\t\tfloat minspeed = GRAVITY * CTimer::GetTimeStep();\n\n\t\t\tif(IsObject())\n\t\t\t\telasticityType = 1;\n\t\t\telse if(IsVehicle() && !bIsInWater){\n\t\t\t\tif(((CVehicle*)this)->IsBike() && (GetStatus() == STATUS_ABANDONED || GetStatus() == STATUS_WRECKED)){\n\t\t\t\t\tminspeed *= 1.3f;\n\t\t\t\t\telasticityType = 3;\n\t\t\t\t}else if(((CVehicle*)this)->IsBoat()){\n\t\t\t\t\tminspeed *= 1.2f;\n\t\t\t\t\telasticityType = 4;\n\t\t\t\t}else if(GetUp().z < -0.3f){\n\t\t\t\t\tminspeed *= 1.1f;\n\t\t\t\t\telasticityType = 2;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif(elasticityType == 1 && !bHasContacted &&\n\t\t\t   Abs(m_vecMoveSpeed.x) < minspeed &&\n\t\t\t   Abs(m_vecMoveSpeed.y) < minspeed &&\n\t\t\t   Abs(m_vecMoveSpeed.z) < minspeed*2.0f)\n\t\t\t\timpulse = -0.98f * normalSpeed * mass;\n\t\t\tif(elasticityType == 3 &&\n\t\t\t   Abs(m_vecMoveSpeed.x) < minspeed &&\n\t\t\t   Abs(m_vecMoveSpeed.y) < minspeed &&\n\t\t\t   Abs(m_vecMoveSpeed.z) < minspeed*2.0f)\n\t\t\t\timpulse = -0.8f * normalSpeed * mass;\n\t\t\telse if(elasticityType == 2 &&\n\t\t\t   Abs(m_vecMoveSpeed.x) < minspeed &&\n\t\t\t   Abs(m_vecMoveSpeed.y) < minspeed &&\n\t\t\t   Abs(m_vecMoveSpeed.z) < minspeed*2.0f)\n\t\t\t\timpulse = -0.92f * normalSpeed * mass;\n\t\t\telse if(elasticityType == 4 &&\n\t\t\t   Abs(m_vecMoveSpeed.x) < minspeed &&\n\t\t\t   Abs(m_vecMoveSpeed.y) < minspeed &&\n\t\t\t   Abs(m_vecMoveSpeed.z) < minspeed*2.0f)\n\t\t\t\timpulse = -0.8f * normalSpeed * mass;\n\t\t\telse if(IsVehicle() && ((CVehicle*)this)->IsBoat() &&\n\t\t\t   colpoint.surfaceB == SURFACE_WOOD_SOLID && colpoint.normal.z < 0.5f)\n\t\t\t\timpulse = -(2.0f * m_fElasticity + 1.0f) * normalSpeed * mass;\n\t\t\telse\n\t\t\t\timpulse = -(m_fElasticity + 1.0f) * normalSpeed * mass;\n\n\t\t\t// ApplyMoveForce\n\t\t\tvImpulse = colpoint.normal*impulse;\n\t\t\tif(IsVehicle()){\n\t\t\t\tif(!bHasHitWall ||\n\t\t\t\t   !(m_vecMoveSpeed.MagnitudeSqr() > 0.1 || !(B->IsBuilding() || ((CPhysical*)B)->bInfiniteMass)))\n\t\t\t\t\tmoveSpeed += vImpulse * 1.2f * (1.0f/m_fMass);\n\t\t\t\telse\n\t\t\t\t\tmoveSpeed += vImpulse * (1.0f/m_fMass);\n\t\t\t\tvImpulse *= 0.8f;\n\t\t\t}else\n\t\t\t\tmoveSpeed += vImpulse * (1.0f/m_fMass);\n\n\t\t\t// ApplyTurnForce\n\t\t\tCVector com = Multiply3x3(m_matrix, m_vecCentreOfMass);\n\t\t\tCVector turnimpulse = CrossProduct(pointpos-com, vImpulse);\n\t\t\tturnSpeed += turnimpulse*(1.0f/m_fTurnMass);\n\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n\n// --MIAMI: Proof-read once\nbool\nCPhysical::ApplyFriction(CPhysical *B, float adhesiveLimit, CColPoint &colpoint)\n{\n\tCVector speedA, speedB;\n\tfloat normalSpeedA, normalSpeedB;\n\tCVector vOtherSpeedA, vOtherSpeedB;\n\tfloat fOtherSpeedA, fOtherSpeedB;\n\tfloat speedSum;\n\tCVector frictionDir;\n\tfloat impulseA, impulseB;\n\tfloat impulseLimit;\n\tCPhysical *A = this;\n\n\tif(A->bPedPhysics && B->bPedPhysics){\n\t\tnormalSpeedA = DotProduct(A->m_vecMoveSpeed, colpoint.normal);\n\t\tnormalSpeedB = DotProduct(B->m_vecMoveSpeed, colpoint.normal);\n\t\tvOtherSpeedA = A->m_vecMoveSpeed - colpoint.normal*normalSpeedA;\n\t\tvOtherSpeedB = B->m_vecMoveSpeed - colpoint.normal*normalSpeedB;\n\n\t\tfOtherSpeedA = vOtherSpeedA.Magnitude();\n\t\tfOtherSpeedB = vOtherSpeedB.Magnitude();\n\n#ifdef FIX_BUGS // division by 0\n\t\tfrictionDir = vOtherSpeedA;\n\t\tfrictionDir.Normalise();\n#else\n\t\tfrictionDir = vOtherSpeedA * (1.0f/fOtherSpeedA);\n#endif\n\n\t\tspeedSum = (B->m_fMass*fOtherSpeedB + A->m_fMass*fOtherSpeedA)/(B->m_fMass + A->m_fMass);\n\t\tif(fOtherSpeedA > speedSum){\n\t\t\timpulseA = (speedSum - fOtherSpeedA) * A->m_fMass;\n\t\t\timpulseB = (speedSum - fOtherSpeedB) * B->m_fMass;\n\t\t\timpulseLimit = adhesiveLimit*CTimer::GetTimeStep();\n\t\t\tif(impulseA < -impulseLimit) impulseA = -impulseLimit;\n#ifdef FIX_BUGS\n\t\t\tif(impulseB > impulseLimit) impulseB = impulseLimit;\n#else\n\t\t\tif(impulseA < -impulseLimit) impulseA = -impulseLimit; // duplicate\n#endif\n\t\t\tA->ApplyFrictionMoveForce(frictionDir*impulseA);\n\t\t\tB->ApplyFrictionMoveForce(frictionDir*impulseB);\n\t\t\treturn true;\n\t\t}\n\t}else if(A->bPedPhysics){\n\t\tif(B->IsVehicle())\n\t\t\treturn false;\n\t\tCVector pointposB = colpoint.point - B->GetPosition();\n\t\tspeedB = B->GetSpeed(pointposB);\n\n\t\tnormalSpeedA = DotProduct(A->m_vecMoveSpeed, colpoint.normal);\n\t\tnormalSpeedB = DotProduct(speedB, colpoint.normal);\n\t\tvOtherSpeedA = A->m_vecMoveSpeed - colpoint.normal*normalSpeedA;\n\t\tvOtherSpeedB = speedB - colpoint.normal*normalSpeedB;\n\n\t\tfOtherSpeedA = vOtherSpeedA.Magnitude();\n\t\tfOtherSpeedB = vOtherSpeedB.Magnitude();\n\n#ifdef FIX_BUGS // division by 0\n\t\tfrictionDir = vOtherSpeedA;\n\t\tfrictionDir.Normalise();\n#else\n\t\tfrictionDir = vOtherSpeedA * (1.0f/fOtherSpeedA);\n#endif\n\t\tfloat massB = B->GetMass(pointposB, frictionDir);\n\t\tspeedSum = (massB*fOtherSpeedB + A->m_fMass*fOtherSpeedA)/(massB + A->m_fMass);\n\t\tif(fOtherSpeedA > speedSum){\n\t\t\timpulseA = (speedSum - fOtherSpeedA) * A->m_fMass;\n\t\t\timpulseB = (speedSum - fOtherSpeedB) * massB;\n\t\t\timpulseLimit = adhesiveLimit*CTimer::GetTimeStep();\n\t\t\tif(impulseA < -impulseLimit) impulseA = -impulseLimit;\n\t\t\tif(impulseB > impulseLimit) impulseB = impulseLimit;\n\t\t\tA->ApplyFrictionMoveForce(frictionDir*impulseA);\n\t\t\tB->ApplyFrictionMoveForce(frictionDir*impulseB);\n\t\t\tB->ApplyFrictionTurnForce(frictionDir*impulseB, pointposB);\n\t\t\treturn true;\n\t\t}\n\t}else if(B->bPedPhysics){\n\t\tif(A->IsVehicle())\n\t\t\treturn false;\n\t\tCVector pointposA = colpoint.point - A->GetPosition();\n\t\tspeedA = A->GetSpeed(pointposA);\n\n\t\tnormalSpeedA = DotProduct(speedA, colpoint.normal);\n\t\tnormalSpeedB = DotProduct(B->m_vecMoveSpeed, colpoint.normal);\n\t\tvOtherSpeedA = speedA - colpoint.normal*normalSpeedA;\n\t\tvOtherSpeedB = B->m_vecMoveSpeed - colpoint.normal*normalSpeedB;\n\n\t\tfOtherSpeedA = vOtherSpeedA.Magnitude();\n\t\tfOtherSpeedB = vOtherSpeedB.Magnitude();\n\n#ifdef FIX_BUGS // division by 0\n\t\tfrictionDir = vOtherSpeedA;\n\t\tfrictionDir.Normalise();\n#else\n\t\tfrictionDir = vOtherSpeedA * (1.0f/fOtherSpeedA);\n#endif\n\t\tfloat massA = A->GetMass(pointposA, frictionDir);\n\t\tspeedSum = (B->m_fMass*fOtherSpeedB + massA*fOtherSpeedA)/(B->m_fMass + massA);\n\t\tif(fOtherSpeedA > speedSum){\n\t\t\timpulseA = (speedSum - fOtherSpeedA) * massA;\n\t\t\timpulseB = (speedSum - fOtherSpeedB) * B->m_fMass;\n\t\t\timpulseLimit = adhesiveLimit*CTimer::GetTimeStep();\n\t\t\tif(impulseA < -impulseLimit) impulseA = -impulseLimit;\n\t\t\tif(impulseB > impulseLimit) impulseB = impulseLimit;\n\t\t\tA->ApplyFrictionMoveForce(frictionDir*impulseA);\n\t\t\tA->ApplyFrictionTurnForce(frictionDir*impulseA, pointposA);\n\t\t\tB->ApplyFrictionMoveForce(frictionDir*impulseB);\n\t\t\treturn true;\n\t\t}\n\t}else{\n\t\tCVector pointposA = colpoint.point - A->GetPosition();\n\t\tCVector pointposB = colpoint.point - B->GetPosition();\n\t\tspeedA = A->GetSpeed(pointposA);\n\t\tspeedB = B->GetSpeed(pointposB);\n\n\t\tnormalSpeedA = DotProduct(speedA, colpoint.normal);\n\t\tnormalSpeedB = DotProduct(speedB, colpoint.normal);\n\t\tvOtherSpeedA = speedA - colpoint.normal*normalSpeedA;\n\t\tvOtherSpeedB = speedB - colpoint.normal*normalSpeedB;\n\n\t\tfOtherSpeedA = vOtherSpeedA.Magnitude();\n\t\tfOtherSpeedB = vOtherSpeedB.Magnitude();\n\n#ifdef FIX_BUGS // division by 0\n\t\tfrictionDir = vOtherSpeedA;\n\t\tfrictionDir.Normalise();\n#else\n\t\tfrictionDir = vOtherSpeedA * (1.0f/fOtherSpeedA);\n#endif\n\t\tfloat massA = A->GetMass(pointposA, frictionDir);\n\t\tfloat massB = B->GetMass(pointposB, frictionDir);\n\t\tspeedSum = (massB*fOtherSpeedB + massA*fOtherSpeedA)/(massB + massA);\n\t\tif(fOtherSpeedA > speedSum){\n\t\t\timpulseA = (speedSum - fOtherSpeedA) * massA;\n\t\t\timpulseB = (speedSum - fOtherSpeedB) * massB;\n\t\t\timpulseLimit = adhesiveLimit*CTimer::GetTimeStep();\n\t\t\tif(impulseA < -impulseLimit) impulseA = -impulseLimit;\n\t\t\tif(impulseB > impulseLimit) impulseB = impulseLimit;\n\t\t\tA->ApplyFrictionMoveForce(frictionDir*impulseA);\n\t\t\tA->ApplyFrictionTurnForce(frictionDir*impulseA, pointposA);\n\t\t\tB->ApplyFrictionMoveForce(frictionDir*impulseB);\n\t\t\tB->ApplyFrictionTurnForce(frictionDir*impulseB, pointposB);\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n\n// --MIAMI: Proof-read once\nbool\nCPhysical::ApplyFriction(float adhesiveLimit, CColPoint &colpoint)\n{\n\tCVector speed;\n\tfloat normalSpeed;\n\tCVector vOtherSpeed;\n\tfloat fOtherSpeed;\n\tCVector frictionDir;\n\tfloat fImpulse;\n\tfloat impulseLimit;\n\n\tif(bPedPhysics){\n\t\tnormalSpeed = DotProduct(m_vecMoveSpeed, colpoint.normal);\n\t\tvOtherSpeed = m_vecMoveSpeed - colpoint.normal*normalSpeed;\n\n\t\tfOtherSpeed = vOtherSpeed.Magnitude();\n\t\tif(fOtherSpeed > 0.0f){\n#ifdef FIX_BUGS // division by 0\n\t\t\tfrictionDir = vOtherSpeed;\n\t\t\tfrictionDir.Normalise();\n#else\n\t\t\tfrictionDir = vOtherSpeed * (1.0f/fOtherSpeed);\n#endif\n\t\t\t// not really impulse but speed\n\t\t\t// maybe use ApplyFrictionMoveForce instead?\n\t\t\tfImpulse = -fOtherSpeed;\n\t\t\timpulseLimit = adhesiveLimit*CTimer::GetTimeStep() / m_fMass;\n\t\t\tif(fImpulse < -impulseLimit) fImpulse = -impulseLimit;\n\t\t\tCVector vImpulse = frictionDir*fImpulse;\n\t\t\tm_vecMoveFriction += CVector(vImpulse.x, vImpulse.y, 0.0f);\n\t\t\treturn true;\n\t\t}\n\t}else{\n\t\tCVector pointpos = colpoint.point - GetPosition();\n\t\tspeed = GetSpeed(pointpos);\n\t\tnormalSpeed = DotProduct(speed, colpoint.normal);\n\t\tvOtherSpeed = speed - colpoint.normal*normalSpeed;\n\n\t\tfOtherSpeed = vOtherSpeed.Magnitude();\n\t\tif(fOtherSpeed > 0.0f){\n#ifdef FIX_BUGS // division by 0\n\t\t\tfrictionDir = vOtherSpeed;\n\t\t\tfrictionDir.Normalise();\n#else\n\t\t\tfrictionDir = vOtherSpeed * (1.0f/fOtherSpeed);\n#endif\n\t\t\tfImpulse = -fOtherSpeed * m_fMass;\n\t\t\timpulseLimit = adhesiveLimit*CTimer::GetTimeStep() * 1.5;\n\t\t\tif(fImpulse < -impulseLimit) fImpulse = -impulseLimit;\n\t\t\tApplyFrictionMoveForce(frictionDir*fImpulse);\n\t\t\tApplyFrictionTurnForce(frictionDir*fImpulse, pointpos);\n\n\t\t\tif(fOtherSpeed > 0.1f &&\n\t\t\t   colpoint.surfaceB != SURFACE_GRASS && colpoint.surfaceB != SURFACE_MUD_DRY &&\n\t\t\t   CSurfaceTable::GetAdhesionGroup(colpoint.surfaceA) == ADHESIVE_HARD){\n\t\t\t\tCVector v = frictionDir * fOtherSpeed * 0.25f;\n\t\t\t\tfor(int i = 0; i < 4; i++)\n\t\t\t\t\tCParticle::AddParticle(PARTICLE_SPARK_SMALL, colpoint.point, v);\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n\n// --MIAMI: Proof-read once\nbool\nCPhysical::ProcessShiftSectorList(CPtrList *lists)\n{\n\tint i, j;\n\tCPtrList *list;\n\tCPtrNode *node;\n\tCPhysical *A, *B;\n\tCObject *Bobj;\n\tbool canshift;\n\tCVector center;\n\tfloat radius;\n\n\tint numCollisions;\n\tint mostColliding;\n\tCColPoint colpoints[MAX_COLLISION_POINTS];\n\tCVector shift = CVector(0.0f, 0.0f, 0.0f);\n\tbool doShift = false;\n\tCEntity *boat = nil;\n\n\tbool skipShift;\n\n\tA = this;\n\n\tA->GetBoundCentre(center);\n\tradius = A->GetBoundRadius();\n\tfor(i = 0; i <= ENTITYLIST_PEDS_OVERLAP; i++){\n\t\tlist = &lists[i];\n\t\tfor(node = list->first; node; node = node->next){\n\t\t\tB = (CPhysical*)node->item;\n\t\t\tBobj = (CObject*)B;\n\t\t\tskipShift = false;\n\n\t\t\tif(B->IsBuilding() ||\n\t\t\t   B->IsObject() && B->bInfiniteMass)\n\t\t\t\tcanshift = true;\n\t\t\telse\n\t\t\t\tcanshift = A->IsPed() &&\n\t\t\t\t\tB->IsObject() && B->GetIsStatic() && !Bobj->bHasBeenDamaged;\n\t\t\tif(B == A ||\n\t\t\t   B->m_scanCode == CWorld::GetCurrentScanCode() ||\n\t\t\t   !B->bUsesCollision ||\n\t\t\t   (A->bHasHitWall && !canshift) ||\n\t\t\t   !B->GetIsTouching(center, radius))\n\t\t\t\tcontinue;\n\n\t\t\t// This could perhaps be done a bit nicer\n\n\t\t\tif(B->IsBuilding())\n\t\t\t\tskipShift = false;\n\t\t\telse if(IsLightWithoutShift(A->GetModelIndex()) &&\n\t\t\t  (B->IsVehicle() || B->IsPed()) &&\n\t\t\t  A->GetUp().z < 0.66f)\n\t\t\t\tskipShift = true;\n\t\t\telse if((A->IsVehicle() || A->IsPed()) &&\n\t\t\t  B->GetUp().z < 0.66f &&\n\t\t\t  IsLightWithoutShift(B->GetModelIndex()))\n\t\t\t\tskipShift = true;\n\t\t\telse if(A->IsObject() && B->IsVehicle()){\n\t\t\t\tCObject *Aobj = (CObject*)A;\n\t\t\t\tif(Aobj->ObjectCreatedBy != TEMP_OBJECT &&\n\t\t\t\t   !Aobj->bHasBeenDamaged &&\n\t\t\t\t   Aobj->GetIsStatic()){\n\t\t\t\t\tif(Aobj->m_pCollidingEntity == B)\n\t\t\t\t\t\tAobj->m_pCollidingEntity = nil;\n\t\t\t\t}else if(Aobj->m_pCollidingEntity != B){\n\t\t\t\t\tCMatrix inv;\n\t\t\t\t\tCVector size = CModelInfo::GetModelInfo(A->GetModelIndex())->GetColModel()->boundingBox.GetSize();\n\t\t\t\t\tsize = A->GetMatrix() * size;\n\t\t\t\t\tif(size.z < B->GetPosition().z ||\n\t\t\t\t\t   (Invert(B->GetMatrix(), inv) * size).z < 0.0f){\n\t\t\t\t\t\tskipShift = true;\n\t\t\t\t\t\tAobj->m_pCollidingEntity = B;\n\t\t\t\t\t}\n\t\t\t\t} else\n\t\t\t\t\tskipShift = true;\n\t\t\t}else if(B->IsObject() && A->IsVehicle()){\n\t\t\t\tCObject *Bobj = (CObject*)B;\n\t\t\t\tif(Bobj->ObjectCreatedBy != TEMP_OBJECT &&\n\t\t\t\t   !Bobj->bHasBeenDamaged &&\n\t\t\t\t   Bobj->GetIsStatic()){\n\t\t\t\t\tif(Bobj->m_pCollidingEntity == A)\n\t\t\t\t\t\tBobj->m_pCollidingEntity = nil;\n\t\t\t\t}else if(Bobj->m_pCollidingEntity != A){\n\t\t\t\t\tCMatrix inv;\n\t\t\t\t\tCVector size = CModelInfo::GetModelInfo(B->GetModelIndex())->GetColModel()->boundingBox.GetSize();\n\t\t\t\t\tsize = B->GetMatrix() * size;\n\t\t\t\t\tif(size.z < A->GetPosition().z ||\n\t\t\t\t\t   (Invert(A->GetMatrix(), inv) * size).z < 0.0f)\n\t\t\t\t\t\tskipShift = true;\n\t\t\t\t} else\n\t\t\t\t\tskipShift = true;\n\t\t\t}else if(IsBodyPart(A->GetModelIndex()) && B->IsPed())\n\t\t\t\tskipShift = true;\n\t\t\telse if(A->IsPed() && IsBodyPart(B->GetModelIndex()))\n\t\t\t\tskipShift = true;\n\t\t\telse if(A->IsPed() && ((CPed*)A)->m_pCollidingEntity == B ||\n\t\t\t  B->IsPed() && ((CPed*)B)->m_pCollidingEntity == A ||\n\t\t\t  A->GetModelIndex() == MI_RCBANDIT && B->IsVehicle() ||\n\t\t\t  B->GetModelIndex() == MI_RCBANDIT && (A->IsPed() || A->IsVehicle()))\n\t\t\t\tskipShift = true;\n\n\t\t\tif(skipShift)\n\t\t\t\tcontinue;\n\n\t\t\tB->m_scanCode = CWorld::GetCurrentScanCode();\n\t\t\tnumCollisions = A->ProcessEntityCollision(B, colpoints);\n\t\t\tif(numCollisions <= 0)\n\t\t\t\tcontinue;\n\n\t\t\tmostColliding = 0;\n\t\t\tfor(j = 1; j < numCollisions; j++)\n\t\t\t\tif (colpoints[j].GetDepth() > colpoints[mostColliding].GetDepth())\n\t\t\t\t\tmostColliding = j;\n\n\t\t\tif(CWorld::bSecondShift)\n\t\t\t\tfor(j = 0; j < numCollisions; j++)\n\t\t\t\t\tshift += colpoints[j].GetNormal() * colpoints[j].GetDepth() * 1.5f / numCollisions;\n\t\t\telse\n\t\t\t\tfor(j = 0; j < numCollisions; j++)\n\t\t\t\t\tshift += colpoints[j].GetNormal() * colpoints[j].GetDepth() * 1.2f / numCollisions;\n\n\t\t\tif(A->IsVehicle() && B->IsVehicle()){\n\t\t\t\tCVector dir = A->GetPosition() - B->GetPosition();\n\t\t\t\tdir.Normalise();\n\t\t\t\tif(dir.z < 0.0f && dir.z < A->GetForward().z && dir.z < A->GetRight().z)\n\t\t\t\t\tdir.z = Min(0.0f, Min(A->GetForward().z, A->GetRight().z));\n\t\t\t\tshift += dir * colpoints[mostColliding].GetDepth() * 0.5f;\n\t\t\t}else if(A->IsPed() && B->IsVehicle() && ((CVehicle*)B)->IsBoat()){\n\t\t\t\tCVector dir = colpoints[mostColliding].GetNormal();\n\t\t\t\tfloat f = Min(Abs(dir.z), 0.9f);\n\t\t\t\tdir.z = 0.0f;\n\t\t\t\tdir.Normalise();\n\t\t\t\tshift += dir * colpoints[mostColliding].GetDepth() / (1.0f - f);\n\t\t\t\tboat = B;\n\t\t\t}else if(B->IsPed() && A->IsVehicle() && ((CVehicle*)A)->IsBoat()){\n\t\t\t\tCVector dir = colpoints[mostColliding].GetNormal() * -1.0f;\n\t\t\t\tfloat f = Min(Abs(dir.z), 0.9f);\n\t\t\t\tdir.z = 0.0f;\n\t\t\t\tdir.Normalise();\n\t\t\t\tB->GetMatrix().Translate(dir * colpoints[mostColliding].GetDepth() / (1.0f - f));\n\t\t\t\t// BUG? how can that ever happen? A is a Ped\n\t\t\t\tif(B->IsVehicle())\n\t\t\t\t\tB->ProcessEntityCollision(A, colpoints);\n\t\t\t}else{\n\t\t\t\tif(CWorld::bSecondShift)\n\t\t\t\t\tshift += colpoints[mostColliding].GetNormal() * colpoints[mostColliding].GetDepth() * 0.4f;\n\t\t\t\telse\n\t\t\t\t\tshift += colpoints[mostColliding].GetNormal() * colpoints[mostColliding].GetDepth() * 0.2f;\n\t\t\t}\n\n\t\t\tdoShift = true;\n\t\t}\n\t}\n\n\tif(!doShift)\n\t\treturn false;\n\tGetMatrix().Translate(shift);\n\tif(boat)\n\t\tProcessEntityCollision(boat, colpoints);\n\treturn true;\n}\n\n// --MIAMI: Proof-read once\nbool\nCPhysical::ProcessCollisionSectorList_SimpleCar(CPtrList *lists)\n{\n\tstatic CColPoint aColPoints[MAX_COLLISION_POINTS];\n\tfloat radius;\n\tCVector center;\n\tint listtype;\n\tCPhysical *A, *B;\n\tint numCollisions;\n\tint i;\n\tfloat impulseA = -1.0f;\n\tfloat impulseB = -1.0f;\n\n\tA = (CPhysical*)this;\n\n\tif(!A->bUsesCollision)\n\t\treturn false;\n\n\tradius = A->GetBoundRadius();\n\tA->GetBoundCentre(center);\n\n\tfor(listtype = 3; listtype >= 0; listtype--){\n\t\t// Go through vehicles and objects\n\t\tCPtrList *list;\n\t\tswitch(listtype){\n\t\tcase 0:\tlist = &lists[ENTITYLIST_VEHICLES]; break;\n\t\tcase 1:\tlist = &lists[ENTITYLIST_VEHICLES_OVERLAP]; break;\n\t\tcase 2:\tlist = &lists[ENTITYLIST_OBJECTS]; break;\n\t\tcase 3:\tlist = &lists[ENTITYLIST_OBJECTS_OVERLAP]; break;\n\t\t}\n\n\t\t// Find first collision in list\n\t\tCPtrNode *listnode;\n\t\tfor(listnode = list->first; listnode; listnode = listnode->next){\n\t\t\tB = (CPhysical*)listnode->item;\n\t\t\tif(B != A &&\n\t\t\t   !(B->IsObject() && ((CObject*)B)->bIsStreetLight && B->GetUp().z < 0.66f) &&\n\t\t\t   B->m_scanCode != CWorld::GetCurrentScanCode() &&\n\t\t\t   B->bUsesCollision &&\n\t\t\t   B->GetIsTouching(center, radius)){\n\t\t\t\tB->m_scanCode = CWorld::GetCurrentScanCode();\n\t\t\t\tnumCollisions = A->ProcessEntityCollision(B, aColPoints);\n\t\t\t\tif(numCollisions > 0)\n\t\t\t\t\tgoto collision;\n\t\t\t}\n\t\t}\n\t}\n\t// no collision\n\treturn false;\n\ncollision:\n\n\tif(A->bHasContacted && B->bHasContacted){\n\t\tfor(i = 0; i < numCollisions; i++){\n\t\t\tif(!A->ApplyCollision(B, aColPoints[i], impulseA, impulseB))\n\t\t\t\tcontinue;\n\n\t\t\tif(impulseA > A->m_fDamageImpulse)\n\t\t\t\tA->SetDamagedPieceRecord(aColPoints[i].pieceA, impulseA, B, aColPoints[i].normal);\n\n\t\t\tif(impulseB > B->m_fDamageImpulse)\n\t\t\t\tB->SetDamagedPieceRecord(aColPoints[i].pieceB, impulseB, A, aColPoints[i].normal);\n\n\t\t\tfloat turnSpeedDiff = (B->m_vecTurnSpeed - A->m_vecTurnSpeed).MagnitudeSqr();\n\t\t\tfloat moveSpeedDiff = (B->m_vecMoveSpeed - A->m_vecMoveSpeed).MagnitudeSqr();\n\n\t\t\tDMAudio.ReportCollision(A, B, aColPoints[i].surfaceA, aColPoints[i].surfaceB, impulseA, Max(turnSpeedDiff, moveSpeedDiff));\n\t\t}\n\t}else if(A->bHasContacted){\n\t\tCVector savedMoveFriction = A->m_vecMoveFriction;\n\t\tCVector savedTurnFriction = A->m_vecTurnFriction;\n\t\tA->m_vecMoveFriction = CVector(0.0f, 0.0f, 0.0f);\n\t\tA->m_vecTurnFriction = CVector(0.0f, 0.0f, 0.0f);\n\t\tA->bHasContacted = false;\n\n\t\tfor(i = 0; i < numCollisions; i++){\n\t\t\tif(!A->ApplyCollision(B, aColPoints[i], impulseA, impulseB))\n\t\t\t\tcontinue;\n\n\t\t\tif(impulseA > A->m_fDamageImpulse)\n\t\t\t\tA->SetDamagedPieceRecord(aColPoints[i].pieceA, impulseA, B, aColPoints[i].normal);\n\n\t\t\tif(impulseB > B->m_fDamageImpulse)\n\t\t\t\tB->SetDamagedPieceRecord(aColPoints[i].pieceB, impulseB, A, aColPoints[i].normal);\n\n\t\t\tfloat turnSpeedDiff = (B->m_vecTurnSpeed - A->m_vecTurnSpeed).MagnitudeSqr();\n\t\t\tfloat moveSpeedDiff = (B->m_vecMoveSpeed - A->m_vecMoveSpeed).MagnitudeSqr();\n\n\t\t\tDMAudio.ReportCollision(A, B, aColPoints[i].surfaceA, aColPoints[i].surfaceB, impulseA, Max(turnSpeedDiff, moveSpeedDiff));\n\n\t\t\tif(A->ApplyFriction(B, CSurfaceTable::GetAdhesiveLimit(aColPoints[i])/numCollisions, aColPoints[i])){\n\t\t\t\tA->bHasContacted = true;\n\t\t\t\tB->bHasContacted = true;\n\t\t\t}\n\t\t}\n\n\t\tif(!A->bHasContacted){\n\t\t\tA->bHasContacted = true;\n\t\t\tA->m_vecMoveFriction = savedMoveFriction;\n\t\t\tA->m_vecTurnFriction = savedTurnFriction;\n\t\t}\n\t}else if(B->bHasContacted){\n\t\tCVector savedMoveFriction = B->m_vecMoveFriction;\n\t\tCVector savedTurnFriction = B->m_vecTurnFriction;\n\t\tB->m_vecMoveFriction = CVector(0.0f, 0.0f, 0.0f);\n\t\tB->m_vecTurnFriction = CVector(0.0f, 0.0f, 0.0f);\n\t\tB->bHasContacted = false;\n\n\t\tfor(i = 0; i < numCollisions; i++){\n\t\t\tif(!A->ApplyCollision(B, aColPoints[i], impulseA, impulseB))\n\t\t\t\tcontinue;\n\n\t\t\tif(impulseA > A->m_fDamageImpulse)\n\t\t\t\tA->SetDamagedPieceRecord(aColPoints[i].pieceA, impulseA, B, aColPoints[i].normal);\n\n\t\t\tif(impulseB > B->m_fDamageImpulse)\n\t\t\t\tB->SetDamagedPieceRecord(aColPoints[i].pieceB, impulseB, A, aColPoints[i].normal);\n\n\t\t\tfloat turnSpeedDiff = (B->m_vecTurnSpeed - A->m_vecTurnSpeed).MagnitudeSqr();\n\t\t\tfloat moveSpeedDiff = (B->m_vecMoveSpeed - A->m_vecMoveSpeed).MagnitudeSqr();\n\n\t\t\tDMAudio.ReportCollision(A, B, aColPoints[i].surfaceA, aColPoints[i].surfaceB, impulseA, Max(turnSpeedDiff, moveSpeedDiff));\n\n\t\t\tif(A->ApplyFriction(B, CSurfaceTable::GetAdhesiveLimit(aColPoints[i])/numCollisions, aColPoints[i])){\n\t\t\t\tA->bHasContacted = true;\n\t\t\t\tB->bHasContacted = true;\n\t\t\t}\n\t\t}\n\n\t\tif(!B->bHasContacted){\n\t\t\tB->bHasContacted = true;\n\t\t\tB->m_vecMoveFriction = savedMoveFriction;\n\t\t\tB->m_vecTurnFriction = savedTurnFriction;\n\t\t}\n\t}else{\n\t\tfor(i = 0; i < numCollisions; i++){\n\t\t\tif(!A->ApplyCollision(B, aColPoints[i], impulseA, impulseB))\n\t\t\t\tcontinue;\n\n\t\t\tif(impulseA > A->m_fDamageImpulse)\n\t\t\t\tA->SetDamagedPieceRecord(aColPoints[i].pieceA, impulseA, B, aColPoints[i].normal);\n\n\t\t\tif(impulseB > B->m_fDamageImpulse)\n\t\t\t\tB->SetDamagedPieceRecord(aColPoints[i].pieceB, impulseB, A, aColPoints[i].normal);\n\n\t\t\tfloat turnSpeedDiff = (B->m_vecTurnSpeed - A->m_vecTurnSpeed).MagnitudeSqr();\n\t\t\tfloat moveSpeedDiff = (B->m_vecMoveSpeed - A->m_vecMoveSpeed).MagnitudeSqr();\n\n\t\t\tDMAudio.ReportCollision(A, B, aColPoints[i].surfaceA, aColPoints[i].surfaceB, impulseA, Max(turnSpeedDiff, moveSpeedDiff));\n\n\t\t\tif(A->ApplyFriction(B, CSurfaceTable::GetAdhesiveLimit(aColPoints[i])/numCollisions, aColPoints[i])){\n\t\t\t\tA->bHasContacted = true;\n\t\t\t\tB->bHasContacted = true;\n\t\t\t}\n\t\t}\n\t}\n\n\tif(B->GetStatus() == STATUS_SIMPLE){\n\t\tB->SetStatus(STATUS_PHYSICS);\n\t\tif(B->IsVehicle())\n\t\t\tCCarCtrl::SwitchVehicleToRealPhysics((CVehicle*)B);\n\t}\n\n\treturn true;\n}\n\n// --MIAMI: Proof-read once\nbool\nCPhysical::ProcessCollisionSectorList(CPtrList *lists)\n{\n\tstatic CColPoint aColPoints[MAX_COLLISION_POINTS];\n\tfloat radius;\n\tCVector center;\n\tCPtrList *list;\n\tCPhysical *A, *B;\n\tCObject *Aobj, *Bobj;\n\tCPed *Aped, *Bped;\n\tint numCollisions;\n\tint numResponses;\n\tint i, j;\n\tbool skipCollision, altcollision;\n\tbool ret = false;\n\tfloat impulseA = -1.0f;\n\tfloat impulseB = -1.0f;\n\n\tA = (CPhysical*)this;\n\tAobj = (CObject*)A;\n\tAped = (CPed*)A;\n\n\tradius = A->GetBoundRadius();\n\tA->GetBoundCentre(center);\n\n\tfor(j = 0; j <= ENTITYLIST_PEDS_OVERLAP; j++){\n\t\tlist = &lists[j];\n\n\t\tCPtrNode *listnode;\n\t\tfor(listnode = list->first; listnode; listnode = listnode->next){\n\t\t\tB = (CPhysical*)listnode->item;\n\t\t\tBobj = (CObject*)B;\n\t\t\tBped = (CPed*)B;\n\n\t\t\tbool isTouching = true;\n\t\t\tif(!B->bUsesCollision ||\n\t\t\t   B->m_scanCode == CWorld::GetCurrentScanCode() ||\n\t\t\t   B == A ||\t\t\t   \n\t\t\t   !(isTouching = B->GetIsTouching(center, radius))){\n\t\t\t\tif(!isTouching){\n\t\t\t\t\tif(A->IsObject() && Aobj->m_pCollidingEntity == B)\n\t\t\t\t\t\tAobj->m_pCollidingEntity = nil;\n\t\t\t\t\telse if(B->IsObject() && Bobj->m_pCollidingEntity == A)\n\t\t\t\t\t\tBobj->m_pCollidingEntity = nil;\n\t\t\t\t\telse if(A->IsPed() && Aped->m_pCollidingEntity == B)\n\t\t\t\t\t\tAped->m_pCollidingEntity = nil;\n\t\t\t\t\telse if(B->IsPed() && Bped->m_pCollidingEntity == A)\n\t\t\t\t\t\tBped->m_pCollidingEntity = nil;\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tA->bSkipLineCol = false;\n\t\t\tskipCollision = false;\n\t\t\taltcollision = false;\n\n\t\t\tif(B->IsBuilding())\n\t\t\t\tskipCollision = false;\n\t\t\telse if(A->IsObject() && Aobj->bIsStreetLight &&\n\t\t\t  (B->IsVehicle() || B->IsPed()) &&\n\t\t\t  A->GetUp().z < 0.66f){\n\t\t\t\tskipCollision = true;\n\t\t\t\tA->bSkipLineCol = true;\n\t\t\t\tAobj->m_pCollidingEntity = B;\n\t\t\t}else if(B->IsObject() && Bobj->bIsStreetLight &&\n\t\t\t  (A->IsVehicle() || A->IsPed()) &&\n\t\t\t  B->GetUp().z < 0.66f){\n\t\t\t\tskipCollision = true;\n\t\t\t\tA->bSkipLineCol = true;\n\t\t\t\tBobj->m_pCollidingEntity = A;\n\t\t\t}else if(A->IsObject() && B->IsVehicle()){\n\t\t\t\tif(A->GetModelIndex() == MI_CAR_BUMPER)\n\t\t\t\t\tskipCollision = true;\n\t\t\t\telse if(Aobj->ObjectCreatedBy == TEMP_OBJECT ||\n\t\t\t\t   Aobj->bHasBeenDamaged ||\n\t\t\t\t   !Aobj->GetIsStatic()){\n\t\t\t\t\tif(Aobj->m_pCollidingEntity == B)\n\t\t\t\t\t\tskipCollision = true;\n\t\t\t\t\telse if(Aobj->m_nCollisionDamageEffect < DAMAGE_EFFECT_SMASH_COMPLETELY){\n\t\t\t\t\t\tCMatrix inv;\n\t\t\t\t\t\tCVector size = CModelInfo::GetModelInfo(A->GetModelIndex())->GetColModel()->boundingBox.GetSize();\n\t\t\t\t\t\tsize = A->GetMatrix() * size;\n\t\t\t\t\t\tif(size.z < B->GetPosition().z ||\n\t\t\t\t\t\t   (Invert(B->GetMatrix(), inv) * size).z < 0.0f){\n\t\t\t\t\t\t\tskipCollision = true;\n\t\t\t\t\t\t\tAobj->m_pCollidingEntity = B;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}else if(B->IsObject() && A->IsVehicle()){\n\t\t\t\tif(B->GetModelIndex() == MI_CAR_BUMPER)\n\t\t\t\t\tskipCollision = true;\n\t\t\t\telse if(Bobj->ObjectCreatedBy == TEMP_OBJECT ||\n\t\t\t\t   Bobj->bHasBeenDamaged ||\n\t\t\t\t   !Bobj->GetIsStatic()){\n\t\t\t\t\tif(Bobj->m_pCollidingEntity == A)\n\t\t\t\t\t\tskipCollision = true;\n\t\t\t\t\telse if(Bobj->m_nCollisionDamageEffect < DAMAGE_EFFECT_SMASH_COMPLETELY){\n\t\t\t\t\t\tCMatrix inv;\n\t\t\t\t\t\tCVector size = CModelInfo::GetModelInfo(B->GetModelIndex())->GetColModel()->boundingBox.GetSize();\n\t\t\t\t\t\tsize = B->GetMatrix() * size;\n\t\t\t\t\t\tif(size.z < A->GetPosition().z ||\n\t\t\t\t\t\t   (Invert(A->GetMatrix(), inv) * size).z < 0.0f){\n\t\t\t\t\t\t\tskipCollision = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}else if(A->GetModelIndex() == MI_GRENADE && B->IsPed() &&\n\t\t\t  A->GetPosition().z < B->GetPosition().z){\n\t\t\t\tskipCollision = true;\n\t\t\t}else if(B->GetModelIndex() == MI_GRENADE && A->IsPed() &&\n\t\t\t  B->GetPosition().z < A->GetPosition().z){\n\t\t\t\tskipCollision = true;\n\t\t\t\tA->bSkipLineCol = true;\n\t\t\t}else if(A->IsPed() && Aped->m_pCollidingEntity == B){\n\t\t\t\tskipCollision = true;\n\t\t\t\tif(!Aped->bKnockedUpIntoAir || Aped->bKnockedOffBike)\n\t\t\t\t\tA->bSkipLineCol = true;\n\t\t\t}else if(B->IsPed() && Bped->m_pCollidingEntity == A){\n\t\t\t\tskipCollision = true;\n\t\t\t\tA->bSkipLineCol = true;\n\t\t\t}else if(A->GetModelIndex() == MI_RCBANDIT && (B->IsPed() || B->IsVehicle()) ||\n\t\t\t         B->GetModelIndex() == MI_RCBANDIT && (A->IsPed() || A->IsVehicle())){\n\t\t\t\tskipCollision = true;\n\t\t\t\tA->bSkipLineCol = true;\n\t\t\t}else if(A->IsPed() && B->IsObject() && Bobj->m_fUprootLimit > 0.0f)\n\t\t\t\taltcollision = true;\n\n\n\t\t\tif(!A->bUsesCollision || skipCollision){\n\t\t\t\tB->m_scanCode = CWorld::GetCurrentScanCode();\n\t\t\t\tnumCollisions = A->ProcessEntityCollision(B, aColPoints);\n\t\t\t\tif(A->bJustCheckCollision && numCollisions > 0)\n\t\t\t\t\treturn true;\n\t\t\t\tif(numCollisions == 0 && A == (CEntity*)FindPlayerPed() && Aped->m_pCollidingEntity == B)\n\t\t\t\t\tAped->m_pCollidingEntity = nil;\n\t\t\t}else if(B->IsBuilding() || B->bIsStuck || B->m_phy_flagA08 || altcollision){\n\t\t\t\t// This is the case where B doesn't move\n\n\t\t\t\tB->m_scanCode = CWorld::GetCurrentScanCode();\n\t\t\t\tnumCollisions = A->ProcessEntityCollision(B, aColPoints);\n\t\t\t\tif(numCollisions <= 0)\n\t\t\t\t\tcontinue;\n\n\t\t\t\tCVector moveSpeed = CVector(0.0f, 0.0f, 0.0f);\n\t\t\t\tCVector turnSpeed = CVector(0.0f, 0.0f, 0.0f);\n\t\t\t\tfloat maxImpulseA = 0.0f;\n\t\t\t\tnumResponses = 0;\n\t\t\t\tif(A->bHasContacted){\n\t\t\t\t\tfor(i = 0; i < numCollisions; i++){\n\t\t\t\t\t\tif(!A->ApplyCollisionAlt(B, aColPoints[i], impulseA, moveSpeed, turnSpeed))\n\t\t\t\t\t\t\tcontinue;\n\n\t\t\t\t\t\tnumResponses++;\n\t\t\t\t\t\tif(impulseA > maxImpulseA) maxImpulseA = impulseA;\n\n\t\t\t\t\t\tif(A->IsVehicle()){\n\t\t\t\t\t\t\tif(!(((CVehicle*)A)->IsBoat() && aColPoints[i].surfaceB == SURFACE_WOOD_SOLID) &&\n\t\t\t\t\t\t\t   impulseA > A->m_fDamageImpulse)\n\t\t\t\t\t\t\t\tA->SetDamagedPieceRecord(aColPoints[i].pieceA, impulseA, B, aColPoints[i].normal);\n\n\t\t\t\t\t\t\tif(CSurfaceTable::GetAdhesionGroup(aColPoints[i].surfaceB) == ADHESIVE_SAND)\n\t\t\t\t\t\t\t\taColPoints[i].surfaceB = SURFACE_SAND;\n\n\t\t\t\t\t\t\tfloat turnSpeedDiff = A->m_vecTurnSpeed.MagnitudeSqr();\n\t\t\t\t\t\t\tfloat moveSpeedDiff = A->m_vecMoveSpeed.MagnitudeSqr();\n\n\t\t\t\t\t\t\tif(A->GetUp().z < -0.6f &&\n\t\t\t\t\t\t\t   Abs(A->m_vecMoveSpeed.x) < 0.05f &&\n\t\t\t\t\t\t\t   Abs(A->m_vecMoveSpeed.y) < 0.05f)\n\t\t\t\t\t\t\t\tDMAudio.ReportCollision(A, B, aColPoints[i].surfaceA, aColPoints[i].surfaceB, 0.1f*impulseA, Max(turnSpeedDiff, moveSpeedDiff));\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\tDMAudio.ReportCollision(A, B, aColPoints[i].surfaceA, aColPoints[i].surfaceB, impulseA, Max(turnSpeedDiff, moveSpeedDiff));\n\n\t\t\t\t\t\t}else{\n\t\t\t\t\t\t\tif(impulseA > A->m_fDamageImpulse)\n\t\t\t\t\t\t\t\tA->SetDamagedPieceRecord(aColPoints[i].pieceA, impulseA, B, aColPoints[i].normal);\n\n\t\t\t\t\t\t\tfloat turnSpeedDiff = A->m_vecTurnSpeed.MagnitudeSqr();\n\t\t\t\t\t\t\tfloat moveSpeedDiff = A->m_vecMoveSpeed.MagnitudeSqr();\n\n\t\t\t\t\t\t\tDMAudio.ReportCollision(A, B, aColPoints[i].surfaceA, aColPoints[i].surfaceB, impulseA, Max(turnSpeedDiff, moveSpeedDiff));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}else{\n\t\t\t\t\tfor(i = 0; i < numCollisions; i++){\n\t\t\t\t\t\tif(!A->ApplyCollisionAlt(B, aColPoints[i], impulseA, moveSpeed, turnSpeed))\n\t\t\t\t\t\t\tcontinue;\n\n\t\t\t\t\t\tnumResponses++;\n\t\t\t\t\t\tif(impulseA > maxImpulseA) maxImpulseA = impulseA;\n\t\t\t\t\t\tfloat adhesion = CSurfaceTable::GetAdhesiveLimit(aColPoints[i]) / numCollisions;\n\n\t\t\t\t\t\tif(A->IsVehicle()){\n\t\t\t\t\t\t\tif(((CVehicle*)A)->IsBoat() && aColPoints[i].surfaceB == SURFACE_WOOD_SOLID)\n\t\t\t\t\t\t\t\tadhesion = 0.0f;\n\t\t\t\t\t\t\telse if(impulseA > A->m_fDamageImpulse)\n\t\t\t\t\t\t\t\tA->SetDamagedPieceRecord(aColPoints[i].pieceA, impulseA, B, aColPoints[i].normal);\n\n\t\t\t\t\t\t\tif(CSurfaceTable::GetAdhesionGroup(aColPoints[i].surfaceB) == ADHESIVE_SAND)\n\t\t\t\t\t\t\t\taColPoints[i].surfaceB = SURFACE_SAND;\n\n\t\t\t\t\t\t\tfloat turnSpeedDiff = A->m_vecTurnSpeed.MagnitudeSqr();\n\t\t\t\t\t\t\tfloat moveSpeedDiff = A->m_vecMoveSpeed.MagnitudeSqr();\n\n\t\t\t\t\t\t\tif(A->GetUp().z < -0.6f &&\n\t\t\t\t\t\t\t   Abs(A->m_vecMoveSpeed.x) < 0.05f &&\n\t\t\t\t\t\t\t   Abs(A->m_vecMoveSpeed.y) < 0.05f)\n\t\t\t\t\t\t\t\tDMAudio.ReportCollision(A, B, aColPoints[i].surfaceA, aColPoints[i].surfaceB, 0.1f*impulseA, Max(turnSpeedDiff, moveSpeedDiff));\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\tDMAudio.ReportCollision(A, B, aColPoints[i].surfaceA, aColPoints[i].surfaceB, impulseA, Max(turnSpeedDiff, moveSpeedDiff));\n\n\n\t\t\t\t\t\t\tif(A->GetModelIndex() == MI_RCBANDIT)\n\t\t\t\t\t\t\t\tadhesion *= 0.2f;\n\t\t\t\t\t\t\telse if(((CVehicle*)A)->IsBoat()){\n\t\t\t\t\t\t\t\tif(aColPoints[i].normal.z > 0.6f){\n\t\t\t\t\t\t\t\t\tif(CSurfaceTable::GetAdhesionGroup(aColPoints[i].surfaceB) == ADHESIVE_LOOSE ||\n\t\t\t\t\t\t\t\t\t   CSurfaceTable::GetAdhesionGroup(aColPoints[i].surfaceB) == ADHESIVE_SAND)\n\t\t\t\t\t\t\t\t\t\tadhesion *= 3.0f;\n\t\t\t\t\t\t\t\t}else\n\t\t\t\t\t\t\t\t\tadhesion = 0.0f;\n\t\t\t\t\t\t\t}else if(A->GetStatus() == STATUS_WRECKED)\n\t\t\t\t\t\t\t\tadhesion *= 3.0f;\n\t\t\t\t\t\t\telse if(A->GetUp().z > 0.3f)\n\t\t\t\t\t\t\t\tadhesion = 0.0f;\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\tadhesion *= Min(5.0f, 0.03f*impulseA + 1.0f);\n\t\t\t\t\t\t}else{\n\t\t\t\t\t\t\tif(impulseA > A->m_fDamageImpulse)\n\t\t\t\t\t\t\t\tA->SetDamagedPieceRecord(aColPoints[i].pieceA, impulseA, B, aColPoints[i].normal);\n\n\t\t\t\t\t\t\tfloat turnSpeedDiff = A->m_vecTurnSpeed.MagnitudeSqr();\n\t\t\t\t\t\t\tfloat moveSpeedDiff = A->m_vecMoveSpeed.MagnitudeSqr();\n\n\t\t\t\t\t\t\tDMAudio.ReportCollision(A, B, aColPoints[i].surfaceA, aColPoints[i].surfaceB, impulseA, Max(turnSpeedDiff, moveSpeedDiff));\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif(A->ApplyFriction(adhesion, aColPoints[i]))\n\t\t\t\t\t\t\tA->bHasContacted = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif(numResponses){\n\t\t\t\t\tm_vecMoveSpeed += moveSpeed / numResponses;\n\t\t\t\t\tm_vecTurnSpeed += turnSpeed / numResponses;\n\t\t\t\t\tif(!CWorld::bNoMoreCollisionTorque &&\n\t\t\t\t\t   A->GetStatus() == STATUS_PLAYER && A->IsVehicle() &&\n\t\t\t\t\t   Abs(A->m_vecMoveSpeed.x) > 0.2f &&\n\t\t\t\t\t   Abs(A->m_vecMoveSpeed.y) > 0.2f){\n\t\t\t\t\t\tA->m_vecMoveFriction.x += moveSpeed.x * -0.3f / numCollisions;\n\t\t\t\t\t\tA->m_vecMoveFriction.y += moveSpeed.y * -0.3f / numCollisions;\n\t\t\t\t\t\tA->m_vecTurnFriction += turnSpeed * -0.3f / numCollisions;\n\t\t\t\t\t}\n\n\t\t\t\t\tif(B->IsObject() && Bobj->m_nCollisionDamageEffect && maxImpulseA > 20.0f)\n\t\t\t\t\t\tBobj->ObjectDamage(maxImpulseA);\n\n\t\t\t\t\tif(!CWorld::bSecondShift)\n\t\t\t\t\t\treturn true;\n\t\t\t\t\tret = true;\n\t\t\t\t}\n\t\t\t}else{\n\n\t\t\t\t// B can move\n\n\t\t\t\tB->m_scanCode = CWorld::GetCurrentScanCode();\n\t\t\t\tnumCollisions = A->ProcessEntityCollision(B, aColPoints);\n\t\t\t\tif(numCollisions <= 0)\n\t\t\t\t\tcontinue;\n\n\t\t\t\tfloat maxImpulseA = 0.0f;\n\t\t\t\tfloat maxImpulseB = 0.0f;\n\t\t\t\tif(A->bHasContacted && B->bHasContacted){\n\t\t\t\t\tfor(i = 0; i < numCollisions; i++){\n\t\t\t\t\t\tif(!A->ApplyCollision(B, aColPoints[i], impulseA, impulseB))\n\t\t\t\t\t\t\tcontinue;\n\n\t\t\t\t\t\tif(impulseA > maxImpulseA) maxImpulseA = impulseA;\n\t\t\t\t\t\tif(impulseB > maxImpulseB) maxImpulseB = impulseB;\n\n\t\t\t\t\t\tif(impulseA > A->m_fDamageImpulse)\n\t\t\t\t\t\t\tA->SetDamagedPieceRecord(aColPoints[i].pieceA, impulseA, B, aColPoints[i].normal);\n\n\t\t\t\t\t\tif(impulseB > B->m_fDamageImpulse)\n\t\t\t\t\t\t\tB->SetDamagedPieceRecord(aColPoints[i].pieceB, impulseB, A, aColPoints[i].normal);\n\n\t\t\t\t\t\tfloat turnSpeedDiff = (B->m_vecTurnSpeed - A->m_vecTurnSpeed).MagnitudeSqr();\n\t\t\t\t\t\tfloat moveSpeedDiff = (B->m_vecMoveSpeed - A->m_vecMoveSpeed).MagnitudeSqr();\n\n\t\t\t\t\t\tDMAudio.ReportCollision(A, B, aColPoints[i].surfaceA, aColPoints[i].surfaceB, impulseA, Max(turnSpeedDiff, moveSpeedDiff));\n\t\t\t\t\t}\n\t\t\t\t}else if(A->bHasContacted){\n\t\t\t\t\tCVector savedMoveFriction = A->m_vecMoveFriction;\n\t\t\t\t\tCVector savedTurnFriction = A->m_vecTurnFriction;\n\t\t\t\t\tA->m_vecMoveFriction = CVector(0.0f, 0.0f, 0.0f);\n\t\t\t\t\tA->m_vecTurnFriction = CVector(0.0f, 0.0f, 0.0f);\n\t\t\t\t\tA->bHasContacted = false;\n\n\t\t\t\t\tfor(i = 0; i < numCollisions; i++){\n\t\t\t\t\t\tif(!A->ApplyCollision(B, aColPoints[i], impulseA, impulseB))\n\t\t\t\t\t\t\tcontinue;\n\n\t\t\t\t\t\tif(impulseA > maxImpulseA) maxImpulseA = impulseA;\n\t\t\t\t\t\tif(impulseB > maxImpulseB) maxImpulseB = impulseB;\n\n\t\t\t\t\t\tif(impulseA > A->m_fDamageImpulse)\n\t\t\t\t\t\t\tA->SetDamagedPieceRecord(aColPoints[i].pieceA, impulseA, B, aColPoints[i].normal);\n\n\t\t\t\t\t\tif(impulseB > B->m_fDamageImpulse)\n\t\t\t\t\t\t\tB->SetDamagedPieceRecord(aColPoints[i].pieceB, impulseB, A, aColPoints[i].normal);\n\n\t\t\t\t\t\tfloat turnSpeedDiff = (B->m_vecTurnSpeed - A->m_vecTurnSpeed).MagnitudeSqr();\n\t\t\t\t\t\tfloat moveSpeedDiff = (B->m_vecMoveSpeed - A->m_vecMoveSpeed).MagnitudeSqr();\n\n\t\t\t\t\t\tDMAudio.ReportCollision(A, B, aColPoints[i].surfaceA, aColPoints[i].surfaceB, impulseA, Max(turnSpeedDiff, moveSpeedDiff));\n\n\t\t\t\t\t\tif(A->ApplyFriction(B, CSurfaceTable::GetAdhesiveLimit(aColPoints[i])/numCollisions, aColPoints[i])){\n\t\t\t\t\t\t\tA->bHasContacted = true;\n\t\t\t\t\t\t\tB->bHasContacted = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif(!A->bHasContacted){\n\t\t\t\t\t\tA->bHasContacted = true;\n\t\t\t\t\t\tA->m_vecMoveFriction = savedMoveFriction;\n\t\t\t\t\t\tA->m_vecTurnFriction = savedTurnFriction;\n\t\t\t\t\t}\n\t\t\t\t}else if(B->bHasContacted){\n\t\t\t\t\tCVector savedMoveFriction = B->m_vecMoveFriction;\n\t\t\t\t\tCVector savedTurnFriction = B->m_vecTurnFriction;\n\t\t\t\t\tB->m_vecMoveFriction = CVector(0.0f, 0.0f, 0.0f);\n\t\t\t\t\tB->m_vecTurnFriction = CVector(0.0f, 0.0f, 0.0f);\n\t\t\t\t\tB->bHasContacted = false;\n\n\t\t\t\t\tfor(i = 0; i < numCollisions; i++){\n\t\t\t\t\t\tif(!A->ApplyCollision(B, aColPoints[i], impulseA, impulseB))\n\t\t\t\t\t\t\tcontinue;\n\n\t\t\t\t\t\tif(impulseA > maxImpulseA) maxImpulseA = impulseA;\n\t\t\t\t\t\tif(impulseB > maxImpulseB) maxImpulseB = impulseB;\n\n\t\t\t\t\t\tif(impulseA > A->m_fDamageImpulse)\n\t\t\t\t\t\t\tA->SetDamagedPieceRecord(aColPoints[i].pieceA, impulseA, B, aColPoints[i].normal);\n\n\t\t\t\t\t\tif(impulseB > B->m_fDamageImpulse)\n\t\t\t\t\t\t\tB->SetDamagedPieceRecord(aColPoints[i].pieceB, impulseB, A, aColPoints[i].normal);\n\n\t\t\t\t\t\tfloat turnSpeedDiff = (B->m_vecTurnSpeed - A->m_vecTurnSpeed).MagnitudeSqr();\n\t\t\t\t\t\tfloat moveSpeedDiff = (B->m_vecMoveSpeed - A->m_vecMoveSpeed).MagnitudeSqr();\n\n\t\t\t\t\t\tDMAudio.ReportCollision(A, B, aColPoints[i].surfaceA, aColPoints[i].surfaceB, impulseA, Max(turnSpeedDiff, moveSpeedDiff));\n\n\t\t\t\t\t\tif(A->ApplyFriction(B, CSurfaceTable::GetAdhesiveLimit(aColPoints[i])/numCollisions, aColPoints[i])){\n\t\t\t\t\t\t\tA->bHasContacted = true;\n\t\t\t\t\t\t\tB->bHasContacted = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif(!B->bHasContacted){\n\t\t\t\t\t\tB->bHasContacted = true;\n\t\t\t\t\t\tB->m_vecMoveFriction = savedMoveFriction;\n\t\t\t\t\t\tB->m_vecTurnFriction = savedTurnFriction;\n\t\t\t\t\t}\n\t\t\t\t}else{\n\t\t\t\t\tfor(i = 0; i < numCollisions; i++){\n\t\t\t\t\t\tif(!A->ApplyCollision(B, aColPoints[i], impulseA, impulseB))\n\t\t\t\t\t\t\tcontinue;\n\n\t\t\t\t\t\tif(impulseA > maxImpulseA) maxImpulseA = impulseA;\n\t\t\t\t\t\tif(impulseB > maxImpulseB) maxImpulseB = impulseB;\n\n\t\t\t\t\t\tif(impulseA > A->m_fDamageImpulse)\n\t\t\t\t\t\t\tA->SetDamagedPieceRecord(aColPoints[i].pieceA, impulseA, B, aColPoints[i].normal);\n\n\t\t\t\t\t\tif(impulseB > B->m_fDamageImpulse)\n\t\t\t\t\t\t\tB->SetDamagedPieceRecord(aColPoints[i].pieceB, impulseB, A, aColPoints[i].normal);\n\n\t\t\t\t\t\tfloat turnSpeedDiff = (B->m_vecTurnSpeed - A->m_vecTurnSpeed).MagnitudeSqr();\n\t\t\t\t\t\tfloat moveSpeedDiff = (B->m_vecMoveSpeed - A->m_vecMoveSpeed).MagnitudeSqr();\n\n\t\t\t\t\t\tDMAudio.ReportCollision(A, B, aColPoints[i].surfaceA, aColPoints[i].surfaceB, impulseA, Max(turnSpeedDiff, moveSpeedDiff));\n\n\t\t\t\t\t\tif(A->ApplyFriction(B, CSurfaceTable::GetAdhesiveLimit(aColPoints[i])/numCollisions, aColPoints[i])){\n\t\t\t\t\t\t\tA->bHasContacted = true;\n\t\t\t\t\t\t\tB->bHasContacted = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif(B->IsPed() && A->IsVehicle() &&\n\t\t\t\t   (!Bped->IsPlayer() || B->bHasHitWall && A->m_vecMoveSpeed.MagnitudeSqr() > SQR(0.05f)))\n\t\t\t\t\tBped->KillPedWithCar((CVehicle*)A, maxImpulseB);\n\t\t\t\telse if(B->GetModelIndex() == MI_TRAIN && A->IsPed() &&\n\t\t\t\t  (!Aped->IsPlayer() || A->bHasHitWall))\n\t\t\t\t\tAped->KillPedWithCar((CVehicle*)B, maxImpulseA*2.0f);\n\t\t\t\telse if(B->IsObject() && B->bUsesCollision && A->IsVehicle()){\n\t\t\t\t\t// BUG? not impulseA?\n\t\t\t\t\tif(Bobj->m_nCollisionDamageEffect && maxImpulseB > 20.0f)\n\t\t\t\t\t\tBobj->ObjectDamage(maxImpulseB);\n\t\t\t\t\telse if(Bobj->m_nCollisionDamageEffect >= DAMAGE_EFFECT_SMASH_COMPLETELY){\n\t\t\t\t\t\tCMatrix inv;\n\t\t\t\t\t\tCVector size = CModelInfo::GetModelInfo(B->GetModelIndex())->GetColModel()->boundingBox.GetSize();\n\t\t\t\t\t\tsize = B->GetMatrix() * size;\n\t\t\t\t\t\tif(size.z < A->GetPosition().z ||\n\t\t\t\t\t\t   (Invert(A->GetMatrix(), inv) * size).z < 0.0f)\n\t\t\t\t\t\t\tBobj->ObjectDamage(50.0f);\n\t\t\t\t\t}\n\t\t\t\t}else if(A->IsObject() && A->bUsesCollision && B->IsVehicle()){\n\t\t\t\t\tif(Aobj->m_nCollisionDamageEffect && maxImpulseB > 20.0f)\n\t\t\t\t\t\tAobj->ObjectDamage(maxImpulseB);\n#ifdef FIX_BUGS\n\t\t\t\t\telse if(Aobj->m_nCollisionDamageEffect >= DAMAGE_EFFECT_SMASH_COMPLETELY){\n#else\n\t\t\t\t\telse if(Bobj->m_nCollisionDamageEffect >= DAMAGE_EFFECT_SMASH_COMPLETELY){\n#endif\n\t\t\t\t\t\tCMatrix inv;\n\t\t\t\t\t\tCVector size = CModelInfo::GetModelInfo(A->GetModelIndex())->GetColModel()->boundingBox.GetSize();\n\t\t\t\t\t\tsize = A->GetMatrix() * size;\n\t\t\t\t\t\tif(size.z < B->GetPosition().z ||\n\t\t\t\t\t\t   (Invert(B->GetMatrix(), inv) * size).z < 0.0f)\n\t\t\t\t\t\t\tAobj->ObjectDamage(50.0f);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif(B->GetStatus() == STATUS_SIMPLE){\n\t\t\t\t\tB->SetStatus(STATUS_PHYSICS);\n\t\t\t\t\tif(B->IsVehicle())\n\t\t\t\t\t\tCCarCtrl::SwitchVehicleToRealPhysics((CVehicle*)B);\n\t\t\t\t}\n\n\t\t\t\tif(!CWorld::bSecondShift)\n\t\t\t\t\treturn true;\n\t\t\t\tret = true;\n\t\t\t}\n\t\t\t\n\t\t}\n\t}\n\n\treturn ret;\n}\n\nbool\nCPhysical::CheckCollision(void)\n{\n\tCEntryInfoNode *node;\n\n\tbCollisionProcessed = false;\n\tCWorld::AdvanceCurrentScanCode();\n\tfor(node = m_entryInfoList.first; node; node = node->next)\n\t\tif(ProcessCollisionSectorList(node->sector->m_lists))\n\t\t\treturn true;\n\treturn false;\n}\n\nbool\nCPhysical::CheckCollision_SimpleCar(void)\n{\n\tCEntryInfoNode *node;\n\n\tbCollisionProcessed = false;\n\tCWorld::AdvanceCurrentScanCode();\n\tfor(node = m_entryInfoList.first; node; node = node->next)\n\t\tif(ProcessCollisionSectorList_SimpleCar(node->sector->m_lists))\n\t\t\treturn true;\n\treturn false;\n}\n\nfloat PHYSICAL_SHIFT_SPEED_DAMP = 0.707f;\n\n// --MIAMI: Proof-read once\nvoid\nCPhysical::ProcessShift(void)\n{\n\tm_fDistanceTravelled = 0.0f;\n\tif(GetStatus() == STATUS_SIMPLE){\n\t\tbIsStuck = false;\n\t\tbIsInSafePosition = true;\n\t\tRemoveAndAdd();\n\t}else{\n\t\tCPhysical *surf;\n\t\tif(bHasHitWall && (IsPed() && (surf = ((CPed*)this)->m_pCurrentPhysSurface, surf == nil || !surf->bInfiniteMass || surf->m_phy_flagA08) ||\n\t\t   CWorld::bSecondShift)){\n\t\t\tm_vecMoveSpeed *= Pow(PHYSICAL_SHIFT_SPEED_DAMP, CTimer::GetTimeStep());\n\t\t\tm_vecTurnSpeed *= Pow(PHYSICAL_SHIFT_SPEED_DAMP, CTimer::GetTimeStep());\n\t\t}\n\n\t\tCMatrix matrix(GetMatrix());\n\t\tApplyMoveSpeed();\n\t\tApplyTurnSpeed();\n\t\tGetMatrix().Reorthogonalise();\n\n\t\tCWorld::AdvanceCurrentScanCode();\n\n\t\tif(IsVehicle())\n\t\t\tm_bIsVehicleBeingShifted = true;\n\n\t\tCEntryInfoNode *node;\n\t\tbool hasshifted = false;\n\t\tfor(node = m_entryInfoList.first; node; node = node->next)\n\t\t\thasshifted |= ProcessShiftSectorList(node->sector->m_lists);\n\t\tm_bIsVehicleBeingShifted = false;\n\t\tif(hasshifted){\n\t\t\tCWorld::AdvanceCurrentScanCode();\n\t\t\tbool hadCollision = false;\n\t\t\tfor(node = m_entryInfoList.first; node; node = node->next)\n\t\t\t\tif(ProcessCollisionSectorList(node->sector->m_lists)){\n\t\t\t\t\tif(!CWorld::bSecondShift){\n\t\t\t\t\t\tGetMatrix() = matrix;\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\thadCollision = true;\n\t\t\t\t}\n\t\t\tif(hadCollision){\n\t\t\t\tGetMatrix() = matrix;\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\tbIsStuck = false;\n\t\tbIsInSafePosition = true;\n\t\tm_fDistanceTravelled = (GetPosition() - matrix.GetPosition()).Magnitude();\n\t\tRemoveAndAdd();\n\t}\n}\n\n// x is the number of units (m) we would like to step\n#define NUMSTEPS(x) ceil(Sqrt(distSq) * (1.0f/(x)))\n\nfloat HIGHSPEED_ELASTICITY_MULT_PED = 2.0f;\nfloat HIGHSPEED_ELASTICITY_MULT_COPCAR = 2.0f;\n\nvoid\nCPhysical::ProcessCollision(void)\n{\n\tint i;\n\tCPed *ped = (CPed*)this;\n\n\tm_fDistanceTravelled = 0.0f;\n\tm_bIsVehicleBeingShifted = false;\n\tbSkipLineCol = false;\n\n\tif(!bUsesCollision){\n\t\tbIsStuck = false;\n\t\tbIsInSafePosition = true;\n\t\tRemoveAndAdd();\n\t\treturn;\n\t}\n\n\tif(GetStatus() == STATUS_SIMPLE){\n\t\tif(CheckCollision_SimpleCar() && GetStatus() == STATUS_SIMPLE){\n\t\t\tSetStatus(STATUS_PHYSICS);\n\t\t\tif(IsVehicle())\n\t\t\t\tCCarCtrl::SwitchVehicleToRealPhysics((CVehicle*)this);\n\t\t}\n\t\tbIsStuck = false;\n\t\tbIsInSafePosition = true;\n\t\tRemoveAndAdd();\n\t\treturn;\n\t}\n\n\t// Save current state\n\tCMatrix savedMatrix(GetMatrix());\n\tfloat savedElasticity = m_fElasticity;\n\tCVector savedMoveSpeed = m_vecMoveSpeed;\n\tfloat savedTimeStep = CTimer::GetTimeStep();\n\n\tint8 n = 1;\t// The number of steps we divide the time step into\n\tfloat step = 0.0f;\t// divided time step\n\tfloat distSq = m_vecMoveSpeed.MagnitudeSqr() * sq(CTimer::GetTimeStep());\n\n\tif(IsPed() && (distSq >= sq(0.3f) || ped->IsPlayer())){\n\t\tif(ped->IsPlayer()){\n\t\t\tif(ped->m_pCurrentPhysSurface)\n\t\t\t\tn = Max(NUMSTEPS(0.15f), 4.0f);\n\t\t\telse\n\t\t\t\tn = Max(NUMSTEPS(0.3f), 2.0f);\n\t\t}else\n\t\t\tn = NUMSTEPS(0.45f);\n\t\tstep = savedTimeStep / n;\n\t\tif(!ped->IsPlayer())\n\t\t\tped->m_fElasticity *= HIGHSPEED_ELASTICITY_MULT_PED;\n\t}else if(IsVehicle() && distSq >= sq(0.4f)){\n\t\tif(GetStatus() == STATUS_PLAYER)\n\t\t\tn = NUMSTEPS(0.2f);\n\t\telse\n\t\t\tn = distSq > 0.32f ? NUMSTEPS(0.3f) : NUMSTEPS(0.4f);\n\t\tstep = savedTimeStep / n;\n\n\t\tCVector bbox = GetColModel()->boundingBox.GetSize();\n\t\tfloat relDistX = Abs(DotProduct(m_vecMoveSpeed, GetRight())) * CTimer::GetTimeStep() / bbox.x;\n\t\tfloat relDistY = Abs(DotProduct(m_vecMoveSpeed, GetForward())) * CTimer::GetTimeStep() / bbox.y;\n\t\tfloat relDistZ = Abs(DotProduct(m_vecMoveSpeed, GetUp())) * CTimer::GetTimeStep() / bbox.z;\n\t\tif(Max(relDistX, Max(relDistY, relDistZ)) < 1.0f){\n\t\t\t// check if we can get away with simplified processing\n\n\t\t\tApplyMoveSpeed();\n\t\t\tApplyTurnSpeed();\n\t\t\tGetMatrix().Reorthogonalise();\n\t\t\tbSkipLineCol = false;\n\t\t\tm_bIsVehicleBeingShifted = false;\n\n\t\t\tbJustCheckCollision = true;\n\t\t\tbUsesCollision = false;\n\t\t\tif(!CheckCollision()){\n\t\t\t\tbJustCheckCollision = false;\n\t\t\t\tbUsesCollision = true;\n\t\t\t\tif(IsVehicle())\n\t\t\t\t\t((CVehicle*)this)->bVehicleColProcessed = true;\n\n\t\t\t\tbHitByTrain = false;\n\t\t\t\tm_fDistanceTravelled = (GetPosition() - savedMatrix.GetPosition()).Magnitude();\n\t\t\t\tbSkipLineCol = false;\n\n\t\t\t\tbIsStuck = false;\n\t\t\t\tbIsInSafePosition = true;\n\t\t\t\tm_fElasticity = savedElasticity;\n\t\t\t\tRemoveAndAdd();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tbJustCheckCollision = false;\n\t\t\tbUsesCollision = true;\n\t\t\tGetMatrix() = savedMatrix;\n\t\t\tm_vecMoveSpeed = savedMoveSpeed;\n\t\t\tif(IsVehicle() && ((CVehicle*)this)->bIsLawEnforcer)\n\t\t\t\tm_fElasticity *= HIGHSPEED_ELASTICITY_MULT_COPCAR;\n\t\t}\n\t}else if(IsObject() && ((CObject*)this)->ObjectCreatedBy != TEMP_OBJECT){\n\t\tint responsecase = ((CObject*)this)->m_nSpecialCollisionResponseCases;\n\t\tif(responsecase == COLLRESPONSE_LAMPOST){\n\t\t\tCVector speedUp = CVector(0.0f, 0.0f, 0.0f);\n\t\t\tCVector speedDown = CVector(0.0f, 0.0f, 0.0f);\n\t\t\tCColModel *colModel = GetColModel();\n\t\t\tspeedUp.z = colModel->boundingBox.max.z;\n\t\t\tspeedDown.z = colModel->boundingBox.min.z;\n\t\t\tspeedUp = Multiply3x3(GetMatrix(), speedUp);\n\t\t\tspeedDown = Multiply3x3(GetMatrix(), speedDown);\n\t\t\tspeedUp = GetSpeed(speedUp);\n\t\t\tspeedDown = GetSpeed(speedDown);\n\t\t\tdistSq = Max(speedUp.MagnitudeSqr(), speedDown.MagnitudeSqr()) * sq(CTimer::GetTimeStep());\n\t\t\tif(distSq >= sq(0.3f)){\n\t\t\t\tn = NUMSTEPS(0.3f);\n\t\t\t\tstep = savedTimeStep / n;\n\t\t\t}\n\t\t}else if(responsecase == COLLRESPONSE_UNKNOWN5){\n\t\t\tif(distSq >= 0.009f){\n\t\t\t\tn = NUMSTEPS(0.09f);\n\t\t\t\tstep = savedTimeStep / n;\n\t\t\t}\n\t\t}else if(responsecase == COLLRESPONSE_SMALLBOX || responsecase == COLLRESPONSE_FENCEPART){\n\t\t\tif(distSq >= sq(0.15f)){\n\t\t\t\tn = NUMSTEPS(0.15f);\n\t\t\t\tstep = savedTimeStep / n;\n\t\t\t}\n\t\t}else{\n\t\t\tif(distSq >= sq(0.3f)){\n\t\t\t\tn = NUMSTEPS(0.3f);\n\t\t\t\tstep = savedTimeStep / n;\n\t\t\t}\n\t\t}\n\t}\n\n\tfor(i = 1; i < n; i++){\n\t\tCTimer::SetTimeStep(i * step);\n\t\tApplyMoveSpeed();\n\t\tApplyTurnSpeed();\n\t\t// TODO: get rid of copy paste?\n\t\tif(CheckCollision()){\n\t\t\tif(IsPed() && m_vecMoveSpeed.z == 0.0f &&\n\t\t\t   !ped->bWasStanding &&\n\t\t\t   ped->bIsStanding)\n\t\t\t\tsavedMatrix.GetPosition().z = GetPosition().z;\n\t\t\tGetMatrix() = savedMatrix;\n\t\t\tCTimer::SetTimeStep(savedTimeStep);\n\t\t\tm_fElasticity = savedElasticity;\n\t\t\treturn;\n\t\t}\n\t\tif(IsPed() && m_vecMoveSpeed.z == 0.0f &&\n\t\t   !ped->bWasStanding &&\n\t\t   ped->bIsStanding)\n\t\t\tsavedMatrix.GetPosition().z = GetPosition().z;\n\t\tGetMatrix() = savedMatrix;\n\t\tCTimer::SetTimeStep(savedTimeStep);\n\t\tif(IsVehicle()){\n\t\t\tCVehicle *veh = (CVehicle*)this;\n\t\t\tif(veh->m_vehType == VEHICLE_TYPE_CAR){\n\t\t\t\tCAutomobile *car = (CAutomobile*)this;\n\t\t\t\tcar->m_aSuspensionSpringRatio[0] = 1.0f;\n\t\t\t\tcar->m_aSuspensionSpringRatio[1] = 1.0f;\n\t\t\t\tcar->m_aSuspensionSpringRatio[2] = 1.0f;\n\t\t\t\tcar->m_aSuspensionSpringRatio[3] = 1.0f;\n\t\t\t}else if(veh->m_vehType == VEHICLE_TYPE_BIKE){\n\t\t\t\tCBike *bike = (CBike*)this;\n\t\t\t\tbike->m_aSuspensionSpringRatio[0] = 1.0f;\n\t\t\t\tbike->m_aSuspensionSpringRatio[1] = 1.0f;\n\t\t\t\tbike->m_aSuspensionSpringRatio[2] = 1.0f;\n\t\t\t\tbike->m_aSuspensionSpringRatio[3] = 1.0f;\n\t\t\t}\n\t\t}\n\t}\n\t\n\tApplyMoveSpeed();\n\tApplyTurnSpeed();\n\tGetMatrix().Reorthogonalise();\n\tm_bIsVehicleBeingShifted = false;\n\tbSkipLineCol = false;\n\tif(!m_vecMoveSpeed.IsZero() ||\n\t   !m_vecTurnSpeed.IsZero() ||\n\t   bHitByTrain ||\n\t   GetStatus() == STATUS_PLAYER ||\n\t   IsVehicle() && ((CVehicle*)this)->bRestingOnPhysical ||\n\t   IsPed() && ped->IsPlayer()){\n\t\tif(IsVehicle())\n\t\t\t((CVehicle*)this)->bVehicleColProcessed = true;\n\t\tif(CheckCollision()){\n\t\t\tGetMatrix() = savedMatrix;\n\t\t\tm_fElasticity = savedElasticity;\n\t\t\treturn;\n\t\t}\n\t}\n\tbHitByTrain = false;\n\tm_fDistanceTravelled = (GetPosition() - savedMatrix.GetPosition()).Magnitude();\n\tbSkipLineCol = false;\n\n\tbIsStuck = false;\n\tbIsInSafePosition = true;\n\tm_fElasticity = savedElasticity;\n\tRemoveAndAdd();\n}\n"
  },
  {
    "path": "src/entities/Physical.h",
    "content": "#pragma once\n\n#include \"Lists.h\"\n#include \"Timer.h\"\n#include \"Entity.h\"\n\nenum {\n\tPHYSICAL_MAX_COLLISIONRECORDS = 6\n};\n\n#define GRAVITY (0.008f)\n\nclass CTreadable;\n\nclass CPhysical : public CEntity\n{\npublic:\n\t// The not properly indented fields haven't been checked properly yet\n\n\tint32 m_audioEntityId;\n\tfloat m_phys_unused1;\n\tuint32 m_nLastTimeCollided;\n\tCVector m_vecMoveSpeed;\t\t// velocity\n\tCVector m_vecTurnSpeed;\t\t// angular velocity\n\tCVector m_vecMoveFriction;\n\tCVector m_vecTurnFriction;\n\tCVector m_vecMoveSpeedAvg;\n\tCVector m_vecTurnSpeedAvg;\n\tfloat m_fMass;\n\tfloat m_fTurnMass;\t// moment of inertia\n\tfloat m_fForceMultiplier;\n\tfloat m_fAirResistance;\n\tfloat m_fElasticity;\n\tfloat m_fBuoyancy;\n\tCVector m_vecCentreOfMass;\n\tCEntryInfoList m_entryInfoList;\n\tCPtrNode *m_movingListNode;\n\n\tint8 m_phys_unused2;\n\tuint8 m_nStaticFrames;\n\tuint8 m_nCollisionRecords;\n\tCEntity *m_aCollisionRecords[PHYSICAL_MAX_COLLISIONRECORDS];\n\n\tfloat m_fDistanceTravelled;\n\n\t// damaged piece\n\tfloat m_fDamageImpulse;\n\tCEntity *m_pDamageEntity;\n\tCVector m_vecDamageNormal;\n\tint16 m_nDamagePieceType;\n\n\tuint8 bIsHeavy : 1;\n\tuint8 bAffectedByGravity : 1;\n\tuint8 bInfiniteMass : 1;\n\tuint8 m_phy_flagA08 : 1;\n\tuint8 bIsInWater : 1;\n\tuint8 m_phy_flagA20 : 1; // unused\n\tuint8 bHitByTrain : 1;\n\tuint8 bSkipLineCol : 1;\n\n\tuint8 bIsFrozen : 1;\n\tuint8 bDontLoadCollision : 1;\n\tuint8 m_bIsVehicleBeingShifted : 1;\t// wrong name - also used on but never set for peds\n\tuint8 bJustCheckCollision : 1;\t// just see if there is a collision\n\n\tuint8 m_nSurfaceTouched;\n\tint8 m_nZoneLevel;\n\n\tCPhysical(void);\n\t~CPhysical(void);\n\n\t// from CEntity\n\tvoid Add(void);\n\tvoid Remove(void);\n\tCRect GetBoundRect(void);\n\tvoid ProcessControl(void);\n\tvoid ProcessShift(void);\n\tvoid ProcessCollision(void);\n\n\tvirtual int32 ProcessEntityCollision(CEntity *ent, CColPoint *colpoints);\n\n\tvoid RemoveAndAdd(void);\n\tvoid AddToMovingList(void);\n\tvoid RemoveFromMovingList(void);\n\tvoid SetDamagedPieceRecord(uint16 piece, float impulse, CEntity *entity, CVector dir);\n\tvoid AddCollisionRecord(CEntity *ent);\n\tvoid AddCollisionRecord_Treadable(CEntity *ent);\n\tbool GetHasCollidedWith(CEntity *ent);\n\tvoid RemoveRefsToEntity(CEntity *ent);\n\tstatic void PlacePhysicalRelativeToOtherPhysical(CPhysical *other, CPhysical *phys, CVector localPos);\n\n\t// get speed of point p relative to entity center\n\tCVector GetSpeed(const CVector &r);\n\tCVector GetSpeed(void) { return GetSpeed(CVector(0.0f, 0.0f, 0.0f)); }\n\tfloat GetMass(const CVector &pos, const CVector &dir) {\n\t\treturn 1.0f / (CrossProduct(pos, dir).MagnitudeSqr()/m_fTurnMass +\n\t\t               1.0f/m_fMass);\n\t}\n\tfloat GetMassTweak(const CVector &pos, const CVector &dir, float t) {\n\t\treturn 1.0f / (CrossProduct(pos, dir).MagnitudeSqr()/(m_fTurnMass*t) +\n\t\t               1.0f/(m_fMass*t));\n\t}\n\tvoid UnsetIsInSafePosition(void) {\n\t\tm_vecMoveSpeed *= -1.0f;\n\t\tm_vecTurnSpeed *= -1.0f;\n\t\tApplyTurnSpeed();\n\t\tApplyMoveSpeed();\n\t\tm_vecMoveSpeed *= -1.0f;\n\t\tm_vecTurnSpeed *= -1.0f;\n\t\tbIsInSafePosition = false;\t\n\t}\n\n\tconst CVector &GetMoveSpeed() { return m_vecMoveSpeed; }\n\tvoid SetMoveSpeed(float x, float y, float z) {\n\t\tm_vecMoveSpeed.x = x;\n\t\tm_vecMoveSpeed.y = y;\n\t\tm_vecMoveSpeed.z = z;\n\t}\n\tvoid SetMoveSpeed(const CVector& speed) {\n\t\tm_vecMoveSpeed = speed;\n\t}\n\tvoid AddToMoveSpeed(float x, float y, float z) {\n\t\tm_vecMoveSpeed.x += x;\n\t\tm_vecMoveSpeed.y += y;\n\t\tm_vecMoveSpeed.z += z;\n\t}\n\tvoid AddToMoveSpeed(const CVector& addition) {\n\t\tm_vecMoveSpeed += addition;\n\t}\n\tvoid AddToMoveSpeed(const CVector2D& addition) {\n\t\tm_vecMoveSpeed += CVector(addition.x, addition.y, 0.0f);\n\t}\n\tconst CVector &GetTurnSpeed() { return m_vecTurnSpeed; }\n\tvoid SetTurnSpeed(float x, float y, float z) {\n\t\tm_vecTurnSpeed.x = x;\n\t\tm_vecTurnSpeed.y = y;\n\t\tm_vecTurnSpeed.z = z;\n\t}\n\tconst CVector &GetCenterOfMass() { return m_vecCentreOfMass; }\n\tvoid SetCenterOfMass(float x, float y, float z) {\n\t\tm_vecCentreOfMass.x = x;\n\t\tm_vecCentreOfMass.y = y;\n\t\tm_vecCentreOfMass.z = z;\n\t}\n\n\tvoid ApplyMoveSpeed(void);\n\tvoid ApplyTurnSpeed(void);\n\t// Force actually means Impulse here\n\tvoid ApplyMoveForce(float jx, float jy, float jz);\n\tvoid ApplyMoveForce(const CVector &j) { ApplyMoveForce(j.x, j.y, j.z); }\n\t// j(x,y,z) is direction of force, p(x,y,z) is point relative to model center where force is applied\n\tvoid ApplyTurnForce(float jx, float jy, float jz, float px, float py, float pz);\n\t// j is direction of force, p is point relative to model center where force is applied\n\tvoid ApplyTurnForce(const CVector &j, const CVector &p) { ApplyTurnForce(j.x, j.y, j.z, p.x, p.y, p.z); }\n\tvoid ApplyFrictionMoveForce(float jx, float jy, float jz);\n\tvoid ApplyFrictionMoveForce(const CVector &j) { ApplyFrictionMoveForce(j.x, j.y, j.z); }\n\tvoid ApplyFrictionTurnForce(float jx, float jy, float jz, float rx, float ry, float rz);\n\tvoid ApplyFrictionTurnForce(const CVector &j, const CVector &p) { ApplyFrictionTurnForce(j.x, j.y, j.z, p.x, p.y, p.z); }\n\t// springRatio: 1.0 fully extended, 0.0 fully compressed\n\tbool ApplySpringCollision(float springConst, CVector &springDir, CVector &point, float springRatio, float bias);\n\tbool ApplySpringCollisionAlt(float springConst, CVector &springDir, CVector &point, float springRatio, float bias, CVector &forceDir);\n\tbool ApplySpringDampening(float damping, CVector &springDir, CVector &point, CVector &speed);\n\tvoid ApplyGravity(void);\n\tvoid ApplyFriction(void);\n\tvoid ApplyAirResistance(void);\n\tbool ApplyCollision(CPhysical *B, CColPoint &colpoint, float &impulseA, float &impulseB);\n\tbool ApplyCollision(CColPoint &colpoint, float &impulse);\n\tbool ApplyCollisionAlt(CEntity *B, CColPoint &colpoint, float &impulse, CVector &moveSpeed, CVector &turnSpeed);\n\tbool ApplyFriction(CPhysical *B, float adhesiveLimit, CColPoint &colpoint);\n\tbool ApplyFriction(float adhesiveLimit, CColPoint &colpoint);\n\n\tbool ProcessShiftSectorList(CPtrList *ptrlists);\n\tbool ProcessCollisionSectorList_SimpleCar(CPtrList *lists);\n\tbool ProcessCollisionSectorList(CPtrList *lists);\n\tbool CheckCollision(void);\n\tbool CheckCollision_SimpleCar(void);\n};\n"
  },
  {
    "path": "src/extras/GitSHA1.cpp.in",
    "content": "#define GIT_SHA1 \"@GIT_SHA1@\"\nconst char* g_GIT_SHA1 = GIT_SHA1;\n"
  },
  {
    "path": "src/extras/GitSHA1.h",
    "content": "extern const char* g_GIT_SHA1;"
  },
  {
    "path": "src/extras/arrow.inc",
    "content": "255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  \n0, 0, 0, 0,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  0, 0, 0, 0,  \n0, 0, 0, 0,  0, 0, 0, 0,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  0, 0, 0, 0,  0, 0, 0, 0,  \n0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  \n0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  \n0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  \n0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  \n0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  \n0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  \n0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  \n0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  \n0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  \n0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  \n0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  \n0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  \n0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  255, 255, 255, 255,  255, 255, 255, 255,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  \n"
  },
  {
    "path": "src/extras/cursor.inc",
    "content": "255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  255, 255, 255, 255,  \n255, 255, 255, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  255, 255, 255, 255,  \n255, 255, 255, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  255, 255, 255, 255,  119, 119, 119, 0,  \n255, 255, 255, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  255, 255, 255, 255,  255, 255, 255, 255,  119, 119, 119, 0,  119, 119, 119, 0,  \n255, 255, 255, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  255, 255, 255, 255,  119, 119, 119, 0,  119, 119, 119, 0,  119, 119, 119, 0,  119, 119, 119, 0,  \n255, 255, 255, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  255, 255, 255, 255,  119, 119, 119, 0,  119, 119, 119, 0,  119, 119, 119, 0,  119, 119, 119, 0,  \n255, 255, 255, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  255, 255, 255, 255,  119, 119, 119, 0,  119, 119, 119, 0,  119, 119, 119, 0,  \n255, 255, 255, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  255, 255, 255, 255,  119, 119, 119, 0,  119, 119, 119, 0,  \n255, 255, 255, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  255, 255, 255, 255,  119, 119, 119, 0,  \n255, 255, 255, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  255, 255, 255, 255,  \n255, 255, 255, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  255, 255, 255, 255,  119, 119, 119, 0,  \n255, 255, 255, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  255, 255, 255, 255,  255, 255, 255, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  255, 255, 255, 255,  119, 119, 119, 0,  119, 119, 119, 0,  \n255, 255, 255, 255,  0, 0, 0, 255,  0, 0, 0, 255,  255, 255, 255, 255,  119, 119, 119, 0,  119, 119, 119, 0,  255, 255, 255, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  255, 255, 255, 255,  119, 119, 119, 0,  119, 119, 119, 0,  119, 119, 119, 0,  \n255, 255, 255, 255,  0, 0, 0, 255,  0, 0, 0, 255,  255, 255, 255, 255,  119, 119, 119, 0,  119, 119, 119, 0,  119, 119, 119, 0,  255, 255, 255, 255,  0, 0, 0, 255,  0, 0, 0, 255,  0, 0, 0, 255,  255, 255, 255, 255,  119, 119, 119, 0,  119, 119, 119, 0,  119, 119, 119, 0,  119, 119, 119, 0,  \n255, 255, 255, 255,  0, 0, 0, 255,  255, 255, 255, 255,  119, 119, 119, 0,  119, 119, 119, 0,  119, 119, 119, 0,  119, 119, 119, 0,  119, 119, 119, 0,  255, 255, 255, 255,  0, 0, 0, 255,  255, 255, 255, 255,  119, 119, 119, 0,  119, 119, 119, 0,  119, 119, 119, 0,  119, 119, 119, 0,  119, 119, 119, 0,  \n255, 255, 255, 255,  255, 255, 255, 255,  119, 119, 119, 0,  119, 119, 119, 0,  119, 119, 119, 0,  119, 119, 119, 0,  119, 119, 119, 0,  119, 119, 119, 0,  119, 119, 119, 0,  255, 255, 255, 255,  119, 119, 119, 0,  119, 119, 119, 0,  119, 119, 119, 0,  119, 119, 119, 0,  119, 119, 119, 0,  119, 119, 119, 0,  \n"
  },
  {
    "path": "src/extras/custompipes.cpp",
    "content": "#define WITHD3D\n#include \"common.h\"\n\n#ifdef EXTENDED_PIPELINES\n\n#include \"main.h\"\n#include \"RwHelper.h\"\n#include \"Lights.h\"\n#include \"Timecycle.h\"\n#include \"FileMgr.h\"\n#include \"Clock.h\"\n#include \"Weather.h\"\n#include \"TxdStore.h\"\n#include \"Renderer.h\"\n#include \"World.h\"\n#include \"custompipes.h\"\n\n#ifndef LIBRW\n#error \"Need librw for EXTENDED_PIPELINES\"\n#endif\n\nnamespace CustomPipes {\n\nrw::int32 CustomMatOffset;\n\nvoid*\nCustomMatCtor(void *object, int32, int32)\n{\n\tCustomMatExt *ext = GetCustomMatExt((rw::Material*)object);\n\text->glossTex = nil;\n\text->haveGloss = false;\n\treturn object;\n}\n\nvoid*\nCustomMatCopy(void *dst, void *src, int32, int32)\n{\n\tCustomMatExt *srcext = GetCustomMatExt((rw::Material*)src);\n\tCustomMatExt *dstext = GetCustomMatExt((rw::Material*)dst);\n\tdstext->glossTex = srcext->glossTex;\n\tdstext->haveGloss = srcext->haveGloss;\n\treturn dst;\n}\n\n\n\nrw::TexDictionary *neoTxd;\n\nbool bRenderingEnvMap;\nint32 EnvMapSize = 128;\nrw::Camera *EnvMapCam;\nrw::Texture *EnvMapTex;\nrw::Texture *EnvMaskTex;\nstatic rw::RWDEVICE::Im2DVertex EnvScreenQuad[4];\nstatic int16 QuadIndices[6] = { 0, 1, 2, 0, 2, 3 };\n\nstatic rw::Camera*\nCreateEnvMapCam(rw::World *world)\n{\n\trw::Raster *fbuf = rw::Raster::create(EnvMapSize, EnvMapSize, 0, rw::Raster::CAMERATEXTURE);\n\tif(fbuf){\n\t\trw::Raster *zbuf = rw::Raster::create(EnvMapSize, EnvMapSize, 0, rw::Raster::ZBUFFER);\n\t\tif(zbuf){\n\t\t\trw::Frame *frame = rw::Frame::create();\n\t\t\tif(frame){\n\t\t\t\trw::Camera *cam = rw::Camera::create();\n\t\t\t\tif(cam){\n\t\t\t\t\tcam->frameBuffer = fbuf;\n\t\t\t\t\tcam->zBuffer = zbuf;\n\t\t\t\t\tcam->setFrame(frame);\n\t\t\t\t\tcam->setNearPlane(0.1f);\n\t\t\t\t\tcam->setFarPlane(250.0f);\n\t\t\t\t\trw::V2d vw = { 2.0f, 2.0f };\n\t\t\t\t\tcam->setViewWindow(&vw);\n\t\t\t\t\tworld->addCamera(cam);\n\t\t\t\t\tEnvMapTex = rw::Texture::create(fbuf);\n\t\t\t\t\tEnvMapTex->setFilter(rw::Texture::LINEAR);\n\n\t\t\t\t\tframe->matrix.right.x = -1.0f;\n\t\t\t\t\tframe->matrix.up.y = -1.0f;\n\t\t\t\t\tframe->matrix.update();\n\t\t\t\t\treturn cam;\n\t\t\t\t}\n\t\t\t\tframe->destroy();\n\t\t\t}\n\t\t\tzbuf->destroy();\n\t\t}\n\t\tfbuf->destroy();\n\t}\n\treturn nil;\n}\n\nstatic void\nDestroyCam(rw::Camera *cam)\n{\n\tif(cam == nil)\n\t\treturn;\n\tif(cam->frameBuffer){\n\t\tcam->frameBuffer->destroy();\n\t\tcam->frameBuffer = nil;\n\t}\n\tif(cam->zBuffer){\n\t\tcam->zBuffer->destroy();\n\t\tcam->zBuffer = nil;\n\t}\n\trw::Frame *f = cam->getFrame();\n\tif(f){\n\t\tcam->setFrame(nil);\n\t\tf->destroy();\n\t}\n\tcam->world->removeCamera(cam);\n\tcam->destroy();\n}\n\nvoid\nRenderEnvMapScene(void)\n{\n\tCRenderer::RenderRoads();\n\tCRenderer::RenderEverythingBarRoads();\n\tCRenderer::RenderFadingInEntities();\n}\n\nvoid\nEnvMapRender(void)\n{\n\tif(VehiclePipeSwitch != VEHICLEPIPE_NEO)\n\t\treturn;\n\n\tRwCameraEndUpdate(Scene.camera);\n\n\t// Neo does this differently, but i'm not quite convinced it's much better\n\trw::V3d camPos = FindPlayerCoors();\n\tEnvMapCam->getFrame()->matrix.pos = camPos;\n\tEnvMapCam->getFrame()->transform(&EnvMapCam->getFrame()->matrix, rw::COMBINEREPLACE);\n\n\trw::RGBA skycol;\n\tskycol.red = CTimeCycle::GetSkyBottomRed();\n\tskycol.green = CTimeCycle::GetSkyBottomGreen();\n\tskycol.blue = CTimeCycle::GetSkyBottomBlue();\n\tskycol.alpha = 255;\n\tEnvMapCam->clear(&skycol, rwCAMERACLEARZ|rwCAMERACLEARIMAGE);\n\tRwCameraBeginUpdate(EnvMapCam);\n\tbRenderingEnvMap = true;\n\tRenderEnvMapScene();\n\tbRenderingEnvMap = false;\n\n\tif(EnvMaskTex){\n\t\trw::SetRenderState(rw::VERTEXALPHA, TRUE);\n\t\trw::SetRenderState(rw::SRCBLEND, rw::BLENDZERO);\n\t\trw::SetRenderState(rw::DESTBLEND, rw::BLENDSRCCOLOR);\n\t\trw::SetRenderStatePtr(rw::TEXTURERASTER, EnvMaskTex->raster);\n\t\trw::im2d::RenderIndexedPrimitive(rw::PRIMTYPETRILIST, EnvScreenQuad, 4, QuadIndices, 6);\n\t\trw::SetRenderState(rw::SRCBLEND, rw::BLENDSRCALPHA);\n\t\trw::SetRenderState(rw::DESTBLEND, rw::BLENDINVSRCALPHA);\n\t}\n\tRwCameraEndUpdate(EnvMapCam);\n\n\n\tRwCameraBeginUpdate(Scene.camera);\n\n\t// debug env map\n//\trw::SetRenderStatePtr(rw::TEXTURERASTER, EnvMapTex->raster);\n//\trw::im2d::RenderIndexedPrimitive(rw::PRIMTYPETRILIST, EnvScreenQuad, 4, QuadIndices, 6);\n}\n\nstatic void\nEnvMapInit(void)\n{\n\tif(neoTxd)\n\t\tEnvMaskTex = neoTxd->find(\"CarReflectionMask\");\n\n\tEnvMapCam = CreateEnvMapCam(Scene.world);\n\n\tint width = EnvMapCam->frameBuffer->width;\n\tint height = EnvMapCam->frameBuffer->height;\n\tfloat screenZ = RwIm2DGetNearScreenZ();\n\tfloat recipZ = 1.0f/EnvMapCam->nearPlane;\n\n\tEnvScreenQuad[0].setScreenX(0.0f);\n\tEnvScreenQuad[0].setScreenY(0.0f);\n\tEnvScreenQuad[0].setScreenZ(screenZ);\n\tEnvScreenQuad[0].setCameraZ(EnvMapCam->nearPlane);\n\tEnvScreenQuad[0].setRecipCameraZ(recipZ);\n\tEnvScreenQuad[0].setColor(255, 255, 255, 255);\n\tEnvScreenQuad[0].setU(0.0f, recipZ);\n\tEnvScreenQuad[0].setV(0.0f, recipZ);\n\n\tEnvScreenQuad[1].setScreenX(0.0f);\n\tEnvScreenQuad[1].setScreenY(height);\n\tEnvScreenQuad[1].setScreenZ(screenZ);\n\tEnvScreenQuad[1].setCameraZ(EnvMapCam->nearPlane);\n\tEnvScreenQuad[1].setRecipCameraZ(recipZ);\n\tEnvScreenQuad[1].setColor(255, 255, 255, 255);\n\tEnvScreenQuad[1].setU(0.0f, recipZ);\n\tEnvScreenQuad[1].setV(1.0f, recipZ);\n\n\tEnvScreenQuad[2].setScreenX(width);\n\tEnvScreenQuad[2].setScreenY(height);\n\tEnvScreenQuad[2].setScreenZ(screenZ);\n\tEnvScreenQuad[2].setCameraZ(EnvMapCam->nearPlane);\n\tEnvScreenQuad[2].setRecipCameraZ(recipZ);\n\tEnvScreenQuad[2].setColor(255, 255, 255, 255);\n\tEnvScreenQuad[2].setU(1.0f, recipZ);\n\tEnvScreenQuad[2].setV(1.0f, recipZ);\n\n\tEnvScreenQuad[3].setScreenX(width);\n\tEnvScreenQuad[3].setScreenY(0.0f);\n\tEnvScreenQuad[3].setScreenZ(screenZ);\n\tEnvScreenQuad[3].setCameraZ(EnvMapCam->nearPlane);\n\tEnvScreenQuad[3].setRecipCameraZ(recipZ);\n\tEnvScreenQuad[3].setColor(255, 255, 255, 255);\n\tEnvScreenQuad[3].setU(1.0f, recipZ);\n\tEnvScreenQuad[3].setV(0.0f, recipZ);\n}\n\nstatic void\nEnvMapShutdown(void)\n{\n\tEnvMapTex->raster = nil;\n\tEnvMapTex->destroy();\n\tEnvMapTex = nil;\n\tDestroyCam(EnvMapCam);\n\tEnvMapCam = nil;\n}\n\n/*\n * Tweak values\n */\n\n#define INTERP_SETUP \\\n\t\tint h1 = CClock::GetHours();\t\t\t\t\t\t\t\t  \\\n\t\tint h2 = (h1+1)%24;\t\t\t\t\t\t\t\t\t\t  \\\n\t\tint w1 = CWeather::OldWeatherType;\t\t\t\t\t\t\t\t  \\\n\t\tint w2 = CWeather::NewWeatherType;\t\t\t\t\t\t\t\t  \\\n\t\tfloat timeInterp = (CClock::GetSeconds()/60.0f + CClock::GetMinutes())/60.0f;\t  \\\n\t\tfloat c0 = (1.0f-timeInterp)*(1.0f-CWeather::InterpolationValue);\t\t\t\t  \\\n\t\tfloat c1 = timeInterp*(1.0f-CWeather::InterpolationValue);\t\t\t\t\t  \\\n\t\tfloat c2 = (1.0f-timeInterp)*CWeather::InterpolationValue;\t\t\t\t\t  \\\n\t\tfloat c3 = timeInterp*CWeather::InterpolationValue;\n#define INTERP(v) v[h1][w1]*c0 + v[h2][w1]*c1 + v[h1][w2]*c2 + v[h2][w2]*c3;\n#define INTERPF(v,f) v[h1][w1].f*c0 + v[h2][w1].f*c1 + v[h1][w2].f*c2 + v[h2][w2].f*c3;\n\nInterpolatedFloat::InterpolatedFloat(float init)\n{\n\tcurInterpolator = 61;\t// compared against second\n\tfor(int h = 0; h < 24; h++)\n\t\tfor(int w = 0; w < NUMWEATHERS; w++)\n\t\t\tdata[h][w] = init;\n}\n\nvoid\nInterpolatedFloat::Read(char *s, int line, int field)\n{\n\tsscanf(s, \"%f\", &data[line][field]);\n}\n\nfloat\nInterpolatedFloat::Get(void)\n{\n\tif(curInterpolator != CClock::GetSeconds()){\n\t\tINTERP_SETUP\n\t\tcurVal = INTERP(data);\n\t\tcurInterpolator = CClock::GetSeconds();\n\t}\n\treturn curVal;\n}\n\nInterpolatedColor::InterpolatedColor(const Color &init)\n{\n\tcurInterpolator = 61;\t// compared against second\n\tfor(int h = 0; h < 24; h++)\n\t\tfor(int w = 0; w < NUMWEATHERS; w++)\n\t\t\tdata[h][w] = init;\n}\n\nvoid\nInterpolatedColor::Read(char *s, int line, int field)\n{\n\tint r, g, b, a;\n\tsscanf(s, \"%i, %i, %i, %i\", &r, &g, &b, &a);\n\tdata[line][field] = Color(r/255.0f, g/255.0f, b/255.0f, a/255.0f);\n}\n\nColor\nInterpolatedColor::Get(void)\n{\n\tif(curInterpolator != CClock::GetSeconds()){\n\t\tINTERP_SETUP\n\t\tcurVal.r = INTERPF(data, r);\n\t\tcurVal.g = INTERPF(data, g);\n\t\tcurVal.b = INTERPF(data, b);\n\t\tcurVal.a = INTERPF(data, a);\n\t\tcurInterpolator = CClock::GetSeconds();\n\t}\n\treturn curVal;\n}\n\nvoid\nInterpolatedLight::Read(char *s, int line, int field)\n{\n\tint r, g, b, a;\n\tsscanf(s, \"%i, %i, %i, %i\", &r, &g, &b, &a);\n\tdata[line][field] = Color(r/255.0f, g/255.0f, b/255.0f, a/100.0f);\n}\n\nchar*\nReadTweakValueTable(char *fp, InterpolatedValue &interp)\n{\n\tchar buf[24], *p;\n\tint c;\n\tint line, field;\n\n\tline = 0;\n\tc = *fp++;\n\twhile(c != '\\0' && line < 24){\n\t\tfield = 0;\n\t\tif(c != '\\0' && c != '#'){\n\t\t\twhile(c != '\\0' && c != '\\n' && field < NUMWEATHERS){\n\t\t\t\tp = buf;\n\t\t\t\twhile(c != '\\0' && c == '\\t')\n\t\t\t\t\tc = *fp++;\n\t\t\t\t*p++ = c;\n\t\t\t\twhile(c = *fp++, c != '\\0' && c != '\\t' && c != '\\n')\n\t\t\t\t\t*p++ = c;\n\t\t\t\t*p++ = '\\0';\n\t\t\t\tinterp.Read(buf, line, field);\n\t\t\t\tfield++;\n\t\t\t}\n\t\t\tline++;\n\t\t}\n\t\twhile(c != '\\0' && c != '\\n')\n\t\t\tc = *fp++;\n\t\tc = *fp++;\n\t}\n\treturn fp-1;\n}\n\n\n\n/*\n * Neo Vehicle pipe\n */\n\nint32 VehiclePipeSwitch = VEHICLEPIPE_MATFX;\nfloat VehicleShininess = 1.0f;\nfloat VehicleSpecularity = 1.0f;\nInterpolatedFloat Fresnel(0.4f);\nInterpolatedFloat Power(18.0f);\nInterpolatedLight DiffColor(Color(0.0f, 0.0f, 0.0f, 0.0f));\nInterpolatedLight SpecColor(Color(0.7f, 0.7f, 0.7f, 1.0f));\nrw::ObjPipeline *vehiclePipe;\n\nvoid\nAttachVehiclePipe(rw::Atomic *atomic)\n{\n\tatomic->pipeline = vehiclePipe;\n}\n\nvoid\nAttachVehiclePipe(rw::Clump *clump)\n{\n\tFORLIST(lnk, clump->atomics)\n\t\tAttachVehiclePipe(rw::Atomic::fromClump(lnk));\n}\n\n\n\n/*\n * Neo World pipe\n */\n\nbool LightmapEnable;\nfloat LightmapMult = 1.0f;\nInterpolatedFloat WorldLightmapBlend(1.0f);\nrw::ObjPipeline *worldPipe;\n\nvoid\nAttachWorldPipe(rw::Atomic *atomic)\n{\n\tatomic->pipeline = worldPipe;\n}\n\nvoid\nAttachWorldPipe(rw::Clump *clump)\n{\n\tFORLIST(lnk, clump->atomics)\n\t\tAttachWorldPipe(rw::Atomic::fromClump(lnk));\n}\n\n\n\n\n/*\n * Neo Gloss pipe\n */\n\nbool GlossEnable;\nfloat GlossMult = 1.0f;\nrw::ObjPipeline *glossPipe;\n\nrw::Texture*\nGetGlossTex(rw::Material *mat)\n{\n\tif(neoTxd == nil)\n\t\treturn nil;\n\tCustomMatExt *ext = GetCustomMatExt(mat);\n\tif(!ext->haveGloss){\n\t\tchar glossname[128];\n\t\tstrcpy(glossname, mat->texture->name);\n\t\tstrcat(glossname, \"_gloss\");\n\t\text->glossTex = neoTxd->find(glossname);\n\t\text->haveGloss = true;\n\t}\n\treturn ext->glossTex;\n}\n\nvoid\nAttachGlossPipe(rw::Atomic *atomic)\n{\n\tatomic->pipeline = glossPipe;\n}\n\nvoid\nAttachGlossPipe(rw::Clump *clump)\n{\n\tFORLIST(lnk, clump->atomics)\n\t\tAttachWorldPipe(rw::Atomic::fromClump(lnk));\n}\n\n\n\n/*\n * Neo Rim pipes\n */\n\nbool RimlightEnable;\nfloat RimlightMult = 1.0f;\nInterpolatedColor RampStart(Color(0.0f, 0.0f, 0.0f, 1.0f));\nInterpolatedColor RampEnd(Color(1.0f, 1.0f, 1.0f, 1.0f));\nInterpolatedFloat Offset(0.5f);\nInterpolatedFloat Scale(1.5f);\nInterpolatedFloat Scaling(2.0f);\nrw::ObjPipeline *rimPipe;\nrw::ObjPipeline *rimSkinPipe;\n\nvoid\nAttachRimPipe(rw::Atomic *atomic)\n{\n\tif(rw::Skin::get(atomic->geometry))\n\t\tatomic->pipeline = rimSkinPipe;\n\telse\n\t\tatomic->pipeline = rimPipe;\n}\n\nvoid\nAttachRimPipe(rw::Clump *clump)\n{\n\tFORLIST(lnk, clump->atomics)\n\t\tAttachRimPipe(rw::Atomic::fromClump(lnk));\n}\n\n/*\n * High level stuff\n */\n\nvoid\nCustomPipeInit(void)\n{\n\tRwStream *stream = RwStreamOpen(rwSTREAMFILENAME, rwSTREAMREAD, \"neo/neo.txd\");\n\tif(stream == nil)\n\t\tprintf(\"Error: couldn't open 'neo/neo.txd'\\n\");\n\telse{\n\t\tif(RwStreamFindChunk(stream, rwID_TEXDICTIONARY, nil, nil))\n\t\t\tneoTxd = RwTexDictionaryGtaStreamRead(stream);\n\t\tRwStreamClose(stream, nil);\n\t}\n\n\tEnvMapInit();\n\n\tCreateVehiclePipe();\n\tCreateWorldPipe();\n\tCreateGlossPipe();\n\tCreateRimLightPipes();\n}\n\nvoid\nCustomPipeShutdown(void)\n{\n\tDestroyVehiclePipe();\n\tDestroyWorldPipe();\n\tDestroyGlossPipe();\n\tDestroyRimLightPipes();\n\n\tEnvMapShutdown();\n\n\tif(neoTxd){\n\t\tneoTxd->destroy();\n\t\tneoTxd = nil;\n\t}\n}\n\nvoid\nCustomPipeRegister(void)\n{\n#ifdef RW_OPENGL\n\tCustomPipeRegisterGL();\n#endif\n\n\tCustomMatOffset = rw::Material::registerPlugin(sizeof(CustomMatExt), MAKECHUNKID(rwVENDORID_ROCKSTAR, 0x80),\n\t\tCustomMatCtor, nil, CustomMatCopy);\n}\n\n\n// Load textures from generic as fallback\n\nrw::TexDictionary *genericTxd;\nrw::Texture *(*defaultFindCB)(const char *name);\n\nstatic rw::Texture*\ncustomFindCB(const char *name)\n{\n\trw::Texture *res = defaultFindCB(name);\n\tif(res == nil)\n\t\tres = genericTxd->find(name);\n\treturn res;\n}\n\nvoid\nSetTxdFindCallback(void)\n{\n\tint slot = CTxdStore::FindTxdSlot(\"generic\");\n\tCTxdStore::AddRef(slot);\n\t// TODO: function for this\n\tgenericTxd = CTxdStore::GetSlot(slot)->texDict;\n\tassert(genericTxd);\n\tif(defaultFindCB == nil)\n\t\tdefaultFindCB = rw::Texture::findCB;\n\trw::Texture::findCB = customFindCB;\n}\n\n}\n\n#endif\n"
  },
  {
    "path": "src/extras/custompipes.h",
    "content": "#pragma once\n\n#ifdef LIBRW\n#ifdef EXTENDED_PIPELINES\n\nnamespace CustomPipes {\n\n\nextern rw::TexDictionary *neoTxd;\n\nstruct CustomMatExt\n{\n\trw::Texture *glossTex;\n\tbool haveGloss;\n};\nextern rw::int32 CustomMatOffset;\ninline CustomMatExt *GetCustomMatExt(rw::Material *mat) {\n\treturn PLUGINOFFSET(CustomMatExt, mat, CustomMatOffset);\n}\n\n\nstruct Color\n{\n\tfloat r, g, b, a;\n\tColor(void) {}\n\tColor(float r, float g, float b, float a) : r(r), g(g), b(b), a(a) {}\n};\n\nclass InterpolatedValue\n{\npublic:\n\tvirtual void Read(char *s, int line, int field) = 0;\n};\n\nclass InterpolatedFloat : public InterpolatedValue\n{\npublic:\n\tfloat data[24][NUMWEATHERS];\n\tfloat curInterpolator;\n\tfloat curVal;\n\n\tInterpolatedFloat(float init);\n\tvoid Read(char *s, int line, int field);\n\tfloat Get(void);\n};\n\nclass InterpolatedColor : public InterpolatedValue\n{\npublic:\n\tColor data[24][NUMWEATHERS];\n\tfloat curInterpolator;\n\tColor curVal;\n\n\tInterpolatedColor(const Color &init);\n\tvoid Read(char *s, int line, int field);\n\tColor Get(void);\n};\n\nclass InterpolatedLight : public InterpolatedColor\n{\npublic:\n\tInterpolatedLight(const Color &init) : InterpolatedColor(init) {}\n\tvoid Read(char *s, int line, int field);\n};\n\nchar *ReadTweakValueTable(char *fp, InterpolatedValue &interp);\n\n\n\n\n\nvoid CustomPipeRegister(void);\nvoid CustomPipeRegisterGL(void);\nvoid CustomPipeInit(void);\nvoid CustomPipeShutdown(void);\nvoid SetTxdFindCallback(void);\n\nextern bool bRenderingEnvMap;\nextern int32 EnvMapSize;\nextern rw::Camera *EnvMapCam;\nextern rw::Texture *EnvMapTex;\nextern rw::Texture *EnvMaskTex;\nvoid EnvMapRender(void);\n\nenum {\n\tVEHICLEPIPE_MATFX,\n\tVEHICLEPIPE_NEO\n};\nextern int32 VehiclePipeSwitch;\nextern float VehicleShininess;\nextern float VehicleSpecularity;\nextern InterpolatedFloat Fresnel;\nextern InterpolatedFloat Power;\nextern InterpolatedLight DiffColor;\nextern InterpolatedLight SpecColor;\nextern rw::ObjPipeline *vehiclePipe;\nvoid CreateVehiclePipe(void);\nvoid DestroyVehiclePipe(void);\nvoid AttachVehiclePipe(rw::Atomic *atomic);\nvoid AttachVehiclePipe(rw::Clump *clump);\n\nextern bool LightmapEnable;\nextern float LightmapMult;\nextern InterpolatedFloat WorldLightmapBlend;\nextern rw::ObjPipeline *worldPipe;\nvoid CreateWorldPipe(void);\nvoid DestroyWorldPipe(void);\nvoid AttachWorldPipe(rw::Atomic *atomic);\nvoid AttachWorldPipe(rw::Clump *clump);\n\nextern bool GlossEnable;\nextern float GlossMult;\nextern rw::ObjPipeline *glossPipe;\nvoid CreateGlossPipe(void);\nvoid DestroyGlossPipe(void);\nvoid AttachGlossPipe(rw::Atomic *atomic);\nvoid AttachGlossPipe(rw::Clump *clump);\nrw::Texture *GetGlossTex(rw::Material *mat);\n\nextern bool RimlightEnable;\nextern float RimlightMult;\nextern InterpolatedColor RampStart;\nextern InterpolatedColor RampEnd;\nextern InterpolatedFloat Offset;\nextern InterpolatedFloat Scale;\nextern InterpolatedFloat Scaling;\nextern rw::ObjPipeline *rimPipe;\nextern rw::ObjPipeline *rimSkinPipe;\nvoid CreateRimLightPipes(void);\nvoid DestroyRimLightPipes(void);\nvoid AttachRimPipe(rw::Atomic *atomic);\nvoid AttachRimPipe(rw::Clump *clump);\n\n}\n\n#endif\n\nnamespace WorldRender{\nextern int numBlendInsts[3];\nvoid AtomicFirstPass(RpAtomic *atomic, int pass);\nvoid AtomicFullyTransparent(RpAtomic *atomic, int pass, int fadeAlpha);\nvoid RenderBlendPass(int pass);\n}\n\n#endif\n"
  },
  {
    "path": "src/extras/custompipes_d3d9.cpp",
    "content": "#define WITHD3D\n#include \"common.h\"\n\n#ifdef RW_D3D9\n#include \"main.h\"\n#include \"RwHelper.h\"\n#include \"Lights.h\"\n#include \"Timecycle.h\"\n#include \"FileMgr.h\"\n#include \"Clock.h\"\n#include \"Weather.h\"\n#include \"TxdStore.h\"\n#include \"Renderer.h\"\n#include \"World.h\"\n#include \"custompipes.h\"\n\n#ifdef EXTENDED_PIPELINES\n\n#ifndef LIBRW\n#error \"Need librw for EXTENDED_PIPELINES\"\n#endif\n\nextern RwTexture *gpWhiteTexture;\t// from vehicle model info\n\nnamespace CustomPipes {\n\nenum {\n\t// rim pipe\n\tVSLOC_boneMatrices = rw::d3d::VSLOC_afterLights,\n\tVSLOC_viewVec =\tVSLOC_boneMatrices + 64*3,\n\tVSLOC_rampStart,\n\tVSLOC_rampEnd,\n\tVSLOC_rimData,\n\n\t// gloss pipe\n\tVSLOC_eye = rw::d3d::VSLOC_afterLights,\n\n\tVSLOC_reflProps,\n\tVSLOC_specLights\n};\n\n/*\n * Neo Vehicle pipe\n */\n\nstatic void *neoVehicle_VS;\nstatic void *neoVehicle_PS;\n\nvoid\nuploadSpecLights(void)\n{\n\tstruct VsLight {\n\t\trw::RGBAf color;\n\t\tfloat pos[4];\t// unused\n\t\trw::V3d dir;\n\t\tfloat power;\n\t} specLights[1 + NUMEXTRADIRECTIONALS];\n\tmemset(specLights, 0, sizeof(specLights));\n\tfor(int i = 0; i < 1+NUMEXTRADIRECTIONALS; i++)\n\t\tspecLights[i].power = 1.0f;\n\tfloat power = Power.Get();\n\tColor speccol = SpecColor.Get();\n\tspecLights[0].color.red = speccol.r;\n\tspecLights[0].color.green = speccol.g;\n\tspecLights[0].color.blue = speccol.b;\n\tspecLights[0].dir = pDirect->getFrame()->getLTM()->at;\n\tspecLights[0].power = power;\n\tfor(int i = 0; i < NUMEXTRADIRECTIONALS; i++){\n\t\tif(pExtraDirectionals[i]->getFlags() & rw::Light::LIGHTATOMICS){\n\t\t\tspecLights[1+i].color = pExtraDirectionals[i]->color;\n\t\t\tspecLights[1+i].dir = pExtraDirectionals[i]->getFrame()->getLTM()->at;\n\t\t\tspecLights[1+i].power = power*2.0f;\n\t\t}\n\t}\n\trw::d3d::d3ddevice->SetVertexShaderConstantF(VSLOC_specLights, (float*)&specLights, 3*(1 + NUMEXTRADIRECTIONALS));\n}\n\nvoid\nvehicleRenderCB(rw::Atomic *atomic, rw::d3d9::InstanceDataHeader *header)\n{\n\tusing namespace rw;\n\tusing namespace rw::d3d;\n\tusing namespace rw::d3d9;\n\n\t// TODO: make this less of a kludge\n\tif(VehiclePipeSwitch == VEHICLEPIPE_MATFX){\n\t\tmatFXGlobals.pipelines[rw::platform]->render(atomic);\n\t\treturn;\n\t}\n\n\tint vsBits;\n\trw::uint32 flags = atomic->geometry->flags;\n\tsetStreamSource(0, header->vertexStream[0].vertexBuffer, 0, header->vertexStream[0].stride);\n\tsetIndices(header->indexBuffer);\n\tsetVertexDeclaration(header->vertexDeclaration);\n\n\tvsBits = lightingCB_Shader(atomic);\n\tuploadSpecLights();\n\tuploadMatrices(atomic->getFrame()->getLTM());\n\n\tsetVertexShader(neoVehicle_VS);\n\n\tV3d eyePos = rw::engine->currentCamera->getFrame()->getLTM()->pos;\n\td3ddevice->SetVertexShaderConstantF(VSLOC_eye, (float*)&eyePos, 1);\n\n\tfloat reflProps[4];\n\treflProps[0] = Fresnel.Get();\n\treflProps[1] = SpecColor.Get().a;\n\n\td3d::setTexture(1, EnvMapTex);\n\n\tSetRenderState(SRCBLEND, BLENDONE);\n\n\tInstanceData *inst = header->inst;\n\tfor(rw::uint32 i = 0; i < header->numMeshes; i++){\n\t\tMaterial *m = inst->material;\n\n\t\tSetRenderState(VERTEXALPHA, inst->vertexAlpha || m->color.alpha != 255);\n\n\t\treflProps[2] = m->surfaceProps.specular * VehicleShininess;\n\t\treflProps[3] = m->surfaceProps.specular == 0.0f ? 0.0f : VehicleSpecularity;\n\t\td3ddevice->SetVertexShaderConstantF(VSLOC_reflProps, reflProps, 1);\n\n\t\tsetMaterial(flags, m->color, m->surfaceProps);\n\n\t\tif(m->texture)\n\t\t\td3d::setTexture(0, m->texture);\n\t\telse\n\t\t\td3d::setTexture(0, gpWhiteTexture);\n\t\tsetPixelShader(neoVehicle_PS);\n\n\t\tdrawInst(header, inst);\n\t\tinst++;\n\t}\n\n\td3d::setTexture(1, nil);\n\n\tSetRenderState(SRCBLEND, BLENDSRCALPHA);\n}\n\nvoid\nCreateVehiclePipe(void)\n{\n\tif(CFileMgr::LoadFile(\"neo/carTweakingTable.dat\", work_buff, sizeof(work_buff), \"r\") <= 0)\n\t\tprintf(\"Error: couldn't open 'neo/carTweakingTable.dat'\\n\");\n\telse{\n\t\tchar *fp = (char*)work_buff;\n\t\tfp = ReadTweakValueTable(fp, Fresnel);\n\t\tfp = ReadTweakValueTable(fp, Power);\n\t\tfp = ReadTweakValueTable(fp, DiffColor);\n\t\tfp = ReadTweakValueTable(fp, SpecColor);\n\t}\n\n#include \"shaders/obj/neoVehicle_VS.inc\"\n\tneoVehicle_VS = rw::d3d::createVertexShader(neoVehicle_VS_cso);\n\tassert(neoVehicle_VS);\n\n#include \"shaders/obj/neoVehicle_PS.inc\"\n\tneoVehicle_PS = rw::d3d::createPixelShader(neoVehicle_PS_cso);\n\tassert(neoVehicle_PS);\n\n\n\trw::d3d9::ObjPipeline *pipe = rw::d3d9::ObjPipeline::create();\n\tpipe->instanceCB = rw::d3d9::defaultInstanceCB;\n\tpipe->uninstanceCB = rw::d3d9::defaultUninstanceCB;\n\tpipe->renderCB = vehicleRenderCB;\n\tvehiclePipe = pipe;\n}\n\nvoid\nDestroyVehiclePipe(void)\n{\n\trw::d3d::destroyVertexShader(neoVehicle_VS);\n\tneoVehicle_VS = nil;\n\n\trw::d3d::destroyPixelShader(neoVehicle_PS);\n\tneoVehicle_PS = nil;\n\n\t((rw::d3d9::ObjPipeline*)vehiclePipe)->destroy();\n\tvehiclePipe = nil;\n}\n\n\n\n/*\n * Neo World pipe\n */\n\nstatic void *neoWorld_VS;\nstatic void *neoWorldVC_PS;\n\nstatic void\nworldRenderCB(rw::Atomic *atomic, rw::d3d9::InstanceDataHeader *header)\n{\n\tusing namespace rw;\n\tusing namespace rw::d3d;\n\tusing namespace rw::d3d9;\n\n\tif(!LightmapEnable){\n\t\tdefaultRenderCB_Shader(atomic, header);\n\t\treturn;\n\t}\n\n\tint vsBits;\n\tsetStreamSource(0, header->vertexStream[0].vertexBuffer, 0, header->vertexStream[0].stride);\n\tsetIndices(header->indexBuffer);\n\tsetVertexDeclaration(header->vertexDeclaration);\n\n\tvsBits = lightingCB_Shader(atomic);\n\tuploadMatrices(atomic->getFrame()->getLTM());\n\n\n\tfloat lightfactor[4];\n\n\tInstanceData *inst = header->inst;\n\tfor(rw::uint32 i = 0; i < header->numMeshes; i++){\n\t\tMaterial *m = inst->material;\n\n\t\tif(MatFX::getEffects(m) == MatFX::DUAL){\n\t\t\tsetVertexShader(neoWorld_VS);\n\n\t\t\tMatFX *matfx = MatFX::get(m);\n\t\t\tTexture *dualtex = matfx->getDualTexture();\n\t\t\tif(dualtex == nil)\n\t\t\t\tgoto notex;\n\t\t\td3d::setTexture(1, dualtex);\n\t\t\tlightfactor[0] = lightfactor[1] = lightfactor[2] = WorldLightmapBlend.Get()*LightmapMult;\n\t\t}else{\n\t\tnotex:\n\t\t\tsetVertexShader(default_amb_VS);\n\n\t\t\td3d::setTexture(1, nil);\n\t\t\tlightfactor[0] = lightfactor[1] = lightfactor[2] = 0.0f;\n\t\t}\n\t\tlightfactor[3] = m->color.alpha/255.0f;\n\t\td3d::setTexture(0, m->texture);\n\t\td3ddevice->SetPixelShaderConstantF(1, lightfactor, 1);\n\n\t\tSetRenderState(VERTEXALPHA, inst->vertexAlpha || m->color.alpha != 255);\n\n\t\tRGBA color = { 255, 255, 255, m->color.alpha };\n\t\tsetMaterial(color, m->surfaceProps);\n\n\t\tif(m->texture)\n\t\t\td3d::setTexture(0, m->texture);\n\t\telse\n\t\t\td3d::setTexture(0, gpWhiteTexture);\n\t\tsetPixelShader(neoWorldVC_PS);\n\n\t\tdrawInst(header, inst);\n\t\tinst++;\n\t}\n\td3d::setTexture(1, nil);\n}\n\nvoid\nCreateWorldPipe(void)\n{\n\tif(CFileMgr::LoadFile(\"neo/worldTweakingTable.dat\", work_buff, sizeof(work_buff), \"r\") <= 0)\n\t\tprintf(\"Error: couldn't open 'neo/worldTweakingTable.dat'\\n\");\n\telse\n\t\tReadTweakValueTable((char*)work_buff, WorldLightmapBlend);\n\n#include \"shaders/obj/default_UV2_VS.inc\"\n\tneoWorld_VS = rw::d3d::createVertexShader(default_UV2_VS_cso);\n\tassert(neoWorld_VS);\n\n#include \"shaders/obj/neoWorldVC_PS.inc\"\n\tneoWorldVC_PS = rw::d3d::createPixelShader(neoWorldVC_PS_cso);\n\tassert(neoWorldVC_PS);\n\n\n\trw::d3d9::ObjPipeline *pipe = rw::d3d9::ObjPipeline::create();\n\tpipe->instanceCB = rw::d3d9::defaultInstanceCB;\n\tpipe->uninstanceCB = rw::d3d9::defaultUninstanceCB;\n\tpipe->renderCB = worldRenderCB;\n\tworldPipe = pipe;\n}\n\nvoid\nDestroyWorldPipe(void)\n{\n\trw::d3d::destroyVertexShader(neoWorld_VS);\n\tneoWorld_VS = nil;\n\trw::d3d::destroyPixelShader(neoWorldVC_PS);\n\tneoWorldVC_PS = nil;\n\n\n\t((rw::d3d9::ObjPipeline*)worldPipe)->destroy();\n\tworldPipe = nil;\n}\n\n\n\n\n/*\n * Neo Gloss pipe\n */\n\nstatic void *neoGloss_VS;\nstatic void *neoGloss_PS;\n\nstatic void\nglossRenderCB(rw::Atomic *atomic, rw::d3d9::InstanceDataHeader *header)\n{\n\tworldRenderCB(atomic, header);\n\n\tusing namespace rw;\n\tusing namespace rw::d3d;\n\tusing namespace rw::d3d9;\n\n\tif(!GlossEnable)\n\t\treturn;\n\n\tsetVertexShader(neoGloss_VS);\n\tsetPixelShader(neoGloss_PS);\n\n\tV3d eyePos = rw::engine->currentCamera->getFrame()->getLTM()->pos;\n\td3ddevice->SetVertexShaderConstantF(VSLOC_eye, (float*)&eyePos, 1);\n\td3ddevice->SetPixelShaderConstantF(1, (float*)&GlossMult, 1);\n\n\tSetRenderState(VERTEXALPHA, TRUE);\n\tSetRenderState(SRCBLEND, BLENDONE);\n\tSetRenderState(DESTBLEND, BLENDONE);\n\tSetRenderState(ZWRITEENABLE, FALSE);\n\tSetRenderState(ALPHATESTFUNC, ALPHAALWAYS);\n\n\tInstanceData *inst = header->inst;\n\tfor(rw::uint32 i = 0; i < header->numMeshes; i++){\n\t\tMaterial *m = inst->material;\n\n\t\tif(m->texture){\n\t\t\tTexture *tex = GetGlossTex(m);\n\t\t\tif(tex){\n\t\t\t\td3d::setTexture(0, tex);\n\t\t\t\tdrawInst(header, inst);\n\t\t\t}\n\t\t}\n\t\tinst++;\n\t}\n\n\tSetRenderState(ZWRITEENABLE, TRUE);\n\tSetRenderState(ALPHATESTFUNC, ALPHAGREATEREQUAL);\n\tSetRenderState(SRCBLEND, BLENDSRCALPHA);\n\tSetRenderState(DESTBLEND, BLENDINVSRCALPHA);\n}\n\nvoid\nCreateGlossPipe(void)\n{\n#include \"shaders/obj/neoGloss_VS.inc\"\n\tneoGloss_VS = rw::d3d::createVertexShader(neoGloss_VS_cso);\n\tassert(neoGloss_VS);\n\n#include \"shaders/obj/neoGloss_PS.inc\"\n\tneoGloss_PS = rw::d3d::createPixelShader(neoGloss_PS_cso);\n\tassert(neoGloss_PS);\n\n\n\trw::d3d9::ObjPipeline *pipe = rw::d3d9::ObjPipeline::create();\n\tpipe->instanceCB = rw::d3d9::defaultInstanceCB;\n\tpipe->uninstanceCB = rw::d3d9::defaultUninstanceCB;\n\tpipe->renderCB = glossRenderCB;\n\tglossPipe = pipe;\n}\n\nvoid\nDestroyGlossPipe(void)\n{\n\trw::d3d::destroyVertexShader(neoGloss_VS);\n\tneoGloss_VS = nil;\n\n\trw::d3d::destroyPixelShader(neoGloss_PS);\n\tneoGloss_PS = nil;\n\n\t((rw::d3d9::ObjPipeline*)glossPipe)->destroy();\n\tglossPipe = nil;\n}\n\n\n\n/*\n * Neo Rim pipes\n */\n\nstatic void *neoRim_VS;\nstatic void *neoRimSkin_VS;\n\nstatic void\nuploadRimData(bool enable)\n{\n\tusing namespace rw;\n\tusing namespace rw::d3d;\n\n\tV3d viewVec = rw::engine->currentCamera->getFrame()->getLTM()->at;\n\td3ddevice->SetVertexShaderConstantF(VSLOC_viewVec, (float*)&viewVec, 1);\n\tfloat rimData[4];\n\trimData[0] = Offset.Get();\n\trimData[1] = Scale.Get();\n\tif(enable)\n\t\trimData[2] = Scaling.Get()*RimlightMult;\n\telse\n\t\trimData[2] = 0.0f;\n\trimData[3] = 0.0f;\n\td3ddevice->SetVertexShaderConstantF(VSLOC_rimData, rimData, 1);\n\tColor col = RampStart.Get();\n\td3ddevice->SetVertexShaderConstantF(VSLOC_rampStart, (float*)&col, 1);\n\tcol = RampEnd.Get();\n\td3ddevice->SetVertexShaderConstantF(VSLOC_rampEnd, (float*)&col, 1);\n}\n\nstatic void\nrimRenderCB(rw::Atomic *atomic, rw::d3d9::InstanceDataHeader *header)\n{\n\tusing namespace rw;\n\tusing namespace rw::d3d;\n\tusing namespace rw::d3d9;\n\n\tif(!RimlightEnable){\n\t\tdefaultRenderCB_Shader(atomic, header);\n\t\treturn;\n\t}\n\n\tint vsBits;\n\trw::uint32 flags = atomic->geometry->flags;\n\tsetStreamSource(0, header->vertexStream[0].vertexBuffer, 0, header->vertexStream[0].stride);\n\tsetIndices(header->indexBuffer);\n\tsetVertexDeclaration(header->vertexDeclaration);\n\n\tvsBits = lightingCB_Shader(atomic);\n\tuploadMatrices(atomic->getFrame()->getLTM());\n\n\tsetVertexShader(neoRim_VS);\n\n\tuploadRimData(atomic->geometry->flags & Geometry::LIGHT);\n\n\tInstanceData *inst = header->inst;\n\tfor(rw::uint32 i = 0; i < header->numMeshes; i++){\n\t\tMaterial *m = inst->material;\n\n\t\tSetRenderState(VERTEXALPHA, inst->vertexAlpha || m->color.alpha != 255);\n\n\t\tsetMaterial(flags, m->color, m->surfaceProps);\n\n\t\tif(m->texture){\n\t\t\td3d::setTexture(0, m->texture);\n\t\t\tsetPixelShader(default_tex_PS);\n\t\t}else\n\t\t\tsetPixelShader(default_PS);\n\n\t\tdrawInst(header, inst);\n\t\tinst++;\n\t}\n}\n\nstatic void\nrimSkinRenderCB(rw::Atomic *atomic, rw::d3d9::InstanceDataHeader *header)\n{\n\tusing namespace rw;\n\tusing namespace rw::d3d;\n\tusing namespace rw::d3d9;\n\n\tif(!RimlightEnable){\n\t\tskinRenderCB(atomic, header);\n\t\treturn;\n\t}\n\n\tint vsBits;\n\trw::uint32 flags = atomic->geometry->flags;\n\tsetStreamSource(0, (IDirect3DVertexBuffer9*)header->vertexStream[0].vertexBuffer,\n\t                           0, header->vertexStream[0].stride);\n\tsetIndices((IDirect3DIndexBuffer9*)header->indexBuffer);\n\tsetVertexDeclaration((IDirect3DVertexDeclaration9*)header->vertexDeclaration);\n\n\tvsBits = lightingCB_Shader(atomic);\n\tuploadMatrices(atomic->getFrame()->getLTM());\n\n\tuploadSkinMatrices(atomic);\n\n\tsetVertexShader(neoRimSkin_VS);\n\n\tuploadRimData(atomic->geometry->flags & Geometry::LIGHT);\n\n\tInstanceData *inst = header->inst;\n\tfor(rw::uint32 i = 0; i < header->numMeshes; i++){\n\t\tMaterial *m = inst->material;\n\n\t\tSetRenderState(VERTEXALPHA, inst->vertexAlpha || m->color.alpha != 255);\n\n\t\tsetMaterial(flags, m->color, m->surfaceProps);\n\n\t\tif(inst->material->texture){\n\t\t\td3d::setTexture(0, m->texture);\n\t\t\tsetPixelShader(default_tex_PS);\n\t\t}else\n\t\t\tsetPixelShader(default_PS);\n\n\t\tdrawInst(header, inst);\n\t\tinst++;\n\t}\n}\n\nvoid\nCreateRimLightPipes(void)\n{\n\tif(CFileMgr::LoadFile(\"neo/rimTweakingTable.dat\", work_buff, sizeof(work_buff), \"r\") <= 0)\n\t\tprintf(\"Error: couldn't open 'neo/rimTweakingTable.dat'\\n\");\n\telse{\n\t\tchar *fp = (char*)work_buff;\n\t\tfp = ReadTweakValueTable(fp, RampStart);\n\t\tfp = ReadTweakValueTable(fp, RampEnd);\n\t\tfp = ReadTweakValueTable(fp, Offset);\n\t\tfp = ReadTweakValueTable(fp, Scale);\n\t\tfp = ReadTweakValueTable(fp, Scaling);\n\t}\n\n\n#include \"shaders/obj/neoRim_VS.inc\"\n\tneoRim_VS = rw::d3d::createVertexShader(neoRim_VS_cso);\n\tassert(neoRim_VS);\n\n#include \"shaders/obj/neoRimSkin_VS.inc\"\n\tneoRimSkin_VS = rw::d3d::createVertexShader(neoRimSkin_VS_cso);\n\tassert(neoRimSkin_VS);\n\n\n\trw::d3d9::ObjPipeline *pipe = rw::d3d9::ObjPipeline::create();\n\tpipe->instanceCB = rw::d3d9::defaultInstanceCB;\n\tpipe->uninstanceCB = rw::d3d9::defaultUninstanceCB;\n\tpipe->renderCB = rimRenderCB;\n\trimPipe = pipe;\n\n\tpipe = rw::d3d9::ObjPipeline::create();\n\tpipe->instanceCB = rw::d3d9::skinInstanceCB;\n\tpipe->uninstanceCB = nil;\n\tpipe->renderCB = rimSkinRenderCB;\n\trimSkinPipe = pipe;\n}\n\nvoid\nDestroyRimLightPipes(void)\n{\n\trw::d3d::destroyVertexShader(neoRim_VS);\n\tneoRim_VS = nil;\n\n\trw::d3d::destroyVertexShader(neoRimSkin_VS);\n\tneoRimSkin_VS = nil;\n\n\t((rw::d3d9::ObjPipeline*)rimPipe)->destroy();\n\trimPipe = nil;\n\n\t((rw::d3d9::ObjPipeline*)rimSkinPipe)->destroy();\n\trimSkinPipe = nil;\n}\n\n}\n\n#endif\n\n#ifdef NEW_RENDERER\n#ifndef LIBRW\n#error \"Need librw for NEW_PIPELINES\"\n#endif\n\nnamespace WorldRender\n{\n\nstruct BuildingInst\n{\n\trw::RawMatrix combinedMat;\n\trw::d3d9::InstanceDataHeader *instHeader;\n\tuint8 fadeAlpha;\n\tbool lighting;\n};\nBuildingInst blendInsts[3][2000];\nint numBlendInsts[3];\n\nstatic RwRGBAReal black;\n\nstatic void\nSetMatrix(BuildingInst *building, rw::Matrix *worldMat)\n{\n\tusing namespace rw;\n\tRawMatrix world, worldview;\n\tCamera *cam = engine->currentCamera;\n\tconvMatrix(&world, worldMat);\n\tRawMatrix::mult(&worldview, &world, &cam->devView);\n\tRawMatrix::mult(&building->combinedMat, &worldview, &cam->devProj);\n}\n\nstatic bool\nIsTextureTransparent(RwTexture *tex)\n{\n\tif(tex == nil || tex->raster == nil)\n\t\treturn false;\n\treturn PLUGINOFFSET(rw::d3d::D3dRaster, tex->raster, rw::d3d::nativeRasterOffset)->hasAlpha;\n}\n\n// Render all opaque meshes and put atomics that needs blending\n// into the deferred list.\nvoid\nAtomicFirstPass(RpAtomic *atomic, int pass)\n{\n\tusing namespace rw;\n\tusing namespace rw::d3d;\n\tusing namespace rw::d3d9;\n\n\tBuildingInst *building = &blendInsts[pass][numBlendInsts[pass]];\n\n\tatomic->getPipeline()->instance(atomic);\n\tbuilding->instHeader = (d3d9::InstanceDataHeader*)atomic->geometry->instData;\n\tassert(building->instHeader != nil);\n\tassert(building->instHeader->platform == PLATFORM_D3D9);\n\tbuilding->fadeAlpha = 255;\n\tbuilding->lighting = !!(atomic->geometry->flags & rw::Geometry::LIGHT);\n\trw::uint32 flags = atomic->geometry->flags;\n\n\tbool setupDone = false;\n\tbool defer = false;\n\tSetMatrix(building, atomic->getFrame()->getLTM());\n\n\tInstanceData *inst = building->instHeader->inst;\n\tfor(rw::uint32 i = 0; i < building->instHeader->numMeshes; i++, inst++){\n\t\tMaterial *m = inst->material;\n\n\t\tif(inst->vertexAlpha || m->color.alpha != 255 ||\n\t\t   IsTextureTransparent(m->texture)){\n\t\t\tdefer = true;\n\t\t\tcontinue;\n\t\t}\n\n\t\t// alright we're rendering this atomic\n\t\tif(!setupDone){\n\t\t\tsetStreamSource(0, building->instHeader->vertexStream[0].vertexBuffer, 0, building->instHeader->vertexStream[0].stride);\n\t\t\tsetIndices(building->instHeader->indexBuffer);\n\t\t\tsetVertexDeclaration(building->instHeader->vertexDeclaration);\n\t\t\tsetVertexShader(default_amb_VS);\n\t\t\td3ddevice->SetVertexShaderConstantF(VSLOC_combined, (float*)&building->combinedMat, 4);\n\t\t\tif(building->lighting)\n\t\t\t\tsetAmbient(pAmbient->color);\n\t\t\telse\n\t\t\t\tsetAmbient(black);\n\t\t\tsetupDone = true;\n\t\t}\n\n\t\tsetMaterial(flags, m->color, m->surfaceProps);\n\n\t\tif(m->texture){\n\t\t\td3d::setTexture(0, m->texture);\n\t\t\tsetPixelShader(default_tex_PS);\n\t\t}else\n\t\t\tsetPixelShader(default_PS);\n\n\t\tdrawInst(building->instHeader, inst);\n\t}\n\tif(defer)\n\t\tnumBlendInsts[pass]++;\n}\n\nvoid\nAtomicFullyTransparent(RpAtomic *atomic, int pass, int fadeAlpha)\n{\n\tusing namespace rw;\n\tusing namespace rw::d3d;\n\tusing namespace rw::d3d9;\n\n\tBuildingInst *building = &blendInsts[pass][numBlendInsts[pass]];\n\n\tatomic->getPipeline()->instance(atomic);\n\tbuilding->instHeader = (d3d9::InstanceDataHeader*)atomic->geometry->instData;\n\tassert(building->instHeader != nil);\n\tassert(building->instHeader->platform == PLATFORM_D3D9);\n\tbuilding->fadeAlpha = fadeAlpha;\n\tbuilding->lighting = !!(atomic->geometry->flags & rw::Geometry::LIGHT);\n\tSetMatrix(building, atomic->getFrame()->getLTM());\n\tnumBlendInsts[pass]++;\n}\n\nvoid\nRenderBlendPass(int pass)\n{\n\tusing namespace rw;\n\tusing namespace rw::d3d;\n\tusing namespace rw::d3d9;\n\n\tsetVertexShader(default_amb_VS);\n\n\tint i;\n\tfor(i = 0; i < numBlendInsts[pass]; i++){\n\t\tBuildingInst *building = &blendInsts[pass][i];\n\n\t\tsetStreamSource(0, building->instHeader->vertexStream[0].vertexBuffer, 0, building->instHeader->vertexStream[0].stride);\n\t\tsetIndices(building->instHeader->indexBuffer);\n\t\tsetVertexDeclaration(building->instHeader->vertexDeclaration);\n\t\td3ddevice->SetVertexShaderConstantF(VSLOC_combined, (float*)&building->combinedMat, 4);\n\t\tif(building->lighting)\n\t\t\tsetAmbient(pAmbient->color);\n\t\telse\n\t\t\tsetAmbient(black);\n\n\t\tInstanceData *inst = building->instHeader->inst;\n\t\tfor(rw::uint32 j = 0; j < building->instHeader->numMeshes; j++, inst++){\n\t\t\tMaterial *m = inst->material;\n\t\t\tif(!inst->vertexAlpha && m->color.alpha == 255 && !IsTextureTransparent(m->texture) && building->fadeAlpha == 255)\n\t\t\t\tcontinue;\t// already done this one\n\n\t\t\trw::RGBA color = m->color;\n\t\t\tcolor.alpha = (color.alpha * building->fadeAlpha)/255;\n\t\t\tsetMaterial(color, m->surfaceProps);\t// always modulate here\n\n\t\t\tif(m->texture){\n\t\t\t\td3d::setTexture(0, m->texture);\n\t\t\t\tsetPixelShader(default_tex_PS);\n\t\t\t}else\n\t\t\t\tsetPixelShader(default_PS);\n\n\t\t\tdrawInst(building->instHeader, inst);\n\t\t}\n\t}\n}\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "src/extras/custompipes_gl.cpp",
    "content": "#include \"common.h\"\n\n#ifdef RW_OPENGL\n#include \"main.h\"\n#include \"RwHelper.h\"\n#include \"Lights.h\"\n#include \"Timecycle.h\"\n#include \"FileMgr.h\"\n#include \"Clock.h\"\n#include \"Weather.h\"\n#include \"TxdStore.h\"\n#include \"Renderer.h\"\n#include \"World.h\"\n#include \"custompipes.h\"\n\n#ifdef EXTENDED_PIPELINES\n\n#ifndef LIBRW\n#error \"Need librw for EXTENDED_PIPELINES\"\n#endif\n\nnamespace CustomPipes {\n\nstatic int32 u_viewVec;\nstatic int32 u_rampStart;\nstatic int32 u_rampEnd;\nstatic int32 u_rimData;\n\nstatic int32 u_lightMap;\n\nstatic int32 u_eye;\nstatic int32 u_reflProps;\nstatic int32 u_specDir;\nstatic int32 u_specColor;\n\n#define U(i) currentShader->uniformLocations[i]\n\n/*\n * Neo Vehicle pipe\n */\n\nrw::gl3::Shader *neoVehicleShader;\n\nstatic void\nuploadSpecLights(void)\n{\n\tusing namespace rw::gl3;\n\n\trw::RGBAf colors[1 + NUMEXTRADIRECTIONALS];\n\tstruct {\n\t\trw::V3d dir;\n\t\tfloat power;\n\t} dirs[1 + NUMEXTRADIRECTIONALS];\n\tmemset(colors, 0, sizeof(colors));\n\tmemset(dirs, 0, sizeof(dirs));\n\tfor(int i = 0; i < 1+NUMEXTRADIRECTIONALS; i++)\n\t\tdirs[i].power = 1.0f;\n\tfloat power = Power.Get();\n\tColor speccol = SpecColor.Get();\n\tcolors[0].red = speccol.r;\n\tcolors[0].green = speccol.g;\n\tcolors[0].blue = speccol.b;\n\tdirs[0].dir = pDirect->getFrame()->getLTM()->at;\n\tdirs[0].power = power;\n\tfor(int i = 0; i < NUMEXTRADIRECTIONALS; i++){\n\t\tif(pExtraDirectionals[i]->getFlags() & rw::Light::LIGHTATOMICS){\n\t\t\tcolors[1+i] = pExtraDirectionals[i]->color;\n\t\t\tdirs[1+i].dir = pExtraDirectionals[i]->getFrame()->getLTM()->at;\n\t\t\tdirs[1+i].power = power*2.0f;\n\t\t}\n\t}\n\tglUniform4fv(U(u_specDir), 1 + NUMEXTRADIRECTIONALS, (float*)&dirs);\n\tglUniform4fv(U(u_specColor), 1 + NUMEXTRADIRECTIONALS, (float*)&colors);\n}\n\nstatic void\nvehicleRenderCB(rw::Atomic *atomic, rw::gl3::InstanceDataHeader *header)\n{\n\tusing namespace rw;\n\tusing namespace rw::gl3;\n\n\t// TODO: make this less of a kludge\n\tif(VehiclePipeSwitch == VEHICLEPIPE_MATFX){\n\t\tmatFXGlobals.pipelines[rw::platform]->render(atomic);\n\t\treturn;\n\t}\n\n\tMaterial *m;\n\n\trw::uint32 flags = atomic->geometry->flags;\n\tsetWorldMatrix(atomic->getFrame()->getLTM());\n\tlightingCB(atomic);\n\n\tsetupVertexInput(header);\n\n\tInstanceData *inst = header->inst;\n\trw::int32 n = header->numMeshes;\n\n\tneoVehicleShader->use();\n\n\tV3d eyePos = rw::engine->currentCamera->getFrame()->getLTM()->pos;\n\tglUniform3fv(U(u_eye), 1, (float*)&eyePos);\n\n\tuploadSpecLights();\n\n\tfloat reflProps[4];\n\treflProps[0] = Fresnel.Get();\n\treflProps[1] = SpecColor.Get().a;\n\n\tsetTexture(1, EnvMapTex);\n\n\tSetRenderState(SRCBLEND, BLENDONE);\n\n\twhile(n--){\n\t\tm = inst->material;\n\n\t\tsetMaterial(flags, m->color, m->surfaceProps);\n\n\t\tsetTexture(0, m->texture);\n\n\t\trw::SetRenderState(VERTEXALPHA, inst->vertexAlpha || m->color.alpha != 0xFF);\n\n\t\treflProps[2] = m->surfaceProps.specular * VehicleShininess;\n\t\treflProps[3] = m->surfaceProps.specular == 0.0f ? 0.0f : VehicleSpecularity;\n\t\tglUniform4fv(U(u_reflProps), 1, reflProps);\n\n\t\tdrawInst(header, inst);\n\t\tinst++;\n\t}\n\n\tsetTexture(1, nil);\n\n\tSetRenderState(SRCBLEND, BLENDSRCALPHA);\n\n\tteardownVertexInput(header);\n}\n\nvoid\nCreateVehiclePipe(void)\n{\n\tusing namespace rw;\n\tusing namespace rw::gl3;\n\n\tif(CFileMgr::LoadFile(\"neo/carTweakingTable.dat\", work_buff, sizeof(work_buff), \"r\") <= 0)\n\t\tprintf(\"Error: couldn't open 'neo/carTweakingTable.dat'\\n\");\n\telse{\n\t\tchar *fp = (char*)work_buff;\n\t\tfp = ReadTweakValueTable(fp, Fresnel);\n\t\tfp = ReadTweakValueTable(fp, Power);\n\t\tfp = ReadTweakValueTable(fp, DiffColor);\n\t\tfp = ReadTweakValueTable(fp, SpecColor);\n\t}\n\n\n\t{\n#include \"shaders/obj/neoVehicle_frag.inc\"\n#include \"shaders/obj/neoVehicle_vert.inc\"\n\tconst char *vs[] = { shaderDecl, header_vert_src, neoVehicle_vert_src, nil };\n\tconst char *fs[] = { shaderDecl, header_frag_src, neoVehicle_frag_src, nil };\n\tneoVehicleShader = Shader::create(vs, fs);\n\tassert(neoVehicleShader);\n\t}\n\n\n\trw::gl3::ObjPipeline *pipe = rw::gl3::ObjPipeline::create();\n\tpipe->instanceCB = rw::gl3::defaultInstanceCB;\n\tpipe->uninstanceCB = nil;\n\tpipe->renderCB = vehicleRenderCB;\n\tvehiclePipe = pipe;\n}\n\nvoid\nDestroyVehiclePipe(void)\n{\n\tneoVehicleShader->destroy();\n\tneoVehicleShader = nil;\n\n\t((rw::gl3::ObjPipeline*)vehiclePipe)->destroy();\n\tvehiclePipe = nil;\n}\n\n\n\n/*\n * Neo World pipe\n */\n\nrw::gl3::Shader *neoWorldShader;\n\nstatic void\nworldRenderCB(rw::Atomic *atomic, rw::gl3::InstanceDataHeader *header)\n{\n\tusing namespace rw;\n\tusing namespace rw::gl3;\n\n\tif(!LightmapEnable){\n\t\tgl3::defaultRenderCB(atomic, header);\n\t\treturn;\n\t}\n\n\tMaterial *m;\n\n\tsetWorldMatrix(atomic->getFrame()->getLTM());\n\tlightingCB(atomic);\n\n\tsetupVertexInput(header);\n\n\tInstanceData *inst = header->inst;\n\trw::int32 n = header->numMeshes;\n\n\tneoWorldShader->use();\n\n\tfloat lightfactor[4];\n\n\twhile(n--){\n\t\tm = inst->material;\n\n\t\tif(MatFX::getEffects(m) == MatFX::DUAL){\n\t\t\tMatFX *matfx = MatFX::get(m);\n\t\t\tTexture *dualtex = matfx->getDualTexture();\n\t\t\tif(dualtex == nil)\n\t\t\t\tgoto notex;\n\t\t\tsetTexture(1, dualtex);\n\t\t\tlightfactor[0] = lightfactor[1] = lightfactor[2] = WorldLightmapBlend.Get()*LightmapMult;\n\t\t}else{\n\t\tnotex:\n\t\t\tsetTexture(1, nil);\n\t\t\tlightfactor[0] = lightfactor[1] = lightfactor[2] = 0.0f;\n\t\t}\n\t\tlightfactor[3] = m->color.alpha/255.0f;\n\t\tglUniform4fv(U(u_lightMap), 1, lightfactor);\n\n\t\tRGBA color = { 255, 255, 255, m->color.alpha };\n\t\tsetMaterial(color, m->surfaceProps);\n\n\t\tsetTexture(0, m->texture);\n\n\t\trw::SetRenderState(VERTEXALPHA, inst->vertexAlpha || m->color.alpha != 0xFF);\n\n\t\tdrawInst(header, inst);\n\t\tinst++;\n\t}\n\tsetTexture(1, nil);\n\tteardownVertexInput(header);\n}\n\nvoid\nCreateWorldPipe(void)\n{\n\tusing namespace rw;\n\tusing namespace rw::gl3;\n\n\tif(CFileMgr::LoadFile(\"neo/worldTweakingTable.dat\", work_buff, sizeof(work_buff), \"r\") <= 0)\n\t\tprintf(\"Error: couldn't open 'neo/worldTweakingTable.dat'\\n\");\n\telse\n\t\tReadTweakValueTable((char*)work_buff, WorldLightmapBlend);\n\n\t{\n#include \"shaders/obj/neoWorldVC_frag.inc\"\n#include \"shaders/obj/default_UV2_vert.inc\"\n\tconst char *vs[] = { shaderDecl, header_vert_src, default_UV2_vert_src, nil };\n\tconst char *fs[] = { shaderDecl, header_frag_src, neoWorldVC_frag_src, nil };\n\tneoWorldShader = Shader::create(vs, fs);\n\tassert(neoWorldShader);\n\t}\n\n\n\trw::gl3::ObjPipeline *pipe = rw::gl3::ObjPipeline::create();\n\tpipe->instanceCB = rw::gl3::defaultInstanceCB;\n\tpipe->uninstanceCB = nil;\n\tpipe->renderCB = worldRenderCB;\n\tworldPipe = pipe;\n}\n\nvoid\nDestroyWorldPipe(void)\n{\n\tneoWorldShader->destroy();\n\tneoWorldShader = nil;\n\n\t((rw::gl3::ObjPipeline*)worldPipe)->destroy();\n\tworldPipe = nil;\n}\n\n\n\n\n/*\n * Neo Gloss pipe\n */\n\nrw::gl3::Shader *neoGlossShader;\n\nstatic void\nglossRenderCB(rw::Atomic *atomic, rw::gl3::InstanceDataHeader *header)\n{\n\tusing namespace rw;\n\tusing namespace rw::gl3;\n\n\tworldRenderCB(atomic, header);\n\tif(!GlossEnable)\n\t\treturn;\n\n\tMaterial *m;\n\n\tsetupVertexInput(header);\n\n\tInstanceData *inst = header->inst;\n\trw::int32 n = header->numMeshes;\n\n\tneoGlossShader->use();\n\n\tV3d eyePos = rw::engine->currentCamera->getFrame()->getLTM()->pos;\n\tglUniform3fv(U(u_eye), 1, (float*)&eyePos);\n\tfloat reflProps[4];\n\treflProps[0] = GlossMult;\n\treflProps[1] = 0.0f;\n\treflProps[2] = 0.0f;\n\treflProps[3] = 0.0f;\n\tglUniform4fv(U(u_reflProps), 1, reflProps);\n\n\tSetRenderState(VERTEXALPHA, TRUE);\n\tSetRenderState(SRCBLEND, BLENDONE);\n\tSetRenderState(DESTBLEND, BLENDONE);\n\tSetRenderState(ZWRITEENABLE, FALSE);\n\tSetRenderState(ALPHATESTFUNC, ALPHAALWAYS);\n\n\twhile(n--){\n\t\tm = inst->material;\n\n\t\tRGBA color = { 255, 255, 255, m->color.alpha };\n\t\tsetMaterial(color, m->surfaceProps);\n\n\t\tif(m->texture){\n\t\t\tTexture *tex = GetGlossTex(m);\n\t\t\tif(tex){\n\t\t\t\tsetTexture(0, tex);\n\t\t\t\tdrawInst(header, inst);\n\t\t\t}\n\t\t}\n\t\tinst++;\n\t}\n\n\tSetRenderState(ZWRITEENABLE, TRUE);\n\tSetRenderState(ALPHATESTFUNC, ALPHAGREATEREQUAL);\n\tSetRenderState(SRCBLEND, BLENDSRCALPHA);\n\tSetRenderState(DESTBLEND, BLENDINVSRCALPHA);\n\n\tteardownVertexInput(header);\n}\n\nvoid\nCreateGlossPipe(void)\n{\n\tusing namespace rw;\n\tusing namespace rw::gl3;\n\n\t{\n#include \"shaders/obj/neoGloss_frag.inc\"\n#include \"shaders/obj/neoGloss_vert.inc\"\n\tconst char *vs[] = { shaderDecl, header_vert_src, neoGloss_vert_src, nil };\n\tconst char *fs[] = { shaderDecl, header_frag_src, neoGloss_frag_src, nil };\n\tneoGlossShader = Shader::create(vs, fs);\n\tassert(neoGlossShader);\n\t}\n\n\trw::gl3::ObjPipeline *pipe = rw::gl3::ObjPipeline::create();\n\tpipe->instanceCB = rw::gl3::defaultInstanceCB;\n\tpipe->uninstanceCB = nil;\n\tpipe->renderCB = glossRenderCB;\n\tglossPipe = pipe;\n}\n\nvoid\nDestroyGlossPipe(void)\n{\n\tneoGlossShader->destroy();\n\tneoGlossShader = nil;\n\n\t((rw::gl3::ObjPipeline*)glossPipe)->destroy();\n\tglossPipe = nil;\n}\n\n\n\n/*\n * Neo Rim pipes\n */\n\nrw::gl3::Shader *neoRimShader;\nrw::gl3::Shader *neoRimSkinShader;\n\nstatic void\nuploadRimData(bool enable)\n{\n\tusing namespace rw;\n\tusing namespace rw::gl3;\n\n\tV3d viewVec = rw::engine->currentCamera->getFrame()->getLTM()->at;\n\tglUniform3fv(U(u_viewVec), 1, (float*)&viewVec);\n\tfloat rimData[4];\n\trimData[0] = Offset.Get();\n\trimData[1] = Scale.Get();\n\tif(enable)\n\t\trimData[2] = Scaling.Get()*RimlightMult;\n\telse\n\t\trimData[2] = 0.0f;\n\trimData[3] = 0.0f;\n\tglUniform3fv(U(u_rimData), 1, rimData);\n\tColor col = RampStart.Get();\n\tglUniform4fv(U(u_rampStart), 1, (float*)&col);\n\tcol = RampEnd.Get();\n\tglUniform4fv(U(u_rampEnd), 1, (float*)&col);\n}\n\nstatic void\nrimSkinRenderCB(rw::Atomic *atomic, rw::gl3::InstanceDataHeader *header)\n{\n\tusing namespace rw;\n\tusing namespace rw::gl3;\n\n\tif(!RimlightEnable){\n\t\tgl3::skinRenderCB(atomic, header);\n\t\treturn;\n\t}\n\n\tMaterial *m;\n\n\trw::uint32 flags = atomic->geometry->flags;\n\tsetWorldMatrix(atomic->getFrame()->getLTM());\n\tlightingCB(atomic);\n\n\tsetupVertexInput(header);\n\n\tInstanceData *inst = header->inst;\n\trw::int32 n = header->numMeshes;\n\n\tneoRimSkinShader->use();\n\n\tuploadRimData(atomic->geometry->flags & Geometry::LIGHT);\n\n\tuploadSkinMatrices(atomic);\n\n\twhile(n--){\n\t\tm = inst->material;\n\n\t\tsetMaterial(flags, m->color, m->surfaceProps);\n\n\t\tsetTexture(0, m->texture);\n\n\t\trw::SetRenderState(VERTEXALPHA, inst->vertexAlpha || m->color.alpha != 0xFF);\n\n\t\tdrawInst(header, inst);\n\t\tinst++;\n\t}\n\tteardownVertexInput(header);\n}\n\nstatic void\nrimRenderCB(rw::Atomic *atomic, rw::gl3::InstanceDataHeader *header)\n{\n\tusing namespace rw;\n\tusing namespace rw::gl3;\n\n\tif(!RimlightEnable){\n\t\tgl3::defaultRenderCB(atomic, header);\n\t\treturn;\n\t}\n\n\tMaterial *m;\n\n\trw::uint32 flags = atomic->geometry->flags;\n\tsetWorldMatrix(atomic->getFrame()->getLTM());\n\tlightingCB(atomic);\n\n\tsetupVertexInput(header);\n\n\tInstanceData *inst = header->inst;\n\trw::int32 n = header->numMeshes;\n\n\tneoRimShader->use();\n\n\tuploadRimData(atomic->geometry->flags & Geometry::LIGHT);\n\n\twhile(n--){\n\t\tm = inst->material;\n\n\t\tsetMaterial(flags, m->color, m->surfaceProps);\n\n\t\tsetTexture(0, m->texture);\n\n\t\trw::SetRenderState(VERTEXALPHA, inst->vertexAlpha || m->color.alpha != 0xFF);\n\n\t\tdrawInst(header, inst);\n\t\tinst++;\n\t}\n\tteardownVertexInput(header);\n}\n\nvoid\nCreateRimLightPipes(void)\n{\n\tusing namespace rw::gl3;\n\n\tif(CFileMgr::LoadFile(\"neo/rimTweakingTable.dat\", work_buff, sizeof(work_buff), \"r\") <= 0)\n\t\tprintf(\"Error: couldn't open 'neo/rimTweakingTable.dat'\\n\");\n\telse{\n\t\tchar *fp = (char*)work_buff;\n\t\tfp = ReadTweakValueTable(fp, RampStart);\n\t\tfp = ReadTweakValueTable(fp, RampEnd);\n\t\tfp = ReadTweakValueTable(fp, Offset);\n\t\tfp = ReadTweakValueTable(fp, Scale);\n\t\tfp = ReadTweakValueTable(fp, Scaling);\n\t}\n\n\t{\n#include \"shaders/obj/simple_frag.inc\"\n#include \"shaders/obj/neoRimSkin_vert.inc\"\n\tconst char *vs[] = { shaderDecl, header_vert_src, neoRimSkin_vert_src, nil };\n\tconst char *fs[] = { shaderDecl, header_frag_src, simple_frag_src, nil };\n\tneoRimSkinShader = Shader::create(vs, fs);\n\tassert(neoRimSkinShader);\n\t}\n\n\t{\n#include \"shaders/obj/simple_frag.inc\"\n#include \"shaders/obj/neoRim_vert.inc\"\n\tconst char *vs[] = { shaderDecl, header_vert_src, neoRim_vert_src, nil };\n\tconst char *fs[] = { shaderDecl, header_frag_src, simple_frag_src, nil };\n\tneoRimShader = Shader::create(vs, fs);\n\tassert(neoRimShader);\n\t}\n\n\n\trw::gl3::ObjPipeline *pipe = rw::gl3::ObjPipeline::create();\n\tpipe->instanceCB = rw::gl3::defaultInstanceCB;\n\tpipe->uninstanceCB = nil;\n\tpipe->renderCB = rimRenderCB;\n\trimPipe = pipe;\n\n\tpipe = rw::gl3::ObjPipeline::create();\n\tpipe->instanceCB = rw::gl3::skinInstanceCB;\n\tpipe->uninstanceCB = nil;\n\tpipe->renderCB = rimSkinRenderCB;\n\trimSkinPipe = pipe;\n}\n\nvoid\nDestroyRimLightPipes(void)\n{\n\tneoRimShader->destroy();\n\tneoRimShader = nil;\n\n\tneoRimSkinShader->destroy();\n\tneoRimSkinShader = nil;\n\n\t((rw::gl3::ObjPipeline*)rimPipe)->destroy();\n\trimPipe = nil;\n\n\t((rw::gl3::ObjPipeline*)rimSkinPipe)->destroy();\n\trimSkinPipe = nil;\n}\n\n\n\nvoid\nCustomPipeRegisterGL(void)\n{\n\tu_viewVec = rw::gl3::registerUniform(\"u_viewVec\");\n\tu_rampStart = rw::gl3::registerUniform(\"u_rampStart\");\n\tu_rampEnd = rw::gl3::registerUniform(\"u_rampEnd\");\n\tu_rimData = rw::gl3::registerUniform(\"u_rimData\");\n\n\tu_lightMap = rw::gl3::registerUniform(\"u_lightMap\");\n\n\tu_eye = rw::gl3::registerUniform(\"u_eye\");\n\tu_reflProps = rw::gl3::registerUniform(\"u_reflProps\");\n\tu_specDir = rw::gl3::registerUniform(\"u_specDir\");\n\tu_specColor = rw::gl3::registerUniform(\"u_specColor\");\n}\n\n\n}\n\n#endif\n\n#ifdef NEW_RENDERER\n#ifndef LIBRW\n#error \"Need librw for NEW_PIPELINES\"\n#endif\n\nnamespace WorldRender\n{\n\nstruct BuildingInst\n{\n\trw::Matrix matrix;\n\trw::gl3::InstanceDataHeader *instHeader;\n\tuint8 fadeAlpha;\n\tbool lighting;\n};\nBuildingInst blendInsts[3][2000];\nint numBlendInsts[3];\n\nstatic RwRGBAReal black;\n\nstatic bool\nIsTextureTransparent(RwTexture *tex)\n{\n\tif(tex == nil || tex->raster == nil)\n\t\treturn false;\n\treturn PLUGINOFFSET(rw::gl3::Gl3Raster, tex->raster, rw::gl3::nativeRasterOffset)->hasAlpha;\n}\n\n// Render all opaque meshes and put atomics that needs blending\n// into the deferred list.\nvoid\nAtomicFirstPass(RpAtomic *atomic, int pass)\n{\n\tusing namespace rw;\n\tusing namespace rw::gl3;\n\n\tBuildingInst *building = &blendInsts[pass][numBlendInsts[pass]];\n\n\tatomic->getPipeline()->instance(atomic);\n\tbuilding->instHeader = (gl3::InstanceDataHeader*)atomic->geometry->instData;\n\tassert(building->instHeader != nil);\n\tassert(building->instHeader->platform == PLATFORM_GL3);\n\tbuilding->fadeAlpha = 255;\n\tbuilding->lighting = !!(atomic->geometry->flags & rw::Geometry::LIGHT);\n\trw::uint32 flags = atomic->geometry->flags;\n\n\tWorldLights lights;\n\tlights.numAmbients = 1;\n\tlights.numDirectionals = 0;\n\tlights.numLocals = 0;\n\tif(building->lighting)\n\t\tlights.ambient = pAmbient->color;\n\telse\n\t\tlights.ambient = black;\n\n\tbool setupDone = false;\n\tbool defer = false;\n\tbuilding->matrix = *atomic->getFrame()->getLTM();\n\n\tInstanceData *inst = building->instHeader->inst;\n\tfor(rw::uint32 i = 0; i < building->instHeader->numMeshes; i++, inst++){\n\t\tMaterial *m = inst->material;\n\n\t\tif(inst->vertexAlpha || m->color.alpha != 255 ||\n\t\t   IsTextureTransparent(m->texture)){\n\t\t\tdefer = true;\n\t\t\tcontinue;\n\t\t}\n\n\t\t// alright we're rendering this atomic\n\t\tif(!setupDone){\n\t\t\tdefaultShader->use();\n\t\t\tsetWorldMatrix(&building->matrix);\n\t\t\tsetupVertexInput(building->instHeader);\n\t\t\tsetLights(&lights);\n\t\t\tsetupDone = true;\n\t\t}\n\n\t\tsetMaterial(flags, m->color, m->surfaceProps);\n\n\t\tsetTexture(0, m->texture);\n\n\t\tdrawInst(building->instHeader, inst);\n\t}\n\tteardownVertexInput(building->instHeader);\n\tif(defer)\n\t\tnumBlendInsts[pass]++;\n}\n\nvoid\nAtomicFullyTransparent(RpAtomic *atomic, int pass, int fadeAlpha)\n{\n\tusing namespace rw;\n\tusing namespace rw::gl3;\n\n\tBuildingInst *building = &blendInsts[pass][numBlendInsts[pass]];\n\n\tatomic->getPipeline()->instance(atomic);\n\tbuilding->instHeader = (gl3::InstanceDataHeader*)atomic->geometry->instData;\n\tassert(building->instHeader != nil);\n\tassert(building->instHeader->platform == PLATFORM_GL3);\n\tbuilding->fadeAlpha = fadeAlpha;\n\tbuilding->lighting = !!(atomic->geometry->flags & rw::Geometry::LIGHT);\n\tbuilding->matrix = *atomic->getFrame()->getLTM();\n\tnumBlendInsts[pass]++;\n}\n\nvoid\nRenderBlendPass(int pass)\n{\n\tusing namespace rw;\n\tusing namespace rw::gl3;\n\n\tdefaultShader->use();\n\tWorldLights lights;\n\tlights.numAmbients = 1;\n\tlights.numDirectionals = 0;\n\tlights.numLocals = 0;\n\n\tint i;\n\tfor(i = 0; i < numBlendInsts[pass]; i++){\n\t\tBuildingInst *building = &blendInsts[pass][i];\n\n\t\tsetupVertexInput(building->instHeader);\n\t\tsetWorldMatrix(&building->matrix);\n\t\tif(building->lighting)\n\t\t\tlights.ambient = pAmbient->color;\n\t\telse\n\t\t\tlights.ambient = black;\n\t\tsetLights(&lights);\n\n\t\tInstanceData *inst = building->instHeader->inst;\n\t\tfor(rw::uint32 j = 0; j < building->instHeader->numMeshes; j++, inst++){\n\t\t\tMaterial *m = inst->material;\n\t\t\tif(!inst->vertexAlpha && m->color.alpha == 255 && !IsTextureTransparent(m->texture) && building->fadeAlpha == 255)\n\t\t\t\tcontinue;\t// already done this one\n\n\t\t\trw::RGBA color = m->color;\n\t\t\tcolor.alpha = (color.alpha * building->fadeAlpha)/255;\n\t\t\tsetMaterial(color, m->surfaceProps);\t// always modulate here\n\n\t\t\tsetTexture(0, m->texture);\n\n\t\t\tdrawInst(building->instHeader, inst);\n\t\t}\n\t\tteardownVertexInput(building->instHeader);\n\t}\n}\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "src/extras/debugmenu.cpp",
    "content": "#include \"common.h\"\n#ifdef DEBUGMENU\n#include \"RwHelper.h\"\n#include \"Pad.h\"\n#include \"ControllerConfig.h\"\n#include \"Timer.h\"\n#include \"rtcharse.h\"\n#include \"re3_inttypes.h\"\n#include \"debugmenu.h\"\n#include <new>\n\n#ifdef _WIN32\n#define snprintf _snprintf\n\n#define strdup _strdup\n#endif\n\n\n// Font stuff\nstruct Pt\n{\n\tint x, y;\n};\n\nenum MenuFontStyle\n{\n\tMENUFONT_NORMAL,\n\tMENUFONT_SEL_ACTIVE,\n\tMENUFONT_SEL_INACTIVE,\n\tMENUFONT_MOUSE\n};\n\nRtCharset *fontStyles[4];\nRtCharsetDesc fontDesc;\nint fontscale = 1;\t// not supported right now\n\nPt\nfontGetStringSize(const char *s)\n{\n\tPt sz = { 0, 0 };\n\tint x;\n\tchar c;\n\tsz.y = fontDesc.height*fontscale;\t// always assume one line;\n\tx = 0;\n\twhile(c = *s++){\n\t\tif(c == '\\n'){\n\t\t\tsz.y += fontDesc.height*fontscale;\n\t\t\tif(x > sz.x)\n\t\t\t\tsz.x = x;\n\t\t\tx = 0;\n\t\t}else\n\t\t\tx += fontDesc.width*fontscale;\n\t}\n\tif(x > sz.x)\n\t\tsz.x = x;\n\treturn sz;\n}\n\nPt\nfontPrint(const char *s, float x, float y, int style)\n{\n\tRtCharsetPrintBuffered(fontStyles[style], s, x, y, false);\n\treturn fontGetStringSize(s);\n}\n\nint\nfontGetLen(int len)\n{\n\treturn len*fontDesc.width*fontscale;\n}\n\n\nvoid\ncreateMenuFont(void)\n{\n\tOpenCharsetSafe();\n\n\tRwRGBA fg_normal = { 255, 255, 255, 255 };\n\tRwRGBA bg_normal = { 255, 255, 255, 0 };\n\tfontStyles[MENUFONT_NORMAL] = RtCharsetCreate(&fg_normal, &bg_normal);\n\tassert(fontStyles[MENUFONT_NORMAL]);\n\n\tRwRGBA fg_sel_active = { 200, 200, 200, 255 };\n\tRwRGBA bg_sel_active = { 132, 132, 132, 255 };\n\tfontStyles[MENUFONT_SEL_ACTIVE] = RtCharsetCreate(&fg_sel_active, &bg_sel_active);\n\tassert(fontStyles[MENUFONT_SEL_ACTIVE]);\n\n\tRwRGBA fg_sel_inactive = { 200, 200, 200, 255 };\n\tRwRGBA bg_sel_inactive = { 200, 200, 200, 0 };\n\tfontStyles[MENUFONT_SEL_INACTIVE] = RtCharsetCreate(&fg_sel_inactive, &bg_sel_inactive);\n\tassert(fontStyles[MENUFONT_SEL_INACTIVE]);\n\n\tRwRGBA fg_mouse = { 255, 255, 255, 255 };\n\tRwRGBA bg_mouse = { 132, 132, 132, 255 };\n\tfontStyles[MENUFONT_MOUSE] = RtCharsetCreate(&fg_mouse, &bg_mouse);\n\tassert(fontStyles[MENUFONT_MOUSE]);\n\n\tRtCharsetGetDesc(fontStyles[MENUFONT_NORMAL], &fontDesc);\n}\n\nvoid\ndestroyMenuFont(void)\n{\n\tRtCharsetDestroy(fontStyles[MENUFONT_NORMAL]);\n\tfontStyles[MENUFONT_NORMAL] = nil;\n\tRtCharsetDestroy(fontStyles[MENUFONT_SEL_ACTIVE]);\n\tfontStyles[MENUFONT_SEL_ACTIVE] = nil;\n\tRtCharsetDestroy(fontStyles[MENUFONT_SEL_INACTIVE]);\n\tfontStyles[MENUFONT_SEL_INACTIVE] = nil;\n\tRtCharsetDestroy(fontStyles[MENUFONT_MOUSE]);\n\tfontStyles[MENUFONT_MOUSE] = nil;\n}\n\n\n\n\n\n\nenum EntryType\n{\n\tMENUEMPTY = 0,\n\tMENUSUB,\n\tMENUVAR,\n\n\tMENUVAR_INT,\n\tMENUVAR_FLOAT,\n\tMENUVAR_CMD,\n\n\tMENUSCROLL\t// dummy\n};\n\nstruct Menu\n{\n\tMenu *parent;\n\tRwRect r;\n\tMenuEntry *entries;\n\tint numEntries;\n\tint maxNameWidth, maxValWidth;\n\n\tMenuEntry *findEntry(const char *entryname);\n\tvoid insertEntrySorted(MenuEntry *entry);\n\tvoid appendEntry(MenuEntry *entry);\n\n\tbool isScrollingUp, isScrollingDown;\n\tint scrollStart;\n\tint numVisible;\n\tRwRect scrollUpR, scrollDownR;\n\tvoid scroll(int off);\n\n\tint selection;\n\tMenuEntry *selectedEntry;\t// updated by update\n\tvoid changeSelection(int newsel);\n\tvoid changeSelection(MenuEntry *e);\n\n\tvoid update(void);\n\tvoid draw(void);\n\tMenu(void){ memset(this, 0, sizeof(Menu)); }\n\t~Menu(void);\n};\nextern Menu toplevel;\n\nstruct MenuEntry_Sub : MenuEntry\n{\n\tMenu *submenu;\n\n\tMenuEntry_Sub(const char *name, Menu *menu);\n\t~MenuEntry_Sub(void) { delete submenu; }\n};\n\nstruct MenuEntry_Var : MenuEntry\n{\n\tint maxvallen;\n\tint vartype;\n\tbool wrapAround;\n\n\tvirtual void processInput(bool mouseOver, bool selected) = 0;\n\tint getValWidth(void) { return maxvallen; }\n\tvirtual void getValStr(char *str, int len) = 0;\n\tMenuEntry_Var(const char *name, int type);\n};\n\nstruct MenuEntry_Int : MenuEntry_Var\n{\n\tvirtual void setStrings(const char **strings) = 0;\n\tvirtual int findStringLen(void) = 0;\n\tMenuEntry_Int(const char *name);\n};\n\n#define INTTYPES \\\n\tX(Int8, int8, 4, \"%4\" PRId8) \\\n\tX(Int16, int16, 6, \"%6\" PRId16) \\\n\tX(Int32, int32, 11, \"%11\" PRId32) \\\n\tX(Int64, int64, 21, \"%21\" PRId64) \\\n\tX(UInt8, uint8, 4, \"%4\" PRIu8) \\\n\tX(UInt16, uint16, 6, \"%6\" PRIu16) \\\n\tX(UInt32, uint32, 11, \"%11\" PRIu32) \\\n\tX(UInt64, uint64, 21, \"%21\" PRIu64)\n#define FLOATTYPES \\\n\tX(Float32, float, 11, \"%11.3f\") \\\n\tX(Float64, double, 11, \"%11.3lf\")\n\n#define X(NAME, TYPE, MAXLEN, FMT) \\\nstruct MenuEntry_##NAME : MenuEntry_Int\t\t\t\t\t\t\t\t\t\t\t\t\t\t       \\\n{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t       \\\n\tTYPE *variable;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t       \\\n\tTYPE lowerBound, upperBound;\t\t\t\t\t\t\t\t\t\t\t\t\t\t       \\\n\tTYPE step;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t       \\\n\tTriggerFunc triggerFunc;\t\t\t\t\t\t\t\t\t\t\t\t\t\t       \\\n\tconst char *fmt;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t       \\\n\tconst char **strings;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t       \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t       \\\n\tvoid processInput(bool mouseOver, bool selected);\t\t\t\t\t\t\t\t\t\t\t\t\t\t       \\\n\tvoid getValStr(char *str, int len);\t\t\t\t\t\t\t\t\t\t\t\t\t       \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t       \\\n\tvoid setStrings(const char **strings);\t\t\t\t\t\t\t\t\t\t\t\t\t       \\\n\tint findStringLen(void);\t\t\t\t\t\t\t\t\t\t\t\t\t\t       \\\n\tMenuEntry_##NAME(const char *name, TYPE *ptr, TriggerFunc triggerFunc, TYPE step, TYPE lowerBound, TYPE upperBound, const char **strings);     \\\n};\nINTTYPES\n#undef X\n\n#define X(NAME, TYPE, MAXLEN, FMT) \\\nstruct MenuEntry_##NAME : MenuEntry_Var\t\t\t\t\t\t\t\t\t\t\t\t \\\n{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \\\n\tTYPE *variable;\t\t\t\t\t\t\t\t\t\t\t\t\t\t \\\n\tTYPE lowerBound, upperBound;\t\t\t\t\t\t\t\t\t\t\t\t \\\n\tTYPE step;\t\t\t\t\t\t\t\t\t\t\t\t\t\t \\\n\tTriggerFunc triggerFunc;\t\t\t\t\t\t\t\t\t\t\t\t \\\n\tconst char *fmt;\t\t\t\t\t\t\t\t\t\t\t\t\t \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \\\n\tvoid processInput(bool mouseOver, bool selected);\t\t\t\t\t\t\t\t\t\t\t\t \\\n\tvoid getValStr(char *str, int len);\t\t\t\t\t\t\t\t\t\t\t \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \\\n\tMenuEntry_##NAME(const char *name, TYPE *ptr, TriggerFunc triggerFunc, TYPE step, TYPE lowerBound, TYPE upperBound);\t \\\n};\nFLOATTYPES\n#undef X\n\nstruct MenuEntry_Cmd : MenuEntry_Var\n{\n\tTriggerFunc triggerFunc;\n\n\tvoid processInput(bool mouseOver, bool selected);\n\tvoid getValStr(char *str, int len);\n\n\tMenuEntry_Cmd(const char *name, TriggerFunc triggerFunc);\n};\n\n\nMenu *findMenu(const char *name);\n\n\n\n#define MUHKEYS \\\n\tX(leftjustdown, rsLEFT) \\\n\tX(rightjustdown, rsRIGHT) \\\n\tX(upjustdown, rsUP) \\\n\tX(downjustdown, rsDOWN) \\\n\tX(pgupjustdown, rsPGUP) \\\n\tX(pgdnjustdown, rsPGDN)\n\n#define MUHBUTTONS \\\n\tX(button1justdown, 1) \\\n\tX(button2justdown, 2) \\\n\tX(button3justdown, 3)\n\n#define REPEATDELAY 700\n#define REPEATINTERVAL 50\n#define X(var, keycode) static int var;\nMUHKEYS\n#undef X\nstatic int downtime;\nstatic int repeattime;\nstatic int lastkeydown;\nstatic int *keyptr;\n\nstatic int buttondown[3];\nstatic int lastbuttondown;\nstatic int *buttonptr;\nstatic int button1justdown, button2justdown, button3justdown;\nstatic float mouseX, mouseY;\n\nstatic int menuOn;\nstatic int menuInitialized;\nstatic int screenWidth, screenHeight;\nstatic RwRaster *cursor, *arrow;\n\nstatic int firstBorder = 10;\nstatic int topBorder = 40;\t//10;\nstatic int leading = 4;\nstatic int gap = 10;\nstatic int minwidth = 100;\n\nvoid drawMouse(void);\nvoid drawArrow(RwRect r, int direction, int style);\n\nMenu toplevel;\nMenu *activeMenu = &toplevel;\nMenu *deepestMenu = &toplevel;\nMenu *mouseOverMenu;\nMenuEntry *mouseOverEntry;\nMenuEntry scrollUpEntry(\"SCROLLUP\"), scrollDownEntry(\"SCROLLDOWN\");\t// dummies\n\n\n#define KEYJUSTDOWN(k) ControlsManager.GetIsKeyboardKeyJustDown((RsKeyCodes)k)\n#define KEYDOWN(k) ControlsManager.GetIsKeyboardKeyDown((RsKeyCodes)k)\n#define CTRLJUSTDOWN(key) \\\n\t       ((KEYDOWN(rsLCTRL) || KEYDOWN(rsRCTRL)) && KEYJUSTDOWN((RsKeyCodes)key) || \\\n\t        (KEYJUSTDOWN(rsLCTRL) || KEYJUSTDOWN(rsRCTRL)) && KEYDOWN((RsKeyCodes)key))\n#define CTRLDOWN(key) ((KEYDOWN(rsLCTRL) || KEYDOWN(rsRCTRL)) && KEYDOWN((RsKeyCodes)key))\n\n\nbool\nisMouseInRect(RwRect r)\n{\n\treturn (mouseX >= r.x && mouseX < r.x+r.w &&\n\t\tmouseY >= r.y && mouseY < r.y+r.h);\n}\n\n/*\n * MenuEntry\n */\n\nMenuEntry::MenuEntry(const char *name)\n{\n\tthis->type = MENUEMPTY;\n\tthis->name = strdup(name);\n\tthis->next = nil;\n\tthis->menu = nil;\n}\n\nMenuEntry_Sub::MenuEntry_Sub(const char *name, Menu *menu)\n: MenuEntry(name)\n{\n\tthis->type = MENUSUB;\n\tthis->submenu = menu;\n}\n\nMenuEntry_Var::MenuEntry_Var(const char *name, int vartype)\n: MenuEntry(name)\n{\n\tthis->type = MENUVAR;\n\tthis->vartype = vartype;\n\tthis->maxvallen = 0;\n\tthis->wrapAround = false;\n}\n\n/*\n * *****************************\n * MenuEntry_Int\n * *****************************\n */\n\nMenuEntry_Int::MenuEntry_Int(const char *name)\n: MenuEntry_Var(name, MENUVAR_INT)\n{\n}\n\n#define X(NAME, TYPE, MAXLEN, FMT) \\\nint\t\t\t\t\t\t\t\t     \\\nMenuEntry_##NAME::findStringLen(void){\t\t\t\t     \\\n\tTYPE i;\t\t\t\t\t\t\t     \\\n\tint len, maxlen = 0;\t\t\t\t\t     \\\n\tfor(i = this->lowerBound; i <= this->upperBound; i++){\t     \\\n\t\tlen = strlen(this->strings[i-this->lowerBound]);     \\\n\t\tif(len > maxlen)\t\t\t\t     \\\n\t\t\tmaxlen = len;\t\t\t\t     \\\n\t}\t\t\t\t\t\t\t     \\\n\treturn maxlen;\t\t\t\t\t\t     \\\n}\t\t\t\t\t\t\t\t     \\\nvoid\t\t\t\t\t\t\t\t     \\\nMenuEntry_##NAME::processInput(bool mouseOver, bool selected)\t\t\t\t     \\\n{\t\t\t\t\t\t\t\t     \\\n\tTYPE v, oldv;\t\t\t\t\t\t     \\\n\tint overflow = 0;\t\t\t\t\t     \\\n\tint underflow = 0;\t\t\t\t\t     \\\n\t\t\t\t\t\t\t\t     \\\n\tv = *this->variable;\t\t\t\t\t     \\\n\toldv = v;\t\t\t\t\t\t     \\\n\t\t\t\t\t\t\t\t     \\\n\tif((selected && leftjustdown) || (mouseOver && button3justdown)){\t\t\t\t\t     \\\n\t\tv -= this->step;\t\t\t\t     \\\n\t\tif(v > oldv)\t\t\t\t\t     \\\n\t\t\tunderflow = 1;\t\t\t\t     \\\n\t}\t\t\t\t\t\t\t     \\\n\tif((selected && rightjustdown) || (mouseOver && button1justdown)){\t\t\t\t\t     \\\n\t\tv += this->step;\t\t\t\t     \\\n\t\tif(v < oldv)\t\t\t\t\t     \\\n\t\t\toverflow = 1;\t\t\t\t     \\\n\t}\t\t\t\t\t\t\t     \\\n\tif(this->wrapAround){\t\t\t\t\t     \\\n\t\tif(v > this->upperBound || overflow) v = this->lowerBound;\t     \\\n\t\tif(v < this->lowerBound || underflow) v = this->upperBound;\t     \\\n\t}else{\t\t\t\t\t\t\t\t\t     \\\n\t\tif(v > this->upperBound || overflow) v = this->upperBound;\t     \\\n\t\tif(v < this->lowerBound || underflow) v = this->lowerBound;\t     \\\n\t}\t\t\t\t\t\t\t     \\\n\t\t\t\t\t\t\t\t     \\\n\t*this->variable = v;\t\t\t\t\t     \\\n\tif(oldv != v && this->triggerFunc)\t\t\t     \\\n\t\tthis->triggerFunc();\t\t\t\t     \\\n}\t\t\t\t\t\t\t\t     \\\nvoid\t\t\t\t\t\t\t\t\t\t\t       \\\nMenuEntry_##NAME::getValStr(char *str, int len)\t\t\t\t\t\t       \\\n{\t\t\t\t\t\t\t\t\t\t\t       \\\n\tstatic char tmp[20];\t\t\t\t\t\t\t\t       \\\n\tif(this->strings){\t\t\t\t\t\t\t\t       \\\n\t\tsnprintf(tmp, 20, \"%%%ds\", this->maxvallen);\t\t\t\t       \\\n\t\tif(*this->variable < this->lowerBound || *this->variable > this->upperBound){  \\\n\t\t\tsnprintf(str, len, \"ERROR\");\t\t\t\t\t       \\\n\t\t\treturn;\t\t\t\t\t\t\t\t       \\\n\t\t}\t\t\t\t\t\t\t\t\t       \\\n\t\tsnprintf(str, len, tmp, this->strings[*this->variable-this->lowerBound]);      \\\n\t}else\t\t\t\t\t\t\t\t\t\t       \\\n\t\tsnprintf(str, len, this->fmt, *this->variable);\t\t\t\t       \\\n}\t\t\t\t\t\t\t\t\t\t\t       \\\nvoid\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \\\nMenuEntry_##NAME::setStrings(const char **strings)\t\t\t\t\t\t\t\t\t\t\t\t\t   \\\n{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \\\n\tthis->strings = strings;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \\\n\tif(this->strings)\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \\\n\t\tthis->maxvallen = findStringLen();\t\t\t\t\t\t\t\t\t\t\t\t\t   \\\n}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \\\nMenuEntry_##NAME::MenuEntry_##NAME(const char *name, TYPE *ptr, TriggerFunc triggerFunc, TYPE step, TYPE lowerBound, TYPE upperBound, const char **strings)   \\\n: MenuEntry_Int(name)\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \\\n{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \\\n\tthis->variable = ptr;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \\\n\tthis->step = step;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \\\n\tthis->lowerBound = lowerBound;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \\\n\tthis->upperBound = upperBound;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \\\n\tthis->triggerFunc = triggerFunc;\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \\\n\tthis->maxvallen = MAXLEN;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \\\n\tthis->fmt = FMT;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \\\n\tthis->setStrings(strings);\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   \\\n}\nINTTYPES\n#undef X\n\n/*\n * *****************************\n * MenuEntry_Float\n * *****************************\n */\n\n#define X(NAME, TYPE, MAXLEN, FMT) \\\nMenuEntry_##NAME::MenuEntry_##NAME(const char *name, TYPE *ptr, TriggerFunc triggerFunc, TYPE step, TYPE lowerBound, TYPE upperBound)\t     \\\n: MenuEntry_Var(name, MENUVAR_FLOAT)\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t     \\\n{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t     \\\n\tthis->variable = ptr;\t\t\t\t\t\t\t\t\t\t\t\t\t\t     \\\n\tthis->step = step;\t\t\t\t\t\t\t\t\t\t\t\t\t\t     \\\n\tthis->lowerBound = lowerBound;\t\t\t\t\t\t\t\t\t\t\t\t\t     \\\n\tthis->upperBound = upperBound;\t\t\t\t\t\t\t\t\t\t\t\t\t     \\\n\tthis->triggerFunc = triggerFunc;\t\t\t\t\t\t\t\t\t\t\t\t     \\\n\tthis->maxvallen = MAXLEN;\t\t\t\t\t\t\t\t\t\t\t\t\t     \\\n\tthis->fmt = FMT;\t\t\t\t\t\t\t\t\t\t\t\t\t\t     \\\n}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t     \\\nvoid\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t     \\\nMenuEntry_##NAME::getValStr(char *str, int len)\t\t\t\t\t\t\t\t\t\t\t\t     \\\n{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t     \\\n\tsnprintf(str, len, this->fmt, *this->variable);\t\t\t\t\t\t\t\t\t\t\t     \\\n}\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t     \\\nvoid\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t     \\\nMenuEntry_##NAME::processInput(bool mouseOver, bool selected)\t\t\t\t\t\t\t\t\t\t\t\t\t     \\\n{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t     \\\n\tfloat v, oldv;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t     \\\n\tint overflow = 0;\t\t\t\t\t     \\\n\tint underflow = 0;\t\t\t\t\t     \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t     \\\n\tv = *this->variable;\t\t\t\t\t\t\t\t\t\t\t\t\t\t     \\\n\toldv = v;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t     \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t     \\\n\tif((selected && leftjustdown) || (mouseOver && button3justdown)){\t\t\t\t\t     \\\n\t\tv -= this->step;\t\t\t\t     \\\n\t\tif(v > oldv)\t\t\t\t\t     \\\n\t\t\tunderflow = 1;\t\t\t\t     \\\n\t}\t\t\t\t\t\t\t     \\\n\tif((selected && rightjustdown) || (mouseOver && button1justdown)){\t\t\t\t\t     \\\n\t\tv += this->step;\t\t\t\t     \\\n\t\tif(v < oldv)\t\t\t\t\t     \\\n\t\t\toverflow = 1;\t\t\t\t     \\\n\t}\t\t\t\t\t\t\t     \\\n\tif(this->wrapAround){\t\t\t\t\t     \\\n\t\tif(v > this->upperBound || overflow) v = this->lowerBound;\t     \\\n\t\tif(v < this->lowerBound || underflow) v = this->upperBound;\t     \\\n\t}else{\t\t\t\t\t\t\t\t\t     \\\n\t\tif(v > this->upperBound || overflow) v = this->upperBound;\t     \\\n\t\tif(v < this->lowerBound || underflow) v = this->lowerBound;\t     \\\n\t}\t\t\t\t\t\t\t     \\\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t     \\\n\t*this->variable = v;\t\t\t\t\t\t\t\t\t\t\t\t\t\t     \\\n\tif(oldv != v && this->triggerFunc)\t\t\t\t\t\t\t\t\t\t\t\t     \\\n\t\tthis->triggerFunc();\t\t\t\t\t\t\t\t\t\t\t\t\t     \\\n}\n\nFLOATTYPES\n#undef X\n\n/*\n * *****************************\n * MenuEntry_Cmd\n * *****************************\n */\n\nvoid\nMenuEntry_Cmd::processInput(bool mouseOver, bool selected)\n{\n\t// Don't execute on button3\n\tif(this->triggerFunc && (selected && (leftjustdown || rightjustdown) || (mouseOver && button1justdown)))\n\t\tthis->triggerFunc();\n}\n\nvoid\nMenuEntry_Cmd::getValStr(char *str, int len)\n{\n\tstrncpy(str, \"<\", len);\n}\n\nMenuEntry_Cmd::MenuEntry_Cmd(const char *name, TriggerFunc triggerFunc)\n: MenuEntry_Var(name, MENUVAR_CMD)\n{\n\tthis->maxvallen = 1;\n\tthis->triggerFunc = triggerFunc;\n}\n\n\n/*\n * *****************************\n * Menu\n * *****************************\n */\n\nvoid\nMenu::scroll(int off) {\n\tif(isScrollingUp && off < 0)\n\t\tscrollStart += off;\n\tif(isScrollingDown && off > 0)\n\t\tscrollStart += off;\n\tif(scrollStart < 0) scrollStart = 0;\n\tif(scrollStart > numEntries-numVisible) scrollStart = numEntries-numVisible;\n}\n\nvoid\nMenu::changeSelection(int newsel){\n\tselection = newsel;\n\tif(selection < 0) selection = 0;\n\tif(selection >= numEntries) selection = numEntries-1;\n\tif(selection < scrollStart) scrollStart = selection;\n\tif(selection >= scrollStart+numVisible) scrollStart = selection-numVisible+1;\n}\n\nvoid\nMenu::changeSelection(MenuEntry *sel)\n{\n\tMenuEntry *e;\n\tint i = 0;\n\tfor(e = this->entries; e; e = e->next){\n\t\tif(e == sel){\n\t\t\tthis->selection = i;\n\t\t\tthis->selectedEntry = sel;\n\t\t\tbreak;\n\t\t}\n\t\ti++;\n\t}\n}\n\n\n\nMenuEntry*\nMenu::findEntry(const char *entryname)\n{\n\tMenuEntry *m;\n\tfor(m = this->entries; m; m = m->next)\n\t\tif(strcmp(entryname, m->name) == 0)\n\t\t\treturn m;\n\treturn nil;\n}\n\nvoid\nMenu::insertEntrySorted(MenuEntry *entry)\n{\n\tMenuEntry **mp;\n\tint cmp;\n\tfor(mp = &this->entries; *mp; mp = &(*mp)->next){\n\t\tcmp = strcmp(entry->name, (*mp)->name);\n\t\tif(cmp == 0)\n\t\t\treturn;\n\t\tif(cmp < 0)\n\t\t\tbreak;\n\t}\n\tentry->next = *mp;\n\t*mp = entry;\n\tentry->menu = this;\n\tthis->numEntries++;\n}\n\nvoid\nMenu::appendEntry(MenuEntry *entry)\n{\n\tMenuEntry **mp;\n\tfor(mp = &this->entries; *mp; mp = &(*mp)->next);\n\tentry->next = *mp;\n\t*mp = entry;\n\tentry->menu = this;\n\tthis->numEntries++;\n}\n\nvoid\nMenu::update(void)\n{\n\tint i;\n\tint x, y;\n\tPt sz;\n\tMenuEntry *e;\n\tint onscreen;\n\tx = this->r.x;\n\ty = this->r.y + 18;\n\tint end = this->r.y+this->r.h - 18;\n\tthis->numVisible = 0;\n\n\tdeepestMenu = this;\n\n\tint bottomy = end;\n\tonscreen = 1;\n\ti = 0;\n\tthis->maxNameWidth = 0;\n\tthis->maxValWidth = 0;\n\tthis->isScrollingUp = this->scrollStart > 0;\n\tthis->isScrollingDown = false;\n\tthis->selectedEntry = nil;\n\tfor(e = this->entries; e; e = e->next){\n\t\tsz = fontGetStringSize(e->name);\n\t\te->r.x = x;\n\t\te->r.y = y;\n\t\te->r.w = sz.x;\n\t\te->r.h = sz.y;\n\n\t\tif(i == this->selection)\n\t\t\tthis->selectedEntry = e;\n\n\t\tif(i >= this->scrollStart)\n\t\t\ty += sz.y + leading*fontscale;\n\t\tif(y >= end){\n\t\t\tthis->isScrollingDown = true;\n\t\t\tonscreen = 0;\n\t\t}else\n\t\t\tbottomy = y;\n\t\tif(i >= this->scrollStart && onscreen)\n\t\t\tthis->numVisible++;\n\n\t\tif(e->type == MENUVAR){\n\t\t\tint valwidth = fontGetLen(((MenuEntry_Var*)e)->getValWidth());\n\t\t\tif(valwidth > maxValWidth)\n\t\t\t\tmaxValWidth = valwidth;\n\t\t}\n\t\tif(e->r.w > maxNameWidth)\n\t\t\tmaxNameWidth = e->r.w;\n\t\ti++;\n\t}\n\tif(this->r.w < maxNameWidth + maxValWidth + gap*fontscale)\n\t\tthis->r.w = maxNameWidth + maxValWidth + gap*fontscale;\n\n\tthis->scrollUpR = this->r;\n\tthis->scrollUpR.h = 16;\n\tthis->scrollDownR = this->scrollUpR;\n\tthis->scrollDownR.y = bottomy;\n\n\t// Update active submenu\n\tif(this->selectedEntry && this->selectedEntry->type == MENUSUB){\n\t\tMenu *submenu = ((MenuEntry_Sub*)this->selectedEntry)->submenu;\n\t\tsubmenu->r.x = this->r.x+this->r.w + 10;\n\t\tsubmenu->r.y = this->r.y;\n\t\tsubmenu->r.w = minwidth;\t// update menu will expand\n\t\tsubmenu->r.h = this->r.h;\n\t\tsubmenu->update();\n\t}\n}\n\nvoid\nMenu::draw(void)\n{\n\tstatic char val[100];\n\tint i;\n\tMenuEntry *e;\n\ti = 0;\n\tfor(e = this->entries; e; e = e->next){\n\t\tif(i >= this->scrollStart+this->numVisible)\n\t\t\tbreak;\n\t\tif(i >= this->scrollStart){\n\t\t\tint style = MENUFONT_NORMAL;\n\t\t\tif(i == this->selection)\n\t\t\t\tstyle = this == activeMenu ? MENUFONT_SEL_ACTIVE : MENUFONT_SEL_INACTIVE;\n\t\t\tif(style != MENUFONT_SEL_ACTIVE && e == mouseOverEntry)\n\t\t\t\tstyle = MENUFONT_MOUSE;\n\t\t\tfontPrint(e->name, e->r.x, e->r.y, style);\n\t\t\tif(e->type == MENUVAR){\n\t\t\t\tint valw = fontGetLen(((MenuEntry_Var*)e)->getValWidth());\n\t\t\t\t((MenuEntry_Var*)e)->getValStr(val, 100);\n\t\t\t\tfontPrint(val, e->r.x+this->r.w-valw, e->r.y, style);\n\t\t\t}\n\t\t}\n\t\ti++;\n\t}\n\n\tif(this->isScrollingUp)\n\t\tdrawArrow(this->scrollUpR, -1, isMouseInRect(this->scrollUpR));\n\tif(this->isScrollingDown)\n\t\tdrawArrow(this->scrollDownR, 1, isMouseInRect(this->scrollDownR));\n\n\tif(this->selectedEntry && this->selectedEntry->type == MENUSUB)\n\t\t((MenuEntry_Sub*)this->selectedEntry)->submenu->draw();\n}\n\nMenu::~Menu(void)\n{\n\tMenuEntry *e, *next;\n\tfor(e = entries; e; e = next){\n\t\tnext = e->next;\n\t\tdelete e;\n\t}\n\tmemset(this, 0, sizeof(Menu));\n}\n\nMenu*\nfindMenu(const char *name)\n{\n\tMenu *m;\n\tMenuEntry *e;\n\tchar *tmppath = strdup(name);\n\tchar *next, *curname;\n\n\tcurname = tmppath;\n\tnext = curname;\n\n\tm = &toplevel;\n\twhile(*next){\n\t\tcurname = next;\n\t\twhile(*next){\n\t\t\tif(*next == '|'){\n\t\t\t\t*next++ = '\\0';\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tnext++;\n\t\t}\n\t\te = m->findEntry(curname);\n\t\tif(e){\n\t\t\t// return an error if the entry exists but isn't a menu\n\t\t\tif(e->type != MENUSUB){\n\t\t\t\tfree(tmppath);\n\t\t\t\treturn nil;\n\t\t\t}\n\t\t\tm = ((MenuEntry_Sub*)e)->submenu;\n\t\t}else{\n\t\t\t// Create submenus that don't exist yet\n\t\t\tMenu *submenu = new Menu();\n\t\t\tsubmenu->parent = m;\n\t\t\tMenuEntry *me = new MenuEntry_Sub(curname, submenu);\n\t\t\t// Don't sort submenus outside the toplevel menu\n\t\t\tif(m == &toplevel)\n\t\t\t\tm->insertEntrySorted(me);\n\t\t\telse\n\t\t\t\tm->appendEntry(me);\n\t\t\tm = submenu;\n\t\t}\n\t}\n\n\tfree(tmppath);\n\treturn m;\n}\n\n/*\n * ****************\n * debug menu\n * ****************\n */\n\nstatic uint8 cursorPx[] = {\n#include \"cursor.inc\"\n};\n\nstatic uint8 arrowPx[] = {\n#include \"arrow.inc\"\n};\n\nvoid\nDebugMenuInit(void)\n{\n\tcreateMenuFont();\n\n\tRwInt32 w, h, d, flags;\n\tRwImage *img = RwImageCreate(16, 16, 32);\n\tassert(img);\n\tRwImageSetPixels(img, cursorPx);\n\tRwImageSetStride(img, RwImageGetWidth(img)*4);\n\tRwImageFindRasterFormat(img, rwRASTERTYPETEXTURE, &w, &h, &d, &flags);\n\tcursor = RwRasterCreate(w, h, d, flags);\n\tcursor = RwRasterSetFromImage(cursor, img);\n\tassert(cursor);\n\tRwImageDestroy(img);\n\n\timg = RwImageCreate(32, 16, 32);\n\tassert(img);\n\tRwImageSetPixels(img, arrowPx);\n\tRwImageSetStride(img, RwImageGetWidth(img)*4);\n\tRwImageFindRasterFormat(img, rwRASTERTYPETEXTURE, &w, &h, &d, &flags);\n\tarrow = RwRasterCreate(w, h, d, flags);\n\tarrow = RwRasterSetFromImage(arrow, img);\n\tassert(arrow);\n\tRwImageDestroy(img);\n\n\n\tmenuInitialized = true;\n}\n\nvoid\nDebugMenuShutdown(void)\n{\n\tif(menuInitialized){\n\t\tdestroyMenuFont();\n\t\tRwRasterDestroy(cursor);\n\t\tcursor = nil;\n\t\tRwRasterDestroy(arrow);\n\t\tarrow = nil;\n\n\t\ttoplevel.~Menu();\n\t\tnew (&toplevel) Menu();\n\n\t\tactiveMenu = &toplevel;\n\t\tdeepestMenu = &toplevel;\n\t\tmouseOverMenu = nil;\n\t\tmouseOverEntry = nil;\n\t}\n\tmenuInitialized = false;\n}\n\nvoid\nprocessInput(void)\n{\n\tint shift = KEYDOWN(rsRSHIFT) || KEYDOWN(rsLSHIFT);\n#define X(var, keycode) var = KEYJUSTDOWN(keycode);\n\tMUHKEYS\n#undef X\n\n\t// Implement auto-repeat\n#define X(var, keycode) \\\n\tif(var){ \\\n\t\trepeattime = downtime = CTimer::GetTimeInMilliseconds(); \\\n\t\tlastkeydown = keycode; \\\n\t\tkeyptr = &var; \\\n\t}\n\tMUHKEYS\n#undef X\n\tif(lastkeydown){\n\t\tif(KEYDOWN(lastkeydown)){\n\t\t\tint curtime = CTimer::GetTimeInMilliseconds();\n\t\t\tif(curtime - downtime > REPEATDELAY){\n\t\t\t\tif(curtime - repeattime > REPEATINTERVAL){\n\t\t\t\t\trepeattime = curtime;\n\t\t\t\t\t*keyptr = 1;\n\t\t\t\t}\n\t\t\t}\n\t\t}else{\n\t\t\tlastkeydown = 0;\n\t\t}\n\t}\n\n\t// Also for mouse buttons\n#define X(var, num)\t\t\t\t\t\t\t  \\\n\tif(var){\t\t\t\t\t\t\t  \\\n\t\trepeattime = downtime = CTimer::GetTimeInMilliseconds();\t  \\\n\t\tlastbuttondown = num;\t\t\t\t\t  \\\n\t\tbuttonptr = &var;\t\t\t\t\t  \\\n\t}\n\tMUHBUTTONS\n#undef X\n\tif(lastbuttondown){\n\t\tif(buttondown[lastbuttondown-1]){\n\t\t\tint curtime = CTimer::GetTimeInMilliseconds();\n\t\t\tif(curtime - downtime > REPEATDELAY){\n\t\t\t\tif(curtime - repeattime > REPEATINTERVAL){\n\t\t\t\t\trepeattime = curtime;\n\t\t\t\t\t*buttonptr = 1;\n\t\t\t\t}\n\t\t\t}\n\t\t}else{\n\t\t\tlastbuttondown = 0;\n\t\t}\n\t}\n\n\t// Walk through all visible menus and figure out which one the mouse is over\n\tmouseOverMenu = nil;\n\tmouseOverEntry = nil;\n\tMenu *menu;\n\tfor(menu = deepestMenu; menu; menu = menu->parent)\n\t\tif(isMouseInRect(menu->r)){\n\t\t\tmouseOverMenu = menu;\n\t\t\tbreak;\n\t\t}\n\tif(mouseOverMenu){\n\t\t// Walk all visibile entries and figure out which one the mouse is over\n\t\tMenuEntry *e;\n\t\tint i = 0;\n\t\tfor(e = mouseOverMenu->entries; e; e = e->next){\n\t\t\tif(i >= mouseOverMenu->scrollStart+mouseOverMenu->numVisible)\n\t\t\t\tbreak;\n\t\t\tif(i >= mouseOverMenu->scrollStart){\n\t\t\t\tRwRect r = e->r;\n\t\t\t\tr.w = mouseOverMenu->r.w;\t// span the whole menu\n\t\t\t\tif(isMouseInRect(r)){\n\t\t\t\t\tmouseOverEntry = e;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\ti++;\n\t\t}\n\t\tif(mouseOverMenu->isScrollingUp && isMouseInRect(mouseOverMenu->scrollUpR)){\n\t\t\tmouseOverEntry = &scrollUpEntry;\n\t\t\tmouseOverEntry->r = mouseOverMenu->scrollUpR;\n\t\t\tmouseOverEntry->menu = mouseOverMenu;\n\t\t\tmouseOverEntry->type = MENUSCROLL;\n\t\t}\n\t\tif(mouseOverMenu->isScrollingDown && isMouseInRect(mouseOverMenu->scrollDownR)){\n\t\t\tmouseOverEntry = &scrollDownEntry;\n\t\t\tmouseOverEntry->r = mouseOverMenu->scrollDownR;\n\t\t\tmouseOverEntry->menu = mouseOverMenu;\n\t\t\tmouseOverEntry->type = MENUSCROLL;\n\t\t}\n\t}\n\n\tif(pgupjustdown)\n\t\tactiveMenu->scroll(shift ? -5 : -1);\n\tif(pgdnjustdown)\n\t\tactiveMenu->scroll(shift ? 5 : 1);\n\tif(downjustdown)\n\t\tactiveMenu->changeSelection(activeMenu->selection + (shift ? 5 : 1));\n\tif(upjustdown)\n\t\tactiveMenu->changeSelection(activeMenu->selection - (shift ? 5 : 1));\n\n\tif(CPad::NewMouseControllerState.WHEELUP){\n\t\tif(mouseOverMenu)\n\t\t\tactiveMenu = mouseOverMenu;\n\t\tactiveMenu->scroll(shift ? -5 : -1);\n\t}\n\tif(CPad::NewMouseControllerState.WHEELDN){\n\t\tif(mouseOverMenu)\n\t\t\tactiveMenu = mouseOverMenu;\n\t\tactiveMenu->scroll(shift ? 5 : 1);\n\t}\n\n\tif(mouseOverEntry == &scrollUpEntry){\n\t\tif(button1justdown){\n\t\t\tactiveMenu = mouseOverEntry->menu;\n\t\t\tactiveMenu->scroll(shift ? -5 : -1);\n\t\t}\n\t}\n\tif(mouseOverEntry == &scrollDownEntry){\n\t\tif(button1justdown){\n\t\t\tactiveMenu = mouseOverEntry->menu;\n\t\t\tactiveMenu->scroll(shift ? 5 : 1);\n\t\t}\n\t}\n\n\t// Have to call this before processInput below because menu entry can change\n\tif((button1justdown || button3justdown) && mouseOverEntry){\n\t\tactiveMenu = mouseOverEntry->menu;\n\t\tactiveMenu->changeSelection(mouseOverEntry);\n\t}\n\tif(KEYJUSTDOWN(rsENTER)){\n\t\tif(activeMenu->selectedEntry && activeMenu->selectedEntry->type == MENUSUB)\n\t\t\tactiveMenu = ((MenuEntry_Sub*)activeMenu->selectedEntry)->submenu;\n\t}else if(KEYJUSTDOWN(rsBACKSP)){\n\t\tif(activeMenu->parent)\n\t\t\tactiveMenu = activeMenu->parent;\n\t}else{\n\t\tif(mouseOverEntry && mouseOverEntry->type == MENUVAR)\n\t\t\t((MenuEntry_Var*)mouseOverEntry)->processInput(true, mouseOverEntry == activeMenu->selectedEntry);\n\t\tif(activeMenu->selectedEntry && activeMenu->selectedEntry->type == MENUVAR &&\n\t\t   mouseOverEntry != activeMenu->selectedEntry)\n\t\t\t((MenuEntry_Var*)activeMenu->selectedEntry)->processInput(false, true);\n\t}\n}\n\nvoid\nupdateMouse(void)\n{\n\tCPad *pad = CPad::GetPad(0);\n\tint dirX = 1;\n\tint dirY = 1;\n\n\tif(MousePointerStateHelper.bInvertHorizontally) dirX = -1;\n\tif(MousePointerStateHelper.bInvertVertically) dirY = -1;\n\n\tmouseX += pad->NewMouseControllerState.x*dirX;\n\tmouseY += pad->NewMouseControllerState.y*dirY;\n\n\tif(mouseX < 0.0f) mouseX = 0.0f;\n\tif(mouseY < 0.0f) mouseY = 0.0f;\n\tif(mouseX >= screenWidth) mouseX = screenWidth;\n\tif(mouseY >= screenHeight) mouseY = screenHeight;\n\n\tbutton1justdown = pad->NewMouseControllerState.LMB && !pad->OldMouseControllerState.LMB;\n\tbutton2justdown = pad->NewMouseControllerState.MMB && !pad->OldMouseControllerState.MMB;\n\tbutton3justdown = pad->NewMouseControllerState.RMB && !pad->OldMouseControllerState.RMB;\n\tbuttondown[0] = pad->NewMouseControllerState.LMB;\n\tbuttondown[1] = pad->NewMouseControllerState.MMB;\n\tbuttondown[2] = pad->NewMouseControllerState.RMB;\n\n\t// Zero the mouse position so the camera won't move\n\tpad->NewMouseControllerState.x = 0.0f;\n\tpad->NewMouseControllerState.y = 0.0f;\n}\n\nvoid\nDebugMenuProcess(void)\n{\n\t// We only process some input here\n\n\tCPad *pad = CPad::GetPad(0);\n\tif(CTRLJUSTDOWN('M'))\n\t\tmenuOn = !menuOn;\n\tif(!menuOn)\n\t\treturn;\n\n\tpad->DisablePlayerControls = 1;\n\t// TODO: this could happen earlier\n\tif(!menuInitialized)\n\t\tDebugMenuInit();\n\tupdateMouse();\n\n}\n\nvoid\nDebugMenuRender(void)\n{\n\tif(!menuOn)\n\t\treturn;\n\n\tRwRenderStateSet(rwRENDERSTATEZTESTENABLE, 0);\n\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE, 0);\n\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);\n\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);\n\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);\n\tRwRenderStateSet(rwRENDERSTATEFOGENABLE, 0);\n\tRwRenderStateSet(rwRENDERSTATECULLMODE, (void*)rwCULLMODECULLNONE);\n\n\tRwCamera *cam = RwCameraGetCurrentCamera();\n\tscreenWidth = RwRasterGetWidth(RwCameraGetRaster(cam));\n\tscreenHeight = RwRasterGetHeight(RwCameraGetRaster(cam));\n\n//\tif(screenHeight > 1080)\n//\t\tfontscale = 2;\n//\telse\n\t\tfontscale = 1;\n\n\tPt sz;\n\tsz = fontPrint(\"Debug Menu\", firstBorder*fontscale+30, topBorder, 0);\n\n\ttoplevel.r.x = firstBorder*fontscale;\n\ttoplevel.r.y = topBorder + sz.y + 10;\n\ttoplevel.r.w = minwidth;\t// update menu will expand\n\ttoplevel.r.h = screenHeight - 10 - toplevel.r.y;\n\ttoplevel.update();\n\ttoplevel.draw();\n\tprocessInput();\n\tRtCharsetBufferFlush();\n\n\tdrawMouse();\n}\n\n\n\nvoid\ndrawArrow(RwRect r, int direction, int style)\n{\n\tstatic RwImVertexIndex indices[] = { 0, 1, 2, 2, 1, 3 };\n\tstatic RwIm2DVertex arrowVerts[4];\n\n\tRwCamera *cam = RwCameraGetCurrentCamera();\n\tfloat recipz = 1.0f/RwCameraGetNearClipPlane(cam);\n\n\tint width = RwRasterGetWidth(arrow);\n\tint height = RwRasterGetHeight(arrow);\n\n\tint left = r.x + (r.w - width)/2;\n\tint right = left + width;\n\tint top = r.y;\n\tint bottom = r.y+r.h;\n\n\tfloat umin = HALFPX / width;\n\tfloat vmin = HALFPX / height;\n\tfloat umax = (width + HALFPX) / width;\n\tfloat vmax = (height + HALFPX) / height;\n\tif(direction < 0){\n\t\tvmin = (height - HALFPX) / height;\n\t\tvmax = -HALFPX / height;\n\t}\n\n\tif(style){\n\t\tRwIm2DVertexSetScreenX(&arrowVerts[0], r.x);\n\t\tRwIm2DVertexSetScreenY(&arrowVerts[0], r.y-1);\n\t\tRwIm2DVertexSetScreenZ(&arrowVerts[0], RwIm2DGetNearScreenZ());\n\t\tRwIm2DVertexSetCameraZ(&arrowVerts[0], RwCameraGetNearClipPlane(cam));\n\t\tRwIm2DVertexSetRecipCameraZ(&arrowVerts[0], recipz);\n\t\tRwIm2DVertexSetIntRGBA(&arrowVerts[0], 132, 132, 132, 255);\n\n\t\tRwIm2DVertexSetScreenX(&arrowVerts[1], r.x+r.w);\n\t\tRwIm2DVertexSetScreenY(&arrowVerts[1], r.y-1);\n\t\tRwIm2DVertexSetScreenZ(&arrowVerts[1], RwIm2DGetNearScreenZ());\n\t\tRwIm2DVertexSetCameraZ(&arrowVerts[1], RwCameraGetNearClipPlane(cam));\n\t\tRwIm2DVertexSetRecipCameraZ(&arrowVerts[1], recipz);\n\t\tRwIm2DVertexSetIntRGBA(&arrowVerts[1], 132, 132, 132, 255);\n\n\t\tRwIm2DVertexSetScreenX(&arrowVerts[2], r.x);\n\t\tRwIm2DVertexSetScreenY(&arrowVerts[2], r.y+r.h+1);\n\t\tRwIm2DVertexSetScreenZ(&arrowVerts[2], RwIm2DGetNearScreenZ());\n\t\tRwIm2DVertexSetCameraZ(&arrowVerts[2], RwCameraGetNearClipPlane(cam));\n\t\tRwIm2DVertexSetRecipCameraZ(&arrowVerts[2], recipz);\n\t\tRwIm2DVertexSetIntRGBA(&arrowVerts[2], 132, 132, 132, 255);\n\n\t\tRwIm2DVertexSetScreenX(&arrowVerts[3], r.x+r.w);\n\t\tRwIm2DVertexSetScreenY(&arrowVerts[3], r.y+r.h+1);\n\t\tRwIm2DVertexSetScreenZ(&arrowVerts[3], RwIm2DGetNearScreenZ());\n\t\tRwIm2DVertexSetCameraZ(&arrowVerts[3], RwCameraGetNearClipPlane(cam));\n\t\tRwIm2DVertexSetRecipCameraZ(&arrowVerts[3], recipz);\n\t\tRwIm2DVertexSetIntRGBA(&arrowVerts[3], 132, 132, 132, 255);\n\n\t\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil);\n\t\tRwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR);\n\t\tRwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, arrowVerts, 4, indices, 6);\n\t}\n\n\n\tRwIm2DVertexSetScreenX(&arrowVerts[0], left);\n\tRwIm2DVertexSetScreenY(&arrowVerts[0], top);\n\tRwIm2DVertexSetScreenZ(&arrowVerts[0], RwIm2DGetNearScreenZ());\n\tRwIm2DVertexSetCameraZ(&arrowVerts[0], RwCameraGetNearClipPlane(cam));\n\tRwIm2DVertexSetRecipCameraZ(&arrowVerts[0], recipz);\n\tRwIm2DVertexSetIntRGBA(&arrowVerts[0], 255, 255, 255, 255);\n\tRwIm2DVertexSetU(&arrowVerts[0], umin, recipz);\n\tRwIm2DVertexSetV(&arrowVerts[0], vmin, recipz);\n\n\tRwIm2DVertexSetScreenX(&arrowVerts[1], right);\n\tRwIm2DVertexSetScreenY(&arrowVerts[1], top);\n\tRwIm2DVertexSetScreenZ(&arrowVerts[1], RwIm2DGetNearScreenZ());\n\tRwIm2DVertexSetCameraZ(&arrowVerts[1], RwCameraGetNearClipPlane(cam));\n\tRwIm2DVertexSetRecipCameraZ(&arrowVerts[1], recipz);\n\tRwIm2DVertexSetIntRGBA(&arrowVerts[1], 255, 255, 255, 255);\n\tRwIm2DVertexSetU(&arrowVerts[1], umax, recipz);\n\tRwIm2DVertexSetV(&arrowVerts[1], vmin, recipz);\n\n\tRwIm2DVertexSetScreenX(&arrowVerts[2], left);\n\tRwIm2DVertexSetScreenY(&arrowVerts[2], bottom);\n\tRwIm2DVertexSetScreenZ(&arrowVerts[2], RwIm2DGetNearScreenZ());\n\tRwIm2DVertexSetCameraZ(&arrowVerts[2], RwCameraGetNearClipPlane(cam));\n\tRwIm2DVertexSetRecipCameraZ(&arrowVerts[2], recipz);\n\tRwIm2DVertexSetIntRGBA(&arrowVerts[2], 255, 255, 255, 255);\n\tRwIm2DVertexSetU(&arrowVerts[2], umin, recipz);\n\tRwIm2DVertexSetV(&arrowVerts[2], vmax, recipz);\n\n\tRwIm2DVertexSetScreenX(&arrowVerts[3], right);\n\tRwIm2DVertexSetScreenY(&arrowVerts[3], bottom);\n\tRwIm2DVertexSetScreenZ(&arrowVerts[3], RwIm2DGetNearScreenZ());\n\tRwIm2DVertexSetCameraZ(&arrowVerts[3], RwCameraGetNearClipPlane(cam));\n\tRwIm2DVertexSetRecipCameraZ(&arrowVerts[3], recipz);\n\tRwIm2DVertexSetIntRGBA(&arrowVerts[3], 255, 255, 255, 255);\n\tRwIm2DVertexSetU(&arrowVerts[3], umax, recipz);\n\tRwIm2DVertexSetV(&arrowVerts[3], vmax, recipz);\n\n\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, arrow);\n\tRwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR);\n\tRwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, arrowVerts, 4, indices, 6);\n}\n\nvoid\ndrawMouse(void)\n{\n\tstatic RwImVertexIndex indices[] = { 0, 1, 2, 2, 1, 3 };\n\tstatic RwIm2DVertex vertices[4];\n\tRwIm2DVertex *vert;\n\tRwCamera *cam;\n\tcam = RwCameraGetCurrentCamera();\n\tfloat x = mouseX;\n\tfloat y = mouseY;\n\tfloat w = RwRasterGetWidth(cursor);\n\tfloat h = RwRasterGetHeight(cursor);\n\tfloat recipz = 1.0f/RwCameraGetNearClipPlane(cam);\n\n\tfloat umin = HALFPX / w;\n\tfloat vmin = HALFPX / h;\n\tfloat umax = (w + HALFPX) / w;\n\tfloat vmax = (h + HALFPX) / h;\n\n\tvert = vertices;\n\tRwIm2DVertexSetScreenX(vert, x);\n\tRwIm2DVertexSetScreenY(vert, y);\n\tRwIm2DVertexSetScreenZ(vert, RwIm2DGetNearScreenZ());\n\tRwIm2DVertexSetCameraZ(vert, RwCameraGetNearClipPlane(cam));\n\tRwIm2DVertexSetRecipCameraZ(vert, recipz);\n\tRwIm2DVertexSetIntRGBA(vert, 255, 255, 255, 255);\n\tRwIm2DVertexSetU(vert, umin, recipz);\n\tRwIm2DVertexSetV(vert, vmin, recipz);\n\tvert++;\n\n\tRwIm2DVertexSetScreenX(vert, x+w);\n\tRwIm2DVertexSetScreenY(vert, y);\n\tRwIm2DVertexSetScreenZ(vert, RwIm2DGetNearScreenZ());\n\tRwIm2DVertexSetCameraZ(vert, RwCameraGetNearClipPlane(cam));\n\tRwIm2DVertexSetRecipCameraZ(vert, recipz);\n\tRwIm2DVertexSetIntRGBA(vert, 255, 255, 255, 255);\n\tRwIm2DVertexSetU(vert, umax, recipz);\n\tRwIm2DVertexSetV(vert, vmin, recipz);\n\tvert++;\n\n\tRwIm2DVertexSetScreenX(vert, x);\n\tRwIm2DVertexSetScreenY(vert, y+h);\n\tRwIm2DVertexSetScreenZ(vert, RwIm2DGetNearScreenZ());\n\tRwIm2DVertexSetCameraZ(vert, RwCameraGetNearClipPlane(cam));\n\tRwIm2DVertexSetRecipCameraZ(vert, recipz);\n\tRwIm2DVertexSetIntRGBA(vert, 255, 255, 255, 255);\n\tRwIm2DVertexSetU(vert, umin, recipz);\n\tRwIm2DVertexSetV(vert, vmax, recipz);\n\tvert++;\n\n\tRwIm2DVertexSetScreenX(vert, x+w);\n\tRwIm2DVertexSetScreenY(vert, y+h);\n\tRwIm2DVertexSetScreenZ(vert, RwIm2DGetNearScreenZ());\n\tRwIm2DVertexSetCameraZ(vert, RwCameraGetNearClipPlane(cam));\n\tRwIm2DVertexSetRecipCameraZ(vert, recipz);\n\tRwIm2DVertexSetIntRGBA(vert, 255, 255, 255, 255);\n\tRwIm2DVertexSetU(vert, umax, recipz);\n\tRwIm2DVertexSetV(vert, vmax, recipz);\n\tvert++;\n\n\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, cursor);\n\tRwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR);\n\tRwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, vertices, 4, indices, 6);\n}\n\n\n\n\n/*\n * Generate interfaces\n */\n\n\n#define X(NAME, TYPE, unused1, unused2) \\\nMenuEntry*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\nDebugMenuAdd##NAME(const char *path, const char *name, TYPE *ptr, TriggerFunc triggerFunc, TYPE step, TYPE lowerBound, TYPE upperBound, const char **strings)\t\\\n{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tMenu *m = findMenu(path);\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tif(m == nil)\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\treturn nil;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tMenuEntry *e = new MenuEntry_##NAME(name, ptr, triggerFunc, step, lowerBound, upperBound, strings);\t\t\t\t\t\t\t\\\n\tm->appendEntry(e);\t\t\t\t\t\t\t\\\n\treturn e;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n}\nINTTYPES\n#undef X\n\n#define X(NAME, TYPE, unused1, unused2) \\\nMenuEntry*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\nDebugMenuAdd##NAME(const char *path, const char *name, TYPE *ptr, TriggerFunc triggerFunc, TYPE step, TYPE lowerBound, TYPE upperBound)\t\\\n{\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tMenu *m = findMenu(path);\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tif(m == nil)\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\treturn nil;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tMenuEntry *e = new MenuEntry_##NAME(name, ptr, triggerFunc, step, lowerBound, upperBound);\t\t\t\t\t\t\t\t\\\n\tm->appendEntry(e);\t\t\t\t\t\t\t\\\n\treturn e;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\n}\nFLOATTYPES\n#undef X\n\nMenuEntry*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\\\nDebugMenuAddCmd(const char *path, const char *name, TriggerFunc triggerFunc)\n{\n\tMenu *m = findMenu(path);\n\tif(m == nil)\n\t\treturn nil;\n\tMenuEntry *e = new MenuEntry_Cmd(name, triggerFunc);\n\tm->appendEntry(e);\n\treturn e;\n}\n\nvoid\nDebugMenuEntrySetWrap(MenuEntry *e, bool wrap)\n{\n\tif(e && e->type == MENUVAR)\n\t\t((MenuEntry_Var*)e)->wrapAround = wrap;\n}\n\nvoid\nDebugMenuEntrySetStrings(MenuEntry *e, const char **strings)\n{\n\tif(e && e->type == MENUVAR_INT)\n\t\t((MenuEntry_Int*)e)->setStrings(strings);\n}\n\nvoid\nDebugMenuEntrySetAddress(MenuEntry *e, void *addr)\n{\n\tif(e && e->type == MENUVAR){\n\t\tMenuEntry_Var *ev = (MenuEntry_Var*)e;\n\t\t// HACK - we know the variable field is at the same address\n\t\t// for all int/float classes. let's hope it stays that way.\n\t\tif(ev->vartype = MENUVAR_INT)\n\t\t\t((MenuEntry_Int32*)e)->variable = (int32*)addr;\n\t\telse if(ev->vartype = MENUVAR_FLOAT)\n\t\t\t((MenuEntry_Float32*)e)->variable = (float*)addr;\n\t}\n}\n#endif"
  },
  {
    "path": "src/extras/debugmenu.h",
    "content": "#pragma once\n\n#ifdef DEBUGMENU\n\ntypedef void (*TriggerFunc)(void);\n\nstruct Menu;\n\nstruct MenuEntry\n{\n\tint type;\n\tconst char *name;\n\tMenuEntry *next;\n\tRwRect r;\n\tMenu *menu;\n\n\tMenuEntry(const char *name);\n\tvirtual ~MenuEntry(void) { free((void*)name); }\n};\n\ntypedef MenuEntry DebugMenuEntry;\n\nMenuEntry *DebugMenuAddInt8(const char *path, const char *name, int8 *ptr, TriggerFunc triggerFunc, int8 step, int8 lowerBound, int8 upperBound, const char **strings);\nMenuEntry *DebugMenuAddInt16(const char *path, const char *name, int16 *ptr, TriggerFunc triggerFunc, int16 step, int16 lowerBound, int16 upperBound, const char **strings);\nMenuEntry *DebugMenuAddInt32(const char *path, const char *name, int32 *ptr, TriggerFunc triggerFunc, int32 step, int32 lowerBound, int32 upperBound, const char **strings);\nMenuEntry *DebugMenuAddInt64(const char *path, const char *name, int64 *ptr, TriggerFunc triggerFunc, int64 step, int64 lowerBound, int64 upperBound, const char **strings);\nMenuEntry *DebugMenuAddUInt8(const char *path, const char *name, uint8 *ptr, TriggerFunc triggerFunc, uint8 step, uint8 lowerBound, uint8 upperBound, const char **strings);\nMenuEntry *DebugMenuAddUInt16(const char *path, const char *name, uint16 *ptr, TriggerFunc triggerFunc, uint16 step, uint16 lowerBound, uint16 upperBound, const char **strings);\nMenuEntry *DebugMenuAddUInt32(const char *path, const char *name, uint32 *ptr, TriggerFunc triggerFunc, uint32 step, uint32 lowerBound, uint32 upperBound, const char **strings);\nMenuEntry *DebugMenuAddUInt64(const char *path, const char *name, uint64 *ptr, TriggerFunc triggerFunc, uint64 step, uint64 lowerBound, uint64 upperBound, const char **strings);\nMenuEntry *DebugMenuAddFloat32(const char *path, const char *name, float *ptr, TriggerFunc triggerFunc, float step, float lowerBound, float upperBound);\nMenuEntry *DebugMenuAddFloat64(const char *path, const char *name, double *ptr, TriggerFunc triggerFunc, double step, double lowerBound, double upperBound);\nMenuEntry *DebugMenuAddCmd(const char *path, const char *name, TriggerFunc triggerFunc);\nvoid DebugMenuEntrySetWrap(MenuEntry *e, bool wrap);\nvoid DebugMenuEntrySetStrings(MenuEntry *e, const char **strings);\nvoid DebugMenuEntrySetAddress(MenuEntry *e, void *addr);\nvoid DebugMenuInit(void);\nvoid DebugMenuShutdown(void);\nvoid DebugMenuProcess(void);\nvoid DebugMenuRender(void);\n\n\n// Some overloads for simplicity\ninline DebugMenuEntry *DebugMenuAddVar(const char *path, const char *name, int8_t *ptr, TriggerFunc triggerFunc, int8_t step, int8_t lowerBound, int8_t upperBound, const char **strings)\n{ return DebugMenuAddInt8(path, name, ptr, triggerFunc, step, lowerBound, upperBound, strings); }\ninline DebugMenuEntry *DebugMenuAddVar(const char *path, const char *name, int16_t *ptr, TriggerFunc triggerFunc, int16_t step, int16_t lowerBound, int16_t upperBound, const char **strings)\n{ return DebugMenuAddInt16(path, name, ptr, triggerFunc, step, lowerBound, upperBound, strings); }\ninline DebugMenuEntry *DebugMenuAddVar(const char *path, const char *name, int32_t *ptr, TriggerFunc triggerFunc, int32_t step, int32_t lowerBound, int32_t upperBound, const char **strings)\n{ return DebugMenuAddInt32(path, name, ptr, triggerFunc, step, lowerBound, upperBound, strings); }\ninline DebugMenuEntry *DebugMenuAddVar(const char *path, const char *name, int64_t *ptr, TriggerFunc triggerFunc, int64_t step, int64_t lowerBound, int64_t upperBound, const char **strings)\n{ return DebugMenuAddInt64(path, name, ptr, triggerFunc, step, lowerBound, upperBound, strings); }\ninline DebugMenuEntry *DebugMenuAddVar(const char *path, const char *name, uint8_t *ptr, TriggerFunc triggerFunc, uint8_t step, uint8_t lowerBound, uint8_t upperBound, const char **strings)\n{ return DebugMenuAddUInt8(path, name, ptr, triggerFunc, step, lowerBound, upperBound, strings); }\ninline DebugMenuEntry *DebugMenuAddVar(const char *path, const char *name, uint16_t *ptr, TriggerFunc triggerFunc, uint16_t step, uint16_t lowerBound, uint16_t upperBound, const char **strings)\n{ return DebugMenuAddUInt16(path, name, ptr, triggerFunc, step, lowerBound, upperBound, strings); }\ninline DebugMenuEntry *DebugMenuAddVar(const char *path, const char *name, uint32_t *ptr, TriggerFunc triggerFunc, uint32_t step, uint32_t lowerBound, uint32_t upperBound, const char **strings)\n{ return DebugMenuAddUInt32(path, name, ptr, triggerFunc, step, lowerBound, upperBound, strings); }\ninline DebugMenuEntry *DebugMenuAddVar(const char *path, const char *name, uint64_t *ptr, TriggerFunc triggerFunc, uint64_t step, uint64_t lowerBound, uint64_t upperBound, const char **strings)\n{ return DebugMenuAddUInt64(path, name, ptr, triggerFunc, step, lowerBound, upperBound, strings); }\ninline DebugMenuEntry *DebugMenuAddVar(const char *path, const char *name, float *ptr, TriggerFunc triggerFunc, float step, float lowerBound, float upperBound)\n{ return DebugMenuAddFloat32(path, name, ptr, triggerFunc, step, lowerBound, upperBound); }\ninline DebugMenuEntry *DebugMenuAddVar(const char *path, const char *name, double *ptr, TriggerFunc triggerFunc, double step, double lowerBound, double upperBound)\n{ return DebugMenuAddFloat64(path, name, ptr, triggerFunc, step, lowerBound, upperBound); }\n\ninline DebugMenuEntry *DebugMenuAddVarBool32(const char *path, const char *name, int32_t *ptr, TriggerFunc triggerFunc)\n{\n\tstatic const char *boolstr[] = { \"Off\", \"On\" };\n\tDebugMenuEntry *e = DebugMenuAddVar(path, name, ptr, triggerFunc, 1, 0, 1, boolstr);\n\tDebugMenuEntrySetWrap(e, true);\n\treturn e;\n}\ninline DebugMenuEntry *DebugMenuAddVarBool16(const char *path, const char *name, int16_t *ptr, TriggerFunc triggerFunc)\n{\n\tstatic const char *boolstr[] = { \"Off\", \"On\" };\n\tDebugMenuEntry *e = DebugMenuAddVar(path, name, ptr, triggerFunc, 1, 0, 1, boolstr);\n\tDebugMenuEntrySetWrap(e, true);\n\treturn e;\n}\ninline DebugMenuEntry *DebugMenuAddVarBool8(const char *path, const char *name, int8_t *ptr, TriggerFunc triggerFunc)\n{\n\tstatic const char *boolstr[] = { \"Off\", \"On\" };\n\tDebugMenuEntry *e = DebugMenuAddVar(path, name, ptr, triggerFunc, 1, 0, 1, boolstr);\n\tDebugMenuEntrySetWrap(e, true);\n\treturn e;\n}\ninline DebugMenuEntry *DebugMenuAddVarBool8(const char *path, const char *name, bool *ptr, TriggerFunc triggerFunc)\n{\n\treturn DebugMenuAddVarBool8(path, name, (int8_t*)ptr, triggerFunc);\n}\n#endif"
  },
  {
    "path": "src/extras/frontendoption.cpp",
    "content": "#include \"common.h\"\n\n#ifdef CUSTOM_FRONTEND_OPTIONS\n#include \"Frontend.h\"\n#include \"Text.h\"\n\nint lastOgScreen = MENUPAGES; // means no new pages\n\nint numCustomFrontendOptions = 0;\nint numCustomFrontendScreens = 0;\n\nint optionCursor = -2;\nint currentMenu;\nbool optionOverwrite = false;\n\nvoid GoBack()\n{\n\tFrontEndMenuManager.SwitchToNewScreen(-1);\n}\n\nuint8\nGetNumberOfMenuOptions(int screen)\n{\n\tuint8 Rows = 0;\n\tfor (int i = 0; i < NUM_MENUROWS; i++) {\n\t\tif (aScreens[screen].m_aEntries[i].m_Action == MENUACTION_NOTHING)\n\t\t\tbreak;\n\n\t\t++Rows;\n\t}\n\treturn Rows;\n}\n\nuint8\nGetLastMenuScreen()\n{\n\tint8 page = -1;\n\tfor (int i = 0; i < MENUPAGES; i++) {\n\t\tif (strcmp(aScreens[i].m_ScreenName, \"\") == 0 && aScreens[i].m_PreviousPage == MENUPAGE_NONE)\n\t\t\tbreak;\n\n\t\t++page;\n\t}\n\treturn page;\n}\n\nint8 RegisterNewScreen(const char *name, int prevPage, ReturnPrevPageFunc returnPrevPageFunc)\n{\n\tif (lastOgScreen == MENUPAGES)\n\t\tlastOgScreen = GetLastMenuScreen();\n\n\tnumCustomFrontendScreens++;\n\tint id = lastOgScreen + numCustomFrontendScreens;\n\tassert(id < MENUPAGES && \"No room for new custom frontend screens! Increase MENUPAGES\");\n\tstrncpy(aScreens[id].m_ScreenName, name, 8);\n\taScreens[id].m_PreviousPage = prevPage;\n\taScreens[id].returnPrevPageFunc = returnPrevPageFunc;\n\treturn id;\n}\n\nint8 RegisterNewOption()\n{\n\tnumCustomFrontendOptions++;\n\tuint8 numOptions = GetNumberOfMenuOptions(currentMenu);\n\tuint8 curIdx;\n\tif (optionCursor < 0) {\n\t\toptionCursor = curIdx = numOptions + optionCursor + 1;\n\t} else \n\t\tcurIdx = optionCursor;\n\n\tif (!optionOverwrite) {\n\t\tif (aScreens[currentMenu].m_aEntries[curIdx].m_Action != MENUACTION_NOTHING) {\n\t\t\tfor (int i = numOptions - 1; i >= curIdx; i--) {\n\t\t\t\tmemcpy(&aScreens[currentMenu].m_aEntries[i + 1], &aScreens[currentMenu].m_aEntries[i], sizeof(CMenuScreenCustom::CMenuEntry));\n\t\t\t}\n\t\t}\n\t}\n\toptionCursor++;\n\treturn curIdx;\n}\n\nvoid FrontendOptionSetCursor(int screen, int8 option, bool overwrite)\n{\n\tcurrentMenu = screen;\n\toptionCursor = option;\n\toptionOverwrite = overwrite;\n}\n\nvoid FrontendOptionAddBuiltinAction(const char* gxtKey, uint16 x, uint16 y, uint8 align, int action, int targetMenu, int saveSlot) {\n\tint8 screenOptionOrder = RegisterNewOption();\n\n\tCMenuScreenCustom::CMenuEntry &option = aScreens[currentMenu].m_aEntries[screenOptionOrder];\n\n\t// We can't use custom text on those :shrug:\n\tswitch (action) {\n\t\tcase MENUACTION_SCREENRES:\n\t\t\tstrcpy(option.m_EntryName, \"FED_RES\");\n\t\t\tbreak;\n\t\tcase MENUACTION_AUDIOHW:\n\t\t\tstrcpy(option.m_EntryName, \"FEA_3DH\");\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tstrncpy(option.m_EntryName, gxtKey, 8);\n\t\t\tbreak;\n\t}\n\toption.m_X = x;\n\toption.m_Y = y;\n\toption.m_Align = align;\n\toption.m_Action = action;\n\toption.m_SaveSlot = saveSlot;\n\toption.m_TargetMenu = targetMenu;\n}\n\nvoid FrontendOptionAddSelect(const char* gxtKey, uint16 x, uint16 y, uint8 align, const char** rightTexts, int8 numRightTexts, int8 *var, bool onlyApplyOnEnter, ChangeFunc changeFunc, const char* saveCat, const char* saveName, bool disableIfGameLoaded)\n{\t\n\tint8 screenOptionOrder = RegisterNewOption();\n\n\tCMenuScreenCustom::CMenuEntry &option = aScreens[currentMenu].m_aEntries[screenOptionOrder];\n\toption.m_Action = MENUACTION_CFO_SELECT;\n\toption.m_X = x;\n\toption.m_Y = y;\n\toption.m_Align = align;\n\tstrncpy(option.m_EntryName, gxtKey, 8);\n\toption.m_CFOSelect = new CCFOSelect();\n\toption.m_CFOSelect->rightTexts = (char**)malloc(numRightTexts * sizeof(char*));\n\tmemcpy(option.m_CFOSelect->rightTexts, rightTexts, numRightTexts * sizeof(char*));\n\toption.m_CFOSelect->numRightTexts = numRightTexts;\n\toption.m_CFOSelect->value = var;\n\tif (var) {\n\t\toption.m_CFOSelect->displayedValue = *var;\n\t\toption.m_CFOSelect->lastSavedValue = *var;\n\t}\n\toption.m_CFOSelect->saveCat = saveCat;\n\toption.m_CFOSelect->save = saveName;\n\toption.m_CFOSelect->onlyApplyOnEnter = onlyApplyOnEnter;\n\toption.m_CFOSelect->changeFunc = changeFunc;\n\toption.m_CFOSelect->disableIfGameLoaded = disableIfGameLoaded;\n}\n\nvoid FrontendOptionAddDynamic(const char* gxtKey, uint16 x, uint16 y, uint8 align, DrawFunc drawFunc, int8 *var, ButtonPressFunc buttonPressFunc, const char* saveCat, const char* saveName)\n{\n\tint8 screenOptionOrder = RegisterNewOption();\n\n\tCMenuScreenCustom::CMenuEntry &option = aScreens[currentMenu].m_aEntries[screenOptionOrder];\n\toption.m_Action = MENUACTION_CFO_DYNAMIC;\n\toption.m_X = x;\n\toption.m_Y = y;\n\toption.m_Align = align;\n\tstrncpy(option.m_EntryName, gxtKey, 8);\n\toption.m_CFODynamic = new CCFODynamic();\n\toption.m_CFODynamic->drawFunc = drawFunc;\n\toption.m_CFODynamic->buttonPressFunc = buttonPressFunc;\n\toption.m_CFODynamic->value = var;\n\toption.m_CFODynamic->saveCat = saveCat;\n\toption.m_CFODynamic->save = saveName;\n}\n\n// lineHeight = 0 means game will use MENU_DEFAULT_LINE_HEIGHT\nuint8 FrontendScreenAdd(const char* gxtKey, int prevPage, int lineHeight, bool showLeftRightHelper, ReturnPrevPageFunc returnPrevPageFunc) {\n\n\tuint8 screenOrder = RegisterNewScreen(gxtKey, prevPage, returnPrevPageFunc);\n\n\tCCustomScreenLayout *screen = new CCustomScreenLayout();\n\taScreens[screenOrder].layout = screen;\n\tscreen->lineHeight = lineHeight;\n\tscreen->showLeftRightHelper = showLeftRightHelper;\n\n\treturn screenOrder;\n}\n#endif\n"
  },
  {
    "path": "src/extras/frontendoption.h",
    "content": "#pragma once\n#include \"common.h\"\n\n#ifdef CUSTOM_FRONTEND_OPTIONS\n\n// ! There are 2 ways to use CFO,\n//\t\t1st; by adding a new option to the array in MenuScreensCustom.cpp and passing attributes/CBs to it\n//\t\t2nd; by calling the functions listed at the bottom of this file.\n\n// -- Option types\n//\n// Static/select:\tYou allocate the variable, pass it to function and game sets it from user input among the strings given to function,\n//\t\t\t\t\toptionally you can add post-change event via ChangeFunc(only called on enter if onlyApplyOnEnter set, or set immediately)\n//\t\t\t\t\tYou can store the option in an INI file if you pass the key(as a char array) to corresponding parameter.\n//\n// Dynamic:\t\t\tPassing variable to function is only needed if you want to store it, otherwise you should do\n//\t\t\t\t\tall the operations with ButtonPressFunc, this includes allocating the variable.\n//\t\t\t\t\tLeft-side text is passed while creating and static, but ofc right-side text is dynamic -\n//\t\t\t\t\tyou should return it in DrawFunc, which is called on every draw.\n//\n// Built-in action:\tAs the name suggests, any action that game has built-in. But as an extra you can set the option text,\n\n// -- Returned via ButtonPressFunc() action param.\n#define FEOPTION_ACTION_LEFT 0\n#define FEOPTION_ACTION_RIGHT 1\n#define FEOPTION_ACTION_SELECT 2\n#define FEOPTION_ACTION_FOCUSLOSS 3\n\n// -- Callbacks\n\n// pretty much in everything I guess, and optional in all of them\ntypedef void (*ReturnPrevPageFunc)();\n\n// for static options\ntypedef void (*ChangeFunc)(int8 before, int8 after); // called after updating the value.\n\t\t\t\t\t\t\t\t\t\t\t\t// only called on enter if onlyApplyOnEnter set, otherwise called on every value change\n\n// for dynamic options\ntypedef wchar* (*DrawFunc)(bool* disabled, bool userHovering); // you must return a pointer for right text.\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// you can also set *disabled if you want to gray it out.\ntypedef void (*ButtonPressFunc)(int8 action); // see FEOPTION_ACTIONs above\n\n// -- Internal things\nvoid CustomFrontendOptionsPopulate();\nextern int lastOgScreen; // for reloading\nextern int numCustomFrontendOptions;\nextern int numCustomFrontendScreens;\n\n// -- To be used in ButtonPressFunc / ChangeFunc(this one would be weird):\nvoid GoBack(void);\n\nuint8 GetNumberOfMenuOptions(int screen);\n\n// !!! We're now moved to MenuScreensCustom.cpp, which houses an array that keeps all original+custom options.\n//\t\tBut you can still use the APIs below, and manipulate aScreens while in game.\n\n// Limits:\n//\t\tThe code relies on that you won't use more then NUM_MENUROWS(18) options on one page, and won't exceed the MENUPAGES of pages.\n//\t\tAlso congrats if you can make 18 options visible at once.\n\n// Texts:\n//\t\tAll text parameters accept char[8] GXT key.\n\n// Execute direction:\n//\t\tAll of the calls below eventually manipulate the aScreens array, so keep in mind to add/replace options in order,\n//\t\ti.e. don't set cursor to 8 first and then 3.\n\n\n// -- Placing the cursor to append/overwrite option\n//\n// Done via FrontendOptionSetCursor(screen, position, overwrite = false), parameters explained below:\n// Screen:\t\t\tas the name suggests. Also accepts the screen IDs returned from FrontendScreenAdd.\n// Option:\t\t\tif positive, next AddOption call will put the option to there and progress the cursor.\n//\t\t\t\t\tif negative, cursor will be placed on bottom-(pos+1), so -1 means the very bottom, -2 means before the back button etc.\n// Overwrite:\t\tUse to overwrite the options, not appending a new one. AddOption calls will still progress the cursor.\n\nvoid FrontendOptionSetCursor(int screen, int8 option, bool overwrite = false);\n\n// var is optional in AddDynamic, enables you to save them in an INI file(also needs passing char array to saveCat and saveKey param. obv), otherwise pass nil/0\nvoid FrontendOptionAddBuiltinAction(const char* gxtKey, uint16 x, uint16 y, uint8 align, int action, int targetMenu = MENUPAGE_NONE, int saveSlot = SAVESLOT_NONE);\nvoid FrontendOptionAddSelect(const char* gxtKey, uint16 x, uint16 y, uint8 align, const char** rightTexts, int8 numRightTexts, int8 *var, bool onlyApplyOnEnter, ChangeFunc changeFunc, const char* saveCat = nil, const char* saveKey = nil, bool disableIfGameLoaded = false);\nvoid FrontendOptionAddDynamic(const char* gxtKey, uint16 x, uint16 y, uint8 align, DrawFunc rightTextDrawFunc, int8 *var, ButtonPressFunc buttonPressFunc, const char* saveCat = nil, const char* saveKey = nil);\n\n// lineHeight = 0 means game will use MENU_DEFAULT_LINE_HEIGHT\nuint8 FrontendScreenAdd(const char* gxtKey, int prevPage, int lineHeight, bool showLeftRightHelper, ReturnPrevPageFunc returnPrevPageFunc = nil);\n#endif\n"
  },
  {
    "path": "src/extras/ini_parser.hpp",
    "content": "/* \n *  Copyright (c) 2013-2015 Denilson das Mercês Amorim <dma_2012@hotmail.com>\n *  \n *  This software is provided 'as-is', without any express or implied\n *  warranty. In no event will the authors be held liable for any damages\n *  arising from the use of this software.\n * \n *  Permission is granted to anyone to use this software for any purpose,\n *  including commercial applications, and to alter it and redistribute it\n *  freely, subject to the following restrictions:\n * \n *     1. The origin of this software must not be misrepresented; you must not\n *     claim that you wrote the original software. If you use this software\n *     in a product, an acknowledgment in the product documentation would be\n *     appreciated but is not required.\n * \n *     2. Altered source versions must be plainly marked as such, and must not be\n *     misrepresented as being the original software.\n * \n *     3. This notice may not be removed or altered from any source\n *     distribution.\n * \n */\n#ifndef LINB_INI_PARSER_HPP\n#define LINB_INI_PARSER_HPP\n\n/*\n *  STL-like INI Container\n */\n\n#include <string>       // for std::string\n#include <map>          // for std::map\n#include <cstdio>       // for std::FILE\n#include <algorithm>    // for std::find_if\n#include <functional>   // for std::function\n\nnamespace linb\n{\n    template<\n        class CharT             = char,     /* Not compatible with other type here, since we're using C streams */\n        class StringType        = std::basic_string<CharT>,\n        class KeyContainer      = std::map<StringType, StringType>,\n        class SectionContainer  = std::map<StringType, KeyContainer>\n    > class basic_ini\n    {\n        public:\n            typedef CharT               char_type;\n            typedef StringType          string_type;\n            typedef KeyContainer        key_container;\n            typedef SectionContainer    section_container;\n            \n            // Typedef container values types\n            typedef typename section_container::value_type              value_type;\n            typedef typename section_container::key_type                key_type;\n            typedef typename section_container::mapped_type             mapped_type;\n            \n            // Typedef common types\n            typedef typename section_container::size_type               size_type;\n            typedef typename section_container::difference_type         difference_type;\n            \n            // Typedef iterators\n            typedef typename section_container::iterator                iterator;\n            typedef typename section_container::const_iterator          const_iterator;\n            typedef typename section_container::reverse_iterator        reverse_iterator;\n            typedef typename section_container::const_reverse_iterator  const_reverse_iterator;\n            \n            // typedef References and pointers\n            typedef typename section_container::reference               reference;\n            typedef typename section_container::const_reference         const_reference;\n            typedef typename section_container::pointer                 pointer;\n            typedef typename section_container::const_pointer           const_pointer;\n            \n        private:\n            section_container data;\n            \n        public:\n            \n            basic_ini()\n            { }\n\n            basic_ini(const char_type* filename)\n            { this->read_file(filename); }\n            \n            /* Iterator methods */\n            iterator begin()\n            { return data.begin(); }\n            const_iterator begin() const\n            { return data.begin(); }\n            iterator end()\n            { return data.end(); }\n            const_iterator end() const\n            { return data.end(); }\n            const_iterator cbegin() const\n            { return data.cbegin(); }\n            const_iterator cend() const\n            { return data.cend(); }\n            \n            /* Reverse iterator methods */\n            reverse_iterator rbegin()\n            { return data.rbegin(); }\n            const_reverse_iterator rbegin() const\n            { return data.rbegin(); }\n            reverse_iterator rend()\n            { return data.rend(); }\n            const_reverse_iterator rend() const\n            { return data.rend(); }\n            const_reverse_iterator crbegin() const\n            { return data.crbegin(); }\n            const_reverse_iterator crend() const\n            { return data.crend(); }\n            \n            /* Acessing index methods */\n            mapped_type& operator[](const string_type& sect)\n            { return data[sect]; }\n            mapped_type& operator[](string_type&& sect)\n            { return data[std::forward<string_type>(sect)]; }\n            mapped_type& at( const string_type& sect)\n            { return data.at(sect); }\n            const mapped_type& at(const string_type& sect) const\n            { return data.at(sect); }\n            \n            /* Capacity information */\n            bool empty() const\n            { return data.empty(); }\n            size_type size() const\n            { return data.size(); }\n            size_type max_size() const\n            { return data.max_size(); }\n            \n            /* Modifiers */\n            void clear()\n            { return data.clear(); }\n            \n            /* Lookup */\n            size_type count(const string_type& sect)\n            { return data.count(sect); }\n            iterator find(const string_type& sect)\n            { return data.find(sect); }\n\n            /* Gets a value from the specified section & key, default_value is returned if the sect & key doesn't exist */\n            string_type get(const string_type& sect, const key_type& key, const string_type& default_value)\n            {\n                auto it = this->find(sect);\n                if(it != this->end())\n                {\n                    auto itv = it->second.find(key);\n                    if(itv != it->second.end())\n                        return itv->second;\n                }\n                return default_value;\n            }\n\n            /* Sets the value of a value in the ini */\n            void set(const string_type& sect, const key_type& key, const string_type& value)\n            {\n                (*this)[sect][key] = value; // no emplace since overwrite!\n            }\n\n            /* Too lazy to continue this container... If you need more methods, just add it */\n            \n            // re3\n            void remove(const string_type& sect, const key_type& key)\n            {\n                auto it = this->find(sect);\n                if(it != this->end())\n                {\n                    it->second.erase(key);\n                }\n            }\n\n            int category_size(const string_type& sect)\n            {\n                auto it = this->find(sect);\n                if(it != this->end())\n                {\n                    return it->second.size();\n                }\n                return 0;\n            }\n\n#if 1\n            bool read_file(const char_type* filename)\n            {\n                /* Using C stream in a STL-like container, funny?\n                 */\n                if(FILE* f = fopen(filename, \"r\"))\n                {\n                    key_container* keys = nullptr;\n                    char_type buf[2048];\n                    string_type line;\n                    string_type key;\n                    string_type value;\n                    string_type null_string;\n                    size_type pos;\n                    \n                    // Trims an string\n                    auto trim = [](string_type& s, bool trimLeft, bool trimRight) -> string_type&\n                    {\n                        if(s.size())\n                        {\n                            // Ignore UTF-8 BOM\n                            while(s.size() >= 3 && s[0] == (char)(0xEF) && s[1] == (char)(0xBB) && s[2] == (char)(0xBF))\n                                s.erase(s.begin(), s.begin() + 3);\n\n                            if(trimLeft)\n                                s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::function<int(int)>(::isspace))));\n                            if(trimRight)\n                                s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::function<int(int)>(::isspace))).base(), s.end());\n                        }\n                        return s;\n                    };\n                    \n                    // Start parsing\n                    while(fgets(buf, sizeof(buf), f))\n                    {\n                        // What a thing, reading into a char buffer and then putting in the string...\n                        line = buf;\n                        \n                        // Find comment and remove anything after it from the line\n                        if((pos = line.find_first_of(';')) != line.npos)\n                            line.erase(pos);\n                        \n                        // Trim the string, and if it gets empty, skip this line\n                        if(trim(line, true, true).empty())\n                            continue;\n                        \n                        // Find section name\n                        if(line.front() == '[' && line.back() == ']')\n                        {\n                            pos = line.length() - 1; //line.find_first_of(']');\n                            if(pos != line.npos)\n                            {\n                                trim(key.assign(line, 1, pos-1), true, true);\n                                keys = &data[std::move(key)];  // Create section\n                            }\n                            else\n                                keys = nullptr;\n                        }\n                        else\n                        {\n                            // Find key and value positions\n                            pos = line.find_first_of('=');\n                            if(pos == line.npos)\n                            {\n                                // There's only the key\n                                key = line;         // No need for trim, line is already trimmed\n                                value.clear();\n                            }\n                            else\n                            {\n                                // There's the key and the value\n                                trim(key.assign(line, 0, pos), false, true);                  // trim the right\n                                trim(value.assign(line, pos + 1, line.npos), true, false);    // trim the left\n                            }\n\n                            // Put the key/value into the current keys object, or into the section \"\" if no section has been found\n                            #if __cplusplus >= 201103L || _MSC_VER >= 1800\n                            (keys ? *keys : data[null_string]).emplace(std::move(key), std::move(value));\n                            #else\n                            (keys ? *keys : data[null_string])[key] = value;\n                            key.clear(); value.clear();\n                            #endif\n                        }\n                    }\n                    \n                    fclose(f);\n                    return true;\n                }\n                return false;\n            }\n\n            /*\n             *  Dumps the content of this container into an ini file\n             */\n            bool write_file(const char_type* filename)\n            {\n                if(FILE* f = fopen(filename, \"w\"))\n                {\n                    bool first = true;\n                    for(auto& sec : this->data)\n                    {\n                        fprintf(f, first? \"[%s]\\n\" : \"\\n[%s]\\n\", sec.first.c_str());\n                        first = false;\n                        for(auto& kv : sec.second)\n                        {\n                            if(kv.second.empty())\n                                fprintf(f, \"%s\\n\", kv.first.c_str());\n                            else\n                                fprintf(f, \"%s = %s\\n\", kv.first.c_str(), kv.second.c_str());\n                        }\n                    }\n                    fclose(f);\n                    return true;\n                }\n                return false;\n            }\n\n\n            /*\n            */\n            bool load_file(const char_type* filename)\n            {\n                return read_file(filename);\n            }\n\n            bool load_file(const StringType& filename)\n            {\n                return load_file(filename.c_str());\n            }\n\n            bool write_file(const StringType& filename)\n            {\n                return write_file(filename.c_str());\n            }\n#endif       \n            \n\n        \n    };\n    \n    \n    /* Use default basic_ini\n     * \n     *  Limitations:\n     *      * Not unicode aware\n     *      * Case sensitive\n     *      * Sections must have unique keys\n     */\n    typedef basic_ini<>     ini;\n}\n    \n#endif\n\n"
  },
  {
    "path": "src/extras/postfx.cpp",
    "content": "#define WITHD3D\n#include \"common.h\"\n\n#ifdef EXTENDED_COLOURFILTER\n\n#ifndef LIBRW\n#error \"Need librw for EXTENDED_COLOURFILTER\"\n#endif\n\n#include \"main.h\"\n#include \"RwHelper.h\"\n#include \"Camera.h\"\n#include \"MBlur.h\"\n#include \"postfx.h\"\n\nRwRaster *CPostFX::pFrontBuffer;\nRwRaster *CPostFX::pBackBuffer;\nbool CPostFX::bJustInitialised;\nint CPostFX::EffectSwitch = POSTFX_NORMAL;\nbool CPostFX::BlurOn = false;\nbool CPostFX::MotionBlurOn = false;\n\nstatic RwIm2DVertex Vertex[4];\nstatic RwIm2DVertex Vertex2[4];\nstatic RwImVertexIndex Index[6] = { 0, 1, 2, 0, 2, 3 };\n\n#ifdef RW_D3D9\nvoid *colourfilterVC_PS;\nvoid *contrast_PS;\n#endif\n#ifdef RW_OPENGL\nint32 u_blurcolor;\nint32 u_contrastAdd;\nint32 u_contrastMult;\nrw::gl3::Shader *colourFilterVC;\nrw::gl3::Shader *contrast;\n#endif\n\nvoid\nCPostFX::InitOnce(void)\n{\n#ifdef RW_OPENGL\n\tu_blurcolor = rw::gl3::registerUniform(\"u_blurcolor\");\n\tu_contrastAdd = rw::gl3::registerUniform(\"u_contrastAdd\");\n\tu_contrastMult = rw::gl3::registerUniform(\"u_contrastMult\");\n#endif\n}\n\nvoid\nCPostFX::Open(RwCamera *cam)\n{\n\tuint32 width  = Pow(2.0f, int32(log2(RwRasterGetWidth (RwCameraGetRaster(cam))))+1);\n\tuint32 height = Pow(2.0f, int32(log2(RwRasterGetHeight(RwCameraGetRaster(cam))))+1);\n\tuint32 depth  = RwRasterGetDepth(RwCameraGetRaster(cam));\n\tpFrontBuffer = RwRasterCreate(width, height, depth, rwRASTERTYPECAMERATEXTURE);\n\tpBackBuffer = RwRasterCreate(width, height, depth, rwRASTERTYPECAMERATEXTURE);\n\tbJustInitialised = true;\n\n\tfloat zero, xmax, ymax;\n\n\tif(RwRasterGetDepth(RwCameraGetRaster(cam)) == 16){\n\t\tzero = HALFPX;\n\t\txmax = width + HALFPX;\n\t\tymax = height + HALFPX;\n\t}else{\n\t\tzero = -HALFPX;\n\t\txmax = width - HALFPX;\n\t\tymax = height - HALFPX;\n\t}\n\n\tRwIm2DVertexSetScreenX(&Vertex[0], zero);\n\tRwIm2DVertexSetScreenY(&Vertex[0], zero);\n\tRwIm2DVertexSetScreenZ(&Vertex[0], RwIm2DGetNearScreenZ());\n\tRwIm2DVertexSetCameraZ(&Vertex[0], RwCameraGetNearClipPlane(cam));\n\tRwIm2DVertexSetRecipCameraZ(&Vertex[0], 1.0f/RwCameraGetNearClipPlane(cam));\n\tRwIm2DVertexSetU(&Vertex[0], 0.0f, 1.0f/RwCameraGetNearClipPlane(cam));\n\tRwIm2DVertexSetV(&Vertex[0], 0.0f, 1.0f/RwCameraGetNearClipPlane(cam));\n\tRwIm2DVertexSetIntRGBA(&Vertex[0], 255, 255, 255, 255);\n\n\tRwIm2DVertexSetScreenX(&Vertex[1], zero);\n\tRwIm2DVertexSetScreenY(&Vertex[1], ymax);\n\tRwIm2DVertexSetScreenZ(&Vertex[1], RwIm2DGetNearScreenZ());\n\tRwIm2DVertexSetCameraZ(&Vertex[1], RwCameraGetNearClipPlane(cam));\n\tRwIm2DVertexSetRecipCameraZ(&Vertex[1], 1.0f/RwCameraGetNearClipPlane(cam));\n\tRwIm2DVertexSetU(&Vertex[1], 0.0f, 1.0f/RwCameraGetNearClipPlane(cam));\n\tRwIm2DVertexSetV(&Vertex[1], 1.0f, 1.0f/RwCameraGetNearClipPlane(cam));\n\tRwIm2DVertexSetIntRGBA(&Vertex[1], 255, 255, 255, 255);\n\n\tRwIm2DVertexSetScreenX(&Vertex[2], xmax);\n\tRwIm2DVertexSetScreenY(&Vertex[2], ymax);\n\tRwIm2DVertexSetScreenZ(&Vertex[2], RwIm2DGetNearScreenZ());\n\tRwIm2DVertexSetCameraZ(&Vertex[2], RwCameraGetNearClipPlane(cam));\n\tRwIm2DVertexSetRecipCameraZ(&Vertex[2], 1.0f/RwCameraGetNearClipPlane(cam));\n\tRwIm2DVertexSetU(&Vertex[2], 1.0f, 1.0f/RwCameraGetNearClipPlane(cam));\n\tRwIm2DVertexSetV(&Vertex[2], 1.0f, 1.0f/RwCameraGetNearClipPlane(cam));\n\tRwIm2DVertexSetIntRGBA(&Vertex[2], 255, 255, 255, 255);\n\n\tRwIm2DVertexSetScreenX(&Vertex[3], xmax);\n\tRwIm2DVertexSetScreenY(&Vertex[3], zero);\n\tRwIm2DVertexSetScreenZ(&Vertex[3], RwIm2DGetNearScreenZ());\n\tRwIm2DVertexSetCameraZ(&Vertex[3], RwCameraGetNearClipPlane(cam));\n\tRwIm2DVertexSetRecipCameraZ(&Vertex[3], 1.0f/RwCameraGetNearClipPlane(cam));\n\tRwIm2DVertexSetU(&Vertex[3], 1.0f, 1.0f/RwCameraGetNearClipPlane(cam));\n\tRwIm2DVertexSetV(&Vertex[3], 0.0f, 1.0f/RwCameraGetNearClipPlane(cam));\n\tRwIm2DVertexSetIntRGBA(&Vertex[3], 255, 255, 255, 255);\n\n\n\tRwIm2DVertexSetScreenX(&Vertex2[0], zero + 2.0f);\n\tRwIm2DVertexSetScreenY(&Vertex2[0], zero + 2.0f);\n\tRwIm2DVertexSetScreenZ(&Vertex2[0], RwIm2DGetNearScreenZ());\n\tRwIm2DVertexSetCameraZ(&Vertex2[0], RwCameraGetNearClipPlane(cam));\n\tRwIm2DVertexSetRecipCameraZ(&Vertex2[0], 1.0f/RwCameraGetNearClipPlane(cam));\n\tRwIm2DVertexSetU(&Vertex2[0], 0.0f, 1.0f/RwCameraGetNearClipPlane(cam));\n\tRwIm2DVertexSetV(&Vertex2[0], 0.0f, 1.0f/RwCameraGetNearClipPlane(cam));\n\tRwIm2DVertexSetIntRGBA(&Vertex2[0], 255, 255, 255, 255);\n\n\tRwIm2DVertexSetScreenX(&Vertex2[1], 2.0f);\n\tRwIm2DVertexSetScreenY(&Vertex2[1], ymax + 2.0f);\n\tRwIm2DVertexSetScreenZ(&Vertex2[1], RwIm2DGetNearScreenZ());\n\tRwIm2DVertexSetCameraZ(&Vertex2[1], RwCameraGetNearClipPlane(cam));\n\tRwIm2DVertexSetRecipCameraZ(&Vertex2[1], 1.0f/RwCameraGetNearClipPlane(cam));\n\tRwIm2DVertexSetU(&Vertex2[1], 0.0f, 1.0f/RwCameraGetNearClipPlane(cam));\n\tRwIm2DVertexSetV(&Vertex2[1], 1.0f, 1.0f/RwCameraGetNearClipPlane(cam));\n\tRwIm2DVertexSetIntRGBA(&Vertex2[1], 255, 255, 255, 255);\n\n\tRwIm2DVertexSetScreenX(&Vertex2[2], xmax + 2.0f);\n\tRwIm2DVertexSetScreenY(&Vertex2[2], ymax + 2.0f);\n\tRwIm2DVertexSetScreenZ(&Vertex2[2], RwIm2DGetNearScreenZ());\n\tRwIm2DVertexSetCameraZ(&Vertex2[2], RwCameraGetNearClipPlane(cam));\n\tRwIm2DVertexSetRecipCameraZ(&Vertex2[2], 1.0f/RwCameraGetNearClipPlane(cam));\n\tRwIm2DVertexSetU(&Vertex2[2], 1.0f, 1.0f/RwCameraGetNearClipPlane(cam));\n\tRwIm2DVertexSetV(&Vertex2[2], 1.0f, 1.0f/RwCameraGetNearClipPlane(cam));\n\tRwIm2DVertexSetIntRGBA(&Vertex2[2], 255, 255, 255, 255);\n\n\tRwIm2DVertexSetScreenX(&Vertex2[3], xmax + 2.0f);\n\tRwIm2DVertexSetScreenY(&Vertex2[3], zero + 2.0f);\n\tRwIm2DVertexSetScreenZ(&Vertex2[3], RwIm2DGetNearScreenZ());\n\tRwIm2DVertexSetCameraZ(&Vertex2[3], RwCameraGetNearClipPlane(cam));\n\tRwIm2DVertexSetRecipCameraZ(&Vertex2[3], 1.0f/RwCameraGetNearClipPlane(cam));\n\tRwIm2DVertexSetU(&Vertex2[3], 1.0f, 1.0f/RwCameraGetNearClipPlane(cam));\n\tRwIm2DVertexSetV(&Vertex2[3], 0.0f, 1.0f/RwCameraGetNearClipPlane(cam));\n\tRwIm2DVertexSetIntRGBA(&Vertex2[3], 255, 255, 255, 255);\n\n\n#ifdef RW_D3D9\n#include \"shaders/obj/colourfilterVC_PS.inc\"\n\tcolourfilterVC_PS = rw::d3d::createPixelShader(colourfilterVC_PS_cso);\n#include \"shaders/obj/contrastPS.inc\"\n\tcontrast_PS = rw::d3d::createPixelShader(contrastPS_cso);\n#endif\n#ifdef RW_OPENGL\n\tusing namespace rw::gl3;\n\n\t{\n#include \"shaders/obj/im2d_vert.inc\"\n#include \"shaders/obj/colourfilterVC_frag.inc\"\n\tconst char *vs[] = { shaderDecl, header_vert_src, im2d_vert_src, nil };\n\tconst char *fs[] = { shaderDecl, header_frag_src, colourfilterVC_frag_src, nil };\n\tcolourFilterVC = Shader::create(vs, fs);\n\tassert(colourFilterVC);\n\t}\n\n\t{\n#include \"shaders/obj/im2d_vert.inc\"\n#include \"shaders/obj/contrast_frag.inc\"\n\tconst char *vs[] = { shaderDecl, header_vert_src, im2d_vert_src, nil };\n\tconst char *fs[] = { shaderDecl, header_frag_src, contrast_frag_src, nil };\n\tcontrast = Shader::create(vs, fs);\n\tassert(contrast);\n\t}\n\n#endif\n}\n\nvoid\nCPostFX::Close(void)\n{\n\tif(pFrontBuffer){\n\t\tRwRasterDestroy(pFrontBuffer);\n\t\tpFrontBuffer = nil;\n\t}\n\tif(pBackBuffer){\n\t\tRwRasterDestroy(pBackBuffer);\n\t\tpBackBuffer = nil;\n\t}\n#ifdef RW_D3D9\n\tif(colourfilterVC_PS){\n\t\trw::d3d::destroyPixelShader(colourfilterVC_PS);\n\t\tcolourfilterVC_PS = nil;\n\t}\n\tif(contrast_PS){\n\t\trw::d3d::destroyPixelShader(contrast_PS);\n\t\tcontrast_PS = nil;\n\t}\n#endif\n#ifdef RW_OPENGL\n\tif(colourFilterVC){\n\t\tcolourFilterVC->destroy();\n\t\tcolourFilterVC = nil;\n\t}\n\tif(contrast){\n\t\tcontrast->destroy();\n\t\tcontrast = nil;\n\t}\n#endif\n}\n\nvoid\nCPostFX::RenderOverlayBlur(RwCamera *cam, int32 r, int32 g, int32 b, int32 a)\n{\n\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, pFrontBuffer);\n\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);\n\n\tRwIm2DVertexSetIntRGBA(&Vertex[0], r*2, g*2, b*2, 30);\n\tRwIm2DVertexSetIntRGBA(&Vertex[1], r*2, g*2, b*2, 30);\n\tRwIm2DVertexSetIntRGBA(&Vertex[2], r*2, g*2, b*2, 30);\n\tRwIm2DVertexSetIntRGBA(&Vertex[3], r*2, g*2, b*2, 30);\n\tRwIm2DVertexSetIntRGBA(&Vertex2[0], r*2, g*2, b*2, 30);\n\tRwIm2DVertexSetIntRGBA(&Vertex2[1], r*2, g*2, b*2, 30);\n\tRwIm2DVertexSetIntRGBA(&Vertex2[2], r*2, g*2, b*2, 30);\n\tRwIm2DVertexSetIntRGBA(&Vertex2[3], r*2, g*2, b*2, 30);\n\n\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);\n\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);\n\n\tRwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, BlurOn ? Vertex2 : Vertex, 4, Index, 6);\n\n\n\tRwIm2DVertexSetIntRGBA(&Vertex2[0], r, g, b, a);\n\tRwIm2DVertexSetIntRGBA(&Vertex[0], r, g, b, a);\n\tRwIm2DVertexSetIntRGBA(&Vertex2[1], r, g, b, a);\n\tRwIm2DVertexSetIntRGBA(&Vertex[1], r, g, b, a);\n\tRwIm2DVertexSetIntRGBA(&Vertex2[2], r, g, b, a);\n\tRwIm2DVertexSetIntRGBA(&Vertex[2], r, g, b, a);\n\tRwIm2DVertexSetIntRGBA(&Vertex2[3], r, g, b, a);\n\tRwIm2DVertexSetIntRGBA(&Vertex[3], r, g, b, a);\n\n\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE);\n\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE);\n\n\tRwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, Vertex, 4, Index, 6);\n\tRwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, BlurOn ? Vertex2 : Vertex, 4, Index, 6);\n}\n\nvoid\nCPostFX::RenderOverlaySniper(RwCamera *cam, int32 r, int32 g, int32 b, int32 a)\n{\n\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, pFrontBuffer);\n\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);\n\n\tRwIm2DVertexSetIntRGBA(&Vertex[0], r, g, b, 80);\n\tRwIm2DVertexSetIntRGBA(&Vertex[1], r, g, b, 80);\n\tRwIm2DVertexSetIntRGBA(&Vertex[2], r, g, b, 80);\n\tRwIm2DVertexSetIntRGBA(&Vertex[3], r, g, b, 80);\n\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);\n\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);\n\n\tRwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, Vertex, 4, Index, 6);\n}\n\nfloat CPostFX::Intensity = 1.0f;\n\nvoid\nCPostFX::RenderOverlayShader(RwCamera *cam, int32 r, int32 g, int32 b, int32 a)\n{\n\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, pBackBuffer);\n\n\tif(EffectSwitch == POSTFX_MOBILE){\n\t\tfloat mult[3], add[3];\n\t\tmult[0] = (r-64)/256.0f + 1.4f;\n\t\tmult[1] = (g-64)/256.0f + 1.4f;\n\t\tmult[2] = (b-64)/256.0f + 1.4f;\n\t\tadd[0] = r/1536.f - 0.05f;\n\t\tadd[1] = g/1536.f - 0.05f;\n\t\tadd[2] = b/1536.f - 0.05f;\n#ifdef RW_D3D9\n\t\trw::d3d::d3ddevice->SetPixelShaderConstantF(10, mult, 1);\n\t\trw::d3d::d3ddevice->SetPixelShaderConstantF(11, add, 1);\n\n\t\trw::d3d::im2dOverridePS = contrast_PS;\n#endif\n#ifdef RW_OPENGL\n\t\trw::gl3::im2dOverrideShader = contrast;\n\t\tcontrast->use();\n\t\tglUniform3fv(contrast->uniformLocations[u_contrastMult], 1, mult);\n\t\tglUniform3fv(contrast->uniformLocations[u_contrastAdd], 1, add);\n#endif\n\t}else{\n\t\tfloat f = Intensity;\n\t\tfloat blurcolors[4];\n\t\tblurcolors[0] = r*f/255.0f;\n\t\tblurcolors[1] = g*f/255.0f;\n\t\tblurcolors[2] = b*f/255.0f;\n\t\tblurcolors[3] = 30/255.0f;\n#ifdef RW_D3D9\n\t\trw::d3d::d3ddevice->SetPixelShaderConstantF(10, blurcolors, 1);\n\t\trw::d3d::im2dOverridePS = colourfilterVC_PS;\n#endif\n#ifdef RW_OPENGL\n\t\trw::gl3::im2dOverrideShader = colourFilterVC;\n\t\tcolourFilterVC->use();\n\t\tglUniform4fv(colourFilterVC->uniformLocations[u_blurcolor], 1, blurcolors);\n#endif\n\t}\n\tRwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, Vertex, 4, Index, 6);\n#ifdef RW_D3D9\n\trw::d3d::im2dOverridePS = nil;\n#endif\n#ifdef RW_OPENGL\n\trw::gl3::im2dOverrideShader = nil;\n#endif\n}\n\nvoid\nCPostFX::RenderMotionBlur(RwCamera *cam, uint32 blur)\n{\n\tif(blur == 0)\n\t\treturn;\n\n\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, pFrontBuffer);\n\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);\n\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);\n\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);\n\n\tRwIm2DVertexSetIntRGBA(&Vertex[0], 255, 255, 255, blur);\n\tRwIm2DVertexSetIntRGBA(&Vertex[1], 255, 255, 255, blur);\n\tRwIm2DVertexSetIntRGBA(&Vertex[2], 255, 255, 255, blur);\n\tRwIm2DVertexSetIntRGBA(&Vertex[3], 255, 255, 255, blur);\n\n\tRwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, Vertex, 4, Index, 6);\n}\n\nbool\nCPostFX::NeedBackBuffer(void)\n{\n\t// Current frame -- needed for non-blur effect\n\tswitch(EffectSwitch){\n\tcase POSTFX_OFF:\n\tcase POSTFX_SIMPLE:\n\t\t// no actual rendering here\n\t\treturn false;\n\tcase POSTFX_NORMAL:\n\t\tif(MotionBlurOn)\n\t\t\treturn false;\n\t\telse\n\t\t\treturn true;\n\tcase POSTFX_MOBILE:\n\t\treturn true;\n\t}\n\treturn false;\n}\n\nbool\nCPostFX::NeedFrontBuffer(int32 type)\n{\n\t// Last frame -- needed for motion blur\n\tif(CMBlur::Drunkness > 0.0f)\n\t\treturn true;\n\tif(type == MOTION_BLUR_SNIPER)\n\t\treturn true;\n\n\tswitch(EffectSwitch){\n\tcase POSTFX_OFF:\n\tcase POSTFX_SIMPLE:\n\t\t// no actual rendering here\n\t\treturn false;\n\tcase POSTFX_NORMAL:\n\t\tif(MotionBlurOn)\n\t\t\treturn true;\n\t\telse\n\t\t\treturn false;\n\tcase POSTFX_MOBILE:\n\t\treturn false;\n\t}\n\treturn false;\n}\n\nvoid\nCPostFX::GetBackBuffer(RwCamera *cam)\n{\n\tRwRasterPushContext(pBackBuffer);\n\tRwRasterRenderFast(RwCameraGetRaster(cam), 0, 0);\n\tRwRasterPopContext();\n}\n\nvoid\nCPostFX::Render(RwCamera *cam, uint32 red, uint32 green, uint32 blue, uint32 blur, int32 type, uint32 bluralpha)\n{\n\tPUSH_RENDERGROUP(\"CPostFX::Render\");\n\n\tif(pFrontBuffer == nil)\n\t\tOpen(cam);\n\tassert(pFrontBuffer);\n\tassert(pBackBuffer);\n\n\tif(type == MOTION_BLUR_LIGHT_SCENE){\n\t\tSmoothColor(red, green, blue, blur);\n\t\tred = AvgRed;\n\t\tgreen = AvgGreen;\n\t\tblue = AvgBlue;\n\t\tblur = AvgAlpha;\n\t}\n\n\tif(NeedBackBuffer())\n\t\tGetBackBuffer(cam);\n\n\tDefinedState();\n\n\tRwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE);\n\tRwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERNEAREST);\n\tRwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE);\n\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);\n\n\tif(type == MOTION_BLUR_SNIPER){\n\t\tif(!bJustInitialised)\n\t\t\tRenderOverlaySniper(cam, red, green, blue, blur);\n\t}else switch(EffectSwitch){\n\tcase POSTFX_OFF:\n\tcase POSTFX_SIMPLE:\n\t\t// no actual rendering here\n\t\tbreak;\n\tcase POSTFX_NORMAL:\n\t\tif(MotionBlurOn){\n\t\t\tif(!bJustInitialised)\n\t\t\t\tRenderOverlayBlur(cam, red, green, blue, blur);\n\t\t}else{\n\t\t\tRenderOverlayShader(cam, red, green, blue, blur);\n\t\t}\n\t\tbreak;\n\tcase POSTFX_MOBILE:\n\t\tRenderOverlayShader(cam, red, green, blue, blur);\n\t\tbreak;\n\t}\n\n\tif(!bJustInitialised)\n\t\tRenderMotionBlur(cam, 175.0f * CMBlur::Drunkness);\n\n\tRwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);\n\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);\n\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil);\n\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);\n\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);\n\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);\n\n\tif(NeedFrontBuffer(type)){\n\t\tRwRasterPushContext(pFrontBuffer);\n\t\tRwRasterRenderFast(RwCameraGetRaster(cam), 0, 0);\n\t\tRwRasterPopContext();\n\t\tbJustInitialised = false;\n\t}else\n\t\tbJustInitialised = true;\n\n\tPOP_RENDERGROUP();\n}\n\nint CPostFX::PrevRed[NUMAVERAGE], CPostFX::AvgRed;\nint CPostFX::PrevGreen[NUMAVERAGE], CPostFX::AvgGreen;\nint CPostFX::PrevBlue[NUMAVERAGE], CPostFX::AvgBlue;\nint CPostFX::PrevAlpha[NUMAVERAGE], CPostFX::AvgAlpha;\nint CPostFX::Next;\nint CPostFX::NumValues;\n\n// This is rather annoying...the blur color can flicker slightly\n// which becomes very visible when amplified by the shader\nvoid\nCPostFX::SmoothColor(uint32 red, uint32 green, uint32 blue, uint32 alpha)\n{\n\tPrevRed[Next] = red;\n\tPrevGreen[Next] = green;\n\tPrevBlue[Next] = blue;\n\tPrevAlpha[Next] = alpha;\n\tNext = (Next+1) % NUMAVERAGE;\n\tNumValues = Min(NumValues+1, NUMAVERAGE);\n\n\tAvgRed = 0;\n\tAvgGreen = 0;\n\tAvgBlue = 0;\n\tAvgAlpha = 0;\n\tfor(int i = 0; i < NumValues; i++){\n\t\tAvgRed += PrevRed[i];\n\t\tAvgGreen += PrevGreen[i];\n\t\tAvgBlue += PrevBlue[i];\n\t\tAvgAlpha += PrevAlpha[i];\n\t}\n\tAvgRed /= NumValues;\n\tAvgGreen /= NumValues;\n\tAvgBlue /= NumValues;\n\tAvgAlpha /= NumValues;\n}\n\n#endif\n"
  },
  {
    "path": "src/extras/postfx.h",
    "content": "#pragma once\n\n#ifdef EXTENDED_COLOURFILTER\n\nclass CPostFX\n{\npublic:\n\tenum {\n\t\tPOSTFX_OFF,\n\t\tPOSTFX_SIMPLE,\n\t\tPOSTFX_NORMAL,\n\t\tPOSTFX_MOBILE\n\t};\n\tstatic RwRaster *pFrontBuffer;\n\tstatic RwRaster *pBackBuffer;\n\tstatic bool bJustInitialised;\n\tstatic int EffectSwitch;\n\tstatic bool BlurOn;\t// or use CMblur for that?\n\tstatic bool MotionBlurOn;\t// or use CMblur for that?\n\tstatic float Intensity;\n\n\t// smooth blur color\n\tenum { NUMAVERAGE = 20 };\n\tstatic int PrevRed[NUMAVERAGE], AvgRed;\n\tstatic int PrevGreen[NUMAVERAGE], AvgGreen;\n\tstatic int PrevBlue[NUMAVERAGE], AvgBlue;\n\tstatic int PrevAlpha[NUMAVERAGE], AvgAlpha;\n\tstatic int Next;\n\tstatic int NumValues;\n\n\tstatic void InitOnce(void);\n\tstatic void Open(RwCamera *cam);\n\tstatic void Close(void);\n\tstatic void RenderOverlayBlur(RwCamera *cam, int32 r, int32 g, int32 b, int32 a);\n\tstatic void RenderOverlaySniper(RwCamera *cam, int32 r, int32 g, int32 b, int32 a);\n\tstatic void RenderOverlayShader(RwCamera *cam, int32 r, int32 g, int32 b, int32 a);\n\tstatic void RenderMotionBlur(RwCamera *cam, uint32 blur);\n\tstatic void Render(RwCamera *cam, uint32 red, uint32 green, uint32 blue, uint32 blur, int32 type, uint32 bluralpha);\n\tstatic void SmoothColor(uint32 red, uint32 green, uint32 blue, uint32 alpha);\n\tstatic bool NeedBackBuffer(void);\n\tstatic bool NeedFrontBuffer(int32 type);\n\tstatic void GetBackBuffer(RwCamera *cam);\n\tstatic bool UseBlurColours(void) { return EffectSwitch != POSTFX_SIMPLE; }\n};\n\n#endif\n"
  },
  {
    "path": "src/extras/re3_inttypes.h",
    "content": "#define PRId8     \"hhd\"\n#define PRId16    \"hd\"\n#define PRId32    \"ld\"\n#define PRId64    \"lld\"\n\n#define PRIdFAST8    \"hhd\"\n#define PRIdFAST16    \"hd\"\n#define PRIdFAST32    \"ld\"\n#define PRIdFAST64   \"lld\"\n\n#define PRIdLEAST8   \"hhd\"\n#define PRIdLEAST16  \"hd\"\n#define PRIdLEAST32  \"ld\"\n#define PRIdLEAST64  \"lld\"\n\n#define PRIdMAX   \"lld\"\n#define PRIdPTR   \"lld\"\n\n#define PRIi8     \"hhi\"\n#define PRIi16    \"hi\"\n#define PRIi32    \"li\"\n#define PRIi64    \"lli\"\n\n#define PRIiFAST8    \"hhi\"\n#define PRIiFAST16    \"hi\"\n#define PRIiFAST32    \"li\"\n#define PRIiFAST64    \"lli\"\n\n#define PRIiLEAST8   \"hhi\"\n#define PRIiLEAST16  \"hi\"\n#define PRIiLEAST32  \"li\"\n#define PRIiLEAST64  \"lli\"\n\n#define PRIiMAX   \"lli\"\n#define PRIiPTR   \"lli\"\n\n#define PRIo8     \"hho\"\n#define PRIo16    \"ho\"\n#define PRIo32    \"lo\"\n#define PRIo64    \"llo\"\n\n#define PRIoFAST8    \"hho\"\n#define PRIoFAST16    \"ho\"\n#define PRIoFAST32    \"lo\"\n#define PRIoFAST64   \"llo\"\n\n#define PRIoLEAST8   \"hho\"\n#define PRIoLEAST16  \"ho\"\n#define PRIoLEAST32  \"lo\"\n#define PRIoLEAST64  \"llo\"\n\n#define PRIoMAX   \"llo\"\n#define PRIoPTR   \"llo\"\n\n#define PRIu8     \"hhu\"\n#define PRIu16    \"hu\"\n#define PRIu32    \"lu\"\n#define PRIu64    \"llu\"\n\n#define PRIuFAST8    \"hhu\"\n#define PRIuFAST16    \"hu\"\n#define PRIuFAST32    \"lu\"\n#define PRIuFAST64   \"llu\"\n\n#define PRIuLEAST8   \"hhu\"\n#define PRIuLEAST16  \"hu\"\n#define PRIuLEAST32  \"lu\"\n#define PRIuLEAST64  \"llu\"\n\n#define PRIuMAX   \"llu\"\n#define PRIuPTR   \"llu\"\n\n#define PRIx8     \"hhx\"\n#define PRIx16    \"hx\"\n#define PRIx32    \"lx\"\n#define PRIx64    \"llx\"\n\n#define PRIxFAST8    \"hhx\"\n#define PRIxFAST16    \"hx\"\n#define PRIxFAST32    \"lx\"\n#define PRIxFAST64   \"llx\"\n\n#define PRIxLEAST8   \"hhx\"\n#define PRIxLEAST16  \"hx\"\n#define PRIxLEAST32  \"lx\"\n#define PRIxLEAST64  \"llx\"\n\n#define PRIxMAX   \"llx\"\n#define PRIxPTR   \"llx\"\n\n#define PRIX8     \"hhX\"\n#define PRIX16    \"hX\"\n#define PRIX32    \"lX\"\n#define PRIX64    \"llX\"\n\n#define PRIXFAST8    \"hhX\"\n#define PRIXFAST16    \"hX\"\n#define PRIXFAST32    \"lX\"\n#define PRIXFAST64   \"llX\"\n\n#define PRIXLEAST8   \"hhX\"\n#define PRIXLEAST16  \"hX\"\n#define PRIXLEAST32  \"lX\"\n#define PRIXLEAST64  \"llX\"\n\n#define PRIXMAX   \"llX\"\n#define PRIXPTR   \"llX\"\n\n        /* SCAN FORMAT MACROS */\n#define SCNd8     \"hhd\"\n#define SCNd16    \"hd\"\n#define SCNd32    \"ld\"\n#define SCNd64    \"lld\"\n\n#define SCNdFAST8    \"hhd\"\n#define SCNdFAST16    \"hd\"\n#define SCNdFAST32    \"ld\"\n#define SCNdFAST64   \"lld\"\n\n#define SCNdLEAST8   \"hhd\"\n#define SCNdLEAST16  \"hd\"\n#define SCNdLEAST32  \"ld\"\n#define SCNdLEAST64  \"lld\"\n\n#define SCNdMAX   \"lld\"\n#define SCNdPTR   \"lld\"\n\n#define SCNi8     \"hhi\"\n#define SCNi16    \"hi\"\n#define SCNi32    \"li\"\n#define SCNi64    \"lli\"\n\n#define SCNiFAST8    \"hhi\"\n#define SCNiFAST16    \"hi\"\n#define SCNiFAST32    \"li\"\n#define SCNiFAST64   \"lli\"\n\n#define SCNiLEAST8   \"hhi\"\n#define SCNiLEAST16  \"hi\"\n#define SCNiLEAST32  \"li\"\n#define SCNiLEAST64  \"lli\"\n\n#define SCNiMAX   \"lli\"\n#define SCNiPTR   \"lli\"\n\n#define SCNo8     \"hho\"\n#define SCNo16    \"ho\"\n#define SCNo32    \"lo\"\n#define SCNo64    \"llo\"\n\n#define SCNoFAST8    \"hho\"\n#define SCNoFAST16    \"ho\"\n#define SCNoFAST32    \"lo\"\n#define SCNoFAST64   \"llo\"\n\n#define SCNoLEAST8   \"hho\"\n#define SCNoLEAST16  \"ho\"\n#define SCNoLEAST32  \"lo\"\n#define SCNoLEAST64  \"llo\"\n\n#define SCNoMAX   \"llo\"\n#define SCNoPTR   \"llo\"\n\n#define SCNu8     \"hhu\"\n#define SCNu16    \"hu\"\n#define SCNu32    \"lu\"\n#define SCNu64    \"llu\"\n\n#define SCNuFAST8    \"hhu\"\n#define SCNuFAST16    \"hu\"\n#define SCNuFAST32    \"lu\"\n#define SCNuFAST64   \"llu\"\n\n#define SCNuLEAST8   \"hhu\"\n#define SCNuLEAST16  \"hu\"\n#define SCNuLEAST32  \"lu\"\n#define SCNuLEAST64  \"llu\"\n\n#define SCNuMAX   \"llu\"\n#define SCNuPTR   \"llu\"\n\n#define SCNx8     \"hhx\"\n#define SCNx16    \"hx\"\n#define SCNx32    \"lx\"\n#define SCNx64    \"llx\"\n\n#define SCNxFAST8    \"hhx\"\n#define SCNxFAST16    \"hx\"\n#define SCNxFAST32    \"lx\"\n#define SCNxFAST64   \"llx\"\n\n#define SCNxLEAST8   \"hhx\"\n#define SCNxLEAST16  \"hx\"\n#define SCNxLEAST32  \"lx\"\n#define SCNxLEAST64  \"llx\"\n\n#define SCNxMAX   \"llx\"\n#define SCNxPTR   \"llx\"\n\n#define SCNX8     \"hhX\"\n#define SCNX16    \"hX\"\n#define SCNX32    \"lX\"\n#define SCNX64    \"llX\"\n\n#define SCNXFAST8    \"hhX\"\n#define SCNXFAST16    \"hX\"\n#define SCNXFAST32    \"lX\"\n#define SCNXFAST64   \"llX\"\n\n#define SCNXLEAST8   \"hhX\"\n#define SCNXLEAST16  \"hX\"\n#define SCNXLEAST32  \"lX\"\n#define SCNXLEAST64  \"llX\"\n\n#define SCNXMAX   \"llX\"\n#define SCNXPTR   \"llX\""
  },
  {
    "path": "src/extras/screendroplets.cpp",
    "content": "#define WITHD3D\n#include \"common.h\"\n\n#ifdef SCREEN_DROPLETS\n\n#ifndef LIBRW\n#error \"Need librw for SCREEN_DROPLETS\"\n#endif\n\n#include \"General.h\"\n#include \"main.h\"\n#include \"RwHelper.h\"\n#include \"Timer.h\"\n#include \"Camera.h\"\n#include \"World.h\"\n#include \"ZoneCull.h\"\n#include \"Weather.h\"\n#include \"ParticleObject.h\"\n\t#include \"Pad.h\"\n#include \"RenderBuffer.h\"\n#include \"custompipes.h\"\n#include \"postfx.h\"\n#include \"screendroplets.h\"\n\n// for 640\n#define MAXSIZE 15\n#define MINSIZE 4\n\nint ScreenDroplets::ms_initialised;\nRwTexture *ScreenDroplets::ms_maskTex;\nRwTexture *ScreenDroplets::ms_screenTex;\n\nbool ScreenDroplets::ms_enabled = true;\nbool ScreenDroplets::ms_movingEnabled = true;\n\nScreenDroplets::ScreenDrop ScreenDroplets::ms_drops[ScreenDroplets::MAXDROPS];\nint ScreenDroplets::ms_numDrops;\nScreenDroplets::ScreenDropMoving ScreenDroplets::ms_dropsMoving[ScreenDroplets::MAXDROPSMOVING];\nint ScreenDroplets::ms_numDropsMoving;\n\nCVector ScreenDroplets::ms_prevCamUp;\nCVector ScreenDroplets::ms_prevCamPos;\nCVector ScreenDroplets::ms_camMoveDelta;\nfloat ScreenDroplets::ms_camMoveDist;\nCVector ScreenDroplets::ms_screenMoveDelta;\nfloat ScreenDroplets::ms_screenMoveDist;\nfloat ScreenDroplets::ms_camUpAngle;\n\nint ScreenDroplets::ms_splashDuration;\nCParticleObject *ScreenDroplets::ms_splashObject;\n\nstruct Im2DVertexUV2 : rw::RWDEVICE::Im2DVertex\n{\n\trw::float32 u2, v2;\n};\n\n#ifdef RW_D3D9\nstatic void *screenDroplet_PS;\n#endif\n#ifdef RW_GL3\nstatic rw::gl3::Shader *screenDroplet;\n#endif\n\n// platform specific\nstatic void openim2d_uv2(void);\nstatic void closeim2d_uv2(void);\nstatic void RenderIndexedPrimitive_UV2(RwPrimitiveType primType, Im2DVertexUV2 *vertices, RwInt32 numVertices, RwImVertexIndex *indices, RwInt32 numIndices);\n\nstatic Im2DVertexUV2 VertexBuffer[TEMPBUFFERVERTSIZE];\n\nvoid\nScreenDroplets::Initialise(void)\n{\n\tClear();\n\tms_splashDuration = -1;\n\tms_splashObject = nil;\n}\n\n// Create white circle mask for rain drops\nstatic RwTexture*\nCreateDropMask(int32 size)\n{\n\tRwImage *img = RwImageCreate(size, size, 32);\n\tRwImageAllocatePixels(img);\n\n\tuint8 *pixels = RwImageGetPixels(img);\n\tint32 stride = RwImageGetStride(img);\n\n\tfor(int y = 0; y < size; y++){\n\t\tfloat yf = ((y + 0.5f)/size - 0.5f)*2.0f;\n\t\tfor(int x = 0; x < size; x++){\n\t\t\tfloat xf = ((x + 0.5f)/size - 0.5f)*2.0f;\n\t\t\tmemset(&pixels[y*stride + x*4], xf*xf + yf*yf < 1.0f ? 0xFF : 0x00, 4);\n\t\t}\n\t}\n\n\tint32 width, height, depth, format;\n\tRwImageFindRasterFormat(img, rwRASTERTYPETEXTURE, &width, &height, &depth, &format);\n\tRwRaster *ras = RwRasterCreate(width, height, depth, format);\n\tRwRasterSetFromImage(ras, img);\n\tRwImageDestroy(img);\n\treturn RwTextureCreate(ras);\n}\n\nvoid\nScreenDroplets::InitDraw(void)\n{\n\tms_maskTex = CreateDropMask(64);\n\n\tms_screenTex = RwTextureCreate(nil);\n\tRwTextureSetFilterMode(ms_screenTex, rwFILTERLINEAR);\n\n\topenim2d_uv2();\n#ifdef RW_D3D9\n#include \"shaders/obj/screenDroplet_PS.inc\"\n\tscreenDroplet_PS = rw::d3d::createPixelShader(screenDroplet_PS_cso);\n#endif\n#ifdef RW_GL3\n\tusing namespace rw::gl3;\n\t{\n#include \"shaders/obj/im2d_UV2_vert.inc\"\n#include \"shaders/obj/screenDroplet_frag.inc\"\n\tconst char *vs[] = { shaderDecl, header_vert_src, im2d_UV2_vert_src, nil };\n\tconst char *fs[] = { shaderDecl, header_frag_src, screenDroplet_frag_src, nil };\n\tscreenDroplet = Shader::create(vs, fs);\n\tassert(screenDroplet);\n\t}\n#endif\n\n\tms_initialised = 1;\n}\n\nvoid\nScreenDroplets::Shutdown(void)\n{\n\tif(ms_maskTex){\n\t\tRwTextureDestroy(ms_maskTex);\n\t\tms_maskTex = nil;\n\t}\n\tif(ms_screenTex){\n\t\tRwTextureSetRaster(ms_screenTex, nil);\n\t\tRwTextureDestroy(ms_screenTex);\n\t\tms_screenTex = nil;\n\t}\n#ifdef RW_D3D9\n\tif(screenDroplet_PS){\n\t\trw::d3d::destroyPixelShader(screenDroplet_PS);\n\t\tscreenDroplet_PS = nil;\n\t}\n#endif\n#ifdef RW_GL3\n\tif(screenDroplet){\n\t\tscreenDroplet->destroy();\n\t\tscreenDroplet = nil;\n\t}\n#endif\n\n\tcloseim2d_uv2();\n}\n\nvoid\nScreenDroplets::Process(void)\n{\n\tProcessCameraMovement();\n\tSprayDrops();\n\tProcessMoving();\n\tFade();\n}\n\nstatic void\nFlushBuffer(void)\n{\n\tif(TempBufferIndicesStored){\n\t\tRenderIndexedPrimitive_UV2(rwPRIMTYPETRILIST,\n\t\t\tVertexBuffer, TempBufferVerticesStored,\n\t\t\tTempBufferRenderIndexList, TempBufferIndicesStored);\n\t\tTempBufferVerticesStored = 0;\n\t\tTempBufferIndicesStored = 0;\n\t}\n}\n\nstatic int\nStartStoring(int numIndices, int numVertices, RwImVertexIndex **indexStart, Im2DVertexUV2 **vertexStart)\n{\n\tif(TempBufferIndicesStored + numIndices >= TEMPBUFFERINDEXSIZE ||\n\t   TempBufferVerticesStored + numVertices >= TEMPBUFFERVERTSIZE)\n\t\tFlushBuffer();\n        *indexStart = &TempBufferRenderIndexList[TempBufferIndicesStored];\n        *vertexStart = &VertexBuffer[TempBufferVerticesStored];\n\tint vertOffset = TempBufferVerticesStored;\n        TempBufferIndicesStored += numIndices;\n        TempBufferVerticesStored += numVertices;\n\treturn vertOffset;\n}\n\nvoid\nScreenDroplets::Render(void)\n{\n\tScreenDrop *drop;\n\n\tDefinedState();\n\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(ms_maskTex));\n\tRwRenderStateSet(rwRENDERSTATEFOGENABLE, FALSE);\n\tRwRenderStateSet(rwRENDERSTATEZTESTENABLE, FALSE);\n\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE, FALSE);\n\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);\n\n\tRwTextureSetRaster(ms_screenTex, CPostFX::pBackBuffer);\n#ifdef RW_D3D9\n\trw::d3d::im2dOverridePS = screenDroplet_PS;\n\trw::d3d::setTexture(1, ms_screenTex);\n#endif\n#ifdef RW_GL3\n\trw::gl3::im2dOverrideShader = screenDroplet;\n\trw::gl3::setTexture(1, ms_screenTex);\n#endif\n\n\tRenderBuffer::ClearRenderBuffer();\n\tfor(drop = &ms_drops[0]; drop < &ms_drops[MAXDROPS]; drop++)\n\t\tif(drop->active)\n\t\t\tAddToRenderList(drop);\n\tFlushBuffer();\n\n#ifdef RW_D3D9\n\trw::d3d::im2dOverridePS = nil;\n\trw::d3d::setTexture(1, nil);\n#endif\n#ifdef RW_GL3\n\trw::gl3::im2dOverrideShader = nil;\n\trw::gl3::setTexture(1, nil);\n#endif\n\n\tRwRenderStateSet(rwRENDERSTATEFOGENABLE, FALSE);\n\tRwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);\n\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);\n\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil);\n\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, FALSE);\n}\n\nvoid\nScreenDroplets::AddToRenderList(ScreenDroplets::ScreenDrop *drop)\n{\n\tstatic float xy[] = {\n\t\t-1.0f, -1.0f,\n\t\t-1.0f,  1.0f,\n\t\t1.0f,  1.0f,\n\t\t1.0f, -1.0f\n\t};\n\tstatic float uv[] = {\n\t\t0.0f, 0.0f,\n\t\t0.0f, 1.0f,\n\t\t1.0f, 1.0f,\n\t\t1.0f, 0.0f\n\t};\n\n\tint i;\n\tRwImVertexIndex *indices;\n\tIm2DVertexUV2 *verts;\n\tint first = StartStoring(6, 4, &indices, &verts);\n\n\tfloat scale = 0.5f*SCREEN_SCALE_X(drop->size);\n\n\tfloat screenz = RwIm2DGetNearScreenZ();\n\tfloat z = RwCameraGetNearClipPlane(Scene.camera);\n\tfloat recipz = 1.0f/z;\n\n\tfloat magSize = SCREEN_SCALE_Y(drop->magnification*(300.0f-40.0f) + 40.0f);\n\tfloat ul = drop->x - magSize;\n\tfloat vt = drop->y - magSize;\n\tfloat ur = drop->x + magSize;\n\tfloat vb = drop->y + magSize;\n\tul = Max(ul, 0.0f)/RwRasterGetWidth(CPostFX::pBackBuffer);\n\tvt = Max(vt, 0.0f)/RwRasterGetHeight(CPostFX::pBackBuffer);\n\tur = Min(ur, SCREEN_WIDTH)/RwRasterGetWidth(CPostFX::pBackBuffer);\n\tvb = Min(vb, SCREEN_HEIGHT)/RwRasterGetHeight(CPostFX::pBackBuffer);\n\n\tfor(i = 0; i < 4; i++){\n\t\tRwIm2DVertexSetScreenX(&verts[i], drop->x + xy[i*2]*scale);\n\t\tRwIm2DVertexSetScreenY(&verts[i], drop->y + xy[i*2+1]*scale);\n\t\tRwIm2DVertexSetScreenZ(&verts[i], screenz);\n\t\tRwIm2DVertexSetCameraZ(&verts[i], z);\n\t\tRwIm2DVertexSetRecipCameraZ(&verts[i], recipz);\n\t\tRwIm2DVertexSetIntRGBA(&verts[i], drop->color.r, drop->color.g, drop->color.b, drop->color.a);\n\t\tRwIm2DVertexSetU(&verts[i], uv[i*2], recipz);\n\t\tRwIm2DVertexSetV(&verts[i], uv[i*2+1], recipz);\n\n\t\tverts[i].u2 = i < 2 ? ul : ur;\n\t\tverts[i].v2 = i % 3 ? vt : vb;\n\t}\n\tindices[0] = first + 0;\n\tindices[1] = first + 1;\n\tindices[2] = first + 2;\n\tindices[3] = first + 2;\n\tindices[4] = first + 3;\n\tindices[5] = first + 0;\n}\n\nvoid\nScreenDroplets::Clear(void)\n{\n\tScreenDrop *drop;\n\tfor(drop = &ms_drops[0]; drop < &ms_drops[MAXDROPS]; drop++)\n\t\tdrop->active = false;\n\tms_numDrops = 0;\n}\n\nScreenDroplets::ScreenDrop*\nScreenDroplets::NewDrop(float x, float y, float size, float lifetime, bool fades, int r, int g, int b)\n{\n\tScreenDrop *drop;\n\tint i;\n\n\tfor(i = 0, drop = ms_drops; i < MAXDROPS; i++, drop++)\n\t\tif(!ms_drops[i].active)\n\t\t\tgoto found;\n\treturn nil;\nfound:\n\tms_numDrops++;\n\tdrop->x = x;\n\tdrop->y = y;\n\tdrop->size = size;\n\tdrop->magnification = (MAXSIZE - size + 1.0f) / (MAXSIZE - MINSIZE + 1.0f);\n\tdrop->fades = fades;\n\tdrop->active = true;\n\tdrop->color.r = r;\n\tdrop->color.g = g;\n\tdrop->color.b = b;\n\tdrop->color.a = 255;\n\tdrop->time = 0.0f;\n\tdrop->lifetime = lifetime;\n\treturn drop;\n}\n\nvoid\nScreenDroplets::SetMoving(ScreenDroplets::ScreenDrop *drop)\n{\n\tScreenDropMoving *moving;\n\tfor(moving = ms_dropsMoving; moving < &ms_dropsMoving[MAXDROPSMOVING]; moving++)\n\t\tif(moving->drop == nil)\n\t\t\tgoto found;\n\treturn;\nfound:\n\tms_numDropsMoving++;\n\tmoving->drop = drop;\n\tmoving->dist = 0.0f;\n}\n\nvoid\nScreenDroplets::FillScreen(int n)\n{\n\tfloat x, y, size;\n\tScreenDrop *drop;\n\n\tif(!ms_initialised)\n\t\treturn;\n\tms_numDrops = 0;\n\tfor(drop = &ms_drops[0]; drop < &ms_drops[MAXDROPS]; drop++){\n\t\tdrop->active = false;\n\t\tif(drop < &ms_drops[n]){\n\t\t\tx = CGeneral::GetRandomNumber() % (int)SCREEN_WIDTH;\n\t\t\ty = CGeneral::GetRandomNumber() % (int)SCREEN_HEIGHT;\n\t\t\tsize = CGeneral::GetRandomNumberInRange(MINSIZE, MAXSIZE);\n\t\t\tNewDrop(x, y, size, 2000.0f, true);\n\t\t}\n\t}\n}\n\nvoid\nScreenDroplets::FillScreenMoving(float amount, bool isBlood)\n{\n\tint n = (ms_screenMoveDelta.z > 5.0f ? 1.5f : 1.0f)*amount*20.0f;\n\tfloat x, y, size;\n\tScreenDrop *drop;\n\n\twhile(n--)\n\t\tif(ms_numDrops < MAXDROPS && ms_numDropsMoving < MAXDROPSMOVING){\n\t\t\tx = CGeneral::GetRandomNumber() % (int)SCREEN_WIDTH;\n\t\t\ty = CGeneral::GetRandomNumber() % (int)SCREEN_HEIGHT;\n\t\t\tsize = CGeneral::GetRandomNumberInRange(MINSIZE, MAXSIZE);\n\t\t\tdrop = nil;\n\t\t\tif(isBlood)\n\t\t\t\tdrop = NewDrop(x, y, size, 2000.0f, true, 255, 0, 0);\n\t\t\telse\n\t\t\t\tdrop = NewDrop(x, y, size, 2000.0f, true);\n\t\t\tif(drop)\n\t\t\t\tSetMoving(drop);\n\t\t}\n}\n\nvoid\nScreenDroplets::RegisterSplash(CParticleObject *pobj)\n{\n\tCVector dist = pobj->GetPosition() - ms_prevCamPos;\n\tif(dist.MagnitudeSqr() < 50.0f){\t// 20 originally\n\t\tms_splashDuration = 14;\n\t\tms_splashObject = pobj;\n\t}\n}\n\nvoid\nScreenDroplets::ProcessCameraMovement(void)\n{\n\tRwMatrix *camMat = RwFrameGetMatrix(RwCameraGetFrame(Scene.camera));\n\tCVector camPos = camMat->pos;\n\tCVector camUp = camMat->at;\n\tms_camMoveDelta = camPos - ms_prevCamPos;\n\tms_camMoveDist = ms_camMoveDelta.Magnitude();\n\n\tms_prevCamUp = camUp;\n\tms_prevCamPos = camPos;\n\n\tms_screenMoveDelta.x = -RwV3dDotProduct(&camMat->right, &ms_camMoveDelta);\n\tms_screenMoveDelta.y = RwV3dDotProduct(&camMat->up, &ms_camMoveDelta);\n\tms_screenMoveDelta.z = RwV3dDotProduct(&camMat->at, &ms_camMoveDelta);\n\tms_screenMoveDelta *= 10.0f;\n\tms_screenMoveDist = ms_screenMoveDelta.Magnitude2D();\n\n\tuint16 mode = TheCamera.Cams[TheCamera.ActiveCam].Mode;\n\tbool isTopDown = mode == CCam::MODE_TOPDOWN || mode == CCam::MODE_GTACLASSIC || mode == CCam::MODE_TOP_DOWN_PED;\n\tbool isLookingInDirection = FindPlayerVehicle() && mode == CCam::MODE_1STPERSON &&\n\t\t(CPad::GetPad(0)->GetLookBehindForCar() || CPad::GetPad(0)->GetLookLeft() || CPad::GetPad(0)->GetLookRight());\n\tms_enabled = !isTopDown && !isLookingInDirection;\n\tms_movingEnabled = !isTopDown && !isLookingInDirection;\n\n\t// 0 when looking stright up, 180 when looking up or down\n\tms_camUpAngle = RADTODEG(Acos(clamp(camUp.z, -1.0f, 1.0f)));\n}\n\nvoid\nScreenDroplets::SprayDrops(void)\n{\n\tbool noRain = CCullZones::PlayerNoRain() || CCullZones::CamNoRain();\n\tif(!noRain && CWeather::Rain > 0.0f && ms_enabled){\n\t\t// 180 when looking stright up, 0 when looking up or down\n\t\tfloat angle = 180.0f - ms_camUpAngle;\n\t\tangle = Max(angle, 40.0f);\t// want at least some rain\n\t\tFillScreenMoving((angle - 40.0f) / 150.0f * CWeather::Rain * 0.5f);\n\t}\n\n\tint i;\n\tfor(i = 0; i < MAX_AUDIOHYDRANTS; i++){\n\t\tCAudioHydrant *hyd = CAudioHydrant::Get(i);\n\t\tif (hyd->pParticleObject){\n\t\t\tCVector dist = hyd->pParticleObject->GetPosition() - ms_prevCamPos;\n\t\t\tif(dist.MagnitudeSqr() > 40.0f ||\n\t\t\t   DotProduct(dist, ms_prevCamUp) < 0.0f) continue;\n\n\t\t\tFillScreenMoving(1.0f);\n\t\t}\n\t}\n\n\tstatic int ndrops[] = {\n\t\t125, 250, 500, 1000, 1000,\n\t\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0\n\t};\n\tif(ms_splashDuration >= 0){\n\t\tif(ms_numDrops < MAXDROPS) {\n\t\t\tfloat numDropMult = 1.0f;\n\t\t\tif(ms_splashObject){\n\t\t\t\tfloat dist = (ms_splashObject->GetPosition() - ms_prevCamPos).Magnitude();\n\t\t\t\tnumDropMult = 1.0f - (dist - 5.0f)/15.0f;\n\t\t\t\tif(numDropMult < 0) numDropMult = 0.0f;\t// fix\n\t\t\t}\n\t\t\tint n = ndrops[ms_splashDuration] * numDropMult;\n\t\t\twhile(n--)\n\t\t\t\tif(ms_numDrops < MAXDROPS){\n\t\t\t\t\tfloat x = CGeneral::GetRandomNumber() % (int)SCREEN_WIDTH;\n\t\t\t\t\tfloat y = CGeneral::GetRandomNumber() % (int)SCREEN_HEIGHT;\n\t\t\t\t\tfloat size = CGeneral::GetRandomNumberInRange(MINSIZE, MAXSIZE);\n\t\t\t\t\tNewDrop(x, y, size, 10000.0f, false);\n\t\t\t\t}\n\t\t}\n\t\tms_splashDuration--;\n\t}\n}\n\nvoid\nScreenDroplets::NewTrace(ScreenDroplets::ScreenDropMoving *moving)\n{\n\tif(ms_numDrops < MAXDROPS){\n\t\tmoving->dist = 0.0f;\n\t\tNewDrop(moving->drop->x, moving->drop->y, MINSIZE, 500.0f, true,\n\t\t\tmoving->drop->color.r, moving->drop->color.g, moving->drop->color.b);\n\t}\n}\n\nvoid\nScreenDroplets::MoveDrop(ScreenDroplets::ScreenDropMoving *moving)\n{\n\tScreenDrop *drop = moving->drop;\n\tif(!ms_movingEnabled)\n\t\treturn;\n\tif(!drop->active){\n\t\tmoving->drop = nil;\n\t\tms_numDropsMoving--;\n\t\treturn;\n\t}\n\tif(ms_screenMoveDelta.z > 0.0f && ms_camMoveDist > 0.3f){\n\t\tif(ms_screenMoveDist > 0.5f && TheCamera.Cams[TheCamera.ActiveCam].Mode != CCam::MODE_1STPERSON){\n\t\t\t// movement when camera turns\n\t\t\tmoving->dist += ms_screenMoveDist;\n\t\t\tif(moving->dist > 20.0f && drop->color.a > 100)\n\t\t\t\tNewTrace(moving);\n\n\t\t\tdrop->x -= ms_screenMoveDelta.x;\n\t\t\tdrop->y += ms_screenMoveDelta.y;\n\t\t}else{\n\t\t\t// movement out of center \n\t\t\tfloat d = ms_screenMoveDelta.z*0.2f;\n\t\t\tfloat dx, dy, sum;\n\t\t\tdx = drop->x - SCREEN_WIDTH*0.5f + ms_screenMoveDelta.x;\n\t\t\tif(TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_1STPERSON)\n\t\t\t\tdy = drop->y - SCREEN_HEIGHT*1.2f - ms_screenMoveDelta.y;\n\t\t\telse\n\t\t\t\tdy = drop->y - SCREEN_HEIGHT*0.5f - ms_screenMoveDelta.y;\n\t\t\tsum = fabs(dx) + fabs(dy);\n\t\t\tif(sum > 0.001f){\n\t\t\t\tdx /= sum;\n\t\t\t\tdy /= sum;\n\t\t\t}\n\t\t\tmoving->dist += d;\n\t\t\tif(moving->dist > 20.0f && drop->color.a > 100)\n\t\t\t\tNewTrace(moving);\n\t\t\tdrop->x += dx * d;\n\t\t\tdrop->y += dy * d;\n\t\t}\n\n\t\tif(drop->x < 0.0f || drop->y < 0.0f ||\n\t\t   drop->x > SCREEN_WIDTH || drop->y > SCREEN_HEIGHT){\n\t\t\tmoving->drop = nil;\n\t\t\tms_numDropsMoving--;\n\t\t}\n\t}\n}\n\nvoid\nScreenDroplets::ProcessMoving(void)\n{\n\tScreenDropMoving *moving;\n\tif(!ms_movingEnabled)\n\t\treturn;\n\tfor(moving = ms_dropsMoving; moving < &ms_dropsMoving[MAXDROPSMOVING]; moving++)\n\t\tif(moving->drop)\n\t\t\tMoveDrop(moving);\n}\n\nvoid\nScreenDroplets::Fade(void)\n{\n\tScreenDrop *drop;\n\tfor(drop = &ms_drops[0]; drop < &ms_drops[MAXDROPS]; drop++)\n\t\tif(drop->active)\n\t\t\tdrop->Fade();\n}\n\nvoid\nScreenDroplets::ScreenDrop::Fade(void)\n{\n\tint delta = CTimer::GetTimeStepInMilliseconds();\n\ttime += delta;\n\tif(time < lifetime){\n\t\tcolor.a = 255 - time/lifetime*255;\n\t}else if(fades){\n\t\tScreenDroplets::ms_numDrops--;\n\t\tactive = false;\n\t}\n}\n\n\n/*\n * Im2D with two uv coors\n */\n\n#ifdef RW_D3D9\n// stolen from RW, not in a public header\nnamespace rw {\nnamespace d3d {\nvoid addDynamicVB(uint32 length, uint32 fvf, IDirect3DVertexBuffer9 **buf);\t// NB: don't share this pointer\nvoid removeDynamicVB(IDirect3DVertexBuffer9 **buf);\nvoid addDynamicIB(uint32 length, IDirect3DIndexBuffer9 **buf);\t// NB: don't share this pointer\nvoid removeDynamicIB(IDirect3DIndexBuffer9 **buf);\n}\n}\n// different than im2d\n#define NUMINDICES 1024\n#define NUMVERTICES 1024\n\nstatic int primTypeMap[] = {\n\tD3DPT_POINTLIST,\t// invalid\n\tD3DPT_LINELIST,\n\tD3DPT_LINESTRIP,\n\tD3DPT_TRIANGLELIST,\n\tD3DPT_TRIANGLESTRIP,\n\tD3DPT_TRIANGLEFAN,\n\tD3DPT_POINTLIST,\t// actually not supported!\n};\n// end of stolen stuff\n\n\nstatic IDirect3DVertexDeclaration9 *im2ddecl_uv2;\nstatic IDirect3DVertexBuffer9 *im2dvertbuf_uv2;\nstatic IDirect3DIndexBuffer9 *im2dindbuf_uv2;\n\nvoid\nopenim2d_uv2(void)\n{\n\tusing namespace rw;\n\tusing namespace d3d;\n\tD3DVERTEXELEMENT9 elements[5] = {\n\t\t{ 0, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITIONT, 0 },\n\t\t{ 0, offsetof(Im2DVertexUV2, color), D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0 },\n\t\t{ 0, offsetof(Im2DVertexUV2, u), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 },\n\t\t{ 0, offsetof(Im2DVertexUV2, u2), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1 },\n\t\tD3DDECL_END()\n\t};\n\tassert(im2ddecl_uv2 == nil);\n\tim2ddecl_uv2 = (IDirect3DVertexDeclaration9*)d3d9::createVertexDeclaration((d3d9::VertexElement*)elements);\n\tassert(im2ddecl_uv2);\n\n\tassert(im2dvertbuf_uv2 == nil);\n\tim2dvertbuf_uv2 = (IDirect3DVertexBuffer9*)createVertexBuffer(NUMVERTICES*sizeof(Im2DVertexUV2), 0, true);\n\tassert(im2dvertbuf_uv2);\n\taddDynamicVB(NUMVERTICES*sizeof(Im2DVertexUV2), 0, &im2dvertbuf_uv2);\n\n\tassert(im2dindbuf_uv2 == nil);\n\tim2dindbuf_uv2 = (IDirect3DIndexBuffer9*)createIndexBuffer(NUMINDICES*sizeof(rw::uint16), true);\n\tassert(im2dindbuf_uv2);\n\taddDynamicIB(NUMINDICES*sizeof(rw::uint16), &im2dindbuf_uv2);\n}\n\nvoid\ncloseim2d_uv2(void)\n{\n\tusing namespace rw;\n\tusing namespace d3d;\n\n\td3d9::destroyVertexDeclaration(im2ddecl_uv2);\n\tim2ddecl_uv2 = nil;\n\n\tremoveDynamicVB(&im2dvertbuf_uv2);\n\tdestroyVertexBuffer(im2dvertbuf_uv2);\n\tim2dvertbuf_uv2 = nil;\n\n\tremoveDynamicIB(&im2dindbuf_uv2);\n\tdestroyIndexBuffer(im2dindbuf_uv2);\n\tim2dindbuf_uv2 = nil;\n}\n\nvoid\nRenderIndexedPrimitive_UV2(RwPrimitiveType primType, Im2DVertexUV2 *vertices, RwInt32 numVertices, RwImVertexIndex *indices, RwInt32 numIndices)\n{\n\tusing namespace rw;\n\tusing namespace d3d;\n\n\tif(numVertices > NUMVERTICES ||\n\t   numIndices > NUMINDICES){\n\t\t// TODO: error\n\t\treturn;\n\t}\n\trw::uint16 *lockedindices = lockIndices(im2dindbuf_uv2, 0, numIndices*sizeof(rw::uint16), D3DLOCK_DISCARD);\n\tmemcpy(lockedindices, indices, numIndices*sizeof(rw::uint16));\n\tunlockIndices(im2dindbuf_uv2);\n\n\trw::uint8 *lockedvertices = lockVertices(im2dvertbuf_uv2, 0, numVertices*sizeof(Im2DVertexUV2), D3DLOCK_DISCARD);\n\tmemcpy(lockedvertices, vertices, numVertices*sizeof(Im2DVertexUV2));\n\tunlockVertices(im2dvertbuf_uv2);\n\n\tsetStreamSource(0, im2dvertbuf_uv2, 0, sizeof(Im2DVertexUV2));\n\tsetIndices(im2dindbuf_uv2);\n\tsetVertexDeclaration(im2ddecl_uv2);\n\n\tif(im2dOverridePS)\n\t\tsetPixelShader(im2dOverridePS);\n\telse if(engine->device.getRenderState(TEXTURERASTER))\n\t\tsetPixelShader(im2d_tex_PS);\n\telse\n\t\tsetPixelShader(im2d_PS);\n\n\td3d::flushCache();\n\n\trw::uint32 primCount = 0;\n\tswitch(primType){\n\tcase PRIMTYPELINELIST:\n\t\tprimCount = numIndices/2;\n\t\tbreak;\n\tcase PRIMTYPEPOLYLINE:\n\t\tprimCount = numIndices-1;\n\t\tbreak;\n\tcase PRIMTYPETRILIST:\n\t\tprimCount = numIndices/3;\n\t\tbreak;\n\tcase PRIMTYPETRISTRIP:\n\t\tprimCount = numIndices-2;\n\t\tbreak;\n\tcase PRIMTYPETRIFAN:\n\t\tprimCount = numIndices-2;\n\t\tbreak;\n\tcase PRIMTYPEPOINTLIST:\n\t\tprimCount = numIndices;\n\t\tbreak;\n\t}\n\td3ddevice->DrawIndexedPrimitive((D3DPRIMITIVETYPE)primTypeMap[primType], 0,\n\t                                0, numVertices,\n\t                                0, primCount);\n}\n#endif\n\n#ifdef RW_GL3\n// different than im2d\n#define NUMINDICES 1024\n#define NUMVERTICES 1024\n\nstatic rw::gl3::AttribDesc im2d_UV2_attribDesc[4] = {\n\t{ rw::gl3::ATTRIB_POS,        GL_FLOAT,         GL_FALSE, 4,\n\t\tsizeof(Im2DVertexUV2), 0 },\n\t{ rw::gl3::ATTRIB_COLOR,      GL_UNSIGNED_BYTE, GL_TRUE,  4,\n\t\tsizeof(Im2DVertexUV2), offsetof(Im2DVertexUV2, r) },\n\t{ rw::gl3::ATTRIB_TEXCOORDS0, GL_FLOAT,         GL_FALSE, 2,\n\t\tsizeof(Im2DVertexUV2), offsetof(Im2DVertexUV2, u) },\n\t{ rw::gl3::ATTRIB_TEXCOORDS1, GL_FLOAT,         GL_FALSE, 2,\n\t\tsizeof(Im2DVertexUV2), offsetof(Im2DVertexUV2, u2) }\n};\n\nstatic int primTypeMap[] = {\n\tGL_POINTS,\t// invalid\n\tGL_LINES,\n\tGL_LINE_STRIP,\n\tGL_TRIANGLES,\n\tGL_TRIANGLE_STRIP,\n\tGL_TRIANGLE_FAN,\n\tGL_POINTS\n};\n\nstatic int32 u_xform;\n\nuint32 im2D_UV2_Vbo, im2D_UV2_Ibo;\n#ifdef RW_GL_USE_VAOS\nuint32 im2D_UV2_Vao;\n#endif\n\nvoid\nopenim2d_uv2(void)\n{\n\tu_xform = rw::gl3::registerUniform(\"u_xform\");\t// this doesn't add a new one, so it's safe\n\n\tglGenBuffers(1, &im2D_UV2_Ibo);\n\tglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, im2D_UV2_Ibo);\n\tglBufferData(GL_ELEMENT_ARRAY_BUFFER, NUMINDICES*2, nil, GL_STREAM_DRAW);\n\n\tglGenBuffers(1, &im2D_UV2_Vbo);\n\tglBindBuffer(GL_ARRAY_BUFFER, im2D_UV2_Vbo);\n\tglBufferData(GL_ARRAY_BUFFER, NUMVERTICES*sizeof(Im2DVertexUV2), nil, GL_STREAM_DRAW);\n\n#ifdef RW_GL_USE_VAOS\n\tglGenVertexArrays(1, &im2D_UV2_Vao);\n\tglBindVertexArray(im2D_UV2_Vao);\n\tsetAttribPointers(im2d_UV2_attribDesc, 4);\n#endif\n}\n\nvoid\ncloseim2d_uv2(void)\n{\n\tglDeleteBuffers(1, &im2D_UV2_Ibo);\n\tglDeleteBuffers(1, &im2D_UV2_Vbo);\n#ifdef RW_GL_USE_VAOS\n\tglDeleteVertexArrays(1, &im2D_UV2_Vao);\n#endif\n}\n\nvoid\nRenderIndexedPrimitive_UV2(RwPrimitiveType primType, Im2DVertexUV2 *vertices, RwInt32 numVertices, RwImVertexIndex *indices, RwInt32 numIndices)\n{\n\tusing namespace rw;\n\tusing namespace gl3;\n\n\tGLfloat xform[4];\n\tCamera *cam;\n\tcam = (Camera*)engine->currentCamera;\n\n#ifdef RW_GL_USE_VAOS\n\tglBindVertexArray(im2D_UV2_Vao);\n#endif\n\n\tglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, im2D_UV2_Ibo);\n\tglBufferData(GL_ELEMENT_ARRAY_BUFFER, NUMINDICES*2, nil, GL_STREAM_DRAW);\n\tglBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, numIndices*2, indices);\n\n\tglBindBuffer(GL_ARRAY_BUFFER, im2D_UV2_Vbo);\n\tglBufferData(GL_ARRAY_BUFFER, NUMVERTICES*sizeof(Im2DVertexUV2), nil, GL_STREAM_DRAW);\n\tglBufferSubData(GL_ARRAY_BUFFER, 0, numVertices*sizeof(Im2DVertexUV2), vertices);\n\n\txform[0] = 2.0f/cam->frameBuffer->width;\n\txform[1] = -2.0f/cam->frameBuffer->height;\n\txform[2] = -1.0f;\n\txform[3] = 1.0f;\n\n\tif(im2dOverrideShader)\n\t\tim2dOverrideShader->use();\n\telse\n\t\tassert(0);//im2dShader->use();\n#ifndef RW_GL_USE_VAOS\n\tsetAttribPointers(im2d_UV2_attribDesc, 4);\n#endif\n\n\tglUniform4fv(currentShader->uniformLocations[u_xform], 1, xform);\n\n\tflushCache();\n\tglDrawElements(primTypeMap[primType], numIndices,\n\t               GL_UNSIGNED_SHORT, nil);\n#ifndef RW_GL_USE_VAOS\n\tdisableAttribPointers(im2d_UV2_attribDesc, 4);\n#endif\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "src/extras/screendroplets.h",
    "content": "#pragma once\n\n#ifdef SCREEN_DROPLETS\n\nclass CParticleObject;\n\nclass ScreenDroplets\n{\npublic:\n\tenum {\n\t\tMAXDROPS = 2000,\n\t\tMAXDROPSMOVING = 700\n\t};\n\n\tclass ScreenDrop\n\t{\n\tpublic:\n\t\tfloat x, y, time;\t\t// shorts on xbox (short float?)\n\t\tfloat size, magnification, lifetime;\t// \"\n\t\tCRGBA color;\n\t\tbool active;\n\t\tbool fades;\n\n\t\tvoid Fade(void);\n\t};\n\n\tstruct ScreenDropMoving\n\t{\n\t\tScreenDrop *drop;\n\t\tfloat dist;\n\t};\n\n\tstatic int ms_initialised;\n\tstatic RwTexture *ms_maskTex;\n\tstatic RwTexture *ms_screenTex;\n\n\tstatic bool ms_enabled;\n\tstatic bool ms_movingEnabled;\n\n\tstatic ScreenDrop ms_drops[MAXDROPS];\n\tstatic int ms_numDrops;\n\tstatic ScreenDropMoving ms_dropsMoving[MAXDROPSMOVING];\n\tstatic int ms_numDropsMoving;\n\n\tstatic CVector ms_prevCamUp;\n\tstatic CVector ms_prevCamPos;\n\tstatic CVector ms_camMoveDelta;\n\tstatic float ms_camMoveDist;\n\tstatic CVector ms_screenMoveDelta;\n\tstatic float ms_screenMoveDist;\n\tstatic float ms_camUpAngle;\n\n\tstatic int ms_splashDuration;\n\tstatic CParticleObject *ms_splashObject;\n\n\tstatic void Initialise(void);\n\tstatic void InitDraw(void);\n\tstatic void Shutdown(void);\n\tstatic void Process(void);\n\tstatic void Render(void);\n\tstatic void AddToRenderList(ScreenDrop *drop);\n\n\tstatic void Clear(void);\n\tstatic ScreenDrop *NewDrop(float x, float y, float size, float lifetime, bool fades, int r = 255, int g = 255, int b = 255);\n\tstatic void SetMoving(ScreenDroplets::ScreenDrop *drop);\n\tstatic void FillScreen(int n);\n\tstatic void FillScreenMoving(float amount, bool isBlood = false);\n\tstatic void RegisterSplash(CParticleObject *pobj);\n\n\tstatic void ProcessCameraMovement(void);\n\tstatic void SprayDrops(void);\n\tstatic void NewTrace(ScreenDroplets::ScreenDropMoving *moving);\n\tstatic void MoveDrop(ScreenDropMoving *moving);\n\tstatic void ProcessMoving(void);\n\tstatic void Fade(void);\n};\n\n#endif\n"
  },
  {
    "path": "src/extras/shaders/colourfilterVC.frag",
    "content": "uniform sampler2D tex0;\nuniform vec4 u_blurcolor;\n\nFSIN vec4 v_color;\nFSIN vec2 v_tex0;\nFSIN float v_fog;\n\nvoid\nmain(void)\n{\n\tfloat a = u_blurcolor.a;\n\tvec4 doublec = clamp(u_blurcolor*2.0, 0.0, 1.0);\n\tvec4 dst = texture(tex0, vec2(v_tex0.x, 1.0-v_tex0.y));\n\tvec4 prev = dst;\n\tfor(int i = 0; i < 5; i++){\n\t\tvec4 tmp = dst*(1.0-a) + prev*doublec*a;\n\t\ttmp += prev*u_blurcolor;\n\t\ttmp += prev*u_blurcolor;\n\t\tprev = clamp(tmp, 0.0, 1.0);\n\t}\n\tvec4 color;\n\tcolor.rgb = prev.rgb;\n\tcolor.a = 1.0;\n\n\tFRAGCOLOR(color);\n}\n\n"
  },
  {
    "path": "src/extras/shaders/colourfilterVC_PS.hlsl",
    "content": "sampler2D tex : register(s0);\nfloat4 blurcol : register(c10);\n\n//float4 blurcols[10] : register(c15);\n\n\nfloat4 main(in float2 texcoord : TEXCOORD0) : COLOR0\n{\n\tfloat a = blurcol.a;\n\n\tfloat4 doublec = saturate(blurcol*2);\n\tfloat4 dst = tex2D(tex, texcoord.xy);\n\tfloat4 prev = dst;\n\tfor(int i = 0; i < 5; i++){\n//\t\tfloat4 doublec = saturate(blurcol*2);\n\t\tfloat4 tmp = dst*(1-a) + prev*doublec*a;\n\t\ttmp += prev*blurcol;\n\t\ttmp += prev*blurcol;\n\t\tprev = saturate(tmp);\n\t}\n\tprev.a = 1.0;\n\treturn prev;\n}\n"
  },
  {
    "path": "src/extras/shaders/contrast.frag",
    "content": "uniform sampler2D tex0;\nuniform vec3 u_contrastAdd;\nuniform vec3 u_contrastMult;\n\nFSIN vec4 v_color;\nFSIN vec2 v_tex0;\nFSIN float v_fog;\n\nvoid\nmain(void)\n{\n\tvec4 dst = texture(tex0, vec2(v_tex0.x, 1.0-v_tex0.y));\n\tvec4 color;\n\tcolor.rgb = dst.rgb*u_contrastMult + u_contrastAdd;\n\tcolor.a = 1.0;\n\n\tFRAGCOLOR(color);\n}\n\n"
  },
  {
    "path": "src/extras/shaders/contrastPS.hlsl",
    "content": "struct PS_INPUT\n{\n\tfloat4 position\t\t: POSITION;\n\tfloat3 texcoord0\t: TEXCOORD0;\n\tfloat4 color\t\t: COLOR0;\n};\n\nuniform float3 contrastMult : register(c10);\nuniform float3 contrastAdd : register(c11);\n\nsampler2D tex : register(s0);\n\nfloat4\nmain(PS_INPUT In) : COLOR\n{\n\tfloat4 dst = tex2D(tex, In.texcoord0.xy);\n\n\tdst.rgb = dst.rgb*contrastMult + contrastAdd;\n\tdst.a = 1.0;\n\treturn dst;\n}\n"
  },
  {
    "path": "src/extras/shaders/default_UV2.vert",
    "content": "VSIN(ATTRIB_POS)\tvec3 in_pos;\n\nVSOUT vec4 v_color;\nVSOUT vec2 v_tex0;\nVSOUT vec2 v_tex1;\nVSOUT float v_fog;\n\nvoid\nmain(void)\n{\n\tvec4 Vertex = u_world * vec4(in_pos, 1.0);\n\tgl_Position = u_proj * u_view * Vertex;\n\tvec3 Normal = mat3(u_world) * in_normal;\n\n\tv_tex0 = in_tex0;\n\tv_tex1 = in_tex1;\n\n\tv_color = in_color;\n\tv_color.rgb += u_ambLight.rgb*surfAmbient;\n\tv_color.rgb += DoDynamicLight(Vertex.xyz, Normal)*surfDiffuse;\n\tv_color = clamp(v_color, 0.0, 1.0);\n\tv_color *= u_matColor;\n\n\tv_fog = DoFog(gl_Position.w);\n}\n"
  },
  {
    "path": "src/extras/shaders/default_UV2_VS.hlsl",
    "content": "#include \"standardConstants.h\"\n\nstruct VS_in\n{\n\tfloat4 Position\t\t: POSITION;\n\tfloat3 Normal\t\t: NORMAL;\n\tfloat2 TexCoord\t\t: TEXCOORD0;\n\tfloat2 TexCoord1\t: TEXCOORD1;\n\tfloat4 Prelight\t\t: COLOR0;\n};\n\nstruct VS_out {\n\tfloat4 Position\t\t: POSITION;\n\tfloat3 TexCoord0\t: TEXCOORD0;\t// also fog\n\tfloat2 TexCoord1\t: TEXCOORD1;\n\tfloat4 Color\t\t: COLOR0;\n};\n\n\nVS_out main(in VS_in input)\n{\n\tVS_out output;\n\n\toutput.Position = mul(combinedMat, input.Position);\n\tfloat3 Vertex = mul(worldMat, input.Position).xyz;\n\tfloat3 Normal = mul(normalMat, input.Normal);\n\n\toutput.TexCoord0.xy = input.TexCoord;\n\toutput.TexCoord1.xy = input.TexCoord1;\n\n\toutput.Color = input.Prelight;\n\toutput.Color.rgb += ambientLight.rgb * surfAmbient;\n\n\tint i;\n#ifdef DIRECTIONALS\n\tfor(i = 0; i < numDirLights; i++)\n\t\toutput.Color.xyz += DoDirLight(lights[i+firstDirLight], Normal)*surfDiffuse;\n#endif\n#ifdef POINTLIGHTS\n\tfor(i = 0; i < numPointLights; i++)\n\t\toutput.Color.xyz += DoPointLight(lights[i+firstPointLight], Vertex.xyz, Normal)*surfDiffuse;\n#endif\n#ifdef SPOTLIGHTS\n\tfor(i = 0; i < numSpotLights; i++)\n\t\toutput.Color.xyz += DoSpotLight(lights[i+firstSpotLight], Vertex.xyz, Normal)*surfDiffuse;\n#endif\n\t// PS2 clamps before material color\n\toutput.Color = clamp(output.Color, 0.0, 1.0);\n\toutput.Color *= matCol;\n\n\toutput.TexCoord0.z = clamp((output.Position.w - fogEnd)*fogRange, fogDisable, 1.0);\n\n\treturn output;\n}\n"
  },
  {
    "path": "src/extras/shaders/im2d.vert",
    "content": "uniform vec4 u_xform;\n\nVSIN(ATTRIB_POS)\tvec4 in_pos;\n\nVSOUT vec4 v_color;\nVSOUT vec2 v_tex0;\nVSOUT float v_fog;\n\nvoid\nmain(void)\n{\n\tgl_Position = in_pos;\n\tgl_Position.w = 1.0;\n\tgl_Position.xy = gl_Position.xy * u_xform.xy + u_xform.zw;\n\tv_fog = DoFog(gl_Position.z);\n\tgl_Position.xyz *= gl_Position.w;\n\tv_color = in_color;\n\tv_tex0 = in_tex0;\n}\n"
  },
  {
    "path": "src/extras/shaders/im2d_UV2.vert",
    "content": "uniform vec4 u_xform;\n\nVSIN(ATTRIB_POS)\tvec4 in_pos;\n\nVSOUT vec4 v_color;\nVSOUT vec2 v_tex0;\nVSOUT vec2 v_tex1;\nVSOUT float v_fog;\n\nvoid\nmain(void)\n{\n\tgl_Position = in_pos;\n\tgl_Position.w = 1.0;\n\tgl_Position.xy = gl_Position.xy * u_xform.xy + u_xform.zw;\n\tv_fog = DoFog(gl_Position.z);\n\tgl_Position.xyz *= gl_Position.w;\n\tv_color = in_color;\n\tv_tex0 = in_tex0;\n\tv_tex1 = in_tex1;\n}\n"
  },
  {
    "path": "src/extras/shaders/lighting.h",
    "content": "struct Light\n{\n\tfloat4 color;\t// and radius\n\tfloat4 position;\t// and -cos(angle)\n\tfloat4 direction;\t// and falloff clamp\n};\n\nfloat3 DoDirLight(Light L, float3 N)\n{\n\tfloat l = max(0.0, dot(N, -L.direction.xyz));\n\treturn l*L.color.xyz;\n}\n\nfloat3 DoDirLightSpec(Light L, float3 N, float3 V, float power)\n{\n\treturn pow(saturate(dot(N, normalize(V + -L.direction.xyz))), power)*L.color.xyz;\n}\n\nfloat3 DoPointLight(Light L, float3 V, float3 N)\n{\n\t// As on PS2\n\tfloat3 dir = V - L.position.xyz;\n\tfloat dist = length(dir);\n\tfloat atten = max(0.0, (1.0 - dist/L.color.w));\n\tfloat l = max(0.0, dot(N, -normalize(dir)));\n\treturn l*L.color.xyz*atten;\n}\n\nfloat3 DoSpotLight(Light L, float3 V, float3 N)\n{\n\t// As on PS2\n\tfloat3 dir = V - L.position.xyz;\n\tfloat dist = length(dir);\n\tfloat atten = max(0.0, (1.0 - dist/L.color.w));\n\tdir /= dist;\n\tfloat l = max(0.0, dot(N, -dir));\n\tfloat pcos = dot(dir, L.direction.xyz);\t// cos to point\n\tfloat ccos = -L.position.w;\t// cos of cone\n\tfloat falloff = (pcos-ccos)/(1.0-ccos);\n\tif(falloff < 0)\t// outside of cone\n\t\tl = 0;\n\tl *= max(falloff, L.direction.w);\t// falloff clamp\n\treturn l*L.color.xyz*atten;\n}\n"
  },
  {
    "path": "src/extras/shaders/make_glsl.sh",
    "content": "#!sh\nfor i in *.vert; do\n\techo $i\n\t./makeinc_glsl.sh $i\ndone\nfor i in *.frag; do\n\techo $i\n\t./makeinc_glsl.sh $i\ndone\n"
  },
  {
    "path": "src/extras/shaders/make_hlsl.cmd",
    "content": "@echo off\nfor %%f in (*PS.hlsl) do \"%DXSDK_DIR%\\Utilities\\bin\\x86\\fxc.exe\" /T ps_2_0 /nologo /E main /Fo obj\\%%~nf.cso %%f\nfor %%f in (*VS.hlsl) do \"%DXSDK_DIR%\\Utilities\\bin\\x86\\fxc.exe\" /T vs_2_0 /nologo /E main /Fo obj\\%%~nf.cso %%f\n"
  },
  {
    "path": "src/extras/shaders/makeinc_glsl.sh",
    "content": "#!sh\next=${1##*.}\nname=${1%.*}\n(echo \"const char *${name}_${ext}_src =\";\\\nsed 's/..*/\"&\\\\n\"/' $1;\\\necho ';') > obj/${name}_${ext}.inc\n"
  },
  {
    "path": "src/extras/shaders/makeinc_hlsl.sh",
    "content": "#!sh\ncd obj\nfor i in *cso; do\n\t(echo -n 'static '\n\txxd -i $i | grep -v '_len = ') > ${i%cso}inc\ndone\n"
  },
  {
    "path": "src/extras/shaders/neoGloss.frag",
    "content": "uniform sampler2D tex0;\n\nuniform vec4 u_reflProps;\n\n#define glossMult (u_reflProps.x)\n\nFSIN vec3 v_normal;\nFSIN vec3 v_light;\nFSIN vec2 v_tex0;\nFSIN float v_fog;\n\nvoid\nmain(void)\n{\n\tvec4 color = texture(tex0, vec2(v_tex0.x, 1.0-v_tex0.y));\n\tvec3 n = 2.0*v_normal-1.0;            // unpack\n\tvec3 v = 2.0*v_light-1.0;             //\n\n\tfloat s = dot(n, v);\n\tcolor = s*s*s*s*s*s*s*s*color*v_fog*glossMult;\n\n\tDoAlphaTest(color.a);\n\n\tFRAGCOLOR(color);\n}\n\n"
  },
  {
    "path": "src/extras/shaders/neoGloss.vert",
    "content": "uniform vec3 u_eye;\n\nVSIN(ATTRIB_POS)\tvec3 in_pos;\n\nVSOUT vec3 v_normal;\nVSOUT vec3 v_light;\nVSOUT vec2 v_tex0;\nVSOUT float v_fog;\n\nvoid\nmain(void)\n{\n\tvec4 Vertex = u_world * vec4(in_pos, 1.0);\n\tgl_Position = u_proj * u_view * Vertex;\n\tvec3 Normal = mat3(u_world) * in_normal;\n\n\tv_tex0 = in_tex0;\n\n\tvec3 viewVec = normalize(u_eye - Vertex.xyz);\n\tvec3 Light = normalize(viewVec - u_lightDirection[0].xyz);\n\tv_normal = 0.5*(1.0 + vec3(0.0, 0.0, 1.0));    // compress\n\tv_light  = 0.5*(1.0 + Light);                  //\n\n\tv_fog = DoFog(gl_Position.w);\n}\n"
  },
  {
    "path": "src/extras/shaders/neoGloss_PS.hlsl",
    "content": "sampler2D tex0 : register(s0);\nfloat glossMult : register(c1);\n\nstruct VS_out\n{\n\tfloat4 Position         : POSITION;\n\tfloat3 TexCoord0        : TEXCOORD0;\n\tfloat3 Normal           : COLOR0;\n\tfloat3 Light            : COLOR1;\n};\n\nfloat4 main(VS_out input) : COLOR\n{\n\tfloat4 color = tex2D(tex0, input.TexCoord0.xy);\n\tfloat3 n = 2.0*input.Normal-1.0;            // unpack\n\tfloat3 v = 2.0*input.Light-1.0;             //\n\n\tfloat s = dot(n, v);\n\treturn s*s*s*s*s*s*s*s*color*input.TexCoord0.z*glossMult;\n}\n"
  },
  {
    "path": "src/extras/shaders/neoGloss_VS.hlsl",
    "content": "#include \"standardConstants.h\"\n\nstruct VS_in\n{\n\tfloat4 Position         : POSITION;\n\tfloat2 TexCoord         : TEXCOORD0;\n};\n\nstruct VS_out\n{\n\tfloat4 Position         : POSITION;\n\tfloat3 TexCoord0        : TEXCOORD0;\n\tfloat3 Normal           : COLOR0;\n\tfloat3 Light            : COLOR1;\n};\n\nfloat3 eye : register(c41);\n\nVS_out main(in VS_in input)\n{\n\tVS_out output;\n\n\toutput.Position = mul(combinedMat, input.Position);\n\tfloat3 Vertex = mul(worldMat, input.Position).xyz;\n\toutput.TexCoord0.xy = input.TexCoord;\n\n\tfloat3 viewVec = normalize(eye - Vertex);\n\tfloat3 Light = normalize(viewVec - lights[0].direction.xyz);\n\toutput.Normal = 0.5*(1.0 + float3(0.0, 0.0, 1.0));    // compress\n\toutput.Light  = 0.5*(1.0 + Light);                    //\n\n\toutput.TexCoord0.z = clamp((output.Position.w - fogEnd)*fogRange, fogDisable, 1.0);\n\n\treturn output;\n}\n"
  },
  {
    "path": "src/extras/shaders/neoRim.vert",
    "content": "uniform vec3 u_viewVec;\nuniform vec4 u_rampStart;\nuniform vec4 u_rampEnd;\nuniform vec3 u_rimData;\n\nVSIN(ATTRIB_POS)\tvec3 in_pos;\n\nVSOUT vec4 v_color;\nVSOUT vec2 v_tex0;\nVSOUT float v_fog;\n\nvoid\nmain(void)\n{\n\tvec4 Vertex = u_world * vec4(in_pos, 1.0);\n\tgl_Position = u_proj * u_view * Vertex;\n\tvec3 Normal = mat3(u_world) * in_normal;\n\n\tv_tex0 = in_tex0;\n\n\tv_color = in_color;\n\tv_color.rgb += u_ambLight.rgb*surfAmbient;\n\tv_color.rgb += DoDynamicLight(Vertex.xyz, Normal)*surfDiffuse;\n\n\t// rim light\n\tfloat f = u_rimData.x - u_rimData.y*dot(Normal, u_viewVec);\n\tvec4 rimlight = clamp(mix(u_rampEnd, u_rampStart, f)*u_rimData.z, 0.0, 1.0);\n\tv_color.rgb += rimlight.rgb;\n\n\tv_color = clamp(v_color, 0.0, 1.0);\n\tv_color *= u_matColor;\n\n\tv_fog = DoFog(gl_Position.w);\n}\n"
  },
  {
    "path": "src/extras/shaders/neoRimSkin.vert",
    "content": "uniform mat4 u_boneMatrices[64];\n\nuniform vec3 u_viewVec;\nuniform vec4 u_rampStart;\nuniform vec4 u_rampEnd;\nuniform vec3 u_rimData;\n\nVSIN(ATTRIB_POS)\tvec3 in_pos;\n\nVSOUT vec4 v_color;\nVSOUT vec2 v_tex0;\nVSOUT float v_fog;\n\nvoid\nmain(void)\n{\n\tvec3 SkinVertex = vec3(0.0, 0.0, 0.0);\n\tvec3 SkinNormal = vec3(0.0, 0.0, 0.0);\n\tfor(int i = 0; i < 4; i++){\n\t\tSkinVertex += (u_boneMatrices[int(in_indices[i])] * vec4(in_pos, 1.0)).xyz * in_weights[i];\n\t\tSkinNormal += (mat3(u_boneMatrices[int(in_indices[i])]) * in_normal) * in_weights[i];\n\t}\n\n\tvec4 Vertex = u_world * vec4(SkinVertex, 1.0);\n\tgl_Position = u_proj * u_view * Vertex;\n\tvec3 Normal = mat3(u_world) * SkinNormal;\n\n\tv_tex0 = in_tex0;\n\n\tv_color = in_color;\n\tv_color.rgb += u_ambLight.rgb*surfAmbient;\n\tv_color.rgb += DoDynamicLight(Vertex.xyz, Normal)*surfDiffuse;\n\n\t// rim light\n\tfloat f = u_rimData.x - u_rimData.y*dot(Normal, u_viewVec);\n\tvec4 rimlight = clamp(mix(u_rampEnd, u_rampStart, f)*u_rimData.z, 0.0, 1.0);\n\tv_color.rgb += rimlight.rgb;\n\n\tv_color = clamp(v_color, 0.0, 1.0);\n\tv_color *= u_matColor;\n\n\tv_fog = DoFog(gl_Position.z);\n}\n"
  },
  {
    "path": "src/extras/shaders/neoRimSkin_VS.hlsl",
    "content": "#include \"standardConstants.h\"\n\nfloat4x3 boneMatrices[64] : register(c41);\n\nstruct VS_in\n{\n\tfloat4 Position\t\t: POSITION;\n\tfloat3 Normal\t\t: NORMAL;\n\tfloat2 TexCoord\t\t: TEXCOORD0;\n\tfloat4 Prelight\t\t: COLOR0;\n\tfloat4 Weights\t\t: BLENDWEIGHT;\n\tint4 Indices\t\t: BLENDINDICES;\n};\n\nstruct VS_out {\n\tfloat4 Position\t\t: POSITION;\n\tfloat3 TexCoord0\t: TEXCOORD0;\t// also fog\n\tfloat4 Color\t\t: COLOR0;\n};\n\nfloat3\t    viewVec     : register(c233);\nfloat4      rampStart   : register(c234);\nfloat4      rampEnd     : register(c235);\nfloat3      rimData     : register(c236);\n\nVS_out main(in VS_in input)\n{\n\tVS_out output;\n\n\tint j;\n\tfloat3 SkinVertex = float3(0.0, 0.0, 0.0);\n\tfloat3 SkinNormal = float3(0.0, 0.0, 0.0);\n\tfor(j = 0; j < 4; j++){\n\t\tSkinVertex += mul(input.Position, boneMatrices[input.Indices[j]]).xyz * input.Weights[j];\n\t\tSkinNormal += mul(input.Normal, (float3x3)boneMatrices[input.Indices[j]]).xyz * input.Weights[j];\n\t}\n\n\toutput.Position = mul(combinedMat, float4(SkinVertex, 1.0));\n\tfloat3 Vertex = mul(worldMat, float4(SkinVertex, 1.0)).xyz;\n\tfloat3 Normal = mul(normalMat, SkinNormal);\n\n\toutput.TexCoord0.xy = input.TexCoord;\n\n\toutput.Color = input.Prelight;\n\toutput.Color.rgb += ambientLight.rgb * surfAmbient;\n\n\tint i;\n//#ifdef DIRECTIONALS\n\tfor(i = 0; i < numDirLights; i++)\n\t\toutput.Color.xyz += DoDirLight(lights[i+firstDirLight], Normal)*surfDiffuse;\n//#endif\n//#ifdef POINTLIGHTS\n//\tfor(i = 0; i < numPointLights; i++)\n//\t\toutput.Color.xyz += DoPointLight(lights[i+firstPointLight], Vertex.xyz, Normal)*surfDiffuse;\n//#endif\n//#ifdef SPOTLIGHTS\n//\tfor(i = 0; i < numSpotLights; i++)\n//\t\toutput.Color.xyz += DoSpotLight(lights[i+firstSpotLight], Vertex.xyz, Normal)*surfDiffuse;\n//#endif\n\n\t// rim light\n\tfloat f = rimData.x - rimData.y*dot(Normal, viewVec);\n\tfloat4 rimlight = saturate(lerp(rampEnd, rampStart, f)*rimData.z);\n\toutput.Color.xyz += rimlight.xyz;\n\n\t// PS2 clamps before material color\n\toutput.Color = clamp(output.Color, 0.0, 1.0);\n\toutput.Color *= matCol;\n\n\toutput.TexCoord0.z = clamp((output.Position.w - fogEnd)*fogRange, fogDisable, 1.0);\n\n\treturn output;\n}\n"
  },
  {
    "path": "src/extras/shaders/neoRim_VS.hlsl",
    "content": "#include \"standardConstants.h\"\n\nstruct VS_in\n{\n\tfloat4 Position\t\t: POSITION;\n\tfloat3 Normal\t\t: NORMAL;\n\tfloat2 TexCoord\t\t: TEXCOORD0;\n\tfloat4 Prelight\t\t: COLOR0;\n};\n\nstruct VS_out {\n\tfloat4 Position\t\t: POSITION;\n\tfloat3 TexCoord0\t: TEXCOORD0;\t// also fog\n\tfloat4 Color\t\t: COLOR0;\n};\n\nfloat3\t    viewVec     : register(c233);\nfloat4      rampStart   : register(c234);\nfloat4      rampEnd     : register(c235);\nfloat3      rimData     : register(c236);\n\nVS_out main(in VS_in input)\n{\n\tVS_out output;\n\n\toutput.Position = mul(combinedMat, input.Position);\n\tfloat3 Vertex = mul(worldMat, input.Position).xyz;\n\tfloat3 Normal = mul(normalMat, input.Normal);\n\n\toutput.TexCoord0.xy = input.TexCoord;\n\n\toutput.Color = input.Prelight;\n\toutput.Color.rgb += ambientLight.rgb * surfAmbient;\n\n\tint i;\n//#ifdef DIRECTIONALS\n\tfor(i = 0; i < numDirLights; i++)\n\t\toutput.Color.xyz += DoDirLight(lights[i+firstDirLight], Normal)*surfDiffuse;\n//#endif\n//#ifdef POINTLIGHTS\n//\tfor(i = 0; i < numPointLights; i++)\n//\t\toutput.Color.xyz += DoPointLight(lights[i+firstPointLight], Vertex.xyz, Normal)*surfDiffuse;\n//#endif\n//#ifdef SPOTLIGHTS\n//\tfor(i = 0; i < numSpotLights; i++)\n//\t\toutput.Color.xyz += DoSpotLight(lights[i+firstSpotLight], Vertex.xyz, Normal)*surfDiffuse;\n//#endif\n\n\t// rim light\n\tfloat f = rimData.x - rimData.y*dot(Normal, viewVec);\n\tfloat4 rimlight = saturate(lerp(rampEnd, rampStart, f)*rimData.z);\n\toutput.Color.xyz += rimlight.xyz;\n\n\t// PS2 clamps before material color\n\toutput.Color = clamp(output.Color, 0.0, 1.0);\n\toutput.Color *= matCol;\n\n\toutput.TexCoord0.z = clamp((output.Position.w - fogEnd)*fogRange, fogDisable, 1.0);\n\n\treturn output;\n}\n"
  },
  {
    "path": "src/extras/shaders/neoVehicle.frag",
    "content": "uniform sampler2D tex0;\nuniform sampler2D tex1;\n\nFSIN vec4 v_color;\nFSIN vec4 v_reflcolor;\nFSIN vec2 v_tex0;\nFSIN vec2 v_tex1;\nFSIN float v_fog;\n\nvoid\nmain(void)\n{\n\tvec4 pass1 = v_color*texture(tex0, vec2(v_tex0.x, 1.0-v_tex0.y));\n\tvec3 envmap = texture(tex1, vec2(v_tex1.x, 1.0-v_tex1.y)).rgb;\n\tpass1.rgb = mix(pass1.rgb, envmap, v_reflcolor.a);\n\tpass1.rgb = mix(u_fogColor.rgb, pass1.rgb, v_fog);\n//\tpass1.rgb += v_reflcolor.rgb * v_fog;\n\n\tvec3 pass2 = v_reflcolor.rgb * v_fog;\n\n\tvec4 color;\n\tcolor.rgb = pass1.rgb*pass1.a + pass2;\n\tcolor.a = pass1.a;\n\n//\tcolor.rgb = mix(u_fogColor.rgb, color.rgb, v_fog);\n\tDoAlphaTest(color.a);\n\n\tFRAGCOLOR(color);\n}\n"
  },
  {
    "path": "src/extras/shaders/neoVehicle.vert",
    "content": "uniform vec3 u_eye;\nuniform vec4 u_reflProps;\nuniform vec4 u_specDir[5];\nuniform vec4 u_specColor[5];\n\n#define fresnel (u_reflProps.x)\n#define lightStrength (u_reflProps.y)\t// speclight alpha\n#define shininess (u_reflProps.z)\n#define specularity (u_reflProps.w)\n\nVSIN(ATTRIB_POS)\tvec3 in_pos;\n\nVSOUT vec4 v_color;\nVSOUT vec4 v_reflcolor;\nVSOUT vec2 v_tex0;\nVSOUT vec2 v_tex1;\nVSOUT float v_fog;\n\nvec3 DoDirLightSpec(vec3 Ldir, vec3 Lcol, vec3 N, vec3 V, float power)\n{\n\treturn pow(clamp(dot(N, normalize(V + -Ldir)), 0.0, 1.0), power)*Lcol;\n}\n\nvoid\nmain(void)\n{\n\tvec4 Vertex = u_world * vec4(in_pos, 1.0);\n\tgl_Position = u_proj * u_view * Vertex;\n\tvec3 Normal = mat3(u_world) * in_normal;\n\tvec3 viewVec = normalize(u_eye - Vertex.xyz);\n\n\tv_tex0 = in_tex0;\n\n\tv_color = in_color;\n\tv_color.rgb += u_ambLight.rgb*surfAmbient;\n\tv_color.rgb += DoDynamicLight(Vertex.xyz, Normal)*surfDiffuse*lightStrength;\n\tv_color = clamp(v_color, 0.0, 1.0);\n\tv_color *= u_matColor;\n\n\t// reflect V along Normal\n\tvec3 uv2 = Normal*dot(viewVec, Normal)*2.0 - viewVec;\n\tv_tex1 = uv2.xy*0.5 + 0.5;\n\tfloat b = 1.0 - clamp(dot(viewVec, Normal), 0.0, 1.0);\n\tv_reflcolor = vec4(0.0, 0.0, 0.0, 1.0);\n\tv_reflcolor.a = mix(b*b*b*b*b, 1.0, fresnel)*shininess;\n\n\tfor(int i = 0; i < 5; i++)\n\t\tv_reflcolor.rgb += DoDirLightSpec(u_specDir[i].xyz, u_specColor[i].rgb, Normal, viewVec, u_specDir[i].w)*specularity*lightStrength;\n\n\tv_fog = DoFog(gl_Position.w);\n}\n"
  },
  {
    "path": "src/extras/shaders/neoVehicle_PS.hlsl",
    "content": "struct VS_out {\n\tfloat4 Position\t\t: POSITION;\n\tfloat3 TexCoord0\t: TEXCOORD0;\n\tfloat2 TexCoord1\t: TEXCOORD1;\n\tfloat4 Color\t\t: COLOR0;\n\tfloat4 ReflColor\t: COLOR1;\n};\n\nsampler2D tex0 : register(s0);\nsampler2D tex1 : register(s1);\n\nfloat4 fogColor : register(c0);\n\nfloat4 main(VS_out input) : COLOR\n{\n\tfloat4 pass1 = input.Color;\n//#ifdef TEX\n\tpass1 *= tex2D(tex0, input.TexCoord0.xy);\n//#endif\n\tfloat3 envmap = tex2D(tex1, input.TexCoord1).rgb;\n\tpass1.rgb = lerp(pass1.rgb, envmap, input.ReflColor.a);\n//\tpass1.rgb = envmap;\n//\tpass1.rgb *= input.ReflColor.a;\n\tpass1.rgb = lerp(fogColor.rgb, pass1.rgb, input.TexCoord0.z);\n//\tpass1.rgb += input.ReflColor.rgb * input.TexCoord0.z;\n\n\tfloat3 pass2 = input.ReflColor.rgb*input.TexCoord0.z;\n\n\tfloat4 color;\n\tcolor.rgb = pass1.rgb*pass1.a + pass2;\n\tcolor.a = pass1.a;\n\n\treturn color;\n}\n"
  },
  {
    "path": "src/extras/shaders/neoVehicle_VS.hlsl",
    "content": "#include \"standardConstants.h\"\n\nstruct VS_in\n{\n\tfloat4 Position\t\t: POSITION;\n\tfloat3 Normal\t\t: NORMAL;\n\tfloat2 TexCoord\t\t: TEXCOORD0;\n\tfloat4 Prelight\t\t: COLOR0;\n};\n\nstruct VS_out {\n\tfloat4 Position\t\t: POSITION;\n\tfloat3 TexCoord0\t: TEXCOORD0;\t// also fog\n\tfloat2 TexCoord1\t: TEXCOORD1;\n\tfloat4 Color\t\t: COLOR0;\n\tfloat4 ReflColor\t: COLOR1;\n};\n\nfloat3 eye : register(c41);\nfloat4 reflProps : register(c42);\nLight specLights[5] : register(c43);\n\n\n#define fresnel (reflProps.x)\n#define lightStrength (reflProps.y)\t// speclight alpha\n#define shininess (reflProps.z)\n#define specularity (reflProps.w)\n\nVS_out main(in VS_in input)\n{\n\tVS_out output;\n\n\toutput.Position = mul(combinedMat, input.Position);\n\tfloat3 Vertex = mul(worldMat, input.Position).xyz;\n\tfloat3 Normal = mul(normalMat, input.Normal);\n\tfloat3 viewVec = normalize(eye - Vertex);\n\n\toutput.TexCoord0.xy = input.TexCoord;\n\n\toutput.Color = input.Prelight;\n\toutput.Color.rgb += ambientLight.rgb * surfAmbient*lightStrength;\n\n\tint i;\n\tfor(i = 0; i < numDirLights; i++)\n\t\toutput.Color.xyz += DoDirLight(lights[i+firstDirLight], Normal)*surfDiffuse*lightStrength;\n\t// PS2 clamps before material color\n\toutput.Color = clamp(output.Color, 0.0, 1.0);\n\toutput.Color *= matCol;\n\n\t// reflect V along Normal\n\tfloat3 uv2 = Normal*dot(viewVec, Normal)*2.0 - viewVec;\n\toutput.TexCoord1 = uv2.xy*0.5 + 0.5;\n\tfloat b = 1.0 - saturate(dot(viewVec, Normal));\n\toutput.ReflColor = float4(0.0, 0.0, 0.0, 1.0);\n\toutput.ReflColor.a = lerp(b*b*b*b*b, 1.0, fresnel)*shininess;\n\n\t//Light mainLight = lights[0];\n\tfor(i = 0; i < 5; i++)\n\t\toutput.ReflColor.xyz += DoDirLightSpec(specLights[i], Normal, viewVec, specLights[i].direction.w)*specularity*lightStrength;\n\n\toutput.TexCoord0.z = clamp((output.Position.w - fogEnd)*fogRange, fogDisable, 1.0);\n\n\treturn output;\n}\n"
  },
  {
    "path": "src/extras/shaders/neoWorldVC.frag",
    "content": "uniform sampler2D tex0;\nuniform sampler2D tex1;\n\nuniform vec4 u_lightMap;\n\nFSIN vec4 v_color;\nFSIN vec2 v_tex0;\nFSIN vec2 v_tex1;\nFSIN float v_fog;\n\nvoid\nmain(void)\n{\n\tvec4 t0 = texture(tex0, vec2(v_tex0.x, 1.0-v_tex0.y));\n\tvec4 t1 = texture(tex1, vec2(v_tex1.x, 1.0-v_tex1.y));\n\n\tvec4 color;\n\tcolor = t0*v_color*(1.0 + u_lightMap*(t1-1.0));\n\tcolor.a = v_color.a*t0.a*u_lightMap.a;\n\n\tcolor.rgb = mix(u_fogColor.rgb, color.rgb, v_fog);\n\tDoAlphaTest(color.a);\n\n\tFRAGCOLOR(color);\n}\n\n"
  },
  {
    "path": "src/extras/shaders/neoWorldVC_PS.hlsl",
    "content": "sampler2D Diffuse : register(s0);\nsampler2D Light : register(s1);\nfloat4 fogColor : register(c0);\nfloat4 lm : register(c1);\n \nstruct PS_INPUT\n{\n\tfloat4 Color\t: COLOR0;\n\tfloat3 Tex0\t: TEXCOORD0;\n\tfloat2 Tex1\t: TEXCOORD1;\n};\n\nfloat4\nmain(PS_INPUT IN) : COLOR\n{\n\tfloat4 t0 = tex2D(Diffuse, IN.Tex0.xy);\n\tfloat4 t1 = tex2D(Light, IN.Tex1);\n\n\tfloat4 col = t0*IN.Color*(1 + lm*(t1-1));\n\tcol.a = IN.Color.a*t0.a*lm.a;\n\n\tcol.rgb = lerp(fogColor.rgb, col.rgb, IN.Tex0.z);\n\n\treturn col;\n}\n"
  },
  {
    "path": "src/extras/shaders/screenDroplet.frag",
    "content": "uniform sampler2D tex0;\nuniform sampler2D tex1;\n\nFSIN vec4 v_color;\nFSIN vec2 v_tex0;\nFSIN vec2 v_tex1;\nFSIN float v_fog;\n\nvoid\nmain(void)\n{\n\tvec4 color;\n\tcolor = v_color*texture(tex0, vec2(v_tex0.x, 1.0-v_tex0.y));\n\tcolor *= texture(tex1, vec2(v_tex1.x, 1.0-v_tex1.y));\n\n\tFRAGCOLOR(color);\n}\n\n"
  },
  {
    "path": "src/extras/shaders/screenDroplet_PS.hlsl",
    "content": "struct VS_out {\n\tfloat4 Position\t\t: POSITION;\n\tfloat2 TexCoord0\t: TEXCOORD0;\n\tfloat2 TexCoord1\t: TEXCOORD1;\n\tfloat4 Color\t\t: COLOR0;\n};\n\nsampler2D tex0 : register(s0);\nsampler2D tex1 : register(s1);\n\nfloat4 main(VS_out input) : COLOR\n{\n\tfloat4 color = input.Color;\n\tcolor *= tex2D(tex0, input.TexCoord0.xy);\n\tcolor *= tex2D(tex1, input.TexCoord1.xy);\n\treturn color;\n}\n"
  },
  {
    "path": "src/extras/shaders/simple.frag",
    "content": "uniform sampler2D tex0;\n\nFSIN vec4 v_color;\nFSIN vec2 v_tex0;\nFSIN float v_fog;\n\nvoid\nmain(void)\n{\n\tvec4 color;\n\tcolor = v_color*texture(tex0, vec2(v_tex0.x, 1.0-v_tex0.y));\n\tcolor.rgb = mix(u_fogColor.rgb, color.rgb, v_fog);\n\tDoAlphaTest(color.a);\n\n\tFRAGCOLOR(color);\n}\n\n"
  },
  {
    "path": "src/extras/shaders/standardConstants.h",
    "content": "float4x4\tcombinedMat\t: register(c0);\nfloat4x4\tworldMat\t: register(c4);\nfloat3x3\tnormalMat\t: register(c8);\nfloat4\t\tmatCol\t\t: register(c12);\nfloat4\t\tsurfProps\t: register(c13);\nfloat4\t\tfogData\t: register(c14);\nfloat4\t\tambientLight\t: register(c15);\n\n#define surfAmbient (surfProps.x)\n#define surfSpecular (surfProps.y)\n#define surfDiffuse (surfProps.z)\n\n#define fogStart (fogData.x)\n#define fogEnd (fogData.y)\n#define fogRange (fogData.z)\n#define fogDisable (fogData.w)\n\n#include \"lighting.h\"\n\nint numDirLights : register(i0);\nint numPointLights : register(i1);\nint numSpotLights : register(i2);\nint4 firstLight : register(c16);\nLight lights[8] : register(c17);\n\n#define firstDirLight (firstLight.x)\n#define firstPointLight (firstLight.y)\n#define firstSpotLight (firstLight.z)\n"
  },
  {
    "path": "src/fakerw/fake.cpp",
    "content": "#define _CRT_SECURE_NO_WARNINGS\n#define WITH_D3D // not WITHD3D, so it's librw define\n#include <rwcore.h>\n#include <rpworld.h>\n#include <rpmatfx.h>\n#include <rphanim.h>\n#include <rpskin.h>\n#include <assert.h>\n#include <string.h>\n#ifndef _WIN32\n#include \"crossplatform.h\"\n#endif\n\nusing namespace rw;\n\nRwUInt8 RwObjectGetType(const RwObject *obj) { return obj->type; }\nRwFrame* rwObjectGetParent(const RwObject *obj) { return (RwFrame*)obj->parent; }\n\n\nvoid *RwMalloc(size_t size) { return engine->memfuncs.rwmalloc(size, 0); }\nvoid *RwCalloc(size_t numObj, size_t sizeObj) {\n\tvoid *mem = RwMalloc(numObj*sizeObj);\n\tif(mem)\n\t\tmemset(mem, 0, numObj*sizeObj);\n\treturn mem;\n}\nvoid  RwFree(void *mem) { engine->memfuncs.rwfree(mem); }\n\n\n//RwReal RwV3dNormalize(RwV3d * out, const RwV3d * in);\nRwReal RwV3dLength(const RwV3d * in) { return length(*in); }\n//RwReal RwV2dLength(const RwV2d * in);\n//RwReal RwV2dNormalize(RwV2d * out, const RwV2d * in);\n//void RwV2dAssign(RwV2d * out, const RwV2d * ina);\n//void RwV2dAdd(RwV2d * out, const RwV2d * ina, const RwV2d * inb);\n//void RwV2dLineNormal(RwV2d * out, const RwV2d * ina, const RwV2d * inb);\n//void RwV2dSub(RwV2d * out, const RwV2d * ina, const RwV2d * inb);\n//void RwV2dPerp(RwV2d * out, const RwV2d * in);\n//void RwV2dScale(RwV2d * out, const RwV2d * in, RwReal scalar);\n//RwReal RwV2dDotProduct(const RwV2d * ina, const RwV2d * inb);\n//void RwV3dAssign(RwV3d * out, const RwV3d * ina);\nvoid RwV3dAdd(RwV3d * out, const RwV3d * ina, const RwV3d * inb) { *out = add(*ina, *inb); }\nvoid RwV3dSub(RwV3d * out, const RwV3d * ina, const RwV3d * inb) { *out = sub(*ina, *inb); }\nvoid RwV3dScale(RwV3d * out, const RwV3d * in, RwReal scalar) { *out = scale(*in, scalar); }\nvoid RwV3dIncrementScaled(RwV3d * out,  const RwV3d * in, RwReal scalar) { *out = add(*out, scale(*in, scalar)); }\nvoid RwV3dNegate(RwV3d * out, const RwV3d * in) { *out = neg(*in); }\nRwReal RwV3dDotProduct(const RwV3d * ina, const RwV3d * inb) { return dot(*ina, *inb); }\n//void RwV3dCrossProduct(RwV3d * out, const RwV3d * ina, const RwV3d * inb);\nRwV3d *RwV3dTransformPoints(RwV3d * pointsOut, const RwV3d * pointsIn, RwInt32 numPoints, const RwMatrix * matrix)\n\t{ V3d::transformPoints(pointsOut, pointsIn, numPoints, matrix); return pointsOut; }\n//RwV3d *RwV3dTransformVectors(RwV3d * vectorsOut, const RwV3d * vectorsIn, RwInt32 numPoints, const RwMatrix * matrix);\n\n\n\nRwBool RwMatrixDestroy(RwMatrix *mpMat) { mpMat->destroy(); return true; }\nRwMatrix *RwMatrixCreate(void) { return Matrix::create(); }\nvoid RwMatrixCopy(RwMatrix * dstMatrix, const RwMatrix * srcMatrix) { *dstMatrix = *srcMatrix; }\nvoid RwMatrixSetIdentity(RwMatrix * matrix) { matrix->setIdentity(); }\nRwMatrix *RwMatrixMultiply(RwMatrix * matrixOut, const RwMatrix * MatrixIn1, const RwMatrix * matrixIn2);\nRwMatrix *RwMatrixTransform(RwMatrix * matrix, const RwMatrix * transform, RwOpCombineType combineOp)\n\t{ matrix->transform(transform, (rw::CombineOp)combineOp); return matrix; }\n//RwMatrix *RwMatrixOrthoNormalize(RwMatrix * matrixOut, const RwMatrix * matrixIn);\nRwMatrix *RwMatrixInvert(RwMatrix * matrixOut, const RwMatrix * matrixIn) { Matrix::invert(matrixOut, matrixIn); return matrixOut; }\nRwMatrix *RwMatrixScale(RwMatrix * matrix, const RwV3d * scale, RwOpCombineType combineOp)\n\t{ matrix->scale(scale, (rw::CombineOp)combineOp); return matrix; }\nRwMatrix *RwMatrixTranslate(RwMatrix * matrix, const RwV3d * translation, RwOpCombineType combineOp)\n\t{ matrix->translate(translation, (rw::CombineOp)combineOp); return matrix; }\nRwMatrix *RwMatrixRotate(RwMatrix * matrix, const RwV3d * axis, RwReal angle, RwOpCombineType combineOp)\n\t{ matrix->rotate(axis, angle, (rw::CombineOp)combineOp); return matrix; }\n//RwMatrix *RwMatrixRotateOneMinusCosineSine(RwMatrix * matrix, const RwV3d * unitAxis, RwReal oneMinusCosine, RwReal sine, RwOpCombineType combineOp);\n//const RwMatrix *RwMatrixQueryRotate(const RwMatrix * matrix, RwV3d * unitAxis, RwReal * angle, RwV3d * center);\nRwV3d *RwMatrixGetRight(RwMatrix * matrix) { return &matrix->right; }\nRwV3d *RwMatrixGetUp(RwMatrix * matrix) { return &matrix->up; }\nRwV3d *RwMatrixGetAt(RwMatrix * matrix) { return &matrix->at; }\nRwV3d *RwMatrixGetPos(RwMatrix * matrix) { return &matrix->pos; }\nRwMatrix *RwMatrixUpdate(RwMatrix * matrix) { matrix->update(); return matrix; }\n//RwMatrix *RwMatrixOptimize(RwMatrix * matrix, const RwMatrixTolerance *tolerance);\n\n\n\n\nRwFrame *RwFrameForAllObjects(RwFrame * frame, RwObjectCallBack callBack, void *data) {\n\tFORLIST(lnk, frame->objectList)\n\t\tif(callBack(&ObjectWithFrame::fromFrame(lnk)->object, data) == nil)\n\t\t\tbreak;\n\treturn frame;\n}\nRwFrame *RwFrameTranslate(RwFrame * frame, const RwV3d * v, RwOpCombineType combine) { frame->translate(v, (CombineOp)combine); return frame; }\nRwFrame *RwFrameRotate(RwFrame * frame, const RwV3d * axis, RwReal angle, RwOpCombineType combine) { frame->rotate(axis, angle, (CombineOp)combine); return frame; }\nRwFrame *RwFrameScale(RwFrame * frame, const RwV3d * v, RwOpCombineType combine) { frame->scale(v, (CombineOp)combine); return frame; }\nRwFrame *RwFrameTransform(RwFrame * frame, const RwMatrix * m, RwOpCombineType combine) { frame->transform(m, (CombineOp)combine); return frame; }\n//TODO: actually implement this!\nRwFrame *RwFrameOrthoNormalize(RwFrame * frame) { return frame; }\nRwFrame *RwFrameSetIdentity(RwFrame * frame) { frame->matrix.setIdentity(); frame->updateObjects(); return frame; }\n//RwFrame *RwFrameCloneHierarchy(RwFrame * root);\n//RwBool RwFrameDestroyHierarchy(RwFrame * frame);\nRwFrame *RwFrameForAllChildren(RwFrame * frame, RwFrameCallBack callBack, void *data)\n\t{ return frame->forAllChildren(callBack, data); }\nRwFrame *RwFrameRemoveChild(RwFrame * child) { child->removeChild(); return child; }\nRwFrame *RwFrameAddChild(RwFrame * parent, RwFrame * child) { parent->addChild(child); return parent; }\nRwFrame *RwFrameGetParent(const RwFrame * frame) { return frame->getParent(); }\n//RwFrame *RwFrameGetRoot(const RwFrame * frame);\nRwMatrix *RwFrameGetLTM(RwFrame * frame) { return frame->getLTM(); }\nRwMatrix *RwFrameGetMatrix(RwFrame * frame) { return &frame->matrix; }\nRwFrame *RwFrameUpdateObjects(RwFrame * frame) { frame->updateObjects(); return frame; }\nRwFrame *RwFrameCreate(void) { return rw::Frame::create(); }\n//RwBool RwFrameInit(RwFrame *frame);\n//RwBool RwFrameDeInit(RwFrame *frame);\nRwBool RwFrameDestroy(RwFrame * frame) { frame->destroy(); return true; }\n//void _rwFrameInit(RwFrame *frame);\n//void _rwFrameDeInit(RwFrame *frame);\n//RwBool RwFrameDirty(const RwFrame * frame);\n//RwInt32 RwFrameCount(RwFrame * frame);\n//RwBool RwFrameSetStaticPluginsSize(RwInt32 size);\nRwInt32 RwFrameRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor constructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB)\n\t{ return Frame::registerPlugin(size, pluginID, constructCB, destructCB, (CopyConstructor)copyCB); }\n//RwInt32 RwFrameGetPluginOffset(RwUInt32 pluginID);\n//RwBool RwFrameValidatePlugins(const RwFrame * frame);\n//RwFrame *_rwFrameCloneAndLinkClones(RwFrame * root);\n//RwFrame *_rwFramePurgeClone(RwFrame *root);\n\nRwInt32 RwFrameRegisterPluginStream(RwUInt32 pluginID, RwPluginDataChunkReadCallBack readCB, RwPluginDataChunkWriteCallBack writeCB, RwPluginDataChunkGetSizeCallBack getSizeCB)\n\t{ return Frame::registerPluginStream(pluginID, readCB, (StreamWrite)writeCB, (StreamGetSize)getSizeCB); }\n\n\nrwFrameList *rwFrameListDeinitialize(rwFrameList *frameList) {\n\trwFree(frameList->frames);\n\tframeList->frames = nil;\n\treturn frameList;\n}\nrwFrameList *rwFrameListStreamRead(RwStream *stream, rwFrameList *fl) { return fl->streamRead(stream); }\n\n\n\n\nRwCamera    *RwCameraBeginUpdate(RwCamera * camera) { camera->beginUpdate(); return camera; }\nRwCamera    *RwCameraEndUpdate(RwCamera * camera) { camera->endUpdate(); return camera; }\nRwCamera    *RwCameraClear(RwCamera * camera, RwRGBA * colour, RwInt32 clearMode) { camera->clear(colour, clearMode); return camera; }\n// WARNING: ignored argument\nRwCamera    *RwCameraShowRaster(RwCamera * camera, void *pDev, RwUInt32 flags) { camera->showRaster(flags); return camera; }\nRwBool       RwCameraDestroy(RwCamera * camera) { camera->destroy(); return true; }\nRwCamera    *RwCameraCreate(void) { return rw::Camera::create(); }\nRwCamera    *RwCameraClone(RwCamera * camera) { return camera->clone(); }\nRwCamera    *RwCameraSetViewOffset(RwCamera *camera, const RwV2d *offset) { camera->setViewOffset(offset); return camera; }\nRwCamera    *RwCameraSetViewWindow(RwCamera *camera, const RwV2d *viewWindow) { camera->setViewWindow(viewWindow); return camera; }\nRwCamera    *RwCameraSetProjection(RwCamera *camera, RwCameraProjection projection) { camera->projection = projection; return camera; }\nRwCamera    *RwCameraSetNearClipPlane(RwCamera *camera, RwReal nearClip) { camera->setNearPlane(nearClip); return camera; }\nRwCamera    *RwCameraSetFarClipPlane(RwCamera *camera, RwReal farClip) { camera->setFarPlane(farClip); return camera; }\nRwInt32      RwCameraRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor constructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB);\nRwInt32      RwCameraGetPluginOffset(RwUInt32 pluginID);\nRwBool       RwCameraValidatePlugins(const RwCamera * camera);\nRwFrustumTestResult RwCameraFrustumTestSphere(const RwCamera * camera, const RwSphere * sphere) { return (RwFrustumTestResult)camera->frustumTestSphere(sphere); }\nconst RwV2d *RwCameraGetViewOffset(const RwCamera *camera) { return &camera->viewOffset; }\nRwCamera    *RwCameraSetRaster(RwCamera *camera, RwRaster *raster) { camera->frameBuffer = raster; return camera; }\nRwRaster    *RwCameraGetRaster(const RwCamera *camera) { return camera->frameBuffer; }\nRwCamera    *RwCameraSetZRaster(RwCamera *camera, RwRaster *zRaster) { camera->zBuffer = zRaster; return camera; }\nRwRaster    *RwCameraGetZRaster(const RwCamera *camera) { return camera->zBuffer; }\nRwReal       RwCameraGetNearClipPlane(const RwCamera *camera) { return camera->nearPlane; }\nRwReal       RwCameraGetFarClipPlane(const RwCamera *camera) { return camera->farPlane; }\nRwCamera    *RwCameraSetFogDistance(RwCamera *camera, RwReal fogDistance) { camera->fogPlane = fogDistance; return camera; }\nRwReal       RwCameraGetFogDistance(const RwCamera *camera) { return camera->fogPlane; }\nRwCamera    *RwCameraGetCurrentCamera(void) { return rw::engine->currentCamera; }\nRwCameraProjection RwCameraGetProjection(const RwCamera *camera);\nconst RwV2d *RwCameraGetViewWindow(const RwCamera *camera) { return &camera->viewWindow; }\nRwMatrix    *RwCameraGetViewMatrix(RwCamera *camera) { return &camera->viewMatrix; }\nRwCamera    *RwCameraSetFrame(RwCamera *camera, RwFrame *frame) { camera->setFrame(frame); return camera; }\nRwFrame     *RwCameraGetFrame(const RwCamera *camera) { return camera->getFrame(); }\n\n\n\n\n\nRwImage     *RwImageCreate(RwInt32 width, RwInt32 height, RwInt32 depth) { return Image::create(width, height, depth); }\nRwBool       RwImageDestroy(RwImage * image) { image->destroy(); return true; }\nRwImage     *RwImageAllocatePixels(RwImage * image) { image->allocate(); return image; }\nRwImage     *RwImageFreePixels(RwImage * image) { image->free(); return image; }\nRwImage     *RwImageCopy(RwImage * destImage, const RwImage * sourceImage);\nRwImage     *RwImageResize(RwImage * image, RwInt32 width, RwInt32 height);\nRwImage     *RwImageApplyMask(RwImage * image, const RwImage * mask);\nRwImage     *RwImageMakeMask(RwImage * image);\nRwImage     *RwImageReadMaskedImage(const RwChar * imageName, const RwChar * maskname);\nRwImage     *RwImageRead(const RwChar * imageName);\nRwImage     *RwImageWrite(RwImage * image, const RwChar * imageName);\nRwChar      *RwImageGetPath(void);\nconst RwChar *RwImageSetPath(const RwChar * path) { Image::setSearchPath(path); return path; }\nRwImage     *RwImageSetStride(RwImage * image, RwInt32 stride) { image->stride = stride; return image; }\nRwImage     *RwImageSetPixels(RwImage * image, RwUInt8 * pixels) { image->pixels = pixels; return image; }\nRwImage     *RwImageSetPalette(RwImage * image, RwRGBA * palette) { image->palette = (uint8*)palette; return image; }\nRwInt32      RwImageGetWidth(const RwImage * image) { return image->width; }\nRwInt32      RwImageGetHeight(const RwImage * image) { return image->height; }\nRwInt32      RwImageGetDepth(const RwImage * image) { return image->depth; }\nRwInt32      RwImageGetStride(const RwImage * image) { return image->stride; }\nRwUInt8     *RwImageGetPixels(const RwImage * image) { return image->pixels; }\nRwRGBA      *RwImageGetPalette(const RwImage * image) { return (RwRGBA*)image->palette; }\nRwUInt32     RwRGBAToPixel(RwRGBA * rgbIn, RwInt32 rasterFormat);\nRwRGBA      *RwRGBASetFromPixel(RwRGBA * rgbOut, RwUInt32 pixelValue, RwInt32 rasterFormat);\nRwBool       RwImageSetGamma(RwReal gammaValue);\nRwReal       RwImageGetGamma(void);\nRwImage     *RwImageGammaCorrect(RwImage * image);\nRwRGBA      *RwRGBAGammaCorrect(RwRGBA * rgb);\nRwInt32      RwImageRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor constructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB);\nRwInt32      RwImageGetPluginOffset(RwUInt32 pluginID);\nRwBool       RwImageValidatePlugins(const RwImage * image);\n//RwBool       RwImageRegisterImageFormat(const RwChar * extension, RwImageCallBackRead imageRead, RwImageCallBackWrite imageWrite);\nconst RwChar *RwImageFindFileType(const RwChar * imageName);\nRwInt32      RwImageStreamGetSize(const RwImage * image);\nRwImage     *RwImageStreamRead(RwStream * stream);\nconst RwImage *RwImageStreamWrite(const RwImage * image, RwStream * stream);\n\nRwImage *RwImageFindRasterFormat(RwImage *ipImage,RwInt32 nRasterType, RwInt32 *npWidth,RwInt32 *npHeight, RwInt32 *npDepth,RwInt32 *npFormat)\n{\n\treturn Raster::imageFindRasterFormat(ipImage, nRasterType, npWidth, npHeight, npDepth, npFormat) ? ipImage : nil;\n}\n\n\n\n\nRwRaster    *RwRasterCreate(RwInt32 width, RwInt32 height, RwInt32 depth, RwInt32 flags) { return Raster::create(width, height, depth, flags); }\nRwBool       RwRasterDestroy(RwRaster * raster) { raster->destroy(); return true; }\nRwInt32      RwRasterGetWidth(const RwRaster *raster) { return raster->width; }\nRwInt32      RwRasterGetHeight(const RwRaster *raster) { return raster->height; }\nRwInt32      RwRasterGetStride(const RwRaster *raster);\nRwInt32      RwRasterGetDepth(const RwRaster *raster) { return raster->depth; }\nRwInt32      RwRasterGetFormat(const RwRaster *raster);\nRwInt32      RwRasterGetType(const RwRaster *raster);\nRwRaster    *RwRasterGetParent(const RwRaster *raster) { return raster->parent; }\nRwRaster    *RwRasterGetOffset(RwRaster *raster,  RwInt16 *xOffset, RwInt16 *yOffset);\nRwInt32      RwRasterGetNumLevels(RwRaster * raster);\nRwRaster    *RwRasterSubRaster(RwRaster * subRaster, RwRaster * raster, RwRect * rect);\nRwRaster    *RwRasterRenderFast(RwRaster * raster, RwInt32 x, RwInt32 y) { return raster->renderFast(x, y) ? raster : nil; }\nRwRaster    *RwRasterRender(RwRaster * raster, RwInt32 x, RwInt32 y);\nRwRaster    *RwRasterRenderScaled(RwRaster * raster, RwRect * rect);\nRwRaster    *RwRasterPushContext(RwRaster * raster) { return Raster::pushContext(raster); }\nRwRaster    *RwRasterPopContext(void) { return Raster::popContext(); }\nRwRaster    *RwRasterGetCurrentContext(void) { return Raster::getCurrentContext(); }\nRwBool       RwRasterClear(RwInt32 pixelValue);\nRwBool       RwRasterClearRect(RwRect * rpRect, RwInt32 pixelValue);\nRwRaster    *RwRasterShowRaster(RwRaster * raster, void *dev, RwUInt32 flags);\nRwUInt8     *RwRasterLock(RwRaster * raster, RwUInt8 level, RwInt32 lockMode);\nRwRaster    *RwRasterUnlock(RwRaster * raster);\nRwUInt8     *RwRasterLockPalette(RwRaster * raster, RwInt32 lockMode);\nRwRaster    *RwRasterUnlockPalette(RwRaster * raster);\nRwInt32      RwRasterRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor constructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB);\nRwInt32      RwRasterGetPluginOffset(RwUInt32 pluginID);\nRwBool       RwRasterValidatePlugins(const RwRaster * raster);\n\nRwRaster *RwRasterSetFromImage(RwRaster *raster, RwImage *image) { return raster->setFromImage(image); }\n\n\n\n\nRwTexture *RwTextureCreate(RwRaster * raster) { return Texture::create(raster); }\nRwBool RwTextureDestroy(RwTexture * texture) { texture->destroy(); return true; }\nRwTexture *RwTextureAddRef(RwTexture *texture) { texture->addRef(); return texture; }\n// TODO\nRwBool RwTextureSetMipmapping(RwBool enable) { return true; }\nRwBool RwTextureGetMipmapping(void);\n// TODO\nRwBool RwTextureSetAutoMipmapping(RwBool enable) { return true; }\nRwBool RwTextureGetAutoMipmapping(void);\nRwBool RwTextureSetMipmapGenerationCallBack(RwTextureCallBackMipmapGeneration callback);\nRwTextureCallBackMipmapGeneration RwTextureGetMipmapGenerationCallBack(void);\nRwBool RwTextureSetMipmapNameCallBack(RwTextureCallBackMipmapName callback);\nRwTextureCallBackMipmapName RwTextureGetMipmapNameCallBack(void);\nRwBool RwTextureGenerateMipmapName(RwChar * name, RwChar * maskName, RwUInt8 mipLevel, RwInt32 format);\nRwBool RwTextureRasterGenerateMipmaps(RwRaster * raster, RwImage * image);\nRwTextureCallBackRead RwTextureGetReadCallBack(void);\nRwBool RwTextureSetReadCallBack(RwTextureCallBackRead fpCallBack);\nRwTexture *RwTextureSetName(RwTexture * texture, const RwChar * name) { strncpy(texture->name, name, 32); return texture; }\nRwTexture *RwTextureSetMaskName(RwTexture * texture, const RwChar * maskName);\nRwChar *RwTextureGetName(RwTexture *texture) { return texture->name; }\nRwChar *RwTextureGetMaskName(RwTexture *texture);\nRwTexture *RwTextureSetRaster(RwTexture * texture, RwRaster * raster) { texture->raster = raster; return texture; }\nRwTexture   *RwTextureRead(const RwChar * name, const RwChar * maskName) { return Texture::read(name, maskName); }\nRwRaster *RwTextureGetRaster(const RwTexture *texture) { return texture->raster; }\nRwInt32 RwTextureRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor constructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB);\nRwInt32 RwTextureGetPluginOffset(RwUInt32 pluginID);\nRwBool RwTextureValidatePlugins(const RwTexture * texture);\n\nRwTexDictionary *RwTextureGetDictionary(RwTexture *texture);\nRwTexture *RwTextureSetFilterMode(RwTexture *texture, RwTextureFilterMode filtering) { texture->setFilter((Texture::FilterMode)filtering); return texture; }\nRwTextureFilterMode RwTextureGetFilterMode(const RwTexture *texture);\nRwTexture *RwTextureSetAddressing(RwTexture *texture, RwTextureAddressMode addressing) {\n\ttexture->setAddressU((Texture::Addressing)addressing);\n\ttexture->setAddressV((Texture::Addressing)addressing);\n\treturn texture;\n}\nRwTexture *RwTextureSetAddressingU(RwTexture *texture, RwTextureAddressMode addressing) {\n\ttexture->setAddressU((Texture::Addressing)addressing);\n\treturn texture;\n}\nRwTexture *RwTextureSetAddressingV(RwTexture *texture, RwTextureAddressMode addressing) {\n\ttexture->setAddressV((Texture::Addressing)addressing);\n\treturn texture;\n}\nRwTextureAddressMode RwTextureGetAddressing(const RwTexture *texture);\nRwTextureAddressMode RwTextureGetAddressingU(const RwTexture *texture);\nRwTextureAddressMode RwTextureGetAddressingV(const RwTexture *texture);\n\n// TODO\nvoid _rwD3D8TexDictionaryEnableRasterFormatConversion(bool enable) { }\n\n\n// hack for reading native textures\nRwBool rwNativeTextureHackRead(RwStream *stream, RwTexture **tex, RwInt32 size)\n{\n\t*tex = Texture::streamReadNative(stream);\n#ifdef LIBRW\n\t(*tex)->raster = rw::Raster::convertTexToCurrentPlatform((*tex)->raster);\n#endif\n\treturn *tex != nil;\n}\n\n\n\n\n\nRwTexDictionary *RwTexDictionaryCreate(void) { return TexDictionary::create(); }\nRwBool RwTexDictionaryDestroy(RwTexDictionary * dict) { dict->destroy(); return true; }\nRwTexture *RwTexDictionaryAddTexture(RwTexDictionary * dict, RwTexture * texture) { dict->addFront(texture); return texture; }\n//RwTexture *RwTexDictionaryRemoveTexture(RwTexture * texture);\nRwTexture *RwTexDictionaryFindNamedTexture(RwTexDictionary * dict, const RwChar * name) { return dict->find(name); }\nRwTexDictionary *RwTexDictionaryGetCurrent(void) { return TexDictionary::getCurrent(); }\nRwTexDictionary *RwTexDictionarySetCurrent(RwTexDictionary * dict) { TexDictionary::setCurrent(dict); return dict; }\nconst RwTexDictionary *RwTexDictionaryForAllTextures(const RwTexDictionary * dict, RwTextureCallBack fpCallBack, void *pData) {\n\tFORLIST(lnk, ((RwTexDictionary*)dict)->textures)\n\t\tif(fpCallBack(Texture::fromDict(lnk), pData) == nil)\n\t\t\tbreak;\n\treturn dict;\n}\nRwBool RwTexDictionaryForAllTexDictionaries(RwTexDictionaryCallBack fpCallBack, void *pData);\nRwInt32 RwTexDictionaryRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor constructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB);\nRwInt32 RwTexDictionaryGetPluginOffset(RwUInt32 pluginID);\nRwBool RwTexDictionaryValidatePlugins(const RwTexDictionary * dict);\nRwUInt32 RwTexDictionaryStreamGetSize(const RwTexDictionary *texDict);\nRwTexDictionary *RwTexDictionaryStreamRead(RwStream *stream);\nconst RwTexDictionary *RwTexDictionaryStreamWrite(const RwTexDictionary *texDict, RwStream *stream) {\n\t((RwTexDictionary*)texDict)->streamWrite(stream);\n\treturn texDict;\n}\n\n\n\n\n\nRwStream *RwStreamOpen(RwStreamType type, RwStreamAccessType accessType, const void *pData) {\n\tStreamFile *file;\n\tStreamMemory *mem;\n\tRwMemory *memargs;\n\tconst char *mode;\n\n\tswitch(accessType){\n\tcase rwSTREAMREAD: mode = \"rb\"; break;\n\tcase rwSTREAMWRITE: mode = \"wb\"; break;\n\tcase rwSTREAMAPPEND: mode = \"ab\"; break;\n\tdefault: return nil;\n\t}\n\n\t// oh god this is horrible. librw streams really need fixing\n\tswitch(type){\n\tcase rwSTREAMFILENAME:{\n\t\tStreamFile fakefile;\n\t\tfile = rwNewT(StreamFile, 1, 0);\n\t\tmemcpy(file, &fakefile, sizeof(StreamFile));\n#ifndef _WIN32\n\t\tchar *r = casepath((char*)pData);\n\t\tif (r) {\n\t\t\tif (file->open((char*)r, mode)) {\n\t\t\t\tfree(r);\n\t\t\t\treturn file;\n\t\t\t}\n\t\t\tfree(r);\n\t\t} else\n#endif\n\t\t{\n\t\t\tif (file->open((char*)pData, mode))\n\t\t\t\treturn file;\n\t\t}\n\t\trwFree(file);\n\t\treturn nil;\n\t}\n\tcase rwSTREAMMEMORY:{\n\t\tStreamMemory fakemem;\n\t\tmemargs = (RwMemory*)pData;\n\t\tmem = rwNewT(StreamMemory, 1, 0);\n\t\tmemcpy(mem, &fakemem, sizeof(StreamMemory));\n\t\tif(mem->open(memargs->start, memargs->length))\n\t\t\treturn mem;\n\t\trwFree(mem);\n\t\treturn nil;\n\t}\n\tdefault:\n\t\tassert(0 && \"unknown type\");\n\t\treturn nil;\n\t}\n}\nRwBool RwStreamClose(RwStream * stream, void *pData) { stream->close(); rwFree(stream); return true; }\nRwUInt32 RwStreamRead(RwStream * stream, void *buffer, RwUInt32 length) { return stream->read8(buffer, length); }\nRwStream *RwStreamWrite(RwStream * stream, const void *buffer, RwUInt32 length) { stream->write8(buffer, length); return stream; }\nRwStream *RwStreamSkip(RwStream * stream, RwUInt32 offset) { stream->seek(offset); return stream; }\n\nRwBool RwStreamFindChunk(RwStream *stream, RwUInt32 type, RwUInt32 *lengthOut, RwUInt32 *versionOut)\n\t{ return findChunk(stream, type, lengthOut, versionOut); }\n\n\n\nvoid RwIm2DVertexSetCameraX(RwIm2DVertex *vert, RwReal camx) { }\nvoid RwIm2DVertexSetCameraY(RwIm2DVertex *vert, RwReal camy) { }\nvoid RwIm2DVertexSetCameraZ(RwIm2DVertex *vert, RwReal camz) { vert->setCameraZ(camz); }\nvoid RwIm2DVertexSetRecipCameraZ(RwIm2DVertex *vert, RwReal recipz) { vert->setRecipCameraZ(recipz); }\nvoid RwIm2DVertexSetScreenX(RwIm2DVertex *vert, RwReal scrnx) { vert->setScreenX(scrnx); }\nvoid RwIm2DVertexSetScreenY(RwIm2DVertex *vert, RwReal scrny) { vert->setScreenY(scrny); }\nvoid RwIm2DVertexSetScreenZ(RwIm2DVertex *vert, RwReal scrnz) { vert->setScreenZ(scrnz); }\nvoid RwIm2DVertexSetU(RwIm2DVertex *vert, RwReal texU, RwReal recipz) { vert->setU(texU, recipz); }\nvoid RwIm2DVertexSetV(RwIm2DVertex *vert, RwReal texV, RwReal recipz) { vert->setV(texV, recipz); }\nvoid RwIm2DVertexSetIntRGBA(RwIm2DVertex *vert, RwUInt8 red, RwUInt8 green, RwUInt8 blue, RwUInt8 alpha) { vert->setColor(red, green, blue, alpha); }\n\nRwReal RwIm2DGetNearScreenZ(void) { return im2d::GetNearZ(); }\nRwReal RwIm2DGetFarScreenZ(void) { return im2d::GetFarZ(); }\nRwBool RwIm2DRenderLine(RwIm2DVertex *vertices, RwInt32 numVertices, RwInt32 vert1, RwInt32 vert2)\n\t{ im2d::RenderLine(vertices, numVertices, vert1, vert2); return true; }\nRwBool RwIm2DRenderTriangle(RwIm2DVertex *vertices, RwInt32 numVertices, RwInt32 vert1, RwInt32 vert2, RwInt32 vert3 )\n\t{ im2d::RenderTriangle(vertices, numVertices, vert1, vert2, vert3); return true; }\nRwBool RwIm2DRenderPrimitive(RwPrimitiveType primType, RwIm2DVertex *vertices, RwInt32 numVertices)\n\t{ im2d::RenderPrimitive((PrimitiveType)primType, vertices, numVertices); return true; }\nRwBool RwIm2DRenderIndexedPrimitive(RwPrimitiveType primType, RwIm2DVertex *vertices, RwInt32 numVertices, RwImVertexIndex *indices, RwInt32 numIndices)\n\t{ im2d::RenderIndexedPrimitive((PrimitiveType)primType, vertices, numVertices, indices, numIndices); return true; }\n\n\nvoid RwIm3DVertexSetPos(RwIm3DVertex *vert, RwReal x, RwReal y, RwReal z) { vert->setX(x); vert->setY(y); vert->setZ(z); }\nvoid RwIm3DVertexSetU(RwIm3DVertex *vert, RwReal u) { vert->setU(u); }\nvoid RwIm3DVertexSetV(RwIm3DVertex *vert, RwReal v) { vert->setV(v); }\nvoid RwIm3DVertexSetRGBA(RwIm3DVertex *vert, RwUInt8 r, RwUInt8 g, RwUInt8 b, RwUInt8 a) { vert->setColor(r, g, b, a); }\n\nvoid  *RwIm3DTransform(RwIm3DVertex *pVerts, RwUInt32 numVerts, RwMatrix *ltm, RwUInt32 flags) { im3d::Transform(pVerts, numVerts, ltm, flags); return pVerts; }\nRwBool RwIm3DEnd(void) { im3d::End(); return true; }\nRwBool RwIm3DRenderLine(RwInt32 vert1, RwInt32 vert2) {\n\tRwImVertexIndex indices[2];\n\tindices[0] = vert1;\n\tindices[1] = vert2;\n\tim3d::RenderIndexedPrimitive((PrimitiveType)PRIMTYPELINELIST, indices, 2);\n\treturn true;\n}\nRwBool RwIm3DRenderTriangle(RwInt32 vert1, RwInt32 vert2, RwInt32 vert3);\nRwBool RwIm3DRenderIndexedPrimitive(RwPrimitiveType primType, RwImVertexIndex *indices, RwInt32 numIndices) { im3d::RenderIndexedPrimitive((PrimitiveType)primType, indices, numIndices); return true; }\nRwBool RwIm3DRenderPrimitive(RwPrimitiveType primType);\n\n\n\n\n\nRwBool RwRenderStateGet(RwRenderState state, void *value)\n{\n\tuint32 *uival = (uint32*)value;\n\tuint32 fog;\n\tswitch(state){\n\tcase rwRENDERSTATETEXTURERASTER: *(void**)value = GetRenderStatePtr(TEXTURERASTER); return true;\n\tcase rwRENDERSTATETEXTUREADDRESS: *uival = GetRenderState(TEXTUREADDRESS); return true;\n\tcase rwRENDERSTATETEXTUREADDRESSU: *uival = GetRenderState(TEXTUREADDRESSU); return true;\n\tcase rwRENDERSTATETEXTUREADDRESSV: *uival = GetRenderState(TEXTUREADDRESSV); return true;\n\tcase rwRENDERSTATETEXTUREPERSPECTIVE: *uival = 1; return true;\n\tcase rwRENDERSTATEZTESTENABLE: *uival = GetRenderState(ZTESTENABLE); return true;\n\tcase rwRENDERSTATESHADEMODE: *uival = rwSHADEMODEGOURAUD; return true;\n\tcase rwRENDERSTATEZWRITEENABLE: *uival = GetRenderState(ZWRITEENABLE); return true;\n\tcase rwRENDERSTATETEXTUREFILTER: *uival = GetRenderState(TEXTUREFILTER); return true;\n\tcase rwRENDERSTATESRCBLEND: *uival = GetRenderState(SRCBLEND); return true;\n\tcase rwRENDERSTATEDESTBLEND: *uival = GetRenderState(DESTBLEND); return true;\n\tcase rwRENDERSTATEVERTEXALPHAENABLE: *uival = GetRenderState(VERTEXALPHA); return true;\n\tcase rwRENDERSTATEBORDERCOLOR: *uival = 0; return true;\n\tcase rwRENDERSTATEFOGENABLE: *uival = GetRenderState(FOGENABLE); return true;\n\tcase rwRENDERSTATEFOGCOLOR:\n\t\t// have to swap R and B here\n\t\tfog = GetRenderState(FOGCOLOR);\n\t\t*uival = (fog>>16)&0xFF;\n\t\t*uival |= (fog&0xFF)<<16;\n\t\t*uival |= fog&0xFF00;\n\t\t*uival |= fog&0xFF000000;\n\t\treturn true;\n\tcase rwRENDERSTATEFOGTYPE: *uival = rwFOGTYPELINEAR; return true;\n\tcase rwRENDERSTATEFOGDENSITY: *(float*)value = 1.0f; return true;\n\tcase rwRENDERSTATECULLMODE: *uival = GetRenderState(CULLMODE); return true;\n\n\t// all unsupported\n\tcase rwRENDERSTATEFOGTABLE:\n\tcase rwRENDERSTATEALPHAPRIMITIVEBUFFER:\n\n\tcase rwRENDERSTATESTENCILENABLE:\n\tcase rwRENDERSTATESTENCILFAIL:\n\tcase rwRENDERSTATESTENCILZFAIL:\n\tcase rwRENDERSTATESTENCILPASS:\n\tcase rwRENDERSTATESTENCILFUNCTION:\n\tcase rwRENDERSTATESTENCILFUNCTIONREF:\n\tcase rwRENDERSTATESTENCILFUNCTIONMASK:\n\tcase rwRENDERSTATESTENCILFUNCTIONWRITEMASK:\n\tdefault:\n\t\treturn false;\n\t}\n}\nRwBool RwRenderStateSet(RwRenderState state, void *value)\n{\n\tuint32 uival = (uintptr)value;\n\tuint32 fog;\n\tswitch(state){\n\tcase rwRENDERSTATETEXTURERASTER: SetRenderStatePtr(TEXTURERASTER, value); return true;\n\tcase rwRENDERSTATETEXTUREADDRESS: SetRenderState(TEXTUREADDRESS, uival); return true;\n\tcase rwRENDERSTATETEXTUREADDRESSU: SetRenderState(TEXTUREADDRESSU, uival); return true;\n\tcase rwRENDERSTATETEXTUREADDRESSV: SetRenderState(TEXTUREADDRESSV, uival); return true;\n\tcase rwRENDERSTATETEXTUREPERSPECTIVE: return true;\n\tcase rwRENDERSTATEZTESTENABLE: SetRenderState(ZTESTENABLE, uival); return true;\n\tcase rwRENDERSTATESHADEMODE: return true;\n\tcase rwRENDERSTATEZWRITEENABLE: SetRenderState(ZWRITEENABLE, uival); return true;\n\tcase rwRENDERSTATETEXTUREFILTER: SetRenderState(TEXTUREFILTER, uival); return true;\n\tcase rwRENDERSTATESRCBLEND: SetRenderState(SRCBLEND, uival); return true;\n\tcase rwRENDERSTATEDESTBLEND: SetRenderState(DESTBLEND, uival); return true;\n\tcase rwRENDERSTATEVERTEXALPHAENABLE: SetRenderState(VERTEXALPHA, uival); return true;\n\tcase rwRENDERSTATEBORDERCOLOR: return true;\n\tcase rwRENDERSTATEFOGENABLE: SetRenderState(FOGENABLE, uival); return true;\n\tcase rwRENDERSTATEFOGCOLOR:\n\t\t// have to swap R and B here\n\t\tfog = (uival>>16)&0xFF;\n\t\tfog |= (uival&0xFF)<<16;\n\t\tfog |= uival&0xFF00;\n\t\tfog |= uival&0xFF000000;\n\t\tSetRenderState(FOGCOLOR, fog);\n\t\treturn true;\n\tcase rwRENDERSTATEFOGTYPE: return true;\n\tcase rwRENDERSTATEFOGDENSITY: return true;\n\tcase rwRENDERSTATEFOGTABLE: return true;\n\tcase rwRENDERSTATEALPHAPRIMITIVEBUFFER: return true;\n\tcase rwRENDERSTATECULLMODE: SetRenderState(CULLMODE, uival); return true;\n\n\t// all unsupported\n\tcase rwRENDERSTATESTENCILENABLE:\n\tcase rwRENDERSTATESTENCILFAIL:\n\tcase rwRENDERSTATESTENCILZFAIL:\n\tcase rwRENDERSTATESTENCILPASS:\n\tcase rwRENDERSTATESTENCILFUNCTION:\n\tcase rwRENDERSTATESTENCILFUNCTIONREF:\n\tcase rwRENDERSTATESTENCILFUNCTIONMASK:\n\tcase rwRENDERSTATESTENCILFUNCTIONWRITEMASK:\n\tdefault:\n\t\treturn true;\n\t}\n}\n\nstatic rw::MemoryFunctions gMemfuncs;\nstatic void *(*real_malloc)(size_t size);\nstatic void *(*real_realloc)(void *mem, size_t newSize);\nstatic void *mallocWrap(size_t sz, uint32 hint) { if(sz == 0) return nil; return real_malloc(sz); }\nstatic void *reallocWrap(void *p, size_t sz, uint32 hint) { return real_realloc(p, sz); }\n\n\n// WARNING: unused parameters\nRwBool RwEngineInit(RwMemoryFunctions *memFuncs, RwUInt32 initFlags, RwUInt32 resArenaSize) {\n\tif(memFuncs){\n\t\treal_malloc = memFuncs->rwmalloc;\n\t\treal_realloc = memFuncs->rwrealloc;\n\t\tgMemfuncs.rwmalloc = mallocWrap;\n\t\tgMemfuncs.rwrealloc = reallocWrap;\n\t\tgMemfuncs.rwfree = memFuncs->rwfree;\n\t\tEngine::init(&gMemfuncs);\n\t}else{\n\t\tEngine::init(nil);\n\t}\n\treturn true;\n}\n// TODO: this is platform dependent\nRwBool RwEngineOpen(RwEngineOpenParams *initParams) {\n\tstatic EngineOpenParams openParams;\n#ifdef RW_D3D9\n\topenParams.window = (HWND)initParams->displayID;\n#else\n\topenParams = *(EngineOpenParams*)initParams->displayID;\n#endif\n\treturn Engine::open(&openParams);\n}\nRwBool RwEngineStart(void) {\n\trw::d3d::isP8supported = false;\n\treturn Engine::start();\n}\nRwBool RwEngineStop(void) { Engine::stop(); return true; }\nRwBool RwEngineClose(void) { Engine::close(); return true; }\nRwBool RwEngineTerm(void) { Engine::term(); return true; }\nRwInt32 RwEngineRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor initCB, RwPluginObjectDestructor termCB);\nRwInt32 RwEngineGetPluginOffset(RwUInt32 pluginID);\nRwInt32 RwEngineGetNumSubSystems(void) { return Engine::getNumSubSystems(); }\nRwSubSystemInfo *RwEngineGetSubSystemInfo(RwSubSystemInfo *subSystemInfo, RwInt32 subSystemIndex)\n\t{ return Engine::getSubSystemInfo(subSystemInfo, subSystemIndex); }\nRwInt32 RwEngineGetCurrentSubSystem(void) { return Engine::getCurrentSubSystem(); }\nRwBool RwEngineSetSubSystem(RwInt32 subSystemIndex) { return Engine::setSubSystem(subSystemIndex); }\nRwInt32 RwEngineGetNumVideoModes(void) { return Engine::getNumVideoModes(); }\nRwVideoMode *RwEngineGetVideoModeInfo(RwVideoMode *modeinfo, RwInt32 modeIndex)\n\t{ return Engine::getVideoModeInfo(modeinfo, modeIndex); }\nRwInt32 RwEngineGetCurrentVideoMode(void) { return Engine::getCurrentVideoMode(); }\nRwBool RwEngineSetVideoMode(RwInt32 modeIndex) { return Engine::setVideoMode(modeIndex); }\nRwInt32 RwEngineGetTextureMemorySize(void);\nRwInt32 RwEngineGetMaxTextureSize(void);\n\n\n\n// TODO\nvoid RwD3D8EngineSetRefreshRate(RwUInt32 refreshRate) {}\nRwBool RwD3D8DeviceSupportsDXTTexture(void) { return true; }\n\n\nvoid RwD3D8EngineSetMultiSamplingLevels(RwUInt32 level) { Engine::setMultiSamplingLevels(level); }\nRwUInt32 RwD3D8EngineGetMaxMultiSamplingLevels(void) { return Engine::getMaxMultiSamplingLevels(); }\n\n\nRpMaterial *RpMaterialCreate(void) { return Material::create(); }\nRwBool RpMaterialDestroy(RpMaterial *material) { material->destroy(); return true; }\n//RpMaterial *RpMaterialClone(RpMaterial *material);\nRpMaterial *RpMaterialSetTexture(RpMaterial *material, RwTexture *texture) { material->setTexture(texture); return material; }\n//RpMaterial *RpMaterialAddRef(RpMaterial *material);\nRwTexture *RpMaterialGetTexture(const RpMaterial *material) { return material->texture; }\nRpMaterial *RpMaterialSetColor(RpMaterial *material, const RwRGBA *color) { material->color = *color; return material; }\nconst RwRGBA *RpMaterialGetColor(const RpMaterial *material) { return &material->color; }\nRpMaterial *RpMaterialSetSurfaceProperties(RpMaterial *material, const RwSurfaceProperties *surfaceProperties);\nconst RwSurfaceProperties *RpMaterialGetSurfaceProperties(const RpMaterial *material) { return &material->surfaceProps; }\n//RwInt32 RpMaterialRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor constructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB);\n//RwInt32 RpMaterialRegisterPluginStream(RwUInt32 pluginID, RwPluginDataChunkReadCallBack readCB, RwPluginDataChunkWriteCallBack writeCB, RwPluginDataChunkGetSizeCallBack getSizeCB);\n//RwInt32 RpMaterialSetStreamAlwaysCallBack(RwUInt32 pluginID, RwPluginDataChunkAlwaysCallBack alwaysCB);\n//RwInt32 RpMaterialGetPluginOffset(RwUInt32 pluginID);\n//RwBool RpMaterialValidatePlugins(const RpMaterial *material);\n//RwUInt32 RpMaterialStreamGetSize(const RpMaterial *material);\n//RpMaterial *RpMaterialStreamRead(RwStream *stream);\n//const RpMaterial *RpMaterialStreamWrite(const RpMaterial *material, RwStream *stream);\n//RpMaterialChunkInfo *_rpMaterialChunkInfoRead(RwStream *stream,  RpMaterialChunkInfo *materialChunkInfo, RwInt32 *bytesRead);\n\n\n\n\n\nRwReal RpLightGetRadius(const RpLight *light) { return light->radius; }\n//const RwRGBAReal *RpLightGetColor(const RpLight *light);\nRpLight *RpLightSetFrame(RpLight *light, RwFrame *frame) { light->setFrame(frame); return light; }\nRwFrame *RpLightGetFrame(const RpLight *light) { return light->getFrame(); }\n//RpLightType RpLightGetType(const RpLight *light);\nRpLight *RpLightSetFlags(RpLight *light, RwUInt32 flags) { light->setFlags(flags); return light; }\n//RwUInt32 RpLightGetFlags(const RpLight *light);\nRpLight *RpLightCreate(RwInt32 type) { return rw::Light::create(type); }\nRwBool RpLightDestroy(RpLight *light) { light->destroy(); return true; }\nRpLight *RpLightSetRadius(RpLight *light, RwReal radius) { light->radius = radius; return light; }\nRpLight *RpLightSetColor(RpLight *light, const RwRGBAReal *color) { light->setColor(color->red, color->green, color->blue); return light; }\n//RwReal RpLightGetConeAngle(const RpLight *light);\n//RpLight *RpLightSetConeAngle(RpLight * ight, RwReal angle);\n//RwUInt32 RpLightStreamGetSize(const RpLight *light);\n//RpLight *RpLightStreamRead(RwStream *stream);\n//const RpLight *RpLightStreamWrite(const RpLight *light, RwStream *stream);\n//RpLightChunkInfo *_rpLightChunkInfoRead(RwStream *stream, RpLightChunkInfo *lightChunkInfo, RwInt32 *bytesRead);\n//RwInt32 RpLightRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor constructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB);\n//RwInt32 RpLightRegisterPluginStream(RwUInt32 pluginID, RwPluginDataChunkReadCallBack readCB, RwPluginDataChunkWriteCallBack writeCB, RwPluginDataChunkGetSizeCallBack getSizeCB);\n//RwInt32 RpLightSetStreamAlwaysCallBack(RwUInt32 pluginID, RwPluginDataChunkAlwaysCallBack alwaysCB);\n//RwInt32 RpLightGetPluginOffset(RwUInt32 pluginID);\n//RwBool RpLightValidatePlugins(const RpLight * light);\n\n\n\n\n\nRpGeometry  *RpGeometryCreate(RwInt32 numVert, RwInt32 numTriangles, RwUInt32 format) { return Geometry::create(numVert, numTriangles, format); }\nRwBool RpGeometryDestroy(RpGeometry *geometry) { geometry->destroy(); return true; }\nRpGeometry *_rpGeometryAddRef(RpGeometry *geometry);\nRpGeometry  *RpGeometryLock(RpGeometry *geometry, RwInt32 lockMode) { geometry->lock(lockMode); return geometry; }\nRpGeometry  *RpGeometryUnlock(RpGeometry *geometry) { geometry->unlock(); return geometry; }\nRpGeometry  *RpGeometryTransform(RpGeometry *geometry, const RwMatrix *matrix);\nRpGeometry  *RpGeometryCreateSpace(RwReal radius);\nRpMorphTarget  *RpMorphTargetSetBoundingSphere(RpMorphTarget *morphTarget, const RwSphere *boundingSphere) { morphTarget->boundingSphere = *boundingSphere; return morphTarget; }\nRwSphere  *RpMorphTargetGetBoundingSphere(RpMorphTarget *morphTarget) { return &morphTarget->boundingSphere; }\nconst RpMorphTarget  *RpMorphTargetCalcBoundingSphere(const RpMorphTarget *morphTarget, RwSphere *boundingSphere) { *boundingSphere = morphTarget->calculateBoundingSphere(); return morphTarget; }\nRwInt32 RpGeometryAddMorphTargets(RpGeometry *geometry, RwInt32 mtcount) { RwInt32 n = geometry->numMorphTargets; geometry->addMorphTargets(mtcount); return n; }\nRwInt32 RpGeometryAddMorphTarget(RpGeometry *geometry) { return RpGeometryAddMorphTargets(geometry, 1); }\nRpGeometry  *RpGeometryRemoveMorphTarget(RpGeometry *geometry, RwInt32 morphTarget);\nRwInt32 RpGeometryGetNumMorphTargets(const RpGeometry *geometry);\nRpMorphTarget  *RpGeometryGetMorphTarget(const RpGeometry *geometry, RwInt32 morphTarget) { return &geometry->morphTargets[morphTarget]; }\nRwRGBA  *RpGeometryGetPreLightColors(const RpGeometry *geometry) { return geometry->colors; }\nRwTexCoords  *RpGeometryGetVertexTexCoords(const RpGeometry *geometry, RwTextureCoordinateIndex uvIndex) {\n\tif(uvIndex == rwNARWTEXTURECOORDINATEINDEX)\n\t\treturn nil;\n\treturn geometry->texCoords[uvIndex-rwTEXTURECOORDINATEINDEX0];\n}\nRwInt32 RpGeometryGetNumTexCoordSets(const RpGeometry *geometry) { return geometry->numTexCoordSets; }\nRwInt32 RpGeometryGetNumVertices (const RpGeometry *geometry) { return geometry->numVertices; }\nRwV3d  *RpMorphTargetGetVertices(const RpMorphTarget *morphTarget) { return morphTarget->vertices; }\nRwV3d  *RpMorphTargetGetVertexNormals(const RpMorphTarget *morphTarget) { return morphTarget->normals; }\nRpTriangle  *RpGeometryGetTriangles(const RpGeometry *geometry) { return geometry->triangles; }\nRwInt32 RpGeometryGetNumTriangles(const RpGeometry *geometry) { return geometry->numTriangles; }\nRpMaterial  *RpGeometryGetMaterial(const RpGeometry *geometry, RwInt32 matNum) { return geometry->matList.materials[matNum]; }\nconst RpGeometry  *RpGeometryTriangleSetVertexIndices(const RpGeometry *geometry, RpTriangle *triangle, RwUInt16 vert1, RwUInt16 vert2, RwUInt16 vert3)\n\t{ triangle->v[0] = vert1; triangle->v[1] = vert2; triangle->v[2] = vert3; return geometry; }\nRpGeometry  *RpGeometryTriangleSetMaterial(RpGeometry *geometry, RpTriangle *triangle, RpMaterial *material) {\n\tint id = geometry->matList.findIndex(material);\n\tif(id < 0)\n\t\tid = geometry->matList.appendMaterial(material);\n\tif(id < 0)\n\t\treturn nil;\n\ttriangle->matId = id;\n\treturn geometry;\n}\nconst RpGeometry  *RpGeometryTriangleGetVertexIndices(const RpGeometry *geometry, const RpTriangle *triangle, RwUInt16 *vert1, RwUInt16 *vert2, RwUInt16 *vert3);\nRpMaterial   *RpGeometryTriangleGetMaterial(const RpGeometry *geometry, const RpTriangle *triangle);\nRwInt32 RpGeometryGetNumMaterials(const RpGeometry *geometry);\nRpGeometry  *RpGeometryForAllMaterials(RpGeometry *geometry, RpMaterialCallBack fpCallBack, void *pData) {\n\tint i;\n\tfor(i = 0; i < geometry->matList.numMaterials; i++)\n\t\tif(fpCallBack(geometry->matList.materials[i], pData) == nil)\n\t\t\tbreak;\n\treturn geometry;\n}\n//const RpGeometry  *RpGeometryForAllMeshes(const RpGeometry *geometry, RpMeshCallBack fpCallBack, void *pData);\nRwInt32 RpGeometryRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor constructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB);\nRwInt32 RpGeometryRegisterPluginStream(RwUInt32 pluginID, RwPluginDataChunkReadCallBack readCB, RwPluginDataChunkWriteCallBack writeCB, RwPluginDataChunkGetSizeCallBack getSizeCB);\nRwInt32 RpGeometrySetStreamAlwaysCallBack(RwUInt32 pluginID, RwPluginDataChunkAlwaysCallBack alwaysCB);\nRwInt32 RpGeometryGetPluginOffset(RwUInt32 pluginID);\nRwBool RpGeometryValidatePlugins(const RpGeometry *geometry);\nRwUInt32 RpGeometryStreamGetSize(const RpGeometry *geometry);\nconst RpGeometry  *RpGeometryStreamWrite(const RpGeometry *geometry, RwStream *stream);\nRpGeometry  *RpGeometryStreamRead(RwStream *stream) { return Geometry::streamRead(stream); }\n//RpGeometryChunkInfo *_rpGeometryChunkInfoRead(RwStream *stream, RpGeometryChunkInfo *geometryChunkInfo, RwInt32 *bytesRead);\nRwUInt32 RpGeometryGetFlags(const RpGeometry *geometry) { return geometry->flags; }\nRpGeometry  *RpGeometrySetFlags(RpGeometry *geometry, RwUInt32 flags) { geometry->flags = flags; return geometry; }\nconst RwSurfaceProperties *_rpGeometryGetSurfaceProperties(const RpGeometry *geometry);\nRpGeometry *_rpGeometrySetSurfaceProperties(RpGeometry *geometry, const RwSurfaceProperties *surfaceProperties);\n\n\n\n\n\nRwFrame *RpClumpGetFrame(const RpClump * clump) { return clump->getFrame(); }\nRpClump *RpClumpSetFrame(RpClump * clump, RwFrame * frame) { clump->setFrame(frame); return clump; }\nRpClump *RpClumpForAllAtomics(RpClump * clump, RpAtomicCallBack callback, void *pData) {\n\tFORLIST(lnk, clump->atomics)\n\t\tif(callback(Atomic::fromClump(lnk), pData) == nil)\n\t\t\tbreak;\n\treturn clump;\n}\nRpClump *RpClumpForAllLights(RpClump * clump, RpLightCallBack callback, void *pData);\nRpClump *RpClumpForAllCameras(RpClump * clump, RwCameraCallBack callback, void *pData);\n//RpClump *RpClumpCreateSpace(const RwV3d * position, RwReal radius);\nRpClump *RpClumpRender(RpClump * clump) { clump->render(); return clump; }\nRpClump *RpClumpRemoveAtomic(RpClump * clump, RpAtomic * atomic) { clump->removeAtomic(atomic); return clump; }\nRpClump *RpClumpAddAtomic(RpClump * clump, RpAtomic * atomic) { clump->addAtomic(atomic); return clump; }\n//RpClump *RpClumpRemoveLight(RpClump * clump, RpLight * light);\n//RpClump *RpClumpAddLight(RpClump * clump, RpLight * light);\n//RpClump *RpClumpRemoveCamera(RpClump * clump, RwCamera * camera);\n//RpClump *RpClumpAddCamera(RpClump * clump, RwCamera * camera);\nRwBool RpClumpDestroy(RpClump * clump) { clump->destroy(); return true; }\nRpClump *RpClumpCreate(void) { return rw::Clump::create(); }\nRpClump *RpClumpClone(RpClump * clump) { return clump->clone(); }\n//RpClump *RpClumpSetCallBack(RpClump * clump, RpClumpCallBack callback);\n//RpClumpCallBack RpClumpGetCallBack(const RpClump * clump);\nRwInt32 RpClumpGetNumAtomics(RpClump * clump) { return clump->countAtomics(); }\n//RwInt32 RpClumpGetNumLights(RpClump * clump);\n//RwInt32 RpClumpGetNumCameras(RpClump * clump);\nRpClump *RpClumpStreamRead(RwStream * stream) { return rw::Clump::streamRead(stream); }\n//RpClump *RpClumpStreamWrite(RpClump * clump, RwStream * stream);\nRwInt32 RpClumpRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor constructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB)\n\t{ return Clump::registerPlugin(size, pluginID, constructCB, destructCB, (CopyConstructor)copyCB); }\nRwInt32 RpClumpRegisterPluginStream(RwUInt32 pluginID, RwPluginDataChunkReadCallBack  readCB, RwPluginDataChunkWriteCallBack writeCB, RwPluginDataChunkGetSizeCallBack getSizeCB)\n\t{ return Clump::registerPluginStream(pluginID, readCB, (StreamWrite)writeCB, (StreamGetSize)getSizeCB); }\n//RwInt32 RpClumpSetStreamAlwaysCallBack(RwUInt32 pluginID, RwPluginDataChunkAlwaysCallBack alwaysCB);\n//RwInt32 RpClumpGetPluginOffset(RwUInt32 pluginID);\n//RwBool RpClumpValidatePlugins(const RpClump * clump);\n\n\n\nRpAtomic *RpAtomicCreate(void) { return rw::Atomic::create(); }\nRwBool RpAtomicDestroy(RpAtomic * atomic) { atomic->destroy(); return true; }\nRpAtomic *RpAtomicClone(RpAtomic * atomic) { return atomic->clone(); }\nRpAtomic *RpAtomicSetFrame(RpAtomic * atomic, RwFrame * frame) { atomic->setFrame(frame); return atomic; }\nRpAtomic *RpAtomicSetGeometry(RpAtomic * atomic, RpGeometry * geometry, RwUInt32 flags) { atomic->setGeometry(geometry, flags); return atomic; }\n\nRwFrame *RpAtomicGetFrame(const RpAtomic * atomic) { return atomic->getFrame(); }\nRpAtomic *RpAtomicSetFlags(RpAtomic * atomic, RwUInt32 flags) { atomic->setFlags(flags); return atomic; }\nRwUInt32 RpAtomicGetFlags(const RpAtomic * atomic) { return atomic->getFlags(); }\nRwSphere *RpAtomicGetBoundingSphere(RpAtomic * atomic) { return &atomic->boundingSphere; }\nRpAtomic *RpAtomicRender(RpAtomic * atomic) { atomic->render(); return atomic; }\nRpClump *RpAtomicGetClump(const RpAtomic * atomic) { return atomic->clump; }\n//RpInterpolator *RpAtomicGetInterpolator(RpAtomic * atomic);\nRpGeometry *RpAtomicGetGeometry(const RpAtomic * atomic) { return atomic->geometry; }\n// WARNING: illegal cast\nvoid RpAtomicSetRenderCallBack(RpAtomic * atomic, RpAtomicCallBackRender callback) { atomic->setRenderCB((Atomic::RenderCB)callback); }\nRpAtomicCallBackRender RpAtomicGetRenderCallBack(const RpAtomic * atomic) { return (RpAtomicCallBackRender)atomic->renderCB; }\n//RwBool RpAtomicInstance(RpAtomic *atomic);\n//RwUInt32 RpAtomicStreamGetSize(RpAtomic * atomic);\n//RpAtomic *RpAtomicStreamRead(RwStream * stream);\n//RpAtomic *RpAtomicStreamWrite(RpAtomic * atomic, RwStream * stream);\nRwInt32 RpAtomicRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor constructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB)\n\t{ return Atomic::registerPlugin(size, pluginID, constructCB, destructCB, (CopyConstructor)copyCB); }\n//RwInt32 RpAtomicRegisterPluginStream(RwUInt32 pluginID, RwPluginDataChunkReadCallBack readCB, RwPluginDataChunkWriteCallBack writeCB, RwPluginDataChunkGetSizeCallBack getSizeCB);\n//RwInt32 RpAtomicSetStreamAlwaysCallBack(RwUInt32 pluginID, RwPluginDataChunkAlwaysCallBack alwaysCB);\n//RwInt32 RpAtomicSetStreamRightsCallBack(RwUInt32 pluginID, RwPluginDataChunkRightsCallBack rightsCB);\n//RwInt32 RpAtomicGetPluginOffset(RwUInt32 pluginID);\n//RwBool RpAtomicValidatePlugins(const RpAtomic * atomic);\n\nRpAtomic *AtomicDefaultRenderCallBack(RpAtomic * atomic) { Atomic::defaultRenderCB(atomic); return atomic; }\n\n\n// TODO: this is extremely simplified\nRpWorld     *RpWorldCreate(RwBBox * boundingBox) { return World::create(); }\nRwBool       RpWorldDestroy(RpWorld * world) { world->destroy(); return true; }\n\nRwBool       RpWorldPluginAttach(void) {\n\tregisterMeshPlugin();\n\tregisterNativeDataPlugin();\n\tregisterAtomicRightsPlugin();\n\tregisterMaterialRightsPlugin();\n\n\t// not sure if this goes here\n\trw::xbox::registerVertexFormatPlugin();\n\treturn true;\n}\n\nRpWorld *RpWorldRemoveCamera(RpWorld *world, RwCamera *camera) { world->removeCamera(camera); return world; }\nRpWorld *RpWorldAddCamera(RpWorld *world, RwCamera *camera) { world->addCamera(camera); return world; }\nRpWorld *RwCameraGetWorld(const RwCamera *camera);\nRpWorld *RpWorldRemoveAtomic(RpWorld *world, RpAtomic *atomic);\nRpWorld *RpWorldAddAtomic(RpWorld *world, RpAtomic *atomic);\nRpWorld *RpAtomicGetWorld(const RpAtomic *atomic);\nRpWorld *RpWorldAddClump(RpWorld *world, RpClump *clump);\nRpWorld *RpWorldRemoveClump(RpWorld *world, RpClump *clump);\nRpWorld *RpClumpGetWorld(const RpClump *clump);\nRpWorld *RpWorldAddLight(RpWorld *world, RpLight *light) { world->addLight(light); return world; }\nRpWorld *RpWorldRemoveLight(RpWorld *world, RpLight *light) { world->removeLight(light); return world; }\nRpWorld *RpLightGetWorld(const RpLight *light);\nRwCamera *RwCameraForAllClumpsInFrustum(RwCamera *camera, void *data);\nRwCamera *RwCameraForAllClumpsNotInFrustum(RwCamera *camera, RwInt32 numClumps, void *data);\n\n\n\n\nRwBool RpMatFXPluginAttach( void ) { registerMatFXPlugin(); return true; }\nRpAtomic *RpMatFXAtomicEnableEffects( RpAtomic *atomic ) { MatFX::enableEffects(atomic); return atomic; }\nRpMatFXMaterialFlags RpMatFXMaterialGetEffects( const RpMaterial *material ){ return (RpMatFXMaterialFlags)MatFX::getEffects(material); }\nRpMaterial *RpMatFXMaterialSetEffects( RpMaterial *material, RpMatFXMaterialFlags flags ) { MatFX::setEffects(material, (uint32)flags); return material; }\nRpMaterial *RpMatFXMaterialSetupEnvMap( RpMaterial *material, RwTexture *texture, RwFrame *frame, RwBool useFrameBufferAlpha, RwReal coef ) {\n\tMatFX *mfx = MatFX::get(material);\n\tmfx->setEnvTexture(texture);\n\tmfx->setEnvFrame(frame);\n\tmfx->setEnvCoefficient(coef);\n\treturn material;\n}\nRpMaterial *RpMatFXMaterialSetEnvMapFrame( RpMaterial *material, RwFrame *frame )\n{\n\tMatFX *mfx = MatFX::get(material);\n\tmfx->setEnvFrame(frame);\n\treturn material;\n}\nRpMaterial *RpMatFXMaterialSetEnvMapFrameBufferAlpha( RpMaterial *material, RwBool useFrameBufferAlpha )\n{\n\tMatFX *mfx = MatFX::get(material);\n\tmfx->setEnvFBAlpha(useFrameBufferAlpha);\n\treturn material;\n}\nRpMaterial *RpMatFXMaterialSetEnvMapCoefficient( RpMaterial *material, RwReal coef )\n{\n\tMatFX *mfx = MatFX::get(material);\n\tmfx->setEnvCoefficient(coef);\n\treturn material;\n}\nRwReal RpMatFXMaterialGetEnvMapCoefficient( const RpMaterial *material )\n{\n\tMatFX *mfx = MatFX::get(material);\n\treturn mfx->getEnvCoefficient();\n}\n\n\n\nRwBool RpHAnimPluginAttach(void) {\n\tregisterHAnimPlugin();\n\treturn true;\n}\n\nRwInt32 RpHAnimFrameGetID(RwFrame *frame) { return HAnimData::get(frame)->id; }\n\nRwInt32 RpHAnimIDGetIndex(RpHAnimHierarchy *hierarchy, RwInt32 ID) { return hierarchy->getIndex(ID); }\n\nRwBool RpHAnimFrameSetHierarchy(RwFrame *frame, RpHAnimHierarchy *hierarchy) { HAnimData::get(frame)->hierarchy = hierarchy; return true; }\nRpHAnimHierarchy *RpHAnimFrameGetHierarchy(RwFrame *frame) { return HAnimHierarchy::get(frame); }\n\nRpHAnimHierarchy *RpHAnimHierarchySetFlags(RpHAnimHierarchy *hierarchy, RpHAnimHierarchyFlag flags) { hierarchy->flags = flags; return hierarchy; }\n\nRwBool RpHAnimHierarchySetCurrentAnim(RpHAnimHierarchy *hierarchy, RpHAnimAnimation *anim) { hierarchy->interpolator->setCurrentAnim(anim); return true; }\nRwBool RpHAnimHierarchyAddAnimTime(RpHAnimHierarchy *hierarchy, RwReal time) { hierarchy->interpolator->addTime(time); return true; }\n\nRwMatrix *RpHAnimHierarchyGetMatrixArray(RpHAnimHierarchy *hierarchy) { return hierarchy->matrices; }\nRwBool RpHAnimHierarchyUpdateMatrices(RpHAnimHierarchy *hierarchy) { hierarchy->updateMatrices(); return true; }\n\nRpHAnimAnimation *RpHAnimAnimationCreate(RwInt32 typeID, RwInt32 numFrames, RwInt32 flags, RwReal duration)\n\t{ return Animation::create(AnimInterpolatorInfo::find(typeID), numFrames, flags, duration); }\nRpHAnimAnimation  *RpHAnimAnimationDestroy(RpHAnimAnimation *animation) { animation->destroy(); return animation; }\nRpHAnimAnimation  *RpHAnimAnimationStreamRead(RwStream *stream) { return Animation::streamRead(stream); }\n\n\n\n\n\n\nRwBool RpSkinPluginAttach(void) {\n\tregisterSkinPlugin();\n\treturn true;\n}\n\nRwUInt32 RpSkinGetNumBones( RpSkin *skin ) { return skin->numBones; }\nconst RwMatrixWeights *RpSkinGetVertexBoneWeights( RpSkin *skin ) { return (RwMatrixWeights*)skin->weights; }\nconst RwUInt32 *RpSkinGetVertexBoneIndices( RpSkin *skin ) { return (RwUInt32*)skin->indices; }\nconst RwMatrix *RpSkinGetSkinToBoneMatrices( RpSkin *skin ) { return (const RwMatrix*)skin->inverseMatrices; }\n\nRpSkin *RpSkinGeometryGetSkin( RpGeometry *geometry ) { return Skin::get(geometry); }\n\nRpAtomic *RpSkinAtomicSetHAnimHierarchy( RpAtomic *atomic, RpHAnimHierarchy *hierarchy ) { Skin::setHierarchy(atomic, hierarchy); return atomic; }\nRpHAnimHierarchy *RpSkinAtomicGetHAnimHierarchy( const RpAtomic *atomic ) { return Skin::getHierarchy(atomic); }\n\nRwImage *\nRtBMPImageWrite(RwImage *image, const RwChar *imageName)\n{\n#ifndef _WIN32\n\tchar *r = casepath(imageName);\n\tif (r) {\n\t\trw::writeBMP(image, r);\n\t\tfree(r);\n\t} else {\n\t\trw::writeBMP(image, imageName);\n\t}\n\t\n#else\n\trw::writeBMP(image, imageName);\n#endif\n\treturn image;\n}\nRwImage *\nRtBMPImageRead(const RwChar *imageName)\n{\n#ifndef _WIN32\n\tRwImage *image;\n\tchar *r = casepath(imageName);\n\tif (r) {\n\t\timage = rw::readBMP(r);\n\t\tfree(r);\n\t} else {\n\t\timage = rw::readBMP(imageName);\n\t}\n\treturn image;\n\n#else\n\treturn rw::readBMP(imageName);\n#endif\n}\n\n\nRwImage *\nRtPNGImageWrite(RwImage *image, const RwChar *imageName)\n{\n#ifndef _WIN32\n\tchar *r = casepath(imageName);\n\tif (r) {\n\t\trw::writePNG(image, r);\n\t\tfree(r);\n\t} else {\n\t\trw::writePNG(image, imageName);\n\t}\n\t\n#else\n\trw::writePNG(image, imageName);\n#endif\n\treturn image;\n}\nRwImage *\nRtPNGImageRead(const RwChar *imageName)\n{\n#ifndef _WIN32\n\tRwImage *image;\n\tchar *r = casepath(imageName);\n\tif (r) {\n\t\timage = rw::readPNG(r);\n\t\tfree(r);\n\t} else {\n\t\timage = rw::readPNG(imageName);\n\t}\n\treturn image;\n\n#else\n\treturn rw::readPNG(imageName);\n#endif\n}\n\n#include \"rtquat.h\"\n\nRtQuat *RtQuatRotate(RtQuat * quat, const RwV3d * axis, RwReal angle, RwOpCombineType combineOp) { return (RtQuat*)((rw::Quat*)quat)->rotate(axis, angle/180.0f*3.14159f, (CombineOp)combineOp); }\nvoid RtQuatConvertToMatrix(const RtQuat * const qpQuat, RwMatrix * const mpMatrix) { mpMatrix->rotate(*(rw::Quat*)qpQuat, COMBINEREPLACE); }\n\n\n#include \"rtcharse.h\"\n\nRwBool       RtCharsetOpen(void) { return Charset::open(); }\nvoid         RtCharsetClose(void) { return Charset::close(); }\nRtCharset   *RtCharsetPrint(RtCharset * charSet, const RwChar * string, RwInt32 x, RwInt32 y) { charSet->print(string, x, y, true); return charSet; }\nRtCharset   *RtCharsetPrintBuffered(RtCharset * charSet, const RwChar * string, RwInt32 x, RwInt32 y, RwBool hideSpaces) { charSet->printBuffered(string, x, y, hideSpaces); return charSet; }\nRwBool       RtCharsetBufferFlush(void) { Charset::flushBuffer(); return true; }\nRtCharset   *RtCharsetSetColors(RtCharset * charSet, const RwRGBA * foreGround, const RwRGBA * backGround) { return charSet->setColors(foreGround, backGround); }\nRtCharset   *RtCharsetGetDesc(RtCharset * charset, RtCharsetDesc * desc) { *desc = charset->desc; return charset; }\nRtCharset   *RtCharsetCreate(const RwRGBA * foreGround, const RwRGBA * backGround) { return Charset::create(foreGround, backGround); }\nRwBool       RtCharsetDestroy(RtCharset * charSet) { charSet->destroy(); return true; }\n\n\n\n#include <rpanisot.h>\n\nRwInt8      RpAnisotGetMaxSupportedMaxAnisotropy(void) { return rw::getMaxSupportedMaxAnisotropy(); }\nRwTexture    *RpAnisotTextureSetMaxAnisotropy(RwTexture *tex, RwInt8 val) { tex->setMaxAnisotropy(val); return tex; }\nRwInt8       RpAnisotTextureGetMaxAnisotropy(RwTexture *tex) { return tex->getMaxAnisotropy(); }\nRwBool       RpAnisotPluginAttach(void) { rw::registerAnisotropyPlugin(); return true; }\n"
  },
  {
    "path": "src/fakerw/rpanisot.h",
    "content": "#pragma once\n\nRwInt8      RpAnisotGetMaxSupportedMaxAnisotropy(void);\nRwTexture    *RpAnisotTextureSetMaxAnisotropy(RwTexture *tex, RwInt8 val);\nRwInt8       RpAnisotTextureGetMaxAnisotropy(RwTexture *tex);\nRwBool       RpAnisotPluginAttach(void);\n"
  },
  {
    "path": "src/fakerw/rphanim.h",
    "content": "#pragma once\n\n#include \"rtquat.h\"\n\n//struct RpHAnimHierarchy;\ntypedef rw::HAnimHierarchy RpHAnimHierarchy;\n//struct RpHAnimAnimation;\ntypedef rw::Animation RpHAnimAnimation;\n\n#define rpHANIMSTDKEYFRAMETYPEID 0x1\n\n// same as rw::HAnimKeyFrame, but we need RtQuat in this one\nstruct RpHAnimStdKeyFrame\n{\n\tRpHAnimStdKeyFrame *prevFrame;\n\tRwReal        time;\n\tRtQuat           q;\n\tRwV3d            t;\n};\n// same story, this one only exists in later RW versions\n// but we need it for 64 bit builds because offset and size differs!\nstruct RpHAnimStdInterpFrame\n{\n\tRpHAnimStdKeyFrame *keyFrame1;\n\tRpHAnimStdKeyFrame *keyFrame2;\n\tRtQuat           q;\n\tRwV3d            t;\n};\n\nenum RpHAnimHierarchyFlag\n{\n\trpHANIMHIERARCHYSUBHIERARCHY =              rw::HAnimHierarchy::SUBHIERARCHY,\n\trpHANIMHIERARCHYNOMATRICES =                rw::HAnimHierarchy::NOMATRICES,\n\n\trpHANIMHIERARCHYUPDATEMODELLINGMATRICES = rw::HAnimHierarchy::UPDATEMODELLINGMATRICES,\n\trpHANIMHIERARCHYUPDATELTMS =              rw::HAnimHierarchy::UPDATELTMS,\n\trpHANIMHIERARCHYLOCALSPACEMATRICES =      rw::HAnimHierarchy::LOCALSPACEMATRICES\n};\n\n#define rpHANIMPOPPARENTMATRIX      rw::HAnimHierarchy::POP\n#define rpHANIMPUSHPARENTMATRIX     rw::HAnimHierarchy::PUSH\n\nRwBool RpHAnimPluginAttach(void);\n\nRwBool RpHAnimFrameSetID(RwFrame *frame, RwInt32 id);\nRwInt32 RpHAnimFrameGetID(RwFrame *frame);\n\nRwInt32 RpHAnimIDGetIndex(RpHAnimHierarchy *hierarchy, RwInt32 ID);\n\nRwBool RpHAnimFrameSetHierarchy(RwFrame *frame, RpHAnimHierarchy *hierarchy);\nRpHAnimHierarchy *RpHAnimFrameGetHierarchy(RwFrame *frame);\n\nRpHAnimHierarchy *RpHAnimHierarchySetFlags(RpHAnimHierarchy *hierarchy, RpHAnimHierarchyFlag flags);\nRpHAnimHierarchyFlag RpHAnimHierarchyGetFlags(RpHAnimHierarchy *hierarchy);\n\nRwBool RpHAnimHierarchySetCurrentAnim(RpHAnimHierarchy *hierarchy, RpHAnimAnimation *anim);\nRwBool RpHAnimHierarchySetCurrentAnimTime(RpHAnimHierarchy *hierarchy, RwReal time);\nRwBool RpHAnimHierarchySubAnimTime(RpHAnimHierarchy *hierarchy, RwReal time);\nRwBool RpHAnimHierarchyAddAnimTime(RpHAnimHierarchy *hierarchy, RwReal time);\n\nRwMatrix *RpHAnimHierarchyGetMatrixArray(RpHAnimHierarchy *hierarchy);\nRwBool RpHAnimHierarchyUpdateMatrices(RpHAnimHierarchy *hierarchy);\n\n#define rpHANIMHIERARCHYGETINTERPFRAME( hierarchy, nodeIndex )    \\\n        ( (void *)( ( (RwUInt8 *)&(hierarchy->interpolator[1]) +                \\\n                      ((nodeIndex) *                               \\\n                       hierarchy->interpolator->currentInterpKeyFrameSize) ) ) )\n\n\nRpHAnimAnimation *RpHAnimAnimationCreate(RwInt32 typeID, RwInt32 numFrames, RwInt32 flags, RwReal duration);\nRpHAnimAnimation  *RpHAnimAnimationDestroy(RpHAnimAnimation *animation);\nRpHAnimAnimation  *RpHAnimAnimationStreamRead(RwStream *stream);\n"
  },
  {
    "path": "src/fakerw/rpmatfx.h",
    "content": "#pragma once\n\nenum RpMatFXMaterialFlags\n{\n\trpMATFXEFFECTNULL       = rw::MatFX::NOTHING,\n\trpMATFXEFFECTBUMPMAP    = rw::MatFX::BUMPMAP,\n\trpMATFXEFFECTENVMAP     = rw::MatFX::ENVMAP,\n\trpMATFXEFFECTBUMPENVMAP = rw::MatFX::BUMPENVMAP,\n\trpMATFXEFFECTDUAL       = rw::MatFX::DUAL,\n\n\trpMATFXEFFECTMAX,\n\trpMATFXNUMEFFECTS       = rpMATFXEFFECTMAX - 1,\n};\n\nRwBool RpMatFXPluginAttach( void );\nRpAtomic *RpMatFXAtomicEnableEffects( RpAtomic *atomic );\nRwBool RpMatFXAtomicQueryEffects( RpAtomic *atomic );\n//RpWorldSector *RpMatFXWorldSectorEnableEffects( RpWorldSector *worldSector );\n//RwBool RpMatFXWorldSectorQueryEffects( RpWorldSector *worldSector );\nRpMaterial *RpMatFXMaterialSetEffects( RpMaterial *material, RpMatFXMaterialFlags flags );\nRpMaterial *RpMatFXMaterialSetupBumpMap( RpMaterial *material, RwTexture *texture, RwFrame *frame, RwReal coef );\nRpMaterial *RpMatFXMaterialSetupEnvMap( RpMaterial *material, RwTexture *texture, RwFrame *frame, RwBool useFrameBufferAlpha, RwReal coef );\nRpMaterial *RpMatFXMaterialSetupDualTexture( RpMaterial *material, RwTexture *texture, RwBlendFunction srcBlendMode, RwBlendFunction dstBlendMode );\nRpMatFXMaterialFlags RpMatFXMaterialGetEffects( const RpMaterial *material );\nRpMaterial *RpMatFXMaterialSetBumpMapTexture( RpMaterial *material, RwTexture *texture );\nRpMaterial *RpMatFXMaterialSetBumpMapFrame( RpMaterial *material, RwFrame *frame );\nRpMaterial *RpMatFXMaterialSetBumpMapCoefficient( RpMaterial *material, RwReal coef );\nRwTexture *RpMatFXMaterialGetBumpMapTexture( const RpMaterial *material );\nRwTexture *RpMatFXMaterialGetBumpMapBumpedTexture( const RpMaterial *material );\nRwFrame *RpMatFXMaterialGetBumpMapFrame( const RpMaterial *material );\nRwReal RpMatFXMaterialGetBumpMapCoefficient( const RpMaterial *material );\nRpMaterial *RpMatFXMaterialSetEnvMapTexture( RpMaterial *material, RwTexture *texture );\nRpMaterial *RpMatFXMaterialSetEnvMapFrame( RpMaterial *material, RwFrame *frame );\nRpMaterial *RpMatFXMaterialSetEnvMapFrameBufferAlpha( RpMaterial *material, RwBool useFrameBufferAlpha );\nRpMaterial *RpMatFXMaterialSetEnvMapCoefficient( RpMaterial *material, RwReal coef );\nRwTexture *RpMatFXMaterialGetEnvMapTexture( const RpMaterial *material );\nRwFrame *RpMatFXMaterialGetEnvMapFrame( const RpMaterial *material );\nRwBool RpMatFXMaterialGetEnvMapFrameBufferAlpha( const RpMaterial *material );\nRwReal RpMatFXMaterialGetEnvMapCoefficient( const RpMaterial *material );\nRpMaterial *RpMatFXMaterialSetDualTexture( RpMaterial *material, RwTexture *texture );\nRpMaterial *RpMatFXMaterialSetDualBlendModes( RpMaterial *material, RwBlendFunction srcBlendMode, RwBlendFunction dstBlendMode );\nRwTexture *RpMatFXMaterialGetDualTexture( const RpMaterial *material );\nconst RpMaterial *RpMatFXMaterialGetDualBlendModes( const RpMaterial *material, RwBlendFunction *srcBlendMode, RwBlendFunction *dstBlendMode );\n"
  },
  {
    "path": "src/fakerw/rpskin.h",
    "content": "#pragma once\n\n#include <rphanim.h>\n\n//struct RpSkin;\ntypedef rw::Skin RpSkin;\n\nstruct RwMatrixWeights\n{\n\tRwReal w0;\n\tRwReal w1;\n\tRwReal w2;\n\tRwReal w3;\n};\n\nRwBool RpSkinPluginAttach(void);\n\nRwUInt32 RpSkinGetNumBones( RpSkin *skin );\nconst RwMatrixWeights *RpSkinGetVertexBoneWeights( RpSkin *skin );\nconst RwUInt32 *RpSkinGetVertexBoneIndices( RpSkin *skin );\nconst RwMatrix *RpSkinGetSkinToBoneMatrices( RpSkin *skin );\n\nRpSkin *RpSkinGeometryGetSkin( RpGeometry *geometry );\n\nRpAtomic *RpSkinAtomicSetHAnimHierarchy( RpAtomic *atomic, RpHAnimHierarchy *hierarchy );\nRpHAnimHierarchy *RpSkinAtomicGetHAnimHierarchy( const RpAtomic *atomic );\n"
  },
  {
    "path": "src/fakerw/rpworld.h",
    "content": "#pragma once\n\n#define rpATOMIC rw::Atomic::ID\n#define rpCLUMP rw::Clump::ID\n\n/*\n ***********************************************\n *\n * RpMaterial\n *\n ***********************************************\n */\n\n//struct RpMaterial;\ntypedef rw::Material RpMaterial;\n\ntypedef RpMaterial *(*RpMaterialCallBack)(RpMaterial *material, void *data);\n\nRpMaterial *RpMaterialCreate(void);\nRwBool RpMaterialDestroy(RpMaterial *material);\nRpMaterial *RpMaterialClone(RpMaterial *material);\nRpMaterial *RpMaterialSetTexture(RpMaterial *material, RwTexture *texture);\nRpMaterial *RpMaterialAddRef(RpMaterial *material);\nRwTexture *RpMaterialGetTexture(const RpMaterial *material);\nRpMaterial *RpMaterialSetColor(RpMaterial *material, const RwRGBA *color);\nconst RwRGBA *RpMaterialGetColor(const RpMaterial *material);\nRpMaterial *RpMaterialSetSurfaceProperties(RpMaterial *material, const RwSurfaceProperties *surfaceProperties);\nconst RwSurfaceProperties *RpMaterialGetSurfaceProperties(const RpMaterial *material);\nRwInt32 RpMaterialRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor constructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB);\nRwInt32 RpMaterialRegisterPluginStream(RwUInt32 pluginID, RwPluginDataChunkReadCallBack readCB, RwPluginDataChunkWriteCallBack writeCB, RwPluginDataChunkGetSizeCallBack getSizeCB);\nRwInt32 RpMaterialSetStreamAlwaysCallBack(RwUInt32 pluginID, RwPluginDataChunkAlwaysCallBack alwaysCB);\nRwInt32 RpMaterialGetPluginOffset(RwUInt32 pluginID);\nRwBool RpMaterialValidatePlugins(const RpMaterial *material);\nRwUInt32 RpMaterialStreamGetSize(const RpMaterial *material);\nRpMaterial *RpMaterialStreamRead(RwStream *stream);\nconst RpMaterial *RpMaterialStreamWrite(const RpMaterial *material, RwStream *stream);\n//RpMaterialChunkInfo *_rpMaterialChunkInfoRead(RwStream *stream,  RpMaterialChunkInfo *materialChunkInfo, RwInt32 *bytesRead);\n\n\n/*\n ***********************************************\n *\n * RpLight\n *\n ***********************************************\n */\n\n//struct RpLight;\ntypedef rw::Light RpLight;\n\nenum RpLightType\n{\n\trpNALIGHTTYPE = 0,\n\trpLIGHTDIRECTIONAL,\n\trpLIGHTAMBIENT,\n\trpLIGHTPOINT = 0x80,\n\trpLIGHTSPOT,\n\trpLIGHTSPOTSOFT,\n};\n\nenum RpLightFlag\n{\n\trpLIGHTLIGHTATOMICS = 0x01,\n\trpLIGHTLIGHTWORLD = 0x02,\n};\n\ntypedef RpLight    *(*RpLightCallBack) (RpLight * light, void *data);\n\nRwReal RpLightGetRadius(const RpLight *light);\nconst RwRGBAReal *RpLightGetColor(const RpLight *light);\nRpLight *RpLightSetFrame(RpLight *light, RwFrame *frame);\nRwFrame *RpLightGetFrame(const RpLight *light);\nRpLightType RpLightGetType(const RpLight *light);\nRpLight *RpLightSetFlags(RpLight *light, RwUInt32 flags);\nRwUInt32 RpLightGetFlags(const RpLight *light);\nRpLight *RpLightCreate(RwInt32 type);\nRwBool RpLightDestroy(RpLight *light);\nRpLight *RpLightSetRadius(RpLight *light, RwReal radius);\nRpLight *RpLightSetColor(RpLight *light, const RwRGBAReal *color);\nRwReal RpLightGetConeAngle(const RpLight *light);\nRpLight *RpLightSetConeAngle(RpLight * ight, RwReal angle);\nRwUInt32 RpLightStreamGetSize(const RpLight *light);\nRpLight *RpLightStreamRead(RwStream *stream);\nconst RpLight *RpLightStreamWrite(const RpLight *light, RwStream *stream);\n//RpLightChunkInfo *_rpLightChunkInfoRead(RwStream *stream, RpLightChunkInfo *lightChunkInfo, RwInt32 *bytesRead);\nRwInt32 RpLightRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor constructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB);\nRwInt32 RpLightRegisterPluginStream(RwUInt32 pluginID, RwPluginDataChunkReadCallBack readCB, RwPluginDataChunkWriteCallBack writeCB, RwPluginDataChunkGetSizeCallBack getSizeCB);\nRwInt32 RpLightSetStreamAlwaysCallBack(RwUInt32 pluginID, RwPluginDataChunkAlwaysCallBack alwaysCB);\nRwInt32 RpLightGetPluginOffset(RwUInt32 pluginID);\nRwBool RpLightValidatePlugins(const RpLight * light);\n\n/*\n ***********************************************\n *\n * RpGeometry\n *\n ***********************************************\n */\n\ntypedef rw::Triangle RpTriangle;\n\n//struct RpGeometry;\ntypedef rw::Geometry RpGeometry;\n//struct RpMorphTarget;\ntypedef rw::MorphTarget RpMorphTarget;\n\nenum RpGeometryFlag\n{\n\trpGEOMETRYTRISTRIP  = rw::Geometry::TRISTRIP,\n\trpGEOMETRYPOSITIONS = rw::Geometry::POSITIONS,\n\trpGEOMETRYTEXTURED  = rw::Geometry::TEXTURED,\n\trpGEOMETRYPRELIT    = rw::Geometry::PRELIT,\n\trpGEOMETRYNORMALS   = rw::Geometry::NORMALS,\n\trpGEOMETRYLIGHT     = rw::Geometry::LIGHT,\n\trpGEOMETRYMODULATEMATERIALCOLOR = rw::Geometry::MODULATE,\n\trpGEOMETRYTEXTURED2 = rw::Geometry::TEXTURED2,\n\trpGEOMETRYNATIVE            = rw::Geometry::NATIVE,\n\trpGEOMETRYNATIVEINSTANCE    = rw::Geometry::NATIVEINSTANCE,\n\trpGEOMETRYFLAGSMASK         = 0x000000FF,\n\trpGEOMETRYNATIVEFLAGSMASK   = 0x0F000000,\n};\n\nenum RpGeometryLockMode\n{\n\trpGEOMETRYLOCKPOLYGONS     = rw::Geometry::LOCKPOLYGONS,\n\trpGEOMETRYLOCKVERTICES     = rw::Geometry::LOCKVERTICES,\n\trpGEOMETRYLOCKNORMALS      = rw::Geometry::LOCKNORMALS,\n\trpGEOMETRYLOCKPRELIGHT     = rw::Geometry::LOCKPRELIGHT,\n\trpGEOMETRYLOCKTEXCOORDS    = rw::Geometry::LOCKTEXCOORDS,\n\trpGEOMETRYLOCKTEXCOORDS1   = rw::Geometry::LOCKTEXCOORDS1,\n\trpGEOMETRYLOCKTEXCOORDS2   = rw::Geometry::LOCKTEXCOORDS2,\n\trpGEOMETRYLOCKTEXCOORDS3   = rw::Geometry::LOCKTEXCOORDS3,\n\trpGEOMETRYLOCKTEXCOORDS4   = rw::Geometry::LOCKTEXCOORDS4,\n\trpGEOMETRYLOCKTEXCOORDS5   = rw::Geometry::LOCKTEXCOORDS5,\n\trpGEOMETRYLOCKTEXCOORDS6   = rw::Geometry::LOCKTEXCOORDS6,\n\trpGEOMETRYLOCKTEXCOORDS7   = rw::Geometry::LOCKTEXCOORDS7,\n\trpGEOMETRYLOCKTEXCOORDS8   = rw::Geometry::LOCKTEXCOORDS8,\n\trpGEOMETRYLOCKTEXCOORDSALL = rw::Geometry::LOCKTEXCOORDSALL,\n\trpGEOMETRYLOCKALL          = rw::Geometry::LOCKALL\n};\n\nRpGeometry  *RpGeometryCreate(RwInt32 numVert, RwInt32 numTriangles, RwUInt32 format);\nRwBool RpGeometryDestroy(RpGeometry *geometry);\nRpGeometry *_rpGeometryAddRef(RpGeometry *geometry);\nRpGeometry  *RpGeometryLock(RpGeometry *geometry, RwInt32 lockMode);\nRpGeometry  *RpGeometryUnlock(RpGeometry *geometry);\nRpGeometry  *RpGeometryTransform(RpGeometry *geometry, const RwMatrix *matrix);\nRpGeometry  *RpGeometryCreateSpace(RwReal radius);\nRpMorphTarget  *RpMorphTargetSetBoundingSphere(RpMorphTarget *morphTarget, const RwSphere *boundingSphere);\nRwSphere  *RpMorphTargetGetBoundingSphere(RpMorphTarget *morphTarget);\nconst RpMorphTarget  *RpMorphTargetCalcBoundingSphere(const RpMorphTarget *morphTarget, RwSphere *boundingSphere);\nRwInt32 RpGeometryAddMorphTargets(RpGeometry *geometry, RwInt32 mtcount);\nRwInt32 RpGeometryAddMorphTarget(RpGeometry *geometry);\nRpGeometry  *RpGeometryRemoveMorphTarget(RpGeometry *geometry, RwInt32 morphTarget);\nRwInt32 RpGeometryGetNumMorphTargets(const RpGeometry *geometry);\nRpMorphTarget  *RpGeometryGetMorphTarget(const RpGeometry *geometry, RwInt32 morphTarget);\nRwRGBA  *RpGeometryGetPreLightColors(const RpGeometry *geometry);\nRwTexCoords  *RpGeometryGetVertexTexCoords(const RpGeometry *geometry, RwTextureCoordinateIndex uvIndex);\nRwInt32 RpGeometryGetNumTexCoordSets(const RpGeometry *geometry);\nRwInt32 RpGeometryGetNumVertices (const RpGeometry *geometry);\nRwV3d  *RpMorphTargetGetVertices(const RpMorphTarget *morphTarget);\nRwV3d  *RpMorphTargetGetVertexNormals(const RpMorphTarget *morphTarget);\nRpTriangle  *RpGeometryGetTriangles(const RpGeometry *geometry);\nRwInt32 RpGeometryGetNumTriangles(const RpGeometry *geometry);\nRpMaterial  *RpGeometryGetMaterial(const RpGeometry *geometry, RwInt32 matNum);\nconst RpGeometry  *RpGeometryTriangleSetVertexIndices(const RpGeometry *geometry, RpTriangle *triangle, RwUInt16 vert1, RwUInt16 vert2, RwUInt16 vert3);\nRpGeometry  *RpGeometryTriangleSetMaterial(RpGeometry *geometry, RpTriangle *triangle, RpMaterial *material);\nconst RpGeometry  *RpGeometryTriangleGetVertexIndices(const RpGeometry *geometry, const RpTriangle *triangle, RwUInt16 *vert1, RwUInt16 *vert2, RwUInt16 *vert3);\nRpMaterial   *RpGeometryTriangleGetMaterial(const RpGeometry *geometry, const RpTriangle *triangle);\nRwInt32 RpGeometryGetNumMaterials(const RpGeometry *geometry);\nRpGeometry  *RpGeometryForAllMaterials(RpGeometry *geometry, RpMaterialCallBack fpCallBack, void *pData);\n//const RpGeometry  *RpGeometryForAllMeshes(const RpGeometry *geometry, RpMeshCallBack fpCallBack, void *pData);\nRwInt32 RpGeometryRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor constructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB);\nRwInt32 RpGeometryRegisterPluginStream(RwUInt32 pluginID, RwPluginDataChunkReadCallBack readCB, RwPluginDataChunkWriteCallBack writeCB, RwPluginDataChunkGetSizeCallBack getSizeCB);\nRwInt32 RpGeometrySetStreamAlwaysCallBack(RwUInt32 pluginID, RwPluginDataChunkAlwaysCallBack alwaysCB);\nRwInt32 RpGeometryGetPluginOffset(RwUInt32 pluginID);\nRwBool RpGeometryValidatePlugins(const RpGeometry *geometry);\nRwUInt32 RpGeometryStreamGetSize(const RpGeometry *geometry);\nconst RpGeometry  *RpGeometryStreamWrite(const RpGeometry *geometry, RwStream *stream);\nRpGeometry  *RpGeometryStreamRead(RwStream *stream);\n//RpGeometryChunkInfo *_rpGeometryChunkInfoRead(RwStream *stream, RpGeometryChunkInfo *geometryChunkInfo, RwInt32 *bytesRead);\nRwUInt32 RpGeometryGetFlags(const RpGeometry *geometry);\nRpGeometry  *RpGeometrySetFlags(RpGeometry *geometry, RwUInt32 flags);\nconst RwSurfaceProperties *_rpGeometryGetSurfaceProperties(const RpGeometry *geometry);\nRpGeometry *_rpGeometrySetSurfaceProperties(RpGeometry *geometry, const RwSurfaceProperties *surfaceProperties);\n\n\n/*\n ***********************************************\n *\n * RpAtomic and RpClump\n *\n ***********************************************\n */\n\n//struct RpAtomic;\ntypedef rw::Atomic RpAtomic;\n\nenum RpAtomicFlag\n{\n\trpATOMICCOLLISIONTEST = 0x01,\n\trpATOMICRENDER = 0x04,\n};\n\nenum RpAtomicSetGeomFlag\n{\n\trpATOMICSAMEBOUNDINGSPHERE = 0x01,\n};\n\ntypedef RpAtomic   *(*RpAtomicCallBack) (RpAtomic * atomic, void *data);\ntypedef RpAtomic   *(*RpAtomicCallBackRender) (RpAtomic * atomic);\n\n\n//struct RpClump;\ntypedef rw::Clump RpClump;\n\nstruct RpClumpChunkInfo\n{\n\tRwInt32             numAtomics;\n\tRwInt32             numLights;\n\tRwInt32             numCameras;\n};\n\ntypedef RpClump    *(*RpClumpCallBack) (RpClump * clump, void *data);\n\n\nRpAtomic *AtomicDefaultRenderCallBack(RpAtomic * atomic);\n//void _rpAtomicResyncInterpolatedSphere(RpAtomic * atomic);\n//const RwSphere *RpAtomicGetWorldBoundingSphere(RpAtomic *  atomic);\n\nRwFrame *RpClumpGetFrame(const RpClump * clump);\nRpClump *RpClumpSetFrame(RpClump * clump, RwFrame * frame);\nRpClump *RpClumpForAllAtomics(RpClump * clump, RpAtomicCallBack callback, void *pData);\nRpClump *RpClumpForAllLights(RpClump * clump, RpLightCallBack callback, void *pData);\nRpClump *RpClumpForAllCameras(RpClump * clump, RwCameraCallBack callback, void *pData);\nRpClump *RpClumpCreateSpace(const RwV3d * position, RwReal radius);\nRpClump *RpClumpRender(RpClump * clump);\nRpClump *RpClumpRemoveAtomic(RpClump * clump, RpAtomic * atomic);\nRpClump *RpClumpAddAtomic(RpClump * clump, RpAtomic * atomic);\nRpClump *RpClumpRemoveLight(RpClump * clump, RpLight * light);\nRpClump *RpClumpAddLight(RpClump * clump, RpLight * light);\nRpClump *RpClumpRemoveCamera(RpClump * clump, RwCamera * camera);\nRpClump *RpClumpAddCamera(RpClump * clump, RwCamera * camera);\nRwBool RpClumpDestroy(RpClump * clump);\nRpClump *RpClumpCreate(void);\nRpClump *RpClumpClone(RpClump * clump);\nRpClump *RpClumpSetCallBack(RpClump * clump, RpClumpCallBack callback);\nRpClumpCallBack RpClumpGetCallBack(const RpClump * clump);\nRwInt32 RpClumpGetNumAtomics(RpClump * clump);\nRwInt32 RpClumpGetNumLights(RpClump * clump);\nRwInt32 RpClumpGetNumCameras(RpClump * clump);\nRwUInt32 RpClumpStreamGetSize(RpClump * clump);\nRpClump *RpClumpStreamRead(RwStream * stream);\nRpClump *RpClumpStreamWrite(RpClump * clump, RwStream * stream);\nRwInt32 RpClumpRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor constructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB);\nRwInt32 RpClumpRegisterPluginStream(RwUInt32 pluginID, RwPluginDataChunkReadCallBack  readCB, RwPluginDataChunkWriteCallBack writeCB, RwPluginDataChunkGetSizeCallBack getSizeCB);\nRwInt32 RpClumpSetStreamAlwaysCallBack(RwUInt32 pluginID, RwPluginDataChunkAlwaysCallBack alwaysCB);\nRwInt32 RpClumpGetPluginOffset(RwUInt32 pluginID);\nRwBool RpClumpValidatePlugins(const RpClump * clump);\n\nRpAtomic *RpAtomicCreate(void);\nRwBool RpAtomicDestroy(RpAtomic * atomic);\nRpAtomic *RpAtomicClone(RpAtomic * atomic);\nRpAtomic *RpAtomicSetFrame(RpAtomic * atomic, RwFrame * frame);\nRpAtomic *RpAtomicSetGeometry(RpAtomic * atomic, RpGeometry * geometry, RwUInt32 flags);\n\nRwFrame *RpAtomicGetFrame(const RpAtomic * atomic);\nRpAtomic *RpAtomicSetFlags(RpAtomic * atomic, RwUInt32 flags);\nRwUInt32 RpAtomicGetFlags(const RpAtomic * atomic);\nRwSphere *RpAtomicGetBoundingSphere(RpAtomic * atomic);\nRpAtomic *RpAtomicRender(RpAtomic * atomic);\nRpClump *RpAtomicGetClump(const RpAtomic * atomic);\n//RpInterpolator *RpAtomicGetInterpolator(RpAtomic * atomic);\nRpGeometry *RpAtomicGetGeometry(const RpAtomic * atomic);\nvoid RpAtomicSetRenderCallBack(RpAtomic * atomic, RpAtomicCallBackRender callback);\nRpAtomicCallBackRender RpAtomicGetRenderCallBack(const RpAtomic * atomic);\nRwBool RpAtomicInstance(RpAtomic *atomic);\nRwUInt32 RpAtomicStreamGetSize(RpAtomic * atomic);\nRpAtomic *RpAtomicStreamRead(RwStream * stream);\nRpAtomic *RpAtomicStreamWrite(RpAtomic * atomic, RwStream * stream);\nRwInt32 RpAtomicRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor constructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB);\nRwInt32 RpAtomicRegisterPluginStream(RwUInt32 pluginID, RwPluginDataChunkReadCallBack readCB, RwPluginDataChunkWriteCallBack writeCB, RwPluginDataChunkGetSizeCallBack getSizeCB);\nRwInt32 RpAtomicSetStreamAlwaysCallBack(RwUInt32 pluginID, RwPluginDataChunkAlwaysCallBack alwaysCB);\nRwInt32 RpAtomicSetStreamRightsCallBack(RwUInt32 pluginID, RwPluginDataChunkRightsCallBack rightsCB);\nRwInt32 RpAtomicGetPluginOffset(RwUInt32 pluginID);\nRwBool RpAtomicValidatePlugins(const RpAtomic * atomic);\n\n//RwInt32 RpInterpolatorGetEndMorphTarget(const RpInterpolator * interpolator);\n//RwInt32 RpInterpolatorGetStartMorphTarget(const RpInterpolator * interpolator);\n//RwReal RpInterpolatorGetValue(const RpInterpolator * interpolator);\n//RwReal RpInterpolatorGetScale(const RpInterpolator * interpolator);\n//RpInterpolator *RpInterpolatorSetEndMorphTarget(RpInterpolator * interpolator, RwInt32 morphTarget, RpAtomic * atomic);\n//RpInterpolator *RpInterpolatorSetStartMorphTarget(RpInterpolator * interpolator, RwInt32 morphTarget, RpAtomic * atomic);\n//RpInterpolator *RpInterpolatorSetValue(RpInterpolator *  interpolator, RwReal value, RpAtomic *atomic);\n//RpInterpolator *RpInterpolatorSetScale(RpInterpolator * interpolator, RwReal scale, RpAtomic *atomic);\n\n\nRpClump *RpLightGetClump(const RpLight *light);\nRpClump *RwCameraGetClump(const RwCamera *camera);\n\n/*\n ***********************************************\n *\n * RpWorld\n *\n ***********************************************\n */\n\n//struct RpWorld;\ntypedef rw::World RpWorld;\n\nRwBool       RpWorldDestroy(RpWorld * world);\nRpWorld     *RpWorldCreate(RwBBox * boundingBox);\n\nRwBool       RpWorldPluginAttach(void);\n\nRpWorld *RpWorldRemoveCamera(RpWorld *world, RwCamera *camera);\nRpWorld *RpWorldAddCamera(RpWorld *world, RwCamera *camera);\nRpWorld *RwCameraGetWorld(const RwCamera *camera);\nRpWorld *RpWorldRemoveAtomic(RpWorld *world, RpAtomic *atomic);\nRpWorld *RpWorldAddAtomic(RpWorld *world, RpAtomic *atomic);\nRpWorld *RpAtomicGetWorld(const RpAtomic *atomic);\nRpWorld *RpWorldAddClump(RpWorld *world, RpClump *clump);\nRpWorld *RpWorldRemoveClump(RpWorld *world, RpClump *clump);\nRpWorld *RpClumpGetWorld(const RpClump *clump);\nRpWorld *RpWorldAddLight(RpWorld *world, RpLight *light);\nRpWorld *RpWorldRemoveLight(RpWorld *world, RpLight *light);\nRpWorld *RpLightGetWorld(const RpLight *light);\nRwCamera *RwCameraForAllClumpsInFrustum(RwCamera *camera, void *data);\nRwCamera *RwCameraForAllClumpsNotInFrustum(RwCamera *camera, RwInt32 numClumps, void *data);\n//RwCamera *RwCameraForAllSectorsInFrustum(RwCamera *camera, RpWorldSectorCallBack callBack, void *pData);\n//RpLight *RpLightForAllWorldSectors(RpLight *light, RpWorldSectorCallBack callback, void *data);\n//RpAtomic *RpAtomicForAllWorldSectors(RpAtomic *atomic, RpWorldSectorCallBack callback, void *data);\n//RpWorldSector *RpWorldSectorForAllAtomics(RpWorldSector *sector, RpAtomicCallBack callback, void *data);\n//RpWorldSector *RpWorldSectorForAllCollisionAtomics(RpWorldSector *sector, RpAtomicCallBack callback, void *data);\n//RpWorldSector *RpWorldSectorForAllLights(RpWorldSector *sector, RpLightCallBack callback, void *data);\n"
  },
  {
    "path": "src/fakerw/rtbmp.h",
    "content": "#pragma once\n\nRwImage *RtBMPImageWrite(RwImage * image, const RwChar * imageName);\nRwImage *RtBMPImageRead(const RwChar * imageName);\n"
  },
  {
    "path": "src/fakerw/rtcharse.h",
    "content": "#pragma once\n\ntypedef rw::Charset RtCharset;\ntypedef rw::Charset::Desc RtCharsetDesc;\n\nRwBool       RtCharsetOpen(void);\nvoid         RtCharsetClose(void);\nRtCharset   *RtCharsetPrint(RtCharset * charSet, const RwChar * string, RwInt32 x, RwInt32 y);\nRtCharset   *RtCharsetPrintBuffered(RtCharset * charSet, const RwChar * string, RwInt32 x, RwInt32 y, RwBool hideSpaces);\nRwBool       RtCharsetBufferFlush(void);\nRtCharset   *RtCharsetSetColors(RtCharset * charSet, const RwRGBA * foreGround, const RwRGBA * backGround);\nRtCharset   *RtCharsetGetDesc(RtCharset * charset, RtCharsetDesc * desc);\nRtCharset   *RtCharsetCreate(const RwRGBA * foreGround, const RwRGBA * backGround);\nRwBool       RtCharsetDestroy(RtCharset * charSet);\n"
  },
  {
    "path": "src/fakerw/rtpng.h",
    "content": "#pragma once\n\nRwImage *RtPNGImageWrite(RwImage * image, const RwChar * imageName);\nRwImage *RtPNGImageRead(const RwChar * imageName);\n"
  },
  {
    "path": "src/fakerw/rtquat.h",
    "content": "#pragma once\n\n// Same layout as rw::Quat but with ugly imag,real separation which i don't want in librw\nstruct RtQuat\n{\n\trw::V3d imag;\n\trw::float32 real;\n};\n\nRwBool RtQuatConvertFromMatrix(RtQuat * const qpQuat, const RwMatrix * const mpMatrix);\nRtQuat *RtQuatRotate(RtQuat * quat, const RwV3d * axis, RwReal angle, RwOpCombineType combineOp);\nconst RtQuat *RtQuatQueryRotate(const RtQuat *quat, RwV3d * unitAxis, RwReal * angle);\nRwV3d *RtQuatTransformVectors(RwV3d * vectorsOut, const RwV3d * vectorsIn, const RwInt32 numPoints, const RtQuat *quat);\n\nvoid RtQuatConvertToMatrix(const RtQuat * const qpQuat, RwMatrix * const mpMatrix);\n"
  },
  {
    "path": "src/fakerw/rwcore.h",
    "content": "#pragma once\n\n#define RWCORE_H\t// needed by CVector\n\n#include <rw.h>\n\n#include <rwplcore.h>\n\n/*\n ***********************************************\n *\n * RwIm2D and RwIm3D\n *\n ***********************************************\n */\n\ntypedef rw::RWDEVICE::Im2DVertex RwIm2DVertex;\ntypedef rw::RWDEVICE::Im3DVertex RwIm3DVertex;\ntypedef RwUInt16 RwImVertexIndex;\n\nenum RwIm3DTransformFlags\n{\n\trwIM3D_VERTEXUV      = rw::im3d::VERTEXUV,\n\trwIM3D_ALLOPAQUE     = rw::im3d::ALLOPAQUE,\n\trwIM3D_NOCLIP        = rw::im3d::NOCLIP,\n\trwIM3D_VERTEXXYZ     = rw::im3d::VERTEXXYZ,\n\trwIM3D_VERTEXRGBA    = rw::im3d::VERTEXRGBA,\n};\n\nvoid RwIm2DVertexSetCameraX(RwIm2DVertex *vert, RwReal camx);\nvoid RwIm2DVertexSetCameraY(RwIm2DVertex *vert, RwReal camy);\nvoid RwIm2DVertexSetCameraZ(RwIm2DVertex *vert, RwReal camz);\nvoid RwIm2DVertexSetRecipCameraZ(RwIm2DVertex *vert, RwReal recipz);\nvoid RwIm2DVertexSetScreenX(RwIm2DVertex *vert, RwReal scrnx);\nvoid RwIm2DVertexSetScreenY(RwIm2DVertex *vert, RwReal scrny);\nvoid RwIm2DVertexSetScreenZ(RwIm2DVertex *vert, RwReal scrnz);\nvoid RwIm2DVertexSetU(RwIm2DVertex *vert, RwReal texU, RwReal recipz);\nvoid RwIm2DVertexSetV(RwIm2DVertex *vert, RwReal texV, RwReal recipz);\nvoid RwIm2DVertexSetIntRGBA(RwIm2DVertex *vert, RwUInt8 red, RwUInt8 green, RwUInt8 blue, RwUInt8 alpha);\n\nRwReal RwIm2DGetNearScreenZ(void);\nRwReal RwIm2DGetFarScreenZ(void);\nRwBool RwIm2DRenderLine(RwIm2DVertex *vertices, RwInt32 numVertices, RwInt32 vert1, RwInt32 vert2);\nRwBool RwIm2DRenderTriangle(RwIm2DVertex *vertices, RwInt32 numVertices, RwInt32 vert1, RwInt32 vert2, RwInt32 vert3 );\nRwBool RwIm2DRenderPrimitive(RwPrimitiveType primType, RwIm2DVertex *vertices, RwInt32 numVertices);\nRwBool RwIm2DRenderIndexedPrimitive(RwPrimitiveType primType, RwIm2DVertex *vertices, RwInt32 numVertices, RwImVertexIndex *indices, RwInt32 numIndices);\n\n\nvoid RwIm3DVertexSetPos(RwIm3DVertex *vert, RwReal x, RwReal y, RwReal z);\nvoid RwIm3DVertexSetU(RwIm3DVertex *vert, RwReal u);\nvoid RwIm3DVertexSetV(RwIm3DVertex *vert, RwReal v);\nvoid RwIm3DVertexSetRGBA(RwIm3DVertex *vert, RwUInt8 r, RwUInt8 g, RwUInt8 b, RwUInt8 a);\n\nvoid  *RwIm3DTransform(RwIm3DVertex *pVerts, RwUInt32 numVerts, RwMatrix *ltm, RwUInt32 flags);\nRwBool RwIm3DEnd(void);\nRwBool RwIm3DRenderLine(RwInt32 vert1, RwInt32 vert2);\nRwBool RwIm3DRenderTriangle(RwInt32 vert1, RwInt32 vert2, RwInt32 vert3);\nRwBool RwIm3DRenderIndexedPrimitive(RwPrimitiveType primType, RwImVertexIndex *indices, RwInt32 numIndices);\nRwBool RwIm3DRenderPrimitive(RwPrimitiveType primType);\n\n\n/*\n ***********************************************\n *\n * RwRaster\n *\n ***********************************************\n */\n\n//struct RwRaster;\ntypedef rw::Raster RwRaster;\n\nenum RwRasterType\n{\n\trwRASTERTYPENORMAL = rw::Raster::NORMAL,\n\trwRASTERTYPEZBUFFER = rw::Raster::ZBUFFER,\n\trwRASTERTYPECAMERA = rw::Raster::CAMERA,\n\trwRASTERTYPETEXTURE = rw::Raster::TEXTURE,\n\trwRASTERTYPECAMERATEXTURE = rw::Raster::CAMERATEXTURE,\n\trwRASTERTYPEMASK = 0x07,\n\trwRASTERDONTALLOCATE = rw::Raster::DONTALLOCATE,\n};\n\nenum RwRasterFormat\n{\n\trwRASTERFORMATDEFAULT = rw::Raster::DEFAULT,\n\trwRASTERFORMAT1555 = rw::Raster::C1555,\n\trwRASTERFORMAT565 = rw::Raster::C565,\n\trwRASTERFORMAT4444 = rw::Raster::C4444,\n\trwRASTERFORMATLUM8 = rw::Raster::LUM8,\n\trwRASTERFORMAT8888 = rw::Raster::C8888,\n\trwRASTERFORMAT888 = rw::Raster::C888,\n\trwRASTERFORMAT16 = rw::Raster::D16,\n\trwRASTERFORMAT24 = rw::Raster::D24,\n\trwRASTERFORMAT32 = rw::Raster::D32,\n\trwRASTERFORMAT555 = rw::Raster::C555,\n\n\trwRASTERFORMATAUTOMIPMAP = rw::Raster::AUTOMIPMAP,\n\trwRASTERFORMATPAL8 = rw::Raster::PAL8,\n\trwRASTERFORMATPAL4 = rw::Raster::PAL4,\n\trwRASTERFORMATMIPMAP = rw::Raster::MIPMAP,\n\n\trwRASTERFORMATPIXELFORMATMASK = 0x0f00,\n\trwRASTERFORMATMASK = 0xff00\n};\n\nenum RwRasterFlipMode\n{\n\trwRASTERFLIPDONTWAIT = 0,\n\trwRASTERFLIPWAITVSYNC = 1,\n};\n\nRwRaster    *RwRasterCreate(RwInt32 width, RwInt32 height, RwInt32 depth, RwInt32 flags);\nRwBool       RwRasterDestroy(RwRaster * raster);\nRwInt32      RwRasterGetWidth(const RwRaster *raster);\nRwInt32      RwRasterGetHeight(const RwRaster *raster);\nRwInt32      RwRasterGetStride(const RwRaster *raster);\nRwInt32      RwRasterGetDepth(const RwRaster *raster);\nRwInt32      RwRasterGetFormat(const RwRaster *raster);\nRwInt32      RwRasterGetType(const RwRaster *raster);\nRwRaster    *RwRasterGetParent(const RwRaster *raster);\nRwRaster    *RwRasterGetOffset(RwRaster *raster,  RwInt16 *xOffset, RwInt16 *yOffset);\nRwInt32      RwRasterGetNumLevels(RwRaster * raster);\nRwRaster    *RwRasterSubRaster(RwRaster * subRaster, RwRaster * raster, RwRect * rect);\nRwRaster    *RwRasterRenderFast(RwRaster * raster, RwInt32 x, RwInt32 y);\nRwRaster    *RwRasterRender(RwRaster * raster, RwInt32 x, RwInt32 y);\nRwRaster    *RwRasterRenderScaled(RwRaster * raster, RwRect * rect);\nRwRaster    *RwRasterPushContext(RwRaster * raster);\nRwRaster    *RwRasterPopContext(void);\nRwRaster    *RwRasterGetCurrentContext(void);\nRwBool       RwRasterClear(RwInt32 pixelValue);\nRwBool       RwRasterClearRect(RwRect * rpRect, RwInt32 pixelValue);\nRwRaster    *RwRasterShowRaster(RwRaster * raster, void *dev, RwUInt32 flags);\nRwUInt8     *RwRasterLock(RwRaster * raster, RwUInt8 level, RwInt32 lockMode);\nRwRaster    *RwRasterUnlock(RwRaster * raster);\nRwUInt8     *RwRasterLockPalette(RwRaster * raster, RwInt32 lockMode);\nRwRaster    *RwRasterUnlockPalette(RwRaster * raster);\nRwInt32      RwRasterRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor constructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB);\nRwInt32      RwRasterGetPluginOffset(RwUInt32 pluginID);\nRwBool       RwRasterValidatePlugins(const RwRaster * raster);\n\n\n/*\n ***********************************************\n *\n * RwImage\n *\n ***********************************************\n */\n\n//struct RwImage;\ntypedef rw::Image RwImage;\n\nRwImage     *RwImageCreate(RwInt32 width, RwInt32 height, RwInt32 depth);\nRwBool       RwImageDestroy(RwImage * image);\nRwImage     *RwImageAllocatePixels(RwImage * image);\nRwImage     *RwImageFreePixels(RwImage * image);\nRwImage     *RwImageCopy(RwImage * destImage, const RwImage * sourceImage);\nRwImage     *RwImageResize(RwImage * image, RwInt32 width, RwInt32 height);\nRwImage     *RwImageApplyMask(RwImage * image, const RwImage * mask);\nRwImage     *RwImageMakeMask(RwImage * image);\nRwImage     *RwImageReadMaskedImage(const RwChar * imageName, const RwChar * maskname);\nRwImage     *RwImageRead(const RwChar * imageName);\nRwImage     *RwImageWrite(RwImage * image, const RwChar * imageName);\nRwChar      *RwImageGetPath(void);\nconst RwChar *RwImageSetPath(const RwChar * path);\nRwImage     *RwImageSetStride(RwImage * image, RwInt32 stride);\nRwImage     *RwImageSetPixels(RwImage * image, RwUInt8 * pixels);\nRwImage     *RwImageSetPalette(RwImage * image, RwRGBA * palette);\nRwInt32      RwImageGetWidth(const RwImage * image);\nRwInt32      RwImageGetHeight(const RwImage * image);\nRwInt32      RwImageGetDepth(const RwImage * image);\nRwInt32      RwImageGetStride(const RwImage * image);\nRwUInt8     *RwImageGetPixels(const RwImage * image);\nRwRGBA      *RwImageGetPalette(const RwImage * image);\nRwUInt32     RwRGBAToPixel(RwRGBA * rgbIn, RwInt32 rasterFormat);\nRwRGBA      *RwRGBASetFromPixel(RwRGBA * rgbOut, RwUInt32 pixelValue, RwInt32 rasterFormat);\nRwBool       RwImageSetGamma(RwReal gammaValue);\nRwReal       RwImageGetGamma(void);\nRwImage     *RwImageGammaCorrect(RwImage * image);\nRwRGBA      *RwRGBAGammaCorrect(RwRGBA * rgb);\nRwInt32      RwImageRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor constructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB);\nRwInt32      RwImageGetPluginOffset(RwUInt32 pluginID);\nRwBool       RwImageValidatePlugins(const RwImage * image);\n//RwBool       RwImageRegisterImageFormat(const RwChar * extension, RwImageCallBackRead imageRead, RwImageCallBackWrite imageWrite);\nconst RwChar *RwImageFindFileType(const RwChar * imageName);\nRwInt32      RwImageStreamGetSize(const RwImage * image);\nRwImage     *RwImageStreamRead(RwStream * stream);\nconst RwImage *RwImageStreamWrite(const RwImage * image, RwStream * stream);\n\n\n/*\n ***********************************************\n *\n * RwTexture\n *\n ***********************************************\n */\n\n//struct RwTexture;\ntypedef rw::Texture RwTexture;\n//struct RwTexDictionary;\ntypedef rw::TexDictionary RwTexDictionary;\n\ntypedef RwTexture *(*RwTextureCallBackRead)(const RwChar *name, const RwChar *maskName);\ntypedef RwTexture *(*RwTextureCallBack)(RwTexture *texture, void *pData);\ntypedef RwTexDictionary *(*RwTexDictionaryCallBack)(RwTexDictionary *dict, void *data);\ntypedef RwRaster *(*RwTextureCallBackMipmapGeneration)(RwRaster * raster, RwImage * image);\ntypedef RwBool (*RwTextureCallBackMipmapName)(RwChar *name, RwChar *maskName, RwUInt8 mipLevel, RwInt32 format);\n\nRwTexture *RwTextureCreate(RwRaster * raster);\nRwBool RwTextureDestroy(RwTexture * texture);\nRwTexture *RwTextureAddRef(RwTexture *texture);\nRwBool RwTextureSetMipmapping(RwBool enable);\nRwBool RwTextureGetMipmapping(void);\nRwBool RwTextureSetAutoMipmapping(RwBool enable);\nRwBool RwTextureGetAutoMipmapping(void);\nRwBool RwTextureSetMipmapGenerationCallBack(RwTextureCallBackMipmapGeneration callback);\nRwTextureCallBackMipmapGeneration RwTextureGetMipmapGenerationCallBack(void);\nRwBool RwTextureSetMipmapNameCallBack(RwTextureCallBackMipmapName callback);\nRwTextureCallBackMipmapName RwTextureGetMipmapNameCallBack(void);\nRwBool RwTextureGenerateMipmapName(RwChar * name, RwChar * maskName, RwUInt8 mipLevel, RwInt32 format);\nRwBool RwTextureRasterGenerateMipmaps(RwRaster * raster, RwImage * image);\nRwTextureCallBackRead RwTextureGetReadCallBack(void);\nRwBool RwTextureSetReadCallBack(RwTextureCallBackRead fpCallBack);\nRwTexture *RwTextureSetName(RwTexture * texture, const RwChar * name);\nRwTexture *RwTextureSetMaskName(RwTexture * texture, const RwChar * maskName);\nRwChar *RwTextureGetName(RwTexture *texture);\nRwChar *RwTextureGetMaskName(RwTexture *texture);\nRwTexture *RwTextureSetRaster(RwTexture * texture, RwRaster * raster);\nRwTexture   *RwTextureRead(const RwChar * name, const RwChar * maskName);\nRwRaster *RwTextureGetRaster(const RwTexture *texture);\nRwInt32 RwTextureRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor constructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB);\nRwInt32 RwTextureGetPluginOffset(RwUInt32 pluginID);\nRwBool RwTextureValidatePlugins(const RwTexture * texture);\n\nRwTexDictionary *RwTextureGetDictionary(RwTexture *texture);\nRwTexture *RwTextureSetFilterMode(RwTexture *texture, RwTextureFilterMode filtering);\nRwTextureFilterMode RwTextureGetFilterMode(const RwTexture *texture);\nRwTexture *RwTextureSetAddressing(RwTexture *texture, RwTextureAddressMode addressing);\nRwTexture *RwTextureSetAddressingU(RwTexture *texture, RwTextureAddressMode addressing);\nRwTexture *RwTextureSetAddressingV(RwTexture *texture, RwTextureAddressMode addressing);\nRwTextureAddressMode RwTextureGetAddressing(const RwTexture *texture);\nRwTextureAddressMode RwTextureGetAddressingU(const RwTexture *texture);\nRwTextureAddressMode RwTextureGetAddressingV(const RwTexture *texture);\n\nvoid _rwD3D8TexDictionaryEnableRasterFormatConversion(bool enable);\n\n// hack for reading native textures\nRwBool rwNativeTextureHackRead(RwStream *stream, RwTexture **tex, RwInt32 size);\n\n\nRwTexDictionary *RwTexDictionaryCreate(void);\nRwBool RwTexDictionaryDestroy(RwTexDictionary * dict);\nRwTexture *RwTexDictionaryAddTexture(RwTexDictionary * dict, RwTexture * texture);\nRwTexture *RwTexDictionaryRemoveTexture(RwTexture * texture);\nRwTexture *RwTexDictionaryFindNamedTexture(RwTexDictionary * dict, const RwChar * name);\nRwTexDictionary *RwTexDictionaryGetCurrent(void);\nRwTexDictionary *RwTexDictionarySetCurrent(RwTexDictionary * dict);\nconst RwTexDictionary *RwTexDictionaryForAllTextures(const RwTexDictionary * dict, RwTextureCallBack fpCallBack, void *pData);\nRwBool RwTexDictionaryForAllTexDictionaries(RwTexDictionaryCallBack fpCallBack, void *pData);\nRwInt32 RwTexDictionaryRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor constructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB);\nRwInt32 RwTexDictionaryGetPluginOffset(RwUInt32 pluginID);\nRwBool RwTexDictionaryValidatePlugins(const RwTexDictionary * dict);\nRwUInt32 RwTexDictionaryStreamGetSize(const RwTexDictionary *texDict);\nRwTexDictionary *RwTexDictionaryStreamRead(RwStream *stream);\nconst RwTexDictionary *RwTexDictionaryStreamWrite(const RwTexDictionary *texDict, RwStream *stream);\n\n/* RwImage/RwRaster */\n\nRwImage *RwImageSetFromRaster(RwImage *image, RwRaster *raster);\nRwRaster *RwRasterSetFromImage(RwRaster *raster, RwImage *image);\nRwRGBA *RwRGBAGetRasterPixel(RwRGBA *rgbOut, RwRaster *raster, RwInt32 x, RwInt32 y);\nRwRaster *RwRasterRead(const RwChar *filename);\nRwRaster *RwRasterReadMaskedRaster(const RwChar *filename, const RwChar *maskname);\nRwImage *RwImageFindRasterFormat(RwImage *ipImage,RwInt32 nRasterType, RwInt32 *npWidth,RwInt32 *npHeight, RwInt32 *npDepth,RwInt32 *npFormat);\n\n\n/*\n ***********************************************\n *\n * RwFrame\n *\n ***********************************************\n */\n\n//struct RwFrame;\ntypedef rw::Frame RwFrame;\n\ntypedef RwFrame *(*RwFrameCallBack)(RwFrame *frame, void *data);\n\n\nRwFrame *RwFrameForAllObjects(RwFrame * frame, RwObjectCallBack callBack, void *data);\nRwFrame *RwFrameTranslate(RwFrame * frame, const RwV3d * v, RwOpCombineType combine);\nRwFrame *RwFrameRotate(RwFrame * frame, const RwV3d * axis, RwReal angle, RwOpCombineType combine);\nRwFrame *RwFrameScale(RwFrame * frame, const RwV3d * v, RwOpCombineType combine);\nRwFrame *RwFrameTransform(RwFrame * frame, const RwMatrix * m, RwOpCombineType combine);\nRwFrame *RwFrameOrthoNormalize(RwFrame * frame);\nRwFrame *RwFrameSetIdentity(RwFrame * frame);\nRwFrame *RwFrameCloneHierarchy(RwFrame * root);\nRwBool RwFrameDestroyHierarchy(RwFrame * frame);\nRwFrame *RwFrameForAllChildren(RwFrame * frame, RwFrameCallBack callBack, void *data);\nRwFrame *RwFrameRemoveChild(RwFrame * child);\nRwFrame *RwFrameAddChild(RwFrame * parent, RwFrame * child);\nRwFrame *RwFrameGetParent(const RwFrame * frame);\nRwFrame *RwFrameGetRoot(const RwFrame * frame);\nRwMatrix *RwFrameGetLTM(RwFrame * frame);\nRwMatrix *RwFrameGetMatrix(RwFrame * frame);\nRwFrame *RwFrameUpdateObjects(RwFrame * frame);\nRwFrame *RwFrameCreate(void);\nRwBool RwFrameInit(RwFrame *frame);\nRwBool RwFrameDeInit(RwFrame *frame);\nRwBool RwFrameDestroy(RwFrame * frame);\nvoid _rwFrameInit(RwFrame *frame);\nvoid _rwFrameDeInit(RwFrame *frame);\nRwBool RwFrameDirty(const RwFrame * frame);\nRwInt32 RwFrameCount(RwFrame * frame);\nRwBool RwFrameSetStaticPluginsSize(RwInt32 size);\nRwInt32 RwFrameRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor constructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB);\nRwInt32 RwFrameGetPluginOffset(RwUInt32 pluginID);\nRwBool RwFrameValidatePlugins(const RwFrame * frame);\nRwFrame *_rwFrameCloneAndLinkClones(RwFrame * root);\nRwFrame *_rwFramePurgeClone(RwFrame *root);\n\nRwInt32 RwFrameRegisterPluginStream(RwUInt32 pluginID, RwPluginDataChunkReadCallBack readCB, RwPluginDataChunkWriteCallBack writeCB, RwPluginDataChunkGetSizeCallBack getSizeCB);\nRwInt32 RwFrameSetStreamAlwaysCallBack(RwUInt32 pluginID, RwPluginDataChunkAlwaysCallBack alwaysCB);\n\ntypedef rw::FrameList_ rwFrameList;\nrwFrameList *rwFrameListInitialize(rwFrameList *frameList, RwFrame *frame);\nRwBool  rwFrameListFindFrame(const rwFrameList *frameList, const RwFrame *frame, RwInt32 *npIndex);\nrwFrameList *rwFrameListDeinitialize(rwFrameList *frameList);\nRwUInt32 rwFrameListStreamGetSize(const rwFrameList *frameList);\nrwFrameList *rwFrameListStreamRead(RwStream *stream, rwFrameList *fl);\nconst rwFrameList *rwFrameListStreamWrite(const rwFrameList *frameList, RwStream *stream);\n\n\ntypedef rw::BBox RwBBox;\n\n/*\n ***********************************************\n *\n * RwCamera\n *\n ***********************************************\n */\n\n//struct RwCamera;\ntypedef rw::Camera RwCamera;\n\ntypedef RwCamera *(*RwCameraCallBack)(RwCamera *camera, void *data);\n\nenum RwCameraClearMode\n{\n\trwCAMERACLEARIMAGE = 0x1,\n\trwCAMERACLEARZ = 0x2,\n\trwCAMERACLEARSTENCIL = 0x4\n};\n\nenum RwCameraProjection\n{\n\trwNACAMERAPROJECTION = 0,\n\trwPERSPECTIVE = 1,\n\trwPARALLEL = 2\n};\n\nenum RwFrustumTestResult\n{\n\trwSPHEREOUTSIDE = 0,\n\trwSPHEREBOUNDARY = 1,\n\trwSPHEREINSIDE = 2\n};\n\nRwCamera    *RwCameraBeginUpdate(RwCamera * camera);\nRwCamera    *RwCameraEndUpdate(RwCamera * camera);\nRwCamera    *RwCameraClear(RwCamera * camera, RwRGBA * colour, RwInt32 clearMode);\nRwCamera    *RwCameraShowRaster(RwCamera * camera, void *pDev, RwUInt32 flags);\nRwBool       RwCameraDestroy(RwCamera * camera);\nRwCamera    *RwCameraCreate(void);\nRwCamera    *RwCameraClone(RwCamera * camera);\nRwCamera    *RwCameraSetViewOffset(RwCamera *camera, const RwV2d *offset);\nRwCamera    *RwCameraSetViewWindow(RwCamera *camera, const RwV2d *viewWindow);\nRwCamera    *RwCameraSetProjection(RwCamera *camera, RwCameraProjection projection);\nRwCamera    *RwCameraSetNearClipPlane(RwCamera *camera, RwReal nearClip);\nRwCamera    *RwCameraSetFarClipPlane(RwCamera *camera, RwReal farClip);\nRwInt32      RwCameraRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor constructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB);\nRwInt32      RwCameraGetPluginOffset(RwUInt32 pluginID);\nRwBool       RwCameraValidatePlugins(const RwCamera * camera);\nRwFrustumTestResult RwCameraFrustumTestSphere(const RwCamera * camera, const RwSphere * sphere);\nconst RwV2d *RwCameraGetViewOffset(const RwCamera *camera);\nRwCamera    *RwCameraSetRaster(RwCamera *camera, RwRaster *raster);\nRwRaster    *RwCameraGetRaster(const RwCamera *camera);\nRwCamera    *RwCameraSetZRaster(RwCamera *camera, RwRaster *zRaster);\nRwRaster    *RwCameraGetZRaster(const RwCamera *camera);\nRwReal       RwCameraGetNearClipPlane(const RwCamera *camera);\nRwReal       RwCameraGetFarClipPlane(const RwCamera *camera);\nRwCamera    *RwCameraSetFogDistance(RwCamera *camera, RwReal fogDistance);\nRwReal       RwCameraGetFogDistance(const RwCamera *camera);\nRwCamera    *RwCameraGetCurrentCamera(void);\nRwCameraProjection RwCameraGetProjection(const RwCamera *camera);\nconst RwV2d *RwCameraGetViewWindow(const RwCamera *camera);\nRwMatrix    *RwCameraGetViewMatrix(RwCamera *camera);\nRwCamera    *RwCameraSetFrame(RwCamera *camera, RwFrame *frame);\nRwFrame     *RwCameraGetFrame(const RwCamera *camera);\n\n\n/*\n *\n * D3D-engine specific stuff\n *\n */\n\nvoid RwD3D8EngineSetRefreshRate(RwUInt32 refreshRate);\nRwBool RwD3D8DeviceSupportsDXTTexture(void);\nvoid RwD3D8EngineSetMultiSamplingLevels(RwUInt32 level);\nRwUInt32 RwD3D8EngineGetMaxMultiSamplingLevels(void);\n"
  },
  {
    "path": "src/fakerw/rwplcore.h",
    "content": "#pragma once\n\ntypedef rw::int8 RwInt8;\ntypedef rw::int16 RwInt16;\ntypedef rw::int32 RwInt32;\ntypedef rw::uint8 RwUInt8;\ntypedef rw::uint16 RwUInt16;\ntypedef rw::uint32 RwUInt32;\ntypedef rw::float32 RwReal;\n\ntypedef char RwChar;\ntypedef RwInt32 RwBool;\n\n#define __RWUNUSED__\n\n#ifndef FALSE\n#define FALSE 0\n#endif\n\n#ifndef TRUE\n#define TRUE !FALSE\n#endif\n\n// used for unicode\n#define RWSTRING(x) x\n\ntypedef rw::V2d RwV2d;\n\ntypedef rw::V3d RwV3d;\n\ntypedef rw::Rect RwRect;\n\ntypedef rw::Sphere RwSphere;\n\nenum RwTextureCoordinateIndex\n{\n\trwNARWTEXTURECOORDINATEINDEX = 0,\n\trwTEXTURECOORDINATEINDEX0,\n\trwTEXTURECOORDINATEINDEX1,\n\trwTEXTURECOORDINATEINDEX2,\n\trwTEXTURECOORDINATEINDEX3,\n\trwTEXTURECOORDINATEINDEX4,\n\trwTEXTURECOORDINATEINDEX5,\n\trwTEXTURECOORDINATEINDEX6,\n\trwTEXTURECOORDINATEINDEX7,\n};\n\ntypedef rw::TexCoords RwTexCoords;\n\ntypedef rw::SurfaceProperties RwSurfaceProperties;\n\n#define RWRGBALONG(r,g,b,a)                                             \\\n    ((RwUInt32) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b)))\n\n\n#define MAKECHUNKID(vendorID, chunkID) (((vendorID & 0xFFFFFF) << 8) | (chunkID & 0xFF))\n\nenum RwCorePluginID\n{\n\trwID_NAOBJECT               = 0x00,\n\trwID_STRUCT                 = 0x01,\n\trwID_STRING                 = 0x02,\n\trwID_EXTENSION              = 0x03,\n\trwID_CAMERA                 = 0x05,\n\trwID_TEXTURE                = 0x06,\n\trwID_MATERIAL               = 0x07,\n\trwID_MATLIST                = 0x08,\n\trwID_ATOMICSECT             = 0x09,\n\trwID_PLANESECT              = 0x0A,\n\trwID_WORLD                  = 0x0B,\n\trwID_SPLINE                 = 0x0C,\n\trwID_MATRIX                 = 0x0D,\n\trwID_FRAMELIST              = 0x0E,\n\trwID_GEOMETRY               = 0x0F,\n\trwID_CLUMP                  = 0x10,\n\trwID_LIGHT                  = 0x12,\n\trwID_UNICODESTRING          = 0x13,\n\trwID_ATOMIC                 = 0x14,\n\trwID_TEXTURENATIVE          = 0x15,\n\trwID_TEXDICTIONARY          = 0x16,\n\trwID_ANIMDATABASE           = 0x17,\n\trwID_IMAGE                  = 0x18,\n\trwID_SKINANIMATION          = 0x19,\n\trwID_GEOMETRYLIST           = 0x1A,\n\trwID_HANIMANIMATION         = 0x1B,\n\trwID_TEAM                   = 0x1C,\n\trwID_CROWD                  = 0x1D,\n\trwID_DMORPHANIMATION        = 0x1E,\n\trwID_RIGHTTORENDER          = 0x1f,\n\trwID_MTEFFECTNATIVE         = 0x20,\n\trwID_MTEFFECTDICT           = 0x21,\n\trwID_TEAMDICTIONARY         = 0x22,\n\trwID_PITEXDICTIONARY        = 0x23,\n\trwID_TOC                    = 0x24,\n\trwID_PRTSTDGLOBALDATA       = 0x25,\n\t/* Insert before MAX and increment MAX */\n\trwID_COREPLUGINIDMAX        = 0x26,\n};\n\n\n/*\n ***********************************************\n *\n * RwObject\n *\n ***********************************************\n */\n\n//struct RwObject;\ntypedef rw::Object RwObject;\ntypedef rw::Frame RwFrame;\n\ntypedef RwObject *(*RwObjectCallBack)(RwObject *object, void *data);\n\nRwUInt8 RwObjectGetType(const RwObject *obj);\nRwFrame* rwObjectGetParent(const RwObject *obj);\n\n#define rwsprintf   sprintf\n#define rwvsprintf  vsprintf\n#define rwstrcpy    strcpy\n#define rwstrncpy   strncpy\n#define rwstrcat    strcat\n#define rwstrncat   strncat\n#define rwstrrchr   strrchr\n#define rwstrchr    strchr\n#define rwstrstr    strstr\n#define rwstrcmp    strcmp\n#define rwstricmp   stricmp\n#define rwstrlen    strlen\n#define rwstrupr    strupr\n#define rwstrlwr    strlwr\n#define rwstrtok    strtok\n#define rwsscanf    sscanf\n\n\n/*\n ***********************************************\n *\n * Memory\n *\n ***********************************************\n */\n\nstruct RwMemoryFunctions\n{\n\t// NB: from RW 3.6 on the allocating functions take\n\t// a hint parameter!\n\tvoid *(*rwmalloc)(size_t size);\n\tvoid  (*rwfree)(void *mem);\n\tvoid *(*rwrealloc)(void *mem, size_t newSize);\n\tvoid *(*rwcalloc)(size_t numObj, size_t sizeObj);\n};\n\nvoid *RwMalloc(size_t size);\nvoid  RwFree(void *mem);\nvoid *RwRealloc(void *mem, size_t newSize);\nvoid *RwCalloc(size_t numObj, size_t sizeObj);\n\n/*\n ***********************************************\n *\n * RwStream\n *\n ***********************************************\n */\n\n//struct RwStream;\ntypedef rw::Stream RwStream;\n\nstruct RwMemory\n{\n\tRwUInt8     *start;\n\tRwUInt32    length;\n};\n\nenum RwStreamType\n{\n\trwNASTREAM = 0,\n\trwSTREAMFILE,\n\trwSTREAMFILENAME,\n\trwSTREAMMEMORY,\n\trwSTREAMCUSTOM\n};\n\nenum RwStreamAccessType\n{\n\trwNASTREAMACCESS = 0,\n\trwSTREAMREAD,\n\trwSTREAMWRITE,\n\trwSTREAMAPPEND\n};\n\nRwStream *RwStreamOpen(RwStreamType type, RwStreamAccessType accessType, const void *pData);\nRwBool RwStreamClose(RwStream * stream, void *pData);\nRwUInt32 RwStreamRead(RwStream * stream, void *buffer, RwUInt32 length);\nRwStream *RwStreamWrite(RwStream * stream, const void *buffer, RwUInt32 length);\nRwStream *RwStreamSkip(RwStream * stream, RwUInt32 offset);\n\n\n/*\n ***********************************************\n *\n * Plugin Registry \n *\n ***********************************************\n */\n\n#define RWPLUGINOFFSET(_type, _base, _offset)                   \\\n   ((_type *)((RwUInt8 *)(_base) + (_offset)))\n\ntypedef RwStream *(*RwPluginDataChunkWriteCallBack)(RwStream *stream, RwInt32 binaryLength, const void *object, RwInt32 offsetInObject, RwInt32 sizeInObject);\ntypedef RwStream *(*RwPluginDataChunkReadCallBack)(RwStream *stream, RwInt32 binaryLength, void *object, RwInt32 offsetInObject, RwInt32 sizeInObject);\ntypedef RwInt32(*RwPluginDataChunkGetSizeCallBack)(const void *object, RwInt32 offsetInObject, RwInt32 sizeInObject);\ntypedef RwBool(*RwPluginDataChunkAlwaysCallBack)(void *object, RwInt32 offsetInObject, RwInt32 sizeInObject);\ntypedef RwBool(*RwPluginDataChunkRightsCallBack)(void *object, RwInt32 offsetInObject, RwInt32 sizeInObject, RwUInt32 extraData);\ntypedef void *(*RwPluginObjectConstructor)(void *object, RwInt32 offsetInObject, RwInt32 sizeInObject);\ntypedef void *(*RwPluginObjectCopy)(void *dstObject, const void *srcObject, RwInt32 offsetInObject, RwInt32 sizeInObject);\ntypedef void *(*RwPluginObjectDestructor)(void *object, RwInt32 offsetInObject, RwInt32 sizeInObject);\n\n/*\n ***********************************************\n *\n * RwMatrix\n *\n ***********************************************\n */\n\ntypedef rw::Matrix RwMatrix;\n\nenum RwOpCombineType\n{\n\trwCOMBINEREPLACE = rw::COMBINEREPLACE,\n\trwCOMBINEPRECONCAT = rw::COMBINEPRECONCAT,\n\trwCOMBINEPOSTCONCAT = rw::COMBINEPOSTCONCAT\n};\n\nenum RwMatrixType\n{\n\trwMATRIXTYPENORMAL = rw::Matrix::TYPENORMAL,\n\trwMATRIXTYPEORTHOGANAL = rw::Matrix::TYPEORTHOGONAL,\n\trwMATRIXTYPEORTHONORMAL = rw::Matrix::TYPEORTHONORMAL,\n\trwMATRIXTYPEMASK = 0x00000003,\n};\n\ntypedef rw::Matrix::Tolerance RwMatrixTolerance;\n\nRwBool RwMatrixDestroy(RwMatrix *mpMat);\nRwMatrix *RwMatrixCreate(void);\nvoid RwMatrixCopy(RwMatrix * dstMatrix, const RwMatrix * srcMatrix);\nvoid RwMatrixSetIdentity(RwMatrix * matrix);\nRwMatrix *RwMatrixMultiply(RwMatrix * matrixOut, const RwMatrix * MatrixIn1, const RwMatrix * matrixIn2);\nRwMatrix *RwMatrixTransform(RwMatrix * matrix, const RwMatrix * transform, RwOpCombineType combineOp);\nRwMatrix *RwMatrixOrthoNormalize(RwMatrix * matrixOut, const RwMatrix * matrixIn);\nRwMatrix *RwMatrixInvert(RwMatrix * matrixOut, const RwMatrix * matrixIn);\nRwMatrix *RwMatrixScale(RwMatrix * matrix, const RwV3d * scale, RwOpCombineType combineOp);\nRwMatrix *RwMatrixTranslate(RwMatrix * matrix, const RwV3d * translation, RwOpCombineType combineOp);\nRwMatrix *RwMatrixRotate(RwMatrix * matrix, const RwV3d * axis, RwReal angle, RwOpCombineType combineOp);\nRwMatrix *RwMatrixRotateOneMinusCosineSine(RwMatrix * matrix, const RwV3d * unitAxis, RwReal oneMinusCosine, RwReal sine, RwOpCombineType combineOp);\nconst RwMatrix *RwMatrixQueryRotate(const RwMatrix * matrix, RwV3d * unitAxis, RwReal * angle, RwV3d * center);\nRwV3d *RwMatrixGetRight(RwMatrix * matrix);\nRwV3d *RwMatrixGetUp(RwMatrix * matrix);\nRwV3d *RwMatrixGetAt(RwMatrix * matrix);\nRwV3d *RwMatrixGetPos(RwMatrix * matrix);\nRwMatrix *RwMatrixUpdate(RwMatrix * matrix);\nRwMatrix *RwMatrixOptimize(RwMatrix * matrix, const RwMatrixTolerance *tolerance);\n\n/*\n ***********************************************\n *\n * RwRGBA\n *\n ***********************************************\n */\n\ntypedef rw::RGBA RwRGBA;\ntypedef rw::RGBAf RwRGBAReal;\n\n\ninline void RwRGBAAssign(RwRGBA *target, const RwRGBA *source) { *target = *source; }\n\n\nRwReal RwV3dNormalize(RwV3d * out, const RwV3d * in);\nRwReal RwV3dLength(const RwV3d * in);\nRwReal RwV2dLength(const RwV2d * in);\nRwReal RwV2dNormalize(RwV2d * out, const RwV2d * in);\nvoid RwV2dAssign(RwV2d * out, const RwV2d * ina);\nvoid RwV2dAdd(RwV2d * out, const RwV2d * ina, const RwV2d * inb);\nvoid RwV2dLineNormal(RwV2d * out, const RwV2d * ina, const RwV2d * inb);\nvoid RwV2dSub(RwV2d * out, const RwV2d * ina, const RwV2d * inb);\nvoid RwV2dPerp(RwV2d * out, const RwV2d * in);\nvoid RwV2dScale(RwV2d * out, const RwV2d * in, RwReal scalar);\nRwReal RwV2dDotProduct(const RwV2d * ina, const RwV2d * inb);\nvoid RwV3dAssign(RwV3d * out, const RwV3d * ina);\nvoid RwV3dAdd(RwV3d * out, const RwV3d * ina, const RwV3d * inb);\nvoid RwV3dSub(RwV3d * out, const RwV3d * ina, const RwV3d * inb);\nvoid RwV3dScale(RwV3d * out, const RwV3d * in, RwReal scalar);\nvoid RwV3dIncrementScaled(RwV3d * out,  const RwV3d * in, RwReal scalar);\nvoid RwV3dNegate(RwV3d * out, const RwV3d * in);\nRwReal RwV3dDotProduct(const RwV3d * ina, const RwV3d * inb);\nvoid RwV3dCrossProduct(RwV3d * out, const RwV3d * ina, const RwV3d * inb);\nRwV3d *RwV3dTransformPoints(RwV3d * pointsOut, const RwV3d * pointsIn, RwInt32 numPoints, const RwMatrix * matrix);\nRwV3d *RwV3dTransformVectors(RwV3d * vectorsOut, const RwV3d * vectorsIn, RwInt32 numPoints, const RwMatrix * matrix);\n\n\n/*\n ***********************************************\n *\n * Render States\n *\n ***********************************************\n */\n\n// not librw because we don't support all of them (yet?) - mapping in wrapper functions\nenum RwRenderState\n{\n\trwRENDERSTATENARENDERSTATE = 0,\n\trwRENDERSTATETEXTURERASTER,\n\trwRENDERSTATETEXTUREADDRESS,\n\trwRENDERSTATETEXTUREADDRESSU,\n\trwRENDERSTATETEXTUREADDRESSV,\n\trwRENDERSTATETEXTUREPERSPECTIVE,\n\trwRENDERSTATEZTESTENABLE,\n\trwRENDERSTATESHADEMODE,\n\trwRENDERSTATEZWRITEENABLE,\n\trwRENDERSTATETEXTUREFILTER,\n\trwRENDERSTATESRCBLEND,\n\trwRENDERSTATEDESTBLEND,\n\trwRENDERSTATEVERTEXALPHAENABLE,\n\trwRENDERSTATEBORDERCOLOR,\n\trwRENDERSTATEFOGENABLE,\n\trwRENDERSTATEFOGCOLOR,\n\trwRENDERSTATEFOGTYPE,\n\trwRENDERSTATEFOGDENSITY,\n\trwRENDERSTATEFOGTABLE,\n\trwRENDERSTATEALPHAPRIMITIVEBUFFER,\n\trwRENDERSTATECULLMODE,\n\trwRENDERSTATESTENCILENABLE,\n\trwRENDERSTATESTENCILFAIL,\n\trwRENDERSTATESTENCILZFAIL,\n\trwRENDERSTATESTENCILPASS,\n\trwRENDERSTATESTENCILFUNCTION,\n\trwRENDERSTATESTENCILFUNCTIONREF,\n\trwRENDERSTATESTENCILFUNCTIONMASK,\n\trwRENDERSTATESTENCILFUNCTIONWRITEMASK\n};\n\n// not supported - we only do gouraud\nenum RwShadeMode\n{\n\trwSHADEMODENASHADEMODE = 0,\n\trwSHADEMODEFLAT,\n\trwSHADEMODEGOURAUD\n};\n\nenum RwBlendFunction\n{\n\trwBLENDNABLEND = 0,\n\trwBLENDZERO = rw::BLENDZERO,\n\trwBLENDONE = rw::BLENDONE,\n\trwBLENDSRCCOLOR = rw::BLENDSRCCOLOR,\n\trwBLENDINVSRCCOLOR = rw::BLENDINVSRCCOLOR,\n\trwBLENDSRCALPHA = rw::BLENDSRCALPHA,\n\trwBLENDINVSRCALPHA = rw::BLENDINVSRCALPHA,\n\trwBLENDDESTALPHA = rw::BLENDDESTALPHA,\n\trwBLENDINVDESTALPHA = rw::BLENDINVDESTALPHA,\n\trwBLENDDESTCOLOR = rw::BLENDDESTCOLOR,\n\trwBLENDINVDESTCOLOR = rw::BLENDINVDESTCOLOR,\n\trwBLENDSRCALPHASAT = rw::BLENDSRCALPHASAT\n};\n\n// unsupported - we only need linear\nenum RwFogType\n{\n\trwFOGTYPENAFOGTYPE = 0,\n\trwFOGTYPELINEAR,\n\trwFOGTYPEEXPONENTIAL,\n\trwFOGTYPEEXPONENTIAL2\n};\n\nenum RwTextureFilterMode\n{\n\trwFILTERNAFILTERMODE = 0,\n\trwFILTERNEAREST = rw::Texture::NEAREST,\n\trwFILTERLINEAR = rw::Texture::LINEAR,\n\trwFILTERMIPNEAREST = rw::Texture::MIPNEAREST,\n\trwFILTERMIPLINEAR = rw::Texture::MIPLINEAR,\n\trwFILTERLINEARMIPNEAREST = rw::Texture::LINEARMIPNEAREST,\n\trwFILTERLINEARMIPLINEAR = rw::Texture::LINEARMIPLINEAR\n};\n\nenum RwTextureAddressMode\n{\n\trwTEXTUREADDRESSNATEXTUREADDRESS = 0,\n\trwTEXTUREADDRESSWRAP = rw::Texture::WRAP,\n\trwTEXTUREADDRESSMIRROR = rw::Texture::MIRROR,\n\trwTEXTUREADDRESSCLAMP = rw::Texture::CLAMP,\n\trwTEXTUREADDRESSBORDER = rw::Texture::BORDER\n};\n\nenum RwCullMode\n{\n\trwCULLMODENACULLMODE = 0,\n\trwCULLMODECULLNONE = rw::CULLNONE,\n\trwCULLMODECULLBACK = rw::CULLBACK,\n\trwCULLMODECULLFRONT = rw::CULLFRONT\n};\n\nenum RwPrimitiveType\n{\n\trwPRIMTYPENAPRIMTYPE = rw::PRIMTYPENONE,\n\trwPRIMTYPELINELIST = rw::PRIMTYPELINELIST,\n\trwPRIMTYPEPOLYLINE = rw::PRIMTYPEPOLYLINE,\n\trwPRIMTYPETRILIST = rw::PRIMTYPETRILIST,\n\trwPRIMTYPETRISTRIP = rw::PRIMTYPETRISTRIP,\n\trwPRIMTYPETRIFAN = rw::PRIMTYPETRIFAN,\n\trwPRIMTYPEPOINTLIST = rw::PRIMTYPEPOINTLIST\n};\n\n\nRwBool RwRenderStateGet(RwRenderState state, void *value);\nRwBool RwRenderStateSet(RwRenderState state, void *value);\n\n\n/*\n ***********************************************\n *\n * Engine\n *\n ***********************************************\n */\n\nstruct RwEngineOpenParams\n{\n\tvoid    *displayID;\n};\n\ntypedef rw::SubSystemInfo RwSubSystemInfo;\n\nenum RwVideoModeFlag\n{\n\trwVIDEOMODEEXCLUSIVE  = rw::VIDEOMODEEXCLUSIVE,\n/*\n\trwVIDEOMODEINTERLACE  = 0x2,\n\trwVIDEOMODEFFINTERLACE  = 0x4,\n\trwVIDEOMODEFSAA0 = 0x8,\n\trwVIDEOMODEFSAA1 = 0x10\n*/\n};\n\ntypedef rw::VideoMode RwVideoMode;\n\n#if 0\nstruct RwFileFunctions\n{\n\trwFnFexist  rwfexist; /**< Pointer to fexist function */\n\trwFnFopen   rwfopen;  /**< Pointer to fopen function */\n\trwFnFclose  rwfclose; /**< Pointer to fclose function */\n\trwFnFread   rwfread;  /**< Pointer to fread function */\n\trwFnFwrite  rwfwrite; /**< Pointer to fwrite function */\n\trwFnFgets   rwfgets;  /**< Pointer to fgets function */\n\trwFnFputs   rwfputs;  /**< Pointer to puts function */\n\trwFnFeof    rwfeof;   /**< Pointer to feof function */\n\trwFnFseek   rwfseek;  /**< Pointer to fseek function */\n\trwFnFflush  rwfflush; /**< Pointer to fflush function */\n\trwFnFtell   rwftell;  /**< Pointer to ftell function */  \n};\nRwFileFunctions *RwOsGetFileInterface(void);\n#endif\n\nRwBool RwEngineInit(RwMemoryFunctions *memFuncs, RwUInt32 initFlags, RwUInt32 resArenaSize);\nRwInt32 RwEngineRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor initCB, RwPluginObjectDestructor termCB);\nRwInt32 RwEngineGetPluginOffset(RwUInt32 pluginID);\nRwBool RwEngineOpen(RwEngineOpenParams *initParams);\nRwBool RwEngineStart(void);\nRwBool RwEngineStop(void);\nRwBool RwEngineClose(void);\nRwBool RwEngineTerm(void);\nRwInt32 RwEngineGetNumSubSystems(void);\nRwSubSystemInfo *RwEngineGetSubSystemInfo(RwSubSystemInfo *subSystemInfo, RwInt32 subSystemIndex);\nRwInt32 RwEngineGetCurrentSubSystem(void);\nRwBool RwEngineSetSubSystem(RwInt32 subSystemIndex);\nRwInt32 RwEngineGetNumVideoModes(void);\nRwVideoMode *RwEngineGetVideoModeInfo(RwVideoMode *modeinfo, RwInt32 modeIndex);\nRwInt32 RwEngineGetCurrentVideoMode(void);\nRwBool RwEngineSetVideoMode(RwInt32 modeIndex);\nRwInt32 RwEngineGetTextureMemorySize(void);\nRwInt32 RwEngineGetMaxTextureSize(void);\n\n\n/*\n ***********************************************\n *\n * Binary stream\n *\n ***********************************************\n */\n\nRwBool RwStreamFindChunk(RwStream *stream, RwUInt32 type, RwUInt32 *lengthOut, RwUInt32 *versionOut);\n"
  },
  {
    "path": "src/math/Matrix.cpp",
    "content": "#include \"common.h\"\n\nCMatrix::CMatrix(void)\n{\n\tm_attachment = nil;\n\tm_hasRwMatrix = false;\n}\n\nCMatrix::CMatrix(CMatrix const &m)\n{\n\tm_attachment = nil;\n\tm_hasRwMatrix = false;\n\t*this = m;\n}\n\nCMatrix::CMatrix(RwMatrix *matrix, bool owner)\n{\n\tm_attachment = nil;\n\tAttach(matrix, owner);\n}\n\nCMatrix::~CMatrix(void)\n{\n\tif (m_hasRwMatrix && m_attachment)\n\t\tRwMatrixDestroy(m_attachment);\n}\n\nvoid\nCMatrix::Attach(RwMatrix *matrix, bool owner)\n{\n#ifdef FIX_BUGS\n\tif (m_attachment && m_hasRwMatrix)\n#else\n\tif (m_hasRwMatrix && m_attachment)\n#endif\n\t\tRwMatrixDestroy(m_attachment);\n\tm_attachment = matrix;\n\tm_hasRwMatrix = owner;\n\tUpdate();\n}\n\nvoid\nCMatrix::AttachRW(RwMatrix *matrix, bool owner)\n{\n\tif (m_hasRwMatrix && m_attachment)\n\t\tRwMatrixDestroy(m_attachment);\n\tm_attachment = matrix;\n\tm_hasRwMatrix = owner;\n\tUpdateRW();\n}\n\nvoid\nCMatrix::Detach(void)\n{\n\tif (m_hasRwMatrix && m_attachment)\n\t\tRwMatrixDestroy(m_attachment);\n\tm_attachment = nil;\n}\n\nvoid\nCMatrix::Update(void)\n{\n\tGetRight() = m_attachment->right;\n\tGetForward() = m_attachment->up;\n\tGetUp() = m_attachment->at;\n\tGetPosition() = m_attachment->pos;\n}\n\nvoid\nCMatrix::UpdateRW(void)\n{\n\tif (m_attachment) {\n\t\tm_attachment->right = GetRight();\n\t\tm_attachment->up = GetForward();\n\t\tm_attachment->at = GetUp();\n\t\tm_attachment->pos = GetPosition();\n\t\tRwMatrixUpdate(m_attachment);\n\t}\n}\n\nvoid\nCMatrix::operator=(CMatrix const &rhs)\n{\n\tmemcpy(this, &rhs, sizeof(f));\n\tif (m_attachment)\n\t\tUpdateRW();\n}\n\nvoid\nCMatrix::CopyOnlyMatrix(const CMatrix &other)\n{\n\tmemcpy(this, &other, sizeof(f));\n}\n\nCMatrix &\nCMatrix::operator+=(CMatrix const &rhs)\n{\n\tGetRight() += rhs.GetRight();\n\tGetForward() += rhs.GetForward();\n\tGetUp() += rhs.GetUp();\n\tGetPosition() += rhs.GetPosition();\n\treturn *this;\n}\n\nvoid\nCMatrix::SetUnity(void)\n{\n\trx = 1.0f;\n\try = 0.0f;\n\trz = 0.0f;\n\tfx = 0.0f;\n\tfy = 1.0f;\n\tfz = 0.0f;\n\tux = 0.0f;\n\tuy = 0.0f;\n\tuz = 1.0f;\n\tpx = 0.0f;\n\tpy = 0.0f;\n\tpz = 0.0f;\n}\n\nvoid\nCMatrix::ResetOrientation(void)\n{\n\trx = 1.0f;\n\try = 0.0f;\n\trz = 0.0f;\n\tfx = 0.0f;\n\tfy = 1.0f;\n\tfz = 0.0f;\n\tux = 0.0f;\n\tuy = 0.0f;\n\tuz = 1.0f;\n}\n\nvoid\nCMatrix::SetScale(float s)\n{\n\trx = s;\n\try = 0.0f;\n\trz = 0.0f;\n\n\tfx = 0.0f;\n\tfy = s;\n\tfz = 0.0f;\n\n\tux = 0.0f;\n\tuy = 0.0f;\n\tuz = s;\n\n\tpx = 0.0f;\n\tpy = 0.0f;\n\tpz = 0.0f;\n}\n\nvoid\nCMatrix::SetTranslate(float x, float y, float z)\n{\n\trx = 1.0f;\n\try = 0.0f;\n\trz = 0.0f;\n\n\tfx = 0.0f;\n\tfy = 1.0f;\n\tfz = 0.0f;\n\n\tux = 0.0f;\n\tuy = 0.0f;\n\tuz = 1.0f;\n\n\tpx = x;\n\tpy = y;\n\tpz = z;\n}\n\nvoid\nCMatrix::SetRotateXOnly(float angle)\n{\n\tfloat c = Cos(angle);\n\tfloat s = Sin(angle);\n\n\trx = 1.0f;\n\try = 0.0f;\n\trz = 0.0f;\n\n\tfx = 0.0f;\n\tfy = c;\n\tfz = s;\n\n\tux = 0.0f;\n\tuy = -s;\n\tuz = c;\n}\n\nvoid\nCMatrix::SetRotateYOnly(float angle)\n{\n\tfloat c = Cos(angle);\n\tfloat s = Sin(angle);\n\n\trx = c;\n\try = 0.0f;\n\trz = -s;\n\n\tfx = 0.0f;\n\tfy = 1.0f;\n\tfz = 0.0f;\n\n\tux = s;\n\tuy = 0.0f;\n\tuz = c;\n}\n\nvoid\nCMatrix::SetRotateZOnly(float angle)\n{\n\tfloat c = Cos(angle);\n\tfloat s = Sin(angle);\n\n\trx = c;\n\try = s;\n\trz = 0.0f;\n\n\tfx = -s;\n\tfy = c;\n\tfz = 0.0f;\n\n\tux = 0.0f;\n\tuy = 0.0f;\n\tuz = 1.0f;\n}\n\nvoid\nCMatrix::SetRotateX(float angle)\n{\n\tSetRotateXOnly(angle);\n\tpx = 0.0f;\n\tpy = 0.0f;\n\tpz = 0.0f;\n}\n\n\nvoid\nCMatrix::SetRotateY(float angle)\n{\n\tSetRotateYOnly(angle);\n\tpx = 0.0f;\n\tpy = 0.0f;\n\tpz = 0.0f;\n}\n\nvoid\nCMatrix::SetRotateZ(float angle)\n{\n\tSetRotateZOnly(angle);\n\tpx = 0.0f;\n\tpy = 0.0f;\n\tpz = 0.0f;\n}\n\nvoid\nCMatrix::SetRotate(float xAngle, float yAngle, float zAngle)\n{\n\tfloat cX = Cos(xAngle);\n\tfloat sX = Sin(xAngle);\n\tfloat cY = Cos(yAngle);\n\tfloat sY = Sin(yAngle);\n\tfloat cZ = Cos(zAngle);\n\tfloat sZ = Sin(zAngle);\n\n\trx = cZ * cY - (sZ * sX) * sY;\n\try = (cZ * sX) * sY + sZ * cY;\n\trz = -cX * sY;\n\n\tfx = -sZ * cX;\n\tfy = cZ * cX;\n\tfz = sX;\n\n\tux = (sZ * sX) * cY + cZ * sY;\n\tuy = sZ * sY - (cZ * sX) * cY;\n\tuz = cX * cY;\n\n\tpx = 0.0f;\n\tpy = 0.0f;\n\tpz = 0.0f;\n}\n\nvoid\nCMatrix::RotateX(float x)\n{\n\tfloat c = Cos(x);\n\tfloat s = Sin(x);\n\n\tfloat ry = this->ry;\n\tfloat rz = this->rz;\n\tfloat uy = this->fy;\n\tfloat uz = this->fz;\n\tfloat ay = this->uy;\n\tfloat az = this->uz;\n\tfloat py = this->py;\n\tfloat pz = this->pz;\n\n\tthis->ry = c * ry - s * rz;\n\tthis->rz = c * rz + s * ry;\n\tthis->fy = c * uy - s * uz;\n\tthis->fz = c * uz + s * uy;\n\tthis->uy = c * ay - s * az;\n\tthis->uz = c * az + s * ay;\n\tthis->py = c * py - s * pz;\n\tthis->pz = c * pz + s * py;\n}\n\nvoid\nCMatrix::RotateY(float y)\n{\n\tfloat c = Cos(y);\n\tfloat s = Sin(y);\n\n\tfloat rx = this->rx;\n\tfloat rz = this->rz;\n\tfloat ux = this->fx;\n\tfloat uz = this->fz;\n\tfloat ax = this->ux;\n\tfloat az = this->uz;\n\tfloat px = this->px;\n\tfloat pz = this->pz;\n\n\tthis->rx = c * rx + s * rz;\n\tthis->rz = c * rz - s * rx;\n\tthis->fx = c * ux + s * uz;\n\tthis->fz = c * uz - s * ux;\n\tthis->ux = c * ax + s * az;\n\tthis->uz = c * az - s * ax;\n\tthis->px = c * px + s * pz;\n\tthis->pz = c * pz - s * px;\n}\n\nvoid\nCMatrix::RotateZ(float z)\n{\n\tfloat c = Cos(z);\n\tfloat s = Sin(z);\n\n\tfloat ry = this->ry;\n\tfloat rx = this->rx;\n\tfloat uy = this->fy;\n\tfloat ux = this->fx;\n\tfloat ay = this->uy;\n\tfloat ax = this->ux;\n\tfloat py = this->py;\n\tfloat px = this->px;\n\n\tthis->rx = c * rx - s * ry;\n\tthis->ry = c * ry + s * rx;\n\tthis->fx = c * ux - s * uy;\n\tthis->fy = c * uy + s * ux;\n\tthis->ux = c * ax - s * ay;\n\tthis->uy = c * ay + s * ax;\n\tthis->px = c * px - s * py;\n\tthis->py = c * py + s * px;\n\n}\n\nvoid\nCMatrix::Rotate(float x, float y, float z)\n{\n\tfloat cX = Cos(x);\n\tfloat sX = Sin(x);\n\tfloat cY = Cos(y);\n\tfloat sY = Sin(y);\n\tfloat cZ = Cos(z);\n\tfloat sZ = Sin(z);\n\t\n\tfloat rx = this->rx;\n\tfloat ry = this->ry;\n\tfloat rz = this->rz;\n\tfloat ux = this->fx;\n\tfloat uy = this->fy;\n\tfloat uz = this->fz;\n\tfloat ax = this->ux;\n\tfloat ay = this->uy;\n\tfloat az = this->uz;\n\tfloat px = this->px;\n\tfloat py = this->py;\n\tfloat pz = this->pz;\n\n\tfloat x1 = cZ * cY - (sZ * sX) * sY;\n\tfloat x2 = (cZ * sX) * sY + sZ * cY;\n\tfloat x3 = -cX * sY;\n\tfloat y1 = -sZ * cX;\n\tfloat y2 = cZ * cX;\n\tfloat y3 = sX;\n\tfloat z1 = (sZ * sX) * cY + cZ * sY;\n\tfloat z2 = sZ * sY - (cZ * sX) * cY;\n\tfloat z3 = cX * cY;\n\n\tthis->rx = x1 * rx + y1 * ry + z1 * rz;\n\tthis->ry = x2 * rx + y2 * ry + z2 * rz;\n\tthis->rz = x3 * rx + y3 * ry + z3 * rz;\n\tthis->fx = x1 * ux + y1 * uy + z1 * uz;\n\tthis->fy = x2 * ux + y2 * uy + z2 * uz;\n\tthis->fz = x3 * ux + y3 * uy + z3 * uz;\n\tthis->ux = x1 * ax + y1 * ay + z1 * az;\n\tthis->uy = x2 * ax + y2 * ay + z2 * az;\n\tthis->uz = x3 * ax + y3 * ay + z3 * az;\n\tthis->px = x1 * px + y1 * py + z1 * pz;\n\tthis->py = x2 * px + y2 * py + z2 * pz;\n\tthis->pz = x3 * px + y3 * py + z3 * pz;\n}\n\nCMatrix &\nCMatrix::operator*=(CMatrix const &rhs)\n{\n\t// TODO: VU0 code\n\t*this = *this * rhs;\n\treturn *this;\n}\n\nvoid\nCMatrix::Reorthogonalise(void)\n{\n\tCVector &r = GetRight();\n\tCVector &f = GetForward();\n\tCVector &u = GetUp();\n\tu = CrossProduct(r, f);\n\tu.Normalise();\n\tr = CrossProduct(f, u);\n\tr.Normalise();\n\tf = CrossProduct(u, r);\n}\n\nCMatrix\noperator*(const CMatrix &m1, const CMatrix &m2)\n{\n\t// TODO: VU0 code\n\tCMatrix out;\n\tout.rx = m1.rx * m2.rx + m1.fx * m2.ry + m1.ux * m2.rz;\n\tout.ry = m1.ry * m2.rx + m1.fy * m2.ry + m1.uy * m2.rz;\n\tout.rz = m1.rz * m2.rx + m1.fz * m2.ry + m1.uz * m2.rz;\n\tout.fx = m1.rx * m2.fx + m1.fx * m2.fy + m1.ux * m2.fz;\n\tout.fy = m1.ry * m2.fx + m1.fy * m2.fy + m1.uy * m2.fz;\n\tout.fz = m1.rz * m2.fx + m1.fz * m2.fy + m1.uz * m2.fz;\n\tout.ux = m1.rx * m2.ux + m1.fx * m2.uy + m1.ux * m2.uz;\n\tout.uy = m1.ry * m2.ux + m1.fy * m2.uy + m1.uy * m2.uz;\n\tout.uz = m1.rz * m2.ux + m1.fz * m2.uy + m1.uz * m2.uz;\n\tout.px = m1.rx * m2.px + m1.fx * m2.py + m1.ux * m2.pz + m1.px;\n\tout.py = m1.ry * m2.px + m1.fy * m2.py + m1.uy * m2.pz + m1.py;\n\tout.pz = m1.rz * m2.px + m1.fz * m2.py + m1.uz * m2.pz + m1.pz;\n\treturn out;\n}\n\nCMatrix &\nInvert(const CMatrix &src, CMatrix &dst)\n{\n\t// TODO: VU0 code\n\tdst.f[3][0] = dst.f[3][1] = dst.f[3][2] = 0.0f;\n\n\tdst.f[0][0] = src.f[0][0];\n\tdst.f[0][1] = src.f[1][0];\n\tdst.f[0][2] = src.f[2][0];\n\n\tdst.f[1][0] = src.f[0][1];\n\tdst.f[1][1] = src.f[1][1];\n\tdst.f[1][2] = src.f[2][1];\n\n\tdst.f[2][0] = src.f[0][2];\n\tdst.f[2][1] = src.f[1][2];\n\tdst.f[2][2] = src.f[2][2];\n\n\n\tdst.f[3][0] += dst.f[0][0] * src.f[3][0];\n\tdst.f[3][1] += dst.f[0][1] * src.f[3][0];\n\tdst.f[3][2] += dst.f[0][2] * src.f[3][0];\n\n\tdst.f[3][0] += dst.f[1][0] * src.f[3][1];\n\tdst.f[3][1] += dst.f[1][1] * src.f[3][1];\n\tdst.f[3][2] += dst.f[1][2] * src.f[3][1];\n\n\tdst.f[3][0] += dst.f[2][0] * src.f[3][2];\n\tdst.f[3][1] += dst.f[2][1] * src.f[3][2];\n\tdst.f[3][2] += dst.f[2][2] * src.f[3][2];\n\n\tdst.f[3][0] = -dst.f[3][0];\n\tdst.f[3][1] = -dst.f[3][1];\n\tdst.f[3][2] = -dst.f[3][2];\n\n\treturn dst;\n}\n\nvoid\nCMatrix::CopyToRwMatrix(RwMatrix* matrix)\n{\n\tmatrix->right = GetRight();\n\tmatrix->up = GetForward();\n\tmatrix->at = GetUp();\n\tmatrix->pos = GetPosition();\n\tRwMatrixUpdate(matrix);\n}\n\nCMatrix\nInvert(const CMatrix &matrix)\n{\n\tCMatrix inv;\n\treturn Invert(matrix, inv);\n}\n\nvoid\nCCompressedMatrixNotAligned::CompressFromFullMatrix(CMatrix &other)\n{\n\tm_rightX = 127.0f * other.GetRight().x;\n\tm_rightY = 127.0f * other.GetRight().y;\n\tm_rightZ = 127.0f * other.GetRight().z;\n\tm_upX = 127.0f * other.GetForward().x;\n\tm_upY = 127.0f * other.GetForward().y;\n\tm_upZ = 127.0f * other.GetForward().z;\n\tm_vecPos = other.GetPosition();\n}\n\nvoid\nCCompressedMatrixNotAligned::DecompressIntoFullMatrix(CMatrix &other)\n{\n\tother.GetRight().x = m_rightX / 127.0f;\n\tother.GetRight().y = m_rightY / 127.0f;\n\tother.GetRight().z = m_rightZ / 127.0f;\n\tother.GetForward().x = m_upX / 127.0f;\n\tother.GetForward().y = m_upY / 127.0f;\n\tother.GetForward().z = m_upZ / 127.0f;\n\tother.GetUp() = CrossProduct(other.GetRight(), other.GetForward());\n\tother.GetPosition() = m_vecPos;\n\tother.Reorthogonalise();\n}"
  },
  {
    "path": "src/math/Matrix.h",
    "content": "#pragma once\n\nclass CMatrix\n{\npublic:\n#ifdef GTA_PS2\n\tunion\n\t{\n\t\tfloat f[4][4];\n\t\tstruct\n\t\t{\n\t\t\tfloat rx, ry, rz;\n\t\t\tRwMatrix *m_attachment;\n\t\t\tfloat fx, fy, fz;\n\t\t\tbool m_hasRwMatrix;\t// are we the owner?\n\t\t\tfloat ux, uy, uz, uw;\n\t\t\tfloat px, py, pz, pw;\n\t\t};\n\t};\n#else\n\tunion\n\t{\n\t\tfloat f[4][4];\n\t\tstruct\n\t\t{\n\t\t\tfloat rx, ry, rz, rw;\n\t\t\tfloat fx, fy, fz, fw;\n\t\t\tfloat ux, uy, uz, uw;\n\t\t\tfloat px, py, pz, pw;\n\t\t};\n\t};\n\n\tRwMatrix *m_attachment;\n\tbool m_hasRwMatrix;\t// are we the owner?\n#endif\n\n\tCMatrix(void);\n\tCMatrix(CMatrix const &m);\n\tCMatrix(RwMatrix *matrix, bool owner = false);\n\tCMatrix(float scale){\n\t\tm_attachment = nil;\n\t\tm_hasRwMatrix = false;\n\t\tSetScale(scale);\n\t}\n\t~CMatrix(void);\n\tvoid Attach(RwMatrix *matrix, bool owner = false);\n\tvoid AttachRW(RwMatrix *matrix, bool owner = false);\n\tvoid Detach(void);\n\tvoid Update(void);\n\tvoid UpdateRW(void);\n\tvoid operator=(CMatrix const &rhs);\n\tCMatrix &operator+=(CMatrix const &rhs);\n\tCMatrix &operator*=(CMatrix const &rhs);\n\n\tCVector &GetPosition(void) { return *(CVector*)&px; }\n\tCVector &GetRight(void) { return *(CVector*)&rx; }\n\tCVector &GetForward(void) { return *(CVector*)&fx; }\n\tCVector &GetUp(void) { return *(CVector*)&ux; }\n\n\tconst CVector &GetPosition(void) const { return *(CVector*)&px; }\n\tconst CVector &GetRight(void) const { return *(CVector*)&rx; }\n\tconst CVector &GetForward(void) const { return *(CVector*)&fx; }\n\tconst CVector &GetUp(void) const { return *(CVector*)&ux; }\n\n\n\tvoid SetTranslate(float x, float y, float z);\n\tvoid SetTranslate(const CVector &trans){ SetTranslate(trans.x, trans.y, trans.z); }\n\tvoid Translate(float x, float y, float z){\n\t\tpx += x;\n\t\tpy += y;\n\t\tpz += z;\n\t}\n\tvoid Translate(const CVector &trans){ Translate(trans.x, trans.y, trans.z); }\n\n\tvoid SetScale(float s);\n\tvoid Scale(float scale)\n\t{\n\t\tfor (int i = 0; i < 3; i++)\n\t\t\tfor (int j = 0; j < 3; j++)\n\t\t\t\tf[i][j] *= scale;\n\t}\n\tvoid Scale(float sx, float sy, float sz)\n\t{\n\t\tfor (int i = 0; i < 3; i++){\n\t\t\tf[i][0] *= sx;\n\t\t\tf[i][1] *= sy;\n\t\t\tf[i][2] *= sz;\n\t\t}\n\t}\n\n\n\tvoid SetRotateXOnly(float angle);\n\tvoid SetRotateYOnly(float angle);\n\tvoid SetRotateZOnly(float angle);\n\tvoid SetRotateZOnlyScaled(float angle, float scale) {\n\t\tfloat c = Cos(angle);\n\t\tfloat s = Sin(angle);\n\n\t\trx = c * scale;\n\t\try = s * scale;\n\t\trz = 0.0f;\n\n\t\tfx = -s * scale;\n\t\tfy = c * scale;\n\t\tfz = 0.0f;\n\n\t\tux = 0.0f;\n\t\tuy = 0.0f;\n\t\tuz = scale;\n\t}\n\tvoid SetRotateX(float angle);\n\tvoid SetRotateY(float angle);\n\tvoid SetRotateZ(float angle);\n\tvoid SetRotate(float xAngle, float yAngle, float zAngle);\n\tvoid Rotate(float x, float y, float z);\n\tvoid RotateX(float x);\n\tvoid RotateY(float y);\n\tvoid RotateZ(float z);\n\n\tvoid Reorthogonalise(void);\n\tvoid CopyOnlyMatrix(const CMatrix &other);\n\tvoid SetUnity(void);\n\tvoid ResetOrientation(void);\n\t\n\tvoid CopyToRwMatrix(RwMatrix* matrix);\n\t\n\tvoid SetTranslateOnly(float x, float y, float z) {\n\t\tpx = x;\n\t\tpy = y;\n\t\tpz = z;\n\t}\n\tvoid SetTranslateOnly(const CVector& pos) {\n\t\tSetTranslateOnly(pos.x, pos.y, pos.z);\n\t}\n\tvoid CheckIntegrity(){}\n};\n\n\nCMatrix &Invert(const CMatrix &src, CMatrix &dst);\nCMatrix Invert(const CMatrix &matrix);\nCMatrix operator*(const CMatrix &m1, const CMatrix &m2);\ninline CVector MultiplyInverse(const CMatrix &mat, const CVector &vec)\n{\n\tCVector v(vec.x - mat.px, vec.y - mat.py, vec.z - mat.pz);\n\treturn CVector(\n\t\tmat.rx * v.x + mat.ry * v.y + mat.rz * v.z,\n\t\tmat.fx * v.x + mat.fy * v.y + mat.fz * v.z,\n\t\tmat.ux * v.x + mat.uy * v.y + mat.uz * v.z);\n}\n\n\n\nclass CCompressedMatrixNotAligned\n{\n\tCVector m_vecPos;\n\tint8 m_rightX;\n\tint8 m_rightY;\n\tint8 m_rightZ;\n\tint8 m_upX;\n\tint8 m_upY;\n\tint8 m_upZ;\npublic:\n\tvoid CompressFromFullMatrix(CMatrix &other);\n\tvoid DecompressIntoFullMatrix(CMatrix &other);\n};\n\nclass CCompressedMatrix : public CCompressedMatrixNotAligned\n{\n\tint _alignment; // no clue what would this align to\n};"
  },
  {
    "path": "src/math/Quaternion.cpp",
    "content": "#include \"common.h\"\n#include \"Quaternion.h\"\n\nvoid\nCQuaternion::Normalise(void)\n{\n\tfloat sq = MagnitudeSqr();\n\tif (sq == 0.0f)\n\t\tw = 1.0f;\n\telse {\n\t\tfloat invsqrt = RecipSqrt(sq);\n\t\tx *= invsqrt;\n\t\ty *= invsqrt;\n\t\tz *= invsqrt;\n\t\tw *= invsqrt;\n\t}\n}\n\nvoid\nCQuaternion::Slerp(const CQuaternion &q1, const CQuaternion &q2, float theta, float invSin, float t)\n{\n\tif (theta == 0.0f)\n\t\t*this = q2;\n\telse {\n\t\tfloat w1, w2;\n\t\tif (theta > PI / 2) {\n\t\t\ttheta = PI - theta;\n\t\t\tw1 = Sin((1.0f - t) * theta) * invSin;\n\t\t\tw2 = -Sin(t * theta) * invSin;\n\t\t} else {\n\t\t\tw1 = Sin((1.0f - t) * theta) * invSin;\n\t\t\tw2 = Sin(t * theta) * invSin;\n\t\t}\n\t\t// TODO: VU0 code\n\t\t*this = w1 * q1 + w2 * q2;\n\t}\n}\n\nvoid\nCQuaternion::Multiply(const CQuaternion &q1, const CQuaternion &q2)\n{\n\tx = (q2.z * q1.y) - (q1.z * q2.y) + (q1.x * q2.w) + (q2.x * q1.w);\n\ty = (q2.x * q1.z) - (q1.x * q2.z) + (q1.y * q2.w) + (q2.y * q1.w);\n\tz = (q2.y * q1.x) - (q1.y * q2.x) + (q1.z * q2.w) + (q2.z * q1.w);\n\tw = (q2.w * q1.w) - (q2.x * q1.x) - (q2.y * q1.y) - (q2.z * q1.z);\n}\n\nvoid\nCQuaternion::Get(RwV3d *axis, float *angle)\n{\n\t*angle = Acos(w);\n\tfloat s = Sin(*angle);\n\n\taxis->x = x * (1.0f / s);\n\taxis->y = y * (1.0f / s);\n\taxis->z = z * (1.0f / s);\n}\n\nvoid\nCQuaternion::Set(RwV3d *axis, float angle)\n{\n\tfloat halfCos = Cos(angle * 0.5f);\n\tfloat halfSin = Sin(angle * 0.5f);\n\tx = axis->x * halfSin;\n\ty = axis->y * halfSin;\n\tz = axis->z * halfSin;\n\tw = halfCos;\n}\n\nvoid\nCQuaternion::Get(RwMatrix *matrix)\n{\n\tfloat x2 = x + x;\n\tfloat y2 = y + y;\n\tfloat z2 = z + z;\n\n\tfloat x_2x = x * x2;\n\tfloat x_2y = x * y2;\n\tfloat x_2z = x * z2;\n\tfloat y_2y = y * y2;\n\tfloat y_2z = y * z2;\n\tfloat z_2z = z * z2;\n\tfloat w_2x = w * x2;\n\tfloat w_2y = w * y2;\n\tfloat w_2z = w * z2;\n\n\tmatrix->right.x = 1.0f - (y_2y + z_2z);\n\tmatrix->up.x = x_2y - w_2z;\n\tmatrix->at.x = x_2z + w_2y;\n\tmatrix->right.y = x_2y + w_2z;\n\tmatrix->up.y = 1.0f - (x_2x + z_2z);\n\tmatrix->at.y = y_2z - w_2x;\n\tmatrix->right.z = x_2z - w_2y;\n\tmatrix->up.z = y_2z + w_2x;\n\tmatrix->at.z = 1.0f - (x_2x + y_2y);\n}\n\nvoid\nCQuaternion::Set(const RwMatrix &matrix)\n{\n\tfloat f, s, m;\n\n\tf = matrix.up.y + matrix.right.x + matrix.at.z;\n\tif (f >= 0.0f) {\n\t\ts = Sqrt(f + 1.0f);\n\t\tw = 0.5f * s;\n\t\tm = 0.5f / s;\n\t\tx = (matrix.up.z - matrix.at.y) * m;\n\t\ty = (matrix.at.x - matrix.right.z) * m;\n\t\tz = (matrix.right.y - matrix.up.x) * m;\n\t\treturn;\n\t}\n\n\tf = matrix.right.x - matrix.up.y - matrix.at.z;\n\tif (f >= 0.0f) {\n\t\ts = Sqrt(f + 1.0f);\n\t\tx = 0.5f * s;\n\t\tm = 0.5f / s;\n\t\ty = (matrix.up.x + matrix.right.y) * m;\n\t\tz = (matrix.at.x + matrix.right.z) * m;\n\t\tw = (matrix.up.z - matrix.at.y) * m;\n\t\treturn;\n\t}\n\n\tf = matrix.up.y - matrix.right.x - matrix.at.z;\n\tif (f >= 0.0f) {\n\t\ts = Sqrt(f + 1.0f);\n\t\ty = 0.5f * s;\n\t\tm = 0.5f / s;\n\t\tw = (matrix.at.x - matrix.right.z) * m;\n\t\tx = (matrix.up.x - matrix.right.y) * m;\n\t\tz = (matrix.at.y + matrix.up.z) * m;\n\t\treturn;\n\t}\n\n\tf = matrix.at.z - (matrix.up.y + matrix.right.x);\n\ts = Sqrt(f + 1.0f);\n\tz = 0.5f * s;\n\tm = 0.5f / s;\n\tw = (matrix.right.y - matrix.up.x) * m;\n\tx = (matrix.at.x + matrix.right.z) * m;\n\ty = (matrix.at.y + matrix.up.z) * m;\n}\n\nvoid\nCQuaternion::Get(float *f1, float *f2, float *f3)\n{\n\tRwMatrix matrix;\n\n\tGet(&matrix);\n\t*f3 = Atan2(matrix.right.y, matrix.up.y);\n\tif (*f3 < 0.0f)\n\t\t*f3 += TWOPI;\n\tfloat s = Sin(*f3);\n\tfloat c = Cos(*f3);\n\t*f1 = Atan2(-matrix.at.y, s * matrix.right.y + c * matrix.up.y);\n\tif (*f1 < 0.0f)\n\t\t*f1 += TWOPI;\n\t*f2 = Atan2(-(matrix.right.z * c - matrix.up.z * s), matrix.right.x * c - matrix.up.x * s);\n\tif (*f2 < 0.0f)\n\t\t*f2 += TWOPI;\n}\n\nvoid\nCQuaternion::Set(float f1, float f2, float f3)\n{\n\tfloat c1 = Cos(f1 * 0.5f);\n\tfloat c2 = Cos(f2 * 0.5f);\n\tfloat c3 = Cos(f3 * 0.5f);\n\tfloat s1 = Sin(f1 * 0.5f);\n\tfloat s2 = Sin(f2 * 0.5f);\n\tfloat s3 = Sin(f3 * 0.5f);\n\tx = ((c2 * c1) * s3) - ((s2 * s1) * c3);\n\ty = ((s1 * c2) * c3) + ((s2 * c1) * s3);\n\tz = ((s2 * c1) * c3) - ((s1 * c2) * s3);\n\tw = ((c2 * c1) * c3) + ((s2 * s1) * s3);\n}"
  },
  {
    "path": "src/math/Quaternion.h",
    "content": "#pragma once\n\n// TODO: actually implement this\nclass CQuaternion\n{\npublic:\n\tfloat x, y, z, w;\n\tCQuaternion(void) {}\n\tCQuaternion(float x, float y, float z, float w) : x(x), y(y), z(z), w(w) {}\n\n\tfloat Magnitude(void) const { return Sqrt(x*x + y*y + z*z + w*w); }\n\tfloat MagnitudeSqr(void) const { return x*x + y*y + z*z + w*w; }\n\tvoid Normalise(void);\n\tvoid Multiply(const CQuaternion &q1, const CQuaternion &q2);\n\tvoid Invert(void){\t// Conjugate would have been a better name\n\t\tx = -x;\n\t\ty = -y;\n\t\tz = -z;\n\t}\n\n\tconst CQuaternion &operator+=(CQuaternion const &right) {\n\t\tx += right.x;\n\t\ty += right.y;\n\t\tz += right.z;\n\t\tw += right.w;\n\t\treturn *this;\n\t}\n\n\tconst CQuaternion &operator-=(CQuaternion const &right) {\n\t\tx -= right.x;\n\t\ty -= right.y;\n\t\tz -= right.z;\n\t\tw -= right.w;\n\t\treturn *this;\n\t}\n\n\tconst CQuaternion &operator*=(float right) {\n\t\tx *= right;\n\t\ty *= right;\n\t\tz *= right;\n\t\tw *= right;\n\t\treturn *this;\n\t}\n\n\tconst CQuaternion &operator/=(float right) {\n\t\tx /= right;\n\t\ty /= right;\n\t\tz /= right;\n\t\tw /= right;\n\t\treturn *this;\n\t}\n\n\tCQuaternion operator-() const {\n\t\treturn CQuaternion(-x, -y, -z, -w);\n\t}\n\n\tvoid Slerp(const CQuaternion &q1, const CQuaternion &q2, float theta, float invSin, float t);\n\tvoid Get(RwV3d *axis, float *angle);\n\tvoid Set(RwV3d *axis, float angle);\n\tvoid Get(RwMatrix *matrix);\n\tvoid Set(const RwMatrix &matrix);\n\tvoid Set(float f1, float f2, float f3);\n\tvoid Get(float *f1, float *f2, float *f3);\n};\n\ninline float\nDotProduct(const CQuaternion &q1, const CQuaternion &q2)\n{\n\treturn q1.x*q2.x + q1.y*q2.y + q1.z*q2.z + q1.w*q2.w;\n}\n\ninline CQuaternion operator+(const CQuaternion &left, const CQuaternion &right)\n{\n\treturn CQuaternion(left.x + right.x, left.y + right.y, left.z + right.z, left.w + right.w);\n}\n\ninline CQuaternion operator-(const CQuaternion &left, const CQuaternion &right)\n{\n\treturn CQuaternion(left.x - right.x, left.y - right.y, left.z - right.z, left.w - right.w);\n}\n\ninline CQuaternion operator*(const CQuaternion &left, float right)\n{\n\treturn CQuaternion(left.x * right, left.y * right, left.z * right, left.w * right);\n}\n\ninline CQuaternion operator*(float left, const CQuaternion &right)\n{\n\treturn CQuaternion(left * right.x, left * right.y, left * right.z, left * right.w);\n}\n\ninline CQuaternion operator/(const CQuaternion &left, float right)\n{\n\treturn CQuaternion(left.x / right, left.y / right, left.z / right, left.w / right);\n}\n"
  },
  {
    "path": "src/math/Rect.cpp",
    "content": "#include \"common.h\"\n\nCRect::CRect(void)\n{\n\tleft = 1000000.0f;\n\ttop = 1000000.0f;\n\tright = -1000000.0f;\n\tbottom = -1000000.0f;\n}\n\nCRect::CRect(float l, float t, float r, float b)\n{\n\tleft = l;\n\ttop = t;\n\tright = r;\n\tbottom = b;\n}"
  },
  {
    "path": "src/math/Rect.h",
    "content": "#pragma once\n\nclass CRect\n{\npublic:\n\tfloat left;     // x min\n\tfloat bottom;   // y max\n\tfloat right;    // x max\n\tfloat top;      // y min\n\n\tCRect(void);\n\tCRect(float l, float t, float r, float b);\n\tvoid ContainPoint(CVector const &v){\n\t\tif(v.x < left) left = v.x;\n\t\tif(v.x > right) right = v.x;\n\t\tif(v.y < top) top = v.y;\n\t\tif(v.y > bottom) bottom = v.y;\n\t}\n\tvoid ContainRect(const CRect &r){\n\t\tif(r.left < left) left = r.left;\n\t\tif(r.right > right) right = r.right;\n\t\tif(r.top < top) top = r.top;\n\t\tif(r.bottom > bottom) bottom = r.bottom;\n\t}\n\n\tbool IsPointInside(const CVector2D &p){\n\t\treturn p.x >= left &&\n\t\t\tp.x <= right &&\n\t\t\tp.y >= top &&\n\t\t\tp.y <= bottom;\n\t}\n\tbool IsPointInside(const CVector2D &p, float extraRadius){\n\t\treturn p.x >= left-extraRadius &&\n\t\t\tp.x <= right+extraRadius &&\n\t\t\tp.y >= top-extraRadius &&\n\t\t\tp.y <= bottom+extraRadius;\n\t}\n\n\tvoid Translate(float x, float y){\n\t\tleft += x;\n\t\tright += x;\n\t\tbottom += y;\n\t\ttop += y;\n\t}\n\n\tvoid Grow(float r) {\n\t\tleft -= r;\n\t\tright += r;\n\t\ttop -= r;\n\t\tbottom += r;\n\t}\n\n\tvoid Grow(float l, float r)\n\t{\n\t\tleft -= l;\n\t\ttop -= l;\n\t\tright += r;\n\t\tbottom += r;\n\t}\n\n\tvoid Grow(float l, float r, float t, float b)\n\t{\n\t\tleft -= l;\n\t\ttop -= t;\n\t\tright += r;\n\t\tbottom += b;\n\t}\n\n\tfloat GetWidth(void) { return right - left; }\n\tfloat GetHeight(void) { return bottom - top; }\n};\n"
  },
  {
    "path": "src/math/Vector.cpp",
    "content": "#include \"common.h\"\n\nvoid\nCVector::Normalise(void)\n{\n\tfloat sq = MagnitudeSqr();\n\tif (sq > 0.0f) {\n\t\tfloat invsqrt = RecipSqrt(sq);\n\t\tx *= invsqrt;\n\t\ty *= invsqrt;\n\t\tz *= invsqrt;\n\t} else\n\t\tx = 1.0f;\n}\n\nCVector\nCrossProduct(const CVector &v1, const CVector &v2)\n{\n\treturn CVector(v1.y * v2.z - v1.z * v2.y, v1.z * v2.x - v1.x * v2.z, v1.x * v2.y - v1.y * v2.x);\n}\n\nCVector\nMultiply3x3(const CMatrix &mat, const CVector &vec)\n{\n\t// TODO: VU0 code\n\treturn CVector(mat.rx * vec.x + mat.fx * vec.y + mat.ux * vec.z,\n\t               mat.ry * vec.x + mat.fy * vec.y + mat.uy * vec.z,\n\t               mat.rz * vec.x + mat.fz * vec.y + mat.uz * vec.z);\n}\n\nCVector\nMultiply3x3(const CVector &vec, const CMatrix &mat)\n{\n\treturn CVector(mat.rx * vec.x + mat.ry * vec.y + mat.rz * vec.z,\n\t               mat.fx * vec.x + mat.fy * vec.y + mat.fz * vec.z,\n\t               mat.ux * vec.x + mat.uy * vec.y + mat.uz * vec.z);\n}\n\nCVector\noperator*(const CMatrix &mat, const CVector &vec)\n{\n\t// TODO: VU0 code\n\treturn CVector(mat.rx * vec.x + mat.fx * vec.y + mat.ux * vec.z + mat.px,\n\t               mat.ry * vec.x + mat.fy * vec.y + mat.uy * vec.z + mat.py,\n\t               mat.rz * vec.x + mat.fz * vec.y + mat.uz * vec.z + mat.pz);\n}\n"
  },
  {
    "path": "src/math/Vector.h",
    "content": "#pragma once\n\nclass CVector : public RwV3d\n{\npublic:\n\tCVector(void) {}\n\tCVector(float x, float y, float z)\n\t{\n\t\tthis->x = x;\n\t\tthis->y = y;\n\t\tthis->z = z;\n\t}\n\n\tCVector(const RwV3d &v)\n\t{\n\t\tx = v.x;\n\t\ty = v.y;\n\t\tz = v.z;\n\t}\n\t// (0,1,0) means no rotation. So get right vector and its atan\n\tfloat Heading(void) const { return Atan2(-x, y); }\n\tfloat Magnitude(void) const { return Sqrt(x*x + y*y + z*z); }\n\tfloat MagnitudeSqr(void) const { return x*x + y*y + z*z; }\n\tfloat Magnitude2D(void) const { return Sqrt(x*x + y*y); }\n\tfloat MagnitudeSqr2D(void) const { return x*x + y*y; }\n\tvoid Normalise(void);\n\t\n\tvoid Normalise2D(void) {\n\t\tfloat sq = MagnitudeSqr2D();\n\t\tfloat invsqrt = RecipSqrt(sq);\n\t\tx *= invsqrt;\n\t\ty *= invsqrt;\n\t}\n\n\tconst CVector &operator+=(CVector const &right) {\n\t\tx += right.x;\n\t\ty += right.y;\n\t\tz += right.z;\n\t\treturn *this;\n\t}\n\n\tconst CVector &operator-=(CVector const &right) {\n\t\tx -= right.x;\n\t\ty -= right.y;\n\t\tz -= right.z;\n\t\treturn *this;\n\t}\n\n\tconst CVector &operator*=(float right) {\n\t\tx *= right;\n\t\ty *= right;\n\t\tz *= right;\n\t\treturn *this;\n\t}\n\n\tconst CVector &operator/=(float right) {\n\t\tx /= right;\n\t\ty /= right;\n\t\tz /= right;\n\t\treturn *this;\n\t}\n\n\tCVector operator-() const {\n\t\treturn CVector(-x, -y, -z);\n\t}\n\n\tconst bool operator==(CVector const &right) const {\n\t\treturn x == right.x && y == right.y && z == right.z;\n\t}\n\n\tconst bool operator!=(CVector const &right) const {\n\t\treturn x != right.x || y != right.y || z != right.z;\n\t}\n\n\tbool IsZero(void) const { return x == 0.0f && y == 0.0f && z == 0.0f; }\n};\n\ninline CVector operator+(const CVector &left, const CVector &right)\n{\n\treturn CVector(left.x + right.x, left.y + right.y, left.z + right.z);\n}\n\ninline CVector operator-(const CVector &left, const CVector &right)\n{\n\treturn CVector(left.x - right.x, left.y - right.y, left.z - right.z);\n}\n\ninline CVector operator*(const CVector &left, float right)\n{\n\treturn CVector(left.x * right, left.y * right, left.z * right);\n}\n\ninline CVector operator*(float left, const CVector &right)\n{\n\treturn CVector(left * right.x, left * right.y, left * right.z);\n}\n\ninline CVector operator/(const CVector &left, float right)\n{\n\treturn CVector(left.x / right, left.y / right, left.z / right);\n}\n\ninline float\nDotProduct(const CVector &v1, const CVector &v2)\n{\n\treturn v1.x*v2.x + v1.y*v2.y + v1.z*v2.z;\n}\n\nCVector CrossProduct(const CVector &v1, const CVector &v2);\n\ninline float\nDistance(const CVector &v1, const CVector &v2)\n{\n\treturn (v2 - v1).Magnitude();\n}\n\ninline float\nDistance2D(const CVector &v1, const CVector &v2)\n{\n\tfloat x = v2.x - v1.x;\n\tfloat y = v2.y - v1.y;\n\treturn Sqrt(x*x + y*y);\n}\n\nclass CMatrix;\n\nCVector Multiply3x3(const CMatrix &mat, const CVector &vec);\nCVector Multiply3x3(const CVector &vec, const CMatrix &mat);\nCVector operator*(const CMatrix &mat, const CVector &vec);"
  },
  {
    "path": "src/math/Vector2D.h",
    "content": "#pragma once\n\nclass CVector2D\n{\npublic:\n\tfloat x, y;\n\tCVector2D(void) {}\n\tCVector2D(float x, float y) : x(x), y(y) {}\n\tCVector2D(const CVector &v) : x(v.x), y(v.y) {}\n\tfloat Heading(void) const { return Atan2(-x, y); }\n\tfloat Magnitude(void) const { return Sqrt(x*x + y*y); }\n\tfloat MagnitudeSqr(void) const { return x*x + y*y; }\n\n\tvoid Normalise(void) {\n\t\tfloat sq = MagnitudeSqr();\n\t\tif(sq > 0.0f){\n\t\t\tfloat invsqrt = RecipSqrt(sq);\n\t\t\tx *= invsqrt;\n\t\t\ty *= invsqrt;\n\t\t}else\n\t\t\tx = 1.0f;\n\t}\n\n\tconst CVector2D &operator+=(CVector2D const &right) {\n\t\tx += right.x;\n\t\ty += right.y;\n\t\treturn *this;\n\t}\n\n\tconst CVector2D &operator-=(CVector2D const &right) {\n\t\tx -= right.x;\n\t\ty -= right.y;\n\t\treturn *this;\n\t}\n\n\tconst CVector2D &operator*=(float right) {\n\t\tx *= right;\n\t\ty *= right;\n\t\treturn *this;\n\t}\n\n\tconst CVector2D &operator/=(float right) {\n\t\tx /= right;\n\t\ty /= right;\n\t\treturn *this;\n\t}\n\tCVector2D operator-(const CVector2D &rhs) const {\n\t\treturn CVector2D(x-rhs.x, y-rhs.y);\n\t}\n\tCVector2D operator+(const CVector2D &rhs) const {\n\t\treturn CVector2D(x+rhs.x, y+rhs.y);\n\t}\n\tCVector2D operator/(float t) const {\n\t\treturn CVector2D(x/t, y/t);\n\t}\n\tCVector2D operator-() const {\n\t\treturn CVector2D(-x, -y);\n\t}\n};\n\ninline float\nDotProduct2D(const CVector2D &v1, const CVector2D &v2)\n{\n\treturn v1.x*v2.x + v1.y*v2.y;\n}\n\ninline float\nCrossProduct2D(const CVector2D &v1, const CVector2D &v2)\n{\n\treturn v1.x*v2.y - v1.y*v2.x;\n}\n\ninline float\nDistance2D(const CVector2D &v, float x, float y)\n{\n\treturn Sqrt((v.x-x)*(v.x-x) + (v.y-y)*(v.y-y));\n}\n\ninline float\nDistanceSqr2D(const CVector2D &v, float x, float y)\n{\n\treturn (v.x-x)*(v.x-x) + (v.y-y)*(v.y-y);\n}\n\ninline void\nNormalizeXY(float &x, float &y)\n{\n\tfloat l  = Sqrt(x*x + y*y);\n\tif(l != 0.0f){\n\t\tx /= l;\n\t\ty /= l;\n\t}else\n\t\tx = 1.0f;\n}\n\ninline CVector2D operator*(const CVector2D &left, float right)\n{\n\treturn CVector2D(left.x * right, left.y * right);\n}\n\ninline CVector2D operator*(float left, const CVector2D &right)\n{\n\treturn CVector2D(left * right.x, left * right.y);\n}\n"
  },
  {
    "path": "src/math/VuVector.h",
    "content": "#pragma once\n\nclass TYPEALIGN(16) CVuVector : public CVector\n{\npublic:\n\tfloat w;\n\tCVuVector(void) {}\n\tCVuVector(float x, float y, float z) : CVector(x, y, z) {}\n\tCVuVector(float x, float y, float z, float w) : CVector(x, y, z), w(w) {}\n\tCVuVector(const CVector &v) : CVector(v.x, v.y, v.z) {}\n\tCVuVector(const RwV3d &v) : CVector(v) {}\n/*\n\tvoid Normalise(void) {\n\t\tfloat sq = MagnitudeSqr();\n\t\t// TODO: VU0 code\n\t\tif(sq > 0.0f){\n\t\t\tfloat invsqrt = RecipSqrt(sq);\n\t\t\tx *= invsqrt;\n\t\t\ty *= invsqrt;\n\t\t\tz *= invsqrt;\n\t\t}else\n\t\t\tx = 1.0f;\n\t}\n*/\n};\n\nvoid TransformPoint(CVuVector &out, const CMatrix &mat, const CVuVector &in);\nvoid TransformPoint(CVuVector &out, const CMatrix &mat, const RwV3d &in);\nvoid TransformPoints(CVuVector *out, int n, const CMatrix &mat, const RwV3d *in, int stride);\nvoid TransformPoints(CVuVector *out, int n, const CMatrix &mat, const CVuVector *in);\n"
  },
  {
    "path": "src/math/math.cpp",
    "content": "#include \"common.h\"\n\n#include \"VuVector.h\"\n\n// TODO: move more stuff into here\n\n\nvoid TransformPoint(CVuVector &out, const CMatrix &mat, const CVuVector &in)\n{\n#ifdef GTA_PS2\n\t__asm__ __volatile__(\"\\n\\\n\t\tlqc2    vf01,0x0(%2)\\n\\\n\t\tlqc2    vf02,0x0(%1)\\n\\\n\t\tlqc2    vf03,0x10(%1)\\n\\\n\t\tlqc2    vf04,0x20(%1)\\n\\\n\t\tlqc2    vf05,0x30(%1)\\n\\\n\t\tvmulax.xyz\tACC,   vf02,vf01\\n\\\n\t\tvmadday.xyz\tACC,   vf03,vf01\\n\\\n\t\tvmaddaz.xyz\tACC,   vf04,vf01\\n\\\n\t\tvmaddw.xyz\tvf06,vf05,vf00\\n\\\n\t\tsqc2    vf06,0x0(%0)\\n\\\n\t\t\": : \"r\" (&out) , \"r\" (&mat) ,\"r\" (&in): \"memory\");\n#else\n\tout = mat * in;\n#endif\n}\n\nvoid TransformPoint(CVuVector &out, const CMatrix &mat, const RwV3d &in)\n{\n#ifdef GTA_PS2\n\t__asm__ __volatile__(\"\\n\\\n\t\tldr\t$8,0x0(%2)\\n\\\n\t\tldl\t$8,0x7(%2)\\n\\\n\t\tlw\t$9,0x8(%2)\\n\\\n\t\tpcpyld\t$10,$9,$8\\n\\\n\t\tqmtc2\t$10,vf01\\n\\\n\t\tlqc2    vf02,0x0(%1)\\n\\\n\t\tlqc2    vf03,0x10(%1)\\n\\\n\t\tlqc2    vf04,0x20(%1)\\n\\\n\t\tlqc2    vf05,0x30(%1)\\n\\\n\t\tvmulax.xyz\tACC,   vf02,vf01\\n\\\n\t\tvmadday.xyz\tACC,   vf03,vf01\\n\\\n\t\tvmaddaz.xyz\tACC,   vf04,vf01\\n\\\n\t\tvmaddw.xyz\tvf06,vf05,vf00\\n\\\n\t\tsqc2    vf06,0x0(%0)\\n\\\n\t\t\": : \"r\" (&out) , \"r\" (&mat) ,\"r\" (&in): \"memory\");\n#else\n\tout = mat * in;\n#endif\n}\n\nvoid TransformPoints(CVuVector *out, int n, const CMatrix &mat, const RwV3d *in, int stride)\n{\n#ifdef GTA_PS3\n\t__asm__ __volatile__(\"\\n\\\n\t\tpaddub\t$3,%4,$0\\n\\\n\t\tlqc2    vf02,0x0(%2)\\n\\\n\t\tlqc2    vf03,0x10(%2)\\n\\\n\t\tlqc2    vf04,0x20(%2)\\n\\\n\t\tlqc2    vf05,0x30(%2)\\n\\\n\t\tldr\t$8,0x0(%3)\\n\\\n\t\tldl\t$8,0x7(%3)\\n\\\n\t\tlw\t$9,0x8(%3)\\n\\\n\t\tpcpyld\t$10,$9,$8\\n\\\n\t\tqmtc2\t$10,vf01\\n\\\n\t1:\tvmulax.xyz\tACC,   vf02,vf01\\n\\\n\t\tvmadday.xyz\tACC,   vf03,vf01\\n\\\n\t\tvmaddaz.xyz\tACC,   vf04,vf01\\n\\\n\t\tvmaddw.xyz\tvf06,vf05,vf00\\n\\\n\t\tadd\t%3,%3,$3\\n\\\n\t\tldr\t$8,0x0(%3)\\n\\\n\t\tldl\t$8,0x7(%3)\\n\\\n\t\tlw\t$9,0x8(%3)\\n\\\n\t\tpcpyld\t$10,$9,$8\\n\\\n\t\tqmtc2\t$10,vf01\\n\\\n\t\taddi\t%1,%1,-1\\n\\\n\t\taddiu\t%0,%0,0x10\\n\\\n\t\tsqc2    vf06,-0x10(%0)\\n\\\n\t\tbnez\t%1,1b\\n\\\n\t\t\": : \"r\" (out) , \"r\" (n), \"r\" (&mat), \"r\" (in), \"r\" (stride): \"memory\");\n#else\n\twhile(n--){\n\t\t*out = mat * *in;\n\t\tin = (RwV3d*)((uint8*)in + stride);\n\t\tout++;\n\t}\n#endif\n}\n\nvoid TransformPoints(CVuVector *out, int n, const CMatrix &mat, const CVuVector *in)\n{\n#ifdef GTA_PS2\n\t__asm__ __volatile__(\"\\n\\\n\t\tlqc2    vf02,0x0(%2)\\n\\\n\t\tlqc2    vf03,0x10(%2)\\n\\\n\t\tlqc2    vf04,0x20(%2)\\n\\\n\t\tlqc2    vf05,0x30(%2)\\n\\\n\t\tlqc2    vf01,0x0(%3)\\n\\\n\t\tnop\\n\\\n\t1:\tvmulax.xyz\tACC,   vf02,vf01\\n\\\n\t\tvmadday.xyz\tACC,   vf03,vf01\\n\\\n\t\tvmaddaz.xyz\tACC,   vf04,vf01\\n\\\n\t\tvmaddw.xyz\tvf06,vf05,vf00\\n\\\n\t\tlqc2\tvf01,0x10(%3)\\n\\\n\t\taddiu\t%3,%3,0x10\\n\\\n\t\taddi\t%1,%1,-1\\n\\\n\t\taddiu\t%0,%0,0x10\\n\\\n\t\tsqc2    vf06,-0x10(%0)\\n\\\n\t\tbnez\t%1,1b\\n\\\n\t\t\": : \"r\" (out) , \"r\" (n), \"r\" (&mat) ,\"r\" (in): \"memory\");\n#else\n\twhile(n--){\n\t\t*out = mat * *in;\n\t\tin++;\n\t\tout++;\n\t}\n#endif\n}\n"
  },
  {
    "path": "src/math/maths.h",
    "content": "#pragma once\n\n// wrapper around float versions of functions\n// in gta they are in CMaths but that makes the code rather noisy\n\ninline float Sin(float x) { return sinf(x); }\ninline float Asin(float x) { return asinf(x); }\ninline float Cos(float x) { return cosf(x); }\ninline float Acos(float x) { return acosf(x); }\ninline float Tan(float x) { return tanf(x); }\ninline float Atan(float x) { return atanf(x); }\ninline float Atan2(float y, float x) { return atan2f(y, x); }\ninline float Abs(float x) { return fabs(x); }\ninline float Sqrt(float x) { return sqrtf(x); }\ninline float RecipSqrt(float x, float y) { return x/Sqrt(y); }\ninline float RecipSqrt(float x) { return RecipSqrt(1.0f, x); }\ninline float Pow(float x, float y) { return powf(x, y); }\ninline float Floor(float x) { return floorf(x); }\ninline float Ceil(float x) { return ceilf(x); }\n"
  },
  {
    "path": "src/modelinfo/BaseModelInfo.cpp",
    "content": "#include \"common.h\"\n\n#include \"templates.h\"\n#include \"TxdStore.h\"\n#include \"2dEffect.h\"\n#include \"BaseModelInfo.h\"\n#include \"ModelInfo.h\"\n#include \"ColModel.h\"\n\nCBaseModelInfo::CBaseModelInfo(ModelInfoType type)\n{\n\tm_colModel = nil;\n\tm_2dEffectsID = -1;\n\tm_objectId = -1;\n\tm_refCount = 0;\n\tm_txdSlot = -1;\n\tm_type = type;\n\tm_num2dEffects = 0;\n\tm_bOwnsColModel = false;\n}\n\nvoid\nCBaseModelInfo::Shutdown(void)\n{\n\tDeleteCollisionModel();\n\tDeleteRwObject();\n\tm_2dEffectsID = -1;\n\tm_num2dEffects = 0;\n\tm_txdSlot = -1;\n}\n\nvoid\nCBaseModelInfo::DeleteCollisionModel(void)\n{\n\tif(m_colModel && m_bOwnsColModel){\n\t\tif(m_colModel)\n\t\t\tdelete m_colModel;\n\t\tm_colModel = nil;\n\t}\n}\n\nvoid\nCBaseModelInfo::AddRef(void)\n{\n\tm_refCount++;\n\tAddTexDictionaryRef();\n}\n\nvoid\nCBaseModelInfo::RemoveRef(void)\n{\n\tm_refCount--;\n\tRemoveTexDictionaryRef();\n}\n\nvoid\nCBaseModelInfo::SetTexDictionary(const char *name)\n{\n\tint slot = CTxdStore::FindTxdSlot(name);\n\tif(slot == -1)\n\t\tslot = CTxdStore::AddTxdSlot(name);\n\tm_txdSlot = slot;\n}\n\nvoid\nCBaseModelInfo::AddTexDictionaryRef(void)\n{\n\tCTxdStore::AddRef(m_txdSlot);\n}\n\nvoid\nCBaseModelInfo::RemoveTexDictionaryRef(void)\n{\n\tCTxdStore::RemoveRef(m_txdSlot);\n}\n\nvoid\nCBaseModelInfo::Init2dEffects(void)\n{\n\tm_2dEffectsID = -1;\n\tm_num2dEffects = 0;\n}\n\nvoid\nCBaseModelInfo::Add2dEffect(C2dEffect *fx)\n{\n\tif(m_2dEffectsID >= 0)\n\t\tm_num2dEffects++;\n\telse{\n\t\tm_2dEffectsID = CModelInfo::Get2dEffectStore().GetIndex(fx);\n\t\tm_num2dEffects = 1;\n\t}\n}\n\nC2dEffect*\nCBaseModelInfo::Get2dEffect(int n)\n{\n\tif(m_2dEffectsID >= 0)\n\t\treturn CModelInfo::Get2dEffectStore().GetItem(m_2dEffectsID+n);\n\telse\n\t\treturn nil;\n}\n"
  },
  {
    "path": "src/modelinfo/BaseModelInfo.h",
    "content": "#pragma once\n\nstruct CColModel;\n\n#define MAX_MODEL_NAME (21)\n\nenum ModelInfoType\n{\n\tMITYPE_NA,\n\tMITYPE_SIMPLE,\n\tMITYPE_MLO,\t// unused but still in enum\n\tMITYPE_TIME,\n\tMITYPE_WEAPON,\n\tMITYPE_CLUMP,\n\tMITYPE_VEHICLE,\n\tMITYPE_PED,\n\tMITYPE_XTRACOMPS,\t// unused but still in enum\n\tMITYPE_HAND\t// xbox and mobile\n};\n\nclass C2dEffect;\n\nclass CBaseModelInfo\n{\nprotected:\n\tchar         m_name[MAX_MODEL_NAME];\n\tuint8        m_type;\n\tuint8        m_num2dEffects;\n\tbool         m_bOwnsColModel;\n\tCColModel   *m_colModel;\n\tint16        m_2dEffectsID;\n\tint16        m_objectId;\n\tuint16       m_refCount;\n\tint16        m_txdSlot;\n\npublic:\n\tCBaseModelInfo(ModelInfoType type);\n\tvirtual ~CBaseModelInfo() {}\n\tvirtual void Shutdown(void);\n\tvirtual void DeleteRwObject(void) = 0;\n\tvirtual RwObject *CreateInstance(void) = 0;\n\tvirtual RwObject *CreateInstance(RwMatrix *) = 0;\n\tvirtual RwObject *GetRwObject(void) = 0;\n\tvirtual void SetAnimFile(const char *file) {}\n\tvirtual void ConvertAnimFileIndex(void) {}\n\tvirtual int GetAnimFileIndex(void) { return -1; }\n\n\t// one day it becomes virtual\n\tuint8 GetModelType() const { return m_type; }\n\tbool IsBuilding(void) { return m_type == MITYPE_SIMPLE || m_type == MITYPE_TIME; }\n\tbool IsSimple(void) { return m_type == MITYPE_SIMPLE || m_type == MITYPE_TIME || m_type == MITYPE_WEAPON; }\n\tbool IsClump(void) { return m_type == MITYPE_CLUMP || m_type == MITYPE_PED || m_type == MITYPE_VEHICLE;\t}\n\tchar *GetModelName(void) { return m_name; }\n\tvoid SetModelName(const char *name) { strncpy(m_name, name, MAX_MODEL_NAME); }\n\tvoid SetColModel(CColModel *col, bool owns = false){\n\t\tm_colModel = col; m_bOwnsColModel = owns; }\n\tCColModel *GetColModel(void) { return m_colModel; }\n\tbool DoesOwnColModel(void) { return m_bOwnsColModel; }\n\tvoid DeleteCollisionModel(void);\n\tvoid ClearTexDictionary(void) { m_txdSlot = -1; }\n\tint16 GetObjectID(void) { return m_objectId; }\n\tvoid SetObjectID(int16 id) { m_objectId = id; }\n\tint16 GetTxdSlot(void) { return m_txdSlot; }\n\tvoid AddRef(void);\n\tvoid RemoveRef(void);\n\tvoid SetTexDictionary(const char *name);\n\tvoid AddTexDictionaryRef(void);\n\tvoid RemoveTexDictionaryRef(void);\n\tvoid Init2dEffects(void);\n\tvoid Add2dEffect(C2dEffect *fx);\n\tC2dEffect *Get2dEffect(int n);\n\tuint8 GetNum2dEffects() const { return m_num2dEffects; }\n\tuint16 GetNumRefs() const { return m_refCount; }\n};\n"
  },
  {
    "path": "src/modelinfo/ClumpModelInfo.cpp",
    "content": "#include \"common.h\"\n\n#include \"RwHelper.h\"\n#include \"General.h\"\n#include \"NodeName.h\"\n#include \"VisibilityPlugins.h\"\n#include \"ModelInfo.h\"\n#include \"AnimManager.h\"\n\nvoid\nCClumpModelInfo::DeleteRwObject(void)\n{\n\tif(m_clump){\n\t\tRpClumpDestroy(m_clump);\n\t\tm_clump = nil;\n\t\tRemoveTexDictionaryRef();\n\t\tif(GetAnimFileIndex() != -1)\n\t\t\tCAnimManager::RemoveAnimBlockRef(GetAnimFileIndex());\n\t}\n}\n\nstatic RpAtomic*\nSetHierarchyForSkinAtomic(RpAtomic *atomic, void *data)\n{\n\tRpSkinAtomicSetHAnimHierarchy(atomic, (RpHAnimHierarchy*)data);\n\treturn nil;\n}\n\nRwObject*\nCClumpModelInfo::CreateInstance(void)\n{\n\tif(m_clump == nil)\n\t\treturn nil;\n\tRpClump *clone = RpClumpClone(m_clump);\n\tif(IsClumpSkinned(clone)){\n\t\tRpHAnimHierarchy *hier;\n\t\tRpHAnimAnimation *anim;\n\n\t\thier = GetAnimHierarchyFromClump(clone);\n\t\tassert(hier);\n\t\tRpClumpForAllAtomics(clone, SetHierarchyForSkinAtomic, hier);\n\t\tanim = HAnimAnimationCreateForHierarchy(hier);\n\t\tRpHAnimHierarchySetCurrentAnim(hier, anim);\n\t\tRpHAnimHierarchySetFlags(hier, (RpHAnimHierarchyFlag)(rpHANIMHIERARCHYUPDATEMODELLINGMATRICES|rpHANIMHIERARCHYUPDATELTMS));\n\t}\n\treturn (RwObject*)clone;\n}\n\nRwObject*\nCClumpModelInfo::CreateInstance(RwMatrix *m)\n{\n\tif(m_clump){\n\t\tRpClump *clump = (RpClump*)CreateInstance();\n\t\t*RwFrameGetMatrix(RpClumpGetFrame(clump)) = *m;\n\t\treturn (RwObject*)clump;\n\t}\n\treturn nil;\n}\n\nRpAtomic*\nCClumpModelInfo::SetAtomicRendererCB(RpAtomic *atomic, void *data)\n{\n\tCVisibilityPlugins::SetAtomicRenderCallback(atomic, (RpAtomicCallBackRender)data);\n\treturn atomic;\n}\n\nvoid\nCClumpModelInfo::SetClump(RpClump *clump)\n{\n\tm_clump = clump;\n\tCVisibilityPlugins::SetClumpModelInfo(m_clump, this);\n\tAddTexDictionaryRef();\n\tif(GetAnimFileIndex() != -1)\n\t\tCAnimManager::AddAnimBlockRef(GetAnimFileIndex());\n\tif(IsClumpSkinned(clump)){\n\t\tint i;\n\t\tRpHAnimHierarchy *hier;\n\t\tRpAtomic *skinAtomic;\n\t\tRpSkin *skin;\n\n\t\thier = GetAnimHierarchyFromClump(clump);\n\t\tassert(hier);\n\t\tRpClumpForAllAtomics(clump, SetHierarchyForSkinAtomic, hier);\n\t\tskinAtomic = GetFirstAtomic(clump);\n\n\t\tassert(skinAtomic);\n\t\tskin = RpSkinGeometryGetSkin(RpAtomicGetGeometry(skinAtomic));\n\t\t// ignore const\n\t\tfor(i = 0; i < RpGeometryGetNumVertices(RpAtomicGetGeometry(skinAtomic)); i++){\n\t\t\tRwMatrixWeights *weights = (RwMatrixWeights*)&RpSkinGetVertexBoneWeights(skin)[i];\n\t\t\tfloat sum = weights->w0 + weights->w1 + weights->w2 + weights->w3;\n\t\t\tweights->w0 /= sum;\n\t\t\tweights->w1 /= sum;\n\t\t\tweights->w2 /= sum;\n\t\t\tweights->w3 /= sum;\n\t\t}\n\t\tRpHAnimHierarchySetFlags(hier, (RpHAnimHierarchyFlag)(rpHANIMHIERARCHYUPDATEMODELLINGMATRICES|rpHANIMHIERARCHYUPDATELTMS));\n\t}\n}\n\nvoid\nCClumpModelInfo::SetAnimFile(const char *file)\n{\n\tif(strcasecmp(file, \"null\") == 0)\n\t\treturn;\n\n\tm_animFileName = new char[strlen(file)+1];\n\tstrcpy(m_animFileName, file);\n}\n\nvoid\nCClumpModelInfo::ConvertAnimFileIndex(void)\n{\n\tif(m_animFileIndex != -1){\n\t\t// we have a string pointer in that union\n\t\tint32 index = CAnimManager::GetAnimationBlockIndex(m_animFileName);\n\t\tdelete[] m_animFileName;\n\t\tm_animFileIndex = index;\n\t}\n}\n\nvoid\nCClumpModelInfo::SetFrameIds(RwObjectNameIdAssocation *assocs)\n{\n\tint32 i;\n\tRwObjectNameAssociation objname;\n\n\tfor(i = 0; assocs[i].name; i++)\n\t\tif((assocs[i].flags & CLUMP_FLAG_NO_HIERID) == 0){\n\t\t\tobjname.frame = nil;\n\t\t\tobjname.name = assocs[i].name;\n\t\t\tRwFrameForAllChildren(RpClumpGetFrame(m_clump), FindFrameFromNameWithoutIdCB, &objname);\n\t\t\tif(objname.frame)\n\t\t\t\tCVisibilityPlugins::SetFrameHierarchyId(objname.frame, assocs[i].hierId);\n\t\t}\n}\n\nRwFrame*\nCClumpModelInfo::FindFrameFromIdCB(RwFrame *frame, void *data)\n{\n\tRwObjectIdAssociation *assoc = (RwObjectIdAssociation*)data;\n\n\tif(CVisibilityPlugins::GetFrameHierarchyId(frame) == assoc->id){\n\t\tassoc->frame = frame;\n\t\treturn nil;\n\t}\n\tRwFrameForAllChildren(frame, FindFrameFromIdCB, assoc);\n\treturn assoc->frame ? nil : frame;\n}\n\n// unused\nRwFrame*\nCClumpModelInfo::FindFrameFromNameCB(RwFrame *frame, void *data)\n{\n\tRwObjectNameAssociation *assoc = (RwObjectNameAssociation*)data;\n\n\tif(!CGeneral::faststricmp(GetFrameNodeName(frame), assoc->name)){\n\t\tassoc->frame = frame;\n\t\treturn nil;\n\t}\n\tRwFrameForAllChildren(frame, FindFrameFromNameCB, assoc);\n\treturn assoc->frame ? nil : frame;\n}\n\nRwFrame*\nCClumpModelInfo::FindFrameFromNameWithoutIdCB(RwFrame *frame, void *data)\n{\n\tRwObjectNameAssociation *assoc = (RwObjectNameAssociation*)data;\n\n\tif(CVisibilityPlugins::GetFrameHierarchyId(frame) == 0 &&\n\t   !CGeneral::faststricmp(GetFrameNodeName(frame), assoc->name)){\n\t\tassoc->frame = frame;\n\t\treturn nil;\n\t}\n\tRwFrameForAllChildren(frame, FindFrameFromNameWithoutIdCB, assoc);\n\treturn assoc->frame ? nil : frame;\n}\n\nRwFrame*\nCClumpModelInfo::FillFrameArrayCB(RwFrame *frame, void *data)\n{\n\tint32 id;\n\tRwFrame **frames = (RwFrame**)data;\n\tid = CVisibilityPlugins::GetFrameHierarchyId(frame);\n\tif(id > 0)\n\t\tframes[id] = frame;\n\tRwFrameForAllChildren(frame, FillFrameArrayCB, data);\n\treturn frame;\n}\n\nvoid\nCClumpModelInfo::FillFrameArray(RpClump *clump, RwFrame **frames)\n{\n\tRwFrameForAllChildren(RpClumpGetFrame(clump), FillFrameArrayCB, frames);\n}\n\nRwFrame*\nCClumpModelInfo::GetFrameFromId(RpClump *clump, int32 id)\n{\n\tRwObjectIdAssociation assoc;\n\tassoc.id = id;\n\tassoc.frame = nil;\n\tRwFrameForAllChildren(RpClumpGetFrame(clump), FindFrameFromIdCB, &assoc);\n\treturn assoc.frame;\n}\n"
  },
  {
    "path": "src/modelinfo/ClumpModelInfo.h",
    "content": "#pragma once\n\n#include \"BaseModelInfo.h\"\n\nstruct RwObjectNameIdAssocation\n{\n\tconst char *name;\n\tint32 hierId;\n\tuint32 flags;\n};\n\nstruct RwObjectNameAssociation\n{\n\tconst char *name;\n\tRwFrame *frame;\n};\n\nstruct RwObjectIdAssociation\n{\n\tint32 id;\n\tRwFrame *frame;\n};\n\nenum {\n\tCLUMP_FLAG_NO_HIERID = 0x1,\n};\n\n\nclass CClumpModelInfo : public CBaseModelInfo\n{\npublic:\n\tRpClump *m_clump;\n\tunion {\n\t\tint32 m_animFileIndex;\n\t\tchar *m_animFileName;\n\t};\n\n\tCClumpModelInfo(void) : CBaseModelInfo(MITYPE_CLUMP) { m_animFileIndex = -1; }\n\tCClumpModelInfo(ModelInfoType id) : CBaseModelInfo(id) { m_animFileIndex = -1; }\n\t~CClumpModelInfo() {}\n\tvoid DeleteRwObject(void);\n\tRwObject *CreateInstance(void);\n\tRwObject *CreateInstance(RwMatrix *);\n\tRwObject *GetRwObject(void) { return (RwObject*)m_clump; }\n\n\tvirtual void SetClump(RpClump *);\n\tvirtual void SetAnimFile(const char *file);\n\tvirtual void ConvertAnimFileIndex(void);\n\tvirtual int GetAnimFileIndex(void) { return m_animFileIndex; }\n\n\tstatic RpAtomic *SetAtomicRendererCB(RpAtomic *atomic, void *data);\n\tvoid SetFrameIds(RwObjectNameIdAssocation *assocs);\n\tstatic RwFrame *FindFrameFromNameCB(RwFrame *frame, void *data);\n\tstatic RwFrame *FindFrameFromNameWithoutIdCB(RwFrame *frame, void *data);\n\tstatic RwFrame *FindFrameFromIdCB(RwFrame *frame, void *data);\n\tstatic void FillFrameArray(RpClump *clump, RwFrame **frames);\n\tstatic RwFrame *FillFrameArrayCB(RwFrame *frame, void *data);\n\tstatic RwFrame *GetFrameFromId(RpClump *clump, int32 id);\n};\n//static_assert(sizeof(CClumpModelInfo) == 0x34, \"CClumpModelInfo: error\");\n"
  },
  {
    "path": "src/modelinfo/ModelIndices.cpp",
    "content": "#include \"common.h\"\n\n#include \"General.h\"\n#include \"ModelIndices.h\"\n\n#define X(name, var) int16 var = -1;\n\tMODELINDICES\n#undef X\n\nvoid\nInitModelIndices(void)\n{\n#define X(name, var) var = -1;\n\tMODELINDICES\n#undef X\n}\n\nvoid\nMatchModelString(const char *modelname, int16 id)\n{\n#define X(name, var) \\\n\tif(!CGeneral::faststrcmp(name, modelname)){ \\\n\t\tvar = id; \\\n\t\treturn; \\\n\t}\n\tMODELINDICES\n#undef X\n}\n\nvoid\nTestModelIndices(void)\n{\n\t;\n}\n"
  },
  {
    "path": "src/modelinfo/ModelIndices.h",
    "content": "#pragma once\n\n#include \"ModelInfo.h\"\n\n#define MODELINDICES \\\n\tX(\"fire_hydrant\",\tMI_FIRE_HYDRANT) \\\n\tX(\"phonesign\",\t\tMI_PHONESIGN) \\\n\tX(\"noparkingsign1\",\tMI_NOPARKINGSIGN1) \\\n\tX(\"bussign1\",\t\tMI_BUSSIGN1) \\\n\tX(\"roadworkbarrier1\",\tMI_ROADWORKBARRIER1) \\\n\tX(\"dump1\",\t\tMI_DUMP1) \\\n\tX(\"trafficcone\",\tMI_TRAFFICCONE) \\\n\tX(\"newsstand1\",\t\tMI_NEWSSTAND) \\\n\tX(\"postbox1\",\t\tMI_POSTBOX1) \\\n\tX(\"bin1\",\t\tMI_BIN) \\\n\tX(\"wastebin\",\t\tMI_WASTEBIN) \\\n\tX(\"phonebooth1\",\tMI_PHONEBOOTH1) \\\n\tX(\"parkingmeter\",\tMI_PARKINGMETER) \\\n\tX(\"parkingmeterg\",\tMI_PARKINGMETER2) \\\n\tX(\"mall_fans\",\t\tMI_MALLFAN) \\\n\tX(\"htl_fan_rotate_nt\",\tMI_HOTELFAN_NIGHT) \\\n\tX(\"htl_fan_rotate_dy\",\tMI_HOTELFAN_DAY) \\\n\tX(\"hotroomfan\",\t\tMI_HOTROOMFAN) \\\n\tX(\"trafficlight1\",\tMI_TRAFFICLIGHTS) \\\n\tX(\"MTraffic4\",\t\tMI_TRAFFICLIGHTS_VERTICAL) \\\n\tX(\"MTraffic1\",\t\tMI_TRAFFICLIGHTS_MIAMI) \\\n\tX(\"MTraffic2\",\t\tMI_TRAFFICLIGHTS_TWOVERTICAL) \\\n\tX(\"lamppost1\",\t\tMI_SINGLESTREETLIGHTS1) \\\n\tX(\"lamppost2\",\t\tMI_SINGLESTREETLIGHTS2) \\\n\tX(\"lamppost3\",\t\tMI_SINGLESTREETLIGHTS3) \\\n\tX(\"doublestreetlght1\",\tMI_DOUBLESTREETLIGHTS) \\\n\tX(\"Streetlamp1\",\tMI_STREETLAMP1) \\\n\tX(\"Streetlamp2\",\tMI_STREETLAMP2) \\\n\tX(\"veg_tree3\",\t\tMI_TREE2) \\\n\tX(\"veg_treea1\",\t\tMI_TREE3) \\\n\tX(\"veg_treeb1\",\t\tMI_TREE6) \\\n\tX(\"veg_treea3\",\t\tMI_TREE8) \\\n\tX(\"doc_crane_cab0\",\tMODELID_CRANE_1) \\\n\tX(\"doc_crane_cab01\",\tMODELID_CRANE_2) \\\n\tX(\"doc_crane_cab02\",\tMODELID_CRANE_3) \\\n\tX(\"doc_crane_cab03\",\tMODELID_CRANE_4) \\\n\tX(\"boatcranelg0\",\tMODELID_CRANE_5) \\\n\tX(\"LODnetopa0\",\t\tMODELID_CRANE_6) \\\n\tX(\"package1\",\t\tMI_COLLECTABLE1) \\\n\tX(\"Money\",\t\tMI_MONEY) \\\n\tX(\"barrel1\",\t\tMI_CARMINE) \\\n\tX(\"dk_paynspraydoor\",\tMI_GARAGEDOOR2) \\\n\tX(\"dk_waretankdoor1\",\tMI_GARAGEDOOR3) \\\n\tX(\"hav_garagedoor1\",\tMI_GARAGEDOOR4) \\\n\tX(\"hav_garagedoor02\",\tMI_GARAGEDOOR5) \\\n\tX(\"hav_garagedoor03\",\tMI_GARAGEDOOR6) \\\n\tX(\"hav_garagedoor04\",\tMI_GARAGEDOOR7) \\\n\tX(\"lh_showdoor03\",\tMI_GARAGEDOOR9) \\\n\tX(\"lh_showdoor1\",\tMI_GARAGEDOOR10) \\\n\tX(\"lhtankdoor\",\t\tMI_GARAGEDOOR11) \\\n\tX(\"nbtgardoor\",\t\tMI_GARAGEDOOR12) \\\n\tX(\"dk_camjonesdoor\",\tMI_GARAGEDOOR13) \\\n\tX(\"nbtgardoor02\",\tMI_GARAGEDOOR14) \\\n\tX(\"dt_savedra\",\t\tMI_GARAGEDOOR15) \\\n\tX(\"dt_savedrb\",\t\tMI_GARAGEDOOR16) \\\n\tX(\"dk_bombdoor\",\tMI_GARAGEDOOR18) \\\n\tX(\"haiwshpnsdoor\",\tMI_GARAGEDOOR19) \\\n\tX(\"wshpnsdoor\",\t\tMI_GARAGEDOOR20) \\\n\tX(\"nbecpnsdoor\",\tMI_GARAGEDOOR21) \\\n\tX(\"nbtgardoor03\",\tMI_GARAGEDOOR22) \\\n\tX(\"dt_savedrc\",\t\tMI_GARAGEDOOR23) \\\n\tX(\"dt_savedrd\",\t\tMI_GARAGEDOOR24) \\\n\tX(\"man_frntstepGD\",\tMI_GARAGEDOOR25) \\\n\tX(\"svegrgedoor\",\tMI_GARAGEDOOR26) \\\n\tX(\"barrel2\",\t\tMI_NAUTICALMINE) \\\n\tX(\"briefcase\",\t\tMI_BRIEFCASE) \\\n\tX(\"wglasssmash\",\tMI_GLASS1) \\\n\tX(\"glassfx_composh\",\tMI_GLASS8) \\\n\tX(\"barrel4\",\t\tMI_EXPLODINGBARREL) \\\n\tX(\"adrenaline\",\t\tMI_PICKUP_ADRENALINE) \\\n\tX(\"bodyarmour\",\t\tMI_PICKUP_BODYARMOUR) \\\n\tX(\"info\",\t\tMI_PICKUP_INFO) \\\n\tX(\"health\",\t\tMI_PICKUP_HEALTH) \\\n\tX(\"bonus\",\t\tMI_PICKUP_BONUS) \\\n\tX(\"bribe\",\t\tMI_PICKUP_BRIBE) \\\n\tX(\"killfrenzy\",\t\tMI_PICKUP_KILLFRENZY) \\\n\tX(\"camerapickup\",\tMI_PICKUP_CAMERA) \\\n\tX(\"bigdollar\",\t\tMI_PICKUP_REVENUE) \\\n\tX(\"pickupsave\",\t\tMI_PICKUP_SAVEGAME) \\\n\tX(\"property_locked\",\tMI_PICKUP_PROPERTY) \\\n\tX(\"property_fsale\",\tMI_PICKUP_PROPERTY_FORSALE) \\\n\tX(\"clothesp\",\t\tMI_PICKUP_CLOTHES) \\\n\tX(\"bollardlight\",\tMI_BOLLARDLIGHT) \\\n\tX(\"bar_barrier10\",\tMI_FENCE) \\\n\tX(\"bar_barrier12\",\tMI_FENCE2) \\\n\tX(\"petrolpump\",\t\tMI_PETROLPUMP) \\\n\tX(\"washgaspump\",\tMI_PETROLPUMP2) \\\n\tX(\"bouy\",\t\tMI_BUOY) \\\n\tX(\"parktable1\",\t\tMI_PARKTABLE) \\\n\tX(\"lamppost1\",\t\tMI_LAMPPOST1) \\\n\tX(\"veg_palm04\",\t\tMI_VEG_PALM01) \\\n\tX(\"veg_palwee02\",\tMI_VEG_PALM02) \\\n\tX(\"veg_palmkbb11\",\tMI_VEG_PALM03) \\\n\tX(\"veg_palmkb4\",\tMI_VEG_PALM04) \\\n\tX(\"veg_palm02\",\t\tMI_VEG_PALM05) \\\n\tX(\"veg_palmkb3\",\tMI_VEG_PALM06) \\\n\tX(\"veg_palmbig14\",\tMI_VEG_PALM07) \\\n\tX(\"veg_palm01\",\t\tMI_VEG_PALM08) \\\n\tX(\"mlamppost\",\t\tMI_MLAMPPOST) \\\n\tX(\"roadworkbarrier1\",\tMI_BARRIER1) \\\n\tX(\"littleha_police\",\tMI_LITTLEHA_POLICE) \\\n\tX(\"telgrphpole02\",\tMI_TELPOLE02) \\\n\tX(\"trafficlight1\",\tMI_TRAFFICLIGHT01) \\\n\tX(\"parkbench1\",\t\tMI_PARKBENCH) \\\n\tX(\"plc_stinger\",\tMI_PLC_STINGER) \\\n\tX(\"od_lightbeam\",\tMI_LIGHTBEAM) \\\n\tX(\"ap_radar1_01\",\tMI_AIRPORTRADAR) \\\n\tX(\"rcbomb\",\t\tMI_RCBOMB) \\\n\tX(\"beachball\",\t\tMI_BEACHBALL) \\\n\tX(\"sandcastle1\",\tMI_SANDCASTLE1) \\\n\tX(\"sandcastle2\",\tMI_SANDCASTLE2) \\\n\tX(\"jellyfish\",\t\tMI_JELLYFISH) \\\n\tX(\"jellyfish01\",\tMI_JELLYFISH01) \\\n\tX(\"fish1single\",\tMI_FISH1SINGLE) \\\n\tX(\"fish1s\",\t\tMI_FISH1S) \\\n\tX(\"fish2single\",\tMI_FISH2SINGLE) \\\n\tX(\"fish2s\",\t\tMI_FISH2S) \\\n\tX(\"fish3single\",\tMI_FISH3SINGLE) \\\n\tX(\"fish3s\",\t\tMI_FISH3S) \\\n\tX(\"turtle\",\t\tMI_TURTLE) \\\n\tX(\"dolphin\",\t\tMI_DOLPHIN) \\\n\tX(\"shark\",\t\tMI_SHARK) \\\n\tX(\"submarine\",\t\tMI_SUBMARINE) \\\n\tX(\"Esc_step\",\t\tMI_ESCALATORSTEP) \\\n\tX(\"lounge_wood_up\",\tMI_LOUNGE_WOOD_UP) \\\n\tX(\"lounge_towel_up\",\tMI_LOUNGE_TOWEL_UP) \\\n\tX(\"lounge_wood_dn\",\tMI_LOUNGE_WOOD_DN) \\\n\tX(\"lotion\",\t\tMI_LOTION) \\\n\tX(\"beachtowel01\",\tMI_BEACHTOWEL01) \\\n\tX(\"beachtowel02\",\tMI_BEACHTOWEL02) \\\n\tX(\"beachtowel03\",\tMI_BEACHTOWEL03) \\\n\tX(\"beachtowel04\",\tMI_BEACHTOWEL04) \\\n\tX(\"blimp_night\",\tMI_BLIMP_NIGHT) \\\n\tX(\"blimp_day\",\t\tMI_BLIMP_DAY) \\\n\tX(\"yt_main_body\",\tMI_YT_MAIN_BODY) \\\n\tX(\"yt_main_body2\",\tMI_YT_MAIN_BODY2)\n\n#define X(name, var) extern int16 var;\n\tMODELINDICES\n#undef X\n\n// and some hardcoded ones\n// expand as needed\nenum\n{\n\tMI_PLAYER = 0,\n\tMI_COP,\n\tMI_SWAT,\n\tMI_FBI,\n\tMI_ARMY,\n\tMI_MEDIC,\n\tMI_FIREMAN,\n\tMI_MALE01,\n\n\tMI_HFYST = 9,\n\tMI_HFOST,\n\tMI_HMYST,\n\tMI_HMOST,\n\tMI_HFYRI,\n\tMI_HFORI,\n\tMI_HMYRI,\n\tMI_HMORI,\n\tMI_HFYBE,\n\tMI_HFOBE,\n\tMI_HMYBE,\n\tMI_HMOBE,\n\tMI_HFYBU,\n\tMI_HFYMD,\n\tMI_HFYCG,\n\tMI_HFYPR,\n\tMI_HFOTR,\n\tMI_HMOTR,\n\tMI_HMYAP,\n\tMI_HMOCA,\n\tMI_TAXI_D = MI_HMOCA,\n\tMI_BMODK,\n\tMI_BMYKR,\n\tMI_BFYST,\n\tMI_BFOST,\n\tMI_BMYST,\n\tMI_BMOST,\n\tMI_BFYRI,\n\tMI_BFORI,\n\tMI_BMYRI,\n\tMI_BFYBE,\n\tMI_BMYBE,\n\tMI_BFOBE,\n\tMI_BMOBE,\n\tMI_BMYBU,\n\tMI_BFYPR,\n\tMI_BFOTR,\n\tMI_BMOTR,\n\tMI_BMYPI,\n\tMI_BMYBB,\n\tMI_WMYCR,\n\tMI_WFYST,\n\tMI_WFOST,\n\tMI_WMYST,\n\tMI_WMOST,\n\tMI_WFYRI,\n\tMI_WFORI,\n\tMI_WMYRI,\n\tMI_WMORI,\n\tMI_WFYBE,\n\tMI_WMYBE,\n\tMI_WFOBE,\n\tMI_WMOBE,\n\tMI_WMYCW,\n\tMI_WMYGO,\n\tMI_WFOGO,\n\tMI_WMOGO,\n\tMI_WFYLG,\n\tMI_WMYLG,\n\tMI_WFYBU,\n\tMI_WMYBU,\n\tMI_WMOBU,\n\tMI_WFYPR,\n\tMI_WFOTR,\n\tMI_WMOTR,\n\tMI_WMYPI,\n\tMI_WMOCA,\n\tMI_WFYJG,\n\tMI_WMYJG,\n\tMI_WFYSK,\n\tMI_WMYSK,\n\tMI_WFYSH,\n\tMI_WFOSH,\n\tMI_JFOTO,\n\tMI_JMOTO,\n\n\tMI_CBA,// = 83,\n\tMI_CBB,\n\tMI_HNA,\n\tMI_HNB,\n\tMI_SGA,\n\tMI_SGB,\n\tMI_CLA,\n\tMI_CLB,\n\tMI_GDA,\n\tMI_GDB,\n\tMI_BKA,\n\tMI_BKB,\n\tMI_PGA,\n\tMI_PGB,\n\tMI_VICE1,\n\tMI_VICE2,\n\tMI_VICE3,\n\tMI_VICE4,\n\tMI_VICE5,\n\tMI_VICE6,\n\tMI_VICE7,\n\tMI_VICE8,\n\tMI_WFYG1,\n\tMI_WFYG2,// = 106,\t// last regular ped\n\t// three more peds possible\n\tMI_SPECIAL01 = 109,\n\tMI_SPECIAL02,\n\tMI_SPECIAL03,\n\tMI_SPECIAL04,\n\tMI_SPECIAL05,\n\tMI_SPECIAL06,\n\tMI_SPECIAL07,\n\tMI_SPECIAL08,\n\tMI_SPECIAL09,\n\tMI_SPECIAL10,\n\tMI_SPECIAL11,\n\tMI_SPECIAL12,\n\tMI_SPECIAL13,\n\tMI_SPECIAL14,\n\tMI_SPECIAL15,\n\tMI_SPECIAL16,\n\tMI_SPECIAL17,\n\tMI_SPECIAL18,\n\tMI_SPECIAL19,\n\tMI_SPECIAL20,\n\tMI_SPECIAL21,// = 129,\n\n\tMI_LAST_PED = MI_SPECIAL21,\n\tMI_FIRST_VEHICLE,\n\n\tMI_LANDSTAL = MI_FIRST_VEHICLE,\n\tMI_IDAHO,\n\tMI_STINGER,\n\tMI_LINERUN,\n\tMI_PEREN,\n\tMI_SENTINEL,\n\tMI_RIO,\n\tMI_FIRETRUCK,\n\tMI_TRASH,\n\tMI_STRETCH,\n\tMI_MANANA,\n\tMI_INFERNUS,\n\tMI_VOODOO,\n\tMI_PONY,\n\tMI_MULE,\n\tMI_CHEETAH,\n\tMI_AMBULAN,\n\tMI_FBICAR,\n\tMI_MOONBEAM,\n\tMI_ESPERANT,\n\tMI_TAXI,\n\tMI_WASHING,\n\tMI_BOBCAT,\n\tMI_MRWHOOP,\n\tMI_BFINJECT,\n\tMI_HUNTER,\n\tMI_POLICE,\n\tMI_ENFORCER,\n\tMI_SECURICA,\n\tMI_BANSHEE,\n\tMI_PREDATOR,\n\tMI_BUS,\n\tMI_RHINO,\n\tMI_BARRACKS,\n\tMI_CUBAN,\n\tMI_CHOPPER,\n\tMI_ANGEL,\n\tMI_COACH,\n\tMI_CABBIE,\n\tMI_STALLION,\n\tMI_RUMPO,\n\tMI_RCBANDIT,\n\tMI_ROMERO,\n\tMI_PACKER,\n\tMI_SENTXS,\n\tMI_ADMIRAL,\n\tMI_SQUALO,\n\tMI_SEASPAR,\n\tMI_PIZZABOY,\n\tMI_GANGBUR,\n\tMI_AIRTRAIN,\n\tMI_DEADDODO,\n\tMI_SPEEDER,\n\tMI_REEFER,\n\tMI_TROPIC,\n\tMI_FLATBED,\n\tMI_YANKEE,\n\tMI_CADDY,\n\tMI_ZEBRA,\n\tMI_TOPFUN,\n\tMI_SKIMMER,\n\tMI_PCJ600,\n\tMI_FAGGIO,\n\tMI_FREEWAY,\n\tMI_RCBARON,\n\tMI_RCRAIDER,\n\tMI_GLENDALE,\n\tMI_OCEANIC,\n\tMI_SANCHEZ,\n\tMI_SPARROW,\n\tMI_PATRIOT,\n\tMI_LOVEFIST,\n\tMI_COASTG,\n\tMI_DINGHY,\n\tMI_HERMES,\n\tMI_SABRE,\n\tMI_SABRETUR,\n\tMI_PHEONIX,\n\tMI_WALTON,\n\tMI_REGINA,\n\tMI_COMET,\n\tMI_DELUXO,\n\tMI_BURRITO,\n\tMI_SPAND,\n\tMI_MARQUIS,\n\tMI_BAGGAGE,\n\tMI_KAUFMAN,\n\tMI_MAVERICK,\n\tMI_VCNMAV,\n\tMI_RANCHER,\n\tMI_FBIRANCH,\n\tMI_VIRGO,\n\tMI_GREENWOO,\n\tMI_JETMAX,\n\tMI_HOTRING,\n\tMI_SANDKING,\n\tMI_BLISTAC,\n\tMI_POLMAV,\n\tMI_BOXVILLE,\n\tMI_BENSON,\n\tMI_MESA,\n\tMI_RCGOBLIN,\n\tMI_HOTRINA,\n\tMI_HOTRINB,\n\tMI_BLOODRA,\n\tMI_BLOODRB,\n\tMI_VICECHEE,\n\n\t// HACK\n\tMI_TRAIN = -1,\n\tMI_DODO = -2,\n\n\tMI_LAST_VEHICLE = MI_VICECHEE,\n\n\tMI_WHEEL_RIM,\n\tMI_WHEEL_OFFROAD,\n\tMI_WHEEL_TRUCK,\n\n\tMI_CAR_DOOR,// = 240,\n\tMI_CAR_BUMPER,\n\tMI_CAR_PANEL,\n\tMI_CAR_BONNET,\n\tMI_CAR_BOOT,\n\tMI_CAR_WHEEL,\n\tMI_BODYPARTA,\n\tMI_BODYPARTB,\n\n\tMI_WHEEL_SPORT = 250,\n\tMI_WHEEL_SALOON,\n\tMI_WHEEL_LIGHTVAN,\n\tMI_WHEEL_CLASSIC,\n\tMI_WHEEL_ALLOY,\n\tMI_WHEEL_LIGHTTRUCK,\n\tMI_WHEEL_SMALLCAR,\n\n\tMI_AIRTRAIN_VLO, // = 257,\n\tMI_MOBILE,\n\n\tMI_BRASS_KNUCKLES, // 259\n\tMI_SCREWDRIVER,\n\tMI_GOLFCLUB,\n\tMI_NIGHTSTICK,\n\tMI_KNIFE,\n\tMI_BASEBALL_BAT,\n\tMI_HAMMER,\n\tMI_MEAT_CLEAVER,\n\tMI_MACHETE,\n\tMI_KATANA,\n\tMI_CHAINSAW,\n\tMI_GRENADE,\n\tMI_TEARGAS,\n\tMI_MOLOTOV,\n\tMI_MISSILE,\n\tMI_COLT45,\n\tMI_PYTHON,\n\tMI_RUGER,\n\tMI_SHOTGUN,\n\tMI_SPAS12_SHOTGUN,\n\tMI_STUBBY_SHOTGUN,\n\tMI_M4,\n\tMI_TEC9,\n\tMI_UZI,\n\tMI_SILENCEDINGRAM,\n\tMI_MP5,\n\tMI_SNIPERRIFLE,\n\tMI_LASERSCOPE,\n\tMI_ROCKETLAUNCHER,\n\tMI_FLAMETHROWER,\n\tMI_M60,\n\tMI_MINIGUN,\n\tMI_BOMB,\n\tMI_CAMERA,\n\tMI_FINGERS,\n\tMI_MINIGUN2,\n\n\tMI_CUTOBJ01,// = 295,\n\tMI_CUTOBJ02,\n\tMI_CUTOBJ03,\n\tMI_CUTOBJ04,\n\tMI_CUTOBJ05,\n\n\n\tNUM_DEFAULT_MODELS,// = 300\n};\n\nenum{\n\tNUM_OF_SPECIAL_CHARS = 21,\n\tNUM_OF_CUTSCENE_OBJECTS = 5\n};\n\nvoid InitModelIndices(void);\nvoid MatchModelString(const char *name, int16 id);\nvoid TestModelIndices(void);\n\ninline bool\nIsGlass(int16 id)\n{\n\tCSimpleModelInfo *mi = (CSimpleModelInfo*)CModelInfo::GetModelInfo(id);\n\treturn mi->IsBuilding() && (mi->m_isCodeGlass || mi->m_isArtistGlass);\n}\n\ninline bool\nIsTrafficLight(int16 id)\n{\n\treturn id == MI_TRAFFICLIGHTS ||\n\t\tid == MI_TRAFFICLIGHTS_VERTICAL ||\n\t\tid == MI_TRAFFICLIGHTS_MIAMI ||\n\t\tid == MI_TRAFFICLIGHTS_TWOVERTICAL;\n}\n\ninline bool\nIsLightWithoutShift(int16 id)\n{\n\treturn id == MI_TRAFFICLIGHTS ||\n\t\tid == MI_SINGLESTREETLIGHTS1 ||\n\t\tid == MI_SINGLESTREETLIGHTS2 ||\n\t\tid == MI_SINGLESTREETLIGHTS3 ||\n\t\tid == MI_DOUBLESTREETLIGHTS;\n}\n\ninline bool\nIsLightWithPreRenderEffects(int16 id)\n{\n\treturn IsTrafficLight(id) ||\n\t\tid == MI_SINGLESTREETLIGHTS1 ||\n\t\tid == MI_SINGLESTREETLIGHTS2 ||\n\t\tid == MI_SINGLESTREETLIGHTS3 ||\n\t\tid == MI_DOUBLESTREETLIGHTS;\n}\n\ninline bool\nIsLightThatNeedsRepositioning(int16 id)\n{\n\treturn id == MI_SINGLESTREETLIGHTS1 ||\n\t\tid == MI_SINGLESTREETLIGHTS2 ||\n\t\tid == MI_SINGLESTREETLIGHTS3 ||\n\t\tid == MI_TRAFFICLIGHTS_MIAMI ||\n\t\tid == MI_TRAFFICLIGHTS_TWOVERTICAL ||\n\t\tid == MI_MLAMPPOST ||\n\t\tid == MI_STREETLAMP1 ||\n\t\tid == MI_STREETLAMP2;\n}\n\ninline bool\nIsLightObject(int16 id)\n{\n\treturn id == MI_TRAFFICLIGHTS_MIAMI ||\n\t\tid == MI_MLAMPPOST ||\n\t\tid == MI_SINGLESTREETLIGHTS1 ||\n\t\tid == MI_SINGLESTREETLIGHTS2 ||\n\t\tid == MI_SINGLESTREETLIGHTS3 ||\n\t\tid == MI_DOUBLESTREETLIGHTS ||\n\t\tid == MI_TRAFFICLIGHTS_TWOVERTICAL;\n}\n\ninline bool\nIsLampPost(int16 id)\n{\n\treturn id == MI_SINGLESTREETLIGHTS1 ||\n\t\tid == MI_SINGLESTREETLIGHTS2 ||\n\t\tid == MI_SINGLESTREETLIGHTS3 ||\n\t\tid == MI_BOLLARDLIGHT ||\n\t\tid == MI_MLAMPPOST ||\n\t\tid == MI_STREETLAMP1 ||\n\t\tid == MI_STREETLAMP2 ||\n\t\tid == MI_TELPOLE02 ||\n\t\tid == MI_TRAFFICLIGHTS_MIAMI ||\n\t\tid == MI_TRAFFICLIGHTS_TWOVERTICAL;\n}\n\ninline bool\nIsBodyPart(int16 id)\n{\n\treturn id == MI_BODYPARTA || id == MI_BODYPARTB;\n}\n\ninline bool\nIsPedModel(int16 id)\n{\n\treturn id >= MI_PLAYER && id <= MI_LAST_PED;\n}\ninline bool\nIsPalmTreeModel(int16 id)\n{\n\treturn\tid == MI_VEG_PALM01 ||\n\t\tid == MI_VEG_PALM02 ||\n\t\tid == MI_VEG_PALM03 ||\n\t\tid == MI_VEG_PALM04 ||\n\t\tid == MI_VEG_PALM05 ||\n\t\tid == MI_VEG_PALM06 ||\n\t\tid == MI_VEG_PALM07 ||\n\t\tid == MI_VEG_PALM08;\n}\n\ninline bool\nIsTreeModel(int16 id)\n{\n\treturn\tid == MI_TREE2 ||\n\t\tid == MI_TREE3 ||\n\t\tid == MI_TREE6 ||\n\t\tid == MI_TREE8 ||\n\t\tIsPalmTreeModel(id);\n}\n\ninline bool\nIsPolicePedModel(int16 id)\n{\n\treturn id == MI_COP ||\n\t\tid == MI_SWAT ||\n\t\tid == MI_FBI ||\n\t\tid == MI_ARMY;\n}\n\ninline bool\nIsPoliceVehicleModel(int16 id)\n{\n\treturn id == MI_CHOPPER ||\n\t\tid == MI_PREDATOR ||\n\t\tid == MI_POLICE ||\n\t\tid == MI_ENFORCER;\n}\n\ninline bool\nIsExplosiveThingModel(int16 id)\n{\n\treturn id == MI_EXPLODINGBARREL ||\n\t\tid == MI_PETROLPUMP ||\n\t\tid == MI_PETROLPUMP2;\n}\n\ninline bool \nIsFence(int16 id)\n{\n\treturn id == MI_FENCE ||\n\t\tid == MI_FENCE2;\n}\n"
  },
  {
    "path": "src/modelinfo/ModelInfo.cpp",
    "content": "#include \"common.h\"\n\n#include \"General.h\"\n#include \"TempColModels.h\"\n#include \"ModelIndices.h\"\n#include \"ModelInfo.h\"\n\nCBaseModelInfo *CModelInfo::ms_modelInfoPtrs[MODELINFOSIZE];\n\nCStore<CSimpleModelInfo, SIMPLEMODELSIZE> CModelInfo::ms_simpleModelStore;\nCStore<CTimeModelInfo, TIMEMODELSIZE> CModelInfo::ms_timeModelStore;\nCStore<CWeaponModelInfo, WEAPONMODELSIZE> CModelInfo::ms_weaponModelStore;\nCStore<CClumpModelInfo, CLUMPMODELSIZE> CModelInfo::ms_clumpModelStore;\nCStore<CPedModelInfo, PEDMODELSIZE> CModelInfo::ms_pedModelStore;\nCStore<CVehicleModelInfo, VEHICLEMODELSIZE> CModelInfo::ms_vehicleModelStore;\nCStore<C2dEffect, TWODFXSIZE> CModelInfo::ms_2dEffectStore;\n\nvoid\nCModelInfo::Initialise(void)\n{\n\tint i;\n\tCSimpleModelInfo *m;\n\n\tdebug(\"sizeof SimpleModelStore %d\\n\", sizeof(ms_simpleModelStore));\n\tdebug(\"sizeof TimeModelStore %d\\n\", sizeof(ms_timeModelStore));\n\tdebug(\"sizeof WeaponModelStore %d\\n\", sizeof(ms_weaponModelStore));\n\tdebug(\"sizeof ClumpModelStore %d\\n\", sizeof(ms_clumpModelStore));\n\tdebug(\"sizeof VehicleModelStore %d\\n\", sizeof(ms_vehicleModelStore));\n\tdebug(\"sizeof PedModelStore %d\\n\", sizeof(ms_pedModelStore));\n\tdebug(\"sizeof 2deffectsModelStore %d\\n\", sizeof(ms_2dEffectStore));\n\n\tfor(i = 0; i < MODELINFOSIZE; i++)\n\t\tms_modelInfoPtrs[i] = nil;\n\tms_2dEffectStore.Clear();\n\tms_simpleModelStore.Clear();\n\tms_timeModelStore.Clear();\n\tms_weaponModelStore.Clear();\n\tms_clumpModelStore.Clear();\n\tms_pedModelStore.Clear();\n\tms_vehicleModelStore.Clear();\n\n\tm = AddSimpleModel(MI_CAR_DOOR);\n\tm->SetColModel(&CTempColModels::ms_colModelDoor1);\n\tm->SetTexDictionary(\"generic\");\n\tm->SetNumAtomics(1);\n\tm->m_lodDistances[0] = 80.0f;\n\n\tm = AddSimpleModel(MI_CAR_BUMPER);\n\tm->SetColModel(&CTempColModels::ms_colModelBumper1);\n\tm->SetTexDictionary(\"generic\");\n\tm->SetNumAtomics(1);\n\tm->m_lodDistances[0] = 80.0f;\n\n\tm = AddSimpleModel(MI_CAR_PANEL);\n\tm->SetColModel(&CTempColModels::ms_colModelPanel1);\n\tm->SetTexDictionary(\"generic\");\n\tm->SetNumAtomics(1);\n\tm->m_lodDistances[0] = 80.0f;\n\n\tm = AddSimpleModel(MI_CAR_BONNET);\n\tm->SetColModel(&CTempColModels::ms_colModelBonnet1);\n\tm->SetTexDictionary(\"generic\");\n\tm->SetNumAtomics(1);\n\tm->m_lodDistances[0] = 80.0f;\n\n\tm = AddSimpleModel(MI_CAR_BOOT);\n\tm->SetColModel(&CTempColModels::ms_colModelBoot1);\n\tm->SetTexDictionary(\"generic\");\n\tm->SetNumAtomics(1);\n\tm->m_lodDistances[0] = 80.0f;\n\n\tm = AddSimpleModel(MI_CAR_WHEEL);\n\tm->SetColModel(&CTempColModels::ms_colModelWheel1);\n\tm->SetTexDictionary(\"generic\");\n\tm->SetNumAtomics(1);\n\tm->m_lodDistances[0] = 80.0f;\n\n\tm = AddSimpleModel(MI_BODYPARTA);\n\tm->SetColModel(&CTempColModels::ms_colModelBodyPart1);\n\tm->SetTexDictionary(\"generic\");\n\tm->SetNumAtomics(1);\n\tm->m_lodDistances[0] = 80.0f;\n\n\tm = AddSimpleModel(MI_BODYPARTB);\n\tm->SetColModel(&CTempColModels::ms_colModelBodyPart2);\n\tm->SetTexDictionary(\"generic\");\n\tm->SetNumAtomics(1);\n\tm->m_lodDistances[0] = 80.0f;\n}\n\nvoid\nCModelInfo::ShutDown(void)\n{\n\tint i;\n\tfor(i = 0; i < ms_simpleModelStore.allocPtr; i++)\n\t\tms_simpleModelStore.store[i].Shutdown();\n\tfor(i = 0; i < ms_timeModelStore.allocPtr; i++)\n\t\tms_timeModelStore.store[i].Shutdown();\n\tfor(i = 0; i < ms_weaponModelStore.allocPtr; i++)\n\t\tms_weaponModelStore.store[i].Shutdown();\n\tfor(i = 0; i < ms_clumpModelStore.allocPtr; i++)\n\t\tms_clumpModelStore.store[i].Shutdown();\n\tfor(i = 0; i < ms_vehicleModelStore.allocPtr; i++)\n\t\tms_vehicleModelStore.store[i].Shutdown();\n\tfor(i = 0; i < ms_pedModelStore.allocPtr; i++)\n\t\tms_pedModelStore.store[i].Shutdown();\n\tfor(i = 0; i < ms_2dEffectStore.allocPtr; i++)\n\t\tms_2dEffectStore.store[i].Shutdown();\n\n\tms_2dEffectStore.Clear();\n\tms_simpleModelStore.Clear();\n\tms_timeModelStore.Clear();\n\tms_weaponModelStore.Clear();\n\tms_pedModelStore.Clear();\n\tms_clumpModelStore.Clear();\n\tms_vehicleModelStore.Clear();\n}\n\nCSimpleModelInfo*\nCModelInfo::AddSimpleModel(int id)\n{\n\tCSimpleModelInfo *modelinfo;\n\tmodelinfo = CModelInfo::ms_simpleModelStore.Alloc();\n\tCModelInfo::ms_modelInfoPtrs[id] = modelinfo;\n\tmodelinfo->Init();\n\treturn modelinfo;\n}\n\nCTimeModelInfo*\nCModelInfo::AddTimeModel(int id)\n{\n\tCTimeModelInfo *modelinfo;\n\tmodelinfo = CModelInfo::ms_timeModelStore.Alloc();\n\tCModelInfo::ms_modelInfoPtrs[id] = modelinfo;\n\tmodelinfo->Init();\n\treturn modelinfo;\n}\n\nCWeaponModelInfo*\nCModelInfo::AddWeaponModel(int id)\n{\n\tCWeaponModelInfo *modelinfo;\n\tmodelinfo = CModelInfo::ms_weaponModelStore.Alloc();\n\tCModelInfo::ms_modelInfoPtrs[id] = modelinfo;\n\tmodelinfo->Init();\n\treturn modelinfo;\n}\n\nCClumpModelInfo*\nCModelInfo::AddClumpModel(int id)\n{\n\tCClumpModelInfo *modelinfo;\n\tmodelinfo = CModelInfo::ms_clumpModelStore.Alloc();\n\tCModelInfo::ms_modelInfoPtrs[id] = modelinfo;\n\tmodelinfo->m_clump = nil;\n\treturn modelinfo;\n}\n\nCPedModelInfo*\nCModelInfo::AddPedModel(int id)\n{\n\tCPedModelInfo *modelinfo;\n\tmodelinfo = CModelInfo::ms_pedModelStore.Alloc();\n\tCModelInfo::ms_modelInfoPtrs[id] = modelinfo;\n\tmodelinfo->m_clump = nil;\n\treturn modelinfo;\n}\n\nCVehicleModelInfo*\nCModelInfo::AddVehicleModel(int id)\n{\n\tCVehicleModelInfo *modelinfo;\n\tmodelinfo = CModelInfo::ms_vehicleModelStore.Alloc();\n\tCModelInfo::ms_modelInfoPtrs[id] = modelinfo;\n\tmodelinfo->m_clump = nil;\n\tmodelinfo->m_vehicleType = -1;\n\tmodelinfo->m_wheelId = -1;\n\tmodelinfo->m_materials1[0] = nil;\n\tmodelinfo->m_materials2[0] = nil;\n\tmodelinfo->m_bikeSteerAngle = 999.99f;\n\treturn modelinfo;\n}\n\nCBaseModelInfo*\nCModelInfo::GetModelInfo(const char *name, int *id)\n{\n\tCBaseModelInfo *modelinfo;\n\tfor(int i = 0; i < MODELINFOSIZE; i++){\n\t\tmodelinfo = CModelInfo::ms_modelInfoPtrs[i];\n\t \tif(modelinfo && !CGeneral::faststricmp(modelinfo->GetModelName(), name)){\n\t\t\tif(id)\n\t\t\t\t*id = i;\n\t\t\treturn modelinfo;\n\t\t}\n\t}\n\treturn nil;\n}\n\nCBaseModelInfo*\nCModelInfo::GetModelInfo(const char *name, int minIndex, int maxIndex)\n{\n\tif (minIndex > maxIndex)\n\t\treturn 0;\n\n\tCBaseModelInfo *modelinfo;\n\tfor(int i = minIndex; i <= maxIndex; i++){\n\t\tmodelinfo = CModelInfo::ms_modelInfoPtrs[i];\n\t \tif(modelinfo && !CGeneral::faststricmp(modelinfo->GetModelName(), name))\n\t\t\treturn modelinfo;\n\t}\n\treturn nil;\n}\n\nbool\nCModelInfo::IsBoatModel(int32 id)\n{\n\treturn GetModelInfo(id)->GetModelType() == MITYPE_VEHICLE &&\n\t\t((CVehicleModelInfo*)GetModelInfo(id))->m_vehicleType == VEHICLE_TYPE_BOAT;\n}\n\nbool\nCModelInfo::IsBikeModel(int32 id)\n{\n\treturn GetModelInfo(id)->GetModelType() == MITYPE_VEHICLE &&\n\t\t((CVehicleModelInfo*)GetModelInfo(id))->m_vehicleType == VEHICLE_TYPE_BIKE;\n}\n\nbool\nCModelInfo::IsCarModel(int32 id)\n{\n\treturn GetModelInfo(id)->GetModelType() == MITYPE_VEHICLE &&\n\t\t((CVehicleModelInfo*)GetModelInfo(id))->m_vehicleType == VEHICLE_TYPE_CAR;\n}\n\nbool\nCModelInfo::IsHeliModel(int32 id)\n{\n\treturn GetModelInfo(id)->GetModelType() == MITYPE_VEHICLE &&\n\t\t((CVehicleModelInfo*)GetModelInfo(id))->m_vehicleType == VEHICLE_TYPE_HELI;\n}\n\nbool\nCModelInfo::IsPlaneModel(int32 id)\n{\n\treturn GetModelInfo(id)->GetModelType() == MITYPE_VEHICLE &&\n\t\t((CVehicleModelInfo*)GetModelInfo(id))->m_vehicleType == VEHICLE_TYPE_PLANE;\n}\n\nvoid\nCModelInfo::ReInit2dEffects()\n{\n\tms_2dEffectStore.Clear();\n\n\tfor (int i = 0; i < MODELINFOSIZE; i++) {\n\t\tif (ms_modelInfoPtrs[i])\n\t\t\tms_modelInfoPtrs[i]->Init2dEffects();\n\t}\n}\n"
  },
  {
    "path": "src/modelinfo/ModelInfo.h",
    "content": "#pragma once\n\n#include \"2dEffect.h\"\n#include \"SimpleModelInfo.h\"\n#include \"TimeModelInfo.h\"\n#include \"WeaponModelInfo.h\"\n#include \"ClumpModelInfo.h\"\n#include \"PedModelInfo.h\"\n#include \"VehicleModelInfo.h\"\n#include \"templates.h\"\n\nclass CModelInfo\n{\n\tstatic CBaseModelInfo *ms_modelInfoPtrs[MODELINFOSIZE];\n\tstatic CStore<CSimpleModelInfo, SIMPLEMODELSIZE> ms_simpleModelStore;\n\tstatic CStore<CTimeModelInfo, TIMEMODELSIZE> ms_timeModelStore;\n\tstatic CStore<CWeaponModelInfo, WEAPONMODELSIZE> ms_weaponModelStore;\n\tstatic CStore<CClumpModelInfo, CLUMPMODELSIZE> ms_clumpModelStore;\n\tstatic CStore<CPedModelInfo, PEDMODELSIZE> ms_pedModelStore;\n\tstatic CStore<CVehicleModelInfo, VEHICLEMODELSIZE> ms_vehicleModelStore;\n\tstatic CStore<C2dEffect, TWODFXSIZE> ms_2dEffectStore;\n\npublic:\n\tstatic void Initialise(void);\n\tstatic void ShutDown(void);\n\n\tstatic CSimpleModelInfo *AddSimpleModel(int id);\n\tstatic CTimeModelInfo *AddTimeModel(int id);\n\tstatic CWeaponModelInfo *AddWeaponModel(int id);\n\tstatic CClumpModelInfo *AddClumpModel(int id);\n\tstatic CPedModelInfo *AddPedModel(int id);\n\tstatic CVehicleModelInfo *AddVehicleModel(int id);\n\n\tstatic CStore<C2dEffect, TWODFXSIZE> &Get2dEffectStore(void) { return ms_2dEffectStore; }\n\n\tstatic CBaseModelInfo *GetModelInfo(const char *name, int *id);\n\tstatic CBaseModelInfo *GetModelInfo(int id){\n\t\treturn ms_modelInfoPtrs[id];\n\t}\n\tstatic CBaseModelInfo *GetModelInfo(const char *name, int minIndex, int maxIndex);\n\n\tstatic bool IsBoatModel(int32 id);\n\tstatic bool IsBikeModel(int32 id);\n\tstatic bool IsCarModel(int32 id);\n\tstatic bool IsHeliModel(int32 id);\n\tstatic bool IsPlaneModel(int32 id);\n\tstatic void ReInit2dEffects();\n};\n"
  },
  {
    "path": "src/modelinfo/PedModelInfo.cpp",
    "content": "#include \"common.h\"\n\n#include \"RwHelper.h\"\n#include \"General.h\"\n#include \"Bones.h\"\n#include \"SurfaceTable.h\"\n#include \"Ped.h\"\n#include \"NodeName.h\"\n#include \"VisibilityPlugins.h\"\n#include \"ModelInfo.h\"\n#include \"custompipes.h\"\n\nvoid\nCPedModelInfo::DeleteRwObject(void)\n{\n\tCClumpModelInfo::DeleteRwObject();\n\tif(m_hitColModel)\n\t\tdelete m_hitColModel;\n\tm_hitColModel = nil;\n}\n\n// leftover...\nRwObjectNameIdAssocation CPedModelInfo::m_pPedIds[PED_NODE_MAX] = {\n\t{ \"Smid\",\tPED_MID, 0, },\t// that is strange...\n\t{ \"Shead\",\tPED_HEAD, 0, },\n\t{ \"Supperarml\",\tPED_UPPERARML, 0, },\n\t{ \"Supperarmr\",\tPED_UPPERARMR, 0, },\n\t{ \"SLhand\",\tPED_HANDL, 0, },\n\t{ \"SRhand\",\tPED_HANDR, 0, },\n\t{ \"Supperlegl\",\tPED_UPPERLEGL, 0, },\n\t{ \"Supperlegr\",\tPED_UPPERLEGR, 0, },\n\t{ \"Sfootl\",\tPED_FOOTL, 0, },\n\t{ \"Sfootr\",\tPED_FOOTR, 0, },\n\t{ \"Slowerlegr\",\tPED_LOWERLEGR, 0, },\n\t{ nil,\t0, 0, },\n};\n\nvoid\nCPedModelInfo::SetClump(RpClump *clump)\n{\n#ifdef EXTENDED_PIPELINES\n\tCustomPipes::AttachRimPipe(clump);\n#endif\n\tCClumpModelInfo::SetClump(clump);\n\tSetFrameIds(m_pPedIds);\t// not needed in VC actually\n\tif(m_hitColModel == nil)\n\t\tCreateHitColModelSkinned(clump);\n\tRpClumpForAllAtomics(m_clump, SetAtomicRendererCB, (void*)CVisibilityPlugins::RenderPedCB);\n\tif(strcmp(GetModelName(), \"player\") == 0)\n\t\tRpClumpForAllAtomics(m_clump, SetAtomicRendererCB, (void*)CVisibilityPlugins::RenderPlayerCB);\n}\n\nstruct ColNodeInfo\n{\n\tConst char *name;\n\tint pedNode;\n\tint pieceType;\n\tfloat x, z;\n\tfloat radius;\n};\n\n#define NUMPEDINFONODES 10\nColNodeInfo m_pColNodeInfos[NUMPEDINFONODES] = {\n\t{ nil, PED_HEAD,\tPEDPIECE_HEAD,\t0.0f,   0.05f, 0.15f },\n\t{ nil, PED_MID,\t\tPEDPIECE_TORSO,\t0.0f,   0.15f, 0.2f },\n\t{ nil, PED_MID,\t\tPEDPIECE_TORSO,\t0.0f,  -0.05f, 0.25f },\n\t{ nil, PED_MID,\t\tPEDPIECE_MID,\t0.0f,  -0.25f, 0.25f },\n\t{ nil, PED_UPPERARML,\tPEDPIECE_LEFTARM,\t0.03f, -0.05f,  0.16f },\n\t{ nil, PED_UPPERARMR,\tPEDPIECE_RIGHTARM,\t-0.03f, -0.05f,  0.16f },\n\t{ nil, PED_LOWERLEGL,\tPEDPIECE_LEFTLEG,\t0.0f,   0.15f, 0.2f },\n\t{ nil, PED_LOWERLEGR,\tPEDPIECE_RIGHTLEG,\t0.0f,   0.15f, 0.2f },\n\t{ nil, PED_FOOTL,\tPEDPIECE_LEFTLEG,\t0.0f,   0.15f, 0.15f },\n\t{ nil, PED_FOOTR,\tPEDPIECE_RIGHTLEG,\t0.0f,   0.15f, 0.15f },\n};\n\nvoid\nCPedModelInfo::CreateHitColModelSkinned(RpClump *clump)\n{\n\tRpHAnimHierarchy *hier = GetAnimHierarchyFromSkinClump(clump);\n\tCColModel *colmodel = new CColModel;\n\tCColSphere *spheres = (CColSphere*)RwMalloc(NUMPEDINFONODES*sizeof(CColSphere));\n\tRwFrame *root = RpClumpGetFrame(m_clump);\n\tRwMatrix *invmat = RwMatrixCreate();\n\tRwMatrix *mat = RwMatrixCreate();\n\tRwMatrixInvert(invmat, RwFrameGetMatrix(RpClumpGetFrame(clump)));\n\n\tfor(int i = 0; i < NUMPEDINFONODES; i++){\n\t\t*mat = *invmat;\n\t\tint id = ConvertPedNode2BoneTag(m_pColNodeInfos[i].pedNode);\t// this is wrong, wtf R* ???\n\t\tint idx = RpHAnimIDGetIndex(hier, id);\n\n\t\t// This doesn't really work as the positions are not initialized yet\n\t\tRwMatrixTransform(mat, &RpHAnimHierarchyGetMatrixArray(hier)[idx], rwCOMBINEPRECONCAT);\n\t\tRwV3d pos = { 0.0f, 0.0f, 0.0f };\n\t\tRwV3dTransformPoints(&pos, &pos, 1, mat);\n\n\t\tspheres[i].center = pos + CVector(m_pColNodeInfos[i].x, 0.0f, m_pColNodeInfos[i].z);\n\t\tspheres[i].radius = m_pColNodeInfos[i].radius;\n\t\tspheres[i].surface = SURFACE_PED;\n\t\tspheres[i].piece = m_pColNodeInfos[i].pieceType;\n\t}\n\tRwMatrixDestroy(invmat);\n\tRwMatrixDestroy(mat);\n\tcolmodel->spheres = spheres;\n\tcolmodel->numSpheres = NUMPEDINFONODES;\n\tcolmodel->boundingSphere.Set(2.0f, CVector(0.0f, 0.0f, 0.0f));\n\tcolmodel->boundingBox.Set(CVector(-0.5f, -0.5f, -1.2f), CVector(0.5f, 0.5f, 1.2f));\n\tcolmodel->level = LEVEL_GENERIC;\n\tm_hitColModel = colmodel;\n}\n\nCColModel*\nCPedModelInfo::AnimatePedColModelSkinned(RpClump *clump)\n{\n\tif(m_hitColModel == nil){\n\t\tCreateHitColModelSkinned(clump);\n\t\treturn m_hitColModel;\n\t}\n\tRwMatrix *invmat, *mat;\n\tCColSphere *spheres = m_hitColModel->spheres;\n\tRpHAnimHierarchy *hier = GetAnimHierarchyFromSkinClump(clump);\n\tinvmat = RwMatrixCreate();\n\tmat = RwMatrixCreate();\n\tRwMatrixInvert(invmat, RwFrameGetMatrix(RpClumpGetFrame(clump)));\n\n\tfor(int i = 0; i < NUMPEDINFONODES; i++){\n\t\t*mat = *invmat;\n\t\tint id = ConvertPedNode2BoneTag(m_pColNodeInfos[i].pedNode);\n\t\tint idx = RpHAnimIDGetIndex(hier, id);\n\n\t\tRwMatrixTransform(mat, &RpHAnimHierarchyGetMatrixArray(hier)[idx], rwCOMBINEPRECONCAT);\n\t\tRwV3d pos = { 0.0f, 0.0f, 0.0f };\n\t\tRwV3dTransformPoints(&pos, &pos, 1, mat);\n\n\t\tspheres[i].center = pos + CVector(m_pColNodeInfos[i].x, 0.0f, m_pColNodeInfos[i].z);\n\t}\n\tRwMatrixDestroy(invmat);\n\tRwMatrixDestroy(mat);\n\treturn m_hitColModel;\n}\n\nCColModel*\nCPedModelInfo::AnimatePedColModelSkinnedWorld(RpClump *clump)\n{\n\tif(m_hitColModel == nil)\n\t\tCreateHitColModelSkinned(clump);\n\tCColSphere *spheres = m_hitColModel->spheres;\n\tRpHAnimHierarchy *hier = GetAnimHierarchyFromSkinClump(clump);\n\tRwMatrix *mat;\n\n\tfor(int i = 0; i < NUMPEDINFONODES; i++){\n\t\tint id = ConvertPedNode2BoneTag(m_pColNodeInfos[i].pedNode);\n\t\tint idx = RpHAnimIDGetIndex(hier, id);\n\n\t\tmat = &RpHAnimHierarchyGetMatrixArray(hier)[idx];\n\t\tRwV3d pos = { 0.0f, 0.0f, 0.0f };\n\t\tRwV3dTransformPoints(&pos, &pos, 1, mat);\n\n\t\tspheres[i].center = pos + CVector(m_pColNodeInfos[i].x, 0.0f, m_pColNodeInfos[i].z);\n\t}\n\treturn m_hitColModel;\n}\n"
  },
  {
    "path": "src/modelinfo/PedModelInfo.h",
    "content": "#pragma once\n\n#include \"ClumpModelInfo.h\"\n#include \"ColModel.h\"\n#include \"PedType.h\"\n\nenum PedNode {\n\tPED_TORSO = 0,\t// has no bone!\n\tPED_MID,\n\tPED_HEAD,\n\tPED_UPPERARML,\n\tPED_UPPERARMR,\n\tPED_HANDL,\n\tPED_HANDR,\n\tPED_UPPERLEGL,\n\tPED_UPPERLEGR,\n\tPED_FOOTL,\n\tPED_FOOTR,\n\tPED_LOWERLEGR,\n\tPED_LOWERLEGL,\n\n\tPED_FOREARML,\n\tPED_FOREARMR,\n\tPED_CLAVICLEL,\n\tPED_CLAVICLER,\n\tPED_NECK,\n\n\tPED_NODE_MAX\n};\n\nclass CPedModelInfo : public CClumpModelInfo\n{\npublic:\n\tuint32 m_animGroup;\n\tePedType m_pedType;\n\tePedStats m_pedStatType;\n\tuint32 m_carsCanDrive;\n\tCColModel *m_hitColModel;\n\tint8 radio1, radio2;\n\n\tstatic RwObjectNameIdAssocation m_pPedIds[PED_NODE_MAX];\n\n\tCPedModelInfo(void) : CClumpModelInfo(MITYPE_PED) { m_hitColModel = nil; }\n\t~CPedModelInfo(void) { delete m_hitColModel; }\n\tvoid DeleteRwObject(void);\n\tvoid SetClump(RpClump *);\n\n\tvoid CreateHitColModelSkinned(RpClump *clump);\n\tCColModel *GetHitColModel(void) { return m_hitColModel; }\n\tCColModel *AnimatePedColModelSkinned(RpClump *clump);\n\tCColModel *AnimatePedColModelSkinnedWorld(RpClump *clump);\n};\n"
  },
  {
    "path": "src/modelinfo/SimpleModelInfo.cpp",
    "content": "#include \"common.h\"\n\n#include \"General.h\"\n#include \"Camera.h\"\n#include \"Renderer.h\"\n#include \"ModelInfo.h\"\n#include \"AnimManager.h\"\n#include \"custompipes.h\"\n\nvoid\nCSimpleModelInfo::DeleteRwObject(void)\n{\n\tint i;\n\tRwFrame *f;\n\tfor(i = 0; i < m_numAtomics; i++)\n\t\tif(m_atomics[i]){\n\t\t\tf = RpAtomicGetFrame(m_atomics[i]);\n\t\t\tRpAtomicDestroy(m_atomics[i]);\n\t\t\tRwFrameDestroy(f);\n\t\t\tm_atomics[i] = nil;\n\t\t\tRemoveTexDictionaryRef();\n\t\t\tif(GetAnimFileIndex() != -1)\n\t\t\t\tCAnimManager::RemoveAnimBlockRef(GetAnimFileIndex());\n\t\t}\n}\n\nRwObject*\nCSimpleModelInfo::CreateInstance(void)\n{\n\tRpAtomic *atomic;\n\tif(m_atomics[0] == nil)\n\t\treturn nil;\n\tatomic = RpAtomicClone(m_atomics[0]);\n\tRpAtomicSetFrame(atomic, RwFrameCreate());\n\treturn (RwObject*)atomic;\n}\n\nRwObject*\nCSimpleModelInfo::CreateInstance(RwMatrix *matrix)\n{\n\tRpAtomic *atomic;\n\tRwFrame *frame;\n\n\tif(m_atomics[0] == nil)\n\t\treturn nil;\n\tatomic = RpAtomicClone(m_atomics[0]);\n\tframe = RwFrameCreate();\n\t*RwFrameGetMatrix(frame) = *matrix;\n\tRpAtomicSetFrame(atomic, frame);\n\treturn (RwObject*)atomic;\n}\n\nvoid\nCSimpleModelInfo::Init(void)\n{\n\tm_atomics[0] = nil;\n\tm_atomics[1] = nil;\n\tm_atomics[2] = nil;\n\tm_numAtomics = 0;\n\tm_firstDamaged  = 0;\n\tm_wetRoadReflection    = 0;\n\tm_isDamaged     = 0;\n\tm_isBigBuilding = 0;\n\tm_noFade        = 0;\n\tm_drawLast      = 0;\n\tm_additive      = 0;\n\tm_isSubway      = 0;\n\tm_ignoreLight   = 0;\n\tm_noZwrite      = 0;\n\tm_noShadows     = 0;\n\tm_ignoreDrawDist  = 0;\n\tm_isCodeGlass     = 0;\n\tm_isArtistGlass   = 0;\n}\n\nvoid\nCSimpleModelInfo::SetAtomic(int n, RpAtomic *atomic)\n{\n\tAddTexDictionaryRef();\n\tm_atomics[n] = atomic;\n\tif(GetAnimFileIndex() != -1)\n\t\tCAnimManager::AddAnimBlockRef(GetAnimFileIndex());\n\tRpGeometry *geo = RpAtomicGetGeometry(atomic);\n\tif(m_ignoreLight)\n\t\tRpGeometrySetFlags(geo, RpGeometryGetFlags(geo) & ~rpGEOMETRYLIGHT);\n\tif(RpGeometryGetFlags(geo) & rpGEOMETRYNORMALS &&\n\t   RpGeometryGetNumTriangles(geo) > 200)\n\t\tdebug(\"%s has %d polys\\n\", m_name, RpGeometryGetNumTriangles(geo));\n\n#ifdef EXTENDED_PIPELINES\n\tif(m_wetRoadReflection)\n\t\tCustomPipes::AttachGlossPipe(atomic);\n\telse\n\t\tCustomPipes::AttachWorldPipe(atomic);\n#endif\n}\n\nvoid\nCSimpleModelInfo::SetLodDistances(float *dist)\n{\n\tm_lodDistances[0] = dist[0];\n\tm_lodDistances[1] = dist[1];\n\tm_lodDistances[2] = dist[2];\n}\n\nvoid\nCSimpleModelInfo::IncreaseAlpha(void)\n{\n\tif(m_alpha >= 0xEF)\n\t\tm_alpha = 0xFF;\n\telse\n\t\tm_alpha += 0x10;\n}\n\nfloat\nCSimpleModelInfo::GetLodDistance(int i)\n{\n\treturn m_lodDistances[i] * TheCamera.LODDistMultiplier;\n}\n\nfloat\nCSimpleModelInfo::GetNearDistance(void)\n{\n\treturn m_lodDistances[2] * TheCamera.LODDistMultiplier;\n}\n\nfloat\nCSimpleModelInfo::GetLargestLodDistance(void)\n{\n\tfloat d;\n\tif(m_firstDamaged == 0 || m_isDamaged)\n\t\td = m_lodDistances[m_numAtomics-1];\n\telse\n\t\td = m_lodDistances[m_firstDamaged-1];\n\treturn d * TheCamera.LODDistMultiplier;\n}\n\nRpAtomic*\nCSimpleModelInfo::GetAtomicFromDistance(float dist)\n{\n\tint i;\n\ti = 0;\n\tif(m_isDamaged)\n\t\ti = m_firstDamaged;\n\tfor(; i < m_numAtomics; i++)\n\t\tif(dist < m_lodDistances[i] * TheCamera.LODDistMultiplier)\n\t\t\treturn m_atomics[i];\n\treturn nil;\n}\n\nRpAtomic*\nCSimpleModelInfo::GetFirstAtomicFromDistance(float dist)\n{\n\tif(dist < m_lodDistances[0] * TheCamera.LODDistMultiplier)\n\t\treturn m_atomics[0];\n\treturn nil;\n}\n\nvoid\nCSimpleModelInfo::FindRelatedModel(int32 minID, int32 maxID)\n{\n\tint i;\n\tCBaseModelInfo *mi;\n\tfor(i = minID; i <= maxID; i++){\n\t\tmi = CModelInfo::GetModelInfo(i);\n\t\tif(mi && mi != this &&\n\t\t   !CGeneral::faststrcmp(GetModelName()+3, mi->GetModelName()+3)){\n\t\t\tassert(mi->IsSimple());\n\t\t\tthis->SetRelatedModel((CSimpleModelInfo*)mi);\n\t\t\treturn;\n\t\t}\n\t}\n}\n\n#define NEAR_DRAW_DIST 0.0f\t// 100.0f in liberty city\n\nvoid\nCSimpleModelInfo::SetupBigBuilding(int32 minID, int32 maxID)\n{\n\tCSimpleModelInfo *related;\n\tif(m_lodDistances[0] > LOD_DISTANCE && GetRelatedModel() == nil){\n\t\tm_isBigBuilding = 1;\n\t\tFindRelatedModel(minID, maxID);\n\t\trelated = GetRelatedModel();\n\t\tif(related){\n\t\t\tm_lodDistances[2] = related->GetLargestLodDistance()/TheCamera.LODDistMultiplier;\n\t\t\tif(m_drawLast){\n\t\t\t\tm_drawLast = false;\n\t\t\t\tdebug(\"%s was draw last\\n\", GetModelName());\n\t\t\t}\n\t\t}else\n\t\t\tm_lodDistances[2] = NEAR_DRAW_DIST;\n\t}\n}\n"
  },
  {
    "path": "src/modelinfo/SimpleModelInfo.h",
    "content": "#pragma once\n\n#include \"BaseModelInfo.h\"\n\nclass CSimpleModelInfo : public CBaseModelInfo\n{\npublic:\n\t// atomics[2] is often a pointer to the non-LOD modelinfo\n\tRpAtomic *m_atomics[3];\n\t// m_lodDistances[2] holds the near distance for LODs\n\tfloat  m_lodDistances[3];\n\tuint8  m_numAtomics;\n\tuint8  m_alpha;\n\tuint16 m_firstDamaged   : 2; // 0: no damage model\n\t                         // 1: 1 and 2 are damage models\n\t                         // 2: 2 is damage model\n\tuint16  m_wetRoadReflection    : 1;\n\tuint16  m_isDamaged     : 1;\n\n\tuint16  m_isBigBuilding : 1;\n\tuint16  m_noFade        : 1;\n\tuint16  m_drawLast      : 1;\n\tuint16  m_additive      : 1;\n\n\tuint16  m_isSubway      : 1;\n\tuint16  m_ignoreLight   : 1;\n\tuint16  m_noZwrite      : 1;\n\tuint16  m_noShadows     : 1;\n\n\tuint16  m_ignoreDrawDist   : 1;\n\tuint16  m_isCodeGlass      : 1;\n\tuint16  m_isArtistGlass    : 1;\n\n\tCSimpleModelInfo(void) : CBaseModelInfo(MITYPE_SIMPLE) {}\n\tCSimpleModelInfo(ModelInfoType id) : CBaseModelInfo(id) {}\n\t~CSimpleModelInfo() {}\n\tvoid DeleteRwObject(void);\n\tRwObject *CreateInstance(void);\n\tRwObject *CreateInstance(RwMatrix *);\n\tRwObject *GetRwObject(void) { return (RwObject*)m_atomics[0]; }\n\n\tvirtual void SetAtomic(int n, RpAtomic *atomic);\n\n\tvoid Init(void);\n\tvoid IncreaseAlpha(void);\n\tvoid SetLodDistances(float *dist);\n\tfloat GetLodDistance(int i);\n\tfloat GetNearDistance(void);\n\tfloat GetLargestLodDistance(void);\n\tRpAtomic *GetAtomicFromDistance(float dist);\n\tRpAtomic *GetFirstAtomicFromDistance(float dist);\n\tvoid FindRelatedModel(int32 minID, int32 maxID);\n\tvoid SetupBigBuilding(int32 minID, int32 maxID);\n\n\tvoid SetNumAtomics(int n) { m_numAtomics = n; }\n\tCSimpleModelInfo *GetRelatedModel(void){\n\t\treturn (CSimpleModelInfo*)m_atomics[2]; }\n\tvoid SetRelatedModel(CSimpleModelInfo *m){\n\t\tm_atomics[2] = (RpAtomic*)m; }\n};\n//static_assert(sizeof(CSimpleModelInfo) == 0x4C, \"CSimpleModelInfo: error\");\n"
  },
  {
    "path": "src/modelinfo/TimeModelInfo.cpp",
    "content": "#include \"common.h\"\n\n#include \"Camera.h\"\n#include \"ModelInfo.h\"\n#include \"General.h\"\n\nCTimeModelInfo*\nCTimeModelInfo::FindOtherTimeModel(void)\n{\n\tchar name[40];\n\tchar *p;\n\tint i;\n\n\tstrcpy(name, GetModelName());\n\t// change _nt to _dy\n\tif(p = strstr(name, \"_nt\"))\n\t\tstrncpy(p, \"_dy\", 4);\n\t// change _dy to _nt\n\telse if(p = strstr(name, \"_dy\"))\n\t\tstrncpy(p, \"_nt\", 4);\n\telse\n\t\treturn nil;\n\n\tfor(i = 0; i < MODELINFOSIZE; i++){\n\t\tCBaseModelInfo *mi = CModelInfo::GetModelInfo(i);\n\t\tif (mi && mi->GetModelType() == MITYPE_TIME &&\n\t\t   !CGeneral::faststrncmp(name, mi->GetModelName(), MAX_MODEL_NAME)){\n\t\t\tm_otherTimeModelID = i;\n\t\t\treturn (CTimeModelInfo*)mi;\n\t\t}\n\t}\n\treturn nil;\n}\n"
  },
  {
    "path": "src/modelinfo/TimeModelInfo.h",
    "content": "#pragma once\n\n#include \"SimpleModelInfo.h\"\n\nclass CTimeModelInfo : public CSimpleModelInfo\n{\n\tint32 m_timeOn;\n\tint32 m_timeOff;\n\tint32 m_otherTimeModelID;\npublic:\n\tCTimeModelInfo(void) : CSimpleModelInfo(MITYPE_TIME) { m_otherTimeModelID = -1; }\n\n\tint32 GetTimeOn(void) { return m_timeOn; }\n\tint32 GetTimeOff(void) { return m_timeOff; }\n\tvoid SetTimes(int32 on, int32 off) { m_timeOn = on; m_timeOff = off; }\n\tint32 GetOtherTimeModel(void) { return m_otherTimeModelID; }\n\tvoid SetOtherTimeModel(int32 other) { m_otherTimeModelID = other; }\n\tCTimeModelInfo *FindOtherTimeModel(void);\n};\n//static_assert(sizeof(CTimeModelInfo) == 0x58, \"CTimeModelInfo: error\");\n"
  },
  {
    "path": "src/modelinfo/VehicleModelInfo.cpp",
    "content": "#include \"common.h\"\n#include <rpmatfx.h>\n\n#include \"RwHelper.h\"\n#include \"General.h\"\n#include \"NodeName.h\"\n#include \"TxdStore.h\"\n#include \"Weather.h\"\n#include \"HandlingMgr.h\"\n#include \"VisibilityPlugins.h\"\n#include \"FileMgr.h\"\n#include \"World.h\"\n#include \"Vehicle.h\"\n#include \"Automobile.h\"\n#include \"Boat.h\"\n#include \"Train.h\"\n#include \"Plane.h\"\n#include \"Heli.h\"\n#include \"Bike.h\"\n#include \"ModelIndices.h\"\n#include \"ModelInfo.h\"\n#include \"custompipes.h\"\n\nint8 CVehicleModelInfo::ms_compsToUse[2] = { -2, -2 };\nint8 CVehicleModelInfo::ms_compsUsed[2];\nRwRGBA CVehicleModelInfo::ms_vehicleColourTable[256];\nRwTexture *CVehicleModelInfo::ms_colourTextureTable[256];\n\nRwTexture *gpWhiteTexture;\nRwFrame *pMatFxIdentityFrame;\n\nenum {\n\tVEHICLE_FLAG_COLLAPSE\t= 0x2,\n\tVEHICLE_FLAG_ADD_WHEEL\t= 0x4,\n\tVEHICLE_FLAG_POS\t= 0x8,\n\tVEHICLE_FLAG_DOOR\t= 0x10,\n\tVEHICLE_FLAG_LEFT\t= 0x20,\n\tVEHICLE_FLAG_RIGHT\t= 0x40,\n\tVEHICLE_FLAG_FRONT\t= 0x80,\n\tVEHICLE_FLAG_REAR\t= 0x100,\n\tVEHICLE_FLAG_COMP\t= 0x200,\n\tVEHICLE_FLAG_DRAWLAST\t= 0x400,\n\tVEHICLE_FLAG_WINDSCREEN\t= 0x800,\n\tVEHICLE_FLAG_ANGLECULL\t= 0x1000,\n\tVEHICLE_FLAG_REARDOOR\t= 0x2000,\n\tVEHICLE_FLAG_FRONTDOOR\t= 0x4000,\n};\n\nRwObjectNameIdAssocation carIds[] = {\n\t{ \"wheel_rf_dummy\",\tCAR_WHEEL_RF,\tVEHICLE_FLAG_RIGHT | VEHICLE_FLAG_ADD_WHEEL },\n\t{ \"wheel_rm_dummy\",\tCAR_WHEEL_RM,\tVEHICLE_FLAG_RIGHT | VEHICLE_FLAG_ADD_WHEEL },\n\t{ \"wheel_rb_dummy\",\tCAR_WHEEL_RB,\tVEHICLE_FLAG_RIGHT | VEHICLE_FLAG_ADD_WHEEL },\n\t{ \"wheel_lf_dummy\",\tCAR_WHEEL_LF,\tVEHICLE_FLAG_LEFT | VEHICLE_FLAG_ADD_WHEEL },\n\t{ \"wheel_lm_dummy\",\tCAR_WHEEL_LM,\tVEHICLE_FLAG_LEFT | VEHICLE_FLAG_ADD_WHEEL },\n\t{ \"wheel_lb_dummy\",\tCAR_WHEEL_LB,\tVEHICLE_FLAG_LEFT | VEHICLE_FLAG_ADD_WHEEL },\n\t{ \"bump_front_dummy\",\tCAR_BUMP_FRONT,\tVEHICLE_FLAG_FRONT | VEHICLE_FLAG_COLLAPSE },\n\t{ \"bonnet_dummy\",\tCAR_BONNET,\tVEHICLE_FLAG_COLLAPSE },\n\t{ \"wing_rf_dummy\",\tCAR_WING_RF,\tVEHICLE_FLAG_COLLAPSE },\n\t{ \"wing_rr_dummy\",\tCAR_WING_RR,\tVEHICLE_FLAG_RIGHT | VEHICLE_FLAG_COLLAPSE },\n\t{ \"door_rf_dummy\",\tCAR_DOOR_RF,\tVEHICLE_FLAG_FRONTDOOR | VEHICLE_FLAG_ANGLECULL | VEHICLE_FLAG_RIGHT | VEHICLE_FLAG_DOOR | VEHICLE_FLAG_COLLAPSE },\n\t{ \"door_rr_dummy\",\tCAR_DOOR_RR,\tVEHICLE_FLAG_REARDOOR | VEHICLE_FLAG_ANGLECULL | VEHICLE_FLAG_REAR | VEHICLE_FLAG_RIGHT | VEHICLE_FLAG_DOOR | VEHICLE_FLAG_COLLAPSE },\n\t{ \"wing_lf_dummy\",\tCAR_WING_LF,\tVEHICLE_FLAG_COLLAPSE },\n\t{ \"wing_lr_dummy\",\tCAR_WING_LR,\tVEHICLE_FLAG_LEFT | VEHICLE_FLAG_COLLAPSE },\n\t{ \"door_lf_dummy\",\tCAR_DOOR_LF,\tVEHICLE_FLAG_FRONTDOOR | VEHICLE_FLAG_ANGLECULL | VEHICLE_FLAG_LEFT | VEHICLE_FLAG_DOOR | VEHICLE_FLAG_COLLAPSE },\n\t{ \"door_lr_dummy\",\tCAR_DOOR_LR,\tVEHICLE_FLAG_REARDOOR | VEHICLE_FLAG_ANGLECULL | VEHICLE_FLAG_REAR | VEHICLE_FLAG_LEFT | VEHICLE_FLAG_DOOR | VEHICLE_FLAG_COLLAPSE },\n\t{ \"boot_dummy\",\t\tCAR_BOOT,\tVEHICLE_FLAG_REAR | VEHICLE_FLAG_COLLAPSE },\n\t{ \"bump_rear_dummy\",\tCAR_BUMP_REAR,\tVEHICLE_FLAG_REAR | VEHICLE_FLAG_COLLAPSE },\n\t{ \"windscreen_dummy\",\tCAR_WINDSCREEN,\tVEHICLE_FLAG_WINDSCREEN | VEHICLE_FLAG_DRAWLAST | VEHICLE_FLAG_FRONT | VEHICLE_FLAG_COLLAPSE },\n\n\t{ \"ped_frontseat\",\tCAR_POS_FRONTSEAT,\tVEHICLE_FLAG_POS | CLUMP_FLAG_NO_HIERID },\n\t{ \"ped_backseat\",\tCAR_POS_BACKSEAT,\tVEHICLE_FLAG_POS | CLUMP_FLAG_NO_HIERID },\n\t{ \"headlights\",\t\tCAR_POS_HEADLIGHTS,\tVEHICLE_FLAG_POS | CLUMP_FLAG_NO_HIERID },\n\t{ \"taillights\",\t\tCAR_POS_TAILLIGHTS,\tVEHICLE_FLAG_POS | CLUMP_FLAG_NO_HIERID },\n\t{ \"exhaust\",\t\tCAR_POS_EXHAUST,\tVEHICLE_FLAG_POS | CLUMP_FLAG_NO_HIERID },\n\t{ \"extra1\",\t\t0, VEHICLE_FLAG_DRAWLAST | VEHICLE_FLAG_COMP | CLUMP_FLAG_NO_HIERID },\n\t{ \"extra2\",\t\t0, VEHICLE_FLAG_DRAWLAST | VEHICLE_FLAG_COMP | CLUMP_FLAG_NO_HIERID },\n\t{ \"extra3\",\t\t0, VEHICLE_FLAG_DRAWLAST | VEHICLE_FLAG_COMP | CLUMP_FLAG_NO_HIERID },\n\t{ \"extra4\",\t\t0, VEHICLE_FLAG_DRAWLAST | VEHICLE_FLAG_COMP | CLUMP_FLAG_NO_HIERID },\n\t{ \"extra5\",\t\t0, VEHICLE_FLAG_DRAWLAST | VEHICLE_FLAG_COMP | CLUMP_FLAG_NO_HIERID },\n\t{ \"extra6\",\t\t0, VEHICLE_FLAG_DRAWLAST | VEHICLE_FLAG_COMP | CLUMP_FLAG_NO_HIERID },\n\t{ nil, 0, 0 }\n};\n\nRwObjectNameIdAssocation boatIds[] = {\n\t{ \"boat_moving_hi\",\tBOAT_MOVING,\t0 },\n\t{ \"boat_rudder_hi\",\tBOAT_RUDDER,\t0 },\n\t{ \"boat_flap_left\",\tBOAT_FLAP_LEFT,\t0 },\n\t{ \"boat_flap_right\",\tBOAT_FLAP_RIGHT,\t0 },\n\t{ \"boat_rearflap_left\",\tBOAT_REARFLAP_LEFT,\t0 },\n\t{ \"boat_rearflap_right\",\tBOAT_REARFLAP_RIGHT,\t0 },\n#ifdef FIX_BUGS\n\t// let's just accept both\n\t{ \"windscreen\",\t\tBOAT_WINDSCREEN,\tVEHICLE_FLAG_WINDSCREEN | VEHICLE_FLAG_DRAWLAST },\n\t{ \"windscreen_hi_ok\",\t\tBOAT_WINDSCREEN,\tVEHICLE_FLAG_WINDSCREEN | VEHICLE_FLAG_DRAWLAST },\n#else\n#ifdef GTA_PS2\n\t{ \"windscreen\",\t\tBOAT_WINDSCREEN,\tVEHICLE_FLAG_WINDSCREEN | VEHICLE_FLAG_DRAWLAST },\n#else\n\t{ \"windscreen_hi_ok\",\t\tBOAT_WINDSCREEN,\tVEHICLE_FLAG_WINDSCREEN | VEHICLE_FLAG_DRAWLAST },\n#endif\n#endif\n\t{ \"ped_frontseat\",\tBOAT_POS_FRONTSEAT,\tVEHICLE_FLAG_POS | CLUMP_FLAG_NO_HIERID },\n\t{ nil, 0, 0 }\n};\n\nRwObjectNameIdAssocation trainIds[] = {\n\t{ \"door_lhs_dummy\",\tTRAIN_DOOR_LHS,\tVEHICLE_FLAG_LEFT | VEHICLE_FLAG_COLLAPSE },\n\t{ \"door_rhs_dummy\",\tTRAIN_DOOR_RHS,\tVEHICLE_FLAG_LEFT | VEHICLE_FLAG_COLLAPSE },\n\t{ \"light_front\",\tTRAIN_POS_LIGHT_FRONT,\tVEHICLE_FLAG_POS | CLUMP_FLAG_NO_HIERID },\n\t{ \"light_rear\",\t\tTRAIN_POS_LIGHT_REAR,\tVEHICLE_FLAG_POS | CLUMP_FLAG_NO_HIERID },\n\t{ \"ped_left_entry\",\tTRAIN_POS_LEFT_ENTRY,\tVEHICLE_FLAG_DOOR | VEHICLE_FLAG_POS | CLUMP_FLAG_NO_HIERID },\n\t{ \"ped_mid_entry\",\tTRAIN_POS_MID_ENTRY,\tVEHICLE_FLAG_DOOR | VEHICLE_FLAG_POS | CLUMP_FLAG_NO_HIERID },\n\t{ \"ped_right_entry\",\tTRAIN_POS_RIGHT_ENTRY,\tVEHICLE_FLAG_DOOR | VEHICLE_FLAG_POS | CLUMP_FLAG_NO_HIERID },\n\t{ nil, 0, 0 }\n};\n\nRwObjectNameIdAssocation heliIds[] = {\n\t{ \"chassis_dummy\",\tHELI_CHASSIS,\tVEHICLE_FLAG_COLLAPSE },\n\t{ \"toprotor\",\t\tHELI_TOPROTOR,\t0 },\n\t{ \"backrotor\",\t\tHELI_BACKROTOR,\t0 },\n\t{ \"tail\",\t\tHELI_TAIL,\t0 },\n\t{ \"topknot\",\t\tHELI_TOPKNOT,\t0 },\n\t{ \"skid_left\",\t\tHELI_SKID_LEFT,\t0 },\n\t{ \"skid_right\",\t\tHELI_SKID_RIGHT,\t0 },\n\t{ nil, 0, 0 }\n};\n\nRwObjectNameIdAssocation planeIds[] = {\n\t{ \"wheel_front_dummy\",\tPLANE_WHEEL_FRONT,\t0 },\n\t{ \"wheel_rear_dummy\",\tPLANE_WHEEL_READ,\t0 },\n\t{ \"light_tailplane\",\tPLANE_POS_LIGHT_TAIL,\tVEHICLE_FLAG_POS | CLUMP_FLAG_NO_HIERID },\n\t{ \"light_left\",\t\tPLANE_POS_LIGHT_LEFT,\tVEHICLE_FLAG_POS | CLUMP_FLAG_NO_HIERID },\n\t{ \"light_right\",\tPLANE_POS_LIGHT_RIGHT,\tVEHICLE_FLAG_POS | CLUMP_FLAG_NO_HIERID },\n\t{ nil, 0, 0 }\n};\n\nRwObjectNameIdAssocation bikeIds[] = {\n\t{ \"chassis_dummy\",\tBIKE_CHASSIS,\t0 },\n\t{ \"forks_front\",\tBIKE_FORKS_FRONT,\t0 },\n\t{ \"forks_rear\",\t\tBIKE_FORKS_REAR,\t0 },\n\t{ \"wheel_front\",\tBIKE_WHEEL_FRONT,\t0 },\n\t{ \"wheel_rear\",\t\tBIKE_WHEEL_REAR,\t0 },\n\t{ \"mudguard\",\t\tBIKE_MUDGUARD,\t0 },\n\t{ \"handlebars\",\t\tBIKE_HANDLEBARS,\t0 },\n\t{ \"ped_frontseat\",\tCAR_POS_FRONTSEAT,\tVEHICLE_FLAG_POS | CLUMP_FLAG_NO_HIERID },\n\t{ \"ped_backseat\",\tCAR_POS_BACKSEAT,\tVEHICLE_FLAG_POS | CLUMP_FLAG_NO_HIERID },\n\t{ \"headlights\",\t\tCAR_POS_HEADLIGHTS,\tVEHICLE_FLAG_POS | CLUMP_FLAG_NO_HIERID },\n\t{ \"taillights\",\t\tCAR_POS_TAILLIGHTS,\tVEHICLE_FLAG_POS | CLUMP_FLAG_NO_HIERID },\n\t{ \"exhaust\",\t\tCAR_POS_EXHAUST,\tVEHICLE_FLAG_POS | CLUMP_FLAG_NO_HIERID },\n\t{ \"extra1\",\t\t0,\tVEHICLE_FLAG_DRAWLAST | VEHICLE_FLAG_COMP | CLUMP_FLAG_NO_HIERID },\n\t{ \"extra2\",\t\t0,\tVEHICLE_FLAG_DRAWLAST | VEHICLE_FLAG_COMP | CLUMP_FLAG_NO_HIERID },\n\t{ \"extra3\",\t\t0,\tVEHICLE_FLAG_DRAWLAST | VEHICLE_FLAG_COMP | CLUMP_FLAG_NO_HIERID },\n\t{ \"extra4\",\t\t0,\tVEHICLE_FLAG_DRAWLAST | VEHICLE_FLAG_COMP | CLUMP_FLAG_NO_HIERID },\n\t{ \"extra5\",\t\t0,\tVEHICLE_FLAG_DRAWLAST | VEHICLE_FLAG_COMP | CLUMP_FLAG_NO_HIERID },\n\t{ \"extra6\",\t\t0,\tVEHICLE_FLAG_DRAWLAST | VEHICLE_FLAG_COMP | CLUMP_FLAG_NO_HIERID },\n\t{ nil, 0, 0 }\n};\n\nRwObjectNameIdAssocation *CVehicleModelInfo::ms_vehicleDescs[] = {\n\tcarIds,\n\tboatIds,\n\ttrainIds,\n\theliIds,\n\tplaneIds,\n\tbikeIds\n};\n\nbool gbBlackCars;\nbool gbPinkCars;\n\nCVehicleModelInfo::CVehicleModelInfo(void)\n : CClumpModelInfo(MITYPE_VEHICLE)\n{\n\tint32 i;\n\tfor(i = 0; i < NUM_VEHICLE_POSITIONS; i++){\n\t\tm_positions[i].x = 0.0f;\n\t\tm_positions[i].y = 0.0f;\n\t\tm_positions[i].z = 0.0f;\n\t}\n\tm_numColours = 0;\n\tm_animFileIndex = -1;\n}\n\nvoid\nCVehicleModelInfo::DeleteRwObject(void)\n{\n\tint32 i;\n\tRwFrame *f;\n\n\tfor(i = 0; i < m_numComps; i++){\n\t\tf = RpAtomicGetFrame(m_comps[i]);\n\t\tRpAtomicDestroy(m_comps[i]);\n\t\tRwFrameDestroy(f);\n\t}\n\tm_numComps = 0;\n\tCClumpModelInfo::DeleteRwObject();\n}\n\nRwObject*\nCVehicleModelInfo::CreateInstance(void)\n{\n\tRpClump *clump;\n\tRpAtomic *atomic;\n\tRwFrame *clumpframe, *f;\n\tint32 comp1, comp2;\n\n\tclump = (RpClump*)CClumpModelInfo::CreateInstance();\n\tif(m_numComps != 0){\n\t\tclumpframe = RpClumpGetFrame(clump);\n\n\t\tcomp1 = ChooseComponent();\n\t\tif(comp1 != -1 && m_comps[comp1]){\n\t\t\tatomic = RpAtomicClone(m_comps[comp1]);\n\t\t\tf = RwFrameCreate();\n\t\t\tRwFrameTransform(f,\n\t\t\t\tRwFrameGetMatrix(RpAtomicGetFrame(m_comps[comp1])),\n\t\t\t\trwCOMBINEREPLACE);\n\t\t\tRpAtomicSetFrame(atomic, f);\n\t\t\tRpClumpAddAtomic(clump, atomic);\n\t\t\tRwFrameAddChild(clumpframe, f);\n\t\t}\n\t\tms_compsUsed[0] = comp1;\n\n\t\tcomp2 = ChooseSecondComponent();\n\t\tif(comp2 != -1 && m_comps[comp2]){\n\t\t\tatomic = RpAtomicClone(m_comps[comp2]);\n\t\t\tf = RwFrameCreate();\n\t\t\tRwFrameTransform(f,\n\t\t\t\tRwFrameGetMatrix(RpAtomicGetFrame(m_comps[comp2])),\n\t\t\t\trwCOMBINEREPLACE);\n\t\t\tRpAtomicSetFrame(atomic, f);\n\t\t\tRpClumpAddAtomic(clump, atomic);\n\t\t\tRwFrameAddChild(clumpframe, f);\n\t\t}\n\t\tms_compsUsed[1] = comp2;\n\t}else{\n\t\tms_compsUsed[0] = -1;\n\t\tms_compsUsed[1] = -1;\n\t}\n\treturn (RwObject*)clump;\n}\n\nvoid\nCVehicleModelInfo::SetClump(RpClump *clump)\n{\n\tCClumpModelInfo::SetClump(clump);\n\tSetAtomicRenderCallbacks();\n\tSetFrameIds(ms_vehicleDescs[m_vehicleType]);\n\tPreprocessHierarchy();\n\tFindEditableMaterialList();\n\tSetEnvironmentMap();\n}\n\nvoid\nCVehicleModelInfo::SetAnimFile(const char *file)\n{\n\tif(strcasecmp(file, \"null\") == 0)\n\t\treturn;\n\n\tm_animFileName = new char[strlen(file)+1];\n\tstrcpy(m_animFileName, file);\n}\n\nvoid\nCVehicleModelInfo::ConvertAnimFileIndex(void)\n{\n\tif(m_animFileIndex != -1){\n\t\t// we have a string pointer in that union\n\t\tint32 index = CAnimManager::GetAnimationBlockIndex(m_animFileName);\n\t\tdelete[] m_animFileName;\n\t\tm_animFileIndex = index;\n\t}\n}\n\nRwFrame*\nCVehicleModelInfo::CollapseFramesCB(RwFrame *frame, void *data)\n{\n\tRwFrameForAllChildren(frame, CollapseFramesCB, data);\n\tRwFrameForAllObjects(frame, MoveObjectsCB, data);\n\tRwFrameDestroy(frame);\n\treturn frame;\n}\n\nRwObject*\nCVehicleModelInfo::MoveObjectsCB(RwObject *object, void *data)\n{\n\tRpAtomicSetFrame((RpAtomic*)object, (RwFrame*)data);\n\treturn object;\n}\n\nRpAtomic*\nCVehicleModelInfo::HideDamagedAtomicCB(RpAtomic *atomic, void *data)\n{\n\tif(strstr(GetFrameNodeName(RpAtomicGetFrame(atomic)), \"_dam\")){\n\t\tRpAtomicSetFlags(atomic, 0);\n\t\tCVisibilityPlugins::SetAtomicFlag(atomic, ATOMIC_FLAG_DAM);\n\t}else if(strstr(GetFrameNodeName(RpAtomicGetFrame(atomic)), \"_ok\"))\n\t\tCVisibilityPlugins::SetAtomicFlag(atomic, ATOMIC_FLAG_OK);\n\treturn atomic;\n}\n\nRpAtomic*\nCVehicleModelInfo::HideAllComponentsAtomicCB(RpAtomic *atomic, void *data)\n{\n\tif(CVisibilityPlugins::GetAtomicId(atomic) & (uintptr)data)\n\t\tRpAtomicSetFlags(atomic, 0);\n\telse\n\t\tRpAtomicSetFlags(atomic, rpATOMICRENDER);\n\treturn atomic;\n}\n\nRpMaterial*\nCVehicleModelInfo::HasAlphaMaterialCB(RpMaterial *material, void *data)\n{\n\tif(RpMaterialGetColor(material)->alpha != 0xFF){\n\t\t*(bool*)data = true;\n\t\treturn nil;\n\t}\n\treturn material;\n}\n\n\nRpAtomic*\nCVehicleModelInfo::SetAtomicRendererCB(RpAtomic *atomic, void *data)\n{\n\tRpClump *clump;\n\tchar *name;\n\tbool alpha;\n\n\tclump = (RpClump*)data;\n\tname = GetFrameNodeName(RpAtomicGetFrame(atomic));\n\talpha = false;\n\tRpGeometryForAllMaterials(RpAtomicGetGeometry(atomic), HasAlphaMaterialCB, &alpha);\n\tif(strstr(name, \"_hi\") || !CGeneral::faststrncmp(name, \"extra\", 5)) {\n\t\tif(alpha || strncmp(name, \"windscreen\", 10) == 0)\n\t\t\tCVisibilityPlugins::SetAtomicRenderCallback(atomic, CVisibilityPlugins::RenderVehicleHiDetailAlphaCB);\n\t\telse\n\t\t\tCVisibilityPlugins::SetAtomicRenderCallback(atomic, CVisibilityPlugins::RenderVehicleHiDetailCB);\n\t}else if(strstr(name, \"_lo\")){\n\t\tRpClumpRemoveAtomic(clump, atomic);\n\t\tRpAtomicDestroy(atomic);\n\t\treturn atomic;\t\t// BUG: nil in gta\n\t}else if(strstr(name, \"_vlo\"))\n\t\tCVisibilityPlugins::SetAtomicRenderCallback(atomic, CVisibilityPlugins::RenderVehicleReallyLowDetailCB);\n\telse\n\t\tCVisibilityPlugins::SetAtomicRenderCallback(atomic, nil);\n\tHideDamagedAtomicCB(atomic, nil);\n\treturn atomic;\n}\n\nRpAtomic*\nCVehicleModelInfo::SetAtomicRendererCB_BigVehicle(RpAtomic *atomic, void *data)\n{\n\tchar *name;\n\tbool alpha;\n\n\tname = GetFrameNodeName(RpAtomicGetFrame(atomic));\n\talpha = false;\n\tRpGeometryForAllMaterials(RpAtomicGetGeometry(atomic), HasAlphaMaterialCB, &alpha);\n\tif(strstr(name, \"_hi\") || !CGeneral::faststrncmp(name, \"extra\", 5)) {\n\t\tif(alpha)\n\t\t\tCVisibilityPlugins::SetAtomicRenderCallback(atomic, CVisibilityPlugins::RenderVehicleHiDetailAlphaCB_BigVehicle);\n\t\telse\n\t\t\tCVisibilityPlugins::SetAtomicRenderCallback(atomic, CVisibilityPlugins::RenderVehicleHiDetailCB_BigVehicle);\n\t}else if(strstr(name, \"_lo\")){\n\t\tif(alpha)\n\t\t\tCVisibilityPlugins::SetAtomicRenderCallback(atomic, CVisibilityPlugins::RenderVehicleLowDetailAlphaCB_BigVehicle);\n\t\telse\n\t\t\tCVisibilityPlugins::SetAtomicRenderCallback(atomic, CVisibilityPlugins::RenderVehicleLowDetailCB_BigVehicle);\n\t}else if(strstr(name, \"_vlo\"))\n\t\tCVisibilityPlugins::SetAtomicRenderCallback(atomic, CVisibilityPlugins::RenderVehicleReallyLowDetailCB_BigVehicle);\n\telse\n\t\tCVisibilityPlugins::SetAtomicRenderCallback(atomic, nil);\n\tHideDamagedAtomicCB(atomic, nil);\n\treturn atomic;\n}\n\nRpAtomic*\nCVehicleModelInfo::SetAtomicRendererCB_Train(RpAtomic *atomic, void *data)\n{\n\tchar *name;\n\tbool alpha;\n\n\tname = GetFrameNodeName(RpAtomicGetFrame(atomic));\n\talpha = false;\n\tRpGeometryForAllMaterials(RpAtomicGetGeometry(atomic), HasAlphaMaterialCB, &alpha);\n\tif(strstr(name, \"_hi\")){\n\t\tif(alpha)\n\t\t\tCVisibilityPlugins::SetAtomicRenderCallback(atomic, CVisibilityPlugins::RenderTrainHiDetailAlphaCB);\n\t\telse\n\t\t\tCVisibilityPlugins::SetAtomicRenderCallback(atomic, CVisibilityPlugins::RenderTrainHiDetailCB);\n\t}else if(strstr(name, \"_vlo\"))\n\t\tCVisibilityPlugins::SetAtomicRenderCallback(atomic, CVisibilityPlugins::RenderVehicleReallyLowDetailCB_BigVehicle);\n\telse\n\t\tCVisibilityPlugins::SetAtomicRenderCallback(atomic, nil);\n\tHideDamagedAtomicCB(atomic, nil);\n\treturn atomic;\n}\n\nRpAtomic*\nCVehicleModelInfo::SetAtomicRendererCB_Boat(RpAtomic *atomic, void *data)\n{\n\tRpClump *clump;\n\tchar *name;\n\tbool alpha;\n\n\tclump = (RpClump*)data;\n\tname = GetFrameNodeName(RpAtomicGetFrame(atomic));\n\talpha = false;\n\tRpGeometryForAllMaterials(RpAtomicGetGeometry(atomic), HasAlphaMaterialCB, &alpha);\n\tif(strcmp(name, \"boat_hi\") == 0 || !CGeneral::faststrncmp(name, \"extra\", 5))\n\t\tCVisibilityPlugins::SetAtomicRenderCallback(atomic, CVisibilityPlugins::RenderVehicleHiDetailCB_Boat);\n\telse if(strstr(name, \"_hi\")){\n\t\tif(alpha)\n\t\t\tCVisibilityPlugins::SetAtomicRenderCallback(atomic, CVisibilityPlugins::RenderVehicleHiDetailAlphaCB_Boat);\n\t\telse\n\t\t\tCVisibilityPlugins::SetAtomicRenderCallback(atomic, CVisibilityPlugins::RenderVehicleHiDetailCB);\n\t}else if(strstr(name, \"_lo\")){\n\t\tRpClumpRemoveAtomic(clump, atomic);\n\t\tRpAtomicDestroy(atomic);\n\t\treturn atomic;\t\t// BUG: not done by gta\n\t}else if(strstr(name, \"_vlo\"))\n\t\tCVisibilityPlugins::SetAtomicRenderCallback(atomic, CVisibilityPlugins::RenderVehicleLoDetailCB_Boat);\n\telse{\n\t\tif(alpha)\n\t\t\tCVisibilityPlugins::SetAtomicRenderCallback(atomic, CVisibilityPlugins::RenderVehicleHiDetailAlphaCB_Boat);\n\t\telse\n\t\t\tCVisibilityPlugins::SetAtomicRenderCallback(atomic, nil);\n\t}\n\tHideDamagedAtomicCB(atomic, nil);\n\treturn atomic;\n}\n\nRpAtomic*\nCVehicleModelInfo::SetAtomicRendererCB_Heli(RpAtomic *atomic, void *data)\n{\n\tchar *name;\n\n\tname = GetFrameNodeName(RpAtomicGetFrame(atomic));\n\tif(strncmp(name, \"toprotor\", 8) == 0)\n\t\tCVisibilityPlugins::SetAtomicRenderCallback(atomic, CVisibilityPlugins::RenderVehicleRotorAlphaCB);\n\telse if(strncmp(name, \"rearrotor\", 9) == 0)\n\t\tCVisibilityPlugins::SetAtomicRenderCallback(atomic, CVisibilityPlugins::RenderVehicleTailRotorAlphaCB);\n\telse\n\t\tCVisibilityPlugins::SetAtomicRenderCallback(atomic, nil);\n\treturn atomic;\n}\n\nRpAtomic*\nCVehicleModelInfo::SetAtomicRendererCB_RealHeli(RpAtomic *atomic, void *data)\n{\n\tRpClump *clump;\n\tchar *name;\n\tbool alpha;\n\n\tclump = (RpClump*)data;\n\tname = GetFrameNodeName(RpAtomicGetFrame(atomic));\n\talpha = false;\n\tRpGeometryForAllMaterials(RpAtomicGetGeometry(atomic), HasAlphaMaterialCB, &alpha);\n\tif(strncmp(name, \"toprotor\", 8) == 0)\n\t\tCVisibilityPlugins::SetAtomicRenderCallback(atomic, CVisibilityPlugins::RenderVehicleRotorAlphaCB);\n\telse if(strncmp(name, \"rearrotor\", 9) == 0)\n\t\tCVisibilityPlugins::SetAtomicRenderCallback(atomic, CVisibilityPlugins::RenderVehicleTailRotorAlphaCB);\n\telse if(strstr(name, \"_hi\") || !CGeneral::faststrncmp(name, \"extra\", 5)) {\n\t\tif(alpha || strncmp(name, \"windscreen\", 10) == 0)\n\t\t\tCVisibilityPlugins::SetAtomicRenderCallback(atomic, CVisibilityPlugins::RenderVehicleHiDetailAlphaCB);\n\t\telse\n\t\t\tCVisibilityPlugins::SetAtomicRenderCallback(atomic, CVisibilityPlugins::RenderVehicleHiDetailCB);\n\t}else if(strstr(name, \"_lo\")){\n\t\tRpClumpRemoveAtomic(clump, atomic);\n\t\tRpAtomicDestroy(atomic);\n\t\treturn atomic;\t\t// BUG: nil in gta\n\t}else if(strstr(name, \"_vlo\"))\n\t\tCVisibilityPlugins::SetAtomicRenderCallback(atomic, CVisibilityPlugins::RenderVehicleReallyLowDetailCB);\n\telse\n\t\tCVisibilityPlugins::SetAtomicRenderCallback(atomic, nil);\n\tHideDamagedAtomicCB(atomic, nil);\n\treturn atomic;\n}\n\nvoid\nCVehicleModelInfo::SetAtomicRenderCallbacks(void)\n{\n#ifdef GTA_TRAIN\n\tif(m_vehicleType == VEHICLE_TYPE_TRAIN)\n\t\tRpClumpForAllAtomics(m_clump, SetAtomicRendererCB_Train, nil);\n\telse\n#endif\n\tif(m_vehicleType == VEHICLE_TYPE_HELI)\n\t\tRpClumpForAllAtomics(m_clump, SetAtomicRendererCB_Heli, nil);\n\telse if(m_vehicleType == VEHICLE_TYPE_PLANE)\n\t\tRpClumpForAllAtomics(m_clump, SetAtomicRendererCB_BigVehicle, nil);\n\telse if(m_vehicleType == VEHICLE_TYPE_BOAT)\n\t\tRpClumpForAllAtomics(m_clump, SetAtomicRendererCB_Boat, m_clump);\n\telse if(mod_HandlingManager.GetHandlingData((tVehicleType)m_handlingId)->Flags & HANDLING_IS_HELI)\n\t\tRpClumpForAllAtomics(m_clump, SetAtomicRendererCB_RealHeli, m_clump);\n\telse\n\t\tRpClumpForAllAtomics(m_clump, SetAtomicRendererCB, m_clump);\n}\n\nRwObject*\nCVehicleModelInfo::SetAtomicFlagCB(RwObject *object, void *data)\n{\n\tRpAtomic *atomic = (RpAtomic*)object;\n\tassert(RwObjectGetType(object) == rpATOMIC);\n\tCVisibilityPlugins::SetAtomicFlag(atomic, (uintptr)data);\n\treturn object;\n}\n\nRwObject*\nCVehicleModelInfo::ClearAtomicFlagCB(RwObject *object, void *data)\n{\n\tRpAtomic *atomic = (RpAtomic*)object;\n\tassert(RwObjectGetType(object) == rpATOMIC);\n\tCVisibilityPlugins::ClearAtomicFlag(atomic, (uintptr)data);\n\treturn object;\n}\n\nRwObject*\nGetOkAndDamagedAtomicCB(RwObject *object, void *data)\n{\n\tRpAtomic *atomic = (RpAtomic*)object;\n\tif(CVisibilityPlugins::GetAtomicId(atomic) & ATOMIC_FLAG_OK)\n\t\t((RpAtomic**)data)[0] = atomic;\n\telse if(CVisibilityPlugins::GetAtomicId(atomic) & ATOMIC_FLAG_DAM)\n\t\t((RpAtomic**)data)[1] = atomic;\n\treturn object;\n}\n\nvoid\nCVehicleModelInfo::PreprocessHierarchy(void)\n{\n\tint32 i;\n\tRwObjectNameIdAssocation *desc;\n\tRwFrame *f;\n\tRpAtomic *atomic;\n\tRwV3d *rwvec;\n\n\tdesc = ms_vehicleDescs[m_vehicleType];\n\tm_numDoors = 0;\n\tm_numComps = 0;\n\n\tfor(i = 0; desc[i].name; i++){\n\t\tRwObjectNameAssociation assoc;\n\n\t\tif((desc[i].flags & (VEHICLE_FLAG_COMP|VEHICLE_FLAG_POS)) == 0)\n\t\t\tcontinue;\n\t\tassoc.frame = nil;\n\t\tassoc.name = desc[i].name;\n\t\tRwFrameForAllChildren(RpClumpGetFrame(m_clump),\n\t\t\tFindFrameFromNameWithoutIdCB, &assoc);\n\t\tif(assoc.frame == nil)\n\t\t\tcontinue;\n\n\t\tif(desc[i].flags & VEHICLE_FLAG_DOOR)\n\t\t\tm_numDoors++;\n\n\t\tif(desc[i].flags & VEHICLE_FLAG_POS){\n\t\t\tf = assoc.frame;\n\t\t\trwvec = &m_positions[desc[i].hierId];\n\t\t\t*rwvec = *RwMatrixGetPos(RwFrameGetMatrix(f));\n\t\t\tfor(f = RwFrameGetParent(f); f; f = RwFrameGetParent(f))\n\t\t\t\tRwV3dTransformPoints(rwvec, rwvec, 1, RwFrameGetMatrix(f));\n\t\t\tRwFrameDestroy(assoc.frame);\n\t\t}else{\n\t\t\tatomic = (RpAtomic*)GetFirstObject(assoc.frame);\n\t\t\tRpClumpRemoveAtomic(m_clump, atomic);\n\t\t\tRwFrameRemoveChild(assoc.frame);\n\t\t\tSetVehicleComponentFlags(assoc.frame, desc[i].flags);\n\t\t\tm_comps[m_numComps++] = atomic;\n\t\t}\n\t}\n\n\tfor(i = 0; desc[i].name; i++){\n\t\tRwObjectIdAssociation assoc;\n\n\t\tif(desc[i].flags & (VEHICLE_FLAG_COMP|VEHICLE_FLAG_POS))\n\t\t\tcontinue;\n\t\tassoc.frame = nil;\n\t\tassoc.id = desc[i].hierId;\n\t\tRwFrameForAllChildren(RpClumpGetFrame(m_clump),\n\t\t\tFindFrameFromIdCB, &assoc);\n\t\tif(assoc.frame == nil)\n\t\t\tcontinue;\n\n\t\tif(desc[i].flags & VEHICLE_FLAG_DOOR)\n\t\t\tm_numDoors++;\n\n\t\tif(desc[i].flags & VEHICLE_FLAG_COLLAPSE){\n\t\t\tRpAtomic *okdam[2] = { nil, nil };\n\t\t\tRwFrameForAllChildren(assoc.frame, CollapseFramesCB, assoc.frame);\n\t\t\tRwFrameUpdateObjects(assoc.frame);\n\t\t\tRwFrameForAllObjects(assoc.frame, GetOkAndDamagedAtomicCB, okdam);\n\t\t\tif(okdam[0] && okdam[1])\n\t\t\t\tRpAtomicSetRenderCallBack(okdam[1], RpAtomicGetRenderCallBack(okdam[0]));\n\t\t}\n\n\t\tSetVehicleComponentFlags(assoc.frame, desc[i].flags);\n\n\t\tif(desc[i].flags & VEHICLE_FLAG_ADD_WHEEL){\n\t\t\tif(m_wheelId == -1)\n\t\t\t\tRwFrameDestroy(assoc.frame);\n\t\t\telse{\n\t\t\t\tRwV3d scale;\n\t\t\t\tatomic = (RpAtomic*)CModelInfo::GetModelInfo(m_wheelId)->CreateInstance();\n\t\t\t\tRwFrameDestroy(RpAtomicGetFrame(atomic));\n\t\t\t\tRpAtomicSetFrame(atomic, assoc.frame);\n\t\t\t\tRpClumpAddAtomic(m_clump, atomic);\n\t\t\t\tCVisibilityPlugins::SetAtomicRenderCallback(atomic,\n\t\t\t\t\tCVisibilityPlugins::RenderWheelAtomicCB);\n\t\t\t\tscale.x = m_wheelScale;\n\t\t\t\tscale.y = m_wheelScale;\n\t\t\t\tscale.z = m_wheelScale;\n\t\t\t\tRwFrameScale(assoc.frame, &scale, rwCOMBINEPRECONCAT);\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nCVehicleModelInfo::SetVehicleComponentFlags(RwFrame *frame, uint32 flags)\n{\n\ttHandlingData *handling;\n\n\thandling = mod_HandlingManager.GetHandlingData((tVehicleType)m_handlingId);\n\n#define SETFLAGS(f) RwFrameForAllObjects(frame, SetAtomicFlagCB, (void*)(f))\n\n\tif(flags & VEHICLE_FLAG_WINDSCREEN){\n\t\tif(this == CModelInfo::GetModelInfo(MI_RHINO))\n\t\t\treturn;\n\t\tSETFLAGS(ATOMIC_FLAG_WINDSCREEN);\n\t}\n\n\tif(flags & VEHICLE_FLAG_ANGLECULL)\n\t\tSETFLAGS(ATOMIC_FLAG_ANGLECULL);\n\n\tif(flags & VEHICLE_FLAG_FRONT)\n\t\tSETFLAGS(ATOMIC_FLAG_FRONT);\n\telse if(flags & VEHICLE_FLAG_REAR && (handling->Flags & HANDLING_IS_VAN || (flags & (VEHICLE_FLAG_LEFT|VEHICLE_FLAG_RIGHT)) == 0))\n\t\tSETFLAGS(ATOMIC_FLAG_REAR);\n\telse if(flags & VEHICLE_FLAG_LEFT)\n\t\tSETFLAGS(ATOMIC_FLAG_LEFT);\n\telse if(flags & VEHICLE_FLAG_RIGHT)\n\t\tSETFLAGS(ATOMIC_FLAG_RIGHT);\n\n\tif(flags & VEHICLE_FLAG_REARDOOR)\n\t\tSETFLAGS(ATOMIC_FLAG_REARDOOR);\n\telse if(flags & VEHICLE_FLAG_FRONTDOOR)\n\t\tSETFLAGS(ATOMIC_FLAG_FRONTDOOR);\n\n\tif(flags & VEHICLE_FLAG_DRAWLAST)\n\t\tSETFLAGS(ATOMIC_FLAG_DRAWLAST);\n}\n\n#define COMPRULE_RULE(comprule) (((comprule) >> 12) & 0xF)\n#define COMPRULE_COMPS(comprule) ((comprule) & 0xFFF)\n#define COMPRULE_COMPN(comps, n) (((comps) >> 4*(n)) & 0xF)\n#define COMPRULE2_RULE(comprule) (((comprule) >> (12+16)) & 0xF)\n#define COMPRULE2_COMPS(comprule) ((comprule >> 16) & 0xFFF)\n#define COMPRULE2_COMPN(comps, n) (((comps >> 16) >> 4*(n)) & 0xF)\n\nbool\nIsValidCompRule(int rule)\n{\n\tif(rule == 2)\n\t\treturn CWeather::OldWeatherType == WEATHER_RAINY ||\n\t\t       CWeather::NewWeatherType == WEATHER_RAINY;\n\treturn true;\n}\n\nint32\nCountCompsInRule(int comps)\n{\n\tint32 n;\n\tfor(n = 0; comps != 0; comps >>= 4)\n\t\tif((comps & 0xF) != 0xF)\n\t\t\tn++;\n\treturn n;\n}\n\nint32\nChooseComponent(int32 rule, int32 comps)\n{\n\tint32 n;\n\tswitch(rule){\n\t// identical cases....\n\tcase 1:\n\t\tn = CGeneral::GetRandomNumberInRange(0, CountCompsInRule(comps));\n\t\treturn COMPRULE_COMPN(comps, n);\n\tcase 2:\n\t\t// only valid in rain\n\t\tn = CGeneral::GetRandomNumberInRange(0, CountCompsInRule(comps));\n\t\treturn COMPRULE_COMPN(comps, n);\n\tcase 3:\n\t\tn = CGeneral::GetRandomNumberInRange(0, 1+CountCompsInRule(comps));\n\t\tif(n != 0)\n\t\t\treturn COMPRULE_COMPN(comps, n-1);\n\t\treturn -1;\n\tcase 4:\n#ifdef FIX_BUGS\n\t\treturn CGeneral::GetRandomNumberInRange(0, 6);\n#else\n\t\treturn CGeneral::GetRandomNumberInRange(0, 5);\n#endif\n\t}\n\treturn -1;\n}\n\nint32\nGetListOfComponentsNotUsedByRules(uint32 comprules, int32 numComps, int32 *comps)\n{\n\tint32 i, n;\n\tint32 unused[6] = { 0, 1, 2, 3, 4, 5 };\n\n\t// first comprule\n\tif(COMPRULE_RULE(comprules) && IsValidCompRule(COMPRULE_RULE(comprules)))\n\t\tfor(i = 0; i < 3; i++){\n\t\t\tn = COMPRULE_COMPN(comprules, i);\n\t\t\tif(n != 0xF)\n\t\t\t\tunused[n] = 0xF;\n\t\t}\n\t// second comprule\n\tcomprules >>= 16;\n\tif(COMPRULE_RULE(comprules) && IsValidCompRule(COMPRULE_RULE(comprules)))\n\t\tfor(i = 0; i < 3; i++){\n\t\t\tn = COMPRULE_COMPN(comprules, i);\n\t\t\tif(n != 0xF)\n\t\t\t\tunused[n] = 0xF;\n\t\t}\n\n\tn = 0;\n\tfor(i = 0; i < numComps; i++)\n\t\tif(unused[i] != 0xF)\n\t\t\tcomps[n++] = unused[i];\n\treturn n;\n}\n\nint32 wheelIds[] = { CAR_WHEEL_LF, CAR_WHEEL_LB, CAR_WHEEL_RF, CAR_WHEEL_RB };\n\nvoid\nCVehicleModelInfo::GetWheelPosn(int32 n, CVector &pos)\n{\n\tRwMatrix *m = RwFrameGetMatrix(GetFrameFromId(m_clump, wheelIds[n]));\n\tpos.x = RwMatrixGetPos(m)->x;\n\tpos.y = RwMatrixGetPos(m)->y;\n\tpos.z = RwMatrixGetPos(m)->z;\n}\n\n\nint32\nCVehicleModelInfo::ChooseComponent(void)\n{\n\tint32 comp;\n\tint32 comps[8];\n\tint32 n;\n\n\tcomp = -1;\n\tif(ms_compsToUse[0] == -2){\n\t\tif(COMPRULE_RULE(m_compRules) && IsValidCompRule(COMPRULE_RULE(m_compRules)))\n\t\t\tcomp = ::ChooseComponent(COMPRULE_RULE(m_compRules), COMPRULE_COMPS(m_compRules));\n\t\telse if(CGeneral::GetRandomNumberInRange(0, 3) < 2){\n\t\t\tn = GetListOfComponentsNotUsedByRules(m_compRules, m_numComps, comps);\n\t\t\tif(n)\n\t\t\t\tcomp = comps[(int)CGeneral::GetRandomNumberInRange(0, n)];\n\t\t}\n\t}else{\n\t\tcomp = ms_compsToUse[0];\n\t\tms_compsToUse[0] = -2;\n\t}\n\treturn comp;\n}\n\nint32\nCVehicleModelInfo::ChooseSecondComponent(void)\n{\n\tint32 comp;\n\tint32 comps[8];\n\tint32 n;\n\n\tcomp = -1;\n\tif(ms_compsToUse[1] == -2){\n\t\tif(COMPRULE2_RULE(m_compRules) && IsValidCompRule(COMPRULE2_RULE(m_compRules)))\n\t\t\tcomp = ::ChooseComponent(COMPRULE2_RULE(m_compRules), COMPRULE2_COMPS(m_compRules));\n\t\telse if(COMPRULE_RULE(m_compRules) && IsValidCompRule(COMPRULE_RULE(m_compRules)) &&\n\t\t        CGeneral::GetRandomNumberInRange(0, 3) < 2){\n\n\t\t\tn = GetListOfComponentsNotUsedByRules(m_compRules, m_numComps, comps);\n\t\t\tif(n)\n\t\t\t\tcomp = comps[(int)CGeneral::GetRandomNumberInRange(0, n)];\n\t\t}\n\t}else{\n\t\tcomp = ms_compsToUse[1];\n\t\tms_compsToUse[1] = -2;\n\t}\n\treturn comp;\n}\n\nstruct editableMatCBData\n{\n\tCVehicleModelInfo *vehicle;\n\tint32 numMats1;\n\tint32 numMats2;\n};\n\nRpMaterial*\nCVehicleModelInfo::GetEditableMaterialListCB(RpMaterial *material, void *data)\n{\n\tRwRGBA white = { 255, 255, 255, 255 };\n\tconst RwRGBA *col;\n\teditableMatCBData *cbdata;\n\n\tcbdata = (editableMatCBData*)data;\n\tcol = RpMaterialGetColor(material);\n\tif(col->red == 0x3C && col->green == 0xFF && col->blue == 0){\n\t\tcbdata->vehicle->m_materials1[cbdata->numMats1++] = material;\n\t\tRpMaterialSetColor(material, &white);\n\t}else if(col->red == 0xFF && col->green == 0 && col->blue == 0xAF){\n\t\tcbdata->vehicle->m_materials2[cbdata->numMats2++] = material;\n\t\tRpMaterialSetColor(material, &white);\n\t}\n\treturn material;\n}\n\nRpAtomic*\nCVehicleModelInfo::GetEditableMaterialListCB(RpAtomic *atomic, void *data)\n{\n\tRpGeometryForAllMaterials(RpAtomicGetGeometry(atomic), GetEditableMaterialListCB, data);\n\treturn atomic;\n}\n\nstatic int maxFirstMaterials;\nstatic int maxSecondMaterials;\n\nvoid\nCVehicleModelInfo::FindEditableMaterialList(void)\n{\n\teditableMatCBData cbdata;\n\tint32 i;\n\n\tcbdata.vehicle = this;\n\tcbdata.numMats1 = 0;\n\tcbdata.numMats2 = 0;\n\tRpClumpForAllAtomics(m_clump, GetEditableMaterialListCB, &cbdata);\n\tfor(i = 0; i < m_numComps; i++)\n\t\tGetEditableMaterialListCB(m_comps[i], &cbdata);\n\tm_materials1[cbdata.numMats1] = nil;\n\tm_materials2[cbdata.numMats2] = nil;\n\tmaxFirstMaterials = Max(maxFirstMaterials, cbdata.numMats1);\n\tmaxSecondMaterials = Max(maxSecondMaterials, cbdata.numMats2);\n\tm_currentColour1 = -1;\n\tm_currentColour2 = -1;\n}\n\nvoid\nCVehicleModelInfo::SetVehicleColour(uint8 c1, uint8 c2)\n{\n\tRwRGBA col, *colp;\n\tRpMaterial **matp;\n\n\tif(c1 != m_currentColour1){\n\t\tcol = ms_vehicleColourTable[c1];\n\t\tfor(matp = m_materials1; *matp; matp++){\n\t\t\tcolp = (RwRGBA*)RpMaterialGetColor(*matp);\t// get rid of const\n\t\t\tcolp->red = col.red;\n\t\t\tcolp->green = col.green;\n\t\t\tcolp->blue = col.blue;\n\t\t}\n\t\tm_currentColour1 = c1;\n\t}\n\n\tif(c2 != m_currentColour2){\n\t\tcol = ms_vehicleColourTable[c2];\n\t\tfor(matp = m_materials2; *matp; matp++){\n\t\t\tcolp = (RwRGBA*)RpMaterialGetColor(*matp);\t// get rid of const\n\t\t\tcolp->red = col.red;\n\t\t\tcolp->green = col.green;\n\t\t\tcolp->blue = col.blue;\n\t\t}\n\t\tm_currentColour2 = c2;\n\t}\n}\n\nvoid\nCVehicleModelInfo::ChooseVehicleColour(uint8 &col1, uint8 &col2)\n{\n\tif(m_numColours == 0 || gbBlackCars){\n\t\tcol1 = 0;\n\t\tcol2 = 0;\n\t}else if(gbPinkCars){\n\t\tcol1 = 68;\n\t\tcol2 = 68;\n\t}else{\n\t\tm_lastColorVariation = (m_lastColorVariation+1) % m_numColours;\n\t\tcol1 = m_colours1[m_lastColorVariation];\n\t\tcol2 = m_colours2[m_lastColorVariation];\n\t\tif(m_numColours > 1){\n\t\t\tCVehicle *veh = FindPlayerVehicle();\n\t\t\tif(veh && CModelInfo::GetModelInfo(veh->GetModelIndex()) == this &&\n\t\t\t   veh->m_currentColour1 == col1 &&\n\t\t\t   veh->m_currentColour2 == col2){\n\t\t\t\tm_lastColorVariation = (m_lastColorVariation+1) % m_numColours;\n\t\t\t\tcol1 = m_colours1[m_lastColorVariation];\n\t\t\t\tcol2 = m_colours2[m_lastColorVariation];\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nCVehicleModelInfo::AvoidSameVehicleColour(uint8 *col1, uint8 *col2)\n{\n\tint i, n;\n\n\tif(gbBlackCars){\n\t\t*col1 = 0;\n\t\t*col2 = 0;\n\t}else if(gbPinkCars){\n\t\t*col1 = 68;\n\t\t*col2 = 68;\n\t}else{\n\t\tif(m_numColours > 1)\n\t\t\tfor(i = 0; i < 8; i++){\n\t\t\t\tif(*col1 != m_lastColour1 || *col2 != m_lastColour2)\n\t\t\t\t\tbreak;\n\t\t\t\tn = CGeneral::GetRandomNumberInRange(0, m_numColours);\n\t\t\t\t*col1 = m_colours1[n];\n\t\t\t\t*col2 = m_colours2[n];\n\t\t\t}\n\t\tm_lastColour1 = *col1;\n\t\tm_lastColour2 = *col2;\n\t}\n}\n\n// unused\nRwTexture*\nCreateCarColourTexture(uint8 r, uint8 g, uint8 b)\n{\n\tRwImage *img;\n\tRwRaster *ras;\n\tRwTexture *tex;\n\tRwUInt8 *pixels;\n\tRwInt32 width, height, depth, format;\n\n\timg = RwImageCreate(2, 2, 32);\n\tpixels = (RwUInt8*)RwMalloc(2*2*4);\n\tpixels[0] = r;\n\tpixels[1] = g;\n\tpixels[2] = b;\n\tpixels[3] = 0xFF;\n\tpixels[4] = r;\n\tpixels[5] = g;\n\tpixels[6] = b;\n\tpixels[7] = 0xFF;\n\tpixels[8] = r;\n\tpixels[9] = g;\n\tpixels[10] = b;\n\tpixels[11] = 0xFF;\n\tpixels[12] = r;\n\tpixels[13] = g;\n\tpixels[14] = b;\n\tpixels[15] = 0xFF;\n\tRwImageSetPixels(img, pixels);\n\tRwImageSetStride(img, 8);\n\tRwImageSetPalette(img, nil);\n\tRwImageFindRasterFormat(img, rwRASTERTYPETEXTURE, &width, &height, &depth, &format);\n\tras = RwRasterCreate(width, height, depth, format);\n\tRwRasterSetFromImage(ras, img);\n\tRwImageDestroy(img);\n\tRwFree(pixels);\n\ttex = RwTextureCreate(ras);\n\tRwTextureGetName(tex)[0] = '@';\n\treturn tex;\n}\n\nvoid\nCVehicleModelInfo::LoadVehicleColours(void)\n{\n\tint fd;\n\tint i;\n\tchar line[1024];\n\tint start, end;\n\tint section, numCols;\n\tenum {\n\t\tNONE,\n\t\tCOLOURS,\n\t\tCARS\n\t};\n\tint r, g, b;\n\tchar name[64];\n\tint colors[16];\n\tint n;\n\n\tCFileMgr::ChangeDir(\"\\\\DATA\\\\\");\n\tfd = CFileMgr::OpenFile(\"CARCOLS.DAT\", \"r\");\n\tCFileMgr::ChangeDir(\"\\\\\");\n\n\tfor(i = 0; i < 256; i++)\n\t\tms_colourTextureTable[i] = nil;\n\n\tsection = 0;\n\tnumCols = 0;\n\twhile(CFileMgr::ReadLine(fd, line, sizeof(line))){\n\t\t// find first valid character in line\n\t\tfor(start = 0; ; start++)\n\t\t\tif(line[start] > ' ' || line[start] == '\\0' || line[start] == '\\n')\n\t\t\t\tbreak;\n\t\t// find end of line\n\t\tfor(end = start; ; end++){\n\t\t\tif(line[end] == '\\0' || line[end] == '\\n')\n\t\t\t\tbreak;\n\t\t\tif(line[end] == ',' || line[end] == '\\r')\n\t\t\t\tline[end] = ' ';\n\t\t}\n\t\tline[end] = '\\0';\n\n\t\t// empty line\n\t\tif(line[start] == '#' || line[start] == '\\0')\n\t\t\tcontinue;\n\n\t\tif(section == NONE){\n\t\t\tif(line[start] == 'c' && line[start + 1] == 'o' && line[start + 2] == 'l')\n\t\t\t\tsection = COLOURS;\n\t\t\tif(line[start] == 'c' && line[start + 1] == 'a' && line[start + 2] == 'r')\n\t\t\t\tsection = CARS;\n\t\t}else if(line[start] == 'e' && line[start + 1] == 'n' && line[start + 2] == 'd'){\n\t\t\tsection = NONE;\n\t\t}else if(section == COLOURS){\n\t\t\tsscanf(&line[start],\t// BUG: games doesn't add start\n\t\t\t\t\"%d %d %d\", &r, &g, &b);\n\t\t\tms_vehicleColourTable[numCols].red = r;\n\t\t\tms_vehicleColourTable[numCols].green = g;\n\t\t\tms_vehicleColourTable[numCols].blue = b;\n\t\t\tms_vehicleColourTable[numCols].alpha = 0xFF;\n\t\t\tnumCols++;\n\t\t}else if(section == CARS){\n\t\t\tn = sscanf(&line[start],\t// BUG: games doesn't add start\n\t\t\t\t\"%s %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\",\n\t\t\t\tname,\n\t\t\t\t&colors[0], &colors[1],\n\t\t\t\t&colors[2], &colors[3],\n\t\t\t\t&colors[4], &colors[5],\n\t\t\t\t&colors[6], &colors[7],\n\t\t\t\t&colors[8], &colors[9],\n\t\t\t\t&colors[10], &colors[11],\n\t\t\t\t&colors[12], &colors[13],\n\t\t\t\t&colors[14], &colors[15]);\n\t\t\tCVehicleModelInfo *mi = (CVehicleModelInfo*)CModelInfo::GetModelInfo(name, nil);\n\t\t\tassert(mi);\n\t\t\tmi->m_numColours = (n-1)/2;\n\t\t\tfor(i = 0; i < mi->m_numColours; i++){\n\t\t\t\tmi->m_colours1[i] = colors[i*2 + 0];\n\t\t\t\tmi->m_colours2[i] = colors[i*2 + 1];\n\t\t\t}\n\t\t}\n\t}\n\n\tCFileMgr::CloseFile(fd);\n}\n\nvoid\nCVehicleModelInfo::DeleteVehicleColourTextures(void)\n{\n\tint i;\n\n\tfor(i = 0; i < 256; i++){\n\t\tif(ms_colourTextureTable[i]){\n\t\t\tRwTextureDestroy(ms_colourTextureTable[i]);\n\t\t\tms_colourTextureTable[i] = nil;\n\t\t}\n\t}\n}\n\nRpMaterial*\nCVehicleModelInfo::GetMatFXEffectMaterialCB(RpMaterial *material, void *data)\n{\n\tif(RpMatFXMaterialGetEffects(material) == rpMATFXEFFECTNULL)\n\t\treturn material;\n\t*(int*)data = RpMatFXMaterialGetEffects(material);\n\treturn nil;\n}\n\nRpMaterial*\nCVehicleModelInfo::SetDefaultEnvironmentMapCB(RpMaterial *material, void *data)\n{\n\tif(RpMatFXMaterialGetEffects(material) == rpMATFXEFFECTENVMAP){\n\t\tRpMatFXMaterialSetEnvMapFrame(material, pMatFxIdentityFrame);\n\t\tif(RpMaterialGetTexture(material) == nil)\n\t\t\tRpMaterialSetTexture(material, gpWhiteTexture);\n\t\tRpMatFXMaterialSetEffects(material, rpMATFXEFFECTENVMAP);\n#ifndef PS2_MATFX\n\t\tfloat coef = RpMatFXMaterialGetEnvMapCoefficient(material);\n\t\tcoef *= 0.25f;\t// Tone down a bit for PC\n\t\tRpMatFXMaterialSetEnvMapCoefficient(material, coef);\n#endif\n\t}\n\treturn material;\n}\n\nRpAtomic*\nCVehicleModelInfo::SetEnvironmentMapCB(RpAtomic *atomic, void *data)\n{\n\tint fx;\n\tRpGeometry *geo;\n\n\tgeo = RpAtomicGetGeometry(atomic);\n\tfx = rpMATFXEFFECTNULL;\n\tRpGeometryForAllMaterials(geo, GetMatFXEffectMaterialCB, &fx);\n\tif(fx != rpMATFXEFFECTNULL){\n\t\tRpMatFXAtomicEnableEffects(atomic);\n\t\tRpGeometryForAllMaterials(geo, SetDefaultEnvironmentMapCB, data);\n\t}\n\treturn atomic;\n}\n\nvoid\nCVehicleModelInfo::SetEnvironmentMap(void)\n{\n\tCSimpleModelInfo *wheelmi;\n\tint32 i;\n\n\tif(pMatFxIdentityFrame == nil){\n\t\tRwV3d axis = { 1.0f, 0.0f, 0.0f };\n\t\tpMatFxIdentityFrame = RwFrameCreate();\n\t\tRwMatrixRotate(RwFrameGetMatrix(pMatFxIdentityFrame), &axis, 60.0f, rwCOMBINEREPLACE);\n\t\tRwFrameUpdateObjects(pMatFxIdentityFrame);\n\t\tRwFrameGetLTM(pMatFxIdentityFrame);\n\t}\n\n\tRpClumpForAllAtomics(m_clump, SetEnvironmentMapCB, nil);\n\tif(m_wheelId != -1){\n\t\twheelmi = (CSimpleModelInfo*)CModelInfo::GetModelInfo(m_wheelId);\n\t\tfor(i = 0; i < wheelmi->m_numAtomics; i++)\n\t\t\tSetEnvironmentMapCB(wheelmi->m_atomics[i], nil);\n\t}\n\n#ifdef EXTENDED_PIPELINES\n\tCustomPipes::AttachVehiclePipe(m_clump);\n#endif\n}\n\nvoid\nCVehicleModelInfo::LoadEnvironmentMaps(void)\n{\n\tint32 txdslot;\n\n\ttxdslot = CTxdStore::FindTxdSlot(\"particle\");\n\tCTxdStore::PushCurrentTxd();\n\tCTxdStore::SetCurrentTxd(txdslot);\n\tif(gpWhiteTexture == nil){\n\t\tgpWhiteTexture = RwTextureRead(\"white\", nil);\n\t\tRwTextureGetName(gpWhiteTexture)[0] = '@';\n\t\tRwTextureSetFilterMode(gpWhiteTexture, rwFILTERLINEAR);\n\t}\n\tCTxdStore::PopCurrentTxd();\n}\n\nvoid\nCVehicleModelInfo::ShutdownEnvironmentMaps(void)\n{\n\tRwTextureDestroy(gpWhiteTexture);\n\tgpWhiteTexture = nil;\n\tRwFrameDestroy(pMatFxIdentityFrame);\n\tpMatFxIdentityFrame = nil;\n}\n\nint\nCVehicleModelInfo::GetMaximumNumberOfPassengersFromNumberOfDoors(int id)\n{\n\tint n;\n\n\tswitch(id){\n\tcase MI_TRAIN:\n\t\tn = 3;\n\t\tbreak;\n\tcase MI_FIRETRUCK:\n\t\tn = 2;\n\t\tbreak;\n\tcase MI_HUNTER:\n\t\tn = 1;\n\t\tbreak;\n\tdefault:\n\t\tn = ((CVehicleModelInfo*)CModelInfo::GetModelInfo(id))->m_numDoors;\n\t}\n\n\tif(n == 0)\n\t\treturn id == MI_RCBANDIT || id == MI_PIZZABOY || id == MI_BAGGAGE ? 0 : 1;\n\n\tif(id == MI_COACH)\n\t\treturn 8;\n\n\treturn n - 1;\n}\n"
  },
  {
    "path": "src/modelinfo/VehicleModelInfo.h",
    "content": "#pragma once\n\n#include \"ClumpModelInfo.h\"\n\nenum {\n\tNUM_FIRST_MATERIALS = 24,\n\tNUM_SECOND_MATERIALS = 20,\n\tNUM_VEHICLE_COLOURS = 8,\n};\n\nenum {\n\tATOMIC_FLAG_NONE\t= 0x0,\n\tATOMIC_FLAG_OK\t\t= 0x1,\n\tATOMIC_FLAG_DAM\t\t= 0x2,\n\tATOMIC_FLAG_LEFT\t= 0x4,\n\tATOMIC_FLAG_RIGHT\t= 0x8,\n\tATOMIC_FLAG_FRONT\t= 0x10,\n\tATOMIC_FLAG_REAR\t= 0x20,\n\tATOMIC_FLAG_DRAWLAST\t= 0x40,\n\tATOMIC_FLAG_WINDSCREEN\t= 0x80,\n\tATOMIC_FLAG_ANGLECULL\t= 0x100,\n\tATOMIC_FLAG_REARDOOR\t= 0x200,\n\tATOMIC_FLAG_FRONTDOOR\t= 0x400,\n\tATOMIC_FLAG_NOCULL\t= 0x800,\n};\n\nenum eVehicleType {\n\tVEHICLE_TYPE_CAR,\n\tVEHICLE_TYPE_BOAT,\n\tVEHICLE_TYPE_TRAIN,\n\tVEHICLE_TYPE_HELI,\n\tVEHICLE_TYPE_PLANE,\n\tVEHICLE_TYPE_BIKE,\n\tNUM_VEHICLE_TYPES\n};\n\nenum eCarPositions\n{\n\tCAR_POS_HEADLIGHTS,\n\tCAR_POS_TAILLIGHTS,\n\tCAR_POS_FRONTSEAT,\n\tCAR_POS_BACKSEAT,\n\tCAR_POS_EXHAUST\n};\n\nenum eBoatPositions\n{\n\tBOAT_POS_FRONTSEAT\n};\n\nenum eTrainPositions\n{\n\tTRAIN_POS_LIGHT_FRONT,\n\tTRAIN_POS_LIGHT_REAR,\n\tTRAIN_POS_LEFT_ENTRY,\n\tTRAIN_POS_MID_ENTRY,\n\tTRAIN_POS_RIGHT_ENTRY\n};\n\nenum ePlanePositions\n{\n\tPLANE_POS_LIGHT_LEFT,\n\tPLANE_POS_LIGHT_RIGHT,\n\tPLANE_POS_LIGHT_TAIL,\n};\n\nenum {\n\tNUM_VEHICLE_POSITIONS = 5\n};\n\nclass CVehicleModelInfo : public CClumpModelInfo\n{\npublic:\n\tuint8 m_lastColour1;\n\tuint8 m_lastColour2;\n\tchar m_gameName[10];\n\tint32 m_vehicleType;\n\tfloat m_wheelScale;\n\tunion {\n\t\tint16 m_wheelId;\n\t\tint16 m_planeLodId;\n\t};\n\tint16 m_handlingId;\n\tint8 m_numDoors;\n\tint8 m_vehicleClass;\n\tint8 m_level;\n\tint8 m_numComps;\n\tint16 m_frequency;\n\tCVector m_positions[NUM_VEHICLE_POSITIONS];\n\tuint32 m_compRules;\n\tfloat m_bikeSteerAngle;\n\tRpMaterial *m_materials1[NUM_FIRST_MATERIALS];\n\tRpMaterial *m_materials2[NUM_SECOND_MATERIALS];\n\tuint8 m_colours1[NUM_VEHICLE_COLOURS];\n\tuint8 m_colours2[NUM_VEHICLE_COLOURS];\n\tuint8 m_numColours;\n\tuint8 m_lastColorVariation;\n\tuint8 m_currentColour1;\n\tuint8 m_currentColour2;\n\tRpAtomic *m_comps[6];\n\t// This is stupid, CClumpModelInfo already has it!\n\tunion {\n\t\tint32 m_animFileIndex;\n\t\tchar *m_animFileName;\n\t};\n\n\tstatic int8 ms_compsToUse[2];\n\tstatic int8 ms_compsUsed[2];\n\tstatic RwRGBA ms_vehicleColourTable[256];\n\tstatic RwTexture *ms_colourTextureTable[256];\n\tstatic RwObjectNameIdAssocation *ms_vehicleDescs[NUM_VEHICLE_TYPES];\n\n\tCVehicleModelInfo(void);\n\tvoid DeleteRwObject(void);\n\tRwObject *CreateInstance(void);\n\tvoid SetClump(RpClump *);\n\tvoid SetAnimFile(const char *file);\n\tvoid ConvertAnimFileIndex(void);\n\tint GetAnimFileIndex(void) { return m_animFileIndex; }\n\n\tstatic RwFrame *CollapseFramesCB(RwFrame *frame, void *data);\n\tstatic RwObject *MoveObjectsCB(RwObject *object, void *data);\n\tstatic RpAtomic *HideDamagedAtomicCB(RpAtomic *atomic, void *data);\n\tstatic RpAtomic *HideAllComponentsAtomicCB(RpAtomic *atomic, void *data);\n\tstatic RpMaterial *HasAlphaMaterialCB(RpMaterial *material, void *data);\n\n\tstatic RpAtomic *SetAtomicRendererCB(RpAtomic *atomic, void *data);\n\tstatic RpAtomic *SetAtomicRendererCB_BigVehicle(RpAtomic *atomic, void *data);\n\tstatic RpAtomic *SetAtomicRendererCB_Train(RpAtomic *atomic, void *data);\n\tstatic RpAtomic *SetAtomicRendererCB_Boat(RpAtomic *atomic, void *data);\n\tstatic RpAtomic *SetAtomicRendererCB_Heli(RpAtomic *atomic, void *data);\n\tstatic RpAtomic *SetAtomicRendererCB_RealHeli(RpAtomic *atomic, void *data);\n\tvoid SetAtomicRenderCallbacks(void);\n\n\tstatic RwObject *SetAtomicFlagCB(RwObject *object, void *data);\n\tstatic RwObject *ClearAtomicFlagCB(RwObject *atomic, void *data);\n\tvoid SetVehicleComponentFlags(RwFrame *frame, uint32 flags);\n\tvoid PreprocessHierarchy(void);\n\tvoid GetWheelPosn(int32 n, CVector &pos);\n\tconst CVector &GetFrontSeatPosn(void) { return m_vehicleType == VEHICLE_TYPE_BOAT ? m_positions[BOAT_POS_FRONTSEAT] : m_positions[CAR_POS_FRONTSEAT]; }\n\n\tint32 ChooseComponent(void);\n\tint32 ChooseSecondComponent(void);\n\n\tstatic RpMaterial *GetEditableMaterialListCB(RpMaterial *material, void *data);\n\tstatic RpAtomic *GetEditableMaterialListCB(RpAtomic *atomic, void *data);\n\tvoid FindEditableMaterialList(void);\n\tvoid SetVehicleColour(uint8 c1, uint8 c2);\n\tvoid ChooseVehicleColour(uint8 &col1, uint8 &col2);\n\tvoid AvoidSameVehicleColour(uint8 *col1, uint8 *col2);\n\tstatic void LoadVehicleColours(void);\n\tstatic void DeleteVehicleColourTextures(void);\n\n\tstatic RpAtomic *SetEnvironmentMapCB(RpAtomic *atomic, void *data);\n\tstatic RpMaterial *SetDefaultEnvironmentMapCB(RpMaterial *material, void *data);\n\tstatic RpMaterial *GetMatFXEffectMaterialCB(RpMaterial *material, void *data);\n\tvoid SetEnvironmentMap(void);\n\tstatic void LoadEnvironmentMaps(void);\n\tstatic void ShutdownEnvironmentMaps(void);\n\n\tstatic int GetMaximumNumberOfPassengersFromNumberOfDoors(int id);\n\tstatic void SetComponentsToUse(int8 c1, int8 c2) { ms_compsToUse[0] = c1; ms_compsToUse[1] = c2; }\n};\n\nextern bool gbBlackCars;\nextern bool gbPinkCars;\n"
  },
  {
    "path": "src/modelinfo/WeaponModelInfo.cpp",
    "content": "#include \"common.h\"\n\n#include \"ModelInfo.h\"\n#include \"AnimManager.h\"\n#include \"VisibilityPlugins.h\"\n\nvoid\nCWeaponModelInfo::SetAnimFile(const char *file)\n{\n\tif(strcasecmp(file, \"null\") == 0)\n\t\treturn;\n\n\tm_animFileName = new char[strlen(file)+1];\n\tstrcpy(m_animFileName, file);\n}\n\nvoid\nCWeaponModelInfo::ConvertAnimFileIndex(void)\n{\n\tif(m_animFileIndex != -1){\n\t\t// we have a string pointer in that union\n\t\tint32 index = CAnimManager::GetAnimationBlockIndex(m_animFileName);\n\t\tdelete[] m_animFileName;\n\t\tm_animFileIndex = index;\n\t}\n}\n\nvoid\nCWeaponModelInfo::Init(void)\n{\n\tCSimpleModelInfo::Init();\n\tSetWeaponInfo(0);\n}\n\nvoid\nCWeaponModelInfo::SetWeaponInfo(int32 weaponId)\n{\n\tm_atomics[2] = (RpAtomic*)weaponId;\n}\n\neWeaponType\nCWeaponModelInfo::GetWeaponInfo(void)\n{\n\treturn (eWeaponType)(uintptr)m_atomics[2];\n}\n\nvoid\nCWeaponModelInfo::SetAtomic(int n, RpAtomic *atomic)\n{\n\tCSimpleModelInfo::SetAtomic(n, atomic);\n\tCVisibilityPlugins::SetAtomicRenderCallback(atomic, CVisibilityPlugins::RenderWeaponCB);\n}\n\n"
  },
  {
    "path": "src/modelinfo/WeaponModelInfo.h",
    "content": "#pragma once\n\n#include \"SimpleModelInfo.h\"\n#include \"WeaponType.h\"\n\nclass CWeaponModelInfo : public CSimpleModelInfo\n{\n\tunion {\n\t\tint32 m_animFileIndex;\n\t\tchar *m_animFileName;\n\t};\npublic:\n\tCWeaponModelInfo(void) : CSimpleModelInfo(MITYPE_WEAPON) { m_animFileIndex = -1; }\n\n\tvirtual void SetAnimFile(const char *file);\n\tvirtual void ConvertAnimFileIndex(void);\n\tvirtual int GetAnimFileIndex(void) { return m_animFileIndex; }\n\tvirtual void SetAtomic(int n, RpAtomic *atomic);\n\t\n\tvoid Init(void);\n\tvoid SetWeaponInfo(int32 weaponId);\n\teWeaponType GetWeaponInfo(void);\n};\n"
  },
  {
    "path": "src/objects/CutsceneObject.cpp",
    "content": "#include \"common.h\"\n\n#include \"main.h\"\n#include \"RwHelper.h\"\n#include \"Lights.h\"\n#include \"PointLights.h\"\n#include \"RpAnimBlend.h\"\n#include \"AnimBlendClumpData.h\"\n#include \"Bones.h\"\n#include \"Renderer.h\"\n#include \"ModelIndices.h\"\n#include \"Shadows.h\"\n#include \"Timecycle.h\"\n#include \"CutsceneShadow.h\"\n#include \"CutsceneObject.h\"\n#include \"ModelIndices.h\"\n#include \"RpAnimBlend.h\"\n\n\nCCutsceneObject::CCutsceneObject(void)\n{\n\tSetStatus(STATUS_SIMPLE);\n\tbUsesCollision = false;\n\tbStreamingDontDelete = true;\n\tObjectCreatedBy = CUTSCENE_OBJECT;\n\tm_fMass = 1.0f;\n\tm_fTurnMass = 1.0f;\n\t\n\tm_pAttachTo = nil;\n\tm_pAttachmentObject = nil;\n\tm_pShadow = nil;\n}\n\nCCutsceneObject::~CCutsceneObject(void)\n{\n\tif ( m_pShadow )\n\t{\n\t\tdelete m_pShadow;\n\t\tm_pShadow = nil;\n\t}\n}\n\nvoid\nCCutsceneObject::SetModelIndex(uint32 id)\n{\n\tCEntity::SetModelIndex(id);\n\tassert(RwObjectGetType(m_rwObject) == rpCLUMP);\n\tRpAnimBlendClumpInit((RpClump*)m_rwObject);\n\t(*RPANIMBLENDCLUMPDATA(m_rwObject))->velocity3d = &m_vecMoveSpeed;\n\t(*RPANIMBLENDCLUMPDATA(m_rwObject))->frames[0].flag |= AnimBlendFrameData::VELOCITY_EXTRACTION_3D;\n}\n\nvoid\nCCutsceneObject::CreateShadow(void)\n{\n\tif ( IsPedModel(GetModelIndex()) )\n\t{\n\t\tm_pShadow = new CCutsceneShadow();\n\t\tif (!m_pShadow->IsInitialized())\n\t\t\tm_pShadow->Create(m_rwObject, 6, true, 4, true);\n\t}\n}\n\nvoid\nCCutsceneObject::ProcessControl(void)\n{\n\tCPhysical::ProcessControl();\n\n\tif ( m_pAttachTo )\n\t{\n\t\tif ( m_pAttachmentObject )\n\t\t\tGetMatrix() = CMatrix((RwMatrix*)m_pAttachTo);\n\t\telse\n\t\t\tGetMatrix() = CMatrix(RwFrameGetLTM((RwFrame*)m_pAttachTo));\n\t}\n\telse\n\t{\n\t\tif(CTimer::GetTimeStep() < 1/100.0f)\n\t\t\tm_vecMoveSpeed *= 100.0f;\n\t\telse\n\t\t\tm_vecMoveSpeed *= 1.0f/CTimer::GetTimeStep();\n\t\n\t\tApplyMoveSpeed();\n\t}\n}\n\nstatic RpMaterial*\nMaterialSetAlpha(RpMaterial *material, void *data)\n{\n\t((RwRGBA*)RpMaterialGetColor(material))->alpha = (uint8)(uintptr)data;\n\treturn material;\n}\n\nvoid\nCCutsceneObject::PreRender(void)\n{\n\tif ( m_pAttachTo )\n\t{\n\t\tif ( m_pAttachmentObject )\n\t\t{\n\t\t\tm_pAttachmentObject->UpdateRpHAnim();\n\t\t\tGetMatrix() = CMatrix((RwMatrix*)m_pAttachTo);\n\t\t}\n\t\telse\n\t\t\tGetMatrix() = CMatrix(RwFrameGetLTM((RwFrame*)m_pAttachTo));\n\t\t\n\t\tif ( RwObjectGetType(m_rwObject) == rpCLUMP && IsClumpSkinned(GetClump()) )\n\t\t{\n\t\t\tRpAtomic *atomic = GetFirstAtomic(GetClump());\n\t\t\tatomic->boundingSphere.center = (*RPANIMBLENDCLUMPDATA(GetClump()))->frames[0].hanimFrame->t;\n\t\t}\n\t}\n\t\n\tif ( RwObjectGetType(m_rwObject) == rpCLUMP )\n\t\tUpdateRpHAnim();\n\t\n\tif(IsPedModel(GetModelIndex()))\n\t{\n\t\tif ( m_pShadow == nil )\n\t\t{\n\t\t\tCShadows::StoreShadowForPedObject(this,\n\t\t\t\tCTimeCycle::m_fShadowDisplacementX[CTimeCycle::m_CurrentStoredValue],\n\t\t\t\tCTimeCycle::m_fShadowDisplacementY[CTimeCycle::m_CurrentStoredValue],\n\t\t\t\tCTimeCycle::m_fShadowFrontX[CTimeCycle::m_CurrentStoredValue],\n\t\t\t\tCTimeCycle::m_fShadowFrontY[CTimeCycle::m_CurrentStoredValue],\n\t\t\t\tCTimeCycle::m_fShadowSideX[CTimeCycle::m_CurrentStoredValue],\n\t\t\t\tCTimeCycle::m_fShadowSideY[CTimeCycle::m_CurrentStoredValue]);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif ( m_pShadow->IsInitialized() )\n\t\t\t\tm_pShadow->UpdateForCutscene();\n\t\t\t\n\t\t\tCShadows::StoreShadowForCutscenePedObject(this,\n\t\t\t\tCTimeCycle::m_fShadowDisplacementX[CTimeCycle::m_CurrentStoredValue],\n\t\t\t\tCTimeCycle::m_fShadowDisplacementY[CTimeCycle::m_CurrentStoredValue],\n\t\t\t\tCTimeCycle::m_fShadowFrontX[CTimeCycle::m_CurrentStoredValue],\n\t\t\t\tCTimeCycle::m_fShadowFrontY[CTimeCycle::m_CurrentStoredValue],\n\t\t\t\tCTimeCycle::m_fShadowSideX[CTimeCycle::m_CurrentStoredValue],\n\t\t\t\tCTimeCycle::m_fShadowSideY[CTimeCycle::m_CurrentStoredValue]);\n\t\t}\n\t\t\t\n\t\t// For some reason xbox/android limbs are transparent here...\n\t\tRpGeometry *geometry = RpAtomicGetGeometry(GetFirstAtomic(GetClump()));\n\t\tRpGeometrySetFlags(geometry, RpGeometryGetFlags(geometry) | rpGEOMETRYMODULATEMATERIALCOLOR);\n\t\tRpGeometryForAllMaterials(geometry, MaterialSetAlpha, (void*)255);\n\t}\n}\n\nvoid\nCCutsceneObject::Render(void)\n{\n\tSetCullMode(rwCULLMODECULLNONE);\n\tCObject::Render();\n\tSetCullMode(rwCULLMODECULLBACK);\n}\n\nbool\nCCutsceneObject::SetupLighting(void)\n{\n\tActivateDirectional();\n\tSetAmbientColoursForPedsCarsAndObjects();\n\n\tif(bRenderScorched){\n\t\tWorldReplaceNormalLightsWithScorched(Scene.world, 0.1f);\n\t}else{\n\t\tCVector coors = GetPosition();\n\t\tfloat lighting = CPointLights::GenerateLightsAffectingObject(&coors);\n\t\tif(lighting != 1.0f){\n\t\t\tSetAmbientAndDirectionalColours(lighting);\n\t\t\treturn true;\n\t\t}\n\t}\n\n\treturn false;\n}\n\nvoid\nCCutsceneObject::RemoveLighting(bool reset)\n{\n\tCRenderer::RemoveVehiclePedLights(this, reset);\n}\n"
  },
  {
    "path": "src/objects/CutsceneObject.h",
    "content": "#pragma once\n\n#include \"Object.h\"\n\nclass CCutsceneShadow;\n\nclass CCutsceneObject : public CObject\n{\npublic:\n\tCCutsceneShadow *m_pShadow;\n\tvoid     *m_pAttachTo;\n\tCObject  *m_pAttachmentObject;\n  \n\tCCutsceneObject(void);\n\t~CCutsceneObject(void);\n\n\tvoid SetModelIndex(uint32 id);\n\tvoid CreateShadow(void);\n\tvoid ProcessControl(void);\n\tvoid PreRender(void);\n\tvoid Render(void);\n\tbool SetupLighting(void);\n\tvoid RemoveLighting(bool reset);\n};\n"
  },
  {
    "path": "src/objects/DummyObject.cpp",
    "content": "#include \"common.h\"\n\n#include \"DummyObject.h\"\n#include \"Pools.h\"\n\nCDummyObject::CDummyObject(CObject *obj)\n{\n\tSetModelIndexNoCreate(obj->GetModelIndex());\n\tif(obj->m_rwObject)\n\t\tAttachToRwObject(obj->m_rwObject);\n\tobj->DetachFromRwObject();\n\tm_level = obj->m_level;\n\tm_area = obj->m_area;\n}\n"
  },
  {
    "path": "src/objects/DummyObject.h",
    "content": "#pragma once\n\n#include \"Dummy.h\"\n\nclass CObject;\n\nclass CDummyObject : public CDummy\n{\npublic:\n\tCDummyObject(void) {}\n\tCDummyObject(CObject *obj);\n};\n"
  },
  {
    "path": "src/objects/Object.cpp",
    "content": "#include \"common.h\"\n\n#include \"main.h\"\n#include \"Lights.h\"\n#include \"Pools.h\"\n#include \"Radar.h\"\n#include \"Object.h\"\n#include \"DummyObject.h\"\n#include \"Particle.h\"\n#include \"General.h\"\n#include \"ObjectData.h\"\n#include \"World.h\"\n#include \"Floater.h\"\n#include \"soundlist.h\"\n#include \"WaterLevel.h\"\n#include \"Timecycle.h\"\n#include \"Stats.h\"\n#include \"SpecialFX.h\"\n\n#define BEACHBALL_MAX_SCORE 250\n// the proportion of the ball speed compared to the player speed when it hits the player\n#define BEACHBALL_SPEED_PROPORTION 0.4f\n\nint16 CObject::nNoTempObjects;\n//int16 CObject::nBodyCastHealth = 1000;\nfloat CObject::fDistToNearestTree;\n\nvoid *CObject::operator new(size_t sz) { return CPools::GetObjectPool()->New();  }\nvoid *CObject::operator new(size_t sz, int handle) { return CPools::GetObjectPool()->New(handle);};\nvoid CObject::operator delete(void *p, size_t sz) { CPools::GetObjectPool()->Delete((CObject*)p); }\nvoid CObject::operator delete(void *p, int handle) { CPools::GetObjectPool()->Delete((CObject*)p); }\n\nCObject::CObject(void)\n{\n\tm_type = ENTITY_TYPE_OBJECT;\n\tm_fUprootLimit = 0.0f;\n\tm_nCollisionDamageEffect = 0;\n\tm_nSpecialCollisionResponseCases = COLLRESPONSE_NONE;\n\tm_bCameraToAvoidThisObject = false;\n\tObjectCreatedBy = UNKNOWN_OBJECT;\n\tm_nEndOfLifeTime = 0;\n\t//\tm_nRefModelIndex = -1;\t// duplicate\n\t//\tbUseVehicleColours = false;\t// duplicate\n\tm_colour2 = 0;\n\tm_colour1 = m_colour2;\n\tm_nBonusValue = 0;\n\tm_nCostValue = 0;\n\tbIsPickup = false;\n\tbPickupObjWithMessage = false;\n\tbOutOfStock = false;\n\tbGlassCracked = false;\n\tbGlassBroken = false;\n\tbHasBeenDamaged = false;\n\tm_nRefModelIndex = -1;\n\tbUseVehicleColours = false;\n\t//\tbIsStreetLight = false;\t\t// duplicate\n\tm_pCurSurface = nil;\n\tm_pCollidingEntity = nil;\n\tm_nBeachballBounces = 0;\n\tbIsStreetLight = false;\n\tm_area = AREA_EVERYWHERE;\n}\n\nCObject::CObject(int32 mi, bool createRW)\n{\n\tif (createRW)\n\t\tSetModelIndex(mi);\n\telse\n\t\tSetModelIndexNoCreate(mi);\n\tInit();\n}\n\nCObject::CObject(CDummyObject *dummy)\n{\n\tSetModelIndexNoCreate(dummy->GetModelIndex());\n\n\tif (dummy->m_rwObject)\n\t\tAttachToRwObject(dummy->m_rwObject);\n\telse\n\t\tGetMatrix() = dummy->GetMatrix();\n\n\tm_objectMatrix = dummy->GetMatrix();\n\tdummy->DetachFromRwObject();\n\tInit();\n\tm_level = dummy->m_level;\n\tm_area = dummy->m_area;\n}\n\nCObject::~CObject(void)\n{\n\tCRadar::ClearBlipForEntity(BLIP_OBJECT, CPools::GetObjectPool()->GetIndex(this));\n\n\tif (m_nRefModelIndex != -1)\n\t\tCModelInfo::GetModelInfo(m_nRefModelIndex)->RemoveRef();\n\n\tif (ObjectCreatedBy == TEMP_OBJECT && nNoTempObjects != 0)\n\t\tnNoTempObjects--;\n}\n\nvoid\nCObject::ProcessControl(void)\n{\n\tCVector point, impulse;\n\tif (m_nCollisionDamageEffect)\n\t\tObjectDamage(m_fDamageImpulse);\n\tCPhysical::ProcessControl();\n\tif (mod_Buoyancy.ProcessBuoyancy(this, m_fBuoyancy, &point, &impulse)) {\n\t\tbIsInWater = true;\n\t\tSetIsStatic(false);\n\t\tApplyMoveForce(impulse);\n\t\tApplyTurnForce(impulse, point);\n\t\tfloat fTimeStep = Pow(0.97f, CTimer::GetTimeStep());\n\t\tm_vecMoveSpeed *= fTimeStep;\n\t\tm_vecTurnSpeed *= fTimeStep;\n\t}\n\tint16 mi = GetModelIndex();\n\tif ((mi == MI_EXPLODINGBARREL || mi == MI_PETROLPUMP || mi == MI_PETROLPUMP2) && bHasBeenDamaged && bIsVisible\n\t\t&& (CGeneral::GetRandomNumber() & 0x1F) == 10) {\n\t\tbExplosionProof = true;\n\t\tbIsVisible = false;\n\t\tbUsesCollision = false;\n\t\tbAffectedByGravity = false;\n\t\tm_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);\n\t}\n\tif (mi == MI_RCBOMB) {\n\t\tfloat fTurnForce = -(m_fTurnMass / 20.0f);\n\t\tCPhysical::ApplyTurnForce(m_vecMoveSpeed * fTurnForce, -GetForward());\n\t\tfloat fScalar = 1.0f - m_vecMoveSpeed.MagnitudeSqr() / 5.0f;\n\t\tfloat fScalarTimed = Pow(fScalar, CTimer::GetTimeStep());\n\t\tm_vecMoveSpeed *= fScalarTimed;\n\t}\n\tif (mi == MI_BEACHBALL) {\n\t\tfloat fTimeStep = Pow(0.95f, CTimer::GetTimeStep());\n\t\tfloat fPreviousVecSpeedMag = m_vecMoveSpeed.Magnitude2D();\n\t\tm_vecMoveSpeed.x *= fTimeStep;\n\t\tm_vecMoveSpeed.y *= fTimeStep;\n\t\tm_vecMoveSpeed.z += fPreviousVecSpeedMag - m_vecMoveSpeed.Magnitude2D();\n\t\tif (!FindPlayerVehicle()) {\n\t\t\tCVector distance;\n\t\t\tdistance.x = FindPlayerCoors().x - GetPosition().x;\n\t\t\tdistance.y = FindPlayerCoors().y - GetPosition().y;\n\t\t\tdistance.z = FindPlayerCoors().z - GetPosition().z;\n\t\t\tif (distance.z > 0.0 && distance.z < 1.5f && distance.Magnitude2D() < 1.0f) {\n\t\t\t\tCVector playerSpeed = FindPlayerSpeed();\n\t\t\t\tif (fPreviousVecSpeedMag < 0.05f && playerSpeed.Magnitude() > 0.1f) {\n\t\t\t\t\tplayerSpeed.z = 0.0f;\n\t\t\t\t\tplayerSpeed.Normalise();\n\t\t\t\t\tplayerSpeed.z = 0.3f;\n\t\t\t\t\tm_vecMoveSpeed = CVector(\n\t\t\t\t\t\tplayerSpeed.x * BEACHBALL_SPEED_PROPORTION,\n\t\t\t\t\t\tplayerSpeed.y * BEACHBALL_SPEED_PROPORTION,\n\t\t\t\t\t\t0.3f          * BEACHBALL_SPEED_PROPORTION\n\t\t\t\t\t);\n\t\t\t\t\tPlayOneShotScriptObject(SCRIPT_SOUND_HIT_BALL, GetPosition());\n\t\t\t\t\tm_vecTurnSpeed += CVector(\n\t\t\t\t\t\t((CGeneral::GetRandomNumber() % 16) - 7) / 10.0f,\n\t\t\t\t\t\t((CGeneral::GetRandomNumber() % 16) - 7) / 10.0f,\n\t\t\t\t\t\t0.0f);\n\t\t\t\t\tif (m_nBeachballBounces > 0) {\n\t\t\t\t\t\tm_nBeachballBounces++;\n\t\t\t\t\t}\n\t\t\t\t\tif (m_nBeachballBounces > 0) {\n\t\t\t\t\t\tsprintf(gString, \"%d\", m_nBeachballBounces);\n\t\t\t\t\t\tCMoneyMessages::RegisterOne(GetPosition(), gString, 255, 50, 0, 0.6f, 0.5f);\n\t\t\t\t\t\tCStats::RegisterHighestScore(3, m_nBeachballBounces);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (distance.z > -1.05 && distance.z < -0.6 && m_vecMoveSpeed.z < 0.0f && distance.Magnitude2D() < 0.9f) {\n\t\t\t\tm_vecMoveSpeed.x += (CGeneral::GetRandomNumber() % 8 - 3) / 100.0f;\n\t\t\t\tm_vecMoveSpeed.y += (CGeneral::GetRandomNumber() % 8 - 3) / 100.0f;\n\t\t\t\tm_vecMoveSpeed.z = Max(m_vecMoveSpeed.z + 0.3f, 0.2f);\n\t\t\t\tPlayOneShotScriptObject(SCRIPT_SOUND_HIT_BALL, GetPosition());\n\t\t\t\tm_vecTurnSpeed.x += (CGeneral::GetRandomNumber() % 16 - 7) / 10.0f;\n\t\t\t\tm_vecTurnSpeed.y += (CGeneral::GetRandomNumber() % 16 - 7) / 10.0f;\n\t\t\t\tm_nBeachballBounces++;\n\t\t\t\tm_nBeachballBounces = Min(m_nBeachballBounces, BEACHBALL_MAX_SCORE);\n\t\t\t\tsprintf(gString, \"%d\", m_nBeachballBounces);\n\t\t\t\tCMoneyMessages::RegisterOne(GetPosition(), gString, 255, 50, 0, 0.6f, 0.5f);\n\t\t\t\tCStats::RegisterHighestScore(3, m_nBeachballBounces);\n\t\t\t}\n\t\t}\n\t}\n\tif (bIsBIGBuilding) {\n\t\tbIsInSafePosition = true;\n\t}\n}\n\nvoid\nCObject::Teleport(CVector vecPos)\n{\n\tCWorld::Remove(this);\n\tm_matrix.GetPosition() = vecPos;\n\tm_matrix.UpdateRW();\n\tUpdateRwFrame();\n\tCWorld::Add(this);\n}\n\nvoid\nCObject::Render(void)\n{\n\tif (bDoNotRender)\n\t\treturn;\n\n\tif (m_nRefModelIndex != -1 && ObjectCreatedBy == TEMP_OBJECT && bUseVehicleColours) {\n\t\tCVehicleModelInfo *mi = (CVehicleModelInfo*)CModelInfo::GetModelInfo(m_nRefModelIndex);\n\t\tassert(mi->GetModelType() == MITYPE_VEHICLE);\n\t\tmi->SetVehicleColour(m_colour1, m_colour2);\n\t}\n\n\tfloat red = (0.8f * CTimeCycle::GetDirectionalRed() + CTimeCycle::GetAmbientRed_Obj()) * 165.75f;\n\tfloat green = (0.8f * CTimeCycle::GetDirectionalGreen() + CTimeCycle::GetAmbientGreen_Obj()) * 165.75f;\n\tfloat blue = (0.8f * CTimeCycle::GetDirectionalBlue() + CTimeCycle::GetAmbientBlue_Obj()) * 165.75f;\n\n\tred = clamp(red, 0.0f, 255.0f);\n\tgreen = clamp(green, 0.0f, 255.0f);\n\tblue = clamp(blue, 0.0f, 255.0f);\n\n\tint alpha = CGeneral::GetRandomNumberInRange(196, 225);\n\n\tRwRGBA color = { (uint8)red, (uint8)green, (uint8)blue, (uint8)alpha };\n\n\tif (this->GetModelIndex() == MI_YT_MAIN_BODY) {\n\t\tfloat moveSpeedMagnitude = this->GetMoveSpeed().Magnitude();\n\t\tif (moveSpeedMagnitude > 0.0f) {\n\t\t\tfloat scaleMax = GetColModel()->boundingBox.max.y * 0.85f;\n\n\t\t\tCVector dir = this->GetMoveSpeed() + 0.3f * this->GetRight() - 0.5f * this->GetForward();\n\t\t\tdir.z += 0.05f * moveSpeedMagnitude;\n\n\t\t\tCVector pos = scaleMax * this->GetForward() + 2.25f * this->GetRight() + this->GetPosition();\n\n\t\t\tfloat fWaterLevel;\n\t\t\tCWaterLevel::GetWaterLevel(pos.x, pos.y, pos.z, &fWaterLevel, true);\n\t\t\tpos.z = fWaterLevel + 0.75f;\n\n\t\t\tCParticle::AddParticle(PARTICLE_BOAT_SPLASH, pos, dir, nil, 1.2f * moveSpeedMagnitude, color,\n\t\t\t\tCGeneral::GetRandomNumberInRange(0.0f, 0.4f), CGeneral::GetRandomNumberInRange(0.0f, 45.0f), 0, 0);\n\n\t\t\tfloat scaleMin = GetColModel()->boundingBox.min.y;\n\n\t\t\tdir = this->GetMoveSpeed() - 0.5f * this->GetForward();\n\t\t\tdir.z += 0.05f * moveSpeedMagnitude;\n\n\t\t\tpos = scaleMin * this->GetForward() + 4.5f * this->GetRight() + this->GetPosition();\n\n\t\t\tCWaterLevel::GetWaterLevel(pos.x, pos.y, pos.z, &fWaterLevel, true);\n\t\t\tpos.z = fWaterLevel + 0.55f;\n\n\t\t\tCParticle::AddParticle(PARTICLE_BOAT_SPLASH, pos, dir, nil, 0.9f, color,\n\t\t\t\tCGeneral::GetRandomNumberInRange(0.0f, 0.4f), CGeneral::GetRandomNumberInRange(0.0f, 45.0f), 0, 0);\n\n\t\t\tpos = scaleMin * 1.1f * this->GetForward() + 2.25f * this->GetRight() + this->GetPosition();\n\n\t\t\tCWaterLevel::GetWaterLevel(pos.x, pos.y, pos.z, &fWaterLevel, true);\n\t\t\tpos.z = fWaterLevel + 0.55f;\n\n\t\t\tCParticle::AddParticle(PARTICLE_BOAT_SPLASH, pos, dir, nil, 0.9f, color,\n\t\t\t\tCGeneral::GetRandomNumberInRange(0.0f, 0.4f), CGeneral::GetRandomNumberInRange(0.0f, 45.0f), 0, 0);\n\n\t\t\tpos = scaleMin * 1.1f * this->GetForward() - 0.05f * this->GetRight() + this->GetPosition();\n\n\t\t\tCWaterLevel::GetWaterLevel(pos.x, pos.y, pos.z, &fWaterLevel, true);\n\t\t\tpos.z = fWaterLevel + 0.55f;\n\n\t\t\tCParticle::AddParticle(PARTICLE_BOAT_SPLASH, pos, dir, nil, 0.9f, color,\n\t\t\t\tCGeneral::GetRandomNumberInRange(0.0f, 0.4f), CGeneral::GetRandomNumberInRange(0.0f, 45.0f), 0, 0);\n\t\t}\n\t}\n\n\tif (this->GetModelIndex() == MI_YT_MAIN_BODY2) {\n\t\tfloat moveSpeedMagnitude = this->GetMoveSpeed().Magnitude();\n\t\tif (moveSpeedMagnitude > 0.0f) {\n\t\t\tfloat scaleMax = GetColModel()->boundingBox.max.y * 0.85f;\n\n\t\t\tCVector dir = this->GetMoveSpeed() - 0.3f * this->GetRight() - 0.5f * this->GetForward();\n\t\t\tdir.z += 0.05f * moveSpeedMagnitude;\n\n\t\t\tCVector pos = scaleMax * this->GetForward() - 2.25f * this->GetRight() + this->GetPosition();\n\n\t\t\tfloat fWaterLevel;\n\t\t\tCWaterLevel::GetWaterLevel(pos.x, pos.y, pos.z, &fWaterLevel, true);\n\t\t\tpos.z = fWaterLevel + 0.75f;\n\n\t\t\tCParticle::AddParticle(PARTICLE_BOAT_SPLASH, pos, dir, nil, 1.2f * moveSpeedMagnitude, color,\n\t\t\t\tCGeneral::GetRandomNumberInRange(0.0f, 0.4f), CGeneral::GetRandomNumberInRange(0.0f, 45.0f), 0, 0);\n\n\t\t\tfloat scaleMin = GetColModel()->boundingBox.min.y;\n\n\t\t\tdir = this->GetMoveSpeed() - 0.5f * this->GetForward();\n\t\t\tdir.z += 0.05f * moveSpeedMagnitude;\n\n\t\t\tpos = scaleMin * this->GetForward() - 4.5f * this->GetRight() + this->GetPosition();\n\n\t\t\tCWaterLevel::GetWaterLevel(pos.x, pos.y, pos.z, &fWaterLevel, true);\n\t\t\tpos.z = fWaterLevel + 0.55f;\n\n\t\t\tCParticle::AddParticle(PARTICLE_BOAT_SPLASH, pos, dir, nil, 0.9f, color,\n\t\t\t\tCGeneral::GetRandomNumberInRange(0.0f, 0.4f), CGeneral::GetRandomNumberInRange(0.0f, 45.0f), 0, 0);\n\n\t\t\tpos = scaleMin * 1.1f * this->GetForward() - 2.25f * this->GetRight() + this->GetPosition();\n\n\t\t\tCWaterLevel::GetWaterLevel(pos.x, pos.y, pos.z, &fWaterLevel, true);\n\t\t\tpos.z = fWaterLevel + 0.55f;\n\n\t\t\tCParticle::AddParticle(PARTICLE_BOAT_SPLASH, pos, dir, nil, 0.9f, color,\n\t\t\t\tCGeneral::GetRandomNumberInRange(0.0f, 0.4f), CGeneral::GetRandomNumberInRange(0.0f, 45.0f), 0, 0);\n\t\t}\n\t}\n\n\tCEntity::Render();\n}\n\nbool\nCObject::SetupLighting(void)\n{\n\tif (bRenderScorched) {\n\t\tWorldReplaceNormalLightsWithScorched(Scene.world, 0.1f);\n\t\treturn true;\n\t} else if (bIsPickup) {\n\t\tSetFullAmbient();\n\t\treturn true;\n\t} else if (bIsWeapon) {\n\t\tActivateDirectional();\n\t\tSetAmbientColoursForPedsCarsAndObjects();\n\t\treturn true;\n\t}\n\treturn false;\n}\n\nvoid\nCObject::RemoveLighting(bool reset)\n{\n\tif (reset) {\n\t\tSetAmbientColours();\n\t\tDeActivateDirectional();\n\t}\n}\n\nvoid\nCObject::ObjectDamage(float amount)\n{\n\tif (!m_nCollisionDamageEffect || !bUsesCollision)\n\t\treturn;\n\tstatic int8 nFrameGen = 0;\n\tbool bBodyCastDamageEffect = false;\n#if 0\n\tif (GetModelIndex() == MI_BODYCAST) {\n\t\tif (amount > 50.0f)\n\t\t\tnBodyCastHealth = (int16)(nBodyCastHealth - 0.5f * amount);\n\t\tif (nBodyCastHealth < 0)\n\t\t\tnBodyCastHealth = 0;\n\t\tif (nBodyCastHealth < 200)\n\t\t\tbBodyCastDamageEffect = true;\n\t\tamount = 0.0f;\n\t}\n#endif\n\tif ((amount * m_fCollisionDamageMultiplier > 150.0f || bBodyCastDamageEffect) && m_nCollisionDamageEffect) {\n\t\tconst CVector &vecPos = m_matrix.GetPosition();\n\t\tconst float fDirectionZ = 0.0002f * amount;\n\t\tswitch (m_nCollisionDamageEffect) {\n\t\t\tcase DAMAGE_EFFECT_CHANGE_MODEL:\n\t\t\t\tbRenderDamaged = true;\n\t\t\t\treturn;\n\t\t\tcase DAMAGE_EFFECT_SPLIT_MODEL:\n\t\t\t\treturn;\n\t\t\tcase DAMAGE_EFFECT_SMASH_AND_DAMAGE_TRAFFICLIGHTS:\n\t\t\t{\n\t\t\t\tstatic RwRGBA debrisColor = { 0xc8,0xc8,0xc8,0xff };\n\t\t\t\tif (bRenderDamaged) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tbRenderDamaged = true;\n\t\t\t\tCVector min = 0.85f * GetColModel()->boundingBox.min;\n\t\t\t\tCVector max = 0.85f * GetColModel()->boundingBox.max;\n\t\t\t\tmin.z = max.z;\n\t\t\t\tmin = GetMatrix() * min;\n\t\t\t\tmax = GetMatrix() * max;\n\t\t\t\tCVector temp = (max - min) * 0.02f;\n\t\t\t\tfor (int32 i = 0; i < 50; i++) {\n\t\t\t\t\tCVector vecDir = CVector(\n\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(-0.35f, 0.35f),\n\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(-0.35f, 0.35f),\n\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(0.10f, 0.25f)\n\t\t\t\t\t);\n\t\t\t\t\t++nFrameGen;\n\t\t\t\t\tint32 currentFrame = nFrameGen & 3;\n\t\t\t\t\tCVector pos = min + temp * (float)i;\n\t\t\t\t\tfloat fSize = CGeneral::GetRandomNumberInRange(0.02f, 0.20f);\n\t\t\t\t\tfloat fColorFactor = CGeneral::GetRandomNumberInRange(0.6f, 1.2f);\n\t\t\t\t\tRwRGBA color = debrisColor;\n\t\t\t\t\tcolor.red *= fColorFactor;\n\t\t\t\t\tcolor.green *= fColorFactor;\n\t\t\t\t\tint32 nRotationSpeed = CGeneral::GetRandomNumberInRange(-0.40f, 0.40f);\n\t\t\t\t\tCParticle::AddParticle(PARTICLE_CAR_DEBRIS, pos, vecDir, nil, fSize, color, nRotationSpeed, 0, currentFrame, 0);\n\t\t\t\t}\n\t\t\t\tPlayOneShotScriptObject(SCRIPT_SOUND_METAL_COLLISION, min);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase DAMAGE_EFFECT_CHANGE_THEN_SMASH: {\n\t\t\t\tif (!bRenderDamaged) {\n\t\t\t\t\tbRenderDamaged = true;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\t// fall through\n\t\t\t}\n\t\t\tcase DAMAGE_EFFECT_SMASH_COMPLETELY: {\n\t\t\t\tbIsVisible = false;\n\t\t\t\tbUsesCollision = false;\n\t\t\t\tif (!GetIsStatic()) {\n\t\t\t\t\tRemoveFromMovingList();\n\t\t\t\t}\n\t\t\t\tSetIsStatic(true);\n\t\t\t\tbExplosionProof = true;\n\t\t\t\tSetMoveSpeed(0.0f, 0.0f, 0.0f);\n\t\t\t\tSetTurnSpeed(0.0f, 0.0f, 0.0f);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase DAMAGE_EFFECT_SMASH_CARDBOARD_COMPLETELY:\n\t\t\tcase DAMAGE_EFFECT_SMASH_YELLOW_TARGET_COMPLETELY:\n\t\t\t{\n\t\t\t\tbIsVisible = false;\n\t\t\t\tbUsesCollision = false;\n\t\t\t\tif (!GetIsStatic()) {\n\t\t\t\t\tRemoveFromMovingList();\n\t\t\t\t}\n\t\t\t\tSetIsStatic(true);\n\t\t\t\tbExplosionProof = true;\n\t\t\t\tSetMoveSpeed(0.0f, 0.0f, 0.0f);\n\t\t\t\tSetTurnSpeed(0.0f, 0.0f, 0.0f);\n\t\t\t\tconst RwRGBA color = { 96, 48, 0, 255 };\n\t\t\t\tfor (int32 i = 0; i < 25; i++) {\n\t\t\t\t\tCVector vecDir = CVector(\n\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(-0.35f, 0.35f),\n\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(-0.35f, 0.35f),\n\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(0.10f, 0.25f) + fDirectionZ\n\t\t\t\t\t);\n\t\t\t\t\t++nFrameGen;\n\t\t\t\t\tint32 currentFrame = nFrameGen & 3;\n\t\t\t\t\tRwRGBA randomColor = color;\n\t\t\t\t\tswitch (m_nCollisionDamageEffect) {\n\t\t\t\t\t\tcase DAMAGE_EFFECT_SMASH_CARDBOARD_COMPLETELY: {\n\t\t\t\t\t\t\tfloat fRandom = CGeneral::GetRandomNumberInRange(0.01f, 1.0f);\n\t\t\t\t\t\t\trandomColor.red *= fRandom;\n\t\t\t\t\t\t\trandomColor.green *= fRandom;\n\t\t\t\t\t\t\trandomColor.blue *= fRandom;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcase DAMAGE_EFFECT_SMASH_YELLOW_TARGET_COMPLETELY: {\n\t\t\t\t\t\t\trandomColor.red = 0xff;\n\t\t\t\t\t\t\trandomColor.green = 0xfc;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tfloat fSize = CGeneral::GetRandomNumberInRange(0.02f, 0.20f);\n\t\t\t\t\tint32 nRotationSpeed = CGeneral::GetRandomNumberInRange(-40, 40);\n\t\t\t\t\tCParticle::AddParticle(PARTICLE_CAR_DEBRIS, vecPos, vecDir, nil, fSize, randomColor, nRotationSpeed, 0, currentFrame, 0);\n\t\t\t\t}\n\t\t\t\tPlayOneShotScriptObject(SCRIPT_SOUND_BOX_DESTROYED_2, vecPos);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase DAMAGE_EFFECT_SMASH_WOODENBOX_COMPLETELY:\n\t\t\t{\n\t\t\t\tbIsVisible = false;\n\t\t\t\tbUsesCollision = false;\n\t\t\t\tif (!GetIsStatic()) {\n\t\t\t\t\tRemoveFromMovingList();\n\t\t\t\t}\n\t\t\t\tSetIsStatic(true);\n\t\t\t\tbExplosionProof = true;\n\t\t\t\tSetMoveSpeed(0.0f, 0.0f, 0.0f);\n\t\t\t\tSetTurnSpeed(0.0f, 0.0f, 0.0f);\n\t\t\t\tstatic const RwRGBA color = { 128, 128, 128, 255 };\n\t\t\t\tCVector position = GetPosition();\n\t\t\t\tfor (int32 i = 0; i < 45; i++) {\n\t\t\t\t\tCVector vecDir = CVector(\n\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(-0.35f, 0.35f),\n\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(-0.35f, 0.35f),\n\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(0.10f, 0.25f) + fDirectionZ\n\t\t\t\t\t);\n\t\t\t\t\t++nFrameGen;\n\t\t\t\t\tint32 currentFrame = nFrameGen & 3;\n\t\t\t\t\tfloat fRandom = CGeneral::GetRandomNumberInRange(0.5f, 1.0f);\n\t\t\t\t\tRwRGBA randomColor = { uint8(color.red * fRandom), uint8(color.green * fRandom), uint8(color.blue * fRandom), color.alpha };\n\t\t\t\t\tfloat fSize = CGeneral::GetRandomNumberInRange(0.02f, 0.20f);\n\t\t\t\t\tint32 nRotationSpeed = CGeneral::GetRandomNumberInRange(-40, 40);\n\t\t\t\t\tCParticle::AddParticle(PARTICLE_CAR_DEBRIS, vecPos, vecDir, nil, fSize, randomColor, nRotationSpeed, 0, currentFrame, 0);\n\t\t\t\t}\n\t\t\t\tPlayOneShotScriptObject(SCRIPT_SOUND_BOX_DESTROYED_1, vecPos);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase DAMAGE_EFFECT_SMASH_TRAFFICCONE_COMPLETELY:\n\t\t\tcase DAMAGE_EFFECT_BURST_BEACHBALL:\n\t\t\t{\n\t\t\t\tbIsVisible = false;\n\t\t\t\tbUsesCollision = false;\n\t\t\t\tif (!GetIsStatic()) {\n\t\t\t\t\tRemoveFromMovingList();\n\t\t\t\t}\n\t\t\t\tSetIsStatic(true);\n\t\t\t\tbExplosionProof = true;\n\t\t\t\tSetMoveSpeed(0.0f, 0.0f, 0.0f);\n\t\t\t\tSetTurnSpeed(0.0f, 0.0f, 0.0f);\n\t\t\t\tconst RwRGBA color1 = { 200, 0, 0, 255 };\n\t\t\t\tconst RwRGBA color2 = { 200, 200, 200, 255 };\n\t\t\t\tfor (int32 i = 0; i < 10; i++) {\n\t\t\t\t\tCVector vecDir = CVector(\n\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(-0.35f, 0.35f),\n\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(-0.35f, 0.35f),\n\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(0.10f, 0.25f) + fDirectionZ\n\t\t\t\t\t);\n\t\t\t\t\t++nFrameGen;\n\t\t\t\t\tint32 currentFrame = nFrameGen & 3;\n\t\t\t\t\tRwRGBA color = color2;\n\t\t\t\t\tif (nFrameGen & 1)\n\t\t\t\t\t\tcolor = color1;\n\t\t\t\t\tfloat fSize = CGeneral::GetRandomNumberInRange(0.02f, 0.20f);\n\t\t\t\t\tint32 nRotationSpeed = CGeneral::GetRandomNumberInRange(-40, 40);\n\t\t\t\t\tCParticle::AddParticle(PARTICLE_CAR_DEBRIS, vecPos, vecDir, nil, fSize, color, nRotationSpeed, 0, currentFrame, 0);\n\t\t\t\t}\n\t\t\t\tif (m_nCollisionDamageEffect == DAMAGE_EFFECT_BURST_BEACHBALL) {\n\t\t\t\t\tPlayOneShotScriptObject(SCRIPT_SOUND_HIT_BALL, vecPos);\n\t\t\t\t} else {\n\t\t\t\t\tPlayOneShotScriptObject(SCRIPT_SOUND_TIRE_COLLISION, vecPos);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase DAMAGE_EFFECT_SMASH_BARPOST_COMPLETELY:\n\t\t\t{\n\t\t\t\tbIsVisible = false;\n\t\t\t\tbUsesCollision = false;\n\t\t\t\tif (!GetIsStatic()) {\n\t\t\t\t\tRemoveFromMovingList();\n\t\t\t\t}\n\t\t\t\tSetIsStatic(true);\n\t\t\t\tbExplosionProof = true;\n\t\t\t\tSetMoveSpeed(0.0f, 0.0f, 0.0f);\n\t\t\t\tSetTurnSpeed(0.0f, 0.0f, 0.0f);\n\t\t\t\tconst RwRGBA color1 = { 200, 0, 0, 255 };\n\t\t\t\tconst RwRGBA color2 = { 200, 200, 200, 255 };\n\t\t\t\tSetMoveSpeed(0.0f, 0.0f, 0.0f);\n\t\t\t\tSetTurnSpeed(0.0f, 0.0f, 0.0f);\n\t\t\t\tfor (int32 i = 0; i < 32; i++) {\n\t\t\t\t\tCVector vecDir = CVector(\n\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(-0.35f, 0.35f),\n\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(-0.35f, 0.35f),\n\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(0.10f, 0.25f) + fDirectionZ\n\t\t\t\t\t);\n\t\t\t\t\t++nFrameGen;\n\t\t\t\t\tint32 currentFrame = nFrameGen & 3;\n\t\t\t\t\tconst RwRGBA &color = nFrameGen & 1 ? color1 : color2;\n\t\t\t\t\tfloat fSize = CGeneral::GetRandomNumberInRange(0.02f, 0.20f);\n\t\t\t\t\tint32 nRotationSpeed = CGeneral::GetRandomNumberInRange(-40, 40);\n\t\t\t\t\tCParticle::AddParticle(PARTICLE_CAR_DEBRIS, vecPos, vecDir, nil, fSize, color, nRotationSpeed, 0, currentFrame, 0);\n\t\t\t\t}\n\t\t\t\tPlayOneShotScriptObject(SCRIPT_SOUND_METAL_COLLISION, vecPos);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase DAMAGE_EFFECT_SMASH_NEWSTANDNEW1:\n\t\t\tcase DAMAGE_EFFECT_SMASH_NEWSTANDNEW2:\n\t\t\tcase DAMAGE_EFFECT_SMASH_NEWSTANDNEW3:\n\t\t\tcase DAMAGE_EFFECT_SMASH_NEWSTANDNEW4:\n\t\t\tcase DAMAGE_EFFECT_SMASH_NEWSTANDNEW5:\n\t\t\t{\n\t\t\t\tbIsVisible = false;\n\t\t\t\tbUsesCollision = false;\n\t\t\t\tif (!GetIsStatic()) {\n\t\t\t\t\tRemoveFromMovingList();\n\t\t\t\t}\n\t\t\t\tSetIsStatic(true);\n\t\t\t\tbExplosionProof = true;\n\t\t\t\tSetMoveSpeed(0.0f, 0.0f, 0.0f);\n\t\t\t\tSetTurnSpeed(0.0f, 0.0f, 0.0f);\n\t\t\t\tCRGBA possibleColor1;\n\t\t\t\tCRGBA possibleColor2;\n\t\t\t\tswitch (m_nCollisionDamageEffect) {\n\t\t\t\t\tcase DAMAGE_EFFECT_SMASH_NEWSTANDNEW1:\n\t\t\t\t\t\tpossibleColor1 = CRGBA(0xC0, 0x3E, 0xC, 0xFF);\n\t\t\t\t\t\tpossibleColor2 = possibleColor1;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase DAMAGE_EFFECT_SMASH_NEWSTANDNEW2:\n\t\t\t\t\t\tpossibleColor1 = CRGBA(0xA3, 0x36, 0x21, 0xFF);\n\t\t\t\t\t\tpossibleColor2 = possibleColor1;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase DAMAGE_EFFECT_SMASH_NEWSTANDNEW3:\n\t\t\t\t\t\tpossibleColor1 = CRGBA(0x12, 0x31, 0x24, 0xFF);\n\t\t\t\t\t\tpossibleColor2 = possibleColor1;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase DAMAGE_EFFECT_SMASH_NEWSTANDNEW4:\n\t\t\t\t\t\tpossibleColor1 = CRGBA(0xC0, 0xC8, 0xBE, 0xFF);\n\t\t\t\t\t\tpossibleColor2 = CRGBA(0x10, 0x57, 0x85, 0xFF);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase DAMAGE_EFFECT_SMASH_NEWSTANDNEW5:\n\t\t\t\t\t\tpossibleColor1 = CRGBA(0xD0, 0x94, 0x1B, 0xFF);\n\t\t\t\t\t\tpossibleColor2 = possibleColor1;\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tfor (int32 i = 0; i < 16; i++) {\n\t\t\t\t\tCVector vecDir(\n\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(-0.35f, 0.35f),\n\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(-0.35f, 0.35f),\n\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(0.10f, 0.15f) + fDirectionZ\n\t\t\t\t\t);\n\t\t\t\t\tfloat fSize = CGeneral::GetRandomNumberInRange(0.02f, 0.20f);\n\t\t\t\t\tint32 nRotationSpeed = CGeneral::GetRandomNumberInRange(-40, 40);\n\t\t\t\t\t++nFrameGen;\n\t\t\t\t\tint32 nCurFrame = nFrameGen & 0x3;\n\t\t\t\t\tCRGBA &selectedColor = nFrameGen & 0x1 ? possibleColor1 : possibleColor2;\n\t\t\t\t\tCParticle::AddParticle(PARTICLE_CAR_DEBRIS, vecPos, vecDir, nil, fSize, selectedColor, nRotationSpeed, 0, nCurFrame, 0);\n\t\t\t\t\tif (!(i % 7)) {\n\t\t\t\t\t\tstatic CRGBA secondParticleColors[4] = {\n\t\t\t\t\t\t\tCRGBA(0xA0, 0x60, 0x60, 0xFF),\n\t\t\t\t\t\t\tCRGBA(0x60, 0xA0, 0x60, 0xFF),\n\t\t\t\t\t\t\tCRGBA(0x60, 0x60, 0xA0, 0xFF),\n\t\t\t\t\t\t\tCRGBA(0xA0, 0xA0, 0xA0, 0xFF)\n\t\t\t\t\t\t};\n\t\t\t\t\t\tvecDir *= 0.5f;\n\t\t\t\t\t\tCRGBA &secondParticleColor = secondParticleColors[nFrameGen & 3];\n\t\t\t\t\t\tint32 nSecondRotationSpeed = CGeneral::GetRandomNumberInRange(-40, 40);\n\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_DEBRIS, vecPos, vecDir, nil, 0.1f, secondParticleColor, nSecondRotationSpeed, 0, 1, 0);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tPlayOneShotScriptObject(SCRIPT_SOUND_METAL_COLLISION, vecPos);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase DAMAGE_EFFECT_SMASH_VEGPALM:\n\t\t\t{\n\t\t\t\tstatic RwRGBA primaryColor1 = { 0x39, 0x4D, 0x29, 0xff };\n\t\t\t\tstatic RwRGBA primaryColor2 = { 0x94, 0x7D, 0x73, 0xff };\n\t\t\t\tbIsVisible = false;\n\t\t\t\tbUsesCollision = false;\n\t\t\t\tif (!GetIsStatic()) {\n\t\t\t\t\tRemoveFromMovingList();\n\t\t\t\t}\n\t\t\t\tSetIsStatic(true);\n\t\t\t\tbExplosionProof = true;\n\t\t\t\tSetMoveSpeed(0.0f, 0.0f, 0.0f);\n\t\t\t\tSetTurnSpeed(0.0f, 0.0f, 0.0f);\n\t\t\t\tfloat fRadius = GetColModel()->boundingSphere.radius;\n\t\t\t\tfor (int32 i = 0; i < 32; i++) {\n\t\t\t\t\tCVector particleDir = CVector(\n\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(-0.25f, 0.25f),\n\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(-0.25f, 0.25f),\n\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(-0.05f, 0.05f) + fDirectionZ\n\t\t\t\t\t);\n\t\t\t\t\tCVector particlePos = vecPos;\n\t\t\t\t\tparticlePos.z += CGeneral::GetRandomNumberInRange(0.0f, 1.0f) * fRadius;\n\t\t\t\t\t++nFrameGen;\n\t\t\t\t\tint32 nRotationSpeed = CGeneral::GetRandomNumberInRange(-40, 40);\n\t\t\t\t\tint32 nCurFrame = nFrameGen & 0x3;\n\t\t\t\t\tfloat fSize = CGeneral::GetRandomNumberInRange(0.02f, 0.20f);\n\t\t\t\t\tRwRGBA& particleColor = nFrameGen & 1 ? primaryColor1 : primaryColor2;\n\t\t\t\t\tCParticle::AddParticle(PARTICLE_CAR_DEBRIS, particlePos, particleDir, nil, fSize, particleColor, nRotationSpeed, 0, nCurFrame, 0);\n\t\t\t\t\tif ((i % 7) == 0) {\n\t\t\t\t\t\tstatic RwRGBA secondaryColor = { 0x9A, 0x99, 0x99, 0x3E };\n\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_DEBRIS, particlePos, particleDir, nil, 0.3, secondaryColor, nRotationSpeed, 0, 0, 0);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tPlayOneShotScriptObject(SCRIPT_SOUND_BOX_DESTROYED_2, vecPos);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase DAMAGE_EFFECT_SMASH_BLACKBAG:\n\t\t\tcase DAMAGE_EFFECT_SMASH_BEACHLOUNGE_WOOD:\n\t\t\tcase DAMAGE_EFFECT_SMASH_BEACHLOUNGE_TOWEL:\n\t\t\t{\n\t\t\t\tbIsVisible = false;\n\t\t\t\tbUsesCollision = false;\n\t\t\t\tif (!GetIsStatic()) {\n\t\t\t\t\tRemoveFromMovingList();\n\t\t\t\t}\n\t\t\t\tSetIsStatic(true);\n\t\t\t\tbExplosionProof = true;\n\t\t\t\tSetMoveSpeed(0.0f, 0.0f, 0.0f);\n\t\t\t\tSetTurnSpeed(0.0f, 0.0f, 0.0f);\n\t\t\t\tCRGBA possibleColor1;\n\t\t\t\tCRGBA possibleColor2;\n\t\t\t\tswitch (m_nCollisionDamageEffect) {\n\t\t\t\t\tcase DAMAGE_EFFECT_SMASH_BLACKBAG:\n\t\t\t\t\t\tpossibleColor1 = CRGBA(0, 0, 0, 0xFF);\n\t\t\t\t\t\tpossibleColor2 = possibleColor1;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase DAMAGE_EFFECT_SMASH_BEACHLOUNGE_WOOD:\n\t\t\t\t\t\tpossibleColor1 = CRGBA(0x8F, 0x8A, 0x8C, 0xFF);\n\t\t\t\t\t\tpossibleColor2 = CRGBA(0x73, 0x75, 0x7B, 0xFF);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase DAMAGE_EFFECT_SMASH_BEACHLOUNGE_TOWEL:\n\t\t\t\t\t\tpossibleColor1 = CRGBA(0x52, 0x92, 0x4A, 0xFF);\n\t\t\t\t\t\tpossibleColor2 = CRGBA(0xCE, 0xCF, 0xCE, 0xFF);\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tfor (int32 i = 0; i < 16; i++) {\n\t\t\t\t\tCVector vecDir(\n\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(-0.35f, 0.35f),\n\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(-0.35f, 0.35f),\n\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(0.10f, 0.25f) + fDirectionZ\n\t\t\t\t\t);\n\t\t\t\t\t++nFrameGen;\n\t\t\t\t\tint32 nCurFrame = nFrameGen & 0x3;\n\t\t\t\t\tCRGBA &selectedColor = nFrameGen & 0x1 ? possibleColor1 : possibleColor2;\n\t\t\t\t\tfloat fSize = CGeneral::GetRandomNumberInRange(0.02f, 0.20f);\n\t\t\t\t\tint32 nRotationSpeed = CGeneral::GetRandomNumberInRange(-40, 40);\n\t\t\t\t\tCParticle::AddParticle(PARTICLE_CAR_DEBRIS, vecPos, vecDir, nil, fSize, selectedColor, nRotationSpeed, 0, nCurFrame, 0);\n\t\t\t\t}\n\t\t\t\tif (m_nCollisionDamageEffect == DAMAGE_EFFECT_SMASH_BLACKBAG) {\n\t\t\t\t\tPlayOneShotScriptObject(SCRIPT_SOUND_BOX_DESTROYED_2, vecPos);\n\t\t\t\t} else if (m_nCollisionDamageEffect == DAMAGE_EFFECT_SMASH_BEACHLOUNGE_WOOD) {\n\t\t\t\t\tPlayOneShotScriptObject(SCRIPT_SOUND_METAL_COLLISION, vecPos);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tdefault:\n\t\t\t\tDEV(\"Unhandled collision damage effect id: %d\\n\", m_nCollisionDamageEffect);\n\t\t\t\treturn;\n\t\t}\n\t}\n}\n\nvoid\nCObject::RefModelInfo(int32 modelId)\n{\n\tm_nRefModelIndex = modelId;\n\tCModelInfo::GetModelInfo(modelId)->AddRef();\n}\n\nvoid\nCObject::Init(void)\n{\n\tm_type = ENTITY_TYPE_OBJECT;\n\tCObjectData::SetObjectData(GetModelIndex(), *this);\n\tm_nEndOfLifeTime = 0;\n\tObjectCreatedBy = GAME_OBJECT;\n\tSetIsStatic(true);\n\tbIsPickup = false;\n\tbPickupObjWithMessage = false;\n\tbOutOfStock = false;\n\tbGlassCracked = false;\n\tbGlassBroken = false;\n\tbHasBeenDamaged = false;\n\tbUseVehicleColours = false;\n\tm_nRefModelIndex = -1;\n\tm_colour1 = 0;\n\tm_colour2 = 0;\n\tm_nBonusValue = 0;\n\tbIsWeapon = false;\n\tm_nCostValue = 0;\n\tm_pCollidingEntity = nil;\n\tCColPoint point;\n\tCEntity *outEntity = nil;\n\tconst CVector &vecPos = m_matrix.GetPosition();\n\tif (CWorld::ProcessVerticalLine(vecPos, vecPos.z - 10.0f, point, outEntity, true, false, false, false, false, false, nil))\n\t\tm_pCurSurface = outEntity;\n\telse\n\t\tm_pCurSurface = nil;\n\n\tif (GetModelIndex() == MI_BUOY)\n\t\tbTouchingWater = true;\n\n\tif (CModelInfo::GetModelInfo(GetModelIndex())->GetModelType() == MITYPE_WEAPON)\n\t\tbIsWeapon = true;\n\tbIsStreetLight = IsLightObject(GetModelIndex());\n\n\tm_area = AREA_EVERYWHERE;\n}\n\nbool\nCObject::CanBeDeleted(void)\n{\n\tswitch (ObjectCreatedBy) {\n\t\tcase GAME_OBJECT:\n\t\t\treturn true;\n\t\tcase MISSION_OBJECT:\n\t\t\treturn false;\n\t\tcase TEMP_OBJECT:\n\t\t\treturn true;\n\t\tcase CUTSCENE_OBJECT:\n\t\t\treturn false;\n\t\tcase CONTROLLED_SUB_OBJECT:\n\t\t\treturn false;\n\t\tdefault:\n\t\t\treturn true;\n\t}\n}\n\nvoid\nCObject::DeleteAllMissionObjects()\n{\n\tCObjectPool *objectPool = CPools::GetObjectPool();\n\tfor (int32 i = 0; i < objectPool->GetSize(); i++) {\n\t\tCObject *pObject = objectPool->GetSlot(i);\n\t\tif (pObject && pObject->ObjectCreatedBy == MISSION_OBJECT) {\n\t\t\tCWorld::Remove(pObject);\n\t\t\tdelete pObject;\n\t\t}\n\t}\n}\n\nvoid\nCObject::DeleteAllTempObjects()\n{\n\tCObjectPool *objectPool = CPools::GetObjectPool();\n\tfor (int32 i = 0; i < objectPool->GetSize(); i++) {\n\t\tCObject *pObject = objectPool->GetSlot(i);\n\t\tif (pObject && pObject->ObjectCreatedBy == TEMP_OBJECT) {\n\t\t\tCWorld::Remove(pObject);\n\t\t\tdelete pObject;\n\t\t}\n\t}\n}\n\nvoid\nCObject::DeleteAllTempObjectsInArea(CVector point, float fRadius)\n{\n\tCObjectPool *objectPool = CPools::GetObjectPool();\n\tfor (int32 i = 0; i < objectPool->GetSize(); i++) {\n\t\tCObject *pObject = objectPool->GetSlot(i);\n\t\tif (pObject && pObject->ObjectCreatedBy == TEMP_OBJECT && (point - pObject->GetPosition()).MagnitudeSqr() < SQR(fRadius)) {\n\t\t\tCWorld::Remove(pObject);\n\t\t\tdelete pObject;\n\t\t}\n\t}\n}\n\nbool\nIsObjectPointerValid(CObject *pObject)\n{\n\tif (!pObject)\n\t\treturn false;\n\tint index = CPools::GetObjectPool()->GetJustIndex_NoFreeAssert(pObject);\n#ifdef FIX_BUGS\n\tif (index < 0 || index >= CPools::GetObjectPool()->GetSize())\n#else\n\tif (index < 0 || index > CPools::GetObjectPool()->GetSize())\n#endif\n\t\treturn false;\n\treturn pObject->bIsBIGBuilding || pObject->m_entryInfoList.first;\n}\n"
  },
  {
    "path": "src/objects/Object.h",
    "content": "#pragma once\n\n#include \"Physical.h\"\n\nenum {\n\tUNKNOWN_OBJECT = 0,\n\tGAME_OBJECT = 1,\n\tMISSION_OBJECT = 2,\n\tTEMP_OBJECT = 3,\n\tCUTSCENE_OBJECT = 4,\n\tCONTROLLED_SUB_OBJECT = 5,\n};\n\nenum CollisionSpecialResponseCase\n{\n\tCOLLRESPONSE_NONE,\n\tCOLLRESPONSE_LAMPOST,\n\tCOLLRESPONSE_SMALLBOX,\n\tCOLLRESPONSE_BIGBOX,\n\tCOLLRESPONSE_FENCEPART,\n\tCOLLRESPONSE_UNKNOWN5\n};\n\nenum CollisionDamageEffect\n{\n\tDAMAGE_EFFECT_NONE,\n\tDAMAGE_EFFECT_CHANGE_MODEL,\n\tDAMAGE_EFFECT_SPLIT_MODEL,\n\tDAMAGE_EFFECT_SMASH_AND_DAMAGE_TRAFFICLIGHTS,\n\n\tDAMAGE_EFFECT_SMASH_COMPLETELY = 20,\n\tDAMAGE_EFFECT_CHANGE_THEN_SMASH,\n\n\tDAMAGE_EFFECT_SMASH_CARDBOARD_COMPLETELY = 50,\n\tDAMAGE_EFFECT_SMASH_YELLOW_TARGET_COMPLETELY = 51,\n\n\tDAMAGE_EFFECT_SMASH_WOODENBOX_COMPLETELY = 60,\n\tDAMAGE_EFFECT_SMASH_TRAFFICCONE_COMPLETELY = 70,\n\tDAMAGE_EFFECT_SMASH_BARPOST_COMPLETELY = 80,\n\n\tDAMAGE_EFFECT_SMASH_NEWSTANDNEW1 = 91,\n\tDAMAGE_EFFECT_SMASH_NEWSTANDNEW2 = 92,\n\tDAMAGE_EFFECT_SMASH_NEWSTANDNEW3 = 93,\n\tDAMAGE_EFFECT_SMASH_NEWSTANDNEW4 = 94,\n\tDAMAGE_EFFECT_SMASH_NEWSTANDNEW5 = 95,\n\n\tDAMAGE_EFFECT_SMASH_BLACKBAG = 100,\n\tDAMAGE_EFFECT_SMASH_VEGPALM = 110,\n\tDAMAGE_EFFECT_BURST_BEACHBALL = 120,\n\tDAMAGE_EFFECT_SMASH_BEACHLOUNGE_WOOD = 131,\n\tDAMAGE_EFFECT_SMASH_BEACHLOUNGE_TOWEL = 132,\n};\n\nclass CVehicle;\nclass CDummyObject;\n\nclass CObject : public CPhysical\n{\npublic:\n\tCMatrix m_objectMatrix;\n\tfloat m_fUprootLimit;\n\tint8 ObjectCreatedBy;\n\tuint8 bIsPickup : 1;\n\tuint8 bAmmoCollected : 1;\n\tuint8 bPickupObjWithMessage : 1;\n\tuint8 bOutOfStock : 1;\n\tuint8 bGlassCracked : 1;\n\tuint8 bGlassBroken : 1;\n\tuint8 bHasBeenDamaged : 1;\n\tuint8 bUseVehicleColours : 1;\n\tuint8 bIsWeapon : 1;\n\tuint8 bIsStreetLight : 1;\n\tint8 m_nBonusValue;\n\tuint16 m_nCostValue;\n\tfloat m_fCollisionDamageMultiplier;\n\tuint8 m_nCollisionDamageEffect;\n\tuint8 m_nSpecialCollisionResponseCases;\n\tbool m_bCameraToAvoidThisObject;\n\tuint8 m_nBeachballBounces;\n\tuint32 m_obj_unused1;\n\tuint32 m_nEndOfLifeTime;\n\tint16 m_nRefModelIndex;\n\tCEntity *m_pCurSurface;\n\tCEntity *m_pCollidingEntity;\n\tint8 m_colour1, m_colour2;\n\n\tstatic int16 nNoTempObjects;\n\tstatic float fDistToNearestTree;\n\n\tstatic void *operator new(size_t);\n\tstatic void *operator new(size_t, int);\n\tstatic void operator delete(void*, size_t);\n\tstatic void operator delete(void*, int);\n\n\tCObject(void);\n\tCObject(int32, bool);\n\tCObject(CDummyObject*);\n\t~CObject(void);\n\n\tvoid ProcessControl(void);\n\tvoid Teleport(CVector vecPos);\n\tvoid Render(void);\n\tbool SetupLighting(void);\n\tvoid RemoveLighting(bool reset);\n\n\tvoid ObjectDamage(float amount);\n\tvoid RefModelInfo(int32 modelId);\n\tvoid Init(void);\n\tbool CanBeDeleted(void);\n\n\tstatic void DeleteAllMissionObjects();\n\tstatic void DeleteAllTempObjects();\n\tstatic void DeleteAllTempObjectsInArea(CVector point, float fRadius);\n};\n\nbool IsObjectPointerValid(CObject* pObject);\n"
  },
  {
    "path": "src/objects/ObjectData.cpp",
    "content": "#include \"common.h\"\n\n#include \"main.h\"\n#include \"ModelInfo.h\"\n#include \"Object.h\"\n#include \"FileMgr.h\"\n#include \"ObjectData.h\"\n\nCObjectInfo CObjectData::ms_aObjectInfo[NUMOBJECTINFO];\n\n// Another ugly file reader\nvoid\nCObjectData::Initialise(const char *filename)\n{\n\tchar *p, *lp;\n\tchar line[1024], name[256];\n\tint id;\n\tfloat percentSubmerged;\n\tint damageEffect, responseCase, camAvoid;\n\tCBaseModelInfo *mi;\n\t\n\tms_aObjectInfo[0].m_fMass = 99999.0f;\n\tms_aObjectInfo[0].m_fTurnMass = 99999.0f;\n\tms_aObjectInfo[0].m_fAirResistance = 0.99f;\n\tms_aObjectInfo[0].m_fElasticity = 0.1f;\n\tms_aObjectInfo[0].m_fBuoyancy = GRAVITY * ms_aObjectInfo[0].m_fMass * 2.0f;\n\tms_aObjectInfo[0].m_fUprootLimit = 0.0f;\n\tms_aObjectInfo[0].m_fCollisionDamageMultiplier = 1.0f;\n\tms_aObjectInfo[0].m_nCollisionDamageEffect = 0;\n\tms_aObjectInfo[0].m_nSpecialCollisionResponseCases = 0;\n\tms_aObjectInfo[0].m_bCameraToAvoidThisObject = false;\n\n\tms_aObjectInfo[1].m_fMass = 99999.0f;\n\tms_aObjectInfo[1].m_fTurnMass = 99999.0f;\n\tms_aObjectInfo[1].m_fAirResistance = 0.99f;\n\tms_aObjectInfo[1].m_fElasticity = 0.1f;\n\tms_aObjectInfo[1].m_fBuoyancy = ms_aObjectInfo[0].m_fBuoyancy;\n\tms_aObjectInfo[1].m_fUprootLimit = 0.0f;\n\tms_aObjectInfo[1].m_fCollisionDamageMultiplier = 1.0f;\n\tms_aObjectInfo[1].m_nCollisionDamageEffect = 0;\n\tms_aObjectInfo[1].m_nSpecialCollisionResponseCases = 0;\n\tms_aObjectInfo[1].m_bCameraToAvoidThisObject = true;\n\n\tms_aObjectInfo[2].m_fMass = 99999.0f;\n\tms_aObjectInfo[2].m_fTurnMass = 99999.0f;\n\tms_aObjectInfo[2].m_fAirResistance = 0.99f;\n\tms_aObjectInfo[2].m_fElasticity = 0.1f;\n\tms_aObjectInfo[2].m_fBuoyancy = ms_aObjectInfo[0].m_fBuoyancy;\n\tms_aObjectInfo[2].m_fUprootLimit = 0.0f;\n\tms_aObjectInfo[2].m_fCollisionDamageMultiplier = 1.0f;\n\tms_aObjectInfo[2].m_nCollisionDamageEffect = 0;\n\tms_aObjectInfo[2].m_bCameraToAvoidThisObject = false;\n\tms_aObjectInfo[2].m_nSpecialCollisionResponseCases = 4;\n\n\tms_aObjectInfo[3].m_fMass = 99999.0f;\n\tms_aObjectInfo[3].m_fTurnMass = 99999.0f;\n\tms_aObjectInfo[3].m_fAirResistance = 0.99f;\n\tms_aObjectInfo[3].m_fElasticity = 0.1f;\n\tms_aObjectInfo[3].m_fBuoyancy = ms_aObjectInfo[0].m_fBuoyancy;\n\tms_aObjectInfo[3].m_fUprootLimit = 0.0f;\n\tms_aObjectInfo[3].m_fCollisionDamageMultiplier = 1.0f;\n\tms_aObjectInfo[3].m_nCollisionDamageEffect = 0;\n\tms_aObjectInfo[3].m_nSpecialCollisionResponseCases = 4;\n\tms_aObjectInfo[3].m_bCameraToAvoidThisObject = true;\n\n\tCFileMgr::SetDir(\"\");\n\tCFileMgr::LoadFile(filename, work_buff, sizeof(work_buff), \"r\");\n\n\tid = 4;\n\tp = (char*)work_buff;\n\twhile(*p != '*'){\n\t\t// skip over white space and comments\n\t\twhile(*p == ' ' || *p == '\\n' || *p == '\\r' || *p == ';')\n\t\t\tif(*p == ';')\n\t\t\t\twhile(*p != '\\n' && *p != '*')\n\t\t\t\t\tp++;\n\t\t\telse\n\t\t\t\tp++;\n\n\t\tif(*p == '*')\n\t\t\tbreak;\n\n\t\t// read one line\n\t\tlp = line;\n\t\twhile(*p != '\\n' && *p != '*'){\n\t\t\t*lp++ = *p == ',' ? ' ' : *p;\n\t\t\tp++;\n\t\t}\n\t\tif(*p == '\\n')\n\t\t\tp++;\n#ifdef FIX_BUGS\n\t\t*lp = '\\0';\t// FIX: game wrote '\\n' here\n#else\n\t\t*lp = '\\n';\n#endif\n\n\t\tassert(id < NUMOBJECTINFO);\n\t\tsscanf(line, \"%s %f %f %f %f %f %f %f %d %d %d\", name,\n\t\t\t&ms_aObjectInfo[id].m_fMass,\n\t\t\t&ms_aObjectInfo[id].m_fTurnMass,\n\t\t\t&ms_aObjectInfo[id].m_fAirResistance,\n\t\t\t&ms_aObjectInfo[id].m_fElasticity,\n\t\t\t&percentSubmerged,\n\t\t\t&ms_aObjectInfo[id].m_fUprootLimit,\n\t\t\t&ms_aObjectInfo[id].m_fCollisionDamageMultiplier,\n\t\t\t&damageEffect, &responseCase, &camAvoid);\n\n\t\tms_aObjectInfo[id].m_fBuoyancy = 100.0f/percentSubmerged * GRAVITY *ms_aObjectInfo[id].m_fMass;\n\t\tms_aObjectInfo[id].m_nCollisionDamageEffect = damageEffect;\n\t\tms_aObjectInfo[id].m_nSpecialCollisionResponseCases = responseCase;\n\t\tms_aObjectInfo[id].m_bCameraToAvoidThisObject = camAvoid;\n\n\t\tmi = CModelInfo::GetModelInfo(name, nil);\n\t\tif (mi) {\n\t\t\tif (ms_aObjectInfo[0].m_fMass != ms_aObjectInfo[id].m_fMass\n\t\t\t\t|| ms_aObjectInfo[0].m_fCollisionDamageMultiplier != ms_aObjectInfo[id].m_fCollisionDamageMultiplier\n\t\t\t\t|| ms_aObjectInfo[0].m_nCollisionDamageEffect != ms_aObjectInfo[id].m_nCollisionDamageEffect\n\t\t\t\t|| ((ms_aObjectInfo[0].m_nSpecialCollisionResponseCases != ms_aObjectInfo[id].m_nSpecialCollisionResponseCases)\n\t\t\t\t\t&& (ms_aObjectInfo[2].m_nSpecialCollisionResponseCases != ms_aObjectInfo[id].m_nSpecialCollisionResponseCases))) {\n\t\t\t\tmi->SetObjectID(id++);\n\t\t\t} else if (ms_aObjectInfo[0].m_nSpecialCollisionResponseCases == ms_aObjectInfo[id].m_nSpecialCollisionResponseCases) {\n\t\t\t\tif (ms_aObjectInfo[0].m_bCameraToAvoidThisObject == ms_aObjectInfo[id].m_bCameraToAvoidThisObject)\n\t\t\t\t\tmi->SetObjectID(0);\n\t\t\t\telse\n\t\t\t\t\tmi->SetObjectID(1);\n\t\t\t} else if (ms_aObjectInfo[2].m_bCameraToAvoidThisObject == ms_aObjectInfo[id].m_bCameraToAvoidThisObject)\n\t\t\t\tmi->SetObjectID(2);\n\t\t\telse \n\t\t\t\tmi->SetObjectID(3);\n\t\t} else\n\t\t\tdebug(\"CObjectData: Cannot find object %s\\n\", name);\n\t}\n}\n\nvoid\nCObjectData::SetObjectData(int32 modelId, CObject &object)\n{\n\tCObjectInfo *objinfo;\n\n\tif(CModelInfo::GetModelInfo(modelId)->GetObjectID() == -1)\n\t\treturn;\n\n\tobjinfo = &ms_aObjectInfo[CModelInfo::GetModelInfo(modelId)->GetObjectID()];\n\n\tobject.m_fMass = objinfo->m_fMass;\n\tobject.m_fTurnMass = objinfo->m_fTurnMass;\n\tobject.m_fAirResistance = objinfo->m_fAirResistance;\n\tobject.m_fElasticity = objinfo->m_fElasticity;\n\tobject.m_fBuoyancy = objinfo->m_fBuoyancy;\n\tobject.m_fUprootLimit = objinfo->m_fUprootLimit;\n\tobject.m_fCollisionDamageMultiplier = objinfo->m_fCollisionDamageMultiplier;\n\tobject.m_nCollisionDamageEffect = objinfo->m_nCollisionDamageEffect;\n\tobject.m_nSpecialCollisionResponseCases = objinfo->m_nSpecialCollisionResponseCases;\n\tobject.m_bCameraToAvoidThisObject = objinfo->m_bCameraToAvoidThisObject;\n\tif(object.m_fMass >= 99998.0f){\n\t\tobject.bInfiniteMass = true;\n\t\tobject.m_phy_flagA08 = true;\n\t\tobject.bAffectedByGravity = false;\n\t\tobject.bExplosionProof = true;\n\t}\n}\n"
  },
  {
    "path": "src/objects/ObjectData.h",
    "content": "#pragma once\n\nclass CObject;\n\nclass CObjectInfo\n{\npublic:\n\tfloat m_fMass;\n\tfloat m_fTurnMass;\n\tfloat m_fAirResistance;\n\tfloat m_fElasticity;\n\tfloat m_fBuoyancy;\n\tfloat m_fUprootLimit;\n\tfloat m_fCollisionDamageMultiplier;\n\tuint8 m_nCollisionDamageEffect;\n\tuint8 m_nSpecialCollisionResponseCases;\n\tbool m_bCameraToAvoidThisObject;\n};\nVALIDATE_SIZE(CObjectInfo, 0x20);\n\nclass CObjectData\n{\n\tstatic CObjectInfo ms_aObjectInfo[NUMOBJECTINFO];\npublic:\n\tstatic void Initialise(const char *filename);\n\tstatic void SetObjectData(int32 modelId, CObject &object);\n};\n"
  },
  {
    "path": "src/objects/ParticleObject.cpp",
    "content": "#include \"common.h\"\n\n#include \"ParticleObject.h\"\n#include \"Timer.h\"\n#include \"General.h\"\n#include \"ParticleMgr.h\"\n#include \"Particle.h\"\n#include \"Camera.h\"\n#include \"Game.h\"\n#include \"DMAudio.h\"\n#include \"screendroplets.h\"\n\n\nCParticleObject gPObjectArray[MAX_PARTICLEOBJECTS];\n\nCParticleObject *CParticleObject::pCloseListHead;\nCParticleObject *CParticleObject::pFarListHead;\nCParticleObject *CParticleObject::pUnusedListHead;\n\nCAudioHydrant List[MAX_AUDIOHYDRANTS];\n\nCAudioHydrant *CAudioHydrant::Get(int n) { return &List[n]; }\n\nbool\nCAudioHydrant::Add(CParticleObject *particleobject)\n{\n\tfor ( int32 i = 0; i < MAX_AUDIOHYDRANTS; i++ )\n\t{\n\t\tif ( List[i].AudioEntity == AEHANDLE_NONE )\n\t\t{\n\t\t\tList[i].AudioEntity = DMAudio.CreateEntity(AUDIOTYPE_FIREHYDRANT, particleobject);\n\n\t\t\tif ( AEHANDLE_IS_FAILED(List[i].AudioEntity) )\n\t\t\t\treturn false;\n\t\t\t\n\t\t\tDMAudio.SetEntityStatus(List[i].AudioEntity, true);\n\t\t\t\n\t\t\tList[i].pParticleObject = particleobject;\n\t\t\t\n\t\t\treturn true;\n\t\t}\n\t}\n\t\n\treturn false;\n}\n\nvoid\nCAudioHydrant::Remove(CParticleObject *particleobject)\n{\n\tfor ( int32 i = 0; i < MAX_AUDIOHYDRANTS; i++ )\n\t{\n\t\tif ( List[i].pParticleObject == particleobject )\n\t\t{\n\t\t\tDMAudio.DestroyEntity(List[i].AudioEntity);\n\t\t\tList[i].AudioEntity = AEHANDLE_NONE;\n\t\t\tList[i].pParticleObject = nil;\n\t\t}\n\t}\n}\n\nCParticleObject::CParticleObject() :\n\tCPlaceable(),\n\tm_nFrameCounter(0),\n\tm_nState(POBJECTSTATE_INITIALISED),\n\tm_pNext(nil),\n\tm_pPrev(nil),\n\tm_nRemoveTimer(0)\n\t\n{\n\t;\n}\n\nCParticleObject::~CParticleObject()\n{\n\t\n}\n\nvoid\nCParticleObject::Initialise()\n{\n\tpCloseListHead = nil;\n\tpFarListHead   = nil;\n\t\n\tpUnusedListHead = &gPObjectArray[0];\n\t\n\tfor ( int32 i = 0; i < MAX_PARTICLEOBJECTS; i++ )\n\t{\n\t\tif ( i == 0 )\n\t\t\tgPObjectArray[i].m_pPrev = nil;\n\t\telse\n\t\t\tgPObjectArray[i].m_pPrev = &gPObjectArray[i - 1];\n\t\t\n\t\tif ( i == MAX_PARTICLEOBJECTS-1 )\n\t\t\tgPObjectArray[i].m_pNext = nil;\n\t\telse\n\t\t\tgPObjectArray[i].m_pNext = &gPObjectArray[i + 1];\n\t\t\n\t\tgPObjectArray[i].m_nState = POBJECTSTATE_FREE;\n\t}\n}\n\nCParticleObject *\nCParticleObject::AddObject(uint16 type, CVector const &pos, uint8 remove)\n{\n\tCRGBA color(0, 0, 0, 0);\n\tCVector target(0.0f, 0.0f, 0.0f);\n\treturn AddObject(type, pos, target, 0.0f, 0, color, remove);\n}\n\nCParticleObject *\nCParticleObject::AddObject(uint16 type, CVector const &pos, float size, uint8 remove)\n{\n\tCRGBA color(0, 0, 0, 0);\n\tCVector target(0.0f, 0.0f, 0.0f);\n\treturn AddObject(type, pos, target, size, 0, color, remove);\n}\n\nCParticleObject *\nCParticleObject::AddObject(uint16 type, CVector const &pos, CVector const &target, float size, uint8 remove)\n{\n\tCRGBA color(0, 0, 0, 0);\n\treturn AddObject(type, pos, target, size, 0, color, remove);\n}\n\nCParticleObject *\nCParticleObject::AddObject(uint16 type, CVector const &pos, CVector const &target, float size, uint32 lifeTime, RwRGBA const &color, uint8 remove)\n{\n\tCParticleObject *pobj = pUnusedListHead;\n\t\n\tif ( pobj == nil )\n\t{\n\t\tprintf(\"Error: No particle objects available!\\n\");\n\t\treturn nil;\n\t}\n\t\n\tMoveToList(&pUnusedListHead, &pCloseListHead, pobj);\n\t\n\tpobj->m_nState           = POBJECTSTATE_UPDATE_CLOSE;\n\tpobj->m_Type             = (eParticleObjectType)type;\n\t\n\tpobj->SetPosition(pos);\n\tpobj->m_vecTarget        = target;\n\t\n\tpobj->m_nNumEffectCycles = 1;\n\tpobj->m_nSkipFrames      = 1;\n\tpobj->m_nCreationChance  = 0;\n\tpobj->m_nFrameCounter    = 0;\n\t\n\tpobj->m_bRemove          = remove;\n\t\n\tpobj->m_pParticle        = nil;\n\t\n\tif ( lifeTime != 0 )\n\t\tpobj->m_nRemoveTimer = CTimer::GetTimeInMilliseconds() + lifeTime;\n\telse\n\t\tpobj->m_nRemoveTimer = 0;\n\t\n\tif ( color.alpha != 0 )\n\t\tpobj->m_Color = color;\n\telse\n\t\tpobj->m_Color.alpha  = 0;\n\t\n\tpobj->m_fSize            = size;\n\tpobj->m_fRandVal         = 0.0f;\n\t\n\tswitch ( type )\n\t{\n\t\tcase POBJECT_PAVEMENT_STEAM:\n\t\t{\n\t\t\tpobj->m_ParticleType     = PARTICLE_STEAM_NY;\n\t\t\tpobj->m_nNumEffectCycles = 1;\n\t\t\tpobj->m_nSkipFrames      = 3;\n\t\t\tpobj->m_nCreationChance  = 8;\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\tcase POBJECT_PAVEMENT_STEAM_SLOWMOTION:\n\t\t{\n\t\t\tpobj->m_ParticleType     = PARTICLE_STEAM_NY_SLOWMOTION;\n\t\t\tpobj->m_nNumEffectCycles = 1;\n\t\t\tpobj->m_nSkipFrames      = 1;\n\t\t\tpobj->m_nCreationChance  = 8;\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\tcase POBJECT_WALL_STEAM:\n\t\t{\n\t\t\tpobj->m_ParticleType     = PARTICLE_STEAM_NY;\n\t\t\tpobj->m_nNumEffectCycles = 1;\n\t\t\tpobj->m_nSkipFrames      = 3;\n\t\t\tpobj->m_nCreationChance  = 8;\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\tcase POBJECT_WALL_STEAM_SLOWMOTION:\n\t\t{\n\t\t\tpobj->m_ParticleType     = PARTICLE_STEAM_NY_SLOWMOTION;\n\t\t\tpobj->m_nNumEffectCycles = 1;\n\t\t\tpobj->m_nSkipFrames      = 1;\n\t\t\tpobj->m_nCreationChance  = 8;\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\tcase POBJECT_DARK_SMOKE:\n\t\t{\n\t\t\tpobj->m_ParticleType     = PARTICLE_STEAM_NY;\n\t\t\tpobj->m_nNumEffectCycles = 1;\n\t\t\tpobj->m_nSkipFrames      = 3;\n\t\t\tpobj->m_nCreationChance  = 8;\n\t\t\tpobj->m_Color            = CRGBA(16, 16, 16, 255);\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\tcase POBJECT_WATER_FOUNTAIN_VERT:\n\t\t{\n\t\t\tpobj->m_ParticleType     = PARTICLE_WATER_HYDRANT;\n\t\t\tpobj->m_nNumEffectCycles = 1;\n\t\t\tpobj->m_nSkipFrames      = 1;\n\t\t\tpobj->m_nCreationChance  = 0;\n\t\t\tpobj->m_vecTarget        = CVector(0.0f, 0.0f, 0.1f);\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\tcase POBJECT_WATER_FOUNTAIN_HORIZ:\n\t\t{\n\t\t\tpobj->m_ParticleType     = PARTICLE_WATER_HYDRANT;\n\t\t\tpobj->m_nNumEffectCycles = 1;\n\t\t\tpobj->m_nSkipFrames      = 1;\n\t\t\tpobj->m_nCreationChance  = 0;\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\tcase POBJECT_FIRE_HYDRANT:\n\t\t{\n\t\t\tpobj->m_ParticleType     = PARTICLE_WATER_HYDRANT;\n\t\t\tpobj->m_nNumEffectCycles = 1;\n\t\t\tpobj->m_nSkipFrames      = 1;\n\t\t\tpobj->m_nCreationChance  = 0;\n\t\t\tpobj->m_vecTarget        = CVector(0.0f, 0.0f, 0.3f);\n\t\t\tpobj->m_nRemoveTimer     = CTimer::GetTimeInMilliseconds() + 5000;\n\t\t\tCAudioHydrant::Add(pobj);\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\tcase POBJECT_CAR_WATER_SPLASH:\n\t\tcase POBJECT_PED_WATER_SPLASH:\n\t\t{\n\t\t\tpobj->m_ParticleType     = PARTICLE_CAR_SPLASH;\n\t\t\tpobj->m_nNumEffectCycles = 0;\n\t\t\tpobj->m_nSkipFrames      = 1;\n\t\t\tpobj->m_nCreationChance  = 0;\n#ifdef SCREEN_DROPLETS\n\t\t\tScreenDroplets::RegisterSplash(pobj);\n#endif\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\tcase POBJECT_SPLASHES_AROUND:\n\t\t{\n\t\t\tpobj->m_ParticleType     = PARTICLE_SPLASH;\n\t\t\tpobj->m_nNumEffectCycles = 15;\n\t\t\tpobj->m_nSkipFrames      = 2;\n\t\t\tpobj->m_nCreationChance  = 0;\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\tcase POBJECT_SMALL_FIRE:\n\t\t{\n\t\t\tpobj->m_ParticleType     = PARTICLE_FLAME;\n\t\t\tpobj->m_nNumEffectCycles = 1;\n\t\t\tpobj->m_nSkipFrames      = 2;\n\t\t\tpobj->m_nCreationChance  = 2;\n\t\t\tpobj->m_vecTarget        = CVector(0.0f, 0.0f, 0.0f);\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\tcase POBJECT_BIG_FIRE:\n\t\t{\n\t\t\tpobj->m_ParticleType     = PARTICLE_FLAME;\n\t\t\tpobj->m_nNumEffectCycles = 1;\n\t\t\tpobj->m_nSkipFrames      = 2;\n\t\t\tpobj->m_nCreationChance  = 4;\n\t\t\tpobj->m_vecTarget        = CVector(0.0f, 0.0f, 0.0f);\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\tcase POBJECT_DRY_ICE:\n\t\t{\n\t\t\tpobj->m_ParticleType     = PARTICLE_SMOKE;\n\t\t\tpobj->m_nNumEffectCycles = 1;\n\t\t\tpobj->m_nSkipFrames      = 1;\n\t\t\tpobj->m_nCreationChance  = 0;\n\t\t\tpobj->m_vecTarget        = CVector(0.0f, 0.0f, 0.0f);\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\tcase POBJECT_DRY_ICE_SLOWMOTION:\n\t\t{\n\t\t\tpobj->m_ParticleType     = PARTICLE_SMOKE_SLOWMOTION;\n\t\t\tpobj->m_nNumEffectCycles = 1;\n\t\t\tpobj->m_nSkipFrames      = 1;\n\t\t\tpobj->m_nCreationChance  = 0;\n\t\t\tpobj->m_vecTarget        = CVector(0.0f, 0.0f, 0.0f);\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\tcase POBJECT_FIRE_TRAIL:\n\t\t{\n\t\t\tpobj->m_ParticleType     = PARTICLE_EXPLOSION_MEDIUM;\n\t\t\tpobj->m_nNumEffectCycles = 1;\n\t\t\tpobj->m_nSkipFrames      = 3;\n\t\t\tpobj->m_nCreationChance  = 2;\n\t\t\tpobj->m_fRandVal         = 0.01f;\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\tcase POBJECT_SMOKE_TRAIL:\n\t\t{\n\t\t\tpobj->m_ParticleType     = PARTICLE_FIREBALL_SMOKE;\n\t\t\tpobj->m_nNumEffectCycles = 1;\n\t\t\tpobj->m_nSkipFrames      = 1;\n\t\t\tpobj->m_nCreationChance  = 2;\n\t\t\tpobj->m_fRandVal         = 0.02f;\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\tcase POBJECT_FIREBALL_AND_SMOKE:\n\t\t{\n\t\t\tpobj->m_ParticleType     = PARTICLE_FLAME;\n\t\t\tpobj->m_nNumEffectCycles = 1;\n\t\t\tpobj->m_nSkipFrames      = 1;\n\t\t\tpobj->m_nCreationChance  = 0;\n\t\t\tpobj->m_fRandVal         = 0.1f;\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\tcase POBJECT_ROCKET_TRAIL:\n\t\t{\n\t\t\tpobj->m_ParticleType     = PARTICLE_FLAME;\n\t\t\tpobj->m_nNumEffectCycles = 1;\n\t\t\tpobj->m_nSkipFrames      = 2;\n\t\t\tpobj->m_nCreationChance  = 8;\n\t\t\tpobj->m_fRandVal         = 0.1f;\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\tcase POBJECT_EXPLOSION_ONCE:\n\t\t{\n\t\t\tpobj->m_ParticleType     = PARTICLE_EXPLOSION_LARGE;\n\t\t\tpobj->m_nNumEffectCycles = 1;\n\t\t\tpobj->m_nSkipFrames      = 1;\n\t\t\tpobj->m_nCreationChance  = 0;\n\t\t\tpobj->m_nRemoveTimer     = CTimer::GetTimeInMilliseconds();\n\t\t\tbreak;\n\t\t}\n\t}\n\t\n\treturn pobj;\n}\n\nCParticleObject *\nCParticleObject::AddObject(tParticleType type, CVector const &pos, CVector const &target, float size, uint32 lifeTime, uint8 numEffectCycles, uint8 skipFrames, uint16 creationChance, uint8 remove)\n{\n\tCParticleObject *pobj = pUnusedListHead;\n\t\n\tASSERT(pobj != nil);\n\t\n\tif ( pobj == nil )\n\t{\n\t\tprintf(\"Error: No particle objects available!\\n\");\n\t\treturn nil;\n\t}\n\t\n\tMoveToList(&pUnusedListHead, &pCloseListHead, pobj);\n\t\n\tpobj->m_nState           = POBJECTSTATE_UPDATE_CLOSE;\n\tpobj->m_Type             = (eParticleObjectType)-1;\n\tpobj->m_ParticleType     = type;\n\t\n\tpobj->SetPosition(pos);\n\tpobj->m_vecTarget        = target;\n\t\n\tpobj->m_nNumEffectCycles = numEffectCycles;\n\tpobj->m_nSkipFrames      = skipFrames;\n\tpobj->m_nCreationChance  = creationChance;\n\tpobj->m_nFrameCounter    = 0;\n\t\n\tpobj->m_bRemove          = remove;\n\t\n\tif ( lifeTime != 0 )\n\t\tpobj->m_nRemoveTimer = CTimer::GetTimeInMilliseconds() + lifeTime;\n\telse\n\t\tpobj->m_nRemoveTimer = 0;\n\t\n\tpobj->m_Color.alpha  = 0;\n\t\n\tpobj->m_fSize            = size;\n\tpobj->m_fRandVal         = 0.0f;\n\n\treturn pobj;\n}\n\nvoid\nCParticleObject::RemoveObject(void)\n{\n\tswitch ( this->m_nState )\n\t{\n\t\tcase POBJECTSTATE_UPDATE_CLOSE:\n\t\t{\n\t\t\tMoveToList(&pCloseListHead, &pUnusedListHead, this);\n\t\t\tthis->m_nState = POBJECTSTATE_FREE;\n\t\t\tbreak;\n\t\t}\n\t\tcase POBJECTSTATE_UPDATE_FAR:\n\t\t{\n\t\t\tMoveToList(&pFarListHead, &pUnusedListHead, this);\n\t\t\tthis->m_nState = POBJECTSTATE_FREE;\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\nvoid\nCParticleObject::UpdateAll(void)\n{\n\t{\n\t\tCParticleObject *pobj = pCloseListHead;\n\t\tCParticleObject *nextpobj;\n\t\tif ( pobj != nil )\n\t\t{\n\t\t\tdo\n\t\t\t{\n\t\t\t\tnextpobj = pobj->m_pNext;\n\t\t\t\tpobj->UpdateClose();\n\t\t\t\tpobj = nextpobj;\n\t\t\t}\n\t\t\twhile ( nextpobj != nil );\n\t\t}\n\t}\n\n\t{\n\t\tint32 frame = CTimer::GetFrameCounter() & 31;\n\t\tint32 counter = 0;\n\t\n\t\tCParticleObject *pobj = pFarListHead;\n\t\tCParticleObject *nextpobj;\n\t\tif ( pobj != nil )\n\t\t{\n\t\t\tdo\n\t\t\t{\n\t\t\t\tnextpobj = pobj->m_pNext;\n\t\t\t\t\n\t\t\t\tif ( counter == frame )\n\t\t\t\t{\n\t\t\t\t\tpobj->UpdateFar();\n\t\t\t\t\tframe += 32;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tcounter++;\n\t\t\t\t\n\t\t\t\tpobj = nextpobj;\n\t\t\t}\n\t\t\twhile ( nextpobj != nil );\n\t\t}\n\t}\n}\n\nvoid CParticleObject::UpdateClose(void)\n{\n\tif ( !CGame::playingIntro )\n\t{\n\t\tif ( (this->GetPosition() - TheCamera.GetPosition()).MagnitudeSqr2D() > SQR(100.0f) )\n\t\t{\n\t\t\tif ( this->m_bRemove )\n\t\t\t{\n\t\t\t\tif ( this->m_Type == POBJECT_FIRE_HYDRANT )\n\t\t\t\t\tCAudioHydrant::Remove(this);\n\t\t\t\t\n\t\t\t\tMoveToList(&pCloseListHead, &pUnusedListHead, this);\n\t\t\t\tthis->m_nState = POBJECTSTATE_FREE;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tMoveToList(&pCloseListHead, &pFarListHead, this);\n\t\t\t\tthis->m_nState = POBJECTSTATE_UPDATE_FAR;\n\t\t\t}\n\t\t\t\n\t\t\treturn;\n\t\t}\n\t}\n\t\n\tif ( ++this->m_nFrameCounter >= this->m_nSkipFrames )\n    {\n\t\tthis->m_nFrameCounter = 0;\n\t\t\n\t\tint32 randVal;\n\t\tif ( this->m_nCreationChance != 0 )\n\t\t\trandVal = CGeneral::GetRandomNumber() % this->m_nCreationChance;\n\t\t\n\t\tif (   this->m_nCreationChance == 0\n\t\t\t|| randVal == 0 && this->m_nCreationChance < 0\n\t\t\t|| randVal != 0 && this->m_nCreationChance > 0)\n\t\t{\n\t\t\tswitch ( this->m_Type )\n\t\t\t{\n\t\t\t\tcase POBJECT_SMALL_FIRE:\n\t\t\t\t{\n\t\t\t\t\tCVector pos = this->GetPosition();\n\t\t\t\t\tCVector vel = this->m_vecTarget;\n\t\t\t\t\tfloat size  = this->m_fSize;\n\t\t\t\t\t\n\t\t\t\t\tCVector flamevel;\n\t\t\t\t\t\n\t\t\t\t\tflamevel.x = vel.x;\n\t\t\t\t\tflamevel.y = vel.y;\n\t\t\t\t\tflamevel.z = CGeneral::GetRandomNumberInRange(0.0125f*size, 0.1f*size);\n\t\t\t\t\t\t\n\t\t\t\t\tCParticle::AddParticle(PARTICLE_FLAME, pos, flamevel, nil, size);\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\tCVector possmoke = pos;\n\t\t\t\t\t\n\t\t\t\t\tpossmoke.x += CGeneral::GetRandomNumberInRange(0.625f*-size, size*0.625f);\n\t\t\t\t\tpossmoke.y += CGeneral::GetRandomNumberInRange(0.625f*-size, size*0.625f);\n\t\t\t\t\tpossmoke.z += CGeneral::GetRandomNumberInRange(0.625f* size, size*2.5f);\n\t\t\t\t\t\n\t\t\t\t\tCParticle::AddParticle(PARTICLE_CARFLAME_SMOKE, possmoke, vel);\n            \n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tcase POBJECT_BIG_FIRE:\n\t\t\t\t{\n\t\t\t\t\tCVector pos = this->GetPosition();\n\t\t\t\t\tCVector vel = this->m_vecTarget;\n\t\t\t\t\tfloat size  = this->m_fSize;\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\tfloat s = 0.7f*size;\n\t\t\t\t\t\n\t\t\t\t\tCVector flamevel;\n\t\t\t\t\t\n\t\t\t\t\tflamevel.x = vel.x;\n\t\t\t\t\tflamevel.y = vel.y;\n\t\t\t\t\tflamevel.z = CGeneral::GetRandomNumberInRange(0.0125f*s, 0.1f*s);\n\t\t\t\t\t\n\t\t\t\t\tfloat flamesize = 0.8f*size;\n\t\t\t\t\t\n\t\t\t\t\tCParticle::AddParticle(PARTICLE_FLAME, pos, flamevel, nil, flamesize);\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\tfor ( int32 i = 0; i < 4; i++ )\n\t\t\t\t\t{\n\t\t\t\t\t\tCVector smokepos = pos;\n\t\t\t\t\t\t\n\t\t\t\t\t\tsmokepos.x += CGeneral::GetRandomNumberInRange(0.625f*-size, 0.625f*size);\n\t\t\t\t\t\tsmokepos.y += CGeneral::GetRandomNumberInRange(0.625f*-size, 0.625f*size);\n\t\t\t\t\t\tsmokepos.z += CGeneral::GetRandomNumberInRange(0.625f* size, 3.5f  *size);\n\t\t\t\t\t\t\n\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_CARFLAME_SMOKE, smokepos, vel);\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tcase POBJECT_FIREBALL_AND_SMOKE:\n\t\t\t\t{\n\t\t\t\t\tif ( this->m_pParticle == nil )\n\t\t\t\t\t{\n\t\t\t\t\t\tCVector pos = this->GetPosition();\n\t\t\t\t\t\tCVector vel = this->m_vecTarget;\n\t\t\t\t\t\tfloat size  = this->m_fSize;\n\t\t\t\t\t\t\n\t\t\t\t\t\tCVector expvel = 1.2f*vel;\n\t\t\t\t\t\tfloat expsize  = 1.2f*size;\n\t\t\t\t\t\tthis->m_pParticle = CParticle::AddParticle(PARTICLE_EXPLOSION_MEDIUM, pos, expvel, nil, expsize);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tCVector pos = this->GetPosition(); // this->m_pParticle->m_vecPosition ?\n\t\t\t\t\t\tCVector vel = this->m_vecTarget;\n\t\t\t\t\t\tfloat size  = this->m_fSize;\n\t\t\t\t\t\t\n\t\t\t\t\t\tCVector veloffset   = 0.35f*vel;\n\t\t\t\t\t\tCVector fireballvel = vel;\n\t\t\t\t\t\t\n\t\t\t\t\t\tfor ( int32 i = 0; i < this->m_nNumEffectCycles; i++ )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tfireballvel.x += CGeneral::GetRandomNumberInRange(-veloffset.x, veloffset.x);\n\t\t\t\t\t\t\tfireballvel.y += CGeneral::GetRandomNumberInRange(-veloffset.y, veloffset.y);\n\t\t\t\t\t\t\tfireballvel.z += CGeneral::GetRandomNumberInRange(-veloffset.z, veloffset.z);\n\n\t\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_FIREBALL_SMOKE, pos, fireballvel, nil, size);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tcase POBJECT_ROCKET_TRAIL:\n\t\t\t\t{\n\t\t\t\t\tif ( this->m_pParticle == nil )\n\t\t\t\t\t{\n\t\t\t\t\t\tCVector pos = this->GetPosition();\n\t\t\t\t\t\tCVector vel = this->m_vecTarget;\n\t\t\t\t\t\tfloat size  = this->m_fSize;\n\t\t\t\t\t\t\n\t\t\t\t\t\tthis->m_pParticle = CParticle::AddParticle(PARTICLE_EXPLOSION_MEDIUM, pos, vel, nil, size);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tCVector pos = this->m_pParticle->m_vecPosition;\n\t\t\t\t\t\tCVector vel = this->m_vecTarget;\n\t\t\t\t\t\tfloat size  = this->m_fSize;\n\t\t\t\t\t\t\n\t\t\t\t\t\tfloat fireballsize  = size * 1.5f;\n\t\t\t\t\t\tCVector fireballvel = vel * -0.8f;\n\t\t\t\t\t\t\n\t\t\t\t\t\tfor ( int32 i = 0; i < this->m_nNumEffectCycles; i++ )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_FIREBALL_SMOKE, pos, fireballvel, nil, fireballsize);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tcase POBJECT_FIRE_TRAIL:\n\t\t\t\t{\n\t\t\t\t\tfor ( int32 i = 0; i < this->m_nNumEffectCycles; i++ )\n\t\t\t\t\t{\n\t\t\t\t\t\tCVector vel = this->m_vecTarget;\n\n\t\t\t\t\t\tif ( vel.x != 0.0f )\n\t\t\t\t\t\t\tvel.x += CGeneral::GetRandomNumberInRange(-this->m_fRandVal, this->m_fRandVal);\n\t\t\t\t\t\t\n\t\t\t\t\t\tif ( vel.y != 0.0f )\n\t\t\t\t\t\t\tvel.y += CGeneral::GetRandomNumberInRange(-this->m_fRandVal, this->m_fRandVal);\n\t\t\t\t\t\t\n\t\t\t\t\t\tif ( vel.z != 0.0f )\n\t\t\t\t\t\t\tvel.z += CGeneral::GetRandomNumberInRange(-this->m_fRandVal, this->m_fRandVal);\n\t\t\t\t\t\t\n\t\t\t\t\t\tCParticle::AddParticle(this->m_ParticleType, this->GetPosition(), vel, nil, this->m_fSize,\n\t\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(-6.0f, 6.0f));\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tcase POBJECT_PED_WATER_SPLASH:\n\t\t\t\t{\n\t\t\t\t\tCRGBA colorsmoke(255, 255, 255, 196);\n\t\t\t\t\t\n\t\t\t\t\tCVector pos = this->GetPosition();\n\t\t\t\t\tCVector vel = this->m_vecTarget;\n\t\t\t\t\t\n\t\t\t\t\tfor ( int32 i = 0; i < 3; i++ )\n\t\t\t\t\t{\n\t\t\t\t\t\tint32 angle = 90 * i;\n\t\t\t\t\t\tfloat fCos = CParticle::Cos(angle);\n\t\t\t\t\t\tfloat fSin = CParticle::Sin(angle);\n\t\t\t\t\t\t\n\t\t\t\t\t\tCVector splashpos;\n\t\t\t\t\t\tCVector splashvel;\n\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\tsplashpos = pos + CVector(0.75f*fCos, 0.75f*fSin, 0.0f);\n\t\t\t\t\t\tsplashvel = vel + CVector(0.05f*fCos, 0.05f*fSin, CGeneral::GetRandomNumberInRange(0.04f, 0.08f));\n\t\t\t\t\t\t\n\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_RUBBER_SMOKE, splashpos, splashvel, nil,\n\t\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(0.1f, 0.8f), colorsmoke);\n\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_CAR_SPLASH, splashpos, splashvel, nil,\n\t\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(0.1f, 0.5f), this->m_Color);\n\t\t\t\t\t\t\n\n\t\t\t\t\t\tsplashpos = pos + CVector(0.75f*fCos, 0.75f*-fSin, 0.0f);\n\t\t\t\t\t\tsplashvel = vel + CVector(0.05f*fCos, 0.05f*-fSin, CGeneral::GetRandomNumberInRange(0.04f, 0.08f));\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_RUBBER_SMOKE, splashpos, splashvel, nil,\n\t\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(0.1f, 0.8f), colorsmoke);\n\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_CAR_SPLASH, splashpos, splashvel, nil,\n\t\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(0.1f, 0.5f), this->m_Color);\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\tsplashpos = pos + CVector(0.75f*-fCos, 0.75f*fSin, 0.0f);\n\t\t\t\t\t\tsplashvel = vel + CVector(0.05f*-fCos, 0.05f*fSin, CGeneral::GetRandomNumberInRange(0.04f, 0.08f));\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_RUBBER_SMOKE, splashpos, splashvel, nil,\n\t\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(0.1f, 0.8f), colorsmoke);\n\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_CAR_SPLASH, splashpos, splashvel, nil,\n\t\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(0.1f, 0.5f), this->m_Color);\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\tsplashpos = pos + CVector(0.75f*-fCos, 0.75f*-fSin, 0.0f);\n\t\t\t\t\t\tsplashvel = vel + CVector(0.05f*-fCos, 0.05f*-fSin, CGeneral::GetRandomNumberInRange(0.04f, 0.08f));\n\t\t\t\t\t\t\n\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_RUBBER_SMOKE, splashpos, splashvel, nil,\n\t\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(0.1f, 0.8f), colorsmoke);\n\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_CAR_SPLASH, splashpos, splashvel, nil,\n\t\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(0.1f, 0.5f), this->m_Color);\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tfor ( int32 i = 0; i < 1; i++ )\n\t\t\t\t\t{\n\t\t\t\t\t\tint32 angle = 180 * (i + 1);\n\t\t\t\t\t\t\n\t\t\t\t\t\tfloat fCos = CParticle::Cos(angle);\n\t\t\t\t\t\tfloat fSin = CParticle::Sin(angle);\n\t\t\t\t\t\t\n\t\t\t\t\t\tCVector splashpos;\n\t\t\t\t\t\tCVector splashvel;\n\t\t\t\t\t\t\n\t\t\t\t\t\tsplashpos = pos + CVector(0.5f*fCos, 0.5f*fSin, 0.0f);\n\t\t\t\t\t\tsplashvel = vel;\n\t\t\t\t\t\tsplashvel.x += CGeneral::GetRandomNumberInRange(-0.25f, 0.25f) * fCos;\n\t\t\t\t\t\tsplashvel.y += CGeneral::GetRandomNumberInRange(-0.25f, 0.25f) * fSin;\n\t\t\t\t\t\tsplashvel.z += CGeneral::GetRandomNumberInRange(0.05f, 0.25f);\n\t\t\t\t\t\t\n\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_CAR_SPLASH, splashpos, splashvel, nil,\n\t\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(0.4f, 1.0f), this->m_Color);\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\tsplashpos = pos + CVector(0.5f*fCos, 0.5f*-fSin, 0.0f);\n\t\t\t\t\t\tsplashvel = vel;\n\t\t\t\t\t\tsplashvel.x += CGeneral::GetRandomNumberInRange(-0.25f, 0.25f) *  fCos;\n\t\t\t\t\t\tsplashvel.y += CGeneral::GetRandomNumberInRange(-0.25f, 0.25f) * -fSin;\n\t\t\t\t\t\tsplashvel.z += CGeneral::GetRandomNumberInRange(0.05f, 0.25f);\n\n\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_CAR_SPLASH, splashpos, splashvel, nil,\n\t\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(0.4f, 1.0f), this->m_Color);\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\tsplashpos = pos + CVector(0.5f*-fCos, 0.5f*fSin, 0.0f);\n\t\t\t\t\t\tsplashvel = vel;\n\t\t\t\t\t\tsplashvel.x += CGeneral::GetRandomNumberInRange(-0.25f, 0.25f) * -fCos;\n\t\t\t\t\t\tsplashvel.y += CGeneral::GetRandomNumberInRange(-0.25f, 0.25f) *  fSin;\n\t\t\t\t\t\tsplashvel.z += CGeneral::GetRandomNumberInRange(0.05f, 0.25f);\n\n\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_CAR_SPLASH, splashpos, splashvel, nil,\n\t\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(0.4f, 1.0f), this->m_Color);\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\tsplashpos = pos + CVector(0.5f*-fCos, 0.5f*-fSin, 0.0f);\n\t\t\t\t\t\tsplashvel = vel;\n\t\t\t\t\t\tsplashvel.x += CGeneral::GetRandomNumberInRange(-0.25f, 0.25f) * -fCos;\n\t\t\t\t\t\tsplashvel.y += CGeneral::GetRandomNumberInRange(-0.25f, 0.25f) * -fSin;\n\t\t\t\t\t\tsplashvel.z += CGeneral::GetRandomNumberInRange(0.05f, 0.25f);\n\n\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_CAR_SPLASH, splashpos, splashvel, nil,\n\t\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(0.4f, 1.0f), this->m_Color);\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tcase POBJECT_CAR_WATER_SPLASH:\n\t\t\t\t{\n\t\t\t\t\tCRGBA colorsmoke(255, 255, 255, 196);\n\t\t\t\t\t\n\t\t\t\t\tCVector pos = this->GetPosition();\n\t\t\t\t\tCVector vel = this->m_vecTarget;\n\t\t\t\t\t\n\t\t\t\t\tfloat size = CGeneral::GetRandomNumberInRange(1.0f, 2.5f);\n\t\t\t\t\t\n\t\t\t\t\tfor ( int32 i = 0; i < 3; i++ )\n\t\t\t\t\t{\n\t\t\t\t\t\tint32 angle = 90 * i;\n\t\t\t\t\t\t\n\t\t\t\t\t\tfloat fCos = CParticle::Cos(angle);\n\t\t\t\t\t\tfloat fSin = CParticle::Sin(angle);\n\t\t\t\t\t\t\n\t\t\t\t\t\tCVector splashpos;\n\t\t\t\t\t\tCVector splashvel;\n\t\t\t\t\t\t\n\t\t\t\t\t\tsplashpos = pos + CVector(2.0f*fCos, 2.0f*fSin, 0.0f);\n\t\t\t\t\t\tsplashvel = vel;\n\t\t\t\t\t\tsplashvel.x += CGeneral::GetRandomNumberInRange(-0.5f, 0.5f) * fCos;\n\t\t\t\t\t\tsplashvel.y += CGeneral::GetRandomNumberInRange(-0.5f, 0.5f) * fSin;\n\t\t\t\t\t\tsplashvel.z += CGeneral::GetRandomNumberInRange(0.01f, 0.03f);\n\t\t\t\t\t\t\n\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_RUBBER_SMOKE, splashpos, splashvel, nil, size, colorsmoke);\n\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_CAR_SPLASH, splashpos, splashvel, nil, 0.0f, this->m_Color);\n\t\t\t\t\t\t\n\n\t\t\t\t\t\tsplashpos = pos + CVector(2.0f*fCos, 2.0f*-fSin, 0.0f);\t\t\t\t\t\t\n\t\t\t\t\t\tsplashvel = vel;\n\t\t\t\t\t\tsplashvel.x += CGeneral::GetRandomNumberInRange(-0.5f, 0.5f) * fCos;\n\t\t\t\t\t\tsplashvel.y += CGeneral::GetRandomNumberInRange(-0.5f, 0.5f) * -fSin;\n\t\t\t\t\t\tsplashvel.z += CGeneral::GetRandomNumberInRange(0.01f, 0.03f);\n\t\t\t\t\t\t\n\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_RUBBER_SMOKE, splashpos, splashvel, nil, size, colorsmoke);\n\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_CAR_SPLASH, splashpos, splashvel, nil, 0.0f, this->m_Color);\n\t\t\t\t\t\t\n\t\t\t\t\t\tsplashpos = pos + CVector(2.0f*-fCos, 2.0f*fSin, 0.0f);\n\t\t\t\t\t\tsplashvel = vel;\n\t\t\t\t\t\tsplashvel.x += CGeneral::GetRandomNumberInRange(-0.5f, 0.5f) * -fCos;\n\t\t\t\t\t\tsplashvel.y += CGeneral::GetRandomNumberInRange(-0.5f, 0.5f) * fSin;\n\t\t\t\t\t\tsplashvel.z += CGeneral::GetRandomNumberInRange(0.01f, 0.03f);\n\t\t\t\t\t\t\n\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_RUBBER_SMOKE, splashpos, splashvel, nil, size, colorsmoke);\n\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_CAR_SPLASH, splashpos, splashvel, nil, 0.0f, this->m_Color);\n\t\t\t\t\t\t\n\t\t\t\t\t\tsplashpos = pos + CVector(2.0f*-fCos, 2.0f*-fSin, 0.0f);\n\t\t\t\t\t\tsplashvel = vel;\n\t\t\t\t\t\tsplashvel.x += CGeneral::GetRandomNumberInRange(-0.5f, 0.5f) * -fCos;\n\t\t\t\t\t\tsplashvel.y += CGeneral::GetRandomNumberInRange(-0.5f, 0.5f) * -fSin;\n\t\t\t\t\t\tsplashvel.z += CGeneral::GetRandomNumberInRange(0.01f, 0.03f);\n\t\t\t\t\t\t\n\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_RUBBER_SMOKE, splashpos, splashvel, nil, size, colorsmoke);\n\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_CAR_SPLASH, splashpos, splashvel, nil, 0.0f, this->m_Color);\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tfor ( int32 i = 0; i < 1; i++ )\n\t\t\t\t\t{\n\t\t\t\t\t\tint32 angle = 180 * (i + 1);\n\t\t\t\t\t\t\n\t\t\t\t\t\tfloat fCos = CParticle::Cos(angle);\n\t\t\t\t\t\tfloat fSin = CParticle::Sin(angle);\n\t\t\t\t\t\t\n\t\t\t\t\t\tCVector splashpos;\n\t\t\t\t\t\tCVector splashvel;\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\tsplashpos = pos + CVector(1.25f*fCos, 1.25f*fSin, 0.0f);\n\t\t\t\t\t\tsplashvel = vel;\n\t\t\t\t\t\tsplashvel.x += CGeneral::GetRandomNumberInRange(-0.1f, 0.1f) * fCos;\n\t\t\t\t\t\tsplashvel.y += CGeneral::GetRandomNumberInRange(-0.1f, 0.1f) * fSin;\n\t\t\t\t\t\tsplashvel.z += CGeneral::GetRandomNumberInRange(0.26f, 0.53f);\n\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_CAR_SPLASH, splashpos, splashvel, nil, 0.0f, this->m_Color);\n\t\t\t\t\t\t\n\t\t\t\t\t\tsplashpos = pos + CVector(1.25f*fCos, 1.25f*-fSin, 0.0f);\t\t\t\t\t\t\n\t\t\t\t\t\tsplashvel = vel;\n\t\t\t\t\t\tsplashvel.x += CGeneral::GetRandomNumberInRange(-0.1f, 0.1f) * fCos;\n\t\t\t\t\t\tsplashvel.y += CGeneral::GetRandomNumberInRange(-0.1f, 0.1f) * -fSin;\n\t\t\t\t\t\tsplashvel.z += CGeneral::GetRandomNumberInRange(0.26f, 0.53f);\n\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_CAR_SPLASH, splashpos, splashvel, nil, 0.0f, this->m_Color);\n\t\t\t\t\t\t\n\t\t\t\t\t\tsplashpos = pos + CVector(1.25f*-fCos, 1.25f*fSin, 0.0f);\t\t\t\t\t\t\n\t\t\t\t\t\tsplashvel = vel;\n\t\t\t\t\t\tsplashvel.x += CGeneral::GetRandomNumberInRange(-0.1f, 0.1f) * -fCos;\n\t\t\t\t\t\tsplashvel.y += CGeneral::GetRandomNumberInRange(-0.1f, 0.1f) * fSin;\n\t\t\t\t\t\tsplashvel.z += CGeneral::GetRandomNumberInRange(0.26f, 0.53f);\n\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_CAR_SPLASH, splashpos, splashvel, nil, 0.0f, this->m_Color);\n\n\t\t\t\t\t\tsplashpos = pos + CVector(1.25f*-fCos, 1.25f*-fSin, 0.0f);\t\t\t\t\t\t\n\t\t\t\t\t\tsplashvel = vel;\n\t\t\t\t\t\tsplashvel.x += CGeneral::GetRandomNumberInRange(-0.1f, 0.1f) * -fCos;\n\t\t\t\t\t\tsplashvel.y += CGeneral::GetRandomNumberInRange(-0.1f, 0.1f) * -fSin;\n\t\t\t\t\t\tsplashvel.z += CGeneral::GetRandomNumberInRange(0.26f, 0.53f);\n\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_CAR_SPLASH, splashpos, splashvel, nil, 0.0f, this->m_Color);\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tcase POBJECT_SPLASHES_AROUND:\n\t\t\t\t{\n\t\t\t\t\tCVector pos = this->GetPosition();\n\t\t\t\t\tfloat size  = this->m_fSize;\n\t\t\t\t\t\n\t\t\t\t\tfor ( int32 i = 0; i < this->m_nNumEffectCycles; i++ )\n\t\t\t\t\t{\n\t\t\t\t\t\tCVector splashpos = pos;\n\t\t\t\t\t\t\n\t\t\t\t\t\tsplashpos.x += CGeneral::GetRandomNumberInRange(-size, size);\n\t\t\t\t\t\tsplashpos.y += CGeneral::GetRandomNumberInRange(-size, size);\n\n\t\t\t\t\t\tif ( CGeneral::GetRandomNumber() & 1 )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_RAIN_SPLASH,   splashpos, CVector(0.0f, 0.0f, 0.0f),\n\t\t\t\t\t\t\t\tnil, 0.1f,  this->m_Color);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_RAIN_SPLASHUP, splashpos, CVector(0.0f, 0.0f, 0.0f),\n\t\t\t\t\t\t\t\tnil, 0.12f, this->m_Color);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tcase POBJECT_FIRE_HYDRANT:\n\t\t\t\t{\n\t\t\t\t\tCVector pos = this->GetPosition();\n\t\t\t\t\tCVector vel = this->m_vecTarget;\n\t\t\t\t\t\n\t\t\t\t\tif ( (TheCamera.GetPosition() - pos).Magnitude() > 5.0f )\n\t\t\t\t\t{\n\t\t\t\t\t\tfor ( int32 i = 0; i < 1; i++ )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tint32 angle = 180 * i;\n\t\t\t\t\t\t\n\t\t\t\t\t\t\tfloat fCos = CParticle::Cos(angle);\n\t\t\t\t\t\t\tfloat fSin = CParticle::Sin(angle);\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tCVector splashpos, splashvel;\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tsplashpos = pos + CVector(0.01f*fCos, 0.01f*fSin, 0.0f);\n\t\t\t\t\t\t\tsplashvel = vel + CVector(0.0f, 0.0f, CGeneral::GetRandomNumberInRange(0.004f, 0.008f));\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_CAR_SPLASH, splashpos, splashvel, nil,\n\t\t\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(0.005f, 0.0075f), this->m_Color, 0, 0, 1, 300);\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tsplashpos = pos + CVector(0.01f*fCos, 0.01f*-fSin, 0.0f);\n\t\t\t\t\t\t\tsplashvel = vel + CVector(0.0f, 0.0f, CGeneral::GetRandomNumberInRange(0.004f, 0.008f));\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_CAR_SPLASH, splashpos, splashvel, nil,\n\t\t\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(0.005f, 0.0075f), this->m_Color, 0, 0, 1, 300);\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tsplashpos = pos + CVector(0.01f*-fCos, 0.01f*fSin, 0.0f);\n\t\t\t\t\t\t\tsplashvel = vel + CVector(0.0f, 0.0f, CGeneral::GetRandomNumberInRange(0.004f, 0.008f));\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_CAR_SPLASH, splashpos, splashvel, nil,\n\t\t\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(0.005f, 0.0075f), this->m_Color, 0, 0, 1, 300);\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tsplashpos = pos + CVector(0.01f*-fCos, 0.01f*-fSin, 0.0f);\n\t\t\t\t\t\t\tsplashvel = vel + CVector(0.0f, 0.0f, CGeneral::GetRandomNumberInRange(0.004f, 0.008f));\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_CAR_SPLASH, splashpos, splashvel, nil,\n\t\t\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(0.005f, 0.0075f), this->m_Color, 0, 0, 1, 300);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tfor ( int32 i = 0; i < this->m_nNumEffectCycles; i++ )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tCParticle::AddParticle(this->m_ParticleType, pos, vel, nil, 0.0f, this->m_Color);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tcase POBJECT_WATER_FOUNTAIN_VERT:\n\t\t\t\t{\n\t\t\t\t\tCVector pos = this->GetPosition();\n\t\t\t\t\tCVector vel = this->m_vecTarget;\n\t\t\t\t\t\n\t\t\t\t\tfor ( int32 i = 0; i < 2; i++ )\n\t\t\t\t\t{\n\t\t\t\t\t\tint32 angle = 180 * i;\n\t\t\t\t\t\t\n\t\t\t\t\t\tfloat fCos = CParticle::Cos(angle);\n\t\t\t\t\t\tfloat fSin = CParticle::Sin(angle);\n\t\t\t\t\t\t\n\t\t\t\t\t\tCVector splashpos, splashvel;\n\t\t\t\t\t\t\n\t\t\t\t\t\tsplashpos = pos + CVector(0.015f*fCos, 0.015f*fSin, 0.0f);\n\t\t\t\t\t\tsplashvel = vel + CVector(0.015f*fCos, 0.015f*fSin, CGeneral::GetRandomNumberInRange(0.004f, 0.008f));\n\t\t\t\t\t\t\t\n\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_SPLASH, splashpos, splashvel, nil,\n\t\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(0.001f, 0.005f), this->m_Color, 0, 0, 1, 1000);\n\t\t\t\t\t\t\t\n\t\t\t\t\t\tsplashpos = pos + CVector(0.015f*fCos, 0.015f*-fSin, 0.0f);\n\t\t\t\t\t\tsplashvel = vel + CVector(0.015f*fCos, 0.015f*-fSin, CGeneral::GetRandomNumberInRange(0.004f, 0.008f));\n\t\t\t\t\t\t\t\n\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_SPLASH, splashpos, splashvel, nil,\n\t\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(0.001f, 0.005f), this->m_Color, 0, 0, 1, 1000);\n\t\t\t\t\t\t\t\n\t\t\t\t\t\tsplashpos = pos + CVector(0.015f*-fCos, 0.015f*fSin, 0.0f);\n\t\t\t\t\t\tsplashvel = vel + CVector(0.015f*-fCos, 0.015f*fSin, CGeneral::GetRandomNumberInRange(0.004f, 0.008f));\n\t\t\t\t\t\t\t\n\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_SPLASH, splashpos, splashvel, nil,\n\t\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(0.001f, 0.005f), this->m_Color, 0, 0, 1, 1000);\n\t\t\t\t\t\t\t\n\t\t\t\t\t\tsplashpos = pos + CVector(0.015f*-fCos, 0.015f*-fSin, 0.0f);\n\t\t\t\t\t\tsplashvel = vel + CVector(0.015f*-fCos, 0.015f*-fSin, CGeneral::GetRandomNumberInRange(0.004f, 0.008f));\n\t\t\t\t\t\t\t\n\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_SPLASH, splashpos, splashvel, nil,\n\t\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(0.001f, 0.005f), this->m_Color, 0, 0, 1, 1000);\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tcase POBJECT_WATER_FOUNTAIN_HORIZ:\n\t\t\t\t{\n\t\t\t\t\tCVector pos = this->GetPosition();\n\t\t\t\t\tCVector vel = this->m_vecTarget;\n\t\t\t\t\t\n\t\t\t\t\tfor ( int32 i = 0; i < 3; i++ )\n\t\t\t\t\t{\n\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_CAR_SPLASH, pos, vel, nil, 0.001f, this->m_Color, 0, 0, 1, 1000);\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tdefault:\n\t\t\t\t{\n\t\t\t\t\tif ( this->m_fRandVal != 0.0f )\n\t\t\t\t\t{\n\t\t\t\t\t\tfor ( int32 i = 0; i < this->m_nNumEffectCycles; i++ )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tCVector vel = this->m_vecTarget;\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tif ( vel.x != 0.0f )\n\t\t\t\t\t\t\t\tvel.x += CGeneral::GetRandomNumberInRange(-this->m_fRandVal, this->m_fRandVal);\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tif ( vel.y != 0.0f )\n\t\t\t\t\t\t\t\tvel.y += CGeneral::GetRandomNumberInRange(-this->m_fRandVal, this->m_fRandVal);\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tif ( vel.z != 0.0f )\n\t\t\t\t\t\t\t\tvel.z += CGeneral::GetRandomNumberInRange(-this->m_fRandVal, this->m_fRandVal);\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tCParticle::AddParticle(this->m_ParticleType, this->GetPosition(), vel, nil,\n\t\t\t\t\t\t\t\tthis->m_fSize, this->m_Color);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tfor ( int32 i = 0; i < this->m_nNumEffectCycles; i++ )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tCParticle::AddParticle(this->m_ParticleType, this->GetPosition(), this->m_vecTarget, nil,\n\t\t\t\t\t\t\t\tthis->m_fSize, this->m_Color);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\t\n\tif ( this->m_nRemoveTimer != 0 && this->m_nRemoveTimer < CTimer::GetTimeInMilliseconds() )\n\t{\n\t\tMoveToList(&pCloseListHead, &pUnusedListHead, this);\n\t\tthis->m_nState = POBJECTSTATE_FREE;\n\n\t\tif ( this->m_Type == POBJECT_FIRE_HYDRANT )\n\t\t\tCAudioHydrant::Remove(this);\n\t}\n}\n\nvoid\nCParticleObject::UpdateFar(void)\n{\n\tif ( this->m_nRemoveTimer != 0 && this->m_nRemoveTimer < CTimer::GetTimeInMilliseconds() )\n\t{\n\t\tMoveToList(&pFarListHead, &pUnusedListHead, this);\n\t\tthis->m_nState = POBJECTSTATE_FREE;\n\t\t\n\t\tif ( this->m_Type == POBJECT_FIRE_HYDRANT )\n\t\t\tCAudioHydrant::Remove(this);\n\t}\n\t\n\tCVector2D dist = this->GetPosition() - TheCamera.GetPosition();\n\tif ( dist.MagnitudeSqr() < SQR(100.0f)/*10000.0f*/ )\n\t{\n\t\tMoveToList(&pFarListHead, &pCloseListHead, this);\n\t\tthis->m_nState = POBJECTSTATE_UPDATE_CLOSE;\n\t}\n}\n\nbool\nCParticleObject::SaveParticle(uint8 *buffer, uint32 *length)\n{\n\tASSERT( buffer != nil );\n\tASSERT( length != nil );\n\t\n\tint32 numObjects = 0;\n\t\n\tfor ( CParticleObject *p = pCloseListHead; p != nil; p = p->m_pNext )\n\t\t++numObjects;\n\t\n\tfor ( CParticleObject *p = pFarListHead; p != nil; p = p->m_pNext )\n\t\t++numObjects;\n\t\n\t*(int32 *)buffer = numObjects;\n\tbuffer += sizeof(int32);\n\t\n\tint32 objectsLength = sizeof(CParticleObject) * (numObjects + 1);\n\tint32 dataLength = objectsLength + sizeof(int32);\n\t\n\tfor ( CParticleObject *p = pCloseListHead; p != nil; p = p->m_pNext )\n\t{\n#if 0 // todo better\n\t\t*(CParticleObject*)buffer = *p;\n#else\n\t\tmemcpy(buffer, p, sizeof(CParticleObject));\n#endif\n\t\tbuffer += sizeof(CParticleObject);\n\t}\n\t\n\tfor ( CParticleObject *p = pFarListHead; p != nil; p = p->m_pNext )\n\t{\n#if 0 // todo better\n\t\t*(CParticleObject*)buffer = *p;\n#else\n\t\tmemcpy(buffer, p, sizeof(CParticleObject));\n#endif\n\t\tbuffer += sizeof(CParticleObject);\n\t}\n\t\n\t*length = dataLength;\n  \n\treturn true;\n}\n\nbool\nCParticleObject::LoadParticle(uint8 *buffer, uint32  length)\n{\n\tASSERT( buffer != nil );\n\t\n\tRemoveAllParticleObjects();\n\t\n\tint32 numObjects = *(int32 *)buffer;\n\tbuffer += sizeof(int32);\n\t\n\tif ( length != sizeof(CParticleObject) * (numObjects + 1) + sizeof(int32) )\n\t\treturn false;\n\t\n\tif ( numObjects == 0 )\n\t\treturn true;\n\t\n\n\tint32 i = 0;\n\twhile ( i < numObjects )\n\t{\n\t\tCParticleObject *dst = pUnusedListHead;\n\t\tCParticleObject *src = (CParticleObject *)buffer;\n\t\tbuffer += sizeof(CParticleObject);\n\t\t\n\t\tif ( dst == nil )\n\t\t\treturn false;\n\t\t\n\t\tMoveToList(&pUnusedListHead, &pCloseListHead, dst);\n\t\t\n\t\tdst->m_nState           = POBJECTSTATE_UPDATE_CLOSE;\n\t\tdst->m_Type             = src->m_Type;\n\t\tdst->m_ParticleType     = src->m_ParticleType;\n\t\tdst->SetPosition(src->GetPosition());\n\t\tdst->m_vecTarget        = src->m_vecTarget;\n\t\tdst->m_nFrameCounter    = src->m_nFrameCounter;\n\t\tdst->m_bRemove          = src->m_bRemove;\n\t\tdst->m_pParticle        = nil;\n\t\tdst->m_nRemoveTimer     = src->m_nRemoveTimer;\n\t\tdst->m_Color            = src->m_Color;\n\t\tdst->m_fSize            = src->m_fSize;\n\t\tdst->m_fRandVal         = src->m_fRandVal;\n\t\tdst->m_nNumEffectCycles = src->m_nNumEffectCycles;\n\t\tdst->m_nSkipFrames      = src->m_nSkipFrames;\n\t\tdst->m_nCreationChance  = src->m_nCreationChance;\n\t\t\n\t\ti++;\n\t}\n\t\n\treturn true;\n}\n\nvoid\nCParticleObject::RemoveAllExpireableParticleObjects(void)\n{\n\t{\n\t\tCParticleObject *pobj = pCloseListHead;\n\t\tCParticleObject *nextpobj;\n\t\tif ( pobj != nil )\n\t\t{\n\t\t\tdo\n\t\t\t{\n\t\t\t\tnextpobj = pobj->m_pNext;\n\t\t\t\tif ( pobj->m_nRemoveTimer != 0 )\n\t\t\t\t{\n\t\t\t\t\tMoveToList(&pCloseListHead, &pUnusedListHead, pobj);\n\t\t\t\t\tpobj->m_nState = POBJECTSTATE_FREE;\n\t\t\t\t}\n\t\t\t\tpobj = nextpobj;\n\t\t\t}\n\t\t\twhile ( nextpobj != nil );\n\t\t}\n\t}\n\t\n\t{\n\t\tCParticleObject *pobj = pFarListHead;\n\t\tCParticleObject *nextpobj;\n\t\tif ( pobj != nil )\n\t\t{\n\t\t\tdo\n\t\t\t{\n\t\t\t\tnextpobj = pobj->m_pNext;\n\t\t\t\tif ( pobj->m_nRemoveTimer != 0 )\n\t\t\t\t{\n\t\t\t\t\tMoveToList(&pFarListHead, &pUnusedListHead, pobj);\n\t\t\t\t\tpobj->m_nState = POBJECTSTATE_FREE;\n\t\t\t\t}\n\t\t\t\tpobj = nextpobj;\n\t\t\t}\n\t\t\twhile ( nextpobj != nil );\n\t\t}\n\t}\n}\n\nvoid\nCParticleObject::RemoveAllParticleObjects(void)\n{\n\tpUnusedListHead = &gPObjectArray[0];\n\t\n\tpCloseListHead = nil;\n\tpFarListHead   = nil;\n\t\n\tfor ( int32 i = 0; i < MAX_PARTICLEOBJECTS; i++ )\n\t{\n\t\tif ( i == 0 )\n\t\t\tgPObjectArray[i].m_pPrev = nil;\n\t\telse\n\t\t\tgPObjectArray[i].m_pPrev = &gPObjectArray[i - 1];\n\t\t\n\t\tif ( i == MAX_PARTICLEOBJECTS-1 )\n\t\t\tgPObjectArray[i].m_pNext = nil;\n\t\telse\n\t\t\tgPObjectArray[i].m_pNext = &gPObjectArray[i + 1];\n\t\t\n\t\tgPObjectArray[i].m_nState = POBJECTSTATE_FREE;\n\t}\n}\n\nvoid\nCParticleObject::MoveToList(CParticleObject **from, CParticleObject **to, CParticleObject *obj)\n{\n\tASSERT( from != nil );\n\tASSERT( to   != nil );\n\tASSERT( obj  != nil );\n\t\n\tif ( obj->m_pPrev == nil )\n\t{\n\t\t*from = obj->m_pNext;\n\t\tif ( *from )\n\t\t\t(*from)->m_pPrev = nil;\n\t}\n\telse\n\t{\n\t\tif ( obj->m_pNext == nil )\n\t\t\tobj->m_pPrev->m_pNext = nil;\n\t\telse\n\t\t{\n\t\t\tobj->m_pNext->m_pPrev = obj->m_pPrev;\n\t\t\tobj->m_pPrev->m_pNext = obj->m_pNext;\n\t\t}\n\t}\n\t\n\tobj->m_pNext = *to;\n\tobj->m_pPrev = nil;\n\t*to = obj;\n\n\tif ( obj->m_pNext )\n\t\tobj->m_pNext->m_pPrev = obj;\n}\n"
  },
  {
    "path": "src/objects/ParticleObject.h",
    "content": "#pragma once\n\n#include \"AudioManager.h\"\n#include \"ParticleType.h\"\n#include \"Placeable.h\"\n\n#define MAX_PARTICLEOBJECTS 70\n#define MAX_AUDIOHYDRANTS   8\n\nenum eParticleObjectType\n{\n\tPOBJECT_PAVEMENT_STEAM = 0,\n\tPOBJECT_PAVEMENT_STEAM_SLOWMOTION,\n\tPOBJECT_WALL_STEAM,\n\tPOBJECT_WALL_STEAM_SLOWMOTION,\n\tPOBJECT_DARK_SMOKE,\n\tPOBJECT_FIRE_HYDRANT,\n\tPOBJECT_CAR_WATER_SPLASH,\n\tPOBJECT_PED_WATER_SPLASH,\n\tPOBJECT_SPLASHES_AROUND,\n\tPOBJECT_SMALL_FIRE,\n\tPOBJECT_BIG_FIRE,\n\tPOBJECT_DRY_ICE,\n\tPOBJECT_DRY_ICE_SLOWMOTION,\n\tPOBJECT_WATER_FOUNTAIN_VERT,\n\tPOBJECT_WATER_FOUNTAIN_HORIZ,\n\tPOBJECT_FIRE_TRAIL,\n\tPOBJECT_SMOKE_TRAIL,\n\tPOBJECT_FIREBALL_AND_SMOKE,\n\tPOBJECT_ROCKET_TRAIL,\n\tPOBJECT_EXPLOSION_ONCE,\n\tPOBJECT_CATALINAS_GUNFLASH,\n\tPOBJECT_CATALINAS_SHOTGUNFLASH,\n};\n\nenum eParticleObjectState\n{\n\tPOBJECTSTATE_INITIALISED = 0,\n\tPOBJECTSTATE_UPDATE_CLOSE,\n\tPOBJECTSTATE_UPDATE_FAR,\n\tPOBJECTSTATE_FREE,\n};\n\nclass CParticle;\n\nclass CParticleObject : public CPlaceable\n{\npublic:\n\tCParticleObject    *m_pNext;\n\tCParticleObject    *m_pPrev;\n\tCParticle          *m_pParticle;\n\tuint32               m_nRemoveTimer;\n\teParticleObjectType m_Type;\n\ttParticleType       m_ParticleType;\n\tuint8               m_nNumEffectCycles;\n\tuint8               m_nSkipFrames;\n\tuint16              m_nFrameCounter;\n\tuint16              m_nState;\n\tCVector             m_vecTarget;\n\tfloat               m_fRandVal;\n\tfloat               m_fSize;\n\tCRGBA               m_Color;\n\tuint8               m_bRemove;\n\tint8                m_nCreationChance;\n\t\n\tstatic CParticleObject *pCloseListHead;\n\tstatic CParticleObject *pFarListHead;\n\tstatic CParticleObject *pUnusedListHead;\n\t\n\tCParticleObject();\n\t~CParticleObject();\n\t\n\tstatic void Initialise(void);\n\n\tstatic CParticleObject *AddObject(uint16        type, CVector const &pos,                                                                                                                     uint8 remove);\n\tstatic CParticleObject *AddObject(uint16        type, CVector const &pos,                        float size,                                                                                  uint8 remove);\n\tstatic CParticleObject *AddObject(uint16        type, CVector const &pos, CVector const &target, float size,                                                                                  uint8 remove);\t\n\tstatic CParticleObject *AddObject(uint16        type, CVector const &pos, CVector const &target, float size, uint32 lifeTime, RwRGBA const &color,                                            uint8 remove);\n\tstatic CParticleObject *AddObject(tParticleType type, CVector const &pos, CVector const &target, float size, uint32 lifeTime, uint8 numEffectCycles, uint8 skipFrames, uint16 creationChance, uint8 remove);\n\n\tvoid RemoveObject(void);\n\t\n\tstatic void UpdateAll(void);\n\tvoid UpdateClose(void);\n\tvoid UpdateFar(void);\n\t\n\tstatic bool SaveParticle(uint8 *buffer, uint32 *length);\n\tstatic bool LoadParticle(uint8 *buffer, uint32  length);\n\t\n\tstatic void RemoveAllExpireableParticleObjects(void);\n\tstatic void RemoveAllParticleObjects(void);\n\tstatic void MoveToList(CParticleObject **from, CParticleObject **to, CParticleObject *obj);\n};\n\nextern CParticleObject gPObjectArray[MAX_PARTICLEOBJECTS];\n\nclass CAudioHydrant\n{\npublic:\n\tint32 AudioEntity;\n\tCParticleObject *pParticleObject;\n\t\n\tCAudioHydrant() : \n\t\tAudioEntity(AEHANDLE_NONE),\n\t\tpParticleObject(nil)\n\t{ }\n\t\n\tstatic bool Add   (CParticleObject *particleobject);\n\tstatic void Remove(CParticleObject *particleobject);\n\n\tstatic CAudioHydrant *Get(int n);\t// for neo screen droplets\n};"
  },
  {
    "path": "src/objects/Projectile.cpp",
    "content": "#include \"common.h\"\n\n#include \"Projectile.h\"\n\nCProjectile::CProjectile(int32 model) : CObject()\n{\n\tm_fMass = 1.0f;\n\tm_fTurnMass = 1.0f;\n\tm_fAirResistance = 0.99999f;\n\tm_fElasticity = 0.75f;\n\tm_fBuoyancy = GRAVITY * m_fMass * 0.1f;\n\tbExplosionProof = true;\n\tSetModelIndex(model);\n\tObjectCreatedBy = MISSION_OBJECT;\n}\n"
  },
  {
    "path": "src/objects/Projectile.h",
    "content": "#pragma once\n\n#include \"Object.h\"\n\nclass CProjectile : public CObject\n{\npublic:\n\tCProjectile(int32);\n};\n"
  },
  {
    "path": "src/objects/Stinger.cpp",
    "content": "#include \"common.h\"\n#include \"Stinger.h\"\n#include \"CopPed.h\"\n#include \"ModelIndices.h\"\n#include \"RpAnimBlend.h\"\n#include \"World.h\"\n#include \"Automobile.h\"\n#include \"Bike.h\"\n#include \"Particle.h\"\n#include \"AnimBlendAssociation.h\"\n#include \"General.h\"\n\nuint32 NumOfStingerSegments;\n\n/* --  CStingerSegment  -- */\n\nCStingerSegment::CStingerSegment()\n{\n\tm_fMass = 1.0f;\n\tm_fTurnMass = 1.0f;\n\tm_fAirResistance = 0.99999f;\n\tm_fElasticity = 0.75f;\n\tm_fBuoyancy = GRAVITY * m_fMass * 0.1f;\n\tbExplosionProof = true;\n\tSetModelIndex(MI_PLC_STINGER);\n\tObjectCreatedBy = CONTROLLED_SUB_OBJECT;\n\tNumOfStingerSegments++;\n}\n\nCStingerSegment::~CStingerSegment()\n{\n\tNumOfStingerSegments--;\n}\n\n/* --  CStinger  -- */\n\nCStinger::CStinger()\n{\n\tbIsDeployed = false;\n}\n\nvoid\nCStinger::Init(CPed *pPed)\n{\n\tint32 i;\n\n\tpOwner = pPed;\n\tfor (i = 0; i < NUM_STINGER_SEGMENTS; i++) {\n\t\tpSpikes[i] = new CStingerSegment;\n\t\tpSpikes[i]->bUsesCollision = false;\n\t}\n\tbIsDeployed = true;\n\tm_vPos = pPed->GetPosition();\n\tm_vPos.z -= 1.0f;\n\tm_fMax_Z = Atan2(-pPed->GetForward().x, pPed->GetForward().y) + HALFPI;\n\n\tfor (i = 0; i < NUM_STINGER_SEGMENTS; i++) {\n\t\tpSpikes[i]->SetOrientation(0.0f, 0.0f, Atan2(-pPed->GetForward().x, pPed->GetForward().y));\n\t\tpSpikes[i]->SetPosition(m_vPos);\n\t}\n\n\tCVector2D fwd2d(pPed->GetForward().x, pPed->GetForward().y);\n\n\tfor (i = 0; i < ARRAY_SIZE(m_vPositions); i++)\n\t\tm_vPositions[i] = fwd2d * 1.8f * Sin(DEGTORAD(i));\n\n\tm_nSpikeState = STINGERSTATE_NONE;\n\tm_nTimeOfDeploy = CTimer::GetTimeInMilliseconds();\n}\n\nvoid\nCStinger::Remove()\n{\n\tif (!bIsDeployed) return;\n\n\tfor (int32 i = 0; i < NUM_STINGER_SEGMENTS; i++) {\n\t\tCStingerSegment *spikeSegment = pSpikes[i];\n\t\tif (spikeSegment->m_entryInfoList.first != nil)\n\t\t\tspikeSegment->bRemoveFromWorld = true;\n\t\telse\n\t\t\tdelete spikeSegment;\n\t}\n\tbIsDeployed = false;\n}\n\nvoid\nCStinger::Deploy(CPed *pPed)\n{\n\tif (NumOfStingerSegments < NUM_STINGER_SEGMENTS*2 && !pPed->bInVehicle && pPed->IsPedInControl()) {\n\t\tif (!bIsDeployed && RpAnimBlendClumpGetAssociation(pPed->GetClump(), ANIM_STD_THROW_UNDER) == nil) {\n\t\t\tInit(pPed);\n\t\t\tpPed->SetPedState(PED_DEPLOY_STINGER);\n\t\t\tCAnimManager::AddAnimation(pPed->GetClump(), ASSOCGRP_STD, ANIM_STD_THROW_UNDER);\n\t\t}\n\t}\n}\n\nvoid\nCStinger::CheckForBurstTyres()\n{\n\tCVector firstPos = pSpikes[0]->GetPosition();\n\tfirstPos.z += 0.2f;\n\tCVector lastPos = pSpikes[NUM_STINGER_SEGMENTS - 1]->GetPosition();\n\tlastPos.z += 0.2f;\n\tfloat dist = (lastPos - firstPos).Magnitude();\n\tif (dist < 0.1f) return;\n\n\tCVehicle *vehsInRange[16];\n\tint16 numObjects;\n\tCEntity entity;\n\n\tCWorld::FindObjectsInRange((lastPos + firstPos) / 2.0f,\n\t\tdist, true, &numObjects, 15, (CEntity**)vehsInRange,\n\t\tfalse, true, false, false, false);\n\n\tfor (int32 i = 0; i < numObjects; i++) {\n\t\tCAutomobile *pAutomobile = nil;\n\t\tCBike *pBike = nil;\n\n\t\tif (vehsInRange[i]->IsCar())\n\t\t\tpAutomobile = (CAutomobile*)vehsInRange[i];\n\t\telse if (vehsInRange[i]->IsBike())\n\t\t\tpBike = (CBike*)vehsInRange[i];\n\n\t\tif (pAutomobile == nil && pBike == nil) continue;\n\t\t\n\t\tfloat maxWheelDistToSpike = sq(((CVehicleModelInfo*)CModelInfo::GetModelInfo(vehsInRange[i]->GetModelIndex()))->m_wheelScale + 0.1f);\n\n\t\tfor (int wheelId = 0; wheelId < 4; wheelId++) {\n\t\t\tif ((pAutomobile != nil && pAutomobile->m_aSuspensionSpringRatioPrev[wheelId] < 1.0f) ||\n\t\t\t\t(pBike != nil && pBike->m_aSuspensionSpringRatioPrev[wheelId] < 1.0f)) {\n\t\t\t\tCVector vecWheelPos;\n\t\t\t\tif (pAutomobile != nil)\n\t\t\t\t\tvecWheelPos = pAutomobile->m_aWheelColPoints[wheelId].point;\n\t\t\t\telse if (pBike != nil)\n\t\t\t\t\tvecWheelPos = pBike->m_aWheelColPoints[wheelId].point;\n\n\t\t\t\tfor (int32 spike = 0; spike < NUM_STINGER_SEGMENTS; spike++) {\n\t\t\t\t\tif ((pSpikes[spike]->GetPosition() - vecWheelPos).Magnitude() < maxWheelDistToSpike) {\n\t\t\t\t\t\tif (pBike) {\n\t\t\t\t\t\t\tif (wheelId < 2)\n\t\t\t\t\t\t\t\tvehsInRange[i]->BurstTyre(CAR_PIECE_WHEEL_LF, true);\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\tvehsInRange[i]->BurstTyre(CAR_PIECE_WHEEL_LR, true);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tswitch (wheelId) {\n\t\t\t\t\t\t\tcase 0: vehsInRange[i]->BurstTyre(CAR_PIECE_WHEEL_LF, true); break;\n\t\t\t\t\t\t\tcase 1: vehsInRange[i]->BurstTyre(CAR_PIECE_WHEEL_LR, true); break;\n\t\t\t\t\t\t\tcase 2: vehsInRange[i]->BurstTyre(CAR_PIECE_WHEEL_RF, true); break;\n\t\t\t\t\t\t\tcase 3: vehsInRange[i]->BurstTyre(CAR_PIECE_WHEEL_RR, true); break;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tvecWheelPos.z += 0.15f;\n\t\t\t\t\t\tfor (int j = 0; j < 4; j++)\n\t\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_BULLETHIT_SMOKE, vecWheelPos, vehsInRange[i]->GetRight() * 0.1f);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nCStinger::Process()\n{\n\tswitch (m_nSpikeState)\n\t{\n\tcase STINGERSTATE_NONE:\n\t\tif (pOwner != nil\n\t\t\t&& !pOwner->bInVehicle\n\t\t\t&& pOwner->GetPedState() == PED_DEPLOY_STINGER\n\t\t\t&& RpAnimBlendClumpGetAssociation(pOwner->GetClump(), ANIM_STD_THROW_UNDER)->currentTime > 0.39f)\n\t\t{\n\t\t\tm_nSpikeState = STINGERSTATE_DEPLOYING;\n\t\t\tfor (int i = 0; i < NUM_STINGER_SEGMENTS; i++)\n\t\t\t\tCWorld::Add(pSpikes[i]);\n\t\t\tpOwner->SetIdle();\n\t\t}\n\t\tbreak;\n\tcase STINGERSTATE_DEPLOYED:\n\t\tif (pOwner != nil && pOwner->m_nPedType == PEDTYPE_COP)\n\t\t\t((CCopPed*)pOwner)->m_bThrowsSpikeTrap = false;\n\t\tbreak;\n\tcase STINGERSTATE_UNDEPLOYING:\n\t\tif (CTimer::GetTimeInMilliseconds() > m_nTimeOfDeploy + 2500)\n\t\t\tm_nSpikeState = STINGERSTATE_REMOVE;\n\t\t// no break\n\tcase STINGERSTATE_DEPLOYING:\n\t\tif (m_nSpikeState == STINGERSTATE_DEPLOYING && CTimer::GetTimeInMilliseconds() > m_nTimeOfDeploy + 2500)\n\t\t\tm_nSpikeState = STINGERSTATE_DEPLOYED;\n\t\telse {\n\t\t\tfloat progress = (CTimer::GetTimeInMilliseconds() - m_nTimeOfDeploy) / 2500.0f;\n\t\t\tif (m_nSpikeState != STINGERSTATE_DEPLOYING)\n\t\t\t\tprogress = 1.0f - progress;\n\n\t\t\tfloat degangle = progress * ARRAY_SIZE(m_vPositions);\n\t\t\tfloat angle1 = m_fMax_Z + DEGTORAD(degangle);\n\t\t\tfloat angle2 = m_fMax_Z - DEGTORAD(degangle);\n\t\t\tint pos = clamp(degangle, 0, ARRAY_SIZE(m_vPositions)-1);\n\n\t\t\tCVector2D pos2d = m_vPositions[pos];\n\t\t\tCVector pos3d = m_vPos;\n\t\t\tCColPoint colPoint;\n\t\t\tCEntity *pEntity;\n\t\t\tif (CWorld::ProcessVerticalLine(CVector(pos3d.x, pos3d.y, pos3d.z - 10.0f), pos3d.z, colPoint, pEntity, true, false, false, false, true, false, nil))\n\t\t\t\tpos3d.z = colPoint.point.z + 0.15f;\n\n\t\t\tangle1 = CGeneral::LimitRadianAngle(angle1);\n\t\t\tangle2 = CGeneral::LimitRadianAngle(angle2);\n\n\t\t\tfor (int spike = 0; spike < NUM_STINGER_SEGMENTS; spike++) {\n\t\t\t\tif (CWorld::TestSphereAgainstWorld(pos3d + CVector(pos2d.x, pos2d.y, 0.6f), 0.3f, nil, true, false, false, true, false, false))\n\t\t\t\t\tpos2d = CVector2D(0.0f, 0.0f);\n\n\t\t\t\tif (spike % 2 == 0) {\n\t\t\t\t\tpSpikes[spike]->SetOrientation(0.0f, 0.0f, angle1);\n\t\t\t\t\tpos3d.x += pos2d.x;\n\t\t\t\t\tpos3d.y += pos2d.y;\n\t\t\t\t} else {\n\t\t\t\t\tpSpikes[spike]->SetOrientation(0.0f, 0.0f, angle2);\n\t\t\t\t}\n\t\t\t\tpSpikes[spike]->SetPosition(pos3d);\n\t\t\t}\n\t\t}\n\t\tbreak;\n\tcase STINGERSTATE_REMOVE:\n\t\tRemove();\n\t\tbreak;\n\t}\n\tCheckForBurstTyres();\n}"
  },
  {
    "path": "src/objects/Stinger.h",
    "content": "#pragma once\n\n#include \"Object.h\"\n\nclass CStingerSegment : public CObject\n{\npublic:\n\tCStingerSegment();\n\t~CStingerSegment();\n};\n\n#define NUM_STINGER_SEGMENTS (12)\n\nenum {\n\tSTINGERSTATE_NONE = 0,\n\tSTINGERSTATE_DEPLOYING,\n\tSTINGERSTATE_DEPLOYED,\n\tSTINGERSTATE_UNDEPLOYING,\n\tSTINGERSTATE_REMOVE,\n};\n\nclass CStinger\n{\npublic:\n\tbool bIsDeployed;\n\tuint32 m_nTimeOfDeploy;\n\tCVector m_vPos;\n\tfloat m_fMax_Z;\n\tfloat m_fMin_Z;\n\tCVector2D m_vPositions[60];\n\tCStingerSegment *pSpikes[NUM_STINGER_SEGMENTS];\n\tclass CPed *pOwner;\n\tuint8 m_nSpikeState;\n\tCStinger();\n\tvoid Init(CPed *pPed);\n\tvoid Remove();\n\tvoid Deploy(CPed *pPed);\n\tvoid CheckForBurstTyres();\n\tvoid Process();\n};"
  },
  {
    "path": "src/peds/CivilianPed.cpp",
    "content": "#include \"common.h\"\n\n#include \"CivilianPed.h\"\n#include \"Phones.h\"\n#include \"General.h\"\n#include \"PlayerPed.h\"\n#include \"Wanted.h\"\n#include \"DMAudio.h\"\n#include \"World.h\"\n#include \"Vehicle.h\"\n#include \"SurfaceTable.h\"\n#include \"Weather.h\"\n#include \"PedAttractor.h\"\n#include \"Object.h\"\n#include \"CarCtrl.h\"\n\n#ifndef _WIN32\n#include <float.h>\n#endif\n\nCCivilianPed::CCivilianPed(ePedType pedtype, uint32 mi) : CPed(pedtype)\n{\n\tSetModelIndex(mi);\n\tfor (int i = 0; i < ARRAY_SIZE(m_nearPeds); i++) {\n\t\tm_nearPeds[i] = nil;\n\t}\n\tm_bLookForVacantCars = false;\n\tif (pedtype == PEDTYPE_CRIMINAL)\n\t\tm_bLookForVacantCars = true;\n\n\tm_nLookForVacantCarsCounter = 0;\n\tm_bJustStoleACar = false;\n\tm_bStealCarEvenIfThereIsSomeoneInIt = false;\n\tfor (int i = 0; i < ARRAY_SIZE(m_nStealWishList); i++) {\n#ifdef FIX_BUGS\n\t\tuint32 randomCarModel = CGeneral::GetRandomNumberInRange(MI_LANDSTAL, MI_LAST_VEHICLE);\n#else\n\t\tuint32 randomCarModel = CGeneral::GetRandomNumberInRange(MI_LANDSTAL, MI_LANDSTAL + VEHICLEMODELSIZE);\n#endif\n\t\tif (CModelInfo::IsCarModel(randomCarModel) || CModelInfo::IsBikeModel(randomCarModel))\n\t\t\tm_nStealWishList[i] = randomCarModel;\n\t\telse\n\t\t\tm_nStealWishList[i] = MI_CHEETAH;\n\t}\n\tm_nAttractorCycleState = 0;\n\tm_bAttractorUnk = (CGeneral::GetRandomNumberInRange(0.0f, 1.0f) < 1.25f);\n}\n\nvoid\nCCivilianPed::CivilianAI(void)\n{\n\tif (CTimer::GetTimeInMilliseconds() <= m_fleeTimer || m_objective != OBJECTIVE_NONE && !bRespondsToThreats\n\t\t|| !IsPedInControl())  {\n\n\t\tif (m_objective == OBJECTIVE_GUARD_SPOT)\n\t\t\treturn;\n\n\t\tif (m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT || m_objective == OBJECTIVE_KILL_CHAR_ANY_MEANS) {\n\t\t\tif (m_pedInObjective && m_pedInObjective->IsPlayer())\n\t\t\t\treturn;\n\t\t}\n\t\tif (CTimer::GetTimeInMilliseconds() <= m_lookTimer)\n\t\t\treturn;\n\n\t\tScanForDelayedResponseThreats();\n\t\tif (!m_threatFlags || CTimer::GetTimeInMilliseconds() <= m_threatCheckTimer)\n\t\t\treturn;\n\t\tCheckThreatValidity();\n\t\tuint32 closestThreatFlag = m_threatFlags;\n\t\tm_threatFlags = 0;\n\t\tm_threatCheckTimer = 0;\n\t\tif (closestThreatFlag == PED_FLAG_EXPLOSION) {\n\t\t\tfloat angleToFace = CGeneral::GetRadianAngleBetweenPoints(\n\t\t\t\tm_eventOrThreat.x,  m_eventOrThreat.y,\n\t\t\t\tGetPosition().x, GetPosition().y);\n\t\t\tSetLookFlag(angleToFace, true);\n\t\t\tSetLookTimer(500);\n\n\t\t} else if (closestThreatFlag == PED_FLAG_GUN) {\n\t\t\tSetLookFlag(m_threatEntity, true);\n\t\t\tSetLookTimer(500);\n\t\t}\n\t\treturn;\n\t}\n\tScanForDelayedResponseThreats();\n\tif (!m_threatFlags || CTimer::GetTimeInMilliseconds() <= m_threatCheckTimer)\n\t\treturn;\n\tCheckThreatValidity();\n\tuint32 closestThreatFlag = m_threatFlags;\n\tm_threatFlags = 0;\n\tm_threatCheckTimer = 0;\n\tif (closestThreatFlag == PED_FLAG_GUN) {\n\t\tif (!m_threatEntity || !m_threatEntity->IsPed())\n\t\t\treturn;\n\n\t\tCPed *threatPed = (CPed*)m_threatEntity;\n\t\tfloat threatDistSqr = (m_threatEntity->GetPosition() - GetPosition()).MagnitudeSqr2D();\n\t\tif (CharCreatedBy == MISSION_CHAR && bCrouchWhenScared) {\n\t\t\tSetDuck(10000, true);\n\t\t\tSetLookFlag(m_threatEntity, false);\n\t\t\tSetLookTimer(500);\n\t\t\treturn;\n\t\t}\n\t\tif (m_pedStats->m_fear <= m_pedStats->m_lawfulness) {\n\t\t\tif (m_pedStats->m_temper <= m_pedStats->m_fear) {\n\t\t\t\tif (!threatPed->IsPlayer() || !RunToReportCrime(CRIME_POSSESSION_GUN)) {\n\t\t\t\t\tif (threatDistSqr < sq(30.0f)) {\n\t\t\t\t\t\tbMakeFleeScream = true;\n\t\t\t\t\t\tSetFindPathAndFlee(m_threatEntity, 10000);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tSetFindPathAndFlee(m_threatEntity->GetPosition(), 5000, true);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if (m_objective != OBJECTIVE_NONE || GetWeapon()->IsTypeMelee()) {\n\t\t\t\tSetFindPathAndFlee(m_threatEntity, 5000);\n\t\t\t\tif (threatDistSqr < sq(20.0f)) {\n\t\t\t\t\tSetMoveState(PEDMOVE_RUN);\n\t\t\t\t\tbMakeFleeScream = true;\n\t\t\t\t} else {\n\t\t\t\t\tSetMoveState(PEDMOVE_WALK);\n\t\t\t\t}\n\t\t\t} else if (threatPed->IsPlayer() && IsGangMember() && bCanAttackPlayerWithCops) {\n\t\t\t\tSetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, m_threatEntity);\n\n\t\t\t} else if (threatPed->IsPlayer() && FindPlayerPed()->m_pWanted->m_CurrentCops != 0)  {\n\t\t\t\tSetFindPathAndFlee(m_threatEntity, 5000);\n\t\t\t\tif (threatDistSqr < sq(30.0f)) {\n\t\t\t\t\tSetMoveState(PEDMOVE_RUN);\n\t\t\t\t} else {\n\t\t\t\t\tSetMoveState(PEDMOVE_WALK);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tSetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, m_threatEntity);\n\t\t\t}\n\t\t} else {\n\t\t\tif (threatDistSqr < sq(30.0f)) {\n\t\t\t\tbMakeFleeScream = true;\n\t\t\t\tSetFindPathAndFlee(m_threatEntity, 10000);\n\t\t\t\tSetMoveState(PEDMOVE_SPRINT);\n\t\t\t} else {\n\t\t\t\tbMakeFleeScream = false;\n\t\t\t\tSetFindPathAndFlee(m_threatEntity, 5000);\n\t\t\t\tSetMoveState(PEDMOVE_RUN);\n\t\t\t}\n\t\t}\n\t\tSetLookFlag(m_threatEntity, false);\n\t\tSetLookTimer(500);\n\t} else if (closestThreatFlag == PED_FLAG_DEADPEDS) {\n\t\tfloat eventDistSqr = (m_pEventEntity->GetPosition() - GetPosition()).MagnitudeSqr2D();\n\t\tif (CharCreatedBy == MISSION_CHAR && bCrouchWhenScared && eventDistSqr < sq(5.0f)) {\n\t\t\tSetDuck(10000, true);\n\n\t\t} else if (((CPed*)m_pEventEntity)->bIsDrowning || IsGangMember() && m_nPedType == ((CPed*)m_pEventEntity)->m_nPedType) {\n\t\t\tif (eventDistSqr < sq(5.0f)) {\n\t\t\t\tSetFindPathAndFlee(m_pEventEntity, 2000);\n\t\t\t\tSetMoveState(PEDMOVE_RUN);\n\t\t\t}\n\t\t} else if (IsGangMember() || eventDistSqr > sq(5.0f)) {\n\t\t\tbool investigateDeadPed = true;\n\t\t\tCEntity *killerOfDeadPed = ((CPed*)m_pEventEntity)->m_threatEntity;\n\t\t\tif (killerOfDeadPed && killerOfDeadPed->IsPed()) {\n\t\t\t\tCVector killerPos = killerOfDeadPed->GetPosition();\n\t\t\t\tCVector deadPedPos = m_pEventEntity->GetPosition();\n\t\t\t\tif (CVector2D(killerPos - deadPedPos).MagnitudeSqr() < sq(10.0f))\n\t\t\t\t\tinvestigateDeadPed = false;\n\t\t\t}\n\n\t\t\tif (investigateDeadPed)\n\t\t\t\tSetInvestigateEvent(EVENT_DEAD_PED, CVector2D(m_pEventEntity->GetPosition()), 1.0f, 20000, 0.0f);\n\n\t\t} else {\n\t\t\tSetFindPathAndFlee(m_pEventEntity, 5000);\n\t\t\tSetMoveState(PEDMOVE_RUN);\n\t\t}\n\t} else if (closestThreatFlag == PED_FLAG_EXPLOSION) {\n\t\tCVector2D eventDistVec = m_eventOrThreat - GetPosition();\n\t\tfloat eventDistSqr = eventDistVec.MagnitudeSqr();\n\t\tif (CharCreatedBy == MISSION_CHAR && bCrouchWhenScared && eventDistSqr < sq(20.0f)) {\n\t\t\tSetDuck(10000, true);\n\n\t\t} else if (eventDistSqr < sq(20.0f)) {\n\t\t\tbMakeFleeScream = true;\n\t\t\tSetFlee(m_eventOrThreat, 2000);\n\t\t\tfloat angleToFace = CGeneral::GetRadianAngleBetweenPoints(\n\t\t\t\tm_eventOrThreat.x, m_eventOrThreat.y,\n\t\t\t\tGetPosition().x, GetPosition().y);\n\t\t\tSetLookFlag(angleToFace, true);\n\t\t\tSetLookTimer(500);\n\t\t} else if (eventDistSqr < sq(40.0f)) {\n\t\t\tif (bGonnaInvestigateEvent) {\n\t\t\t\tif (CharCreatedBy != MISSION_CHAR && !IsGangMember())\n\t\t\t\t\tSetInvestigateEvent(EVENT_EXPLOSION, m_eventOrThreat, 6.0f, 30000, 0.0f);\n\n\t\t\t} else {\n\t\t\t\tfloat eventHeading = CGeneral::GetRadianAngleBetweenPoints(eventDistVec.x, eventDistVec.y, 0.0f, 0.0f);\n\t\t\t\teventHeading = CGeneral::LimitRadianAngle(eventHeading);\n\t\t\t\tif (eventHeading < 0.0f)\n\t\t\t\t\teventHeading = eventHeading + TWOPI;\n\n\t\t\t\tSetWanderPath(eventHeading / 8.0f);\n\t\t\t}\n\t\t}\n\t} else {\n\t\tif (m_threatEntity && m_threatEntity->IsPed()) {\n\t\t\tCPed *threatPed = (CPed*)m_threatEntity;\n\t\t\tif (m_pedStats->m_fear <= 100 - threatPed->m_pedStats->m_temper && threatPed->m_nPedType != PEDTYPE_COP) {\n\t\t\t\tif (threatPed->GetWeapon()->IsTypeMelee() || !GetWeapon()->IsTypeMelee()) {\n\t\t\t\t\tif (threatPed->IsPlayer() && IsGangMember() && bCanAttackPlayerWithCops) {\n\t\t\t\t\t\tSetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, m_threatEntity);\n\n\t\t\t\t\t} else if (threatPed->IsPlayer() && FindPlayerPed()->m_pWanted->m_CurrentCops != 0) {\n\t\t\t\t\t\tif (m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT || m_objective == OBJECTIVE_KILL_CHAR_ANY_MEANS) {\n\t\t\t\t\t\t\tSetFindPathAndFlee(m_threatEntity, 10000);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tSetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, m_threatEntity);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tSetFindPathAndFlee(m_threatEntity, 10000, true);\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nCCivilianPed::ProcessControl(void)\n{\n\tif (CharCreatedBy == UNK_CHAR)\n\t\treturn;\n\n\tCPed::ProcessControl();\n\n\tif (bWasPostponed)\n\t\treturn;\n\n\tif (DyingOrDead())\n\t\treturn;\n\n\tGetWeapon()->Update(m_audioEntityId, nil);\n\tswitch (m_nPedState) {\n\t\tcase PED_WANDER_RANGE:\n\t\tcase PED_WANDER_PATH:\n\t\t\tif (IsVisible())\n\t\t\t\tScanForInterestingStuff();\n\t\t\tbreak;\n\t\tcase PED_SEEK_ENTITY:\n\t\t\tif (!m_pSeekTarget) {\n\t\t\t\tRestorePreviousState();\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tm_vecSeekPos = m_pSeekTarget->GetPosition();\n\n\t\t\t// fall through\n\t\tcase PED_SEEK_POS:\n\t\t\tif (Seek()) {\n\t\t\t\tif ((m_objective == OBJECTIVE_GOTO_AREA_ON_FOOT || m_objective == OBJECTIVE_RUN_TO_AREA || m_objective == OBJECTIVE_SPRINT_TO_AREA ||\n\t\t\t\t\tIsUseAttractorObjective(m_objective)) && m_pNextPathNode) {\n\t\t\t\t\tm_pNextPathNode = nil;\n\n\t\t\t\t} else if (bRunningToPhone) {\n\t\t\t\t\tif (gPhoneInfo.m_aPhones[m_phoneId].m_nState != PHONE_STATE_FREE) {\n\t\t\t\t\t\tRestorePreviousState();\n\t\t\t\t\t\tm_phoneId = -1;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tgPhoneInfo.m_aPhones[m_phoneId].m_nState = PHONE_STATE_REPORTING_CRIME;\n\t\t\t\t\t\tSetPedState(PED_FACE_PHONE);\n\t\t\t\t\t}\n\t\t\t\t} else if (m_objective != OBJECTIVE_KILL_CHAR_ANY_MEANS && m_objective != OBJECTIVE_KILL_CHAR_ON_FOOT) {\n\t\t\t\t\tif (m_pedInObjective && m_objective == OBJECTIVE_FOLLOW_CHAR_IN_FORMATION) {\n\t\t\t\t\t\tif (m_moved.Magnitude() == 0.0f) {\n\t\t\t\t\t\t\tif (m_pedInObjective->m_nMoveState == PEDMOVE_STILL)\n\t\t\t\t\t\t\t\tm_fRotationDest = m_pedInObjective->m_fRotationCur;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (m_objective == OBJECTIVE_GOTO_CHAR_ON_FOOT\n\t\t\t\t\t\t&& m_pedInObjective && m_pedInObjective->m_nMoveState != PEDMOVE_STILL) {\n\t\t\t\t\t\tSetMoveState(m_pedInObjective->m_nMoveState);\n\t\t\t\t\t} else if (m_objective == OBJECTIVE_GOTO_AREA_ON_FOOT || m_objective == OBJECTIVE_RUN_TO_AREA || m_objective == OBJECTIVE_SPRINT_TO_AREA ||\n\t\t\t\t\t\tIsUseAttractorObjective(m_objective)) {\n\t\t\t\t\t\tSetIdle();\n\t\t\t\t\t} else {\n\t\t\t\t\t\tRestorePreviousState();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\tcase PED_FACE_PHONE:\n\t\t\tif (FacePhone())\n\t\t\t\tSetPedState(PED_MAKE_CALL);\n\t\t\tbreak;\n\t\tcase PED_MAKE_CALL:\n\t\t\tif (MakePhonecall())\n\t\t\t\tSetWanderPath(CGeneral::GetRandomNumber() & 7);\n\t\t\tbreak;\n\t\tcase PED_MUG:\n\t\t\tMug();\n\t\t\tbreak;\n\t\tcase PED_SOLICIT:\n\t\t\tSolicit();\n\t\t\tbreak;\n\t\tcase PED_UNKNOWN:\n\t\t{\n\t\t\tint pedsInSameState = 0;\n\t\t\tIdle();\n\t\t\tfor (int i = 0; i < m_numNearPeds; ++i) {\n\t\t\t\tCPed *nearPed = m_nearPeds[i];\n\t\t\t\tif (nearPed->m_nPedType == m_nPedType && nearPed->m_nPedState == PED_UNKNOWN) {\n\t\t\t\t\t++pedsInSameState;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (pedsInSameState < 5) {\n\t\t\t\tfor (int j = 0; j < m_numNearPeds; ++j) {\n\t\t\t\t\tCPed *nearPed = m_nearPeds[j];\n\t\t\t\t\tif (nearPed->m_nPedType == m_nPedType && nearPed->m_nPedState == PED_WANDER_PATH) {\n\t\t\t\t\t\tnearPed->SetPedState(PED_UNKNOWN);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tcase PED_DRIVING:\n\t\t\tif (m_nPedType != PEDTYPE_PROSTITUTE)\n\t\t\t\tbreak;\n\n\t\t\tif (CWorld::Players[CWorld::PlayerInFocus].m_pHooker != this)\n\t\t\t\tbreak;\n\n\t\t\tif (CTimer::GetTimeInMilliseconds() > CWorld::Players[CWorld::PlayerInFocus].m_nNextSexFrequencyUpdateTime) {\n\t\t\t\tif (m_nPedState == PED_DRIVING\n\t\t\t\t\t&& m_pMyVehicle->pDriver && m_pMyVehicle->pDriver->IsPlayer() && m_pMyVehicle->pDriver->m_nPedState == PED_DRIVING) {\n\t\t\t\t\tCColPoint foundCol;\n\t\t\t\t\tCEntity* foundEnt;\n\n\t\t\t\t\tCWorld::ProcessVerticalLine(m_pMyVehicle->GetPosition(), -100.0f,\n\t\t\t\t\t\tfoundCol, foundEnt, true, false, false, false, false, false, nil);\n\n\t\t\t\t\tif (m_pMyVehicle->m_vecMoveSpeed.MagnitudeSqr() < sq(0.01f)\n\t\t\t\t\t\t&& foundCol.surfaceB != SURFACE_DEFAULT && foundCol.surfaceB != SURFACE_TARMAC && foundCol.surfaceB != SURFACE_PAVEMENT) {\n\n\t\t\t\t\t\tif (m_pMyVehicle->CarHasRoof()) {\n\t\t\t\t\t\t\tm_pMyVehicle->ApplyTurnForce(0.0f, 0.0f, CGeneral::GetRandomNumberInRange(-0.8f, -1.2f) * m_fMass,\n\t\t\t\t\t\t\t\tGetPosition().x - m_pMyVehicle->GetPosition().x, GetPosition().y - m_pMyVehicle->GetPosition().y, 0.0f);\n\n\t\t\t\t\t\t\tDMAudio.PlayOneShot(m_pMyVehicle->m_audioEntityId, SOUND_CAR_JERK, 0.0f);\n\t\t\t\t\t\t\tm_pMyVehicle->pDriver->Say(SOUND_PED_PLAYER_BEFORESEX);\n\t\t\t\t\t\t\tSay(SOUND_PED_PLAYER_BEFORESEX);\n\n\t\t\t\t\t\t\tint playerSexFrequency = CWorld::Players[CWorld::PlayerInFocus].m_nSexFrequency;\n\t\t\t\t\t\t\tif (CWorld::Players[CWorld::PlayerInFocus].m_nMoney >= 10 && playerSexFrequency > 250) {\n\t\t\t\t\t\t\t\t\tCWorld::Players[CWorld::PlayerInFocus].m_nNextSexFrequencyUpdateTime = CTimer::GetTimeInMilliseconds() + playerSexFrequency;\n\t\t\t\t\t\t\t\t\tif (playerSexFrequency >= 350) {\n\t\t\t\t\t\t\t\t\t\tCWorld::Players[CWorld::PlayerInFocus].m_nSexFrequency = Max(250, playerSexFrequency - 30);\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tCWorld::Players[CWorld::PlayerInFocus].m_nSexFrequency = Max(250, playerSexFrequency - 10);\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\tm_pMyVehicle->pDriver->m_fHealth = Min(CWorld::Players[0].m_nMaxHealth + 25.0f, 1.0f + m_pMyVehicle->pDriver->m_fHealth);\n\t\t\t\t\t\t\t\t\tif (CWorld::Players[CWorld::PlayerInFocus].m_nSexFrequency == 250)\n\t\t\t\t\t\t\t\t\t\tCWorld::Players[CWorld::PlayerInFocus].m_nNextSexFrequencyUpdateTime = CTimer::GetTimeInMilliseconds() + 3000;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tbWanderPathAfterExitingCar = true;\n\t\t\t\t\t\t\t\tCWorld::Players[CWorld::PlayerInFocus].m_pHooker = nil;\n\t\t\t\t\t\t\t\tClearLeader();\n\t\t\t\t\t\t\t\tSetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle);\n\t\t\t\t\t\t\t\tm_pMyVehicle->pDriver->Say(SOUND_PED_PLAYER_AFTERSEX);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tbWanderPathAfterExitingCar = true;\n\t\t\t\t\t\t\tCWorld::Players[CWorld::PlayerInFocus].m_pHooker = nil;\n\t\t\t\t\t\t\tm_pMyVehicle->pDriver->m_fHealth = CWorld::Players[0].m_nMaxHealth + 25.0f;\n\t\t\t\t\t\t\tClearLeader();\n\t\t\t\t\t\t\tSetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle);\n\t\t\t\t\t\t\tm_pMyVehicle->pDriver->Say(SOUND_PED_PLAYER_AFTERSEX);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tCWorld::Players[CWorld::PlayerInFocus].m_nNextSexFrequencyUpdateTime = CTimer::GetTimeInMilliseconds() + 3000;\n\t\t\t\t\t\tint playerSexFrequency = CWorld::Players[CWorld::PlayerInFocus].m_nSexFrequency;\n\t\t\t\t\t\tif (playerSexFrequency >= 1000 || playerSexFrequency <= 250)\n\t\t\t\t\t\t\tCWorld::Players[CWorld::PlayerInFocus].m_nSexFrequency = 1200;\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tCWorld::Players[CWorld::PlayerInFocus].m_nSexFrequency = 250;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tbWanderPathAfterExitingCar = true;\n\t\t\t\t\tCWorld::Players[CWorld::PlayerInFocus].m_pHooker = nil;\n\t\t\t\t\tClearLeader();\n\t\t\t\t\tSetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (CTimer::GetTimeInMilliseconds() > CWorld::Players[CWorld::PlayerInFocus].m_nNextSexMoneyUpdateTime) {\n\t\t\t\tint playerMoney = CWorld::Players[CWorld::PlayerInFocus].m_nMoney;\n\t\t\t\tif (playerMoney <= 1) {\n\t\t\t\t\tCWorld::Players[CWorld::PlayerInFocus].m_nSexFrequency = 250;\n\t\t\t\t} else {\n\t\t\t\t\tCWorld::Players[CWorld::PlayerInFocus].m_nMoney = Max(0, playerMoney - 1);\n\t\t\t\t}\n\t\t\t\tCWorld::Players[CWorld::PlayerInFocus].m_nNextSexMoneyUpdateTime = CTimer::GetTimeInMilliseconds() + 1000;\n\t\t\t}\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\tif (IsPedInControl())\n\t\tCivilianAI();\n\n\tif (CharCreatedBy == RANDOM_CHAR) {\n\t\tEnterVacantNearbyCars();\n\t\tUseNearbyAttractors();\n\t}\n\n\tif (CTimer::GetTimeInMilliseconds() > m_timerUnused) {\n\t\tm_stateUnused = 0;\n\t\tm_timerUnused = 0;\n\t}\n\n\tif (m_moved.Magnitude() > 0.0f)\n\t\tAvoid();\n}\n\nbool\nCPed::RunToReportCrime(eCrimeType crimeToReport)\n{\n\t// They changed true into false to make this function unusable. So running to phone actually starts but first frame after that cancels it.\n\tif (m_nPedState == PED_SEEK_POS)\n\t\treturn false;\n\n\tCVector pos = GetPosition();\n\tint phoneId = gPhoneInfo.FindNearestFreePhone(&pos);\n\n\tif (phoneId == -1)\n\t\treturn false;\n\n\tCPhone* phone = &gPhoneInfo.m_aPhones[phoneId];\n\tif (phone->m_nState != PHONE_STATE_FREE)\n\t\treturn false;\n\n\tbRunningToPhone = true;\n\tSetSeek(phone->m_vecPos, 0.3f);\n\tSetMoveState(PEDMOVE_RUN);\n\tm_phoneId = phoneId;\n\tm_crimeToReportOnPhone = crimeToReport;\n\treturn true;\n}\n\nconst int32 gFrequencyOfAttractorAttempt = 11;\nconst float gDistanceToSeekAttractors = 50.0f;\nconst float gMaxDistanceToAttract = 10.0f;\n\n/* Probably this was inlined */\nvoid CCivilianPed::FindNearbyAttractorsSectorList(CPtrList& list, float& minDistance, C2dEffect*& pClosestAttractor, CEntity*& pAttractorEntity)\n{\n\tfor (CPtrNode* pNode = list.first; pNode != nil; pNode = pNode->next) {\n\t\tCEntity* pEntity = (CEntity*)pNode->item;\n\t\tif (pEntity->IsObject() && (!pEntity->GetIsStatic() || ((CObject*)pEntity)->bHasBeenDamaged))\n\t\t\tcontinue;\n\t\tCBaseModelInfo* pModelInfo = CModelInfo::GetModelInfo(pEntity->GetModelIndex());\n\t\tfor (int i = 0; i < pModelInfo->GetNum2dEffects(); i++) {\n\t\t\tC2dEffect* pEffect = pModelInfo->Get2dEffect(i);\n\t\t\tif (pEffect->type != EFFECT_PED_ATTRACTOR)\n\t\t\t\tcontinue;\n\t\t\tif (!IsAttractedTo(pEffect->pedattr.type))\n\t\t\t\tcontinue;\n\t\t\tCVector pos;\n\t\t\tCPedAttractorManager::ComputeEffectPos(pEffect, pEntity->GetMatrix(), pos);\n\t\t\tif ((pos - GetPosition()).MagnitudeSqr() < minDistance) {\n\t\t\t\tCPedAttractorManager* pManager = GetPedAttractorManager();\n\t\t\t\tif (pManager->HasEmptySlot(pEffect) && pManager->IsApproachable(pEffect, pEntity->GetMatrix(), 0, this)) {\n\t\t\t\t\tpClosestAttractor = pEffect;\n\t\t\t\t\tpAttractorEntity = pEntity;\n\t\t\t\t\tminDistance = (pos - GetPosition()).MagnitudeSqr();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid CCivilianPed::UseNearbyAttractors()\n{\n\tif (CWeather::Rain < 0.2f && !m_bAttractorUnk)\n\t\treturn;\n\tif (HasAttractor())\n\t\treturn;\n\tif (m_nAttractorCycleState != gFrequencyOfAttractorAttempt) {\n\t\tm_nAttractorCycleState++;\n\t\treturn;\n\t}\n\tm_nAttractorCycleState = 0;\n\tif (!IsPedInControl())\n\t\treturn;\n\tif (m_nPedState == PED_FLEE_ENTITY)\n\t\treturn;\n\n\tfloat left = GetPosition().x - gDistanceToSeekAttractors;\n\tfloat right = GetPosition().x + gDistanceToSeekAttractors;\n\tfloat top = GetPosition().y - gDistanceToSeekAttractors;\n\tfloat bottom = GetPosition().y + gDistanceToSeekAttractors;\n\tint xstart = Max(0, CWorld::GetSectorIndexX(left));\n\tint xend = Min(NUMSECTORS_X - 1, CWorld::GetSectorIndexX(right));\n\tint ystart = Max(0, CWorld::GetSectorIndexY(top));\n\tint yend = Min(NUMSECTORS_Y - 1, CWorld::GetSectorIndexY(bottom));\n\tassert(xstart <= xend);\n\tassert(ystart <= yend);\n\n\tfloat minDistance = SQR(gMaxDistanceToAttract);\n\tC2dEffect* pClosestAttractor = nil;\n\tCEntity* pAttractorEntity = nil;\n\n\tfor (int y = ystart; y <= yend; y++) {\n\t\tfor (int x = xstart; x <= xend; x++) {\n\t\t\tCSector* s = CWorld::GetSector(x, y);\n\t\t\tFindNearbyAttractorsSectorList(s->m_lists[ENTITYLIST_BUILDINGS], minDistance, pClosestAttractor, pAttractorEntity);\n\t\t\tFindNearbyAttractorsSectorList(s->m_lists[ENTITYLIST_OBJECTS], minDistance, pClosestAttractor, pAttractorEntity);\n\t\t}\n\t}\n\tif (pClosestAttractor)\n\t\tGetPedAttractorManager()->RegisterPedWithAttractor(this, pClosestAttractor, pAttractorEntity->GetMatrix());\n}\n\nbool CCivilianPed::IsAttractedTo(int8 type)\n{\n\tswitch (type) {\n\tcase ATTRACTOR_ATM: return true;\n\tcase ATTRACTOR_SEAT: return true;\n\tcase ATTRACTOR_STOP: return true;\n\tcase ATTRACTOR_PIZZA: return true;\n\tcase ATTRACTOR_SHELTER: return CWeather::Rain >= 0.2f;\n\tcase ATTRACTOR_ICECREAM: return false;\n\t}\n\treturn false;\n}\n\nvoid\nCCivilianPed::EnterVacantNearbyCars(void)\n{\n\tif (!m_bLookForVacantCars)\n\t\treturn;\n\n\tif (m_bJustStoleACar && bInVehicle && m_carInObjective == m_pMyVehicle) {\n\t\tm_bJustStoleACar = false;\n\t\tm_pMyVehicle->SetStatus(STATUS_PHYSICS);\n\t\tm_pMyVehicle->AutoPilot.m_nCarMission = MISSION_CRUISE;\n\t\tm_pMyVehicle->AutoPilot.m_nCruiseSpeed = 10;\n\t\tm_pMyVehicle->bEngineOn = true;\n\n\t} else if (!bHasAlreadyStoleACar) {\n\t\tif (m_nLookForVacantCarsCounter == 8) {\n\t\t\tm_nLookForVacantCarsCounter = 0;\n\t\t\tif (IsPedInControl() && m_objective == OBJECTIVE_NONE) {\n\n\t\t\t\tCVehicle *foundCar = nil;\n\t\t\t\tfloat closestDist = FLT_MAX;\n\t\t\t\tint minX = CWorld::GetSectorIndexX(GetPosition().x - 10.0f);\n\t\t\t\tif (minX < 0) minX = 0;\n\t\t\t\tint minY = CWorld::GetSectorIndexY(GetPosition().y - 10.0f);\n\t\t\t\tif (minY < 0) minY = 0;\n\t\t\t\tint maxX = CWorld::GetSectorIndexX(GetPosition().x + 10.0f);\n\t\t\t\tif (maxX > NUMSECTORS_X - 1) maxX = NUMSECTORS_X - 1;\n\t\t\t\tint maxY = CWorld::GetSectorIndexY(GetPosition().y + 10.0f);\n\t\t\t\tif (maxY > NUMSECTORS_Y - 1) maxY = NUMSECTORS_Y - 1;\n\n\t\t\t\tfor (int curY = minY; curY <= maxY; curY++) {\n\t\t\t\t\tfor (int curX = minX; curX <= maxX; curX++) {\n\t\t\t\t\t\tCSector* sector = CWorld::GetSector(curX, curY);\n\t\t\t\t\t\tfor (CPtrNode* node = sector->m_lists[ENTITYLIST_VEHICLES].first; node; node = node->next) {\n\t\t\t\t\t\t\tCVehicle* veh = (CVehicle*)node->item;\n\t\t\t\t\t\t\tif (veh && veh->IsCar()) {\n\n\t\t\t\t\t\t\t\t// Looks like PARKED_VEHICLE condition isn't there in Mobile.\n\t\t\t\t\t\t\t\tif (veh->VehicleCreatedBy == RANDOM_VEHICLE || veh->VehicleCreatedBy == PARKED_VEHICLE) {\n\t\t\t\t\t\t\t\t\tif (IsOnStealWishList(veh->GetModelIndex()) && !veh->IsLawEnforcementVehicle()\n\t\t\t\t\t\t\t\t\t\t&& (m_bStealCarEvenIfThereIsSomeoneInIt || !veh->pDriver && !veh->m_nNumPassengers)\n\t\t\t\t\t\t\t\t\t\t&& !veh->m_nNumGettingIn && !veh->m_nGettingInFlags && !veh->m_nGettingOutFlags\n\t\t\t\t\t\t\t\t\t\t&& !veh->m_pCarFire && veh->m_fHealth > 800.0f\n\t\t\t\t\t\t\t\t\t\t&& !veh->IsUpsideDown() && !veh->IsOnItsSide() && veh->CanPedEnterCar()) {\n\t\t\t\t\t\t\t\t\t\tfloat dist = (GetPosition() - veh->GetPosition()).MagnitudeSqr();\n\t\t\t\t\t\t\t\t\t\tif (dist < sq(10.0f) && dist < closestDist && veh->IsClearToDriveAway()) {\n\t\t\t\t\t\t\t\t\t\t\tfoundCar = veh;\n\t\t\t\t\t\t\t\t\t\t\tclosestDist = dist;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (foundCar) {\n\t\t\t\t\tm_bJustStoleACar = true;\n\t\t\t\t\tbHasAlreadyStoleACar = true;\n\t\t\t\t\tCCarCtrl::JoinCarWithRoadSystem(foundCar);\n\t\t\t\t\tSetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, foundCar);\n\t\t\t\t\tSetObjectiveTimer(10000);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\t++m_nLookForVacantCarsCounter;\n\t\t}\n\t}\n}\n\nbool\nCCivilianPed::IsOnStealWishList(int32 model)\n{\n\tfor (int i = 0; i < ARRAY_SIZE(m_nStealWishList); i++) {\n\t\tif (model == m_nStealWishList[i]) {\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}"
  },
  {
    "path": "src/peds/CivilianPed.h",
    "content": "#pragma once\n\n#include \"Ped.h\"\n\nclass CCivilianPed : public CPed\n{\n\tbool m_bLookForVacantCars;\n\tuint32 m_nLookForVacantCarsCounter;\n\tbool m_bStealCarEvenIfThereIsSomeoneInIt; // unused\n\tbool m_bJustStoleACar;\n\tuint32 m_nStealWishList[16];\n\tbool m_bAttractorUnk;\n\tint32 m_nAttractorCycleState;\npublic:\n\tCCivilianPed(ePedType, uint32);\n\t~CCivilianPed(void) { }\n\n\tvoid CivilianAI(void);\n\tvoid ProcessControl(void);\n\tvoid UseNearbyAttractors(void);\n\tvoid FindNearbyAttractorsSectorList(CPtrList&, float&, C2dEffect*&, CEntity*&);\n\tbool IsAttractedTo(int8);\n\tvoid EnterVacantNearbyCars(void);\n\tbool IsOnStealWishList(int32);\n};\n//VALIDATE_SIZE(CCivilianPed, 0x53C);\n"
  },
  {
    "path": "src/peds/CopPed.cpp",
    "content": "#include \"common.h\"\n\n#include \"World.h\"\n#include \"PlayerPed.h\"\n#include \"CopPed.h\"\n#include \"Wanted.h\"\n#include \"DMAudio.h\"\n#include \"ModelIndices.h\"\n#include \"Vehicle.h\"\n#include \"RpAnimBlend.h\"\n#include \"AnimBlendAssociation.h\"\n#include \"General.h\"\n#include \"ZoneCull.h\"\n#include \"PathFind.h\"\n#include \"RoadBlocks.h\"\n#include \"CarCtrl.h\"\n#include \"Renderer.h\"\n#include \"Camera.h\"\n#include \"PedPlacement.h\"\n#include \"Ropes.h\"\n#include \"Stinger.h\"\n\nCCopPed::CCopPed(eCopType copType, int32 modifier) : CPed(PEDTYPE_COP)\n{\n\tm_nCopType = copType;\n\tswitch (copType) {\n\tcase COP_STREET:\n\t\tSetModelIndex(MI_COP);\n\t\tGiveWeapon(WEAPONTYPE_NIGHTSTICK, 1000, true);\n\t\tGiveDelayedWeapon(WEAPONTYPE_COLT45, 1000);\n\t\tm_currentWeapon = WEAPONTYPE_UNARMED;\n\t\tm_fArmour = 0.0f;\n\t\tm_wepSkills = 208; /* TODO: what is this? seems unused */\n\t\tm_wepAccuracy = 60;\n\t\tbreak;\n\tcase COP_FBI:\n\t\tSetModelIndex(MI_FBI);\n\t\tGiveDelayedWeapon(WEAPONTYPE_MP5, 1000);\n\t\tSetCurrentWeapon(WEAPONTYPE_MP5);\n\t\tm_fArmour = 100.0f;\n\t\tm_wepSkills = 176; /* TODO: what is this? seems unused */\n\t\tm_wepAccuracy = 76;\n\t\tbreak;\n\tcase COP_SWAT:\n\tcase COP_HELI_SWAT:\n\t\tSetModelIndex(MI_SWAT);\n\t\tGiveDelayedWeapon(WEAPONTYPE_UZI, 1000);\n\t\tSetCurrentWeapon(WEAPONTYPE_UZI);\n\t\tm_fArmour = 50.0f;\n\t\tm_wepSkills = 32; /* TODO: what is this? seems unused */\n\t\tm_wepAccuracy = 68;\n\t\tbreak;\n\tcase COP_ARMY:\n\t\tSetModelIndex(MI_ARMY);\n\t\tGiveDelayedWeapon(WEAPONTYPE_MP5, 1000);\n\t\tSetCurrentWeapon(WEAPONTYPE_MP5);\n\t\tm_fArmour = 100.0f;\n\t\tm_wepSkills = 32; /* TODO: what is this? seems unused */\n\t\tm_wepAccuracy = 84;\n\t\tbreak;\n\tcase COP_MIAMIVICE:\n\t\tswitch (modifier) {\n\t\tcase 0: SetModelIndex(MI_VICE1); break;\n\t\tcase 1: SetModelIndex(MI_VICE2); break;\n\t\tcase 2: SetModelIndex(MI_VICE3); break;\n\t\tcase 3: SetModelIndex(MI_VICE4); break;\n\t\tcase 4: SetModelIndex(MI_VICE5); break;\n\t\tcase 5: SetModelIndex(MI_VICE6); break;\n\t\tcase 6: SetModelIndex(MI_VICE7); break;\n\t\tcase 7: SetModelIndex(MI_VICE8); break;\n\t\tdefault: assert(0); break;\n\t\t}\n\t\tGiveDelayedWeapon(WEAPONTYPE_UZI, 1000);\n\t\tSetCurrentWeapon(WEAPONTYPE_UZI);\n\t\tm_fArmour = 100.0f;\n\t\tm_wepSkills = 176;\n\t\tm_wepAccuracy = 76;\n\t\tbreak;\n\t}\n\tm_bIsInPursuit = false;\n\tfield_5FE = 1;\n\tm_bIsDisabledCop = false;\n\tm_attackTimer = 0;\n\tm_bBeatingSuspect = false;\n\tm_bStopAndShootDisabledZone = false;\n\tm_bDragsPlayerFromCar = false;\n\tm_bZoneDisabled = false;\n\tfield_628 = -1;\n\tm_nRoadblockVeh = nil;\n\tm_bThrowsSpikeTrap = false;\n\tm_pRopeEntity = nil;\n\tm_fAbseilPos = 0.0f;\n\tm_nHassleTimer = 0;\n\tfield_61C = 0;\n\tfield_624 = 0;\n\tm_pStinger = new CStinger;\n\tSetWeaponLockOnTarget(nil);\n}\n\nCCopPed::~CCopPed()\n{\n\tClearPursuit();\n\tm_pStinger->Remove();\n\tdelete m_pStinger;\n}\n\n// Parameter should always be CPlayerPed, but it seems they considered making civilians arrestable at some point\nvoid\nCCopPed::SetArrestPlayer(CPed *player)\n{\n\tif (!IsPedInControl() || !player)\n\t\treturn;\n\n\tplayer->Say(SOUND_PED_PLAYER_REACTTOCOP);\n\tSay(SOUND_PED_ARREST_COP);\n\n\tif (player->EnteringCar()) {\n\t\tif (CTimer::GetTimeInMilliseconds() > m_nPedStateTimer)\n\t\t\treturn;\n\n\t\t// why?\n\t\tplayer->bGonnaKillTheCarJacker = true;\n\n\t\t// Genius\n\t\tFindPlayerPed()->m_bCanBeDamaged = false;\n\t\t((CPlayerPed*)player)->m_pArrestingCop = this;\n\t\tthis->RegisterReference((CEntity**) &((CPlayerPed*)player)->m_pArrestingCop);\n\n\t} else if (player->m_nPedState != PED_DIE && player->m_nPedState != PED_DEAD && player->m_nPedState != PED_ARRESTED) {\n\t\tplayer->m_nLastPedState = player->m_nPedState;\n\t\tplayer->SetPedState(PED_ARRESTED);\n\n\t\tFindPlayerPed()->m_bCanBeDamaged = false;\n\t\t((CPlayerPed*)player)->m_pArrestingCop = this;\n\t\tthis->RegisterReference((CEntity**) &((CPlayerPed*)player)->m_pArrestingCop);\n\t}\n\n\tSetPedState(PED_ARREST_PLAYER);\n\tSetObjective(OBJECTIVE_NONE);\n\tm_prevObjective = OBJECTIVE_NONE;\n\tbIsPointingGunAt = false;\n\tm_pSeekTarget = player;\n\tm_pSeekTarget->RegisterReference((CEntity**) &m_pSeekTarget);\n\tSetCurrentWeapon(WEAPONTYPE_COLT45);\n\tif (player->InVehicle()) {\n\t\tplayer->m_pMyVehicle->m_nNumGettingIn = 0;\n\t\tplayer->m_pMyVehicle->m_nGettingInFlags = 0;\n\t\tplayer->m_pMyVehicle->bIsHandbrakeOn = true;\n\t\tplayer->m_pMyVehicle->SetStatus(STATUS_PLAYER_DISABLED);\n\t}\n\tif (GetWeapon()->m_eWeaponType == WEAPONTYPE_UNARMED || GetWeapon()->m_eWeaponType == WEAPONTYPE_BRASSKNUCKLE)\n\t\tSetCurrentWeapon(WEAPONTYPE_COLT45);\n}\n\nvoid\nCCopPed::ClearPursuit(void)\n{\n\tCPlayerPed *player = FindPlayerPed();\n\tif (!player)\n\t\treturn;\n\n\tCWanted *wanted = player->m_pWanted;\n\tint ourCopId = 0;\n\tbool foundMyself = false;\n\tint biggestCopId = 0;\n\tif (!m_bIsInPursuit)\n\t\treturn;\n\n\tm_bIsInPursuit = false;\n\tfor (int i = 0; i < Max(wanted->m_MaxCops, wanted->m_CurrentCops); ++i)  {\n\t\tif (!foundMyself && wanted->m_pCops[i] == this) {\n\t\t\twanted->m_pCops[i] = nil;\n\t\t\t--wanted->m_CurrentCops;\n\t\t\tfoundMyself = true;\n\t\t\tourCopId = i;\n\t\t\tbiggestCopId = i;\n\t\t} else {\n\t\t\tif (wanted->m_pCops[i])\n\t\t\t\tbiggestCopId = i;\n\t\t}\n\t}\n\tif (foundMyself && biggestCopId > ourCopId) {\n\t\twanted->m_pCops[ourCopId] = wanted->m_pCops[biggestCopId];\n\t\twanted->m_pCops[biggestCopId] = nil;\n\t}\n\tm_objective = OBJECTIVE_NONE;\n\tm_prevObjective = OBJECTIVE_NONE;\n\tm_nLastPedState = PED_NONE;\n\tbIsRunning = false;\n\tbNotAllowedToDuck = false;\n\tbKindaStayInSamePlace = false;\n\tm_bStopAndShootDisabledZone = false;\n\tm_bDragsPlayerFromCar = false;\n\tm_bZoneDisabled = false;\n\tClearObjective();\n\tif (IsPedInControl()) {\n\t\tif (!m_pMyVehicle || wanted->GetWantedLevel() != 0)  {\n\t\t\tif (m_pMyVehicle && (m_pMyVehicle->GetPosition() - GetPosition()).MagnitudeSqr() < sq(5.0f)) {\n\t\t\t\tm_nLastPedState = PED_IDLE;\n\t\t\t\tSetSeek((CEntity*)m_pMyVehicle, 2.5f);\n\t\t\t} else {\n\t\t\t\tm_nLastPedState = PED_WANDER_PATH;\n\t\t\t\tSetFindPathAndFlee(FindPlayerPed()->GetPosition(), 10000, true);\n\t\t\t}\n\t\t} else {\n\t\t\tSetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, m_pMyVehicle);\n\t\t}\n\t}\n}\n\n// TODO: I don't know why they needed that parameter.\nvoid\nCCopPed::SetPursuit(bool ignoreCopLimit)\n{\n\tif (CTimer::GetTimeInMilliseconds() < field_61C)\n\t\treturn;\n\n\tCWanted *wanted = FindPlayerPed()->m_pWanted;\n\tif (m_bIsInPursuit || !IsPedInControl())\n\t\treturn;\n\n\tif (wanted->m_CurrentCops < wanted->m_MaxCops || ignoreCopLimit) {\n\t\tfor (int i = 0; i < wanted->m_MaxCops; ++i) {\n\t\t\tif (!wanted->m_pCops[i]) {\n\t\t\t\tm_bIsInPursuit = true;\n\t\t\t\t++wanted->m_CurrentCops;\n\t\t\t\twanted->m_pCops[i] = this;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (m_bIsInPursuit) {\n\t\t\tClearObjective();\n\t\t\tm_prevObjective = OBJECTIVE_NONE;\n\t\t\tSetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, FindPlayerPed());\n\t\t\tSetObjectiveTimer(0);\n\t\t\tbNotAllowedToDuck = true;\n\t\t\tbIsRunning = true;\n\t\t\tm_bStopAndShootDisabledZone = false;\n\t\t}\n\t}\n}\n\nvoid\nCCopPed::ArrestPlayer(void)\n{\n\tm_pVehicleAnim = nil;\n\tCPed *suspect = (CPed*)m_pSeekTarget;\n\tif (suspect) {\n\t\tif (suspect->CanSetPedState())\n\t\t\tsuspect->SetPedState(PED_ARRESTED);\n\n\t\tif (suspect->bInVehicle && m_pMyVehicle && suspect->m_pMyVehicle == m_pMyVehicle) {\n\n\t\t\t// BUG? I will never understand why they used LINE_UP_TO_CAR_2...\n\t\t\tLineUpPedWithCar(LINE_UP_TO_CAR_2);\n\t\t}\n\n\t\tif (suspect && (suspect->m_nPedState == PED_ARRESTED || suspect->DyingOrDead() || suspect->EnteringCar())) {\n\n\t\t\tCAnimBlendAssociation *arrestAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_ARREST);\n\t\t\tif (!arrestAssoc || arrestAssoc->blendDelta < 0.0f)\n\t\t\t\tCAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_ARREST, 4.0f);\n\n\t\t\tCVector suspMidPos;\n\t\t\tsuspect->m_pedIK.GetComponentPosition(suspMidPos, PED_MID);\n\t\t\tm_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(suspMidPos.x, suspMidPos.y,\n\t\t\t\tGetPosition().x, GetPosition().y);\n\n\t\t\tm_fRotationCur = m_fRotationDest;\n\t\t\tSetOrientation(0.0f, 0.0f, m_fRotationCur);\n\t\t} else {\n\t\t\tClearPursuit();\n\t\t}\n\t} else {\n\t\tClearPursuit();\n\t}\n}\n\nvoid\nCCopPed::ScanForCrimes(void)\n{\n\tCVehicle *playerVeh = FindPlayerVehicle();\n\n\t// Look for car alarms\n\tif (playerVeh && playerVeh->IsCar()) {\n\t\tif (playerVeh->IsAlarmOn()) {\n\t\t\tif ((playerVeh->GetPosition() - GetPosition()).MagnitudeSqr() < sq(20.0f))\n\t\t\t\tFindPlayerPed()->SetWantedLevelNoDrop(1);\n\t\t}\n\t}\n\n\t// Look for stolen cop cars\n\tif (!m_bIsInPursuit) {\n\t\tCPlayerPed *player = FindPlayerPed();\n\t\tif ((m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER || m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER)\n\t\t\t&& player->m_pWanted->GetWantedLevel() == 0) {\n\n\t\t\tif (player->m_pMyVehicle\n#ifdef FIX_BUGS\n\t\t\t\t&& m_pMyVehicle == player->m_pMyVehicle\n#endif\n\t\t\t\t&& player->m_pMyVehicle->bIsLawEnforcer)\n\t\t\t\tplayer->SetWantedLevelNoDrop(1);\n\t\t}\n\t}\n}\n\nvoid\nCCopPed::CopAI(void)\n{\n\tCWanted *wanted = FindPlayerPed()->m_pWanted;\n\tint wantedLevel = wanted->GetWantedLevel();\n\tCPhysical *playerOrHisVeh = FindPlayerVehicle() ? (CPhysical*)FindPlayerVehicle() : (CPhysical*)FindPlayerPed();\n\n\tif (wanted->m_bIgnoredByEveryone || wanted->m_bIgnoredByCops) {\n\t\tif (m_nPedState != PED_ARREST_PLAYER)\n\t\t\tClearPursuit();\n\n\t\treturn;\n\t}\n\tif (CCullZones::NoPolice() && m_bIsInPursuit && !m_bIsDisabledCop) {\n\t\tif (bHitSomethingLastFrame) {\n\t\t\tm_bZoneDisabled = true;\n\t\t\tm_bIsDisabledCop = true;\n\t\t\tbKindaStayInSamePlace = true;\n\t\t\tbIsRunning = false;\n\t\t\tbNotAllowedToDuck = false;\n\t\t\tbCrouchWhenShooting = false;\n\t\t\tSetIdle();\n\t\t\tClearObjective();\n\t\t\tClearPursuit();\n\t\t\tm_prevObjective = OBJECTIVE_NONE;\n\t\t\tm_nLastPedState = PED_NONE;\n\t\t\tSetAttackTimer(0);\n\n\t\t\t// Safe distance for disabled zone? Or to just make game easier?\n\t\t\tif (m_fDistanceToTarget > 15.0f)\n\t\t\t\tm_bStopAndShootDisabledZone = true;\n\t\t}\n\t} else if (m_bZoneDisabled && !CCullZones::NoPolice()) {\n\t\tm_bZoneDisabled = false;\n\t\tm_bIsDisabledCop = false;\n\t\tm_bStopAndShootDisabledZone = false;\n\t\tbKindaStayInSamePlace = false;\n\t\tbCrouchWhenShooting = false;\n\t\tbDuckAndCover = false;\n\t\tClearPursuit();\n\t}\n\tif (wantedLevel > 0) {\n\t\tif (!m_bIsDisabledCop) {\n\t\t\t// Turn and shoot the player's vehicle, if possible\n\t\t\tif (!m_bIsInPursuit && !GetWeapon()->IsTypeMelee() && FindPlayerVehicle() && m_fDistanceToTarget < CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->m_fRange) {\n\t\t\t\tif (FindPlayerVehicle()->m_vecMoveSpeed.Magnitude2D() > 0.1f) {\n\t\t\t\t\tCVector2D distToVeh = GetPosition() - FindPlayerVehicle()->GetPosition();\n\t\t\t\t\tdistToVeh.Normalise();\n\t\t\t\t\tCVector2D vehSpeed = FindPlayerVehicle()->m_vecMoveSpeed;\n\t\t\t\t\tvehSpeed.Normalise();\n\n\t\t\t\t\tif (DotProduct2D(distToVeh, vehSpeed) > 0.8f) {\n\t\t\t\t\t\tSetLookFlag(playerOrHisVeh, true);\n\t\t\t\t\t\tSetMoveState(PEDMOVE_STILL);\n\t\t\t\t\t\tif (TurnBody()) {\n\t\t\t\t\t\t\tSetAttack(FindPlayerVehicle());\n\t\t\t\t\t\t\tSetShootTimer(CGeneral::GetRandomNumberInRange(500.0f, 1000.0f));\n\t\t\t\t\t\t\tSetAttackTimer(CGeneral::GetRandomNumberInRange(200.0f, 300.0f));\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (m_nPedState == PED_ATTACK)\n\t\t\t\t\t\tRestorePreviousState();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!m_bIsInPursuit || wanted->m_CurrentCops > wanted->m_MaxCops) {\n\t\t\t\tCCopPed *copFarthestToTarget = nil;\n\t\t\t\tfloat copFarthestToTargetDist = m_fDistanceToTarget;\n\n\t\t\t\tint oldCopNum = wanted->m_CurrentCops;\n\t\t\t\tint maxCops = wanted->m_MaxCops;\n\t\t\t\t\n\t\t\t\tfor (int i = 0; i < Max(maxCops, oldCopNum); i++) {\n\t\t\t\t\tCCopPed *cop = wanted->m_pCops[i];\n\t\t\t\t\tif (cop && cop->m_fDistanceToTarget > copFarthestToTargetDist) {\n\t\t\t\t\t\tcopFarthestToTargetDist = cop->m_fDistanceToTarget;\n\t\t\t\t\t\tcopFarthestToTarget = wanted->m_pCops[i];\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (m_bIsInPursuit) {\n\t\t\t\t\tif (copFarthestToTarget && oldCopNum > maxCops) {\n\t\t\t\t\t\tif (copFarthestToTarget == this && m_fDistanceToTarget > 10.0f) {\n\t\t\t\t\t\t\tClearPursuit();\n\t\t\t\t\t\t} else if(copFarthestToTargetDist > 10.0f)\n\t\t\t\t\t\t\tcopFarthestToTarget->ClearPursuit();\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (oldCopNum < maxCops) {\n\t\t\t\t\t\tSetPursuit(true);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (m_fDistanceToTarget <= 10.0f || copFarthestToTarget && m_fDistanceToTarget < copFarthestToTargetDist) {\n\t\t\t\t\t\t\tif (copFarthestToTarget && copFarthestToTargetDist > 10.0f)\n\t\t\t\t\t\t\t\tcopFarthestToTarget->ClearPursuit();\n\n\t\t\t\t\t\t\tSetPursuit(true);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else\n\t\t\t\tSetPursuit(false);\n\n\t\t\tif (!m_bIsInPursuit)\n\t\t\t\treturn;\n\n\t\t\tif (wantedLevel > 1 && GetWeapon()->m_eWeaponType == WEAPONTYPE_UNARMED)\n\t\t\t\tSetCurrentWeapon(WEAPONTYPE_COLT45);\n\t\t\telse if (wantedLevel == 1 && GetWeapon()->m_eWeaponType == WEAPONTYPE_UNARMED && !FindPlayerPed()->m_pCurrentPhysSurface) {\n\t\t\t\t// i.e. if player is on top of car, cop will still use colt45.\n\t\t\t\tSetCurrentWeapon(GetWeaponSlot(WEAPONTYPE_NIGHTSTICK) >= 0 ? WEAPONTYPE_NIGHTSTICK : WEAPONTYPE_UNARMED);\n\t\t\t}\n\n\t\t\tif (m_bBeatingSuspect && GetWeapon()->m_eWeaponType == WEAPONTYPE_NIGHTSTICK)\n\t\t\t\tSay(SOUND_PED_PULLOUTWEAPON);\n\n\t\t\tif (FindPlayerVehicle()) {\n\t\t\t\tif (m_bBeatingSuspect) {\n\t\t\t\t\t--wanted->m_CopsBeatingSuspect;\n\t\t\t\t\tm_bBeatingSuspect = false;\n\t\t\t\t}\n\t\t\t\tif (m_fDistanceToTarget * FindPlayerSpeed().Magnitude() > 4.0f)\n\t\t\t\t\tClearPursuit();\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tSetCurrentWeapon(WEAPONTYPE_COLT45);\n\t\tCWeaponInfo *weaponInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);\n\t\tfloat weaponRange = weaponInfo->m_fRange;\n\t\tSetLookFlag(playerOrHisVeh, true);\n\t\tTurnBody();\n\t\tif (!bIsDucking || bCrouchWhenShooting && GetCrouchFireAnim(weaponInfo)) {\n\t\t\tif (m_attackTimer >= CTimer::GetTimeInMilliseconds()) {\n\t\t\t\tif (m_nPedState != PED_ATTACK && m_nPedState != PED_FIGHT && !m_bZoneDisabled) {\n\t\t\t\t\tCVector targetDist = playerOrHisVeh->GetPosition() - GetPosition();\n\t\t\t\t\tif (m_fDistanceToTarget > 30.0f) {\n\t\t\t\t\t\tif (bIsDucking)\n\t\t\t\t\t\t\tClearDuck();\n\n\t\t\t\t\t\t// Target is coming onto us\n\t\t\t\t\t\tif (DotProduct(playerOrHisVeh->m_vecMoveSpeed, targetDist) > 0.0f) {\n\t\t\t\t\t\t\tm_bIsDisabledCop = false;\n\t\t\t\t\t\t\tbKindaStayInSamePlace = false;\n\t\t\t\t\t\t\tbNotAllowedToDuck = false;\n\t\t\t\t\t\t\tbDuckAndCover = false;\n\t\t\t\t\t\t\tSetPursuit(false);\n\t\t\t\t\t\t\tSetObjective(OBJECTIVE_KILL_CHAR_ANY_MEANS, FindPlayerPed());\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (m_fDistanceToTarget < 5.0f\n\t\t\t\t\t\t\t&& (!FindPlayerVehicle() || FindPlayerVehicle()->m_vecMoveSpeed.MagnitudeSqr() < sq(1.f/200.f))) {\n\t\t\t\t\t\tm_bIsDisabledCop = false;\n\t\t\t\t\t\tbKindaStayInSamePlace = false;\n\t\t\t\t\t\tbNotAllowedToDuck = false;\n\t\t\t\t\t\tbDuckAndCover = false;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tfloat dotProd;\n\t\t\t\t\t\tif (m_nRoadblockVeh) {\n\t\t\t\t\t\t\tdotProd = DotProduct2D(playerOrHisVeh->GetPosition() - m_nRoadblockVeh->GetPosition(), GetPosition() - m_nRoadblockVeh->GetPosition());\n\t\t\t\t\t\t} else\n\t\t\t\t\t\t\tdotProd = -1.0f;\n\n\t\t\t\t\t\tif(dotProd < 0.0f) {\n\t\t\t\t\t\t\tif (bIsDucking)\n\t\t\t\t\t\t\t\tClearDuck();\n\t\t\t\t\t\t\tm_bIsDisabledCop = false;\n\t\t\t\t\t\t\tbKindaStayInSamePlace = false;\n\t\t\t\t\t\t\tbNotAllowedToDuck = false;\n\t\t\t\t\t\t\tbCrouchWhenShooting = false;\n\t\t\t\t\t\t\tbDuckAndCover = false;\n\t\t\t\t\t\t\tSetPursuit(false);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tbIsPointingGunAt = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (m_fDistanceToTarget < weaponRange) {\n\t\t\t\t\tCVector gunPos = weaponInfo->m_vecFireOffset;\n\t\t\t\t\tTransformToNode(gunPos, PED_HANDR);\n\n\t\t\t\t\tCColPoint foundCol;\n\t\t\t\t\tCEntity *foundEnt;\n\t\t\t\t\tif (!CWorld::ProcessLineOfSight(gunPos, playerOrHisVeh->GetPosition(), foundCol, foundEnt,\n\t\t\t\t\t\tfalse, true, false, false, true, false, false)\n\t\t\t\t\t\t|| foundEnt && foundEnt == playerOrHisVeh) {\n\n\t\t\t\t\t\tSetWeaponLockOnTarget(playerOrHisVeh);\n\t\t\t\t\t\tSetAttack(playerOrHisVeh);\n\t\t\t\t\t\tSetShootTimer(CGeneral::GetRandomNumberInRange(500, 1000));\n\t\t\t\t\t}\n\t\t\t\t\tSetAttackTimer(CGeneral::GetRandomNumberInRange(200, 300));\n\t\t\t\t}\n\t\t\t\tSetMoveState(PEDMOVE_STILL);\n\t\t\t}\n\t\t}\n\t} else {\n\t\tif (!m_bIsDisabledCop || m_bZoneDisabled) {\n\t\t\tif (m_nPedState != PED_AIM_GUN) {\n\t\t\t\tif (m_bIsInPursuit)\n\t\t\t\t\tClearPursuit();\n\n\t\t\t\tif (IsPedInControl()) {\n\t\t\t\t\t// Entering the vehicle\n\t\t\t\t\tif (m_pMyVehicle && !bInVehicle) {\n\t\t\t\t\t\tif (m_pMyVehicle->IsLawEnforcementVehicle()) {\n\t\t\t\t\t\t\tif (m_pMyVehicle->pDriver) {\n\t\t\t\t\t\t\t\tif (m_pMyVehicle->pDriver->m_nPedType == PEDTYPE_COP) {\n\t\t\t\t\t\t\t\t\tif (m_objective != OBJECTIVE_ENTER_CAR_AS_PASSENGER)\n\t\t\t\t\t\t\t\t\t\tSetObjective(OBJECTIVE_ENTER_CAR_AS_PASSENGER, m_pMyVehicle);\n\t\t\t\t\t\t\t\t} else if (m_pMyVehicle->pDriver->IsPlayer()) {\n\t\t\t\t\t\t\t\t\tFindPlayerPed()->SetWantedLevelNoDrop(1);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else if (m_objective != OBJECTIVE_ENTER_CAR_AS_DRIVER) {\n\t\t\t\t\t\t\t\tSetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, m_pMyVehicle);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tm_pMyVehicle = nil;\n\t\t\t\t\t\t\tClearObjective();\n\t\t\t\t\t\t\tSetWanderPath(CGeneral::GetRandomNumber() & 7);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (m_objective != OBJECTIVE_KILL_CHAR_ON_FOOT && m_objective != OBJECTIVE_HASSLE_CHAR && CharCreatedBy == RANDOM_CHAR) {\n\t\t\t\t\t\t\tfor (int i = 0; i < m_numNearPeds; i++) {\n\t\t\t\t\t\t\t\tCPed *nearPed = m_nearPeds[i];\n\t\t\t\t\t\t\t\tif (nearPed->CharCreatedBy == RANDOM_CHAR) {\n\t\t\t\t\t\t\t\t\tif ((nearPed->m_nPedType == PEDTYPE_CRIMINAL || nearPed->IsGangMember())\n\t\t\t\t\t\t\t\t\t\t&& nearPed->IsPedInControl()) {\n\n\t\t\t\t\t\t\t\t\t\tbool anotherCopChasesHim = false;\n\t\t\t\t\t\t\t\t\t\tif (nearPed->m_nPedState == PED_FLEE_ENTITY) {\n\t\t\t\t\t\t\t\t\t\t\tif (nearPed->m_fleeFrom && nearPed->m_fleeFrom->IsPed() &&\n\t\t\t\t\t\t\t\t\t\t\t\t((CPed*)nearPed->m_fleeFrom)->m_nPedType == PEDTYPE_COP) {\n\t\t\t\t\t\t\t\t\t\t\t\tanotherCopChasesHim = true;\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\tif (!anotherCopChasesHim) {\n\t\t\t\t\t\t\t\t\t\t\tSetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, nearPed);\n\t\t\t\t\t\t\t\t\t\t\tnearPed->SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE, this);\n\t\t\t\t\t\t\t\t\t\t\tnearPed->bBeingChasedByPolice = true;\n\t\t\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tif (nearPed->m_nPedType != PEDTYPE_COP && !nearPed->IsPlayer()\n\t\t\t\t\t\t\t\t\t\t\t&& nearPed->IsPedInControl() && m_nHassleTimer < CTimer::GetTimeInMilliseconds()) {\n\n\t\t\t\t\t\t\t\t\t\t\tif (nearPed->m_objective == OBJECTIVE_NONE && nearPed->m_nPedState == PED_WANDER_PATH\n\t\t\t\t\t\t\t\t\t\t\t\t&& !nearPed->m_pLookTarget && nearPed->m_lookTimer < CTimer::GetTimeInMilliseconds()) {\n\n\t\t\t\t\t\t\t\t\t\t\t\tif ((GetPosition() - nearPed->GetPosition()).MagnitudeSqr() < sq(5.0f)) {\n\n\t\t\t\t\t\t\t\t\t\t\t\t\tif (CWorld::GetIsLineOfSightClear(GetPosition(), nearPed->GetPosition(),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttrue, false, false, false, false, false, false)) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tSay(SOUND_PED_COP_REACTION);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tSetObjective(OBJECTIVE_HASSLE_CHAR, nearPed);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tnearPed->SetObjective(OBJECTIVE_WAIT_ON_FOOT_FOR_COP, this);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tm_nHassleTimer = CTimer::GetTimeInMilliseconds() + 100000;\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tif (m_bIsInPursuit && m_nPedState != PED_AIM_GUN)\n\t\t\t\tClearPursuit();\n\n\t\t\tm_bIsDisabledCop = false;\n\t\t\tbKindaStayInSamePlace = false;\n\t\t\tbNotAllowedToDuck = false;\n\t\t\tbCrouchWhenShooting = false;\n\t\t\tbDuckAndCover = false;\n\t\t\tif (bIsDucking)\n\t\t\t\tClearDuck();\n\t\t\tif (m_pMyVehicle)\n\t\t\t\tSetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, m_pMyVehicle);\n\t\t}\n\t}\n}\n\nvoid\nCCopPed::ProcessControl(void)\n{\n\tif (m_nCopType == COP_HELI_SWAT)\n\t\tProcessHeliSwat();\n\n\tCPed::ProcessControl();\n\n\tif (m_bThrowsSpikeTrap) {\n\t\tif (CGame::currArea != AREA_MALL)\n\t\t\tProcessStingerCop();\n\t\treturn;\n\t}\n\n\tif (m_pStinger && m_pStinger->bIsDeployed && m_pStinger->m_nSpikeState == STINGERSTATE_DEPLOYED && CGame::currArea != AREA_MALL)\n\t\tm_pStinger->Process();\n\n\tif (bWasPostponed)\n\t\treturn;\n\n\tif (m_nPedState == PED_DEAD) {\n\t\tClearPursuit();\n\t\tm_objective = OBJECTIVE_NONE;\n\t\treturn;\n\t}\n\tif (m_nPedState == PED_DIE)\n\t\treturn;\n\n\tif (m_nPedState == PED_ARREST_PLAYER) {\n\t\tArrestPlayer();\n\t\treturn;\n\t}\n\tGetWeapon()->Update(m_audioEntityId, nil);\n\tif (m_moved.Magnitude() > 0.0f)\n\t\tAvoid();\n\n\tCPhysical *playerOrHisVeh = FindPlayerVehicle() ? (CPhysical*)FindPlayerVehicle() : (CPhysical*)FindPlayerPed();\n\tCPlayerPed *player = FindPlayerPed();\n\n\tm_fDistanceToTarget = (playerOrHisVeh->GetPosition() - GetPosition()).Magnitude();\n\tif (player->m_nPedState == PED_ARRESTED || player->DyingOrDead()) {\n\t\tif (m_fDistanceToTarget < 5.0f) {\n\t\t\tSetArrestPlayer(player);\n\t\t\treturn;\n\t\t}\n\t\tif (IsPedInControl())\n\t\t\tSetIdle();\n\t}\n\n\tif (m_bIsInPursuit) {\n\t\tif (player->m_nPedState != PED_ARRESTED && !player->DyingOrDead()) {\n\t\t\tif (player->m_pWanted->m_CurrentCops == 1) {\n\t\t\t\tSay(SOUND_PED_COP_ALONE);\n\t\t\t} else {\n\t\t\t\tint numCopsNear = 0;\n\t\t\t\tfor (int i = 0; i < player->m_numNearPeds; ++i) {\n\t\t\t\t\tCPed *nearPed = player->m_nearPeds[i];\n\t\t\t\t\tif (nearPed->m_nPedType == PEDTYPE_COP && nearPed->m_nPedState != PED_DEAD)\n\t\t\t\t\t\t++numCopsNear;\n\t\t\t\t}\n\t\t\t\tif (numCopsNear <= 3) {\n\t\t\t\t\tSay(SOUND_PED_COP_LITTLECOPSAROUND);\n\t\t\t\t\tif (!player->bInVehicle) {\n\t\t\t\t\t\tCVector distToPlayer = player->GetPosition() - GetPosition();\n\t\t\t\t\t\tif (distToPlayer.MagnitudeSqr() < sq(20.0f)) {\n\t\t\t\t\t\t\tplayer->Say(SOUND_PED_PLAYER_FARFROMCOPS);\n\t\t\t\t\t\t\tif (player->m_nPedState != PED_ATTACK && player->m_nPedState != PED_AIM_GUN) {\n\t\t\t\t\t\t\t\tplayer->SetLookFlag(this, false);\n\t\t\t\t\t\t\t\tplayer->SetLookTimer(1000);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else if ((CGeneral::GetRandomNumber() % 16) == 1) {\n\t\t\t\t\tSay(SOUND_PED_COP_MANYCOPSAROUND);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (IsPedInControl()) {\n\t\tCopAI();\n\t\t/* switch (m_nCopType)\n\t\t{\n\t\t\tcase COP_FBI:\n\t\t\t\tCopAI();\n\t\t\t\tbreak;\n\t\t\tcase COP_SWAT:\n\t\t\t\tCopAI();\n\t\t\t\tbreak;\n\t\t\tcase COP_ARMY:\n\t\t\t\tCopAI();\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tCopAI();\n\t\t\t\tbreak;\n\t\t} */\n\t} else if (InVehicle()) {\n\t\tif (m_pMyVehicle->pDriver == this && m_pMyVehicle->AutoPilot.m_nCarMission == MISSION_NONE &&\n\t\t\tCanPedDriveOff() && m_pMyVehicle->VehicleCreatedBy != MISSION_VEHICLE) {\n\n\t\t\tCCarCtrl::JoinCarWithRoadSystem(m_pMyVehicle);\n\t\t\tm_pMyVehicle->AutoPilot.m_nCarMission = MISSION_CRUISE;\n\t\t\tm_pMyVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_STOP_FOR_CARS;\n\t\t\tm_pMyVehicle->AutoPilot.m_nCruiseSpeed = 17;\n\t\t}\n\t}\n\tif (IsPedInControl() || m_nPedState == PED_DRIVING)\n\t\tScanForCrimes();\n\n\t// They may have used goto to jump here in case of PED_ATTACK.\n\tif (m_nPedState == PED_IDLE || m_nPedState == PED_ATTACK) {\n\t\tif (m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT &&\n\t\t\tplayer && player->EnteringCar() && m_fDistanceToTarget < 1.3f) {\n\t\t\tSetArrestPlayer(player);\n\t\t}\n\t} else {\n\t\tif (m_nPedState == PED_SEEK_POS) {\n\t\t\tif (player->m_nPedState == PED_ARRESTED) {\n\t\t\t\tSetIdle();\n\t\t\t\tSetLookFlag(player, false);\n\t\t\t\tSetLookTimer(1000);\n\t\t\t\tRestorePreviousObjective();\n\t\t\t} else {\n\t\t\t\tif (player->m_pMyVehicle && player->m_pMyVehicle->m_nNumGettingIn != 0) {\n\t\t\t\t\tm_distanceToCountSeekDone = 1.3f;\n\t\t\t\t}\n\n\t\t\t\tif (!bDuckAndCover && Seek()) {\n\t\t\t\t\tCVehicle *playerVeh = FindPlayerVehicle();\n\t\t\t\t\tif (!playerVeh && player && player->EnteringCar()) {\n\t\t\t\t\t\tSetArrestPlayer(player);\n\t\t\t\t\t} else if (1.5f + GetPosition().z <= m_vecSeekPos.z || GetPosition().z - 0.3f >= m_vecSeekPos.z) {\n\t\t\t\t\t\tSetMoveState(PEDMOVE_STILL);\n\t\t\t\t\t} else if (playerVeh && playerVeh->CanPedEnterCar() && playerVeh->m_nNumGettingIn == 0) {\n\t\t\t\t\t\tSetCarJack(playerVeh);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (m_nPedState == PED_SEEK_ENTITY) {\n\t\t\tif (!m_pSeekTarget) {\n\t\t\t\tRestorePreviousState();\n\t\t\t} else {\n\t\t\t\tm_vecSeekPos = m_pSeekTarget->GetPosition();\n\t\t\t\tif (Seek()) {\n\t\t\t\t\tif (m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT && m_fDistanceToTarget < 2.5f && player) {\n\t\t\t\t\t\tif (player->m_nPedState == PED_ARRESTED || player->m_nPedState == PED_ENTER_CAR ||\n\t\t\t\t\t\t\t(player->m_nPedState == PED_CARJACK && m_fDistanceToTarget < 1.3f)) {\n\t\t\t\t\t\t\tSetArrestPlayer(player);\n\t\t\t\t\t\t} else\n\t\t\t\t\t\t\tRestorePreviousState();\n\t\t\t\t\t} else {\n\t\t\t\t\t\tRestorePreviousState();\n\t\t\t\t\t}\n\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (m_pPointGunAt)\n\t\tSay(SOUND_PED_COP_UNK_129);\n\n\tif (m_bStopAndShootDisabledZone) {\n\t\tbool dontShoot = false;\n\t\tif (GetIsOnScreen()) {\n\t\t\tif (((CTimer::GetFrameCounter() + m_randomSeed) & 0x1F) == 17) {\n\t\t\t\tCEntity* foundBuilding = nil;\n\t\t\t\tCColPoint foundCol;\n\t\t\t\tCVector lookPos = GetPosition() + CVector(0.0f, 0.0f, 0.7f);\n\t\t\t\tCVector camPos = TheCamera.GetGameCamPosition();\n\t\t\t\tCWorld::ProcessLineOfSight(camPos, lookPos, foundCol, foundBuilding,\n\t\t\t\t\ttrue, false, false, false, false, false, false);\n\n\t\t\t\t// He's at least 15.0 far, in disabled zone, collided into somewhere (that's why m_bStopAndShootDisabledZone set),\n\t\t\t\t// and now has building on front of him. He's stupid, we don't need him.\n\t\t\t\tif (foundBuilding) {\n\t\t\t\t\tFlagToDestroyWhenNextProcessed();\n\t\t\t\t\tdontShoot = true;\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tFlagToDestroyWhenNextProcessed();\n\t\t\tdontShoot = true;\n\t\t}\n\n\t\tif (!dontShoot) {\n\t\t\tbStopAndShoot = true;\n\t\t\tbKindaStayInSamePlace = true;\n\t\t\tbIsPointingGunAt = true;\n\t\t\tSetAttack(m_pedInObjective);\n\t\t}\n\t}\n\n\tif (field_624 >= 2 && m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT) {\n\t\tCVector centre = GetPosition() + CVector(0.f, 0.f, 0.65f);\n\t\tif (CWorld::TestSphereAgainstWorld(centre, 0.35f, this, true, false, false, false, false, false)) {\n\t\t\tfield_624 = 0;\n\t\t\tm_bStopAndShootDisabledZone = true;\n\t\t\tClearPursuit();\n\t\t\tSetObjective(OBJECTIVE_NONE);\n\t\t\tSetWanderPath(CGeneral::GetRandomNumberInRange(0,8));\n\t\t\tfield_61C = CTimer::GetTimeInMilliseconds() + 30000;\n\t\t} else {\n\t\t\tfield_624 = 0;\n\t\t\tif (GetWeapon()->IsTypeMelee()) {\n\t\t\t\t// TODO(Miami): enum\n\t\t\t\tfor (int i = 3; i < 7; i++) {\n\t\t\t\t\tif (HasWeaponSlot(i)) {\n\t\t\t\t\t\tSetCurrentWeapon(i);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tSetMoveState(PEDMOVE_STILL);\n\t\t\t\tbStopAndShoot = true;\n\t\t\t}\n\t\t}\n\t} else if (CTimer::GetTimeStep() / 100.f <= m_fDistanceTravelled)\n\t\tfield_624 = 0;\n}\n\nvoid\nCCopPed::ProcessHeliSwat(void)\n{\n\tCVector bestPos = GetPosition();\n\tSetPedState(PED_ABSEIL);\n\tCPedPlacement::FindZCoorForPed(&bestPos);\n\tif (GetPosition().z - 2.0f >= bestPos.z && m_pRopeEntity) {\n\t\tm_fAbseilPos += 0.003f * CTimer::GetTimeStep();\n\t\tm_vecMoveSpeed.z = -0.03f;\n\t\tm_vecTurnSpeed = CVector(0.f, 0.f, (m_randomSeed % 32) * 0.003f - 0.05f);\n\t\tCPhysical::ApplyTurnSpeed();\n\t\tGetMatrix().Reorthogonalise();\n\t\tCVector posOnRope;\n\n\t\tif (CRopes::FindCoorsAlongRope(m_nRopeID, m_fAbseilPos, &posOnRope)) {\n\t\t\tSetPosition(posOnRope);\n\t\t} else {\n\t\t\tbUsesCollision = true;\n\t\t\tm_vecMoveSpeed = CVector(0.f, 0.f, 0.f);\n\t\t\tSetPedState(PED_IDLE);\n\t\t\tm_nCopType = COP_SWAT;\n\t\t\tSetInTheAir();\n\t\t\tbKnockedUpIntoAir = true;\n\t\t}\n\t\tSay(SOUND_PED_COP_HELIPILOTPHRASE);\n\t} else {\n\t\tbUsesCollision = true;\n\t\tm_vecMoveSpeed = CVector(0.f, 0.f, 0.f);\n\t\tSetPedState(PED_IDLE);\n\t\tm_nCopType = COP_SWAT;\n\t\tSetInTheAir();\n\t\tbKnockedUpIntoAir = true;\n\t}\n}\n\nvoid\nCCopPed::ProcessStingerCop(void)\n{\n\tif (m_pStinger->bIsDeployed || FindPlayerVehicle() && (FindPlayerVehicle()->IsCar() || FindPlayerVehicle()->IsBike())) {\n\t\tif (m_pStinger->bIsDeployed) {\n\t\t\tm_pStinger->Process();\n\t\t} else {\n\t\t\tCVector2D vehDist = GetPosition() - FindPlayerVehicle()->GetPosition();\n\t\t\tCVector2D dirVehGoing = FindPlayerVehicle()->m_vecMoveSpeed;\n\t\t\tif (vehDist.MagnitudeSqr() < sq(30.0f)) {\n\t\t\t\tif (dirVehGoing.MagnitudeSqr() > 0.0f) {\n\t\t\t\t\tvehDist.Normalise();\n\t\t\t\t\tdirVehGoing.Normalise();\n\t\t\t\t\tif (DotProduct2D(vehDist, dirVehGoing) > 0.8f) {\n\t\t\t\t\t\tfloat angle = (CrossProduct2D(vehDist, dirVehGoing - vehDist) < 0.0f ?\n\t\t\t\t\t\t\tFindPlayerVehicle()->GetForward().Heading() - HALFPI :\n\t\t\t\t\t\t\tHALFPI + FindPlayerVehicle()->GetForward().Heading());\n\n\t\t\t\t\t\tSetHeading(angle);\n\t\t\t\t\t\tm_fRotationCur = angle;\n\t\t\t\t\t\tm_fRotationDest = angle;\n\t\t\t\t\t\tm_pStinger->Deploy(this);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} else {\n\t\tClearPursuit();\n\t}\n}\n"
  },
  {
    "path": "src/peds/CopPed.h",
    "content": "#pragma once\n#include \"Ped.h\"\n\nenum eCopType\n{\n\tCOP_STREET = 0,\n\tCOP_FBI = 1,\n\tCOP_SWAT = 2,\n\tCOP_HELI_SWAT = 3,\n\tCOP_ARMY = 4,\n\tCOP_MIAMIVICE = 5\n};\n\nclass CCopPed : public CPed\n{\npublic:\n\tCVehicle* m_nRoadblockVeh;\n\tfloat m_fDistanceToTarget;\n\tbool m_bIsInPursuit;\n\tbool m_bIsDisabledCop;\n\tint8 field_5FE;\n\tbool m_bBeatingSuspect;\n\tbool m_bStopAndShootDisabledZone;\n\tbool m_bDragsPlayerFromCar;\n\tbool m_bZoneDisabled;\n\tfloat m_fAbseilPos;\n\teCopType m_nCopType;\n\tbool m_bThrowsSpikeTrap;\n\tCEntity *m_pRopeEntity;\t// CHeli or 1\n\tuintptr m_nRopeID;\n\tuint32 m_nHassleTimer;\n\tuint32 field_61C;\n\tclass CStinger *m_pStinger;\n\tint32 field_624;\n\tint8 field_628;\n\n\tCCopPed(eCopType, int32 modifier = 0);\n\t~CCopPed();\n\n\tvoid ClearPursuit(void);\n\tvoid ProcessControl(void);\n\tvoid SetArrestPlayer(CPed*);\n\tvoid SetPursuit(bool);\n\tvoid ArrestPlayer(void);\n\tvoid ScanForCrimes(void);\n\tvoid CopAI(void);\n\tvoid ProcessHeliSwat(void);\n\tvoid ProcessStingerCop(void);\n};\n\nVALIDATE_SIZE(CCopPed, 0x62C);\n"
  },
  {
    "path": "src/peds/DummyPed.h",
    "content": "#pragma once\n\n#include \"Dummy.h\"\n\n// actually unused\nclass CDummyPed : CDummy\n{\n\tint32 pedType;\n\tint32 unknown;\n};\n"
  },
  {
    "path": "src/peds/EmergencyPed.cpp",
    "content": "#include \"common.h\"\n\n#include \"EmergencyPed.h\"\n#include \"DMAudio.h\"\n#include \"ModelIndices.h\"\n#include \"Vehicle.h\"\n#include \"Fire.h\"\n#include \"General.h\"\n#include \"CarCtrl.h\"\n#include \"Accident.h\"\n\nCEmergencyPed::CEmergencyPed(uint32 type) : CPed(type)\n{\n\tswitch (type){\n\t\tcase PEDTYPE_EMERGENCY:\n\t\t\tSetModelIndex(MI_MEDIC);\n\t\t\tm_pRevivedPed = nil;\n\t\t\tfield_1360 = 0;\n\t\t\tbreak;\n\t\tcase PEDTYPE_FIREMAN:\n\t\t\tSetModelIndex(MI_FIREMAN);\n\t\t\tm_pRevivedPed = nil;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\tm_nEmergencyPedState = EMERGENCY_PED_READY;\n\tm_pAttendedAccident = nil;\n\tm_bStartedToCPR = false;\n}\n\nbool\nCEmergencyPed::InRange(CPed *victim)\n{\n\tif (!m_pMyVehicle)\n\t\treturn true;\n\n\tif ((m_pMyVehicle->GetPosition() - victim->GetPosition()).Magnitude() > 30.0f)\n\t\treturn false;\n\n\treturn true;\n}\n\nvoid\nCEmergencyPed::ProcessControl(void)\n{\n\tCPed::ProcessControl();\n\tif (bWasPostponed)\n\t\treturn;\n\n\tif(!DyingOrDead()) {\n\t\tGetWeapon()->Update(m_audioEntityId, nil);\n\n\t\tif (IsPedInControl() && m_moved.Magnitude() > 0.0f)\n\t\t\tAvoid();\n\n\t\tswitch (m_nPedState) {\n\t\t\tcase PED_SEEK_POS:\n\t\t\t\tSeek();\n\t\t\t\tbreak;\n\t\t\tcase PED_SEEK_ENTITY:\n\t\t\t\tif (m_pSeekTarget) {\n\t\t\t\t\tm_vecSeekPos = m_pSeekTarget->GetPosition();\n\t\t\t\t\tSeek();\n\t\t\t\t} else {\n\t\t\t\t\tClearSeek();\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\n\t\tswitch (m_nPedType) {\n\t\t\tcase PEDTYPE_EMERGENCY:\n\t\t\t\tif (IsPedInControl() || m_nPedState == PED_DRIVING)\n\t\t\t\t\tMedicAI();\n\t\t\t\tbreak;\n\t\t\tcase PEDTYPE_FIREMAN:\n\t\t\t\tif (IsPedInControl())\n\t\t\t\t\tFiremanAI();\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\treturn;\n\t\t}\n\t}\n}\n\n// This function was buggy and incomplete in both III and VC, firemen had to be in 5.0m range of fire etc. etc.\n// Copied some code from MedicAI to make it work.\nvoid\nCEmergencyPed::FiremanAI(void)\n{\n\tfloat fireDist;\n\tCFire *nearestFire;\n\n\tswitch (m_nEmergencyPedState) {\n\t\tcase EMERGENCY_PED_READY:\n\t\t\tnearestFire = gFireManager.FindNearestFire(GetPosition(), &fireDist);\n\t\t\tif (nearestFire) {\n\t\t\t\tSetPedState(PED_NONE);\n\t\t\t\tSetSeek(nearestFire->m_vecPos, 1.0f);\n\t\t\t\tSetMoveState(PEDMOVE_RUN);\n\t\t\t\tm_nEmergencyPedState = EMERGENCY_PED_DETERMINE_NEXT_STATE;\n\t\t\t\tm_pAttendedFire = nearestFire;\n#ifdef FIX_BUGS\n\t\t\t\tbIsRunning = true;\n#endif\n\t\t\t}\n\t\t\tbreak;\n\t\tcase EMERGENCY_PED_DETERMINE_NEXT_STATE:\n\t\t\tnearestFire = gFireManager.FindNearestFire(GetPosition(), &fireDist);\n\t\t\tif (nearestFire && nearestFire != m_pAttendedFire) {\n\t\t\t\tSetPedState(PED_NONE);\n\t\t\t\tSetSeek(nearestFire->m_vecPos, 1.0f);\n\t\t\t\tSetMoveState(PEDMOVE_RUN);\n#ifdef FIX_BUGS\n\t\t\t\tbIsRunning = true;\n\t\t\t\tm_pAttendedFire = nearestFire;\n\t\t\t} else if (!nearestFire) {\n#else\n\t\t\t\tm_pAttendedFire = nearestFire;\n\t\t\t} else {\n#endif\n\t\t\t\tm_nEmergencyPedState = EMERGENCY_PED_STOP;\n\t\t\t}\n\n\t\t\t// \"Extinguish\" the fire (Will overwrite the stop decision above if the attended and nearest fires are same)\n\t\t\tif (fireDist < 5.0f) {\n\t\t\t\tSetIdle();\n\t\t\t\tm_nEmergencyPedState = EMERGENCY_PED_STAND_STILL;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase EMERGENCY_PED_STAND_STILL:\n\t\t\tif (!m_pAttendedFire->m_bIsOngoing)\n\t\t\t\tm_nEmergencyPedState = EMERGENCY_PED_STOP;\n\n\t\t\t// Leftover\n\t\t\t// fireDist = 30.0f;\n\t\t\tnearestFire = gFireManager.FindNearestFire(GetPosition(), &fireDist);\n\t\t\tif (nearestFire) {\n#ifdef FIX_BUGS\n\t\t\t\tif(nearestFire != m_pAttendedFire && (nearestFire->m_vecPos - GetPosition()).Magnitude() < 30.0f)\n#endif\n\t\t\t\t\tm_nEmergencyPedState = EMERGENCY_PED_DETERMINE_NEXT_STATE;\n\t\t\t}\n\t\t\tSay(SOUND_PED_EXTINGUISHING_FIRE);\n\t\t\tbreak;\n\t\tcase EMERGENCY_PED_STOP:\n#ifdef FIX_BUGS\n\t\t\tbIsRunning = false;\n#endif\n\t\t\tSetPedState(PED_NONE);\n\t\t\tSetWanderPath(CGeneral::GetRandomNumber() & 7);\n\t\t\tm_pAttendedFire = nil;\n\t\t\tm_nEmergencyPedState = EMERGENCY_PED_READY;\n\t\t\tSetMoveState(PEDMOVE_WALK);\n\t\t\tbreak;\n\t\tdefault: break;\n\t}\n}\n\nvoid\nCEmergencyPed::MedicAI(void)\n{\n\tfloat distToEmergency;\n\tif (!bInVehicle && IsPedInControl()) {\n\t\tScanForDelayedResponseThreats();\n\t\tif (m_threatFlags && CTimer::GetTimeInMilliseconds() > m_threatCheckTimer) {\n\t\t\tCheckThreatValidity();\n\t\t\tm_threatFlags = 0;\n\t\t\tm_threatCheckTimer = 0;\n\t\t\tif (m_threatEntity && m_threatEntity->IsPed() && ((CPed*)m_threatEntity)->IsPlayer()) {\n\t\t\t\tif (((CPed*)m_threatEntity)->GetWeapon()->IsTypeMelee()) {\n\t\t\t\t\tSetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, m_threatEntity);\n\t\t\t\t} else {\n\t\t\t\t\tSetFlee(m_threatEntity, 6000);\n\t\t\t\t\tSay(SOUND_PED_FLEE_SPRINT);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (InVehicle()) {\n\t\tif (m_pMyVehicle->IsCar() && m_objective != OBJECTIVE_LEAVE_CAR) {\n\t\t\tif (gAccidentManager.FindNearestAccident(m_pMyVehicle->GetPosition(), &distToEmergency)\n\t\t\t\t&& distToEmergency < 25.0f && m_pMyVehicle->m_vecMoveSpeed.Magnitude() < 0.01f) {\n\n\t\t\t\tm_pMyVehicle->AutoPilot.m_nCarMission = MISSION_NONE;\n\t\t\t\tSetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle);\n\t\t\t\tSay(SOUND_PED_LEAVE_VEHICLE);\n\t\t\t} else if (m_pMyVehicle->pDriver == this && m_nPedState == PED_DRIVING\n\t\t\t\t&& m_pMyVehicle->AutoPilot.m_nCarMission == MISSION_NONE && !(CGeneral::GetRandomNumber() & 31)) {\n\n\t\t\t\tbool waitUntilMedicEntersCar = false;\n\t\t\t\tfor (int i = 0; i < m_numNearPeds; ++i) {\n\t\t\t\t\tCPed *nearPed = m_nearPeds[i];\n\t\t\t\t\tif (nearPed->m_nPedType == PEDTYPE_EMERGENCY) {\n\t\t\t\t\t\tif ((nearPed->m_nPedState == PED_SEEK_CAR || nearPed->m_nPedState == PED_ENTER_CAR)\n\t\t\t\t\t\t\t&& nearPed->m_pMyVehicle == m_pMyVehicle) {\n\t\t\t\t\t\t\twaitUntilMedicEntersCar = true;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (!waitUntilMedicEntersCar) {\n\t\t\t\t\tCCarCtrl::JoinCarWithRoadSystem(m_pMyVehicle);\n\t\t\t\t\tm_pMyVehicle->AutoPilot.m_nCarMission = MISSION_CRUISE;\n\t\t\t\t\tm_pMyVehicle->m_bSirenOrAlarm = 0;\n\t\t\t\t\tm_pMyVehicle->AutoPilot.m_nCruiseSpeed = 12;\n\t\t\t\t\tm_pMyVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_SLOW_DOWN_FOR_CARS;\n\t\t\t\t\tif (m_pMyVehicle->bIsAmbulanceOnDuty) {\n\t\t\t\t\t\tm_pMyVehicle->bIsAmbulanceOnDuty = false;\n\t\t\t\t\t\t--CCarCtrl::NumAmbulancesOnDuty;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tCVector headPos, midPos;\n\tCAccident *nearestAccident;\n\tif (IsPedInControl()) {\n\t\tswitch (m_nEmergencyPedState) {\n\t\t\tcase EMERGENCY_PED_READY:\n\t\t\t\tnearestAccident = gAccidentManager.FindNearestAccident(GetPosition(), &distToEmergency);\n\t\t\t\tfield_1360 = 0;\n\t\t\t\tif (nearestAccident) {\n\t\t\t\t\tm_pRevivedPed = nearestAccident->m_pVictim;\n\t\t\t\t\tm_pRevivedPed->RegisterReference((CEntity**)&m_pRevivedPed);\n\t\t\t\t\tm_pRevivedPed->m_pedIK.GetComponentPosition(midPos, PED_MID);\n\t\t\t\t\tm_pRevivedPed->m_pedIK.GetComponentPosition(headPos, PED_HEAD);\n\t\t\t\t\tSetObjective(OBJECTIVE_GOTO_AREA_ON_FOOT, CVector((headPos + midPos) * 0.5f));\n\t\t\t\t\tbIsRunning = true;\n\t\t\t\t\tm_nEmergencyPedState = EMERGENCY_PED_DETERMINE_NEXT_STATE;\n\t\t\t\t\tm_pAttendedAccident = nearestAccident;\n\t\t\t\t\t++m_pAttendedAccident->m_nMedicsAttending;\n\t\t\t\t} else {\n\t\t\t\t\tif (m_pMyVehicle) {\n\t\t\t\t\t\tif (!bInVehicle) {\n\t\t\t\t\t\t\tif (m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER || m_pMyVehicle->pDriver || m_pMyVehicle->m_nGettingInFlags) {\n\n\t\t\t\t\t\t\t\tCPed* driver = m_pMyVehicle->pDriver;\n\t\t\t\t\t\t\t\tif (driver && driver->m_nPedType != PEDTYPE_EMERGENCY && m_objective != OBJECTIVE_KILL_CHAR_ON_FOOT) {\n\t\t\t\t\t\t\t\t\tSetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, driver);\n\n\t\t\t\t\t\t\t\t} else if (m_objective != OBJECTIVE_ENTER_CAR_AS_DRIVER\n\t\t\t\t\t\t\t\t\t&& m_objective != OBJECTIVE_ENTER_CAR_AS_PASSENGER\n\t\t\t\t\t\t\t\t\t&& m_objective != OBJECTIVE_KILL_CHAR_ON_FOOT) {\n\t\t\t\t\t\t\t\t\tSetObjective(OBJECTIVE_ENTER_CAR_AS_PASSENGER, m_pMyVehicle);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tSetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, m_pMyVehicle);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (m_nPedState != PED_WANDER_PATH) {\n\t\t\t\t\t\tSetWanderPath(CGeneral::GetRandomNumber() & 7);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase EMERGENCY_PED_DETERMINE_NEXT_STATE:\n\t\t\t\tnearestAccident = gAccidentManager.FindNearestAccident(GetPosition(), &distToEmergency);\n\t\t\t\tif (nearestAccident) {\n\t\t\t\t\tif (nearestAccident != m_pAttendedAccident || m_nPedState != PED_SEEK_POS) {\n\t\t\t\t\t\tm_pRevivedPed = nearestAccident->m_pVictim;\n\t\t\t\t\t\tm_pRevivedPed->RegisterReference((CEntity**)&m_pRevivedPed);\n\t\t\t\t\t\tif (!InRange(m_pRevivedPed)) {\n\t\t\t\t\t\t\tm_nEmergencyPedState = EMERGENCY_PED_STOP;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tm_pRevivedPed->m_pedIK.GetComponentPosition(midPos, PED_MID);\n\t\t\t\t\t\tm_pRevivedPed->m_pedIK.GetComponentPosition(headPos, PED_HEAD);\n\t\t\t\t\t\tSetObjective(OBJECTIVE_GOTO_AREA_ON_FOOT, CVector((headPos + midPos) * 0.5f));\n\t\t\t\t\t\tbIsRunning = true;\n\t\t\t\t\t\t--m_pAttendedAccident->m_nMedicsAttending;\n\t\t\t\t\t\t++nearestAccident->m_nMedicsAttending;\n\t\t\t\t\t\tm_pAttendedAccident = nearestAccident;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tm_nEmergencyPedState = EMERGENCY_PED_STOP;\n\t\t\t\t\tbIsRunning = false;\n\t\t\t\t}\n\t\t\t\tif (distToEmergency < 5.0f) {\n\t\t\t\t\tif (m_pRevivedPed->m_pFire) {\n\t\t\t\t\t\tbIsRunning = false;\n\t\t\t\t\t\tSetMoveState(PEDMOVE_STILL);\n\t\t\t\t\t} else if (distToEmergency < 4.5f) {\n\t\t\t\t\t\tbIsRunning = false;\n\t\t\t\t\t\tSetMoveState(PEDMOVE_WALK);\n\t\t\t\t\t\tif (distToEmergency < 1.0f\n\t\t\t\t\t\t\t|| distToEmergency < 4.5f && m_pAttendedAccident->m_nMedicsPerformingCPR) {\n\t\t\t\t\t\t\tm_nEmergencyPedState = EMERGENCY_PED_START_CPR;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase EMERGENCY_PED_START_CPR:\n\t\t\t\tif (!m_pRevivedPed || m_pRevivedPed->m_fHealth > 0.0f || m_pRevivedPed->bFadeOut) {\n\t\t\t\t\tm_nEmergencyPedState = EMERGENCY_PED_DETERMINE_NEXT_STATE;\n\t\t\t\t} else {\n\t\t\t\t\tm_pRevivedPed->m_bloodyFootprintCountOrDeathTime = CTimer::GetTimeInMilliseconds();\n\t\t\t\t\tSetMoveState(PEDMOVE_STILL);\n\t\t\t\t\tSetPedState(PED_CPR);\n\t\t\t\t\tm_nLastPedState = PED_CPR;\n\t\t\t\t\tSetLookFlag(m_pRevivedPed, 0);\n\t\t\t\t\tSetLookTimer(500);\n\t\t\t\t\tSay(SOUND_PED_HEALING);\n\t\t\t\t\tif (m_pAttendedAccident->m_nMedicsPerformingCPR) {\n\t\t\t\t\t\tSetIdle();\n\t\t\t\t\t\tm_nEmergencyPedState = EMERGENCY_PED_STAND_STILL;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tm_nEmergencyPedState = EMERGENCY_PED_FACE_TO_PATIENT;\n\t\t\t\t\t\tm_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_MEDIC, ANIM_MEDIC_CPR, 4.0f);\n\t\t\t\t\t\tbIsDucking = true;\n\t\t\t\t\t}\n\t\t\t\t\tSetLookTimer(2000);\n\t\t\t\t\t++m_pAttendedAccident->m_nMedicsPerformingCPR;\n\t\t\t\t\tm_bStartedToCPR = true;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase EMERGENCY_PED_FACE_TO_PATIENT:\n\t\t\t\tif (!m_pRevivedPed || m_pRevivedPed->m_fHealth > 0.0f)\n\t\t\t\t\tm_nEmergencyPedState = EMERGENCY_PED_DETERMINE_NEXT_STATE;\n\t\t\t\telse {\n\t\t\t\t\tm_pRevivedPed->m_pedIK.GetComponentPosition(midPos, PED_MID);\n\t\t\t\t\tm_pRevivedPed->m_pedIK.GetComponentPosition(headPos, PED_HEAD);\n\t\t\t\t\tmidPos = (headPos + midPos) * 0.5f;\n\t\t\t\t\tm_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(\n\t\t\t\t\t\tmidPos.x, midPos.y,\n\t\t\t\t\t\tGetPosition().x, GetPosition().y);\n\t\t\t\t\tm_fRotationDest = CGeneral::LimitAngle(m_fRotationDest);\n\t\t\t\t\tm_pLookTarget = m_pRevivedPed;\n\t\t\t\t\tm_pLookTarget->RegisterReference((CEntity**)&m_pLookTarget);\n\t\t\t\t\tTurnBody();\n\n\t\t\t\t\tif (Abs(m_fRotationCur - m_fRotationDest) < DEGTORAD(45.0f))\n\t\t\t\t\t\tm_nEmergencyPedState = EMERGENCY_PED_PERFORM_CPR;\n\t\t\t\t\telse\n\t\t\t\t\t\tm_fRotationCur = (m_fRotationCur + m_fRotationDest) * 0.5f;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase EMERGENCY_PED_PERFORM_CPR:\n\t\t\t\tif (!m_pRevivedPed || m_pRevivedPed->m_fHealth > 0.0f) {\n\t\t\t\t\tm_nEmergencyPedState = EMERGENCY_PED_DETERMINE_NEXT_STATE;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tm_pRevivedPed->m_pedIK.GetComponentPosition(midPos, PED_MID);\n\t\t\t\tm_pRevivedPed->m_pedIK.GetComponentPosition(headPos, PED_HEAD);\n\t\t\t\tmidPos = (headPos + midPos) * 0.5f;\n\t\t\t\tm_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(\n\t\t\t\t\tmidPos.x, midPos.y,\n\t\t\t\t\tGetPosition().x, GetPosition().y);\n\t\t\t\tm_fRotationDest = CGeneral::LimitAngle(m_fRotationDest);\n\t\t\t\tm_pLookTarget = m_pRevivedPed;\n\t\t\t\tm_pLookTarget->RegisterReference((CEntity**)&m_pLookTarget);\n\t\t\t\tTurnBody();\n\t\t\t\tif (CTimer::GetTimeInMilliseconds() <= m_lookTimer) {\n\t\t\t\t\tSetMoveState(PEDMOVE_STILL);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tm_nEmergencyPedState = EMERGENCY_PED_STOP_CPR;\n\t\t\t\tSetPedState(PED_NONE);\n\t\t\t\tSetMoveState(PEDMOVE_WALK);\n\t\t\t\tm_pVehicleAnim = nil;\n\t\t\t\tif (!m_pRevivedPed->bBodyPartJustCameOff) {\n\t\t\t\t\tm_pRevivedPed->m_fHealth = 100.0f;\n\t\t\t\t\tm_pRevivedPed->SetPedState(PED_NONE);\n\t\t\t\t\tm_pRevivedPed->m_nLastPedState = PED_WANDER_PATH;\n\t\t\t\t\tm_pRevivedPed->SetGetUp();\n\t\t\t\t\tm_pRevivedPed->bUsesCollision = true;\n\t\t\t\t\tm_pRevivedPed->SetMoveState(PEDMOVE_WALK);\n\t\t\t\t\tm_pRevivedPed->RestartNonPartialAnims();\n\t\t\t\t\tm_pRevivedPed->bIsPedDieAnimPlaying = false;\n\t\t\t\t\tm_pRevivedPed->bKnockedUpIntoAir = false;\n\t\t\t\t\tm_pRevivedPed->m_pCollidingEntity = nil;\n\t\t\t\t\tm_pRevivedPed->bKnockedOffBike = false;\n\t\t\t\t\tm_pRevivedPed->Say(SOUND_PED_ACCIDENTREACTION1);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase EMERGENCY_PED_STOP_CPR:\n\t\t\t\tm_nEmergencyPedState = EMERGENCY_PED_STOP;\n\t\t\t\tbIsDucking = true;\n\t\t\t\tbreak;\n\t\t\tcase EMERGENCY_PED_STAND_STILL:\n\t\t\t\tif (!m_pRevivedPed || m_pRevivedPed->m_fHealth > 0.0f)\n\t\t\t\t\tm_nEmergencyPedState = EMERGENCY_PED_DETERMINE_NEXT_STATE;\n\t\t\t\telse {\n\t\t\t\t\tif (!m_pAttendedAccident->m_pVictim)\n\t\t\t\t\t\tm_nEmergencyPedState = EMERGENCY_PED_DETERMINE_NEXT_STATE;\n\t\t\t\t\tif (!m_pAttendedAccident->m_nMedicsPerformingCPR)\n\t\t\t\t\t\tm_nEmergencyPedState = EMERGENCY_PED_DETERMINE_NEXT_STATE;\n\t\t\t\t\tif (gAccidentManager.UnattendedAccidents())\n\t\t\t\t\t\tm_nEmergencyPedState = EMERGENCY_PED_DETERMINE_NEXT_STATE;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase EMERGENCY_PED_STOP:\n\t\t\t\tm_bStartedToCPR = false;\n\t\t\t\tSetPedState(PED_NONE);\n\t\t\t\tif (m_pAttendedAccident) {\n\t\t\t\t\tm_pAttendedAccident->m_pVictim = nil;\n\t\t\t\t\t--m_pAttendedAccident->m_nMedicsAttending;\n\t\t\t\t\tm_pAttendedAccident = nil;\n\t\t\t\t}\n\t\t\t\tSetWanderPath(CGeneral::GetRandomNumber() & 7);\n\t\t\t\tm_pRevivedPed = nil;\n\t\t\t\tm_nEmergencyPedState = EMERGENCY_PED_READY;\n\t\t\t\tSetMoveState(PEDMOVE_WALK);\n\t\t\t\tbreak;\n\t\t\tdefault: break;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/peds/EmergencyPed.h",
    "content": "#pragma once\n\n#include \"Ped.h\"\n\nclass CAccident;\nclass CFire;\n\nenum EmergencyPedState\n{\n\tEMERGENCY_PED_READY = 0x0,\n\tEMERGENCY_PED_DETERMINE_NEXT_STATE = 0x1, // you can set that anytime you want\n\tEMERGENCY_PED_START_CPR = 0x2,\n\tEMERGENCY_PED_FLAG_4 = 0x4, // unused\n\tEMERGENCY_PED_FLAG_8 = 0x8, // unused\n\tEMERGENCY_PED_FACE_TO_PATIENT = 0x10, // for CPR\n\tEMERGENCY_PED_PERFORM_CPR = 0x20,\n\tEMERGENCY_PED_STOP_CPR = 0x40,\n\tEMERGENCY_PED_STAND_STILL = 0x80, // waiting colleagues for medics, \"extinguishing\" fire for firemen\n\tEMERGENCY_PED_STOP = 0x100,\n};\n\nclass CEmergencyPed : public CPed\n{\npublic:\n\tCPed *m_pRevivedPed;\n\tEmergencyPedState m_nEmergencyPedState;\n\tCAccident *m_pAttendedAccident;\n\tCFire *m_pAttendedFire;\n\tbool m_bStartedToCPR; // set but unused\n\tint32 field_1360; // set to 0 but unused\n\n\tCEmergencyPed(uint32);\n\t~CEmergencyPed() { }\n\tbool InRange(CPed*);\n\tvoid ProcessControl(void);\n\tvoid FiremanAI(void);\n\tvoid MedicAI(void);\n};\n//VALIDATE_SIZE(CEmergencyPed, 0x554);\n"
  },
  {
    "path": "src/peds/Gangs.cpp",
    "content": "#include \"common.h\"\n\n#include \"ModelIndices.h\"\n#include \"Gangs.h\"\n#include \"General.h\"\n#include \"Streaming.h\"\n#include \"Weapon.h\"\n\nCGangInfo CGangs::Gang[NUM_GANGS];\nbool CGangs::GangAttackWithCops[NUM_GANGS];\n\nCGangInfo::CGangInfo() :\n\tm_nVehicleMI(-1),\n\tm_nPedModel1MI(-1),\n\tm_nPedModel2MI(-1),\n\tm_nPedModelOverride(-1),\n\tm_Weapon1(WEAPONTYPE_UNARMED),\n\tm_Weapon2(WEAPONTYPE_UNARMED)\n{}\n\nvoid CGangs::Initialise(void)\n{\n\tSetGangPedModels(GANG_CUBAN, MI_CBA, MI_CBB);\n\tSetGangPedModels(GANG_HAITIAN, MI_HNA, MI_HNB);\n\tSetGangPedModels(GANG_STREET, MI_SGA, MI_SGB);\n\tSetGangPedModels(GANG_DIAZ, MI_CLA, MI_CLB);\n\tSetGangPedModels(GANG_SECURITY, MI_GDA, MI_GDB);\n\tSetGangPedModels(GANG_BIKER, MI_BKA, MI_BKB);\n\tSetGangPedModels(GANG_PLAYER, MI_PGA, MI_PGB);\n\tSetGangPedModels(GANG_GOLFER, MI_WFOGO, MI_WMOGO);\n\tSetGangVehicleModel(GANG_CUBAN, MI_CUBAN);\n\tSetGangVehicleModel(GANG_HAITIAN, MI_VOODOO);\n\tSetGangVehicleModel(GANG_STREET, MI_GANGBUR);\n\tSetGangVehicleModel(GANG_DIAZ, -1);\n\tSetGangVehicleModel(GANG_SECURITY, -1);\n\tSetGangVehicleModel(GANG_BIKER, MI_ANGEL);\n\tSetGangVehicleModel(GANG_PLAYER, -1);\n\tSetGangVehicleModel(GANG_GOLFER, MI_CADDY);\n\tSetGangWeapons(GANG_GOLFER, WEAPONTYPE_GOLFCLUB, WEAPONTYPE_GOLFCLUB);\n#ifdef FIX_BUGS\n\tfor (int i = 0; i < NUM_GANGS; i++)\n\t\tSetGangPedModelOverride(i, -1);\n#endif\n}\n\nbool CGangs::HaveGangModelsLoaded(int16 gang)\n{\n\tCGangInfo* pGangInfo = GetGangInfo(gang);\n\treturn CStreaming::HasModelLoaded(pGangInfo->m_nPedModel1MI) && CStreaming::HasModelLoaded(pGangInfo->m_nPedModel2MI);\n}\n\nvoid CGangs::SetGangPedModels(int16 gang, int32 mi1, int32 mi2)\n{\n\tGetGangInfo(gang)->m_nPedModel1MI = mi1;\n\tGetGangInfo(gang)->m_nPedModel2MI = mi2;\n}\n\nvoid CGangs::SetWillAttackPlayerWithCops(ePedType type, bool will)\n{\n\tif (type >= PEDTYPE_GANG1 && type <= PEDTYPE_GANG9)\n\t\tGangAttackWithCops[type - PEDTYPE_GANG1] = will;\n}\n\nbool CGangs::GetWillAttackPlayerWithCops(ePedType type)\n{\n\tif (type >= PEDTYPE_GANG1 && type <= PEDTYPE_GANG9)\n\t\treturn GangAttackWithCops[type - PEDTYPE_GANG1];\n\treturn false;\n}\n\nint32 CGangs::ChooseGangPedModel(int16 gang)\n{\n\tCGangInfo* pGangInfo = GetGangInfo(gang);\n\tif (pGangInfo->m_nPedModelOverride != -1 || CGeneral::GetRandomTrueFalse())\n\t\treturn pGangInfo->m_nPedModel1MI;\n\telse\n\t\treturn pGangInfo->m_nPedModel2MI;\n}\n\nvoid CGangs::SetGangVehicleModel(int16 gang, int32 model)\n{\n\tGetGangInfo(gang)->m_nVehicleMI = model;\n}\n\nvoid CGangs::SetGangWeapons(int16 gang, int32 weapon1, int32 weapon2)\n{\n\tCGangInfo *gi = GetGangInfo(gang);\n\tgi->m_Weapon1 = weapon1;\n\tgi->m_Weapon2 = weapon2;\n}\n\nvoid CGangs::SetGangPedModelOverride(int16 gang, int8 ovrd)\n{\n\tGetGangInfo(gang)->m_nPedModelOverride = ovrd;\n}\n\nint8 CGangs::GetGangPedModelOverride(int16 gang)\n{\n\treturn GetGangInfo(gang)->m_nPedModelOverride;\n}\n\nvoid CGangs::SaveAllGangData(uint8 *buf, uint32 *size)\n{\nINITSAVEBUF\n\n\t*size = SAVE_HEADER_SIZE + sizeof(Gang);\n\tWriteSaveHeader(buf, 'G','N','G','\\0', *size - SAVE_HEADER_SIZE);\n\tfor (int i = 0; i < NUM_GANGS; i++)\n\t\tWriteSaveBuf(buf, Gang[i]);\n\nVALIDATESAVEBUF(*size);\n}\n\nvoid CGangs::LoadAllGangData(uint8 *buf, uint32 size)\n{\n\tInitialise();\n\nINITSAVEBUF\n\tCheckSaveHeader(buf, 'G','N','G','\\0', size - SAVE_HEADER_SIZE);\n\n\tfor (int i = 0; i < NUM_GANGS; i++)\n\t\tGang[i] = ReadSaveBuf<CGangInfo>(buf);\nVALIDATESAVEBUF(size);\n}\n"
  },
  {
    "path": "src/peds/Gangs.h",
    "content": "#pragma once\n\n#include \"PedType.h\"\n\nstruct CGangInfo\n{\n\tint32 m_nVehicleMI;\n\tint32 m_nPedModel1MI;\n\tint32 m_nPedModel2MI;\n\tint8 m_nPedModelOverride;\n\tint32 m_Weapon1;\n\tint32 m_Weapon2;\n\n\tCGangInfo();\n};\n\nVALIDATE_SIZE(CGangInfo, 0x10);\n\nenum {\n\tGANG_CUBAN = 0,\n\tGANG_HAITIAN,\n\tGANG_STREET,\n\tGANG_DIAZ,\n\tGANG_SECURITY,\n\tGANG_BIKER,\n\tGANG_PLAYER,\n\tGANG_GOLFER,\n\tGANG_9,\n\tNUM_GANGS\n};\n\nclass CGangs\n{\npublic:\n\tstatic void Initialise(void);\n\tstatic void SetGangVehicleModel(int16, int32);\n\tstatic void SetGangWeapons(int16, int32, int32);\n\tstatic void SetGangPedModelOverride(int16, int8);\n\tstatic int8 GetGangPedModelOverride(int16);\n\tstatic void SaveAllGangData(uint8 *, uint32 *);\n\tstatic void LoadAllGangData(uint8 *, uint32);\n\n\tstatic void SetGangPedModels(int16, int32, int32);\n\tstatic void SetWillAttackPlayerWithCops(ePedType type, bool will);\n\tstatic bool GetWillAttackPlayerWithCops(ePedType type);\n\tstatic int32 ChooseGangPedModel(int16);\n\n\tstatic bool HaveGangModelsLoaded(int16 gang);\n\tstatic int32 GetGangPedModel1(int16 gang) { return Gang[gang].m_nPedModel1MI; }\n\tstatic int32 GetGangPedModel2(int16 gang) { return Gang[gang].m_nPedModel2MI; }\n\tstatic int32 GetGangVehicleModel(int16 gang) { return Gang[gang].m_nVehicleMI; }\n\tstatic CGangInfo *GetGangInfo(int16 gang) { return &Gang[gang]; }\n\nprivate:\n\tstatic CGangInfo Gang[NUM_GANGS];\n\tstatic bool GangAttackWithCops[NUM_GANGS];\n};\n"
  },
  {
    "path": "src/peds/Ped.cpp",
    "content": "#include \"common.h\"\n\n#include \"main.h\"\n#include \"Pools.h\"\n#include \"Particle.h\"\n#include \"RpAnimBlend.h\"\n#include \"Bones.h\"\n#include \"Ped.h\"\n#include \"AnimBlendAssociation.h\"\n#include \"Fire.h\"\n#include \"DMAudio.h\"\n#include \"General.h\"\n#include \"VisibilityPlugins.h\"\n#include \"HandlingMgr.h\"\n#include \"Replay.h\"\n#include \"Radar.h\"\n#include \"PedPlacement.h\"\n#include \"Shadows.h\"\n#include \"Weather.h\"\n#include \"ZoneCull.h\"\n#include \"Population.h\"\n#include \"Pad.h\"\n#include \"Phones.h\"\n#include \"TrafficLights.h\"\n#include \"CopPed.h\"\n#include \"Script.h\"\n#include \"CarCtrl.h\"\n#include \"Garages.h\"\n#include \"WaterLevel.h\"\n#include \"Timecycle.h\"\n#include \"ParticleObject.h\"\n#include \"Floater.h\"\n#include \"Range2D.h\" \n#include \"Streaming.h\"\n#include \"PedAttractor.h\"\n#include \"GameLogic.h\"\n#include \"Bike.h\"\n#include \"WindModifiers.h\"\n#include \"CutsceneShadow.h\"\n#include \"Clock.h\"\n#include \"Wanted.h\"\n\nCPed *gapTempPedList[50];\nuint16 gnNumTempPedList;\n\nstatic CColPoint aTempPedColPts[MAX_COLLISION_POINTS];\n\nuint16 CPed::nThreatReactionRangeMultiplier = 1;\nuint16 CPed::nEnterCarRangeMultiplier = 1;\n\nbool CPed::bNastyLimbsCheat;\nbool CPed::bFannyMagnetCheat;\nbool CPed::bPedCheat3;\nCVector2D CPed::ms_vec2DFleePosition;\n\nvoid *CPed::operator new(size_t sz) { return CPools::GetPedPool()->New();  }\nvoid *CPed::operator new(size_t sz, int handle) { return CPools::GetPedPool()->New(handle); }\nvoid CPed::operator delete(void *p, size_t sz) { CPools::GetPedPool()->Delete((CPed*)p); }\nvoid CPed::operator delete(void *p, int handle) { CPools::GetPedPool()->Delete((CPed*)p); }\n\nfloat gfTommyFatness = 1.0f;\n\nCPed::CPed(uint32 pedType) : m_pedIK(this)\n{\n#ifdef USE_CUTSCENE_SHADOW_FOR_PED\n\tm_pRTShadow = nil;\n#endif\n\tm_vecAnimMoveDelta.x = 0.0f;\n\tm_vecAnimMoveDelta.y = 0.0f;\n\tm_fHealth = 100.0f;\n\tm_fArmour = 0.0f;\n\tm_nPedType = pedType;\n\tm_lastSoundStart = 0;\n\tm_soundStart = 0;\n\tm_lastQueuedSound = SOUND_NO_SOUND;\n\tm_queuedSound = SOUND_NO_SOUND;\n\tm_canTalk = true;\n\n\tm_type = ENTITY_TYPE_PED;\n\tbPedPhysics = true;\n\tbUseCollisionRecords = true;\n\n\tm_objective = OBJECTIVE_NONE;\n\tm_prevObjective = OBJECTIVE_NONE;\n#ifdef FIX_BUGS\n\tm_objectiveTimer = 0;\n#endif\n\tCharCreatedBy = RANDOM_CHAR;\n\tm_leader = nil;\n\tm_pedInObjective = nil;\n\tm_attractorHeading = 0.0f;\n\tm_carInObjective = nil;\n\tm_attractorHeading = 0.0f;\n\tbInVehicle = false;\n\tm_pMyVehicle = nil;\n\tm_pVehicleAnim = nil;\n\tm_vecOffsetSeek.x = 0.0f;\n\tm_vecOffsetSeek.y = 0.0f;\n\tm_vecOffsetSeek.z = 0.0f;\n\tm_attractor = nil;\n\tm_positionInQueue = -1;\n\tm_pedFormation = FORMATION_UNDEFINED;\n\tm_collidingThingTimer = 0;\n\tm_nPedStateTimer = 0;\n\tm_actionX = 0.0f;\n\tm_actionY = 0.0f;\n\tm_phoneTalkTimer = 0;\n\tm_stateUnused = 0;\n\tm_leaveCarTimer = 0;\n\tm_getUpTimer = 0;\n\tm_attackTimer = 0;\n\tm_timerUnused = 0;\n\tm_lookTimer = 0;\n\tm_chatTimer = 0;\n\tm_shootTimer = 0;\n\tm_carJackTimer = 0;\n\tm_duckAndCoverTimer = 0;\n\tm_moved = CVector2D(0.0f, 0.0f);\n\tm_fRotationCur = 0.0f;\n\tm_headingRate = 15.0f;\n\tm_fRotationDest = 0.0f;\n\tm_vehDoor = CAR_DOOR_LF;\n\tm_walkAroundType = 0;\n\tm_pCurrentPhysSurface = nil;\n\tm_vecOffsetFromPhysSurface = CVector(0.0f, 0.0f, 0.0f);\n\tm_pSeekTarget = nil;\n\tm_vecSeekPos = CVector(0.0f, 0.0f, 0.0f);\n\tm_wepSkills = 0;\n\tm_distanceToCountSeekDone = 1.0f;\n\tm_acceptableHeadingOffset = 0.1f;\n\tm_followPathDestPos = CVector(0.f, 0.f, 0.f);\n\tm_followPathAbortDist = 0.0f;\n\tm_followPathMoveState = PEDMOVE_NONE;\n\tbRunningToPhone = false;\n\tm_phoneId = -1;\n\tm_lastAccident = 0;\n\tm_fleeFrom = nil;\n\tm_fleeFromPos = CVector2D(0.0f, 0.0f);\n\tm_fleeTimer = 0;\n\tm_threatEx = nil;\n\tm_vecSpotToGuard = CVector(0.0f, 0.0f, 0.0f);\n\tm_radiusToGuard = 0.0f;\n\tm_nWaitState = WAITSTATE_FALSE;\n\tm_nWaitTimer = 0;\n\tm_pCollidingEntity = nil;\n\tm_nPedState = PED_IDLE;\n\tm_nLastPedState = PED_NONE;\n\tm_nMoveState = PEDMOVE_STILL;\n#ifdef FIX_BUGS\n\tm_nPrevMoveState = PEDMOVE_NONE;\n#endif\n\tm_nStoredMoveState = PEDMOVE_NONE;\n\tm_pFire = nil;\n\tm_pPointGunAt = nil;\n\tm_pLookTarget = nil;\n\tm_fLookDirection = 0.0f;\n\tm_pCurSurface = nil;\n\tm_wanderRangeBounds = nil;\n\n\tfor (int i = 0; i < ARRAY_SIZE(m_pathNodesToGo); i++) {\n\t\tm_pathNodesToGo[i] = nil;\n\t}\n\tm_nNumPathNodes = 0;\n\tm_nCurPathNodeId = 0;\n\tm_nPathDir = 0;\n\tm_pLastPathNode = nil;\n\tm_pNextPathNode = nil;\n\tm_followPathWalkAroundEnt = nil;\n\tm_followPathTargetEnt = nil;\n\tm_pathNodeTimer = 0;\n\tm_pCurPathNode = nil;\n\n\tm_threatFlags = 0;\n\tm_threatCheckTimer = 0;\n\tm_threatCheckInterval = CGeneral::GetRandomNumberInRange(250, 1000);\n\n\tm_routeLastPoint = -1;\n\tm_routeStartPoint = 0;\n\tm_routePointsPassed = 0;\n\tm_routeType = 0;\n\n\tm_fMass = 70.0f;\n\tm_fTurnMass = 100.0f;\n\tm_fAirResistance = 0.4f / m_fMass;\n\tm_fElasticity = 0.05f;\n\n\tm_ceaseAttackTimer = 0;\n\tm_bodyPartBleeding = -1;\n\n\tbIsStanding = false;\n\tbWasStanding = false;\n\tbIsAttacking = false;\n\tbIsPointingGunAt = false;\n\tbIsLooking = false;\n\tbKeepTryingToLook = false;\n\tbIsRestoringLook = false;\n\tbIsAimingGun = false;\n\n\tbIsRestoringGun = false;\n\tbCanPointGunAtTarget = false;\n\tbIsTalking = false;\n\tbIsInTheAir = false;\n\tbIsLanding = false;\n\tbIsRunning = false;\n\tbHitSomethingLastFrame = false;\n\tbVehEnterDoorIsBlocked = false;\n\n\tbCanPedEnterSeekedCar = false;\n\tbRespondsToThreats = true;\n\tbRenderPedInCar = true;\n\tbChangedSeat = false;\n\tbUpdateAnimHeading = false;\n\tbBodyPartJustCameOff = false;\n\tbIsShooting = false;\n\tbFindNewNodeAfterStateRestore = false;\n\n\tbGonnaInvestigateEvent = false;\n\tbPedIsBleeding = false;\n\tbStopAndShoot = false;\n\tbIsPedDieAnimPlaying = false;\n\tbUsePedNodeSeek = false;\n\tbObjectiveCompleted = false;\n\tbScriptObjectiveCompleted = false;\n\n\tbKindaStayInSamePlace = false;\n\tbBeingChasedByPolice = false;\n\tbNotAllowedToDuck = false;\n\tbCrouchWhenShooting = false;\n\tbIsDucking = false;\n\tbGetUpAnimStarted = false;\n\tbDoBloodyFootprints = false;\n\tbFleeAfterExitingCar = false;\n\n\tbWanderPathAfterExitingCar = false;\n\tbIsLeader = false;\n\tbDontDragMeOutCar = false;\n\tbWillBeQuickJacked = false;\n\tbCancelEnteringCar = false;\n\tbObstacleShowedUpDuringKillObjective = false;\n\tbDuckAndCover = false;\n\n\tbStillOnValidPoly = false;\n\tbAllowMedicsToReviveMe = true;\n\tbResetWalkAnims = false;\n\tbStartWanderPathOnFoot = false;\n\tbOnBoat = false;\n\tbBusJacked = false;\n\tbGonnaKillTheCarJacker = false;\n\tbFadeOut = false;\n\n\tbKnockedUpIntoAir = false;\n\tbHitSteepSlope = false;\n\tbCullExtraFarAway = false;\n\tbClearObjective = false;\n\tbTryingToReachDryLand = false;\n\tbCollidedWithMyVehicle = false;\n\tbRichFromMugging = false;\n\tbChrisCriminal = false;\n\n\tbShakeFist = false;\n\tbNoCriticalHits = false;\n\tbVehExitWillBeInstant = false;\n\tbHasAlreadyBeenRecorded = false;\n\tbFallenDown = false;\n\tbDontAcceptIKLookAts = false;\n\tbReachedAttractorHeadingTarget = false;\n\tbTurnedAroundOnAttractor = false;\n#ifdef KANGAROO_CHEAT\n\tm_ped_flagI80 = false;\n#endif\n\n\tbHasAlreadyUsedAttractor = false;\n\tbHasAlreadyStoleACar = false;\n\tbCarPassenger = false;\n\tbFleeWhenStanding = false;\n\tbGotUpOfMyOwnAccord = false;\n\tbMiamiViceCop = false;\n\tbMoneyHasBeenGivenByScript = false;\n\tbHasBeenPhotographed = false;\n\n\tbIsDrowning = false;\n\tbDrownsInWater = true;\n\tbWaitForLeaderToComeCloser = false;\n\tbHeldHostageInCar = false;\n\tbIsPlayerFriend = true;\n\tbHeadStuckInCollision = false;\n\tbDeadPedInFrontOfCar = false;\n\n\tm_gangFlags = 0xFF;\n\t\n\tbStayInCarOnJack = false;\n\n\tbDontFight = false;\n\tbDoomAim = true;\n\tbCanBeShotInVehicle = true;\n\tbPushedAlongByCar = false;\n\tbRemoveMeWhenIGotIntoCar = false;\n\tbIgnoreThreatsBehindObjects = false;\n\n\tbNeverEverTargetThisPed = false;\n\tbCrouchWhenScared = false;\n\tbKnockedOffBike = false;\n\tb158_8 = false;\n\tbCollectBusFare = false;\n\tbBoughtIceCream = false;\n\tbDonePositionOutOfCollision = false;\n\tbCanAttackPlayerWithCops = false;\n\n\tif (CGeneral::GetRandomNumber() & 3)\n\t\tbHasACamera = false;\n\telse\n\t\tbHasACamera = true;\n\n\tif (CGeneral::GetRandomNumberInRange(0.0f, 1.0f) <= 0.95f)\n\t\tbCanGiveUpSunbathing = false;\n\telse\n\t\tbCanGiveUpSunbathing = true;\n\n\tm_audioEntityId = DMAudio.CreateEntity(AUDIOTYPE_PHYSICAL, this);\n\tDMAudio.SetEntityStatus(m_audioEntityId, true);\n\tm_fearFlags = CPedType::GetThreats(m_nPedType);\n\tm_threatEntity = nil;\n\tm_eventOrThreat = CVector2D(0.0f, 0.0f);\n\tm_pEventEntity = nil;\n\tm_fAngleToEvent = 0.0f;\n\tm_numNearPeds = 0;\n\n\tfor (int i = 0; i < ARRAY_SIZE(m_nearPeds); i++) {\n\t\tm_nearPeds[i] = nil;\n\t}\n\tm_maxWeaponTypeAllowed = WEAPONTYPE_UNARMED;\n\tm_currentWeapon = WEAPONTYPE_UNARMED;\n\tm_storedWeapon = WEAPONTYPE_UNIDENTIFIED;\n\tm_delayedWeapon = WEAPONTYPE_UNIDENTIFIED;\n\n\tfor(int i = 0; i < TOTAL_WEAPON_SLOTS; i++) {\n\t\tCWeapon &weapon = GetWeapon(i);\n\t\tweapon.m_eWeaponType = WEAPONTYPE_UNARMED;\n\t\tweapon.m_eWeaponState = WEAPONSTATE_READY;\n\t\tweapon.m_nAmmoInClip = 0;\n\t\tweapon.m_nAmmoTotal = 0;\n\t\tweapon.m_nTimer = 0;\n\t}\n\n\tm_curFightMove = m_lastFightMove = FIGHTMOVE_IDLE;\n\tGiveWeapon(WEAPONTYPE_UNARMED, 0, true);\n\tm_wepAccuracy = 60;\n\tm_lastWepDam = -1;\n\tm_lastDamEntity = nil;\n\tm_attachedTo = nil;\n\tm_attachWepAmmo = 0;\n\tm_collPoly.valid = false;\n\tm_fCollisionSpeed = 0.0f;\n\tm_wepModelID = -1;\n\tuint16 random = CGeneral::GetRandomNumber();\n\tm_nPedMoney = random % 25;\n\tif (m_nPedMoney == 23)\n\t\tm_nPedMoney = 400;\n\tm_bleedCounter = 0;\n\tm_nExtendedRangeTimer = 0;\n\tm_vehicleInAccident = nil;\n\tm_attractor = nil;\n\tm_positionInQueue = -1;\n\tm_pWeaponModel = nil;\n\tm_delayedSoundID = -1;\n\tm_delayedSoundTimer = 0;\n\tCPopulation::UpdatePedCount((ePedType)m_nPedType, false);\n\tm_lastComment = UINT32_MAX;\n}\n\nCPed::~CPed(void)\n{\n#ifdef USE_CUTSCENE_SHADOW_FOR_PED\n\tif ( m_pRTShadow ) delete m_pRTShadow;\n#endif\n\tCWorld::Remove(this);\n\tif (m_attractor)\n\t\tGetPedAttractorManager()->DeRegisterPed(this, m_attractor);\n\tCRadar::ClearBlipForEntity(BLIP_CHAR, CPools::GetPedPool()->GetIndex(this));\n\tif (InVehicle()){\n\t\tuint8 door_flag = GetCarDoorFlag(m_vehDoor);\n\t\tif (m_pMyVehicle->pDriver == this)\n\t\t\tm_pMyVehicle->pDriver = nil;\n\t\telse {\n\t\t\t// FIX: Passenger counter now being decreased after removing ourself from vehicle.\n\t\t\tm_pMyVehicle->RemovePassenger(this);\n\t\t}\n\t\tif (m_nPedState == PED_EXIT_CAR || m_nPedState == PED_DRAG_FROM_CAR)\n\t\t\tm_pMyVehicle->m_nGettingOutFlags &= ~door_flag;\n\t\tbInVehicle = false;\n\t\tm_pMyVehicle = nil;\n\t} else if (EnteringCar()) {\n\t\tQuitEnteringCar();\n\t}\n\tif (m_pFire)\n\t\tm_pFire->Extinguish();\n\n\tClearWeapons();\n\tif (bCarPassenger)\n\t\tCPopulation::ms_nTotalCarPassengerPeds--;\n\tif (bMiamiViceCop)\n\t\tCPopulation::NumMiamiViceCops--;\n\tCPopulation::UpdatePedCount((ePedType)m_nPedType, true);\n\tDMAudio.DestroyEntity(m_audioEntityId);\n}\n\nvoid\nCPed::Initialise(void)\n{\n\tdebug(\"Initialising CPed...\\n\");\n\tCPedType::Initialise();\n\tLoadFightData();\n\tSetAnimOffsetForEnterOrExitVehicle();\n\tdebug(\"CPed ready\\n\");\n}\n\nvoid\nCPed::SetModelIndex(uint32 mi)\n{\n\tCEntity::SetModelIndex(mi);\n\tRpAnimBlendClumpInit(GetClump());\n\tRpAnimBlendClumpFillFrameArray(GetClump(), m_pFrames);\n\tCPedModelInfo *modelInfo = (CPedModelInfo *)CModelInfo::GetModelInfo(GetModelIndex());\n\tSetPedStats(modelInfo->m_pedStatType);\n\tm_headingRate = m_pedStats->m_headingChangeRate;\n\tm_animGroup = (AssocGroupId) modelInfo->m_animGroup;\n\tCAnimManager::AddAnimation(GetClump(), m_animGroup, ANIM_STD_IDLE);\n\n\tif (!CanUseTorsoWhenLooking())\n\t\tm_pedIK.m_flags |= CPedIK::LOOKAROUND_HEAD_ONLY;\n\n\t(*RPANIMBLENDCLUMPDATA(m_rwObject))->velocity2d = &m_vecAnimMoveDelta;\n\n\tif(modelInfo->GetHitColModel() == nil)\n\t\tmodelInfo->CreateHitColModelSkinned(GetClump());\n\n\tUpdateRpHAnim();\n#ifdef USE_CUTSCENE_SHADOW_FOR_PED\n\tif (!m_pRTShadow)\n\t{\n\t\tm_pRTShadow = new CCutsceneShadow;\n\t\tm_pRTShadow->Create(m_rwObject, 10, 1, 1, 1);\n\t\t//m_pRTShadow->Create(m_rwObject, 8, 0, 0, 0);\n\t}\n#endif\n}\n\nvoid\nCPed::SetPedStats(ePedStats pedStat)\n{\n\tm_pedStats = CPedStats::ms_apPedStats[pedStat];\n}\n\nvoid\nCPed::DeleteRwObject()\n{\n\tCEntity::DeleteRwObject();\n}\n\nvoid\nCPed::BuildPedLists(void)\n{\n\tif (((CTimer::GetFrameCounter() + m_randomSeed) % 16) == 0) {\n\t\tCVector centre = CEntity::GetBoundCentre();\n\t\tint deadsRegistered = 0;\n\t\tCRect rect(centre.x - 20.f * nThreatReactionRangeMultiplier,\n\t\t\tcentre.y - 20.f * nThreatReactionRangeMultiplier,\n\t\t\tcentre.x + 20.f * nThreatReactionRangeMultiplier,\n\t\t\tcentre.y + 20.f * nThreatReactionRangeMultiplier);\n\t\tint xstart = CWorld::GetSectorIndexX(rect.left);\n\t\tint ystart = CWorld::GetSectorIndexY(rect.top);\n\t\tint xend = CWorld::GetSectorIndexX(rect.right);\n\t\tint yend = CWorld::GetSectorIndexY(rect.bottom);\n\t\tgnNumTempPedList = 0;\n\n\t\tfor(int y = ystart; y <= yend; y++) {\n\t\t\tfor(int x = xstart; x <= xend; x++) {\n\t\t\t\tfor (CPtrNode *pedPtrNode = CWorld::GetSector(x,y)->m_lists[ENTITYLIST_PEDS].first; pedPtrNode; pedPtrNode = pedPtrNode->next) {\n\t\t\t\t\tCPed *ped = (CPed*)pedPtrNode->item;\n\t\t\t\t\tif (ped != this && (!ped->bInVehicle || (ped->m_pMyVehicle && ped->m_pMyVehicle->IsBike()))) {\n\n\t\t\t\t\t\tif (nThreatReactionRangeMultiplier * 30.0f > (ped->GetPosition() - GetPosition()).Magnitude2D()) {\n\t\t\t\t\t\t\tif (ped->m_nPedState == PED_DEAD) {\n\t\t\t\t\t\t\t\tif (deadsRegistered > 3)\n\t\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t\tdeadsRegistered++;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tgapTempPedList[gnNumTempPedList] = ped;\n\t\t\t\t\t\t\tgnNumTempPedList++;\n\t\t\t\t\t\t\tassert(gnNumTempPedList < ARRAY_SIZE(gapTempPedList));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tgapTempPedList[gnNumTempPedList] = nil;\n\t\tSortPeds(gapTempPedList, 0, gnNumTempPedList - 1);\n\t\tfor (m_numNearPeds = 0; m_numNearPeds < ARRAY_SIZE(m_nearPeds); m_numNearPeds++) {\n\t\t\tCPed *ped = gapTempPedList[m_numNearPeds];\n\t\t\tif (!ped)\n\t\t\t\tbreak;\n\n\t\t\tm_nearPeds[m_numNearPeds] = ped;\n\t\t}\n\t\tfor (int pedToClear = m_numNearPeds; pedToClear < ARRAY_SIZE(m_nearPeds); pedToClear++)\n\t\t\tm_nearPeds[pedToClear] = nil;\n\t}\n\n\tfor(int i = 0; i < ARRAY_SIZE(m_nearPeds); ) {\n\t\tbool removePed = false;\n\t\tif (m_nearPeds[i]) {\n\t\t\tif (m_nearPeds[i]->IsPointerValid()) {\n\t\t\t\tfloat distSqr = (GetPosition() - m_nearPeds[i]->GetPosition()).MagnitudeSqr2D();\n\t\t\t\tif (distSqr > sq(nThreatReactionRangeMultiplier * 30.f)) {\n\t\t\t\t\tremovePed = true;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tremovePed = true;\n\t\t\t}\n\t\t}\n\t\tif (removePed) {\n\t\t\t// If we arrive here, the ped we're checking isn't \"near\", so we should remove it.\n\t\t\tfor (int j = i; j < ARRAY_SIZE(m_nearPeds) - 1; j++) {\n\t\t\t\tm_nearPeds[j] = m_nearPeds[j + 1];\n\t\t\t\tm_nearPeds[j + 1] = nil;\n\t\t\t}\n\t\t\t// Above loop won't work on last slot, so we need to empty it.\n\t\t\tm_nearPeds[ARRAY_SIZE(m_nearPeds) - 1] = nil;\n\t\t\tm_numNearPeds--;\n\t\t} else\n\t\t\ti++;\n\t}\n}\n\nbool\nCPed::OurPedCanSeeThisOne(CEntity *target, bool shootablesDoBlock)\n{\n\tCColPoint colpoint;\n\tCEntity *ent;\n\n\tCVector2D dist = CVector2D(target->GetPosition()) - CVector2D(GetPosition());\n\n\t// Check if target is behind ped\n\tif (DotProduct2D(dist, CVector2D(GetForward())) < 0.0f)\n\t\treturn false;\n\n\t// Check if target is too far away\n\tif (dist.Magnitude() >= 40.0f)\n\t\treturn false;\n\n\t// Check line of sight from head\n\treturn !CWorld::ProcessLineOfSight(GetPosition() + CVector(0.f, 0.f, 1.f), target->GetPosition() + CVector(0.f, 0.f, 1.f),\n\t\tcolpoint, ent, true, false, false, shootablesDoBlock, false, false, false, shootablesDoBlock);\n}\n\n// Some kind of binary sort\nvoid\nCPed::SortPeds(CPed **list, int min, int max)\n{\n\tif (min >= max)\n\t\treturn;\n\n\tCVector leftDiff, rightDiff;\n\tCVector middleDiff = GetPosition() - list[(max + min) / 2]->GetPosition();\n\tfloat middleDist = middleDiff.Magnitude();\n\n\tint left = max;\n\tint right = min;\n\twhile(right <= left){\n\t\tfloat rightDist, leftDist;\n\t\tdo {\n\t\t\trightDiff = GetPosition() - list[right]->GetPosition();\n\t\t\trightDist = rightDiff.Magnitude();\n\t\t} while (middleDist > rightDist && ++right);\n\n\t\tdo {\n\t\t\tleftDiff = GetPosition() - list[left]->GetPosition();\n\t\t\tleftDist = leftDiff.Magnitude();\n\t\t} while (middleDist < leftDist && left--);\n\n\t\tif (right <= left) {\n\t\t\tCPed *ped = list[right];\n\t\t\tlist[right] = list[left];\n\t\t\tlist[left] = ped;\n\t\t\tright++;\n\t\t\tleft--;\n\t\t}\n\t}\n\tSortPeds(list, min, left);\n\tSortPeds(list, right, max);\n}\n\nvoid\nCPed::SetMoveState(eMoveState state)\n{\n\tm_nMoveState = state;\n}\n\nvoid\nCPed::SetMoveAnim(void)\n{\n\tif (m_nStoredMoveState == m_nMoveState || !IsPedInControl() || m_attachedTo)\n\t\treturn;\n\n\tif (m_nMoveState == PEDMOVE_NONE) {\n\t\tm_nStoredMoveState = PEDMOVE_NONE;\n\t\treturn;\n\t}\n\n\tAssocGroupId animGroupToUse;\n\tif (m_leader && m_leader->IsPlayer())\n\t\tanimGroupToUse = ASSOCGRP_PLAYER;\n\telse\n\t\tanimGroupToUse = m_animGroup;\n\n\tCAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_BLOCK);\n\tif (!animAssoc) {\n\t\tanimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_FIGHT_IDLE);\n\t\tif (!animAssoc)\n\t\t\tanimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_MELEE_IDLE_FIGHTMODE);\n\n\t\tif (animAssoc && m_nPedState == PED_FIGHT)\n\t\t\treturn;\n\n\t\tif (animAssoc) {\n\t\t\tCAnimBlendAssociation *idleAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_IDLE);\n\t\t\tif (!idleAssoc || idleAssoc->blendDelta <= 0.0f) {\n\t\t\t\tanimAssoc->flags |= ASSOC_DELETEFADEDOUT;\n\t\t\t\tanimAssoc = CAnimManager::BlendAnimation(GetClump(), animGroupToUse, ANIM_STD_IDLE, 8.0f);\n\t\t\t}\n\t\t}\n\t}\n\tif (!animAssoc) {\n\t\tanimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_IDLE_TIRED);\n\t\tif (animAssoc)\n\t\t\tif (m_nWaitState == WAITSTATE_STUCK || m_nWaitState == WAITSTATE_FINISH_FLEE)\n\t\t\t\treturn;\n\n\t\tif (animAssoc) {\n\t\t\tCAnimBlendAssociation *idleAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_IDLE);\n\t\t\tif (!idleAssoc || idleAssoc->blendDelta <= 0.0f) {\n\t\t\t\tanimAssoc->flags |= ASSOC_DELETEFADEDOUT;\n\t\t\t\tanimAssoc = CAnimManager::BlendAnimation(GetClump(), animGroupToUse, ANIM_STD_IDLE, 4.0f);\n\t\t\t}\n\t\t}\n\t}\n\tif (!animAssoc) {\n\t\tm_nStoredMoveState = m_nMoveState;\n\t\tif (m_nMoveState == PEDMOVE_WALK || m_nMoveState == PEDMOVE_RUN || m_nMoveState == PEDMOVE_SPRINT) {\n\t\t\tfor (CAnimBlendAssociation *assoc = RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_PARTIAL);\n\t\t\t\tassoc; assoc = RpAnimBlendGetNextAssociation(assoc, ASSOC_PARTIAL)) {\n\n\t\t\t\tif (!(assoc->flags & ASSOC_FADEOUTWHENDONE)) {\n\t\t\t\t\tassoc->blendDelta = -2.0f;\n\t\t\t\t\tassoc->flags |= ASSOC_DELETEFADEDOUT;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tClearAimFlag();\n\t\t\tClearLookFlag();\n\t\t}\n\n\t\tswitch (m_nMoveState) {\n\t\t\tcase PEDMOVE_STILL:\n\t\t\t\tanimAssoc = CAnimManager::BlendAnimation(GetClump(), animGroupToUse, ANIM_STD_IDLE, 4.0f);\n\t\t\t\tbreak;\n\t\t\tcase PEDMOVE_WALK:\n\t\t\t\tanimAssoc = CAnimManager::BlendAnimation(GetClump(), animGroupToUse, ANIM_STD_WALK, 1.0f);\n\t\t\t\tbreak;\n\t\t\tcase PEDMOVE_RUN:\n\t\t\t\tif (m_nPedState == PED_FLEE_ENTITY) {\n\t\t\t\t\tanimAssoc = CAnimManager::BlendAnimation(GetClump(), animGroupToUse, ANIM_STD_RUN, 3.0f);\n\t\t\t\t} else {\n\t\t\t\t\tanimAssoc = CAnimManager::BlendAnimation(GetClump(), animGroupToUse, ANIM_STD_RUN, 1.0f);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase PEDMOVE_SPRINT:\n\t\t\t\tanimAssoc = CAnimManager::BlendAnimation(GetClump(), animGroupToUse, ANIM_STD_RUNFAST, 1.0f);\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\n\t\tif (animAssoc) {\n\t\t\tif (m_leader) {\n\t\t\t\tCAnimBlendAssociation *walkAssoc = RpAnimBlendClumpGetAssociation(m_leader->GetClump(), ANIM_STD_WALK);\n\t\t\t\tif (!walkAssoc)\n\t\t\t\t\twalkAssoc = RpAnimBlendClumpGetAssociation(m_leader->GetClump(), ANIM_STD_RUN);\n\n\t\t\t\tif (!walkAssoc)\n\t\t\t\t\twalkAssoc = RpAnimBlendClumpGetAssociation(m_leader->GetClump(), ANIM_STD_RUNFAST);\n\n\t\t\t\tif (walkAssoc) {\n\t\t\t\t\tanimAssoc->speed = walkAssoc->speed;\n\t\t\t\t} else {\n\t\t\t\t\tif (CharCreatedBy == MISSION_CHAR)\n\t\t\t\t\t\tanimAssoc->speed = 1.0f;\n\t\t\t\t\telse\n\t\t\t\t\t\tanimAssoc->speed = 1.2f - m_randomSeed * 0.4f / MYRAND_MAX;\n\t\t\t\t\t\t\t\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (CharCreatedBy == MISSION_CHAR)\n\t\t\t\t\tanimAssoc->speed = 1.0f;\n\t\t\t\telse\n\t\t\t\t\tanimAssoc->speed = 1.2f - m_randomSeed * 0.4f / MYRAND_MAX;\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nCPed::StopNonPartialAnims(void)\n{\n\tCAnimBlendAssociation *assoc;\n\n\tfor (assoc = RpAnimBlendClumpGetFirstAssociation(GetClump()); assoc; assoc = RpAnimBlendGetNextAssociation(assoc)) {\n\t\tif (!assoc->IsPartial())\n\t\t\tassoc->flags &= ~ASSOC_RUNNING;\n\t}\n}\n\nvoid\nCPed::RestartNonPartialAnims(void)\n{\n\tCAnimBlendAssociation *assoc;\n\n\tfor (assoc = RpAnimBlendClumpGetFirstAssociation(GetClump()); assoc; assoc = RpAnimBlendGetNextAssociation(assoc)) {\n\t\tif (!assoc->IsPartial())\n\t\t\tassoc->SetRun();\n\t}\n}\n\nvoid\nCPed::SetStoredState(void)\n{\n\tif (m_nLastPedState != PED_NONE || !CanPedReturnToState())\n\t\treturn;\n\n\tif (m_nPedState == PED_WANDER_PATH) {\n\t\tbFindNewNodeAfterStateRestore = true;\n\t\tif (m_nMoveState == PEDMOVE_NONE || m_nMoveState == PEDMOVE_STILL)\n\t\t\tm_nMoveState = PEDMOVE_WALK;\n\t}\n\tif (m_nPedState != PED_IDLE) {\n\t\tm_nLastPedState = m_nPedState;\n\t\tif (m_nMoveState >= m_nPrevMoveState)\n\t\t\tm_nPrevMoveState = m_nMoveState;\n\t}\n}\n\nvoid\nCPed::RestorePreviousState(void)\n{\n\tif (!CanSetPedState() || m_nPedState == PED_FALL)\n\t\treturn;\n\n\tif (m_nPedState == PED_GETUP && !bGetUpAnimStarted)\n\t\treturn;\n\n\tif (InVehicle()) {\n\t\tSetPedState(PED_DRIVING);\n\t\tm_nLastPedState = PED_NONE;\n\t} else {\n\t\tif (m_nLastPedState == PED_NONE) {\n\t\t\tif (!IsPlayer() && CharCreatedBy != MISSION_CHAR && m_objective == OBJECTIVE_NONE) {\n\t\t\t\tif (SetWanderPath(CGeneral::GetRandomNumber() & 7) != 0)\n\t\t\t\t\treturn;\n\t\t\t}\n\t\t\tSetIdle();\n\t\t\treturn;\n\t\t}\n\n\t\tswitch (m_nLastPedState) {\n\t\t\tcase PED_IDLE:\n\t\t\t\tSetIdle();\n\t\t\t\tbreak;\n\t\t\tcase PED_WANDER_PATH:\n\t\t\t\tSetPedState(PED_WANDER_PATH);\n\t\t\t\tbIsRunning = false;\n\t\t\t\tif (bFindNewNodeAfterStateRestore) {\n\t\t\t\t\tif (m_pNextPathNode) {\n\t\t\t\t\t\tCVector nextNode = CPathFind::TakeWidthIntoAccountForWandering(m_pNextPathNode, m_randomSeed);\n\t\t\t\t\t\tCVector diff = nextNode - GetPosition();\n\t\t\t\t\t\tif (diff.MagnitudeSqr() < sq(7.0f)) {\n\t\t\t\t\t\t\tSetMoveState(PEDMOVE_WALK);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tSetWanderPath(m_nPedState == PED_FOLLOW_PATH ? m_nPathDir : CGeneral::GetRandomNumber() & 7);\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tSetPedState(m_nLastPedState);\n\t\t\t\tSetMoveState((eMoveState) m_nPrevMoveState);\n\t\t\t\tbreak;\n\t\t}\n\t\tm_nLastPedState = PED_NONE;\n\t}\n}\n\nuint32\nCPed::ScanForThreats(void)\n{\n\tint fearFlags = m_fearFlags;\n\tCVector ourPos = GetPosition();\n\tfloat closestPedDist = 60.0f;\n\tCVector2D explosionPos = GetPosition();\n\tif (fearFlags & PED_FLAG_EXPLOSION && CheckForExplosions(explosionPos)) {\n\t\tm_eventOrThreat = explosionPos;\n\t\treturn PED_FLAG_EXPLOSION;\n\t}\n\t\n\tif (fearFlags & PED_FLAG_GUN) {\n\t\tCPed *shooter = CheckForGunShots();\n\t\tif (shooter && (m_nPedType != shooter->m_nPedType || m_nPedType == PEDTYPE_CIVMALE || m_nPedType == PEDTYPE_CIVFEMALE)) {\n\t\t\tif (!IsGangMember()) {\n\t\t\t\tm_threatEntity = shooter;\n\t\t\t\tm_threatEntity->RegisterReference((CEntity**)&m_threatEntity);\n\t\t\t\treturn PED_FLAG_GUN;\n\t\t\t}\n\n\t\t\tif (CPedType::GetFlag(shooter->m_nPedType) & fearFlags || m_nPedType == PEDTYPE_GANG5) {\n\t\t\t\tif (m_threatEntity)\n\t\t\t\t\tm_threatEntity->CleanUpOldReference(&m_threatEntity);\n\t\t\t\tm_threatEntity = shooter;\n\t\t\t\tm_threatEntity->RegisterReference((CEntity**)&m_threatEntity);\n\t\t\t\treturn CPedType::GetFlag(shooter->m_nPedType);\n\t\t\t}\n\t\t}\n\t}\n\n\tCPed *deadPed;\n\tif (fearFlags & PED_FLAG_DEADPEDS && CharCreatedBy != MISSION_CHAR\n\t\t&& (deadPed = CheckForDeadPeds()) != nil && (deadPed->GetPosition() - ourPos).MagnitudeSqr() < sq(20.0f)\n#ifdef FIX_BUGS\n\t\t&& !deadPed->bIsInWater\n#endif\n\t\t) {\n\t\tm_pEventEntity = deadPed;\n\t\tm_pEventEntity->RegisterReference((CEntity **) &m_pEventEntity);\n\t\treturn PED_FLAG_DEADPEDS;\n\t} else {\n\t\tuint32 flagsOfNearPed = 0;\n\n\t\tCPed *pedToFearFrom = nil;\n\t\tbool weSawOurEnemy = false;\n\t\tbool weMaySeeOurEnemy = false;\n\t\tfloat closestEnemyDist = 60.0f;\n\t\tif ((CTimer::GetFrameCounter() + (uint8)m_randomSeed + 16) & 4) {\n\n\t\t\tfor (int i = 0; i < m_numNearPeds; ++i) {\n\t\t\t\tif (CharCreatedBy == RANDOM_CHAR && m_nearPeds[i]->CharCreatedBy == MISSION_CHAR && !m_nearPeds[i]->IsPlayer()) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// BUG: Putting this here will result in returning the flags of farthest ped to us, since m_nearPeds is sorted by distance.\n\t\t\t\t// \t\tFixed at the bottom of the function.\n\t\t\t\tflagsOfNearPed = CPedType::GetFlag(m_nearPeds[i]->m_nPedType);\n\n\t\t\t\tif (flagsOfNearPed & fearFlags) {\n\t\t\t\t\tif (m_nearPeds[i]->m_fHealth > 0.0f) {\n\t\t\t\t\t\tif (OurPedCanSeeThisOne(m_nearPeds[i], !!bIgnoreThreatsBehindObjects)) {\n\t\t\t\t\t\t\tif (m_nearPeds[i]->m_nPedState == PED_ATTACK) {\n\t\t\t\t\t\t\t\tif (m_nearPeds[i]->m_pedInObjective == this) {\n\n\t\t\t\t\t\t\t\t\tfloat enemyDistSqr = (m_nearPeds[i]->GetPosition() - ourPos).MagnitudeSqr2D();\n\t\t\t\t\t\t\t\t\tif (sq(closestEnemyDist) > enemyDistSqr) {\n\t\t\t\t\t\t\t\t\t\tfloat enemyDist = Sqrt(enemyDistSqr);\n\t\t\t\t\t\t\t\t\t\tweSawOurEnemy = true;\n\t\t\t\t\t\t\t\t\t\tclosestPedDist = enemyDist;\n\t\t\t\t\t\t\t\t\t\tclosestEnemyDist = enemyDist;\n\t\t\t\t\t\t\t\t\t\tpedToFearFrom = m_nearPeds[i];\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tfloat nearPedDistSqr = (m_nearPeds[i]->GetPosition() - ourPos).MagnitudeSqr2D();\n\t\t\t\t\t\t\t\tif (sq(closestPedDist) > nearPedDistSqr && !weSawOurEnemy) {\n\t\t\t\t\t\t\t\t\tclosestPedDist = Sqrt(nearPedDistSqr);\n\t\t\t\t\t\t\t\t\tpedToFearFrom = m_nearPeds[i];\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if (!weSawOurEnemy) {\n\t\t\t\t\t\t\tCPed *nearPed = m_nearPeds[i];\n\t\t\t\t\t\t\tif (nearPed->m_nPedState == PED_ATTACK) {\n\t\t\t\t\t\t\t\tCColPoint foundCol;\n\t\t\t\t\t\t\t\tCEntity *foundEnt;\n\n\t\t\t\t\t\t\t\t// We don't see him yet but he's behind a ped, vehicle or object\n\t\t\t\t\t\t\t\tif (!CWorld::ProcessLineOfSight(ourPos, nearPed->GetPosition(), foundCol, foundEnt,\n\t\t\t\t\t\t\t\t\ttrue, false, false, !!bIgnoreThreatsBehindObjects, false, false, false)) {\n\n\t\t\t\t\t\t\t\t\tif (nearPed->m_pedInObjective == this) {\n\t\t\t\t\t\t\t\t\t\tfloat enemyDistSqr = (m_nearPeds[i]->GetPosition() - ourPos).MagnitudeSqr2D();\n\t\t\t\t\t\t\t\t\t\tif (sq(closestEnemyDist) > enemyDistSqr) {\n\t\t\t\t\t\t\t\t\t\t\tfloat enemyDist = Sqrt(enemyDistSqr);\n\t\t\t\t\t\t\t\t\t\t\tweMaySeeOurEnemy = true;\n\t\t\t\t\t\t\t\t\t\t\tclosestPedDist = enemyDist;\n\t\t\t\t\t\t\t\t\t\t\tclosestEnemyDist = enemyDist;\n\t\t\t\t\t\t\t\t\t\t\tpedToFearFrom = m_nearPeds[i];\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t} else if (!nearPed->GetWeapon()->IsTypeMelee() && !weMaySeeOurEnemy) {\n\t\t\t\t\t\t\t\t\t\tfloat nearPedDistSqr = (m_nearPeds[i]->GetPosition() - ourPos).MagnitudeSqr2D();\n\t\t\t\t\t\t\t\t\t\tif (sq(closestPedDist) > nearPedDistSqr) {\n\t\t\t\t\t\t\t\t\t\t\tweMaySeeOurEnemy = true;\n\t\t\t\t\t\t\t\t\t\t\tclosestPedDist = Sqrt(nearPedDistSqr);\n\t\t\t\t\t\t\t\t\t\t\tpedToFearFrom = m_nearPeds[i];\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tint16 lastVehicle;\n\t\tCEntity* vehicles[8];\n\t\tCWorld::FindObjectsInRange(ourPos, 20.0f, true, &lastVehicle, 6, vehicles, false, true, false, false, false);\n\t\tCVehicle* foundVeh = nil;\n\t\tfor (int i = 0; i < lastVehicle; i++) {\n\t\t\tCVehicle* nearVeh = (CVehicle*)vehicles[i];\n\n\t\t\tCPed *driver = nearVeh->pDriver;\n\t\t\tif (driver) {\n\n\t\t\t\t// BUG: Same bug as above. Fixed at the bottom of function.\n\t\t\t\tflagsOfNearPed = CPedType::GetFlag(driver->m_nPedType);\n\t\t\t\tif (flagsOfNearPed & fearFlags) {\n\n\t\t\t\t\tif (driver->m_fHealth > 0.0f && OurPedCanSeeThisOne(nearVeh->pDriver)) {\n\t\t\t\t\t\t// FIX: Taken from VC\n#ifdef FIX_BUGS\n\t\t\t\t\t\tfloat driverDistSqr = (driver->GetPosition() - ourPos).MagnitudeSqr2D();\n#else\n\t\t\t\t\t\tfloat driverDistSqr = (CVector2D(ourPos) - explosionPos).MagnitudeSqr();\n#endif\n\t\t\t\t\t\tif (sq(closestPedDist) > driverDistSqr) {\n\t\t\t\t\t\t\tclosestPedDist = Sqrt(driverDistSqr);\n\t\t\t\t\t\t\tpedToFearFrom = nearVeh->pDriver;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tm_threatEntity = pedToFearFrom;\n\t\tif (m_threatEntity)\n\t\t\tm_threatEntity->RegisterReference((CEntity **) &m_threatEntity);\n\n#ifdef FIX_BUGS\n\t\tif (pedToFearFrom)\n\t\t\tflagsOfNearPed = CPedType::GetFlag(((CPed*)m_threatEntity)->m_nPedType);\n\t\telse\n\t\t\tflagsOfNearPed = 0;\n#endif\n\n\t\treturn flagsOfNearPed;\n\t}\n}\n\nvoid\nCPed::ScanForDelayedResponseThreats(void)\n{\n\tif (m_threatFlags)\n\t\treturn;\n\n\tm_threatEntity = nil;\n\tm_pEventEntity = nil;\n\tm_threatFlags = ScanForThreats();\n\tif (m_threatFlags) {\n\t\tif (m_threatEntity || m_pEventEntity) {\n\t\t\tm_threatCheckTimer = CTimer::GetTimeInMilliseconds() + m_threatCheckInterval;\n\t\t\treturn;\n\t\t}\n\t\tm_threatFlags = 0;\n\t}\n\tm_threatCheckTimer = 0;\n}\n\nvoid\nCPed::CheckThreatValidity(void)\n{\n\tif (m_threatEntity && !IsEntityPointerValid(m_threatEntity)) {\n\t\tm_threatFlags = 0;\n\t\tm_threatEntity = nil;\n\t}\n\tif (m_pEventEntity && !IsEntityPointerValid(m_pEventEntity)) {\n\t\tm_threatFlags = 0;\n\t\tm_pEventEntity = nil;\n\t}\n\tif (!m_threatEntity && !m_pEventEntity)\n\t\tm_threatFlags = 0;\n}\n\nbool\nCPed::CanUseTorsoWhenLooking(void)\n{\n\tif (m_nPedState != PED_DRIVING && m_nPedState != PED_DRAG_FROM_CAR && !bIsDucking) {\n\t\tif (m_animGroup != ASSOCGRP_SEXYWOMAN && m_animGroup != ASSOCGRP_WOMAN)\n\t\t\treturn true;\n\t}\n\treturn false;\n}\n\nvoid\nCPed::SetLookFlag(float direction, bool keepTryingToLook, bool cancelPrevious)\n{\n\tif (m_lookTimer < CTimer::GetTimeInMilliseconds() || cancelPrevious) {\n\t\tbIsLooking = true;\n\t\tbIsRestoringLook = false;\n\t\tm_fLookDirection = direction;\n\t\tm_pLookTarget = nil;\n\t\tm_lookTimer = 0;\n\t\tbKeepTryingToLook = keepTryingToLook;\n\t\tif (CanUseTorsoWhenLooking()) {\n\t\t\tm_pedIK.m_flags &= ~CPedIK::LOOKAROUND_HEAD_ONLY;\n\t\t}\n\t}\n}\n\nvoid\nCPed::SetLookFlag(CEntity *target, bool keepTryingToLook, bool cancelPrevious)\n{\n\tif (m_lookTimer < CTimer::GetTimeInMilliseconds() || cancelPrevious) {\n\t\tbIsLooking = true;\n\t\tbIsRestoringLook = false;\n\t\tm_pLookTarget = target;\n\t\tm_pLookTarget->RegisterReference((CEntity**)&m_pLookTarget);\n\t\tm_fLookDirection = 999999.0f;\n\t\tm_lookTimer = 0;\n\t\tbKeepTryingToLook = keepTryingToLook;\n\t\tif (CanUseTorsoWhenLooking()) {\n\t\t\tm_pedIK.m_flags &= ~CPedIK::LOOKAROUND_HEAD_ONLY;\n\t\t}\n\t}\n}\n\nvoid\nCPed::ClearLookFlag(void) {\n\tif (bIsLooking) {\n\t\tbIsLooking = false;\n\t\tbIsRestoringLook = true;\n\t\tbShakeFist = false;\n\n\t\tif (CanUseTorsoWhenLooking())\n\t\t\tm_pedIK.m_flags &= ~CPedIK::LOOKAROUND_HEAD_ONLY;\n\n\t\tif (IsPlayer())\n\t\t\tm_lookTimer = CTimer::GetTimeInMilliseconds() + 2000;\n\t\telse\n\t\t\tm_lookTimer = CTimer::GetTimeInMilliseconds() + 4000;\n\n\t\tif (m_nPedState == PED_LOOK_HEADING || m_nPedState == PED_LOOK_ENTITY) {\n\t\t\tClearLook();\n\t\t}\n\t}\n}\n\nvoid\nCPed::MoveHeadToLook(void)\n{\n\tCVector lookPos;\n\n\tif (m_lookTimer && CTimer::GetTimeInMilliseconds() > m_lookTimer) {\n\t\tClearLookFlag();\n\t} \n\n\tif (bIsLooking || bIsRestoringLook)\n\t\tif (!CanUseTorsoWhenLooking())\n\t\t\tm_pedIK.m_flags |= CPedIK::LOOKAROUND_HEAD_ONLY;\n\n\tif (m_pLookTarget) {\n\t\tif (m_pLookTarget->IsPed()) {\n\t\t\t((CPed*)m_pLookTarget)->m_pedIK.GetComponentPosition(lookPos, PED_MID);\n\t\t} else {\n\t\t\tlookPos = m_pLookTarget->GetPosition();\n\t\t}\n\n\t\tif (!m_pedIK.LookAtPosition(lookPos)) {\n\t\t\tif (!bKeepTryingToLook) {\n\t\t\t\tClearLookFlag();\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tif (!bShakeFist || bIsAimingGun || bIsRestoringGun)\n\t\t\treturn;\n\n\t\tif (m_nPedState == PED_ANSWER_MOBILE)\n\t\t\treturn;\n\n\t\tif (m_lookTimer - CTimer::GetTimeInMilliseconds() >= 1000)\n\t\t\treturn;\n\n\t\tbool handFreeToMove = false;\n\t\tAnimationId animToPlay = ANIM_STD_NUM;\n\n\t\tif (!GetWeapon()->IsType2Handed() && GetWeapon()->m_eWeaponType != WEAPONTYPE_ROCKETLAUNCHER)\n\t\t\thandFreeToMove = true;\n\n\t\tif (IsPlayer() && handFreeToMove) {\n\n\t\t\tif (m_pLookTarget->IsPed()) {\n#ifdef FIX_BUGS\n\t\t\t\tif (m_pedStats->m_temper > 49 || ((CPed*)m_pLookTarget)->m_nPedType == PEDTYPE_COP)\n#else\n\t\t\t\tif (m_pedStats->m_temper < 49 || ((CPed*)m_pLookTarget)->m_nPedType == PEDTYPE_COP)\n#endif\n\t\t\t\t\tanimToPlay = ANIM_STD_PARTIAL_FUCKU;\n\t\t\t\telse if(m_pedStats->m_temper < 47)\n\t\t\t\t\tanimToPlay = ANIM_STD_PARTIAL_PUNCH;\n\t\t\t} else {\n\t\t\t\tif (m_pedStats->m_temper > 49 || m_pLookTarget->GetModelIndex() == MI_POLICE)\n\t\t\t\t\tanimToPlay = ANIM_STD_PARTIAL_FUCKU;\n\t\t\t}\n\t\t} else if (handFreeToMove && (CGeneral::GetRandomNumber() & 1)) {\n\t\t\tanimToPlay = ANIM_STD_PARTIAL_FUCKU;\n\t\t}\n\n\t\tif (animToPlay != ANIM_STD_NUM) {\n\t\t\tCAnimBlendAssociation *newAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, animToPlay, 4.0f);\n\n\t\t\tif (newAssoc) {\n\t\t\t\tnewAssoc->flags |= ASSOC_FADEOUTWHENDONE;\n\t\t\t\tnewAssoc->flags |= ASSOC_DELETEFADEDOUT;\n\t\t\t}\n\t\t}\n\t\tbShakeFist = false;\n\t} else if (m_fLookDirection == 999999.0f) {\n\t\tClearLookFlag();\n\t} else if (!m_pedIK.LookInDirection(m_fLookDirection, 0.0f)) {\n\t\tif (!bKeepTryingToLook)\n\t\t\tClearLookFlag();\n\t}\n}\n\nvoid\nCPed::RestoreHeadPosition(void)\n{\n\tif(!CanUseTorsoWhenLooking())\n\t\tm_pedIK.m_flags |= CPedIK::LOOKAROUND_HEAD_ONLY;\n\n\tif (m_pedIK.RestoreLookAt()) {\n\t\tbIsRestoringLook = false;\n\t\tif(CanUseTorsoWhenLooking())\n\t\t\tm_pedIK.m_flags &= ~CPedIK::LOOKAROUND_HEAD_ONLY;\n\t}\n}\n\nvoid\nCPed::SetAimFlag(float angle)\n{\n\tbIsAimingGun = true;\n\tbIsRestoringGun = false;\n\tm_fLookDirection = angle;\n\tm_lookTimer = 0;\n\tm_pLookTarget = nil;\n\tm_pSeekTarget = nil;\n\n\tif (bIsDucking)\n\t\tm_pedIK.m_flags &= ~CPedIK::AIMS_WITH_ARM;\n\n\tif (CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->IsFlagSet(WEAPONFLAG_CANAIM_WITHARM))\n\t\tm_pedIK.m_flags |= CPedIK::AIMS_WITH_ARM;\n\telse\n\t\tm_pedIK.m_flags &= ~CPedIK::AIMS_WITH_ARM;\n}\n\nvoid\nCPed::SetAimFlag(CEntity *to)\n{\n\tbIsAimingGun = true;\n\tbIsRestoringGun = false;\n\tif (m_pLookTarget)\n\t\tm_pLookTarget->CleanUpOldReference(&m_pLookTarget);\n\tm_pLookTarget = to;\n\tm_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget);\n\tif (m_pSeekTarget)\n\t\tm_pSeekTarget->CleanUpOldReference(&m_pSeekTarget);\n\tm_pSeekTarget = to;\n\tm_pSeekTarget->RegisterReference((CEntity **) &m_pSeekTarget);\n\tm_lookTimer = 0;\n}\n\nvoid\nCPed::ClearAimFlag(void)\n{\n\tif (bIsAimingGun) {\n\t\tbIsAimingGun = false;\n\t\tbIsRestoringGun = true;\n\t\tm_pedIK.m_flags &= ~CPedIK::AIMS_WITH_ARM;\n\t\tm_lookTimer = 0;\n\t}\n\n\tif (IsPlayer())\n\t\t((CPlayerPed*)this)->m_fFPSMoveHeading = 0.0f;\n}\n\nvoid\nCPed::AimGun(void)\n{\n\tCVector vector;\n\n\tif (IsPlayer() && bIsDucking)\n\t\tm_pedIK.m_flags &= ~CPedIK::AIMS_WITH_ARM;\n\n\tif (m_pSeekTarget) {\n\t\tif (m_pSeekTarget->IsPed()) {\n\t\t\t((CPed*)m_pSeekTarget)->m_pedIK.GetComponentPosition(vector, PED_MID);\n\t\t} else {\n\t\t\tvector = m_pSeekTarget->GetPosition();\n\t\t}\n\n\t\tif (!IsPlayer())\n\t\t\tSay(SOUND_PED_ATTACK);\n\n\t\tbCanPointGunAtTarget = m_pedIK.PointGunAtPosition(vector);\n\t\tif (m_pLookTarget != m_pSeekTarget) {\n\t\t\tSetLookFlag(m_pSeekTarget, true, true);\n\t\t}\n\n\t} else {\n\t\tif (IsPlayer()) {\n\t\t\tbCanPointGunAtTarget = m_pedIK.PointGunInDirection(m_fLookDirection, ((CPlayerPed*)this)->m_fFPSMoveHeading);\n\t\t} else {\n\t\t\tbCanPointGunAtTarget = m_pedIK.PointGunInDirection(m_fLookDirection, 0.0f);\n\t\t}\n\t}\n}\n\nvoid\nCPed::RestoreGunPosition(void)\n{\n\tif (bIsLooking) {\n\t\tm_pedIK.m_flags &= ~CPedIK::LOOKAROUND_HEAD_ONLY;\n\t\tbIsRestoringGun = false;\n\t} else if (m_pedIK.RestoreGunPosn()) {\n\t\tbIsRestoringGun = false;\n\t} else {\n\t\tif (IsPlayer())\n\t\t\t((CPlayerPed*)this)->m_fFPSMoveHeading = 0.0f;\n\t}\n}\n\nbool\nCPed::CanWeRunAndFireWithWeapon(void)\n{\n\treturn CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->IsFlagSet(WEAPONFLAG_CANAIM_WITHARM);\n}\n\nvoid\nCPed::ScanForInterestingStuff(void)\n{\n\tif (!IsPedInControl())\n\t\treturn;\n\n\tif (m_objective != OBJECTIVE_NONE)\n\t\treturn;\n\n\tif (CharCreatedBy == MISSION_CHAR)\n\t\treturn;\n\n\tLookForSexyPeds();\n\tLookForSexyCars();\n\tif (LookForInterestingNodes())\n\t\treturn;\n\n\tif (m_nPedType == PEDTYPE_CRIMINAL && m_carJackTimer < CTimer::GetTimeInMilliseconds()) {\n\t\t// Find a car to steal or a ped to mug if we haven't already decided to steal a car\n\t\tif (CGeneral::GetRandomNumber() % 100 < 10) {\n\t\t\tint mostExpensiveVehAround = -1;\n\t\t\tint bestMonetaryValue = 0;\n\n\t\t\tCVector pos = GetPosition();\n\t\t\tint16 lastVehicle;\n\t\t\tCEntity *vehicles[8];\n\t\t\tCWorld::FindObjectsInRange(pos, 10.0f, true, &lastVehicle, 6, vehicles, false, true, false, false, false);\n\n\t\t\tfor (int i = 0; i < lastVehicle; i++) {\n\t\t\t\tCVehicle* veh = (CVehicle*)vehicles[i];\n\n\t\t\t\tif (veh->VehicleCreatedBy != MISSION_VEHICLE) {\n\t\t\t\t\tif (veh->m_vecMoveSpeed.Magnitude() <= 0.1f && veh->IsVehicleNormal()\n\t\t\t\t\t\t&& veh->IsCar() && bestMonetaryValue < veh->pHandling->nMonetaryValue) {\n\t\t\t\t\t\tmostExpensiveVehAround = i;\n\t\t\t\t\t\tbestMonetaryValue = veh->pHandling->nMonetaryValue;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (bestMonetaryValue > 2000 && mostExpensiveVehAround != -1 && vehicles[mostExpensiveVehAround]) {\n\t\t\t\tSetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, vehicles[mostExpensiveVehAround]);\n\t\t\t\tm_carJackTimer = CTimer::GetTimeInMilliseconds() + 5000;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tm_carJackTimer = CTimer::GetTimeInMilliseconds() + 5000;\n\t\t} else if (m_objective != OBJECTIVE_MUG_CHAR && !(CGeneral::GetRandomNumber() & 7)) {\n\t\t\tCPed *charToMug = nil;\n\t\t\tfor (int i = 0; i < m_numNearPeds; ++i) {\n\t\t\t\tCPed *nearPed = m_nearPeds[i];\n\n\t\t\t\tif ((nearPed->GetPosition() - GetPosition()).MagnitudeSqr() > sq(7.0f))\n\t\t\t\t\tbreak;\n\n\t\t\t\tif ((nearPed->m_nPedType == PEDTYPE_CIVFEMALE || nearPed->m_nPedType == PEDTYPE_CIVMALE\n\t\t\t\t\t|| nearPed->m_nPedType == PEDTYPE_CRIMINAL || nearPed->m_nPedType == PEDTYPE_UNUSED1\n\t\t\t\t\t|| nearPed->m_nPedType == PEDTYPE_PROSTITUTE)\n\t\t\t\t\t&& nearPed->CharCreatedBy != MISSION_CHAR\n\t\t\t\t\t&& nearPed->IsPedShootable()\n\t\t\t\t\t&& nearPed->m_objective != OBJECTIVE_MUG_CHAR) {\n\t\t\t\t\tcharToMug = nearPed;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (charToMug)\n\t\t\t\tSetObjective(OBJECTIVE_MUG_CHAR, charToMug);\n\n\t\t\tm_carJackTimer = CTimer::GetTimeInMilliseconds() + 5000;\n\t\t}\n\t}\n\n\tif (m_nPedState == PED_WANDER_PATH) {\n\t\tif (CGeneral::GetRandomNumberInRange(0.0f, 1.0f) < 0.5f) {\n\t\t\tif (CTimer::GetTimeInMilliseconds() > m_chatTimer) {\n\t\t\t\tfor (int i = 0; i < m_numNearPeds; i ++) {\n\t\t\t\t\tif (m_nearPeds[i] && m_nearPeds[i]->m_nPedState == PED_WANDER_PATH) {\n\t\t\t\t\t\tif ((GetPosition() - m_nearPeds[i]->GetPosition()).Magnitude() < 1.8f\n\t\t\t\t\t\t\t&& CanSeeEntity(m_nearPeds[i])\n\t\t\t\t\t\t\t&& m_nearPeds[i]->CanSeeEntity(this)\n\t\t\t\t\t\t\t&& WillChat(m_nearPeds[i])) {\n\n\t\t\t\t\t\t\tint time = CGeneral::GetRandomNumber() % 4000 + 10000;\n\t\t\t\t\t\t\tSetChat(m_nearPeds[i], time);\n\t\t\t\t\t\t\tm_nearPeds[i]->SetChat(this, time);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tm_chatTimer = CTimer::GetTimeInMilliseconds() + 200;\n\t\t}\n\t}\n}\n\nbool\nCPed::WillChat(CPed *stranger)\n{\n\tif (m_pNextPathNode && m_pLastPathNode) {\n\t\tif (m_pNextPathNode != m_pLastPathNode && ThePaths.TestCrossesRoad(m_pNextPathNode, m_pLastPathNode)) {\n\t\t\treturn false;\n\t\t}\n\t}\n\tif (m_nSurfaceTouched == SURFACE_TARMAC)\n\t\treturn false;\n\tif (stranger == this)\n\t\treturn false;\n\tif (m_nPedType == stranger->m_nPedType)\n\t\treturn true;\n\tif (m_nPedType == PEDTYPE_CRIMINAL)\n\t\treturn false;\n\tif (stranger->m_nPedType == PEDTYPE_COP)\n\t\treturn false;\n\tif (stranger->IsPlayer())\n\t\treturn false;\n\tif ((IsGangMember() || stranger->IsGangMember()) && m_nPedType != stranger->m_nPedType)\n\t\treturn false;\n\treturn true;\n}\n\nvoid\nCPed::CalculateNewVelocity(void)\n{\n\tif (IsPedInControl()) {\n\t\tfloat headAmount = DEGTORAD(m_headingRate) * CTimer::GetTimeStep();\n\t\tm_fRotationCur = CGeneral::LimitRadianAngle(m_fRotationCur);\n\t\tfloat limitedRotDest = CGeneral::LimitRadianAngle(m_fRotationDest);\n\n\t\tif (m_fRotationCur - PI > limitedRotDest) {\n\t\t\t\tlimitedRotDest += 2 * PI;\n\t\t} else if(PI + m_fRotationCur < limitedRotDest) {\n\t\t\tlimitedRotDest -= 2 * PI;\n\t\t}\n\n\t\tfloat neededTurn = limitedRotDest - m_fRotationCur;\n\t\tif (neededTurn <= headAmount) {\n\t\t\tif (neededTurn > (-headAmount))\n\t\t\t\tm_fRotationCur += neededTurn;\n\t\t\telse\n\t\t\t\tm_fRotationCur -= headAmount;\n\t\t} else {\n\t\t\tm_fRotationCur += headAmount;\n\t\t}\n\t}\n\n\tCVector2D forward(Sin(m_fRotationCur), Cos(m_fRotationCur));\n\n\tm_moved.x = CrossProduct2D(m_vecAnimMoveDelta, forward); // (m_vecAnimMoveDelta.x * Cos(m_fRotationCur)) + -Sin(m_fRotationCur) * m_vecAnimMoveDelta.y;\n\tm_moved.y = DotProduct2D(m_vecAnimMoveDelta, forward);  // m_vecAnimMoveDelta.y* Cos(m_fRotationCur) + (m_vecAnimMoveDelta.x * Sin(m_fRotationCur));\n\n\tif (CTimer::GetTimeStep() >= 0.01f) {\n\t\tm_moved = m_moved * (1 / CTimer::GetTimeStep());\n\t} else {\n\t\tm_moved = m_moved * (1 / 100.0f);\n\t}\n\n\tif ((!TheCamera.Cams[TheCamera.ActiveCam].GetWeaponFirstPersonOn() && !TheCamera.Cams[0].Using3rdPersonMouseCam())\n\t\t|| FindPlayerPed() != this || !CanStrafeOrMouseControl()) {\n\n\t\tif (FindPlayerPed() == this)\n\t\t\tFindPlayerPed()->m_fWalkAngle = 0.0f;\n\t\treturn;\n\t}\n\n\tfloat walkAngle = WorkOutHeadingForMovingFirstPerson(m_fRotationCur);\n\tfloat pedSpeed = m_moved.Magnitude();\n\tfloat localWalkAngle = CGeneral::LimitRadianAngle(walkAngle - m_fRotationCur);\n\n\tif (localWalkAngle < -0.5f * PI) {\n\t\tlocalWalkAngle += PI;\n\t} else if (localWalkAngle > 0.5f * PI) {\n\t\tlocalWalkAngle -= PI;\n\t}\n\n\t// Interestingly this part is responsible for diagonal walking.\n\tif (localWalkAngle > -DEGTORAD(50.0f) && localWalkAngle < DEGTORAD(50.0f)) {\n\t\tTheCamera.Cams[TheCamera.ActiveCam].m_fPlayerVelocity = pedSpeed;\n\t\tm_moved = CVector2D(-Sin(walkAngle), Cos(walkAngle)) * pedSpeed;\n\t}\n\n\tCAnimBlendAssociation *idleAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_IDLE);\n\tCAnimBlendAssociation *fightAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_FIGHT_IDLE);\n\tif(!fightAssoc)\n\t\tfightAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_IDLE_TIRED);\n\n\tif(!fightAssoc)\n\t\tfightAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_MELEE_IDLE_FIGHTMODE);\n\n\tif ((!idleAssoc || idleAssoc->blendAmount < 0.5f) && !fightAssoc && !bIsDucking) {\n\t\tLimbOrientation newUpperLegs;\n\t\tnewUpperLegs.yaw = localWalkAngle;\n\n\t\tif (newUpperLegs.yaw < -DEGTORAD(100.0f)) {\n\t\t\tnewUpperLegs.yaw += PI;\n\t\t} else if (newUpperLegs.yaw > DEGTORAD(100.0f)) {\n\t\t\tnewUpperLegs.yaw -= PI;\n\t\t}\n\n\t\tif (newUpperLegs.yaw > -DEGTORAD(50.0f) && newUpperLegs.yaw < DEGTORAD(50.0f)) {\n\t\t\tnewUpperLegs.pitch = 0.1f;\n\t\t\tRwV3d Xaxis = { 1.0f, 0.0f, 0.0f };\n\t\t\tRwV3d Zaxis = { 0.0f, 0.0f, 1.0f };\n\t\t\tRtQuatRotate(&m_pFrames[PED_UPPERLEGL]->hanimFrame->q, &Zaxis, RADTODEG(newUpperLegs.pitch), rwCOMBINEPOSTCONCAT);\n\t\t\tRtQuatRotate(&m_pFrames[PED_UPPERLEGL]->hanimFrame->q, &Xaxis, RADTODEG(newUpperLegs.yaw), rwCOMBINEPOSTCONCAT);\n\t\t\tRtQuatRotate(&m_pFrames[PED_UPPERLEGR]->hanimFrame->q, &Zaxis, RADTODEG(newUpperLegs.pitch), rwCOMBINEPOSTCONCAT);\n\t\t\tRtQuatRotate(&m_pFrames[PED_UPPERLEGR]->hanimFrame->q, &Xaxis, RADTODEG(newUpperLegs.yaw), rwCOMBINEPOSTCONCAT);\n\t\t\tbDontAcceptIKLookAts = true;\n\t\t}\n\t}\n}\n\nfloat\nCPed::WorkOutHeadingForMovingFirstPerson(float offset)\n{\n\tif (!IsPlayer())\n\t\treturn 0.0f;\n\n\tCPad *pad0 = CPad::GetPad(0);\n\tfloat leftRight = pad0->GetPedWalkLeftRight();\n\tfloat upDown = pad0->GetPedWalkUpDown();\n\tfloat &angle = ((CPlayerPed*)this)->m_fWalkAngle;\n\n\tif (upDown != 0.0f) {\n\t\tangle = CGeneral::GetRadianAngleBetweenPoints(0.0f, 0.0f, -leftRight, upDown);\n\t} else {\n\t\tif (leftRight < 0.0f)\n\t\t\tangle = HALFPI;\n\t\telse if (leftRight > 0.0f)\n\t\t\tangle = -HALFPI;\n\t}\n\n\treturn CGeneral::LimitRadianAngle(offset + angle);\n}\n\nvoid\nCPed::UpdatePosition(void)\n{\n\tif (CReplay::IsPlayingBack() || !bIsStanding || m_attachedTo)\n\t\treturn;\n\n\tCVector2D velocityChange;\n\n\tSetHeading(m_fRotationCur);\n\tif (m_pCurrentPhysSurface) {\n\t\tCVector2D velocityOfSurface;\n\t\tif (!IsPlayer() && m_pCurrentPhysSurface->IsVehicle() && ((CVehicle*)m_pCurrentPhysSurface)->IsBoat()) {\n\n\t\t\t// It seems R* didn't like m_vecOffsetFromPhysSurface for boats\n\t\t\tCVector offsetToSurface = GetPosition() - m_pCurrentPhysSurface->GetPosition();\n\t\t\toffsetToSurface.z -= FEET_OFFSET;\n\n\t\t\tCVector surfaceMoveVelocity = m_pCurrentPhysSurface->m_vecMoveSpeed;\n\t\t\tCVector surfaceTurnVelocity = CrossProduct(m_pCurrentPhysSurface->m_vecTurnSpeed, offsetToSurface);\n\n\t\t\t// Also we use that weird formula instead of friction if it's boat\n\t\t\tfloat slideMult = -m_pCurrentPhysSurface->m_vecTurnSpeed.MagnitudeSqr();\n\t\t\tvelocityOfSurface = slideMult * offsetToSurface * CTimer::GetTimeStep() + (surfaceTurnVelocity + surfaceMoveVelocity);\n\t\t\tm_vecMoveSpeed.z = slideMult * offsetToSurface.z * CTimer::GetTimeStep() + (surfaceTurnVelocity.z + surfaceMoveVelocity.z);\n\t\t} else {\n\t\t\tvelocityOfSurface = m_pCurrentPhysSurface->GetSpeed(m_vecOffsetFromPhysSurface);\n\t\t}\n\t\t// Reminder: m_moved is displacement from walking/running.\n\t\tvelocityChange = m_moved + velocityOfSurface - m_vecMoveSpeed;\n\t\tm_fRotationCur += m_pCurrentPhysSurface->m_vecTurnSpeed.z * CTimer::GetTimeStep();\n\t\tm_fRotationDest += m_pCurrentPhysSurface->m_vecTurnSpeed.z * CTimer::GetTimeStep();\n\t} else if (m_nSurfaceTouched == SURFACE_STEEP_CLIFF && (m_vecDamageNormal.x != 0.0f || m_vecDamageNormal.y != 0.0f)) {\n\t\t// Ped got damaged by steep slope\n\t\tm_vecMoveSpeed = CVector(0.0f, 0.0f, -0.001f);\n\t\t// some kind of\n\t\tCVector2D reactionForce = m_vecDamageNormal;\n\t\treactionForce.Normalise();\n\n\t\tvelocityChange = 0.02f * reactionForce + m_moved;\n\n\t\tfloat reactionAndVelocityDotProd = DotProduct2D(reactionForce, velocityChange);\n\t\t// they're in same direction\n\t\tif (reactionAndVelocityDotProd < 0.0f) {\n\t\t\tvelocityChange -= reactionAndVelocityDotProd * reactionForce;\n\t\t}\n\t} else {\n\t\tvelocityChange = m_moved - m_vecMoveSpeed;\n\t}\n\t\n\t// Take time step into account\n\tif (m_pCurrentPhysSurface && (!m_pCurrentPhysSurface->bInfiniteMass || m_pCurrentPhysSurface->m_phy_flagA08)) {\n\t\tfloat speedChange = velocityChange.Magnitude();\n\t\tfloat changeMult = speedChange;\n\t\tif (m_nPedState == PED_DIE && m_pCurrentPhysSurface->IsVehicle()) {\n\t\t\tchangeMult = 0.002f * CTimer::GetTimeStep();\n\t\t} else if (!(m_pCurrentPhysSurface->IsVehicle() && ((CVehicle*)m_pCurrentPhysSurface)->IsBoat())) {\n\t\t\tchangeMult = 0.01f * CTimer::GetTimeStep();\n\t\t}\n\n\t\tif (speedChange > changeMult) {\n\t\t\tvelocityChange = velocityChange * (changeMult / speedChange);\n\t\t}\n\t}\n\tm_vecMoveSpeed.x += velocityChange.x;\n\tm_vecMoveSpeed.y += velocityChange.y;\n}\n\nvoid\nCPed::CalculateNewOrientation(void)\n{\n\tif (CReplay::IsPlayingBack() || !IsPedInControl())\n\t\treturn;\n\n\tSetHeading(m_fRotationCur);\n}\n\nvoid\nCPed::ClearAll(void)\n{\n\tif (!IsPedInControl() && m_nPedState != PED_DEAD)\n\t\treturn;\n\n\tSetPedState(PED_NONE);\n\tSetMoveState(PEDMOVE_NONE);\n\tm_pSeekTarget = nil;\n\tm_vecSeekPos = CVector(0.0f, 0.0f, 0.0f);\n\tm_fleeFromPos = CVector2D(0.0f, 0.0f);\n\tm_fleeFrom = nil;\n\tm_fleeTimer = 0;\n\tm_threatEx = nil;\n\tbUsesCollision = true;\n\tClearPointGunAt();\n\tbIsPointingGunAt = false;\n\tbRenderPedInCar = true;\n\tbKnockedUpIntoAir = false;\n\tbKnockedOffBike = false;\n\tm_pCollidingEntity = nil;\n}\n\nvoid\nCPed::ProcessBuoyancy(void)\n{\n\tfloat buoyancyLevel = 1.1f;\n\tstatic uint32 nGenerateRaindrops = 0;\n\tstatic uint32 nGenerateWaterCircles = 0;\n\tCRGBA color;\n\n\tif (bInVehicle)\n\t\treturn;\n\n\tCVector buoyancyPoint;\n\tCVector buoyancyImpulse;\n\n\tif (DyingOrDead())\n\t\tbuoyancyLevel = 1.8f;\n\n\tif (mod_Buoyancy.ProcessBuoyancy(this, GRAVITY * m_fMass * buoyancyLevel, &buoyancyPoint, &buoyancyImpulse)) {\n\t\tbTouchingWater = true;\n\t\tCEntity *entity;\n\t\tCColPoint point;\n\t\tif (CWorld::ProcessVerticalLine(GetPosition(), GetPosition().z - 3.0f, point, entity, false, true, false, false, false, false, nil)\n\t\t\t&& entity->IsVehicle() && ((CVehicle*)entity)->IsBoat() && !entity->bRenderScorched) {\n\t\t\tbIsInWater = false;\n\t\t\treturn;\n\t\t}\n\t\tcolor.r = (0.5f * CTimeCycle::GetDirectionalRed() + CTimeCycle::GetAmbientRed()) * 127.5f;\n\t\tcolor.g = (0.5f * CTimeCycle::GetDirectionalBlue() + CTimeCycle::GetAmbientBlue()) * 127.5f;\n\t\tcolor.b = (0.5f * CTimeCycle::GetDirectionalGreen() + CTimeCycle::GetAmbientGreen()) * 127.5f;\n\t\tcolor.a = CGeneral::GetRandomNumberInRange(48.0f, 96.0f);\n\t\tbIsInWater = true;\n\t\tApplyMoveForce(buoyancyImpulse);\n\t\tif (!DyingOrDead()) {\n\t\t\tif (bTryingToReachDryLand) {\n\t\t\t\tif (buoyancyImpulse.z / m_fMass > GRAVITY * 0.4f * CTimer::GetTimeStep()) {\n\t\t\t\t\tbTryingToReachDryLand = false;\n\t\t\t\t\tCVector pos = GetPosition();\n\t\t\t\t\tif (PlacePedOnDryLand()) {\n\t\t\t\t\t\tif (m_fHealth > 20.0f)\n\t\t\t\t\t\t\tInflictDamage(nil, WEAPONTYPE_DROWNING, 15.0f, PEDPIECE_TORSO, false);\n\n\t\t\t\t\t\tif (bIsInTheAir) {\n\t\t\t\t\t\t\tRpAnimBlendClumpSetBlendDeltas(GetClump(), ASSOC_PARTIAL, -1000.0f);\n\t\t\t\t\t\t\tbIsInTheAir = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tpos.z = pos.z - 0.8f;\n\t\t\t\t\t\tCParticleObject::AddObject(POBJECT_PED_WATER_SPLASH, pos, CVector(0.0f, 0.0f, 0.0f), 0.0f, 50, color, true);\n\t\t\t\t\t\tm_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);\n\t\t\t\t\t\tSetPedState(PED_IDLE);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tfloat speedMult = 0.0f;\n\t\tif (buoyancyImpulse.z / m_fMass > GRAVITY * CTimer::GetTimeStep()\n\t\t\t|| mod_Buoyancy.m_waterlevel > GetPosition().z + 0.6f) {\n\t\t\tspeedMult = pow(0.9f, CTimer::GetTimeStep());\n\t\t\tm_vecMoveSpeed.x *= speedMult;\n\t\t\tm_vecMoveSpeed.y *= speedMult;\n\t\t\tm_vecMoveSpeed.z *= speedMult;\n\t\t\tbIsStanding = false;\n\t\t\tbIsDrowning = true;\n\t\t\tInflictDamage(nil, WEAPONTYPE_DROWNING, 3.0f * CTimer::GetTimeStep(), PEDPIECE_TORSO, 0);\n\t\t}\n\t\tif (buoyancyImpulse.z / m_fMass > GRAVITY * 0.25f * CTimer::GetTimeStep()) {\n\t\t\tif (speedMult == 0.0f) {\n\t\t\t\tspeedMult = pow(0.9f, CTimer::GetTimeStep());\n\t\t\t}\n\t\t\tm_vecMoveSpeed.x *= speedMult;\n\t\t\tm_vecMoveSpeed.y *= speedMult;\n\t\t\tif (m_vecMoveSpeed.z >= -0.1f) {\n\t\t\t\tif (m_vecMoveSpeed.z < -0.04f)\n\t\t\t\t\tm_vecMoveSpeed.z = -0.02f;\n\t\t\t} else {\n\t\t\t\tm_vecMoveSpeed.z = -0.01f;\n\t\t\t\tDMAudio.PlayOneShot(m_audioEntityId, SOUND_SPLASH, 0.0f);\n\t\t\t\tCVector aBitForward = 2.2f * m_vecMoveSpeed + GetPosition();\n\t\t\t\tfloat level = 0.0f;\n\t\t\t\tif (CWaterLevel::GetWaterLevel(aBitForward, &level, false))\n\t\t\t\t\taBitForward.z = level;\n\n\t\t\t\tCParticleObject::AddObject(POBJECT_PED_WATER_SPLASH, aBitForward, CVector(0.0f, 0.0f, 0.1f), 0.0f, 200, color, true);\n\t\t\t\tnGenerateRaindrops = CTimer::GetTimeInMilliseconds() + 80;\n\t\t\t\tnGenerateWaterCircles = CTimer::GetTimeInMilliseconds() + 100;\n\t\t\t}\n\t\t}\n\t\tif (nGenerateWaterCircles && CTimer::GetTimeInMilliseconds() >= nGenerateWaterCircles) {\n\t\t\tCVector pos = GetPosition();\n\t\t\tfloat level = 0.0f;\n\t\t\tif (CWaterLevel::GetWaterLevel(pos, &level, false))\n\t\t\t\tpos.z = level;\n\n\t\t\tif (pos.z != 0.0f) {\n\t\t\t\tnGenerateWaterCircles = 0;\n\t\t\t\tfor(int i = 0; i < 4; i++) {\n\t\t\t\t\tpos.x += CGeneral::GetRandomNumberInRange(-0.75f, 0.75f);\n\t\t\t\t\tpos.y += CGeneral::GetRandomNumberInRange(-0.75f, 0.75f);\n\t\t\t\t\tCParticle::AddParticle(PARTICLE_RAIN_SPLASH_BIGGROW, pos, CVector(0.0f, 0.0f, 0.0f), nil, 0.0f, color, 0, 0, 0, 0);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (nGenerateRaindrops && CTimer::GetTimeInMilliseconds() >= nGenerateRaindrops) {\n\t\t\tCVector pos = GetPosition();\n\t\t\tfloat level = 0.0f;\n\t\t\tif (CWaterLevel::GetWaterLevel(pos, &level, false))\n\t\t\t\tpos.z = level;\n\n\t\t\tif (pos.z >= 0.0f) {\n\t\t\t\tpos.z += 0.25f;\n\t\t\t\tnGenerateRaindrops = 0;\n\t\t\t\tCParticleObject::AddObject(POBJECT_SPLASHES_AROUND, pos, CVector(0.0f, 0.0f, 0.0f), 4.5f, 1500, CRGBA(0,0,0,0), true);\n\t\t\t}\n\t\t}\n\t} else\n\t\tbTouchingWater = false;\n}\n\nvoid\nCPed::ProcessControl(void)\n{\n\tCColPoint foundCol;\n\tCEntity *foundEnt = nil;\n\n\tif (CTimer::GetFrameCounter() + m_randomSeed % 32 == 0)\n\t\tPruneReferences();\n\n\tint alpha = CVisibilityPlugins::GetClumpAlpha(GetClump());\n\tif (!bFadeOut) {\n\t\tif (alpha < 255) {\n\t\t\talpha += 16;\n\t\t\tif (alpha > 255)\n\t\t\t\talpha = 255;\n\t\t}\n\t} else {\n\t\talpha -= 8;\n\t\tif (alpha < 0)\n\t\t\talpha = 0;\n\t}\n\n\tCVisibilityPlugins::SetClumpAlpha(GetClump(), alpha);\n\tbIsShooting = false;\n\tbDonePositionOutOfCollision = false;\n\tBuildPedLists();\n\tbIsInWater = false;\n\tbIsDrowning = false;\n\tProcessBuoyancy();\n\n\tif (m_nPedState != PED_ARRESTED) {\n\t\tif (m_nPedState == PED_DEAD) {\n\t\t\tDeadPedMakesTyresBloody();\n\t\t\tif (CGame::nastyGame && !bIsInWater) {\n\t\t\t\tuint32 remainingBloodyFpTime = CTimer::GetTimeInMilliseconds() - m_bloodyFootprintCountOrDeathTime;\n\t\t\t\tfloat timeDependentDist;\n\t\t\t\tif (remainingBloodyFpTime >= 2000) {\n\t\t\t\t\tif (remainingBloodyFpTime <= 7000)\n\t\t\t\t\t\ttimeDependentDist = (remainingBloodyFpTime - 2000) / 5000.0f * 0.75f;\n\t\t\t\t\telse\n\t\t\t\t\t\ttimeDependentDist = 0.75f;\n\t\t\t\t} else {\n\t\t\t\t\ttimeDependentDist = 0.0f;\n\t\t\t\t}\n\n\t\t\t\tfor (int i = 0; i < m_numNearPeds; ++i) {\n\t\t\t\t\tCPed *nearPed = m_nearPeds[i];\n\t\t\t\t\tif (!nearPed->DyingOrDead()) {\n\t\t\t\t\t\tCVector dist = nearPed->GetPosition() - GetPosition();\n\t\t\t\t\t\tif (dist.MagnitudeSqr() < sq(timeDependentDist)) {\n\t\t\t\t\t\t\tnearPed->m_bloodyFootprintCountOrDeathTime = 200;\n\t\t\t\t\t\t\tnearPed->bDoBloodyFootprints = true;\n\t\t\t\t\t\t\tif (nearPed->IsPlayer()) {\n\t\t\t\t\t\t\t\tif (!nearPed->bIsLooking && nearPed->m_nPedState != PED_ATTACK) {\n\t\t\t\t\t\t\t\t\tint16 camMode = TheCamera.Cams[TheCamera.ActiveCam].Mode;\n\t\t\t\t\t\t\t\t\tif (camMode != CCam::MODE_SNIPER\n\t\t\t\t\t\t\t\t\t\t&& camMode != CCam::MODE_CAMERA\n\t\t\t\t\t\t\t\t\t\t&& camMode != CCam::MODE_ROCKETLAUNCHER\n\t\t\t\t\t\t\t\t\t\t&& camMode != CCam::MODE_M16_1STPERSON\n\t\t\t\t\t\t\t\t\t\t&& camMode != CCam::MODE_1STPERSON\n\t\t\t\t\t\t\t\t\t\t&& camMode != CCam::MODE_HELICANNON_1STPERSON\n\t\t\t\t\t\t\t\t\t\t&& !TheCamera.Cams[TheCamera.ActiveCam].GetWeaponFirstPersonOn()) {\n\n\t\t\t\t\t\t\t\t\t\tnearPed->SetLookFlag(this, true);\n\t\t\t\t\t\t\t\t\t\tnearPed->SetLookTimer(500);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (remainingBloodyFpTime > 2000) {\n\t\t\t\t\tCVector bloodPos = GetPosition();\n\t\t\t\t\tif (remainingBloodyFpTime - 2000 >= 5000) {\n\t\t\t\t\t\tif (!m_deadBleeding) {\n\t\t\t\t\t\t\tCShadows::AddPermanentShadow(SHADOWTYPE_DARK, gpBloodPoolTex, &bloodPos,\n\t\t\t\t\t\t\t\t0.75f, 0.0f, 0.0f, -0.75f, 255, 255, 0, 0, 4.0f, 40000, 1.0f);\n\t\t\t\t\t\t\tm_deadBleeding = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tCShadows::StoreStaticShadow(\n\t\t\t\t\t\t\t(uintptr)this + 17, SHADOWTYPE_DARK, gpBloodPoolTex, &bloodPos,\n\t\t\t\t\t\t\t(remainingBloodyFpTime - 2000) / 5000.0f * 0.75f, 0.0f,\n\t\t\t\t\t\t\t0.0f, (remainingBloodyFpTime - 2000) / 5000.0f * -0.75f,\n\t\t\t\t\t\t\t255, 255, 0, 0, 4.0f, 1.0f, 40.0f, false, 0.0f);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (ServiceTalkingWhenDead())\n\t\t\t\tServiceTalking();\n\n\t\t\tif (bIsInWater) {\n\t\t\t\tbIsStanding = false;\n\t\t\t\tbWasStanding = false;\n\t\t\t\tCPhysical::ProcessControl();\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tbWasStanding = false;\n\t\tif (bIsStanding) {\n\t\t\tif (!CWorld::bForceProcessControl) {\n\t\t\t\tif (m_pCurrentPhysSurface && m_pCurrentPhysSurface->bIsInSafePosition) {\n\t\t\t\t\tbWasPostponed = true;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (!IsPedInControl() || m_nWaitState != WAITSTATE_FALSE || 0.01f * CTimer::GetTimeStep() <= m_fDistanceTravelled\n\t\t\t|| (m_nStoredMoveState != PEDMOVE_WALK && m_nStoredMoveState != PEDMOVE_RUN && m_nStoredMoveState != PEDMOVE_SPRINT))\n\t\t\tm_panicCounter = 0;\n\t\telse if (m_panicCounter < 50)\n\t\t\t++m_panicCounter;\n\n\t\tif (m_fHealth <= 1.0f && m_nPedState <= PED_STATES_NO_AI && !bIsInTheAir && !bIsLanding)\n\t\t\tSetDie();\n\n\t\tif (bIsStanding)\n\t\t\tbPushedAlongByCar = false;\n\n\t\tbCollidedWithMyVehicle = false;\n\n\t\tCEntity *collidingEnt = m_pDamageEntity;\n\t\tif (!bUsesCollision || ((!collidingEnt || m_fDamageImpulse <= 0.0f) && (!IsPlayer() || !bIsStuck)) || m_nPedState == PED_DIE) {\t\n\t\t\tbHitSomethingLastFrame = false;\n\t\t\tif (m_nPedStateTimer <= 500 && bIsInTheAir) {\n\t\t\t\tif (m_nPedStateTimer)\n\t\t\t\t\tm_nPedStateTimer--;\n\t\t\t} else if (m_nPedStateTimer < 1001) {\n\t\t\t\tm_nPedStateTimer = 0;\n\t\t\t}\n\t\t} else if (!GetPedAttractorManager()->IsInQueue(this, m_attractor)) {\n\t\t\tif (m_panicCounter == 50 && IsPedInControl()) {\n\t\t\t\tSetWaitState(WAITSTATE_STUCK, nil);\n\t\t\t\t// Leftover\n\t\t\t\t/*\n\t\t\t\tif (m_nPedType < PEDTYPE_COP) {\n\n\t\t\t\t} else {\n\n\t\t\t\t}\n\t\t\t\t*/\n\t\t\t} else if (collidingEnt) {\n\t\t\t\tswitch (collidingEnt->GetType())\n\t\t\t\t{\n\t\t\t\tcase ENTITY_TYPE_BUILDING:\n\t\t\t\tcase ENTITY_TYPE_OBJECT:\n\t\t\t\t{\n\t\t\t\t\tCBaseModelInfo *collidingModel = CModelInfo::GetModelInfo(collidingEnt->GetModelIndex());\n\t\t\t\t\tCColModel *collidingCol = collidingModel->GetColModel();\n\t\t\t\t\tif (collidingEnt->IsObject() && ((CObject*)collidingEnt)->m_nSpecialCollisionResponseCases != COLLRESPONSE_FENCEPART\n\t\t\t\t\t\t|| collidingCol->boundingBox.max.x < 3.0f\n\t\t\t\t\t\t&& collidingCol->boundingBox.max.y < 3.0f) {\n\n\t\t\t\t\t\tif (!IsPlayer()) {\n\t\t\t\t\t\t\tSetDirectionToWalkAroundObject(collidingEnt);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (IsPlayer()) {\n\t\t\t\t\t\tbHitSomethingLastFrame = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tfloat angleToFaceWhenHit = CGeneral::GetRadianAngleBetweenPoints(\n\t\t\t\t\t\tGetPosition().x,\n\t\t\t\t\t\tGetPosition().y,\n\t\t\t\t\t\tm_vecDamageNormal.x + GetPosition().x,\n\t\t\t\t\t\tm_vecDamageNormal.y + GetPosition().y);\n\n\t\t\t\t\tfloat neededTurn = Abs(m_fRotationCur - angleToFaceWhenHit);\n\n\t\t\t\t\tif (neededTurn > PI)\n\t\t\t\t\t\tneededTurn = TWOPI - neededTurn;\n\n\t\t\t\t\tfloat oldDestRot = CGeneral::LimitRadianAngle(m_fRotationDest);\n\n\t\t\t\t\tif (m_nPedState == PED_FOLLOW_PATH) {\n\t\t\t\t\t\tif (DotProduct(m_vecDamageNormal, GetForward()) < -0.866f && CanPedJumpThis(collidingEnt, &m_vecDamageNormal)) {\n\t\t\t\t\t\t\tSetJump();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (m_pedInObjective &&\n\t\t\t\t\t\t(m_objective == OBJECTIVE_GOTO_CHAR_ON_FOOT || m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT)) {\n\n\t\t\t\t\t\tif (m_pedInObjective->IsPlayer()\n\t\t\t\t\t\t\t&& (neededTurn < DEGTORAD(20.0f) || m_panicCounter > 10)) {\n\t\t\t\t\t\t\tif (CanPedJumpThis(collidingEnt)) {\n\t\t\t\t\t\t\t\tSetJump();\n\t\t\t\t\t\t\t} else if (m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT) {\n\t\t\t\t\t\t\t\tif (m_nPedType == PEDTYPE_COP && m_nWaitState != WAITSTATE_LOOK_ABOUT)\n\t\t\t\t\t\t\t\t\t((CCopPed*)this)->field_624++;\n\n\t\t\t\t\t\t\t\tSetWaitState(WAITSTATE_LOOK_ABOUT, nil);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tSetWaitState(WAITSTATE_PLAYANIM_TAXI, nil);\n\t\t\t\t\t\t\t\tm_headingRate = 0.0f;\n\t\t\t\t\t\t\t\tSetLookFlag(m_pedInObjective, true);\n\t\t\t\t\t\t\t\tSetLookTimer(3000);\n\t\t\t\t\t\t\t\tSay(SOUND_PED_TAXI_CALL);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (m_pLookTarget)\n\t\t\t\t\t\t\t\tm_pLookTarget->CleanUpOldReference(&m_pLookTarget);\n\n\t\t\t\t\t\t\tm_pLookTarget = m_pedInObjective;\n\t\t\t\t\t\t\tm_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget);\n\t\t\t\t\t\t\tTurnBody();\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (m_nPedType != PEDTYPE_COP && neededTurn < DEGTORAD(15.0f) && m_nWaitState == WAITSTATE_FALSE) {\n\t\t\t\t\t\t\tif ((m_nStoredMoveState == PEDMOVE_RUN || m_nStoredMoveState == PEDMOVE_SPRINT) && m_vecDamageNormal.z < 0.3f) {\n\t\t\t\t\t\t\t\tCAnimBlendAssociation *runAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_RUN);\n\t\t\t\t\t\t\t\tif (!runAssoc)\n\t\t\t\t\t\t\t\t\trunAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_RUNFAST);\n\n\t\t\t\t\t\t\t\tif (runAssoc && runAssoc->blendAmount > 0.9f && runAssoc->IsRunning()) {\n\t\t\t\t\t\t\t\t\tSetWaitState(WAITSTATE_HITWALL, nil);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (m_nPedState == PED_FLEE_POS) {\n\t\t\t\t\t\t\tCVector2D fleePos = collidingEnt->GetPosition();\n\t\t\t\t\t\t\tuint32 oldFleeTimer = m_fleeTimer;\n\t\t\t\t\t\t\tSetFlee(fleePos, 5000);\n\t\t\t\t\t\t\tif (oldFleeTimer != m_fleeTimer)\n\t\t\t\t\t\t\t\tm_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 500;\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (m_nPedState == PED_FLEE_ENTITY && (neededTurn < DEGTORAD(25.0f) || m_panicCounter > 10)) {\n\t\t\t\t\t\t\t\tm_collidingThingTimer = CTimer::GetTimeInMilliseconds() + 2500;\n\t\t\t\t\t\t\t\tm_collidingEntityWhileFleeing = collidingEnt;\n\t\t\t\t\t\t\t\tm_collidingEntityWhileFleeing->RegisterReference((CEntity **) &m_collidingEntityWhileFleeing);\n\n\t\t\t\t\t\t\t\tif (m_nWaitState != WAITSTATE_HITWALL)\n\t\t\t\t\t\t\t\t\tSetWaitState(WAITSTATE_TURN180, nil);\n\t\t\t\t\t\t\t\tm_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 5000;\n\t\t\t\t\t\t\t\tFlee();\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tif (neededTurn < DEGTORAD(60.0f)) {\n\t\t\t\t\t\t\t\t\tCVector posToHead = m_vecDamageNormal * 4.0f;\n\t\t\t\t\t\t\t\t\tposToHead.z = 0.0f;\n\t\t\t\t\t\t\t\t\tposToHead += GetPosition();\n\t\t\t\t\t\t\t\t\tint closestNodeId = ThePaths.FindNodeClosestToCoors(posToHead, PATH_PED,\n\t\t\t\t\t\t\t\t\t\t999999.9f, false, false);\n\t\t\t\t\t\t\t\t\tfloat angleToFace;\n\n\t\t\t\t\t\t\t\t\tif (m_objective != OBJECTIVE_KILL_CHAR_ON_FOOT && m_objective != OBJECTIVE_KILL_CHAR_ANY_MEANS) {\n\t\t\t\t\t\t\t\t\t\tif (m_nPedState != PED_SEEK_POS && m_nPedState != PED_SEEK_CAR) {\n\t\t\t\t\t\t\t\t\t\t\tif (m_nPedState == PED_WANDER_PATH) {\n\t\t\t\t\t\t\t\t\t\t\t\tm_pNextPathNode = &ThePaths.m_pathNodes[closestNodeId];\n\t\t\t\t\t\t\t\t\t\t\t\tCVector bestCoords = CPathFind::TakeWidthIntoAccountForWandering(m_pNextPathNode, m_randomSeed);\n\t\t\t\t\t\t\t\t\t\t\t\tangleToFace = CGeneral::GetRadianAngleBetweenPoints(\n\t\t\t\t\t\t\t\t\t\t\t\t\tbestCoords.x, bestCoords.y,\n\t\t\t\t\t\t\t\t\t\t\t\t\tGetPosition().x, GetPosition().y);\n\n\t\t\t\t\t\t\t\t\t\t\t} else if (m_nPedState == PED_FOLLOW_PATH) {\n\t\t\t\t\t\t\t\t\t\t\t\tCVector bestCoords = m_pathNodesToGo[m_nCurPathNodeId]->GetPosition();\n\t\t\t\t\t\t\t\t\t\t\t\tangleToFace = CGeneral::GetRadianAngleBetweenPoints(\n\t\t\t\t\t\t\t\t\t\t\t\t\tbestCoords.x, bestCoords.y,\n\t\t\t\t\t\t\t\t\t\t\t\t\tGetPosition().x, GetPosition().y);\n\n\t\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\t\tif (ThePaths.m_pathNodes[closestNodeId].GetX() == 0.0f\n\t\t\t\t\t\t\t\t\t\t\t\t\t|| ThePaths.m_pathNodes[closestNodeId].GetY() == 0.0f) {\n\t\t\t\t\t\t\t\t\t\t\t\t\tposToHead = (3.0f * m_vecDamageNormal) + GetPosition();\n\t\t\t\t\t\t\t\t\t\t\t\t\tposToHead.x += (CGeneral::GetRandomNumber() % 512) / 250.0f - 1.0f;\n\t\t\t\t\t\t\t\t\t\t\t\t\tposToHead.y += (CGeneral::GetRandomNumber() % 512) / 250.0f - 1.0f;\n\t\t\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\t\t\tposToHead.x = ThePaths.m_pathNodes[closestNodeId].GetX();\n\t\t\t\t\t\t\t\t\t\t\t\t\tposToHead.y = ThePaths.m_pathNodes[closestNodeId].GetY();\n\t\t\t\t\t\t\t\t\t\t\t\t\tposToHead.z = ThePaths.m_pathNodes[closestNodeId].GetZ();\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\tangleToFace = CGeneral::GetRadianAngleBetweenPoints(\n\t\t\t\t\t\t\t\t\t\t\t\t\tposToHead.x, posToHead.y,\n\t\t\t\t\t\t\t\t\t\t\t\t\tGetPosition().x, GetPosition().y);\n\n\t\t\t\t\t\t\t\t\t\t\t\tif (m_nPedState != PED_FOLLOW_PATH)\n\t\t\t\t\t\t\t\t\t\t\t\t\tm_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 500;\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\tangleToFace = CGeneral::GetRadianAngleBetweenPoints(\n\t\t\t\t\t\t\t\t\t\t\t\tThePaths.m_pathNodes[closestNodeId].GetX(),\n\t\t\t\t\t\t\t\t\t\t\t\tThePaths.m_pathNodes[closestNodeId].GetY(),\n\t\t\t\t\t\t\t\t\t\t\t\tGetPosition().x,\n\t\t\t\t\t\t\t\t\t\t\t\tGetPosition().y);\n\n\t\t\t\t\t\t\t\t\t\t\tCVector2D distToNode = ThePaths.m_pathNodes[closestNodeId].GetPosition() - GetPosition();\n\t\t\t\t\t\t\t\t\t\t\tCVector2D distToSeekPos = m_vecSeekPos - GetPosition();\n\n\t\t\t\t\t\t\t\t\t\t\tif (DotProduct2D(distToNode, distToSeekPos) < 0.0f) {\n\t\t\t\t\t\t\t\t\t\t\t\tm_fRotationCur = m_fRotationDest;\n\t\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tfloat angleToFaceAwayDamage = CGeneral::GetRadianAngleBetweenPoints(\n\t\t\t\t\t\t\t\t\t\t\tm_vecDamageNormal.x,\n\t\t\t\t\t\t\t\t\t\t\tm_vecDamageNormal.y,\n\t\t\t\t\t\t\t\t\t\t\t0.0f,\n\t\t\t\t\t\t\t\t\t\t\t0.0f);\n\n\t\t\t\t\t\t\t\t\t\tif (angleToFaceAwayDamage < m_fRotationCur)\n\t\t\t\t\t\t\t\t\t\t\tangleToFaceAwayDamage += TWOPI;\n\n\t\t\t\t\t\t\t\t\t\tfloat neededTurn = angleToFaceAwayDamage - m_fRotationCur;\n\n\t\t\t\t\t\t\t\t\t\tif (neededTurn <= PI) {\n\t\t\t\t\t\t\t\t\t\t\tangleToFace = 0.5f * neededTurn + m_fRotationCur;\n\t\t\t\t\t\t\t\t\t\t\tm_fRotationCur += DEGTORAD(m_pedStats->m_headingChangeRate) * 2.0f;\n\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\tangleToFace = m_fRotationCur - (TWOPI - neededTurn) * 0.5f;\n\t\t\t\t\t\t\t\t\t\t\tm_fRotationCur -= DEGTORAD(m_pedStats->m_headingChangeRate) * 2.0f;\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\tm_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 200;\n\t\t\t\t\t\t\t\t\t\tif (m_nPedType == PEDTYPE_COP) {\n\t\t\t\t\t\t\t\t\t\t\tif (m_pedInObjective) {\n\t\t\t\t\t\t\t\t\t\t\t\tfloat angleToLookCriminal = CGeneral::GetRadianAngleBetweenPoints(\n\t\t\t\t\t\t\t\t\t\t\t\t\tm_pedInObjective->GetPosition().x,\n\t\t\t\t\t\t\t\t\t\t\t\t\tm_pedInObjective->GetPosition().y,\n\t\t\t\t\t\t\t\t\t\t\t\t\tGetPosition().x,\n\t\t\t\t\t\t\t\t\t\t\t\t\tGetPosition().y);\n\n\t\t\t\t\t\t\t\t\t\t\t\tangleToLookCriminal = CGeneral::LimitRadianAngle(angleToLookCriminal);\n\t\t\t\t\t\t\t\t\t\t\t\tangleToFace = CGeneral::LimitRadianAngle(angleToFace);\n\n\t\t\t\t\t\t\t\t\t\t\t\tif (angleToLookCriminal < angleToFace)\n\t\t\t\t\t\t\t\t\t\t\t\t\tangleToLookCriminal += TWOPI;\n\n\t\t\t\t\t\t\t\t\t\t\t\tfloat neededTurnToCriminal = angleToLookCriminal - angleToFace;\n\n\t\t\t\t\t\t\t\t\t\t\t\tif (neededTurnToCriminal > DEGTORAD(150.0f) && neededTurnToCriminal < DEGTORAD(210.0f)) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t((CCopPed*)this)->m_bStopAndShootDisabledZone = true;\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tm_fRotationDest = CGeneral::LimitRadianAngle(angleToFace);\n\n\t\t\t\t\t\t\t\t\tif (m_fRotationCur - PI > m_fRotationDest) {\n\t\t\t\t\t\t\t\t\t\tm_fRotationDest += TWOPI;\n\t\t\t\t\t\t\t\t\t} else if (PI + m_fRotationCur < m_fRotationDest) {\n\t\t\t\t\t\t\t\t\t\tm_fRotationDest -= TWOPI;\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\tif (oldDestRot == m_fRotationDest && CTimer::GetTimeInMilliseconds() > m_nPedStateTimer) {\n\t\t\t\t\t\t\t\t\t\tm_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 200;\n\t\t\t\t\t\t\t\t\t\tm_fRotationDest += HALFPI;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (m_nPedState != PED_WANDER_PATH && m_nPedState != PED_FLEE_ENTITY)\n\t\t\t\t\t\tm_pNextPathNode = nil;\n\n\t\t\t\t\tbHitSomethingLastFrame = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase ENTITY_TYPE_VEHICLE:\n\t\t\t\t{\n\t\t\t\t\tCVehicle* collidingVeh = ((CVehicle*)collidingEnt);\n\t\t\t\t\tfloat collidingVehSpeedSqr = collidingVeh->m_vecMoveSpeed.MagnitudeSqr();\n\n\t\t\t\t\tif (collidingVeh == m_pMyVehicle)\n\t\t\t\t\t\tbCollidedWithMyVehicle = true;\n\n\t\t\t\t\tfloat oldHealth = m_fHealth;\n\t\t\t\t\tbool playerSufferSound = false;\n\n\t\t\t\t\tif (collidingVehSpeedSqr <= 1.0f / 400.0f) {\n\t\t\t\t\t\tif (IsPedInControl()\n\t\t\t\t\t\t\t&& (!IsPlayer()\n\t\t\t\t\t\t\t\t|| m_objective == OBJECTIVE_GOTO_AREA_ON_FOOT\n\t\t\t\t\t\t\t\t|| m_objective == OBJECTIVE_RUN_TO_AREA\n\t\t\t\t\t\t\t\t|| m_objective == OBJECTIVE_SPRINT_TO_AREA\n\t\t\t\t\t\t\t\t|| m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER\n\t\t\t\t\t\t\t\t|| IsUseAttractorObjective(m_objective))) {\n\n\t\t\t\t\t\t\tif (collidingVeh != m_pCurrentPhysSurface || IsPlayer()) {\n\t\t\t\t\t\t\t\tif (!bVehEnterDoorIsBlocked) {\n\t\t\t\t\t\t\t\t\tif (collidingVeh->GetStatus() != STATUS_PLAYER || CharCreatedBy == MISSION_CHAR) {\n\n\t\t\t\t\t\t\t\t\t\tif (m_nPedState == PED_SEEK_CAR) {\n\t\t\t\t\t\t\t\t\t\t\tSetDirectionToWalkAroundObject(collidingVeh);\n\t\t\t\t\t\t\t\t\t\t\tCWorld::Players[CWorld::PlayerInFocus].m_nLastBumpPlayerCarTimer = m_nPedStateTimer;\n\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\tSetDirectionToWalkAroundVehicle(collidingVeh);\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tif (CTimer::GetTimeInMilliseconds() >= CWorld::Players[CWorld::PlayerInFocus].m_nLastBumpPlayerCarTimer\n\t\t\t\t\t\t\t\t\t\t\t|| m_nPedStateTimer >= CTimer::GetTimeInMilliseconds()) {\n\n\t\t\t\t\t\t\t\t\t\t\tif (m_nPedState == PED_SEEK_CAR) {\n\t\t\t\t\t\t\t\t\t\t\t\tSetDirectionToWalkAroundObject(collidingVeh);\n\t\t\t\t\t\t\t\t\t\t\t\tCWorld::Players[CWorld::PlayerInFocus].m_nLastBumpPlayerCarTimer = m_nPedStateTimer;\n\t\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\t\tSetDirectionToWalkAroundVehicle(collidingVeh);\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t} else if (m_fleeFrom != collidingVeh) {\n\t\t\t\t\t\t\t\t\t\t\tSetFlee(collidingVeh, 4000);\n\t\t\t\t\t\t\t\t\t\t\tbUsePedNodeSeek = false;\n\t\t\t\t\t\t\t\t\t\t\tSetMoveState(PEDMOVE_WALK);\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tfloat angleLeftToCompleteTurn = Abs(m_fRotationCur - m_fRotationDest);\n\t\t\t\t\t\t\t\tif (angleLeftToCompleteTurn < 0.01f && CanPedJumpThis(collidingVeh)) {\n\t\t\t\t\t\t\t\t\tSetJump();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if (IsPlayer() && !bIsInTheAir) {\n\n\t\t\t\t\t\t\tif (IsPedInControl() && ((CPlayerPed*)this)->m_fMoveSpeed == 0.0f\n\t\t\t\t\t\t\t\t&& !bIsLooking && CTimer::GetTimeInMilliseconds() > m_lookTimer && collidingVeh->pDriver) {\n\n\t\t\t\t\t\t\t\t((CPlayerPed*)this)->AnnoyPlayerPed(false);\n\t\t\t\t\t\t\t\tSetLookFlag(collidingVeh, true);\n\t\t\t\t\t\t\t\tSetLookTimer(1300);\n\n\t\t\t\t\t\t\t\teWeaponType weaponType = GetWeapon()->m_eWeaponType;\n\t\t\t\t\t\t\t\tuint32 weaponSlot = CWeaponInfo::GetWeaponInfo(weaponType)->m_nWeaponSlot;\n\t\t\t\t\t\t\t\tif (weaponType == WEAPONTYPE_UNARMED\n\t\t\t\t\t\t\t\t\t|| weaponSlot == 3\n\t\t\t\t\t\t\t\t\t|| weaponSlot == 5\n\t\t\t\t\t\t\t\t\t|| weaponSlot == 1) {\n\t\t\t\t\t\t\t\t\tbShakeFist = true;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tSetLookFlag(collidingVeh, true);\n\t\t\t\t\t\t\t\tSetLookTimer(500);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tfloat adjustedImpulse = m_fDamageImpulse;\n\t\t\t\t\t\tif (IsPlayer()) {\n\t\t\t\t\t\t\tif (bIsStanding) {\n\t\t\t\t\t\t\t\tfloat forwardVecAndDamageDirDotProd = DotProduct(m_vecAnimMoveDelta.y * GetForward(), m_vecDamageNormal);\n\t\t\t\t\t\t\t\tif (forwardVecAndDamageDirDotProd < 0.0f) {\n\t\t\t\t\t\t\t\t\tadjustedImpulse = forwardVecAndDamageDirDotProd * m_fMass + m_fDamageImpulse;\n\t\t\t\t\t\t\t\t\tif (adjustedImpulse < 0.0f)\n\t\t\t\t\t\t\t\t\t\tadjustedImpulse = 0.0f;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (m_fMass / 20.0f < adjustedImpulse)\n\t\t\t\t\t\t\tDMAudio.PlayOneShot(collidingVeh->m_audioEntityId, SOUND_CAR_PED_COLLISION, adjustedImpulse);\n\n\t\t\t\t\t\tif (IsPlayer()) {\n\t\t\t\t\t\t\tif (adjustedImpulse > 20.0f)\n\t\t\t\t\t\t\t\tadjustedImpulse = 20.0f;\n\n\t\t\t\t\t\t\tif (adjustedImpulse > 5.0f) {\n\t\t\t\t\t\t\t\tif (adjustedImpulse <= 13.0f)\n\t\t\t\t\t\t\t\t\tplayerSufferSound = true;\n\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\tSay(SOUND_PED_DAMAGE);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tCColModel* collidingCol = CModelInfo::GetModelInfo(collidingVeh->m_modelIndex)->GetColModel();\n\t\t\t\t\t\t\tCVector colMinVec = collidingCol->boundingBox.min;\n\t\t\t\t\t\t\tCVector colMaxVec = collidingCol->boundingBox.max;\n\n\t\t\t\t\t\t\tCVector vehColCenterDist = collidingVeh->GetMatrix() * ((colMinVec + colMaxVec) * 0.5f) - GetPosition();\n\n\t\t\t\t\t\t\t// TLVC = To look vehicle center\n\n\t\t\t\t\t\t\tfloat angleToVehFront = collidingVeh->GetForward().Heading();\n\t\t\t\t\t\t\tfloat angleDiffFromLookingFrontTLVC = angleToVehFront - vehColCenterDist.Heading();\n\t\t\t\t\t\t\tangleDiffFromLookingFrontTLVC = CGeneral::LimitRadianAngle(angleDiffFromLookingFrontTLVC);\n\n\t\t\t\t\t\t\t// I don't know why do we use that\n\t\t\t\t\t\t\tfloat vehTopRightHeading = Atan2(colMaxVec.x - colMinVec.x, colMaxVec.y - colMinVec.y);\n\n\t\t\t\t\t\t\tCVector vehDist = GetPosition() - collidingVeh->GetPosition();\n\t\t\t\t\t\t\tvehDist.Normalise();\n\n\t\t\t\t\t\t\tfloat vehRightVecAndSpeedDotProd;\n\n\t\t\t\t\t\t\tif (Abs(angleDiffFromLookingFrontTLVC) >= vehTopRightHeading && Abs(angleDiffFromLookingFrontTLVC) < PI - vehTopRightHeading) {\n\t\t\t\t\t\t\t\tif (angleDiffFromLookingFrontTLVC <= 0.0f) {\n\t\t\t\t\t\t\t\t\tvehRightVecAndSpeedDotProd = DotProduct(collidingVeh->GetRight(), collidingVeh->m_vecMoveSpeed);\n\n\t\t\t\t\t\t\t\t\t// vehRightVecAndSpeedDotProd < 0.1f = Vehicle being overturned or spinning to it's right?\n\t\t\t\t\t\t\t\t\tif (collidingVehSpeedSqr > 1.0f / 100.0f && vehRightVecAndSpeedDotProd < 0.1f) {\n\n\t\t\t\t\t\t\t\t\t\t// Car's right faces towards us and isn't coming directly to us\n\t\t\t\t\t\t\t\t\t\tif (DotProduct(collidingVeh->GetRight(), GetForward()) < 0.0f\n\t\t\t\t\t\t\t\t\t\t\t&& DotProduct(vehDist, collidingVeh->m_vecMoveSpeed) > 0.0f) {\n\t\t\t\t\t\t\t\t\t\t\tSetEvasiveStep(collidingVeh, 1);\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tvehRightVecAndSpeedDotProd = DotProduct(-1.0f * collidingVeh->GetRight(), collidingVeh->m_vecMoveSpeed);\n\n\t\t\t\t\t\t\t\t\tif (collidingVehSpeedSqr > 1.0f / 100.0f && vehRightVecAndSpeedDotProd < 0.1f) {\n\t\t\t\t\t\t\t\t\t\tif (DotProduct(collidingVeh->GetRight(), GetForward()) > 0.0f\n\t\t\t\t\t\t\t\t\t\t\t&& DotProduct(vehDist, collidingVeh->m_vecMoveSpeed) > 0.0f) {\n\t\t\t\t\t\t\t\t\t\t\tSetEvasiveStep(collidingVeh, 1);\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tvehRightVecAndSpeedDotProd = DotProduct(vehDist, collidingVeh->m_vecMoveSpeed);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (vehRightVecAndSpeedDotProd <= 0.1f) {\n\t\t\t\t\t\t\t\tif (m_nPedState != PED_FIGHT) {\n\t\t\t\t\t\t\t\t\tSetLookFlag(collidingVeh, true);\n\t\t\t\t\t\t\t\t\tSetLookTimer(700);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tbIsStanding = false;\n\t\t\t\t\t\t\t\tCVector2D collidingEntMoveDir = -collidingVeh->m_vecMoveSpeed;\n\t\t\t\t\t\t\t\tint dir = GetLocalDirection(collidingEntMoveDir);\n\t\t\t\t\t\t\t\tSetFall(1000, (AnimationId)(dir + ANIM_STD_HIGHIMPACT_FRONT), false);\n\n\t\t\t\t\t\t\t\tfloat damage;\n\t\t\t\t\t\t\t\tif (collidingVeh->m_modelIndex == MI_TRAIN) {\n\t\t\t\t\t\t\t\t\tdamage = 50.0f;\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tdamage = 20.0f;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tInflictDamage(collidingVeh, WEAPONTYPE_RAMMEDBYCAR, damage, PEDPIECE_TORSO, dir);\n\t\t\t\t\t\t\t\tSay(SOUND_PED_DAMAGE);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tKillPedWithCar(collidingVeh, m_fDamageImpulse);\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (m_pCollidingEntity != collidingEnt)\n\t\t\t\t\t\t\tbPushedAlongByCar = true;\n\t\t\t\t\t}\n\t\t\t\t\tif (m_fHealth < oldHealth && playerSufferSound)\n\t\t\t\t\t\tSay(SOUND_PED_HIT);\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase ENTITY_TYPE_PED:\n\t\t\t\t{\n\t\t\t\t\tCollideWithPed((CPed*)collidingEnt);\n\t\t\t\t\tif (((CPed*)collidingEnt)->IsPlayer()) {\n\t\t\t\t\t\tCPlayerPed *player = ((CPlayerPed*)collidingEnt);\n\t\t\t\t\t\tSay(SOUND_PED_CHAT);\n\t\t\t\t\t\tif (m_nMoveState > PEDMOVE_STILL && player->IsPedInControl()) {\n\t\t\t\t\t\t\tif (player->m_fMoveSpeed < 1.0f) {\n\t\t\t\t\t\t\t\tif (!player->bIsLooking) {\n\t\t\t\t\t\t\t\t\tif (CTimer::GetTimeInMilliseconds() > player->m_lookTimer) {\n\t\t\t\t\t\t\t\t\t\tplayer->AnnoyPlayerPed(false);\n\t\t\t\t\t\t\t\t\t\tplayer->SetLookFlag(this, true);\n\t\t\t\t\t\t\t\t\t\tplayer->SetLookTimer(1300);\n\t\t\t\t\t\t\t\t\t\teWeaponType weaponType = player->GetWeapon()->m_eWeaponType;\n\t\t\t\t\t\t\t\t\t\tuint32 weaponSlot = CWeaponInfo::GetWeaponInfo(weaponType)->m_nWeaponSlot;\n\t\t\t\t\t\t\t\t\t\tif (weaponType == WEAPONTYPE_UNARMED\n\t\t\t\t\t\t\t\t\t\t\t|| weaponSlot == 3\n\t\t\t\t\t\t\t\t\t\t\t|| weaponSlot == 5\n\t\t\t\t\t\t\t\t\t\t\t|| weaponSlot == 1) {\n\t\t\t\t\t\t\t\t\t\t\tplayer->bShakeFist = true;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tCVector forceDir;\n\t\t\tif (!bIsInTheAir && m_nPedState != PED_JUMP && m_fDamageImpulse > 0.0f) {\n\t\t\t\tforceDir = m_vecDamageNormal;\n\t\t\t\tforceDir.z = 0.0f;\n\t\t\t\tif (!bIsStanding) {\n\t\t\t\t\tforceDir *= 4.0f;\n\t\t\t\t} else {\n\t\t\t\t\tforceDir *= 0.5f;\n\t\t\t\t}\n\n\t\t\t\tApplyMoveForce(forceDir);\n\t\t\t}\n\t\t\tif ((bIsInTheAir && !DyingOrDead()) || (!bIsStanding && !bWasStanding && m_nPedState == PED_FALL)) {\n\t\t\t\tif (m_nPedStateTimer > 0 && m_nPedStateTimer <= 1000) {\n\t\t\t\t\tforceDir = GetPosition() - m_vecHitLastPos;\n\t\t\t\t} else {\n\t\t\t\t\tm_nPedStateTimer = 0;\n\t\t\t\t\tm_vecHitLastPos = GetPosition();\n\t\t\t\t\tforceDir = CVector(0.0f, 0.0f, 0.0f);\n\t\t\t\t}\n\n\t\t\t\tCVector offsetToCheck;\n\t\t\t\tm_nPedStateTimer++;\n\n\t\t\t\tfloat adjustedTs = Max(CTimer::GetTimeStep(), 0.01f);\n\n\t\t\t\tCPad *pad0 = CPad::GetPad(0);\n\t\t\t\tif ((m_nPedStateTimer <= 50.0f / (4.0f * adjustedTs) || m_nPedStateTimer * 0.01f <= forceDir.MagnitudeSqr())\n\t\t\t\t\t&& (m_nCollisionRecords <= 1 || m_nPedStateTimer <= 50.0f / (2.0f * adjustedTs) || m_nPedStateTimer * 1.0f / 250.0f <= Abs(forceDir.z))) {\n\n\t\t\t\t\tif (m_nCollisionRecords == 1 && m_aCollisionRecords[0] != nil && m_aCollisionRecords[0]->IsBuilding()\n\t\t\t\t\t\t&& m_nPedStateTimer > 50.0f / (2.0f * adjustedTs) && m_nPedStateTimer * 1.0f / 250.0f > Abs(forceDir.z)) {\n\t\t\t\t\t\toffsetToCheck.x = -forceDir.y;\n\t\t\t\t\t\toffsetToCheck.z = 1.0f;\n\t\t\t\t\t\toffsetToCheck.y = forceDir.x;\n\t\t\t\t\t\toffsetToCheck.Normalise();\n\n\t\t\t\t\t\tCVector posToCheck = GetPosition() + offsetToCheck;\n\n\t\t\t\t\t\t// These are either obstacle or ground to land, I don't know which one.\n\t\t\t\t\t\tfloat obstacleForFlyingZ, obstacleForFlyingOtherDirZ;\n\t\t\t\t\t\tCColPoint obstacleForFlying, obstacleForFlyingOtherDir;\n\n\t\t\t\t\t\t// Check is there any room for being knocked up in reverse direction of force\n\t\t\t\t\t\tif (CWorld::ProcessVerticalLine(posToCheck, -20.0f, obstacleForFlying, foundEnt, true, false, false, false, false, false, nil)) {\n\t\t\t\t\t\t\tobstacleForFlyingZ = obstacleForFlying.point.z;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tobstacleForFlyingZ = 500.0f;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\tposToCheck = GetPosition() - offsetToCheck;\n\n\t\t\t\t\t\t// Now check for direction of force this time\n\t\t\t\t\t\tif (CWorld::ProcessVerticalLine(posToCheck, -20.0f, obstacleForFlyingOtherDir, foundEnt, true, false, false, false, false, false, nil)) {\n\t\t\t\t\t\t\tobstacleForFlyingOtherDirZ = obstacleForFlyingOtherDir.point.z;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tobstacleForFlyingOtherDirZ = 501.0f;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tuint8 flyDir = 0;\n\t\t\t\t\t\tfloat feetZ = GetPosition().z - FEET_OFFSET;\n#ifdef FIX_BUGS\n\t\t\t\t\t\tif (obstacleForFlyingZ > feetZ && obstacleForFlyingOtherDirZ < 501.0f)\n\t\t\t\t\t\t\tflyDir = 1;\n\t\t\t\t\t\telse if (obstacleForFlyingOtherDirZ > feetZ && obstacleForFlyingZ < 500.0f)\n\t\t\t\t\t\t\tflyDir = 2;\n#else\n\t\t\t\t\t\tif ((obstacleForFlyingZ > feetZ && obstacleForFlyingOtherDirZ < 500.0f) || (obstacleForFlyingZ > feetZ && obstacleForFlyingOtherDirZ > feetZ))\n\t\t\t\t\t\t\tflyDir = 1;\n\t\t\t\t\t\telse if (obstacleForFlyingOtherDirZ > feetZ && obstacleForFlyingZ < 499.0f)\n\t\t\t\t\t\t\tflyDir = 2;\n#endif\n\n\t\t\t\t\t\tif (flyDir != 0 && !bHeadStuckInCollision) {\n\t\t\t\t\t\t\tSetPosition((flyDir == 2 ? obstacleForFlyingOtherDir.point : obstacleForFlying.point));\n\t\t\t\t\t\t\tGetMatrix().GetPosition().z += FEET_OFFSET;\n\t\t\t\t\t\t\tGetMatrix().UpdateRW();\n\t\t\t\t\t\t\tSetLanding();\n\t\t\t\t\t\t\tbIsStanding = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (obstacleForFlyingZ < obstacleForFlyingOtherDirZ) {\n\t\t\t\t\t\t\toffsetToCheck *= -1.0f;\n\t\t\t\t\t\t}\n\t\t\t\t\t\toffsetToCheck.z = 1.0f;\n\t\t\t\t\t\tforceDir = 4.0f * offsetToCheck;\n\t\t\t\t\t\tforceDir.z = 4.0f;\n\t\t\t\t\t\tApplyMoveForce(forceDir);\n\n\t\t\t\t\t\t// What was that for?? It pushes player inside of collision sometimes and kills him.\n#ifdef FIX_BUGS\n\t\t\t\t\t\tif (!IsPlayer())\n#endif\n\t\t\t\t\t\tGetMatrix().GetPosition() += 0.25f * offsetToCheck;\n\n\t\t\t\t\t\tm_fRotationCur = CGeneral::GetRadianAngleBetweenPoints(offsetToCheck.x, offsetToCheck.y, 0.0f, 0.0f);\n\t\t\t\t\t\tm_fRotationCur = CGeneral::LimitRadianAngle(m_fRotationCur);\n\t\t\t\t\t\tm_fRotationDest = m_fRotationCur;\n\t\t\t\t\t\tSetHeading(m_fRotationCur);\n\n\t\t\t\t\t\tif (m_nPedState != PED_FALL && !bIsPedDieAnimPlaying) {\n\t\t\t\t\t\t\tSetFall(1000, ANIM_STD_HIGHIMPACT_BACK, true);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbIsInTheAir = false;\n\t\t\t\t\t} else if (m_vecDamageNormal.z > 0.4f) {\n\t\t\t\t\t\tif (m_nPedState == PED_JUMP) {\n\t\t\t\t\t\t\tif (m_nWaitTimer <= 2000) {\n\t\t\t\t\t\t\t\tif (m_nWaitTimer < 1000)\n\t\t\t\t\t\t\t\t\tm_nWaitTimer += CTimer::GetTimeStep() * 0.02f * 1000.0f;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tm_nWaitTimer = 0;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tforceDir = m_vecDamageNormal;\n\t\t\t\t\t\tforceDir.z = 0.0f;\n\t\t\t\t\t\tforceDir.Normalise();\n\t\t\t\t\t\tif (m_nPedState != PED_JUMP || m_nWaitTimer >= 300) {\n\t\t\t\t\t\t\tApplyMoveForce(2.0f * forceDir);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tApplyMoveForce(-4.0f * forceDir);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else if ((CTimer::GetFrameCounter() + m_randomSeed % 256 + 3) & 7) {\n\t\t\t\t\tif (IsPlayer() && m_nPedState != PED_JUMP && pad0->JumpJustDown()) {\n\t\t\t\t\t\tint16 padWalkX = pad0->GetPedWalkLeftRight();\n\t\t\t\t\t\tint16 padWalkY = pad0->GetPedWalkUpDown();\n\t\t\t\t\t\tif (Abs(padWalkX) > 0.0f || Abs(padWalkY) > 0.0f) {\n\t\t\t\t\t\t\tm_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(0.0f, 0.0f, -padWalkX, padWalkY);\n\t\t\t\t\t\t\tm_fRotationDest -= TheCamera.Orientation;\n\t\t\t\t\t\t\tm_fRotationDest = CGeneral::LimitRadianAngle(m_fRotationDest);\n\t\t\t\t\t\t\tm_fRotationCur = m_fRotationDest;\n\t\t\t\t\t\t\tSetHeading(m_fRotationCur);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tSetJump();\n\t\t\t\t\t\tm_nPedStateTimer = 0;\n\t\t\t\t\t\tm_vecHitLastPos = GetPosition();\n\n\t\t\t\t\t\t// Why? forceDir is unused after this point.\n\t\t\t\t\t\tforceDir = CVector(0.0f, 0.0f, 0.0f);\n\t\t\t\t\t} else if (IsPlayer()) {\n\t\t\t\t\t\tint16 padWalkX = pad0->GetPedWalkLeftRight();\n\t\t\t\t\t\tint16 padWalkY = pad0->GetPedWalkUpDown();\n\t\t\t\t\t\tif (Abs(padWalkX) > 0.0f || Abs(padWalkY) > 0.0f) {\n\t\t\t\t\t\t\tm_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(0.0f, 0.0f, -padWalkX, padWalkY);\n\t\t\t\t\t\t\tm_fRotationDest -= TheCamera.Orientation;\n\t\t\t\t\t\t\tm_fRotationDest = CGeneral::LimitRadianAngle(m_fRotationDest);\n\t\t\t\t\t\t\tm_fRotationCur = m_fRotationDest;\n\t\t\t\t\t\t\tSetHeading(m_fRotationCur);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tCAnimBlendAssociation *jumpAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_JUMP_GLIDE);\n\n\t\t\t\t\t\tif (!jumpAssoc)\n\t\t\t\t\t\t\tjumpAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_FALL_GLIDE);\n\n\t\t\t\t\t\tif (jumpAssoc) {\n\t\t\t\t\t\t\tjumpAssoc->blendDelta = -3.0f;\n\t\t\t\t\t\t\tjumpAssoc->flags |= ASSOC_DELETEFADEDOUT;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (m_nPedState == PED_JUMP)\n\t\t\t\t\t\t\tm_nPedState = PED_IDLE;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tCAnimBlendAssociation *jumpAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_JUMP_GLIDE);\n\n\t\t\t\t\t\tif (!jumpAssoc)\n\t\t\t\t\t\t\tjumpAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_FALL_GLIDE);\n\n\t\t\t\t\t\tif (jumpAssoc) {\n\t\t\t\t\t\t\tjumpAssoc->blendDelta = -3.0f;\n\t\t\t\t\t\t\tjumpAssoc->flags |= ASSOC_DELETEFADEDOUT;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\toffsetToCheck = GetPosition();\n\t\t\t\t\toffsetToCheck.z += 0.5f;\n\n\t\t\t\t\tif (CWorld::ProcessVerticalLine(offsetToCheck, GetPosition().z - FEET_OFFSET, foundCol, foundEnt, true, true, false, true, false, false, nil)) {\n\t\t\t\t\t\tif (!bHeadStuckInCollision || FEET_OFFSET + foundCol.point.z < GetPosition().z) {\n\t\t\t\t\t\t\tGetMatrix().GetPosition().z = FEET_OFFSET + foundCol.point.z;\n\t\t\t\t\t\t\tGetMatrix().UpdateRW();\n\t\t\t\t\t\t\tif (bHeadStuckInCollision)\n\t\t\t\t\t\t\t\tbHeadStuckInCollision = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tSetLanding();\n\t\t\t\t\t\tbIsStanding = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if (m_nPedStateTimer < 1001) {\n\t\t\t\tm_nPedStateTimer = 0;\n\t\t\t}\n\t\t}\n\n\t\tif (bIsDucking)\n\t\t\tDuck();\n\n\t\tif (bStartWanderPathOnFoot) {\n\t\t\tif (IsPedInControl()) {\n\t\t\t\tClearAll();\n\t\t\t\tSetWanderPath(m_nPathDir);\n\t\t\t\tbStartWanderPathOnFoot = false;\n\t\t\t} else if (m_nPedState == PED_DRIVING) {\n\t\t\t\tbWanderPathAfterExitingCar = true;\n\t\t\t\tSetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle);\n\t\t\t\tbStartWanderPathOnFoot = false;\n\t\t\t}\n\t\t}\n\n\t\tif (!bIsStanding && m_vecMoveSpeed.z > 0.25) {\n\t\t\tfloat airResistance = Pow(0.95f, CTimer::GetTimeStep());\n\n\t\t\tm_vecMoveSpeed *= airResistance;\n\t\t}\n\t\tif (IsPlayer() || !bIsStanding || m_vecMoveSpeed.x != 0.0f || m_vecMoveSpeed.y != 0.0f || m_vecMoveSpeed.z != 0.0f\n\t\t\t|| (m_nMoveState != PEDMOVE_NONE && m_nMoveState != PEDMOVE_STILL)\n\t\t\t|| m_vecAnimMoveDelta.x != 0.0f || m_vecAnimMoveDelta.y != 0.0f\n\t\t\t|| m_nPedState == PED_JUMP\n\t\t\t|| bIsInTheAir\n\t\t\t|| m_pCurrentPhysSurface) {\n\n\t\t\tCPhysical::ProcessControl();\n\t\t} else {\n\t\t\tbHasContacted = false;\n\t\t\tbIsInSafePosition = false;\n\t\t\tbWasPostponed = false;\n\t\t\tbHasHitWall = false;\n\t\t\tm_nCollisionRecords = 0;\n\t\t\tbHasCollided = false;\n\t\t\tm_nDamagePieceType = 0;\n\t\t\tm_fDamageImpulse = 0.0f;\n\t\t\tm_pDamageEntity = nil;\n\t\t\tm_vecTurnFriction = CVector(0.0f, 0.0f, 0.0f);\n\t\t\tm_vecMoveFriction = CVector(0.0f, 0.0f, 0.0f);\n\t\t}\n\n\t\tif (m_nPedState != PED_DIE || bIsPedDieAnimPlaying) {\n\t\t\tRequestDelayedWeapon();\n\t\t\tPlayFootSteps();\n\t\t\tif (m_nPedState != PED_DEAD) {\n\t\t\t\tCalculateNewVelocity();\n\t\t\t\tCalculateNewOrientation();\n\t\t\t}\n\t\t\tUpdatePosition();\n\t\t\tif (IsPedInControl() && !bIsStanding && !m_pDamageEntity) {\n\t\t\t\tif (m_attachedTo) {\n\t\t\t\t\tbIsInTheAir = false;\n\t\t\t\t} else if (CheckIfInTheAir()) {\n\t\t\t\t\tSetInTheAir();\n\t\t\t\t\tbHeadStuckInCollision = false;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (bHeadStuckInCollision) {\n\t\t\t\tCVector posToCheck = GetPosition();\n\t\t\t\tposToCheck.z += 0.9f;\n\t\t\t\tif (!CWorld::TestSphereAgainstWorld(posToCheck, 0.2f, this, true, true, false, true, false, false))\n\t\t\t\t\tbHeadStuckInCollision = false;\n\t\t\t}\n\t\t\tProcessObjective();\n\t\t\tif (!bIsAimingGun) {\n\t\t\t\tif (bIsRestoringGun)\n\t\t\t\t\tRestoreGunPosition();\n\t\t\t} else {\n\t\t\t\tAimGun();\n\t\t\t}\n\n\t\t\tif (bIsLooking) {\n\t\t\t\tMoveHeadToLook();\n\t\t\t} else if (bIsRestoringLook) {\n\t\t\t\tRestoreHeadPosition();\n\t\t\t}\n\n\t\t\tif (bIsInTheAir)\n\t\t\t\tInTheAir();\n\n\t\t\tif (bUpdateAnimHeading) {\n\t\t\t\tif (m_nPedState != PED_GETUP && m_nPedState != PED_FALL) {\n\t\t\t\t\tm_fRotationCur -= HALFPI;\n\t\t\t\t\tm_fRotationDest = m_fRotationCur;\n\t\t\t\t\tbUpdateAnimHeading = false;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (m_nWaitState != WAITSTATE_FALSE)\n\t\t\t\tWait();\n\n#ifdef CANCELLABLE_CAR_ENTER\n\t\t\tstatic bool cancelJack = false;\n\t\t\tif (IsPlayer()) {\n\t\t\t\tif (EnteringCar() && m_pVehicleAnim) {\n\t\t\t\t\tCPad *pad = CPad::GetPad(0);\n\n\t\t\t\t\tif (!pad->ArePlayerControlsDisabled()) {\n\t\t\t\t\t\tint vehAnim = m_pVehicleAnim->animId;\n\n\t\t\t\t\t\tint16 padWalkX = pad->GetPedWalkLeftRight();\n\t\t\t\t\t\tint16 padWalkY = pad->GetPedWalkUpDown();\n\t\t\t\t\t\tif (Abs(padWalkX) > 0.0f || Abs(padWalkY) > 0.0f) {\n\t\t\t\t\t\t\tif (vehAnim == ANIM_STD_CAR_OPEN_DOOR_LHS || vehAnim == ANIM_STD_CAR_OPEN_DOOR_RHS || vehAnim == ANIM_STD_COACH_OPEN_LHS || vehAnim == ANIM_STD_COACH_OPEN_RHS ||\n\t\t\t\t\t\t\t\tvehAnim == ANIM_STD_VAN_OPEN_DOOR_REAR_LHS || vehAnim == ANIM_STD_VAN_OPEN_DOOR_REAR_RHS) {\n\n\t\t\t\t\t\t\t\tif (!m_pMyVehicle->pDriver) {\n\t\t\t\t\t\t\t\t\tcancelJack = false;\n\t\t\t\t\t\t\t\t\tbCancelEnteringCar = true;\n\t\t\t\t\t\t\t\t} else\n\t\t\t\t\t\t\t\t\tcancelJack = true;\n\t\t\t\t\t\t\t} else if (vehAnim == ANIM_STD_QUICKJACK && m_pVehicleAnim->GetTimeLeft() > 0.75f) {\n\t\t\t\t\t\t\t\tcancelJack = true;\n\t\t\t\t\t\t\t} else if (vehAnim == ANIM_STD_CAR_PULL_OUT_PED_LHS || vehAnim == ANIM_STD_CAR_PULL_OUT_PED_LO_LHS || vehAnim == ANIM_STD_CAR_PULL_OUT_PED_LO_RHS || vehAnim == ANIM_STD_CAR_PULL_OUT_PED_RHS) {\n\t\t\t\t\t\t\t\tbCancelEnteringCar = true;\n\t\t\t\t\t\t\t\tcancelJack = false;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (cancelJack && vehAnim == ANIM_STD_QUICKJACK && m_pVehicleAnim->GetTimeLeft() > 0.75f && m_pVehicleAnim->GetTimeLeft() < 0.78f) {\n\t\t\t\t\t\t\tcancelJack = false;\n\t\t\t\t\t\t\tQuitEnteringCar();\n\t\t\t\t\t\t\tRestorePreviousObjective();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (cancelJack && (vehAnim == ANIM_STD_CAR_PULL_OUT_PED_LHS || vehAnim == ANIM_STD_CAR_PULL_OUT_PED_LO_LHS || vehAnim == ANIM_STD_CAR_PULL_OUT_PED_LO_RHS || vehAnim == ANIM_STD_CAR_PULL_OUT_PED_RHS)) {\n\t\t\t\t\t\t\tcancelJack = false;\n\t\t\t\t\t\t\tbCancelEnteringCar = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else\n\t\t\t\t\tcancelJack = false;\n\t\t\t}\n#endif\n\n\t\t\tswitch (m_nPedState) {\n\t\t\t\tcase PED_IDLE:\n\t\t\t\t\tIdle();\n\t\t\t\t\tbreak;\n\t\t\t\tcase PED_LOOK_ENTITY:\n\t\t\t\tcase PED_LOOK_HEADING:\n\t\t\t\t\tLook();\n\t\t\t\t\tbreak;\n\t\t\t\tcase PED_WANDER_RANGE:\n\t\t\t\t\t// III has these in here(and they were unused):\n\t\t\t\t\t/*\n\t\t\t\t\tWanderRange();\n\t\t\t\t\tCheckAroundForPossibleCollisions();\n\t\t\t\t\t*/\n\t\t\t\t\tbreak;\n\t\t\t\tcase PED_WANDER_PATH:\n\t\t\t\t\tWanderPath();\n\t\t\t\t\tbreak;\n\t\t\t\tcase PED_ENTER_CAR:\n\t\t\t\tcase PED_CARJACK:\n\t\t\t\t{\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase PED_FLEE_POS:\n\t\t\t\t\tms_vec2DFleePosition = m_fleeFromPos;\n\t\t\t\t\tFlee();\n\t\t\t\t\tbreak;\n\t\t\t\tcase PED_FLEE_ENTITY:\n\t\t\t\t\tif (!m_fleeFrom) {\n\t\t\t\t\t\tbMakeFleeScream = false;\n\t\t\t\t\t\tSetIdle();\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (CTimer::GetTimeInMilliseconds() <= m_nPedStateTimer)\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tms_vec2DFleePosition = m_fleeFrom->GetPosition();\n\t\t\t\t\tFlee();\n\t\t\t\t\tbreak;\n\t\t\t\tcase PED_FOLLOW_PATH:\n\t\t\t\t\tFollowPath();\n\t\t\t\t\tbreak;\n\t\t\t\tcase PED_PAUSE:\n\t\t\t\t\tPause();\n\t\t\t\t\tbreak;\n\t\t\t\tcase PED_ATTACK:\n\t\t\t\t\tAttack();\n\t\t\t\t\tbreak;\n\t\t\t\tcase PED_FIGHT:\n\t\t\t\t\tFight();\n\t\t\t\t\tbreak;\n\t\t\t\tcase PED_CHAT:\n\t\t\t\t\tChat();\n\t\t\t\t\tbreak;\n\t\t\t\tcase PED_AIM_GUN:\n\t\t\t\t\tif (m_pPointGunAt && m_pPointGunAt->IsPed()\n#ifdef FIX_BUGS\n\t\t\t\t        && !GetWeapon()->IsTypeMelee()\n#endif\n\t\t\t\t\t\t&& ((CPed*)m_pPointGunAt)->CanSeeEntity(this, CAN_SEE_ENTITY_ANGLE_THRESHOLD * 2)) {\n\t\t\t\t\t\t((CPed*)m_pPointGunAt)->ReactToPointGun(this);\n\t\t\t\t\t}\n\t\t\t\t\tPointGunAt();\n\t\t\t\t\tbreak;\n\t\t\t\tcase PED_SEEK_CAR:\n\t\t\t\t\tSeekCar();\n\t\t\t\t\tbreak;\n\t\t\t\tcase PED_SEEK_IN_BOAT:\n\t\t\t\t\tSeekBoatPosition();\n\t\t\t\t\tbreak;\n\t\t\t\tcase PED_BUY_ICECREAM:\n\t\t\t\t\tBuyIceCream();\n\t\t\t\t\tbreak;\n\t\t\t\tcase PED_INVESTIGATE:\n\t\t\t\t\tInvestigateEvent();\n\t\t\t\t\tbreak;\n\t\t\t\tcase PED_ON_FIRE:\n\t\t\t\t\tif (IsPlayer())\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tif (CTimer::GetTimeInMilliseconds() <= m_fleeTimer) {\n\t\t\t\t\t\tif (m_pFire) {\n\t\t\t\t\t\t\tif (m_fleeFrom) {\n\t\t\t\t\t\t\t\tms_vec2DFleePosition = m_fleeFrom->GetPosition();\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tms_vec2DFleePosition = m_fleeFromPos;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tFlee();\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tm_nLastPedState = PED_NONE;\n\t\t\t\t\t\t\tSetWanderPath(0);\n\t\t\t\t\t\t\tSetWaitState(WAITSTATE_FINISH_FLEE, 0);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (m_pFire)\n\t\t\t\t\t\t\tm_pFire->Extinguish();\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase PED_ANSWER_MOBILE:\n\t\t\t\t\tAnswerMobile();\n\t\t\t\t\tbreak;\n\t\t\t\tcase PED_FALL:\n\t\t\t\t\tFall();\n\t\t\t\t\tbreak;\n\t\t\t\tcase PED_GETUP:\n\t\t\t\t\tSetGetUp();\n\t\t\t\t\tbreak;\n#ifdef GTA_TRAIN\n\t\t\t\tcase PED_ENTER_TRAIN:\n\t\t\t\t\tEnterTrain();\n\t\t\t\t\tbreak;\n\t\t\t\tcase PED_EXIT_TRAIN:\n\t\t\t\t\tExitTrain();\n\t\t\t\t\tbreak;\n#endif\n\t\t\t\tcase PED_DRIVING:\n\t\t\t\t{\n\t\t\t\t\tif (!m_pMyVehicle) {\n\t\t\t\t\t\tbInVehicle = false;\n\t\t\t\t\t\tFlagToDestroyWhenNextProcessed();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n#ifdef CAR_AIRBREAK\n\t\t\t\t\tif (IsPlayer()) {\n\t\t\t\t\t\tCPad* pad = CPad::GetPad(0);\n\t\t\t\t\t\tif (!pad->ArePlayerControlsDisabled()) {\n\t\t\t\t\t\t\tif (pad->GetHorn()) {\n\t\t\t\t\t\t\t\tfloat c = Cos(m_fRotationCur);\n\t\t\t\t\t\t\t\tfloat s = Sin(m_fRotationCur);\n\t\t\t\t\t\t\t\tm_pMyVehicle->GetRight() = CVector(1.0f, 0.0f, 0.0f);\n\t\t\t\t\t\t\t\tm_pMyVehicle->GetForward() = CVector(0.0f, 1.0f, 0.0f);\n\t\t\t\t\t\t\t\tm_pMyVehicle->GetUp() = CVector(0.0f, 0.0f, 1.0f);\n\t\t\t\t\t\t\t\tif (pad->GetAccelerate()) {\n\t\t\t\t\t\t\t\t\tm_pMyVehicle->ApplyMoveForce(GetForward() * 30.0f);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\telse if (pad->GetBrake()) {\n\t\t\t\t\t\t\t\t\tm_pMyVehicle->ApplyMoveForce(-GetForward() * 30.0f);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\t\tint16 lr = pad->GetSteeringLeftRight();\n\t\t\t\t\t\t\t\t\tif (lr < 0) {\n\t\t\t\t\t\t\t\t\t\t//m_pMyVehicle->ApplyTurnForce(20.0f * -GetRight(), GetForward());\n\t\t\t\t\t\t\t\t\t\tm_pMyVehicle->ApplyMoveForce(-GetRight() * 30.0f);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\telse if (lr > 0) {\n\t\t\t\t\t\t\t\t\t\tm_pMyVehicle->ApplyMoveForce(GetRight() * 30.0f);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\t\t\tm_pMyVehicle->ApplyMoveForce(0.0f, 0.0f, 50.0f);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n#endif\n\n\t\t\t\t\tif (m_pMyVehicle->pDriver == this) {\n\t\t\t\t\t\tDriveVehicle();\n\t\t\t\t\t\tif (!m_pMyVehicle)\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tLookForSexyPeds();\n\t\t\t\t\t\tLookForSexyCars();\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tif (!IsPlayer() && m_pMyVehicle->IsBoat()\n\t\t\t\t\t\t&& FindPlayerPed()->m_pCurrentPhysSurface == m_pMyVehicle\n\t\t\t\t\t\t&& (CharCreatedBy != MISSION_CHAR || !bIsPlayerFriend)) {\n\t\t\t\t\t\tSetObjective(OBJECTIVE_KILL_CHAR_ON_BOAT, FindPlayerPed());\n\t\t\t\t\t\tSay(SOUND_PED_CAR_JACKED);\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase PED_DIE:\n\t\t\t\t\tDie();\n\t\t\t\t\tbreak;\n\t\t\t\tcase PED_HANDS_UP:\n\t\t\t\t\tif (m_pedStats->m_flags & STAT_GUN_PANIC) {\n\t\t\t\t\t\tif (!RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_HANDSCOWER)) {\n\t\t\t\t\t\t\tCAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_HANDSCOWER);\n\t\t\t\t\t\t\tSay(SOUND_PED_HANDS_COWER);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (!RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_HANDSUP)) {\n\t\t\t\t\t\tCAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_HANDSUP);\n\t\t\t\t\t\tSay(SOUND_PED_HANDS_UP);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tSetMoveAnim();\n\t\t\tif (bPedIsBleeding || m_bleedCounter != 0) {\n\t\t\t\tif (CGame::nastyGame) {\n\t\t\t\t\tif (m_bleedCounter != 0)\n\t\t\t\t\t\tm_bleedCounter--;\n\n\t\t\t\t\tif (!(CTimer::GetFrameCounter() & 3)) {\n\t\t\t\t\t\tCVector cameraDist = GetPosition() - TheCamera.GetPosition();\n\t\t\t\t\t\tif (cameraDist.MagnitudeSqr() < sq(50.0f)) {\n\n\t\t\t\t\t\t\tfloat length = (CGeneral::GetRandomNumber() & 127) * 0.0015f + 0.15f;\n\t\t\t\t\t\t\tCVector bloodPos(\n\t\t\t\t\t\t\t\t((CGeneral::GetRandomNumber() & 127) - 64) * 0.007f,\n\t\t\t\t\t\t\t\t((CGeneral::GetRandomNumber() & 127) - 64) * 0.007f,\n\t\t\t\t\t\t\t\t1.0f);\n\t\t\t\t\t\t\tbloodPos += GetPosition();\n\n\t\t\t\t\t\t\tCShadows::AddPermanentShadow(SHADOWTYPE_DARK, gpBloodPoolTex, &bloodPos, length, 0.0f,\n\t\t\t\t\t\t\t\t0.0f, -length, 255, 255, 0, 0, 4.0f, (CGeneral::GetRandomNumber() & 4095) + 2000, 1.0f);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tServiceTalking();\n\t\t\tif (bInVehicle && !m_pMyVehicle)\n\t\t\t\tbInVehicle = false;\n\n\t\t\tif (bHeldHostageInCar) {\n\t\t\t\tif (m_pMyVehicle && m_pMyVehicle->pDriver && m_pMyVehicle->pDriver->IsPlayer()) {\n\t\t\t\t\tSay(SOUND_PED_FLEE_SPRINT);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (m_delayedSoundID >= 0 && CTimer::GetTimeInMilliseconds() > m_delayedSoundTimer) {\n\t\t\t\tSay(m_delayedSoundID);\n\t\t\t\tm_delayedSoundID = -1;\n\t\t\t\tm_delayedSoundTimer = 0;\n\t\t\t}\n\n\t\t\tif (bFannyMagnetCheat && m_nPedType == PEDTYPE_CIVFEMALE\n\t\t\t\t&& m_pedStats->m_sexiness > 40 && !m_leader) {\n\t\t\t\tSetLeader(FindPlayerPed());\n\t\t\t}\n\n\t\t} else {\n\t\t\tif (bIsStanding && (!m_pCurrentPhysSurface || IsPlayer())\n\t\t\t\t|| bIsInWater || !bUsesCollision) {\n\t\t\t\tSetDead();\n\t\t\t}\n\t\t\tm_pCurrentPhysSurface = nil;\n\t\t}\n\t} else\n\t\tServiceTalking();\n}\n\nint32\nCPed::ProcessEntityCollision(CEntity *collidingEnt, CColPoint *collidingPoints)\n{\n\tbool collidedWithBoat = false;\n\tbool belowTorsoCollided = false;\n\tfloat gravityEffect = -0.15f * CTimer::GetTimeStep();\n\tCColPoint intersectionPoint;\n\tCColLine ourLine;\n\n\tCColModel *ourCol = CModelInfo::GetModelInfo(GetModelIndex())->GetColModel();\n\tCColModel *hisCol = CModelInfo::GetModelInfo(collidingEnt->GetModelIndex())->GetColModel();\n\n\tif (!bUsesCollision && !bJustCheckCollision)\n\t\treturn false;\n\n\tif (collidingEnt->IsVehicle() && ((CVehicle*)collidingEnt)->IsBoat())\n\t\tcollidedWithBoat = true;\n\n\t// ofc we're not vehicle\n\tif (!m_bIsVehicleBeingShifted && !bSkipLineCol && !collidingEnt->IsPed()) {\n\t\tif (!bCollisionProcessed) {\n\t\t\tm_pCurrentPhysSurface = nil;\n\t\t\tif (bIsStanding) {\n\t\t\t\tbIsStanding = false;\n\t\t\t\tbWasStanding = true;\n\t\t\t}\n\t\t\tbCollisionProcessed = true;\n\t\t\tm_fCollisionSpeed += m_vecMoveSpeed.Magnitude2D() * CTimer::GetTimeStep();\n\t\t\tbStillOnValidPoly = false;\n\t\t\tif (IsPlayer() || m_fCollisionSpeed >= 1.0f\n\t\t\t\t&& (m_fCollisionSpeed >= 2.0f || m_nPedState != PED_WANDER_PATH)) {\n\t\t\t\tm_collPoly.valid = false;\n\t\t\t\tm_fCollisionSpeed = 0.0f;\n\t\t\t\tbHitSteepSlope = false;\n\t\t\t} else {\n\t\t\t\tCVector pos = GetPosition();\n\t\t\t\tfloat potentialGroundZ = GetPosition().z - FEET_OFFSET;\n\t\t\t\tif (bWasStanding) {\n\t\t\t\t\tpos.z += -0.25f;\n\t\t\t\t\tpotentialGroundZ += gravityEffect;\n\t\t\t\t}\n\t\t\t\tif (CCollision::IsStoredPolyStillValidVerticalLine(pos, potentialGroundZ, intersectionPoint, &m_collPoly)) {\n\t\t\t\t\tbStillOnValidPoly = true;\n\t\t\t\t\tif(!bHeadStuckInCollision || FEET_OFFSET + intersectionPoint.point.z < GetPosition().z) {\n\t\t\t\t\t\tGetMatrix().GetPosition().z = FEET_OFFSET + intersectionPoint.point.z;\n\t\t\t\t\t\tif (bHeadStuckInCollision)\n\t\t\t\t\t\t\tbHeadStuckInCollision = false;\n\t\t\t\t\t}\n\t\t\t\t\tm_vecMoveSpeed.z = 0.0f;\n\t\t\t\t\tbIsStanding = true;\n\t\t\t\t} else {\n\t\t\t\t\tm_collPoly.valid = false;\n\t\t\t\t\tm_fCollisionSpeed = 0.0f;\n\t\t\t\t\tbHitSteepSlope = false;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (!bStillOnValidPoly) {\n\t\t\tCVector potentialCenter = GetPosition();\n\t\t\tpotentialCenter.z = GetPosition().z - 0.52f;\n\n\t\t\t// 0.52f should be a ped's approx. radius\n\t\t\tfloat totalRadiusWhenCollided = collidingEnt->GetBoundRadius() + 0.52f - gravityEffect;\n\t\t\tif (bWasStanding) {\n\t\t\t\tif (collidedWithBoat) {\n\t\t\t\t\tpotentialCenter.z += 2.0f * gravityEffect;\n\t\t\t\t\ttotalRadiusWhenCollided += Abs(gravityEffect);\n\t\t\t\t} else {\n\t\t\t\t\tpotentialCenter.z += gravityEffect;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (sq(totalRadiusWhenCollided) > (potentialCenter - collidingEnt->GetBoundCentre()).MagnitudeSqr()) {\n\t\t\t\tourLine.p0 = GetPosition();\n\t\t\t\tourLine.p1 = GetPosition();\n\t\t\t\tourLine.p1.z = GetPosition().z - FEET_OFFSET;\n\t\t\t\tif (bWasStanding) {\n\t\t\t\t\tourLine.p1.z = ourLine.p1.z + gravityEffect;\n\t\t\t\t\tourLine.p0.z = ourLine.p0.z + -0.25f;\n\t\t\t\t}\n\t\t\t\tfloat minDist = 1.0f;\n\t\t\t\tbelowTorsoCollided = CCollision::ProcessVerticalLine(ourLine, collidingEnt->GetMatrix(), *hisCol,\n\t\t\t\t\tintersectionPoint, minDist, false, false, &m_collPoly);\n\n\t\t\t\tif (collidedWithBoat && bWasStanding && !belowTorsoCollided) {\n\t\t\t\t\tourLine.p0.z = ourLine.p1.z;\n\t\t\t\t\tourLine.p1.z = ourLine.p1.z + gravityEffect;\n\t\t\t\t\tbelowTorsoCollided = CCollision::ProcessVerticalLine(ourLine, collidingEnt->GetMatrix(), *hisCol,\n\t\t\t\t\t\tintersectionPoint, minDist, false, false, &m_collPoly);\n\t\t\t\t}\n\t\t\t\tif (belowTorsoCollided) {\n\t\t\t\t\t\tif (!bIsStanding\n\t\t\t\t\t\t\t|| FEET_OFFSET + intersectionPoint.point.z > GetPosition().z\n\t\t\t\t\t\t\t|| collidedWithBoat && 3.12f + intersectionPoint.point.z > GetPosition().z) {\n\n\t\t\t\t\t\t\tif (!collidingEnt->IsVehicle() && !collidingEnt->IsObject()) {\n\t\t\t\t\t\t\t\tm_pCurSurface = collidingEnt;\n\t\t\t\t\t\t\t\tcollidingEnt->RegisterReference((CEntity**)&m_pCurSurface);\n\t\t\t\t\t\t\t\tbTryingToReachDryLand = false;\n\t\t\t\t\t\t\t\tbOnBoat = false;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tm_pCurrentPhysSurface = (CPhysical*)collidingEnt;\n\t\t\t\t\t\t\t\tcollidingEnt->RegisterReference((CEntity**)&m_pCurrentPhysSurface);\n\t\t\t\t\t\t\t\tm_vecOffsetFromPhysSurface = intersectionPoint.point - collidingEnt->GetPosition();\n\t\t\t\t\t\t\t\tm_pCurSurface = collidingEnt;\n\t\t\t\t\t\t\t\tcollidingEnt->RegisterReference((CEntity**)&m_pCurSurface);\n\t\t\t\t\t\t\t\tm_collPoly.valid = false;\n\t\t\t\t\t\t\t\tif (collidingEnt->IsVehicle() && ((CVehicle*)collidingEnt)->IsBoat()) {\n\t\t\t\t\t\t\t\t\tbOnBoat = true;\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tbOnBoat = false;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (!bHeadStuckInCollision || FEET_OFFSET + intersectionPoint.point.z < GetPosition().z) {\n\t\t\t\t\t\t\t\tGetMatrix().GetPosition().z = FEET_OFFSET + intersectionPoint.point.z;\n\t\t\t\t\t\t\t\tif (bHeadStuckInCollision)\n\t\t\t\t\t\t\t\t\tbHeadStuckInCollision = false;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tm_nSurfaceTouched = intersectionPoint.surfaceB;\n\t\t\t\t\t\t\tif (m_nSurfaceTouched == SURFACE_STEEP_CLIFF) {\n\t\t\t\t\t\t\t\tbHitSteepSlope = true;\n\t\t\t\t\t\t\t\tm_vecDamageNormal = intersectionPoint.normal;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tfloat upperSpeedLimit = 0.33f;\n\t\t\t\t\t\tfloat lowerSpeedLimit = -0.25f;\n\t\t\t\t\t\tfloat speed = m_vecMoveSpeed.Magnitude2D();\n\t\t\t\t\t\tif (m_nPedState == PED_IDLE) {\n\t\t\t\t\t\t\tupperSpeedLimit *= 2.0f;\n\t\t\t\t\t\t\tlowerSpeedLimit *= 1.5f;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tCAnimBlendAssociation *fallAnim = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_FALL);\n\t\t\t\t\t\tif (!bWasStanding && speed > upperSpeedLimit && (!bPushedAlongByCar || m_vecMoveSpeed.z < lowerSpeedLimit)\n\t\t\t\t\t\t\t&& m_pCollidingEntity != collidingEnt) {\n\n\t\t\t\t\t\t\tfloat damage = 100.0f * Max(speed - 0.25f, 0.0f);\n\t\t\t\t\t\t\tfloat damage2 = damage;\n\t\t\t\t\t\t\tif (m_vecMoveSpeed.z < -0.25f)\n\t\t\t\t\t\t\t\tdamage += (-0.25f - m_vecMoveSpeed.z) * 150.0f;\n\n\t\t\t\t\t\t\tuint8 dir = 2; // from backward\n\t\t\t\t\t\t\tif (m_vecMoveSpeed.x > 0.01f || m_vecMoveSpeed.x < -0.01f || m_vecMoveSpeed.y > 0.01f || m_vecMoveSpeed.y < -0.01f) {\n\t\t\t\t\t\t\t\tCVector2D offset = -m_vecMoveSpeed;\n\t\t\t\t\t\t\t\tdir = GetLocalDirection(offset);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (CSurfaceTable::IsSoftLanding(intersectionPoint.surfaceB))\n\t\t\t\t\t\t\t\tdamage *= 0.5f;\n\n\t\t\t\t\t\t\tInflictDamage(collidingEnt, WEAPONTYPE_FALL, damage, PEDPIECE_TORSO, dir);\n\t\t\t\t\t\t\tif (IsPlayer() && damage2 > 5.0f)\n\t\t\t\t\t\t\t\tSay(SOUND_PED_LAND);\n\n\t\t\t\t\t\t} else if (!bWasStanding && fallAnim && -0.016f * CTimer::GetTimeStep() > m_vecMoveSpeed.z) {\n\t\t\t\t\t\t\tInflictDamage(collidingEnt, WEAPONTYPE_FALL, 15.0f, PEDPIECE_TORSO, 2);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tm_vecMoveSpeed.z = 0.0f;\n\t\t\t\t\t\tbIsStanding = true;\n\t\t\t\t} else {\n\t\t\t\t\tbOnBoat = false;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tint ourCollidedSpheres = CCollision::ProcessColModels(GetMatrix(), *ourCol, collidingEnt->GetMatrix(), *hisCol, collidingPoints, nil, nil);\n\tif (ourCollidedSpheres > 0 || belowTorsoCollided) {\n\t\tAddCollisionRecord(collidingEnt);\n\t\tif (!collidingEnt->IsBuilding())\n\t\t\t((CPhysical*)collidingEnt)->AddCollisionRecord(this);\n\n\t\tif (ourCollidedSpheres > 0 && (collidingEnt->IsBuilding() || collidingEnt->GetIsStatic())) {\n\t\t\tbHasHitWall = true;\n\t\t}\n\t}\n\tif (collidingEnt->IsBuilding() || collidingEnt->GetIsStatic()) {\n\t\tif (bWasStanding) {\n\t\t\tCVector sphereNormal;\n\t\t\tfloat normalLength;\n\t\t\tfor(int sphere = 0; sphere < ourCollidedSpheres; sphere++) {\n\t\t\t\tsphereNormal = collidingPoints[sphere].normal;\n\t\t\t\tif (sphereNormal.z >= -1.0f || !IsPlayer()) {\n\t\t\t\t\tnormalLength = sphereNormal.Magnitude2D();\n\t\t\t\t\tif (normalLength != 0.0f) {\n\t\t\t\t\t\tsphereNormal.x = sphereNormal.x / normalLength;\n\t\t\t\t\t\tsphereNormal.y = sphereNormal.y / normalLength;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tfloat speed = m_vecMoveSpeed.Magnitude2D();\n\t\t\t\t\tsphereNormal.x = -m_vecMoveSpeed.x / Max(0.001f, speed);\n\t\t\t\t\tsphereNormal.y = -m_vecMoveSpeed.y / Max(0.001f, speed);\n\t\t\t\t\tGetMatrix().GetPosition().z -= 0.05f;\n\t\t\t\t\tbHeadStuckInCollision = true;\n\t\t\t\t}\n\t\t\t\tsphereNormal.Normalise();\n\t\t\t\tcollidingPoints[sphere].normal = sphereNormal;\n\t\t\t\tif (collidingPoints[sphere].surfaceB == SURFACE_STEEP_CLIFF)\n\t\t\t\t\tbHitSteepSlope = true;\n\t\t\t}\n\t\t}\n\t}\n\treturn ourCollidedSpheres;\n}\n\nstatic void\nparticleProduceFootSplash(CPed *ped, CVector const &pos, float size, int times)\n{\n\tfor (int i = 0; i < times; i++) {\n\t\tCVector adjustedPos = pos;\n\t\tadjustedPos.x += CGeneral::GetRandomNumberInRange(-0.1f, 0.1f);\n\t\tadjustedPos.y += CGeneral::GetRandomNumberInRange(-0.1f, 0.1f);\n\n\t\tCVector direction = ped->GetForward() * -0.05f;\n\t\tCParticle::AddParticle(PARTICLE_RAIN_SPLASHUP, adjustedPos, direction, nil, size, CRGBA(32, 32, 32, 32), 0, 0, CGeneral::GetRandomNumber() & 1, 200);\n\t}\n}\n\nstatic void\nparticleProduceFootDust(CPed *ped, CVector const &pos, float size, int times)\n{\n\tswitch (ped->m_nSurfaceTouched)\n\t{\n\t\tcase SURFACE_TARMAC:\n\t\tcase SURFACE_GRAVEL:\n\t\tcase SURFACE_PAVEMENT:\n\t\tcase SURFACE_SAND:\n\t\tcase SURFACE_SAND_BEACH:\n\t\tcase SURFACE_CONCRETE_BEACH:\n\t\t\tfor (int i = 0; i < times; ++i) {\n\t\t\t\tCVector adjustedPos = pos;\n\t\t\t\tadjustedPos.x += CGeneral::GetRandomNumberInRange(-0.1f, 0.1f);\n\t\t\t\tadjustedPos.y += CGeneral::GetRandomNumberInRange(-0.1f, 0.1f);\n\t\t\t\t// ??\n\t\t\t\tCGeneral::GetRandomNumber();\n\t\t\t\tCGeneral::GetRandomNumber();\n\t\t\t\tCParticle::AddParticle(PARTICLE_PEDFOOT_DUST, adjustedPos, CVector(0.0f, 0.0f, 0.0f), nil, size, CRGBA(0, 0, 0, 0), 0, 0, 0, 0);\n\t\t\t}\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t}\n}\n\nvoid\nCPed::PlayFootSteps(void)\n{\n\tCAnimBlendAssociation *assoc = RpAnimBlendClumpGetFirstAssociation(GetClump());\n\tCAnimBlendAssociation *walkRunAssoc = nil;\n\tfloat walkRunAssocBlend = 0.0f, idleAssocBlend = 0.0f;\n\tbool isSkater = m_pedStats == CPedStats::ms_apPedStats[PEDSTAT_SKATER];\n\n\tCVector footPosL(0.0f, 0.0f, 0.0f), footPosR(0.0f, 0.0f, 0.0f);\n\tbool footPosLok = false, footPosRok = false;\n\n\tif (bDoBloodyFootprints) {\n\t\tif (m_bloodyFootprintCountOrDeathTime > 0 && m_bloodyFootprintCountOrDeathTime < 300) {\n\t\t\tm_bloodyFootprintCountOrDeathTime--;\n\n\t\t\tif (m_bloodyFootprintCountOrDeathTime == 0)\n\t\t\t\tbDoBloodyFootprints = false;\n\t\t}\n\t}\n\n\tif (!bIsStanding)\n\t\treturn;\n\n\tfor (; assoc; assoc = RpAnimBlendGetNextAssociation(assoc)) {\n\t\tif (assoc->flags & ASSOC_WALK) {\n\t\t\twalkRunAssoc = assoc;\n\t\t\twalkRunAssocBlend += assoc->blendAmount;\n\t\t} else if ((assoc->flags & ASSOC_NOWALK) == 0) {\n\t\t\tidleAssocBlend += assoc->blendAmount;\n\t\t}\n\t}\n\n\tif (walkRunAssoc && walkRunAssocBlend > 0.5f && idleAssocBlend < 1.0f) {\n\n\t\tfloat stepStart = 1.f / 15.f;\n\t\tfloat stepEnd = walkRunAssoc->hierarchy->totalLength / 2.0f + stepStart;\n\t\tfloat currentTime = walkRunAssoc->currentTime;\n\n\t\tif (isSkater) {\n\t\t\t// both are unused\n\t\t\tstatic float stepStartSection = 1.0f;\n\t\t\tstatic float animSections = 15.f;\n\n\t\t\tfloat moveStart, soundVolume, skateTime;\n\t\t\tif (walkRunAssoc->animId == ANIM_STD_WALK) {\n\t\t\t\tmoveStart = 0.0f;\n\t\t\t\tskateTime = 8.f / 15.f;\n\t\t\t} else {\n\t\t\t\tmoveStart = 0.0f;\n\t\t\t\tskateTime = 5.f / 15.f;\n\t\t\t}\n\t\t\tswitch (CSurfaceTable::GetAdhesionGroup(m_nSurfaceTouched)) {\n\t\t\t\tcase ADHESIVE_LOOSE:\n\t\t\t\t\tif (CGeneral::GetRandomNumber() % 128) {\n\t\t\t\t\t\tm_vecAnimMoveDelta *= 0.5f;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tSetFall(0, ANIM_STD_HIGHIMPACT_BACK, false);\n\t\t\t\t\t}\n\t\t\t\t\tsoundVolume = 0.5f;\n\t\t\t\t\tbreak;\n\t\t\t\tcase ADHESIVE_SAND:\n\t\t\t\t\tif (CGeneral::GetRandomNumber() % 64) {\n\t\t\t\t\t\tm_vecAnimMoveDelta *= 0.2f;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tSetFall(0, ANIM_STD_HIGHIMPACT_BACK, false);\n\t\t\t\t\t}\n\t\t\t\t\tsoundVolume = 0.2f;\n\t\t\t\t\tbreak;\n\t\t\t\tcase ADHESIVE_WET:\n\t\t\t\t\tm_vecAnimMoveDelta *= 0.3f;\n\t\t\t\t\tsoundVolume = 0.2f;\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tsoundVolume = 1.f;\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (soundVolume > 0.2f && currentTime > moveStart && currentTime - walkRunAssoc->timeStep <= moveStart) {\n\t\t\t\tDMAudio.PlayOneShot(m_audioEntityId, SOUND_SKATING, ((int)(127.f * soundVolume) | (walkRunAssoc->animId << 8)));\n\t\t\t} else if (soundVolume > 0.2f) {\n\t\t\t\tif (currentTime > skateTime && currentTime - walkRunAssoc->timeStep <= skateTime) {\n\t\t\t\t\tDMAudio.PlayOneShot(m_audioEntityId, SOUND_SKATING, ((int)(127.f * soundVolume) | (walkRunAssoc->animId << 8)));\n\t\t\t\t}\n\t\t\t}\n\n\t\t} else {\n\t\t\tint stepPart = 0;\n\t\t\t\n\t\t\t// This section is shortened/optimized for sanity.\n\n\t\t\tif (currentTime >= stepStart && currentTime - walkRunAssoc->timeStep < stepStart)\n\t\t\t\tstepPart = 1;\n\t\t\telse if (currentTime >= stepEnd && currentTime - walkRunAssoc->timeStep < stepEnd)\n\t\t\t\tstepPart = 2;\n\n\t\t\tif (stepPart != 0) {\n\t\t\t\tCVector adjustedFootPos;\n\t\t\t\tif (stepPart == 1) {\n\t\t\t\t\tDMAudio.PlayOneShot(m_audioEntityId, SOUND_STEP_START, 1.0f);\n\t\t\t\t\tTransformToNode(footPosL, PED_FOOTL);\n\t\t\t\t\tfootPosLok = true;\n\t\t\t\t\tadjustedFootPos = footPosL;\n\t\t\t\t} else {\n\t\t\t\t\tDMAudio.PlayOneShot(m_audioEntityId, SOUND_STEP_END, 1.0f);\n\t\t\t\t\tTransformToNode(footPosR, PED_FOOTR);\n\t\t\t\t\tfootPosRok = true;\n\t\t\t\t\tadjustedFootPos = footPosR;\n\t\t\t\t}\n\n\t\t\t\tCVector forward = GetForward();\n\n\t\t\t\tadjustedFootPos.z -= 0.1f;\n\t\t\t\tadjustedFootPos += 0.2f * forward;\n\n\t\t\t\tif (bDoBloodyFootprints) {\n\t\t\t\t\tCVector2D top(forward * 0.26f);\n\t\t\t\t\tCVector2D right(GetRight() * (stepPart == 1 ? 0.14f : 0.1f));\n\n\t\t\t\t\tCShadows::AddPermanentShadow(SHADOWTYPE_DARK, gpBloodPoolTex, &adjustedFootPos,\n\t\t\t\t\t\ttop.x, top.y,\n\t\t\t\t\t\tright.x, right.y,\n\t\t\t\t\t\t255, 255, 0, 0, 4.0f, 3000, 1.0f);\n\n\t\t\t\t\tif (m_bloodyFootprintCountOrDeathTime <= 20) {\n\t\t\t\t\t\tm_bloodyFootprintCountOrDeathTime = 0;\n\t\t\t\t\t\tbDoBloodyFootprints = false;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tm_bloodyFootprintCountOrDeathTime -= 20;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (m_nSurfaceTouched == SURFACE_SAND || m_nSurfaceTouched == SURFACE_SAND_BEACH) {\n\t\t\t\t\tCVector2D top(forward * -0.26f);\n\t\t\t\t\tCVector2D right(GetRight() * (stepPart == 1 ? 0.1f : 0.14f));\n\n\t\t\t\t\tCShadows::AddPermanentShadow(SHADOWTYPE_DARK, gpShadowPedTex, &adjustedFootPos,\n\t\t\t\t\t\ttop.x, top.y,\n\t\t\t\t\t\tright.x, right.y,\n\t\t\t\t\t\t120, 250, 250, 50, 4.0f, 5000, 1.0f);\n\t\t\t\t}\n\t\t\t\tif (CWeather::Rain <= 0.1f || CCullZones::CamNoRain() || CCullZones::PlayerNoRain()) {\n\t\t\t\t\tif (IsPlayer())\n\t\t\t\t\t\tparticleProduceFootDust(this, adjustedFootPos, 0.0f, 4);\n\n\t\t\t\t} else if (stepPart == 2) {\n\t\t\t\t\tparticleProduceFootSplash(this, adjustedFootPos, 0.15f, 4);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (IsPlayer() && !walkRunAssoc && bIsLanding) {\n\t\tif (!footPosLok)\n\t\t\tTransformToNode(footPosL, PED_FOOTL);\n\n\t\tCVector forward = GetForward();\n\n\t\tCVector adjustedFootPosL = footPosL;\n\t\tadjustedFootPosL.z -= 0.1f;\n\t\tadjustedFootPosL += 0.2f * forward;\n\t\tif (bDoBloodyFootprints) {\n\t\t\tCVector2D top(forward * 0.26f);\n\t\t\tCVector2D right(GetRight() * 0.14f);\n\n\t\t\tCShadows::AddPermanentShadow(SHADOWTYPE_DARK, gpBloodPoolTex, &adjustedFootPosL,\n\t\t\t\ttop.x, top.y,\n\t\t\t\tright.x, right.y,\n\t\t\t\t255, 255, 0, 0, 4.0f, 3000, 1.0f);\n\n\t\t\tif (m_bloodyFootprintCountOrDeathTime <= 20) {\n\t\t\t\tm_bloodyFootprintCountOrDeathTime = 0;\n\t\t\t\tbDoBloodyFootprints = false;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tm_bloodyFootprintCountOrDeathTime -= 20;\n\t\t\t}\n\t\t}\n\t\tif (!isSkater) {\n\t\t\tif (m_nSurfaceTouched == SURFACE_SAND || m_nSurfaceTouched == SURFACE_SAND_BEACH) {\n\t\t\t\tCVector2D top(forward * -0.26f);\n\t\t\t\tCVector2D right(GetRight() * 0.14f);\n\n\t\t\t\tCShadows::AddPermanentShadow(SHADOWTYPE_DARK, gpShadowPedTex, &adjustedFootPosL,\n\t\t\t\t\ttop.x, top.y,\n\t\t\t\t\tright.x, right.y,\n\t\t\t\t\t120, 250, 250, 50, 4.0f, 5000, 1.0f);\n\t\t\t}\n\t\t}\n\t\tif(!footPosRok)\n\t\t\tTransformToNode(footPosR, PED_FOOTR);\n\n\t\tCVector adjustedFootPosR = footPosR;\n\t\tadjustedFootPosR.z -= 0.1f;\n\t\tadjustedFootPosR += 0.2f * forward;\n\n\t\tif (bDoBloodyFootprints) {\n\t\t\tCVector2D top(forward * 0.26f);\n\t\t\tCVector2D right(GetRight() * 0.1f);\n\n\t\t\tCShadows::AddPermanentShadow(SHADOWTYPE_DARK, gpBloodPoolTex, &adjustedFootPosR,\n\t\t\t\ttop.x, top.y,\n\t\t\t\tright.x, right.y,\n\t\t\t\t255, 255, 0, 0, 4.0f, 3000, 1.0f);\n\n\t\t\tif (m_bloodyFootprintCountOrDeathTime <= 20) {\n\t\t\t\tm_bloodyFootprintCountOrDeathTime = 0;\n\t\t\t\tbDoBloodyFootprints = false;\n\t\t\t} else {\n\t\t\t\tm_bloodyFootprintCountOrDeathTime -= 20;\n\t\t\t}\n\t\t}\n\t\tif (!isSkater) {\n\t\t\tif (m_nSurfaceTouched == SURFACE_SAND || m_nSurfaceTouched == SURFACE_SAND_BEACH) {\n\t\t\t\tCVector2D top(forward * -0.26f);\n\t\t\t\tCVector2D right(GetRight() * 0.14f);\n\n\t\t\t\tCShadows::AddPermanentShadow(SHADOWTYPE_DARK, gpShadowPedTex, &adjustedFootPosR,\n\t\t\t\t\ttop.x, top.y,\n\t\t\t\t\tright.x, right.y,\n\t\t\t\t\t120, 250, 250, 50, 4.0f, 5000, 1.0f);\n\t\t\t}\n\t\t}\n\t}\n\n\tif (m_nSurfaceTouched == SURFACE_WATER) {\n\t\tCRGBA rubberSmokeColor(255, 255, 255, 196);\n\t\tfloat pedSpeed = CVector2D(m_vecMoveSpeed).Magnitude();\n\t\tif (pedSpeed > 0.03f && CTimer::GetFrameCounter() % 2 == 0 && pedSpeed > 0.13f) {\n\t\t\tfloat particleSize = pedSpeed * 2.0f;\n\n\t\t\tif (particleSize < 0.25f)\n\t\t\t\tparticleSize = 0.25f;\n\n\t\t\tif (particleSize > 0.75f)\n\t\t\t\tparticleSize = 0.75f;\n\n\t\t\tCVector particlePos = GetPosition() + GetForward() * 0.3f;\n\t\t\tparticlePos.z -= 1.2f;\n\n\t\t\tCVector particleDir = m_vecMoveSpeed * -0.75f;\n\n\t\t\tparticleDir.z = CGeneral::GetRandomNumberInRange(0.01f, 0.03f);\n\t\t\tCParticle::AddParticle(PARTICLE_CAR_SPLASH, particlePos, particleDir, nil, 0.5f * particleSize, CRGBA(0,0,0,0), 0, 0, 0, 0);\n\t\t\tCParticle::AddParticle(PARTICLE_RUBBER_SMOKE, particlePos, particleDir, nil, particleSize, rubberSmokeColor, 0, 0, 0, 0);\n\t\t}\n\n\t\tif (m_nPedState == PED_JUMP) {\n\t\t\tCVector particlePos = GetPosition();\n\t\t\tparticlePos.z -= 0.1f;\n\n\t\t\tCVector particleDir(0.0f, 0.075f, 0.0f);\n\t\t\tCParticle::AddParticle(PARTICLE_CAR_SPLASH, particlePos, particleDir, nil, 0.005f, CRGBA(0, 0, 0, 0), 0, 0, 0, 0);\n\t\t\tparticleDir.x += CGeneral::GetRandomNumberInRange(-0.05f, 0.05f);\n\t\t\tparticleDir.y += CGeneral::GetRandomNumberInRange(-0.05f, 0.05f);\n\t\t\tparticleDir.z -= CGeneral::GetRandomNumberInRange(0.025f, 0.05f);\n\t\t\tCParticle::AddParticle(PARTICLE_RUBBER_SMOKE, particlePos, particleDir, nil, 0.5f, rubberSmokeColor, 0, 0, 0, 0);\n\t\t}\n\t}\n}\n\n// Actually GetLocalDirectionTo(Turn/Look)\nint\nCPed::GetLocalDirection(const CVector2D &posOffset)\n{\n\tint direction;\n\tfloat angle;\n\n\tfor (angle = posOffset.Heading() - m_fRotationCur + DEGTORAD(45.0f); angle < 0.0f; angle += TWOPI);\n\n\tfor (direction = RADTODEG(angle)/90.0f; direction > 3; direction -= 4);\n\n\t// 0-forward, 1-left, 2-backward, 3-right.\n\treturn direction;\n}\n\nbool\nCPed::SetDirectionToWalkAroundVehicle(CVehicle* veh)\n{\n\treturn SetFollowPath(m_vecSeekPos, 0.0f, m_nMoveState, veh, m_pedInObjective, m_nMoveState == PEDMOVE_WALK ? 2000 : 250);\n}\n\nvoid\nCPed::SetDirectionToWalkAroundObject(CEntity *obj)\n{\n\tfloat distLimitForTimer = 8.0f;\n\tCColModel *objCol = CModelInfo::GetModelInfo(obj->GetModelIndex())->GetColModel();\n\tCVector objColMin = objCol->boundingBox.min;\n\tCVector objColMax = objCol->boundingBox.max;\n\tCVector objColCenter = (objColMin + objColMax) / 2.0f;\n\tCMatrix objMat(obj->GetMatrix());\n\tfloat dirToSet = obj->GetForward().Heading();\n\tbool goingToEnterCarAndItsVan = false;\n\tbool goingToEnterCar = false;\n\tbool objUpsideDown = false;\n\n\tfloat checkIntervalInDist = (objColMax.y - objColMin.y) * 0.1f;\n\tfloat checkIntervalInTime;\n\n\tif (m_nMoveState == PEDMOVE_NONE || m_nMoveState == PEDMOVE_STILL)\n\t\treturn;\n\n\tif (CharCreatedBy != MISSION_CHAR && obj->GetModelIndex() == MI_PHONEBOOTH1) {\n\t\tbool isRunning = m_nMoveState == PEDMOVE_RUN || m_nMoveState == PEDMOVE_SPRINT;\n\t\tSetFindPathAndFlee(obj, 5000, !isRunning);\n\t\treturn;\n\t}\n\n\tCVector2D adjustedColMin(objColMin.x - 0.35f, objColMin.y - 0.35f);\n\tCVector2D adjustedColMax(objColMax.x + 0.35f, objColMax.y + 0.35f);\n\n\tcheckIntervalInDist = Max(checkIntervalInDist, 0.5f);\n\tcheckIntervalInDist = Min(checkIntervalInDist, (objColMax.z - objColMin.z) / 2.0f);\n\tcheckIntervalInDist = Min(checkIntervalInDist, (adjustedColMax.x - adjustedColMin.x) / 2.0f);\n\n\tif (objMat.GetUp().z < 0.0f)\n\t\tobjUpsideDown = true;\n\n\tif (obj->GetModelIndex() != MI_TRAFFICLIGHTS && obj->GetModelIndex() != MI_SINGLESTREETLIGHTS1 && obj->GetModelIndex() != MI_SINGLESTREETLIGHTS2) {\n\t\tobjColCenter = obj->GetMatrix() * objColCenter;\n\t} else {\n\t\tcheckIntervalInDist = 0.4f;\n\t\tif (objMat.GetUp().z <= 0.57f) {\n\n\t\t\t// Specific calculations for traffic lights, didn't get a bit.\n\t\t\tadjustedColMin.x = 1.2f * (adjustedColMin.x < adjustedColMin.y ? adjustedColMin.x : adjustedColMin.y);\n\t\t\tadjustedColMax.x = 1.2f * (adjustedColMax.x > adjustedColMax.y ? adjustedColMax.x : adjustedColMax.y);\n\t\t\tadjustedColMin.y = 1.2f * objColMin.z;\n\t\t\tadjustedColMax.y = 1.2f * objColMax.z;\n\t\t\tdirToSet = objMat.GetUp().Heading();\n\t\t\tobjMat.SetUnity();\n\t\t\tobjMat.RotateZ(dirToSet);\n\t\t\tobjMat.GetPosition() += obj->GetPosition();\n\t\t\tobjColCenter = obj->GetPosition();\n\t\t} else {\n\t\t\tobjColCenter.x = adjustedColMax.x - 0.25f;\n\t\t\tobjColCenter = obj->GetMatrix() * objColCenter;\n\t\t\tdistLimitForTimer = 0.75f;\n\t\t}\n\t\tobjUpsideDown = false;\n\t}\n\tfloat oldRotDest = m_fRotationDest;\n\tfloat angleToFaceObjCenter = (objColCenter - GetPosition()).Heading();\n\tfloat angleDiffBtwObjCenterAndForward = CGeneral::LimitRadianAngle(dirToSet - angleToFaceObjCenter);\n\tfloat objTopRightHeading = Atan2(adjustedColMax.x - adjustedColMin.x, adjustedColMax.y - adjustedColMin.y);\n\n\tif (IsPlayer()) {\n\t\tif (FindPlayerPed()->m_fMoveSpeed <= 0.0f)\n\t\t\tcheckIntervalInTime = 0.0f;\n\t\telse\n\t\t\tcheckIntervalInTime = 2.0f / FindPlayerPed()->m_fMoveSpeed;\n\t} else {\n\t\tswitch (m_nMoveState) {\n\t\t\tcase PEDMOVE_WALK:\n\t\t\t\tcheckIntervalInTime = 2.0f;\n\t\t\t\tbreak;\n\t\t\tcase PEDMOVE_RUN:\n\t\t\t\tcheckIntervalInTime = 0.5f;\n\t\t\t\tbreak;\n\t\t\tcase PEDMOVE_SPRINT:\n\t\t\t\tcheckIntervalInTime = 0.5f;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tcheckIntervalInTime = 0.0f;\n\t\t\t\tbreak;\n\t\t}\n\t}\n\tif (m_pSeekTarget == obj && obj->IsVehicle()) {\n\t\tif (m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER || m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER\n\t\t\t|| m_objective == OBJECTIVE_SOLICIT_VEHICLE) {\n\t\t\tgoingToEnterCar = true;\n\t\t\tif (IsPlayer())\n\t\t\t\tcheckIntervalInTime = 0.0f;\n\n\t\t\tif (((CVehicle*)obj)->bIsVan)\n\t\t\t\tgoingToEnterCarAndItsVan = true;\n\t\t}\n\t}\n\n\tint entityOnTopLeftOfObj = 0;\n\tint entityOnBottomLeftOfObj = 0;\n\tint entityOnTopRightOfObj = 0;\n\tint entityOnBottomRightOfObj = 0;\n\n\tif (CTimer::GetTimeInMilliseconds() > m_collidingThingTimer || m_collidingEntityWhileFleeing != obj) {\n\t\tbool collidingThingChanged = true;\n\t\tCEntity *obstacle;\n\n\t\tif (!obj->IsVehicle() || objUpsideDown) {\n\t\t\tcollidingThingChanged = false;\n\t\t} else {\n\t\t\tfloat adjustedCheckInterval = 0.7f * checkIntervalInDist;\n\t\t\tCVector posToCheck;\n\n\t\t\t// Top left of obj\n\t\t\tposToCheck.x = adjustedColMin.x + adjustedCheckInterval;\n\t\t\tposToCheck.y = adjustedColMax.y - adjustedCheckInterval;\n\t\t\tposToCheck.z = 0.0f;\n\t\t\tposToCheck = objMat * posToCheck;\n\t\t\tposToCheck.z += 0.6f;\n\t\t\tobstacle = CWorld::TestSphereAgainstWorld(posToCheck, checkIntervalInDist, obj,\n\t\t\t\ttrue, true, false, true, false, false);\n\t\t\tif (obstacle) {\n\t\t\t\tif (obstacle->IsBuilding()) {\n\t\t\t\t\tentityOnTopLeftOfObj = 1;\n\t\t\t\t} else if (obstacle->IsVehicle()) {\n\t\t\t\t\tentityOnTopLeftOfObj = 2;\n\t\t\t\t} else {\n\t\t\t\t\tentityOnTopLeftOfObj = 3;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Top right of obj\n\t\t\tposToCheck.x = adjustedColMax.x - adjustedCheckInterval;\n\t\t\tposToCheck.y = adjustedColMax.y - adjustedCheckInterval;\n\t\t\tposToCheck.z = 0.0f;\n\t\t\tposToCheck = objMat * posToCheck;\n\t\t\tposToCheck.z += 0.6f;\n\t\t\tobstacle = CWorld::TestSphereAgainstWorld(posToCheck, checkIntervalInDist, obj,\n\t\t\t\ttrue, true, false, true, false, false);\n\t\t\tif (obstacle) {\n\t\t\t\tif (obstacle->IsBuilding()) {\n\t\t\t\t\tentityOnTopRightOfObj = 1;\n\t\t\t\t} else if (obstacle->IsVehicle()) {\n\t\t\t\t\tentityOnTopRightOfObj = 2;\n\t\t\t\t} else {\n\t\t\t\t\tentityOnTopRightOfObj = 3;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Bottom right of obj\n\t\t\tposToCheck.x = adjustedColMax.x - adjustedCheckInterval;\n\t\t\tposToCheck.y = adjustedColMin.y + adjustedCheckInterval;\n\t\t\tposToCheck.z = 0.0f;\n\t\t\tposToCheck = objMat * posToCheck;\n\t\t\tposToCheck.z += 0.6f;\n\t\t\tobstacle = CWorld::TestSphereAgainstWorld(posToCheck, checkIntervalInDist, obj,\n\t\t\t\ttrue, true, false, true, false, false);\n\t\t\tif (obstacle) {\n\t\t\t\tif (obstacle->IsBuilding()) {\n\t\t\t\t\tentityOnBottomRightOfObj = 1;\n\t\t\t\t} else if (obstacle->IsVehicle()) {\n\t\t\t\t\tentityOnBottomRightOfObj = 2;\n\t\t\t\t} else {\n\t\t\t\t\tentityOnBottomRightOfObj = 3;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Bottom left of obj\n\t\t\tposToCheck.x = adjustedColMin.x + adjustedCheckInterval;\n\t\t\tposToCheck.y = adjustedColMin.y + adjustedCheckInterval;\n\t\t\tposToCheck.z = 0.0f;\n\t\t\tposToCheck = objMat * posToCheck;\n\t\t\tposToCheck.z += 0.6f;\n\t\t\tobstacle = CWorld::TestSphereAgainstWorld(posToCheck, checkIntervalInDist, obj,\n\t\t\t\ttrue, true, false, true, false, false);\n\t\t\tif (obstacle) {\n\t\t\t\tif (obstacle->IsBuilding()) {\n\t\t\t\t\tentityOnBottomLeftOfObj = 1;\n\t\t\t\t} else if (obstacle->IsVehicle()) {\n\t\t\t\t\tentityOnBottomLeftOfObj = 2;\n\t\t\t\t} else {\n\t\t\t\t\tentityOnBottomLeftOfObj = 3;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (!entityOnTopLeftOfObj && !entityOnTopRightOfObj) {\n\t\t\tCVector topLeftCorner(adjustedColMin.x - 0.3f, adjustedColMax.y + 0.3f, 0.0f);\n\t\t\ttopLeftCorner = objMat * topLeftCorner;\n\t\t\tCVector topRightCorner(adjustedColMax.x + 0.3f, adjustedColMax.y + 0.3f, 0.0f);\n\t\t\ttopRightCorner = objMat * topRightCorner;\n\t\t\tCColPoint foundCol;\n\t\t\tCEntity *foundEnt;\n\t\t\tif (CWorld::ProcessLineOfSight(topLeftCorner, topRightCorner, foundCol, foundEnt, true, true, false, true, false, false, false, false)) {\n\t\t\t\tswitch (foundEnt->GetType()) {\n\t\t\t\tcase ENTITY_TYPE_VEHICLE:\n\t\t\t\t\tentityOnTopRightOfObj = 2;\n\t\t\t\t\tentityOnTopLeftOfObj = 2;\n\t\t\t\t\tbreak;\n\t\t\t\tcase ENTITY_TYPE_BUILDING:\n\t\t\t\t\tentityOnTopRightOfObj = 1;\n\t\t\t\t\tentityOnTopLeftOfObj = 1;\n\t\t\t\t\tbreak;\n\t\t\t\tcase ENTITY_TYPE_OBJECT:\n\t\t\t\t\tentityOnTopRightOfObj = 3;\n\t\t\t\t\tentityOnTopLeftOfObj = 3;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (!entityOnBottomRightOfObj && !entityOnBottomLeftOfObj) {\n\t\t\tCVector bottomRightCorner(adjustedColMax.x + 0.3f, adjustedColMin.y - 0.3f, 0.0f);\n\t\t\tbottomRightCorner = objMat * bottomRightCorner;\n\t\t\tCVector bottomLeftCorner(adjustedColMin.x - 0.3f, adjustedColMin.y - 0.3f, 0.0f);\n\t\t\tbottomLeftCorner = objMat * bottomLeftCorner;\n\t\t\tCColPoint foundCol;\n\t\t\tCEntity* foundEnt;\n\t\t\tif (CWorld::ProcessLineOfSight(bottomRightCorner, bottomLeftCorner, foundCol, foundEnt, true, true, false, true, false, false, false, false)) {\n\t\t\t\tswitch (foundEnt->GetType()) {\n\t\t\t\tcase ENTITY_TYPE_VEHICLE:\n\t\t\t\t\tentityOnBottomLeftOfObj = 2;\n\t\t\t\t\tentityOnBottomRightOfObj = 2;\n\t\t\t\t\tbreak;\n\t\t\t\tcase ENTITY_TYPE_BUILDING:\n\t\t\t\t\tentityOnBottomLeftOfObj = 1;\n\t\t\t\t\tentityOnBottomRightOfObj = 1;\n\t\t\t\t\tbreak;\n\t\t\t\tcase ENTITY_TYPE_OBJECT:\n\t\t\t\t\tentityOnBottomLeftOfObj = 3;\n\t\t\t\t\tentityOnBottomRightOfObj = 3;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (entityOnTopLeftOfObj && entityOnTopRightOfObj && entityOnBottomRightOfObj && entityOnBottomLeftOfObj) {\n\t\t\tcollidingThingChanged = false;\n\t\t\tentityOnTopLeftOfObj = 0;\n\t\t\tentityOnBottomLeftOfObj = 0;\n\t\t\tentityOnTopRightOfObj = 0;\n\t\t\tentityOnBottomRightOfObj = 0;\n\t\t}\n\n\t\tif (!collidingThingChanged) {\n\t\t\tm_walkAroundType = 0;\n\t\t} else {\n\t\t\tif (Abs(angleDiffBtwObjCenterAndForward) >= objTopRightHeading) {\n\t\t\t\tif (PI - objTopRightHeading >= Abs(angleDiffBtwObjCenterAndForward)) {\n\t\t\t\t\tif ((angleDiffBtwObjCenterAndForward <= 0.0f || objUpsideDown) && (angleDiffBtwObjCenterAndForward < 0.0f || !objUpsideDown)) {\n\t\t\t\t\t\tif (goingToEnterCar && (m_vehDoor == CAR_DOOR_RF || m_vehDoor == CAR_DOOR_RR)) {\n\t\t\t\t\t\t\tm_walkAroundType = 0;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (CGeneral::LimitRadianAngle(m_fRotationDest - angleToFaceObjCenter) >= 0.0f) {\n\t\t\t\t\t\t\t\tif (entityOnBottomRightOfObj == 1 || entityOnBottomRightOfObj && !entityOnTopLeftOfObj && !entityOnTopRightOfObj) {\n\t\t\t\t\t\t\t\t\tm_walkAroundType = 1;\n\t\t\t\t\t\t\t\t} else if (entityOnBottomLeftOfObj == 1 || entityOnBottomLeftOfObj && !entityOnTopLeftOfObj && !entityOnTopRightOfObj) {\n\t\t\t\t\t\t\t\t\tm_walkAroundType = 1;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tif (entityOnTopRightOfObj == 1 || entityOnTopRightOfObj && !entityOnBottomRightOfObj && !entityOnBottomLeftOfObj) {\n\t\t\t\t\t\t\t\t\tm_walkAroundType = 4;\n\t\t\t\t\t\t\t\t} else if (entityOnTopLeftOfObj == 1 || entityOnTopLeftOfObj && !entityOnBottomRightOfObj && !entityOnBottomLeftOfObj) {\n\t\t\t\t\t\t\t\t\tm_walkAroundType = 4;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (goingToEnterCar && (m_vehDoor == CAR_DOOR_LF || m_vehDoor == CAR_DOOR_LR)) {\n\t\t\t\t\t\t\tm_walkAroundType = 0;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (CGeneral::LimitRadianAngle(m_fRotationDest - angleToFaceObjCenter) <= 0.0f) {\n\t\t\t\t\t\t\t\tif (entityOnBottomLeftOfObj == 1 || entityOnBottomLeftOfObj && !entityOnTopLeftOfObj && !entityOnTopRightOfObj) {\n\t\t\t\t\t\t\t\t\tm_walkAroundType = 2;\n\t\t\t\t\t\t\t\t} else if (entityOnBottomRightOfObj == 1 || entityOnBottomRightOfObj && !entityOnTopLeftOfObj && !entityOnTopRightOfObj) {\n\t\t\t\t\t\t\t\t\tm_walkAroundType = 2;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tif (entityOnTopLeftOfObj == 1 || entityOnTopLeftOfObj && !entityOnBottomRightOfObj && !entityOnBottomLeftOfObj) {\n\t\t\t\t\t\t\t\t\tm_walkAroundType = 3;\n\t\t\t\t\t\t\t\t} else if (entityOnTopRightOfObj == 1 || entityOnTopRightOfObj && !entityOnBottomRightOfObj && !entityOnBottomLeftOfObj) {\n\t\t\t\t\t\t\t\t\tm_walkAroundType = 3;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else if (goingToEnterCar && (m_vehDoor == CAR_DOOR_LF || m_vehDoor == CAR_DOOR_LR)\n\t\t\t\t\t|| CGeneral::LimitRadianAngle(m_fRotationDest - angleToFaceObjCenter) < 0.0f) {\n\t\t\t\t\tif (entityOnTopLeftOfObj == 1 || entityOnTopLeftOfObj && !entityOnTopRightOfObj && !entityOnBottomRightOfObj) {\n\t\t\t\t\t\tm_walkAroundType = 3;\n\t\t\t\t\t}\n\t\t\t\t} else if (entityOnTopRightOfObj == 1 || entityOnTopRightOfObj && !entityOnTopLeftOfObj && !entityOnBottomLeftOfObj) {\n\t\t\t\t\tm_walkAroundType = 4;\n\t\t\t\t}\n\t\t\t} else if (goingToEnterCar && (m_vehDoor == CAR_DOOR_LF || m_vehDoor == CAR_DOOR_LR)\n\t\t\t\t|| CGeneral::LimitRadianAngle(m_fRotationDest - angleToFaceObjCenter) > 0.0f) {\n\t\t\t\tif (entityOnBottomLeftOfObj == 1 || entityOnBottomLeftOfObj && !entityOnTopRightOfObj && !entityOnBottomRightOfObj) {\n\t\t\t\t\tm_walkAroundType = 2;\n\t\t\t\t}\n\t\t\t} else if (entityOnBottomRightOfObj == 1 || entityOnBottomRightOfObj && !entityOnTopLeftOfObj && !entityOnBottomLeftOfObj) {\n\t\t\t\tm_walkAroundType = 1;\n\t\t\t} else {\n\t\t\t\tm_walkAroundType = 0;\n\t\t\t}\n\t\t}\n\t}\n\tm_collidingEntityWhileFleeing = obj;\n\tm_collidingEntityWhileFleeing->RegisterReference((CEntity**) &m_collidingEntityWhileFleeing);\n\n\t// TODO: This random may need to be changed.\n\tm_collidingThingTimer = CTimer::GetTimeInMilliseconds() + 512 + CGeneral::GetRandomNumber();\n\n\tCVector localPosToHead;\n\n\tif (Abs(angleDiffBtwObjCenterAndForward) < objTopRightHeading) {\n\t\tif (goingToEnterCar) {\n\t\t\tif (goingToEnterCarAndItsVan) {\n\t\t\t\tif (m_vehDoor == CAR_DOOR_LR || m_vehDoor == CAR_DOOR_RR)\n\t\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (m_vehDoor != CAR_DOOR_LF && m_vehDoor != CAR_DOOR_LR && (!entityOnBottomRightOfObj || entityOnBottomLeftOfObj)) {\n\t\t\t\tm_fRotationDest = CGeneral::LimitRadianAngle(dirToSet - HALFPI);\n\t\t\t\tlocalPosToHead.x = adjustedColMax.x;\n\t\t\t\tlocalPosToHead.z = 0.0f;\n\t\t\t\tlocalPosToHead.y = adjustedColMin.y;\n\t\t\t} else {\n\t\t\t\tm_fRotationDest = CGeneral::LimitRadianAngle(HALFPI + dirToSet);\n\t\t\t\tlocalPosToHead.x = adjustedColMin.x;\n\t\t\t\tlocalPosToHead.z = 0.0f;\n\t\t\t\tlocalPosToHead.y = adjustedColMin.y;\n\t\t\t}\n\t\t} else {\n\t\t\tif (m_walkAroundType != 1 && m_walkAroundType != 4\n\t\t\t\t&& (m_walkAroundType || CGeneral::LimitRadianAngle(m_fRotationDest - angleToFaceObjCenter) <= 0.0f)) {\n\n\t\t\t\tm_fRotationDest = CGeneral::LimitRadianAngle(dirToSet - HALFPI);\n\t\t\t\tlocalPosToHead.x = adjustedColMax.x;\n\t\t\t\tlocalPosToHead.z = 0.0f;\n\t\t\t\tlocalPosToHead.y = adjustedColMin.y;\n\t\t\t} else {\n\t\t\t\tm_fRotationDest = CGeneral::LimitRadianAngle(HALFPI + dirToSet);\n\t\t\t\tlocalPosToHead.x = adjustedColMin.x;\n\t\t\t\tlocalPosToHead.z = 0.0f;\n\t\t\t\tlocalPosToHead.y = adjustedColMin.y;\n\t\t\t}\n\t\t}\n\t} else {\n\t\tif (PI - objTopRightHeading >= Abs(angleDiffBtwObjCenterAndForward)) {\n\t\t\tif (angleDiffBtwObjCenterAndForward <= 0.0f) {\n\t\t\t\tif (!goingToEnterCar || !goingToEnterCarAndItsVan || m_vehDoor != CAR_DOOR_LR && m_vehDoor != CAR_DOOR_RR) {\n\t\t\t\t\tif (goingToEnterCar) {\n\t\t\t\t\t\tif (m_vehDoor == CAR_DOOR_RF || (m_vehDoor == CAR_DOOR_RR && !goingToEnterCarAndItsVan))\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (m_walkAroundType == 4 || m_walkAroundType == 3\n\t\t\t\t\t\t|| !m_walkAroundType && CGeneral::LimitRadianAngle(m_fRotationDest - angleToFaceObjCenter) > 0.0f) {\n\n\t\t\t\t\t\tm_fRotationDest = CGeneral::LimitRadianAngle(PI + dirToSet);\n\t\t\t\t\t\tlocalPosToHead.x = adjustedColMax.x;\n\t\t\t\t\t\tlocalPosToHead.z = 0.0f;\n\t\t\t\t\t\tlocalPosToHead.y = adjustedColMin.y;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tm_fRotationDest = dirToSet;\n\t\t\t\t\t\tlocalPosToHead.x = adjustedColMax.x;\n\t\t\t\t\t\tlocalPosToHead.z = 0.0f;\n\t\t\t\t\t\tlocalPosToHead.y = adjustedColMax.y;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tm_fRotationDest = CGeneral::LimitRadianAngle(PI + dirToSet);\n\t\t\t\t\tlocalPosToHead.x = adjustedColMax.x;\n\t\t\t\t\tlocalPosToHead.z = 0.0f;\n\t\t\t\t\tlocalPosToHead.y = adjustedColMin.y;\n\t\t\t\t}\n\t\t\t} else if (goingToEnterCar && goingToEnterCarAndItsVan && (m_vehDoor == CAR_DOOR_LR || m_vehDoor == CAR_DOOR_RR)) {\n\t\t\t\tm_fRotationDest = CGeneral::LimitRadianAngle(PI + dirToSet);\n\t\t\t\tlocalPosToHead.x = adjustedColMin.x;\n\t\t\t\tlocalPosToHead.z = 0.0f;\n\t\t\t\tlocalPosToHead.y = adjustedColMin.y;\n\t\t\t} else {\n\t\t\t\tif (goingToEnterCar) {\n\t\t\t\t\tif (m_vehDoor == CAR_DOOR_LF || m_vehDoor == CAR_DOOR_LR && !goingToEnterCarAndItsVan)\n\t\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (m_walkAroundType == 1 || m_walkAroundType == 2\n\t\t\t\t\t|| !m_walkAroundType && CGeneral::LimitRadianAngle(m_fRotationDest - angleToFaceObjCenter) > 0.0f) {\n\n\t\t\t\t\tm_fRotationDest = dirToSet;\n\t\t\t\t\tlocalPosToHead.x = adjustedColMin.x;\n\t\t\t\t\tlocalPosToHead.z = 0.0f;\n\t\t\t\t\tlocalPosToHead.y = adjustedColMax.y;\n\t\t\t\t} else {\n\t\t\t\t\tm_fRotationDest = CGeneral::LimitRadianAngle(PI + dirToSet);\n\t\t\t\t\tlocalPosToHead.x = adjustedColMin.x;\n\t\t\t\t\tlocalPosToHead.z = 0.0f;\n\t\t\t\t\tlocalPosToHead.y = adjustedColMin.y;\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tif (goingToEnterCar && (!goingToEnterCarAndItsVan || m_vehDoor != CAR_DOOR_LR && m_vehDoor != CAR_DOOR_RR)) {\n\t\t\t\tif (m_vehDoor != CAR_DOOR_LF && m_vehDoor != CAR_DOOR_LR && (!entityOnTopRightOfObj || entityOnTopLeftOfObj)) {\n\n\t\t\t\t\tm_fRotationDest = CGeneral::LimitRadianAngle(dirToSet - HALFPI);\n\t\t\t\t\tlocalPosToHead.x = adjustedColMax.x;\n\t\t\t\t\tlocalPosToHead.z = 0.0f;\n\t\t\t\t\tlocalPosToHead.y = adjustedColMax.y;\n\t\t\t\t} else {\n\t\t\t\t\tm_fRotationDest = CGeneral::LimitRadianAngle(HALFPI + dirToSet);\n\t\t\t\t\tlocalPosToHead.x = adjustedColMin.x;\n\t\t\t\t\tlocalPosToHead.z = 0.0f;\n\t\t\t\t\tlocalPosToHead.y = adjustedColMax.y;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (m_walkAroundType == 2 || m_walkAroundType == 3\n\t\t\t\t\t|| !m_walkAroundType && CGeneral::LimitRadianAngle(m_fRotationDest - angleToFaceObjCenter) > 0.0f) {\n\n\t\t\t\t\tm_fRotationDest = CGeneral::LimitRadianAngle(dirToSet - HALFPI);\n\t\t\t\t\tlocalPosToHead.x = adjustedColMax.x;\n\t\t\t\t\tlocalPosToHead.z = 0.0f;\n\t\t\t\t\tlocalPosToHead.y = adjustedColMax.y;\n\t\t\t\t} else {\n\t\t\t\t\tm_fRotationDest = CGeneral::LimitRadianAngle(HALFPI + dirToSet);\n\t\t\t\t\tlocalPosToHead.x = adjustedColMin.x;\n\t\t\t\t\tlocalPosToHead.z = 0.0f;\n\t\t\t\t\tlocalPosToHead.y = adjustedColMax.y;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tif (objUpsideDown)\n\t\tlocalPosToHead.x = localPosToHead.x * -1.0f;\n\n\tlocalPosToHead = objMat * localPosToHead;\n\tm_actionX = localPosToHead.x;\n\tm_actionY = localPosToHead.y;\n\tlocalPosToHead -= GetPosition();\n\tm_fRotationDest = CGeneral::LimitRadianAngle(localPosToHead.Heading());\n\n\tif (m_fRotationDest != m_fRotationCur && bHitSomethingLastFrame) {\n\t\tif (m_fRotationDest == oldRotDest) {\n\t\t\tm_fRotationDest = oldRotDest;\n\t\t} else {\n\t\t\tm_fRotationDest = CGeneral::LimitRadianAngle(PI + dirToSet);\n\t\t}\n\t}\n\n\tfloat dist = localPosToHead.Magnitude2D();\n\tif (dist < 0.5f)\n\t\tdist = 0.5f;\n\n\tif (dist > distLimitForTimer)\n\t\tdist = distLimitForTimer;\n\tm_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 280.0f * dist * checkIntervalInTime;\n}\n\nbool\nCPed::IsPedInControl(void)\n{\n\treturn m_nPedState <= PED_STATES_NO_AI\n\t\t&& !bIsInTheAir && !bIsLanding\n\t\t&& m_fHealth > 0.0f;\n}\n\nbool\nCPed::IsPedShootable(void)\n{\n\treturn m_nPedState <= PED_STATES_NO_ST;\n}\n\nbool\nCPed::UseGroundColModel(void)\n{\n\treturn m_nPedState == PED_FALL ||\n\t\tm_nPedState == PED_DIVE_AWAY ||\n\t\tm_nPedState == PED_DIE ||\n\t\tm_nPedState == PED_DEAD;\n}\n\nbool\nCPed::CanPedReturnToState(void)\n{\n\treturn m_nPedState <= PED_STATES_NO_AI && m_nPedState != PED_AIM_GUN && m_nPedState != PED_ATTACK &&\n\t\tm_nPedState != PED_FIGHT && m_nPedState != PED_STEP_AWAY && m_nPedState != PED_SNIPER_MODE && m_nPedState != PED_LOOK_ENTITY;\n}\n\nbool\nCPed::CanSetPedState(void)\n{\n\treturn !DyingOrDead() && m_nPedState != PED_ARRESTED && !EnteringCar() && m_nPedState != PED_STEAL_CAR;\n}\n\nbool\nCPed::CanStrafeOrMouseControl(void)\n{\n#ifdef FREE_CAM\n\tif (CCamera::bFreeCam)\n\t\treturn false;\n#endif\n\treturn m_nPedState == PED_NONE || m_nPedState == PED_IDLE || m_nPedState == PED_FLEE_POS || m_nPedState == PED_FLEE_ENTITY ||\n\t\tm_nPedState == PED_ATTACK || m_nPedState == PED_FIGHT || m_nPedState == PED_AIM_GUN || m_nPedState == PED_JUMP || m_nPedState == PED_ANSWER_MOBILE;\n}\n\nvoid\nCPed::PedSetPreviousStateCB(CAnimBlendAssociation* assoc, void* arg)\n{\n\tCPed* ped = (CPed*)arg;\n\tped->RestorePreviousState();\n\tped->m_pVehicleAnim = nil;\n}\n\nvoid\nCPed::PedGetupCB(CAnimBlendAssociation* animAssoc, void* arg)\n{\n\tCPed* ped = (CPed*)arg;\n\n\tif (ped->m_nPedState == PED_GETUP)\n\t\tRpAnimBlendClumpSetBlendDeltas(ped->GetClump(), ASSOC_PARTIAL, -1000.0f);\n\n\tped->bFallenDown = false;\n\tanimAssoc->blendDelta = -1000.0f;\n\tif (ped->m_nPedState == PED_GETUP)\n\t\tped->RestorePreviousState();\n\n\tif (ped->bFleeWhenStanding && ped->m_threatEx) {\n\t\tped->SetFlee(ped->m_threatEx, 10000);\n\t\tped->Say(SOUND_PED_FLEE_SPRINT);\n\t\tped->bFleeWhenStanding = false;\n\t\tped->m_threatEx = nil;\n\n\t} else if (ped->bGotUpOfMyOwnAccord) {\n\t\tped->SetObjective(OBJECTIVE_NONE);\n\t\tped->SetWanderPath(CGeneral::GetRandomNumberInRange(0.f, 8.f));\n\t\tped->bGotUpOfMyOwnAccord = false;\n\n\t} else {\n\t\tif (ped->m_nPedState != PED_FLEE_POS && ped->m_nPedState != PED_FLEE_ENTITY)\n\t\t\tped->SetMoveState(PEDMOVE_STILL);\n\t\telse\n\t\t\tped->SetMoveState(PEDMOVE_RUN);\n\t\tped->SetMoveAnim();\n\t}\n\n\tped->bGetUpAnimStarted = false;\n}\n\nvoid\nCPed::PedLandCB(CAnimBlendAssociation* animAssoc, void* arg)\n{\n\tCPed* ped = (CPed*)arg;\n\n\tanimAssoc->blendDelta = -1000.0f;\n\tped->bIsLanding = false;\n\n\tif (ped->m_nPedState == PED_JUMP)\n\t\tped->RestorePreviousState();\n}\n\nvoid\nCPed::PedStaggerCB(CAnimBlendAssociation* animAssoc, void* arg)\n{\n\t/*\n\tCPed *ped = (CPed*)arg;\n\n\tif (ped->m_nPedState == PED_STAGGER)\n\t\t// nothing\n\t*/\n}\nvoid\nCPed::PedSetOutCarCB(CAnimBlendAssociation *animAssoc, void *arg)\n{\n\tCPed *ped = (CPed*)arg;\n\n\tCVehicle *veh = ped->m_pMyVehicle;\n\n\tbool startedToRun = false;\n\tped->bUsesCollision = true;\n\tped->m_actionX = 0.0f;\n\tped->m_actionY = 0.0f;\n\tped->bVehExitWillBeInstant = false;\n\tif (veh && veh->IsBoat())\n\t\tped->ApplyMoveSpeed();\n\n\tif (ped->m_objective == OBJECTIVE_LEAVE_CAR)\n\t\tped->RestorePreviousObjective();\n\telse if (ped->m_objective == OBJECTIVE_LEAVE_CAR_AND_DIE) {\n\t\tped->m_fHealth = 0.0f;\n\t\tped->SetDie(ANIM_STD_HIT_FLOOR, 4.0f, 0.5f);\n\t}\n\n\tped->bInVehicle = false;\n\tif (veh && (veh->IsCar() || veh->IsBike())) {\n\t\tCWorld::pIgnoreEntity = veh;\n\t\tif (CWorld::TestSphereAgainstWorld(ped->GetPosition() - CVector(0.f, 0.f, 0.2f),\n\t\t\t\t0.4f, veh, true, true, false, false, false, false)\n\t\t\t|| CWorld::TestSphereAgainstWorld(ped->GetPosition() + CVector(0.f, 0.f, 0.2f),\n\t\t\t\t0.4f, veh, true, true, false, false, false, false)\n\t\t\t|| !CWorld::GetIsLineOfSightClear(veh->GetPosition(), ped->GetPosition(), true, false, false, true, false, false, false)) {\n\t\t\tCWorld::pIgnoreEntity = nil;\n\t\t\tped->PositionPedOutOfCollision();\n\t\t}\n\t\tCWorld::pIgnoreEntity = nil;\n\t}\n\n\tif (ped->m_nPedState == PED_EXIT_CAR) {\n\t\tif (ped->m_nPedType == PEDTYPE_COP) {\n\t\t\tped->SetIdle();\n\t\t\tif (((CCopPed*)ped)->m_nCopType == COP_MIAMIVICE && ped->m_pMyVehicle && ped->m_pMyVehicle->pDriver == ped) {\n\t\t\t\tDMAudio.PlayOneShot(ped->m_audioEntityId, SOUND_PED_MIAMIVICE_EXITING_CAR, 0.f);\n\t\t\t}\n\t\t} else\n\t\t\tped->RestorePreviousState();\n\n\t\tveh = ped->m_pMyVehicle;\n\t\tif (ped->bFleeAfterExitingCar && veh) {\n\t\t\tped->bFleeAfterExitingCar = false;\n\t\t\tped->SetFlee(veh->GetPosition(), 12000);\n\t\t\tped->bUsePedNodeSeek = true;\n\t\t\tped->m_pNextPathNode = nil;\n\t\t\tif (CGeneral::GetRandomNumber() & 1 || ped->m_pedStats->m_fear > 70) {\n\t\t\t\tped->SetMoveState(PEDMOVE_SPRINT);\n\t\t\t\tped->Say(SOUND_PED_FLEE_SPRINT);\n\t\t\t} else {\n\t\t\t\tped->SetMoveState(PEDMOVE_RUN);\n\t\t\t\tped->Say(SOUND_PED_FLEE_RUN);\n\t\t\t}\n\t\t\tstartedToRun = true;\n\n\t\t\t// This is not a good way to do this...\n\t\t\tped->m_nLastPedState = PED_WANDER_PATH;\n\n\t\t} else if (ped->bWanderPathAfterExitingCar) {\n\t\t\tped->SetWanderPath(CGeneral::GetRandomNumberInRange(0.0f, 8.0f));\n\t\t\tped->bWanderPathAfterExitingCar = false;\n\t\t\tif (ped->m_nPedType == PEDTYPE_PROSTITUTE)\n\t\t\t\tped->SetObjectiveTimer(30000);\n\t\t\tped->m_nLastPedState = PED_NONE;\n\n\t\t} else if (ped->bGonnaKillTheCarJacker) {\n\n\t\t\t// Kill objective is already given at this point.\n\t\t\tped->bGonnaKillTheCarJacker = false;\n\t\t\tif (ped->m_pedInObjective) {\n\t\t\t\tif (!(CGeneral::GetRandomNumber() & 1)\n\t\t\t\t\t&& ped->m_nPedType != PEDTYPE_COP\n\t\t\t\t\t&& (!ped->m_pedInObjective->IsPlayer() || !CTheScripts::IsPlayerOnAMission())) {\n\t\t\t\t\tped->ClearObjective();\n\t\t\t\t\tped->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, veh);\n\t\t\t\t}\n\t\t\t\tped->m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + 1500;\n\t\t\t}\n\t\t\tint waitTime = 1500;\n\t\t\tped->SetWaitState(WAITSTATE_PLAYANIM_COWER, &waitTime);\n\t\t\tped->SetMoveState(PEDMOVE_RUN);\n\t\t\tstartedToRun = true;\n\t\t} else if (ped->m_objective == OBJECTIVE_NONE && ped->CharCreatedBy != MISSION_CHAR && ped->m_nPedState == PED_IDLE && !ped->IsPlayer()) {\n\t\t\tped->SetWanderPath(CGeneral::GetRandomNumberInRange(0.0f, 8.0f));\n\t\t}\n\t} else if (ped->m_nPedState == PED_DRIVING) {\n\t\tped->m_nPedState = PED_IDLE;\n\t}\n\n\tif (animAssoc)\n\t\tanimAssoc->blendDelta = -1000.0f;\n\n\tped->RestartNonPartialAnims();\n\tped->m_pVehicleAnim = nil;\n\tped->m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);\n\tveh = ped->m_pMyVehicle;\n\tif (veh) {\n\t\tif (ped->m_nPedType == PEDTYPE_PROSTITUTE) {\n\t\t\tif (veh->pDriver) {\n\t\t\t\tif (veh->pDriver->IsPlayer() && ped->CharCreatedBy == RANDOM_CHAR) {\n\t\t\t\t\tCWorld::Players[CWorld::PlayerInFocus].m_nNextSexMoneyUpdateTime = 0;\n\t\t\t\t\tCWorld::Players[CWorld::PlayerInFocus].m_nNextSexFrequencyUpdateTime = 0;\n\t\t\t\t\tCWorld::Players[CWorld::PlayerInFocus].m_pHooker = nil;\n\t\t\t\t\tCWorld::Players[CWorld::PlayerInFocus].m_nMoney -= 100;\n\t\t\t\t\tif (CWorld::Players[CWorld::PlayerInFocus].m_nMoney < 0)\n\t\t\t\t\t\tCWorld::Players[CWorld::PlayerInFocus].m_nMoney = 0;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (veh && veh->IsBike())\n\t\t\t// BUG? \n\t\t\tveh->m_nGettingOutFlags &= ~GetBikeDoorFlag(ped->m_vehDoor);\n\t\telse\n\t\t\tveh->m_nGettingOutFlags &= ~GetCarDoorFlag(ped->m_vehDoor);\n\n\t\tif (veh->pDriver == ped) {\n\t\t\tveh->RemoveDriver();\n#ifndef FIX_BUGS // RemoveDriver does it anyway\n\t\t\tveh->SetStatus(STATUS_ABANDONED);\n#endif\n\t\t\tif (veh->m_nDoorLock == CARLOCK_LOCKED_INITIALLY)\n\t\t\t\tveh->m_nDoorLock = CARLOCK_UNLOCKED;\n\t\t\tif (ped->m_nPedType == PEDTYPE_COP && veh->IsLawEnforcementVehicle())\n\t\t\t\tveh->ChangeLawEnforcerState(false);\n\t\t\tif (veh->IsBike()) {\n\t\t\t\tif (Abs(veh->m_vecMoveSpeed.x) < 0.1 && Abs(veh->m_vecMoveSpeed.y) < 0.1f) {\n\t\t\t\t\t((CBike*)veh)->bIsStanding = true;\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tveh->RemovePassenger(ped);\n\t\t}\n\n\t\tif (veh->bIsBus && !veh->IsUpsideDown() && !veh->IsOnItsSide()) {\n\t\t\tfloat angleAfterExit;\n\t\t\tif (ped->m_vehDoor == CAR_DOOR_LF) {\n\t\t\t\tangleAfterExit = HALFPI + veh->GetForward().Heading();\n\t\t\t} else {\n\t\t\t\tangleAfterExit = veh->GetForward().Heading() - HALFPI;\n\t\t\t}\n\t\t\tped->SetHeading(angleAfterExit);\n\t\t\tped->m_fRotationDest = angleAfterExit;\n\t\t\tped->m_fRotationCur = angleAfterExit;\n\t\t\tif (!ped->bBusJacked)\n\t\t\t\tped->SetMoveState(PEDMOVE_WALK);\n\t\t}\n\t\tif (CGarages::IsPointWithinAnyGarage(ped->GetPosition()))\n\t\t\tveh->bLightsOn = false;\n\t}\n\n\tif (ped->IsPlayer())\n\t\tAudioManager.PlayerJustLeftCar();\n\n\tped->ReplaceWeaponWhenExitingVehicle();\n\n\tped->bOnBoat = false;\n\tif (ped->bBusJacked) {\n\t\tped->SetFall(1500, ANIM_STD_HIGHIMPACT_BACK, false);\n\t\tped->bBusJacked = false;\n\t}\n\tped->m_nStoredMoveState = PEDMOVE_NONE;\n\tif (!ped->IsPlayer()) {\n\t\t// It's a shame...\n#ifdef FIX_BUGS\n\t\tint createdBy = ped->CharCreatedBy;\n#else\n\t\tint createdBy = !ped->CharCreatedBy;\n#endif\n\n\t\tif (createdBy == MISSION_CHAR && !startedToRun)\n\t\t\tped->SetMoveState(PEDMOVE_WALK);\n\t}\n\tped->bHeldHostageInCar = false;\n}\n\nvoid\nCPed::PedSetDraggedOutCarCB(CAnimBlendAssociation *dragAssoc, void *arg)\n{\n\tCAnimBlendAssociation *quickJackedAssoc;\n\tCVehicle *vehicle; \n\tCPed *ped = (CPed*)arg;\n\n\tuint8 exitFlags = 0;\n\tquickJackedAssoc = RpAnimBlendClumpGetAssociation(ped->GetClump(), ANIM_STD_QUICKJACKED);\n\tif (dragAssoc && dragAssoc->animId == ANIM_BIKE_HIT && ped->m_pMyVehicle) {\n\t\tif (ped->m_vehDoor == CAR_DOOR_LF || ped->m_vehDoor == CAR_DOOR_RF) {\n\t\t\tCAnimManager::BlendAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_BIKE_FALLOFF, 100.0f);\n\t\t\tped->m_pMyVehicle->m_nGettingOutFlags &= ~(CAR_DOOR_FLAG_RF | CAR_DOOR_FLAG_LF);\n\t\t} else {\n\t\t\tCAnimManager::BlendAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_BIKE_FALLBACK, 100.0f);\n\t\t\tped->m_pMyVehicle->m_nGettingOutFlags &= ~(CAR_DOOR_FLAG_RR | CAR_DOOR_FLAG_LR);\n\t\t}\n\t\t((CBike*)ped->m_pMyVehicle)->KnockOffRider(WEAPONTYPE_UNIDENTIFIED, 0, ped, true);\n\t\treturn;\n\t}\n\n\tif (ped->m_nPedState != PED_ARRESTED) {\n\t\tped->m_nLastPedState = PED_NONE;\n\t\tif (dragAssoc)\n\t\t\tdragAssoc->blendDelta = -1000.0f;\n\t}\n\tped->RestartNonPartialAnims();\n\tped->m_pVehicleAnim = nil;\n\tped->m_pSeekTarget = nil;\n\tvehicle = ped->m_pMyVehicle;\n\n\tif (vehicle && vehicle->IsBike())\n\t\texitFlags = GetBikeDoorFlagInclJumpInFromFront(ped->m_vehDoor);\n\telse\n\t\texitFlags = GetCarDoorFlag(ped->m_vehDoor);\n\n\tif (vehicle)\n\t\tvehicle->m_nGettingOutFlags &= ~exitFlags;\n\n\tif (vehicle) {\n\t\tif (vehicle->pDriver == ped) {\n\t\t\tvehicle->RemoveDriver();\n\t\t\tif (vehicle->m_nDoorLock == CARLOCK_LOCKED_INITIALLY)\n\t\t\t\tvehicle->m_nDoorLock = CARLOCK_UNLOCKED;\n\n\t\t\tif (ped->m_nPedType == PEDTYPE_COP && vehicle->IsLawEnforcementVehicle())\n\t\t\t\tvehicle->ChangeLawEnforcerState(false);\n\t\t} else {\n\t\t\tvehicle->RemovePassenger(ped);\n\t\t}\n\t}\n\tped->bInVehicle = false;\n\tif (ped->IsPlayer())\n\t\tAudioManager.PlayerJustLeftCar();\n\n\tif (ped->m_objective == OBJECTIVE_LEAVE_CAR_AND_DIE) {\n\t\tdragAssoc->SetDeleteCallback(PedSetDraggedOutCarPositionCB, ped);\n\t\tped->m_fHealth = 0.0f;\n\t\tped->SetDie(ANIM_STD_HIT_FLOOR, 1000.0f, 0.5f);\n\t\treturn;\n\t}\n\n\tif (quickJackedAssoc) {\n\t\tdragAssoc->SetDeleteCallback(PedSetQuickDraggedOutCarPositionCB, ped);\n\t} else {\n\t\tdragAssoc->SetDeleteCallback(PedSetDraggedOutCarPositionCB, ped);\n\t\tif (ped->CanSetPedState())\n\t\t\tCAnimManager::BlendAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_GET_UP, 1000.0f);\n\t}\n\n\tped->ReplaceWeaponWhenExitingVehicle();\n\n\tped->m_nStoredMoveState = PEDMOVE_NONE;\n\tped->bVehExitWillBeInstant = false;\n}\n\nvoid\nCPed::PedSetInCarCB(CAnimBlendAssociation *animAssoc, void *arg)\n{\n\tCPed *ped = (CPed*)arg;\n\n\tCVehicle *veh = ped->m_pMyVehicle;\n\n\t// Pointless code\n\tif (!veh)\n\t\treturn;\n\n\t// Situation of entering car as a driver while there is already a driver exiting atm.\n\tCPed *driver = veh->pDriver;\n\tif (driver && driver->m_nPedState == PED_DRIVING && !veh->bIsBus && driver->m_objective == OBJECTIVE_LEAVE_CAR\n\t\t&& (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER || ped->m_nPedState == PED_CARJACK)) {\n\n\t\tif (!ped->IsPlayer() && (ped->CharCreatedBy != MISSION_CHAR || driver->IsPlayer())) {\n\t\t\tped->QuitEnteringCar();\n\t\t\treturn;\n\t\t}\n\t\tif (driver->CharCreatedBy == MISSION_CHAR) {\n\t\t\tPedSetOutCarCB(nil, veh->pDriver);\n\t\t\tif (driver->m_pMyVehicle) {\n\t\t\t\tdriver->PositionPedOutOfCollision();\n\t\t\t} else {\n\t\t\t\tdriver->m_pMyVehicle = veh;\n\t\t\t\tdriver->PositionPedOutOfCollision();\n\t\t\t\tdriver->m_pMyVehicle = nil;\n\t\t\t}\n\t\t\tveh->pDriver = nil;\n\t\t} else {\n\t\t\tdriver->SetDead();\n\t\t\tdriver->FlagToDestroyWhenNextProcessed();\n\t\t\tveh->pDriver = nil;\n\t\t}\n\t}\n\n\tif (ped->bRemoveMeWhenIGotIntoCar) {\n\t\tped->bRemoveMeWhenIGotIntoCar = false;\n\t\tped->bRemoveFromWorld = true;\n\t}\n\tif (ped->bCollectBusFare) {\n\t\tped->bCollectBusFare = false;\n\t\tif (FindPlayerPed())\n\t\t\tFindPlayerPed()->m_nLastBusFareCollected += 5;\n\t}\n\n\tif (!ped->IsNotInWreckedVehicle() || ped->DyingOrDead())\n\t\treturn;\n\n\tped->bInVehicle = true;\n\tif (ped->m_nPedType == PEDTYPE_PROSTITUTE) {\n\t\tif (veh->pDriver) {\n\t\t\tif (veh->pDriver->IsPlayer() && ped->CharCreatedBy == RANDOM_CHAR) {\n\t\t\t\tCWorld::Players[CWorld::PlayerInFocus].m_nSexFrequency = 1000;\n\t\t\t\tCWorld::Players[CWorld::PlayerInFocus].m_nNextSexMoneyUpdateTime = CTimer::GetTimeInMilliseconds() + 1000;\n\t\t\t\tCWorld::Players[CWorld::PlayerInFocus].m_nNextSexFrequencyUpdateTime = CTimer::GetTimeInMilliseconds() + 3000;\n\t\t\t\tCWorld::Players[CWorld::PlayerInFocus].m_pHooker = (CCivilianPed*)ped;\n\t\t\t}\n\t\t}\n\t}\n\tif (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER || ped->m_nPedState == PED_CARJACK)\n\t\tveh->bIsBeingCarJacked = false;\n\n\tif (veh->m_nNumGettingIn)\n\t\t--veh->m_nNumGettingIn;\n\n\tif (ped->IsPlayer() && ((CPlayerPed*)ped)->m_bAdrenalineActive)\n\t\t((CPlayerPed*)ped)->ClearAdrenaline();\n\n\tif (veh->IsBoat()) {\n\t\tif (ped->IsPlayer()) {\n\t\t\tCCarCtrl::RegisterVehicleOfInterest(veh);\n\t\t\tif (veh->GetStatus() == STATUS_SIMPLE) {\n\t\t\t\tveh->m_vecMoveSpeed = CVector(0.0f, 0.0f, -0.00001f);\n\t\t\t\tveh->m_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f);\n\t\t\t}\n\t\t\tveh->SetStatus(STATUS_PLAYER);\n\t\t\tAudioManager.PlayerJustGotInCar();\n\t\t}\n\t\tveh->SetDriver(ped);\n\t\tif (!veh->bEngineOn)\n\t\t\tveh->bEngineOn = true;\n\n\t\tped->SetPedState(PED_DRIVING);\n\t\tped->StopNonPartialAnims();\n\t\tped->RemoveWeaponWhenEnteringVehicle();\n\t\treturn;\n\t}\n\n\tif (ped->m_pVehicleAnim)\n\t\tped->m_pVehicleAnim->blendDelta = -1000.0f;\n\n\tped->bDoBloodyFootprints = false;\n\tif (veh->m_nAlarmState == -1)\n\t\tveh->m_nAlarmState = 15000;\n\n\tif (ped->IsPlayer()) {\n\t\tif (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER || veh->IsBike()) {\n\t\t\tif (veh->GetStatus() == STATUS_SIMPLE) {\n\t\t\t\tveh->m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);\n\t\t\t\tveh->m_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f);\n\t\t\t}\n\t\t\tveh->SetStatus(STATUS_PLAYER);\n\t\t}\n\t\tAudioManager.PlayerJustGotInCar();\n\t} else if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER) {\n\t\tif (veh->GetStatus() == STATUS_SIMPLE) {\n\t\t\tveh->m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);\n\t\t\tveh->m_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f);\n\t\t}\n\t\tveh->SetStatus(STATUS_PHYSICS);\n\t}\n\t\n\tif (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER) {\n\t\tfor (int i = 0; i < veh->m_nNumMaxPassengers; ++i) {\n\t\t\tCPed *passenger = veh->pPassengers[i];\n\t\t\tif (passenger && !passenger->bStayInCarOnJack && !passenger->bHeldHostageInCar && (passenger->m_leader != ped || !ped->bIsLeader)) {\n\t\t\t\tpassenger->SetObjective(OBJECTIVE_LEAVE_CAR, veh);\n\t\t\t\tpassenger->m_leaveCarTimer = CTimer::GetTimeInMilliseconds();\n\t\t\t}\n\t\t}\n\t}\n\n\tif (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER || ped->m_nPedState == PED_CARJACK) {\n\t\tveh->SetDriver(ped);\n\t\tif (veh->VehicleCreatedBy == PARKED_VEHICLE) {\n\t\t\tveh->VehicleCreatedBy = RANDOM_VEHICLE;\n\t\t\t++CCarCtrl::NumRandomCars;\n\t\t\t--CCarCtrl::NumParkedCars;\n\t\t}\n\t\tif (veh->bIsAmbulanceOnDuty) {\n\t\t\tveh->bIsAmbulanceOnDuty = false;\n\t\t\t--CCarCtrl::NumAmbulancesOnDuty;\n\t\t}\n\t\tif (veh->bIsFireTruckOnDuty) {\n\t\t\tveh->bIsFireTruckOnDuty = false;\n\t\t\t--CCarCtrl::NumFiretrucksOnDuty;\n\t\t}\n\t\tif (ped->m_nPedType == PEDTYPE_COP && veh->IsLawEnforcementVehicle())\n\t\t\tveh->ChangeLawEnforcerState(true);\n\n\t\tif (!veh->bEngineOn) {\n\t\t\tveh->bEngineOn = true;\n\t\t\tDMAudio.PlayOneShot(ped->m_audioEntityId, SOUND_CAR_ENGINE_START, 1.0f);\n\t\t}\n\t\tif (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER && ped->CharCreatedBy == RANDOM_CHAR\n\t\t\t&& ped != FindPlayerPed() && ped->m_nPedType != PEDTYPE_EMERGENCY) {\n\n\t\t\tCCarCtrl::JoinCarWithRoadSystem(veh);\n\t\t\tveh->AutoPilot.m_nCarMission = MISSION_CRUISE;\n\t\t\tveh->AutoPilot.m_nTempAction = TEMPACT_NONE;\n\t\t\tveh->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS;\n\t\t\tveh->AutoPilot.m_nCruiseSpeed = 25;\n\t\t}\n\t\tped->SetPedState(PED_DRIVING);\n\t\tif (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER) {\n\n\t\t\tif (ped->m_prevObjective == OBJECTIVE_RUN_TO_AREA || ped->m_prevObjective == OBJECTIVE_GOTO_CHAR_ON_FOOT\n\t\t\t\t|| ped->m_prevObjective == OBJECTIVE_SPRINT_TO_AREA || ped->m_prevObjective == OBJECTIVE_KILL_CHAR_ON_FOOT)\n\t\t\t\tped->m_prevObjective = OBJECTIVE_NONE;\n\n\t\t\tped->RestorePreviousObjective();\n\t\t}\n\n\t} else {\n\n\t\tbool slowDown = false;\n\t\tif (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER && veh->pDriver && ped->CharCreatedBy == RANDOM_CHAR)\n\t\t\tslowDown = true;\n\n\t\t// VC also has a dead condition in here.\n\n\t\tif (veh->IsBike()) {\n\t\t\tveh->AddPassenger(ped, 0);\n\t\t} else if (veh->bIsBus) {\n\t\t\tveh->AddPassenger(ped);\n\t\t} else {\n\t\t\tswitch (ped->m_vehDoor) {\n\t\t\t\tcase CAR_DOOR_RF:\n\t\t\t\t\tveh->AddPassenger(ped, 0);\n\t\t\t\t\tbreak;\n\t\t\t\tcase CAR_DOOR_RR:\n\t\t\t\t\tveh->AddPassenger(ped, 2);\n\t\t\t\t\tbreak;\n\t\t\t\tcase CAR_DOOR_LR:\n\t\t\t\t\tveh->AddPassenger(ped, 1);\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tveh->AddPassenger(ped);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tped->SetPedState(PED_DRIVING);\n\t\tif (ped->m_prevObjective == OBJECTIVE_RUN_TO_AREA || ped->m_prevObjective == OBJECTIVE_GOTO_CHAR_ON_FOOT\n\t\t\t|| ped->m_prevObjective == OBJECTIVE_SPRINT_TO_AREA || ped->m_prevObjective == OBJECTIVE_KILL_CHAR_ON_FOOT)\n\t\t\tped->m_prevObjective = OBJECTIVE_NONE;\n\n\t\tped->RestorePreviousObjective();\n\n\t\t// VC has conditional OBJECTIVE_LEAVE_CAR here, which runs if it entered the first dead condition.\n\n\t\tif(slowDown)\n\t\t\tveh->AutoPilot.m_nCruiseSpeed = 17;\n\t}\n\n\tint8 doorFlag;\n\tif (veh->IsBike()) {\n\t\tdoorFlag = GetBikeDoorFlagInclJumpInFromFront(ped->m_vehDoor);\n\t} else {\n\t\tdoorFlag = GetEnterCarDoorFlag(ped->m_vehDoor, veh->m_nNumMaxPassengers);\n\t}\n\n\tveh->m_nGettingInFlags &= ~doorFlag;\n\n\tif (veh->bIsBus && !veh->m_nGettingInFlags)\n\t\t((CAutomobile*)veh)->SetBusDoorTimer(1000, 1);\n\n\tswitch (ped->m_objective) {\n\t\tcase OBJECTIVE_KILL_CHAR_ON_FOOT:\n\t\tcase OBJECTIVE_KILL_CHAR_ANY_MEANS:\n\t\tcase OBJECTIVE_LEAVE_CAR:\n\t\tcase OBJECTIVE_FOLLOW_CAR_IN_CAR:\n\t\tcase OBJECTIVE_GOTO_AREA_ANY_MEANS:\n\t\tcase OBJECTIVE_GOTO_AREA_ON_FOOT:\n\t\tcase OBJECTIVE_RUN_TO_AREA:\n\t\tcase OBJECTIVE_GOTO_SEAT_ON_FOOT:\n\t\tcase OBJECTIVE_GOTO_ATM_ON_FOOT:\n\t\tcase OBJECTIVE_GOTO_BUS_STOP_ON_FOOT:\n\t\tcase OBJECTIVE_GOTO_PIZZA_ON_FOOT:\n\t\tcase OBJECTIVE_GOTO_SHELTER_ON_FOOT:\n\t\tcase OBJECTIVE_SPRINT_TO_AREA:\n\t\tcase OBJECTIVE_GOTO_ICE_CREAM_VAN_ON_FOOT:\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tped->SetObjective(OBJECTIVE_NONE);\n\t}\n\n\tped->AddInCarAnims(veh, veh->pDriver == ped);\n\tif (veh->bIsBus)\n\t\tped->bRenderPedInCar = false;\n\n\t// FIX: RegisterVehicleOfInterest not just registers the vehicle, but also updates register time. So remove the IsThisVehicleInteresting check.\n#ifndef FIX_BUGS\n\tif (ped->IsPlayer() && !CCarCtrl::IsThisVehicleInteresting(veh) && veh->VehicleCreatedBy != MISSION_VEHICLE) {\n#else\n\tif (ped->IsPlayer() && veh->VehicleCreatedBy != MISSION_VEHICLE) {\n#endif\n\t\tCCarCtrl::RegisterVehicleOfInterest(veh);\n\n\t\tif (!veh->bHasBeenOwnedByPlayer && veh->VehicleCreatedBy != MISSION_VEHICLE)\n\t\t\tCEventList::RegisterEvent(EVENT_STEAL_CAR, EVENT_ENTITY_VEHICLE, veh, ped, 1500);\n\n\t\tveh->bHasBeenOwnedByPlayer = true;\n\t}\n\tped->bChangedSeat = true;\n}\n\nbool\nCPed::CanBeDeleted(void)\n{\n\tif (bInVehicle)\n\t\treturn false;\n\n\tswitch (CharCreatedBy) {\n\t\tcase RANDOM_CHAR:\n\t\t\treturn true;\n\t\tcase MISSION_CHAR:\n\t\t\treturn false;\n\t\tcase UNK_CHAR:\n\t\t\treturn false;\n\t\tdefault:\n\t\t\treturn true;\n\t}\n}\n\nbool\nCPed::CanBeDeletedEvenInVehicle(void)\n{\n\tswitch (CharCreatedBy) {\n\t\tcase RANDOM_CHAR:\n\t\t\treturn true;\n\t\tcase MISSION_CHAR:\n\t\t\treturn false;\n\t\tcase UNK_CHAR:\n\t\t\treturn false;\n\t\tdefault:\n\t\t\treturn true;\n\t}\n}\n\nvoid\nCPed::AddWeaponModel(int id)\n{\n\tif (id != -1) {\n\t\tif (m_pWeaponModel)\n\t\t\tRemoveWeaponModel(-1);\n\n\t\tm_pWeaponModel = (RpAtomic*)CModelInfo::GetModelInfo(id)->CreateInstance();\n\t\tCModelInfo::GetModelInfo(id)->AddRef();\n\t\tm_wepModelID = id;\n\n\t\tif (IsPlayer() && id == MI_MINIGUN)\n\t\t\t((CPlayerPed*)this)->m_pMinigunTopAtomic = (RpAtomic*)CModelInfo::GetModelInfo(MI_MINIGUN2)->CreateInstance();\n\t}\n}\n\nstatic RwObject*\nRemoveAllModelCB(RwObject *object, void *data)\n{\n\tRpAtomic *atomic = (RpAtomic*)object;\n\tif (CVisibilityPlugins::GetAtomicModelInfo(atomic)) {\n\t\tRpClumpRemoveAtomic(RpAtomicGetClump(atomic), atomic);\n\t\tRpAtomicDestroy(atomic);\n\t}\n\treturn object;\n}\n\nvoid\nCPed::RemoveWeaponModel(int modelId)\n{\n\t// modelId is not used!! This function just removes the current weapon.\n\tif(m_pWeaponModel){\n\t\tif (modelId == -1\n\t\t\t|| CVisibilityPlugins::GetAtomicModelInfo(m_pWeaponModel) == CModelInfo::GetModelInfo(modelId)) {\n\t\t\tCVisibilityPlugins::GetAtomicModelInfo(m_pWeaponModel)->RemoveRef();\n\t\t\tRwFrame* frm = RpAtomicGetFrame(m_pWeaponModel);\n\t\t\tRpAtomicDestroy(m_pWeaponModel);\n\t\t\tRwFrameDestroy(frm);\n\t\t\tm_pWeaponModel = nil;\n\t\t}\n\t}\n\n\tif (IsPlayer() && (modelId == -1 || modelId == MI_MINIGUN)) {\n\t\tRpAtomic* &atm = ((CPlayerPed*)this)->m_pMinigunTopAtomic;\n\t\tif (atm) {\n\t\t\tRwFrame *frm = RpAtomicGetFrame(atm);\n\t\t\tRpAtomicDestroy(atm);\n\t\t\tRwFrameDestroy(frm);\n\t\t\tatm = nil;\n\t\t}\n\t}\n\tm_wepModelID = -1;\n}\n\nvoid\nCPed::RequestDelayedWeapon()\n{\n\tif (m_delayedWeapon != WEAPONTYPE_UNIDENTIFIED) {\n\t\tint modelId1 = CWeaponInfo::GetWeaponInfo(m_delayedWeapon)->m_nModelId;\n\t\tint modelId2 = CWeaponInfo::GetWeaponInfo(m_delayedWeapon)->m_nModel2Id;\n\t\tif (modelId1 != -1)\n\t\t\tCStreaming::RequestModel(modelId1, STREAMFLAGS_DEPENDENCY);\n\t\tif (modelId2 != -1)\n\t\t\tCStreaming::RequestModel(modelId2, STREAMFLAGS_DEPENDENCY);\n\n\t\tif ((modelId1 == -1 || CStreaming::HasModelLoaded(modelId1))\n\t\t\t&& (modelId2 == -1 || CStreaming::HasModelLoaded(modelId2))) {\n\t\t\tGiveWeapon(m_delayedWeapon, m_delayedWeaponAmmo, 1);\n\t\t\tm_delayedWeapon = WEAPONTYPE_UNIDENTIFIED;\n\t\t}\n\t}\n}\n\nvoid\nCPed::GiveDelayedWeapon(eWeaponType weapon, uint32 ammo)\n{\n\tm_delayedWeapon = weapon;\n\tm_delayedWeaponAmmo = ammo;\n\tif (m_delayedWeapon != WEAPONTYPE_UNIDENTIFIED) {\n\t\tint modelId1 = CWeaponInfo::GetWeaponInfo(m_delayedWeapon)->m_nModelId;\n\t\tint modelId2 = CWeaponInfo::GetWeaponInfo(m_delayedWeapon)->m_nModel2Id;\n\t\tif (modelId1 != -1)\n\t\t\tCStreaming::RequestModel(modelId1, STREAMFLAGS_DEPENDENCY);\n\t\tif (modelId2 != -1)\n\t\t\tCStreaming::RequestModel(modelId2, STREAMFLAGS_DEPENDENCY);\n\n\t\tif ((modelId1 == -1 || CStreaming::HasModelLoaded(modelId1))\n\t\t\t&& (modelId2 == -1 || CStreaming::HasModelLoaded(modelId2))) {\n\t\t\tGiveWeapon(m_delayedWeapon, m_delayedWeaponAmmo, true);\n\t\t\tm_delayedWeapon = WEAPONTYPE_UNIDENTIFIED;\n\t\t}\n\t}\n}\n\nint32\nCPed::GiveWeapon(eWeaponType weaponType, uint32 ammo, bool unused)\n{\n\tint slot = GetWeaponSlot(weaponType);\n\n\tif (m_weapons[slot].m_eWeaponType == weaponType) {\n\t\tGetWeapon(slot).m_nAmmoTotal += ammo;\n\t\tif (weaponType < WEAPONTYPE_TOTALWEAPONS && weaponType > WEAPONTYPE_UNARMED && CWeaponInfo::ms_aMaxAmmoForWeapon[weaponType] >= 0) {\n\n\t\t\t// Looks like abandoned idea. This block never runs, ms_aMaxAmmoForWeapon is always -1.\n\t\t\tGetWeapon(slot).m_nAmmoTotal = Min(CWeaponInfo::ms_aMaxAmmoForWeapon[weaponType], GetWeapon(slot).m_nAmmoTotal);\n\t\t} else {\n\t\t\tGetWeapon(slot).m_nAmmoTotal = Min(99999, GetWeapon(slot).m_nAmmoTotal);\n\t\t}\n\t\tGetWeapon(slot).Reload();\n\t\tif (GetWeapon(slot).m_eWeaponState == WEAPONSTATE_OUT_OF_AMMO && GetWeapon(slot).m_nAmmoTotal > 0)\n\t\t\tGetWeapon(slot).m_eWeaponState = WEAPONSTATE_READY;\n\t} else {\n\t\tif (HasWeaponSlot(slot)) {\n\t\t\tif (CWeaponInfo::IsWeaponSlotAmmoMergeable(slot))\n\t\t\t\tammo += GetWeapon(slot).m_nAmmoTotal;\n\n\t\t\tRemoveWeaponModel(CWeaponInfo::GetWeaponInfo(GetWeapon(slot).m_eWeaponType)->m_nModelId);\n\t\t\tGetWeapon(slot).Shutdown();\n\t\t}\n\t\tGetWeapon(slot).Initialise(weaponType, ammo);\n\t\tif (slot == m_currentWeapon && !bInVehicle) {\n\t\t\tAddWeaponModel(CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->m_nModelId);\n\t\t}\n\t}\n\tif (GetWeapon(slot).m_eWeaponState != WEAPONSTATE_OUT_OF_AMMO)\n\t\tGetWeapon(slot).m_eWeaponState = WEAPONSTATE_READY;\n\n\treturn slot;\n}\n\nint\nCPed::GetWeaponSlot(eWeaponType weaponType)\n{\n\treturn CWeaponInfo::GetWeaponInfo(weaponType)->m_nWeaponSlot;\n}\n\nvoid\nCPed::SetCurrentWeapon(int slot)\n{\n\tif (slot == -1)\n\t\treturn;\n\n\tCWeaponInfo* weaponInfo;\n\tif (GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED) {\n\t\tweaponInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);\n\t\tRemoveWeaponModel(weaponInfo->m_nModelId);\n\t}\n\tm_currentWeapon = slot;\n\n\tif (FindPlayerPed() && IsPlayer())\n\t\t((CPlayerPed*)this)->m_nSelectedWepSlot = m_currentWeapon;\n\n\tif (HasWeaponSlot(slot)) {\n\t\tweaponInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);\n\t\tAddWeaponModel(weaponInfo->m_nModelId);\n\t}\n}\n\nvoid\nCPed::SetCurrentWeapon(eWeaponType weaponType)\n{\n\tSetCurrentWeapon(CWeaponInfo::GetWeaponInfo(weaponType)->m_nWeaponSlot);\n}\n\nvoid\nCPed::GrantAmmo(eWeaponType weaponType, uint32 ammo)\n{\n\tint slot = CWeaponInfo::GetWeaponInfo(weaponType)->m_nWeaponSlot;\n\tif (slot == -1)\n\t\treturn;\n\n\tGetWeapon(slot).m_nAmmoTotal += ammo;\n\tif (weaponType < WEAPONTYPE_TOTALWEAPONS && weaponType > WEAPONTYPE_UNARMED && CWeaponInfo::ms_aMaxAmmoForWeapon[weaponType] >= 0) {\n\n\t\t// Looks like abandoned idea. This block never runs, ms_aMaxAmmoForWeapon is always -1.\n\t\tGetWeapon(slot).m_nAmmoTotal = Min(CWeaponInfo::ms_aMaxAmmoForWeapon[weaponType], GetWeapon(slot).m_nAmmoTotal);\n\t} else {\n\t\tGetWeapon(slot).m_nAmmoTotal = Min(99999, GetWeapon(slot).m_nAmmoTotal);\n\t}\n\n\tif (GetWeapon(slot).m_eWeaponState == WEAPONSTATE_OUT_OF_AMMO && GetWeapon(slot).m_nAmmoTotal > 0)\n\t\tGetWeapon(slot).m_eWeaponState = WEAPONSTATE_READY;\n}\n\nvoid\nCPed::SetAmmo(eWeaponType weaponType, uint32 ammo)\n{\n\tint slot = CWeaponInfo::GetWeaponInfo(weaponType)->m_nWeaponSlot;\n\tif (slot == -1)\n\t\treturn;\n\n\tGetWeapon(slot).m_nAmmoTotal = ammo;\n\tif (weaponType < WEAPONTYPE_TOTALWEAPONS && weaponType > WEAPONTYPE_UNARMED && CWeaponInfo::ms_aMaxAmmoForWeapon[weaponType] >= 0) {\n\n\t\t// Looks like abandoned idea. This block never runs, ms_aMaxAmmoForWeapon is always -1.\n\t\tGetWeapon(slot).m_nAmmoTotal = Min(CWeaponInfo::ms_aMaxAmmoForWeapon[weaponType], GetWeapon(slot).m_nAmmoTotal);\n\t} else {\n\t\tGetWeapon(slot).m_nAmmoTotal = Min(99999, GetWeapon(slot).m_nAmmoTotal);\n\t}\n\tint32 newClip = GetWeapon(slot).m_nAmmoTotal;\n\tif (newClip >= GetWeapon(slot).m_nAmmoInClip)\n\t\tnewClip = GetWeapon(slot).m_nAmmoInClip;\n\tGetWeapon(slot).m_nAmmoInClip = newClip;\n\n\tif (GetWeapon(slot).m_eWeaponState == WEAPONSTATE_OUT_OF_AMMO && GetWeapon(slot).m_nAmmoTotal > 0)\n\t\tGetWeapon(slot).m_eWeaponState = WEAPONSTATE_READY;\n}\n\nvoid\nCPed::ClearWeapons(void)\n{\n\tRemoveWeaponModel(-1);\n\tfor (int i = 0; i < ARRAY_SIZE(m_weapons); i++) {\n\t\tGetWeapon(i).Shutdown();\n\t}\n\tSetCurrentWeapon(WEAPONTYPE_UNARMED);\n}\n\nvoid\nCPed::RemoveWeaponWhenEnteringVehicle(void)\n{\n\tif (IsPlayer() && HasWeaponSlot(5) && GetWeapon(5).m_nAmmoTotal > 0 && ((CPlayerPed*)this)->GetPlayerInfoForThisPlayerPed()->m_bDriveByAllowed) {\n\t\tif (m_storedWeapon == WEAPONTYPE_UNIDENTIFIED)\n\t\t\tm_storedWeapon = GetWeapon()->m_eWeaponType;\n\t\tSetCurrentWeapon(GetWeapon(5).m_eWeaponType);\n\t} else {\n\t\tCWeaponInfo *ourWeapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);\n\t\tRemoveWeaponModel(ourWeapon->m_nModelId);\n\t}\n}\nvoid\nCPed::ReplaceWeaponWhenExitingVehicle(void)\n{\n\teWeaponType weaponType = GetWeapon()->m_eWeaponType;\n\n\t// If it's Uzi, we may have stored weapon. Uzi is the only gun we can use in car.\n\tif (IsPlayer() && GetWeaponSlot(weaponType) == WEAPONSLOT_SUBMACHINEGUN) {\n\t\tif (m_storedWeapon != WEAPONTYPE_UNIDENTIFIED) {\n\t\t\tSetCurrentWeapon(m_storedWeapon);\n\t\t\tm_storedWeapon = WEAPONTYPE_UNIDENTIFIED;\n\t\t}\n\t} else {\n\t\tAddWeaponModel(CWeaponInfo::GetWeaponInfo(weaponType)->m_nModelId);\n\t}\n}\n\nvoid\nCPed::PreRender(void)\n{\n\tCShadows::StoreShadowForPed(this,\n\t\tCTimeCycle::m_fShadowDisplacementX[CTimeCycle::m_CurrentStoredValue], CTimeCycle::m_fShadowDisplacementY[CTimeCycle::m_CurrentStoredValue],\n\t\tCTimeCycle::m_fShadowFrontX[CTimeCycle::m_CurrentStoredValue], CTimeCycle::m_fShadowFrontY[CTimeCycle::m_CurrentStoredValue],\n\t\tCTimeCycle::m_fShadowSideX[CTimeCycle::m_CurrentStoredValue], CTimeCycle::m_fShadowSideY[CTimeCycle::m_CurrentStoredValue]);\n\n\tUpdateRpHAnim();\n\n\tbool bIsWindModifierTurnedOn = false;\n\tfloat fAnyDirectionShift = 1.0f;\n\tbool bIsPedDrivingBikeOrOpenTopCar = false;\n\tif (IsPlayer() && CWindModifiers::FindWindModifier(GetPosition(), &fAnyDirectionShift, &fAnyDirectionShift)\n\t\t&& !CCullZones::PlayerNoRain() && GetPedState() != PED_DRIVING)\n\t\tbIsWindModifierTurnedOn = true;\n\n\tif (GetPedState() == PED_DRIVING && m_pMyVehicle) {\n\t\tif (m_pMyVehicle->m_vehType == VEHICLE_TYPE_BIKE\n\t\t\t|| (m_pMyVehicle->m_vehType == VEHICLE_TYPE_CAR && m_pMyVehicle->IsOpenTopCar()))\n\t\t\tbIsPedDrivingBikeOrOpenTopCar = true;\n\t}\n\n\tif (bIsWindModifierTurnedOn || bIsPedDrivingBikeOrOpenTopCar) {\n\t\tfloat fWindMult = 0.0f;\n\t\tif (bIsPedDrivingBikeOrOpenTopCar) {\n\t\t\tfWindMult = DotProduct(m_pMyVehicle->m_vecMoveSpeed, GetForward());\n\t\t\tif (fWindMult > 0.4f) {\n\t\t\t\tfloat volume = (fWindMult - 0.4f) / 0.6f;\n\t\t\t\tDMAudio.PlayOneShot(m_audioEntityId, SOUND_SHIRT_WIND_FLAP, volume);\n\t\t\t}\n\t\t}\n\n\t\tif (bIsWindModifierTurnedOn) \n\t\t\tfWindMult = Min(fWindMult, Abs(fAnyDirectionShift - 1.0f));\n\n\t\tRpHAnimHierarchy* hier = GetAnimHierarchyFromSkinClump(GetClump());\n\t\tint32 idx;\n\t\tRwV3d scale;\n\t\tfloat fScaleOffset;\n\n\t\tfScaleOffset = fWindMult * 0.2f;\n\t\tscale.x = CGeneral::GetRandomNumberInRange(1.0f - fScaleOffset, 1.0f + fScaleOffset);\n\t\tscale.y = CGeneral::GetRandomNumberInRange(1.0f - fScaleOffset, 1.0f + fScaleOffset);\n\t\tscale.z = CGeneral::GetRandomNumberInRange(1.0f - fScaleOffset, 1.0f + fScaleOffset);\n\n\t\tidx = RpHAnimIDGetIndex(hier, ConvertPedNode2BoneTag(PED_NECK));\n\t\tRwMatrix* neck = &RpHAnimHierarchyGetMatrixArray(hier)[idx];\n\t\tRwMatrixScale(neck, &scale, rwCOMBINEPRECONCAT);\n\n\t\tfScaleOffset = fWindMult * 0.1f;\n\t\tscale.x = CGeneral::GetRandomNumberInRange(1.0f - fScaleOffset, 1.0f + fScaleOffset);\n\t\tscale.y = CGeneral::GetRandomNumberInRange(1.0f - fScaleOffset, 1.0f + fScaleOffset);\n\t\tscale.z = CGeneral::GetRandomNumberInRange(1.0f - fScaleOffset, 1.0f + fScaleOffset);\n\n\t\tidx = RpHAnimIDGetIndex(hier, ConvertPedNode2BoneTag(PED_CLAVICLEL));\n\t\tRwMatrix* clavicleL = &RpHAnimHierarchyGetMatrixArray(hier)[idx];\n\t\tRwMatrixScale(clavicleL, &scale, rwCOMBINEPRECONCAT);\n\t\t\n\t\tidx = RpHAnimIDGetIndex(hier, ConvertPedNode2BoneTag(PED_CLAVICLER));\n\t\tRwMatrix* clavicleR = &RpHAnimHierarchyGetMatrixArray(hier)[idx];\n\t\tRwMatrixScale(clavicleR, &scale, rwCOMBINEPRECONCAT);\n\n\t\tidx = RpHAnimIDGetIndex(hier, ConvertPedNode2BoneTag(PED_MID));\n\t\tRwMatrix* mid = &RpHAnimHierarchyGetMatrixArray(hier)[idx];\n\t\tRwMatrixScale(mid, &scale, rwCOMBINEPRECONCAT);\n\n\t\tfScaleOffset = fWindMult * 0.2f;\n\t\tscale.x = CGeneral::GetRandomNumberInRange(1.0f - fScaleOffset, 1.0f + fScaleOffset);\n\t\tscale.y = CGeneral::GetRandomNumberInRange(1.0f - fScaleOffset, 1.0f + fScaleOffset);\n\t\tscale.z = CGeneral::GetRandomNumberInRange(1.0f - fScaleOffset, 1.0f + fScaleOffset);\n\n\t\tidx = RpHAnimIDGetIndex(hier, ConvertPedNode2BoneTag(PED_UPPERARML));\n\t\tRwMatrix* upperArmL = &RpHAnimHierarchyGetMatrixArray(hier)[idx];\n\t\tRwMatrixScale(upperArmL, &scale, rwCOMBINEPRECONCAT);\n\n\t\tidx = RpHAnimIDGetIndex(hier, ConvertPedNode2BoneTag(PED_UPPERARMR));\n\t\tRwMatrix* upperArmR = &RpHAnimHierarchyGetMatrixArray(hier)[idx];\n\t\tRwMatrixScale(upperArmR, &scale, rwCOMBINEPRECONCAT);\n\t}\n\n\tif (bBodyPartJustCameOff && m_bodyPartBleeding == PED_HEAD) {\n\t\t// scale head to 0 if shot off\n\t\tRpHAnimHierarchy* hier = GetAnimHierarchyFromSkinClump(GetClump());\n\t\tint32 idx = RpHAnimIDGetIndex(hier, ConvertPedNode2BoneTag(PED_HEAD));\n\t\tRwMatrix* head = &RpHAnimHierarchyGetMatrixArray(hier)[idx];\n\t\tRwV3d zero = { 0.0f, 0.0f, 0.0f };\n\t\tRwMatrixScale(head, &zero, rwCOMBINEPRECONCAT);\n\t}\n\n\tif (IsPlayer() && gfTommyFatness != 1.0f) {\n\t\tRpHAnimHierarchy* hier = GetAnimHierarchyFromSkinClump(GetClump());\n\t\tint32 idx;\n\t\tRwV3d scale;\n\n\t\tscale.x = 1.0f;\n\t\tscale.y = 1.0f + gfTommyFatness * 0.7f;\n\t\tscale.z = 1.0f + gfTommyFatness * 0.7f;\n\t\tidx = RpHAnimIDGetIndex(hier, ConvertPedNode2BoneTag(PED_HEAD));\n\t\tRwMatrix* head = &RpHAnimHierarchyGetMatrixArray(hier)[idx];\n\t\tRwMatrixScale(head, &scale, rwCOMBINEPRECONCAT);\n\n\t\tscale.y = 1.0f + gfTommyFatness * 0.2f;\n\t\tscale.z = 1.0f + gfTommyFatness * 0.2f;\n\t\tidx = RpHAnimIDGetIndex(hier, ConvertPedNode2BoneTag(PED_NECK));\n\t\tRwMatrix* neck = &RpHAnimHierarchyGetMatrixArray(hier)[idx];\n\t\tRwMatrixScale(neck, &scale, rwCOMBINEPRECONCAT);\n\n\t\tscale.y = 1.0f + gfTommyFatness * 0.5f;\n\t\tscale.z = 1.0f + gfTommyFatness * 0.5f;\n\t\tidx = RpHAnimIDGetIndex(hier, ConvertPedNode2BoneTag(PED_MID));\n\t\tRwMatrix* mid = &RpHAnimHierarchyGetMatrixArray(hier)[idx];\n\t\tRwMatrixScale(mid, &scale, rwCOMBINEPRECONCAT);\n\n\t\tscale.y = 1.0f + gfTommyFatness;\n\t\tscale.z = 1.0f + gfTommyFatness;\n\t\tidx = RpHAnimIDGetIndex(hier, ConvertPedNode2BoneTag(PED_UPPERLEGL));\n\t\tRwMatrix* upperLegL = &RpHAnimHierarchyGetMatrixArray(hier)[idx];\n\t\tRwMatrixScale(upperLegL, &scale, rwCOMBINEPRECONCAT);\n\n\t\tidx = RpHAnimIDGetIndex(hier, ConvertPedNode2BoneTag(PED_UPPERLEGR));\n\t\tRwMatrix* upperLegR = &RpHAnimHierarchyGetMatrixArray(hier)[idx];\n\t\tRwMatrixScale(upperLegR, &scale, rwCOMBINEPRECONCAT);\n\n\t\tscale.y = 1.0f + gfTommyFatness * 0.5f;\n\t\tscale.z = 1.0f + gfTommyFatness * 0.5f;\n\t\tidx = RpHAnimIDGetIndex(hier, ConvertPedNode2BoneTag(PED_LOWERLEGR));\n\t\tRwMatrix* lowerLegR = &RpHAnimHierarchyGetMatrixArray(hier)[idx];\n\t\tRwMatrixScale(lowerLegR, &scale, rwCOMBINEPRECONCAT);\n\n\t\tidx = RpHAnimIDGetIndex(hier, ConvertPedNode2BoneTag(PED_LOWERLEGL));\n\t\tRwMatrix* lowerLegL = &RpHAnimHierarchyGetMatrixArray(hier)[idx];\n\t\tRwMatrixScale(lowerLegL, &scale, rwCOMBINEPRECONCAT);\n\n\t\tscale.y = 1.0f + gfTommyFatness * 0.23f;\n\t\tscale.z = 1.0f + gfTommyFatness * 0.23f;\n\t\tidx = RpHAnimIDGetIndex(hier, ConvertPedNode2BoneTag(PED_FOOTL));\n\t\tRwMatrix* footL = &RpHAnimHierarchyGetMatrixArray(hier)[idx];\n\t\tRwMatrixScale(footL, &scale, rwCOMBINEPRECONCAT);\n\n\t\tidx = RpHAnimIDGetIndex(hier, ConvertPedNode2BoneTag(PED_FOOTR));\n\t\tRwMatrix* footR = &RpHAnimHierarchyGetMatrixArray(hier)[idx];\n\t\tRwMatrixScale(footR, &scale, rwCOMBINEPRECONCAT);\n\n\t\tidx = RpHAnimIDGetIndex(hier, ConvertPedNode2BoneTag(PED_UPPERARML));\n\t\tRwMatrix* upperArmL = &RpHAnimHierarchyGetMatrixArray(hier)[idx];\n\t\tRwMatrixScale(upperArmL, &scale, rwCOMBINEPRECONCAT);\n\n\t\tidx = RpHAnimIDGetIndex(hier, ConvertPedNode2BoneTag(PED_UPPERARMR));\n\t\tRwMatrix* upperArmR = &RpHAnimHierarchyGetMatrixArray(hier)[idx];\n\t\tRwMatrixScale(upperArmR, &scale, rwCOMBINEPRECONCAT);\n\n\t\tscale.y = 1.0f + gfTommyFatness * 0.2f;\n\t\tscale.z = 1.0f + gfTommyFatness * 0.2f;\n\t\tidx = RpHAnimIDGetIndex(hier, ConvertPedNode2BoneTag(PED_FOREARML));\n\t\tRwMatrix* foreArmL = &RpHAnimHierarchyGetMatrixArray(hier)[idx];\n\t\tRwMatrixScale(foreArmL, &scale, rwCOMBINEPRECONCAT);\n\n\t\tidx = RpHAnimIDGetIndex(hier, ConvertPedNode2BoneTag(PED_FOREARMR));\n\t\tRwMatrix* foreArmR = &RpHAnimHierarchyGetMatrixArray(hier)[idx];\n\t\tRwMatrixScale(foreArmR, &scale, rwCOMBINEPRECONCAT);\n\t}\n\n\tif (bBodyPartJustCameOff && bIsPedDieAnimPlaying && m_bodyPartBleeding != -1 && (CTimer::GetFrameCounter() & 7) > 3) {\n\t\tCVector bloodDir(0.0f, 0.0f, 0.0f);\n\t\tCVector bloodPos(0.0f, 0.0f, 0.0f);\n\n\t\tTransformToNode(bloodPos, m_bodyPartBleeding);\n\n\t\tswitch (m_bodyPartBleeding) {\n\t\t\tcase PED_HEAD:\n\t\t\t\tbloodDir = 0.1f * GetUp();\n\t\t\t\tbreak;\n\t\t\tcase PED_UPPERARML:\n\t\t\t\tbloodDir = 0.04f * GetUp() - 0.04f * GetRight();\n\t\t\t\tbreak;\n\t\t\tcase PED_UPPERARMR:\n\t\t\t\tbloodDir = 0.04f * GetUp() - 0.04f * GetRight();\n\t\t\t\tbreak;\n\t\t\tcase PED_UPPERLEGL:\n\t\t\t\tbloodDir = 0.04f * GetUp() + 0.05f * GetForward();\n\t\t\t\tbreak;\n\t\t\tcase PED_UPPERLEGR:\n\t\t\t\tbloodDir = 0.04f * GetUp() + 0.05f * GetForward();\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbloodDir = CVector(0.0f, 0.0f, 0.0f);\n\t\t\t\tbreak;\n\t\t}\n\n\t\tfor(int i = 0; i < 4; i++)\n\t\t\tCParticle::AddParticle(PARTICLE_BLOOD_SPURT, bloodPos, bloodDir, nil, 0.0f, 0, 0, 0, 0);\n\t}\n\tif (CWeather::Rain > 0.3f && TheCamera.SoundDistUp > 15.0f) {\n\t\tif ((TheCamera.GetPosition() - GetPosition()).Magnitude() < 25.0f) {\n\t\t\tbool doSplashUp = true;\n\t\t\tCColModel *ourCol = CModelInfo::GetModelInfo(GetModelIndex())->GetColModel();\n\t\t\tCVector speed = FindPlayerSpeed();\n\n\t\t\tif (Abs(speed.x) <= 0.05f && Abs(speed.y) <= 0.05f) {\n\t\t\t\tif (!OnGround() && m_nPedState != PED_ATTACK && m_nPedState != PED_FIGHT) {\n\t\t\t\t\tif (!IsPedHeadAbovePos(0.3f) || RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_IDLE_TIRED)) {\n\t\t\t\t\t\tdoSplashUp = false;\n\t\t\t\t\t}\n\t\t\t\t} else\n\t\t\t\t\tdoSplashUp = false;\n\t\t\t} else\n\t\t\t\tdoSplashUp = false;\n\n\t\t\tif (doSplashUp && ourCol->numSpheres > 0) {\n\t\t\t\tfor(int i = 0; i < ourCol->numSpheres; i++) {\n\t\t\t\t\tCColSphere *sphere = &ourCol->spheres[i];\n\t\t\t\t\tCVector splashPos;\n\t\t\t\t\tswitch (sphere->piece) {\n\t\t\t\t\t\tcase PEDPIECE_LEFTARM:\n\t\t\t\t\t\tcase PEDPIECE_RIGHTARM:\n\t\t\t\t\t\tcase PEDPIECE_HEAD:\n\t\t\t\t\t\t\tsplashPos = GetMatrix() * ourCol->spheres[i].center;\n\t\t\t\t\t\t\tsplashPos.z += 0.7f * sphere->radius;\n\t\t\t\t\t\t\tsplashPos.x += CGeneral::GetRandomNumberInRange(-0.15f, 0.15f);\n\t\t\t\t\t\t\tsplashPos.y += CGeneral::GetRandomNumberInRange(-0.15f, 0.15f);\n\t\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_RAIN_SPLASHUP, splashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.0f, 0, 0, CGeneral::GetRandomNumber() & 1, 0);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nCVector vecTestTemp(-1.0f, -1.0f, -1.0f);\n\nvoid\nCPed::Render(void)\n{\n\tif (bInVehicle && m_pMyVehicle && m_nPedState != PED_EXIT_CAR && m_nPedState != PED_DRAG_FROM_CAR) {\n\t\tif (!bRenderPedInCar)\n\t\t\treturn;\n\n\t\tif (!m_pMyVehicle->IsBike() && !IsPlayer()) {\n\t\t\tfloat camDistSq = (TheCamera.GetPosition() - GetPosition()).MagnitudeSqr();\n\t\t\tif (camDistSq > SQR((m_pMyVehicle->IsBoat() ? 40.0f : 25.0f) * TheCamera.LODDistMultiplier))\n\t\t\t\treturn;\n\t\t}\n\t}\n\n\tCEntity::Render();\n\n\tif(m_pWeaponModel){\n\t\tRpHAnimHierarchy *hier = GetAnimHierarchyFromSkinClump(GetClump());\n\t\tint idx = RpHAnimIDGetIndex(hier, m_pFrames[PED_HANDR]->nodeID);\n\t\tRwMatrix *mat = &RpHAnimHierarchyGetMatrixArray(hier)[idx];\n\t\tRwFrame *frame = RpAtomicGetFrame(m_pWeaponModel);\n\t\t*RwFrameGetMatrix(frame) = *mat;\n\t\tRwFrameUpdateObjects(frame);\n\t\tRpAtomicRender(m_pWeaponModel);\n\t\tif (IsPlayer()) {\n\t\t\tCPlayerPed *player = (CPlayerPed*)this;\n\t\t\tif (player->m_pMinigunTopAtomic) {\n\t\t\t\tframe = RpAtomicGetFrame(player->m_pMinigunTopAtomic);\n\t\t\t\t*RwFrameGetMatrix(frame) = *mat;\n\n\t\t\t\tplayer->m_fGunSpinAngle = player->m_fGunSpinSpeed * CTimer::GetTimeStep() + player->m_fGunSpinAngle;\n\t\t\t\tif (player->m_fGunSpinAngle > TWOPI)\n\t\t\t\t\tplayer->m_fGunSpinAngle -= TWOPI;\n\n\t\t\t\tCMatrix mgTopMat, localAdjMat;\n\t\t\t\tmgTopMat.Attach(RwFrameGetMatrix(frame));\n\t\t\t\tlocalAdjMat.SetRotateX(player->m_fGunSpinAngle);\n\t\t\t\tlocalAdjMat.Rotate(DEGTORAD(-4.477f)* vecTestTemp.x, DEGTORAD(29.731f) * vecTestTemp.y, DEGTORAD(1.064f) * vecTestTemp.z);\n\t\t\t\tlocalAdjMat.GetPosition() += CVector(0.829f, -0.001f, 0.226f);\n\t\t\t\tmgTopMat = mgTopMat * localAdjMat;\n\t\t\t\tmgTopMat.UpdateRW();\n\n\t\t\t\tRwFrameUpdateObjects(frame);\n\t\t\t\tRpAtomicRender(player->m_pMinigunTopAtomic);\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nCPed::CheckAroundForPossibleCollisions(void)\n{\n\tCVector ourCentre, objCentre;\n\tCEntity *objects[8];\n\tint16 maxObject;\n\n\tif (CTimer::GetTimeInMilliseconds() <= m_nPedStateTimer)\n\t\treturn;\n\n\tGetBoundCentre(ourCentre);\n\n\tCWorld::FindObjectsInRange(ourCentre, 10.0f, true, &maxObject, 6, objects, false, true, false, true, false);\n\tfor (int i = 0; i < maxObject; i++) {\n\t\tCEntity *object = objects[i];\n\t\tif (bRunningToPhone) {\n\t\t\tif (gPhoneInfo.PhoneAtThisPosition(object->GetPosition()))\n\t\t\t\tbreak;\n\t\t}\n\t\tobject->GetBoundCentre(objCentre);\n\t\tfloat radius = object->GetBoundRadius();\n\t\tif (radius > 4.5f || radius < 1.0f)\n\t\t\tradius = 1.0f;\n\n\t\t// Developers gave up calculating Z diff. later according to asm.\n\t\tfloat diff = CVector(ourCentre - objCentre).MagnitudeSqr2D();\n\n\t\tif (sq(radius + 1.0f) > diff)\n\t\t\tm_fRotationDest += DEGTORAD(22.5f);\n\t}\n}\n\nvoid\nCPed::SetIdle(void)\n{\n\tif (m_nPedState != PED_IDLE && m_nPedState != PED_MUG && m_nPedState != PED_FLEE_ENTITY) {\n\t\tif (m_nPedState == PED_AIM_GUN)\n\t\t\tClearPointGunAt();\n\n\t\tSetPedState(PED_IDLE);\n\t\tSetMoveState(PEDMOVE_STILL);\n\t\tm_nLastPedState = PED_NONE;\n\t}\n\tif (m_nWaitState == WAITSTATE_FALSE) {\n\t\tm_nWaitTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(2000, 4000);\n\t}\n}\n\nvoid\nCPed::Idle(void)\n{\n\tCVehicle *veh = m_pMyVehicle;\n\tif (veh && veh->m_nGettingOutFlags && m_vehDoor) {\n\n\t\tif (veh->m_nGettingOutFlags & GetCarDoorFlag(m_vehDoor)) {\n\n\t\t\tif (m_objective != OBJECTIVE_KILL_CHAR_ON_FOOT) {\n\n\t\t\t\tCVector doorPos = GetPositionToOpenCarDoor(veh, m_vehDoor);\n\t\t\t\tCVector doorDist = GetPosition() - doorPos;\n\n\t\t\t\tif (doorDist.MagnitudeSqr() < sq(0.5f)) {\n\t\t\t\t\tSetMoveState(PEDMOVE_WALK);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (m_nMoveState != PEDMOVE_STILL && !IsPlayer())\n\t\tSetMoveState(PEDMOVE_STILL);\n\n\tm_moved = CVector2D(0.0f, 0.0f);\n}\n\nvoid\nCPed::ClearPause(void)\n{\n\tRestorePreviousState();\n}\n\nvoid\nCPed::Pause(void)\n{\n\tm_moved = CVector2D(0.0f, 0.0f);\n\tif (CTimer::GetTimeInMilliseconds() > m_leaveCarTimer)\n\t\tClearPause();\n}\n\nvoid\nCPed::SetFall(int extraTime, AnimationId animId, uint8 evenIfNotInControl)\n{\n\tif (m_attachedTo)\n\t\treturn;\n\n\tif (!IsPedInControl() && (!evenIfNotInControl || DyingOrDead()))\n\t\treturn;\n\n\tClearLookFlag();\n\tClearAimFlag();\n\tSetStoredState();\n\tSetPedState(PED_FALL);\n\tCAnimBlendAssociation *fallAssoc = nil;\n\tif (animId == ANIM_STD_NUM) {\n\t\tif (IsPlayer()) {\n\t\t\tfallAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_ROLLOUT_LHS);\n\t\t\tif (!fallAssoc)\n\t\t\t\tfallAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_ROLLOUT_RHS);\n\t\t}\n\t} else {\n\t\tfallAssoc = RpAnimBlendClumpGetAssociation(GetClump(), animId);\n\n\t\tif (fallAssoc) {\n\t\t\tfallAssoc->SetCurrentTime(0.0f);\n\t\t\tfallAssoc->blendAmount = 0.0f;\n\t\t\tfallAssoc->blendDelta = 8.0f;\n\t\t\tfallAssoc->SetRun();\n\t\t}\n\t\telse {\n\t\t\tfallAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, animId, 8.0f);\n\t\t}\n\t\tif (animId == ANIM_STD_BIKE_FALLBACK)\n\t\t\tfallAssoc->SetCurrentTime(0.4f);\n\t}\n\n\tif (extraTime == -1) {\n\t\tm_getUpTimer = UINT32_MAX;\n\t} else if (fallAssoc) {\n\t\tif (IsPlayer()) {\n\t\t\tif (fallAssoc->animId == ANIM_STD_ROLLOUT_LHS || fallAssoc->animId == ANIM_STD_ROLLOUT_RHS) {\n\t\t\t\tm_getUpTimer = 1000.0f * fallAssoc->hierarchy->totalLength\n\t\t\t\t\t+ CTimer::GetTimeInMilliseconds()\n\t\t\t\t\t- 1000.0f * fallAssoc->currentTime\n\t\t\t\t\t+ 100.0f;\n\t\t\t} else {\n\t\t\t\tm_getUpTimer = 1000.0f * fallAssoc->hierarchy->totalLength\n\t\t\t\t\t+ CTimer::GetTimeInMilliseconds()\n\t\t\t\t\t+ 500.0f;\n\t\t\t}\n\t\t} else {\n\t\t\tm_getUpTimer = 1000.0f * fallAssoc->hierarchy->totalLength\n\t\t\t\t+ CTimer::GetTimeInMilliseconds()\n\t\t\t\t+ extraTime\n\t\t\t\t+ ((m_randomSeed + CTimer::GetFrameCounter()) % 1000);\n\t\t}\n\t} else {\n\t\tm_getUpTimer = extraTime\n\t\t\t+ CTimer::GetTimeInMilliseconds()\n\t\t\t+ 1000\n\t\t\t+ ((m_randomSeed + CTimer::GetFrameCounter()) % 1000);\n\t}\n\tbFallenDown = true;\n}\n\nvoid\nCPed::ClearFall(void)\n{\n\tSetGetUp();\n}\n\nvoid\nCPed::Fall(void)\n{\n\tif (m_getUpTimer != UINT32_MAX && CTimer::GetTimeInMilliseconds() > m_getUpTimer && bIsStanding)\n\t\tClearFall();\n\n\tCAnimBlendAssociation *firstPartialAssoc;\n\tCAnimBlendAssociation *fallAssoc;\n\n\tif (IsPlayer() && (bKnockedUpIntoAir || bKnockedOffBike) && !bIsStanding) {\n\t\tfirstPartialAssoc = RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_PARTIAL);\n\n\t\t// What???\n\t\tif (firstPartialAssoc && (firstPartialAssoc->animId == ANIM_STD_FALL_ONBACK || firstPartialAssoc->animId == ANIM_STD_FALL_ONFRONT))\n\t\t\tfallAssoc = firstPartialAssoc;\n\t\telse\n\t\t\tfallAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_FALL_ONBACK);\n\n\t\tif (!fallAssoc)\n\t\t\tfallAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_FALL_ONFRONT);\n\n\t\tif (!fallAssoc && firstPartialAssoc && 0.8f * firstPartialAssoc->hierarchy->totalLength < firstPartialAssoc->currentTime) {\n\t\t\tif (firstPartialAssoc->flags & ASSOC_FRONTAL) {\n\t\t\t\tCAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_FALL_ONFRONT, 8.0f);\n\t\t\t} else {\n\t\t\t\tCAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_FALL_ONBACK, 8.0f);\n\t\t\t}\n\t\t} else if (fallAssoc && fallAssoc->blendAmount > 0.3f && fallAssoc->blendDelta >= 0.0f)\t{\n\t\t\tfloat time = fallAssoc->currentTime;\n\n\t\t\tif (time > 0.667f && time - fallAssoc->timeStep <= 0.667f) {\n\t\t\t\tfallAssoc->SetCurrentTime(0.0f);\n\t\t\t\tfallAssoc->SetRun();\n\t\t\t}\n\t\t}\n\t} else if ((bKnockedUpIntoAir || bKnockedOffBike) && bIsStanding && !bWasStanding) {\n\t\tfallAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_FALL_ONBACK);\n\n\t\tif (!fallAssoc)\n\t\t\tfallAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_FALL_ONFRONT);\n\n\t\tif (fallAssoc) {\n\t\t\tbKnockedUpIntoAir = false;\n\t\t\tbKnockedOffBike = false;\n\t\t\tfallAssoc->speed = 3.0f;\n\t\t\tif (IsPlayer())\n\t\t\t\tSay(SOUND_PED_LAND);\n\n\t\t} else {\n\t\t\tfirstPartialAssoc = RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_PARTIAL);\n\t\t\tif (firstPartialAssoc && !firstPartialAssoc->IsRunning()) {\n\t\t\t\tbKnockedUpIntoAir = false;\n\t\t\t\tbKnockedOffBike = false;\n\t\t\t}\n\t\t}\n\t}\n}\n\nbool\nCPed::CheckIfInTheAir(void)\n{\n\tif (bInVehicle)\n\t\treturn false;\n\n\tCVector pos = GetPosition();\n\tCColPoint foundColPoint;\n\tCEntity *foundEntity;\n\n\tfloat startZ = pos.z - 1.54f;\n\tbool foundGround = CWorld::ProcessVerticalLine(pos, startZ, foundColPoint, foundEntity, true, true, false, true, false, false, nil);\n\tif (!foundGround && m_nPedState != PED_JUMP)\n\t{\n\t\tpos.z -= FEET_OFFSET;\n\t\tif (CWorld::TestSphereAgainstWorld(pos, 0.15f, this, true, false, false, false, false, false))\n\t\t\tfoundGround = true;\n\t}\n\treturn !foundGround;\n}\n\nvoid\nCPed::SetInTheAir(void)\n{\n\tif (bIsInTheAir)\n\t\treturn;\n\n\tbIsInTheAir = true;\n\tCAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_FALL_GLIDE, 4.0f);\n\n\tif (m_nPedState == PED_ATTACK) {\n\t\tClearAttack();\n\t\tClearPointGunAt();\n\t} else if (m_nPedState == PED_FIGHT) {\n\t\tEndFight(ENDFIGHT_FAST);\n\t}\n\n}\n\nvoid\nCPed::InTheAir(void)\n{\n\tCColPoint foundCol;\n\tCEntity *foundEnt;\n\n\tCVector ourPos = GetPosition();\n\tCVector bitBelow = GetPosition();\n\tbitBelow.z -= 4.04f;\n\n\tif (m_vecMoveSpeed.z < 0.0f && !bIsPedDieAnimPlaying) {\n\t\tif (!DyingOrDead()) {\n\t\t\tif (CWorld::ProcessLineOfSight(ourPos, bitBelow, foundCol, foundEnt, true, true, false, true, false, false, false)) {\n\t\t\t\tif (GetPosition().z - foundCol.point.z < 1.3f || bIsStanding)\n\t\t\t\t\tSetLanding();\n\t\t\t} else if (m_nPedState != PED_ABSEIL && !RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_FALL)) {\n\t\t\t\tif (m_vecMoveSpeed.z < -0.1f)\n\t\t\t\t\tCAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_FALL, 4.0f);\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nCPed::SetLanding(void)\n{\n\tif (DyingOrDead())\n\t\treturn;\n\n\tCAnimBlendAssociation *fallAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_FALL);\n\tCAnimBlendAssociation *landAssoc;\n\n\tif (fallAssoc && bIsDrowning)\n\t\treturn;\n\n\tRpAnimBlendClumpSetBlendDeltas(GetClump(), ASSOC_PARTIAL, -1000.0f);\n\tif (fallAssoc || m_nPedType == PEDTYPE_COP && bKnockedUpIntoAir) {\n\t\tlandAssoc = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_FALL_COLLAPSE);\n\t\tDMAudio.PlayOneShot(m_audioEntityId, SOUND_FALL_COLLAPSE, 1.0f);\n\n\t\tif (IsPlayer())\n\t\t\tSay(SOUND_PED_LAND);\n\n\t\tif (m_nPedType == PEDTYPE_COP) {\n\t\t\tif (bKnockedUpIntoAir)\n\t\t\t\tbKnockedUpIntoAir = false;\n\t\t}\n\n\t} else {\n\t\tlandAssoc = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_FALL_LAND);\n\t\tDMAudio.PlayOneShot(m_audioEntityId, SOUND_FALL_LAND, 1.0f);\n\t}\n\n\tlandAssoc->SetFinishCallback(PedLandCB, this);\n\tbIsInTheAir = false;\n\tbIsLanding = true;\n}\n\nvoid\nCPed::SetGetUp(void)\n{\n\tif (m_nPedState == PED_GETUP && bGetUpAnimStarted)\n\t\treturn;\n\n\tif (!CanSetPedState())\n\t\treturn;\n\n\tif (m_fHealth >= 1.0f || IsPedHeadAbovePos(-0.3f)) {\n\t\tif (bUpdateAnimHeading) {\n\t\t\tm_fRotationCur = CGeneral::LimitRadianAngle(m_fRotationCur);\n\t\t\tm_fRotationCur -= HALFPI;\n\t\t\tbUpdateAnimHeading = false;\n\t\t}\n\t\tif (m_nPedState != PED_GETUP) {\n\t\t\tSetStoredState();\n\t\t\tSetPedState(PED_GETUP);\n\t\t}\n\n\t\tCVehicle *collidingVeh = (CVehicle*)m_pCollidingEntity;\n\t\tCVehicle *veh = (CVehicle*)CPedPlacement::IsPositionClearOfCars(&GetPosition());\n\t\tif (veh && veh->m_vehType != VEHICLE_TYPE_BIKE && veh != m_attachedTo ||\n\t\t\tcollidingVeh && collidingVeh->IsVehicle() && collidingVeh->m_vehType != VEHICLE_TYPE_BIKE\n\t\t\t&& ((uint8)(CTimer::GetFrameCounter() + m_randomSeed + 5) % 8 ||\n\t\t\t\t CCollision::ProcessColModels(GetMatrix(), *GetColModel(), collidingVeh->GetMatrix(), *collidingVeh->GetColModel(),\n\t\t\t\t\taTempPedColPts, nil, nil) > 0)) {\n\n\t\t\tbGetUpAnimStarted = false;\n\t\t\tif (IsPlayer())\n\t\t\t\tInflictDamage(nil, WEAPONTYPE_RUNOVERBYCAR, CTimer::GetTimeStep(), PEDPIECE_TORSO, 0);\n\t\t\telse if(CPad::GetPad(0)->ArePlayerControlsDisabled())\n\t\t\t\tInflictDamage(nil, WEAPONTYPE_RUNOVERBYCAR, 1000.0f, PEDPIECE_TORSO, 0);\n\t\t\treturn;\n\t\t}\n\t\tbGetUpAnimStarted = true;\n\t\tm_pCollidingEntity = nil;\n\t\tbKnockedUpIntoAir = false;\n\t\tbKnockedOffBike = false;\n\t\tCAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_RUNFAST);\n\t\tif (animAssoc) {\n\t\t\tif (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_RUN)) {\n\t\t\t\tCAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_STD_RUN, 8.0f);\n\t\t\t} else {\n\t\t\t\tCAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_STD_IDLE, 8.0f);\n\t\t\t}\n\t\t\tanimAssoc->flags |= ASSOC_DELETEFADEDOUT;\n\t\t}\n\n\t\tif (m_nWaitState == WAITSTATE_SUN_BATHE_IDLE) {\n\t\t\tm_headingRate = 0.0f;\n\n\t\t\t// Seemingly they planned to use different getup anims for different conditions, but sadly in final game all getup anims(GETUP1, GETUP2, GETUP3) are same...\n\t\t\tif (bFleeWhenStanding && m_threatEx)\n\t\t\t\tanimAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_GET_UP, 1000.0f);\n\t\t\telse\n\t\t\t\tanimAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_GET_UP, 1000.0f);\n\n\t\t} else if (RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_FRONTAL))\n\t\t\tanimAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_GET_UP_FRONT, 1000.0f);\n\t\telse\n\t\t\tanimAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_GET_UP, 1000.0f);\n\n\t\tanimAssoc->SetFinishCallback(PedGetupCB, this);\n\t} else {\n\t\tm_fHealth = 0.0f;\n\t\tSetDie(ANIM_STD_NUM, 4.0f, 0.0f);\n\t}\n}\n\nvoid\nCPed::Mug(void)\n{\n\tif (m_pSeekTarget && m_pSeekTarget->IsPed()) {\n\n\t\tif (CTimer::GetTimeInMilliseconds() <= m_attackTimer - 2000) {\n\t\t\tif ((m_pSeekTarget->GetPosition() - GetPosition()).Magnitude() > 3.0f)\n\t\t\t\tm_wepSkills = 50;\n\n\t\t\tSay(SOUND_PED_MUGGING);\n\t\t\t((CPed*)m_pSeekTarget)->Say(SOUND_PED_ROBBED);\n\t\t} else {\n\t\t\tSetWanderPath(CGeneral::GetRandomNumber() & 7);\n\t\t\tSetFlee(m_pSeekTarget, 20000);\n\t\t}\n\n\t} else {\n\t\tSetIdle();\n\t}\n}\n\n// Unused\nvoid\nCPed::SetLook(float direction)\n{\n\tif (IsPedInControl()) {\n\t\tSetStoredState();\n\t\tSetPedState(PED_LOOK_HEADING);\n\t\tSetLookFlag(direction, false);\n\t}\n}\n\nvoid\nCPed::SetLook(CEntity* to)\n{\n\tif (IsPedInControl()) {\n\t\tSetStoredState();\n\t\tSetPedState(PED_LOOK_ENTITY);\n\t\tSetLookFlag(to, false);\n\t}\n}\n\nvoid\nCPed::SetLookTimer(int time)\n{\n\tif (CTimer::GetTimeInMilliseconds() > m_lookTimer) {\n\t\tm_lookTimer = CTimer::GetTimeInMilliseconds() + time;\n\t}\n}\n\nvoid\nCPed::SetAttackTimer(uint32 time)\n{\n\tif (CTimer::GetTimeInMilliseconds() > m_attackTimer)\n\t\tm_attackTimer = Max(m_shootTimer, CTimer::GetTimeInMilliseconds()) + time;\n}\n\nvoid\nCPed::SetShootTimer(uint32 time)\n{\n\tif (CTimer::GetTimeInMilliseconds() > m_shootTimer) {\n\t\tm_shootTimer = CTimer::GetTimeInMilliseconds() + time;\n\t}\n}\n\nvoid\nCPed::ClearLook(void)\n{\n\tRestorePreviousState();\n\tClearLookFlag();\n}\n\nvoid\nCPed::Look(void)\n{\n\tTurnBody();\n}\n\nbool\nCPed::TurnBody(void)\n{\n\tbool turnDone = true;\n\n\tif (m_pLookTarget)\n\t\tm_fLookDirection = CGeneral::GetRadianAngleBetweenPoints(\n\t\t\t\t\tm_pLookTarget->GetPosition().x,\n\t\t\t\t\tm_pLookTarget->GetPosition().y,\n\t\t\t\t\tGetPosition().x,\n\t\t\t\t\tGetPosition().y);\n\n\tfloat limitedLookDir = CGeneral::LimitRadianAngle(m_fLookDirection);\n\tfloat currentRot = m_fRotationCur;\n\n\tif (currentRot - PI > limitedLookDir)\n\t\tlimitedLookDir += 2 * PI;\n\telse if (PI + currentRot < limitedLookDir)\n\t\tlimitedLookDir -= 2 * PI;\n\n\tfloat neededTurn = currentRot - limitedLookDir;\n\tm_fRotationDest = limitedLookDir;\n\n\tif (Abs(neededTurn) > 0.05f) {\n\t\tturnDone = false;\n\t\tcurrentRot -= neededTurn * 0.2f;\n\t}\n\n\tm_fRotationCur = currentRot;\n\tm_fLookDirection = limitedLookDir;\n\treturn turnDone;\n}\n\nvoid\nCPed::SetSeek(CVector pos, float distanceToCountDone)\n{\n\tif (!IsPedInControl()\n\t\t|| (m_nPedState == PED_SEEK_POS && m_vecSeekPos.x == pos.x && m_vecSeekPos.y == pos.y) || m_nPedState == PED_FOLLOW_PATH)\n\t\treturn;\n\n\tif (!CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->IsFlagSet(WEAPONFLAG_CANAIM_WITHARM)) {\n\t\tClearPointGunAt();\n\t}\n\n\tif (m_nPedState != PED_SEEK_POS)\n\t\tSetStoredState();\n\n\tSetPedState(PED_SEEK_POS);\n\tm_distanceToCountSeekDone = distanceToCountDone;\n\tm_vecSeekPos = pos;\n}\nvoid\nCPed::SetSeek(CEntity *seeking, float distanceToCountDone)\n{\n\tif (!IsPedInControl())\n\t\treturn;\n\n\tif (m_nPedState == PED_SEEK_ENTITY && m_pSeekTarget == seeking)\n\t\treturn;\n\n\tif (!seeking || m_nPedState == PED_FOLLOW_PATH)\n\t\treturn;\n\n\tif (m_nPedState != PED_SEEK_ENTITY)\n\t\tSetStoredState();\n\n\tSetPedState(PED_SEEK_ENTITY);\n\tm_distanceToCountSeekDone = distanceToCountDone;\n\tm_pSeekTarget = seeking;\n\tm_pSeekTarget->RegisterReference((CEntity **) &m_pSeekTarget);\n\tSetMoveState(PEDMOVE_STILL);\n}\n\nvoid\nCPed::ClearSeek(void)\n{\n\tSetIdle();\n\tbRunningToPhone = false;\n}\n\nbool\nCPed::Seek(void)\n{\n\tfloat distanceToCountItDone = m_distanceToCountSeekDone;\n\teMoveState nextMove = PEDMOVE_NONE;\n\n\tif (m_objective != OBJECTIVE_ENTER_CAR_AS_DRIVER) {\n\n\t\tif (m_nPedState != PED_EXIT_TRAIN && m_nPedState != PED_ENTER_TRAIN && m_nPedState != PED_SEEK_IN_BOAT &&\n\t\t\tm_objective != OBJECTIVE_ENTER_CAR_AS_PASSENGER && m_objective != OBJECTIVE_SOLICIT_VEHICLE && !bDuckAndCover) {\n\t\t\t\n\t\t\tif ((!m_pedInObjective || !m_pedInObjective->bInVehicle)\n\t\t\t\t&& (CTimer::GetFrameCounter() + m_randomSeed + 60) % 32 == 0) {\n\n\t\t\t\tCEntity *obstacle = CWorld::TestSphereAgainstWorld(m_vecSeekPos, 0.4f, nil,\n\t\t\t\t\t\t\t\t\tfalse, true, false, false, false, false);\n\n\t\t\t\tif (obstacle) {\n\t\t\t\t\tif (!obstacle->IsVehicle() || ((CVehicle*)obstacle)->IsCar()) {\n\t\t\t\t\t\tdistanceToCountItDone = 2.5f;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tCVehicleModelInfo *vehModel = (CVehicleModelInfo *)CModelInfo::GetModelInfo(obstacle->GetModelIndex());\n\t\t\t\t\t\tfloat yLength = vehModel->GetColModel()->boundingBox.max.y\n\t\t\t\t\t\t\t\t\t\t- vehModel->GetColModel()->boundingBox.min.y;\n\t\t\t\t\t\tdistanceToCountItDone = yLength * 0.55f;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (!m_pSeekTarget && m_nPedState == PED_SEEK_ENTITY)\n\t\tClearSeek();\n\n\tif (m_objective == OBJECTIVE_FOLLOW_CHAR_IN_FORMATION && !m_pedInObjective) {\n\t\tm_objective = OBJECTIVE_NONE;\n\t\tClearObjective();\n\t\tSetWanderPath(0);\n\t\treturn false;\n\t}\n\n\tfloat seekPosDist = (m_vecSeekPos - GetPosition()).Magnitude2D();\n\tif (seekPosDist < 2.0f || m_objective == OBJECTIVE_GOTO_AREA_ON_FOOT) {\n\n\t\tif (m_objective == OBJECTIVE_FOLLOW_CHAR_IN_FORMATION) {\n\n\t\t\tif (m_pedInObjective->m_nMoveState != PEDMOVE_STILL)\n\t\t\t\tnextMove = m_pedInObjective->m_nMoveState;\n\t\t} else\n\t\t\tnextMove = PEDMOVE_WALK;\n\n\t} else if (m_objective != OBJECTIVE_FOLLOW_CHAR_IN_FORMATION) {\n\n\t\tif (m_objective == OBJECTIVE_SPRINT_TO_AREA)\n\t\t\tnextMove = PEDMOVE_SPRINT;\n\t\telse if (m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT || m_objective == OBJECTIVE_KILL_CHAR_ANY_MEANS || m_objective == OBJECTIVE_RUN_TO_AREA || bIsRunning)\n\t\t\tnextMove = PEDMOVE_RUN;\n\t\telse\n\t\t\tnextMove = PEDMOVE_WALK;\n\n\t} else if (seekPosDist <= 2.0f) {\n\n\t\tif (m_pedInObjective->m_nMoveState != PEDMOVE_STILL)\n\t\t\tnextMove = m_pedInObjective->m_nMoveState;\n\n\t} else {\n\t\tnextMove = PEDMOVE_RUN;\n\t}\n\n\tif (m_nPedState == PED_SEEK_ENTITY) {\n\t\tif (m_pSeekTarget->IsPed()) {\n\t\t\tif (((CPed*)m_pSeekTarget)->bInVehicle)\n\t\t\t\tdistanceToCountItDone += 2.0f;\n\t\t}\n\t}\n\n\tCVector *nextNode = SeekFollowingPath();\n\n\tif (nextNode || seekPosDist >= distanceToCountItDone) {\n\t\tif (bIsRunning && nextMove != PEDMOVE_SPRINT)\n\t\t\tnextMove = PEDMOVE_RUN;\n\n\t\tif (CTimer::GetTimeInMilliseconds() <= m_nPedStateTimer) {\n\n\t\t\tif (m_actionX != 0.0f && m_actionY != 0.0f) {\n\n\t\t\t\tm_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(\n\t\t\t\t\tm_actionX, m_actionY,\n\t\t\t\t\tGetPosition().x, GetPosition().y);\n\n\t\t\t\tfloat neededTurn = Abs(m_fRotationDest - m_fRotationCur);\n\n\t\t\t\tif (neededTurn > PI)\n\t\t\t\t\tneededTurn = TWOPI - neededTurn;\n\n\t\t\t\tif (neededTurn > HALFPI) {\n\t\t\t\t\tif (seekPosDist >= 1.0f) {\n\t\t\t\t\t\tif (seekPosDist < 2.0f) {\n\t\t\t\t\t\t\tif (bIsRunning)\n\t\t\t\t\t\t\t\tnextMove = PEDMOVE_RUN;\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\tnextMove = PEDMOVE_WALK;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tnextMove = PEDMOVE_STILL;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tCVector2D moveDist(GetPosition().x - m_actionX, GetPosition().y - m_actionY);\n\t\t\t\tif (moveDist.Magnitude() < 0.5f) {\n\t\t\t\t\tm_nPedStateTimer = 0;\n\t\t\t\t\tm_actionX = 0.f;\n\t\t\t\t\tm_actionY = 0.f;\n\t\t\t\t}\n\t\t\t}\n\n\t\t} else {\n\t\t\tif (nextNode) {\n\t\t\t\tm_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(\n\t\t\t\t\tnextNode->x, nextNode->y,\n\t\t\t\t\tGetPosition().x, GetPosition().y);\n\t\t\t} else {\n\t\t\t\tm_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(\n\t\t\t\t\tm_vecSeekPos.x, m_vecSeekPos.y,\n\t\t\t\t\tGetPosition().x, GetPosition().y);\n\t\t\t}\n\n\t\t\tfloat neededTurn = Abs(m_fRotationDest - m_fRotationCur);\n\n\t\t\tif (neededTurn > PI)\n\t\t\t\tneededTurn = TWOPI - neededTurn;\n\n\t\t\tif (neededTurn > HALFPI) {\n\t\t\t\tif (seekPosDist >= 1.0f && neededTurn <= DEGTORAD(135.0f)) {\n\t\t\t\t\tif (seekPosDist < 2.0f)\n\t\t\t\t\t\tnextMove = PEDMOVE_WALK;\n\t\t\t\t} else {\n\t\t\t\t\tnextMove = PEDMOVE_STILL;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (((m_nPedState == PED_FLEE_POS || m_nPedState == PED_FLEE_ENTITY) && m_nMoveState < nextMove)\n\t\t\t|| (m_nPedState != PED_FLEE_POS && m_nPedState != PED_FLEE_ENTITY && m_nPedState != PED_FOLLOW_PATH && m_objective != OBJECTIVE_GOTO_CHAR_ON_FOOT && m_nWaitState == WAITSTATE_FALSE)) {\n\n\t\t\tSetMoveState(nextMove);\n\t\t}\n\t\t\n\t\tSetMoveAnim();\n\t\treturn false;\n\t}\n\n\tif ((m_objective != OBJECTIVE_FOLLOW_CHAR_IN_FORMATION || m_pedInObjective->m_nMoveState == PEDMOVE_STILL) && m_nMoveState != PEDMOVE_STILL) {\n\t\tm_nPedStateTimer = 0;\n\t\tm_actionX = 0.f;\n\t\tm_actionY = 0.f;\n\t}\n\n\tif (m_objective == OBJECTIVE_GOTO_AREA_ON_FOOT || m_objective == OBJECTIVE_RUN_TO_AREA || m_objective == OBJECTIVE_SPRINT_TO_AREA ||\n\t\tm_objective == OBJECTIVE_GOTO_AREA_ANY_MEANS || IsUseAttractorObjective(m_objective)) {\n\n\t\tif (m_pNextPathNode)\n\t\t\tm_pNextPathNode = nil;\n\t\telse\n\t\t\tbScriptObjectiveCompleted = true;\n\n\t\tbUsePedNodeSeek = true;\n\t}\n\n\treturn true;\n}\n\nvoid\nCPed::SetFlee(CVector2D const &from, int time)\n{\n\tif (CTimer::GetTimeInMilliseconds() < m_nPedStateTimer || !IsPedInControl() || bKindaStayInSamePlace)\n\t\treturn;\n\n\tif (m_nPedState != PED_FLEE_ENTITY) {\n\t\tSetStoredState();\n\t\tSetPedState(PED_FLEE_POS);\n\t\tSetMoveState(PEDMOVE_RUN);\n\t\tm_fleeFromPos = from;\n\t}\n\n\tbUsePedNodeSeek = true;\n\tm_pNextPathNode = nil;\n\tm_fleeTimer = CTimer::GetTimeInMilliseconds() + time;\n\n\tfloat angleToFace = CGeneral::GetRadianAngleBetweenPoints(\n\t\tGetPosition().x, GetPosition().y,\n\t\tfrom.x, from.y);\n\n\tm_fRotationDest = CGeneral::LimitRadianAngle(angleToFace);\n\tif (m_fRotationCur - PI > m_fRotationDest) {\n\t\tm_fRotationDest += 2 * PI;\n\t} else if (PI + m_fRotationCur < m_fRotationDest) {\n\t\tm_fRotationDest -= 2 * PI;\n\t}\n}\n\nvoid\nCPed::SetFlee(CEntity *fleeFrom, int time)\n{\n\tif (!IsPedInControl() || bKindaStayInSamePlace || !fleeFrom)\n\t\treturn;\n\n\tSetStoredState();\n\tSetPedState(PED_FLEE_ENTITY);\n\tbUsePedNodeSeek = true;\n\tSetMoveState(PEDMOVE_RUN);\n\tm_fleeFrom = fleeFrom;\n\tm_fleeFrom->RegisterReference((CEntity **) &m_fleeFrom);\n\n\tif (time <= 0)\n\t\tm_fleeTimer = 0;\n\telse\n\t\tm_fleeTimer = CTimer::GetTimeInMilliseconds() + time;\n\n\tfloat angleToFace = CGeneral::GetRadianAngleBetweenPoints(\n\t\t\tGetPosition().x, GetPosition().y,\n\t\t\tfleeFrom->GetPosition().x, fleeFrom->GetPosition().y);\n\n\tm_fRotationDest = CGeneral::LimitRadianAngle(angleToFace);\n\tif (m_fRotationCur - PI > m_fRotationDest) {\n\t\tm_fRotationDest += 2 * PI;\n\t} else if (PI + m_fRotationCur < m_fRotationDest) {\n\t\tm_fRotationDest -= 2 * PI;\n\t}\n}\n\nvoid\nCPed::ClearFlee(void)\n{\n\tRestorePreviousState();\n\tbUsePedNodeSeek = false;\n\tm_chatTimer = 0;\n\tm_fleeTimer = 0;\n}\n\nvoid\nCPed::Flee(void)\n{\n\tif (CTimer::GetTimeInMilliseconds() > m_fleeTimer && m_fleeTimer) {\n\t\tbool mayFinishFleeing = true;\n\t\tif (m_nPedState == PED_FLEE_ENTITY) {\n\t\t\tif ((CVector2D(GetPosition()) - ms_vec2DFleePosition).MagnitudeSqr() < sq(30.0f))\n\t\t\t\tmayFinishFleeing = false;\n\t\t}\n\n\t\tif (mayFinishFleeing) {\n\t\t\tbMakeFleeScream = false;\n\t\t\teMoveState moveState = m_nMoveState;\n\t\t\tClearFlee();\n\n\t\t\tif (m_objective == OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE || m_objective == OBJECTIVE_FLEE_CHAR_ON_FOOT_ALWAYS) {\n\t\t\t\tbBeingChasedByPolice = false;\n\t\t\t\tRestorePreviousObjective();\n\t\t\t}\n\n\t\t\tif ((m_nPedState == PED_IDLE || m_nPedState == PED_WANDER_PATH) && CGeneral::GetRandomNumber() & 1) {\n\t\t\t\tSetWaitState(moveState <= PEDMOVE_WALK ? WAITSTATE_CROSS_ROAD_LOOK : WAITSTATE_FINISH_FLEE, nil);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tm_fleeTimer = CTimer::GetTimeInMilliseconds() + 5000;\n\t}\n\n\tif (bMakeFleeScream && !((CTimer::GetFrameCounter() + m_randomSeed) & 7)) {\n\t\tSay(SOUND_PED_FLEE_SPRINT);\n\t\tbMakeFleeScream = false;\n\t}\n\n\tif (bUsePedNodeSeek) {\n\t\tCPathNode *realLastNode = nil;\n\t\tuint8 nextDirection = 0;\n\t\tuint8 curDirectionShouldBe = 9; // means not defined yet\n\n\t\tif (m_nPedStateTimer < CTimer::GetTimeInMilliseconds()\n\t\t\t&& m_collidingThingTimer < CTimer::GetTimeInMilliseconds()) {\n\n\t\t\tif (m_pNextPathNode && CTimer::GetTimeInMilliseconds() > m_chatTimer)  {\n\n\t\t\t\tcurDirectionShouldBe = CGeneral::GetNodeHeadingFromVector(GetPosition().x - ms_vec2DFleePosition.x, GetPosition().y - ms_vec2DFleePosition.y);\n\t\t\t\tif (m_nPathDir < curDirectionShouldBe)\n\t\t\t\t\tm_nPathDir += 8;\n\n\t\t\t\tint dirDiff = m_nPathDir - curDirectionShouldBe;\n\t\t\t\tif (dirDiff > 2 && dirDiff < 6) {\n\t\t\t\t\trealLastNode = nil;\n\t\t\t\t\tm_pLastPathNode = m_pNextPathNode;\n\t\t\t\t\tm_pNextPathNode = nil;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (m_pNextPathNode) {\n\t\t\t\tm_vecSeekPos = CPathFind::TakeWidthIntoAccountForWandering(m_pNextPathNode, m_randomSeed);\n\t\t\t\tif (m_nMoveState == PEDMOVE_RUN)\n\t\t\t\t\tbIsRunning = true;\n\n\t\t\t\teMoveState moveState = m_nMoveState;\n\t\t\t\tif (Seek()) {\n\t\t\t\t\trealLastNode = m_pLastPathNode;\n\t\t\t\t\tm_pLastPathNode = m_pNextPathNode;\n\t\t\t\t\tm_pNextPathNode = nil;\n\t\t\t\t}\n\t\t\t\tbIsRunning = false;\n\t\t\t\tSetMoveState(moveState);\n\t\t\t}\n\t\t}\n\n\t\tif (!m_pNextPathNode) {\n\t\t\tif (curDirectionShouldBe == 9) {\n\t\t\t\tcurDirectionShouldBe = CGeneral::GetNodeHeadingFromVector(GetPosition().x - ms_vec2DFleePosition.x, GetPosition().y - ms_vec2DFleePosition.y);\n\t\t\t}\n\t\t\tThePaths.FindNextNodeWandering(PATH_PED, GetPosition(), &m_pLastPathNode, &m_pNextPathNode,\n\t\t\t\tcurDirectionShouldBe,\n\t\t\t\t&nextDirection);\n\n\t\t\tif (curDirectionShouldBe < nextDirection)\n\t\t\t\tcurDirectionShouldBe += 8;\n\t\t\t\n\t\t\tif (m_pNextPathNode && m_pNextPathNode != realLastNode && m_pNextPathNode != m_pLastPathNode && curDirectionShouldBe - nextDirection != 4) {\n\t\t\t\tm_nPathDir = nextDirection;\n\t\t\t\tm_chatTimer = CTimer::GetTimeInMilliseconds() + 2000;\n\t\t\t} else {\n\t\t\t\tbUsePedNodeSeek = false;\n\t\t\t\tSetMoveState(PEDMOVE_RUN);\n\t\t\t\tFlee();\n\t\t\t}\n\t\t}\n\t\treturn;\n\t}\n\n\tif ((m_nPedState == PED_FLEE_ENTITY || m_nPedState == PED_ON_FIRE) && m_nPedStateTimer < CTimer::GetTimeInMilliseconds()) {\n\n\t\tfloat angleToFleeFromPos = CGeneral::GetRadianAngleBetweenPoints(\n\t\t\tGetPosition().x,\n\t\t\tGetPosition().y,\n\t\t\tms_vec2DFleePosition.x,\n\t\t\tms_vec2DFleePosition.y);\n\n\t\tm_fRotationDest = CGeneral::LimitRadianAngle(angleToFleeFromPos);\n\n\t\tif (m_fRotationCur - PI > m_fRotationDest)\n\t\t\tm_fRotationDest += TWOPI;\n\t\telse if (PI + m_fRotationCur < m_fRotationDest)\n\t\t\tm_fRotationDest -= TWOPI;\n\t}\n\n\tif (CTimer::GetTimeInMilliseconds() >= m_collidingThingTimer)\n\t\treturn;\n\n\tif (!m_collidingEntityWhileFleeing)\n\t\treturn;\n\n\tdouble collidingThingPriorityMult = (double)(m_collidingThingTimer - CTimer::GetTimeInMilliseconds()) * 2.0 / 2500;\n\n\tif (collidingThingPriorityMult <= 1.5) {\n\t\tdouble angleToFleeEntity = CGeneral::GetRadianAngleBetweenPoints(\n\t\t\tGetPosition().x,\n\t\t\tGetPosition().y,\n\t\t\tm_collidingEntityWhileFleeing->GetPosition().x,\n\t\t\tm_collidingEntityWhileFleeing->GetPosition().y);\n\t\tangleToFleeEntity = CGeneral::LimitRadianAngle(angleToFleeEntity);\n\n\t\tdouble angleToFleeCollidingThing = CGeneral::GetRadianAngleBetweenPoints(\n\t\t\tm_vecDamageNormal.x,\n\t\t\tm_vecDamageNormal.y,\n\t\t\t0.0f,\n\t\t\t0.0f);\n\t\tangleToFleeCollidingThing = CGeneral::LimitRadianAngle(angleToFleeCollidingThing);\n\n\t\tif (angleToFleeEntity - PI > angleToFleeCollidingThing)\n\t\t\tangleToFleeCollidingThing += TWOPI;\n\t\telse if (PI + angleToFleeEntity < angleToFleeCollidingThing)\n\t\t\tangleToFleeCollidingThing -= TWOPI;\n\n\t\tif (collidingThingPriorityMult <= 1.0f) {\n\t\t\t// Range [0.0, 1.0]\n\n\t\t\tfloat angleToFleeBoth = (angleToFleeCollidingThing + angleToFleeEntity) * 0.5f;\n\n\t\t\tif (m_fRotationDest - PI > angleToFleeBoth)\n\t\t\t\tangleToFleeBoth += TWOPI;\n\t\t\telse if (PI + m_fRotationDest < angleToFleeBoth)\n\t\t\t\tangleToFleeBoth -= TWOPI;\n\t\n\t\t\tm_fRotationDest = (1.0f - collidingThingPriorityMult) * m_fRotationDest + collidingThingPriorityMult * angleToFleeBoth;\n\t\t} else {\n\t\t\t// Range (1.0, 1.5]\n\n\t\t\tdouble adjustedMult = (collidingThingPriorityMult - 1.0f) * 2.0f;\n\t\t\tm_fRotationDest = angleToFleeEntity * (1.0 - adjustedMult) + adjustedMult * angleToFleeCollidingThing;\n\t\t}\n\t} else {\n\t\tm_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(\n\t\t\tm_vecDamageNormal.x,\n\t\t\tm_vecDamageNormal.y,\n\t\t\t0.0f,\n\t\t\t0.0f);\n\t\tm_fRotationDest = CGeneral::LimitRadianAngle(m_fRotationDest);\n\t}\n\n\tm_fRotationCur = CGeneral::LimitRadianAngle(m_fRotationCur);\n\n\tif (m_fRotationCur - PI > m_fRotationDest)\n\t\tm_fRotationDest += TWOPI;\n\telse if (PI + m_fRotationCur < m_fRotationDest)\n\t\tm_fRotationDest -= TWOPI;\n\n}\n\n// \"Wander range\" state is unused in game, and you can't use it without SetWanderRange anyway\nvoid\nCPed::WanderRange(void)\n{\n\tbool arrived = Seek();\n\tif (arrived) {\n\t\tIdle();\n\t\tif ((m_randomSeed + 3 * CTimer::GetFrameCounter()) % 1000 > 997) {\n\t\t\tCVector2D newCoords2D = m_wanderRangeBounds->GetRandomPointInRange();\n\t\t\tSetSeek(CVector(newCoords2D.x, newCoords2D.y, GetPosition().z), 2.5f);\n\t\t}\n\t}\n}\n\nbool\nCPed::SetWanderPath(int8 pathStateDest)\n{\n\tuint8 nextPathState;\n\n\tif (IsPlayer())\n\t\treturn false;\n\n\tif (IsPedInControl()) {\n\t\tif (bKindaStayInSamePlace) {\n\t\t\tSetIdle();\n\t\t\treturn false;\n\t\t} else {\n\t\t\tm_nPathDir = pathStateDest;\n\t\t\tif (pathStateDest == 0)\n\t\t\t\tpathStateDest = CGeneral::GetRandomNumberInRange(1, 7);\n\n\t\t\tThePaths.FindNextNodeWandering(PATH_PED, GetPosition(), &m_pLastPathNode, &m_pNextPathNode,\n\t\t\t\tm_nPathDir, &nextPathState);\n\n\t\t\t// Circular loop until we find a node for current m_nPathDir\n\t\t\twhile (!m_pNextPathNode) {\n\t\t\t\tm_nPathDir = (m_nPathDir+1) % 8;\n\n\t\t\t\t// We're at where we started and couldn't find any node\n\t\t\t\tif (m_nPathDir == pathStateDest) {\n\t\t\t\t\tClearAll();\n\t\t\t\t\tSetIdle();\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tThePaths.FindNextNodeWandering(PATH_PED, GetPosition(), &m_pLastPathNode, &m_pNextPathNode,\n\t\t\t\t\tm_nPathDir, &nextPathState);\n\t\t\t}\n\n\t\t\t// We did it, save next path state and return true\n\t\t\tm_nPathDir = nextPathState;\n\t\t\tSetPedState(PED_WANDER_PATH);\n\t\t\tSetMoveState(PEDMOVE_WALK);\n\t\t\tbIsRunning = false;\n\t\t\treturn true;\n\t\t}\n\t} else {\n\t\tm_nPathDir = pathStateDest;\n\t\tbStartWanderPathOnFoot = true;\n\t\treturn false;\n\t}\n}\n\nvoid\nCPed::WanderPath(void)\n{\n\tif (!m_pNextPathNode) {\n\t\tprintf(\"THIS SHOULDN@T HAPPEN TOO OFTEN\\n\");\n\t\tSetIdle();\n\t\treturn;\n\t}\n\tif (m_nWaitState == WAITSTATE_FALSE) {\n\t\tif (m_nMoveState == PEDMOVE_STILL || m_nMoveState == PEDMOVE_NONE)\n\t\t\tSetMoveState(PEDMOVE_WALK);\n\t}\n\tm_vecSeekPos = CPathFind::TakeWidthIntoAccountForWandering(m_pNextPathNode, m_randomSeed);\n\tm_vecSeekPos.z += 1.0f;\n\n\t// Only returns true when ped is stuck(not stopped) I think, then we should assign new direction or wait state to him.\n\tif (!Seek())\n\t\treturn;\n\n\tCPathNode *previousLastNode = m_pLastPathNode;\n\tuint8 randVal = (m_randomSeed + 3 * CTimer::GetFrameCounter()) % 100;\n\n\t// We don't prefer 180-degree turns in normal situations\n\tuint8 dirWeWouldntPrefer = m_nPathDir;\n\tif (dirWeWouldntPrefer <= 3)\n\t\tdirWeWouldntPrefer += 4;\n\telse\n\t\tdirWeWouldntPrefer -= 4;\n\n\tCPathNode *nodeWeWouldntPrefer = nil;\n\tuint8 dirToSet = 9; // means undefined\n\tuint8 dirWeWouldntPrefer2 = 9; // means undefined\n\tuint8 tryCount = 0;\n\n\tif (randVal <= 90) {\n\t\tif (randVal > 80) {\n\t\t\tm_nPathDir += 2;\n\t\t\tm_nPathDir %= 8;\n\t\t}\n\t} else {\n\t\tm_nPathDir -= 2;\n\t\tif (m_nPathDir < 0)\n\t\t\tm_nPathDir += 8;\n\t}\n\n\tm_pLastPathNode = m_pNextPathNode;\n\tThePaths.FindNextNodeWandering(PATH_PED, GetPosition(), &m_pLastPathNode, &m_pNextPathNode,\n\t\tm_nPathDir, &dirToSet);\n\n\tif (((CPedModelInfo*)CModelInfo::GetModelInfo(m_modelIndex))->m_pedStatType == PEDSTAT_SKATER) {\n\t\tif (m_pNextPathNode) {\n\t\t\tCVector unpacked(m_pNextPathNode->GetPosition() / 8.f);\n\t\t\tif (!CPopulation::IsSkateable(unpacked))\n\t\t\t\tm_pNextPathNode = nil;\n\t\t}\n\t}\n\n\t// NB: SetWanderPath checks for m_nPathDir == dirToStartWith, this one checks for tryCount > 7\n\twhile (!m_pNextPathNode) {\n\t\ttryCount++;\n\t\tm_nPathDir = (m_nPathDir + 1) % 8;\n\n\t\t// We're at where we started and couldn't find any node\n\t\tif (tryCount > 7) {\n\t\t\tif (!nodeWeWouldntPrefer) {\n\t\t\t\tClearAll();\n\t\t\t\tSetIdle();\n\t\t\t\t// Probably this text carried over here after copy-pasting this loop from early version of SetWanderPath.\n\t\t\t\tError(\"Can't find valid path node, SetWanderPath, Ped.cpp\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tm_pNextPathNode = nodeWeWouldntPrefer;\n\t\t\tdirToSet = dirWeWouldntPrefer2;\n\t\t} else {\n\t\t\tThePaths.FindNextNodeWandering(PATH_PED, GetPosition(), &m_pLastPathNode, &m_pNextPathNode,\n\t\t\t\tm_nPathDir, &dirToSet);\n\t\t\tif (m_pNextPathNode) {\n\t\t\t\tif (dirToSet == dirWeWouldntPrefer) {\n\t\t\t\t\tnodeWeWouldntPrefer = m_pNextPathNode;\n\t\t\t\t\tdirWeWouldntPrefer2 = dirToSet;\n\t\t\t\t\tm_pNextPathNode = nil;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (((CPedModelInfo*)CModelInfo::GetModelInfo(m_modelIndex))->m_pedStatType == PEDSTAT_SKATER) {\n\t\t\t\tif (m_pNextPathNode) {\n\t\t\t\t\tCVector unpacked(m_pNextPathNode->GetPosition() / 8.f);\n\t\t\t\t\tif (!CPopulation::IsSkateable(unpacked))\n\t\t\t\t\t\tm_pNextPathNode = nil;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tm_nPathDir = dirToSet;\n\tif (m_pLastPathNode == m_pNextPathNode) {\n\t\tm_pNextPathNode = previousLastNode;\n\t\tSetWaitState(WAITSTATE_DOUBLEBACK, nil);\n\t\tSay(SOUND_PED_WAIT_DOUBLEBACK);\n\t} else if (ThePaths.TestForPedTrafficLight(m_pLastPathNode, m_pNextPathNode)) {\n\t\tSetWaitState(WAITSTATE_TRAFFIC_LIGHTS, nil);\n\t} else if (ThePaths.TestCrossesRoad(m_pLastPathNode, m_pNextPathNode)) {\n\t\tSetWaitState(WAITSTATE_CROSS_ROAD, nil);\n\t} else if (m_pNextPathNode == previousLastNode) {\n\t\tSetWaitState(WAITSTATE_DOUBLEBACK, nil);\n\t\tSay(SOUND_PED_WAIT_DOUBLEBACK);\n\t}\n}\nvoid\nCPed::Avoid(void)\n{\n\tCPed *nearestPed;\n\n\tif(m_pedStats->m_temper > m_pedStats->m_fear && m_pedStats->m_temper > 50)\n\t\treturn;\n\n\tif (CTimer::GetTimeInMilliseconds() > m_nPedStateTimer) {\n\n\t\tif (m_nMoveState != PEDMOVE_NONE && m_nMoveState != PEDMOVE_STILL) {\n\t\t\tnearestPed = m_nearPeds[0];\n\n\t\t\tif (nearestPed && nearestPed->m_nPedState != PED_DEAD && nearestPed != m_pSeekTarget && nearestPed != m_pedInObjective) {\n\n\t\t\t\t// Check if this ped wants to avoid the nearest one\n\t\t\t\tif (CPedType::GetAvoid(m_nPedType) & CPedType::GetFlag(nearestPed->m_nPedType)) {\n\n\t\t\t\t\t// Further codes checks whether the distance between us and ped will be equal or below 1.0, if we walk up to him by 1.25 meters.\n\t\t\t\t\t// If so, we want to avoid it, so we turn our body 45 degree and look to somewhere else.\n\n\t\t\t\t\t// Game converts from radians to degress and back again here, doesn't make much sense\n\t\t\t\t\tCVector2D forward(-Sin(m_fRotationCur), Cos(m_fRotationCur));\n\t\t\t\t\tforward.Normalise();\t// this is kinda pointless\n\n\t\t\t\t\t// Move forward 1.25 meters\n\t\t\t\t\tCVector2D testPosition = CVector2D(GetPosition()) + forward*1.25f;\n\n\t\t\t\t\t// Get distance to ped we want to avoid\n\t\t\t\t\tCVector2D distToPed = CVector2D(nearestPed->GetPosition()) - testPosition;\n\n\t\t\t\t\tif (distToPed.Magnitude() <= 1.0f && OurPedCanSeeThisOne((CEntity*)nearestPed)) {\n\t\t\t\t\t\tm_nPedStateTimer = CTimer::GetTimeInMilliseconds()\n\t\t\t\t\t\t\t+ 500 + (m_randomSeed + 3 * CTimer::GetFrameCounter())\n\t\t\t\t\t\t\t% 1000 / 5;\n\n\t\t\t\t\t\tm_fRotationDest += DEGTORAD(45.0f);\n\t\t\t\t\t\tif (!bIsLooking) {\n\t\t\t\t\t\t\tSetLookFlag(nearestPed, false);\n\t\t\t\t\t\t\tSetLookTimer(CGeneral::GetRandomNumberInRange(500, 800));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nCVector*\nCPed::SeekFollowingPath(void)\n{\n\tstatic CVector vecNextPathNode;\n\n\tif (m_nCurPathNodeId >= m_nNumPathNodes || m_nNumPathNodes == 0)\n\t\treturn nil;\n\n\tvecNextPathNode = m_pathNodesToGo[m_nCurPathNodeId]->GetPosition();\n\n\tif ((vecNextPathNode - GetPosition()).Magnitude2D() < m_distanceToCountSeekDone) {\n\t\tm_nCurPathNodeId++;\n\t\tif (m_nCurPathNodeId < m_nNumPathNodes)\n\t\t\tm_pCurPathNode = m_pathNodesToGo[m_nCurPathNodeId];\n\t}\n\tif (m_nCurPathNodeId == m_nNumPathNodes)\n\t\treturn nil;\n\telse\n\t\treturn &vecNextPathNode;\n}\n\nbool\nCPed::SetFollowPath(CVector dest, float radius, eMoveState state, CEntity* walkAroundEnt, CEntity* targetEnt, int time)\n{\n\tif (m_nPedState == PED_FOLLOW_PATH) {\n\t\tbool stopFollow = false;\n\t\tif (walkAroundEnt && walkAroundEnt != m_followPathWalkAroundEnt || !walkAroundEnt && m_followPathWalkAroundEnt\n\t\t\t|| targetEnt && targetEnt != m_followPathTargetEnt || !targetEnt && m_followPathTargetEnt) {\n\t\t\tstopFollow = true;\n\n\t\t} else if (targetEnt) {\n\t\t\tif ((targetEnt->GetPosition() - m_followPathDestPos).MagnitudeSqr() > 1.f)\n\t\t\t\tstopFollow = true;\n\n\t\t} else if (!walkAroundEnt && !targetEnt) {\n\t\t\tif ((dest - m_followPathDestPos).MagnitudeSqr() > 1.f)\n\t\t\t\tstopFollow = true;\n\t\t}\n\n\t\tif (!stopFollow)\n\t\t\treturn false;\n\t}\n\tm_pathNodeTimer = CTimer::GetTimeInMilliseconds() + time;\n\tm_followPathWalkAroundEnt = walkAroundEnt;\n\tm_followPathTargetEnt = targetEnt;\n\tm_distanceToCountSeekDone = 0.5f;\n\n\tbool weHaveTargetPed = targetEnt && targetEnt->IsPed();\n\tbool useDestVec = !weHaveTargetPed;\n\n\tif (useDestVec)\n\t\tm_followPathDestPos = dest;\n\telse\n\t\tm_followPathDestPos = targetEnt->GetPosition();\n\n\tif (targetEnt && m_nPedState == PED_SEEK_POS) {\n\t\tm_followPathDestPos = m_vecSeekPos;\n\t}\n\n\tm_followPathAbortDist = radius > 0.f ? radius : 20.f;\n\n\tbool useGivenPedMove = state == PEDMOVE_RUN || state == PEDMOVE_WALK;\n\tif (useGivenPedMove)\n\t\tm_followPathMoveState = state;\n\telse\n\t\tm_followPathMoveState = PEDMOVE_WALK;\n\n\tif (m_followPathWalkAroundEnt)\n\t\treturn SetFollowPathDynamic();\n\telse\n\t\treturn SetFollowPathStatic();\n}\n\nbool\nCPed::SetFollowPathStatic(void)\n{\n\tClearFollowPath();\n\tif (sq(m_followPathAbortDist) > (GetPosition() - m_followPathDestPos).MagnitudeSqr()\n\t\t&& CWorld::IsWanderPathClear(GetPosition(), m_followPathDestPos, 0.5f, 4)) {\n\n\t\tRestorePreviousState();\n\t\tif (m_objective == OBJECTIVE_NONE) {\n\t\t\tif (m_followPathMoveState == PEDMOVE_RUN)\n\t\t\t\tSetObjective(OBJECTIVE_RUN_TO_AREA, m_followPathDestPos);\n\t\t\telse\n\t\t\t\tSetObjective(OBJECTIVE_GOTO_AREA_ON_FOOT, m_followPathDestPos);\t\t\t\n\t\t}\n\t\tSetPedState(PED_NONE);\n\t} else {\n\t\tThePaths.DoPathSearch(PATH_PED, GetPosition(), -1, m_followPathDestPos, m_pathNodesToGo, &m_nNumPathNodes,\n\t\t\tARRAY_SIZE(m_pathNodesToGo), nil, nil, 999999.9f, -1);\n\n\t\tif (m_nNumPathNodes != 0) {\n\t\t\tif (m_nNumPathNodes > 0 && m_pathNodesToGo[0] != m_pCurPathNode) {\n\t\t\t\tfor (int i = 0; i < ARRAY_SIZE(m_pathNodesToGo) - 1; i++) {\n\t\t\t\t\tm_pathNodesToGo[i] = m_pathNodesToGo[i+1];\n\t\t\t\t}\n\t\t\t\t--m_nNumPathNodes;\n\t\t\t}\n\t\t\tfor (int i = 0; i < m_nNumPathNodes; ++i) {\n\t\t\t\tCVector nodePos = m_pathNodesToGo[i]->GetPosition();\n\t\t\t\tif (sq(m_followPathAbortDist) > (nodePos - m_followPathDestPos).MagnitudeSqr()\n\t\t\t\t\t&& CWorld::IsWanderPathClear(nodePos, m_followPathDestPos, 0.5f, 4)) {\n\n\t\t\t\t\tm_nNumPathNodes = i + 1;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tm_nCurPathNodeId = 0;\n\t\t\tif (m_pCurPathNode) {\n\t\t\t\tfor (int j = 0; j < m_nNumPathNodes; ++j) {\n\t\t\t\t\tif (m_pathNodesToGo[j] == m_pCurPathNode) {\n\t\t\t\t\t\tm_nCurPathNodeId = j;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tm_pCurPathNode = m_pathNodesToGo[m_nCurPathNodeId];\n\t\t\tPedState oldLastState = m_nLastPedState;\n\t\t\tm_nLastPedState = PED_NONE;\n\t\t\tSetStoredState();\n\t\t\tif (m_nLastPedState == PED_NONE)\n\t\t\t\tm_nLastPedState = oldLastState;\n\n\t\t\tSetPedState(PED_FOLLOW_PATH);\n\t\t\tSetMoveState(m_followPathMoveState);\n\t\t} else {\n\t\t\tRestorePreviousState();\n\t\t\tif (m_objective == OBJECTIVE_NONE) {\n\t\t\t\tif (m_followPathMoveState == PEDMOVE_RUN)\n\t\t\t\t\tSetObjective(OBJECTIVE_RUN_TO_AREA, m_followPathDestPos);\n\t\t\t\telse\n\t\t\t\t\tSetObjective(OBJECTIVE_GOTO_AREA_ON_FOOT, m_followPathDestPos);\n\t\t\t}\n\t\t\tSetPedState(PED_NONE);\n\t\t}\n\t}\n\treturn true;\n}\n\nbool\nCPed::SetFollowPathDynamic(void)\n{\n\tCVector colBoxMin = m_followPathWalkAroundEnt->GetColModel()->boundingBox.min + CVector(-0.35f, -0.35f, 0.f);\n\tCVector colBoxMax = m_followPathWalkAroundEnt->GetColModel()->boundingBox.max + CVector(0.35f, 0.35f, 0.f);\n\n\tCVector colCornerOffsets[4]; // BL, BR, TR, TL\n\tcolCornerOffsets[0] = CVector(colBoxMin.x, colBoxMin.y, 0.f);\n\tcolCornerOffsets[1] = CVector(colBoxMax.x, colBoxMin.y, 0.f);\n\tcolCornerOffsets[2] = CVector(colBoxMax.x, colBoxMax.y, 0.f);\n\tcolCornerOffsets[3] = CVector(colBoxMin.x, colBoxMax.y, 0.f);\n\n\tif (m_followPathWalkAroundEnt->IsVehicle() && ((CVehicle*)m_followPathWalkAroundEnt)->IsUpsideDown()) {\n\t\tCVector old0 = colCornerOffsets[0];\n\t\tcolCornerOffsets[0] = colCornerOffsets[1];\n\t\tcolCornerOffsets[1] = old0;\n\t\tCVector old2 = colCornerOffsets[2];\n\t\tcolCornerOffsets[2] = colCornerOffsets[3];\n\t\tcolCornerOffsets[3] = old2;\n\t}\n\n\tCVector colCornerPos[4]; // global. again BL, BR, TR, TL\n\tfloat dotProdCorrection[4];\n\tCVector colBoxPlaneNormal[4];\n\n\tfor (int i=0; i<4; i++) {\n\t\tcolCornerPos[i] = m_followPathWalkAroundEnt->GetMatrix() * colCornerOffsets[i];\n\t\tcolCornerPos[i].z = GetPosition().z;\n\t}\n\n\tCVector prevColCorner = colCornerPos[3];  // top left\n\tCVector *curCornerPos;\n\tCVector fwdToNextCorner;\n\n\tfor (int i=0; i<4; i++) {\n\t\tcurCornerPos = &colCornerPos[i];\n\t\tfwdToNextCorner = *curCornerPos - prevColCorner;\n\t\tfwdToNextCorner.Normalise();\n\t\tcolBoxPlaneNormal[i] = CrossProduct(fwdToNextCorner, CVector(0.f, 0.f, 1.f));\n\t\tdotProdCorrection[i] = -DotProduct(prevColCorner, colBoxPlaneNormal[i]); // yes, dp with global coord, as if in distance to plane calculation\n\t\tprevColCorner = *curCornerPos;\n\t}\n\n\tbool weReGoingGreat = false;\n\tCVector startVecCandidate = GetPosition();\n\tCVector targetVecCandidate = m_followPathDestPos;\n\tCVector dirToGo = targetVecCandidate - startVecCandidate;\n\tdirToGo.Normalise();\n\tCVector ourPos = startVecCandidate;\n\t\n\tfor (int i=0; i<4; i++) {\n\t\tCVector curPlaneNormal = colBoxPlaneNormal[i];\n\t\tfloat minusGlobalCornerPos = dotProdCorrection[i];\n\t\tfloat startVecDistToPlane = DotProduct(curPlaneNormal, startVecCandidate) + minusGlobalCornerPos;\n\n#define FRONT_OF_PLANE 1\n#define ON_THE_PLANE 0\n#define BEHIND_THE_PLANE -1\n\n\t\tint8 startVecStatus;\n\t\tint8 targetVecStatus;\n\n\t\tif (startVecDistToPlane > 0.1f)\n\t\t\tstartVecStatus = FRONT_OF_PLANE;\n\t\telse if (startVecDistToPlane < -0.1f)\n\t\t\tstartVecStatus = BEHIND_THE_PLANE;\n\t\telse\n\t\t\tstartVecStatus = ON_THE_PLANE;\n\n\t\tfloat targetVecDistToPlane = DotProduct(curPlaneNormal, targetVecCandidate) + minusGlobalCornerPos;\n\t\tif (targetVecDistToPlane > 0.1f)\n\t\t\ttargetVecStatus = FRONT_OF_PLANE;\n\t\telse if (targetVecDistToPlane < -0.1f)\n\t\t\ttargetVecStatus = BEHIND_THE_PLANE;\n\t\telse\n\t\t\ttargetVecStatus = ON_THE_PLANE;\n\n\n\t\tif (startVecStatus == BEHIND_THE_PLANE || targetVecStatus == BEHIND_THE_PLANE) {\n\t\t\tif (startVecStatus == BEHIND_THE_PLANE && targetVecStatus == FRONT_OF_PLANE) {\n\t\t\t\ttargetVecCandidate = -(DotProduct(ourPos, curPlaneNormal) + minusGlobalCornerPos) / DotProduct(dirToGo, curPlaneNormal) * dirToGo + ourPos;\n\n\t\t\t} else if (startVecStatus == FRONT_OF_PLANE && targetVecStatus == BEHIND_THE_PLANE) {\n\t\t\t\tstartVecCandidate = -(DotProduct(ourPos, curPlaneNormal) + minusGlobalCornerPos) / DotProduct(dirToGo, curPlaneNormal) * dirToGo + ourPos;\n\t\t\t}\n\t\t} else {\n\t\t\tweReGoingGreat = true;\n\t\t\tif (startVecStatus == ON_THE_PLANE)\n\t\t\t\tstartVecCandidate += (0.1f - startVecDistToPlane) * curPlaneNormal;\n\n\t\t\tif (targetVecStatus == ON_THE_PLANE)\n\t\t\t\ttargetVecCandidate += (0.1f - targetVecDistToPlane) * curPlaneNormal;\n\t\t}\n#undef FRONT_OF_PLANE\n#undef ON_THE_PLANE\n#undef BEHIND_THE_PLANE\n\t}\n\n\tif (!weReGoingGreat) {\n\t\tCVector avgOfColPoints = (colCornerPos[0] + colCornerPos[1] + colCornerPos[2] + colCornerPos[3]) / 4.f;\n\t\tfloat radius = 0.0f;\n\n\t\t// Find radius of col box of the entity we follow\n\t\tfor (int i=0; i<4; i++) {\n\t\t\tfloat cornerDist = (colCornerPos[i] - avgOfColPoints).MagnitudeSqr();\n\n\t\t\tif (cornerDist > radius)\n\t\t\t\tradius = cornerDist;\n\t\t}\n\t\tCColSphere followedEntSphere;\n\t\tfollowedEntSphere.Set(Sqrt(radius) * 1.1f, avgOfColPoints, 0, 0);\n\t\tCVector distToDest = m_followPathDestPos - GetPosition();\n\t\tdistToDest.z = 0.f;\n\t\t\n\t\tif (distToDest.Magnitude() == 0.0f)\n\t\t\treturn false;\n\n\t\tdistToDest.Normalise();\n\n\t\t// Entity we follow doesn't go toward destination anymore, abort the following.\n\t\tif (!followedEntSphere.IntersectRay(GetPosition(), distToDest, startVecCandidate, targetVecCandidate)) {\n\t\t\tm_pathNodeTimer = 0;\n\t\t\tif (m_nPedState == PED_FOLLOW_PATH)\n\t\t\t\tRestorePreviousState();\n\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tint lastPlaneBehindUs = -1;\n\tint lastPlaneInFrontOfUs = -1;\n\tCVector oldstartVecCandidate = startVecCandidate;\n\tCVector oldDirToGo = targetVecCandidate - startVecCandidate;\n\toldDirToGo.Normalise();\n\t\t\n\n\t// At least one plane should be between target and us.\n\tfor (int i=0; i<4; i++) {\n\t\tCVector curPlaneNormal = colBoxPlaneNormal[i];\n\t\tfloat minusGlobalCornerPos = dotProdCorrection[i];\n\t\tfloat startVecDistToPlane = DotProduct(curPlaneNormal, startVecCandidate) + minusGlobalCornerPos;\n\t\tfloat targetVecDistToPlane = DotProduct(curPlaneNormal, targetVecCandidate) + minusGlobalCornerPos;\n\n\t\tif (startVecDistToPlane > 0.0f && targetVecDistToPlane < 0.0f) {\n\t\t\tlastPlaneInFrontOfUs = i;\n\t\t\tstartVecCandidate = -(DotProduct(oldstartVecCandidate, curPlaneNormal) + minusGlobalCornerPos) / DotProduct(oldDirToGo, curPlaneNormal) * oldDirToGo + oldstartVecCandidate;\n\n\t\t} else if (startVecDistToPlane < 0.0f && targetVecDistToPlane > 0.0f) {\n\t\t\tlastPlaneBehindUs = i;\n\t\t\ttargetVecCandidate = -(DotProduct(oldstartVecCandidate, curPlaneNormal) + minusGlobalCornerPos) / DotProduct(oldDirToGo, curPlaneNormal) * oldDirToGo + oldstartVecCandidate;\n\t\t}\n\t}\n\n\tCVector destsVariant1[5];\n\tCVector destsVariant2[5];\n\n\t// If not, followed entity diverged from route and we should abort the following.\n\tif (lastPlaneBehindUs >= 0 && lastPlaneInFrontOfUs >= 0) {\n\n\t\tint planeInFrontCircular = (lastPlaneInFrontOfUs + 4) % -4;\n\t\tint planeInFrontCircularMinusOne = (lastPlaneInFrontOfUs + 3) % -4;\n\t\tint planeInBehindCircular = (lastPlaneBehindUs + 4) % -4;\n\t\tint planeInBehindCircularMinusOne = (lastPlaneBehindUs + 3) % -4;\n\n\t\tdestsVariant1[0] = GetPosition();\n\t\tdestsVariant1[1] = colCornerPos[planeInFrontCircularMinusOne];\n\n\t\tint destsVar1LastNode = 2;\n\t\tfor(; planeInFrontCircularMinusOne != planeInBehindCircular; destsVar1LastNode++) {\n\t\t\tplaneInFrontCircularMinusOne = (planeInFrontCircularMinusOne + 3) % -4;\n\t\t\tdestsVariant1[destsVar1LastNode] = colCornerPos[planeInFrontCircularMinusOne];\n\t\t}\n\t\tdestsVariant1[destsVar1LastNode] = m_followPathDestPos;\n\n\t\tdestsVariant2[0] = GetPosition();\n\t\tdestsVariant2[1] = colCornerPos[planeInFrontCircular];\n\n\t\tint destsVar2LastNode = 2;\n\t\tfor (; planeInFrontCircular != planeInBehindCircularMinusOne; destsVar2LastNode++) {\n\t\t\tplaneInFrontCircular = (planeInFrontCircular + 5) % -4;\n\t\t\tdestsVariant2[destsVar2LastNode] = colCornerPos[planeInFrontCircular];\n\t\t}\n\t\tdestsVariant2[destsVar2LastNode] = m_followPathDestPos;\n\t\tCEntity *foundEnt1 = nil;\n\t\tint dests1isOk = true;\n\t\tint nodeToStopDestsVar1 = destsVar1LastNode + 1;\n\t\tCVector avgOfColPoints2 = (colCornerPos[0] + colCornerPos[1] + colCornerPos[2] + colCornerPos[3]) / 4.f;\n\n\t\tCVector prevDestVar1 = destsVariant1[0];\n\t\t\t\n\t\tfor (int i = 1; i < destsVar1LastNode + 1; i++) {\n\t\t\tCVector *curDestVar1 = &destsVariant1[i];\n\n\t\t\tCVector routeNormalHalf = *curDestVar1 - prevDestVar1;\n\t\t\trouteNormalHalf.z = 0.f;\n\t\t\trouteNormalHalf.Normalise();\n\t\t\trouteNormalHalf *= 0.5f;\n\n\t\t\tfloat oldX = -routeNormalHalf.x;\n\t\t\trouteNormalHalf.z = 0.0f;\n\t\t\trouteNormalHalf.x = routeNormalHalf.y;\n\t\t\trouteNormalHalf.y = oldX;\n\n\t\t\tif (DotProduct(*curDestVar1 - avgOfColPoints2, routeNormalHalf) < 0.0f)\n\t\t\t\trouteNormalHalf *= -1.f;\n\n\t\t\tCColPoint foundCol;\n\t\t\tbool foundObstacle = CWorld::ProcessLineOfSight(prevDestVar1, *curDestVar1, foundCol, foundEnt1,\n\t\t\t\ttrue, true, true, true, false, false, false, false);\n\n\t\t\tif (!foundObstacle)\n\t\t\t\tfoundObstacle = CWorld::ProcessLineOfSight(prevDestVar1 + routeNormalHalf, *curDestVar1 + routeNormalHalf, foundCol, foundEnt1, true, true, true, true, false, false, false, false);\n\n\t\t\tif (foundObstacle) {\n\t\t\t\tif (foundEnt1 == m_followPathWalkAroundEnt || foundEnt1 == this || foundEnt1 == m_pSeekTarget) {\n\t\t\t\t\tfoundEnt1 = nil;\n\n\t\t\t\t} else {\n\t\t\t\t\tif (!foundEnt1->IsPed()) {\n\t\t\t\t\t\tdests1isOk = false;\n\t\t\t\t\t\tnodeToStopDestsVar1 = i;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tif (((CPed*)foundEnt1)->m_nPedState == PED_IDLE) {\n\t\t\t\t\t\tdests1isOk = false;\n\t\t\t\t\t\tnodeToStopDestsVar1 = i;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tif (DotProduct(*curDestVar1 - prevDestVar1, foundEnt1->GetForward()) < 0.f) {\n\t\t\t\t\t\tdests1isOk = false;\n\t\t\t\t\t\tnodeToStopDestsVar1 = i;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tif (((CPed*)foundEnt1)->m_pedInObjective == this) {\n\t\t\t\t\t\tdests1isOk = false;\n\t\t\t\t\t\tnodeToStopDestsVar1 = i;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tprevDestVar1 = *curDestVar1;\n\t\t}\n\t\tCEntity *foundEnt2 = nil;\n\t\tint dests2isOk = true;\n\t\tint nodeToStopDestsVar2 = destsVar2LastNode + 1;\n\n\t\tCVector prevDestVar2 = destsVariant2[0];\n\n\t\tfor (int i = 1; i < destsVar2LastNode + 1; i++) {\n\t\t\tCVector *curDestVar2 = &destsVariant2[i];\n\n\t\t\tCVector routeNormalHalf = *curDestVar2 - prevDestVar2;\n\t\t\trouteNormalHalf.z = 0.f;\n\t\t\trouteNormalHalf.Normalise();\n\t\t\trouteNormalHalf *= 0.5f;\n\n\t\t\tfloat oldX = -routeNormalHalf.x;\n\t\t\trouteNormalHalf.z = 0.0f;\n\t\t\trouteNormalHalf.x = routeNormalHalf.y;\n\t\t\trouteNormalHalf.y = oldX;\n\n\t\t\tif (DotProduct(*curDestVar2 - avgOfColPoints2, routeNormalHalf) < 0.0f)\n\t\t\t\trouteNormalHalf *= -1.f;\n\n\t\t\tCColPoint foundCol;\n\t\t\tbool foundObstacle = CWorld::ProcessLineOfSight(prevDestVar2, *curDestVar2, foundCol, foundEnt2,\n\t\t\t\ttrue, true, true, true, false, false, false, false);\n\n\t\t\tif (!foundObstacle)\n\t\t\t\tfoundObstacle = CWorld::ProcessLineOfSight(prevDestVar2 + routeNormalHalf, *curDestVar2 + routeNormalHalf, foundCol, foundEnt2, true, true, true, true, false, false, false, false);\n\n\t\t\t\tif (foundObstacle) {\n\t\t\t\t\tif (foundEnt2 == m_followPathWalkAroundEnt || foundEnt2 == this || foundEnt2 == m_pSeekTarget) {\n\t\t\t\t\t\tfoundEnt2 = 0;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (!foundEnt2->IsPed()) {\n\t\t\t\t\t\t\tdests2isOk = false;\n\t\t\t\t\t\t\tnodeToStopDestsVar2 = i;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (((CPed*)foundEnt2)->m_nPedState == PED_IDLE) {\n\t\t\t\t\t\t\tdests2isOk = false;\n\t\t\t\t\t\t\tnodeToStopDestsVar2 = i;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (DotProduct(*curDestVar2 - prevDestVar2, foundEnt2->GetForward()) < 0.f) {\n\t\t\t\t\t\t\tdests2isOk = false;\n\t\t\t\t\t\t\tnodeToStopDestsVar2 = i;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (((CPed*)foundEnt2)->m_pedInObjective == this) {\n\t\t\t\t\t\t\tdests2isOk = false;\n\t\t\t\t\t\t\tnodeToStopDestsVar2 = i;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tprevDestVar2 = *curDestVar2;\n\t\t}\n\n\t\tfloat destTotalLengthVar1 = 0.0f;\n\t\tfor(int i=0; i < destsVar1LastNode; i++){\n\t\t\tdestTotalLengthVar1 += (destsVariant1[i + 1] - destsVariant1[i]).Magnitude();\n\t\t}\n\n\t\tfloat destTotalLengthVar2 = 0.0f;\n\t\tfor (int i = 0; i < destsVar2LastNode; i++) {\n\t\t\tdestTotalLengthVar2 += (destsVariant2[i + 1] - destsVariant2[i]).Magnitude();\n\t\t}\n\n\t\tint destVariantToUse;\n\t\tif (dests1isOk && dests2isOk) {\n\t\t\tif (destTotalLengthVar1 < destTotalLengthVar2)\n\t\t\t\tdestVariantToUse = 1;\n\t\t\telse\n\t\t\t\tdestVariantToUse = 2;\n\n\t\t} else if (dests1isOk) {\n\t\t\tdestVariantToUse = 1;\n\n\t\t} else if (dests2isOk) {\n\t\t\tdestVariantToUse = 2;\n\n\t\t} else if (nodeToStopDestsVar1 == 1 && nodeToStopDestsVar2 > 1) {\n\t\t\tdestVariantToUse = 2;\n\n\t\t} else if (nodeToStopDestsVar1 > 1 && nodeToStopDestsVar2 == 1) {\n\t\t\tdestVariantToUse = 1;\n\n\t\t} else if (foundEnt1 == foundEnt2) {\n\t\t\tif (destTotalLengthVar1 < destTotalLengthVar2)\n\t\t\t\tdestVariantToUse = 1;\n\t\t\telse\n\t\t\t\tdestVariantToUse = 2;\n\n\t\t} else if (foundEnt1->GetColModel()->boundingSphere.radius >= foundEnt2->GetColModel()->boundingSphere.radius) {\n\t\t\tdestVariantToUse = 2;\n\t\t} else {\n\t\t\tdestVariantToUse = 1;\n\t\t}\n\n\t\tif (destVariantToUse == 1) {\n\t\t\tClearFollowPath();\n\t\t\tfor (int i = 1; i < destsVar1LastNode; i++) {\n\t\t\t\tCPathNode* nextNode = &m_pathNodeObjPool[m_nNumPathNodes];\n\t\t\t\tnextNode->SetPosition(destsVariant1[i]);\n\t\t\t\tm_pathNodesToGo[m_nNumPathNodes++] = nextNode;\n\t\t\t}\n\t\t} else if (destVariantToUse == 2) {\n\t\t\tClearFollowPath();\n\t\t\tfor (int i = 1; i < destsVar2LastNode; i++) {\n\t\t\t\tCPathNode *nextNode = &m_pathNodeObjPool[m_nNumPathNodes];\n\t\t\t\tnextNode->SetPosition(destsVariant2[i]);\n\t\t\t\tm_pathNodesToGo[m_nNumPathNodes++] = nextNode;\n\t\t\t}\n\t\t}\n\t\tif (m_nNumPathNodes != 0) {\n\t\t\tPedState oldLastState = m_nLastPedState;\n\t\t\tm_nLastPedState = PED_NONE;\n\t\t\tSetStoredState();\n\t\t\tif (m_nLastPedState == PED_NONE)\n\t\t\t\tm_nLastPedState = oldLastState;\n\n\t\t\tSetPedState(PED_FOLLOW_PATH);\n\t\t\tSetMoveState(m_followPathMoveState);\n\t\t\treturn true;\n\n\t\t} else {\n\t\t\tm_pathNodeTimer = 0;\n\t\t\tif (m_nPedState == PED_FOLLOW_PATH)\n\t\t\t\tRestorePreviousState();\n\n\t\t\treturn false;\n\t\t}\n\t} else {\n\t\tm_pathNodeTimer = 0;\n\t\tif (m_nPedState == PED_FOLLOW_PATH)\n\t\t\tRestorePreviousState();\n\n\t\treturn false;\n\t}\n}\n\nvoid\nCPed::ClearFollowPath()\n{\n\tfor (int i = 0; i < ARRAY_SIZE(m_pathNodesToGo); i++) {\n\t\tm_pathNodesToGo[i] = nil;\n\t}\n\tm_nNumPathNodes = 0;\n\tm_nCurPathNodeId = 0;\n}\n\nvoid\nCPed::FollowPath(void)\n{\n\tm_pCurPathNode = m_pathNodesToGo[m_nCurPathNodeId];\n\tif (m_pathNodeTimer > 0 && CTimer::GetTimeInMilliseconds() > m_pathNodeTimer) {\n\t\tRestorePreviousState();\n\t\tClearFollowPath();\n\t\tm_pathNodeTimer = 0;\n\t} else {\n\t\tif (m_pathNodesToGo[m_nCurPathNodeId]) {\n\t\t\tm_vecSeekPos.x = m_pathNodesToGo[m_nCurPathNodeId]->GetPosition().x;\n\t\t\tm_vecSeekPos.y = m_pathNodesToGo[m_nCurPathNodeId]->GetPosition().y;\n\t\t\tm_vecSeekPos.z = GetPosition().z;\n\n\t\t\tif (Seek()) {\n\t\t\t\tif (m_nCurPathNodeId == m_nNumPathNodes) {\n\t\t\t\t\tRestorePreviousState();\n\t\t\t\t\tClearFollowPath();\n\t\t\t\t\tSetFollowPath(m_followPathDestPos, m_followPathAbortDist, m_followPathMoveState, m_followPathWalkAroundEnt,\n\t\t\t\t\t\tm_followPathTargetEnt, m_pathNodeTimer - CTimer::GetTimeInMilliseconds());\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tRestorePreviousState();\n\t\t\tClearFollowPath();\n\t\t\tm_pathNodeTimer = 0;\n\t\t}\n\t}\n}\n\nvoid\nCPed::SetEvasiveStep(CEntity *reason, uint8 animType)\n{\n\tAnimationId stepAnim;\n\n\tif (m_nPedState == PED_STEP_AWAY || !IsPedInControl() || ((IsPlayer() || !bRespondsToThreats) && animType == 0))\n\t\treturn;\n\n\tfloat angleToFace = CGeneral::GetRadianAngleBetweenPoints(\n\t\treason->GetPosition().x, reason->GetPosition().y,\n\t\tGetPosition().x, GetPosition().y);\n\tangleToFace = CGeneral::LimitRadianAngle(angleToFace);\n\tm_fRotationCur = CGeneral::LimitRadianAngle(m_fRotationCur);\n\tfloat neededTurn = Abs(angleToFace - m_fRotationCur);\n\tbool vehPressedHorn = false;\n\n\tif (neededTurn > PI)\n\t\tneededTurn = TWOPI - neededTurn;\n\n\tCVehicle *veh = (CVehicle*)reason;\n\tif (reason->IsVehicle() && veh->IsCar()) {\n\t\tif (veh->m_nCarHornTimer != 0) {\n\t\t\tvehPressedHorn = true;\n\t\t\tif (!IsPlayer())\n\t\t\t\tanimType = 1;\n\t\t}\n\t}\n\tif (neededTurn <= DEGTORAD(90.0f) || veh->GetModelIndex() == MI_RCBANDIT || vehPressedHorn || animType != 0) {\n\t\tSetLookFlag(veh, true);\n\t\tif ((CGeneral::GetRandomNumber() & 1) && veh->GetModelIndex() != MI_RCBANDIT && animType == 0) {\n\t\t\tstepAnim = ANIM_STD_HAILTAXI;\n\n\t\t} else {\n\t\t\tfloat vehDirection = CGeneral::GetRadianAngleBetweenPoints(\n\t\t\t\tveh->m_vecMoveSpeed.x, veh->m_vecMoveSpeed.y,\n\t\t\t\t0.0f, 0.0f);\n\n\t\t\t// Let's turn our back to the \"reason\"\n\t\t\tangleToFace += PI;\n\n\t\t\tif (angleToFace > PI)\n\t\t\t\tangleToFace -=  TWOPI;\n\n\t\t\t// We don't want to run towards car's direction\n\t\t\tfloat dangerZone = angleToFace - vehDirection;\n\t\t\tdangerZone = CGeneral::LimitRadianAngle(dangerZone);\n\n\t\t\t// So, add or subtract 90deg (jump to left/right) according to that\n\t\t\tif (dangerZone > 0.0f)\n\t\t\t\tangleToFace = vehDirection - HALFPI;\n\t\t\telse\n\t\t\t\tangleToFace = vehDirection + HALFPI;\n\n\t\t\tstepAnim = ANIM_STD_NUM;\n\t\t\tif (animType == 0 || animType == 1)\n\t\t\t\tstepAnim = ANIM_STD_EVADE_STEP;\n\t\t\telse if (animType == 2)\n\t\t\t\tstepAnim = ANIM_STD_HANDSCOWER;\n\t\t}\n\t\tif (!RpAnimBlendClumpGetAssociation(GetClump(), stepAnim)) {\n\t\t\tCAnimBlendAssociation *stepAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, stepAnim, 8.0f);\n\t\t\tstepAssoc->flags &= ~ASSOC_DELETEFADEDOUT;\n\t\t\tstepAssoc->SetFinishCallback(PedEvadeCB, this);\n\n\t\t\tif (animType == 0)\n\t\t\t\tSay(SOUND_PED_EVADE);\n\n\t\t\tm_fRotationCur = CGeneral::LimitRadianAngle(angleToFace);\n\t\t\tClearAimFlag();\n\t\t\tSetStoredState();\n\t\t\tSetPedState(PED_STEP_AWAY);\n\t\t}\n\t}\n}\n\nvoid\nCPed::SetEvasiveDive(CPhysical *reason, uint8 onlyRandomJump)\n{\n\tif (!IsPedInControl() || !bRespondsToThreats)\n\t\treturn;\n\n\tCAnimBlendAssociation *animAssoc;\n\tfloat angleToFace, neededTurn;\n\tbool handsUp = false;\n\n\tangleToFace = m_fRotationCur;\n\tCVehicle *veh = (CVehicle*) reason;\n\tif (reason->IsVehicle() && veh->m_vehType == VEHICLE_TYPE_CAR && veh->m_nCarHornTimer != 0 && !IsPlayer()) {\n\t\tonlyRandomJump = true;\n\t}\n\n\tif (onlyRandomJump) {\n\t\tif (reason) {\n\t\t\t// Simple version of my bug fix below. Doesn't calculate \"danger zone\", selects jump direction randomly.\n\t\t\t// Also doesn't include random hands up, sound etc. Only used on player ped and peds running from gun shots.\n\n\t\t\tfloat vehDirection = CGeneral::GetRadianAngleBetweenPoints(\n\t\t\t\tveh->m_vecMoveSpeed.x, veh->m_vecMoveSpeed.y,\n\t\t\t\t0.0f, 0.0f);\n\t\t\tangleToFace = (CGeneral::GetRandomNumber() & 1) * PI + (-0.5f*PI) + vehDirection;\n\t\t\tangleToFace = CGeneral::LimitRadianAngle(angleToFace);\n\t\t}\n\t} else {\n\t\tif (IsPlayer()) {\n\t\t\t((CPlayerPed*)this)->m_nEvadeAmount = 5;\n\t\t\t((CPlayerPed*)this)->m_pEvadingFrom = reason;\n\t\t\treason->RegisterReference((CEntity**) &((CPlayerPed*)this)->m_pEvadingFrom);\n\t\t\treturn;\n\t\t}\n\n\t\tangleToFace = CGeneral::GetRadianAngleBetweenPoints(\n\t\t\treason->GetPosition().x, reason->GetPosition().y,\n\t\t\tGetPosition().x, GetPosition().y);\n\t\tangleToFace = CGeneral::LimitRadianAngle(angleToFace);\n\t\tm_fRotationCur = CGeneral::LimitRadianAngle(m_fRotationCur);\n\n\t\t// FIX: Peds no more select dive direction randomly. Taken from SetEvasiveStep, last if statement inverted\n#ifdef FIX_BUGS\n\t\tfloat vehDirection = CGeneral::GetRadianAngleBetweenPoints(\n\t\t\tveh->m_vecMoveSpeed.x, veh->m_vecMoveSpeed.y,\n\t\t\t0.0f, 0.0f);\n\n\t\t// Let's turn our back to the \"reason\"\n\t\tangleToFace += PI;\n\n\t\tif (angleToFace > PI)\n\t\t\tangleToFace -= 2 * PI;\n\n\t\t// We don't want to dive towards car's direction\n\t\tfloat dangerZone = angleToFace - vehDirection;\n\t\tdangerZone = CGeneral::LimitRadianAngle(dangerZone);\n\n\t\t// So, add or subtract 90deg (jump to left/right) according to that\n\t\tif (dangerZone > 0.0f)\n\t\t\tangleToFace = 0.5f * PI + vehDirection;\n\t\telse\n\t\t\tangleToFace = vehDirection - 0.5f * PI;\n#endif\n\n\t\tneededTurn = Abs(angleToFace - m_fRotationCur);\n\n\t\tif (neededTurn > PI)\n\t\t\tneededTurn = 2 * PI - neededTurn;\n\n\t\tif (neededTurn <= 0.5f*PI) {\n\t\t\tif (CGeneral::GetRandomNumber() & 1)\n\t\t\t\thandsUp = true;\n\t\t} else {\n\t\t\tif (CGeneral::GetRandomNumber() & 7)\n\t\t\t\treturn;\n\t\t}\n\n\t\t// VC's primitve solution to dive direction problem, see above for better one. This part doesn't exist on III at all\n#ifndef FIX_BUGS\n\t\tangleToFace += HALFPI;\n\t\tif (CGeneral::GetRandomNumber() & 1)\n\t\t\tangleToFace -= PI;\n#endif\n\t\tSay(SOUND_PED_EVADE);\n\t}\n\n\tif (handsUp || !IsPlayer() && m_pedStats->m_flags & STAT_NO_DIVE) {\n\t\tm_fRotationCur = angleToFace;\n\t\tClearLookFlag();\n\t\tClearAimFlag();\n\t\tSetLookFlag(reason, true);\n\t\tanimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_HANDSUP);\n\t\tif (animAssoc)\n\t\t\treturn;\n\n\t\tanimAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_HANDSUP, 8.0f);\n\t\tanimAssoc->flags &= ~ASSOC_DELETEFADEDOUT;\n\t\tanimAssoc->SetFinishCallback(PedEvadeCB, this);\n\t\tSetStoredState();\n\t\tSetPedState(PED_STEP_AWAY);\n\t} else {\n\t\tm_fRotationCur = angleToFace;\n\t\tClearLookFlag();\n\t\tClearAimFlag();\n\t\tSetStoredState();\n\t\tSetPedState(PED_DIVE_AWAY);\n\t\tanimAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_EVADE_DIVE, 8.0f);\n\t\tanimAssoc->SetFinishCallback(PedEvadeCB, this);\n\t}\n\n\tif (reason->IsVehicle() && m_nPedType == PEDTYPE_COP) {\n\t\tif (veh->pDriver && veh->pDriver->IsPlayer()) {\n\t\t\tCWanted *wanted = FindPlayerPed()->m_pWanted;\n\t\t\twanted->RegisterCrime_Immediately(CRIME_RECKLESS_DRIVING, GetPosition(), (uintptr)this, false);\n\t\t\twanted->RegisterCrime_Immediately(CRIME_SPEEDING, GetPosition(), (uintptr)this, false);\n\t\t}\n\t}\n}\n\nvoid\nCPed::PedEvadeCB(CAnimBlendAssociation* animAssoc, void* arg)\n{\n\tCPed* ped = (CPed*)arg;\n\n\tif (!animAssoc) {\n\t\tped->ClearLookFlag();\n\t\tif (ped->m_nPedState == PED_DIVE_AWAY || ped->m_nPedState == PED_STEP_AWAY)\n\t\t\tped->RestorePreviousState();\n\n\t} else if (animAssoc->animId == ANIM_STD_EVADE_DIVE) {\n\t\tped->bUpdateAnimHeading = true;\n\t\tped->ClearLookFlag();\n\t\tif (ped->m_nPedState == PED_DIVE_AWAY) {\n\t\t\tped->m_getUpTimer = CTimer::GetTimeInMilliseconds() + 1;\n\t\t\tped->SetPedState(PED_FALL);\n\t\t}\n\t\tanimAssoc->flags &= ~ASSOC_FADEOUTWHENDONE;\n\t\tanimAssoc->flags |= ASSOC_DELETEFADEDOUT;\n\n\t} else if (animAssoc->flags & ASSOC_FADEOUTWHENDONE) {\n\t\tped->ClearLookFlag();\n\t\tif (ped->m_nPedState == PED_DIVE_AWAY || ped->m_nPedState == PED_STEP_AWAY)\n\t\t\tped->RestorePreviousState();\n\n\t} else if (ped->m_nPedState != PED_ARRESTED) {\n\t\tanimAssoc->flags |= ASSOC_DELETEFADEDOUT;\n\t\tif (animAssoc->blendDelta >= 0.0f)\n\t\t\tanimAssoc->blendDelta = -4.0f;\n\n\t\tped->ClearLookFlag();\n\t\tif (ped->m_nPedState == PED_DIVE_AWAY || ped->m_nPedState == PED_STEP_AWAY) {\n\t\t\tped->RestorePreviousState();\n\t\t}\n\t}\n}\n\nvoid\nCPed::SetDie(AnimationId animId, float delta, float speed)\n{\n\tif (m_attractor)\n\t\tGetPedAttractorManager()->DeRegisterPed(this, m_attractor);\n\tCPlayerPed *player = FindPlayerPed();\n\tif (player == this) {\n\t\tif (!player->m_bCanBeDamaged)\n\t\t\treturn;\n\t}\n\n\tm_threatEntity = nil;\n\tif (DyingOrDead())\n\t\treturn;\n\n\tCAnimBlendAssociation *dieAssoc = nil;\n\tif (m_nPedState == PED_FALL || m_nPedState == PED_GETUP)\n\t\tdelta *=  0.5f;\n\n\tSetStoredState();\n\tClearAll();\n\tm_fHealth = 0.0f;\n\tif (m_nPedState == PED_DRIVING) {\n\t\tif (!IsPlayer() && (!m_pMyVehicle || !m_pMyVehicle->IsBike()))\n\t\t\tFlagToDestroyWhenNextProcessed();\n\t} else if (bInVehicle) {\n\t\tif (m_pVehicleAnim)\n\t\t\tm_pVehicleAnim->blendDelta = -1000.0f;\n\t} else if (EnteringCar()) {\n\t\tQuitEnteringCar();\n\t}\n\n\tSetPedState(PED_DIE);\n\tif (animId == ANIM_STD_NUM) {\n\t\tbIsPedDieAnimPlaying = false;\n\t} else {\n\t\tdieAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, animId, delta);\n\t\tif (speed > 0.0f)\n\t\t\tdieAssoc->speed = speed;\n\n\t\tdieAssoc->flags &= ~ASSOC_FADEOUTWHENDONE;\n\t\tif (dieAssoc->IsRunning()) {\n\t\t\tdieAssoc->SetFinishCallback(FinishDieAnimCB, this);\n\t\t\tbIsPedDieAnimPlaying = true;\n\t\t}\n\t}\n\n\tSay(SOUND_PED_DEATH);\n\tif (m_nLastPedState == PED_ENTER_CAR || m_nLastPedState == PED_CARJACK)\n\t\tQuitEnteringCar();\n\n\tif (!bInVehicle)\n\t\tStopNonPartialAnims();\n\n\tm_bloodyFootprintCountOrDeathTime = CTimer::GetTimeInMilliseconds();\n\tif (!CGame::nastyGame && animId == ANIM_STD_HIT_FLOOR) {\n\t\tif (dieAssoc) {\n\t\t\tdieAssoc->SetCurrentTime(dieAssoc->hierarchy->totalLength - 0.01f);\n\t\t\tdieAssoc->SetRun();\n\t\t}\n\t}\n}\n\nvoid\nCPed::FinishDieAnimCB(CAnimBlendAssociation *animAssoc, void *arg)\n{\n\tCPed *ped = (CPed*)arg;\n\n\tif (ped->bIsPedDieAnimPlaying)\n\t\tped->bIsPedDieAnimPlaying = false;\n}\n\nvoid\nCPed::SetDead(void)\n{\n\tif (!RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_DROWN))\n\t\tbUsesCollision = false;\n\n\tm_fHealth = 0.0f;\n\tif (m_nPedState == PED_DRIVING)\n\t\tbIsVisible = false;\n\n\tSetPedState(PED_DEAD);\n\tm_pVehicleAnim = nil;\n\tm_pCollidingEntity = nil;\n\n\tCWeaponInfo *weapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);\n\tRemoveWeaponModel(weapon->m_nModelId);\n\n\tm_currentWeapon = WEAPONTYPE_UNARMED;\n\tCEventList::RegisterEvent(EVENT_INJURED_PED, EVENT_ENTITY_PED, this, nil, 250);\n\tif (this != FindPlayerPed()) {\n\t\tRemoveWeaponAnims(0, -1000.0f);\n\t\tCreateDeadPedWeaponPickups();\n\t\tCreateDeadPedMoney();\n\t}\n\n\tm_bloodyFootprintCountOrDeathTime = CTimer::GetTimeInMilliseconds();\n\tm_deadBleeding = false;\n\tbDoBloodyFootprints = false;\n\tbVehExitWillBeInstant = false;\n\tCEventList::RegisterEvent(EVENT_DEAD_PED, EVENT_ENTITY_PED, this, nil, 1000);\n}\n\nvoid\nCPed::Die(void)\n{\n\t// UNUSED: This is a perfectly empty function.\n}\n\nvoid\nCPed::SetChat(CEntity *chatWith, uint32 time)\n{\n\tif (m_nPedState != PED_CHAT) {\n\t\tm_nLastPedState = PED_NONE;\n\t\tSetStoredState();\n\t}\n\n\tSetPedState(PED_CHAT);\n\tSetMoveState(PEDMOVE_STILL);\n\tm_lookTimer = 0;\n\tSetLookFlag(chatWith, true);\n\tm_chatTimer = CTimer::GetTimeInMilliseconds() + time;\n\tm_lookTimer = CTimer::GetTimeInMilliseconds() + 3000;\n}\n\nvoid\nCPed::Chat(void)\n{\n\t// We're already looking to our partner\n\tif (bIsLooking && TurnBody())\n\t\tClearLookFlag();\n\n\tif (!m_pLookTarget || !m_pLookTarget->IsPed()) {\n\t\tClearChat();\n\t\treturn;\n\t}\n\n\tCPed *partner = (CPed*) m_pLookTarget;\n\n\tif (partner->m_nPedState != PED_CHAT) {\n\t\tClearChat();\n\t\tm_chatTimer = CTimer::GetTimeInMilliseconds() + 30000;\n\t\tif (partner->m_pedInObjective) {\n\t\t\tif (partner->m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT ||\n\t\t\t\tpartner->m_objective == OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE)\n\t\t\t\tReactToAttack(partner->m_pedInObjective);\n\t\t}\n\t\treturn;\n\t}\n\tif (bIsTalking) {\n\t\tif (CGeneral::GetRandomNumber() < 512) {\n\t\t\tCAnimBlendAssociation *chatAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_CHAT);\n\t\t\tif (chatAssoc) {\n\t\t\t\tchatAssoc->blendDelta = -4.0f;\n\t\t\t\tchatAssoc->flags |= ASSOC_DELETEFADEDOUT;\n\t\t\t}\n\t\t\tbIsTalking = false;\n\t\t} else\n\t\t\tSay(SOUND_PED_CHAT);\n\n\t} else {\n\n\t\tif (CGeneral::GetRandomNumber() < 20 && !RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_IDLE)) {\n\t\t\tCAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_XPRESS_SCRATCH, 4.0f);\n\t\t}\n\t\tif (!bIsTalking && !RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_IDLE)) {\n\t\t\tCAnimBlendAssociation *chatAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_CHAT, 4.0f);\n\t\t\tfloat chatTime = CGeneral::GetRandomNumberInRange(0.0f, 3.0f);\n\t\t\tchatAssoc->SetCurrentTime(chatTime);\n\n\t\t\tbIsTalking = true;\n\t\t\tSay(SOUND_PED_CHAT);\n\t\t}\n\t}\n\tif (m_chatTimer && CTimer::GetTimeInMilliseconds() > m_chatTimer) {\n\t\tClearChat();\n\t\tm_chatTimer = CTimer::GetTimeInMilliseconds() + 30000;\n\t}\n}\n\nvoid\nCPed::ClearChat(void)\n{\n\tCAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_CHAT);\n\tif (animAssoc) {\n\t\tanimAssoc->blendDelta = -8.0f;\n\t\tanimAssoc->flags |= ASSOC_DELETEFADEDOUT;\n\t}\n\tbIsTalking = false;\n\tClearLookFlag();\n\tRestorePreviousState();\n\tif (m_objective == OBJECTIVE_BUY_ICE_CREAM) {\n\t\tbBoughtIceCream = true;\n\t\tSetObjective(OBJECTIVE_NONE);\n\t\tSetWanderPath(CGeneral::GetRandomNumberInRange(0, 8));\n\t}\n}\n\nbool\nCPed::FacePhone(void)\n{\n\t// FIX: This function was broken since it's left unused early in development.\n#ifdef FIX_BUGS\n\tfloat phoneDir = CGeneral::GetRadianAngleBetweenPoints(\n\t\tgPhoneInfo.m_aPhones[m_phoneId].m_vecPos.x, gPhoneInfo.m_aPhones[m_phoneId].m_vecPos.y,\n\t\tGetPosition().x, GetPosition().y);\n\n\tSetLookFlag(phoneDir, false);\n\tbool turnDone = TurnBody();\n\tif (turnDone) {\n\t\tSetIdle();\n\t\tClearLookFlag();\n\t\tm_phoneTalkTimer = CTimer::GetTimeInMilliseconds() + 10000;\n\t}\n\treturn turnDone;\n#else\n\tfloat currentRot = RADTODEG(m_fRotationCur);\n\tfloat phoneDir = CGeneral::GetRadianAngleBetweenPoints(\n\t\tgPhoneInfo.m_aPhones[m_phoneId].m_vecPos.x,\n\t\tgPhoneInfo.m_aPhones[m_phoneId].m_vecPos.y,\n\t\tGetPosition().x,\n\t\tGetPosition().y);\n\n\tSetLookFlag(phoneDir, false);\n\tphoneDir = CGeneral::LimitAngle(phoneDir);\n\tm_moved = CVector2D(0.0f, 0.0f);\n\n\tif (currentRot - 180.0f > phoneDir)\n\t\tphoneDir += 2 * 180.0f;\n\telse if (180.0f + currentRot < phoneDir)\n\t\tphoneDir -= 2 * 180.0f;\n\n\tfloat neededTurn = currentRot - phoneDir;\n\n\tif (Abs(neededTurn) <= 0.75f) {\n\t\tSetIdle();\n\t\tClearLookFlag();\n\t\tm_phoneTalkTimer = CTimer::GetTimeInMilliseconds() + 10000;\n\t\treturn true;\n\t} else {\n\t\tm_fRotationCur = DEGTORAD(currentRot - neededTurn * 0.2f);\n\t\treturn false;\n\t}\n#endif\n}\n\nbool\nCPed::MakePhonecall(void)\n{\n\tif (CTimer::GetTimeInMilliseconds() <= m_phoneTalkTimer)\n\t\treturn false;\n\n\tSetIdle();\n\tgPhoneInfo.m_aPhones[m_phoneId].m_nState = PHONE_STATE_FREE;\n\tm_phoneId = -1;\n\treturn true;\n}\n\nvoid\nStartTalkingOnMobileCB(CAnimBlendAssociation* assoc, void* arg)\n{\n\tCPed* ped = (CPed*)arg;\n\tif (ped->m_nPedState == PED_ANSWER_MOBILE)\n\t\tCAnimManager::BlendAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_PHONE_TALK, 4.0f);\n}\n\nvoid\nFinishTalkingOnMobileCB(CAnimBlendAssociation *assoc, void *arg)\n{\n\tCPed *ped = (CPed*)arg;\n\tif (ped->m_storedWeapon != WEAPONTYPE_UNIDENTIFIED) {\n\t\tped->RemoveWeaponModel(MI_MOBILE);\n\t\tped->SetCurrentWeapon(ped->m_storedWeapon);\n\t\tped->m_storedWeapon = WEAPONTYPE_UNIDENTIFIED;\n\t}\n\tped->m_lookTimer = 0;\n}\n\nvoid\nCPed::SetAnswerMobile(void)\n{\n\tif (m_nPedState != PED_ANSWER_MOBILE && !DyingOrDead()) {\n\t\tSetPedState(PED_ANSWER_MOBILE);\n\t\tRemoveWeaponAnims(GetWeapon()->m_eWeaponType, -4.0f);\n\t\tCAnimBlendAssociation *assoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_PHONE_IN, 4.0f);\n\t\tassoc->SetFinishCallback(StartTalkingOnMobileCB, this);\n\t\tm_lookTimer = INT32_MAX;\n\t\tif (m_storedWeapon == WEAPONTYPE_UNIDENTIFIED)\n\t\t\tm_storedWeapon = GetWeapon()->m_eWeaponType;\n\n\t\tRemoveWeaponModel(-1);\n\t}\n}\n\nvoid\nCPed::ClearAnswerMobile(void)\n{\n\tif (m_nLastPedState == PED_ANSWER_MOBILE)\n\t\tm_nLastPedState = PED_NONE;\n\n\tif (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_PHONE_TALK)) {\n\t\tCAnimBlendAssociation *assoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_PHONE_OUT, 8.0f);\n\t\tassoc->SetFinishCallback(FinishTalkingOnMobileCB, this);\n\t} else\n\t\tFinishTalkingOnMobileCB(nil, this);\n\n\tif (m_nPedState == PED_ANSWER_MOBILE) {\n\t\tm_nPedState = PED_IDLE;\n\t\tRestorePreviousState();\n\t\tm_pVehicleAnim = nil;\n\t}\n}\n\nvoid\nCPed::AnswerMobile(void)\n{\n\tif (!IsPedInControl())\n\t\treturn;\n\n\tCAnimBlendAssociation *phoneInAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_PHONE_IN);\n\tCAnimBlendAssociation *phoneOutAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_PHONE_OUT);\n\tCAnimBlendAssociation *phoneTalkAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_PHONE_TALK);\n\tif (phoneInAssoc || phoneTalkAssoc || phoneOutAssoc) {\n\t\tif (phoneInAssoc) {\n\t\t\tif (phoneInAssoc->currentTime >= 0.85f && !m_pWeaponModel) {\n\t\t\t\tCBaseModelInfo *phoneModel = CModelInfo::GetModelInfo(MI_MOBILE);\n\t\t\t\tm_pWeaponModel = (RpAtomic*)phoneModel->CreateInstance();\n\t\t\t\tphoneModel->AddRef();\n\t\t\t\tm_wepModelID = MI_MOBILE;\n\n\t\t\t\t// They copied AddWeaponModel and forgot that here\n\t\t\t\t// bool unused = IsPlayer();\n\t\t\t}\n\t\t} else if (phoneOutAssoc) {\n\t\t\tif (phoneOutAssoc->currentTime >= 0.5f && phoneOutAssoc->currentTime - phoneOutAssoc->timeStep < 0.5f) {\n\t\t\t\tRemoveWeaponModel(MI_MOBILE);\n\t\t\t\tSetCurrentWeapon(m_storedWeapon);\n\t\t\t\tm_storedWeapon = WEAPONTYPE_UNIDENTIFIED;\n\t\t\t}\n\t\t}\n\t} else {\n\t\tCAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_PHONE_TALK, 4.0f);\n\t}\n}\n\nvoid\nCPed::Teleport(CVector pos)\n{\n\tCWorld::Remove(this);\n\tSetPosition(pos);\n\tbIsStanding = false;\n\tm_nPedStateTimer = 0;\n\tm_actionX = 0.0f;\n\tm_actionY = 0.0f;\n\tm_pDamageEntity = nil;\n\tCWorld::Add(this);\n}\n\nvoid\nCPed::SetSeekCar(CVehicle *car, uint32 doorNode)\n{\n\tif (m_nPedState == PED_SEEK_CAR)\n\t\treturn;\n\n\tif (!CanSetPedState() || m_nPedState == PED_DRIVING)\n\t\treturn;\n\n\tSetStoredState();\n\tm_pSeekTarget = car;\n\tm_pSeekTarget->RegisterReference((CEntity**) &m_pSeekTarget);\n\tm_carInObjective = car;\n\tm_carInObjective->RegisterReference((CEntity**) &m_carInObjective);\n\tm_pMyVehicle = car;\n\tm_pMyVehicle->RegisterReference((CEntity**) &m_pMyVehicle);\n\t// m_pSeekTarget->RegisterReference((CEntity**) &m_pSeekTarget);\n\tm_vehDoor = doorNode;\n\tm_distanceToCountSeekDone = 0.5f;\n\tSetPedState(PED_SEEK_CAR);\n\n}\n\nvoid\nCPed::SeekCar(void)\n{\n\tCVehicle *vehToSeek = m_carInObjective;\n\tCVector dest(0.0f, 0.0f, 0.0f);\n\tif (!vehToSeek) {\n\t\tRestorePreviousState();\n\t\treturn;\n\t}\n\n\tif (m_objective != OBJECTIVE_ENTER_CAR_AS_PASSENGER) {\n\t\tif (!vehToSeek->IsBike() && m_vehDoor && m_objective != OBJECTIVE_ENTER_CAR_AS_DRIVER) {\n\t\t\tif (IsRoomToBeCarJacked()) {\n\t\t\t\tdest = GetPositionToOpenCarDoor(vehToSeek, m_vehDoor);\n\t\t\t} else if (m_nPedType == PEDTYPE_COP) {\n\t\t\t\tdest = GetPositionToOpenCarDoor(vehToSeek, CAR_DOOR_RF);\n\t\t\t} else {\n\t\t\t\tSetMoveState(PEDMOVE_STILL);\n\t\t\t}\n\t\t} else\n\t\t\tGetNearestDoor(vehToSeek, dest);\n\t} else {\n\t\tif (m_carJackTimer > CTimer::GetTimeInMilliseconds()) {\n\t\t\tSetMoveState(PEDMOVE_STILL);\n\t\t\treturn;\n\t\t}\n\t\tif (vehToSeek->GetModelIndex() == MI_COACH) {\n\t\t\tGetNearestDoor(vehToSeek, dest);\n\t\t} else {\n\t\t\tif (vehToSeek->IsTrain()) {\n\t\t\t\tif (vehToSeek->GetStatus() != STATUS_TRAIN_NOT_MOVING) {\n\t\t\t\t\tRestorePreviousObjective();\n\t\t\t\t\tRestorePreviousState();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (!GetNearestTrainDoor(vehToSeek, dest)) {\n\t\t\t\t\tRestorePreviousObjective();\n\t\t\t\t\tRestorePreviousState();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (!GetNearestPassengerDoor(vehToSeek, dest)) {\n\t\t\t\t\tif (vehToSeek->m_nNumPassengers == vehToSeek->m_nNumMaxPassengers) {\n\t\t\t\t\t\tRestorePreviousObjective();\n\t\t\t\t\t\tRestorePreviousState();\n\t\t\t\t\t} else {\n\t\t\t\t\t\tSetMoveState(PEDMOVE_STILL);\n\t\t\t\t\t}\n\t\t\t\t\tbVehEnterDoorIsBlocked = true;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tbVehEnterDoorIsBlocked = false;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (dest.x == 0.0f && dest.y == 0.0f) {\n#ifdef FIX_BUGS\n\t\tif ((!IsPlayer() && CharCreatedBy != MISSION_CHAR) || vehToSeek->VehicleCreatedBy != MISSION_VEHICLE || vehToSeek->pDriver || !vehToSeek->CanPedOpenLocks(this)) {\n#else\n\t\tif ((!IsPlayer() && CharCreatedBy != MISSION_CHAR) || vehToSeek->VehicleCreatedBy != MISSION_VEHICLE || vehToSeek->pDriver) {\n#endif\n\t\t\tRestorePreviousState();\n\t\t\tif (IsPlayer()) {\n\t\t\t\tClearObjective();\n\t\t\t} else if (CharCreatedBy == RANDOM_CHAR) {\n\t\t\t\tm_carJackTimer = CTimer::GetTimeInMilliseconds() + 30000;\n\t\t\t}\n\t\t\tSetMoveState(PEDMOVE_STILL);\n\t\t\tTheCamera.ClearPlayerWeaponMode();\n\t\t\tCCarCtrl::RemoveFromInterestingVehicleList(vehToSeek);\n\t\t\treturn;\n\t\t}\n\t\tdest = vehToSeek->GetPosition();\n\t\tif (bCollidedWithMyVehicle) {\n\t\t\tWarpPedIntoCar(m_pMyVehicle);\n\t\t\treturn;\n\t\t}\n\t}\n\tbool foundBetterPosToSeek = PossiblyFindBetterPosToSeekCar(&dest, vehToSeek);\n\tm_vecSeekPos = dest;\n\tfloat distToDestSqr = (m_vecSeekPos - GetPosition()).MagnitudeSqr();\n\n\tif (bIsRunning ||\n\t\tvehToSeek->pDriver && distToDestSqr > sq(2.0f) && (Abs(vehToSeek->m_vecMoveSpeed.x) > 0.01f || Abs(vehToSeek->m_vecMoveSpeed.y) > 0.01f))\n\t\tSetMoveState(PEDMOVE_RUN);\n\telse if (distToDestSqr < sq(2.0f))\n\t\tSetMoveState(PEDMOVE_WALK);\n\n\tif (distToDestSqr >= 1.0f)\n\t\tbCanPedEnterSeekedCar = false;\n\telse if (2.0f * vehToSeek->GetColModel()->boundingBox.max.x > distToDestSqr)\n\t\tbCanPedEnterSeekedCar = true;\n\n\tif (vehToSeek->m_nGettingInFlags & GetCarDoorFlag(m_vehDoor))\n\t\tbVehEnterDoorIsBlocked = true;\n\telse\n\t\tbVehEnterDoorIsBlocked = false;\n\n\t// Arrived to the car\n\tif (Seek()) {\n\t\tif (!foundBetterPosToSeek) {\n\t\t\tif (1.6f + GetPosition().z > dest.z && GetPosition().z - 0.5f < dest.z) {\n#ifdef GTA_TRAIN\n\t\t\t\tif (vehToSeek->IsTrain()) {\n\t\t\t\t\tSetEnterTrain(vehToSeek, m_vehDoor);\n\t\t\t\t} else\n#endif\n\t\t\t\t{\n\t\t\t\t\tm_fRotationCur = m_fRotationDest;\n\t\t\t\t\tif (!bVehEnterDoorIsBlocked) {\n\t\t\t\t\t\tvehToSeek->SetIsStatic(false);\n\t\t\t\t\t\tif (m_objective == OBJECTIVE_SOLICIT_VEHICLE) {\n\t\t\t\t\t\t\tSetSolicit(1000);\n\t\t\t\t\t\t} else if (m_objective == OBJECTIVE_BUY_ICE_CREAM) {\n\t\t\t\t\t\t\tSetBuyIceCream();\n\t\t\t\t\t\t} else if (vehToSeek->m_nNumGettingIn < vehToSeek->m_nNumMaxPassengers + 1\n\t\t\t\t\t\t\t&& vehToSeek->CanPedEnterCar()) {\n\n\t\t\t\t\t\t\tswitch (vehToSeek->GetStatus()) {\n\t\t\t\t\t\t\t\tcase STATUS_PLAYER:\n\t\t\t\t\t\t\t\tcase STATUS_SIMPLE:\n\t\t\t\t\t\t\t\tcase STATUS_PHYSICS:\n\t\t\t\t\t\t\t\tcase STATUS_PLAYER_DISABLED:\n\t\t\t\t\t\t\t\t\tif (vehToSeek->IsBike()) {\n\t\t\t\t\t\t\t\t\t\tif ((!m_leader || m_leader != vehToSeek->pDriver) &&\n\t\t\t\t\t\t\t\t\t\t\t((m_vehDoor == CAR_DOOR_LF || m_vehDoor == CAR_DOOR_RF || m_vehDoor == CAR_WINDSCREEN) && vehToSeek->pDriver ||\n\t\t\t\t\t\t\t\t\t\t\t(m_vehDoor == CAR_DOOR_LR || m_vehDoor == CAR_DOOR_RR) && vehToSeek->pPassengers[0])) {\n\t\t\t\t\t\t\t\t\t\t\tSetCarJack(vehToSeek);\n\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\tSetEnterCar(vehToSeek, m_vehDoor);\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t} else if (!vehToSeek->bIsBus && (!m_leader || m_leader != vehToSeek->pDriver) &&\n\t\t\t\t\t\t\t\t\t\t(m_vehDoor == CAR_DOOR_LF && vehToSeek->pDriver || m_vehDoor == CAR_DOOR_RF && vehToSeek->pPassengers[0] || m_vehDoor == CAR_DOOR_LR && vehToSeek->pPassengers[1] || m_vehDoor == CAR_DOOR_RR && vehToSeek->pPassengers[2])) {\n\t\t\t\t\t\t\t\t\t\tSetCarJack(vehToSeek);\n\t\t\t\t\t\t\t\t\t\tif (m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER && m_vehDoor != CAR_DOOR_LF)\n\t\t\t\t\t\t\t\t\t\t\tvehToSeek->pDriver->bFleeAfterExitingCar = true;\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tSetEnterCar(vehToSeek, m_vehDoor);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase STATUS_ABANDONED:\n\t\t\t\t\t\t\t\t\tif (vehToSeek->IsBike()) {\n\t\t\t\t\t\t\t\t\t\tif ((m_vehDoor == CAR_DOOR_LR || m_vehDoor == CAR_DOOR_RR) && vehToSeek->pPassengers[0]) {\n\t\t\t\t\t\t\t\t\t\t\tif (vehToSeek->pPassengers[0]->bDontDragMeOutCar) {\n\t\t\t\t\t\t\t\t\t\t\t\tif (IsPlayer())\n\t\t\t\t\t\t\t\t\t\t\t\t\tSetEnterCar(vehToSeek, m_vehDoor);\n\t\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\t\tSetCarJack(vehToSeek);\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\tSetEnterCar(vehToSeek, m_vehDoor);\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t} else if (m_vehDoor == CAR_DOOR_RF && vehToSeek->pPassengers[0]) {\n\t\t\t\t\t\t\t\t\t\tif (vehToSeek->pPassengers[0]->bDontDragMeOutCar) {\n\t\t\t\t\t\t\t\t\t\t\tif (IsPlayer())\n\t\t\t\t\t\t\t\t\t\t\t\tSetEnterCar(vehToSeek, m_vehDoor);\n\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\tSetCarJack(vehToSeek);\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tSetEnterCar(vehToSeek, m_vehDoor);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase STATUS_WRECKED:\n\t\t\t\t\t\t\t\t\tSetIdle();\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tRestorePreviousState();\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tSetMoveState(PEDMOVE_STILL);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nbool\nCPed::CheckForExplosions(CVector2D &area)\n{\n\tint event = 0;\n\tif (CEventList::FindClosestEvent(EVENT_EXPLOSION, GetPosition(), &event)) {\n\t\tarea.x = gaEvent[event].posn.x;\n\t\tarea.y = gaEvent[event].posn.y;\n\t\tCEntity *actualEntity = nil;\n\n\t\tswitch (gaEvent[event].entityType) {\n\t\t\tcase EVENT_ENTITY_PED:\n\t\t\t\tactualEntity = CPools::GetPed(gaEvent[event].entityRef);\n\t\t\t\tbreak;\n\t\t\tcase EVENT_ENTITY_VEHICLE:\n\t\t\t\tactualEntity = CPools::GetVehicle(gaEvent[event].entityRef);\n\t\t\t\tbreak;\n\t\t\tcase EVENT_ENTITY_OBJECT:\n\t\t\t\tactualEntity = CPools::GetObject(gaEvent[event].entityRef);\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\n\t\tif (actualEntity) {\n\t\t\tm_pEventEntity = actualEntity;\n\t\t\tm_pEventEntity->RegisterReference((CEntity **) &m_pEventEntity);\n\t\t\tbGonnaInvestigateEvent = true;\n\t\t} else\n\t\t\tbGonnaInvestigateEvent = false;\n\n\t\tCEventList::ClearEvent(event);\n\t\treturn true;\n\t} else if (CEventList::FindClosestEvent(EVENT_FIRE, GetPosition(), &event)) {\n\t\tarea.x = gaEvent[event].posn.x;\n\t\tarea.y = gaEvent[event].posn.y;\n\t\tCEventList::ClearEvent(event);\n\t\tbGonnaInvestigateEvent = false;\n\t\treturn true;\n\t}\n\n\tbGonnaInvestigateEvent = false;\n\treturn false;\n}\n\nCPed *\nCPed::CheckForGunShots(void)\n{\n\tint event;\n\tif (CEventList::FindClosestEvent(EVENT_GUNSHOT, GetPosition(), &event)) {\n\t\tif (gaEvent[event].entityType == EVENT_ENTITY_PED) {\n\t\t\t// Probably due to we don't want peds to go gunshot area? (same on VC)\n\t\t\tbGonnaInvestigateEvent = false;\n\t\t\treturn CPools::GetPed(gaEvent[event].entityRef);\n\t\t}\n\t}\n\tbGonnaInvestigateEvent = false;\n\treturn nil;\n}\n\nCPed *\nCPed::CheckForDeadPeds(void)\n{\n\tint event;\n\tif (CEventList::FindClosestEvent(EVENT_DEAD_PED, GetPosition(), &event)) {\n\t\tint pedHandle = gaEvent[event].entityRef;\n\t\tif (pedHandle && gaEvent[event].entityType == EVENT_ENTITY_PED) {\n\t\t\tbGonnaInvestigateEvent = true;\n\t\t\treturn CPools::GetPed(pedHandle);\n\t\t}\n\t}\n\tbGonnaInvestigateEvent = false;\n\treturn nil;\n}\n\nbool\nCPed::IsPlayer(void) const\n{\n#if 0\n\treturn m_nPedType == PEDTYPE_PLAYER1; // Original\n#else\n\t// We still have those in enum, so let's also check for them.\n\treturn m_nPedType == PEDTYPE_PLAYER1 || m_nPedType == PEDTYPE_PLAYER2 ||\n\t\tm_nPedType == PEDTYPE_PLAYER3 || m_nPedType == PEDTYPE_PLAYER4;\n#endif\n}\n\nbool\nCPed::IsGangMember(void) const\n{\n\treturn m_nPedType >= PEDTYPE_GANG1 && m_nPedType <= PEDTYPE_GANG9;\n}\n\nbool\nIsPedPointerValid(CPed* pPed)\n{\n\tif (!IsPedPointerValid_NotInWorld(pPed))\n\t\treturn false;\n\tif (pPed->bInVehicle && pPed->m_pMyVehicle)\n\t\treturn IsEntityPointerValid(pPed->m_pMyVehicle);\n\treturn pPed->m_entryInfoList.first || pPed == FindPlayerPed();\n}\n\nbool\nIsPedPointerValid_NotInWorld(CPed* pPed)\n{\n\tif (!pPed)\n\t\treturn false;\n\tint index = CPools::GetPedPool()->GetJustIndex_NoFreeAssert(pPed);\n#ifdef FIX_BUGS\n\tif (index < 0 || index >= NUMPEDS)\n#else\n\tif (index < 0 || index > NUMPEDS)\n#endif\n\t\treturn false;\n\treturn true;\n}\n\nbool\nCPed::IsPointerValid(void)\n{\n\tint pedIndex = CPools::GetPedPool()->GetIndex(this) >> 8;\n\tif (pedIndex < 0 || pedIndex >= NUMPEDS)\n\t\treturn false;\n\n\tif (m_entryInfoList.first || FindPlayerPed() == this)\n\t\treturn true;\n\n\treturn false;\n}\n\nvoid\nCPed::SetPedPositionInCar(void)\n{\n\tbool notYet = false;\n\tif (CReplay::IsPlayingBack())\n\t\treturn;\n\n\tif (bChangedSeat) {\n\t\tif (m_pMyVehicle->IsBike()) {\n\t\t\tif (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_BIKE_JUMPON_LHS)\n\t\t\t\t|| RpAnimBlendClumpGetAssociation(GetClump(), ANIM_BIKE_JUMPON_RHS)\n\t\t\t\t|| RpAnimBlendClumpGetAssociation(GetClump(), ANIM_BIKE_KICK)) {\n\t\t\t\tLineUpPedWithCar(LINE_UP_TO_CAR_START);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tbChangedSeat = false;\n\t\t} else {\n\t\t\tif (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_CAR_GET_IN_LHS)\n\t\t\t\t|| RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_CAR_GET_IN_LO_LHS)\n\t\t\t\t|| RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_CAR_CLOSE_DOOR_LHS)\n\t\t\t\t|| RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_CAR_CLOSE_DOOR_LO_LHS)\n\t\t\t\t|| RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_CAR_SHUFFLE_RHS)\n\t\t\t\t|| RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_CAR_SHUFFLE_LO_RHS)\n\t\t\t\t|| RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_VAN_CLOSE_DOOR_REAR_LHS)\n\t\t\t\t|| RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_VAN_CLOSE_DOOR_REAR_RHS)\n\t\t\t\t|| RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_VAN_GET_IN_REAR_LHS)\n\t\t\t\t|| RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_VAN_GET_IN_REAR_RHS)\n\t\t\t\t|| RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_COACH_GET_IN_LHS)\n\t\t\t\t|| RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_COACH_GET_IN_RHS)\n\t\t\t\t|| RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_CAR_JUMP_IN_LO_LHS)) {\n\t\t\t\tnotYet = true;\n\t\t\t}\n\t\t}\n\t\tif (notYet) {\n\t\t\tLineUpPedWithCar(LINE_UP_TO_CAR_START);\n\t\t\tbChangedSeat = false;\n\t\t\treturn;\n\t\t}\n\t}\n\tCVehicleModelInfo *vehModel = (CVehicleModelInfo *)CModelInfo::GetModelInfo(m_pMyVehicle->GetModelIndex());\n\tCMatrix newMat(m_pMyVehicle->GetMatrix());\n\tCVector seatPos;\n\tif (m_pMyVehicle->pDriver == this) {\n\t\tseatPos = vehModel->GetFrontSeatPosn();\n\t\tif (!m_pMyVehicle->IsBoat() && !m_pMyVehicle->IsBike())\n\t\t\tseatPos.x = -seatPos.x;\n\n\t} else if (m_pMyVehicle->pPassengers[0] == this) {\n\t\tseatPos = m_pMyVehicle->IsBike() ? vehModel->m_positions[CAR_POS_BACKSEAT]: vehModel->GetFrontSeatPosn();\n\n\t} else if (m_pMyVehicle->pPassengers[1] == this) {\n\t\tseatPos = vehModel->m_positions[CAR_POS_BACKSEAT];\n\t\tseatPos.x = -seatPos.x;\n\n\t} else {\n\t\tif (m_pMyVehicle->pPassengers[2] == this) {\n\t\t\tseatPos = vehModel->m_positions[CAR_POS_BACKSEAT];\n\t\t} else {\n\t\t\tseatPos = vehModel->GetFrontSeatPosn();\n\t\t}\n\t}\n\tif (m_pMyVehicle->IsBike()) {\n\t\t((CBike*)m_pMyVehicle)->CalculateLeanMatrix();\n\t\tnewMat = ((CBike*)m_pMyVehicle)->m_leanMatrix;\n\t}\n\tnewMat.GetPosition() += Multiply3x3(newMat, seatPos);\n\t// Already done below (SetTranslate(0.0f, 0.0f, 0.0f))\n\t// tempMat.SetUnity();\n\n\t// Rear seats on vans don't face to front, so rotate them HALFPI.\n\tif (m_pMyVehicle->bIsVan) {\n\t\tCMatrix tempMat;\n\t\tif (m_pMyVehicle->pPassengers[1] == this) {\n\t\t\tm_fRotationCur = m_pMyVehicle->GetForward().Heading() - HALFPI;\n\t\t\ttempMat.SetTranslate(0.0f, 0.0f, 0.0f);\n\t\t\ttempMat.RotateZ(-HALFPI);\n\t\t\ttempMat.Translate(0.0f, 0.6f, 0.0f);\n\t\t\tnewMat = newMat * tempMat;\n\t\t} else if (m_pMyVehicle->pPassengers[2] == this) {\n\t\t\tm_fRotationCur = m_pMyVehicle->GetForward().Heading() + HALFPI;\n\t\t\ttempMat.SetTranslate(0.0f, 0.0f, 0.0f);\n\t\t\ttempMat.RotateZ(HALFPI);\n\t\t\tnewMat = newMat * tempMat;\n\t\t} else {\n\t\t\tm_fRotationCur = m_pMyVehicle->GetForward().Heading();\n\t\t}\n\t} else {\n\t\tm_fRotationCur = m_pMyVehicle->GetForward().Heading();\n\t}\n\tGetMatrix() = newMat;\n}\n\nvoid\nCPed::LookForSexyPeds(void)\n{\n\tif ((!IsPedInControl() && m_nPedState != PED_DRIVING)\n\t\t|| m_lookTimer >= CTimer::GetTimeInMilliseconds() || m_nPedType != PEDTYPE_CIVMALE)\n\t\treturn;\n\n\tfor (int i = 0; i < m_numNearPeds; i++) {\n\t\tif (CanSeeEntity(m_nearPeds[i])) {\n\t\t\tif ((GetPosition() - m_nearPeds[i]->GetPosition()).Magnitude() < 10.0f) {\n\t\t\t\tCPed *nearPed = m_nearPeds[i];\n\t\t\t\tif ((nearPed->m_pedStats->m_sexiness > m_pedStats->m_sexiness)\n\t\t\t\t\t&& nearPed->m_nPedType == PEDTYPE_CIVFEMALE) {\n\n\t\t\t\t\tSetLookFlag(nearPed, true);\n\t\t\t\t\tm_lookTimer = CTimer::GetTimeInMilliseconds() + 4000;\n\t\t\t\t\tSay(SOUND_PED_CHAT_SEXY);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tm_lookTimer = CTimer::GetTimeInMilliseconds() + 10000;\n}\n\nvoid\nCPed::LookForSexyCars(void)\n{\n\tCEntity *vehicles[8];\n\tCVehicle *veh;\n\tint foundVehId = 0;\n\tint bestPriceYet = 0;\n\tint16 lastVehicle;\n\n\tif (!IsPedInControl() && m_nPedState != PED_DRIVING)\n\t\treturn;\n\n\tif (m_lookTimer < CTimer::GetTimeInMilliseconds()) {\n\t\tCWorld::FindObjectsInRange(GetPosition(), 10.0f, true, &lastVehicle, 6, vehicles, false, true, false, false, false);\n\n\t\tfor (int vehId = 0; vehId < lastVehicle; vehId++) {\n\t\t\tveh = (CVehicle*)vehicles[vehId];\n\t\t\tif (veh != m_pMyVehicle && bestPriceYet < veh->pHandling->nMonetaryValue) {\n\t\t\t\tfoundVehId = vehId;\n\t\t\t\tbestPriceYet = veh->pHandling->nMonetaryValue;\n\t\t\t}\n\t\t}\n\t\tif (lastVehicle > 0 && bestPriceYet > 40000)\n\t\t\tSetLookFlag(vehicles[foundVehId], false);\n\n\t\tm_lookTimer = CTimer::GetTimeInMilliseconds() + 10000;\n\t}\n}\n\nbool\nCPed::LookForInterestingNodes(void)\n{\n\tCBaseModelInfo *model;\n\tCPtrNode *ptrNode;\n\tCVector effectDist;\n\tC2dEffect *effect;\n\tCMatrix *objMat;\n\n\tif ((CTimer::GetFrameCounter() + (m_randomSeed % 256)) & 7 || CTimer::GetTimeInMilliseconds() <= m_chatTimer) {\n\t\treturn false;\n\t}\n\tbool found = false;\n\tuint8 randVal = CGeneral::GetRandomNumber() % 256;\n\n\tint minX = CWorld::GetSectorIndexX(GetPosition().x - CHECK_NEARBY_THINGS_MAX_DIST);\n\tif (minX < 0) minX = 0;\n\tint minY = CWorld::GetSectorIndexY(GetPosition().y - CHECK_NEARBY_THINGS_MAX_DIST);\n\tif (minY < 0) minY = 0;\n\tint maxX = CWorld::GetSectorIndexX(GetPosition().x + CHECK_NEARBY_THINGS_MAX_DIST);\n#ifdef FIX_BUGS\n\tif (maxX >= NUMSECTORS_X) maxX = NUMSECTORS_X - 1;\n#else\n\tif (maxX >= NUMSECTORS_X) maxX = NUMSECTORS_X;\n#endif\n\n\tint maxY = CWorld::GetSectorIndexY(GetPosition().y + CHECK_NEARBY_THINGS_MAX_DIST);\n#ifdef FIX_BUGS\n\tif (maxY >= NUMSECTORS_Y) maxY = NUMSECTORS_Y - 1;\n#else\n\tif (maxY >= NUMSECTORS_Y) maxY = NUMSECTORS_Y;\n#endif\n\n\tfor (int curY = minY; curY <= maxY && !found; curY++) {\n\t\tfor (int curX = minX; curX <= maxX && !found; curX++) {\n\t\t\tCSector *sector = CWorld::GetSector(curX, curY);\n\n\t\t\tfor (ptrNode = sector->m_lists[ENTITYLIST_VEHICLES].first; ptrNode && !found; ptrNode = ptrNode->next) {\n\t\t\t\tCVehicle *veh = (CVehicle*)ptrNode->item;\n\t\t\t\tmodel = veh->GetModelInfo();\n\t\t\t\tif (model->GetNum2dEffects() != 0) {\n\t\t\t\t\tfor (int e = 0; e < model->GetNum2dEffects(); e++) {\n\t\t\t\t\t\teffect = model->Get2dEffect(e);\n\t\t\t\t\t\tif (effect->type == EFFECT_ATTRACTOR && effect->attractor.probability >= randVal) {\n\t\t\t\t\t\t\tobjMat = &veh->GetMatrix();\n\t\t\t\t\t\t\tCVector effectPos = veh->GetMatrix() * effect->pos;\n\t\t\t\t\t\t\teffectDist = effectPos - GetPosition();\n\t\t\t\t\t\t\tif (effectDist.MagnitudeSqr() < sq(8.0f)) {\n\t\t\t\t\t\t\t\tfound = true;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (ptrNode = sector->m_lists[ENTITYLIST_OBJECTS].first; ptrNode && !found; ptrNode = ptrNode->next) {\n\t\t\t\tCObject *obj = (CObject*)ptrNode->item;\n\t\t\t\tmodel = CModelInfo::GetModelInfo(obj->GetModelIndex());\n\t\t\t\tif (model->GetNum2dEffects() != 0) {\n\t\t\t\t\tfor (int e = 0; e < model->GetNum2dEffects(); e++) {\n\t\t\t\t\t\teffect = model->Get2dEffect(e);\n\t\t\t\t\t\tif (effect->type == EFFECT_ATTRACTOR && effect->attractor.probability >= randVal) {\n\t\t\t\t\t\t\tobjMat = &obj->GetMatrix();\n\t\t\t\t\t\t\tCVector effectPos = obj->GetMatrix() * effect->pos;\n\t\t\t\t\t\t\teffectDist = effectPos - GetPosition();\n\t\t\t\t\t\t\tif (effectDist.MagnitudeSqr() < sq(8.0f)) {\n\t\t\t\t\t\t\t\tfound = true;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (ptrNode = sector->m_lists[ENTITYLIST_BUILDINGS].first; ptrNode && !found; ptrNode = ptrNode->next) {\n\t\t\t\tCBuilding *building = (CBuilding*)ptrNode->item;\n\t\t\t\tmodel = CModelInfo::GetModelInfo(building->GetModelIndex());\n\t\t\t\tif (model->GetNum2dEffects() != 0) {\n\t\t\t\t\tfor (int e = 0; e < model->GetNum2dEffects(); e++) {\n\t\t\t\t\t\teffect = model->Get2dEffect(e);\n\t\t\t\t\t\tif (effect->type == EFFECT_ATTRACTOR && effect->attractor.probability >= randVal) {\n\t\t\t\t\t\t\tobjMat = &building->GetMatrix();\n\t\t\t\t\t\t\tCVector effectPos = building->GetMatrix() * effect->pos;\n\t\t\t\t\t\t\teffectDist = effectPos - GetPosition();\n\t\t\t\t\t\t\tif (effectDist.MagnitudeSqr() < sq(8.0f)) {\n\t\t\t\t\t\t\t\tfound = true;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (ptrNode = sector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP].first; ptrNode && !found; ptrNode = ptrNode->next) {\n\t\t\t\tCBuilding *building = (CBuilding*)ptrNode->item;\n\t\t\t\tmodel = CModelInfo::GetModelInfo(building->GetModelIndex());\n\t\t\t\tif (model->GetNum2dEffects() != 0) {\n\t\t\t\t\tfor (int e = 0; e < model->GetNum2dEffects(); e++) {\n\t\t\t\t\t\teffect = model->Get2dEffect(e);\n\t\t\t\t\t\tif (effect->type == EFFECT_ATTRACTOR && effect->attractor.probability >= randVal) {\n\t\t\t\t\t\t\tobjMat = &building->GetMatrix();\n\t\t\t\t\t\t\tCVector effectPos = building->GetMatrix() * effect->pos;\n\t\t\t\t\t\t\teffectDist = effectPos - GetPosition();\n\t\t\t\t\t\t\tif (effectDist.MagnitudeSqr() < sq(8.0f)) {\n\t\t\t\t\t\t\t\tfound = true;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (!found)\n\t\treturn false;\n\n\tCVector effectFrontLocal = Multiply3x3(*objMat, effect->attractor.dir);\n\tfloat angleToFace = CGeneral::GetRadianAngleBetweenPoints(effectFrontLocal.x, effectFrontLocal.y, 0.0f, 0.0f);\n\trandVal = CGeneral::GetRandomNumber() % 256;\n\tif (randVal <= m_randomSeed % 256) {\n\t\tm_chatTimer = CTimer::GetTimeInMilliseconds() + 2000;\n\t\tSetLookFlag(angleToFace, true);\n\t\tSetLookTimer(1000);\n\t\treturn false;\n\t}\n\n\tCVector2D effectPos = *objMat * effect->pos;\n\tswitch (effect->attractor.type) {\n\t\tcase ATTRACTORTYPE_ICECREAM:\n\t\t\tSetInvestigateEvent(EVENT_ICECREAM, effectPos, 0.1f, 15000, angleToFace);\n\t\t\tbreak;\n\t\tcase ATTRACTORTYPE_STARE:\n\t\t\tSetInvestigateEvent(EVENT_SHOPSTALL, effectPos, 1.0f,\n\t\t\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(8000, 10 * effect->attractor.probability + 8500),\n\t\t\t\t\t\t\t\tangleToFace);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\treturn true;\n\t}\n\treturn true;\n}\n\nvoid\nPlayRandomAnimationsFromAnimBlock(CPed* ped, AssocGroupId animGroup, uint32 first, uint32 amount)\n{\n\tif (!ped->IsPedInControl())\n\t\treturn;\n\n\tconst char *groupName = CAnimManager::GetAnimGroupName(animGroup);\n\tCAnimBlock *animBlock = CAnimManager::GetAnimationBlock(groupName);\n\tCAnimBlendAssociation *assoc;\n\tfor (assoc = RpAnimBlendClumpGetFirstAssociation(ped->GetClump()); assoc; assoc = RpAnimBlendGetNextAssociation(assoc)) {\n\t\tint first = animBlock->firstIndex;\n\t\tint index = assoc->hierarchy - CAnimManager::GetAnimation(0);\n\t\tif (index >= first && index < first + animBlock->numAnims) {\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tif (CTimer::GetTimeInMilliseconds() > ped->m_nWaitTimer && assoc)\n\t\tassoc->flags &= ~ASSOC_REPEAT;\n\n\tif (!assoc || assoc->blendDelta < 0.0f) {\n\t\tint selectedAnimOffset;\n\t\tdo\n\t\t\tselectedAnimOffset = CGeneral::GetRandomNumberInRange(0, amount);\n\t\twhile (assoc && first + selectedAnimOffset == assoc->animId);\n\n\t\tassoc = CAnimManager::BlendAnimation(ped->GetClump(), animGroup, (AnimationId)(first + selectedAnimOffset), 3.0f);\n\n\t\tassoc->SetFinishCallback(CPed::FinishedWaitCB, ped);\n\t\tif (assoc->flags & ASSOC_REPEAT)\n\t\t\tped->m_nWaitTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(3000, 8000);\n\t\telse\n\t\t\tped->m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 8000;\n\t}\n}\n\nvoid\nCPed::ClearWaitState(void)\n{\n\tCAnimBlendAssociation *assoc;\n\tswitch (m_nWaitState) {\n\t\tcase WAITSTATE_PLAYANIM_CHAT:\n\t\tcase WAITSTATE_SIT_DOWN:\n\t\tcase WAITSTATE_SIT_DOWN_RVRS:\n\t\tcase WAITSTATE_SIT_UP:\n\t\tcase WAITSTATE_SIT_IDLE:\n\t\tcase WAITSTATE_USE_ATM:\n\t\t\tif (CTimer::GetTimeInMilliseconds() <= m_nWaitTimer) {\n\t\t\t\tif (m_nWaitState == WAITSTATE_USE_ATM) {\n\t\t\t\t\tassoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_ATM);\n\t\t\t\t\tif (assoc)\n\t\t\t\t\t\tassoc->blendDelta = -8.0f;\n\t\t\t\t\tif (m_attractor)\n\t\t\t\t\t\tGetPedAttractorManager()->DeRegisterPed(this, m_attractor);\n\n\t\t\t\t} else if (m_nWaitState == WAITSTATE_PLAYANIM_CHAT) {\n\t\t\t\t\tassoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_CHAT);\n\t\t\t\t\tif (assoc)\n\t\t\t\t\t\tassoc->blendDelta = -8.0f;\n\t\t\t\t\tif (m_attractor)\n\t\t\t\t\t\tGetPedAttractorManager()->DeRegisterPed(this, m_attractor);\n\n\t\t\t\t} else if (m_nWaitState == WAITSTATE_SIT_DOWN || m_nWaitState == WAITSTATE_SIT_DOWN_RVRS || m_nWaitState == WAITSTATE_SIT_IDLE || m_nWaitState == WAITSTATE_SIT_UP) {\n\t\t\t\t\tswitch (m_nWaitState) {\n\t\t\t\t\t\tcase WAITSTATE_SIT_DOWN:\n\t\t\t\t\t\t\tassoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_SEAT_DOWN);\n\t\t\t\t\t\t\tif (assoc)\n\t\t\t\t\t\t\t\tassoc->blendDelta = -8.0f;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase WAITSTATE_SIT_IDLE:\n\t\t\t\t\t\t\tassoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_SEAT_IDLE);\n\t\t\t\t\t\t\tif (assoc)\n\t\t\t\t\t\t\t\tassoc->blendDelta = -8.0f;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase WAITSTATE_SIT_UP:\n\t\t\t\t\t\t\tassoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_SEAT_UP);\n\t\t\t\t\t\t\tif (assoc)\n\t\t\t\t\t\t\t\tassoc->blendDelta = -8.0f;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tif (m_attractor)\n\t\t\t\t\t\tGetPedAttractorManager()->DeRegisterPed(this, m_attractor);\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\tcase WAITSTATE_RIOT:\n\t\t{\n\t\t\tCAnimBlock* riotAnimBlock = CAnimManager::GetAnimationBlock(\"riot\");\n\n\t\t\tfor (assoc = RpAnimBlendClumpGetFirstAssociation(GetClump()); assoc; assoc = RpAnimBlendGetNextAssociation(assoc)) {\n\t\t\t\tint first = riotAnimBlock->firstIndex;\n\t\t\t\tint index = assoc->hierarchy - CAnimManager::GetAnimation(0);\n\t\t\t\tif (index >= first && index < first + riotAnimBlock->numAnims) {\n\t\t\t\t\tassoc->blendDelta = -1000.0f;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tcase WAITSTATE_FAST_FALL:\n\t\t\tif (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_HIGHIMPACT_FRONT))\n\t\t\t\tSetGetUp();\n\n\t\t\tbreak;\n\t\tcase WAITSTATE_BOMBER:\n\t\t\tassoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_DETONATE);\n\t\t\tif (assoc)\n\t\t\t\tassoc->blendDelta = -8.0f;\n\t\t\tbreak;\n\t\tcase WAITSTATE_STRIPPER:\n\t\t{\n\t\t\tCAnimBlock* stripAnimBlock = CAnimManager::GetAnimationBlock(\"strip\");\n\n\t\t\tfor (assoc = RpAnimBlendClumpGetFirstAssociation(GetClump()); assoc; assoc = RpAnimBlendGetNextAssociation(assoc)) {\n\t\t\t\tint first = stripAnimBlock->firstIndex;\n\t\t\t\tint index = assoc->hierarchy - CAnimManager::GetAnimation(0);\n\t\t\t\tif (index >= first && index < first + stripAnimBlock->numAnims) {\n\t\t\t\t\tassoc->blendDelta = -1000.0f;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tcase WAITSTATE_LANCESITTING:\n\t\t\tassoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_SUNBATHE_IDLE);\n\t\t\tif (assoc)\n\t\t\t\tassoc->blendDelta = -8.0f;\n\t\t\tbreak;\n\t\tcase WAITSTATE_PLAYANIM_HANDSUP_SIMPLE:\n\t\t\tassoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_HANDSUP);\n\t\t\tif (assoc)\n\t\t\t\tassoc->blendDelta = -8.0f;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\tm_nWaitState = WAITSTATE_FALSE;\n}\n\nvoid\nCPed::SetWaitState(eWaitState state, void *time)\n{\n\tAnimationId waitAnim = ANIM_STD_NUM;\n\tCAnimBlendAssociation *animAssoc;\n\n\tif (!IsPedInControl())\n\t\treturn;\n\n\tif (m_nWaitState == WAITSTATE_RIOT && state != WAITSTATE_FALSE)\n\t\treturn;\n\n\tif (state != m_nWaitState)\n\t\tFinishedWaitCB(nil, this);\n\n\tswitch (state) {\n\t\tcase WAITSTATE_TRAFFIC_LIGHTS:\n\t\t\tm_nWaitTimer = CTimer::GetTimeInMilliseconds() + 500;\n\t\t\tSetMoveState(PEDMOVE_STILL);\n\t\t\tbreak;\n\t\tcase WAITSTATE_CROSS_ROAD:\n\t\t\tm_nWaitTimer = CTimer::GetTimeInMilliseconds() + 1000;\n\t\t\tCAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_IDLE_HBHB, 4.0f);\n\t\t\tbreak;\n\t\tcase WAITSTATE_CROSS_ROAD_LOOK:\n\t\t\tCAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_ROADCROSS, 8.0f);\n\n\t\t\tif (time)\n\t\t\t\tm_nWaitTimer = CTimer::GetTimeInMilliseconds() + *(int*)time;\n\t\t\telse\n\t\t\t\tm_nWaitTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(2000,5000);\n\n\t\t\tbreak;\n\t\tcase WAITSTATE_LOOK_PED:\n\t\tcase WAITSTATE_LOOK_SHOP:\n\t\tcase WAITSTATE_LOOK_ACCIDENT:\n\t\tcase WAITSTATE_FACEOFF_GANG:\n\t\tcase WAITSTATE_RIOT:\n\t\tcase WAITSTATE_STRIPPER:\n\t\t\tbreak;\n\t\tcase WAITSTATE_DOUBLEBACK:\n\t\t\tm_headingRate = 0.0f;\n\t\t\tm_nWaitTimer = CTimer::GetTimeInMilliseconds() + 3500;\n\t\t\tanimAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_IDLE_HBHB, 4.0f);\n#ifdef FIX_BUGS\n\t\t\tanimAssoc->SetFinishCallback(RestoreHeadingRateCB, this);\n#endif\n\t\t\tbreak;\n\t\tcase WAITSTATE_HITWALL:\n\t\t\tm_headingRate = 2.0f;\n\t\t\tm_nWaitTimer = CTimer::GetTimeInMilliseconds() + 5000;\n\t\t\tanimAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_HIT_WALL, 16.0f);\n\t\t\tanimAssoc->flags |= ASSOC_DELETEFADEDOUT;\n\t\t\tanimAssoc->flags |= ASSOC_FADEOUTWHENDONE;\n\t\t\tanimAssoc->SetDeleteCallback(FinishedWaitCB, this);\n\n\t\t\tif (m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER && CharCreatedBy == RANDOM_CHAR && m_nPedState == PED_SEEK_CAR) {\n\t\t\t\tClearObjective();\n\t\t\t\tRestorePreviousState();\n\t\t\t\tm_carJackTimer = CTimer::GetTimeInMilliseconds() + 30000;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase WAITSTATE_TURN180:\n\t\t\tm_headingRate = 0.0f;\n\t\t\tm_nWaitTimer = CTimer::GetTimeInMilliseconds() + 5000;\n\t\t\tanimAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_TURN180, 4.0f);\n\t\t\tanimAssoc->SetFinishCallback(FinishedWaitCB, this);\n\t\t\tbreak;\n\t\tcase WAITSTATE_SURPRISE:\n\t\t\tm_headingRate = 0.0f;\n\t\t\tm_nWaitTimer = CTimer::GetTimeInMilliseconds() + 2000;\n\t\t\tanimAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_HIT_WALL, 4.0f);\n\t\t\tanimAssoc->SetFinishCallback(FinishedWaitCB, this);\n\t\t\tbreak;\n\t\tcase WAITSTATE_STUCK:\n\t\t\tSetMoveState(PEDMOVE_STILL);\n\t\t\tSetMoveAnim();\n\t\t\tm_headingRate = 0.0f;\n\t\t\tm_nWaitTimer = CTimer::GetTimeInMilliseconds() + 5000;\n\t\t\tanimAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_IDLE_TIRED, 4.0f);\n#ifdef FIX_BUGS\n\t\t\tanimAssoc->SetFinishCallback(RestoreHeadingRateCB, this);\n#endif\n\n\t\t\t// Random char as passenger? Cop, medic etc.?\n\t\t\tif (m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER && CharCreatedBy == RANDOM_CHAR && m_nPedState == PED_SEEK_CAR) {\n\t\t\t\tClearObjective();\n\t\t\t\tRestorePreviousState();\n\t\t\t\tm_carJackTimer = CTimer::GetTimeInMilliseconds() + 30000;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase WAITSTATE_LOOK_ABOUT:\n\t\t\tSetMoveState(PEDMOVE_STILL);\n\t\t\tSetMoveAnim();\n\t\t\tm_headingRate = 0.0f;\n\t\t\tm_nWaitTimer = CTimer::GetTimeInMilliseconds() + 5000;\n\t\t\tanimAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_IDLE_HBHB, 4.0f);\n#ifdef FIX_BUGS\n\t\t\tanimAssoc->SetFinishCallback(RestoreHeadingRateCB, this);\n#endif\n\n\t\t\tbreak;\n\t\tcase WAITSTATE_PLAYANIM_COWER:\n\t\t\twaitAnim = ANIM_STD_HANDSCOWER;\n\t\tcase WAITSTATE_PLAYANIM_HANDSUP:\n\t\t\tif (waitAnim == ANIM_STD_NUM)\n\t\t\t\twaitAnim = ANIM_STD_HANDSUP;\n\t\tcase WAITSTATE_PLAYANIM_HANDSCOWER:\n\t\t\tif (waitAnim == ANIM_STD_NUM)\n\t\t\t\twaitAnim = ANIM_STD_HANDSCOWER;\n\t\t\tm_headingRate = 0.0f;\n\t\t\tif (time)\n\t\t\t\tm_nWaitTimer = CTimer::GetTimeInMilliseconds() + *(int*)time;\n\t\t\telse\n\t\t\t\tm_nWaitTimer = CTimer::GetTimeInMilliseconds() + 3000;\n\n\t\t\tanimAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, waitAnim, 4.0f);\n\t\t\tanimAssoc->SetDeleteCallback(FinishedWaitCB, this);\n\t\t\tbreak;\n\t\tcase WAITSTATE_PLAYANIM_DUCK:\n\t\t\twaitAnim = ANIM_STD_DUCK_DOWN;\n\t\tcase WAITSTATE_PLAYANIM_TAXI:\n\t\t\tif (waitAnim == ANIM_STD_NUM)\n\t\t\t\twaitAnim = ANIM_STD_HAILTAXI;\n\t\tcase WAITSTATE_PLAYANIM_CHAT:\n\t\t\tif (waitAnim == ANIM_STD_NUM)\n\t\t\t\twaitAnim = ANIM_STD_CHAT;\n\t\t\tif (time)\n\t\t\t\tm_nWaitTimer = CTimer::GetTimeInMilliseconds() + *(int*)time;\n\t\t\telse\n\t\t\t\tm_nWaitTimer = CTimer::GetTimeInMilliseconds() + 3000;\n\n\t\t\tanimAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, waitAnim, 4.0f);\n\t\t\tanimAssoc->flags &= ~ASSOC_FADEOUTWHENDONE;\n\t\t\tanimAssoc->flags |= ASSOC_DELETEFADEDOUT;\n\t\t\tanimAssoc->SetDeleteCallback(FinishedWaitCB, this);\n\t\t\tbreak;\n\t\tcase WAITSTATE_FINISH_FLEE:\n\t\t\tSetMoveState(PEDMOVE_STILL);\n\t\t\tSetMoveAnim();\n\t\t\tm_headingRate = 0.0f;\n\t\t\tm_nWaitTimer = CTimer::GetTimeInMilliseconds() + 2500;\n\t\t\tanimAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_IDLE_TIRED, 4.0f);\n#ifdef FIX_BUGS\n\t\t\tanimAssoc->SetFinishCallback(RestoreHeadingRateCB, this);\n#endif\n\t\t\tbreak;\n\t\tcase WAITSTATE_SIT_DOWN:\n\t\t\tanimAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_SEAT_DOWN, 4.0f);\n\t\t\tanimAssoc->SetFinishCallback(FinishedWaitCB, this);\n\t\t\tm_nWaitTimer = CTimer::GetTimeInMilliseconds() + 100000;\n\t\t\tbreak;\n\t\tcase WAITSTATE_SIT_UP:\n\t\t\tanimAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_SEAT_UP, 4.0f);\n\t\t\tanimAssoc->SetFinishCallback(FinishedWaitCB, this);\n\t\t\tm_nWaitTimer = CTimer::GetTimeInMilliseconds() + 100000;\n\t\t\tbreak;\n\t\tcase WAITSTATE_SIT_IDLE:\n\t\t\tanimAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_SEAT_IDLE, 128.f);\n\t\t\tanimAssoc->SetFinishCallback(FinishedWaitCB, this);\n\t\t\tif (time)\n\t\t\t\tm_nWaitTimer = CTimer::GetTimeInMilliseconds() + *(int*)time;\n\t\t\telse\n\t\t\t\tm_nWaitTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(25000, 30000);\n\t\t\tbreak;\n\t\tcase WAITSTATE_USE_ATM:\n\t\t\tanimAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_ATM, 4.0f);\n\t\t\tanimAssoc->SetFinishCallback(FinishedWaitCB, this);\n\t\t\tif (time)\n\t\t\t\tm_nWaitTimer = CTimer::GetTimeInMilliseconds() + *(int*)time;\n\t\t\telse\n\t\t\t\tm_nWaitTimer = CTimer::GetTimeInMilliseconds() + 100000;\n\t\t\tbreak;\n\t\tcase WAITSTATE_SUN_BATHE_IDLE:\n\t\t\tm_headingRate = 0.0f;\n\t\t\tanimAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_SUNBATHE, ANIM_SUNBATHE_IDLE, 4.0f);\n\t\t\tanimAssoc->SetDeleteCallback(DeleteSunbatheIdleAnimCB, this);\n\t\t\tm_nWaitTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(50000, 100000);\n\t\t\tbreak;\n\t\tcase WAITSTATE_FAST_FALL:\n\t\t\tSetFall(-1, ANIM_STD_HIGHIMPACT_FRONT, true);\n\t\t\tbreak;\n\t\tcase WAITSTATE_BOMBER:\n\t\t\tCAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_DETONATE, 4.0f);\n\t\t\tm_nWaitTimer = CTimer::GetTimeInMilliseconds() + *(int*)time;\n\t\t\tbreak;\n\t\tcase WAITSTATE_GROUND_ATTACK:\n\t\t{\n\t\t\tCWeaponInfo* currentWeapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);\n\t\t\tif (!currentWeapon)\n\t\t\t\tbreak;\n\t\t\tif (GetFireAnimGround(currentWeapon, false)) {\n\t\t\t\tif (!RpAnimBlendClumpGetAssociation(GetClump(), GetFireAnimGround(currentWeapon, false))) {\n\t\t\t\t\tm_nWaitTimer = CTimer::GetTimeInMilliseconds() + 5000;\n\t\t\t\t\tCAnimBlendAssociation* newAnim = CAnimManager::BlendAnimation(GetClump(),\n\t\t\t\t\t\tcurrentWeapon->m_AnimToPlay, GetFireAnimGround(currentWeapon, false), 8.0f);\n\t\t\t\t\tnewAnim->SetDeleteCallback(FinishedWaitCB, this);\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tcase WAITSTATE_LANCESITTING:\n\t\t\tCAnimManager::BlendAnimation(GetClump(), ASSOCGRP_LANCE, ANIM_SUNBATHE_IDLE, 4.0f);\n\t\t\tbreak;\n\t\tcase WAITSTATE_PLAYANIM_HANDSUP_SIMPLE:\n\t\t\tanimAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_HANDSUP, 4.0f);\n\t\t\tanimAssoc->flags &= ~ASSOC_FADEOUTWHENDONE;\n\t\t\tanimAssoc->flags |= ASSOC_DELETEFADEDOUT;\n\t\t\tanimAssoc->SetDeleteCallback(FinishedWaitCB, this);\n\t\t\tm_nWaitTimer = CTimer::GetTimeInMilliseconds() + *(int*)time;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tClearWaitState();\n\t\t\tRestoreHeadingRate();\n\t\t\treturn;\n\t}\n\tm_nWaitState = state;\n}\n\nvoid\nCPed::Wait(void)\n{\n\tAnimationId mustHaveAnim = ANIM_STD_NUM;\n\tCAnimBlendAssociation *animAssoc;\n\tCPed *pedWeLook;\n\n\tif (DyingOrDead()) {\n\t\tClearWaitState();\n\t\tRestoreHeadingRate();\n\t\treturn;\n\t}\n\n\tswitch (m_nWaitState) {\n\n\t\tcase WAITSTATE_TRAFFIC_LIGHTS:\n\t\t\tif (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {\n\t\t\t\tif (CTrafficLights::LightForPeds() == PED_LIGHTS_WALK) {\n\t\t\t\t\tClearWaitState();\n\t\t\t\t\tSetMoveState(PEDMOVE_WALK);\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase WAITSTATE_CROSS_ROAD:\n\t\t\tif (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {\n\t\t\t\tif (CGeneral::GetRandomNumber() & 1 || !m_nWaitTimer)\n\t\t\t\t\tClearWaitState();\n\t\t\t\telse\n\t\t\t\t\tSetWaitState(WAITSTATE_CROSS_ROAD_LOOK, nil);\n\n\t\t\t\tanimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_IDLE_HBHB);\n\t\t\t\tif (animAssoc) {\n\t\t\t\t\tanimAssoc->blendDelta = -8.0f;\n\t\t\t\t\tanimAssoc->flags |= ASSOC_DELETEFADEDOUT;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase WAITSTATE_CROSS_ROAD_LOOK:\n\t\t\tif (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {\n\t\t\t\tClearWaitState();\n\t\t\t\tanimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_ROADCROSS);\n\t\t\t\tif (animAssoc) {\n\t\t\t\t\tanimAssoc->blendDelta = -8.0f;\n\t\t\t\t\tanimAssoc->flags |= ASSOC_DELETEFADEDOUT;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase WAITSTATE_DOUBLEBACK:\n\t\t\tif (CTimer::GetTimeInMilliseconds() <= m_nWaitTimer) {\n\t\t\t\tuint32 timeLeft = m_nWaitTimer - CTimer::GetTimeInMilliseconds();\n\t\t\t\tif (timeLeft < 2500 && timeLeft > 2000) {\n\t\t\t\t\tm_nWaitTimer -= 500;\n\t\t\t\t\tCAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_XPRESS_SCRATCH, 4.0f);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tClearWaitState();\n\t\t\t\tSetMoveState(PEDMOVE_WALK);\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase WAITSTATE_HITWALL:\n\t\t\tif (CTimer::GetTimeInMilliseconds() <= m_nWaitTimer) {\n\t\t\t\tif (m_collidingThingTimer > CTimer::GetTimeInMilliseconds()) {\n\t\t\t\t\tm_collidingThingTimer = CTimer::GetTimeInMilliseconds() + 2500;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tClearWaitState();\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase WAITSTATE_TURN180:\n\t\t\tif (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {\n\t\t\t\tClearWaitState();\n\t\t\t\tm_fRotationCur = m_fRotationCur + PI;\n\t\t\t\tif (m_nPedState == PED_INVESTIGATE)\n\t\t\t\t\tClearInvestigateEvent();\n\t\t\t}\n\n\t\t\tif (m_collidingThingTimer > CTimer::GetTimeInMilliseconds()) {\n\t\t\t\tm_collidingThingTimer = CTimer::GetTimeInMilliseconds() + 2500;\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase WAITSTATE_SURPRISE:\n\t\t\tif (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {\n\t\t\t\tif (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_HIT_WALL)) {\n\t\t\t\t\tanimAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_XPRESS_SCRATCH, 4.0f);\n\t\t\t\t\tanimAssoc->SetFinishCallback(FinishedWaitCB, this);\n\t\t\t\t\tm_nWaitTimer = CTimer::GetTimeInMilliseconds() + 5000;\n\t\t\t\t} else {\n\t\t\t\t\tClearWaitState();\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase WAITSTATE_STUCK:\n\t\t\tif (CTimer::GetTimeInMilliseconds() <= m_nWaitTimer)\n\t\t\t\tbreak;\n\n\t\t\tanimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_IDLE_TIRED);\n\n\t\t\tif (!animAssoc)\n\t\t\t\tanimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_TURN180);\n\t\t\tif (!animAssoc)\n\t\t\t\tanimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_XPRESS_SCRATCH);\n\t\t\tif (!animAssoc)\n\t\t\t\tanimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_ROADCROSS);\n\n\t\t\tif (animAssoc) {\n\t\t\t\tif (animAssoc->IsPartial()) {\n\t\t\t\t\tanimAssoc->blendDelta = -8.0f;\n\t\t\t\t\tanimAssoc->flags |= ASSOC_DELETEFADEDOUT;\n\t\t\t\t} else {\n\t\t\t\t\tanimAssoc->flags |= ASSOC_DELETEFADEDOUT;\n\t\t\t\t\tCAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_STD_IDLE, 4.0f);\n\t\t\t\t}\n\n\t\t\t\tif (animAssoc->animId == ANIM_STD_TURN180) {\n\t\t\t\t\tm_fRotationCur = CGeneral::LimitRadianAngle(PI + m_fRotationCur);\n\t\t\t\t\tClearWaitState();\n\t\t\t\t\tSetMoveState(PEDMOVE_WALK);\n\t\t\t\t\tm_nStoredMoveState = PEDMOVE_NONE;\n\t\t\t\t\tm_panicCounter = 0;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tAnimationId animToPlay;\n\n\t\t\tswitch (CGeneral::GetRandomNumber() & 3) {\n\t\t\t\tcase 0:\n\t\t\t\t\tanimToPlay = ANIM_STD_ROADCROSS;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 1:\n\t\t\t\t\tanimToPlay = ANIM_STD_IDLE_TIRED;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 2:\n\t\t\t\t\tanimToPlay = ANIM_STD_XPRESS_SCRATCH;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 3:\n\t\t\t\t\tanimToPlay = ANIM_STD_TURN180;\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tanimAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, animToPlay, 4.0f);\n\n\t\t\tif (animToPlay == ANIM_STD_TURN180)\n\t\t\t\tanimAssoc->SetFinishCallback(FinishedWaitCB, this);\n\n\t\t\tm_nWaitTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(1500, 5000);\n\t\t\tbreak;\n\n\t\tcase WAITSTATE_LOOK_ABOUT:\n\t\t\tif (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {\n\t\t\t\tClearWaitState();\n\t\t\t\tanimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_IDLE_HBHB);\n\t\t\t\tif (animAssoc) {\n\t\t\t\t\tanimAssoc->blendDelta = -8.0f;\n\t\t\t\t\tanimAssoc->flags |= ASSOC_DELETEFADEDOUT;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase WAITSTATE_PLAYANIM_HANDSUP:\n\t\t\tmustHaveAnim = ANIM_STD_HANDSUP;\n\t\t\t\n\t\tcase WAITSTATE_PLAYANIM_HANDSCOWER:\n\t\t\tif (mustHaveAnim == ANIM_STD_NUM)\n\t\t\t\tmustHaveAnim = ANIM_STD_HANDSCOWER;\n\n\t\t\tanimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), mustHaveAnim);\n\t\t\tpedWeLook = (CPed*) m_pLookTarget;\n\n\t\t\tif ((!m_pLookTarget || !m_pLookTarget->IsPed() || pedWeLook->m_pPointGunAt)\n\t\t\t\t&& m_nPedState != PED_FLEE_ENTITY\n\t\t\t\t&& m_nPedState != PED_ATTACK\n\t\t\t\t&& CTimer::GetTimeInMilliseconds() <= m_nWaitTimer\n\t\t\t\t&& animAssoc) {\n\n\t\t\t\tif (pedWeLook)\n\t\t\t\t\tTurnBody();\n\t\t\t} else {\n\t\t\t\tClearWaitState();\n\t\t\t\tm_nWaitTimer = 0;\n\t\t\t\tif (m_pLookTarget && m_pLookTarget->IsPed()) {\n\t\t\t\t\tif (m_nPedState != PED_FLEE_ENTITY && m_nPedState != PED_ATTACK) {\n\t\t\t\t\t\tif (bCrouchWhenScared) {\n\t\t\t\t\t\t\tif (bIsDucking) {\n\t\t\t\t\t\t\t\tClearDuck(false);\n\t\t\t\t\t\t\t\tSetDuck(10000, true);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t} else if (m_pedStats->m_fear <= 100 - pedWeLook->m_pedStats->m_temper) {\n\t\t\t\t\t\t\tif (GetWeapon()->IsTypeMelee()) {\n\t\t\t\t\t\t\t\tif(m_pedStats->m_flags & STAT_GUN_PANIC) {\n\t\t\t\t\t\t\t\t\tSetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE, m_pLookTarget);\n\t\t\t\t\t\t\t\t\tif (m_nPedState == PED_FLEE_ENTITY || m_nPedState == PED_FLEE_POS) {\n\n\t\t\t\t\t\t\t\t\t\tbUsePedNodeSeek = true;\n\t\t\t\t\t\t\t\t\t\tm_pNextPathNode = nil;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tif (m_nMoveState != PEDMOVE_RUN)\n\t\t\t\t\t\t\t\t\t\tSetMoveState(PEDMOVE_WALK);\n\n\t\t\t\t\t\t\t\t\tif (m_nPedType != PEDTYPE_COP) {\n\t\t\t\t\t\t\t\t\t\tProcessObjective();\n\t\t\t\t\t\t\t\t\t\tSetMoveState(PEDMOVE_WALK);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tSetObjective(OBJECTIVE_NONE);\n\t\t\t\t\t\t\t\t\tSetWanderPath(CGeneral::GetRandomNumberInRange(0.0f, 8.0f));\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tSetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, m_pLookTarget);\n\t\t\t\t\t\t\t\tSetObjectiveTimer(20000);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tSetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE, m_pLookTarget);\n\t\t\t\t\t\t\tif (m_nPedState == PED_FLEE_ENTITY || m_nPedState == PED_FLEE_POS)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tbUsePedNodeSeek = true;\n\t\t\t\t\t\t\t\tm_pNextPathNode = nil;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tSetMoveState(PEDMOVE_RUN);\n\t\t\t\t\t\t\tSay(SOUND_PED_FLEE_RUN);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tanimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), mustHaveAnim);\n\t\t\t\tif (animAssoc) {\n\t\t\t\t\tanimAssoc->blendDelta = -4.0f;\n\t\t\t\t\tanimAssoc->flags |= ASSOC_DELETEFADEDOUT;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\tcase WAITSTATE_PLAYANIM_COWER:\n\t\t\tmustHaveAnim = ANIM_STD_HANDSCOWER;\n\n\t\tcase WAITSTATE_PLAYANIM_DUCK:\n\t\t\tif (mustHaveAnim == ANIM_STD_NUM)\n\t\t\t\tmustHaveAnim = ANIM_STD_DUCK_DOWN;\n\n\t\tcase WAITSTATE_PLAYANIM_TAXI:\n\t\t\tif (mustHaveAnim == ANIM_STD_NUM)\n\t\t\t\tmustHaveAnim = ANIM_STD_HAILTAXI;\n\n\t\tcase WAITSTATE_PLAYANIM_CHAT:\n\t\t\tif (mustHaveAnim == ANIM_STD_NUM)\n\t\t\t\tmustHaveAnim = ANIM_STD_CHAT;\n\n\t\t\tif (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {\n\t\t\t\tanimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), mustHaveAnim);\n\t\t\t\tif (animAssoc) {\n\t\t\t\t\tanimAssoc->blendDelta = -4.0f;\n\t\t\t\t\tanimAssoc->flags |= ASSOC_DELETEFADEDOUT;\n\t\t\t\t}\n\t\t\t\tif (m_attractor && m_objective == OBJECTIVE_WAIT_ON_FOOT_AT_ICE_CREAM_VAN) {\n\t\t\t\t\tGetPedAttractorManager()->BroadcastDeparture(this, m_attractor);\n\t\t\t\t\tbBoughtIceCream = true;\n\t\t\t\t}\n\t\t\t\tClearWaitState();\n\t\t\t} else if (m_nWaitState == WAITSTATE_PLAYANIM_TAXI) {\n\t\t\t\tif (m_pedInObjective) {\n\t\t\t\t\tif (m_objective == OBJECTIVE_GOTO_CHAR_ON_FOOT || m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT) {\n\n\t\t\t\t\t\tif (m_pLookTarget)\n\t\t\t\t\t\t\tm_pLookTarget->CleanUpOldReference(&m_pLookTarget);\n\t\t\t\t\t\tm_pLookTarget = m_pedInObjective;\n\t\t\t\t\t\tm_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget);\n\t\t\t\t\t\tTurnBody();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase WAITSTATE_FINISH_FLEE:\n\t\t\tanimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_IDLE_TIRED);\n\t\t\tif (animAssoc) {\n\t\t\t\tif (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {\n\t\t\t\t\tanimAssoc->flags |= ASSOC_DELETEFADEDOUT;\n\t\t\t\t\tCAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_STD_IDLE, 4.0f);\n\t\t\t\t\tint timer = 2000;\n\t\t\t\t\tClearWaitState();\n\t\t\t\t\tSetWaitState(WAITSTATE_CROSS_ROAD_LOOK, &timer);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tClearWaitState();\n\t\t\t}\n\t\t\tbreak;\n\t\tcase WAITSTATE_SIT_DOWN:\n\t\t\tif (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {\n\t\t\t\tClearWaitState();\n\t\t\t\tSetWaitState(WAITSTATE_SIT_IDLE, 0);\n\t\t\t}\n\t\t\tbreak;\n\t\t//case WAITSTATE_SIT_DOWN_RVRS:\n\t\tcase WAITSTATE_SIT_UP:\n\t\t\tif (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {\n\t\t\t\tif (m_attractor)\n\t\t\t\t\tGetPedAttractorManager()->BroadcastDeparture(this, m_attractor);\n\t\t\t\tClearWaitState();\n\t\t\t\tif (bFleeWhenStanding) {\n\t\t\t\t\tif (m_threatEx) {\n\t\t\t\t\t\tSetFlee(m_threatEx, 10000);\n\t\t\t\t\t\tbFleeWhenStanding = false;\n\t\t\t\t\t\tm_threatEx = nil;\n\t\t\t\t\t\tSay(SOUND_PED_FLEE_SPRINT);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\tcase WAITSTATE_SIT_IDLE:\n\t\t\tif (bTurnedAroundOnAttractor) {\n\t\t\t\tm_fRotationCur += PI;\n\t\t\t\tm_fRotationCur = CGeneral::LimitRadianAngle(m_fRotationCur);\n\t\t\t\tm_fRotationDest = m_fRotationCur;\n\t\t\t\tbTurnedAroundOnAttractor = false;\n\t\t\t}\n\t\t\tif (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {\n\t\t\t\tClearWaitState();\n\t\t\t\tSetWaitState(WAITSTATE_SIT_UP, 0);\n\t\t\t} else {\n\t\t\t\tif (m_fleeFrom && m_fleeFrom->IsVehicle()) {\n\t\t\t\t\tm_pNextPathNode = nil;\n\t\t\t\t\tm_threatEx = m_threatEntity;\n\t\t\t\t\tbFleeWhenStanding = true;\n\t\t\t\t\tClearWaitState();\n\t\t\t\t\tSetWaitState(WAITSTATE_SIT_UP, 0);\n\t\t\t\t} else {\n\t\t\t\t\tuint32 threatFlag = ScanForThreats();\n\t\t\t\t\tif (threatFlag == PED_FLAG_GUN || threatFlag == PED_FLAG_EXPLOSION || threatFlag == PED_FLAG_DEADPEDS) {\n\t\t\t\t\t\tm_pNextPathNode = nil;\n\t\t\t\t\t\tm_threatEx = m_threatEntity;\n\t\t\t\t\t\tbFleeWhenStanding = true;\n\t\t\t\t\t\tClearWaitState();\n\t\t\t\t\t\tSetWaitState(WAITSTATE_SIT_UP, 0);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\tcase WAITSTATE_USE_ATM:\n\t\t\tif (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {\n\t\t\t\tif (m_attractor)\n\t\t\t\t\tGetPedAttractorManager()->BroadcastDeparture(this, m_attractor);\n\t\t\t\tClearWaitState();\n\t\t\t}\n\t\t\tbreak;\n\t\tcase WAITSTATE_SUN_BATHE_IDLE:\n\t\t\tif (CTimer::GetTimeInMilliseconds() > m_nWaitTimer && bCanGiveUpSunbathing) {\n\t\t\t\tm_pNextPathNode = nil;\n\t\t\t\tbGotUpOfMyOwnAccord = true;\n\t\t\t\tSetGetUp();\n\t\t\t\tClearWaitState();\n\n\t\t\t} else if (CWeather::Rain <= 0.1f) {\n\t\t\t\tif (CClock::GetHours() <= 18 || CGeneral::GetRandomNumberInRange(0.f, 1.0f) < 0.005f) {\n\t\t\t\t\tuint32 threatFlag = ScanForThreats();\n\t\t\t\t\tif (threatFlag == PED_FLAG_GUN || threatFlag == PED_FLAG_EXPLOSION || threatFlag == PED_FLAG_DEADPEDS) {\n\t\t\t\t\t\t// Get up in case of danger\n\t\t\t\t\t\tm_pNextPathNode = nil;\n\t\t\t\t\t\tm_threatEx = m_threatEntity;\n\t\t\t\t\t\tbFleeWhenStanding = true;\n\t\t\t\t\t\tSetGetUp();\n\t\t\t\t\t\tClearWaitState();\n\t\t\t\t\t}\n\t\t\t\t\tCPlayerPed *player = FindPlayerPed();\n\t\t\t\t\tif (player) {\n\t\t\t\t\t\t// Get up if player coming towards us with a car\n\t\t\t\t\t\tif (player->InVehicle()){\n\t\t\t\t\t\t\tCVector vehSpeedPerSec = player->m_pMyVehicle->m_vecMoveSpeed * GAME_SPEED_TO_METERS_PER_SECOND;\n\t\t\t\t\t\t\tCVector vehPos = player->m_pMyVehicle->GetPosition();\n\t\t\t\t\t\t\tCVector ourPos = GetPosition();\n\t\t\t\t\t\t\tfloat timeUntilVehReachPed = DotProduct(ourPos - vehPos, vehSpeedPerSec) / vehSpeedPerSec.MagnitudeSqr();\n\t\t\t\t\t\t\tif (timeUntilVehReachPed > 0.0 && timeUntilVehReachPed < 8.0f) {\n\t\t\t\t\t\t\t\tif ((ourPos - (timeUntilVehReachPed * vehSpeedPerSec + vehPos)).Magnitude() < 5.0f) {\n\t\t\t\t\t\t\t\t\tm_pNextPathNode = nil;\n\t\t\t\t\t\t\t\t\tm_threatEx = player;\n\t\t\t\t\t\t\t\t\tbFleeWhenStanding = true;\n\t\t\t\t\t\t\t\t\tSetGetUp();\n\t\t\t\t\t\t\t\t\tClearWaitState();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tm_pNextPathNode = nil;\n\t\t\t\t\tbGotUpOfMyOwnAccord = true;\n\t\t\t\t\tSetGetUp();\n\t\t\t\t\tClearWaitState();\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tm_pNextPathNode = nil;\n\t\t\t\tbGotUpOfMyOwnAccord = true;\n\t\t\t\tSetGetUp();\n\t\t\t\tClearWaitState();\n\t\t\t}\n\t\t\tbreak;\n\t\tcase WAITSTATE_RIOT:\n\t\t\tif (m_nPedState == PED_FLEE_ENTITY || m_nPedState == PED_ATTACK) {\n\t\t\t\tClearWaitState();\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tPlayRandomAnimationsFromAnimBlock(this, ASSOCGRP_RIOT, ANIM_RIOT_ANGRY, ANIM_RIOT_FUCKYOU - ANIM_RIOT_ANGRY + 1);\n\t\t\tif (IsPedInControl() && CGeneral::GetRandomNumberInRange(0.f,1.f) < 0.25f\n\t\t\t\t&& CPopulation::CanJeerAtStripper(m_modelIndex)) {\n\t\t\t\tfor (int i = 0; i < m_numNearPeds; ++i) {\n\t\t\t\t\tCPed *nearPed = m_nearPeds[i];\n\t\t\t\t\tif (nearPed) {\n\t\t\t\t\t\tif ((GetPosition() - nearPed->GetPosition()).MagnitudeSqr() < sq(10.f)) {\n\t\t\t\t\t\t\tfor (int anim = ANIM_STRIP_A; anim <= ANIM_STRIP_G; anim++) {\n\t\t\t\t\t\t\t\tif (RpAnimBlendClumpGetAssociation(nearPed->GetClump(), anim))\n\t\t\t\t\t\t\t\t\tSay(SOUND_PED_149);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\tcase WAITSTATE_BOMBER:\n\t\t\tif (CTimer::GetTimeInMilliseconds() > m_nWaitTimer)\n\t\t\t\tClearWaitState();\n\t\t\tbreak;\n\t\tcase WAITSTATE_STRIPPER:\n\t\t\tPlayRandomAnimationsFromAnimBlock(this, ASSOCGRP_STRIP, ANIM_STRIP_A, ANIM_STRIP_G - ANIM_STRIP_A + 1);\n\t\t\tbreak;\n\t\tcase WAITSTATE_PLAYANIM_HANDSUP_SIMPLE:\n\t\t\tif (CTimer::GetTimeInMilliseconds() > m_nWaitTimer)\n\t\t\t\tClearWaitState();\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\n\tif(!m_nWaitState)\n\t\tRestoreHeadingRate();\n}\n\nvoid\nCPed::DeleteSunbatheIdleAnimCB(CAnimBlendAssociation *assoc, void *arg)\n{\n\tCPed *ped = (CPed*) arg;\n\n\tif (CTimer::GetTimeInMilliseconds() <= ped->m_nWaitTimer\n\t\t&& !ped->bGotUpOfMyOwnAccord && !ped->bFleeWhenStanding && !ped->m_threatEx) {\n\t\tped->m_pNextPathNode = nil;\n\t\tped->bFleeWhenStanding = true;\n\t\tped->m_threatEx = FindPlayerPed();\n\t\tped->SetGetUp();\n\t\tped->ClearWaitState();\n\t}\n\tped->m_nWaitTimer = 0;\n\tped->RestoreHeadingRate();\n\tped->Wait();\n}\n\nvoid\nCPed::FinishedWaitCB(CAnimBlendAssociation *animAssoc, void *arg)\n{\n\tCPed *ped = (CPed*)arg;\n\n\tped->m_nWaitTimer = 0;\n\tped->RestoreHeadingRate();\n\tped->Wait();\n}\n\nvoid\nCPed::RestoreHeadingRate(void)\n{\n\tm_headingRate = m_pedStats->m_headingChangeRate;\n}\n\nvoid\nCPed::RestoreHeadingRateCB(CAnimBlendAssociation *assoc, void *arg)\n{\n\t((CPed*)arg)->RestoreHeadingRate();\n}\n\nvoid\nCPed::FlagToDestroyWhenNextProcessed(void)\n{\n\tbRemoveFromWorld = true;\n\tif (!InVehicle())\n\t\treturn;\n\tif (m_pMyVehicle->pDriver == this){\n\t\tm_pMyVehicle->pDriver = nil;\n\t\tif (IsPlayer() && m_pMyVehicle->GetStatus() != STATUS_WRECKED)\n\t\t\tm_pMyVehicle->SetStatus(STATUS_ABANDONED);\n\t}else{\n\t\tm_pMyVehicle->RemovePassenger(this);\n\t}\n\tbInVehicle = false;\n\tm_pMyVehicle = nil;\n\n\tif (CharCreatedBy == MISSION_CHAR)\n\t\tSetPedState(PED_DEAD);\n\telse\n\t\tSetPedState(PED_NONE);\n\tm_pVehicleAnim = nil;\n}\n\nvoid\nCPed::SetSolicit(uint32 time)\n{\n\tif (m_nPedState == PED_SOLICIT || !IsPedInControl() || !m_carInObjective)\n\t\treturn;\n\n\tif (CharCreatedBy != MISSION_CHAR && m_carInObjective->m_nNumGettingIn == 0\n\t\t&& CTimer::GetTimeInMilliseconds() < m_objectiveTimer) {\n\t\tif (m_vehDoor == CAR_DOOR_LF) {\n\t\t\tm_fRotationDest = m_carInObjective->GetForward().Heading() - HALFPI;\n\t\t} else {\n\t\t\tm_fRotationDest = m_carInObjective->GetForward().Heading() + HALFPI;\n\t\t}\n\n\t\tif (Abs(m_fRotationDest - m_fRotationCur) < HALFPI) {\n\t\t\tm_chatTimer = CTimer::GetTimeInMilliseconds() + time;\n\n\t\t\tif(!m_carInObjective->bIsVan && !m_carInObjective->bIsBus)\n\t\t\t\tm_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_HOOKERTALK, 4.0f);\n\n\t\t\tSetPedState(PED_SOLICIT);\n\t\t}\n\t}\n}\n\nvoid\nCPed::Solicit(void)\n{\n\tif (m_chatTimer >= CTimer::GetTimeInMilliseconds() && m_carInObjective) {\n\t\tCVector doorPos = GetPositionToOpenCarDoor(m_carInObjective, m_vehDoor, 0.0f);\n\t\tSay(SOUND_PED_SOLICIT);\n\t\tif (FindPlayerVehicle() == m_carInObjective) {\n\t\t\tFindPlayerPed()->Say(SOUND_PED_SOLICIT);\n\t\t}\n\t\tSetMoveState(PEDMOVE_STILL);\n\n\t\t// Game uses GetAngleBetweenPoints and converts it to radian\n\t\tm_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(\n\t\t\tdoorPos.x, doorPos.y,\n\t\t\tGetPosition().x, GetPosition().y);\n\n\t\tif (m_fRotationDest < 0.0f) {\n\t\t\tm_fRotationDest += TWOPI;\n\t\t} else if (m_fRotationDest > TWOPI) {\n\t\t\tm_fRotationDest -= TWOPI;\n\t\t}\n\n\t\tif ((GetPosition() - doorPos).MagnitudeSqr() <= 1.0f)\n\t\t\treturn;\n\t\tCAnimBlendAssociation *talkAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_CAR_HOOKERTALK);\n\t\tif (talkAssoc) {\n\t\t\ttalkAssoc->blendDelta = -1000.0f;\n\t\t\ttalkAssoc->flags |= ASSOC_DELETEFADEDOUT;\n\t\t}\n\t\tRestorePreviousState();\n\t\tRestorePreviousObjective();\n\t\tSetObjectiveTimer(10000);\n\t} else if (!m_carInObjective) {\n\t\tRestorePreviousState();\n\t\tRestorePreviousObjective();\n\t\tSetObjectiveTimer(10000);\n\t} else if (CWorld::Players[CWorld::PlayerInFocus].m_nMoney <= 100) {\n\t\tm_carInObjective = nil;\n\t} else {\n\t\tm_pVehicleAnim = nil;\n\t\tSetLeader(m_carInObjective->pDriver);\n\t\tSay(SOUND_PED_SOLICIT);\n\t}\n}\n\nvoid\nCPed::SetBuyIceCream(void)\n{\n\tif (m_nPedState == PED_BUY_ICECREAM || !IsPedInControl())\n\t\treturn;\n\n\tif (!m_carInObjective)\n\t\treturn;\n\n\tSetPedState(PED_BUY_ICECREAM);\n}\n\nvoid\nCPed::BuyIceCream(void)\n{\n\tif (m_carInObjective) {\n\t\tCPed *driver = m_carInObjective->pDriver;\n\t\tif (driver && CTimer::GetTimeInMilliseconds() > m_chatTimer) {\n\t\t\tSetChat(driver, 8000);\n\t\t\tdriver->SetChat(this, 8000);\n\t\t\treturn;\n\t\t}\n\t\tSetObjective(OBJECTIVE_NONE);\n\t\tSetWanderPath(CGeneral::GetRandomNumberInRange(0, 8));\n\t} else {\n\t\tSetObjective(OBJECTIVE_NONE);\n\t\tSetWanderPath(CGeneral::GetRandomNumberInRange(0, 8));\n\t}\n}\n\nbool\nCPed::PossiblyFindBetterPosToSeekCar(CVector *pos, CVehicle *veh)\n{\n\tbool foundIt = false;\n\n\tCVector helperPos = GetPosition();\n\thelperPos.z = pos->z - 0.5f;\n\n\tCVector foundPos = *pos;\n\tfoundPos.z -= 0.5f;\n\n\t// If there is another car between target car and us.\n\tif (CWorld::TestSphereAgainstWorld((foundPos + helperPos) / 2.0f, 0.25f, veh, false, true, false, false, false, false)) {\n\n\t\tCColModel *vehCol = veh->GetModelInfo()->GetColModel();\n\t\tCVector *colMin = &vehCol->boundingBox.min;\n\t\tCVector *colMax = &vehCol->boundingBox.max;\n\n\t\tCVector leftRearPos = CVector(colMin->x - 0.5f, colMin->y - 0.5f, 0.0f);\n\t\tCVector rightRearPos = CVector(0.5f + colMax->x, colMin->y - 0.5f, 0.0f);\n\t\tCVector leftFrontPos = CVector(colMin->x - 0.5f, 0.5f + colMax->y, 0.0f);\n\t\tCVector rightFrontPos = CVector(0.5f + colMax->x, 0.5f + colMax->y, 0.0f);\n\n\t\tleftRearPos = veh->GetMatrix() * leftRearPos;\n\t\trightRearPos = veh->GetMatrix() * rightRearPos;\n\t\tleftFrontPos = veh->GetMatrix() * leftFrontPos;\n\t\trightFrontPos = veh->GetMatrix() * rightFrontPos;\n\n\t\t// Makes helperPos veh-ped distance vector.\n\t\thelperPos -= veh->GetPosition();\n\n\t\t// ?!? I think it's absurd to use this unless another function like SeekCar finds next pos. with it and we're trying to simulate it's behaviour.\n\t\t// On every run it returns another pos. for ped, with same distance to the veh.\n\t\t// Sequence of positions are not guaranteed, it depends on global pos. (So sometimes it returns positions to make ped draw circle, sometimes don't)\n\t\thelperPos = veh->GetMatrix() * helperPos;\n\n\t\tfloat vehForwardHeading = veh->GetForward().Heading();\n\n\t\t// I'm absolutely not sure about these namings.\n\t\t// NTVF = needed turn if we're looking to vehicle front and wanna look to...\n\n\t\tfloat potentialLrHeading = Atan2(leftRearPos.x - helperPos.x, leftRearPos.y - helperPos.y);\n\t\tfloat NTVF_LR = CGeneral::LimitRadianAngle(potentialLrHeading - vehForwardHeading);\n\n\t\tfloat potentialRrHeading = Atan2(rightRearPos.x - helperPos.x, rightRearPos.y - helperPos.y);\n\t\tfloat NTVF_RR = CGeneral::LimitRadianAngle(potentialRrHeading - vehForwardHeading);\n\n\t\tfloat potentialLfHeading = Atan2(leftFrontPos.x - helperPos.x, leftFrontPos.y - helperPos.y);\n\t\tfloat NTVF_LF = CGeneral::LimitRadianAngle(potentialLfHeading - vehForwardHeading);\n\n\t\tfloat potentialRfHeading = Atan2(rightFrontPos.x - helperPos.x, rightFrontPos.y - helperPos.y);\n\t\tfloat NTVF_RF = CGeneral::LimitRadianAngle(potentialRfHeading - vehForwardHeading);\n\n\t\tbool canHeadToLr = NTVF_LR <= -PI || NTVF_LR >= -HALFPI;\n\n\t\tbool canHeadToRr = NTVF_RR <= HALFPI || NTVF_RR >= PI;\n\n\t\tbool canHeadToLf = NTVF_LF >= 0.0f || NTVF_LF <= -HALFPI;\n\n\t\tbool canHeadToRf = NTVF_RF <= 0.0f || NTVF_RF >= HALFPI;\n\n\t\t// Only order of conditions are different among enterTypes.\n\t\tif (m_vehDoor == CAR_DOOR_RR) {\n\t\t\tif (canHeadToRr) {\n\t\t\t\tfoundPos = rightRearPos;\n\t\t\t\tfoundIt = true;\n\t\t\t} else if (canHeadToRf) {\n\t\t\t\tfoundPos = rightFrontPos;\n\t\t\t\tfoundIt = true;\n\t\t\t} else if (canHeadToLr) {\n\t\t\t\tfoundPos = leftRearPos;\n\t\t\t\tfoundIt = true;\n\t\t\t} else if (canHeadToLf) {\n\t\t\t\tfoundPos = leftFrontPos;\n\t\t\t\tfoundIt = true;\n\t\t\t}\n\t\t} else if(m_vehDoor == CAR_DOOR_RF) {\n\t\t\tif (canHeadToRf) {\n\t\t\t\tfoundPos = rightFrontPos;\n\t\t\t\tfoundIt = true;\n\t\t\t} else if (canHeadToRr) {\n\t\t\t\tfoundPos = rightRearPos;\n\t\t\t\tfoundIt = true;\n\t\t\t} else if (canHeadToLf) {\n\t\t\t\tfoundPos = leftFrontPos;\n\t\t\t\tfoundIt = true;\n\t\t\t} else if (canHeadToLr) {\n\t\t\t\tfoundPos = leftRearPos;\n\t\t\t\tfoundIt = true;\n\t\t\t}\n\t\t} else if (m_vehDoor == CAR_DOOR_LF) {\n\t\t\tif (canHeadToLf) {\n\t\t\t\tfoundPos = leftFrontPos;\n\t\t\t\tfoundIt = true;\n\t\t\t} else if (canHeadToLr) {\n\t\t\t\tfoundPos = leftRearPos;\n\t\t\t\tfoundIt = true;\n\t\t\t} else if (canHeadToRf) {\n\t\t\t\tfoundPos = rightFrontPos;\n\t\t\t\tfoundIt = true;\n\t\t\t} else if (canHeadToRr) {\n\t\t\t\tfoundPos = rightRearPos;\n\t\t\t\tfoundIt = true;\n\t\t\t}\n\t\t} else if (m_vehDoor == CAR_DOOR_LR) {\n\t\t\tif (canHeadToLr) {\n\t\t\t\tfoundPos = leftRearPos;\n\t\t\t\tfoundIt = true;\n\t\t\t} else if (canHeadToLf) {\n\t\t\t\tfoundPos = leftFrontPos;\n\t\t\t\tfoundIt = true;\n\t\t\t} else if (canHeadToRr) {\n\t\t\t\tfoundPos = rightRearPos;\n\t\t\t\tfoundIt = true;\n\t\t\t} else if (canHeadToRf) {\n\t\t\t\tfoundPos = rightFrontPos;\n\t\t\t\tfoundIt = true;\n\t\t\t}\n\t\t}\n\t}\n\tif (!foundIt)\n\t\treturn false;\n\n\thelperPos = GetPosition() - foundPos;\n\thelperPos.z = 0.0f;\n\tif (helperPos.MagnitudeSqr() <= sq(0.5f))\n\t\treturn false;\n\n\tpos->x = foundPos.x;\n\tpos->y = foundPos.y;\n\treturn true;\n}\n\nvoid\nCPed::SetLeader(CEntity *leader)\n{\n\tm_leader = (CPed*)leader;\n\n\tif (m_leader) {\n\t\tm_leader->bIsLeader = true;\n\t\tm_leader->RegisterReference((CEntity**)&m_leader);\n\t}\n}\n\nbool\nCPed::CanPedJumpThis(CEntity *unused, CVector *damageNormal)\n{\n\tif (m_nSurfaceTouched == SURFACE_WATER)\n\t\treturn true;\n\n\tCVector pos = GetPosition();\n\tCVector forwardOffset = GetForward();\n\tif (damageNormal && damageNormal->z > 0.17f) {\n\t\tif (damageNormal->z > 0.9f)\n\t\t\treturn false;\n\n\t\tCColModel *ourCol = GetColModel();\n\t\tpos.z = ourCol->spheres->center.z - ourCol->spheres->radius * damageNormal->z + pos.z;\n\t\tpos.z = pos.z + 0.05f;\n\t\tfloat collPower = damageNormal->Magnitude2D();\n\t\tif (damageNormal->z > 0.5f) {\n\t\t\tCVector invDamageNormal(-damageNormal->x, -damageNormal->y, 0.0f);\n\t\t\tinvDamageNormal *= 1.0f / collPower;\n\t\t\tCVector estimatedJumpDist = invDamageNormal + collPower * invDamageNormal * ourCol->spheres->radius;\n\t\t\tforwardOffset = estimatedJumpDist * Min(2.0f / collPower, 4.0f);\n\t\t} else {\n\t\t\tforwardOffset += collPower * ourCol->spheres->radius * forwardOffset;\n\t\t}\n\t} else {\n\t\tpos.z -= 0.15f;\n\t}\n\n\tCVector forwardPos = pos + forwardOffset;\n\treturn CWorld::GetIsLineOfSightClear(pos, forwardPos, true, false, false, true, false, false, false);\n}\n\nvoid\nCPed::SetJump(void)\n{\n\tif (!bInVehicle && m_nPedState != PED_JUMP && !RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_JUMP_LAUNCH) &&\n\t\t(m_nSurfaceTouched != SURFACE_STEEP_CLIFF || DotProduct(GetForward(), m_vecDamageNormal) >= 0.0f)) {\n\n\t\tSetStoredState();\n\t\tSetPedState(PED_JUMP);\n\t\tCAnimBlendAssociation *jumpAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_JUMP_LAUNCH, 8.0f);\n\t\tjumpAssoc->SetFinishCallback(FinishLaunchCB, this);\n\t\tm_fRotationDest = m_fRotationCur;\n\t}\n}\n\nvoid\nCPed::FinishLaunchCB(CAnimBlendAssociation *animAssoc, void *arg)\n{\n\tCPed *ped = (CPed*)arg;\n\n\tif (ped->m_nPedState != PED_JUMP)\n\t\treturn;\n\n\tCVector forward(0.09f * ped->GetForward() + ped->GetPosition());\n\tforward.z += CModelInfo::GetModelInfo(ped->GetModelIndex())->GetColModel()->spheres[2].center.z + 0.35f;\n\n\tCEntity *obstacle = CWorld::TestSphereAgainstWorld(forward, 0.25f, nil, true, true, false, true, false, false);\n\tif (!obstacle) {\n\t\t// Forward of forward\n\t\tforward += 0.15f * ped->GetForward();\n\t\tforward.z += 0.15f;\n\t\tobstacle = CWorld::TestSphereAgainstWorld(forward, 0.25f, nil, true, true, false, true, false, false);\n\t}\n\n\tif (!obstacle && CCullZones::CamStairsForPlayer() && CCullZones::FindZoneWithStairsAttributeForPlayer())\n\t\tobstacle = ped;\n\n\tif (obstacle) {\n\t\tanimAssoc->flags |= ASSOC_DELETEFADEDOUT;\n\t\tCAnimBlendAssociation *handsCoverAssoc = CAnimManager::BlendAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_HIT_WALL, 8.0f);\n\t\thandsCoverAssoc->flags &= ~ASSOC_FADEOUTWHENDONE;\n\t\thandsCoverAssoc->SetFinishCallback(FinishHitHeadCB, ped);\n\t\tped->bIsLanding = true;\n\t\treturn;\n\t}\n\n\tfloat velocityFromAnim = 0.1f;\n\tCAnimBlendAssociation *sprintAssoc = RpAnimBlendClumpGetAssociation(ped->GetClump(), ANIM_STD_RUNFAST);\n\n\tif (sprintAssoc) {\n\t\tvelocityFromAnim = 0.05f * sprintAssoc->blendAmount + 0.17f;\n\t} else {\n\t\tCAnimBlendAssociation *runAssoc = RpAnimBlendClumpGetAssociation(ped->GetClump(), ANIM_STD_RUN);\n\t\tif (runAssoc) {\n\t\t\tvelocityFromAnim = 0.07f * runAssoc->blendAmount + 0.1f;\n\t\t}\n\t}\n\n\tif (ped->IsPlayer() || ped->m_pedInObjective && ped->m_pedInObjective->IsPlayer())\n\t\tped->ApplyMoveForce(0.0f, 0.0f, 8.5f);\n\telse\n\t\tped->ApplyMoveForce(0.0f, 0.0f, 4.5f);\n\t\n\tif (sq(velocityFromAnim) > ped->m_vecMoveSpeed.MagnitudeSqr2D() || ped->m_pCurrentPhysSurface) {\n\n#ifdef FREE_CAM\n\t\tif (TheCamera.Cams[0].Using3rdPersonMouseCam() && !CCamera::bFreeCam) {\n#else\n\t\tif (TheCamera.Cams[0].Using3rdPersonMouseCam()) {\n#endif\n\t\t\tfloat fpsAngle = ped->WorkOutHeadingForMovingFirstPerson(ped->m_fRotationCur);\n\t\t\tped->m_vecMoveSpeed.x = -velocityFromAnim * Sin(fpsAngle);\n\t\t\tped->m_vecMoveSpeed.y = velocityFromAnim * Cos(fpsAngle);\n\t\t} else {\n\t\t\tped->m_vecMoveSpeed.x = -velocityFromAnim * Sin(ped->m_fRotationCur);\n\t\t\tped->m_vecMoveSpeed.y = velocityFromAnim * Cos(ped->m_fRotationCur);\n\t\t}\n\n\t\tif (ped->m_pCurrentPhysSurface) {\n\t\t\tped->m_vecMoveSpeed.x += ped->m_pCurrentPhysSurface->m_vecMoveSpeed.x;\n\t\t\tped->m_vecMoveSpeed.y += ped->m_pCurrentPhysSurface->m_vecMoveSpeed.y;\n\t\t}\n\t}\n\n\tped->bIsStanding = false;\n\tped->bIsInTheAir = true;\n\tanimAssoc->blendDelta = -1000.0f;\n\tCAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_JUMP_GLIDE);\n\n\tif (ped->bDoBloodyFootprints) {\n\t\tCVector bloodPos(0.0f, 0.0f, 0.0f);\n\t\tped->TransformToNode(bloodPos, PED_FOOTL);\n\n\t\tbloodPos.z -= 0.1f;\n\t\tbloodPos += 0.2f * ped->GetForward();\n\n\t\tCShadows::AddPermanentShadow(SHADOWTYPE_DARK, gpBloodPoolTex, &bloodPos,\n\t\t\t0.26f * ped->GetForward().x,\n\t\t\t0.26f * ped->GetForward().y,\n\t\t\t0.14f * ped->GetRight().x,\n\t\t\t0.14f * ped->GetRight().y,\n\t\t\t255, 255, 0, 0, 4.0f, 3000, 1.0f);\n\n\t\tbloodPos = CVector(0.0f, 0.0f, 0.0f);\n\t\tped->TransformToNode(bloodPos, PED_FOOTR);\n\n\t\tbloodPos.z -= 0.1f;\n\t\tbloodPos += 0.2f * ped->GetForward();\n\t\tCShadows::AddPermanentShadow(SHADOWTYPE_DARK, gpBloodPoolTex, &bloodPos,\n\t\t\t0.26f * ped->GetForward().x,\n\t\t\t0.26f * ped->GetForward().y,\n\t\t\t0.14f * ped->GetRight().x,\n\t\t\t0.14f * ped->GetRight().y,\n\t\t\t255, 255, 0, 0, 4.0f, 3000, 1.0f);\n\n\t\tif (ped->m_bloodyFootprintCountOrDeathTime <= 40) {\n\t\t\tped->m_bloodyFootprintCountOrDeathTime = 0;\n\t\t\tped->bDoBloodyFootprints = false;\n\t\t} else {\n\t\t\tped->m_bloodyFootprintCountOrDeathTime -= 40;\n\t\t}\n\t}\n}\n\nvoid\nCPed::FinishJumpCB(CAnimBlendAssociation *animAssoc, void *arg)\n{\n\tCPed *ped = (CPed*)arg;\n\n\tped->bResetWalkAnims = true;\n\tped->bIsLanding = false;\n\n\tanimAssoc->blendDelta = -1000.0f;\n}\n\nvoid\nCPed::FinishHitHeadCB(CAnimBlendAssociation *animAssoc, void *arg)\n{\n\tCPed *ped = (CPed*)arg;\n\n\tif (animAssoc) {\n\t\tanimAssoc->blendDelta = -4.0f;\n\t\tanimAssoc->flags |= ASSOC_DELETEFADEDOUT;\n\t}\n\n\tif (ped->m_nPedState == PED_JUMP)\n\t\tped->RestorePreviousState();\n\n\tped->bIsLanding = false;\n}\n\nbool\nCPed::CanPedDriveOff(void)\n{\n\tif (m_nPedState != PED_DRIVING || m_lookTimer > CTimer::GetTimeInMilliseconds())\n\t\treturn false;\n\n\tfor (int i = 0; i < m_numNearPeds; i++) {\n\t\tCPed *nearPed = m_nearPeds[i];\n\t\tif (nearPed->m_nPedType == m_nPedType && nearPed->m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER && nearPed->m_carInObjective == m_carInObjective) {\n\t\t\tm_lookTimer = CTimer::GetTimeInMilliseconds() + 1000;\n\t\t\treturn false;\n\t\t}\n\t}\n\treturn true;\n}\nvoid\nCPed::SetRadioStation(void)\n{\n\tCPedModelInfo* modelInfo = (CPedModelInfo*)CModelInfo::GetModelInfo(GetModelIndex());\n\n\tif (IsPlayer() || !m_pMyVehicle || m_pMyVehicle->pDriver != this)\n\t\treturn;\n\n\tif (GetModelIndex() != MI_PGA && GetModelIndex() != MI_PGB) {\n\t\tif (m_pMyVehicle->m_nRadioStation != modelInfo->radio1 && m_pMyVehicle->m_nRadioStation != modelInfo->radio2) {\n\t\t\tif (CGeneral::GetRandomTrueFalse())\n\t\t\t\tm_pMyVehicle->m_nRadioStation = modelInfo->radio1;\n\t\t\telse\n\t\t\t\tm_pMyVehicle->m_nRadioStation = modelInfo->radio2;\n\t\t}\n\t} else {\n\t\tm_pMyVehicle->m_nRadioStation = DMAudio.GetFavouriteRadioStation();\n\t}\n}\n\nvoid\nCPed::WarpPedIntoCar(CVehicle *car)\n{\n\tbInVehicle = true;\n\tm_pMyVehicle = car;\n\tm_pMyVehicle->RegisterReference((CEntity **) &m_pMyVehicle);\n\tm_carInObjective = car;\n\tm_carInObjective->RegisterReference((CEntity **) &m_carInObjective);\n\tSetPedState(PED_DRIVING);\n\tbUsesCollision = false;\n\tbIsInTheAir = false;\n\tbVehExitWillBeInstant = true;\n\tif (m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER) {\n\t\tcar->SetDriver(this);\n\t\tcar->pDriver->RegisterReference((CEntity **) &car->pDriver);\n\n\t} else if (m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER) {\n\t\tif (car->IsBike() && !car->pPassengers[0]) {\n\t\t\tcar->pPassengers[0] = this;\n\t\t\tcar->pPassengers[0]->RegisterReference((CEntity**) &car->pPassengers[0]);\n\t\t}\n\t\tfor (int i = 0; i < 4; i++) {\n\t\t\tif (!car->pPassengers[i]) {\n\t\t\t\tcar->pPassengers[i] = this;\n\t\t\t\tcar->pPassengers[i]->RegisterReference((CEntity **) &car->pPassengers[i]);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t} else\n\t\treturn;\n\n\tif (IsPlayer()) {\n\t\tcar->SetStatus(STATUS_PLAYER);\n\t\tAudioManager.PlayerJustGotInCar();\n\t\tCCarCtrl::RegisterVehicleOfInterest(car);\n\t} else {\n\t\tcar->SetStatus(STATUS_PHYSICS);\n\t}\n\n\tCWorld::Remove(this);\n\tSetPosition(car->GetPosition());\n\tCWorld::Add(this);\n\n\tif (car->bIsAmbulanceOnDuty) {\n\t\tcar->bIsAmbulanceOnDuty = false;\n\t\t--CCarCtrl::NumAmbulancesOnDuty;\n\t}\n\tif (car->bIsFireTruckOnDuty) {\n\t\tcar->bIsFireTruckOnDuty = false;\n\t\t--CCarCtrl::NumFiretrucksOnDuty;\n\t}\n\tif (!car->bEngineOn) {\n\t\tcar->bEngineOn = true;\n\t\tDMAudio.PlayOneShot(car->m_audioEntityId, SOUND_CAR_ENGINE_START, 1.0f);\n\t}\n\n\tRpAnimBlendClumpSetBlendDeltas(GetClump(), ASSOC_PARTIAL, -1000.0f);\n\n\tAddInCarAnims(car, car->pDriver == this);\n\tRemoveWeaponWhenEnteringVehicle();\n\n\tif (car->bIsBus)\n\t\tbRenderPedInCar = false;\n\n\tbChangedSeat = true;\n}\n\nbool\nCPed::HasAttractor(void)\n{\n\treturn m_attractor != nil;\n}\n\nvoid\nCPed::SetNewAttraction(CPedAttractor* pAttractor, const CVector& pos, float heading, float time, int32 qid)\n{\n\tif (!m_attractor)\n\t\tm_attractor = pAttractor;\n\tif (m_attractor != pAttractor)\n\t\treturn;\n\tswitch (pAttractor->GetEffect()->pedattr.type) {\n\tcase ATTRACTOR_ATM: SetObjective(OBJECTIVE_GOTO_ATM_ON_FOOT, heading, pos); break;\n\tcase ATTRACTOR_SEAT: SetObjective(OBJECTIVE_GOTO_SEAT_ON_FOOT, heading, pos); break;\n\tcase ATTRACTOR_STOP: SetObjective(OBJECTIVE_GOTO_BUS_STOP_ON_FOOT, heading, pos); break;\n\tcase ATTRACTOR_PIZZA: SetObjective(OBJECTIVE_GOTO_PIZZA_ON_FOOT, heading, pos); break;\n\tcase ATTRACTOR_SHELTER: SetObjective(OBJECTIVE_GOTO_SHELTER_ON_FOOT, heading, pos); break;\n\tcase ATTRACTOR_ICECREAM: SetObjective(OBJECTIVE_GOTO_ICE_CREAM_VAN_ON_FOOT, heading, pos); break;\n\tdefault: return;\n\t}\n\tSetObjectiveTimer(time);\n\tm_positionInQueue = qid;\n}\n\nvoid\nCPed::AttachPedToEntity(CEntity *ent, CVector offset, uint16 type, float rot, eWeaponType weapon)\n{\n\tif (!ent || bInVehicle)\n\t\treturn;\n\n\tm_attachedTo = ent;\n\tm_attachedTo->RegisterReference(&m_attachedTo);\n\tm_vecAttachOffset = offset;\n\tm_attachType = type;\n\tm_attachRotStep = rot;\n\tif (IsPlayer()) {\n\t\tbUsesCollision = false;\n\t} else if (ent->IsVehicle()) {\n\t\tm_pCollidingEntity = ent;\n\t}\n\n\tif (IsPlayer()) {\n\t\tm_objective = OBJECTIVE_NONE;\n\t\tm_prevObjective = OBJECTIVE_NONE;\n\t}\n\tSetStoredState();\n\tSetPedState(PED_IDLE);\n\tCAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_STD_IDLE, 1000.0f);\n\n\tif (m_storedWeapon == WEAPONTYPE_UNIDENTIFIED) {\n\t\tm_storedWeapon = GetWeapon()->m_eWeaponType;\n\t\tm_attachWepAmmo = GetWeapon()->m_nAmmoTotal;\n\t}\n\tif (IsPlayer()) {\n\t\tGiveWeapon(weapon, 30000, 1);\n#ifndef FIX_BUGS\n\t\t((CPlayerPed*)this)->m_nSelectedWepSlot = weapon;\n#else\n\t\t((CPlayerPed*)this)->m_nSelectedWepSlot = GetWeaponSlot(weapon);\n#endif\n\t\t((CPlayerPed*)this)->MakeChangesForNewWeapon(weapon);\n\t\tTheCamera.SetNewPlayerWeaponMode(CCam::MODE_HELICANNON_1STPERSON, 0, 0);\n\t\tSetPedState(PED_SNIPER_MODE);\n\t} else {\n\t\tGiveWeapon(weapon, 30000, true);\n\t\tSetCurrentWeapon(weapon);\n\t}\n\n\tPositionAttachedPed();\n}\n\nvoid\nCPed::DettachPedFromEntity(void)\n{\n\tCEntity* pVehicleAttachedTo = m_attachedTo;\n\tm_attachedTo = nil;\n\tif (m_nPedState == PED_DIE) {\n\t\tm_pCollidingEntity = pVehicleAttachedTo;\n\t\tApplyMoveForce(pVehicleAttachedTo->GetForward() * -4.0f + CVector(0.0f, 0.0f, 4.0f));\n\t\tbIsStanding = false;\n\t} else if (m_nPedState != PED_DEAD) {\n\t\tRestorePreviousState();\n\t\tCAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_STD_IDLE, 1000.0f);\n\t\tbUsesCollision = true;\n\t\tif (m_storedWeapon != WEAPONTYPE_UNIDENTIFIED) {\n\t\t\tGetWeapon()->m_nAmmoInClip = 0;\n\t\t\tGetWeapon()->m_nAmmoTotal = 0;\n\t\t\tSetCurrentWeapon(m_storedWeapon);\n\t\t\tGetWeapon()->m_nAmmoTotal = m_attachWepAmmo;\n\t\t\tm_storedWeapon = WEAPONTYPE_UNIDENTIFIED;\n\t\t}\n\t}\n}\n\nvoid\nCPed::PositionAttachedPed()\n{\n\tif(!m_attachedTo)\n\t\treturn;\n\n\tCMatrix rotMatrix, targetMat;\n\ttargetMat = m_attachedTo->GetMatrix();\n\ttargetMat.GetPosition() += Multiply3x3(m_attachedTo->GetMatrix(), m_vecAttachOffset);\n\tfloat objAngle = m_attachedTo->GetForward().Heading();\n\n\tif (!IsPlayer()) {\n\t\tfloat targetAngle = objAngle;\n\t\tswitch (m_attachType) {\n\t\t\tcase 1:\n\t\t\t\ttargetAngle += HALFPI;\n\t\t\t\tbreak;\n\t\t\tcase 2:\n\t\t\t\ttargetAngle += PI;\n\t\t\t\tbreak;\n\t\t\tcase 3:\n\t\t\t\ttargetAngle -= HALFPI;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t\ttargetAngle = CGeneral::LimitRadianAngle(targetAngle);\n\t\tm_fRotationCur = CGeneral::LimitRadianAngle(m_fRotationCur);\n\t\tfloat neededTurn = m_fRotationCur - targetAngle;\n\n\t\tif (neededTurn > PI)\n\t\t\tneededTurn -= TWOPI;\n\t\telse if (neededTurn < -PI)\n\t\t\tneededTurn += TWOPI;\n\n\t\tif (neededTurn > m_attachRotStep)\n\t\t\tm_fRotationCur = CGeneral::LimitRadianAngle(targetAngle + m_attachRotStep);\n\t\telse if (-m_attachRotStep > neededTurn)\n\t\t\tm_fRotationCur = CGeneral::LimitRadianAngle(targetAngle - m_attachRotStep);\n\t\telse\n\t\t\tm_fRotationCur = CGeneral::LimitRadianAngle(m_fRotationCur);\n\t}\n\trotMatrix.SetRotateZ(m_fRotationCur - objAngle);\n\ttargetMat = targetMat * rotMatrix;\n\tGetMatrix() = targetMat;\n\tif (m_attachedTo->IsVehicle() || m_attachedTo->IsObject()) {\n\t\tm_vecMoveSpeed = ((CPhysical*)m_attachedTo)->m_vecMoveSpeed;\n\t\tm_vecTurnSpeed = ((CPhysical*)m_attachedTo)->m_vecTurnSpeed;\n\t}\n}\n\nvoid\nCPed::Undress(const char* name)\n{\n\tint mi = GetModelIndex();\n\tCAnimBlendAssociation* pAnim = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_PHONE_OUT);\n\tif (pAnim)\n\t\tFinishTalkingOnMobileCB(pAnim, this);\n\n\tDeleteRwObject();\n\tif (IsPlayer())\n\t\tmi = MI_PLAYER;\n\tCStreaming::RequestSpecialModel(mi, name, STREAMFLAGS_DEPENDENCY | STREAMFLAGS_SCRIPTOWNED);\n\tCWorld::Remove(this);\n}\n\nvoid\nCPed::Dress(void)\n{\n\tint mi = GetModelIndex();\n\tm_modelIndex = -1;\n\tSetModelIndex(mi);\n\tm_nPedState = PED_IDLE;\n\tm_nLastPedState = PED_NONE;\n\tm_objective = OBJECTIVE_NONE;\n\tm_prevObjective = OBJECTIVE_NONE;\n\tm_nWaitState = WAITSTATE_FALSE;\n\tCWorld::Add(this);\n\tRestoreHeadingRate();\n}\n\nvoid\nCPed::Say(uint16 audio, int32 time)\n{\n\tif (m_delayedSoundID == -1) {\n\t\tm_delayedSoundID = audio;\n\t\tm_delayedSoundTimer = CTimer::GetTimeInMilliseconds() + time;\n\t}\n}\n\n#ifdef COMPATIBLE_SAVES\n#define CopyFromBuf(buf, data) memcpy(&data, buf, sizeof(data)); SkipSaveBuf(buf, sizeof(data));\n#define CopyToBuf(buf, data) memcpy(buf, &data, sizeof(data)); SkipSaveBuf(buf, sizeof(data));\nvoid\nCPed::Save(uint8*& buf)\n{\n\tSkipSaveBuf(buf, 52);\n\tCopyToBuf(buf, GetPosition().x);\n\tCopyToBuf(buf, GetPosition().y);\n\tCopyToBuf(buf, GetPosition().z);\n\tSkipSaveBuf(buf, 288);\n\tCopyToBuf(buf, CharCreatedBy);\n\tSkipSaveBuf(buf, 499);\n\tCopyToBuf(buf, m_fHealth);\n\tCopyToBuf(buf, m_fArmour);\n\tSkipSaveBuf(buf, 172);\n\tfor (int i = 0; i < 10; i++) // has to be hardcoded\n\t\tm_weapons[i].Save(buf);\n\tSkipSaveBuf(buf, 252);\n}\n\nvoid\nCPed::Load(uint8*& buf)\n{\n\tSkipSaveBuf(buf, 52);\n\tCopyFromBuf(buf, GetMatrix().GetPosition().x);\n\tCopyFromBuf(buf, GetMatrix().GetPosition().y);\n\tCopyFromBuf(buf, GetMatrix().GetPosition().z);\n\tSkipSaveBuf(buf, 288);\n\tCopyFromBuf(buf, CharCreatedBy);\n\tSkipSaveBuf(buf, 499);\n\tCopyFromBuf(buf, m_fHealth);\n\tCopyFromBuf(buf, m_fArmour);\n\tSkipSaveBuf(buf, 172);\n\tm_currentWeapon = WEAPONTYPE_UNARMED;\n\n\tCWeapon bufWeapon;\n\tfor (int i = 0; i < 10; i++) { // has to be hardcoded\n\t\tbufWeapon.Load(buf);\n\n\t\tif (bufWeapon.m_eWeaponType != WEAPONTYPE_UNARMED) {\n\t\t\tint modelId = CWeaponInfo::GetWeaponInfo(bufWeapon.m_eWeaponType)->m_nModelId;\n\t\t\tif (modelId != -1) {\n\t\t\t\tCStreaming::RequestModel(modelId, STREAMFLAGS_DEPENDENCY);\n\t\t\t\tint modelId2 = CWeaponInfo::GetWeaponInfo(bufWeapon.m_eWeaponType)->m_nModel2Id;\n\t\t\t\tif (modelId2 != -1)\n\t\t\t\t\tCStreaming::RequestModel(modelId2, STREAMFLAGS_DEPENDENCY);\n\n\t\t\t\tCStreaming::LoadAllRequestedModels(false);\n\t\t\t}\n\t\t\tGiveWeapon(bufWeapon.m_eWeaponType, bufWeapon.m_nAmmoTotal, false);\n\t\t}\n\t}\n\tSkipSaveBuf(buf, 252);\n}\n#undef CopyFromBuf\n#undef CopyToBuf\n#endif\n"
  },
  {
    "path": "src/peds/Ped.h",
    "content": "#pragma once\n\n#include \"RwHelper.h\"\n#include \"AnimManager.h\"\n#include \"Crime.h\"\n#include \"EventList.h\"\n#include \"PedIK.h\"\n#include \"PedType.h\"\n#include \"Physical.h\"\n#include \"Weapon.h\"\n#include \"WeaponInfo.h\"\n#include \"PathFind.h\"\n#include \"Collision.h\"\n\n#define FEET_OFFSET\t1.04f\n#define CHECK_NEARBY_THINGS_MAX_DIST\t15.0f\n#define ENTER_CAR_MAX_DIST\t30.0f\n#define CAN_SEE_ENTITY_ANGLE_THRESHOLD\tDEGTORAD(60.0f)\n\nclass CAccident;\nclass CObject;\nclass CFire;\nstruct AnimBlendFrameData;\nclass CAnimBlendAssociation;\nclass CPedAttractor;\n\nstruct PedAudioData\n{\n\tint m_nFixedDelayTime;\n\tint m_nOverrideFixedDelayTime;\n\tint m_nOverrideMaxRandomDelayTime;\n\tint m_nMaxRandomDelayTime;\n};\n\nenum\n{\n\tATTACK_IN_PROGRESS,\n\tCANT_ATTACK,\n\tWATCH_UNTIL_HE_DISAPPEARS,\n};\n\nenum eFormation\n{\n\tFORMATION_UNDEFINED,\n\tFORMATION_REAR,\n\tFORMATION_REAR_LEFT,\n\tFORMATION_REAR_RIGHT,\n\tFORMATION_FRONT_LEFT,\n\tFORMATION_FRONT_RIGHT,\n\tFORMATION_LEFT,\n\tFORMATION_RIGHT,\n\tFORMATION_FRONT\n};\n\nenum FightState {\n\tFIGHTSTATE_MOVE_FINISHED = -2,\n\tFIGHTSTATE_JUST_ATTACKED,\n\tFIGHTSTATE_NO_MOVE,\n\tFIGHTSTATE_1\n};\n\nenum\n{\n\tENDFIGHT_NORMAL,\n\tENDFIGHT_WITH_A_STEP,\n\tENDFIGHT_FAST\n};\n\nenum PedRouteType\n{\n\tPEDROUTE_STOP_WHEN_DONE = 1,\n\tPEDROUTE_GO_BACKWARD_WHEN_DONE,\n\tPEDROUTE_GO_TO_START_WHEN_DONE\n};\n\nenum FightMoveHitLevel\n{\n\tHITLEVEL_NULL,\n\tHITLEVEL_GROUND,\n\tHITLEVEL_LOW,\n\tHITLEVEL_MEDIUM,\n\tHITLEVEL_HIGH\n};\n\nstruct FightMove\n{\n\tAnimationId animId;\n\tfloat startFireTime;\n\tfloat endFireTime;\n\tfloat comboFollowOnTime;\n\tfloat strikeRadius;\n\tfloat extendReachMultiplier;\n\tuint8 hitLevel; // FightMoveHitLevel\n\tuint8 damage;\n\tuint8 flags;\n};\n\n// TODO: This is eFightState on mobile.\nenum PedFightMoves\n{\n\tFIGHTMOVE_NULL,\n\t// Attacker\n\tFIGHTMOVE_STDPUNCH,\n\tFIGHTMOVE_IDLE,\n\tFIGHTMOVE_SHUFFLE_F,\n\tFIGHTMOVE_KNEE,\n\tFIGHTMOVE_PUNCHHOOK,\n\tFIGHTMOVE_PUNCHJAB,\n\tFIGHTMOVE_PUNCH,\n\tFIGHTMOVE_LONGKICK,\n\tFIGHTMOVE_ROUNDHOUSE,\n\t// Directionals\n\tFIGHTMOVE_FWDLEFT,\n\tFIGHTMOVE_FWDRIGHT,\n\tFIGHTMOVE_BACKKICK,\n\tFIGHTMOVE_BACKFLIP,\n\tFIGHTMOVE_BACKLEFT,\n\tFIGHTMOVE_BACKRIGHT,\n\tFIGHTMOVE_RIGHTSWEEP,\n\t// Special\n\tFIGHTMOVE_GROUNDKICK,\n\t// Opponent\n\tFIGHTMOVE_HITFRONT,\n\tFIGHTMOVE_HITBACK,\n\tFIGHTMOVE_HITRIGHT,\n\tFIGHTMOVE_HITLEFT,\n\tFIGHTMOVE_HITBODY,\n\tFIGHTMOVE_HITCHEST,\n\tFIGHTMOVE_HITHEAD,\n\tFIGHTMOVE_HITBIGSTEP,\n\tFIGHTMOVE_HITONFLOOR,\n\tFIGHTMOVE_HITBEHIND,\n\tFIGHTMOVE_MELEE1,\n\tFIGHTMOVE_MELEE2,\n\tFIGHTMOVE_MELEE3,\n\tFIGHTMOVE_IDLE2NORM,\n\tNUM_FIGHTMOVES\n};\n\nenum ePedPieceTypes\n{\n\tPEDPIECE_TORSO,\n\tPEDPIECE_MID,\n\tPEDPIECE_LEFTARM,\n\tPEDPIECE_RIGHTARM,\n\tPEDPIECE_LEFTLEG,\n\tPEDPIECE_RIGHTLEG,\n\tPEDPIECE_HEAD,\n};\n\nenum eWaitState {\n\tWAITSTATE_FALSE,\n\tWAITSTATE_TRAFFIC_LIGHTS,\n\tWAITSTATE_CROSS_ROAD,\n\tWAITSTATE_CROSS_ROAD_LOOK,\n\tWAITSTATE_LOOK_PED,\n\tWAITSTATE_LOOK_SHOP,\n\tWAITSTATE_LOOK_ACCIDENT,\n\tWAITSTATE_FACEOFF_GANG,\n\tWAITSTATE_DOUBLEBACK,\n\tWAITSTATE_HITWALL,\n\tWAITSTATE_TURN180,\n\tWAITSTATE_SURPRISE,\n\tWAITSTATE_STUCK,\n\tWAITSTATE_LOOK_ABOUT,\n\tWAITSTATE_PLAYANIM_DUCK,\n\tWAITSTATE_PLAYANIM_COWER,\n\tWAITSTATE_PLAYANIM_TAXI,\n\tWAITSTATE_PLAYANIM_HANDSUP,\n\tWAITSTATE_PLAYANIM_HANDSCOWER,\n\tWAITSTATE_PLAYANIM_CHAT,\n\tWAITSTATE_FINISH_FLEE,\n\tWAITSTATE_SIT_DOWN,\n\tWAITSTATE_SIT_DOWN_RVRS,\n\tWAITSTATE_SIT_UP,\n\tWAITSTATE_SIT_IDLE,\n\tWAITSTATE_USE_ATM,\n\tWAITSTATE_SUN_BATHE_PRE,\n\tWAITSTATE_SUN_BATHE_DOWN,\n\tWAITSTATE_SUN_BATHE_IDLE,\n\tWAITSTATE_RIOT,\n\tWAITSTATE_FAST_FALL,\n\tWAITSTATE_BOMBER,\n\tWAITSTATE_STRIPPER,\n\tWAITSTATE_GROUND_ATTACK,\n\tWAITSTATE_LANCESITTING,\n\tWAITSTATE_PLAYANIM_HANDSUP_SIMPLE,\n};\n\nenum eObjective {\n\tOBJECTIVE_NONE,\n\tOBJECTIVE_WAIT_ON_FOOT,\n\tOBJECTIVE_WAIT_ON_FOOT_FOR_COP,\n\tOBJECTIVE_FLEE_ON_FOOT_TILL_SAFE,\n\tOBJECTIVE_GUARD_SPOT,\n\tOBJECTIVE_GUARD_AREA,\n\tOBJECTIVE_WAIT_IN_CAR,\n\tOBJECTIVE_WAIT_IN_CAR_THEN_GET_OUT,\n\tOBJECTIVE_KILL_CHAR_ON_FOOT,\n\tOBJECTIVE_KILL_CHAR_ANY_MEANS,\n\tOBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE,\n\tOBJECTIVE_FLEE_CHAR_ON_FOOT_ALWAYS,\n\tOBJECTIVE_GOTO_CHAR_ON_FOOT,\n\tOBJECTIVE_GOTO_CHAR_ON_FOOT_WALKING,\n\tOBJECTIVE_HASSLE_CHAR,\n\tOBJECTIVE_FOLLOW_CHAR_IN_FORMATION,\n\tOBJECTIVE_LEAVE_CAR,\n\tOBJECTIVE_ENTER_CAR_AS_PASSENGER,\n\tOBJECTIVE_ENTER_CAR_AS_DRIVER,\n\tOBJECTIVE_FOLLOW_CAR_IN_CAR,\n\tOBJECTIVE_FIRE_AT_OBJECT_FROM_VEHICLE,\n\tOBJECTIVE_DESTROY_OBJECT,\n\tOBJECTIVE_DESTROY_CAR,\n\tOBJECTIVE_GOTO_AREA_ANY_MEANS,\n\tOBJECTIVE_GOTO_AREA_ON_FOOT,\n\tOBJECTIVE_RUN_TO_AREA,\n\tOBJECTIVE_GOTO_AREA_IN_CAR,\n\tOBJECTIVE_FOLLOW_CAR_ON_FOOT_WITH_OFFSET,\n\tOBJECTIVE_GUARD_ATTACK,\n\tOBJECTIVE_SET_LEADER,\n\tOBJECTIVE_FOLLOW_ROUTE,\n\tOBJECTIVE_SOLICIT_VEHICLE,\n\tOBJECTIVE_HAIL_TAXI,\n\tOBJECTIVE_CATCH_TRAIN,\n\tOBJECTIVE_BUY_ICE_CREAM,\n\tOBJECTIVE_STEAL_ANY_CAR,\n\tOBJECTIVE_STEAL_ANY_MISSION_CAR,\n\tOBJECTIVE_MUG_CHAR,\n\tOBJECTIVE_LEAVE_CAR_AND_DIE,\n\tOBJECTIVE_GOTO_SEAT_ON_FOOT,\n\tOBJECTIVE_GOTO_ATM_ON_FOOT,\n\tOBJECTIVE_FLEE_CAR,\n\tOBJECTIVE_SUN_BATHE,\n\tOBJECTIVE_GOTO_BUS_STOP_ON_FOOT,\n\tOBJECTIVE_GOTO_PIZZA_ON_FOOT,\n\tOBJECTIVE_GOTO_SHELTER_ON_FOOT,\n\tOBJECTIVE_AIM_GUN_AT,\n\tOBJECTIVE_WANDER,\n\tOBJECTIVE_WAIT_ON_FOOT_AT_SHELTER,\n\tOBJECTIVE_SPRINT_TO_AREA,\n\tOBJECTIVE_KILL_CHAR_ON_BOAT,\n\tOBJECTIVE_SOLICIT_FOOT,\n\tOBJECTIVE_WAIT_ON_FOOT_AT_BUS_STOP,\n\tOBJECTIVE_GOTO_ICE_CREAM_VAN_ON_FOOT,\n\tOBJECTIVE_WAIT_ON_FOOT_AT_ICE_CREAM_VAN,\n\tOBJ_55,\n\tOBJ_56,\n\tOBJ_57,\n\tOBJ_58,\n\tOBJ_59\n\n};\n\nenum {\n\tRANDOM_CHAR = 1,\n\tMISSION_CHAR,\n\tUNK_CHAR,\n};\n\nenum PedLineUpPhase {\n\tLINE_UP_TO_CAR_START,\n\tLINE_UP_TO_CAR_END,\n\tLINE_UP_TO_CAR_2, // Buggy. Used for cops arresting you from passenger door\n\tLINE_UP_TO_CAR_FALL\n};\n\nenum PedOnGroundState {\n\tNO_PED,\n\tPED_IN_FRONT_OF_ATTACKER,\n\tPED_ON_THE_FLOOR,\n\tPED_DEAD_ON_THE_FLOOR\n};\n\nenum PointBlankNecessity {\n\tNO_POINT_BLANK_PED,\n\tPOINT_BLANK_FOR_WANTED_PED,\n\tPOINT_BLANK_FOR_SOMEONE_ELSE\n};\n\nenum PedState\n{\n\tPED_NONE,\n\tPED_IDLE,\n\tPED_LOOK_ENTITY,\n\tPED_LOOK_HEADING,\n\tPED_WANDER_RANGE,\n\tPED_WANDER_PATH,\n\tPED_SEEK_POS,\n\tPED_SEEK_ENTITY,\n\tPED_FLEE_POS,\n\tPED_FLEE_ENTITY,\n\tPED_PURSUE,\n\tPED_FOLLOW_PATH,\n\tPED_SNIPER_MODE,\n\tPED_ROCKET_MODE,\n\tPED_DUMMY,\n\tPED_PAUSE,\n\tPED_ATTACK,\n\tPED_FIGHT,\n\tPED_FACE_PHONE,\n\tPED_MAKE_CALL,\n\tPED_CHAT,\n\tPED_MUG,\n\tPED_AIM_GUN,\n\tPED_AI_CONTROL,\n\tPED_SEEK_CAR,\n\tPED_SEEK_IN_BOAT,\n\tPED_FOLLOW_ROUTE,\n\tPED_CPR,\n\tPED_SOLICIT,\n\tPED_BUY_ICECREAM,\n\tPED_INVESTIGATE,\n\tPED_STEP_AWAY,\n\tPED_ON_FIRE,\n\tPED_SUN_BATHE,\n\tPED_FLASH,\n\tPED_JOG,\n\tPED_ANSWER_MOBILE,\n\n\tPED_UNKNOWN,\t// Same with IDLE, but also infects up to 5 peds with same pedType and WANDER_PATH, so they become stone too. HANG_OUT in Fire_Head's idb\n\n\tPED_STATES_NO_AI,\n\n\tPED_ABSEIL,\n\tPED_SIT,\n\tPED_JUMP,\n\tPED_FALL,\n\tPED_GETUP,\n\tPED_STAGGER,\n\tPED_DIVE_AWAY,\n\n\tPED_STATES_NO_ST,\n\tPED_ENTER_TRAIN,\n\tPED_EXIT_TRAIN,\n\tPED_ARREST_PLAYER,\n\n\tPED_DRIVING,\n\tPED_PASSENGER,\n\tPED_TAXI_PASSENGER,\n\tPED_OPEN_DOOR,\n\tPED_DIE,\n\tPED_DEAD,\n\tPED_CARJACK,\n\tPED_DRAG_FROM_CAR,\n\tPED_ENTER_CAR,\n\tPED_STEAL_CAR,\n\tPED_EXIT_CAR,\n\tPED_HANDS_UP,\n\tPED_ARRESTED,\n\tPED_DEPLOY_STINGER\n};\n\nenum eMoveState {\n\tPEDMOVE_NONE,\n\tPEDMOVE_STILL,\n\tPEDMOVE_WALK,\n\tPEDMOVE_JOG,\n\tPEDMOVE_RUN,\n\tPEDMOVE_SPRINT,\n\tPEDMOVE_THROWN\n};\n\nextern float gfTommyFatness;\n\nclass CVehicle;\n\nclass CPed : public CPhysical\n{\npublic:\n#ifdef USE_CUTSCENE_SHADOW_FOR_PED\n\tclass CCutsceneShadow *m_pRTShadow;\n#endif\n\t// 0x128\n\tCStoredCollPoly m_collPoly;\n\tfloat m_fCollisionSpeed;\n\n\t// cf. https://github.com/DK22Pac/plugin-sdk/blob/master/plugin_sa/game_sa/CPed.h from R*\n\tuint32 bIsStanding : 1;\n\tuint32 bWasStanding : 1;\n\tuint32 bIsAttacking : 1;\t\t// doesn't reset after fist fight\n\tuint32 bIsPointingGunAt : 1;\n\tuint32 bIsLooking : 1;\n\tuint32 bKeepTryingToLook : 1; // if we can't look somewhere due to unreachable angles\n\tuint32 bIsRestoringLook : 1;\n\tuint32 bIsAimingGun : 1;\n\n\tuint32 bIsRestoringGun : 1;\n\tuint32 bCanPointGunAtTarget : 1;\n\tuint32 bIsTalking : 1;\n\tuint32 bIsInTheAir : 1;\n\tuint32 bIsLanding : 1;\n\tuint32 bIsRunning : 1; // on some conditions\n\tuint32 bHitSomethingLastFrame : 1;\n\tuint32 bVehEnterDoorIsBlocked : 1; // because someone else enters/exits from there\n\n\tuint32 bCanPedEnterSeekedCar : 1;\n\tuint32 bRespondsToThreats : 1;\n\tuint32 bRenderPedInCar : 1;\n\tuint32 bChangedSeat : 1;\n\tuint32 bUpdateAnimHeading : 1;\n\tuint32 bBodyPartJustCameOff : 1;\n\tuint32 bIsShooting : 1;\n\tuint32 bFindNewNodeAfterStateRestore : 1;\n\n\tuint32 bHasACamera : 1; // does ped possess a camera to document accidents involves fire/explosion\n\tuint32 bGonnaInvestigateEvent : 1;\n\tuint32 bPedIsBleeding : 1;\n\tuint32 bStopAndShoot : 1; // Ped cannot reach target to attack with fist, need to use gun\n\tuint32 bIsPedDieAnimPlaying : 1;\n\tuint32 bUsePedNodeSeek : 1;\n\tuint32 bObjectiveCompleted : 1;\n\tuint32 bScriptObjectiveCompleted : 1;\n\n\tuint32 bKindaStayInSamePlace : 1;\n\tuint32 bBeingChasedByPolice : 1;\n\tuint32 bNotAllowedToDuck : 1;\n\tuint32 bCrouchWhenShooting : 1;\n\tuint32 bIsDucking : 1;\n\tuint32 bGetUpAnimStarted : 1;\n\tuint32 bDoBloodyFootprints : 1;\n\tuint32 bFleeAfterExitingCar : 1;\n\n\tuint32 bWanderPathAfterExitingCar : 1;\n\tuint32 bIsLeader : 1;\n\tuint32 bDontDragMeOutCar : 1; // unfinished feature\n\tuint32 m_ped_flagF8 : 1;\n\tuint32 bWillBeQuickJacked : 1;\n\tuint32 bCancelEnteringCar : 1; // after door is opened or couldn't be opened due to it's locked\n\tuint32 bObstacleShowedUpDuringKillObjective : 1;\n\tuint32 bDuckAndCover : 1;\n\n\tuint32 bStillOnValidPoly : 1; // set if the polygon the ped is on is still valid for collision\n\tuint32 bAllowMedicsToReviveMe : 1;\n\tuint32 bResetWalkAnims : 1;\n\tuint32 bStartWanderPathOnFoot : 1; // exits the car if he's in it, reset after path found\n\tuint32 bOnBoat : 1; // not just driver, may be just standing\n\tuint32 bBusJacked : 1;\n\tuint32 bGonnaKillTheCarJacker : 1; // only set when car is jacked from right door and when arrested by police\n\tuint32 bFadeOut : 1;\n\n\tuint32 bKnockedUpIntoAir : 1; // has ped been knocked up into the air by a car collision\n\tuint32 bHitSteepSlope : 1; // has ped collided/is standing on a steep slope (surface type)\n\tuint32 bCullExtraFarAway : 1; // special ped only gets culled if it's extra far away (for roadblocks)\n\tuint32 bClearObjective : 1;\n\tuint32 bTryingToReachDryLand : 1; // has ped just exited boat and trying to get to dry land\n\tuint32 bCollidedWithMyVehicle : 1;\n\tuint32 bRichFromMugging : 1; // ped has lots of cash cause they've been mugging people\n\tuint32 bChrisCriminal : 1; // Is a criminal as killed during Chris' police mission (should be counted as such)\n\n\tuint32 bShakeFist : 1;  // test shake hand at look entity\n\tuint32 bNoCriticalHits : 1; // if set, limbs won't came off\n\tuint32 bVehExitWillBeInstant : 1;\n\tuint32 bHasAlreadyBeenRecorded : 1;\n\tuint32 bFallenDown : 1;\n\tuint32 bDontAcceptIKLookAts : 1;\n\tuint32 bReachedAttractorHeadingTarget : 1;\n\tuint32 bTurnedAroundOnAttractor : 1;\n\n\tuint32 bHasAlreadyUsedAttractor : 1;\n\tuint32 bHasAlreadyStoleACar : 1;\n\tuint32 bCarPassenger : 1;\n\tuint32 bFleeWhenStanding : 1;\n\tuint32 bGotUpOfMyOwnAccord : 1;\n\tuint32 bMiamiViceCop : 1;\n\tuint32 bMoneyHasBeenGivenByScript : 1; //\n\tuint32 bHasBeenPhotographed : 1;  //\n\n\tuint32 bIsDrowning : 1;\n\tuint32 bDrownsInWater : 1;\n\tuint32 bWaitForLeaderToComeCloser : 1;\n\tuint32 bHeldHostageInCar : 1;\n\tuint32 bIsPlayerFriend : 1;\n\tuint32 bHeadStuckInCollision : 1;\n\tuint32 bDeadPedInFrontOfCar : 1;\n\tuint32 bStayInCarOnJack : 1;\n\n\tuint32 bDontFight : 1;\n\tuint32 bDoomAim : 1;\n\tuint32 bCanBeShotInVehicle : 1;\n\tuint32 bCanGiveUpSunbathing : 1;\n\tuint32 bMakeFleeScream : 1;\n\tuint32 bPushedAlongByCar : 1;\n\tuint32 bRemoveMeWhenIGotIntoCar : 1;\n\tuint32 bIgnoreThreatsBehindObjects : 1;\n\n\tuint32 bNeverEverTargetThisPed : 1;\n\tuint32 bCrouchWhenScared : 1;\n\tuint32 bKnockedOffBike : 1;\n\tuint32 b158_8 : 1;\n\tuint32 bCollectBusFare : 1;\n\tuint32 bBoughtIceCream : 1;\n\tuint32 bDonePositionOutOfCollision : 1;\n\tuint32 bCanAttackPlayerWithCops : 1;\n\n#ifdef KANGAROO_CHEAT\n\t// our own flags\n\tuint32 m_ped_flagI80 : 1; // KANGAROO_CHEAT define makes use of this as cheat toggle \n#endif\n\n\tuint8 m_gangFlags;\n\tuint8 m_unused15D; // these 3 can't be padding but had to actually have been members ...\n\tuint8 m_unused15E;\n\tuint8 m_unused15F;\n\tuint8 CharCreatedBy;\n\teObjective m_objective;\n\teObjective m_prevObjective;\n\tCPed *m_pedInObjective;\n\tCVehicle *m_carInObjective;\n\tCVector m_nextRoutePointPos;\n\tfloat m_attractorHeading;\n\tCPed *m_leader;\n\teFormation m_pedFormation;\n\tuint32 m_fearFlags;\n\tCEntity *m_threatEntity;\n\tCVector2D m_eventOrThreat;\n\tuint32 m_eventType;\n\tCEntity* m_pEventEntity;\n\tfloat m_fAngleToEvent;\n\tAnimBlendFrameData *m_pFrames[PED_NODE_MAX];\n\tRpAtomic *m_pWeaponModel;\n\tAssocGroupId m_animGroup;\n\tCAnimBlendAssociation *m_pVehicleAnim;\n\tCVector2D m_vecAnimMoveDelta;\n\tCVector m_vecOffsetSeek;\n\tCPedIK m_pedIK; \n\tfloat m_actionX;\n\tfloat m_actionY;\n\tuint32 m_nPedStateTimer;\n\tPedState m_nPedState;\n\tPedState m_nLastPedState;\n\teMoveState m_nMoveState;\n\tint32 m_nStoredMoveState;\n\tint32 m_nPrevMoveState;\n\teWaitState m_nWaitState;\n\tuint32 m_nWaitTimer;\n\tCPathNode* m_pathNodesToGo[8];\n\tint16 m_nNumPathNodes;\n\tint16 m_nCurPathNodeId;\n\tCEntity* m_followPathWalkAroundEnt;\n\tCEntity* m_followPathTargetEnt;\n\tuint32 m_pathNodeTimer;\n\tCPathNode m_pathNodeObjPool[8];\n\tCPathNode* m_pCurPathNode;\n\tint8 m_nPathDir;\n\tCPathNode* m_pLastPathNode;\n\tCPathNode* m_pNextPathNode;\n\tCVector m_followPathDestPos;\n\tfloat m_followPathAbortDist;\n\teMoveState m_followPathMoveState;\n\tfloat m_fHealth;\n\tfloat m_fArmour;\n\tuint32 m_nExtendedRangeTimer;\n\tint16 m_routeLastPoint;\n\tuint16 m_routeStartPoint;\n\tint16 m_routePointsPassed;\n\tint16 m_routeType;\t// See PedRouteType\n\tint16 m_routePointsBeingPassed;\n\tCVector2D m_moved;\n\tfloat m_fRotationCur;\n\tfloat m_fRotationDest;\n\tfloat m_headingRate;\n\tuint16 m_vehDoor;\n\tint16 m_walkAroundType;\n\tCPhysical *m_pCurrentPhysSurface;\n\tCVector m_vecOffsetFromPhysSurface;\n\tCEntity *m_pCurSurface;\n\tCVector m_vecSeekPos;\n\tCEntity *m_pSeekTarget;\n\tCVehicle *m_pMyVehicle;\n\tbool bInVehicle;\n\tfloat m_distanceToCountSeekDone;\n\tfloat m_acceptableHeadingOffset;\n\tCVehicle* m_vehicleInAccident;\n\tCPedAttractor* m_attractor;\n\tint32 m_positionInQueue;\n\tbool bRunningToPhone;\n\tint16 m_phoneId;\n\teCrimeType m_crimeToReportOnPhone;\n\tuint32 m_phoneTalkTimer;\n\tCAccident *m_lastAccident;\n\tuint32 m_nPedType;\n\tCPedStats *m_pedStats;\n\tCVector2D m_fleeFromPos;\n\tCEntity *m_fleeFrom;\n\tuint32 m_fleeTimer;\n\tCEntity* m_threatEx; // TODO(Miami): What is this?\n\tCEntity* m_collidingEntityWhileFleeing;\n\tuint32 m_collidingThingTimer;\n\tCEntity *m_pCollidingEntity;\n\tuint8 m_stateUnused;\n\tuint32 m_timerUnused;\n\tclass CRange2D *m_wanderRangeBounds;\n\tCWeapon m_weapons[TOTAL_WEAPON_SLOTS];\n\teWeaponType m_storedWeapon;\n\teWeaponType m_delayedWeapon;\n\tuint32 m_delayedWeaponAmmo;\n\tuint8 m_currentWeapon;\t\t\t// eWeaponType\n\tuint8 m_maxWeaponTypeAllowed;\t// eWeaponType\n\tuint8 m_wepSkills;\n\tuint8 m_wepAccuracy;\n\tCEntity *m_pPointGunAt;\n\tCVector m_vecHitLastPos;\n\tuint32 m_curFightMove;\n\tuint32 m_lastFightMove;\n\tuint8 m_fightButtonPressure;\n\tint8 m_fightState;\n\tbool m_takeAStepAfterAttack;\n\tuint8 m_bleedCounter;\n\tCFire *m_pFire;\n\tCEntity *m_pLookTarget;\n\tfloat m_fLookDirection;\n\tint32 m_wepModelID;\n\tuint32 m_leaveCarTimer;\n\tuint32 m_getUpTimer;\n\tuint32 m_lookTimer;\n\tuint32 m_chatTimer;\n\tuint32 m_attackTimer;\n\tuint32 m_shootTimer; // shooting is a part of attack\n\tuint32 m_carJackTimer;\n\tuint32 m_objectiveTimer;\n\tuint32 m_duckTimer;\n\tuint32 m_duckAndCoverTimer;\n\tuint32 m_bloodyFootprintCountOrDeathTime;\t// Death time when bDoBloodyFootprints is false. Weird decision\n\tuint32 m_shotTime;\n\tuint32 m_ceaseAttackTimer;\n\tuint8 m_panicCounter;\n\tbool m_deadBleeding;\n\tint8 m_bodyPartBleeding;\t\t// PedNode, but -1 if there isn't\n\tCPed *m_nearPeds[10];\n\tuint16 m_numNearPeds;\n\tuint16 m_nPedMoney;\n \tint8 m_lastWepDam;\n\tCEntity *m_lastDamEntity;\n\tCEntity *m_attachedTo;\n\tCVector m_vecAttachOffset;\n\tuint16 m_attachType;\n\tfloat m_attachRotStep;\n\tuint32 m_attachWepAmmo;\n\tuint32 m_threatFlags;\n\tuint32 m_threatCheckTimer;\n\tuint32 m_threatCheckInterval;\n\tint32 m_delayedSoundID;\n\tuint32 m_delayedSoundTimer;\n\tuint32 m_lastSoundStart;\n\tuint32 m_soundStart;\n\tuint16 m_lastQueuedSound;\n\tuint16 m_queuedSound;\n\tbool m_canTalk;\n\tuint32 m_lastComment;\n\tCVector m_vecSpotToGuard;\n\tfloat m_radiusToGuard;\n\n\tstatic void *operator new(size_t);\n\tstatic void *operator new(size_t, int);\n\tstatic void operator delete(void*, size_t);\n\tstatic void operator delete(void*, int);\n\n\tCPed(uint32 pedType);\n\t~CPed(void);\n\n\tvoid DeleteRwObject();\n\tvoid SetModelIndex(uint32 mi);\n\tvoid ProcessControl(void);\n\tvoid Teleport(CVector);\n\tvoid PreRender(void);\n\tvoid Render(void);\n\tbool SetupLighting(void);\n\tvoid RemoveLighting(bool);\n\tvoid FlagToDestroyWhenNextProcessed(void);\n\tint32 ProcessEntityCollision(CEntity*, CColPoint*);\n\n\tvirtual void SetMoveAnim(void);\n\n\tvoid AddWeaponModel(int id);\n\tvoid AimGun(void);\n\tvoid KillPedWithCar(CVehicle *veh, float impulse);\n\tvoid Say(uint16 audio);\n\tvoid Say(uint16 audio, int32 time);\n\tvoid SetLookFlag(CEntity* target, bool keepTryingToLook, bool cancelPrevious = false);\n\tvoid SetLookFlag(float direction, bool keepTryingToLook, bool cancelPrevious = false);\n\tvoid SetLookTimer(int time);\n\tvoid SetDie(AnimationId anim = ANIM_STD_KO_FRONT, float arg1 = 4.0f, float arg2 = 0.0f);\n\tvoid SetDead(void);\n\tvoid ApplyHeadShot(eWeaponType weaponType, CVector pos, bool evenOnPlayer);\n\tvoid RemoveBodyPart(PedNode nodeId, int8 direction);\n\tbool OurPedCanSeeThisOne(CEntity *target, bool shootablesDoBlock = false);\n\tvoid Avoid(void);\n\tvoid Attack(void);\n\tvoid ClearAimFlag(void);\n\tvoid ClearLookFlag(void);\n\tvoid RestorePreviousState(void);\n\tvoid ClearAttack(void);\n\tbool IsPedHeadAbovePos(float zOffset);\n\tvoid RemoveWeaponModel(int modelId);\n\tvoid SetCurrentWeapon(eWeaponType weaponType);\n\tvoid SetCurrentWeapon(int weapon);\n\tvoid Duck(void);\n\tvoid ClearDuck(bool = false);\n\tvoid ClearPointGunAt(void);\n\tvoid BeingDraggedFromCar(void);\n\tvoid RestartNonPartialAnims(void);\n\tvoid LineUpPedWithCar(PedLineUpPhase phase);\n\tvoid SetPedPositionInCar(void);\n\tvoid PlayFootSteps(void);\n\tvoid QuitEnteringCar(void);\n\tvoid BuildPedLists(void);\n\tint32 GiveWeapon(eWeaponType weaponType, uint32 ammo, bool unused = true);\n\tvoid CalculateNewOrientation(void);\n\tfloat WorkOutHeadingForMovingFirstPerson(float);\n\tvoid CalculateNewVelocity(void);\n\tbool CanSeeEntity(CEntity*, float threshold = CAN_SEE_ENTITY_ANGLE_THRESHOLD);\n\tvoid RestorePreviousObjective(void);\n\tvoid SetIdle(void);\n#ifdef _MSC_VER\n\t__declspec(noinline) // workaround for a compiler bug, hooray MS :P\n#endif\n\tvoid SetObjective(eObjective, void*);\n\tvoid SetObjective(eObjective);\n\tvoid SetObjective(eObjective, int16, int16);\n\tvoid SetObjective(eObjective, CVector);\n\tvoid SetObjective(eObjective, float, const CVector&);\n\tvoid ClearChat(void);\n\tvoid InformMyGangOfAttack(CEntity*);\n\tvoid ReactToAttack(CEntity*);\n\tvoid SetDuck(uint32, bool = false);\n\tvoid RegisterThreatWithGangPeds(CEntity*);\n\tbool TurnBody(void);\n\tvoid Chat(void);\n\tvoid CheckAroundForPossibleCollisions(void);\n\tvoid SetSeek(CVector, float);\n\tvoid SetSeek(CEntity*, float);\n\tbool MakePhonecall(void);\n\tbool FacePhone(void);\n\tCPed *CheckForDeadPeds(void);\n\tbool CheckForExplosions(CVector2D &area);\n\tCPed *CheckForGunShots(void);\n\tuint8 CheckForPointBlankPeds(CPed*);\n\tbool CheckIfInTheAir(void);\n\tvoid ClearAll(void);\n\tvoid SetPointGunAt(CEntity*);\n\tbool Seek(void);\n\tbool SetWanderPath(int8);\n\tbool SetFollowPath(CVector dest, float radius, eMoveState state, CEntity*, CEntity*, int);\n\tbool SetFollowPathStatic(void);\n\tbool SetFollowPathDynamic(void);\n\tvoid ClearAttackByRemovingAnim(void);\n\tvoid SetStoredState(void);\n\tvoid StopNonPartialAnims(void);\n\tbool InflictDamage(CEntity*, eWeaponType, float, ePedPieceTypes, uint8);\n\tvoid ClearFlee(void);\n\tvoid ClearFall(void);\n\tvoid SetGetUp(void);\n\tvoid ClearInvestigateEvent(void);\n\tvoid ClearLeader(void);\n\tvoid ClearLook(void);\n\tvoid ClearObjective(void);\n\tvoid ClearPause(void);\n\tvoid ClearSeek(void);\n\tvoid ClearWeapons(void);\n\tvoid RestoreGunPosition(void);\n\tvoid RestoreHeadingRate(void);\n\tvoid SetAimFlag(CEntity* to);\n\tvoid SetAimFlag(float angle);\n\tvoid SetAmmo(eWeaponType weaponType, uint32 ammo);\n\tvoid SetEvasiveStep(CEntity*, uint8);\n\tvoid GrantAmmo(eWeaponType, uint32);\n\tvoid SetEvasiveDive(CPhysical*, uint8);\n\tvoid SetAttack(CEntity*);\n\tvoid StartFightAttack(uint8);\n\tvoid SetWaitState(eWaitState, void*);\n\tbool FightStrike(CVector&, bool);\n\tvoid FightHitPed(CPed*, CVector&, CVector&, int16);\n\tint32 ChooseAttackPlayer(uint8, bool);\n\tint32 ChooseAttackAI(uint8, bool);\n\tint GetLocalDirection(const CVector2D &);\n\tvoid StartFightDefend(uint8, uint8, uint8);\n\tvoid PlayHitSound(CPed*);\n\tvoid SetFall(int, AnimationId, uint8);\n\tvoid SetFlee(CEntity*, int);\n\tvoid SetFlee(CVector2D const &, int);\n\tvoid RemoveDrivebyAnims(void);\n\tvoid RemoveInCarAnims(void);\n\tvoid CollideWithPed(CPed*);\n\tvoid SetDirectionToWalkAroundObject(CEntity*);\n\tbool SetDirectionToWalkAroundVehicle(CVehicle*);\n\tvoid RemoveWeaponAnims(int, float);\n\tvoid CreateDeadPedMoney(void);\n\tvoid CreateDeadPedWeaponPickups(void);\n\tvoid CreateDeadPedPickupCoors(float *x, float *y, float *z);\n\tvoid SetAttackTimer(uint32);\n\tvoid SetBeingDraggedFromCar(CVehicle*, uint32, bool);\n\tvoid SetRadioStation(void);\n\tvoid SetBuyIceCream(void);\n\tvoid SetChat(CEntity*, uint32);\n\tvoid DeadPedMakesTyresBloody(void);\n\tvoid MakeTyresMuddySectorList(CPtrList&);\n\tbool DuckAndCover(void);\n\tvoid EndFight(uint8);\n\tvoid EnterCar(void);\n\tuint8 GetNearestTrainPedPosition(CVehicle*, CVector&);\n\tuint8 GetNearestTrainDoor(CVehicle*, CVector&);\n\tvoid ExitCar(void);\n\tvoid Fight(void);\n\tbool FindBestCoordsFromNodes(CVector, CVector*);\n\tvoid Wait(void);\n\tvoid ProcessObjective(void);\n\tCVector *SeekFollowingPath(void);\n\tvoid Flee(void);\n\tvoid FollowPath(void);\n\tCVector GetFormationPosition(void);\n\tvoid GetNearestDoor(CVehicle*, CVector&);\n\tbool GetNearestPassengerDoor(CVehicle*, CVector&);\n\tint GetNextPointOnRoute(void);\n\tint GetWeaponSlot(eWeaponType);\n\tbool CanWeRunAndFireWithWeapon(void);\n\tvoid GoToNearestDoor(CVehicle*);\n\tbool HaveReachedNextPointOnRoute(float);\n\tvoid Idle(void);\n\tvoid InTheAir(void);\n\tvoid SetLanding(void);\n\tvoid InvestigateEvent(void);\n\tbool IsPedDoingDriveByShooting(void);\n\tbool IsRoomToBeCarJacked(void);\n\tvoid SetInvestigateEvent(eEventType, CVector2D, float, uint16, float);\n\tbool LookForInterestingNodes(void);\n\tvoid LookForSexyCars(void);\n\tvoid LookForSexyPeds(void);\n\tvoid Mug(void);\n\tvoid MoveHeadToLook(void);\n\tvoid Pause(void);\n\tvoid ProcessBuoyancy(void);\n\tvoid ServiceTalking(void);\n\tvoid SetJump(void);\n\tvoid WanderPath(void);\n\tvoid ReactToPointGun(CEntity*);\n\tvoid SeekCar(void);\n\tbool PositionPedOutOfCollision(void);\n\tbool PositionAnyPedOutOfCollision(void);\n\tbool RunToReportCrime(eCrimeType);\n\tbool PlacePedOnDryLand(void);\n\tbool PossiblyFindBetterPosToSeekCar(CVector*, CVehicle*);\n\tvoid UpdateFromLeader(void);\n\tuint32 ScanForThreats(void);\n\tvoid SetEnterCar(CVehicle*, uint32);\n\tbool WarpPedToNearEntityOffScreen(CEntity*);\n\tvoid SetExitCar(CVehicle*, uint32);\n\tvoid SetFormation(eFormation);\n\tbool WillChat(CPed*);\n\tvoid SetEnterCar_AllClear(CVehicle*, uint32, uint32);\n\tvoid SetSolicit(uint32 time);\n\tvoid ScanForInterestingStuff(void);\n\tvoid WarpPedIntoCar(CVehicle*);\n\tvoid SetCarJack(CVehicle*);\n\tbool WarpPedToNearLeaderOffScreen(void);\n\tvoid Solicit(void);\n\tvoid SetExitBoat(CVehicle*);\n\tvoid ClearFollowPath();\n\tvoid GiveDelayedWeapon(eWeaponType weapon, uint32 ammo);\n\tvoid RequestDelayedWeapon();\n\tvoid AddInCarAnims(CVehicle* car, bool isDriver);\n\tbool CanBeDamagedByThisGangMember(CPed*);\n\tvoid AnswerMobile(void);\n\tvoid BuyIceCream(void);\n\tvoid CheckThreatValidity(void);\n\tvoid ClearAnswerMobile(void);\n\tvoid SetAnswerMobile(void);\n\tvoid AttachPedToEntity(CEntity*, CVector, uint16, float, eWeaponType);\n\tvoid DettachPedFromEntity();\n\tvoid PedShuffle();\n\tvoid DriveVehicle();\n\tvoid PositionAttachedPed();\n\tbool CanUseTorsoWhenLooking();\n\tvoid ScanForDelayedResponseThreats();\n\n\t// Static methods\n\tstatic CVector GetLocalPositionToOpenCarDoor(CVehicle *veh, uint32 component, float offset);\n\tstatic CVector GetPositionToOpenCarDoor(CVehicle *veh, uint32 component, float seatPosMult);\n\tstatic CVector GetPositionToOpenCarDoor(CVehicle* veh, uint32 component);\n\tstatic void Initialise(void);\n\tstatic void SetAnimOffsetForEnterOrExitVehicle(void);\n\tstatic void LoadFightData(void);\n\n\t// Callbacks\n\tstatic void PedGetupCB(CAnimBlendAssociation *assoc, void *arg);\n\tstatic void PedStaggerCB(CAnimBlendAssociation *assoc, void *arg);\n\tstatic void PedEvadeCB(CAnimBlendAssociation *assoc, void *arg);\n\tstatic void FinishDieAnimCB(CAnimBlendAssociation *assoc, void *arg);\n\tstatic void FinishedWaitCB(CAnimBlendAssociation *assoc, void *arg);\n\tstatic void FinishLaunchCB(CAnimBlendAssociation *assoc, void *arg);\n\tstatic void FinishHitHeadCB(CAnimBlendAssociation *assoc, void *arg);\n\tstatic void PedAnimGetInCB(CAnimBlendAssociation *assoc, void *arg);\n\tstatic void PedAnimDoorOpenCB(CAnimBlendAssociation *assoc, void *arg);\n\tstatic void PedAnimPullPedOutCB(CAnimBlendAssociation *assoc, void *arg);\n\tstatic void PedAnimDoorCloseCB(CAnimBlendAssociation *assoc, void *arg);\n\tstatic void PedSetInCarCB(CAnimBlendAssociation *assoc, void *arg);\n\tstatic void PedSetOutCarCB(CAnimBlendAssociation *assoc, void *arg);\n\tstatic void PedAnimAlignCB(CAnimBlendAssociation *assoc, void *arg);\n\tstatic void PedSetDraggedOutCarCB(CAnimBlendAssociation *assoc, void *arg);\n\tstatic void PedAnimStepOutCarCB(CAnimBlendAssociation *assoc, void *arg);\n\tstatic void PedSetInTrainCB(CAnimBlendAssociation *assoc, void *arg);\n#ifdef GTA_TRAIN\n\tstatic void PedSetOutTrainCB(CAnimBlendAssociation *assoc, void *arg);\n#endif\n\tstatic void FinishedAttackCB(CAnimBlendAssociation *assoc, void *arg);\n\tstatic void FinishedReloadCB(CAnimBlendAssociation *assoc, void *arg);\n\tstatic void FinishFightMoveCB(CAnimBlendAssociation *assoc, void *arg);\n\tstatic void PedAnimDoorCloseRollingCB(CAnimBlendAssociation *assoc, void *arg);\n\tstatic void FinishJumpCB(CAnimBlendAssociation *assoc, void *arg);\n\tstatic void PedLandCB(CAnimBlendAssociation *assoc, void *arg);\n\tstatic void RestoreHeadingRateCB(CAnimBlendAssociation *assoc, void *arg);\n\tstatic void PedSetQuickDraggedOutCarPositionCB(CAnimBlendAssociation *assoc, void *arg);\n\tstatic void PedSetDraggedOutCarPositionCB(CAnimBlendAssociation *assoc, void *arg);\n\tstatic void DeleteSunbatheIdleAnimCB(CAnimBlendAssociation *assoc, void *arg);\n\tstatic void PedSetPreviousStateCB(CAnimBlendAssociation *assoc, void *arg);\n\tstatic void PedAnimShuffleCB(CAnimBlendAssociation *assoc, void *arg);\n\tstatic void PedSetGetInCarPositionCB(CAnimBlendAssociation* assoc, void* arg);\n\n\tbool IsPlayer(void) const;\n\tbool IsFemale(void) { return m_nPedType == PEDTYPE_CIVFEMALE || m_nPedType == PEDTYPE_PROSTITUTE; }\n\tbool UseGroundColModel(void);\n\tbool CanSetPedState(void);\n\tbool IsPedInControl(void);\n\tbool CanPedDriveOff(void);\n\tbool CanBeDeleted(void);\n\tbool CanBeDeletedEvenInVehicle(void);\n\tbool CanStrafeOrMouseControl(void);\n\tbool CanPedReturnToState(void);\n\tvoid SetMoveState(eMoveState);\n\tbool IsTemporaryObjective(eObjective objective);\n\tvoid SetObjectiveTimer(int);\n\tbool SelectGunIfArmed(void);\n\tbool IsPointerValid(void);\n\tvoid SortPeds(CPed**, int, int);\n\tvoid ForceStoredObjective(eObjective);\n\tvoid SetStoredObjective(void);\n\tvoid SetLeader(CEntity* leader);\n\tvoid SetPedStats(ePedStats);\n\tbool IsGangMember(void) const;\n\tvoid Die(void);\n#ifdef GTA_TRAIN\n\tvoid EnterTrain(void);\n\tvoid ExitTrain(void);\n\tvoid SetExitTrain(CVehicle*);\n\tvoid SetPedPositionInTrain(void);\n\tvoid LineUpPedWithTrain(void);\n\tvoid SetEnterTrain(CVehicle*, uint32);\n#endif\n\tvoid Fall(void);\n\tbool IsPedShootable(void);\n\tvoid Look(void);\n\tvoid SetInTheAir(void);\n\tvoid RestoreHeadPosition(void);\n\tvoid PointGunAt(void);\n\tbool ServiceTalkingWhenDead(void);\n\tvoid SetShootTimer(uint32);\n\tvoid SetSeekCar(CVehicle*, uint32);\n\tvoid SetSeekBoatPosition(CVehicle*);\n\tvoid WanderRange(void);\n\tvoid SetFollowRoute(int16, int16);\n\tvoid SeekBoatPosition(void);\n\tvoid UpdatePosition(void);\n\tCObject *SpawnFlyingComponent(int, int8);\n\tvoid SetCarJack_AllClear(CVehicle*, uint32, uint32);\n\tbool CanPedJumpThis(CEntity *unused, CVector *damageNormal = nil);\n\tvoid SetNewAttraction(CPedAttractor* pAttractor, const CVector& pos, float, float, int);\n\tvoid ClearWaitState(void);\n\tvoid Undress(const char*);\n\tvoid Dress(void);\n\tint32 KillCharOnFootMelee(CVector&, CVector&, CVector&);\n\tint32 KillCharOnFootArmed(CVector&, CVector&, CVector&);\n\tvoid SetLook(CEntity* to);\n\tvoid SetLook(float direction);\n\n\tbool HasWeaponSlot(uint8 slot) { return m_weapons[slot].m_eWeaponType != WEAPONTYPE_UNARMED; }\n\tCWeapon& GetWeapon(uint8 slot) { return m_weapons[slot]; }\n\tCWeapon *GetWeapon(void) { return &m_weapons[m_currentWeapon]; }\n\n\tPedState GetPedState(void) { return m_nPedState; }\n\tvoid SetPedState(PedState state) \n\t{\n\t\tif (GetPedState() == PED_FOLLOW_PATH && state != PED_FOLLOW_PATH)\n\t\t\tClearFollowPath();\n\t\tm_nPedState = state;\n\t}\n\tbool Dead(void) { return m_nPedState == PED_DEAD; }\n\tbool Dying(void) { return m_nPedState == PED_DIE; }\n\tbool DyingOrDead(void) { return m_nPedState == PED_DIE || m_nPedState == PED_DEAD; }\n\tbool OnGround(void) { return m_nPedState == PED_FALL || m_nPedState == PED_DIE || m_nPedState == PED_DEAD; }\n\tbool OnGroundOrGettingUp(void) { return OnGround() || m_nPedState == PED_GETUP; }\n\t\n\tbool Driving(void) { return m_nPedState == PED_DRIVING; }\n\tbool InVehicle(void) { return bInVehicle && m_pMyVehicle; } // True when ped is sitting/standing in vehicle, not in enter/exit state.\n\tbool EnteringCar(void) { return m_nPedState == PED_ENTER_CAR || m_nPedState == PED_CARJACK; }\n\tbool HasAttractor(void);\n\tbool IsUseAttractorObjective(eObjective obj) {\n\t\treturn obj == OBJECTIVE_GOTO_ATM_ON_FOOT || obj == OBJECTIVE_GOTO_ICE_CREAM_VAN_ON_FOOT ||\n\t\t\tobj == OBJECTIVE_GOTO_PIZZA_ON_FOOT || obj == OBJECTIVE_GOTO_SEAT_ON_FOOT ||\n\t\t\tobj == OBJECTIVE_GOTO_SHELTER_ON_FOOT || obj == OBJECTIVE_GOTO_BUS_STOP_ON_FOOT;\n\t}\n\n\tvoid ReplaceWeaponWhenExitingVehicle(void);\n\tvoid RemoveWeaponWhenEnteringVehicle(void);\n\tbool IsNotInWreckedVehicle()\n\t{\n\t\treturn m_pMyVehicle != nil && ((CEntity*)m_pMyVehicle)->GetStatus() != STATUS_WRECKED;\n\t}\n\n\t// My names. Inlined in VC\n\tAnimationId GetFireAnimNotDucking(CWeaponInfo* weapon) {\n\t\tif (m_nPedType == PEDTYPE_COP && weapon->IsFlagSet(WEAPONFLAG_COP3_RD))\n\t\t\treturn Get3rdFireAnim(weapon);\n\t\telse\n\t\t\treturn GetPrimaryFireAnim(weapon);\n\t}\n\n\tstatic AnimationId Get3rdFireAnim(CWeaponInfo* weapon) {\n\t\tif (weapon->IsFlagSet(WEAPONFLAG_COP3_RD))\n\t\t\treturn ANIM_WEAPON_FIRE_3RD;\n\t\telse\n\t\t\treturn (AnimationId)0;\n\t}\n\n\tstatic AnimationId GetFireAnimGround(CWeaponInfo* weapon, bool kickFloorIfNone = true) {\n\t\tif (weapon->IsFlagSet(WEAPONFLAG_GROUND_2ND))\n\t\t\treturn ANIM_WEAPON_CROUCHFIRE;\n\t\telse if (weapon->IsFlagSet(WEAPONFLAG_GROUND_3RD))\n\t\t\treturn ANIM_WEAPON_FIRE_3RD;\n\t\telse if (kickFloorIfNone)\n\t\t\treturn ANIM_STD_KICKGROUND;\n\t\telse\n\t\t\treturn (AnimationId)0;\n\t}\n\n\tstatic AnimationId GetPrimaryFireAnim(CWeaponInfo* weapon) {\n\t\tif (weapon->IsFlagSet(WEAPONFLAG_ANIMDETONATE))\n\t\t\treturn ANIM_STD_DETONATE;\n\t\telse\n\t\t\treturn ANIM_WEAPON_FIRE;\n\t}\n\n\tstatic AnimationId GetCrouchReloadAnim(CWeaponInfo* weapon) {\n\t\tif (weapon->IsFlagSet(WEAPONFLAG_RELOAD))\n\t\t\treturn ANIM_WEAPON_CROUCHRELOAD;\n\t\telse\n\t\t\treturn (AnimationId)0;\n\t}\n\n\tstatic AnimationId GetCrouchFireAnim(CWeaponInfo* weapon) {\n\t\tif (weapon->IsFlagSet(WEAPONFLAG_CROUCHFIRE))\n\t\t\treturn ANIM_WEAPON_CROUCHFIRE;\n\t\telse\n\t\t\treturn (AnimationId)0;\n\t}\n\n\tstatic AnimationId GetReloadAnim(CWeaponInfo* weapon) {\n\t\tif (weapon->IsFlagSet(WEAPONFLAG_RELOAD))\n\t\t\treturn ANIM_WEAPON_RELOAD;\n\t\telse\n\t\t\treturn (AnimationId)0;\n\t}\n\n\tstatic AnimationId GetFightIdleWithMeleeAnim(CWeaponInfo* weapon) {\n\t\tif (weapon->IsFlagSet(WEAPONFLAG_FIGHTMODE))\n\t\t\treturn ANIM_MELEE_IDLE_FIGHTMODE;\n\t\telse\n\t\t\treturn (AnimationId)0;\n\t}\n\n\tstatic AnimationId GetFinishingAttackAnim(CWeaponInfo* weapon) {\n\t\tif (weapon->IsFlagSet(WEAPONFLAG_FINISH_3RD))\n\t\t\treturn ANIM_MELEE_ATTACK_FINISH;\n\t\telse\n\t\t\treturn (AnimationId)0;\n\t}\n\n\tstatic AnimationId GetSecondFireAnim(CWeaponInfo* weapon) {\n\t\tif (weapon->IsFlagSet(WEAPONFLAG_USE_2ND))\n\t\t\treturn ANIM_WEAPON_FIRE_2ND;\n\t\telse\n\t\t\treturn (AnimationId)0;\n\t}\n\t\n\tstatic AnimationId GetMeleeStartAnim(CWeaponInfo* weapon) {\n\t\tif (weapon->IsFlagSet(WEAPONFLAG_PARTIALATTACK))\n\t\t\treturn ANIM_MELEE_ATTACK_START;\n\t\telse\n\t\t\treturn (AnimationId)0;\n\t}\n\n\tstatic AnimationId GetThrowAnim(CWeaponInfo *weapon)\n\t{\n\t\tif (weapon->IsFlagSet(WEAPONFLAG_THROW))\n\t\t\treturn ANIM_THROWABLE_START_THROW;\n\t\telse\n\t\t\treturn (AnimationId)0;\n\t}\n\t// --\n\n\t// My additions, because there were many, many instances of that.\n\tinline void SetFindPathAndFlee(CEntity *fleeFrom, int time, bool walk = false)\n\t{\n\t\tSetFlee(fleeFrom, time);\n\t\tbUsePedNodeSeek = true;\n\t\tm_pNextPathNode = nil;\n\t\tif (walk)\n\t\t\tSetMoveState(PEDMOVE_WALK);\n\t}\n\n\tinline void SetFindPathAndFlee(CVector2D const &from, int time, bool walk = false)\n\t{\n\t\tSetFlee(from, time);\n\t\tbUsePedNodeSeek = true;\n\t\tm_pNextPathNode = nil;\n\t\tif (walk)\n\t\t\tSetMoveState(PEDMOVE_WALK);\n\t}\n\t// --\n\n\tinline void SetWeaponLockOnTarget(CEntity *target)\n\t{\n\t\tif (m_pPointGunAt)\n\t\t\tm_pPointGunAt->CleanUpOldReference(&m_pPointGunAt);\n\n\t\tm_pPointGunAt = (CPed*)target;\n\t\tif (target)\n\t\t\t((CEntity*)target)->RegisterReference(&m_pPointGunAt);\n\t}\n\n\t// Using this to abstract nodes of skinned and non-skinned meshes\n\tCVector GetNodePosition(int32 node)\n\t{\n\t\tRwV3d pos = { 0.0f, 0.0f, 0.0f };\n\t\tRpHAnimHierarchy *hier = GetAnimHierarchyFromSkinClump(GetClump());\n\t\tint32 idx = RpHAnimIDGetIndex(hier, m_pFrames[node]->nodeID);\n\t\tRwMatrix *mats = RpHAnimHierarchyGetMatrixArray(hier);\n\t\tpos = mats[idx].pos;\n\t\treturn pos;\n\t}\n\tvoid TransformToNode(CVector &pos, int32 node)\n\t{\n\t\tRpHAnimHierarchy *hier = GetAnimHierarchyFromSkinClump(GetClump());\n\t\tint32 idx = RpHAnimIDGetIndex(hier, m_pFrames[node]->nodeID);\n\t\tRwMatrix *mats = RpHAnimHierarchyGetMatrixArray(hier);\n\t\tRwV3dTransformPoints(&pos, &pos, 1, &mats[idx]);\n\t}\n\n\t// set by 0482:set_threat_reaction_range_multiplier opcode\n\tstatic uint16 nThreatReactionRangeMultiplier;\n\n\t// set by 0481:set_enter_car_range_multiplier opcode\n\tstatic uint16 nEnterCarRangeMultiplier;\n\n\tstatic bool bNastyLimbsCheat;\n\tstatic bool bFannyMagnetCheat;\n\tstatic bool bPedCheat3;\n\tstatic CVector2D ms_vec2DFleePosition;\n\n#ifndef MASTER\n\t// Mobile things\n\tvoid DebugDrawPedDestination(CPed *, int, int);\n\tvoid DebugDrawPedDesiredHeading(CPed *, int, int);\n\tvoid DebugDrawCollisionRadius(float, float, float, float, int);\n\tvoid DebugDrawVisionRange(CVector, float);\n\tvoid DebugDrawVisionSimple(CVector, float);\n\tvoid DebugDrawLook();\n\tvoid DebugDrawPedPsyche();\n\tvoid DebugDrawDebugLines();\n\n\tstatic void SwitchDebugDisplay(void);\n\tstatic int GetDebugDisplay(void);\n\n\tvoid DebugDrawLookAtPoints();\n\tvoid DebugRenderOnePedText(void);\n\tvoid DebugRenderClosePedText();\n#endif\n\n#ifdef COMPATIBLE_SAVES\n\tvirtual void Save(uint8*& buf);\n\tvirtual void Load(uint8*& buf);\n#endif\n};\n\nvoid FinishTalkingOnMobileCB(CAnimBlendAssociation* assoc, void* arg);\nvoid StartTalkingOnMobileCB(CAnimBlendAssociation* assoc, void* arg);\nvoid PlayRandomAnimationsFromAnimBlock(CPed* ped, AssocGroupId animGroup, uint32 first, uint32 amount);\n\nVALIDATE_SIZE(CPed, 0x5F4);\n\nbool IsPedPointerValid(CPed*);\nbool IsPedPointerValid_NotInWorld(CPed*);\n"
  },
  {
    "path": "src/peds/PedAI.cpp",
    "content": "#include \"common.h\"\n\n#include \"main.h\"\n#include \"Particle.h\"\n#include \"RpAnimBlend.h\"\n#include \"Ped.h\"\n#include \"Wanted.h\"\n#include \"AnimBlendAssociation.h\"\n#include \"DMAudio.h\"\n#include \"General.h\"\n#include \"HandlingMgr.h\"\n#include \"Replay.h\"\n#include \"Camera.h\"\n#include \"PedPlacement.h\"\n#include \"ZoneCull.h\"\n#include \"Pad.h\"\n#include \"Pickups.h\"\n#include \"Train.h\"\n#include \"PedRoutes.h\"\n#include \"CopPed.h\"\n#include \"Script.h\"\n#include \"CarCtrl.h\"\n#include \"WaterLevel.h\"\n#include \"CarAI.h\"\n#include \"Zones.h\"\n#include \"Cranes.h\"\n#include \"PedAttractor.h\"\n#include \"Bike.h\"\n#include \"Weather.h\"\n#include \"GameLogic.h\"\n#include \"Streaming.h\"\n\nCVector vecPedCarDoorAnimOffset;\nCVector vecPedCarDoorLoAnimOffset;\nCVector vecPedVanRearDoorAnimOffset;\nCVector vecPedQuickDraggedOutCarAnimOffset;\nCVector vecPedDraggedOutCarAnimOffset;\nCVector vecPedTrainDoorAnimOffset;\nCVector vecPedStdBikeJumpRhsAnimOffset;\nCVector vecPedVespaBikeJumpRhsAnimOffset;\nCVector vecPedHarleyBikeJumpRhsAnimOffset;\nCVector vecPedDirtBikeJumpRhsAnimOffset;\nCVector vecPedBikeKickAnimOffset;\n\nvoid\nCPed::SetObjectiveTimer(int time)\n{\n\tif (time == 0) {\n\t\tm_objectiveTimer = 0;\n\t} else if (CTimer::GetTimeInMilliseconds() > m_objectiveTimer) {\n\t\tm_objectiveTimer = CTimer::GetTimeInMilliseconds() + time;\n\t}\n}\n\nvoid\nCPed::SetStoredObjective(void)\n{\n\tif (m_objective == m_prevObjective)\n\t\treturn;\n\n\tswitch (m_objective) {\n\t\tcase OBJECTIVE_FLEE_ON_FOOT_TILL_SAFE:\n\t\tcase OBJECTIVE_KILL_CHAR_ON_FOOT:\n\t\tcase OBJECTIVE_KILL_CHAR_ANY_MEANS:\n\t\tcase OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE:\n\t\tcase OBJECTIVE_FLEE_CHAR_ON_FOOT_ALWAYS:\n\t\tcase OBJECTIVE_GOTO_CHAR_ON_FOOT:\n\t\tcase OBJECTIVE_GOTO_CHAR_ON_FOOT_WALKING:\n\t\tcase OBJECTIVE_HASSLE_CHAR:\n\t\tcase OBJECTIVE_FOLLOW_CHAR_IN_FORMATION:\n\t\tcase OBJECTIVE_LEAVE_CAR:\n\t\tcase OBJECTIVE_ENTER_CAR_AS_PASSENGER:\n\t\tcase OBJECTIVE_ENTER_CAR_AS_DRIVER:\n\t\tcase OBJECTIVE_GOTO_AREA_ON_FOOT:\n\t\tcase OBJECTIVE_RUN_TO_AREA:\n\t\tcase OBJECTIVE_GOTO_SEAT_ON_FOOT:\n\t\tcase OBJECTIVE_GOTO_ATM_ON_FOOT:\n\t\tcase OBJECTIVE_GOTO_BUS_STOP_ON_FOOT:\n\t\tcase OBJECTIVE_GOTO_PIZZA_ON_FOOT:\n\t\tcase OBJECTIVE_GOTO_SHELTER_ON_FOOT:\n\t\tcase OBJECTIVE_SPRINT_TO_AREA:\n\t\tcase OBJECTIVE_GOTO_ICE_CREAM_VAN_ON_FOOT:\n\t\t\treturn;\n\t\tdefault:\n\t\t\tm_prevObjective = m_objective;\n\t}\n}\n\nvoid\nCPed::ForceStoredObjective(eObjective objective)\n{\n\tif (objective != OBJECTIVE_ENTER_CAR_AS_DRIVER && objective != OBJECTIVE_ENTER_CAR_AS_PASSENGER) {\n\t\tm_prevObjective = m_objective;\n\t\treturn;\n\t}\n\n\tswitch (m_objective) {\n\t\tcase OBJECTIVE_FLEE_ON_FOOT_TILL_SAFE:\n\t\tcase OBJECTIVE_KILL_CHAR_ON_FOOT:\n\t\tcase OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE:\n\t\tcase OBJECTIVE_FLEE_CHAR_ON_FOOT_ALWAYS:\n\t\tcase OBJECTIVE_GOTO_CHAR_ON_FOOT:\n\t\tcase OBJECTIVE_GOTO_CHAR_ON_FOOT_WALKING:\n\t\tcase OBJECTIVE_HASSLE_CHAR:\n\t\tcase OBJECTIVE_ENTER_CAR_AS_PASSENGER:\n\t\tcase OBJECTIVE_ENTER_CAR_AS_DRIVER:\n\t\tcase OBJECTIVE_GOTO_AREA_ON_FOOT:\n\t\tcase OBJECTIVE_RUN_TO_AREA:\n\t\tcase OBJECTIVE_GOTO_SEAT_ON_FOOT:\n\t\tcase OBJECTIVE_GOTO_ATM_ON_FOOT:\n\t\tcase OBJECTIVE_GOTO_BUS_STOP_ON_FOOT:\n\t\tcase OBJECTIVE_GOTO_PIZZA_ON_FOOT:\n\t\tcase OBJECTIVE_GOTO_SHELTER_ON_FOOT:\n\t\tcase OBJECTIVE_SPRINT_TO_AREA:\n\t\tcase OBJECTIVE_GOTO_ICE_CREAM_VAN_ON_FOOT:\n\t\t\treturn;\n\t\tdefault:\n\t\t\tm_prevObjective = m_objective;\n\t}\n}\n\nbool\nCPed::IsTemporaryObjective(eObjective objective)\n{\n\treturn objective == OBJECTIVE_LEAVE_CAR || objective == OBJECTIVE_SET_LEADER ||\n\t\tobjective == OBJECTIVE_LEAVE_CAR_AND_DIE || objective == OBJECTIVE_ENTER_CAR_AS_DRIVER ||\n\t\tobjective == OBJECTIVE_ENTER_CAR_AS_PASSENGER;\n}\n\nvoid\nCPed::SetObjective(eObjective newObj)\n{\n\tif (DyingOrDead() || m_attachedTo)\n\t\treturn;\n\n\tif (newObj == OBJECTIVE_NONE) {\n\t\tif ((m_objective == OBJECTIVE_LEAVE_CAR || m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER || m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER\n\t\t\t|| m_objective == OBJECTIVE_LEAVE_CAR_AND_DIE) && !IsPlayer() && !IsPedInControl()) {\n\n\t\t\tbStartWanderPathOnFoot = true;\n\t\t} else {\n\t\t\tm_objective = OBJECTIVE_NONE;\n\t\t\tm_prevObjective = OBJECTIVE_NONE;\n\t\t}\n\t} else if (m_prevObjective != newObj || m_prevObjective == OBJECTIVE_NONE) {\n\t\tSetObjectiveTimer(0);\n\n\t\tif (m_objective == newObj)\n\t\t\treturn;\n\n\t\tif (IsTemporaryObjective(m_objective)) {\n\t\t\tm_prevObjective = newObj;\n\t\t} else {\n\t\t\tif (m_objective != newObj)\n\t\t\t\tSetStoredObjective();\n\n\t\t\tm_objective = newObj;\n\t\t}\n\t\tbObjectiveCompleted = false;\n\n\t\tswitch (newObj) {\n\t\t\tcase OBJECTIVE_NONE:\n\t\t\t\tm_prevObjective = OBJECTIVE_NONE;\n\t\t\t\tbreak;\n\t\t\tcase OBJECTIVE_HAIL_TAXI:\n\t\t\t\tm_nWaitTimer = 0;\n\t\t\t\tSetIdle();\n\t\t\t\tSetMoveState(PEDMOVE_STILL);\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n}\n\nvoid\nCPed::SetObjective(eObjective newObj, void *entity)\n{\n\tif (DyingOrDead())\n\t\treturn;\n\n\tif (m_prevObjective == newObj && m_prevObjective != OBJECTIVE_NONE)\n\t\treturn;\n\n\tif (entity == this)\n\t\treturn;\n\n\tif (m_attachedTo && newObj != OBJECTIVE_KILL_CHAR_ON_FOOT && newObj != OBJECTIVE_KILL_CHAR_ANY_MEANS && newObj != OBJECTIVE_DESTROY_OBJECT && newObj != OBJECTIVE_DESTROY_CAR)\n\t\treturn;\n\n\tif (m_objective == newObj) {\n\t\tswitch (newObj) {\n\t\t\tcase OBJECTIVE_KILL_CHAR_ON_FOOT:\n\t\t\tcase OBJECTIVE_KILL_CHAR_ANY_MEANS:\n\t\t\tcase OBJECTIVE_GOTO_CHAR_ON_FOOT:\n\t\t\tcase OBJECTIVE_GOTO_CHAR_ON_FOOT_WALKING:\n\t\t\tcase OBJECTIVE_HASSLE_CHAR:\n\t\t\tcase OBJECTIVE_FOLLOW_CHAR_IN_FORMATION:\n\t\t\tcase OBJECTIVE_GOTO_AREA_ANY_MEANS:\n\t\t\tcase OBJECTIVE_GUARD_ATTACK:\n\t\t\tcase OBJECTIVE_KILL_CHAR_ON_BOAT:\n\t\t\tcase OBJECTIVE_SOLICIT_FOOT:\n\t\t\t\tif (m_pedInObjective == entity)\n\t\t\t\t\treturn;\n\t\t\t\tbreak;\n\t\t\tcase OBJECTIVE_LEAVE_CAR:\n\t\t\tcase OBJECTIVE_FLEE_CAR:\n\t\t\tcase OBJECTIVE_LEAVE_CAR_AND_DIE:\n\t\t\t\treturn;\n\t\t\tcase OBJECTIVE_ENTER_CAR_AS_PASSENGER:\n\t\t\tcase OBJECTIVE_ENTER_CAR_AS_DRIVER:\n\t\t\tcase OBJECTIVE_DESTROY_CAR:\n\t\t\tcase OBJECTIVE_SOLICIT_VEHICLE:\n\t\t\tcase OBJECTIVE_BUY_ICE_CREAM:\n\t\t\t\tif (m_carInObjective == entity)\n\t\t\t\t\treturn;\n\n\t\t\t\tif (newObj == OBJECTIVE_BUY_ICE_CREAM && bBoughtIceCream)\n\t\t\t\t\treturn;\n\n\t\t\t\tbreak;\n\t\t\tcase OBJECTIVE_SET_LEADER:\n\t\t\t\tif (m_leader == entity)\n\t\t\t\t\treturn;\n\t\t\t\tbreak;\n\t\t\tcase OBJECTIVE_AIM_GUN_AT:\n\t\t\t\tif (m_pedInObjective == entity)\n\t\t\t\t\treturn;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t} else {\n\t\tif (newObj != OBJECTIVE_WAIT_IN_CAR_THEN_GET_OUT && (newObj == OBJECTIVE_LEAVE_CAR || newObj == OBJECTIVE_LEAVE_CAR_AND_DIE)\n\t\t\t&& !bInVehicle)\n\t\t\treturn;\n\t}\n\n\tbObjectiveCompleted = false;\n\tClearPointGunAt();\n\tm_objectiveTimer = 0;\n\tif (IsTemporaryObjective(m_objective) && !IsTemporaryObjective(newObj)) {\n\t\tm_prevObjective = newObj;\n\t} else {\n\t\tif (m_objective != newObj) {\n\t\t\tif (IsTemporaryObjective(newObj))\n\t\t\t\tForceStoredObjective(newObj);\n\t\t\telse\n\t\t\t\tSetStoredObjective();\n\t\t}\n\t\tm_objective = newObj;\n\t}\n\n\tswitch (newObj) {\n\t\tcase OBJECTIVE_WAIT_ON_FOOT_FOR_COP:\n\t\t\tm_pedInObjective = (CPed*)entity;\n\t\t\tm_pedInObjective->RegisterReference((CEntity**)&m_pedInObjective);\n\t\t\tSetIdle();\n\t\t\tSetLook(m_pedInObjective);\n\t\t\tbreak;\n\t\tcase OBJECTIVE_WAIT_IN_CAR_THEN_GET_OUT:\n\n\t\t\t// In this special case, entity parameter isn't CEntity, but int.\n\t\t\tSetObjectiveTimer((uintptr)entity);\n\t\t\tbreak;\n\t\tcase OBJECTIVE_KILL_CHAR_ON_FOOT:\n\t\tcase OBJECTIVE_KILL_CHAR_ANY_MEANS:\n\t\tcase OBJECTIVE_MUG_CHAR:\n\t\tcase OBJECTIVE_KILL_CHAR_ON_BOAT:\n\t\t\tm_pNextPathNode = nil;\n\t\t\tbUsePedNodeSeek = false;\n\n\t\t\tif (m_pedInObjective)\n\t\t\t\tm_pedInObjective->CleanUpOldReference((CEntity**)&m_pedInObjective);\n\t\t\tif (m_pLookTarget)\n\t\t\t\tm_pLookTarget->CleanUpOldReference(&m_pLookTarget);\n\t\t\t\n\t\t\tm_pLookTarget = (CEntity*)entity;\n\t\t\tm_pedInObjective = (CPed*)entity;\n\t\t\tm_vecSeekPos = CVector(0.0f, 0.0f, 0.0f);\n\t\t\tm_pedInObjective->RegisterReference((CEntity**)&m_pedInObjective);\n\t\t\t// m_pLookTarget = (CEntity*)entity; // duplicate\n\t\t\tm_pLookTarget->RegisterReference((CEntity**)&m_pLookTarget);\n\t\t\tbreak;\n\t\tcase OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE:\n\t\tcase OBJECTIVE_FLEE_CHAR_ON_FOOT_ALWAYS:\n\t\tcase OBJECTIVE_GOTO_CHAR_ON_FOOT:\n\t\tcase OBJECTIVE_GOTO_CHAR_ON_FOOT_WALKING:\n\t\tcase OBJECTIVE_HASSLE_CHAR:\n\t\tcase OBJECTIVE_GUARD_ATTACK:\n\n\t\t\tif (m_pedInObjective)\n\t\t\t\tm_pedInObjective->CleanUpOldReference((CEntity**)&m_pedInObjective);\n\t\t\tm_pedInObjective = (CPed*)entity;\n\t\t\tm_vecSeekPos = CVector(0.0f, 0.0f, 0.0f);\n\t\t\tm_pedInObjective->RegisterReference((CEntity**)&m_pedInObjective);\n\t\t\tbreak;\n\t\tcase OBJECTIVE_FOLLOW_CHAR_IN_FORMATION:\n\t\t\tm_pedInObjective = (CPed*)entity;\n\t\t\tm_pedInObjective->RegisterReference((CEntity**)&m_pedInObjective);\n\t\t\tm_pedFormation = FORMATION_REAR;\n\t\t\tbreak;\n\t\tcase OBJECTIVE_LEAVE_CAR:\n\t\tcase OBJECTIVE_LEAVE_CAR_AND_DIE:\n\t\tcase OBJECTIVE_FLEE_CAR:\n\t\t\tm_carInObjective = (CVehicle*)entity;\n\t\t\tm_carInObjective->RegisterReference((CEntity **)&m_carInObjective);\n\t\t\tif (m_carInObjective->bIsBus && m_leaveCarTimer == 0) {\n\t\t\t\tfor (int i = 0; i < m_carInObjective->m_nNumMaxPassengers; i++) {\n\t\t\t\t\tif (m_carInObjective->pPassengers[i] == this) {\n\t\t\t\t\t\tm_leaveCarTimer = CTimer::GetTimeInMilliseconds() + 1200 * i;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tbreak;\n\t\tcase OBJECTIVE_DESTROY_OBJECT:\n\t\t\tSetWeaponLockOnTarget((CEntity*)entity);\n\t\t\tbreak;\n\t\tcase OBJECTIVE_ENTER_CAR_AS_PASSENGER:\n\t\tcase OBJECTIVE_ENTER_CAR_AS_DRIVER:\n\t\t\tif (m_nMoveState == PEDMOVE_STILL)\n\t\t\t\tSetMoveState(PEDMOVE_RUN);\n\n\t\t\tif (((CVehicle*)entity)->IsBoat() && !IsPlayer() && m_pCurrentPhysSurface != entity) {\n\t\t\t\tRestorePreviousObjective();\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t// fall through\n\t\tcase OBJECTIVE_DESTROY_CAR:\n\t\tcase OBJECTIVE_SOLICIT_VEHICLE:\n\t\tcase OBJECTIVE_BUY_ICE_CREAM:\n\t\t\tm_carInObjective = (CVehicle*)entity;\n\t\t\tm_carInObjective->RegisterReference((CEntity**)&m_carInObjective);\n\t\t\tm_pSeekTarget = m_carInObjective;\n\t\t\tm_pSeekTarget->RegisterReference((CEntity**)&m_pSeekTarget);\n\t\t\tm_vecSeekPos = CVector(0.0f, 0.0f, 0.0f);\n\t\t\tif (newObj == OBJECTIVE_SOLICIT_VEHICLE) {\n\t\t\t\tm_objectiveTimer = CTimer::GetTimeInMilliseconds() + 10000;\n\t\t\t} else if (m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER && CharCreatedBy == MISSION_CHAR &&\n\t\t\t\t\t(m_carInObjective->GetStatus() == STATUS_PLAYER_DISABLED || CPad::GetPad(CWorld::PlayerInFocus)->ArePlayerControlsDisabled())) {\n\t\t\t\tSetObjectiveTimer(14000);\n\t\t\t} else {\n\t\t\t\tm_objectiveTimer = 0;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase OBJECTIVE_SET_LEADER:\n\t\t\tSetLeader((CEntity*)entity);\n\t\t\tRestorePreviousObjective();\n\t\t\tbreak;\n\t\tcase OBJECTIVE_AIM_GUN_AT:\n\t\t\tm_pedInObjective = (CPed*)entity;\n\t\t\tm_pedInObjective->RegisterReference((CEntity**)&m_pedInObjective);\n\t\t\tbreak;\n\t\tcase OBJECTIVE_SOLICIT_FOOT:\n\t\t\tm_pedInObjective = (CPed*)entity;\n\t\t\tm_pedInObjective->RegisterReference((CEntity**)&m_pedInObjective);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t}\n}\n\n// Only used in 01E1: SET_CHAR_OBJ_FOLLOW_ROUTE opcode\n// IDA fails very badly in here, puts a fake loop and ignores SetFollowRoute call...\nvoid\nCPed::SetObjective(eObjective newObj, int16 routePoint, int16 routeType)\n{\n\tif (DyingOrDead())\n\t\treturn;\n\n\tif (m_prevObjective == newObj && m_prevObjective != OBJECTIVE_NONE)\n\t\treturn;\n\n\tif (m_objective == newObj && newObj == OBJECTIVE_FOLLOW_ROUTE && m_routeLastPoint == routePoint && m_routeType == routeType)\n\t\treturn;\n\n\tClearPointGunAt();\n\tSetObjectiveTimer(0);\n\n\tbObjectiveCompleted = false;\n\tif (IsTemporaryObjective(m_objective)) {\n\t\tm_prevObjective = newObj;\n\t} else {\n\t\tif (m_objective != newObj)\n\t\t\tSetStoredObjective();\n\n\t\tm_objective = newObj;\n\t}\n\n\tif (newObj == OBJECTIVE_FOLLOW_ROUTE) {\n\t\tSetFollowRoute(routePoint, routeType);\n\t}\n}\n\nvoid\nCPed::SetObjective(eObjective newObj, CVector dest)\n{\n\tif (DyingOrDead())\n\t\treturn;\n\n\tif (m_prevObjective != OBJECTIVE_NONE && m_prevObjective == newObj)\n\t\treturn;\n\n\tif (m_objective == newObj) {\n\t\tif (newObj == OBJECTIVE_GOTO_AREA_ANY_MEANS || newObj == OBJECTIVE_GOTO_AREA_ON_FOOT || newObj == OBJECTIVE_RUN_TO_AREA || newObj == OBJECTIVE_SPRINT_TO_AREA) {\n\t\t\tif (m_nextRoutePointPos == dest)\n\t\t\t\treturn;\n\t\t} else if (newObj == OBJECTIVE_GUARD_SPOT) {\n\t\t\tif (m_vecSpotToGuard == dest)\n\t\t\t\treturn;\n\t\t}\n\t}\n\n\tClearPointGunAt();\n\tm_objectiveTimer = 0;\n\tbObjectiveCompleted = false;\n\tswitch (newObj) {\n\t\tcase OBJECTIVE_GUARD_SPOT:\n\t\t\tm_vecSpotToGuard = dest;\n\t\t\tm_radiusToGuard = 5.0f;\n\t\t\tSetMoveState(PEDMOVE_STILL);\n\t\t\tbreak;\n\t\tcase OBJECTIVE_GUARD_AREA:\n\t\tcase OBJECTIVE_WAIT_IN_CAR:\n\t\tcase OBJECTIVE_WAIT_IN_CAR_THEN_GET_OUT:\n\t\tcase OBJECTIVE_KILL_CHAR_ON_FOOT:\n\t\tcase OBJECTIVE_KILL_CHAR_ANY_MEANS:\n\t\tcase OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE:\n\t\tcase OBJECTIVE_FLEE_CHAR_ON_FOOT_ALWAYS:\n\t\tcase OBJECTIVE_GOTO_CHAR_ON_FOOT:\n\t\tcase OBJECTIVE_GOTO_CHAR_ON_FOOT_WALKING:\n\t\tcase OBJECTIVE_HASSLE_CHAR:\n\t\tcase OBJECTIVE_FOLLOW_CHAR_IN_FORMATION:\n\t\tcase OBJECTIVE_LEAVE_CAR:\n\t\tcase OBJECTIVE_ENTER_CAR_AS_PASSENGER:\n\t\tcase OBJECTIVE_ENTER_CAR_AS_DRIVER:\n\t\tcase OBJECTIVE_FOLLOW_CAR_IN_CAR:\n\t\tcase OBJECTIVE_FIRE_AT_OBJECT_FROM_VEHICLE:\n\t\tcase OBJECTIVE_DESTROY_OBJECT:\n\t\tcase OBJECTIVE_DESTROY_CAR:\n\t\tcase OBJECTIVE_GOTO_AREA_IN_CAR:\n\t\tcase OBJECTIVE_FOLLOW_CAR_ON_FOOT_WITH_OFFSET:\n\t\tcase OBJECTIVE_GUARD_ATTACK:\n\t\tcase OBJECTIVE_SET_LEADER:\n\t\tcase OBJECTIVE_FOLLOW_ROUTE:\n\t\tcase OBJECTIVE_SOLICIT_VEHICLE:\n\t\tcase OBJECTIVE_HAIL_TAXI:\n\t\tcase OBJECTIVE_CATCH_TRAIN:\n\t\tcase OBJECTIVE_BUY_ICE_CREAM:\n\t\tcase OBJECTIVE_STEAL_ANY_CAR:\n\t\tcase OBJECTIVE_STEAL_ANY_MISSION_CAR:\n\t\tcase OBJECTIVE_MUG_CHAR:\n\t\tcase OBJECTIVE_LEAVE_CAR_AND_DIE:\n\t\tcase OBJECTIVE_FLEE_CAR:\n\t\tcase OBJECTIVE_SUN_BATHE:\n\t\tcase OBJECTIVE_AIM_GUN_AT:\n\t\tcase OBJECTIVE_WANDER:\n\t\tcase OBJECTIVE_WAIT_ON_FOOT_AT_SHELTER:\n\t\tcase OBJECTIVE_KILL_CHAR_ON_BOAT:\n\t\tcase OBJECTIVE_SOLICIT_FOOT:\n\t\tcase OBJECTIVE_WAIT_ON_FOOT_AT_BUS_STOP:\n\t\t\tbreak;\n\t\tcase OBJECTIVE_GOTO_AREA_ANY_MEANS:\n\t\tcase OBJECTIVE_GOTO_AREA_ON_FOOT:\n\t\tcase OBJECTIVE_GOTO_SEAT_ON_FOOT:\n\t\tcase OBJECTIVE_GOTO_ATM_ON_FOOT:\n\t\tcase OBJECTIVE_GOTO_BUS_STOP_ON_FOOT:\n\t\tcase OBJECTIVE_GOTO_PIZZA_ON_FOOT:\n\t\tcase OBJECTIVE_GOTO_SHELTER_ON_FOOT:\n\t\tcase OBJECTIVE_GOTO_ICE_CREAM_VAN_ON_FOOT:\n\t\t\tbIsRunning = false;\n\t\t\tm_pNextPathNode = nil;\n\t\t\tm_nextRoutePointPos = dest;\n\t\t\tm_vecSeekPos = m_nextRoutePointPos;\n\t\t\tm_distanceToCountSeekDone = 0.5f;\n\t\t\tif (newObj == OBJECTIVE_GOTO_ATM_ON_FOOT) {\n\t\t\t\tm_distanceToCountSeekDone = m_attractor->GetDistanceToCountSeekDone();\n\t\t\t\tm_acceptableHeadingOffset = m_attractor->GetAcceptableHeading();\n\t\t\t}\n\t\t\tif (newObj == OBJECTIVE_GOTO_SEAT_ON_FOOT) {\n\t\t\t\tm_distanceToCountSeekDone = m_attractor->GetDistanceToCountSeekDone();\n\t\t\t\tm_acceptableHeadingOffset = m_attractor->GetAcceptableHeading();\n\t\t\t}\n\t\t\tif (newObj == OBJECTIVE_GOTO_BUS_STOP_ON_FOOT) {\n\t\t\t\tm_distanceToCountSeekDone = m_attractor->GetDistanceToCountSeekDone();\n\t\t\t\tm_acceptableHeadingOffset = m_attractor->GetAcceptableHeading();\n\t\t\t}\n\t\t\tif (newObj == OBJECTIVE_GOTO_PIZZA_ON_FOOT) {\n\t\t\t\tm_distanceToCountSeekDone = m_attractor->GetDistanceToCountSeekDone();\n\t\t\t\tm_acceptableHeadingOffset = m_attractor->GetAcceptableHeading();\n\t\t\t}\n\t\t\tif (newObj == OBJECTIVE_GOTO_SHELTER_ON_FOOT) {\n\t\t\t\tbIsRunning = true;\n\t\t\t\tm_distanceToCountSeekDone = m_attractor->GetDistanceToCountSeekDone();\n\t\t\t\tm_acceptableHeadingOffset = m_attractor->GetAcceptableHeading();\n\t\t\t}\n\t\t\tif (newObj == OBJECTIVE_GOTO_ICE_CREAM_VAN_ON_FOOT) {\n\t\t\t\tbIsRunning = true;\n\t\t\t\tm_distanceToCountSeekDone = m_attractor->GetDistanceToCountSeekDone();\n\t\t\t\tm_acceptableHeadingOffset = m_attractor->GetAcceptableHeading();\n\t\t\t}\n\t\t\tbUsePedNodeSeek = false;\n\t\t\tif (sq(m_distanceToCountSeekDone) > (m_nextRoutePointPos - GetPosition()).MagnitudeSqr2D()) {\n\t\t\t\tif (!IsUseAttractorObjective(m_objective))\n\t\t\t\t\treturn;\n\t\t\t\tif (Abs(m_fRotationCur - m_attractorHeading) < m_acceptableHeadingOffset)\n\t\t\t\t\treturn;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase OBJECTIVE_RUN_TO_AREA:\n\t\tcase OBJECTIVE_SPRINT_TO_AREA:\n\t\t\tbIsRunning = true;\n\t\t\tm_pNextPathNode = nil;\n\t\t\tm_nextRoutePointPos = dest;\n\t\t\tm_vecSeekPos = m_nextRoutePointPos;\n\t\t\tm_distanceToCountSeekDone = 0.5f;\n\t\t\tbUsePedNodeSeek = true;\n\t\t\tif (sq(m_distanceToCountSeekDone) > (m_nextRoutePointPos - GetPosition()).MagnitudeSqr2D())\n\t\t\t\treturn;\n\t\t\tbreak;\n\t\tdefault: break;\n\t}\n\n\tif (IsTemporaryObjective(m_objective)) {\n\t\tm_prevObjective = newObj;\n\t} else {\n\t\tif (m_objective != newObj)\n\t\t\tSetStoredObjective();\n\n\t\tm_objective = newObj;\n\t}\n}\n\nvoid\nCPed::SetObjective(eObjective newObj, float heading, const CVector& pos)\n{\n\tswitch (newObj) {\n\tcase OBJECTIVE_GOTO_SEAT_ON_FOOT:\n\tcase OBJECTIVE_GOTO_ATM_ON_FOOT:\n\tcase OBJECTIVE_GOTO_BUS_STOP_ON_FOOT:\n\tcase OBJECTIVE_GOTO_PIZZA_ON_FOOT:\n\tcase OBJECTIVE_GOTO_SHELTER_ON_FOOT:\n\tcase OBJECTIVE_GOTO_ICE_CREAM_VAN_ON_FOOT:\n\t\tClearPointGunAt();\n\t\tSetObjective(newObj, pos);\n\t\tm_attractorHeading = heading;\n\t}\n}\n\nvoid\nCPed::ClearObjective(void)\n{\n\tif (IsPedInControl() || m_nPedState == PED_DRIVING) {\n\t\tm_objective = OBJECTIVE_NONE;\n\t\tm_pedInObjective = nil;\n\t\tm_carInObjective = nil;\n\n\t\tif (m_nPedState == PED_DRIVING && m_pMyVehicle) {\n\t\t\tif (m_pMyVehicle->pDriver != this) {\n\t\t\t\tif(!IsPlayer())\n\t\t\t\t\tbWanderPathAfterExitingCar = true;\n\n\t\t\t\tSetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle);\n\t\t\t}\n\t\t\tm_nLastPedState = PED_NONE;\n\t\t} else {\n\t\t\tSetIdle();\n\t\t\tSetMoveState(PEDMOVE_STILL);\n\t\t}\n\t} else {\n\t\tbClearObjective = true;\n\t}\n}\n\nvoid\nCPed::ClearLeader(void)\n{\n\tif (!m_leader)\n\t\treturn;\n\n\tm_leader = nil;\n\tif (IsPedInControl()) {\n\t\tSetObjective(OBJECTIVE_NONE);\n\t\tif (CharCreatedBy == MISSION_CHAR) {\n\t\t\tSetIdle();\n\t\t} else {\n\t\t\tSetWanderPath(CGeneral::GetRandomNumberInRange(0,8));\n\t\t}\n\t} else if (m_objective != OBJECTIVE_NONE) {\n\t\tbClearObjective = true;\n\t}\n}\n\nvoid\nCPed::UpdateFromLeader(void)\n{\n\tif (CTimer::GetTimeInMilliseconds() <= m_objectiveTimer)\n\t\treturn;\n\n\tif (!m_leader)\n\t\treturn;\n\n\tCVector leaderDist;\n\tif (m_leader->InVehicle())\n\t\tleaderDist = m_leader->m_pMyVehicle->GetPosition() - GetPosition();\n\telse\n\t\tleaderDist = m_leader->GetPosition() - GetPosition();\n\n\tif (leaderDist.Magnitude() > 30.0f) {\n\t\tif (bWaitForLeaderToComeCloser) {\n\t\t\tif (IsPedInControl()) {\n\t\t\t\tSetObjective(OBJECTIVE_NONE);\n\t\t\t\tSetIdle();\n\t\t\t\tSetMoveState(PEDMOVE_STILL);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tbWaitForLeaderToComeCloser = true;\n\t} else\n\t\tbWaitForLeaderToComeCloser = false;\n\n\tif (IsPedInControl()) {\n\t\tif (m_nWaitState == WAITSTATE_PLAYANIM_TAXI)\n\t\t\tWarpPedToNearLeaderOffScreen();\n\n\t\tif (m_leader->m_nPedState == PED_DEAD) {\n\t\t\tSetLeader(nil);\n\t\t\tSetObjective(OBJECTIVE_FLEE_ON_FOOT_TILL_SAFE);\n\t\t\treturn;\n\t\t}\n\t\tif (!m_leader->bInVehicle) {\n\t\t\tif (m_leader->m_objective != OBJECTIVE_ENTER_CAR_AS_DRIVER) {\n\t\t\t\tif (bInVehicle) {\n\t\t\t\t\tif (m_objective != OBJECTIVE_WAIT_IN_CAR_THEN_GET_OUT && m_objective != OBJECTIVE_LEAVE_CAR)\n\t\t\t\t\t\tSetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle);\n\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER) {\n\t\t\t\t\tRestorePreviousObjective();\n\t\t\t\t\tRestorePreviousState();\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (m_nPedType == PEDTYPE_PROSTITUTE && CharCreatedBy == RANDOM_CHAR) {\n\t\t\t\tSetLeader(nil);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\tif (!bInVehicle && m_leader->bInVehicle && m_leader->m_nPedState == PED_DRIVING) {\n\t\t\tif (m_objective != OBJECTIVE_ENTER_CAR_AS_PASSENGER && m_objective != OBJECTIVE_ENTER_CAR_AS_DRIVER) {\n\t\t\t\tif (m_leader->m_pMyVehicle->m_nNumPassengers < m_leader->m_pMyVehicle->m_nNumMaxPassengers)\n\t\t\t\t\tSetObjective(OBJECTIVE_ENTER_CAR_AS_PASSENGER, m_leader->m_pMyVehicle);\n\t\t\t}\n\t\t} else if (m_leader->m_objective == OBJECTIVE_NONE || (m_leader->IsPlayer() && m_leader->m_objective == OBJECTIVE_WAIT_ON_FOOT)\n\t\t\t|| m_objective == m_leader->m_objective) {\n\n\t\t\tif (m_leader->m_nPedState == PED_ATTACK && !bDontFight) {\n\t\t\t\tCEntity *lookTargetOfLeader = m_leader->m_pLookTarget;\n\n\t\t\t\tif (lookTargetOfLeader && m_objective != OBJECTIVE_KILL_CHAR_ON_FOOT && lookTargetOfLeader->IsPed() && lookTargetOfLeader != this) {\n\t\t\t\t\tSetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, lookTargetOfLeader);\n\t\t\t\t\tSetObjectiveTimer(8000);\n\t\t\t\t\tSetLookFlag(m_leader->m_pLookTarget, false);\n\t\t\t\t\tSetLookTimer(500);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (IsPedInControl() && m_nPedState != PED_ATTACK) {\n\t\t\t\t\tif (m_leader->m_objective == OBJECTIVE_NONE && m_objective == OBJECTIVE_NONE && m_leader->m_nPedState == PED_CHAT && m_nPedState == PED_CHAT) {\n\t\t\t\t\t\tSetObjective(OBJECTIVE_NONE);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tSetObjective(OBJECTIVE_GOTO_CHAR_ON_FOOT, m_leader);\n\t\t\t\t\t\tSetObjectiveTimer(0);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (m_nPedState == PED_IDLE && m_leader->IsPlayer() && !bDontFight) {\n\t\t\t\t\tif (ScanForThreats() && m_threatEntity) {\n\t\t\t\t\t\tm_pLookTarget = m_threatEntity;\n\t\t\t\t\t\tm_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget);\n\t\t\t\t\t\tTurnBody();\n\t\t\t\t\t\tif (m_attackTimer < CTimer::GetTimeInMilliseconds() && !GetWeapon()->IsTypeMelee()) {\n\t\t\t\t\t\t\tSetWeaponLockOnTarget(m_threatEntity);\n\t\t\t\t\t\t\tSetAttack(m_threatEntity);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tswitch (m_leader->m_objective) {\n\t\t\t\tcase OBJECTIVE_WAIT_ON_FOOT:\n\t\t\t\tcase OBJECTIVE_FLEE_ON_FOOT_TILL_SAFE:\n\t\t\t\tcase OBJECTIVE_WAIT_IN_CAR:\n\t\t\t\tcase OBJECTIVE_FOLLOW_ROUTE:\n\t\t\t\t\tSetObjective(m_leader->m_objective);\n\t\t\t\t\tm_objectiveTimer = m_leader->m_objectiveTimer;\n\t\t\t\t\tbreak;\n\t\t\t\tcase OBJECTIVE_GUARD_SPOT:\n\t\t\t\t\tSetObjective(OBJECTIVE_GUARD_SPOT, m_leader->m_vecSpotToGuard);\n\t\t\t\t\tm_objectiveTimer = m_leader->m_objectiveTimer;\n\t\t\t\t\tbreak;\n\t\t\t\tcase OBJECTIVE_KILL_CHAR_ON_FOOT:\n\t\t\t\tcase OBJECTIVE_KILL_CHAR_ANY_MEANS:\n\t\t\t\tcase OBJECTIVE_GOTO_CHAR_ON_FOOT:\n\t\t\t\tcase OBJECTIVE_GOTO_CHAR_ON_FOOT_WALKING:\n\t\t\t\tcase OBJECTIVE_HASSLE_CHAR:\n\t\t\t\t\tif (m_leader->m_pedInObjective) {\n\t\t\t\t\t\tSetObjective(m_leader->m_objective, m_leader->m_pedInObjective);\n\t\t\t\t\t\tm_objectiveTimer = m_leader->m_objectiveTimer;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase OBJECTIVE_ENTER_CAR_AS_PASSENGER:\n\t\t\t\tcase OBJECTIVE_ENTER_CAR_AS_DRIVER:\n\t\t\t\t\tif (m_leader->m_carInObjective) {\n\t\t\t\t\t\tm_leaveCarTimer = CTimer::GetTimeInMilliseconds() + 150;\n\t\t\t\t\t\tSetObjective(OBJECTIVE_ENTER_CAR_AS_PASSENGER, m_leader->m_carInObjective);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase OBJECTIVE_GUARD_ATTACK:\n\t\t\t\t\treturn;\n\t\t\t\tcase OBJECTIVE_HAIL_TAXI:\n\t\t\t\t\tm_leader = nil;\n\t\t\t\t\tSetObjective(OBJECTIVE_NONE);\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tSetObjective(OBJECTIVE_GOTO_CHAR_ON_FOOT, m_leader);\n\t\t\t\t\tSetObjectiveTimer(0);\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t} else if (bInVehicle) {\n\t\tif ((!m_leader->bInVehicle || m_leader->m_nPedState == PED_EXIT_CAR) && m_objective != OBJECTIVE_WAIT_IN_CAR_THEN_GET_OUT) {\n\n\t\t\tswitch (m_leader->m_objective) {\n\t\t\t\tcase OBJECTIVE_ENTER_CAR_AS_PASSENGER:\n\t\t\t\tcase OBJECTIVE_ENTER_CAR_AS_DRIVER:\n\t\t\t\t\tif (m_pMyVehicle == m_leader->m_pMyVehicle || m_pMyVehicle == m_leader->m_carInObjective)\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t// fall through\n\t\t\t\tdefault:\n\t\t\t\t\tif (m_pMyVehicle && m_objective != OBJECTIVE_LEAVE_CAR) {\n\t\t\t\t\t\tm_leaveCarTimer = CTimer::GetTimeInMilliseconds() + 250;\n\t\t\t\t\t\tSetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle);\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nCPed::RestorePreviousObjective(void)\n{\n\tif (m_objective == OBJECTIVE_NONE)\n\t\treturn;\n\n\tif (m_objective != OBJECTIVE_LEAVE_CAR && m_objective != OBJECTIVE_ENTER_CAR_AS_PASSENGER && m_objective != OBJECTIVE_ENTER_CAR_AS_DRIVER\n\t\t&& m_nPedState != PED_CARJACK)\n\t\tm_pedInObjective = nil;\n\n\tif (m_objective == OBJECTIVE_WAIT_IN_CAR_THEN_GET_OUT) {\n\t\tm_objective = OBJECTIVE_NONE;\n\t\tif (m_pMyVehicle)\n\t\t\tSetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle);\n\n\t} else {\n\t\tm_objective = m_prevObjective;\n\t\tm_prevObjective = OBJECTIVE_NONE;\n\t}\n\tbObjectiveCompleted = false;\n}\n\nvoid\nCPed::ProcessObjective(void)\n{\n\tif (bClearObjective && (IsPedInControl() || m_nPedState == PED_DRIVING)) {\n\t\tClearObjective();\n\t\tbClearObjective = false;\n\t}\n\tUpdateFromLeader();\n\n\tCVector carOrOurPos;\n\tCVector targetCarOrHisPos;\n\tCVector distWithTarget;\n\n\tif (m_objective != OBJECTIVE_NONE && (IsPedInControl() || m_nPedState == PED_DRIVING)) {\n\t\tif (bInVehicle) {\n\t\t\tif (!m_pMyVehicle) {\n\t\t\t\tbInVehicle = false;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tcarOrOurPos = m_pMyVehicle->GetPosition();\n\t\t} else {\n\t\t\tcarOrOurPos = GetPosition();\n\t\t}\n\n\t\tif (m_pedInObjective) {\n\t\t\tif (m_pedInObjective->InVehicle() && m_pedInObjective->m_nPedState != PED_DRAG_FROM_CAR) {\n\t\t\t\ttargetCarOrHisPos = m_pedInObjective->m_pMyVehicle->GetPosition();\n\t\t\t} else {\n\t\t\t\ttargetCarOrHisPos = m_pedInObjective->GetPosition();\n\t\t\t}\n\t\t\tdistWithTarget = targetCarOrHisPos - carOrOurPos;\n\t\t} else if (m_carInObjective) {\n\t\t\ttargetCarOrHisPos = m_carInObjective->GetPosition();\n\t\t\tdistWithTarget = targetCarOrHisPos - carOrOurPos;\n\t\t}\n\n\t\tswitch (m_objective) {\n\t\t\tcase OBJECTIVE_WAIT_ON_FOOT:\n\t\t\t\tif (GetPedState() == PED_DRIVING)\n\t\t\t\t\tm_objective = OBJECTIVE_NONE;\n\t\t\t\telse {\n\t\t\t\t\tSetIdle();\n\t\t\t\t\tif (m_attractor) {\n\t\t\t\t\t\tif (m_objectiveTimer && CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {\n\t\t\t\t\t\t\tGetPedAttractorManager()->BroadcastDeparture(this, m_attractor);\n\t\t\t\t\t\t\tm_objectiveTimer = 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tm_objective = OBJECTIVE_NONE;\n\t\t\t\t\t\tSetMoveState(PEDMOVE_STILL);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase OBJECTIVE_WAIT_ON_FOOT_FOR_COP:\n\t\t\t\tif (!m_pedInObjective) {\n\t\t\t\t\tm_objective = OBJECTIVE_NONE;\n\t\t\t\t\tSetWanderPath(CGeneral::GetRandomNumberInRange(0.f, 8.f));\n\t\t\t\t} else if (m_pedInObjective->m_nPedType == PEDTYPE_COP && m_pedInObjective->m_nPedState == PED_DEAD) {\n\t\t\t\t\tm_objective = OBJECTIVE_NONE;\n\t\t\t\t\tSetWanderPath(CGeneral::GetRandomNumberInRange(0.f, 8.f));\n\t\t\t\t\tm_pedInObjective = nil;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase OBJECTIVE_FLEE_ON_FOOT_TILL_SAFE:\n\t\t\t\tif (m_leaveCarTimer >= CTimer::GetTimeInMilliseconds())\n\t\t\t\t\tbreak;\n\n\t\t\t\tif (InVehicle()) {\n\t\t\t\t\tSetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle);\n\t\t\t\t\tbFleeAfterExitingCar = true;\n\t\t\t\t} else if (m_nPedState != PED_FLEE_POS) {\n\t\t\t\t\tCVector2D fleePos = GetPosition();\n\t\t\t\t\tSetFlee(fleePos, 10000);\n\t\t\t\t\tbUsePedNodeSeek = true;\n\t\t\t\t\tm_pNextPathNode = nil;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase OBJECTIVE_GUARD_SPOT:\n\t\t\t{\n\t\t\t\tdistWithTarget = m_vecSpotToGuard - GetPosition();\n\t\t\t\tif (m_pedInObjective) {\n\t\t\t\t\tSetLookFlag(m_pedInObjective, true);\n\t\t\t\t\tm_pLookTarget = m_pedInObjective;\n\t\t\t\t\tm_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget);\n\t\t\t\t\tTurnBody();\n\t\t\t\t}\n\t\t\t\tfloat distWithTargetSc = distWithTarget.Magnitude();\n\t\t\t\tif (2.0f * m_radiusToGuard >= distWithTargetSc) {\n\t\t\t\t\tif (m_pedInObjective && m_pedInObjective->m_nPedState != PED_DEAD) {\n\t\t\t\t\t\tif (distWithTargetSc <= m_radiusToGuard)\n\t\t\t\t\t\t\tSetIdle();\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tCVector seekPos = m_vecSpotToGuard;\n\t\t\t\t\t\t\tSetSeek(seekPos, m_radiusToGuard);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (CTimer::GetTimeInMilliseconds() > m_lookTimer) {\n\t\t\t\t\t\tint threatType = ScanForThreats();\n\t\t\t\t\t\tSetLookTimer(CGeneral::GetRandomNumberInRange(500, 1500));\n\n\t\t\t\t\t\t// Second condition is pointless and isn't there in Mobile.\n\t\t\t\t\t\tif (threatType == PED_FLAG_GUN || (threatType == PED_FLAG_EXPLOSION && m_threatEntity) || m_threatEntity) {\n\t\t\t\t\t\t\tif (m_threatEntity->IsPed())\n\t\t\t\t\t\t\t\tSetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, m_threatEntity);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tCVector seekPos = m_vecSpotToGuard;\n\t\t\t\t\tSetSeek(seekPos, m_radiusToGuard);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase OBJECTIVE_WAIT_IN_CAR:\n\t\t\t\tSetPedState(PED_DRIVING);\n\t\t\t\tbreak;\n\t\t\tcase OBJECTIVE_WAIT_IN_CAR_THEN_GET_OUT:\n\t\t\t\tSetPedState(PED_DRIVING);\n\t\t\t\tbreak;\n\t\t\tcase OBJECTIVE_KILL_CHAR_ANY_MEANS:\n\t\t\t{\n\t\t\t\tif (m_pedInObjective) {\n\t\t\t\t\tif (m_pedInObjective->IsPlayer() && CharCreatedBy != MISSION_CHAR\n\t\t\t\t\t\t&& m_nPedType != PEDTYPE_COP && FindPlayerPed()->m_pWanted->m_CurrentCops != 0\n\t\t\t\t\t\t&& !bKindaStayInSamePlace) {\n\n\t\t\t\t\t\tSetObjective(OBJECTIVE_FLEE_ON_FOOT_TILL_SAFE);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tif (InVehicle()) {\n\t\t\t\t\t\tif (distWithTarget.Magnitude() >= 20.0f || m_pMyVehicle->m_vecMoveSpeed.MagnitudeSqr() >= sq(0.02f)) {\n\n\t\t\t\t\t\t\tif (((m_pMyVehicle->pDriver == this && m_pMyVehicle->AutoPilot.m_nCarMission == MISSION_NONE) || m_pMyVehicle->AutoPilot.m_nCarMission == MISSION_CRUISE)\n\t\t\t\t\t\t\t\t&& !m_pMyVehicle->m_nGettingInFlags) {\n\t\t\t\t\t\t\t\tm_pMyVehicle->SetStatus(STATUS_PHYSICS);\n\t\t\t\t\t\t\t\tm_pMyVehicle->AutoPilot.m_nPrevRouteNode = 0;\n\t\t\t\t\t\t\t\tif (m_nPedType == PEDTYPE_COP) {\n\t\t\t\t\t\t\t\t\tm_pMyVehicle->AutoPilot.m_nCruiseSpeed = (FindPlayerPed()->m_pWanted->GetWantedLevel() * 0.1f + 0.6f) * (GAME_SPEED_TO_CARAI_SPEED * m_pMyVehicle->pHandling->Transmission.fMaxCruiseVelocity);\n\t\t\t\t\t\t\t\t\tm_pMyVehicle->AutoPilot.m_nCarMission = CCarAI::FindPoliceCarMissionForWantedLevel();\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tm_pMyVehicle->AutoPilot.m_nCruiseSpeed = GAME_SPEED_TO_CARAI_SPEED * m_pMyVehicle->pHandling->Transmission.fMaxCruiseVelocity * 0.8f;\n\t\t\t\t\t\t\t\t\tm_pMyVehicle->AutoPilot.m_nCarMission = MISSION_RAMPLAYER_FARAWAY;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tm_pMyVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tbool targetHasVeh = m_pedInObjective->bInVehicle;\n\t\t\t\t\t\t\tif (!targetHasVeh || targetHasVeh && m_pedInObjective->m_pMyVehicle->CanPedExitCar(false)) {\n\t\t\t\t\t\t\t\tm_pMyVehicle->AutoPilot.m_nCruiseSpeed = 0;\n\t\t\t\t\t\t\t\tm_pMyVehicle->AutoPilot.m_nCarMission = MISSION_NONE;\n\t\t\t\t\t\t\t\tSetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tif (distWithTarget.Magnitude() > 30.0f && !bKindaStayInSamePlace) {\n\t\t\t\t\t\tif (m_pMyVehicle) {\n\t\t\t\t\t\t\tm_pMyVehicle->AutoPilot.m_nCruiseSpeed = 0;\n\t\t\t\t\t\t\tSetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, m_pMyVehicle);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tfloat closestVehDist = 60.0f;\n\t\t\t\t\t\t\tint16 lastVehicle;\n\t\t\t\t\t\t\tCEntity* vehicles[8];\n\t\t\t\t\t\t\tCWorld::FindObjectsInRange(GetPosition(), ENTER_CAR_MAX_DIST, true, &lastVehicle, 6, vehicles, false, true, false, false, false);\n\t\t\t\t\t\t\tCVehicle *foundVeh = nil;\n\t\t\t\t\t\t\tfor(int i = 0; i < lastVehicle; i++) {\n\t\t\t\t\t\t\t\tCVehicle *nearVeh = (CVehicle*)vehicles[i];\n\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\tNot used.\n\t\t\t\t\t\t\t\tCVector vehSpeed = nearVeh->GetSpeed();\n\t\t\t\t\t\t\t\tCVector ourSpeed = GetSpeed();\n\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\t\tCVector vehDistVec = nearVeh->GetPosition() - GetPosition();\n\t\t\t\t\t\t\t\tif (vehDistVec.Magnitude() < closestVehDist && m_pedInObjective->m_pMyVehicle != nearVeh\n\t\t\t\t\t\t\t\t\t&& nearVeh->CanPedOpenLocks(this) && nearVeh->m_fHealth > 250.f) {\n\n\t\t\t\t\t\t\t\t\tfoundVeh = nearVeh;\n\t\t\t\t\t\t\t\t\tclosestVehDist = vehDistVec.Magnitude();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tm_pMyVehicle = foundVeh;\n\t\t\t\t\t\t\tif (m_pMyVehicle) {\n\t\t\t\t\t\t\t\tm_pMyVehicle->RegisterReference((CEntity **) &m_pMyVehicle);\n\t\t\t\t\t\t\t\tm_pMyVehicle->AutoPilot.m_nCruiseSpeed = 0;\n\t\t\t\t\t\t\t\tSetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, m_pMyVehicle);\n\t\t\t\t\t\t\t} else if (!GetIsOnScreen()) {\n\t\t\t\t\t\t\t\tCVector ourPos = GetPosition();\n\t\t\t\t\t\t\t\tint closestNode = ThePaths.FindNodeClosestToCoors(ourPos, PATH_CAR, 20.0f);\n\t\t\t\t\t\t\t\tif (closestNode >= 0) {\n\t\t\t\t\t\t\t\t\tint16 colliding;\n\t\t\t\t\t\t\t\t\tCWorld::FindObjectsKindaColliding(\n\t\t\t\t\t\t\t\t\t\tThePaths.m_pathNodes[closestNode].GetPosition(), 10.0f, true, &colliding, 2, nil, false, true, true, false, false);\n\t\t\t\t\t\t\t\t\tif (!colliding) {\n\t\t\t\t\t\t\t\t\t\tCZoneInfo zoneInfo;\n\t\t\t\t\t\t\t\t\t\tint chosenCarClass;\n\t\t\t\t\t\t\t\t\t\tCTheZones::GetZoneInfoForTimeOfDay(&ourPos, &zoneInfo);\n\t\t\t\t\t\t\t\t\t\tint chosenModel = CCarCtrl::ChooseModel(&zoneInfo, &chosenCarClass);\n\t\t\t\t\t\t\t\t\t\tCVehicle *newVeh = nil;\n\t\t\t\t\t\t\t\t\t\tif (chosenModel != -1) {\n\t\t\t\t\t\t\t\t\t\t\tif (CModelInfo::IsBikeModel(chosenModel)) {\n\t\t\t\t\t\t\t\t\t\t\t\tnewVeh = new CBike(chosenModel, RANDOM_VEHICLE);\n\t\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\t\tnewVeh = new CAutomobile(chosenModel, RANDOM_VEHICLE);\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\tif (newVeh) {\n\t\t\t\t\t\t\t\t\t\t\tnewVeh->GetMatrix().GetPosition() = ThePaths.m_pathNodes[closestNode].GetPosition();\n\t\t\t\t\t\t\t\t\t\t\tnewVeh->GetMatrix().GetPosition().z += 4.0f;\n\t\t\t\t\t\t\t\t\t\t\tnewVeh->SetHeading(DEGTORAD(200.0f));\n\t\t\t\t\t\t\t\t\t\t\tnewVeh->SetStatus(STATUS_ABANDONED);\n\t\t\t\t\t\t\t\t\t\t\tnewVeh->m_nDoorLock = CARLOCK_UNLOCKED;\n\t\t\t\t\t\t\t\t\t\t\tCWorld::Add(newVeh);\n\t\t\t\t\t\t\t\t\t\t\tm_pMyVehicle = newVeh;\n\t\t\t\t\t\t\t\t\t\t\tif (m_pMyVehicle) {\n\t\t\t\t\t\t\t\t\t\t\t\tm_pMyVehicle->RegisterReference((CEntity **) &m_pMyVehicle);\n\t\t\t\t\t\t\t\t\t\t\t\tm_pMyVehicle->AutoPilot.m_nCruiseSpeed = 0;\n\t\t\t\t\t\t\t\t\t\t\t\tSetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, m_pMyVehicle);\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tClearLookFlag();\n\t\t\t\t\tbObjectiveCompleted = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\tcase OBJECTIVE_KILL_CHAR_ON_FOOT:\n\t\t\t{\n\t\t\t\tif (m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT && InVehicle()) {\n\t\t\t\t\tSetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif (!m_pedInObjective || m_pedInObjective->DyingOrDead()) {\n\t\t\t\t\tbObjectiveCompleted = true;\n\t\t\t\t\tClearLookFlag();\n\t\t\t\t\tSetMoveAnim();\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif (m_pedInObjective) {\n\t\t\t\t\tint status;\n\t\t\t\t\tif (GetWeapon()->IsTypeMelee())\n\t\t\t\t\t\tstatus = KillCharOnFootMelee(carOrOurPos, targetCarOrHisPos, distWithTarget);\n\t\t\t\t\telse\n\t\t\t\t\t\tstatus = KillCharOnFootArmed(carOrOurPos, targetCarOrHisPos, distWithTarget);\n\n\t\t\t\t\tif (status == WATCH_UNTIL_HE_DISAPPEARS)\n\t\t\t\t\t\treturn;\n\t\t\t\t\tif (status == CANT_ATTACK)\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tSetMoveAnim();\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE:\n\t\t\tcase OBJECTIVE_FLEE_CHAR_ON_FOOT_ALWAYS:\n\t\t\t{\n\t\t\t\tif (InVehicle()) {\n\t\t\t\t\tif (m_nPedState == PED_DRIVING)\n\t\t\t\t\t\tSetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle);\n\t\t\t\t} else if (m_nPedState != PED_FLEE_ENTITY) {\n\t\t\t\t\tint time;\n\t\t\t\t\tif (m_objective == OBJECTIVE_FLEE_CHAR_ON_FOOT_ALWAYS)\n\t\t\t\t\t\ttime = 0;\n\t\t\t\t\telse\n\t\t\t\t\t\ttime = 6000;\n\n\t\t\t\t\tSetFindPathAndFlee(m_pedInObjective, time);\n\t\t\t\t\tif (m_pedStats == CPedStats::ms_apPedStats[PEDSTAT_FIREMAN])\n\t\t\t\t\t\tbMakeFleeScream = true;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase OBJECTIVE_GOTO_CHAR_ON_FOOT:\n\t\t\tcase OBJECTIVE_GOTO_CHAR_ON_FOOT_WALKING:\n\t\t\tcase OBJECTIVE_HASSLE_CHAR:\n\t\t\t{\n\t\t\t\tif (m_pedInObjective) {\n\t\t\t\t\tfloat safeDistance = 2.0f;\n\t\t\t\t\tif (m_pedInObjective->bInVehicle)\n\t\t\t\t\t\tsafeDistance = 3.0f;\n\t\t\t\t\tif (m_objective == OBJECTIVE_HASSLE_CHAR)\n\t\t\t\t\t\tsafeDistance = 1.0f;\n\n\t\t\t\t\tfloat distWithTargetSc = distWithTarget.Magnitude();\n\t\t\t\t\tif (m_nPedStateTimer < CTimer::GetTimeInMilliseconds()) {\n\t\t\t\t\t\tif (distWithTargetSc <= safeDistance) {\n\t\t\t\t\t\t\tbScriptObjectiveCompleted = true;\n\t\t\t\t\t\t\tif (m_nPedState != PED_ATTACK) {\n\t\t\t\t\t\t\t\tSetIdle();\n\t\t\t\t\t\t\t\tif (m_pLookTarget)\n\t\t\t\t\t\t\t\t\tm_pLookTarget->CleanUpOldReference(&m_pLookTarget);\n\t\t\t\t\t\t\t\tm_pLookTarget = m_pedInObjective;\n\t\t\t\t\t\t\t\tm_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget);\n\t\t\t\t\t\t\t\tTurnBody();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (distWithTargetSc > 2.0f)\n\t\t\t\t\t\t\t\tSetMoveState(m_pedInObjective->m_nMoveState);\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\tSetMoveState(PEDMOVE_STILL);\n\n\t\t\t\t\t\t\tif (m_objective == OBJECTIVE_HASSLE_CHAR) {\n\t\t\t\t\t\t\t\tSay(SOUND_PED_COP_REACTION);\n\t\t\t\t\t\t\t\tm_pedInObjective->Say(SOUND_PED_UNK_126);\n\t\t\t\t\t\t\t\tm_leaveCarTimer = CTimer::GetTimeInMilliseconds() + 3000;\n\t\t\t\t\t\t\t\tm_pedInObjective->m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + 3000;\n\t\t\t\t\t\t\t\tSetObjective(OBJECTIVE_WANDER);\n\t\t\t\t\t\t\t\tm_pedInObjective->SetObjective(OBJECTIVE_WANDER);\n\t\t\t\t\t\t\t\tCVector2D dist = GetPosition() - m_pedInObjective->GetPosition();\n\t\t\t\t\t\t\t\tm_nPathDir = CGeneral::GetNodeHeadingFromVector(dist.x, dist.y);\n\t\t\t\t\t\t\t\tm_pedInObjective->m_nPathDir = CGeneral::GetNodeHeadingFromVector(-dist.x, -dist.y);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tSetSeek(m_pedInObjective, safeDistance);\n\t\t\t\t\t\t\tif (distWithTargetSc >= 5.0f) {\n\t\t\t\t\t\t\t\tif (m_leader && m_leader->m_nMoveState == PEDMOVE_SPRINT)\n\t\t\t\t\t\t\t\t\tSetMoveState(PEDMOVE_SPRINT);\n\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\tSetMoveState(PEDMOVE_RUN);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tif (m_leader && m_leader->m_nMoveState != PEDMOVE_STILL\n\t\t\t\t\t\t\t\t\t&& m_leader->m_nMoveState != PEDMOVE_NONE) {\n\t\t\t\t\t\t\t\t\tif (m_leader->IsPlayer()) {\n\t\t\t\t\t\t\t\t\t\tif (distWithTargetSc >= 3.0f && FindPlayerPed()->m_fMoveSpeed >= 1.3f)\n\t\t\t\t\t\t\t\t\t\t\tSetMoveState(PEDMOVE_RUN);\n\t\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t\t\tSetMoveState(PEDMOVE_WALK);\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tSetMoveState(m_leader->m_nMoveState);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} else if (distWithTargetSc <= 3.0f) {\n\t\t\t\t\t\t\t\t\tSetMoveState(PEDMOVE_WALK);\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tSetMoveState(PEDMOVE_RUN);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (m_objective == OBJECTIVE_GOTO_CHAR_ON_FOOT_WALKING && m_nMoveState > PEDMOVE_STILL)\n\t\t\t\t\t\t\tSetMoveState(PEDMOVE_WALK);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tSetObjective(OBJECTIVE_NONE);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase OBJECTIVE_FOLLOW_CHAR_IN_FORMATION:\n\t\t\t{\n\t\t\t\tif (m_pedInObjective) {\n\t\t\t\t\tCVector posToGo = GetFormationPosition();\n\t\t\t\t\tdistWithTarget = posToGo - carOrOurPos;\n\t\t\t\t\tSetSeek(posToGo, 1.0f);\n\t\t\t\t\tif (distWithTarget.Magnitude() <= 3.0f) {\n\t\t\t\t\t\tSetSeek(posToGo, 1.0f);\n\t\t\t\t\t\tif (m_pedInObjective && m_pedInObjective->m_nMoveState != PEDMOVE_STILL)\n\t\t\t\t\t\t\tSetMoveState(m_pedInObjective->m_nMoveState);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tSetSeek(posToGo, 1.0f);\n\t\t\t\t\t\tSetMoveState(PEDMOVE_RUN);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tSetObjective(OBJECTIVE_NONE);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase OBJECTIVE_ENTER_CAR_AS_PASSENGER:\n\t\t\t{\n\t\t\t\tif (m_carInObjective) {\n\t\t\t\t\tif (!bInVehicle && m_carInObjective->m_nNumPassengers >= m_carInObjective->m_nNumMaxPassengers) {\n\t\t\t\t\t\tRestorePreviousObjective();\n\t\t\t\t\t\tRestorePreviousState();\n\t\t\t\t\t\tif (IsPedInControl())\n\t\t\t\t\t\t\tm_pMyVehicle = nil;\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (m_prevObjective == OBJECTIVE_HAIL_TAXI && !((CAutomobile*)m_carInObjective)->bTaxiLight) {\n\t\t\t\t\t\tRestorePreviousObjective();\n\t\t\t\t\t\tClearObjective();\n\t\t\t\t\t\tSetWanderPath(CGeneral::GetRandomNumber() & 7);\n\t\t\t\t\t\tbIsRunning = false;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tif (m_objectiveTimer && m_objectiveTimer < CTimer::GetTimeInMilliseconds()) {\n\t\t\t\t\t\tif (!EnteringCar()) {\n\t\t\t\t\t\t\tbool foundSeat = false;\n\t\t\t\t\t\t\tif (m_carInObjective->IsBike()) {\n\t\t\t\t\t\t\t\tif (!m_carInObjective->pPassengers[0] && !(m_carInObjective->m_nGettingInFlags & (CAR_DOOR_FLAG_RR | CAR_DOOR_FLAG_LR))) {\n\t\t\t\t\t\t\t\t\tm_vehDoor = CAR_DOOR_RR;\n\t\t\t\t\t\t\t\t\tfoundSeat = true;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tif (m_carInObjective->pPassengers[0] || m_carInObjective->m_nGettingInFlags & CAR_DOOR_FLAG_RF) {\n\t\t\t\t\t\t\t\t\tif (m_carInObjective->pPassengers[1] || m_carInObjective->m_nGettingInFlags & CAR_DOOR_FLAG_LR) {\n\t\t\t\t\t\t\t\t\t\tif (m_carInObjective->pPassengers[2] || m_carInObjective->m_nGettingInFlags & CAR_DOOR_FLAG_RR) {\n\t\t\t\t\t\t\t\t\t\t\tfoundSeat = false;\n\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\tm_vehDoor = CAR_DOOR_RR;\n\t\t\t\t\t\t\t\t\t\t\tfoundSeat = true;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tm_vehDoor = CAR_DOOR_LR;\n\t\t\t\t\t\t\t\t\t\tfoundSeat = true;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tm_vehDoor = CAR_DOOR_RF;\n\t\t\t\t\t\t\t\t\tfoundSeat = true;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tfor (int i = 2; i < m_carInObjective->m_nNumMaxPassengers; ++i) {\n\t\t\t\t\t\t\t\tif (!m_carInObjective->pPassengers[i] && !(m_carInObjective->m_nGettingInFlags & CAR_DOOR_FLAG_RF)) {\n\t\t\t\t\t\t\t\t\tm_vehDoor = CAR_DOOR_RF;\n\t\t\t\t\t\t\t\t\tfoundSeat = true;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (foundSeat) {\n\t\t\t\t\t\t\t\tSetPosition(GetPositionToOpenCarDoor(m_carInObjective, m_vehDoor));\n\t\t\t\t\t\t\t\tSetEnterCar(m_carInObjective, m_vehDoor);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tm_objectiveTimer = 0;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// fall through\n\t\t\t}\n\t\t\tcase OBJECTIVE_ENTER_CAR_AS_DRIVER:\n\t\t\t{\n\t\t\t\tif (!m_carInObjective || bInVehicle) {\n\t\t\t\t\tif (bInVehicle && m_pMyVehicle != m_carInObjective) {\n\t\t\t\t\t\tSetExitCar(m_pMyVehicle, 0);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tbObjectiveCompleted = true;\n\t\t\t\t\t\tbScriptObjectiveCompleted = true;\n\t\t\t\t\t\tRestorePreviousState();\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (m_leaveCarTimer > CTimer::GetTimeInMilliseconds()) {\n\t\t\t\t\t\tSetMoveState(PEDMOVE_STILL);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tif (IsPedInControl()) {\n\t\t\t\t\t\tif (m_prevObjective == OBJECTIVE_KILL_CHAR_ANY_MEANS) {\n\t\t\t\t\t\t\tif (distWithTarget.Magnitude() < 20.0f) {\n\t\t\t\t\t\t\t\tRestorePreviousObjective();\n\t\t\t\t\t\t\t\tRestorePreviousState();\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER) {\n\t\t\t\t\t\t\t\tif (m_carInObjective->pDriver && !IsPlayer()) {\n\t\t\t\t\t\t\t\t\tif (m_carInObjective->pDriver->m_objective == OBJECTIVE_KILL_CHAR_ANY_MEANS && m_carInObjective->pDriver != m_pedInObjective) {\n\t\t\t\t\t\t\t\t\t\tSetObjective(OBJECTIVE_ENTER_CAR_AS_PASSENGER, m_carInObjective);\n\t\t\t\t\t\t\t\t\t\tm_carInObjective->bIsBeingCarJacked = false;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if (m_objective != OBJECTIVE_ENTER_CAR_AS_PASSENGER) {\n\t\t\t\t\t\t\tif (m_carInObjective->pDriver\n\t\t\t\t\t\t\t\t&& (CharCreatedBy != MISSION_CHAR || m_carInObjective->pDriver->CharCreatedBy != RANDOM_CHAR)\n\t\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\tif (m_carInObjective->pDriver->m_nPedType == m_nPedType) {\n\t\t\t\t\t\t\t\t\tSetObjective(OBJECTIVE_ENTER_CAR_AS_PASSENGER, m_carInObjective);\n\t\t\t\t\t\t\t\t\tm_carInObjective->bIsBeingCarJacked = false;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (m_carInObjective->IsUpsideDown() && m_carInObjective->m_vehType != VEHICLE_TYPE_BIKE) {\n\t\t\t\t\t\t\tRestorePreviousObjective();\n\t\t\t\t\t\t\tRestorePreviousState();\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!m_carInObjective->IsBoat() || m_nPedState == PED_SEEK_IN_BOAT) {\n\t\t\t\t\t\t\tif (m_nPedState != PED_SEEK_CAR)\n\t\t\t\t\t\t\t\tSetSeekCar(m_carInObjective, 0);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tSetSeekBoatPosition(m_carInObjective);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (m_nMoveState == PEDMOVE_STILL && !bVehEnterDoorIsBlocked)\n\t\t\t\t\t\t\tSetMoveState(PEDMOVE_RUN);\n\n\t\t\t\t\t\tif (m_carInObjective && m_carInObjective->m_fHealth > 0.0f) {\n\t\t\t\t\t\t\tdistWithTarget = m_carInObjective->GetPosition() - GetPosition();\n\t\t\t\t\t\t\tif (!bInVehicle) {\n\t\t\t\t\t\t\t\tif (nEnterCarRangeMultiplier * ENTER_CAR_MAX_DIST < distWithTarget.Magnitude()) {\n\t\t\t\t\t\t\t\t\tif (!m_carInObjective->pDriver && !m_carInObjective->GetIsOnScreen() && !GetIsOnScreen())\n\t\t\t\t\t\t\t\t\t\tWarpPedToNearEntityOffScreen(m_carInObjective);\n\n\t\t\t\t\t\t\t\t\tif (CharCreatedBy != MISSION_CHAR || m_prevObjective == OBJECTIVE_KILL_CHAR_ANY_MEANS\n\t\t\t\t\t\t\t\t\t\t|| IsPlayer() && !CPad::GetPad(0)->ArePlayerControlsDisabled()) {\n\t\t\t\t\t\t\t\t\t\tRestorePreviousObjective();\n\t\t\t\t\t\t\t\t\t\tRestorePreviousState();\n\t\t\t\t\t\t\t\t\t\tif (IsPedInControl())\n\t\t\t\t\t\t\t\t\t\t\tm_pMyVehicle = nil;\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tSetIdle();\n\t\t\t\t\t\t\t\t\t\tSetMoveState(PEDMOVE_STILL);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if (!bInVehicle) {\n\t\t\t\t\t\t\tRestorePreviousObjective();\n\t\t\t\t\t\t\tRestorePreviousState();\n\t\t\t\t\t\t\tif (IsPedInControl())\n\t\t\t\t\t\t\t\tm_pMyVehicle = nil;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase OBJECTIVE_DESTROY_OBJECT:\n\t\t\t\tif (m_pPointGunAt) {\n\t\t\t\t\tif (m_nPedState != PED_ATTACK)\n\t\t\t\t\t\tSetAttack(m_pPointGunAt);\n\t\t\t\t} else {\n\t\t\t\t\tbScriptObjectiveCompleted = true;\n\t\t\t\t\tRestorePreviousObjective();\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase OBJECTIVE_DESTROY_CAR:\n\t\t\t{\n\t\t\t\tif (!m_carInObjective) {\n\t\t\t\t\tClearLookFlag();\n\t\t\t\t\tbObjectiveCompleted = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tfloat distWithTargetSc = distWithTarget.Magnitude();\n\t\t\t\tCWeaponInfo *wepInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);\n\t\t\t\tfloat wepRange = wepInfo->m_fRange;\n\t\t\t\tm_pLookTarget = m_carInObjective;\n\t\t\t\tm_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget);\n\n\t\t\t\tm_pSeekTarget = m_carInObjective;\n\t\t\t\tm_pSeekTarget->RegisterReference((CEntity**) &m_pSeekTarget);\n\n\t\t\t\tTurnBody();\n\t\t\t\tif (m_carInObjective->m_fHealth <= 0.0f) {\n\t\t\t\t\tClearLookFlag();\n\t\t\t\t\tbScriptObjectiveCompleted = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif (m_attackTimer < CTimer::GetTimeInMilliseconds() && distWithTargetSc < wepRange) {\n\t\t\t\t\t// I hope so\n\t\t\t\t\tCVector ourHead = GetMatrix() * CVector(0.5f, 0.0f, 0.6f);\n\t\t\t\t\tCVector maxShotPos = m_carInObjective->GetPosition() - ourHead;\n\t\t\t\t\tmaxShotPos *= wepInfo->m_fRange / maxShotPos.Magnitude();\n\t\t\t\t\tmaxShotPos += ourHead;\n\n\t\t\t\t\tCColPoint foundCol;\n\t\t\t\t\tCEntity *foundEnt;\n\n\t\t\t\t\tCWorld::bIncludeDeadPeds = true;\n\t\t\t\t\tCWorld::ProcessLineOfSight(ourHead, maxShotPos, foundCol, foundEnt, true, true, true, true, false, true, false);\n\t\t\t\t\tCWorld::bIncludeDeadPeds = false;\n\t\t\t\t\tif (foundEnt == m_carInObjective) {\n\t\t\t\t\t\tSetAttack(m_carInObjective);\n\t\t\t\t\t\tSetWeaponLockOnTarget(m_carInObjective);\n\t\t\t\t\t\tSetShootTimer(CGeneral::GetRandomNumberInRange(500, 2000));\n\t\t\t\t\t\tif (distWithTargetSc > 10.0f && !bKindaStayInSamePlace) {\n\t\t\t\t\t\t\tSetAttackTimer(CGeneral::GetRandomNumberInRange(2000, 5000));\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tSetAttackTimer(CGeneral::GetRandomNumberInRange(50, 300));\n\t\t\t\t\t\t\tSetMoveState(PEDMOVE_STILL);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else if (m_nPedState != PED_ATTACK && !bKindaStayInSamePlace) {\n\t\t\t\t\tif (wepRange <= 5.0f) {\n\t\t\t\t\t\tif (Abs(distWithTarget.x) > wepRange || Abs(distWithTarget.y) > wepRange ||\n\t\t\t\t\t\t\t(distWithTarget.z > -1.0f && distWithTarget.z < 0.3)) {\n\t\t\t\t\t\t\tSetSeek(m_carInObjective, 3.0f);\n\t\t\t\t\t\t\tSetMoveState(PEDMOVE_RUN);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tSetIdle();\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tfloat safeDistance = wepRange * 0.25f;\n\n\t\t\t\t\t\tSetSeek(m_carInObjective, safeDistance);\n\t\t\t\t\t\tSetMoveState(PEDMOVE_RUN);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tSetLookFlag(m_carInObjective, false);\n\t\t\t\tTurnBody();\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase OBJECTIVE_GOTO_AREA_ON_FOOT:\n\t\t\tcase OBJECTIVE_RUN_TO_AREA:\n\t\t\tcase OBJECTIVE_SPRINT_TO_AREA:\n\t\t\t{\n\t\t\t\tif (InVehicle()) {\n\t\t\t\t\tSetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle);\n\t\t\t\t} else {\n\t\t\t\t\tdistWithTarget = m_nextRoutePointPos - GetPosition();\n\t\t\t\t\tdistWithTarget.z = 0.0f;\n\t\t\t\t\tif (sq(m_distanceToCountSeekDone) >= distWithTarget.MagnitudeSqr()) {\n\t\t\t\t\t\tbObjectiveCompleted = true;\n\t\t\t\t\t\tbScriptObjectiveCompleted = true;\n\t\t\t\t\t\tSetMoveState(PEDMOVE_STILL);\n\t\t\t\t\t} else if (CTimer::GetTimeInMilliseconds() > m_nPedStateTimer || m_nPedState != PED_SEEK_POS) {\n\t\t\t\t\t\tif (bUsePedNodeSeek) {\n\t\t\t\t\t\t\tCVector bestCoords(0.0f, 0.0f, 0.0f);\n\t\t\t\t\t\t\tm_vecSeekPos = m_nextRoutePointPos;\n\n\t\t\t\t\t\t\tif (!m_pNextPathNode) {\n\t\t\t\t\t\t\t\tbool found = FindBestCoordsFromNodes(m_vecSeekPos, &bestCoords);\n\t\t\t\t\t\t\t\tif (m_pNextPathNode) {\n\t\t\t\t\t\t\t\t\t// Because it already does that if it finds better coords.\n\t\t\t\t\t\t\t\t\tif (!found) {\n\t\t\t\t\t\t\t\t\t\tbestCoords = CPathFind::TakeWidthIntoAccountForWandering(m_pNextPathNode, m_randomSeed);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tif ((bestCoords - GetPosition()).Magnitude2D() < m_distanceToCountSeekDone) {\n\t\t\t\t\t\t\t\t\t\tm_pNextPathNode = nil;\n\t\t\t\t\t\t\t\t\t\tbUsePedNodeSeek = false;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (m_pNextPathNode)\n\t\t\t\t\t\t\t\tm_vecSeekPos = CPathFind::TakeWidthIntoAccountForWandering(m_pNextPathNode, m_randomSeed);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tCVector seekPos = m_vecSeekPos;\n\t\t\t\t\t\tSetSeek(m_vecSeekPos, m_distanceToCountSeekDone);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase OBJECTIVE_GUARD_ATTACK:\n\t\t\t{\n\t\t\t\tif (m_pedInObjective) {\n\t\t\t\t\tSetLookFlag(m_pedInObjective, true);\n\t\t\t\t\tm_pLookTarget = m_pedInObjective;\n\t\t\t\t\tm_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget);\n\t\t\t\t\tm_lookTimer = m_attackTimer;\n\t\t\t\t\tTurnBody();\n\t\t\t\t\tfloat distWithTargetSc = distWithTarget.Magnitude();\n\t\t\t\t\tif (distWithTargetSc >= 20.0f) {\n\t\t\t\t\t\tRestorePreviousObjective();\n\t\t\t\t\t} else if (m_attackTimer < CTimer::GetTimeInMilliseconds()) {\n\t\t\t\t\t\tif (m_nPedState != PED_SEEK_ENTITY && distWithTargetSc >= 2.0f) {\n\t\t\t\t\t\t\tSetSeek(m_pedInObjective, 1.0f);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tSetAttack(m_pedInObjective);\n\t\t\t\t\t\t\tSetShootTimer(CGeneral::GetRandomNumberInRange(500.0f, 1500.0f));\n\t\t\t\t\t\t}\n\t\t\t\t\t\tSetAttackTimer(1000);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tRestorePreviousObjective();\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase OBJECTIVE_FOLLOW_ROUTE:\n\t\t\t\tif (HaveReachedNextPointOnRoute(1.0f)) {\n\t\t\t\t\tint nextPoint = GetNextPointOnRoute();\n\t\t\t\t\tm_nextRoutePointPos = CRouteNode::GetPointPosition(nextPoint);\n\t\t\t\t} else {\n\t\t\t\t\tCVector seekPos = m_nextRoutePointPos;\n\t\t\t\t\tSetSeek(seekPos, 0.8f);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase OBJECTIVE_SOLICIT_VEHICLE:\n\t\t\t\tif (m_carInObjective) {\n\t\t\t\t\tif (m_objectiveTimer <= CTimer::GetTimeInMilliseconds()) {\n\t\t\t\t\t\tif (!bInVehicle) {\n\t\t\t\t\t\t\tSetObjective(OBJECTIVE_NONE);\n\t\t\t\t\t\t\tSetWanderPath(CGeneral::GetRandomNumber() & 7);\n\t\t\t\t\t\t\tm_objectiveTimer = CTimer::GetTimeInMilliseconds() + 10000;\n\t\t\t\t\t\t\tif (IsPedInControl())\n\t\t\t\t\t\t\t\tm_pMyVehicle = nil;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (m_nPedState != PED_FLEE_ENTITY && m_nPedState != PED_SOLICIT)\n\t\t\t\t\t\t\tSetSeekCar(m_carInObjective, 0);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tRestorePreviousObjective();\n\t\t\t\t\tRestorePreviousState();\n\t\t\t\t\tif (IsPedInControl())\n\t\t\t\t\t\tm_pMyVehicle = nil;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase OBJECTIVE_HAIL_TAXI:\n\t\t\t\tif (!RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_HAILTAXI) && CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {\n\t\t\t\t\tSay(SOUND_PED_TAXI_WAIT);\n\t\t\t\t\tCAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_HAILTAXI, 4.0f);\n\t\t\t\t\tm_nWaitTimer = CTimer::GetTimeInMilliseconds() + 2000;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase OBJECTIVE_CATCH_TRAIN:\n\t\t\t{\n\t\t\t\tif (m_carInObjective) {\n\t\t\t\t\tSetObjective(OBJECTIVE_ENTER_CAR_AS_PASSENGER, m_carInObjective);\n\t\t\t\t} else {\n\t\t\t\t\tCVehicle* trainToEnter = nil;\n\t\t\t\t\tfloat closestCarDist = CHECK_NEARBY_THINGS_MAX_DIST;\n\t\t\t\t\tCVector pos = GetPosition();\n\t\t\t\t\tint16 lastVehicle;\n\t\t\t\t\tCEntity* vehicles[8];\n\n\t\t\t\t\tCWorld::FindObjectsInRange(pos, 10.0f, true, &lastVehicle, 6, vehicles, false, true, false, false, false);\n\t\t\t\t\tfor (int i = 0; i < lastVehicle; i++) {\n\t\t\t\t\t\tCVehicle* nearVeh = (CVehicle*)vehicles[i];\n\t\t\t\t\t\tif (nearVeh->IsTrain()) {\n\t\t\t\t\t\t\tCVector vehDistVec = GetPosition() - nearVeh->GetPosition();\n\t\t\t\t\t\t\tfloat vehDist = vehDistVec.Magnitude();\n\t\t\t\t\t\t\tif (vehDist < closestCarDist && m_pedInObjective->m_pMyVehicle != nearVeh)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ttrainToEnter = nearVeh;\n\t\t\t\t\t\t\t\tclosestCarDist = vehDist;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (trainToEnter) {\n\t\t\t\t\t\tm_carInObjective = trainToEnter;\n\t\t\t\t\t\tm_carInObjective->RegisterReference((CEntity **) &m_carInObjective);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase OBJECTIVE_BUY_ICE_CREAM:\n\t\t\t\tif (m_carInObjective) {\n\t\t\t\t\tif (m_nPedState != PED_FLEE_ENTITY && m_nPedState != PED_BUY_ICECREAM && m_nPedState != PED_CHAT)\n\t\t\t\t\t\tSetSeekCar(m_carInObjective, 0);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase OBJECTIVE_STEAL_ANY_CAR:\n\t\t\tcase OBJECTIVE_STEAL_ANY_MISSION_CAR:\n\t\t\t{\n\t\t\t\tif (bInVehicle) {\n\t\t\t\t\tbScriptObjectiveCompleted = true;\n\t\t\t\t\tRestorePreviousObjective();\n\t\t\t\t} else if (m_carJackTimer < CTimer::GetTimeInMilliseconds()) {\n\t\t\t\t\tCVehicle *carToSteal = nil;\n\t\t\t\t\tfloat closestCarDist = nEnterCarRangeMultiplier * ENTER_CAR_MAX_DIST;\n\t\t\t\t\tCVector pos = GetPosition();\n\t\t\t\t\tint16 lastVehicle;\n\t\t\t\t\tCEntity *vehicles[8];\n\n\t\t\t\t\tCWorld::FindObjectsInRange(pos, closestCarDist, true, &lastVehicle, 6, vehicles, false, true, false, false, false);\n\t\t\t\t\tfor(int i = 0; i < lastVehicle; i++) {\n\t\t\t\t\t\tCVehicle *nearVeh = (CVehicle*)vehicles[i];\n\t\t\t\t\t\tif (m_objective == OBJECTIVE_STEAL_ANY_MISSION_CAR || nearVeh->VehicleCreatedBy != MISSION_VEHICLE) {\n\t\t\t\t\t\t\tif (nearVeh->m_vecMoveSpeed.Magnitude() <= 0.1f) {\n\t\t\t\t\t\t\t\tif (nearVeh->CanPedOpenLocks(this)) {\n\t\t\t\t\t\t\t\t\tCVector vehDistVec = GetPosition() - nearVeh->GetPosition();\n\t\t\t\t\t\t\t\t\tfloat vehDist = vehDistVec.Magnitude();\n\t\t\t\t\t\t\t\t\tif (vehDist < closestCarDist) {\n\t\t\t\t\t\t\t\t\t\tcarToSteal = nearVeh;\n\t\t\t\t\t\t\t\t\t\tclosestCarDist = vehDist;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (carToSteal) {\n\t\t\t\t\t\tSetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, carToSteal);\n\t\t\t\t\t\tm_carJackTimer = CTimer::GetTimeInMilliseconds() + 5000;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tRestorePreviousObjective();\n\t\t\t\t\t\tRestorePreviousState();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase OBJECTIVE_MUG_CHAR:\n\t\t\t{\n\t\t\t\tif (m_pedInObjective) {\n\t\t\t\t\tif (m_pedInObjective->IsPlayer() || m_pedInObjective->bInVehicle || m_pedInObjective->m_fHealth <= 0.0f) {\n\t\t\t\t\t\tClearObjective();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (m_pedInObjective->m_nMoveState > PEDMOVE_WALK) {\n\t\t\t\t\t\tClearObjective();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (m_pedInObjective->m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT && m_pedInObjective->m_pedInObjective == this) {\n\t\t\t\t\t\tSetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE, m_pedInObjective);\n\t\t\t\t\t\tSetMoveState(PEDMOVE_SPRINT);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (m_pedInObjective->m_nPedState == PED_FLEE_ENTITY && m_fleeFrom == this\n\t\t\t\t\t\t|| m_pedInObjective->m_objective == OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE && m_pedInObjective->m_pedInObjective == this) {\n\t\t\t\t\t\tClearObjective();\n\t\t\t\t\t\tSetFindPathAndFlee(m_pedInObjective, 15000, true);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tfloat distWithTargetScSqr = distWithTarget.MagnitudeSqr();\n\t\t\t\t\tif (distWithTargetScSqr <= sq(10.0f)) {\n\t\t\t\t\t\tif (distWithTargetScSqr <= sq(1.4f)) {\n\t\t\t\t\t\t\tCAnimBlendAssociation *reloadAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_PARTIAL_FUCKU);\n\t\t\t\t\t\t\tm_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(\n\t\t\t\t\t\t\t\tm_pedInObjective->GetPosition().x, m_pedInObjective->GetPosition().y,\n\t\t\t\t\t\t\t\tGetPosition().x, GetPosition().y);\n\n\t\t\t\t\t\t\tif (reloadAssoc || !m_pedInObjective->IsPedShootable()) {\n\t\t\t\t\t\t\t\tif (reloadAssoc &&\n\t\t\t\t\t\t\t\t\t(!reloadAssoc->IsRunning() || reloadAssoc->GetProgress() > 0.8f)) {\n\t\t\t\t\t\t\t\t\tCAnimBlendAssociation *punchAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_PARTIAL_PUNCH, 8.0f);\n\t\t\t\t\t\t\t\t\tpunchAssoc->flags |= ASSOC_DELETEFADEDOUT;\n\t\t\t\t\t\t\t\t\tpunchAssoc->flags |= ASSOC_FADEOUTWHENDONE;\n\t\t\t\t\t\t\t\t\tCVector2D offset(distWithTarget.x, distWithTarget.y);\n\t\t\t\t\t\t\t\t\tint dir = m_pedInObjective->GetLocalDirection(offset);\n\t\t\t\t\t\t\t\t\tm_pedInObjective->StartFightDefend(dir, HITLEVEL_HIGH, 5);\n\t\t\t\t\t\t\t\t\tm_pedInObjective->ReactToAttack(this);\n\t\t\t\t\t\t\t\t\tm_pedInObjective->Say(SOUND_PED_ROBBED);\n\t\t\t\t\t\t\t\t\tSay(SOUND_PED_MUGGING);\n\t\t\t\t\t\t\t\t\tbRichFromMugging = true;\n\n\t\t\t\t\t\t\t\t\t// FIX: ClearObjective() clears m_pedInObjective, so get it before call\n\t\t\t\t\t\t\t\t\tCPed *victim = m_pedInObjective;\n\t\t\t\t\t\t\t\t\tClearObjective();\n\t\t\t\t\t\t\t\t\tif (victim->m_objective != OBJECTIVE_KILL_CHAR_ON_FOOT\n\t\t\t\t\t\t\t\t\t\t|| victim->m_pedInObjective != this) {\n\t\t\t\t\t\t\t\t\t\tSetFindPathAndFlee(victim, 15000, true);\n\t\t\t\t\t\t\t\t\t\tm_nLastPedState = PED_WANDER_PATH;\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tSetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE, victim);\n\t\t\t\t\t\t\t\t\t\tSetMoveState(PEDMOVE_SPRINT);\n\t\t\t\t\t\t\t\t\t\tm_nLastPedState = PED_WANDER_PATH;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\teWeaponType weaponType = GetWeapon()->m_eWeaponType;\n\t\t\t\t\t\t\t\tif (weaponType != WEAPONTYPE_UNARMED && weaponType != WEAPONTYPE_BASEBALLBAT)\n\t\t\t\t\t\t\t\t\tSetCurrentWeapon(WEAPONTYPE_UNARMED);\n\n\t\t\t\t\t\t\t\tCAnimBlendAssociation *newReloadAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_PARTIAL_FUCKU, 8.0f);\n\t\t\t\t\t\t\t\tnewReloadAssoc->flags |= ASSOC_DELETEFADEDOUT;\n\t\t\t\t\t\t\t\tnewReloadAssoc->flags |= ASSOC_FADEOUTWHENDONE;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tSetSeek(m_pedInObjective, 1.0f);\n\t\t\t\t\t\t\tCAnimBlendAssociation *walkAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_WALK);\n\n\t\t\t\t\t\t\tif (walkAssoc)\n\t\t\t\t\t\t\t\twalkAssoc->speed = 1.3f;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tClearObjective();\n\t\t\t\t\t\tSetWanderPath(CGeneral::GetRandomNumber() & 7);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tm_objective = OBJECTIVE_NONE;\n\t\t\t\t\tClearObjective();\n\t\t\t\t}\n\t\t\t}\n\t\t\t// fall through\n\t\t\tcase OBJECTIVE_WANDER:\n\t\t\t\tif (CTimer::GetTimeInMilliseconds() > m_leaveCarTimer && !bInVehicle) {\n\t\t\t\t\tm_leaveCarTimer = 0;\n\t\t\t\t\tm_objective = OBJECTIVE_NONE;\n\t\t\t\t\tSetWanderPath(m_nPathDir);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase OBJECTIVE_LEAVE_CAR_AND_DIE:\n\t\t\t{\n\t\t\t\tif (CTimer::GetTimeInMilliseconds() > m_leaveCarTimer) {\n\t\t\t\t\tif (InVehicle()) {\n\t\t\t\t\t\tif (m_nPedState != PED_EXIT_CAR && m_nPedState != PED_DRAG_FROM_CAR && m_nPedState != PED_EXIT_TRAIN) {\n\t\t\t\t\t\t\tif (m_pMyVehicle->IsBoat())\n\t\t\t\t\t\t\t\tSetExitBoat(m_pMyVehicle);\n\t\t\t\t\t\t\telse if (m_pMyVehicle->bIsBus)\n\t\t\t\t\t\t\t\tSetExitCar(m_pMyVehicle, 0);\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\teCarNodes doorNode = CAR_DOOR_LF;\n\t\t\t\t\t\t\t\tif (m_pMyVehicle->pDriver != this) {\n\t\t\t\t\t\t\t\t\tif (m_pMyVehicle->pPassengers[0] == this) {\n\t\t\t\t\t\t\t\t\t\tdoorNode = CAR_DOOR_RF;\n\t\t\t\t\t\t\t\t\t} else if (m_pMyVehicle->pPassengers[1] == this) {\n\t\t\t\t\t\t\t\t\t\tdoorNode = CAR_DOOR_LR;\n\t\t\t\t\t\t\t\t\t} else if (m_pMyVehicle->pPassengers[2] == this) {\n\t\t\t\t\t\t\t\t\t\tdoorNode = CAR_DOOR_RR;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tSetBeingDraggedFromCar(m_pMyVehicle, doorNode, false);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase OBJECTIVE_GOTO_AREA_ANY_MEANS:\n\t\t\t{\n\t\t\t\tdistWithTarget = m_nextRoutePointPos - GetPosition();\n\t\t\t\tdistWithTarget.z = 0.0f;\n\t\t\t\tif (InVehicle()) {\n\t\t\t\t\tCCarAI::GetCarToGoToCoors(m_pMyVehicle, &m_nextRoutePointPos);\n\t\t\t\t\tCCarCtrl::RegisterVehicleOfInterest(m_pMyVehicle);\n\t\t\t\t\tif (distWithTarget.MagnitudeSqr() < sq(20.0f)) {\n\t\t\t\t\t\tm_pMyVehicle->AutoPilot.m_nCruiseSpeed = 0;\n\t\t\t\t\t\tForceStoredObjective(OBJECTIVE_GOTO_AREA_ANY_MEANS);\n\t\t\t\t\t\tSetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif (distWithTarget.Magnitude() > 30.0f) {\n\t\t\t\t\tif (m_pMyVehicle) {\n\t\t\t\t\t\tm_pMyVehicle->AutoPilot.m_nCruiseSpeed = 0;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tfloat closestVehDist = SQR(60.0f);\n\t\t\t\t\t\tint16 lastVehicle;\n\t\t\t\t\t\tCEntity* vehicles[8];\n\t\t\t\t\t\t// NB: 25.0f in here is prolly a forgotten setting, all other places now use 30.0f (ENTER_CAR_MAX_DIST)\n\t\t\t\t\t\tCWorld::FindObjectsInRange(GetPosition(), 25.0f, true, &lastVehicle, 6, vehicles, false, true, false, false, false);\n\t\t\t\t\t\tCVehicle* foundVeh = nil;\n\t\t\t\t\t\tfor (int i = 0; i < lastVehicle; i++) {\n\t\t\t\t\t\t\tCVehicle* nearVeh = (CVehicle*)vehicles[i];\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\tNot used.\n\t\t\t\t\t\t\tCVector vehSpeed = nearVeh->GetSpeed();\n\t\t\t\t\t\t\tCVector ourSpeed = GetSpeed();\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tCVector vehDistVec = nearVeh->GetPosition() - GetPosition();\n\t\t\t\t\t\t\tif (vehDistVec.MagnitudeSqr() < closestVehDist && m_pedInObjective->m_pMyVehicle != nearVeh) {\n\t\t\t\t\t\t\t\tfoundVeh = nearVeh;\n\t\t\t\t\t\t\t\tclosestVehDist = vehDistVec.MagnitudeSqr();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tm_pMyVehicle = foundVeh;\n\t\t\t\t\t\tif (m_pMyVehicle) {\n\t\t\t\t\t\t\tm_pMyVehicle->RegisterReference((CEntity **) &m_pMyVehicle);\n\t\t\t\t\t\t\tm_pMyVehicle->AutoPilot.m_nCruiseSpeed = 0;\n\t\t\t\t\t\t\tSetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, m_pMyVehicle);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t// Falls to different objectives in III and VC\n#ifdef FIX_BUGS\n\t\t\t\tbreak;\n#else\n\t\t\t\t// fall through\n#endif\n\t\t\t}\n\t\t\tcase OBJECTIVE_GOTO_SEAT_ON_FOOT:\n\t\t\tcase OBJECTIVE_GOTO_ATM_ON_FOOT:\n\t\t\tcase OBJECTIVE_GOTO_BUS_STOP_ON_FOOT:\n\t\t\tcase OBJECTIVE_GOTO_PIZZA_ON_FOOT:\n\t\t\tcase OBJECTIVE_GOTO_SHELTER_ON_FOOT:\n\t\t\tcase OBJECTIVE_GOTO_ICE_CREAM_VAN_ON_FOOT:\n\t\t\t\tif (CTimer::GetTimeInMilliseconds() > m_objectiveTimer) {\n\t\t\t\t\tm_objectiveTimer = 0;\n\t\t\t\t\tif (m_attractor)\n\t\t\t\t\t\tGetPedAttractorManager()->DeRegisterPed(this, m_attractor);\n\t\t\t\t} else {\n\t\t\t\t\tCVector distance = m_nextRoutePointPos - GetPosition();\n\t\t\t\t\tdistance.z = 0.0f;\n\t\t\t\t\tif (m_objective == OBJECTIVE_GOTO_SHELTER_ON_FOOT) {\n\t\t\t\t\t\tif (m_nMoveState == PEDMOVE_RUN && distance.MagnitudeSqr() < SQR(2.0f)) {\n\t\t\t\t\t\t\tSetMoveState(PEDMOVE_WALK);\n\t\t\t\t\t\t\tbIsRunning = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (CWeather::Rain < 0.2f && m_attractor) {\n\t\t\t\t\t\t\tGetPedAttractorManager()->DeRegisterPed(this, m_attractor);\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse if (m_objective == OBJECTIVE_GOTO_ICE_CREAM_VAN_ON_FOOT) {\n\t\t\t\t\t\tif (m_nMoveState == PEDMOVE_RUN && distance.MagnitudeSqr() < SQR(4.0f)) {\n\t\t\t\t\t\t\tSetMoveState(PEDMOVE_WALK);\n\t\t\t\t\t\t\tbIsRunning = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tCVehicle* pIceCreamVan = GetPedAttractorManager()->GetIceCreamVanForEffect(m_attractor->GetEffect());\n\t\t\t\t\t\tif (0.01f * CTimer::GetTimeStep() * 5.0f < pIceCreamVan->m_fDistanceTravelled) {\n\t\t\t\t\t\t\tGetPedAttractorManager()->DeRegisterPed(this, m_attractor);\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!pIceCreamVan->pDriver ||\n\t\t\t\t\t\t\t!pIceCreamVan->pDriver->IsPlayer() ||\n\t\t\t\t\t\t\tpIceCreamVan->pDriver->GetPedState() == PED_ARRESTED ||\n\t\t\t\t\t\t\tpIceCreamVan->pDriver->GetPedState() == PED_DEAD) {\n\t\t\t\t\t\t\tGetPedAttractorManager()->DeRegisterPed(this, m_attractor);\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!pIceCreamVan->m_bSirenOrAlarm) {\n\t\t\t\t\t\t\tGetPedAttractorManager()->DeRegisterPed(this, m_attractor);\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (pIceCreamVan->GetStatus() == STATUS_WRECKED) {\n\t\t\t\t\t\t\tGetPedAttractorManager()->DeRegisterPed(this, m_attractor);\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (sq(m_distanceToCountSeekDone) < distance.MagnitudeSqr()) {\n\t\t\t\t\t\tif (CTimer::GetTimeInMilliseconds() > m_nPedStateTimer || GetPedState() != PED_SEEK_POS) {\n\t\t\t\t\t\t\tm_vecSeekPos = m_nextRoutePointPos;\n\t\t\t\t\t\t\tSetSeek(m_vecSeekPos, m_distanceToCountSeekDone);\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\tif (!bReachedAttractorHeadingTarget) {\n\t\t\t\t\t\t\tfloat fHeadingDistance = m_fRotationCur - m_attractorHeading;\n\t\t\t\t\t\t\tfloat fSinHeading = Sin(fHeadingDistance);\n\t\t\t\t\t\t\tfloat fCosHeading = Cos(fHeadingDistance);\n\t\t\t\t\t\t\tif (fSinHeading > 0.0f) {\n\t\t\t\t\t\t\t\tif (fCosHeading > 0.0f)\n\t\t\t\t\t\t\t\t\tm_attractorHeading = m_fRotationCur - Asin(fSinHeading);\n\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\tm_attractorHeading = m_fRotationCur - Acos(fCosHeading);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tif (fCosHeading > 0.0f)\n\t\t\t\t\t\t\t\t\tm_attractorHeading = m_fRotationCur - Asin(fSinHeading);\n\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\tm_attractorHeading = m_fRotationCur + Acos(fCosHeading);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tm_fRotationDest = m_attractorHeading;\n\t\t\t\t\t\t\tm_headingRate = 3.5f;\n\t\t\t\t\t\t\tbReachedAttractorHeadingTarget = true;\n\t\t\t\t\t\t\tbTurnedAroundOnAttractor = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (Abs(m_fRotationCur - m_attractorHeading) >= m_acceptableHeadingOffset &&\n\t\t\t\t\t\t\tAbs(m_fRotationCur - m_attractorHeading + TWOPI) >= m_acceptableHeadingOffset &&\n\t\t\t\t\t\t\tAbs(m_fRotationCur - m_attractorHeading - TWOPI) >= m_acceptableHeadingOffset)\n\t\t\t\t\t\t\tSetMoveState(PEDMOVE_STILL);\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tm_fRotationDest = m_fRotationCur;\n\t\t\t\t\t\t\tbReachedAttractorHeadingTarget = false;\n\t\t\t\t\t\t\tbObjectiveCompleted = true;\n\t\t\t\t\t\t\tbScriptObjectiveCompleted = true;\n\t\t\t\t\t\t\tRestoreHeadingRate();\n\t\t\t\t\t\t\tGetPedAttractorManager()->BroadcastArrival(this, m_attractor);\n\t\t\t\t\t\t\tif (GetPedAttractorManager()->IsAtHeadOfQueue(this, m_attractor)) {\n\t\t\t\t\t\t\t\tswitch (m_objective) {\n\t\t\t\t\t\t\t\tcase OBJECTIVE_GOTO_SEAT_ON_FOOT:\n\t\t\t\t\t\t\t\t\tif (!bTurnedAroundOnAttractor) {\n\t\t\t\t\t\t\t\t\t\tClearObjective();\n\t\t\t\t\t\t\t\t\t\tSetWaitState(WAITSTATE_SIT_DOWN, 0);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\t\t\tClearObjective();\n\t\t\t\t\t\t\t\t\t\tSetWaitState(WAITSTATE_SIT_DOWN_RVRS, 0);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase OBJECTIVE_GOTO_ATM_ON_FOOT:\n\t\t\t\t\t\t\t\t\tClearObjective();\n\t\t\t\t\t\t\t\t\tSetWaitState(WAITSTATE_USE_ATM, 0);\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase OBJECTIVE_GOTO_BUS_STOP_ON_FOOT:\n\t\t\t\t\t\t\t\t\tClearObjective();\n\t\t\t\t\t\t\t\t\tSetObjective(OBJECTIVE_WAIT_ON_FOOT_AT_BUS_STOP);\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase OBJECTIVE_GOTO_PIZZA_ON_FOOT:\n\t\t\t\t\t\t\t\t\tClearObjective();\n\t\t\t\t\t\t\t\t\tm_prevObjective = OBJECTIVE_NONE;\n\t\t\t\t\t\t\t\t\tSetObjective(OBJECTIVE_WAIT_ON_FOOT);\n\t\t\t\t\t\t\t\t\tm_objectiveTimer = CTimer::GetTimeInMilliseconds() + m_attractor->GetHeadOfQueueWaitTime();\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase OBJECTIVE_GOTO_SHELTER_ON_FOOT:\n\t\t\t\t\t\t\t\t\tm_prevObjective = OBJECTIVE_NONE;\n\t\t\t\t\t\t\t\t\tSetObjective(OBJECTIVE_WAIT_ON_FOOT_AT_SHELTER);\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase OBJECTIVE_GOTO_ICE_CREAM_VAN_ON_FOOT:\n\t\t\t\t\t\t\t\t\tm_prevObjective = OBJECTIVE_NONE;\n\t\t\t\t\t\t\t\t\tSetObjective(OBJECTIVE_WAIT_ON_FOOT_AT_ICE_CREAM_VAN);\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tm_prevObjective = OBJECTIVE_NONE;\n\t\t\t\t\t\t\t\tSetObjective(OBJECTIVE_WAIT_ON_FOOT);\n\t\t\t\t\t\t\t\tm_objectiveTimer = 0;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\tcase OBJECTIVE_FLEE_CAR:\n\t\t\t\tif (!bInVehicle && m_nPedState != PED_FLEE_ENTITY && m_pMyVehicle) {\n\t\t\t\t\tRestorePreviousObjective();\n\t\t\t\t\tSetFlee(m_pMyVehicle, 6000);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t// fall through\n\t\t\tcase OBJECTIVE_LEAVE_CAR:\n\t\t\t\tif (CTimer::GetTimeInMilliseconds() > m_leaveCarTimer) {\n\t\t\t\t\tif (InVehicle() &&\n\t\t\t\t\t\t(FindPlayerPed() != this || !CPad::GetPad(0)->GetAccelerate() || bBusJacked)) {\n\n\t\t\t\t\t\tif (m_nPedState != PED_EXIT_CAR && m_nPedState != PED_DRAG_FROM_CAR && m_nPedState != PED_EXIT_TRAIN\n\t\t\t\t\t\t\t&& (m_nPedType != PEDTYPE_COP\n\t\t\t\t\t\t\t\t|| m_pMyVehicle->IsBoat()\n\t\t\t\t\t\t\t\t|| m_pMyVehicle->m_vecMoveSpeed.MagnitudeSqr2D() < sq(0.005f))) {\n#ifdef GTA_TRAIN\n\t\t\t\t\t\t\tif (m_pMyVehicle->IsTrain())\n\t\t\t\t\t\t\t\tSetExitTrain(m_pMyVehicle);\n\t\t\t\t\t\t\telse\n#endif\n\t\t\t\t\t\t\tif (m_pMyVehicle->IsBoat())\n\t\t\t\t\t\t\t\tSetExitBoat(m_pMyVehicle);\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\tSetExitCar(m_pMyVehicle, 0);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tRestorePreviousObjective();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (bHeldHostageInCar) {\n\t\t\t\t\tif (CTheScripts::IsPlayerOnAMission()) {\n\t\t\t\t\t\tCVehicle *playerVeh = FindPlayerVehicle();\n\t\t\t\t\t\tif (playerVeh && playerVeh->IsPassenger(this)) {\n\t\t\t\t\t\t\tif (m_leaveCarTimer != 0)\n\t\t\t\t\t\t\t\tm_leaveCarTimer = 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase OBJECTIVE_AIM_GUN_AT:\n\t\t\t\tif (m_pedInObjective) {\n\t\t\t\t\tif (!bObstacleShowedUpDuringKillObjective)\n\t\t\t\t\t\tSetPointGunAt(m_pedInObjective);\n\n\t\t\t\t\tif (m_nMoveState == PEDMOVE_STILL && IsPedInControl()) {\n\t\t\t\t\t\tSetLookFlag(m_pedInObjective, false);\n\t\t\t\t\t\tTurnBody();\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tClearObjective();\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase OBJECTIVE_WAIT_ON_FOOT_AT_SHELTER:\n\t\t\t\tSetIdle();\n\t\t\t\tif (m_attractor && CWeather::Rain < 0.2f)\n\t\t\t\t\tGetPedAttractorManager()->DeRegisterPed(this, m_attractor);\n\t\t\t\tbreak;\n\t\t\tcase OBJECTIVE_KILL_CHAR_ON_BOAT:\n\t\t\t\tSetPedStats(PEDSTAT_TOUGH_GUY);\n\t\t\t\tif (bInVehicle) {\n\t\t\t\t\tif (m_pedInObjective && m_pedInObjective->m_pCurrentPhysSurface != m_pMyVehicle) {\n\t\t\t\t\t\tbObjectiveCompleted = true;\n\t\t\t\t\t\tClearObjective();\n\t\t\t\t\t\tCCarCtrl::SwitchVehicleToRealPhysics(m_pMyVehicle);\n\t\t\t\t\t\tm_pMyVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS;\n\t\t\t\t\t\tm_pMyVehicle->AutoPilot.m_nCruiseSpeed = GAME_SPEED_TO_CARAI_SPEED * m_pMyVehicle->pHandling->Transmission.fMaxCruiseVelocity;\n\t\t\t\t\t\tm_pMyVehicle->SetStatus(STATUS_PHYSICS);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tSetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle);\n\t\t\t\t\t}\n\t\t\t\t} else if (m_pedInObjective && !m_pedInObjective->DyingOrDead() &&\n\t\t\t\t\t(!m_pCurrentPhysSurface || !m_pedInObjective->m_pCurrentPhysSurface ||\n\t\t\t\t\t\tm_pedInObjective->m_pCurrentPhysSurface == m_pCurrentPhysSurface)) {\n\n\t\t\t\t\tCBoat *boatWeAreOn = nil;\n\t\t\t\t\tif (m_pCurrentPhysSurface && m_pCurrentPhysSurface->IsVehicle() && ((CVehicle*)m_pCurrentPhysSurface)->IsBoat())\n\t\t\t\t\t\tboatWeAreOn = (CBoat*)m_pCurrentPhysSurface;\n\n\t\t\t\t\tif (boatWeAreOn) {\n\t\t\t\t\t\tSetObjective(OBJECTIVE_RUN_TO_AREA, boatWeAreOn->GetPosition() - (boatWeAreOn->GetForward() * 10.f));\n\t\t\t\t\t} else if (m_pedInObjective) {\n\t\t\t\t\t\tSetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_ALWAYS, m_pedInObjective);\n\t\t\t\t\t}\n\t\t\t\t\tSetMoveAnim();\n\t\t\t\t} else {\n\t\t\t\t\tClearLookFlag();\n\t\t\t\t\tSetMoveAnim();\n\t\t\t\t\tif (m_pCurrentPhysSurface && m_pCurrentPhysSurface->IsVehicle())\n\t\t\t\t\t\tSetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, m_pCurrentPhysSurface);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase OBJECTIVE_SOLICIT_FOOT:\n\t\t\t\tif (m_pedInObjective) {\n\t\t\t\t\tif (m_objectiveTimer < CTimer::GetTimeInMilliseconds())\n\t\t\t\t\t\tbScriptObjectiveCompleted = true;\n\t\t\t\t} else {\n\t\t\t\t\tbScriptObjectiveCompleted = true;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase OBJECTIVE_WAIT_ON_FOOT_AT_BUS_STOP:\n\t\t\t\tSetIdle();\n\t\t\t\tif (m_attractor) {\n\t\t\t\t\tfloat left = GetPosition().x - 10.0f;\n\t\t\t\t\tfloat right = GetPosition().x + 10.0f;\n\t\t\t\t\tfloat top = GetPosition().y - 10.0f;\n\t\t\t\t\tfloat bottom = GetPosition().y + 10.0f;\n\t\t\t\t\tint xstart = Max(0, CWorld::GetSectorIndexX(left));\n\t\t\t\t\tint xend = Min(NUMSECTORS_X - 1, CWorld::GetSectorIndexX(right));\n\t\t\t\t\tint ystart = Max(0, CWorld::GetSectorIndexY(top));\n\t\t\t\t\tint yend = Min(NUMSECTORS_Y - 1, CWorld::GetSectorIndexY(bottom));\n\t\t\t\t\tassert(xstart <= xend);\n\t\t\t\t\tassert(ystart <= yend);\n\n\t\t\t\t\tfloat minDistance = SQR(10.0f);\n\t\t\t\t\tCVehicle* pBus = nil;\n\n\t\t\t\t\tfor (int y = ystart; y <= yend; y++) {\n\t\t\t\t\t\tfor (int x = xstart; x <= xend; x++) {\n\t\t\t\t\t\t\tCSector* s = CWorld::GetSector(x, y);\n\t\t\t\t\t\t\tfor (CPtrNode* pNode = s->m_lists[ENTITYLIST_VEHICLES].first; pNode != nil; pNode = pNode->next) {\n\t\t\t\t\t\t\t\tCEntity* pEntity = (CEntity*)pNode->item;\n\t\t\t\t\t\t\t\tif (!pEntity->IsVehicle())\n\t\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t\tCVehicle* pVehicle = (CVehicle*)pEntity;\n\t\t\t\t\t\t\t\tif (!pVehicle->bIsBus)\n\t\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t\tif (pVehicle->GetMoveSpeed().MagnitudeSqr() >= SQR(0.005f))\n\t\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t\tfloat distanceSq = (GetPosition() - pVehicle->GetPosition()).MagnitudeSqr();\n\t\t\t\t\t\t\t\tif (distanceSq < minDistance) {\n\t\t\t\t\t\t\t\t\tminDistance = distanceSq;\n\t\t\t\t\t\t\t\t\tpBus = pVehicle;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (pBus) {\n\t\t\t\t\t\tif (pBus->m_nNumPassengers >= pBus->m_nNumMaxPassengers - 1)\n\t\t\t\t\t\t\tSetObjective(OBJECTIVE_WAIT_ON_FOOT);\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tGetPedAttractorManager()->DeRegisterPed(this, m_attractor);\n\t\t\t\t\t\t\tSetObjective(OBJECTIVE_ENTER_CAR_AS_PASSENGER, pBus);\n\t\t\t\t\t\t\tbDontDragMeOutCar = true;\n\t\t\t\t\t\t\tbRemoveMeWhenIGotIntoCar = true;\n\t\t\t\t\t\t\tCPlayerPed *player = FindPlayerPed();\n\t\t\t\t\t\t\tif (pBus->IsPassenger(player) || pBus->IsDriver(player)) {\n\t\t\t\t\t\t\t\tbCollectBusFare = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase OBJECTIVE_WAIT_ON_FOOT_AT_ICE_CREAM_VAN:\n\t\t\t{\n\t\t\t\tSetIdle();\n\t\t\t\tCVehicle* pIceCreamVan = GetPedAttractorManager()->GetIceCreamVanForEffect(m_attractor->GetEffect());\n\t\t\t\tif (m_attractor && m_nWaitState != WAITSTATE_PLAYANIM_CHAT && pIceCreamVan && pIceCreamVan->pDriver && pIceCreamVan->pDriver->IsPlayer()) {\n\t\t\t\t\tint time = 5000;\n\t\t\t\t\tSetWaitState(WAITSTATE_PLAYANIM_CHAT, &time);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif (!m_attractor)\n\t\t\t\t\tbreak;\n\t\t\t\tCVehicle* pVan = GetPedAttractorManager()->GetIceCreamVanForEffect(m_attractor->GetEffect());\n\t\t\t\tif (!pVan)\n\t\t\t\t\tbreak;\n\t\t\t\tif (0.01f * CTimer::GetTimeStep() * 5.0f < pVan->m_fDistanceTravelled) {\n\t\t\t\t\tGetPedAttractorManager()->DeRegisterPed(this, m_attractor);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif (!pVan->pDriver || !pVan->pDriver->IsPlayer() || pVan->pDriver->GetPedState() == PED_ARRESTED || pVan->pDriver->GetPedState() == PED_DEAD) {\n\t\t\t\t\tGetPedAttractorManager()->DeRegisterPed(this, m_attractor);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif (!pVan->m_bSirenOrAlarm) {\n\t\t\t\t\tGetPedAttractorManager()->DeRegisterPed(this, m_attractor);\n\t\t\t\t\treturn; // Why?\n\t\t\t\t}\n\t\t\t\tif (pVan->GetStatus() == STATUS_WRECKED) {\n\t\t\t\t\tGetPedAttractorManager()->DeRegisterPed(this, m_attractor);\n\t\t\t\t\treturn; // Why?\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (bObjectiveCompleted\n\t\t\t|| m_objectiveTimer > 0 && CTimer::GetTimeInMilliseconds() > m_objectiveTimer) {\n\t\t\tRestorePreviousObjective();\n\t\t\tif (m_objectiveTimer > CTimer::GetTimeInMilliseconds() || !m_objectiveTimer)\n\t\t\t\tm_objectiveTimer = CTimer::GetTimeInMilliseconds() - 1;\n\n\t\t\tif (CharCreatedBy != RANDOM_CHAR || bInVehicle) {\n\t\t\t\tif (IsPedInControl())\n\t\t\t\t\tRestorePreviousState();\n\t\t\t} else {\n\t\t\t\tSetWanderPath(CGeneral::GetRandomNumber() & 7);\n\t\t\t}\n\t\t\tClearAimFlag();\n\t\t\tClearLookFlag();\n\t\t}\n\t}\n}\n\nvoid\nCPed::SetFollowRoute(int16 currentPoint, int16 routeType)\n{\n\tm_routeLastPoint = currentPoint;\n\tm_routeType = routeType;\n\tm_routePointsBeingPassed = 1;\n\tm_routePointsPassed = 0;\n\tm_objective = OBJECTIVE_FOLLOW_ROUTE;\n\tm_routeStartPoint = CRouteNode::GetRouteStart(currentPoint);\n\tm_nextRoutePointPos = CRouteNode::GetPointPosition(GetNextPointOnRoute());\n}\n\nint\nCPed::GetNextPointOnRoute(void)\n{\n\tint16 nextPoint = m_routePointsBeingPassed + m_routePointsPassed + m_routeStartPoint;\n\n\t// Route is complete\n\tif (nextPoint < 0 || nextPoint > NUMPEDROUTES || m_routeLastPoint != CRouteNode::GetRouteThisPointIsOn(nextPoint)) {\n\n\t\tswitch (m_routeType) {\n\t\t\tcase PEDROUTE_STOP_WHEN_DONE:\n\t\t\t\tnextPoint = -1;\n\t\t\t\tbreak;\n\t\t\tcase PEDROUTE_GO_BACKWARD_WHEN_DONE:\n\t\t\t\tm_routePointsBeingPassed = -m_routePointsBeingPassed;\n\t\t\t\tnextPoint = m_routePointsBeingPassed + m_routePointsPassed + m_routeStartPoint;\n\t\t\t\tbreak;\n\t\t\tcase PEDROUTE_GO_TO_START_WHEN_DONE:\n\t\t\t\tm_routePointsPassed = -1;\n\t\t\t\tnextPoint = m_routePointsBeingPassed + m_routePointsPassed + m_routeStartPoint;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n\treturn nextPoint;\n}\n\nbool\nCPed::HaveReachedNextPointOnRoute(float distToCountReached)\n{\n\tif ((m_nextRoutePointPos - GetPosition()).Magnitude2D() < distToCountReached) {\n\t\tm_routePointsPassed += m_routePointsBeingPassed;\n\t\treturn true;\n\t}\n\treturn false;\n}\n\nbool\nCPed::CanSeeEntity(CEntity *entity, float threshold)\n{\n\tfloat neededAngle = CGeneral::GetRadianAngleBetweenPoints(\n\t\tentity->GetPosition().x,\n\t\tentity->GetPosition().y,\n\t\tGetPosition().x,\n\t\tGetPosition().y);\n\n\tif (neededAngle < 0.0f)\n\t\tneededAngle += TWOPI;\n\telse if (neededAngle > TWOPI)\n\t\tneededAngle -= TWOPI;\n\n\tfloat ourAngle = m_fRotationCur;\n\tif (ourAngle < 0.0f)\n\t\tourAngle += TWOPI;\n\telse if (ourAngle > TWOPI)\n\t\tourAngle -= TWOPI;\n\n\tfloat neededTurn = Abs(neededAngle - ourAngle);\n\n\treturn neededTurn < threshold || TWOPI - threshold < neededTurn;\n}\n\n// Only used while deciding which gun ped should switch to, if no ammo left.\nbool\nCPed::SelectGunIfArmed(void)\n{\n\tfor (int i = 0; i < TOTAL_WEAPON_SLOTS; i++) {\n\t\tif (GetWeapon(i).m_nAmmoTotal > 0) {\n\t\t\teWeaponType weaponType = GetWeapon(i).m_eWeaponType;\n\n\t\t\tif (weaponType == WEAPONTYPE_COLT45 || weaponType == WEAPONTYPE_UZI || weaponType == WEAPONTYPE_MP5 || weaponType == WEAPONTYPE_M4 ||\n\t\t\t\tweaponType == WEAPONTYPE_COLT45 || weaponType == WEAPONTYPE_PYTHON || weaponType == WEAPONTYPE_SHOTGUN ||\n\t\t\t\tweaponType == WEAPONTYPE_SPAS12_SHOTGUN || weaponType == WEAPONTYPE_STUBBY_SHOTGUN ||\n\t\t\t\tweaponType == WEAPONTYPE_ROCKETLAUNCHER || weaponType == WEAPONTYPE_SNIPERRIFLE || weaponType == WEAPONTYPE_FLAMETHROWER) {\n\t\t\t\tSetCurrentWeapon(i);\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t}\n\tSetCurrentWeapon(WEAPONTYPE_UNARMED);\n\treturn false;\n}\nvoid\nCPed::ReactToPointGun(CEntity *entWithGun)\n{\n\tCPed *pedWithGun = (CPed*)entWithGun;\n\tint waitTime;\n\n\tif (IsPlayer() || !IsPedInControl() || (CharCreatedBy == MISSION_CHAR && !bCrouchWhenScared))\n\t\treturn;\n\n\tif (m_leader == pedWithGun)\n\t\treturn;\n\n\tif (m_nWaitState == WAITSTATE_PLAYANIM_HANDSUP || m_nWaitState == WAITSTATE_PLAYANIM_HANDSCOWER ||\n\t\t(GetPosition() - pedWithGun->GetPosition()).MagnitudeSqr2D() > 225.0f || (m_nPedType == PEDTYPE_GANG7 && pedWithGun == FindPlayerPed()))\n\t\treturn;\n\n\tif (m_leader) {\n\t\tif (FindPlayerPed() == m_leader)\n\t\t\treturn;\n\n\t\tClearLeader();\n\t}\n\tif (m_pedStats->m_flags & STAT_GUN_PANIC\n\t\t&& (m_nPedState != PED_ATTACK || GetWeapon()->IsTypeMelee())\n\t\t&& m_nPedState != PED_FLEE_ENTITY && m_nPedState != PED_AIM_GUN) {\n\n\t\twaitTime = CGeneral::GetRandomNumberInRange(3000, 6000);\n\t\tSetWaitState(WAITSTATE_PLAYANIM_HANDSCOWER, &waitTime);\n\t\tSay(SOUND_PED_HANDS_COWER);\n\t\tm_pLookTarget = pedWithGun;\n\t\tm_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget);\n\t\tSetMoveState(PEDMOVE_NONE);\n\n\t} else if (m_nPedType != pedWithGun->m_nPedType) {\n\t\tif (IsGangMember() || m_nPedType == PEDTYPE_EMERGENCY || m_nPedType == PEDTYPE_FIREMAN) {\n\t\t\tRegisterThreatWithGangPeds(pedWithGun);\n\t\t}\n\n\t\tif (m_nPedType == PEDTYPE_COP) {\n\t\t\tif (pedWithGun->IsPlayer()) {\n\t\t\t\t((CPlayerPed*)pedWithGun)->m_pWanted->SetWantedLevelNoDrop(2);\n\t\t\t\tif (bCrouchWhenShooting || bKindaStayInSamePlace) {\n\t\t\t\t\tSetDuck(CGeneral::GetRandomNumberInRange(1000, 3000));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (m_nPedType != PEDTYPE_COP\n\t\t\t&& (m_nPedState != PED_ATTACK || GetWeapon()->IsTypeMelee())\n\t\t\t&& (m_nPedState != PED_FLEE_ENTITY || pedWithGun->IsPlayer() && m_fleeFrom != pedWithGun)\n\t\t\t&& m_nPedState != PED_AIM_GUN && m_objective != OBJECTIVE_KILL_CHAR_ON_FOOT) {\n\n\t\t\twaitTime = CGeneral::GetRandomNumberInRange(3000, 6000);\n\t\t\tSetWaitState(WAITSTATE_PLAYANIM_HANDSUP, &waitTime);\n\t\t\tSay(SOUND_PED_HANDS_UP);\n\t\t\tm_pLookTarget = pedWithGun;\n\t\t\tm_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget);\n\t\t\tSetMoveState(PEDMOVE_NONE);\n\t\t\tif (m_nPedState == PED_FLEE_ENTITY) {\n\t\t\t\tm_fleeFrom = pedWithGun;\n\t\t\t\tm_fleeFrom->RegisterReference((CEntity **) &m_fleeFrom);\n\t\t\t}\n\n\t\t\tif (FindPlayerPed() == pedWithGun && bRichFromMugging) {\n\t\t\t\tint money = CGeneral::GetRandomNumberInRange(100, 300);\n\t\t\t\tint pickupCount = money / 40 + 1;\n\t\t\t\tint moneyPerPickup = money / pickupCount;\n\n\t\t\t\tfor (int i = 0; i < pickupCount; i++) {\n\t\t\t\t\tfloat pickupX = 1.5f * Sin((CGeneral::GetRandomNumber() % 256)/256.0f * TWOPI) + GetPosition().x;\n\t\t\t\t\tfloat pickupY = 1.5f * Cos((CGeneral::GetRandomNumber() % 256)/256.0f * TWOPI) + GetPosition().y;\n\t\t\t\t\tbool found = false;\n\t\t\t\t\tfloat groundZ = CWorld::FindGroundZFor3DCoord(pickupX, pickupY, GetPosition().z, &found) + 0.5f;\n\t\t\t\t\tif (found) {\n\t\t\t\t\t\tCPickups::GenerateNewOne(CVector(pickupX, pickupY, groundZ), MI_MONEY, PICKUP_MONEY, moneyPerPickup + (CGeneral::GetRandomNumber() & 7));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbRichFromMugging = false;\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nCPed::ReactToAttack(CEntity *attacker)\n{\n\tif (IsPlayer() && attacker->IsPed()) {\n\t\tInformMyGangOfAttack(attacker);\n\t\tSetLookFlag(attacker, true);\n\t\tSetLookTimer(700);\n\t\treturn;\n\t}\n\t\n\tif (m_nPedType == PEDTYPE_GANG7 && attacker->IsPed() && ((CPed*)attacker)->IsPlayer()) {\n\t\tif (m_nPedState != PED_FALL) {\n\t\t\tSetFall(15000, (AnimationId)(ANIM_STD_KO_FRONT + CGeneral::GetRandomNumberInRange(0, 5)), 0);\n\t\t}\n\n\t} else if (m_nPedState == PED_DRIVING && InVehicle()\n\t\t&& (m_pMyVehicle->pDriver == this || m_pMyVehicle->pDriver && m_pMyVehicle->pDriver->m_nPedState == PED_DRIVING && m_pMyVehicle->pDriver->m_objective != OBJECTIVE_LEAVE_CAR_AND_DIE)) {\n\n\t\tif (m_pMyVehicle->VehicleCreatedBy == RANDOM_VEHICLE\n\t\t\t&& (m_pMyVehicle->GetStatus() == STATUS_SIMPLE || m_pMyVehicle->GetStatus() == STATUS_PHYSICS)\n\t\t\t&& m_pMyVehicle->AutoPilot.m_nCarMission == MISSION_CRUISE) {\n\n\t\t\tCCarCtrl::SwitchVehicleToRealPhysics(m_pMyVehicle);\n\t\t\tm_pMyVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS;\n\t\t\tm_pMyVehicle->AutoPilot.m_nCruiseSpeed = GAME_SPEED_TO_CARAI_SPEED * m_pMyVehicle->pHandling->Transmission.fMaxCruiseVelocity;\n\t\t\tm_pMyVehicle->SetStatus(STATUS_PHYSICS);\n\t\t}\n\n\t} else if ((IsPedInControl() || m_nPedState == PED_DRIVING) && (CharCreatedBy != MISSION_CHAR || bRespondsToThreats)) {\n\t\tif (m_leader != attacker && (!m_leader || FindPlayerPed() != m_leader) && attacker->IsPed()) {\n\n\t\t\tCPed *attackerPed = (CPed*)attacker; \n\t\t\tif (bNotAllowedToDuck) {\n\t\t\t\tif (!attackerPed->GetWeapon()->IsTypeMelee()) {\n\t\t\t\t\tm_duckAndCoverTimer = CTimer::GetTimeInMilliseconds();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t} else if (bCrouchWhenShooting || bKindaStayInSamePlace) {\n\t\t\t\tSetDuck(CGeneral::GetRandomNumberInRange(1000,3000));\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (m_nWaitState == WAITSTATE_STRIPPER) {\n\t\t\t\tClearWaitState();\n\t\t\t\tSetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, attacker);\n\t\t\t\tSetObjectiveTimer(20000);\n\n\t\t\t} else {\n\t\t\t\tif (m_pedStats->m_fear <= 100 - attackerPed->m_pedStats->m_temper) {\n\t\t\t\t\tif (m_pedStats != attackerPed->m_pedStats) {\n\t\t\t\t\t\tif (IsGangMember() || m_nPedType == PEDTYPE_EMERGENCY || m_nPedType == PEDTYPE_FIREMAN) {\n\t\t\t\t\t\t\tRegisterThreatWithGangPeds(attackerPed);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!attackerPed->GetWeapon()->IsTypeMelee() && GetWeapon()->IsTypeMelee()) {\n\t\t\t\t\t\t\tSetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE, attacker);\n\t\t\t\t\t\t\tSetMoveState(PEDMOVE_RUN);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tSetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, attacker);\n\t\t\t\t\t\t\tSetObjectiveTimer(20000);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tSetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE, attackerPed);\n\t\t\t\t\tSetMoveState(PEDMOVE_RUN);\n\t\t\t\t\tif (attackerPed->GetWeapon()->IsTypeMelee())\n\t\t\t\t\t\tSay(SOUND_PED_FLEE_RUN);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nCPed::PedAnimAlignCB(CAnimBlendAssociation *animAssoc, void *arg)\n{\n\tCPed *ped = (CPed*)arg;\n\n\tCVehicle *veh = ped->m_pMyVehicle;\n\tif (animAssoc)\n\t\tanimAssoc->blendDelta = -1000.0f;\n\n\tif (!ped->IsNotInWreckedVehicle())\n\t\treturn;\n\n\tif (!ped->EnteringCar()) {\n\t\tif (ped->m_nPedState != PED_DRIVING)\n\t\t\tped->QuitEnteringCar();\n\n\t\treturn;\n\t}\n\n\tif (!ped->m_vehDoor) {\n\t\tped->QuitEnteringCar();\n\t\treturn;\n\t}\n\n\tif (ped->m_fHealth == 0.0f) {\n\t\tped->QuitEnteringCar();\n\t\treturn;\n\t}\n\tbool itsVan = !!veh->bIsVan;\n\tbool itsBus = !!veh->bIsBus;\n\tbool itsLow = !!veh->bLowVehicle;\n\teDoors enterDoor;\n\n\tswitch (ped->m_vehDoor) {\n\t\tcase CAR_DOOR_RF:\n\t\t\titsVan = false;\n\t\t\tenterDoor = DOOR_FRONT_RIGHT;\n\t\t\tbreak;\n\t\tcase CAR_DOOR_RR:\n\t\t\tenterDoor = DOOR_REAR_RIGHT;\n\t\t\tbreak;\n\t\tcase CAR_DOOR_LF:\n\t\t\titsVan = false;\n\t\t\tenterDoor = DOOR_FRONT_LEFT;\n\t\t\tbreak;\n\t\tcase CAR_DOOR_LR:\n\t\t\tenterDoor = DOOR_REAR_LEFT;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\n\tif (veh->IsBike()) {\n\t\tCPed *pedToDragOut = nil;\n\t\tif (veh->GetStatus() == STATUS_ABANDONED) {\n\t\t\tif (ped->m_vehDoor == CAR_WINDSCREEN) {\n\t\t\t\tped->m_pVehicleAnim = CAnimManager::BlendAnimation(ped->GetClump(), ((CBike*)veh)->m_bikeAnimType, ANIM_BIKE_KICK, 6.0f);\n\t\t\t\tped->m_pVehicleAnim->SetFinishCallback(PedAnimGetInCB, ped);\n\t\t\t\t((CBike*)veh)->bIsBeingPickedUp = true;\n\n\t\t\t} else if (veh->GetRight().z >= 0.5f || veh->GetRight().z <= -0.5f || veh->GetUp().z <= 0.0f) {\n\t\t\t\tif (enterDoor == DOOR_FRONT_LEFT || enterDoor == DOOR_REAR_LEFT) {\n\t\t\t\t\tif (veh->GetRight().z > 0.0f)\n\t\t\t\t\t\tped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_BIKE_PICKUP_LHS);\n\t\t\t\t\telse\n\t\t\t\t\t\tped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_BIKE_PULLUP_LHS);\n\n\t\t\t\t} else {\n\t\t\t\t\tif (veh->GetRight().z < 0.0f)\n\t\t\t\t\t\tped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_BIKE_PICKUP_RHS);\n\t\t\t\t\telse\n\t\t\t\t\t\tped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_BIKE_PULLUP_RHS);\n\t\t\t\t}\n\t\t\t\tped->m_pVehicleAnim->SetFinishCallback(PedAnimDoorOpenCB, ped);\n\n\t\t\t} else {\n\t\t\t\tped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ((CBike*)veh)->m_bikeAnimType,\n\t\t\t\t\tenterDoor == DOOR_FRONT_LEFT || enterDoor == DOOR_REAR_LEFT ? ANIM_BIKE_JUMPON_LHS : ANIM_BIKE_JUMPON_RHS);\n\t\t\t\tped->m_pVehicleAnim->SetFinishCallback(PedAnimGetInCB, ped);\n\t\t\t\t((CBike*)veh)->bIsBeingPickedUp = true;\n\t\t\t}\n\t\t} else if (ped->m_vehDoor == CAR_WINDSCREEN) {\n\t\t\tif (veh->pDriver->m_nPedState != PED_DRIVING || veh->pDriver->bDontDragMeOutCar) {\n\t\t\t\tped->QuitEnteringCar();\n\t\t\t} else {\n\t\t\t\tped->m_pVehicleAnim = CAnimManager::BlendAnimation(ped->GetClump(), ((CBike*)veh)->m_bikeAnimType, ANIM_BIKE_KICK, 6.0f);\n\t\t\t\tped->m_pVehicleAnim->SetFinishCallback(PedAnimGetInCB, ped);\n\t\t\t\tpedToDragOut = veh->pDriver;\n\t\t\t}\n\t\t\t((CBike*)veh)->bIsBeingPickedUp = true;\n\t\t} else {\n\t\t\tif (enterDoor == DOOR_FRONT_LEFT || enterDoor == DOOR_FRONT_RIGHT) {\n\t\t\t\tif (veh->pDriver) {\n\t\t\t\t\tif (veh->m_vecMoveSpeed.Magnitude() > 0.2f) {\n\t\t\t\t\t\tped->QuitEnteringCar();\n\t\t\t\t\t\tped->SetFall(1000, ped->m_vehDoor == CAR_DOOR_LF || ped->m_vehDoor == CAR_DOOR_LR ? ANIM_STD_HIGHIMPACT_RIGHT : ANIM_STD_HIGHIMPACT_LEFT, false);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (veh->pDriver->m_nPedState != PED_DRIVING || veh->pDriver->bDontDragMeOutCar) {\n\t\t\t\t\t\tped->QuitEnteringCar();\n\t\t\t\t\t} else {\n\t\t\t\t\t\tped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, enterDoor == DOOR_FRONT_LEFT ? ANIM_STD_BIKE_ELBOW_LHS : ANIM_STD_BIKE_ELBOW_RHS);\n\t\t\t\t\t\tped->m_pVehicleAnim->SetFinishCallback(PedAnimPullPedOutCB, ped);\n\t\t\t\t\t\tpedToDragOut = veh->pDriver;\n\t\t\t\t\t}\n\t\t\t\t\t((CBike*)veh)->bIsBeingPickedUp = true;\n\n\t\t\t\t} else {\n\t\t\t\t\tped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ((CBike*)veh)->m_bikeAnimType, enterDoor == DOOR_FRONT_LEFT ? ANIM_BIKE_JUMPON_LHS : ANIM_BIKE_JUMPON_RHS);\n\t\t\t\t\tped->m_pVehicleAnim->SetFinishCallback(PedAnimGetInCB, ped);\n\t\t\t\t\t((CBike*)veh)->bIsBeingPickedUp = true;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (veh->pPassengers[0]) {\n\t\t\t\t\tif (veh->m_vecMoveSpeed.Magnitude() > 0.2f) {\n\t\t\t\t\t\tped->QuitEnteringCar();\n\t\t\t\t\t\tped->SetFall(1000, ped->m_vehDoor == CAR_DOOR_LF || ped->m_vehDoor == CAR_DOOR_LR ? ANIM_STD_HIGHIMPACT_RIGHT : ANIM_STD_HIGHIMPACT_LEFT, false);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (veh->pPassengers[0]->m_nPedState != PED_DRIVING || veh->pPassengers[0]->bDontDragMeOutCar) {\n\t\t\t\t\t\tped->QuitEnteringCar();\n\t\t\t\t\t} else {\n\t\t\t\t\t\tped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD,\n\t\t\t\t\t\t\tenterDoor == DOOR_REAR_LEFT ? ANIM_STD_BIKE_ELBOW_LHS : ANIM_STD_BIKE_ELBOW_RHS);\n\t\t\t\t\t\tped->m_pVehicleAnim->SetFinishCallback(PedAnimPullPedOutCB, ped);\n\t\t\t\t\t\tpedToDragOut = veh->pPassengers[0];\n\t\t\t\t\t}\n\t\t\t\t\t((CBike*)veh)->bIsBeingPickedUp = true;\n\n\t\t\t\t} else {\n\t\t\t\t\tped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(),\n\t\t\t\t\t\t((CBike*)veh)->m_bikeAnimType, enterDoor == DOOR_REAR_LEFT ? ANIM_BIKE_JUMPON_LHS : ANIM_BIKE_JUMPON_RHS);\n\t\t\t\t\tped->m_pVehicleAnim->SetFinishCallback(PedAnimGetInCB, ped);\n\t\t\t\t\t((CBike*)veh)->bIsBeingPickedUp = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (pedToDragOut) {\n\t\t\tpedToDragOut->SetBeingDraggedFromCar(veh, ped->m_vehDoor, false);\n\t\t\tif (pedToDragOut->IsGangMember())\n\t\t\t\tpedToDragOut->RegisterThreatWithGangPeds(ped);\n\n\t\t\tif (ped->m_nPedType == PEDTYPE_COP && pedToDragOut == FindPlayerPed() && veh->IsBike())\n\t\t\t\t((CCopPed*)ped)->m_bDragsPlayerFromCar = 1;\n\n\t\t\tif (pedToDragOut == veh->pDriver) {\n\t\t\t\tif (veh->pPassengers[0])\n\t\t\t\t\tveh->pPassengers[0]->SetBeingDraggedFromCar(veh, CAR_DOOR_LR, false);\n\t\t\t}\n\t\t}\n\t\treturn;\n\t}\n\n\tif (veh->IsDoorMissing(enterDoor) || veh->IsDoorFullyOpen(enterDoor)) {\n\n\t\tveh->AutoPilot.m_nCruiseSpeed = 0;\n\t\tif (ped->m_nPedState == PED_CARJACK || veh->m_nNumMaxPassengers == 0 && veh->pDriver && enterDoor == DOOR_FRONT_RIGHT) {\n\t\t\tped->PedAnimDoorOpenCB(nil, ped);\n\t\t\treturn;\n\t\t}\n\t\tif (enterDoor != DOOR_FRONT_LEFT && enterDoor != DOOR_REAR_LEFT) {\n\t\t\tif (itsVan) {\n\t\t\t\tped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_VAN, ANIM_STD_VAN_GET_IN_REAR_RHS);\n\t\t\t} else if (itsBus) {\n\t\t\t\tped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_COACH, ANIM_STD_COACH_GET_IN_RHS);\n\t\t\t} else if (itsLow) {\n\t\t\t\tped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_GET_IN_LO_RHS);\n\t\t\t} else {\n\t\t\t\tped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_GET_IN_RHS);\n\t\t\t}\n\t\t} else if (itsVan) {\n\t\t\tped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_VAN, ANIM_STD_VAN_GET_IN_REAR_LHS);\n\t\t} else if (itsBus) {\n\t\t\tped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_COACH, ANIM_STD_COACH_GET_IN_LHS);\n\t\t} else if (itsLow) {\n\t\t\tped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_GET_IN_LO_LHS);\n\t\t} else {\n\t\t\tped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_GET_IN_LHS);\n\t\t}\n\t\tped->m_pVehicleAnim->SetFinishCallback(PedAnimGetInCB, ped);\n\n\t} else if (veh->CanPedOpenLocks(ped)) {\n\n\t\tveh->AutoPilot.m_nCruiseSpeed = 0;\n\t\tif (enterDoor != DOOR_FRONT_LEFT && enterDoor != DOOR_REAR_LEFT) {\n\t\t\tif (itsVan) {\n\t\t\t\tped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_VAN, ANIM_STD_VAN_OPEN_DOOR_REAR_RHS);\n\t\t\t} else if (itsBus) {\n\t\t\t\tped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_COACH, ANIM_STD_COACH_OPEN_RHS);\n\t\t\t} else {\n\t\t\t\tped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_OPEN_DOOR_RHS);\n\t\t\t}\n\t\t} else if (itsVan) {\n\t\t\tped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_VAN, ANIM_STD_VAN_OPEN_DOOR_REAR_LHS);\n\t\t} else if (itsBus) {\n\t\t\tped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_COACH, ANIM_STD_COACH_OPEN_LHS);\n\t\t} else {\n\n\t\t\tif (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER && veh->pDriver) {\n\n\t\t\t\tif (!veh->bLowVehicle\n\t\t\t\t\t&& veh->pDriver->CharCreatedBy != MISSION_CHAR\n\t\t\t\t\t&& veh->pDriver->m_nPedState == PED_DRIVING) {\n\n\t\t\t\t\tped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_QUICKJACK);\n\t\t\t\t\tped->m_pVehicleAnim->SetFinishCallback(PedAnimGetInCB, ped);\n\n\t\t\t\t\tCPlayerPed *player = nil;\n\t\t\t\t\tCCopPed *cop = nil;\n\t\t\t\t\tveh->MakeNonDraggedPedsLeaveVehicle(veh->pDriver, ped, player, cop);\n\t\t\t\t\tif (player && cop) {\n\t\t\t\t\t\tcop->QuitEnteringCar();\n\t\t\t\t\t\tcop->SetArrestPlayer(player);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (player != veh->pDriver) {\n\t\t\t\t\t\tveh->pDriver->SetBeingDraggedFromCar(veh, ped->m_vehDoor, true);\n\t\t\t\t\t\tif (veh->pDriver->IsGangMember())\n\t\t\t\t\t\t\tveh->pDriver->RegisterThreatWithGangPeds(ped);\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (veh->IsOpenTopCar() && !veh->pDriver && ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER) {\n\t\t\t\tped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_JUMP_IN_LO_LHS);\n\t\t\t\tped->m_pVehicleAnim->SetFinishCallback(PedAnimGetInCB, ped);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_OPEN_DOOR_LHS);\n\t\t}\n\t\tped->m_pVehicleAnim->SetFinishCallback(PedAnimDoorOpenCB, ped);\n\n\t} else {\n\t\tif (enterDoor != DOOR_FRONT_LEFT && enterDoor != DOOR_REAR_LEFT)\n\t\t\tped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_CARDOOR_LOCKED_RHS);\n\t\telse\n\t\t\tped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_CARDOOR_LOCKED_LHS);\n\n\t\tped->bCancelEnteringCar = true;\n\t\tped->m_pVehicleAnim->SetFinishCallback(PedAnimDoorOpenCB, ped);\n\t}\n}\n\nvoid\nCPed::PedAnimDoorOpenCB(CAnimBlendAssociation* animAssoc, void* arg)\n{\n\tCPed* ped = (CPed*)arg;\n\n\tCVehicle* veh = ped->m_pMyVehicle;\n\n\tif (animAssoc)\n\t\tanimAssoc->blendDelta = -1000.0f;\n\n\tif (!ped->IsNotInWreckedVehicle())\n\t\treturn;\n\n\tif (!ped->EnteringCar()) {\n\t\tif(ped->m_nPedState != PED_DRIVING)\n\t\t\tped->QuitEnteringCar();\n\n\t\treturn;\n\t}\n\n\teDoors door;\n\tCPed *pedInSeat = nil;\n\tswitch (ped->m_vehDoor) {\n\t\tcase CAR_DOOR_RF:\n\t\t\tdoor = DOOR_FRONT_RIGHT;\n\t\t\tpedInSeat = veh->pPassengers[0];\n\t\t\tif (!veh->pPassengers[0] && ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER)\n\t\t\t\tpedInSeat = veh->pDriver;\n\t\t\tbreak;\n\t\tcase CAR_DOOR_RR:\n\t\t\tdoor = DOOR_REAR_RIGHT;\n\t\t\tpedInSeat = veh->pPassengers[2];\n\t\t\tbreak;\n\t\tcase CAR_DOOR_LF:\n\t\t\tdoor = DOOR_FRONT_LEFT;\n\t\t\tpedInSeat = veh->pDriver;\n\t\t\tif (veh->bIsBus && ped->m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER)\n\t\t\t\tpedInSeat = nil;\n\t\t\tbreak;\n\t\tcase CAR_DOOR_LR:\n\t\t\tdoor = DOOR_REAR_LEFT;\n\t\t\tpedInSeat = veh->pPassengers[1];\n\t\t\tbreak;\n\t\tdefault: assert(0);\n\t}\n\n\tif (ped->m_fHealth == 0.0f || CPad::GetPad(0)->ArePlayerControlsDisabled() && pedInSeat && pedInSeat->IsPlayer()) {\n\t\tped->QuitEnteringCar();\n\t\treturn;\n\t}\n\n\tbool isVan = veh->bIsVan;\n\tbool isBus = veh->bIsBus;\n\tbool isLow = veh->bLowVehicle;\n\tbool vehUpsideDown = veh->IsUpsideDown();\n\tif (ped->bCancelEnteringCar) {\n\t\tif (ped->IsPlayer()) {\n\t\t\tif (veh->pDriver) {\n\t\t\t\tif (veh->pDriver->m_nPedType == PEDTYPE_COP) {\n\t\t\t\t\tFindPlayerPed()->SetWantedLevelNoDrop(1);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n#ifdef CANCELLABLE_CAR_ENTER\n\t\tif (!veh->IsDoorMissing(door) && veh->CanPedOpenLocks(ped) && veh->IsCar()) {\n\t\t\t((CAutomobile*)veh)->Damage.SetDoorStatus(door, DOOR_STATUS_SWINGING);\n\t\t}\n#endif\n\t\tped->QuitEnteringCar();\n\t\tped->RestorePreviousObjective();\n\t\tped->bCancelEnteringCar = false;\n\t\treturn;\n\t}\n\tif (!veh->IsDoorMissing(door) && veh->IsCar()) {\n\t\t((CAutomobile*)veh)->Damage.SetDoorStatus(door, DOOR_STATUS_SWINGING);\n\t}\n\n\tif (veh->m_vecMoveSpeed.Magnitude() > 0.2f ||\n\t\tveh->IsCar() && veh->GetVehicleAppearance() == VEHICLE_APPEARANCE_HELI && ((CAutomobile*)veh)->m_nWheelsOnGround == 0) {\n\t\tped->QuitEnteringCar();\n\t\tif (ped->m_vehDoor != CAR_DOOR_LF && ped->m_vehDoor != CAR_DOOR_LR)\n\t\t\tped->SetFall(1000, ANIM_STD_HIGHIMPACT_LEFT, false);\n\t\telse\n\t\t\tped->SetFall(1000, ANIM_STD_HIGHIMPACT_RIGHT, false);\n\t\t\n\t\treturn;\n\t}\n\tveh->ProcessOpenDoor(ped->m_vehDoor, ANIM_STD_CAR_OPEN_DOOR_LHS, 1.0f);\n\n\tif (ped->m_vehDoor == CAR_DOOR_LF || ped->m_vehDoor == CAR_DOOR_RF)\n\t\tisVan = false;\n\n\tif (ped->m_nPedState != PED_CARJACK || isBus) {\n\n\t\tif (ped->m_vehDoor == CAR_DOOR_LF || ped->m_vehDoor == CAR_DOOR_LR) {\n\t\t\tif (veh->IsBike()) {\n\t\t\t\tped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ((CBike*)veh)->m_bikeAnimType, ANIM_BIKE_JUMPON_LHS);\n\t\t\t} else if (isVan) {\n\t\t\t\tped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_VAN, ANIM_STD_VAN_GET_IN_REAR_LHS);\n\t\t\t} else if (isBus) {\n\t\t\t\tped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_COACH, ANIM_STD_COACH_GET_IN_LHS);\n\t\t\t} else if (isLow) {\n\t\t\t\tped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_GET_IN_LO_LHS);\n\t\t\t} else {\n\t\t\t\tped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_GET_IN_LHS);\n\t\t\t}\n\t\t} else {\n\t\t\tif (veh->IsBike()) {\n\t\t\t\tped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ((CBike*)veh)->m_bikeAnimType, ANIM_BIKE_JUMPON_RHS);\n\t\t\t} else if (isVan) {\n\t\t\t\tped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_VAN, ANIM_STD_VAN_GET_IN_REAR_RHS);\n\t\t\t} else if (isBus) {\n\t\t\t\tped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_COACH, ANIM_STD_COACH_GET_IN_RHS);\n\t\t\t} else if (isLow) {\n\t\t\t\tped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_GET_IN_LO_RHS);\n\t\t\t} else {\n\t\t\t\tped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_GET_IN_RHS);\n\t\t\t}\n\n\t\t\tif (ped->m_vehDoor == CAR_DOOR_RF && pedInSeat && veh->IsCar())\n\t\t\t\tpedInSeat->SetObjective(OBJECTIVE_LEAVE_CAR, veh);\n\t\t}\n\t\t\n\t\tped->m_pVehicleAnim->SetFinishCallback(PedAnimGetInCB, ped);\n\t} else {\n\t\tCPed *pedToDragOut = nil;\n\t\tswitch (ped->m_vehDoor) {\n\t\t\tcase CAR_DOOR_RF: pedToDragOut = veh->pPassengers[0]; break;\n\t\t\tcase CAR_DOOR_RR: pedToDragOut = veh->pPassengers[2]; break;\n\t\t\tcase CAR_DOOR_LF: pedToDragOut = veh->pDriver; break;\n\t\t\tcase CAR_DOOR_LR: pedToDragOut = veh->pPassengers[1]; break;\n\t\t\tdefault: assert(0);\n\t\t}\n\n\t\tif (vehUpsideDown) {\n\t\t\tped->QuitEnteringCar();\n\t\t\tif (ped->m_nPedType == PEDTYPE_COP)\n\t\t\t\t((CCopPed*)ped)->SetArrestPlayer(ped->m_pedInObjective);\n\t\t}\n\n\t\tif (ped->m_vehDoor != CAR_DOOR_LF && ped->m_vehDoor != CAR_DOOR_LR) {\n\n\t\t\tif (pedToDragOut && !pedToDragOut->bDontDragMeOutCar) {\n\t\t\t\tif (pedToDragOut->m_nPedState != PED_DRIVING) {\n\t\t\t\t\tped->QuitEnteringCar();\n\t\t\t\t\tpedToDragOut = nil;\n\t\t\t\t} else {\n\t\t\t\t\tif (isLow)\n\t\t\t\t\t\tped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_PULL_OUT_PED_LO_RHS);\n\t\t\t\t\telse\n\t\t\t\t\t\tped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_PULL_OUT_PED_RHS);\n\n\t\t\t\t\tped->m_pVehicleAnim->SetFinishCallback(PedAnimPullPedOutCB, ped);\n\t\t\t\t}\n\t\t\t} else if (ped->m_nPedType == PEDTYPE_COP) {\n\t\t\t\tped->QuitEnteringCar();\n\t\t\t\tif (ped->m_pedInObjective && ped->m_pedInObjective->m_nPedState == PED_DRIVING) {\n\t\t\t\t\tveh->SetStatus(STATUS_PLAYER_DISABLED);\n\n\t\t\t\t\tif (ped->m_pedInObjective->IsPlayer()) {\n\t\t\t\t\t\t((CCopPed*)ped)->SetArrestPlayer(ped->m_pedInObjective);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tped->ClearObjective();\n\t\t\t\t\t\tped->SetWanderPath(CGeneral::GetRandomNumberInRange(0.f, 8.f));\n\t\t\t\t\t}\n\n\t\t\t\t} else if (!veh->IsDoorMissing(DOOR_FRONT_RIGHT)) {\n\t\t\t\t\t((CAutomobile*)veh)->Damage.SetDoorStatus(DOOR_FRONT_RIGHT, DOOR_STATUS_SWINGING);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (isLow)\n\t\t\t\t\tped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_GET_IN_LO_RHS);\n\t\t\t\telse\n\t\t\t\t\tped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_GET_IN_RHS);\n\n\t\t\t\tped->m_pVehicleAnim->SetFinishCallback(PedAnimGetInCB, ped);\n\t\t\t}\n\t\t} else if (pedToDragOut) {\n\n\t\t\tif (pedToDragOut->m_nPedState != PED_DRIVING || pedToDragOut->bDontDragMeOutCar) {\n\t\t\t\tped->QuitEnteringCar();\n\t\t\t\tpedToDragOut = nil;\n\t\t\t} else {\n\t\t\t\tif (isLow)\n\t\t\t\t\tped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_PULL_OUT_PED_LO_LHS);\n\t\t\t\telse\n\t\t\t\t\tped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_PULL_OUT_PED_LHS);\n\t\t\t\t\t\n\t\t\t\tped->m_pVehicleAnim->SetFinishCallback(PedAnimPullPedOutCB, ped);\n\t\t\t}\n\t\t} else {\n\t\t\tif (isLow)\n\t\t\t\tped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_GET_IN_LO_LHS);\n\t\t\telse\n\t\t\t\tped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_GET_IN_LHS);\n\n\t\t\tped->m_pVehicleAnim->SetFinishCallback(PedAnimGetInCB, ped);\n\t\t}\n\n\t\tif (pedToDragOut) {\n\t\t\tCPlayerPed* player = nil;\n\t\t\tCCopPed* cop = nil;\n\t\t\tveh->MakeNonDraggedPedsLeaveVehicle(pedToDragOut, ped, player, cop);\n\t\t\tif (player && cop) {\n\t\t\t\tcop->QuitEnteringCar();\n\t\t\t\tveh->SetStatus(STATUS_PLAYER_DISABLED);\n\t\t\t\tcop->SetArrestPlayer(player);\n\t\t\t}\n\n\t\t\tif (player != pedToDragOut) {\n\t\t\t\tpedToDragOut->SetBeingDraggedFromCar(veh, ped->m_vehDoor, false);\n\t\t\t\tif (pedToDragOut->IsGangMember())\n\t\t\t\t\tpedToDragOut->RegisterThreatWithGangPeds(ped);\n\t\t\t}\n\t\t}\n\t}\n\treturn;\n}\n\nvoid\nCPed::PedAnimPullPedOutCB(CAnimBlendAssociation* animAssoc, void* arg)\n{\n\tCPed* ped = (CPed*)arg;\n\n\tCVehicle* veh = ped->m_pMyVehicle;\n\tif (animAssoc)\n\t\tanimAssoc->blendDelta = -1000.0f;\n\n\tif (ped->EnteringCar()) {\n\t\tif (!ped->IsNotInWreckedVehicle())\n\t\t\treturn;\n\n#ifdef CANCELLABLE_CAR_ENTER\n\t\tif (ped->bCancelEnteringCar) {\n\t\t\tped->QuitEnteringCar();\n\t\t\tped->RestorePreviousObjective();\n\t\t\tped->bCancelEnteringCar = false;\n\t\t\treturn;\n\t\t}\n#endif\n\n\t\tbool isLow = !!veh->bLowVehicle;\n\n\t\tint padNo;\n\t\tif (ped->IsPlayer()) {\n\n\t\t\t// BUG? This will cause crash if m_nPedType is bigger then 1, there are only 2 pads\n\t\t\tswitch (ped->m_nPedType) {\n\t\t\t\tcase PEDTYPE_PLAYER1:\n\t\t\t\t\tpadNo = 0;\n\t\t\t\t\tbreak;\n\t\t\t\tcase PEDTYPE_PLAYER2:\n\t\t\t\t\tpadNo = 1;\n\t\t\t\t\tbreak;\n\t\t\t\tcase PEDTYPE_PLAYER3:\n\t\t\t\t\tpadNo = 2;\n\t\t\t\t\tbreak;\n\t\t\t\tcase PEDTYPE_PLAYER4:\n\t\t\t\t\tpadNo = 3;\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tCPad *pad = CPad::GetPad(padNo);\n\n\t\t\tif (!pad->ArePlayerControlsDisabled()) {\n\n\t\t\t\tif (pad->GetTarget()\n\t\t\t\t\t|| pad->NewState.LeftStickX\n\t\t\t\t\t|| pad->NewState.LeftStickY\n\t\t\t\t\t|| pad->NewState.DPadUp\n\t\t\t\t\t|| pad->NewState.DPadDown\n\t\t\t\t\t|| pad->NewState.DPadLeft\n\t\t\t\t\t|| pad->NewState.DPadRight) {\n\t\t\t\t\tped->QuitEnteringCar();\n\t\t\t\t\tped->RestorePreviousObjective();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER) {\n\t\t\tif (ped->m_vehDoor == CAR_DOOR_LF || ped->m_vehDoor == CAR_DOOR_LR) {\n\t\t\t\tif (veh->IsBike())\n\t\t\t\t\tped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ((CBike*)veh)->m_bikeAnimType, ANIM_BIKE_JUMPON_LHS);\n\t\t\t\telse if (isLow)\n\t\t\t\t\tped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_GET_IN_LO_LHS);\n\t\t\t\telse\n\t\t\t\t\tped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_GET_IN_LHS);\n\t\t\t} else {\n\t\t\t\tif (veh->IsBike())\n\t\t\t\t\tped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ((CBike*)veh)->m_bikeAnimType, ANIM_BIKE_JUMPON_RHS);\n\t\t\t\telse if (isLow)\n\t\t\t\t\tped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_GET_IN_LO_RHS);\n\t\t\t\telse\n\t\t\t\t\tped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_GET_IN_RHS);\n\t\t\t}\n\t\t\tped->m_pVehicleAnim->SetFinishCallback(PedAnimGetInCB, ped);\n\t\t} else {\n\t\t\tped->QuitEnteringCar();\n\t\t}\n\t} else if(ped->m_nPedState != PED_DRIVING) {\n\t\tped->QuitEnteringCar();\n\t}\n}\n\nvoid\nCPed::PedAnimGetInCB(CAnimBlendAssociation *animAssoc, void *arg)\n{\n\tCPed *ped = (CPed*) arg;\n\n\tCVehicle *veh = ped->m_pMyVehicle;\n\tif (animAssoc)\n\t\tanimAssoc->blendDelta = -1000.0f;\n\n\tif (!ped->IsNotInWreckedVehicle() || ped->DyingOrDead())\n\t\treturn;\n\n\tif (!ped->EnteringCar()) {\n\t\tif(ped->m_nPedState != PED_DRIVING)\n\t\t\tped->QuitEnteringCar();\n\t\treturn;\n\t}\n\n\tped->RemoveWeaponWhenEnteringVehicle();\n\tif (ped->IsPlayer() && ped->bGonnaKillTheCarJacker && ((CPlayerPed*)ped)->m_pArrestingCop) {\n\t\tPedSetInCarCB(nil, ped);\n\t\tped->m_nLastPedState = ped->m_nPedState;\n\t\tped->SetPedState(PED_ARRESTED);\n\t\tped->bGonnaKillTheCarJacker = false;\n\t\tif (veh) {\n\t\t\tveh->m_nNumGettingIn = 0;\n\t\t\tveh->m_nGettingInFlags = 0;\t\n\t\t\tveh->bIsHandbrakeOn = true;\n\t\t\tveh->SetStatus(STATUS_PLAYER_DISABLED);\n\t\t}\n\t\treturn;\n\t}\n\tif (ped->IsPlayer() && ped->m_vehDoor == CAR_DOOR_LF\n\t\t&& (Pads[0].GetAccelerate() >= 255.0f || Pads[0].GetBrake() >= 255.0f)\n\t\t&& veh->IsCar() && !veh->pDriver) {\n\n\t\tif (!animAssoc || animAssoc->animId != ANIM_STD_CAR_JUMP_IN_LO_LHS)\n\t\tif (((CAutomobile*)veh)->Damage.GetDoorStatus(DOOR_FRONT_LEFT) != DOOR_STATUS_MISSING)\n\t\t\t((CAutomobile*)veh)->Damage.SetDoorStatus(DOOR_FRONT_LEFT, DOOR_STATUS_SWINGING);\n\n\t\tPedSetInCarCB(nil, ped);\n\t\treturn;\n\t}\n\tif (veh->IsBike()) {\n\t\tped->PedSetInCarCB(nil, ped);\n\t\treturn;\n\t}\n\tbool isVan = !!veh->bIsVan;\n\tbool isBus = !!veh->bIsBus;\n\tbool isLow = !!veh->bLowVehicle;\n\teDoors enterDoor;\n\tswitch (ped->m_vehDoor) {\n\t\tcase CAR_DOOR_RF:\n\t\t\tisVan = false;\n\t\t\tenterDoor = DOOR_FRONT_RIGHT;\n\t\t\tbreak;\n\t\tcase CAR_DOOR_RR:\n\t\t\tenterDoor = DOOR_REAR_RIGHT;\n\t\t\tbreak;\n\t\tcase CAR_DOOR_LF:\n\t\t\tisVan = false;\n\t\t\tenterDoor = DOOR_FRONT_LEFT;\n\t\t\tbreak;\n\t\tcase CAR_DOOR_LR:\n\t\t\tenterDoor = DOOR_REAR_LEFT;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\tbool doorClosed = true;\n\tif (veh->IsOpenTopCar() && enterDoor == DOOR_FRONT_LEFT && veh->IsDoorClosed(DOOR_FRONT_LEFT)) {\n\t\tdoorClosed = false;\n\n\t} else if (!veh->IsDoorMissing(enterDoor)) {\n\t\tif (veh->IsCar())\n\t\t\t((CAutomobile*)veh)->Damage.SetDoorStatus(enterDoor, DOOR_STATUS_SWINGING);\n\t}\n\n\tCPed *driver = veh->pDriver;\n\tif (driver && (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER || ped->m_nPedState == PED_CARJACK)) {\n\t\tif (veh->bIsBus) {\n\t\t\tdriver->SetObjective(OBJECTIVE_LEAVE_CAR, veh);\n\t\t\tif (driver->IsPlayer()) {\n\t\t\t\tveh->bIsHandbrakeOn = true;\n\t\t\t\tveh->SetStatus(STATUS_PLAYER_DISABLED);\n\t\t\t}\n\t\t\tdriver->bBusJacked = true;\n\t\t\tveh->bIsBeingCarJacked = false;\n\t\t\tPedSetInCarCB(nil, ped);\n\t\t\tif (ped->m_nPedType == PEDTYPE_COP\n\t\t\t\t|| ped->m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT\n\t\t\t\t|| ped->m_objective == OBJECTIVE_KILL_CHAR_ANY_MEANS) {\n\t\t\t\tped->SetObjective(OBJECTIVE_LEAVE_CAR, veh);\n\t\t\t}\n\t\t\tped->m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + 400;\n\t\t\treturn;\n\t\t}\n\t\tif (driver != ped && ped->m_vehDoor != CAR_DOOR_LF) {\n\t\t\tif (!driver->IsPlayer()) {\n\t\t\t\tdriver->bUsePedNodeSeek = true;\n\t\t\t\tdriver->m_pLastPathNode = nil;\n\t\t\t\tif (driver->m_pedStats->m_temper <= driver->m_pedStats->m_fear\n\t\t\t\t\t|| driver->CharCreatedBy == MISSION_CHAR\n\t\t\t\t\t|| veh->VehicleCreatedBy == MISSION_VEHICLE) {\n\t\t\t\t\tdriver->bFleeAfterExitingCar = true;\n\t\t\t\t} else {\n\t\t\t\t\tdriver->bGonnaKillTheCarJacker = true;\n\t\t\t\t\tveh->pDriver->SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, ped);\n\n\t\t\t\t\tif (veh->pDriver->m_nPedType == PEDTYPE_COP && ped->IsPlayer()) {\n\t\t\t\t\t\tFindPlayerPed()->SetWantedLevelNoDrop(1);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ((ped->m_nPedType != PEDTYPE_EMERGENCY || veh->pDriver->m_nPedType != PEDTYPE_EMERGENCY)\n\t\t\t\t&& (ped->m_nPedType != PEDTYPE_COP || veh->pDriver->m_nPedType != PEDTYPE_COP)) {\n\t\t\t\tveh->pDriver->SetObjective(OBJECTIVE_LEAVE_CAR, veh);\n\t\t\t\tveh->pDriver->Say(SOUND_PED_CAR_JACKED);\n\t\t\t\tveh->pDriver->SetRadioStation();\n\t\t\t\tif (veh->m_nDoorLock == CARLOCK_UNLOCKED)\n\t\t\t\t\tped->Say(SOUND_PED_CAR_JACKING);\n\n\t\t\t} else {\n\t\t\t\tped->m_objective = OBJECTIVE_ENTER_CAR_AS_PASSENGER;\n\t\t\t}\n\t\t}\n\t}\n\tif (veh->IsDoorMissing(enterDoor) || !doorClosed || isBus) {\n\t\tPedAnimDoorCloseCB(nil, ped);\n\t} else {\n\t\tif (enterDoor != DOOR_FRONT_LEFT && enterDoor != DOOR_REAR_LEFT) {\n\t\t\tif (isVan) {\n\t\t\t\tped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_VAN, ANIM_STD_VAN_CLOSE_DOOR_REAR_RHS);\n\t\t\t} else if (isLow) {\n\t\t\t\tped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_CLOSE_DOOR_LO_RHS);\n\t\t\t} else {\n\t\t\t\tped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_CLOSE_DOOR_RHS);\n\t\t\t}\n\t\t} else if (isVan) {\n\t\t\tped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_VAN, ANIM_STD_VAN_CLOSE_DOOR_REAR_LHS);\n\t\t} else if (isLow) {\n\t\t\tped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_CLOSE_DOOR_LO_LHS);\n\t\t} else {\n\t\t\tped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_CLOSE_DOOR_LHS);\n\t\t}\n\t\tped->m_pVehicleAnim->SetFinishCallback(PedAnimDoorCloseCB, ped);\n\t}\n}\n\nvoid\nCPed::PedShuffle(void)\n{\n\tif (m_pMyVehicle->pPassengers[0] == this) {\n\t\tCPed *driver = m_pMyVehicle->pDriver;\n\t\tif (!driver || driver->m_objective == OBJECTIVE_LEAVE_CAR) {\n\t\t\tm_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, m_pMyVehicle->bLowVehicle ? ANIM_STD_CAR_SHUFFLE_LO_RHS : ANIM_STD_CAR_SHUFFLE_RHS);\n\t\t\tm_objective = OBJECTIVE_ENTER_CAR_AS_DRIVER;\n\t\t\tm_pMyVehicle->RemovePassenger(this);\n\t\t\tbInVehicle = false;\n\t\t\tm_pVehicleAnim->SetFinishCallback(PedSetInCarCB, this);\n\t\t}\n\t}\n}\n\nvoid\nCPed::PedAnimDoorCloseCB(CAnimBlendAssociation *animAssoc, void *arg)\n{\n\tCPed *ped = (CPed*)arg;\n\n\tCAutomobile *veh = (CAutomobile*)(ped->m_pMyVehicle);\n\t\n\tif (!ped->IsNotInWreckedVehicle() || ped->DyingOrDead())\n\t\treturn;\n\n\tif (ped->EnteringCar()) {\n\t\tbool isLow = !!veh->bLowVehicle;\n\n\t\tif (!veh->bIsBus)\n\t\t\tveh->ProcessOpenDoor(ped->m_vehDoor, ANIM_STD_CAR_CLOSE_DOOR_LHS, 1.0f);\n\n\t\teDoors door;\n\t\tswitch (ped->m_vehDoor) {\n\t\t\tcase CAR_DOOR_RF: door = DOOR_FRONT_RIGHT; break;\n\t\t\tcase CAR_DOOR_RR: door = DOOR_REAR_RIGHT; break;\n\t\t\tcase CAR_DOOR_LF: door = DOOR_FRONT_LEFT; break;\n\t\t\tcase CAR_DOOR_LR: door = DOOR_REAR_LEFT; break;\n\t\t\tdefault: assert(0);\n\t\t}\n\n\t\tif (veh->Damage.GetDoorStatus(door) == DOOR_STATUS_SWINGING)\n\t\t\tveh->Damage.SetDoorStatus(door, DOOR_STATUS_OK);\n\n\t\tif (door == DOOR_FRONT_LEFT || ped->m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER || veh->bIsBus || veh->m_nNumMaxPassengers == 0) {\n\t\t\tPedSetInCarCB(nil, ped);\n\t\t} else if (ped->m_vehDoor == CAR_DOOR_RF\n\t\t\t\t&& (veh->m_nGettingInFlags & CAR_DOOR_FLAG_LF ||\n\t\t\t\t\t(veh->pDriver != nil && \n\t\t\t\t\t\t(veh->pDriver->m_objective != OBJECTIVE_LEAVE_CAR\n\t\t\t\t\t\t\t&& veh->pDriver->m_objective != OBJECTIVE_LEAVE_CAR_AND_DIE\n\t\t\t\t\t\t\t|| !veh->IsRoomForPedToLeaveCar(CAR_DOOR_LF, nil))))) {\n\n\t\t\tif (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER || ped->m_nPedState == PED_CARJACK)\n\t\t\t\tveh->bIsBeingCarJacked = false;\n\n\t\t\tped->m_objective = OBJECTIVE_ENTER_CAR_AS_PASSENGER;\n\t\t\tPedSetInCarCB(nil, ped);\n\n\t\t\tped->SetObjective(OBJECTIVE_LEAVE_CAR, veh);\n\t\t\tif (!ped->IsPlayer())\n\t\t\t\tped->bFleeAfterExitingCar = true;\n\n\t\t\tped->bUsePedNodeSeek = true;\n\t\t\tped->m_pNextPathNode = nil;\n\n\t\t} else {\n\t\t\tif (animAssoc)\n\t\t\t\tanimAssoc->blendDelta = -1000.0f;\n\n\t\t\tif (isLow)\n\t\t\t\tped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_SHUFFLE_LO_RHS);\n\t\t\telse\n\t\t\t\tped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_SHUFFLE_RHS);\n\n\t\t\tped->m_pVehicleAnim->SetFinishCallback(PedSetInCarCB, ped);\n\t\t}\n\t} else if (ped->m_nPedState != PED_DRIVING) {\n\t\tped->QuitEnteringCar();\n\t}\n}\n\nvoid\nCPed::PedAnimShuffleCB(CAnimBlendAssociation* assoc, void* arg)\n{\n\tCPed *ped = (CPed*)arg;\n\tif (ped->EnteringCar()) {\n\t\tPedSetInCarCB(nil, ped);\n\t} else if (ped->m_nPedState != PED_DRIVING) {\n\t\tped->QuitEnteringCar();\n\t}\n}\n\nvoid\nCPed::SetFormation(eFormation type)\n{\n\t// FIX: Formations in GetFormationPosition were in range 1-8, whereas in here it's 0-7.\n\t//      To not change the behaviour, range in here tweaked by 1 with the use of enum.\n\n\tswitch (m_pedFormation) {\n\t\tcase FORMATION_REAR:\n\t\tcase FORMATION_REAR_LEFT:\n\t\tcase FORMATION_REAR_RIGHT:\n\t\tcase FORMATION_FRONT_LEFT:\n\t\tcase FORMATION_FRONT_RIGHT:\n\t\tcase FORMATION_LEFT:\n\t\tcase FORMATION_RIGHT:\n\t\tcase FORMATION_FRONT:\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tError(\"Unknown formation type, PedAI.cpp\");\n\t\t\tbreak;\n\t}\n\tm_pedFormation = type;\n}\n\nCVector\nCPed::GetFormationPosition(void)\n{\n\tif (!m_pedInObjective)\n\t\treturn GetPosition();\n\n\tif (m_pedInObjective->m_nPedState == PED_DEAD) {\n\t\tif (!m_pedInObjective->m_pedInObjective) {\n\t\t\tm_pedInObjective = nil;\n\t\t\treturn GetPosition();\n\t\t}\n\t\tm_pedInObjective = m_pedInObjective->m_pedInObjective;\n\t}\n\n\tCVector formationOffset;\n\tfloat offset = CGeneral::GetRandomNumberInRange(1.f, 1.25f) * 1.75f;\n\tswitch (m_pedFormation) {\n\t\tcase FORMATION_REAR:\n\t\t\tformationOffset = CVector(0.0f, -offset, 0.0f);\n\t\t\tbreak;\n\t\tcase FORMATION_REAR_LEFT:\n\t\t\tformationOffset = CVector(-offset, -offset, 0.0f);\n\t\t\tbreak;\n\t\tcase FORMATION_REAR_RIGHT:\n\t\t\tformationOffset = CVector(offset, -offset, 0.0f);\n\t\t\tbreak;\n\t\tcase FORMATION_FRONT_LEFT:\n\t\t\tformationOffset = CVector(-offset, offset, 0.0f);\n\t\t\tbreak;\n\t\tcase FORMATION_FRONT_RIGHT:\n\t\t\tformationOffset = CVector(offset, offset, 0.0f);\n\t\t\tbreak;\n\t\tcase FORMATION_LEFT:\n\t\t\tformationOffset = CVector(-offset, 0.0f, 0.0f);\n\t\t\tbreak;\n\t\tcase FORMATION_RIGHT:\n\t\t\tformationOffset = CVector(offset, 0.0f, 0.0f);\n\t\t\tbreak;\n\t\tcase FORMATION_FRONT:\n\t\t\tformationOffset = CVector(0.0f, offset, 0.0f);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tformationOffset = CVector(0.0f, 0.0f, 0.0f);\n\t\t\tbreak;\n\t}\n\treturn m_pedInObjective->GetMatrix() * formationOffset;\n}\n\nvoid\nCPed::PedAnimStepOutCarCB(CAnimBlendAssociation* animAssoc, void* arg)\n{\n\tCPed* ped = (CPed*)arg;\n\n\tCVehicle* veh = ped->m_pMyVehicle;\n\tif (animAssoc) {\n\t\tif ((animAssoc->animId == ANIM_STD_ROLLOUT_LHS || animAssoc->animId == ANIM_STD_ROLLOUT_RHS) && ped && ped->m_nPedState == PED_FALL) {\n\t\t\tped->RestoreHeadingRate();\n\t\t\treturn;\n\t\t}\n\t\tanimAssoc->blendDelta = -1000.0f;\n\t\tif (animAssoc->animId == ANIM_BIKE_GETOFF_BACK)\n\t\t\tped->RestoreHeadingRate();\n\t}\n\n\tif (!veh) {\n\t\tPedSetOutCarCB(nil, ped);\n\t\treturn;\n\t}\n\tCVector posForZ = ped->GetPosition();\n\tCPedPlacement::FindZCoorForPed(&posForZ);\n\tif (ped->GetPosition().z - 0.5f > posForZ.z) {\n\t\tPedSetOutCarCB(nil, ped);\n\t\treturn;\n\t}\n\n\tveh->m_nStaticFrames = 0;\n\tveh->m_vecMoveSpeed += CVector(0.001f, 0.001f, 0.001f);\n\tveh->m_vecTurnSpeed += CVector(0.001f, 0.001f, 0.001f);\n\tif (!veh->bIsBus)\n\t\tveh->ProcessOpenDoor(ped->m_vehDoor, ANIM_STD_GETOUT_LHS, 1.0f);\n\n\t/* \n\t// Duplicate and only in PC for some reason\n\tif (!veh) {\n\t\tPedSetOutCarCB(nil, ped);\n\t\treturn;\n\t}\n\t*/\n\teDoors door;\n\tswitch (ped->m_vehDoor) {\n\t\tcase CAR_DOOR_RF:\n\t\t\tdoor = DOOR_FRONT_RIGHT;\n\t\t\tbreak;\n\t\tcase CAR_DOOR_RR:\n\t\t\tdoor = DOOR_REAR_RIGHT;\n\t\t\tbreak;\n\t\tcase CAR_DOOR_LF:\n\t\t\tdoor = DOOR_FRONT_LEFT;\n\t\t\tbreak;\n\t\tcase CAR_DOOR_LR:\n\t\t\tdoor = DOOR_REAR_LEFT;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\tbool closeDoor = !veh->IsDoorMissing(door);\n\n\tint padNo;\n\tif (ped->IsPlayer()) {\n\n\t\t// BUG? This will cause crash if m_nPedType is bigger then 1, there are only 2 pads\n\t\tswitch (ped->m_nPedType) {\n\t\t\tcase PEDTYPE_PLAYER1:\n\t\t\t\tpadNo = 0;\n\t\t\t\tbreak;\n\t\t\tcase PEDTYPE_PLAYER2:\n\t\t\t\tpadNo = 1;\n\t\t\t\tbreak;\n\t\t\tcase PEDTYPE_PLAYER3:\n\t\t\t\tpadNo = 2;\n\t\t\t\tbreak;\n\t\t\tcase PEDTYPE_PLAYER4:\n\t\t\t\tpadNo = 3;\n\t\t\t\tbreak;\n\t\t}\n\t\tCPad* pad = CPad::GetPad(padNo);\n\t\tbool engineIsIntact = veh->IsCar() && ((CAutomobile*)veh)->Damage.GetEngineStatus() >= 225;\n\t\tif (!pad->ArePlayerControlsDisabled() && veh->m_nDoorLock != CARLOCK_FORCE_SHUT_DOORS\n\t\t\t&& (pad->GetTarget()\n\t\t\t\t|| pad->NewState.LeftStickX\n\t\t\t\t|| pad->NewState.LeftStickY\n\t\t\t\t|| pad->NewState.DPadUp\n\t\t\t\t|| pad->NewState.DPadDown\n\t\t\t\t|| pad->NewState.DPadLeft\n\t\t\t\t|| pad->NewState.DPadRight)\n\t\t\t|| veh->bIsBus\n\t\t\t|| veh->m_pCarFire\n\t\t\t|| engineIsIntact) {\n\t\t\tcloseDoor = false;\n\t\t}\n\t}\n\n\tif (ped->m_objective == OBJECTIVE_LEAVE_CAR_AND_DIE)\n\t\tcloseDoor = false;\n\n\tif (!closeDoor) {\n\t\tif (!veh->IsDoorMissing(door) && !veh->bIsBus) {\n\t\t\t((CAutomobile*)veh)->Damage.SetDoorStatus(door, DOOR_STATUS_SWINGING);\n\t\t}\n\t\tPedSetOutCarCB(nil, ped);\n\t\treturn;\n\t}\n\n\tif (ped->bFleeAfterExitingCar || ped->bGonnaKillTheCarJacker) {\n#ifdef FIX_BUGS\n\t\tif (!veh->IsDoorMissing(door))\n\t\t\t((CAutomobile*)veh)->Damage.SetDoorStatus(door, DOOR_STATUS_SWINGING);\n\t\tPedSetOutCarCB(nil, ped);\n\t\treturn;\n#else\n\t\tif (!veh->IsDoorMissing(door))\n\t\t\t((CAutomobile*)veh)->Damage.SetDoorStatus(DOOR_FRONT_LEFT, DOOR_STATUS_SWINGING);\n#endif\n\t} else {\n\t\tswitch (door) {\n\t\t\tcase DOOR_FRONT_LEFT:\n\t\t\t\tped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_CLOSE_LHS);\n\t\t\t\tbreak;\n\t\t\tcase DOOR_FRONT_RIGHT:\n\t\t\t\tped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_CLOSE_RHS);\n\t\t\t\tbreak;\n\t\t\tcase DOOR_REAR_LEFT:\n\t\t\t\tped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_CLOSE_LHS);\n\t\t\t\tbreak;\n\t\t\tcase DOOR_REAR_RIGHT:\n\t\t\t\tped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_CLOSE_RHS);\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tif (ped->m_pVehicleAnim)\n\t\tped->m_pVehicleAnim->SetFinishCallback(PedSetOutCarCB, ped);\n\treturn;\n}\n\nvoid\nCPed::LineUpPedWithCar(PedLineUpPhase phase)\n{\n\tbool vehIsUpsideDown = false;\n\tbool stillGettingInOut = false;\n\tint vehAnim;\n\tfloat seatPosMult = 0.0f;\n\tfloat currentZ;\n\tfloat adjustedTimeStep;\n\tCVector autoZPos;\n\n\tif (CReplay::IsPlayingBack())\n\t\treturn;\n\n\tif (!bChangedSeat && phase != LINE_UP_TO_CAR_2) {\n\t\tif (m_pMyVehicle->IsBike()) {\n\t\t\tif (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_BIKE_RIDE) ||\n\t\t\t\tRpAnimBlendClumpGetAssociation(GetClump(), ANIM_BIKE_RIDE_P)) {\n\t\t\t\tSetPedPositionInCar();\n\t\t\t\treturn;\n\t\t\t}\n\t\t} else {\n\t\t\tif (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_CAR_SIT)) {\n\t\t\t\tSetPedPositionInCar();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_CAR_SIT_LO)) {\n\t\t\t\tSetPedPositionInCar();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_CAR_SIT_P)) {\n\t\t\t\tSetPedPositionInCar();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_CAR_SIT_P_LO)) {\n\t\t\t\tSetPedPositionInCar();\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\tbChangedSeat = true;\n\t}\n\tif (phase == LINE_UP_TO_CAR_FALL) {\n\t\tSetPedPositionInCar();\n\t\tautoZPos = GetPosition();\n\t\tCPedPlacement::FindZCoorForPed(&autoZPos);\n\t\tif (m_pVehicleAnim && (m_pVehicleAnim->animId == ANIM_STD_ROLLOUT_LHS || m_pVehicleAnim->animId == ANIM_STD_ROLLOUT_RHS)\n\t\t\t&& autoZPos.z > GetPosition().z) {\n\t\t\tm_matrix.GetPosition().z = autoZPos.z;\n\t\t}\n\t\tif (m_pVehicleAnim && m_pVehicleAnim->animId == ANIM_BIKE_HIT) {\n\t\t\tif (autoZPos.z > GetPosition().z)\n\t\t\t\tm_matrix.GetPosition().z += m_pVehicleAnim->GetProgress() * (autoZPos.z - GetPosition().z);\n\n\t\t} else if (m_pVehicleAnim) {\n\t\t\tif (m_pVehicleAnim->animId == ANIM_BIKE_GETOFF_BACK) {\n\t\t\t\tif (autoZPos.z > GetPosition().z) {\n\t\t\t\t\tm_matrix.GetPosition().z += (m_pVehicleAnim->currentTime * (20.f / 7.f)) * (autoZPos.z - GetPosition().z);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn;\n\t}\n\tif (phase == LINE_UP_TO_CAR_START) {\n\t\tm_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);\n\t}\n\tCVehicle *veh = m_pMyVehicle;\n\n\t// Not quite right, IsUpsideDown func. checks for <= -0.9f.\n\tif (veh->GetUp().z <= -0.8f)\n\t\tvehIsUpsideDown = true;\n\n\tif (m_vehDoor == CAR_DOOR_RF || m_vehDoor == CAR_DOOR_RR) {\n\t\tif (vehIsUpsideDown) {\n\t\t\tm_fRotationDest = -PI + veh->GetForward().Heading();\n\t\t} else if (veh->bIsBus) {\n\t\t\tm_fRotationDest = 0.5f * PI + veh->GetForward().Heading();\n\t\t} else {\n\t\t\tm_fRotationDest = veh->GetForward().Heading();\n\t\t}\n\t} else if (m_vehDoor == CAR_DOOR_LF || m_vehDoor == CAR_DOOR_LR) {\n\t\tif (vehIsUpsideDown) {\n\t\t\tm_fRotationDest = veh->GetForward().Heading();\n\t\t} else if (veh->bIsBus) {\n\t\t\tm_fRotationDest = -0.5f * PI + veh->GetForward().Heading();\n\t\t} else {\n\t\t\tm_fRotationDest = veh->GetForward().Heading();\n\t\t}\n\t} else {\n\t\t// I don't know will this part ever run(maybe boats?), but the game also handles that. I don't know is it intentional.\n\n\t\tif (vehIsUpsideDown) {\n\t\t\tm_fRotationDest = veh->GetForward().Heading();\n\t\t} else if (veh->bIsBus) {\n\t\t\tm_fRotationDest = 0.5f * PI + veh->GetForward().Heading();\n\t\t} else if (m_vehDoor == CAR_WINDSCREEN) {\n\t\t\tm_fRotationDest = veh->GetForward().Heading() + PI;\n\t\t} else {\n\t\t\tm_fRotationDest = veh->GetForward().Heading();\n\t\t}\n\t}\n\n\tbool multExtractedFromAnim = false;\n\tbool multExtractedFromAnimBus = false;\n\tfloat zBlend;\n\tif (m_pVehicleAnim) {\n\t\tvehAnim = m_pVehicleAnim->animId;\n\n\t\tswitch (vehAnim) {\n\t\t\tcase ANIM_STD_JACKEDCAR_RHS:\n\t\t\tcase ANIM_STD_JACKEDCAR_LO_RHS:\n\t\t\tcase ANIM_STD_JACKEDCAR_LHS:\n\t\t\tcase ANIM_STD_JACKEDCAR_LO_LHS:\n\t\t\tcase ANIM_STD_VAN_GET_IN_REAR_LHS:\n\t\t\tcase ANIM_STD_VAN_GET_IN_REAR_RHS:\n\t\t\t\tmultExtractedFromAnim = true;\n\t\t\t\tzBlend = Max(m_pVehicleAnim->GetProgress() - 0.3f, 0.0f) / (1.0f - 0.3f);\n\t\t\t\t// fall through\n\n\t\t\tcase ANIM_STD_QUICKJACKED:\n\t\t\tcase ANIM_STD_GETOUT_LHS:\n\t\t\tcase ANIM_STD_GETOUT_LO_LHS:\n\t\t\tcase ANIM_STD_GETOUT_RHS:\n\t\t\tcase ANIM_STD_GETOUT_LO_RHS:\n\n\t\t\t\tif (!multExtractedFromAnim) {\n\t\t\t\t\tmultExtractedFromAnim = true;\n\t\t\t\t\tzBlend = Max(m_pVehicleAnim->GetProgress() - 0.5f, 0.0f) / (1.0f - 0.5f);\n\t\t\t\t}\n\t\t\t\t// fall through\n\n\t\t\tcase ANIM_STD_CRAWLOUT_LHS:\n\t\t\tcase ANIM_STD_CRAWLOUT_RHS:\n\t\t\tcase ANIM_STD_VAN_GET_OUT_REAR_LHS:\n\t\t\tcase ANIM_STD_VAN_GET_OUT_REAR_RHS:\n\t\t\tcase ANIM_BIKE_GETOFF_LHS:\n\t\t\tcase ANIM_BIKE_GETOFF_RHS:\n\t\t\t\tseatPosMult = m_pVehicleAnim->GetProgress();\n\t\t\t\tbreak;\n\t\t\tcase ANIM_STD_CAR_GET_IN_RHS:\n\t\t\tcase ANIM_STD_CAR_GET_IN_LHS:\n\t\t\t\tif (veh && veh->IsCar() && veh->bIsBus) {\n\t\t\t\t\tmultExtractedFromAnimBus = true;\n\t\t\t\t\tzBlend = Min(m_pVehicleAnim->GetProgress(), 0.5f) / 0.5f;\n\t\t\t\t}\n\t\t\t\t// fall through\n\n\t\t\tcase ANIM_STD_QUICKJACK:\n\t\t\tcase ANIM_STD_CAR_GET_IN_LO_LHS:\n\t\t\tcase ANIM_STD_CAR_GET_IN_LO_RHS:\n\t\t\tcase ANIM_STD_BOAT_DRIVE:\n\t\t\t\tseatPosMult = m_pVehicleAnim->GetTimeLeft() / m_pVehicleAnim->hierarchy->totalLength;\n\t\t\t\tbreak;\n\t\t\tcase ANIM_STD_CAR_CLOSE_DOOR_LHS:\n\t\t\tcase ANIM_STD_CAR_CLOSE_DOOR_LO_LHS:\n\t\t\tcase ANIM_STD_CAR_CLOSE_DOOR_RHS:\n\t\t\tcase ANIM_STD_CAR_CLOSE_DOOR_LO_RHS:\n\t\t\tcase ANIM_STD_CAR_SHUFFLE_RHS:\n\t\t\tcase ANIM_STD_CAR_SHUFFLE_LO_RHS:\n\t\t\t\tseatPosMult = 0.0f;\n\t\t\t\tbreak;\n\t\t\tcase ANIM_STD_CAR_JUMP_IN_LO_LHS:\n\t\t\t{\n\t\t\t\tfloat animLength = m_pVehicleAnim->hierarchy->totalLength;\n\t\t\t\tseatPosMult = Max(0.0f, 0.5f * animLength - m_pVehicleAnim->currentTime) / animLength;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase ANIM_STD_CAR_CLOSE_LHS:\n\t\t\tcase ANIM_STD_CAR_CLOSE_RHS:\n\t\t\tcase ANIM_STD_COACH_OPEN_LHS:\n\t\t\tcase ANIM_STD_COACH_OPEN_RHS:\n\t\t\tcase ANIM_STD_COACH_GET_IN_LHS:\n\t\t\tcase ANIM_STD_COACH_GET_IN_RHS:\n\t\t\tcase ANIM_STD_COACH_GET_OUT_LHS:\n\t\t\t\tseatPosMult = 1.0f;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tif (veh->IsBike()) {\n\t\t\t\t\tseatPosMult = 0.0f;\n\t\t\t\t} else {\n\t\t\t\t\tif (bInVehicle)\n\t\t\t\t\t\tseatPosMult = 0.0f;\n\t\t\t\t\telse\n\t\t\t\t\t\tseatPosMult = 1.0f;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\t} else {\n\t\tif (veh->IsBike()) {\n\t\t\tseatPosMult = 0.0f;\n\t\t} else {\n\t\t\tif (bInVehicle)\n\t\t\t\tseatPosMult = 0.0f;\n\t\t\telse\n\t\t\t\tseatPosMult = 1.0f;\n\t\t}\n\t}\n\n\tCVector neededPos;\n\n\tif (phase == LINE_UP_TO_CAR_2) {\n\t\tneededPos = GetPosition();\n\t} else {\n\t\tneededPos = GetPositionToOpenCarDoor(veh, m_vehDoor, seatPosMult);\n\t}\n\n\tautoZPos = neededPos;\n\n\tif (veh->bIsInWater) {\n\t\tif (veh->m_vehType == VEHICLE_TYPE_BOAT && veh->IsUpsideDown())\n\t\t\tautoZPos.z += 1.0f;\n\t} else {\n\t\tCPedPlacement::FindZCoorForPed(&autoZPos);\n\t}\n\n\tif (phase == LINE_UP_TO_CAR_END || phase == LINE_UP_TO_CAR_2) {\n\t\tneededPos.z = GetPosition().z;\n\n\t\t// Getting out\n\t\tif (!veh->bIsBus || (veh->bIsBus && vehIsUpsideDown)) {\n\t\t\tfloat nextZSpeed = m_vecMoveSpeed.z - GRAVITY * CTimer::GetTimeStep();\n\n\t\t\t// If we're not in ground at next step, apply animation\n\t\t\tif (neededPos.z + nextZSpeed >= autoZPos.z) {\n\t\t\t\tm_vecMoveSpeed.z = nextZSpeed;\n\t\t\t\tApplyMoveSpeed();\n\t\t\t\t// Removing below line breaks the animation\n\t\t\t\tneededPos.z = GetPosition().z;\n\t\t\t} else {\n\t\t\t\tneededPos.z = autoZPos.z;\n\t\t\t\tm_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);\n\t\t\t}\n\t\t}\n\t}\n\n\tif (autoZPos.z > neededPos.z) {\n\t\tvehAnim = m_pVehicleAnim->animId;\n\t\tif (veh->IsBike() && (m_pVehicleAnim && vehAnim != ANIM_BIKE_KICK)) {\n\t\t\tfloat zBlend;\n\t\t\tif (vehAnim != ANIM_BIKE_GETOFF_LHS && vehAnim != ANIM_BIKE_GETOFF_RHS) {\n\t\t\t\tif (vehAnim != ANIM_BIKE_JUMPON_LHS && vehAnim != ANIM_BIKE_JUMPON_RHS) {\n\t\t\t\t\tzBlend = 0.0f;\n\t\t\t\t} else {\n\t\t\t\t\tfloat animLength = m_pVehicleAnim->hierarchy->totalLength;\n\t\t\t\t\tzBlend = Min(1.0f, 2.0f * m_pVehicleAnim->currentTime / animLength);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tzBlend = 1.0f - seatPosMult;\n\t\t\t}\n\t\t\tfloat curZ = veh->GetPosition().z + FEET_OFFSET;\n\t\t\tneededPos.z = ((curZ - autoZPos.z) - veh->GetHeightAboveRoad()) * zBlend + autoZPos.z;\n\t\t} else if (multExtractedFromAnim) {\n\t\t\tneededPos.z += (autoZPos.z - neededPos.z) * zBlend;\n\t\t} else {\n\t\t\tcurrentZ = GetPosition().z;\n\t\t\tif (m_pVehicleAnim && vehAnim != ANIM_STD_VAN_GET_IN_REAR_LHS && vehAnim != ANIM_STD_VAN_CLOSE_DOOR_REAR_LHS && vehAnim != ANIM_STD_VAN_CLOSE_DOOR_REAR_RHS && vehAnim != ANIM_STD_VAN_GET_IN_REAR_RHS) {\n\t\t\t\tneededPos.z = autoZPos.z;\n\t\t\t\tm_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);\n\t\t\t} else if (neededPos.z < currentZ && m_pVehicleAnim && vehAnim != ANIM_STD_VAN_CLOSE_DOOR_REAR_LHS && vehAnim != ANIM_STD_VAN_CLOSE_DOOR_REAR_RHS) {\n\t\t\t\tadjustedTimeStep = Max(m_pVehicleAnim->timeStep, 0.1f);\n\n\t\t\t\t// Smoothly change ped position\n\t\t\t\tneededPos.z = currentZ - (currentZ - neededPos.z) / (m_pVehicleAnim->GetTimeLeft() / adjustedTimeStep);\n\t\t\t}\n\t\t}\n\t} else {\n\t\t// We may need to raise up the ped\n\t\tif (phase == LINE_UP_TO_CAR_START) {\n\t\t\tcurrentZ = GetPosition().z;\n\n\t\t\tif (neededPos.z > currentZ) {\n\t\t\t\tif (multExtractedFromAnimBus) {\n\t\t\t\t\tneededPos.z = (neededPos.z - currentZ) * zBlend + currentZ;\n\t\t\t\t} else {\n\t\t\t\t\tif (m_pVehicleAnim &&\n\t\t\t\t\t\t(vehAnim == ANIM_STD_CAR_GET_IN_RHS || vehAnim == ANIM_STD_CAR_GET_IN_LO_RHS || vehAnim == ANIM_STD_CAR_GET_IN_LHS || vehAnim == ANIM_STD_CAR_GET_IN_LO_LHS\n\t\t\t\t\t\t\t|| vehAnim == ANIM_STD_QUICKJACK || vehAnim == ANIM_STD_VAN_GET_IN_REAR_LHS || vehAnim == ANIM_STD_VAN_GET_IN_REAR_RHS)) {\n\t\t\t\t\t\tadjustedTimeStep = Max(m_pVehicleAnim->timeStep, 0.1f);\n\n\t\t\t\t\t\t// Smoothly change ped position\n\t\t\t\t\t\tneededPos.z = (neededPos.z - currentZ) / (m_pVehicleAnim->GetTimeLeft() / adjustedTimeStep) + currentZ;\n\t\t\t\t\t} else if (EnteringCar() || m_nPedState == PED_DRIVING && veh->IsBike()) {\n\t\t\t\t\t\tneededPos.z = Max(currentZ, autoZPos.z);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (CTimer::GetTimeInMilliseconds() < m_nPedStateTimer)\n\t\tstillGettingInOut = veh->m_vehType != VEHICLE_TYPE_BOAT || bOnBoat;\n\n\tif (!stillGettingInOut) {\n\t\tm_fRotationCur = m_fRotationDest;\n\t} else {\n\t\tfloat limitedDest = CGeneral::LimitRadianAngle(m_fRotationDest);\n\t\tfloat timeUntilStateChange = (m_nPedStateTimer - CTimer::GetTimeInMilliseconds())/600.0f;\n\n\t\tif (timeUntilStateChange <= 0.0f) {\n\t\t\tm_vecOffsetSeek.x = 0.0f;\n\t\t\tm_vecOffsetSeek.y = 0.0f;\n\t\t}\n\t\tm_vecOffsetSeek.z = 0.0f;\n\n\t\tneededPos -= timeUntilStateChange * m_vecOffsetSeek;\n\n\t\tif (PI + m_fRotationCur < limitedDest) {\n\t\t\tlimitedDest -= 2 * PI;\n\t\t} else if (m_fRotationCur - PI > limitedDest) {\n\t\t\tlimitedDest += 2 * PI;\n\t\t}\n\t\tm_fRotationCur -= (m_fRotationCur - limitedDest) * (1.0f - timeUntilStateChange);\n\t}\n\n\tif (seatPosMult > 0.2f || vehIsUpsideDown || veh->IsBike()) {\n\t\tSetPosition(neededPos);\n\t\tSetHeading(m_fRotationCur);\n\t} else {\n\t\tCMatrix vehDoorMat(veh->GetMatrix());\n\t\tvehDoorMat.GetPosition() += Multiply3x3(vehDoorMat, GetLocalPositionToOpenCarDoor(veh, m_vehDoor, 0.0f));\n\n\t\tif (m_vehDoor == CAR_WINDSCREEN || veh->bIsBus) {\n\t\t\tCMatrix correctionMat;\n\t\t\tif (veh->bIsBus && (m_vehDoor == CAR_DOOR_LF || m_vehDoor == CAR_DOOR_LR))\n\t\t\t\tcorrectionMat.SetRotateZ(-HALFPI);\n\t\t\telse if (veh->bIsBus && (m_vehDoor == CAR_DOOR_RF || m_vehDoor == CAR_DOOR_RR))\n\t\t\t\tcorrectionMat.SetRotateZ(HALFPI);\n\t\t\telse\n\t\t\t\tcorrectionMat.SetRotateZ(PI);\n\n\t\t\tvehDoorMat = vehDoorMat * correctionMat;\n\t\t}\n\t\tGetMatrix() = vehDoorMat;\n\t}\n\n}\n\nvoid\nCPed::SetCarJack(CVehicle* car)\n{\n\tuint8 doorFlag;\n\teDoors door;\n\tCPed *pedInSeat = nil;\n\n\tif (car->IsBoat())\n\t\treturn;\n\n\tif (car->IsBike()) {\n\t\tswitch (m_vehDoor) {\n\t\t\tcase CAR_DOOR_RF:\n\t\t\t\tdoorFlag = CAR_DOOR_FLAG_LF | CAR_DOOR_FLAG_RF;\n\t\t\t\tdoor = DOOR_FRONT_RIGHT;\n\t\t\t\tpedInSeat = car->pDriver;\n\t\t\t\tbreak;\n\t\t\tcase CAR_DOOR_RR:\n\t\t\t\tdoorFlag = CAR_DOOR_FLAG_LR | CAR_DOOR_FLAG_RR;\n\t\t\t\tdoor = DOOR_REAR_RIGHT;\n\t\t\t\tpedInSeat = car->pPassengers[0];\n\t\t\t\tbreak;\n\t\t\tcase CAR_DOOR_LF:\n\t\t\tcase CAR_WINDSCREEN:\n\t\t\t\tdoorFlag = CAR_DOOR_FLAG_LF | CAR_DOOR_FLAG_RF;\n\t\t\t\tdoor = DOOR_FRONT_LEFT;\n\t\t\t\tpedInSeat = car->pDriver;\n\t\t\t\tbreak;\n\t\t\tcase CAR_DOOR_LR:\n\t\t\t\tdoorFlag = CAR_DOOR_FLAG_LR | CAR_DOOR_FLAG_RR;\n\t\t\t\tdoor = DOOR_REAR_LEFT;\n\t\t\t\tpedInSeat = car->pPassengers[0];\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tdoorFlag = CAR_DOOR_FLAG_UNKNOWN;\n\t\t\t\tbreak;\n\t\t}\n\t} else {\n\t\tswitch (m_vehDoor) {\n\t\t\tcase CAR_DOOR_RF:\n\t\t\t\tdoorFlag = CAR_DOOR_FLAG_RF;\n\t\t\t\tdoor = DOOR_FRONT_RIGHT;\n\t\t\t\tif (car->pPassengers[0]) {\n\t\t\t\t\tpedInSeat = car->pPassengers[0];\n\t\t\t\t}\n\t\t\t\telse if (m_nPedType == PEDTYPE_COP) {\n\t\t\t\t\tpedInSeat = car->pDriver;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase CAR_DOOR_RR:\n\t\t\t\tdoorFlag = CAR_DOOR_FLAG_RR;\n\t\t\t\tdoor = DOOR_REAR_RIGHT;\n\t\t\t\tpedInSeat = car->pPassengers[2];\n\t\t\t\tbreak;\n\t\t\tcase CAR_DOOR_LF:\n\t\t\t\tdoorFlag = CAR_DOOR_FLAG_LF;\n\t\t\t\tdoor = DOOR_FRONT_LEFT;\n\t\t\t\tpedInSeat = car->pDriver;\n\t\t\t\tbreak;\n\t\t\tcase CAR_DOOR_LR:\n\t\t\t\tdoorFlag = CAR_DOOR_FLAG_LR;\n\t\t\t\tdoor = DOOR_REAR_LEFT;\n\t\t\t\tpedInSeat = car->pPassengers[1];\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tdoorFlag = CAR_DOOR_FLAG_UNKNOWN;\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tif(car->bIsBus)\n\t\tpedInSeat = car->pDriver;\n\n\tif (m_fHealth > 0.0f && (IsPlayer() || m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT || m_objective == OBJECTIVE_KILL_CHAR_ANY_MEANS ||\n\t\t\t\t\tCharCreatedBy == MISSION_CHAR ||  (car->VehicleCreatedBy != MISSION_VEHICLE && car->GetModelIndex() != MI_DODO)))\n\t\tif (pedInSeat && !pedInSeat->IsPedDoingDriveByShooting() && pedInSeat->m_nPedState == PED_DRIVING)\n\t\t\tif (m_nPedState != PED_CARJACK && !m_pVehicleAnim)\n\t\t\t\tif ((car->IsDoorReady(door) || car->IsDoorFullyOpen(door)))\n\t\t\t\t\tif (!car->bIsBeingCarJacked && !(doorFlag & car->m_nGettingInFlags) && !(doorFlag & car->m_nGettingOutFlags))\n\t\t\t\t\t\tSetCarJack_AllClear(car, m_vehDoor, doorFlag);\n}\n\nvoid\nCPed::SetCarJack_AllClear(CVehicle* car, uint32 doorNode, uint32 doorFlag)\n{\n\tif (m_nPedState != PED_SEEK_CAR)\n\t\tSetStoredState();\n\n\tm_pSeekTarget = car;\n\tm_pSeekTarget->RegisterReference((CEntity**)&m_pSeekTarget);\n\tSetPedState(PED_CARJACK);\n\tcar->bIsBeingCarJacked = true;\n\tm_pMyVehicle = (CVehicle*)m_pSeekTarget;\n\tm_pMyVehicle->RegisterReference((CEntity**)&m_pMyVehicle);\n\t((CVehicle*)m_pSeekTarget)->m_nNumGettingIn++;\n\n\tif (m_nPedType == PEDTYPE_COP)\n\t\tSay(SOUND_PED_ARREST_COP);\n\telse if (car->m_nDoorLock == CARLOCK_UNLOCKED)\n\t\tSay(SOUND_PED_CAR_JACKING, 1000);\n\n\tCVector carEnterPos;\n\tcarEnterPos = GetPositionToOpenCarDoor(car, m_vehDoor);\n\n\tcar->m_nGettingInFlags |= doorFlag;\n\tm_vecOffsetSeek = carEnterPos - GetPosition();\n\tm_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 600;\n\n\tif(car->IsBike()){\n\t\tbUsesCollision = false;\n\t\tPedAnimAlignCB(nil, this);\n\t} else {\n\t\tfloat zDiff = Max(0.0f, carEnterPos.z - GetPosition().z);\n\t\tbUsesCollision = false;\n\n\t\tif (m_vehDoor == CAR_DOOR_LF || m_vehDoor == CAR_DOOR_LR)\n\t\t\tm_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, zDiff > 4.4f ? ANIM_STD_CAR_ALIGNHI_DOOR_LHS : ANIM_STD_CAR_ALIGN_DOOR_LHS, 4.0f);\n\t\telse\n\t\t\tm_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, zDiff > 4.4f ? ANIM_STD_CAR_ALIGNHI_DOOR_RHS : ANIM_STD_CAR_ALIGN_DOOR_RHS, 4.0f);\n\n\t\tm_pVehicleAnim->SetFinishCallback(PedAnimAlignCB, this);\n\t}\n}\n\nvoid\nCPed::SetBeingDraggedFromCar(CVehicle *veh, uint32 vehEnterType, bool quickJack)\n{\n\tif (m_nPedState == PED_DRAG_FROM_CAR)\n\t\treturn;\n\n\tbUsesCollision = false;\n\tm_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);\n\tm_nLastPedState = PED_IDLE;\n\tSetMoveState(PEDMOVE_STILL);\n\tm_pSeekTarget = veh;\n\tm_pSeekTarget->RegisterReference((CEntity **) &m_pSeekTarget);\n\n\tif (veh->IsBike()) {\n\t\t((CBike*)veh)->bIsBeingPickedUp = true;\n\t\tif (veh->pPassengers[0] != this && (vehEnterType != CAR_WINDSCREEN || veh->pPassengers[0]))\n\t\t\tm_vehDoor = CAR_DOOR_LF;\n\t\telse\n\t\t\tm_vehDoor = CAR_DOOR_LR;\n\t} else {\n\t\tm_vehDoor = vehEnterType;\n\t}\n\n\tif (m_vehDoor == CAR_DOOR_LF) {\n\t\tif (veh->pDriver && veh->pDriver->IsPlayer())\n\t\t\tveh->SetStatus(STATUS_PLAYER_DISABLED);\n\t\telse\n\t\t\tveh->SetStatus(STATUS_ABANDONED);\n\t}\n\tRemoveInCarAnims();\n\tSetMoveState(PEDMOVE_NONE);\n\tLineUpPedWithCar(veh->IsBike() ? LINE_UP_TO_CAR_FALL : LINE_UP_TO_CAR_START);\n\tm_pVehicleAnim = nil;\n\tSetPedState(PED_DRAG_FROM_CAR);\n\tbChangedSeat = false;\n\tbWillBeQuickJacked = quickJack;\n\n\tSetHeading(m_fRotationCur);\n\n\tSay(SOUND_PED_CAR_JACKED);\n\tSetRadioStation();\n\n\tif(veh->IsBike())\n\t\tveh->m_nGettingOutFlags |= GetBikeDoorFlagInclJumpInFromFront(m_vehDoor);\n\telse\n\t\tveh->m_nGettingOutFlags |= GetCarDoorFlag(m_vehDoor);\n}\n\nvoid\nCPed::BeingDraggedFromCar(void)\n{\n\tAnimationId enterAnim;\n\tbool dontRunAnim = false;\n\n\tif (!m_pVehicleAnim) {\n\t\tCAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_STD_IDLE, 1000.0f);\n\n\t\tAssocGroupId assocGroup;\n\t\tif (m_pMyVehicle && m_pMyVehicle->IsBike()) {\n\t\t\tenterAnim = ANIM_BIKE_HIT;\n\t\t\tassocGroup = ((CBike*)m_pMyVehicle)->m_bikeAnimType;\n\n\t\t} else {\n\t\t\tif (m_vehDoor == CAR_DOOR_LF || m_vehDoor == CAR_DOOR_LR) {\n\t\t\t\tif (bWillBeQuickJacked && m_vehDoor == CAR_DOOR_LF) {\n\t\t\t\t\tenterAnim = ANIM_STD_QUICKJACKED;\n\t\t\t\t} else if (m_pMyVehicle->bLowVehicle) {\n\t\t\t\t\tenterAnim = ANIM_STD_JACKEDCAR_LO_LHS;\n\t\t\t\t} else {\n\t\t\t\t\tenterAnim = ANIM_STD_JACKEDCAR_LHS;\n\t\t\t\t}\n\t\t\t} else if (m_vehDoor == CAR_DOOR_RF || m_vehDoor == CAR_DOOR_RR) {\n\t\t\t\tif (m_pMyVehicle->bLowVehicle)\n\t\t\t\t\tenterAnim = ANIM_STD_JACKEDCAR_LO_RHS;\n\t\t\t\telse\n\t\t\t\t\tenterAnim = ANIM_STD_JACKEDCAR_RHS;\n\t\t\t} else\n\t\t\t\tdontRunAnim = true;\n\n\t\t\tassocGroup = ASSOCGRP_STD;\n\t\t}\n\n\t\tif (!dontRunAnim)\n\t\t\tm_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), assocGroup, enterAnim);\n\n\t\tm_pVehicleAnim->SetFinishCallback(PedSetDraggedOutCarCB, this);\n\n\t\tif (m_pMyVehicle && m_pMyVehicle->IsBike()) {\n\t\t\tLineUpPedWithCar(LINE_UP_TO_CAR_FALL);\n\t\t} else {\n\t\t\tLineUpPedWithCar(LINE_UP_TO_CAR_START);\n\t\t}\n\t\treturn;\n\n\t} else if (m_pVehicleAnim->animId == ANIM_BIKE_HIT) {\n\t\tLineUpPedWithCar(LINE_UP_TO_CAR_FALL);\n\n\t} else if (m_pVehicleAnim->currentTime <= 1.4f) {\n\t\tm_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);\n\t\tLineUpPedWithCar(LINE_UP_TO_CAR_START);\n\n\t} else {\n\t\tLineUpPedWithCar(LINE_UP_TO_CAR_2);\n\t}\n\n\tstatic float mult = 5.f;\n\tif (m_objective == OBJECTIVE_LEAVE_CAR_AND_DIE) {\n\t\tif (m_pMyVehicle) {\n\t\t\tm_pMyVehicle->ProcessOpenDoor(m_vehDoor, ANIM_STD_NUM, m_pVehicleAnim->currentTime * mult);\n\t\t}\n\t}\n}\n\nvoid\nCPed::SetEnterCar(CVehicle *car, uint32 unused)\n{\n\tif (CCranes::IsThisCarBeingCarriedByAnyCrane(car)) {\n\t\tRestorePreviousState();\n\t\tRestorePreviousObjective();\n\t} else {\n\t\tuint8 doorFlag;\n\t\teDoors door;\n\t\tif (car->IsBike()) {\n\t\t\tswitch (m_vehDoor) {\n\t\t\t\tcase CAR_DOOR_RF:\n\t\t\t\t\tdoorFlag = CAR_DOOR_FLAG_RF | CAR_DOOR_FLAG_LF;\n\t\t\t\t\tdoor = DOOR_FRONT_RIGHT;\n\t\t\t\t\tbreak;\n\t\t\t\tcase CAR_DOOR_RR:\n\t\t\t\t\tdoorFlag = CAR_DOOR_FLAG_RR | CAR_DOOR_FLAG_LR;\n\t\t\t\t\tdoor = DOOR_REAR_RIGHT;\n\t\t\t\t\tbreak;\n\t\t\t\tcase CAR_WING_LF:\n\t\t\t\tcase CAR_WING_LR:\n\t\t\t\tcase CAR_BONNET:\n\t\t\t\tcase CAR_BOOT:\n\t\t\t\t\tdoorFlag = CAR_DOOR_FLAG_UNKNOWN;\n\t\t\t\t\tbreak;\n\t\t\t\tcase CAR_DOOR_LF:\n\t\t\t\tcase CAR_WINDSCREEN:\n\t\t\t\t\tdoorFlag = CAR_DOOR_FLAG_RF | CAR_DOOR_FLAG_LF;\n\t\t\t\t\tdoor = DOOR_FRONT_LEFT;\n\t\t\t\t\tbreak;\n\t\t\t\tcase CAR_DOOR_LR:\n\t\t\t\t\tdoorFlag = CAR_DOOR_FLAG_RR | CAR_DOOR_FLAG_LR;\n\t\t\t\t\tdoor = DOOR_REAR_LEFT;\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t} else {\n\t\t\tswitch (m_vehDoor) {\n\t\t\t\tcase CAR_DOOR_RF:\n\t\t\t\t\tdoorFlag = CAR_DOOR_FLAG_RF;\n\t\t\t\t\tdoor = DOOR_FRONT_RIGHT;\n\t\t\t\t\tbreak;\n\t\t\t\tcase CAR_DOOR_RR:\n\t\t\t\t\tdoorFlag = CAR_DOOR_FLAG_RR;\n\t\t\t\t\tdoor = DOOR_REAR_RIGHT;\n\t\t\t\t\tbreak;\n\t\t\t\tcase CAR_DOOR_LF:\n\t\t\t\t\tif(car->m_nNumMaxPassengers != 0)\n\t\t\t\t\t\tdoorFlag = CAR_DOOR_FLAG_LF;\n\t\t\t\t\telse\n\t\t\t\t\t\tdoorFlag = CAR_DOOR_FLAG_LF | CAR_DOOR_FLAG_LR;\n\n\t\t\t\t\tdoor = DOOR_FRONT_LEFT;\n\t\t\t\t\tbreak;\n\t\t\t\tcase CAR_DOOR_LR:\n\t\t\t\t\tif (car->m_nNumMaxPassengers != 0)\n\t\t\t\t\t\tdoorFlag = CAR_DOOR_FLAG_LR;\n\t\t\t\t\telse\n\t\t\t\t\t\tdoorFlag = CAR_DOOR_FLAG_LF | CAR_DOOR_FLAG_LR;\n\n\t\t\t\t\tdoor = DOOR_REAR_LEFT;\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tdoorFlag = CAR_DOOR_FLAG_UNKNOWN;\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (!IsPedInControl() || m_fHealth <= 0.0f\n\t\t\t|| doorFlag & car->m_nGettingInFlags || doorFlag & car->m_nGettingOutFlags\n\t\t\t|| car->bIsBeingCarJacked || m_pVehicleAnim\n\t\t\t|| doorFlag && !car->IsDoorReady(door) && !car->IsDoorFullyOpen(door))\n\t\t\tSetMoveState(PEDMOVE_STILL);\n\t\telse\n\t\t\tSetEnterCar_AllClear(car, m_vehDoor, doorFlag);\n\t}\n}\n\nvoid\nCPed::SetEnterCar_AllClear(CVehicle *car, uint32 doorNode, uint32 doorFlag)\n{\n\tfloat zDiff = 0.0f;\n\tcar->m_nGettingInFlags |= doorFlag;\n\tbVehEnterDoorIsBlocked = false;\n\tif (m_nPedState != PED_SEEK_CAR && m_nPedState != PED_SEEK_IN_BOAT)\n\t\tSetStoredState();\n\n\tm_pSeekTarget = car;\n\tm_pSeekTarget->RegisterReference((CEntity **) &m_pSeekTarget);\n\tm_vehDoor = doorNode;\n\tSetPedState(PED_ENTER_CAR);\n\tif (m_vehDoor == CAR_DOOR_RF && m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER && !car->IsBike()) {\n\t\tcar->bIsBeingCarJacked = true;\n\t}\n\n\tm_pMyVehicle = (CVehicle*)m_pSeekTarget;\n\tm_pMyVehicle->RegisterReference((CEntity**) &m_pMyVehicle);\n\t((CVehicle*)m_pSeekTarget)->m_nNumGettingIn++;\n\tbUsesCollision = false;\n\tCVector doorOpenPos = GetPositionToOpenCarDoor(car, m_vehDoor);\n\n\t// Because buses have stairs\n\tif (!m_pMyVehicle->bIsBus)\n\t\tzDiff = Max(0.0f, doorOpenPos.z - GetPosition().z);\n\n\tm_vecOffsetSeek = doorOpenPos - GetPosition();\n\tm_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 600;\n\n\tif (car->IsBoat()) {\n\t\tif (car->pHandling->Flags & HANDLING_SIT_IN_BOAT)\n\t\t\tm_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_SIT, 100.0f);\n\t\telse\n\t\t\tm_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_BOAT_DRIVE, 100.0f);\n\n\t\tPedSetInCarCB(nil, this);\n\t\tbVehExitWillBeInstant = true;\n\n\t} else if (car->IsBike()) {\n\t\tPedAnimAlignCB(0, this);\n\t\tcar->AutoPilot.m_nCruiseSpeed = 0;\n\n\t} else {\n\t\tif (m_vehDoor == CAR_DOOR_LF || m_vehDoor == CAR_DOOR_LR)\n\t\t\tm_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, zDiff > 4.4f ? ANIM_STD_CAR_ALIGNHI_DOOR_RHS : ANIM_STD_CAR_ALIGN_DOOR_RHS, 4.0f);\n\t\telse\n\t\t\tm_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, zDiff > 4.4f ? ANIM_STD_CAR_ALIGNHI_DOOR_LHS : ANIM_STD_CAR_ALIGN_DOOR_LHS, 4.0f);\n\t\tm_pVehicleAnim->SetFinishCallback(PedAnimAlignCB, this);\n\t}\n}\n\nvoid\nCPed::EnterCar(void)\n{\n\tif (IsNotInWreckedVehicle() && m_fHealth > 0.0f) {\n\t\tCVehicle *veh = m_pMyVehicle;\n\n\t\t// Not used.\n\t\t// CVector posForDoor = GetPositionToOpenCarDoor(veh, m_vehDoor);\n\n\t\tif (veh->CanPedOpenLocks(this)) {\n\t\t\tif (m_vehDoor && m_pVehicleAnim) {\n\t\t\t\tveh->ProcessOpenDoor(m_vehDoor, m_pVehicleAnim->animId, m_pVehicleAnim->currentTime);\n\t\t\t}\n\t\t}\n\t\tbIsInTheAir = false;\n\t\tLineUpPedWithCar(LINE_UP_TO_CAR_START);\n\t\tif (veh->IsBike()) {\n\t\t\tCBike *bike = (CBike*)veh;\n\t\t\tif (bike->GetStatus() == STATUS_ABANDONED && !bike->bIsBeingPickedUp && m_pVehicleAnim) {\n\t\t\t\tint anim = m_pVehicleAnim->animId;\n\n\t\t\t\t// One is pickup and other one is pullup, not same :p\n\t\t\t\tif ((anim == ANIM_STD_BIKE_PICKUP_LHS || anim == ANIM_STD_BIKE_PICKUP_RHS) && m_pVehicleAnim->currentTime > 0.4667f)\n\t\t\t\t\tbike->bIsBeingPickedUp = true;\n\t\t\t\telse if ((anim == ANIM_STD_BIKE_PULLUP_LHS || anim == ANIM_STD_BIKE_PULLUP_RHS) && m_pVehicleAnim->currentTime > 0.4667f)\n\t\t\t\t\tbike->bIsBeingPickedUp = true;\n\t\t\t} else if (m_nPedState == PED_CARJACK && m_pVehicleAnim) {\n\t\t\t\tif (m_pVehicleAnim->currentTime > 0.4f && m_pVehicleAnim->currentTime - m_pVehicleAnim->timeStep <= 0.4f) {\n\t\t\t\t\tint anim = m_pVehicleAnim->animId;\n\t\t\t\t\tif (anim == ANIM_BIKE_KICK) {\n\t\t\t\t\t\tDMAudio.PlayOneShot(m_audioEntityId, SOUND_187, 3.0f);\n\t\t\t\t\t} else if (anim == ANIM_STD_BIKE_ELBOW_LHS || anim == ANIM_STD_BIKE_ELBOW_RHS) {\n\t\t\t\t\t\tDMAudio.PlayOneShot(m_audioEntityId, SOUND_186, 3.0f);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} else {\n\t\tQuitEnteringCar();\n\t\tSetDie();\n\t}\n}\n\nvoid\nCPed::QuitEnteringCar(void)\n{\n\tCVehicle *veh = m_pMyVehicle;\n\tif (m_pVehicleAnim)\n\t\tm_pVehicleAnim->blendDelta = -1000.0f;\n\t\n\tRestartNonPartialAnims();\n\n\tif (!RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_IDLE))\n\t\tCAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_STD_IDLE, 100.0f);\n\t\n\tif (veh) {\n\t\tif (m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER || m_nPedState == PED_CARJACK)\n\t\t\tveh->bIsBeingCarJacked = false;\n\n\t\tif (veh->m_nNumGettingIn != 0)\n\t\t\tveh->m_nNumGettingIn--;\n\n\t\tif (m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER || m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER)\n\t\t\tRestorePreviousObjective();\n\n\t\tif (veh->IsBike()) {\n\t\t\tveh->m_nGettingInFlags &= ~GetBikeDoorFlag(m_vehDoor);\n\t\t\t((CBike*)veh)->bIsBeingPickedUp = false;\n\t\t} else\n\t\t\tveh->m_nGettingInFlags &= ~GetEnterCarDoorFlag(m_vehDoor, veh->m_nNumMaxPassengers);\n\t}\n\n\tbUsesCollision = true;\n\n\tif (DyingOrDead()) {\n\t\tif (m_pVehicleAnim) {\n\t\t\tm_pVehicleAnim->blendDelta = -4.0f;\n\t\t\tm_pVehicleAnim->flags |= ASSOC_DELETEFADEDOUT;\n\t\t\tm_pVehicleAnim->flags &= ~ASSOC_RUNNING;\n\t\t}\n\t} else\n\t\tSetIdle();\n\n\tm_pVehicleAnim = nil;\n\t\n\tif (veh) {\n\t\tif (veh->AutoPilot.m_nCruiseSpeed == 0 && veh->VehicleCreatedBy == RANDOM_VEHICLE)\n\t\t\tveh->AutoPilot.m_nCruiseSpeed = 17;\n\t}\n}\n\nvoid\nCPed::SetExitBoat(CVehicle *boat)\n{\n\tSetPedState(PED_IDLE);\n\tCVector newPos = GetPosition();\n\tRemoveInCarAnims();\n\tCColModel* boatCol = boat->GetColModel();\n\tif (boat->IsUpsideDown()) {\n\t\tnewPos = CVector(0.0f, 0.0f, boatCol->boundingBox.min.z);\n\t\tnewPos = boat->GetMatrix() * newPos;\n\t\tnewPos.z += 1.0f;\n\t\tm_vehDoor = CAR_DOOR_RF;\n\t\tPedSetOutCarCB(nil, this);\n\t\tbIsStanding = true;\n\t\tm_pCurSurface = boat;\n\t\tm_pCurSurface->RegisterReference((CEntity**)&m_pCurSurface);\n\t\tm_pCurrentPhysSurface = boat;\n\t} else {\n\t\tif (boat->m_modelIndex == MI_SKIMMER) {\n\t\t\tif (!boat->bIsInWater) {\n\t\t\t\tm_vehDoor = CAR_DOOR_RF;\n\t\t\t\tPedSetOutCarCB(nil, this);\n\t\t\t\tbIsStanding = true;\n\t\t\t\tSetMoveState(PEDMOVE_STILL);\n\t\t\t\tbTryingToReachDryLand = true;\n\t\t\t\tfloat upMult = 1.04f + boatCol->boundingBox.min.z;\n\t\t\t\tfloat rightMult = 0.6f * boatCol->boundingBox.max.x;\n\t\t\t\tnewPos = upMult * boat->GetUp() + rightMult * boat->GetRight() + boat->GetPosition();\n\t\t\t\tSetPosition(newPos);\n\t\t\t\tif (m_pMyVehicle) {\n\t\t\t\t\tPositionPedOutOfCollision();\n\t\t\t\t} else {\n\t\t\t\t\tm_pMyVehicle = boat;\n\t\t\t\t\tPositionPedOutOfCollision();\n\t\t\t\t\tm_pMyVehicle = nil;\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tnewPos.z += 2.0f;\n\t\t}\n\t\tm_vehDoor = CAR_DOOR_RF;\n\t\tPedSetOutCarCB(nil, this);\n\t\tbIsStanding = true;\n\t\tm_pCurSurface = boat;\n\t\tm_pCurSurface->RegisterReference((CEntity**)&m_pCurSurface);\n\t\tm_pCurrentPhysSurface = boat;\n\t\tCColPoint foundCol;\n\t\tCEntity *foundEnt = nil;\n\t\tif (CWorld::ProcessVerticalLine(newPos, newPos.z - 1.4f, foundCol, foundEnt, false, true, false, false, false, false, nil))\n\t\t\tnewPos.z = FEET_OFFSET + foundCol.point.z;\n\t}\n\tSetPosition(newPos);\n\tSetMoveState(PEDMOVE_STILL);\n\tm_vecMoveSpeed = boat->m_vecMoveSpeed;\n}\n\n// wantedDoorNode = 0 means that func. will determine it\nvoid\nCPed::SetExitCar(CVehicle *veh, uint32 wantedDoorNode)\n{\n\tuint32 optedDoorNode = wantedDoorNode;\n\tbool teleportNeeded = false;\n\tbool isLow = !!veh->bLowVehicle;\n\n\tbool canJumpOut = false;\n\tif (!veh->CanPedExitCar(false) && !bBusJacked) {\n\t\tif (IsPlayer()) {\n\t\t\tcanJumpOut = veh->IsBike() ? veh->CanPedJumpOffBike() : veh->CanPedJumpOutCar();\n\t\t}\n\t\tif (!canJumpOut) {\n\t\t\tif (veh->pDriver) {\n\t\t\t\tif (veh->pDriver->IsPlayer()) {\n\t\t\t\t\tif (veh->pDriver != this) {\n\t\t\t\t\t\tm_leaveCarTimer = CTimer::GetTimeInMilliseconds() + 5000;\n\t\t\t\t\t\tbHeldHostageInCar = true;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tveh->AutoPilot.m_nCruiseSpeed = 0;\n\t\t\t\t\tveh->AutoPilot.m_nCarMission = MISSION_NONE;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t}\n\n\tif (m_nPedState == PED_EXIT_CAR || m_nPedState == PED_DRAG_FROM_CAR)\n\t\treturn;\n\n\tm_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);\n\tm_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f);\n\tif (wantedDoorNode == 0) {\n\t\toptedDoorNode = CAR_DOOR_LF;\n\t\tif (veh->IsBike()) {\n\t\t\tif (canJumpOut) {\n\t\t\t\toptedDoorNode = veh->pPassengers[0] == this ? CAR_BUMP_REAR : CAR_BOOT;\n\t\t\t} else if (veh->pPassengers[0] == this) {\n\t\t\t\toptedDoorNode = CAR_DOOR_LR;\n\t\t\t} else {\n\t\t\t\toptedDoorNode = CAR_DOOR_LF;\n\t\t\t}\n\t\t} else if (veh->bIsBus) {\n\t\t\toptedDoorNode = CAR_DOOR_LF;\n\t\t} else if (veh->pDriver == this) {\n\t\t\toptedDoorNode = CAR_DOOR_LF;\n\t\t} else if (veh->pPassengers[0] == this) {\n\t\t\toptedDoorNode = CAR_DOOR_RF;\n\t\t} else if (veh->pPassengers[1] == this) {\n\t\t\toptedDoorNode = CAR_DOOR_LR;\n\t\t} else if (veh->pPassengers[2] == this) {\n\t\t\toptedDoorNode = CAR_DOOR_RR;\n\t\t} else {\n\t\t\tfor (int i = 3; i < veh->m_nNumMaxPassengers; ++i) {\n\t\t\t\tif (veh->pPassengers[i] == this) {\n\t\t\t\t\tif (i & 1)\n\t\t\t\t\t\toptedDoorNode = CAR_DOOR_RR;\n\t\t\t\t\telse\n\t\t\t\t\t\toptedDoorNode = CAR_DOOR_LR;\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tbool someoneExitsFromOurExitDoor = false;\n\tbool someoneEntersFromOurExitDoor = false;\n\tif (veh->IsBike()) {\n\t\tswitch (optedDoorNode) {\n\t\t\tcase CAR_BUMP_REAR:\n\t\t\tcase CAR_DOOR_RR:\n\t\t\tcase CAR_DOOR_LR:\n\t\t\t\tif (veh->m_nGettingInFlags & (CAR_DOOR_FLAG_LR | CAR_DOOR_FLAG_RR))\n\t\t\t\t\tsomeoneEntersFromOurExitDoor = true;\n\t\t\t\tbreak;\n\t\t\tcase CAR_DOOR_RF:\n\t\t\tcase CAR_DOOR_LF:\n\t\t\tcase CAR_BOOT:\n\t\t\t\tif (veh->m_nGettingInFlags & (CAR_DOOR_FLAG_LF | CAR_DOOR_FLAG_RF))\n\t\t\t\t\tsomeoneEntersFromOurExitDoor = true;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t} else {\n\t\tswitch (optedDoorNode) {\n\t\t\tcase CAR_DOOR_RF:\n\t\t\t\tif (veh->m_nGettingInFlags & CAR_DOOR_FLAG_RF)\n\t\t\t\t\tsomeoneEntersFromOurExitDoor = true;\n\t\t\t\tif (veh->m_nGettingOutFlags & CAR_DOOR_FLAG_RF)\n\t\t\t\t\tsomeoneExitsFromOurExitDoor = true;\n\t\t\t\tbreak;\n\t\t\tcase CAR_DOOR_RR:\n\t\t\t\tif (veh->m_nGettingInFlags & CAR_DOOR_FLAG_RR)\n\t\t\t\t\tsomeoneEntersFromOurExitDoor = true;\n\t\t\t\tif (veh->m_nGettingOutFlags & CAR_DOOR_FLAG_RR)\n\t\t\t\t\tsomeoneExitsFromOurExitDoor = true;\n\t\t\t\tbreak;\n\t\t\tcase CAR_DOOR_LF:\n\t\t\t\tif (veh->m_nGettingInFlags & CAR_DOOR_FLAG_LF)\n\t\t\t\t\tsomeoneEntersFromOurExitDoor = true;\n\t\t\t\tif (veh->m_nGettingOutFlags & CAR_DOOR_FLAG_LF)\n\t\t\t\t\tsomeoneExitsFromOurExitDoor = true;\n\t\t\t\tbreak;\n\t\t\tcase CAR_DOOR_LR:\n\t\t\t\tif (veh->m_nGettingInFlags & CAR_DOOR_FLAG_LR)\n\t\t\t\t\tsomeoneEntersFromOurExitDoor = true;\n\t\t\t\tif (veh->m_nGettingOutFlags & CAR_DOOR_FLAG_LR)\n\t\t\t\t\tsomeoneExitsFromOurExitDoor = true;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n\tif (someoneEntersFromOurExitDoor && m_objective == OBJECTIVE_LEAVE_CAR) {\n\t\tRestorePreviousObjective();\n\t\treturn;\n\t}\n\tif (!someoneExitsFromOurExitDoor || m_nPedType == PEDTYPE_COP && veh->bIsBus) {\n#if defined GTAVC_JP_PATCH || defined FIX_BUGS\n\t\tif (veh->pDriver == this && !IsPlayer() && veh == CGameLogic::pShortCutTaxi) {\n\t\t\tm_objective = OBJECTIVE_NONE;\n\t\t\treturn;\n\t\t}\n#endif\n\t\tbool thereIsRoom;\n\t\tif (canJumpOut) {\n\t\t\tthereIsRoom = 1;\n\t\t} else {\n\t\t\t// Again, unused...\n\t\t\t// CVector exitPos = GetPositionToOpenCarDoor(veh, optedDoorNode);\n\t\t\tthereIsRoom = veh->IsRoomForPedToLeaveCar(optedDoorNode, nil);\n\t\t}\n\n\t\tif (!thereIsRoom) {\n\t\t\tbool trySideSeat = false;\n\t\t\tCPed *pedOnSideSeat;\n\t\t\tint firstOptedDoor = optedDoorNode;\n\t\t\tif (veh->IsBike()) {\n\t\t\t\tswitch (optedDoorNode) {\n\t\t\t\t\tcase CAR_DOOR_RF:\n\t\t\t\t\t\toptedDoorNode = CAR_DOOR_LF;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase CAR_DOOR_RR:\n\t\t\t\t\t\toptedDoorNode = CAR_DOOR_LR;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase CAR_DOOR_LF:\n\t\t\t\t\t\toptedDoorNode = CAR_DOOR_RF;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase CAR_DOOR_LR:\n\t\t\t\t\t\toptedDoorNode = CAR_DOOR_RR;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tswitch (optedDoorNode) {\n\t\t\t\t\tcase CAR_DOOR_RF:\n\t\t\t\t\t\tif (veh->pDriver || veh->m_nGettingInFlags & CAR_DOOR_FLAG_LF) {\n\t\t\t\t\t\t\tpedOnSideSeat = veh->pDriver;\n\t\t\t\t\t\t\ttrySideSeat = true;\n\t\t\t\t\t\t} else\n\t\t\t\t\t\t\toptedDoorNode = CAR_DOOR_LF;\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase CAR_DOOR_RR:\n\t\t\t\t\t\tif (veh->pPassengers[1] || veh->m_nGettingInFlags & CAR_DOOR_FLAG_LR) {\n\t\t\t\t\t\t\tpedOnSideSeat = veh->pPassengers[1];\n\t\t\t\t\t\t\ttrySideSeat = true;\n\t\t\t\t\t\t} else\n\t\t\t\t\t\t\toptedDoorNode = CAR_DOOR_LR;\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase CAR_DOOR_LF:\n\t\t\t\t\t\tif (veh->pPassengers[0] || veh->m_nGettingInFlags & CAR_DOOR_FLAG_RF) {\n\t\t\t\t\t\t\tpedOnSideSeat = veh->pPassengers[0];\n\t\t\t\t\t\t\ttrySideSeat = true;\n\t\t\t\t\t\t} else\n\t\t\t\t\t\t\toptedDoorNode = CAR_DOOR_RF;\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase CAR_DOOR_LR:\n\t\t\t\t\t\tif (veh->pPassengers[2] || veh->m_nGettingInFlags & CAR_DOOR_FLAG_RR) {\n\t\t\t\t\t\t\tpedOnSideSeat = (CPed*)veh->pPassengers[2];\n\t\t\t\t\t\t\ttrySideSeat = true;\n\t\t\t\t\t\t} else\n\t\t\t\t\t\t\toptedDoorNode = CAR_DOOR_RR;\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (trySideSeat) {\n\t\t\t\tif (!pedOnSideSeat || !IsPlayer() && CharCreatedBy != MISSION_CHAR)\n\t\t\t\t\treturn;\n\n\t\t\t\tswitch (optedDoorNode) {\n\t\t\t\t\tcase CAR_DOOR_RF:\n\t\t\t\t\t\toptedDoorNode = CAR_DOOR_LF;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase CAR_DOOR_RR:\n\t\t\t\t\t\toptedDoorNode = CAR_DOOR_LR;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase CAR_DOOR_LF:\n\t\t\t\t\t\toptedDoorNode = CAR_DOOR_RF;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase CAR_DOOR_LR:\n\t\t\t\t\t\toptedDoorNode = CAR_DOOR_RR;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\t// ...\n\t\t\t// CVector exitPos = GetPositionToOpenCarDoor(veh, optedDoorNode);\n\t\t\tif (!veh->IsRoomForPedToLeaveCar(optedDoorNode, nil)) {\n\t\t\t\tif (!IsPlayer() && CharCreatedBy != MISSION_CHAR)\n\t\t\t\t\treturn;\n\n\t\t\t\t// needed for PositionPedOutOfCollision()\n\t\t\t\toptedDoorNode = firstOptedDoor;\n\t\t\t\tm_vehDoor = firstOptedDoor;\n\t\t\t\tPositionPedOutOfCollision();\n\t\t\t\tteleportNeeded = true;\n\t\t\t}\n\t\t}\n\n\t\tif (!teleportNeeded && veh->IsOnItsSide()) {\n\t\t\tm_vehDoor = optedDoorNode;\n\t\t\tPositionPedOutOfCollision();\n\t\t\tteleportNeeded = true;\n\t\t}\n\n\t\tif (m_nPedState == PED_FLEE_POS) {\n\t\t\tm_nLastPedState = PED_FLEE_POS;\n\t\t\tm_nPrevMoveState = PEDMOVE_RUN;\n\t\t\tSetMoveState(PEDMOVE_SPRINT);\n\t\t} else {\n\t\t\tm_nLastPedState = PED_IDLE;\n\t\t\tm_nPrevMoveState = PEDMOVE_STILL;\n\t\t\tSetMoveState(PEDMOVE_STILL);\n\t\t}\n\n\t\tbUsesCollision = false;\n\t\tm_pSeekTarget = veh;\n\t\tm_pSeekTarget->RegisterReference((CEntity**) &m_pSeekTarget);\n\t\tm_vehDoor = optedDoorNode;\n\t\tSetPedState(PED_EXIT_CAR);\n\t\tif (m_pVehicleAnim && m_pVehicleAnim->flags & ASSOC_PARTIAL)\n\t\t\tm_pVehicleAnim->blendDelta = -1000.0f;\n\t\tRemoveInCarAnims();\n\t\tSetMoveState(PEDMOVE_NONE);\n\t\tCAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_STD_IDLE, 100.0f);\n\t\tveh->AutoPilot.m_nCruiseSpeed = 0;\n\n\t\tif (teleportNeeded) {\n\t\t\tPedSetOutCarCB(nil, this);\n\t\t} else {\n\t\t\tif (veh->GetUp().z <= -0.8f && !veh->IsBike()) {\n\t\t\t\tif (m_vehDoor == CAR_DOOR_RF || m_vehDoor == CAR_DOOR_RR) {\n\t\t\t\t\tm_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_CRAWLOUT_RHS);\n\t\t\t\t} else if (m_vehDoor == CAR_DOOR_LF || m_vehDoor == CAR_DOOR_LR) {\n\t\t\t\t\tm_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_CRAWLOUT_LHS);\n\t\t\t\t}\n\t\t\t\tm_pVehicleAnim->SetFinishCallback(PedSetOutCarCB, this);\n\n\t\t\t} else if (veh->IsBike()) {\n\t\t\t\tCBike* bike = (CBike*)veh;\n\t\t\t\tswitch (m_vehDoor) {\n\t\t\t\t\tcase CAR_BUMP_REAR:\n\t\t\t\t\tcase CAR_BOOT:\n\t\t\t\t\t\tm_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), bike->m_bikeAnimType, ANIM_BIKE_GETOFF_BACK);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase CAR_DOOR_RF:\n\t\t\t\t\tcase CAR_DOOR_RR:\n\t\t\t\t\t\tm_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), bike->m_bikeAnimType, ANIM_BIKE_GETOFF_RHS);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase CAR_DOOR_LF:\n\t\t\t\t\tcase CAR_DOOR_LR:\n\t\t\t\t\t\tm_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), bike->m_bikeAnimType, ANIM_BIKE_GETOFF_LHS);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tint8 exitFlags = 0;\n\n\t\t\t\t// Bike door flags incl. passenger jump off\n\t\t\t\tswitch (m_vehDoor) {\n\t\t\t\t\tcase CAR_BUMP_REAR:\n\t\t\t\t\tcase CAR_DOOR_RR:\n\t\t\t\t\tcase CAR_DOOR_LR:\n\t\t\t\t\t\texitFlags = CAR_DOOR_FLAG_RR | CAR_DOOR_FLAG_LR;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase CAR_DOOR_RF:\n\t\t\t\t\tcase CAR_DOOR_LF:\n\t\t\t\t\tcase CAR_BOOT:\n\t\t\t\t\t\texitFlags = CAR_DOOR_FLAG_RF | CAR_DOOR_FLAG_LF;\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\t// Passenger get off\n\t\t\t\tif (m_vehDoor == CAR_BUMP_REAR || m_vehDoor == CAR_BOOT) {\n\t\t\t\t\tm_pVehicleAnim->SetFinishCallback(RestoreHeadingRateCB, this);\n\t\t\t\t\tm_headingRate = 0.0f;\n\n\t\t\t\t} else {\n\t\t\t\t\tveh->m_nGettingOutFlags |= exitFlags;\n\t\t\t\t\tm_pVehicleAnim->SetFinishCallback(PedAnimStepOutCarCB, this);\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\tswitch (m_vehDoor) {\n\t\t\t\t\tcase CAR_DOOR_RF:\n\t\t\t\t\t\tif (canJumpOut) {\n\t\t\t\t\t\t\tm_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_ROLLOUT_RHS);\n\t\t\t\t\t\t} else if (veh->bIsBus) {\n\t\t\t\t\t\t\tm_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_COACH, ANIM_STD_COACH_GET_OUT_LHS);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (isLow)\n\t\t\t\t\t\t\t\tm_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_GETOUT_LO_RHS);\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\tm_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_GETOUT_RHS);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase CAR_DOOR_RR:\n\t\t\t\t\t\tif (canJumpOut) {\n\t\t\t\t\t\t\tm_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_ROLLOUT_RHS);\n\t\t\t\t\t\t} else if (veh->bIsVan) {\n\t\t\t\t\t\t\tm_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_VAN, ANIM_STD_VAN_GET_OUT_REAR_RHS);\n\t\t\t\t\t\t} else if (isLow) {\n\t\t\t\t\t\t\tm_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_GETOUT_LO_RHS);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tm_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_GETOUT_RHS);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase CAR_DOOR_LF:\n\t\t\t\t\t\tif (canJumpOut) {\n\t\t\t\t\t\t\tm_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_ROLLOUT_LHS);\n\t\t\t\t\t\t} else if (veh->bIsBus) {\n\t\t\t\t\t\t\tm_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_COACH, ANIM_STD_COACH_GET_OUT_LHS);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (isLow)\n\t\t\t\t\t\t\t\tm_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_GETOUT_LO_LHS);\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\tm_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_GETOUT_LHS);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase CAR_DOOR_LR:\n\t\t\t\t\t\tif (canJumpOut) {\n\t\t\t\t\t\t\tm_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_ROLLOUT_LHS);\n\t\t\t\t\t\t} else if (veh->bIsVan) {\n\t\t\t\t\t\t\tm_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_VAN, ANIM_STD_VAN_GET_OUT_REAR_LHS);\n\t\t\t\t\t\t} else if (isLow) {\n\t\t\t\t\t\t\tm_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_GETOUT_LO_LHS);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tm_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_GETOUT_LHS);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif (!bBusJacked && !canJumpOut) {\n\t\t\t\t\tveh->m_nGettingOutFlags |= GetCarDoorFlag(m_vehDoor);\n\t\t\t\t}\n\t\t\t\tm_pVehicleAnim->SetFinishCallback(canJumpOut ? RestoreHeadingRateCB : PedAnimStepOutCarCB, this);\n\t\t\t}\n\t\t}\n\t\tbChangedSeat = false;\n\t\tif (veh->bIsBus)\n\t\t\tbRenderPedInCar = true;\n\n\t\tSetRadioStation();\n\t\tif (veh->pDriver == this) {\n\t\t\tif (IsPlayer())\n\t\t\t\tveh->SetStatus(STATUS_PLAYER_DISABLED);\n\t\t\telse\n\t\t\t\tveh->SetStatus(STATUS_ABANDONED);\n\t\t}\n\t}\n}\n\nvoid\nCPed::ExitCar(void)\n{\n\tif (!m_pVehicleAnim) {\n\t\tif (InVehicle()) {\n\t\t\tif (m_pMyVehicle->IsBike()) {\n\t\t\t\tif (m_vehDoor == CAR_BOOT || m_vehDoor == CAR_BUMP_REAR) {\n\t\t\t\t\t((CBike*)m_pMyVehicle)->KnockOffRider(WEAPONTYPE_UNARMED, 0, this, false);\n\t\t\t\t}\n\t\t\t} else if (m_pMyVehicle->IsCar()) {\n\t\t\t\tif (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_ROLLOUT_LHS)) {\n\t\t\t\t\t((CAutomobile*)m_pMyVehicle)->KnockPedOutCar(WEAPONTYPE_UNIDENTIFIED, CAR_DOOR_LF, this);\n\t\t\t\t} else if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_ROLLOUT_RHS)) {\n\t\t\t\t\t((CAutomobile*)m_pMyVehicle)->KnockPedOutCar(WEAPONTYPE_UNIDENTIFIED, CAR_DOOR_RF, this);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn;\n\t}\n\n\tAnimationId exitAnim = (AnimationId) m_pVehicleAnim->animId;\n\tfloat animTime = m_pVehicleAnim->currentTime;\n\n\tif (exitAnim == ANIM_BIKE_GETOFF_BACK) {\n\t\tif (animTime > 0.35f && m_pMyVehicle && m_pMyVehicle->IsBike())\n\t\t\t((CBike*)m_pMyVehicle)->KnockOffRider(WEAPONTYPE_UNARMED, 0, this, false);\n\t\telse\n\t\t\tLineUpPedWithCar(LINE_UP_TO_CAR_FALL);\n\n\t} else if (exitAnim == ANIM_STD_ROLLOUT_LHS || exitAnim == ANIM_STD_ROLLOUT_RHS) {\n\t\tif (animTime > 0.07f && m_pMyVehicle && m_pMyVehicle->IsCar()) {\n\t\t\tif (exitAnim == ANIM_STD_ROLLOUT_LHS) {\n\t\t\t\t((CAutomobile*)m_pMyVehicle)->KnockPedOutCar(WEAPONTYPE_UNIDENTIFIED, CAR_DOOR_LF, this);\n\t\t\t} else {\n\t\t\t\t((CAutomobile*)m_pMyVehicle)->KnockPedOutCar(WEAPONTYPE_UNIDENTIFIED, CAR_DOOR_RF, this);\n\t\t\t}\n\t\t} else {\n\t\t\tLineUpPedWithCar(LINE_UP_TO_CAR_FALL);\n\t\t}\n\t} else {\n\t\tm_pMyVehicle->ProcessOpenDoor(m_vehDoor, exitAnim, animTime);\n\n\t\tif (m_pSeekTarget) {\n\t\t\t// Car is upside down\n\t\t\tif (m_pMyVehicle->GetUp().z > -0.8f) {\n\t\t\t\tif (exitAnim == ANIM_STD_CAR_CLOSE_RHS || exitAnim == ANIM_STD_CAR_CLOSE_LHS || animTime > 0.3f)\n\t\t\t\t\tLineUpPedWithCar(LINE_UP_TO_CAR_END);\n\t\t\t\telse\n\t\t\t\t\tLineUpPedWithCar((m_pMyVehicle->GetModelIndex() == MI_DODO ? LINE_UP_TO_CAR_END : LINE_UP_TO_CAR_START));\n\t\t\t}\n\t\t\telse {\n\t\t\t\tLineUpPedWithCar(LINE_UP_TO_CAR_END);\n\t\t\t}\n\t\t}\n\n\t\t// If there is someone in front of the door, make him fall while we exit.\n\t\tif (m_nPedState == PED_EXIT_CAR) {\n\t\t\tCPed* foundPed = nil;\n\t\t\tfor (int i = 0; i < m_numNearPeds; i++) {\n\t\t\t\tif ((m_nearPeds[i]->GetPosition() - GetPosition()).MagnitudeSqr2D() < SQR(0.2f)) {\n\t\t\t\t\tfoundPed = m_nearPeds[i];\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif(foundPed && (!foundPed->IsPlayer() || m_nPedType == PEDTYPE_COP || m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT || m_objective == OBJECTIVE_KILL_CHAR_ANY_MEANS))\n\t\t\t\tif (animTime > 0.4f && foundPed->IsPedInControl())\n\t\t\t\t\tfoundPed->SetFall(1000, ANIM_STD_HIGHIMPACT_FRONT, 1);\n\t\t}\n\t}\n}\n\nCVector\nCPed::GetPositionToOpenCarDoor(CVehicle *veh, uint32 component)\n{\n\tCVector vehDoorPos = GetPositionToOpenCarDoor(veh, component, 1.0f);\n\n/*\n\t// Unused\n\tvehDoorPosWithoutOffset = veh->GetMatrix() * localVehDoorPos;\n*/\n\treturn vehDoorPos;\n}\n\nvoid\nCPed::GetNearestDoor(CVehicle *veh, CVector &posToOpen)\n{\n\tCVector *enterOffset = nil;\n\tif (veh->IsBike()) {\n\t\tif (m_objective != OBJECTIVE_ENTER_CAR_AS_PASSENGER) {\n\n\t\t\t// If bike didn't fall to ground\n\t\t\tif (Abs(veh->GetRight().z) < 0.1f) {\n\t\t\t\tfloat angleDiff = (GetPosition() - veh->GetPosition()).Heading() - veh->GetForward().Heading();\n\n\t\t\t\tif (angleDiff > PI)\n\t\t\t\t\tangleDiff -= TWOPI;\n\t\t\t\telse if (angleDiff < -PI)\n\t\t\t\t\tangleDiff += TWOPI;\n\n\t\t\t\tif (Abs(angleDiff) < DEGTORAD(30.f)\n\t\t\t\t\t&& (IsPlayer() && ((CPlayerPed*)this)->m_fMoveSpeed > 1.5f && !m_vehDoor ||\n\t\t\t\t\t\t!IsPlayer() && m_nPedType != PEDTYPE_COP && m_nMoveState == PEDMOVE_RUN\n\t\t\t\t\t\t&& m_pedStats->m_temper > 65\n\t\t\t\t\t\t&& !m_vehDoor || m_vehDoor == CAR_WINDSCREEN)) {\n\t\t\t\t\tm_vehDoor = CAR_WINDSCREEN;\n\t\t\t\t\tposToOpen = GetPositionToOpenCarDoor(veh, CAR_WINDSCREEN);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} else if (m_vehDoor == CAR_DOOR_LF && veh->pDriver && !veh->bLowVehicle && !veh->bIsBus) {\n\t\tenterOffset = &vecPedQuickDraggedOutCarAnimOffset;\n\t}\n\n\tCVector lfPos = GetPositionToOpenCarDoor(veh, CAR_DOOR_LF);\n\tCVector rfPos = GetPositionToOpenCarDoor(veh, CAR_DOOR_RF);\n\n\t// Left front door is closer\n\tif ((lfPos - GetPosition()).MagnitudeSqr2D() < (rfPos - GetPosition()).MagnitudeSqr2D()) {\n\n\t\tif (veh->IsRoomForPedToLeaveCar(CAR_DOOR_LF, enterOffset)) {\n\t\t\tm_vehDoor = CAR_DOOR_LF;\n\t\t\tposToOpen = lfPos;\n\t\t} else if (veh->IsRoomForPedToLeaveCar(CAR_DOOR_RF, enterOffset)) {\n\t\t\tm_vehDoor = CAR_DOOR_RF;\n\t\t\tposToOpen = rfPos;\n\t\t}\n\t} else {\n\n\t\tif (veh->IsRoomForPedToLeaveCar(CAR_DOOR_RF, enterOffset)) {\n\n\t\t\tCPed *rfPassenger = veh->pPassengers[0];\n\t\t\tif (rfPassenger && !veh->IsBike()\n\t\t\t\t\t&& (rfPassenger->m_leader == this || rfPassenger->bDontDragMeOutCar ||\n\t\t\t\t\t\tveh->VehicleCreatedBy == MISSION_VEHICLE && m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER)\n\t\t\t\t\t&& veh->IsRoomForPedToLeaveCar(CAR_DOOR_LF, enterOffset)\n\t\t\t\t|| (veh->m_nGettingInFlags & CAR_DOOR_FLAG_RF) && veh->IsRoomForPedToLeaveCar(CAR_DOOR_LF, enterOffset)) {\n\n\t\t\t\tm_vehDoor = CAR_DOOR_LF;\n\t\t\t\tposToOpen = lfPos;\n\t\t\t} else {\n\t\t\t\tm_vehDoor = CAR_DOOR_RF;\n\t\t\t\tposToOpen = rfPos;\n\t\t\t}\n\t\t} else if (veh->IsRoomForPedToLeaveCar(CAR_DOOR_LF, enterOffset)) {\n\t\t\tm_vehDoor = CAR_DOOR_LF;\n\t\t\tposToOpen = lfPos;\n\t\t}\n\t}\n}\n\nbool\nCPed::GetNearestPassengerDoor(CVehicle *veh, CVector &posToOpen)\n{\n\tCVector rfPos, lrPos, rrPos;\n\tbool canEnter = false;\n\n\tCVehicleModelInfo *vehModel = (CVehicleModelInfo *)CModelInfo::GetModelInfo(veh->GetModelIndex());\n\n\tswitch (veh->GetModelIndex()) {\n\t\tcase MI_BUS:\n\t\t\tm_vehDoor = CAR_DOOR_RF;\n\t\t\tposToOpen = GetPositionToOpenCarDoor(veh, CAR_DOOR_RF);\n\t\t\treturn true;\n\t\tcase MI_RHINO:\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\n\tCVector2D rfPosDist(999.0f, 999.0f);\n\tCVector2D lrPosDist(999.0f, 999.0f);\n\tCVector2D rrPosDist(999.0f, 999.0f);\n\n\tif (veh->IsBike()) {\n\t\tif (!veh->pPassengers[0]\n\t\t\t&& !(veh->m_nGettingInFlags & CAR_DOOR_FLAG_LR)\n\t\t\t&& veh->IsRoomForPedToLeaveCar(CAR_DOOR_LR, nil)) {\n\t\t\tlrPos = GetPositionToOpenCarDoor(veh, CAR_DOOR_LR);\n\t\t\tcanEnter = true;\n\t\t\tlrPosDist = lrPos - GetPosition();\n\t\t}\n\t\tif (!veh->pPassengers[0]\n\t\t\t&& !(veh->m_nGettingInFlags & CAR_DOOR_FLAG_RR)\n\t\t\t&& veh->IsRoomForPedToLeaveCar(CAR_DOOR_RR, nil)) {\n\t\t\trrPos = GetPositionToOpenCarDoor(veh, CAR_DOOR_RR);\n\t\t\tcanEnter = true;\n\t\t\trrPosDist = rrPos - GetPosition();\n\t\t}\n\t} else if (!veh->pPassengers[0]\n\t\t&& !(veh->m_nGettingInFlags & CAR_DOOR_FLAG_RF)\n\t\t&& veh->IsRoomForPedToLeaveCar(CAR_DOOR_RF, nil)) {\n\n\t\trfPos = GetPositionToOpenCarDoor(veh, CAR_DOOR_RF);\n\t\tcanEnter = true;\n\t\trfPosDist = rfPos - GetPosition();\n\t}\n\n\tif (vehModel->m_numDoors == 4) {\n\t\tif (!veh->pPassengers[1]\n\t\t\t&& !(veh->m_nGettingInFlags & CAR_DOOR_FLAG_LR)\n\t\t\t&& veh->IsRoomForPedToLeaveCar(CAR_DOOR_LR, nil)) {\n\t\t\tlrPos = GetPositionToOpenCarDoor(veh, CAR_DOOR_LR);\n\t\t\tcanEnter = true;\n\t\t\tlrPosDist = lrPos - GetPosition();\n\t\t}\n\t\tif (!veh->pPassengers[2]\n\t\t\t&& !(veh->m_nGettingInFlags & CAR_DOOR_FLAG_RR)\n\t\t\t&& veh->IsRoomForPedToLeaveCar(CAR_DOOR_RR, nil)) {\n\t\t\trrPos = GetPositionToOpenCarDoor(veh, CAR_DOOR_RR);\n\t\t\tcanEnter = true;\n\t\t\trrPosDist = rrPos - GetPosition();\n\t\t}\n\n\t\t// When the door we should enter is blocked by some object.\n\t\tif (!canEnter)\n\t\t\tveh->ShufflePassengersToMakeSpace();\n\t}\n\n\tCVector2D nextToCompare = rfPosDist;\n\tposToOpen = rfPos;\n\tm_vehDoor = CAR_DOOR_RF;\n\tif (lrPosDist.MagnitudeSqr() < nextToCompare.MagnitudeSqr()) {\n\t\tm_vehDoor = CAR_DOOR_LR;\n\t\tposToOpen = lrPos;\n\t\tnextToCompare = lrPosDist;\n\t}\n\n\tif (rrPosDist.MagnitudeSqr() < nextToCompare.MagnitudeSqr()) {\n\t\tm_vehDoor = CAR_DOOR_RR;\n\t\tposToOpen = rrPos;\n\t}\n\treturn canEnter;\n}\n\nvoid\nCPed::GoToNearestDoor(CVehicle *veh)\n{\n\tCVector posToOpen;\n\tGetNearestDoor(veh, posToOpen);\n\tSetSeek(posToOpen, 0.5f);\n\tSetMoveState(PEDMOVE_RUN);\n}\n\n// Unused\nvoid CPed::PedSetGetInCarPositionCB(CAnimBlendAssociation* assoc, void* arg)\n{\n\tCPed* pPed = (CPed*)arg;\n\tCMatrix mat(pPed->GetMatrix());\n\tCVehicle* pVehicle = pPed->m_pMyVehicle;\n\tconst CVector& offset = (pVehicle->bIsVan && (pPed->m_vehDoor == CAR_DOOR_RR || pPed->m_vehDoor == CAR_DOOR_LR)) ? vecPedVanRearDoorAnimOffset : vecPedCarDoorAnimOffset;\n\tCVector position = Multiply3x3(mat, offset) + pPed->GetPosition();\n\tCPedPlacement::FindZCoorForPed(&position);\n\tpPed->SetMoveSpeed(0.0f, 0.0f, 0.0f);\n\tpPed->SetPosition(position);\n}\n\nvoid\nCPed::SetAnimOffsetForEnterOrExitVehicle(void)\n{\n\t// FIX_BUGS: If there were no translations on enter anims, there were overflows all over this function.\n\n\tint vanBlock = CAnimManager::GetAnimationBlockIndex(\"van\");\n\tint bikesBlock = CAnimManager::GetAnimationBlockIndex(\"bikes\");\n\tint bikevBlock = CAnimManager::GetAnimationBlockIndex(\"bikev\");\n\tint bikehBlock = CAnimManager::GetAnimationBlockIndex(\"bikeh\");\n\tint bikedBlock = CAnimManager::GetAnimationBlockIndex(\"biked\");\n\tCStreaming::RequestAnim(vanBlock, STREAMFLAGS_DEPENDENCY);\n\tCStreaming::RequestAnim(bikesBlock, STREAMFLAGS_DEPENDENCY);\n\tCStreaming::RequestAnim(bikevBlock, STREAMFLAGS_DEPENDENCY);\n\tCStreaming::RequestAnim(bikehBlock, STREAMFLAGS_DEPENDENCY);\n\tCStreaming::RequestAnim(bikedBlock, STREAMFLAGS_DEPENDENCY);\n\tCStreaming::LoadAllRequestedModels(false);\n\tCAnimManager::AddAnimBlockRef(vanBlock);\n\tCAnimManager::AddAnimBlockRef(bikesBlock);\n\tCAnimManager::AddAnimBlockRef(bikevBlock);\n\tCAnimManager::AddAnimBlockRef(bikehBlock);\n\tCAnimManager::AddAnimBlockRef(bikedBlock);\n\n\tCAnimBlendHierarchy *enterAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_STD, ANIM_STD_JACKEDCAR_LHS)->hierarchy;\n\tCAnimBlendSequence *seq = enterAssoc->sequences;\n\tCAnimManager::UncompressAnimation(enterAssoc);\n\tif (seq->numFrames > 0) {\n\t\tif (!seq->HasTranslation())\n\t\t\tvecPedDraggedOutCarAnimOffset = CVector(0.0f, 0.0f, 0.0f);\n\t\telse {\n\t\t\tKeyFrameTrans *lastFrame = (KeyFrameTrans*)seq->GetKeyFrame(seq->numFrames - 1);\n\t\t\tvecPedDraggedOutCarAnimOffset = lastFrame->translation;\n\t\t}\n\t}\n\n\tenterAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_STD, ANIM_STD_CAR_GET_IN_LHS)->hierarchy;\n\tseq = enterAssoc->sequences;\n\tCAnimManager::UncompressAnimation(enterAssoc);\n\tif (seq->numFrames > 0) {\n\t\tif (!seq->HasTranslation())\n\t\t\tvecPedCarDoorAnimOffset = CVector(0.0f, 0.0f, 0.0f);\n\t\telse {\n\t\t\tKeyFrameTrans *lastFrame = (KeyFrameTrans*)seq->GetKeyFrame(seq->numFrames - 1);\n\t\t\tvecPedCarDoorAnimOffset = lastFrame->translation;\n\t\t}\n\t}\n\n\tenterAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_STD, ANIM_STD_CAR_GET_IN_LO_LHS)->hierarchy;\n\tseq = enterAssoc->sequences;\n\tCAnimManager::UncompressAnimation(enterAssoc);\n\tif (seq->numFrames > 0) {\n\t\tif (!seq->HasTranslation())\n\t\t\tvecPedCarDoorLoAnimOffset = CVector(0.0f, 0.0f, 0.0f);\n\t\telse {\n\t\t\tKeyFrameTrans *lastFrame = (KeyFrameTrans*)seq->GetKeyFrame(seq->numFrames - 1);\n\t\t\tvecPedCarDoorLoAnimOffset = lastFrame->translation;\n\t\t}\n\t}\n\n\tenterAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_STD, ANIM_STD_QUICKJACKED)->hierarchy;\n\tseq = enterAssoc->sequences;\n\tCAnimManager::UncompressAnimation(enterAssoc);\n\tif (seq->numFrames > 0) {\n\t\tif (!seq->HasTranslation())\n\t\t\tvecPedQuickDraggedOutCarAnimOffset = CVector(0.0f, 0.0f, 0.0f);\n\t\telse {\n\t\t\tKeyFrameTrans *lastFrame = (KeyFrameTrans*)seq->GetKeyFrame(seq->numFrames - 1);\n\t\t\tvecPedQuickDraggedOutCarAnimOffset = lastFrame->translation;\n\t\t}\n\t}\n\n\tenterAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_VAN, ANIM_STD_VAN_GET_IN_REAR_LHS)->hierarchy;\n\tseq = enterAssoc->sequences;\n\tCAnimManager::UncompressAnimation(enterAssoc);\n\tif (seq->numFrames > 0) {\n\t\tif (!seq->HasTranslation())\n\t\t\tvecPedVanRearDoorAnimOffset = CVector(0.0f, 0.0f, 0.0f);\n\t\telse {\n\t\t\tKeyFrameTrans *lastFrame = (KeyFrameTrans*)seq->GetKeyFrame(seq->numFrames - 1);\n\t\t\tvecPedVanRearDoorAnimOffset = lastFrame->translation;\n\t\t}\n\t}\n\n\tenterAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_STD, ANIM_STD_TRAIN_GETOUT)->hierarchy;\n\tseq = enterAssoc->sequences;\n\tCAnimManager::UncompressAnimation(enterAssoc);\n\tif (seq->numFrames > 0) {\n\t\tif (!seq->HasTranslation())\n\t\t\tvecPedTrainDoorAnimOffset = CVector(0.0f, 0.0f, 0.0f);\n\t\telse {\n\t\t\tKeyFrameTrans *lastFrame = (KeyFrameTrans*)seq->GetKeyFrame(seq->numFrames - 1);\n\t\t\tvecPedTrainDoorAnimOffset = lastFrame->translation;\n\t\t}\n\t}\n\n\tenterAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_BIKE_STANDARD, ANIM_BIKE_JUMPON_LHS)->hierarchy;\n\tseq = enterAssoc->sequences;\n\tCAnimManager::UncompressAnimation(enterAssoc);\n\tif (seq->numFrames > 0) {\n\t\tif (!seq->HasTranslation())\n\t\t\tvecPedStdBikeJumpRhsAnimOffset = CVector(0.0f, 0.0f, 0.0f);\n\t\telse {\n\t\t\tKeyFrameTrans* lastFrame = (KeyFrameTrans*)seq->GetKeyFrame(seq->numFrames - 1);\n\t\t\tvecPedStdBikeJumpRhsAnimOffset = lastFrame->translation;\n\t\t}\n\t}\n\n\tenterAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_BIKE_VESPA, ANIM_BIKE_JUMPON_LHS)->hierarchy;\n\tseq = enterAssoc->sequences;\n\tCAnimManager::UncompressAnimation(enterAssoc);\n\tif (seq->numFrames > 0) {\n\t\tif (!seq->HasTranslation())\n\t\t\tvecPedVespaBikeJumpRhsAnimOffset = CVector(0.0f, 0.0f, 0.0f);\n\t\telse {\n\t\t\tKeyFrameTrans* lastFrame = (KeyFrameTrans*)seq->GetKeyFrame(seq->numFrames - 1);\n\t\t\tvecPedVespaBikeJumpRhsAnimOffset = lastFrame->translation;\n\t\t}\n\t}\n\n\tenterAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_BIKE_HARLEY, ANIM_BIKE_JUMPON_LHS)->hierarchy;\n\tseq = enterAssoc->sequences;\n\tCAnimManager::UncompressAnimation(enterAssoc);\n\tif (seq->numFrames > 0) {\n\t\tif (!seq->HasTranslation())\n\t\t\tvecPedHarleyBikeJumpRhsAnimOffset = CVector(0.0f, 0.0f, 0.0f);\n\t\telse {\n\t\t\tKeyFrameTrans* lastFrame = (KeyFrameTrans*)seq->GetKeyFrame(seq->numFrames - 1);\n\t\t\tvecPedHarleyBikeJumpRhsAnimOffset = lastFrame->translation;\n\t\t}\n\t}\n\n\tenterAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_BIKE_DIRT, ANIM_BIKE_JUMPON_LHS)->hierarchy;\n\tseq = enterAssoc->sequences;\n\tCAnimManager::UncompressAnimation(enterAssoc);\n\tif (seq->numFrames > 0) {\n\t\tif (!seq->HasTranslation())\n\t\t\tvecPedDirtBikeJumpRhsAnimOffset = CVector(0.0f, 0.0f, 0.0f);\n\t\telse {\n\t\t\tKeyFrameTrans* lastFrame = (KeyFrameTrans*)seq->GetKeyFrame(seq->numFrames - 1);\n\t\t\tvecPedDirtBikeJumpRhsAnimOffset = lastFrame->translation;\n\t\t}\n\t}\n\n\tenterAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_BIKE_HARLEY, ANIM_BIKE_KICK)->hierarchy;\n\tseq = enterAssoc->sequences;\n\tCAnimManager::UncompressAnimation(enterAssoc);\n\tif (seq->numFrames > 0) {\n\t\tif (!seq->HasTranslation())\n\t\t\tvecPedBikeKickAnimOffset = CVector(0.0f, 0.0f, 0.0f);\n\t\telse {\n\t\t\tKeyFrameTrans* lastFrame = (KeyFrameTrans*)seq->GetKeyFrame(seq->numFrames - 1);\n\t\t\tvecPedBikeKickAnimOffset = lastFrame->translation;\n\t\t}\n\t}\n\n\tCAnimManager::RemoveAnimBlockRef(vanBlock);\n\tCAnimManager::RemoveAnimBlockRef(bikesBlock);\n\tCAnimManager::RemoveAnimBlockRef(bikevBlock);\n\tCAnimManager::RemoveAnimBlockRef(bikehBlock);\n\tCAnimManager::RemoveAnimBlockRef(bikedBlock);\n}\n\nvoid\nCPed::PedSetQuickDraggedOutCarPositionCB(CAnimBlendAssociation *animAssoc, void *arg)\n{\n\tCPed *ped = (CPed*)arg;\n\n\tCVehicle *veh = ped->m_pMyVehicle;\n\n\tCVector finalPos;\n\tCVector draggedOutOffset;\n\n\tCMatrix pedMat(ped->GetMatrix());\n\tped->bUsesCollision = true;\n\tped->RestartNonPartialAnims();\n\tdraggedOutOffset = vecPedQuickDraggedOutCarAnimOffset;\n\tif (ped->m_vehDoor == CAR_DOOR_RF || ped->m_vehDoor == CAR_DOOR_RR)\n\t\tdraggedOutOffset.x = -draggedOutOffset.x;\n\n\tfinalPos = Multiply3x3(pedMat, draggedOutOffset) + ped->GetPosition();\n\tCPedPlacement::FindZCoorForPed(&finalPos);\n\tped->m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);\n\tped->SetPosition(finalPos);\n\n\tif (veh) {\n\t\tped->m_fRotationDest = veh->GetForward().Heading() - HALFPI;\n\t\tped->m_fRotationCur = ped->m_fRotationDest;\n\t\tped->CalculateNewOrientation();\n\n\t\tif (!veh->IsRoomForPedToLeaveCar(ped->m_vehDoor, &vecPedQuickDraggedOutCarAnimOffset))\n\t\t\tped->PositionPedOutOfCollision();\n\t}\n\n\tif (!ped->CanSetPedState())\n\t\treturn;\n\n\tped->SetIdle();\n\tif (veh) {\n\t\tif (ped->bFleeAfterExitingCar) {\n\t\t\tped->bFleeAfterExitingCar = false;\n\t\t\tped->SetFlee(veh->GetPosition(), 14000);\n\n\t\t} else if (ped->bWanderPathAfterExitingCar) {\n\t\t\tped->SetWanderPath(CGeneral::GetRandomNumberInRange(0.0f, 8.0f));\n\t\t\tped->bWanderPathAfterExitingCar = false;\n\n\t\t} else if (ped->bGonnaKillTheCarJacker) {\n\t\t\tped->bGonnaKillTheCarJacker = false;\n\t\t\tif (ped->m_pedInObjective && CGeneral::GetRandomNumber() & 1) {\n\t\t\t\tif (ped->m_objective != OBJECTIVE_KILL_CHAR_ON_FOOT)\n\t\t\t\t\tped->SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, ped->m_pedInObjective);\n\n\t\t\t} else {\n\t\t\t\tCPed *driver = veh->pDriver;\n\t\t\t\tif (!driver || driver == ped || driver->IsPlayer() && CTheScripts::IsPlayerOnAMission()) {\n\t\t\t\t\tped->SetFlee(veh->GetPosition(), 14000);\n\t\t\t\t} else {\n\t\t\t\t\tped->ClearObjective();\n\t\t\t\t\tped->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, veh);\n\t\t\t\t}\n\t\t\t\tped->bUsePedNodeSeek = true;\n\t\t\t\tped->m_pNextPathNode = nil;\n\t\t\t\tped->Say(SOUND_PED_FLEE_RUN);\n\t\t\t}\n\t\t} else if (ped->m_pedStats->m_temper > ped->m_pedStats->m_fear\n\t\t\t&& ped->CharCreatedBy != MISSION_CHAR && veh->VehicleCreatedBy != MISSION_VEHICLE\n\t\t\t&& veh->pDriver && veh->pDriver->IsPlayer()\n\t\t\t&& !CTheScripts::IsPlayerOnAMission()) {\n\t\t\tped->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, veh);\n\n\t\t} else if (ped->m_pedStats->m_temper > ped->m_pedStats->m_fear\n\t\t\t&& ped->CharCreatedBy != MISSION_CHAR && veh->VehicleCreatedBy != MISSION_VEHICLE\n\t\t\t&& !veh->pDriver && FindPlayerPed()->m_carInObjective == veh\n\t\t\t&& !CTheScripts::IsPlayerOnAMission()) {\n\t\t\tped->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, veh);\n\n\t\t} else {\n\t\t\tped->SetFindPathAndFlee(veh->GetPosition(), 10000);\n\t\t\tif (CGeneral::GetRandomNumber() & 1 || ped->m_pedStats->m_fear > 70) {\n\t\t\t\tped->SetMoveState(PEDMOVE_SPRINT);\n\t\t\t\tped->Say(SOUND_PED_FLEE_SPRINT);\n\t\t\t} else {\n\t\t\t\tped->Say(SOUND_PED_FLEE_RUN);\n\t\t\t}\n\t\t}\n\t}\n\tif (ped->m_nLastPedState == PED_IDLE)\n\t\tped->m_nLastPedState = PED_WANDER_PATH;\n}\n\nvoid\nCPed::PedSetDraggedOutCarPositionCB(CAnimBlendAssociation* animAssoc, void* arg)\n{\n\tCPed *ped = (CPed*)arg;\n\n\tped->bUsesCollision = true;\n\tped->RestartNonPartialAnims();\n\n\tCMatrix pedMat(ped->GetMatrix());\n\tCVector draggedOutOffset;\n\tif (ped->m_pMyVehicle && ped->m_pMyVehicle->IsBike()) {\n\t\tAssocGroupId animGroup = ((CBike*)ped->m_pMyVehicle)->m_bikeAnimType;\n\t\tswitch (animGroup) {\n\t\t\tcase ASSOCGRP_BIKE_VESPA:\n\t\t\t\tdraggedOutOffset = vecPedVespaBikeJumpRhsAnimOffset;\n\t\t\t\tbreak;\n\t\t\tcase ASSOCGRP_BIKE_HARLEY:\n\t\t\t\tdraggedOutOffset = vecPedHarleyBikeJumpRhsAnimOffset;\n\t\t\t\tbreak;\n\t\t\tcase ASSOCGRP_BIKE_DIRT:\n\t\t\t\tdraggedOutOffset = vecPedDirtBikeJumpRhsAnimOffset;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tdraggedOutOffset = vecPedStdBikeJumpRhsAnimOffset;\n\t\t\t\tbreak;\n\t\t}\n\t} else {\n\t\tdraggedOutOffset = vecPedDraggedOutCarAnimOffset;\n\t}\n\tif (ped->m_vehDoor == CAR_DOOR_RF || ped->m_vehDoor == CAR_DOOR_RR)\n\t\tdraggedOutOffset.x = -draggedOutOffset.x;\n\n\tCVector posAfterBeingDragged = Multiply3x3(pedMat, draggedOutOffset);\n\tposAfterBeingDragged += ped->GetPosition();\n\tCPedPlacement::FindZCoorForPed(&posAfterBeingDragged);\n\tped->m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);\n\tped->SetPosition(posAfterBeingDragged);\n\n\tif (ped->m_pMyVehicle && !ped->m_pMyVehicle->IsBike() && !ped->m_pMyVehicle->IsRoomForPedToLeaveCar(ped->m_vehDoor, &vecPedDraggedOutCarAnimOffset)) {\n\t\tped->PositionPedOutOfCollision();\n\t}\n\n\tif (!ped->CanSetPedState())\n\t\treturn;\n\t\n\tif (!ped->m_pMyVehicle) {\n\t\tped->SetIdle();\n\t\tped->SetGetUp();\n\t\treturn;\n\t}\n\n\tCPed *driver = ped->m_pMyVehicle->pDriver;\n\n\tif (ped->IsPlayer()) {\n\t\tped->SetIdle();\n\n\t} else if (ped->bFleeAfterExitingCar) {\n\t\tped->bFleeAfterExitingCar = false;\n\t\tped->SetFlee(ped->m_pMyVehicle->GetPosition(), 4000);\n\n\t} else if (ped->bWanderPathAfterExitingCar) {\n\t\tped->SetWanderPath(CGeneral::GetRandomNumberInRange(0.0f, 8.0f));\n\t\tped->bWanderPathAfterExitingCar = false;\n\n\t} else if (ped->bGonnaKillTheCarJacker) {\n\t\t// Kill objective is already set at this point.\n\n\t\tped->bGonnaKillTheCarJacker = false;\n\t\tif (!ped->m_pedInObjective || !(CGeneral::GetRandomNumber() & 1)) {\n\t\t\tif (!driver || driver == ped || driver->IsPlayer() && CTheScripts::IsPlayerOnAMission()) {\n\t\t\t\tped->SetPedState(PED_NONE);\n\t\t\t\tped->m_nLastPedState = PED_NONE;\n\t\t\t\tped->SetFlee(ped->m_pMyVehicle->GetPosition(), 4000);\n\t\t\t} else {\n\t\t\t\tped->ClearObjective();\n\t\t\t\tped->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, ped->m_pMyVehicle);\n\t\t\t}\n\t\t}\n\n\t} else if (ped->m_pedStats->m_temper > ped->m_pedStats->m_fear && ped->CharCreatedBy != MISSION_CHAR\n\t\t&& ped->m_pMyVehicle->VehicleCreatedBy != MISSION_VEHICLE && driver\n\t\t&& driver->IsPlayer() && !CTheScripts::IsPlayerOnAMission()) {\n\t\tped->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, ped->m_pMyVehicle);\n\n\t} else if (ped->m_pedStats->m_temper > ped->m_pedStats->m_fear && ped->CharCreatedBy != MISSION_CHAR\n\t\t&& ped->m_pMyVehicle->VehicleCreatedBy != MISSION_VEHICLE && !driver\n\t\t&& FindPlayerPed()->m_carInObjective == ped->m_pMyVehicle && !CTheScripts::IsPlayerOnAMission())\n\t\tped->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, ped->m_pMyVehicle);\n\telse {\n\t\tped->SetPedState(PED_NONE);\n\t\tped->m_nLastPedState = PED_NONE;\n\t\tped->SetFindPathAndFlee(ped->m_pMyVehicle->GetPosition(), 10000);\n\t}\n\tped->SetGetUp();\n}\n\nuint8\nCPed::GetNearestTrainDoor(CVehicle *train, CVector &doorPos)\n{\n\tGetNearestTrainPedPosition(train, doorPos);\n/*\n\t// Not used.\n\tCVehicleModelInfo* trainModel = (CVehicleModelInfo*)CModelInfo::GetModelInfo(train->m_modelIndex);\n\tCMatrix trainMat = CMatrix(train->GetMatrix());\n\n\tdoorPos = trainModel->m_positions[m_vehDoor];\n\tdoorPos.x -= 1.5f;\n\tdoorPos = Multiply3x3(trainMat, doorPos);\n\tdoorPos += train->GetPosition();\n*/\n\treturn 1;\n}\n\nuint8\nCPed::GetNearestTrainPedPosition(CVehicle *train, CVector &enterPos)\n{\n\tCVector enterStepOffset;\n\tCVehicleModelInfo *trainModel = (CVehicleModelInfo *)CModelInfo::GetModelInfo(train->GetModelIndex());\n\tCMatrix trainMat = CMatrix(train->GetMatrix());\n\tCVector leftEntryPos, rightEntryPos, midEntryPos;\n\tfloat distLeftEntry, distRightEntry, distMidEntry;\n\n\t// enterStepOffset = vecPedCarDoorAnimOffset;\n\tenterStepOffset = CVector(1.5f, 0.0f, 0.0f);\n\n\tif (train->pPassengers[TRAIN_POS_LEFT_ENTRY]) {\n\t\tdistLeftEntry = 999.0f;\n\t} else {\n\t\tleftEntryPos = trainModel->m_positions[TRAIN_POS_LEFT_ENTRY] - enterStepOffset;\n\t\tleftEntryPos = Multiply3x3(trainMat, leftEntryPos);\n\t\tleftEntryPos += train->GetPosition();\n\t\tdistLeftEntry = (leftEntryPos - GetPosition()).Magnitude();\n\t}\n\n\tif (train->pPassengers[TRAIN_POS_MID_ENTRY]) {\n\t\tdistMidEntry = 999.0f;\n\t} else {\n\t\tmidEntryPos = trainModel->m_positions[TRAIN_POS_MID_ENTRY] - enterStepOffset;\n\t\tmidEntryPos = Multiply3x3(trainMat, midEntryPos);\n\t\tmidEntryPos += train->GetPosition();\n\t\tdistMidEntry = (midEntryPos - GetPosition()).Magnitude();\n\t}\n\n\tif (train->pPassengers[TRAIN_POS_RIGHT_ENTRY]) {\n\t\tdistRightEntry = 999.0f;\n\t} else {\n\t\trightEntryPos = trainModel->m_positions[TRAIN_POS_RIGHT_ENTRY] - enterStepOffset;\n\t\trightEntryPos = Multiply3x3(trainMat, rightEntryPos);\n\t\trightEntryPos += train->GetPosition();\n\t\tdistRightEntry = (rightEntryPos - GetPosition()).Magnitude();\n\t}\n\n\tif (distMidEntry < distLeftEntry) {\n\t\tif (distMidEntry < distRightEntry) {\n\t\t\tenterPos = midEntryPos;\n\t\t\tm_vehDoor = TRAIN_POS_MID_ENTRY;\n\t\t} else {\n\t\t\tenterPos = rightEntryPos;\n\t\t\tm_vehDoor = TRAIN_POS_RIGHT_ENTRY;\n\t\t}\n\t} else if (distRightEntry < distLeftEntry) {\n\t\tenterPos = rightEntryPos;\n\t\tm_vehDoor = TRAIN_POS_RIGHT_ENTRY;\n\t} else {\n\t\tenterPos = leftEntryPos;\n\t\tm_vehDoor = TRAIN_POS_LEFT_ENTRY;\n\t}\n\n\treturn 1;\n}\n\nvoid\nCPed::PedSetInTrainCB(CAnimBlendAssociation* animAssoc, void* arg)\n{\n\tCPed *ped = (CPed*)arg;\n\tCTrain *veh = (CTrain*)ped->m_pMyVehicle;\n\n\tif (!veh)\n\t\treturn;\n\n\tped->bInVehicle = true;\n\tped->SetPedState(PED_DRIVING);\n\tped->RestorePreviousObjective();\n\tped->SetMoveState(PEDMOVE_STILL);\n\tveh->AddPassenger(ped);\n}\n\n#ifdef GTA_TRAIN\nvoid\nCPed::SetEnterTrain(CVehicle *train, uint32 unused)\n{\n\tif (m_nPedState == PED_ENTER_TRAIN || !((CTrain*)train)->Doors[0].IsFullyOpen())\n\t\treturn;\n\n\t/*\n\t// Not used\n\tCVector enterPos;\n\tGetNearestTrainPedPosition(train, enterPos);\n\t*/\n\tm_fRotationCur = train->GetForward().Heading() - HALFPI;\n\tm_pMyVehicle = train;\n\tm_pMyVehicle->RegisterReference((CEntity **) &m_pMyVehicle);\n\n\tSetPedState(PED_ENTER_TRAIN);\n\tm_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_TRAIN_GETIN, 4.0f);\n\tm_pVehicleAnim->SetFinishCallback(PedSetInTrainCB, this);\n\tbUsesCollision = false;\n\tLineUpPedWithTrain();\n\tif (IsPlayer()) {\n\t\tif (((CPlayerPed*)this)->m_bAdrenalineActive)\n\t\t\t((CPlayerPed*)this)->ClearAdrenaline();\n\t}\n}\n\nvoid\nCPed::EnterTrain(void)\n{\n\tLineUpPedWithTrain();\n}\n\nvoid\nCPed::SetPedPositionInTrain(void)\n{\n\tLineUpPedWithTrain();\n}\n\nvoid\nCPed::LineUpPedWithTrain(void)\n{\n\tCVector lineUpPos;\n\tCVehicleModelInfo *trainModel = (CVehicleModelInfo *)CModelInfo::GetModelInfo(m_pMyVehicle->GetModelIndex());\n\tCVector enterOffset(1.5f, 0.0f, -0.2f);\n\n\tm_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);\n\tm_fRotationCur = m_pMyVehicle->GetForward().Heading() - HALFPI;\n\tm_fRotationDest = m_fRotationCur;\n\n\tif (!bInVehicle) {\n\t\tGetNearestTrainDoor(m_pMyVehicle, lineUpPos);\n\t\tlineUpPos.z += 0.2f;\n\t} else {\n\t\tif (m_pMyVehicle->pPassengers[TRAIN_POS_LEFT_ENTRY] == this) {\n\n\t\t\tlineUpPos = trainModel->m_positions[TRAIN_POS_LEFT_ENTRY] - enterOffset;\n\n\t\t} else if (m_pMyVehicle->pPassengers[TRAIN_POS_MID_ENTRY] == this) {\n\n\t\t\tlineUpPos = trainModel->m_positions[TRAIN_POS_MID_ENTRY] - enterOffset;\n\n\t\t} else if (m_pMyVehicle->pPassengers[TRAIN_POS_RIGHT_ENTRY] == this) {\n\n\t\t\tlineUpPos = trainModel->m_positions[TRAIN_POS_RIGHT_ENTRY] - enterOffset;\n\t\t}\n\t\tlineUpPos = Multiply3x3(m_pMyVehicle->GetMatrix(), lineUpPos);\n\t\tlineUpPos += m_pMyVehicle->GetPosition();\n\t}\n\n\tif (m_pVehicleAnim) {\n\t\tfloat percentageLeft = m_pVehicleAnim->GetTimeLeft() / m_pVehicleAnim->hierarchy->totalLength;\n\t\tlineUpPos += (GetPosition() - lineUpPos) * percentageLeft;\n\t}\n\n\tSetPosition(lineUpPos);\n\tSetHeading(m_fRotationCur);\n}\n\nvoid\nCPed::SetExitTrain(CVehicle* train)\n{\n\tif (m_nPedState == PED_EXIT_TRAIN || train->GetStatus() != STATUS_TRAIN_NOT_MOVING || !((CTrain*)train)->Doors[0].IsFullyOpen())\n\t\treturn;\n\n\t/*\n\t// Not used\n\tCVector exitPos;\n\tGetNearestTrainPedPosition(train, exitPos);\n\t*/\n\tSetPedState(PED_EXIT_TRAIN);\n\tm_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_TRAIN_GETOUT, 4.0f);\n\tm_pVehicleAnim->SetFinishCallback(PedSetOutTrainCB, this);\n\tbUsesCollision = false;\n\tLineUpPedWithTrain();\n}\n\nvoid\nCPed::ExitTrain(void)\n{\n\tLineUpPedWithTrain();\n}\n\nvoid\nCPed::PedSetOutTrainCB(CAnimBlendAssociation *animAssoc, void *arg)\n{\n\tCPed *ped = (CPed*)arg;\n\n\tCVehicle *veh = ped->m_pMyVehicle;\n\n\tif (ped->m_pVehicleAnim)\n\t\tped->m_pVehicleAnim->blendDelta = -1000.0f;\n\n\tped->bUsesCollision = true;\n\tped->m_pVehicleAnim = nil;\n\tped->bInVehicle = false;\n\tped->SetPedState(PED_IDLE);\n\tped->RestorePreviousObjective();\n\tped->SetMoveState(PEDMOVE_STILL);\n\n\tCMatrix pedMat(ped->GetMatrix());\n\tped->m_fRotationCur = HALFPI + veh->GetForward().Heading();\n\tped->m_fRotationDest = ped->m_fRotationCur;\n\tCVector posAfterExit = Multiply3x3(pedMat, vecPedTrainDoorAnimOffset);\n\tposAfterExit += ped->GetPosition();\n\tCPedPlacement::FindZCoorForPed(&posAfterExit);\n\tped->m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);\n\tped->SetPosition(posAfterExit);\n\tped->SetHeading(ped->m_fRotationCur);\n\tveh->RemovePassenger(ped);\n}\n#endif\n\nvoid\nCPed::RegisterThreatWithGangPeds(CEntity *attacker)\n{\n\tCPed *attackerPed = nil;\n\tif ((CharCreatedBy == MISSION_CHAR && bIsPlayerFriend && (attacker == FindPlayerPed() || attacker == FindPlayerVehicle()))\n\t\t|| (attacker && m_leader == attacker)\n\t\t|| (m_nPedType == PEDTYPE_GANG7 && attacker == FindPlayerPed()))\n\t\treturn;\n\n\tif (attacker) {\n\t\tif (m_objective != OBJECTIVE_KILL_CHAR_ON_FOOT && m_objective != OBJECTIVE_KILL_CHAR_ANY_MEANS) {\n\t\t\tif (attacker->IsPed()) {\n\t\t\t\tattackerPed = (CPed*)attacker;\n\t\t\t} else if (attacker->IsVehicle()) {\n\t\t\t\tattackerPed = ((CVehicle*)attacker)->pDriver;\n\t\t\t\tif (!attackerPed)\n\t\t\t\t\treturn;\n\t\t\t} else\n\t\t\t\treturn;\n\n\t\t\tif (attackerPed && (attackerPed->IsPlayer() || attackerPed->IsGangMember())) {\n\t\t\t\tfor (int i = 0; i < m_numNearPeds; ++i) {\n\t\t\t\t\tCPed *nearPed = m_nearPeds[i];\n\t\t\t\t\tif (nearPed->IsPointerValid()) {\n\t\t\t\t\t\tif (nearPed->CharCreatedBy == RANDOM_CHAR && nearPed != this && nearPed->m_nPedType == m_nPedType)\n\t\t\t\t\t\t\tnearPed->m_fearFlags |= CPedType::GetFlag(attackerPed->m_nPedType);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (attackerPed && attackerPed->IsPlayer() && (attackerPed->m_nPedState == PED_CARJACK || attackerPed->bInVehicle)) {\n\t\tif (!attackerPed->m_pMyVehicle || attackerPed->m_pMyVehicle->GetModelIndex() != MI_TOPFUN) {\n\t\t\tint16 lastVehicle;\n\t\t\tCEntity *vehicles[8];\n\t\t\tCWorld::FindObjectsInRange(GetPosition(), 30.0f, true, &lastVehicle, 6, vehicles, false, true, false, false, false);\n\n\t\t\tif (lastVehicle > 8)\n\t\t\t\tlastVehicle = 8;\n\n\t\t\tfor (int j = 0; j < lastVehicle; ++j) {\n\t\t\t\tCVehicle *nearVeh = (CVehicle*) vehicles[j];\n\n\t\t\t\tif (nearVeh->VehicleCreatedBy != MISSION_VEHICLE) {\n\t\t\t\t\tCPed *nearVehDriver = nearVeh->pDriver;\n\n\t\t\t\t\tif (nearVehDriver && nearVehDriver != this && nearVehDriver->m_nPedType == m_nPedType && nearVehDriver->CharCreatedBy == RANDOM_CHAR) {\n\n\t\t\t\t\t\tif (nearVeh->IsVehicleNormal() && nearVeh->IsCar()) {\n\t\t\t\t\t\t\tnearVeh->AutoPilot.m_nCruiseSpeed = GAME_SPEED_TO_CARAI_SPEED * nearVeh->pHandling->Transmission.fMaxCruiseVelocity * 0.8f;\n\t\t\t\t\t\t\tnearVeh->AutoPilot.m_nCarMission = MISSION_RAMPLAYER_FARAWAY;\n\t\t\t\t\t\t\tnearVeh->SetStatus(STATUS_PHYSICS);\n\t\t\t\t\t\t\tnearVeh->AutoPilot.m_nTempAction = TEMPACT_NONE;\n\t\t\t\t\t\t\tnearVeh->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n// Some helper function which doesn't exist in og game.\ninline void\nSelectClosestNodeForSeek(CPed *ped, CPathNode *node, CVector2D closeDist, CVector2D farDist, CPathNode *closeNode, CPathNode *closeNode2, int runCount = 3)\n{\n\tfor (int i = 0; i < node->numLinks; i++) {\n\n\t\tCPathNode *testNode = &ThePaths.m_pathNodes[ThePaths.ConnectedNode(i + node->firstLink)];\n\n\t\tif (testNode && testNode != closeNode && testNode != closeNode2) {\n\t\t\tCVector2D posDiff(ped->m_vecSeekPos - testNode->GetPosition());\n\t\t\tfloat dist = posDiff.MagnitudeSqr();\n\n\t\t\tif (farDist.MagnitudeSqr() > dist) {\n\n\t\t\t\tif (closeDist.MagnitudeSqr() > dist) {\n\t\t\t\t\tped->m_pNextPathNode = (closeNode2 ? closeNode2 : testNode);\n\t\t\t\t\tfarDist = posDiff;\n\t\t\t\t} else {\n\t\t\t\t\tped->m_pNextPathNode = closeNode;\n\t\t\t\t\tcloseDist = posDiff;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (--runCount > 0)\n\t\t\t\tSelectClosestNodeForSeek(ped, testNode, closeDist, farDist, closeNode, (closeNode2 ? closeNode2 : testNode), runCount);\n\t\t}\n\t}\n}\n\nbool\nCPed::FindBestCoordsFromNodes(CVector unused, CVector *bestCoords)\n{\n\tif (m_pNextPathNode || !bUsePedNodeSeek)\n\t\treturn false;\n\n\tconst CVector &ourPos = GetPosition();\n\n\tint closestNodeId = ThePaths.FindNodeClosestToCoors(GetPosition(), 1, 999999.9f);\n\n\tCVector seekObjPos = m_vecSeekPos;\n\tseekObjPos.z += 1.0f;\n\n\tif (CWorld::GetIsLineOfSightClear(ourPos, seekObjPos, true, false, false, true, false, false, false))\n\t\treturn false;\n\n\tm_pNextPathNode = nil;\n\n\tCVector2D seekPosDist (m_vecSeekPos - ourPos);\n\n\tCPathNode *closestNode = &ThePaths.m_pathNodes[closestNodeId];\n\tCVector2D closeDist(m_vecSeekPos - closestNode->GetPosition());\n\n\tSelectClosestNodeForSeek(this, closestNode, closeDist, seekPosDist, closestNode, nil);\n\n\tif (m_pNextPathNode) {\n\n\t\t// Function above decided that directly going to next node makes more sense then seeking the object.\n\t\tCVector correctedCoords = CPathFind::TakeWidthIntoAccountForWandering(m_pNextPathNode, m_randomSeed);\n\n\t\tif ((correctedCoords - ourPos).MagnitudeSqr2D() < seekPosDist.MagnitudeSqr()) {\n\t\t\t*bestCoords = CPathFind::TakeWidthIntoAccountForWandering(m_pNextPathNode, m_randomSeed);\n\t\t\treturn true;\n\t\t}\n\t\tm_pNextPathNode = nil;\n\t}\n\n\treturn false;\n}\n\nbool\nCPed::DuckAndCover(void)\n{\n\tif (!m_pedInObjective || CTimer::GetTimeInMilliseconds() <= m_duckAndCoverTimer)\n\t\treturn false;\n\n\tif (bKindaStayInSamePlace){\n\n\t\tif (CTimer::GetTimeInMilliseconds() <= m_leaveCarTimer) {\n\t\t\tif (!m_pLookTarget || m_pLookTarget != m_pedInObjective) {\n\t\t\t\tm_pLookTarget = m_pedInObjective;\n\t\t\t\tm_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget);\n\t\t\t}\n\t\t\tif (!bIsAimingGun)\n\t\t\t\tSetAimFlag(m_pedInObjective);\n\n\t\t} else {\n\t\t\tbKindaStayInSamePlace = false;\n\t\t\tif (bIsDucking)\n\t\t\t\tClearDuck(true);\n\n\t\t\tbCrouchWhenShooting = false;\n\t\t\tbDuckAndCover = false;\n\t\t\tm_headingRate = 10.0f;\n\t\t\tm_duckAndCoverTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(20000,30000);\n\t\t\tif (m_pSeekTarget && m_pSeekTarget->IsVehicle())\n\t\t\t\t((CVehicle*)m_pSeekTarget)->m_numPedsUseItAsCover--;\n\t\t}\n\t\treturn false;\n\t}\n\t\n\tint16 lastVehicle = 0;\n\tCEntity* vehicles[8];\n\n\tbool justDucked = false;\n\tCVehicle *foundVeh = nil;\n\tfloat maxDist = 225.0f;\n\tif (bIsDucking)\n\t\tClearDuck(true);\n\n\tbCrouchWhenShooting = false;\n\tbool duckingWithoutVeh = false;\n\tif (CTimer::GetTimeInMilliseconds() > m_leaveCarTimer) {\n\n\t\tfor(int i = 0; i < 6; i++) {\n\t\t\tCPlayerPed *player = (CPlayerPed*)m_pedInObjective;\n\n\t\t\tif (player->m_pPedAtSafePos[i] == this) {\n\t\t\t\tduckingWithoutVeh = true;\n\t\t\t\tCVector &safePos = player->m_vecSafePos[i];\n\t\t\t\tbool notRunningToSafePos = false;\n\n\t\t\t\tif (m_vecSeekPos.x != safePos.x && m_vecSeekPos.y != safePos.y && m_vecSeekPos.z != safePos.z)\n\t\t\t\t\tnotRunningToSafePos = true;\n\n\t\t\t\tif (!notRunningToSafePos) {\n\t\t\t\t\tCVector target = player->m_vecSafePos[i];\n\t\t\t\t\tSetSeek(target, 1.0f);\n\t\t\t\t\tduckingWithoutVeh = true;\n\t\t\t\t\tm_attackTimer = CTimer::GetTimeInMilliseconds() + 6000;\n\t\t\t\t\tbDuckAndCover = true;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (!duckingWithoutVeh) {\n\t\t\tfor (int i = 0; i < 6; i++) {\n\t\t\t\tCPlayerPed* player = (CPlayerPed*)m_pedInObjective;\n\t\t\t\tif (!player->m_pPedAtSafePos[i] && player->m_vecSafePos[i].x != 0.0f) {\n\t\t\t\t\tplayer->m_pPedAtSafePos[i] = this;\n\t\t\t\t\tCVector target = player->m_vecSafePos[i];\n\t\t\t\t\tSetSeek(target, 1.0f);\n\t\t\t\t\tm_headingRate = 15.0f;\n\t\t\t\t\tClearPointGunAt();\n\t\t\t\t\tduckingWithoutVeh = 1;\n\t\t\t\t\tbIsRunning = true;\n\t\t\t\t\tbDuckAndCover = true;\n\t\t\t\t\tjustDucked = true;\n\t\t\t\t\tm_leaveCarTimer = CTimer::GetTimeInMilliseconds() + 500;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (!duckingWithoutVeh) {\n\t\t\tCVector pos = GetPosition();\n\t\t\tCWorld::FindObjectsInRange(pos, CHECK_NEARBY_THINGS_MAX_DIST, true, &lastVehicle, 6, vehicles, false, true, false, false, false);\n\t\t}\n\n\t\tfor (int i = 0; i < lastVehicle; i++) {\n\t\t\tCVehicle *veh = (CVehicle*) vehicles[i];\n\t\t\tif (veh->IsCar() && veh->m_vecMoveSpeed.Magnitude() <= 0.02f\n\t\t\t\t&& !veh->bIsBus && !veh->bIsVan && !veh->bIsBig\n\t\t\t\t&& veh->m_numPedsUseItAsCover < 3) {\n\n\t\t\t\tfloat dist = (GetPosition() - veh->GetPosition()).MagnitudeSqr();\n\t\t\t\tif (dist < maxDist) {\n\t\t\t\t\tmaxDist = dist;\n\t\t\t\t\tfoundVeh = veh;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (foundVeh) {\n\t\t\t// Unused.\n\t\t\t// CVector lfWheelPos, rfWheelPos;\n\t\t\t// foundVeh->GetComponentWorldPosition(CAR_WHEEL_RF, rfWheelPos);\n\t\t\t// foundVeh->GetComponentWorldPosition(CAR_WHEEL_LF, lfWheelPos);\n\t\t\tCVector rightSide, leftSide;\n\n\t\t\t// 3 persons can use the car as cover. Found the correct position for us.\n\t\t\tif (foundVeh->m_numPedsUseItAsCover == 2) {\n\t\t\t\trightSide = CVector(1.5f, -0.5f, 0.0f);\n\t\t\t\tleftSide = CVector(-1.5f, -0.5f, 0.0f);\n\t\t\t} else if (foundVeh->m_numPedsUseItAsCover == 1) {\n\t\t\t\trightSide = CVector(1.5f, 0.5f, 0.0f);\n\t\t\t\tleftSide = CVector(-1.5f, 0.5f, 0.0f);\n\t\t\t} else if (foundVeh->m_numPedsUseItAsCover == 0) {\n\t\t\t\trightSide = CVector(1.5f, 0.0f, 0.0f);\n\t\t\t\tleftSide = CVector(-1.5f, 0.0f, 0.0f);\n\t\t\t}\n\n\t\t\tCMatrix vehMatrix(foundVeh->GetMatrix());\n\t\t\tCVector duckAtRightSide = Multiply3x3(vehMatrix, rightSide) + foundVeh->GetPosition();\n\n\t\t\tCVector duckAtLeftSide = Multiply3x3(vehMatrix, leftSide) + foundVeh->GetPosition();\n\n\t\t\tCVector distWithPedRightSide = m_pedInObjective->GetPosition() - duckAtRightSide;\n\t\t\tCVector distWithPedLeftSide = m_pedInObjective->GetPosition() - duckAtLeftSide;\n\n\t\t\tCVector duckPos;\n\t\t\tif (distWithPedRightSide.MagnitudeSqr() <= distWithPedLeftSide.MagnitudeSqr())\n\t\t\t\tduckPos = duckAtLeftSide;\n\t\t\telse\n\t\t\t\tduckPos = duckAtRightSide;\n\n\t\t\tif (CWorld::TestSphereAgainstWorld(duckPos, 0.5f, nil, true, true, true, false, false, false)) {\n\t\t\t\tSetSeek(duckPos, 1.0f);\n\t\t\t\tm_headingRate = 15.0f;\n\t\t\t\tbIsRunning = true;\n\t\t\t\tbDuckAndCover = true;\n\t\t\t\tjustDucked = true;\n\t\t\t\tm_leaveCarTimer = CTimer::GetTimeInMilliseconds() + 500;\n\t\t\t\tif (foundVeh->bIsLawEnforcer) {\n\t\t\t\t\tm_carInObjective = foundVeh;\n\t\t\t\t\tm_carInObjective->RegisterReference((CEntity**)&m_carInObjective);\n\t\t\t\t}\n\t\t\t\tm_pSeekTarget = foundVeh;\n\t\t\t\tm_pSeekTarget->RegisterReference((CEntity**)&m_pSeekTarget);\n\t\t\t\tClearPointGunAt();\n\t\t\t} else {\n\t\t\t\tm_duckAndCoverTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(10000, 15000);\n\t\t\t\tbDuckAndCover = false;\n\t\t\t}\n\t\t} else if (!duckingWithoutVeh) {\n\t\t\tbDuckAndCover = false;\n\t\t}\n\t}\n\n\tif (!justDucked && !bDuckAndCover)\n\t\treturn false;\n\t\n\tif (!Seek()) {\n\t\tif (m_nMoveState == PEDMOVE_STILL) {\n\t\t\tbDuckAndCover = false;\n\t\t\treturn false;\n\t\t} else\n\t\t\treturn true;\n\t}\n\n\tbKindaStayInSamePlace = true;\n\tbDuckAndCover = false;\n\tm_vecSeekPos = CVector(0.0f, 0.0f, 0.0f);\n\tif (m_pSeekTarget && m_pSeekTarget->IsVehicle())\n\t\t((CVehicle*)m_pSeekTarget)->m_numPedsUseItAsCover++;\n\t\n\tSetIdle();\n\tSetMoveState(PEDMOVE_STILL);\n\tSetMoveAnim();\n\tif (!m_pLookTarget || m_pLookTarget != m_pedInObjective) {\n\t\tm_pLookTarget = m_pedInObjective;\n\t\tm_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget);\n\t}\n\n\tm_leaveCarTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(3000, 6000);\n\tbCrouchWhenShooting = true;\n\tSetDuck(CGeneral::GetRandomNumberInRange(2000, 5000), true);\n\treturn false;\n}\n\nCVector\nCPed::GetPositionToOpenCarDoor(CVehicle *veh, uint32 component, float offset)\n{\t\n\tCVector doorPos;\n\tCMatrix vehMat(veh->GetMatrix());\n\n\tif (veh->IsBike()) {\n\t\tCVehicleModelInfo* vehModel = (CVehicleModelInfo*)CModelInfo::GetModelInfo(veh->GetModelIndex());\n\t\tCVector vehDoorOffset;\n\t\tCBike* bike = (CBike*)veh;\n\t\tdoorPos = vehModel->GetFrontSeatPosn();\n\n\t\tif (component == CAR_WINDSCREEN) {\n\t\t\treturn bike->GetMatrix() * (doorPos + vecPedBikeKickAnimOffset);\n\t\t} else {\n\t\t\tswitch (bike->m_bikeAnimType) {\n\t\t\tcase ASSOCGRP_BIKE_VESPA:\n\t\t\t\tvehDoorOffset = vecPedVespaBikeJumpRhsAnimOffset;\n\t\t\t\tbreak;\n\t\t\tcase ASSOCGRP_BIKE_HARLEY:\n\t\t\t\tvehDoorOffset = vecPedHarleyBikeJumpRhsAnimOffset;\n\t\t\t\tbreak;\n\t\t\tcase ASSOCGRP_BIKE_DIRT:\n\t\t\t\tvehDoorOffset = vecPedDirtBikeJumpRhsAnimOffset;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tvehDoorOffset = vecPedStdBikeJumpRhsAnimOffset;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tvehDoorOffset.x += offset * bike->pHandling->fSeatOffsetDistance;\n\t\t\tif (component == CAR_DOOR_LR || component == CAR_DOOR_RR) {\n\t\t\t\tdoorPos = vehModel->m_positions[CAR_POS_BACKSEAT];\n\t\t\t}\n\n\t\t\tif (component == CAR_DOOR_LR || component == CAR_DOOR_LF)\n\t\t\t\tvehDoorOffset.x *= -1.f;\n\n\t\t\tCVector correctedPos;\n\t\t\tbike->GetCorrectedWorldDoorPosition(correctedPos, vehDoorOffset, doorPos);\n\t\t\treturn correctedPos;\n\t\t}\n\t}\n\tdoorPos = Multiply3x3(vehMat, GetLocalPositionToOpenCarDoor(veh, component, offset));\n\n\treturn veh->GetPosition() + doorPos;\n}\n\nCVector\nCPed::GetLocalPositionToOpenCarDoor(CVehicle *veh, uint32 component, float seatPosMult)\n{\n\tCVehicleModelInfo *vehModel; \n\tCVector vehDoorPos;\n\tCVector vehDoorOffset;\n\tfloat seatOffset;\n\n\tvehModel = (CVehicleModelInfo *)CModelInfo::GetModelInfo(veh->GetModelIndex());\n\n\tif (veh->IsBike()) {\n\t\tCBike *bike = (CBike*)veh;\n\t\tvehDoorPos = vehModel->GetFrontSeatPosn();\n\n\t\tif (component == CAR_WINDSCREEN) {\n\t\t\treturn bike->GetMatrix() * (vehDoorPos + vecPedBikeKickAnimOffset);\n\t\t} else {\n\t\t\tswitch (bike->m_bikeAnimType) {\n\t\t\t\tcase ASSOCGRP_BIKE_VESPA:\n\t\t\t\t\tvehDoorOffset = vecPedVespaBikeJumpRhsAnimOffset;\n\t\t\t\t\tbreak;\n\t\t\t\tcase ASSOCGRP_BIKE_HARLEY:\n\t\t\t\t\tvehDoorOffset = vecPedHarleyBikeJumpRhsAnimOffset;\n\t\t\t\t\tbreak;\n\t\t\t\tcase ASSOCGRP_BIKE_DIRT:\n\t\t\t\t\tvehDoorOffset = vecPedDirtBikeJumpRhsAnimOffset;\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tvehDoorOffset = vecPedStdBikeJumpRhsAnimOffset;\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tfloat xOffsetFromAnim = vehDoorOffset.x + seatPosMult * bike->pHandling->fSeatOffsetDistance;\n\t\t\tif (component == CAR_DOOR_LR || component == CAR_DOOR_RR) {\n\t\t\t\tvehDoorPos = vehModel->m_positions[CAR_POS_BACKSEAT];\n\t\t\t}\n\n\t\t\tif (component == CAR_DOOR_LR || component == CAR_DOOR_LF)\n\t\t\t\txOffsetFromAnim *= -1.f;\n\n\t\t\treturn bike->GetMatrix() * (vehDoorPos + CVector(xOffsetFromAnim, vehDoorOffset.y, vehDoorOffset.z));\n\t\t}\n\t} else {\n\t\tif (veh->bIsVan && (component == CAR_DOOR_LR || component == CAR_DOOR_RR)) {\n\t\t\tseatOffset = 0.0f;\n\t\t\tvehDoorOffset = vecPedVanRearDoorAnimOffset;\n\t\t} else {\n\t\t\tseatOffset = veh->pHandling->fSeatOffsetDistance * seatPosMult;\n\t\t\tif (veh->bLowVehicle) {\n\t\t\t\tvehDoorOffset = vecPedCarDoorLoAnimOffset;\n\t\t\t} else {\n\t\t\t\tvehDoorOffset = vecPedCarDoorAnimOffset;\n\t\t\t}\n\t\t}\n\n\t\tswitch (component) {\n\t\t\tcase CAR_DOOR_RF:\n\t\t\t\tvehDoorPos = vehModel->GetFrontSeatPosn();\n\t\t\t\tvehDoorPos.x += seatOffset;\n\t\t\t\tvehDoorOffset.x = -vehDoorOffset.x;\n\t\t\t\tbreak;\n\n\t\t\tcase CAR_DOOR_RR:\n\t\t\t\tvehDoorPos = vehModel->m_positions[CAR_POS_BACKSEAT];\n\t\t\t\tvehDoorPos.x += seatOffset;\n\t\t\t\tvehDoorOffset.x = -vehDoorOffset.x;\n\t\t\t\tbreak;\n\n\t\t\tcase CAR_DOOR_LF:\n\t\t\t\tvehDoorPos = vehModel->GetFrontSeatPosn();\n\t\t\t\tvehDoorPos.x = -(vehDoorPos.x + seatOffset);\n\t\t\t\tbreak;\n\n\t\t\tcase CAR_DOOR_LR:\n\t\t\t\tvehDoorPos = vehModel->m_positions[CAR_POS_BACKSEAT];\n\t\t\t\tvehDoorPos.x = -(vehDoorPos.x + seatOffset);\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tvehDoorPos = vehModel->GetFrontSeatPosn();\n\t\t\t\tvehDoorOffset = CVector(0.0f, 0.0f, 0.0f);\n\t\t}\n\t\treturn vehDoorPos - vehDoorOffset;\n\t}\n}\n\n// TODO: what is this parameter for?\nvoid\nCPed::SetDuck(uint32 time, bool sth)\n{\n\tif (bIsDucking || CTimer::GetTimeInMilliseconds() <= m_duckTimer && !sth) {\n\t\tif (sth && CTimer::GetTimeInMilliseconds() + time > m_duckTimer)\n\t\t\tm_duckTimer = CTimer::GetTimeInMilliseconds() + time;\n\t\treturn;\n\t}\n\n\tCAnimBlendAssociation *duckAssoc;\n\tif (bCrouchWhenShooting) {\n\t\tduckAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_DUCK_WEAPON, 4.0f);\n\t\tduckAssoc->flags &= ~ASSOC_FADEOUTWHENDONE;\n\t\tbIsDucking = true;\n\t\tm_duckTimer = CTimer::GetTimeInMilliseconds() + time;\n\t} else {\n\t\tCAnimBlendAssociation *duckAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_DUCK_DOWN);\n\t\tif (!duckAssoc || duckAssoc->blendDelta < 0.0f) {\n\t\t\tCAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_DUCK_DOWN, 4.0f);\n\t\t\tbIsDucking = true;\n\t\t\tm_duckTimer = CTimer::GetTimeInMilliseconds() + time;\n\t\t}\n\t}\n}\n\nvoid\nCPed::Duck(void)\n{\n\tif (CTimer::GetTimeInMilliseconds() > m_duckTimer)\n\t\tClearDuck();\n\telse if (bIsDucking && bCrouchWhenShooting) {\n\t\tCWeaponInfo *weapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);\n\t\tCAnimBlendAssociation *crouchAnim = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_DUCK_WEAPON);\n\t\tif (!crouchAnim) {\n\t\t\tif(GetCrouchFireAnim(weapon))\n\t\t\t\tcrouchAnim = RpAnimBlendClumpGetAssociation(GetClump(), GetCrouchFireAnim(weapon));\n\t\t}\n\t\tif (!crouchAnim) {\n\t\t\tif(GetCrouchReloadAnim(weapon))\n\t\t\t\tcrouchAnim = RpAnimBlendClumpGetAssociation(GetClump(), GetCrouchReloadAnim(weapon));\n\t\t}\n\t\tif (!crouchAnim) {\n\t\t\tbIsDucking = false;\n#if defined FIX_BUGS || defined FREE_CAM\n\t\t\tif (IsPlayer())\n\t\t\t\tbCrouchWhenShooting = false;\n#endif\n\t\t}\n\t}\n}\n\nvoid\nCPed::ClearDuck(bool clearTimer)\n{\n\tCAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_DUCK_DOWN);\n\tif (!animAssoc) {\n\t\tanimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_DUCK_LOW);\n\t}\n\tif (!animAssoc) {\n\t\tanimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_DUCK_WEAPON);\n\t}\n\n\tif (animAssoc) {\n\t\tanimAssoc->flags |= ASSOC_DELETEFADEDOUT;\n\t\tanimAssoc->blendDelta = -4.0f;\n\t}\n\tbIsDucking = false;\n\n\tif (clearTimer) {\n\t\tm_duckTimer = 0;\n\t}\n}\n\nvoid\nCPed::InformMyGangOfAttack(CEntity *attacker)\n{\n\tCPed *attackerPed;\n\n\tif (m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT || m_objective == OBJECTIVE_KILL_CHAR_ANY_MEANS)\n\t\treturn;\n\n\tif (attacker->IsPed()) {\n\t\tattackerPed = (CPed*)attacker;\n\t} else {\n\t\tif (!attacker->IsVehicle())\n\t\t\treturn;\n\n\t\tattackerPed = ((CVehicle*)attacker)->pDriver;\n\t\tif (!attackerPed)\n\t\t\treturn;\n\t}\n\n\tif (attackerPed->m_nPedType == PEDTYPE_COP)\n\t\treturn;\n\n\tfor (int i = 0; i < m_numNearPeds; i++)\t{\n\t\tCPed *nearPed = m_nearPeds[i];\n\t\tif (nearPed && nearPed != this) {\n\t\t\tCPed *leader = nearPed->m_leader;\n\t\t\tif (leader && leader == this && nearPed->m_pedStats->m_fear < nearPed->m_pedStats->m_temper) {\n\t\t\t\tnearPed->SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, attackerPed);\n\t\t\t\tnearPed->SetObjectiveTimer(30000);\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nCPed::PedAnimDoorCloseRollingCB(CAnimBlendAssociation* animAssoc, void* arg)\n{\n\tCPed* ped = (CPed*)arg;\n\n\tCAutomobile* veh = (CAutomobile*)(ped->m_pMyVehicle);\n\n\tif (animAssoc)\n\t\tanimAssoc->blendDelta = -1000.0f;\n\n\tif (veh->bLowVehicle) {\n\t\tveh->ProcessOpenDoor(CAR_DOOR_LF, ANIM_STD_CAR_CLOSE_DOOR_ROLLING_LO_LHS, 1.0f);\n\t} else {\n\t\tveh->ProcessOpenDoor(CAR_DOOR_LF, ANIM_STD_CAR_CLOSE_DOOR_ROLLING_LHS, 1.0f);\n\t}\n\n\tveh->m_nGettingOutFlags &= ~CAR_DOOR_FLAG_LF;\n\n\tif (veh->Damage.GetDoorStatus(DOOR_FRONT_LEFT) == DOOR_STATUS_SWINGING)\n\t\tveh->Damage.SetDoorStatus(DOOR_FRONT_LEFT, DOOR_STATUS_OK);\n}\n\nvoid\nCPed::SetSeekBoatPosition(CVehicle *boat)\n{\n\tif (m_nPedState == PED_SEEK_IN_BOAT || boat->pDriver || !IsPedInControl())\n\t\treturn;\n\n\tSetStoredState();\n\tm_carInObjective = boat;\n\tm_carInObjective->RegisterReference((CEntity **) &m_carInObjective);\n\tm_pMyVehicle = boat;\n\tm_pMyVehicle->RegisterReference((CEntity **) &m_pMyVehicle);\n\tm_distanceToCountSeekDone = 0.5f;\n\tSetPedState(PED_SEEK_IN_BOAT);\n}\n\nvoid\nCPed::SeekBoatPosition(void)\n{\n\tif (m_carInObjective && !m_carInObjective->pDriver) {\n\t\tCVehicleModelInfo *boatModel = m_carInObjective->GetModelInfo();\n\n\t\tCVector enterOffset;\n\t\tenterOffset = boatModel->GetFrontSeatPosn();\n\t\tenterOffset.x = 0.0f;\n\t\tCMatrix boatMat(m_carInObjective->GetMatrix());\n\t\tSetMoveState(PEDMOVE_WALK);\n\t\tm_vecSeekPos = boatMat * enterOffset;\n\t\tif (Seek()) {\n\t\t\t// We arrived to the boat\n\t\t\tm_vehDoor = 0;\n\t\t\tSetEnterCar(m_carInObjective, 0);\n\t\t}\n\t} else\n\t\tRestorePreviousState();\n}\n\nbool\nCPed::IsRoomToBeCarJacked(void)\n{\n\tif (!m_pMyVehicle)\n\t\treturn false;\n\n\tCVector offset;\n\tif (m_pMyVehicle->IsBike()) {\n\t\toffset = vecPedStdBikeJumpRhsAnimOffset;\n\t} else if (m_pMyVehicle->bLowVehicle || m_nPedType == PEDTYPE_COP) {\n\t\toffset = vecPedDraggedOutCarAnimOffset;\n\t} else {\n\t\toffset = vecPedQuickDraggedOutCarAnimOffset;\n\t}\n\n\toffset.z = 0.0f;\n\tif (m_pMyVehicle->IsRoomForPedToLeaveCar(CAR_DOOR_LF, &offset)) {\n\t\treturn true;\n\t}\n\n\treturn false;\n}\n\nvoid\nCPed::AddInCarAnims(CVehicle* car, bool isDriver)\n{\n\tif (car->IsBoat()) {\n\t\tif (car->pHandling->Flags & HANDLING_SIT_IN_BOAT) {\n\t\t\tm_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_SIT, 100.0f);\n\t\t} else {\n\t\t\tm_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_BOAT_DRIVE, 100.0f);\n\t\t}\n\t} else if (car->IsBike()) {\n\t\tif (isDriver) {\n\t\t\tm_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ((CBike*)car)->m_bikeAnimType, ANIM_BIKE_RIDE, 100.0f);\n\t\t} else {\n\t\t\tm_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ((CBike*)car)->m_bikeAnimType, ANIM_BIKE_RIDE_P, 100.0f);\n\t\t}\n\t} else {\n\t\tif (isDriver) {\n\t\t\tif (car->bLowVehicle) {\n\t\t\t\tm_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_SIT_LO, 100.0f);\n\t\t\t} else {\n\t\t\t\tm_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_SIT, 100.0f);\n\t\t\t}\n\t\t} else {\n\t\t\tif (car->bLowVehicle) {\n\t\t\t\tm_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_SIT_P_LO, 100.0f);\n\t\t\t} else {\n\t\t\t\tm_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_SIT_P, 100.0f);\n\t\t\t}\n\t\t}\n\t}\n\n\tStopNonPartialAnims();\n}\n\nvoid\nCPed::RemoveDrivebyAnims()\n{\n\tCAnimBlendAssociation *animAssoc;\n\n\tAnimationId LeftAnim = ANIM_STD_CAR_DRIVEBY_LEFT;\n\tAnimationId RightAnim = ANIM_STD_CAR_DRIVEBY_RIGHT;\n\n\tif (m_pMyVehicle->pHandling->Flags & HANDLING_IS_BIKE) {\n\t\tLeftAnim = ANIM_BIKE_DRIVEBY_RHS;\n\t\tRightAnim = ANIM_BIKE_DRIVEBY_LHS;\n\t} else if (m_pMyVehicle->bLowVehicle) {\n\t\tLeftAnim = ANIM_STD_CAR_DRIVEBY_LEFT_LO;\n\t\tRightAnim = ANIM_STD_CAR_DRIVEBY_RIGHT_LO;\n\t}\n\n\tanimAssoc = RpAnimBlendClumpGetAssociation((RpClump*)m_rwObject, ANIM_BIKE_DRIVEBY_RHS);\n\tif (animAssoc)\n\t\tanimAssoc->blendDelta = -1000.0f;\n\tanimAssoc = RpAnimBlendClumpGetAssociation((RpClump*)m_rwObject, ANIM_BIKE_DRIVEBY_LHS);\n\tif (animAssoc)\n\t\tanimAssoc->blendDelta = -1000.0f;\n\tanimAssoc = RpAnimBlendClumpGetAssociation((RpClump*)m_rwObject, ANIM_BIKE_DRIVEBY_FORWARD);\n\tif (animAssoc)\n\t\tanimAssoc->blendDelta = -1000.0f;\n}\n\nvoid\nCPed::RemoveInCarAnims(void)\n{\n\tCAnimBlendAssociation* assoc;\n\n\tfor (assoc = RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_DRIVING); assoc;\n\t\tassoc = RpAnimBlendGetNextAssociation(assoc, ASSOC_DRIVING)) {\n\t\tassoc->flags |= ASSOC_DELETEFADEDOUT;\n\t\tassoc->blendDelta = -1000.0f;\n\t}\n}\n\nbool\nCPed::PositionPedOutOfCollision(void)\n{\n\tCVehicle *veh = m_pMyVehicle;\n\tif (!veh)\n\t\treturn false;\n\n\tif (bDonePositionOutOfCollision)\n\t\treturn true;\n\n\tbool foundAPos = false;\n\tCColModel *vehCol = veh->GetColModel();\n\tCVector vehPos = veh->GetPosition();\n\tCVector ourPos = GetPosition();\n\tCVector newPos = ourPos;\n\tCWorld::pIgnoreEntity = veh;\n\tbUsesCollision = false;\n\tbJustCheckCollision = true;\n\tm_vecMoveSpeed = CVector(0.f, 0.f, 0.f);\n\tif (veh->IsOnItsSide()) {\n\t\t// Top of the veh.\n\t\tnewPos = vehPos;\n\t\tnewPos.z = FEET_OFFSET + vehCol->boundingBox.max.x + vehPos.z;\n\t\tGetMatrix().SetTranslate(newPos);\n\t\tif (!CheckCollision()) {\n\t\t\tif (CWorld::GetIsLineOfSightClear(vehPos, newPos, true, false, false, true, false, false, false))\n\t\t\t\tfoundAPos = true;\n\t\t}\n\n\t} else if (m_vehDoor != 0) {\n\t\t// Try the normal way\n\t\tCVector pos = GetPositionToOpenCarDoor(m_pMyVehicle, m_vehDoor);\n\t\tnewPos = pos;\n\t\tGetMatrix().SetTranslate(newPos);\n\t\tif (!CheckCollision()) {\n\t\t\tif (CWorld::GetIsLineOfSightClear(vehPos, newPos, true, false, false, true, false, false, false))\n\t\t\t\tfoundAPos = true;\n\t\t}\n\t}\n\n\tfloat vehRelativeExitX = vehCol->boundingBox.min.x - 0.355f;\n\tif (m_vehDoor == CAR_DOOR_RF || m_vehDoor == CAR_DOOR_RR)\n\t\tvehRelativeExitX = 0.355f + vehCol->boundingBox.max.x;\n\n\tif (!foundAPos) {\n\t\t// Check sides of veh., respective to seat column-veh. center difference(why?)\n\t\tfloat exitOffset = vehRelativeExitX - DotProduct(ourPos - vehPos, veh->GetRight());\n\t\tnewPos = exitOffset * veh->GetRight() + ourPos;\n\t\tGetMatrix().SetTranslate(newPos);\n\t\tif (!CheckCollision()) {\n\t\t\tif (CWorld::GetIsLineOfSightClear(vehPos, newPos, true, false, false, true, false, false, false))\n\t\t\t\tfoundAPos = true;\n\t\t}\n\t}\n\tif (!foundAPos) {\n\t\t// Iterate through sections of veh. length + static offset on X\n\t\tfloat minY = vehCol->boundingBox.min.y;\n\t\tfloat ySection = (vehCol->boundingBox.max.y - minY) / 3.f;\n\t\tfor (int i = 0; i < 4; i++) {\n\t\t\tfloat fwdMult = i * ySection + minY;\n\t\t\tnewPos = vehRelativeExitX * veh->GetRight() + fwdMult * veh->GetForward() + vehPos;\n\t\t\tGetMatrix().SetTranslate(newPos);\n\t\t\tif (!CheckCollision()) {\n\t\t\t\tif (CWorld::GetIsLineOfSightClear(vehPos, newPos, true, false, false, true, false, false, false)) {\n\t\t\t\t\tfoundAPos = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tif (!foundAPos) {\n\t\t// Back of veh.\n\t\tnewPos = (vehCol->boundingBox.min.y - 0.355f) * veh->GetForward() + vehPos;\n\t\tGetMatrix().SetTranslate(newPos);\n\t\tif (!CheckCollision()) {\n\t\t\tif (CWorld::GetIsLineOfSightClear(vehPos, newPos, true, false, false, true, false, false, false))\n\t\t\t\tfoundAPos = true;\n\t\t}\n\t}\n\tif (!foundAPos) {\n\t\t// Front of veh.\n\t\tnewPos = (0.355f + vehCol->boundingBox.max.y) * veh->GetForward() + vehPos;\n\t\tGetMatrix().SetTranslate(newPos);\n\t\tif (!CheckCollision()) {\n\t\t\tif (CWorld::GetIsLineOfSightClear(vehPos, newPos, true, false, false, true, false, false, false))\n\t\t\t\tfoundAPos = true;\n\t\t}\n\t}\n\tif (!foundAPos) {\n\t\t// Opposite X side + back\n\t\tnewPos = vehCol->boundingBox.min.y * veh->GetForward() + vehPos - vehRelativeExitX * veh->GetRight();\n\t\tGetMatrix().SetTranslate(newPos);\n\t\tif (!CheckCollision()) {\n\t\t\tif (CWorld::GetIsLineOfSightClear(vehPos, newPos, true, false, false, true, false, false, false))\n\t\t\t\tfoundAPos = true;\n\t\t}\n\t}\n\tif (!foundAPos) {\n\t\t// Opposite X side + front\n\t\tnewPos = vehCol->boundingBox.max.y * veh->GetForward() + vehPos - vehRelativeExitX * veh->GetRight();\n\t\tGetMatrix().SetTranslate(newPos);\n\t\tif (!CheckCollision()) {\n\t\t\tif (CWorld::GetIsLineOfSightClear(vehPos, newPos, true, false, false, true, false, false, false))\n\t\t\t\tfoundAPos = true;\n\t\t}\n\t}\n\tif (!foundAPos) {\n\t\t// Top of veh.\n\t\tif (veh->m_vehType == 0) {\n\t\t\tnewPos = vehCol->boundingBox.max.z * veh->GetUp() + vehPos;\n\t\t\tnewPos.z += FEET_OFFSET;\n\t\t\tGetMatrix().SetTranslate(newPos);\n\t\t\tif (!CheckCollision()) {\n\t\t\t\tif (CWorld::GetIsLineOfSightClear(vehPos, newPos, true, false, false, true, false, false, false))\n\t\t\t\t\tfoundAPos = true;\n\t\t\t}\n\t\t}\n\t}\n\tm_vecMoveSpeed = CVector(0.f, 0.f, 0.f);\n\tm_vecTurnSpeed = CVector(0.f, 0.f, 0.f);\n\tveh->m_vecMoveSpeed = CVector(0.f, 0.f, 0.f);\n\tveh->m_vecTurnSpeed = CVector(0.f, 0.f, 0.f);\n\tCWorld::pIgnoreEntity = nil;\n\tbUsesCollision = true;\n\tbJustCheckCollision = false;\n\tbDonePositionOutOfCollision = true;\n\tif (foundAPos)\n\t\treturn true;\n\tint foundNode = ThePaths.FindNodeClosestToCoors(vehPos, PATH_PED, 999999.9f, true, false, false, false);\n\tif (foundNode < 0)\n\t\treturn false;\n\tnewPos = ThePaths.m_pathNodes[foundNode].GetPosition();\n\tCPedPlacement::FindZCoorForPed(&newPos);\n\tGetMatrix().SetTranslate(newPos);\n\tSetHeading(m_pMyVehicle->GetForward().Heading());\n\treturn true;\n}\n\n// \"Any\" means he shouldn't have to be in vehicle.\nbool\nCPed::PositionAnyPedOutOfCollision(void)\n{\n\tCVehicle *veh;\n\tCVector posNearVeh;\n\tCVector posSomewhereClose;\n\tbool putNearVeh = false;\n\tbool putSomewhereClose = false;\n\tint smallestDistNearVeh = 999;\n\tint smallestDistSomewhereClose = 999;\n\n\tCVector potentialPos;\n\tpotentialPos.y = GetPosition().y - 3.5f;\n\tpotentialPos.z = GetPosition().z;\n\n\tfor (int yTry = 0; yTry < 15; yTry++) {\n\t\tpotentialPos.x = GetPosition().x - 3.5f;\n\n\t\tfor (int xTry = 0; xTry < 15; xTry++) {\n\t\t\tCPedPlacement::FindZCoorForPed(&potentialPos);\n\t\t\tif (!CWorld::TestSphereAgainstWorld(potentialPos, 0.6f, this, true, false, false, true, false, false)) {\n\t\t\t\tfloat potentialChangeSqr = (potentialPos - GetPosition()).MagnitudeSqr();\n\t\t\t\tveh = (CVehicle*)CWorld::TestSphereAgainstWorld(potentialPos, 0.6f, this, false, true, false, false, false, false);\n\t\t\t\tif (veh) {\n\t\t\t\t\tif (potentialChangeSqr < smallestDistNearVeh) {\n\t\t\t\t\t\tposNearVeh = potentialPos;\n\t\t\t\t\t\tputNearVeh = true;\n\t\t\t\t\t\tsmallestDistNearVeh = potentialChangeSqr;\n\t\t\t\t\t}\n\t\t\t\t} else if (potentialChangeSqr < smallestDistSomewhereClose) {\n\t\t\t\t\tsmallestDistSomewhereClose = potentialChangeSqr;\n\t\t\t\t\tposSomewhereClose = potentialPos;\n\t\t\t\t\tputSomewhereClose = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\tpotentialPos.x += 0.5f;\n\t\t}\n\t\tpotentialPos.y += 0.5f;\n\t}\n\n\tif (!putSomewhereClose && !putNearVeh)\n\t\treturn false;\n\n\t// We refrain from using posNearVeh, probably because of it may be top of the vehicle.\n\tif (putSomewhereClose) {\n\t\tSetPosition(posSomewhereClose);\n\t} else {\n\t\tCVector vehSize = veh->GetModelInfo()->GetColModel()->boundingBox.max;\n\t\tposNearVeh.z += vehSize.z;\n\t\tSetPosition(posNearVeh);\n\t}\n\treturn true;\n}\n\nbool\nCPed::WarpPedToNearLeaderOffScreen(void)\n{\n\tbool teleported = false;\n\tif (GetIsOnScreen() || m_leaveCarTimer > CTimer::GetTimeInMilliseconds())\n\t\treturn false;\n\n\tCVector warpToPos = m_leader->GetPosition();\n\tCVector distVec = warpToPos - GetPosition();\n\tfloat halfOfDist = distVec.Magnitude() * 0.5f;\n\tCVector halfNormalizedDist = distVec / halfOfDist;\n\n\tCVector appropriatePos = GetPosition();\n\tint tryCount = Min(10, (int)halfOfDist);\n\tfor (int i = 0; i < tryCount; ++i) {\n\t\tappropriatePos += halfNormalizedDist;\n\t\tCVector zCorrectedPos = appropriatePos;\n\t\tCPedPlacement::FindZCoorForPed(&zCorrectedPos);\n\n\t\tif (Abs(zCorrectedPos.z - warpToPos.z) < 3.0f || Abs(zCorrectedPos.z - appropriatePos.z) < 3.0f) {\n\t\t\tappropriatePos.z = zCorrectedPos.z;\n\t\t\tif (!TheCamera.IsSphereVisible(appropriatePos, 0.6f)\n\t\t\t\t&& CWorld::GetIsLineOfSightClear(appropriatePos, warpToPos, true, true, false, true, false, false, false)\n\t\t\t\t&& !CWorld::TestSphereAgainstWorld(appropriatePos, 0.6f, this, true, true, false, true, false, false)) {\n\t\t\t\tteleported = true;\n\t\t\t\tTeleport(appropriatePos);\n\t\t\t}\n\t\t}\n\t}\n\tm_leaveCarTimer = CTimer::GetTimeInMilliseconds() + 3000;\n\treturn teleported;\n}\n\nbool\nCPed::WarpPedToNearEntityOffScreen(CEntity *warpTo)\n{\n\tbool teleported = false;\n\tif (GetIsOnScreen() || m_leaveCarTimer > CTimer::GetTimeInMilliseconds())\n\t\treturn false;\n\n\tCVector warpToPos = warpTo->GetPosition();\n\tCVector distVec = warpToPos - GetPosition();\n\tfloat halfOfDist = distVec.Magnitude() * 0.5f;\n\tCVector halfNormalizedDist = distVec / halfOfDist;\n\n\tCVector appropriatePos = GetPosition();\n\tint tryCount = Min(10, (int)halfOfDist);\n\tfor (int i = 0; i < tryCount; ++i) {\n\t\tappropriatePos += halfNormalizedDist;\n\t\tCVector zCorrectedPos = appropriatePos;\n\t\tCPedPlacement::FindZCoorForPed(&zCorrectedPos);\n\n\t\tif (Abs(zCorrectedPos.z - warpToPos.z) < 3.0f || Abs(zCorrectedPos.z - appropriatePos.z) < 3.0f) {\n\t\t\tappropriatePos.z = zCorrectedPos.z;\n\t\t\tif (!TheCamera.IsSphereVisible(appropriatePos, 0.6f, &TheCamera.GetCameraMatrix())\n\t\t\t\t&& CWorld::GetIsLineOfSightClear(appropriatePos, warpToPos, true, true, false, true, false, false, false)\n\t\t\t\t&& !CWorld::TestSphereAgainstWorld(appropriatePos, 0.6f, this, true, true, false, true, false, false)) {\n\t\t\t\tteleported = true;\n\t\t\t\tTeleport(appropriatePos);\n\t\t\t}\n\t\t}\n\t}\n\tm_leaveCarTimer = CTimer::GetTimeInMilliseconds() + 3000;\n\treturn teleported;\n}\n\nint32\nCPed::KillCharOnFootArmed(CVector &ourPos, CVector &targetPos, CVector &distWithTarget)\n{\n\tbool killPlayerInNoPoliceZone = false;\n\tif (m_pedInObjective->IsPlayer() && CCullZones::NoPolice())\n\t\tkillPlayerInNoPoliceZone = true;\n\n\tif (!bNotAllowedToDuck || killPlayerInNoPoliceZone) {\n\t\tif (m_nPedType == PEDTYPE_COP && !m_pedInObjective->GetWeapon()->IsTypeMelee())\n\t\t\tbNotAllowedToDuck = true;\n\t} else {\n\t\tif (!m_pedInObjective->bInVehicle) {\n\t\t\tif (m_pedInObjective->GetWeapon()->IsTypeMelee()) {\n\t\t\t\tbNotAllowedToDuck = false;\n\t\t\t\tbCrouchWhenShooting = false;\n\t\t\t} else if (DuckAndCover()) {\n\t\t\t\treturn CANT_ATTACK;\n\t\t\t}\n\t\t} else {\n\t\t\tbNotAllowedToDuck = false;\n\t\t\tbCrouchWhenShooting = false;\n\t\t}\n\t}\n\tif (m_leaveCarTimer > CTimer::GetTimeInMilliseconds() && !bKindaStayInSamePlace) {\n\t\tSetMoveState(PEDMOVE_STILL);\n\t\treturn CANT_ATTACK;\n\t}\n\tif (m_pedInObjective->IsPlayer()) {\n\t\tCPlayerPed *player = FindPlayerPed();\n\t\tif (m_nPedType == PEDTYPE_COP && player->m_pWanted->m_bIgnoredByCops\n\t\t\t|| player->m_pWanted->m_bIgnoredByEveryone\n\t\t\t|| m_pedInObjective->bIsInWater\n\t\t\t|| m_pedInObjective->m_nPedState == PED_ARRESTED) {\n\n\t\t\tif (m_nPedState != PED_ARREST_PLAYER)\n\t\t\t\tSetIdle();\n\n\t\t\treturn CANT_ATTACK;\n\t\t}\n\t}\n\tif (m_pedInObjective->IsPlayer() && m_nPedType != PEDTYPE_COP\n\t\t&& CharCreatedBy != MISSION_CHAR && FindPlayerPed()->m_pWanted->m_CurrentCops != 0) {\n\t\tSetObjective(OBJECTIVE_FLEE_ON_FOOT_TILL_SAFE);\n\n\t\treturn CANT_ATTACK;\n\t}\n\tif (m_pedInObjective->m_fHealth <= 0.0f) {\n\t\tbObjectiveCompleted = true;\n\t\tbScriptObjectiveCompleted = true;\n\t\treturn CANT_ATTACK;\n\t}\n\tCWeaponInfo *wepInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);\n\tfloat wepRange = wepInfo->m_fRange;\n\tfloat wepRangeAdjusted = wepRange / 3.f;\n\n\tfloat distWithTargetSc = distWithTarget.Magnitude();\n\tif (m_pedInObjective->bInVehicle && m_pedInObjective->m_nPedState != PED_DRAG_FROM_CAR) {\n\t\tCVehicle *vehOfTarget = m_pedInObjective->m_pMyVehicle;\n\t\tif (vehOfTarget->bIsInWater || vehOfTarget->GetStatus() == STATUS_PLAYER_DISABLED\n\t\t\t|| m_pedInObjective->IsPlayer() && CPad::GetPad(0)->ArePlayerControlsDisabled()) {\n\t\t\tSetIdle();\n\t\t\treturn WATCH_UNTIL_HE_DISAPPEARS;\n\t\t}\n\t\tSetLookFlag(vehOfTarget, false);\n\t\tif (m_nMoveState == PEDMOVE_STILL && IsPedInControl())\n\t\t\tTurnBody();\n\n\t\tif (m_nPedState != PED_CARJACK) {\n\t\t\tif (m_pedInObjective->m_nPedState != PED_ARRESTED) {\n\t\t\t\tif (m_attackTimer < CTimer::GetTimeInMilliseconds() && distWithTargetSc < wepRange && distWithTargetSc > 3.0f) {\n\n\t\t\t\t\tSetAttack(vehOfTarget);\n\t\t\t\t\tSetWeaponLockOnTarget(vehOfTarget);\n\t\t\t\t\tSetShootTimer(CGeneral::GetRandomNumberInRange(500, 2000));\n\t\t\t\t\t\n\t\t\t\t\tCVector2D dirVehGoing = vehOfTarget->m_vecMoveSpeed;\n\t\t\t\t\tif (dirVehGoing.Magnitude() > 0.2f) {\n\t\t\t\t\t\tCVector2D vehDist = GetPosition() - vehOfTarget->GetPosition();\n\t\t\t\t\t\tvehDist.Normalise();\n\t\t\t\t\t\tdirVehGoing.Normalise();\n\t\t\t\t\t\tif (DotProduct2D(vehDist, dirVehGoing) > 0.8f) {\n\t\t\t\t\t\t\tSetAttackTimer(CGeneral::GetRandomNumberInRange(200, 500));\n\t\t\t\t\t\t\tSetMoveState(PEDMOVE_STILL);\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn ATTACK_IN_PROGRESS;\n\t\t\t\t\t}\n\t\t\t\t\tif (distWithTargetSc <= m_distanceToCountSeekDone) {\n\t\t\t\t\t\tSetAttackTimer(CGeneral::GetRandomNumberInRange(200, 500));\n\t\t\t\t\t\tSetMoveState(PEDMOVE_STILL);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tSetAttackTimer(CGeneral::GetRandomNumberInRange(2000, 5000));\n\t\t\t\t\t}\n\t\t\t\t\treturn ATTACK_IN_PROGRESS;\n\t\t\t\t} else if (m_nPedState != PED_ATTACK && !bKindaStayInSamePlace && !killPlayerInNoPoliceZone) {\n\t\t\t\t\tif (vehOfTarget) {\n\t\t\t\t\t\tif (m_nPedType == PEDTYPE_COP || vehOfTarget->bIsBus) {\n\t\t\t\t\t\t\tGoToNearestDoor(vehOfTarget);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tm_vehDoor = 0;\n\t\t\t\t\t\t\tif (m_pedInObjective == vehOfTarget->pDriver || vehOfTarget->bIsBus) {\n\t\t\t\t\t\t\t\tm_vehDoor = CAR_DOOR_LF;\n\t\t\t\t\t\t\t} else if (m_pedInObjective == vehOfTarget->pPassengers[0]) {\n\t\t\t\t\t\t\t\tm_vehDoor = CAR_DOOR_RF;\n\t\t\t\t\t\t\t} else if (m_pedInObjective == vehOfTarget->pPassengers[1]) {\n\t\t\t\t\t\t\t\tm_vehDoor = CAR_DOOR_LR;\n\t\t\t\t\t\t\t} else if (m_pedInObjective == vehOfTarget->pPassengers[2]) {\n\t\t\t\t\t\t\t\tm_vehDoor = CAR_DOOR_RR;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t// Unused\n\t\t\t\t\t\t\t// GetPositionToOpenCarDoor(vehOfTarget, m_vehDoor);\n\t\t\t\t\t\t\tSetSeekCar(vehOfTarget, m_vehDoor);\n\t\t\t\t\t\t\tSetMoveState(PEDMOVE_RUN);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn ATTACK_IN_PROGRESS;\n\t}\n\tif (m_nMoveState == PEDMOVE_STILL && IsPedInControl()) {\n\t\tSetLookFlag(m_pedInObjective, false);\n\t\tTurnBody();\n\t}\n\tif (m_nPedType == PEDTYPE_COP && m_pedInObjective->IsPlayer()) {\n\t\tfloat maxArrestDist = 1.5f;\n\t\tif (((CCopPed*)this)->m_bDragsPlayerFromCar) {\n\t\t\tif (m_nPedState == PED_FALL) {\n\t\t\t\tmaxArrestDist = 3.5f;\n\t\t\t} else if (m_nPedState != PED_DRAG_FROM_CAR) {\n\t\t\t\t((CCopPed*)this)->m_bDragsPlayerFromCar = 0;\n\t\t\t}\n\t\t}\n\n\t\tif (distWithTargetSc < maxArrestDist) {\n\t\t\tif (m_pedInObjective->m_getUpTimer > CTimer::GetTimeInMilliseconds()\n\t\t\t\t|| m_pedInObjective->m_nPedState == PED_DRAG_FROM_CAR) {\n\n\t\t\t\t((CCopPed*)this)->SetArrestPlayer(m_pedInObjective);\n\t\t\t\treturn WATCH_UNTIL_HE_DISAPPEARS;\n\t\t\t}\n\t\t}\n\t}\n\t/*\n\tif (distWithTargetSc > 0.1f) {\n\t\tjunk code\n\t} */\n\n\tif (m_shotTime != 0 && m_ceaseAttackTimer != 0) {\n\t\tif (CTimer::GetTimeInMilliseconds() > m_ceaseAttackTimer + m_shotTime) {\n\t\t\tClearLookFlag();\n\t\t\tbObjectiveCompleted = true;\n\t\t\tm_shotTime = 0;\n\t\t\treturn CANT_ATTACK;\n\t\t}\n\t}\n\n\tif (!bKindaStayInSamePlace && !bStopAndShoot && m_nPedState != PED_ATTACK && !bDuckAndCover && !killPlayerInNoPoliceZone) {\n\t\tif (distWithTargetSc > wepRange\n\t\t\t|| m_pedInObjective->m_getUpTimer > CTimer::GetTimeInMilliseconds()\n\t\t\t|| m_pedInObjective->m_nPedState == PED_ARRESTED\n\t\t\t|| m_pedInObjective->EnteringCar() && distWithTargetSc < 3.0f) {\n\n\t\t\tif (m_pedInObjective->EnteringCar())\n\t\t\t\twepRangeAdjusted = 2.0f;\n\n\t\t\tif (bUsePedNodeSeek) {\n\t\t\t\tCVector bestCoords(0.0f, 0.0f, 0.0f);\n\t\t\t\tm_vecSeekPos = m_pedInObjective->GetPosition();\n\n\t\t\t\tif (!m_pNextPathNode)\n\t\t\t\t\tFindBestCoordsFromNodes(m_vecSeekPos, &bestCoords);\n\n\t\t\t\tif (m_pNextPathNode)\n\t\t\t\t\tm_vecSeekPos = CPathFind::TakeWidthIntoAccountForWandering(m_pNextPathNode, m_randomSeed);\n\n\t\t\t\tSetSeek(m_vecSeekPos, m_distanceToCountSeekDone);\n\t\t\t} else {\n\t\t\t\tSetSeek(m_pedInObjective, wepRangeAdjusted);\n\t\t\t}\n\t\t\tif (m_pedInObjective->m_pCurrentPhysSurface && distWithTargetSc < 5.0f) {\n\t\t\t\tbStopAndShoot = true;\n\t\t\t\tb158_8 = true;\n\t\t\t\tSetMoveState(PEDMOVE_STILL);\n\t\t\t} else if (b158_8) {\n\t\t\t\tbStopAndShoot = false;\n\t\t\t\tb158_8 = false;\n\t\t\t}\n\t\t\treturn ATTACK_IN_PROGRESS;\n\t\t}\n\t}\n\tif (m_attackTimer < CTimer::GetTimeInMilliseconds()\n\t\t&& distWithTargetSc < wepRange && m_pedInObjective->m_nPedState != PED_GETUP && m_pedInObjective->m_nPedState != PED_DRAG_FROM_CAR) {\n\n\t\tif (bIsDucking && !bCrouchWhenShooting) {\n\t\t\tCAnimBlendAssociation* duckAnim = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_DUCK_DOWN);\n\t\t\tif (!duckAnim)\n\t\t\t\tduckAnim = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_DUCK_LOW);\n\t\t\tif (!duckAnim)\n\t\t\t\tduckAnim = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_DUCK_WEAPON);\n\n\t\t\tif (duckAnim) {\n\t\t\t\tduckAnim->flags |= ASSOC_DELETEFADEDOUT;\n\t\t\t\tduckAnim->blendDelta = -4.0f;\n\t\t\t}\n\t\t\tbIsDucking = false;\n\t\t\treturn CANT_ATTACK;\n\t\t}\n\t\tbObstacleShowedUpDuringKillObjective = false;\n\t\tSetAttack(m_pedInObjective);\n\t\tSetWeaponLockOnTarget(m_pedInObjective);\n\t\tSetShootTimer(CGeneral::GetRandomNumberInRange(600.0f, 1500.0f));\n\n\t\tint time;\n\t\tif (distWithTargetSc <= wepRangeAdjusted)\n\t\t\ttime = CGeneral::GetRandomNumberInRange(100.0f, 500.0f);\n\t\telse\n\t\t\ttime = CGeneral::GetRandomNumberInRange(1500.0f, 3000.0f);\n\n\t\tSetAttackTimer(time);\n\t} else {\n\t\tif (!m_pedInObjective->m_pCurrentPhysSurface && b158_8) {\n\t\t\tb158_8 = false;\n\t\t\tbStopAndShoot = false;\n\t\t}\n\n\t\tif (m_nPedState != PED_ATTACK && m_nPedState != PED_FIGHT) {\n\t\t\tif (bNotAllowedToDuck && bKindaStayInSamePlace && !bIsDucking && bCrouchWhenShooting) {\n\t\t\t\tSetDuck(CGeneral::GetRandomNumberInRange(1000, 5000), false);\n\t\t\t\treturn CANT_ATTACK;\n\t\t\t}\n\t\t\tif (bObstacleShowedUpDuringKillObjective) {\n\t\t\t\tif (m_nPedType == PEDTYPE_COP) {\n\t\t\t\t\tif (GetWeapon()->m_eWeaponType > WEAPONTYPE_COLT45\n\t\t\t\t\t\t|| m_fleeFrom && m_fleeFrom->IsObject()) {\n\t\t\t\t\t\twepRangeAdjusted = 6.0f;\n\t\t\t\t\t} else if (m_fleeFrom && m_fleeFrom->IsVehicle()) {\n\t\t\t\t\t\twepRangeAdjusted = 4.0f;\n\t\t\t\t\t} else {\n\t\t\t\t\t\twepRangeAdjusted = 2.0f;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\twepRangeAdjusted = 2.0f;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (distWithTargetSc <= wepRangeAdjusted) {\n\t\t\t\tSetMoveState(PEDMOVE_STILL);\n\t\t\t\tbIsPointingGunAt = true;\n\t\t\t\tif (m_nPedState != PED_AIM_GUN && !bDuckAndCover) {\n\t\t\t\t\tm_attackTimer = CTimer::GetTimeInMilliseconds();\n\t\t\t\t\tSetIdle();\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (m_nPedState != PED_SEEK_ENTITY && m_nPedState != PED_SEEK_POS\n\t\t\t\t\t&& !bStopAndShoot && !killPlayerInNoPoliceZone && !bKindaStayInSamePlace) {\n\t\t\t\t\tSay(SOUND_PED_ATTACK);\n\t\t\t\t\tSetSeek(m_pedInObjective, wepRangeAdjusted);\n\t\t\t\t\tbIsRunning = true;\n\t\t\t\t\tif (m_nPedType == PEDTYPE_COP && FindPlayerPed()->m_pWanted->m_CurrentCops > 1) {\n\t\t\t\t\t\tif (CGeneral::GetRandomNumber() & 1)\n\t\t\t\t\t\t\tSay(SOUND_PED_GUNAIMEDAT3);\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tSay(SOUND_PED_GUNAIMEDAT2);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (CTimer::GetTimeInMilliseconds() > m_nPedStateTimer)\n\t\tm_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(m_pedInObjective->GetPosition().x, m_pedInObjective->GetPosition().y, GetPosition().x, GetPosition().y);\n\t\t\t\t\n\treturn ATTACK_IN_PROGRESS;\n}\n\nint32\nCPed::KillCharOnFootMelee(CVector &ourPos, CVector &targetPos, CVector &distWithTarget)\n{\n\tbool killPlayerInNoPoliceZone = false;\n\tfloat distWithTargetSc = distWithTarget.Magnitude();\n\tCPlayerPed *victimPlayer = nil;\n\tif (m_pedInObjective->IsPlayer())\n\t\tvictimPlayer = (CPlayerPed*)m_pedInObjective;\n\n\tif (victimPlayer) {\n\t\tif (CCullZones::NoPolice()\n\t\t\t|| m_pedInObjective->m_pCurrentPhysSurface\n\t\t\t&& m_pedInObjective->m_pCurrentPhysSurface != m_pCurrentPhysSurface\n\t\t\t&& distWithTargetSc < 5.f) {\n\n\t\t\tif (victimPlayer && victimPlayer->m_bSpeedTimerFlag && (IsGangMember() || m_nPedType == PEDTYPE_COP)\n\t\t\t\t&& CharCreatedBy != MISSION_CHAR) {\n\t\t\t\tGiveWeapon(WEAPONTYPE_COLT45, 1000, 1);\n\t\t\t\tSetCurrentWeapon(WEAPONTYPE_COLT45);\n\t\t\t\tSetMoveState(PEDMOVE_STILL);\n\t\t\t\tbStopAndShoot = true;\n\t\t\t\tb158_8 = true;\n\t\t\t\treturn CANT_ATTACK;\n\t\t\t}\n\t\t\tkillPlayerInNoPoliceZone = true;\n\t\t}\n\t}\n\tbNotAllowedToDuck = false;\n\tbStopAndShoot = false;\n\tb158_8 = false;\n\tif (m_leaveCarTimer > CTimer::GetTimeInMilliseconds() && !bKindaStayInSamePlace) {\n\t\tSetMoveState(PEDMOVE_STILL);\n\t\treturn CANT_ATTACK;\n\t}\n\tif (victimPlayer) {\n\t\tCPlayerPed *player = FindPlayerPed();\n\t\tif (m_nPedType == PEDTYPE_COP && player->m_pWanted->m_bIgnoredByCops\n\t\t\t|| player->m_pWanted->m_bIgnoredByEveryone\n\t\t\t|| m_pedInObjective->bIsInWater\n\t\t\t|| m_pedInObjective->m_nPedState == PED_ARRESTED) {\n\n\t\t\tif (m_nPedState != PED_ARREST_PLAYER)\n\t\t\t\tSetIdle();\n\n\t\t\treturn CANT_ATTACK;\n\t\t}\n\t}\n\tif (victimPlayer && m_nPedType != PEDTYPE_COP && CharCreatedBy != MISSION_CHAR\n\t\t&& FindPlayerPed()->m_pWanted->m_CurrentCops != 0) {\n\t\tSetObjective(OBJECTIVE_FLEE_ON_FOOT_TILL_SAFE);\n\n\t\treturn CANT_ATTACK;\n\t}\n\tif (m_pedInObjective->m_fHealth <= 0.0f) {\n\t\tbObjectiveCompleted = true;\n\t\tbScriptObjectiveCompleted = true;\n\t\treturn ATTACK_IN_PROGRESS;\n\t}\n\tbool canReachVictim = false;\n\tuint32 endOfAttack = 0;\n\tCWeaponInfo *wepInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);\n\n\t// Already calculated at the start\n\t// float distWithTargetSc = distWithTarget.Magnitude();\n\tfloat maxDistToKeep = 0.3f;\n\tfloat wepRange = wepInfo->m_fRange / 2.f;\n\n\tif (GetWeapon()->m_eWeaponType == WEAPONTYPE_UNARMED && !IsPlayer() && !(m_pedStats->m_flags & STAT_CAN_KICK))\n\t\twepRange -= 0.3f;\n\n\tif (distWithTargetSc <= 5.f && victimPlayer && !victimPlayer->m_bNoPosForMeleeAttack) {\n\t\n\t\tif (m_pedInObjective->EnteringCar() && wepRange > 2.f) {\n\t\t\tm_vecSeekPos = m_pedInObjective->GetPosition();\n\t\t\twepRange = 1.0f;\n\t\t\tmaxDistToKeep = 0.5f;\n\t\t} else {\n\t\t\tint8 attackDir = victimPlayer->FindMeleeAttackPoint(this, distWithTarget, endOfAttack);\n\t\t\tif (attackDir == -1) {\n\t\t\t\tm_vecSeekPos = victimPlayer->GetPosition();\n\t\t\t\tmaxDistToKeep = 4.0f;\n\t\t\t} else {\n\t\t\t\tvictimPlayer->GetMeleeAttackCoords(m_vecSeekPos, attackDir, wepRange);\n\t\t\t\tdistWithTargetSc = (m_vecSeekPos - GetPosition()).Magnitude();\n\t\t\t\tcanReachVictim = true;\n\t\t\t}\n\t\t}\n\t} else {\n\t\tm_vecSeekPos = m_pedInObjective->GetPosition();\n\t\tmaxDistToKeep = Max(0.8f, 0.9f * wepRange);\n\t\twepRange *= 1.1f;\n\t\tif (victimPlayer && victimPlayer->m_bNoPosForMeleeAttack)\n\t\t\tvictimPlayer = nil;\n\t}\n\n\tif (m_pedInObjective->bInVehicle && m_pedInObjective->m_nPedState != PED_DRAG_FROM_CAR) {\n\t\tCVehicle *vehOfTarget = m_pedInObjective->m_pMyVehicle;\n\n\t\tif (vehOfTarget){\n\t\t\tif (vehOfTarget->bIsInWater || vehOfTarget->GetStatus() == STATUS_PLAYER_DISABLED\n\t\t\t\t|| m_pedInObjective->IsPlayer() && CPad::GetPad(0)->ArePlayerControlsDisabled()) {\n\t\t\t\tSetIdle();\n\t\t\t\treturn WATCH_UNTIL_HE_DISAPPEARS;\n\t\t\t}\n\t\t\tSetLookFlag(vehOfTarget, false);\n\n\t\t\tif (m_nPedState != PED_CARJACK) {\n\t\t\t\tif (m_pedInObjective->m_nPedState != PED_ARRESTED) {\n\t\t\t\t\tif (m_nPedState != PED_ATTACK && !bKindaStayInSamePlace && !killPlayerInNoPoliceZone) {\n\n\t\t\t\t\t\tif (m_nPedType == PEDTYPE_COP || vehOfTarget->bIsBus) {\n\t\t\t\t\t\t\tGoToNearestDoor(vehOfTarget);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tm_vehDoor = 0;\n\t\t\t\t\t\t\tif (m_pedInObjective == vehOfTarget->pDriver || vehOfTarget->bIsBus) {\n\t\t\t\t\t\t\t\tm_vehDoor = CAR_DOOR_LF;\n\t\t\t\t\t\t\t} else if (m_pedInObjective == vehOfTarget->pPassengers[0]) {\n\t\t\t\t\t\t\t\tm_vehDoor = CAR_DOOR_RF;\n\t\t\t\t\t\t\t} else if (m_pedInObjective == vehOfTarget->pPassengers[1]) {\n\t\t\t\t\t\t\t\tm_vehDoor = CAR_DOOR_LR;\n\t\t\t\t\t\t\t} else if (m_pedInObjective == vehOfTarget->pPassengers[2]) {\n\t\t\t\t\t\t\t\tm_vehDoor = CAR_DOOR_RR;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t// Unused\n\t\t\t\t\t\t\t// GetPositionToOpenCarDoor(vehOfTarget, m_vehDoor);\n\t\t\t\t\t\t\tSetSeekCar(vehOfTarget, m_vehDoor);\n\t\t\t\t\t\t\tSetMoveState(PEDMOVE_RUN);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn ATTACK_IN_PROGRESS;\n\t}\n\tif (m_nMoveState == PEDMOVE_STILL && IsPedInControl()) {\n\t\tSetLookFlag(m_pedInObjective, false);\n\t\tif(m_nPedState == PED_IDLE || m_nPedState == PED_ATTACK || m_nPedState == PED_FIGHT)\n\t\t\tTurnBody();\n\t}\n\tif (m_nPedType == PEDTYPE_COP && m_pedInObjective->IsPlayer()) {\n\t\tfloat maxArrestDist = 1.5f;\n\t\tif (((CCopPed*)this)->m_bDragsPlayerFromCar) {\n\t\t\tif (m_nPedState == PED_FALL) {\n\t\t\t\tmaxArrestDist = 3.5f;\n\t\t\t} else if (m_nPedState != PED_DRAG_FROM_CAR) {\n\t\t\t\t((CCopPed*)this)->m_bDragsPlayerFromCar = 0;\n\t\t\t}\n\t\t}\n\n\t\tif (distWithTargetSc < maxArrestDist) {\n\t\t\tif (m_pedInObjective->m_getUpTimer > CTimer::GetTimeInMilliseconds()\n\t\t\t\t|| m_pedInObjective->m_nPedState == PED_DRAG_FROM_CAR) {\n\n\t\t\t\t((CCopPed*)this)->SetArrestPlayer(m_pedInObjective);\n\t\t\t\treturn WATCH_UNTIL_HE_DISAPPEARS;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (distWithTargetSc > maxDistToKeep && !bKindaStayInSamePlace && m_nPedState != PED_ATTACK &&\n\t\t(m_nPedState != PED_FIGHT || m_curFightMove == FIGHTMOVE_IDLE) && !killPlayerInNoPoliceZone) {\n\n\t\tbool goForward = false;\n\n\t\tif (m_nPedState == PED_FIGHT) {\n\t\t\tif (canReachVictim) {\n\t\t\t\tCVector attackAndVictimDist = m_vecSeekPos - m_pedInObjective->GetPosition();\n\t\t\t\tCVector victimFarness = attackAndVictimDist / wepRange;\n\t\t\t\tCVector distVec = GetPosition() - m_pedInObjective->GetPosition();\n\t\t\t\tfloat distSqr = distVec.MagnitudeSqr();\n\t\t\t\tif (sq(wepRange) > distSqr && distSqr > 0.05f) {\n\t\t\t\t\tdistVec.Normalise();\n\t\t\t\t\tif (DotProduct2D(victimFarness, distVec) > Cos(DEGTORAD(30.f)))\n\t\t\t\t\t\tgoForward = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (goForward) {\n\t\t\tm_curFightMove = FIGHTMOVE_SHUFFLE_F;\n\t\t\tCAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_FIGHT_SHUFFLE_B, 16.f)->SetFinishCallback(FinishFightMoveCB,this);\n\t\t\tm_fightState = FIGHTSTATE_NO_MOVE;\n\t\t\tm_fightButtonPressure = 0;\n\t\t\tm_takeAStepAfterAttack = false;\n\n\t\t} else if (bUsePedNodeSeek && !canReachVictim) {\n\t\t\tCVector bestCoords(0.0f, 0.0f, 0.0f);\n\n\t\t\tif (!m_pNextPathNode)\n\t\t\t\tFindBestCoordsFromNodes(m_vecSeekPos, &bestCoords);\n\n\t\t\tif (m_pNextPathNode)\n\t\t\t\tm_vecSeekPos = CPathFind::TakeWidthIntoAccountForWandering(m_pNextPathNode, m_randomSeed);\n\n\t\t\tSetSeek(m_vecSeekPos, m_distanceToCountSeekDone);\n\t\t} else {\n\t\t\tif (canReachVictim)\n\t\t\t\tSetSeek(m_vecSeekPos, maxDistToKeep);\n\t\t\telse\n\t\t\t\tSetSeek(m_pedInObjective, maxDistToKeep);\n\t\t}\n\t\treturn ATTACK_IN_PROGRESS;\n\t}\n\n\tif (m_attackTimer < CTimer::GetTimeInMilliseconds()\n\t\t&& distWithTargetSc < wepRange && m_pedInObjective->m_nPedState != PED_GETUP && m_pedInObjective->m_nPedState != PED_DRAG_FROM_CAR) {\n\n\t\tif (bIsDucking) {\n\t\t\tCAnimBlendAssociation* duckAnim = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_DUCK_DOWN);\n\t\t\tif (!duckAnim)\n\t\t\t\tduckAnim = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_DUCK_LOW);\n\t\t\tif (!duckAnim)\n\t\t\t\tduckAnim = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_DUCK_WEAPON);\n\n\t\t\tif (duckAnim) {\n\t\t\t\tduckAnim->flags |= ASSOC_DELETEFADEDOUT;\n\t\t\t\tduckAnim->blendDelta = -4.0f;\n\t\t\t}\n\t\t\tbIsDucking = false;\n\t\t\treturn CANT_ATTACK;\n\t\t}\n\n\t\tif (canReachVictim || !victimPlayer) {\n\t\t\tSetMoveState(PEDMOVE_STILL);\n\t\t\tSetAttack(m_pedInObjective);\n\t\t\tm_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(\n\t\t\t\tm_pedInObjective->GetPosition().x, m_pedInObjective->GetPosition().y,\n\t\t\t\tGetPosition().x, GetPosition().y);\n\t\t\tSetShootTimer(CGeneral::GetRandomNumberInRange(0.f, 500.f));\n\n\t\t\tint time;\n\t\t\tif (endOfAttack <= CTimer::GetTimeInMilliseconds())\n\t\t\t\ttime = CGeneral::GetRandomNumberInRange(100.0f, 1500.0f);\n\t\t\telse\n\t\t\t\ttime = endOfAttack - CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(400.0f, 1500.0f);\n\n\t\t\tSetAttackTimer(time);\n\t\t\tbObstacleShowedUpDuringKillObjective = false;\n\t\t}\n\t\treturn ATTACK_IN_PROGRESS;\n\t} else {\n\t\tif (!m_pedInObjective->m_pCurrentPhysSurface && m_pCurrentPhysSurface && b158_8) {\n\t\t\tb158_8 = false;\n\t\t\tbStopAndShoot = false;\n\t\t}\n\n\t\tif (m_nPedState != PED_ATTACK && m_nPedState != PED_FIGHT) {\n\t\t\tSetMoveState(PEDMOVE_STILL);\n\t\t\tif (GetWeapon()->m_eWeaponType == WEAPONTYPE_UNARMED)\n\t\t\t\tStartFightAttack(0);\n\t\t}\n\t\treturn ATTACK_IN_PROGRESS;\n\t}\n}\n\nbool\nCPed::CanBeDamagedByThisGangMember(CPed* who)\n{\n\treturn m_gangFlags & (1 << (who->m_nPedType - PEDTYPE_GANG1));\n}\n"
  },
  {
    "path": "src/peds/PedAttractor.cpp",
    "content": "#include \"common.h\"\n#include \"PedAttractor.h\"\n\n#include \"General.h\"\n#include \"Vehicle.h\"\n#include \"World.h\"\n#include \"MemoryHeap.h\"\n\nconst int gcMaxSizeOfAtmQueue = 1;\nconst int gcMaxSizeOfSeatQueue = 1;\nconst int gcMaxSizeOfStopQueue = 5;\nconst int gcMaxSizeOfPizzaQueue = 5;\nconst int gcMaxSizeOfShelterQueue = 5;\nconst int gcMaxSizeOfIceCreamQueue = 1;\n\nstd::vector<CVector> CPedShelterAttractor::ms_displacements;\n\nCPedAttractorManager* GetPedAttractorManager()\n{\n// mobile just has a static here:\n/*\n\tstatic CPedAttractorManager pedAttrMgr;\n\treturn &pedAttrMgr;\n*/\n\tstatic CPedAttractorManager *pedAttrMgr;\n\tif(pedAttrMgr == nil){\n\t\tPUSH_MEMID(MEMID_PED_ATTR);\n\t\tpedAttrMgr = new CPedAttractorManager;\n\t\tPOP_MEMID();\n\t}\n\treturn pedAttrMgr;\n}\n\nCVehicleToEffect::CVehicleToEffect(CVehicle* pVehicle) : m_pVehicle(pVehicle)\n{\n\tm_effects[1].col = CRGBA(0, 0, 0, 0);\n\tm_effects[1].type = EFFECT_PED_ATTRACTOR;\n\tm_effects[1].pos = CVector(2.0f, 1.0f, 0.0f);\n\tm_effects[1].pedattr.useDir = CVector(-1.0f, 0.0f, 0.0f);\n\tm_effects[1].pedattr.queueDir = CVector(-1.0f, 0.0f, 0.0f);\n\tm_effects[1].pedattr.type = ATTRACTOR_ICECREAM;\n\n\tm_effects[3].col = CRGBA(0, 0, 0, 0);\n\tm_effects[3].type = EFFECT_PED_ATTRACTOR;\n\tm_effects[3].pos = CVector(2.0f, -0.5f, 0.0f);\n\tm_effects[3].pedattr.useDir = CVector(-1.0f, 0.0f, 0.0f);\n\tm_effects[3].pedattr.queueDir = CVector(-1.0f, 0.0f, 0.0f);\n\tm_effects[3].pedattr.type = ATTRACTOR_ICECREAM;\n\n\tm_effects[0].col = CRGBA(0, 0, 0, 0);\n\tm_effects[0].type = EFFECT_PED_ATTRACTOR;\n\tm_effects[0].pos = CVector(-2.0f, 1.0f, 0.0f);\n\tm_effects[0].pedattr.useDir = CVector(1.0f, 0.0f, 0.0f);\n\tm_effects[0].pedattr.queueDir = CVector(1.0f, 0.0f, 0.0f);\n\tm_effects[0].pedattr.type = ATTRACTOR_ICECREAM;\n\n\tm_effects[2].col = CRGBA(0, 0, 0, 0);\n\tm_effects[2].type = EFFECT_PED_ATTRACTOR;\n\tm_effects[2].pos = CVector(-2.0f, -0.5f, 0.0f);\n\tm_effects[2].pedattr.useDir = CVector(1.0f, 0.0f, 0.0f);\n\tm_effects[2].pedattr.queueDir = CVector(1.0f, 0.0f, 0.0f);\n\tm_effects[2].pedattr.type = ATTRACTOR_ICECREAM;\n}\n\nCVehicleToEffect& CVehicleToEffect::From(const CVehicleToEffect& other)\n{\n\tm_pVehicle = other.m_pVehicle;\n\tfor (int i = 0; i < NUM_ATTRACTORS_FOR_ICECREAM_VAN; i++) {\n\t\tm_effects[i].col = other.m_effects[i].col;\n\t\tm_effects[i].type = other.m_effects[i].type;\n\t\tm_effects[i].pos = other.m_effects[i].pos;\n\t\tm_effects[i].pedattr = other.m_effects[i].pedattr;\n\t}\n\treturn *this;\n}\n\nconst C2dEffect* CVehicleToEffect::ChooseEffect(const CVector& pos) const\n{\n\tif (!m_pVehicle)\n\t\treturn nil;\n\tif (DotProduct(pos - m_pVehicle->GetPosition(), m_pVehicle->GetRight()) > 0.0f) {\n\t\tif (DotProduct(pos - m_pVehicle->GetPosition(), m_pVehicle->GetForward()) > 0.0f)\n\t\t\treturn &m_effects[1];\n\t\telse\n\t\t\treturn &m_effects[3];\n\t}\n\telse {\n\t\tif (DotProduct(pos - m_pVehicle->GetPosition(), m_pVehicle->GetForward()) > 0.0f)\n\t\t\treturn &m_effects[0];\n\t\telse\n\t\t\treturn &m_effects[2];\n\t}\n}\n\nbool CVehicleToEffect::HasThisEffect(C2dEffect* pEffect) const\n{\n\tfor (int i = 0; i < NUM_ATTRACTORS_FOR_ICECREAM_VAN; i++) {\n\t\tif (pEffect == &m_effects[i])\n\t\t\treturn true;\n\t}\n\treturn false;\n}\n\nconst C2dEffect* CPedAttractorManager::GetEffectForIceCreamVan(CVehicle* pVehicle, const CVector& pos)\n{\n\tif (!vVehicleToEffect.empty()) {\n\t\tfor (std::vector<CVehicleToEffect>::const_iterator assoc = vVehicleToEffect.begin(); assoc != vVehicleToEffect.end(); ++assoc) {\n\t\t\tif (assoc->GetVehicle() == pVehicle)\n\t\t\t\treturn assoc->ChooseEffect(pos);\n\t\t}\n\t}\n\tPUSH_MEMID(MEMID_PED_ATTR);\n\tCVehicleToEffect effect(pVehicle);\n\tvVehicleToEffect.push_back(effect);\n\tPOP_MEMID();\n#ifdef FIX_BUGS\n\treturn vVehicleToEffect.back().ChooseEffect(pos);\n#else\n\treturn effect.ChooseEffect(pos);\n#endif\n}\n\nCVehicle* CPedAttractorManager::GetIceCreamVanForEffect(C2dEffect* pEffect)\n{\n\tif (vVehicleToEffect.empty())\n\t\treturn nil;\n\tfor (std::vector<CVehicleToEffect>::const_iterator assoc = vVehicleToEffect.begin(); assoc != vVehicleToEffect.end(); ++assoc) {\n\t\tif (assoc->HasThisEffect(pEffect))\n\t\t\treturn assoc->GetVehicle();\n\t}\n\treturn nil;\n}\n\nconst CPedAttractor* CPedAttractorManager::FindAssociatedAttractor(const C2dEffect* pEffect, std::vector<CPedAttractor*>& vecAttractors)\n{\n\tif (vecAttractors.empty())\n\t\treturn nil;\n\tfor (std::vector<CPedAttractor*>::const_iterator attractor = vecAttractors.begin(); attractor != vecAttractors.end(); ++attractor) {\n\t\tif ((*attractor)->GetEffect() == pEffect)\n\t\t\treturn *attractor;\n\t}\n\treturn nil;\n}\n\nvoid CPedAttractorManager::RemoveIceCreamVanEffects(C2dEffect* pEffect)\n{\n\tCVehicle* pVehicle = GetIceCreamVanForEffect(pEffect);\n\tif (!pVehicle)\n\t\treturn;\n\tif (vVehicleToEffect.empty())\n\t\treturn;\n\tfor (std::vector<CVehicleToEffect>::iterator assoc = vVehicleToEffect.begin(); assoc != vVehicleToEffect.end();) {\n\t\tif (assoc->GetVehicle() != pVehicle) {\n\t\t\t++assoc;\n\t\t\tcontinue;\n\t\t}\n\t\tuint32 total = 0;\n\t\tfor (uint32 j = 0; j < NUM_ATTRACTORS_FOR_ICECREAM_VAN; j++) {\n\t\t\tif (FindAssociatedAttractor(assoc->GetEffect(j), vIceCreamAttractors))\n\t\t\t\ttotal++;\n\t\t}\n\t\tif (total > 0)\n\t\t\t++assoc;\n\t\telse\n\t\t\tassoc = vVehicleToEffect.erase(assoc);\n\t}\n}\n\nCPedAttractor::CPedAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float distance, float headingdiff, float posdisp, float headdisp) :\n\tp2dEffect(pEffect),\n\tm_nMaxPedsInAttractor(maxpeds),\n\tm_fQueueDistance(qdist),\n\tm_fTimeInWaitQueue(waitTime),\n\tm_fTimeInApproachingQueue(approachTime),\n\tm_fDistanceToUseAttractor(distance),\n\tm_fAcceptableHeading(headingdiff),\n\tm_fMaxPositionDisplacement(posdisp),\n\tm_fMaxHeadingDisplacement(headdisp)\n{\n\tCPedAttractorManager::ComputeEffectPos(pEffect, matrix, vecEffectPos);\n\tCPedAttractorManager::ComputeEffectQueueDir(pEffect, matrix, vecQueueDir);\n\tCPedAttractorManager::ComputeEffectUseDir(pEffect, matrix, vecUseDir);\n}\n\nvoid CPedPizzaAttractor::UpdatePedStateOnDeparture(CPed* pPed) const\n{\n\tif (pPed->m_nPedMoney > 10)\n\t\tpPed->m_nPedMoney -= 10;\n\telse\n\t\tpPed->m_nPedMoney = 0;\n}\n\nvoid CPedAtmAttractor::UpdatePedStateOnDeparture(CPed* pPed) const\n{\n\tpPed->m_nPedMoney += 20 * CGeneral::GetRandomNumberInRange(1, 51);\n};\n\nfloat CPedAttractor::ComputeDeltaHeading() const\n{\n\treturn CGeneral::GetRandomNumberInRange(-m_fMaxHeadingDisplacement, m_fMaxHeadingDisplacement);\n}\n\nfloat CPedAttractor::ComputeDeltaPos() const\n{\n\treturn CGeneral::GetRandomNumberInRange(-m_fMaxPositionDisplacement, m_fMaxPositionDisplacement);\n}\n\nvoid CPedAttractor::ComputeAttractTime(int32 id, bool approacher, float& time) const\n{\n\tif (approacher)\n\t\ttime = m_fTimeInApproachingQueue;\n\telse\n\t\ttime = m_fTimeInWaitQueue;\n}\n\nvoid CPedAttractor::ComputeAttractPos(int32 qid, CVector& pos) const\n{\n\tif (!p2dEffect)\n\t\treturn;\n\tpos = vecEffectPos - qid * vecQueueDir * m_fQueueDistance;\n\tif (qid != 0) {\n\t\tpos.x += ComputeDeltaPos();\n\t\tpos.y += ComputeDeltaPos();\n\t}\n}\n\nCVector CPedShelterAttractor::GetDisplacement(int32 qid) const\n{\n\tif (ms_displacements.empty()) {\n\t\tint i = 0;\n\t\twhile (i < gcMaxSizeOfShelterQueue) {\n\t\t\tfloat fRandomAngle = CGeneral::GetRandomNumberInRange(0.0f, TWOPI);\n\t\t\tfloat fRandomOffset = CGeneral::GetRandomNumberInRange(0.0f, 2.0f);\n\t\t\tCVector vecDisplacement(fRandomOffset * Sin(fRandomAngle), fRandomOffset * Cos(fRandomAngle), 0.0f);\n\t\t\tbool close = false;\n\t\t\tfor (std::vector<CVector>::const_iterator v = ms_displacements.begin(); v != ms_displacements.end(); ++v) {\n\t\t\t\tif ((*v - vecDisplacement).Magnitude() < 1.0f) {\n\t\t\t\t\tclose = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!close) {\n\t\t\t\tms_displacements.push_back(vecDisplacement);\n\t\t\t\ti++;\n\t\t\t}\n\t\t}\n\t}\n\treturn ms_displacements[qid];\n}\n\nvoid CPedShelterAttractor::ComputeAttractPos(int32 qid, CVector& pos) const\n{\n\tif (!p2dEffect)\n\t\treturn;\n\tpos = vecEffectPos + GetDisplacement(qid);\n}\n\nvoid CPedAttractor::ComputeAttractHeading(int32 qid, float& heading) const\n{\n\theading = CGeneral::GetRadianAngleBetweenPoints(qid != 0 ? vecQueueDir.x : vecUseDir.x, qid != 0 ? vecQueueDir.y : vecUseDir.y, 0.0f, 0.0f);\n\tif (qid != 0)\n\t\theading += ComputeDeltaHeading();\n}\n\nvoid CPedShelterAttractor::ComputeAttractHeading(int32 qid, float& heading) const\n{\n\theading = CGeneral::GetRandomNumberInRange(0.0f, TWOPI);\n}\n\nbool CPedAttractor::RegisterPed(CPed* pPed)\n{\n\tfor (std::vector<CPed*>::iterator pPedIt = vApproachingQueue.begin(); pPedIt != vApproachingQueue.end(); ++pPedIt) {\n\t\tif (*pPedIt == pPed) {\n\t\t\tvApproachingQueue.erase(pPedIt);\n\t\t\treturn false;\n\t\t}\n\t}\n\tif (GetNoOfRegisteredPeds() >= m_nMaxPedsInAttractor)\n\t\treturn 0;\n\tvApproachingQueue.push_back(pPed);\n\tCVector pos;\n\tfloat heading;\n\tfloat time;\n\tint32 slot = ComputeFreeSlot();\n\tComputeAttractPos(slot, pos);\n\tComputeAttractHeading(slot, heading);\n\tComputeAttractTime(slot, false, time);\n\tpPed->SetNewAttraction(this, pos, heading, time, slot);\n\treturn true;\n}\n\nstatic bool IsPedUsingAttractorOfThisType(int8 type, CPed* pPed)\n{\n\tswitch (type) {\n\tcase ATTRACTOR_ATM:\n\t\tif (pPed->m_objective == OBJECTIVE_GOTO_ATM_ON_FOOT)\n\t\t\treturn true;\n\t\tbreak;\n\tcase ATTRACTOR_SEAT:\n\t\tif (pPed->m_objective == OBJECTIVE_GOTO_SEAT_ON_FOOT)\n\t\t\treturn true;\n\t\tbreak;\n\tcase ATTRACTOR_STOP:\n\t\tif (pPed->m_objective == OBJECTIVE_GOTO_BUS_STOP_ON_FOOT || pPed->m_objective == OBJECTIVE_WAIT_ON_FOOT_AT_BUS_STOP || pPed->m_objective == OBJECTIVE_WAIT_ON_FOOT)\n\t\t\treturn true;\n\t\tbreak;\n\tcase ATTRACTOR_PIZZA:\n\t\tif (pPed->m_objective == OBJECTIVE_GOTO_PIZZA_ON_FOOT || pPed->m_objective == OBJECTIVE_WAIT_ON_FOOT)\n\t\t\treturn true;\n\t\tbreak;\n\tcase ATTRACTOR_SHELTER:\n\t\tif (pPed->m_objective == OBJECTIVE_GOTO_SHELTER_ON_FOOT || pPed->m_objective == OBJECTIVE_WAIT_ON_FOOT_AT_SHELTER)\n\t\t\treturn true;\n\t\tbreak;\n\tcase ATTRACTOR_ICECREAM:\n\t\tif (pPed->m_objective == OBJECTIVE_GOTO_ICE_CREAM_VAN_ON_FOOT || pPed->m_objective == OBJECTIVE_WAIT_ON_FOOT_AT_ICE_CREAM_VAN)\n\t\t\treturn true;\n\t\tbreak;\n\t}\n\treturn false;\n}\n\nbool CPedAttractor::DeRegisterPed(CPed* pPed)\n{\n\tfor (std::vector<CPed*>::iterator pPedIt = vApproachingQueue.begin(); pPedIt != vApproachingQueue.end(); ++pPedIt) {\n\t\tif (*pPedIt != pPed)\n\t\t\tcontinue;\n\t\tpPed->m_attractor = nil;\n\t\tpPed->m_positionInQueue = -1;\n\t\tpPed->bHasAlreadyUsedAttractor = true;\n\t\t\n\t\tif (IsPedUsingAttractorOfThisType(p2dEffect->pedattr.type, pPed))\n\t\t\tpPed->SetObjective(OBJECTIVE_NONE);\n\t\telse if (pPed->GetPedState() != PED_IDLE && pPed->GetPedState() != PED_NONE) {\n\t\t\tvApproachingQueue.erase(pPedIt);\n\t\t\treturn true;\n\t\t}\n\t\tpPed->SetWanderPath(CGeneral::GetNodeHeadingFromVector(-vecQueueDir.x, -vecQueueDir.y));\n\t\tvApproachingQueue.erase(pPedIt);\n\t\treturn true;\n\t}\n\treturn BroadcastDeparture(pPed);\n}\n\nbool CPedAttractor::BroadcastArrival(CPed* pPed)\n{\n\tfor (std::vector<CPed*>::const_iterator pPedIt = vWaitingQueue.begin(); pPedIt != vWaitingQueue.end(); ++pPedIt) {\n\t\tif (*pPedIt == pPed)\n\t\t\treturn false;\n\t}\n\tvWaitingQueue.push_back(pPed);\n\tfor (std::vector<CPed*>::iterator pPedIt = vApproachingQueue.begin(); pPedIt != vApproachingQueue.end(); ++pPedIt) {\n\t\tif (*pPedIt == pPed) {\n\t\t\tvApproachingQueue.erase(pPedIt);\n\t\t\tbreak;\n\t\t}\n\t}\n\tfor (std::vector<CPed*>::iterator pPedIt = vApproachingQueue.begin(); pPedIt != vApproachingQueue.end(); ++pPedIt) {\n\t\tCPed* pPed = *pPedIt;\n\t\tCVector pos;\n\t\tfloat heading;\n\t\tfloat time;\n\t\tint32 slot = ComputeFreeSlot();\n\t\tComputeAttractPos(slot, pos);\n\t\tComputeAttractHeading(slot, heading);\n\t\tComputeAttractTime(slot, false, time);\n\t\tpPed->SetNewAttraction(this, pos, heading, time, slot);\n\t}\n\treturn true;\n}\n\nbool CPedAttractor::BroadcastDeparture(CPed* pPed)\n{\n\tint qid = -1;\n\tfor (uint32 i = 0; i < vWaitingQueue.size(); i++){\n\t\tif (vWaitingQueue[i] == pPed)\n\t\t\tqid = i;\n\t}\n\tif (qid < 0)\n\t\treturn false;\n\tfor (uint32 i = qid + 1; i < vWaitingQueue.size(); i++) {\n\t\tCVector pos;\n\t\tfloat heading;\n\t\tfloat time;\n\t\tComputeAttractPos(i - 1, pos);\n\t\tComputeAttractHeading(i - 1, heading);\n\t\tComputeAttractTime(i - 1, true, time);\n\t\tpPed->SetNewAttraction(this, pos, heading, time, i - 1);\n\t}\n\tpPed->m_attractor = nil;\n\tpPed->m_positionInQueue = -1;\n\tpPed->bHasAlreadyUsedAttractor = true;\n\tif (!IsPedUsingAttractorOfThisType(p2dEffect->pedattr.type, pPed)) {\n\t\tif (pPed->GetPedState() == PED_IDLE || pPed->GetPedState() == PED_NONE)\n\t\t\tpPed->SetWanderPath(CGeneral::GetNodeHeadingFromVector(-vecQueueDir.x, -vecQueueDir.y));\n\t}\n\telse {\n\t\tpPed->SetObjective(OBJECTIVE_NONE);\n\t\tif (qid == 0)\n\t\t\tpPed->SetWanderPath(CGeneral::GetNodeHeadingFromVector(vecQueueDir.x, vecQueueDir.y));\n\t\telse if (qid == vWaitingQueue.size() - 1)\n\t\t\tpPed->SetWanderPath(CGeneral::GetNodeHeadingFromVector(-vecQueueDir.x, -vecQueueDir.y));\n\t\telse\n\t\t\tpPed->SetWanderPath(CGeneral::GetNodeHeadingFromVector(-vecQueueDir.y, -vecQueueDir.x));\n\t\tUpdatePedStateOnDeparture(pPed);\n\t}\n\tvWaitingQueue.erase(vWaitingQueue.begin() + qid);\n\tfor (std::vector<CPed*>::iterator pPedIt = vApproachingQueue.begin(); pPedIt != vApproachingQueue.end(); ++pPedIt) {\n\t\tCPed* pPed = *pPedIt;\n\t\tCVector pos;\n\t\tfloat heading;\n\t\tfloat time;\n\t\tint32 slot = ComputeFreeSlot();\n\t\tComputeAttractPos(slot, pos);\n\t\tComputeAttractHeading(slot, heading);\n\t\tComputeAttractTime(slot, false, time);\n\t\tpPed->SetNewAttraction(this, pos, heading, time, slot);\n\t}\n\treturn true;\n}\n\nbool CPedShelterAttractor::BroadcastDeparture(CPed* pPed)\n{\n\tint qid = -1;\n\tfor (uint32 i = 0; i < vWaitingQueue.size(); i++) {\n\t\tif (vWaitingQueue[i] == pPed)\n\t\t\tqid = i;\n\t}\n\tif (qid < 0)\n\t\treturn false;\n\tpPed->m_attractor = nil;\n\tpPed->m_positionInQueue = -1;\n\tpPed->bHasAlreadyUsedAttractor = true;\n\tif (!IsPedUsingAttractorOfThisType(p2dEffect->pedattr.type, pPed)) {\n\t\tif (pPed->GetPedState() == PED_IDLE || pPed->GetPedState() == PED_NONE)\n\t\t\tpPed->SetWanderPath(CGeneral::GetNodeHeadingFromVector(-vecQueueDir.x, -vecQueueDir.y));\n\t}\n\telse {\n\t\tpPed->SetObjective(OBJECTIVE_NONE);\n\t\tif (qid == 0)\n\t\t\tpPed->SetWanderPath(CGeneral::GetNodeHeadingFromVector(vecQueueDir.x, vecQueueDir.y));\n\t\telse if (qid == vWaitingQueue.size() - 1)\n\t\t\tpPed->SetWanderPath(CGeneral::GetNodeHeadingFromVector(-vecQueueDir.x, -vecQueueDir.y));\n\t\telse\n\t\t\tpPed->SetWanderPath(CGeneral::GetNodeHeadingFromVector(-vecQueueDir.y, -vecQueueDir.x));\n\t\tUpdatePedStateOnDeparture(pPed);\n\t}\n\tvWaitingQueue.erase(vWaitingQueue.begin() + qid);\n\tfor (std::vector<CPed*>::iterator pPedIt = vApproachingQueue.begin(); pPedIt != vApproachingQueue.end(); ++pPedIt) {\n\t\tCPed* pPed = *pPedIt;\n\t\tCVector pos;\n\t\tfloat heading;\n\t\tfloat time;\n\t\tint32 slot = ComputeFreeSlot();\n\t\tComputeAttractPos(slot, pos);\n\t\tComputeAttractHeading(slot, heading);\n\t\tComputeAttractTime(slot, false, time);\n\t\tpPed->SetNewAttraction(this, pos, heading, time, slot);\n\t}\n\treturn true;\n}\n\nbool CPedAttractor::IsRegisteredWithPed(CPed* pPed) const\n{\n\tfor (std::vector<CPed*>::const_iterator pPedIt = vWaitingQueue.begin(); pPedIt != vWaitingQueue.end(); ++pPedIt) {\n\t\tif (*pPedIt == pPed)\n\t\t\treturn true;\n\t}\n\tfor (std::vector<CPed*>::const_iterator pPedIt = vApproachingQueue.begin(); pPedIt != vApproachingQueue.end(); ++pPedIt) {\n\t\tif (*pPedIt == pPed) {\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n\nbool CPedAttractor::IsInQueue(CPed* pPed) const\n{\n\tfor (std::vector<CPed*>::const_iterator pPedIt = vWaitingQueue.begin(); pPedIt != vWaitingQueue.end(); ++pPedIt) {\n\t\tif (*pPedIt == pPed)\n\t\t\treturn true;\n\t}\n\treturn false;\n}\n\nCPedAttractor* CPedAttractorManager::RegisterPedWithAttractor(CPed* pPed, C2dEffect* pEffect, const CMatrix& matrix)\n{\n\tif (pEffect->type != EFFECT_PED_ATTRACTOR)\n\t\treturn nil;\n\tif (IsPedRegisteredWithEffect(pPed))\n\t\treturn nil;\n\tswitch (pEffect->pedattr.type) {\n\tcase ATTRACTOR_ATM: return RegisterPed(pPed, pEffect, matrix, vAtmAttractors);\n\tcase ATTRACTOR_SEAT: return RegisterPed(pPed, pEffect, matrix, vSeatAttractors);\n\tcase ATTRACTOR_STOP: return RegisterPed(pPed, pEffect, matrix, vStopAttractors);\n\tcase ATTRACTOR_PIZZA: return RegisterPed(pPed, pEffect, matrix, vPizzaAttractors);\n\tcase ATTRACTOR_SHELTER: return RegisterPed(pPed, pEffect, matrix, vShelterAttractors);\n\tcase ATTRACTOR_ICECREAM: return RegisterPed(pPed, pEffect, matrix, vIceCreamAttractors);\n\t}\n\treturn nil;\n}\n\nbool CPedAttractorManager::DeRegisterPed(CPed* pPed, CPedAttractor* pAttractor)\n{\n\tif (!pAttractor)\n\t\treturn false;\n\tif (pAttractor->GetEffect()->type != EFFECT_PED_ATTRACTOR)\n\t\treturn nil;\n\tif (!IsPedRegisteredWithEffect(pPed))\n\t\treturn nil;\n\tswitch (pAttractor->GetEffect()->pedattr.type) {\n\tcase ATTRACTOR_ATM: return DeRegisterPed(pPed, pAttractor, vAtmAttractors);\n\tcase ATTRACTOR_SEAT: return DeRegisterPed(pPed, pAttractor, vSeatAttractors);\n\tcase ATTRACTOR_STOP: return DeRegisterPed(pPed, pAttractor, vStopAttractors);\n\tcase ATTRACTOR_PIZZA: return DeRegisterPed(pPed, pAttractor, vPizzaAttractors);\n\tcase ATTRACTOR_SHELTER: return DeRegisterPed(pPed, pAttractor, vShelterAttractors);\n\tcase ATTRACTOR_ICECREAM: return DeRegisterPed(pPed, pAttractor, vIceCreamAttractors);\n\t}\n\treturn nil;\n}\n\nbool CPedAttractorManager::BroadcastArrival(CPed* pPed, CPedAttractor* pAttractor)\n{\n\tif (!pAttractor)\n\t\treturn false;\n\tif (pAttractor->GetEffect()->type != EFFECT_PED_ATTRACTOR)\n\t\treturn nil;\n\tif (!IsPedRegisteredWithEffect(pPed))\n\t\treturn nil;\n\tswitch (pAttractor->GetEffect()->pedattr.type) {\n\tcase ATTRACTOR_ATM: return BroadcastArrival(pPed, pAttractor, vAtmAttractors);\n\tcase ATTRACTOR_SEAT: return BroadcastArrival(pPed, pAttractor, vSeatAttractors);\n\tcase ATTRACTOR_STOP: return BroadcastArrival(pPed, pAttractor, vStopAttractors);\n\tcase ATTRACTOR_PIZZA: return BroadcastArrival(pPed, pAttractor, vPizzaAttractors);\n\tcase ATTRACTOR_SHELTER: return BroadcastArrival(pPed, pAttractor, vShelterAttractors);\n\tcase ATTRACTOR_ICECREAM: return BroadcastArrival(pPed, pAttractor, vIceCreamAttractors);\n\t}\n\treturn nil;\n}\n\nbool CPedAttractorManager::BroadcastDeparture(CPed* pPed, CPedAttractor* pAttractor)\n{\n\tif (!pAttractor)\n\t\treturn false;\n\tif (pAttractor->GetEffect()->type != EFFECT_PED_ATTRACTOR)\n\t\treturn nil;\n\tif (!IsPedRegisteredWithEffect(pPed))\n\t\treturn nil;\n\tswitch (pAttractor->GetEffect()->pedattr.type) {\n\tcase ATTRACTOR_ATM: return BroadcastDeparture(pPed, pAttractor, vAtmAttractors);\n\tcase ATTRACTOR_SEAT: return BroadcastDeparture(pPed, pAttractor, vSeatAttractors);\n\tcase ATTRACTOR_STOP: return BroadcastDeparture(pPed, pAttractor, vStopAttractors);\n\tcase ATTRACTOR_PIZZA: return BroadcastDeparture(pPed, pAttractor, vPizzaAttractors);\n\tcase ATTRACTOR_SHELTER: return BroadcastDeparture(pPed, pAttractor, vShelterAttractors);\n\tcase ATTRACTOR_ICECREAM: return BroadcastDeparture(pPed, pAttractor, vIceCreamAttractors);\n\t}\n\treturn nil;\n}\n\nbool CPedAttractorManager::IsAtHeadOfQueue(CPed* pPed, CPedAttractor* pAttractor)\n{\n\tif (!pAttractor)\n\t\treturn false;\n\tif (pAttractor->GetEffect()->type != EFFECT_PED_ATTRACTOR)\n\t\treturn nil;\n\tif (!IsPedRegisteredWithEffect(pPed))\n\t\treturn nil;\n\tswitch (pAttractor->GetEffect()->pedattr.type) {\n\tcase ATTRACTOR_ATM: return IsAtHeadOfQueue(pPed, pAttractor, vAtmAttractors);\n\tcase ATTRACTOR_SEAT: return IsAtHeadOfQueue(pPed, pAttractor, vSeatAttractors);\n\tcase ATTRACTOR_STOP: return IsAtHeadOfQueue(pPed, pAttractor, vStopAttractors);\n\tcase ATTRACTOR_PIZZA: return IsAtHeadOfQueue(pPed, pAttractor, vPizzaAttractors);\n\tcase ATTRACTOR_SHELTER: return IsAtHeadOfQueue(pPed, pAttractor, vShelterAttractors);\n\tcase ATTRACTOR_ICECREAM: return IsAtHeadOfQueue(pPed, pAttractor, vIceCreamAttractors);\n\t}\n\treturn nil;\n}\n\nbool CPedAttractorManager::IsInQueue(CPed* pPed, CPedAttractor* pAttractor)\n{\n\tif (!pAttractor)\n\t\treturn false;\n\tif (pAttractor->GetEffect()->type != EFFECT_PED_ATTRACTOR)\n\t\treturn nil;\n\tif (!IsPedRegisteredWithEffect(pPed))\n\t\treturn nil;\n\tswitch (pAttractor->GetEffect()->pedattr.type) {\n\tcase ATTRACTOR_ATM: return IsInQueue(pPed, pAttractor, vAtmAttractors);\n\tcase ATTRACTOR_SEAT: return IsInQueue(pPed, pAttractor, vSeatAttractors);\n\tcase ATTRACTOR_STOP: return IsInQueue(pPed, pAttractor, vStopAttractors);\n\tcase ATTRACTOR_PIZZA: return IsInQueue(pPed, pAttractor, vPizzaAttractors);\n\tcase ATTRACTOR_SHELTER: return IsInQueue(pPed, pAttractor, vShelterAttractors);\n\tcase ATTRACTOR_ICECREAM: return IsInQueue(pPed, pAttractor, vIceCreamAttractors);\n\t}\n\treturn nil;\n}\n\nbool CPedAttractorManager::HasEmptySlot(const C2dEffect* pEffect)\n{\n\tif (!pEffect)\n\t\treturn false;\n\tif (pEffect->type != EFFECT_PED_ATTRACTOR)\n\t\treturn nil;\n\tconst CPedAttractor* pAttractor;\n\tswitch (pEffect->pedattr.type) {\n\tcase ATTRACTOR_ATM: pAttractor = FindAssociatedAttractor(pEffect, vAtmAttractors); break;\n\tcase ATTRACTOR_SEAT: pAttractor = FindAssociatedAttractor(pEffect, vSeatAttractors); break;\n\tcase ATTRACTOR_STOP: pAttractor = FindAssociatedAttractor(pEffect, vStopAttractors); break;\n\tcase ATTRACTOR_PIZZA: pAttractor = FindAssociatedAttractor(pEffect, vPizzaAttractors); break;\n\tcase ATTRACTOR_SHELTER: pAttractor = FindAssociatedAttractor(pEffect, vShelterAttractors); break;\n\tcase ATTRACTOR_ICECREAM: pAttractor = FindAssociatedAttractor(pEffect, vIceCreamAttractors); break;\n\tdefault: return true;\n\t}\n\tif (!pAttractor)\n\t\treturn true;\n\treturn pAttractor->GetNoOfRegisteredPeds() < pAttractor->GetMaxPedsInAttractor();\n}\n\nbool CPedAttractorManager::IsPedRegisteredWithEffect(CPed* pPed)\n{\n\treturn IsPedRegistered(pPed, vAtmAttractors) ||\n\t\tIsPedRegistered(pPed, vSeatAttractors) ||\n\t\tIsPedRegistered(pPed, vStopAttractors) ||\n\t\tIsPedRegistered(pPed, vPizzaAttractors) ||\n\t\tIsPedRegistered(pPed, vShelterAttractors) ||\n\t\tIsPedRegistered(pPed, vIceCreamAttractors);\n}\n\nvoid CPedAttractorManager::ComputeEffectPos(const C2dEffect* pEffect, const CMatrix& matrix, CVector& pos)\n{\n\tpos = matrix.GetPosition() + Multiply3x3(matrix, pEffect->pos);\n}\n\nvoid CPedAttractorManager::ComputeEffectQueueDir(const C2dEffect* pEffect, const CMatrix& matrix, CVector& pos)\n{\n\tpos = Multiply3x3(matrix, pEffect->pedattr.queueDir);\n}\n\nvoid CPedAttractorManager::ComputeEffectUseDir(const C2dEffect* pEffect, const CMatrix& matrix, CVector& pos)\n{\n\tpos = Multiply3x3(matrix, pEffect->pedattr.useDir);\n}\n\nCPedAttractor* CPedAttractorManager::RegisterPed(CPed* pPed, C2dEffect* pEffect, const CMatrix& matrix, std::vector<CPedAttractor*>& vecAttractors)\n{\n\tCPedAttractor* pRegisteredAttractor = nil;\n\tfor (std::vector<CPedAttractor*>::const_iterator pAttractorIt = vecAttractors.begin(); pAttractorIt != vecAttractors.end(); ++pAttractorIt) {\n\t\tCPedAttractor* pAttractor = *pAttractorIt;\n\t\tCVector vEffectPos;\n\t\tComputeEffectPos(pAttractor->GetEffect(), matrix, vEffectPos);\n\t\tif (pAttractor->GetEffect() == pEffect && vEffectPos == pAttractor->GetEffectPos()) {\n\t\t\tif (!IsApproachable(pEffect, matrix, pAttractor->ComputeFreeSlot(), pPed))\n\t\t\t\treturn nil;\n\t\t\tpRegisteredAttractor = pAttractor;\n\t\t\tbreak;\n\t\t}\n\t}\n\tif (pRegisteredAttractor || !IsApproachable(pEffect, matrix, 0, pPed)) {\n\t\tif (pRegisteredAttractor)\n\t\t\tpRegisteredAttractor->RegisterPed(pPed);\n\t\treturn pRegisteredAttractor;\n\t}\n\tPUSH_MEMID(MEMID_PED_ATTR);\n\tswitch (pEffect->pedattr.type) {\n\tcase ATTRACTOR_ATM: pRegisteredAttractor = new CPedAtmAttractor(pEffect, matrix, gcMaxSizeOfAtmQueue, 1.0f, 30000.0f, 3000.0f, 0.2f, 0.15f, 0.1f, 0.1f); vecAttractors.push_back(pRegisteredAttractor); break;\n\tcase ATTRACTOR_SEAT: pRegisteredAttractor = new CPedSeatAttractor(pEffect, matrix, gcMaxSizeOfSeatQueue, 1.0f, 30000.0f, 3000.0f, 0.125f, 0.1f, 0.1f, 0.1f); vecAttractors.push_back(pRegisteredAttractor); break;\n\tcase ATTRACTOR_STOP: pRegisteredAttractor = new CPedStopAttractor(pEffect, matrix, gcMaxSizeOfStopQueue, 1.0f, 30000.0f, 3000.0f, 0.2f, 0.1f, 0.1f, 0.1f); vecAttractors.push_back(pRegisteredAttractor); break;\n\tcase ATTRACTOR_PIZZA: pRegisteredAttractor = new CPedPizzaAttractor(pEffect, matrix, gcMaxSizeOfPizzaQueue, 1.0f, 30000.0f, 3000.0f, 0.2f, 0.1f, 0.1f, 0.1f); vecAttractors.push_back(pRegisteredAttractor); break;\n\tcase ATTRACTOR_SHELTER: pRegisteredAttractor = new CPedShelterAttractor(pEffect, matrix, gcMaxSizeOfShelterQueue, 1.0f, 30000.0f, 3000.0f, 0.5f, 6.28f, 0.1f, 0.1f); vecAttractors.push_back(pRegisteredAttractor); break;\n\tcase ATTRACTOR_ICECREAM: pRegisteredAttractor = new CPedIceCreamAttractor(pEffect, matrix, gcMaxSizeOfIceCreamQueue, 1.0f, 30000.0f, 3000.0f, 0.2f, 0.3f, 0.1f, 0.1f); vecAttractors.push_back(pRegisteredAttractor); break;\n\t}\n\tPOP_MEMID();\n\tif (pRegisteredAttractor)\n\t\tpRegisteredAttractor->RegisterPed(pPed);\n\treturn pRegisteredAttractor;\n}\n\nbool CPedAttractorManager::DeRegisterPed(CPed* pPed, CPedAttractor* pAttractor, std::vector<CPedAttractor*>& vecAttractors)\n{\n\tif (!pAttractor)\n\t\treturn false;\n\tCPedAttractor* pFound = nil;\n\tfor (std::vector<CPedAttractor*>::const_iterator pAttractorIt = vecAttractors.begin(); pAttractorIt != vecAttractors.end(); ++pAttractorIt) {\n\t\tif (*pAttractorIt == pAttractor) {\n\t\t\tpFound = *pAttractorIt;\n\t\t\tbreak;\n\t\t}\n\t}\n\tif (!pFound)\n\t\treturn false;\n\tpFound->DeRegisterPed(pPed);\n\tif (pFound->GetNoOfRegisteredPeds() != 0)\n\t\treturn true;\n\tfor (std::vector<CPedAttractor*>::iterator pAttractorIt = vecAttractors.begin(); pAttractorIt != vecAttractors.end(); ++pAttractorIt) {\n\t\tif (*pAttractorIt == pAttractor) {\n\t\t\tvecAttractors.erase(pAttractorIt);\n\t\t\tbreak;\n\t\t}\n\t}\n\tdelete pAttractor;\n\treturn true;\n}\n\nbool CPedAttractorManager::BroadcastArrival(CPed* pPed, CPedAttractor* pAttractor, std::vector<CPedAttractor*>& vecAttractors)\n{\n\tif (!pAttractor)\n\t\treturn false;\n\tCPedAttractor* pFound = nil;\n\tfor (std::vector<CPedAttractor*>::const_iterator pAttractorIt = vecAttractors.begin(); pAttractorIt != vecAttractors.end(); ++pAttractorIt) {\n\t\tif (*pAttractorIt == pAttractor) {\n\t\t\tpFound = *pAttractorIt;\n\t\t\tbreak;\n\t\t}\n\t}\n\tif (!pFound)\n\t\treturn false;\n\tpFound->BroadcastArrival(pPed);\n\treturn true;\n}\n\nbool CPedAttractorManager::BroadcastDeparture(CPed* pPed, CPedAttractor* pAttractor, std::vector<CPedAttractor*>& vecAttractors)\n{\n\tif (!pAttractor)\n\t\treturn false;\n\tCPedAttractor* pFound = nil;\n\tfor (std::vector<CPedAttractor*>::const_iterator pAttractorIt = vecAttractors.begin(); pAttractorIt != vecAttractors.end(); ++pAttractorIt) {\n\t\tif (*pAttractorIt == pAttractor) {\n\t\t\tpFound = *pAttractorIt;\n\t\t\tbreak;\n\t\t}\n\t}\n\tif (!pFound)\n\t\treturn false;\n\tpFound->DeRegisterPed(pPed);\n\tif (pFound->GetNoOfRegisteredPeds() != 0)\n\t\treturn true;\n\tfor (std::vector<CPedAttractor*>::iterator pAttractorIt = vecAttractors.begin(); pAttractorIt != vecAttractors.end(); ++pAttractorIt) {\n\t\tif (*pAttractorIt == pAttractor) {\n\t\t\tvecAttractors.erase(pAttractorIt);\n\t\t\tbreak;\n\t\t}\n\t}\n\tdelete pAttractor;\n\treturn true;\n}\n\nbool CPedAttractorManager::IsInQueue(CPed* pPed, CPedAttractor* pAttractor, std::vector<CPedAttractor*>& vecAttractors)\n{\n\tif (!pAttractor)\n\t\treturn false;\n\tfor (std::vector<CPedAttractor*>::const_iterator pAttractorIt = vecAttractors.begin(); pAttractorIt != vecAttractors.end(); ++pAttractorIt) {\n\t\tif (*pAttractorIt == pAttractor) {\n\t\t\treturn (*pAttractorIt)->IsInQueue(pPed);\n\t\t}\n\t}\n\treturn false;\n}\n\nbool CPedAttractorManager::IsAtHeadOfQueue(CPed* pPed, CPedAttractor* pAttractor, std::vector<CPedAttractor*>& vecAttractors)\n{\n\tif (!pAttractor)\n\t\treturn false;\n\tfor (std::vector<CPedAttractor*>::const_iterator pAttractorIt = vecAttractors.begin(); pAttractorIt != vecAttractors.end(); ++pAttractorIt) {\n\t\tif (*pAttractorIt == pAttractor) {\n\t\t\treturn (*pAttractorIt)->IsAtHeadOfQueue(pPed);\n\t\t}\n\t}\n\treturn false;\n}\n\nbool CPedAttractorManager::IsPedRegistered(CPed* pPed, std::vector<CPedAttractor*>& vecAttractors)\n{\n\tfor (std::vector<CPedAttractor*>::const_iterator pAttractorIt = vecAttractors.begin(); pAttractorIt != vecAttractors.end(); ++pAttractorIt) {\n\t\tif ((*pAttractorIt)->IsRegisteredWithPed(pPed))\n\t\t\treturn true;\n\t}\n\treturn false;\n}\n\nbool CPedAttractorManager::IsApproachable(C2dEffect* pEffect, const CMatrix& matrix, int32, CPed* pPed)\n{\n\tif (pEffect->pedattr.type == ATTRACTOR_SHELTER) {\n\t\tCVector pos;\n\t\tComputeEffectPos(pEffect, matrix, pos);\n\t\treturn CWorld::GetIsLineOfSightClear(pPed->GetPosition(), pos, true, false, false, false, false, false);\n\t}\n\tCVector vecUseDir, vecEffectPos;\n\tComputeEffectUseDir(pEffect, matrix, vecUseDir);\n\tComputeEffectPos(pEffect, matrix, vecEffectPos);\n\tfloat dp = -DotProduct(vecUseDir, vecEffectPos);\n\tif (pEffect->pedattr.type == ATTRACTOR_ATM || pEffect->pedattr.type == ATTRACTOR_PIZZA || pEffect->pedattr.type == ATTRACTOR_ICECREAM) {\n\t\tvecUseDir = -vecUseDir;\n\t\tdp = -dp;\n\t}\n\tif (dp + DotProduct(vecEffectPos, pPed->GetPosition()) > 0.0f) {\n\t\tCVector vecPedToAttractor = pPed->GetPosition() - vecEffectPos;\n\t\tvecPedToAttractor.Normalise();\n\t\tif (DotProduct(vecPedToAttractor, vecUseDir) > 0.25f && CWorld::IsWanderPathClear(pPed->GetPosition(), vecEffectPos, 2.0f, 0))\n\t\t\treturn true;\n\t}\n\treturn false;\n}\n"
  },
  {
    "path": "src/peds/PedAttractor.h",
    "content": "#pragma once\n#include \"common.h\"\n#include <vector>\n\n#include \"2dEffect.h\"\n#include \"Ped.h\"\n\n#define NUM_ATTRACTORS_FOR_ICECREAM_VAN 4\n\nclass CPedAttractor;\n\nclass CVehicleToEffect\n{\n\tCVehicle* m_pVehicle;\n\tC2dEffect m_effects[NUM_ATTRACTORS_FOR_ICECREAM_VAN];\n\npublic:\n\tCVehicleToEffect(CVehicle* pVehicle);\n\tconst C2dEffect* ChooseEffect(const CVector& pos) const;\n\tCVehicleToEffect& From(const CVehicleToEffect& other);\n\tCVehicleToEffect& operator=(const CVehicleToEffect& other) { return From(other); }\n\t~CVehicleToEffect() { m_pVehicle = nil; }\n\tCVehicle* GetVehicle() const { return m_pVehicle; }\n\tbool HasThisEffect(C2dEffect* pEffect) const;\n\tconst C2dEffect* GetEffect(int32 i) const { return &m_effects[i]; }\n};\n\nclass CPedAttractorManager\n{\n\tstd::vector<CPedAttractor*> vAtmAttractors;\n\tstd::vector<CPedAttractor*> vSeatAttractors;\n\tstd::vector<CPedAttractor*> vStopAttractors;\n\tstd::vector<CPedAttractor*> vPizzaAttractors;\n\tstd::vector<CPedAttractor*> vShelterAttractors;\n\tstd::vector<CPedAttractor*> vIceCreamAttractors;\n\tstd::vector<CVehicleToEffect> vVehicleToEffect;\n\npublic:\n\tCPedAttractor* RegisterPedWithAttractor(CPed* pPed, C2dEffect* pEffect, const CMatrix& matrix);\n\tCPedAttractor* RegisterPed(CPed* pPed, C2dEffect* pEffect, const CMatrix& matrix, std::vector<CPedAttractor*>& vecAttractors);\n\tbool BroadcastArrival(CPed* pPed, CPedAttractor* pAttractor);\n\tbool BroadcastArrival(CPed* pPed, CPedAttractor* pAttractor, std::vector<CPedAttractor*>& vecAttractors);\n\tconst C2dEffect* GetEffectForIceCreamVan(CVehicle* pVehicle, const CVector& pos);\n\tbool IsApproachable(C2dEffect* pEffect, const CMatrix& matrix, int32, CPed* pPed);\n\tvoid RemoveIceCreamVanEffects(C2dEffect* pEffect);\n\tbool HasEmptySlot(const C2dEffect* pEffect);\n\tconst CPedAttractor* FindAssociatedAttractor(const C2dEffect* pEffect, std::vector<CPedAttractor*>& vecAttractors);\n\tbool IsInQueue(CPed* pPed, CPedAttractor* pAttractor);\n\tbool IsInQueue(CPed* pPed, CPedAttractor* pAttractor, std::vector<CPedAttractor*>& vecAttractors);\n\tbool IsAtHeadOfQueue(CPed* pPed, CPedAttractor* pAttractor);\n\tbool IsAtHeadOfQueue(CPed* pPed, CPedAttractor* pAttractor, std::vector<CPedAttractor*>& vecAttractors);\n\tbool BroadcastDeparture(CPed* pPed, CPedAttractor* pAttractor);\n\tbool BroadcastDeparture(CPed* pPed, CPedAttractor* pAttractor, std::vector<CPedAttractor*>& vecAttractors);\n\tbool DeRegisterPed(CPed* pPed, CPedAttractor* pAttractor);\n\tbool DeRegisterPed(CPed* pPed, CPedAttractor* pAttractor, std::vector<CPedAttractor*>& vecAttractors);\n\tbool IsPedRegisteredWithEffect(CPed* pPed);\n\tbool IsPedRegistered(CPed* pPed, std::vector<CPedAttractor*>& vecAttractors);\n\tCVehicle* GetIceCreamVanForEffect(C2dEffect* pEffect);\n\n\tstatic void ComputeEffectPos(const C2dEffect* pEffect, const CMatrix& matrix, CVector& pos);\n\tstatic void ComputeEffectQueueDir(const C2dEffect* pEffect, const CMatrix& matrix, CVector& pos);\n\tstatic void ComputeEffectUseDir(const C2dEffect* pEffect, const CMatrix& matrix, CVector& pos);\n\n};\n\nCPedAttractorManager* GetPedAttractorManager();\n\nenum ePedAttractorType\n{\n\tATTRACTOR_ATM = 0,\n\tATTRACTOR_SEAT,\n\tATTRACTOR_STOP,\n\tATTRACTOR_PIZZA,\n\tATTRACTOR_SHELTER,\n\tATTRACTOR_ICECREAM\n};\n\nclass CPedAttractor\n{\nprotected:\n\tC2dEffect* p2dEffect;\n\tstd::vector<CPed*> vApproachingQueue;\n\tstd::vector<CPed*> vWaitingQueue;\n\tint32 m_nMaxPedsInAttractor;\n\tfloat m_fQueueDistance;\n\tfloat m_fTimeInWaitQueue;\n\tfloat m_fTimeInApproachingQueue;\n\tfloat m_fDistanceToUseAttractor;\n\tfloat m_fAcceptableHeading;\n\tfloat m_fMaxPositionDisplacement;\n\tfloat m_fMaxHeadingDisplacement;\n\tCVector vecEffectPos;\n\tCVector vecQueueDir;\n\tCVector vecUseDir;\n\npublic:\n\tvirtual float GetHeadOfQueueWaitTime() { return 0.0f; }\n\tvirtual ~CPedAttractor() {};\n\tvirtual ePedAttractorType GetType() const = 0;\n\tvirtual void UpdatePedStateOnDeparture(CPed* pPed) const = 0;\n\tvirtual bool IsAtHeadOfQueue(CPed* pPed) const { return vWaitingQueue.front() == pPed; }\n\tvirtual void ComputeAttractPos(int32 id, CVector& pos) const;\n\tvirtual void ComputeAttractHeading(int32 id, float& pHeading) const;\n\tvirtual bool BroadcastDeparture(CPed* pPed);\n\n\tbool IsRegisteredWithPed(CPed* pPed) const;\n\tbool DeRegisterPed(CPed* pPed);\n\tfloat ComputeDeltaHeading() const;\n\tfloat ComputeDeltaPos() const;\n\tvoid ComputeAttractTime(int32 id, bool, float& time) const;\n\tint32 GetNoOfRegisteredPeds() const { return (int32)(vWaitingQueue.size() + vApproachingQueue.size()); }\n\tint32 ComputeFreeSlot() const { return (int32)vWaitingQueue.size(); }\n\tbool IsInQueue(CPed*) const;\n\tbool RegisterPed(CPed*);\n\tbool BroadcastArrival(CPed*);\n\n\tCPedAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float distance, float headingdiff, float posdisp, float headdisp);\n\n\tC2dEffect* GetEffect() const { return p2dEffect; }\n\tconst CVector& GetEffectPos() const { return vecEffectPos; }\n\tint32 GetMaxPedsInAttractor() const { return m_nMaxPedsInAttractor; }\n\tfloat GetDistanceToCountSeekDone() const { return m_fDistanceToUseAttractor; }\n\tfloat GetAcceptableHeading() const { return m_fAcceptableHeading; }\n};\n\nclass CPedAtmAttractor : public CPedAttractor\n{\npublic:\n\tvirtual ePedAttractorType GetType() const { return ATTRACTOR_ATM; };\n\tvirtual void UpdatePedStateOnDeparture(CPed* pPed) const;\n\tCPedAtmAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float distance, float headingdiff, float posdisp, float headdisp) :\n\t\tCPedAttractor(pEffect, matrix, maxpeds, qdist, waitTime, approachTime, distance, headingdiff, posdisp, headdisp)\n\t{};\n};\n\nclass CPedIceCreamAttractor : public CPedAttractor\n{\npublic:\n\tvirtual ~CPedIceCreamAttractor() { GetPedAttractorManager()->RemoveIceCreamVanEffects(p2dEffect); }\n\tvirtual ePedAttractorType GetType() const { return ATTRACTOR_ICECREAM; }\n\tvirtual void UpdatePedStateOnDeparture(CPed* pPed) const {};\n\tCPedIceCreamAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float distance, float headingdiff, float posdisp, float headdisp) :\n\t\tCPedAttractor(pEffect, matrix, maxpeds, qdist, waitTime, approachTime, distance, headingdiff, posdisp, headdisp)\n\t{};\n};\n\nclass CPedPizzaAttractor : public CPedAttractor\n{\npublic:\n\tvirtual float GetHeadOfQueueWaitTime() { return 2000.0f; }\n\tvirtual ePedAttractorType GetType() const { return ATTRACTOR_PIZZA; }\n\tvirtual void UpdatePedStateOnDeparture(CPed* pPed) const;\n\tCPedPizzaAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float distance, float headingdiff, float posdisp, float headdisp) :\n\t\tCPedAttractor(pEffect, matrix, maxpeds, qdist, waitTime, approachTime, distance, headingdiff, posdisp, headdisp)\n\t{};\n};\n\nclass CPedSeatAttractor : public CPedAttractor\n{\npublic:\n\tvirtual ePedAttractorType GetType() const { return ATTRACTOR_SEAT; }\n\tvirtual void UpdatePedStateOnDeparture(CPed* pPed) const {};\n\tCPedSeatAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float distance, float headingdiff, float posdisp, float headdisp) :\n\t\tCPedAttractor(pEffect, matrix, maxpeds, qdist, waitTime, approachTime, distance, headingdiff, posdisp, headdisp)\n\t{};\n};\n\nclass CPedShelterAttractor : public CPedAttractor\n{\n\tstatic std::vector<CVector> ms_displacements;\npublic:\n\tvirtual ePedAttractorType GetType() const { return ATTRACTOR_SHELTER; }\n\tvirtual bool BroadcastDeparture(CPed*);\n\tvirtual void UpdatePedStateOnDeparture(CPed* pPed) const {};\n\tvirtual bool IsAtHeadOfQueue(CPed* pPed) const { return true; }\n\tvirtual void ComputeAttractPos(int qid, CVector& pos) const;\n\tvirtual void ComputeAttractHeading(int qid, float& heading) const;\n\n\tCPedShelterAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float distance, float headingdiff, float posdisp, float headdisp) :\n\t\tCPedAttractor(pEffect, matrix, maxpeds, qdist, waitTime, approachTime, distance, headingdiff, posdisp, headdisp)\n\t{};\n\n\n\tCVector GetDisplacement(int32 qid) const;\n};\n\nclass CPedStopAttractor : public CPedAttractor\n{\npublic:\n\tvirtual ePedAttractorType GetType() const { return ATTRACTOR_STOP; }\n\tvirtual void UpdatePedStateOnDeparture(CPed* pPed) const {};\n\n\tCPedStopAttractor(C2dEffect* pEffect, const CMatrix& matrix, int32 maxpeds, float qdist, float waitTime, float approachTime, float distance, float headingdiff, float posdisp, float headdisp) :\n\t\tCPedAttractor(pEffect, matrix, maxpeds, qdist, waitTime, approachTime, distance, headingdiff, posdisp, headdisp)\n\t{};\n};"
  },
  {
    "path": "src/peds/PedChat.cpp",
    "content": "#include \"common.h\"\n#include \"Camera.h\"\n#include \"DMAudio.h\"\n#include \"General.h\"\n#include \"Ped.h\"\n\n// Corresponds to ped sounds (from SOUND_PED_DEATH to SOUND_PED_TAXI_CALL)\nPedAudioData CommentWaitTime[56] = {\n  { 500, 800, 500, 2 },\n  { 500, 800, 500, 2 },\n  { 500, 800, 500, 2 },\n  { 500, 800, 500, 2 },\n  { 100, 2, 100, 2 },\n  { 500, 500, 2000, 1000 },\n  { 2000, 50, 2050, 1000 },\n  { 5000, 2000, 7000, 3000 },\n  { 5000, 2000, 7000, 3000 },\n  { 300, 200, 500, 200 },\n  { 3000, 1000, 4000, 1000 },\n  { 6000, 6000, 6000, 6000 },\n  { 4000, 1000, 5000, 1000 },\n  { 3000, 1000, 4000, 1000 },\n  { 1000, 1000, 2000, 2000 },\n  { 1000, 500, 2000, 1500 },\n  { 1700, 1000, 3000, 1000 },\n  { 800, 200, 1000, 500 },\n  { 800, 200, 1000, 500 },\n  { 800, 400, 2000, 1000 },\n  { 800, 400, 2000, 1000 },\n  { 2000, 2000, 4000, 4000 },\n  { 2000, 2000, 4000, 1000 },\n  { 4000, 1000, 5000, 1000 },\n  { 800, 400, 1200, 500 },\n  { 5000, 1000, 6000, 2000 },\n  { 5000, 1000, 6000, 2000 },\n  { 5000, 1000, 6000, 2000 },\n  { 5000, 1000, 6000, 2000 },\n  { 5000, 1000, 6000, 2000 },\n  { 5000, 1000, 6000, 2000 },\n  { 5000, 1000, 6000, 2000 },\n  { 4000, 2000, 7000, 2000 },\n  { 1000, 300, 2000, 1000 },\n  { 1500, 1000, 2500, 1000 },\n  { 200, 200, 200, 200 },\n  { 2000, 1000, 4000, 1000 },\n  { 2000, 1000, 4000, 1000 },\n  { 1000, 500, 3000, 1000 },\n  { 1000, 500, 1000, 1000 },\n  { 3000, 2000, 5000, 1000 },\n  { 3000, 2000, 5000, 1000 },\n  { 3000, 2000, 3000, 2000 },\n  { 2000, 1000, 3000, 1000 },\n  { 2500, 1000, 5000, 5000 },\n  { 2000, 1000, 3000, 2000 },\n  { 4000, 1000, 5000, 1000 },\n  { 1000, 500, 2000, 4000 },\n  { 1000, 500, 2000, 5000 },\n  { 2000, 500, 2500, 500 },\n  { 1000, 500, 3000, 2000 },\n  { 1600, 1000, 2000, 2000 },\n  { 2000, 1000, 4000, 2000 },\n  { 1500, 1000, 2500, 1000 },\n  { 1000, 1000, 5000, 5000 },\n  { 0, 0, 0, 0 }\n};\n\nbool\nCPed::ServiceTalkingWhenDead(void)\n{\n\treturn m_queuedSound == SOUND_PED_DEATH;\n}\n\nvoid\nCPed::ServiceTalking(void)\n{\n\tif (bBodyPartJustCameOff && m_bodyPartBleeding == PED_HEAD)\n\t\treturn;\n\n\tif (!CGame::germanGame && m_pFire)\n\t\tm_queuedSound = SOUND_PED_BURNING;\n\n\tif (m_queuedSound != SOUND_NO_SOUND) {\n\t\tif (m_queuedSound == SOUND_PED_DEATH)\n\t\t\tm_soundStart = CTimer::GetTimeInMilliseconds() - 1;\n\n\t\tif (CTimer::GetTimeInMilliseconds() > m_soundStart) {\n\t\t\tDMAudio.PlayOneShot(m_audioEntityId, m_queuedSound, 1.0f);\n\t\t\tm_lastSoundStart = CTimer::GetTimeInMilliseconds();\n\t\t\tm_soundStart =\n\t\t\t\tCommentWaitTime[m_queuedSound - SOUND_PED_DEATH].m_nFixedDelayTime\n\t\t\t\t+ CTimer::GetTimeInMilliseconds()\n\t\t\t\t+ CGeneral::GetRandomNumberInRange(0, CommentWaitTime[m_queuedSound - SOUND_PED_DEATH].m_nOverrideFixedDelayTime);\n\n\t\t\tif (m_queuedSound == SOUND_PED_PLAYER_BEFORESEX && IsPlayer())\n\t\t\t\tm_soundStart += 2000;\n\n\t\t\tm_lastQueuedSound = m_queuedSound;\n\t\t\tm_queuedSound = SOUND_NO_SOUND;\n\t\t}\n\t}\n}\n\nvoid\nCPed::Say(uint16 audio)\n{\n\tif (3.0f + TheCamera.GetPosition().z < GetPosition().z)\n\t\treturn;\n\n\tif (TheCamera.m_CameraAverageSpeed > 1.65f) {\n\t\tif (audio != SOUND_PED_DAMAGE && audio != SOUND_PED_HIT && audio != SOUND_PED_LAND)\n\t\t\treturn;\n\n\t} else if (TheCamera.m_CameraAverageSpeed > 1.25f) {\n\t\tif (audio != SOUND_PED_DEATH &&\n\t\t\taudio != SOUND_PED_DAMAGE && audio != SOUND_PED_HIT && audio != SOUND_PED_LAND &&\n\t\t\taudio != SOUND_PED_TAXI_WAIT && audio != SOUND_PED_EVADE)\n\t\t\treturn;\n\n\t} else if (TheCamera.m_CameraAverageSpeed > 0.9f) {\n\t\tswitch (audio) {\n\t\t\tcase SOUND_PED_DEATH:\n\t\t\tcase SOUND_PED_DAMAGE:\n\t\t\tcase SOUND_PED_HIT:\n\t\t\tcase SOUND_PED_LAND:\n\t\t\tcase SOUND_PED_BURNING:\n\t\t\tcase SOUND_PED_FLEE_SPRINT:\n\t\t\tcase SOUND_PED_TAXI_WAIT:\n\t\t\tcase SOUND_PED_EVADE:\n\t\t\tcase SOUND_PED_CRASH_VEHICLE:\n\t\t\tcase SOUND_PED_CRASH_CAR:\n\t\t\tcase SOUND_PED_ANNOYED_DRIVER:\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\treturn;\n\t\t}\n\t}\n\n\tif (audio < m_queuedSound) {\n\t\tif (audio != m_lastQueuedSound || audio == SOUND_PED_DEATH\n\n\t\t// See VC Ped Speech patch\n#ifdef FIX_BUGS\n\t\t\t|| CommentWaitTime[audio - SOUND_PED_DEATH].m_nOverrideMaxRandomDelayTime\n\t\t\t\t+ (uint32)CGeneral::GetRandomNumberInRange(0, CommentWaitTime[audio - SOUND_PED_DEATH].m_nMaxRandomDelayTime)\n#else\n\t\t\t|| CommentWaitTime[m_queuedSound - SOUND_PED_DEATH].m_nOverrideMaxRandomDelayTime\n\t\t\t+ (uint32)CGeneral::GetRandomNumberInRange(0, CommentWaitTime[m_queuedSound - SOUND_PED_DEATH].m_nMaxRandomDelayTime)\n#endif\n\t\t\t\t+ m_lastSoundStart <= CTimer::GetTimeInMilliseconds()) {\n\t\t\tm_queuedSound = audio;\n\t\t}\n\t}\n}"
  },
  {
    "path": "src/peds/PedDebug.cpp",
    "content": "#include \"common.h\"\n#ifndef MASTER\n#include \"main.h\"\n#include \"Camera.h\"\n#include \"Font.h\"\n#include \"Ped.h\"\n#include \"Sprite.h\"\n#include \"Text.h\"\n\nstatic char ObjectiveText[][28] = {\n\t\"No Obj\",\n\t\"Wait on Foot\",\n\t\"Wait on Foot for cop\",\n\t\"Flee on Foot Till Safe\",\n\t\"Guard Spot\",\n\t\"Guard Area\",\n\t\"Wait in Car\",\n\t\"Wait in Car then Getout\",\n\t\"Kill Char on Foot\",\n\t\"Kill Char Any Means\",\n\t\"Flee Char on Foot Till Safe\",\n\t\"Flee Char on Foot Always\",\n\t\"GoTo Char on Foot\",\n\t\"GoTo Char on Foot walking\",\n\t\"Hassle char\",\n\t\"Follow Char in Formation\",\n\t\"Leave Car\",\n\t\"Enter Car as Passenger\",\n\t\"Enter Car as Driver\",\n\t\"Follow Car in Car\",\n\t\"Fire at Obj from Vehicle\",\n\t\"Destroy Obj\",\n\t\"Destroy Car\",\n\t\"GoTo Area Any Means\",\n\t\"GoTo Area on Foot\",\n\t\"Run to Area\",\n\t\"GoTo Area in Car\",\n\t\"Follow Car on Foot Woffset\",\n\t\"Guard Attack\",\n\t\"Set Leader\",\n\t\"Follow Route\",\n\t\"Solicit vehicle\",\n\t\"Take Taxi\",\n\t\"Catch Train\",\n\t\"Buy IceCream\",\n\t\"Steal Any Car\",\n\t\"Steal any mission car\",\n\t\"Mug Char\",\n\t\"Lv car die\",\n\t\"Goto seat\",\n\t\"Goto atm\",\n\t\"Flee car\",\n\t\"Sunbathe\",\n\t\"Goto bus stop\",\n\t\"Goto pizza\",\n\t\"Goto shelter\",\n\t\"Aim gun at\",\n\t\"Wander\",\n\t\"Wait on foot at shltr\",\n\t\"Sprint to area\",\n\t\"Kill char on boat\",\n\t\"Solicit ped\",\n\t\"Wait at bus stop\",\n\t\"Goto ice cream van foot\",\n\t\"Wait foot icecream van\"\n};\n\nstatic char StateText[][18] = {\n\t\"None\",\n\t\"Idle\",\n\t\"Look Entity\",\n\t\"Look Heading\",\n\t\"Wander Range\",\n\t\"Wander Path\",\n\t\"Seek Pos\",\n\t\"Seek Entity\",\n\t\"Flee Pos\",\n\t\"Flee Entity\",\n\t\"Pursue\",\n\t\"Follow Path\",\n\t\"Sniper Mode\",\n\t\"Rocket Mode\",\n\t\"Dummy\",\n\t\"Pause\",\n\t\"Attack\",\n\t\"Fight\",\n\t\"Face Phone\",\n\t\"Make Call\",\n\t\"Chat\",\n\t\"Mug\",\n\t\"AimGun\",\n\t\"AI Control\",\n\t\"Seek Car\",\n\t\"Seek InBoat\",\n\t\"Follow Route\",\n\t\"C.P.R.\",\n\t\"Solicit\",\n\t\"Buy IceCream\",\n\t\"Investigate\",\n\t\"Step away\",\n\t\"On Fire\",\n\t\"Bathe\",\n\t\"Flash\",\n\t\"Jog\",\n\t\"Answer mobile\",\n\t\"Hang out\",\n\t\"STATES_NO_AI\",\n\t\"Abseil\",\n\t\"Sit\",\n\t\"Jump\",\n\t\"Fall\",\n\t\"GetUp\",\n\t\"Stagger\",\n\t\"Dive away\",\n\t\"STATES_NO_ST\",\n\t\"Enter Train\",\n\t\"Exit Train\",\n\t\"Arrest Plyr\",\n\t\"Driving\",\n\t\"Passenger\",\n\t\"Taxi Passngr\",\n\t\"Open Door\",\n\t\"Die\",\n\t\"Dead\",\n\t\"CarJack\",\n\t\"Drag fm Car\",\n\t\"Enter Car\",\n\t\"Steal Car\",\n\t\"Exit Car\",\n\t\"Hands Up\",\n\t\"Arrested\",\n\t\"Deply stgr\"\n};\n\nstatic char PersonalityTypeText[][18] = {\n\t\"Player\",\n\t\"Cop\",\n\t\"Medic\",\n\t\"Fireman\",\n\t\"Gang 1\",\n\t\"Gang 2\",\n\t\"Gang 3\",\n\t\"Gang 4\",\n\t\"Gang 5\",\n\t\"Gang 6\",\n\t\"Gang 7\",\n\t\"Street Guy\",\n\t\"Suit Guy\",\n\t\"Sensible Guy\",\n\t\"Geek Guy\",\n\t\"Old Guy\",\n\t\"Tough Guy\",\n\t\"Street Girl\",\n\t\"Suit Girl\",\n\t\"Sensible Girl\",\n\t\"Geek Girl\",\n\t\"Old Girl\",\n\t\"Tough Girl\",\n\t\"Tramp\",\n\t\"Tourist\",\n\t\"Prostitute\",\n\t\"Criminal\",\n\t\"Busker\",\n\t\"Taxi Driver\",\n\t\"Psycho\",\n\t\"Steward\",\n\t\"Sports Fan\",\n};\n\nstatic char WaitStateText[][16] = {\n\t\"No Wait\",\n\t\"Traffic Lights\",\n\t\"Pause CrossRoad\",\n\t\"Look CrossRoad\",\n\t\"Look Ped\",\n\t\"Look Shop\",\n\t\"Look Accident\",\n\t\"FaceOff Gang\",\n\t\"Double Back\",\n\t\"Hit Wall\",\n\t\"Turn 180deg\",\n\t\"Surprised\",\n\t\"Ped Stuck\",\n\t\"Look About\",\n\t\"Play Duck\",\n\t\"Play Cower\",\n\t\"Play Taxi\",\n\t\"Play HandsUp\",\n\t\"Play HandsCower\",\n\t\"Play Chat\",\n\t\"Finish Flee\",\n\t\"Sit down\",\n\t\"Sit down rvrs\",\n\t\"Sit up\",\n\t\"Sit idle\",\n\t\"Use atm\",\n\t\"Sunbth pre\",\n\t\"Sunbth down\",\n\t\"Sunbth idle\",\n\t\"Riot\",\n\t\"Fast fall\",\n\t\"Bomber\",\n\t\"Stripper\",\n\t\"Ground attack\",\n\t\"Lance sitting\",\n\t\"Handsup simple\"\n};\n\nvoid\nCPed::DebugDrawPedDestination(CPed *, int, int)\n{\n#ifndef FINAL\n\t// TODO: something was here\n#endif // !FINAL\n}\n\nvoid\nCPed::DebugDrawPedDesiredHeading(CPed *, int, int)\n{\n#ifndef FINAL\n\t// TODO: something was here\n#endif // !FINAL\n}\n\nvoid\nCPed::DebugDrawCollisionRadius(float, float, float, float, int)\n{\n#ifndef FINAL\n\t// TODO: something was here\n#endif // !FINAL\n}\n\nvoid\nCPed::DebugDrawVisionRange(CVector a1, float)\n{\n\tfor (int i = a1.x - 90; i < a1.x + 89; i += 30) {\n#ifndef FINAL\n\t\t// TODO: something was here\n#endif // !FINAL\n\t}\n}\n\nvoid\nCPed::DebugDrawVisionSimple(CVector, float)\n{\n#ifndef FINAL\n\t// TODO: something was here\n#endif // !FINAL\n}\n\nvoid\nCPed::DebugDrawLook()\n{\n#ifndef FINAL\n\t// TODO: something was here\n#endif // !FINAL\n}\n\nvoid\nCPed::DebugDrawPedPsyche()\n{\n#ifndef FINAL\n\t// TODO: something was here\n#endif // !FINAL\n}\n\nvoid\nCPed::DebugDrawDebugLines()\n{\n#ifndef FINAL\n\t// TODO: something was here\n#endif // !FINAL\n}\n\nint nDisplayDebugInfo = 0;\n\nvoid\nCPed::SwitchDebugDisplay(void)\n{\n\tif (++nDisplayDebugInfo > 2)\n\t\tnDisplayDebugInfo = 0;\n}\n\nint\nCPed::GetDebugDisplay(void)\n{\n\treturn nDisplayDebugInfo;\n}\n\nvoid\nCPed::DebugDrawLookAtPoints()\n{\n\t// TODO: mobile code\n}\n\nvoid\nCPed::DebugRenderOnePedText(void)\n{\n\tif ((GetPosition() - TheCamera.GetPosition()).MagnitudeSqr() < sq(30.0f)) {\n\t\tfloat width, height;\n\t\tRwV3d screenCoords;\n\t\tCVector bitAbove = GetPosition();\n\t\tbitAbove.z += 2.0f;\n\t\tif (CSprite::CalcScreenCoors(bitAbove, &screenCoords, &width, &height, true)) {\n\n\t\t\tfloat lineHeight = SCREEN_SCALE_Y(Min(height / 100.0f, 0.7f) * 22.0f);\n\n\t\t\tDefinedState();\n\t\t\tCFont::SetPropOn();\n\t\t\tCFont::SetBackgroundOn();\n\n\t\t\t// Originally both of them were being divided by 60.0f.\n\t\t\tfloat xScale = Min(width / 240.0f, 0.7f);\n\t\t\tfloat yScale = Min(height / 80.0f, 0.7f);\n\n\t\t\tCFont::SetScale(SCREEN_SCALE_X(xScale), SCREEN_SCALE_Y(yScale));\n\t\t\tCFont::SetCentreOn();\n\t\t\tCFont::SetCentreSize(SCREEN_WIDTH);\n\t\t\tCFont::SetJustifyOff();\n\t\t\tCFont::SetColor(CRGBA(255, 255, 0, 255));\n\t\t\tCFont::SetBackGroundOnlyTextOn();\n\t\t\tCFont::SetFontStyle(1);\n\t\t\tAsciiToUnicode(StateText[m_nPedState], gUString);\n\t\t\tCFont::PrintString(screenCoords.x, screenCoords.y, gUString);\n\t\t\tAsciiToUnicode(ObjectiveText[m_objective], gUString);\n\t\t\tCFont::PrintString(screenCoords.x, screenCoords.y + lineHeight, gUString);\n\t\t\tAsciiToUnicode(PersonalityTypeText[m_pedStats->m_type], gUString);\n\t\t\tCFont::PrintString(screenCoords.x, screenCoords.y + 2 * lineHeight, gUString);\n\t\t\tAsciiToUnicode(WaitStateText[m_nWaitState], gUString);\n\t\t\tCFont::PrintString(screenCoords.x, screenCoords.y + 3 * lineHeight, gUString);\n\t\t\tif (m_nPedState == PED_SEEK_POS || m_nPedState == PED_SEEK_ENTITY) {\n\t\t\t\tsprintf(gString, \"Safe distance to target: %.2f\", m_distanceToCountSeekDone);\n\t\t\t\tAsciiToUnicode(gString, gUString);\n\t\t\t\tCFont::PrintString(screenCoords.x, screenCoords.y + 4 * lineHeight, gUString);\n\t\t\t}\n\t\t\tDefinedState();\n\t\t}\n\t}\n}\n\nvoid\nCPed::DebugRenderClosePedText()\n{\n\t// TODO: mobile code\n}\n#endif"
  },
  {
    "path": "src/peds/PedFight.cpp",
    "content": "#include \"common.h\"\n\n#include \"main.h\"\n#include \"RpAnimBlend.h\"\n#include \"AnimBlendClumpData.h\"\n#include \"AnimBlendAssociation.h\"\n#include \"Camera.h\"\n#include \"CarCtrl.h\"\n#include \"Darkel.h\"\n#include \"DMAudio.h\"\n#include \"FileMgr.h\"\n#include \"General.h\"\n#include \"Object.h\"\n#include \"Pad.h\"\n#include \"Particle.h\"\n#include \"Ped.h\"\n#include \"PlayerPed.h\"\n#include \"Stats.h\"\n#include \"TempColModels.h\"\n#include \"VisibilityPlugins.h\"\n#include \"Vehicle.h\"\n#include \"Automobile.h\"\n#include \"WaterLevel.h\"\n#include \"World.h\"\n#include \"Bike.h\"\n#include \"Glass.h\"\n#include \"SpecialFX.h\"\n\nuint16 nPlayerInComboMove;\nRpClump* flyingClumpTemp;\n\nFightMove tFightMoves[NUM_FIGHTMOVES] =\n{\n  { ANIM_STD_NUM,  0.0f,  0.0f,  0.0f,  0.0f,  1.0f, HITLEVEL_NULL, 0, 0 },\n  { ANIM_STD_PUNCH, 0.2f, 8.f/30.f, 0.0f, 0.3f, 1.0f, HITLEVEL_HIGH, 1, 0 },\n  { ANIM_STD_FIGHT_IDLE,  0.0f,  0.0f,  0.0f,  0.0f,  1.0f, HITLEVEL_NULL, 0, 0 },\n  { ANIM_STD_FIGHT_SHUFFLE_F,  0.0f,  0.0f,  0.0f,  0.0f,  1.0f, HITLEVEL_NULL, 0, 0 },\n  { ANIM_STD_FIGHT_KNEE, 4.f/30.f, 0.2f, 0.0f, 0.6f, 1.0f, HITLEVEL_LOW, 2, 0 },\n  { ANIM_STD_FIGHT_LHOOK, 8.f/30.f, 10.f/30.f, 0.0f, 0.4f, 1.0f, HITLEVEL_HIGH, 3, 0 },\n  { ANIM_STD_FIGHT_JAB, 4.f/30.f, 0.2f, 0.0f, 0.7f, 1.0f, HITLEVEL_HIGH, 3, 0 },\n  { ANIM_STD_FIGHT_PUNCH, 4.f/30.f, 7.f/30.f, 10.f/30.f, 0.4f, 1.0f, HITLEVEL_HIGH, 1, 0 },\n  { ANIM_STD_FIGHT_LONGKICK, 8.f/30.f, 10.f/30.f, 0.0f, 0.5f, 1.0f, HITLEVEL_MEDIUM, 4, 0 },\n  { ANIM_STD_FIGHT_ROUNDHOUSE, 8.f/30.f, 10.f/30.f, 0.0f,  0.6f, 1.0f, HITLEVEL_MEDIUM, 4, 0 },\n  { ANIM_STD_FIGHT_KICK,  8.f/30.f,  10.f/30.f,  0.0f,  0.5f,  1.0f, HITLEVEL_HIGH, 2, 0 },\n  { ANIM_STD_FIGHT_HEAD,  8.f/30.f,  10.f/30.f,  0.0f,  0.5f,  1.0f, HITLEVEL_MEDIUM, 2, 0 },\n  { ANIM_STD_FIGHT_BKICK_L,  8.f/30.f,  10.f/30.f,  0.0f,  0.5f,  1.0f, HITLEVEL_LOW, 2, 0 },\n  { ANIM_STD_FIGHT_BKICK_L,  8.f/30.f,  10.f/30.f,  0.0f,  0.5f,  1.0f, HITLEVEL_LOW, 2, 0 },\n  { ANIM_STD_FIGHT_ELBOW_L,  8.f/30.f,  10.f/30.f,  0.0f,  0.5f,  1.0f, HITLEVEL_MEDIUM, 2, 0 },\n  { ANIM_STD_FIGHT_BKICK_R,  8.f/30.f,  10.f/30.f,  0.0f,  0.5f,  1.0f, HITLEVEL_MEDIUM, 2, 0 },\n  { ANIM_STD_FIGHT_ELBOW_R,  8.f/30.f,  10.f/30.f,  0.0f,  0.5f,  1.0f, HITLEVEL_HIGH, 2, 0 },\n  { ANIM_STD_KICKGROUND, 10.f/30.f, 14.f/30.f, 0.0f, 0.4f, 1.0f, HITLEVEL_GROUND, 1, 0 },\n  { ANIM_STD_HIT_FRONT,  0.0f,  0.0f,  0.0f,  0.0f,  1.0f, HITLEVEL_NULL, 0, 0 },\n  { ANIM_STD_HIT_BACK,  0.0f,  0.0f,  0.0f,  0.0f,  1.0f, HITLEVEL_NULL, 0, 0 },\n  { ANIM_STD_HIT_RIGHT,  0.0f,  0.0f,  0.0f,  0.0f,  1.0f, HITLEVEL_NULL, 0, 0 },\n  { ANIM_STD_HIT_LEFT,  0.0f,  0.0f,  0.0f,  0.0f,  1.0f, HITLEVEL_NULL, 0, 0 },\n  { ANIM_STD_HIT_BODYBLOW,  0.0f,  0.0f,  0.0f,  0.0f,  1.0f, HITLEVEL_NULL, 0, 0 },\n  { ANIM_STD_HIT_CHEST,  0.0f,  0.0f,  0.0f,  0.0f,  1.0f, HITLEVEL_NULL, 0, 0 },\n  { ANIM_STD_HIT_HEAD,  0.0f,  0.0f,  0.0f,  0.0f,  1.0f, HITLEVEL_NULL, 0, 0 },\n  { ANIM_STD_HIT_WALK,  0.0f,  0.0f,  0.0f,  0.0f,  1.0f, HITLEVEL_NULL, 0, 0 },\n  { ANIM_STD_HIT_FLOOR,  0.0f,  0.0f,  0.0f,  0.0f,  1.0f, HITLEVEL_NULL, 0, 0 },\n  { ANIM_STD_HIT_BEHIND,  0.0f,  0.0f,  0.0f,  0.0f,  1.0f, HITLEVEL_NULL, 0, 0 },\n  { ANIM_ATTACK_1, 4.f/30.f, 7.f/30.f, 10.f/30.f, 0.4f, 1.0f, HITLEVEL_HIGH, 1, 0 },\n  { ANIM_ATTACK_2, 4.f/30.f, 7.f/30.f, 10.f/30.f, 0.4f, 1.0f, HITLEVEL_HIGH, 1, 0 },\n  { ANIM_ATTACK_3, 4.f / 30.f, 7.f / 30.f, 10.f / 30.f, 0.4f, 1.0f, HITLEVEL_HIGH, 1, 0 },\n  { ANIM_STD_FIGHT_2IDLE,  0.0f,  0.0f,  0.0f,  0.0f,  1.0f, HITLEVEL_NULL, 0, 0 }\n};\n\nstatic PedOnGroundState\nCheckForPedsOnGroundToAttack(CPed *attacker, CPed **pedOnGround)\n{\n\tPedOnGroundState stateToReturn;\n\tfloat angleToFace;\n\tCPed *currentPed = nil;\n\tPedState currentPedState;\n\tCPed *pedOnTheFloor = nil;\n\tCPed *deadPed = nil;\n\tCPed *pedBelow = nil;\n\tbool foundDead = false;\n\tbool foundOnTheFloor = false;\n\tbool foundBelow = false;\n\tfloat angleDiff;\n\tfloat distance;\n\n\tif (!CGame::nastyGame)\n\t\treturn NO_PED;\n\n\tfor (int currentPedId = 0; currentPedId < attacker->m_numNearPeds; currentPedId++) {\n\n\t\tcurrentPed = attacker->m_nearPeds[currentPedId];\n\n\t\tCVector posDifference = currentPed->GetPosition() - attacker->GetPosition();\n\t\tdistance = posDifference.Magnitude();\n\n\t\tif (distance < 2.0f) {\n\t\t\tangleToFace = CGeneral::GetRadianAngleBetweenPoints(\n\t\t\t\tcurrentPed->GetPosition().x, currentPed->GetPosition().y,\n\t\t\t\tattacker->GetPosition().x, attacker->GetPosition().y);\n\n\t\t\tangleToFace = CGeneral::LimitRadianAngle(angleToFace);\n\t\t\tattacker->m_fRotationCur = CGeneral::LimitRadianAngle(attacker->m_fRotationCur);\n\n\t\t\tangleDiff = Abs(angleToFace - attacker->m_fRotationCur);\n\n\t\t\tif (angleDiff > PI)\n\t\t\t\tangleDiff = 2 * PI - angleDiff;\n\n\t\t\tcurrentPedState = currentPed->m_nPedState;\n\n\t\t\tif (currentPed->OnGroundOrGettingUp()) {\n\t\t\t\tif (distance < 2.0f && angleDiff < DEGTORAD(65.0f)) {\n\t\t\t\t\tif (currentPedState == PED_DEAD) {\n\t\t\t\t\t\tfoundDead = 1;\n\t\t\t\t\t\tif (!deadPed)\n\t\t\t\t\t\t\tdeadPed = currentPed;\n\t\t\t\t\t} else if (!currentPed->IsPedHeadAbovePos(-0.6f)) {\n\t\t\t\t\t\tfoundOnTheFloor = 1;\n\t\t\t\t\t\tif (!pedOnTheFloor)\n\t\t\t\t\t\t\tpedOnTheFloor = currentPed;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if ((distance < 0.8f && angleDiff < DEGTORAD(75.0f))\n\t\t\t\t\t\t|| (distance < 1.3f && angleDiff < DEGTORAD(55.0f))\n\t\t\t\t\t\t|| (distance < 1.7f && angleDiff < DEGTORAD(35.0f))\n\t\t\t\t\t\t|| (distance < 2.0f && angleDiff < DEGTORAD(30.0f))) {\n\n\t\t\t\t// Either this condition or below one was probably returning 4 early in development. See Fight().\n\t\t\t\tfoundBelow = 1;\n\t\t\t\tpedBelow = currentPed;\n\t\t\t\tbreak;\n\t\t\t} else {\n\t\t\t\tif (angleDiff < DEGTORAD(75.0f)) {\n\t\t\t\t\tfoundBelow = 1;\n\t\t\t\t\tif (!pedBelow)\n\t\t\t\t\t\tpedBelow = currentPed;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (foundOnTheFloor) {\n\t\tcurrentPed = pedOnTheFloor;\n\t\tstateToReturn = PED_ON_THE_FLOOR;\n\t} else if (foundDead) {\n\t\tcurrentPed = deadPed;\n\t\tstateToReturn = PED_DEAD_ON_THE_FLOOR;\n\t} else if (foundBelow) {\n\t\tcurrentPed = pedBelow;\n\t\tstateToReturn = PED_IN_FRONT_OF_ATTACKER;\n\t} else {\n\t\tcurrentPed = nil;\n\t\tstateToReturn = NO_PED;\n\t}\n\n\tif (pedOnGround)\n\t\t*pedOnGround = currentPed;\n\n\treturn stateToReturn;\n}\n\nvoid\nCPed::SetPointGunAt(CEntity *to)\n{\n\tif (to) {\n\t\tSetLookFlag(to, true, true);\n\t\tSetAimFlag(to);\n\t\tSetLookTimer(INT32_MAX);\n\t}\n\n\tCWeaponInfo* curWeapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);\n\tif (m_nPedState == PED_AIM_GUN || (bIsDucking && !IsPlayer()) || m_nWaitState == WAITSTATE_PLAYANIM_DUCK || curWeapon->m_AnimToPlay == ASSOCGRP_STD)\n\t\treturn;\n\n\tif (m_nPedState != PED_ATTACK)\n\t\tSetStoredState();\n\n\tSetPedState(PED_AIM_GUN);\n\tbIsPointingGunAt = true;\n\tSetMoveState(PEDMOVE_STILL);\n\n\tCAnimBlendAssociation *aimAssoc;\n\n\tif (bCrouchWhenShooting && bIsDucking && GetCrouchFireAnim(curWeapon)) {\n\t\taimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), GetCrouchFireAnim(curWeapon));\n\t} else {\n\t\taimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WEAPON_FIRE);\n\t}\n\n\tif (!aimAssoc || aimAssoc->blendDelta < 0.0f) {\n\t\tif (bCrouchWhenShooting && bIsDucking && GetCrouchFireAnim(curWeapon)) {\n\t\t\taimAssoc = CAnimManager::BlendAnimation(GetClump(), curWeapon->m_AnimToPlay, GetCrouchFireAnim(curWeapon), 4.0f);\n\t\t} else {\n\t\t\taimAssoc = CAnimManager::AddAnimation(GetClump(), curWeapon->m_AnimToPlay, ANIM_WEAPON_FIRE);\n\t\t}\n\n\t\taimAssoc->blendAmount = 0.0f;\n\t\taimAssoc->blendDelta = 8.0f;\n\t}\n\tif (to && !IsPlayer())\n\t\tSay(SOUND_PED_ATTACK);\n}\n\nvoid\nCPed::PointGunAt(void)\n{\n\tCWeaponInfo *weaponInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);\n\tfloat animLoopStart = weaponInfo->m_fAnimLoopStart;\n\tCAnimBlendAssociation *weaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WEAPON_FIRE);\n\tif (!weaponAssoc || weaponAssoc->blendDelta < 0.0f) {\n\t\tif (weaponInfo->IsFlagSet(WEAPONFLAG_CROUCHFIRE)) {\n\t\t\tweaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), GetCrouchFireAnim(weaponInfo));\n\t\t\tanimLoopStart = weaponInfo->m_fAnim2LoopStart;\n\t\t}\n\t}\n\n\tif (weaponAssoc && weaponAssoc->currentTime > animLoopStart * 0.4f) {\n\t\tweaponAssoc->SetCurrentTime(animLoopStart);\n\t\tweaponAssoc->flags &= ~ASSOC_RUNNING;\n\n\t\tif (bIsDucking)\n\t\t\tm_pedIK.m_flags &= ~CPedIK::AIMS_WITH_ARM;\n\n\t\tif (weaponInfo->IsFlagSet(WEAPONFLAG_CANAIM_WITHARM))\n\t\t\tm_pedIK.m_flags |= CPedIK::AIMS_WITH_ARM;\n\t\telse\n\t\t\tm_pedIK.m_flags &= ~CPedIK::AIMS_WITH_ARM;\n\t}\n}\n\nvoid\nCPed::ClearPointGunAt(void)\n{\n\tCAnimBlendAssociation *animAssoc;\n\tCWeaponInfo *weaponInfo;\n\n\tClearLookFlag();\n\tClearAimFlag();\n\tbIsPointingGunAt = false;\n\tif (m_nPedState == PED_AIM_GUN || m_nPedState == PED_ATTACK) {\n\t\tSetPedState(PED_IDLE);\n\t\tRestorePreviousState();\n\t}\n\tweaponInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);\n\tanimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WEAPON_FIRE);\n\tif (!animAssoc || animAssoc->blendDelta < 0.0f) {\n\t\tif (weaponInfo->IsFlagSet(WEAPONFLAG_CROUCHFIRE)) {\n\t\t\tanimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), GetCrouchFireAnim(weaponInfo));\n\t\t}\n\t}\n\tif (animAssoc) {\n\t\tanimAssoc->flags |= ASSOC_DELETEFADEDOUT;\n\t\tanimAssoc->blendDelta = -4.0f;\n\t}\n}\n\nvoid\nCPed::SetAttack(CEntity *victim)\n{\n\tCPed *victimPed = nil;\n\tCWeaponInfo *curWeapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);\n\tCAnimBlendAssociation *animAssoc;\n\n\tif (victim && victim->IsPed())\n\t\tvictimPed = (CPed*)victim;\n\n\tif (m_attackTimer > CTimer::GetTimeInMilliseconds() || m_nWaitState == WAITSTATE_SURPRISE || (bIsDucking && !bCrouchWhenShooting))\n\t\treturn;\n\n\tif (curWeapon->IsFlagSet(WEAPONFLAG_RELOAD) &&\n\t\t(RpAnimBlendClumpGetAssociation(GetClump(), GetReloadAnim(curWeapon)) || RpAnimBlendClumpGetAssociation(GetClump(), GetCrouchReloadAnim(curWeapon)))) {\n\t\tif (!IsPlayer() || m_nPedState != PED_ATTACK || ((CPlayerPed*)this)->m_bHaveTargetSelected)\n\t\t\tbIsAttacking = false;\n\t\telse\n\t\t\tbIsAttacking = true;\n\n\t\treturn;\n\t}\n\n\tif (GetWeapon()->m_eWeaponType == WEAPONTYPE_UNARMED || curWeapon->IsFlagSet(WEAPONFLAG_FIGHTMODE) || GetWeapon()->m_eWeaponType == WEAPONTYPE_BRASSKNUCKLE) {\n\t\tif (IsPlayer() ||\n\t\t\t(m_nPedState != PED_FIGHT && m_nMoveState != PEDMOVE_NONE && m_nMoveState != PEDMOVE_STILL\n\t\t\t\t&& !(m_pedStats->m_flags & STAT_SHOPPING_BAGS) && curWeapon->IsFlagSet(WEAPONFLAG_PARTIALATTACK))) {\n\n\t\t\tif (m_nPedState != PED_ATTACK) {\n\t\t\t\tSetPedState(PED_ATTACK);\n\t\t\t\tbIsAttacking = false;\n\n\t\t\t\tCAnimBlendAssociation *animAssoc = CAnimManager::BlendAnimation(GetClump(), curWeapon->m_AnimToPlay, ANIM_MELEE_ATTACK_START, 8.0f);\n\t\t\t\tanimAssoc->SetRun();\n\t\t\t\tif (animAssoc->currentTime == animAssoc->hierarchy->totalLength)\n\t\t\t\t\tanimAssoc->SetCurrentTime(0.0f);\n\n\t\t\t\tanimAssoc->SetFinishCallback(FinishedAttackCB, this);\n\t\t\t}\n\t\t} else {\n\t\t\tStartFightAttack(CGeneral::GetRandomNumber());\n\t\t}\n\t\treturn;\n\t}\n\n\tif (curWeapon->IsFlagSet(WEAPONFLAG_PARTIALATTACK) &&\n\t\t(IsPlayer() && ((CPlayerPed*)this)->m_fMoveSpeed >= 1.0f ||\n\t\tm_nMoveState == PEDMOVE_WALK || m_nMoveState == PEDMOVE_RUN)) {\n\n\t\tif (m_nPedState != PED_ATTACK) {\n\t\t\tSetPedState(PED_ATTACK);\n\t\t\tbIsAttacking = false;\n\t\t\tCAnimBlendAssociation* animAssoc = CAnimManager::BlendAnimation(GetClump(), curWeapon->m_AnimToPlay, ANIM_MELEE_ATTACK_START, 8.0f);\n\t\t\tanimAssoc->SetRun();\n\t\t\tif (animAssoc->currentTime == animAssoc->hierarchy->totalLength)\n\t\t\t\tanimAssoc->SetCurrentTime(0.0f);\n\n\t\t\tanimAssoc->SetFinishCallback(FinishedAttackCB, this);\n\t\t}\n\t\treturn;\n\t}\n\n\tif (m_pSeekTarget)\n\t\tm_pSeekTarget->CleanUpOldReference(&m_pSeekTarget);\n\tm_pSeekTarget = victim;\n\tif (m_pSeekTarget)\n\t\tm_pSeekTarget->RegisterReference((CEntity **) &m_pSeekTarget);\n\n\tif (curWeapon->IsFlagSet(WEAPONFLAG_CANAIM)) {\n\t\tCVector aimPos = GetRight() * 0.1f + GetForward() * 0.2f + GetPosition();\n\t\taimPos += GetUp() * 0.35f;\n\t\tCEntity *obstacle = CWorld::TestSphereAgainstWorld(aimPos, 0.2f, nil, true, false, false, true, false, false);\n\t\tif (obstacle) {\n\t\t\tif(gaTempSphereColPoints[0].surfaceB != SURFACE_TRANSPARENT_CLOTH && gaTempSphereColPoints[0].surfaceB != SURFACE_METAL_CHAIN_FENCE &&\n\t\t\t\tgaTempSphereColPoints[0].surfaceB != SURFACE_WOOD_BENCH && gaTempSphereColPoints[0].surfaceB != SURFACE_SCAFFOLD_POLE) {\n\t\t\t\tif (!IsPlayer()) {\n\t\t\t\t\tbObstacleShowedUpDuringKillObjective = true;\n\t\t\t\t\tm_shootTimer = 0;\n\t\t\t\t\tSetAttackTimer(1500);\n\t\t\t\t\tm_shotTime = CTimer::GetTimeInMilliseconds();\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tm_pLookTarget = victim;\n\t\tif (victim) {\n\t\t\tm_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget);\n\t\t\tm_pSeekTarget->RegisterReference((CEntity **) &m_pSeekTarget);\n\t\t}\n\n\t\tif (m_pLookTarget) {\n\t\t\tSetAimFlag(m_pLookTarget);\n\t\t} else if (this == FindPlayerPed() && TheCamera.Cams[0].Using3rdPersonMouseCam()) {\n\t\t\tSetAimFlag(m_fRotationCur);\n\t\t\t((CPlayerPed*)this)->m_fFPSMoveHeading = TheCamera.Find3rdPersonQuickAimPitch();\n\t\t} else if (curWeapon->IsFlagSet(WEAPONFLAG_CANAIM_WITHARM)) {\n\t\t\tSetAimFlag(m_fRotationCur);\n\t\t}\n\t}\n\tif (m_nPedState == PED_ATTACK) {\n\t\tbIsAttacking = true;\n\t\treturn;\n\t}\n\n\tif (IsPlayer() || (!victimPed || victimPed->IsPedInControl())) {\n\t\tif (IsPlayer())\n\t\t\tCPad::GetPad(0)->ResetAverageWeapon();\n\n\t\tuint8 pointBlankStatus;\n\t\tif ((curWeapon->m_eWeaponFire == WEAPON_FIRE_INSTANT_HIT || GetWeapon()->m_eWeaponType == WEAPONTYPE_FLAMETHROWER)\n\t\t\t&& TheCamera.PlayerWeaponMode.Mode != CCam::MODE_M16_1STPERSON\n\t\t\t&& TheCamera.PlayerWeaponMode.Mode != CCam::MODE_M16_1STPERSON_RUNABOUT\n\t\t\t&& TheCamera.PlayerWeaponMode.Mode != CCam::MODE_SNIPER\n\t\t\t&& TheCamera.PlayerWeaponMode.Mode != CCam::MODE_SNIPER_RUNABOUT\n\t\t\t&& (pointBlankStatus = CheckForPointBlankPeds(victimPed)) != NO_POINT_BLANK_PED) {\n\t\t\tClearAimFlag();\n\n\t\t\t// This condition is pointless\n\t\t\tif (pointBlankStatus == POINT_BLANK_FOR_WANTED_PED || !victimPed && (IsPlayer() || !m_carInObjective))\n\t\t\t\tStartFightAttack(200);\n\t\t} else {\n\t\t\tif (!curWeapon->IsFlagSet(WEAPONFLAG_CANAIM))\n\t\t\t\tm_pSeekTarget = nil;\n\n\t\t\tif (m_nPedState != PED_AIM_GUN)\n\t\t\t\tSetStoredState();\n\n\t\t\tSetPedState(PED_ATTACK);\n\t\t\tSetMoveState(PEDMOVE_NONE);\n\t\t\tif (bCrouchWhenShooting && bIsDucking && curWeapon->IsFlagSet(WEAPONFLAG_CROUCHFIRE)) {\n\t\t\t\tCAnimBlendAssociation* curMoveAssoc = RpAnimBlendClumpGetAssociation(GetClump(), GetCrouchFireAnim(curWeapon));\n\t\t\t\tif (curMoveAssoc) {\n\t\t\t\t\tif (strcmp(CAnimManager::GetAnimAssociation(curWeapon->m_AnimToPlay, GetCrouchFireAnim(curWeapon))->hierarchy->name, curMoveAssoc->hierarchy->name) != 0) {\n\t\t\t\t\t\tdelete curMoveAssoc;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tanimAssoc = CAnimManager::BlendAnimation(GetClump(), curWeapon->m_AnimToPlay, GetCrouchFireAnim(curWeapon), 8.0f);\n\t\t\t} else {\n\t\t\t\tfloat animDelta = 8.0f;\n\t\t\t\tif (curWeapon->m_eWeaponFire == WEAPON_FIRE_MELEE)\n\t\t\t\t\tanimDelta = 1000.0f;\n\n\t\t\t\tAnimationId fireAnim;\n\t\t\t\tif (curWeapon->IsFlagSet(WEAPONFLAG_THROW))\n\t\t\t\t\tfireAnim = ANIM_THROWABLE_START_THROW;\n\t\t\t\telse if (CGame::nastyGame && (curWeapon->IsFlagSet(WEAPONFLAG_GROUND_2ND) || curWeapon->IsFlagSet(WEAPONFLAG_GROUND_3RD))) {\n\t\t\t\t\tPedOnGroundState pedOnGround = CheckForPedsOnGroundToAttack(this, nil);\n\t\t\t\t\tif (pedOnGround > PED_IN_FRONT_OF_ATTACKER || pedOnGround == NO_PED && bIsStanding && m_pCurSurface && m_pCurSurface->IsVehicle()) {\n\t\t\t\t\t\tfireAnim = GetFireAnimGround(curWeapon, false);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tfireAnim = GetFireAnimNotDucking(curWeapon);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tfireAnim = GetFireAnimNotDucking(curWeapon);\n\t\t\t\t}\n\n\t\t\t\tCAnimBlendAssociation* curFireAssoc = RpAnimBlendClumpGetAssociation(GetClump(), fireAnim);\n\t\t\t\tif (curFireAssoc) {\n\t\t\t\t\tif (strcmp(CAnimManager::GetAnimAssociation(curWeapon->m_AnimToPlay, fireAnim)->hierarchy->name, curFireAssoc->hierarchy->name) != 0) {\n\t\t\t\t\t\tdelete curFireAssoc;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tanimAssoc = CAnimManager::BlendAnimation(GetClump(), curWeapon->m_AnimToPlay, fireAnim, animDelta);\n\t\t\t}\n\n\t\t\tanimAssoc->SetRun();\n\t\t\tif (animAssoc->currentTime == animAssoc->hierarchy->totalLength)\n\t\t\t\tanimAssoc->SetCurrentTime(0.0f);\n\n\t\t\tanimAssoc->SetFinishCallback(FinishedAttackCB, this);\n\t\t}\n\t\treturn;\n\t}\n\n\tif (GetWeapon()->m_eWeaponType == WEAPONTYPE_BASEBALLBAT && victimPed->m_nPedState == PED_GETUP)\n\t\tSetWaitState(WAITSTATE_SURPRISE, nil);\n\n\tSetLookFlag(victim, true, true);\n\tSetLookTimer(100);\n}\n\nvoid\nCPed::ClearAttack(void)\n{\n\tif (m_nPedState != PED_ATTACK || (bIsDucking && !IsPlayer()) || m_nWaitState == WAITSTATE_PLAYANIM_DUCK)\n\t\treturn;\n\n\tif (FindPlayerPed() == this && TheCamera.Using1stPersonWeaponMode()) {\n\t\tSetPointGunAt(nil);\n\t} else if (bIsPointingGunAt) {\n\t\tif (m_pLookTarget)\n\t\t\tSetPointGunAt(m_pLookTarget);\n\t\telse\n\t\t\tClearPointGunAt();\n\t} else if (m_objective != OBJECTIVE_NONE) {\n\t\tSetIdle();\n\t} else {\n\t\tRestorePreviousState();\n\t}\n}\n\nvoid\nCPed::ClearAttackByRemovingAnim(void)\n{\n\tif (m_nPedState != PED_ATTACK)\n\t\treturn;\n\n\tCWeaponInfo *weapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);\n\tCAnimBlendAssociation *weaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), GetPrimaryFireAnim(weapon));\n\n\tif (!weaponAssoc) {\n\t\tif (GetCrouchFireAnim(weapon))\n\t\t\tweaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), GetCrouchFireAnim(weapon));\n\t}\n\tif (!weaponAssoc) {\n\t\tif(GetFinishingAttackAnim(weapon))\n\t\t\tweaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), GetFinishingAttackAnim(weapon));\n\t}\n\tif (!weaponAssoc) {\n\t\tif(GetSecondFireAnim(weapon))\n\t\t\tweaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), GetSecondFireAnim(weapon));\n\t}\n\tif (!weaponAssoc) {\n\t\tif(Get3rdFireAnim(weapon))\n\t\t\tweaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), Get3rdFireAnim(weapon));\n\t}\n\tif (weaponAssoc) {\n\t\tweaponAssoc->blendDelta = -8.0f;\n\t\tweaponAssoc->flags &= ~ASSOC_RUNNING;\n\t\tweaponAssoc->flags |= ASSOC_DELETEFADEDOUT;\n\t\tweaponAssoc->SetDeleteCallback(FinishedAttackCB, this);\n\t} else {\n\t\tClearAttack();\n\t}\n}\n\nvoid\nCPed::FinishedAttackCB(CAnimBlendAssociation *attackAssoc, void *arg)\n{\n\tCAnimBlendAssociation *newAnim, *reloadAnimAssoc = nil;\n\tCPed *ped = (CPed*)arg;\n\tCWeaponInfo *currentWeapon = CWeaponInfo::GetWeaponInfo(ped->GetWeapon()->m_eWeaponType);\n\n\tif (ped->m_nPedState != PED_ATTACK) {\n\t\tif (ped->bIsDucking && ped->IsPedInControl()) {\n\t\t\tif (GetCrouchReloadAnim(currentWeapon)) {\n\t\t\t\treloadAnimAssoc = RpAnimBlendClumpGetAssociation(ped->GetClump(), GetCrouchReloadAnim(currentWeapon));\n\t\t\t}\n\t\t\tif (GetCrouchFireAnim(currentWeapon) && attackAssoc) {\n\t\t\t\tif (attackAssoc->animId == GetCrouchFireAnim(currentWeapon) && !reloadAnimAssoc) {\n\t\t\t\t\tnewAnim = CAnimManager::BlendAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_DUCK_WEAPON, 8.0f);\n\t\t\t\t\tnewAnim->SetCurrentTime(newAnim->hierarchy->totalLength);\n\t\t\t\t\tnewAnim->flags &= ~ASSOC_RUNNING;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} else if (attackAssoc && attackAssoc->animId == ANIM_THROWABLE_START_THROW && currentWeapon->m_AnimToPlay == ASSOCGRP_THROW) {\n\t\tif ((!ped->IsPlayer() || ((CPlayerPed*)ped)->m_bHaveTargetSelected) && ped->IsPlayer()) {\n\t\t\tattackAssoc->blendDelta = -1000.0f;\n\t\t\tnewAnim = CAnimManager::AddAnimation(ped->GetClump(), currentWeapon->m_AnimToPlay, ANIM_THROWABLE_THROWU);\n\t\t} else {\n\t\t\tattackAssoc->blendDelta = -1000.0;\n\t\t\tnewAnim = CAnimManager::AddAnimation(ped->GetClump(), currentWeapon->m_AnimToPlay, ANIM_THROWABLE_THROW);\n\t\t}\n\t\tnewAnim->SetFinishCallback(FinishedAttackCB, ped);\n\n\t} else if (ped->bIsDucking && ped->bCrouchWhenShooting) {\n\t\tif (GetCrouchReloadAnim(currentWeapon)) {\n\t\t\treloadAnimAssoc = RpAnimBlendClumpGetAssociation(ped->GetClump(), GetCrouchReloadAnim(currentWeapon));\n\t\t}\n\t\tif (GetCrouchFireAnim(currentWeapon) && attackAssoc) {\n\t\t\tif (attackAssoc->animId == GetCrouchFireAnim(currentWeapon) && !reloadAnimAssoc) {\n\t\t\t\tnewAnim = CAnimManager::BlendAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_DUCK_WEAPON, 8.0f);\n\t\t\t\tnewAnim->SetCurrentTime(newAnim->hierarchy->totalLength);\n\t\t\t\tnewAnim->flags &= ~ASSOC_RUNNING;\n\t\t\t}\n\t\t}\n\n\t\tif (!ped->bIsAttacking)\n\t\t\tped->ClearAttack();\n\n\t} else if (GetSecondFireAnim(currentWeapon) && ped->bIsAttacking && currentWeapon->m_AnimToPlay != ASSOCGRP_THROW) {\n\t\tAnimationId groundAnim = GetFireAnimGround(currentWeapon);\n\t\tCAnimBlendAssociation *groundAnimAssoc = RpAnimBlendClumpGetAssociation(ped->GetClump(), groundAnim);\n\t\tif (!(groundAnimAssoc && (groundAnimAssoc->blendAmount > 0.95f || groundAnimAssoc->blendDelta > 0.0f))) {\n\t\t\tif (attackAssoc && attackAssoc->animId == ANIM_MELEE_ATTACK) {\n\t\t\t\tnewAnim = CAnimManager::BlendAnimation(\n\t\t\t\t\tped->GetClump(), currentWeapon->m_AnimToPlay, GetSecondFireAnim(currentWeapon), 8.0f);\n\t\t\t} else {\n\t\t\t\tnewAnim = CAnimManager::BlendAnimation(\n\t\t\t\t\tped->GetClump(), currentWeapon->m_AnimToPlay, ANIM_MELEE_ATTACK, 8.0f);\n\t\t\t}\n\t\t\tnewAnim->SetFinishCallback(FinishedAttackCB, ped);\n\t\t}\n\t} else {\n\t\tif (attackAssoc && attackAssoc->animId == ANIM_MELEE_ATTACK && currentWeapon->m_AnimToPlay == ASSOCGRP_UNARMED) {\n\t\t\tattackAssoc->blendDelta = -8.0f;\n\t\t\tattackAssoc->flags |= ASSOC_DELETEFADEDOUT;\n\t\t\tped->ClearAttack();\n\t\t\treturn;\n\t\t}\n\t\tif (attackAssoc) {\n\t\t\tif (currentWeapon->m_AnimToPlay == ASSOCGRP_THROW) {\n\t\t\t\tif ((attackAssoc->animId == ANIM_THROWABLE_THROW || attackAssoc->animId == ANIM_THROWABLE_THROWU) && ped->GetWeapon()->m_nAmmoTotal > 0) {\n\t\t\t\t\tped->RemoveWeaponModel(currentWeapon->m_nModelId);\n\t\t\t\t\tped->AddWeaponModel(currentWeapon->m_nModelId);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (!ped->bIsAttacking)\n\t\t\tped->ClearAttack();\n\t}\n}\n\nvoid\nCPed::FinishedReloadCB(CAnimBlendAssociation *reloadAssoc, void *arg)\n{\n\tCPed *ped = (CPed*)arg;\n\tCWeaponInfo *weapon = CWeaponInfo::GetWeaponInfo(ped->GetWeapon()->m_eWeaponType);\n\t\n\tif (ped->DyingOrDead())\n\t\treturn;\n\n\tif (ped->bIsDucking && ped->bCrouchWhenShooting) {\n\t\tCAnimBlendAssociation *crouchFireAssoc = nil;\n\t\tif (weapon->IsFlagSet(WEAPONFLAG_CROUCHFIRE)) {\n\t\t\tcrouchFireAssoc = RpAnimBlendClumpGetAssociation(ped->GetClump(), GetCrouchFireAnim(weapon));\n\t\t}\n\t\tif (weapon->IsFlagSet(WEAPONFLAG_RELOAD) && reloadAssoc) {\n\t\t\tif (reloadAssoc->animId == GetCrouchReloadAnim(weapon) && !crouchFireAssoc) {\n\t\t\t\tCAnimBlendAssociation *crouchAssoc = CAnimManager::BlendAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_DUCK_WEAPON, 8.0f);\n\t\t\t\tcrouchAssoc->SetCurrentTime(crouchAssoc->hierarchy->totalLength);\n\t\t\t\tcrouchAssoc->flags &= ~ASSOC_RUNNING;\n\t\t\t}\n\t\t}\n\t} else if (weapon->IsFlagSet(WEAPONFLAG_RELOAD_LOOP2START) && ped->bIsAttacking) {\n\t\tCAnimBlendAssociation *fireAssoc =\n\t\t\tCAnimManager::BlendAnimation(ped->GetClump(), weapon->m_AnimToPlay, GetPrimaryFireAnim(weapon), 8.0f);\n\t\tfireAssoc->SetFinishCallback(FinishedAttackCB, ped);\n\t\tfireAssoc->SetRun();\n\t\tif (fireAssoc->currentTime == reloadAssoc->hierarchy->totalLength)\n\t\t\tfireAssoc->SetCurrentTime(Max(weapon->m_fAnimLoopStart - 0.04f, 0.0f));\n\t\telse if (fireAssoc->currentTime < weapon->m_fAnimLoopStart)\n\t\t\tfireAssoc->SetCurrentTime(Max(weapon->m_fAnimLoopStart - 0.04f, 0.0f));\n\t}\n}\n\nuint8\nCPed::CheckForPointBlankPeds(CPed *pedToVerify)\n{\n\tfloat pbDistance = 1.1f;\n\tif (GetWeapon()->IsType2Handed())\n\t\tpbDistance = 1.6f;\n\n\tfor (int i = 0; i < m_numNearPeds; i++)\t{\n\t\tCPed *nearPed = m_nearPeds[i];\n\n\t\tif (!pedToVerify || pedToVerify == nearPed) {\n\n\t\t\tCVector diff = nearPed->GetPosition() - GetPosition();\n\t\t\tif (diff.MagnitudeSqr() < SQR(pbDistance)) {\n\n\t\t\t\tfloat neededAngle = CGeneral::GetRadianAngleBetweenPoints(\n\t\t\t\t\tnearPed->GetPosition().x, nearPed->GetPosition().y,\n\t\t\t\t\tGetPosition().x, GetPosition().y);\n\t\t\t\tneededAngle = CGeneral::LimitRadianAngle(neededAngle);\n\t\t\t\tm_fRotationCur = CGeneral::LimitRadianAngle(m_fRotationCur);\n\n\t\t\t\tfloat neededTurn = Abs(neededAngle - m_fRotationCur);\n\n\t\t\t\tif (neededTurn > PI)\n\t\t\t\t\tneededTurn = 2*PI - neededTurn;\n\n\t\t\t\tPedState nearPedState = nearPed->m_nPedState;\n\n\t\t\t\tif (nearPedState == PED_FALL || nearPedState == PED_GETUP || nearPedState == PED_DIE || nearPedState == PED_DEAD || nearPedState == PED_DIVE_AWAY)\n\t\t\t\t\treturn NO_POINT_BLANK_PED;\n\n\t\t\t\tif (neededTurn < CAN_SEE_ENTITY_ANGLE_THRESHOLD) {\n\t\t\t\t\tif (pedToVerify == nearPed)\n\t\t\t\t\t\treturn POINT_BLANK_FOR_WANTED_PED;\n\t\t\t\t\telse\n\t\t\t\t\t\treturn POINT_BLANK_FOR_SOMEONE_ELSE;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn NO_POINT_BLANK_PED;\n}\n\nvoid\nCPed::Attack(void)\n{\n\tCAnimBlendAssociation *weaponAnimAssoc;\n\tint32 weaponAnim;\n\tfloat weaponAnimTime;\n\tfloat animLoopEnd;\n\tCWeaponInfo *ourWeapon;\n\tbool attackShouldContinue;\n\tCAnimBlendAssociation *reloadAnimAssoc;\n\tCAnimBlendAssociation *throwAssoc;\n\tfloat delayBetweenAnimAndFire;\n\tfloat animLoopStart;\n\tCVector firePos;\n\n\tourWeapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);\n\tweaponAnimAssoc = nil;\n\tattackShouldContinue = !!bIsAttacking;\n\treloadAnimAssoc = nil;\n\tthrowAssoc = nil;\n\tanimLoopStart = ourWeapon->m_fAnimLoopStart;\n\tanimLoopEnd = ourWeapon->m_fAnimLoopEnd;\n\tdelayBetweenAnimAndFire = ourWeapon->m_fAnimFrameFire;\n\tweaponAnim = ourWeapon->m_AnimToPlay;\n\n\tif (bIsDucking) {\n\t\tif(GetCrouchFireAnim(ourWeapon) && bCrouchWhenShooting) {\n\t\t\tweaponAnimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), GetCrouchFireAnim(ourWeapon));\n\t\t\tif (weaponAnimAssoc) {\n\t\t\t\tanimLoopStart = ourWeapon->m_fAnim2LoopStart;\n\t\t\t\tanimLoopEnd = ourWeapon->m_fAnim2LoopEnd;\n\t\t\t\tdelayBetweenAnimAndFire = ourWeapon->m_fAnim2FrameFire;\n\t\t\t}\n\t\t}\n\t} else if (m_nPedType == PEDTYPE_COP && Get3rdFireAnim(ourWeapon)){\n\t\tweaponAnimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), Get3rdFireAnim(ourWeapon));\n\t\tif (weaponAnimAssoc) {\n\t\t\tanimLoopStart = 11.f/30.f;\n\t\t\tanimLoopEnd = 19.f/30.f;\n\t\t\tdelayBetweenAnimAndFire = 14.f/30.f;\n\t\t}\n\t} else {\n\t\tweaponAnimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), GetPrimaryFireAnim(ourWeapon));\n\t}\n\n\tif (GetReloadAnim(ourWeapon)) {\n\t\treloadAnimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), GetReloadAnim(ourWeapon));\n\t}\n\n\tif (GetCrouchReloadAnim(ourWeapon) && !reloadAnimAssoc)  {\n\t\treloadAnimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), GetCrouchReloadAnim(ourWeapon));\n\t}\n\n\tif ( reloadAnimAssoc && reloadAnimAssoc->IsRunning() ) {\n\t\tif (!IsPlayer() || ((CPlayerPed*)this)->m_bHaveTargetSelected)\n\t\t\tClearAttack();\n\t\treturn;\n\t}\n\n\tif ( reloadAnimAssoc ) {\n\t\treloadAnimAssoc->flags |= ASSOC_DELETEFADEDOUT;\n\t\tif ( reloadAnimAssoc->blendDelta >= 0.0f )\n\t\t\treloadAnimAssoc->blendDelta = -8.0f;\n\t}\n\n\tif (GetThrowAnim(ourWeapon))  {\n\t\tthrowAssoc = RpAnimBlendClumpGetAssociation(GetClump(), GetThrowAnim(ourWeapon));\n\t}\n\n\tif ( CTimer::GetTimeInMilliseconds() < m_shootTimer )\n\t\tattackShouldContinue = true;\n\n\tbool meleeAttackStarted = false;\n\tif ( !weaponAnimAssoc ) {\n\t\tif (GetMeleeStartAnim(ourWeapon)) {\n\t\t\tweaponAnimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), GetMeleeStartAnim(ourWeapon));\n\t\t\tif ( weaponAnimAssoc ) {\n\t\t\t\tif ( IsPlayer() )\n\t\t\t\t\tmeleeAttackStarted = true;\n\n\t\t\t\tswitch ( ourWeapon->m_AnimToPlay ) {\n\t\t\t\t\tcase ASSOCGRP_UNARMED:\n\t\t\t\t\tcase ASSOCGRP_SCREWDRIVER:\n\t\t\t\t\tcase ASSOCGRP_KNIFE:\n\t\t\t\t\tcase ASSOCGRP_BASEBALLBAT:\n\t\t\t\t\tcase ASSOCGRP_GOLFCLUB:\n\t\t\t\t\tcase ASSOCGRP_CHAINSAW:\n\t\t\t\t\t\tdelayBetweenAnimAndFire = 0.2f;\n\t\t\t\t\t\tanimLoopStart = 0.1f;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tanimLoopEnd = 99.9f;\n\t\t\t}\n\t\t}\n\t}\n\tif (!weaponAnimAssoc) {\n\t\tif (GetSecondFireAnim(ourWeapon)) {\n\t\t\tweaponAnimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), GetSecondFireAnim(ourWeapon));\n\t\t\tif (weaponAnimAssoc) {\n\t\t\t\tanimLoopStart = ourWeapon->m_fAnim2LoopStart;\n\t\t\t\tanimLoopEnd = ourWeapon->m_fAnim2LoopEnd;\n\t\t\t\tdelayBetweenAnimAndFire = ourWeapon->m_fAnim2FrameFire;\n\t\t\t}\n\t\t}\n\t}\n\tif (!weaponAnimAssoc) {\n\t\tweaponAnimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), GetFireAnimGround(ourWeapon));\n\t\tif (weaponAnimAssoc) {\n\t\t\tanimLoopStart = ourWeapon->m_fAnim2LoopStart;\n\t\t\tanimLoopEnd = ourWeapon->m_fAnim2LoopEnd;\n\t\t\tdelayBetweenAnimAndFire = ourWeapon->m_fAnim2FrameFire;\n\t\t}\n\t}\n\n\tif (!weaponAnimAssoc) {\n\t\tif (!throwAssoc) {\n\t\t\tif (attackShouldContinue) {\n\t\t\t\tif (ourWeapon->m_eWeaponFire != WEAPON_FIRE_PROJECTILE || !IsPlayer() || ((CPlayerPed*)this)->m_bHaveTargetSelected) {\n\t\t\t\t\tif (bCrouchWhenShooting && bIsDucking && GetCrouchFireAnim(ourWeapon)) {\n\t\t\t\t\t\tweaponAnimAssoc = CAnimManager::BlendAnimation(GetClump(), ourWeapon->m_AnimToPlay, GetCrouchFireAnim(ourWeapon), 8.0f);\n\n\t\t\t\t\t} else if(GetSecondFireAnim(ourWeapon) && CGeneral::GetRandomNumber() & 1){\n\t\t\t\t\t\tweaponAnimAssoc = CAnimManager::BlendAnimation(GetClump(), ourWeapon->m_AnimToPlay, GetSecondFireAnim(ourWeapon), 8.0f);\n\n\t\t\t\t\t} else if(!CGame::nastyGame || ourWeapon->m_eWeaponFire != WEAPON_FIRE_MELEE ||\n\t\t\t\t\t          !GetFireAnimGround(ourWeapon, false) || \n\t\t\t\t\t\t CheckForPedsOnGroundToAttack(this, nil) < PED_ON_THE_FLOOR) {\n\n\t\t\t\t\t\tweaponAnimAssoc = CAnimManager::BlendAnimation(GetClump(), ourWeapon->m_AnimToPlay, GetFireAnimNotDucking(ourWeapon), 8.0f);\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tweaponAnimAssoc = CAnimManager::BlendAnimation(GetClump(), ourWeapon->m_AnimToPlay, GetFireAnimGround(ourWeapon, false), 8.0f);\n\t\t\t\t\t}\n\n\t\t\t\t\tweaponAnimAssoc->SetFinishCallback(FinishedAttackCB, this);\n\t\t\t\t\tweaponAnimAssoc->SetRun();\n\n\t\t\t\t\tif (weaponAnimAssoc->currentTime == weaponAnimAssoc->hierarchy->totalLength)\n\t\t\t\t\t\tweaponAnimAssoc->SetCurrentTime(0.0f);\n\n\t\t\t\t\tif (IsPlayer()) {\n\t\t\t\t\t\t((CPlayerPed*)this)->m_fAttackButtonCounter = 0.0f;\n\t\t\t\t\t\t((CPlayerPed*)this)->m_bHaveTargetSelected = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else\n\t\t\t\tFinishedAttackCB(nil, this);\n\n\t\t}\n\t\treturn;\n\t}\n\n\tif (meleeAttackStarted && IsPlayer()) {\n\t\tif (((CPlayerPed*)this)->m_bHaveTargetSelected || ((CPlayerPed*)this)->m_fMoveSpeed < 0.5f) {\n\t\t\tweaponAnimAssoc->SetRun();\n\t\t} else {\n\t\t\tif (weaponAnimAssoc->currentTime > animLoopStart && weaponAnimAssoc->currentTime - weaponAnimAssoc->timeStep <= animLoopStart)\n\t\t\t\tweaponAnimAssoc->flags &= ~ASSOC_RUNNING;\n\t\t}\n\t}\n\n\tfloat animStart = animLoopStart * 0.4f;\n\tweaponAnimTime = weaponAnimAssoc->currentTime;\n\tif (weaponAnimTime > animStart && weaponAnimTime - weaponAnimAssoc->timeStep <= animStart) {\n\t\tif (!bIsDucking && !GetFireAnimNotDucking(ourWeapon) && ourWeapon->IsFlagSet(WEAPONFLAG_CANAIM_WITHARM))\n\t\t\tm_pedIK.m_flags |= CPedIK::AIMS_WITH_ARM;\n\t\telse\n\t\t\tm_pedIK.m_flags &= ~CPedIK::AIMS_WITH_ARM;\n\t}\n\n\tif (GetWeapon()->m_eWeaponType != WEAPONTYPE_CHAINSAW\n\t\t|| !meleeAttackStarted && delayBetweenAnimAndFire - 0.5f >= weaponAnimAssoc->currentTime\n\t\t|| weaponAnimAssoc->currentTime - weaponAnimAssoc->timeStep > delayBetweenAnimAndFire) {\n\n\t\tif (GetWeapon()->m_eWeaponType == WEAPONTYPE_CHAINSAW) {\n\t\t\tDMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_CHAINSAW_ATTACK, 0.0f);\n\t\t} else if (weaponAnimTime <= delayBetweenAnimAndFire || weaponAnimTime - weaponAnimAssoc->timeStep > delayBetweenAnimAndFire || !weaponAnimAssoc->IsRunning()) {\n\t\t\tif (weaponAnimAssoc->speed < 1.0f)\n\t\t\t\tweaponAnimAssoc->speed = 1.0f;\n\n\t\t} else {\n\t\t\tfirePos = ourWeapon->m_vecFireOffset;\n\n\t\t\tif(ourWeapon->m_AnimToPlay != ASSOCGRP_BASEBALLBAT && ourWeapon->m_AnimToPlay != ASSOCGRP_GOLFCLUB) {\n\t\t\t\tif (ourWeapon->m_eWeaponFire != WEAPON_FIRE_MELEE) {\n\t\t\t\t\tTransformToNode(firePos, (weaponAnimAssoc->animId == ANIM_MELEE_ATTACK_2ND && ourWeapon->m_AnimToPlay == ASSOCGRP_UNARMED) ? PED_FOOTR : PED_HANDR);\n\t\t\t\t} else {\n\t\t\t\t\tfirePos = GetMatrix() * firePos;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (weaponAnimAssoc->animId == ANIM_MELEE_ATTACK_2ND)\n\t\t\t\t\tfirePos.z = 0.7f * ourWeapon->m_fRadius - 1.0f;\n\n\t\t\t\tfirePos = GetMatrix() * firePos;\n\t\t\t}\n\t\t\t\n\t\t\tGetWeapon()->Fire(this, &firePos);\n\n\t\t\tif (GetWeapon()->m_eWeaponType == WEAPONTYPE_MOLOTOV || GetWeapon()->m_eWeaponType == WEAPONTYPE_GRENADE || GetWeapon()->m_eWeaponType == WEAPONTYPE_DETONATOR_GRENADE ||\n\t\t\t\tGetWeapon()->m_eWeaponType == WEAPONTYPE_TEARGAS) {\n\t\t\t\tRemoveWeaponModel(CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->m_nModelId);\n\t\t\t}\n\t\t\tif (GetWeapon()->m_nAmmoTotal == 0 && ourWeapon->m_eWeaponFire != WEAPON_FIRE_MELEE && FindPlayerPed() != this) {\n\t\t\t\tSelectGunIfArmed();\n\t\t\t}\n\n\t\t\tif (GetWeapon()->m_eWeaponState == WEAPONSTATE_MELEE_MADECONTACT) {\n\t\t\t\tint damagerType = ENTITY_TYPE_NOTHING;\n\t\t\t\tif (m_pDamageEntity && (m_fDamageImpulse == 0.0f || !m_pDamageEntity->IsBuilding())) {\n\t\t\t\t\tdamagerType = m_pDamageEntity->GetType();\n\t\t\t\t}\n\t\t\t\tswitch (ourWeapon->m_AnimToPlay) {\n\t\t\t\t\tcase ASSOCGRP_UNARMED:\n\t\t\t\t\t\tif (weaponAnimAssoc->animId == ANIM_MELEE_ATTACK || weaponAnimAssoc->animId == ANIM_MELEE_ATTACK_START) \n\t\t\t\t\t\t\tDMAudio.PlayOneShot(m_audioEntityId, SOUND_FIGHT_46, (damagerType | (GetWeapon()->m_eWeaponType << 8)));\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase ASSOCGRP_KNIFE:\n\t\t\t\t\tcase ASSOCGRP_BASEBALLBAT:\n\t\t\t\t\tcase ASSOCGRP_GOLFCLUB:\n\t\t\t\t\tcase ASSOCGRP_CHAINSAW:\n\t\t\t\t\t\tDMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_BAT_ATTACK, (damagerType | (GetWeapon()->m_eWeaponType << 8)));\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif (bIsAttacking || CTimer::GetTimeInMilliseconds() < m_shootTimer) {\n\t\t\t\t\tweaponAnimAssoc->callbackType = 0;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tattackShouldContinue = false;\n\t\t}\n\t} else {\n\t\tCVector firePos = ourWeapon->m_vecFireOffset;\n\n\t\tif (weaponAnimAssoc->animId == ANIM_MELEE_ATTACK_2ND)\n\t\t\tfirePos.z = 0.7f * ourWeapon->m_fRadius - 1.0f;\n\n\t\tfirePos = GetMatrix() * firePos;\n\t\tGetWeapon()->Fire(this, &firePos);\n\t\tif (GetWeapon()->m_eWeaponState == WEAPONSTATE_MELEE_MADECONTACT) {\n\t\t\tint damagerType = ENTITY_TYPE_PED;\n\t\t\tif (m_pDamageEntity)\n\t\t\t\tdamagerType = m_pDamageEntity->GetType();\n\n\t\t\tDMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_CHAINSAW_MADECONTACT, (float)damagerType);\n\t\t\tif (IsPlayer()) {\n\t\t\t\tCPad::GetPad(0)->StartShake(240, 180);\n\t\t\t}\n\t\t} else {\n\t\t\tDMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_CHAINSAW_IDLE, 0.0f);\n\t\t\tif (IsPlayer()) {\n\t\t\t\tCPad::GetPad(0)->StartShake(240, 90);\n\t\t\t}\n\t\t}\n\t\tattackShouldContinue = false;\n\t}\n\n\tif (ourWeapon->m_eWeaponFire == WEAPON_FIRE_INSTANT_HIT && ourWeapon->m_AnimToPlay == ASSOCGRP_SHOTGUN) {\n\t\tweaponAnimTime = weaponAnimAssoc->currentTime;\n\n\t\tif (weaponAnimTime > 1.0f && weaponAnimTime - weaponAnimAssoc->timeStep <= 1.0f && weaponAnimAssoc->IsRunning()) {\n\t\t\tfirePos = ourWeapon->m_vecFireOffset;\n\t\t\tTransformToNode(firePos, PED_HANDR);\n\n\t\t\tCVector gunshellPos(\n\t\t\t\tfirePos.x - 0.6f * GetForward().x,\n\t\t\t\tfirePos.y - 0.6f * GetForward().y,\n\t\t\t\tfirePos.z - 0.15f * GetUp().z\n\t\t\t);\n\n\t\t\tCVector2D gunshellRot(\n\t\t\t\tGetRight().x,\n\t\t\t\tGetRight().y\n\t\t\t);\n\n\t\t\tgunshellRot.Normalise();\n\t\t\tGetWeapon()->AddGunshell(this, gunshellPos, gunshellRot, 0.025f);\n\t\t}\n\t}\n\n\tif (IsPlayer()) {\n\t\tif (GetWeapon()->m_eWeaponType == WEAPONTYPE_BASEBALLBAT || GetWeapon()->m_eWeaponType == WEAPONTYPE_GOLFCLUB || GetWeapon()->m_eWeaponType == WEAPONTYPE_KATANA) {\n\t\t\tfloat loopEndWithDelay = animLoopEnd;\n\t\t\tif (loopEndWithDelay >= 98.0f)\n\t\t\t\tloopEndWithDelay = (14.0f / 30.0f) + delayBetweenAnimAndFire;\n\t\t\tif (weaponAnimAssoc->flags & ASSOC_RUNNING) {\n\t\t\t\tif (weaponAnimAssoc->currentTime >= animLoopStart && weaponAnimAssoc->currentTime <= loopEndWithDelay)\n\t\t\t\t\tCSpecialFX::AddWeaponStreak(GetWeapon()->m_eWeaponType);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Anim breakout on running\n\tif (IsPlayer()) {\n\t\tif (CPad::GetPad(0)->GetSprint()) {\n\t\t\tif (!attackShouldContinue && weaponAnimAssoc->currentTime > ourWeapon->m_fAnimBreakout) {\n\t\t\t\tweaponAnimAssoc->blendDelta = -4.0f;\n\t\t\t\tFinishedAttackCB(nil, this);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t}\n\n\tweaponAnimTime = weaponAnimAssoc->currentTime;\n\n\t// Anim loop end, either start the loop again or finish the attack\n\tif (weaponAnimTime > animLoopEnd || !weaponAnimAssoc->IsRunning() && ourWeapon->m_eWeaponFire != WEAPON_FIRE_PROJECTILE) {\n\t\tif (GetWeapon()->m_eWeaponState == WEAPONSTATE_RELOADING) {\n\t\t\tif (GetReloadAnim(ourWeapon) && !reloadAnimAssoc) {\n\t\t\t\tif (!CWorld::Players[CWorld::PlayerInFocus].m_bFastReload) {\n\t\t\t\t\tCAnimBlendAssociation *newReloadAssoc = CAnimManager::BlendAnimation(\n\t\t\t\t\t\tGetClump(), ourWeapon->m_AnimToPlay,\n\t\t\t\t\t\tbIsDucking && GetCrouchReloadAnim(ourWeapon) ? GetCrouchReloadAnim(ourWeapon) : GetReloadAnim(ourWeapon),\n\t\t\t\t\t\t8.0f);\n\t\t\t\t\tnewReloadAssoc->SetFinishCallback(FinishedReloadCB, this);\n\t\t\t\t}\n\t\t\t\tClearLookFlag();\n\t\t\t\tClearAimFlag();\n\t\t\t\tbIsAttacking = false;\n\t\t\t\tbIsPointingGunAt = false;\n\t\t\t\tm_shootTimer = CTimer::GetTimeInMilliseconds();\n\t\t\t\tDMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_AK47_BULLET_ECHO, GetWeapon()->m_eWeaponType);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\tif (weaponAnimTime - 2.0f * weaponAnimAssoc->timeStep <= animLoopEnd\n\t\t\t&& (bIsAttacking || CTimer::GetTimeInMilliseconds() < m_shootTimer)\n\t\t\t&& (GetWeapon()->m_eWeaponState != WEAPONSTATE_RELOADING\n\t\t\t\t|| GetWeapon()->m_eWeaponType == WEAPONTYPE_MINIGUN)) {\n\n\t\t\tPedOnGroundState pedOnGroundState;\n\t\t\tif (ourWeapon->m_eWeaponFire == WEAPON_FIRE_MELEE &&\n\t\t\t\t(CGame::nastyGame && ((pedOnGroundState = CheckForPedsOnGroundToAttack(this, nil)) > PED_IN_FRONT_OF_ATTACKER)\n\t\t\t\t|| GetWeapon()->m_eWeaponType == WEAPONTYPE_BASEBALLBAT && pedOnGroundState == NO_PED && bIsStanding && m_pCurSurface && m_pCurSurface->IsVehicle())) {\n\n\t\t\t\tAnimationId fireAnim = GetFireAnimGround(ourWeapon, false);\n\t\t\t\tif (weaponAnimAssoc->animId == fireAnim)\n\t\t\t\t\tweaponAnimAssoc->SetCurrentTime(0.1f);\n\t\t\t\telse {\n\t\t\t\t\tif (GetFireAnimGround(ourWeapon, false)) {\n\t\t\t\t\t\tweaponAnimAssoc = CAnimManager::BlendAnimation(GetClump(), ourWeapon->m_AnimToPlay, fireAnim, 8.0f);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tweaponAnimAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_KICKGROUND, 8.0f);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tweaponAnimAssoc->SetFinishCallback(FinishedAttackCB, this);\n\t\t\t} else if (GetSecondFireAnim(ourWeapon)) {\n\t\t\t\tif (weaponAnimAssoc->animId == GetSecondFireAnim(ourWeapon)) {\n\t\t\t\t\tweaponAnimAssoc = CAnimManager::BlendAnimation(GetClump(), ourWeapon->m_AnimToPlay, ANIM_WEAPON_FIRE, 8.0f);\n\t\t\t\t} else {\n\t\t\t\t\tweaponAnimAssoc = CAnimManager::BlendAnimation(GetClump(), ourWeapon->m_AnimToPlay, GetSecondFireAnim(ourWeapon), 8.0f);\n\t\t\t\t}\n\t\t\t\tweaponAnimAssoc->SetFinishCallback(FinishedAttackCB, this);\n\t\t\t} else {\n\t\t\t\tweaponAnimAssoc->SetCurrentTime(animLoopStart);\n\t\t\t\tweaponAnimAssoc->SetRun();\n\t\t\t}\n\t\t} else if (IsPlayer() && m_pPointGunAt && bIsAimingGun && GetWeapon()->m_eWeaponState != WEAPONSTATE_RELOADING) {\n\t\t\tweaponAnimAssoc->SetCurrentTime(animLoopEnd);\n\t\t\tweaponAnimAssoc->flags &= ~ASSOC_RUNNING;\n\t\t\tSetPointGunAt(m_pPointGunAt);\n\t\t} else {\n\t\t\tClearAimFlag();\n\n\t\t\t// Echoes of bullets, at the end of the attack. (Bug: doesn't play while reloading)\n\t\t\tif (weaponAnimAssoc->currentTime - weaponAnimAssoc->timeStep < animLoopEnd) \n\t\t\t\tDMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_AK47_BULLET_ECHO, GetWeapon()->m_eWeaponType);\n\n\t\t\t// Fun fact: removing this part leds to reloading flamethrower\n\t\t\tif (GetWeapon()->m_eWeaponType == WEAPONTYPE_FLAMETHROWER && weaponAnimAssoc->IsRunning()) {\n\t\t\t\tweaponAnimAssoc->flags |= ASSOC_DELETEFADEDOUT;\n\t\t\t\tweaponAnimAssoc->flags &= ~ASSOC_RUNNING;\n\t\t\t\tweaponAnimAssoc->blendDelta = -4.0f;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (weaponAnimAssoc->currentTime > delayBetweenAnimAndFire)\n\t\tattackShouldContinue = false;\n\n\tbIsAttacking = attackShouldContinue;\n}\n\nvoid\nCPed::StartFightAttack(uint8 buttonPressure)\n{\n\tif (!IsPedInControl() || (m_attackTimer > CTimer::GetTimeInMilliseconds() && buttonPressure != 0))\n\t\treturn;\n\n\tif (m_nPedState == PED_FIGHT) {\n\t\tm_fightButtonPressure = buttonPressure;\n\t\treturn;\n\t}\n\n\tif (m_nPedState != PED_AIM_GUN)\n\t\tSetStoredState();\n\n\tif (m_nWaitState != WAITSTATE_FALSE) {\n\t\tClearWaitState();\n\t\tRestoreHeadingRate();\n\t}\n\n\tCAnimBlendAssociation* animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_RUNSTOP1);\n\tif (!animAssoc)\n\t\tanimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_RUNSTOP2);\n\n\tif (animAssoc) {\n\t\tRestoreHeadingRate();\n\t}\n\tSetMoveState(PEDMOVE_NONE);\n\tm_nStoredMoveState = PEDMOVE_NONE;\n\tbool fightWithWeapon = false;\n\tCAnimBlendAssociation *fightIdleAssoc;\n\n\tCWeaponInfo* weaponInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);\n\tif (GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED) {\n\t\tif (GetFightIdleWithMeleeAnim(weaponInfo)) {\n\t\t\tfightIdleAssoc = CAnimManager::BlendAnimation(GetClump(), weaponInfo->m_AnimToPlay, GetFightIdleWithMeleeAnim(weaponInfo), 1000.0f);\n\t\t\tfightWithWeapon = true;\n\t\t} else {\n\t\t\tfightIdleAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_FIGHT_IDLE, 1000.0f);\n\t\t}\n\t} else {\n\t\tfightIdleAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_FIGHT_IDLE, 1000.0f);\n\t}\n\tm_lastFightMove = FIGHTMOVE_IDLE;\n\tm_curFightMove = IsPlayer() ? ChooseAttackPlayer(buttonPressure, fightWithWeapon) : ChooseAttackAI(buttonPressure, fightWithWeapon);\n\n\tSetPedState(PED_FIGHT);\n\tm_fightButtonPressure = 0;\n\n\tif (m_curFightMove > FIGHTMOVE_NULL && m_curFightMove != FIGHTMOVE_IDLE) {\n\t\tanimAssoc = CAnimManager::BlendAnimation(GetClump(), m_curFightMove < FIGHTMOVE_MELEE1 ? ASSOCGRP_STD : weaponInfo->m_AnimToPlay,\n\t\t\ttFightMoves[m_curFightMove].animId, 8.0f);\n\n\t\tif (weaponInfo->m_AnimToPlay == ASSOCGRP_KNIFE && m_curFightMove >= FIGHTMOVE_MELEE1) {\n\t\t\tswitch (GetWeapon()->m_eWeaponType) {\n\t\t\t\tcase WEAPONTYPE_SCREWDRIVER:\n\t\t\t\tcase WEAPONTYPE_KNIFE:\n\t\t\t\t\tanimAssoc->speed = 1.05f;\n\t\t\t\t\tbreak;\n\t\t\t\tcase WEAPONTYPE_GOLFCLUB:\n\t\t\t\tcase WEAPONTYPE_NIGHTSTICK:\n\t\t\t\tcase WEAPONTYPE_BASEBALLBAT:\n\t\t\t\tcase WEAPONTYPE_HAMMER:\n\t\t\t\tcase WEAPONTYPE_KATANA:\n\t\t\t\t\tanimAssoc->speed = 0.8f;\n\t\t\t\t\tbreak;\n\t\t\t\tcase WEAPONTYPE_CLEAVER:\n\t\t\t\tcase WEAPONTYPE_MACHETE:\n\t\t\t\t\tanimAssoc->speed = 0.9f;\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t} else {\n\t\t\tif (m_curFightMove == FIGHTMOVE_BACKKICK)\n\t\t\t\tanimAssoc->speed = 1.15f;\n\t\t\telse\n\t\t\t\tanimAssoc->speed = 0.8f;\n\t\t}\n\t\tif (IsPlayer())\n\t\t\tanimAssoc->SetCurrentTime(0.08f);\n\n\t\tanimAssoc->SetFinishCallback(FinishFightMoveCB, this);\n\t} else {\n\t\tm_nWaitTimer = CTimer::GetTimeInMilliseconds() + 2000;\n\t}\n\n\tm_fightState = FIGHTSTATE_NO_MOVE;\n\tm_takeAStepAfterAttack = false;\n\tbIsAttacking = true;\n\n\tif (IsPlayer())\n\t\tnPlayerInComboMove = 0;\n}\n\nvoid\nCPed::StartFightDefend(uint8 direction, uint8 hitLevel, uint8 unk)\n{\n\tif (m_nPedState == PED_DEAD) {\n\t\tif (CGame::nastyGame) {\n\t\t\tif (hitLevel == HITLEVEL_GROUND) {\n\t\t\t\tCAnimBlendAssociation *floorHitAssoc;\n\t\t\t\tif (RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_FRONTAL)) {\n\t\t\t\t\tfloorHitAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_HIT_FLOOR_FRONT, 8.0f);\n\t\t\t\t} else {\n\t\t\t\t\tfloorHitAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[FIGHTMOVE_HITONFLOOR].animId, 8.0f);\n\t\t\t\t}\n\t\t\t\tif (floorHitAssoc) {\n\t\t\t\t\tfloorHitAssoc->SetCurrentTime(0.0f);\n\t\t\t\t\tfloorHitAssoc->SetRun();\n\t\t\t\t\tfloorHitAssoc->flags &= ~ASSOC_FADEOUTWHENDONE;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (CGame::nastyGame) {\n\t\t\t\tCVector headPos = GetNodePosition(PED_HEAD);\n\t\t\t\tfor(int i = 0; i < 4; ++i) {\n\t\t\t\t\tCVector bloodDir(0.0f, 0.0f, 0.1f);\n\t\t\t\t\tCVector bloodPos = headPos - 0.2f * GetForward();\n\t\t\t\t\tCParticle::AddParticle(PARTICLE_BLOOD, bloodPos, bloodDir, nil, 0.0f, 0, 0, 0, 0);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} else if (m_nPedState == PED_FALL) {\n\t\tif (hitLevel == HITLEVEL_GROUND && !IsPedHeadAbovePos(-0.3f)) {\n\t\t\tCAnimBlendAssociation *floorHitAssoc = RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_FRONTAL) ?\n\t\t\t\tCAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_HIT_FLOOR_FRONT, 8.0f) :\n\t\t\t\tCAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_HIT_FLOOR, 8.0f);\n\t\t\tif (floorHitAssoc) {\n\t\t\t\tfloorHitAssoc->flags &= ~ASSOC_FADEOUTWHENDONE;\n\t\t\t\tfloorHitAssoc->flags |= ASSOC_DELETEFADEDOUT;\n\t\t\t}\n\t\t}\n\t} else if (IsPedInControl()) {\n\t\tif ((IsPlayer() && m_nPedState != PED_FIGHT && ((CPlayerPed*)this)->m_fMoveSpeed > 1.0f)\n\t\t\t|| (!IsPlayer() && m_objective == OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE)) {\n\n\t\t\tif (hitLevel != HITLEVEL_HIGH && hitLevel != HITLEVEL_LOW || (IsPlayer() || CGeneral::GetRandomNumber() & 1) && CGeneral::GetRandomNumber() & 7) {\n\t\t\t\tif (IsPlayer() || CGeneral::GetRandomNumber() & 1) {\n\t\t\t\t\tAnimationId shotAnim;\n\t\t\t\t\tswitch (direction) {\n\t\t\t\t\t\tcase 1:\n\t\t\t\t\t\t\tshotAnim = ANIM_STD_HITBYGUN_LEFT;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 2:\n\t\t\t\t\t\t\tshotAnim = ANIM_STD_HITBYGUN_BACK;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 3:\n\t\t\t\t\t\t\tshotAnim = ANIM_STD_HITBYGUN_RIGHT;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tshotAnim = ANIM_STD_HITBYGUN_FRONT;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tCAnimBlendAssociation *shotAssoc = RpAnimBlendClumpGetAssociation(GetClump(), shotAnim);\n\t\t\t\t\tif (!shotAssoc || shotAssoc->blendDelta < 0.0f)\n\t\t\t\t\t\tshotAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, shotAnim, 8.0f);\n\n\t\t\t\t\tshotAssoc->SetCurrentTime(0.0f);\n\t\t\t\t\tshotAssoc->SetRun();\n\t\t\t\t\tshotAssoc->flags |= ASSOC_FADEOUTWHENDONE;\n\t\t\t\t} else {\n\t\t\t\t\tint time = CGeneral::GetRandomNumberInRange(1000, 3000);\n\t\t\t\t\tSetWaitState(WAITSTATE_PLAYANIM_DUCK, &time);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tbool fall = true;\n\t\t\t\tAnimationId hitAnim;\n\t\t\t\tswitch (direction) {\n\t\t\t\t\tcase 1:\n\t\t\t\t\t\thitAnim = ANIM_STD_HIGHIMPACT_LEFT;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 2:\n\t\t\t\t\t\tif (CGeneral::GetRandomNumber() & 1) {\n\t\t\t\t\t\t\tfall = false;\n\t\t\t\t\t\t\thitAnim = ANIM_STD_HIT_BACK;\n\t\t\t\t\t\t} else\t{\n\t\t\t\t\t\t\thitAnim = ANIM_STD_HIGHIMPACT_BACK;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 3:\n\t\t\t\t\t\thitAnim = ANIM_STD_HIGHIMPACT_RIGHT;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tif (hitLevel == HITLEVEL_LOW) {\n\t\t\t\t\t\t\thitAnim = ANIM_STD_KO_SHOT_STOMACH;\n\t\t\t\t\t\t} else if (CGeneral::GetRandomNumber() & 1) {\n\t\t\t\t\t\t\tfall = false;\n\t\t\t\t\t\t\thitAnim = ANIM_STD_HIT_WALK;\n\t\t\t\t\t\t} else if (CGeneral::GetRandomNumber() & 1) {\n\t\t\t\t\t\t\tfall = false;\n\t\t\t\t\t\t\thitAnim = ANIM_STD_HIT_HEAD;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\thitAnim = ANIM_STD_KO_SHOT_FACE;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif (fall) {\n\t\t\t\t\tSetFall(500, hitAnim, false);\n\t\t\t\t} else {\n\t\t\t\t\tCAnimBlendAssociation *hitAssoc = RpAnimBlendClumpGetAssociation(GetClump(), hitAnim);\n\t\t\t\t\tif (!hitAssoc || hitAssoc->blendDelta < 0.0f)\n\t\t\t\t\t\thitAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, hitAnim, 8.0f);\n\n\t\t\t\t\thitAssoc->SetCurrentTime(0.0f);\n\t\t\t\t\thitAssoc->SetRun();\n\t\t\t\t\thitAssoc->flags |= ASSOC_FADEOUTWHENDONE;\n\t\t\t\t}\n\t\t\t}\n\t\t\tSay(SOUND_PED_DEFEND);\n\t\t} else {\n\t\t\tSay(SOUND_PED_DEFEND);\n\t\t\tswitch (hitLevel) {\n\t\t\t\tcase HITLEVEL_GROUND:\n\t\t\t\t\tm_curFightMove = FIGHTMOVE_HITONFLOOR;\n\t\t\t\t\tbreak;\n\t\t\t\tcase HITLEVEL_LOW:\n\t\t\t\t\tif (direction == 2 && (!IsPlayer() || ((CGeneral::GetRandomNumber() & 1) && m_fHealth < 30.0f))) {\n\t\t\t\t\t\tSetFall(1000, ANIM_STD_HIGHIMPACT_BACK, false);\n\t\t\t\t\t\tSay(SOUND_PED_DEFEND);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t} else if (direction != 2 && !IsPlayer() && (CGeneral::GetRandomNumber() & 1) && m_fHealth < 30.0f) {\n\t\t\t\t\t\tSetFall(1000, ANIM_STD_KO_SHOT_STOMACH, false);\n\t\t\t\t\t\tSay(SOUND_PED_DEFEND);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\t\n\t\t\t\t\tm_curFightMove = FIGHTMOVE_HITBODY;\n\t\t\t\t\tbreak;\n\t\t\t\tcase HITLEVEL_HIGH:\n\t\t\t\t\tswitch (direction) {\n\t\t\t\t\t\tcase 1:\n\t\t\t\t\t\t\tm_curFightMove = FIGHTMOVE_HITLEFT;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 2:\n\t\t\t\t\t\t\tm_curFightMove = FIGHTMOVE_HITBACK;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 3:\n\t\t\t\t\t\t\tm_curFightMove = FIGHTMOVE_HITRIGHT;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tif (unk <= 5)\n\t\t\t\t\t\t\t\tm_curFightMove = FIGHTMOVE_HITHEAD;\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\tm_curFightMove = FIGHTMOVE_HITBIGSTEP;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tswitch (direction) {\n\t\t\t\t\t\tcase 1:\n\t\t\t\t\t\t\tm_curFightMove = FIGHTMOVE_HITLEFT;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 2:\n\t\t\t\t\t\t\tm_curFightMove = FIGHTMOVE_HITBACK;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 3:\n\t\t\t\t\t\t\tm_curFightMove = FIGHTMOVE_HITRIGHT;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tif (unk <= 5)\n\t\t\t\t\t\t\t\tm_curFightMove = FIGHTMOVE_HITCHEST;\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\tm_curFightMove = FIGHTMOVE_HITBIGSTEP;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (m_nPedState == PED_GETUP && !IsPedHeadAbovePos(0.0f))\n\t\t\t\tm_curFightMove = FIGHTMOVE_HITONFLOOR;\n\n\t\t\tif (m_nPedState == PED_FIGHT) {\n\t\t\t\tCAnimBlendAssociation *moveAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[m_curFightMove].animId, 8.0f);\n\t\t\t\tmoveAssoc->SetCurrentTime(0.0f);\n\t\t\t\tmoveAssoc->SetFinishCallback(FinishFightMoveCB, this);\n\t\t\t\tif (IsPlayer())\n\t\t\t\t\tmoveAssoc->speed = 1.2f;\n\n\t\t\t\tm_takeAStepAfterAttack = 0;\n\t\t\t\tm_fightButtonPressure = 0;\n\n\t\t\t} else if (IsPlayer() && GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED && GetWeapon()->m_eWeaponType != WEAPONTYPE_BRASSKNUCKLE &&\n\t\t\t\t\t!CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->IsFlagSet(WEAPONFLAG_FIGHTMODE)) {\n\t\t\t\tCAnimBlendAssociation *moveAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[m_curFightMove].animId, 4.0f);\n\t\t\t\tmoveAssoc->SetCurrentTime(0.0f);\n\t\t\t\tmoveAssoc->speed = 1.2f;\n\n\t\t\t} else {\n\t\t\t\tif (m_nPedState != PED_AIM_GUN && m_nPedState != PED_ATTACK)\n\t\t\t\t\tSetStoredState();\n\n\t\t\t\tif (m_nWaitState != WAITSTATE_FALSE) {\n\t\t\t\t\tClearWaitState();\n\t\t\t\t\tRestoreHeadingRate();\n\t\t\t\t}\n\t\t\t\tSetPedState(PED_FIGHT);\n\t\t\t\tm_fightButtonPressure = 0;\n\t\t\t\tm_lastFightMove = FIGHTMOVE_IDLE;\n\t\t\t\tRpAnimBlendClumpRemoveAssociations(GetClump(), ASSOC_REPEAT);\n\t\t\t\tCAnimBlendAssociation *walkStartAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_STARTWALK);\n\t\t\t\tif (walkStartAssoc) {\n\t\t\t\t\twalkStartAssoc->flags |= ASSOC_DELETEFADEDOUT;\n\t\t\t\t\twalkStartAssoc->blendDelta = -1000.0f;\n\t\t\t\t}\n\t\t\t\tCAnimBlendAssociation *walkStopAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_RUNSTOP1);\n\t\t\t\tif (!walkStopAssoc)\n\t\t\t\t\twalkStopAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_RUNSTOP2);\n\t\t\t\tif (walkStopAssoc) {\n\t\t\t\t\twalkStopAssoc->flags |= ASSOC_DELETEFADEDOUT;\n\t\t\t\t\twalkStopAssoc->blendDelta = -1000.0f;\n\t\t\t\t\tRestoreHeadingRate();\n\t\t\t\t}\n\t\t\t\tSetMoveState(PEDMOVE_NONE);\n\t\t\t\tm_nStoredMoveState = PEDMOVE_NONE;\n\t\t\t\tCAnimBlendAssociation *fightIdleAssoc;\n\n\t\t\t\tif (GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED) {\n\t\t\t\t\tCWeaponInfo *weaponInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);\n\t\t\t\t\tif (GetFightIdleWithMeleeAnim(weaponInfo)) {\n\t\t\t\t\t\tfightIdleAssoc = CAnimManager::AddAnimation(GetClump(), weaponInfo->m_AnimToPlay, GetFightIdleWithMeleeAnim(weaponInfo));\n\t\t\t\t\t} else {\n\t\t\t\t\t\tfightIdleAssoc = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_FIGHT_IDLE);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tfightIdleAssoc = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_FIGHT_IDLE);\n\t\t\t\t}\n\t\t\t\tfightIdleAssoc->blendAmount = 1.0f;\n\t\t\t\tCAnimBlendAssociation *moveAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[m_curFightMove].animId, 8.0f);\n\t\t\t\tmoveAssoc->SetFinishCallback(FinishFightMoveCB, this);\n\t\t\t\tm_fightState = FIGHTSTATE_NO_MOVE;\n\t\t\t\tm_takeAStepAfterAttack = false;\n\t\t\t\tbIsAttacking = true;\n\t\t\t}\n\n\t\t\tif (m_pedInObjective && m_pedInObjective->IsPlayer() && !IsPlayer())\n\t\t\t\t((CPlayerPed*)m_pedInObjective)->RemovePedFromMeleeList(this);\n\t\t}\n\t}\n}\n\nvoid\nCPed::Fight(void)\n{\n\tCAnimBlendAssociation *currentAssoc, *animAssoc;\n\tbool fightWithWeapon = false;\n\n\teWeaponType weapon = GetWeapon()->m_eWeaponType;\n\tCWeaponInfo *weaponInfo = CWeaponInfo::GetWeaponInfo(weapon);\n\n\tif (weaponInfo->IsFlagSet(WEAPONFLAG_FIGHTMODE) && weapon != WEAPONTYPE_UNARMED) {\n\t\tfightWithWeapon = true;\n\t\ttFightMoves[FIGHTMOVE_MELEE1].startFireTime = weaponInfo->m_fAnimFrameFire;\n\t\ttFightMoves[FIGHTMOVE_MELEE1].endFireTime = weaponInfo->m_fAnimLoopEnd;\n\t\ttFightMoves[FIGHTMOVE_MELEE2].startFireTime = weaponInfo->m_fAnim2FrameFire;\n\t\ttFightMoves[FIGHTMOVE_MELEE2].endFireTime = weaponInfo->m_fAnim2LoopEnd;\n\t\ttFightMoves[FIGHTMOVE_MELEE3].startFireTime = weaponInfo->m_fAnim2FrameFire;\n\t\ttFightMoves[FIGHTMOVE_MELEE3].endFireTime = weaponInfo->m_fAnim2LoopEnd;\n\t}\n\n\tswitch (m_curFightMove) {\n\t\tcase FIGHTMOVE_NULL:\n\t\t\treturn;\n\t\tcase FIGHTMOVE_IDLE2NORM:\n\t\t\tm_curFightMove = FIGHTMOVE_NULL;\n\t\t\tRestorePreviousState();\n\n\t\t\t// FIX: Uninitialized\n\t\t\tcurrentAssoc = nil;\n\t\t\tbreak;\n\t\tcase FIGHTMOVE_IDLE:\n\t\t\tcurrentAssoc = nil;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tcurrentAssoc = RpAnimBlendClumpGetAssociation(GetClump(), tFightMoves[m_curFightMove].animId);\n\t\t\tbreak;\n\t}\n\n\tif (m_curFightMove == FIGHTMOVE_SHUFFLE_F && !currentAssoc)\n\t\tcurrentAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_FIGHT_SHUFFLE_B);\n\n\tif (IsPlayer() && currentAssoc && weapon == WEAPONTYPE_KATANA) {\n\t\tif (m_curFightMove == FIGHTMOVE_MELEE1 || m_curFightMove == FIGHTMOVE_MELEE2) {\n\t\t\tstatic float streakDelay = 0.2f;\n\n\t\t\tif (tFightMoves[m_curFightMove].startFireTime - streakDelay < currentAssoc->currentTime &&\n\t\t\t\tstreakDelay + tFightMoves[m_curFightMove].endFireTime > currentAssoc->currentTime) {\n\t\t\t\tCSpecialFX::AddWeaponStreak(GetWeapon()->m_eWeaponType);\n\t\t\t}\n\t\t}\n\t}\n\n\tif (!bIsAttacking && IsPlayer()) {\n\t\tif (currentAssoc) {\n\t\t\tcurrentAssoc->blendDelta = -1000.0f;\n\t\t\tcurrentAssoc->flags |= ASSOC_DELETEFADEDOUT;\n\t\t\tcurrentAssoc->flags &= ~ASSOC_RUNNING;\n\t\t}\n\t\tif (m_takeAStepAfterAttack)\n\t\t\tEndFight(ENDFIGHT_WITH_A_STEP);\n\t\telse\n\t\t\tEndFight(ENDFIGHT_FAST);\n\n\t} else if (currentAssoc && m_fightState > FIGHTSTATE_MOVE_FINISHED) {\n\t\tfloat animTime = currentAssoc->currentTime;\n\t\tFightMove &curMove = tFightMoves[m_curFightMove];\n\t\tif (curMove.hitLevel != HITLEVEL_NULL && animTime > curMove.startFireTime && animTime <= curMove.endFireTime && m_fightState >= FIGHTSTATE_NO_MOVE) {\n\n\t\t\tif (animTime > curMove.startFireTime && animTime - currentAssoc->timeStep < curMove.startFireTime &&\n\t\t\t\t(IsPlayer() || weapon != WEAPONTYPE_UNARMED)) {\n\n\t\t\t\tDMAudio.PlayOneShot(m_audioEntityId, SOUND_MELEE_ATTACK_START, weapon << 8);\n\t\t\t}\n\n\t\t\tCVector touchingNodePos(0.0f, 0.0f, 0.0f);\n\n\t\t\tswitch (m_curFightMove) {\n\t\t\t\tcase FIGHTMOVE_KNEE:\n\t\t\t\t\tTransformToNode(touchingNodePos, PED_LOWERLEGR);\n\t\t\t\t\tbreak;\n\t\t\t\tcase FIGHTMOVE_PUNCHHOOK:\n\t\t\t\tcase FIGHTMOVE_PUNCHJAB:\n\t\t\t\t\tTransformToNode(touchingNodePos, PED_HANDL);\n\t\t\t\t\tbreak;\n\t\t\t\tcase FIGHTMOVE_LONGKICK:\n\t\t\t\tcase FIGHTMOVE_ROUNDHOUSE:\n\t\t\t\tcase FIGHTMOVE_FWDLEFT:\n\t\t\t\tcase FIGHTMOVE_BACKRIGHT:\n\t\t\t\tcase FIGHTMOVE_GROUNDKICK:\n\t\t\t\t\tTransformToNode(touchingNodePos, PED_FOOTR);\n\t\t\t\t\tbreak;\n\t\t\t\tcase FIGHTMOVE_FWDRIGHT:\n\t\t\t\t\tTransformToNode(touchingNodePos, PED_HEAD);\n\t\t\t\t\tbreak;\n\t\t\t\tcase FIGHTMOVE_BACKKICK:\n\t\t\t\tcase FIGHTMOVE_BACKFLIP:\n\t\t\t\t\tTransformToNode(touchingNodePos, PED_FOOTL);\n\t\t\t\t\tbreak;\n\t\t\t\tcase FIGHTMOVE_BACKLEFT:\n\t\t\t\t\tTransformToNode(touchingNodePos, PED_UPPERARML);\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tTransformToNode(touchingNodePos, PED_HANDR);\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tFightStrike(touchingNodePos, fightWithWeapon);\n\t\t\tm_fightButtonPressure = 0;\n\t\t\treturn;\n\t\t}\n\n\t\tif (curMove.hitLevel != HITLEVEL_NULL) {\n\t\t\tif (animTime > curMove.endFireTime && weaponInfo->m_AnimToPlay != ASSOCGRP_KNIFE) {\n\t\t\t\tif (IsPlayer())\n\t\t\t\t\tcurrentAssoc->speed = 1.0f;\n\t\t\t\telse\n\t\t\t\t\tcurrentAssoc->speed = 0.8f;\n\t\t\t}\n\n\t\t\tif (IsPlayer() && !nPlayerInComboMove && !fightWithWeapon) {\n\t\t\t\tif (curMove.comboFollowOnTime > 0.0f && m_fightButtonPressure != 0 && animTime > curMove.comboFollowOnTime) {\n\n\t\t\t\t\tm_lastFightMove = m_curFightMove;\n\t\t\t\t\t// Notice that it increases fight move index, because we're in combo!\n\t\t\t\t\tanimAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[++m_curFightMove].animId, 8.0f);\n\t\t\t\t\tanimAssoc->SetFinishCallback(FinishFightMoveCB, this);\n\t\t\t\t\tanimAssoc->SetCurrentTime(0.1f * animAssoc->hierarchy->totalLength);\n\t\t\t\t\tanimAssoc->speed = 0.8f;\n\t\t\t\t\tm_fightButtonPressure = 0;\n\t\t\t\t\tnPlayerInComboMove = 1;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t} else if (GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED && GetWeapon()->m_eWeaponType != WEAPONTYPE_BRASSKNUCKLE && !fightWithWeapon) {\n\t\tEndFight(ENDFIGHT_FAST);\n\n\t} else if (m_fightButtonPressure != 0) {\n\t\tif (!IsPlayer())\n\t\t\tSay(SOUND_PED_ATTACK);\n\n\t\tif (m_curFightMove != FIGHTMOVE_IDLE)\n\t\t\tm_lastFightMove = m_curFightMove;\n\n\t\tm_curFightMove = IsPlayer() ? ChooseAttackPlayer(m_fightButtonPressure, fightWithWeapon) : ChooseAttackAI(m_fightButtonPressure, fightWithWeapon);\n\n\t\tif (m_curFightMove != FIGHTMOVE_IDLE) {\n\n\t\t\tanimAssoc = CAnimManager::BlendAnimation(GetClump(), m_curFightMove < FIGHTMOVE_MELEE1 ? ASSOCGRP_STD : weaponInfo->m_AnimToPlay,\n\t\t\t\ttFightMoves[m_curFightMove].animId, 8.0f);\n\n\t\t\tif (weaponInfo->m_AnimToPlay != ASSOCGRP_KNIFE || m_curFightMove < FIGHTMOVE_MELEE1) {\n\t\t\t\tif (m_curFightMove == FIGHTMOVE_BACKKICK)\n\t\t\t\t\tanimAssoc->speed = 1.15f;\n\t\t\t\telse\n\t\t\t\t\tanimAssoc->speed = 0.8f;\n\t\t\t} else {\n\t\t\t\tswitch (GetWeapon()->m_eWeaponType) {\n\t\t\t\t\tcase WEAPONTYPE_SCREWDRIVER:\n\t\t\t\t\tcase WEAPONTYPE_KNIFE:\n\t\t\t\t\t\tanimAssoc->speed = 1.05f;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase WEAPONTYPE_GOLFCLUB:\n\t\t\t\t\tcase WEAPONTYPE_NIGHTSTICK:\n\t\t\t\t\tcase WEAPONTYPE_BASEBALLBAT:\n\t\t\t\t\tcase WEAPONTYPE_HAMMER:\n\t\t\t\t\tcase WEAPONTYPE_KATANA:\n\t\t\t\t\t\tanimAssoc->speed = 0.8f;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase WEAPONTYPE_CLEAVER:\n\t\t\t\t\tcase WEAPONTYPE_MACHETE:\n\t\t\t\t\t\tanimAssoc->speed = 0.9f;\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (m_fightState == FIGHTSTATE_MOVE_FINISHED && animAssoc->currentTime != 0.0f) {\n\t\t\t\tanimAssoc->SetRun();\n\t\t\t\tif (!IsPlayer())\n\t\t\t\t\tanimAssoc->SetCurrentTime(0.0f);\n\t\t\t}\n\t\t\tif (IsPlayer())\n\t\t\t\tanimAssoc->SetCurrentTime(0.08f);\n\n\t\t\tanimAssoc->SetFinishCallback(FinishFightMoveCB, this);\n\t\t\tm_fightButtonPressure = 0;\n\t\t}\n\t\tm_fightState = FIGHTSTATE_NO_MOVE;\n\t} else if (m_takeAStepAfterAttack && m_curFightMove != FIGHTMOVE_SHUFFLE_F\n#ifndef FIX_BUGS\n\t\t&& CheckForPedsOnGroundToAttack(this, nil) == 4) {\n#else\n\t\t&& CheckForPedsOnGroundToAttack(this, nil) == PED_IN_FRONT_OF_ATTACKER) {\n#endif\n\t\tm_lastFightMove = m_curFightMove;\n\t\tm_curFightMove = FIGHTMOVE_SHUFFLE_F;\n\t\tanimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), tFightMoves[m_curFightMove].animId);\n\n\t\tif (animAssoc) {\n\t\t\tanimAssoc->SetCurrentTime(0.0f);\n\t\t\tanimAssoc->blendDelta = 4.0f;\n\t\t\tanimAssoc->SetRun();\n\t\t} else {\n\t\t\tanimAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[m_curFightMove].animId, 32.0f);\n\t\t}\n\t\tanimAssoc->SetFinishCallback(FinishFightMoveCB, this);\n\t\tm_fightState = FIGHTSTATE_NO_MOVE;\n\t\tm_fightButtonPressure = 0;\n\t\tm_takeAStepAfterAttack = false;\n\n\t} else if (m_takeAStepAfterAttack) {\n\t\tEndFight(ENDFIGHT_FAST);\n\n\t} else if (m_curFightMove == FIGHTMOVE_IDLE) {\n\t\tif (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {\n\t\t\tEndFight(ENDFIGHT_NORMAL);\n\t\t}\n\n\t} else {\n\t\tm_lastFightMove = m_curFightMove;\n\t\tm_curFightMove = FIGHTMOVE_IDLE;\n\t\tif (IsPlayer())\n\t\t\tm_nWaitTimer = CTimer::GetTimeInMilliseconds() + 500;\n\t\telse\n\t\t\tm_nWaitTimer = CTimer::GetTimeInMilliseconds() + 2000;\n\t}\n}\n\nint32\nCPed::ChooseAttackAI(uint8 buttonPressure, bool fightWithWeapon)\n{\n\teWeaponType weapon = GetWeapon()->m_eWeaponType;\n\tCWeaponInfo *weaponInfo = CWeaponInfo::GetWeaponInfo(weapon);\n\tif (!fightWithWeapon && weapon != WEAPONTYPE_UNARMED && weapon != WEAPONTYPE_BRASSKNUCKLE) {\n\t\treturn FIGHTMOVE_PUNCH;\n\t}\n\n\tif (!m_pedInObjective)\n\t\treturn FIGHTMOVE_IDLE;\n\tif (buttonPressure == 0)\n\t\treturn FIGHTMOVE_IDLE;\n\n\tuint16 pedFeatures = m_pedStats->m_flags;\n\tbool punchOnly = !!(pedFeatures & STAT_PUNCH_ONLY);\n\tbool canRoundhouse = !!(pedFeatures & STAT_CAN_ROUNDHOUSE);\n\tbool canKneeHead = !!(pedFeatures & STAT_CAN_KNEE_HEAD);\n\tbool canKick = !!(pedFeatures & STAT_CAN_KICK);\n\tbool hasShoppingBags = !!(pedFeatures & STAT_SHOPPING_BAGS);\n\n\tCVector distVec(m_pedInObjective->GetPosition() - GetPosition());\n\tfloat dist = distVec.Magnitude();\n\tm_fRotationDest = CGeneral::LimitRadianAngle(distVec.Heading());\n\tm_fRotationCur = m_fRotationDest;\n\n\tif (fightWithWeapon) {\n\t\tif (m_pedInObjective->OnGroundOrGettingUp()) {\n\t\t\tif (CGame::nastyGame && dist < 1.2f && !m_pedInObjective->IsPlayer()\n\t\t\t\t&& (m_pedInObjective->m_nPedState == PED_DEAD || !m_pedInObjective->IsPedHeadAbovePos(-0.3f))) {\n\t\t\t\tif (weaponInfo->IsFlagSet(WEAPONFLAG_GROUND_2ND))\n\t\t\t\t\treturn FIGHTMOVE_MELEE2;\n\t\t\t\tif (weaponInfo->IsFlagSet(WEAPONFLAG_GROUND_3RD))\n\t\t\t\t\treturn FIGHTMOVE_MELEE3;\n\n\t\t\t\treturn FIGHTMOVE_GROUNDKICK;\n\t\t\t} else {\n\t\t\t\treturn FIGHTMOVE_IDLE;\n\t\t\t}\n\t\t}\n\t\tif (dist < 2.f) {\n\t\t\tif (m_curFightMove == FIGHTMOVE_MELEE1) {\n\t\t\t\tif (GetSecondFireAnim(weaponInfo))\n\t\t\t\t\treturn FIGHTMOVE_MELEE2;\n\t\t\t}\n\t\t\tif (m_curFightMove == FIGHTMOVE_MELEE2) {\n\t\t\t\tif (GetFinishingAttackAnim(weaponInfo))\n\t\t\t\t\treturn FIGHTMOVE_MELEE3;\n\t\t\t}\n\t\t\treturn FIGHTMOVE_MELEE1;\n\t\t}\n\t\treturn FIGHTMOVE_SHUFFLE_F;\n\t}\n\tif (!hasShoppingBags) {\n\t\tif (punchOnly) {\n\t\t\tif (dist < 1.4f)\n\t\t\t\treturn FIGHTMOVE_PUNCH;\n\t\t} else {\n\t\t\tif (m_pedInObjective->OnGroundOrGettingUp()) {\n\t\t\t\tif (CGame::nastyGame && dist < 1.2f && !m_pedInObjective->IsPlayer()\n\t\t\t\t\t&& (m_pedInObjective->m_nPedState == PED_DEAD || !m_pedInObjective->IsPedHeadAbovePos(-0.3f))) {\n\n\t\t\t\t\treturn FIGHTMOVE_GROUNDKICK;\n\t\t\t\t} else {\n\t\t\t\t\treturn FIGHTMOVE_IDLE;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (dist < 0.95f && canKneeHead)\n\t\t\t\treturn FIGHTMOVE_KNEE;\n\t\t\tif (dist < 1.4f)\n\t\t\t\treturn FIGHTMOVE_PUNCH;\n\t\t\tif (dist < 2.f && canKick) {\n\t\t\t\tint nextMove = FIGHTMOVE_LONGKICK;\n\t\t\t\tif (canRoundhouse && CGeneral::GetRandomNumber() & 1)\n\t\t\t\t\tnextMove = FIGHTMOVE_ROUNDHOUSE;\n\t\t\t\treturn nextMove;\n\t\t\t}\n\t\t}\n\t\treturn FIGHTMOVE_SHUFFLE_F;\n\t}\n\tif (dist < 2.f)\n\t\treturn FIGHTMOVE_ROUNDHOUSE;\n\telse\n\t\treturn FIGHTMOVE_SHUFFLE_F;\n}\n\nint32\nCPed::ChooseAttackPlayer(uint8 buttonPressure, bool fightWithWeapon)\n{\n\tCWeaponInfo *weaponInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);\n\tconst float maxAttackDist = 2.7f;\n\tfloat weaponAttackDist = 2.0f;\n\tCPed *victimPed = nil;\n\tCPed *walkUpTo = nil;\n\tCPed *groundAttackDeadPed = nil;\n\tCPed *groundAttackAlivePed = nil;\n\tif (fightWithWeapon)\n\t\tweaponAttackDist = weaponInfo->m_fRange;\n\n\tbool willWalkUp = false;\n\tPedFightMoves choosenMove = FIGHTMOVE_IDLE;\n\tint numPedsWeCanReach = 0;\n\tif (m_takeAStepAfterAttack)\n\t\twillWalkUp = true;\n\n\tfloat groundAttackDeadAngle, groundAttackAliveAngle, walkAngle, victimAngle, distToVictim;\n\n\tfor (int i = 0; i < m_numNearPeds; ++i) {\n\t\tCPed *nearPed = m_nearPeds[i];\n\t\tCVector distVec(nearPed->GetPosition() - GetPosition());\n\t\tfloat dist = distVec.Magnitude();\n\t\tif (dist < maxAttackDist) {\n\t\t\tfloat nearPedAngle = CGeneral::LimitRadianAngle(distVec.Heading());\n\t\t\tm_fRotationCur = CGeneral::LimitRadianAngle(m_fRotationCur);\n\t\t\tfloat neededTurn = Abs(nearPedAngle - m_fRotationCur);\n\t\t\tif (neededTurn > PI)\n\t\t\t\tneededTurn = TWOPI - neededTurn;\n\n\t\t\tif (!nearPed->OnGroundOrGettingUp() && nearPed->m_nWaitState != WAITSTATE_SUN_BATHE_IDLE) {\n\t\t\t\tif (!willWalkUp || neededTurn <= DEGTORAD(45.0f)) {\n\n\t\t\t\t\tif (neededTurn <= DEGTORAD(30.0f) || nearPed->m_pedInObjective == this\n\t\t\t\t\t\t&& (nearPed->m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT || nearPed->m_objective == OBJECTIVE_KILL_CHAR_ANY_MEANS)) {\n\n\t\t\t\t\t\tif (dist < weaponAttackDist) {\n\t\t\t\t\t\t\tif (!victimPed\n\t\t\t\t\t\t\t\t|| nearPed->m_attackTimer < victimPed->m_attackTimer && nearPed->m_attackTimer > CTimer::GetTimeInMilliseconds() - 100) {\n\t\t\t\t\t\t\t\tvictimPed = nearPed;\n\t\t\t\t\t\t\t\tvictimAngle = nearPedAngle;\n\t\t\t\t\t\t\t\tdistToVictim = dist;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t++numPedsWeCanReach;\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (neededTurn < DEGTORAD(30.0f)) {\n\t\t\t\t\t\t\t\twalkUpTo = nearPed;\n\t\t\t\t\t\t\t\twalkAngle = nearPedAngle;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if (CGame::nastyGame && dist < 1.2f && neededTurn < DEGTORAD(55.0f)) {\n\t\t\t\tif (!nearPed->DyingOrDead() || groundAttackDeadPed) {\n\t\t\t\t\tif (!nearPed->IsPedHeadAbovePos(-0.3f)) {\n\t\t\t\t\t\tgroundAttackAlivePed = nearPed;\n\t\t\t\t\t\tgroundAttackAliveAngle = nearPedAngle;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tgroundAttackDeadPed = nearPed;\n\t\t\t\t\tgroundAttackDeadAngle = nearPedAngle;\n\t\t\t\t}\n\t\t\t\t++numPedsWeCanReach;\n\n\t\t\t} else if (dist > 1.4f && dist < maxAttackDist && neededTurn < DEGTORAD(30.0f)) {\n\t\t\t\tif (!walkUpTo) {\n\t\t\t\t\twalkUpTo = nearPed;\n\t\t\t\t\twalkAngle = nearPedAngle;\n\t\t\t\t}\n#ifdef FIX_BUGS\n\t\t\t\tif(dist < 2.1f)\n#endif\n\t\t\t\t++numPedsWeCanReach;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (victimPed) {\n\t\tfloat adjustedAngleDiff = victimAngle - m_fRotationCur + DEGTORAD(30.0f);\n\t\tif (adjustedAngleDiff < 0.0f)\n\t\t\tadjustedAngleDiff += TWOPI;\n\n\t\tint16 dir = Floor(adjustedAngleDiff / DEGTORAD(60.0f));\n\n\t\t// Just focus on who we're fighting with, don't care peds on ground\n\t\tif (numPedsWeCanReach < 2 || fightWithWeapon) {\n\t\t\tfloat angleDiff = Abs(victimAngle - m_fRotationCur);\n\t\t\tif (angleDiff > PI)\n\t\t\t\tangleDiff = TWOPI - angleDiff;\n\n\t\t\tif (angleDiff < DEGTORAD(60.0f))\n\t\t\t\tdir = 0; // forward\n\t\t}\n\t\tint16 randVal = CGeneral::GetRandomNumber() & 3;\n\t\tswitch (dir) {\n\t\t\tcase 0: // forward\n\t\t\t\tif (fightWithWeapon) {\n\t\t\t\t\tif (distToVictim < 0.95f - 0.2f && m_nPedState == PED_FIGHT) {\n\t\t\t\t\t\tchoosenMove = FIGHTMOVE_KNEE;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (GetWeapon()->m_eWeaponType == WEAPONTYPE_CLEAVER) {\n\t\t\t\t\t\t\tif (distToVictim < 0.85f * weaponInfo->m_fRange)\n\t\t\t\t\t\t\t\tchoosenMove = FIGHTMOVE_MELEE1;\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\tchoosenMove = FIGHTMOVE_SHUFFLE_F;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tfloat weaponRange = weaponInfo->m_fRange;\n\t\t\t\t\t\t\tif (distToVictim < 0.75f * weaponRange && GetWeapon()->m_eWeaponType != WEAPONTYPE_SCREWDRIVER) {\n\t\t\t\t\t\t\t\tif (m_lastFightMove == FIGHTMOVE_MELEE1 && GetFinishingAttackAnim(weaponInfo)) {\n\t\t\t\t\t\t\t\t\tchoosenMove = FIGHTMOVE_MELEE2;\n\t\t\t\t\t\t\t\t} else if (m_lastFightMove == FIGHTMOVE_MELEE2 && GetFinishingAttackAnim(weaponInfo)) {\n\t\t\t\t\t\t\t\t\tchoosenMove = FIGHTMOVE_MELEE3;\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tchoosenMove = FIGHTMOVE_MELEE1;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else if (distToVictim < weaponRange && GetFinishingAttackAnim(weaponInfo)) {\n\t\t\t\t\t\t\t\tchoosenMove = FIGHTMOVE_MELEE3;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tchoosenMove = FIGHTMOVE_SHUFFLE_F;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else if (distToVictim < 0.95f && m_nPedState == PED_FIGHT) {\n\t\t\t\t\tchoosenMove = FIGHTMOVE_KNEE;\n\n\t\t\t\t} else if (distToVictim < 1.4f) {\n\t\t\t\t\tif (m_curFightMove == FIGHTMOVE_PUNCHJAB) {\n\t\t\t\t\t\tchoosenMove = FIGHTMOVE_PUNCH;\n\n\t\t\t\t\t} else if (m_curFightMove != FIGHTMOVE_PUNCH || randVal != 1) {\n\t\t\t\t\t\tif (randVal == 2)\n\t\t\t\t\t\t\tchoosenMove = FIGHTMOVE_PUNCH;\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tchoosenMove = FIGHTMOVE_PUNCHJAB;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tchoosenMove = FIGHTMOVE_LONGKICK;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tchoosenMove = FIGHTMOVE_LONGKICK;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 1:\n\t\t\t\tchoosenMove = FIGHTMOVE_FWDLEFT;\n\t\t\t\tbreak;\n\t\t\tcase 2:\n\t\t\t\tchoosenMove = FIGHTMOVE_BACKLEFT;\n\t\t\t\tbreak;\n\t\t\tcase 3:\n\t\t\t\tchoosenMove = FIGHTMOVE_BACKKICK;\n\t\t\t\tbreak;\n\t\t\tcase 4:\n\t\t\t\tchoosenMove = FIGHTMOVE_BACKRIGHT;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tchoosenMove = FIGHTMOVE_FWDRIGHT;\n\t\t\t\tbreak;\n\t\t}\n\n\t\t// forward\n\t\tif (dir == 0) {\n\t\t\tm_fRotationDest = CGeneral::LimitRadianAngle(victimAngle);\n\t\t} else {\n\t\t\tm_fRotationDest = victimAngle - dir * DEGTORAD(60.0f);\n\t\t\tm_fRotationDest = CGeneral::LimitRadianAngle(m_fRotationDest);\n\t\t}\n\t\t\n\t\tm_fRotationCur = m_fRotationDest;\n\t\tSay(SOUND_PED_ATTACK);\n\n\t} else if (groundAttackAlivePed || groundAttackDeadPed) {\n\t\tif (fightWithWeapon && weaponInfo->IsFlagSet(WEAPONFLAG_GROUND_2ND)) {\n\t\t\tchoosenMove = FIGHTMOVE_MELEE2;\n\t\t} else if (fightWithWeapon && weaponInfo->IsFlagSet(WEAPONFLAG_GROUND_3RD)) {\n\t\t\tchoosenMove = FIGHTMOVE_MELEE3;\n\t\t} else {\n\t\t\tchoosenMove = FIGHTMOVE_GROUNDKICK;\n\t\t}\n\t\tif (groundAttackAlivePed)\n\t\t\tm_fRotationDest = groundAttackAliveAngle;\n\t\telse\n\t\t\tm_fRotationDest = groundAttackDeadAngle;\n\n\t\tm_fRotationCur = m_fRotationDest;\n\t\tm_lookTimer = 0;\n\t\tif (groundAttackAlivePed)\n\t\t\tSetLookFlag(groundAttackAlivePed, 1, 0);\n\t\telse\n\t\t\tSetLookFlag(groundAttackDeadPed, 1, 0);\n\n\t\tSetLookTimer(1500u);\n\n\t} else if (walkUpTo) {\n\t\tchoosenMove = FIGHTMOVE_SHUFFLE_F;\n\t\tm_fRotationCur = m_fRotationDest = walkAngle;\n\t\tm_lookTimer = 0;\n\t\tSetLookFlag(walkUpTo, true);\n\t\tSetLookTimer(1500);\n\n\t} else if (fightWithWeapon) {\n\t\t// No enemy, fight with space\n\t\tif (GetWeapon()->m_eWeaponType == WEAPONTYPE_SCREWDRIVER) {\n\t\t\tchoosenMove = FIGHTMOVE_MELEE3;\n\t\t} else {\n\t\t\tif (m_lastFightMove == FIGHTMOVE_MELEE1 && GetFinishingAttackAnim(weaponInfo)) {\n\t\t\t\tchoosenMove = FIGHTMOVE_MELEE2;\n\t\t\t} else if (m_lastFightMove == FIGHTMOVE_MELEE2 && GetFinishingAttackAnim(weaponInfo)) {\n\t\t\t\tchoosenMove = FIGHTMOVE_MELEE3;\n\t\t\t} else {\n\t\t\t\tchoosenMove = FIGHTMOVE_MELEE1;\n\t\t\t}\n\t\t}\n\t} else {\n\t\t// Max number GetRandomNumberInRange returns is max-1\n#ifdef FIX_BUGS\n\t\tswitch (CGeneral::GetRandomNumberInRange(0,4)) {\n#else\n\t\tswitch (CGeneral::GetRandomNumberInRange(0,3)) {\n#endif\n\t\t\tcase 0:\n\t\t\t\tchoosenMove = FIGHTMOVE_PUNCHJAB;\n\t\t\t\tbreak;\n\t\t\tcase 1:\n\t\t\t\tchoosenMove = FIGHTMOVE_PUNCH;\n\t\t\t\tbreak;\n\t\t\tcase 2:\n\t\t\t\tchoosenMove = FIGHTMOVE_LONGKICK;\n\t\t\t\tbreak;\n\t\t\tcase 3:\n\t\t\t\tchoosenMove = FIGHTMOVE_KNEE;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n\treturn choosenMove;\n}\n\nvoid\nCPed::EndFight(uint8 endType)\n{\n\tif (m_nPedState != PED_FIGHT)\n\t\treturn;\n\n\tm_curFightMove = FIGHTMOVE_NULL;\n\tRestorePreviousState();\n\tCAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_FIGHT_IDLE);\n\tif (!animAssoc)\n\t\tanimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_MELEE_IDLE_FIGHTMODE);\n\n\tif (animAssoc)\n\t\tanimAssoc->flags |= ASSOC_DELETEFADEDOUT;\n\n\tswitch (endType) {\n\t\tcase ENDFIGHT_NORMAL:\n\t\t\tCAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_STD_IDLE, 8.0f);\n\t\t\tCAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_FIGHT_2IDLE, 8.0f);\n\t\t\tbreak;\n\t\tcase ENDFIGHT_WITH_A_STEP:\n\t\t\tCAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_STD_IDLE, 1.0f);\n\t\t\tCAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_STARTWALK, 8.0f);\n\t\t\tbreak;\n\t\tcase ENDFIGHT_FAST:\n\t\t\tCAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_STD_IDLE, 8.0f);\n\t\t\tCAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_FIGHT_2IDLE, 8.0f)->speed = 2.0f;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\tm_nWaitTimer = 0;\n}\n\nvoid\nCPed::PlayHitSound(CPed *hitTo)\n{\n\t// That was very complicated to reverse for me...\n\t// First index is our fight move ID (from 1 to 17, total 17), second is the one of we fight with (from 18 to 27, total 10).\n\tenum {\n\t\tS37 = SOUND_FIGHT_37,\n\t\tS38 = SOUND_FIGHT_38,\n\t\tS39 = SOUND_FIGHT_39,\n\t\tS40 = SOUND_FIGHT_40,\n\t\tS41 = SOUND_FIGHT_41,\n\t\tS42 = SOUND_FIGHT_42,\n\t\tS43 = SOUND_FIGHT_43,\n\t\tS44 = SOUND_FIGHT_44,\n\t\tS45 = SOUND_FIGHT_45,\n\t\tS46 = SOUND_FIGHT_46,\n\t\tS47 = SOUND_FIGHT_47,\n\t\tS48 = SOUND_FIGHT_48,\n\t\tNO_SND = SOUND_NO_SOUND\n\t};\n\tconst uint16 hitSoundsByFightMoves[17][10] = {\n\t  { S37, S46, S41, S41, S46, S46, S40, S41, S43, S40 },\n\t  { NO_SND, NO_SND, NO_SND, NO_SND, NO_SND, NO_SND, NO_SND, NO_SND, NO_SND, NO_SND },\n\t  { NO_SND, NO_SND, NO_SND, NO_SND, NO_SND, NO_SND, NO_SND, NO_SND, NO_SND, NO_SND },\n\t  { S46, S46, S46, S46, S37, S47, S37, S38, S43, S38 },\n\t  { S46, S46, S46, S46, S46, S46, S40, S41, S43, S46 },\n\t  { S46, S46, S46, S46, S46, S46, S40, S41, S43, S40 },\n\t  { S46, S46, S46, S46, S46, S46, S40, S41, S43, S40 },\n\t  { S46, S46, S37, S46, S37, S47, S40, S47, S43, S37 },\n\t  { S46, S46, S46, S46, S46, S46, S43, S44, S43, S43 },\n\t  { S37, S46, S46, S46, S38, S47, S40, S38, S43, S46 },\n\t  { S46, S37, S46, S37, S39, S46, S40, S39, S43, S37 },\n\t  { S46, S37, S46, S46, S38, S47, S40, S38, S43, S46 },\n\t  { S37, S37, S46, S46, S38, S47, S48, S38, S43, S37 },\n\t  { S46, S46, S46, S46, S37, S46, S40, S38, S43, S46 },\n\t  { S46, S46, S46, S37, S39, S46, S40, S39, S43, S46 },\n\t  { S37, S46, S46, S46, S37, S46, S40, S37, S43, S46 },\n\t  { S43, S43, S43, S43, S43, S43, S43, S43, S43, S43 }\n\t};\n\n\teWeaponType weapon = GetWeapon()->m_eWeaponType;\n\tCWeaponInfo *weaponInfo = CWeaponInfo::GetWeaponInfo(weapon);\n\tif (weaponInfo->m_AnimToPlay == ASSOCGRP_KNIFE) {\n\t\tif (m_curFightMove >= FIGHTMOVE_MELEE1) {\n\t\t\tif (m_curFightMove == FIGHTMOVE_MELEE3) {\n\t\t\t\tDMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_BAT_ATTACK, (weapon << 8) | ENTITY_TYPE_PED);\n\t\t\t} else {\n\t\t\t\tDMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_KNIFE_ATTACK, (weapon << 8) | ENTITY_TYPE_PED);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t}\n\n\t// This is why first dimension is between FightMove 1 and 17.\n\tif (m_curFightMove <= FIGHTMOVE_NULL || m_curFightMove >= FIGHTMOVE_HITFRONT)\n\t\treturn;\n\n\tuint16 soundId;\n\n\t// And this is why second dimension is between 18 and 27.\n\tif (hitTo->m_curFightMove > FIGHTMOVE_GROUNDKICK && hitTo->m_curFightMove < FIGHTMOVE_IDLE2NORM) {\n\t\tsoundId = hitSoundsByFightMoves[m_curFightMove - FIGHTMOVE_STDPUNCH][hitTo->m_curFightMove - FIGHTMOVE_HITFRONT];\n\n\t} else {\n\t\tif (hitTo->m_nPedState == PED_DEAD || hitTo->UseGroundColModel()) {\t\n\t\t\tsoundId = hitSoundsByFightMoves[m_curFightMove - FIGHTMOVE_STDPUNCH][FIGHTMOVE_HITONFLOOR - FIGHTMOVE_HITFRONT];\n\t\t} else {\n\t\t\tsoundId = hitSoundsByFightMoves[m_curFightMove - FIGHTMOVE_STDPUNCH][FIGHTMOVE_HITFRONT - FIGHTMOVE_HITFRONT];\n\t\t}\n\t}\n\n\tif (soundId != NO_SND)\n\t\tDMAudio.PlayOneShot(m_audioEntityId, soundId, (weapon << 8) | ENTITY_TYPE_PED);\n}\n\nbool\nCPed::FightStrike(CVector &touchedNodePos, bool fightWithWeapon)\n{\n\tCColModel *hisCol;\n\tCVector attackDistance;\n\tfloat maxDistanceToBeat;\n\tCPed *nearPed;\n\tCVector extendedTouchPoint;\n\n\tCWeaponInfo *weaponInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);\n\tfloat radius = tFightMoves[m_curFightMove].strikeRadius;\n\tif (fightWithWeapon)\n\t\tradius = weaponInfo->m_fRadius;\n\n\tif (m_fightState == FIGHTSTATE_JUST_ATTACKED)\n\t\treturn false;\n\n\tif (this == FindPlayerPed() && fightWithWeapon && GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED)\n\t\tCGlass::BreakGlassPhysically(touchedNodePos, radius);\n\n\tfor (int i = 0; i < m_numNearPeds; i++) {\n\t\tint8 pedFound = 0;\n\t\tnearPed = m_nearPeds[i];\n\t\tif (!fightWithWeapon && GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED && GetWeapon()->m_eWeaponType != WEAPONTYPE_BRASSKNUCKLE)\n\t\t\tmaxDistanceToBeat = nearPed->GetBoundRadius() + radius + 0.1f;\n\t\telse\n\t\t\tmaxDistanceToBeat = nearPed->GetBoundRadius() + radius;\n\n\t\tif ((nearPed->bUsesCollision || nearPed->m_nPedState == PED_DEAD) && (m_pedInObjective != FindPlayerPed() || nearPed == FindPlayerPed())) {\n\t\t\tCVector nearPedCentre;\n\n\t\t\t// Have to animate a skinned clump because the initial col model is useless\n\t\t\thisCol = ((CPedModelInfo*)CModelInfo::GetModelInfo(nearPed->GetModelIndex()))->AnimatePedColModelSkinnedWorld(nearPed->GetClump());\n\n\t\t\tnearPed->GetBoundCentre(nearPedCentre);\n\t\t\tCVector potentialAttackDistance = nearPedCentre - touchedNodePos;\n\n\t\t\t// He can beat us\n\t\t\tif (sq(maxDistanceToBeat) > potentialAttackDistance.MagnitudeSqr()) {\n\n\t\t\t\tfor (int j = 0; j < hisCol->numSpheres; j++) {\n\t\t\t\t\tattackDistance = hisCol->spheres[j].center;\n\t\t\t\t\tattackDistance -= touchedNodePos;\n\t\t\t\t\tCColSphere *hisPieces = hisCol->spheres;\n\t\t\t\t\tmaxDistanceToBeat = hisPieces[j].radius + radius;\n\n\t\t\t\t\t// We can beat him too\n\t\t\t\t\tif (sq(maxDistanceToBeat) > attackDistance.MagnitudeSqr()) {\n\t\t\t\t\t\tFightHitPed(nearPed, touchedNodePos, attackDistance, hisPieces[j].piece);\n\t\t\t\t\t\tpedFound = 1;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!pedFound && !fightWithWeapon) {\n\t\t\t\textendedTouchPoint = touchedNodePos - GetPosition();\n\t\t\t\tif (DotProduct(touchedNodePos - GetPosition(), nearPed->GetPosition() - GetPosition()) > 0.f) {\n\t\t\t\t\tif (m_curFightMove == FIGHTMOVE_GROUNDKICK) {\n\t\t\t\t\t\textendedTouchPoint += tFightMoves[FIGHTMOVE_GROUNDKICK].extendReachMultiplier * GetForward();\n\t\t\t\t\t} else {\n\t\t\t\t\t\textendedTouchPoint.x *= tFightMoves[m_curFightMove].extendReachMultiplier;\n\t\t\t\t\t\textendedTouchPoint.y *= tFightMoves[m_curFightMove].extendReachMultiplier;\n\t\t\t\t\t}\n\t\t\t\t\tpedFound = -1;\n\t\t\t\t\textendedTouchPoint += GetPosition();\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (pedFound == -1) {\n\t\t\t\tCVector nearPedCentre = nearPed->GetBoundCentre();\n\t\t\t\tif (sq(maxDistanceToBeat) > (nearPedCentre - extendedTouchPoint).MagnitudeSqr()) {\n\n\t\t\t\t\tfor (int j = 0; j < hisCol->numSpheres; j++) {\n\t\t\t\t\t\tattackDistance = hisCol->spheres[j].center;\n\t\t\t\t\t\tattackDistance -= extendedTouchPoint;\n\t\t\t\t\t\tCColSphere* hisPieces = hisCol->spheres;\n\t\t\t\t\t\tfloat maxDistanceToBeat2 = hisPieces[j].radius + tFightMoves[m_curFightMove].strikeRadius;\n\n\t\t\t\t\t\t// We can beat him too\n\t\t\t\t\t\tif (sq(maxDistanceToBeat2) > attackDistance.MagnitudeSqr()) {\n\t\t\t\t\t\t\tFightHitPed(nearPed, extendedTouchPoint, attackDistance, hisPieces[j].piece);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\n\tif (m_fightState == FIGHTSTATE_NO_MOVE)\n\t\tm_fightState = FIGHTSTATE_1;\n\n\tm_vecHitLastPos = touchedNodePos;\n\treturn false;\n}\n\nvoid\nCPed::FightHitPed(CPed *victim, CVector &touchPoint, CVector &dir, int16 piece)\n{\n\tif (victim->IsPlayer() && victim->m_nPedState == PED_GETUP)\n\t\treturn;\n\n\tCWeaponInfo *weaponInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);\n\tbool fightingWithWeapon = false;\n\tint damageMult = tFightMoves[m_curFightMove].damage * ((CGeneral::GetRandomNumber() & 1) + 2) + 1;\n\n\tif (weaponInfo->IsFlagSet(WEAPONFLAG_FIGHTMODE)) {\n\t\tfightingWithWeapon = true;\n\t\tif (m_curFightMove >= FIGHTMOVE_MELEE1) {\n\t\t\tdamageMult = weaponInfo->m_nDamage;\n\t\t\tif (m_curFightMove == FIGHTMOVE_MELEE3 && GetWeapon()->m_eWeaponType != WEAPONTYPE_SCREWDRIVER)\n\t\t\t\tdamageMult *= 5;\n\t\t}\n\t}\n\n\tif (IsPlayer()) {\n\t\tif (((CPlayerPed*)this)->m_bAdrenalineActive)\n\t\t\tdamageMult = 20;\n\t} else if (!fightingWithWeapon) {\n\t\tdamageMult *= m_pedStats->m_attackStrength;\n\t}\n\n\tfloat oldVictimHealth = victim->m_fHealth;\n\tCVector bloodPos = 0.5f * dir + touchPoint;\n\tCVector2D diff(GetPosition() - victim->GetPosition());\n\tint direction = victim->GetLocalDirection(diff);\n\n\tbool brassKnucklePunch = false;\n\tif (GetWeapon()->m_eWeaponType == WEAPONTYPE_BRASSKNUCKLE) {\n\t\tif (m_curFightMove == FIGHTMOVE_PUNCHHOOK || m_curFightMove == FIGHTMOVE_PUNCHJAB || m_curFightMove == FIGHTMOVE_BACKLEFT ||\n\t\t\tm_curFightMove == FIGHTMOVE_STDPUNCH || m_curFightMove == FIGHTMOVE_PUNCH) {\n\t\t\tbrassKnucklePunch = true;\n\t\t\tdamageMult *= 1.5f;\n\t\t}\n\t}\n\tvictim->ReactToAttack(this);\n\n\t// Mostly unused. if > 5, ANIM_HIT_BIGSTEP will be run, that's it.\n\tint unk2;\n\tif (GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED && GetWeapon()->m_eWeaponType != WEAPONTYPE_BRASSKNUCKLE &&\n\t\t!victim->IsPlayer() && !fightingWithWeapon)\n\t\tunk2 = 101;\n\telse\n\t\tunk2 = damageMult;\n\n\tvictim->StartFightDefend(direction, tFightMoves[m_curFightMove].hitLevel, unk2);\n\tPlayHitSound(victim);\n\tm_fightState = FIGHTSTATE_JUST_ATTACKED;\n\tRpAnimBlendClumpGetAssociation(GetClump(), tFightMoves[m_curFightMove].animId)->speed = 0.6f;\n\n\tif (!victim->DyingOrDead()) {\n\t\tif(fightingWithWeapon)\n\t\t\tvictim->InflictDamage(this, GetWeapon()->m_eWeaponType, damageMult, (ePedPieceTypes)piece, direction);\n\t\telse\n\t\t\tvictim->InflictDamage(this, WEAPONTYPE_UNARMED, damageMult * 3.0f, (ePedPieceTypes)piece, direction);\n\t}\n\n\tif (CGame::nastyGame && weaponInfo->m_AnimToPlay == ASSOCGRP_KNIFE && m_curFightMove >= FIGHTMOVE_MELEE1\n\t\t&& victim->GetIsOnScreen()) {\n\n\t\tstatic float particleRightLen = 0.05f;\n\t\tstatic float particleUpLen = 0.05f;\n\n\t\t// Just for particles. We will restore it below.\n\t\tdir /= (20.0f * dir.Magnitude());\n\t\tif (m_curFightMove == FIGHTMOVE_MELEE1) {\n\t\t\tfloat rightMult = -particleRightLen;\n\t\t\tdir += particleUpLen * GetUp() + rightMult * GetRight();\n\n\t\t} else if (m_curFightMove == FIGHTMOVE_MELEE2) {\n\t\t\tfloat upMult = 2.0f * particleUpLen;\n\t\t\tdir += particleRightLen * GetRight() + upMult * GetUp();\n\t\t}\n\t\tCParticle::AddParticle(PARTICLE_BLOOD_SPURT, bloodPos, dir, nil, 0.0f, 0, 0, 0, 0);\n\t\tCParticle::AddParticle(PARTICLE_BLOOD_SPURT, bloodPos, dir, nil, 0.0f, 0, 0, 0, 0);\n\t\tif (IsPlayer()) {\n\t\t\tCParticle::AddParticle(PARTICLE_BLOOD_SPURT, bloodPos, dir, nil, 0.0f, 0, 0, 0, 0);\n\t\t\tCParticle::AddParticle(PARTICLE_BLOOD_SPURT, bloodPos, dir, nil, 0.0f, 0, 0, 0, 0);\n\t\t}\n\t\tif (!(CGeneral::GetRandomNumber() & 3)) {\n\t\t\tCParticle::AddParticle(PARTICLE_TEST, bloodPos, dir, nil, 0.0f, 0, 0, 0, 0);\n\t\t}\n\t} else if (CGame::nastyGame && (tFightMoves[m_curFightMove].hitLevel > HITLEVEL_MEDIUM || fightingWithWeapon)\n\t\t\t&& victim->GetIsOnScreen()) {\n\n\t\t// Just for particles. We will restore it below.\n\t\tdir /= (10.0f * dir.Magnitude());\n\t\tfor (int i = 0; i < 4; i++) {\n\t\t\tCParticle::AddParticle(PARTICLE_BLOOD, bloodPos, dir, nil, 0.0f, 0, 0, 0, 0);\n\t\t}\n\t}\n\n\teWeaponType weaponType = GetWeapon()->m_eWeaponType;\n\tif (!fightingWithWeapon) {\n\t\tif (!victim->OnGround()) {\n\t\t\tfloat curVictimHealth = victim->m_fHealth;\n\t\t\tif (curVictimHealth > 0.0f\n\t\t\t\t&& (curVictimHealth < 30.0f && oldVictimHealth > 30.0f\n\t\t\t\t\t|| weaponType != WEAPONTYPE_UNARMED && weaponType != WEAPONTYPE_BRASSKNUCKLE && IsPlayer()\n\t\t\t\t\t|| victim->m_pedStats->m_flags & STAT_ONE_HIT_KNOCKDOWN || brassKnucklePunch)) {\n\n\t\t\t\tvictim->SetFall(0, (AnimationId)(direction + ANIM_STD_HIGHIMPACT_FRONT), 0);\n\t\t\t\tif (victim->m_nPedState == PED_FALL)\n\t\t\t\t\tvictim->bIsStanding = false;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (victim->m_nPedState == PED_DIE || !victim->bIsStanding) {\n\t\tdir = victim->GetPosition() - GetPosition();\n\t\tdir.Normalise();\n\t\tdir.z = 1.0f;\n\t\tvictim->bIsStanding = false;\n\n\t\tfloat moveMult;\n\t\tif (fightingWithWeapon) {\n\t\t\tmoveMult = Min(damageMult * 0.02f, 1.0f);\n\t\t} else if (m_curFightMove == FIGHTMOVE_GROUNDKICK) {\n\t\t\tmoveMult = Min(damageMult * 0.6f, 4.0f);\n\t\t} else {\n\t\t\tif (victim->m_nPedState != PED_DIE || damageMult >= 20) {\n\t\t\t\tmoveMult = damageMult;\n\t\t\t} else {\n\t\t\t\tmoveMult = Min(damageMult * 2.0f, 14.0f);\n\t\t\t}\n\t\t}\n\n\t\tvictim->ApplyMoveForce(moveMult * 0.6 * dir);\n\t}\n\n\tif (weaponType != WEAPONTYPE_KNIFE && weaponType != WEAPONTYPE_MACHETE\n\t\t&& weaponType != WEAPONTYPE_KATANA && weaponType != WEAPONTYPE_CHAINSAW) {\n\n\t\tif (victim->m_nPedType == PEDTYPE_COP)\n\t\t\tCEventList::RegisterEvent(EVENT_ASSAULT_POLICE, EVENT_ENTITY_PED, victim, this, 2000);\n\t\telse\n\t\t\tCEventList::RegisterEvent(EVENT_ASSAULT, EVENT_ENTITY_PED, victim, this, 2000);\n\t} else {\n\t\tif (victim->m_nPedType == PEDTYPE_COP)\n\t\t\tCEventList::RegisterEvent(EVENT_ASSAULT_NASTYWEAPON_POLICE, EVENT_ENTITY_PED, victim, this, 2000);\n\t\telse\n\t\t\tCEventList::RegisterEvent(EVENT_ASSAULT_NASTYWEAPON, EVENT_ENTITY_PED, victim, this, 2000);\n\t}\n}\n\nvoid\nCPed::FinishFightMoveCB(CAnimBlendAssociation *animAssoc, void *arg)\n{\n\tCPed *ped = (CPed*)arg;\n\n\tif (tFightMoves[ped->m_curFightMove].animId == animAssoc->animId) {\n\t\tped->m_fightState = FIGHTSTATE_MOVE_FINISHED;\n\t\tanimAssoc->blendDelta = -1000.0f;\n\t}\n}\n\nvoid\nCPed::LoadFightData(void)\n{\n\tfloat startFireTime, endFireTime, comboFollowOnTime, strikeRadius, extendReachMultiplier;\n\tint damage, flags;\n\tchar line[256], moveName[32], animName[32], hitLevel;\n\tint moveId = 0;\n\n\tCAnimBlendAssociation *animAssoc;\n\n\tsize_t bp, buflen;\n\tint lp, linelen;\n\n\tbuflen = CFileMgr::LoadFile(\"DATA\\\\fistfite.dat\", work_buff, sizeof(work_buff), \"r\");\n\n\tfor (bp = 0; bp < buflen; ) {\n\t\t// read file line by line\n\t\tfor (linelen = 0; work_buff[bp] != '\\n' && bp < buflen; bp++) {\n\t\t\tline[linelen++] = work_buff[bp];\n\t\t}\n\t\tbp++;\n\t\tline[linelen] = '\\0';\n\n\t\t// skip white space\n\t\tfor (lp = 0; line[lp] <= ' ' && line[lp] != '\\0'; lp++);\n\n\t\tif (line[lp] == '\\0' ||\n\t\t\tline[lp] == '#')\n\t\t\tcontinue;\n\n\t\tsscanf(\n\t\t\t&line[lp],\n\t\t\t\"%s %f %f %f %f %f %c %s %d %d\",\n\t\t\tmoveName,\n\t\t\t&startFireTime,\n\t\t\t&endFireTime,\n\t\t\t&comboFollowOnTime,\n\t\t\t&strikeRadius,\n\t\t\t&extendReachMultiplier,\n\t\t\t&hitLevel,\n\t\t\tanimName,\n\t\t\t&damage,\n\t\t\t&flags);\n\n\t\tif (strncmp(moveName, \"ENDWEAPONDATA\", 13) == 0)\n\t\t\treturn;\n\n\t\ttFightMoves[moveId].startFireTime = startFireTime / 30.0f;\n\t\ttFightMoves[moveId].endFireTime = endFireTime / 30.0f;\n\t\ttFightMoves[moveId].comboFollowOnTime = comboFollowOnTime / 30.0f;\n\t\ttFightMoves[moveId].strikeRadius = strikeRadius;\n\t\ttFightMoves[moveId].extendReachMultiplier = extendReachMultiplier;\n\t\ttFightMoves[moveId].damage = damage;\n\t\ttFightMoves[moveId].flags = flags;\n\n\t\tswitch (hitLevel) {\n\t\t\tcase 'G':\n\t\t\t\ttFightMoves[moveId].hitLevel = HITLEVEL_GROUND;\n\t\t\t\tbreak;\n\t\t\tcase 'H':\n\t\t\t\ttFightMoves[moveId].hitLevel = HITLEVEL_HIGH;\n\t\t\t\tbreak;\n\t\t\tcase 'L':\n\t\t\t\ttFightMoves[moveId].hitLevel = HITLEVEL_LOW;\n\t\t\t\tbreak;\n\t\t\tcase 'M':\n\t\t\t\ttFightMoves[moveId].hitLevel = HITLEVEL_MEDIUM;\n\t\t\t\tbreak;\n\t\t\tcase 'N':\n\t\t\t\ttFightMoves[moveId].hitLevel = HITLEVEL_NULL;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\n\t\tif (strcmp(animName, \"default\") != 0) {\n\t\t\tif (strcmp(animName, \"null\") != 0) {\n\t\t\t\tanimAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_STD, animName);\n\t\t\t\ttFightMoves[moveId].animId = (AnimationId)animAssoc->animId;\n\t\t\t} else {\n\t\t\t\ttFightMoves[moveId].animId = ANIM_STD_WALK;\n\t\t\t}\n\t\t}\n\t\tmoveId++;\n\t}\n}\n\nvoid\nCPed::SetInvestigateEvent(eEventType event, CVector2D pos, float distanceToCountDone, uint16 time, float angle)\n{\n\tif (!IsPedInControl() || CharCreatedBy == MISSION_CHAR)\n\t\treturn;\n\n\tSetStoredState();\n\tbFindNewNodeAfterStateRestore = false;\n\tSetPedState(PED_INVESTIGATE);\n\tm_chatTimer = CTimer::GetTimeInMilliseconds() + time;\n\tm_eventType = event;\n\tm_eventOrThreat = pos;\n\tm_distanceToCountSeekDone = distanceToCountDone;\n\tm_fAngleToEvent = angle;\n\n\tif (m_eventType >= EVENT_ICECREAM)\n\t\tm_lookTimer = 0;\n\telse\n\t\tCAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_HANDSCOWER, 4.0f);\n\n}\n\nvoid\nCPed::InvestigateEvent(void)\n{\n\tCAnimBlendAssociation *animAssoc;\n\tAnimationId animToPlay;\n\tAssocGroupId animGroup;\n\n\tif (m_nWaitState == WAITSTATE_TURN180)\n\t\treturn;\n\n\tif (CTimer::GetTimeInMilliseconds() > m_chatTimer) {\n\n\t\tif (m_chatTimer) {\n\t\t\tif (m_eventType < EVENT_UNK)\n\t\t\t\tSetWaitState(WAITSTATE_TURN180, nil);\n\n\t\t\tm_chatTimer = 0;\n\t\t} else {\n\t\t\tClearInvestigateEvent();\n\t\t}\n\t\treturn;\n\t}\n\n\tCVector2D vecDist = m_eventOrThreat - GetPosition();\n\tfloat distSqr = vecDist.MagnitudeSqr();\n\tif (sq(m_distanceToCountSeekDone) >= distSqr) {\n\n\t\tm_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(vecDist.x, vecDist.y, 0.0f, 0.0f);\n\t\tSetMoveState(PEDMOVE_STILL);\n\n\t\tswitch (m_eventType) {\n\t\t\tcase EVENT_DEAD_PED:\n\t\t\tcase EVENT_HIT_AND_RUN:\n\t\t\tcase EVENT_HIT_AND_RUN_COP:\n\n\t\t\t\tif (CTimer::GetTimeInMilliseconds() > m_lookTimer) {\n\t\t\t\t\tanimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_ROADCROSS);\n\n\t\t\t\t\tif (animAssoc) {\n\t\t\t\t\t\tanimAssoc->blendDelta = -8.0f;\n\t\t\t\t\t\tanimAssoc->flags |= ASSOC_DELETEFADEDOUT;\n\t\t\t\t\t\tif (m_pEventEntity)\n\t\t\t\t\t\t\tSetLookFlag(m_pEventEntity, true);\n\n\t\t\t\t\t\tSetLookTimer(CGeneral::GetRandomNumberInRange(1500, 4000));\n\n\t\t\t\t\t} else if (CGeneral::GetRandomNumber() & 3) {\n\t\t\t\t\t\tClearLookFlag();\n\t\t\t\t\t\tCAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_ROADCROSS, 4.0f);\n\n\t\t\t\t\t\tSetLookTimer(CGeneral::GetRandomNumberInRange(1000, 2500));\n\t\t\t\t\t\tSay(SOUND_PED_CHAT_EVENT);\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tClearInvestigateEvent();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase EVENT_FIRE:\n\t\t\tcase EVENT_EXPLOSION:\n\n\t\t\t\tif (bHasACamera && CTimer::GetTimeInMilliseconds() > m_lookTimer) {\n\t\t\t\t\tanimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_IDLE_CAM);\n\t\t\t\t\tif (!animAssoc)\n\t\t\t\t\t\tanimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_IDLE);\n\n\t\t\t\t\tif (animAssoc && animAssoc->animId == ANIM_STD_IDLE_CAM) {\n\t\t\t\t\t\tCAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_STD_IDLE, 4.0f);\n\t\t\t\t\t\tSetLookTimer(CGeneral::GetRandomNumberInRange(1000, 2500));\n\n\t\t\t\t\t} else if (CGeneral::GetRandomNumber() & 3) {\n\t\t\t\t\t\tCAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_IDLE_CAM, 4.0f);\n\t\t\t\t\t\tSetLookTimer(CGeneral::GetRandomNumberInRange(2500, 5000));\n\t\t\t\t\t\tif (!CGame::germanGame)\n\t\t\t\t\t\t\tSay(SOUND_PED_CHAT_EVENT);\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tm_chatTimer = 0;\n\t\t\t\t\t}\n\n\t\t\t\t} else if (CTimer::GetTimeInMilliseconds() > m_lookTimer) {\n\t\t\t\t\tanimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_IDLE);\n\t\t\t\t\tif (!animAssoc)\n\t\t\t\t\t\tanimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_IDLE_HBHB);\n\n\t\t\t\t\tif (!animAssoc)\n\t\t\t\t\t\tanimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_XPRESS_SCRATCH);\n\n\t\t\t\t\tif (animAssoc && animAssoc->animId == ANIM_STD_IDLE) {\n\t\t\t\t\t\tif (CGeneral::GetRandomNumber() & 1)\n\t\t\t\t\t\t\tanimToPlay = ANIM_STD_IDLE_HBHB;\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tanimToPlay = ANIM_STD_XPRESS_SCRATCH;\n\n\t\t\t\t\t\tCAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, animToPlay, 4.0f);\n\t\t\t\t\t\tSetLookTimer(CGeneral::GetRandomNumberInRange(1500, 4000));\n\n\t\t\t\t\t} else if (animAssoc && animAssoc->animId == ANIM_STD_IDLE_HBHB) {\n\t\t\t\t\t\tanimAssoc->blendDelta = -8.0f;\n\t\t\t\t\t\tanimAssoc->flags |= ASSOC_DELETEFADEDOUT;\n\t\t\t\t\t\tif (CGeneral::GetRandomNumber() & 1) {\n\t\t\t\t\t\t\tanimToPlay = ANIM_STD_IDLE;\n\t\t\t\t\t\t\tanimGroup = m_animGroup;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tanimToPlay = ANIM_STD_XPRESS_SCRATCH;\n\t\t\t\t\t\t\tanimGroup = ASSOCGRP_STD;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tCAnimManager::BlendAnimation(GetClump(), animGroup, animToPlay, 4.0f);\n\t\t\t\t\t\tSetLookTimer(CGeneral::GetRandomNumberInRange(1000, 2500));\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (CGeneral::GetRandomNumber() & 1) {\n\t\t\t\t\t\t\tanimToPlay = ANIM_STD_IDLE;\n\t\t\t\t\t\t\tanimGroup = m_animGroup;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tanimToPlay = ANIM_STD_IDLE_HBHB;\n\t\t\t\t\t\t\tanimGroup = ASSOCGRP_STD;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tCAnimManager::BlendAnimation(GetClump(), animGroup, animToPlay, 4.0f);\n\t\t\t\t\t\tSetLookTimer(CGeneral::GetRandomNumberInRange(1000, 2500));\n\t\t\t\t\t}\n\t\t\t\t\tif (!CGame::germanGame)\n\t\t\t\t\t\tSay(SOUND_PED_CHAT_EVENT);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase EVENT_ICECREAM:\n\t\t\tcase EVENT_SHOPSTALL:\n\n\t\t\t\tm_fRotationDest = m_fAngleToEvent;\n\t\t\t\tif (CTimer::GetTimeInMilliseconds() > m_lookTimer) {\n\n\t\t\t\t\tif (m_lookTimer) {\n\t\t\t\t\t\tanimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_ROADCROSS);\n\n\t\t\t\t\t\tif (animAssoc) {\n\t\t\t\t\t\t\tanimAssoc->blendDelta = -8.0f;\n\t\t\t\t\t\t\tanimAssoc->flags |= ASSOC_DELETEFADEDOUT;\n\t\t\t\t\t\t\tif (m_eventType == EVENT_ICECREAM)\n\t\t\t\t\t\t\t\tanimToPlay = ANIM_STD_CHAT;\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\tanimToPlay = ANIM_STD_XPRESS_SCRATCH;\n\t\t\t\t\t\t\tCAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, animToPlay,4.0f);\n\t\t\t\t\t\t\tSetLookTimer(CGeneral::GetRandomNumberInRange(2000, 5000));\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tanimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_CHAT);\n\t\t\t\t\t\t\tif (animAssoc) {\n\t\t\t\t\t\t\t\tanimAssoc->blendDelta = -8.0f;\n\t\t\t\t\t\t\t\tanimAssoc->flags |= ASSOC_DELETEFADEDOUT;\n\t\t\t\t\t\t\t\tClearInvestigateEvent();\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tanimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_XPRESS_SCRATCH);\n\t\t\t\t\t\t\t\tif (animAssoc) {\n\t\t\t\t\t\t\t\t\tanimAssoc->blendDelta = -8.0f;\n\t\t\t\t\t\t\t\t\tanimAssoc->flags |= ASSOC_DELETEFADEDOUT;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tClearInvestigateEvent();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tCAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_ROADCROSS, 4.0f);\n\t\t\t\t\t\tSetLookTimer(CGeneral::GetRandomNumberInRange(1000, 2500));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\treturn;\n\t\t}\n\t} else {\n\t\tm_vecSeekPos.x = m_eventOrThreat.x;\n\t\tm_vecSeekPos.y = m_eventOrThreat.y;\n\t\tm_vecSeekPos.z = GetPosition().z;\n\t\tSeek();\n\n\t\tif (m_eventType < EVENT_ICECREAM) {\n\t\t\tif (sq(5.0f + m_distanceToCountSeekDone) < distSqr) {\n\t\t\t\tSetMoveState(PEDMOVE_RUN);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\tif (m_eventType <= EVENT_EXPLOSION || m_eventType >= EVENT_SHOPSTALL) {\n\t\t\tSetMoveState(PEDMOVE_WALK);\n\t\t\treturn;\n\t\t}\n\t\tif (distSqr > sq(1.2f)) {\n\t\t\tSetMoveState(PEDMOVE_WALK);\n\t\t\treturn;\n\t\t}\n\n\t\tbool willStandStill = false;\n\t\tfor (int i = 0; i < m_numNearPeds; i++) {\n\t\t\tif ((m_eventOrThreat - m_nearPeds[i]->GetPosition()).MagnitudeSqr() < sq(0.4f)) {\n\t\t\t\tSetMoveState(PEDMOVE_STILL);\n\t\t\t\twillStandStill = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif (!willStandStill)\n\t\t\tSetMoveState(PEDMOVE_WALK);\n\t}\n}\n\nvoid\nCPed::ClearInvestigateEvent(void)\n{\n\tCAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_ROADCROSS);\n\tif (!animAssoc)\n\t\tanimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_XPRESS_SCRATCH);\n\tif (!animAssoc)\n\t\tanimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_IDLE_HBHB);\n\tif (!animAssoc)\n\t\tanimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_CHAT);\n\tif (animAssoc) {\n\t\tanimAssoc->blendDelta = -8.0f;\n\t\tanimAssoc->flags |= ASSOC_DELETEFADEDOUT;\n\t}\n\tif (m_eventType > EVENT_EXPLOSION)\n\t\tm_chatTimer = CTimer::GetTimeInMilliseconds() + 15000;\n\n\tbGonnaInvestigateEvent = false;\n\tm_pEventEntity = nil;\n\tClearLookFlag();\n\tRestorePreviousState();\n\tif(m_nMoveState == PEDMOVE_NONE || m_nMoveState == PEDMOVE_STILL)\n\t\tSetMoveState(PEDMOVE_WALK);\n}\n\nbool\nCPed::InflictDamage(CEntity *damagedBy, eWeaponType method, float damage, ePedPieceTypes pedPiece, uint8 direction)\n{\n\tCPlayerPed *player = FindPlayerPed();\n\tfloat dieDelta = 4.0f;\n\tfloat dieSpeed = 0.0f;\n\tAnimationId dieAnim = ANIM_STD_KO_FRONT;\n\tbool headShot = false;\n\tbool willLinger = false;\n\tint random;\n\n\tif (damagedBy == FindPlayerPed() && damagedBy != this && damage > 3.0f)\n\t\t++CWorld::Players[CWorld::PlayerInFocus].m_nHavocLevel;\n\n\tif (player == this) {\n\t\tif (!player->m_bCanBeDamaged)\n\t\t\treturn false;\n\n\t\tif (damagedBy && damagedBy->IsPed() && ((CPed*)damagedBy)->m_nPedType == PEDTYPE_GANG7)\n\t\t\treturn false;\n\n\t\tif ((method == WEAPONTYPE_FLAMETHROWER || method == WEAPONTYPE_MOLOTOV) && CWorld::Players[CWorld::PlayerInFocus].m_bFireproof)\n\t\t\treturn false;\n\n\t\tplayer->AnnoyPlayerPed(false);\n\t}\n\n\tif (DyingOrDead())\n\t\treturn false;\n\n\tif (method == WEAPONTYPE_DROWNING && !bDrownsInWater)\n\t\treturn false;\n\n\tif (!bUsesCollision && (!bInVehicle || m_nPedState != PED_DRIVING) && method != WEAPONTYPE_DROWNING)\n\t\treturn false;\n\n\tif (bOnlyDamagedByPlayer && damagedBy != player && damagedBy != FindPlayerVehicle() &&\n\t\tmethod != WEAPONTYPE_DROWNING && method != WEAPONTYPE_EXPLOSION)\n\t\treturn false;\n\n\tfloat healthImpact;\n\tif (IsPlayer())\n\t\thealthImpact = damage * 0.33f;\n\telse\n\t\thealthImpact = damage * m_pedStats->m_defendWeakness;\n\n\tif (!IsPlayer() &&\n\t\t(method == WEAPONTYPE_SCREWDRIVER || method == WEAPONTYPE_KNIFE || (method >= WEAPONTYPE_CLEAVER && method <= WEAPONTYPE_CHAINSAW)))\n\t\tm_bleedCounter = 200;\n\n\tbool detectDieAnim = true;\n\tif (m_nPedState == PED_GETUP) {\n\t\tif (!IsPedHeadAbovePos(-0.3f)) {\n\t\t\tif (RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_FRONTAL))\n\t\t\t\tdieAnim = ANIM_STD_HIT_FLOOR_FRONT;\n\t\t\telse\n\t\t\t\tdieAnim = ANIM_STD_HIT_FLOOR;\n\t\t\tdieDelta *= 2.0f;\n\t\t\tdieSpeed = 0.5f;\n\t\t\tdetectDieAnim = false;\n\t\t}\n\t} else if (m_nPedState == PED_FALL) {\n\t\tCAnimBlendAssociation *fallAssoc = RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_PARTIAL);\n\t\tif (!fallAssoc || fallAssoc->IsRunning()) {\n\t\t\tif (fallAssoc && fallAssoc->blendDelta >= 0.0f)\n\t\t\t\tdieAnim = ANIM_STD_NUM;\n\t\t\telse\n\t\t\t\tdieAnim = ANIM_STD_KO_FRONT;\n\t\t} else {\n\t\t\tif (fallAssoc->flags & ASSOC_FRONTAL)\n\t\t\t\tdieAnim = ANIM_STD_HIT_FLOOR_FRONT;\n\t\t\telse\n\t\t\t\tdieAnim = ANIM_STD_HIT_FLOOR;\n\n\t\t\tdieDelta *= 2.0f;\n\t\t\tdieSpeed = 0.5f;\n\t\t}\n\t\tdetectDieAnim = false;\n\t}\n\n\tif (detectDieAnim) {\n\t\tswitch (method) {\n\t\t\tcase WEAPONTYPE_UNARMED:\n\t\t\tcase WEAPONTYPE_BRASSKNUCKLE:\n\t\t\t\tif (bMeleeProof)\n\t\t\t\t\treturn false;\n\n\t\t\t\tif (m_nPedState == PED_FALL) {\n\t\t\t\t\tif (IsPedHeadAbovePos(-0.3f)) {\n\t\t\t\t\t\tdieAnim = ANIM_STD_NUM;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_FRONTAL))\n\t\t\t\t\t\t\tdieAnim = ANIM_STD_HIT_FLOOR_FRONT;\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tdieAnim = ANIM_STD_HIT_FLOOR;\n\t\t\t\t\t\tdieDelta = dieDelta * 2.0f;\n\t\t\t\t\t\tdieSpeed = 0.5f;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tswitch (direction) {\n\t\t\t\t\t\tcase 0:\n\t\t\t\t\t\t\tdieAnim = ANIM_STD_HIGHIMPACT_FRONT;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 1:\n\t\t\t\t\t\t\tdieAnim = ANIM_STD_HIGHIMPACT_LEFT;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 2:\n\t\t\t\t\t\t\tdieAnim = ANIM_STD_HIGHIMPACT_BACK;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 3:\n\t\t\t\t\t\t\tdieAnim = ANIM_STD_HIGHIMPACT_RIGHT;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase WEAPONTYPE_SCREWDRIVER:\n\t\t\tcase WEAPONTYPE_GOLFCLUB:\n\t\t\tcase WEAPONTYPE_NIGHTSTICK:\n\t\t\tcase WEAPONTYPE_KNIFE:\n\t\t\tcase WEAPONTYPE_BASEBALLBAT:\n\t\t\tcase WEAPONTYPE_HAMMER:\n\t\t\tcase WEAPONTYPE_CLEAVER:\n\t\t\tcase WEAPONTYPE_MACHETE:\n\t\t\tcase WEAPONTYPE_KATANA:\n\t\t\tcase WEAPONTYPE_CHAINSAW:\n\t\t\t\tif (bMeleeProof)\n\t\t\t\t\treturn false;\n\n\t\t\t\tif (method != WEAPONTYPE_KATANA ||\n\t\t\t\t\tdamagedBy != FindPlayerPed()\n\t\t\t\t\t|| FindPlayerPed()->m_nPedState != PED_FIGHT\n\t\t\t\t\t|| FindPlayerPed()->m_curFightMove != FIGHTMOVE_MELEE1 && FindPlayerPed()->m_curFightMove != FIGHTMOVE_MELEE2\n\t\t\t\t\t|| CGeneral::GetRandomNumber() & 3) {\n\n\t\t\t\t\tif (m_nPedState == PED_FALL) {\n\t\t\t\t\t\tif (IsPedHeadAbovePos(-0.3f)) {\n\t\t\t\t\t\t\tdieAnim = ANIM_STD_NUM;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_FRONTAL))\n\t\t\t\t\t\t\t\tdieAnim = ANIM_STD_HIT_FLOOR_FRONT;\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\tdieAnim = ANIM_STD_HIT_FLOOR;\n\t\t\t\t\t\t\tdieDelta = dieDelta * 2.0f;\n\t\t\t\t\t\t\tdieSpeed = 0.5f;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (damagedBy != FindPlayerPed() || FindPlayerPed()->m_curFightMove != FIGHTMOVE_MELEE2) {\n\t\t\t\t\t\tif (damagedBy != FindPlayerPed() || FindPlayerPed()->m_curFightMove != FIGHTMOVE_MELEE3) {\n\t\t\t\t\t\t\tswitch (direction) {\n\t\t\t\t\t\t\t\tcase 0:\n\t\t\t\t\t\t\t\t\tdieAnim = ANIM_STD_HIGHIMPACT_FRONT;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase 1:\n\t\t\t\t\t\t\t\t\tdieAnim = ANIM_STD_HIGHIMPACT_LEFT;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase 2:\n\t\t\t\t\t\t\t\t\tdieAnim = ANIM_STD_HIGHIMPACT_BACK;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase 3:\n\t\t\t\t\t\t\t\t\tdieAnim = ANIM_STD_HIGHIMPACT_RIGHT;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tdieAnim = ANIM_STD_KO_SHOT_STOMACH;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tdieAnim = ANIM_STD_KO_SHOT_FACE;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tdieAnim = ANIM_STD_KO_SHOT_FACE;\n\t\t\t\t\tRemoveBodyPart(PED_HEAD, direction);\n\t\t\t\t\theadShot = true;\n\t\t\t\t\twillLinger = true;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase WEAPONTYPE_COLT45:\n\t\t\tcase WEAPONTYPE_SHOTGUN:\n\t\t\tcase WEAPONTYPE_STUBBY_SHOTGUN:\n\t\t\tcase WEAPONTYPE_SPAS12_SHOTGUN:\n\t\t\tcase WEAPONTYPE_TEC9:\n\t\t\tcase WEAPONTYPE_UZI:\n\t\t\tcase WEAPONTYPE_SILENCED_INGRAM:\n\t\t\tcase WEAPONTYPE_MP5:\n\t\t\tcase WEAPONTYPE_M4:\n\t\t\tcase WEAPONTYPE_RUGER:\n\t\t\tcase WEAPONTYPE_SNIPERRIFLE:\n\t\t\tcase WEAPONTYPE_LASERSCOPE:\n\t\t\tcase WEAPONTYPE_M60:\n\t\t\tcase WEAPONTYPE_MINIGUN:\n\t\t\tcase WEAPONTYPE_UZI_DRIVEBY:\n\n\t\t\t\tif (bBulletProof)\n\t\t\t\t\treturn false;\n\n\t\t\t\tbool dontRemoveLimb;\n\t\t\t\tif (IsPlayer() || bNoCriticalHits)\n\t\t\t\t\tdontRemoveLimb = true;\n\t\t\t\telse if (method != WEAPONTYPE_M4 && method != WEAPONTYPE_RUGER && method != WEAPONTYPE_SNIPERRIFLE &&\n\t\t\t\t\t\tmethod != WEAPONTYPE_LASERSCOPE) {\n\t\t\t\t\tif (method == WEAPONTYPE_SHOTGUN)\n\t\t\t\t\t\tdontRemoveLimb = CGeneral::GetRandomNumber() & 7;\n\t\t\t\t\telse\n\t\t\t\t\t\tdontRemoveLimb = CGeneral::GetRandomNumber() & 15;\n\t\t\t\t} else\n\t\t\t\t\tdontRemoveLimb = false;\n\n\t\t\t\tif (dontRemoveLimb) {\n\t\t\t\t\tif (method == WEAPONTYPE_SHOTGUN) {\n\t\t\t\t\t\tswitch (direction) {\n\t\t\t\t\t\t\tcase 0:\n\t\t\t\t\t\t\t\tdieAnim = ANIM_STD_HIGHIMPACT_FRONT;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase 1:\n\t\t\t\t\t\t\t\tdieAnim = ANIM_STD_HIGHIMPACT_LEFT;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase 2:\n\t\t\t\t\t\t\t\tdieAnim = ANIM_STD_HIGHIMPACT_BACK;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase 3:\n\t\t\t\t\t\t\t\tdieAnim = ANIM_STD_HIGHIMPACT_RIGHT;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else\n\t\t\t\t\t\tdieAnim = ANIM_STD_KO_FRONT;\n\n\t\t\t\t\twillLinger = false;\n\t\t\t\t} else {\n\t\t\t\t\tswitch (pedPiece) {\n\t\t\t\t\t\tcase PEDPIECE_TORSO:\n\t\t\t\t\t\t\twillLinger = false;\n\t\t\t\t\t\t\tdieAnim = ANIM_STD_KO_FRONT;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase PEDPIECE_MID:\n\t\t\t\t\t\t\twillLinger = false;\n\t\t\t\t\t\t\tdieAnim = ANIM_STD_KO_SHOT_STOMACH;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase PEDPIECE_LEFTARM:\n\t\t\t\t\t\t\tdieAnim = ANIM_STD_KO_SHOT_ARM_L;\n\t\t\t\t\t\t\tRemoveBodyPart(PED_UPPERARML, direction);\n\t\t\t\t\t\t\twillLinger = true;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase PEDPIECE_RIGHTARM:\n\t\t\t\t\t\t\tdieAnim = ANIM_STD_KO_SHOT_ARM_R;\n\t\t\t\t\t\t\tRemoveBodyPart(PED_UPPERARMR, direction);\n\t\t\t\t\t\t\twillLinger = true;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase PEDPIECE_LEFTLEG:\n\t\t\t\t\t\t\tdieAnim = ANIM_STD_KO_SHOT_LEG_L;\n\t\t\t\t\t\t\tRemoveBodyPart(PED_UPPERLEGL, direction);\n\t\t\t\t\t\t\twillLinger = true;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase PEDPIECE_RIGHTLEG:\n\t\t\t\t\t\t\tdieAnim = ANIM_STD_KO_SHOT_LEG_R;\n\t\t\t\t\t\t\tRemoveBodyPart(PED_UPPERLEGR, direction);\n\t\t\t\t\t\t\twillLinger = true;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase PEDPIECE_HEAD:\n\t\t\t\t\t\t\tdieAnim = ANIM_STD_KO_SHOT_FACE;\n\t\t\t\t\t\t\tRemoveBodyPart(PED_HEAD, direction);\n\t\t\t\t\t\t\theadShot = true;\n\t\t\t\t\t\t\twillLinger = true;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase WEAPONTYPE_GRENADE:\n\t\t\tcase WEAPONTYPE_ROCKETLAUNCHER:\n\t\t\tcase WEAPONTYPE_EXPLOSION:\n\t\t\t\tif (bExplosionProof)\n\t\t\t\t\treturn false;\n\n\t\t\t\tif (CGame::nastyGame && !IsPlayer() && !bInVehicle &&\n\t\t\t\t\t1.0f + healthImpact > m_fArmour + m_fHealth) {\n\n\t\t\t\t\trandom = CGeneral::GetRandomNumber();\n\t\t\t\t\tif (random & 1)\n\t\t\t\t\t\tRemoveBodyPart(PED_UPPERARML, direction);\n\t\t\t\t\tif (random & 2)\n\t\t\t\t\t\tRemoveBodyPart(PED_UPPERLEGR, direction);\n\t\t\t\t\tif (random & 4)\n\t\t\t\t\t\tRemoveBodyPart(PED_HEAD, direction);\n\t\t\t\t\tif (random & 8)\n\t\t\t\t\t\tRemoveBodyPart(PED_UPPERARMR, direction);\n\t\t\t\t\tif (random & 0x10)\n\t\t\t\t\t\tRemoveBodyPart(PED_UPPERLEGL, direction);\n\t\t\t\t\tif (bBodyPartJustCameOff)\n\t\t\t\t\t\twillLinger = true;\n\t\t\t\t}\n\t\t\t\t// fall through\n\t\t\tcase WEAPONTYPE_MOLOTOV:\n\t\t\t\tif (bExplosionProof)\n\t\t\t\t\treturn false;\n\n\t\t\t\tswitch (direction) {\n\t\t\t\t\tcase 0:\n\t\t\t\t\t\tdieAnim = ANIM_STD_HIGHIMPACT_FRONT;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 1:\n\t\t\t\t\t\tdieAnim = ANIM_STD_HIGHIMPACT_LEFT;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 2:\n\t\t\t\t\t\tdieAnim = ANIM_STD_HIGHIMPACT_BACK;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 3:\n\t\t\t\t\t\tdieAnim = ANIM_STD_HIGHIMPACT_RIGHT;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase WEAPONTYPE_FLAMETHROWER:\n\t\t\t\tif (bFireProof)\n\t\t\t\t\treturn false;\n\n\t\t\t\tdieAnim = ANIM_STD_KO_FRONT;\n\t\t\t\tbreak;\n\t\t\tcase WEAPONTYPE_RAMMEDBYCAR:\n\t\t\tcase WEAPONTYPE_RUNOVERBYCAR:\n\t\t\t\tif (bCollisionProof)\n\t\t\t\t\treturn false;\n\n\t\t\t\trandom = CGeneral::GetRandomNumber() & 3;\n\t\t\t\tswitch (random) {\n\t\t\t\t\tcase 0:\n\t\t\t\t\t\tif ((pedPiece != PEDPIECE_LEFTARM || random <= 1)\n\t\t\t\t\t\t\t&& (pedPiece != PEDPIECE_MID || random != 1)) {\n\t\t\t\t\t\t\tif (pedPiece == PEDPIECE_RIGHTARM && random > 1\n\t\t\t\t\t\t\t\t|| pedPiece == PEDPIECE_MID && random == 2)\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\tdieAnim = ANIM_STD_HIGHIMPACT_RIGHT;\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\tdieAnim = ANIM_STD_HIGHIMPACT_FRONT;\n\t\t\t\t\t\t} else\n\t\t\t\t\t\t\tdieAnim = ANIM_STD_HIGHIMPACT_LEFT;\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 1:\n\t\t\t\t\t\tif (m_nPedState == PED_DIVE_AWAY)\n\t\t\t\t\t\t\tdieAnim = ANIM_STD_SPINFORWARD_LEFT;\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tdieAnim = ANIM_STD_HIGHIMPACT_LEFT;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 2:\n\t\t\t\t\t\tif ((pedPiece != PEDPIECE_LEFTARM || random <= 1)\n\t\t\t\t\t\t\t&& (pedPiece != PEDPIECE_MID || random != 1)) {\n\t\t\t\t\t\t\tif ((pedPiece != PEDPIECE_RIGHTARM || random <= 1)\n\t\t\t\t\t\t\t\t&& (pedPiece != PEDPIECE_MID || random != 2)) {\n\t\t\t\t\t\t\t\tdieAnim = ANIM_STD_HIGHIMPACT_BACK;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tdieAnim = ANIM_STD_SPINFORWARD_RIGHT;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else\n\t\t\t\t\t\t\tdieAnim = ANIM_STD_SPINFORWARD_LEFT;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 3:\n\t\t\t\t\t\tif (m_nPedState == PED_DIVE_AWAY)\n\t\t\t\t\t\t\tdieAnim = ANIM_STD_SPINFORWARD_RIGHT;\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tdieAnim = ANIM_STD_HIGHIMPACT_RIGHT;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif (damagedBy && pedPiece != PEDPIECE_TORSO) {\n\t\t\t\t\tCVehicle *vehicle = (CVehicle*)damagedBy;\n\t\t\t\t\tif (method == WEAPONTYPE_RAMMEDBYCAR) {\n\t\t\t\t\t\tfloat vehSpeed = vehicle->m_vecMoveSpeed.Magnitude();\n\t\t\t\t\t\tdieDelta = 8.0f * vehSpeed + 4.0f;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tfloat vehSpeed = vehicle->m_vecMoveSpeed.Magnitude();\n\t\t\t\t\t\tdieDelta = 12.0f * vehSpeed + 4.0f;\n\t\t\t\t\t\tdieSpeed = 16.0f * vehSpeed + 1.0f;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase WEAPONTYPE_DROWNING:\n\t\t\t\tdieAnim = ANIM_STD_DROWN;\n\t\t\t\tbreak;\n\t\t\tcase WEAPONTYPE_FALL:\n\t\t\t\tif (bCollisionProof)\n\t\t\t\t\treturn false;\n\n\t\t\t\tswitch (direction) {\n\t\t\t\t\tcase 0:\n\t\t\t\t\t\tdieAnim = ANIM_STD_HIGHIMPACT_FRONT;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 1:\n\t\t\t\t\t\tdieAnim = ANIM_STD_HIGHIMPACT_LEFT;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 2:\n\t\t\t\t\t\tdieAnim = ANIM_STD_HIGHIMPACT_BACK;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 3:\n\t\t\t\t\t\tdieAnim = ANIM_STD_HIGHIMPACT_RIGHT;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tif (m_fArmour != 0.0f && method != WEAPONTYPE_DROWNING) {\n\t\tif (player == this)\n\t\t\tCWorld::Players[CWorld::PlayerInFocus].m_nTimeLastArmourLoss = CTimer::GetTimeInMilliseconds();\n\n\t\tif (healthImpact < m_fArmour) {\n\t\t\tm_fArmour = m_fArmour - healthImpact;\n\t\t\thealthImpact = 0.0f;\n\t\t} else {\n\t\t\thealthImpact = healthImpact - m_fArmour;\n\t\t\tm_fArmour = 0.0f;\n\t\t}\n\t}\n\n\tif (healthImpact != 0.0f) {\n\t\tif (player == this)\n\t\t\tCWorld::Players[CWorld::PlayerInFocus].m_nTimeLastHealthLoss = CTimer::GetTimeInMilliseconds();\n\n\t\tm_lastWepDam = method;\n\t\tm_lastDamEntity = damagedBy;\n\t}\n\n\tif (method == WEAPONTYPE_FALL) {\n\t\tif (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_ROLLOUT_LHS)) {\n\t\t\tif (m_fHealth >= 1.0 && m_fHealth - healthImpact < 5.0f) {\n\t\t\t\tm_fHealth = Min(m_fHealth, 5.0f);\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (m_fHealth - healthImpact >= 1.0f && !willLinger) {\n\t\tm_fHealth -= healthImpact;\n\t\treturn false;\n\t}\n\n\tif (bInVehicle) {\n\t\tif (method != WEAPONTYPE_DROWNING) {\n\t\t\tif (m_pMyVehicle) {\n\t\t\t\tCVehicle* pVehicle = m_pMyVehicle;\n\t\t\t\tbool bDone = false;\n\t\t\t\tif (m_pMyVehicle->IsBike()) {\n\t\t\t\t\tm_fHealth = 0.0f;\n\t\t\t\t\t((CBike*)m_pMyVehicle)->KnockOffRider(method, direction, this, false);\n\t\t\t\t\tbDone = true;\n\t\t\t\t} else {\n\t\t\t\t\tif (m_pMyVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_CAR) {\n\t\t\t\t\t\tif (m_pMyVehicle->pDriver == this) {\n\t\t\t\t\t\t\tif (m_pMyVehicle->GetStatus() == STATUS_SIMPLE) {\n\t\t\t\t\t\t\t\tm_pMyVehicle->SetStatus(STATUS_PHYSICS);\n\t\t\t\t\t\t\t\tCCarCtrl::SwitchVehicleToRealPhysics(m_pMyVehicle);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tm_pMyVehicle->AutoPilot.m_nCarMission = MISSION_NONE;\n\t\t\t\t\t\t\tm_pMyVehicle->AutoPilot.m_nCruiseSpeed = 0;\n\t\t\t\t\t\t\tm_pMyVehicle->AutoPilot.m_nTempAction = TEMPACT_HANDBRAKESTRAIGHT;\n\t\t\t\t\t\t\tm_pMyVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 2000;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (m_pMyVehicle->CanPedExitCar(true)) {\n\t\t\t\t\t\tSetObjective(OBJECTIVE_LEAVE_CAR_AND_DIE, m_pMyVehicle);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tm_fHealth = 0.0f;\n\t\t\t\t\t\tif (m_pMyVehicle && m_pMyVehicle->pDriver == this) {\n\t\t\t\t\t\t\tSetRadioStation();\n\t\t\t\t\t\t\tm_pMyVehicle->SetStatus(STATUS_ABANDONED);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tSetDie(dieAnim, dieDelta, dieSpeed);\n\n\t\t\t\t\t\tif (damagedBy == FindPlayerPed() && damagedBy != this) {\n\t\t\t\t\t\t\tCWorld::Players[CWorld::PlayerInFocus].m_nHavocLevel += 10;\n\t\t\t\t\t\t\tCWorld::Players[CWorld::PlayerInFocus].m_fMediaAttention += 5.f;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tfor (int i = 0; i < ARRAY_SIZE(pVehicle->pPassengers); i++) {\n\t\t\t\t\tCPed* passenger = pVehicle->pPassengers[i];\n\t\t\t\t\tif (passenger && passenger != this && damagedBy)\n\t\t\t\t\t\tpassenger->ReactToAttack(damagedBy);\n\t\t\t\t}\n\n\t\t\t\tCPed *driverOfVeh = pVehicle->pDriver;\n\t\t\t\tif (driverOfVeh && driverOfVeh != this && damagedBy)\n\t\t\t\t\tdriverOfVeh->ReactToAttack(damagedBy);\n\n\t\t\t\tif (damagedBy == FindPlayerPed() || damagedBy && damagedBy == FindPlayerVehicle()) {\n\t\t\t\t\tCDarkel::RegisterKillByPlayer(this, method, headShot);\n\t\t\t\t\tm_threatEntity = FindPlayerPed();\n\t\t\t\t} else {\n\t\t\t\t\tCDarkel::RegisterKillNotByPlayer(this, method);\n\t\t\t\t}\n\t\t\t\tif (bDone)\n\t\t\t\t\treturn true;\n\t\t\t}\n\t\t\tm_fHealth = 1.0f;\n\t\t\treturn false;\n\t\t}\n\t\tm_fHealth = 0.0f;\n\t\tif (player == this)\n\t\t\tm_pMyVehicle->SetStatus(STATUS_PLAYER_DISABLED);\n\n\t\tSetDie(ANIM_STD_NUM, 4.0f, 0.0f);\n\t\treturn true;\n\t} else {\n\t\tm_fHealth = 0.0f;\n\t\tSetDie(dieAnim, dieDelta, dieSpeed);\n\n\t\tif (damagedBy == player || damagedBy && damagedBy == FindPlayerVehicle()) {\n\t\t\tCDarkel::RegisterKillByPlayer(this, method, headShot);\n\t\t\tCWorld::Players[CWorld::PlayerInFocus].m_nHavocLevel += 10;\n\t\t\tCWorld::Players[CWorld::PlayerInFocus].m_fMediaAttention += 5.f;\n\t\t\tm_threatEntity = player;\n\t\t} else {\n\t\t\tCDarkel::RegisterKillNotByPlayer(this, method);\n\t\t}\n\t\tif (method == WEAPONTYPE_DROWNING) {\n\t\t\tbIsInTheAir = false;\n\t\t\tif (FindPlayerPed() == this)\n\t\t\t\tCStats::TimesDrowned++;\n\t\t}\n\n\t\treturn true;\n\t}\n}\n\nstatic RwObject*\nSetPedAtomicVisibilityCB(RwObject* object, void* data)\n{\n\tif (data == nil)\n\t\tRpAtomicSetFlags((RpAtomic*)object, 0);\n\treturn object;\n}\n\nstatic RwFrame*\nRecurseFrameChildrenVisibilityCB(RwFrame* frame, void* data)\n{\n\tRwFrameForAllObjects(frame, SetPedAtomicVisibilityCB, data);\n\tRwFrameForAllChildren(frame, RecurseFrameChildrenVisibilityCB, nil);\n\treturn frame;\n}\n\nstatic RwObject*\nCloneAtomicToFrameCB(RwObject *frame, void *data)\n{\n\tRpAtomic *newAtomic = RpAtomicClone((RpAtomic*)frame);\n\tRpAtomicSetFrame(newAtomic, (RwFrame*)data);\n\tRpClumpAddAtomic(flyingClumpTemp, newAtomic);\n\tCVisibilityPlugins::SetAtomicRenderCallback(newAtomic, nil);\n\treturn frame;\n}\n\nstatic RwFrame*\nRecurseFrameChildrenToCloneCB(RwFrame *frame, void *data)\n{\n\tRwFrame *newFrame = RwFrameCreate();\n\tRwFrameAddChild((RwFrame*)data, newFrame);\n\tRwFrameTransform(newFrame, RwFrameGetMatrix(frame), rwCOMBINEREPLACE);\n\tRwFrameForAllObjects(frame, CloneAtomicToFrameCB, newFrame);\n\tRwFrameForAllChildren(frame, RecurseFrameChildrenToCloneCB, newFrame);\n\treturn newFrame;\n}\n\nvoid\nCPed::RemoveBodyPart(PedNode nodeId, int8 direction)\n{\n\tRwFrame *frame;\n\tCVector pos;\n\n\tframe = m_pFrames[nodeId]->frame;\n\tif (frame) {\n\t\tif (CGame::nastyGame) {\n\t\t\tif (CEntity::GetIsOnScreen()) {\n\t\t\t\tm_pedIK.GetComponentPosition(pos, nodeId);\n\t\t\t\tCParticle::AddParticle(PARTICLE_TEST, pos,\n\t\t\t\t\tCVector(0.0f, 0.0f, 0.0f),\n\t\t\t\t\tnil, 0.1f, 0, 0, 0, 0);\n\n\t\t\t\tfor (int i = 0; i < 16; i++) {\n\t\t\t\t\tCParticle::AddParticle(PARTICLE_BLOOD_SMALL,\n\t\t\t\t\t\tpos,\n\t\t\t\t\t\tCVector(0.0f, 0.0f, 0.03f),\n\t\t\t\t\t\tnil, 0.0f, 0, 0, 0, 0);\n\t\t\t\t}\n\t\t\t}\n\t\t\tbBodyPartJustCameOff = true;\n\t\t\tm_bodyPartBleeding = nodeId;\n\t\t}\n\t} else {\n\t\tprintf(\"Trying to remove ped component\");\n\t}\n}\n\nCObject*\nCPed::SpawnFlyingComponent(int pedNode, int8 direction)\n{\n\t// VC doesn't have detachable limbs :shrug:\n\treturn nil;\n}\n\n// III leftover and unused\nvoid\nCPed::ApplyHeadShot(eWeaponType weaponType, CVector pos, bool evenOnPlayer)\n{\n\tCVector pos2 = CVector(\n\t\tpos.x,\n\t\tpos.y,\n\t\tpos.z + 0.1f\n\t);\n\n\tif (!IsPlayer() || evenOnPlayer) {\n\t\t++CStats::HeadsPopped;\n\n\t\t// BUG: This condition will always return true. Even fixing it won't work, because these states are unused.\n\t\t// if (m_nPedState != PED_PASSENGER || m_nPedState != PED_TAXI_PASSENGER) {\n\t\t\tSetDie();\n\t\t// }\n\n\t\tbBodyPartJustCameOff = true;\n\t\tm_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 150;\n\n\t\tRemoveBodyPart(PED_HEAD, 0);\n\t\tCParticle::AddParticle(PARTICLE_TEST, pos2,\n\t\t\tCVector(0.0f, 0.0f, 0.0f), nil, 0.2f, 0, 0, 0, 0);\n\n\t\tif (CEntity::GetIsOnScreen()) {\n\t\t\tfor(int i=0; i < 32; i++) {\n\t\t\t\tCParticle::AddParticle(PARTICLE_BLOOD_SMALL,\n\t\t\t\t\tpos2, CVector(0.0f, 0.0f, 0.03f),\n\t\t\t\t\tnil, 0.0f, 0, 0, 0, 0);\n\t\t\t}\n\n\t\t\tfor (int i = 0; i < 16; i++) {\n\t\t\t\tCParticle::AddParticle(PARTICLE_DEBRIS2,\n\t\t\t\t\tpos2,\n\t\t\t\t\tCVector(0.0f, 0.0f, 0.01f),\n\t\t\t\t\tnil, 0.0f, 0, 0, 0, 0);\n\t\t\t}\n\t\t}\n\t}\n}\n\nbool\nCPed::IsPedHeadAbovePos(float zOffset)\n{\n\treturn zOffset + GetPosition().z < GetNodePosition(PED_HEAD).z;\n}\n\nbool\nCPed::PlacePedOnDryLand(void)\n{\n\tfloat waterLevel = 0.0f;\n\tCEntity *foundEnt = nil;\n\tCColPoint foundCol;\n\tfloat foundColZ;\n\n\tCWaterLevel::GetWaterLevelNoWaves(GetPosition().x, GetPosition().y, GetPosition().z, &waterLevel);\n\n\tCVector potentialGround = GetPosition();\n\tpotentialGround.z = waterLevel;\n\n\tif (!CWorld::TestSphereAgainstWorld(potentialGround, 5.0f, nil, true, false, false, false, false, false))\n\t\treturn false;\n\n\tCVector potentialGroundDist = gaTempSphereColPoints[0].point - GetPosition();\n\tpotentialGroundDist.z = 0.0f;\n\tpotentialGroundDist.Normalise();\n\n\tCVector posToCheck = 0.5f * potentialGroundDist + gaTempSphereColPoints[0].point;\n\tposToCheck.z = 3.0f + waterLevel;\n\n\tif (CWorld::ProcessVerticalLine(posToCheck, waterLevel - 1.0f, foundCol, foundEnt, true, true, false, true, false, false, nil)) {\n\t\tfoundColZ = foundCol.point.z;\n\t\tif (foundColZ >= waterLevel) {\n\t\t\tposToCheck.z = 0.8f + foundColZ;\n\t\t\tSetPosition(posToCheck);\n\t\t\tbIsStanding = true;\n\t\t\tbWasStanding = true;\n\t\t\treturn true;\n\t\t}\n\t}\n\n\tposToCheck = 5.0f * potentialGroundDist + GetPosition();\n\tposToCheck.z = 3.0f + waterLevel;\n\n\tif (!CWorld::ProcessVerticalLine(posToCheck, waterLevel - 1.0f, foundCol, foundEnt, true, true, false, true, false, false, nil))\n\t\treturn false;\n\n\tfoundColZ = foundCol.point.z;\n\tif (foundColZ < waterLevel)\n\t\treturn false;\n\n\tposToCheck.z = 0.8f + foundColZ;\n\tSetPosition(posToCheck);\n\tbIsStanding = true;\n\tbWasStanding = true;\n\treturn true;\n}\n\nvoid\nCPed::CollideWithPed(CPed *collideWith)\n{\n\tCAnimBlendAssociation *animAssoc;\n\tAnimationId animToPlay;\n\n\tbool weAreMissionChar = CharCreatedBy == MISSION_CHAR;\n\tbool heIsMissionChar = collideWith->CharCreatedBy == MISSION_CHAR;\n\tCVector posDiff = collideWith->GetPosition() - GetPosition();\n\tint waitTime = 0;\n\n\tif (weAreMissionChar || !collideWith->IsPlayer() || collideWith->m_nPedState != PED_MAKE_CALL) {\n\t\tif (m_nWaitState == WAITSTATE_SUN_BATHE_IDLE) {\n\t\t\tSetGetUp();\n\t\t\treturn;\n\t\t}\n\t\tif (collideWith->m_nWaitState == WAITSTATE_SUN_BATHE_IDLE) {\n\t\t\tcollideWith->SetGetUp();\n\t\t\treturn;\n\t\t}\n\n\t\tbool weDontLookToHim = DotProduct(posDiff, GetForward()) > 0.0f;\n\t\tbool heLooksToUs = DotProduct(posDiff, collideWith->GetForward()) < 0.0f;\n\n\t\tif (m_nMoveState != PEDMOVE_NONE && m_nMoveState != PEDMOVE_STILL) {\n\n\t\t\tif ((!IsPlayer() || ((CPlayerPed*)this)->m_fMoveSpeed <= 1.8f)\n\t\t\t\t&& (IsPlayer() || heIsMissionChar && weAreMissionChar || m_nMoveState != PEDMOVE_RUN && m_nMoveState != PEDMOVE_SPRINT\n\t\t\t\t\t|| m_objective == OBJECTIVE_FOLLOW_CHAR_IN_FORMATION && m_pedInObjective == collideWith\n\t\t\t\t\t|| collideWith->m_objective == OBJECTIVE_FOLLOW_CHAR_IN_FORMATION && collideWith->m_pedInObjective == this\t\t\n\t\t\t\t\t)) {\n\n\t\t\t\tif (m_objective != OBJECTIVE_FOLLOW_CHAR_IN_FORMATION && m_objective != OBJECTIVE_GOTO_CHAR_ON_FOOT) {\n\n\t\t\t\t\tif (CTimer::GetTimeInMilliseconds() > m_nPedStateTimer) {\n\n\t\t\t\t\t\tif (heIsMissionChar || !weAreMissionChar && collideWith->m_nMoveState != PEDMOVE_STILL) {\n\n\t\t\t\t\t\t\tif (weAreMissionChar && (m_nPedState == PED_SEEK_POS || m_nPedState == PED_SEEK_ENTITY)) {\n\n\t\t\t\t\t\t\t\tif (collideWith->m_nMoveState != PEDMOVE_STILL\n\t\t\t\t\t\t\t\t\t&& (!collideWith->IsPlayer() || collideWith->IsPlayer() && CPad::GetPad(0)->ArePlayerControlsDisabled())) {\n\t\t\t\t\t\t\t\t\tfloat seekPosDist = (GetPosition() - m_vecSeekPos).MagnitudeSqr2D();\n\t\t\t\t\t\t\t\t\tfloat heAndSeekPosDist = (collideWith->GetPosition() - m_vecSeekPos).MagnitudeSqr2D();\n\n\t\t\t\t\t\t\t\t\tif (seekPosDist <= heAndSeekPosDist) {\n\t\t\t\t\t\t\t\t\t\twaitTime = 1000;\n\t\t\t\t\t\t\t\t\t\tcollideWith->SetWaitState(WAITSTATE_CROSS_ROAD_LOOK, &waitTime);\n\t\t\t\t\t\t\t\t\t\tcollideWith->m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + waitTime;\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\twaitTime = 500;\n\t\t\t\t\t\t\t\t\t\tSetWaitState(WAITSTATE_CROSS_ROAD_LOOK, &waitTime);\n\t\t\t\t\t\t\t\t\t\tm_nPedStateTimer = CTimer::GetTimeInMilliseconds() + waitTime;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} else if (collideWith->m_nMoveState == PEDMOVE_STILL) {\n\t\t\t\t\t\t\t\t\tSetDirectionToWalkAroundObject(collideWith);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tif (FindPlayerPed() != m_pedInObjective\n\t\t\t\t\t\t\t\t\t|| m_objective != OBJECTIVE_KILL_CHAR_ANY_MEANS && m_objective != OBJECTIVE_KILL_CHAR_ON_FOOT\n\t\t\t\t\t\t\t\t\t|| collideWith == m_pedInObjective) {\n\n\t\t\t\t\t\t\t\t\tif (weAreMissionChar || m_pedStats->m_fear <= 100 - collideWith->m_pedStats->m_temper\n\t\t\t\t\t\t\t\t\t\t|| (collideWith->IsPlayer() || collideWith->m_nMoveState == PEDMOVE_NONE || collideWith->m_nMoveState == PEDMOVE_STILL) &&\n\t\t\t\t\t\t\t\t\t\t(!collideWith->IsPlayer() || ((CPlayerPed*)collideWith)->m_fMoveSpeed <= 1.0f)) {\n\t\t\t\t\t\t\t\t\t\tSetDirectionToWalkAroundObject(collideWith);\n\t\t\t\t\t\t\t\t\t\tif (!weAreMissionChar)\n\t\t\t\t\t\t\t\t\t\t\tSay(SOUND_PED_CHAT);\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tSetEvasiveStep(collideWith, 2);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} else if (collideWith->m_nMoveState != PEDMOVE_STILL && GetWeapon()->IsTypeMelee()\n\t\t\t\t\t\t\t\t\t&& collideWith->m_pedInObjective == m_pedInObjective) {\n\n\t\t\t\t\t\t\t\t\tint colliderIndexAtPlayersKillList = -1;\n\t\t\t\t\t\t\t\t\tint ourIndexAtPlayersKillList = -1;\n\t\t\t\t\t\t\t\t\tfor (int i = 0; i < ARRAY_SIZE(((CPlayerPed*)m_pedInObjective)->m_pMeleeList); i++) {\n\t\t\t\t\t\t\t\t\t\tCPed *pedInKillList = ((CPlayerPed*)m_pedInObjective)->m_pMeleeList[i];\n\t\t\t\t\t\t\t\t\t\tif (pedInKillList == this) {\n\t\t\t\t\t\t\t\t\t\t\tourIndexAtPlayersKillList = i;\n\t\t\t\t\t\t\t\t\t\t} else if (pedInKillList == collideWith) {\n\t\t\t\t\t\t\t\t\t\t\tcolliderIndexAtPlayersKillList = i;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tbool weAreCloserToTargetThenCollider = false;\n\t\t\t\t\t\t\t\t\tif ((GetPosition() - m_vecSeekPos).MagnitudeSqr2D() < (collideWith->GetPosition() - m_vecSeekPos).MagnitudeSqr2D())\n\t\t\t\t\t\t\t\t\t\tweAreCloserToTargetThenCollider = true;\n\n\t\t\t\t\t\t\t\t\tif (ourIndexAtPlayersKillList > 0 && !weAreCloserToTargetThenCollider) {\n\t\t\t\t\t\t\t\t\t\tif (colliderIndexAtPlayersKillList > 0) {\n\t\t\t\t\t\t\t\t\t\t\tint time = 300;\n\t\t\t\t\t\t\t\t\t\t\tSetWaitState(WAITSTATE_CROSS_ROAD_LOOK, &time);\n\t\t\t\t\t\t\t\t\t\t\tm_nPedStateTimer = CTimer::GetTimeInMilliseconds() + time;\n\n\t\t\t\t\t\t\t\t\t\t} else if (collideWith->m_pedInObjective == FindPlayerPed()) {\n\t\t\t\t\t\t\t\t\t\t\t((CPlayerPed*)m_pedInObjective)->RemovePedFromMeleeList(this);\n\t\t\t\t\t\t\t\t\t\t\tint time = 500;\n\t\t\t\t\t\t\t\t\t\t\tSetWaitState(WAITSTATE_CROSS_ROAD_LOOK, &time);\n\t\t\t\t\t\t\t\t\t\t\tm_nPedStateTimer = CTimer::GetTimeInMilliseconds() + time;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t} else if (!weAreCloserToTargetThenCollider) {\n\t\t\t\t\t\t\t\t\t\tint time = 300;\n\t\t\t\t\t\t\t\t\t\tSetWaitState(WAITSTATE_CROSS_ROAD_LOOK, &time);\n\t\t\t\t\t\t\t\t\t\tm_nPedStateTimer = CTimer::GetTimeInMilliseconds() + time;\n\t\t\t\t\t\t\t\t\t} \n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tSetDirectionToWalkAroundObject(collideWith);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (m_pedStats->m_temper <= m_pedStats->m_fear\n\t\t\t\t\t\t\t\t|| GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED\n\t\t\t\t\t\t\t\t|| weAreMissionChar\n\t\t\t\t\t\t\t\t|| collideWith->m_nPedType == PEDTYPE_CIVFEMALE\n\t\t\t\t\t\t\t\t|| collideWith->m_nPedType == m_nPedType\n\t\t\t\t\t\t\t\t|| collideWith->GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED) {\n\t\t\t\t\t\t\t\tSetDirectionToWalkAroundObject(collideWith);\n\t\t\t\t\t\t\t\tSay(SOUND_PED_CHAT);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tTurnBody();\n\t\t\t\t\t\t\t\tSetAttack(collideWith);\n\t\t\t\t\t\t\t\tm_fRotationCur = 0.3f + m_fRotationCur;\n\t\t\t\t\t\t\t\tm_fRotationDest = m_fRotationCur;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tm_nPedStateTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(250, 450);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (m_pedInObjective && (collideWith == m_pedInObjective || collideWith->m_pedInObjective == m_pedInObjective) && CTimer::GetTimeInMilliseconds() > m_nPedStateTimer) {\n\t\t\t\t\t\tif (heLooksToUs) {\n\t\t\t\t\t\t\tSetEvasiveStep(collideWith, 1);\n\t\t\t\t\t\t\tm_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 3000;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (weDontLookToHim && IsPedInControl()) {\n\n\t\t\t\t\t\tif (m_pedStats != collideWith->m_pedStats) {\n\n\t\t\t\t\t\t\tif (collideWith->m_pedStats->m_fear <= 100 - m_pedStats->m_temper || collideWith->IsPlayer()\n\t\t\t\t\t\t\t\t|| CTimer::GetTimeInMilliseconds() < m_nPedStateTimer) {\n\n\t\t\t\t\t\t\t\tif (collideWith->IsPlayer()) {\n\t\t\t\t\t\t\t\t\t// He's on our right side\n\t\t\t\t\t\t\t\t\tif (DotProduct(posDiff,GetRight()) <= 0.0f)\n\t\t\t\t\t\t\t\t\t\tm_fRotationCur -= m_headingRate;\n\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t\tm_fRotationCur += m_headingRate;\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t// He's on our right side\n\t\t\t\t\t\t\t\t\tif (DotProduct(posDiff, collideWith->GetRight()) <= 0.0f)\n\t\t\t\t\t\t\t\t\t\tcollideWith->m_fRotationCur -= collideWith->m_headingRate;\n\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t\tcollideWith->m_fRotationCur += collideWith->m_headingRate;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tSetLookFlag(collideWith, false);\n\t\t\t\t\t\t\t\tTurnBody();\n\t\t\t\t\t\t\t\tanimAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_PARTIAL_PUNCH, 8.0f);\n\t\t\t\t\t\t\t\tanimAssoc->flags |= ASSOC_FADEOUTWHENDONE;\n\t\t\t\t\t\t\t\tm_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 2000;\n\t\t\t\t\t\t\t\tif (!heIsMissionChar) {\n\t\t\t\t\t\t\t\t\tCVector2D posDiff2D(posDiff);\n\t\t\t\t\t\t\t\t\tint direction = collideWith->GetLocalDirection(posDiff2D);\n\t\t\t\t\t\t\t\t\tcollideWith->StartFightDefend(direction, HITLEVEL_HIGH, 5);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if (collideWith->m_pedStats->m_defendWeakness <= 1.5f || heIsMissionChar ||\n\t\t\t\tm_pedStats->m_defendWeakness <= collideWith->m_pedStats->m_defendWeakness) {\n\n\t\t\t\t// He looks us and we're not at his right side\n\t\t\t\tif (heLooksToUs && DotProduct(posDiff,collideWith->GetRight()) > 0.0f) {\n\t\t\t\t\tCVector moveForce = GetRight();\n\t\t\t\t\tmoveForce.z += 0.1f;\n\t\t\t\t\tApplyMoveForce(moveForce);\n\t\t\t\t\tif (collideWith->m_nMoveState != PEDMOVE_RUN && collideWith->m_nMoveState != PEDMOVE_SPRINT)\n\t\t\t\t\t\tanimToPlay = ANIM_STD_HIT_LEFT;\n\t\t\t\t\telse\n\t\t\t\t\t\tanimToPlay = ANIM_STD_HITBYGUN_LEFT;\n\t\t\t\t} else if (heLooksToUs) {\n\t\t\t\t\tCVector moveForce = GetRight() * -1.0f;\n\t\t\t\t\tmoveForce.z += 0.1f;\n\t\t\t\t\tApplyMoveForce(moveForce);\n\t\t\t\t\tif (collideWith->m_nMoveState != PEDMOVE_RUN && collideWith->m_nMoveState != PEDMOVE_SPRINT)\n\t\t\t\t\t\tanimToPlay = ANIM_STD_HIT_RIGHT;\n\t\t\t\t\telse\n\t\t\t\t\t\tanimToPlay = ANIM_STD_HITBYGUN_RIGHT;\n\t\t\t\t} else {\n\t\t\t\t\tif (collideWith->m_nMoveState != PEDMOVE_RUN && collideWith->m_nMoveState != PEDMOVE_SPRINT)\n\t\t\t\t\t\tanimToPlay = ANIM_STD_HIT_BACK;\n\t\t\t\t\telse\n\t\t\t\t\t\tanimToPlay = ANIM_STD_HITBYGUN_BACK;\n\t\t\t\t}\n\n\t\t\t\tif (collideWith->IsPedInControl() && CTimer::GetTimeInMilliseconds() > collideWith->m_nPedStateTimer) {\n\t\t\t\t\tanimAssoc = CAnimManager::BlendAnimation(collideWith->GetClump(), ASSOCGRP_STD, animToPlay, 8.0f);\n\t\t\t\t\tanimAssoc->flags |= ASSOC_FADEOUTWHENDONE;\n\t\t\t\t\tcollideWith->m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 1000;\n\t\t\t\t\tif (m_nPedState == PED_ATTACK)\n\t\t\t\t\t\tDMAudio.PlayOneShot(m_audioEntityId, SOUND_49, 0.0f);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// We're at his right side\n\t\t\t\tif (DotProduct(posDiff, collideWith->GetRight()) <= 0.0f) {\n\t\t\t\t\tCVector moveForce = GetRight() * -1.0f;\n\t\t\t\t\tmoveForce.z += 0.1f;\n\t\t\t\t\tApplyMoveForce(moveForce);\n\t\t\t\t\tif (heLooksToUs)\n\t\t\t\t\t\tanimToPlay = ANIM_STD_HIGHIMPACT_RIGHT;\n\t\t\t\t\telse\n\t\t\t\t\t\tanimToPlay = ANIM_STD_SPINFORWARD_RIGHT;\n\t\t\t\t} else {\n\t\t\t\t\tCVector moveForce = GetRight();\n\t\t\t\t\tmoveForce.z += 0.1f;\n\t\t\t\t\tApplyMoveForce(moveForce);\n\t\t\t\t\tif (heLooksToUs)\n\t\t\t\t\t\tanimToPlay = ANIM_STD_HIGHIMPACT_LEFT;\n\t\t\t\t\telse\n\t\t\t\t\t\tanimToPlay = ANIM_STD_SPINFORWARD_LEFT;\n\t\t\t\t}\n\n\t\t\t\tif (m_nPedState == PED_ATTACK && collideWith->IsPedInControl())\n\t\t\t\t\tDMAudio.PlayOneShot(m_audioEntityId, SOUND_49, 0.0f);\n\n\t\t\t\tcollideWith->SetFall(3000, animToPlay, 0);\n\t\t\t}\n\t\t} else {\n\t\t\tif (!IsPedInControl())\n\t\t\t\treturn;\n\n\t\t\tif (collideWith->m_nMoveState == PEDMOVE_NONE || collideWith->m_nMoveState == PEDMOVE_STILL)\n\t\t\t\treturn;\n\n\t\t\tif (m_nPedType != collideWith->m_nPedType || m_nPedType == PEDTYPE_CIVMALE || m_nPedType == PEDTYPE_CIVFEMALE) {\n\n\t\t\t\tif (!weAreMissionChar && heLooksToUs && m_pedStats->m_fear > 100 - collideWith->m_pedStats->m_temper) {\n\n\t\t\t\t\tif (CGeneral::GetRandomNumber() & 1 && CTimer::GetTimeInMilliseconds() < m_nPedStateTimer){\n\t\t\t\t\t\tSetEvasiveStep(collideWith, 2);\n\t\t\t\t\t\tm_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 3000;\n\t\t\t\t\t} else if (collideWith->m_nMoveState > PEDMOVE_WALK) {\n\t\t\t\t\t\twaitTime = 2000;\n\t\t\t\t\t\tSetWaitState(WAITSTATE_PLAYANIM_DUCK, &waitTime);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if (heLooksToUs\n\t\t\t\t&& collideWith->m_nPedState != PED_STEP_AWAY\n\t\t\t\t&& m_nPedState != PED_STEP_AWAY\n\t\t\t\t&& CTimer::GetTimeInMilliseconds() > m_nPedStateTimer) {\n\n\t\t\t\tSetEvasiveStep(collideWith, 1);\n\t\t\t\tm_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 3000;\n\t\t\t}\n\t\t}\n\n\t\tif (IsPlayer()) {\n\t\t\tSetLookFlag(collideWith, true);\n\t\t\tSetLookTimer(800);\n\t\t}\n\t} else {\n\t\tbool isRunning = m_nMoveState == PEDMOVE_RUN || m_nMoveState == PEDMOVE_SPRINT;\n\t\tSetFindPathAndFlee(collideWith, 5000, !isRunning);\n\t}\n}\n\nvoid\nCPed::KillPedWithCar(CVehicle *car, float impulse)\n{\n\tCVehicleModelInfo *vehModel;\n\tCColModel *vehColModel;\n\tuint8 damageDir;\n\tPedNode nodeToDamage;\n\teWeaponType killMethod;\n\n\tif (m_nPedState == PED_FALL || m_nPedState == PED_DIE) {\n\t\tif (!m_pCollidingEntity || car->GetStatus() == STATUS_PLAYER)\n\t\t\tm_pCollidingEntity = car;\n\t\treturn;\n\t}\n\n\tif (m_nPedState == PED_DEAD)\n\t\treturn;\n\n\tif (m_pCurSurface) {\n\t\tif (m_pCurSurface->IsVehicle() && (((CVehicle*)m_pCurSurface)->IsBoat()|| IsPlayer()))\n\t\t\treturn;\n\t}\n\n\tCVector distVec = GetPosition() - car->GetPosition();\n\n\tif ((impulse > 12.0f || car->GetModelIndex() == MI_TRAIN) && !IsPlayer()) {\n\t\tnodeToDamage = PED_TORSO;\n\t\tkillMethod = WEAPONTYPE_RAMMEDBYCAR;\n\t\tuint8 randVal = CGeneral::GetRandomNumber() & 3;\n\n\t\tif (car == FindPlayerVehicle()) {\n\t\t\tfloat carSpeed = car->m_vecMoveSpeed.Magnitude();\n\t\t\tuint8 shakeFreq;\n\t\t\tif (100.0f * carSpeed * 2000.0f / car->m_fMass + 80.0f <= 250.0f) {\n\t\t\t\tshakeFreq = 100.0f * carSpeed * 2000.0f / car->m_fMass + 80.0f;\n\t\t\t} else {\n\t\t\t\tshakeFreq = 250.0f;\n\t\t\t}\n\t\t\tCPad::GetPad(0)->StartShake(40000 / shakeFreq, shakeFreq);\n\t\t}\n\t\tbIsStanding = false;\n\t\tdamageDir = GetLocalDirection(-m_vecMoveSpeed);\n\t\tvehModel = (CVehicleModelInfo *)CModelInfo::GetModelInfo(car->GetModelIndex());\n\t\tvehColModel = vehModel->GetColModel();\n\t\tfloat carRightAndDistDotProd = DotProduct(distVec, car->GetRight());\n\n\t\tif (car->GetModelIndex() == MI_TRAIN) {\n\t\t\tkillMethod = WEAPONTYPE_RUNOVERBYCAR;\n\t\t\tnodeToDamage = PED_HEAD;\n\t\t\tm_vecMoveSpeed = 0.9f * car->m_vecMoveSpeed;\n\t\t\tm_vecMoveSpeed.z = 0.0f;\n\t\t\tif (damageDir == 1 || damageDir == 3)\n\t\t\t\tdamageDir = 2;\n\t\t\tif (CGame::nastyGame)\n\t\t\t\tDMAudio.PlayOneShot(m_audioEntityId, SOUND_SPLATTER, 0.0f);\n\n\t\t// Car doesn't look to us\n\t\t} else if (DotProduct(car->m_vecMoveSpeed, car->GetForward()) >= 0.0f){\n\n\t\t\tif (0.99f * vehColModel->boundingBox.max.x < Abs(carRightAndDistDotProd)) {\n\n\t\t\t\t// We're at the right of the car\n\t\t\t\tif (carRightAndDistDotProd <= 0.0f)\n\t\t\t\t\tnodeToDamage = PED_UPPERARML;\n\t\t\t\telse\n\t\t\t\t\tnodeToDamage = PED_UPPERARMR;\n\n\t\t\t\tif (Abs(DotProduct(distVec, car->GetForward())) < 0.85f * vehColModel->boundingBox.max.y) {\n\t\t\t\t\tkillMethod = WEAPONTYPE_RUNOVERBYCAR;\n\t\t\t\t\tm_vecMoveSpeed = 0.9f * car->m_vecMoveSpeed;\n\t\t\t\t\tm_vecMoveSpeed.z = 0.0f;\n\t\t\t\t\tif (damageDir == 1 || damageDir == 3)\n\t\t\t\t\t\tdamageDir = 2;\n\t\t\t\t\tif (CGame::nastyGame)\n\t\t\t\t\t\tDMAudio.PlayOneShot(m_audioEntityId, SOUND_SPLATTER, 0.0f);\n\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfloat carFrontAndDistDotProd = DotProduct(distVec, car->GetForward());\n\n\t\t\t\t// carFrontAndDistDotProd <= 0.0 car looks to us\n\t\t\t\tif ((carFrontAndDistDotProd <= 0.1 || randVal <= 1) && randVal != 0) {\n\t\t\t\t\tkillMethod = WEAPONTYPE_RUNOVERBYCAR;\n\t\t\t\t\tnodeToDamage = PED_HEAD;\n\t\t\t\t\tm_vecMoveSpeed = 0.9f * car->m_vecMoveSpeed;\n\t\t\t\t\tm_vecMoveSpeed.z = 0.0f;\n\t\t\t\t\tif (damageDir == 1 || damageDir == 3)\n\t\t\t\t\t\tdamageDir = 2;\n\n\t\t\t\t\tif (CGame::nastyGame)\n\t\t\t\t\t\tDMAudio.PlayOneShot(m_audioEntityId, SOUND_SPLATTER, 0.0f);\n\n\t\t\t\t} else {\n\t\t\t\t\tnodeToDamage = PED_MID;\n\t\t\t\t\tfloat vehColMaxY = vehColModel->boundingBox.max.y;\n\t\t\t\t\tfloat vehColMinY = vehColModel->boundingBox.min.y;\n\t\t\t\t\tfloat vehColMaxZ = vehColModel->boundingBox.max.z;\n\t\t\t\t\tfloat carFrontZ = car->GetForward().z;\n\t\t\t\t\tfloat carHighestZ, carLength;\n\n\t\t\t\t\tif (carFrontZ < -0.2f) {\n\t\t\t\t\t\t// Highest point of car's back\n\t\t\t\t\t\tcarHighestZ = (car->GetMatrix() * CVector(0.0f, vehColMinY, vehColMaxZ)).z;\n\t\t\t\t\t\tcarLength = vehColMaxY - vehColMinY;\n\n\t\t\t\t\t} else if (carFrontZ > 0.1f) {\n\t\t\t\t\t\t// Highest point of car's front\n\t\t\t\t\t\tcarHighestZ = (car->GetMatrix() * CVector(0.0f, vehColMaxY, vehColMaxZ)).z;\n\t\t\t\t\t\tfloat highestZDist = carHighestZ - GetPosition().z;\n\t\t\t\t\t\tif (highestZDist > 0.0f) {\n\t\t\t\t\t\t\tGetMatrix().GetPosition().z += 0.5f * highestZDist;\n\t\t\t\t\t\t\tcarHighestZ += highestZDist * 0.25f;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcarLength = vehColMaxY;\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Highest point of car's front\n\t\t\t\t\t\tcarHighestZ = (car->GetMatrix() * CVector(0.0f, vehColMaxY, vehColMaxZ)).z;\n\t\t\t\t\t\tcarLength = vehColMaxY;\n\t\t\t\t\t}\n\n\t\t\t\t\tfloat pedJumpSpeedToReachHighestZ = (carHighestZ - GetPosition().z) / (carLength / car->m_vecMoveSpeed.Magnitude());\n\n\t\t\t\t\t// TODO: What are we doing down here?\n\t\t\t\t\tfloat unknown = ((CGeneral::GetRandomNumber() % 256) * 0.002 + 1.5) * pedJumpSpeedToReachHighestZ;\n\n\t\t\t\t\t// After this point distVec isn't really distVec.\n\t\t\t\t\tdistVec = car->m_vecMoveSpeed;\n\t\t\t\t\tdistVec.Normalise();\n\t\t\t\t\tdistVec *= 0.2 * unknown;\n\n\t\t\t\t\tif (damageDir != 1 && damageDir != 3)\n\t\t\t\t\t\tdistVec.z += unknown;\n\t\t\t\t\telse\n\t\t\t\t\t\tdistVec.z += 1.5f * unknown;\n\n\t\t\t\t\tm_vecMoveSpeed = distVec;\n\t\t\t\t\tdamageDir += 2;\n\t\t\t\t\tif (damageDir > 3)\n\t\t\t\t\t\tdamageDir = damageDir - 4;\n\n\t\t\t\t\tif (car->IsCar()) {\n\t\t\t\t\t\tCObject *bonnet = ((CAutomobile*)car)->RemoveBonnetInPedCollision();\n\n\t\t\t\t\t\tif (bonnet) {\n\t\t\t\t\t\t\tif (CGeneral::GetRandomNumber() & 1) {\n\t\t\t\t\t\t\t\tbonnet->m_vecMoveSpeed += Multiply3x3(car->GetMatrix(), CVector(0.1f, 0.0f, 0.5f));\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tbonnet->m_vecMoveSpeed += Multiply3x3(car->GetMatrix(), CVector(-0.1f, 0.0f, 0.5f));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tCVector forceDir = car->GetUp() * 10.0f;\n\t\t\t\t\t\t\tbonnet->ApplyTurnForce(forceDir, car->GetForward());\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (car->pDriver) {\n\t\t\tCEventList::RegisterEvent((m_nPedType == PEDTYPE_COP ? EVENT_HIT_AND_RUN_COP : EVENT_HIT_AND_RUN), EVENT_ENTITY_PED, this, car->pDriver, 1000);\n\t\t}\n\n\t\tePedPieceTypes pieceToDamage;\n\t\tswitch (nodeToDamage) {\n\t\t\tcase PED_HEAD:\n\t\t\t\tpieceToDamage = PEDPIECE_HEAD;\n\t\t\t\tbreak;\n\t\t\tcase PED_UPPERARML:\n\t\t\t\tpieceToDamage = PEDPIECE_LEFTARM;\n\t\t\t\tbreak;\n\t\t\tcase PED_UPPERARMR:\n\t\t\t\tpieceToDamage = PEDPIECE_RIGHTARM;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tpieceToDamage = PEDPIECE_MID;\n\t\t\t\tbreak;\n\t\t}\n\t\tInflictDamage(car, killMethod, 1000.0f, pieceToDamage, damageDir);\n\n\t\tif (DyingOrDead()\n\t\t\t&& bIsPedDieAnimPlaying && !m_pCollidingEntity) {\n\t\t\tm_pCollidingEntity = car;\n\t\t}\n\t\tif (nodeToDamage == PED_MID)\n\t\t\tbKnockedUpIntoAir = true;\n\t\telse\n\t\t\tbKnockedUpIntoAir = false;\n\n\t\tdistVec.Normalise();\n\n\t\tdistVec *= Min(car->m_fMass / 1400.0f, 1.0f);\n\t\tcar->ApplyMoveForce(distVec * -100.0f);\n\t\tSay(SOUND_PED_DEFEND);\n\n\t} else if (m_vecDamageNormal.z < -0.8f && impulse > 3.0f\n\t\t|| impulse > 6.0f && (!IsPlayer() || impulse > 10.0f)) {\n\n\t\tbIsStanding = false;\n\t\tuint8 fallDirection = GetLocalDirection(-car->m_vecMoveSpeed);\n\t\tfloat damage;\n\t\tif (IsPlayer() && car->GetModelIndex() == MI_TRAIN)\n\t\t\tdamage = 150.0f;\n\t\telse\n\t\t\tdamage = 30.0f;\n\t\n\t\tInflictDamage(car, WEAPONTYPE_RAMMEDBYCAR, damage, PEDPIECE_TORSO, fallDirection);\n\t\tSetFall(1000, (AnimationId)(fallDirection + ANIM_STD_HIGHIMPACT_FRONT), true);\n\n\t\tif (OnGround() && !m_pCollidingEntity &&\n\t\t\t(!IsPlayer() || bHasHitWall || car->GetModelIndex() == MI_TRAIN || m_vecDamageNormal.z < -0.8f)) {\n\n\t\t\tm_pCollidingEntity = car;\n\t\t}\n\n\t\tbKnockedUpIntoAir = false;\n\t\tif (car->GetModelIndex() != MI_TRAIN && !bHasHitWall) {\n\t\t\tm_vecMoveSpeed = car->m_vecMoveSpeed * 0.75f;\n\t\t}\n\t\tm_vecMoveSpeed.z = 0.0f;\n\t\tdistVec.Normalise();\n\t\tdistVec *= Min(car->m_fMass / 1400.0f, 1.0f);\n\t\tcar->ApplyMoveForce(distVec * -60.0f);\n\t\tSay(SOUND_PED_DEFEND);\n\t}\n\n\tif (IsGangMember()) {\n\t\tCPed *driver = car->pDriver;\n\t\tif (driver && driver->IsPlayer()\n#ifdef FIX_BUGS\n\t\t\t&& (CharCreatedBy != MISSION_CHAR || bRespondsToThreats) && (!m_leader || m_leader != driver)\n#endif\n\t\t\t) {\n\t\t\tRegisterThreatWithGangPeds(driver);\n\t\t}\n\t}\n}\n\nvoid\nCPed::DriveVehicle(void)\n{\n\tif (bOffscreen)\n\t\treturn;\n\n\tCVehicle *veh = m_pMyVehicle;\n\tif (veh->IsBike()) {\n\t\tCBike *bike = (CBike*)veh;\n\t\tfloat blendDelta = 1.0f;\n\t\tfloat targetUDLean = 0.0f;\n\t\tCAnimBlendAssociation *leftAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_BIKE_LEFT);\n\t\tCAnimBlendAssociation *rightAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_BIKE_RIGHT);\n\t\tCAnimBlendAssociation *stillAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_BIKE_READY);\n\t\tCAnimBlendAssociation *fwdAssoc, *backAssoc;\n\t\tif (IsPlayer()) {\n\t\t\tfwdAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_BIKE_LEANF);\n\t\t\tbackAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_BIKE_LEANB);\n\t\t}\n\t\tCAnimBlendAssociation *walkbackAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_BIKE_WALKBACK);\n\t\tCAnimBlendAssociation *drivebyAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_BIKE_DRIVEBY_LHS);\n\t\tif (!drivebyAssoc)\n\t\t\tdrivebyAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_BIKE_DRIVEBY_RHS);\n\t\tif (!drivebyAssoc)\n\t\t\tdrivebyAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_BIKE_DRIVEBY_FORWARD);\n\n\t\tfloat velocityFwdDotProd = DotProduct(bike->m_vecMoveSpeed, bike->GetForward());\n\t\tif (m_vecTurnSpeed.MagnitudeSqr() > 0.09f) {\n\t\t\tbike->KnockOffRider(WEAPONTYPE_FALL, 2, this, false);\n\t\t\tif (bike->pPassengers[0])\n\t\t\t\tbike->KnockOffRider(WEAPONTYPE_FALL, 2, bike->pPassengers[0], false);\n\t\t\treturn;\n\t\t}\n\t\tif (!drivebyAssoc && Abs(velocityFwdDotProd) < 0.02f) {\n\t\t\tif (!stillAssoc || stillAssoc->blendAmount < 1.0 && stillAssoc->blendDelta <= 0.0) {\n\t\t\t\tstillAssoc = CAnimManager::BlendAnimation(GetClump(), bike->m_bikeAnimType, ANIM_BIKE_READY, 2.0f);\n\t\t\t}\n\t\t} else {\n\t\t\tif (velocityFwdDotProd >= 0.0f) {\n\t\t\t\tif (stillAssoc && stillAssoc->blendDelta >= 0.0f)\n\t\t\t\t\tstillAssoc->blendDelta = -4.0f;\n\t\t\t\tif (walkbackAssoc && walkbackAssoc->blendDelta >= 0.0f)\n\t\t\t\t\twalkbackAssoc->blendDelta = -4.0f;\n\t\t\t} else {\n\t\t\t\tfloat maxReverseSpeed = bike->pHandling->Transmission.fMaxReverseVelocity;\n\t\t\t\tif (3.5f * maxReverseSpeed > velocityFwdDotProd && (bike->m_nWheelsOnGround || bike->GetUp().z < -0.5f)) {\n\t\t\t\t\tbike->KnockOffRider(WEAPONTYPE_FALL, 2, this, false);\n\t\t\t\t\tif (bike->pPassengers[0])\n\t\t\t\t\t\tbike->KnockOffRider(WEAPONTYPE_FALL, 2, bike->pPassengers[0], false);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (bike->m_fGasPedal >= 0.0 || velocityFwdDotProd <= maxReverseSpeed * 1.5) {\n\t\t\t\t\tif (IsPlayer() && velocityFwdDotProd < maxReverseSpeed * 1.5)\n\t\t\t\t\t\ttargetUDLean = -1.0f;\n\n\t\t\t\t\tif (stillAssoc && stillAssoc->blendDelta >= 0.0f)\n\t\t\t\t\t\tstillAssoc->blendDelta = -4.0f;\n\n\t\t\t\t\tif (walkbackAssoc && walkbackAssoc->blendDelta >= 0.0f) {\n\t\t\t\t\t\twalkbackAssoc->blendDelta = -4.0f;\n\t\t\t\t\t}\n\t\t\t\t} else if (!walkbackAssoc || walkbackAssoc->blendAmount < 1.0f && walkbackAssoc->blendDelta <= 0.0f) {\n\t\t\t\t\twalkbackAssoc = CAnimManager::BlendAnimation(GetClump(), bike->m_bikeAnimType, ANIM_BIKE_WALKBACK, 4.0f);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (stillAssoc)\n\t\t\tblendDelta -= Min(1.0f, CTimer::GetTimeStepNonClipped() * 0.02f * stillAssoc->blendDelta + stillAssoc->blendAmount);\n\n\t\tif (drivebyAssoc)\n\t\t\tblendDelta -= Min(blendDelta, CTimer::GetTimeStepNonClipped() * 0.02f * drivebyAssoc->blendDelta + drivebyAssoc->blendAmount);\n\n\t\tif (walkbackAssoc)\n\t\t\tblendDelta -= Min(blendDelta, CTimer::GetTimeStepNonClipped() * 0.02f * walkbackAssoc->blendDelta + walkbackAssoc->blendAmount);\n\n\t\tfloat targetLRLean, timeBlend, neededAngForWheelie, stoppieAng;\n\n\t\t// Smooth the lean amount\n\t\tif (targetUDLean == -1.0f) {\n\t\t\ttargetLRLean = 0.0f;\n\t\t\ttimeBlend = Pow(0.86f, CTimer::GetTimeStep());\n\t\t} else {\n\t\t\ttargetLRLean = clamp(bike->m_fLeanLRAngle / bike->pBikeHandling->fFullAnimLean, -1.0f, 1.0f);\n\t\t\ttimeBlend = Pow(0.86f, CTimer::GetTimeStep());\n\t\t}\n\n\t\tbike->m_fPedLeanAmountLR = bike->m_fPedLeanAmountLR * timeBlend + (1.0 - timeBlend) * targetLRLean;\n\n\t\tif (!IsPlayer()) {\n\t\t\ttargetUDLean = 0.0f;\n\n\t\t} else if (targetUDLean > -1.0f) {\n\t\t\ttargetUDLean = bike->m_fLeanInput;\n\t\t\tbike->bWheelieCam = false;\n\t\t\tneededAngForWheelie = 1.0f;\n\t\t\tif (bike->m_aWheelTimer[0] != 0.0f || bike->m_aWheelTimer[1] != 0.0f || bike->GetForward().z <= 0.0f ||\n\t\t\t\t(0.0f == bike->m_aWheelTimer[2] && 0.0f == bike->m_aWheelTimer[3])) {\n\n\t\t\t\tif (0.0f == bike->m_aWheelTimer[2] && 0.0f == bike->m_aWheelTimer[3] &&\n\t\t\t\t\t(bike->GetForward().z < 0.0f && (bike->m_aWheelTimer[0] != 0.0f || bike->m_aWheelTimer[1] != 0.0f))) {\n\n\t\t\t\t\tstoppieAng = bike->pBikeHandling->fStoppieAng;\n\t\t\t\t\tif (stoppieAng - bike->GetForward().z > 0.6f * stoppieAng)\n\t\t\t\t\t\tbike->bWheelieCam = true;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfloat wheelieAng = bike->pBikeHandling->fWheelieAng;\n\t\t\t\tneededAngForWheelie = wheelieAng - bike->GetForward().z;\n\t\t\t\tif (neededAngForWheelie < wheelieAng / 2.f)\n\t\t\t\t\tbike->bWheelieCam = true;\n\t\t\t}\n\t\t\tif (neededAngForWheelie >= 0.15f) {\n\t\t\t\tif (bike->m_fBrakePedal <= 0.5f || velocityFwdDotProd <= 0.01f) {\n\t\t\t\t\tif (bike->m_fGasPedal > 0.5f && targetUDLean <= 0.0f && 0.3f * bike->pHandling->Transmission.fMaxCruiseVelocity > velocityFwdDotProd) {\n\t\t\t\t\t\ttargetUDLean = Min(0.1f, targetUDLean);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\ttargetUDLean = Max(0.1f, targetUDLean);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\ttargetUDLean = Max(0.25f, targetUDLean);\n\t\t\t}\n\t\t\tfloat targetLRLeanABS = Abs(targetLRLean);\n\t\t\tif (targetLRLeanABS > 0.3f) {\n\t\t\t\t// Yes, UD\n\t\t\t\ttargetUDLean *= Max(0.0f, 1.0f - (targetLRLeanABS - 0.3f) * 50.f / 13.f);\n\t\t\t}\n\t\t}\n\t\tif (IsPlayer()) {\n\t\t\tfloat timeBlend = Pow(0.89f, CTimer::GetTimeStep());\n\t\t\tbike->m_fPedLeanAmountUD = (timeBlend * bike->m_fPedLeanAmountUD) + ((1.0f - timeBlend) * targetUDLean);\n\t\t} else {\n\t\t\tbike->m_fPedLeanAmountUD = 0.0f;\n\t\t}\n\n\t\tfloat fwdBackLeanAmount, leftRightLeanAmount;\n\t\tif (Abs(bike->m_fPedLeanAmountLR) <= 0.56f && IsPlayer()) {\n\n\t\t\tif (Abs(bike->m_fPedLeanAmountUD) <= 0.56f) {\n\t\t\t\tCVector2D smoothedLean(bike->m_fPedLeanAmountLR, bike->m_fPedLeanAmountUD);\n\t\t\t\tfloat smoothLeanMag = smoothedLean.Magnitude();\n\t\t\t\tif (smoothLeanMag <= 0.01f) {\n\t\t\t\t\tfwdBackLeanAmount = Abs(smoothedLean.y);\n\t\t\t\t\tleftRightLeanAmount = Abs(smoothedLean.x);\n\t\t\t\t} else {\n\t\t\t\t\tfwdBackLeanAmount = Abs(smoothedLean.y / smoothLeanMag);\n\t\t\t\t\tleftRightLeanAmount = Abs(smoothedLean.x / smoothLeanMag);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfwdBackLeanAmount = 1.0f;\n\t\t\t\tleftRightLeanAmount = 0.0f;\n\t\t\t}\n\t\t} else {\n\t\t\tfwdBackLeanAmount = 0.0f;\n\t\t\tleftRightLeanAmount = 1.0f;\n\t\t}\n\t\tfloat fwdBackBlend = fwdBackLeanAmount * blendDelta;\n\t\tfloat leftRightBlend = leftRightLeanAmount * blendDelta;\n\t\tif (IsPlayer()) {\n\t\t\tif (!fwdAssoc)\n\t\t\t\tfwdAssoc = CAnimManager::AddAnimation(GetClump(), bike->m_bikeAnimType, ANIM_BIKE_LEANF);\n\t\t\tif (!backAssoc)\n\t\t\t\tbackAssoc = CAnimManager::AddAnimation(GetClump(), bike->m_bikeAnimType, ANIM_BIKE_LEANB);\n\n\t\t\tif (bike->m_fPedLeanAmountUD < 0.0f) {\n\t\t\t\tbackAssoc->blendAmount = fwdBackBlend;\n\t\t\t\tbackAssoc->SetCurrentTime(-(bike->m_fPedLeanAmountUD * backAssoc->hierarchy->totalLength));\n\t\t\t\tbackAssoc->flags &= ~ASSOC_RUNNING;\n\t\t\t\tfwdAssoc->blendAmount = 0.0f;\n\t\t\t} else {\n\t\t\t\tfwdAssoc->blendAmount = fwdBackBlend;\n\t\t\t\tfwdAssoc->SetCurrentTime(bike->m_fPedLeanAmountUD* fwdAssoc->hierarchy->totalLength);\n\t\t\t\tfwdAssoc->flags &= ~ASSOC_RUNNING;\n\t\t\t\tbackAssoc->blendAmount = 0.0f;\n\t\t\t}\n\t\t}\n\t\tif (!leftAssoc)\n\t\t\tleftAssoc = CAnimManager::AddAnimation(GetClump(), bike->m_bikeAnimType, ANIM_BIKE_LEFT);\n\t\tif (!rightAssoc)\n\t\t\trightAssoc = CAnimManager::AddAnimation(GetClump(), bike->m_bikeAnimType, ANIM_BIKE_RIGHT);\n\n\t\tif (bike->m_fPedLeanAmountLR < 0.0f) {\n\t\t\tleftAssoc->blendAmount = leftRightBlend;\n\t\t\tleftAssoc->SetCurrentTime(-(bike->m_fPedLeanAmountLR * leftAssoc->hierarchy->totalLength));\n\t\t\tleftAssoc->flags &= ~ASSOC_RUNNING;\n\t\t\trightAssoc->blendAmount = 0.0f;\n\t\t} else {\n\t\t\trightAssoc->blendAmount = leftRightBlend;\n\t\t\trightAssoc->SetCurrentTime(bike->m_fPedLeanAmountLR* rightAssoc->hierarchy->totalLength);\n\t\t\trightAssoc->flags &= ~ASSOC_RUNNING;\n\t\t\tleftAssoc->blendAmount = 0.0f;\n\t\t}\n\t\tif (velocityFwdDotProd > 0.3f) {\n\t\t\tRwV3d Xaxis = { 1.0f, 0.0f, 0.0f };\n\t\t\tRwV3d Yaxis = { 0.0f, 1.0f, 0.0f };\n\t\t\tRtQuatRotate(&m_pFrames[PED_HEAD]->hanimFrame->q, &Xaxis, CGeneral::GetRandomNumberInRange(-6.0f * velocityFwdDotProd, 6.0f * velocityFwdDotProd), rwCOMBINEPOSTCONCAT);\n\t\t\tRtQuatRotate(&m_pFrames[PED_HEAD]->hanimFrame->q, &Yaxis, CGeneral::GetRandomNumberInRange(-6.0f * velocityFwdDotProd, 6.0f * velocityFwdDotProd), rwCOMBINEPOSTCONCAT);\n\t\t\tbDontAcceptIKLookAts = true;\n\t\t}\n\t\treturn;\n\t}\n\n\tif (!IsPlayer())\n\t\treturn;\n\n\tfloat steerAngle = m_pMyVehicle->m_fSteerAngle;\n\tCAnimBlendAssociation* lDriveAssoc;\n\tCAnimBlendAssociation* rDriveAssoc;\n\tCAnimBlendAssociation* lbAssoc;\n\tCAnimBlendAssociation* sitAssoc;\n\tif (m_pMyVehicle->IsBoat() && !(m_pMyVehicle->pHandling->Flags & HANDLING_SIT_IN_BOAT)) {\n\t\tsitAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_BOAT_DRIVE);\n\n\t\tif (!sitAssoc || sitAssoc->blendAmount < 1.0f) {\n\t\t\treturn;\n\t\t}\n\n\t\tlDriveAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_BOAT_DRIVE_LEFT);\n\t\trDriveAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_BOAT_DRIVE_RIGHT);\n\t\tlbAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_BOAT_LOOKBEHIND);\n\t} else if (m_pMyVehicle->bLowVehicle) {\n\t\tsitAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_CAR_SIT_LO);\n\n\t\tif (!sitAssoc || sitAssoc->blendAmount < 1.0f) {\n\t\t\treturn;\n\t\t}\n\n\t\tlDriveAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_CAR_DRIVE_LEFT_LO);\n\t\tlbAssoc = nil;\n\t\trDriveAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_CAR_DRIVE_RIGHT_LO);\n\t} else {\n\t\tsitAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_CAR_SIT);\n\n\t\tif (!sitAssoc || sitAssoc->blendAmount < 1.0f) {\n\t\t\treturn;\n\t\t}\n\n\t\tlDriveAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_CAR_DRIVE_LEFT);\n\t\trDriveAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_CAR_DRIVE_RIGHT);\n\t\tlbAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_CAR_LOOKBEHIND);\n\t}\n\n\tif (lbAssoc &&\n\t\tTheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_1STPERSON\n\t\t&& TheCamera.Cams[TheCamera.ActiveCam].DirectionWasLooking == LOOKING_LEFT) {\n\t\tlbAssoc->blendDelta = -1000.0f;\n\t}\n\n\tCAnimBlendAssociation* driveByAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_CAR_DRIVEBY_LEFT);\n\tif (!driveByAssoc)\n\t\tdriveByAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_CAR_DRIVEBY_RIGHT);\n\tif (!driveByAssoc)\n\t\tdriveByAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_CAR_DRIVEBY_LEFT_LO);\n\tif (!driveByAssoc)\n\t\tdriveByAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_CAR_DRIVEBY_RIGHT_LO);\n\n\tif (m_pMyVehicle->bLowVehicle || m_pMyVehicle->m_fGasPedal >= 0.0f || driveByAssoc ||\n\t\tm_pMyVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_HELI || m_pMyVehicle->GetVehicleAppearance() == VEHICLE_APPEARANCE_PLANE) {\n\t\tif (steerAngle == 0.0f || driveByAssoc) {\n\t\t\tif (lDriveAssoc)\n\t\t\t\tlDriveAssoc->blendAmount = 0.0f;\n\t\t\tif (rDriveAssoc)\n\t\t\t\trDriveAssoc->blendAmount = 0.0f;\n\n\t\t} else if (steerAngle <= 0.0f) {\n\t\t\tif (lDriveAssoc)\n\t\t\t\tlDriveAssoc->blendAmount = 0.0f;\n\n\t\t\tif (rDriveAssoc)\n\t\t\t\trDriveAssoc->blendAmount = clamp(steerAngle * -100.0f / 61.0f, 0.0f, 1.0f);\n\t\t\telse if (m_pMyVehicle->IsBoat() && !(m_pMyVehicle->pHandling->Flags & HANDLING_SIT_IN_BOAT))\n\t\t\t\tCAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_BOAT_DRIVE_RIGHT);\n\t\t\telse if (m_pMyVehicle->bLowVehicle)\n\t\t\t\tCAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_DRIVE_RIGHT_LO);\n\t\t\telse\n\t\t\t\tCAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_DRIVE_RIGHT);\n\n\t\t} else {\n\t\t\tif (rDriveAssoc)\n\t\t\t\trDriveAssoc->blendAmount = 0.0f;\n\n\t\t\tif (lDriveAssoc)\n\t\t\t\tlDriveAssoc->blendAmount = clamp(steerAngle * 100.0f / 61.0f, 0.0f, 1.0f);\n\t\t\telse if (m_pMyVehicle->IsBoat() && !(m_pMyVehicle->pHandling->Flags & HANDLING_SIT_IN_BOAT))\n\t\t\t\tCAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_BOAT_DRIVE_LEFT);\n\t\t\telse if (m_pMyVehicle->bLowVehicle)\n\t\t\t\tCAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_DRIVE_LEFT_LO);\n\t\t\telse\n\t\t\t\tCAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_DRIVE_LEFT);\n\t\t}\n\n\t\tif (lbAssoc)\n\t\t\tlbAssoc->blendDelta = -4.0f;\n\t} else {\n\n\t\tif ((TheCamera.Cams[TheCamera.ActiveCam].Mode != CCam::MODE_1STPERSON\n\t\t\t|| TheCamera.Cams[TheCamera.ActiveCam].DirectionWasLooking != LOOKING_LEFT)\n\t\t\t&& (!lbAssoc || lbAssoc->blendAmount < 1.0f && lbAssoc->blendDelta <= 0.0f)) {\n\n\t\t\tif (m_pMyVehicle->IsBoat() && !(m_pMyVehicle->pHandling->Flags & HANDLING_SIT_IN_BOAT))\n\t\t\t\tCAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_BOAT_LOOKBEHIND, 4.0f);\n\t\t\telse\n\t\t\t\tCAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_LOOKBEHIND, 4.0f);\n\t\t}\n\t}\n}\n\nvoid\nCPed::RemoveWeaponAnims(int unused, float animDelta)\n{\t\n\tCAnimBlendAssociation *weaponAssoc;\n\t//CWeaponInfo::GetWeaponInfo(unused);\n\n\tweaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WEAPON_FIRE);\n\tif (weaponAssoc) {\n\t\tweaponAssoc->blendDelta = animDelta;\n\t\tweaponAssoc->flags |= ASSOC_DELETEFADEDOUT;\n\t}\n\tweaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WEAPON_FIRE_2ND);\n\tif (weaponAssoc) {\n\t\tweaponAssoc->blendDelta = animDelta;\n\t\tweaponAssoc->flags |= ASSOC_DELETEFADEDOUT;\n\t}\n\tweaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WEAPON_FIRE_3RD);\n\tif (weaponAssoc) {\n\t\tweaponAssoc->blendDelta = animDelta;\n\t\tweaponAssoc->flags |= ASSOC_DELETEFADEDOUT;\n\t}\n\tweaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WEAPON_RELOAD);\n\tif (weaponAssoc) {\n\t\tweaponAssoc->blendDelta = animDelta;\n\t\tweaponAssoc->flags |= ASSOC_DELETEFADEDOUT;\n\t}\n\tweaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_MELEE_IDLE_FIGHTMODE);\n\tif (weaponAssoc) {\n\t\tweaponAssoc->flags |= ASSOC_DELETEFADEDOUT;\n\t\tif (weaponAssoc->flags & ASSOC_PARTIAL)\n\t\t\tweaponAssoc->blendDelta = animDelta;\n\t\telse\n\t\t\tCAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_STD_IDLE, -animDelta);\n\t}\n}\n"
  },
  {
    "path": "src/peds/PedIK.cpp",
    "content": "#include \"common.h\"\n\n#include \"Bones.h\"\n#include \"Camera.h\"\n#include \"PedIK.h\"\n#include \"Ped.h\"\n#include \"General.h\"\n#include \"RwHelper.h\"\n\nLimbMovementInfo CPedIK::ms_torsoInfo = { DEGTORAD(50.0f), DEGTORAD(-50.0f), DEGTORAD(8.0f), DEGTORAD(45.0f), DEGTORAD(-45.0f), DEGTORAD(5.0f) };\nLimbMovementInfo CPedIK::ms_headInfo = { DEGTORAD(90.0f), DEGTORAD(-90.0f), DEGTORAD(15.0f), DEGTORAD(45.0f), DEGTORAD(-45.0f), DEGTORAD(8.0f) };\nLimbMovementInfo CPedIK::ms_headRestoreInfo = { DEGTORAD(90.0f), DEGTORAD(-90.0f), DEGTORAD(10.0f), DEGTORAD(45.0f), DEGTORAD(-45.0f), DEGTORAD(5.0f) };\nLimbMovementInfo CPedIK::ms_upperArmInfo = { DEGTORAD(5.0f), DEGTORAD(-120.0f), DEGTORAD(20.0f), DEGTORAD(70.0f), DEGTORAD(-70.0f), DEGTORAD(20.0f) };\nLimbMovementInfo CPedIK::ms_lowerArmInfo = { DEGTORAD(60.0f), DEGTORAD(0.0f), DEGTORAD(15.0f), DEGTORAD(90.0f), DEGTORAD(-90.0f), DEGTORAD(10.0f) };\n\nconst RwV3d XaxisIK = { 1.0f, 0.0f, 0.0f};\nconst RwV3d YaxisIK = { 0.0f, 1.0f, 0.0f};\nconst RwV3d ZaxisIK = { 0.0f, 0.0f, 1.0f};\n\nCPedIK::CPedIK(CPed *ped)\n{\n\tm_ped = ped;\n\tm_flags = 0;\n\tm_headOrient.yaw = 0.0f;\n\tm_headOrient.pitch = 0.0f;\n\tm_torsoOrient.yaw = 0.0f;\n\tm_torsoOrient.pitch = 0.0f;\n\tm_upperArmOrient.yaw = 0.0f;\n\tm_upperArmOrient.pitch = 0.0f;\n\tm_lowerArmOrient.yaw = 0.0f;\n\tm_lowerArmOrient.pitch = 0.0f;\n}\n\ninline RwMatrix*\nGetBoneMatrix(CPed *ped, int32 bone)\n{\n\tRpHAnimHierarchy *hier = GetAnimHierarchyFromSkinClump(ped->GetClump());\n\tint idx = RpHAnimIDGetIndex(hier, bone);\n\tRwMatrix *mats = RpHAnimHierarchyGetMatrixArray(hier);\n\treturn &mats[idx];\n}\ninline RwMatrix*\nGetComponentMatrix(CPed *ped, int32 node)\n{\n\treturn GetBoneMatrix(ped, ped->m_pFrames[node]->nodeID);\n}\n\nvoid\nCPedIK::RotateTorso(AnimBlendFrameData *node, LimbOrientation *limb, bool changeRoll)\n{\n\tRtQuat *q = &node->hanimFrame->q;\n\tRtQuatRotate(q, &XaxisIK, RADTODEG(limb->yaw), rwCOMBINEREPLACE);\n\tRtQuatRotate(q, &ZaxisIK, RADTODEG(limb->pitch), rwCOMBINEPRECONCAT);\n\tm_ped->bDontAcceptIKLookAts = true;\n}\n\nvoid\nCPedIK::GetComponentPosition(RwV3d &pos, uint32 node)\n{\n\tpos = GetComponentMatrix(m_ped, node)->pos;\n}\n\nLimbMoveStatus\nCPedIK::MoveLimb(LimbOrientation &limb, float targetYaw, float targetPitch, LimbMovementInfo &moveInfo)\n{\n\tLimbMoveStatus result = ONE_ANGLE_COULDNT_BE_SET_EXACTLY;\n\n\t// yaw\n\n\tif(Abs(limb.yaw-targetYaw) < moveInfo.yawD){\n\t\tlimb.yaw = targetYaw;\n\t\tresult = ANGLES_SET_EXACTLY;\n\t}else{\n\t\tif (limb.yaw > targetYaw) {\n\t\t\tlimb.yaw -= moveInfo.yawD;\n\t\t} else if (limb.yaw < targetYaw) {\n\t\t\tlimb.yaw += moveInfo.yawD;\n\t\t}\n\t}\n\n\tif (limb.yaw > moveInfo.maxYaw || limb.yaw < moveInfo.minYaw) {\n\t\tlimb.yaw = clamp(limb.yaw, moveInfo.minYaw, moveInfo.maxYaw);\n\t\tresult = ANGLES_SET_TO_MAX;\n\t}\n\n\t// pitch\n\n\tif (Abs(limb.pitch - targetPitch) < moveInfo.pitchD){\n\t\tlimb.pitch = targetPitch;\n\t}else{\n\t\tif (limb.pitch > targetPitch) {\n\t\t\tlimb.pitch -= moveInfo.pitchD;\n\t\t} else if (limb.pitch < targetPitch) {\n\t\t\tlimb.pitch += moveInfo.pitchD;\n\t\t}\n\t\tresult = ONE_ANGLE_COULDNT_BE_SET_EXACTLY;\n\t}\n\n\tif (limb.pitch > moveInfo.maxPitch || limb.pitch < moveInfo.minPitch) {\n\t\tlimb.pitch = clamp(limb.pitch, moveInfo.minPitch, moveInfo.maxPitch);\n\t\tresult = ANGLES_SET_TO_MAX;\n\t}\n\treturn result;\n}\n\nbool\nCPedIK::RestoreGunPosn(void)\n{\n\tLimbMoveStatus limbStatus = MoveLimb(m_torsoOrient, 0.0f, 0.0f, ms_torsoInfo);\n\tRotateTorso(m_ped->m_pFrames[PED_MID], &m_torsoOrient, false);\n\treturn limbStatus == ANGLES_SET_EXACTLY;\n}\n\nbool\nCPedIK::LookInDirection(float targetYaw, float targetPitch)\n{\n\tbool success = true;\n\tfloat yaw, pitch;\n\tif (!(m_ped->m_pFrames[PED_HEAD]->flag & AnimBlendFrameData::IGNORE_ROTATION)) {\n\t\tm_ped->m_pFrames[PED_HEAD]->flag |= AnimBlendFrameData::IGNORE_ROTATION;\n\t\tRwMatrix *m = GetComponentMatrix(m_ped, PED_NECK);\n\t\tm_headOrient.yaw = Atan2(-m->at.y, -m->at.x);\n\t\tm_headOrient.yaw -= m_ped->m_fRotationCur;\n\t\tm_headOrient.yaw = CGeneral::LimitRadianAngle(m_headOrient.yaw);\n\t\tfloat up = clamp(m->up.z, -1.0f, 1.0f);\n\t\tm_headOrient.pitch = Atan2(-up, Sqrt(1.0f - SQR(-up)));\n\t}\n\n\t// parent of head is neck\n\tRwMatrix *m = GetComponentMatrix(m_ped, PED_NECK);\n\tyaw = CGeneral::LimitRadianAngle(Atan2(-m->at.y, -m->at.x));\n\tfloat up = clamp(m->up.z, -1.0f, 1.0f);\n\tpitch = Atan2(-up, Sqrt(1.0f - SQR(-up)));\n\tfloat headYaw = CGeneral::LimitRadianAngle(targetYaw - (yaw + m_torsoOrient.yaw));\n\tfloat headPitch = CGeneral::LimitRadianAngle(targetPitch - pitch) * Cos(Min(Abs(headYaw), HALFPI));\n\n\tLimbMoveStatus headStatus = MoveLimb(m_headOrient, headYaw, headPitch, ms_headInfo);\n\tif (headStatus == ANGLES_SET_TO_MAX)\n\t\tsuccess = false;\n\n\tif (headStatus != ANGLES_SET_EXACTLY && !(m_flags & LOOKAROUND_HEAD_ONLY))\n\t\tif (MoveLimb(m_torsoOrient, CGeneral::LimitRadianAngle(targetYaw-m_ped->m_fRotationCur), targetPitch, ms_torsoInfo))\n\t\t\tsuccess = true;\n\n\t// This was RotateHead\n\tRtQuat *q = &m_ped->m_pFrames[PED_HEAD]->hanimFrame->q;\n\tRtQuatRotate(q, &ZaxisIK, RADTODEG(m_headOrient.pitch), rwCOMBINEREPLACE);\n\tRtQuatRotate(q, &XaxisIK, RADTODEG(m_headOrient.yaw), rwCOMBINEPRECONCAT);\n\tm_ped->bDontAcceptIKLookAts = true;\n\n\tif (!(m_flags & LOOKAROUND_HEAD_ONLY))\n\t\tRotateTorso(m_ped->m_pFrames[PED_MID], &m_torsoOrient, false);\n\treturn success;\n}\n\nbool\nCPedIK::LookAtPosition(CVector const &pos)\n{\n\tRwV3d *pedpos = &GetComponentMatrix(m_ped, PED_MID)->pos;\n\tfloat yawToFace = CGeneral::GetRadianAngleBetweenPoints(\n\t\tpos.x, pos.y,\n\t\tpedpos->x, pedpos->y);\n\n\tfloat pitchToFace = CGeneral::GetRadianAngleBetweenPoints(\n\t\t// BUG? not using pedpos here\n\t\tpos.z, (m_ped->GetPosition() - pos).Magnitude2D(),\n\t\tpedpos->z, 0.0f);\n\n\treturn LookInDirection(yawToFace, pitchToFace);\n}\n\nbool\nCPedIK::PointGunInDirection(float targetYaw, float targetPitch)\n{\n\tbool result = true;\n\tbool armPointedToGun = false;\n\ttargetYaw = CGeneral::LimitRadianAngle(targetYaw - m_ped->GetForward().Heading());\n\tm_flags &= ~GUN_POINTED_SUCCESSFULLY;\n\tm_flags |= LOOKAROUND_HEAD_ONLY;\n\tif (m_flags & AIMS_WITH_ARM) {\n\t\tarmPointedToGun = PointGunInDirectionUsingArm(targetYaw, targetPitch);\n\t\ttargetYaw = CGeneral::LimitRadianAngle(targetYaw - (m_upperArmOrient.yaw + m_lowerArmOrient.yaw));\n\t}\n\tif (armPointedToGun) {\n\t\tif (m_flags & AIMS_WITH_ARM && m_torsoOrient.yaw * m_upperArmOrient.yaw < 0.0f)\n\t\t\tMoveLimb(m_torsoOrient, 0.0f, m_torsoOrient.pitch, ms_torsoInfo);\n\t} else {\n\t\t// Unused code\n\t\tRwMatrix *matrix;\n\t\tfloat yaw, pitch;\n\t\tmatrix = RwMatrixCreate();\n\t\t*matrix = *GetComponentMatrix(m_ped, PED_CLAVICLER);\n\t\tExtractYawAndPitchWorld(matrix, &yaw, &pitch);\n\t\tRwMatrixDestroy(matrix);\n\n\t\tif(m_flags & AIMS_WITH_ARM){\n\t\t\tif(targetPitch > 0.0f)\n\t\t\t\ttargetPitch = Max(targetPitch - Abs(targetYaw), 0.0f);\n\t\t\telse\n\t\t\t\ttargetPitch = Min(targetPitch + Abs(targetYaw), 0.0f);\n\t\t}\n\t\tLimbMoveStatus status = MoveLimb(m_torsoOrient, targetYaw, targetPitch, ms_torsoInfo);\n\t\tif (status == ANGLES_SET_TO_MAX)\n\t\t\tresult = false;\n\t\telse if (status == ANGLES_SET_EXACTLY)\n\t\t\tm_flags |= GUN_POINTED_SUCCESSFULLY;\n\t}\n\tRwMatrix *m = GetBoneMatrix(m_ped, BONE_spine);\t// BUG: game uses index 2 directly, which happens to be identical to BONE_spine\n\tRwV3d axis = { 0.0f, 0.0f, 0.0f };\n\tfloat axisangle = -CGeneral::LimitRadianAngle(Atan2(-m->at.y, -m->at.x) - m_ped->m_fRotationCur);\n\taxis.y = -Sin(axisangle);\n\taxis.z = Cos(axisangle);\n\n\t// this was RotateTorso\n\tRtQuat *q = &m_ped->m_pFrames[PED_MID]->hanimFrame->q;\n\tRtQuatRotate(q, &axis, RADTODEG(m_torsoOrient.pitch), rwCOMBINEPOSTCONCAT);\n\tRtQuatRotate(q, &XaxisIK, RADTODEG(m_torsoOrient.yaw), rwCOMBINEPOSTCONCAT);\n\tm_ped->bDontAcceptIKLookAts = true;\n\n\treturn result;\n}\n\nbool\nCPedIK::PointGunInDirectionUsingArm(float targetYaw, float targetPitch)\n{\n\tbool result = false;\n\tRwMatrix *matrix;\n\tfloat yaw, pitch;\n\n\tfloat uaRoll = 45.0f;\n\tfloat handRoll = 30.0f;\n\n\tmatrix = GetComponentMatrix(m_ped, PED_CLAVICLER);\n\tyaw = CGeneral::LimitRadianAngle(Atan2(matrix->right.y, matrix->right.x) - m_ped->m_fRotationCur);\n\tpitch = Atan2(matrix->up.z, Sqrt(1.0f - SQR(matrix->up.z)));\n\n\tfloat uaYaw, uaPitch;\n\tuaYaw = CGeneral::LimitRadianAngle(targetYaw - yaw - DEGTORAD(15.0f));\n\tuaPitch = CGeneral::LimitRadianAngle(targetPitch - pitch + DEGTORAD(10.0f));\n\tLimbMoveStatus uaStatus = MoveLimb(m_upperArmOrient, uaYaw, uaPitch, ms_upperArmInfo);\n\tif (uaStatus == ANGLES_SET_EXACTLY) {\n\t\tm_flags |= GUN_POINTED_SUCCESSFULLY;\n\t\tresult = true;\n\t}\n\n\tif (uaStatus == ANGLES_SET_TO_MAX) {\n\t\tfloat laYaw = uaYaw - m_upperArmOrient.yaw;\n\n\t\tLimbMoveStatus laStatus;\n\t\tif (laYaw > 0.0f){\n\t\t\tfloat rollReduce = laYaw/DEGTORAD(30.0f);\n\t\t\tuaRoll *= 1.0f - Min(rollReduce, 1.0f);\n\t\t\thandRoll *= 1.0f - Min(rollReduce, 1.0f);\n\n\t\t\tlaYaw *= 1.9f;\n\t\t\tlaStatus = MoveLimb(m_lowerArmOrient, laYaw, 0.0f, ms_lowerArmInfo);\n\n\t\t\t// some unused statics here\n\t\t\tfloat uaPitchAmount = 1.0f - (m_lowerArmOrient.yaw + m_upperArmOrient.yaw) * 0.34f;\n\t\t\tfloat f1 = ms_upperArmInfo.maxPitch * Max(uaPitchAmount, 0.0f);\n\t\t\tfloat f2 = 0.2f*m_lowerArmOrient.yaw + m_upperArmOrient.pitch;\n\t\t\tm_upperArmOrient.pitch = Min(f1, f2);\n\t\t}else\n\t\t\tlaStatus = MoveLimb(m_lowerArmOrient, laYaw, 0.0f, ms_lowerArmInfo);\n\n\t\tif (laStatus == ANGLES_SET_EXACTLY) {\n\t\t\tm_flags |= GUN_POINTED_SUCCESSFULLY;\n\t\t\tresult = true;\n\t\t}\n\n\t\t// game does this stupidly by going through the clump extension...\n\t\tRtQuat *q = &m_ped->m_pFrames[PED_FOREARMR]->hanimFrame->q;\n\t\tRtQuatRotate(q, &ZaxisIK, -RADTODEG(m_lowerArmOrient.yaw), rwCOMBINEREPLACE);\n\t\tRtQuatRotate(q, &XaxisIK, -RADTODEG(m_lowerArmOrient.pitch), rwCOMBINEPOSTCONCAT);\n\t\tm_ped->bDontAcceptIKLookAts = true;\n\t}\n\n\tRtQuat *q = &m_ped->m_pFrames[PED_UPPERARMR]->hanimFrame->q;\n\tRtQuatRotate(q, &XaxisIK, uaRoll, rwCOMBINEREPLACE);\n\tRtQuatRotate(q, &YaxisIK, -RADTODEG(m_upperArmOrient.pitch), rwCOMBINEPOSTCONCAT);\n\tRtQuatRotate(q, &ZaxisIK, -RADTODEG(m_upperArmOrient.yaw+HALFPI), rwCOMBINEPOSTCONCAT);\n\tm_ped->bDontAcceptIKLookAts = true;\n\n\tq = &m_ped->m_pFrames[PED_HANDR]->hanimFrame->q;\n\tRtQuatRotate(q, &XaxisIK, handRoll, rwCOMBINEPRECONCAT);\n\n\treturn result;\n}\n\nbool\nCPedIK::PointGunAtPosition(CVector const& position)\n{\n\tCVector startPoint;\n\tif (m_ped->GetWeapon()->m_eWeaponType == WEAPONTYPE_SPAS12_SHOTGUN || m_ped->GetWeapon()->m_eWeaponType == WEAPONTYPE_STUBBY_SHOTGUN)\n\t\tstartPoint = m_ped->GetPosition();\n\telse {\n\t\tRwV3d armPos;\n\t\tGetComponentPosition(armPos, PED_UPPERARMR);\n\t\tstartPoint.x = m_ped->GetPosition().x;\n\t\tstartPoint.y = m_ped->GetPosition().y;\n\t\tstartPoint.z = armPos.z;\n\t}\n\n\treturn PointGunInDirection(\n\t\tCGeneral::GetRadianAngleBetweenPoints(position.x, position.y, startPoint.x, startPoint.y),\n\t\tCGeneral::GetRadianAngleBetweenPoints(position.z, Distance2D(m_ped->GetPosition(), position.x, position.y), startPoint.z, 0.0f));\n}\n\nbool\nCPedIK::RestoreLookAt(void)\n{\n\tbool result = false;\n\tfloat yaw, pitch;\n\n\tif (m_ped->m_pFrames[PED_HEAD]->flag & AnimBlendFrameData::IGNORE_ROTATION) {\n\t\tm_ped->m_pFrames[PED_HEAD]->flag &= (~AnimBlendFrameData::IGNORE_ROTATION);\n\t} else {\n\t\tExtractYawAndPitchLocalSkinned(m_ped->m_pFrames[PED_HEAD], &yaw, &pitch);\n\t\tif (MoveLimb(m_headOrient, yaw, pitch, ms_headRestoreInfo) == ANGLES_SET_EXACTLY)\n\t\t\tresult = true;\n\t}\n\n\t// This was RotateHead\n\tRtQuat *q = &m_ped->m_pFrames[PED_HEAD]->hanimFrame->q;\n\tRtQuatRotate(q, &XaxisIK, RADTODEG(m_headOrient.yaw), rwCOMBINEREPLACE);\n\tRtQuatRotate(q, &ZaxisIK, RADTODEG(m_headOrient.pitch), rwCOMBINEPRECONCAT);\n\tm_ped->bDontAcceptIKLookAts = true;\n\n\tif (!(m_flags & LOOKAROUND_HEAD_ONLY))\n\t\tMoveLimb(m_torsoOrient, 0.0f, 0.0f, ms_torsoInfo);\n\tif (!(m_flags & LOOKAROUND_HEAD_ONLY))\n\t\tRotateTorso(m_ped->m_pFrames[PED_MID], &m_torsoOrient, false);\n\treturn result;\n}\n\nvoid\nCPedIK::ExtractYawAndPitchWorld(RwMatrix *mat, float *yaw, float *pitch)\n{\n\tfloat f = clamp(DotProduct(mat->up, CVector(0.0f, 1.0f, 0.0f)), -1.0f, 1.0f);\n\t*yaw = Acos(f);\n\tif (mat->up.x > 0.0f) *yaw = -*yaw;\n\n\tf = clamp(DotProduct(mat->right, CVector(0.0f, 0.0f, 1.0f)), -1.0f, 1.0f);\n\t*pitch = Acos(f);\n\tif (mat->up.z > 0.0f) *pitch = -*pitch;\n}\n\nvoid\nCPedIK::ExtractYawAndPitchLocal(RwMatrix *mat, float *yaw, float *pitch)\n{\n\tfloat f = clamp(DotProduct(mat->at, CVector(0.0f, 0.0f, 1.0f)), -1.0f, 1.0f);\n\t*yaw = Acos(f);\n\tif (mat->at.y > 0.0f) *yaw = -*yaw;\n\n\tf = clamp(DotProduct(mat->right, CVector(1.0f, 0.0f, 0.0f)), -1.0f, 1.0f);\n\t*pitch = Acos(f);\n\tif (mat->up.x > 0.0f) *pitch = -*pitch;\n}\n\nvoid\nCPedIK::ExtractYawAndPitchLocalSkinned(AnimBlendFrameData *node, float *yaw, float *pitch)\n{\n\tRwMatrix *mat = RwMatrixCreate();\n\tRtQuatConvertToMatrix(&node->hanimFrame->q, mat);\n\tExtractYawAndPitchLocal(mat, yaw, pitch);\n\tRwMatrixDestroy(mat);\n}\n"
  },
  {
    "path": "src/peds/PedIK.h",
    "content": "#pragma once\n#include \"common.h\"\n#include \"AnimBlendClumpData.h\"\n\nstruct LimbOrientation\n{\n\tfloat yaw;\n\tfloat pitch;\n};\n\nstruct LimbMovementInfo {\n\tfloat maxYaw;\n\tfloat minYaw;\n\tfloat yawD;\n\tfloat maxPitch;\n\tfloat minPitch;\n\tfloat pitchD;\n};\n\nenum LimbMoveStatus {\n\tANGLES_SET_TO_MAX, // because given angles were unreachable\n\tONE_ANGLE_COULDNT_BE_SET_EXACTLY, // because it can't be reached in a jiffy\n\tANGLES_SET_EXACTLY\n};\n\nclass CPed;\n\nclass CPedIK\n{\npublic:\n\tenum {\n\t\tGUN_POINTED_SUCCESSFULLY = 1, // set but unused\n\t\tLOOKAROUND_HEAD_ONLY = 2,\n\t\tAIMS_WITH_ARM = 4,\n\t};\n\n\tCPed *m_ped;\n\tLimbOrientation m_headOrient;\n\tLimbOrientation m_torsoOrient;\n\tLimbOrientation m_upperArmOrient;\n\tLimbOrientation m_lowerArmOrient;\n\tint32 m_flags;\n\n\tstatic LimbMovementInfo ms_torsoInfo;\n\tstatic LimbMovementInfo ms_headInfo;\n\tstatic LimbMovementInfo ms_headRestoreInfo;\n\tstatic LimbMovementInfo ms_upperArmInfo;\n\tstatic LimbMovementInfo ms_lowerArmInfo;\n\n\tCPedIK(CPed *ped);\n\tbool PointGunInDirection(float targetYaw, float targetPitch);\n\tbool PointGunInDirectionUsingArm(float targetYaw, float targetPitch);\n\tbool PointGunAtPosition(CVector const& position);\n\tvoid GetComponentPosition(RwV3d &pos, uint32 node);\n\tvoid RotateTorso(AnimBlendFrameData* animBlend, LimbOrientation* limb, bool changeRoll);\n\tvoid ExtractYawAndPitchLocal(RwMatrix *mat, float *yaw, float *pitch);\n\tvoid ExtractYawAndPitchLocalSkinned(AnimBlendFrameData *node, float *yaw, float *pitch);\n\tvoid ExtractYawAndPitchWorld(RwMatrix *mat, float *yaw, float *pitch);\n\tLimbMoveStatus MoveLimb(LimbOrientation &limb, float targetYaw, float targetPitch, LimbMovementInfo &moveInfo);\n\tbool RestoreGunPosn(void);\n\tbool LookInDirection(float targetYaw, float targetPitch);\n\tbool LookAtPosition(CVector const& pos);\n\tbool RestoreLookAt(void);\n};\n\nVALIDATE_SIZE(CPedIK, 0x28);\n"
  },
  {
    "path": "src/peds/PedPlacement.cpp",
    "content": "#include \"common.h\"\n\n#include \"Ped.h\"\n#include \"PedPlacement.h\"\n#include \"World.h\"\n\nbool\nCPedPlacement::FindZCoorForPed(CVector* pos)\n{\n\tfloat zForPed;\n\tfloat startZ = pos->z - 100.0f;\n\tfloat foundColZ = -100.0f;\n\tfloat foundColZ2 = -100.0f;\n\tCColPoint foundCol;\n\tCEntity* foundEnt;\n\n\tCVector vec(\n\t\tpos->x,\n\t\tpos->y,\n\t\tpos->z + 1.0f\n\t);\n\n\tif (CWorld::ProcessVerticalLine(vec, startZ, foundCol, foundEnt, true, false, false, false, true, false, nil))\n\t\tfoundColZ = foundCol.point.z;\n\n\t// Adjust coords and do a second test\n\tvec.x += 0.1f;\n\tvec.y += 0.1f;\n\n\tif (CWorld::ProcessVerticalLine(vec, startZ, foundCol, foundEnt, true, false, false, false, true, false, nil))\n\t\tfoundColZ2 = foundCol.point.z;\n\n\tzForPed = Max(foundColZ, foundColZ2);\n\n\tif (zForPed > -99.0f) {\n\t\tpos->z = FEET_OFFSET + zForPed;\n\t\treturn true;\n\t}\n\treturn false;\n}\n\nCEntity*\nCPedPlacement::IsPositionClearOfCars(Const CVector *pos)\n{\n\treturn CWorld::TestSphereAgainstWorld(*pos, 0.25f, nil, true, true, false, false, false, false);\n}\n\nbool\nCPedPlacement::IsPositionClearForPed(const CVector& pos, float radius, int total, CEntity** entities)\n{\n\tint16 count;\n\tif (radius == -1.0f)\n\t\tradius = 0.75f;\n\tif (total == -1)\n\t\ttotal = 2;\n\tCWorld::FindObjectsKindaColliding(pos, radius, true, &count, total, entities, false, true, true, false, false);\n\treturn count == 0;\n}\n"
  },
  {
    "path": "src/peds/PedPlacement.h",
    "content": "#pragma once\n\nclass CPedPlacement {\npublic:\n\tstatic bool FindZCoorForPed(CVector* pos);\n\tstatic CEntity* IsPositionClearOfCars(Const CVector*);\n\tstatic bool IsPositionClearForPed(const CVector& pos, float radius = -1.0f, int total = -1, CEntity** entities = nil);\n};"
  },
  {
    "path": "src/peds/PedRoutes.cpp",
    "content": "#include \"common.h\"\n\n#include \"main.h\"\n#include \"PedRoutes.h\"\n\nCRouteNode gaRoutes[NUMPEDROUTES];\n\nvoid\nCRouteNode::Initialise()\n{\n\tfor (int i = 0; i < NUMPEDROUTES; i++) {\n\t\tgaRoutes[i].m_route = -1;\n\t\tgaRoutes[i].m_pos = CVector(0.0f, 0.0f, 0.0f);\n\t}\n}\n\nint16\nCRouteNode::GetRouteThisPointIsOn(int16 point)\n{\n\treturn gaRoutes[point].m_route;\n}\n\n// Actually GetFirstPointOfRoute\nint16\nCRouteNode::GetRouteStart(int16 route)\n{\n\tfor (int i = 0; i < NUMPEDROUTES; i++) {\n\t\tif (route == gaRoutes[i].m_route)\n\t\t\treturn i;\n\t}\n\treturn -1;\n}\n\nCVector\nCRouteNode::GetPointPosition(int16 point)\n{\n\treturn gaRoutes[point].m_pos;\n}\n\nvoid\nCRouteNode::AddRoutePoint(int16 route, CVector pos)\n{\n\tuint16 point;\n\tfor (point = 0; point < NUMPEDROUTES; point++) {\n\t\tif (gaRoutes[point].m_route == -1)\n\t\t\tbreak;\n\t}\n#ifdef FIX_BUGS\n\tif (point == NUMPEDROUTES)\n\t\treturn;\n#endif\n\tgaRoutes[point].m_route = route;\n\tgaRoutes[point].m_pos = pos;\n}\n\nvoid\nCRouteNode::RemoveRoute(int16 route)\n{\n\tuint16 first_point, last_point, i;\n\tfor (first_point = 0; first_point < NUMPEDROUTES; first_point++) {\n\t\tif (gaRoutes[first_point].m_route == route)\n\t\t\tbreak;\n\t}\n\tif (first_point == NUMPEDROUTES)\n\t\treturn;\n\tfor (last_point = first_point; last_point < NUMPEDROUTES; last_point++)\n\t\tif (gaRoutes[last_point].m_route != route)\n\t\t\tbreak;\n\tuint16 diff = last_point - first_point;\n#ifdef FIX_BUGS\t\n\tfor (i = first_point; i < NUMPEDROUTES - diff; i++)\n\t\tgaRoutes[i] = gaRoutes[i + diff];\n#else\n\tfor (i = 0; i < diff; i++)\n\t\tgaRoutes[first_point + i] = gaRoutes[last_point + i];\n#endif\n\tfor (i = NUMPEDROUTES - diff; i < NUMPEDROUTES; i++)\n\t\tgaRoutes[i].m_route = -1;\n}\n"
  },
  {
    "path": "src/peds/PedRoutes.h",
    "content": "#pragma once\n\nclass CRouteNode\n{\npublic:\n\tint16 m_route;\n\tCVector m_pos;\n\n\tstatic int16 GetRouteThisPointIsOn(int16);\n\tstatic CVector GetPointPosition(int16);\n\tstatic int16 GetRouteStart(int16);\n\tstatic void AddRoutePoint(int16, CVector);\n\tstatic void RemoveRoute(int16);\n\tstatic void Initialise(void);\n};\n"
  },
  {
    "path": "src/peds/PedType.cpp",
    "content": "#include \"common.h\"\n\n#include \"General.h\"\n#include \"FileMgr.h\"\n#include \"PedType.h\"\n\nCPedType *CPedType::ms_apPedType[NUM_PEDTYPES];\nCPedStats *CPedStats::ms_apPedStats[NUM_PEDSTATS];\n\nvoid\nCPedType::Initialise(void)\n{\n\tint i;\n\n\tdebug(\"Initialising CPedType...\\n\");\n\tfor(i = 0; i < NUM_PEDTYPES; i++){\n\t\tms_apPedType[i] = new CPedType;\n\t\tms_apPedType[i]->m_flag = PED_FLAG_PLAYER1;\n\t\tms_apPedType[i]->unknown1 = 0.0f;\n\t\tms_apPedType[i]->unknown2 = 0.0f;\n\t\t// unknown3 not initialized\n\t\tms_apPedType[i]->unknown4 = 0.0f;\n\t\tms_apPedType[i]->unknown5 = 0.0f;\n\t\tms_apPedType[i]->m_threats = 0;\n\t\tms_apPedType[i]->m_avoid = 0;\n\t}\n\tdebug(\"Loading ped data...\\n\");\n\tLoadPedData();\n\tdebug(\"CPedType ready\\n\");\n}\n\nvoid\nCPedType::Shutdown(void)\n{\n\tint i;\n\tdebug(\"Shutting down CPedType...\\n\");\n\tfor(i = 0; i < NUM_PEDTYPES; i++)\n\t\tdelete ms_apPedType[i];\n\tdebug(\"CPedType shut down\\n\");\n}\n\nvoid\nCPedType::LoadPedData(void)\n{\n\tchar *buf;\n\tchar line[256];\n\tchar word[32];\n\tssize_t bp, buflen;\n\tint lp, linelen;\n\tint type;\n\tuint32 flags;\n\tfloat f1, f2, f3, f4, f5;\n\n\ttype = NUM_PEDTYPES;\n\tbuf = new char[16 * 1024];\n\n\tCFileMgr::SetDir(\"DATA\");\n\tbuflen = CFileMgr::LoadFile(\"PED.DAT\", (uint8*)buf, 16 * 1024, \"r\");\n\tCFileMgr::SetDir(\"\");\n\n\tfor(bp = 0; bp < buflen; ){\n\t\t// read file line by line\n\t\tfor(linelen = 0; buf[bp] != '\\n' && bp < buflen; bp++){\n\t\t\tif(buf[bp] == '\\r' || buf[bp] == ',' || buf[bp] == '\\t')\n\t\t\t\tline[linelen++] = ' ';\n\t\t\telse\n\t\t\t\tline[linelen++] = buf[bp];\n\t\t}\n\t\tbp++;\n\t\tline[linelen] = '\\0';\n\n\t\t// skip white space\n\t\tfor(lp = 0; line[lp] <= ' '; lp++);\n\n\t\tif(lp >= linelen ||\t\t// FIX: game uses == here, but this is safer if we have empty lines\n\t\t   line[lp] == '#')\n\t\t\tcontinue;\n\n\t\t// Game uses just \"line\" here since sscanf already trims whitespace, but this is safer\n\t\tsscanf(&line[lp], \"%s\", word);\n\n\t\tif(strcmp(word, \"Threat\") == 0){\n\t\t\tflags = 0;\n\t\t\tlp += 7;\n\t\t\twhile(sscanf(&line[lp], \"%s\", word) == 1 && lp <= linelen){\n\t\t\t\tflags |= FindPedFlag(word);\n\t\t\t\t// skip word\n\t\t\t\twhile(line[lp] != ' ' && line[lp] != '\\n' && line[lp] != '\\0')\n\t\t\t\t\tlp++;\n\t\t\t\t// skip white space\n\t\t\t\twhile(line[lp] == ' ')\n\t\t\t\t\tlp++;\n\t\t\t}\n\t\t\tms_apPedType[type]->m_threats = flags;\n\t\t}else if(strcmp(word, \"Avoid\") == 0){\n\t\t\tflags = 0;\n\t\t\tlp += 6;\n\t\t\twhile(sscanf(&line[lp], \"%s\", word) == 1 && lp <= linelen){\n\t\t\t\tflags |= FindPedFlag(word);\n\t\t\t\t// skip word\n\t\t\t\twhile(line[lp] != ' ' && line[lp] != '\\n' && line[lp] != '\\0')\n\t\t\t\t\tlp++;\n\t\t\t\t// skip white space\n\t\t\t\twhile(line[lp] == ' ')\n\t\t\t\t\tlp++;\n\t\t\t}\n\t\t\tms_apPedType[type]->m_avoid = flags;\n\t\t}else{\n\t\t\tsscanf(line, \"%s %f %f %f %f %f\", word, &f1, &f2, &f3, &f4, &f5);\n\t\t\ttype = FindPedType(word);\n\t\t\tms_apPedType[type]->m_flag = FindPedFlag(word);\n\t\t\t// unknown values\n\t\t\tms_apPedType[type]->unknown1 = f1 / 50.0f;\n\t\t\tms_apPedType[type]->unknown2 = f2 / 50.0f;\n\t\t\tms_apPedType[type]->unknown3 = f3 / 50.0f;\n\t\t\tms_apPedType[type]->unknown4 = f4;\n\t\t\tms_apPedType[type]->unknown5 = f5;\n\n\t\t}\n\t}\n\n\tdelete[] buf;\n}\n\nePedType\nCPedType::FindPedType(char *type)\n{\n\tif(strcmp(type, \"PLAYER1\") == 0) return PEDTYPE_PLAYER1;\n\tif(strcmp(type, \"PLAYER2\") == 0) return PEDTYPE_PLAYER2;\n\tif(strcmp(type, \"PLAYER3\") == 0) return PEDTYPE_PLAYER3;\n\tif(strcmp(type, \"PLAYER4\") == 0) return PEDTYPE_PLAYER4;\n\tif(strcmp(type, \"CIVMALE\") == 0) return PEDTYPE_CIVMALE;\n\tif(strcmp(type, \"CIVFEMALE\") == 0) return PEDTYPE_CIVFEMALE;\n\tif(strcmp(type, \"COP\") == 0) return PEDTYPE_COP;\n\tif(strcmp(type, \"GANG1\") == 0) return PEDTYPE_GANG1;\n\tif(strcmp(type, \"GANG2\") == 0) return PEDTYPE_GANG2;\n\tif(strcmp(type, \"GANG3\") == 0) return PEDTYPE_GANG3;\n\tif(strcmp(type, \"GANG4\") == 0) return PEDTYPE_GANG4;\n\tif(strcmp(type, \"GANG5\") == 0) return PEDTYPE_GANG5;\n\tif(strcmp(type, \"GANG6\") == 0) return PEDTYPE_GANG6;\n\tif(strcmp(type, \"GANG7\") == 0) return PEDTYPE_GANG7;\n\tif(strcmp(type, \"GANG8\") == 0) return PEDTYPE_GANG8;\n\tif(strcmp(type, \"GANG9\") == 0) return PEDTYPE_GANG9;\n\tif(strcmp(type, \"EMERGENCY\") == 0) return PEDTYPE_EMERGENCY;\n\tif(strcmp(type, \"FIREMAN\") == 0) return PEDTYPE_FIREMAN;\n\tif(strcmp(type, \"CRIMINAL\") == 0) return PEDTYPE_CRIMINAL;\n\tif(strcmp(type, \"SPECIAL\") == 0) return PEDTYPE_SPECIAL;\n\tif(strcmp(type, \"PROSTITUTE\") == 0) return PEDTYPE_PROSTITUTE;\n\tError(\"Unknown ped type, Pedtype.cpp\");\n\treturn NUM_PEDTYPES;\n}\n\nuint32\nCPedType::FindPedFlag(char *type)\n{\n\tif(strcmp(type, \"PLAYER1\") == 0) return PED_FLAG_PLAYER1;\n\tif(strcmp(type, \"PLAYER2\") == 0) return PED_FLAG_PLAYER2;\n\tif(strcmp(type, \"PLAYER3\") == 0) return PED_FLAG_PLAYER3;\n\tif(strcmp(type, \"PLAYER4\") == 0) return PED_FLAG_PLAYER4;\n\tif(strcmp(type, \"CIVMALE\") == 0) return PED_FLAG_CIVMALE;\n\tif(strcmp(type, \"CIVFEMALE\") == 0) return PED_FLAG_CIVFEMALE;\n\tif(strcmp(type, \"COP\") == 0) return PED_FLAG_COP;\n\tif(strcmp(type, \"GANG1\") == 0) return PED_FLAG_GANG1;\n\tif(strcmp(type, \"GANG2\") == 0) return PED_FLAG_GANG2;\n\tif(strcmp(type, \"GANG3\") == 0) return PED_FLAG_GANG3;\n\tif(strcmp(type, \"GANG4\") == 0) return PED_FLAG_GANG4;\n\tif(strcmp(type, \"GANG5\") == 0) return PED_FLAG_GANG5;\n\tif(strcmp(type, \"GANG6\") == 0) return PED_FLAG_GANG6;\n\tif(strcmp(type, \"GANG7\") == 0) return PED_FLAG_GANG7;\n\tif(strcmp(type, \"GANG8\") == 0) return PED_FLAG_GANG8;\n\tif(strcmp(type, \"GANG9\") == 0) return PED_FLAG_GANG9;\n\tif(strcmp(type, \"EMERGENCY\") == 0) return PED_FLAG_EMERGENCY;\n\tif(strcmp(type, \"FIREMAN\") == 0) return PED_FLAG_FIREMAN;\n\tif(strcmp(type, \"CRIMINAL\") == 0) return PED_FLAG_CRIMINAL;\n\tif(strcmp(type, \"SPECIAL\") == 0) return PED_FLAG_SPECIAL;\n\tif(strcmp(type, \"GUN\") == 0) return PED_FLAG_GUN;\n\tif(strcmp(type, \"COP_CAR\") == 0) return PED_FLAG_COP_CAR;\n\tif(strcmp(type, \"FAST_CAR\") == 0) return PED_FLAG_FAST_CAR;\n\tif(strcmp(type, \"EXPLOSION\") == 0) return PED_FLAG_EXPLOSION;\n\tif(strcmp(type, \"PROSTITUTE\") == 0) return PED_FLAG_PROSTITUTE;\n\tif(strcmp(type, \"DEADPEDS\") == 0) return PED_FLAG_DEADPEDS;\n\treturn 0;\n}\n\nvoid\nCPedType::Save(uint8 *buf, uint32 *size)\n{\n\t*size = sizeof(CPedType) * NUM_PEDTYPES + SAVE_HEADER_SIZE;\nINITSAVEBUF\n\tWriteSaveHeader(buf, 'P','T','P','\\0', *size - SAVE_HEADER_SIZE);\n\tfor(int i = 0; i < NUM_PEDTYPES; i++)\n\t\tWriteSaveBuf(buf, *ms_apPedType[i]);\nVALIDATESAVEBUF(*size)\n}\n\nvoid\nCPedType::Load(uint8 *buf, uint32 size)\n{\nINITSAVEBUF\n\t// original: SkipSaveBuf(buf, SAVE_HEADER_SIZE);\n\tCheckSaveHeader(buf, 'P', 'T', 'P', '\\0', size - SAVE_HEADER_SIZE);\n\n\tfor(int i = 0; i < NUM_PEDTYPES; i++)\n\t\t*ms_apPedType[i] = ReadSaveBuf<CPedType>(buf);\nVALIDATESAVEBUF(size)\n}\n\nvoid\nCPedStats::Initialise(void)\n{\n\tint i;\n\n\tdebug(\"Initialising CPedStats...\\n\");\n\tfor(i = 0; i < NUM_PEDSTATS; i++){\n\t\tms_apPedStats[i] = new CPedStats;\n\t\tms_apPedStats[i]->m_type = PEDSTAT_PLAYER;\n\t\tms_apPedStats[i]->m_name[8] = 'R';\t// WHAT?\n\t\tms_apPedStats[i]->m_fleeDistance = 20.0f;\n\t\tms_apPedStats[i]->m_headingChangeRate = 15.0f;\n\t\tms_apPedStats[i]->m_fear = 50;\n\t\tms_apPedStats[i]->m_temper = 50;\n\t\tms_apPedStats[i]->m_lawfulness = 50;\n\t\tms_apPedStats[i]->m_sexiness = 50;\n\t\tms_apPedStats[i]->m_attackStrength = 1.0f;\n\t\tms_apPedStats[i]->m_defendWeakness = 1.0f;\n\t\tms_apPedStats[i]->m_flags = 0;\n\t}\n\tdebug(\"Loading pedstats data...\\n\");\n\tCPedStats::LoadPedStats();\n\tdebug(\"CPedStats ready\\n\");\n}\n\nvoid\nCPedStats::Shutdown(void)\n{\n\tint i;\n\tdebug(\"Shutting down CPedStats...\\n\");\n\tfor(i = 0; i < NUM_PEDSTATS; i++)\n\t\tdelete ms_apPedStats[i];\n\tdebug(\"CPedStats shut down\\n\");\n}\n\nvoid\nCPedStats::LoadPedStats(void)\n{\n\tchar *buf;\n\tchar line[256];\n\tchar name[32];\n\tssize_t bp, buflen;\n\tint lp, linelen;\n\tint type;\n\tfloat fleeDist, headingChangeRate, attackStrength, defendWeakness;\n\tint fear, temper, lawfullness, sexiness, flags;\n\n\ttype = 0;\n\tbuf = new char[16 * 1024];\n\n\tCFileMgr::SetDir(\"DATA\");\n\tbuflen = CFileMgr::LoadFile(\"PEDSTATS.DAT\", (uint8*)buf, 16 * 1024, \"r\");\n\tCFileMgr::SetDir(\"\");\n\n\tfor(bp = 0; bp < buflen; ){\n\t\t// read file line by line\n\t\tfor(linelen = 0; buf[bp] != '\\n' && bp < buflen; bp++){\n\t\t\tif(buf[bp] == '\\r' || buf[bp] == ',' || buf[bp] == '\\t')\n\t\t\t\tline[linelen++] = ' ';\n\t\t\telse\n\t\t\t\tline[linelen++] = buf[bp];\n\t\t}\n\t\tbp++;\n\t\tline[linelen] = '\\0';\n\n\t\t// skip white space\n\t\tfor(lp = 0; line[lp] <= ' '; lp++);\n\n\t\tif(lp >= linelen ||\t\t// FIX: game uses == here, but this is safer if we have empty lines\n\t\t   line[lp] == '#')\n\t\t\tcontinue;\n\n\t\tsscanf(&line[lp], \"%s %f %f %d %d %d %d %f %f %d\",\n\t\t\tname,\n\t\t\t&fleeDist,\n\t\t\t&headingChangeRate,\n\t\t\t&fear,\n\t\t\t&temper,\n\t\t\t&lawfullness,\n\t\t\t&sexiness,\n\t\t\t&attackStrength,\n\t\t\t&defendWeakness,\n\t\t\t&flags);\n\t\tms_apPedStats[type]->m_type = (ePedStats)type;\n\t\tstrncpy(ms_apPedStats[type]->m_name, name, 24);\t// FIX: game uses strcpy\n\t\tms_apPedStats[type]->m_fleeDistance = fleeDist;\n\t\tms_apPedStats[type]->m_headingChangeRate = headingChangeRate;\n\t\tms_apPedStats[type]->m_fear = fear;\n\t\tms_apPedStats[type]->m_temper = temper;\n\t\tms_apPedStats[type]->m_lawfulness = lawfullness;\n\t\tms_apPedStats[type]->m_sexiness = sexiness;\n\t\tms_apPedStats[type]->m_attackStrength = attackStrength;\n\t\tms_apPedStats[type]->m_defendWeakness = defendWeakness;\n\t\tms_apPedStats[type]->m_flags = flags;\n\t\ttype++;\n\t}\n\n\tdelete[] buf;\n}\n\nePedStats\nCPedStats::GetPedStatType(char *name)\n{\n\tfor(uint16 type = 0; type < NUM_PEDSTATS; type++)\n\t\tif(!CGeneral::faststrcmp(ms_apPedStats[type]->m_name, name))\n\t\t\treturn (ePedStats) type;\n\n\treturn NUM_PEDSTATS;\n}\n"
  },
  {
    "path": "src/peds/PedType.h",
    "content": "#pragma once\n\n// Index into the PedType array\nenum ePedType\n{\n\tPEDTYPE_PLAYER1,\n\tPEDTYPE_PLAYER2,\n\tPEDTYPE_PLAYER3,\n\tPEDTYPE_PLAYER4,\n\tPEDTYPE_CIVMALE,\n\tPEDTYPE_CIVFEMALE,\n\tPEDTYPE_COP,\n\tPEDTYPE_GANG1,\n\tPEDTYPE_GANG2,\n\tPEDTYPE_GANG3,\n\tPEDTYPE_GANG4,\n\tPEDTYPE_GANG5, // Security - hardcoded\n\tPEDTYPE_GANG6,\n\tPEDTYPE_GANG7, // Vercetti gang - hardcoded\n\tPEDTYPE_GANG8,\n\tPEDTYPE_GANG9,\n\tPEDTYPE_EMERGENCY,\n\tPEDTYPE_FIREMAN,\n\tPEDTYPE_CRIMINAL,\n\tPEDTYPE_UNUSED1,\n\tPEDTYPE_PROSTITUTE,\n\tPEDTYPE_SPECIAL,\n\tPEDTYPE_UNUSED2,\n\n\tNUM_PEDTYPES\n};\n\nenum\n{\n\tPED_FLAG_PLAYER1 = 1 << 0,\n\tPED_FLAG_PLAYER2 = 1 << 1,\n\tPED_FLAG_PLAYER3 = 1 << 2,\n\tPED_FLAG_PLAYER4 = 1 << 3,\n\tPED_FLAG_CIVMALE = 1 << 4,\n\tPED_FLAG_CIVFEMALE = 1 << 5,\n\tPED_FLAG_COP = 1 << 6,\n\tPED_FLAG_GANG1 = 1 << 7,\n\tPED_FLAG_GANG2 = 1 << 8,\n\tPED_FLAG_GANG3 = 1 << 9,\n\tPED_FLAG_GANG4 = 1 << 10,\n\tPED_FLAG_GANG5 = 1 << 11,\n\tPED_FLAG_GANG6 = 1 << 12,\n\tPED_FLAG_GANG7 = 1 << 13,\n\tPED_FLAG_GANG8 = 1 << 14,\n\tPED_FLAG_GANG9 = 1 << 15,\n\tPED_FLAG_EMERGENCY = 1 << 16,\n\tPED_FLAG_PROSTITUTE = 1 << 17,\n\tPED_FLAG_CRIMINAL = 1 << 18,\n\tPED_FLAG_SPECIAL = 1 << 19,\n\tPED_FLAG_GUN = 1 << 20,\n\tPED_FLAG_COP_CAR = 1 << 21,\n\tPED_FLAG_FAST_CAR = 1 << 22,\n\tPED_FLAG_EXPLOSION = 1 << 23,\n\tPED_FLAG_FIREMAN = 1 << 24,\n\tPED_FLAG_DEADPEDS = 1 << 25,\n};\n\nclass CPedType\n{\n\tuint32 m_flag;\n\tfloat unknown1;\n\tfloat unknown2;\n\tfloat unknown3;\n\tfloat unknown4;\n\tfloat unknown5;\n\tuint32 m_threats;\n\tuint32 m_avoid;\n\n\tstatic CPedType *ms_apPedType[NUM_PEDTYPES];\npublic:\n\n\tstatic void Initialise(void);\n\tstatic void Shutdown(void);\n\tstatic void LoadPedData(void);\n\tstatic ePedType FindPedType(char *type);\n\tstatic uint32 FindPedFlag(char *type);\n\tstatic void Save(uint8 *buf, uint32 *size);\n\tstatic void Load(uint8 *buf, uint32 size);\n\n\tstatic uint32 GetFlag(int type) { return ms_apPedType[type]->m_flag; }\n\tstatic uint32 GetAvoid(int type) { return ms_apPedType[type]->m_avoid; }\n\tstatic uint32 GetThreats(int type) { return ms_apPedType[type]->m_threats; }\n\tstatic void SetThreats(int type, uint32 threat) { ms_apPedType[type]->m_threats = threat; }\n\tstatic void AddThreat(int type, int threat) { ms_apPedType[type]->m_threats |= threat; }\n\tstatic void RemoveThreat(int type, int threat) { ms_apPedType[type]->m_threats &= ~threat; }\n\tstatic bool IsThreat(int type, int threat) { return ms_apPedType[type]->m_threats & threat; }\n};\n\nVALIDATE_SIZE(CPedType, 0x20);\n\nenum ePedStats\n{\n\tPEDSTAT_PLAYER,\n\tPEDSTAT_COP,\n\tPEDSTAT_MEDIC,\n\tPEDSTAT_FIREMAN,\n\tPEDSTAT_GANG1,\n\tPEDSTAT_GANG2,\n\tPEDSTAT_GANG3,\n\tPEDSTAT_GANG4,\n\tPEDSTAT_GANG5,\n\tPEDSTAT_GANG6,\n\tPEDSTAT_GANG7,\n\tPEDSTAT_STREET_GUY,\n\tPEDSTAT_SUIT_GUY,\n\tPEDSTAT_SENSIBLE_GUY,\n\tPEDSTAT_GEEK_GUY,\n\tPEDSTAT_OLD_GUY,\n\tPEDSTAT_TOUGH_GUY,\n\tPEDSTAT_STREET_GIRL,\n\tPEDSTAT_SUIT_GIRL,\n\tPEDSTAT_SENSIBLE_GIRL,\n\tPEDSTAT_GEEK_GIRL,\n\tPEDSTAT_OLD_GIRL,\n\tPEDSTAT_TOUGH_GIRL,\n\tPEDSTAT_TRAMP_MALE,\n\tPEDSTAT_TRAMP_FEMALE,\n\tPEDSTAT_TOURIST,\n\tPEDSTAT_PROSTITUTE,\n\tPEDSTAT_CRIMINAL,\n\tPEDSTAT_BUSKER,\n\tPEDSTAT_TAXIDRIVER,\n\tPEDSTAT_PSYCHO,\n\tPEDSTAT_STEWARD,\n\tPEDSTAT_SPORTSFAN,\n\tPEDSTAT_SHOPPER,\n\tPEDSTAT_OLDSHOPPER,\n\tPEDSTAT_BEACH_GUY,\n\tPEDSTAT_BEACH_GIRL,\n\tPEDSTAT_SKATER,\n\tPEDSTAT_STD_MISSION,\n\tPEDSTAT_COWARD,\n\n\tNUM_PEDSTATS\n};\n\n// flags\nenum\n{\n\tSTAT_PUNCH_ONLY = 1,\n\tSTAT_CAN_KNEE_HEAD = 2,\n\tSTAT_CAN_KICK = 4,\n\tSTAT_CAN_ROUNDHOUSE = 8,\n\tSTAT_NO_DIVE = 0x10,\n\tSTAT_ONE_HIT_KNOCKDOWN = 0x20,\n\tSTAT_SHOPPING_BAGS = 0x40,\n\tSTAT_GUN_PANIC = 0x80\n};\n\nclass CPedStats\n{\npublic:\n\tePedStats m_type;\n\tchar m_name[24];\n\tfloat m_fleeDistance;\n\tfloat m_headingChangeRate;\n\tint8 m_fear;\n\tint8 m_temper;\n\tint8 m_lawfulness;\n\tint8 m_sexiness;\n\tfloat m_attackStrength;\n\tfloat m_defendWeakness;\n\tint16 m_flags;\n\n\tstatic CPedStats *ms_apPedStats[NUM_PEDSTATS];\n\n\tstatic void Initialise(void);\n\tstatic void Shutdown(void);\n\tstatic void LoadPedStats(void);\n\tstatic ePedStats GetPedStatType(char *name);\n};\n\nVALIDATE_SIZE(CPedStats, 0x34);\n"
  },
  {
    "path": "src/peds/PlayerPed.cpp",
    "content": "#include \"common.h\"\n\n#include \"RwHelper.h\"\n#include \"PlayerPed.h\"\n#include \"Wanted.h\"\n#include \"Fire.h\"\n#include \"DMAudio.h\"\n#include \"Pad.h\"\n#include \"Camera.h\"\n#include \"WeaponEffects.h\"\n#include \"ModelIndices.h\"\n#include \"World.h\"\n#include \"RpAnimBlend.h\"\n#include \"AnimBlendAssociation.h\"\n#include \"General.h\"\n#include \"Pools.h\"\n#include \"Darkel.h\"\n#include \"CarCtrl.h\"\n#include \"MBlur.h\"\n#include \"Streaming.h\"\n#include \"Population.h\"\n#include \"Script.h\"\n#include \"Replay.h\"\n#include \"PedPlacement.h\"\n#include \"VarConsole.h\"\n\n#define PAD_MOVE_TO_GAME_WORLD_MOVE 60.0f\n\nbool CPlayerPed::bDontAllowWeaponChange;\n#ifndef MASTER\nbool CPlayerPed::bDebugPlayerInfo;\n#endif\n\nconst uint32 CPlayerPed::nSaveStructSize =\n#ifdef COMPATIBLE_SAVES\n\t1752;\n#else\n\tsizeof(CPlayerPed);\n#endif\n\nint32 idleAnimBlockIndex;\n\nCPad*\nGetPadFromPlayer(CPlayerPed*)\n{\n\treturn CPad::GetPad(0);\n}\n\nCPlayerPed::~CPlayerPed()\n{\n\tdelete m_pWanted;\n}\n\nCPlayerPed::CPlayerPed(void) : CPed(PEDTYPE_PLAYER1)\n{\n\tm_fMoveSpeed = 0.0f;\n\tSetModelIndex(MI_PLAYER);\n#ifdef FIX_BUGS\n\tm_fCurrentStamina = m_fMaxStamina = 150.0f;\n#endif\n\tSetInitialState();\n\n\tm_pWanted = new CWanted();\n\tm_pWanted->Initialise();\n\tm_pArrestingCop = nil;\n\tm_currentWeapon = WEAPONTYPE_UNARMED;\n\tm_nSelectedWepSlot = WEAPONSLOT_UNARMED;\n\tm_nSpeedTimer = 0;\n\tm_bSpeedTimerFlag = false;\n\tSetWeaponLockOnTarget(nil);\n\tSetPedState(PED_IDLE);\n#ifndef FIX_BUGS\n\tm_fCurrentStamina = m_fMaxStamina = 150.0f;\n#endif\n\tm_fStaminaProgress = 0.0f;\n\tm_nEvadeAmount = 0;\n\tm_pEvadingFrom = nil;\n\tm_nHitAnimDelayTimer = 0;\n\tm_fAttackButtonCounter = 0.0f;\n\tm_bHaveTargetSelected = false;\n\tm_bHasLockOnTarget = false;\n\tm_bCanBeDamaged = true;\n\tm_bNoPosForMeleeAttack = false;\n\tm_fWalkAngle = 0.0f;\n\tm_fFPSMoveHeading = 0.0f;\n\tm_pMinigunTopAtomic = nil;\n\tm_fGunSpinSpeed = 0.0;\n\tm_fGunSpinAngle = 0.0;\n\tm_nPadDownPressedInMilliseconds = 0;\n\tm_nTargettableObjects[0] = m_nTargettableObjects[1] = m_nTargettableObjects[2] = m_nTargettableObjects[3] = -1;\n\tunk1 = false;\n\tfor (int i = 0; i < 6; i++) {\n\t\tm_vecSafePos[i] = CVector(0.0f, 0.0f, 0.0f);\n\t\tm_pPedAtSafePos[i] = nil;\n\t\tm_pMeleeList[i] = nil;\n\t}\n\tm_nAttackDirToCheck = 0;\n\tm_nLastBusFareCollected = 0;\n\tidleAnimBlockIndex = CAnimManager::GetAnimationBlockIndex(\"playidles\");\n}\n\nvoid\nCPlayerPed::ClearWeaponTarget()\n{\n\tif (m_nPedType == PEDTYPE_PLAYER1) {\n\t\tSetWeaponLockOnTarget(nil);\n\t\tTheCamera.ClearPlayerWeaponMode();\n\t\tCWeaponEffects::ClearCrossHair();\n\t}\n \tClearPointGunAt();\n}\n\nvoid\nCPlayerPed::SetWantedLevel(int32 level)\n{\n\tm_pWanted->SetWantedLevel(level);\n}\n\nvoid\nCPlayerPed::SetWantedLevelNoDrop(int32 level)\n{\n\tm_pWanted->SetWantedLevelNoDrop(level);\n}\n\nvoid\nCPlayerPed::MakeObjectTargettable(int32 handle)\n{\n\tfor (int i = 0; i < ARRAY_SIZE(m_nTargettableObjects); i++) {\n\t\tif (CPools::GetObjectPool()->GetAt(m_nTargettableObjects[i]) == nil) {\n\t\t\tm_nTargettableObjects[i] = handle;\n\t\t\treturn;\n\t\t}\n\t}\n}\n\n// I don't know the actual purpose of parameter\nvoid\nCPlayerPed::AnnoyPlayerPed(bool annoyedByPassingEntity)\n{\n\tif (m_pedStats->m_temper < 52) {\n\t\tm_pedStats->m_temper++;\n\t} else if (annoyedByPassingEntity && m_pedStats->m_temper < 55) {\n\t\tm_pedStats->m_temper++;\n\t} else if (annoyedByPassingEntity) {\n\t\tm_pedStats->m_temper = 46;\n\t}\n}\n\nvoid\nCPlayerPed::ClearAdrenaline(void)\n{\n\tif (m_bAdrenalineActive && m_nAdrenalineTime != 0) {\n\t\tm_nAdrenalineTime = 0;\n\t\tCTimer::SetTimeScale(1.0f);\n\t}\n}\n\nCPlayerInfo *\nCPlayerPed::GetPlayerInfoForThisPlayerPed()\n{\n\tif (CWorld::Players[0].m_pPed == this)\n\t\treturn &CWorld::Players[0];\n\n\treturn nil;\n}\n\nvoid\nCPlayerPed::SetupPlayerPed(int32 index)\n{\n\tCPlayerPed *player = new CPlayerPed();\n\tCWorld::Players[index].m_pPed = player;\n#ifdef FIX_BUGS\n\tplayer->RegisterReference((CEntity**)&CWorld::Players[index].m_pPed);\n#endif\n\n\tplayer->SetOrientation(0.0f, 0.0f, 0.0f);\n\n\tCWorld::Add(player);\n\tplayer->m_wepAccuracy = 100;\n\n#ifndef MASTER\n\tVarConsole.Add(\"Debug PlayerPed\", &CPlayerPed::bDebugPlayerInfo, true);\n\tVarConsole.Add(\"Tweak Vehicle Handling\", &CVehicle::m_bDisplayHandlingInfo, true);\n#endif\n}\n\nvoid\nCPlayerPed::DeactivatePlayerPed(int32 index)\n{\n\tCWorld::Remove(CWorld::Players[index].m_pPed);\n}\n\nvoid\nCPlayerPed::ReactivatePlayerPed(int32 index)\n{\n\tCWorld::Add(CWorld::Players[index].m_pPed);\n}\n\nvoid\nCPlayerPed::UseSprintEnergy(void)\n{\n\tif (m_fCurrentStamina > -150.0f && !CWorld::Players[CWorld::PlayerInFocus].m_bInfiniteSprint\n\t\t&& !m_bAdrenalineActive) {\n\t\tm_fCurrentStamina = m_fCurrentStamina - CTimer::GetTimeStep();\n\t\tm_fStaminaProgress = m_fStaminaProgress + CTimer::GetTimeStep();\n\t}\n\n\tif (m_fStaminaProgress >= 500.0f) {\n\t\tm_fStaminaProgress = 0;\n\t\tif (m_fMaxStamina < 1000.0f)\n\t\t\tm_fMaxStamina += 10.0f;\n\t}\n}\n\nvoid\nCPlayerPed::MakeChangesForNewWeapon(eWeaponType weapon)\n{\n\tif (m_nPedState == PED_SNIPER_MODE) {\n\t\tRestorePreviousState();\n\t\tTheCamera.ClearPlayerWeaponMode();\n\t}\n\tSetCurrentWeapon(weapon);\n\tm_nSelectedWepSlot = m_currentWeapon;\n\n\tGetWeapon()->m_nAmmoInClip = Min(GetWeapon()->m_nAmmoTotal, CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->m_nAmountofAmmunition);\n\n\tif (CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->IsFlagSet(WEAPONFLAG_CANAIM))\n\t\tClearWeaponTarget();\n\n\t// WEAPONTYPE_SNIPERRIFLE? Wut?\n\tCAnimBlendAssociation* weaponAnim = RpAnimBlendClumpGetAssociation(GetClump(), GetPrimaryFireAnim(CWeaponInfo::GetWeaponInfo(WEAPONTYPE_SNIPERRIFLE)));\n\tif (weaponAnim) {\n\t\tweaponAnim->SetRun();\n\t\tweaponAnim->flags |= ASSOC_FADEOUTWHENDONE;\n\t}\n\tTheCamera.ClearPlayerWeaponMode();\n}\n\nvoid\nCPlayerPed::MakeChangesForNewWeapon(int32 slot)\n{\n\tif(slot != -1)\n\t\tMakeChangesForNewWeapon(m_weapons[slot].m_eWeaponType);\n}\n\nvoid\nCPlayerPed::ReApplyMoveAnims(void)\n{\n\tstatic AnimationId moveAnims[] = { ANIM_STD_WALK, ANIM_STD_RUN, ANIM_STD_RUNFAST, ANIM_STD_IDLE, ANIM_STD_STARTWALK };\n\n\tfor(int i = 0; i < ARRAY_SIZE(moveAnims); i++) {\n\t\tCAnimBlendAssociation *curMoveAssoc = RpAnimBlendClumpGetAssociation(GetClump(), moveAnims[i]);\n\t\tif (curMoveAssoc) {\n\t\t\tif (CGeneral::faststrcmp(CAnimManager::GetAnimAssociation(m_animGroup, moveAnims[i])->hierarchy->name, curMoveAssoc->hierarchy->name)) {\n\t\t\t\tCAnimBlendAssociation *newMoveAssoc = CAnimManager::AddAnimation(GetClump(), m_animGroup, moveAnims[i]);\n\t\t\t\tnewMoveAssoc->blendDelta = curMoveAssoc->blendDelta;\n\t\t\t\tnewMoveAssoc->blendAmount = curMoveAssoc->blendAmount;\n\t\t\t\tcurMoveAssoc->blendDelta = -1000.0f;\n\t\t\t\tcurMoveAssoc->flags |= ASSOC_DELETEFADEDOUT;\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nCPlayerPed::SetInitialState(void)\n{\n\tm_nDrunkenness = 0;\n\tm_nFadeDrunkenness = 0;\n\tCMBlur::ClearDrunkBlur();\n\tm_nDrunkCountdown = 0;\n\tm_bAdrenalineActive = false;\n\tm_nAdrenalineTime = 0;\n\tCTimer::SetTimeScale(1.0f);\n\tm_pSeekTarget = nil;\n\tm_vecSeekPos = CVector(0.0f, 0.0f, 0.0f);\n\tm_fleeFromPos = CVector2D(0.0f, 0.0f);\n\tm_fleeFrom = nil;\n\tm_fleeTimer = 0;\n\tm_objective = OBJECTIVE_NONE;\n\tm_prevObjective = OBJECTIVE_NONE;\n\tbUsesCollision = true;\n\tClearAimFlag();\n\tClearLookFlag();\n\tbIsPointingGunAt = false;\n\tbRenderPedInCar = true;\n\tif (m_pFire)\n\t\tm_pFire->Extinguish();\n\n\tRpAnimBlendClumpRemoveAllAssociations(GetClump());\n\tSetPedState(PED_IDLE);\n\tSetMoveState(PEDMOVE_STILL);\n\tm_nLastPedState = PED_NONE;\n\tm_animGroup = ASSOCGRP_PLAYER;\n\tm_fMoveSpeed = 0.0f;\n\tm_nSelectedWepSlot = WEAPONSLOT_UNARMED;\n\tm_nEvadeAmount = 0;\n\tm_pEvadingFrom = nil;\n\tbIsPedDieAnimPlaying = false;\n\tSetRealMoveAnim();\n\tm_bCanBeDamaged = true;\n\tm_pedStats->m_temper = 50;\n\tm_fWalkAngle = 0.0f;\n\tif (m_attachedTo && !bUsesCollision)\n\t\tbUsesCollision = true;\n\n\tm_attachedTo = nil;\n\tm_attachWepAmmo = 0;\n}\n\nvoid\nCPlayerPed::SetRealMoveAnim(void)\n{\n\tCAnimBlendAssociation *curWalkAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_WALK);\n\tCAnimBlendAssociation *curRunAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_RUN);\n\tCAnimBlendAssociation *curSprintAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_RUNFAST);\n\tCAnimBlendAssociation *curWalkStartAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_STARTWALK);\n\tCAnimBlendAssociation *curIdleAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_IDLE);\n\tCAnimBlendAssociation *curRunStopAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_RUNSTOP1);\n\tCAnimBlendAssociation *curRunStopRAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_RUNSTOP2);\n\tif (bResetWalkAnims) {\n\t\tif (curWalkAssoc)\n\t\t\tcurWalkAssoc->SetCurrentTime(0.0f);\n\t\tif (curRunAssoc)\n\t\t\tcurRunAssoc->SetCurrentTime(0.0f);\n\t\tif (curSprintAssoc)\n\t\t\tcurSprintAssoc->SetCurrentTime(0.0f);\n\t\tbResetWalkAnims = false;\n\t}\n\n\tif (!curIdleAssoc)\n\t\tcurIdleAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_IDLE_TIRED);\n\tif (!curIdleAssoc)\n\t\tcurIdleAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_FIGHT_IDLE);\n\tif (!curIdleAssoc)\n\t\tcurIdleAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_MELEE_IDLE_FIGHTMODE);\n\n\tif (!((curRunStopAssoc && curRunStopAssoc->IsRunning()) || (curRunStopRAssoc && curRunStopRAssoc->IsRunning()))) {\n\n\t\tif (curRunStopAssoc && curRunStopAssoc->blendDelta >= 0.0f || curRunStopRAssoc && curRunStopRAssoc->blendDelta >= 0.0f) {\n\t\t\tif (curRunStopAssoc) {\n\t\t\t\tcurRunStopAssoc->flags |= ASSOC_DELETEFADEDOUT;\n\t\t\t\tcurRunStopAssoc->blendAmount = 1.0f;\n\t\t\t\tcurRunStopAssoc->blendDelta = -8.0f;\n\t\t\t} else if (curRunStopRAssoc) {\n\t\t\t\tcurRunStopRAssoc->flags |= ASSOC_DELETEFADEDOUT;\n\t\t\t\tcurRunStopRAssoc->blendAmount = 1.0f;\n\t\t\t\tcurRunStopRAssoc->blendDelta = -8.0f;\n\t\t\t}\n\t\t\t\n\t\t\tRestoreHeadingRate();\n\t\t\tif (!curIdleAssoc) {\n\t\t\t\tif (m_fCurrentStamina < 0.0f && !bIsAimingGun && !CWorld::TestSphereAgainstWorld(GetPosition(), 0.5f,\n\t\t\t\t\t\tnil, true, false, false, false, false, false)) {\n\t\t\t\t\tcurIdleAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_IDLE_TIRED, 8.0f);\n\n\t\t\t\t} else {\n\t\t\t\t\tcurIdleAssoc = CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_STD_IDLE, 8.0f);\n\t\t\t\t}\n\t\t\t\tm_nWaitTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(2500, 4000);\n\t\t\t}\n\t\t\tcurIdleAssoc->blendAmount = 0.0f;\n\t\t\tcurIdleAssoc->blendDelta = 8.0f;\n\n\t\t} else if (m_fMoveSpeed == 0.0f && !curSprintAssoc) {\n\t\t\tif (!curIdleAssoc) {\n\t\t\t\tif (m_fCurrentStamina < 0.0f && !bIsAimingGun && !CWorld::TestSphereAgainstWorld(GetPosition(), 0.5f,\n\t\t\t\t\t\tnil, true, false, false, false, false, false)) {\n\t\t\t\t\tcurIdleAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_IDLE_TIRED, 4.0f);\n\t\t\t\t\t\n\t\t\t\t} else {\n\t\t\t\t\tcurIdleAssoc = CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_STD_IDLE, 4.0f);\n\t\t\t\t}\n\n\t\t\t\tm_nWaitTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(2500, 4000);\n\t\t\t}\n\n\t\t\tif ((m_fCurrentStamina > 0.0f || bIsAimingGun) && curIdleAssoc->animId == ANIM_STD_IDLE_TIRED) {\n\t\t\t\tCAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_STD_IDLE, 4.0f);\n\n\t\t\t} else if (m_nPedState != PED_FIGHT) {\n\t\t\t\tif (m_fCurrentStamina < 0.0f && !bIsAimingGun && curIdleAssoc->animId != ANIM_STD_IDLE_TIRED\n\t\t\t\t\t&& !CWorld::TestSphereAgainstWorld(GetPosition(), 0.5f, nil, true, false, false, false, false, false)) {\n\t\t\t\t\tCAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_IDLE_TIRED, 4.0f);\n\n\t\t\t\t} else if (curIdleAssoc->animId != ANIM_STD_IDLE) {\n\t\t\t\t\tCAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_STD_IDLE, 4.0f);\n\t\t\t\t}\n\t\t\t}\n\t\t\tm_nMoveState = PEDMOVE_STILL;\n\n\t\t} else {\n\t\t\tif (curIdleAssoc) {\n\t\t\t\tif (curWalkStartAssoc) {\n\t\t\t\t\tcurWalkStartAssoc->blendAmount = 1.0f;\n\t\t\t\t\tcurWalkStartAssoc->blendDelta = 0.0f;\n\t\t\t\t} else {\n\t\t\t\t\tcurWalkStartAssoc = CAnimManager::AddAnimation(GetClump(), m_animGroup, ANIM_STD_STARTWALK);\n\t\t\t\t}\n\t\t\t\tif (curWalkAssoc)\n\t\t\t\t\tcurWalkAssoc->SetCurrentTime(0.0f);\n\t\t\t\tif (curRunAssoc)\n\t\t\t\t\tcurRunAssoc->SetCurrentTime(0.0f);\n\n\t\t\t\tdelete curIdleAssoc;\n\t\t\t\tdelete RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_IDLE_TIRED);\n\t\t\t\tCAnimBlendAssociation *fightIdleAnim = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_FIGHT_IDLE);\n\t\t\t\tif (!fightIdleAnim)\n\t\t\t\t\tfightIdleAnim = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_MELEE_IDLE_FIGHTMODE);\n\t\t\t\tdelete fightIdleAnim;\n\t\t\t\tdelete curSprintAssoc;\n\n\t\t\t\tcurSprintAssoc = nil;\n\t\t\t\tm_nMoveState = PEDMOVE_WALK;\n\t\t\t}\n\t\t\tif (curRunStopAssoc) {\n\t\t\t\tdelete curRunStopAssoc;\n\t\t\t\tRestoreHeadingRate();\n\t\t\t}\n\t\t\tif (curRunStopRAssoc) {\n\t\t\t\tdelete curRunStopRAssoc;\n\t\t\t\tRestoreHeadingRate();\n\t\t\t}\n\t\t\tif (!curWalkAssoc) {\n\t\t\t\tcurWalkAssoc = CAnimManager::AddAnimation(GetClump(), m_animGroup, ANIM_STD_WALK);\n\t\t\t\tcurWalkAssoc->blendAmount = 0.0f;\n\t\t\t}\n\t\t\tif (!curRunAssoc) {\n\t\t\t\tcurRunAssoc = CAnimManager::AddAnimation(GetClump(), m_animGroup, ANIM_STD_RUN);\n\t\t\t\tcurRunAssoc->blendAmount = 0.0f;\n\t\t\t}\n\t\t\tif (curWalkStartAssoc && !(curWalkStartAssoc->IsRunning())) {\n\t\t\t\tdelete curWalkStartAssoc;\n\t\t\t\tcurWalkStartAssoc = nil;\n\t\t\t\tcurWalkAssoc->SetRun();\n\t\t\t\tcurRunAssoc->SetRun();\n\t\t\t}\n\t\t\tif (m_nMoveState == PEDMOVE_SPRINT) {\n\t\t\t\tif (m_fCurrentStamina < 0.0f && (m_fCurrentStamina <= -150.0f || !curSprintAssoc || curSprintAssoc->blendDelta < 0.0f))\n\t\t\t\t\tm_nMoveState = PEDMOVE_STILL;\n\n\t\t\t\tif (curWalkStartAssoc)\n\t\t\t\t\tm_nMoveState = PEDMOVE_STILL;\n\t\t\t}\n\n\t\t\tif (curSprintAssoc && (m_nMoveState != PEDMOVE_SPRINT || m_fMoveSpeed < 0.4f)) {\n\t\t\t\t// Stop sprinting in various conditions\n\t\t\t\tif (curSprintAssoc->blendAmount == 0.0f) {\n\t\t\t\t\tcurSprintAssoc->blendDelta = -1000.0f;\n\t\t\t\t\tcurSprintAssoc->flags |= ASSOC_DELETEFADEDOUT;\n\n\t\t\t\t} else if (curSprintAssoc->blendDelta >= 0.0f || curSprintAssoc->blendAmount >= 0.8f) {\n\t\t\t\t\tif (m_fMoveSpeed < 0.4f) {\n\t\t\t\t\t\tAnimationId runStopAnim;\n\t\t\t\t\t\tif (curSprintAssoc->GetProgress() < 0.5) // double\n\t\t\t\t\t\t\trunStopAnim = ANIM_STD_RUNSTOP1;\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\trunStopAnim = ANIM_STD_RUNSTOP2;\n\t\t\t\t\t\tCAnimBlendAssociation* newRunStopAssoc = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, runStopAnim);\n\t\t\t\t\t\tnewRunStopAssoc->blendAmount = 1.0f;\n\t\t\t\t\t\tnewRunStopAssoc->SetDeleteCallback(RestoreHeadingRateCB, this);\n\t\t\t\t\t\tm_headingRate = 0.0f;\n\t\t\t\t\t\tcurSprintAssoc->flags |= ASSOC_DELETEFADEDOUT;\n\t\t\t\t\t\tcurSprintAssoc->blendDelta = -1000.0f;\n\t\t\t\t\t\tcurWalkAssoc->flags &= ~ASSOC_RUNNING;\n\t\t\t\t\t\tcurWalkAssoc->blendAmount = 0.0f;\n\t\t\t\t\t\tcurWalkAssoc->blendDelta = 0.0f;\n\t\t\t\t\t\tcurRunAssoc->flags &= ~ASSOC_RUNNING;\n\t\t\t\t\t\tcurRunAssoc->blendAmount = 0.0f;\n\t\t\t\t\t\tcurRunAssoc->blendDelta = 0.0f;\n\n\t\t\t\t\t} else if (curSprintAssoc->blendDelta >= 0.0f) { // this condition is absent on mobile\n\t\t\t\t\t\t// Stop sprinting when tired\n\t\t\t\t\t\tcurSprintAssoc->flags |= ASSOC_DELETEFADEDOUT;\n\t\t\t\t\t\tcurSprintAssoc->blendDelta = -1.0f;\n\t\t\t\t\t\tcurRunAssoc->blendDelta = 1.0f;\n\t\t\t\t\t}\n\t\t\t\t} else if (m_fMoveSpeed < 1.0f) {\n\t\t\t\t\tcurSprintAssoc->blendDelta = -8.0f;\n\t\t\t\t\tcurRunAssoc->blendDelta = 8.0f;\n\t\t\t\t}\n\n\t\t\t} else if (curWalkStartAssoc) {\n\t\t\t\t// Walk start and walk/run shouldn't run at the same time\n\t\t\t\tcurWalkAssoc->flags &= ~ASSOC_RUNNING;\n\t\t\t\tcurRunAssoc->flags &= ~ASSOC_RUNNING;\n\t\t\t\tcurWalkAssoc->blendAmount = 0.0f;\n\t\t\t\tcurRunAssoc->blendAmount = 0.0f;\n\n\t\t\t} else if (m_nMoveState == PEDMOVE_SPRINT) {\n\t\t\t\tif (curSprintAssoc) {\n\t\t\t\t\t// We have anim, do it\n\t\t\t\t\tif (curSprintAssoc->blendDelta < 0.0f) {\n\t\t\t\t\t\tcurSprintAssoc->blendDelta = 2.0f;\n\t\t\t\t\t\tcurRunAssoc->blendDelta = -2.0f;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// Transition between run-sprint\n\t\t\t\t\tcurWalkAssoc->blendAmount = 0.0f;\n\t\t\t\t\tcurRunAssoc->blendAmount = 1.0f;\n\t\t\t\t\tcurSprintAssoc = CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_STD_RUNFAST, 2.0f);\n\t\t\t\t}\n\t\t\t\tUseSprintEnergy();\n\t\t\t} else {\n\t\t\t\tif (m_fMoveSpeed < 1.0f) {\n\t\t\t\t\tcurWalkAssoc->blendAmount = 1.0f;\n\t\t\t\t\tcurRunAssoc->blendAmount = 0.0f;\n\t\t\t\t\tm_nMoveState = PEDMOVE_WALK;\n\t\t\t\t} else if (m_fMoveSpeed < 2.0f) {\n\t\t\t\t\tcurWalkAssoc->blendAmount = 2.0f - m_fMoveSpeed;\n\t\t\t\t\tcurRunAssoc->blendAmount = m_fMoveSpeed - 1.0f;\n\t\t\t\t\tm_nMoveState = PEDMOVE_RUN;\n\t\t\t\t} else {\n\t\t\t\t\tcurWalkAssoc->blendAmount = 0.0f;\n\t\t\t\t\tcurRunAssoc->blendAmount = 1.0f;\n\t\t\t\t\tm_nMoveState = PEDMOVE_RUN;\n\t\t\t\t}\n\t\t\t\tcurWalkAssoc->blendDelta = 0.0f;\n\t\t\t\tcurRunAssoc->blendDelta = 0.0f;\n\t\t\t}\n\t\t}\n\t}\n\tif (m_bAdrenalineActive) {\n\t\tif (CTimer::GetTimeInMilliseconds() > m_nAdrenalineTime) {\n\t\t\tm_bAdrenalineActive = false;\n\t\t\tCTimer::SetTimeScale(1.0f);\n\t\t\tif (curWalkStartAssoc)\n\t\t\t\tcurWalkStartAssoc->speed = 1.0f;\n\t\t\tif (curWalkAssoc)\n\t\t\t\tcurWalkAssoc->speed = 1.0f;\n\t\t\tif (curRunAssoc)\n\t\t\t\tcurRunAssoc->speed = 1.0f;\n\t\t\tif (curSprintAssoc)\n\t\t\t\tcurSprintAssoc->speed = 1.0f;\n\t\t} else {\n\t\t\tCTimer::SetTimeScale(1.0f / 3);\n\t\t\tif (curWalkStartAssoc)\n\t\t\t\tcurWalkStartAssoc->speed = 2.0f;\n\t\t\tif (curWalkAssoc)\n\t\t\t\tcurWalkAssoc->speed = 2.0f;\n\t\t\tif (curRunAssoc)\n\t\t\t\tcurRunAssoc->speed = 2.0f;\n\t\t\tif (curSprintAssoc)\n\t\t\t\tcurSprintAssoc->speed = 2.0f;\n\t\t}\n\t} else if (curSprintAssoc) {\n\t\tif (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_FIXED) {\n\t\t\tcurSprintAssoc->speed = 0.7f;\n\t\t} else\n\t\t\tcurSprintAssoc->speed = 1.0f;\n\t}\n}\n\nvoid\nCPlayerPed::RestoreSprintEnergy(float restoreSpeed)\n{\n\tif (m_fCurrentStamina < m_fMaxStamina)\n\t\tm_fCurrentStamina += restoreSpeed * CTimer::GetTimeStep() * 0.5f;\n}\n\nfloat\nCPlayerPed::DoWeaponSmoothSpray(void)\n{\n\tif (m_nPedState == PED_ATTACK && !m_pPointGunAt) {\n\t\tCWeaponInfo *weaponInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);\n\t\tswitch (GetWeapon()->m_eWeaponType) {\n\t\t\tcase WEAPONTYPE_GOLFCLUB:\n\t\t\tcase WEAPONTYPE_NIGHTSTICK:\n\t\t\tcase WEAPONTYPE_BASEBALLBAT:\n\t\t\t\tif (GetFireAnimGround(weaponInfo, false) && RpAnimBlendClumpGetAssociation(GetClump(), GetFireAnimGround(weaponInfo, false)))\n\t\t\t\t\treturn PI / 176.f;\n\t\t\t\telse\n\t\t\t\t\treturn -1.0f;\n\n\t\t\tcase WEAPONTYPE_CHAINSAW:\n\t\t\t\tif (GetMeleeStartAnim(weaponInfo) && RpAnimBlendClumpGetAssociation(GetClump(), GetMeleeStartAnim(weaponInfo)))\n\t\t\t\t\treturn PI / 128.0f;\n\t\t\t\telse if (GetFireAnimGround(weaponInfo, false) && RpAnimBlendClumpGetAssociation(GetClump(), GetFireAnimGround(weaponInfo, false)))\n\t\t\t\t\treturn PI / 176.f;\n\t\t\t\telse\n\t\t\t\t\treturn PI / 80.f;\n\n\t\t\tcase WEAPONTYPE_PYTHON:\n\t\t\t\treturn PI / 112.f;\n\t\t\tcase WEAPONTYPE_SHOTGUN:\n\t\t\tcase WEAPONTYPE_SPAS12_SHOTGUN:\n\t\t\tcase WEAPONTYPE_STUBBY_SHOTGUN:\n\t\t\t\treturn PI / 112.f;\n\t\t\tcase WEAPONTYPE_UZI:\n\t\t\tcase WEAPONTYPE_MP5:\n\t\t\t\treturn PI / 112.f;\n\t\t\tcase WEAPONTYPE_M4:\n\t\t\tcase WEAPONTYPE_RUGER:\n\t\t\t\treturn PI / 112.f;\n\t\t\tcase WEAPONTYPE_FLAMETHROWER:\n\t\t\t\treturn PI / 80.f;\n\t\t\tcase WEAPONTYPE_M60:\n\t\t\tcase WEAPONTYPE_MINIGUN:\n\t\t\tcase WEAPONTYPE_HELICANNON:\n\t\t\t\treturn PI / 176.f;\n\t\t\tdefault:\n\t\t\t\treturn -1.0f;\n\t\t}\n\t} else if (bIsDucking)\n\t\treturn PI / 112.f;\n\telse\n\t\treturn -1.0f;\n}\n\nvoid\nCPlayerPed::DoStuffToGoOnFire(void)\n{\n\tif (m_nPedState == PED_SNIPER_MODE)\n\t\tTheCamera.ClearPlayerWeaponMode();\n}\n\nbool\nCPlayerPed::DoesTargetHaveToBeBroken(CVector target, CWeapon *weaponUsed)\n{\n\tCVector distVec = target - GetPosition();\n\n\tif (distVec.Magnitude() > CWeaponInfo::GetWeaponInfo(weaponUsed->m_eWeaponType)->m_fRange)\n\t\treturn true;\n\n\treturn false;\n}\n\n// Cancels landing anim while running & jumping? I think\nvoid\nCPlayerPed::RunningLand(CPad *padUsed)\n{\n\tCAnimBlendAssociation *landAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_FALL_LAND);\n\tif (landAssoc && landAssoc->currentTime == 0.0f && m_fMoveSpeed > 1.5f\n\t\t&& padUsed && (padUsed->GetPedWalkLeftRight() != 0.0f || padUsed->GetPedWalkUpDown() != 0.0f)) {\n\n\t\tlandAssoc->blendDelta = -1000.0f;\n\t\tlandAssoc->flags |= ASSOC_DELETEFADEDOUT;\n\n\t\tCAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_JUMP_LAND)->SetFinishCallback(FinishJumpCB, this);\n\n\t\tif (m_nPedState == PED_JUMP)\n\t\t\tRestorePreviousState();\n\t}\n}\n\nbool\nCPlayerPed::IsThisPedAnAimingPriority(CPed *suspect)\n{\n\tif (!suspect->bIsPlayerFriend)\n\t\treturn true;\n\n\tif (suspect->m_pPointGunAt == this)\n\t\treturn true;\n\n\tswitch (suspect->m_objective) {\n\t\tcase OBJECTIVE_KILL_CHAR_ON_FOOT:\n\t\tcase OBJECTIVE_KILL_CHAR_ANY_MEANS:\n\t\t\tif (suspect->m_pedInObjective == this)\n\t\t\t\treturn true;\n\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\treturn suspect->m_nPedState == PED_ABSEIL;\n}\n\nvoid\nCPlayerPed::PlayerControlSniper(CPad *padUsed)\n{\n\tProcessWeaponSwitch(padUsed);\n\tTheCamera.PlayerExhaustion = (1.0f - (m_fCurrentStamina - -150.0f) / 300.0f) * 0.9f + 0.1f;\n\n\tif (padUsed->DuckJustDown() && !bIsDucking && m_nMoveState != PEDMOVE_SPRINT) {\n\t\tbCrouchWhenShooting = true;\n\t\tSetDuck(60000, true);\n\t} else if (bIsDucking && (padUsed->DuckJustDown() || m_nMoveState == PEDMOVE_SPRINT)) {\n\t\tClearDuck(true);\n\t\tbCrouchWhenShooting = false;\n\t}\n\n\tif (!padUsed->GetTarget() && !m_attachedTo) {\n\t\tRestorePreviousState();\n\t\tTheCamera.ClearPlayerWeaponMode();\n\t\treturn;\n\t}\n\n\tint firingRate = GetWeapon()->m_eWeaponType == WEAPONTYPE_LASERSCOPE ? 333 : 266;\n\tif (padUsed->WeaponJustDown() && CTimer::GetTimeInMilliseconds() > GetWeapon()->m_nTimer) {\n\t\tCVector firePos(0.0f, 0.0f, 0.6f);\n\t\tfirePos = GetMatrix() * firePos;\n\t\tGetWeapon()->Fire(this, &firePos);\n\t\tm_nPadDownPressedInMilliseconds = CTimer::GetTimeInMilliseconds();\n\t} else if (CTimer::GetTimeInMilliseconds() > m_nPadDownPressedInMilliseconds + firingRate &&\n\t\tCTimer::GetTimeInMilliseconds() - CTimer::GetTimeStepInMilliseconds() < m_nPadDownPressedInMilliseconds + firingRate && padUsed->GetWeapon()) {\n\t\t\n\t\tif (GetWeapon()->m_nAmmoTotal > 0) {\n\t\t\tDMAudio.PlayFrontEndSound(SOUND_WEAPON_AK47_BULLET_ECHO, GetWeapon()->m_eWeaponType);\n\t\t}\n\t}\n\tGetWeapon()->Update(m_audioEntityId, nil);\n}\n\n// I think R* also used goto in here.\nvoid\nCPlayerPed::ProcessWeaponSwitch(CPad *padUsed)\n{\n\tif (CDarkel::FrenzyOnGoing() || m_attachedTo)\n\t\tgoto switchDetectDone;\n\n\tif (!m_pPointGunAt && !bDontAllowWeaponChange && GetWeapon()->m_eWeaponType != WEAPONTYPE_DETONATOR) {\n\t\tif (padUsed->CycleWeaponRightJustDown()) {\n\n\t\t\tif (TheCamera.PlayerWeaponMode.Mode != CCam::MODE_M16_1STPERSON\n\t\t\t\t&& TheCamera.PlayerWeaponMode.Mode != CCam::MODE_M16_1STPERSON_RUNABOUT\n\t\t\t\t&& TheCamera.PlayerWeaponMode.Mode != CCam::MODE_SNIPER\n\t\t\t\t&& TheCamera.PlayerWeaponMode.Mode != CCam::MODE_SNIPER_RUNABOUT\n\t\t\t\t&& TheCamera.PlayerWeaponMode.Mode != CCam::MODE_ROCKETLAUNCHER\n\t\t\t\t&& TheCamera.PlayerWeaponMode.Mode != CCam::MODE_ROCKETLAUNCHER_RUNABOUT\n\t\t\t\t&& TheCamera.PlayerWeaponMode.Mode != CCam::MODE_CAMERA) {\n\n\t\t\t\tfor (m_nSelectedWepSlot = m_currentWeapon + 1; m_nSelectedWepSlot < TOTAL_WEAPON_SLOTS; ++m_nSelectedWepSlot) {\n\t\t\t\t\tif (HasWeaponSlot(m_nSelectedWepSlot) && GetWeapon(m_nSelectedWepSlot).HasWeaponAmmoToBeUsed()) {\n\t\t\t\t\t\tgoto spentAmmoCheck;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tm_nSelectedWepSlot = 0;\n\t\t\t}\n\t\t} else if (padUsed->CycleWeaponLeftJustDown()) {\n\t\t\tif (TheCamera.PlayerWeaponMode.Mode != CCam::MODE_M16_1STPERSON\n\t\t\t\t&& TheCamera.PlayerWeaponMode.Mode != CCam::MODE_SNIPER\n\t\t\t\t&& TheCamera.PlayerWeaponMode.Mode != CCam::MODE_ROCKETLAUNCHER\n\t\t\t\t&& TheCamera.PlayerWeaponMode.Mode != CCam::MODE_CAMERA) {\n\n\t\t\t\t// I don't know what kind of loop that was\n\t\t\t\tm_nSelectedWepSlot = m_currentWeapon - 1;\n\t\t\t\tdo {\n\t\t\t\t\tif (m_nSelectedWepSlot < 0)\n\t\t\t\t\t\tm_nSelectedWepSlot = TOTAL_WEAPON_SLOTS - 1;\n\n\t\t\t\t\tif (m_nSelectedWepSlot == WEAPONSLOT_UNARMED)\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tif (HasWeaponSlot(m_nSelectedWepSlot) && GetWeapon(m_nSelectedWepSlot).HasWeaponAmmoToBeUsed())\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t\n\t\t\t\t\t--m_nSelectedWepSlot;\n\t\t\t\t} while (m_nSelectedWepSlot != WEAPONSLOT_UNARMED);\n\t\t\t}\n\t\t}\n\t}\n\t\nspentAmmoCheck:\n\tif (CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->m_eWeaponFire != WEAPON_FIRE_MELEE\n\t\t&& (!padUsed->GetWeapon() || GetWeapon()->m_eWeaponType != WEAPONTYPE_MINIGUN)) {\n\t\tif (GetWeapon()->m_nAmmoTotal <= 0) {\n\t\t\tif (TheCamera.PlayerWeaponMode.Mode == CCam::MODE_M16_1STPERSON\n\t\t\t\t|| TheCamera.PlayerWeaponMode.Mode == CCam::MODE_SNIPER\n\t\t\t\t|| TheCamera.PlayerWeaponMode.Mode == CCam::MODE_ROCKETLAUNCHER)\n\t\t\t\treturn;\n\n\t\t\tif (GetWeapon()->m_eWeaponType == WEAPONTYPE_DETONATOR\n\t\t\t\t&& GetWeapon(WEAPONSLOT_PROJECTILE).m_eWeaponType == WEAPONTYPE_DETONATOR_GRENADE)\n\t\t\t\tm_nSelectedWepSlot = WEAPONSLOT_PROJECTILE;\n\t\t\telse\n\t\t\t\tm_nSelectedWepSlot = m_currentWeapon - 1;\n\n\t\t\tfor (; m_nSelectedWepSlot >= WEAPONSLOT_UNARMED; --m_nSelectedWepSlot) {\n\n\t\t\t\t// BUG: m_nSelectedWepSlot and GetWeapon(..) takes slot in VC but they compared them against weapon types in whole condition! jeez\n#ifdef FIX_BUGS\n\t\t\t\tif (m_nSelectedWepSlot == WEAPONSLOT_MELEE || GetWeapon(m_nSelectedWepSlot).m_nAmmoTotal > 0 && m_nSelectedWepSlot != WEAPONSLOT_PROJECTILE) {\n#else\n\t\t\t\tif (m_nSelectedWepSlot == WEAPONTYPE_BASEBALLBAT && GetWeapon(WEAPONTYPE_BASEBALLBAT).m_eWeaponType == WEAPONTYPE_BASEBALLBAT\n\t\t\t\t\t|| GetWeapon(m_nSelectedWepSlot).m_nAmmoTotal > 0\n\t\t\t\t\t&& m_nSelectedWepSlot != WEAPONTYPE_MOLOTOV && m_nSelectedWepSlot != WEAPONTYPE_GRENADE && m_nSelectedWepSlot != WEAPONTYPE_TEARGAS) {\n#endif\n\t\t\t\t\tgoto switchDetectDone;\n\t\t\t\t}\n\t\t\t}\n\t\t\tm_nSelectedWepSlot = WEAPONSLOT_UNARMED;\n\t\t}\n\t}\n\nswitchDetectDone:\n\tif (m_nSelectedWepSlot != m_currentWeapon) {\n\t\tif (m_nPedState != PED_ATTACK && m_nPedState != PED_AIM_GUN && m_nPedState != PED_FIGHT) {\n\t\t\tRemoveWeaponAnims(m_currentWeapon, -1000.0f);\n\t\t\tMakeChangesForNewWeapon(m_nSelectedWepSlot);\n\t\t}\n\t}\n}\n\nvoid\nCPlayerPed::PlayerControlM16(CPad *padUsed)\n{\n\tProcessWeaponSwitch(padUsed);\n\tTheCamera.PlayerExhaustion = (1.0f - (m_fCurrentStamina - -150.0f) / 300.0f) * 0.9f + 0.1f;\n\n\tif (padUsed->DuckJustDown() && !bIsDucking && m_nMoveState != PEDMOVE_SPRINT) {\n\t\tbCrouchWhenShooting = true;\n\t\tSetDuck(60000, true);\n\t} else if (bIsDucking && (padUsed->DuckJustDown() || m_nMoveState == PEDMOVE_SPRINT)) {\n\t\tClearDuck(true);\n\t\tbCrouchWhenShooting = false;\n\t}\n\n\tif (!padUsed->GetTarget() && !m_attachedTo) {\n\t\tRestorePreviousState();\n\t\tTheCamera.ClearPlayerWeaponMode();\n\t}\n\n\tif (padUsed->GetWeapon() && CTimer::GetTimeInMilliseconds() > GetWeapon()->m_nTimer) {\n\t\tif (GetWeapon()->m_eWeaponState == WEAPONSTATE_OUT_OF_AMMO) {\n\t\t\tDMAudio.PlayFrontEndSound(SOUND_WEAPON_SNIPER_SHOT_NO_ZOOM, 0.f);\n\t\t\tGetWeapon()->m_nTimer = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->m_nFiringRate + CTimer::GetTimeInMilliseconds();\n\t\t} else {\n\t\t\tCVector firePos(0.0f, 0.0f, 0.6f);\n\t\t\tfirePos = GetMatrix() * firePos;\n\t\t\tGetWeapon()->Fire(this, &firePos);\n\t\t\tm_nPadDownPressedInMilliseconds = CTimer::GetTimeInMilliseconds();\n\t\t}\n\t} else if (CTimer::GetTimeInMilliseconds() > GetWeapon()->m_nTimer &&\n\t\tCTimer::GetTimeInMilliseconds() - CTimer::GetTimeStepInMilliseconds() < GetWeapon()->m_nTimer && GetWeapon()->m_eWeaponState != WEAPONSTATE_OUT_OF_AMMO) {\n\t\tDMAudio.PlayFrontEndSound(SOUND_WEAPON_AK47_BULLET_ECHO, GetWeapon()->m_eWeaponType);\n\t}\n\tGetWeapon()->Update(m_audioEntityId, nil);\n}\n\nvoid\nCPlayerPed::PlayerControlFighter(CPad *padUsed)\n{\n\tfloat leftRight = padUsed->GetPedWalkLeftRight();\n\tfloat upDown = padUsed->GetPedWalkUpDown();\n\tfloat padMove = CVector2D(leftRight, upDown).Magnitude();\n\n\tif (padMove > 0.0f) {\n\t\tm_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(0.0f, 0.0f, -leftRight, upDown) - TheCamera.Orientation;\n\t\tm_takeAStepAfterAttack = padMove > 2 * PAD_MOVE_TO_GAME_WORLD_MOVE;\n\t\tif (padUsed->GetSprint() && padMove > 1 * PAD_MOVE_TO_GAME_WORLD_MOVE)\n\t\t\tbIsAttacking = false;\n\t}\n\n\tif (!CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->IsFlagSet(WEAPONFLAG_HEAVY) && padUsed->JumpJustDown()) {\n\t\tif (m_nEvadeAmount != 0 && m_pEvadingFrom) {\n\t\t\tSetEvasiveDive((CPhysical*)m_pEvadingFrom, 1);\n\t\t\tm_nEvadeAmount = 0;\n\t\t\tm_pEvadingFrom = nil;\n\t\t} else {\n\t\t\tSetJump();\n\t\t}\n\t}\n}\n\nvoid\nCPlayerPed::PlayerControl1stPersonRunAround(CPad *padUsed)\n{\n\tfloat leftRight = padUsed->GetPedWalkLeftRight();\n\tfloat upDown = padUsed->GetPedWalkUpDown();\n\tfloat padMove = CVector2D(leftRight, upDown).Magnitude();\n\tfloat padMoveInGameUnit = padMove / PAD_MOVE_TO_GAME_WORLD_MOVE;\n\tif (padMoveInGameUnit > 0.0f) {\n\t\tm_fRotationDest = CGeneral::LimitRadianAngle(TheCamera.Orientation);\n\t\tm_fMoveSpeed = Min(padMoveInGameUnit, 0.07f * CTimer::GetTimeStep() + m_fMoveSpeed);\n\t} else {\n\t\tm_fMoveSpeed = 0.0f;\n\t}\n\n\tif (m_nPedState == PED_JUMP) {\n\t\tif (bIsInTheAir) {\n\t\t\tif (bUsesCollision && !bHitSteepSlope && (!bHitSomethingLastFrame || m_vecDamageNormal.z > 0.6f)\n\t\t\t\t&& m_fDistanceTravelled < CTimer::GetTimeStep() * 0.02 && m_vecMoveSpeed.MagnitudeSqr() < 0.01f) {\n\n\t\t\t\tfloat angleSin = Sin(m_fRotationCur); // originally sin(DEGTORAD(RADTODEG(m_fRotationCur))) o_O\n\t\t\t\tfloat angleCos = Cos(m_fRotationCur);\n\t\t\t\tApplyMoveForce(-angleSin * 3.0f, 3.0f * angleCos, 0.05f);\n\t\t\t}\n\t\t} else if (bIsLanding) {\n\t\t\tm_fMoveSpeed = 0.0f;\n\t\t}\n\t}\n\n\tif (m_nPedState == PED_ANSWER_MOBILE) {\n\t\tSetRealMoveAnim();\n\t\treturn;\n\t}\n\n\tif (!CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->IsFlagSet(WEAPONFLAG_HEAVY) && padUsed->GetSprint()) {\n\t\tm_nMoveState = PEDMOVE_SPRINT;\n\t}\n\tif (m_nPedState != PED_FIGHT)\n\t\tSetRealMoveAnim();\n\n\tif (!bIsInTheAir && !(CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->IsFlagSet(WEAPONFLAG_HEAVY)) &&\n\t\tpadUsed->JumpJustDown() && m_nPedState != PED_JUMP) {\n\n\t\tClearAttack();\n\t\tClearWeaponTarget();\n\t\tif (m_nEvadeAmount != 0 && m_pEvadingFrom) {\n\t\t\tSetEvasiveDive((CPhysical*)m_pEvadingFrom, 1);\n\t\t\tm_nEvadeAmount = 0;\n\t\t\tm_pEvadingFrom = nil;\n\t\t} else {\n\t\t\tSetJump();\n\t\t}\n\t}\n\n\t// FIX: Fact that PlayIdleAnimations only called through PlayerControlZelda was making it visible to only Classic control players. This isn't fair!\n#ifdef FIX_BUGS\n\tif (m_nPedState != PED_FIGHT)\n\t\tPlayIdleAnimations(padUsed);\n#endif\n}\n\nvoid\nCPlayerPed::KeepAreaAroundPlayerClear(void)\n{\n\tBuildPedLists();\n\tfor (int i = 0; i < m_numNearPeds; ++i) {\n\t\tCPed *nearPed = m_nearPeds[i];\n\t\tif (nearPed->CharCreatedBy == RANDOM_CHAR && nearPed->m_nPedState != PED_DRIVING && !nearPed->DyingOrDead()) {\n\t\t\tif (nearPed->GetIsOnScreen()) {\n\t\t\t\tif (nearPed->m_objective == OBJECTIVE_NONE) {\n\t\t\t\t\tnearPed->SetFindPathAndFlee(this, 5000, true);\n\t\t\t\t} else {\n\t\t\t\t\tif (nearPed->EnteringCar())\n\t\t\t\t\t\tnearPed->QuitEnteringCar();\n\n\t\t\t\t\tnearPed->ClearObjective();\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tnearPed->FlagToDestroyWhenNextProcessed();\n\t\t\t}\n\t\t}\n\t}\n\tCVector playerPos = (InVehicle() ? m_pMyVehicle->GetPosition() : GetPosition());\n\n\tCVector pos = GetPosition();\n\tint16 lastVehicle;\n\tCEntity *vehicles[8];\n\tCWorld::FindObjectsInRange(pos, CHECK_NEARBY_THINGS_MAX_DIST, true, &lastVehicle, 6, vehicles, false, true, false, false, false);\n\n\tfor (int i = 0; i < lastVehicle; i++) {\n\t\tCVehicle *veh = (CVehicle*)vehicles[i];\n\t\tif (veh->VehicleCreatedBy != MISSION_VEHICLE) {\n\t\t\tif (veh->GetStatus() != STATUS_PLAYER && veh->GetStatus() != STATUS_PLAYER_DISABLED) {\n\t\t\t\tif ((veh->GetPosition() - playerPos).MagnitudeSqr() > 25.0f) {\n\t\t\t\t\tveh->AutoPilot.m_nTempAction = TEMPACT_WAIT;\n\t\t\t\t\tveh->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 5000;\n\t\t\t\t} else {\n\t\t\t\t\tif (DotProduct2D(playerPos - veh->GetPosition(), veh->GetForward()) > 0.0f)\n\t\t\t\t\t\tveh->AutoPilot.m_nTempAction = TEMPACT_REVERSE;\n\t\t\t\t\telse\n\t\t\t\t\t\tveh->AutoPilot.m_nTempAction = TEMPACT_GOFORWARD;\n\n\t\t\t\t\tveh->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 2000;\n\t\t\t\t}\n\t\t\t\tCCarCtrl::PossiblyRemoveVehicle(veh);\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nCPlayerPed::EvaluateNeighbouringTarget(CEntity *candidate, CEntity **targetPtr, float *lastCloseness, float distLimit, float angleOffset, bool lookToLeft, bool priority)\n{\n\t// priority param is unused\n\tCVector distVec = candidate->GetPosition() - GetPosition();\n\tif (distVec.Magnitude2D() <= distLimit) {\n\t\tif (!DoesTargetHaveToBeBroken(candidate->GetPosition(), GetWeapon())) {\n\t\t\tfloat angleBetweenUs = CGeneral::GetATanOfXY(candidate->GetPosition().x - TheCamera.GetPosition().x,\n\t\t\t\tcandidate->GetPosition().y - TheCamera.GetPosition().y);\n\n\t\t\tangleBetweenUs = CGeneral::LimitAngle(angleBetweenUs - angleOffset);\n\t\t\tfloat closeness;\n\t\t\tif (lookToLeft) {\n\t\t\t\tcloseness = angleBetweenUs > 0.0f ? -Abs(angleBetweenUs) : -100000.0f;\n\t\t\t} else {\n\t\t\t\tcloseness = angleBetweenUs > 0.0f ? -100000.0f : -Abs(angleBetweenUs);\n\t\t\t}\n\n\t\t\tif (closeness > *lastCloseness) {\n\t\t\t\t*targetPtr = candidate;\n\t\t\t\t*lastCloseness = closeness;\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nCPlayerPed::EvaluateTarget(CEntity *candidate, CEntity **targetPtr, float *lastCloseness, float distLimit, float angleOffset, bool priority)\n{\n\tCVector distVec = candidate->GetPosition() - GetPosition();\n\tfloat dist = distVec.Magnitude2D();\n\tif (dist <= distLimit) {\n\t\tif (!DoesTargetHaveToBeBroken(candidate->GetPosition(), GetWeapon())) {\n\t\t\tfloat angleBetweenUs = CGeneral::GetATanOfXY(distVec.x, distVec.y);\n\t\t\tangleBetweenUs = CGeneral::LimitAngle(angleBetweenUs - angleOffset);\n\n\t\t\tfloat closeness = -dist - 5.0f * Abs(angleBetweenUs);\n\t\t\tif (priority) {\n\t\t\t\tcloseness += 30.0f;\n\t\t\t}\n\n\t\t\tif (closeness > *lastCloseness) {\n\t\t\t\t*targetPtr = candidate;\n\t\t\t\t*lastCloseness = closeness;\n\t\t\t}\n\t\t}\n\t}\n}\n\nbool\nCPlayerPed::CanIKReachThisTarget(CVector target, CWeapon* weapon, bool zRotImportant)\n{\n\tfloat angleToFace = CGeneral::GetRadianAngleBetweenPoints(target.x, target.y, GetPosition().x, GetPosition().y);\n\tfloat angleDiff = CGeneral::LimitRadianAngle(angleToFace - m_fRotationCur);\n\n\treturn (!zRotImportant || CWeaponInfo::GetWeaponInfo(weapon->m_eWeaponType)->IsFlagSet(WEAPONFLAG_CANAIM_WITHARM) || Abs(angleDiff) <= HALFPI) &&\n\t\t(CWeaponInfo::GetWeaponInfo(weapon->m_eWeaponType)->IsFlagSet(WEAPONFLAG_CANAIM_WITHARM) || Abs(target.z - GetPosition().z) <= (target - GetPosition()).Magnitude2D());\n}\n\nvoid\nCPlayerPed::RotatePlayerToTrackTarget(void)\n{\n\tif (CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->IsFlagSet(WEAPONFLAG_CANAIM_WITHARM))\n\t\treturn;\n\n\tfloat angleToFace = CGeneral::GetRadianAngleBetweenPoints(\n\t\tm_pPointGunAt->GetPosition().x, m_pPointGunAt->GetPosition().y,\n\t\tGetPosition().x, GetPosition().y);\n\n\tfloat angleDiff = CGeneral::LimitRadianAngle(m_fRotationCur - angleToFace);\n\tif (angleDiff < -DEGTORAD(25.0f)) {\n\t\tm_fRotationCur -= angleDiff + DEGTORAD(25.0f);\n\t\tm_fRotationDest -= angleDiff + DEGTORAD(25.0f);\n\n\t} else if (angleDiff > DEGTORAD(25.0f)) {\n\t\tm_fRotationCur -= angleDiff - DEGTORAD(25.0f);\n\t\tm_fRotationDest -= angleDiff - DEGTORAD(25.0f);\n\t}\n}\n\nbool\nCPlayerPed::FindNextWeaponLockOnTarget(CEntity *previousTarget, bool lookToLeft)\n{\n\tCEntity *nextTarget = nil;\n\tfloat weaponRange = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->m_fRange;\n\t// nextTarget = nil; // duplicate\n\tfloat lastCloseness = -10000.0f;\n\t// CGeneral::GetATanOfXY(GetForward().x, GetForward().y); // unused\n\tCVector distVec = previousTarget->GetPosition() - GetPosition();\n\tfloat referenceBeta = CGeneral::GetATanOfXY(distVec.x, distVec.y);\n\n\tfor (int h = CPools::GetPedPool()->GetSize() - 1; h >= 0; h--) {\n\t\tCPed *pedToCheck = CPools::GetPedPool()->GetSlot(h);\n\t\tif (pedToCheck) {\n\t\t\tif (pedToCheck != this && pedToCheck != previousTarget) {\n\t\t\t\tif (!pedToCheck->DyingOrDead()\n#ifndef AIMING_VEHICLE_OCCUPANTS // Mobile thing\n\t\t\t\t\t&& (!pedToCheck->bInVehicle || (pedToCheck->m_pMyVehicle && pedToCheck->m_pMyVehicle->IsBike()))\n#endif\n\t\t\t\t\t&& pedToCheck->m_leader != this && !pedToCheck->bNeverEverTargetThisPed\n\t\t\t\t\t&& OurPedCanSeeThisOne(pedToCheck) && CanIKReachThisTarget(pedToCheck->GetPosition(), GetWeapon(), true)) {\n\n\t\t\t\t\tEvaluateNeighbouringTarget(pedToCheck, &nextTarget, &lastCloseness,\n\t\t\t\t\t\tweaponRange, referenceBeta, lookToLeft, IsThisPedAnAimingPriority(pedToCheck));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tfor (int i = 0; i < ARRAY_SIZE(m_nTargettableObjects); i++) {\n\t\tCObject *obj = CPools::GetObjectPool()->GetAt(m_nTargettableObjects[i]);\n\t\tif (obj && !obj->bHasBeenDamaged && CanIKReachThisTarget(obj->GetPosition(), GetWeapon(), true))\n\t\t\tEvaluateNeighbouringTarget(obj, &nextTarget, &lastCloseness, weaponRange, referenceBeta, lookToLeft, true);\n\t}\n\tif (!nextTarget)\n\t\treturn false;\n\n\tSetWeaponLockOnTarget(nextTarget);\n\tbDontAllowWeaponChange = true;\n\tSetPointGunAt(nextTarget);\n\treturn true;\n}\n\nbool\nCPlayerPed::FindWeaponLockOnTarget(void)\n{\n\tCEntity *nextTarget = nil;\n\tfloat weaponRange = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->m_fRange;\n\n\tif (m_pPointGunAt) {\n\t\tCVector distVec = m_pPointGunAt->GetPosition() - GetPosition();\n\t\tif (distVec.Magnitude2D() > weaponRange) {\n\t\t\tSetWeaponLockOnTarget(nil);\n\t\t\treturn false;\n\t\t} else {\n\t\t\treturn true;\n\t\t}\n\t}\n\n\t// nextTarget = nil; // duplicate\n\tfloat lastCloseness = -10000.0f;\n\tfloat referenceBeta = CGeneral::GetATanOfXY(GetForward().x, GetForward().y);\n\tfor (int h = CPools::GetPedPool()->GetSize() - 1; h >= 0; h--) {\n\t\tCPed *pedToCheck = CPools::GetPedPool()->GetSlot(h);\n\t\tif (pedToCheck) {\n\t\t\tif (pedToCheck != this) {\n\t\t\t\tif (!pedToCheck->DyingOrDead()\n#ifndef AIMING_VEHICLE_OCCUPANTS // Mobile thing\n\t\t\t\t\t&& (!pedToCheck->bInVehicle || (pedToCheck->m_pMyVehicle && pedToCheck->m_pMyVehicle->IsBike()))\n#endif\n\t\t\t\t\t&& pedToCheck->m_leader != this && !pedToCheck->bNeverEverTargetThisPed\n\t\t\t\t\t&& OurPedCanSeeThisOne(pedToCheck) && CanIKReachThisTarget(pedToCheck->GetPosition(), GetWeapon(), true)) {\n\n\t\t\t\t\tEvaluateTarget(pedToCheck, &nextTarget, &lastCloseness,\n\t\t\t\t\t\tweaponRange, referenceBeta, IsThisPedAnAimingPriority(pedToCheck));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tfor (int i = 0; i < ARRAY_SIZE(m_nTargettableObjects); i++) {\n\t\tCObject *obj = CPools::GetObjectPool()->GetAt(m_nTargettableObjects[i]);\n\t\tif (obj && !obj->bHasBeenDamaged && CanIKReachThisTarget(obj->GetPosition(), GetWeapon(), true))\n\t\t\tEvaluateTarget(obj, &nextTarget, &lastCloseness, weaponRange, referenceBeta, true);\n\t}\n\tif (!nextTarget)\n\t\treturn false;\n\n\tSetWeaponLockOnTarget(nextTarget);\n\tbDontAllowWeaponChange = true;\n\tSetPointGunAt(nextTarget);\n\tSay(SOUND_PED_AIMING);\n\treturn true;\n}\n\nvoid\nCPlayerPed::ProcessAnimGroups(void)\n{\n\tAssocGroupId groupToSet;\n#ifdef PC_PLAYER_CONTROLS\n\tif ((m_fWalkAngle <= -DEGTORAD(50.0f) || m_fWalkAngle >= DEGTORAD(50.0f))\n\t\t&& TheCamera.Cams[TheCamera.ActiveCam].Using3rdPersonMouseCam()\n\t\t&& CanStrafeOrMouseControl()) {\n\n\t\tif (m_fWalkAngle >= -DEGTORAD(130.0f) && m_fWalkAngle <= DEGTORAD(130.0f)) {\n\t\t\tif (m_fWalkAngle > 0.0f) {\n\t\t\t\tif (GetWeapon()->m_eWeaponType == WEAPONTYPE_ROCKETLAUNCHER)\n\t\t\t\t\tgroupToSet = ASSOCGRP_ROCKETLEFT;\n\t\t\t\telse if (GetWeapon()->m_eWeaponType == WEAPONTYPE_CHAINSAW ||\n\t\t\t\t\tGetWeapon()->m_eWeaponType == WEAPONTYPE_FLAMETHROWER ||\n\t\t\t\t\tGetWeapon()->m_eWeaponType == WEAPONTYPE_MINIGUN)\n\t\t\t\t\tgroupToSet = ASSOCGRP_CHAINSAWLEFT;\n\t\t\t\telse\n\t\t\t\t\tgroupToSet = ASSOCGRP_PLAYERLEFT;\n\t\t\t} else {\n\t\t\t\tif (GetWeapon()->m_eWeaponType == WEAPONTYPE_ROCKETLAUNCHER)\n\t\t\t\t\tgroupToSet = ASSOCGRP_ROCKETRIGHT;\n\t\t\t\telse if (GetWeapon()->m_eWeaponType == WEAPONTYPE_CHAINSAW ||\n\t\t\t\t\tGetWeapon()->m_eWeaponType == WEAPONTYPE_FLAMETHROWER ||\n\t\t\t\t\tGetWeapon()->m_eWeaponType == WEAPONTYPE_MINIGUN)\n\t\t\t\t\tgroupToSet = ASSOCGRP_CHAINSAWRIGHT;\n\t\t\t\telse\n\t\t\t\t\tgroupToSet = ASSOCGRP_PLAYERRIGHT;\n\t\t\t}\n\t\t} else {\n\t\t\tif (GetWeapon()->m_eWeaponType == WEAPONTYPE_ROCKETLAUNCHER)\n\t\t\t\tgroupToSet = ASSOCGRP_ROCKETBACK;\n\t\t\telse if (GetWeapon()->m_eWeaponType == WEAPONTYPE_CHAINSAW ||\n\t\t\t\tGetWeapon()->m_eWeaponType == WEAPONTYPE_FLAMETHROWER ||\n\t\t\t\tGetWeapon()->m_eWeaponType == WEAPONTYPE_MINIGUN)\n\t\t\t\tgroupToSet = ASSOCGRP_CHAINSAWBACK;\n\t\t\telse\n\t\t\t\tgroupToSet = ASSOCGRP_PLAYERBACK;\n\t\t}\n\t} else\n#endif\n\t{\n\t\tif (GetWeapon()->m_eWeaponType == WEAPONTYPE_ROCKETLAUNCHER) {\n\t\t\tgroupToSet = ASSOCGRP_PLAYERROCKET;\n\t\t} else {\n\t\t\tif (GetWeapon()->m_eWeaponType == WEAPONTYPE_BASEBALLBAT\n\t\t\t\t || GetWeapon()->m_eWeaponType == WEAPONTYPE_MACHETE)\n\t\t\t\tgroupToSet = ASSOCGRP_PLAYERBBBAT;\n\t\t\telse if (GetWeapon()->m_eWeaponType == WEAPONTYPE_CHAINSAW ||\n\t\t\t\tGetWeapon()->m_eWeaponType == WEAPONTYPE_FLAMETHROWER ||\n\t\t\t\tGetWeapon()->m_eWeaponType == WEAPONTYPE_MINIGUN)\n\t\t\t\tgroupToSet = ASSOCGRP_PLAYERCHAINSAW;\n\t\t\telse if (GetWeapon()->m_eWeaponType != WEAPONTYPE_COLT45 && GetWeapon()->m_eWeaponType != WEAPONTYPE_UZI\n\t\t\t\t// I hope this is a inlined function...\n\t\t\t\t&& GetWeapon()->m_eWeaponType != WEAPONTYPE_PYTHON && GetWeapon()->m_eWeaponType != WEAPONTYPE_TEC9\n\t\t\t\t&& GetWeapon()->m_eWeaponType != WEAPONTYPE_SILENCED_INGRAM && GetWeapon()->m_eWeaponType != WEAPONTYPE_MP5\n\t\t\t\t&& GetWeapon()->m_eWeaponType != WEAPONTYPE_GOLFCLUB && GetWeapon()->m_eWeaponType != WEAPONTYPE_KATANA\n\t\t\t\t&& GetWeapon()->m_eWeaponType != WEAPONTYPE_CAMERA) {\n\t\t\t\tif (!GetWeapon()->IsType2Handed()) {\n\t\t\t\t\tgroupToSet = ASSOCGRP_PLAYER;\n\t\t\t\t} else {\n\t\t\t\t\tgroupToSet = ASSOCGRP_PLAYER2ARMED;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tgroupToSet = ASSOCGRP_PLAYER1ARMED;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (m_animGroup != groupToSet) {\n\t\tm_animGroup = groupToSet;\n\t\tReApplyMoveAnims();\n\t}\n}\n\nvoid\nCPlayerPed::ProcessPlayerWeapon(CPad *padUsed)\n{\n\tCWeaponInfo *weaponInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);\n\tif (m_bHasLockOnTarget && !m_pPointGunAt) {\n\t\tTheCamera.ClearPlayerWeaponMode();\n\t\tCWeaponEffects::ClearCrossHair();\n\t\tClearPointGunAt();\n\t}\n\n\tif (padUsed->DuckJustDown() && !bIsDucking && m_nMoveState != PEDMOVE_SPRINT) {\n\t\tbCrouchWhenShooting = true;\n\t\tSetDuck(60000, true);\n\t} else if (bIsDucking && (padUsed->DuckJustDown() || m_nMoveState == PEDMOVE_SPRINT ||\n\t\tpadUsed->GetSprint() || padUsed->JumpJustDown() || padUsed->ExitVehicleJustDown())) {\n\n\t\tClearDuck(true);\n\t\tbCrouchWhenShooting = false;\n\t}\n\n\tif(weaponInfo->IsFlagSet(WEAPONFLAG_CANAIM))\n\t\tm_wepAccuracy = 95;\n\telse\n\t\tm_wepAccuracy = 100;\n\n\tif (!m_pFire) {\n\t\teWeaponType weapon = GetWeapon()->m_eWeaponType;\n\t\tif (weapon == WEAPONTYPE_ROCKETLAUNCHER || weapon == WEAPONTYPE_SNIPERRIFLE ||\n\t\t\tweapon == WEAPONTYPE_LASERSCOPE || weapon == WEAPONTYPE_M4 ||\n\t\t\tweapon == WEAPONTYPE_RUGER || weapon == WEAPONTYPE_M60 ||\n\t\t\tweapon == WEAPONTYPE_CAMERA) {\n\n\t\t\tif (padUsed->TargetJustDown() || TheCamera.m_bJustJumpedOutOf1stPersonBecauseOfTarget) {\n#ifdef FREE_CAM\n\t\t\t\tif (CCamera::bFreeCam && TheCamera.Cams[0].Using3rdPersonMouseCam()) {\n\t\t\t\t\tm_fRotationCur = CGeneral::LimitRadianAngle(-TheCamera.Orientation);\n\t\t\t\t\tSetHeading(m_fRotationCur);\n\t\t\t\t}\n#endif\n\t\t\t\tif (weapon == WEAPONTYPE_ROCKETLAUNCHER)\n\t\t\t\t\tTheCamera.SetNewPlayerWeaponMode(CCam::MODE_ROCKETLAUNCHER, 0, 0);\n\t\t\t\telse if (weapon == WEAPONTYPE_SNIPERRIFLE || weapon == WEAPONTYPE_LASERSCOPE)\n\t\t\t\t\tTheCamera.SetNewPlayerWeaponMode(CCam::MODE_SNIPER, 0, 0);\n\t\t\t\telse if (weapon == WEAPONTYPE_CAMERA)\n\t\t\t\t\tTheCamera.SetNewPlayerWeaponMode(CCam::MODE_CAMERA, 0, 0);\n\t\t\t\telse\n\t\t\t\t\tTheCamera.SetNewPlayerWeaponMode(CCam::MODE_M16_1STPERSON, 0, 0);\n\n\t\t\t\tm_fMoveSpeed = 0.0f;\n\t\t\t\tCAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_IDLE, 1000.0f);\n\t\t\t\tSetPedState(PED_SNIPER_MODE);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (!TheCamera.Using1stPersonWeaponMode())\n\t\t\t\tif (weapon == WEAPONTYPE_ROCKETLAUNCHER || weapon == WEAPONTYPE_SNIPERRIFLE || weapon == WEAPONTYPE_LASERSCOPE || weapon == WEAPONTYPE_CAMERA)\n\t\t\t\t\treturn;\n\t\t}\n\t}\n\n\tif (padUsed->GetWeapon() && m_nMoveState != PEDMOVE_SPRINT) {\n\t\tif (m_nSelectedWepSlot == m_currentWeapon) {\n\t\t\tif (m_pPointGunAt) {\n\t\t\t\tif (m_nPedState == PED_ATTACK) {\n\t\t\t\t\tm_fAttackButtonCounter *= Pow(0.94f, CTimer::GetTimeStep());\n\t\t\t\t} else {\n\t\t\t\t\tm_fAttackButtonCounter = 0.0f;\n\t\t\t\t}\n\t\t\t\tSetAttack(m_pPointGunAt);\n\t\t\t} else {\n\t\t\t\tif (m_nPedState == PED_ATTACK) {\n\t\t\t\t\tif (padUsed->WeaponJustDown()) {\n\t\t\t\t\t\tm_bHaveTargetSelected = true;\n\t\t\t\t\t} else if (!m_bHaveTargetSelected) {\n\t\t\t\t\t\tm_fAttackButtonCounter += CTimer::GetTimeStepNonClipped();\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tm_fAttackButtonCounter = 0.0f;\n\t\t\t\t\tm_bHaveTargetSelected = false;\n\t\t\t\t}\n\t\t\t\tif (GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED && GetWeapon()->m_eWeaponType != WEAPONTYPE_BRASSKNUCKLE &&\n\t\t\t\t\t!weaponInfo->IsFlagSet(WEAPONFLAG_FIGHTMODE)) {\n\n\t\t\t\t\tif (GetWeapon()->m_eWeaponType != WEAPONTYPE_DETONATOR && GetWeapon()->m_eWeaponType != WEAPONTYPE_DETONATOR_GRENADE ||\n\t\t\t\t\t\tpadUsed->WeaponJustDown())\n\t\t\t\t\t\tSetAttack(nil);\n\n\t\t\t\t} else if (padUsed->WeaponJustDown()) {\n\t\t\t\t\tif (m_fMoveSpeed < 1.0f || m_nPedState == PED_FIGHT)\n\t\t\t\t\t\tStartFightAttack(padUsed->GetWeapon());\n\t\t\t\t\telse\n\t\t\t\t\t\tSetAttack(nil);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} else {\n\t\tm_pedIK.m_flags &= ~CPedIK::LOOKAROUND_HEAD_ONLY;\n\t\tif (m_nPedState == PED_ATTACK) {\n\t\t\tm_bHaveTargetSelected = true;\n\t\t\tbIsAttacking = false;\n\t\t}\n\t}\n\n#ifdef FREE_CAM\n\tstatic int8 changedHeadingRate = 0;\n\tstatic int8 pointedGun = 0;\n\tif (changedHeadingRate == 2) changedHeadingRate = 1;\n\tif (pointedGun == 2) pointedGun = 1;\n\n\t// Rotate player/arm when shooting. We don't have auto-rotation anymore\n\tif (CCamera::m_bUseMouse3rdPerson && CCamera::bFreeCam &&\n\t\tm_nSelectedWepSlot == m_currentWeapon && m_nMoveState != PEDMOVE_SPRINT) {\n\n#define CAN_AIM_WITH_ARM (weaponInfo->IsFlagSet(WEAPONFLAG_CANAIM_WITHARM) && !bIsDucking && !bCrouchWhenShooting)\n\t\t// Weapons except throwable and melee ones\n\t\tif (weaponInfo->m_nWeaponSlot > 2) {\n\t\t\tif ((padUsed->GetTarget() && CAN_AIM_WITH_ARM) || padUsed->GetWeapon()) {\n\t\t\t\tfloat limitedCam = CGeneral::LimitRadianAngle(-TheCamera.Orientation);\n\n\t\t\t\t// On this one we can rotate arm.\n\t\t\t\tif (CAN_AIM_WITH_ARM) {\n\t\t\t\t\tif (!padUsed->GetWeapon()) { // making this State != ATTACK still stops it after attack. Re-start it immediately!\n\t\t\t\t\t\tSetPointGunAt(nil);\n\t\t\t\t\t\tbIsPointingGunAt = false; // to not stop after attack\n\t\t\t\t\t}\n\t\t\t\t\tpointedGun = 2;\n\t\t\t\t\tSetLookFlag(limitedCam, true);\n\t\t\t\t\tSetAimFlag(limitedCam);\n\t\t\t\t\tSetLookTimer(INT32_MAX); // removing this makes head move for real, but I experinced some bugs.\n\t\t\t\t\t\n\t\t\t\t} else {\n\t\t\t\t\tm_fRotationDest = limitedCam;\n\t\t\t\t\tchangedHeadingRate = 2;\n\t\t\t\t\tm_headingRate = 12.5f;\n\n\t\t\t\t\t// Anim. fix for shotgun, ak47 and m16 (we must finish rot. it quickly)\n\t\t\t\t\tif (weaponInfo->IsFlagSet(WEAPONFLAG_CANAIM) && padUsed->WeaponJustDown()) {\n\t\t\t\t\t\tm_fRotationCur = CGeneral::LimitRadianAngle(m_fRotationCur);\n\t\t\t\t\t\tfloat limitedRotDest = m_fRotationDest;\n\n\t\t\t\t\t\tif (m_fRotationCur - PI > m_fRotationDest) {\n\t\t\t\t\t\t\tlimitedRotDest += 2 * PI;\n\t\t\t\t\t\t} else if (PI + m_fRotationCur < m_fRotationDest) {\n\t\t\t\t\t\t\tlimitedRotDest -= 2 * PI;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tm_fRotationCur += (limitedRotDest - m_fRotationCur) / 2;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n#undef CAN_AIM_WITH_ARM\n\t}\n\tif (changedHeadingRate == 1) {\n\t\tchangedHeadingRate = 0;\n\t\tRestoreHeadingRate();\n\t}\n\tif (pointedGun == 1 && m_nPedState != PED_ATTACK) {\n\t\tpointedGun = 0;\n\t\tClearPointGunAt();\n\t}\n#endif\n\n\tif (padUsed->GetTarget() && m_nSelectedWepSlot == m_currentWeapon && m_nMoveState != PEDMOVE_SPRINT && !TheCamera.Using1stPersonWeaponMode() && weaponInfo->IsFlagSet(WEAPONFLAG_CANAIM)) {\n\t\tif (m_pPointGunAt) {\n\t\t\t// what??\n\t\t\tif (!m_pPointGunAt\n#ifdef FREE_CAM\n\t\t\t\t|| (!CCamera::bFreeCam && CCamera::m_bUseMouse3rdPerson)\n#else\n\t\t\t\t|| CCamera::m_bUseMouse3rdPerson\n#endif\t\t\n\t\t\t) {\n\t\t\t\tClearWeaponTarget();\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (m_pPointGunAt->IsPed() && (\n#ifndef AIMING_VEHICLE_OCCUPANTS\n\t\t\t\t(((CPed*)m_pPointGunAt)->bInVehicle && (!((CPed*)m_pPointGunAt)->m_pMyVehicle || !((CPed*)m_pPointGunAt)->m_pMyVehicle->IsBike())) ||\n#endif\n\t\t\t\t!CGame::nastyGame && ((CPed*)m_pPointGunAt)->DyingOrDead())) {\n\t\t\t\tClearWeaponTarget();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (CPlayerPed::DoesTargetHaveToBeBroken(m_pPointGunAt->GetPosition(), GetWeapon()) || \n\t\t\t\t(!bCanPointGunAtTarget && !weaponInfo->IsFlagSet(WEAPONFLAG_CANAIM_WITHARM))) { // this line isn't on Mobile, idk why\n\t\t\t\tClearWeaponTarget();\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (m_pPointGunAt) {\n\t\t\t\tRotatePlayerToTrackTarget();\n\t\t\t}\n\n\t\t\tif (m_pPointGunAt) {\n\t\t\t\tif (padUsed->ShiftTargetLeftJustDown())\n\t\t\t\t\tFindNextWeaponLockOnTarget(m_pPointGunAt, true);\n\t\t\t\tif (padUsed->ShiftTargetRightJustDown())\n\t\t\t\t\tFindNextWeaponLockOnTarget(m_pPointGunAt, false);\n\t\t\t}\n\t\t\tTheCamera.SetNewPlayerWeaponMode(CCam::MODE_SYPHON, 0, 0);\n\t\t\tTheCamera.UpdateAimingCoors(m_pPointGunAt->GetPosition());\n\n\t\t} else if (!CCamera::m_bUseMouse3rdPerson) {\n\t\t\tif (padUsed->TargetJustDown() || TheCamera.m_bJustJumpedOutOf1stPersonBecauseOfTarget)\n\t\t\t\tFindWeaponLockOnTarget();\n\t\t}\n\t} else if (m_pPointGunAt) {\n\t\tClearWeaponTarget();\n\t}\n\n\tif (m_pPointGunAt) {\n\t\tCVector markPos;\n\t\tif (m_pPointGunAt->IsPed()) {\n\t\t\t((CPed*)m_pPointGunAt)->m_pedIK.GetComponentPosition(markPos, PED_MID);\n\t\t} else {\n\t\t\tmarkPos = m_pPointGunAt->GetPosition();\n\t\t}\n\t\tif (bCanPointGunAtTarget) {\n\t\t\tCWeaponEffects::MarkTarget(markPos, 64, 0, 0, 255, 0.8f);\n\t\t} else {\n\t\t\tCWeaponEffects::MarkTarget(markPos, 64, 32, 0, 255, 0.8f);\n\t\t}\n\t}\n\tm_bHasLockOnTarget = m_pPointGunAt != nil;\n}\n\nbool\nCPlayerPed::MovementDisabledBecauseOfTargeting(void)\n{\n\treturn m_pPointGunAt && !CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->IsFlagSet(WEAPONFLAG_CANAIM_WITHARM);\n}\n\nvoid\nCPlayerPed::PlayerControlZelda(CPad *padUsed)\n{\n\tfloat smoothSprayRate = DoWeaponSmoothSpray();\n\tfloat camOrientation = TheCamera.Orientation;\n\tfloat leftRight = padUsed->GetPedWalkLeftRight();\n\tfloat upDown = padUsed->GetPedWalkUpDown();\n\tfloat padMoveInGameUnit;\n\tbool smoothSprayWithoutMove = false;\n\n\tif (MovementDisabledBecauseOfTargeting()) {\n\t\tupDown = 0.0f;\n\t\tleftRight = 0.0f;\n\t}\n\n\tif (smoothSprayRate > 0.0f && upDown > 0.0f) {\n\t\tpadMoveInGameUnit = 0.0f;\n\t\tsmoothSprayWithoutMove = true;\n\t} else {\n\t\tpadMoveInGameUnit = CVector2D(leftRight, upDown).Magnitude() / PAD_MOVE_TO_GAME_WORLD_MOVE;\n\t}\n\n\tif (padMoveInGameUnit > 0.0f || smoothSprayWithoutMove) {\n\t\tfloat padHeading = CGeneral::GetRadianAngleBetweenPoints(0.0f, 0.0f, -leftRight, upDown);\n\t\tfloat neededTurn = CGeneral::LimitRadianAngle(padHeading - camOrientation);\n\t\tif (smoothSprayRate > 0.0f) {\n\t\t\tm_fRotationDest = m_fRotationCur - leftRight / 128.0f * smoothSprayRate * CTimer::GetTimeStep();\n\t\t} else {\n\t\t\tm_fRotationDest = neededTurn;\n\t\t}\n\n\t\tfloat maxAcc = 0.07f * CTimer::GetTimeStep();\n\t\tm_fMoveSpeed = Min(padMoveInGameUnit, m_fMoveSpeed + maxAcc);\n\n\t} else {\n\t\tm_fMoveSpeed = 0.0f;\n\t}\n\n\tif (m_nPedState == PED_JUMP) {\n\t\tif (bIsInTheAir) {\n\t\t\tif (bUsesCollision && !bHitSteepSlope && (!bHitSomethingLastFrame || m_vecDamageNormal.z > 0.6f)\n\t\t\t\t&& m_fDistanceTravelled < CTimer::GetTimeStep() * 0.02 && m_vecMoveSpeed.MagnitudeSqr() < 0.01f) {\n\n\t\t\t\tfloat angleSin = Sin(m_fRotationCur); // originally sin(DEGTORAD(RADTODEG(m_fRotationCur))) o_O\n\t\t\t\tfloat angleCos = Cos(m_fRotationCur);\n\t\t\t\tApplyMoveForce(-angleSin * 3.0f, 3.0f * angleCos, 0.05f);\n\t\t\t}\n\t\t} else if (bIsLanding) {\n\t\t\tm_fMoveSpeed = 0.0f;\n\t\t}\n\t}\n\n\tif (m_nPedState == PED_ANSWER_MOBILE) {\n\t\tSetRealMoveAnim();\n\t\treturn;\n\t}\n\n\tif (!CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->IsFlagSet(WEAPONFLAG_HEAVY) && padUsed->GetSprint()) {\n\t\tif (!m_pCurrentPhysSurface || (!m_pCurrentPhysSurface->bInfiniteMass || m_pCurrentPhysSurface->m_phy_flagA08))\n\t\t\tm_nMoveState = PEDMOVE_SPRINT;\n\t}\n\n\tif (m_nPedState != PED_FIGHT)\n\t\tSetRealMoveAnim();\n\n\tif (!bIsInTheAir && !CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->IsFlagSet(WEAPONFLAG_HEAVY)\n\t\t&& padUsed->JumpJustDown() && m_nPedState != PED_JUMP) {\n\t\tClearAttack();\n\t\tClearWeaponTarget();\n\t\tif (m_nEvadeAmount != 0 && m_pEvadingFrom) {\n\t\t\tSetEvasiveDive((CPhysical*)m_pEvadingFrom, 1);\n\t\t\tm_nEvadeAmount = 0;\n\t\t\tm_pEvadingFrom = nil;\n\t\t} else {\n\t\t\tSetJump();\n\t\t}\n\t}\n\tPlayIdleAnimations(padUsed);\n}\n\n// Finds nice positions for peds to duck and shoot player. And it's inside PlayerPed, this is treachery!\nvoid\nCPlayerPed::FindNewAttackPoints(void)\n{\n\tfor (int i=0; i<ARRAY_SIZE(m_pPedAtSafePos); i++) {\n\t\tCPed *safeNeighbour = m_pPedAtSafePos[i];\n\t\tif (safeNeighbour) {\n\t\t\tif (safeNeighbour->m_nPedState == PED_DEAD || safeNeighbour->m_pedInObjective != this) {\n\t\t\t\tm_vecSafePos[i].x = 0.0f;\n\t\t\t\tm_vecSafePos[i].y = 0.0f;\n\t\t\t\tm_vecSafePos[i].z = 0.0f;\n\t\t\t\tm_pPedAtSafePos[i] = nil;\n\t\t\t}\n\t\t} else {\n\t\t\tm_vecSafePos[i].x = 0.0f;\n\t\t\tm_vecSafePos[i].y = 0.0f;\n\t\t\tm_vecSafePos[i].z = 0.0f;\n\t\t}\n\t}\n\tCEntity *entities[6];\n\tint16 numEnts;\n\tfloat rightMult, fwdMult;\n\tCWorld::FindObjectsInRange(GetPosition(), 18.0f, true, &numEnts, 6, entities, true, false, false, true, false);\n\tfor (int i = 0; i < numEnts; ++i) {\n\t\tCEntity *ent = entities[i];\n\t\tint16 mi = ent->GetModelIndex();\n\t\tif (!ent->IsObject() || ((CObject*)ent)->m_nSpecialCollisionResponseCases == COLLRESPONSE_FENCEPART)\n\t\t\tif (!IsTreeModel(mi))\n\t\t\t\tcontinue;\n\n\t\tif (mi == MI_TRAFFICLIGHTS) {\n\t\t\trightMult = 2.957f;\n\t\t\tfwdMult = 0.147f;\n\n\t\t} else if (mi == MI_SINGLESTREETLIGHTS1) {\n\t\t\trightMult = 0.744f;\n\t\t\tfwdMult = 0.0f;\n\n\t\t} else if (mi == MI_SINGLESTREETLIGHTS2) {\n\t\t\trightMult = 0.043f;\n\t\t\tfwdMult = 0.0f;\n\n\t\t} else if (mi == MI_SINGLESTREETLIGHTS3) {\n\t\t\trightMult = 1.143f;\n\t\t\tfwdMult = 0.145f;\n\n\t\t} else if (mi == MI_DOUBLESTREETLIGHTS) {\n\t\t\trightMult = 0.744f;\n\t\t\tfwdMult = 0.0f;\n\n\t\t} else if (mi == MI_LAMPPOST1) {\n\t\t\trightMult = 0.744f;\n\t\t\tfwdMult = 0.0f;\n\n\t\t} else if (mi == MI_TRAFFICLIGHT01) {\n\t\t\trightMult = 2.957f;\n\t\t\tfwdMult = 0.147f;\n\n\t\t} else if (mi == MI_LITTLEHA_POLICE) {\n\t\t\trightMult = 0.0f;\n\t\t\tfwdMult = 0.0f;\n\n\t\t} else if (mi == MI_PARKBENCH) {\n\t\t\trightMult = 0.0f;\n\t\t\tfwdMult = 0.0f;\n\n\t\t} else if (IsTreeModel(mi)) {\n\t\t\trightMult = 0.0f;\n\t\t\tfwdMult = 0.0f;\n\t\t} else\n\t\t\tcontinue;\n\n\t\tCVector entAttackPoint(rightMult * ent->GetRight().x + fwdMult * ent->GetForward().x + ent->GetPosition().x,\n\t\t\trightMult * ent->GetRight().y + fwdMult * ent->GetForward().y + ent->GetPosition().y,\n\t\t\tent->GetPosition().z);\n\t\tCVector attackerPos = GetPosition() - entAttackPoint; // for now it's dist, not attackerPos\n\t\tCVector dirTowardsUs = attackerPos;\n\t\tdirTowardsUs.Normalise();\n\t\tdirTowardsUs *= 2.0f;\n\t\tattackerPos = entAttackPoint - dirTowardsUs; // to make cop farther from us\n\t\tCPedPlacement::FindZCoorForPed(&attackerPos);\n\t\tif (CPedPlacement::IsPositionClearForPed(attackerPos))\n\t\t\tm_vecSafePos[i] = attackerPos;\n\t}\n}\n\nvoid\nCPlayerPed::ProcessControl(void)\n{\n\t// Mobile has some debug/abandoned cheat thing in here: \"gbFrankenTommy\"\n\n\tif (m_nEvadeAmount != 0)\n\t\t--m_nEvadeAmount;\n\n\tif (m_nEvadeAmount == 0)\n\t\tm_pEvadingFrom = nil;\n\n\tif (m_pWanted->GetWantedLevel() > 0)\n\t\tFindNewAttackPoints();\n\t\n\tUpdateMeleeAttackers();\n\n\tif (m_pCurrentPhysSurface && m_pCurrentPhysSurface->IsVehicle() && ((CVehicle*)m_pCurrentPhysSurface)->IsBoat()) {\n\t\tbTryingToReachDryLand = true;\n\n\t} else if (!(((uint8)CTimer::GetFrameCounter() + m_randomSeed) & 0xF)) {\n\t\tCVehicle *nearVeh = (CVehicle*)CWorld::TestSphereAgainstWorld(GetPosition(), 7.0f, nil, false, true, false, false, false, false);\n\t\tif (nearVeh && nearVeh->IsBoat())\n\t\t\tbTryingToReachDryLand = true;\n\t\telse\n\t\t\tbTryingToReachDryLand = false;\n\t}\n\n\tif (m_nFadeDrunkenness) {\n\t\tif (m_nDrunkenness - 1 > 0) {\n\t\t\t--m_nDrunkenness;\n\t\t} else {\n\t\t\tm_nDrunkenness = 0;\n\t\t\tCMBlur::ClearDrunkBlur();\n\t\t\tm_nFadeDrunkenness = 0;\n\t\t}\n\t}\n\tif (m_nDrunkenness != 0) {\n\t\tCMBlur::SetDrunkBlur(m_nDrunkenness / 255.f);\n\t}\n\tCPed::ProcessControl();\n\tSetNearbyPedsToInteractWithPlayer();\n\tif (bWasPostponed)\n\t\treturn;\n\n\tCPad *padUsed = GetPadFromPlayer(this);\n\tm_pWanted->Update();\n\tPruneReferences();\n\n\tif (GetWeapon()->m_eWeaponType == WEAPONTYPE_MINIGUN) {\n\t\tCWeaponInfo *weaponInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);\n\t\tCAnimBlendAssociation *fireAnim = RpAnimBlendClumpGetAssociation(GetClump(), GetPrimaryFireAnim(weaponInfo));\n\t\tif (fireAnim && fireAnim->currentTime - fireAnim->timeStep < weaponInfo->m_fAnimLoopEnd && m_nPedState == PED_ATTACK) {\n\t\t\tif (m_fGunSpinSpeed < 0.45f) {\n\t\t\t\tm_fGunSpinSpeed = Min(0.45f, m_fGunSpinSpeed + CTimer::GetTimeStep() * 0.013f);\n\t\t\t}\n\n\t\t\tif (padUsed->GetWeapon() && GetWeapon()->m_nAmmoTotal > 0 && fireAnim->currentTime >= weaponInfo->m_fAnimLoopStart) {\n\t\t\t\tDMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_MINIGUN_ATTACK, 0.0f);\n\t\t\t} else {\n\t\t\t\tDMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_MINIGUN_2, m_fGunSpinSpeed * (20.f / 9));\n\t\t\t}\n\t\t} else {\n\t\t\tif (m_fGunSpinSpeed > 0.0f) {\n\t\t\t\tif (m_fGunSpinSpeed >= 0.45f) {\n\t\t\t\t\tDMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_MINIGUN_3,  0.0f);\n\t\t\t\t}\n\t\t\t\tm_fGunSpinSpeed = Max(0.0f, m_fGunSpinSpeed - CTimer::GetTimeStep() * 0.003f);\n\t\t\t}\n\t\t}\n\t}\n\tif (GetWeapon()->m_eWeaponType == WEAPONTYPE_CHAINSAW && m_nPedState != PED_ATTACK && !bInVehicle) {\n\t\tDMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_CHAINSAW_ATTACK, 0.0f);\n\t}\n\n\tif (m_nMoveState != PEDMOVE_RUN && m_nMoveState != PEDMOVE_SPRINT)\n\t\tRestoreSprintEnergy(1.0f);\n\telse if (m_nMoveState == PEDMOVE_RUN)\n\t\tRestoreSprintEnergy(0.3f);\n\n\tif (m_nPedState == PED_DEAD) {\n\t\tClearWeaponTarget();\n\t\treturn;\n\t}\n\tif (m_nPedState == PED_DIE) {\n\t\tClearWeaponTarget();\n\t\tif (CTimer::GetTimeInMilliseconds() > m_bloodyFootprintCountOrDeathTime + 4000)\n\t\t\tSetDead();\n\t\treturn;\n\t}\n\tif (m_nPedState == PED_DRIVING && m_objective != OBJECTIVE_LEAVE_CAR) {\n\t\tif (!CReplay::IsPlayingBack() || m_pMyVehicle) {\n\t\t\tif (m_pMyVehicle->IsCar() && ((CAutomobile*)m_pMyVehicle)->Damage.GetDoorStatus(DOOR_FRONT_LEFT) == DOOR_STATUS_SWINGING) {\n\t\t\t\tCAnimBlendAssociation *rollDoorAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_CAR_CLOSE_DOOR_ROLLING_LHS);\n\n\t\t\t\tif (m_pMyVehicle->m_nGettingOutFlags & CAR_DOOR_FLAG_LF || rollDoorAssoc || (rollDoorAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_STD_CAR_CLOSE_DOOR_ROLLING_LO_LHS))) {\n\t\t\t\t\tif (rollDoorAssoc)\n\t\t\t\t\t\tm_pMyVehicle->ProcessOpenDoor(CAR_DOOR_LF, ANIM_STD_CAR_CLOSE_DOOR_ROLLING_LHS, rollDoorAssoc->currentTime);\n\n\t\t\t\t} else {\n\t\t\t\t\t// These comparisons are wrong, they return uint16\n\t\t\t\t\tif (padUsed && (padUsed->GetAccelerate() != 0.0f || padUsed->GetSteeringLeftRight() != 0.0f || padUsed->GetBrake() != 0.0f)) {\n\t\t\t\t\t\tif (rollDoorAssoc)\n\t\t\t\t\t\t\tm_pMyVehicle->ProcessOpenDoor(CAR_DOOR_LF, ANIM_STD_CAR_CLOSE_DOOR_ROLLING_LHS, rollDoorAssoc->currentTime);\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tm_pMyVehicle->m_nGettingOutFlags |= CAR_DOOR_FLAG_LF;\n\t\t\t\t\t\tif (m_pMyVehicle->bLowVehicle)\n\t\t\t\t\t\t\trollDoorAssoc = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_CLOSE_DOOR_ROLLING_LO_LHS);\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\trollDoorAssoc = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_CLOSE_DOOR_ROLLING_LHS);\n\n\t\t\t\t\t\trollDoorAssoc->SetFinishCallback(PedAnimDoorCloseRollingCB, this);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn;\n\t}\n\tif (m_objective == OBJECTIVE_NONE)\n\t\tm_nMoveState = PEDMOVE_STILL;\n\tif (bIsLanding)\n\t\tRunningLand(padUsed);\n\n\tif (padUsed && padUsed->WeaponJustDown() && !TheCamera.Using1stPersonWeaponMode()) {\n\t\t// ...Really?\n\t\teWeaponType playerWeapon = FindPlayerPed()->GetWeapon()->m_eWeaponType;\n\t\tif (playerWeapon == WEAPONTYPE_SNIPERRIFLE || playerWeapon == WEAPONTYPE_LASERSCOPE) {\n\t\t\tDMAudio.PlayFrontEndSound(SOUND_WEAPON_SNIPER_SHOT_NO_ZOOM, 0);\n\t\t} else if (playerWeapon == WEAPONTYPE_ROCKETLAUNCHER) {\n\t\t\tDMAudio.PlayFrontEndSound(SOUND_WEAPON_ROCKET_SHOT_NO_ZOOM, 0);\n\t\t}\n\t}\n\n\tswitch (m_nPedState) {\n\t\tcase PED_NONE:\n\t\tcase PED_IDLE:\n\t\tcase PED_FLEE_POS:\n\t\tcase PED_FLEE_ENTITY:\n\t\tcase PED_ATTACK:\n\t\tcase PED_FIGHT:\n\t\tcase PED_AIM_GUN:\n\t\tcase PED_ANSWER_MOBILE:\n\t\t\tif (!RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_BLOCK) && !m_attachedTo) {\n\t\t\t\tif (TheCamera.Using1stPersonWeaponMode()) {\n\t\t\t\t\tif (padUsed)\n\t\t\t\t\t\tPlayerControlSniper(padUsed);\n\n\t\t\t\t} else if (TheCamera.Cams[0].Using3rdPersonMouseCam()\n#ifdef FREE_CAM\n\t\t\t\t\t&& !CCamera::bFreeCam\n#endif\n\t\t\t\t\t) {\n\t\t\t\t\tif (padUsed)\n\t\t\t\t\t\tPlayerControl1stPersonRunAround(padUsed);\n\n\t\t\t\t} else if (m_nPedState == PED_FIGHT) {\n\t\t\t\t\tif (padUsed)\n\t\t\t\t\t\tPlayerControlFighter(padUsed);\n\n\t\t\t\t} else if (padUsed) {\n\t\t\t\t\tPlayerControlZelda(padUsed);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (IsPedInControl() && m_nPedState != PED_ANSWER_MOBILE && padUsed)\n\t\t\t\tProcessPlayerWeapon(padUsed);\n\t\t\tbreak;\n\t\tcase PED_SEEK_ENTITY:\n\t\t\tm_vecSeekPos = m_pSeekTarget->GetPosition();\n\n\t\t\t// fall through\n\t\tcase PED_SEEK_POS:\n\t\t\tswitch (m_nMoveState) {\n\t\t\t\tcase PEDMOVE_WALK:\n\t\t\t\t\tm_fMoveSpeed = 1.0f;\n\t\t\t\t\tbreak;\n\t\t\t\tcase PEDMOVE_RUN:\n\t\t\t\t\tm_fMoveSpeed = 1.8f;\n\t\t\t\t\tbreak;\n\t\t\t\tcase PEDMOVE_SPRINT:\n\t\t\t\t\tm_fMoveSpeed = 2.5f;\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tm_fMoveSpeed = 0.0f;\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tSetRealMoveAnim();\n\t\t\tif (Seek()) {\n\t\t\t\tRestorePreviousState();\n\t\t\t\tSetMoveState(PEDMOVE_STILL);\n\t\t\t}\n\t\t\tbreak;\n\t\tcase PED_SNIPER_MODE:\n\t\t\tif (GetWeapon()->m_eWeaponType == WEAPONTYPE_SNIPERRIFLE || GetWeapon()->m_eWeaponType == WEAPONTYPE_LASERSCOPE) {\n\t\t\t\tif (padUsed)\n\t\t\t\t\tPlayerControlSniper(padUsed);\n\n\t\t\t} else if (padUsed) {\n\t\t\t\tPlayerControlM16(padUsed);\n\t\t\t}\n\t\t\tbreak;\n\t\tcase PED_SEEK_CAR:\n\t\tcase PED_SEEK_IN_BOAT:\n\t\t\tif (bVehEnterDoorIsBlocked || bKindaStayInSamePlace) {\n\t\t\t\tm_fMoveSpeed = 0.0f;\n\t\t\t} else {\n\t\t\t\tm_fMoveSpeed = Min(2.0f, 2.0f * (m_vecSeekPos - GetPosition()).Magnitude2D());\n\t\t\t}\n\t\t\tif (padUsed && !padUsed->ArePlayerControlsDisabled()) {\n\t\t\t\tif (padUsed->GetTarget() || padUsed->GetLeftStickXJustDown() || padUsed->GetLeftStickYJustDown() ||\n\t\t\t\t\tpadUsed->GetDPadUpJustDown() || padUsed->GetDPadDownJustDown() || padUsed->GetDPadLeftJustDown() ||\n\t\t\t\t\tpadUsed->GetDPadRightJustDown()) {\n\n\t\t\t\t\tRestorePreviousState();\n\t\t\t\t\tif (m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER || m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER) {\n\t\t\t\t\t\tRestorePreviousObjective();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (padUsed && padUsed->GetSprint())\n\t\t\t\tm_nMoveState = PEDMOVE_SPRINT;\n\t\t\tSetRealMoveAnim();\n\t\t\tbreak;\n\t\tcase PED_JUMP:\n\t\t\tif (padUsed)\n\t\t\t\tPlayerControlZelda(padUsed);\n\t\t\tif (bIsLanding)\n\t\t\t\tbreak;\n\n\t\t\t// This has been added later it seems\n\t\t\treturn;\n\t\tcase PED_FALL:\n\t\tcase PED_GETUP:\n\t\tcase PED_ENTER_TRAIN:\n\t\tcase PED_EXIT_TRAIN:\n\t\tcase PED_CARJACK:\n\t\tcase PED_DRAG_FROM_CAR:\n\t\tcase PED_ENTER_CAR:\n\t\tcase PED_STEAL_CAR:\n\t\tcase PED_EXIT_CAR:\n\t\t\tClearWeaponTarget();\n\t\t\tbreak;\n\t\tcase PED_ARRESTED:\n\t\t\tif (m_nLastPedState == PED_DRAG_FROM_CAR && m_pVehicleAnim)\n\t\t\t\tBeingDraggedFromCar();\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\tif (padUsed && IsPedShootable() && m_nPedState != PED_ANSWER_MOBILE && m_nLastPedState != PED_ANSWER_MOBILE) {\n\t\tProcessWeaponSwitch(padUsed);\n\t\tGetWeapon()->Update(m_audioEntityId, this);\n\t}\n\tProcessAnimGroups();\n\tif (padUsed) {\n\t\tif (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_FOLLOWPED\n\t\t\t&& TheCamera.Cams[TheCamera.ActiveCam].DirectionWasLooking == LOOKING_BEHIND) {\n\n\t\t\tm_lookTimer = 0;\n\t\t\tfloat camAngle = CGeneral::LimitRadianAngle(TheCamera.Cams[TheCamera.ActiveCam].Front.Heading());\n\t\t\tfloat angleBetweenPlayerAndCam = Abs(camAngle - m_fRotationCur);\n\n\t\t\tif (m_nPedState != PED_ATTACK && angleBetweenPlayerAndCam > DEGTORAD(30.0f) && angleBetweenPlayerAndCam < DEGTORAD(330.0f)) {\n\t\t\t\tif (angleBetweenPlayerAndCam > DEGTORAD(150.0f) && angleBetweenPlayerAndCam < DEGTORAD(210.0f)) {\n\t\t\t\t\tfloat rightTurnAngle = CGeneral::LimitRadianAngle(m_fRotationCur - DEGTORAD(150.0f));\n\t\t\t\t\tfloat leftTurnAngle = CGeneral::LimitRadianAngle(DEGTORAD(150.0f) + m_fRotationCur);\n\n\t\t\t\t\tif (m_fLookDirection == 999999.0f || bIsDucking)\n\t\t\t\t\t\tcamAngle = rightTurnAngle;\n\t\t\t\t\telse if (Abs(rightTurnAngle - m_fLookDirection) < Abs(leftTurnAngle - m_fLookDirection))\n\t\t\t\t\t\tcamAngle = rightTurnAngle;\n\t\t\t\t\telse\n\t\t\t\t\t\tcamAngle = leftTurnAngle;\n\t\t\t\t}\n\t\t\t\tSetLookFlag(camAngle, true);\n\t\t\t\tSetLookTimer(CTimer::GetTimeStepInMilliseconds() * 5.0f);\n\t\t\t} else {\n\t\t\t\tClearLookFlag();\n\t\t\t}\n\t\t}\n\t}\n\tif (m_nMoveState == PEDMOVE_SPRINT && bIsLooking) {\n\t\tClearLookFlag();\n\t\tSetLookTimer(250);\n\t}\n\n\tif (m_vecMoveSpeed.Magnitude2D() < 0.1f) {\n\t\tif (m_nSpeedTimer) {\n\t\t\tif (CTimer::GetTimeInMilliseconds() > m_nSpeedTimer)\n\t\t\t\tm_bSpeedTimerFlag = true;\n\t\t} else {\n\t\t\tm_nSpeedTimer = CTimer::GetTimeInMilliseconds() + 500;\n\t\t}\n\t} else {\n\t\tm_nSpeedTimer = 0;\n\t\tm_bSpeedTimerFlag = false;\n\t}\n\n\tif (bDontAllowWeaponChange && FindPlayerPed() == this) {\n\t\tif (!CPad::GetPad(0)->GetTarget())\n\t\t\tbDontAllowWeaponChange = false;\n\t}\n\n\tif (m_nPedState != PED_SNIPER_MODE && (GetWeapon()->m_eWeaponState == WEAPONSTATE_FIRING || m_nPedState == PED_ATTACK))\n\t\tm_nPadDownPressedInMilliseconds = CTimer::GetTimeInMilliseconds();\n\n\tif (!bIsVisible)\n\t\tUpdateRpHAnim();\n}\n\nbool\nCPlayerPed::DoesPlayerWantNewWeapon(eWeaponType weapon, bool onlyIfSlotIsEmpty)\n{\n\t// GetPadFromPlayer(); // unused\n\tuint32 slot = CWeaponInfo::GetWeaponInfo(weapon)->m_nWeaponSlot;\n\n\tif (!HasWeaponSlot(slot) || GetWeapon(slot).m_eWeaponType == weapon)\n\t\treturn true;\n\n\tif (onlyIfSlotIsEmpty)\n\t\treturn false;\n\n\t// Check if he's using that slot right now.\n\treturn m_nPedState != PED_ATTACK && m_nPedState != PED_AIM_GUN || slot != m_currentWeapon;\n}\n\nvoid\nCPlayerPed::PlayIdleAnimations(CPad *padUsed)\n{\n\tCAnimBlendAssociation* assoc;\n\n\tif (TheCamera.m_WideScreenOn || bIsDucking)\n\t\treturn;\n\n\tstruct animAndGroup {\n\t\tAnimationId animId;\n\t\tAssocGroupId groupId;\n\t};\n\n\tconst animAndGroup idleAnims[] = {\n\t\t{ANIM_PLAYER_IDLE1, ASSOCGRP_PLAYER_IDLE},\n\t\t{ANIM_PLAYER_IDLE2, ASSOCGRP_PLAYER_IDLE},\n\t\t{ANIM_PLAYER_IDLE3, ASSOCGRP_PLAYER_IDLE},\n\t\t{ANIM_PLAYER_IDLE4, ASSOCGRP_PLAYER_IDLE},\n\t\t{ANIM_STD_XPRESS_SCRATCH, ASSOCGRP_STD},\n\t};\n\n\tstatic int32 lastTime = 0;\n\tstatic int32 lastAnim = -1;\n\n\tbool hasIdleAnim = false;\n\tCAnimBlock *idleAnimBlock = CAnimManager::GetAnimationBlock(idleAnimBlockIndex);\n\tuint32 sinceLastInput = padUsed->InputHowLongAgo();\n\tif (sinceLastInput <= 30000) {\n\t\tif (idleAnimBlock->isLoaded) {\n\t\t\tfor (assoc = RpAnimBlendClumpGetFirstAssociation(GetClump()); assoc; assoc = RpAnimBlendGetNextAssociation(assoc)) {\n\t\t\t\tif (assoc->flags & ASSOC_IDLE) {\n\t\t\t\t\thasIdleAnim = true;\n\t\t\t\t\tassoc->blendDelta = -8.0f;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!hasIdleAnim)\n\t\t\t\tCStreaming::RemoveAnim(idleAnimBlockIndex);\n\t\t} else {\n\t\t\tlastTime = 0;\n\t\t}\n\t} else {\n\t\tCStreaming::RequestAnim(idleAnimBlockIndex, STREAMFLAGS_DONT_REMOVE);\n\t\tif (idleAnimBlock->isLoaded) {\n\t\t\tfor(CAnimBlendAssociation *assoc = RpAnimBlendClumpGetFirstAssociation(GetClump()); assoc; assoc = RpAnimBlendGetNextAssociation(assoc)) {\n\t\t\t\tint firstIdle = idleAnimBlock->firstIndex;\n\t\t\t\tint index = assoc->hierarchy - CAnimManager::GetAnimation(0);\n\t\t\t\tif (index >= firstIdle && index < firstIdle + idleAnimBlock->numAnims) {\n\t\t\t\t\thasIdleAnim = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!hasIdleAnim && !bIsLooking && !bIsRestoringLook && sinceLastInput - lastTime > 25000) {\n\t\t\t\tint anim;\n\t\t\t\tdo\n\t\t\t\t\tanim = CGeneral::GetRandomNumberInRange(0, ARRAY_SIZE(idleAnims));\n\t\t\t\twhile (lastAnim == anim);\n\n\t\t\t\tassoc = CAnimManager::BlendAnimation(GetClump(), idleAnims[anim].groupId, idleAnims[anim].animId, 8.0f);\n\t\t\t\tassoc->flags |= ASSOC_IDLE;\n\t\t\t\tlastAnim = anim;\n\t\t\t\tlastTime = sinceLastInput;\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nCPlayerPed::SetNearbyPedsToInteractWithPlayer(void)\n{\n\tif (CGame::noProstitutes)\n\t\treturn;\n\n\tfor (int i = 0; i < m_numNearPeds; ++i) {\n\t\tCPed *nearPed = m_nearPeds[i];\n\t\tif (nearPed && nearPed->m_objectiveTimer < CTimer::GetTimeInMilliseconds() && !CTheScripts::IsPlayerOnAMission()) {\n\t\t\tint mi = nearPed->GetModelIndex();\n\t\t\tif (CPopulation::CanSolicitPlayerOnFoot(mi)) {\n\t\t\t\tCVector distToMe = nearPed->GetPosition() - GetPosition();\n\t\t\t\tCVector dirToMe = GetPosition() - nearPed->GetPosition();\n\t\t\t\tdirToMe.Normalise();\n\t\t\t\tif (DotProduct(dirToMe, nearPed->GetForward()) > 0.707 && DotProduct(GetForward(), nearPed->GetForward()) < -0.707 // those are double\n\t\t\t\t\t&& distToMe.MagnitudeSqr() < 9.0f && nearPed->m_objective == OBJECTIVE_NONE) {\n\t\t\t\t\tnearPed->SetObjective(OBJECTIVE_SOLICIT_FOOT, this);\n\t\t\t\t\tnearPed->m_objectiveTimer = CTimer::GetTimeInMilliseconds() + 10000;\n\t\t\t\t\tnearPed->Say(SOUND_PED_SOLICIT);\n\t\t\t\t}\n\t\t\t} else if (CPopulation::CanSolicitPlayerInCar(mi)) {\n\t\t\t\tif (InVehicle() && m_pMyVehicle->IsVehicleNormal()) {\n\t\t\t\t\tif (m_pMyVehicle->IsCar()) {\n\t\t\t\t\t\tCVector distToVeh = nearPed->GetPosition() - m_pMyVehicle->GetPosition();\n\t\t\t\t\t\tif (distToVeh.MagnitudeSqr() < 25.0f && m_pMyVehicle->IsRoomForPedToLeaveCar(CAR_DOOR_LF, nil) && nearPed->m_objective == OBJECTIVE_NONE) {\n\t\t\t\t\t\t\tnearPed->SetObjective(OBJECTIVE_SOLICIT_VEHICLE, m_pMyVehicle);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nCPlayerPed::UpdateMeleeAttackers(void)\n{\n\tCVector attackCoord;\n\tif (((CTimer::GetFrameCounter() + m_randomSeed + 7) & 3) == 0) {\n\t\tGetMeleeAttackCoords(attackCoord, m_nAttackDirToCheck, 2.0f);\n\n\t\t// Check if there is any vehicle/building inbetween us and m_nAttackDirToCheck. Peds will be able to attack us from those available directions.\n\t\tif (CWorld::GetIsLineOfSightClear(GetPosition(), attackCoord, true, true, false, true, false, false, false)\n\t\t\t&& !CWorld::TestSphereAgainstWorld(attackCoord, 0.4f, m_pMeleeList[m_nAttackDirToCheck], true, true, false, true, false, false)) {\n\t\t\tif (m_pMeleeList[m_nAttackDirToCheck] == this)\n\t\t\t\tm_pMeleeList[m_nAttackDirToCheck] = nil; // mark it as available\n\t\t} else {\n\t\t\tm_pMeleeList[m_nAttackDirToCheck] = this; // slot not available. useful for m_bNoPosForMeleeAttack\n\t\t}\n\t\tif (++m_nAttackDirToCheck >= ARRAY_SIZE(m_pMeleeList))\n\t\t\tm_nAttackDirToCheck = 0;\n\t}\n\t// 6 directions\n\tfor (int i = 0; i < ARRAY_SIZE(m_pMeleeList); ++i) {\n\t\tCPed *victim = m_pMeleeList[i];\n\t\tif (victim && victim != this) {\n\t\t\tif (victim->m_nPedState != PED_DEAD && victim->m_pedInObjective == this)  {\n\t\t\t\tif (victim->m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT || victim->m_objective == OBJECTIVE_KILL_CHAR_ANY_MEANS || victim->m_objective == OBJECTIVE_KILL_CHAR_ON_BOAT) {\n\t\t\t\t\tGetMeleeAttackCoords(attackCoord, i, 2.0f);\n\t\t\t\t\tif ((attackCoord - GetPosition()).MagnitudeSqr() > 12.25f)\n\t\t\t\t\t\tm_pMeleeList[i] = nil;\n\t\t\t\t} else {\n\t\t\t\t\tm_pMeleeList[i] = nil;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tm_pMeleeList[i] = nil;\n\t\t\t}\n\t\t}\n\t}\n\tm_bNoPosForMeleeAttack = m_pMeleeList[0] == this && m_pMeleeList[1] == this && m_pMeleeList[2] == this\n#ifdef FIX_BUGS\n\t\t&& m_pMeleeList[3] == this\n#endif\n\t\t&& m_pMeleeList[4] == this && m_pMeleeList[5] == this;\n}\n\nvoid\nCPlayerPed::RemovePedFromMeleeList(CPed *ped)\n{\n\tint i = 0;\n\tfor (; m_pMeleeList[i] != ped; i++) {\n\t\tif (i >= ARRAY_SIZE(m_pMeleeList))\n\t\t\treturn;\n\t}\n\tm_pMeleeList[i] = nil;\n\tped->m_attackTimer = 0;\n}\n\nvoid\nCPlayerPed::GetMeleeAttackCoords(CVector& coords, int8 dir, float dist)\n{\n\tcoords = GetPosition();\n\tswitch (dir) {\n\t\tcase 0:\n\t\t\tcoords.y += dist;\n\t\t\tbreak;\n\t\tcase 1:\n\t\t\tcoords.x += Sqrt(3.f / 4.f) * dist;\n\t\t\tcoords.y += 0.5f * dist;\n\t\t\tbreak;\n\t\tcase 2:\n\t\t\tcoords.x += Sqrt(3.f / 4.f) * dist;\n\t\t\tcoords.y -= 0.5f * dist;\n\t\t\tbreak;\n\t\tcase 3:\n\t\t\tcoords.y -= dist;\n\t\t\tbreak;\n\t\tcase 4:\n\t\t\tcoords.x -= Sqrt(3.f / 4.f) * dist;\n\t\t\tcoords.y -= 0.5f * dist;\n\t\t\tbreak;\n\t\tcase 5:\n\t\t\tcoords.x -= Sqrt(3.f / 4.f) * dist;\n\t\t\tcoords.y += 0.5f * dist;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t}\n}\n\nint32\nCPlayerPed::FindMeleeAttackPoint(CPed *victim, CVector &dist, uint32 &endOfAttackOut)\n{\n\tendOfAttackOut = 0;\n\tbool thereIsAnEmptySlot = false;\n\tint dirToAttack = -1;\n\tfor (int i = 0; i < ARRAY_SIZE(m_pMeleeList); i++) {\n\t\tCPed* pedAtThisDir = m_pMeleeList[i];\n\t\tif (pedAtThisDir) {\n\t\t\tif (pedAtThisDir == victim) {\n\t\t\t\tdirToAttack = i;\n\t\t\t} else {\n\t\t\t\tif (pedAtThisDir->m_attackTimer > endOfAttackOut)\n\t\t\t\t\tendOfAttackOut = pedAtThisDir->m_attackTimer;\n\t\t\t}\n\t\t} else {\n\t\t\tthereIsAnEmptySlot = true;\n\t\t}\n\t}\n\n\t// We don't have victim ped in our melee list\n\tif (dirToAttack == -1 && thereIsAnEmptySlot) {\n\t\tfloat angle = Atan2(-dist.x, -dist.y);\n\t\tfloat adjustedAngle = angle + DEGTORAD(30.0f);\n\t\tif (adjustedAngle < 0.f)\n\t\t\tadjustedAngle += TWOPI;\n\n\t\tint wantedDir = Floor(adjustedAngle / DEGTORAD(60.0f));\n\n\t\t// And we have another ped at the direction of victim ped, so store victim to next empty direction to it's real direction. (Bollocks)\n\t\tif (m_pMeleeList[wantedDir]) {\n\t\t\tint closestDirToPreferred = -99;\n\t\t\tint preferredDir = wantedDir;\n\n\t\t\tfor (int i = 0; i < ARRAY_SIZE(m_pMeleeList); i++) {\n\t\t\t\tif (!m_pMeleeList[i]) {\n\t\t\t\t\tif (Abs(i - preferredDir) < Abs(closestDirToPreferred - preferredDir))\n\t\t\t\t\t\tclosestDirToPreferred = i;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (closestDirToPreferred > 0)\n\t\t\t\tdirToAttack = closestDirToPreferred;\n\t\t} else {\n\n\t\t\t// Luckily the direction of victim ped is already empty, good\n\t\t\tdirToAttack = wantedDir;\n\t\t}\n\n\t\tif (dirToAttack != -1) {\n\t\t\tm_pMeleeList[dirToAttack] = victim;\n\t\t\tvictim->RegisterReference((CEntity**) &m_pMeleeList[dirToAttack]);\n\t\t\tif (endOfAttackOut > CTimer::GetTimeInMilliseconds())\n\t\t\t\tvictim->m_attackTimer = endOfAttackOut + CGeneral::GetRandomNumberInRange(1000, 2000);\n\t\t\telse\n\t\t\t\tvictim->m_attackTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(500, 1000);\n\t\t}\n\t}\n\treturn dirToAttack;\n}\n\n#ifdef COMPATIBLE_SAVES\n#define CopyFromBuf(buf, data) memcpy(&data, buf, sizeof(data)); SkipSaveBuf(buf, sizeof(data));\n#define CopyToBuf(buf, data) memcpy(buf, &data, sizeof(data)); SkipSaveBuf(buf, sizeof(data));\nvoid\nCPlayerPed::Save(uint8*& buf)\n{\n\tCPed::Save(buf);\n\tSkipSaveBuf(buf, 16);\n\tCopyToBuf(buf, m_fMaxStamina);\n\tSkipSaveBuf(buf, 28);\n\tCopyToBuf(buf, m_nTargettableObjects[0]);\n\tCopyToBuf(buf, m_nTargettableObjects[1]);\n\tCopyToBuf(buf, m_nTargettableObjects[2]);\n\tCopyToBuf(buf, m_nTargettableObjects[3]);\n\tSkipSaveBuf(buf, 164);\n}\n\nvoid\nCPlayerPed::Load(uint8*& buf)\n{\n\tCPed::Load(buf);\n\tSkipSaveBuf(buf, 16);\n\tCopyFromBuf(buf, m_fMaxStamina);\n\tSkipSaveBuf(buf, 28);\n\tCopyFromBuf(buf, m_nTargettableObjects[0]);\n\tCopyFromBuf(buf, m_nTargettableObjects[1]);\n\tCopyFromBuf(buf, m_nTargettableObjects[2]);\n\tCopyFromBuf(buf, m_nTargettableObjects[3]);\n\tSkipSaveBuf(buf, 164);\n}\n#undef CopyFromBuf\n#undef CopyToBuf\n#endif\n"
  },
  {
    "path": "src/peds/PlayerPed.h",
    "content": "#pragma once\n\n#include \"Ped.h\"\n\nclass CPad;\nclass CCopPed;\nclass CWanted;\n\nclass CPlayerPed : public CPed\n{\npublic:\n\tCWanted *m_pWanted;\n\tCCopPed *m_pArrestingCop;\n\tfloat m_fMoveSpeed;\n\tfloat m_fCurrentStamina;\n\tfloat m_fMaxStamina;\n\tfloat m_fStaminaProgress;\n\tint8 m_nSelectedWepSlot;\n\tbool m_bSpeedTimerFlag;\n\tuint8 m_nEvadeAmount;\n\tuint32 m_nSpeedTimer; // m_nStandStillTimer?\n\tuint32 m_nHitAnimDelayTimer; // m_nShotDelay?\n\tfloat m_fAttackButtonCounter;\n\tbool m_bHaveTargetSelected;\t// may have better name\n\tCEntity *m_pEvadingFrom;\t// is this CPhysical?\n\tint32 m_nTargettableObjects[4];\n\tuint32 m_nAdrenalineTime;\n\tuint8 m_nDrunkenness;             // Needed to work out whether we lost target this frame\n\tuint8 m_nFadeDrunkenness;\n\tuint8 m_nDrunkCountdown; //countdown in frames when the drunk effect ends\n\tbool m_bAdrenalineActive;\n\tbool m_bHasLockOnTarget;\n\tbool m_bCanBeDamaged;\n\tbool m_bNoPosForMeleeAttack;\n\tbool unk1;\n\tCVector m_vecSafePos[6]; // safe places from the player, for example behind a tree\n\tCPed *m_pPedAtSafePos[6];\n\tCPed *m_pMeleeList[6]; // reachable peds at each direction(6)\n\tint16 m_nAttackDirToCheck;\n\tfloat m_fWalkAngle; //angle between heading and walking direction\n\tfloat m_fFPSMoveHeading;\n\tRpAtomic* m_pMinigunTopAtomic; //atomic for the spinning part of the minigun model\n\tfloat m_fGunSpinSpeed; // for minigun\n\tfloat m_fGunSpinAngle;\n\tunsigned int m_nPadDownPressedInMilliseconds;\n\tunsigned int m_nLastBusFareCollected;\n\n\tstatic bool bDontAllowWeaponChange;\n#ifndef MASTER\n\tstatic bool bDebugPlayerInfo;\n#endif\n\n\tCPlayerPed();\n\t~CPlayerPed();\n\tvoid SetMoveAnim() { };\n\n\tvoid ReApplyMoveAnims(void);\n\tvoid ClearWeaponTarget(void);\n\tvoid SetWantedLevel(int32 level);\n\tvoid SetWantedLevelNoDrop(int32 level);\n\tvoid KeepAreaAroundPlayerClear(void);\n\tvoid AnnoyPlayerPed(bool);\n\tvoid MakeChangesForNewWeapon(int32);\n\tvoid MakeChangesForNewWeapon(eWeaponType);\n\tvoid SetInitialState(void);\n\tvoid ProcessControl(void);\n\tvoid ClearAdrenaline(void);\n\tvoid UseSprintEnergy(void);\n\tclass CPlayerInfo *GetPlayerInfoForThisPlayerPed();\n\tvoid SetRealMoveAnim(void);\n\tvoid RestoreSprintEnergy(float);\n\tfloat DoWeaponSmoothSpray(void);\n\tvoid DoStuffToGoOnFire(void);\n\tbool DoesTargetHaveToBeBroken(CVector, CWeapon*);\n\tvoid RunningLand(CPad*);\n\tbool IsThisPedAnAimingPriority(CPed*);\n\tvoid PlayerControlSniper(CPad*);\n\tvoid PlayerControlM16(CPad*);\n\tvoid PlayerControlFighter(CPad*);\n\tvoid ProcessWeaponSwitch(CPad*);\n\tvoid MakeObjectTargettable(int32);\n\tvoid PlayerControl1stPersonRunAround(CPad *padUsed);\n\tvoid EvaluateNeighbouringTarget(CEntity*, CEntity**, float*, float, float, bool, bool);\n\tvoid EvaluateTarget(CEntity*, CEntity**, float*, float, float, bool);\n\tbool FindNextWeaponLockOnTarget(CEntity*, bool);\n\tbool FindWeaponLockOnTarget(void);\n\tvoid ProcessAnimGroups(void);\n\tvoid ProcessPlayerWeapon(CPad*);\n\tvoid PlayerControlZelda(CPad*);\n\tbool DoesPlayerWantNewWeapon(eWeaponType, bool);\n\tvoid PlayIdleAnimations(CPad*);\n\tvoid RemovePedFromMeleeList(CPed*);\n\tvoid GetMeleeAttackCoords(CVector&, int8, float);\n\tint32 FindMeleeAttackPoint(CPed*, CVector&, uint32&);\n\tbool CanIKReachThisTarget(CVector, CWeapon*, bool);\n\tvoid RotatePlayerToTrackTarget(void);\n\tbool MovementDisabledBecauseOfTargeting(void);\n\tvoid FindNewAttackPoints(void);\n\tvoid SetNearbyPedsToInteractWithPlayer(void);\n\tvoid UpdateMeleeAttackers(void);\n\n\tstatic void SetupPlayerPed(int32);\n\tstatic void DeactivatePlayerPed(int32);\n\tstatic void ReactivatePlayerPed(int32);\n\n#ifdef COMPATIBLE_SAVES\n\tvirtual void Save(uint8*& buf);\n\tvirtual void Load(uint8*& buf);\n#endif\n\n\tstatic const uint32 nSaveStructSize;\n};\n\n//VALIDATE_SIZE(CPlayerPed, 0x5F0);\n"
  },
  {
    "path": "src/peds/Population.cpp",
    "content": "#include \"common.h\"\n\n#include \"Game.h\"\n#include \"General.h\"\n#include \"World.h\"\n#include \"Population.h\"\n#include \"CopPed.h\"\n#include \"Wanted.h\"\n#include \"FileMgr.h\"\n#include \"Gangs.h\"\n#include \"ModelIndices.h\"\n#include \"Zones.h\"\n#include \"CivilianPed.h\"\n#include \"EmergencyPed.h\"\n#include \"Replay.h\"\n#include \"Camera.h\"\n#include \"CutsceneMgr.h\"\n#include \"CarCtrl.h\"\n#include \"IniFile.h\"\n#include \"VisibilityPlugins.h\"\n#include \"PedPlacement.h\"\n#include \"DummyObject.h\"\n#include \"Script.h\"\n#include \"Shadows.h\"\n#include \"SurfaceTable.h\"\n#include \"Weather.h\"\n#include \"Darkel.h\"\n#include \"Streaming.h\"\n#include \"Clock.h\"\n#include \"WaterLevel.h\"\n\n#define MIN_CREATION_DIST\t\t40.0f // not for start of the game (look at the GeneratePedsAtStartOfGame)\n#define CREATION_RANGE\t\t\t10.0f // added over the MIN_CREATION_DIST.\n#define OFFSCREEN_CREATION_MULT\t0.5f\n#define PED_REMOVE_DIST\t\t\t(MIN_CREATION_DIST + CREATION_RANGE + 1.0f)\n#define PED_REMOVE_DIST_SPECIAL\t(MIN_CREATION_DIST + CREATION_RANGE + 15.0f) // for peds with bCullExtraFarAway flag\n\nPedGroup CPopulation::ms_pPedGroups[NUMPEDGROUPS];\nbool CPopulation::ms_bGivePedsWeapons;\nint32 CPopulation::m_AllRandomPedsThisType = -1;\nfloat CPopulation::PedDensityMultiplier = 1.0f;\nuint32 CPopulation::ms_nTotalMissionPeds;\nint32 CPopulation::MaxNumberOfPedsInUse = 25;\nint32 CPopulation::MaxNumberOfPedsInUseInterior = 40;\nuint32 CPopulation::ms_nNumCivMale;\nuint32 CPopulation::ms_nNumCivFemale;\nuint32 CPopulation::ms_nNumCop;\nbool CPopulation::bZoneChangeHasHappened;\nuint32 CPopulation::ms_nNumEmergency;\nint8 CPopulation::m_CountDownToPedsAtStart;\nuint32 CPopulation::ms_nNumGang1;\nuint32 CPopulation::ms_nNumGang2;\nuint32 CPopulation::ms_nTotalPeds;\nuint32 CPopulation::ms_nNumGang3;\nuint32 CPopulation::ms_nTotalGangPeds;\nuint32 CPopulation::ms_nNumGang4;\nuint32 CPopulation::ms_nTotalCivPeds;\nuint32 CPopulation::ms_nNumGang5;\nuint32 CPopulation::ms_nNumDummy;\nuint32 CPopulation::ms_nNumGang6;\nuint32 CPopulation::ms_nNumGang9;\nuint32 CPopulation::ms_nNumGang7;\nuint32 CPopulation::ms_nNumGang8;\n\nuint32 CPopulation::ms_nTotalCarPassengerPeds;\nuint32 CPopulation::NumMiamiViceCops;\n\nuint32 gLastSelectedCivilianIndex;\nCEntity *gSunbatheObstacles[2];\nCEntity *gCoupleObstacles[3];\n\nvoid\nCPopulation::Initialise()\n{\n\tdebug(\"Initialising CPopulation...\\n\");\n\n\tms_nNumCivMale = 0;\n\tms_nNumCivFemale = 0;\n\tms_nNumCop = 0;\n\tms_nNumEmergency = 0;\n\tms_nNumGang1 = 0;\n\tms_nNumGang2 = 0;\n\tms_nNumGang3 = 0;\n\tms_nNumGang4 = 0;\n\tms_nNumGang5 = 0;\n\tms_nNumGang6 = 0;\n\tms_nNumGang7 = 0;\n\tms_nNumGang8 = 0;\n\tms_nNumGang9 = 0;\n\tms_nNumDummy = 0;\n\n\tms_nTotalCarPassengerPeds = 0;\n\tms_nTotalCivPeds = 0;\n\tms_nTotalGangPeds = 0;\n\tms_nTotalPeds = 0;\n\tms_nTotalMissionPeds = 0;\n\tm_CountDownToPedsAtStart = 2;\n\tbZoneChangeHasHappened = false; // III leftover\n\n\tm_AllRandomPedsThisType = -1;\n\tPedDensityMultiplier = 1.0f;\n\t\n\n\tLoadPedGroups();\n\n\tdebug(\"CPopulation ready\\n\");\n}\n\nvoid\nCPopulation::RemovePed(CPed *ent)\n{\n\tCWorld::Remove((CEntity*)ent);\n\tdelete ent;\n}\n\nint32\nCPopulation::ChooseCivilianOccupation(int32 group)\n{\n\tif (CWeather::Rain > 0.1f) {\n\t\tint32 lastModel;\n\t\tfor (int i = 0; i < 8; i++) {\n\t\t\tgLastSelectedCivilianIndex = CGeneral::GetRandomNumberInRange(0, NUMMODELSPERPEDGROUP);\n\t\t\tlastModel = ms_pPedGroups[group].models[gLastSelectedCivilianIndex];\n\n\t\t\tif (!CPopulation::IsSunbather(lastModel))\n\t\t\t\tbreak;\n\t\t}\n\t\treturn lastModel;\n\n\t} else {\n\t\tgLastSelectedCivilianIndex = CGeneral::GetRandomNumberInRange(0, NUMMODELSPERPEDGROUP);\n\t\treturn ms_pPedGroups[group].models[gLastSelectedCivilianIndex];\n\t}\n}\n\nint32\nCPopulation::ChooseNextCivilianOccupation(int32 group)\n{\n\tif (CWeather::Rain > 0.1f) {\n\t\tint32 lastModel;\n\t\tfor (int i = 0; i < NUMMODELSPERPEDGROUP; i++) {\n\t\t\t++gLastSelectedCivilianIndex;\n\t\t\tif (gLastSelectedCivilianIndex >= NUMMODELSPERPEDGROUP)\n\t\t\t\tgLastSelectedCivilianIndex = 0;\n\t\t\tlastModel = ms_pPedGroups[group].models[gLastSelectedCivilianIndex];\n\n\t\t\tif (!CPopulation::IsSunbather(ms_pPedGroups[group].models[gLastSelectedCivilianIndex]))\n\t\t\t\tbreak;\n\t\t}\n\t\treturn lastModel;\n\n\t} else {\n\t\t++gLastSelectedCivilianIndex;\n\t\tif (gLastSelectedCivilianIndex >= NUMMODELSPERPEDGROUP)\n\t\t\tgLastSelectedCivilianIndex = 0;\n\t\treturn ms_pPedGroups[group].models[gLastSelectedCivilianIndex];\n\t}\n}\n\n// returns eCopType\nint32\nCPopulation::ChoosePolicePedOccupation()\n{\n\tCGeneral::GetRandomNumber();\n\treturn COP_STREET;\n}\n\nvoid\nCPopulation::LoadPedGroups()\n{\n\tint fd;\n\tchar line[1024];\n\tint nextPedGroup = 0;\n\t// char unused[16]; // non-existence of that in mobile kinda verifies that\n\tchar modelName[256];\n\n\tCFileMgr::ChangeDir(\"\\\\DATA\\\\\");\n\tfd = CFileMgr::OpenFile(\"PEDGRP.DAT\", \"r\");\n\tCFileMgr::ChangeDir(\"\\\\\");\n\twhile (CFileMgr::ReadLine(fd, line, sizeof(line))) {\n\t\tint end;\n\t\t// find end of line\n\t\tfor (end = 0; ; end++) {\n\t\t\tif (line[end] == '\\n')\n\t\t\t\tbreak;\n\t\t\tif (line[end] == ',' || line[end] == '\\r')\n\t\t\t\tline[end] = ' ';\n\t\t}\n\t\tline[end] = '\\0';\n\t\tint cursor = 0;\n\t\tint i;\n\t\tfor (i = 0; i < NUMMODELSPERPEDGROUP; i++) {\n\t\t\twhile (line[cursor] <= ' ' && line[cursor] != '\\0')\n\t\t\t\t++cursor;\n\n\t\t\tif (line[cursor] == '#')\n\t\t\t\tbreak;\n\n\t\t\t// find next whitespace\n\t\t\tint nextWhitespace;\n\t\t\tfor (nextWhitespace = cursor; line[nextWhitespace] > ' '; ++nextWhitespace)\n\t\t\t\t;\n\n\t\t\tif (cursor == nextWhitespace)\n\t\t\t\tbreak;\n\t\t\t\n\t\t\t// read until next whitespace\n\t\t\tstrncpy(modelName, &line[cursor], nextWhitespace - cursor);\n\t\t\tmodelName[nextWhitespace - cursor] = '\\0';\n\t\t\tCModelInfo::GetModelInfo(modelName, &ms_pPedGroups[nextPedGroup].models[i]);\n\t\t\tcursor = nextWhitespace;\n\t\t}\n\t\tif (i == NUMMODELSPERPEDGROUP)\n\t\t\tnextPedGroup++;\n\t}\n\tCFileMgr::CloseFile(fd);\n}\n\nvoid\nCPopulation::UpdatePedCount(ePedType pedType, bool decrease)\n{\n\tif (decrease) {\n\t\tswitch (pedType) {\n\t\t\tcase PEDTYPE_PLAYER1:\n\t\t\tcase PEDTYPE_PLAYER2:\n\t\t\tcase PEDTYPE_PLAYER3:\n\t\t\tcase PEDTYPE_PLAYER4:\n\t\t\tcase PEDTYPE_UNUSED1:\n\t\t\tcase PEDTYPE_SPECIAL:\n\t\t\t\treturn;\n\t\t\tcase PEDTYPE_CIVMALE:\n\t\t\t\t--ms_nNumCivMale;\n\t\t\t\tbreak;\n\t\t\tcase PEDTYPE_CIVFEMALE:\n\t\t\t\t--ms_nNumCivFemale;\n\t\t\t\tbreak;\n\t\t\tcase PEDTYPE_COP:\n\t\t\t\t--ms_nNumCop;\n\t\t\t\tbreak;\n\t\t\tcase PEDTYPE_GANG1:\n\t\t\t\t--ms_nNumGang1;\n\t\t\t\tbreak;\n\t\t\tcase PEDTYPE_GANG2:\n\t\t\t\t--ms_nNumGang2;\n\t\t\t\tbreak;\n\t\t\tcase PEDTYPE_GANG3:\n\t\t\t\t--ms_nNumGang3;\n\t\t\t\tbreak;\n\t\t\tcase PEDTYPE_GANG4:\n\t\t\t\t--ms_nNumGang4;\n\t\t\t\tbreak;\n\t\t\tcase PEDTYPE_GANG5:\n\t\t\t\t--ms_nNumGang5;\n\t\t\t\tbreak;\n\t\t\tcase PEDTYPE_GANG6:\n\t\t\t\t--ms_nNumGang6;\n\t\t\t\tbreak;\n\t\t\tcase PEDTYPE_GANG7:\n\t\t\t\t--ms_nNumGang7;\n\t\t\t\tbreak;\n\t\t\tcase PEDTYPE_GANG8:\n\t\t\t\t--ms_nNumGang8;\n\t\t\t\tbreak;\n\t\t\tcase PEDTYPE_GANG9:\n\t\t\t\t--ms_nNumGang9;\n\t\t\t\tbreak;\n\t\t\tcase PEDTYPE_EMERGENCY:\n\t\t\tcase PEDTYPE_FIREMAN:\n\t\t\t\t--ms_nNumEmergency;\n\t\t\t\tbreak;\n\t\t\tcase PEDTYPE_CRIMINAL:\n\t\t\t\t--ms_nNumCivMale;\n\t\t\t\tbreak;\n\t\t\tcase PEDTYPE_PROSTITUTE:\n\t\t\t\t--ms_nNumCivFemale;\n\t\t\t\tbreak;\n\t\t\tcase PEDTYPE_UNUSED2:\n\t\t\t\t--ms_nNumDummy;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tError(\"Unknown ped type, UpdatePedCount, Population.cpp\");\n\t\t\t\tbreak;\n\t\t}\n\t} else {\n\t\tswitch (pedType) {\n\t\t\tcase PEDTYPE_PLAYER1:\n\t\t\tcase PEDTYPE_PLAYER2:\n\t\t\tcase PEDTYPE_PLAYER3:\n\t\t\tcase PEDTYPE_PLAYER4:\n\t\t\tcase PEDTYPE_UNUSED1:\n\t\t\tcase PEDTYPE_SPECIAL:\n\t\t\t\treturn;\n\t\t\tcase PEDTYPE_CIVMALE:\n\t\t\t\t++ms_nNumCivMale;\n\t\t\t\tbreak;\n\t\t\tcase PEDTYPE_CIVFEMALE:\n\t\t\t\t++ms_nNumCivFemale;\n\t\t\t\tbreak;\n\t\t\tcase PEDTYPE_COP:\n\t\t\t\t++ms_nNumCop;\n\t\t\t\tbreak;\n\t\t\tcase PEDTYPE_GANG1:\n\t\t\t\t++ms_nNumGang1;\n\t\t\t\tbreak;\n\t\t\tcase PEDTYPE_GANG2:\n\t\t\t\t++ms_nNumGang2;\n\t\t\t\tbreak;\n\t\t\tcase PEDTYPE_GANG3:\n\t\t\t\t++ms_nNumGang3;\n\t\t\t\tbreak;\n\t\t\tcase PEDTYPE_GANG4:\n\t\t\t\t++ms_nNumGang4;\n\t\t\t\tbreak;\n\t\t\tcase PEDTYPE_GANG5:\n\t\t\t\t++ms_nNumGang5;\n\t\t\t\tbreak;\n\t\t\tcase PEDTYPE_GANG6:\n\t\t\t\t++ms_nNumGang6;\n\t\t\t\tbreak;\n\t\t\tcase PEDTYPE_GANG7:\n\t\t\t\t++ms_nNumGang7;\n\t\t\t\tbreak;\n\t\t\tcase PEDTYPE_GANG8:\n\t\t\t\t++ms_nNumGang8;\n\t\t\t\tbreak;\n\t\t\tcase PEDTYPE_GANG9:\n\t\t\t\t++ms_nNumGang9;\n\t\t\t\tbreak;\n\t\t\tcase PEDTYPE_EMERGENCY:\n\t\t\tcase PEDTYPE_FIREMAN:\n\t\t\t\t++ms_nNumEmergency;\n\t\t\t\tbreak;\n\t\t\tcase PEDTYPE_CRIMINAL:\n\t\t\t\t++ms_nNumCivMale;\n\t\t\t\tbreak;\n\t\t\tcase PEDTYPE_PROSTITUTE:\n\t\t\t\t++ms_nNumCivFemale;\n\t\t\t\tbreak;\n\t\t\tcase PEDTYPE_UNUSED2:\n\t\t\t\t++ms_nNumDummy;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tError(\"Unknown ped type, UpdatePedCount, Population.cpp\");\n\t\t\t\tbreak;\n\t\t}\n\t}\n}\n\nint\nCPopulation::ChooseGangOccupation(int gangId)\n{\n\treturn CGangs::ChooseGangPedModel(gangId);\n}\n\nvoid\nCPopulation::DealWithZoneChange(eLevelName oldLevel, eLevelName newLevel, bool forceIndustrialZone)\n{\n}\n\nvoid\nCPopulation::Update(bool addPeds)\n{\n\tif (!CReplay::IsPlayingBack()) {\n\t\tManagePopulation();\n\t\tRemovePedsIfThePoolGetsFull();\n\t\tMoveCarsAndPedsOutOfAbandonedZones();\n\t\tif (m_CountDownToPedsAtStart != 0) {\n\t\t\tif (--m_CountDownToPedsAtStart == 0)\n\t\t\t\tGeneratePedsAtStartOfGame();\n\t\t} else {\n\t\t\tms_nTotalCivPeds = ms_nNumCivFemale + ms_nNumCivMale;\n\t\t\tms_nTotalGangPeds = ms_nNumGang9 + ms_nNumGang8 + ms_nNumGang7\n\t\t\t\t+ ms_nNumGang6 + ms_nNumGang5 + ms_nNumGang4 + ms_nNumGang3\n\t\t\t\t+ ms_nNumGang2 + ms_nNumGang1;\n\t\t\tms_nTotalPeds = ms_nNumDummy + ms_nNumEmergency + ms_nNumCop\n\t\t\t\t+ ms_nTotalGangPeds + ms_nNumCivFemale + ms_nNumCivMale;\n\t\t\tms_nTotalPeds -= ms_nTotalCarPassengerPeds;\n\t\t\tif (!CCutsceneMgr::IsRunning() && addPeds) {\n\t\t\t\tfloat pcdm = PedCreationDistMultiplier();\n\t\t\t\tAddToPopulation(pcdm * (MIN_CREATION_DIST * TheCamera.GenerationDistMultiplier),\n\t\t\t\t\tpcdm * ((MIN_CREATION_DIST + CREATION_RANGE) * TheCamera.GenerationDistMultiplier),\n\t\t\t\t\tpcdm * (MIN_CREATION_DIST + CREATION_RANGE) * OFFSCREEN_CREATION_MULT - CREATION_RANGE,\n\t\t\t\t\tpcdm * (MIN_CREATION_DIST + CREATION_RANGE) * OFFSCREEN_CREATION_MULT);\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nCPopulation::GeneratePedsAtStartOfGame()\n{\n\tfor (int i = 0; i < 100; i++) {\n\t\tms_nTotalCivPeds = ms_nNumCivFemale + ms_nNumCivMale;\n\t\tms_nTotalGangPeds = ms_nNumGang9 + ms_nNumGang8 + ms_nNumGang7\n\t\t\t+ ms_nNumGang6 + ms_nNumGang5 + ms_nNumGang4\n\t\t\t+ ms_nNumGang3 + ms_nNumGang2 + ms_nNumGang1;\n\t\tms_nTotalPeds = ms_nNumDummy + ms_nNumEmergency + ms_nNumCop\n\t\t\t+ ms_nTotalGangPeds + ms_nNumCivFemale + ms_nNumCivMale;\n\t\tms_nTotalPeds -= ms_nTotalCarPassengerPeds;\n\n\t\t// Min dist is 10.0f only for start of the game (naturally)\n\t\tAddToPopulation(10.0f, PedCreationDistMultiplier() * (MIN_CREATION_DIST + CREATION_RANGE),\n\t\t\t10.0f, PedCreationDistMultiplier() * (MIN_CREATION_DIST + CREATION_RANGE));\n\t}\n}\n\n// More speed = wider area to spawn peds\nfloat\nCPopulation::PedCreationDistMultiplier()\n{\n\tCVehicle *veh = FindPlayerVehicle();\n\tif (!veh)\n\t\treturn 1.0f;\n\n\tfloat vehSpeed = veh->m_vecMoveSpeed.Magnitude2D();\n\treturn clamp(vehSpeed - 0.1f + 1.0f, 1.0f, 1.5f);\n}\n\nCPed*\nCPopulation::AddPed(ePedType pedType, uint32 miOrCopType, CVector const &coors, int32 modifier)\n{\n\tswitch (pedType) {\n\t\tcase PEDTYPE_CIVMALE:\n\t\tcase PEDTYPE_CIVFEMALE:\n\t\t{\n\t\t\tCCivilianPed *ped = new CCivilianPed(pedType, miOrCopType);\n\t\t\tped->SetPosition(coors);\n\t\t\tped->SetOrientation(0.0f, 0.0f, 0.0f);\n\t\t\tCWorld::Add(ped);\n\t\t\tif (ms_bGivePedsWeapons) {\n\t\t\t\teWeaponType weapon;\n\n\t\t\t\tswitch (CGeneral::GetRandomNumber() & 3) {\n\t\t\t\t\tcase 0:\n\t\t\t\t\t\tweapon = WEAPONTYPE_COLT45;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 1:\n\t\t\t\t\t\tweapon = WEAPONTYPE_NIGHTSTICK;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 2:\n\t\t\t\t\t\tweapon = WEAPONTYPE_GOLFCLUB;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 3:\n\t\t\t\t\t\tweapon = WEAPONTYPE_TEC9;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif (weapon != WEAPONTYPE_UNARMED) {\n\t\t\t\t\tped->GiveDelayedWeapon(weapon, 25001);\n\t\t\t\t\tped->SetCurrentWeapon(CWeaponInfo::GetWeaponInfo(weapon)->m_nWeaponSlot);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn ped;\n\t\t}\n\t\tcase PEDTYPE_COP:\n\t\t{\n\t\t\tCCopPed *ped = new CCopPed((eCopType)miOrCopType, modifier);\n\t\t\tped->SetPosition(coors);\n\t\t\tped->SetOrientation(0.0f, 0.0f, 0.0f);\n\t\t\tCWorld::Add(ped);\n\t\t\treturn ped;\n\t\t}\n\t\tcase PEDTYPE_GANG1:\n\t\tcase PEDTYPE_GANG2:\n\t\tcase PEDTYPE_GANG3:\n\t\tcase PEDTYPE_GANG4:\n\t\tcase PEDTYPE_GANG5:\n\t\tcase PEDTYPE_GANG6:\n\t\tcase PEDTYPE_GANG7:\n\t\tcase PEDTYPE_GANG8:\n\t\tcase PEDTYPE_GANG9:\n\t\t{\n\t\t\tCCivilianPed *ped = new CCivilianPed(pedType, miOrCopType);\n\t\t\tped->SetPosition(coors);\n\t\t\tped->SetOrientation(0.0f, 0.0f, 0.0f);\n\t\t\tCWorld::Add(ped);\n\n\t\t\teWeaponType weapon;\n\t\t\tif (CGeneral::GetRandomNumberInRange(0, 100) >= 50)\n\t\t\t\tweapon = (eWeaponType)CGangs::GetGangInfo(pedType - PEDTYPE_GANG1)->m_Weapon2;\n\t\t\telse\n\t\t\t\tweapon = (eWeaponType)CGangs::GetGangInfo(pedType - PEDTYPE_GANG1)->m_Weapon1;\n\n\t\t\tped->GiveDelayedWeapon(weapon, 25001);\n\t\t\tped->SetCurrentWeapon(CWeaponInfo::GetWeaponInfo(weapon)->m_nWeaponSlot);\n\t\t\treturn ped;\n\t\t}\n\t\tcase PEDTYPE_EMERGENCY:\n\t\t{\n\t\t\tCEmergencyPed *ped = new CEmergencyPed(PEDTYPE_EMERGENCY);\n\t\t    ped->SetPosition(coors);\n\t\t\tped->SetOrientation(0.0f, 0.0f, 0.0f);\n\t\t\tCWorld::Add(ped);\n\t\t\treturn ped;\n\t\t}\n\t\tcase PEDTYPE_FIREMAN:\n\t\t{\n\t\t\tCEmergencyPed *ped = new CEmergencyPed(PEDTYPE_FIREMAN);\n\t\t    ped->SetPosition(coors);\n\t\t\tped->SetOrientation(0.0f, 0.0f, 0.0f);\n\t\t\tCWorld::Add(ped);\n\t\t\treturn ped;\n\t\t}\n\t\tcase PEDTYPE_CRIMINAL:\n\t\tcase PEDTYPE_PROSTITUTE:\n\t\t{\n\t\t\tCCivilianPed *ped = new CCivilianPed(pedType, miOrCopType);\n\t\t\tped->SetPosition(coors);\n\t\t\tped->SetOrientation(0.0f, 0.0f, 0.0f);\n\t\t\tCWorld::Add(ped);\n\t\t\treturn ped;\n\t\t}\n\t\tdefault:\n\t\t\tError(\"Unknown ped type, AddPed, Population.cpp\");\n\t\t\treturn nil;\n\t}\n}\n\nvoid\nCPopulation::AddToPopulation(float minDist, float maxDist, float minDistOffScreen, float maxDistOffScreen)\n{\n\tuint32 pedTypeToAdd;\n\tint32 modelToAdd;\n\tint pedAmount;\n\n\tCZoneInfo zoneInfo;\n\tint32 man = -1, woman = -1;\n\tCPed *gangLeader = nil;\n\tbool addCop = false;\n\tbool isSecurityGuard = false;\n\tbool forceAddingCop = false;\n\tCPlayerInfo *playerInfo = &CWorld::Players[CWorld::PlayerInFocus];\n\tCVector playerCentreOfWorld = FindPlayerCentreOfWorld(CWorld::PlayerInFocus);\n\tCTheZones::GetZoneInfoForTimeOfDay(&playerCentreOfWorld, &zoneInfo);\n\tCWanted *wantedInfo = playerInfo->m_pPed->m_pWanted;\n\n\tif (wantedInfo->GetWantedLevel() > 2) {\n\t\tif (!CGame::IsInInterior() && (CGeneral::GetRandomNumber() % 32 == 0) && FindPlayerVehicle())\n\t\t\tforceAddingCop = true;\n\n\t\tuint32 maxCops = CGame::IsInInterior() ? wantedInfo->m_MaxCops * 1.6f : wantedInfo->m_MaxCops;\n\t\tif ((ms_nNumCop < maxCops || forceAddingCop) &&\n\t\t\t(!playerInfo->m_pPed->bInVehicle &&\n\t\t\t\t(CCarCtrl::NumLawEnforcerCars >= wantedInfo->m_MaximumLawEnforcerVehicles\n\t\t\t\t|| CCarCtrl::NumRandomCars >= playerInfo->m_nTrafficMultiplier * CCarCtrl::CarDensityMultiplier\n\t\t\t\t|| CCarCtrl::NumFiretrucksOnDuty + CCarCtrl::NumAmbulancesOnDuty + CCarCtrl::NumParkedCars\n\t\t\t\t+ CCarCtrl::NumMissionCars + CCarCtrl::NumLawEnforcerCars + CCarCtrl::NumRandomCars >= CCarCtrl::MaxNumberOfCarsInUse) || forceAddingCop)) {\n\t\t\taddCop = true;\n\t\t\tminDist = PedCreationDistMultiplier() * MIN_CREATION_DIST;\n\t\t\tmaxDist = PedCreationDistMultiplier() * (MIN_CREATION_DIST + CREATION_RANGE);\n\t\t}\n\t}\n\tfloat missionAndWeatherMult = -0.8f * Sqrt(CWeather::Rain) + 1.0f;\n\n\t// Taxi side mission\n\tif (CTheScripts::IsPlayerOnAMission()) {\n\t\tCPed *player = FindPlayerPed();\n\t\tif (player && player->InVehicle() && player->m_pMyVehicle->IsTaxi())\n\t\t\tmissionAndWeatherMult = 1.0f;\n\t}\n\tif (CDarkel::FrenzyOnGoing())\n\t\tmissionAndWeatherMult = 1.0f;\n\tint selectedMaxPeds = CGame::IsInInterior() ? CPopulation::MaxNumberOfPedsInUseInterior : CPopulation::MaxNumberOfPedsInUse;\n\n\t// Yeah, float\n\tfloat maxPossiblePedsForArea = (zoneInfo.pedDensity + zoneInfo.carDensity) * playerInfo->m_fRoadDensity * PedDensityMultiplier\n\t\t* (CDarkel::FrenzyOnGoing() ? 1.f : CIniFile::PedNumberMultiplier) * missionAndWeatherMult;\n\tmaxPossiblePedsForArea = Min(maxPossiblePedsForArea, selectedMaxPeds);\n\n\tif (ms_nTotalPeds < maxPossiblePedsForArea || addCop) {\n\t\tint decisionThreshold = CGeneral::GetRandomNumberInRange(0, 1000);\n\t\tif (decisionThreshold < zoneInfo.copPedThreshold || addCop) {\n\t\t\tpedTypeToAdd = PEDTYPE_COP;\n\t\t\tmodelToAdd = ChoosePolicePedOccupation();\n\t\t} else {\n\t\t\tint i = 0;\n\t\t\tfor (i = 0; i < NUM_GANGS; i++) {\n\t\t\t\tif (decisionThreshold < zoneInfo.gangPedThreshold[i]) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (i == NUM_GANGS) {\n\t\t\t\tif (CGeneral::GetRandomNumberInRange(0.0f, 1.0f) <= 0.95f) {\n\t\t\t\t\tmodelToAdd = ChooseCivilianOccupation(zoneInfo.pedGroup);\n\n\t\t\t\t\tif (modelToAdd == -1)\n\t\t\t\t\t\treturn;\n\t\t\t\t\tpedTypeToAdd = ((CPedModelInfo*)CModelInfo::GetModelInfo(modelToAdd))->m_pedType;\n\n\t\t\t\t} else {\n\t\t\t\t\tChooseCivilianCoupleOccupations(zoneInfo.pedGroup, man, woman);\n\t\t\t\t\tif (man == -1 || woman == -1)\n\t\t\t\t\t\treturn;\n\t\t\t\t\tpedTypeToAdd = ((CPedModelInfo*)CModelInfo::GetModelInfo(woman))->m_pedType;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tpedTypeToAdd = PEDTYPE_GANG1 + i;\n\n\t\t\t\tif (IsSecurityGuard((ePedType)pedTypeToAdd)) {\n\t\t\t\t\tisSecurityGuard = true;\n\t\t\t\t\tmodelToAdd = ChooseGangOccupation(pedTypeToAdd - PEDTYPE_GANG1);\n\n\t\t\t\t\tif (modelToAdd == -1)\n\t\t\t\t\t\treturn;\n\t\t\t\t\tpedTypeToAdd = ((CPedModelInfo*)CModelInfo::GetModelInfo(modelToAdd))->m_pedType;\n\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (!addCop && m_AllRandomPedsThisType > PEDTYPE_PLAYER1)\n\t\t\tpedTypeToAdd = m_AllRandomPedsThisType;\n\n\t\tif (pedTypeToAdd >= PEDTYPE_GANG1 && pedTypeToAdd <= PEDTYPE_GANG9 && !isSecurityGuard) {\n\t\t\tminDist += 30.0f;\n\t\t\tmaxDist += 30.0f;\n\t\t\tpedAmount = ComputeRandomisedGangSize();\n\t\t} else\n\t\t\tpedAmount = 1;\n\n\t\tCVector generatedCoors;\n\t\tint node1, node2;\n\t\tfloat randomPos;\n\t\tbool foundCoors = !!ThePaths.GeneratePedCreationCoors(playerCentreOfWorld.x, playerCentreOfWorld.y, minDist, maxDist, minDistOffScreen, maxDistOffScreen,\n\t\t\t&generatedCoors, &node1, &node2, &randomPos, nil);\n\n\t\tif (!foundCoors)\n\t\t\treturn;\n\n\t\tuint8 nodeSpawnRate = Min(ThePaths.m_pathNodes[node1].spawnRate, ThePaths.m_pathNodes[node2].spawnRate);\n\t\tint randomRate = CGeneral::GetRandomNumber() & 0xF;\n\t\tif (randomRate > nodeSpawnRate)\n\t\t\treturn;\n\n\t\tCPathFind::TakeWidthIntoAccountForCoors(&ThePaths.m_pathNodes[node1], &ThePaths.m_pathNodes[node2], CGeneral::GetRandomNumber(), &generatedCoors.x, &generatedCoors.y);\n\t\tif (CGame::currArea == AREA_MALL && (pedTypeToAdd == PEDTYPE_CIVMALE || pedTypeToAdd == PEDTYPE_CIVFEMALE || pedTypeToAdd == PEDTYPE_CRIMINAL) &&\n\t\t\tCGeneral::GetRandomNumberInRange(0.f, 1.f) > 0.5f) {\n\n\t\t\tPlaceMallPedsAsStationaryGroup(generatedCoors, zoneInfo.pedGroup);\n\t\t\treturn;\n\t\t}\n\n\t\tif (pedTypeToAdd >= PEDTYPE_GANG1 && pedTypeToAdd <= PEDTYPE_GANG9 && !isSecurityGuard) {\n\t\t\tPlaceGangMembers((ePedType)pedTypeToAdd, pedAmount, generatedCoors);\n\t\t\treturn;\n\t\t}\n\n\t\tif (man > -1 && woman > -1) {\n\t\t\tPlaceCouple(PEDTYPE_CIVMALE, man, PEDTYPE_CIVFEMALE, woman, generatedCoors);\n\t\t\treturn;\n\t\t}\n\n\t\tfor (int i = 0; i < pedAmount; ++i) {\n\n\t\t\tif (pedTypeToAdd == PEDTYPE_COP) {\n\t\t\t\t// Unused code, ChoosePolicePedOccupation returns COP_STREET. Spawning FBI/SWAT/Army done in somewhere else.\n\t\t\t\tif (modelToAdd == COP_STREET) {\n\t\t\t\t\tif (!CStreaming::HasModelLoaded(MI_COP))\n\t\t\t\t\t\treturn;\n\n\t\t\t\t} else if (modelToAdd == COP_FBI) {\n\t\t\t\t\tif (!CStreaming::HasModelLoaded(MI_COP) || !CStreaming::HasModelLoaded(CWeaponInfo::GetWeaponInfo(WEAPONTYPE_MP5)->m_nModelId))\n\t\t\t\t\t\treturn;\n\n\t\t\t\t} else if (modelToAdd == COP_SWAT) {\n\t\t\t\t\tif (!CStreaming::HasModelLoaded(MI_SWAT) || !CStreaming::HasModelLoaded(CWeaponInfo::GetWeaponInfo(WEAPONTYPE_UZI)->m_nModelId))\n\t\t\t\t\t\treturn;\n\n\t\t\t\t} else if (modelToAdd == COP_ARMY) {\n\t\t\t\t\tif (!CStreaming::HasModelLoaded(MI_ARMY) ||\n\t\t\t\t\t\t!CStreaming::HasModelLoaded(CWeaponInfo::GetWeaponInfo(WEAPONTYPE_MP5)->m_nModelId) || !CStreaming::HasModelLoaded(CWeaponInfo::GetWeaponInfo(WEAPONTYPE_GRENADE)->m_nModelId))\n\t\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t} else if (!CStreaming::HasModelLoaded(modelToAdd)) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tgeneratedCoors.z += 0.7f;\n\n\t\t\t// What? How can this not be met?\n\t\t\tif (i < pedAmount) {\n\t\t\t\t// rand()\n\t\t\t\t// III leftover, unused\n\t\t\t\tif (gangLeader) {\n\t\t\t\t\t// Align gang members in formation. (btw i can't be 0 in here)\n\t\t\t\t\tfloat offsetMin = i * 0.75f;\n\t\t\t\t\tfloat offsetMax = (i + 1.0f) * 0.75f - offsetMin;\n\t\t\t\t\tfloat xOffset = CGeneral::GetRandomNumberInRange(offsetMin, offsetMin + offsetMax);\n\t\t\t\t\tfloat yOffset = CGeneral::GetRandomNumberInRange(offsetMin, offsetMin + offsetMax);\n\t\t\t\t\tif (CGeneral::GetRandomNumber() & 1)\n\t\t\t\t\t\txOffset = -xOffset;\n\t\t\t\t\tif (CGeneral::GetRandomNumber() & 1)\n\t\t\t\t\t\tyOffset = -yOffset;\n\t\t\t\t\tgeneratedCoors.x = xOffset + gangLeader->GetPosition().x;\n\t\t\t\t\tgeneratedCoors.y = yOffset + gangLeader->GetPosition().y;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!CPedPlacement::IsPositionClearForPed(generatedCoors))\n\t\t\t\tbreak;\n\n\t\t\t// Why no love for last gang member?!\n\t\t\tif (i + 1 < pedAmount) {\n\t\t\t\tbool foundGround;\n\t\t\t\tfloat groundZ = CWorld::FindGroundZFor3DCoord(generatedCoors.x, generatedCoors.y, 2.0f + generatedCoors.z, &foundGround) + 0.7f;\n\t\t\t\tif (!foundGround)\n\t\t\t\t\treturn;\n\n\t\t\t\tgeneratedCoors.z = Max(generatedCoors.z, groundZ);\n\t\t\t}\n\t\t\tbool surfaceAndDistIsOk = true;\n\t\t\tif (TheCamera.IsSphereVisible(generatedCoors, 2.0f)) {\n\t\t\t\tif (PedCreationDistMultiplier() * MIN_CREATION_DIST > (generatedCoors - playerCentreOfWorld).Magnitude2D())\n\t\t\t\t\tsurfaceAndDistIsOk = false;\n\t\t\t}\n\n\t\t\t// Place skaters if only they're on tarmac.\n\t\t\tif (((CPedModelInfo*)CModelInfo::GetModelInfo(modelToAdd))->m_pedStatType == PEDSTAT_SKATER) {\n\t\t\t\tCEntity* foundEnt = nil;\n\t\t\t\tCColPoint foundCol;\n\t\t\t\tCWorld::ProcessVerticalLine(generatedCoors + CVector(0.f, 0.f, 2.f), generatedCoors.z - 2.0f, foundCol, foundEnt, true, false, false, false, false, false, nil);\n\t\t\t\tif (foundEnt) {\n\t\t\t\t\tif (foundCol.surfaceB == SURFACE_TARMAC || foundCol.surfaceB == SURFACE_PAVEMENT)\n\t\t\t\t\t\tsurfaceAndDistIsOk = true;\n\t\t\t\t\telse\n\t\t\t\t\t\tsurfaceAndDistIsOk = false;\n\n\t\t\t\t} else {\n\t\t\t\t\tsurfaceAndDistIsOk = false;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!surfaceAndDistIsOk)\n\t\t\t\tbreak;\n\t\t\tCPed *newPed = AddPed((ePedType)pedTypeToAdd, modelToAdd, generatedCoors);\n\t\t\tif (forceAddingCop && newPed->m_nPedType == PEDTYPE_COP)\n\t\t\t\t((CCopPed*)newPed)->m_bThrowsSpikeTrap = true;\n\n\t\t\tbool gonnaSunbathe = false;\n\t\t\tif (CPopulation::IsSunbather(modelToAdd)) {\n\t\t\t\tCEntity* foundEnt = nil;\n\t\t\t\tCColPoint foundCol;\n\t\t\t\tCWorld::ProcessVerticalLine(generatedCoors + CVector(0.f, 0.f, 2.f), generatedCoors.z - 2.0f, foundCol, foundEnt, true, false, false, false, false, false, nil);\n\t\t\t\tif (foundEnt) {\n\t\t\t\t\tif ((foundCol.surfaceB == SURFACE_CONCRETE_BEACH || foundCol.surfaceB == SURFACE_SAND)\n\t\t\t\t\t\t&& CClock::GetHours() >= 10 && CClock::GetHours() <= 18 && 0.0f == CWeather::Rain) {\n\t\t\t\t\t\tgonnaSunbathe = true;\n\t\t\t\t\t\tif (CPedPlacement::IsPositionClearForPed(generatedCoors, 3.0f, ARRAY_SIZE(gSunbatheObstacles), gSunbatheObstacles)) {\n\t\t\t\t\t\t\tfor (int j = 0; j < ARRAY_SIZE(gSunbatheObstacles); j++) {\n\t\t\t\t\t\t\t\tif (gSunbatheObstacles[j] && gSunbatheObstacles[j] != newPed)\n\t\t\t\t\t\t\t\t\tgonnaSunbathe = false;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (gonnaSunbathe) {\n\t\t\t\tfloat heading = CGeneral::GetRandomNumberInRange(0.f, 1.f) * TWOPI;\n\t\t\t\tnewPed->m_fRotationDest = heading;\n\t\t\t\tnewPed->m_fRotationCur = heading;\n\t\t\t\t// unused\n\t\t\t\t// v61 = CGeneral::GetRandomTrueFalse();\n\t\t\t\tnewPed->SetWaitState(WAITSTATE_SUN_BATHE_IDLE, nil);\n\t\t\t\tCVector toyPos(newPed->GetPosition());\n\t\t\t\tfloat waterLevel;\n\t\t\t\tif (CWaterLevel::GetGroundLevel(toyPos, &waterLevel, nil, 30.0f)) {\n\t\t\t\t\ttoyPos.z = 0.04f + waterLevel;\n\t\t\t\t\tCEntity *toy = CWaterLevel::CreateBeachToy(toyPos, BEACHTOY_ANY_TOWEL);\n\t\t\t\t\tif (toy)\n\t\t\t\t\t\ttoy->SetHeading(heading);\n\n\t\t\t\t\tif (!(CGeneral::GetRandomNumber() & 3)) {\n\t\t\t\t\t\tCWaterLevel::CreateBeachToy(toyPos + CVector(CGeneral::GetRandomNumberInRange(-2.f, 2.f), CGeneral::GetRandomNumberInRange(-2.f, 2.f), 0.f), BEACHTOY_LOTION);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tnewPed->SetWanderPath(CGeneral::GetRandomNumberInRange(0, 8));\n\t\t\t}\n\t\t\t\n\t\t\tif (i != 0) {\n\t\t\t\t// Gang member\n\t\t\t\tnewPed->SetLeader(gangLeader);\n\n\t\t\t\tnewPed->SetPedState(PED_UNKNOWN);\n\t\t\t\tgangLeader->SetPedState(PED_UNKNOWN);\n\n\t\t\t} else {\n\t\t\t\tgangLeader = newPed;\n\t\t\t}\n\t\t\tCVisibilityPlugins::SetClumpAlpha(newPed->GetClump(), 0);\n\t\t\t/*\n\t\t\t// Pointless, this is already a for loop\n\t\t\tif (i + 1 > pedAmount)\n\t\t\t\tbreak;\n\t\t\tif (pedAmount <= 1)\n\t\t\t\tbreak; */\n\t\t}\n\t}\n}\n\nCPed*\nCPopulation::AddPedInCar(CVehicle* car, bool isDriver)\n{\n\tconst int defaultModel = MI_MALE01;\n\tint miamiViceIndex = 0;\n\tbool imSureThatModelIsLoaded = true;\n\tCVector coors = FindPlayerCoors();\n\tCZoneInfo zoneInfo;\n\tint pedType;\n\n\t// May be eCopType, model index or non-sense(for medic), AddPed knows that by looking to ped type.\n\tint preferredModel;\n\n\tCTheZones::GetZoneInfoForTimeOfDay(&coors, &zoneInfo);\n\tswitch (car->GetModelIndex()) {\n\t\tcase MI_FIRETRUCK:\n\t\t\tpreferredModel = 0;\n\t\t\tpedType = PEDTYPE_FIREMAN;\n\t\t\tbreak;\n\t\tcase MI_AMBULAN:\n\t\t\tpreferredModel = 0;\n\t\t\tpedType = PEDTYPE_EMERGENCY;\n\t\t\tbreak;\n\t\tcase MI_POLICE:\n\t\tcase MI_PREDATOR:\n\t\t\tpreferredModel = COP_STREET;\n\t\t\tpedType = PEDTYPE_COP;\n\t\t\tbreak;\n\t\tcase MI_ENFORCER:\n\t\t\tpreferredModel = COP_SWAT;\n\t\t\tpedType = PEDTYPE_COP;\n\t\t\tbreak;\n\t\tcase MI_RHINO:\n\t\tcase MI_BARRACKS:\n\t\t\tpreferredModel = COP_ARMY;\n\t\t\tpedType = PEDTYPE_COP;\n\t\t\tbreak;\n\t\tcase MI_FBIRANCH:\n\t\t\tpreferredModel = COP_FBI;\n\t\t\tpedType = PEDTYPE_COP;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tif (car->IsTaxi()) {\n\t\t\t\tif (isDriver) {\n\t\t\t\t\tpedType = PEDTYPE_CIVMALE;\n\t\t\t\t\tpreferredModel = MI_TAXI_D;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t// fall through if not\n\t\t\t} else if (car->GetModelIndex() == MI_VICECHEE) {\n\t\t\t\tif (car->bIsLawEnforcer) {\n\t\t\t\t\tpreferredModel = COP_MIAMIVICE;\n\t\t\t\t\tpedType = PEDTYPE_COP;\n\t\t\t\t\tmiamiViceIndex = (isDriver ? 2 * CCarCtrl::MiamiViceCycle : 2 * CCarCtrl::MiamiViceCycle + 1);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t// fall through if not\n\t\t\t}\n\n\t\t\tint gangOfPed = 0;\n\t\t\timSureThatModelIsLoaded = false;\n\n\t\t\twhile (gangOfPed < NUM_GANGS && CGangs::GetGangInfo(gangOfPed)->m_nVehicleMI != car->GetModelIndex())\n\t\t\t\tgangOfPed++;\n\n\t\t\tif (gangOfPed < NUM_GANGS) {\n\t\t\t\tpedType = gangOfPed + PEDTYPE_GANG1;\n\t\t\t\tpreferredModel = ChooseGangOccupation(gangOfPed);\n\t\t\t} else if (gangOfPed == NUM_GANGS) {\n\t\t\t    CVehicleModelInfo *carModel = ((CVehicleModelInfo *)CModelInfo::GetModelInfo(car->GetModelIndex()));\n\t\t\t\tpreferredModel = ChooseCivilianOccupation(zoneInfo.pedGroup);\n\t\t\t\tint i = 15;\n\t\t\t\tfor(; i >= 0; i--) {\n\t\t\t\t\tCPedModelInfo* pedModel = (CPedModelInfo*)CModelInfo::GetModelInfo(preferredModel);\n\n\t\t\t\t\tif (pedModel->GetRwObject()) {\n\t\t\t\t\t\tif (!car->IsPassenger(preferredModel) && !car->IsDriver(preferredModel)) {\n\t\t\t\t\t\t\tif (((CPedModelInfo*)CModelInfo::GetModelInfo(preferredModel))->m_carsCanDrive & (1 << carModel->m_vehicleClass))\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tpreferredModel = ChooseNextCivilianOccupation(zoneInfo.pedGroup);\n\t\t\t\t}\n\t\t\t\tif (i == -1)\n\t\t\t\t\tpreferredModel = defaultModel;\n\n\t\t\t\tpedType = ((CPedModelInfo*)CModelInfo::GetModelInfo(preferredModel))->m_pedType;\n\t\t\t}\n\t\t\tbreak;\n\t}\n\tif (!imSureThatModelIsLoaded && !((CPedModelInfo*)CModelInfo::GetModelInfo(preferredModel))->GetRwObject()) {\n\t\tpreferredModel = defaultModel;\n\t\tpedType = ((CPedModelInfo*)CModelInfo::GetModelInfo(defaultModel))->m_pedType;\n\t}\n\n\tCPed *newPed = CPopulation::AddPed((ePedType)pedType, preferredModel, car->GetPosition(), miamiViceIndex);\n\tnewPed->bUsesCollision = false;\n\n\tif (newPed->GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED) {\n\t\tnewPed->RemoveWeaponModel(CWeaponInfo::GetWeaponInfo(newPed->GetWeapon()->m_eWeaponType)->m_nModelId);\n\t}\n\n\tnewPed->AddInCarAnims(car, isDriver);\n\treturn newPed;\n}\n\nvoid\nCPopulation::MoveCarsAndPedsOutOfAbandonedZones()\n{\n}\n\nvoid\nCPopulation::ConvertAllObjectsToDummyObjects()\n{\n\tint poolSize = CPools::GetObjectPool()->GetSize();\n\tfor (int poolIndex = poolSize - 1; poolIndex >= 0; poolIndex--) {\n\n\t\tCObject *obj = CPools::GetObjectPool()->GetSlot(poolIndex);\n\t\tif (obj) {\n\t\t\tif (obj->CanBeDeleted())\n\t\t\t\tConvertToDummyObject(obj);\n\t\t}\n\t}\n}\n\nvoid\nCPopulation::ConvertToRealObject(CDummyObject *dummy)\n{\n\tif (!TestSafeForRealObject(dummy))\n\t\treturn;\n\n\tCObject *obj = new CObject(dummy);\n\tif (!obj)\n\t\treturn;\n\n\tCWorld::Remove(dummy);\n\tdelete dummy;\n\tCWorld::Add(obj);\n\n\tCSimpleModelInfo *mi = (CSimpleModelInfo*)CModelInfo::GetModelInfo(obj->GetModelIndex());\n\tif (IsGlass(obj->GetModelIndex()) && !mi->m_isArtistGlass) {\n\t\tobj->bIsVisible = false;\n\t} else if (obj->GetModelIndex() == MI_BUOY) {\n\t\tobj->SetIsStatic(false);\n\t\tobj->m_vecMoveSpeed = CVector(0.0f, 0.0f, -0.001f);\n\t\tobj->bTouchingWater = true;\n\t\tobj->AddToMovingList();\n\t}\n}\n\nvoid\nCPopulation::ConvertToDummyObject(CObject *obj)\n{\n\tCDummyObject *dummy = new CDummyObject(obj);\n\n\tdummy->GetMatrix() = obj->m_objectMatrix;\n\tdummy->GetMatrix().UpdateRW();\n\tdummy->UpdateRwFrame();\n\n\tCSimpleModelInfo *mi = (CSimpleModelInfo*)CModelInfo::GetModelInfo(obj->GetModelIndex());\n\tif (IsGlass(obj->GetModelIndex()) && !mi->m_isArtistGlass)\n\t\tdummy->bIsVisible = false;\n\n\tCWorld::Remove(obj);\n\tdelete obj;\n\tCWorld::Add(dummy);\n}\n\nbool\nCPopulation::TestRoomForDummyObject(CObject *obj)\n{\n\tint16 collidingObjs;\n\tCWorld::FindObjectsKindaColliding(obj->m_objectMatrix.GetPosition(), obj->GetBoundRadius(),\n\t\tfalse, &collidingObjs, 2, nil, false, true, true, false, false);\n\n\treturn collidingObjs == 0;\n}\n\nbool\nCPopulation::TestSafeForRealObject(CDummyObject *dummy)\n{\n\tCPtrNode *ptrNode;\n\tCColModel *dummyCol = dummy->GetColModel();\n\tfloat colRadius = dummy->GetBoundRadius();\n\tCVector colCentre = dummy->GetBoundCentre();\n\n\tint minX = CWorld::GetSectorIndexX(dummy->GetPosition().x - colRadius);\n\tif (minX < 0) minX = 0;\n\tint minY = CWorld::GetSectorIndexY(dummy->GetPosition().y - colRadius);\n\tif (minY < 0) minY = 0;\n\tint maxX = CWorld::GetSectorIndexX(dummy->GetPosition().x + colRadius);\n#ifdef FIX_BUGS\n\tif (maxX >= NUMSECTORS_X) maxX = NUMSECTORS_X - 1;\n#else\n\tif (maxX >= NUMSECTORS_X) maxX = NUMSECTORS_X;\n#endif\n\n\tint maxY = CWorld::GetSectorIndexY(dummy->GetPosition().y + colRadius);\n#ifdef FIX_BUGS\n\tif (maxY >= NUMSECTORS_Y) maxY = NUMSECTORS_Y - 1;\n#else\n\tif (maxY >= NUMSECTORS_Y) maxY = NUMSECTORS_Y;\n#endif\n\n\tstatic CColPoint aTempColPoints[MAX_COLLISION_POINTS];\n\n\tfor (int curY = minY; curY <= maxY; curY++) {\n\t\tfor (int curX = minX; curX <= maxX; curX++) {\n\t\t\tCSector *sector = CWorld::GetSector(curX, curY);\n\n\t\t\tfor (ptrNode = sector->m_lists[ENTITYLIST_VEHICLES].first; ptrNode; ptrNode = ptrNode->next) {\n\t\t\t\tCVehicle *veh = (CVehicle*)ptrNode->item;\n\t\t\t\tif (veh->m_scanCode != CWorld::GetCurrentScanCode()) {\n\t\t\t\t\tif (veh->GetIsTouching(colCentre, colRadius)) {\n\t\t\t\t\t\tveh->m_scanCode = CWorld::GetCurrentScanCode();\n\t\t\t\t\t\tif (CCollision::ProcessColModels(dummy->GetMatrix(), *dummyCol, veh->GetMatrix(), *veh->GetColModel(), aTempColPoints, nil, nil) > 0)\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (ptrNode = sector->m_lists[ENTITYLIST_VEHICLES_OVERLAP].first; ptrNode; ptrNode = ptrNode->next) {\n\t\t\t\tCVehicle *veh = (CVehicle*)ptrNode->item;\n\t\t\t\tif (veh->m_scanCode != CWorld::GetCurrentScanCode()) {\n\t\t\t\t\tif (veh->GetIsTouching(colCentre, colRadius)) {\n\t\t\t\t\t\tveh->m_scanCode = CWorld::GetCurrentScanCode();\n\t\t\t\t\t\tif (CCollision::ProcessColModels(dummy->GetMatrix(), *dummyCol, veh->GetMatrix(), *veh->GetColModel(), aTempColPoints, nil, nil) > 0)\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn true;\n}\n\nvoid\nCPopulation::ManagePopulation(void)\n{\n\tint frameMod32 = CTimer::GetFrameCounter() & 31;\n\tCVector playerPos = FindPlayerCentreOfWorld(CWorld::PlayerInFocus);\n\n\t// Why this code is here?! Delete temporary objects when they got too far, and convert others to \"dummy\" objects. (like lamp posts)\n\tint objectPoolSize = CPools::GetObjectPool()->GetSize();\n\tfor (int i = objectPoolSize * frameMod32 / 32; i < objectPoolSize * (frameMod32 + 1) / 32; i++) {\n\t\tCObject *obj = CPools::GetObjectPool()->GetSlot(i);\n\t\tif (obj && obj->CanBeDeleted()) {\n\t\t\tfloat objPlayerDist = (obj->GetPosition() - playerPos).Magnitude();\n\t\t\tif (obj->ObjectCreatedBy == TEMP_OBJECT) {\n\t\t\t\tif (obj->GetModelIndex() != MI_ROADWORKBARRIER1 && obj->GetModelIndex() != MI_BEACHBALL) {\n\t\t\t\t\tif (objPlayerDist > 51.0f || objPlayerDist > 25.0f && !obj->GetIsOnScreen() || CTimer::GetTimeInMilliseconds() > obj->m_nEndOfLifeTime) {\n\t\t\t\t\t\tCWorld::Remove(obj);\n\t\t\t\t\t\tdelete obj;\n\t\t\t\t\t}\n\t\t\t\t} else if (objPlayerDist > 120.0f) {\n\t\t\t\t\tCWorld::Remove(obj);\n\t\t\t\t\tdelete obj;\n\t\t\t\t}\n\n\t\t\t} else if (objPlayerDist > 80.0f && (obj->m_objectMatrix.GetPosition() - playerPos).Magnitude() > 80.0f) {\n\t\t\t\tif (obj->ObjectCreatedBy != CUTSCENE_OBJECT && TestRoomForDummyObject(obj)) {\n\t\t\t\t\tConvertToDummyObject(obj);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Convert them back to real objects. Dummy objects don't have collisions, so they need to be converted.\n\tint dummyPoolSize = CPools::GetDummyPool()->GetSize();\n\tfor (int i = dummyPoolSize * frameMod32 / 32; i < dummyPoolSize * (frameMod32 + 1) / 32; i++) {\n\t\tCDummy *dummy = CPools::GetDummyPool()->GetSlot(i);\n\t\tif (dummy && (dummy->m_area == CGame::currArea || dummy->m_area == AREA_EVERYWHERE)) {\n\t\t\tif ((dummy->GetPosition() - playerPos).Magnitude() < 80.0f)\n\t\t\t\tConvertToRealObject((CDummyObject*)dummy);\n\t\t}\n\t}\n\n\tint pedPoolSize = CPools::GetPedPool()->GetSize();\n#ifndef SQUEEZE_PERFORMANCE\n\tfor (int poolIndex = pedPoolSize-1; poolIndex >= 0; poolIndex--) {\n#else\n\tfor (int poolIndex = (pedPoolSize * (frameMod32 + 1) / 32) - 1; poolIndex >= pedPoolSize * frameMod32 / 32; poolIndex--) {\n#endif\n\t\tCPed *ped = CPools::GetPedPool()->GetSlot(poolIndex);\n\n\t\tif (ped && !ped->IsPlayer() && ped->CanBeDeleted() && !ped->bInVehicle) {\n\t\t\tuint32 timeSinceDeath = CTimer::GetTimeInMilliseconds() - ped->m_bloodyFootprintCountOrDeathTime;\n\t\t\tif (ped->m_nPedState == PED_DEAD && (timeSinceDeath > 30000 || CDarkel::FrenzyOnGoing() && timeSinceDeath > 15000))\n\t\t\t\tped->bFadeOut = true;\n\n\t\t\tif (ped->bFadeOut && CVisibilityPlugins::GetClumpAlpha(ped->GetClump()) == 0) {\n\t\t\t\tRemovePed(ped);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tfloat dist = (ped->GetPosition() - playerPos).Magnitude2D();\n\t\t\tbool pedIsFarAway = false;\n\n\t\t\tif (ped->IsGangMember())\n\t\t\t\tdist -= 30.0f;\n\t\t\telse if (ped->bDeadPedInFrontOfCar && ped->m_vehicleInAccident)\n\t\t\t\tdist = 0.0f;\n\n\t\t\tif (PedCreationDistMultiplier() * (PED_REMOVE_DIST_SPECIAL * TheCamera.GenerationDistMultiplier) < dist ||\n\t\t\t\t(!ped->bCullExtraFarAway && PedCreationDistMultiplier() * PED_REMOVE_DIST * TheCamera.GenerationDistMultiplier < dist)) {\n\t\t\t\tpedIsFarAway = true;\n\n\t\t\t} else if (PedCreationDistMultiplier() * (MIN_CREATION_DIST + CREATION_RANGE) * OFFSCREEN_CREATION_MULT < dist) {\n\t\t\t\tif (CTimer::GetTimeInMilliseconds() > ped->m_nExtendedRangeTimer && !ped->GetIsOnScreen()) {\n\t\t\t\t\tif (TheCamera.Cams[TheCamera.ActiveCam].Mode != CCam::MODE_SNIPER\n\t\t\t\t\t\t&& TheCamera.Cams[TheCamera.ActiveCam].Mode != CCam::MODE_SNIPER_RUNABOUT\n\t\t\t\t\t\t&& TheCamera.Cams[TheCamera.ActiveCam].Mode != CCam::MODE_CAMERA\n\t\t\t\t\t\t&& !TheCamera.Cams[TheCamera.ActiveCam].LookingLeft\n\t\t\t\t\t\t&& !TheCamera.Cams[TheCamera.ActiveCam].LookingRight\n\t\t\t\t\t\t&& !TheCamera.Cams[TheCamera.ActiveCam].LookingBehind) {\n\t\t\t\t\t\tpedIsFarAway = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t} else {\n\t\t\t\tped->m_nExtendedRangeTimer = ped->m_nPedType == PEDTYPE_COP ? CTimer::GetTimeInMilliseconds() + 10000 : CTimer::GetTimeInMilliseconds() + 4000;\n\t\t\t}\n\n\t\t\tif (!pedIsFarAway)\n\t\t\t\tcontinue;\n\n\t\t\tif (ped->m_nPedState == PED_DEAD && !ped->bFadeOut) {\n\t\t\t\tCVector pedPos = ped->GetPosition();\n\n\t\t\t\tfloat randAngle = (uint8) CGeneral::GetRandomNumber() * (3.14f / 128.0f); // Not PI, 3.14\n\t\t\t\tswitch (CGeneral::GetRandomNumber() % 3) {\n\t\t\t\t\tcase 0:\n\t\t\t\t\t\tCShadows::AddPermanentShadow(SHADOWTYPE_DARK, gpOutline1Tex, &pedPos,\n\t\t\t\t\t\t\t0.9f * Cos(randAngle), 0.9f * Sin(randAngle), 0.9f * Sin(randAngle), -0.9f * Cos(randAngle),\n\t\t\t\t\t\t\t255, 255, 255, 255, 4.0f, 40000, 1.0f);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 1:\n\t\t\t\t\t\tCShadows::AddPermanentShadow(SHADOWTYPE_DARK, gpOutline2Tex, &pedPos,\n\t\t\t\t\t\t\t0.9f * Cos(randAngle), 0.9f * Sin(randAngle), 0.9f * Sin(randAngle), -0.9f * Cos(randAngle),\n\t\t\t\t\t\t\t255, 255, 255, 255, 4.0f, 40000, 1.0f);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 2:\n\t\t\t\t\t\tCShadows::AddPermanentShadow(SHADOWTYPE_DARK, gpOutline3Tex, &pedPos,\n\t\t\t\t\t\t\t0.9f * Cos(randAngle), 0.9f * Sin(randAngle), 0.9f * Sin(randAngle), -0.9f * Cos(randAngle),\n\t\t\t\t\t\t\t255, 255, 255, 255, 4.0f, 40000, 1.0f);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (ped->GetIsOnScreen())\n\t\t\t\tped->bFadeOut = true;\n\t\t\telse\n\t\t\t\tRemovePed(ped);\n\t\t}\n\t}\n}\n\nCPed* \nCPopulation::AddDeadPedInFrontOfCar(const CVector& pos, CVehicle* pCulprit)\n{\n\tif (TheCamera.IsSphereVisible(pos, 2.0f) && MIN_CREATION_DIST * PedCreationDistMultiplier() > (pos - FindPlayerPed()->GetPosition()).Magnitude2D()) {\n\t\t\treturn nil;\n\t}\n\n\tbool found;\n\tfloat z = CWorld::FindGroundZFor3DCoord(pos.x, pos.y, pos.z, &found) + 1.0f;\n\tif (!found)\n\t\treturn nil;\n\tz = Max(z, pos.z);\n\tif (!CModelInfo::GetModelInfo(MI_MALE01)->GetRwObject())\n\t\treturn nil;\n\tCPed* pPed = CPopulation::AddPed(PEDTYPE_CIVMALE, MI_MALE01, pos);\n\tpPed->SetDie();\n\tpPed->m_nPedMoney = 0;\n\tpPed->bDeadPedInFrontOfCar = true;\n\tpPed->m_vehicleInAccident = pCulprit;\n\tpCulprit->RegisterReference((CEntity**)&pPed->m_vehicleInAccident);\n\tCEntity* pEntities[3] = { 0 };\n\tif (!CPedPlacement::IsPositionClearForPed(pos, 2.0f, 3, pEntities)) {\n\t\tfor (int i = 0; i < 3; i++) {\n\t\t\tif (pEntities[i] && pEntities[i] != pCulprit && pEntities[i] != pPed) {\n\t\t\t\tRemovePed(pPed);\n\t\t\t\treturn nil;\n\t\t\t}\n\t\t}\n\t}\n\tCColPoint colpts[MAX_COLLISION_POINTS];\n\tif (CCollision::ProcessColModels(pCulprit->GetMatrix(), *pCulprit->GetColModel(), pPed->GetMatrix(), *pPed->GetColModel(), colpts, nil, nil)) {\n\t\tRemovePed(pPed);\n\t\treturn nil;\n\t}\n\tCVisibilityPlugins::SetClumpAlpha(pPed->GetClump(), 0);\n\treturn pPed;\n}\n\nbool\nCPopulation::IsSkateable(CVector const& pos)\n{\n\tCColPoint foundCol;\n\tCEntity* foundEnt = nil;\n\tCWorld::ProcessVerticalLine(pos + CVector(0.f, 0.f, 2.f), pos.z - 2.0f, foundCol, foundEnt, true, false, false, false, false, false, nil);\n\tif (!foundEnt)\n\t\treturn false;\n\n\treturn foundCol.surfaceB == SURFACE_TARMAC || foundCol.surfaceB == SURFACE_PAVEMENT;\n}\n\nbool\nCPopulation::CanJeerAtStripper(int32 model)\n{\n\treturn model == MI_WMOBE || model == MI_WMYBE || model == MI_WMOST || model == MI_BMYBB;\n}\n\nvoid\nCPopulation::RemovePedsIfThePoolGetsFull(void)\n{\n\tif ((CTimer::GetFrameCounter() & 7) == 5) {\n\t\tif (CPools::GetPedPool()->GetNoOfFreeSpaces() < 8) {\n\t\t\tCPed *closestPed = nil;\n\t\t\tfloat closestDist = 10000000.0;\n\t\t\tint poolSize = CPools::GetPedPool()->GetSize();\n\t\t\tfor (int i = poolSize - 1; i >= 0; i--) {\n\t\t\t\tCPed* ped = CPools::GetPedPool()->GetSlot(i);\n\t\t\t\tif (ped && ped->CanBeDeleted()) {\n\t\t\t\t\tfloat dist = (TheCamera.GetPosition() - ped->GetPosition()).Magnitude();\n\t\t\t\t\tif (dist < closestDist) {\n\t\t\t\t\t\tclosestDist = dist;\n\t\t\t\t\t\tclosestPed = ped;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (closestPed) {\n\t\t\t\tRemovePed(closestPed);\n\t\t\t}\n\t\t}\n\t}\n}\n\nbool\nCPopulation::IsMale(int32 model)\n{\n\tswitch (model) {\n\t\tcase MI_HMYST:\n\t\tcase MI_HMOST:\n\t\tcase MI_HMYRI:\n\t\tcase MI_HMORI:\n\t\tcase MI_HMYBE:\n\t\tcase MI_HMOBE:\n\t\tcase MI_HMOTR:\n\t\tcase MI_HMYAP:\n\t\tcase MI_HMOCA:\n\t\tcase MI_BMODK:\n\t\tcase MI_BMYKR:\n\t\tcase MI_BMYST:\n\t\tcase MI_BMOST:\n\t\tcase MI_BMYRI:\n\t\tcase MI_BMYBE:\n\t\tcase MI_BMOBE:\n\t\tcase MI_BMYBU:\n\t\tcase MI_BMOTR:\n\t\tcase MI_BMYPI:\n\t\tcase MI_BMYBB:\n\t\tcase MI_WMYCR:\n\t\tcase MI_WMYST:\n\t\tcase MI_WMOST:\n\t\tcase MI_WMYRI:\n\t\tcase MI_WMORI:\n\t\tcase MI_WMYBE:\n\t\tcase MI_WMOBE:\n\t\tcase MI_WMYCW:\n\t\tcase MI_WMYGO:\n\t\tcase MI_WMOGO:\n\t\tcase MI_WMYLG:\n\t\tcase MI_WMYBU:\n\t\tcase MI_WMOBU:\n\t\tcase MI_WMOTR:\n\t\tcase MI_WMYPI:\n\t\tcase MI_WMOCA:\n\t\tcase MI_WMYJG:\n\t\tcase MI_WMYSK:\n\n\t\t// BUG? Why no JMOTO?\n\t\t\treturn true;\n\t\tdefault:\n\t\t\treturn false;\n\t}\n}\n\nbool\nCPopulation::IsFemale(int32 model)\n{\n\tswitch (model) {\n\t\tcase MI_HFYST:\n\t\tcase MI_HFOST:\n\t\tcase MI_HFYRI:\n\t\tcase MI_HFORI:\n\t\tcase MI_HFYBE:\n\t\tcase MI_HFOBE:\n\t\tcase MI_HFYBU:\n\t\tcase MI_HFYMD:\n\t\tcase MI_HFYCG:\n\t\tcase MI_HFYPR:\n\t\tcase MI_HFOTR:\n\t\tcase MI_BFYST:\n\t\tcase MI_BFOST:\n\t\tcase MI_BFYRI:\n\t\tcase MI_BFORI:\n\t\tcase MI_BFYBE:\n\t\tcase MI_BFOBE:\n\t\tcase MI_BFYPR:\n\t\tcase MI_BFOTR:\n\t\tcase MI_WFYST:\n\t\tcase MI_WFOST:\n\t\tcase MI_WFYRI:\n\t\tcase MI_WFORI:\n\t\tcase MI_WFYBE:\n\t\tcase MI_WFOBE:\n\t\tcase MI_WFOGO:\n\t\tcase MI_WFYLG:\n\t\tcase MI_WFYBU:\n\t\tcase MI_WFYPR:\n\t\tcase MI_WFOTR:\n\t\tcase MI_WFYJG:\n\t\tcase MI_WFYSK:\n\t\tcase MI_WFYSH:\n\t\tcase MI_WFOSH:\n\t\tcase MI_JFOTO:\n\t\t\treturn true;\n\t\tdefault:\n\t\t\treturn false;\n\t}\n}\n\nbool\nCPopulation::IsSunbather(int32 model)\n{\n\tswitch (model) {\n\t\tcase MI_HFYBE:\n\t\tcase MI_HFOBE:\n\t\tcase MI_HMYBE:\n\t\tcase MI_HMOBE:\n\t\tcase MI_BFYBE:\n\t\tcase MI_BMYBE:\n\t\tcase MI_BFOBE:\n\t\tcase MI_BMOBE:\n\t\tcase MI_WFYBE:\n\t\tcase MI_WMYBE:\n\t\tcase MI_WFOBE:\n\t\tcase MI_WMOBE:\n\t\t\treturn true;\n\t\tdefault:\n\t\t\treturn false;\n\t}\n}\n\nint32\nCPopulation::ComputeRandomisedGangSize(void)\n{\n\treturn CGeneral::GetRandomNumberInRange(3, 6);\n}\n\nbool\nCPopulation::CanSolicitPlayerInCar(int32 model)\n{\n\treturn model == MI_HFYPR || model == MI_BFYPR || model == MI_WFYPR;\n}\n\nbool\nCPopulation::CanSolicitPlayerOnFoot(int32 model)\n{\n\treturn model == MI_HFYMD || model == MI_HFYCG || model == MI_BFOTR || model == MI_BMOTR || model == MI_WFOTR || model == MI_WMOTR;\n}\n\nbool\nCPopulation::IsSecurityGuard(ePedType pedType)\n{\n\treturn pedType == PEDTYPE_GANG5;\n}\n\nvoid\nCPopulation::ChooseCivilianCoupleOccupations(int32 group, int32& man, int32& woman)\n{\n\tman = -1;\n\twoman = -1;\n\t\n\tfor (int i = 0; i < 8; i++) {\n\t\tif (man > -1)\n\t\t\tbreak;\n\n\t\tint32 model = ms_pPedGroups[group].models[CGeneral::GetRandomNumberInRange(0, NUMMODELSPERPEDGROUP)];\n\t\tif (man == -1 && IsMale(model) && ((CPedModelInfo*)CModelInfo::GetModelInfo(model))->m_pedType == PEDTYPE_CIVMALE) {\n\t\t\tman = model;\n\t\t}\n\t}\n\n\tif (man != -1) {\n\t\tint32 model;\n\t\tfor (int i = 0; i < NUMMODELSPERPEDGROUP; i++) {\n\t\t\tmodel = ms_pPedGroups[group].models[i];\n\t\t\tif (IsFemale(model)) {\n\t\t\t\tCPedModelInfo* womanModelInfo = (CPedModelInfo*)CModelInfo::GetModelInfo(model);\n\t\t\t\tif (womanModelInfo->m_pedType == PEDTYPE_CIVFEMALE) {\n\t\t\t\t\tCPedModelInfo* manModelInfo = (CPedModelInfo*)CModelInfo::GetModelInfo(man);\n\n\t\t\t\t\t// If both are skater or not, finalize the decision\n\t\t\t\t\tif (manModelInfo && womanModelInfo) {\n\t\t\t\t\t\tif (manModelInfo->m_animGroup == womanModelInfo->m_animGroup) {\n\t\t\t\t\t\t\tif (manModelInfo->m_pedStatType != PEDSTAT_SKATER && womanModelInfo->m_pedStatType != PEDSTAT_SKATER)\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tif (manModelInfo->m_pedStatType == PEDSTAT_SKATER && womanModelInfo->m_pedStatType == PEDSTAT_SKATER)\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\twoman = model;\n\t}\n}\n\nvoid\nCPopulation::PlaceGangMembers(ePedType pedType, int pedAmount, CVector const& coors)\n{\n\tif (CGeneral::GetRandomNumberInRange(0.f, 1.f) < 0.333f) {\n\t\tPlaceGangMembersInFormation(pedType, pedAmount, coors);\n\t} else {\n\t\tPlaceGangMembersInCircle(pedType, pedAmount, coors);\n\t}\n}\n\nvoid\nCPopulation::PlaceGangMembersInFormation(ePedType pedType, int pedAmount, CVector const& coors)\n{\n\tCPed *createdPeds[5];\n\n\tif (!TheCamera.IsSphereVisible(coors, 3.0f) || MIN_CREATION_DIST * PedCreationDistMultiplier() <= (coors - FindPlayerPed()->GetPosition()).Magnitude2D()) {\n\t\tif (CPedPlacement::IsPositionClearForPed(coors, 3.0f, -1, 0)) {\n\t\t\tbool leaderFoundGround;\n\t\t\tfloat leaderGroundZ = CWorld::FindGroundZFor3DCoord(coors.x, coors.y, coors.z, &leaderFoundGround) + 1.0f;\n\t\t\tif (leaderFoundGround) {\n\t\t\t\tfloat finalZ = coors.z > leaderGroundZ ? coors.z : leaderGroundZ;\n\t\t\t\tint leaderModel = ChooseGangOccupation(pedType - PEDTYPE_GANG1);\n\t\t\t\tif (((CPedModelInfo*)CModelInfo::GetModelInfo(leaderModel))->GetRwObject()) {\n\t\t\t\t\tCPed *leader = AddPed(pedType, leaderModel, CVector(coors.x, coors.y, finalZ));\n\t\t\t\t\tif (leader) {\n\t\t\t\t\t\tleader->SetObjective(OBJECTIVE_NONE);\n\t\t\t\t\t\tleader->SetWanderPath(CGeneral::GetRandomNumberInRange(0, 8));\n\t\t\t\t\t\tleader->bIsLeader = true;\n\t\t\t\t\t\tif (CGangs::GetWillAttackPlayerWithCops(pedType))\n\t\t\t\t\t\t\tleader->bCanAttackPlayerWithCops = true;\n\n\t\t\t\t\t\tint pedIdx = 1;\n\t\t\t\t\t\tcreatedPeds[0] = leader;\n\t\t\t\t\t\tfor (int i = 1; i < pedAmount; ++i) {\n\t\t\t\t\t\t\tint memberModel = ChooseGangOccupation(pedType - PEDTYPE_GANG1);\n\t\t\t\t\t\t\tif (!((CPedModelInfo*)CModelInfo::GetModelInfo(memberModel))->GetRwObject())\n\t\t\t\t\t\t\t\tcontinue;\n\n\t\t\t\t\t\t\tCPed* memberPed = AddPed(pedType, memberModel, CVector(coors.x, coors.y, finalZ));\n\t\t\t\t\t\t\tif (!memberPed)\n\t\t\t\t\t\t\t\tcontinue;\n\n\t\t\t\t\t\t\tmemberPed->SetObjective(OBJECTIVE_FOLLOW_CHAR_IN_FORMATION, leader);\n\t\t\t\t\t\t\tmemberPed->SetFormation((eFormation)i);\n\t\t\t\t\t\t\tCVector formationPos = memberPed->GetFormationPosition();\n\t\t\t\t\t\t\tCVector finalFormationPos = formationPos;\n\t\t\t\t\t\t\tbool formationFoundGround;\n\t\t\t\t\t\t\tfloat formationGroundZ = CWorld::FindGroundZFor3DCoord(formationPos.x, formationPos.y, 1.0f + formationPos.z, &formationFoundGround) + 1.0f;\n\n\t\t\t\t\t\t\tfinalFormationPos.z = Max(finalFormationPos.z, formationGroundZ);\n\t\t\t\t\t\t\tif (formationFoundGround) {\n\t\t\t\t\t\t\t\tif (Abs(finalFormationPos.z - leader->GetPosition().z) <= 1.0f) {\n\t\t\t\t\t\t\t\t\tif (CWorld::GetIsLineOfSightClear(finalFormationPos, leader->GetPosition(), true, false, false, false, false, false, false)) {\n\t\t\t\t\t\t\t\t\t\tmemberPed->SetPosition(finalFormationPos);\n\t\t\t\t\t\t\t\t\t\tcreatedPeds[pedIdx++] = memberPed;\n\t\t\t\t\t\t\t\t\t\tif (CGangs::GetWillAttackPlayerWithCops(pedType))\n\t\t\t\t\t\t\t\t\t\t\tleader->bCanAttackPlayerWithCops = true;\n\n\t\t\t\t\t\t\t\t\t\tCVisibilityPlugins::SetClumpAlpha(memberPed->GetClump(), 0);\n\t\t\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tRemovePed(memberPed);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (pedIdx >= 3) {\n\t\t\t\t\t\t\tfor (int j = 1; j < pedIdx; ++j)\n\t\t\t\t\t\t\t\tcreatedPeds[j]->SetLeader(createdPeds[0]);\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tfor (int k = 0; k < pedIdx; ++k) {\n\t\t\t\t\t\t\t\tRemovePed(createdPeds[k]);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nCPopulation::PlaceGangMembersInCircle(ePedType pedType, int pedAmount, CVector const& coors)\n{\n\tCPed *createdPeds[5];\n\n\tif (pedAmount < 2)\n\t\treturn;\n\n\tfloat circleSector = TWOPI / pedAmount;\n\n\tfloat circleR = Sqrt(0.5f / (1.0f - Cos(circleSector)));\n\n\tif (!TheCamera.IsSphereVisible(coors, circleR) ||\n\t\tMIN_CREATION_DIST * PedCreationDistMultiplier() <= (coors - FindPlayerPed()->GetPosition()).Magnitude2D()) {\n\n\t\tif (CPedPlacement::IsPositionClearForPed(coors, circleR, -1, 0)) {\n\t\t\tint pedIdx = 0;\n\t\t\tCVector leaderPos;\n\n\t\t\tfor (int i = 0; i < pedAmount; i++) {\t\n\t\t\t\tfloat angleMult = i + CGeneral::GetRandomNumberInRange(-0.2f, 0.2f);\n\t\t\t\tfloat randomR = circleR + CGeneral::GetRandomNumberInRange(-0.2f, 0.2f) * circleR;\n\t\t\t\tfloat xOffset = randomR * Cos(angleMult * circleSector);\n\t\t\t\tfloat yOffset = randomR * Sin(angleMult * circleSector);\n\t\t\t\tbool foundGround;\n\t\t\t\tfloat groundZ = CWorld::FindGroundZFor3DCoord(xOffset + coors.x, yOffset + coors.y, coors.z + 1.0, &foundGround) + 1.0f;\n\t\t\t\tif (foundGround) {\n\t\t\t\t\tCVector finalPos(coors.x + xOffset, coors.y + yOffset, coors.z > groundZ ? coors.z : groundZ);\n\n\t\t\t\t\tif (i == 0)\n\t\t\t\t\t\tleaderPos = finalPos;\n\n\t\t\t\t\tint gangModel = ChooseGangOccupation(pedType - PEDTYPE_GANG1);\n\t\t\t\t\tif (((CPedModelInfo*)CModelInfo::GetModelInfo(gangModel))->GetRwObject()) {\n\t\t\t\t\t\tCEntity* obstacles[6] = { nil, nil, nil, nil, nil, nil };\n\t\t\t\t\t\tCPedPlacement::IsPositionClearForPed(finalPos, CModelInfo::GetModelInfo(gangModel)->GetColModel()->boundingSphere.radius, ARRAY_SIZE(obstacles), obstacles);\n\t\t\t\t\t\tbool foundObstacle = false;\n\t\t\t\t\t\tfor (int m = 0; m < ARRAY_SIZE(obstacles); m++) {\n\t\t\t\t\t\t\tCEntity* obstacle = obstacles[m];\n\t\t\t\t\t\t\tif (obstacle) {\n\t\t\t\t\t\t\t\tint n = 0;\n\t\t\t\t\t\t\t\tbool obstacleIsHarmless = false;\n\t\t\t\t\t\t\t\tfor (int n = 0; n < pedIdx; n++) {\n\t\t\t\t\t\t\t\t\tif (obstacle == createdPeds[n])\n\t\t\t\t\t\t\t\t\t\tobstacleIsHarmless = true;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (!obstacleIsHarmless) {\n\t\t\t\t\t\t\t\t\tfoundObstacle = true;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbool memberCanSeeLeader = i == 0 ? true : CWorld::GetIsLineOfSightClear(finalPos, leaderPos, true, false, false, false, false, false, false);\n\n\t\t\t\t\t\tbool notTooCloseToLeader = i == 0 ? true : !(Abs(finalPos.z - leaderPos.z) < 1.0f);\n\n\t\t\t\t\t\tif (!foundObstacle && memberCanSeeLeader && notTooCloseToLeader) {\n\t\t\t\t\t\t\tCPed* newPed = AddPed(pedType, gangModel, finalPos);\n\t\t\t\t\t\t\tif (newPed) {\n\t\t\t\t\t\t\t\tcreatedPeds[pedIdx++] = newPed;\n\t\t\t\t\t\t\t\tfloat angle = CGeneral::GetRadianAngleBetweenPoints(\n\t\t\t\t\t\t\t\t\tcoors.x, coors.y,\n\t\t\t\t\t\t\t\t\tfinalPos.x, finalPos.y);\n\t\t\t\t\t\t\t\tnewPed->m_fRotationDest = angle;\n\t\t\t\t\t\t\t\tnewPed->m_fRotationCur = angle;\n\t\t\t\t\t\t\t\tif (CGangs::GetWillAttackPlayerWithCops(pedType))\n\t\t\t\t\t\t\t\t\tnewPed->bCanAttackPlayerWithCops = true;\n\n\t\t\t\t\t\t\t\tCVisibilityPlugins::SetClumpAlpha(newPed->GetClump(), 0);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t// No.\n#ifndef FIX_BUGS\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\tCWorld::Remove(nil);\n#endif\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (pedIdx >= 3) {\n\t\t\t\tfor (int j = 0; j < pedIdx / 2; ++j) {\n\t\t\t\t\tcreatedPeds[j]->SetChat(createdPeds[pedIdx - 1 - j], 100000);\n\t\t\t\t\tcreatedPeds[pedIdx - 1 - j]->SetChat(createdPeds[j], 100000);\n\t\t\t\t}\n\n\t\t\t\t// Make that extra guy in the middle stand there(PED_UNKNOWN locks him) and do nothing :lmao:\n\t\t\t\tif (pedIdx % 2 != 0) {\n\t\t\t\t\tCPed *tmim = createdPeds[(pedIdx - 1) / 2];\n\t\t\t\t\tfloat angle = CGeneral::GetRadianAngleBetweenPoints(\n\t\t\t\t\t\ttmim->GetPosition().x, tmim->GetPosition().y,\n\t\t\t\t\t\tcreatedPeds[0]->GetPosition().x, createdPeds[0]->GetPosition().y);\n\t\t\t\t\ttmim->SetHeading(angle);\n\t\t\t\t\ttmim->SetPedState(PED_UNKNOWN);\n\t\t\t\t}\n\t\t\t\tcreatedPeds[0]->bIsLeader = true;\n\n\t\t\t\tfor (int l = 1; l < pedIdx; ++l)\n\t\t\t\t\tcreatedPeds[l]->SetLeader(createdPeds[0]);\n\n\t\t\t} else {\n\t\t\t\tfor (int k = 0; k < pedIdx; ++k) {\n\t\t\t\t\tRemovePed(createdPeds[k]);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nCPopulation::PlaceCouple(ePedType manType, int32 manModel, ePedType womanType, int32 womanModel, CVector coors)\n{\n\t// Homosexuality filter!!!! Homophobic R* >>>:(\n\tif (manType != PEDTYPE_CIVMALE || womanType != PEDTYPE_CIVFEMALE)\n\t\treturn;\n\n\tif (!TheCamera.IsSphereVisible(coors, 1.5f) || MIN_CREATION_DIST * PedCreationDistMultiplier() <= (coors - FindPlayerPed()->GetPosition()).Magnitude2D()) {\n\t\tif (CPedPlacement::IsPositionClearForPed(coors, CModelInfo::GetModelInfo(manModel)->GetColModel()->boundingSphere.radius, -1, 0)) {\n\t\t\tbool manFoundGround;\n\t\t\tfloat manGroundZ = CWorld::FindGroundZFor3DCoord(coors.x, coors.y, coors.z, &manFoundGround) + 1.0f;\n\t\t\tif (manFoundGround) {\n\t\t\t\tCVector correctedManPos = coors;\n\t\t\t\tcorrectedManPos.z = Max(coors.z, manGroundZ);\n\t\t\t\tif (((CPedModelInfo*)CModelInfo::GetModelInfo(manModel))->GetRwObject()) {\n\t\t\t\t\tCPed *man = AddPed(PEDTYPE_CIVMALE, manModel, correctedManPos);\n\t\t\t\t\tif (man) {\n\t\t\t\t\t\tman->SetObjective(OBJECTIVE_NONE);\n\t\t\t\t\t\tman->SetWanderPath(CGeneral::GetRandomNumberInRange(0, 8));\n\t\t\t\t\t\tman->bIsLeader = true;\n\t\t\t\t\t\tCVisibilityPlugins::SetClumpAlpha(man->GetClump(), 0);\n\n\t\t\t\t\t\tif (((CPedModelInfo*)CModelInfo::GetModelInfo(womanModel))->GetRwObject()) {\n\t\t\t\t\t\t\tCPed* woman = AddPed(PEDTYPE_CIVFEMALE, womanModel, correctedManPos); // will set the correct position later\n\t\t\t\t\t\t\tif (woman) {\n\t\t\t\t\t\t\t\twoman->SetObjective(OBJECTIVE_FOLLOW_CHAR_IN_FORMATION, man);\n\t\t\t\t\t\t\t\twoman->SetFormation(FORMATION_RIGHT);\n\n\t\t\t\t\t\t\t\tCVector formationPos = woman->GetFormationPosition();\n\t\t\t\t\t\t\t\tCVector womanPos = formationPos;\n\t\t\t\t\t\t\t\tbool womanFoundGround;\n\t\t\t\t\t\t\t\tfloat formationGroundZ = CWorld::FindGroundZFor3DCoord(formationPos.x, formationPos.y, 1.0f + formationPos.z, &womanFoundGround) + 1.0f;\n\n\t\t\t\t\t\t\t\tif (womanFoundGround) {\n\t\t\t\t\t\t\t\t\tCVector correctedWomanPos = womanPos;\n\t\t\t\t\t\t\t\t\tcorrectedWomanPos.z = Max(womanPos.z, formationGroundZ);\n\t\t\t\t\t\t\t\t\twoman->SetPosition(correctedWomanPos);\n\n\t\t\t\t\t\t\t\t\t// What's the point of this??\n\t\t\t\t\t\t\t\t\tCEntity* obstacles[3];\n\t\t\t\t\t\t\t\t\tmemcpy(obstacles, gCoupleObstacles, sizeof(gCoupleObstacles));\n\n\t\t\t\t\t\t\t\t\tCPedPlacement::IsPositionClearForPed(womanPos, CModelInfo::GetModelInfo(womanModel)->GetColModel()->boundingSphere.radius, ARRAY_SIZE(obstacles), obstacles);\n\t\t\t\t\t\t\t\t\tfor (int i = 0; i < ARRAY_SIZE(obstacles); i++) {\n\t\t\t\t\t\t\t\t\t\tCEntity *obstacle = obstacles[i];\n\t\t\t\t\t\t\t\t\t\tif (obstacle) {\n\n\t\t\t\t\t\t\t\t\t\t\t// We found a real obstacle, so let's break and we can delete them...\n\t\t\t\t\t\t\t\t\t\t\tif (obstacle != man && obstacle != woman)\n\t\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\tif (i == ARRAY_SIZE(obstacles) - 1) {\n\t\t\t\t\t\t\t\t\t\t\tCVisibilityPlugins::SetClumpAlpha(woman->GetClump(), 0);\n\t\t\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tRemovePed(woman);\n\t\t\t\t\t\t\t\tRemovePed(man);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n// Mostly copy paste of PlaceGangMembersInFormation.\nvoid\nCPopulation::PlaceMallPedsAsStationaryGroup(CVector const& coors, int32 group)\n{\n#ifdef FIX_BUGS\n\tCPed *createdPeds[6];\n#else\n\tCPed *createdPeds[5];\n#endif\n\n\tif (CGame::currArea != AREA_MALL)\n\t\treturn;\n\n\tint pedAmount = CGeneral::GetRandomNumberInRange(0, 4) + 3;\n\n\tfloat circleSector = TWOPI / pedAmount;\n\n\tfloat circleR = Sqrt(0.5f / (1.0f - Cos(circleSector)));\n\n\tif (!TheCamera.IsSphereVisible(coors, circleR) ||\n\t\tMIN_CREATION_DIST * PedCreationDistMultiplier() <= (coors - FindPlayerPed()->GetPosition()).Magnitude2D()) {\n\n\t\tif (CPedPlacement::IsPositionClearForPed(coors, circleR, -1, 0)) {\n\t\t\tint pedIdx = 0;\n\t\t\tCVector leaderPos;\n\n\t\t\tfor (int i = 0; i < pedAmount; i++) {\t\n\t\t\t\tfloat angleMult = i + CGeneral::GetRandomNumberInRange(-0.2f, 0.2f);\n\t\t\t\tfloat randomR = circleR + CGeneral::GetRandomNumberInRange(-0.2f, 0.2f) * circleR;\n\t\t\t\tfloat xOffset = randomR * Cos(angleMult * circleSector);\n\t\t\t\tfloat yOffset = randomR * Sin(angleMult * circleSector);\n\t\t\t\tbool foundGround;\n\t\t\t\tfloat groundZ = CWorld::FindGroundZFor3DCoord(xOffset + coors.x, yOffset + coors.y, coors.z + 1.0, &foundGround) + 1.0f;\n\t\t\t\tif (foundGround) {\n\t\t\t\t\tCVector finalPos(coors.x + xOffset, coors.y + yOffset, coors.z > groundZ ? coors.z : groundZ);\n\n\t\t\t\t\tif (i == 0)\n\t\t\t\t\t\tleaderPos = finalPos;\n\n\t\t\t\t\tint pedModel = ChooseCivilianOccupation(group);\n\t\t\t\t\tCPedModelInfo *pedModelInfo = (CPedModelInfo*)CModelInfo::GetModelInfo(pedModel);\n\t\t\t\t\tif (pedModelInfo->GetRwObject()) {\n\t\t\t\t\t\tCEntity* obstacles[6] = { nil, nil, nil, nil, nil, nil };\n\t\t\t\t\t\tCPedPlacement::IsPositionClearForPed(finalPos, CModelInfo::GetModelInfo(pedModel)->GetColModel()->boundingSphere.radius, ARRAY_SIZE(obstacles), obstacles);\n\t\t\t\t\t\tbool foundObstacle = false;\n\t\t\t\t\t\tfor (int m = 0; m < ARRAY_SIZE(obstacles); m++) {\n\t\t\t\t\t\t\tCEntity* obstacle = obstacles[m];\n\t\t\t\t\t\t\tif (obstacle) {\n\t\t\t\t\t\t\t\tint n = 0;\n\t\t\t\t\t\t\t\tbool obstacleIsHarmless = false;\n\t\t\t\t\t\t\t\tfor (int n = 0; n < pedIdx; n++) {\n\t\t\t\t\t\t\t\t\tif (obstacle == createdPeds[n])\n\t\t\t\t\t\t\t\t\t\tobstacleIsHarmless = true;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (!obstacleIsHarmless) {\n\t\t\t\t\t\t\t\t\tfoundObstacle = true;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbool memberCanSeeLeader = i == 0 ? true : CWorld::GetIsLineOfSightClear(finalPos, leaderPos, true, false, false, false, false, false, false);\n\n\t\t\t\t\t\tbool notTooCloseToLeader = i == 0 ? true : !(Abs(finalPos.z - leaderPos.z) < 1.0f);\n\n\t\t\t\t\t\tif (!foundObstacle && memberCanSeeLeader && notTooCloseToLeader) {\n\t\t\t\t\t\t\tCPed *newPed = AddPed(pedModelInfo->m_pedType, pedModel, finalPos);\n\t\t\t\t\t\t\tif (newPed) {\n\t\t\t\t\t\t\t\tcreatedPeds[pedIdx++] = newPed;\n\t\t\t\t\t\t\t\tfloat angle = CGeneral::GetRadianAngleBetweenPoints(\n\t\t\t\t\t\t\t\t\tcoors.x, coors.y,\n\t\t\t\t\t\t\t\t\tfinalPos.x, finalPos.y);\n\t\t\t\t\t\t\t\tnewPed->m_fRotationDest = angle;\n\t\t\t\t\t\t\t\tnewPed->m_fRotationCur = angle;\n\t\t\t\t\t\t\t\tnewPed->m_fearFlags = 0;\n\t\t\t\t\t\t\t\tCVisibilityPlugins::SetClumpAlpha(newPed->GetClump(), 0);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t// No.\n#ifndef FIX_BUGS\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\tCWorld::Remove(nil);\n#endif\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (pedIdx >= 3) {\n\t\t\t\tfor (int j = 0; j < pedIdx / 2; ++j) {\n\t\t\t\t\tcreatedPeds[j]->SetChat(createdPeds[pedIdx - 1 - j], 100000);\n\t\t\t\t\tcreatedPeds[pedIdx - 1 - j]->SetChat(createdPeds[j], 100000);\n\t\t\t\t}\n\n\t\t\t\t// Make that extra guy in the middle stand there(PED_UNKNOWN locks him) and do nothing :lmao:\n\t\t\t\tif (pedIdx % 2 != 0) {\n\t\t\t\t\tCPed *tmim = createdPeds[(pedIdx - 1) / 2];\n\t\t\t\t\tfloat angle = CGeneral::GetRadianAngleBetweenPoints(\n\t\t\t\t\t\ttmim->GetPosition().x, tmim->GetPosition().y,\n\t\t\t\t\t\tcreatedPeds[0]->GetPosition().x, createdPeds[0]->GetPosition().y);\n\t\t\t\t\ttmim->SetHeading(angle);\n\t\t\t\t\ttmim->SetPedState(PED_UNKNOWN);\n\t\t\t\t}\n\t\t\t\tcreatedPeds[0]->bIsLeader = true;\n\n\t\t\t\tfor (int l = 1; l < pedIdx; ++l)\n\t\t\t\t\tcreatedPeds[l]->SetLeader(createdPeds[0]);\n\n\t\t\t} else {\n\t\t\t\tfor (int k = 0; k < pedIdx; ++k) {\n\t\t\t\t\tRemovePed(createdPeds[k]);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/peds/Population.h",
    "content": "#pragma once\n\n#include \"Game.h\"\n#include \"PedType.h\"\n\nclass CPed;\nclass CVehicle;\nclass CDummyObject;\nclass CObject;\n\nstruct PedGroup\n{\n\tint32 models[NUMMODELSPERPEDGROUP];\n};\n\nclass CPopulation\n{\npublic:\n\tstatic PedGroup ms_pPedGroups[NUMPEDGROUPS];\n\tstatic bool ms_bGivePedsWeapons;\n\tstatic int32 m_AllRandomPedsThisType;\n\tstatic float PedDensityMultiplier;\n\tstatic uint32 ms_nTotalMissionPeds;\n\tstatic int32 MaxNumberOfPedsInUse;\n\tstatic int32 MaxNumberOfPedsInUseInterior;\n\tstatic uint32 ms_nNumCivMale;\n\tstatic uint32 ms_nNumCivFemale;\n\tstatic uint32 ms_nNumCop;\n\tstatic bool bZoneChangeHasHappened;\n\tstatic uint32 ms_nNumEmergency;\n\tstatic int8 m_CountDownToPedsAtStart;\n\tstatic uint32 ms_nNumGang1;\n\tstatic uint32 ms_nNumGang2;\n\tstatic uint32 ms_nTotalPeds;\n\tstatic uint32 ms_nNumGang3;\n\tstatic uint32 ms_nTotalGangPeds;\n\tstatic uint32 ms_nNumGang4;\n\tstatic uint32 ms_nTotalCivPeds;\n\tstatic uint32 ms_nNumGang5;\n\tstatic uint32 ms_nNumDummy;\n\tstatic uint32 ms_nNumGang6;\n\tstatic uint32 ms_nNumGang9;\n\tstatic uint32 ms_nNumGang7;\n\tstatic uint32 ms_nNumGang8;\n\n\tstatic uint32 ms_nTotalCarPassengerPeds;\n\tstatic uint32 NumMiamiViceCops;\n\n\tstatic void Initialise();\n\tstatic void Update(bool);\n\tstatic void LoadPedGroups();\n\tstatic void UpdatePedCount(ePedType, bool);\n\tstatic void DealWithZoneChange(eLevelName oldLevel, eLevelName newLevel, bool);\n\tstatic CPed *AddPedInCar(CVehicle *car, bool isDriver);\n\tstatic void RemovePed(CPed *ent);\n\tstatic int32 ChooseCivilianOccupation(int32);\n\tstatic int32 ChooseNextCivilianOccupation(int32);\n\tstatic void ChooseCivilianCoupleOccupations(int32, int32&, int32&);\n\tstatic int32 ChoosePolicePedOccupation();\n\tstatic int32 ChooseGangOccupation(int);\n\tstatic void GeneratePedsAtStartOfGame();\n\tstatic float PedCreationDistMultiplier();\n\tstatic CPed *AddPed(ePedType pedType, uint32 mi, CVector const &coors, int32 modifier = 0);\n\tstatic void AddToPopulation(float, float, float, float);\n\tstatic void ManagePopulation(void);\n\tstatic void MoveCarsAndPedsOutOfAbandonedZones(void);\n\tstatic void ConvertToRealObject(CDummyObject*);\n\tstatic void ConvertToDummyObject(CObject*);\n\tstatic void ConvertAllObjectsToDummyObjects(void);\n\tstatic bool TestRoomForDummyObject(CObject*);\n\tstatic bool TestSafeForRealObject(CDummyObject*);\n\tstatic bool IsSkateable(CVector const&);\n\tstatic bool CanJeerAtStripper(int32 model);\n\tstatic void RemovePedsIfThePoolGetsFull(void);\n\tstatic bool IsMale(int32);\n\tstatic bool IsFemale(int32);\n\tstatic bool IsSunbather(int32);\n\tstatic int32 ComputeRandomisedGangSize(void);\n\tstatic bool CanSolicitPlayerInCar(int32);\n\tstatic bool CanSolicitPlayerOnFoot(int32);\n\tstatic bool IsSecurityGuard(ePedType);\n\tstatic void PlaceGangMembers(ePedType, int32, CVector const&);\n\tstatic void PlaceGangMembersInFormation(ePedType, int32, CVector const&);\n\tstatic void PlaceGangMembersInCircle(ePedType, int32, CVector const&);\n\tstatic void PlaceCouple(ePedType, int32, ePedType, int32, CVector);\n\tstatic void PlaceMallPedsAsStationaryGroup(CVector const&, int32);\n\tstatic CPed* AddDeadPedInFrontOfCar(const CVector& pos, CVehicle* pCulprit);\n};\n"
  },
  {
    "path": "src/render/2dEffect.h",
    "content": "#pragma once\n\nenum {\n\tEFFECT_LIGHT,\n\tEFFECT_PARTICLE,\n\tEFFECT_ATTRACTOR,\n\tEFFECT_PED_ATTRACTOR,\n\tEFFECT_SUNGLARE\n};\n\nenum {\n\tLIGHT_ON,\n\tLIGHT_ON_NIGHT,\n\tLIGHT_FLICKER,\n\tLIGHT_FLICKER_NIGHT,\n\tLIGHT_FLASH1,\n\tLIGHT_FLASH1_NIGHT,\n\tLIGHT_FLASH2,\n\tLIGHT_FLASH2_NIGHT,\n\tLIGHT_FLASH3,\n\tLIGHT_FLASH3_NIGHT,\n\tLIGHT_RANDOM_FLICKER,\n\tLIGHT_RANDOM_FLICKER_NIGHT,\n\tLIGHT_SPECIAL,\n\tLIGHT_BRIDGE_FLASH1,\n\tLIGHT_BRIDGE_FLASH2,\n};\n\nenum {\n\tATTRACTORTYPE_ICECREAM,\n\tATTRACTORTYPE_STARE\n};\n\nenum {\n\tLIGHTFLAG_LOSCHECK = 1,\n\t// same order as CPointLights flags, must start at 2\n\tLIGHTFLAG_FOG_NORMAL = 2,\t// can have light and fog\n\tLIGHTFLAG_FOG_ALWAYS = 4,\t// fog only\n\tLIGHTFLAG_HIDE_OBJECT = 8,\t// hide the object instead of rendering light (???)\n\tLIGHTFLAG_LONG_DIST = 16,\n\tLIGHTFLAG_FOG = (LIGHTFLAG_FOG_NORMAL|LIGHTFLAG_FOG_ALWAYS)\n};\n\nclass C2dEffect\n{\npublic:\n\tstruct Light {\n\t\tfloat dist;\n\t\tfloat range;\t// of pointlight\n\t\tfloat size;\n\t\tfloat shadowSize;\n\t\tuint8 lightType;\t// LIGHT_\n\t\tuint8 roadReflection;\n\t\tuint8 flareType;\n\t\tuint8 shadowIntensity;\n\t\tuint8 flags;\t\t// LIGHTFLAG_\n\t\tRwTexture *corona;\n\t\tRwTexture *shadow;\n\t};\n\tstruct Particle {\n\t\tint particleType;\n\t\tCVector dir;\n\t\tfloat scale;\n\t};\n\tstruct Attractor {\n\t\tCVector dir;\n\t\tint8 type;\n\t\tuint8 probability;\n\t};\n\tstruct PedAttractor {\n\t\tCVector queueDir;\n\t\tCVector useDir;\n\t\tint8 type;\n\t};\n\n\tCVector pos;\n\tCRGBA col;\n\tuint8 type;\n\tunion {\n\t\tLight light;\n\t\tParticle particle;\n\t\tAttractor attractor;\n\t\tPedAttractor pedattr;\n\t};\n\n\tC2dEffect(void) {}\n\tvoid Shutdown(void){\n\t\tif(type == EFFECT_LIGHT){\n\t\t\tif(light.corona)\n\t\t\t\tRwTextureDestroy(light.corona);\n\t\t\tlight.corona = nil;\n\t\t\tif(light.shadow)\n\t\t\t\tRwTextureDestroy(light.shadow);\n\t\t\tlight.shadow = nil;\n\t\t}\n\t}\n};\n\nVALIDATE_SIZE(C2dEffect, 0x34);\n"
  },
  {
    "path": "src/render/Antennas.cpp",
    "content": "#include \"common.h\"\n\n#include \"main.h\"\n#include \"Antennas.h\"\n\nCAntenna CAntennas::aAntennas[NUMANTENNAS];\n\nvoid\nCAntennas::Init(void)\n{\n\tint i;\n\tfor(i = 0; i < NUMANTENNAS; i++){\n\t\taAntennas[i].active = false;\n\t\taAntennas[i].updatedLastFrame = false;\n\t}\n}\n\n// Free antennas that aren't used anymore\nvoid\nCAntennas::Update(void)\n{\n\tint i;\n\n\tfor(i = 0; i < NUMANTENNAS; i++){\n\t\tif(aAntennas[i].active && !aAntennas[i].updatedLastFrame)\n\t\t\taAntennas[i].active = false;\n\t\taAntennas[i].updatedLastFrame = false;\n\t}\n}\n\n// Add a new one or update an old one\nvoid\nCAntennas::RegisterOne(uint32 id, CVector dir, CVector position, float length)\n{\n\tint i, j;\n\n\tfor(i = 0; i < NUMANTENNAS; i++)\n\t\tif(aAntennas[i].active && aAntennas[i].id == id)\n\t\t\tbreak;\n\n\tif(i >= NUMANTENNAS){\n\t\t// not found, register new one\n\n\t\t// find empty slot\n\t\tfor(i = 0; i < NUMANTENNAS; i++)\n\t\t\tif(!aAntennas[i].active)\n\t\t\t\tbreak;\n\n\t\t// there is space\n\t\tif(i < NUMANTENNAS){\n\t\t\taAntennas[i].active = true;\n\t\t\taAntennas[i].updatedLastFrame = true;\n\t\t\taAntennas[i].id = id;\n\t\t\taAntennas[i].segmentLength = length/6.0f;\n\t\t\tfor(j = 0; j < 6; j++){\n\t\t\t\taAntennas[i].pos[j] = position + dir*j*aAntennas[i].segmentLength;\n\t\t\t\taAntennas[i].speed[j] = CVector(0.0f, 0.0f, 0.0f);\n\t\t\t}\n\t\t}\n\t}else{\n\t\t// found, update\n\t\taAntennas[i].Update(dir, position);\n\t\taAntennas[i].updatedLastFrame = true;\n\t}\n}\n\nstatic RwIm3DVertex vertexbufferA[2];\n\nvoid\nCAntennas::Render(void)\n{\n\tint i, j;\n\n\tPUSH_RENDERGROUP(\"CAntennas::Render\");\n\tfor(i = 0; i < NUMANTENNAS; i++){\n\t\tif(!aAntennas[i].active)\n\t\t\tcontinue;\n\n\t\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);\n\t\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);\n\t\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);\n\t\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);\n\t\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil);\n\n\t\tfor(j = 0; j < 5; j++){\n\t\t\tRwIm3DVertexSetRGBA(&vertexbufferA[0], 200, 200, 200, 100);\n\t\t\tRwIm3DVertexSetPos(&vertexbufferA[0],\n\t\t\t\taAntennas[i].pos[j].x,\n\t\t\t\taAntennas[i].pos[j].y,\n\t\t\t\taAntennas[i].pos[j].z);\n\t\t\tRwIm3DVertexSetRGBA(&vertexbufferA[1], 200, 200, 200, 100);\n\t\t\tRwIm3DVertexSetPos(&vertexbufferA[1],\n\t\t\t\taAntennas[i].pos[j+1].x,\n\t\t\t\taAntennas[i].pos[j+1].y,\n\t\t\t\taAntennas[i].pos[j+1].z);\n\n\t\t\t// LittleTest();\n\t\t\tif(RwIm3DTransform(vertexbufferA, 2, nil, 0)){\n\t\t\t\tRwIm3DRenderLine(0, 1);\n\t\t\t\tRwIm3DEnd();\n\t\t\t}\n\t\t}\n\t}\n\n\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);\n\n\tPOP_RENDERGROUP();\n}\n\nvoid\nCAntenna::Update(CVector dir, CVector basepos)\n{\n\tint i;\n\n\tpos[0] = basepos;\n\tpos[1] = basepos + dir*segmentLength;\n\n\tfor(i = 2; i < 6; i++){\n\t\tCVector basedir = pos[i-1] - pos[i-2];\n\t\tCVector newdir = pos[i] - pos[i-1] +\t// drag along\n\t\t\tdir*0.1f +\t// also drag up a bit for stiffness\n\t\t\tspeed[i];\t// and keep moving\n\t\tnewdir.Normalise();\n\t\tnewdir *= segmentLength;\n\t\tCVector newpos = pos[i-1] + (basedir + newdir)/2.0f;\n\t\tspeed[i] = (newpos - pos[i])*0.9f;\n\t\tpos[i] = newpos;\n\t}\n}\n"
  },
  {
    "path": "src/render/Antennas.h",
    "content": "#pragma once\n\nclass CAntenna\n{\npublic:\n\tbool active;\n\tbool updatedLastFrame;\n\tuint32 id;\n\tfloat segmentLength;\n\tCVector pos[6];\n\tCVector speed[6];\n\n\tvoid Update(CVector dir, CVector pos);\n};\n\nclass CAntennas\n{\n\t// no need to use game's array\n\tstatic CAntenna aAntennas[NUMANTENNAS];\npublic:\n\tstatic void Init(void);\n\tstatic void Update(void);\n\tstatic void RegisterOne(uint32 id, CVector dir, CVector position, float length);\n\tstatic void Render(void);\n};\n"
  },
  {
    "path": "src/render/Clouds.cpp",
    "content": "#include \"common.h\"\n\n#include \"main.h\"\n#include \"Sprite.h\"\n#include \"Sprite2d.h\"\n#include \"General.h\"\n#include \"Game.h\"\n#include \"Coronas.h\"\n#include \"Camera.h\"\n#include \"TxdStore.h\"\n#include \"Weather.h\"\n#include \"Clock.h\"\n#include \"Timer.h\"\n#include \"Timecycle.h\"\n#include \"Renderer.h\"\n#include \"Clouds.h\"\n\n#define SMALLSTRIPHEIGHT 4.0f\n#define HORIZSTRIPHEIGHT 48.0f\n\nRwTexture *gpCloudTex[5];\n\nfloat CClouds::CloudRotation;\nuint32 CClouds::IndividualRotation;\n\nfloat CClouds::ms_cameraRoll;\nfloat CClouds::ms_horizonZ;\nfloat CClouds::ms_HorizonTilt;\nCRGBA CClouds::ms_colourTop;\nCRGBA CClouds::ms_colourBottom;\nCRGBA CClouds::ms_colourBkGrd;\n\nvoid\nCClouds::Init(void)\n{\n\tCTxdStore::PushCurrentTxd();\n\tCTxdStore::SetCurrentTxd(CTxdStore::FindTxdSlot(\"particle\"));\n\tgpCloudTex[0] = RwTextureRead(\"cloud1\", nil);\n\tgpCloudTex[1] = RwTextureRead(\"cloud2\", nil);\n\tgpCloudTex[2] = RwTextureRead(\"cloud3\", nil);\n\tgpCloudTex[3] = RwTextureRead(\"cloudhilit\", nil);\n\tgpCloudTex[4] = RwTextureRead(\"cloudmasked\", nil);\n\tCTxdStore::PopCurrentTxd();\n\tCloudRotation = 0.0f;\n}\n\nvoid\nCClouds::Shutdown(void)\n{\n\tRwTextureDestroy(gpCloudTex[0]);\n\tgpCloudTex[0] = nil;\n\tRwTextureDestroy(gpCloudTex[1]);\n\tgpCloudTex[1] = nil;\n\tRwTextureDestroy(gpCloudTex[2]);\n\tgpCloudTex[2] = nil;\n\tRwTextureDestroy(gpCloudTex[3]);\n\tgpCloudTex[3] = nil;\n\tRwTextureDestroy(gpCloudTex[4]);\n\tgpCloudTex[4] = nil;\n}\n\nvoid\nCClouds::Update(void)\n{\n\tfloat s = Sin(TheCamera.Orientation - 0.85f);\n#ifdef FIX_BUGS\n\tCloudRotation += CWeather::Wind*s*0.001f*CTimer::GetTimeStepFix();\n\tIndividualRotation += (CWeather::Wind*CTimer::GetTimeStep()*0.5f + 0.3f*CTimer::GetTimeStepFix()) * 60.0f;\n#else\n\tCloudRotation += CWeather::Wind*s*0.001f;\n\tIndividualRotation += (CWeather::Wind*CTimer::GetTimeStep()*0.5f + 0.3f) * 60.0f;\n#endif\n}\n\nfloat StarCoorsX[9] = { 0.0f, 0.05f, 0.13f, 0.4f, 0.7f, 0.6f, 0.27f, 0.55f, 0.75f };\nfloat StarCoorsY[9] = { 0.0f, 0.45f, 0.9f, 1.0f, 0.85f, 0.52f, 0.48f, 0.35f, 0.2f };\nfloat StarSizes[9] = { 1.0f, 1.4f, 0.9f, 1.0f, 0.6f, 1.5f, 1.3f, 1.0f, 0.8f };\n\nfloat LowCloudsX[12] = { 1.0f, 0.7f, 0.0f, -0.7f, -1.0f, -0.7f, 0.0f, 0.7f, 0.8f, -0.8f, 0.4f, -0.4f };\nfloat LowCloudsY[12] = { 0.0f, -0.7f, -1.0f, -0.7f, 0.0f, 0.7f, 1.0f, 0.7f, 0.4f, 0.4f, -0.8f, -0.8f };\nfloat LowCloudsZ[12] = { 0.0f, 1.0f, 0.5f, 0.0f, 1.0f, 0.3f, 0.9f, 0.4f, 1.3f, 1.4f, 1.2f, 1.7f };\n\nfloat CoorsOffsetX[37] = {\n\t0.0f, 60.0f, 72.0f, 48.0f, 21.0f, 12.0f,\n\t9.0f, -3.0f, -8.4f, -18.0f, -15.0f, -36.0f,\n\t-40.0f, -48.0f, -60.0f, -24.0f, 100.0f, 100.0f,\n\t100.0f, 100.0f, 100.0f, 100.0f, 100.0f, 100.0f,\n\t100.0f, 100.0f, -30.0f, -20.0f, 10.0f, 30.0f,\n\t0.0f, -100.0f, -100.0f, -100.0f, -100.0f, -100.0f, -100.0f\n};\nfloat CoorsOffsetY[37] = {\n\t100.0f, 100.0f, 100.0f, 100.0f, 100.0f, 100.0f,\n\t100.0f, 100.0f, 100.0f, 100.0f, 100.0f, 100.0f,\n\t100.0f, 100.0f, 100.0f, 100.0f, -30.0f, 10.0f,\n\t-25.0f, -5.0f, 28.0f, -10.0f, 10.0f, 0.0f,\n\t15.0f, 40.0f, -100.0f, -100.0f, -100.0f, -100.0f,\n\t-100.0f, -40.0f, -20.0f, 0.0f, 10.0f, 30.0f, 35.0f\n};\nfloat CoorsOffsetZ[37] = {\n\t2.0f, 1.0f, 0.0f, 0.3f, 0.7f, 1.4f,\n\t1.7f, 0.24f, 0.7f, 1.3f, 1.6f, 1.0f,\n\t1.2f, 0.3f, 0.7f, 1.4f, 0.0f, 0.1f,\n\t0.5f, 0.4f, 0.55f, 0.75f, 1.0f, 1.4f,\n\t1.7f, 2.0f, 2.0f, 2.3f, 1.9f, 2.4f,\n\t2.0f, 2.0f, 1.5f, 1.2f, 1.7f, 1.5f, 2.1f\n};\n\nuint8 BowRed[6] = { 30, 30, 30, 10, 0, 15 };\nuint8 BowGreen[6] = { 0, 15, 30, 30, 0, 0 };\nuint8 BowBlue[6] = { 0, 0, 0, 10, 30, 30 };\n\nvoid\nCClouds::Render(void)\n{\n\tint i;\n\tfloat szx, szy;\n\tRwV3d screenpos;\n\tRwV3d worldpos;\n\n\tif(!CGame::CanSeeOutSideFromCurrArea())\n\t\treturn;\n\n\tPUSH_RENDERGROUP(\"CClouds::Render\");\n\n\tCCoronas::SunBlockedByClouds = false;\n\n\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);\n\tRwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE);\n\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);\n\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE);\n\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE);\n\tCSprite::InitSpriteBuffer();\n\n\tfloat minute = CClock::GetHours()*60 + CClock::GetMinutes() + CClock::GetSeconds()/60.0f;\n\tRwV3d campos = TheCamera.GetPosition();\n\n\t// Moon\n\tfloat moonfadeout = Abs(minute - 180.0f);\t// fully visible at 3AM\n\tif((int)moonfadeout < 180){\t\t\t// fade in/out 3 hours\n\t\tfloat coverage = Max(CWeather::Foggyness, CWeather::CloudCoverage);\n\t\tint brightness = (1.0f - coverage) * (180 - (int)moonfadeout);\n\t\tRwV3d pos = { 0.0f, -100.0f, 15.0f };\n\t\tRwV3dAdd(&worldpos, &campos, &pos);\n\t\tif(CSprite::CalcScreenCoors(worldpos, &screenpos, &szx, &szy, false)){\n\t\t\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpCoronaTexture[2]));\n\t\t\tszx *= CCoronas::MoonSize*2.0f + 4.0f;\n\t\t\tszy *= CCoronas::MoonSize*2.0f + 4.0f;\n\t\t\tCSprite::RenderOneXLUSprite(screenpos.x, screenpos.y, screenpos.z,\n\t\t\t\tszx, szy, brightness, brightness, brightness, 255, 1.0f/screenpos.z, 255);\n\t\t}\n\t}\n\n\t// The R* logo\n\tint starintens = 0;\n\tif(CClock::GetHours() < 22 && CClock::GetHours() > 5)\n\t\tstarintens = 0;\n\telse if(CClock::GetHours() > 22 || CClock::GetHours() < 5)\n\t\tstarintens = 255;\n\telse if(CClock::GetHours() == 22)\n\t\tstarintens = 255 * CClock::GetMinutes()/60.0f;\n\telse if(CClock::GetHours() == 5)\n\t\tstarintens = 255 * (60 - CClock::GetMinutes())/60.0f;\n\tif(starintens != 0){\n\t\tfloat coverage = Max(CWeather::Foggyness, CWeather::CloudCoverage);\n\t\tint brightness = (1.0f - coverage) * starintens;\n\n\t\t// R\n\t\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpCoronaTexture[0]));\n\t\tfor(i = 0; i < 11; i++){\n\t\t\tRwV3d pos = { 100.0f, 0.0f, 10.0f };\n\t\t\tif(i >= 9) pos.x = -pos.x;\n\t\t\tRwV3dAdd(&worldpos, &campos, &pos);\n\t\t\tworldpos.y -= 90.0f*StarCoorsX[i%9];\n\t\t\tworldpos.z += 80.0f*StarCoorsY[i%9];\n\t\t\tif(CSprite::CalcScreenCoors(worldpos, &screenpos, &szx, &szy, false)){\n\t\t\t\tfloat sz = 0.8f*StarSizes[i%9];\n\t\t\t\tCSprite::RenderBufferedOneXLUSprite(screenpos.x, screenpos.y, screenpos.z,\n\t\t\t\t\tszx*sz, szy*sz, brightness, brightness, brightness, 255, 1.0f/screenpos.z, 255);\n\t\t\t}\n\t\t}\n\t\tCSprite::FlushSpriteBuffer();\n\n\t\t// *\n\t\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpCoronaTexture[0]));\n\t\tRwV3d pos = { 100.0f, 0.0f, 10.0f };\n\t\tRwV3dAdd(&worldpos, &campos, &pos);\n\t\tworldpos.y -= 90.0f;\n\t\tif(CSprite::CalcScreenCoors(worldpos, &screenpos, &szx, &szy, false)){\n\t\t\tbrightness *= (CGeneral::GetRandomNumber()&127) / 640.0f + 0.5f;\n\t\t\tCSprite::RenderOneXLUSprite(screenpos.x, screenpos.y, screenpos.z,\n\t\t\t\tszx*5.0f, szy*5.0f, brightness, brightness, brightness, 255, 1.0f/screenpos.z, 255);\n\t\t}\n\t}\n\n\t// Low clouds\n\tfloat lowcloudintensity = 1.0f - Max(Max(CWeather::Foggyness, CWeather::CloudCoverage), CWeather::ExtraSunnyness);\n\tint r = CTimeCycle::GetLowCloudsRed() * lowcloudintensity;\n\tint g = CTimeCycle::GetLowCloudsGreen() * lowcloudintensity;\n\tint b = CTimeCycle::GetLowCloudsBlue() * lowcloudintensity;\n\tfor(int cloudtype = 0; cloudtype < 3; cloudtype++){\n\t\tfor(i = cloudtype; i < 12; i += 3){\n\t\t\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpCloudTex[cloudtype]));\n\t\t\tRwV3d pos = { 800.0f*LowCloudsX[i], 800.0f*LowCloudsY[i], 60.0f*LowCloudsZ[i] };\n\t\t\tworldpos.x = campos.x + pos.x;\n\t\t\tworldpos.y = campos.y + pos.y;\n\t\t\tworldpos.z = 40.0f + pos.z;\n\t\t\tif(CSprite::CalcScreenCoors(worldpos, &screenpos, &szx, &szy, false))\n\t\t\t\tCSprite::RenderBufferedOneXLUSprite_Rotate_Dimension(screenpos.x, screenpos.y, screenpos.z,\n\t\t\t\t\tszx*320.0f, szy*40.0f, r, g, b, 255, 1.0f/screenpos.z, ms_cameraRoll, 255);\n\t\t}\n\t\tCSprite::FlushSpriteBuffer();\n\t}\n\n\t// Fluffy clouds\n\tfloat rot_sin = Sin(CloudRotation);\n\tfloat rot_cos = Cos(CloudRotation);\n\tint fluffyalpha = 160 * (1.0f - Max(CWeather::Foggyness, CWeather::ExtraSunnyness));\n\tif(fluffyalpha != 0){\n\t\tstatic bool bCloudOnScreen[37];\n\t\tfloat sundist, hilight;\n\n\t\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);\n\t\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);\n\t\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpCloudTex[4]));\n\t\tfor(i = 0; i < 37; i++){\n\t\t\tRwV3d pos = { 2.0f*CoorsOffsetX[i], 2.0f*CoorsOffsetY[i], 40.0f*CoorsOffsetZ[i] + 40.0f };\n\t\t\tworldpos.x = pos.x*rot_cos + pos.y*rot_sin + campos.x;\n\t\t\tworldpos.y = pos.x*rot_sin - pos.y*rot_cos + campos.y;\n\t\t\tworldpos.z = pos.z;\n\n\t\t\tif(CSprite::CalcScreenCoors(worldpos, &screenpos, &szx, &szy, false)){\n\t\t\t\tsundist = Sqrt(sq(screenpos.x-CCoronas::SunScreenX) + sq(screenpos.y-CCoronas::SunScreenY));\n\t\t\t\tint tr = CTimeCycle::GetFluffyCloudsTopRed();\n\t\t\t\tint tg = CTimeCycle::GetFluffyCloudsTopGreen();\n\t\t\t\tint tb = CTimeCycle::GetFluffyCloudsTopBlue();\n\t\t\t\tint br = CTimeCycle::GetFluffyCloudsBottomRed();\n\t\t\t\tint bg = CTimeCycle::GetFluffyCloudsBottomGreen();\n\t\t\t\tint bb = CTimeCycle::GetFluffyCloudsBottomBlue();\n\t\t\t\tint distLimit = (3*SCREEN_WIDTH)/4;\n\t\t\t\tif(sundist < distLimit){\n\t\t\t\t\thilight = (1.0f - Max(CWeather::Foggyness, CWeather::CloudCoverage)) * (1.0f - sundist/(float)distLimit);\n\t\t\t\t\ttr = tr*(1.0f-hilight) + 255*hilight;\n\t\t\t\t\ttg = tg*(1.0f-hilight) + 190*hilight;\n\t\t\t\t\ttb = tb*(1.0f-hilight) + 190*hilight;\n\t\t\t\t\tbr = br*(1.0f-hilight) + 255*hilight;\n\t\t\t\t\tbg = bg*(1.0f-hilight) + 190*hilight;\n\t\t\t\t\tbb = bb*(1.0f-hilight) + 190*hilight;\n\t\t\t\t\tif(sundist < SCREEN_WIDTH/10)\n\t\t\t\t\t\tCCoronas::SunBlockedByClouds = true;\n\t\t\t\t}else\n\t\t\t\t\thilight = 0.0f;\n\t\t\t\tCSprite::RenderBufferedOneXLUSprite_Rotate_2Colours(screenpos.x, screenpos.y, screenpos.z,\n\t\t\t\t\tszx*55.0f, szy*55.0f,\n\t\t\t\t\ttr, tg, tb, br, bg, bb, 0.0f, -1.0f,\n\t\t\t\t\t1.0f/screenpos.z,\n\t\t\t\t\t(uint16)IndividualRotation/65336.0f * 6.28f + ms_cameraRoll,\n\t\t\t\t\tfluffyalpha);\n\t\t\t\tbCloudOnScreen[i] = true;\n\t\t\t}else\n\t\t\t\tbCloudOnScreen[i] = false;\n\t\t}\n\t\tCSprite::FlushSpriteBuffer();\n\n\t\t// Highlights\n\t\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE);\n\t\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE);\n\t\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpCloudTex[3]));\n\n\t\tfor(i = 0; i < 37; i++){\n\t\t\tRwV3d pos = { 2.0f*CoorsOffsetX[i], 2.0f*CoorsOffsetY[i], 40.0f*CoorsOffsetZ[i] + 40.0f };\n\t\t\tworldpos.x = pos.x*rot_cos + pos.y*rot_sin + campos.x;\n\t\t\tworldpos.y = pos.x*rot_sin + pos.y*rot_cos + campos.y;\n\t\t\tworldpos.z = pos.z;\n\t\t\tif(bCloudOnScreen[i] && CSprite::CalcScreenCoors(worldpos, &screenpos, &szx, &szy, false)){\n\t\t\t\tif(sundist < SCREEN_WIDTH/3){\n\t\t\t\t\tCSprite::RenderBufferedOneXLUSprite_Rotate_Aspect(screenpos.x, screenpos.y, screenpos.z,\n\t\t\t\t\t\tszx*30.0f, szy*30.0f,\n\t\t\t\t\t\t200*hilight, 0, 0, 255, 1.0f/screenpos.z,\n\t\t\t\t\t\t1.7f - CGeneral::GetATanOfXY(screenpos.x-CCoronas::SunScreenX, screenpos.y-CCoronas::SunScreenY) + CClouds::ms_cameraRoll, 255);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tCSprite::FlushSpriteBuffer();\n\t}\n\n\t// Rainbow\n\tif(CWeather::Rainbow != 0.0f){\n\t\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpCoronaTexture[0]));\n\t\tfor(i = 0; i < 6; i++){\n\t\t\tRwV3d pos = { i*1.5f, 100.0f, 5.0f };\n\t\t\tRwV3dAdd(&worldpos, &campos, &pos);\n\t\t\tif(CSprite::CalcScreenCoors(worldpos, &screenpos, &szx, &szy, false))\n\t\t\t\tCSprite::RenderBufferedOneXLUSprite(screenpos.x, screenpos.y, screenpos.z,\n\t\t\t\t\t2.0f*szx, 50.0*szy,\n\t\t\t\t\tBowRed[i]*CWeather::Rainbow, BowGreen[i]*CWeather::Rainbow, BowBlue[i]*CWeather::Rainbow,\n\t\t\t\t\t255, 1.0f/screenpos.z, 255);\n\n\t\t}\n\t\tCSprite::FlushSpriteBuffer();\n\t}\n\n\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);\n\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);\n\tRwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);\n\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);\n\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);\n\n\tPOP_RENDERGROUP();\n}\n\nbool\nUseDarkBackground(void)\n{\n\treturn TheCamera.GetForward().z < -0.9f || gbShowCollisionPolys;\n}\n\nvoid\nCClouds::RenderBackground(int16 topred, int16 topgreen, int16 topblue,\n\tint16 botred, int16 botgreen, int16 botblue, int16 alpha)\n{\n\tPUSH_RENDERGROUP(\"CClouds::RenderBackground\");\n\n\tCVector right = CrossProduct(TheCamera.GetUp(), TheCamera.GetForward());\n\tright.Normalise();\n\tfloat c = right.Magnitude2D();\n\tif(c > 1.0f)\n\t\tc = 1.0f;\n\tms_cameraRoll = Acos(c);\n\tif(right.z < 0.0f)\n\t\tms_cameraRoll = -ms_cameraRoll;\n\n\tms_HorizonTilt = SCREEN_WIDTH/2.0f * Tan(ms_cameraRoll);\n\n\tif(UseDarkBackground()){\n\t\tms_colourTop.r = 50;\n\t\tms_colourTop.g = 50;\n\t\tms_colourTop.b = 50;\n\t\tms_colourTop.a = 255;\n\t\tif(gbShowCollisionPolys){\n\t\t\tif(CTimer::GetFrameCounter() & 1){\n\t\t\t\tms_colourTop.r = 0;\n\t\t\t\tms_colourTop.g = 0;\n\t\t\t\tms_colourTop.b = 0;\n\t\t\t}else{\n\t\t\t\tms_colourTop.r = 255;\n\t\t\t\tms_colourTop.g = 255;\n\t\t\t\tms_colourTop.b = 255;\n\t\t\t}\n\t\t}\n\t\tms_colourBottom = ms_colourTop;\n\t\tCRect r(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);\n\t\tCSprite2d::DrawRect(r, ms_colourBottom, ms_colourBottom, ms_colourTop, ms_colourTop);\n\t}else{\n\t\tms_horizonZ = CSprite::CalcHorizonCoors();\n\n\t\tint fogr = (topred + 2 * botred) / 3;\n\t\tint fogg = (topgreen + 2 * botgreen) / 3;\n\t\tint fogb = (topblue + 2 * botblue) / 3;\n\n\t\t// Draw top/bottom gradient\n\t\tfloat gradheight = SCREEN_HEIGHT/2.0f;\n\n\t\tms_colourTop.r = topred;\n\t\tms_colourTop.g = topgreen;\n\t\tms_colourTop.b = topblue;\n\t\tms_colourTop.a = alpha;\n\t\tms_colourBottom.r = botred;\n\t\tms_colourBottom.g = botgreen;\n\t\tms_colourBottom.b = botblue;\n\t\tms_colourBottom.a = alpha;\n\n\t\tfloat botright = ms_horizonZ - ms_HorizonTilt;\n\t\tfloat botleft = ms_horizonZ + ms_HorizonTilt;\n\t\tfloat topright = botright - gradheight;\n\t\tfloat topleft = botleft - gradheight;\n\n\t\tCSprite2d::DrawAnyRect(0.0f, topleft,  SCREEN_WIDTH, topright,  0.0f, botleft,  SCREEN_WIDTH, botright,\n\t\t\t ms_colourTop, ms_colourTop, ms_colourBottom, ms_colourBottom);\n\n\t\t// draw the small stripe (whatever it's supposed to be)\n\t\tms_colourTop.r = fogr;\n\t\tms_colourTop.g = fogg;\n\t\tms_colourTop.b = fogb;\n\t\tms_colourTop.a = alpha;\n\t\ttopright = ms_horizonZ - ms_HorizonTilt;\n\t\ttopleft = ms_horizonZ + ms_HorizonTilt;\n\t\tbotright = topright + SMALLSTRIPHEIGHT;\n\t\tbotleft = topleft + SMALLSTRIPHEIGHT;\n\t\tCSprite2d::DrawAnyRect(0.0f, topleft,  SCREEN_WIDTH, topright,  0.0f, botleft,  SCREEN_WIDTH, botright,\n\t\t\tms_colourTop, ms_colourTop, ms_colourTop, ms_colourTop);\n\n\t\t// Only top\n\t\tif(ms_horizonZ + ms_HorizonTilt - gradheight > 0.0f ||\n\t\t   ms_horizonZ - ms_HorizonTilt - gradheight > 0.0f){\n\t\t\tms_colourTop.r = topred;\n\t\t\tms_colourTop.g = topgreen;\n\t\t\tms_colourTop.b = topblue;\n\t\t\tms_colourTop.a = alpha;\n\n\t\t\tif(ms_horizonZ - Abs(ms_HorizonTilt) - gradheight > SCREEN_HEIGHT){\n\t\t\t\t// only top is visible\n\t\t\t\ttopleft = 0.0f;\n\t\t\t\ttopright = 0.0f;\n\t\t\t\tbotleft = SCREEN_HEIGHT;\n\t\t\t\tbotright = SCREEN_HEIGHT;\n\t\t\t}else{\n\t\t\t\tbotright = ms_horizonZ - ms_HorizonTilt - gradheight;\n\t\t\t\tbotleft = ms_horizonZ + ms_HorizonTilt - gradheight;\n\t\t\t\ttopright = Min(ms_horizonZ - ms_HorizonTilt - 2*SCREEN_HEIGHT, 0.0f);\n\t\t\t\ttopleft = Min(ms_horizonZ + ms_HorizonTilt - 2*SCREEN_HEIGHT, 0.0f);\n\t\t\t}\n\n\t\t\tCSprite2d::DrawAnyRect(0.0f, topleft,  SCREEN_WIDTH, topright,  0.0f, botleft,  SCREEN_WIDTH, botright,\n\t\t\t\tms_colourTop, ms_colourTop, ms_colourTop, ms_colourTop);\n\t\t}\n\n\t\t// Set both to fog colour for RenderHorizon\n\t\tms_colourTop.r = fogr;\n\t\tms_colourTop.g = fogg;\n\t\tms_colourTop.b = fogb;\n\t\tms_colourBottom.r = fogr;\n\t\tms_colourBottom.g = fogg;\n\t\tms_colourBottom.b = fogb;\n\t}\n\n\tPOP_RENDERGROUP();\n}\n\nvoid\nCClouds::RenderHorizon(void)\n{\n\tif(UseDarkBackground())\n\t\treturn;\n\n\tPUSH_RENDERGROUP(\"CClouds::RenderHorizon\");\n\n\tms_colourBottom.a = 230;\n\tms_colourTop.a = 80;\n\n\tfloat topright = ms_horizonZ - ms_HorizonTilt;\n\tfloat topleft = ms_horizonZ + ms_HorizonTilt;\n\tfloat botright = topright + SMALLSTRIPHEIGHT;\n\tfloat botleft = topleft + SMALLSTRIPHEIGHT;\n\n\tCSprite2d::DrawAnyRect(0.0f, topleft,  SCREEN_WIDTH, topright,  0.0f, botleft,  SCREEN_WIDTH, botright,\n\t\tms_colourTop, ms_colourTop, ms_colourBottom, ms_colourBottom);\n\n\n\tms_colourBkGrd.r = 128.0f*CTimeCycle::GetAmbientRed();\n\tms_colourBkGrd.g = 128.0f*CTimeCycle::GetAmbientGreen();\n\tms_colourBkGrd.b = 128.0f*CTimeCycle::GetAmbientBlue();\n\tms_colourBkGrd.a = 255;\n\n\tfloat horzstrip = SCREEN_STRETCH_Y(HORIZSTRIPHEIGHT);\n\ttopright = botright;\n\ttopleft = botleft;\n\tbotright = topright + horzstrip;\n\tbotleft = topleft + horzstrip;\n\n\tCSprite2d::DrawAnyRect(0.0f, topleft,  SCREEN_WIDTH, topright,  0.0f, botleft,  SCREEN_WIDTH, botright,\n\t\tms_colourBottom, ms_colourBottom, ms_colourBkGrd, ms_colourBkGrd);\n\n\n\ttopright = botright;\n\ttopleft = botleft;\n\tbotright = Max(topright, SCREEN_HEIGHT);\n\tbotleft = Max(topleft, SCREEN_HEIGHT);\n\n\tCSprite2d::DrawAnyRect(0.0f, topleft,  SCREEN_WIDTH, topright,  0.0f, botleft,  SCREEN_WIDTH, botright,\n\t\tms_colourBkGrd, ms_colourBkGrd, ms_colourBkGrd, ms_colourBkGrd);\n\n\tPOP_RENDERGROUP();\n}\n"
  },
  {
    "path": "src/render/Clouds.h",
    "content": "#pragma once\n\nclass CClouds\n{\npublic:\n\tstatic float CloudRotation;\n\tstatic uint32 IndividualRotation;\n\n\tstatic float ms_cameraRoll;\n\tstatic float ms_horizonZ;\n\tstatic float ms_HorizonTilt;\n\tstatic CRGBA ms_colourTop;\n\tstatic CRGBA ms_colourBottom;\n\tstatic CRGBA ms_colourBkGrd;\n\n\tstatic void Init(void);\n\tstatic void Shutdown(void);\n\tstatic void Update(void);\n\tstatic void Render(void);\n\tstatic void RenderBackground(int16 topred, int16 topgreen, int16 topblue,\n\t\tint16 botred, int16 botgreen, int16 botblue, int16 alpha);\n\tstatic void RenderHorizon(void);\n};\n"
  },
  {
    "path": "src/render/Console.cpp",
    "content": "#include \"common.h\"\n#include <stdarg.h>\n\n#include \"Console.h\"\n#include \"Font.h\"\n#include \"Timer.h\"\n\n#define CONSOLE_X_POS (30.0f)\n#define CONSOLE_Y_POS (10.0f)\n#define CONSOLE_LINE_HEIGHT (12.0f)\n\nCConsole TheConsole;\n\nvoid\nCConsole::AddLine(char *s, uint8 r, uint8 g, uint8 b)\n{\n\tchar tempstr[MAX_STR_LEN+1];\n\n\twhile (strlen(s) > MAX_STR_LEN) {\n\t\tstrncpy(tempstr, s, MAX_STR_LEN);\n\t\ttempstr[MAX_STR_LEN-1] = '\\0';\n\t\ts += MAX_STR_LEN - 1;\n\t\tAddOneLine(tempstr, r, g, b);\n\t}\n\tAddOneLine(s, r, g, b);\n}\n\nvoid\nCConsole::AddOneLine(char *s, uint8 r, uint8 g, uint8 b)\n{\n\tint32 StrIndex = (m_nLineCount + m_nCurrentLine) % MAX_LINES;\n\n\tfor (int32 i = 0; i < MAX_STR_LEN; i++) {\n\t\tBuffers[StrIndex][i] = s[i];\n\t\tif (s[i] == '\\0') break;\n\t}\n\n\tuint8 _strNum1 = m_nLineCount;\n\tif (_strNum1 < MAX_LINES)\n\t\t_strNum1++;\n\n\tm_aTimer[StrIndex] = CTimer::GetTimeInMilliseconds();\n\tBuffers[StrIndex][MAX_STR_LEN-1] = '\\0';\n\tm_aRed[StrIndex] = r;\n\tm_aGreen[StrIndex] = g;\n\tm_aBlue[StrIndex] = b;\n\n\tif (_strNum1 >= MAX_LINES)\n\t\tm_nCurrentLine = (m_nCurrentLine + 1) % MAX_LINES;\n\telse\n\t\tm_nLineCount = _strNum1;\n\n}\n\nvoid\nCConsole::Display()\n{\n\tCFont::SetPropOn();\n\tCFont::SetBackgroundOff();\n\tCFont::SetScale(0.6f, 0.6f); \n\tCFont::SetCentreOff();\n\tCFont::SetRightJustifyOff();\n\tCFont::SetJustifyOn();\n\tCFont::SetRightJustifyWrap(0.0f);\n\tCFont::SetBackGroundOnlyTextOff();\n\tCFont::SetFontStyle(FONT_STANDARD);\n#ifndef FIX_BUGS\n\tCFont::SetPropOff(); // not sure why this is here anyway\n#endif\n\tCFont::SetWrapx(RsGlobal.width);\n\n\twhile (m_nLineCount != 0 && CTimer::GetTimeInMilliseconds() - m_aTimer[m_nCurrentLine] > 20000) {\n\t\tm_nLineCount--;\n\t\tm_nCurrentLine = (m_nCurrentLine + 1) % MAX_LINES;\n\t}\n\n\tfor (int16 i = 0; i < m_nLineCount; i++) {\n\t\tint16 line = (i + m_nCurrentLine) % MAX_LINES;\n\t\tCFont::SetColor(CRGBA(0, 0, 0, 200));\n\t\tCFont::PrintString(CONSOLE_X_POS + 1.0f, CONSOLE_Y_POS + 1.0f + i * CONSOLE_LINE_HEIGHT, Buffers[line]);\n\t\tCFont::SetColor(CRGBA(m_aRed[line], m_aGreen[line], m_aBlue[line], 200));\n\t\tCFont::PrintString(CONSOLE_X_POS, CONSOLE_Y_POS + i * CONSOLE_LINE_HEIGHT, Buffers[line]);\n\t}\n}\n\nvoid\ncprintf(char* format, ...)\n{\n\tchar s[256];\n\tva_list vl1, vl2;\n\n\tva_start(vl1, format);\n\tva_copy(vl2, vl1);\n\tvsprintf(s, format, vl1);\n\tTheConsole.AddLine(s, 255, 255, 128);\n}\n"
  },
  {
    "path": "src/render/Console.h",
    "content": "#pragma once\n\nclass CConsole\n{\n\tenum\n\t{\n\t\tMAX_LINES = 8, // BUG? only shows 7\n\t\tMAX_STR_LEN = 40,\n\t};\n\n\tuint8 m_nLineCount;\n\tuint8 m_nCurrentLine;\n\twchar Buffers[MAX_LINES][MAX_STR_LEN];\n\tuint32 m_aTimer[MAX_LINES];\n\tuint8 m_aRed[MAX_LINES];\n\tuint8 m_aGreen[MAX_LINES];\n\tuint8 m_aBlue[MAX_LINES];\npublic:\n\tvoid AddLine(char *s, uint8 r, uint8 g, uint8 b);\n\tvoid AddOneLine(char *s, uint8 r, uint8 g, uint8 b);\n\tvoid Display();\n\tvoid Init() { m_nCurrentLine = 0; m_nLineCount = 0; }\n};\n\nextern CConsole TheConsole;\n"
  },
  {
    "path": "src/render/Coronas.cpp",
    "content": "#include \"common.h\"\n\n#include \"main.h\"\n#include \"General.h\"\n#include \"Entity.h\"\n#include \"RenderBuffer.h\"\n#include \"TxdStore.h\"\n#include \"Camera.h\"\n#include \"Sprite.h\"\n#include \"Timer.h\"\n#include \"World.h\"\n#include \"Weather.h\"\n#include \"Collision.h\"\n#include \"Timecycle.h\"\n#include \"Coronas.h\"\n#include \"PointLights.h\"\n#include \"Shadows.h\"\n#include \"Clock.h\"\n#include \"Bridge.h\"\n\nstruct FlareDef\n{\n\tfloat position;\n\tfloat size;\n\tint16 red;\n\tint16 green;\n\tint16 blue;\n\tint16 alpha;\n\tint16 texture;\n};\n\nFlareDef SunFlareDef[] = {\n\t{ -0.5f, 15.0f, 50, 50, 0, 200, 1 },\n\t{ -1.0f, 10.0f, 50, 20, 0, 200, 2 },\n\t{ -1.5f, 15.0f, 50, 0, 0, 200, 3 },\n\t{ -2.5f, 25.0f, 50, 0, 0, 200, 1 },\n\t{ 0.5f, 12.5f, 40, 40, 25, 200, 1 },\n\t{ 0.05f, 20.0f, 30, 22, 9, 200, 2 },\n\t{ 1.3f, 7.5f, 50, 30, 9, 200, 3 },\n\t{ 0.0f, 0.0f, 255, 255, 255, 255, 0 }\n};\n\nFlareDef HeadLightsFlareDef[] = {\n\t{ -0.5f, 15.5, 70, 70, 70, 200, 1 },\n\t{ -1.0f, 10.0, 70, 70, 70, 200, 2 },\n\t{ -1.5f, 5.5f, 50, 50, 50, 200, 3 },\n\t{ 0.5f, 12.0f, 50, 50, 50, 200, 1 },\n\t{ 0.05f, 20.0f, 40, 40, 40, 200, 2 },\n\t{ 1.3f, 8.0f, 60, 60, 60, 200, 3 },\n\t{ -2.0f, 12.0f, 50, 50, 50, 200, 1 },\n\t{ -2.3f, 15.0f, 40, 40, 40, 200, 2 },\n\t{ -3.0f, 16.0f, 40, 40, 40, 200, 3 },\n\t{ 0.0f, 0.0f, 255, 255, 255, 255, 0 }\n};\n\n\nRwTexture *gpCoronaTexture[9] = { nil, nil, nil, nil, nil, nil, nil, nil, nil };\n\nfloat CCoronas::LightsMult = 1.0f;\nfloat CCoronas::SunScreenX;\nfloat CCoronas::SunScreenY;\nint CCoronas::MoonSize;\nbool CCoronas::SunBlockedByClouds;\nint CCoronas::bChangeBrightnessImmediately;\n\nCRegisteredCorona CCoronas::aCoronas[NUMCORONAS];\n\nconst char aCoronaSpriteNames[][32] = {\n\t\"coronastar\",\n\t\"corona\",\n\t\"coronamoon\",\n\t\"coronareflect\",\n\t\"coronaheadlightline\",\n\t\"coronahex\",\n\t\"coronacircle\",\n\t\"coronaringa\",\n\t\"streek\"\n};\n\nvoid\nCCoronas::Init(void)\n{\n\tint i;\n\n\tCTxdStore::PushCurrentTxd();\n\tCTxdStore::SetCurrentTxd(CTxdStore::FindTxdSlot(\"particle\"));\n\n\tfor(i = 0; i < 9; i++)\n\t\tif(gpCoronaTexture[i] == nil)\n\t\t\tgpCoronaTexture[i] = RwTextureRead(aCoronaSpriteNames[i], nil);\n\n\tCTxdStore::PopCurrentTxd();\n\n\tfor(i = 0; i < NUMCORONAS; i++)\n\t\taCoronas[i].id = 0;\n}\n\nvoid\nCCoronas::Shutdown(void)\n{\n\tint i;\n\tfor(i = 0; i < 9; i++)\n\t\tif(gpCoronaTexture[i]){\n\t\t\tRwTextureDestroy(gpCoronaTexture[i]);\n\t\t\tgpCoronaTexture[i] = nil;\n\t\t}\n}\n\nvoid\nCCoronas::Update(void)\n{\n\tint i;\n\tstatic int LastCamLook = 0;\n\n\tLightsMult = Min(LightsMult + 0.03f * CTimer::GetTimeStep(), 1.0f);\n\n\tint CamLook = 0;\n\tif(TheCamera.Cams[TheCamera.ActiveCam].LookingLeft) CamLook |= 1;\n\tif(TheCamera.Cams[TheCamera.ActiveCam].LookingRight) CamLook |= 2;\n\tif(TheCamera.Cams[TheCamera.ActiveCam].LookingBehind) CamLook |= 4;\n\t// BUG?\n\tif(TheCamera.GetLookDirection() == LOOKING_BEHIND) CamLook |= 8;\n\n\tif(LastCamLook != CamLook)\n\t\tbChangeBrightnessImmediately = 3;\n\telse\n\t\tbChangeBrightnessImmediately = Max(bChangeBrightnessImmediately-1, 0);\n\tLastCamLook = CamLook;\n\n\tfor(i = 0; i < NUMCORONAS; i++)\n\t\tif(aCoronas[i].id != 0)\n\t\t\taCoronas[i].Update();\n}\n\nvoid\nCCoronas::RegisterCorona(uint32 id, uint8 red, uint8 green, uint8 blue, uint8 alpha,\n\tconst CVector &coors, float size, float drawDist, RwTexture *tex,\n\tint8 flareType, uint8 reflection, uint8 LOScheck, uint8 drawStreak, float someAngle,\n\tbool useNearDist, float nearDist)\n{\n\tint i;\n\n\tif(sq(drawDist) < (TheCamera.GetPosition() - coors).MagnitudeSqr2D())\n\t\treturn;\n\n\tif(useNearDist){\n\t\tfloat dist = (TheCamera.GetPosition() - coors).Magnitude();\n\t\tif(dist < 35.0f)\n\t\t\treturn;\n\t\tif(dist < 50.0f)\n\t\t\talpha *= (dist - 35.0f)/(50.0f - 35.0f);\n\t}\n\n\tfor(i = 0; i < NUMCORONAS; i++)\n\t\tif(aCoronas[i].id == id)\n\t\t\tbreak;\n\n\tif(i == NUMCORONAS){\n\t\t// add a new one\n\n\t\t// find empty slot\n\t\tfor(i = 0; i < NUMCORONAS; i++)\n\t\t\tif(aCoronas[i].id == 0)\n\t\t\t\tbreak;\n\t\tif(i == NUMCORONAS)\n\t\t\treturn;\t\t// no space\n\n\t\taCoronas[i].fadeAlpha = 0;\n\t\taCoronas[i].offScreen = true;\n\t\taCoronas[i].firstUpdate = true;\n\t\taCoronas[i].renderReflection = false;\n\t\taCoronas[i].lastLOScheck = 0;\n\t\taCoronas[i].sightClear = false;\n\t\taCoronas[i].hasValue[0] = false;\n\t\taCoronas[i].hasValue[1] = false;\n\t\taCoronas[i].hasValue[2] = false;\n\t\taCoronas[i].hasValue[3] = false;\n\t\taCoronas[i].hasValue[4] = false;\n\t\taCoronas[i].hasValue[5] = false;\n\n\t}else{\n\t\t// use existing one\n\n\t\tif(aCoronas[i].fadeAlpha == 0 && alpha == 0){\n\t\t\t// unregister\n\t\t\taCoronas[i].id = 0;\n\t\t\treturn;\n\t\t}\n\t}\n\n\taCoronas[i].id = id;\n\taCoronas[i].red = red;\n\taCoronas[i].green = green;\n\taCoronas[i].blue = blue;\n\taCoronas[i].alpha = alpha;\n\taCoronas[i].coors = coors;\n\taCoronas[i].size = size;\n\taCoronas[i].someAngle = someAngle;\n\taCoronas[i].registeredThisFrame = true;\n\taCoronas[i].drawDist = drawDist;\n\taCoronas[i].texture = tex;\n\taCoronas[i].flareType = flareType;\n\taCoronas[i].reflection = reflection;\n\taCoronas[i].LOScheck = LOScheck;\n\taCoronas[i].drawStreak = drawStreak;\n\taCoronas[i].useNearDist = useNearDist;\n\taCoronas[i].nearDist = nearDist;\n}\n\nvoid\nCCoronas::RegisterCorona(uint32 id, uint8 red, uint8 green, uint8 blue, uint8 alpha,\n\tconst CVector &coors, float size, float drawDist, uint8 type,\n\tint8 flareType, uint8 reflection, uint8 LOScheck, uint8 drawStreak, float someAngle,\n\tbool useNearDist, float nearDist)\n{\n\tRegisterCorona(id, red, green, blue, alpha, coors, size, drawDist,\n\t\tgpCoronaTexture[type], flareType, reflection, LOScheck, drawStreak, someAngle,\n\t\tuseNearDist, nearDist);\n}\n\nvoid\nCCoronas::UpdateCoronaCoors(uint32 id, const CVector &coors, float drawDist, float someAngle)\n{\n\tint i;\n\n\tif(sq(drawDist) < (TheCamera.GetPosition() - coors).MagnitudeSqr2D())\n\t\treturn;\n\n\tfor(i = 0; i < NUMCORONAS; i++)\n\t\tif(aCoronas[i].id == id)\n\t\t\tbreak;\n\n\tif(i == NUMCORONAS)\n\t\treturn;\n\n\tif(aCoronas[i].fadeAlpha == 0)\n\t\taCoronas[i].id = 0;\t// faded out, remove\n\telse{\n\t\taCoronas[i].coors = coors;\n\t\taCoronas[i].someAngle = someAngle;\n\t}\n}\n\nstatic RwIm2DVertex vertexbufferX[2];\n\nvoid\nCCoronas::Render(void)\n{\n\tint i, j;\n\tint screenw, screenh;\n\n\tPUSH_RENDERGROUP(\"CCoronas::Render\");\n\n\tscreenw = RwRasterGetWidth(RwCameraGetRaster(Scene.camera));\n\tscreenh = RwRasterGetHeight(RwCameraGetRaster(Scene.camera));\n\n\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);\n\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);\n\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE);\n\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE);\n\n\tfor(i = 0; i < NUMCORONAS; i++){\n\t\tfor(j = 5; j > 0; j--){\n\t\t\taCoronas[i].prevX[j] = aCoronas[i].prevX[j-1];\n\t\t\taCoronas[i].prevY[j] = aCoronas[i].prevY[j-1];\n\t\t\taCoronas[i].prevRed[j] = aCoronas[i].prevRed[j-1];\n\t\t\taCoronas[i].prevGreen[j] = aCoronas[i].prevGreen[j-1];\n\t\t\taCoronas[i].prevBlue[j] = aCoronas[i].prevBlue[j-1];\n\t\t\taCoronas[i].hasValue[j] = aCoronas[i].hasValue[j-1];\n\t\t}\n\t\taCoronas[i].hasValue[0] = false;\n\n\t\tif(aCoronas[i].id == 0 ||\n\t\t   aCoronas[i].fadeAlpha == 0 && aCoronas[i].alpha == 0)\n\t\t\tcontinue;\n\n\t\tCVector spriteCoors;\n\t\tfloat spritew, spriteh;\n\t\tif(!CSprite::CalcScreenCoors(aCoronas[i].coors, &spriteCoors, &spritew, &spriteh, true)){\n\t\t\taCoronas[i].offScreen = true;\n\t\t\taCoronas[i].sightClear = false;\n\t\t}else{\n\t\t\taCoronas[i].offScreen = false;\n\n\t\t\tif(spriteCoors.x < 0.0f || spriteCoors.y < 0.0f ||\n\t\t\t   spriteCoors.x > screenw || spriteCoors.y > screenh){\n\t\t\t\taCoronas[i].offScreen = true;\n\t\t\t\taCoronas[i].sightClear = false;\n\t\t\t}else{\n\t\t\t\tif(CTimer::GetTimeInMilliseconds() > aCoronas[i].lastLOScheck + 2000){\n\t\t\t\t\taCoronas[i].lastLOScheck = CTimer::GetTimeInMilliseconds();\n\t\t\t\t\taCoronas[i].sightClear = CWorld::GetIsLineOfSightClear(\n\t\t\t\t\t\taCoronas[i].coors, TheCamera.Cams[TheCamera.ActiveCam].Source,\n\t\t\t\t\t\ttrue, true, false, false, false, true, false);\n\t\t\t\t}\n\t\t\t\n\t\t\t\t// add new streak point\n\t\t\t\tif(aCoronas[i].sightClear){\n\t\t\t\t\taCoronas[i].prevX[0] = spriteCoors.x;\n\t\t\t\t\taCoronas[i].prevY[0] = spriteCoors.y;\n\t\t\t\t\taCoronas[i].prevRed[0] = aCoronas[i].red;\n\t\t\t\t\taCoronas[i].prevGreen[0] = aCoronas[i].green;\n\t\t\t\t\taCoronas[i].prevBlue[0] = aCoronas[i].blue;\n\t\t\t\t\taCoronas[i].hasValue[0] = true;\n\t\t\t\t}\n\t\t\t\n\t\t\t\t// if distance too big, break streak\n\t\t\t\tif(aCoronas[i].hasValue[1]){\n\t\t\t\t\tif(Abs(aCoronas[i].prevX[0] - aCoronas[i].prevX[1]) > 50.0f ||\n\t\t\t\t\t   Abs(aCoronas[i].prevY[0] - aCoronas[i].prevY[1]) > 50.0f)\n\t\t\t\t\t\taCoronas[i].hasValue[0] = false;\n\t\t\t\t}\n\t\t\t}\n\n\n\t\t\tif(aCoronas[i].fadeAlpha && spriteCoors.z < aCoronas[i].drawDist){\n\t\t\t\tfloat recipz = 1.0f/spriteCoors.z;\n\t\t\t\tfloat fadeDistance = aCoronas[i].drawDist / 2.0f;\n\t\t\t\tfloat distanceFade = spriteCoors.z < fadeDistance ? 1.0f : 1.0f - (spriteCoors.z - fadeDistance)/fadeDistance;\n\t\t\t\tint totalFade = aCoronas[i].fadeAlpha * distanceFade;\n\n\t\t\t\tif(aCoronas[i].LOScheck)\n\t\t\t\t\tRwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE);\n\t\t\t\telse\n\t\t\t\t\tRwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);\n\n\t\t\t\t// render corona itself\n\t\t\t\tif(aCoronas[i].texture){\n\t\t\t\t\tfloat fogscale = CWeather::Foggyness*Min(spriteCoors.z, 40.0f)/40.0f + 1.0f;\n\t\t\t\t\tif(CCoronas::aCoronas[i].id == SUN_CORE)\n\t\t\t\t\t\tspriteCoors.z = 0.95f * RwCameraGetFarClipPlane(Scene.camera);\n\t\t\t\t\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(aCoronas[i].texture));\n\t\t\t\t\tspriteCoors.z -= aCoronas[i].nearDist;\n\n\t\t\t\t\tif(aCoronas[i].texture == gpCoronaTexture[8]){\n\t\t\t\t\t\t// what's this?\n\t\t\t\t\t\tfloat f = 1.0f - aCoronas[i].someAngle*2.0f/PI;\n\t\t\t\t\t\tfloat wscale = 6.0f*sq(sq(sq(f))) + 0.5f;\n\t\t\t\t\t\tfloat hscale = 0.35f - (wscale - 0.5f) * 0.06f;\n\t\t\t\t\t\thscale = Max(hscale, 0.15f);\n\n\t\t\t\t\t\tCSprite::RenderOneXLUSprite(spriteCoors.x, spriteCoors.y, spriteCoors.z,\n\t\t\t\t\t\t\tspritew * aCoronas[i].size * wscale,\n\t\t\t\t\t\t\tspriteh * aCoronas[i].size * fogscale * hscale,\n\t\t\t\t\t\t\tCCoronas::aCoronas[i].red / fogscale,\n\t\t\t\t\t\t\tCCoronas::aCoronas[i].green / fogscale,\n\t\t\t\t\t\t\tCCoronas::aCoronas[i].blue / fogscale,\n\t\t\t\t\t\t\ttotalFade,\n\t\t\t\t\t\t\trecipz,\n\t\t\t\t\t\t\t255);\n\t\t\t\t\t}else{\n\t\t\t\t\t\tCSprite::RenderOneXLUSprite_Rotate_Aspect(\n\t\t\t\t\t\t\tspriteCoors.x, spriteCoors.y, spriteCoors.z,\n\t\t\t\t\t\t\tspritew * aCoronas[i].size * fogscale,\n\t\t\t\t\t\t\tspriteh * aCoronas[i].size * fogscale,\n\t\t\t\t\t\t\tCCoronas::aCoronas[i].red / fogscale,\n\t\t\t\t\t\t\tCCoronas::aCoronas[i].green / fogscale,\n\t\t\t\t\t\t\tCCoronas::aCoronas[i].blue / fogscale,\n\t\t\t\t\t\t\ttotalFade,\n\t\t\t\t\t\t\trecipz,\n\t\t\t\t\t\t\t20.0f * recipz,\n\t\t\t\t\t\t\t255);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// render flares\n\t\t\t\tif(aCoronas[i].flareType != FLARE_NONE){\n\t\t\t\t\tFlareDef *flare;\n\n\t\t\t\t\tswitch(aCoronas[i].flareType){\n\t\t\t\t\tcase FLARE_SUN: flare = SunFlareDef; break;\n\t\t\t\t\tcase FLARE_HEADLIGHTS: flare = HeadLightsFlareDef; break;\n\t\t\t\t\tdefault: assert(0);\n\t\t\t\t\t}\n\n\t\t\t\t\tfor(; flare->texture; flare++){\n\t\t\t\t\t\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpCoronaTexture[flare->texture + 4]));\n\t\t\t\t\t\tCSprite::RenderOneXLUSprite(\n\t\t\t\t\t\t\t(spriteCoors.x - (screenw/2)) * flare->position + (screenw/2),\n\t\t\t\t\t\t\t(spriteCoors.y - (screenh/2)) * flare->position + (screenh/2),\n\t\t\t\t\t\t\tspriteCoors.z,\n\t\t\t\t\t\t\t4.0f*flare->size * spritew/spriteh,\n\t\t\t\t\t\t\t4.0f*flare->size,\n\t\t\t\t\t\t\t(flare->red * aCoronas[i].red)>>8,\n\t\t\t\t\t\t\t(flare->green * aCoronas[i].green)>>8,\n\t\t\t\t\t\t\t(flare->blue * aCoronas[i].blue)>>8,\n\t\t\t\t\t\t\t(totalFade * flare->alpha)>>8,\n\t\t\t\t\t\t\trecipz, 255);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);\n\tRwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE);\n\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);\n\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE);\n\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE);\n\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil);\n\n\t// streaks\n\tfor(i = 0; i < NUMCORONAS; i++){\n\t\tif(aCoronas[i].id == 0 || !aCoronas[i].drawStreak)\n\t\t\tcontinue;\n\n\t\tfor(j = 0; j < 5; j++){\n\t\t\tif(!aCoronas[i].hasValue[j] || !aCoronas[i].hasValue[j+1])\n\t\t\t\tcontinue;\n\n\t\t\tint alpha1 = (float)(6 - j) / 6 * 128;\n\t\t\tint alpha2 = (float)(6 - (j+1)) / 6 * 128;\n\n\t\t\tRwIm2DVertexSetScreenX(&vertexbufferX[0], aCoronas[i].prevX[j]);\n\t\t\tRwIm2DVertexSetScreenY(&vertexbufferX[0], aCoronas[i].prevY[j]);\n\t\t\tRwIm2DVertexSetIntRGBA(&vertexbufferX[0], aCoronas[i].prevRed[j] * alpha1 / 256, aCoronas[i].prevGreen[j] * alpha1 / 256, aCoronas[i].prevBlue[j] * alpha1 / 256, 255);\n\t\t\tRwIm2DVertexSetScreenX(&vertexbufferX[1], aCoronas[i].prevX[j+1]);\n\t\t\tRwIm2DVertexSetScreenY(&vertexbufferX[1], aCoronas[i].prevY[j+1]);\n\t\t\tRwIm2DVertexSetIntRGBA(&vertexbufferX[1], aCoronas[i].prevRed[j+1] * alpha2 / 256, aCoronas[i].prevGreen[j+1] * alpha2 / 256, aCoronas[i].prevBlue[j+1] * alpha2 / 256, 255);\n\n#ifdef FIX_BUGS\n\t\t\tRwIm2DVertexSetScreenZ(&vertexbufferX[0], RwIm2DGetNearScreenZ());\n\t\t\tRwIm2DVertexSetCameraZ(&vertexbufferX[0], RwCameraGetNearClipPlane(Scene.camera));\n\t\t\tRwIm2DVertexSetRecipCameraZ(&vertexbufferX[0], 1.0f/RwCameraGetNearClipPlane(Scene.camera));\n\t\t\tRwIm2DVertexSetScreenZ(&vertexbufferX[1], RwIm2DGetNearScreenZ());\n\t\t\tRwIm2DVertexSetCameraZ(&vertexbufferX[1], RwCameraGetNearClipPlane(Scene.camera));\n\t\t\tRwIm2DVertexSetRecipCameraZ(&vertexbufferX[1], 1.0f/RwCameraGetNearClipPlane(Scene.camera));\n#endif\n\n\t\t\tRwIm2DRenderLine(vertexbufferX, 2, 0, 1);\n\t\t}\n\t}\n\n\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);\n\tRwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);\n\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);\n\n\tPOP_RENDERGROUP();\n}\n\nvoid\nCCoronas::RenderReflections(void)\n{\n\tint i;\n\tCColPoint point;\n\tCEntity *entity;\n\n\tif(CWeather::WetRoads > 0.0f){\n\t\tPUSH_RENDERGROUP(\"CCoronas::RenderReflections\");\n\n\t\tCSprite::InitSpriteBuffer();\n\n\t\tRwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE);\n\t\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);\n\t\tRwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE);\n\t\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);\n\t\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE);\n\t\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE);\n\t\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpCoronaTexture[3]));\n\n\t\tfor(i = 0; i < NUMCORONAS; i++){\n\t\t\tif(aCoronas[i].id == 0 ||\n\t\t\t   aCoronas[i].fadeAlpha == 0 && aCoronas[i].alpha == 0 ||\n\t\t\t   aCoronas[i].reflection == 0)\n\t\t\t\tcontinue;\n\n\t\t\t// check if we want a reflection on this corona\n\t\t\tif(aCoronas[i].renderReflection){\n\t\t\t\tif(((CTimer::GetFrameCounter() + i) & 0xF) == 0 &&\n\t\t\t\t   CWorld::ProcessVerticalLine(aCoronas[i].coors, -1000.0f, point, entity, true, false, false, false, true, false, nil))\n\t\t\t\t\taCoronas[i].heightAboveRoad = aCoronas[i].coors.z - point.point.z;\n\t\t\t}else{\n\t\t\t\tif(CWorld::ProcessVerticalLine(aCoronas[i].coors, -1000.0f, point, entity, true, false, false, false, true, false, nil)){\n\t\t\t\t\taCoronas[i].heightAboveRoad = aCoronas[i].coors.z - point.point.z;\n\t\t\t\t\taCoronas[i].renderReflection = true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Don't draw if reflection is too high\n\t\t\tif(aCoronas[i].renderReflection && aCoronas[i].heightAboveRoad < 20.0f){\n\t\t\t\t// don't draw if camera is below road\n\t\t\t\tif(CCoronas::aCoronas[i].coors.z - aCoronas[i].heightAboveRoad > TheCamera.GetPosition().z)\n\t\t\t\t\tcontinue;\n\n\t\t\t\tCVector coors = aCoronas[i].coors;\n\t\t\t\tcoors.z -= 2.0f*aCoronas[i].heightAboveRoad;\n\n\t\t\t\tCVector spriteCoors;\n\t\t\t\tfloat spritew, spriteh;\n\t\t\t\tif(CSprite::CalcScreenCoors(coors, &spriteCoors, &spritew, &spriteh, true)) {\n\t\t\t\t\tfloat drawDist = 0.75f * aCoronas[i].drawDist;\n\t\t\t\t\tdrawDist = Min(drawDist, 55.0f);\n\t\t\t\t\tif(spriteCoors.z < drawDist){\n\t\t\t\t\t\tfloat fadeDistance = drawDist / 2.0f;\n\t\t\t\t\t\tfloat distanceFade = spriteCoors.z < fadeDistance ? 1.0f : 1.0f - (spriteCoors.z - fadeDistance)/fadeDistance;\n\t\t\t\t\t\tdistanceFade = clamp(distanceFade, 0.0f, 1.0f);\n\t\t\t\t\t\tfloat recipz = 1.0f/RwCameraGetNearClipPlane(Scene.camera);\n\t\t\t\t\t\tfloat heightFade = (20.0f - aCoronas[i].heightAboveRoad)/20.0f;\n\t\t\t\t\t\tint intensity = distanceFade*heightFade * 230.0 * CWeather::WetRoads;\n\n\t\t\t\t\t\tCSprite::RenderBufferedOneXLUSprite(\n#ifdef FIX_BUGS\n\t\t\t\t\t\t\tspriteCoors.x, spriteCoors.y, spriteCoors.z,\n#else\n\t\t\t\t\t\t\tspriteCoors.x, spriteCoors.y, RwIm2DGetNearScreenZ(),\n#endif\n\t\t\t\t\t\t\tspritew * aCoronas[i].size * 0.75f,\n\t\t\t\t\t\t\tspriteh * aCoronas[i].size * 2.0f,\n\t\t\t\t\t\t\t(intensity * CCoronas::aCoronas[i].red)>>8,\n\t\t\t\t\t\t\t(intensity * CCoronas::aCoronas[i].green)>>8,\n\t\t\t\t\t\t\t(intensity * CCoronas::aCoronas[i].blue)>>8,\n\t\t\t\t\t\t\t255,\n\t\t\t\t\t\t\trecipz,\n\t\t\t\t\t\t\t255);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tCSprite::FlushSpriteBuffer();\n\n\t\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);\n\t\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);\n\t\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);\n\t\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);\n\t\tRwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);\n\n\t\tPOP_RENDERGROUP();\n\t}else{\n\t\tfor(i = 0; i < NUMCORONAS; i++)\n\t\t\taCoronas[i].renderReflection = false;\n\t}\n}\n\nvoid\nCCoronas::RenderSunReflection(void)\n{\n\tfloat sunZDir = CTimeCycle::GetSunDirection().z;\n\tif(sunZDir > -0.05f){\n\t\tfloat intensity = (0.3f - Abs(sunZDir - 0.25f))/0.3f *\n\t\t\t(1.0f - CWeather::CloudCoverage) *\n\t\t\t(1.0f - CWeather::Foggyness) *\n\t\t\t(1.0f - CWeather::Wind);\n\t\tif(intensity > 0.0f){\n\t\t\tint r = (CTimeCycle::GetSunCoreRed() + CTimeCycle::GetSunCoronaRed())*intensity*0.25f;\n\t\t\tint g = (CTimeCycle::GetSunCoreGreen() + CTimeCycle::GetSunCoronaGreen())*intensity*0.25f;\n\t\t\tint b = (CTimeCycle::GetSunCoreBlue() + CTimeCycle::GetSunCoronaBlue())*intensity*0.25f;\n\n\t\t\tCVector sunPos = 40.0f*CTimeCycle::GetSunDirection() + TheCamera.GetPosition();\n\t\t\tsunPos.z = 0.5f*CWeather::Wind + 6.1f;\n\t\t\tCVector sunDir = CTimeCycle::GetSunDirection();\n\t\t\tsunDir.z = 0.0;\n\t\t\tsunDir.Normalise();\n\n\t\t\tTempBufferIndicesStored = 6;\n\t\t\tTempBufferRenderIndexList[0] = 2;\n\t\t\tTempBufferRenderIndexList[1] = 1;\n\t\t\tTempBufferRenderIndexList[2] = 0;\n\t\t\tTempBufferRenderIndexList[3] = 2;\n\t\t\tTempBufferRenderIndexList[4] = 3;\n\t\t\tTempBufferRenderIndexList[5] = 1;\n\n\t\t\t// 60 unit square in sun direction\n\t\t\tTempBufferVerticesStored = 4;\n\t\t\tRwIm3DVertexSetRGBA(&TempBufferRenderVertices[0], r, g, b, 255);\n\t\t\tRwIm3DVertexSetPos(&TempBufferRenderVertices[0],\n\t\t\t\tsunPos.x + 30.0f*sunDir.y,\n\t\t\t\tsunPos.y - 30.0f*sunDir.x,\n\t\t\t\tsunPos.z);\n\t\t\tRwIm3DVertexSetRGBA(&TempBufferRenderVertices[1], r, g, b, 255);\n\t\t\tRwIm3DVertexSetPos(&TempBufferRenderVertices[1],\n\t\t\t\tsunPos.x - 30.0f*sunDir.y,\n\t\t\t\tsunPos.y + 30.0f*sunDir.x,\n\t\t\t\tsunPos.z);\n\t\t\tRwIm3DVertexSetRGBA(&TempBufferRenderVertices[2], r, g, b, 255);\n\t\t\tRwIm3DVertexSetPos(&TempBufferRenderVertices[2],\n\t\t\t\tsunPos.x + 60.0f*sunDir.x + 30.0f*sunDir.y,\n\t\t\t\tsunPos.y + 60.0f*sunDir.y - 30.0f*sunDir.x,\n\t\t\t\tsunPos.z);\n\t\t\tRwIm3DVertexSetRGBA(&TempBufferRenderVertices[3], r, g, b, 255);\n\t\t\tRwIm3DVertexSetPos(&TempBufferRenderVertices[3],\n\t\t\t\tsunPos.x + 60.0f*sunDir.x - 30.0f*sunDir.y,\n\t\t\t\tsunPos.y + 60.0f*sunDir.y + 30.0f*sunDir.x,\n\t\t\t\tsunPos.z);\n\n\t\t\tRwIm3DVertexSetU(&TempBufferRenderVertices[0], 0.0f);\n\t\t\tRwIm3DVertexSetV(&TempBufferRenderVertices[0], 1.0f);\n\t\t\tRwIm3DVertexSetU(&TempBufferRenderVertices[1], 1.0f);\n\t\t\tRwIm3DVertexSetV(&TempBufferRenderVertices[1], 1.0f);\n\t\t\tRwIm3DVertexSetU(&TempBufferRenderVertices[2], 0.0f);\n\t\t\tRwIm3DVertexSetV(&TempBufferRenderVertices[2], 0.5f);\n\t\t\tRwIm3DVertexSetU(&TempBufferRenderVertices[3], 1.0f);\n\t\t\tRwIm3DVertexSetV(&TempBufferRenderVertices[3], 0.5f);\n\n\t\t\tint timeInc = 0;\n\t\t\tint sideInc = 0;\n\t\t\tint fwdInc = 0;\n\t\t\tfor(int i = 0; i < 20; i++){\n\t\t\t\tTempBufferRenderIndexList[TempBufferIndicesStored + 0] = TempBufferVerticesStored;\n\t\t\t\tTempBufferRenderIndexList[TempBufferIndicesStored + 1] = TempBufferVerticesStored-1;\n\t\t\t\tTempBufferRenderIndexList[TempBufferIndicesStored + 2] = TempBufferVerticesStored-2;\n\t\t\t\tTempBufferRenderIndexList[TempBufferIndicesStored + 3] = TempBufferVerticesStored;\n\t\t\t\tTempBufferRenderIndexList[TempBufferIndicesStored + 4] = TempBufferVerticesStored+1;\n\t\t\t\tTempBufferRenderIndexList[TempBufferIndicesStored + 5] = TempBufferVerticesStored-1;\n\t\t\t\tTempBufferIndicesStored += 6;\n\n\t\t\t\t// What a weird way to do it...\n\t\t\t\tfloat fwdLen = fwdInc/20 + 60;\n\t\t\t\tfloat sideLen = sideInc/20 + 30;\n\t\t\t\tsideLen += 10.0f*Sin((float)(CTimer::GetTimeInMilliseconds()+timeInc & 0x7FF)/0x800*TWOPI);\n\t\t\t\ttimeInc += 900;\n\t\t\t\tsideInc += 970;\n\t\t\t\tfwdInc += 1440;\n\n\t\t\t\tRwIm3DVertexSetRGBA(&TempBufferRenderVertices[TempBufferVerticesStored+0], r, g, b, 255);\n\t\t\t\tRwIm3DVertexSetPos(&TempBufferRenderVertices[TempBufferVerticesStored+0],\n\t\t\t\t\tsunPos.x + fwdLen*sunDir.x + sideLen*sunDir.y,\n\t\t\t\t\tsunPos.y + fwdLen*sunDir.y - sideLen*sunDir.x,\n\t\t\t\t\tsunPos.z);\n\n\t\t\t\tRwIm3DVertexSetRGBA(&TempBufferRenderVertices[TempBufferVerticesStored+1], r, g, b, 255);\n\t\t\t\tRwIm3DVertexSetPos(&TempBufferRenderVertices[TempBufferVerticesStored+1],\n\t\t\t\t\tsunPos.x + fwdLen*sunDir.x - sideLen*sunDir.y,\n\t\t\t\t\tsunPos.y + fwdLen*sunDir.y + sideLen*sunDir.x,\n\t\t\t\t\tsunPos.z);\n\n\t\t\t\tRwIm3DVertexSetU(&TempBufferRenderVertices[TempBufferVerticesStored+0], 0.0f);\n\t\t\t\tRwIm3DVertexSetV(&TempBufferRenderVertices[TempBufferVerticesStored+0], 0.5f);\n\t\t\t\tRwIm3DVertexSetU(&TempBufferRenderVertices[TempBufferVerticesStored+1], 1.0f);\n\t\t\t\tRwIm3DVertexSetV(&TempBufferRenderVertices[TempBufferVerticesStored+1], 0.5f);\n\t\t\t\tTempBufferVerticesStored += 2;\n\t\t\t}\n\n\n\t\t\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);\n\t\t\tRwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);\n\t\t\tRwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE);\n\t\t\tRwRenderStateSet(rwRENDERSTATEFOGTYPE, (void*)rwFOGTYPELINEAR);\n\t\t\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE);\n\t\t\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE);\n\t\t\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);\n\t\t\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpCoronaTexture[4]));\n\t\t\tif(RwIm3DTransform(TempBufferRenderVertices, TempBufferVerticesStored, nil, rwIM3D_VERTEXUV)){\n\t\t\t\tRwIm3DRenderIndexedPrimitive(rwPRIMTYPETRILIST, TempBufferRenderIndexList, TempBufferIndicesStored);\n\t\t\t\tRwIm3DEnd();\n\t\t\t}\n\t\t\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);\n\t\t\tRwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);\n\t\t\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);\n\t\t\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);\n\t\t\tRwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE);\n\t\t\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);\n\t\t\tTempBufferVerticesStored = 0;\n\t\t\tTempBufferIndicesStored = 0;\n\t\t}\n\t}\n}\n\nvoid \nCCoronas::DoSunAndMoon(void)\n{\n\t// yeah, moon is done somewhere else....\n\n\tCVector sunCoors = CTimeCycle::GetSunDirection();\n\tsunCoors *= 150.0f;\n\tsunCoors += TheCamera.GetPosition();\n\n\tif(CTimeCycle::GetSunDirection().z > -0.2f){\n\t\tfloat size = ((CGeneral::GetRandomNumber()&0xFF) * 0.005f + 10.0f) * CTimeCycle::GetSunSize();\n\t\tRegisterCorona(SUN_CORE,\n\t\t\tCTimeCycle::GetSunCoreRed(), CTimeCycle::GetSunCoreGreen(), CTimeCycle::GetSunCoreBlue(),\n\t\t\t255, sunCoors, size,\n\t\t\t999999.88f, TYPE_STAR, FLARE_NONE, REFLECTION_OFF, LOSCHECK_OFF, STREAK_OFF, 0.0f);\n\n\t\tif(CTimeCycle::GetSunDirection().z > 0.0f && !CGame::IsInInterior())\n\t\t\tRegisterCorona(SUN_CORONA,\n\t\t\t\tCTimeCycle::GetSunCoronaRed(), CTimeCycle::GetSunCoronaGreen(), CTimeCycle::GetSunCoronaBlue(),\n\t\t\t\t255, sunCoors, 25.0f * CTimeCycle::GetSunSize(),\n\t\t\t\t999999.88f, TYPE_STAR, FLARE_SUN, REFLECTION_OFF, LOSCHECK_ON, STREAK_OFF, 0.0f);\n\t}\n\n\tCVector spriteCoors;\n\tfloat spritew, spriteh;\n\tif(CSprite::CalcScreenCoors(sunCoors, &spriteCoors, &spritew, &spriteh, true)) {\n\t\tSunScreenX = spriteCoors.x;\n\t\tSunScreenY = spriteCoors.y;\n\t}else{\n\t\tSunScreenX = 1000000.0f;\n\t\tSunScreenY = 1000000.0f;\n\t}\n}\n\nvoid\nCRegisteredCorona::Update(void)\n{\n\tif(!registeredThisFrame)\n\t\talpha = 0;\n\n\tif(LOScheck &&\n\t   (CCoronas::SunBlockedByClouds && id == CCoronas::SUN_CORONA ||\n\t    !CWorld::GetIsLineOfSightClear(coors, TheCamera.GetPosition(), true, false, false, false, false, false))){\n\t\t// Corona is blocked, fade out\n\t\tfadeAlpha = Max(fadeAlpha - 15.0f*CTimer::GetTimeStep(), 0.0f);\n\t}else if(offScreen){\n\t\t// Same when off screen\n\t\tfadeAlpha = Max(fadeAlpha - 15.0f*CTimer::GetTimeStep(), 0.0f);\n\t}else{\n\t\t// Visible\n\t\tif(alpha > fadeAlpha){\n\t\t\t// fade in\n\t\t\tfadeAlpha = Min(fadeAlpha + 15.0f*CTimer::GetTimeStep(), alpha);\n\t\t\tif(CCoronas::bChangeBrightnessImmediately)\n\t\t\t\tfadeAlpha = alpha;\n\t\t}else if(alpha < fadeAlpha){\n\t\t\t// too visible, decrease alpha but not below alpha\n\t\t\tfadeAlpha = Max(fadeAlpha - 15.0f*CTimer::GetTimeStep(), alpha);\n\t\t}\n\n\t\t// darken scene when the sun is visible\n\t\tif(id == CCoronas::SUN_CORONA)\n\t\t\tCCoronas::LightsMult = Max(CCoronas::LightsMult - CTimer::GetTimeStep()*0.06f, 0.6f);\n\t}\n\n\t// remove if invisible\n\tif(fadeAlpha == 0 && !firstUpdate)\n\t\tid = 0;\n\tfirstUpdate = false;\n\tregisteredThisFrame = false;\n}\n\nvoid\nCEntity::ProcessLightsForEntity(void)\n{\n\tint i, n;\n\tC2dEffect *effect;\n\tCVector pos;\n\tbool lightOn, lightFlickering;\n\tuint32 flashTimer1, flashTimer2, flashTimer3;\n\n\tif(bRenderDamaged || !bIsVisible || GetUp().z < 0.96f)\n\t\treturn;\n\n\tflashTimer1 = 0;\n\tflashTimer2 = 0;\n\tflashTimer3 = 0;\n\n\tn = CModelInfo::GetModelInfo(GetModelIndex())->GetNum2dEffects();\n\tfor(i = 0; i < n; i++, flashTimer1 += 0x80, flashTimer2 += 0x100, flashTimer3 += 0x200){\n\t\teffect = CModelInfo::GetModelInfo(GetModelIndex())->Get2dEffect(i);\n\n\t\tswitch(effect->type){\n\t\tcase EFFECT_LIGHT:\n\t\t\tpos = GetMatrix() * effect->pos;\n\n\t\t\tlightOn = false;\n\t\t\tlightFlickering = false;\n\t\t\tswitch(effect->light.lightType){\n\t\t\tcase LIGHT_ON:\n\t\t\t\tlightOn = true;\n\t\t\t\tbreak;\n\t\t\tcase LIGHT_ON_NIGHT:\n\t\t\t\tif(CClock::GetHours() > 18 || CClock::GetHours() < 7)\n\t\t\t\t\tlightOn = true;\n\t\t\t\tbreak;\n\t\t\tcase LIGHT_FLICKER:\n\t\t\t\tif((CTimer::GetTimeInMilliseconds() ^ m_randomSeed) & 0x60)\n\t\t\t\t\tlightOn = true;\n\t\t\t\telse\n\t\t\t\t\tlightFlickering = true;\n\t\t\t\tif((CTimer::GetTimeInMilliseconds()>>11 ^ m_randomSeed) & 3)\n\t\t\t\t\tlightOn = true;\n\t\t\t\tbreak;\n\t\t\tcase LIGHT_FLICKER_NIGHT:\n\t\t\t\tif(CClock::GetHours() > 18 || CClock::GetHours() < 7 || CWeather::WetRoads > 0.5f){\n\t\t\t\t\tif((CTimer::GetTimeInMilliseconds() ^ m_randomSeed) & 0x60)\n\t\t\t\t\t\tlightOn = true;\n\t\t\t\t\telse\n\t\t\t\t\t\tlightFlickering = true;\n\t\t\t\t\tif((CTimer::GetTimeInMilliseconds()>>11 ^ m_randomSeed) & 3)\n\t\t\t\t\t\tlightOn = true;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase LIGHT_FLASH1:\n\t\t\t\tif((CTimer::GetTimeInMilliseconds() + flashTimer1) & 0x200)\n\t\t\t\t\tlightOn = true;\n\t\t\t\tbreak;\n\t\t\tcase LIGHT_FLASH1_NIGHT:\n\t\t\t\tif(CClock::GetHours() > 18 || CClock::GetHours() < 7)\n\t\t\t\t\tif((CTimer::GetTimeInMilliseconds() + flashTimer1) & 0x200)\n\t\t\t\t\t\tlightOn = true;\n\t\t\t\tbreak;\n\t\t\tcase LIGHT_FLASH2:\n\t\t\t\tif((CTimer::GetTimeInMilliseconds() + flashTimer2) & 0x400)\n\t\t\t\t\tlightOn = true;\n\t\t\t\tbreak;\n\t\t\tcase LIGHT_FLASH2_NIGHT:\n\t\t\t\tif(CClock::GetHours() > 18 || CClock::GetHours() < 7)\n\t\t\t\t\tif((CTimer::GetTimeInMilliseconds() + flashTimer2) & 0x400)\n\t\t\t\t\t\tlightOn = true;\n\t\t\t\tbreak;\n\t\t\tcase LIGHT_FLASH3:\n\t\t\t\tif((CTimer::GetTimeInMilliseconds() + flashTimer3) & 0x800)\n\t\t\t\t\tlightOn = true;\n\t\t\t\tbreak;\n\t\t\tcase LIGHT_FLASH3_NIGHT:\n\t\t\t\tif(CClock::GetHours() > 18 || CClock::GetHours() < 7)\n\t\t\t\t\tif((CTimer::GetTimeInMilliseconds() + flashTimer3) & 0x800)\n\t\t\t\t\t\tlightOn = true;\n\t\t\t\tbreak;\n\t\t\tcase LIGHT_RANDOM_FLICKER:\n\t\t\t\tif(m_randomSeed > 16)\n\t\t\t\t\tlightOn = true;\n\t\t\t\telse{\n\t\t\t\t\tif((CTimer::GetTimeInMilliseconds() ^ m_randomSeed*8) & 0x60)\n\t\t\t\t\t\tlightOn = true;\n\t\t\t\t\telse\n\t\t\t\t\t\tlightFlickering = true;\n\t\t\t\t\tif((CTimer::GetTimeInMilliseconds()>>11 ^ m_randomSeed*8) & 3)\n\t\t\t\t\t\tlightOn = true;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase LIGHT_RANDOM_FLICKER_NIGHT:\n\t\t\t\tif(CClock::GetHours() > 18 || CClock::GetHours() < 7){\n\t\t\t\t\tif(m_randomSeed > 16)\n\t\t\t\t\t\tlightOn = true;\n\t\t\t\t\telse{\n\t\t\t\t\t\tif((CTimer::GetTimeInMilliseconds() ^ m_randomSeed*8) & 0x60)\n\t\t\t\t\t\t\tlightOn = true;\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tlightFlickering = true;\n\t\t\t\t\t\tif((CTimer::GetTimeInMilliseconds()>>11 ^ m_randomSeed*8) & 3)\n\t\t\t\t\t\t\tlightOn = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase LIGHT_BRIDGE_FLASH1:\n\t\t\t\tif(CBridge::ShouldLightsBeFlashing() && CTimer::GetTimeInMilliseconds() & 0x200)\n\t\t\t\t\tlightOn = true;\n\t\t\t\tbreak;\n\t\t\tcase LIGHT_BRIDGE_FLASH2:\n\t\t\t\tif(CBridge::ShouldLightsBeFlashing() && (CTimer::GetTimeInMilliseconds() & 0x1FF) < 60)\n\t\t\t\t\tlightOn = true;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tif(effect->light.flags & LIGHTFLAG_HIDE_OBJECT){\n\t\t\t\tif(lightOn)\n\t\t\t\t\tbDoNotRender = false;\n\t\t\t\telse\n\t\t\t\t\tbDoNotRender = true;\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Corona\n\t\t\tif(lightOn)\n\t\t\t\tCCoronas::RegisterCorona((uintptr)this + i,\n\t\t\t\t\teffect->col.r, effect->col.g, effect->col.b, 255,\n\t\t\t\t\tpos, effect->light.size, effect->light.dist,\n\t\t\t\t\teffect->light.corona, effect->light.flareType, effect->light.roadReflection,\n\t\t\t\t\teffect->light.flags&LIGHTFLAG_LOSCHECK, CCoronas::STREAK_OFF, 0.0f,\n\t\t\t\t\t!!(effect->light.flags&LIGHTFLAG_LONG_DIST));\n\t\t\telse if(lightFlickering)\n\t\t\t\tCCoronas::RegisterCorona((uintptr)this + i,\n\t\t\t\t\t0, 0, 0, 255,\n\t\t\t\t\tpos, effect->light.size, effect->light.dist,\n\t\t\t\t\teffect->light.corona, effect->light.flareType, effect->light.roadReflection,\n\t\t\t\t\teffect->light.flags&LIGHTFLAG_LOSCHECK, CCoronas::STREAK_OFF, 0.0f,\n\t\t\t\t\t!!(effect->light.flags&LIGHTFLAG_LONG_DIST));\n\n\t\t\t// Pointlight\n\t\t\tbool alreadyProcessedFog;\n\t\t\talreadyProcessedFog = false;\n\t\t\tif(effect->light.range != 0.0f && lightOn){\n\t\t\t\tif(effect->col.r == 0 && effect->col.g == 0 && effect->col.b == 0){\n\t\t\t\t\tCPointLights::AddLight(CPointLights::LIGHT_POINT,\n\t\t\t\t\t\tpos, CVector(0.0f, 0.0f, 0.0f),\n\t\t\t\t\t\teffect->light.range,\n\t\t\t\t\t\t0.0f, 0.0f, 0.0f,\n\t\t\t\t\t\tCPointLights::FOG_NONE, true);\n\t\t\t\t}else{\n\t\t\t\t\tCPointLights::AddLight(CPointLights::LIGHT_POINT,\n\t\t\t\t\t\tpos, CVector(0.0f, 0.0f, 0.0f),\n\t\t\t\t\t\teffect->light.range,\n\t\t\t\t\t\teffect->col.r*CTimeCycle::GetSpriteBrightness()/255.0f,\n\t\t\t\t\t\teffect->col.g*CTimeCycle::GetSpriteBrightness()/255.0f,\n\t\t\t\t\t\teffect->col.b*CTimeCycle::GetSpriteBrightness()/255.0f,\n\t\t\t\t\t\t(effect->light.flags & LIGHTFLAG_FOG) >> 1,\n\t\t\t\t\t\ttrue);\n\t\t\t\t\talreadyProcessedFog = true; \n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif(!alreadyProcessedFog){\n\t\t\t\tif(effect->light.flags & LIGHTFLAG_FOG_ALWAYS){\n\t\t\t\t\tCPointLights::AddLight(CPointLights::LIGHT_FOGONLY_ALWAYS,\n\t\t\t\t\t\tpos, CVector(0.0f, 0.0f, 0.0f),\n\t\t\t\t\t\t0.0f,\n\t\t\t\t\t\teffect->col.r/255.0f, effect->col.g/255.0f, effect->col.b/255.0f,\n\t\t\t\t\t\tCPointLights::FOG_ALWAYS, true);\n\t\t\t\t}else if(effect->light.flags & LIGHTFLAG_FOG_NORMAL && lightOn && effect->light.range == 0.0f){\n\t\t\t\t\tCPointLights::AddLight(CPointLights::LIGHT_FOGONLY,\n\t\t\t\t\t\tpos, CVector(0.0f, 0.0f, 0.0f),\n\t\t\t\t\t\t0.0f,\n\t\t\t\t\t\teffect->col.r/255.0f, effect->col.g/255.0f, effect->col.b/255.0f,\n\t\t\t\t\t\tCPointLights::FOG_NORMAL, true);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Light shadow\n\t\t\tif(effect->light.shadowSize != 0.0f){\n\t\t\t\tif(lightOn){\n\t\t\t\t\tCShadows::StoreStaticShadow((uintptr)this + i, SHADOWTYPE_ADDITIVE,\n\t\t\t\t\t\teffect->light.shadow, &pos,\n\t\t\t\t\t\teffect->light.shadowSize, 0.0f,\n\t\t\t\t\t\t0.0f, -effect->light.shadowSize,\n\t\t\t\t\t\t128,\n\t\t\t\t\t\teffect->col.r*CTimeCycle::GetSpriteBrightness()*effect->light.shadowIntensity/255.0f,\n\t\t\t\t\t\teffect->col.g*CTimeCycle::GetSpriteBrightness()*effect->light.shadowIntensity/255.0f,\n\t\t\t\t\t\teffect->col.b*CTimeCycle::GetSpriteBrightness()*effect->light.shadowIntensity/255.0f,\n\t\t\t\t\t\t15.0f, 1.0f, 40.0f, false, 0.0f);\n\t\t\t\t}else if(lightFlickering){\n\t\t\t\t\tCShadows::StoreStaticShadow((uintptr)this + i, SHADOWTYPE_ADDITIVE,\n\t\t\t\t\t\teffect->light.shadow, &pos,\n\t\t\t\t\t\teffect->light.shadowSize, 0.0f,\n\t\t\t\t\t\t0.0f, -effect->light.shadowSize,\n\t\t\t\t\t\t0, 0.0f, 0.0f, 0.0f,\n\t\t\t\t\t\t15.0f, 1.0f, 40.0f, false, 0.0f);\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase EFFECT_SUNGLARE:\n\t\t\tif(CWeather::SunGlare >= 0.0f){\n\t\t\t\tCVector pos = GetMatrix() * effect->pos;\n\t\t\t\tCVector glareDir = pos - GetPosition();\n\t\t\t\tglareDir.Normalise();\n\t\t\t\tCVector camDir = TheCamera.GetPosition() - pos;\n\t\t\t\tfloat dist = camDir.Magnitude();\n\t\t\t\tcamDir *= 2.0f/dist;\n\t\t\t\tglareDir += camDir;\n\t\t\t\tglareDir.Normalise();\n\t\t\t\tfloat camAngle = -DotProduct(glareDir, CTimeCycle::GetSunDirection());\n\t\t\t\tif(camAngle > 0.0f){\n\t\t\t\t\tfloat intens = Sqrt(camAngle) * CWeather::SunGlare;\n\t\t\t\t\tpos += camDir;\n\t\t\t\t\tCCoronas::RegisterCorona((uintptr)this + 33 + i,\n\t\t\t\t\t\tintens * (CTimeCycle::GetSunCoreRed() + 2*255)/3.0f,\n\t\t\t\t\t\tintens * (CTimeCycle::GetSunCoreGreen() + 2*255)/3.0f,\n\t\t\t\t\t\tintens * (CTimeCycle::GetSunCoreBlue() + 2*255)/3.0f,\n\t\t\t\t\t\t255,\n\t\t\t\t\t\tpos, 0.5f*CWeather::SunGlare*Sqrt(dist), 120.0f,\n\t\t\t\t\t\tCCoronas::TYPE_STAR, CCoronas::FLARE_NONE,\n\t\t\t\t\t\tCCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF,\n\t\t\t\t\t\tCCoronas::STREAK_OFF, 0.0f);\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t}\n}"
  },
  {
    "path": "src/render/Coronas.h",
    "content": "#pragma once\n\nextern RwTexture *gpCoronaTexture[9];\n\nstruct CRegisteredCorona\n{\n\tCVector coors;\n\tuint32 id;\n\tuint32 lastLOScheck;\n\tRwTexture *texture;\n\tfloat size;\n\tfloat someAngle;\n\tfloat drawDist;\n\tfloat nearDist;\n\tfloat heightAboveRoad;\n\tuint8 red;\n\tuint8 green;\n\tuint8 blue;\n\tuint8 alpha;\t\t// alpha when fully visible\n\tuint8 fadeAlpha;\t// actual value used for rendering, faded\n\tbool registeredThisFrame;\n\tint8 flareType;\n\tint8 reflection;\n\n\tuint8 LOScheck : 1;\n\tuint8 offScreen : 1;\n\tuint8 firstUpdate : 1;\n\tuint8 drawStreak : 1;\n\tuint8 sightClear : 1;\n\tuint8 useNearDist : 1;\n\tuint8 renderReflection : 1;\n\n\tint16 prevX[6];\n\tint16 prevY[6];\n\tuint8 prevRed[6];\n\tuint8 prevGreen[6];\n\tuint8 prevBlue[6];\n\tbool hasValue[6];\n\n\tvoid Update(void);\n};\n\nVALIDATE_SIZE(CRegisteredCorona, 0x68);\n\nclass CCoronas\n{\n\tstatic CRegisteredCorona aCoronas[NUMCORONAS];\npublic:\n\tenum {\n\t\tSUN_CORE = 1,\n\t\tSUN_CORONA\n\t};\n\tenum {\n\t\tTYPE_STAR,\n\t\tTYPE_NORMAL,\n\t\tTYPE_MOON,\n\t\tTYPE_REFLECT,\n\t\tTYPE_HEADLIGHT,\n\t\tTYPE_HEX,\n\t\tTYPE_CIRCLE,\n\t\tTYPE_RING,\n\t\tTYPE_STREAK,\n\t};\n\tenum {\n\t\tFLARE_NONE,\n\t\tFLARE_SUN,\n\t\tFLARE_HEADLIGHTS\n\t};\n\tenum {\n\t\tREFLECTION_OFF,\n\t\tREFLECTION_ON,\n\t};\n\tenum {\n\t\tLOSCHECK_OFF,\n\t\tLOSCHECK_ON,\n\t};\n\tenum {\n\t\tSTREAK_OFF,\n\t\tSTREAK_ON,\n\t};\n\n\tstatic float LightsMult;\n\tstatic float SunScreenY;\n\tstatic float SunScreenX;\n\tstatic int MoonSize;\n\tstatic bool SunBlockedByClouds;\n\tstatic int bChangeBrightnessImmediately;\n\n\tstatic void Init(void);\n\tstatic void Shutdown(void);\n\tstatic void Update(void);\n\tstatic void RegisterCorona(uint32 id, uint8 red, uint8 green, uint8 blue, uint8 alpha,\n\t\tconst CVector &coors, float size, float drawDist, RwTexture *tex,\n\t\tint8 flareType, uint8 reflection, uint8 LOScheck, uint8 drawStreak, float someAngle,\n\t\tbool useNearDist = false, float nearDist = 1.5f);\n\tstatic void RegisterCorona(uint32 id, uint8 red, uint8 green, uint8 blue, uint8 alpha,\n\t\tconst CVector &coors, float size, float drawDist, uint8 type,\n\t\tint8 flareType, uint8 reflection, uint8 LOScheck, uint8 drawStreak, float someAngle,\n\t\tbool useNearDist = false, float nearDist = 1.5f);\n\tstatic void UpdateCoronaCoors(uint32 id, const CVector &coors, float drawDist, float someAngle);\n\tstatic void Render(void);\n\tstatic void RenderReflections(void);\n\tstatic void RenderSunReflection(void);\n\tstatic void DoSunAndMoon(void);\n};\n"
  },
  {
    "path": "src/render/Credits.cpp",
    "content": "#include \"common.h\"\n\n#include \"Timer.h\"\n#include \"Font.h\"\n#include \"Frontend.h\"\n#include \"RwHelper.h\"\n#include \"Camera.h\"\n#include \"Text.h\"\n#include \"Credits.h\"\n#include \"Pad.h\"\n\nbool CCredits::bCreditsGoing;\nuint32 CCredits::CreditsStartTime;\n\nvoid\nCCredits::Init(void)\n{\n\tStop();\n}\n\nvoid\nCCredits::Start(void)\n{\n\tbCreditsGoing = true;\n\tCreditsStartTime = CTimer::GetTimeInMilliseconds();\n}\n\nvoid\nCCredits::Stop(void)\n{\n\tbCreditsGoing = false;\n}\n\nvoid\nCCredits::PrintCreditSpace(float space, uint32 &line)\n{\n\tline += space * 25.0f;\n}\n\nvoid\nCCredits::PrintCreditText(float scaleX, float scaleY, wchar *text, uint32 &lineoffset, float scrolloffset)\n{\n\tCPad::UpdatePads();\n\tif (CPad::GetPad(0)->GetCrossJustDown())\n\t\tbCreditsGoing = false;\n\telse {\n\t\tfloat start = DEFAULT_SCREEN_HEIGHT + 20.0f;\n\t\tfloat y = lineoffset + start - scrolloffset;\n\t\tif (y > 20.0f && DEFAULT_SCREEN_HEIGHT - 20.0f > y) {\n\t\t\tCFont::SetScale(SCREEN_SCALE_X(scaleX), SCREEN_SCALE_Y(scaleY));\n\t\t\tCFont::SetColor(CRGBA(0, 0, 0, 255));\n\t\t\tCFont::PrintString(SCREEN_WIDTH / 2.0f, SCREEN_SCALE_Y(y), (uint16*)text);\n\t\t\tCFont::SetColor(CRGBA(220, 220, 220, 220));\n\t\t\tCFont::PrintString(SCREEN_WIDTH / 2.0f - SCREEN_SCALE_X(1.0f), SCREEN_SCALE_Y(y - 1.0f), (uint16*)text);\n\t\t}\n\t\tlineoffset += scaleY*25.0f;\n\t}\n}\n\nvoid\nCCredits::Render(void)\n{\n\tuint32 lineoffset;\n\tfloat scrolloffset;\n\n\tif(!bCreditsGoing || FrontEndMenuManager.m_bMenuActive)\n\t\treturn;\n\n\tDefinedState();\n\tlineoffset = 0;\n\tscrolloffset = (CTimer::GetTimeInMilliseconds() - CreditsStartTime) / 24.0f;\n\tCFont::SetJustifyOff();\n\tCFont::SetBackgroundOff();\n\tCFont::SetCentreSize(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH * 0.75f));\n\tCFont::SetCentreOn();\n\tCFont::SetPropOn();\n\tCFont::SetFontStyle(FONT_STANDARD);\n\n    PrintCreditText(1.1f, 0.8f, TheText.Get(\"CRED001\"), lineoffset, scrolloffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditText(1.1f, 0.8f, TheText.Get(\"CRED002\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED003\"), lineoffset, scrolloffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditText(1.1f, 0.8f, TheText.Get(\"CRED004\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED005\"), lineoffset, scrolloffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditText(1.1f, 0.8f, TheText.Get(\"CRED006\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED007\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED008\"), lineoffset, scrolloffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditText(1.1f, 0.8f, TheText.Get(\"CRED025\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED026\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED027\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED028\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED029\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED030\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED031\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRD031A\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRD031B\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRD031C\"), lineoffset, scrolloffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditText(1.1f, 0.8f, TheText.Get(\"CRD031D\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRD031E\"), lineoffset, scrolloffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditText(1.1f, 0.8f, TheText.Get(\"CRD024A\"), lineoffset, scrolloffset);\n    if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_SPANISH)\n        PrintCreditSpace(0.5f, lineoffset);\n\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED024\"), lineoffset, scrolloffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditText(1.1f, 0.8f, TheText.Get(\"CRED023\"), lineoffset, scrolloffset);\n    if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH)\n        PrintCreditSpace(0.5f, lineoffset);\n\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRD023A\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRD023B\"), lineoffset, scrolloffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditText(1.1f, 0.8f, TheText.Get(\"CRED018\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED019\"), lineoffset, scrolloffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditText(1.1f, 0.8f, TheText.Get(\"CRD018A\"), lineoffset, scrolloffset);\n    if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH)\n        PrintCreditSpace(0.5f, lineoffset);\n\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRD019A\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRD019B\"), lineoffset, scrolloffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditText(1.1f, 0.8f, TheText.Get(\"CRED020\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED021\"), lineoffset, scrolloffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditText(1.1f, 0.8f, TheText.Get(\"CRD022A\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED022\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRD022B\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRD022C\"), lineoffset, scrolloffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditText(1.1f, 0.8f, TheText.Get(\"CRED032\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED033\"), lineoffset, scrolloffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditText(1.1f, 0.8f, TheText.Get(\"CRD032A\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED034\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED035\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED036\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED037\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRD037A\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRD037B\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRD037C\"), lineoffset, scrolloffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditText(1.1f, 0.8f, TheText.Get(\"CRD041B\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED042\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED039\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED044\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED040\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRD042A\"), lineoffset, scrolloffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditText(1.1f, 0.8f, TheText.Get(\"CRED142\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRD142A\"), lineoffset, scrolloffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditText(1.1f, 0.8f, TheText.Get(\"CRED009\"), lineoffset, scrolloffset);\n    if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH)\n        PrintCreditSpace(0.5f, lineoffset);\n\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED010\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED011\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED012\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED013\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRD013A\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRD013B\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRD013C\"), lineoffset, scrolloffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditText(1.1f, 0.8f, TheText.Get(\"CRED089\"), lineoffset, scrolloffset);\n    if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_SPANISH)\n        PrintCreditSpace(0.5f, lineoffset);\n\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED090\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED347\"), lineoffset, scrolloffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditText(1.1f, 0.8f, TheText.Get(\"CRED047\"), lineoffset, scrolloffset);\n    if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_SPANISH)\n        PrintCreditSpace(0.5f, lineoffset);\n\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED048\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED049\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED348\"), lineoffset, scrolloffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditText(1.1f, 0.8f, TheText.Get(\"CRED050\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED051\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED052\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED053\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED054\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED055\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED056\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRD056A\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRD056B\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRD056C\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRD056D\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED349\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED350\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED351\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED352\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED353\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED354\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED355\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED356\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED357\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED359\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED360\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED361\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED362\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED363\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED364\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED365\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED366\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED367\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED368\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED369\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED370\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED371\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED372\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED373\"), lineoffset, scrolloffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditText(1.1f, 0.8f, TheText.Get(\"CRED256\"), lineoffset, scrolloffset);\n    if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH)\n        PrintCreditSpace(0.5f, lineoffset);\n\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED257\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED258\"), lineoffset, scrolloffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditText(1.1f, 0.8f, TheText.Get(\"CRED057\"), lineoffset, scrolloffset);\n    if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_SPANISH)\n        PrintCreditSpace(0.5f, lineoffset);\n\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED058\"), lineoffset, scrolloffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditText(1.1f, 0.8f, TheText.Get(\"CRD057A\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED059\"), lineoffset, scrolloffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditText(1.1f, 0.8f, TheText.Get(\"CRD060A\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRD060B\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRD060C\"), lineoffset, scrolloffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditText(1.1f, 0.8f, TheText.Get(\"CRD002A\"), lineoffset, scrolloffset);\n    if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_SPANISH)\n        PrintCreditSpace(0.5f, lineoffset);\n\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED003\"), lineoffset, scrolloffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditText(1.1f, 0.8f, TheText.Get(\"CRD001A\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRD001B\"), lineoffset, scrolloffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditText(1.1f, 0.8f, TheText.Get(\"CRED060\"), lineoffset, scrolloffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditText(1.1f, 0.8f, TheText.Get(\"CRED061\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED062\"), lineoffset, scrolloffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditText(1.1f, 0.8f, TheText.Get(\"CRED063\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED064\"), lineoffset, scrolloffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditText(1.1f, 0.8f, TheText.Get(\"CRED069\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED070\"), lineoffset, scrolloffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditText(1.1f, 0.8f, TheText.Get(\"CRED065\"), lineoffset, scrolloffset);\n    if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_SPANISH)\n        PrintCreditSpace(0.5f, lineoffset);\n\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED066\"), lineoffset, scrolloffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditText(1.1f, 0.8f, TheText.Get(\"CRED067\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED068\"), lineoffset, scrolloffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditText(1.1f, 0.8f, TheText.Get(\"CRD071A\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRD072A\"), lineoffset, scrolloffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditText(1.1f, 0.8f, TheText.Get(\"CRED091\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED094\"), lineoffset, scrolloffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditText(1.1f, 0.8f, TheText.Get(\"CRED095\"), lineoffset, scrolloffset);\n    if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_SPANISH || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH)\n        PrintCreditSpace(0.5f, lineoffset);\n\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED097\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED098\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRD098A\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRD098B\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRD098C\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED099\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED096\"), lineoffset, scrolloffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditText(1.1f, 0.8f, TheText.Get(\"CRED273\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRD092A\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED092\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRD092B\"), lineoffset, scrolloffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditText(1.1f, 0.8f, TheText.Get(\"CRED073\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED074\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED076\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED075\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED077\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED078\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED081\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED082\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED079\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED080\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED083\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED084\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRD084A\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRD084B\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRD084C\"), lineoffset, scrolloffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditText(1.1f, 0.8f, TheText.Get(\"CRD084D\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRD084E\"), lineoffset, scrolloffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditText(0.95f, 0.7f, TheText.Get(\"CRED085\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED086\"), lineoffset, scrolloffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRD086A\"), lineoffset, scrolloffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditText(0.95f, 0.7f, TheText.Get(\"CRED087\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED088\"), lineoffset, scrolloffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRD088A\"), lineoffset, scrolloffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRD088B\"), lineoffset, scrolloffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRD088C\"), lineoffset, scrolloffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRD088D\"), lineoffset, scrolloffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRD088E\"), lineoffset, scrolloffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRD088F\"), lineoffset, scrolloffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRD088G\"), lineoffset, scrolloffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditText(1.1f, 0.8f, TheText.Get(\"CRED107\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED108\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED109\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)\n        PrintCreditSpace(0.5f, lineoffset);\n\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED110\"), lineoffset, scrolloffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRD110A\"), lineoffset, scrolloffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditText(1.1f, 0.8f, TheText.Get(\"CRED111\"), lineoffset, scrolloffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED112\"), lineoffset, scrolloffset);\n\n    if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)\n        PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED113\"), lineoffset, scrolloffset);\n    if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)\n        PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED114\"), lineoffset, scrolloffset);\n    if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)\n        PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED115\"), lineoffset, scrolloffset);\n    if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)\n        PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED116\"), lineoffset, scrolloffset);\n    if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)\n        PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED117\"), lineoffset, scrolloffset);\n    if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)\n        PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED118\"), lineoffset, scrolloffset);\n    if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)\n        PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED119\"), lineoffset, scrolloffset);\n    if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)\n        PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED120\"), lineoffset, scrolloffset);\n    if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)\n        PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED121\"), lineoffset, scrolloffset);\n    if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)\n        PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED122\"), lineoffset, scrolloffset);\n    if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)\n        PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED123\"), lineoffset, scrolloffset);\n    if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)\n        PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED124\"), lineoffset, scrolloffset);\n    if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)\n        PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED125\"), lineoffset, scrolloffset);\n    if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)\n        PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED126\"), lineoffset, scrolloffset);\n    if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)\n        PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED127\"), lineoffset, scrolloffset);\n    if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)\n        PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED128\"), lineoffset, scrolloffset);\n    if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)\n        PrintCreditSpace(0.5f, lineoffset);\n\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED129\"), lineoffset, scrolloffset);\n    PrintCreditSpace(1.5f, lineoffset);\n\n    CFont::SetCentreSize(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH * 0.8f));\n\n    PrintCreditText(1.1f, 0.8f, TheText.Get(\"CRD111A\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n\n    if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_SPANISH || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH)\n        PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED130\"), lineoffset, scrolloffset);\n    if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_SPANISH || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH)\n        PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED131\"), lineoffset, scrolloffset);\n    if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_SPANISH || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH)\n        PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED132\"), lineoffset, scrolloffset);\n    if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_SPANISH || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH)\n        PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED133\"), lineoffset, scrolloffset);\n    if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_SPANISH || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH)\n        PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED134\"), lineoffset, scrolloffset);\n    if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_SPANISH || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH)\n        PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRD134A\"), lineoffset, scrolloffset);\n    if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_SPANISH || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH)\n        PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRD134B\"), lineoffset, scrolloffset);\n    if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_SPANISH || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH)\n        PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRD134C\"), lineoffset, scrolloffset);\n    if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_SPANISH || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH)\n        PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRD134D\"), lineoffset, scrolloffset);\n    if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_SPANISH || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH)\n        PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRD134E\"), lineoffset, scrolloffset);\n    if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_SPANISH || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH)\n        PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRD134F\"), lineoffset, scrolloffset);\n    if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_SPANISH || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH)\n        PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRD134G\"), lineoffset, scrolloffset);\n    if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_SPANISH || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH)\n        PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRD134H\"), lineoffset, scrolloffset);\n    if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_SPANISH || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH)\n        PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRD134I\"), lineoffset, scrolloffset);\n\n    CFont::SetCentreSize(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH * 0.7f));\n\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditText(1.1f, 0.8f, TheText.Get(\"CRED135\"), lineoffset, scrolloffset);\n\n    if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_SPANISH)\n        PrintCreditSpace(0.5f, lineoffset);\n\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRD136A\"), lineoffset, scrolloffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRD137A\"), lineoffset, scrolloffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditText(1.1f, 0.8f, TheText.Get(\"CRED138\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED066\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRD138B\"), lineoffset, scrolloffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED139\"), lineoffset, scrolloffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditText(1.1f, 0.8f, TheText.Get(\"CRED140\"), lineoffset, scrolloffset);\n    if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_FRENCH)\n        PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRD140A\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRD140B\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRD140C\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRD140D\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRD140E\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRD140F\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRD140G\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRD140H\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRD140I\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRD140J\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRD140K\"), lineoffset, scrolloffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRD140L\"), lineoffset, scrolloffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    \n    CFont::SetCentreSize(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH * 0.85f));\n\n    PrintCreditText(0.95f, 0.7f, TheText.Get(\"CRED259\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.95f, 0.95f, TheText.Get(\"CRED260\"), lineoffset, scrolloffset);\n    PrintCreditText(0.95f, 0.95f, TheText.Get(\"CRED261\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.95f, 0.95f, TheText.Get(\"CRED262\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.95f, 0.95f, TheText.Get(\"CRED263\"), lineoffset, scrolloffset);\n    PrintCreditText(0.95f, 0.95f, TheText.Get(\"CRED264\"), lineoffset, scrolloffset);\n    PrintCreditText(0.95f, 0.95f, TheText.Get(\"CRED265\"), lineoffset, scrolloffset);\n    PrintCreditText(0.95f, 0.95f, TheText.Get(\"CRED266\"), lineoffset, scrolloffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditText(0.95f, 0.7f, TheText.Get(\"CRED141\"), lineoffset, scrolloffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRD141A\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRD141B\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED143\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED144\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditText(0.95f, 0.7f, TheText.Get(\"CRED145\"), lineoffset, scrolloffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED146\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED147\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED148\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED149\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED150\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED151\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED152\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED153\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED154\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED155\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED156\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED157\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED158\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED159\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED160\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED161\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED162\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED163\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED164\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED165\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED166\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED167\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED168\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED169\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED170\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED171\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED172\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n\n    CFont::SetCentreSize(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH * 0.75f));\n\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditText(0.95f, 0.7f, TheText.Get(\"CRED217\"), lineoffset, scrolloffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditText(0.95f, 0.7f, TheText.Get(\"CRED218\"), lineoffset, scrolloffset);\n    PrintCreditSpace(1.0f, lineoffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRD218A\"), lineoffset, scrolloffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditText(0.95f, 0.7f, TheText.Get(\"CRED219\"), lineoffset, scrolloffset);\n    PrintCreditSpace(1.0f, lineoffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED220\"), lineoffset, scrolloffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditText(0.95f, 0.7f, TheText.Get(\"CRED221\"), lineoffset, scrolloffset);\n    PrintCreditSpace(1.0f, lineoffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED222\"), lineoffset, scrolloffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditText(0.95f, 0.7f, TheText.Get(\"CRED223\"), lineoffset, scrolloffset);\n    PrintCreditSpace(1.0f, lineoffset);\n    PrintCreditText(1.1f, 1.1f, TheText.Get(\"CRED224\"), lineoffset, scrolloffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditText(0.95f, 0.7f, TheText.Get(\"CRED227\"), lineoffset, scrolloffset);\n    PrintCreditSpace(1.0f, lineoffset);\n    PrintCreditText(0.95f, 0.95f, TheText.Get(\"CRED228\"), lineoffset, scrolloffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditText(0.95f, 0.7f, TheText.Get(\"CRED229\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRD229A\"), lineoffset, scrolloffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRD229B\"), lineoffset, scrolloffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditText(0.95f, 0.7f, TheText.Get(\"CRED274\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED275\"), lineoffset, scrolloffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED276\"), lineoffset, scrolloffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED277\"), lineoffset, scrolloffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditText(0.95f, 0.7f, TheText.Get(\"CRED278\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED279\"), lineoffset, scrolloffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED280\"), lineoffset, scrolloffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED281\"), lineoffset, scrolloffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditText(0.95f, 0.7f, TheText.Get(\"CRED282\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED283\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED284\"), lineoffset, scrolloffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED285\"), lineoffset, scrolloffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED286\"), lineoffset, scrolloffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditText(0.95f, 0.7f, TheText.Get(\"CRED287\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED288\"), lineoffset, scrolloffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED289\"), lineoffset, scrolloffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED290\"), lineoffset, scrolloffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditText(0.95f, 0.7f, TheText.Get(\"CRED291\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED292\"), lineoffset, scrolloffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditText(0.95f, 0.7f, TheText.Get(\"CRED293\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED294\"), lineoffset, scrolloffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED295\"), lineoffset, scrolloffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED296\"), lineoffset, scrolloffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditText(0.95f, 0.7f, TheText.Get(\"CRED297\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED298\"), lineoffset, scrolloffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED299\"), lineoffset, scrolloffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED300\"), lineoffset, scrolloffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED301\"), lineoffset, scrolloffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED302\"), lineoffset, scrolloffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED303\"), lineoffset, scrolloffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED304\"), lineoffset, scrolloffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED305\"), lineoffset, scrolloffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED306\"), lineoffset, scrolloffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED307\"), lineoffset, scrolloffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED308\"), lineoffset, scrolloffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditText(0.95f, 0.7f, TheText.Get(\"CRED309\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED310\"), lineoffset, scrolloffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditText(0.95f, 0.7f, TheText.Get(\"CRED314\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.95f, 0.7f, TheText.Get(\"CRED315\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.95f, 0.7f, TheText.Get(\"CRED316\"), lineoffset, scrolloffset);\n    PrintCreditSpace(1.0f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED317\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED318\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED319\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED320\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED321\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED322\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED323\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED324\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED325\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED326\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED327\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED328\"), lineoffset, scrolloffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditText(0.95f, 0.7f, TheText.Get(\"CRED329\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED330\"), lineoffset, scrolloffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED331\"), lineoffset, scrolloffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED332\"), lineoffset, scrolloffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    \n    CFont::SetCentreSize(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH * 0.8f));\n\n    PrintCreditText(0.95f, 0.7f, TheText.Get(\"CRED333\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED334\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED335\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED336\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED337\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED338\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED339\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED340\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED341\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED342\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditSpace(1.0f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRD344A\"), lineoffset, scrolloffset);\n    if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)\n        PrintCreditSpace(0.5f, lineoffset);\n\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED344\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED345\"), lineoffset, scrolloffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRD345A\"), lineoffset, scrolloffset);\n    PrintCreditSpace(1.0f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED346\"), lineoffset, scrolloffset);\n    if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)\n        PrintCreditSpace(1.0f, lineoffset);\n\n    PrintCreditSpace(1.5f, lineoffset);\n\n    CFont::SetCentreSize(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH * 0.75f));\n\n    PrintCreditText(0.95f, 0.7f, TheText.Get(\"CRED267\"), lineoffset, scrolloffset);\n    PrintCreditSpace(0.5f, lineoffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED268\"), lineoffset, scrolloffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditText(0.95f, 0.7f, TheText.Get(\"CRED269\"), lineoffset, scrolloffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED270\"), lineoffset, scrolloffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED271\"), lineoffset, scrolloffset);\n    PrintCreditText(0.65f, 0.65f, TheText.Get(\"CRED272\"), lineoffset, scrolloffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditText(0.95f, 0.7f, TheText.Get(\"CRED230\"), lineoffset, scrolloffset);\n    if (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_ITALIAN)\n        PrintCreditSpace(0.5f, lineoffset);\n\n    PrintCreditText(0.95f, 0.95f, TheText.Get(\"CRED231\"), lineoffset, scrolloffset);\n    PrintCreditText(0.95f, 0.95f, TheText.Get(\"CRED232\"), lineoffset, scrolloffset);\n    PrintCreditText(0.95f, 0.95f, TheText.Get(\"CRED233\"), lineoffset, scrolloffset);\n    PrintCreditText(0.95f, 0.95f, TheText.Get(\"CRED234\"), lineoffset, scrolloffset);\n    PrintCreditText(0.95f, 0.95f, TheText.Get(\"CRED235\"), lineoffset, scrolloffset);\n    PrintCreditText(0.95f, 0.95f, TheText.Get(\"CRED236\"), lineoffset, scrolloffset);\n    PrintCreditText(0.95f, 0.95f, TheText.Get(\"CRED237\"), lineoffset, scrolloffset);\n    PrintCreditText(0.95f, 0.95f, TheText.Get(\"CRED238\"), lineoffset, scrolloffset);\n    PrintCreditText(0.95f, 0.95f, TheText.Get(\"CRED239\"), lineoffset, scrolloffset);\n    PrintCreditText(0.95f, 0.95f, TheText.Get(\"CRED240\"), lineoffset, scrolloffset);\n    PrintCreditText(0.95f, 0.95f, TheText.Get(\"CRED241\"), lineoffset, scrolloffset);\n    PrintCreditText(0.95f, 0.95f, TheText.Get(\"CRED242\"), lineoffset, scrolloffset);\n    PrintCreditText(0.95f, 0.95f, TheText.Get(\"CRED243\"), lineoffset, scrolloffset);\n    PrintCreditText(0.95f, 0.95f, TheText.Get(\"CRED244\"), lineoffset, scrolloffset);\n    PrintCreditText(0.95f, 0.95f, TheText.Get(\"CRED245\"), lineoffset, scrolloffset);\n    PrintCreditText(0.95f, 0.95f, TheText.Get(\"CRED246\"), lineoffset, scrolloffset);\n    PrintCreditText(0.95f, 0.95f, TheText.Get(\"CRED247\"), lineoffset, scrolloffset);\n    PrintCreditText(0.95f, 0.95f, TheText.Get(\"CRED248\"), lineoffset, scrolloffset);\n    PrintCreditText(0.95f, 0.95f, TheText.Get(\"CRED249\"), lineoffset, scrolloffset);\n    PrintCreditText(0.95f, 0.95f, TheText.Get(\"CRED358\"), lineoffset, scrolloffset);\n    PrintCreditText(0.95f, 0.95f, TheText.Get(\"CRED250\"), lineoffset, scrolloffset);\n    PrintCreditText(0.95f, 0.95f, TheText.Get(\"CRED251\"), lineoffset, scrolloffset);\n    PrintCreditText(0.95f, 0.95f, TheText.Get(\"CRED252\"), lineoffset, scrolloffset);\n    PrintCreditText(0.95f, 0.95f, TheText.Get(\"CRD251A\"), lineoffset, scrolloffset);\n    PrintCreditText(0.95f, 0.95f, TheText.Get(\"CRD252A\"), lineoffset, scrolloffset);\n    PrintCreditText(0.95f, 0.95f, TheText.Get(\"CRED253\"), lineoffset, scrolloffset);\n    PrintCreditText(0.95f, 0.95f, TheText.Get(\"CRED254\"), lineoffset, scrolloffset);\n    PrintCreditText(0.95f, 0.95f, TheText.Get(\"CRED374\"), lineoffset, scrolloffset);\n    PrintCreditText(0.95f, 0.95f, TheText.Get(\"CRED375\"), lineoffset, scrolloffset);\n    PrintCreditText(0.95f, 0.95f, TheText.Get(\"CRED376\"), lineoffset, scrolloffset);\n    PrintCreditText(0.95f, 0.95f, TheText.Get(\"CRED377\"), lineoffset, scrolloffset);\n    PrintCreditText(0.95f, 0.95f, TheText.Get(\"CRED378\"), lineoffset, scrolloffset);\n    PrintCreditText(0.95f, 0.95f, TheText.Get(\"CRED379\"), lineoffset, scrolloffset);\n    PrintCreditText(0.95f, 0.95f, TheText.Get(\"CRED380\"), lineoffset, scrolloffset);\n    PrintCreditText(0.95f, 0.95f, TheText.Get(\"CRED381\"), lineoffset, scrolloffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    PrintCreditSpace(1.5f, lineoffset);\n    CFont::DrawFonts();\n#ifdef CUTSCENE_BORDERS_SWITCH\n    if (CMenuManager::m_PrefsCutsceneBorders)\n#endif\n\tif(TheCamera.m_WideScreenOn)\n\t\tTheCamera.DrawBordersForWideScreen();\n\n#ifdef FIX_BUGS\n\tif(lineoffset + DEFAULT_SCREEN_HEIGHT - scrolloffset < -10.0f)\n#else\n\tif(lineoffset + SCREEN_HEIGHT - scrolloffset < -10.0f)\n#endif\n\t{\n\t\tbCreditsGoing = false;\n\t}\n}\n\nbool CCredits::AreCreditsDone(void)\n{\n\treturn !bCreditsGoing;\n}\n"
  },
  {
    "path": "src/render/Credits.h",
    "content": "#pragma once\n\nclass CCredits\n{\n\tstatic bool bCreditsGoing;\n\tstatic uint32 CreditsStartTime;\npublic:\n\tstatic void Init(void);\n\tstatic void Start(void);\n\tstatic void Stop(void);\n\tstatic bool AreCreditsDone(void);\n\tstatic void Render(void);\n\tstatic void PrintCreditSpace(float space, uint32 &line);\n\tstatic void PrintCreditText(float scaleX, float scaleY, wchar *text, uint32 &lineoffset, float scrolloffset);\n};\n"
  },
  {
    "path": "src/render/CutsceneShadow.cpp",
    "content": "#include \"common.h\"\n#include \"main.h\"\n#include \"rwcore.h\"\n#include \"rwplcore.h\"\n#include \"CutsceneShadow.h\"\n#include \"RwHelper.h\"\n\n#define DLIGHT_VALUE        0.8f /* Directional light intensity */\n\n\nCCutsceneShadow::CCutsceneShadow()\n{\t\n\tm_pAtomic = nil;\n\tm_nRwObjectType = -1;\n\tm_pLight = nil;\n\tm_nBlurPasses = 0;\n\tm_bResample = false;\n\tm_bGradient = false;\n}\n\nCCutsceneShadow::~CCutsceneShadow()\n{\n\tDestroy();\n}\n\nbool\nCCutsceneShadow::Create(RwObject *object, int32 rasterSize, bool resample, int32 blurPasses, bool gradient)\n{\n\tASSERT(object != nil);\n\t\n\tRwRGBAReal color;\n\tRwFrame *frame;\n\n\tif (!object)\n\t\treturn false;\n\n\tm_pLight = RpLightCreate(rpLIGHTDIRECTIONAL);\n\tASSERT(m_pLight != nil);\n\t\n\tif (!m_pLight)\n\t\treturn false;\n\n\tcolor.red = color.green = color.blue = DLIGHT_VALUE;\n\tcolor.alpha = 0.0f;\n\t\n\tRpLightSetColor(m_pLight, &color);\n\t\n\tframe = RwFrameCreate();\n\tASSERT(frame != nil);\n\t\n\tRpLightSetFrame(m_pLight, frame);\n\t\n\tSetLightProperties(180.0f, 90.0f, false);\n\n\tm_pObject = object;\n\tm_nRwObjectType = RwObjectGetType(m_pObject);\n\t\n\tswitch ( m_nRwObjectType )\n\t{\n\t\tcase rpCLUMP:\n\t\t{\n\t\t\tRpClumpGetBoundingSphere(m_pClump, &m_BoundingSphere, 1);\n\t\t\tm_BaseSphere.radius = m_BoundingSphere.radius;\n\t\t\tRwV3dTransformPoints(&m_BaseSphere.center, &m_BoundingSphere.center, 1, RwFrameGetMatrix(RpClumpGetFrame(m_pClump)));\n\t\t\tbreak;\n\t\t}\n\n\t\tcase rpATOMIC:\n\t\t{\n\t\t\tm_BoundingSphere = *RpAtomicGetBoundingSphere(m_pAtomic);\n\t\t\tm_BaseSphere.radius = m_BoundingSphere.radius;\n\t\t\tRwV3dTransformPoints(&m_BaseSphere.center, &m_BoundingSphere.center, 1, RwFrameGetMatrix(RpAtomicGetFrame(m_pAtomic)));\n\t\t\tbreak;\n\t\t}\n\n\t\tdefault:\n\t\t{\n\t\t\tDestroy();\n\t\t\treturn false;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tif ( !m_Camera.Create(rasterSize) )\n\t{\n\t\tDestroy();\n\t\treturn false;\n\t}\n  \n\tm_nBlurPasses = blurPasses;\n\tm_bResample = resample;\n\tm_bGradient = gradient;\n\n\tif ( m_bResample && !m_ResampleCamera.Create(rasterSize - 1) )\n\t{\n\t\tDestroy();\n\t\treturn false;\n\t}\n  \n\tif ( m_nBlurPasses != 0 )\n\t{\n\t\tif ( !m_BlurCamera.Create(resample ? rasterSize - 1 : rasterSize) )\n\t\t{\n\t\t\tDestroy();\n\t\t\treturn false;\n\t\t}\n\t}\n  \n\tif ( m_bGradient )\n\t{\n\t\tif ( !m_GradientCamera.Create(resample ? rasterSize - 1 : rasterSize) )\n\t\t{\n\t\t\tDestroy();\n\t\t\treturn false;\n\t\t}\n\t\t\n\t\tm_GradientCamera.MakeGradientRaster();\n\t}\n  \n\tm_Camera.SetLight(m_pLight);\n  \n\tswitch ( m_nRwObjectType )\n\t{\n\t\tcase rpATOMIC:\n\t\t\tm_Camera.SetFrustum(1.1f * m_BoundingSphere.radius);\n\t\t\tbreak;\n\t\t\t\n\t\tcase rpCLUMP:\n\t\t\tm_Camera.SetFrustum(1.1f * m_BoundingSphere.radius);\n\t\t\tbreak;\n\t}\n  \n\tm_Camera.SetCenter(&m_BaseSphere.center);\n\treturn true;\n}\n\nRwFrame *\nCCutsceneShadow::SetLightProperties(float angleY, float angleX, bool setLight)\n{\n\tASSERT(m_pLight != nil);\n\t\n\tRwFrame *frame;\n\tstatic RwV3d        Xaxis = { 1.0f, 0.0f, 0.0f };\n\tstatic RwV3d        Yaxis = { 0.0f, 1.0f, 0.0f };\n\n\tframe = RpLightGetFrame(m_pLight);\n\tASSERT(frame != nil);\n\t\n\tif ( !frame )\n\t\treturn nil;\n\t\n\tRwFrameRotate(frame, &Yaxis, angleY, rwCOMBINEREPLACE);\n\tRwFrameRotate(frame, &Xaxis, angleX, rwCOMBINEPOSTCONCAT);\n\t\n\tif ( setLight )\n\t\tm_Camera.SetLight(m_pLight);\n\t\t\n\treturn frame;\n}\n\nbool\nCCutsceneShadow::IsInitialized()\n{\n\treturn m_pObject != nil;\n}\n\nvoid\nCCutsceneShadow::Destroy()\n{\n\tm_Camera.Destroy();\n\tm_ResampleCamera.Destroy();\n\tm_BlurCamera.Destroy();\n\tm_GradientCamera.Destroy();\n\t\n\tm_pAtomic = nil;\n\t\n\tm_nRwObjectType = -1;\n  \n\tif (m_pLight)\n\t{\n\t\tRwFrame *frame = RpLightGetFrame(m_pLight);\n\t\tRpLightSetFrame(m_pLight, nil);\n\t\tRwFrameDestroy(frame);\n\t\tRpLightDestroy(m_pLight);\n\t\tm_pLight = nil;\n\t}\n}\n\nRwRaster *\nCCutsceneShadow::Update()\n{\n\tswitch ( m_nRwObjectType )\n\t{\n\t\tcase rpCLUMP:\n\t\t\tASSERT(m_pClump != nil);\n\t\t\tRwV3dTransformPoints(&m_BaseSphere.center, &m_BoundingSphere.center, 1, RwFrameGetMatrix(RpClumpGetFrame(m_pClump)));\n\t\t\tbreak;\n\n\t\tcase rpATOMIC:\n\t\t\tASSERT(m_pAtomic != nil);\n\t\t\tRwV3dTransformPoints(&m_BaseSphere.center, &m_BoundingSphere.center, 1, RwFrameGetMatrix(RpAtomicGetFrame(m_pAtomic)));\n\t\t\tbreak;\n\t}\n\n\tm_Camera.SetCenter(&m_BaseSphere.center);\n\n\tswitch ( m_nRwObjectType )\n\t{\n\t\tcase rpCLUMP:\n\t\t\tm_Camera.Update(m_pClump);\n\t\t\tbreak;\n\n\t\tcase rpATOMIC:\n\t\t\tm_Camera.Update(m_pAtomic);\n\t\t\tbreak;\n\t}\n\t\n\tRwRaster *raster = m_Camera.GetRwRenderRaster();\n\tASSERT(raster != nil);\n\n\tif ( m_bResample )\n\t\treturn m_ResampleCamera.RasterResample(raster);\n\n\tif ( m_nBlurPasses )\n\t\treturn m_BlurCamera.RasterBlur(raster, m_nBlurPasses);\n\n\tif ( m_bGradient )\n\t\treturn m_GradientCamera.RasterGradient(raster);\n\t\n\treturn raster;\n}\n\nRwTexture *\nCCutsceneShadow::UpdateForCutscene()\n{\n\tUpdate();\n\treturn GetShadowRwTexture();\n}\n\nCShadowCamera *\nCCutsceneShadow::GetShadowCamera(int32 camType)\n{\n\tswitch ( camType )\n\t{\n\t\tcase RESAMPLE: return &m_ResampleCamera;\n\t\tcase BLUR:     return &m_BlurCamera;    \n\t\tcase GRADIENT: return &m_GradientCamera;\n\t}\n\t\n\treturn &m_Camera;\n}\n\nRwTexture *\nCCutsceneShadow::GetShadowRwTexture()\n{\n\tif ( m_bResample )\n\t\treturn m_ResampleCamera.GetRwRenderTexture();\n\telse\n\t\treturn m_Camera.GetRwRenderTexture();\n}\n\nvoid\nCCutsceneShadow::DrawBorderAroundTexture(RwRGBA  const& color)\n{\n\tif ( m_bResample )\n\t\tm_ResampleCamera.DrawOutlineBorder(color);\n\telse\n\t\tm_Camera.DrawOutlineBorder(color);\n}"
  },
  {
    "path": "src/render/CutsceneShadow.h",
    "content": "#pragma once\n#include \"ShadowCamera.h\"\n\nclass CCutsceneShadow\n{\npublic:\n\tenum\n\t{\n\t\tRASTER = 0,\n\t\tRESAMPLE,\n\t\tBLUR,\n\t\tGRADIENT,\n\t};\n\n\tCShadowCamera m_Camera;\n\tbool          m_bResample;\n\tCShadowCamera m_ResampleCamera;\n\tint32         m_nBlurPasses;\n\tCShadowCamera m_BlurCamera;\n\tbool          m_bGradient;\n\tCShadowCamera m_GradientCamera;\n\t\n\tunion\n\t{\n\t\tRwObject *m_pObject;\n\t\tRpAtomic *m_pAtomic;\n\t\tRpClump  *m_pClump;\n\t};\n\t\n\tint32    m_nRwObjectType;\n\tRpLight *m_pLight;\n\tRwSphere m_BoundingSphere;\n\tRwSphere m_BaseSphere;\n\t\n\tCCutsceneShadow();\n\t~CCutsceneShadow();\n\t\n\tRwSphere GetBaseSphere()\n\t{\n\t\treturn m_BaseSphere;\n\t}\n\n\tbool Create(RwObject *object, int32 rasterSize, bool resample, int32 blurPasses, bool gradient);\n\tRwFrame *SetLightProperties(float angleY, float angleX, bool setLight);\n\tbool IsInitialized();\n\tvoid Destroy();\n\tRwRaster *Update();\n\tRwTexture *UpdateForCutscene();\n\tCShadowCamera *GetShadowCamera(int32 camType = RASTER);\n\tRwTexture *GetShadowRwTexture();\n\tvoid DrawBorderAroundTexture(RwRGBA  const& color);\n};\n"
  },
  {
    "path": "src/render/Draw.cpp",
    "content": "#include \"common.h\"\n\n#include \"Draw.h\"\n#include \"Frontend.h\"\n#include \"Camera.h\"\n#include \"CutsceneMgr.h\"\n\nfloat CDraw::ms_fAspectRatio = DEFAULT_ASPECT_RATIO;\n#ifdef ASPECT_RATIO_SCALE\nfloat CDraw::ms_fScaledFOV = 45.0f;\n#endif\n\nfloat CDraw::ms_fNearClipZ;\nfloat CDraw::ms_fFarClipZ;\nfloat CDraw::ms_fFOV = 45.0f;\nfloat CDraw::ms_fLODDistance;\n\nuint8 CDraw::FadeValue;\nuint8 CDraw::FadeRed;\nuint8 CDraw::FadeGreen;\nuint8 CDraw::FadeBlue;\n\n#ifdef PROPER_SCALING\t\nbool CDraw::ms_bProperScaling = true;\n#endif\n#ifdef  FIX_RADAR\nbool CDraw::ms_bFixRadar = true;\t\n#endif\n#ifdef FIX_SPRITES\nbool CDraw::ms_bFixSprites = true;\t\n#endif\n\n#ifdef ASPECT_RATIO_SCALE\nfloat\nFindAspectRatio(void)\n{\n\tswitch (FrontEndMenuManager.m_PrefsUseWideScreen) {\n\tcase AR_AUTO:\n\t\treturn SCREEN_WIDTH / SCREEN_HEIGHT;\n\tdefault:\n\tcase AR_4_3:\n\t\treturn 4.0f / 3.0f;\n\tcase AR_5_4:\n\t\treturn 5.0f / 4.0f;\n\tcase AR_16_10:\n\t\treturn 16.0f / 10.0f;\n\tcase AR_16_9:\n\t\treturn 16.0f / 9.0f;\n\tcase AR_21_9:\n\t\treturn 21.0f / 9.0f;\n\t};\n}\n#endif\n\nfloat\nCDraw::CalculateAspectRatio(void)\n{\n#ifdef ASPECT_RATIO_SCALE\n\tif (TheCamera.m_WideScreenOn)\n\t\tCDraw::ms_fAspectRatio = (5.f / 3.f) * FindAspectRatio() / (16.f / 9.f); // It's used on theatrical showings according to Wiki\n\telse\n\t\tCDraw::ms_fAspectRatio = FindAspectRatio();\n#else\n\tif(FrontEndMenuManager.m_PrefsUseWideScreen) {\n\t\tif (TheCamera.m_WideScreenOn)\n\t\t\tCDraw::ms_fAspectRatio = 5.f / 3.f; // It's used on theatrical showings according to Wiki\n\t\telse\n\t\t\tCDraw::ms_fAspectRatio = 16.f / 9.f;\n\t} else if (TheCamera.m_WideScreenOn) {\n\t\tCDraw::ms_fAspectRatio = 5.f/4.f;\n\t} else {\n\t\tCDraw::ms_fAspectRatio = 4.f/3.f;\n\t}\n#endif\n\treturn CDraw::ms_fAspectRatio;\n}\n\n#ifdef ASPECT_RATIO_SCALE\n// convert a 4:3 hFOV to vFOV,\n// then convert that vFOV to hFOV for our aspect ratio,\n// i.e. HOR+\nfloat\nCDraw::ConvertFOV(float hfov)\n{\n\t// => tan(hFOV/2) = tan(vFOV/2)*aspectRatio\n\t// => tan(vFOV/2) = tan(hFOV/2)/aspectRatio\n\tfloat ar1 = DEFAULT_ASPECT_RATIO;\n\tfloat ar2 = GetAspectRatio();\n\thfov = DEGTORAD(hfov);\n\tfloat vfov = Atan(tan(hfov/2) / ar1) *2;\n\thfov = Atan(tan(vfov/2) * ar2) *2;\n\treturn RADTODEG(hfov);\n}\n#endif\n\nvoid\nCDraw::SetFOV(float fov)\n{\n#ifdef ASPECT_RATIO_SCALE\n\tif (!CCutsceneMgr::IsRunning())\n\t\tms_fScaledFOV = ConvertFOV(fov);\n\telse\n\t\tms_fScaledFOV = fov;\n#endif\n\tms_fFOV = fov;\n}\n\n#ifdef PROPER_SCALING\t\nfloat CDraw::ScaleY(float y)\n{\n\treturn ms_bProperScaling ? y : y * ((float)DEFAULT_SCREEN_HEIGHT/SCREEN_HEIGHT_NTSC);\n}\n#endif"
  },
  {
    "path": "src/render/Draw.h",
    "content": "#pragma once\n\nenum eAspectRatio \n{\n\t// Make sure these work the same as FrontEndMenuManager.m_PrefsUseWideScreen\n\t// without widescreen support\n\tAR_AUTO,\n\tAR_4_3,\n\tAR_5_4,\n\tAR_16_10,\n\tAR_16_9,\n\tAR_21_9,\n\n\tAR_MAX,\n};\n\nclass CDraw\n{\nprivate:\n\tstatic float ms_fNearClipZ;\n\tstatic float ms_fFarClipZ;\n\tstatic float ms_fFOV;\n\t// we use this variable to scale a lot of 2D elements\n\t// so better cache it\n\tstatic float ms_fAspectRatio;\n#ifdef ASPECT_RATIO_SCALE\n\t// similar thing for 3D rendering\n\tstatic float ms_fScaledFOV;\n#endif\npublic:\n\tstatic float ms_fLODDistance;\t// set but unused?\n\n\tstatic uint8 FadeValue;\n\tstatic uint8 FadeRed;\n\tstatic uint8 FadeGreen;\n\tstatic uint8 FadeBlue;\n\t\n#ifdef PROPER_SCALING\t\n\tstatic bool ms_bProperScaling;\n#endif\n#ifdef FIX_RADAR\n\tstatic bool ms_bFixRadar;\t\n#endif\n#ifdef FIX_SPRITES\n\tstatic bool ms_bFixSprites;\t\n#endif\n\n\tstatic void SetNearClipZ(float nearclip) { ms_fNearClipZ = nearclip; }\n\tstatic float GetNearClipZ(void) { return ms_fNearClipZ; }\n\tstatic void SetFarClipZ(float farclip) { ms_fFarClipZ = farclip; }\n\tstatic float GetFarClipZ(void) { return ms_fFarClipZ; }\n\n\tstatic void SetFOV(float fov);\n\tstatic float GetFOV(void) { return ms_fFOV; }\n#ifdef ASPECT_RATIO_SCALE\n\tstatic float GetScaledFOV(void) { return ms_fScaledFOV; }\n#else\n\tstatic float GetScaledFOV(void) { return ms_fFOV; }\n#endif\n\n\tstatic float CalculateAspectRatio(void);\n#ifdef ASPECT_RATIO_SCALE\n\tstatic float ConvertFOV(float fov);\n#endif\n\tstatic float GetAspectRatio(void) { return ms_fAspectRatio; }\n\tstatic void SetAspectRatio(float ratio) { ms_fAspectRatio = ratio; }\n#ifdef PROPER_SCALING\t\n\tstatic float ScaleY(float y);\n#endif \n};\n"
  },
  {
    "path": "src/render/Fluff.cpp",
    "content": "#include \"common.h\"\n#include \"main.h\"\n\n#include \"RenderBuffer.h\"\n#include \"Entity.h\"\n#include \"Fluff.h\"\n#include \"Camera.h\"\n#include \"Sprite.h\"\n#include \"Coronas.h\"\n#include \"PointLights.h\"\n#include \"Rubbish.h\"\n#include \"Timecycle.h\"\n#include \"General.h\"\n#include \"Timer.h\"\n#include \"Clock.h\"\n#include \"Weather.h\"\n#include \"Stats.h\"\n#include \"maths.h\"\n#include \"Frontend.h\"\n#include \"CutsceneMgr.h\"\n#include \"PlayerPed.h\"\n#include \"Bones.h\"\n#include \"World.h\"\n#include \"Replay.h\"\n#include \"Coronas.h\"\n\nCPlaneTrail CPlaneTrails::aArray[6];\nRwImVertexIndex TrailIndices[32] = {\n\t0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9,\n\t10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16\n};\n\nvoid\nCPlaneTrail::Init(void)\n{\n\tint i;\n\tfor(i = 0; i < ARRAY_SIZE(m_time); i++)\n\t\tm_time[i] = 0;\n}\n\nvoid\nCPlaneTrail::Render(float visibility)\n{\n\tint i;\n\tint numVerts = 0;\n\tif(!TheCamera.IsSphereVisible(m_pos[0], 1000.0f))\n\t\treturn;\n\n\tint alpha = visibility*110.0f;\n\tif(alpha == 0)\n\t\treturn;\n\n\tfor(i = 0; i < ARRAY_SIZE(m_pos); i++){\n\t\tint32 time = CTimer::GetTimeInMilliseconds() - m_time[i];\n\t\tif(time > 30000)\n\t\t\tm_time[i] = 0;\n\t\tif(m_time[i] != 0){\n\t\t\tfloat fade = (30000.0f - time) / 10000.0f;\n\t\t\tfade = Min(fade, 1.0f);\n\t\t\tRwIm3DVertexSetRGBA(&TempBufferRenderVertices[numVerts], 255, 255, 255, (int)(alpha*fade));\n\t\t\tRwIm3DVertexSetPos(&TempBufferRenderVertices[numVerts], m_pos[i].x, m_pos[i].y, m_pos[i].z);\n\t\t\tnumVerts++;\n\t\t}\n\t}\n\tif(numVerts > 1){\n\t\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);\n\t\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);\n\t\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);\n\t\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil);\n\n\t\tif(RwIm3DTransform(TempBufferRenderVertices, numVerts, nil, rwIM3D_VERTEXXYZ|rwIM3D_VERTEXRGBA)){\n\t\t\tRwIm3DRenderIndexedPrimitive(rwPRIMTYPELINELIST, TrailIndices, (numVerts-1)*2);\n\t\t\tRwIm3DEnd();\n\t\t}\n\t}\n}\n\nvoid\nCPlaneTrail::RegisterPoint(CVector pos)\n{\n\tint i;\n\tbool bNewPoint = false;\n\tif(m_time[0] != 0 && CTimer::GetTimeInMilliseconds() - m_time[0] > 2000){\n\t\tbNewPoint = true;\n\t\tfor(i = ARRAY_SIZE(m_pos)-1; i > 0; i--){\n\t\t\tm_pos[i] = m_pos[i-1];\n\t\t\tm_time[i] = m_time[i-1];\n\t\t}\n\t}\n\tm_pos[0] = pos;\n\tif(bNewPoint || m_time[0] == 0)\n\t\tm_time[0] = CTimer::GetTimeInMilliseconds();\n}\n\nvoid\nCPlaneTrails::Init(void)\n{\n\tint i;\n\tfor(i = 0; i < ARRAY_SIZE(aArray); i++)\n\t\taArray[i].Init();\n}\n\nvoid\nCPlaneTrails::Update(void)\n{\n\tCVector planePos;\n\n\tplanePos.x = 1590.0f * Sin((float)(CTimer::GetTimeInMilliseconds() & 0x1FFFF)/0x20000 * TWOPI);\n\tplanePos.y = 1200.0f * Cos((float)(CTimer::GetTimeInMilliseconds() & 0x1FFFF)/0x20000 * TWOPI);\n\tplanePos.z = 550.0f;\n\tRegisterPoint(planePos, 3);\n\tif(CClock::GetHours() > 22 || CClock::GetHours() < 7){\n\t\tif(CTimer::GetTimeInMilliseconds() & 0x200)\n\t\t\tCCoronas::RegisterCorona(101, 255, 0, 0, 255, planePos, 5.0f, 2000.0f,\n\t\t\t\tCCoronas::TYPE_NORMAL, CCoronas::FLARE_NONE, CCoronas::REFLECTION_OFF,\n\t\t\t\tCCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);\n\t\telse\n\t\t\tCCoronas::UpdateCoronaCoors(101, planePos, 2000.0f, 0.0f);\n\t}\n\n\tplanePos.x = 1000.0f * Sin((float)(CTimer::GetTimeInMilliseconds() & 0x1FFFF)/0x20000 * TWOPI);\n\tplanePos.y = -1600.0f * Cos((float)(CTimer::GetTimeInMilliseconds() & 0x1FFFF)/0x20000 * TWOPI);\n\tplanePos.z = 500.0f;\n\tRegisterPoint(planePos, 4);\n\tif(CClock::GetHours() > 22 || CClock::GetHours() < 7){\n\t\tif(CTimer::GetTimeInMilliseconds() & 0x200)\n\t\t\tCCoronas::RegisterCorona(102, 255, 0, 0, 255, planePos, 5.0f, 2000.0f,\n\t\t\t\tCCoronas::TYPE_NORMAL, CCoronas::FLARE_NONE, CCoronas::REFLECTION_OFF,\n\t\t\t\tCCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);\n\t\telse\n\t\t\tCCoronas::UpdateCoronaCoors(102, planePos, 2000.0f, 0.0f);\n\t}\n\n\tplanePos.x = 1100.0f * Cos((float)(CTimer::GetTimeInMilliseconds() & 0x1FFFF)/0x20000 * TWOPI);\n\tplanePos.y = 700.0f * Sin((float)(CTimer::GetTimeInMilliseconds() & 0x1FFFF)/0x20000 * TWOPI);\n\tplanePos.z = 600.0f;\n\tRegisterPoint(planePos, 5);\n\tif(CClock::GetHours() > 22 || CClock::GetHours() < 7){\n\t\tif(CTimer::GetTimeInMilliseconds() & 0x200)\n\t\t\tCCoronas::RegisterCorona(103, 255, 0, 0, 255, planePos, 5.0f, 2000.0f,\n\t\t\t\tCCoronas::TYPE_NORMAL, CCoronas::FLARE_NONE, CCoronas::REFLECTION_OFF,\n\t\t\t\tCCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);\n\t\telse\n\t\t\tCCoronas::UpdateCoronaCoors(103, planePos, 2000.0f, 0.0f);\n\t}\n}\n\nvoid\nCPlaneTrails::Render(void)\n{\n\tint i;\n\tfloat visibility = Min(1.0f-CWeather::Foggyness, 1.0f-CWeather::CloudCoverage);\n\tvisibility = Min(visibility, 1.0f-CWeather::Rain);\n\tvisibility = Min(Max(Max(CTimeCycle::GetSkyTopRed(), CTimeCycle::GetSkyTopGreen()), CTimeCycle::GetSkyTopBlue())/256.0f, visibility);\n\tif(visibility > 0.0001f)\n\t\tfor(i = 0; i < ARRAY_SIZE(aArray); i++)\n\t\t\taArray[i].Render(visibility);\n}\n\nvoid\nCPlaneTrails::RegisterPoint(CVector pos, uint32 id)\n{\n\taArray[id].RegisterPoint(pos);\n}\n\n\n\nCPlaneBanner CPlaneBanners::aArray[5];\n\nvoid\nCPlaneBanner::Init(void)\n{\n\tint i;\n\tfor(i = 0; i < ARRAY_SIZE(m_pos); i++){\n\t\tm_pos[i].x = i;\n\t\tm_pos[i].y = 0.0f;\n\t\tm_pos[i].z = -60.0f;\n\t}\n}\n\nvoid\nCPlaneBanner::Update(void)\n{\n\tint i;\n\tif(m_pos[0].z > -50.0f){\n\t\tm_pos[0].z -= 0.05f*CTimer::GetTimeStep();\n\t\tm_pos[0].z = Max(m_pos[0].z, -100.0f);\n\t\tfor(i = 1; i < ARRAY_SIZE(m_pos); i++){\n\t\t\tCVector dist = m_pos[i] - m_pos[i-1];\n\t\t\tfloat len = dist.Magnitude();\n\t\t\tif(len > 8.0f)\n\t\t\t\tm_pos[i] = m_pos[i-1] + dist/len*8.0f;\n\t\t}\n\t}\n}\n\nvoid\nCPlaneBanner::Render(void)\n{\n\tint i;\n\tif(m_pos[0].z > -50.0f){\n\t\tfloat camDist = (TheCamera.GetPosition() - m_pos[0]).Magnitude();\n\t\tif(TheCamera.IsSphereVisible(m_pos[4], 32.0f) && camDist < 300.0f){\n\t\t\tTempBufferVerticesStored = 0;\n\t\t\tTempBufferIndicesStored = 0;\n\t\t\tint alpha = camDist < 250.0f ? 160 : (300.0f-camDist)/(300.0f-250.0f)*160;\n\n\t\t\tTempBufferVerticesStored += 2;\n\t\t\tRwIm3DVertexSetRGBA(&TempBufferRenderVertices[0], 255, 255, 255, alpha);\n\t\t\tRwIm3DVertexSetRGBA(&TempBufferRenderVertices[1], 255, 255, 255, alpha);\n\t\t\tRwIm3DVertexSetPos(&TempBufferRenderVertices[0], m_pos[2].x, m_pos[2].y, m_pos[2].z);\n\t\t\tRwIm3DVertexSetPos(&TempBufferRenderVertices[1], m_pos[2].x, m_pos[2].y, m_pos[2].z - 4.0f);\n\t\t\tRwIm3DVertexSetU(&TempBufferRenderVertices[0], 0.0f);\n\t\t\tRwIm3DVertexSetV(&TempBufferRenderVertices[0], 0.0f);\n\t\t\tRwIm3DVertexSetU(&TempBufferRenderVertices[1], 0.0f);\n\t\t\tRwIm3DVertexSetV(&TempBufferRenderVertices[1], 1.0f);\n\t\t\tfor(i = 2; i < 8; i++){\n\t\t\t\tRwIm3DVertexSetRGBA(&TempBufferRenderVertices[TempBufferVerticesStored+0], 255, 255, 255, alpha);\n\t\t\t\tRwIm3DVertexSetRGBA(&TempBufferRenderVertices[TempBufferVerticesStored+1], 255, 255, 255, alpha);\n\t\t\t\tRwIm3DVertexSetPos(&TempBufferRenderVertices[TempBufferVerticesStored+0], m_pos[i].x, m_pos[i].y, m_pos[i].z);\n\t\t\t\tRwIm3DVertexSetPos(&TempBufferRenderVertices[TempBufferVerticesStored+1], m_pos[i].x, m_pos[i].y, m_pos[i].z - 4.0f);\n\t\t\t\tRwIm3DVertexSetU(&TempBufferRenderVertices[TempBufferVerticesStored+0], (i-2)/5.0f);\n\t\t\t\tRwIm3DVertexSetV(&TempBufferRenderVertices[TempBufferVerticesStored+0], 0.0f);\n\t\t\t\tRwIm3DVertexSetU(&TempBufferRenderVertices[TempBufferVerticesStored+1], (i-2)/5.0f);\n\t\t\t\tRwIm3DVertexSetV(&TempBufferRenderVertices[TempBufferVerticesStored+1], 1.0f);\n\t\t\t\tTempBufferRenderIndexList[TempBufferIndicesStored+0] = TempBufferVerticesStored-2;\n\t\t\t\tTempBufferRenderIndexList[TempBufferIndicesStored+1] = TempBufferVerticesStored-1;\n\t\t\t\tTempBufferRenderIndexList[TempBufferIndicesStored+2] = TempBufferVerticesStored+1;\n\t\t\t\tTempBufferRenderIndexList[TempBufferIndicesStored+3] = TempBufferVerticesStored-2;\n\t\t\t\tTempBufferRenderIndexList[TempBufferIndicesStored+4] = TempBufferVerticesStored+1;\n\t\t\t\tTempBufferRenderIndexList[TempBufferIndicesStored+5] = TempBufferVerticesStored;\n\t\t\t\tTempBufferVerticesStored += 2;\n\t\t\t\tTempBufferIndicesStored += 6;\n\t\t\t}\n\t\t\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);\n\t\t\tRwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);\n\t\t\tRwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)TRUE);\n\t\t\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);\n\t\t\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);\n\t\t\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);\n\t\t\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpRubbishTexture[2]));\n\n#ifdef FIX_BUGS\n\t\t\tif(RwIm3DTransform(TempBufferRenderVertices, TempBufferVerticesStored, nil, rwIM3D_VERTEXXYZ|rwIM3D_VERTEXUV|rwIM3D_VERTEXRGBA)){\n#else\n\t\t\tif(RwIm3DTransform(TempBufferRenderVertices, TempBufferVerticesStored, nil, 0)){\n#endif\n\t\t\t\tRwIm3DRenderIndexedPrimitive(rwPRIMTYPETRILIST, TempBufferRenderIndexList, TempBufferIndicesStored);\n\t\t\t\tRwIm3DEnd();\n\t\t\t}\n\n\t\t\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);\n\t\t\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);\n\t\t\tRwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE);\n\t\t\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);\n\n\t\t\tTempBufferVerticesStored = 0;\n\t\t\tTempBufferIndicesStored = 0;\n\t\t}\n\t}\n}\n\nvoid\nCPlaneBanner::RegisterPoint(CVector pos)\n{\n\tm_pos[0] = pos;\n}\n\nvoid\nCPlaneBanners::Init(void)\n{\n\tint i;\n\tfor(i = 0; i < ARRAY_SIZE(aArray); i++)\n\t\taArray[i].Init();\n}\n\nvoid\nCPlaneBanners::Update(void)\n{\n\tint i;\n\tfor(i = 0; i < ARRAY_SIZE(aArray); i++)\n\t\taArray[i].Update();\n}\n\nvoid\nCPlaneBanners::Render(void)\n{\n\tint i;\n\tfor(i = 0; i < ARRAY_SIZE(aArray); i++)\n\t\taArray[i].Render();\n}\n\nvoid\nCPlaneBanners::RegisterPoint(CVector pos, uint32 id)\n{\n\taArray[id].RegisterPoint(pos);\n}\n\nbool CSmokeTrails::CigOn = false;\nCSmokeTrail CSmokeTrails::aSmoke[3];\n\nRwImVertexIndex SmokeTrailIndices[32] = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8,\n9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16 };\n\nfloat RandomSmoke[16] = { 10.0f, 5.0f, -1.0f, -9.0f, -7.0f, -1.0f, 0.0f, 3.0f, 6.0f, 7.0f, 4.0f, 2.0f,\n5.0f, 7.0f };\n\nuint8 ScrollCharSet[59][5] = {\n\t{ 0x00, 0x00, 0x00, 0x00, 0x00 }, // ' '\n\t{ 0x00, 0x00, 0x1D, 0x00, 0x00 }, // '!'\n\t{ 0x00, 0x00, 0x00, 0x00, 0x00 }, // '\"'\n\t{ 0x0A, 0x1F, 0x0A, 0x1F, 0x0A }, // '#'\n\t{ 0x00, 0x09, 0x1F, 0x12, 0x00 }, // '$'\n\t{ 0x18, 0x18, 0x00, 0x03, 0x03 }, // '%'\n\t{ 0x00, 0x00, 0x00, 0x00, 0x00 }, // '&'\n\t{ 0x00, 0x00, 0x00, 0x00, 0x00 }, // '''\n\t{ 0x01, 0x02, 0x04, 0x08, 0x10 }, // '('\n\t{ 0x00, 0x00, 0x18, 0x00, 0x00 }, // ')'\n\t{ 0x15, 0x04, 0x1F, 0x04, 0x15 }, // '*'\n\t{ 0x00, 0x04, 0x0E, 0x04, 0x00 }, // '+'\n\t{ 0x00, 0x00, 0x03, 0x00, 0x00 }, // ','\n\t{ 0x00, 0x04, 0x04, 0x04, 0x00 }, // '-'\n\t{ 0x00, 0x00, 0x01, 0x00, 0x00 }, // '.'\n\t{ 0x00, 0x00, 0x00, 0x00, 0x00 }, // '/'\n\t{ 0x0E, 0x11, 0x11, 0x11, 0x0E }, // '0'\n\t{ 0x01, 0x09, 0x1F, 0x01, 0x01 }, // '1'\n\t{ 0x03, 0x15, 0x15, 0x15, 0x09 }, // '2'\n\t{ 0x11, 0x11, 0x15, 0x15, 0x0A }, // '3'\n\t{ 0x02, 0x06, 0x0A, 0x1F, 0x02 }, // '4'\n\t{ 0x1D, 0x15, 0x15, 0x15, 0x12 }, // '5'\n\t{ 0x0E, 0x15, 0x15, 0x15, 0x12 }, // '6'\n\t{ 0x18, 0x10, 0x13, 0x14, 0x18 }, // '7'\n\t{ 0x0A, 0x15, 0x15, 0x15, 0x0A }, // '8'\n\t{ 0x08, 0x15, 0x15, 0x15, 0x0E }, // '9'\n\t{ 0x00, 0x00, 0x0A, 0x00, 0x00 }, // ':'\n\t{ 0x18, 0x18, 0x00, 0x03, 0x03 }, // ';'\n\t{ 0x04, 0x08, 0x1F, 0x08, 0x04 }, // '<'\n\t{ 0x00, 0x0A, 0x0A, 0x0A, 0x00 }, // '='\n\t{ 0x04, 0x02, 0x1F, 0x02, 0x04 }, // '>'\n\t{ 0x10, 0x10, 0x15, 0x14, 0x1D }, // '?'\n\t{ 0x00, 0x1C, 0x14, 0x1C, 0x00 }, // '@'\n\t{ 0x0F, 0x12, 0x12, 0x12, 0x0F }, // 'A'\n\t{ 0x1F, 0x15, 0x15, 0x15, 0x0A }, // 'B'\n\t{ 0x0E, 0x11, 0x11, 0x11, 0x0A }, // 'C'\n\t{ 0x1F, 0x11, 0x11, 0x11, 0x0E }, // 'D'\n\t{ 0x1F, 0x15, 0x15, 0x11, 0x11 }, // 'E'\n\t{ 0x1F, 0x14, 0x14, 0x10, 0x10 }, // 'F'\n\t{ 0x0E, 0x11, 0x15, 0x15, 0x06 }, // 'G'\n\t{ 0x1F, 0x04, 0x04, 0x04, 0x1F }, // 'H'\n\t{ 0x11, 0x11, 0x1F, 0x11, 0x11 }, // 'I'\n\t{ 0x02, 0x01, 0x01, 0x01, 0x1E }, // 'J'\n\t{ 0x1F, 0x04, 0x0C, 0x12, 0x01 }, // 'K'\n\t{ 0x1F, 0x01, 0x01, 0x01, 0x01 }, // 'L'\n\t{ 0x1F, 0x08, 0x06, 0x08, 0x1F }, // 'M'\n\t{ 0x1F, 0x08, 0x04, 0x02, 0x1F }, // 'N'\n\t{ 0x0E, 0x11, 0x11, 0x11, 0x0E }, // 'O'\n\t{ 0x1F, 0x12, 0x12, 0x12, 0x0C }, // 'P'\n\t{ 0x0C, 0x12, 0x12, 0x13, 0x0D }, // 'Q'\n\t{ 0x1F, 0x14, 0x14, 0x16, 0x09 }, // 'R'\n\t{ 0x09, 0x15, 0x15, 0x15, 0x02 }, // 'S'\n\t{ 0x10, 0x10, 0x1F, 0x10, 0x10 }, // 'T'\n\t{ 0x1E, 0x01, 0x01, 0x01, 0x1E }, // 'U'\n\t{ 0x1C, 0x02, 0x01, 0x02, 0x1C }, // 'V'\n\t{ 0x1E, 0x01, 0x06, 0x01, 0x1E }, // 'W'\n\t{ 0x11, 0x0A, 0x04, 0x0A, 0x11 }, // 'X'\n\t{ 0x18, 0x04, 0x03, 0x04, 0x18 }, // 'Y'\n\t{ 0x11, 0x13, 0x15, 0x19, 0x11 }  // 'Z'\n};\n\n// ---------- CMovingThings ----------\nenum eScrollBarTypes\n{\n\tSCROLL_ARENA_STRING\n};\n\nCScrollBar    aScrollBars[1];\n\nCMovingThing CMovingThings::StartCloseList;\nCMovingThing CMovingThings::EndCloseList;\nint16 CMovingThings::Num;\nCMovingThing CMovingThings::aMovingThings[NUMMOVINGTHINGS];\n\nint32 CScrollBar::TonightsEvent;\n \nvoid CMovingThings::Init()\n{\n\tStartCloseList.m_pNext = &CMovingThings::EndCloseList;\n\tStartCloseList.m_pPrev = nil;\n\tEndCloseList.m_pNext = nil;\n\tEndCloseList.m_pPrev = &CMovingThings::StartCloseList;\n\n\tCPlaneTrails::Init();\n\tCSmokeTrails::Init();\n\tCPlaneBanners::Init();\n\tCPointLights::Init();\n\n\tNum = 0;\n\n\tfor (int32 i = 0; i < NUMMOVINGTHINGS; i++) {\n\t\taMovingThings[i].m_nType = 0;\n\t\taMovingThings[i].m_farAway = 0;\n\t}\n\n\tfor (int i = 0; i < NUMSECTORS_X; i++) {\n\t\tfor (int j = 0; j < NUMSECTORS_Y; j++) {\n\t\t\tfor (CPtrNode *pNode = CWorld::GetSector(i, j)->m_lists[ENTITYLIST_BUILDINGS].first; pNode; pNode = pNode->next) {\n\t\t\t\tCEntity *pEntity = (CEntity *)pNode->item;\n\t\t\t\tPossiblyAddThisEntity(pEntity);\n\t\t\t}\n\t\t}\n\t}\n\n\tfor (int32 i = 0; i < NUM_LEVELS; i++) {\n\t\tfor (CPtrNode *pNode = CWorld::GetBigBuildingList((eLevelName)i).first; pNode; pNode = pNode->next) {\n\t\t\tCEntity *pEntity = (CEntity *)pNode->item;\n\t\t\tPossiblyAddThisEntity(pEntity);\n\t\t}\n\t}\n\n\tCEscalators::Init();\n\taScrollBars[0].Init(CVector(-1069.209f, 1320.126f, 18.848f), CVector(-1069.209f, 1342.299f, 22.612f), SCROLL_ARENA_STRING, 128, 255, 0, 0.3f);\n}\n\nvoid CMovingThings::Shutdown()\n{\n\t\n\taScrollBars[0].SetVisibility(false);\n\tCEscalators::Shutdown();\n}\n\nvoid CMovingThings::Update()\n{\n\tCPlaneBanners::Update();\n\tCPlaneTrails::Update();\n\tCEscalators::Update();\n\n\tconst int TIME_SPAN = 8; // frames to process all aMovingThings\n\n\tint16 i;\n\n\tint block = CTimer::GetFrameCounter() % TIME_SPAN;\n\n\tfor (i = (block * NUMMOVINGTHINGS) / TIME_SPAN; i < ((block + 1) * NUMMOVINGTHINGS) / TIME_SPAN; i++) {\n\t\tif (aMovingThings[i].m_farAway == 1)\n\t\t\taMovingThings[i].Update();\n\t}\n\n\tfor (i = 0; i < CMovingThings::Num; i++) {\n\t\tif (aMovingThings[i].m_farAway == 0)\n\t\t\taMovingThings[i].Update();\n\t}\n\n\tfor (i = 0; i < ARRAY_SIZE(aScrollBars); ++i)\n\t{\n\t\tif (aScrollBars[i].IsVisible() || (CTimer::GetFrameCounter() + i) % 8 == 0)\n\t\t\taScrollBars[i].Update();\n\t}\n}\n\nvoid CMovingThings::Render()\n{\n\tPUSH_RENDERGROUP(\"CMovingThings::Render\");\n\tCSmokeTrails::Update();\n\n\tint i;\n\tfor (i = 0; i < ARRAY_SIZE(aScrollBars); ++i)\n\t{\n\t\tif (aScrollBars[i].IsVisible())\n\t\t\taScrollBars[i].Render();\n\t}\n\n\tCPlaneTrails::Render();\n\tCSmokeTrails::Render();\n\tCPlaneBanners::Render();\n\tPOP_RENDERGROUP();\n}\n\nvoid CMovingThings::RegisterOne(CEntity *pEnt, uint16 nType) {\n\tif (Num >= NUMMOVINGTHINGS)\n\t\treturn;\n\n\taMovingThings[Num].m_pEntity = pEnt;\n\taMovingThings[Num].m_nType = nType;\n\taMovingThings[Num].m_farAway = 0;\n\taMovingThings[Num].m_vecPosn = pEnt->GetPosition();\n\taMovingThings[Num].AddToList(&CMovingThings::StartCloseList);\n\tNum++;\n}\n\nvoid CMovingThings::PossiblyAddThisEntity(CEntity *pEnt) {\n\tif (pEnt->GetModelIndex() == MI_LIGHTBEAM) {\n\t\tRegisterOne(pEnt, 1);\n\t}\n\telse if (pEnt->GetModelIndex() == MI_AIRPORTRADAR) {\n\t\tRegisterOne(pEnt, 2);\n\t}\n\telse if (pEnt->GetModelIndex() == MI_MALLFAN || pEnt->GetModelIndex() == MI_HOTELFAN_NIGHT\n\t\t|| pEnt->GetModelIndex() == MI_HOTELFAN_DAY || pEnt->GetModelIndex() == MI_HOTROOMFAN) {\n\t\tRegisterOne(pEnt, 3);\n\t}\n\telse if (pEnt->GetModelIndex() == MI_BLIMP_NIGHT || pEnt->GetModelIndex() == MI_BLIMP_DAY) {\n\t\tRegisterOne(pEnt, 4);\n\t}\n}\n\n// ---------- CMovingThing ----------\nstatic float maxUpdateDists[5] = { 100.0f, 1500.0f, 400.0f, 100.0f, 2000.0f };\n\nvoid CMovingThing::Update()\n{\n\tswitch (m_nType) {\n\tcase 1: {\n\t\tfloat angle = (CTimer::GetTimeInMilliseconds() % 0x3FFF) * TWOPI / 0x3FFF;\n\t\tfloat s = Sin(angle);\n\t\tfloat c = Cos(angle);\n\t\tm_pEntity->GetRight() = CVector(-s, c, 0.0f);\n\t\tm_pEntity->GetForward() = CVector(0.0f, 0.0f, 1.0f);\n\t\tm_pEntity->GetUp() = CVector(c, s, 0.0f);\n\n\t\tif (CClock::GetHours() >= 20 || CClock::GetHours() < 5) {\n\t\t\tif (Abs(TheCamera.GetPosition().x - m_pEntity->GetPosition().x) < 600.0f &&\n\t\t\t\tAbs(TheCamera.GetPosition().y - m_pEntity->GetPosition().y) < 600.0f) {\n\t\t\t\tCVector delta = m_pEntity->GetPosition() - TheCamera.GetPosition();\n\t\t\t\tdelta /= delta.Magnitude();\n\n\t\t\t\tif (DotProduct(delta, CVector(c, s, 0.0f)) < -0.92f) {\n\t\t\t\t\tCVector coors = m_pEntity->GetPosition() - 10.0f * delta;\n\t\t\t\t\tCCoronas::RegisterCorona(43, 128, 128, 100, 255, coors, 70.0f, 600.0f, 0.0f, CCoronas::TYPE_STAR, CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\t\tbreak;\n\tcase 2: {\n\t\tfloat angle = (CTimer::GetTimeInMilliseconds() % 0x7FF) * TWOPI / 0x7FF;\n\t\tfloat s = Sin(angle);\n\t\tfloat c = Cos(angle);\n\t\tm_pEntity->GetRight() = CVector(c, s, 0.0f);\n\t\tm_pEntity->GetForward() = CVector(-s, c, 0.0f);\n\t\tm_pEntity->GetUp() = CVector(0.0f, 0.0f, 1.0f);\n\t}\n\t\tbreak;\n\tcase 3: {\n\t\tfloat angle = (CTimer::GetTimeInMilliseconds() % 0x3FF) * TWOPI / 0x3FF;\n\t\tfloat s = Sin(angle);\n\t\tfloat c = Cos(angle);\n\t\tm_pEntity->GetRight() = CVector(c, s, 0.0f);\n\t\tm_pEntity->GetForward() = CVector(-s, c, 0.0f);\n\t\tm_pEntity->GetUp() = CVector(0.0f, 0.0f, 1.0f);\n\t}\n\t\tbreak;\n\tcase 4: {\n\t\tfloat angle = (CTimer::GetTimeInMilliseconds() % 0x3FFFF) * TWOPI / 0x3FFFF;\n\t\tfloat s = Sin(angle);\n\t\tfloat c = Cos(angle);\n\t\tm_pEntity->GetRight() = CVector(-c, -s, 0.0f);\n\t\tm_pEntity->GetForward() = CVector(s, -c, 0.0f);\n\t\tm_pEntity->GetUp() = CVector(0.0f, 0.0f, 1.0f);\n\t\tm_pEntity->SetPosition(CVector(350.0f * c - 465.0f, 350.0f * s + 1163.0f, 260.0f));\n\t}\n\t\tbreak;\n\tdefault:\n\t\tbreak;\n\t}\n\n\tm_pEntity->GetMatrix().UpdateRW();\n\tm_pEntity->UpdateRwFrame();\n\t\n\tif (SQR(m_pEntity->GetPosition().x - TheCamera.GetPosition().x) + SQR(m_pEntity->GetPosition().y - TheCamera.GetPosition().y) < SQR(maxUpdateDists[m_nType])) {\n\t\tif (m_farAway == 1) {\n\t\t\tAddToList(&CMovingThings::StartCloseList);\n\t\t\tm_farAway = 0;\n\t\t}\n\t}\n\telse {\n\t\tif (m_farAway == 0) {\n\t\t\tRemoveFromList();\n\t\t\tm_farAway = 1;\n\t\t}\n\t}\n}\n\nvoid CMovingThing::AddToList(CMovingThing *pThing)\n{\n\tm_pNext = pThing->m_pNext;\n\tm_pPrev = pThing;\n\tpThing->m_pNext = this;\n\tm_pNext->m_pPrev = this;\n}\n\nvoid CMovingThing::RemoveFromList()\n{\n\tm_pNext->m_pPrev = m_pPrev;\n\tm_pPrev->m_pNext = m_pNext;\n}\n\nint16 CMovingThing::SizeList()\n{\n\tCMovingThing *next = m_pNext;\n\tint16 count = 0;\n\n\twhile (next != nil) {\n\t\tnext = next->m_pNext;\n\t\tcount++;\n\t}\n\n\treturn count;\n}\n\nchar String_Time[] = \"THE TIME IS 12:34    \";\nconst char* FindTimeMessage()\n{\n\tString_Time[12] = '0' + CClock::GetHours() / 10;\n\tString_Time[13] = '0' + CClock::GetHours() % 10;\n\tString_Time[15] = '0' + CClock::GetMinutes() / 10;\n\tString_Time[16] = '0' + CClock::GetMinutes() % 10;\n\treturn String_Time;\n}\n\n// ---------- CScrollBar ----------\nvoid CScrollBar::Init(CVector pos1, CVector pos2, uint8 type, uint8 red, uint8 green, uint8 blue, float scale)\n{\n\tfor (int i = 0; i < ARRAY_SIZE(m_MessageBar); ++i)\n\t\tm_MessageBar[i] = 0;\n\n\tm_pMessage = \". \";\n\tm_MessageCurrentChar = 0;\n\tm_MessageLength = strlen(m_pMessage);\n\n\tm_Counter  = 0;\n\tm_bVisible = false;\n\tm_Position = pos1;\n\tm_Type     = type;\n\tm_Size.x   = (pos2.x - pos1.x) * 0.025f;\n\tm_Size.y   = (pos2.y - pos1.y) * 0.025f;\n\tm_Size.z   = (pos2.z - pos1.z) * 0.2f;\n\tm_uRed     = red;\n\tm_uGreen   = green;\n\tm_uBlue    = blue;\n\tm_fScale   = scale;\n}\n\nvoid CScrollBar::Update()\n{\n\tfloat distanceFromCamera = (TheCamera.GetPosition() - m_Position).Magnitude();\n\tif (distanceFromCamera > 100.0f)\n\t{\n\t\tm_bVisible = false;\n\t\treturn;\n\t}\n\n\tm_bVisible = true;\n\n\tif (distanceFromCamera < 75.0f)\n\t\tm_fIntensity = 1.0f;\n\telse\n\t\tm_fIntensity = 1.0f - 4.0f * (distanceFromCamera - 75.0f) / 100.0f;\n\n\tm_Counter = (m_Counter + 1) % 8;\n\t\t\n\t// if message is fully printed, load up the next one\n\tif (m_Counter == 0 && ++m_MessageCurrentChar >= m_MessageLength)\n\t{\n\t\tconst char* previousMessage = m_pMessage;\n\t\tif (m_Type == SCROLL_ARENA_STRING) {\n\t\t\twhile (previousMessage == m_pMessage)\n\t\t\t{\n\t\t\t\tswitch (CGeneral::GetRandomNumber() % 4)\n\t\t\t\t{\n\t\t\t\tcase 0:\n\t\t\t\t\tswitch (TonightsEvent) {\n\t\t\t\t\tcase 0:\n\t\t\t\t\t\tm_pMessage = \"MAIN EVENT TONIGHT: CAR RACING . . .   \";\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 1:\n\t\t\t\t\t\tm_pMessage = \"MAIN EVENT TONIGHT: DESTRUCTION DERBY . . .   \";\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 2:\n\t\t\t\t\t\tm_pMessage = \"MAIN EVENT TONIGHT: BIKE RACING . . .   \";\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase 1:\n\t\t\t\t\tswitch (TonightsEvent) {\n\t\t\t\t\tcase 0:\n\t\t\t\t\t\tm_pMessage = \"FOR TICKETS TO THE HOT RING EVENT CALL 555-3764 . . .   \";\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 1:\n\t\t\t\t\t\tm_pMessage = \"FOR TICKETS TO THE BLOOD RING EVENT CALL 555-3765 . . .   \";\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 2:\n\t\t\t\t\t\tm_pMessage = \"FOR TICKETS TO THE DIRT RING EVENT CALL 555-3766 . . .   \";\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase 2:\n\t\t\t\t\tm_pMessage = \"HYMAN MEMORIAL STADIUM. HOME TO SOME OF THE BIGGEST EVENTS OF\"\n\t\t\t\t\t\t\" THE WESTERN HEMISPHERE. ALSO AVAILABLE FOR CHILDREN PARTIES. . . \";\n\t\t\t\t\tbreak;\n\t\t\t\tcase 3:\n\t\t\t\t\tm_pMessage = FindTimeMessage();\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tm_MessageLength = (uint32)strlen(m_pMessage);\n\t\tm_MessageCurrentChar = 0;\n\t}\n\n\t// Scroll\n\tfor (int i = 0; i < ARRAY_SIZE(m_MessageBar)-1; i++)\n\t\tm_MessageBar[i] = m_MessageBar[i + 1];\n\tm_MessageBar[ARRAY_SIZE(m_MessageBar)-1] = m_Counter < 5 ? ScrollCharSet[m_pMessage[m_MessageCurrentChar] - ' '][m_Counter] : 0;\n\n\t// Introduce some random displaying glitches; signs aren't supposed to be perfect :P\n\tswitch (CGeneral::GetRandomNumber() & 0xFF)\n\t{\n\tcase 0x0D: m_MessageBar[ARRAY_SIZE(m_MessageBar)-1] = 0;                 break;\n\tcase 0xE3: m_MessageBar[ARRAY_SIZE(m_MessageBar)-1] = 0xE3;              break;\n\tcase 0x64: m_MessageBar[ARRAY_SIZE(m_MessageBar)-1] = ~m_MessageBar[ARRAY_SIZE(m_MessageBar)-1]; break;\n\t}\n}\n\nvoid CScrollBar::Render()\n{\n\tif (!TheCamera.IsSphereVisible(m_Position, 2.0f * 20.0f * (ABS(m_Size.x) + ABS(m_Size.y))))\n\t\treturn;\n\n\tCSprite::InitSpriteBuffer();\n\n\t// Calculate intensity of colours\n\tuint8 r = m_fIntensity * m_uRed;\n\tuint8 g = m_fIntensity * m_uGreen;\n\tuint8 b = m_fIntensity * m_uBlue;\n\n\t// Set render states\n\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE,      (void*)FALSE);\n\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);\n\tRwRenderStateSet(rwRENDERSTATESRCBLEND,          (void*)rwBLENDONE);\n\tRwRenderStateSet(rwRENDERSTATEDESTBLEND,         (void*)rwBLENDONE);\n\tRwRenderStateSet(rwRENDERSTATETEXTUREFILTER,     (void*)rwFILTERLINEAR);\n\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER,     RwTextureGetRaster(gpCoronaTexture[0]));\n\tRwRenderStateSet(rwRENDERSTATEZTESTENABLE,       (void*)TRUE);\n\n\tCVector coronaCoord, screenCoord;\n\tfloat screenW, screenH;\n\tfor (int i = 1; i < ARRAY_SIZE(m_MessageBar); ++i)\n\t{\n\t\tfor (int j = 0; j < 5; ++j)\n\t\t{\n\t\t\tcoronaCoord.x = m_Position.x + m_Size.x * i;\n\t\t\tcoronaCoord.y = m_Position.y + m_Size.y * i;\n\t\t\tcoronaCoord.z = m_Position.z + m_Size.z * j;\n\n\t\t\t// Render main coronas\n\t\t\tif (m_MessageBar[i] & (1 << j))\n\t\t\t{\n\t\t\t\tif (CSprite::CalcScreenCoors(coronaCoord, &screenCoord, &screenW, &screenH, true))\n\t\t\t\t{\n\t\t\t\t\tCSprite::RenderBufferedOneXLUSprite(\n\t\t\t\t\t\tscreenCoord.x, screenCoord.y, screenCoord.z,\n\t\t\t\t\t\tscreenW * m_fScale, screenH * m_fScale,\n\t\t\t\t\t\tr, g, b,\n\t\t\t\t\t\t255, 1.0f / screenCoord.z, 255);\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Render smaller and faded coronas for a trailing effect\n\t\t\telse if (m_MessageBar[i - 1] & (1 << j))\n\t\t\t{\n\t\t\t\tif (CSprite::CalcScreenCoors(coronaCoord, &screenCoord, &screenW, &screenH, true))\n\t\t\t\t{\n\t\t\t\t\tCSprite::RenderBufferedOneXLUSprite(\n\t\t\t\t\t\tscreenCoord.x, screenCoord.y, screenCoord.z,\n\t\t\t\t\t\tscreenW * m_fScale * 0.8f,\n\t\t\t\t\t\tscreenH * m_fScale * 0.8f,\n\t\t\t\t\t\tr / 2,\n\t\t\t\t\t\tg / 2,\n\t\t\t\t\t\tb / 2,\n\t\t\t\t\t\t255, 1.0f / screenCoord.z, 255);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tCSprite::FlushSpriteBuffer();\n}\n\nvoid\nCSmokeTrail::RegisterPoint(CVector regPosition, float opacity) {\n\tbool bAddedNewPoint = false;\n\n\tif (m_time[0] && CTimer::GetTimeInMilliseconds() - m_time[0] > 150) {\n\t\tbAddedNewPoint = true;\n\t\tfor (int32 i = 15; i > 0; i--) {\n\t\t\tm_pos[i] = m_pos[i - 1];\n\t\t\tm_time[i] = m_time[i - 1];\n\t\t\tm_opacity[i] = m_opacity[i - 1];\n\t\t}\n\t\t++m_seed;\n\t}\n\tm_pos[0] = regPosition;\n\n\tif (bAddedNewPoint || !m_time[0]) {\n\t\tm_time[0] = CTimer::GetTimeInMilliseconds();\n\t\tfloat density = 0.1f / (m_pos[1] - m_pos[2]).Magnitude();\n\t\tm_opacity[1] = opacity * Min(density, 1.0f);\n\t}\n\tm_opacity[0] = 0.0f;\n}\n\nvoid\nCSmokeTrail::Init(int num) {\n\tfor (int32 i = 0; i < 16; i++)\n\t\tm_time[i] = 0;\n\tm_seed = num * 2;\n}\n\nvoid\nCSmokeTrails::Init(void) {\n\tfor (int32 i = 0; i < 3; i++)\n\t\taSmoke[i].Init(i);\n}\n\nvoid\nCSmokeTrails::Render(void) {\n\tfor (int32 i = 0; i < 3; i++)\n\t\taSmoke[i].Render();\n}\n\nvoid\nCSmokeTrail::Render(void) {\n\tint numVerts = 0;\n\n\tif (TheCamera.IsSphereVisible(m_pos[0], 10.0f)) {\n\t\tfor (int32 i = 0; i < 16; i++) {\n\t\t\tint timeSinceSpawned = CTimer::GetTimeInMilliseconds() - m_time[i];\n\n\t\t\tif (timeSinceSpawned > 2250)\n\t\t\t\tm_time[i] = 0;\n\n\t\t\tif (m_time[i]) {\n\t\t\t\tint alpha = (1.0f - timeSinceSpawned / 2250.0f) * 110.0f * m_opacity[i];\n\t\t\t\tfloat offset = timeSinceSpawned * CWeather::Wind * 0.0001f;\n\t\t\t\tfloat posX = (m_pos[i].x + timeSinceSpawned * RandomSmoke[(i - m_seed) & 0xF] * 0.00001f) - offset;\n\t\t\t\tfloat posY = (m_pos[i].y + timeSinceSpawned * RandomSmoke[(i - m_seed + 5) & 0xF] * 0.00001f) - offset;\n\t\t\t\tfloat posZ = m_pos[i].z + timeSinceSpawned * 0.0004f;\n\t\t\t\tRwIm3DVertexSetRGBA(&TempBufferRenderVertices[i], 200, 200, 200, alpha);\n\t\t\t\tRwIm3DVertexSetPos(&TempBufferRenderVertices[i], posX, posY, posZ);\n\t\t\t\tnumVerts++;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (numVerts > 1) {\n\t\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);\n\t\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);\n\t\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);\n\t\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil);\n\n\t\tif (RwIm3DTransform(TempBufferRenderVertices, numVerts, nil, rwIM3D_VERTEXXYZ | rwIM3D_VERTEXRGBA)) {\n\t\t\tRwIm3DRenderIndexedPrimitive(rwPRIMTYPEPOLYLINE, SmokeTrailIndices, 2 * (numVerts - 1));\n\t\t\tRwIm3DEnd();\n\t\t}\n\t}\n}\n\nvoid\nCSmokeTrails::Update(void) {\n\n\tif (!CSmokeTrails::CigOn || TheCamera.Using1stPersonWeaponMode() || !FindPlayerPed() ||\n\t\tFindPlayerVehicle() || CCutsceneMgr::IsRunning() || !FindPlayerPed()->GetClump())\n\t\treturn;\n\n\tRwV3d startPos = { 0.026f, 0.15f, 0.02f };\n\tRwV3d endPos = { 0.026f, 0.05f, 0.02f };\n\n\tRpHAnimHierarchy *hier = GetAnimHierarchyFromSkinClump(FindPlayerPed()->GetClump());\n\tint32 idx = RpHAnimIDGetIndex(hier, ConvertPedNode2BoneTag(PED_HEAD));\n\tRwMatrix *head = &RpHAnimHierarchyGetMatrixArray(hier)[idx];\n\tRwV3dTransformPoints(&startPos, &startPos, 1, head);\n\tRwV3dTransformPoints(&endPos, &endPos, 1, head);\n\n\taSmoke[0].RegisterPoint(startPos, 1.0f);\n\taSmoke[1].RegisterPoint(startPos, 0.75f);\n\taSmoke[2].RegisterPoint(startPos, 0.5f);\n\n\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);\n\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);\n\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);\n\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil);\n\n\tRwIm3DVertexSetRGBA(&TempBufferRenderVertices[0], 255, 255, 255, 255);\n\tRwIm3DVertexSetPos(&TempBufferRenderVertices[0], startPos.x, startPos.y, startPos.z);\n\tRwIm3DVertexSetRGBA(&TempBufferRenderVertices[1], 255, 255, 255, 255);\n\tRwIm3DVertexSetPos(&TempBufferRenderVertices[1], endPos.x, endPos.y, endPos.z);\n\n\tif (RwIm3DTransform(TempBufferRenderVertices, 2, nil, rwIM3D_VERTEXXYZ | rwIM3D_VERTEXRGBA)) {\n\t\tRwIm3DRenderIndexedPrimitive(rwPRIMTYPEPOLYLINE, SmokeTrailIndices, 2);\n\t\tRwIm3DEnd();\n\t}\n}\n\nCEscalator CEscalators::aEscalators[NUM_ESCALATORS];\nint32 CEscalators::NumEscalators;\n\nCEscalator::CEscalator() {\n\tm_bIsActive = false;\n\n\tfor (int i = 0; i < 24; i++) {\n\t\tm_pSteps[i] = nil;\n\t}\n}\n\nvoid\nCEscalator::AddThisOne(CVector pos0, CVector pos1, CVector pos2, CVector pos3, bool b_isMovingDown) {\n\tm_pos0 = pos0;\n\tm_pos1 = pos1;\n\tm_pos2 = pos2;\n\tm_pos3 = pos3;\n\n\tfloat escalatorStepHeight = CModelInfo::GetModelInfo(MI_ESCALATORSTEP)->GetColModel()->boundingBox.max.z;\n\tm_pos0.z -= escalatorStepHeight;\n\tm_pos1.z -= escalatorStepHeight;\n\tm_pos2.z -= escalatorStepHeight;\n\tm_pos3.z -= escalatorStepHeight;\n\n\tfloat magnitudes[3];\n\tmagnitudes[0] = (m_pos0 - m_pos1).Magnitude();\n\tmagnitudes[1] = (m_pos1 - m_pos2).Magnitude();\n\tmagnitudes[2] = (m_pos2 - m_pos3).Magnitude();\n\n\tfloat length = magnitudes[0] + magnitudes[1] + magnitudes[2];\n\n\tm_lowerEnd = magnitudes[0] / length;\n\tm_upperEnd = (magnitudes[0] + magnitudes[1]) / length;\n\n\tm_stepsCount = Min(24.0f, length / 0.6f);\n\n\tCVector direction(m_pos0.x - m_pos1.x, m_pos0.y - m_pos1.y, 0.0f);\n\tdirection.Normalise();\n\n\tm_matrix.GetUp() = CVector(0.0f, 0.0f, 1.0f);\n\tm_matrix.GetForward() = CVector(direction.x, direction.y, 0.0f);\n\tm_matrix.GetRight() = CVector(direction.y, -direction.x, 0.0f);\n\tm_matrix.GetPosition() = CVector(0.0f, 0.0f, 0.0f);\n\n\tm_bIsMovingDown = b_isMovingDown;\n\n\tm_midPoint = (m_pos0 + m_pos3) / 2.0f;\n\n\tm_radius = (m_pos0 - m_midPoint).Magnitude();\n}\n\nvoid\nCEscalator::Update(void) {\n\tif (!m_bIsActive) {\n\t\tif ((TheCamera.GetPosition() - m_midPoint).Magnitude() < 25.0f) {\n\t\t\tif (TheCamera.IsSphereVisible(m_midPoint, m_radius) && (m_stepsCount + 10 < CPools::GetObjectPool()->GetNoOfFreeSpaces())) { \n\t\t\t\tm_bIsActive = true;\n\t\t\t\tfor (int i = 0; i < m_stepsCount; i++) {\n\t\t\t\t\tm_pSteps[i] = new CObject(MI_ESCALATORSTEP, TRUE);\n\t\t\t\t\tif (m_pSteps[i]) {\n\t\t\t\t\t\tm_pSteps[i]->SetPosition(m_pos1);\n\t\t\t\t\t\tCWorld::Add(m_pSteps[i]);\n\t\t\t\t\t\tm_pSteps[i]->ObjectCreatedBy = CONTROLLED_SUB_OBJECT;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (m_bIsActive) {\n\t\tfloat time = (CTimer::GetTimeInMilliseconds() % 16384) / 16384.0f;\n\t\tfor (int i = 0; i < m_stepsCount; i++) {\n\t\t\tif (m_pSteps[i]) {\n\t\t\t\tfloat t = i / (float)m_stepsCount + time;\n\n\t\t\t\tif (t > 1.0f)\n\t\t\t\t\tt -= 1.0f;\n\n\t\t\t\tif (m_bIsMovingDown)\n\t\t\t\t\tt = 1.0f - t;\n\n\t\t\t\tCVector oldPosition = m_pSteps[i]->GetPosition();\n\t\t\t\tm_pSteps[i]->GetMatrix() = m_matrix;\n\n\t\t\t\tCVector newPosition;\n\t\t\t\tif (t < m_lowerEnd) {\n\t\t\t\t\tfloat ratio = t / m_lowerEnd;\n\t\t\t\t\tnewPosition = (ratio * m_pos1) + ((1.0f - ratio) * m_pos0);\n\t\t\t\t}\n\t\t\t\telse if (t < m_upperEnd) {\n\t\t\t\t\tfloat ratio = (t - m_lowerEnd) / (m_upperEnd - m_lowerEnd);\n\t\t\t\t\tnewPosition = (ratio * m_pos2) + ((1.0f - ratio) * m_pos1);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tfloat ratio = (t - m_upperEnd) / (1.0f - m_upperEnd);\n\t\t\t\t\tnewPosition = (ratio * m_pos3) + ((1.0f - ratio) * m_pos2);\n\t\t\t\t}\n\n\t\t\t\tm_pSteps[i]->SetPosition(newPosition);\n\t\t\t\tm_pSteps[i]->m_vecMoveSpeed = (newPosition - oldPosition) / Max(CTimer::GetTimeStep(), 1.0f);\n\t\t\t\tm_pSteps[i]->GetMatrix().UpdateRW();\n\t\t\t\tm_pSteps[i]->UpdateRwFrame();\n\t\t\t}\n\t\t\tif ((TheCamera.GetPosition() - m_midPoint).Magnitude() > 28.0f || !TheCamera.IsSphereVisible(m_midPoint, m_radius))\n\t\t\t\tSwitchOff();\n\t\t}\n\t}\n}\n\nbool deletingEscalator;\n\nvoid\nCEscalator::SwitchOff(void) {\n\tif (m_bIsActive) {\n\t\tfor (int i = 0; i < m_stepsCount; i++) {\n\t\t\tif (m_pSteps[i]) {\n\t\t\t\tCWorld::Remove(m_pSteps[i]);\n\t\t\t\tdeletingEscalator = true;\n\t\t\t\tdelete m_pSteps[i];\n\t\t\t\tm_pSteps[i] = nil;\n\t\t\t\tdeletingEscalator = false;\n\t\t\t}\n\t\t}\n\t\tm_bIsActive = false;\n\t}\n}\n\nvoid\nCEscalators::AddOne(CVector pos0, CVector pos1, CVector pos2, CVector pos3, bool b_isMovingDown) {\n\taEscalators[NumEscalators++].AddThisOne(pos0, pos1, pos2, pos3, b_isMovingDown);\n}\n\nvoid\nCEscalators::Init(void) {\n\tShutdown();\n\tNumEscalators = 0;\n\n\tAddOne(CVector(-9.82999f, -938.04498f, 9.4219f), CVector(-8.573f, -938.04498f, 9.4219f),\n\t\tCVector(-0.747f, -938.045f, 15.065f), CVector(0.88f, -938.045f, 15.065f), TRUE);\n\n\tAddOne(CVector(-9.83f, -939.966f, 9.422f), CVector(-8.573f, -939.966f, 9.422f),\n\t\tCVector(-0.747f, -939.966f, 15.065f), CVector(0.880f, -939.966f, 15.065f), FALSE);\n\n\tAddOne(CVector(408.116f, 1058.36f, 18.261f), CVector(408.094f, 1057.04f, 18.261f),\n\t\tCVector(408.116f, 1048.0f, 24.765f), CVector(408.094f, 1046.57f, 24.799f), TRUE);\n\n\tAddOne(CVector(406.195f, 1058.36f, 18.261f), CVector(406.173f, 1057.04f, 18.261f),\n\t\tCVector(406.195f, 1048.0f, 24.729f), CVector(406.173f, 1046.57f, 24.79f), FALSE);\n\n\tAddOne(CVector(421.729f, 1058.3789f, 18.075f), CVector(421.707f, 1057.052f, 18.099f),\n\t\tCVector(421.729f, 1048.016f, 24.604f), CVector(421.707f, 1046.589f, 24.637f), TRUE);\n\n\tAddOne(CVector(419.808f, 1058.378f, 18.099f), CVector(419.786f, 1057.052f, 18.099f),\n\t\tCVector(419.808f, 1048.016f, 24.568f), CVector(419.786f, 1046.589f, 24.637f), FALSE);\n\n\tAddOne(CVector(412.69901f, 1102.729f, 17.569f), CVector(412.72198f, 1104.057f, 17.57f),\n\t\tCVector(412.69901f, 1113.092f, 24.073f), CVector(412.72198f, 1114.3201f, 24.108f), TRUE);\n\n\tAddOne(CVector(414.62f, 1102.729f, 17.569f), CVector(414.64301f, 1104.057f, 17.57f),\n\t\tCVector(414.62f, 1113.092f, 24.037001f), CVector(414.64301f, 1114.3201f, 24.099001f), FALSE);\n\n\tAddOne(CVector(414.64301f, 1145.589f, 17.57f), CVector(414.62f, 1144.261f, 17.569f),\n\t\tCVector(414.64301f, 1135.226f, 24.073999f), CVector(414.62f, 1133.798f, 24.107f), TRUE);\n\n\tAddOne(CVector(412.72198f, 1145.589f, 17.57f), CVector(412.69901f, 1144.261f, 17.569f),\n\t\tCVector(412.72198f, 1135.226f, 24.038f), CVector(412.69901f, 1133.798f, 24.098f), FALSE);\n\n\tAddOne(CVector(406.05099f, 1193.4771f, 18.016001f), CVector(406.07401f, 1194.8051f, 18.017f),\n\t\tCVector(406.05099f, 1203.84f, 24.52f), CVector(406.07401f, 1205.2679f, 24.555f), TRUE);\n\n\tAddOne(CVector(407.97198f, 1193.4771f, 18.016001f), CVector(407.995f, 1194.8051f, 18.017f),\n\t\tCVector(407.97198f, 1203.84f, 24.483999f), CVector(407.995f, 1205.2679f, 24.546f), FALSE);\n\n\tAddOne(CVector(419.659f, 1193.479f, 17.979f), CVector(419.68201f, 1194.807f, 17.98f),\n\t\tCVector(419.659f, 1203.842f, 24.483f), CVector(419.68201f, 1205.27f, 24.518f), TRUE);\n\n\tAddOne(CVector(421.57999f, 1193.479f, 17.979f), CVector(421.603f, 1194.807f, 17.98f),\n\t\tCVector(421.57999f, 1203.842f, 24.447001f), CVector(421.603f, 1205.27f, 24.509001f), FALSE);\n\n\tAddOne(CVector(406.23199f, 1022.857f, 17.917f), CVector(406.23199f, 1024.1851f, 17.917f),\n\t\tCVector(406.23199f, 1033.22f, 24.521f), CVector(406.23199f, 1034.647f, 24.555f), TRUE);\n\n\tAddOne(CVector(408.15302f, 1022.857f, 17.917f), CVector(408.15302f, 1024.1851f, 17.916f),\n\t\tCVector(408.15302f, 1033.22f, 24.486f), CVector(408.15302f, 1034.647f, 24.52f), FALSE);\n\n\tAddOne(CVector(-1506.39f, -813.13f, 13.834f), CVector(-1506.177f, -814.51703f, 13.834f),\n\t\tCVector(-1504.566f, -823.20898f, 19.836f), CVector(-1504.329f, -824.48499f, 19.837f), FALSE);\n\n\tAddOne(CVector(-1481.951f, -859.05402f, 13.834f), CVector(-1482.7791f, -858.22498f, 13.834f),\n\t\tCVector(-1489.03f, -851.974f, 19.836f), CVector(-1489.948f, -851.05701f, 19.837f), TRUE);\n\n\tAddOne(CVector(-1461.743f, -871.35901f, 13.834f), CVector(-1460.62f, -871.69202f, 13.834f),\n\t\tCVector(-1452.144f, -874.20203f, 19.836f), CVector(-1450.9f, -874.57098f, 19.837f), FALSE);\n\n\tAddOne(CVector(-1409.889f, -871.41498f, 13.834f), CVector(-1411.0129f, -871.74701f, 13.834f),\n\t\tCVector(-1419.489f, -874.258f, 19.836f), CVector(-1420.733f, -874.62701f, 19.837f), TRUE);\n\n\tAddOne(CVector(-1389.577f, -858.89301f, 13.834f), CVector(-1388.7271f, -858.08698f, 13.834f),\n\t\tCVector(-1382.314f, -852.00201f, 19.836f), CVector(-1381.373f, -851.10797f, 19.837f), FALSE);\n\n\tAddOne(CVector(-1364.981f, -813.13f, 13.834f), CVector(-1365.204f, -814.28003f, 13.834f),\n\t\tCVector(-1366.891f, -822.95801f, 19.83f), CVector(-1367.139f, -824.23199f, 19.837f), TRUE);\n\n\tfor (int i = 0; i < NUM_ESCALATORS; i++) {\n\t\taEscalators[i].SwitchOff();\n\t}\n}\n\nvoid\nCEscalators::Update(void) {\n\tif (CReplay::IsPlayingBack())\n\t\treturn;\n\n\tfor (int i = 0; i < NUM_ESCALATORS; i++) {\n\t\taEscalators[i].Update();\n\t}\n}\n\nvoid\nCEscalators::Shutdown(void) {\n\tfor (int i = 0; i < NUM_ESCALATORS; i++) {\n\t\taEscalators[i].SwitchOff();\n\t}\n\tNumEscalators = 0;\n}\n\n\nCScriptPath CScriptPaths::aArray[3];\n\nvoid CScriptPath::FindCoorsFromDistanceOnPath(float t, float *pX, float *pY, float *pZ)\n{\n\tint32 i;\n\tfor (i = 0; m_pNode[i + 1].t < t; i++)\n\t\tif (i == m_numNodes - 1) {\n\t\t\t// don't go beyond last node\n\t\t\t*pX = m_pNode[m_numNodes - 1].p.x;\n\t\t\t*pY = m_pNode[m_numNodes - 1].p.y;\n\t\t\t*pZ = m_pNode[m_numNodes - 1].p.z;\n\t\t\treturn;\n\t\t}\n\tfloat f = (t - m_pNode[i].t) / (m_pNode[i + 1].t - m_pNode[i].t);\n\t*pX = (1.0f - f)*m_pNode[i].p.x + f*m_pNode[i + 1].p.x;\n\t*pY = (1.0f - f)*m_pNode[i].p.y + f*m_pNode[i + 1].p.y;\n\t*pZ = (1.0f - f)*m_pNode[i].p.z + f*m_pNode[i + 1].p.z;\n}\n\nvoid CScriptPath::Update(void) {\n\tif (m_state != SCRIPT_PATH_ACTIVE)\n\t\treturn;\n\n\tm_fPosition += m_fSpeed * CTimer::GetTimeStepInSeconds();\n\tm_fPosition = clamp(m_fPosition, 0.0f, m_fTotalLength);\n\n\tif (m_pObjects[0] || m_pObjects[1] || m_pObjects[2] || m_pObjects[3]\n\t\t|| m_pObjects[4] || m_pObjects[5]) {\n\n\t\tfloat t1, t2;\n\t\tCVector pos1, pos2;\n\n\t\tt1 = Max(m_fPosition - m_fObjectLength / 2.0f, 0.0f);\n\t\tFindCoorsFromDistanceOnPath(t1, &pos1.x, &pos1.y, &pos1.z);\n\t\tt2 = Min(m_fPosition + m_fObjectLength / 2.0f, m_fTotalLength);\n\t\tFindCoorsFromDistanceOnPath(t2, &pos2.x, &pos2.y, &pos2.z);\n\n\t\tCVector newForward, newUp(0.0f, 0.0f, 1.0f), newRight;\n\n\t\tnewForward = pos2 - pos1;\n\t\tnewForward.Normalise();\n\t\tnewRight = CrossProduct(newForward, newUp);\n\t\tnewRight.Normalise();\n\t\tnewUp = CrossProduct(newRight, newForward);\n\n\t\tfor (int i = 0; i < 6; i++) {\n\t\t\tif (m_pObjects[i]) {\n\t\t\t\tCMatrix prevMat(m_pObjects[i]->GetMatrix());\n\t\t\t\tCVector prevPosition = m_pObjects[i]->GetPosition();\n\n\t\t\t\tm_pObjects[i]->SetPosition((pos1 + pos2) / 2.0f);\n\t\t\t\tm_pObjects[i]->GetRight() = newRight;\n\t\t\t\tm_pObjects[i]->GetUp() = newUp;\n\t\t\t\tm_pObjects[i]->GetForward() = newForward;\n\t\t\t\tm_pObjects[i]->GetMatrix().UpdateRW();\n\t\t\t\tm_pObjects[i]->UpdateRwFrame();\n\n\t\t\t\tif (!m_pObjects[i]->bIsBIGBuilding && prevPosition != m_pObjects[i]->GetPosition())\n\t\t\t\t\tm_pObjects[i]->RemoveAndAdd();\n\n\t\t\t\tm_pObjects[i]->GetMatrix().UpdateRW();\n\t\t\t\tm_pObjects[i]->UpdateRwFrame();\n\n\t\t\t\tm_pObjects[i]->m_vecMoveSpeed = (m_pObjects[i]->GetPosition() - prevMat.GetPosition()) / CTimer::GetTimeStep();\n\n\t\t\t\tfloat deltaAngle = m_pObjects[i]->GetForward().Heading() - prevMat.GetForward().Heading();\n\t\t\t\twhile (deltaAngle < (float)PI) deltaAngle += (float)TWOPI;\n\t\t\t\twhile (deltaAngle > (float)PI) deltaAngle -= (float)TWOPI;\n\t\t\t\tfloat zTurnSpeed = deltaAngle / CTimer::GetTimeStep();\n\n\t\t\t\tm_pObjects[i]->m_vecTurnSpeed = CVector(0.0f, 0.0f, zTurnSpeed);\n\t\t\t\tm_pObjects[i]->m_vecMoveFriction = CVector(0.0f, 0.0f, 0.0f);\n\t\t\t\tm_pObjects[i]->m_vecTurnFriction = CVector(0.0f, 0.0f, 0.0f);\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid CScriptPath::Clear(void) {\n\tif (m_pNode)\n\t\tdelete[] m_pNode;\n\tm_pNode = nil;\n\tm_numNodes = 0;\n\tfor (int i = 0; i < 6; i++)\n\t\tm_pObjects[i] = nil;\n\tm_state = SCRIPT_PATH_DISABLED;\n}\n\nvoid CScriptPath::InitialiseOne(int32 numNodes, float length) {\n\tchar Dest[32];\n\tsprintf(Dest, \"data\\\\paths\\\\spath%d.dat\", numNodes);\n\tm_pNode = CPlane::LoadPath(Dest, m_numNodes, m_fTotalLength, false);\n\tm_fSpeed = 1.0f;\n\tm_fPosition = 0.0f;\n\tm_fObjectLength = length;\n\tm_state = SCRIPT_PATH_INITIALIZED;\n}\n\nvoid CScriptPath::SetObjectToControl(CObject *pObj) {\n\tint32 i = 0;\n\twhile (i < 6 && m_pObjects[i])\n\t\ti++;\n\tm_pObjects[i] = pObj;\n\tpObj->RegisterReference((CEntity**)&m_pObjects[i]);\n\tpObj->m_phy_flagA08 = false;\n\tm_state = SCRIPT_PATH_ACTIVE;\n}\n\nvoid CScriptPaths::Init(void) {\n\tfor (int i = 0; i < 3; i++)\n\t\taArray[i].Clear();\n}\n\nvoid CScriptPaths::Shutdown(void) {\n\tfor (int i = 0; i < 3; i++)\n\t\taArray[i].Clear();\n}\n\nvoid CScriptPaths::Update(void) {\n\tfor (int i = 0; i < 3; i++)\n\t\taArray[i].Update();\n}\n\nbool CScriptPaths::IsOneActive(void) {\n\tfor (int i = 0; i < 3; i++)\n\t\tif (aArray[i].m_state == SCRIPT_PATH_ACTIVE && aArray[i].m_fSpeed != 0.0f)\n\t\t\treturn true;\n\n\treturn false;\n}\n\nvoid CScriptPaths::Load(uint8 *buf, uint32 size) {\nINITSAVEBUF\n\tfor (int32 i = 0; i < 3; i++)\n\t\taArray[i].Clear();\n\n\tfor (int32 i = 0; i < 3; i++) {\n\t\taArray[i] = ReadSaveBuf<CScriptPath>(buf);\n\n\t\tfor (int32 j = 0; j < 6; j++) {\n\t\t\tCScriptPath *pPath = &aArray[i];\n\t\t\tif (pPath->m_pObjects[j] != nil) {\n\t\t\t\tpPath->m_pObjects[j] = CPools::GetObjectPool()->GetSlot((uintptr)pPath->m_pObjects[j] - 1);\n\t\t\t\tpPath->m_pObjects[j]->m_phy_flagA08 = false;\n\t\t\t}\n\t\t}\n\n\t\taArray[i].m_pNode = new CPlaneNode[aArray[i].m_numNodes];\n\t\tfor (int32 j = 0; j < aArray[i].m_numNodes; j++) {\n\t\t\taArray[i].m_pNode[j] = ReadSaveBuf<CPlaneNode>(buf);\n\t\t}\n\t}\nVALIDATESAVEBUF(size)\n}\n\nvoid CScriptPaths::Save(uint8 *buf, uint32 *size) {\n\t*size = sizeof(aArray);\nINITSAVEBUF\n\tfor (int32 i = 0; i < 3; i++) {\n\t\tCScriptPath *pPath = WriteSaveBuf(buf, aArray[i]);\n\n\t\tfor (int32 j = 0; j < 6; j++) {\n\t\t\tif (pPath->m_pObjects[j] != nil)\n\t\t\t\tpPath->m_pObjects[j] = (CObject*)(CPools::GetObjectPool()->GetJustIndex_NoFreeAssert(pPath->m_pObjects[j]) + 1);\n\t\t}\n\n\t\tfor (int32 j = 0; j < aArray[i].m_numNodes; j++) {\n\t\t\tWriteSaveBuf(buf, aArray[i].m_pNode[j]);\n\t\t\t*size += sizeof(aArray[i].m_pNode[j]);\n\t\t}\n\t}\nVALIDATESAVEBUF(*size);\n}\n\nCObject *g_pScriptPathObjects[18];\n\nvoid CScriptPaths::Load_ForReplay(void) {\n\tfor (int i = 0; i < 3; i++) {\n\t\tfor (int32 j = 0; j < 6; j++) {\n\t\t\taArray[i].m_pObjects[j] = g_pScriptPathObjects[6 * i + j];\n\t\t}\n\t}\n}\n\nvoid CScriptPaths::Save_ForReplay(void) {\n\tfor (int i = 0; i < 3; i++) {\n\t\tfor (int32 j = 0; j < 6; j++) {\n\t\t\tg_pScriptPathObjects[6 * i + j] = aArray[i].m_pObjects[j];\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/render/Fluff.h",
    "content": "#pragma once\n#include \"common.h\"\n#include \"Vector.h\"\n#include \"Object.h\"\n#include \"Plane.h\"\n\nenum {\n\tSCRIPT_PATH_DISABLED = 0,\n\tSCRIPT_PATH_INITIALIZED,\n\tSCRIPT_PATH_ACTIVE\n};\n\nclass CScriptPath\n{\npublic:\n\tint32 m_numNodes;\n\tCPlaneNode *m_pNode;\n\tfloat m_fTotalLength;\n\tfloat m_fSpeed;\n\tfloat m_fPosition;\n\tfloat m_fObjectLength;\n\tint32 m_state;\n\tCObject *m_pObjects[6];\n\n\tvoid Clear(void);\n\tvoid Update(void);\n\tvoid InitialiseOne(int32 numNodes, float length);\n\tvoid FindCoorsFromDistanceOnPath(float t, float *pX, float *pY, float *pZ);\n\tvoid SetObjectToControl(CObject *pObj);\n};\n\nclass CScriptPaths\n{\npublic:\n\tstatic CScriptPath aArray[3];\n\tstatic void Init(void);\n\tstatic void Shutdown(void);\n\tstatic void Update(void);\n\tstatic bool IsOneActive(void);\n\tstatic void Save(uint8 *buf, uint32 *size);\n\tstatic void Load(uint8 *buf, uint32 size);\n\tstatic void Save_ForReplay();\n\tstatic void Load_ForReplay();\n};\n\nclass CPlaneTrail\n{\n\tCVector m_pos[16];\n\tint32 m_time[16];\npublic:\n\tvoid Init(void);\n\tvoid Render(float visibility);\n\tvoid RegisterPoint(CVector pos);\n};\n\nclass CPlaneTrails\n{\n\tstatic CPlaneTrail aArray[6];\t// NB: 3 CPlanes and 3 hardcoded far away ones\npublic:\n\tstatic void Init(void);\n\tstatic void Update(void);\n\tstatic void Render(void);\n\tstatic void RegisterPoint(CVector pos, uint32 id);\n};\n\nclass CPlaneBanner\n{\n\tCVector m_pos[8];\npublic:\n\tvoid Init(void);\n\tvoid Update(void);\n\tvoid Render(void);\n\tvoid RegisterPoint(CVector pos);\n};\n\nclass CPlaneBanners\n{\n\tstatic CPlaneBanner aArray[5];\npublic:\n\tstatic void Init(void);\n\tstatic void Update(void);\n\tstatic void Render(void);\n\tstatic void RegisterPoint(CVector pos, uint32 id);\n};\n\nclass CEscalator\n{\n\tCVector m_pos0;\n\tCVector m_pos1;\n\tCVector m_pos2;\n\tCVector m_pos3;\n\tCMatrix m_matrix;\n\tbool m_bIsActive;\n\tbool m_bIsMovingDown;\n\tint32 m_stepsCount;\n\tfloat m_lowerEnd; \n\tfloat m_upperEnd; \n\tCVector m_midPoint;\n\tfloat m_radius;\n\tCObject *m_pSteps[24];\npublic:\n\tCEscalator();\n\tvoid Update(void);\n\tvoid SwitchOff(void);\n\tvoid AddThisOne(CVector pos0, CVector pos1, CVector pos2, CVector pos3, bool b_isMovingDown);\n\tbool IsActive() const { return m_bIsActive; };\n\tconst CVector& GetPosition() const { return m_midPoint; };\n};\n\nclass CEscalators\n{\n\tstatic CEscalator aEscalators[NUM_ESCALATORS];\npublic:\n\tstatic int32 NumEscalators;\n\tstatic void Init(void);\n\tstatic void Update(void);\n\tstatic void AddOne(CVector pos0, CVector pos1, CVector pos2, CVector pos3, bool b_isMovingDown);\n\tstatic void Shutdown(void);\n\tstatic const CEscalator& GetEscalator(int ind) { return aEscalators[ind]; };\n};\n\nclass CMovingThing\n{\npublic:\n\tCMovingThing *m_pNext;\n\tCMovingThing *m_pPrev;\n\tint16 m_nType;\n\tint16 m_farAway;\n\tCVector m_vecPosn;\n\tCEntity* m_pEntity;\n\n\tvoid Update();\n\tvoid AddToList(CMovingThing *pThing);\n\tvoid RemoveFromList();\n\tint16 SizeList();\n};\n\n#define NUMMOVINGTHINGS 48\n\nclass CMovingThings\n{\npublic:\n\tstatic CMovingThing StartCloseList;\n\tstatic CMovingThing EndCloseList;\n\tstatic int16 Num;\n\tstatic CMovingThing aMovingThings[NUMMOVINGTHINGS];\n\n\tstatic void Init();\n\tstatic void Shutdown();\n\tstatic void Update();\n\tstatic void Render();\n\tstatic void PossiblyAddThisEntity(CEntity *pEnt);\n\tstatic void RegisterOne(CEntity *pEnt, uint16 nType);\n};\n\nclass CScrollBar\n{\nprivate:\n\tuint8       m_Counter;\n\tconst char* m_pMessage;\n\tCVector     m_Position;\n\tuint32      m_MessageCurrentChar;\n\tuint32      m_MessageLength;\n\tCVector     m_Size;\n\tfloat       m_fIntensity;\n\tuint8       m_MessageBar[40];\n\tuint8       m_Type;\n\tbool        m_bVisible;\n\tuint8       m_uRed;\n\tuint8       m_uGreen;\n\tuint8       m_uBlue;\n\tfloat       m_fScale;\n\npublic:\n\tstatic int TonightsEvent;\n\npublic:\n\tvoid SetVisibility(bool visible) { m_bVisible = visible; }\n\tbool IsVisible() { return m_bVisible; }\n\n\tvoid Init(CVector pos1, CVector pos2, uint8 type, uint8 red, uint8 green, uint8 blue, float scale);\n\tvoid Update();\n\tvoid Render();\n};\n\nclass CSmokeTrail {\n\tCVector m_pos[16];\n\tfloat m_opacity[16];\n\tint m_time[16];\n\tchar m_unused[536];\n\tint m_seed;\npublic:\n\tvoid Render(void);\n\tvoid RegisterPoint(CVector position, float a);\n\tvoid Init(int num);\n};\n\nclass CSmokeTrails {\n\tstatic CSmokeTrail aSmoke[3];\npublic:\n\tstatic bool CigOn;\n\tstatic void Update(void);\n\tstatic void Render(void);\n\tstatic void Init(void);\n};"
  },
  {
    "path": "src/render/Font.cpp",
    "content": "#include \"common.h\"\n\n#include \"Sprite2d.h\"\n#include \"TxdStore.h\"\n#include \"Font.h\"\n#ifdef BUTTON_ICONS\n#include \"FileMgr.h\"\n#endif\n#include \"Timer.h\"\n\nvoid\nAsciiToUnicode(const char *src, wchar *dst)\n{\n\twhile((*dst++ = (unsigned char)*src++) != '\\0');\n}\n\nvoid\nUnicodeStrcat(wchar *dst, wchar *append)\n{\n\tUnicodeStrcpy(&dst[UnicodeStrlen(dst)], append);\n}\n\nvoid\nUnicodeStrcpy(wchar *dst, const wchar *src)\n{\n\twhile((*dst++ = *src++) != '\\0');\n}\n\nint\nUnicodeStrlen(const wchar *str)\n{\n\tint len;\n\tfor(len = 0; *str != '\\0'; len++, str++);\n\treturn len;\n}\n\nvoid\nUnicodeMakeUpperCase(wchar *dst, const wchar *src) //idk what to do with it, seems to be incorrect implementation by R*\n{\n\twhile (*src != '\\0') {\n\t\tif (*src < 'a' || *src > 'z')\n\t\t\t*dst = *src;\n\t\telse\n\t\t\t*dst = *src - 32;\n\t\tdst++;\n\t\tsrc++;\n\t}\n\t*dst = '\\0';\n}\n\nCFontDetails CFont::Details;\nint16 CFont::NewLine;\nCSprite2d CFont::Sprite[MAX_FONTS];\nCFontRenderState CFont::RenderState;\n\n#ifdef MORE_LANGUAGES\nuint8 CFont::LanguageSet = FONT_LANGSET_EFIGS;\nint32 CFont::Slot = -1;\n#define JAP_TERMINATION (0x8000 | '~')\n\nint16 CFont::Size[LANGSET_MAX][MAX_FONTS][210] = {\n\t{\n#else\nint16 CFont::Size[MAX_FONTS][210] = {\n#endif\n\t{\n\t\t//FONT2 EFIGS\n\t\t//SPC,!,         $,  %,  &,  ',  [,  ],      +,  ,   -,  .,    \n\t\t12, 9,  22, 17, 19, 19, 25, 4,  33, 33, 25, 35, 11, 10,  6, 33,\n\t\t//0, 1,  2,  3,  4,  5,  6,  7,  8,  9,  :,                 ??,\n\t\t18, 10, 17, 17, 17, 17, 17, 15, 12, 16,  5, 30, 30, 30, 30, 30,\n\t\t//   A,  B,  C,  D,  E,  F,  G,  H,  I,  J,  K,  L,  M,  N,  O,\n\t\t12, 16, 19, 16, 19, 18, 18, 17, 22, 11, 17, 18, 18, 30, 22, 19,\n\t\t//P, Q,  R,  S,  T,  U,  V,  W,  X,  Y,  Z, ??, ??, ??,  ,  \\,\n\t\t#ifdef FIX_BUGS\n\t\t22, 19, 19, 20, 18, 19, 19, 29, 19, 18, 19, 19, 33, 33, 10, 19,\n\t\t#else\n\t\t22, 19, 19, 20, 18, 19, 19, 29, 19, 18, 19, 19, 33, 33, 19, 19,\n\t\t#endif\n\t\t//??,a,  b,  c,  d,  e,  f,  g,  h,  i,  j,  k,  l,  m,  n,  o,\n\t\t12, 14, 11, 11, 16, 11, 12, 14, 14, 10, 13, 12, 10, 19, 18, 12,\n\t\t//p, q,  r,  s,  t,  u,  v,  w,  x,  y,  z, ??, ??, ??, ??, ??,\n\t\t16, 13, 13, 11, 12, 15, 12, 15, 13, 12, 12, 37, 33, 37, 35, 37,\n\t\t//, ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,\n\t\t16, 16, 16, 16, 33, 17, 18, 18, 18, 18, 11, 11, 11, 11, 19, 19,\n\t\t//, ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,\n\t\t19, 19, 19, 19, 19, 19, 15, 14, 14, 14, 14, 20, 14, 11, 11, 11,\n\t\t//, ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,\n\t\t#ifdef FIX_BUGS\n\t\t11, 10, 10, 10, 10, 12, 12, 12, 12, 15, 15, 15, 15, 22, 18, 21,\n\t\t#else\n\t\t11, 10, 10, 10, 10, 12, 12, 12, 12, 15, 15, 15, 15, 24, 18, 21,\n\t\t#endif\n\t\t//i,BLANKS\n\t\t10, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,\n\t\t19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,\n\t\t19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,\n\t\t19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,\n\t\t//space, unprop\n\t\t19, 16\n\t},\n\t{\n\t\t//FONT1 EFIGS\n\t\t//Characters with a '2' refer to the Pricedown font.\n\t\t//Characters that are referred as '*I' are characters that contain icons for PS2/XBOX, but contain regular characters on PC\n\t\t//in order to display them properly in the Keyboard controls menu.\n\t\t//!2,!, *I,(R),  $,  %,  &,  ',  [,  ], *I,  +,  ,   -,  ., *I,\n\t\t15,  7, 31, 25, 20, 23, 21,  7, 11, 10, 26, 14,  6, 12,  6, 26,\n\t\t//0, 1,  2,  3,  4,  5,  6,  7,  8,  9,  :, *I, *I, *I, *I,  ?,\n\t\t20,  7, 20, 20, 21, 20, 20, 19, 21, 20,  8, 30, 24, 30, 24, 19,\n\t\t//TM,A,  B,  C,  D,  E,  F,  G,  H,  I,  J,  K,  L,  M,  N,  O,\n\t\t20, 22, 22, 21, 22, 18, 18, 22, 22,  9, 14, 21, 18, 27, 21, 24,\n\t\t//P, Q,  R,  S,  T,  U,  V,  W,  X,  Y,  Z, *I,  \\, *I,  ,  ,\n\t\t#ifdef FIX_BUGS\n\t\t22, 22, 23, 20, 19, 23, 22, 31, 23, 23, 21, 25, 13, 30,  7, 19,\n\t\t#else\n\t\t22, 22, 23, 20, 19, 23, 22, 31, 23, 23, 21, 25, 13, 30, 10, 19,\n\t\t#endif\n\t\t//(C),a, b,  c,  d,  e,  f,  g,  h,  i,  j,  k,  l,  m,  n,  o,\n\t\t10, 17, 17, 16, 17, 17, 11, 17, 17,  7,  7, 18,  7, 25, 17, 17,\n\t\t//p, q,  r,  s,  t,  u,  v,  w,  x,  y,  z, *I, *I, $2, (2, )2,\n\t\t17, 17, 11, 17, 11, 17, 18, 25, 19, 18, 17, 28, 26, 20, 15, 15,\n\t\t//, ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,\n\t\t20, 20, 20, 20, 29, 22, 19, 19, 19, 19,  9,  9,  9,  9, 23, 23,\n\t\t//, ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,\n\t\t23, 23, 24, 24, 24, 24, 20, 19, 17, 17, 17, 30, 16, 17, 17, 17,\n\t\t//, ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,\n\t\t#ifdef FIX_BUGS\n\t\t17, 11, 11, 15, 12, 17, 17, 17, 17, 17, 17, 17, 17, 21, 17, 19,\n\t\t#else\n\t\t17, 11, 11, 15, 12, 17, 17, 17, 17, 17, 17, 17, 17, 19, 20, 20,\n\t\t#endif\n\t\t//02,12,22, 32, 42, 52, 62, 72, 82, 92, :2, A2, B2, C2, D2, E2,\n\t\t20, 18, 19, 19, 21, 19, 19, 19, 19, 19, 16, 19, 19, 19, 20, 19,\n\t\t//F2,G2,H2, I2, J2, K2, L2, M2, N2, O2, P2, Q2, R2, S2, T2, U2,\n\t\t16, 19, 19,  9, 19, 20, 14, 29, 19, 19, 19, 19, 19, 19, 21, 19,\n\t\t//V2,W2,X2, Y2, Z2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,\n\t\t20, 32, 20, 19, 19, 19, 19, 19, 19, 29, 19, 19, 19, 19, 19,  9,\n\t\t//2,2,2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, '2, .2,\n\t\t#ifdef FIX_BUGS\n\t\t 9,  9,  9, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 10,  9,\n\t\t#else\n\t\t 9,  9,  9, 19, 19, 19, 19, 19, 19, 19, 19, 19, 21, 21, 10,  9,\n\t\t#endif\n\t\t//space, unprop\n\t\t10, 20\n\t}\n\n#ifdef MORE_LANGUAGES\n\t},\n\t{\n        {\n\t\t\t5,  9,  9,  0,  17, 17, 23, 3,  21, 18, 0,  8,  3,  8,  3,  0,\n\t\t\t16, 9,  16, 16, 15, 19, 15, 14, 17, 17, 4,  4,  0,  0,  0,  17,\n\t\t\t19, 17, 19, 15, 21, 18, 19, 16, 21, 13, 15, 21, 20, 28, 21, 18,\n\t\t\t22, 17, 21, 20, 18, 18, 20, 26, 22, 18, 18, 0,  8,  0,  9,  8,\n\t\t\t0,  14, 11, 12, 16, 11, 13, 13, 15, 10, 14, 15, 11, 21, 17, 10,\n\t\t\t20, 15, 12, 12, 16, 17, 13, 16, 13, 21, 11, 0,  0,  0,  0,  0, \n\t\t\t20, 19, 19, 22, 27, 15, 18, 18, 20, 26, 21, 23, 17, 22, 21, 17,\n\t\t\t26, 25, 26, 17, 20, 26, 17, 16, 11, 12, 13, 21, 11, 17, 17, 12,\n\t\t\t21, 17, 17, 15, 24, 16, 10, 20, 23, 16, 7,  9,  16, 23, 12, 11,\n\t\t\t0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,\n\t\t\t0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,\n\t\t\t0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,\n\t\t\t0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  19,\n\t\t\t19, 16\n\t\t},\n        {\n\t\t\t11, 5,  10, 15, 19, 22, 20, 5,  9,  8,  11, 12, 5,  12, 6,  12,\n\t\t\t19, 5,  18, 19, 20, 18, 19, 18, 20, 19, 5,  6,  26, 12, 30, 19,\n\t\t\t23, 21, 20, 20, 20, 16, 16, 21, 19, 5,  13, 19, 16, 24, 20, 21,\n\t\t\t20, 21, 20, 19, 17, 20, 21, 30, 22, 21, 20, 25, 13, 30,  5,  9,\n\t\t\t10, 15, 15, 14, 15, 16, 10, 15, 15, 5,  5,  15, 5,  23, 15, 16,\n\t\t\t15, 15, 9,  16, 10, 15, 17, 24, 18, 15, 15, 27, 5,  19, 2,  2, \n\t\t\t20, 20, 16, 23, 30, 19, 20, 20, 21, 24, 19, 19, 20, 23, 22, 19,\n\t\t\t27, 29, 25, 20, 20, 28, 24, 16, 16, 14, 19, 25, 16, 16, 16, 17,\n\t\t\t19, 16, 16, 17, 25, 19, 15, 23, 26, 21, 16, 14, 22, 20, 16, 19,\n\t\t\t15, 14, 15, 16, 17, 15, 15, 15, 15, 15, 7,  15, 15, 15, 15, 15,\n\t\t\t13, 15, 15, 7,  15, 16, 13, 23, 15, 15, 15, 15, 15, 15, 17, 15,\n\t\t\t16, 24, 17, 17, 17, 15, 15, 13, 20, 23, 15, 17, 17, 16, 24, 15,\n\t\t\t15, 15, 23, 18, 15, 23, 26, 23, 16, 15, 23, 15, 15, 19, 2,  2,\n\t\t\t10, 20\n\t\t},\n\t},\t\n\t{\n\t\t{\n\t\t\t//FONT2 EFIGS\n\t\t\t//SPC,!,         $,  %,  &,  ',  [,  ],      +,  ,   -,  .,    \n\t\t\t12, 9,  22, 17, 19, 19, 25, 4,  33, 33, 25, 35, 11, 10,  6, 33,\n\t\t\t//0, 1,  2,  3,  4,  5,  6,  7,  8,  9,  :,                 ??,\n\t\t\t18, 10, 17, 17, 17, 17, 17, 15, 12, 16,  5, 30, 30, 30, 30, 30,\n\t\t\t//   A,  B,  C,  D,  E,  F,  G,  H,  I,  J,  K,  L,  M,  N,  O,\n\t\t\t12, 16, 19, 16, 19, 18, 18, 17, 22, 11, 17, 18, 18, 30, 22, 19,\n\t\t\t//P, Q,  R,  S,  T,  U,  V,  W,  X,  Y,  Z, ??, ??, ??,  ,  \\,\n\t\t\t22, 19, 19, 20, 18, 19, 19, 29, 19, 18, 19, 19, 33, 33, 10, 19,\n\t\t\t//??,a,  b,  c,  d,  e,  f,  g,  h,  i,  j,  k,  l,  m,  n,  o,\n\t\t\t12, 14, 11, 11, 16, 11, 12, 14, 14, 10, 13, 12, 10, 19, 18, 12,\n\t\t\t//p, q,  r,  s,  t,  u,  v,  w,  x,  y,  z, ??, ??, ??, ??, ??,\n\t\t\t16, 13, 13, 11, 12, 15, 12, 15, 13, 12, 12, 37, 33, 37, 35, 37,\n\t\t\t//, ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,\n\t\t\t16, 16, 16, 16, 33, 17, 18, 18, 18, 18, 11, 11, 11, 11, 19, 19,\n\t\t\t//, ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,\n\t\t\t19, 19, 19, 19, 19, 19, 15, 14, 14, 14, 14, 20, 14, 11, 11, 11,\n\t\t\t//, ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,\n\t\t\t11, 10, 10, 10, 10, 12, 12, 12, 12, 15, 15, 15, 15, 22, 18, 21,\n\t\t\t//i,BLANKS\n\t\t\t10, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,\n\t\t\t19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,\n\t\t\t19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,\n\t\t\t19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,\n\t\t\t//space, unprop\n\t\t\t19, 16\n\t\t},\n\t\t{\n\t\t\t//FONT1 EFIGS\n\t\t\t//Characters with a '2' refer to the Pricedown font.\n\t\t\t//Characters that are referred as '*I' are characters that contain icons for PS2/XBOX, but contain regular characters on PC\n\t\t\t//in order to display them properly in the Keyboard controls menu.\n\t\t\t//!2,!, *I,(R),  $,  %,  &,  ',  [,  ], *I,  +,  ,   -,  ., *I,\n\t\t\t15,  7, 31, 25, 20, 23, 21,  7, 11, 10, 26, 14,  6, 12,  6, 26,\n\t\t\t//0, 1,  2,  3,  4,  5,  6,  7,  8,  9,  :, *I, *I, *I, *I,  ?,\n\t\t\t20,  7, 20, 20, 21, 20, 20, 19, 21, 20,  8, 30, 24, 30, 24, 19,\n\t\t\t//TM,A,  B,  C,  D,  E,  F,  G,  H,  I,  J,  K,  L,  M,  N,  O,\n\t\t\t20, 22, 22, 21, 22, 18, 18, 22, 22,  9, 14, 21, 18, 27, 21, 24,\n\t\t\t//P, Q,  R,  S,  T,  U,  V,  W,  X,  Y,  Z, *I,  \\, *I,  ,  ,\n\t\t\t22, 22, 23, 20, 19, 23, 22, 31, 23, 23, 21, 25, 13, 30,  7, 19,\n\t\t\t//(C),a, b,  c,  d,  e,  f,  g,  h,  i,  j,  k,  l,  m,  n,  o,\n\t\t\t10, 17, 17, 16, 17, 17, 11, 17, 17,  7,  7, 18,  7, 25, 17, 17,\n\t\t\t//p, q,  r,  s,  t,  u,  v,  w,  x,  y,  z, *I, *I, $2, (2, )2,\n\t\t\t17, 17, 11, 17, 11, 17, 18, 25, 19, 18, 17, 28, 26, 20, 15, 15,\n\t\t\t//, ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,\n\t\t\t20, 20, 20, 20, 29, 22, 19, 19, 19, 19,  9,  9,  9,  9, 23, 23,\n\t\t\t//, ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,\n\t\t\t23, 23, 24, 24, 24, 24, 20, 19, 17, 17, 17, 30, 16, 17, 17, 17,\n\t\t\t//, ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,  ,\n\t\t\t17, 11, 11, 15, 12, 17, 17, 17, 17, 17, 17, 17, 17, 21, 17, 19,\n\t\t\t//02,12,22, 32, 42, 52, 62, 72, 82, 92, :2, A2, B2, C2, D2, E2,\n\t\t\t20, 18, 19, 19, 21, 19, 19, 19, 19, 19, 16, 19, 19, 19, 20, 19,\n\t\t\t//F2,G2,H2, I2, J2, K2, L2, M2, N2, O2, P2, Q2, R2, S2, T2, U2,\n\t\t\t16, 19, 19,  9, 19, 20, 14, 29, 19, 19, 19, 19, 19, 19, 21, 19,\n\t\t\t//V2,W2,X2, Y2, Z2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,\n\t\t\t20, 32, 20, 19, 19, 19, 19, 19, 19, 29, 19, 19, 19, 19, 19,  9,\n\t\t\t//2,2,2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, '2, .2,\n\t\t\t 9,  9,  9, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 10,  9,\n\t\t\t//space, unprop\n\t\t\t10, 20\n\t\t}\n\t}\n#endif\n};\n\n#ifdef MORE_LANGUAGES\nint16 Size_jp[] = {\n\t15, 14, 16, 20, 19, 26, 22, 11, 18, 18, 27, 26, 13, //; 0\n\t19, 20, 27, 19, 15, 19, 19, 21, 19, 20, 18, 19, 15, //; 13\n\t13, 28, 15, 32, 15, 35, 15, 19, 19, 19, 19, 17, 16, //; 26\n\t19, 20, 15, 19, 20, 14, 17, 19, 19, 19, 19, 19, 19, //; 39\n\t19, 19, 20, 25, 20, 19, 19, 33, 31, 39, 37, 39, 37, //; 52\n\t21, 21, 21, 19, 17, 15, 23, 21, 15, 19, 20, 16, 19, //; 65\n\t19, 19, 20, 20, 17, 22, 19, 22, 22, 19, 22, 22, 23, //; 78\n\t35, 35, 35, 35, 37, 19, 19, 19, 19, 29, 19, 19, 19, //; 91\n\t19, 19, 9, 9, 9, 9, 19, 19, 19, 19, 19, 19, 19, 19, //; 104\n\t19, 19, 19, 19, 19, 30, 19, 19, 19, 19, 19, 10, 10, //; 118\n\t10, 10, 19, 19, 19, 19, 19, 19, 19, 19, 19, 23, 35, //; 131\n\t12, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, //; 144\n\t19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, //; 157\n\t19, 19, 19, 11, 19, 19, 19, 19, 19, 19, 19, 19, 19, //; 170\n\t19, 19, 19, 19, 19, 19, 19, 19, 19, 21\n};\n#endif\n\nwchar foreign_table[128] = {\n\t  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n\t  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n\t  0, 176,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n\t  0,   0,   0,   0, 177,   0,   0,   0,   0,   0,  95,   0,   0,   0,   0, 175,\n\t128, 129, 130,   0, 131,   0, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141,\n\t  0, 173, 142, 143, 144,   0, 145,   0,   0, 146, 147, 148, 149,   0,   0, 150,\n\t151, 152, 153,   0, 154,   0, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164,\n\t  0, 174, 165, 166, 167,   0, 168,   0,   0, 169, 170, 171, 172,   0,   0,   0,\n};\n\nunion tFontRenderStatePointer\n{\n\tCFontRenderState *pRenderState;\n\twchar *pStr;\n\n\tvoid Align()\n\t{\n\t\tif ((uintptr)pStr % 4)\n\t\t\tpStr++;\n\t}\n};\n\ntFontRenderStatePointer FontRenderStatePointer;\nuint8 FontRenderStateBuf[1024];\n\n#ifdef BUTTON_ICONS\nCSprite2d CFont::ButtonSprite[MAX_BUTTON_ICONS];\nint CFont::PS2Symbol = BUTTON_NONE;\nint CFont::ButtonsSlot = -1;\n#endif // BUTTON_ICONS\n\nvoid\nCFont::Initialise(void)\n{\n\tint slot;\n\n\tslot = CTxdStore::AddTxdSlot(\"fonts\");\n#ifdef MORE_LANGUAGES\n\tSlot = slot;\n\tswitch (LanguageSet)\n\t{\n\tcase FONT_LANGSET_EFIGS:\n\tdefault:\n\t\tCTxdStore::LoadTxd(slot, \"MODELS/FONTS.TXD\");\n\t\tbreak;\n\tcase FONT_LANGSET_POLISH:\n\t\tCTxdStore::LoadTxd(slot, \"MODELS/FONTS_P.TXD\");\n\t\tbreak;\n\tcase FONT_LANGSET_RUSSIAN:\n\t\tCTxdStore::LoadTxd(slot, \"MODELS/FONTS_R.TXD\");\n\t\tbreak;\n\tcase FONT_LANGSET_JAPANESE:\n\t\tCTxdStore::LoadTxd(slot, \"MODELS/FONTS_J.TXD\");\n\t\tbreak;\n\t}\n#else\n\tCTxdStore::LoadTxd(slot, \"MODELS/FONTS.TXD\");\n#endif\n\tCTxdStore::AddRef(slot);\n\tCTxdStore::PushCurrentTxd();\n\tCTxdStore::SetCurrentTxd(slot);\n\tSprite[0].SetTexture(\"font2\", \"font2m\");\n#ifdef MORE_LANGUAGES\n\tif (IsJapanese()) {\n\t\tSprite[1].SetTexture(\"FONTJAP\", \"FONTJAP_mask\");\n\t\tSprite[3].SetTexture(\"FONTJAP\", \"FONTJAP_mask\");\n\t}\n#endif // MORE_LANGUAGES\n\tSprite[1].SetTexture(\"font1\", \"font1m\");\n\tSetScale(1.0f, 1.0f);\n\tSetSlantRefPoint(SCREEN_WIDTH, 0.0f);\n\tSetSlant(0.0f);\n\tSetColor(CRGBA(255, 255, 255, 0));\n\tSetJustifyOff();\n\tSetCentreOff();\n\tSetWrapx(SCREEN_WIDTH);\n\tSetCentreSize(SCREEN_WIDTH);\n\tSetBackgroundOff();\n\tSetBackgroundColor(CRGBA(128, 128, 128, 128));\n\tSetBackGroundOnlyTextOff();\n\tSetPropOn();\n\tSetFontStyle(FONT_BANK);\n\tSetRightJustifyWrap(0.0f);\n\tSetAlphaFade(255.0f);\n\tSetDropShadowPosition(0);\n\tCTxdStore::PopCurrentTxd();\n\n#if !defined(GAMEPAD_MENU) && defined(BUTTON_ICONS)\n\t// loaded in CMenuManager with GAMEPAD_MENU defined\n\tLoadButtons(\"MODELS/X360BTNS.TXD\");\n#endif\n}\n\n#ifdef BUTTON_ICONS\nvoid\nCFont::LoadButtons(const char *txdPath)\n{\n\tif (int file = CFileMgr::OpenFile(txdPath)) {\n\t\tCFileMgr::CloseFile(file);\n\t\tif (ButtonsSlot == -1)\n\t\t\tButtonsSlot = CTxdStore::AddTxdSlot(\"buttons\");\n\t\telse {\n\t\t\tfor (int i = 0; i < MAX_BUTTON_ICONS; i++)\n\t\t\t\tButtonSprite[i].Delete();\n\t\t\tCTxdStore::RemoveTxd(ButtonsSlot);\n\t\t}\n\t\tCTxdStore::LoadTxd(ButtonsSlot, txdPath);\n\t\tCTxdStore::AddRef(ButtonsSlot);\n\t\tCTxdStore::PushCurrentTxd();\n\t\tCTxdStore::SetCurrentTxd(ButtonsSlot);\n\t\tButtonSprite[BUTTON_UP].SetTexture(\"thumblyu\");\n\t\tButtonSprite[BUTTON_DOWN].SetTexture(\"thumblyd\");\n\t\tButtonSprite[BUTTON_LEFT].SetTexture(\"thumblxl\");\n\t\tButtonSprite[BUTTON_RIGHT].SetTexture(\"thumblxr\");\n\t\tButtonSprite[BUTTON_CROSS].SetTexture(\"cross\");\n\t\tButtonSprite[BUTTON_CIRCLE].SetTexture(\"circle\");\n\t\tButtonSprite[BUTTON_SQUARE].SetTexture(\"square\");\n\t\tButtonSprite[BUTTON_TRIANGLE].SetTexture(\"triangle\");\n\t\tButtonSprite[BUTTON_L1].SetTexture(\"l1\");\n\t\tButtonSprite[BUTTON_L2].SetTexture(\"l2\");\n\t\tButtonSprite[BUTTON_L3].SetTexture(\"l3\");\n\t\tButtonSprite[BUTTON_R1].SetTexture(\"r1\");\n\t\tButtonSprite[BUTTON_R2].SetTexture(\"r2\");\n\t\tButtonSprite[BUTTON_R3].SetTexture(\"r3\");\n\t\tButtonSprite[BUTTON_RSTICK_UP].SetTexture(\"thumbryu\");\n\t\tButtonSprite[BUTTON_RSTICK_DOWN].SetTexture(\"thumbryd\");\n\t\tButtonSprite[BUTTON_RSTICK_LEFT].SetTexture(\"thumbrxl\");\n\t\tButtonSprite[BUTTON_RSTICK_RIGHT].SetTexture(\"thumbrxr\");\n\t\tCTxdStore::PopCurrentTxd();\n\t}\n\telse {\n\t\tif (ButtonsSlot != -1) {\n\t\t\tfor (int i = 0; i < MAX_BUTTON_ICONS; i++)\n\t\t\t\tButtonSprite[i].Delete();\n\t\t\tCTxdStore::RemoveTxdSlot(ButtonsSlot);\n\t\t\tButtonsSlot = -1;\n\t\t}\n\t}\n}\n#endif // BUTTON_ICONS\n\n#ifdef MORE_LANGUAGES\nvoid\nCFont::ReloadFonts(uint8 set)\n{\n\tif (Slot != -1 && LanguageSet != set) {\n\t\tSprite[0].Delete();\n\t\tSprite[1].Delete();\n\t\tif (IsJapanese())\n\t\t\tSprite[2].Delete();\n\t\tCTxdStore::PushCurrentTxd();\n\t\tCTxdStore::RemoveTxd(Slot);\n\t\tswitch (set)\n\t\t{\n\t\tcase FONT_LANGSET_EFIGS:\n\t\tdefault:\n\t\t\tCTxdStore::LoadTxd(Slot, \"MODELS/FONTS.TXD\");\n\t\t\tbreak;\n\t\tcase FONT_LANGSET_POLISH:\n\t\t\tCTxdStore::LoadTxd(Slot, \"MODELS/FONTS_P.TXD\");\n\t\t\tbreak;\n\t\tcase FONT_LANGSET_RUSSIAN:\n\t\t\tCTxdStore::LoadTxd(Slot, \"MODELS/FONTS_R.TXD\");\n\t\t\tbreak;\n\t\tcase FONT_LANGSET_JAPANESE:\n\t\t\tCTxdStore::LoadTxd(Slot, \"MODELS/FONTS_J.TXD\");\n\t\t\tbreak;\n\t\t}\n\t\tCTxdStore::SetCurrentTxd(Slot);\n\t\tSprite[0].SetTexture(\"font2\", \"font2_mask\");\n\t\tif (set == FONT_LANGSET_JAPANESE) {\n\t\t\tSprite[2].SetTexture(\"FONTJAP\", \"FONTJAP_mask\");\n\t\t}\n\t\tSprite[1].SetTexture(\"font1\", \"font1_mask\");\n\t\tCTxdStore::PopCurrentTxd();\n\t}\n\tLanguageSet = set;\n}\n#endif\n\nvoid\nCFont::Shutdown(void)\n{\n#ifdef BUTTON_ICONS\n\tif (ButtonsSlot != -1) {\n\t\tfor (int i = 0; i < MAX_BUTTON_ICONS; i++)\n\t\t\tButtonSprite[i].Delete();\n\t\tCTxdStore::RemoveTxdSlot(ButtonsSlot);\n\t\tButtonsSlot = -1;\n\t}\n#endif\n\tSprite[0].Delete();\n\tSprite[1].Delete();\n#ifdef MORE_LANGUAGES\n\tif (IsJapanese())\n\t\tSprite[3].Delete();\n\tCTxdStore::RemoveTxdSlot(Slot);\n\tSlot = -1;\n#else\n\tCTxdStore::RemoveTxdSlot(CTxdStore::FindTxdSlot(\"fonts\"));\n#endif\n}\n\nvoid\nCFont::InitPerFrame(void)\n{\n\tRenderState.style = -1;\n\tDetails.anonymous_25 = 0;\n\tFontRenderStatePointer.pRenderState = (CFontRenderState*)FontRenderStateBuf;\n\tSetDropShadowPosition(0);\n\tNewLine = false;\n#ifdef BUTTON_ICONS\n\tPS2Symbol = BUTTON_NONE;\n#endif\n}\n\n#ifdef BUTTON_ICONS\nvoid\nCFont::DrawButton(float x, float y)\n{\n\tif (x <= 0.0f || x > SCREEN_WIDTH || y <= 0.0f || y > SCREEN_HEIGHT)\n\t\treturn;\n\n\tif (PS2Symbol != BUTTON_NONE) {\n\t\tCRect rect;\n\t\trect.left = x;\n\t\trect.top = RenderState.scaleY + RenderState.scaleY + y;\n\t\trect.right = RenderState.scaleY * 17.0f + x;\n\t\trect.bottom = RenderState.scaleY * 19.0f + y;\n\n\t\tint vertexAlphaState;\n\t\tvoid *raster;\n\t\tRwRenderStateGet(rwRENDERSTATEVERTEXALPHAENABLE, &vertexAlphaState);\n\t\tRwRenderStateGet(rwRENDERSTATETEXTURERASTER, &raster);\n\t\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)TRUE);\n\t\tif (RenderState.bIsShadow)\n\t\t\tButtonSprite[PS2Symbol].Draw(rect, RenderState.color);\n\t\telse\n\t\t\tButtonSprite[PS2Symbol].Draw(rect, CRGBA(255, 255, 255, RenderState.color.a));\n\t\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, raster);\n\t\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)vertexAlphaState);\n\t}\n}\n#endif\n\nvoid\nCFont::PrintChar(float x, float y, wchar c)\n{\n\tbool bDontPrint = false;\n\tif(x <= 0.0f || x > SCREEN_WIDTH ||\n\t   y <= 0.0f || y > SCREEN_HEIGHT)\t// BUG: game uses SCREENW again\n\t\treturn;\n\n\tbDontPrint = c == '\\0';\n\tfloat w = GetCharacterWidth(c) / 32.0f;\n\tif (Details.bFontHalfTexture && c == 208)\n\t\tc = '\\0';\n\tfloat xoff = c % 16;\n\tfloat yoff = c / 16;\n#ifdef MORE_LANGUAGES\n\tif (IsJapaneseFont()) {\n\t\tw = 21.0f;\n\t\txoff = (float)(c % 48);\n\t\tyoff = c / 48;\n\t}\n#endif\n\n\tif(RenderState.style == FONT_BANK || RenderState.style == FONT_STANDARD){\n\t\tif (bDontPrint) return;\n\t\tif (RenderState.slant == 0.0f) {\n#ifdef FIX_BUGS\n\t\t\tif (c < 192) {\n#else\n\t\t\tif (c < 193) {\n#endif\n\t\t\t\tCSprite2d::AddToBuffer(\n\t\t\t\t\tCRect(x, y,\n\t\t\t\t\t\tx + 32.0f * RenderState.scaleX * 1.0f,\n\t\t\t\t\t\ty + 40.0f * RenderState.scaleY * 0.5f),\n\t\t\t\t\tRenderState.color,\n\t\t\t\t\txoff / 16.0f, yoff / 12.8f + 0.0021f,\n\t\t\t\t\t(xoff + 1.0f) / 16.0f - 0.001f, yoff / 12.8f + 0.0021f,\n\t\t\t\t\txoff / 16.0f, (yoff + 1.0f) / 12.8f - 0.0021f,\n\t\t\t\t\t(xoff + 1.0f) / 16.0f - 0.001f, (yoff + 1.0f) / 12.8f - 0.0021f);\n\t\t\t} else {\n\t\t\t\tCSprite2d::AddToBuffer(\n\t\t\t\t\tCRect(x, y,\n\t\t\t\t\t\tx + 32.0f * RenderState.scaleX * 1.0f,\n\t\t\t\t\t\ty + 33.0f * RenderState.scaleY * 0.5f),\n\t\t\t\t\tRenderState.color,\n\t\t\t\t\txoff / 16.0f, yoff / 12.8f + 0.0021f,\n\t\t\t\t\t(xoff + 1.0f) / 16.0f - 0.001f, yoff / 12.8f + 0.0021f,\n\t\t\t\t\txoff / 16.0f, (yoff + 1.0f) / 12.8f - 0.017f,\n\t\t\t\t\t(xoff + 1.0f) / 16.0f - 0.001f, (yoff + 1.0f) / 12.8f - 0.017f);\n\t\t\t}\n\t\t} else\n\t\t\tCSprite2d::AddToBuffer(\n\t\t\t\tCRect(x, y,\n\t\t\t\t\tx + 32.0f * RenderState.scaleX * 1.0f,\n\t\t\t\t\ty + 40.0f * RenderState.scaleY * 0.5f),\n\t\t\t\tRenderState.color,\n\t\t\t\txoff / 16.0f, yoff / 12.8f + 0.00055f,\n\t\t\t\t(xoff + 1.0f) / 16.0f - 0.001f, yoff / 12.8f + 0.0021f + 0.01f,\n\t\t\t\txoff / 16.0f, (yoff + 1.0f) / 12.8f - 0.009f,\n\t\t\t\t(xoff + 1.0f) / 16.0f - 0.001f, (yoff + 1.0f) / 12.8f - 0.0021f + 0.01f);\n#ifdef MORE_LANGUAGES\n\t/*}else if (IsJapaneseFont()) {\n\t\tif (Details.dropShadowPosition != 0) {\n\t\t\tCSprite2d::AddSpriteToBank(Details.bank + Details.style,\t// BUG: game doesn't add bank\n\t\t\t\tCRect(x + SCREEN_SCALE_X(Details.dropShadowPosition),\n\t\t\t\t\ty + SCREEN_SCALE_Y(Details.dropShadowPosition),\n\t\t\t\t\tx + SCREEN_SCALE_X(Details.dropShadowPosition) + 32.0f * Details.scaleX * 1.0f,\n\t\t\t\t\ty + SCREEN_SCALE_Y(Details.dropShadowPosition) + 40.0f * Details.scaleY / 2.75f),\n\t\t\t\tDetails.dropColor,\n\t\t\t\txoff * w / 1024.0f, yoff / 25.6f,\n\t\t\t\txoff * w / 1024.0f + (1.0f / 48.0f) - 0.001f, yoff / 25.6f,\n\t\t\t\txoff * w / 1024.0f, (yoff + 1.0f) / 25.6f,\n\t\t\t\txoff * w / 1024.0f + (1.0f / 48.0f) - 0.001f, (yoff + 1.0f) / 25.6f - 0.0001f);\n\t\t}\n\t\tCSprite2d::AddSpriteToBank(Details.bank + Details.style,\t// BUG: game doesn't add bank\n\t\t\tCRect(x, y,\n\t\t\t\tx + 32.0f * Details.scaleX * 1.0f,\n\t\t\t\ty + 40.0f * Details.scaleY / 2.75f),\n\t\t\tDetails.color,\n\t\t\txoff * w / 1024.0f, yoff / 25.6f,\n\t\t\txoff * w / 1024.0f + (1.0f / 48.0f) - 0.001f, yoff / 25.6f,\n\t\t\txoff * w / 1024.0f, (yoff + 1.0f) / 25.6f - 0.002f,\n\t\t\txoff * w / 1024.0f + (1.0f / 48.0f) - 0.001f, (yoff + 1.0f) / 25.6f - 0.0001f);*/\n#endif\n\t} else {\n\t\tif (bDontPrint) return;\n\t\tCSprite2d::AddToBuffer(\n\t\t\tCRect(x, y,\n\t\t\t\tx + 32.0f * RenderState.scaleX * w,\n\t\t\t\ty + 32.0f * RenderState.scaleY * 0.5f),\n\t\t\tRenderState.color,\n\t\t\txoff / 16.0f, yoff / 16.0f,\n\t\t\t(xoff + w) / 16.0f, yoff / 16.0f,\n\t\t\txoff / 16.0f, (yoff + 1.0f) / 16.0f,\n\t\t\t(xoff + w) / 16.0f - 0.0001f, (yoff + 1.0f) / 16.0f - 0.0001f);\n\t}\n}\n\n#ifdef MORE_LANGUAGES\nbool CFont::IsJapanesePunctuation(wchar *str)\n{\n\treturn (*str == 0xE7 || *str == 0x124 || *str == 0x126 || *str == 0x128 || *str == 0x104 || *str == ',' || *str == '>' || *str == '!' || *str == 0x99 || *str == '?' || *str == ':');\n}\n\nbool CFont::IsAnsiCharacter(wchar *s)\n{\n\tif (*s >= 'A' && *s <= 'Z')\n\t\treturn true;\n\tif (*s >= 'a' && *s <= 'z')\n\t\treturn true;\n\tif (*s >= '0' && *s <= ':')\n\t\treturn true;\n\tif (*s == '(' || *s == ')')\n\t\treturn true;\n\tif (*s == 'D' || *s == '$')\n\t\treturn true;\n\treturn false;\n}\n#endif\n\nvoid\nCFont::RenderFontBuffer()\n{\n\tif (FontRenderStatePointer.pRenderState == (CFontRenderState*)FontRenderStateBuf) return;\n\n\tfloat textPosX;\n\tfloat textPosY;\n\tCRGBA color;\n\tbool bBold = false;\n\tbool bFlash = false;\n\n\tSprite[RenderState.style].SetRenderState();\n\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);\n\tRenderState = *(CFontRenderState*)&FontRenderStateBuf[0];\n\ttextPosX = RenderState.fTextPosX;\n\ttextPosY = RenderState.fTextPosY;\n\tcolor = RenderState.color;\n\ttFontRenderStatePointer pRenderStateBufPointer;\n\tpRenderStateBufPointer.pRenderState = (CFontRenderState*)&FontRenderStateBuf[0];\n\tfor (++pRenderStateBufPointer.pRenderState; pRenderStateBufPointer.pStr < FontRenderStatePointer.pStr; pRenderStateBufPointer.pStr++) {\n\t\tif (*pRenderStateBufPointer.pStr == '\\0') {\n\t\t\ttFontRenderStatePointer tmpPointer = pRenderStateBufPointer;\n\t\t\ttmpPointer.pStr++;\n\t\t\ttmpPointer.Align();\n\t\t\tif (tmpPointer.pStr >= FontRenderStatePointer.pStr)\n\t\t\t\tbreak;\n\n\t\t\tRenderState = *(tmpPointer.pRenderState++);\n\n\t\t\tpRenderStateBufPointer = tmpPointer;\n\n\t\t\ttextPosX = RenderState.fTextPosX;\n\t\t\ttextPosY = RenderState.fTextPosY;\n\t\t\tcolor = RenderState.color;\n\t\t}\n\t\tif (*pRenderStateBufPointer.pStr == '~') {\n#ifdef BUTTON_ICONS\n\t\t\tPS2Symbol = BUTTON_NONE;\n#endif\n\t\t\tpRenderStateBufPointer.pStr = ParseToken(pRenderStateBufPointer.pStr, color, bFlash, bBold);\n#ifdef BUTTON_ICONS\n\t\t\tif(PS2Symbol != BUTTON_NONE) {\n\t\t\t\tDrawButton(textPosX, textPosY);\n\t\t\t\ttextPosX += RenderState.scaleY * 17.0f;\n\t\t\t\tPS2Symbol = BUTTON_NONE;\n\t\t\t}\n#endif\n\t\t\tif (bFlash) {\n\t\t\t\tif (CTimer::GetTimeInMilliseconds() - Details.nFlashTimer > 300) {\n\t\t\t\t\tDetails.bFlashState = !Details.bFlashState;\n\t\t\t\t\tDetails.nFlashTimer = CTimer::GetTimeInMilliseconds();\n\t\t\t\t}\n\t\t\t\tDetails.color.alpha = Details.bFlashState ? 0 : 255;\n\t\t\t}\n\t\t\tif (!RenderState.bIsShadow)\n\t\t\t\tRenderState.color = color;\n\t\t}\n\t\twchar c = *pRenderStateBufPointer.pStr;\n\t\tc -= ' ';\n\t\tif (RenderState.bFontHalfTexture) \n\t\t\tc = FindNewCharacter(c); \n\t\telse if (c > 155) \n\t\t\tc = '\\0'; \n\n\t\tif (RenderState.slant != 0.0f)\n\t\t\ttextPosY = (RenderState.slantRefX - textPosX) * RenderState.slant + RenderState.slantRefY;\n\t\tPrintChar(textPosX, textPosY, c);\n\t\tif (bBold) {\n\t\t\tPrintChar(textPosX + 1.0f, textPosY, c);\n\t\t\tPrintChar(textPosX + 2.0f, textPosY, c);\n\t\t\ttextPosX += 2.0f;\n\t\t}\n#ifdef FIX_BUGS\n\t\t// PS2 uses different chars for some symbols\n\t\tif (!RenderState.bFontHalfTexture && c == 30) c = 61; // wanted star\n#endif\n\t\ttextPosX += RenderState.scaleX * GetCharacterWidth(c);\n\t\tif (c == '\\0')\n\t\t\ttextPosX += RenderState.fExtraSpace;\n\t}\n\tCSprite2d::RenderVertexBuffer();\n\tFontRenderStatePointer.pRenderState = (CFontRenderState*)FontRenderStateBuf;\n}\n\n#if 0 //def MORE_LANGUAGES\nbool\nCFont::PrintString(float x, float y, wchar *start, wchar *&end, float spwidth, float japX)\n{\n\twchar *s, c, unused;\n\n\tif (IsJapanese()) {\n\t\tfloat jx = 0.0f;\n\t\tfor (s = start; s < end; s++) {\n\t\t\tif (*s == JAP_TERMINATION || *s == '~')\n\t\t\t\ts = ParseToken(s, &unused, true);\n\t\t\tif (NewLine) {\n\t\t\t\tNewLine = false;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tjx += GetCharacterSize(*s - ' ');\n\t\t}\n\t\ts = start;\n\t\tif (Details.centre)\n\t\t\tx = japX - jx / 2.0f;\n\t\telse if (Details.rightJustify)\n\t\t\tx = japX - jx;\n\t}\n\n\tfor (s = start; s < end; s++) {\n\t\tif (*s == '~' || (IsJapanese() && *s == JAP_TERMINATION))\n\t\t\ts = ParseToken(s, &unused);\n\t\tif (NewLine && IsJapanese()) {\n\t\t\tNewLine = false;\n\t\t\tend = s;\n\t\t\treturn true;\n\t\t}\n\t\tc = *s - ' ';\n\t\tif (Details.slant != 0.0f && !IsJapanese())\n\t\t\ty = (Details.slantRefX - x) * Details.slant + Details.slantRefY;\n\n\t\tPrintChar(x, y, c);\n\t\tx += GetCharacterSize(c);\n\t\tif (c == 0 && (!NewLine || !IsJapanese()))\t// space\n\t\t\tx += spwidth;\n\t}\n\treturn false;\n}\n#else\nvoid\nCFont::PrintString(float x, float y, uint32, wchar *start, wchar *end, float spwidth)\n{\n\twchar *s;\n\n\tif (RenderState.style != Details.style) {\n\t\tRenderFontBuffer();\n\t\tRenderState.style = Details.style;\n\t}\n\n\tfloat dropShadowPosition = Details.dropShadowPosition;\n\tif (dropShadowPosition != 0.0f && (Details.style == FONT_BANK || Details.style == FONT_STANDARD)) {\n\t\tCRGBA color = Details.color;\n\t\tDetails.color = Details.dropColor;\n\t\tDetails.dropShadowPosition = 0;\n\t\tDetails.bIsShadow = true;\n\t\tif (Details.slant != 0.0f) {\n\t\t\tDetails.slantRefX += SCREEN_SCALE_X(dropShadowPosition);\n\t\t\tDetails.slantRefY += SCREEN_SCALE_Y(dropShadowPosition);\n\t\t\tPrintString(SCREEN_SCALE_X(dropShadowPosition) + x, SCREEN_SCALE_Y(dropShadowPosition) + y, Details.anonymous_25, start, end, spwidth);\n\t\t\tDetails.slantRefX -= SCREEN_SCALE_X(dropShadowPosition);\n\t\t\tDetails.slantRefY -= SCREEN_SCALE_Y(dropShadowPosition);\n\t\t} else {\n\t\t\tPrintString(SCREEN_SCALE_X(dropShadowPosition) + x, SCREEN_SCALE_Y(dropShadowPosition) + y, Details.anonymous_25, start, end, spwidth);\n\t\t}\n\t\tDetails.color = color;\n\t\tDetails.dropShadowPosition = dropShadowPosition;\n\t\tDetails.bIsShadow = false;\n\t}\n\tif (FontRenderStatePointer.pStr >= (wchar*)&FontRenderStateBuf[ARRAY_SIZE(FontRenderStateBuf)] - (end - start + 26)) // why 26?\n\t\tRenderFontBuffer();\n\tCFontRenderState *pRenderState = FontRenderStatePointer.pRenderState;\n\tpRenderState->fTextPosX = x;\n\tpRenderState->fTextPosY = y;\n\tpRenderState->scaleX = Details.scaleX;\n\tpRenderState->scaleY = Details.scaleY;\n\tpRenderState->color = Details.color;\n\tpRenderState->fExtraSpace = spwidth;\n\tpRenderState->slant = Details.slant;\n\tpRenderState->slantRefX = Details.slantRefX;\n\tpRenderState->slantRefY = Details.slantRefY;\n\tpRenderState->bFontHalfTexture = Details.bFontHalfTexture;\n\tpRenderState->proportional = Details.proportional;\n\tpRenderState->style = Details.style;\n\tpRenderState->bIsShadow = Details.bIsShadow;\n\tFontRenderStatePointer.pRenderState++;\n\n\tfor(s = start; s < end;){\n\t\tif (*s == '~') {\n\t\t\tfor (wchar *i = ParseToken(s); s != i; FontRenderStatePointer.pStr++) {\n\t\t\t\t*FontRenderStatePointer.pStr = *(s++);\n\t\t\t}\n\t\t\tif (Details.bFlash) {\n\t\t\t\tif (CTimer::GetTimeInMilliseconds() - Details.nFlashTimer > 300) {\n\t\t\t\t\tDetails.bFlashState = !Details.bFlashState;\n\t\t\t\t\tDetails.nFlashTimer = CTimer::GetTimeInMilliseconds();\n\t\t\t\t}\n\t\t\t\tDetails.color.a = Details.bFlashState ? 0 : 255;\n\t\t\t}\n\t\t} else\n\t\t\t*(FontRenderStatePointer.pStr++) = *(s++);\n\t}\n\t*(FontRenderStatePointer.pStr++) = '\\0';\n\tFontRenderStatePointer.Align();\n}\n#endif\n\nvoid\nCFont::PrintStringFromBottom(float x, float y, wchar *str)\n{\n\ty -= (32.0f * Details.scaleY / 2.0f + 2.0f * Details.scaleY) * GetNumberLines(x, y, str);\n\tif (Details.slant != 0.0f)\n\t\ty -= ((Details.slantRefX - x) * Details.slant + Details.slantRefY);\n\tPrintString(x, y, str);\n}\n\nvoid\nCFont::PrintString(float xstart, float ystart, wchar *s)\n{\n\tCRect rect;\n\tint numSpaces;\n\tfloat lineLength;\n\tfloat x, y;\n\tbool first;\n\twchar *start, *t;\n\n\tDetails.bFlash = false;\n\n\tif(*s == '*')\n\t\treturn;\n\n\tDetails.anonymous_25++;\n\tif(Details.background){\n\t\tRenderState.color = Details.color;\n\t\tGetNumberLines(xstart, ystart, s);\t// BUG: result not used\n\t\tGetTextRect(&rect, xstart, ystart, s);\n\t\tCSprite2d::DrawRect(rect, Details.backgroundColor);\n\t}\n\n\tlineLength = 0.0f;\n\tnumSpaces = 0;\n\tfirst = true;\n\tif(Details.centre || Details.rightJustify)\n\t\tx = 0.0f;\n\telse\n\t\tx = xstart;\n\ty = ystart;\n\tstart = s;\n\n\t// This is super ugly, I blame R*\n\tfor(;;){\n\t\tfor(;;){\n\t\t\tfor(;;){\n\t\t\t\tif(*s == '\\0')\n\t\t\t\t\treturn;\n\t\t\t\tfloat xend = Details.centre ? Details.centreSize :\n\t\t\t\t           Details.rightJustify ? xstart - Details.rightJustifyWrap :\n\t\t\t\t           Details.wrapX;\n#ifdef MORE_LANGUAGES\n\t\t\t\tif (IsJapaneseFont())\n\t\t\t\t\txend -= SCREEN_SCALE_X(21.0f * 2.0f);\n#endif\n\t\t\t\tif(x + GetStringWidth(s) > xend && !first){\n#ifdef MORE_LANGUAGES\n\t\t\t\t\tif (IsJapanese() && IsJapanesePunctuation(s))\n\t\t\t\t\t\ts--;\n#endif\n\t\t\t\t\t// flush line\n\t\t\t\t\tfloat spaceWidth = !Details.justify || Details.centre ? 0.0f :\n\t\t\t\t\t\t(Details.wrapX - lineLength) / numSpaces;\n\t\t\t\t\tfloat xleft = Details.centre ? xstart - x/2 :\n\t\t\t\t\t              Details.rightJustify ? xstart - x :\n\t\t\t\t\t              xstart;\n#if 0//def MORE_LANGUAGES\n\t\t\t\t\tPrintString(xleft, y, start, s, spaceWidth, xstart);\n#else\n\t\t\t\t\tPrintString(xleft, y, Details.anonymous_25, start, s, spaceWidth);\n#endif\n\t\t\t\t\t// reset things\n\t\t\t\t\tlineLength = 0.0f;\n\t\t\t\t\tnumSpaces = 0;\n\t\t\t\t\tfirst = true;\n\t\t\t\t\tif(Details.centre || Details.rightJustify)\n\t\t\t\t\t\tx = 0.0f;\n\t\t\t\t\telse\n\t\t\t\t\t\tx = xstart;\n#ifdef MORE_LANGUAGES\n\t\t\t\t\tif (IsJapaneseFont())\n\t\t\t\t\t\ty += 32.0f * Details.scaleY / 2.75f + 2.0f * Details.scaleY;\n\t\t\t\t\telse\n#endif\n\t\t\t\t\t\ty += 32.0f * Details.scaleY * 0.5f + 2.0f * Details.scaleY;\n\t\t\t\t\tstart = s;\n\t\t\t\t}else\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\t// advance by one word\n\t\t\tt = GetNextSpace(s);\n\t\t\tif(t[0] == '\\0' ||\n\t\t\t   t[0] == ' ' && t[1] == '\\0')\n\t\t\t\tbreak;\n\t\t\tif(!first)\n\t\t\t\tnumSpaces++;\n\t\t\tfirst = false;\n\t\t\tx += GetStringWidth(s) + GetCharacterSize(*t - ' ');\n#ifdef MORE_LANGUAGES\n\t\t\tif (IsJapaneseFont() && IsAnsiCharacter(s))\n\t\t\t\tx += 21.0f;\n#endif\n\t\t\tlineLength = x;\n\t\t\ts = t+1;\n#if 0 //def MORE_LANGUAGES\n\t\t\tif (IsJapaneseFont() && !*s) {\n\t\t\t\tx += GetStringWidth(s);\n\t\t\t\tif (IsAnsiCharacter(s))\n\t\t\t\t\tx += 21.0f;\n\t\t\t\tfloat xleft = Details.centre ? xstart - x / 2 :\n\t\t\t\t\tDetails.rightJustify ? xstart - x :\n\t\t\t\t\txstart;\n\t\t\t\tif (PrintString(xleft, y, start, s, 0.0f, xstart))\n\t\t\t\t{\n\t\t\t\t\tstart = s;\n\t\t\t\t\tif (!Details.centre && !Details.rightJustify)\n\t\t\t\t\t\tx = xstart;\n\t\t\t\t\telse\n\t\t\t\t\t\tx = 0.0f;\n\n\t\t\t\t\ty += 32.0f * Details.scaleY / 2.75f + 2.0f * Details.scaleY;\n\t\t\t\t\tnumSpaces = 0;\n\t\t\t\t\tfirst = true;\n\t\t\t\t\tlineLength = 0.0f;\n\t\t\t\t}\n\t\t\t}\n#endif\n\t\t}\n\t\t// print rest\n\t\tif(t[0] == ' ' && t[1] == '\\0')\n\t\t\tt[0] = '\\0';\n\t\tx += GetStringWidth(s);\n\t\ts = t;\n\t\tfloat xleft = Details.centre ? xstart - x/2 :\n\t\t              Details.rightJustify ? xstart - x :\n\t\t              xstart;\n#if 0 //def MORE_LANGUAGES\n\t\tif (PrintString(xleft, y, start, s, 0.0f, xstart) && IsJapaneseFont()) {\n\t\t\tstart = s;\n\t\t\tif (!Details.centre && !Details.rightJustify)\n\t\t\t\tx = xstart;\n\t\t\telse\n\t\t\t\tx = 0.0f;\n\t\t\ty += 32.0f * Details.scaleY / 2.75f + 2.0f * Details.scaleY;\n\t\t\tnumSpaces = 0;\n\t\t\tfirst = true;\n\t\t\tlineLength = 0.0f;\n\t\t}\n#else\n\t\tPrintString(xleft, y, Details.anonymous_25, start, s, 0.0f);\n#endif\n\t}\n}\n\nint\nCFont::GetNumberLines(float xstart, float ystart, wchar *s)\n{\n\tint n;\n\tfloat x, y;\n\twchar *t;\n\tn = 0;\n\n#if 0//def MORE_LANGUAGES\n\tbool bSomeJapBool = false;\n\n\tif (IsJapanese()) {\n\t\tt = s;\n\t\twchar unused;\n\t\twhile (*t) {\n\t\t\tif (*t == JAP_TERMINATION || *t == '~')\n\t\t\t\tt = ParseToken(t, &unused, true);\n\t\t\tif (NewLine) {\n\t\t\t\tn++;\n\t\t\t\tNewLine = false;\n\t\t\t\tbSomeJapBool = true;\n\t\t\t}\n\t\t\tt++;\n\t\t}\n\t}\n\n\tif (bSomeJapBool) n--;\n#endif\n\n\tif(Details.centre || Details.rightJustify)\n\t\tx = 0.0f;\n\telse\n\t\tx = xstart;\n\ty = ystart;\n\n\twhile(*s){\n#ifdef FIX_BUGS\n\t\tfloat f = Details.centre ? Details.centreSize :\n\t\t           Details.rightJustify ? xstart - Details.rightJustifyWrap :\n\t\t           Details.wrapX;\n#else\n\t\tfloat f = (Details.centre ? Details.centreSize : Details.wrapX);\n#endif\n\n#ifdef MORE_LANGUAGES\n\t\tif (IsJapaneseFont())\n\t\t\tf -= SCREEN_SCALE_X(21.0f * 2.0f);\n#endif\n\n\t\tif(x + GetStringWidth(s) > f){\n#ifdef MORE_LANGUAGES\n\t\t\tif (IsJapanese())\n\t\t\t{\n\t\t\t\tif (IsJapanesePunctuation(s))\n\t\t\t\t\ts--;\n\t\t\t}\n#endif\n\t\t\t// reached end of line\n\t\t\tif(Details.centre || Details.rightJustify)\n\t\t\t\tx = 0.0f;\n\t\t\telse\n\t\t\t\tx = xstart;\n\t\t\tn++;\n\t\t\t// Why even?\n#ifdef MORE_LANGUAGES\n\t\t\tif (IsJapanese())\n\t\t\t\ty += 32.0f * Details.scaleY / 2.75f + 2.0f * Details.scaleY;\n\t\t\telse\n#endif\n\t\t\t\ty += 32.0f * Details.scaleY * 0.5f + 2.0f * Details.scaleY;\n\t\t}else{\n\t\t\t// still space in current line\n\t\t\tt = GetNextSpace(s);\n\t\t\tif(*t == '\\0'){\n\t\t\t\t// end of string\n\t\t\t\tx += GetStringWidth(s);\n#ifdef MORE_LANGUAGES\n\t\t\t\tif (IsJapanese() && IsAnsiCharacter(s))\n\t\t\t\t\tx += 21.0f;\n#endif\n\t\t\t\tn++;\n\t\t\t\ts = t;\n\t\t\t}else{\n\t\t\t\tx += GetStringWidth(s);\n#ifdef MORE_LANGUAGES\n\t\t\t\tif (IsJapanese() && IsAnsiCharacter(s))\n\t\t\t\t\tx += 21.0f;\n#endif\n\t\t\t\ts = t+1;\n\t\t\t\tx += GetCharacterSize(*t - ' ');\n#ifdef MORE_LANGUAGES\n\t\t\t\tif (IsJapanese() && !*s)\n\t\t\t\t\tn++;\n#endif\n\t\t\t}\n\t\t}\n\t}\n\n\treturn n;\n}\n\nvoid\nCFont::GetTextRect(CRect *rect, float xstart, float ystart, wchar *s)\n{\n\tint numLines;\n\tfloat x, y;\n\tint16 maxlength;\n\twchar *t;\n\n\tmaxlength = 0;\n\tnumLines = 0;\n\n#ifdef MORE_LANGUAGES\n\tif (IsJapanese()) {\n\t\tnumLines = GetNumberLines(xstart, ystart, s);\n\t}else{\n#endif\n\t\tif(Details.centre || Details.rightJustify)\n\t\t\tx = 0.0f;\n\t\telse\n\t\t\tx = xstart;\n\t\ty = ystart;\n\n#ifdef FIX_BUGS\n\t\tfloat xEnd = Details.centre ? Details.centreSize :\n\t\t           Details.rightJustify ? xstart - Details.rightJustifyWrap :\n\t\t           Details.wrapX;\n#else\n\t\tfloat xEnd = (Details.centre ? Details.centreSize : Details.wrapX);\n#endif\n\t\twhile(*s){\n\t\t\tif(x + GetStringWidth(s) > xEnd){\n\t\t\t\t// reached end of line\n\t\t\t\tif(x > maxlength)\n\t\t\t\t\tmaxlength = x;\n\t\t\t\tif(Details.centre || Details.rightJustify)\n\t\t\t\t\tx = 0.0f;\n\t\t\t\telse\n\t\t\t\t\tx = xstart;\n\t\t\t\tnumLines++;\n\t\t\t\ty += 32.0f * Details.scaleY * 0.5f + 2.0f * Details.scaleY;\n\t\t\t}else{\n\t\t\t\t// still space in current line\n\t\t\t\tt = GetNextSpace(s);\n\t\t\t\tif(*t == '\\0'){\n\t\t\t\t\t// end of string\n\t\t\t\t\tx += GetStringWidth(s);\n\t\t\t\t\tif(x > maxlength)\n\t\t\t\t\t\tmaxlength = x;\n\t\t\t\t\tnumLines++;\n\t\t\t\t\ts = t;\n\t\t\t\t}else{\n\t\t\t\t\tx += GetStringWidth(s);\n\t\t\t\t\tx += GetCharacterSize(*t - ' ');\n\t\t\t\t\ts = t+1;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n#ifdef MORE_LANGUAGES\n\t}\n#endif\n\n\tif(Details.centre){\n\t\tif(Details.backgroundOnlyText){\n\t\t\trect->left = xstart - maxlength/2 - 4.0f;\n\t\t\trect->right = xstart + maxlength/2 + 4.0f;\n#ifdef MORE_LANGUAGES\n\t\t\tif (IsJapaneseFont()) {\n\t\t\t\trect->bottom = (32.0f * Details.scaleY / 2.75f + 2.0f * Details.scaleY) * numLines + ystart + (4.0f / 2.75f);\n\t\t\t\trect->top = ystart - (4.0f / 2.75f);\n\t\t\t} else {\n#endif\n\t\t\t\trect->bottom = (32.0f * Details.scaleY * 0.5f + 2.0f * Details.scaleY) * numLines + ystart + 2.0f;\n\t\t\t\trect->top = ystart - 2.0f;\n#ifdef MORE_LANGUAGES\n\t\t\t}\n#endif\n\t\t}else{\n\t\t\trect->left = xstart - Details.centreSize*0.5f - 4.0f;\n\t\t\trect->right = xstart + Details.centreSize*0.5f + 4.0f;\n#ifdef MORE_LANGUAGES\n\t\t\tif (IsJapaneseFont()) {\n\t\t\t\trect->bottom = (32.0f * Details.scaleY / 2.75f + 2.0f * Details.scaleY) * numLines + ystart + (4.0f / 2.75f);\n\t\t\t\trect->top = ystart - (4.0f / 2.75f);\n\t\t\t} else {\n#endif\n\t\t\t\trect->bottom = (32.0f * Details.scaleY * 0.5f + 2.0f * Details.scaleY) * numLines + ystart + 2.0f;\n\t\t\t\trect->top = ystart - 2.0f;\n#ifdef MORE_LANGUAGES\n\t\t\t}\n#endif\n\t\t}\n\t}else{\n\t\trect->left = xstart - 4.0f;\n\t\trect->right = Details.wrapX;\n\t\t// WTF?\n\t\trect->bottom = ystart - 4.0f + 4.0f;\n#ifdef MORE_LANGUAGES\n\t\tif (IsJapaneseFont())\n\t\t\trect->top = (32.0f * Details.scaleY / 2.75f + 2.0f * Details.scaleY) * numLines + ystart + 2.0f + (4.0f / 2.75f);\n\t\telse\n#endif\n\t\t\trect->top = (32.0f * Details.scaleY * 0.5f + 2.0f * Details.scaleY) * numLines + ystart + 2.0f + 2.0f;\n\t}\n}\n\nfloat\nCFont::GetCharacterWidth(wchar c)\n{\n#ifdef MORE_LANGUAGES\n\tif (IsJapanese()) {\n\t\tif (!RenderState.proportional)\n\t\t\treturn Size[0][Details.style][192];\n\t\tif (c <= 94 || Details.style == FONT_HEADING || RenderState.style == FONT_BANK) {\n\t\t\tswitch (RenderState.style)\n\t\t\t{\n\t\t\tcase FONT_JAPANESE:\n\t\t\t\treturn Size_jp[c];\n\t\t\tdefault:\n\t\t\t\treturn Size[0][RenderState.style][c];\n\t\t\t}\n\t\t}\n\n\t\tswitch (RenderState.style)\n\t\t{\n\t\tcase FONT_JAPANESE:\n\t\t\treturn 29.4f;\n\t\tcase FONT_BANK:\n\t\t\treturn 10.0f;\n\t\tdefault:\n\t\t\treturn Size[0][RenderState.style][c];\n\t\t}\n\t}\n\n\telse if (RenderState.proportional)\n\t\treturn Size[LanguageSet][RenderState.style][c];\n\telse\n\t\treturn Size[LanguageSet][RenderState.style][209];\n#else\n\n\tif (RenderState.proportional)\n\t\treturn Size[RenderState.style][c];\n\telse\n\t\treturn Size[RenderState.style][209];\n#endif // MORE_LANGUAGES\n}\n\nfloat\nCFont::GetCharacterSize(wchar c)\n{\n#ifdef MORE_LANGUAGES\n\n\tif (IsJapanese())\n\t{\n\t\tif (!Details.proportional)\n\t\t\treturn Size[0][Details.style][209] * Details.scaleX;\n\t\tif (c <= 94 || Details.style == FONT_HEADING || Details.style == FONT_BANK) {\n\t\t\tswitch (Details.style)\n\t\t\t{\n\t\t\tcase FONT_JAPANESE:\n\t\t\t\treturn Size_jp[c] * Details.scaleX;\n\t\t\tdefault:\n\t\t\t\treturn Size[0][Details.style][c] * Details.scaleX;\n\t\t\t}\n\t\t}\n\n\t\tswitch (Details.style)\n\t\t{\n\t\tcase FONT_JAPANESE:\n\t\t\treturn 29.4f * Details.scaleX;\n\t\tcase FONT_BANK:\n\t\t\treturn 10.0f * Details.scaleX;\n\t\tdefault:\n\t\t\treturn Size[0][Details.style][c] * Details.scaleX;\n\t\t}\n\t}\n\telse\n\t{\n\t\tif (!Details.bFontHalfTexture && c == 30) c = 61; // wanted star\n\t\tif (Details.bFontHalfTexture)\n\t\t\tc = FindNewCharacter(c);\n\t\tif (Details.proportional)\n\t\t\treturn Size[LanguageSet][Details.style][c] * Details.scaleX;\n\t\telse\n\t\t\treturn Size[LanguageSet][Details.style][209] * Details.scaleX;\n\t}\n#else\n\n#ifdef FIX_BUGS\n\t// PS2 don't call FindNewCharacter in here at all, and also uses different chars for some symbols\n\tif (!Details.bFontHalfTexture && c == 30) c = 61; // wanted star\n#endif\n\tif (Details.bFontHalfTexture)\n\t\tc = FindNewCharacter(c);\n\tif (Details.proportional)\n\t\treturn Size[Details.style][c] * Details.scaleX;\n\telse\n\t\treturn Size[Details.style][209] * Details.scaleX;\n#endif // MORE_LANGUAGES\n}\n\nfloat\nCFont::GetStringWidth(wchar *s, bool spaces)\n{\n\tfloat w;\n\n\tw = 0.0f;\n#ifdef MORE_LANGUAGES\n\tif (IsJapanese())\n\t{\n\t\tdo\n\t\t{\n\t\t\tif ((*s != ' ' || spaces) && *s != '\\0') {\n\t\t\t\tdo {\n\t\t\t\t\twhile (*s == '~' || *s == JAP_TERMINATION) {\n\t\t\t\t\t\ts++;\n#ifdef BUTTON_ICONS\n\t\t\t\t\t\tswitch (*s) {\n\t\t\t\t\t\tcase 'U':\n\t\t\t\t\t\tcase 'D':\n\t\t\t\t\t\tcase '<':\n\t\t\t\t\t\tcase '>':\n\t\t\t\t\t\tcase 'X':\n\t\t\t\t\t\tcase 'O':\n\t\t\t\t\t\tcase 'Q':\n\t\t\t\t\t\tcase 'T':\n\t\t\t\t\t\tcase 'K':\n\t\t\t\t\t\tcase 'M':\n\t\t\t\t\t\tcase 'A':\n\t\t\t\t\t\tcase 'J':\n\t\t\t\t\t\tcase 'V':\n\t\t\t\t\t\tcase 'C':\n\t\t\t\t\t\tcase '(':\n\t\t\t\t\t\tcase ')':\n\t\t\t\t\t\t\tw += 17.0f * Details.scaleY;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n#endif\n\t\t\t\t\t\twhile (!(*s == '~' || *s == JAP_TERMINATION)) s++;\n\t\t\t\t\t\ts++;\n\t\t\t\t\t}\n\t\t\t\t\tw += GetCharacterSize(*s - ' ');\n\t\t\t\t\t++s;\n\t\t\t\t} while (*s == '~' || *s == JAP_TERMINATION);\n\t\t\t}\n\t\t} while (IsAnsiCharacter(s));\n\t} else\n#endif\n\t{\n\t\tfor (wchar c = *s; (c != ' ' || spaces) && c != '\\0'; c = *(++s)) {\n\t\t\tif (c == '~') {\n\t\t\t\ts++;\n#ifdef BUTTON_ICONS\n\t\t\t\tswitch (*s) {\n\t\t\t\tcase 'U':\n\t\t\t\tcase 'D':\n\t\t\t\tcase '<':\n\t\t\t\tcase '>':\n\t\t\t\tcase 'X':\n\t\t\t\tcase 'O':\n\t\t\t\tcase 'Q':\n\t\t\t\tcase 'T':\n\t\t\t\tcase 'K':\n\t\t\t\tcase 'M':\n\t\t\t\tcase 'A':\n\t\t\t\tcase 'J':\n\t\t\t\tcase 'V':\n\t\t\t\tcase 'C':\n\t\t\t\tcase '(':\n\t\t\t\tcase ')':\n\t\t\t\t\tw += 17.0f * Details.scaleY;\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t\t}\n#endif\n\t\t\t\twhile (*s != '~') {\n\t\t\t\t\ts++;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tw += GetCharacterSize(c - ' ');\n\t\t\t}\n\t\t}\n\t}\n\treturn w;\n}\n\n\n#ifdef MORE_LANGUAGES\nfloat\nCFont::GetStringWidth_Jap(wchar* s)\n{\n\tfloat w;\n\n\tw = 0.0f;\n\tfor (; *s != '\\0';) {\n\t\tdo {\n\t\t\twhile (*s == '~' || *s == JAP_TERMINATION) {\n\t\t\t\ts++;\n\t\t\t\twhile (!(*s == '~' || *s == JAP_TERMINATION)) s++;\n\t\t\t\ts++;\n\t\t\t}\n\t\t\tw += GetCharacterSize(*s - ' ');\n\t\t\t++s;\n\t\t} while (*s == '~' || *s == JAP_TERMINATION);\n\t}\n\treturn w;\n}\n#endif\n\nwchar*\nCFont::GetNextSpace(wchar *s)\n{\n#ifdef MORE_LANGUAGES\n\tif (IsJapanese()) {\n\t\tdo\n\t\t{\n\t\t\tif (*s != ' ' && *s != '\\0') {\n\t\t\t\tdo {\n\t\t\t\t\twhile (*s == '~' || *s == JAP_TERMINATION) {\n\t\t\t\t\t\ts++;\n\t\t\t\t\t\twhile (!(*s == '~' || *s == JAP_TERMINATION)) s++;\n\t\t\t\t\t\ts++;\n\t\t\t\t\t}\n\t\t\t\t\t++s;\n\t\t\t\t} while (*s == '~' || *s == JAP_TERMINATION);\n\t\t\t}\n\t\t} while (IsAnsiCharacter(s));\n\t} else\n#endif\n\t{\n\t\tfor(; *s != ' ' && *s != '\\0'; s++)\n\t\t\tif(*s == '~'){\n\t\t\t\ts++;\n\t\t\t\twhile(*s != '~') s++;\n\t\t\t}\n\t}\n\treturn s;\n}\n\nwchar*\nCFont::ParseToken(wchar* str, CRGBA &color, bool &flash, bool &bold)\n{\n\tDetails.anonymous_23 = false;\n\twchar *s = str + 1;\n\tif (Details.color.r || Details.color.g || Details.color.b)\n\t{\n\t\tswitch (*s)\n\t\t{\n\t\tcase 'B':\n\t\t\tbold = !bold;\n\t\t\tbreak;\n\t\tcase 'b':\n\t\t\tcolor.r = 27;\n\t\t\tcolor.g = 89;\n\t\t\tcolor.b = 130;\n\t\t\tbreak;\n\t\tcase 'f':\n\t\t\tflash = !flash;\n\t\t\tbreak;\n\t\tcase 'g':\n\t\t\tcolor.r = 255;\n\t\t\tcolor.g = 150;\n\t\t\tcolor.b = 225;\n\t\t\tbreak;\n\t\tcase 'h':\n\t\t\tcolor.r = 225;\n\t\t\tcolor.g = 225;\n\t\t\tcolor.b = 225;\n\t\t\tbreak;\n\t\tcase 'l':\n\t\t\tcolor.r = 0;\n\t\t\tcolor.g = 0;\n\t\t\tcolor.b = 0;\n\t\t\tbreak;\n\t\tcase 'o':\n\t\t\tcolor.r = 229;\n\t\t\tcolor.g = 125;\n\t\t\tcolor.b = 126;\n\t\t\tbreak;\n\t\tcase 'p':\n\t\t\tcolor.r = 168;\n\t\t\tcolor.g = 110;\n\t\t\tcolor.b = 252;\n\t\t\tbreak;\n\t\tcase 'q':\n\t\t\tcolor.r = 199;\n\t\t\tcolor.g = 144;\n\t\t\tcolor.b = 203;\n\t\t\tbreak;\n\t\tcase 'r':\n\t\t\tcolor.r = 255;\n\t\t\tcolor.g = 150;\n\t\t\tcolor.b = 225;\n\t\t\tbreak;\n\t\tcase 't':\n\t\t\tcolor.r = 86;\n\t\t\tcolor.g = 212;\n\t\t\tcolor.b = 146;\n\t\t\tbreak;\n\t\tcase 'w':\n\t\t\tcolor.r = 175;\n\t\t\tcolor.g = 175;\n\t\t\tcolor.b = 175;\n\t\t\tbreak;\n#ifdef FIX_BUGS\n\t\tcase 'x':\n\t\t\tcolor.r = 0;\n\t\t\tcolor.g = 255;\n\t\t\tcolor.b = 255;\n\t\t\tbreak;\n#else\n\t\tcase 'x':\n\t\t\tcolor.r = 132;\n\t\t\tcolor.g = 146;\n\t\t\tcolor.b = 197;\n\t\t\tbreak;\n#endif\n\t\tcase 'y':\n\t\t\tcolor.r = 255;\n\t\t\tcolor.g = 227;\n\t\t\tcolor.b = 79;\n\t\t\tbreak;\n#ifdef BUTTON_ICONS\n\t\tcase 'U': PS2Symbol = BUTTON_UP; break;\n\t\tcase 'D': PS2Symbol = BUTTON_DOWN; break;\n\t\tcase '<': PS2Symbol = BUTTON_LEFT; break;\n\t\tcase '>': PS2Symbol = BUTTON_RIGHT; break;\n\t\tcase 'X': PS2Symbol = BUTTON_CROSS; break;\n\t\tcase 'O': PS2Symbol = BUTTON_CIRCLE; break;\n\t\tcase 'Q': PS2Symbol = BUTTON_SQUARE; break;\n\t\tcase 'T': PS2Symbol = BUTTON_TRIANGLE; break;\n\t\tcase 'K': PS2Symbol = BUTTON_L1; break;\n\t\tcase 'M': PS2Symbol = BUTTON_L2; break;\n\t\tcase 'A': PS2Symbol = BUTTON_L3; break;\n\t\tcase 'J': PS2Symbol = BUTTON_R1; break;\n\t\tcase 'V': PS2Symbol = BUTTON_R2; break;\n\t\tcase 'C': PS2Symbol = BUTTON_R3; break;\n\t\tcase 'H': PS2Symbol = BUTTON_RSTICK_UP; break;\n\t\tcase 'L': PS2Symbol = BUTTON_RSTICK_DOWN; break;\n\t\tcase '(': PS2Symbol = BUTTON_RSTICK_LEFT; break;\n\t\tcase ')': PS2Symbol = BUTTON_RSTICK_RIGHT; break;\n#endif\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\t}\n\twhile (*s != '~')\n\t\t++s;\n\tif (*(++s) == '~')\n\t\ts = ParseToken(s, color, flash, bold);\n\treturn s;\n}\n\n#if 0//def MORE_LANGUAGES\nwchar*\nCFont::ParseToken(wchar *s, bool japShit)\n{\n\ts++;\n\tif ((Details.color.r || Details.color.g || Details.color.b) && !japShit) {\n\t\twchar c = *s;\n\t\tif (IsJapanese())\n\t\t\tc &= 0x7FFF;\n\t\tswitch (c) {\n\t\tcase 'N':\n\t\tcase 'n':\n\t\t\tNewLine = true;\n\t\t\tbreak;\n\t\tcase 'b': SetColor(CRGBA(128, 167, 243, 255)); break;\n\t\tcase 'g': SetColor(CRGBA(95, 160, 106, 255)); break;\n\t\tcase 'h': SetColor(CRGBA(225, 225, 225, 255)); break;\n\t\tcase 'l': SetColor(CRGBA(0, 0, 0, 255)); break;\n\t\tcase 'p': SetColor(CRGBA(168, 110, 252, 255)); break;\n\t\tcase 'r': SetColor(CRGBA(113, 43, 73, 255)); break;\n\t\tcase 'w': SetColor(CRGBA(175, 175, 175, 255)); break;\n\t\tcase 'y': SetColor(CRGBA(210, 196, 106, 255)); break;\n#ifdef BUTTON_ICONS\n\t\tcase 'U': PS2Symbol = BUTTON_UP; break;\n\t\tcase 'D': PS2Symbol = BUTTON_DOWN; break;\n\t\tcase '<': PS2Symbol = BUTTON_LEFT; break;\n\t\tcase '>': PS2Symbol = BUTTON_RIGHT; break;\n\t\tcase 'X': PS2Symbol = BUTTON_CROSS; break;\n\t\tcase 'O': PS2Symbol = BUTTON_CIRCLE; break;\n\t\tcase 'Q': PS2Symbol = BUTTON_SQUARE; break;\n\t\tcase 'T': PS2Symbol = BUTTON_TRIANGLE; break;\n\t\tcase 'K': PS2Symbol = BUTTON_L1; break;\n\t\tcase 'M': PS2Symbol = BUTTON_L2; break;\n\t\tcase 'A': PS2Symbol = BUTTON_L3; break;\n\t\tcase 'J': PS2Symbol = BUTTON_R1; break;\n\t\tcase 'V': PS2Symbol = BUTTON_R2; break;\n\t\tcase 'C': PS2Symbol = BUTTON_R3; break;\n\t\tcase 'H': PS2Symbol = BUTTON_RSTICK_UP; break;\n\t\tcase 'L': PS2Symbol = BUTTON_RSTICK_DOWN; break;\n\t\tcase '(': PS2Symbol = BUTTON_RSTICK_LEFT; break;\n\t\tcase ')': PS2Symbol = BUTTON_RSTICK_RIGHT; break;\n#endif\n\t\t}\n\t} else if (IsJapanese()) {\n\t\tif ((*s & 0x7FFF) == 'N' || (*s & 0x7FFF) == 'n')\n\t\t\tNewLine = true;\n\t}\n\twhile ((!IsJapanese() || (*s != JAP_TERMINATION)) && *s != '~') s++;\n\treturn s + 1;\n}\n#else\nwchar*\nCFont::ParseToken(wchar *s)\n{\n\tDetails.anonymous_23 = false;\n\ts++;\n\tif(Details.color.r || Details.color.g || Details.color.b)\n\t\tswitch(*s){\n\t\tcase 'B':\n\t\t\tDetails.bBold = !Details.bBold;\n\t\t\tbreak;\n\t\tcase 'N':\n\t\tcase 'n':\n\t\t\tNewLine = true;\n\t\t\tbreak;\n\t\tcase 'b':\n\t\t\tDetails.color.r = 27;\n\t\t\tDetails.color.g = 89;\n\t\t\tDetails.color.b = 130;\n\t\t\tDetails.anonymous_23 = true;\n\t\t\tbreak;\n\t\tcase 'f':\n\t\t\tDetails.bFlash = !Details.bFlash;\n\t\t\tif (!Details.bFlash)\n\t\t\t\tDetails.color.a = 255;\n\t\t\tbreak;\n\t\tcase 'g':\n\t\t\tDetails.color.r = 255;\n\t\t\tDetails.color.g = 150;\n\t\t\tDetails.color.b = 225;\n\t\t\tDetails.anonymous_23 = true;\n\t\t\tbreak;\n\t\tcase 'h':\n\t\t\tDetails.color.r = 225;\n\t\t\tDetails.color.g = 225;\n\t\t\tDetails.color.b = 225;\n\t\t\tDetails.anonymous_23 = true;\n\t\t\tbreak;\n\t\tcase 'l':\n\t\t\tDetails.color.r = 0;\n\t\t\tDetails.color.g = 0;\n\t\t\tDetails.color.b = 0;\n\t\t\tDetails.anonymous_23 = true;\n\t\t\tbreak;\n\t\tcase 'o':\n\t\t\tDetails.color.r = 229;\n\t\t\tDetails.color.g = 125;\n\t\t\tDetails.color.b = 126;\n\t\t\tDetails.anonymous_23 = true;\n\t\t\tbreak;\n\t\tcase 'p':\n\t\t\tDetails.color.r = 168;\n\t\t\tDetails.color.g = 110;\n\t\t\tDetails.color.b = 252;\n\t\t\tDetails.anonymous_23 = true;\n\t\t\tbreak;\n\t\tcase 'q':\n\t\t\tDetails.color.r = 199;\n\t\t\tDetails.color.g = 144;\n\t\t\tDetails.color.b = 203;\n\t\t\tDetails.anonymous_23 = true;\n\t\t\tbreak;\n\t\tcase 'r':\n\t\t\tDetails.color.r = 255;\n\t\t\tDetails.color.g = 150;\n\t\t\tDetails.color.b = 225;\n\t\t\tDetails.anonymous_23 = true;\n\t\t\tbreak;\n\t\tcase 't':\n\t\t\tDetails.color.r = 86;\n\t\t\tDetails.color.g = 212;\n\t\t\tDetails.color.b = 146;\n\t\t\tDetails.anonymous_23 = true;\n\t\t\tbreak;\n\t\tcase 'w':\n\t\t\tDetails.color.r = 175;\n\t\t\tDetails.color.g = 175;\n\t\t\tDetails.color.b = 175;\n\t\t\tDetails.anonymous_23 = true;\n\t\t\tbreak;\n\t\tcase 'x':\n#ifdef FIX_BUGS\n\t\t\tDetails.color.r = 0;\n\t\t\tDetails.color.g = 255;\n\t\t\tDetails.color.b = 255;\n#else\n\t\t\tDetails.color.r = 132;\n\t\t\tDetails.color.g = 146;\n\t\t\tDetails.color.b = 197;\n#endif\n\t\t\tDetails.anonymous_23 = true;\n\t\t\tbreak;\n\t\tcase 'y':\n\t\t\tDetails.color.r = 255;\n\t\t\tDetails.color.g = 227;\n\t\t\tDetails.color.b = 79;\n\t\t\tDetails.anonymous_23 = true;\n\t\t\tbreak;\n#ifdef BUTTON_ICONS\n\t\tcase 'U': PS2Symbol = BUTTON_UP; break;\n\t\tcase 'D': PS2Symbol = BUTTON_DOWN; break;\n\t\tcase '<': PS2Symbol = BUTTON_LEFT; break;\n\t\tcase '>': PS2Symbol = BUTTON_RIGHT; break;\n\t\tcase 'X': PS2Symbol = BUTTON_CROSS; break;\n\t\tcase 'O': PS2Symbol = BUTTON_CIRCLE; break;\n\t\tcase 'Q': PS2Symbol = BUTTON_SQUARE; break;\n\t\tcase 'T': PS2Symbol = BUTTON_TRIANGLE; break;\n\t\tcase 'K': PS2Symbol = BUTTON_L1; break;\n\t\tcase 'M': PS2Symbol = BUTTON_L2; break;\n\t\tcase 'A': PS2Symbol = BUTTON_L3; break;\n\t\tcase 'J': PS2Symbol = BUTTON_R1; break;\n\t\tcase 'V': PS2Symbol = BUTTON_R2; break;\n\t\tcase 'C': PS2Symbol = BUTTON_R3; break;\n\t\tcase 'H': PS2Symbol = BUTTON_RSTICK_UP; break;\n\t\tcase 'L': PS2Symbol = BUTTON_RSTICK_DOWN; break;\n\t\tcase '(': PS2Symbol = BUTTON_RSTICK_LEFT; break;\n\t\tcase ')': PS2Symbol = BUTTON_RSTICK_RIGHT; break;\n#endif\n\t\t}\n\twhile(*s != '~') s++;\n\tif (*(++s) == '~')\n\t\ts = ParseToken(s);\n\treturn s;\n}\n#endif\n\nvoid\nCFont::FilterOutTokensFromString(wchar *str)\n{\n\tint newIdx = 0;\n\twchar copy[256], *c;\n\tUnicodeStrcpy(copy, str);\n\n\tfor (c = copy; *c != '\\0'; c++) {\n\t\tif (*c == '~') {\n\t\t\tc++;\n\t\t\twhile (*c != '~') c++;\n\t\t} else {\n\t\t\tstr[newIdx++] = *c;\n\t\t}\n\t}\n\tstr[newIdx] = '\\0';\n}\n\nvoid\nCFont::DrawFonts(void)\n{\n\tRenderFontBuffer();\n}\n\nvoid\nCFont::SetScale(float x, float y)\n{\n#ifdef MORE_LANGUAGES\n\t/*if (IsJapanese()) {\n\t\tx *= 1.35f;\n\t\ty *= 1.25f;\n\t}*/\n#endif\n\tDetails.scaleX = x;\n\tDetails.scaleY = y;\n}\n\nvoid\nCFont::SetSlantRefPoint(float x, float y)\n{\n\tDetails.slantRefX = x;\n\tDetails.slantRefY = y;\n}\n\nvoid\nCFont::SetSlant(float s)\n{\n\tDetails.slant = s;\n}\n\nvoid\nCFont::SetColor(CRGBA col)\n{\n\tDetails.color = col;\n\tif (Details.alphaFade < 255.0f)\n\t\tDetails.color.a *= Details.alphaFade / 255.0f;\n}\n\nvoid\nCFont::SetJustifyOn(void)\n{\n\tDetails.justify = true;\n\tDetails.centre = false;\n\tDetails.rightJustify = false;\n}\n\nvoid\nCFont::SetJustifyOff(void)\n{\n\tDetails.justify = false;\n\tDetails.rightJustify = false;\n}\n\nvoid\nCFont::SetCentreOn(void)\n{\n\tDetails.centre = true;\n\tDetails.justify = false;\n\tDetails.rightJustify = false;\n}\n\nvoid\nCFont::SetCentreOff(void)\n{\n\tDetails.centre = false;\n}\n\nvoid\nCFont::SetWrapx(float x)\n{\n\tDetails.wrapX = x;\n}\n\nvoid\nCFont::SetCentreSize(float s)\n{\n\tDetails.centreSize = s;\n}\n\nvoid\nCFont::SetBackgroundOn(void)\n{\n\tDetails.background = true;\n}\n\nvoid\nCFont::SetBackgroundOff(void)\n{\n\tDetails.background = false;\n}\n\nvoid\nCFont::SetBackgroundColor(CRGBA col)\n{\n\tDetails.backgroundColor = col;\n}\n\nvoid\nCFont::SetBackGroundOnlyTextOn(void)\n{\n\tDetails.backgroundOnlyText = true;\n}\n\nvoid\nCFont::SetBackGroundOnlyTextOff(void)\n{\n\tDetails.backgroundOnlyText = false;\n}\n\nvoid\nCFont::SetRightJustifyOn(void)\n{\n\tDetails.rightJustify = true;\n\tDetails.justify = false;\n\tDetails.centre = false;\n}\n\nvoid\nCFont::SetRightJustifyOff(void)\n{\n\tDetails.rightJustify = false;\n\tDetails.justify = false;\n\tDetails.centre = false;\n}\n\nvoid\nCFont::SetPropOff(void)\n{\n\tDetails.proportional = false;\n}\n\nvoid\nCFont::SetPropOn(void)\n{\n\tDetails.proportional = true;\n}\n\nvoid\nCFont::SetFontStyle(int16 style)\n{\n\tif (style == FONT_HEADING) {\n\t\tDetails.style = FONT_STANDARD;\n\t\tDetails.bFontHalfTexture = true;\n\t} else {\n\t\tDetails.style = style;\n\t\tDetails.bFontHalfTexture = false;\n\t}\n}\n\nvoid\nCFont::SetRightJustifyWrap(float wrap)\n{\n\tDetails.rightJustifyWrap = wrap;\n}\n\nvoid\nCFont::SetAlphaFade(float fade)\n{\n\tDetails.alphaFade = fade;\n}\n\nvoid\nCFont::SetDropColor(CRGBA col)\n{\n\tDetails.dropColor = col;\n\tif (Details.alphaFade < 255.0f)\n\t\tDetails.dropColor.a *= Details.alphaFade / 255.0f;\n}\n\nvoid\nCFont::SetDropShadowPosition(int16 pos)\n{\n\tDetails.dropShadowPosition = pos;\n}\n\nwchar CFont::FindNewCharacter(wchar c)\n{\n\tif (c >= 16 && c <= 26) return c + 128;\n\tif (c >= 8 && c <= 9) return c + 86;\n\tif (c == 4) return c + 89;\n\tif (c == 7) return 206;\n\tif (c == 14) return 207;\n\tif (c >= 33 && c <= 58) return c + 122;\n\tif (c >= 65 && c <= 90) return c + 90;\n\tif (c >= 96 && c <= 118) return c + 85;\n\tif (c >= 119 && c <= 140) return c + 62;\n\tif (c >= 141 && c <= 142) return 204;\n\tif (c == 143) return 205;\n\tif (c == 1) return 208;\n\treturn c;\n}\n\nwchar\nCFont::character_code(uint8 c)\n{\n\tif(c < 128)\n\t\treturn c;\n\treturn foreign_table[c-128];\n}"
  },
  {
    "path": "src/render/Font.h",
    "content": "#pragma once\n\n#include \"Sprite2d.h\"\n\nvoid AsciiToUnicode(const char *src, wchar *dst);\nvoid UnicodeStrcpy(wchar *dst, const wchar *src);\nvoid UnicodeStrcat(wchar *dst, wchar *append);\nint UnicodeStrlen(const wchar *str);\nvoid UnicodeMakeUpperCase(wchar *dst, const wchar *src);\n\nstruct CFontDetails\n{\n\tCRGBA color;\n\tfloat scaleX;\n\tfloat scaleY;\n\tfloat slant;\n\tfloat slantRefX;\n\tfloat slantRefY;\n\tbool8 justify;\n\tbool8 centre;\n\tbool8 rightJustify;\n\tbool8 background;\n\tbool8 backgroundOnlyText;\n\tbool8 proportional;\n\tbool8 bIsShadow;\n\tbool8 bFlash;\n\tbool8 bBold;\n\tfloat alphaFade;\n\tCRGBA backgroundColor;\n\tfloat wrapX;\n\tfloat centreSize;\n\tfloat rightJustifyWrap;\n\tint16 style;\n\tbool8 bFontHalfTexture;\n\tuint32 bank;\n\tint16 dropShadowPosition;\n\tCRGBA dropColor;\n\tbool8 bFlashState;\n\tint nFlashTimer;\n\tbool8 anonymous_23;\n\tuint32 anonymous_25;\n};\n\nstruct CFontRenderState\n{\n\tuint32 anonymous_0;\n\tfloat fTextPosX;\n\tfloat fTextPosY;\n\tfloat scaleX;\n\tfloat scaleY;\n\tCRGBA color;\n\tfloat fExtraSpace;\n\tfloat slant;\n\tfloat slantRefX;\n\tfloat slantRefY;\n\tbool8 bIsShadow;\n\tbool8 bFontHalfTexture;\n\tbool8 proportional;\n\tbool8 anonymous_14;\n\tint16 style;\n};\n\nclass CSprite2d;\n\nenum {\n\tFONT_BANK,\n\tFONT_STANDARD,\n\tFONT_HEADING,\n#ifdef MORE_LANGUAGES\n\tFONT_JAPANESE,\n#endif\n\tMAX_FONTS = FONT_HEADING\n};\n\nenum {\n\tALIGN_LEFT,\n\tALIGN_CENTER,\n\tALIGN_RIGHT,\n};\n\n#ifdef MORE_LANGUAGES\nenum\n{\n\tFONT_LANGSET_EFIGS,\n\tFONT_LANGSET_RUSSIAN,\n\tFONT_LANGSET_POLISH,\n\tFONT_LANGSET_JAPANESE,\n\tLANGSET_MAX\n};\n\n#define FONT_LOCALE(style) (CFont::IsJapanese() ? FONT_JAPANESE : style)\n#else\n#define FONT_LOCALE(style) (style)\n#endif\n\n#ifdef BUTTON_ICONS\nenum\n{\n\tBUTTON_NONE = -1,\n\tBUTTON_UP,\n\tBUTTON_DOWN,\n\tBUTTON_LEFT,\n\tBUTTON_RIGHT,\n\tBUTTON_CROSS,\n\tBUTTON_CIRCLE,\n\tBUTTON_SQUARE,\n\tBUTTON_TRIANGLE,\n\tBUTTON_L1,\n\tBUTTON_L2,\n\tBUTTON_L3,\n\tBUTTON_R1,\n\tBUTTON_R2,\n\tBUTTON_R3,\n\tBUTTON_RSTICK_UP,\n\tBUTTON_RSTICK_DOWN,\n\tBUTTON_RSTICK_LEFT,\n\tBUTTON_RSTICK_RIGHT,\n\tMAX_BUTTON_ICONS\n};\n#endif // BUTTON_ICONS\n\n\nclass CFont\n{\n#ifdef MORE_LANGUAGES\n\tstatic int16 Size[LANGSET_MAX][MAX_FONTS][210];\n\tstatic uint8 LanguageSet;\n\tstatic int32 Slot;\n#else\n\tstatic int16 Size[MAX_FONTS][210];\n#endif\n\tstatic int16 NewLine;\npublic:\n\tstatic CSprite2d Sprite[MAX_FONTS];\n\tstatic CFontDetails Details;\n\tstatic CFontRenderState RenderState;\n\n#ifdef BUTTON_ICONS\n\tstatic int32 ButtonsSlot;\n\tstatic CSprite2d ButtonSprite[MAX_BUTTON_ICONS];\n\tstatic int PS2Symbol;\n\t\n\tstatic void LoadButtons(const char *txdPath);\n\tstatic void DrawButton(float x, float y);\n#endif // BUTTON_ICONS\n\n\n\tstatic void Initialise(void);\n\tstatic void Shutdown(void);\n\tstatic void InitPerFrame(void);\n\tstatic void PrintChar(float x, float y, wchar c);\n\tstatic void PrintString(float x, float y, wchar *s);\n#ifdef XBOX_SUBTITLES\n\tstatic void PrintStringFromBottom(float x, float y, wchar *str);\n\tstatic void PrintOutlinedString(float x, float y, wchar *str, float outlineStrength, bool fromBottom, CRGBA outlineColor);\n#endif\n\tstatic int GetNumberLines(float xstart, float ystart, wchar *s);\n\tstatic void GetTextRect(CRect *rect, float xstart, float ystart, wchar *s);\n//#ifdef MORE_LANGUAGES\n//\tstatic bool PrintString(float x, float y, wchar *start, wchar* &end, float spwidth, float japX);\n//#else\n\tstatic void PrintString(float x, float y, uint32, wchar *start, wchar *end, float spwidth);\n//#endif\n\tstatic void PrintStringFromBottom(float x, float y, wchar *str);\n\tstatic float GetCharacterWidth(wchar c);\n\tstatic float GetCharacterSize(wchar c);\n\tstatic float GetStringWidth(wchar *s, bool spaces = false);\n#ifdef MORE_LANGUAGES\n\tstatic float GetStringWidth_Jap(wchar* s);\n#endif\n\tstatic uint16 *GetNextSpace(wchar *s);\n//#ifdef MORE_LANGUAGES\n//\tstatic uint16 *ParseToken(wchar *s, bool japShit = false);\n//#else\n\tstatic uint16 *ParseToken(wchar *s);\n\tstatic uint16 *ParseToken(wchar *s, CRGBA &color, bool &flash, bool &bold);\n//#endif\n\tstatic void DrawFonts(void);\n\tstatic void RenderFontBuffer(void);\n\tstatic uint16 character_code(uint8 c);\n\n\tstatic void SetScale(float x, float y);\n\tstatic void SetSlantRefPoint(float x, float y);\n\tstatic void SetSlant(float s);\n\tstatic void SetJustifyOn(void);\n\tstatic void SetJustifyOff(void);\n\tstatic void SetRightJustifyOn(void);\n\tstatic void SetRightJustifyOff(void);\n\tstatic void SetCentreOn(void);\n\tstatic void SetCentreOff(void);\n\tstatic void SetWrapx(float x);\n\tstatic void SetCentreSize(float s);\n\tstatic void SetBackgroundOn(void);\n\tstatic void SetBackgroundOff(void);\n\tstatic void SetBackGroundOnlyTextOn(void);\n\tstatic void SetBackGroundOnlyTextOff(void);\n\tstatic void SetPropOn(void);\n\tstatic void SetPropOff(void);\n\tstatic void SetFontStyle(int16 style);\n\tstatic void SetRightJustifyWrap(float wrap);\n\tstatic void SetAlphaFade(float fade);\n\tstatic void SetDropShadowPosition(int16 pos);\n\tstatic void SetBackgroundColor(CRGBA col);\n\tstatic void SetColor(CRGBA col);\n\tstatic void SetDropColor(CRGBA col);\n\tstatic wchar FindNewCharacter(wchar c);\n\tstatic void FilterOutTokensFromString(wchar*);\n#ifdef MORE_LANGUAGES\n\tstatic void ReloadFonts(uint8 set);\n\n\t// japanese stuff\n\tstatic bool IsAnsiCharacter(wchar* s);\n\tstatic bool IsJapanesePunctuation(wchar* str);\n\tstatic bool IsJapanese() { return LanguageSet == FONT_LANGSET_JAPANESE; }\n\tstatic bool IsJapaneseFont() { return IsJapanese() && (Details.style == FONT_JAPANESE);  }\n#endif\n};\n"
  },
  {
    "path": "src/render/Glass.cpp",
    "content": "#include \"common.h\"\n\n#include \"Glass.h\"\n#include \"Timer.h\"\n#include \"Object.h\"\n#include \"Vehicle.h\"\n#include \"Pools.h\"\n#include \"General.h\"\n#include \"AudioScriptObject.h\"\n#include \"World.h\"\n#include \"Timecycle.h\"\n#include \"Particle.h\"\n#include \"Camera.h\"\n#include \"RenderBuffer.h\"\n#include \"Shadows.h\"\n#include \"ModelIndices.h\"\n#include \"main.h\"\n#include \"soundlist.h\"\n#include \"SurfaceTable.h\"\n\n\nuint32 CGlass::NumGlassEntities;\nCEntity *CGlass::apEntitiesToBeRendered[NUM_GLASSENTITIES];\nCFallingGlassPane CGlass::aGlassPanes[NUM_GLASSPANES];\n\n\nCVector2D CentersWithTriangle[NUM_GLASSTRIANGLES];\nconst CVector2D CoorsWithTriangle[NUM_GLASSTRIANGLES][3] =\n{\n\t{\n\t\tCVector2D(0.0f, 0.0f),\n\t\tCVector2D(0.0f, 1.0f),\n\t\tCVector2D(0.4f, 0.5f)\n\t},\n\n\t{\n\t\tCVector2D(0.0f, 1.0f),\n\t\tCVector2D(1.0f, 1.0f),\n\t\tCVector2D(0.4f, 0.5f)\n\t},\n\n\t{\n\t\tCVector2D(0.0f, 0.0f),\n\t\tCVector2D(0.4f, 0.5f),\n\t\tCVector2D(0.7f, 0.0f)\n\t},\n\n\t{\n\t\tCVector2D(0.7f, 0.0f),\n\t\tCVector2D(0.4f, 0.5f),\n\t\tCVector2D(1.0f, 1.0f)\n\t},\n\n\t{\n\t\tCVector2D(0.7f, 0.0f),\n\t\tCVector2D(1.0f, 1.0f),\n\t\tCVector2D(1.0f, 0.0f)\n\t}\n};\n\n#define TEMPBUFFERVERTHILIGHTOFFSET     0\n#define TEMPBUFFERINDEXHILIGHTOFFSET    0\n#define TEMPBUFFERVERTHILIGHTSIZE       256\n#define TEMPBUFFERINDEXHILIGHTSIZE      512\n\n#define TEMPBUFFERVERTSHATTEREDOFFSET   TEMPBUFFERVERTHILIGHTSIZE\n#define TEMPBUFFERINDEXSHATTEREDOFFSET  TEMPBUFFERINDEXHILIGHTSIZE\n#define TEMPBUFFERVERTSHATTEREDSIZE     384\n#define TEMPBUFFERINDEXSHATTEREDSIZE    768\n\n#define TEMPBUFFERVERTREFLECTIONOFFSET  TEMPBUFFERVERTSHATTEREDSIZE\n#define TEMPBUFFERINDEXREFLECTIONOFFSET TEMPBUFFERINDEXSHATTEREDSIZE\n#define TEMPBUFFERVERTREFLECTIONSIZE    512\n#define TEMPBUFFERINDEXREFLECTIONSIZE   1024\n\nint32 TempBufferIndicesStoredHiLight     = 0;\nint32 TempBufferVerticesStoredHiLight    = 0;\nint32 TempBufferIndicesStoredShattered   = 0;\nint32 TempBufferVerticesStoredShattered  = 0;\nint32 TempBufferIndicesStoredReflection  = 0;\nint32 TempBufferVerticesStoredReflection = 0;\n\nvoid\nCFallingGlassPane::Update(void)\n{\n\tif ( CTimer::GetTimeInMilliseconds() >= m_nTimer )\n\t{\n\t\t// Apply MoveSpeed\n\t\tif ( m_bCarGlass )\n\t\t\tGetPosition()    += m_vecMoveSpeed * CTimer::GetTimeStep() * 0.35f;\n\t\telse\n\t\t\tGetPosition()    += m_vecMoveSpeed * CTimer::GetTimeStep();\n\n\t\t// Apply Gravity\n\t\tif ( m_bCarGlass )\n\t\t\tm_vecMoveSpeed.z -= 0.01f          *  CTimer::GetTimeStep();\n\t\telse\n\t\t\tm_vecMoveSpeed.z -= 0.02f          *  CTimer::GetTimeStep();\n\n\t\t// Apply TurnSpeed\n\t\tGetRight()   += CrossProduct(m_vecTurn, GetRight());\n\t\tGetForward() += CrossProduct(m_vecTurn, GetForward());\n\t\tGetUp()      += CrossProduct(m_vecTurn, GetUp());\n\n\t\tif ( GetPosition().z < m_fGroundZ )\n\t\t{\n\t\t\tCVector pos;\n\t\t\tCVector dir;\n\n\t\t\tm_bActive = false;\n\n\t\t\tpos = CVector(GetPosition().x, GetPosition().y, m_fGroundZ);\n\n\t\t\tPlayOneShotScriptObject(SCRIPT_SOUND_GLASS_LIGHT_BREAK, pos);\n\n\t\t\tRwRGBA color = { 255, 255, 255, 255 };\n\n\t\t\tif ( !m_bCarGlass )\n\t\t\t{\n\t\t\t\tstatic int32 nFrameGen = 0;\n\t\n\t\t\t\tfor ( int32 i = 0; i < 4; i++ )\n\t\t\t\t{\n\t\t\t\t\tdir.x = CGeneral::GetRandomNumberInRange(-0.35f, 0.35f);\n\t\t\t\t\tdir.y = CGeneral::GetRandomNumberInRange(-0.35f, 0.35f);\n\t\t\t\t\tdir.z = CGeneral::GetRandomNumberInRange(0.05f, 0.20f);\n\t\n\t\t\t\t\tCParticle::AddParticle(PARTICLE_CAR_DEBRIS,\n\t\t\t\t\t\tpos,\n\t\t\t\t\t\tdir,\n\t\t\t\t\t\tnil,\n\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(0.02f, 0.2f),\n\t\t\t\t\t\tcolor,\n\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(-40, 40),\n\t\t\t\t\t\t0,\n\t\t\t\t\t\t++nFrameGen & 3,\n\t\t\t\t\t\t500);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nCFallingGlassPane::Render(void)\n{\n\tfloat distToCamera = (TheCamera.GetPosition() - GetPosition()).Magnitude();\n\n\tCVector fwdNorm = GetForward();\n\tfwdNorm.Normalise();\n\tuint8 alpha = CGlass::CalcAlphaWithNormal(&fwdNorm);\n\n#ifdef FIX_BUGS\n\tuint16 time = clamp(CTimer::GetTimeInMilliseconds() > m_nTimer ? CTimer::GetTimeInMilliseconds() - m_nTimer : 0u, 0u, 500u);\n#else\n\tuint16 time = clamp(CTimer::GetTimeInMilliseconds() - m_nTimer, 0, 500);\n#endif\n\n\tuint8 color = int32( float(alpha) * (float(time) / 500) );\n\n\tif ( TempBufferIndicesStoredHiLight >= TEMPBUFFERINDEXHILIGHTSIZE-7 || TempBufferVerticesStoredHiLight >= TEMPBUFFERVERTHILIGHTSIZE-4 )\n\t\tCGlass::RenderHiLightPolys();\n\n\t// HiLight Polys\n\t\n\tif ( m_bCarGlass && color < 64 )\n\t\tcolor = 64;\n\t\t\n\tRwIm3DVertexSetRGBA (&TempBufferRenderVertices[TempBufferVerticesStoredHiLight + 0], color, color, color, color);\n\tRwIm3DVertexSetRGBA (&TempBufferRenderVertices[TempBufferVerticesStoredHiLight + 1], color, color, color, color);\n\tRwIm3DVertexSetRGBA (&TempBufferRenderVertices[TempBufferVerticesStoredHiLight + 2], color, color, color, color);\n\n\tRwIm3DVertexSetU    (&TempBufferRenderVertices[TempBufferVerticesStoredHiLight + 0], 0.5f);\n\tRwIm3DVertexSetV    (&TempBufferRenderVertices[TempBufferVerticesStoredHiLight + 0], 0.5f);\n\tRwIm3DVertexSetU    (&TempBufferRenderVertices[TempBufferVerticesStoredHiLight + 1], 0.5f);\n\tRwIm3DVertexSetV    (&TempBufferRenderVertices[TempBufferVerticesStoredHiLight + 1], 0.6f);\n\tRwIm3DVertexSetU    (&TempBufferRenderVertices[TempBufferVerticesStoredHiLight + 2], 0.6f);\n\tRwIm3DVertexSetV    (&TempBufferRenderVertices[TempBufferVerticesStoredHiLight + 2], 0.6f);\n\n\tASSERT(m_nTriIndex < NUM_GLASSTRIANGLES);\n\n\tCVector2D p0 = CoorsWithTriangle[m_nTriIndex][0] - CentersWithTriangle[m_nTriIndex];\n\tCVector2D p1 = CoorsWithTriangle[m_nTriIndex][1] - CentersWithTriangle[m_nTriIndex];\n\tCVector2D p2 = CoorsWithTriangle[m_nTriIndex][2] - CentersWithTriangle[m_nTriIndex];\n\tCVector v0 = *this * CVector(p0.x, 0.0f, p0.y);\n\tCVector v1 = *this * CVector(p1.x, 0.0f, p1.y);\n\tCVector v2 = *this * CVector(p2.x, 0.0f, p2.y);\n\n\tRwIm3DVertexSetPos  (&TempBufferRenderVertices[TempBufferVerticesStoredHiLight + 0], v0.x, v0.y, v0.z);\n\tRwIm3DVertexSetPos  (&TempBufferRenderVertices[TempBufferVerticesStoredHiLight + 1], v1.x, v1.y, v1.z);\n\tRwIm3DVertexSetPos  (&TempBufferRenderVertices[TempBufferVerticesStoredHiLight + 2], v2.x, v2.y, v2.z);\n\n\tTempBufferRenderIndexList[TempBufferIndicesStoredHiLight + 0] = TempBufferVerticesStoredHiLight + 0;\n\tTempBufferRenderIndexList[TempBufferIndicesStoredHiLight + 1] = TempBufferVerticesStoredHiLight + 1;\n\tTempBufferRenderIndexList[TempBufferIndicesStoredHiLight + 2] = TempBufferVerticesStoredHiLight + 2;\n\tTempBufferRenderIndexList[TempBufferIndicesStoredHiLight + 3] = TempBufferVerticesStoredHiLight + 0;\n\tTempBufferRenderIndexList[TempBufferIndicesStoredHiLight + 4] = TempBufferVerticesStoredHiLight + 2;\n\tTempBufferRenderIndexList[TempBufferIndicesStoredHiLight + 5] = TempBufferVerticesStoredHiLight + 1;\n\n\tTempBufferVerticesStoredHiLight += 3;\n\tTempBufferIndicesStoredHiLight  += 6;\n\n\tif ( m_bShattered )\n\t{\n\t\tif ( TempBufferIndicesStoredShattered >= TEMPBUFFERINDEXSHATTEREDSIZE-7 || TempBufferVerticesStoredShattered >= TEMPBUFFERVERTSHATTEREDSIZE-4 )\n\t\t\tCGlass::RenderShatteredPolys();\n\n\t\tuint8 shatteredColor = 140;\n\t\tif ( distToCamera > 30.0f )\n\t\t\tshatteredColor = int32((1.0f - (distToCamera - 30.0f) * 4.0f / 40.0f) * 140);\n\n\t\tRwIm3DVertexSetRGBA (&TempBufferRenderVertices[TempBufferVerticesStoredShattered + 0], shatteredColor, shatteredColor, shatteredColor, shatteredColor);\n\t\tRwIm3DVertexSetRGBA (&TempBufferRenderVertices[TempBufferVerticesStoredShattered + 1], shatteredColor, shatteredColor, shatteredColor, shatteredColor);\n\t\tRwIm3DVertexSetRGBA (&TempBufferRenderVertices[TempBufferVerticesStoredShattered + 2], shatteredColor, shatteredColor, shatteredColor, shatteredColor);\n\n\t\tRwIm3DVertexSetU    (&TempBufferRenderVertices[TempBufferVerticesStoredShattered + 0], 4.0f * CoorsWithTriangle[m_nTriIndex][0].x * m_fStep);\n\t\tRwIm3DVertexSetV    (&TempBufferRenderVertices[TempBufferVerticesStoredShattered + 0], 4.0f * CoorsWithTriangle[m_nTriIndex][0].y * m_fStep);\n\t\tRwIm3DVertexSetU    (&TempBufferRenderVertices[TempBufferVerticesStoredShattered + 1], 4.0f * CoorsWithTriangle[m_nTriIndex][1].x * m_fStep);\n\t\tRwIm3DVertexSetV    (&TempBufferRenderVertices[TempBufferVerticesStoredShattered + 1], 4.0f * CoorsWithTriangle[m_nTriIndex][1].y * m_fStep);\n\t\tRwIm3DVertexSetU    (&TempBufferRenderVertices[TempBufferVerticesStoredShattered + 2], 4.0f * CoorsWithTriangle[m_nTriIndex][2].x * m_fStep);\n\t\tRwIm3DVertexSetV    (&TempBufferRenderVertices[TempBufferVerticesStoredShattered + 2], 4.0f * CoorsWithTriangle[m_nTriIndex][2].y * m_fStep);\n\n\t\tRwIm3DVertexSetPos  (&TempBufferRenderVertices[TempBufferVerticesStoredShattered + 0], v0.x, v0.y, v0.z);\n\t\tRwIm3DVertexSetPos  (&TempBufferRenderVertices[TempBufferVerticesStoredShattered + 1], v1.x, v1.y, v1.z);\n\t\tRwIm3DVertexSetPos  (&TempBufferRenderVertices[TempBufferVerticesStoredShattered + 2], v2.x, v2.y, v2.z);\n\n\t\tTempBufferRenderIndexList[TempBufferIndicesStoredShattered + 0] = TempBufferVerticesStoredShattered - TEMPBUFFERVERTSHATTEREDOFFSET + 0;\n\t\tTempBufferRenderIndexList[TempBufferIndicesStoredShattered + 1] = TempBufferVerticesStoredShattered - TEMPBUFFERVERTSHATTEREDOFFSET + 1;\n\t\tTempBufferRenderIndexList[TempBufferIndicesStoredShattered + 2] = TempBufferVerticesStoredShattered - TEMPBUFFERVERTSHATTEREDOFFSET + 2;\n\t\tTempBufferRenderIndexList[TempBufferIndicesStoredShattered + 3] = TempBufferVerticesStoredShattered - TEMPBUFFERVERTSHATTEREDOFFSET + 0;\n\t\tTempBufferRenderIndexList[TempBufferIndicesStoredShattered + 4] = TempBufferVerticesStoredShattered - TEMPBUFFERVERTSHATTEREDOFFSET + 2;\n\t\tTempBufferRenderIndexList[TempBufferIndicesStoredShattered + 5] = TempBufferVerticesStoredShattered - TEMPBUFFERVERTSHATTEREDOFFSET + 1;\n\n\t\tTempBufferIndicesStoredShattered  += 6;\n\t\tTempBufferVerticesStoredShattered += 3;\n\t}\n}\n\nvoid\nCGlass::Init(void)\n{\n\tfor ( int32 i = 0; i < NUM_GLASSPANES; i++ )\n\t\taGlassPanes[i].m_bActive = false;\n\n\tfor ( int32 i = 0; i < NUM_GLASSTRIANGLES; i++  )\n\t\tCentersWithTriangle[i] = (CoorsWithTriangle[i][0] + CoorsWithTriangle[i][1] + CoorsWithTriangle[i][2]) / 3;\n}\n\nvoid\nCGlass::Update(void)\n{\n\tfor ( int32 i = 0; i < NUM_GLASSPANES; i++ )\n\t{\n\t\tif ( aGlassPanes[i].m_bActive )\n\t\t\taGlassPanes[i].Update();\n\t}\n}\n\nvoid\nCGlass::Render(void)\n{\n\tTempBufferVerticesStoredHiLight    = 0;\n\tTempBufferIndicesStoredHiLight     = 0;\n\n\tTempBufferVerticesStoredShattered  = TEMPBUFFERVERTSHATTEREDOFFSET;\n\tTempBufferIndicesStoredShattered   = TEMPBUFFERINDEXSHATTEREDOFFSET;\n\n\tTempBufferVerticesStoredReflection = TEMPBUFFERVERTREFLECTIONOFFSET;\n\tTempBufferIndicesStoredReflection  = TEMPBUFFERINDEXREFLECTIONOFFSET;\n\n\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE,      (void *)FALSE);\n\tRwRenderStateSet(rwRENDERSTATETEXTUREFILTER,     (void *)rwFILTERLINEAR);\n\tRwRenderStateSet(rwRENDERSTATEFOGENABLE,         (void *)TRUE);\n\tRwRenderStateSet(rwRENDERSTATEFOGCOLOR,          (void *)RWRGBALONG(CTimeCycle::GetFogRed(), CTimeCycle::GetFogGreen(), CTimeCycle::GetFogBlue(), 255));\n\tRwRenderStateSet(rwRENDERSTATESRCBLEND,          (void *)rwBLENDONE);\n\tRwRenderStateSet(rwRENDERSTATEDESTBLEND,         (void *)rwBLENDONE);\n\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)TRUE);\n\n\tPUSH_RENDERGROUP(\"CGlass::Render\");\n\n\tfor ( int32 i = 0; i < NUM_GLASSPANES; i++ )\n\t{\n\t\tif ( aGlassPanes[i].m_bActive )\n\t\t\taGlassPanes[i].Render();\n\t}\n\n\tfor ( uint32 i = 0; i < NumGlassEntities; i++ )\n\t\tRenderEntityInGlass(apEntitiesToBeRendered[i]);\n\n\tPOP_RENDERGROUP();\n\n\tNumGlassEntities = 0;\n\n\tRenderHiLightPolys();\n\tRenderShatteredPolys();\n\tRenderReflectionPolys();\n\n\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void *)TRUE);\n\tRwRenderStateSet(rwRENDERSTATEZTESTENABLE,  (void *)TRUE);\n\tRwRenderStateSet(rwRENDERSTATESRCBLEND,     (void *)rwBLENDSRCALPHA);\n\tRwRenderStateSet(rwRENDERSTATEDESTBLEND,    (void *)rwBLENDINVSRCALPHA);\n\tRwRenderStateSet(rwRENDERSTATEFOGENABLE,    (void *)FALSE);\n}\n\nCFallingGlassPane *\nCGlass::FindFreePane(void)\n{\n\tfor ( int32 i = 0; i < NUM_GLASSPANES; i++ )\n\t{\n\t\tif ( !aGlassPanes[i].m_bActive )\n\t\t\treturn &aGlassPanes[i];\n\t}\n\n\treturn nil;\n}\n\nvoid\nCGlass::GeneratePanesForWindow(uint32 type, CVector pos, CVector up, CVector right, CVector speed, CVector center,\n\t\t\t\t\t\t\t\tfloat moveSpeed, bool cracked, bool explosion, int32 stepmul, bool carGlass)\n{\n\tfloat upLen    = up.Magnitude();\n\tfloat rightLen = right.Magnitude();\n\n\tfloat upSteps = upLen + 0.75f;\n\tif ( upSteps < 1.0f ) upSteps = 1.0f;\n\n\tfloat rightSteps = rightLen + 0.75f;\n\tif ( rightSteps < 1.0f ) rightSteps = 1.0f;\n\n\tuint32 ysteps = stepmul * (uint32)upSteps;\n\tif ( ysteps > 3 ) ysteps = 3;\n\n\tuint32 xsteps = stepmul * (uint32)rightSteps;\n\tif ( xsteps > 3 ) xsteps = 3;\n\n\tif ( explosion )\n\t{\n\t\tif ( ysteps > 1 ) ysteps = 1;\n\t\tif ( xsteps > 1 ) xsteps = 1;\n\t}\n\n\tfloat upScl    = upLen    / float(ysteps);\n\tfloat rightScl = rightLen / float(xsteps);\n\n\tbool bZFound;\n\tfloat groundZ = CWorld::FindGroundZFor3DCoord(pos.x, pos.y, pos.z, &bZFound);\n\tif ( !bZFound ) groundZ = pos.z - 2.0f;\n\n\tfor ( uint32 y = 0; y < ysteps; y++  )\n\t{\n\t\tfor ( uint32 x = 0; x < xsteps; x++ )\n\t\t{\n\t\t\tfloat stepy = float(y) * upLen    / float(ysteps);\n\t\t\tfloat stepx = float(x) * rightLen / float(xsteps);\n\n\t\t\tfor ( int32 i = 0; i < NUM_GLASSTRIANGLES; i++ )\n\t\t\t{\n\t\t\t\tCFallingGlassPane *pane = FindFreePane();\n\t\t\t\tif ( pane )\n\t\t\t\t{\n\t\t\t\t\tpane->m_nTriIndex = i;\n\t\t\t\t\t\n\t\t\t\t\tpane->GetRight()  = (right * rightScl) / rightLen;\n\t\t\t\t\tpane->GetUp()     = (up    * upScl)    / upLen;\n\n\t\t\t\t\tCVector fwd = CrossProduct(pane->GetRight(), pane->GetUp());\n\t\t\t\t\tfwd.Normalise();\n\n\t\t\t\t\tpane->GetForward() = fwd;\n\n\t\t\t\t\tpane->GetPosition() = right / rightLen * (rightScl * CentersWithTriangle[i].x + stepx)\n\t\t\t\t\t\t\t\t\t\t+ up    / upLen    * (upScl    * CentersWithTriangle[i].y + stepy)\n\t\t\t\t\t\t\t\t\t\t+ pos;\n\n\t\t\t\t\tpane->m_vecMoveSpeed.x = float((CGeneral::GetRandomNumber() & 127) - 64) * 0.0015f + speed.x;\n\t\t\t\t\tpane->m_vecMoveSpeed.y = float((CGeneral::GetRandomNumber() & 127) - 64) * 0.0015f + speed.y;\n\t\t\t\t\tpane->m_vecMoveSpeed.z = 0.0f + speed.z;\n\n\t\t\t\t\tif ( moveSpeed != 0.0f )\n\t\t\t\t\t{\n\t\t\t\t\t\tCVector dist = pane->GetPosition() - center;\n\t\t\t\t\t\tdist.Normalise();\n\n\t\t\t\t\t\tpane->m_vecMoveSpeed += moveSpeed * dist;\n\t\t\t\t\t}\n\n\t\t\t\t\tpane->m_vecTurn.x = float((CGeneral::GetRandomNumber() & 127) - 64) * 0.002f;\n\t\t\t\t\tpane->m_vecTurn.y = float((CGeneral::GetRandomNumber() & 127) - 64) * 0.002f;\n\t\t\t\t\tpane->m_vecTurn.z = float((CGeneral::GetRandomNumber() & 127) - 64) * 0.002f;\n\n\t\t\t\t\tswitch ( type )\n\t\t\t\t\t{\n\t\t\t\t\t\tcase 0:\n\t\t\t\t\t\tcase 2:\n\t\t\t\t\t\t\tpane->m_nTimer = CTimer::GetTimeInMilliseconds();\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 1:\n\t\t\t\t\t\t\tfloat dist = (pane->GetPosition() - center).Magnitude();\n\t\t\t\t\t\t\tpane->m_nTimer = uint32(dist*100 + CTimer::GetTimeInMilliseconds());\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tpane->m_fGroundZ = groundZ;\n\t\t\t\t\tpane->m_bShattered = cracked;\n\t\t\t\t\tpane->m_fStep = upLen / float(ysteps);\n\t\t\t\t\tpane->m_bCarGlass = carGlass;\n\t\t\t\t\tpane->m_bActive = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nCGlass::AskForObjectToBeRenderedInGlass(CEntity *entity)\n{\n#ifdef FIX_BUGS\n\tif ( NumGlassEntities < NUM_GLASSENTITIES )\n#else\n\tif ( NumGlassEntities < NUM_GLASSENTITIES-1 )\n#endif\n\t{\n\t\tapEntitiesToBeRendered[NumGlassEntities++] = entity;\n\t}\n}\n\nvoid\nCGlass::RenderEntityInGlass(CEntity *entity)\n{\n\tASSERT(entity!=nil);\n\tCObject *object = (CObject *)entity;\n\n\tif ( object->bGlassBroken )\n\t\treturn;\n\n\tfloat distToCamera = (TheCamera.GetPosition() - object->GetPosition()).Magnitude();\n\n\tif ( distToCamera > 40.0f )\n\t\treturn;\n\n\tCVector fwdNorm = object->GetForward();\n\tfwdNorm.Normalise();\n\tuint8 alpha = CalcAlphaWithNormal(&fwdNorm);\n\n\tCColModel *col = object->GetColModel();\n\tASSERT(col!=nil);\n\tif ( col->numTriangles >= 2 )\n\t{\n\t\tCVector a = object->GetMatrix() * col->vertices[0].Get();\n\t\tCVector b = object->GetMatrix() * col->vertices[1].Get();\n\t\tCVector c = object->GetMatrix() * col->vertices[2].Get();\n\t\tCVector d = object->GetMatrix() * col->vertices[3].Get();\n\n\t\tif ( object->bGlassCracked )\n\t\t{\n\t\t\tuint8 color = 255;\n\t\t\tif ( distToCamera > 30.0f )\n\t\t\t\tcolor = int32((1.0f - (distToCamera - 30.0f) * 4.0f / 40.0f) * 255);\n\n\t\t\tif ( TempBufferIndicesStoredShattered >= TEMPBUFFERINDEXSHATTEREDSIZE-13 || TempBufferVerticesStoredShattered >= TEMPBUFFERVERTSHATTEREDSIZE-5 )\n\t\t\t\tRenderShatteredPolys();\n\n\t\t\tRwIm3DVertexSetRGBA (&TempBufferRenderVertices[TempBufferVerticesStoredShattered + 0], color, color, color, color);\n\t\t\tRwIm3DVertexSetRGBA (&TempBufferRenderVertices[TempBufferVerticesStoredShattered + 1], color, color, color, color);\n\t\t\tRwIm3DVertexSetRGBA (&TempBufferRenderVertices[TempBufferVerticesStoredShattered + 2], color, color, color, color);\n\t\t\tRwIm3DVertexSetRGBA (&TempBufferRenderVertices[TempBufferVerticesStoredShattered + 3], color, color, color, color);\n\n\t\t\tRwIm3DVertexSetU    (&TempBufferRenderVertices[TempBufferVerticesStoredShattered + 0], 0.0f);\n\t\t\tRwIm3DVertexSetV    (&TempBufferRenderVertices[TempBufferVerticesStoredShattered + 0], 0.0f);\n\t\t\tRwIm3DVertexSetU    (&TempBufferRenderVertices[TempBufferVerticesStoredShattered + 1], 16.0f);\n\t\t\tRwIm3DVertexSetV    (&TempBufferRenderVertices[TempBufferVerticesStoredShattered + 1], 0.0f);\n\t\t\tRwIm3DVertexSetU    (&TempBufferRenderVertices[TempBufferVerticesStoredShattered + 2], 0.0f);\n\t\t\tRwIm3DVertexSetV    (&TempBufferRenderVertices[TempBufferVerticesStoredShattered + 2], 16.0f);\n\t\t\tRwIm3DVertexSetU    (&TempBufferRenderVertices[TempBufferVerticesStoredShattered + 3], 16.0f);\n\t\t\tRwIm3DVertexSetV    (&TempBufferRenderVertices[TempBufferVerticesStoredShattered + 3], 16.0f);\n\n\t\t\tRwIm3DVertexSetPos  (&TempBufferRenderVertices[TempBufferVerticesStoredShattered + 0], a.x, a.y, a.z);\n\t\t\tRwIm3DVertexSetPos  (&TempBufferRenderVertices[TempBufferVerticesStoredShattered + 1], b.x, b.y, b.z);\n\t\t\tRwIm3DVertexSetPos  (&TempBufferRenderVertices[TempBufferVerticesStoredShattered + 2], c.x, c.y, c.z);\n\t\t\tRwIm3DVertexSetPos  (&TempBufferRenderVertices[TempBufferVerticesStoredShattered + 3], d.x, d.y, d.z);\n\n\t\t\tTempBufferRenderIndexList[TempBufferIndicesStoredShattered + 0]  = col->triangles[0].a + TempBufferVerticesStoredShattered - TEMPBUFFERVERTSHATTEREDOFFSET;\n\t\t\tTempBufferRenderIndexList[TempBufferIndicesStoredShattered + 1]  = col->triangles[0].b + TempBufferVerticesStoredShattered - TEMPBUFFERVERTSHATTEREDOFFSET;\n\t\t\tTempBufferRenderIndexList[TempBufferIndicesStoredShattered + 2]  = col->triangles[0].c + TempBufferVerticesStoredShattered - TEMPBUFFERVERTSHATTEREDOFFSET;\n\t\t\tTempBufferRenderIndexList[TempBufferIndicesStoredShattered + 3]  = col->triangles[1].a + TempBufferVerticesStoredShattered - TEMPBUFFERVERTSHATTEREDOFFSET;\n\t\t\tTempBufferRenderIndexList[TempBufferIndicesStoredShattered + 4]  = col->triangles[1].b + TempBufferVerticesStoredShattered - TEMPBUFFERVERTSHATTEREDOFFSET;\n\t\t\tTempBufferRenderIndexList[TempBufferIndicesStoredShattered + 5]  = col->triangles[1].c + TempBufferVerticesStoredShattered - TEMPBUFFERVERTSHATTEREDOFFSET;\n\t\t\tTempBufferRenderIndexList[TempBufferIndicesStoredShattered + 6]  = col->triangles[0].a + TempBufferVerticesStoredShattered - TEMPBUFFERVERTSHATTEREDOFFSET;\n\t\t\tTempBufferRenderIndexList[TempBufferIndicesStoredShattered + 7]  = col->triangles[0].c + TempBufferVerticesStoredShattered - TEMPBUFFERVERTSHATTEREDOFFSET;\n\t\t\tTempBufferRenderIndexList[TempBufferIndicesStoredShattered + 8]  = col->triangles[0].b + TempBufferVerticesStoredShattered - TEMPBUFFERVERTSHATTEREDOFFSET;\n\t\t\tTempBufferRenderIndexList[TempBufferIndicesStoredShattered + 9]  = col->triangles[1].a + TempBufferVerticesStoredShattered - TEMPBUFFERVERTSHATTEREDOFFSET;\n\t\t\tTempBufferRenderIndexList[TempBufferIndicesStoredShattered + 10] = col->triangles[1].c + TempBufferVerticesStoredShattered - TEMPBUFFERVERTSHATTEREDOFFSET;\n\t\t\tTempBufferRenderIndexList[TempBufferIndicesStoredShattered + 11] = col->triangles[1].b + TempBufferVerticesStoredShattered - TEMPBUFFERVERTSHATTEREDOFFSET;\n\n\t\t\tTempBufferIndicesStoredShattered  += 12;\n\t\t\tTempBufferVerticesStoredShattered += 4;\n\t\t}\n\n\t\tif ( TempBufferIndicesStoredReflection >= TEMPBUFFERINDEXREFLECTIONSIZE-13 || TempBufferVerticesStoredReflection >= TEMPBUFFERVERTREFLECTIONSIZE-5 )\n\t\t\tRenderReflectionPolys();\n\n\t\tuint8 color = 100;\n\t\tif ( distToCamera > 30.0f )\n\t\t\tcolor = int32((1.0f - (distToCamera - 30.0f) * 4.0f / 40.0f) * 100);\n\n\t\tRwIm3DVertexSetRGBA (&TempBufferRenderVertices[TempBufferVerticesStoredReflection + 0], color, color, color, color);\n\t\tRwIm3DVertexSetRGBA (&TempBufferRenderVertices[TempBufferVerticesStoredReflection + 1], color, color, color, color);\n\t\tRwIm3DVertexSetRGBA (&TempBufferRenderVertices[TempBufferVerticesStoredReflection + 2], color, color, color, color);\n\t\tRwIm3DVertexSetRGBA (&TempBufferRenderVertices[TempBufferVerticesStoredReflection + 3], color, color, color, color);\n\n\t\tfloat FwdAngle = CGeneral::GetATanOfXY(TheCamera.GetForward().x, TheCamera.GetForward().y);\n\t\tfloat v = 2.0f * TheCamera.GetForward().z * 0.2f;\n\t\tfloat u = float(object->m_randomSeed & 15) * 0.02f + (FwdAngle / TWOPI);\n\n\t\tRwIm3DVertexSetU    (&TempBufferRenderVertices[TempBufferVerticesStoredReflection + 0], u);\n\t\tRwIm3DVertexSetV    (&TempBufferRenderVertices[TempBufferVerticesStoredReflection + 0], v);\n\t\tRwIm3DVertexSetU    (&TempBufferRenderVertices[TempBufferVerticesStoredReflection + 1], u+0.2f);\n\t\tRwIm3DVertexSetV    (&TempBufferRenderVertices[TempBufferVerticesStoredReflection + 1], v);\n\t\tRwIm3DVertexSetU    (&TempBufferRenderVertices[TempBufferVerticesStoredReflection + 2], u);\n\t\tRwIm3DVertexSetV    (&TempBufferRenderVertices[TempBufferVerticesStoredReflection + 2], v+0.2f);\n\t\tRwIm3DVertexSetU    (&TempBufferRenderVertices[TempBufferVerticesStoredReflection + 3], u+0.2f);\n\t\tRwIm3DVertexSetV    (&TempBufferRenderVertices[TempBufferVerticesStoredReflection + 3], v+0.2f);\n\n\t\tRwIm3DVertexSetPos  (&TempBufferRenderVertices[TempBufferVerticesStoredReflection + 0], a.x, a.y, a.z);\n\t\tRwIm3DVertexSetPos  (&TempBufferRenderVertices[TempBufferVerticesStoredReflection + 1], b.x, b.y, b.z);\n\t\tRwIm3DVertexSetPos  (&TempBufferRenderVertices[TempBufferVerticesStoredReflection + 2], c.x, c.y, c.z);\n\t\tRwIm3DVertexSetPos  (&TempBufferRenderVertices[TempBufferVerticesStoredReflection + 3], d.x, d.y, d.z);\n\n\t\tTempBufferRenderIndexList[TempBufferIndicesStoredReflection + 0]  = col->triangles[0].a + TempBufferVerticesStoredReflection - TEMPBUFFERVERTREFLECTIONOFFSET;\n\t\tTempBufferRenderIndexList[TempBufferIndicesStoredReflection + 1]  = col->triangles[0].b + TempBufferVerticesStoredReflection - TEMPBUFFERVERTREFLECTIONOFFSET;\n\t\tTempBufferRenderIndexList[TempBufferIndicesStoredReflection + 2]  = col->triangles[0].c + TempBufferVerticesStoredReflection - TEMPBUFFERVERTREFLECTIONOFFSET;\n\t\tTempBufferRenderIndexList[TempBufferIndicesStoredReflection + 3]  = col->triangles[1].a + TempBufferVerticesStoredReflection - TEMPBUFFERVERTREFLECTIONOFFSET;\n\t\tTempBufferRenderIndexList[TempBufferIndicesStoredReflection + 4]  = col->triangles[1].b + TempBufferVerticesStoredReflection - TEMPBUFFERVERTREFLECTIONOFFSET;\n\t\tTempBufferRenderIndexList[TempBufferIndicesStoredReflection + 5]  = col->triangles[1].c + TempBufferVerticesStoredReflection - TEMPBUFFERVERTREFLECTIONOFFSET;\n\t\tTempBufferRenderIndexList[TempBufferIndicesStoredReflection + 6]  = col->triangles[0].a + TempBufferVerticesStoredReflection - TEMPBUFFERVERTREFLECTIONOFFSET;\n\t\tTempBufferRenderIndexList[TempBufferIndicesStoredReflection + 7]  = col->triangles[0].c + TempBufferVerticesStoredReflection - TEMPBUFFERVERTREFLECTIONOFFSET;\n\t\tTempBufferRenderIndexList[TempBufferIndicesStoredReflection + 8]  = col->triangles[0].b + TempBufferVerticesStoredReflection - TEMPBUFFERVERTREFLECTIONOFFSET;\n\t\tTempBufferRenderIndexList[TempBufferIndicesStoredReflection + 9]  = col->triangles[1].a + TempBufferVerticesStoredReflection - TEMPBUFFERVERTREFLECTIONOFFSET;\n\t\tTempBufferRenderIndexList[TempBufferIndicesStoredReflection + 10] = col->triangles[1].c + TempBufferVerticesStoredReflection - TEMPBUFFERVERTREFLECTIONOFFSET;\n\t\tTempBufferRenderIndexList[TempBufferIndicesStoredReflection + 11] = col->triangles[1].b + TempBufferVerticesStoredReflection - TEMPBUFFERVERTREFLECTIONOFFSET;\n\n\t\tTempBufferIndicesStoredReflection  += 12;\n\t\tTempBufferVerticesStoredReflection += 4;\n\t}\n}\n\nint32\nCGlass::CalcAlphaWithNormal(CVector *normal)\n{\n\tASSERT(normal!=nil);\n\t\n\tfloat fwdDir = 2.0f * DotProduct(*normal, TheCamera.GetForward());\n\tfloat fwdDot = DotProduct(TheCamera.GetForward()-fwdDir*(*normal), CVector(0.57f, 0.57f, -0.57f));\n\treturn int32(lerp(fwdDot*fwdDot*fwdDot*fwdDot*fwdDot*fwdDot, 20.0f, 255.0f));\n}\n\nvoid\nCGlass::RenderHiLightPolys(void)\n{\n\tif ( TempBufferVerticesStoredHiLight != TEMPBUFFERVERTHILIGHTOFFSET )\n\t{\n\t\tRwRenderStateSet(rwRENDERSTATESRCBLEND,      (void *)rwBLENDONE);\n\t\tRwRenderStateSet(rwRENDERSTATEDESTBLEND,     (void *)rwBLENDONE);\n\t\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void *)RwTextureGetRaster(gpShadowExplosionTex));\n\n\t\tLittleTest();\n\n\t\tif ( RwIm3DTransform(TempBufferRenderVertices, TempBufferVerticesStoredHiLight, nil, rwIM3D_VERTEXUV) )\n\t\t{\n\t\t\tRwIm3DRenderIndexedPrimitive(rwPRIMTYPETRILIST, TempBufferRenderIndexList, TempBufferIndicesStoredHiLight);\n\t\t\tRwIm3DEnd();\n\t\t}\n\n\t\tTempBufferVerticesStoredHiLight = TEMPBUFFERVERTHILIGHTOFFSET;\n\t\tTempBufferIndicesStoredHiLight  = TEMPBUFFERINDEXHILIGHTOFFSET;\n\t}\n}\n\nvoid\nCGlass::RenderShatteredPolys(void)\n{\n\tif ( TempBufferVerticesStoredShattered != TEMPBUFFERVERTSHATTEREDOFFSET )\n\t{\n\t\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void *)RwTextureGetRaster(gpCrackedGlassTex));\n\t\tRwRenderStateSet(rwRENDERSTATESRCBLEND,      (void *)rwBLENDSRCALPHA);\n\t\tRwRenderStateSet(rwRENDERSTATEDESTBLEND,     (void *)rwBLENDINVSRCALPHA);\n\n\t\tLittleTest();\n\n\t\tif ( RwIm3DTransform(&TempBufferRenderVertices[TEMPBUFFERVERTSHATTEREDOFFSET], TempBufferVerticesStoredShattered - TEMPBUFFERVERTSHATTEREDOFFSET, nil, rwIM3D_VERTEXUV) )\n\t\t{\n\t\t\tRwIm3DRenderIndexedPrimitive(rwPRIMTYPETRILIST, &TempBufferRenderIndexList[TEMPBUFFERINDEXSHATTEREDOFFSET], TempBufferIndicesStoredShattered - TEMPBUFFERINDEXSHATTEREDOFFSET);\n\t\t\tRwIm3DEnd();\n\t\t}\n\n\t\tTempBufferIndicesStoredShattered  = TEMPBUFFERINDEXSHATTEREDOFFSET;\n\t\tTempBufferVerticesStoredShattered = TEMPBUFFERVERTSHATTEREDOFFSET;\n\t}\n}\n\nvoid\nCGlass::RenderReflectionPolys(void)\n{\n\tif ( TempBufferVerticesStoredReflection != TEMPBUFFERVERTREFLECTIONOFFSET )\n\t{\n\t\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void *)RwTextureGetRaster(gpShadowHeadLightsTex));\n\t\tRwRenderStateSet(rwRENDERSTATESRCBLEND,      (void *)rwBLENDSRCALPHA);\n\t\tRwRenderStateSet(rwRENDERSTATEDESTBLEND,     (void *)rwBLENDINVSRCALPHA);\n\n\t\tLittleTest();\n\n\t\tif ( RwIm3DTransform(&TempBufferRenderVertices[TEMPBUFFERVERTREFLECTIONOFFSET], TempBufferVerticesStoredReflection - TEMPBUFFERVERTREFLECTIONOFFSET, nil, rwIM3D_VERTEXUV) )\n\t\t{\n\t\t\tRwIm3DRenderIndexedPrimitive(rwPRIMTYPETRILIST, &TempBufferRenderIndexList[TEMPBUFFERINDEXREFLECTIONOFFSET], TempBufferIndicesStoredReflection - TEMPBUFFERINDEXREFLECTIONOFFSET);\n\t\t\tRwIm3DEnd();\n\t\t}\n\n\t\tTempBufferIndicesStoredReflection  = TEMPBUFFERINDEXREFLECTIONOFFSET;\n\t\tTempBufferVerticesStoredReflection = TEMPBUFFERVERTREFLECTIONOFFSET;\n\t}\n}\n\nvoid\nCGlass::WindowRespondsToCollision(CEntity *entity, float amount, CVector speed, CVector point, bool explosion)\n{\n\tASSERT(entity!=nil);\n\t\n\tCObject *object = (CObject *)entity;\n\n\tif ( object->bGlassBroken )\n\t\treturn;\n\n\tobject->bGlassCracked = true;\n\n\tCColModel *col = object->GetColModel();\n\tASSERT(col!=nil);\n\t\n\tif ( col->numTriangles == 2 )\n\t{\n\t\tCVector a = col->vertices[0].Get();\n\t\tCVector b = col->vertices[1].Get();\n\t\tCVector c = col->vertices[2].Get();\n\t\tCVector d = col->vertices[3].Get();\n\t\n\t\tfloat minx = Min(Min(a.x, b.x), Min(c.x, d.x));\n\t\tfloat maxx = Max(Max(a.x, b.x), Max(c.x, d.x));\n\t\tfloat miny = Min(Min(a.y, b.y), Min(c.y, d.y));\n\t\tfloat maxy = Max(Max(a.y, b.y), Max(c.y, d.y));\n\t\tfloat minz = Min(Min(a.z, b.z), Min(c.z, d.z));\n\t\tfloat maxz = Max(Max(a.z, b.z), Max(c.z, d.z));\n\t\t\n\t\tCVector pa = object->GetMatrix() * CVector(minx, miny, minz);\n\t\tCVector pb = object->GetMatrix() * CVector(maxx, maxy, minz);\n\t\n\t\tif ( amount > 300.0f )\n\t\t{\n\t\t\tPlayOneShotScriptObject(SCRIPT_SOUND_GLASS_BREAK_L, object->GetPosition());\n\t\n\t\t\tGeneratePanesForWindow(0,\n\t\t\t\tpa,\n\t\t\t\tCVector(0.0f,      0.0f,      maxz-minz),\n\t\t\t\tpb - pa,\n\t\t\t\tspeed, point, 0.1f, !!object->bGlassCracked, explosion, 1, false);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tPlayOneShotScriptObject(SCRIPT_SOUND_GLASS_BREAK_S, object->GetPosition());\n\t\n\t\t\tGeneratePanesForWindow(1,\n\t\t\t\tpa,\n\t\t\t\tCVector(0.0f,      0.0f,      maxz-minz),\n\t\t\t\tpb - pa,\n\t\t\t\tspeed, point, 0.1f, !!object->bGlassCracked, explosion, 1, false);\n\t\t}\n\t}\n\t\n\tobject->bGlassBroken = true;\n\tobject->bIsVisible = false;\n\tobject->bUsesCollision = false;\n}\n\nvoid\nCGlass::WindowRespondsToSoftCollision(CEntity *entity, float amount)\n{\n\tASSERT(entity!=nil);\n\t\n\tCObject *object = (CObject *)entity;\n\n\tif ( entity->bUsesCollision && amount > 50.0f && !object->bGlassCracked )\n\t{\n\t\tPlayOneShotScriptObject(SCRIPT_SOUND_GLASS_CRACK, object->GetPosition());\n\t\tobject->bGlassCracked = true;\n\t}\n}\n\nvoid\nCGlass::WasGlassHitByBullet(CEntity *entity, CVector point)\n{\n\tASSERT(entity!=nil);\n\t\n\tCObject *object = (CObject *)entity;\n\n\tif ( IsGlass(object->GetModelIndex()) )\n\t{\n\t\tif ( object->bUsesCollision )\n\t\t{\n\t\t\tif ( !object->bGlassCracked )\n\t\t\t{\n\t\t\t\tPlayOneShotScriptObject(SCRIPT_SOUND_GLASS_CRACK, object->GetPosition());\n\t\t\t\tobject->bGlassCracked = true;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif ( (CGeneral::GetRandomNumber() & 3) == 2 )\n\t\t\t\t\tWindowRespondsToCollision(object, 0.0f, CVector(0.0f, 0.0f, 0.0f), point, false);\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nCGlass::WindowRespondsToExplosion(CEntity *entity, CVector point)\n{\n\tASSERT(entity!=nil);\n\t\n\tCObject *object = (CObject *)entity;\n\t\n\tif ( object->bUsesCollision )\n\t{\n\t\tCVector distToGlass = object->GetPosition() - point;\n\t\n\t\tfloat fDistToGlass = distToGlass.Magnitude();\n\t\n\t\tif ( fDistToGlass < 10.0f )\n\t\t{\n\t\t\tdistToGlass *= (0.3f / fDistToGlass); // normalise\n\t\t\tWindowRespondsToCollision(object, 10000.0f, distToGlass, object->GetPosition(), true);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif ( fDistToGlass < 30.0f )\n\t\t\t\tobject->bGlassCracked = true;\n\t\t}\n\t}\n}\n\n\nvoid\nCGlass::CarWindscreenShatters(CVehicle *vehicle, bool unk)\n{\n\tASSERT(vehicle!=nil);\n\t\n\tCColModel *col = vehicle->GetColModel();\n\tASSERT(col!=nil);\n\t\n\tif ( col->numTriangles < 2 )\n\t\treturn;\n\t\n\tCColTriangle *tria = nil;\n\tint32 triIndex = -1;\n\tCColTriangle *trib = nil;\n\t\t\t\n\tfor ( int32 i = 0; i < col->numTriangles; i++ )\n\t{\n\t\tCColTriangle *tri = &col->triangles[i];\n\t\tif ( tri->surface == SURFACE_GLASS )\n\t\t{\n\t\t\tif ( tria )\n\t\t\t{\n\t\t\t\ttrib = tri;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t\n\t\t\ttriIndex = i;\n\t\t\ttria = tri;\n\t\t}\n\t}\n\t\n\tif ( trib == nil )\n\t\treturn;\n\t\n\tCCollision::CalculateTrianglePlanes(col);\n\t\n\tCColTrianglePlane *triPlanes = col->trianglePlanes;\n\t\n\tif ( triPlanes == nil )\n\t\treturn;\n\t\n\tCVector planeNormal;\n\ttriPlanes[triIndex].GetNormal(planeNormal);\n\tplaneNormal = Multiply3x3(vehicle->GetMatrix(), planeNormal);\n\t\n\tCVector vec1 = CrossProduct(vehicle->GetRight(), planeNormal);\n\tvec1.Normalise();\n\t\n\tCVector vec2 = CrossProduct(planeNormal, vehicle->GetUp());\n\tvec2.Normalise();\n\t\n\tCVector v[6];\n\tfloat proj1[6];\n\tfloat proj2[6];\n\t\n\tv[0] = col->vertices[tria->a].Get();\n\tv[1] = col->vertices[tria->b].Get();\n\tv[2] = col->vertices[tria->c].Get();\n\t\n\tv[3] = col->vertices[trib->a].Get();\n\tv[4] = col->vertices[trib->b].Get();\n\tv[5] = col->vertices[trib->c].Get();\n\t\n\tv[0] = vehicle->GetMatrix() * v[0];\n\tv[1] = vehicle->GetMatrix() * v[1];\n\tv[2] = vehicle->GetMatrix() * v[2];\n\tv[3] = vehicle->GetMatrix() * v[3];\n\tv[4] = vehicle->GetMatrix() * v[4];\n\tv[5] = vehicle->GetMatrix() * v[5];\n\t\n\tproj1[0] = DotProduct(v[0], vec1);\n\tproj2[0] = DotProduct(v[0], vec2);\n\tproj1[1] = DotProduct(v[1], vec1);\n\tproj2[1] = DotProduct(v[1], vec2);\n\tproj1[2] = DotProduct(v[2], vec1);\n\tproj2[2] = DotProduct(v[2], vec2);\n\t\n\tproj1[3] = DotProduct(v[3], vec1);\n\tproj2[3] = DotProduct(v[3], vec2);\n\tproj1[4] = DotProduct(v[4], vec1);\n\tproj2[4] = DotProduct(v[4], vec2);\n\tproj1[5] = DotProduct(v[5], vec1);\n\tproj2[5] = DotProduct(v[5], vec2);\n\t\n\tint32 originIndex = 0;\n\tfloat max1 = proj1[0];\n\tfloat max2 = proj2[0];\n\tfloat origin  = proj1[0] + proj2[0];\n\t\n\tfor ( int32 i = 1; i < 6; i++ )\n\t{\n\t\tfloat o = proj1[i] + proj2[i];\n\t\tif ( o < origin )\n\t\t{\n\t\t\torigin = o;\n\t\t\toriginIndex = i;\n\t\t}\n\t\t\n\t\tif ( proj1[i] > max1 )\n\t\t\tmax1 = proj1[i];\n\t\tif ( proj2[i] > max2 )\n\t\t\tmax2 = proj2[i];\n\t}\n\t\n\tfloat bound1 = max1 - proj1[originIndex];\n\tfloat bound2  = max2 - proj2[originIndex];\n\t\t\t\t\t\t\n\tPlayOneShotScriptObject(SCRIPT_SOUND_GLASS_BREAK_L, vehicle->GetPosition());\n\t\n\tCVector center = v[originIndex] + ((0.5f*bound1) * vec1) + ((0.5f*bound2) * vec2);\n\tCVector speed = vehicle->m_vecMoveSpeed;\n\tCVector right = bound2 * vec2;\n\tCVector up    = bound1 * vec1;\n\tCVector pos   = v[originIndex];\n\t\n\tGeneratePanesForWindow(2, pos, up, right, speed, center, 0.1f, false, false, 2, true);\n}\n\nbool\nCGlass::HasGlassBeenShatteredAtCoors(float x, float y, float z)\n{\n\tCEntity *entity = nil;\n\tfloat dist = 20.0f;\n\t  \n\tint32 nStartX = Max(CWorld::GetSectorIndexX(x - 30.0f), 0);\n\tint32 nStartY = Max(CWorld::GetSectorIndexY(y - 30.0f), 0);\n\tint32 nEndX   = Min(CWorld::GetSectorIndexX(x + 30.0f), NUMSECTORS_X-1);\n\tint32 nEndY   = Min(CWorld::GetSectorIndexY(y + 30.0f), NUMSECTORS_Y-1);\n\n\tCWorld::AdvanceCurrentScanCode();\n\t\n\tfor ( int32 ys = nStartY; ys <= nEndY; ys++ )\n\t{\n\t\tfor ( int32 xs = nStartX; xs <= nEndX; xs++ )\n\t\t{\n\t\t\tCSector *sector = CWorld::GetSector(xs, ys);\n\n\t\t\tASSERT(sector != nil);\n\t\t\t\n\t\t\tFindWindowSectorList(sector->m_lists[ENTITYLIST_OBJECTS], &dist, &entity, x, y, z);\n\t\t\tFindWindowSectorList(sector->m_lists[ENTITYLIST_DUMMIES], &dist, &entity, x, y, z);\n\t\t}\n\t}\n\t\n\tif ( entity )\n\t{\n\t\tif ( entity->GetType() == ENTITY_TYPE_DUMMY )\n\t\t\treturn false;\n\t\t\n\t\treturn !!((CObject*)entity)->bGlassBroken;\n\t}\n\t\n\treturn false;\n}\n\nvoid\nCGlass::FindWindowSectorList(CPtrList &list, float *dist, CEntity **entity, float x, float y, float z)\n{\n\tASSERT(dist!=nil);\n\tASSERT(entity!=nil);\n\t\n\tCPtrNode *node = list.first;\n\t\n\twhile ( node != nil )\n\t{\n\t\tCEntity *ent = (CEntity *)node->item;\n\t\tuint16 scanCode = ent->m_scanCode;\n\t\tnode = node->next;\n\t\t\n\t\tASSERT(ent!=nil);\n\t\t\n\t\tif ( IsGlass(ent->GetModelIndex()) )\n\t\t{\n\t\t\tif ( scanCode != CWorld::GetCurrentScanCode() )\n\t\t\t{\n\t\t\t\tent->m_scanCode = CWorld::GetCurrentScanCode();\n\t\t\t\t\n\t\t\t\tfloat dst = (CVector(x,y,z) - ent->GetPosition()).Magnitude();\n\t\t\t\t\n\t\t\t\tif ( dst < *dist )\n\t\t\t\t{\n\t\t\t\t\t*dist = dst;\n\t\t\t\t\t*entity = ent;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nCGlass::BreakGlassPhysically(CVector pos, float radius)\n{\n\tstatic uint32 breakTime = 0;\n\t\n\tif ( CTimer::GetTimeInMilliseconds() < breakTime + 1000 && CTimer::GetTimeInMilliseconds() >= breakTime )\n\t\treturn;\n\t\n\tCColSphere sphere;\n\tsphere.piece = 0;\n\tsphere.radius = radius;\n\tsphere.surface = 0;\n\t\n\tfor ( int32 i = CPools::GetObjectPool()->GetSize() - 1; i >= 0; i-- )\n\t{\n\t\tCObject *object = CPools::GetObjectPool()->GetSlot(i);\n\t\tif (object)\n\t\t{\n\t\t\tif ( IsGlass(object->GetModelIndex()) )\n\t\t\t{\n\t\t\t\tif ( object->bUsesCollision )\n\t\t\t\t{\n\t\t\t\t\tCColModel *col = object->GetColModel();\n\t\t\t\t\tASSERT(col!=nil);\n\t\t\t\t\t\n\t\t\t\t\tif ( col->numTriangles < 2 )\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\n\t\t\t\t\tbool hit = false;\n\t\t\t\t\t\n\t\t\t\t\tCVector dist = pos - object->GetPosition();\n\t\t\t\t\t\n\t\t\t\t\tsphere.center.x = DotProduct(dist, object->GetRight());\n\t\t\t\t\tsphere.center.y = DotProduct(dist, object->GetForward());\n\t\t\t\t\tsphere.center.z = DotProduct(dist, object->GetUp());\n\t\t\t\t\t\n\t\t\t\t\tCCollision::CalculateTrianglePlanes(col);\n\t\t\t\t\t\n\t\t\t\t\tfor ( int32 j = 0; j < col->numTriangles; j++ )\n\t\t\t\t\t{\n\t\t\t\t\t\tif ( CCollision::TestSphereTriangle(sphere,\n\t\t\t\t\t\t\tcol->vertices, col->triangles[j], col->trianglePlanes[j]) )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\thit = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tif ( hit )\n\t\t\t\t\t{\n\t\t\t\t\t\tbreakTime = CTimer::GetTimeInMilliseconds();\n\t\t\t\t\t\t\n\t\t\t\t\t\tif ( object->bGlassCracked )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tCVector a = col->vertices[0].Get();\n\t\t\t\t\t\t\tCVector b = col->vertices[1].Get();\n\t\t\t\t\t\t\tCVector c = col->vertices[2].Get();\n\t\t\t\t\t\t\tCVector d = col->vertices[3].Get();\n\t\t\t\t\t\t\n\t\t\t\t\t\t\tfloat minx = Min(Min(a.x, b.x), Min(c.x, d.x));\n\t\t\t\t\t\t\tfloat maxx = Max(Max(a.x, b.x), Max(c.x, d.x));\n\t\t\t\t\t\t\tfloat miny = Min(Min(a.y, b.y), Min(c.y, d.y));\n\t\t\t\t\t\t\tfloat maxy = Max(Max(a.y, b.y), Max(c.y, d.y));\n\t\t\t\t\t\t\tfloat minz = Min(Min(a.z, b.z), Min(c.z, d.z));\n\t\t\t\t\t\t\tfloat maxz = Max(Max(a.z, b.z), Max(c.z, d.z));\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tCVector pa = object->GetMatrix() * CVector(minx, miny, minz);\n\t\t\t\t\t\t\tCVector pb = object->GetMatrix() * CVector(maxx, maxy, minz);\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tPlayOneShotScriptObject(SCRIPT_SOUND_GLASS_BREAK_S, object->GetPosition());\n\n\t\t\t\t\t\t\tGeneratePanesForWindow(1,\n\t\t\t\t\t\t\t\tpa,\n\t\t\t\t\t\t\t\tCVector(0.0f, 0.0f, maxz-minz),\n\t\t\t\t\t\t\t\tpb - pa,\n\t\t\t\t\t\t\t\tCVector(0.0f, 0.0f, 0.0f), pos, 0.1f, !!object->bGlassCracked, false, 1, false);\t\t\t\t\t\t\t\t  \n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tobject->bGlassBroken = true;\n\t\t\t\t\t\t\tobject->bIsVisible = false;\n\t\t\t\t\t\t\tobject->bUsesCollision = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tPlayOneShotScriptObject(SCRIPT_SOUND_GLASS_CRACK, object->GetPosition());\n\t\t\t\t\t\t\tobject->bGlassCracked = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}"
  },
  {
    "path": "src/render/Glass.h",
    "content": "#pragma once\n\nclass CEntity;\nclass CVehicle;\nclass CPtrList;\n\nclass CFallingGlassPane : public CMatrix\n{\npublic:\n\tCVector m_vecMoveSpeed;\n\tCVector m_vecTurn;\n\tuint32 m_nTimer;\n\tfloat m_fGroundZ;\n\tfloat m_fStep;\n\tuint8 m_nTriIndex;\n\tbool m_bActive;\n\tbool m_bShattered;\n\tbool m_bCarGlass;\n\n\tCFallingGlassPane()  { }\n\t~CFallingGlassPane() { }\n\n\tvoid Update(void);\n\tvoid Render(void);\n};\n\nVALIDATE_SIZE(CFallingGlassPane, 0x70);\n\nenum\n{\n\tNUM_GLASSTRIANGLES = 5,\n};\n\nclass CGlass\n{\n\tstatic uint32 NumGlassEntities;\n\tstatic CEntity *apEntitiesToBeRendered[NUM_GLASSENTITIES];\n\tstatic CFallingGlassPane aGlassPanes[NUM_GLASSPANES];\npublic:\n\tstatic void Init(void);\n\tstatic void Update(void);\n\tstatic void Render(void);\n\tstatic CFallingGlassPane *FindFreePane(void);\n\tstatic void GeneratePanesForWindow(uint32 type, CVector pos, CVector up, CVector right, CVector speed, CVector center, float moveSpeed, bool cracked, bool explosion, int32 stepmul, bool carGlass);\n\tstatic void AskForObjectToBeRenderedInGlass(CEntity *entity);\n\tstatic void RenderEntityInGlass(CEntity *entity);\n\tstatic int32 CalcAlphaWithNormal(CVector *normal);\n\tstatic void RenderHiLightPolys(void);\n\tstatic void RenderShatteredPolys(void);\n\tstatic void RenderReflectionPolys(void);\n\tstatic void WindowRespondsToCollision(CEntity *entity, float amount, CVector speed, CVector point, bool explosion);\n\tstatic void WindowRespondsToSoftCollision(CEntity *entity, float amount);\n\tstatic void WasGlassHitByBullet(CEntity *entity, CVector point);\n\tstatic void WindowRespondsToExplosion(CEntity *entity, CVector point);\n\tstatic void CarWindscreenShatters(CVehicle *vehicle, bool unk);\n\tstatic bool HasGlassBeenShatteredAtCoors(float x, float y, float z);\n\tstatic void FindWindowSectorList(CPtrList &list, float *dist, CEntity **entity, float x, float y, float z);\n\tstatic void BreakGlassPhysically(CVector pos, float radius);\n};"
  },
  {
    "path": "src/render/Hud.cpp",
    "content": "#include \"common.h\"\n\n#include \"Camera.h\"\n#include \"DMAudio.h\"\n#include \"Clock.h\"\n#include \"Darkel.h\"\n#include \"Hud.h\"\n#include \"Messages.h\"\n#include \"Frontend.h\"\n#include \"Font.h\"\n#include \"Pad.h\"\n#include \"Radar.h\"\n#include \"Replay.h\"\n#include \"Wanted.h\"\n#include \"Sprite.h\"\n#include \"Sprite2d.h\"\n#include \"Text.h\"\n#include \"Timer.h\"\n#include \"Script.h\"\n#include \"TxdStore.h\"\n#include \"User.h\"\n#include \"World.h\"\n#include \"CutsceneMgr.h\"\n#include \"Stats.h\"\n#include \"main.h\"\n#include \"General.h\"\n#include \"VarConsole.h\"\n\n#if defined(FIX_BUGS)\n\t#define SCREEN_SCALE_X_FIX(a) SCREEN_SCALE_X(a)\n\t#define SCREEN_SCALE_Y_FIX(a) SCREEN_SCALE_Y(a)\n\t#define SCALE_AND_CENTER_X_FIX(a) SCALE_AND_CENTER_X(a)\n#else\n\t#define SCREEN_SCALE_X_FIX(a) (a)\n\t#define SCREEN_SCALE_Y_FIX(a) (a)\n\t#define SCALE_AND_CENTER_X_FIX(a) (a)\n#endif\n\n// Game has colors inlined in code.\n// For easier modification we collect them here:\nCRGBA MONEY_COLOR(0, 207, 133, 255);\nCRGBA AMMO_COLOR(255, 150, 225, 255);\nCRGBA HEALTH_COLOR(255, 150, 225, 255);\nCRGBA ARMOUR_COLOR(185, 185, 185, 255);\nCRGBA NOTWANTED_COLOR(27, 89, 130, 255);\nCRGBA WANTED_COLOR_FLASH(62, 141, 181, 255);\nCRGBA WANTED_COLOR(97, 194, 247, 255);\nCRGBA ZONE_COLOR(45, 155, 90, 255);\nCRGBA VEHICLE_COLOR(97, 194, 247, 255);\nCRGBA CLOCK_COLOR(97, 194, 247, 255);\nCRGBA TIMER_COLOR(97, 194, 247, 255);\nCRGBA COUNTER_COLOR(97, 194, 247, 255);\nCRGBA PAGER_COLOR(32, 162, 66, 205);\nCRGBA RADARDISC_COLOR(255, 255, 255, 255);\nCRGBA BIGMESSAGE_COLOR(255, 150, 225, 255);\nCRGBA WASTEDBUSTED_COLOR(0, 207, 133, 255);\nCRGBA ODDJOB_COLOR(0, 207, 133, 255);\nCRGBA ODDJOB2_COLOR(97, 194, 247, 255);\nCRGBA MISSIONTITLE_COLOR(220, 172, 2, 255);\n\nwchar CHud::m_HelpMessage[HELP_MSG_LENGTH];\nwchar CHud::m_LastHelpMessage[HELP_MSG_LENGTH];\nuint32 CHud::m_HelpMessageState;\nuint32 CHud::m_HelpMessageTimer;\nint32 CHud::m_HelpMessageFadeTimer;\nwchar CHud::m_HelpMessageToPrint[HELP_MSG_LENGTH];\nfloat CHud::m_HelpMessageDisplayTime;\nbool CHud::m_HelpMessageDisplayForever;\nbool CHud::m_HelpMessageQuick;\nuint32 CHud::m_ZoneState;\nint32 CHud::m_ZoneFadeTimer;\nuint32 CHud::m_ZoneNameTimer;\nwchar *CHud::m_pZoneName;\nwchar *CHud::m_pLastZoneName;\nwchar *CHud::m_ZoneToPrint;\nuint32 CHud::m_VehicleState;\nint32 CHud::m_VehicleFadeTimer;\nuint32 CHud::m_VehicleNameTimer;\nwchar *CHud::m_VehicleName;\nwchar *CHud::m_pLastVehicleName;\nwchar *CHud::m_pVehicleNameToPrint;\nwchar CHud::m_Message[256];\nwchar CHud::m_PagerMessage[256];\nbool CHud::m_Wants_To_Draw_Hud;\nbool CHud::m_Wants_To_Draw_3dMarkers;\nwchar CHud::m_BigMessage[6][128];\nint16 CHud::m_ItemToFlash;\nbool CHud::m_HideRadar;\nint32 CHud::m_ClockState;\n\n// These aren't really in CHud\nfloat CHud::BigMessageInUse[6];\nfloat CHud::BigMessageAlpha[6];\nfloat CHud::BigMessageX[6];\nfloat CHud::OddJob2OffTimer;\nbool CHud::CounterOnLastFrame[NUMONSCREENCOUNTERS];\nfloat CHud::OddJob2XOffset;\nuint16 CHud::CounterFlashTimer[NUMONSCREENCOUNTERS];\nuint16 CHud::OddJob2Timer;\nbool CHud::TimerOnLastFrame;\nint16 CHud::OddJob2On;\nuint16 CHud::TimerFlashTimer;\nint16 CHud::PagerSoundPlayed;\nint32 CHud::SpriteBrightness;\nfloat CHud::PagerXOffset;\nint16 CHud::PagerTimer;\nint16 CHud::PagerOn;\n\nwchar *prevChaseString;\n\nuint32 CHud::m_WantedFadeTimer;\nuint32 CHud::m_WantedState;\nuint32 CHud::m_WantedTimer;\nuint32 CHud::m_EnergyLostFadeTimer;\nuint32 CHud::m_EnergyLostState;\nuint32 CHud::m_EnergyLostTimer;\nuint32 CHud::m_DisplayScoreFadeTimer;\nuint32 CHud::m_DisplayScoreState;\nuint32 CHud::m_DisplayScoreTimer;\nuint32 CHud::m_WeaponFadeTimer;\nuint32 CHud::m_WeaponState;\nuint32 CHud::m_WeaponTimer;\n\nuint32 CHud::m_LastDisplayScore;\nuint32 CHud::m_LastWanted;\nuint32 CHud::m_LastWeapon;\nuint32 CHud::m_LastTimeEnergyLost;\n\nCSprite2d CHud::Sprites[NUM_HUD_SPRITES];\n\nstruct\n{\n\tconst char *name;\n\tconst char *mask;\n} WeaponFilenames[] = {\n  { \"fist\", \"fistm\" },\n  { \"brassk\", \"brasskA\" },\n  { \"screw\", \"screwA\" },\n  { \"golf\", \"golfA\" },\n  { \"nightstick\", \"nightstickA\" },\n  { \"knife\", \"knifeA\" },\n  { \"bat\", \"batm\" },\n  { \"hammer\", \"hammerA\" },\n  { \"cleaver\", \"cleaverA\" },\n  { \"machete\", \"macheteA\" },\n  { \"sword\", \"swordA\" },\n  { \"chainsaw\", \"chainsawA\" },\n  { \"grenade\", \"grenadeA\" },\n  { \"grenade\", \"grenadeA\" },\n  { \"teargas\", \"teargasA\" },\n  { \"molotov\", \"molotovA\" },\n  { \"rocket\", \"rocketA\" },\n  { \"handGun1\", \"handGun1A\" },\n  { \"\", \"\" },\n  { \"python\", \"pythonA\" },\n  { \"chromegun\", \"chromegunA\" },\n  { \"spasshotGun\", \"spasshotGunA\" },\n  { \"stubshotGun\", \"stubshotGunA\" },\n  { \"tec9\", \"tec9A\" },\n  { \"uzi1\", \"uzi1A\" },\n  { \"uzi2\", \"uzi2A\" },\n  { \"mp5\", \"mp5A\" },\n  { \"\", \"\" },\n  { \"m4\", \"m4A\" },\n  { \"ruger\", \"rugerA\" },\n  { \"sniper\", \"sniperA\" },\n  { \"laserscope\", \"laserscopeA\" },\n  { \"\", \"\" },\n  { \"rocket\", \"rocketA\" },\n  { \"flamer\", \"flamerA\" },\n  { \"m60\", \"m60A\" },\n  { \"minigun\", \"minigunA\" },\n  { \"bomb\", \"bombA\" },\n  { \"\", \"\" },\n  { \"camera\", \"cameraA\" },\n  { \"\", \"\" },\n  { \"siterocket\", \"siterocket\" },\n  { \"\", \"\" },\n  { \"\", \"\" },\n  { \"\", \"\" },\n  { \"\", \"\" },\n  { \"\", \"\" },\n  { \"\", \"\" },\n  { \"\", \"\" },\n  { \"\", \"\" },\n  { \"radardisc\", \"radardisc\" },\n  { \"\", \"\" },\n  { \"\", \"\" },\n  { \"\", \"\" },\n  { \"\", \"\" },\n  { \"\", \"\" },\n  { \"\", \"\" },\n  { \"\", \"\" },\n  { \"\", \"\" },\n  { \"\", \"\" },\n  { \"\", \"\" },\n  { \"\", \"\" },\n  { \"\", \"\" },\n  { \"sitesniper\", \"sitesniperm\" },\n  { \"siteM16\", \"siteM16m\" },\n  { \"sitelaser\", \"sitelaserm\" },\n  { \"laserdot\", \"laserdotm\" },\n  { \"viewfinder_128\", \"viewfinder_128m\" },\n  { \"bleeder\", \"\" }\n};\n\nRwTexture *gpSniperSightTex;\nRwTexture *gpRocketSightTex;\nRwTexture *gpLaserSightTex;\nRwTexture *gpLaserDotTex;\nRwTexture *gpViewFinderTex;\n\nvoid CHud::Draw()\n{\n\tRwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERNEAREST);\n\tRwRenderStateSet(rwRENDERSTATETEXTUREADDRESS, (void*)rwTEXTUREADDRESSCLAMP);\n\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);\n\n\t// disable hud via second controller\n\tif (CPad::GetPad(1)->GetStartJustDown())\n\t\tm_Wants_To_Draw_Hud = !m_Wants_To_Draw_Hud;\n\n\tif (CReplay::IsPlayingBack())\n\t\treturn;\n\n\tif (m_Wants_To_Draw_Hud && !TheCamera.m_WideScreenOn) {\n\t\t// unused statics in here\n\t\tbool DrawCrossHair = false;\n\t\tbool CrossHairHidesHud = false;\n\t\tbool DrawCrossHairPC = false;\n\n\t\tCPlayerPed *playerPed = FindPlayerPed();\n\t\teWeaponType WeaponType = playerPed->GetWeapon()->m_eWeaponType;\n\t\tint32 Mode = TheCamera.Cams[TheCamera.ActiveCam].Mode;\n\n\t\tif ((Mode == CCam::MODE_SNIPER || Mode == CCam::MODE_ROCKETLAUNCHER || Mode == CCam::MODE_M16_1STPERSON || Mode == CCam::MODE_HELICANNON_1STPERSON || Mode == CCam::MODE_CAMERA)\n\t\t\t&& playerPed && !playerPed->GetWeapon()->IsTypeMelee())\n\t\t\tDrawCrossHair = true;\n\n\t\tif (Mode == CCam::MODE_M16_1STPERSON_RUNABOUT || Mode == CCam::MODE_ROCKETLAUNCHER_RUNABOUT || Mode == CCam::MODE_SNIPER_RUNABOUT)\n\t\t\tDrawCrossHairPC = true;\n\t\tif (TheCamera.Cams[TheCamera.ActiveCam].Using3rdPersonMouseCam() && (!CPad::GetPad(0)->GetLookBehindForPed() || TheCamera.m_bPlayerIsInGarage)\n\t\t\t|| Mode == CCam::MODE_1STPERSON_RUNABOUT) {\n\t\t\tif (playerPed) {\n\t\t\t\tif (playerPed->m_nPedState != PED_ENTER_CAR && playerPed->m_nPedState != PED_CARJACK) {\n\n\t\t\t\t\tif (WeaponType >= WEAPONTYPE_COLT45 && WeaponType <= WEAPONTYPE_RUGER\n\t\t\t\t\t\t|| WeaponType == WEAPONTYPE_M60 || WeaponType == WEAPONTYPE_MINIGUN\n\t\t\t\t\t\t|| WeaponType == WEAPONTYPE_FLAMETHROWER) {\n\t\t\t\t\t\tDrawCrossHairPC = 1;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (DrawCrossHair || DrawCrossHairPC) {\n\t\t\tRwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void *)rwFILTERLINEAR);\n\n\t\t\tSpriteBrightness = Min(SpriteBrightness+1, 30);\n\n\t\t\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);\n\n\t\t\tfloat fStep = Sin((CTimer::GetTimeInMilliseconds() & 1023)/1024.0f * 6.28f);\n\t\t\tfloat fMultBright = SpriteBrightness * 0.03f * (0.25f * fStep + 0.75f);\n\t\t\tCRect rect;\n\t\t\tif (DrawCrossHairPC && TheCamera.Cams[TheCamera.ActiveCam].Using3rdPersonMouseCam()) {\n\t\t\t\tfloat f3rdX = SCREEN_WIDTH * TheCamera.m_f3rdPersonCHairMultX;\n\t\t\t\tfloat f3rdY = SCREEN_HEIGHT * TheCamera.m_f3rdPersonCHairMultY;\n#ifdef ASPECT_RATIO_SCALE\n\t\t\t\tf3rdY -= SCREEN_SCALE_Y(2.0f);\n#endif\n\t\t\t\tif (playerPed && (WeaponType == WEAPONTYPE_M4 || WeaponType == WEAPONTYPE_RUGER || WeaponType == WEAPONTYPE_M60)) {\n\t\t\t\t\trect.left = f3rdX - SCREEN_SCALE_X(32.0f * 0.6f);\n\t\t\t\t\trect.top = f3rdY - SCREEN_SCALE_Y(32.0f  * 0.6f);\n\t\t\t\t\trect.right = f3rdX + SCREEN_SCALE_X(32.0f * 0.6f);\n\t\t\t\t\trect.bottom = f3rdY + SCREEN_SCALE_Y(32.0f  * 0.6f);\n\n\t\t\t\t\tSprites[HUD_SITEM16].Draw(CRect(rect), CRGBA(255, 255, 255, 255),\n\t\t\t\t\t\t0.0f, 0.0f,  1.0f, 0.0f,  0.0f, 1.0f,  1.0f, 1.0f);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\trect.left = f3rdX - SCREEN_SCALE_X(32.0f * 0.4f);\n\t\t\t\t\trect.top = f3rdY - SCREEN_SCALE_Y(32.0f  * 0.4f);\n\t\t\t\t\trect.right = f3rdX + SCREEN_SCALE_X(32.0f * 0.4f);\n\t\t\t\t\trect.bottom = f3rdY + SCREEN_SCALE_Y(32.0f  * 0.4f);\n\n\t\t\t\t\tSprites[HUD_SITEM16].Draw(CRect(rect), CRGBA(255, 255, 255, 255),\n\t\t\t\t\t\t0.0f, 0.0f,  1.0f, 0.0f,  0.0f, 1.0f,  1.0f, 1.0f);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (Mode == CCam::MODE_M16_1STPERSON ||\n\t\t\t\t    Mode == CCam::MODE_M16_1STPERSON_RUNABOUT ||\n\t\t\t\t    Mode == CCam::MODE_HELICANNON_1STPERSON) {\n\t\t\t\t\trect.left = (SCREEN_WIDTH / 2) - SCREEN_SCALE_X(32.0f);\n\t\t\t\t\trect.top = (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(32.0f);\n\t\t\t\t\trect.right = (SCREEN_WIDTH / 2) + SCREEN_SCALE_X(32.0f);\n\t\t\t\t\trect.bottom = (SCREEN_HEIGHT / 2) + SCREEN_SCALE_Y(32.0f);\n\t\t\t\t\tSprites[HUD_SITEM16].Draw(CRect(rect), CRGBA(255, 255, 255, 255),\n\t\t\t\t\t\t0.0f, 0.0f,  1.0f, 0.0f,  0.0f, 1.0f,  1.0f, 1.0f);\n\t\t\t\t}\n\t\t\t\telse if (Mode == CCam::MODE_1STPERSON_RUNABOUT) {\n\t\t\t\t\trect.left = (SCREEN_WIDTH / 2) - SCREEN_SCALE_X(32.0f * 0.7f);\n\t\t\t\t\trect.top = (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(32.0f * 0.7f);\n\t\t\t\t\trect.right = (SCREEN_WIDTH / 2) + SCREEN_SCALE_X(32.0f * 0.7f);\n\t\t\t\t\trect.bottom = (SCREEN_HEIGHT / 2) + SCREEN_SCALE_Y(32.0f * 0.7f);\n\n\t\t\t\t\tSprites[HUD_SITEM16].Draw(CRect(rect), CRGBA(255, 255, 255, 255),\n\t\t\t\t\t\t0.0f, 0.0f,  1.0f, 0.0f,  0.0f, 1.0f,  1.0f, 1.0f);\n\t\t\t\t}\n\t\t\t\telse if (Mode == CCam::MODE_ROCKETLAUNCHER || Mode == CCam::MODE_ROCKETLAUNCHER_RUNABOUT) {\n\t\t\t\t\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)TRUE);\n\t\t\t\t\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDONE);\n\t\t\t\t\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDONE);\n\t\t\t\t\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);\n\t\t\t\t\tRwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE);\n\t\t\t\t\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpRocketSightTex));\n\n\t\t\t\t\tCSprite::RenderOneXLUSprite(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, 1.0f, SCREEN_SCALE_X(40.0f), SCREEN_SCALE_Y(40.0f), (100.0f * fMultBright), (200.0f * fMultBright), (100.0f * fMultBright), 255, 1.0f, 255);\n\t\t\t\t\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);\n\t\t\t\t\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tint sprite = HUD_SITESNIPER;\n\t\t\t\t\tfloat xOffset = SCREEN_SCALE_X(210.0f);\n\t\t\t\t\tfloat yOffset = SCREEN_SCALE_Y(210.0f);\n\n\t\t\t\t\tif (FindPlayerPed()->GetWeapon()->m_eWeaponType == WEAPONTYPE_LASERSCOPE)\n\t\t\t\t\t  sprite = HUD_SITELASER;\n\n\t\t\t\t\tif (FindPlayerPed()->GetWeapon()->m_eWeaponType == WEAPONTYPE_CAMERA) {\n\t\t\t\t\t\tsprite = HUD_VIEWFINDER;\n\t\t\t\t\t\tCrossHairHidesHud = true;\n\t\t\t\t\t\txOffset = SCREEN_SCALE_X(256.0f);\n\t\t\t\t\t\tyOffset = SCREEN_SCALE_Y(192.0f);\n\t\t\t\t\t}\n\n\t\t\t\t\trect.left = SCREEN_WIDTH/2 - xOffset;\n\t\t\t\t\trect.top = SCREEN_HEIGHT/2 - yOffset;\n\t\t\t\t\trect.right = SCREEN_WIDTH/2;\n\t\t\t\t\trect.bottom = SCREEN_HEIGHT/2;\n\t\t\t\t\tSprites[sprite].Draw(CRect(rect), CRGBA(255, 255, 255, 255),\n\t\t\t\t\t\t0.01f, 0.01f,  1.0f, 0.0f,  0.01f, 1.0f,  1.0f, 1.0f);\n\n\t\t\t\t\trect.left = SCREEN_WIDTH/2;\n\t\t\t\t\trect.top = SCREEN_HEIGHT/2 - yOffset;\n\t\t\t\t\trect.right = SCREEN_WIDTH/2 + xOffset;\n\t\t\t\t\trect.bottom = SCREEN_HEIGHT/2;\n\t\t\t\t\tSprites[sprite].Draw(CRect(rect), CRGBA(255, 255, 255, 255),\n\t\t\t\t\t\t0.99f, 0.0f,  0.01f, 0.01f,  0.99f, 1.0f,  0.01f, 1.0f);\n\n\t\t\t\t\trect.left = SCREEN_WIDTH/2 - xOffset;\n\t\t\t\t\trect.top = SCREEN_HEIGHT/2;\n\t\t\t\t\trect.right = SCREEN_WIDTH/2;\n\t\t\t\t\trect.bottom = SCREEN_HEIGHT/2 + yOffset;\n\t\t\t\t\tSprites[sprite].Draw(CRect(rect), CRGBA(255, 255, 255, 255),\n\t\t\t\t\t\t0.01f, 0.99f,  1.0f, 0.99f,  0.01f, 0.01f,  1.0f, 0.01f);\n\n\t\t\t\t\trect.left = SCREEN_WIDTH/2;\n\t\t\t\t\trect.top = SCREEN_HEIGHT/2;\n\t\t\t\t\trect.right = SCREEN_WIDTH/2 + xOffset;\n\t\t\t\t\trect.bottom = SCREEN_HEIGHT/2 + yOffset;\n\t\t\t\t\tSprites[sprite].Draw(CRect(rect), CRGBA(255, 255, 255, 255),\n\t\t\t\t\t\t0.99f, 0.99f,  0.01f, 0.99f,  0.99f, 0.01f,  0.01f, 0.01f);\n\n\t\t\t\t\tCVector dotPos;\n\t\t\t\t\tfloat size = 25.0f;\n\t\t\t\t\tif (FindPlayerPed()->GetWeapon()->m_eWeaponType == WEAPONTYPE_LASERSCOPE && FindPlayerPed()->GetWeapon()->LaserScopeDot(&dotPos, &size)) {\n\t\t\t\t\t\tRwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE);\n\t\t\t\t\t\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);\n\t\t\t\t\t\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);\n\t\t\t\t\t\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);\n#ifdef FIX_BUGS\n\t\t\t\t\t\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);\n#else\n\t\t\t\t\t\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVDESTALPHA);\n#endif\n\t\t\t\t\t\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpLaserDotTex));\n#ifdef FIX_BUGS\n\t\t\t\t\t\tint intensity = CGeneral::GetRandomNumberInRange(0, 37);\n#else\n\t\t\t\t\t\tint intensity = CGeneral::GetRandomNumberInRange(0, 35);\n#endif\n\t\t\t\t\t\tCSprite::RenderOneXLUSprite(dotPos.x, dotPos.y, dotPos.z,\n\t\t\t\t\t\t\tSCREEN_SCALE_X(size), SCREEN_SCALE_Y(size), intensity - 36, 0, 0, intensity - 36, 1.0f, 127);\n\n\t\t\t\t\t\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDSRCALPHA);\n\t\t\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDINVSRCALPHA);\n\t\t\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);\n\t\t}\n\t\telse {\n\t\t\tSpriteBrightness = 0;\n\t\t}\n\n\t\tif (CrossHairHidesHud)\n\t\t\treturn;\n\n\t\t/*\n\t\t\tDrawMoneyCounter\n\t\t*/\n\n\t\twchar sPrint[16];\n\t\twchar sPrintIcon[16];\n\t\tchar sTemp[16];\n\t\tfloat alpha;\n\n\t\tif (m_LastDisplayScore == CWorld::Players[CWorld::PlayerInFocus].m_nVisibleMoney) {\n\t\t\talpha = DrawFadeState(HUD_SCORE_FADING, 0);\n\t\t} else {\n\t\t\talpha = DrawFadeState(HUD_SCORE_FADING, 1);\n\t\t\tm_LastDisplayScore = CWorld::Players[CWorld::PlayerInFocus].m_nVisibleMoney;\n\t\t}\n\t\tif (m_DisplayScoreState != FADED_OUT) {\n\t\t\tsprintf(sTemp, \"$%08d\", CWorld::Players[CWorld::PlayerInFocus].m_nVisibleMoney);\n\t\t\tAsciiToUnicode(sTemp, sPrint);\n\n\t\t\tCFont::SetPropOff();\n\t\t\tCFont::SetBackgroundOff();\n\t\t\tCFont::SetScale(SCREEN_SCALE_X(HUD_TEXT_SCALE_X), SCREEN_SCALE_Y(HUD_TEXT_SCALE_Y));\n\t\t\tCFont::SetCentreOff();\n\t\t\tCFont::SetRightJustifyOn();\n\t\t\tCFont::SetRightJustifyWrap(0.0f);\n\t\t\tCFont::SetBackGroundOnlyTextOff();\n\t\t\tCFont::SetFontStyle(FONT_HEADING);\n\t\t\tCFont::SetPropOff();\n\t\t\tCFont::SetDropShadowPosition(2);\n\t\t\tCFont::SetDropColor(CRGBA(0, 0, 0, alpha));\n\t\t\tMONEY_COLOR.a = alpha;\n\t\t\tCFont::SetColor(MONEY_COLOR);\n\n\t\t\tif (FrontEndMenuManager.m_PrefsShowHud) {\n\t\t\t\tCFont::PrintString(SCREEN_SCALE_FROM_RIGHT(110.0f), SCREEN_SCALE_Y(43.0f), sPrint);\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t\tDrawAmmo\n\t\t*/\n\t\tif (m_LastWeapon == playerPed->GetWeapon()->m_eWeaponType) {\n\t\t\talpha = CHud::DrawFadeState(HUD_WEAPON_FADING, 0);\n\t\t} else {\n\t\t\talpha = CHud::DrawFadeState(HUD_WEAPON_FADING, 1);\n\t\t\tm_LastWeapon = playerPed->GetWeapon()->m_eWeaponType;\n\t\t}\n\t\tif (m_WeaponState != FADED_OUT) {\n\t\t\tCWeapon *weapon = playerPed->GetWeapon();\n\t\t\tint32 AmmoAmount = CWeaponInfo::GetWeaponInfo((eWeaponType)WeaponType)->m_nAmountofAmmunition;\n\t\t\tint32 AmmoInClip = weapon->m_nAmmoInClip;\n\t\t\tint32 TotalAmmo = weapon->m_nAmmoTotal;\n\t\t\tint32 Ammo, Clip;\n\n\t\t\tif (AmmoAmount <= 1 || AmmoAmount >= 1000)\n\t\t\t\tsprintf(sTemp, \"%d\", TotalAmmo);\n\t\t\telse {\n\t\t\t\tif (WeaponType == WEAPONTYPE_FLAMETHROWER) {\n\t\t\t\t\tClip = AmmoInClip / 10;\n\n\t\t\t\t\tAmmo = Min((TotalAmmo - AmmoInClip) / 10, 9999);\n\t\t\t\t} else {\n\t\t\t\t\tClip = AmmoInClip;\n\n\t\t\t\t\tAmmo = Min(TotalAmmo - AmmoInClip, 9999);\n\t\t\t\t}\n\n\t\t\t\tsprintf(sTemp, \"%d-%d\", Ammo, Clip);\n\t\t\t}\n\n\t\t\tAsciiToUnicode(sTemp, sPrint);\n\t\t\tCWeaponInfo *weaponInfo = CWeaponInfo::GetWeaponInfo((eWeaponType)WeaponType);\n\t\t\t/*\n\t\t\t\tDrawWeaponIcon\n\t\t\t*/\n\n\t\t\tif (FrontEndMenuManager.m_PrefsShowHud) {\n\t\t\t\tif (weaponInfo->m_nModelId <= 0) {\n\t\t\t\t\tRwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR);\n\t\t\t\t\tif (FrontEndMenuManager.m_PrefsShowHud)\n\t\t\t\t\t\tSprites[WeaponType].Draw(\n\t\t\t\t\t\t\tCRect(SCREEN_SCALE_FROM_RIGHT(99.0f), SCREEN_SCALE_Y(27.0f), SCREEN_SCALE_FROM_RIGHT(35.0f), SCREEN_SCALE_Y(91.0f)),\n\t\t\t\t\t\t\tCRGBA(255, 255, 255, alpha),\n\t\t\t\t\t\t\t0.015f, 0.015f,\n\t\t\t\t\t\t\t1.0f, 0.0f,\n\t\t\t\t\t\t\t0.015f, 1.0f,\n\t\t\t\t\t\t\t1.0f, 1.0f);\n\t\t\t\t} else {\n\t\t\t\t\tCBaseModelInfo *weaponModel = CModelInfo::GetModelInfo(weaponInfo->m_nModelId);\n\t\t\t\t\tRwTexDictionary *weaponTxd = CTxdStore::GetSlot(weaponModel->GetTxdSlot())->texDict;\n\t\t\t\t\tif (weaponTxd) {\n\t\t\t\t\t\tRwTexture *weaponIcon = RwTexDictionaryFindNamedTexture(weaponTxd, weaponModel->GetModelName());\n\t\t\t\t\t\tif (weaponIcon) {\n\t\t\t\t\t\t\tRwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR);\n#ifndef FIX_BUGS\n\t\t\t\t\t\t\tconst float xSize = SCREEN_SCALE_X(64.0f / 2.0f);\n\t\t\t\t\t\t\tconst float ySize = SCREEN_SCALE_Y(64.0f / 2.0f);\n\t\t\t\t\t\t\tRwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE);\n\t\t\t\t\t\t\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(weaponIcon));\n\t\t\t\t\t\t\tCSprite::RenderOneXLUSprite(SCREEN_SCALE_FROM_RIGHT(99.0f) + xSize, SCREEN_SCALE_Y(25.0f) + ySize, 1.0f, xSize, ySize,\n\t\t\t\t\t\t\t\t255, 255, 255, 255, 1.0f, 255);\n\t\t\t\t\t\t\tRwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);\n#else\n\t\t\t\t\t\t\tstatic CSprite2d sprite;\n\t\t\t\t\t\t\tsprite.m_pTexture = weaponIcon;\n\t\t\t\t\t\t\tsprite.Draw(\n\t\t\t\t\t\t\t\tCRect(SCREEN_SCALE_FROM_RIGHT(99.0f), SCREEN_SCALE_Y(27.0f), SCREEN_SCALE_FROM_RIGHT(35.0f), SCREEN_SCALE_Y(91.0f)),\n\t\t\t\t\t\t\t\tCRGBA(255, 255, 255, alpha),\n\t\t\t\t\t\t\t\t0.015f, 0.015f,\n\t\t\t\t\t\t\t\t1.0f, 0.0f,\n\t\t\t\t\t\t\t\t0.015f, 1.0f,\n\t\t\t\t\t\t\t\t1.0f, 1.0f);\n\t\t\t\t\t\t\tsprite.m_pTexture = nil;\n#endif\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tCFont::SetBackgroundOff();\n\t\t\t\tCFont::SetScale(SCREEN_SCALE_X(0.5f), SCREEN_SCALE_Y(0.8f));\n\t\t\t\tCFont::SetJustifyOff();\n\t\t\t\tCFont::SetCentreOn();\n\t\t\t\tCFont::SetCentreSize(SCREEN_STRETCH_X(DEFAULT_SCREEN_WIDTH));\n\t\t\t\tCFont::SetPropOn();\n\t\t\t\tCFont::SetDropShadowPosition(0);\n\t\t\t\tCFont::SetFontStyle(FONT_STANDARD);\n\n\t\t\t\tif (Min(9999, TotalAmmo - AmmoInClip) != 9999 && !CDarkel::FrenzyOnGoing() && weaponInfo->m_nWeaponSlot > 1 && weapon->m_eWeaponType != WEAPONTYPE_DETONATOR) {\n\t\t\t\t\tCFont::SetDropShadowPosition(2);\n\t\t\t\t\tCFont::SetDropColor(CRGBA(0, 0, 0, alpha));\n\t\t\t\t\tAMMO_COLOR.a = alpha;\n\t\t\t\t\tCFont::SetColor(AMMO_COLOR);\n\t\t\t\t\tif (FrontEndMenuManager.m_PrefsShowHud)\n\t\t\t\t\t\tCFont::PrintString(SCREEN_SCALE_FROM_RIGHT(66.0f), SCREEN_SCALE_Y(90.0f), sPrint);\n\t\t\t\t\tCFont::SetDropShadowPosition(0);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t\tDrawHealth\n\t\t*/\n\t\tif ( m_LastTimeEnergyLost == CWorld::Players[CWorld::PlayerInFocus].m_nTimeLastHealthLoss ) {\n\t\t\tCHud::DrawFadeState(HUD_ENERGY_FADING, 0);\n\t\t} else {\n\t\t\tCHud::DrawFadeState(HUD_ENERGY_FADING, 1);\n\t\t\tm_LastTimeEnergyLost = CWorld::Players[CWorld::PlayerInFocus].m_nTimeLastHealthLoss;\n\t\t}\n\n\t\tif (m_EnergyLostState != FADED_OUT) {\n\t\t\tCFont::SetBackgroundOff();\n\t\t\tCFont::SetScale(SCREEN_SCALE_X(HUD_TEXT_SCALE_X), SCREEN_SCALE_Y(HUD_TEXT_SCALE_Y));\n\t\t\tCFont::SetJustifyOff();\n\t\t\tCFont::SetCentreOff();\n\t\t\tCFont::SetRightJustifyWrap(0.0f);\n\t\t\tCFont::SetRightJustifyOn();\n\t\t\tCFont::SetPropOff();\n\t\t\tCFont::SetFontStyle(FONT_HEADING);\n\t\t\tCFont::SetDropShadowPosition(2);\n\t\t\tCFont::SetDropColor(CRGBA(0, 0, 0, 255));\n\n\t\t\tif (m_ItemToFlash == ITEM_HEALTH && CTimer::GetFrameCounter() & 8\n\t\t\t\t|| m_ItemToFlash != ITEM_HEALTH\n\t\t\t\t|| playerPed->m_fHealth < 10\n\t\t\t\t&& CTimer::GetFrameCounter() & 8) {\n\t\t\t\tif (playerPed->m_fHealth >= 10\n\t\t\t\t\t|| playerPed->m_fHealth < 10 && CTimer::GetFrameCounter() & 8) {\n\n\t\t\t\t\tAsciiToUnicode(\"{\", sPrintIcon);\n#ifdef FIX_BUGS\n\t\t\t\t\tsprintf(sTemp, \"%03d\", int32(playerPed->m_fHealth + 0.5f));\n#else\n\t\t\t\t\tsprintf(sTemp, \"%03d\", (int32)playerPed->m_fHealth);\n#endif\n\t\t\t\t\tAsciiToUnicode(sTemp, sPrint);\n\n\t\t\t\t\tCFont::SetColor(HEALTH_COLOR);\n\t\t\t\t\tif (FrontEndMenuManager.m_PrefsShowHud) {\n\t\t\t\t\t\tCFont::PrintString(SCREEN_SCALE_FROM_RIGHT(110.0f), SCREEN_SCALE_Y(65.0f), sPrint);\n\n\t\t\t\t\t\tif (!CWorld::Players[CWorld::PlayerInFocus].m_nTimeLastHealthLoss || CTimer::GetTimeInMilliseconds() > CWorld::Players[CWorld::PlayerInFocus].m_nTimeLastHealthLoss + 2000 || CTimer::GetFrameCounter() & 4) {\n\t\t\t\t\t\t\t// CFont::SetColor(HEALTH_COLOR);\n\t\t\t\t\t\t\tCFont::PrintString(SCREEN_SCALE_FROM_RIGHT(110.0f + 54.0f), SCREEN_SCALE_Y(65.0f), sPrintIcon);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t\tDrawArmour\n\t\t\t*/\n\t\t\tif (m_ItemToFlash == ITEM_ARMOUR && CTimer::GetFrameCounter() & 8 || m_ItemToFlash != ITEM_ARMOUR) {\n\t\t\t\tCFont::SetScale(SCREEN_SCALE_X(HUD_TEXT_SCALE_X), SCREEN_SCALE_Y(HUD_TEXT_SCALE_Y));\n\t\t\t\tif (playerPed->m_fArmour > 1.0f) {\n\t\t\t\t\tAsciiToUnicode(\"<\", sPrintIcon);\n#ifdef FIX_BUGS\n\t\t\t\t\tsprintf(sTemp, \"%03d\", int32(playerPed->m_fArmour + 0.5f));\n#else\n\t\t\t\t\tsprintf(sTemp, \"%03d\", (int32)playerPed->m_fArmour);\n#endif\n\t\t\t\t\tAsciiToUnicode(sTemp, sPrint);\n\n\t\t\t\t\tCFont::SetColor(ARMOUR_COLOR);\n\t\t\t\t\tif (FrontEndMenuManager.m_PrefsShowHud) {\n\n\t\t\t\t\t\tCFont::PrintString(SCREEN_SCALE_FROM_RIGHT(182.0f), SCREEN_SCALE_Y(65.0f), sPrint);\n\n\t\t\t\t\t\tif (!CWorld::Players[CWorld::PlayerInFocus].m_nTimeLastArmourLoss || CTimer::GetTimeInMilliseconds() > CWorld::Players[CWorld::PlayerInFocus].m_nTimeLastArmourLoss + 2000 || CTimer::GetFrameCounter() & 4) {\n\t\t\t\t\t\t\t// CFont::SetColor(ARMOUR_COLOR);\n\t\t\t\t\t\t\tCFont::PrintString(SCREEN_SCALE_FROM_RIGHT(182.0f + 52.0f), SCREEN_SCALE_Y(65.0f), sPrintIcon);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t\tDrawWantedLevel\n\t\t*/\n\t\tif (m_LastWanted == playerPed->m_pWanted->GetWantedLevel()) {\n\t\t\talpha = DrawFadeState(HUD_WANTED_FADING, 0);\n\t\t} else {\n\t\t\talpha = DrawFadeState(HUD_WANTED_FADING, 1);\n\t\t\tm_LastWanted = playerPed->m_pWanted->GetWantedLevel();\n\t\t}\n\n\t\tif (m_WantedState != FADED_OUT) {\n\t\t\tCFont::SetBackgroundOff();\n\t\t\tCFont::SetScale(SCREEN_SCALE_X(HUD_TEXT_SCALE_X), SCREEN_SCALE_Y(HUD_TEXT_SCALE_Y));\n\t\t\tCFont::SetJustifyOff();\n\t\t\tCFont::SetCentreOff();\n\t\t\tCFont::SetRightJustifyOn();\n\t\t\tCFont::SetPropOn();\n\t\t\tCFont::SetFontStyle(FONT_STANDARD);\n\n\t\t\tAsciiToUnicode(\">\", sPrintIcon);\n\n\t\t\tfor (int i = 0; i < 6; i++) {\n\t\t\t\tif (FrontEndMenuManager.m_PrefsShowHud) {\n\t\t\t\t\tif (playerPed->m_pWanted->GetWantedLevel() > i\n\t\t\t\t\t\t&& (CTimer::GetTimeInMilliseconds() > playerPed->m_pWanted->m_nLastWantedLevelChange\n\t\t\t\t\t\t\t+ 2000 || CTimer::GetFrameCounter() & 4)) {\n\n\t\t\t\t\t\tWANTED_COLOR.a = alpha;\n\t\t\t\t\t\tCFont::SetColor(WANTED_COLOR);\n\t\t\t\t\t\tCFont::PrintString(SCREEN_SCALE_FROM_RIGHT(110.0f + 23.0f * i), SCREEN_SCALE_Y(87.0f), sPrintIcon);\n\n\t\t\t\t\t} else if (playerPed->m_pWanted->m_nMinWantedLevel > i && CTimer::GetFrameCounter() & 4) {\n\t\t\t\t\t\tWANTED_COLOR_FLASH.a = alpha;\n\t\t\t\t\t\tCFont::SetColor(WANTED_COLOR_FLASH);\n\t\t\t\t\t\tCFont::PrintString(SCREEN_SCALE_FROM_RIGHT(110.0f + 23.0f * i), SCREEN_SCALE_Y(87.0f), sPrintIcon);\n\n\t\t\t\t\t} else if (playerPed->m_pWanted->GetWantedLevel() <= i) {\n\t\t\t\t\t\tNOTWANTED_COLOR.a = alpha;\n\t\t\t\t\t\tCFont::SetColor(NOTWANTED_COLOR);\n\t\t\t\t\t\tCFont::PrintString(SCREEN_SCALE_FROM_RIGHT(110.0f + 23.0f * i), SCREEN_SCALE_Y(87.0f), sPrintIcon);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tstatic int32 nMediaLevelCounter = 0;\n\t\tif (CStats::ShowChaseStatOnScreen != 0) {\n\t\t\tfloat fCurAttentionLevel = CWorld::Players[CWorld::PlayerInFocus].m_fMediaAttention;\n\t\t\tif (0.7f * CStats::HighestChaseValue > fCurAttentionLevel\n\t\t\t\t|| fCurAttentionLevel <= 40.0f || CTheScripts::IsPlayerOnAMission()) {\n\t\t\t\tnMediaLevelCounter = 0;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tif (fCurAttentionLevel == CStats::HighestChaseValue) {\n\t\t\t\t\tsprintf(gString, \"%s %d\", UnicodeToAscii(TheText.Get(\"CHSE\")), (int32)fCurAttentionLevel);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tsprintf(gString, \"%s %d\" \"-%d-\", UnicodeToAscii(TheText.Get(\"CHSE\")), (int32)fCurAttentionLevel, (int32)CStats::HighestChaseValue);\n\t\t\t\t}\n\t\t\t\tAsciiToUnicode(gString, gUString);\n\t\t\t\tCFont::SetBackgroundOff();\n\t\t\t\tCFont::SetScale(SCREEN_SCALE_X(HUD_TEXT_SCALE_X), SCREEN_SCALE_Y(HUD_TEXT_SCALE_Y));\n\t\t\t\tCFont::SetCentreOff();\n\t\t\t\tCFont::SetRightJustifyOn();\n\t\t\t\tCFont::SetRightJustifyWrap(0.0f);\n\t\t\t\tCFont::SetBackGroundOnlyTextOff();\n\t\t\t\tCFont::SetFontStyle(FONT_HEADING);\n\t\t\t\tCFont::SetPropOff();\n\t\t\t\tCFont::SetDropShadowPosition(2);\n\t\t\t\tCFont::SetDropColor(CRGBA(0, 0, 0, 255));\n\n\t\t\t\tCRGBA colour;\n\t\t\t\tif (CTimer::GetTimeInMilliseconds() & 0x200)\n\t\t\t\t\tcolour = CRGBA(204, 0, 185, 180);\n\t\t\t\telse\n\t\t\t\t\tcolour = CRGBA(178, 0, 162, 180);\n\t\t\t\tCFont::SetColor(colour);\n\t\t\t\tCFont::PrintString(SCREEN_SCALE_FROM_RIGHT(110.0f), SCREEN_SCALE_Y(113.0f), gUString);\n\t\t\t\t\n\t\t\t\tif (CStats::FindChaseString(fCurAttentionLevel) != prevChaseString) {\n\t\t\t\t\tprevChaseString = CStats::FindChaseString(fCurAttentionLevel);\n\t\t\t\t\tnMediaLevelCounter = 100;\n\t\t\t\t}\n\n\t\t\t\tif (nMediaLevelCounter != 0) {\n\t\t\t\t\tnMediaLevelCounter--;\n\t\t\t\t\tUnicodeMakeUpperCase(gUString, CStats::FindChaseString(fCurAttentionLevel));\n\t\t\t\t\tCFont::PrintString(SCREEN_SCALE_FROM_RIGHT(110.0f), SCREEN_SCALE_Y(138.0f), gUString);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t\tDrawZoneName\n\t\t*/\n\t\tif (m_pZoneName) {\n\n\t\t\tif (m_pZoneName != m_pLastZoneName) {\n\t\t\t\tswitch (m_ZoneState) {\n\t\t\t\tcase 0:\n\t\t\t\t\tm_ZoneState = 2;\n\t\t\t\t\tm_ZoneToPrint = m_pZoneName;\n\t\t\t\t\tm_ZoneNameTimer = 0;\n\t\t\t\t\tm_ZoneFadeTimer = 0;\n\t\t\t\t\tif (m_VehicleState == 1 || m_VehicleState == 2)\n\t\t\t\t\t\tm_VehicleState = 3;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 1:\n\t\t\t\tcase 2:\n\t\t\t\tcase 3:\n\t\t\t\tcase 4:\n\t\t\t\t\tm_ZoneNameTimer = 5;\n\t\t\t\t\tm_ZoneState = 4;\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tm_pLastZoneName = m_pZoneName;\n\t\t\t}\n\n\t\t\tfloat fZoneAlpha = 255.0f;\n\t\t\tif (m_ZoneState) {\n\t\t\t\tswitch (m_ZoneState) {\n\t\t\t\tcase 1:\n\t\t\t\t\tfZoneAlpha = 255.0f;\n\t\t\t\t\tm_ZoneFadeTimer = 1000;\n\t\t\t\t\tif (m_ZoneNameTimer > 10000.0f) {\n\t\t\t\t\t\tm_ZoneFadeTimer = 1000;\n\t\t\t\t\t\tm_ZoneState = 3;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase 2:\n\t\t\t\t\tm_ZoneFadeTimer += CTimer::GetTimeStepInMilliseconds();\n\t\t\t\t\tif (m_ZoneFadeTimer > 1000.0f) {\n\t\t\t\t\t\tm_ZoneState = 1;\n\t\t\t\t\t\tm_ZoneFadeTimer = 1000;\n\t\t\t\t\t}\n\t\t\t\t\tfZoneAlpha = m_ZoneFadeTimer * 0.001f * 255.0f;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 3:\n\t\t\t\t\tm_ZoneFadeTimer -= CTimer::GetTimeStepInMilliseconds();\n\t\t\t\t\tif (m_ZoneFadeTimer < 0.0f) {\n\t\t\t\t\t\tm_ZoneState = 0;\n\t\t\t\t\t\tm_ZoneFadeTimer = 0;\n\t\t\t\t\t}\n\t\t\t\t\tfZoneAlpha = m_ZoneFadeTimer * 0.001f * 255.0f;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 4:\n\t\t\t\t\tm_ZoneFadeTimer -= CTimer::GetTimeStepInMilliseconds();\n\t\t\t\t\tif (m_ZoneFadeTimer < 0.0f) {\n\t\t\t\t\t\tm_ZoneFadeTimer = 0;\n\t\t\t\t\t\tm_ZoneToPrint = m_pLastZoneName;\n\t\t\t\t\t\tm_ZoneState = 2;\n\t\t\t\t\t}\n\t\t\t\t\tfZoneAlpha = m_ZoneFadeTimer * 0.001f * 255.0f;\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\n\t\t\t\t}\n\n\t\t\t\tif (!m_Message[0] && BigMessageInUse[1] == 0.0f && BigMessageInUse[2] == 0.0f) {\n\n\t\t\t\t\tm_ZoneNameTimer += CTimer::GetTimeStepInMilliseconds();\n\t\t\t\t\tCFont::SetJustifyOff();\n\t\t\t\t\tCFont::SetPropOn();\n\t\t\t\t\tCFont::SetBackgroundOff();\n\n\t\t\t\t\tif (FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_SPANISH)\n\t\t\t\t\t\tCFont::SetScale(SCREEN_SCALE_X(1.7f * 0.8f), SCREEN_SCALE_Y(1.8f));\n\t\t\t\t\telse\n\t\t\t\t\t\tCFont::SetScale(SCREEN_SCALE_X(1.7f), SCREEN_SCALE_Y(1.8f));\n\n\t\t\t\t\tCFont::SetSlantRefPoint(SCREEN_SCALE_FROM_RIGHT(32.0f), SCREEN_SCALE_FROM_BOTTOM(128.0f));\n\t\t\t\t\tCFont::SetSlant(0.15f);\n\n\t\t\t\t\tCFont::SetRightJustifyOn();\n\t\t\t\t\tCFont::SetRightJustifyWrap(0.0f);\n\t\t\t\t\tCFont::SetBackGroundOnlyTextOff();\n\t\t\t\t\tCFont::SetDropShadowPosition(2);\n\t\t\t\t\tCFont::SetDropColor(CRGBA(0, 0, 0, fZoneAlpha));\n\t\t\t\t\tCFont::SetFontStyle(FONT_BANK);\n\t\t\t\t\tCFont::SetColor(CRGBA(ZONE_COLOR.r, ZONE_COLOR.g, ZONE_COLOR.b, fZoneAlpha));\n\n\t\t\t\t\tif (!CTheScripts::bPlayerIsInTheStatium)\n\t\t\t\t\t\tCFont::PrintStringFromBottom(SCREEN_SCALE_FROM_RIGHT(32.0f), SCREEN_SCALE_FROM_BOTTOM(128.0f), m_ZoneToPrint);\n\n\t\t\t\t\tCFont::SetSlant(0.f);\n\t\t\t\t} else {\n\t\t\t\t\tm_ZoneState = 3;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t\tDrawVehicleName\n\t\t*/\n\t\tif (m_VehicleName) {\n\t\t\tfloat fVehicleAlpha = 0.0f;\n\n\t\t\tif (m_VehicleName != m_pLastVehicleName) {\n\t\t\t\tswitch (m_VehicleState) {\n\t\t\t\tcase 0:\n\t\t\t\t\tm_VehicleState = 2;\n\t\t\t\t\tm_pVehicleNameToPrint = m_VehicleName;\n\t\t\t\t\tm_VehicleNameTimer = 0;\n\t\t\t\t\tm_VehicleFadeTimer = 0;\n\t\t\t\t\tif (m_ZoneState == 1 || m_ZoneState == 2)\n\t\t\t\t\t\tm_ZoneState = 3;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 1:\n\t\t\t\tcase 2:\n\t\t\t\tcase 3:\n\t\t\t\tcase 4:\n\t\t\t\t\tm_VehicleNameTimer = 0;\n\t\t\t\t\tm_VehicleState = 4;\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tm_pLastVehicleName = m_VehicleName;\n\t\t\t}\n\n\t\t\tif (m_VehicleState) {\n\t\t\t\tswitch (m_VehicleState) {\n\t\t\t\tcase 1:\n\t\t\t\t\tif (m_VehicleNameTimer > 10000) {\n\t\t\t\t\t\tm_VehicleFadeTimer = 1000;\n\t\t\t\t\t\tm_VehicleState = 3;\n\t\t\t\t\t}\n\t\t\t\t\tfVehicleAlpha = 255.0f;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 2:\n\t\t\t\t\tm_VehicleFadeTimer += CTimer::GetTimeStepInMilliseconds();\n\t\t\t\t\tif (m_VehicleFadeTimer > 1000) {\n\t\t\t\t\t\tm_VehicleState = 1;\n\t\t\t\t\t\tm_VehicleFadeTimer = 1000;\n\t\t\t\t\t}\n\t\t\t\t\tfVehicleAlpha = m_VehicleFadeTimer * 0.001f * 255.0f;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 3:\n\t\t\t\t\tm_VehicleFadeTimer -= CTimer::GetTimeStepInMilliseconds();\n\t\t\t\t\tif (m_VehicleFadeTimer < 0) {\n\t\t\t\t\t\tm_VehicleState = 0;\n\t\t\t\t\t\tm_VehicleFadeTimer = 0;\n\t\t\t\t\t}\n\t\t\t\t\tfVehicleAlpha = m_VehicleFadeTimer * 0.001f * 255.0f;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 4:\n\t\t\t\t\tm_VehicleFadeTimer -= CTimer::GetTimeStepInMilliseconds();\n\t\t\t\t\tif (m_VehicleFadeTimer < 0) {\n\t\t\t\t\t\tm_VehicleFadeTimer = 0;\n\t\t\t\t\t\tm_pVehicleNameToPrint = m_pLastVehicleName;\n\t\t\t\t\t\tm_VehicleNameTimer = 0;\n\t\t\t\t\t\tm_VehicleState = 2;\n\t\t\t\t\t}\n\t\t\t\t\tfVehicleAlpha = m_VehicleFadeTimer * 0.001f * 255.0f;\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif (!m_Message[0]) {\n\t\t\t\t\tm_VehicleNameTimer += CTimer::GetTimeStepInMilliseconds();\n\t\t\t\t\tCFont::SetJustifyOff();\n\t\t\t\t\tCFont::SetPropOn();\n\t\t\t\t\tCFont::SetBackgroundOff();\n\n\t\t\t\t\tif (FrontEndMenuManager.m_PrefsLanguage != CMenuManager::LANGUAGE_ITALIAN && FrontEndMenuManager.m_PrefsLanguage != CMenuManager::LANGUAGE_SPANISH)\n\t\t\t\t\t\tCFont::SetScale(SCREEN_SCALE_X(1.7f), SCREEN_SCALE_Y(1.8f));\n\t\t\t\t\telse\n\t\t\t\t\t\tCFont::SetScale(SCREEN_SCALE_X(1.7f * 0.85f), SCREEN_SCALE_Y(1.8f));\n\n\t\t\t\t\tCFont::SetSlantRefPoint(SCREEN_SCALE_FROM_RIGHT(32.0f), SCREEN_SCALE_FROM_BOTTOM(105.0f));\n\t\t\t\t\tCFont::SetSlant(0.15f);\n\n\t\t\t\t\tCFont::SetRightJustifyOn();\n\t\t\t\t\tCFont::SetRightJustifyWrap(0.0f);\n\t\t\t\t\tCFont::SetBackGroundOnlyTextOff();\n\t\t\t\t\tCFont::SetFontStyle(FONT_BANK);\n\t\t\t\t\tCFont::SetDropShadowPosition(2);\n\t\t\t\t\tCFont::SetColor(CRGBA(VEHICLE_COLOR.r, VEHICLE_COLOR.g, VEHICLE_COLOR.b, fVehicleAlpha));\n\t\t\t\t\tCFont::SetDropColor(CRGBA(0, 0, 0, fVehicleAlpha));\n\n\t\t\t\t\tCFont::PrintStringFromBottom(SCREEN_SCALE_FROM_RIGHT(32.0f), SCREEN_SCALE_FROM_BOTTOM(105.0f), m_pVehicleNameToPrint);\n\n\t\t\t\t\tCFont::SetSlant(0.f);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tm_pLastVehicleName = nil;\n\t\t\tm_VehicleState = 0;\n\t\t\tm_VehicleFadeTimer = 0;\n\t\t\tm_VehicleNameTimer = 0;\n\t\t}\n\n\t\t/*\n\t\t\tDrawClock\n\t\t*/\n\t\tif (m_ClockState) {\n\t\t\tCFont::SetJustifyOff();\n\t\t\tCFont::SetCentreOff();\n\t\t\tCFont::SetBackgroundOff();\n\t\t\tCFont::SetScale(SCREEN_SCALE_X(HUD_TEXT_SCALE_X), SCREEN_SCALE_Y(HUD_TEXT_SCALE_Y));\n\t\t\tCFont::SetBackGroundOnlyTextOff();\n\t\t\tCFont::SetPropOff();\n\t\t\tCFont::SetFontStyle(FONT_HEADING);\n\t\t\tCFont::SetRightJustifyOn();\n\t\t\tCFont::SetRightJustifyWrap(0.0f);\n\t\t\tCFont::SetDropShadowPosition(2);\n\t\t\tCFont::SetDropColor(CRGBA(0, 0, 0, 255));\n\n\t\t\tsprintf(sTemp, \"%02d:%02d\", CClock::GetHours(), CClock::GetMinutes());\n\t\t\tAsciiToUnicode(sTemp, sPrint);\n\n\t\t\tCFont::SetColor(CLOCK_COLOR);\n\t\t\tif (FrontEndMenuManager.m_PrefsShowHud)\n\t\t\t\tCFont::PrintString(SCREEN_SCALE_FROM_RIGHT(111.0f), SCREEN_SCALE_Y(22.0f), sPrint);\n\t\t}\n\n\t\t/*\n\t\t\tDrawOnScreenTimer\n\t\t*/\n\t\t\n\t\twchar sTimer[16];\n\n\t\tif (!CUserDisplay::OnscnTimer.m_sClocks[0].m_bClockProcessed)\n\t\t\tTimerOnLastFrame = false;\n\n\t\tfor(uint32 i = 0; i < NUMONSCREENCOUNTERS; i++) {\n\t\t\tif (!CUserDisplay::OnscnTimer.m_sCounters[0].m_bCounterProcessed)\n\t\t\t\tCounterOnLastFrame[i] = false;\n\t\t}\n\n\t\tif (CUserDisplay::OnscnTimer.m_bProcessed) {\n\t\t\tif (CUserDisplay::OnscnTimer.m_sClocks[0].m_bClockProcessed) {\n\t\t\t\tif (!TimerOnLastFrame)\n\t\t\t\t\tTimerFlashTimer = 1;\n\n\t\t\t\tTimerOnLastFrame = true;\n\n\t\t\t\tif (TimerFlashTimer != 0) {\n\t\t\t\t\tif (++TimerFlashTimer > 50)\n\t\t\t\t\t\tTimerFlashTimer = 0;\n\t\t\t\t}\n\n\t\t\t\tif (CTimer::GetFrameCounter() & 4 || TimerFlashTimer == 0) {\n\t\t\t\t\tAsciiToUnicode(CUserDisplay::OnscnTimer.m_sClocks[0].m_aClockBuffer, sTimer);\n\t\t\t\t\tCFont::SetPropOn();\n\t\t\t\t\tCFont::SetBackgroundOff();\n\t\t\t\t\tCFont::SetScale(SCREEN_SCALE_X(HUD_TEXT_SCALE_X), SCREEN_SCALE_Y(HUD_TEXT_SCALE_Y));\n\t\t\t\t\tCFont::SetRightJustifyOn();\n\t\t\t\t\tCFont::SetRightJustifyWrap(0.0f);\n\t\t\t\t\tCFont::SetFontStyle(FONT_LOCALE(FONT_HEADING));\n\t\t\t\t\tCFont::SetPropOff();\n\t\t\t\t\tCFont::SetBackGroundOnlyTextOn();\n\t\t\t\t\tCFont::SetDropShadowPosition(2);\n\t\t\t\t\tCFont::SetDropColor(CRGBA(0, 0, 0, 255));\n\t\t\t\t\tCFont::SetScale(SCREEN_SCALE_X(HUD_TEXT_SCALE_X), SCREEN_SCALE_Y(HUD_TEXT_SCALE_Y));\n\t\t\t\t\tCFont::SetColor(TIMER_COLOR);\n\t\t\t\t\tCFont::PrintString(SCREEN_SCALE_FROM_RIGHT(37.0f), SCREEN_SCALE_Y(110.0f), sTimer);\n\t\t\t\t\tCFont::SetPropOn();\n\n\t\t\t\t\tif (CUserDisplay::OnscnTimer.m_sClocks[0].m_aClockText[0]) {\n\t\t\t\t\t\tCFont::SetDropShadowPosition(2);\n\t\t\t\t\t\tCFont::SetDropColor(CRGBA(0, 0, 0, 255));\n\t\t\t\t\t\tCFont::SetColor(TIMER_COLOR);\n\t\t\t\t\t\tCFont::PrintString(SCREEN_SCALE_FROM_RIGHT(37.0f) - SCREEN_SCALE_X(80.0f), SCREEN_SCALE_Y(110.0f), TheText.Get(CUserDisplay::OnscnTimer.m_sClocks[0].m_aClockText));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor(uint32 i = 0; i < NUMONSCREENCOUNTERS; i++) {\n\t\t\t\tif (CUserDisplay::OnscnTimer.m_sCounters[i].m_bCounterProcessed) {\n\t\t\t\t\tif (!CounterOnLastFrame[i])\n\t\t\t\t\t\tCounterFlashTimer[i] = 1;\n\n\t\t\t\t\tCounterOnLastFrame[i] = true;\n\n\t\t\t\t\tif (CounterFlashTimer[i] != 0) {\n\t\t\t\t\t\tif (++CounterFlashTimer[i] > 50)\n\t\t\t\t\t\t\tCounterFlashTimer[i] = 0;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (CTimer::GetFrameCounter() & 4 || CounterFlashTimer[i] == 0) {\n\t\t\t\t\t\tif (CUserDisplay::OnscnTimer.m_sCounters[i].m_nType == COUNTER_DISPLAY_NUMBER) {\n\t\t\t\t\t\t\tAsciiToUnicode(CUserDisplay::OnscnTimer.m_sCounters[i].m_aCounterBuffer, sTimer);\n\t\t\t\t\t\t\tCFont::SetPropOn();\n\t\t\t\t\t\t\tCFont::SetBackgroundOff();\n\t\t\t\t\t\t\tCFont::SetScale(SCREEN_SCALE_X(HUD_TEXT_SCALE_X), SCREEN_SCALE_Y(HUD_TEXT_SCALE_Y));\n\t\t\t\t\t\t\tCFont::SetCentreOff();\n\t\t\t\t\t\t\tCFont::SetRightJustifyOn();\n\t\t\t\t\t\t\tCFont::SetRightJustifyWrap(0.0f);\n\t\t\t\t\t\t\tCFont::SetFontStyle(FONT_LOCALE(FONT_HEADING));\n\t\t\t\t\t\t\tCFont::SetWrapx(SCREEN_STRETCH_X(DEFAULT_SCREEN_WIDTH));\n\t\t\t\t\t\t\tCFont::SetPropOn();\n\t\t\t\t\t\t\tCFont::SetBackGroundOnlyTextOn();\n\t\t\t\t\t\t\tCFont::SetDropShadowPosition(2);\n\t\t\t\t\t\t\tCFont::SetDropColor(CRGBA(0, 0, 0, 255));\n\t\t\t\t\t\t\tCFont::SetColor(COUNTER_COLOR);\n\t\t\t\t\t\t\tCFont::PrintString(SCREEN_SCALE_FROM_RIGHT(37.0f), SCREEN_SCALE_Y(HUD_TEXT_SCALE_Y * 20.f * i) + SCREEN_SCALE_Y(132.0f), sTimer);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tint counter = atoi(CUserDisplay::OnscnTimer.m_sCounters[i].m_aCounterBuffer);\n\n\t\t\t\t\t\t\tconst float barWidth = SCREEN_SCALE_X(100.f / 2.f);\n\t\t\t\t\t\t\tconst float right = SCREEN_SCALE_FROM_RIGHT(37.0f);\n\t\t\t\t\t\t\tconst float left = right - barWidth;\n\n\t\t\t\t\t\t\tconst float barHeight = SCREEN_SCALE_Y(11.0f);\n\t\t\t\t\t\t\tconst float top = SCREEN_SCALE_Y(132.0f) + SCREEN_SCALE_Y(8.0f) + SCREEN_SCALE_Y(HUD_TEXT_SCALE_Y * 20.f * i);\n\t\t\t\t\t\t\tconst float bottom = top + barHeight;\n\n\t\t\t\t\t\t\t// shadow\n\t\t\t\t\t\t\tCSprite2d::DrawRect(CRect(left + SCREEN_SCALE_X(6.0f), top + SCREEN_SCALE_Y(2.0f), right + SCREEN_SCALE_X(6.0f), bottom + SCREEN_SCALE_Y(2.0f)), CRGBA(0, 0, 0, 255));\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tCSprite2d::DrawRect(CRect(left + SCREEN_SCALE_X(4.0f), top, right + SCREEN_SCALE_X(4.0f), bottom), CRGBA(27, 89, 130, 255));\n\t\t\t\t\t\t\tCSprite2d::DrawRect(CRect(left + SCREEN_SCALE_X(4.0f), top, left + SCREEN_SCALE_X(counter) / 2.0f + SCREEN_SCALE_X(4.0f), bottom), CRGBA(97, 194, 247, 255));\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (CUserDisplay::OnscnTimer.m_sCounters[i].m_aCounterText[0]) {\n\t\t\t\t\t\t\tCFont::SetPropOn();\n\t\t\t\t\t\t\tCFont::SetFontStyle(FONT_LOCALE(FONT_HEADING));\n\t\t\t\t\t\t\tCFont::SetScale(SCREEN_SCALE_X(HUD_TEXT_SCALE_X), SCREEN_SCALE_Y(HUD_TEXT_SCALE_Y));\n\t\t\t\t\t\t\tCFont::SetDropShadowPosition(2);\n\t\t\t\t\t\t\tCFont::SetDropColor(CRGBA(0, 0, 0, 255));\n\t\t\t\t\t\t\tCFont::SetColor(COUNTER_COLOR);\n\t\t\t\t\t\t\tCFont::PrintString(SCREEN_SCALE_FROM_RIGHT(37.0f) - SCREEN_SCALE_X(61.0f), SCREEN_SCALE_Y(HUD_TEXT_SCALE_Y * 20.f * i) + SCREEN_SCALE_Y(132.0f), TheText.Get(CUserDisplay::OnscnTimer.m_sCounters[i].m_aCounterText));\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// unused/leftover color. I wonder what was it for\n\t\t\t\t\t\tCFont::SetColor(CRGBA(244, 225, 91, 255));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t\tDrawRadar\n\t\t*/\n\t\tif (FrontEndMenuManager.m_PrefsRadarMode != 2 &&\n\t\t\t!m_HideRadar && (m_ItemToFlash == ITEM_RADAR && CTimer::GetFrameCounter() & 8 || m_ItemToFlash != ITEM_RADAR)) {\n\n\t\t\tRwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERNEAREST);\n\t\t\tCRadar::DrawMap();\n\t\t\tif (FrontEndMenuManager.m_PrefsRadarMode != 1) {\n\t\t\t\tCRect rect(0.0f, 0.0f, SCREEN_SCALE_X(RADAR_WIDTH), SCREEN_SCALE_Y(RADAR_HEIGHT));\n\t\t\t\t\n\t\t\t\trect.Translate(SCREEN_SCALE_X_FIX(RADAR_LEFT), SCREEN_SCALE_FROM_BOTTOM(RADAR_BOTTOM + RADAR_HEIGHT));\n\n#ifdef FIX_BUGS\n\t\t\t\trect.Grow(SCREEN_SCALE_X(6.0f), SCREEN_SCALE_X(6.0f), SCREEN_SCALE_Y(6.0f), SCREEN_SCALE_Y(6.0f));\n#else\n\t\t\t\trect.Grow(6.0f);\n#endif\n\t\t\t\trect.Translate(SCREEN_SCALE_X_FIX(0.0f), SCREEN_SCALE_Y_FIX(2.0f));\n\t\t\t\tSprites[HUD_RADARDISC].Draw(rect, CRGBA(0, 0, 0, 255));\n\t\t\t\trect.Translate(SCREEN_SCALE_X_FIX(0.0f), SCREEN_SCALE_Y_FIX(-2.0f));\n\t\t\t\tSprites[HUD_RADARDISC].Draw(rect, RADARDISC_COLOR);\n\t\t\t}\n\t\t\tCRadar::DrawBlips();\n\t\t}\n\t}\n\n\t/*\n\t\tDraw3dMarkers\n\t*/\n\tif (m_Wants_To_Draw_3dMarkers && !TheCamera.m_WideScreenOn && !m_BigMessage[0][0] && !m_BigMessage[2][0]) {\n\t\tCRadar::Draw3dMarkers();\n\t}\n\n\t/*\n\t\tDrawScriptText\n\t*/\n\tif (!CTimer::GetIsUserPaused()) {\n\t\tfor (int i = 0; i < ARRAY_SIZE(CTheScripts::IntroTextLines); i++) {\n\t\t\tif (CTheScripts::IntroTextLines[i].m_Text[0] && CTheScripts::IntroTextLines[i].m_bTextBeforeFade) {\n\t\t\t\tCFont::SetScale(SCREEN_SCALE_X(CTheScripts::IntroTextLines[i].m_fScaleX), SCREEN_SCALE_Y(CTheScripts::IntroTextLines[i].m_fScaleY * 0.5f));\n\t\t\t\tCFont::SetColor(CTheScripts::IntroTextLines[i].m_sColor);\n\n\t\t\t\tif (CTheScripts::IntroTextLines[i].m_bJustify)\n\t\t\t\t\tCFont::SetJustifyOn();\n\t\t\t\telse\n\t\t\t\t\tCFont::SetJustifyOff();\n\n\t\t\t\tif (CTheScripts::IntroTextLines[i].m_bRightJustify)\n\t\t\t\t\tCFont::SetRightJustifyOn();\n\t\t\t\telse\n\t\t\t\t\tCFont::SetRightJustifyOff();\n\n\t\t\t\tif (CTheScripts::IntroTextLines[i].m_bCentered)\n\t\t\t\t\tCFont::SetCentreOn();\n\t\t\t\telse\n\t\t\t\t\tCFont::SetCentreOff();\n\n\t\t\t\tCFont::SetWrapx(SCALE_AND_CENTER_X(CTheScripts::IntroTextLines[i].m_fWrapX));\n\t\t\t\tCFont::SetCentreSize(SCREEN_SCALE_X(CTheScripts::IntroTextLines[i].m_fCenterSize));\n\n\t\t\t\tif (CTheScripts::IntroTextLines[i].m_bBackground)\n\t\t\t\t\tCFont::SetBackgroundOn();\n\t\t\t\telse\n\t\t\t\t\tCFont::SetBackgroundOff();\n\n\t\t\t\tCFont::SetBackgroundColor(CTheScripts::IntroTextLines[i].m_sBackgroundColor);\n\n\t\t\t\tif (CTheScripts::IntroTextLines[i].m_bBackgroundOnly)\n\t\t\t\t\tCFont::SetBackGroundOnlyTextOn();\n\t\t\t\telse\n\t\t\t\t\tCFont::SetBackGroundOnlyTextOff();\n\n\t\t\t\tif (CTheScripts::IntroTextLines[i].m_bTextProportional)\n\t\t\t\t\tCFont::SetPropOn();\n\t\t\t\telse\n\t\t\t\t\tCFont::SetPropOff();\n\n\t\t\t\tCFont::SetFontStyle(FONT_LOCALE(CTheScripts::IntroTextLines[i].m_nFont));\n\t\t\t\tCFont::PrintString(SCREEN_WIDTH - SCALE_AND_CENTER_X(DEFAULT_SCREEN_WIDTH - CTheScripts::IntroTextLines[i].m_fAtX), SCREEN_HEIGHT - SCREEN_SCALE_Y(DEFAULT_SCREEN_HEIGHT - CTheScripts::IntroTextLines[i].m_fAtY), CTheScripts::IntroTextLines[i].m_Text);\n\t\t\t}\n\t\t}\n\t\tfor (int i = 0; i < ARRAY_SIZE(CTheScripts::IntroRectangles); i++) {\n\t\t\tintro_script_rectangle &IntroRect = CTheScripts::IntroRectangles[i];\n\n\t\t\t// Yeah, top and bottom changed place. R* vision\n\t\t\tif (IntroRect.m_bIsUsed && IntroRect.m_bBeforeFade) {\n\t\t\t\tif (IntroRect.m_nTextureId >= 0) {\n\t\t\t\t\tCRect rect (\n\t\t\t\t\t\tIntroRect.m_sRect.left,\n\t\t\t\t\t\tIntroRect.m_sRect.bottom,\n\t\t\t\t\t\tIntroRect.m_sRect.right,\n\t\t\t\t\t\tIntroRect.m_sRect.top );\n\n\t\t\t\t\tCTheScripts::ScriptSprites[IntroRect.m_nTextureId].Draw(rect, IntroRect.m_sColor);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tCRect rect (\n\t\t\t\t\t\tIntroRect.m_sRect.left,\n\t\t\t\t\t\tIntroRect.m_sRect.bottom,\n\t\t\t\t\t\tIntroRect.m_sRect.right,\n\t\t\t\t\t\tIntroRect.m_sRect.top );\n\n\t\t\t\t\tCSprite2d::DrawRect(rect, IntroRect.m_sColor);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t\tDrawSubtitles\n\t\t*/\n\t\tif (m_Message[0] && !m_BigMessage[2][0]) {\n\t\t\tif (m_VehicleState != 0)\n\t\t\t\tm_VehicleState = 3;\n\t\t\tif (m_ZoneState != 0)\n\t\t\t\tm_ZoneState = 3;\n\n\t\t\tCFont::SetJustifyOff();\n\t\t\tCFont::SetBackgroundOff();\n\t\t\tCFont::SetBackgroundColor(CRGBA(0, 0, 0, 128));\n\t\t\tCFont::SetCentreOn();\n\t\t\tCFont::SetPropOn();\n#ifdef CUTSCENE_BORDERS_SWITCH\n\t\t\tif (!FrontEndMenuManager.m_PrefsCutsceneBorders) {\n\t\t\t\tCFont::SetDropColor(CRGBA(0, 0, 0, 255));\n\t\t\t\tCFont::SetDropShadowPosition(2);\n\t\t\t}\n\t\t\telse\n#endif\n\t\t\t\tCFont::SetDropShadowPosition(0);\n\t\t\tCFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD));\n\t\t\tCFont::SetColor(CRGBA(225, 225, 225, 255));\n\n\t\t\tstatic bool onceItWasWidescreen = false;\n\n\t\t\tif (TheCamera.m_WideScreenOn) {\n\t\t\t\tonceItWasWidescreen = true;\n\t\t\t\t\n\t\t\t\tif (FrontEndMenuManager.m_PrefsShowSubtitles || !CCutsceneMgr::IsRunning()) {\n\t\t\t\t\tCFont::SetCentreSize(SCREEN_WIDTH - SCREEN_SCALE_X(60.0f));\n\t\t\t\t\tCFont::SetScale(SCREEN_SCALE_X(0.58f), SCREEN_SCALE_Y(1.2f));\n\t\t\t\t\tCFont::PrintString(SCREEN_WIDTH / 2.f, SCREEN_SCALE_FROM_BOTTOM(80.0f), m_Message);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (onceItWasWidescreen)\n\t\t\t\t\tm_Message[0] = '\\0';\n\n\t\t\t\tonceItWasWidescreen = false;\n\t\t\t\tCFont::DrawFonts();\n\t\t\t\tCFont::SetDropShadowPosition(2);\n\t\t\t\tCFont::SetDropColor(CRGBA(0, 0, 0, 255));\n\t\t\t\tCFont::SetScale(SCREEN_SCALE_X(0.58f), SCREEN_SCALE_Y(1.22f));\n\n\t\t\t\tfloat radarBulge = SCREEN_SCALE_X(140.0f) + SCREEN_SCALE_X(8.0f);\n\t\t\t\tfloat rectWidth = SCREEN_WIDTH - SCREEN_SCALE_X(20.0f) - SCREEN_SCALE_X(8.0f) - radarBulge;\n\t\t\t\tCFont::SetCentreSize(rectWidth);\n\n\t\t\t\tCFont::PrintString(rectWidth / 2.0f + radarBulge, SCREEN_SCALE_FROM_BOTTOM(105.f + 2.0f), m_Message);\n\t\t\t}\n\t\t\tCFont::SetDropShadowPosition(0);\n\t\t}\n\n\t\t/*\n\t\t\tHelpMessage\n\t\t*/\n\n\t\tif (m_HelpMessage[0]) {\n\t\t\tif (!CMessages::WideStringCompare(m_HelpMessage, m_LastHelpMessage, HELP_MSG_LENGTH)) {\n\t\t\t\tswitch (m_HelpMessageState) {\n\t\t\t\tcase 0:\n\t\t\t\t\tm_HelpMessageFadeTimer = 0;\n\t\t\t\t\tm_HelpMessageState = 2;\n\t\t\t\t\tm_HelpMessageTimer = 0;\n\t\t\t\t\tCMessages::WideStringCopy(m_HelpMessageToPrint, m_HelpMessage, HELP_MSG_LENGTH);\n\t\t\t\t\tm_HelpMessageDisplayTime = CMessages::GetWideStringLength(m_HelpMessage) * 0.05f + 3.0f;\n\n\t\t\t\t\tif (TheCamera.m_ScreenReductionPercentage == 0.0f)\n\t\t\t\t\t\tDMAudio.PlayFrontEndSound(SOUND_HUD, 0);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 1:\n\t\t\t\tcase 2:\n\t\t\t\tcase 3:\n\t\t\t\tcase 4:\n\t\t\t\t\tm_HelpMessageTimer = 5;\n\t\t\t\t\tm_HelpMessageState = 4;\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tCMessages::WideStringCopy(m_LastHelpMessage, m_HelpMessage, HELP_MSG_LENGTH);\n\t\t\t}\n\n\t\t\tfloat fAlpha = 225.0f;\n\n\t\t\tif (m_HelpMessageState != 0) {\n\t\t\t\tswitch (m_HelpMessageState) {\n\t\t\t\tcase 1:\n\t\t\t\t\tfAlpha = 225.0f;\n\t\t\t\t\tm_HelpMessageFadeTimer = 600;\n\t\t\t\t\tif (!m_HelpMessageDisplayForever && m_HelpMessageTimer > m_HelpMessageDisplayTime * 1000.0f ||\n\t\t\t\t\t\tm_HelpMessageQuick && m_HelpMessageTimer > 1500.0f) {\n\n\t\t\t\t\t\tm_HelpMessageFadeTimer = 600;\n\t\t\t\t\t\tm_HelpMessageState = 3;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase 2:\n\t\t\t\t\tif (TheCamera.m_WideScreenOn)\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tm_HelpMessageFadeTimer += 2 * CTimer::GetTimeStepInMilliseconds();\n\t\t\t\t\tif (m_HelpMessageFadeTimer > 0) {\n\t\t\t\t\t\tm_HelpMessageState = 1;\n\t\t\t\t\t\tm_HelpMessageFadeTimer = 0;\n\t\t\t\t\t}\n\t\t\t\t\tfAlpha = m_HelpMessageFadeTimer * 0.001f * 225.0f;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 3:\n\t\t\t\t\tm_HelpMessageFadeTimer -= 2 * CTimer::GetTimeStepInMilliseconds();\n\t\t\t\t\tif (m_HelpMessageFadeTimer < 0 || TheCamera.m_WideScreenOn) {\n\t\t\t\t\t\tm_HelpMessageState = 0;\n\t\t\t\t\t\tm_HelpMessageFadeTimer = 0;\n\t\t\t\t\t}\n\t\t\t\t\tfAlpha = m_HelpMessageFadeTimer * 0.001f * 225.0f;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 4:\n\t\t\t\t\tm_HelpMessageFadeTimer -= 2 * CTimer::GetTimeStepInMilliseconds();\n\t\t\t\t\tif (m_HelpMessageFadeTimer < 0) {\n\t\t\t\t\t\tm_HelpMessageState = 2;\n\t\t\t\t\t\tm_HelpMessageFadeTimer = 0;\n\t\t\t\t\t\tCMessages::WideStringCopy(m_HelpMessageToPrint, m_LastHelpMessage, HELP_MSG_LENGTH);\n\t\t\t\t\t}\n\t\t\t\t\tfAlpha = m_HelpMessageFadeTimer * 0.001f * 225.0f;\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif (!TheCamera.m_WideScreenOn) {\n\t\t\t\t\tm_HelpMessageTimer += CTimer::GetTimeStepInMilliseconds();\n\n\t\t\t\t\tCFont::SetAlphaFade(fAlpha);\n\t\t\t\t\tCFont::SetCentreOff();\n\t\t\t\t\tCFont::SetPropOn();\n\n\t\t\t\t\tif (CGame::germanGame)\n\t\t\t\t\t\tCFont::SetScale(SCREEN_SCALE_X(0.52f * 0.85f), SCREEN_SCALE_Y(1.1f * 0.85f));\n#ifdef MORE_LANGUAGES\n\t\t\t\t\telse if (CFont::IsJapanese())\n\t\t\t\t\t\tCFont::SetScale(SCREEN_SCALE_X(0.52f) * 1.35f, SCREEN_SCALE_Y(1.1f) * 1.25f);\n#endif\n\t\t\t\t\telse\n\t\t\t\t\t\tCFont::SetScale(SCREEN_SCALE_X(0.52f), SCREEN_SCALE_Y(1.1f));\n\n\t\t\t\t\tCFont::DrawFonts();\n\t\t\t\t\tCFont::SetColor(CRGBA(175, 175, 175, 255));\n\t\t\t\t\tCFont::SetJustifyOff();\n#ifdef MORE_LANGUAGES\n\t\t\t\t\tif (CFont::IsJapanese())\n\t\t\t\t\t\tCFont::SetWrapx(SCREEN_SCALE_X(229.0f + 34.0f - 4.0f));\n\t\t\t\t\telse\n#endif\n\t\t\t\t\t\tCFont::SetWrapx(SCREEN_SCALE_X(200.0f + 34.0f - 4.0f));\n\t\t\t\t\tCFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD));\n\t\t\t\t\tCFont::SetBackgroundOn();\n\t\t\t\t\tCFont::SetBackGroundOnlyTextOff();\n\t\t\t\t\tCFont::SetDropShadowPosition(0);\n\t\t\t\t\tCFont::SetBackgroundColor(CRGBA(0, 0, 0, fAlpha * 0.9f));\n\t\t\t\t\tCFont::SetColor(CRGBA(175, 175, 175, 255));\n\t\t\t\t\tCFont::PrintString(SCREEN_SCALE_X(34.0f), SCREEN_SCALE_Y(28.0f + (150.0f - PagerXOffset) * 0.6f), m_HelpMessageToPrint);\n\t\t\t\t\tCFont::SetAlphaFade(255.0f);\n\t\t\t\t\tCFont::SetWrapx(SCREEN_WIDTH);\n\t\t\t\t}\n\t\t\t}\n\t\t} else\n\t\t\tm_HelpMessageState = 0;\n\n\t\t/*\n\t\t\tDrawBigMessage\n\t\t*/\n\t\t// MissionCompleteFailedText\n\t\tif (m_BigMessage[0][0]) {\n\t\t\tif (BigMessageInUse[0] != 0.0f) {\n\t\t\t\tCFont::SetJustifyOff();\n\t\t\t\tCFont::SetBackgroundOff();\n\t\t\t\tCFont::SetBackGroundOnlyTextOff();\n\t\t\t\tif (CGame::frenchGame || CGame::germanGame) {\n\t\t\t\t\tCFont::SetScale(SCREEN_SCALE_X(1.6f), SCREEN_SCALE_Y(1.8f));\n\t\t\t\t} else {\n\t\t\t\t\tCFont::SetScale(SCREEN_SCALE_X(1.8f), SCREEN_SCALE_Y(1.8f));\n\t\t\t\t}\n\t\t\t\tCFont::SetPropOn();\n\t\t\t\tCFont::SetCentreOn();\n\t\t\t\tCFont::SetCentreSize(SCREEN_SCALE_X(590.0f));\n\t\t\t\tCFont::SetColor(CRGBA(255, 255, 0, BigMessageAlpha[0])); // unused color\n\t\t\t\tCFont::SetFontStyle(FONT_HEADING);\n\n\t\t\t\t// Appearently sliding text in here was abandoned very early, since this text is centered now.\n\n\t\t\t\tif (BigMessageX[0] >= SCALE_AND_CENTER_X(620.0f)) {\n\t\t\t\t\tBigMessageInUse[0] += CTimer::GetTimeStep();\n\n\t\t\t\t\tif (BigMessageInUse[0] >= 120.0f) {\n\t\t\t\t\t\tBigMessageInUse[0] = 120.0f;\n\t\t\t\t\t\tBigMessageAlpha[0] -= (CTimer::GetTimeStepInMilliseconds() * 0.3f);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (BigMessageAlpha[0] <= 0.0f) {\n\t\t\t\t\t\tm_BigMessage[0][0] = 0;\n\t\t\t\t\t\tBigMessageAlpha[0] = 0.0f;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tBigMessageX[0] += SCREEN_SCALE_X((CTimer::GetTimeStepInMilliseconds() * 0.3f));\n\t\t\t\t\tBigMessageAlpha[0] += (CTimer::GetTimeStepInMilliseconds() * 0.3f);\n\n\t\t\t\t\tif (BigMessageAlpha[0] > 255.0f)\n\t\t\t\t\t\tBigMessageAlpha[0] = 255.0f;\n\t\t\t\t}\n\t\t\t\tCFont::DrawFonts();\n\t\t\t\tCFont::SetDropShadowPosition(2);\n\t\t\t\tCFont::SetDropColor(CRGBA(0, 0, 0, BigMessageAlpha[0]));\n\t\t\t\tCFont::SetColor(CRGBA(BIGMESSAGE_COLOR.r, BIGMESSAGE_COLOR.g, BIGMESSAGE_COLOR.b, BigMessageAlpha[0]));\n\t\t\t\tCFont::PrintString(SCREEN_WIDTH / 2, (SCREEN_HEIGHT / 2) - SCREEN_SCALE_Y(18.0f), m_BigMessage[0]);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tBigMessageAlpha[0] = 0.0f;\n\t\t\t\tBigMessageX[0] = SCALE_AND_CENTER_X(-60.0f);\n\t\t\t\tBigMessageInUse[0] = 1.0f;\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tBigMessageInUse[0] = 0.0f;\n\t\t}\n\n\t\t// WastedBustedText\n\t\tif (m_BigMessage[2][0]) {\n\t\t\tif (BigMessageInUse[2] != 0.0f) {\n\t\t\t\tBigMessageAlpha[2] += (CTimer::GetTimeStepInMilliseconds() * 0.4f);\n\n\t\t\t\tif (BigMessageAlpha[2] > 255.0f)\n\t\t\t\t\tBigMessageAlpha[2] = 255.0f;\n\n\t\t\t\tCFont::SetBackgroundOff();\n\n\t\t\t\tif (CGame::frenchGame || CGame::germanGame)\n\t\t\t\t\tCFont::SetScale(SCREEN_SCALE_X(1.4f), SCREEN_SCALE_Y(1.4f));\n\t\t\t\telse\n\t\t\t\t\tCFont::SetScale(SCREEN_SCALE_X(2.0f), SCREEN_SCALE_Y(2.0f));\n\n\t\t\t\tCFont::SetPropOn();\n\t\t\t\tCFont::SetRightJustifyOn();\n\t\t\t\tCFont::SetFontStyle(FONT_HEADING);\n\n\t\t\t\tCFont::SetDropShadowPosition(2);\n\t\t\t\tCFont::SetDropColor(CRGBA(0, 0, 0, BigMessageAlpha[2]));\n\n\t\t\t\tCFont::SetColor(CRGBA(WASTEDBUSTED_COLOR.r, WASTEDBUSTED_COLOR.g, WASTEDBUSTED_COLOR.b, BigMessageAlpha[2]));\n\t\t\t\tCFont::PrintString(SCREEN_SCALE_FROM_RIGHT(20.0f), SCREEN_SCALE_FROM_BOTTOM(90.0f), m_BigMessage[2]);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tBigMessageInUse[2] = 1.0f;\n\t\t\t\tBigMessageAlpha[2] = 0.0f;\n\t\t\t\tif (m_VehicleState != 0) // Hide vehicle name if wasted/busted text is displaying\n\t\t\t\t\tm_VehicleState = 0;\n\t\t\t\tif (m_ZoneState != 0)\n\t\t\t\t\tm_ZoneState = 0;\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tBigMessageInUse[2] = 0.0f;\n\t\t}\n\t}\n}\n\nvoid CHud::DrawAfterFade()\n{\n\tRwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERNEAREST);\n\tRwRenderStateSet(rwRENDERSTATETEXTUREADDRESS, (void*)rwTEXTUREADDRESSCLAMP);\n\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);\n\n\tif (CTimer::GetIsUserPaused() || CReplay::IsPlayingBack())\n\t\treturn;\n\n\tfor (int i = 0; i < ARRAY_SIZE(CTheScripts::IntroTextLines); i++) {\n\t\tintro_text_line &line = CTheScripts::IntroTextLines[i];\n\t\tif (line.m_Text[0] != '\\0' && !line.m_bTextBeforeFade) {\n\t\t\tCFont::SetScale(SCREEN_SCALE_X(line.m_fScaleX), SCREEN_SCALE_Y(line.m_fScaleY) / 2);\n\n\t\t\tCFont::SetColor(line.m_sColor);\n\t\t\tif (line.m_bJustify)\n\t\t\t\tCFont::SetJustifyOn();\n\t\t\telse\n\t\t\t\tCFont::SetJustifyOff();\n\n\t\t\tif (line.m_bRightJustify)\n\t\t\t\tCFont::SetRightJustifyOn();\n\t\t\telse\n\t\t\t\tCFont::SetRightJustifyOff();\n\n\t\t\tif (line.m_bCentered)\n\t\t\t\tCFont::SetCentreOn();\n\t\t\telse\n\t\t\t\tCFont::SetCentreOff();\n\n\t\t\tCFont::SetWrapx(SCALE_AND_CENTER_X(line.m_fWrapX));\n\t\t\tCFont::SetCentreSize(SCREEN_SCALE_X(line.m_fCenterSize));\n\t\t\tif (line.m_bBackground)\n\t\t\t\tCFont::SetBackgroundOn();\n\t\t\telse\n\t\t\t\tCFont::SetBackgroundOff();\n\n\t\t\tCFont::SetBackgroundColor(line.m_sBackgroundColor);\n\t\t\tif (line.m_bBackgroundOnly)\n\t\t\t\tCFont::SetBackGroundOnlyTextOn();\n\t\t\telse\n\t\t\t\tCFont::SetBackGroundOnlyTextOff();\n\n\t\t\tif (line.m_bTextProportional)\n\t\t\t\tCFont::SetPropOn();\n\t\t\telse\n\t\t\t\tCFont::SetPropOff();\n\n\t\t\tCFont::SetFontStyle(line.m_nFont);\n\t\t\tCFont::PrintString(SCREEN_WIDTH - SCALE_AND_CENTER_X(DEFAULT_SCREEN_WIDTH - line.m_fAtX), SCREEN_HEIGHT - SCREEN_SCALE_Y(DEFAULT_SCREEN_HEIGHT - line.m_fAtY), line.m_Text);\n\t\t}\n\t}\n\tfor (int i = 0; i < ARRAY_SIZE(CTheScripts::IntroRectangles); i++) {\n\t\tintro_script_rectangle &rectangle = CTheScripts::IntroRectangles[i];\n\t\tif (rectangle.m_bIsUsed && !rectangle.m_bBeforeFade) {\n\n\t\t\t// Yeah, top and bottom changed place. R* vision\n\t\t\tif (rectangle.m_nTextureId >= 0) {\n\t\t\t\tCTheScripts::ScriptSprites[rectangle.m_nTextureId].Draw(CRect(rectangle.m_sRect.left, rectangle.m_sRect.bottom,\n\t\t\t\t\trectangle.m_sRect.right, rectangle.m_sRect.top), rectangle.m_sColor);\n\t\t\t} else {\n\t\t\t\tCSprite2d::DrawRect(CRect(rectangle.m_sRect.left, rectangle.m_sRect.bottom,\n\t\t\t\t\trectangle.m_sRect.right, rectangle.m_sRect.top), rectangle.m_sColor);\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t\tDrawBigMessage2\n\t*/\n\t// Oddjob\n\tif (m_BigMessage[3][0]) {\n\t\tCFont::SetJustifyOff();\n\t\tCFont::SetBackgroundOff();\n\t\tCFont::SetScale(SCREEN_SCALE_X(1.2f), SCREEN_SCALE_Y(1.5f));\n\t\tCFont::SetCentreOn();\n\t\tCFont::SetPropOn();\n\t\tCFont::SetCentreSize(SCREEN_SCALE_X(600.0f));\n\t\tCFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD));\n\t\tCFont::SetDropShadowPosition(2);\n\t\tCFont::SetDropColor(CRGBA(0, 0, 0, 255));\n\t\tCFont::SetColor(ODDJOB_COLOR);\n\t\tCFont::PrintString((SCREEN_WIDTH / 2), SCREEN_SCALE_Y(140.0f) - SCREEN_SCALE_Y(16.0f), m_BigMessage[3]);\n\t}\n\n\tif (!m_BigMessage[1][0] && m_BigMessage[4][0]) {\n\t\tCFont::SetJustifyOff();\n\t\tCFont::SetBackgroundOff();\n\t\tCFont::SetScale(SCREEN_SCALE_X(1.2f), SCREEN_SCALE_Y(1.5f));\n\t\tCFont::SetCentreOn();\n\t\tCFont::SetPropOn();\n\t\tCFont::SetCentreSize(SCREEN_SCALE_X(580.0f));\n\t\tCFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD));\n\t\tCFont::SetDropShadowPosition(2);\n\t\tCFont::SetDropColor(CRGBA(0, 0, 0, 255));\n\t\tCFont::SetColor(ODDJOB_COLOR);\n\t\tCFont::PrintString((SCREEN_WIDTH / 2), SCREEN_SCALE_Y(140.0f), m_BigMessage[4]);\n\t}\n\n\t// Oddjob result\n\tif (OddJob2OffTimer > 0)\n\t\tOddJob2OffTimer -= CTimer::GetTimeStepInMilliseconds();\n\n\tfloat fStep;\n\tif (m_BigMessage[5][0] && OddJob2OffTimer <= 0.0f) {\n\t\tswitch (OddJob2On) {\n\t\t\tcase 0:\n\t\t\t\tOddJob2On = 1;\n\t\t\t\tOddJob2XOffset = 380.0f;\n\t\t\t\tbreak;\n\t\t\tcase 1:\n\t\t\t\tif (OddJob2XOffset <= 2.0f) {\n\t\t\t\t\tOddJob2Timer = 0;\n\t\t\t\t\tOddJob2On = 2;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tfStep = Min(40.0f, OddJob2XOffset / 6.0f);\n\t\t\t\t\tOddJob2XOffset = OddJob2XOffset - fStep;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 2:\n\t\t\t\tOddJob2Timer += CTimer::GetTimeStepInMilliseconds();\n\t\t\t\tif (OddJob2Timer > 1500) {\n\t\t\t\t\tOddJob2On = 3;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 3:\n\t\t\t\tfStep = Max(30.0f, OddJob2XOffset / 5.0f);\n\n\t\t\t\tOddJob2XOffset = OddJob2XOffset - fStep;\n\n\t\t\t\tif (OddJob2XOffset < -380.0f) {\n\t\t\t\t\tOddJob2OffTimer = 5000.0f;\n\t\t\t\t\tOddJob2On = 0;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\n\t\tif (!m_BigMessage[1][0]) {\n\t\t\tCFont::SetJustifyOff();\n\t\t\tCFont::SetBackgroundOff();\n\t\t\tCFont::SetScale(SCREEN_SCALE_X(1.0f), SCREEN_SCALE_Y(1.2f));\n\t\t\tCFont::SetCentreOn();\n\t\t\tCFont::SetPropOn();\n\t\t\tCFont::SetCentreSize(SCREEN_SCALE_X(560.0f));\n\t\t\tCFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD));\n\t\t\tCFont::SetDropShadowPosition(2);\n\t\t\tCFont::SetDropColor(CRGBA(0, 0, 0, 255));\n\t\t\tCFont::SetColor(ODDJOB2_COLOR);\n\t\t\tCFont::PrintString(SCREEN_WIDTH / 2, SCREEN_SCALE_Y(217.0f), m_BigMessage[5]);\n\t\t}\n\t}\n\n\t/*\n\t\tDrawMissionTitle\n\t*/\n\tif (m_BigMessage[1][0]) {\n\t\tif (BigMessageInUse[1] != 0.0f) {\n\t\t\tCFont::SetJustifyOff();\n\t\t\tCFont::SetBackgroundOff();\n\n\t\t\t// will be overwritten below\n\t\t\tif (CGame::frenchGame || FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_SPANISH)\n\t\t\t\tCFont::SetScale(SCREEN_SCALE_X(0.884f), SCREEN_SCALE_Y(1.36f));\n\t\t\telse\n\t\t\t\tCFont::SetScale(SCREEN_SCALE_X(1.04f), SCREEN_SCALE_Y(1.6f));\n\n\t\t\tCFont::SetPropOn();\n\t\t\tCFont::SetRightJustifyWrap(SCALE_AND_CENTER_X(0.0f));\n\t\t\tCFont::SetRightJustifyOn();\n\t\t\tCFont::SetFontStyle(FONT_BANK);\n\t\t\tCFont::SetScale(FrontEndMenuManager.m_PrefsLanguage == CMenuManager::LANGUAGE_AMERICAN ? SCREEN_SCALE_X(1.7f) : SCREEN_SCALE_X(1.5f), SCREEN_SCALE_Y(1.8f));\n\n\t\t\tif (BigMessageX[1] >= SCREEN_SCALE_FROM_RIGHT(20.0f)) {\n\t\t\t\tBigMessageInUse[1] += CTimer::GetTimeStep();\n\n\t\t\t\tif (BigMessageInUse[1] >= 120.0f) {\n\t\t\t\t\tBigMessageInUse[1] = 120.0f;\n\t\t\t\t\tBigMessageAlpha[1] -= CTimer::GetTimeStepInMilliseconds();\n\t\t\t\t}\n\t\t\t\tif (BigMessageAlpha[1] <= 0.0f) {\n\t\t\t\t\tm_BigMessage[1][0] = 0;\n\t\t\t\t\tBigMessageInUse[1] = 0.0f;\n\t\t\t\t\tBigMessageAlpha[1] = 0.0f;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tBigMessageX[1] += SCREEN_SCALE_X((CTimer::GetTimeStepInMilliseconds() * 0.3f));\n\t\t\t\tBigMessageAlpha[1] += CTimer::GetTimeStepInMilliseconds();\n\n\t\t\t\tif (BigMessageAlpha[1] > 255.0f)\n\t\t\t\t\tBigMessageAlpha[1] = 255.0f;\n\t\t\t}\n\n\t\t\tCFont::SetColor(CRGBA(40, 40, 40, BigMessageAlpha[1])); // what was that for?\n\n\t\t\tCFont::SetDropShadowPosition(2);\n\t\t\tCFont::SetDropColor(CRGBA(0, 0, 0, BigMessageAlpha[1]));\n\t\t\tCFont::SetColor(CRGBA(MISSIONTITLE_COLOR.r, MISSIONTITLE_COLOR.g, MISSIONTITLE_COLOR.b, BigMessageAlpha[1]));\n\t\t\tCFont::PrintString(SCREEN_SCALE_FROM_RIGHT(20.0f), SCREEN_SCALE_FROM_BOTTOM(140.0f), m_BigMessage[1]);\n\t\t} else {\n\t\t\tm_ZoneFadeTimer = 0;\n\t\t\tBigMessageX[1] = SCREEN_SCALE_FROM_RIGHT(DEFAULT_SCREEN_WIDTH + 60.0f);\n\t\t\tBigMessageInUse[1] = 1.0f;\n\t\t\tm_ZoneState = 0;\n\t\t}\n\t} else {\n\t\tBigMessageInUse[1] = 0.0f;\n\t}\n}\n\nvoid CHud::GetRidOfAllHudMessages()\n{\n\tm_ZoneNameTimer = 0;\n\tm_pZoneName = nil;\n\tm_ZoneState = 0;\n\n\tfor (int i = 0; i < HELP_MSG_LENGTH; i++) {\n\t\tm_HelpMessage[i] = 0;\n\t\tm_LastHelpMessage[i] = 0;\n\t\tm_HelpMessageToPrint[i] = 0;\n\t}\n\n\tm_HelpMessageTimer = 0;\n\tm_HelpMessageFadeTimer = 0;\n\tm_HelpMessageState = 0;\n\tm_HelpMessageQuick = 0;\n\tm_HelpMessageDisplayForever = false;\n\tm_HelpMessageDisplayTime = 1.0f;\n\tm_VehicleName = nil;\n\tm_pVehicleNameToPrint = nil;\n\tm_VehicleNameTimer = 0;\n\tm_VehicleFadeTimer = 0;\n\tm_VehicleState = 0;\n\n\tfor (int i = 0; i < ARRAY_SIZE(m_Message); i++)\n\t\tm_Message[i] = 0;\n\n\tfor (int i = 0; i < 6; i++) {\n\t\tBigMessageInUse[i] = 0.0f;\n\n\t\tfor (int j = 0; j < 128; j++)\n\t\t\tm_BigMessage[i][j] = 0;\n\t}\n}\n\n#ifdef RELOADABLES\nvoid CHud::ReloadTXD()\n{\n\tfor (int i = 0; i < NUM_HUD_SPRITES; ++i) {\n\t\tSprites[i].Delete();\n\t}\n\n\tint HudTXD = CTxdStore::FindTxdSlot(\"hud\");\n\tCTxdStore::RemoveTxdSlot(HudTXD);\n\n\tdebug(\"Reloading HUD.TXD...\\n\");\n\n\tHudTXD = CTxdStore::AddTxdSlot(\"hud\");\n\tCTxdStore::LoadTxd(HudTXD, \"MODELS/HUD.TXD\");\n\tCTxdStore::AddRef(HudTXD);\n\tCTxdStore::PopCurrentTxd();\n\tCTxdStore::SetCurrentTxd(HudTXD);\n\n\tfor (int i = 0; i < NUM_HUD_SPRITES; i++) {\n\t\tSprites[i].SetTexture(WeaponFilenames[i].name, WeaponFilenames[i].mask);\n\t}\n}\n#endif\n\nvoid CHud::Initialise()\n{\n\tm_Wants_To_Draw_Hud = true;\n\tm_Wants_To_Draw_3dMarkers = true;\n\n\tint HudTXD = CTxdStore::AddTxdSlot(\"hud\");\n\tCTxdStore::LoadTxd(HudTXD, \"MODELS/HUD.TXD\");\n\tCTxdStore::AddRef(HudTXD);\n\tCTxdStore::PopCurrentTxd();\n\tCTxdStore::SetCurrentTxd(HudTXD);\n\n\tfor (int i = 0; i < NUM_HUD_SPRITES; i++) {\n\t\tSprites[i].SetTexture(WeaponFilenames[i].name, WeaponFilenames[i].mask);\n\t}\n\n\tm_pLastZoneName = nil;\n\tGetRidOfAllHudMessages();\n\tm_pLastVehicleName = nil;\n\n\tif (gpSniperSightTex == nil)\n\t\tgpSniperSightTex = RwTextureRead(\"sitesniper\", nil); // unused\n\tif (gpRocketSightTex == nil)\n\t\tgpRocketSightTex = RwTextureRead(\"siterocket\", nil);\n\tif (gpLaserSightTex == nil)\n\t\tgpLaserSightTex = RwTextureRead(\"sitelaser\", nil); // unused\n\tif (gpLaserDotTex == nil)\n\t\tgpLaserDotTex = RwTextureRead(\"laserdot\", \"laserdotm\");\n\tif (gpViewFinderTex == nil)\n\t\tgpViewFinderTex = RwTextureRead(\"viewfinder_128\", \"viewfinder_128m\"); // unused\n\n\tm_ClockState = 1;\n\tCounterOnLastFrame[0] = false;\n\tCounterOnLastFrame[1] = false;\n\tCounterOnLastFrame[2] = false;\n\t\n\tm_ItemToFlash = ITEM_NONE;\n\tOddJob2Timer = 0;\n\tOddJob2OffTimer = 0.0f;\n\tOddJob2On = 0;\n\tOddJob2XOffset = 0.0f;\n\tCounterFlashTimer[0] = 0;\n\tCounterFlashTimer[1] = 0;\n\tCounterFlashTimer[2] = 0;\n\tTimerOnLastFrame = false;\n\tTimerFlashTimer = 0;\n\tSpriteBrightness = 0;\n\tPagerOn = 0;\n\tPagerTimer = 0;\n\tPagerSoundPlayed = 0;\n\tPagerXOffset = 150.0f;\n\n#ifdef HUD_AUTO_FADE\n\tm_EnergyLostState = START_FADE_OUT;\n\tm_WantedState = START_FADE_OUT;\n\tm_DisplayScoreState = START_FADE_OUT;\n\tm_WeaponState = START_FADE_OUT;\n#else\n\tm_EnergyLostState = FADE_DISABLED;\n\tm_WantedState = FADE_DISABLED;\n\tm_DisplayScoreState = FADE_DISABLED;\n\tm_WeaponState = FADE_DISABLED;\n#endif\n\tm_WantedFadeTimer = 0;\n\tm_WantedTimer = 0;\n\tm_EnergyLostFadeTimer = 0;\n\tm_EnergyLostTimer = 0;\n\tm_DisplayScoreFadeTimer = 0;\n\tm_DisplayScoreTimer = 0;\n\tm_WeaponFadeTimer = 0;\n\tm_WeaponTimer = 0;\n\n\tm_HideRadar = false;\n\tm_LastDisplayScore = CWorld::Players[CWorld::PlayerInFocus].m_nVisibleMoney;\n\tm_LastTimeEnergyLost = CWorld::Players[CWorld::PlayerInFocus].m_nTimeLastHealthLoss;\n\tm_LastWanted = 0;\n\tm_LastWeapon = 0;\n\n#ifndef MASTER\n\tVarConsole.Add(\"Draw HUD\", &m_Wants_To_Draw_Hud, false);\n#endif\n\tCTxdStore::PopCurrentTxd();\n}\n\nvoid CHud::ReInitialise() {\n\tm_Wants_To_Draw_Hud = true;\n\tm_Wants_To_Draw_3dMarkers = true;\n\n\tm_pLastZoneName = nil;\n\tGetRidOfAllHudMessages();\n\tm_pLastVehicleName = nil;\n\n\tCounterOnLastFrame[0] = false;\n\tCounterOnLastFrame[1] = false;\n\tCounterOnLastFrame[2] = false;\n\tm_ItemToFlash = ITEM_NONE;\n\tm_ClockState = 1;\n\tOddJob2Timer = 0;\n\tOddJob2OffTimer = 0.0f;\n\tOddJob2On = 0;\n\tOddJob2XOffset = 0.0f;\n\tCounterFlashTimer[0] = 0;\n\tCounterFlashTimer[1] = 0;\n\tCounterFlashTimer[2] = 0;\n\tTimerOnLastFrame = false;\n\tTimerFlashTimer = 0;\n\tSpriteBrightness = 0;\n\tPagerOn = 0;\n\tPagerTimer = 0;\n\tPagerSoundPlayed = 0;\n\tPagerXOffset = 150.0f;\n\n#ifdef HUD_AUTO_FADE\n\tm_EnergyLostState = START_FADE_OUT;\n\tm_WantedState = START_FADE_OUT;\n\tm_DisplayScoreState = START_FADE_OUT;\n\tm_WeaponState = START_FADE_OUT;\n#else\n\tm_EnergyLostState = FADE_DISABLED;\n\tm_WantedState = FADE_DISABLED;\n\tm_DisplayScoreState = FADE_DISABLED;\n\tm_WeaponState = FADE_DISABLED;\n#endif\n\tm_WantedFadeTimer = 0;\n\tm_WantedTimer = 0;\n\tm_EnergyLostFadeTimer = 0;\n\tm_EnergyLostTimer = 0;\n\tm_DisplayScoreFadeTimer = 0;\n\tm_DisplayScoreTimer = 0;\n\tm_WeaponFadeTimer = 0;\n\tm_WeaponTimer = 0;\n\n\tm_HideRadar = false;\n\tm_LastDisplayScore = CWorld::Players[CWorld::PlayerInFocus].m_nVisibleMoney;\n\tm_LastTimeEnergyLost = CWorld::Players[CWorld::PlayerInFocus].m_nTimeLastHealthLoss;\n\tm_LastWanted = 0;\n\tm_LastWeapon = 0;\n}\n\nwchar LastBigMessage[6][128];\n\nvoid CHud::SetBigMessage(wchar *message, uint16 style)\n{\n\tint i = 0;\n\n\tif (BigMessageInUse[style] != 0.0f)\n\t\treturn;\n\n\tif (style == 5) {\n\t\tfor (i = 0; i < 128; i++) {\n\t\t\tif (message[i] == 0)\n\t\t\t\tbreak;\n\n\t\t\tif (message[i] != LastBigMessage[5][i]) {\n\t\t\t\tOddJob2On = 0;\n\t\t\t\tOddJob2OffTimer = 0.0f;\n\t\t\t}\n\n\t\t\tm_BigMessage[5][i] = message[i];\n\t\t\tLastBigMessage[5][i] = message[i];\n\t\t}\n\t} else {\n\t\tfor (i = 0; i < 128; i++) {\n\t\t\tif (message[i] == 0)\n\t\t\t\tbreak;\n\t\t\tm_BigMessage[style][i] = message[i];\n\t\t}\n\t}\n\tLastBigMessage[style][i] = 0;\n\tm_BigMessage[style][i] = 0;\n}\n\nvoid CHud::SetHelpMessage(wchar *message, bool quick, bool displayForever)\n{\n\tif (!CReplay::IsPlayingBack()) {\n\t\tfor (int i = 0; i < HELP_MSG_LENGTH; i++) {\n\t\t\tm_HelpMessage[i] = 0;\n\t\t}\n\t\tfor (int i = 0; i < HELP_MSG_LENGTH; i++) {\n\t\t\tm_LastHelpMessage[i] = 0;\n\t\t}\n\t\tfor (int i = 0; i < HELP_MSG_LENGTH; i++) {\n\t\t\tm_HelpMessageToPrint[i] = 0;\n\t\t}\n\n\t\tCMessages::WideStringCopy(m_HelpMessage, message, HELP_MSG_LENGTH);\n\t\tCMessages::InsertPlayerControlKeysInString(m_HelpMessage);\n\t\tif (m_HelpMessageState == 0 || !CMessages::WideStringCompare(m_HelpMessage, m_HelpMessageToPrint, HELP_MSG_LENGTH)) {\n\t\t\tfor (int i = 0; i < HELP_MSG_LENGTH; i++) {\n\t\t\t\tm_LastHelpMessage[i] = 0;\n\t\t\t}\n\n\t\t\tif (!message) {\n\t\t\t\tm_HelpMessage[0] = 0;\n\t\t\t\tm_HelpMessageToPrint[0] = 0;\n\t\t\t}\n\t\t\tif (!displayForever) {\n\t\t\t\tm_HelpMessageState = displayForever;\n\t\t\t} else {\n\t\t\t\tm_HelpMessageState = 1;\n\t\t\t\tCMessages::WideStringCopy(m_HelpMessageToPrint, m_HelpMessage, HELP_MSG_LENGTH);\n\t\t\t\tCMessages::WideStringCopy(m_LastHelpMessage, m_HelpMessage, HELP_MSG_LENGTH);\n\t\t\t}\n\n\t\t\tm_HelpMessageQuick = quick;\n\t\t\tm_HelpMessageDisplayForever = displayForever;\n\t\t}\n\n\t}\n}\n\nbool CHud::IsHelpMessageBeingDisplayed(void)\n{\n\treturn m_HelpMessageState != 0;\n}\n\nvoid CHud::SetMessage(wchar *message)\n{\n\tint i = 0;\n\tfor (i = 0; i < ARRAY_SIZE(m_Message); i++) {\n\t\tif (message[i] == 0)\n\t\t\tbreak;\n\n\t\tm_Message[i] = message[i];\n\t}\n\tm_Message[i] = 0;\n}\n\nvoid CHud::SetPagerMessage(wchar *message)\n{\n\tint i = 0;\n\tfor (i = 0; i < ARRAY_SIZE(m_PagerMessage); i++) {\n\t\tif (message[i] == 0)\n\t\t\tbreak;\n\n\t\tm_PagerMessage[i] = message[i];\n\t}\n\tm_PagerMessage[i] = 0;\n}\n\nvoid CHud::SetVehicleName(wchar *name)\n{\n\tm_VehicleName = name;\n}\n\nvoid CHud::SetZoneName(wchar *name)\n{\n\tm_pZoneName = name;\n}\n\nvoid CHud::Shutdown()\n{\n\tfor (int i = 0; i < NUM_HUD_SPRITES; ++i) {\n\t\tSprites[i].Delete();\n\t}\n\n\tRwTextureDestroy(gpSniperSightTex);\n\tgpSniperSightTex = nil;\n\n\tRwTextureDestroy(gpRocketSightTex);\n\tgpRocketSightTex = nil;\n\n\tRwTextureDestroy(gpLaserSightTex);\n\tgpLaserSightTex = nil;\n\n\tRwTextureDestroy(gpLaserDotTex);\n\tgpLaserDotTex = nil;\n\n\tRwTextureDestroy(gpViewFinderTex);\n\tgpViewFinderTex = nil;\n\n\tint HudTXD = CTxdStore::FindTxdSlot(\"hud\");\n\tCTxdStore::RemoveTxdSlot(HudTXD);\n}\n\nfloat CHud::DrawFadeState(DRAW_FADE_STATE fadingElement, int forceFadingIn)\n{\n\tfloat alpha = 255.0f;\n\tuint32 operation, timer;\n\tint32 fadeTimer;\n\n\tswitch (fadingElement) {\n\t\tcase HUD_WANTED_FADING:\n\t\t\tfadeTimer = m_WantedFadeTimer;\n\t\t\toperation = m_WantedState;\n\t\t\ttimer = m_WantedTimer;\n\t\t\tbreak;\n\t\tcase HUD_ENERGY_FADING:\n\t\t\tfadeTimer = m_EnergyLostFadeTimer;\n\t\t\toperation = m_EnergyLostState;\n\t\t\ttimer = m_EnergyLostTimer;\n\t\t\tbreak;\n\t\tcase HUD_SCORE_FADING:\n\t\t\tfadeTimer = m_DisplayScoreFadeTimer;\n\t\t\toperation = m_DisplayScoreState;\n\t\t\ttimer = m_DisplayScoreTimer;\n\t\t\tbreak;\n\t\tcase HUD_WEAPON_FADING:\n\t\t\tfadeTimer = m_WeaponFadeTimer;\n\t\t\toperation = m_WeaponState;\n\t\t\ttimer = m_WeaponTimer;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\tif (forceFadingIn) {\n\t\tswitch (operation) {\n\t\t\tcase FADED_OUT:\n\t\t\t\tfadeTimer = 0;\n\t\t\tcase START_FADE_OUT:\n\t\t\tcase FADING_OUT:\n\t\t\t\ttimer = 5;\n\t\t\t\toperation = FADING_IN;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n\tif (operation != FADED_OUT && operation != FADE_DISABLED) {\n\t\tswitch (operation) {\n\t\t\tcase START_FADE_OUT:\n\t\t\t\tfadeTimer = 1000;\n\t\t\t\talpha = 255.0f;\n\t\t\t\tif (timer > 10000) {\n\t\t\t\t\tfadeTimer = 3000;\n\t\t\t\t\toperation = FADING_OUT;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase FADING_IN:\n\t\t\t\tfadeTimer += CTimer::GetTimeStepInMilliseconds();\n\t\t\t\tif (fadeTimer > 1000.0f) {\n\t\t\t\t\toperation = START_FADE_OUT;\n\t\t\t\t\tfadeTimer = 1000;\n\t\t\t\t}\n\t\t\t\talpha = fadeTimer / 1000.0f * 255.0f;\n\t\t\t\tbreak;\n\t\t\tcase FADING_OUT:\n\t\t\t\tfadeTimer -= CTimer::GetTimeStepInMilliseconds();\n\t\t\t\tif (fadeTimer < 0.0f) {\n\t\t\t\t\tfadeTimer = 0;\n\t\t\t\t\toperation = FADED_OUT;\n\t\t\t\t}\n\t\t\t\talpha = fadeTimer / 1000.0f * 255.0f;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t\ttimer += CTimer::GetTimeStepInMilliseconds();\n\t}\n\n\tswitch (fadingElement) {\n\t\tcase HUD_WANTED_FADING:\n\t\t\tm_WantedFadeTimer = fadeTimer;\n\t\t\tm_WantedState = operation;\n\t\t\tm_WantedTimer = timer;\n\t\t\tbreak;\n\t\tcase HUD_ENERGY_FADING:\n\t\t\tm_EnergyLostFadeTimer = fadeTimer;\n\t\t\tm_EnergyLostState = operation;\n\t\t\tm_EnergyLostTimer = timer;\n\t\t\tbreak;\n\t\tcase HUD_SCORE_FADING:\n\t\t\tm_DisplayScoreFadeTimer = fadeTimer;\n\t\t\tm_DisplayScoreState = operation;\n\t\t\tm_DisplayScoreTimer = timer;\n\t\t\tbreak;\n\t\tcase HUD_WEAPON_FADING:\n\t\t\tm_WeaponFadeTimer = fadeTimer;\n\t\t\tm_WeaponState = operation;\n\t\t\tm_WeaponTimer = timer;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\n\treturn clamp(alpha, 0.0f, 255.0f);\n}\n\nvoid\nCHud::ResetWastedText(void)\n{\n\tBigMessageInUse[2] = 0.0f;\n\tBigMessageInUse[0] = 0.0f;\n\tm_BigMessage[2][0] = 0;\n\tm_BigMessage[0][0] = 0;\n}\n"
  },
  {
    "path": "src/render/Hud.h",
    "content": "#pragma once\n#include \"Sprite2d.h\"\n\n#define HELP_MSG_LENGTH 256\n\n#define HUD_TEXT_SCALE_X 0.7f\n#define HUD_TEXT_SCALE_Y 1.25f\n\nenum eItems\n{\n\tITEM_NONE = -1,\n\tITEM_ARMOUR = 3,\n\tITEM_HEALTH = 4,\n\tITEM_RADAR = 8\n};\n\n// Thanks for vague name, R*\nenum DRAW_FADE_STATE\n{\n\tHUD_WANTED_FADING = 0,\n\tHUD_ENERGY_FADING,\n\tHUD_SCORE_FADING,\n\tHUD_WEAPON_FADING,\n};\n\n// My name\nenum eFadeOperation\n{\n\tFADED_OUT = 0,\n\tSTART_FADE_OUT,\n\tFADING_IN,\n\tFADING_OUT,\n\tFADE_DISABLED = 5,\n};\n\nenum eSprites \n{\n\tHUD_FIST,\n\tHUD_SITEROCKET = 41,\n\tHUD_RADARDISC = 50,\n\tHUD_SITESNIPER = 63,\n\tHUD_SITEM16,\n\tHUD_SITELASER,\n\tHUD_LASERDOT,\n\tHUD_VIEWFINDER,\n\tHUD_BLEEDER,\n\tNUM_HUD_SPRITES = 69,\n};\n\nclass CHud\n{\npublic:\n\tstatic CSprite2d Sprites[NUM_HUD_SPRITES];\n\tstatic wchar m_HelpMessage[HELP_MSG_LENGTH];\n\tstatic wchar m_LastHelpMessage[HELP_MSG_LENGTH];\n\tstatic uint32 m_HelpMessageState;\n\tstatic uint32 m_HelpMessageTimer;\n\tstatic int32 m_HelpMessageFadeTimer;\n\tstatic wchar m_HelpMessageToPrint[HELP_MSG_LENGTH];\n\tstatic float m_HelpMessageDisplayTime;\n\tstatic bool m_HelpMessageDisplayForever;\n\tstatic bool\tm_HelpMessageQuick;\n\tstatic uint32 m_ZoneState;\n\tstatic int32 m_ZoneFadeTimer;\n\tstatic uint32 m_ZoneNameTimer;\n\tstatic wchar *m_pZoneName;\n\tstatic wchar *m_pLastZoneName;\n\tstatic wchar *m_ZoneToPrint;\n\tstatic wchar *m_VehicleName;\n\tstatic wchar *m_pLastVehicleName;\n\tstatic wchar *m_pVehicleNameToPrint;\n\tstatic uint32 m_VehicleState;\n\tstatic int32 m_VehicleFadeTimer;\n\tstatic uint32 m_VehicleNameTimer;\n\tstatic wchar m_Message[256];\n\tstatic wchar m_PagerMessage[256];\n\tstatic bool m_Wants_To_Draw_Hud;\n\tstatic bool m_Wants_To_Draw_3dMarkers;\n\tstatic wchar m_BigMessage[6][128];\n\tstatic int16 m_ItemToFlash;\n\tstatic bool m_HideRadar;\n\tstatic int32 m_ClockState;\n\n\t// These aren't really in CHud\n\tstatic float BigMessageInUse[6];\n\tstatic float BigMessageAlpha[6];\n\tstatic float BigMessageX[6];\n\tstatic float OddJob2OffTimer;\n\tstatic bool CounterOnLastFrame[NUMONSCREENCOUNTERS];\n\tstatic float OddJob2XOffset;\n\tstatic uint16 CounterFlashTimer[NUMONSCREENCOUNTERS];\n\tstatic uint16 OddJob2Timer;\n\tstatic bool TimerOnLastFrame;\n\tstatic int16 OddJob2On;\n\tstatic uint16 TimerFlashTimer;\n\tstatic int16 PagerSoundPlayed;\n\tstatic int32 SpriteBrightness;\n\tstatic float PagerXOffset;\n\tstatic int16 PagerTimer;\n\tstatic int16 PagerOn;\n\n\tstatic uint32 m_WantedFadeTimer;\n\tstatic uint32 m_WantedState;\n\tstatic uint32 m_WantedTimer;\n\tstatic uint32 m_EnergyLostFadeTimer;\n\tstatic uint32 m_EnergyLostState;\n\tstatic uint32 m_EnergyLostTimer;\n\tstatic uint32 m_DisplayScoreFadeTimer;\n\tstatic uint32 m_DisplayScoreState;\n\tstatic uint32 m_DisplayScoreTimer;\n\tstatic uint32 m_WeaponFadeTimer;\n\tstatic uint32 m_WeaponState;\n\tstatic uint32 m_WeaponTimer;\n\n\tstatic uint32 m_LastDisplayScore;\n\tstatic uint32 m_LastWanted;\n\tstatic uint32 m_LastWeapon;\n\tstatic uint32 m_LastTimeEnergyLost;\n\npublic:\n\tstatic void Draw();\n\tstatic void DrawAfterFade();\n\tstatic void GetRidOfAllHudMessages();\n#ifdef RELOADABLES\n\tstatic void ReloadTXD();\n#endif\n\tstatic void Initialise();\n\tstatic void ReInitialise();\n\tstatic void SetBigMessage(wchar *message, uint16 style);\n\tstatic void SetHelpMessage(wchar *message, bool quick, bool displayForever = false);\n\tstatic bool IsHelpMessageBeingDisplayed(void);\n\tstatic void SetMessage(wchar *message);\n\tstatic void SetPagerMessage(wchar *message);\n\tstatic void SetVehicleName(wchar *name);\n\tstatic void SetZoneName(wchar *name);\n\tstatic void Shutdown();\n\tstatic float DrawFadeState(DRAW_FADE_STATE, int);\n\tstatic void ResetWastedText(void);\n};\n"
  },
  {
    "path": "src/render/Instance.cpp",
    "content": "#include \"common.h\"\n\n#include \"Instance.h\"\n\nvoid\nCInstance::Shutdown()\n{\n\tGetMatrix().Detach();\n}\n"
  },
  {
    "path": "src/render/Instance.h",
    "content": "#pragma once\n\n#include \"Placeable.h\"\n\n// unused\n\nclass CInstance : public CPlaceable\n{\npublic:\n\tint m_modelIndex;\npublic:\n\t~CInstance() { }\n\tvoid Shutdown();\n};\n"
  },
  {
    "path": "src/render/Lines.cpp",
    "content": "#include \"common.h\"\n\n#include \"main.h\"\n#include \"Lines.h\"\n\n// This is super inefficient, why split the line into segments at all?\nvoid\nCLines::RenderLineWithClipping(float x1, float y1, float z1, float x2, float y2, float z2, uint32 c1, uint32 c2)\n{\n\tstatic RwIm3DVertex v[2];\n#ifdef THIS_IS_STUPID\n\tint i;\n\tfloat f1, f2;\n\tfloat len = sqrt(sq(x1-x2) + sq(y1-y2) + sq(z1-z2));\n\tint numsegs = len/1.5f + 1.0f;\n\n\tRwRGBA col1;\n\tcol1.red = c1>>24;\n\tcol1.green = c1>>16;\n\tcol1.blue = c1>>8;\n\tcol1.alpha = c1;\n\tRwRGBA col2;\n\tcol2.red = c2>>24;\n\tcol2.green = c2>>16;\n\tcol2.blue = c2>>8;\n\tcol2.alpha = c2;\n\n\tfloat dx = x2 - x1;\n\tfloat dy = y2 - y1;\n\tfloat dz = z2 - z1;\n\tfor(i = 0; i < numsegs; i++){\n\t\tf1 = (float)i/numsegs;\n\t\tf2 = (float)(i+1)/numsegs;\n\n\t\tRwIm3DVertexSetRGBA(&v[0], (int)(col1.red + (col2.red-col1.red)*f1),\n\t\t\t(int)(col1.green + (col2.green-col1.green)*f1),\n\t\t\t(int)(col1.blue + (col2.blue-col1.blue)*f1),\n\t\t\t(int)(col1.alpha + (col2.alpha-col1.alpha)*f1));\n\t\tRwIm3DVertexSetRGBA(&v[1], (int)(col1.red + (col2.red-col1.red)*f2),\n\t\t\t(int)(col1.green + (col2.green-col1.green)*f2),\n\t\t\t(int)(col1.blue + (col2.blue-col1.blue)*f2),\n\t\t\t(int)(col1.alpha + (col2.alpha-col1.alpha)*f2));\n\t\tRwIm3DVertexSetPos(&v[0], x1 + dx*f1, y1 + dy*f1, z1 + dz*f1);\n\t\tRwIm3DVertexSetPos(&v[1], x1 + dx*f2, y1 + dy*f2, z1 + dz*f2);\n\n\t\tLittleTest();\n\t\tif(RwIm3DTransform(v, 2, nil, 0)){\n\t\t\tRwIm3DRenderLine(0, 1);\n\t\t\tRwIm3DEnd();\n\t\t}\n\t}\n#else\n\tRwRGBA col1;\n\tcol1.red = c1>>24;\n\tcol1.green = c1>>16;\n\tcol1.blue = c1>>8;\n\tcol1.alpha = c1;\n\tRwRGBA col2;\n\tcol2.red = c2>>24;\n\tcol2.green = c2>>16;\n\tcol2.blue = c2>>8;\n\tcol2.alpha = c2;\n\n\tRwIm3DVertexSetRGBA(&v[0], col1.red, col1.green, col1.blue, col1.alpha);\n\tRwIm3DVertexSetRGBA(&v[1], col2.red, col2.green, col2.blue, col2.alpha);\n\tRwIm3DVertexSetPos(&v[0], x1, y1, z1);\n\tRwIm3DVertexSetPos(&v[1], x2, y2, z2);\n\tLittleTest();\n\tif(RwIm3DTransform(v, 2, nil, 0)){\n\t\tRwIm3DRenderLine(0, 1);\n\t\tRwIm3DEnd();\n\t}\n#endif\n}\n"
  },
  {
    "path": "src/render/Lines.h",
    "content": "#pragma once\n\nclass CLines\n{\npublic:\n\tstatic void RenderLineWithClipping(float x1, float y1, float z1, float x2, float y2, float z2, uint32 c1, uint32 c2);\n};\n"
  },
  {
    "path": "src/render/MBlur.cpp",
    "content": "#ifndef LIBRW\n#define WITHD3D\n#endif\n#include \"common.h\"\n#ifndef LIBRW\n#include <d3d8caps.h>\n#endif\n\n#include \"main.h\"\n#include \"General.h\"\n#include \"RwHelper.h\"\n#include \"Camera.h\"\n#include \"Timecycle.h\"\n#include \"Particle.h\"\n#include \"Timer.h\"\n#include \"Hud.h\"\n#include \"Frontend.h\"\n#include \"MBlur.h\"\n#include \"postfx.h\"\n\n// Originally taken from RW example 'mblur'\n\nRwRaster *CMBlur::pFrontBuffer;\nbool CMBlur::ms_bJustInitialised;\nbool CMBlur::ms_bScaledBlur;\nbool CMBlur::BlurOn;\nfloat CMBlur::Drunkness;\n\nint32 CMBlur::pBufVertCount;\n\nstatic RwIm2DVertex Vertex[4];\nstatic RwIm2DVertex Vertex2[4];\nstatic RwImVertexIndex Index[6] = { 0, 1, 2, 0, 2, 3 };\n\n#ifndef LIBRW\nextern \"C\" D3DCAPS8 _RwD3D8DeviceCaps;\n#endif\nRwBool\nCMBlur::MotionBlurOpen(RwCamera *cam)\n{\n#ifdef EXTENDED_COLOURFILTER\n\tCPostFX::Open(cam);\n\treturn TRUE;\n#else\n#ifdef GTA_PS2\n\tRwRect rect = {0, 0, 0, 0};\n\t\n\tif (pFrontBuffer)\n\t\treturn TRUE;\n\t\n\tBlurOn = true;\n\t\n\trect.w = RwRasterGetWidth(RwCameraGetRaster(cam));\n\trect.h = RwRasterGetHeight(RwCameraGetRaster(cam));\n\t\n\tpFrontBuffer = RwRasterCreate(0, 0, 0, rwRASTERDONTALLOCATE|rwRASTERTYPECAMERATEXTURE);\n\tif (!pFrontBuffer)\n\t{\n\t\tprintf(\"Error creating raster\\n\");\n\t\treturn FALSE;\n\t}\n\t\n\tRwRaster *raster = RwRasterSubRaster(pFrontBuffer, RwCameraGetRaster(cam), &rect);\n\tif (!raster)\n\t{\n\t\tRwRasterDestroy(pFrontBuffer);\n\t\tpFrontBuffer = NULL;\n\t\tprintf(\"Error subrastering\\n\");\n\t\treturn FALSE;\n\t}\n\t\n\tCreateImmediateModeData(cam, &rect);\n#else\n\tRwRect rect = { 0, 0, 0, 0 };\n\n\tif(pFrontBuffer)\n\t\tMotionBlurClose();\n\t\n#ifndef LIBRW\n\textern void _GetVideoMemInfo(LPDWORD total, LPDWORD avaible);\n\tDWORD total, avaible;\n\t\n\t_GetVideoMemInfo(&total, &avaible);\n\tdebug(\"Available video memory %d\\n\", avaible);\n#endif\n\t\t\n\tif(BlurOn)\n\t{\n\t\tuint32 width  = Pow(2.0f, int32(log2(RwRasterGetWidth (RwCameraGetRaster(cam))))+1);\n\t\tuint32 height = Pow(2.0f, int32(log2(RwRasterGetHeight(RwCameraGetRaster(cam))))+1);\n\t\tuint32 depth  = RwRasterGetDepth(RwCameraGetRaster(cam));\n\t\t\n#ifndef LIBRW\n\t\textern DWORD _dwMemTotalVideo;\n\t\tif ( _RwD3D8DeviceCaps.MaxTextureWidth >= width && _RwD3D8DeviceCaps.MaxTextureHeight >= height )\n\t\t{\n\t\t\ttotal = _dwMemTotalVideo - 3 *\n\t\t\t\t( RwRasterGetDepth(RwCameraGetRaster(cam))\n\t\t\t\t* RwRasterGetHeight(RwCameraGetRaster(cam))\n\t\t\t\t* RwRasterGetWidth(RwCameraGetRaster(cam)) / 8 );\n\t\t\tBlurOn = total >= height*width*(depth/8) + (12*1024*1024) /*12 MB*/;\n\t\t}\n\t\telse\n\t\t\tBlurOn = false;\n#endif\n\t\t\n\t\tif ( BlurOn )\n\t\t{\n\t\t\tms_bScaledBlur = false;\n\t\t\trect.w = width;\n\t\t\trect.h = height;\n\t\t\t\n\t\t\tpFrontBuffer = RwRasterCreate(rect.w, rect.h, depth, rwRASTERTYPECAMERATEXTURE);\n\t\t\tif ( !pFrontBuffer )\n\t\t\t{\n\t\t\t\tdebug(\"MBlurOpen can't create raster.\");\n\t\t\t\tBlurOn = false;\n\t\t\t\trect.w = RwRasterGetWidth(RwCameraGetRaster(cam));\n\t\t\t\trect.h = RwRasterGetHeight(RwCameraGetRaster(cam));\n\t\t\t}\n\t\t\telse\n\t\t\t\tms_bJustInitialised = true;\n\t\t}\n\t\telse\n\t\t{\n\t\t\trect.w = RwRasterGetWidth(RwCameraGetRaster(cam));\n\t\t\trect.h = RwRasterGetHeight(RwCameraGetRaster(cam));\n\t\t}\n\t\t\n#ifndef LIBRW\n\t\t_GetVideoMemInfo(&total, &avaible);\n\t\tdebug(\"Available video memory %d\\n\", avaible);\n#endif\n\t\tCreateImmediateModeData(cam, &rect);\n\t}\n\telse\n\t{\n\t\trect.w = RwRasterGetWidth(RwCameraGetRaster(cam));\n\t\trect.h = RwRasterGetHeight(RwCameraGetRaster(cam));\n\t\tCreateImmediateModeData(cam, &rect);\n\t}\n\t\n\treturn TRUE;\n#endif\n#endif\n}\n\nRwBool\nCMBlur::MotionBlurClose(void)\n{\n#ifdef EXTENDED_COLOURFILTER\n\tCPostFX::Close();\n#else\n\tif(pFrontBuffer){\n\t\tRwRasterDestroy(pFrontBuffer);\n\t\tpFrontBuffer = nil;\n\t\t\n\t\treturn TRUE;\n\t}\n#endif\n\treturn FALSE;\n}\n\nvoid\nCMBlur::CreateImmediateModeData(RwCamera *cam, RwRect *rect)\n{\n\tfloat zero, xmax, ymax;\n\n\tif(RwRasterGetDepth(RwCameraGetRaster(cam)) == 16){\n\t\tzero = HALFPX;\n\t\txmax = rect->w + HALFPX;\n\t\tymax = rect->h + HALFPX;\n\t}else{\n\t\tzero = -HALFPX;\n\t\txmax = rect->w - HALFPX;\n\t\tymax = rect->h - HALFPX;\n\t}\n\n\tRwIm2DVertexSetScreenX(&Vertex[0], zero);\n\tRwIm2DVertexSetScreenY(&Vertex[0], zero);\n\tRwIm2DVertexSetScreenZ(&Vertex[0], RwIm2DGetNearScreenZ());\n\tRwIm2DVertexSetCameraZ(&Vertex[0], RwCameraGetNearClipPlane(cam));\n\tRwIm2DVertexSetRecipCameraZ(&Vertex[0], 1.0f/RwCameraGetNearClipPlane(cam));\n\tRwIm2DVertexSetU(&Vertex[0], 0.0f, 1.0f/RwCameraGetNearClipPlane(cam));\n\tRwIm2DVertexSetV(&Vertex[0], 0.0f, 1.0f/RwCameraGetNearClipPlane(cam));\n\tRwIm2DVertexSetIntRGBA(&Vertex[0], 255, 255, 255, 255);\n\n\tRwIm2DVertexSetScreenX(&Vertex[1], zero);\n\tRwIm2DVertexSetScreenY(&Vertex[1], ymax);\n\tRwIm2DVertexSetScreenZ(&Vertex[1], RwIm2DGetNearScreenZ());\n\tRwIm2DVertexSetCameraZ(&Vertex[1], RwCameraGetNearClipPlane(cam));\n\tRwIm2DVertexSetRecipCameraZ(&Vertex[1], 1.0f/RwCameraGetNearClipPlane(cam));\n\tRwIm2DVertexSetU(&Vertex[1], 0.0f, 1.0f/RwCameraGetNearClipPlane(cam));\n\tRwIm2DVertexSetV(&Vertex[1], 1.0f, 1.0f/RwCameraGetNearClipPlane(cam));\n\tRwIm2DVertexSetIntRGBA(&Vertex[1], 255, 255, 255, 255);\n\n\tRwIm2DVertexSetScreenX(&Vertex[2], xmax);\n\tRwIm2DVertexSetScreenY(&Vertex[2], ymax);\n\tRwIm2DVertexSetScreenZ(&Vertex[2], RwIm2DGetNearScreenZ());\n\tRwIm2DVertexSetCameraZ(&Vertex[2], RwCameraGetNearClipPlane(cam));\n\tRwIm2DVertexSetRecipCameraZ(&Vertex[2], 1.0f/RwCameraGetNearClipPlane(cam));\n\tRwIm2DVertexSetU(&Vertex[2], 1.0f, 1.0f/RwCameraGetNearClipPlane(cam));\n\tRwIm2DVertexSetV(&Vertex[2], 1.0f, 1.0f/RwCameraGetNearClipPlane(cam));\n\tRwIm2DVertexSetIntRGBA(&Vertex[2], 255, 255, 255, 255);\n\n\tRwIm2DVertexSetScreenX(&Vertex[3], xmax);\n\tRwIm2DVertexSetScreenY(&Vertex[3], zero);\n\tRwIm2DVertexSetScreenZ(&Vertex[3], RwIm2DGetNearScreenZ());\n\tRwIm2DVertexSetCameraZ(&Vertex[3], RwCameraGetNearClipPlane(cam));\n\tRwIm2DVertexSetRecipCameraZ(&Vertex[3], 1.0f/RwCameraGetNearClipPlane(cam));\n\tRwIm2DVertexSetU(&Vertex[3], 1.0f, 1.0f/RwCameraGetNearClipPlane(cam));\n\tRwIm2DVertexSetV(&Vertex[3], 0.0f, 1.0f/RwCameraGetNearClipPlane(cam));\n\tRwIm2DVertexSetIntRGBA(&Vertex[3], 255, 255, 255, 255);\n\n\n\tRwIm2DVertexSetScreenX(&Vertex2[0], zero + 2.0f);\n\tRwIm2DVertexSetScreenY(&Vertex2[0], zero + 2.0f);\n\tRwIm2DVertexSetScreenZ(&Vertex2[0], RwIm2DGetNearScreenZ());\n\tRwIm2DVertexSetCameraZ(&Vertex2[0], RwCameraGetNearClipPlane(cam));\n\tRwIm2DVertexSetRecipCameraZ(&Vertex2[0], 1.0f/RwCameraGetNearClipPlane(cam));\n\tRwIm2DVertexSetU(&Vertex2[0], 0.0f, 1.0f/RwCameraGetNearClipPlane(cam));\n\tRwIm2DVertexSetV(&Vertex2[0], 0.0f, 1.0f/RwCameraGetNearClipPlane(cam));\n\tRwIm2DVertexSetIntRGBA(&Vertex2[0], 255, 255, 255, 255);\n\n\tRwIm2DVertexSetScreenX(&Vertex2[1], 2.0f);\n\tRwIm2DVertexSetScreenY(&Vertex2[1], ymax + 2.0f);\n\tRwIm2DVertexSetScreenZ(&Vertex2[1], RwIm2DGetNearScreenZ());\n\tRwIm2DVertexSetCameraZ(&Vertex2[1], RwCameraGetNearClipPlane(cam));\n\tRwIm2DVertexSetRecipCameraZ(&Vertex2[1], 1.0f/RwCameraGetNearClipPlane(cam));\n\tRwIm2DVertexSetU(&Vertex2[1], 0.0f, 1.0f/RwCameraGetNearClipPlane(cam));\n\tRwIm2DVertexSetV(&Vertex2[1], 1.0f, 1.0f/RwCameraGetNearClipPlane(cam));\n\tRwIm2DVertexSetIntRGBA(&Vertex2[1], 255, 255, 255, 255);\n\n\tRwIm2DVertexSetScreenX(&Vertex2[2], xmax + 2.0f);\n\tRwIm2DVertexSetScreenY(&Vertex2[2], ymax + 2.0f);\n\tRwIm2DVertexSetScreenZ(&Vertex2[2], RwIm2DGetNearScreenZ());\n\tRwIm2DVertexSetCameraZ(&Vertex2[2], RwCameraGetNearClipPlane(cam));\n\tRwIm2DVertexSetRecipCameraZ(&Vertex2[2], 1.0f/RwCameraGetNearClipPlane(cam));\n\tRwIm2DVertexSetU(&Vertex2[2], 1.0f, 1.0f/RwCameraGetNearClipPlane(cam));\n\tRwIm2DVertexSetV(&Vertex2[2], 1.0f, 1.0f/RwCameraGetNearClipPlane(cam));\n\tRwIm2DVertexSetIntRGBA(&Vertex2[2], 255, 255, 255, 255);\n\n\tRwIm2DVertexSetScreenX(&Vertex2[3], xmax + 2.0f);\n\tRwIm2DVertexSetScreenY(&Vertex2[3], zero + 2.0f);\n\tRwIm2DVertexSetScreenZ(&Vertex2[3], RwIm2DGetNearScreenZ());\n\tRwIm2DVertexSetCameraZ(&Vertex2[3], RwCameraGetNearClipPlane(cam));\n\tRwIm2DVertexSetRecipCameraZ(&Vertex2[3], 1.0f/RwCameraGetNearClipPlane(cam));\n\tRwIm2DVertexSetU(&Vertex2[3], 1.0f, 1.0f/RwCameraGetNearClipPlane(cam));\n\tRwIm2DVertexSetV(&Vertex2[3], 0.0f, 1.0f/RwCameraGetNearClipPlane(cam));\n\tRwIm2DVertexSetIntRGBA(&Vertex2[3], 255, 255, 255, 255);\n}\n\nvoid\nCMBlur::CreateImmediateModeData(RwCamera *cam, RwRect *rect, RwIm2DVertex *verts, RwRGBA color, float u1Off, float v1Off, float u2Off, float v2Off, float z, int fullTexture)\n{\n\tfloat x1 = rect->x;\n\tfloat y1 = rect->y;\n\tfloat x2 = rect->w;\n\tfloat y2 = rect->h;\n\n\tfloat u1, v1, u2, v2;\n\tif(fullTexture){\n\t\tu1 = 0.0f;\n\t\tv1 = 0.0f;\n\t\tu2 = 1.0f;\n\t\tv2 = 1.0f;\n\t}else{\n\t\tif(RwRasterGetDepth(RwCameraGetRaster(cam)) == 16){\n\t\t\tx1 += HALFPX;\n\t\t\ty1 += HALFPX;\n\t\t\tx2 += HALFPX;\n\t\t\ty2 += HALFPX;\n\t\t}else{\n\t\t\tx1 -= HALFPX;\n\t\t\ty1 -= HALFPX;\n\t\t\tx2 -= HALFPX;\n\t\t\ty2 -= HALFPX;\n\t\t}\n\n\t\tint32 width  = Pow(2.0f, int32(log2(RwRasterGetWidth (RwCameraGetRaster(cam))))+1);\n\t\tint32 height = Pow(2.0f, int32(log2(RwRasterGetHeight(RwCameraGetRaster(cam))))+1);\n\t\tu1 = x1/width + u1Off;\n\t\tv1 = y1/height + v1Off;\n\t\tu2 = x2/width + u2Off;\n\t\tv2 = y2/height + v2Off;\n\t\tu1 = clamp(u1, 0.0f, 1.0f);\n\t\tv1 = clamp(v1, 0.0f, 1.0f);\n\t\tu2 = clamp(u2, 0.0f, 1.0f);\n\t\tv2 = clamp(v2, 0.0f, 1.0f);\n\t}\n\n\tfloat recipz = 1.0f/z;\n\t// TODO: CameraZ is wrong, what should we do?\n\tRwIm2DVertexSetScreenX(&verts[0], x1);\n\tRwIm2DVertexSetScreenY(&verts[0], y1);\n\tRwIm2DVertexSetScreenZ(&verts[0], z);\n\tRwIm2DVertexSetCameraZ(&verts[0], RwCameraGetNearClipPlane(cam));\n\tRwIm2DVertexSetRecipCameraZ(&verts[0], recipz);\n\tRwIm2DVertexSetU(&verts[0], u1, recipz);\n\tRwIm2DVertexSetV(&verts[0], v1, recipz);\n\tRwIm2DVertexSetIntRGBA(&verts[0], color.red, color.green, color.blue, color.alpha);\n\n\tRwIm2DVertexSetScreenX(&verts[1], x1);\n\tRwIm2DVertexSetScreenY(&verts[1], y2);\n\tRwIm2DVertexSetScreenZ(&verts[1], z);\n\tRwIm2DVertexSetCameraZ(&verts[1], RwCameraGetNearClipPlane(cam));\n\tRwIm2DVertexSetRecipCameraZ(&verts[1], recipz);\n\tRwIm2DVertexSetU(&verts[1], u1, recipz);\n\tRwIm2DVertexSetV(&verts[1], v2, recipz);\n\tRwIm2DVertexSetIntRGBA(&verts[1], color.red, color.green, color.blue, color.alpha);\n\n\tRwIm2DVertexSetScreenX(&verts[2], x2);\n\tRwIm2DVertexSetScreenY(&verts[2], y2);\n\tRwIm2DVertexSetScreenZ(&verts[2], z);\n\tRwIm2DVertexSetCameraZ(&verts[2], RwCameraGetNearClipPlane(cam));\n\tRwIm2DVertexSetRecipCameraZ(&verts[2], recipz);\n\tRwIm2DVertexSetU(&verts[2], u2, recipz);\n\tRwIm2DVertexSetV(&verts[2], v2, recipz);\n\tRwIm2DVertexSetIntRGBA(&verts[2], color.red, color.green, color.blue, color.alpha);\n\n\tRwIm2DVertexSetScreenX(&verts[3], x2);\n\tRwIm2DVertexSetScreenY(&verts[3], y1);\n\tRwIm2DVertexSetScreenZ(&verts[3], z);\n\tRwIm2DVertexSetCameraZ(&verts[3], RwCameraGetNearClipPlane(cam));\n\tRwIm2DVertexSetRecipCameraZ(&verts[3], recipz);\n\tRwIm2DVertexSetU(&verts[3], u2, recipz);\n\tRwIm2DVertexSetV(&verts[3], v1, recipz);\n\tRwIm2DVertexSetIntRGBA(&verts[3], color.red, color.green, color.blue, color.alpha);\n}\n\nvoid\nCMBlur::MotionBlurRender(RwCamera *cam, uint32 red, uint32 green, uint32 blue, uint32 blur, int32 type, uint32 bluralpha)\n{\n#ifdef EXTENDED_COLOURFILTER\n\tCPostFX::Render(cam, red, green, blue, blur, type, bluralpha);\n#else\n\tPUSH_RENDERGROUP(\"CMBlur::MotionBlurRender\");\n\tRwRGBA color = { (RwUInt8)red, (RwUInt8)green, (RwUInt8)blue, (RwUInt8)blur };\n#ifdef GTA_PS2\n\tif( pFrontBuffer )\n\t\tOverlayRender(cam, pFrontBuffer, color, type, bluralpha);\n#else\n\tif(ms_bJustInitialised)\n\t\tms_bJustInitialised = false;\n\telse\n\t\tOverlayRender(cam, pFrontBuffer, color, type, bluralpha);\n\tif(BlurOn){\n\t\tRwRasterPushContext(pFrontBuffer);\n\t\tRwRasterRenderFast(RwCameraGetRaster(cam), 0, 0);\n\t\tRwRasterPopContext();\n\t}\n#endif\n\tPOP_RENDERGROUP();\n#endif\n}\n\nstatic uint8 DrunkBlurRed = 128;\nstatic uint8 DrunkBlurGreen = 128;\nstatic uint8 DrunkBlurBlue = 128;\nstatic int32 DrunkBlurIncrement = 1;\n\nvoid\nCMBlur::OverlayRender(RwCamera *cam, RwRaster *raster, RwRGBA color, int32 type, int32 bluralpha)\n{\n\tint r, g, b, a;\n\n\tr = color.red;\n\tg = color.green;\n\tb = color.blue;\n\ta = color.alpha;\n\n\tDefinedState();\n\n\tswitch(type)\n\t{\n\tcase MOTION_BLUR_SECURITY_CAM:\n\t\tr = 0;\n\t\tg = 255;\n\t\tb = 0;\n\t\ta = 128;\n\t\tbreak;\n\tcase MOTION_BLUR_INTRO:\n\t\tr = 100;\n\t\tg = 220;\n\t\tb = 230;\n\t\ta = 158;\n\t\tbreak;\n\tcase MOTION_BLUR_INTRO2:\n\t\tr = 80;\n\t\tg = 255;\n\t\tb = 230;\n\t\ta = 138;\n\t\tbreak;\n\tcase MOTION_BLUR_INTRO3:\n\t\tr = 255;\n\t\tg = 60;\n\t\tb = 60;\n\t\ta = 200;\n\t\tbreak;\n\tcase MOTION_BLUR_INTRO4:\n\t\tr = 255;\n\t\tg = 180;\n\t\tb = 180;\n\t\ta = 128;\n\t\tbreak;\n\t}\n\n\tif(!BlurOn){\n\t\t// gta clamps these to 255 (probably a macro or inlined function)\n\t\tint ovR = r * 0.6f;\n\t\tint ovG = g * 0.6f;\n\t\tint ovB = b * 0.6f;\n\t\tint ovA = type == MOTION_BLUR_SNIPER ? a : a*0.6f;\n\t\tRwIm2DVertexSetIntRGBA(&Vertex[0], ovR, ovG, ovB, ovA);\n\t\tRwIm2DVertexSetIntRGBA(&Vertex[1], ovR, ovG, ovB, ovA);\n\t\tRwIm2DVertexSetIntRGBA(&Vertex[2], ovR, ovG, ovB, ovA);\n\t\tRwIm2DVertexSetIntRGBA(&Vertex[3], ovR, ovG, ovB, ovA);\n\t}else{\n\t\tRwIm2DVertexSetIntRGBA(&Vertex2[0], r, g, b, a);\n\t\tRwIm2DVertexSetIntRGBA(&Vertex[0], r, g, b, a);\n\t\tRwIm2DVertexSetIntRGBA(&Vertex2[1], r, g, b, a);\n\t\tRwIm2DVertexSetIntRGBA(&Vertex[1], r, g, b, a);\n\t\tRwIm2DVertexSetIntRGBA(&Vertex2[2], r, g, b, a);\n\t\tRwIm2DVertexSetIntRGBA(&Vertex[2], r, g, b, a);\n\t\tRwIm2DVertexSetIntRGBA(&Vertex2[3], r, g, b, a);\n\t\tRwIm2DVertexSetIntRGBA(&Vertex[3], r, g, b, a);\n\t}\n\n\tRwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERNEAREST);\n\tRwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE);\n\tRwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE);\n\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);\n\n\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, raster);\n\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);\n\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE);\n\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE);\n\n\tif(BlurOn){\n\t\tif(type == MOTION_BLUR_SNIPER){\n\t\t\tRwIm2DVertexSetIntRGBA(&Vertex2[0], r, g, b, 80);\n\t\t\tRwIm2DVertexSetIntRGBA(&Vertex2[1], r, g, b, 80);\n\t\t\tRwIm2DVertexSetIntRGBA(&Vertex2[2], r, g, b, 80);\n\t\t\tRwIm2DVertexSetIntRGBA(&Vertex2[3], r, g, b, 80);\n\t\t\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);\n\t\t\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);\n\t\t\tpBufVertCount = 0;\n\t\t}else{\n\t\t\tRwIm2DVertexSetIntRGBA(&Vertex2[0], r*2, g*2, b*2, 30);\n\t\t\tRwIm2DVertexSetIntRGBA(&Vertex2[1], r*2, g*2, b*2, 30);\n\t\t\tRwIm2DVertexSetIntRGBA(&Vertex2[2], r*2, g*2, b*2, 30);\n\t\t\tRwIm2DVertexSetIntRGBA(&Vertex2[3], r*2, g*2, b*2, 30);\n\t\t\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);\n\t\t\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);\n\n\t\t\tRwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, Vertex2, 4, Index, 6);\n\n\t\t\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE);\n\t\t\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE);\n\n\t\t\tRwIm2DVertexSetIntRGBA(&Vertex2[0], r, g, b, a);\n\t\t\tRwIm2DVertexSetIntRGBA(&Vertex[0], r, g, b, a);\n\t\t\tRwIm2DVertexSetIntRGBA(&Vertex2[1], r, g, b, a);\n\t\t\tRwIm2DVertexSetIntRGBA(&Vertex[1], r, g, b, a);\n\t\t\tRwIm2DVertexSetIntRGBA(&Vertex2[2], r, g, b, a);\n\t\t\tRwIm2DVertexSetIntRGBA(&Vertex[2], r, g, b, a);\n\t\t\tRwIm2DVertexSetIntRGBA(&Vertex2[3], r, g, b, a);\n\t\t\tRwIm2DVertexSetIntRGBA(&Vertex[3], r, g, b, a);\n\t\t\tRwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, Vertex, 4, Index, 6);\n\t\t\tRwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, Vertex2, 4, Index, 6);\n\t\t}\n\t}\n\n\tint DrunkBlurAlpha = 175.0f * Drunkness;\n\tif(DrunkBlurAlpha != 0){\n\t\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);\n\t\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);\n\t\tif(BlurOn){\n\t\t\tRwIm2DVertexSetIntRGBA(&Vertex[0], 255, 255, 255, DrunkBlurAlpha);\n\t\t\tRwIm2DVertexSetIntRGBA(&Vertex[1], 255, 255, 255, DrunkBlurAlpha);\n\t\t\tRwIm2DVertexSetIntRGBA(&Vertex[2], 255, 255, 255, DrunkBlurAlpha);\n\t\t\tRwIm2DVertexSetIntRGBA(&Vertex[3], 255, 255, 255, DrunkBlurAlpha);\n\t\t}else{\n\t\t\tRwIm2DVertexSetIntRGBA(&Vertex[0], DrunkBlurRed, DrunkBlurGreen, DrunkBlurBlue, DrunkBlurAlpha);\n\t\t\tRwIm2DVertexSetIntRGBA(&Vertex[1], DrunkBlurRed, DrunkBlurGreen, DrunkBlurBlue, DrunkBlurAlpha);\n\t\t\tRwIm2DVertexSetIntRGBA(&Vertex[2], DrunkBlurRed, DrunkBlurGreen, DrunkBlurBlue, DrunkBlurAlpha);\n\t\t\tRwIm2DVertexSetIntRGBA(&Vertex[3], DrunkBlurRed, DrunkBlurGreen, DrunkBlurBlue, DrunkBlurAlpha);\n\t\t\tif(DrunkBlurIncrement){\n\t\t\t\tif(DrunkBlurRed < 255) DrunkBlurRed++;\n\t\t\t\tif(DrunkBlurGreen < 255) DrunkBlurGreen++;\n\t\t\t\tif(DrunkBlurBlue < 255) DrunkBlurBlue++;\n\t\t\t\tif(DrunkBlurRed == 255)\n\t\t\t\t\tDrunkBlurIncrement = 0;\n\t\t\t}else{\n\t\t\t\tif(DrunkBlurRed > 128) DrunkBlurRed--;\n\t\t\t\tif(DrunkBlurGreen > 128) DrunkBlurGreen--;\n\t\t\t\tif(DrunkBlurBlue > 128) DrunkBlurBlue--;\n\t\t\t\tif(DrunkBlurRed == 128)\n\t\t\t\t\tDrunkBlurIncrement = 1;\n\t\t\t}\n\t\t}\n\t\tRwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, Vertex, 4, Index, 6);\n\t}\n\n\tif(type != MOTION_BLUR_SNIPER)\n\t\tOverlayRenderFx(cam, pFrontBuffer);\n\n\tRwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE);\n\tRwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);\n\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);\n\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil);\n\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);\n\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);\n\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);\n}\n\nvoid\nCMBlur::SetDrunkBlur(float drunkness)\n{\n\tDrunkness = clamp(drunkness, 0.0f, 1.0f);\n}\n\nvoid\nCMBlur::ClearDrunkBlur()\n{\n\tDrunkness = 0.0f;\n\tCTimer::SetTimeScale(1.0f);\n}\n\n#define NUM_RENDER_FX 64\n\nstatic RwRect fxRect[NUM_RENDER_FX];\nstatic FxType fxType[NUM_RENDER_FX];\nstatic float fxZ[NUM_RENDER_FX];\n\nbool\nCMBlur::PosInside(RwRect *rect, float x1, float y1, float x2, float y2)\n{\n\tif((rect->x < x1 - 10.0f || rect->x > x2 + 10.0f || rect->y < y1 - 10.0f || rect->y > y2 + 10.0f) &&\n\t   (rect->w < x1 - 10.0f || rect->w > x2 + 10.0f || rect->h < y1 - 10.0f || rect->h > y2 + 10.0f) &&\n\t   (rect->x < x1 - 10.0f || rect->x > x2 + 10.0f || rect->h < y1 - 10.0f || rect->h > y2 + 10.0f) &&\n\t   (rect->w < x1 - 10.0f || rect->w > x2 + 10.0f || rect->y < y1 - 10.0f || rect->y > y2 + 10.0f))\n\t\treturn false;\n\treturn true;\n}\n\nbool\nCMBlur::AddRenderFx(RwCamera *cam, RwRect *rect, float z, FxType type)\n{\n\tif(pBufVertCount >= NUM_RENDER_FX)\n\t\treturn false;\n\n\trect->x = Max(rect->x, 0);\n\trect->y = Max(rect->y, 0);\n\trect->w = Min(rect->w, SCREEN_WIDTH);\n\trect->h = Min(rect->h, SCREEN_HEIGHT);\n\tif(rect->x >= rect->w || rect->y >= rect->h)\n\t\treturn false;\n\n\tswitch(type){\n\tcase FXTYPE_WATER1:\n\tcase FXTYPE_WATER2:\n\tcase FXTYPE_BLOOD1:\n\tcase FXTYPE_BLOOD2:\n\tcase FXTYPE_HEATHAZE:\t// code seems to be duplicated for this case\n\t\tfor(int i = 0; i < pBufVertCount; i++)\n\t\t\tif(fxType[i] == type && PosInside(rect, fxRect[i].x-10.0f, fxRect[i].y-10.0f, fxRect[i].w+10.0f, fxRect[i].h+10.0f))\n\t\t\t\treturn false;\n\t\t// TODO: fix aspect ratio scaling\n\t\t// radar\n\t\tif(PosInside(rect, 40.0f, SCREEN_SCALE_FROM_BOTTOM(116.0f), 40.0f + SCREEN_SCALE_X(94.0f), SCREEN_SCALE_FROM_BOTTOM(116.0f - 76.0f)))\n\t\t\treturn false;\n\t\t// HUD\n\t\tif(PosInside(rect, 400.0f, 0.0f, SCREEN_WIDTH, 90.0f))\n\t\t\treturn false;\n\t\t// vehicle name\n\t\tif(CHud::m_VehicleState != 0 && PosInside(rect, SCREEN_WIDTH/2, 350.0f, SCREEN_WIDTH, SCREEN_HEIGHT))\n\t\t\treturn false;\n\t\t// zone name\n\t\tif(CHud::m_ZoneState != 0 && PosInside(rect, SCREEN_WIDTH/2, 350.0f, SCREEN_WIDTH, SCREEN_HEIGHT))\n\t\t\treturn false;\n\t\tbreak;\n\t}\n\n\tfxRect[pBufVertCount] = *rect;\n\tfxZ[pBufVertCount] = z;\n\tfxType[pBufVertCount] = type;\n\tpBufVertCount++;\n\n\treturn true;\n}\n\nvoid\nCMBlur::OverlayRenderFx(RwCamera *cam, RwRaster *frontBuf)\n{\n\tbool drawWaterDrops = false;\n\tRwIm2DVertex verts[4];\n\tint red = (0.75f*CTimeCycle::GetDirectionalRed() + CTimeCycle::GetAmbientRed())*0.55f * 255;\n\tint green = (0.75f*CTimeCycle::GetDirectionalGreen() + CTimeCycle::GetAmbientGreen())*0.55f * 255;\n\tint blue = (0.75f*CTimeCycle::GetDirectionalBlue() + CTimeCycle::GetAmbientBlue())*0.55f * 255;\n\tred = clamp(red, 0, 255);\n\tgreen = clamp(green, 0, 255);\n\tblue = clamp(blue, 0, 255);\n\n\tRwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);\n\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);\n\n#ifdef LIBRW\n\trw::SetRenderState(rw::STENCILENABLE, TRUE);\n#else\n\tRwD3D8SetRenderState(D3DRS_STENCILENABLE, TRUE);\n#endif\n\n\tfor(int i = 0; i < pBufVertCount; i++)\n\t\tswitch(fxType[i]){\n\t\tcase FXTYPE_WATER1:\n\t\tcase FXTYPE_WATER2:\n\t\tcase FXTYPE_BLOOD1:\n\t\tcase FXTYPE_BLOOD2: {\n\t\t\tdrawWaterDrops = true;\n\t\t\tint32 width  = Pow(2.0f, int32(log2(RwRasterGetWidth (RwCameraGetRaster(cam))))+1);\n\t\t\tint32 height = Pow(2.0f, int32(log2(RwRasterGetHeight(RwCameraGetRaster(cam))))+1);\n\n\t\t\tfloat u1Off = (fxRect[i].w - fxRect[i].x)/width;\n\t\t\tfloat u2Off = u1Off - (fxRect[i].w - fxRect[i].x + 0.5f)*0.66f/width;\n\t\t\tfloat halfHeight = (fxRect[i].h - fxRect[i].y + 0.5f)*0.25f/height;\n\n\t\t\tif(RwRasterGetDepth(RwCameraGetRaster(cam)) == 16){\n\t\t\t\tif(fxType[i] == FXTYPE_BLOOD1 || fxType[i] == FXTYPE_BLOOD2)\n\t\t\t\t\tCreateImmediateModeData(cam, &fxRect[i], verts, CRGBA(255, 0, 0, 128), 0.0f, 0.0f, 0.0f, 0.0f, fxZ[i], true);\n\t\t\t\telse\n\t\t\t\t\tCreateImmediateModeData(cam, &fxRect[i], verts, CRGBA(32, 32, 32, 225), 0.0f, 0.0f, 0.0f, 0.0f, fxZ[i], true);\n\t\t\t}else{\n\t\t\t\tCreateImmediateModeData(cam, &fxRect[i], verts, CRGBA(32, 32, 32, 225), 0.0f, 0.0f, 0.0f, 0.0f, fxZ[i], true);\n\t\t\t}\n\n\t\t\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, gpDotRaster);\n#ifdef LIBRW\n\t\t\trw::SetRenderState(rw::STENCILFUNCTION, rw::STENCILALWAYS);\n\t\t\trw::SetRenderState(rw::STENCILFUNCTIONREF, 1);\n\t\t\trw::SetRenderState(rw::STENCILFUNCTIONMASK, 0xFFFFFFFF);\n\t\t\trw::SetRenderState(rw::STENCILFUNCTIONWRITEMASK, 0xFFFFFFFF);\n\t\t\trw::SetRenderState(rw::STENCILZFAIL, rw::STENCILKEEP);\n\t\t\trw::SetRenderState(rw::STENCILFAIL, rw::STENCILKEEP);\n\t\t\trw::SetRenderState(rw::STENCILPASS, rw::STENCILREPLACE);\n#else\n\t\t\tRwD3D8SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS);\n\t\t\tRwD3D8SetRenderState(D3DRS_STENCILREF, 1);\n\t\t\tRwD3D8SetRenderState(D3DRS_STENCILMASK, 0xFFFFFFFF);\n\t\t\tRwD3D8SetRenderState(D3DRS_STENCILWRITEMASK, 0xFFFFFFFF);\n\t\t\tRwD3D8SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_KEEP);\n\t\t\tRwD3D8SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP);\n\t\t\tRwD3D8SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE);\n#endif\n\t\t\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);\n\t\t\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE);\n\t\t\tRwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, verts, 4, Index, 6);\n\n\t\t\tif(RwRasterGetDepth(RwCameraGetRaster(cam)) != 16){\n\t\t\t\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, frontBuf);\n#ifdef LIBRW\n\t\t\t\trw::SetRenderState(rw::STENCILFUNCTION, rw::STENCILEQUAL);\n\t\t\t\trw::SetRenderState(rw::STENCILPASS, rw::STENCILKEEP);\n#else\n\t\t\t\tRwD3D8SetRenderState(D3DRS_STENCILFUNC, D3DCMP_EQUAL);\n\t\t\t\tRwD3D8SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_KEEP);\n#endif\n\t\t\t\tif(BlurOn){\n\t\t\t\t\tif(fxType[i] == FXTYPE_BLOOD1 || fxType[i] == FXTYPE_BLOOD2)\n\t\t\t\t\t\tCreateImmediateModeData(cam, &fxRect[i], verts, CRGBA(255, 0, 0, 255), u1Off, 0.0f+halfHeight, u2Off, 0.0f-halfHeight, fxZ[i], false);\n\t\t\t\t\telse\n\t\t\t\t\t\tCreateImmediateModeData(cam, &fxRect[i], verts, CRGBA(225, 225, 225, 160), u1Off, 0.0f+halfHeight, u2Off, 0.0f-halfHeight, fxZ[i], false);\n\t\t\t\t\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDDESTALPHA);\n\t\t\t\t\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVDESTALPHA);\n\t\t\t\t}else{\n\t\t\t\t\tif(fxType[i] == FXTYPE_BLOOD1 || fxType[i] == FXTYPE_BLOOD2)\n\t\t\t\t\t\tCreateImmediateModeData(cam, &fxRect[i], verts, CRGBA(255, 0, 0, 128), u1Off, 0.0f+halfHeight, u2Off, 0.0f-halfHeight, fxZ[i], false);\n\t\t\t\t\telse\n\t\t\t\t\t\tCreateImmediateModeData(cam, &fxRect[i], verts, CRGBA(128, 128, 128, 32), u1Off, 0.0f+halfHeight, u2Off, 0.0f-halfHeight, fxZ[i], false);\n\t\t\t\t\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);\n\t\t\t\t\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);\n\t\t\t\t}\n\t\t\t\tRwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, verts, 4, Index, 6);\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tcase FXTYPE_SPLASH1:\n\t\tcase FXTYPE_SPLASH2:\n\t\tcase FXTYPE_SPLASH3:\n\t\t\tdrawWaterDrops = true;\n\t\t\tbreak;\n\n\t\tcase FXTYPE_HEATHAZE:\n\t\t\tif(TheCamera.GetScreenFadeStatus() == FADE_0 && frontBuf){\n\t\t\t\tint alpha = FrontEndMenuManager.m_PrefsBrightness > 255 ?\n\t\t\t\t\tFrontEndMenuManager.m_PrefsBrightness - 90 :\n\t\t\t\t\tFrontEndMenuManager.m_PrefsBrightness - 130;\n\t\t\t\talpha = clamp(alpha, 16, 200)/2;\n\n\t\t\t\tCreateImmediateModeData(cam, &fxRect[i], verts, CRGBA(0, 0, 0, alpha), 0.0f, 0.0f, 0.0f, 0.0f, fxZ[i], true);\n\t\t\t\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, gpHeatHazeRaster);\n#ifdef LIBRW\n\t\t\t\trw::SetRenderState(rw::STENCILFUNCTION, rw::STENCILALWAYS);\n\t\t\t\trw::SetRenderState(rw::STENCILFUNCTIONREF, 1);\n\t\t\t\trw::SetRenderState(rw::STENCILFUNCTIONMASK, 0xFFFFFFFF);\n\t\t\t\trw::SetRenderState(rw::STENCILFUNCTIONWRITEMASK, 0xFFFFFFFF);\n\t\t\t\trw::SetRenderState(rw::STENCILZFAIL, rw::STENCILKEEP);\n\t\t\t\trw::SetRenderState(rw::STENCILFAIL, rw::STENCILKEEP);\n\t\t\t\trw::SetRenderState(rw::STENCILPASS, rw::STENCILREPLACE);\n#else\n\t\t\t\tRwD3D8SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS);\n\t\t\t\tRwD3D8SetRenderState(D3DRS_STENCILREF, 1);\n\t\t\t\tRwD3D8SetRenderState(D3DRS_STENCILMASK, 0xFFFFFFFF);\n\t\t\t\tRwD3D8SetRenderState(D3DRS_STENCILWRITEMASK, 0xFFFFFFFF);\n\t\t\t\tRwD3D8SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_KEEP);\n\t\t\t\tRwD3D8SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP);\n\t\t\t\tRwD3D8SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE);\n#endif\n\t\t\t\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);\n\t\t\t\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE);\n\t\t\t\tRwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, verts, 4, Index, 6);\n\n\t\t\t\tCreateImmediateModeData(cam, &fxRect[i], verts, CRGBA(255, 255, 255, alpha),\n\t\t\t\t\tCGeneral::GetRandomNumberInRange(-0.002f, 0.002f),\n\t\t\t\t\tCGeneral::GetRandomNumberInRange(-0.002f, 0.002f),\n\t\t\t\t\tCGeneral::GetRandomNumberInRange(-0.002f, 0.002f),\n\t\t\t\t\tCGeneral::GetRandomNumberInRange(-0.002f, 0.002f),\n\t\t\t\t\tfxZ[i], false);\n\t\t\t\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, frontBuf);\n#ifdef LIBRW\n\t\t\t\trw::SetRenderState(rw::STENCILFUNCTION, rw::STENCILEQUAL);\n\t\t\t\trw::SetRenderState(rw::STENCILPASS, rw::STENCILKEEP);\n#else\n\t\t\t\tRwD3D8SetRenderState(D3DRS_STENCILFUNC, D3DCMP_EQUAL);\n\t\t\t\tRwD3D8SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_KEEP);\n#endif\n\t\t\t\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);\n\t\t\t\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);\n\t\t\t\tRwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, verts, 4, Index, 6);\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n#ifdef LIBRW\n\trw::SetRenderState(rw::STENCILENABLE, FALSE);\n#else\n\tRwD3D8SetRenderState(D3DRS_STENCILENABLE, FALSE);\n#endif\n\n\tif(drawWaterDrops){\n\t\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);\n\t\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE);\n\n\t\t// Draw drops\n\t\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, gpRainDripRaster[0]);\n\t\tfor(int i = 0; i < pBufVertCount; i++)\n\t\t\tif(fxType[i] == FXTYPE_WATER1 || fxType[i] == FXTYPE_BLOOD1){\n\t\t\t\tCreateImmediateModeData(cam, &fxRect[i], verts, CRGBA(red, green, blue, fxType[i] == FXTYPE_BLOOD1 ? 255 : 192),\n\t\t\t\t\t0.0f, 0.0f, 0.0f, 0.0f, fxZ[i], true);\n\t\t\t\tRwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, verts, 4, Index, 6);\n\t\t\t}\n\t\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, gpRainDripRaster[1]);\n\t\tfor(int i = 0; i < pBufVertCount; i++)\n\t\t\tif(fxType[i] == FXTYPE_WATER2 || fxType[i] == FXTYPE_BLOOD2){\n\t\t\t\tCreateImmediateModeData(cam, &fxRect[i], verts, CRGBA(red, green, blue, fxType[i] == FXTYPE_BLOOD2 ? 255 : 192),\n\t\t\t\t\t0.0f, 0.0f, 0.0f, 0.0f, fxZ[i], true);\n\t\t\t\tRwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, verts, 4, Index, 6);\n\t\t\t}\n\n\t\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, gpCarSplashRaster[0]);\n\t\tfor(int i = 0; i < pBufVertCount; i++)\n\t\t\tif(fxType[i] == FXTYPE_SPLASH1 || fxType[i] == FXTYPE_SPLASH2 || fxType[i] == FXTYPE_SPLASH3){\n\t\t\t\tCreateImmediateModeData(cam, &fxRect[i], verts, CRGBA(200, 200, 200, 255),\n\t\t\t\t\t0.0f, 0.0f, 0.0f, 0.0f, fxZ[i], true);\n\t\t\t\tRwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, verts, 4, Index, 6);\n\t\t\t}\n\n\t\t// Darken the water drops\n\t\tint alpha = 192*0.5f;\n\t\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);\n\t\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);\n\n\t\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, gpRainDripDarkRaster[0]);\n\t\tfor(int i = 0; i < pBufVertCount; i++)\n\t\t\tif(fxType[i] == FXTYPE_WATER1){\n\t\t\t\tCreateImmediateModeData(cam, &fxRect[i], verts, CRGBA(red, green, blue, alpha),\n\t\t\t\t\t0.0f, 0.0f, 0.0f, 0.0f, fxZ[i], true);\n\t\t\t\tRwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, verts, 4, Index, 6);\n\t\t\t}\n\t\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, gpRainDripDarkRaster[1]);\n\t\tfor(int i = 0; i < pBufVertCount; i++)\n\t\t\tif(fxType[i] == FXTYPE_WATER2){\n\t\t\t\tCreateImmediateModeData(cam, &fxRect[i], verts, CRGBA(red, green, blue, alpha),\n\t\t\t\t\t0.0f, 0.0f, 0.0f, 0.0f, fxZ[i], true);\n\t\t\t\tRwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, verts, 4, Index, 6);\n\t\t\t}\n\t}\n\n\tRwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE);\n\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);\n\tpBufVertCount = 0;\n}\n"
  },
  {
    "path": "src/render/MBlur.h",
    "content": "#pragma once\n\nenum FxType\n{\n\tFXTYPE_WATER1,\n\tFXTYPE_WATER2,\n\tFXTYPE_BLOOD1,\n\tFXTYPE_BLOOD2,\n\tFXTYPE_HEATHAZE,\n\tFXTYPE_SPLASH1,\n\tFXTYPE_SPLASH2,\n\tFXTYPE_SPLASH3\n};\n\nclass CMBlur\n{\npublic:\n\tstatic RwRaster *pFrontBuffer;\n\tstatic bool ms_bJustInitialised;\n\tstatic bool ms_bScaledBlur;\n\tstatic bool BlurOn;\n\tstatic float Drunkness;\n\n\tstatic int32 pBufVertCount;\n\npublic:\n\tstatic RwBool MotionBlurOpen(RwCamera *cam);\n\tstatic RwBool MotionBlurClose(void);\n\tstatic void CreateImmediateModeData(RwCamera *cam, RwRect *rect);\n\tstatic void CreateImmediateModeData(RwCamera *cam, RwRect *rect, RwIm2DVertex *verts, RwRGBA color, float u1Off, float v1Off, float u2Off, float v2Off, float z, int fullTexture);\n\tstatic void MotionBlurRender(RwCamera *cam, uint32 red, uint32 green, uint32 blue, uint32 blur, int32 type, uint32 bluralpha);\n\tstatic void OverlayRender(RwCamera *cam, RwRaster *raster, RwRGBA color, int32 type, int32 bluralpha);\n\tstatic void SetDrunkBlur(float drunkness);\n\tstatic void ClearDrunkBlur();\n\t\n\tstatic bool PosInside(RwRect *rect, float x1, float y1, float x2, float y2);\n\tstatic bool AddRenderFx(RwCamera *cam, RwRect *rect, float z, FxType type);\n\tstatic void OverlayRenderFx(RwCamera *cam, RwRaster *frontBuf);\n};\n"
  },
  {
    "path": "src/render/Occlusion.cpp",
    "content": "#include \"common.h\"\n\n#include \"main.h\"\n#include \"Entity.h\"\n#include \"Occlusion.h\"\n#include \"Game.h\"\n#include \"Camera.h\"\n#include \"Vector.h\"\n#include \"Draw.h\"\n#include \"Timer.h\"\n#include \"RwHelper.h\"\n#include \"VarConsole.h\"\n\nint32 COcclusion::NumOccludersOnMap;\nint16 COcclusion::FarAwayList;\nint16 COcclusion::NearbyList;\nint16 COcclusion::ListWalkThroughFA;\nint16 COcclusion::PreviousListWalkThroughFA;\nint16 COcclusion::NumActiveOccluders;\nCOccluder COcclusion::aOccluders[NUMOCCLUSIONVOLUMES];\nCActiveOccluder COcclusion::aActiveOccluders[NUMACTIVEOCCLUDERS];\n\nCVector gCenterOnScreen;\n\nfloat gMinYInOccluder;\nfloat gMinXInOccluder;\nfloat gMaxYInOccluder;\nfloat gMaxXInOccluder;\n\nbool gOccluderCoorsValid[8];\nCVector gOccluderCoorsOnScreen[8];\nCVector gOccluderCoors[8];\n\n#ifndef MASTER\nbool bDispayOccDebugStuff; // disPAY, yeah\n#endif\n\nvoid\nCOcclusion::Init(void)\n{\n\tNumOccludersOnMap = 0;\n#ifndef MASTER\n\tVarConsole.Add(\"Occlusion debug\", &bDispayOccDebugStuff, true);\n#endif\n\tFarAwayList = -1;\n\tNearbyList = -1;\n\tListWalkThroughFA = -1;\n\tPreviousListWalkThroughFA = -1;\n}\n\nvoid\nCOcclusion::AddOne(float x, float y, float z, float width, float length, float height, float angle)\n{\n\tif(NumOccludersOnMap >= NUMOCCLUSIONVOLUMES)\n\t\treturn;\n\n\taOccluders[NumOccludersOnMap].x = x;\n\taOccluders[NumOccludersOnMap].y = y;\n\taOccluders[NumOccludersOnMap].z = z;\n\taOccluders[NumOccludersOnMap].width = width;\n\taOccluders[NumOccludersOnMap].length = length;\n\taOccluders[NumOccludersOnMap].height = height;\n\twhile(angle < 0.0f) angle += 360.0f;\n\twhile(angle > 360.0f) angle -= 360.0f;\n\taOccluders[NumOccludersOnMap].angle = angle/360.0f * UINT16_MAX;\n\taOccluders[NumOccludersOnMap].listIndex = FarAwayList;\n\tFarAwayList = NumOccludersOnMap++;\n}\n\nbool \nCOccluder::NearCamera() {\n\treturn (TheCamera.GetPosition() - CVector(x, y, z)).Magnitude() - (Max(width, length) / 2.0f) < 250.0f;\n}\n\nbool\nDoesInfiniteLineCrossFiniteLine(float p1X, float p1Y, float p2X, float p2Y, float lineX, float lineY, float lineDX, float lineDY)\n{\n\tfloat side1 = (p1X - lineX) * lineDY - (p1Y - lineY) * lineDX;\n\tfloat side2 = (p2X - lineX) * lineDY - (p2Y - lineY) * lineDX;\n\treturn side1 * side2 < 0.0f;    // if points lie on opposite sides of the infinte line, the line between them crosses it\n}\n\nbool DoesInfiniteLineTouchScreen(float lineX, float lineY, float lineDX, float lineDY) {\n\tif (lineX > 0.0f && lineY > 0.0f && SCREEN_WIDTH > lineX && SCREEN_HEIGHT > lineY)\n\t\treturn true;\n\n\treturn (DoesInfiniteLineCrossFiniteLine(0.0f, 0.0f, SCREEN_WIDTH, 0.0f, lineX, lineY, lineDX, lineDY) ||\n\t\tDoesInfiniteLineCrossFiniteLine(0.0f, 0.0f, 0.0f, SCREEN_HEIGHT, lineX, lineY, lineDX, lineDY) ||\n\t\tDoesInfiniteLineCrossFiniteLine(SCREEN_WIDTH, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT, lineX, lineY, lineDX, lineDY) ||\n\t\tDoesInfiniteLineCrossFiniteLine(0.0f, SCREEN_HEIGHT, SCREEN_WIDTH, SCREEN_HEIGHT, lineX, lineY, lineDX, lineDY));\n}\n\nbool IsPointInsideLine(float lineX, float lineY, float lineDX, float lineDY, float pX, float pY, float area = 0.0f) {\n\treturn (pX - lineX) * lineDY - (pY - lineY) * lineDX >= area;\n}\n\nbool CalcScreenCoors(CVector const &in, CVector *out, float *outw, float *outh) {\n\t*out = TheCamera.m_viewMatrix * in;\n\n\tif (out->z <= 1.0f) return false;\n\t\n\tfloat recip = 1.0f / out->z;\n\tout->x *= SCREEN_WIDTH * recip;\n\tout->y *= SCREEN_HEIGHT * recip;\n\n\tfloat fovScale = DefaultFOV / CDraw::GetFOV();\n\n\t*outw = fovScale * recip * SCREEN_WIDTH;\n\t*outh = fovScale * recip * SCREEN_HEIGHT;\n\n\treturn true;\n}\n\nbool CalcScreenCoors(CVector const &in, CVector *out) {\n\t*out = TheCamera.m_viewMatrix * in;\n\n\tif (out->z <= 1.0f) return false;\n\n\tfloat recip = 1.0f / out->z;\n\tout->x *= SCREEN_WIDTH * recip;\n\tout->y *= SCREEN_HEIGHT * recip;\n\n\treturn true;\n}\n\nbool \nCOccluder::ProcessLineSegment(int corner1, int corner2, CActiveOccluder *occl) {\n\tif (!gOccluderCoorsValid[corner1] && !gOccluderCoorsValid[corner2])\n\t\treturn false;\n\n\tfloat x1, y1, x2, y2;\n\n\tCVector p1, p2;\n\tif (!gOccluderCoorsValid[corner1]) {\n\t\tfloat clipDist1 = Abs((TheCamera.m_viewMatrix * gOccluderCoors[corner1]).z - 1.1f);\n\t\tfloat clipDist2 = Abs((TheCamera.m_viewMatrix * gOccluderCoors[corner2]).z - 1.1f);\n\t\tfloat ratio = clipDist2 / (clipDist1 + clipDist2);\n\t\tCVector clippedCoors = (1.0f - ratio) * gOccluderCoors[corner2] + ratio * gOccluderCoors[corner1];\n\n\t\tif (!CalcScreenCoors(clippedCoors, &p1, &x1, &y1))\n\t\t\treturn true;\n\t}\n\telse {\n\t\tp1 = gOccluderCoorsOnScreen[corner1];\n\t}\n\n\tif (!gOccluderCoorsValid[corner2]) {\n\t\tfloat clipDist1 = Abs((TheCamera.m_viewMatrix * gOccluderCoors[corner1]).z - 1.1f);\n\t\tfloat clipDist2 = Abs((TheCamera.m_viewMatrix * gOccluderCoors[corner2]).z - 1.1f);\n\t\tfloat ratio = clipDist1 / (clipDist1 + clipDist2);\n\t\tCVector clippedCoors = (1.0f - ratio) * gOccluderCoors[corner2] + ratio * gOccluderCoors[corner1];\n\n\t\tif (!CalcScreenCoors(clippedCoors, &p2, &x2, &y2))\n\t\t\treturn true;\n\t}\n\telse {\n\t\tp2 = gOccluderCoorsOnScreen[corner2];\n\t}\n\n\tgMinXInOccluder = Min(Min(gMinXInOccluder, p1.x), p2.x);\n\tgMaxXInOccluder = Max(Max(gMaxXInOccluder, p1.x), p2.x);\n\tgMinYInOccluder = Min(Min(gMinYInOccluder, p1.y), p2.y);\n\tgMaxYInOccluder = Max(Max(gMaxYInOccluder, p1.y), p2.y);\n\n\tCVector2D origin = p1;\n\tCVector2D direction = p2 - p1;\n\n\t// Make sure lines are counter-clockwise around center\n\tif (!IsPointInsideLine(origin.x, origin.y, direction.x, direction.y, gCenterOnScreen.x, gCenterOnScreen.y, 0.0f)) {\n\t\torigin += direction;\n\t\tdirection *= -1.0f;\n\t}\n\n\tfloat magnitude = direction.Magnitude();\n\n\toccl->lines[occl->linesCount].origin = origin;\n\toccl->lines[occl->linesCount].direction = direction / magnitude;\n\toccl->lines[occl->linesCount].length = magnitude;\n\n\tif (!DoesInfiniteLineTouchScreen(origin.x, origin.y, direction.x, direction.y))\n\t\treturn !IsPointInsideLine(origin.x, origin.y, direction.x, direction.y, SCREEN_WIDTH / 2.0f, SCREEN_HEIGHT / 2.0f, 0.0f);\n\n\toccl->linesCount++;\n\t\n\treturn false;\n}\n\nbool \nCOccluder::ProcessOneOccluder(CActiveOccluder *occl) { \n\tfloat outX, outY;\n\n\toccl->linesCount = 0;\n\tCVector pos(x, y, z);\n\n\tif (!CalcScreenCoors(pos, &gCenterOnScreen, &outX, &outY) || gCenterOnScreen.z < -150.0f || gCenterOnScreen.z > 300.0f) {\n\t\treturn false;\n\t}\n\n\toccl->radius = Max(width, length) * 0.35f + gCenterOnScreen.z;\n\n\tCVector vec[3];\n\t\n\tvec[0].x = length / 2.0f * Sin(GetAngle());\n\tvec[0].y = -length / 2.0f * Cos(GetAngle());\n\tvec[0].z = 0.0f;\n\n\tvec[1].x = width / 2.0f * Cos(GetAngle());\n\tvec[1].y = width / 2.0f * Sin(GetAngle());\n\tvec[1].z = 0.0f;\n\n\tvec[2].x = 0.0f;\n\tvec[2].y = 0.0f;\n\tvec[2].z = height / 2.0f;\n\n\t// Figure out if we see the front or back of a face\n\tbool bFrontFace[6];\n\tfor (int i = 0; i < 3; i++) {\n\t\tbFrontFace[i*2+0] = DotProduct((pos + vec[i] - TheCamera.GetPosition()), vec[i]) < 0.0f;\n\t\tbFrontFace[i*2+1] = DotProduct((pos - vec[i] - TheCamera.GetPosition()), -vec[i]) < 0.0f;\n\t}\n\n\t//calculating vertices of a box\n\tgOccluderCoors[0] = pos + vec[0] + vec[1] + vec[2];\n\tgOccluderCoors[1] = pos - vec[0] + vec[1] + vec[2];\n\tgOccluderCoors[2] = pos + vec[0] - vec[1] + vec[2];\n\tgOccluderCoors[3] = pos - vec[0] - vec[1] + vec[2];\n\tgOccluderCoors[4] = pos + vec[0] + vec[1] - vec[2];\n\tgOccluderCoors[5] = pos - vec[0] + vec[1] - vec[2];\n\tgOccluderCoors[6] = pos + vec[0] - vec[1] - vec[2];\n\tgOccluderCoors[7] = pos - vec[0] - vec[1] - vec[2];\n\n\tfor(int i = 0; i < 8; i++)\n\t\tgOccluderCoorsValid[i] = CalcScreenCoors(gOccluderCoors[i], &gOccluderCoorsOnScreen[i], &outX, &outY);\n\n\tgMinYInOccluder = 999999.875f;\n\tgMinXInOccluder = 999999.875f;\n\tgMaxYInOccluder = -999999.875f;\n\tgMaxXInOccluder = -999999.875f;\n\n\t// Between two differently facing sides we see an edge, so process those\n\tif (bFrontFace[2] != bFrontFace[0] && ProcessLineSegment(0, 4, occl))\n\t\treturn false;\n\tif (bFrontFace[3] != bFrontFace[0] && ProcessLineSegment(2, 6, occl))\n\t\treturn false;\n\tif (bFrontFace[4] != bFrontFace[0] && ProcessLineSegment(0, 2, occl))\n\t\treturn false;\n\tif (bFrontFace[5] != bFrontFace[0] && ProcessLineSegment(4, 6, occl))\n\t\treturn false;\n\tif (bFrontFace[2] != bFrontFace[1] && ProcessLineSegment(1, 5, occl))\n\t\treturn false;\n\tif (bFrontFace[3] != bFrontFace[1] && ProcessLineSegment(3, 7, occl))\n\t\treturn false;\n\tif (bFrontFace[4] != bFrontFace[1] && ProcessLineSegment(1, 3, occl))\n\t\treturn false;\n\tif (bFrontFace[5] != bFrontFace[1] && ProcessLineSegment(5, 7, occl))\n\t\treturn false;\n\tif (bFrontFace[4] != bFrontFace[2] && ProcessLineSegment(0, 1, occl))\n\t\treturn false;\n\tif (bFrontFace[3] != bFrontFace[4] && ProcessLineSegment(2, 3, occl))\n\t\treturn false;\n\tif (bFrontFace[5] != bFrontFace[3] && ProcessLineSegment(6, 7, occl))\n\t\treturn false;\n\tif (bFrontFace[2] != bFrontFace[5] && ProcessLineSegment(4, 5, occl))\n\t\treturn false;\n\n\tif (gMaxXInOccluder - gMinXInOccluder < SCREEN_WIDTH * 0.1f ||\n\t\tgMaxYInOccluder - gMinYInOccluder < SCREEN_HEIGHT * 0.07f)\n\t\treturn false;\n\n\treturn true;\n}\n\nbool\nCOcclusion::OccluderHidesBehind(CActiveOccluder *occl1, CActiveOccluder *occl2) {\n\tfor (int i = 0; i < occl1->linesCount; i++) {\n\t\tfor (int j = 0; j < occl2->linesCount; j++) {\n\t\t\tif (!IsPointInsideLine(occl2->lines[j].origin.x, occl2->lines[j].origin.y, occl2->lines[j].direction.x,\n\t\t\t\toccl2->lines[j].direction.y, occl1->lines[i].origin.x, occl1->lines[i].origin.y, 0.0f)) \n\t\t\t\t\treturn false;\n\t\t\t\n\t\t\t\n\t\t\tif (!IsPointInsideLine(occl2->lines[j].origin.x, occl2->lines[j].origin.y, occl2->lines[j].direction.x,\n\t\t\t\toccl2->lines[j].direction.y, (occl1->lines[i].origin.x + occl1->lines[i].direction.x * occl1->lines[i].length),\n\t\t\t\t(occl1->lines[i].origin.y + occl1->lines[i].direction.y * occl1->lines[i].length), 0.0f)) \n\t\t\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn true;\n}\n\nvoid\nCOcclusion::ProcessBeforeRendering(void)\n{\n\tNumActiveOccluders = 0;\n\n#ifndef MASTER\n\tif (gbModelViewer)\n\t\treturn;\n#endif\n\n\tif (CGame::currArea != AREA_MAIN_MAP)\n\t\treturn;\n\n\tif (ListWalkThroughFA == -1) {\n\t\tPreviousListWalkThroughFA = -1;\n\t\tListWalkThroughFA = FarAwayList;\n\t}\n\n\tint i;\n\tfor (i = 0; i < 16 && ListWalkThroughFA != -1; i++) {\n\t\tif (aOccluders[ListWalkThroughFA].NearCamera()) {\n\t\t\tint prevListWalkThroughFA = ListWalkThroughFA;\n\n\t\t\tif (PreviousListWalkThroughFA == -1) {\n\t\t\t\tFarAwayList = aOccluders[ListWalkThroughFA].listIndex;\n\t\t\t}\n\t\t\telse {\n\t\t\t\taOccluders[PreviousListWalkThroughFA].listIndex = aOccluders[ListWalkThroughFA].listIndex;\n\t\t\t}\n\n\t\t\tint prevNearbyList = NearbyList;\n\t\t\tListWalkThroughFA = aOccluders[ListWalkThroughFA].listIndex;\n\t\t\tNearbyList = prevListWalkThroughFA;\n\t\t\taOccluders[prevListWalkThroughFA].listIndex = prevNearbyList;\n\t\t}\n\t\telse {\n\t\t\tPreviousListWalkThroughFA = ListWalkThroughFA;\n\t\t\tListWalkThroughFA = aOccluders[ListWalkThroughFA].listIndex;\n\t\t}\n\t}\n\n\tint prevNearbyList = -1;\n\tint tmpNearbyList = NearbyList;\n\tint indexTmpNearbyList, storeTmpNearbyList, prevFarAwayList;\n\twhile (tmpNearbyList != -1)\n\t{\n\t\tif (NumActiveOccluders < NUMACTIVEOCCLUDERS && aOccluders[tmpNearbyList].ProcessOneOccluder(&aActiveOccluders[NumActiveOccluders]))\n\t\t\t++NumActiveOccluders;\n\n\t\tindexTmpNearbyList = tmpNearbyList;\n\t\tif (aOccluders[indexTmpNearbyList].NearCamera())\n\t\t{\n\t\t\tprevNearbyList = tmpNearbyList;\n\t\t\ttmpNearbyList = aOccluders[indexTmpNearbyList].listIndex;\n\n\t\t}\n\t\telse\n\t\t{\n\t\t\tstoreTmpNearbyList = tmpNearbyList;\n\t\t\tif (prevNearbyList == -1) {\n\t\t\t\tNearbyList = aOccluders[indexTmpNearbyList].listIndex;\n\t\t\t}\n\t\t\telse {\n\t\t\t\taOccluders[prevNearbyList].listIndex = aOccluders[indexTmpNearbyList].listIndex;\n\t\t\t}\n\t\t\ttmpNearbyList = aOccluders[indexTmpNearbyList].listIndex;\n\t\t\tprevFarAwayList = FarAwayList;\n\t\t\tFarAwayList = storeTmpNearbyList;\n\t\t\taOccluders[storeTmpNearbyList].listIndex = prevFarAwayList;\n\t\t}\n\t}\n\n\tfor (i = 0; i < NumActiveOccluders; i++) {\n\t\tfor (int j = 0; j < NumActiveOccluders; j++) {\n\t\t\tif (i != j && aActiveOccluders[j].radius < aActiveOccluders[i].radius) {\n\t\t\t\tif (OccluderHidesBehind(&aActiveOccluders[i], &aActiveOccluders[j])) {\n\t\t\t\t\tfor (int k = i; k < NumActiveOccluders - 1; k++) {\n\t\t\t\t\t\tfor (int l = 0; l < aActiveOccluders[k + 1].linesCount; l++)\n\t\t\t\t\t\t\taActiveOccluders[k].lines[l] = aActiveOccluders[k + 1].lines[l];\n\t\t\t\t\t\taActiveOccluders[k].linesCount = aActiveOccluders[k + 1].linesCount;\n\t\t\t\t\t\taActiveOccluders[k].radius = aActiveOccluders[k + 1].radius;\n\t\t\t\t\t}\n\t\t\t\t\tNumActiveOccluders--;\n\t\t\t\t\ti--;\n\t\t\t\t\t// Taken from Mobile!\n#ifdef FIX_BUGS\n\t\t\t\t\tif (i == -1) {\n\t\t\t\t\t\ti = 0;\n\t\t\t\t\t}\n#endif\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nbool CActiveOccluder::IsPointWithinOcclusionArea(float pX, float pY, float area) {\n\tfor (int i = 0; i < linesCount; i++) {\n\t\tif (!IsPointInsideLine(lines[i].origin.x, lines[i].origin.y, lines[i].direction.x, lines[i].direction.y, pX, pY, area))\n\t\t\treturn false;\n\t}\n\n\treturn true;\n}\n\nbool COcclusion::IsAABoxOccluded(CVector pos, float width, float length, float height) {\n\n\tCVector coors;\n\tfloat outW, outH;\n\n\tif (!NumActiveOccluders || !CalcScreenCoors(pos, &coors, &outW, &outH))\n\t\treturn false;\n\n\tfloat side = CVector(width, length, height).Magnitude() / 4.0f;\n\tfloat area = Max(outW, outH) * side; \n\n\tCVector minCorner, maxCorner;\n\n\tminCorner.x = pos.x - width / 2.0f;\n\tminCorner.y = pos.y - length / 2.0f;\n\tminCorner.z = pos.z - height / 2.0f;\n\n\tmaxCorner.x = pos.x + width / 2.0f;\n\tmaxCorner.y = pos.y + length / 2.0f;\n\tmaxCorner.z = pos.z + height / 2.0f;\n\n\tfor (int i = 0; i < NumActiveOccluders; i++) {\n\t\tif (coors.z - (side * 0.85f) > aActiveOccluders[i].radius) {\n\t\t\tif (aActiveOccluders[i].IsPointWithinOcclusionArea(coors.x, coors.y, area))\n\t\t\t\treturn true;\n\n\t\t\tif (aActiveOccluders[i].IsPointWithinOcclusionArea(coors.x, coors.y, 0.0f)) {\n\t\t\t\tif (CalcScreenCoors(minCorner, &coors) && !aActiveOccluders[i].IsPointWithinOcclusionArea(coors.x, coors.y, 0.0f)) continue;\n\t\t\t\tif (CalcScreenCoors(CVector(maxCorner.x, maxCorner.y, minCorner.z), &coors) && !aActiveOccluders[i].IsPointWithinOcclusionArea(coors.x, coors.y, 0.0f)) continue;\n\t\t\t\tif (CalcScreenCoors(CVector(maxCorner.x, minCorner.y, maxCorner.z), &coors) && !aActiveOccluders[i].IsPointWithinOcclusionArea(coors.x, coors.y, 0.0f)) continue;\n\t\t\t\tif (CalcScreenCoors(CVector(minCorner.x, maxCorner.y, maxCorner.z), &coors, &outW, &outH) && !aActiveOccluders[i].IsPointWithinOcclusionArea(coors.x, coors.y, 0.0f)) continue;\n\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn false;\n}\n\nbool COcclusion::IsPositionOccluded(CVector pos, float side) {\n\n\tCVector coors;\n\tfloat width, height;\n\n\tif (!NumActiveOccluders || !CalcScreenCoors(pos, &coors, &width, &height))\n\t\treturn false;\n\n\tfloat area = Max(width, height) * side;\n\n\tfor (int i = 0; i < NumActiveOccluders; i++) {\n\t\tif (coors.z - (side * 0.85f) > aActiveOccluders[i].radius) \n\t\t\tif (aActiveOccluders[i].IsPointWithinOcclusionArea(coors.x, coors.y, area))\n\t\t\t\treturn true;\n\t}\n\n\treturn false;\n}\n\n#ifndef MASTER\n#include \"Lines.h\"\n\nRwIm2DVertex vertexbufferT[2];\n\nvoid COcclusion::Render() {\n\tif (!bDispayOccDebugStuff || !(CTimer::GetTimeInMilliseconds() & 0x200))\n\t\treturn;\n\n\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);\n\tRwRenderStateSet(rwRENDERSTATEZTESTENABLE, FALSE);\n\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);\n\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE);\n\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE);\n\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, FALSE);\n\n\tfloat recipz = 1.0f/RwCameraGetNearClipPlane(Scene.camera);\n\tfor (int i = 0; i < NumActiveOccluders; i++) {\n\t\tfor (int j = 0; j < aActiveOccluders[i].linesCount; j++) {\n\t\t\tRwIm2DVertexSetScreenX(&vertexbufferT[0], aActiveOccluders[i].lines[j].origin.x);\n\t\t\tRwIm2DVertexSetScreenY(&vertexbufferT[0], aActiveOccluders[i].lines[j].origin.y);\n\t\t\tRwIm2DVertexSetScreenZ(&vertexbufferT[0], RwIm2DGetNearScreenZ());\n\t\t\tRwIm2DVertexSetCameraZ(&vertexbufferT[0], RwCameraGetNearClipPlane(Scene.camera));\n\t\t\tRwIm2DVertexSetRecipCameraZ(&vertexbufferT[0], recipz);\n\n\t\t\tRwIm2DVertexSetScreenX(&vertexbufferT[1],\n\t\t\t\taActiveOccluders[i].lines[j].origin.x + aActiveOccluders[i].lines[j].direction.x * aActiveOccluders[i].lines[j].length);\n\t\t\tRwIm2DVertexSetScreenY(&vertexbufferT[1],\n\t\t\t\taActiveOccluders[i].lines[j].origin.y + aActiveOccluders[i].lines[j].direction.y * aActiveOccluders[i].lines[j].length);\n\t\t\tRwIm2DVertexSetScreenZ(&vertexbufferT[1], RwIm2DGetNearScreenZ());\n\t\t\tRwIm2DVertexSetCameraZ(&vertexbufferT[1], RwCameraGetNearClipPlane(Scene.camera));\n\t\t\tRwIm2DVertexSetRecipCameraZ(&vertexbufferT[1], recipz);\n\n\t\t\tRwIm2DVertexSetIntRGBA(&vertexbufferT[0], 255, 255, 0, 255);\n\t\t\tRwIm2DVertexSetIntRGBA(&vertexbufferT[1], 255, 255, 0, 255);\n\t\t\tRwIm2DRenderLine(vertexbufferT, 2, 0, 1);\n\t\t}\n\t}\n\n\tDefinedState();\n}\n#endif\n\nbool CEntity::IsEntityOccluded(void) {\n\n\tCVector coors;\n\tfloat width, height;\n\n\tif (COcclusion::NumActiveOccluders == 0 || !CalcScreenCoors(GetBoundCentre(), &coors, &width, &height))\n\t\treturn false;\n\n\tfloat area = Max(width, height) * GetBoundRadius() * 0.9f;\n\n\tfor (int i = 0; i < COcclusion::NumActiveOccluders; i++) {\n\t\tif (coors.z - (GetBoundRadius() * 0.85f) > COcclusion::aActiveOccluders[i].radius) {\n\t\t\tif (COcclusion::aActiveOccluders[i].IsPointWithinOcclusionArea(coors.x, coors.y, area)) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\tif (COcclusion::aActiveOccluders[i].IsPointWithinOcclusionArea(coors.x, coors.y, 0.0f)) {\n\t\t\t\tCVector min = m_matrix * CModelInfo::GetModelInfo(GetModelIndex())->GetColModel()->boundingBox.min;\n\t\t\t\tCVector max = m_matrix * CModelInfo::GetModelInfo(GetModelIndex())->GetColModel()->boundingBox.max;\n\n\t\t\t\tif (CalcScreenCoors(min, &coors) && !COcclusion::aActiveOccluders[i].IsPointWithinOcclusionArea(coors.x, coors.y, 0.0f)) continue;\n\t\t\t\tif (CalcScreenCoors(CVector(max.x, max.y, min.z), &coors) && !COcclusion::aActiveOccluders[i].IsPointWithinOcclusionArea(coors.x, coors.y, 0.0f)) continue;\n\t\t\t\tif (CalcScreenCoors(CVector(max.x, min.y, max.z), &coors) && !COcclusion::aActiveOccluders[i].IsPointWithinOcclusionArea(coors.x, coors.y, 0.0f)) continue;\n\t\t\t\tif (CalcScreenCoors(CVector(min.x, max.y, max.z), &coors) && !COcclusion::aActiveOccluders[i].IsPointWithinOcclusionArea(coors.x, coors.y, 0.0f)) continue;\n\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn false;\n}"
  },
  {
    "path": "src/render/Occlusion.h",
    "content": "#pragma once\n\nstruct ActiveOccluderLine {\n\tCVector2D origin;\n\tCVector2D direction;\n\tfloat length; \n};\n\nclass CActiveOccluder {\n\npublic:\n\tActiveOccluderLine lines[6];\n\tint32 linesCount;\n\tfloat radius; \n\n\tbool IsPointWithinOcclusionArea(float x, float y, float area);\n};\n\nclass COccluder\n{\npublic:\n\tint16 length, width, height;\n\tint16 x, y, z;\n\tuint16 angle;\n\tint16 listIndex;\n\n\tbool NearCamera();\n\tbool ProcessOneOccluder(CActiveOccluder *occl);\n\tbool ProcessLineSegment(int corner1, int corner2, CActiveOccluder* occl);\n\tfloat GetAngle(void) { return angle*TWOPI/UINT16_MAX; }\n};\n\nclass COcclusion\n{\npublic:\n\tstatic int32 NumOccludersOnMap;\n\tstatic int16 FarAwayList;\n\tstatic int16 NearbyList;\n\tstatic int16 ListWalkThroughFA;\n\tstatic int16 PreviousListWalkThroughFA;\n\tstatic int16 NumActiveOccluders;\n\n\tstatic COccluder aOccluders[NUMOCCLUSIONVOLUMES];\n\tstatic CActiveOccluder aActiveOccluders[NUMACTIVEOCCLUDERS];\n\n\tstatic void Init(void);\n\tstatic void AddOne(float x, float y, float z, float width, float length, float height, float angle);\n\tstatic void ProcessBeforeRendering(void); \n\tstatic bool OccluderHidesBehind(CActiveOccluder *occl1, CActiveOccluder *occl2);\n\tstatic bool IsAABoxOccluded(CVector pos, float width, float length, float height);\n\tstatic bool IsPositionOccluded(CVector pos, float side);\n#ifndef MASTER\n\tstatic void Render();\n#endif\n};\n\nbool CalcScreenCoors(CVector const &in, CVector *out, float *outw, float *outh);\nbool CalcScreenCoors(CVector const &in, CVector *out);\n\n#ifndef MASTER\nextern bool bDispayOccDebugStuff;\n#endif"
  },
  {
    "path": "src/render/Particle.cpp",
    "content": "#include \"common.h\"\n\n#include \"main.h\"\n#include \"General.h\"\n#include \"Timer.h\"\n#include \"TxdStore.h\"\n#include \"Sprite.h\"\n#include \"Camera.h\"\n#include \"Clock.h\"\n#include \"Collision.h\"\n#include \"World.h\"\n#include \"Shadows.h\"\n#include \"Replay.h\"\n#include \"Stats.h\"\n#include \"Weather.h\"\n#include \"MBlur.h\"\n#include \"main.h\"\n#include \"AudioScriptObject.h\"\n#include \"ParticleObject.h\"\n#include \"Particle.h\"\n#include \"soundlist.h\"\n\n\n#define MAX_PARTICLES_ON_SCREEN   (750)\n\n\n//(5)\n#define MAX_SMOKE_FILES           ARRAY_SIZE(SmokeFiles)\n\n//(5) \n#define MAX_RUBBER_FILES          ARRAY_SIZE(RubberFiles)\n//(5)\n#define MAX_RAINSPLASH_FILES      ARRAY_SIZE(RainSplashFiles)\n//(3)\n#define MAX_WATERSPRAY_FILES      ARRAY_SIZE(WatersprayFiles)\n//(6)\n#define MAX_EXPLOSIONMEDIUM_FILES ARRAY_SIZE(ExplosionMediumFiles)\n//(4)\n#define MAX_GUNFLASH_FILES        ARRAY_SIZE(GunFlashFiles)\n//(2)\n#define MAX_RAINSPLASHUP_FILES    ARRAY_SIZE(RainSplashupFiles)\n//(4)\n#define MAX_BIRDFRONT_FILES       ARRAY_SIZE(BirdfrontFiles)\n//(8)\n#define MAX_BOAT_FILES            ARRAY_SIZE(BoatFiles)\n//(4)\n#define MAX_CARDEBRIS_FILES       ARRAY_SIZE(CardebrisFiles)\n//(4)\n#define MAX_CARSPLASH_FILES       ARRAY_SIZE(CarsplashFiles)\n\n#define MAX_RAINDRIP_FILES       (2)\n\n#define MAX_LEAF_FILES           (2)\n\n\t\nconst char SmokeFiles[][6+1] =\n{\n\t\"smoke1\",\n\t\"smoke2\",\n\t\"smoke3\",\n\t\"smoke4\",\n\t\"smoke5\"\n};\n\n\nconst char RubberFiles[][7+1] =\n{\n\t\"rubber1\",\n\t\"rubber2\",\n\t\"rubber3\",\n\t\"rubber4\",\n\t\"rubber5\"\n};\n\nconst char RainSplashFiles[][7+1] =\n{\n\t\"splash1\",\n\t\"splash2\",\n\t\"splash3\",\n\t\"splash4\",\n\t\"splash5\"\n};\n\nconst char WatersprayFiles[][11+1] =\n{\n\t\"waterspray1\",\n\t\"waterspray2\",\n\t\"waterspray3\"\n};\n\nconst char ExplosionMediumFiles[][7+1] =\n{\n\t\"explo01\",\n\t\"explo02\",\n\t\"explo03\",\n\t\"explo04\",\n\t\"explo05\",\n\t\"explo06\"\n};\n\nconst char GunFlashFiles[][9+1] =\n{\n\t\"gunflash1\",\n\t\"gunflash2\",\n\t\"gunflash3\",\n\t\"gunflash4\"\n};\n\nconst char RainSplashupFiles[][10+1] =\n{\n\t\"splash_up1\",\n\t\"splash_up2\"\n};\n\nconst char BirdfrontFiles[][8+1] =\n{\n\t\"birdf_01\",\n\t\"birdf_02\",\n\t\"birdf_03\",\n\t\"birdf_04\"\n};\n\nconst char BoatFiles[][8+1] =\n{\n\t\"boats_01\",\n\t\"boats_02\",\n\t\"boats_03\",\n\t\"boats_04\",\n\t\"boats_05\",\n\t\"boats_06\",\n\t\"boats_07\",\n\t\"boats_08\"\n};\n\nconst char CardebrisFiles[][12+1] =\n{\n\t\"cardebris_01\",\n\t\"cardebris_02\",\n\t\"cardebris_03\",\n\t\"cardebris_04\"\n};\n\t\t\t\t\nconst char CarsplashFiles[][12+1] =\n{\n\t\"carsplash_01\",\n\t\"carsplash_02\",\n\t\"carsplash_03\",\n\t\"carsplash_04\"\n};\n\nCParticle gParticleArray[MAX_PARTICLES_ON_SCREEN];\n\nRwTexture *gpSmokeTex[MAX_SMOKE_FILES];\nRwTexture *gpSmoke2Tex;\nRwTexture *gpRubberTex[MAX_RUBBER_FILES];\nRwTexture *gpRainSplashTex[MAX_RAINSPLASH_FILES];\nRwTexture *gpWatersprayTex[MAX_WATERSPRAY_FILES];\nRwTexture *gpExplosionMediumTex[MAX_EXPLOSIONMEDIUM_FILES];\nRwTexture *gpGunFlashTex[MAX_GUNFLASH_FILES];\nRwTexture *gpRainSplashupTex[MAX_RAINSPLASHUP_FILES];\nRwTexture *gpBirdfrontTex[MAX_BIRDFRONT_FILES];\nRwTexture *gpBoatTex[MAX_BOAT_FILES];\nRwTexture *gpCarDebrisTex[MAX_CARDEBRIS_FILES];\nRwTexture *gpCarSplashTex[MAX_CARSPLASH_FILES];\n\nRwTexture *gpBoatWakeTex;\nRwTexture *gpFlame1Tex;\nRwTexture *gpFlame5Tex;\nRwTexture *gpRainDropSmallTex;\nRwTexture *gpBloodTex;\nRwTexture *gpLeafTex[MAX_LEAF_FILES];\nRwTexture *gpCloudTex1;\nRwTexture *gpCloudTex4;\nRwTexture *gpBloodSmallTex;\nRwTexture *gpGungeTex;\nRwTexture *gpCollisionSmokeTex;\nRwTexture *gpBulletHitTex;\nRwTexture *gpGunShellTex;\nRwTexture *gpPointlightTex;\n\nRwRaster  *gpSmokeRaster[MAX_SMOKE_FILES];\nRwRaster  *gpSmoke2Raster;\nRwRaster  *gpRubberRaster[MAX_RUBBER_FILES];\nRwRaster  *gpRainSplashRaster[MAX_RAINSPLASH_FILES];\nRwRaster  *gpWatersprayRaster[MAX_WATERSPRAY_FILES];\nRwRaster  *gpExplosionMediumRaster[MAX_EXPLOSIONMEDIUM_FILES];\nRwRaster  *gpGunFlashRaster[MAX_GUNFLASH_FILES];\nRwRaster  *gpRainSplashupRaster[MAX_RAINSPLASHUP_FILES];\nRwRaster  *gpBirdfrontRaster[MAX_BIRDFRONT_FILES];\nRwRaster  *gpBoatRaster[MAX_BOAT_FILES];\nRwRaster  *gpCarDebrisRaster[MAX_CARDEBRIS_FILES];\nRwRaster  *gpCarSplashRaster[MAX_CARSPLASH_FILES];\n\nRwRaster  *gpBoatWakeRaster;\nRwRaster  *gpFlame1Raster;\nRwRaster  *gpFlame5Raster;\nRwRaster  *gpRainDropSmallRaster;\nRwRaster  *gpBloodRaster;\nRwRaster  *gpLeafRaster[MAX_LEAF_FILES];\nRwRaster  *gpCloudRaster1;\nRwRaster  *gpCloudRaster4;\nRwRaster  *gpBloodSmallRaster;\nRwRaster  *gpGungeRaster;\nRwRaster  *gpCollisionSmokeRaster;\nRwRaster  *gpBulletHitRaster;\nRwRaster  *gpGunShellRaster;\nRwRaster  *gpPointlightRaster;\n\nRwTexture *gpRainDropTex;\nRwRaster  *gpRainDropRaster;\n\nRwTexture *gpSparkTex;\nRwTexture *gpNewspaperTex;\nRwTexture *gpGunSmokeTex;\nRwTexture *gpDotTex;\nRwTexture *gpHeatHazeTex;\nRwTexture *gpBeastieTex;\nRwTexture *gpRainDripTex[MAX_RAINDRIP_FILES];\nRwTexture *gpRainDripDarkTex[MAX_RAINDRIP_FILES];\n\nRwRaster *gpSparkRaster;\nRwRaster *gpNewspaperRaster;\nRwRaster *gpGunSmokeRaster;\nRwRaster *gpDotRaster;\nRwRaster *gpHeatHazeRaster;\nRwRaster *gpBeastieRaster;\nRwRaster *gpRainDripRaster[MAX_RAINDRIP_FILES];\nRwRaster *gpRainDripDarkRaster[MAX_RAINDRIP_FILES];\n\nfloat      CParticle::ms_afRandTable[CParticle::RAND_TABLE_SIZE];\nCParticle *CParticle::m_pUnusedListHead;\nfloat      CParticle::m_SinTable[CParticle::SIN_COS_TABLE_SIZE];\nfloat      CParticle::m_CosTable[CParticle::SIN_COS_TABLE_SIZE]; \n\nint32 Randomizer;\nint32 nParticleCreationInterval = 1;\nfloat PARTICLE_WIND_TEST_SCALE  = 0.002f;\nfloat fParticleScaleLimit       = 0.5f;\n\nbool clearWaterDrop;\nint32 numWaterDropOnScreen;\n\n#ifdef DEBUGMENU\nSETTWEAKPATH(\"Particle\");\nTWEAKINT32(nParticleCreationInterval, 0, 5, 1);\nTWEAKFLOAT(fParticleScaleLimit, 0.0f, 1.0f, 0.1f);\nTWEAKFUNC(CParticle::ReloadConfig);\n#endif\n\n\n\nvoid CParticle::ReloadConfig()\n{\n\tdebug(\"Initialising CParticleMgr...\");\n\t\n\tmod_ParticleSystemManager.Initialise();\n\t\n\tdebug(\"Initialising CParticle...\");\n\t\n\tm_pUnusedListHead = gParticleArray;\n\t\n\tfor ( int32 i = 0; i < MAX_PARTICLES_ON_SCREEN; i++ )\n\t{\n\t\tif ( i == MAX_PARTICLES_ON_SCREEN - 1 )\n\t\t\tgParticleArray[i].m_pNext = nil;\n\t\telse\n\t\t\tgParticleArray[i].m_pNext = &gParticleArray[i + 1];\n\t\t\n\t\tgParticleArray[i].m_vecPosition = CVector(0.0f, 0.0f, 0.0f);\n\n\t\tgParticleArray[i].m_vecVelocity = CVector(0.0f, 0.0f, 0.0f);\n\n\t\tgParticleArray[i].m_nTimeWhenWillBeDestroyed = 0;\n\n\t\tgParticleArray[i].m_nTimeWhenColorWillBeChanged = 0;\n\n\t\tgParticleArray[i].m_fSize = 0.2f;\n\n\t\tgParticleArray[i].m_fExpansionRate = 0.0f;\n\n\t\tgParticleArray[i].m_nColorIntensity = 255;\n\n\t\tgParticleArray[i].m_nFadeToBlackTimer = 0;\n\n\t\tgParticleArray[i].m_nAlpha = 255;\n\n\t\tgParticleArray[i].m_nFadeAlphaTimer = 0;\n\n\t\tgParticleArray[i].m_nCurrentZRotation = 0;\n\n\t\tgParticleArray[i].m_nZRotationTimer = 0;\n\n\t\tgParticleArray[i].m_fCurrentZRadius = 0.0f;\n\n\t\tgParticleArray[i].m_nZRadiusTimer = 0;\n\n\t\tgParticleArray[i].m_nCurrentFrame = 0;\n\n\t\tgParticleArray[i].m_nAnimationSpeedTimer = 0;\n\n\t\tgParticleArray[i].m_nRotation = 0;\n\n\t\tgParticleArray[i].m_nRotationStep = 0;\n\t}\n}\n\nvoid CParticle::Initialise()\n{\n\tReloadConfig();\n\n\tCParticleObject::Initialise();\n\n\tfloat randVal = -1.0f;\n\tfor ( int32 i = 0; i < RAND_TABLE_SIZE; i++ )\n\t{\n\t\tms_afRandTable[i] = randVal;\n\t\trandVal += 0.1f;\n\t}\n\t\n\tfor ( int32 i = 0; i < SIN_COS_TABLE_SIZE; i++ )\n\t{\t\t\n\t\tfloat angle = DEGTORAD(float(i) * float(360.0f / SIN_COS_TABLE_SIZE));\n\n\t\tm_SinTable[i] = ::Sin(angle);\n\t\tm_CosTable[i] = ::Cos(angle);\n\t}\n\t\n\tint32 slot = CTxdStore::FindTxdSlot(\"particle\");\n\n\tCTxdStore::PushCurrentTxd();\n\tCTxdStore::SetCurrentTxd(slot);\n\t\n\tfor ( int32 i = 0; i < MAX_SMOKE_FILES; i++ )\n\t{\n\t\tgpSmokeTex[i] = RwTextureRead(SmokeFiles[i], nil);\n\t\tgpSmokeRaster[i] = RwTextureGetRaster(gpSmokeTex[i]);\n\t}\n\t\n\tgpSmoke2Tex = RwTextureRead(\"smokeII_3\", nil);\n\tgpSmoke2Raster = RwTextureGetRaster(gpSmoke2Tex);\n\t\n\tfor ( int32 i = 0; i < MAX_RUBBER_FILES; i++ )\n\t{\n\t\tgpRubberTex[i] = RwTextureRead(RubberFiles[i], nil);\n\t\tgpRubberRaster[i] = RwTextureGetRaster(gpRubberTex[i]);\n\t}\n\t\n\tfor ( int32 i = 0; i < MAX_RAINSPLASH_FILES; i++ )\n\t{\n\t\tgpRainSplashTex[i] = RwTextureRead(RainSplashFiles[i], nil);\n\t\tgpRainSplashRaster[i] = RwTextureGetRaster(gpRainSplashTex[i]);\n\t}\n\t\n\tfor ( int32 i = 0; i < MAX_WATERSPRAY_FILES; i++ )\n\t{\n\t\tgpWatersprayTex[i] = RwTextureRead(WatersprayFiles[i], nil);\n\t\tgpWatersprayRaster[i] = RwTextureGetRaster(gpWatersprayTex[i]);\n\t}\n\t\n\tfor ( int32 i = 0; i < MAX_EXPLOSIONMEDIUM_FILES; i++ )\n\t{\n\t\tgpExplosionMediumTex[i] = RwTextureRead(ExplosionMediumFiles[i], nil);\n\t\tgpExplosionMediumRaster[i] = RwTextureGetRaster(gpExplosionMediumTex[i]);\n\t}\n\t\n\tfor ( int32 i = 0; i < MAX_GUNFLASH_FILES; i++ )\n\t{\n\t\tgpGunFlashTex[i] = RwTextureRead(GunFlashFiles[i], nil);\n\t\tgpGunFlashRaster[i] = RwTextureGetRaster(gpGunFlashTex[i]);\n\t}\n\t\n\tgpRainDropTex = RwTextureRead(\"raindrop4\", nil);\n\tgpRainDropRaster = RwTextureGetRaster(gpRainDropTex);\n\n\t\n\tfor ( int32 i = 0; i < MAX_RAINSPLASHUP_FILES; i++ )\n\t{\n\t\tgpRainSplashupTex[i] = RwTextureRead(RainSplashupFiles[i], nil);\n\t\tgpRainSplashupRaster[i] = RwTextureGetRaster(gpRainSplashupTex[i]);\n\t}\n\t\n\tfor ( int32 i = 0; i < MAX_BIRDFRONT_FILES; i++ )\n\t{\n\t\tgpBirdfrontTex[i] = RwTextureRead(BirdfrontFiles[i], nil);\n\t\tgpBirdfrontRaster[i] = RwTextureGetRaster(gpBirdfrontTex[i]);\n\t}\n\t\n\tfor ( int32 i = 0; i < MAX_BOAT_FILES; i++ )\n\t{\n\t\tgpBoatTex[i] = RwTextureRead(BoatFiles[i], nil);\n\t\tgpBoatRaster[i] = RwTextureGetRaster(gpBoatTex[i]);\n\t}\n\t\n\tfor ( int32 i = 0; i < MAX_CARDEBRIS_FILES; i++ )\n\t{\n\t\tgpCarDebrisTex[i] = RwTextureRead(CardebrisFiles[i], nil);\n\t\tgpCarDebrisRaster[i] = RwTextureGetRaster(gpCarDebrisTex[i]);\n\t}\n\t\n\tfor ( int32 i = 0; i < MAX_CARSPLASH_FILES; i++ )\n\t{\n\t\tgpCarSplashTex[i] = RwTextureRead(CarsplashFiles[i], nil);\n\t\tgpCarSplashRaster[i] = RwTextureGetRaster(gpCarSplashTex[i]);\n\t}\n\n\tgpBoatWakeTex = RwTextureRead(\"boatwake2\", nil);\n\tgpBoatWakeRaster = RwTextureGetRaster(gpBoatWakeTex);\n\t\n\tgpFlame1Tex = RwTextureRead(\"flame1\", nil);\n\tgpFlame1Raster = RwTextureGetRaster(gpFlame1Tex);\n\n\tgpFlame5Tex = RwTextureRead(\"flame5\", nil);\n\t\n//#ifdef FIX_BUGS\n#if 0\n\tgpFlame5Raster = RwTextureGetRaster(gpFlame5Tex);\n#else\n\t// this seems to have become more of a design choice\n\tgpFlame5Raster = RwTextureGetRaster(gpFlame1Tex);\t// copy-paste bug ?\n#endif\n\n\tgpRainDropSmallTex = RwTextureRead(\"rainsmall\", nil);\n\tgpRainDropSmallRaster = RwTextureGetRaster(gpRainDropSmallTex);\n\n\tgpBloodTex = RwTextureRead(\"blood\", nil);\n\tgpBloodRaster = RwTextureGetRaster(gpBloodTex);\n\n\tgpLeafTex[0] = RwTextureRead(\"gameleaf01_64\", nil);\n\tgpLeafRaster[0] = RwTextureGetRaster(gpLeafTex[0]);\n\t\n\tgpLeafTex[1] = RwTextureRead(\"letter\", nil);\n\tgpLeafRaster[1] = RwTextureGetRaster(gpLeafTex[1]);\n\n\tgpCloudTex1 = RwTextureRead(\"cloud3\", nil);\n\tgpCloudRaster1 = RwTextureGetRaster(gpCloudTex1);\n\n\tgpCloudTex4 = RwTextureRead(\"cloudmasked\", nil);\n\tgpCloudRaster4 = RwTextureGetRaster(gpCloudTex4);\n\n\tgpBloodSmallTex = RwTextureRead(\"bloodsplat2\", nil);\n\tgpBloodSmallRaster = RwTextureGetRaster(gpBloodSmallTex);\n\n\tgpGungeTex = RwTextureRead(\"gunge\", nil);\n\tgpGungeRaster = RwTextureGetRaster(gpGungeTex);\n\n\tgpCollisionSmokeTex = RwTextureRead(\"collisionsmoke\", nil);\n\tgpCollisionSmokeRaster = RwTextureGetRaster(gpCollisionSmokeTex);\n\n\tgpBulletHitTex = RwTextureRead(\"bullethitsmoke\", nil);\n\tgpBulletHitRaster = RwTextureGetRaster(gpBulletHitTex);\n\n\tgpGunShellTex = RwTextureRead(\"gunshell\", nil);\n\tgpGunShellRaster = RwTextureGetRaster(gpGunShellTex);\n\n\tgpPointlightTex = RwTextureRead(\"pointlight\", nil);\n\tgpPointlightRaster = RwTextureGetRaster(gpPointlightTex);\n\t\n\tgpSparkTex = RwTextureRead(\"spark\", nil);\n\tgpSparkRaster = RwTextureGetRaster(gpSparkTex);\n\t\n\tgpNewspaperTex = RwTextureRead(\"newspaper02_64\", nil);\n\tgpNewspaperRaster = RwTextureGetRaster(gpNewspaperTex);\n\t\n\tgpGunSmokeTex = RwTextureRead(\"gunsmoke3\", nil);\n\tgpGunSmokeRaster = RwTextureGetRaster(gpGunSmokeTex);\n\t\n\tgpDotTex = RwTextureRead(\"dot\", nil);\n\tgpDotRaster = RwTextureGetRaster(gpDotTex);\n\t\n\tgpHeatHazeTex = RwTextureRead(\"heathaze\", nil);\n\tgpHeatHazeRaster = RwTextureGetRaster(gpHeatHazeTex);\n\t\n\tgpBeastieTex = RwTextureRead(\"beastie\", nil);\n\tgpBeastieRaster = RwTextureGetRaster(gpBeastieTex);\n\t\n\tgpRainDripTex[0] = RwTextureRead(\"raindrip64\", nil);\n\tgpRainDripRaster[0] = RwTextureGetRaster(gpRainDripTex[0]);\n\t\n\tgpRainDripTex[1] = RwTextureRead(\"raindripb64\", nil);\n\tgpRainDripRaster[1] = RwTextureGetRaster(gpRainDripTex[1]);\n\t\n\tgpRainDripDarkTex[0] = RwTextureRead(\"raindrip64_d\", nil);\n\tgpRainDripDarkRaster[0] = RwTextureGetRaster(gpRainDripDarkTex[0]);\n\t\n\tgpRainDripDarkTex[1] = RwTextureRead(\"raindripb64_d\", nil);\n\tgpRainDripDarkRaster[1] = RwTextureGetRaster(gpRainDripDarkTex[1]);\n\t\n\tCTxdStore::PopCurrentTxd();\n\t\n\tfor ( int32 i = 0; i < MAX_PARTICLES; i++ )\n\t{\n\t\ttParticleSystemData *entry = &mod_ParticleSystemManager.m_aParticles[i];\n\t\t\n\t\tswitch ( i )\n\t\t{\n\t\t\tcase PARTICLE_SPARK:\n\t\t\tcase PARTICLE_SPARK_SMALL:\n\t\t\tcase PARTICLE_RAINDROP_SMALL:\n\t\t\tcase PARTICLE_HELI_ATTACK:\n\t\t\t\tentry->m_ppRaster = &gpRainDropSmallRaster;\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tcase PARTICLE_WATER_SPARK:\n\t\t\t\tentry->m_ppRaster = &gpSparkRaster;\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tcase PARTICLE_WHEEL_DIRT:\n\t\t\tcase PARTICLE_SAND:\n\t\t\tcase PARTICLE_STEAM2:\n\t\t\tcase PARTICLE_STEAM_NY:\n\t\t\tcase PARTICLE_STEAM_NY_SLOWMOTION:\n\t\t\tcase PARTICLE_GROUND_STEAM:\n\t\t\tcase PARTICLE_ENGINE_STEAM:\n\t\t\tcase PARTICLE_PEDFOOT_DUST:\n\t\t\tcase PARTICLE_CAR_DUST:\n\t\t\tcase PARTICLE_EXHAUST_FUMES:\n\t\t\t\tentry->m_ppRaster = &gpSmoke2Raster;\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tcase PARTICLE_WHEEL_WATER:\n\t\t\tcase PARTICLE_WATER:\n\t\t\tcase PARTICLE_SMOKE:\n\t\t\tcase PARTICLE_SMOKE_SLOWMOTION:\n\t\t\tcase PARTICLE_DRY_ICE:\n\t\t\tcase PARTICLE_GARAGEPAINT_SPRAY:\n\t\t\tcase PARTICLE_STEAM:\n\t\t\tcase PARTICLE_WATER_CANNON:\n\t\t\tcase PARTICLE_EXTINGUISH_STEAM:\n\t\t\tcase PARTICLE_HELI_DUST:\n\t\t\tcase PARTICLE_PAINT_SMOKE:\n\t\t\tcase PARTICLE_BULLETHIT_SMOKE:\n\t\t\t\tentry->m_ppRaster = gpSmokeRaster;\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tcase PARTICLE_BLOOD:\n\t\t\t\tentry->m_ppRaster = &gpBloodRaster;\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tcase PARTICLE_BLOOD_SMALL:\n\t\t\tcase PARTICLE_BLOOD_SPURT:\n\t\t\t\tentry->m_ppRaster = &gpBloodSmallRaster;\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tcase PARTICLE_DEBRIS:\n\t\t\tcase PARTICLE_TREE_LEAVES:\n\t\t\t\tentry->m_ppRaster = gpLeafRaster;\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tcase PARTICLE_DEBRIS2:\n\t\t\t\tentry->m_ppRaster = &gpGungeRaster;\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tcase PARTICLE_FLYERS:\n\t\t\t\tentry->m_ppRaster = &gpNewspaperRaster;\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tcase PARTICLE_FLAME:\n\t\t\tcase PARTICLE_CARFLAME:\n\t\t\t\tentry->m_ppRaster = &gpFlame1Raster;\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tcase PARTICLE_FIREBALL:\n\t\t\t\tentry->m_ppRaster = &gpFlame5Raster;\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tcase PARTICLE_GUNFLASH:\n\t\t\tcase PARTICLE_GUNFLASH_NOANIM:\n\t\t\t\tentry->m_ppRaster = gpGunFlashRaster;\n\t\t\t\tbreak;\n\t\t\t\n\t\t\t\n\t\t\tcase PARTICLE_GUNSMOKE:\n\t\t\tcase PARTICLE_WATERDROP:\n\t\t\tcase PARTICLE_BLOODDROP:\n\t\t\tcase PARTICLE_HEATHAZE:\n\t\t\tcase PARTICLE_HEATHAZE_IN_DIST:\n\t\t\t\tentry->m_ppRaster = nil;\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tcase PARTICLE_GUNSMOKE2:\n\t\t\tcase PARTICLE_BOAT_THRUSTJET:\n\t\t\tcase PARTICLE_RUBBER_SMOKE:\n\t\t\t\tentry->m_ppRaster = gpRubberRaster;\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tcase PARTICLE_CIGARETTE_SMOKE:\n\t\t\t\tentry->m_ppRaster = &gpGunSmokeRaster;\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tcase PARTICLE_TEARGAS:\n\t\t\t\tentry->m_ppRaster = &gpHeatHazeRaster;\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tcase PARTICLE_SHARD:\n\t\t\tcase PARTICLE_RAINDROP:\n\t\t\tcase PARTICLE_RAINDROP_2D:\n\t\t\t\tentry->m_ppRaster = &gpRainDropRaster;\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tcase PARTICLE_SPLASH:\n\t\t\tcase PARTICLE_PED_SPLASH:\n\t\t\tcase PARTICLE_CAR_SPLASH:\n\t\t\tcase PARTICLE_WATER_HYDRANT:\n\t\t\t\tentry->m_ppRaster = gpCarSplashRaster;\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tcase PARTICLE_RAIN_SPLASH:\n\t\t\tcase PARTICLE_RAIN_SPLASH_BIGGROW:\n\t\t\t\tentry->m_ppRaster = gpRainSplashRaster;\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tcase PARTICLE_RAIN_SPLASHUP:\n\t\t\t\tentry->m_ppRaster = gpRainSplashupRaster;\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tcase PARTICLE_WATERSPRAY:\n\t\t\t\tentry->m_ppRaster = gpWatersprayRaster;\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tcase PARTICLE_EXPLOSION_MEDIUM:\n\t\t\tcase PARTICLE_EXPLOSION_LARGE:\n\t\t\tcase PARTICLE_EXPLOSION_MFAST:\n\t\t\tcase PARTICLE_EXPLOSION_LFAST:\n\t\t\t\tentry->m_ppRaster = gpExplosionMediumRaster;\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tcase PARTICLE_BOAT_SPLASH:\n\t\t\t\tentry->m_ppRaster = &gpBoatWakeRaster;\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tcase PARTICLE_ENGINE_SMOKE:\n\t\t\tcase PARTICLE_ENGINE_SMOKE2:\n\t\t\tcase PARTICLE_CARFLAME_SMOKE:\n\t\t\tcase PARTICLE_FIREBALL_SMOKE:\n\t\t\tcase PARTICLE_ROCKET_SMOKE:\n\t\t\tcase PARTICLE_TEST:\n\t\t\t\tentry->m_ppRaster = &gpCloudRaster4;\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tcase PARTICLE_CARCOLLISION_DUST:\n\t\t\tcase PARTICLE_BURNINGRUBBER_SMOKE:\n\t\t\t\tentry->m_ppRaster = &gpCollisionSmokeRaster;\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tcase PARTICLE_CAR_DEBRIS:\n\t\t\tcase PARTICLE_HELI_DEBRIS:\n\t\t\tcase PARTICLE_BIRD_DEBRIS:\n\t\t\t\tentry->m_ppRaster = gpCarDebrisRaster;\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tcase PARTICLE_GUNSHELL_FIRST:\n\t\t\tcase PARTICLE_GUNSHELL:\n\t\t\tcase PARTICLE_GUNSHELL_BUMP1:\n\t\t\tcase PARTICLE_GUNSHELL_BUMP2:\n\t\t\t\tentry->m_ppRaster = &gpGunShellRaster;\n\t\t\t\tbreak;\n\t\t\t\n\t\t\t\n\t\t\tcase PARTICLE_BIRD_FRONT:\n\t\t\t\tentry->m_ppRaster = gpBirdfrontRaster;\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tcase PARTICLE_SHIP_SIDE:\n\t\t\t\tentry->m_ppRaster = gpBoatRaster;\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tcase PARTICLE_BEASTIE:\n\t\t\t\tentry->m_ppRaster = &gpBeastieRaster;\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tdebug(\"CParticle ready\");\n}\n\nvoid CParticle::Shutdown()\n{\n\tdebug(\"Shutting down CParticle...\");\n\n\tfor ( int32 i = 0; i < MAX_SMOKE_FILES; i++ )\n\t{\n\t\tRwTextureDestroy(gpSmokeTex[i]);\n\t\tgpSmokeTex[i] = nil;\n\t}\n\n\tRwTextureDestroy(gpSmoke2Tex);\n\tgpSmoke2Tex = nil;\n\t \n\tfor ( int32 i = 0; i < MAX_RUBBER_FILES; i++ )\n\t{\n\t\tRwTextureDestroy(gpRubberTex[i]);\n\t\tgpRubberTex[i] = nil;\n\t}\n\t\n\tfor ( int32 i = 0; i < MAX_RAINSPLASH_FILES; i++ )\n\t{\n\t\tRwTextureDestroy(gpRainSplashTex[i]);\n\t\tgpRainSplashTex[i] = nil;\n\t}\n\t\n\tfor ( int32 i = 0; i < MAX_WATERSPRAY_FILES; i++ )\n\t{\n\t\tRwTextureDestroy(gpWatersprayTex[i]);\n\t\tgpWatersprayTex[i] = nil;\n\t}\n\t\n\tfor ( int32 i = 0; i < MAX_EXPLOSIONMEDIUM_FILES; i++ )\n\t{\n\t\tRwTextureDestroy(gpExplosionMediumTex[i]);\n\t\tgpExplosionMediumTex[i] = nil;\n\t}\n\t\n\tfor ( int32 i = 0; i < MAX_GUNFLASH_FILES; i++ )\n\t{\n\t\tRwTextureDestroy(gpGunFlashTex[i]);\n\t\tgpGunFlashTex[i] = nil;\n\t}\n\t\n\tRwTextureDestroy(gpRainDropTex);\n\tgpRainDropTex = nil;\n\t\n\tfor ( int32 i = 0; i < MAX_RAINSPLASHUP_FILES; i++ )\n\t{\n\t\tRwTextureDestroy(gpRainSplashupTex[i]);\n\t\tgpRainSplashupTex[i] = nil;\n\t}\n\t\n\tfor ( int32 i = 0; i < MAX_BIRDFRONT_FILES; i++ )\n\t{\n\t\tRwTextureDestroy(gpBirdfrontTex[i]);\n\t\tgpBirdfrontTex[i] = nil;\n\t}\n\t\n\tfor ( int32 i = 0; i < MAX_BOAT_FILES; i++ )\n\t{\n\t\tRwTextureDestroy(gpBoatTex[i]);\n\t\tgpBoatTex[i] = nil;\n\t}\n\t\n\tfor ( int32 i = 0; i < MAX_CARDEBRIS_FILES; i++ )\n\t{\n\t\tRwTextureDestroy(gpCarDebrisTex[i]);\n\t\tgpCarDebrisTex[i] = nil;\n\t}\n\t\n\tfor ( int32 i = 0; i < MAX_CARSPLASH_FILES; i++ )\n\t{\n\t\tRwTextureDestroy(gpCarSplashTex[i]);\n\t\tgpCarSplashTex[i] = nil;\n\t}\n\t\n\tfor ( int32 i = 0; i < MAX_RAINDRIP_FILES; i++ )\n\t{\n\t\tRwTextureDestroy(gpRainDripTex[i]);\n\t\tgpRainDripTex[i] = nil;\n\n\t\tRwTextureDestroy(gpRainDripDarkTex[i]);\n\t\tgpRainDripDarkTex[i] = nil;\n\t}\n\t\n\tRwTextureDestroy(gpBoatWakeTex);\n\tgpBoatWakeTex = nil;\n\n\tRwTextureDestroy(gpFlame1Tex);\n\tgpFlame1Tex = nil;\n\n\tRwTextureDestroy(gpFlame5Tex);\n\tgpFlame5Tex = nil;\n\t\n\tRwTextureDestroy(gpRainDropSmallTex);\n\tgpRainDropSmallTex = nil;\n\t\n\tRwTextureDestroy(gpBloodTex);\n\tgpBloodTex = nil;\n\t\n\tRwTextureDestroy(gpLeafTex[0]);\n\tgpLeafTex[0] = nil;\n\n\tRwTextureDestroy(gpLeafTex[1]);\n\tgpLeafTex[1] = nil;\n\t\n\tRwTextureDestroy(gpCloudTex1);\n\tgpCloudTex1 = nil;\n\t\n\tRwTextureDestroy(gpCloudTex4);\n\tgpCloudTex4 = nil;\n\t\n\tRwTextureDestroy(gpBloodSmallTex);\n\tgpBloodSmallTex = nil;\n\t\n\tRwTextureDestroy(gpGungeTex);\n\tgpGungeTex = nil;\n\t\n\tRwTextureDestroy(gpCollisionSmokeTex);\n\tgpCollisionSmokeTex = nil;\n\t\n\tRwTextureDestroy(gpBulletHitTex);\n\tgpBulletHitTex = nil;\n\t\n\tRwTextureDestroy(gpGunShellTex);\n\tgpGunShellTex = nil;\n\t\n\tRwTextureDestroy(gpPointlightTex);\n\tgpPointlightTex = nil;\n\n\tRwTextureDestroy(gpSparkTex);\n\tgpSparkTex = nil;\n\t\n\tRwTextureDestroy(gpNewspaperTex);\n\tgpNewspaperTex = nil;\n\n\tRwTextureDestroy(gpGunSmokeTex);\n\tgpGunSmokeTex = nil;\n\t\n\tRwTextureDestroy(gpDotTex);\n\tgpDotTex = nil;\n\tRwTextureDestroy(gpHeatHazeTex);\n\tgpHeatHazeTex = nil;\n\t\n\tRwTextureDestroy(gpBeastieTex);\n\tgpBeastieTex = nil;\n\n\tint32 slot;\n\n\tslot = CTxdStore::FindTxdSlot(\"particle\");\n\tCTxdStore::RemoveTxdSlot(slot);\n\n\tdebug(\"CParticle shut down\");\n}\n\n\nvoid CParticle::AddParticlesAlongLine(tParticleType type, CVector const &vecStart, CVector const &vecEnd, CVector const &vecDir, float fPower, CEntity *pEntity, float fSize, int32 nRotationSpeed, int32 nRotation, int32 nCurFrame, int32 nLifeSpan)\n{\n\tCVector vecDist = vecEnd - vecStart;\n\tfloat fDist = vecDist.Magnitude();\n\tfloat fSteps = Max(fDist / fPower, 1.0f);\n\tint32 nSteps = (int32)fSteps;\n\n\tCVector vecStep = vecDist * (1.0f / (float)nSteps); \n\n\tfor ( int32 i = 0; i < nSteps; i++ )\n\t{\n\t\tCVector vecPos = float(i) * vecStep + vecStart;\n\t\tAddParticle(type, vecPos, vecDir, pEntity, fSize, nRotationSpeed, nRotation, nCurFrame, nLifeSpan);\n\t}\n}\n\nvoid CParticle::AddParticlesAlongLine(tParticleType type, CVector const &vecStart, CVector const &vecEnd, CVector const &vecDir, float fPower, CEntity *pEntity, float fSize, RwRGBA const &color, int32 nRotationSpeed, int32 nRotation, int32 nCurFrame, int32 nLifeSpan)\n{\n\tCVector vecDist = vecEnd - vecStart;\n\tfloat fDist = vecDist.Magnitude();\n\tfloat fSteps = Max(fDist / fPower, 1.0f);\n\tint32 nSteps = (int32)fSteps;\n\t\n\tCVector vecStep = vecDist * (1.0f / (float)nSteps); \n\n\tfor ( int32 i = 0; i < nSteps; i++ )\n\t{\t\t\n\t\tCVector vecPos = float(i) * vecStep + vecStart;\n\t\t\n\t\tAddParticle(type, vecPos, vecDir, pEntity, fSize, color, nRotationSpeed, nRotation, nCurFrame, nLifeSpan);\n\t}\n}\n\nCParticle *CParticle::AddParticle(tParticleType type, CVector const &vecPos, CVector const &vecDir, CEntity *pEntity, float fSize, int32 nRotationSpeed, int32 nRotation, int32 nCurFrame, int32 nLifeSpan)\n{\n\tCRGBA color(0, 0, 0, 0);\n\treturn AddParticle(type, vecPos, vecDir, pEntity, fSize, color, nRotationSpeed, nRotation, nCurFrame, nLifeSpan);\n}\n\nCParticle *CParticle::AddParticle(tParticleType type, CVector const &vecPos, CVector const &vecDir, CEntity *pEntity, float fSize, RwRGBA const &color, int32 nRotationSpeed, int32 nRotation, int32 nCurFrame, int32 nLifeSpan)\n{\n\tif ( CTimer::GetIsPaused() )\n\t\treturn nil;\n\n\tif ( ( type == PARTICLE_ENGINE_SMOKE\n\t\t|| type == PARTICLE_ENGINE_SMOKE2\n\t\t|| type == PARTICLE_ENGINE_STEAM\n\t\t|| type == PARTICLE_CARFLAME_SMOKE\n\t\t|| type == PARTICLE_RUBBER_SMOKE\n\t\t|| type == PARTICLE_BURNINGRUBBER_SMOKE\n\t\t|| type == PARTICLE_EXHAUST_FUMES\n\t\t|| type == PARTICLE_CARCOLLISION_DUST )\n\t\t&& nParticleCreationInterval & CTimer::GetFrameCounter() )\n\t{\n\t\treturn nil;\n\t}\n\n\tif ( !CReplay::IsPlayingBack() )\n\t\tCReplay::RecordParticle(type, vecPos, vecDir, fSize, color);\n\t\n\tCParticle *pParticle = m_pUnusedListHead;\n\t\n\tif ( pParticle == nil )\n\t\treturn nil;\n\t\n\ttParticleSystemData *psystem = &mod_ParticleSystemManager.m_aParticles[type];\n\t\n\tif ( psystem->m_fCreateRange != 0.0f && psystem->m_fCreateRange < ( TheCamera.GetPosition() - vecPos ).MagnitudeSqr() )\n\t\treturn nil;\n\t\n\t\n\tpParticle->m_fSize = psystem->m_fDefaultInitialRadius;\n\tpParticle->m_fExpansionRate = psystem->m_fExpansionRate;\n\t\n\tif ( nLifeSpan != 0 )\n\t\tpParticle->m_nTimeWhenWillBeDestroyed = CTimer::GetTimeInMilliseconds() + nLifeSpan;\n\telse\n\t\tpParticle->m_nTimeWhenWillBeDestroyed = CTimer::GetTimeInMilliseconds() + psystem->m_nLifeSpan;\n\n\tpParticle->m_nColorIntensity = psystem->m_nFadeToBlackInitialIntensity;\n\t\n\tpParticle->m_nFadeToBlackTimer = psystem->m_nFadeToBlackAmount;\n\t\n\tif ( psystem->m_nFadeToBlackTime )\n\t\tpParticle->m_nFadeToBlackTimer /= psystem->m_nFadeToBlackTime;\n\t\n\tpParticle->m_nAlpha = psystem->m_nFadeAlphaInitialIntensity;\n\t\n\tpParticle->m_nFadeAlphaTimer = psystem->m_nFadeAlphaAmount;\n\t\n\tif ( psystem->m_nFadeAlphaTime )\n\t\tpParticle->m_nFadeAlphaTimer /= psystem->m_nFadeAlphaTime;\n\t\n\tpParticle->m_nCurrentZRotation = psystem->m_nZRotationInitialAngle;\n\tpParticle->m_fCurrentZRadius = psystem->m_fInitialZRadius;\n\t\n\tif ( nCurFrame != 0 )\n\t\tpParticle->m_nCurrentFrame = nCurFrame;\n\telse\n\t\tpParticle->m_nCurrentFrame = psystem->m_nStartAnimationFrame;\n\t\n\t\n\tpParticle->m_nZRotationTimer = 0;\n\tpParticle->m_nZRadiusTimer = 0;\n\tpParticle->m_nAnimationSpeedTimer = 0;\n\tpParticle->m_fZGround = 0.0f;\n\t\n\tif ( type != PARTICLE_HEATHAZE )\n\t\tpParticle->m_vecPosition = vecPos;\n\telse\n\t{\n\t\tCVector screen;\n\t\tfloat w, h;\n\n\t\tif ( !CSprite::CalcScreenCoors(vecPos, &screen, &w, &h, true) )\n\t\t\treturn nil;\n\t\t\n\t\tpParticle->m_vecPosition = screen;\n\t\tpsystem->m_vecTextureStretch.x = w;\n\t\tpsystem->m_vecTextureStretch.y = h;\n\t}\n\t\n\tpParticle->m_vecVelocity = vecDir;\n\t\n\tpParticle->m_vecParticleMovementOffset = CVector(0.0f, 0.0f, 0.0f);\n\tpParticle->m_nTimeWhenColorWillBeChanged = 0;\n\t\n\tif ( color.alpha != 0 )\n\t\tRwRGBAAssign(&pParticle->m_Color, &color);\n\telse\n\t{\n\t\tRwRGBAAssign(&pParticle->m_Color, psystem->m_RenderColouring);\n\n\t\tif ( psystem->m_ColorFadeTime != 0 )\n\t\t\tpParticle->m_nTimeWhenColorWillBeChanged = CTimer::GetTimeInMilliseconds() + psystem->m_ColorFadeTime;\n\n\t\tif ( psystem->m_InitialColorVariation != 0 )\n\t\t{\n\t\t\tint32 ColorVariation = CGeneral::GetRandomNumberInRange(-psystem->m_InitialColorVariation, psystem->m_InitialColorVariation);\n\t\t\t//float ColorVariation = CGeneral::GetRandomNumberInRange((float)-psystem->m_InitialColorVariation, (float)psystem->m_InitialColorVariation);\n  \n\t\t\tpParticle->m_Color.red   = clamp(pParticle->m_Color.red +\n\t\t\t\tPERCENT(pParticle->m_Color.red, ColorVariation),\n\t\t\t\t0, 255);\n\t\t\t\n\t\t\tpParticle->m_Color.green = clamp(pParticle->m_Color.green +\n\t\t\t\tPERCENT(pParticle->m_Color.green, ColorVariation),\n\t\t\t\t0, 255);\n\t\t\t\n\t\t\tpParticle->m_Color.blue  = clamp(pParticle->m_Color.blue +\n\t\t\t\tPERCENT(pParticle->m_Color.blue, ColorVariation),\n\t\t\t\t0, 255);\n\t\t}\n\t}\n\n\tpParticle->m_nRotation = nRotation;\n\t\t\n\tif ( nRotationSpeed != 0 )\n\t\tpParticle->m_nRotationStep = nRotationSpeed;\n\telse\n\t\tpParticle->m_nRotationStep = psystem->m_nRotationSpeed;\n\t\n\tif ( CGeneral::GetRandomNumber() & 1 )\n\t\tpParticle->m_nRotationStep = -pParticle->m_nRotationStep;\n\t\n\tif ( psystem->m_fPositionRandomError != 0.0f )\n\t{\n\t\tpParticle->m_vecPosition.x += psystem->m_fPositionRandomError * ms_afRandTable[CGeneral::GetRandomNumber() % RAND_TABLE_SIZE];\n\t\tpParticle->m_vecPosition.y += psystem->m_fPositionRandomError * ms_afRandTable[CGeneral::GetRandomNumber() % RAND_TABLE_SIZE];\n\t\t\n\t\tif ( psystem->Flags & RAND_VERT_V )\n\t\t\tpParticle->m_vecPosition.z += psystem->m_fPositionRandomError * ms_afRandTable[CGeneral::GetRandomNumber() % RAND_TABLE_SIZE];\n\t}\n\t\n\tif ( psystem->m_fVelocityRandomError != 0.0f )\n\t{\n\t\tpParticle->m_vecVelocity.x += psystem->m_fVelocityRandomError * ms_afRandTable[CGeneral::GetRandomNumber() % RAND_TABLE_SIZE];\n\t\tpParticle->m_vecVelocity.y += psystem->m_fVelocityRandomError * ms_afRandTable[CGeneral::GetRandomNumber() % RAND_TABLE_SIZE];\n    \n\t\tif ( psystem->Flags & RAND_VERT_V )\n\t\t\tpParticle->m_vecVelocity.z += psystem->m_fVelocityRandomError * ms_afRandTable[CGeneral::GetRandomNumber() % RAND_TABLE_SIZE];\n\t}\n\t\n\tif ( psystem->m_fExpansionRateError != 0.0f && !(psystem->Flags & SCREEN_TRAIL) )\n\t\tpParticle->m_fExpansionRate += psystem->m_fExpansionRateError * ms_afRandTable[CGeneral::GetRandomNumber() % RAND_TABLE_SIZE] + psystem->m_fExpansionRateError;\n\t\n\tif ( psystem->m_nRotationRateError != 0 )\n\t\tpParticle->m_nRotationStep += CGeneral::GetRandomNumberInRange(-psystem->m_nRotationRateError, psystem->m_nRotationRateError);\n\n\tif ( psystem->m_nLifeSpanErrorShape != 0 )\n\t{\n\t\tfloat randVal = ms_afRandTable[CGeneral::GetRandomNumber() % RAND_TABLE_SIZE];\n\t\tif ( randVal > 0.0f )\n\t\t\tpParticle->m_nTimeWhenWillBeDestroyed += int32(float(psystem->m_nLifeSpan) * randVal * float(psystem->m_nLifeSpanErrorShape));\n\t\telse\n\t\t\tpParticle->m_nTimeWhenWillBeDestroyed += int32(float(psystem->m_nLifeSpan) * randVal / float(psystem->m_nLifeSpanErrorShape));\n\t}\n\t\n\tif ( psystem->Flags & ZCHECK_FIRST )\n\t{\n\t\tstatic bool bValidGroundFound = false;\n\t\tstatic CVector LastTestCoors;\n\t\tstatic float LastTestGroundZ;\n\t\t\n\t\tif ( bValidGroundFound \n\t\t\t&& vecPos.x == LastTestCoors.x \n\t\t\t&& vecPos.y == LastTestCoors.y \n\t\t\t&& vecPos.z == LastTestCoors.z )\n\t\t{\n\t\t\tpParticle->m_fZGround = LastTestGroundZ;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tbValidGroundFound = false;\n\t\t\t\n\t\t\tCColPoint point;\n\t\t\tCEntity *entity;\n\t\t\t\n\t\t\tif ( !CWorld::ProcessVerticalLine(\n\t\t\t\t\t\tpParticle->m_vecPosition + CVector(0.0f, 0.0f, 0.5f),\n\t\t\t\t\t\t-100.0f, point, entity, true, true, false, false, true, false, nil) )\n\t\t\t{\n\t\t\t\treturn nil;\n\t\t\t}\n\t\t\t\n\t\t\tif ( point.point.z >= pParticle->m_vecPosition.z )\n\t\t\t\treturn nil;\n\t\t\t\n\t\t\tpParticle->m_fZGround = point.point.z;\n\t\t\tbValidGroundFound = true;\n\t\t\tLastTestCoors = vecPos;\n\t\t\tLastTestGroundZ = point.point.z;\n\t\t}\n\t}\n\t\n\tif ( psystem->Flags & ZCHECK_BUMP )\n\t{\n\t\tstatic float Z_Ground = 0.0f;\n\t\t\n\t\tif ( psystem->Flags & ZCHECK_BUMP_FIRST )\n\t\t{\n\t\t\tbool bZFound = false;\n\n\t\t\tZ_Ground = CWorld::FindGroundZFor3DCoord(vecPos.x, vecPos.y, vecPos.z, (bool *)&bZFound);\n\n\t\t\tif ( bZFound == false )\n\t\t\t\treturn nil;\n\n\t\t\tpParticle->m_fZGround = Z_Ground;\n\t\t}\n\t\t\n\t\tpParticle->m_fZGround = Z_Ground;\n\t}\n\t\n\tswitch ( type )\n\t{\n\t\tcase PARTICLE_DEBRIS:\n\t\t\tpParticle->m_vecVelocity.z *= CGeneral::GetRandomNumberInRange(0.5f, 3.0f);\n\t\t\tbreak;\n\t\t\n\t\tcase PARTICLE_EXPLOSION_MEDIUM:\n\t\t\tpParticle->m_nColorIntensity -= 30 * (CGeneral::GetRandomNumber() & 1); // mb \"+= -30 * rand\" here ?\n\t\t\tpParticle->m_nAnimationSpeedTimer = CGeneral::GetRandomNumber() & 7;\n\t\t\tpParticle->m_fSize = CGeneral::GetRandomNumberInRange(0.3f, 0.8f);\n\t\t\tpParticle->m_vecPosition.z -= CGeneral::GetRandomNumberInRange(-0.1f, 0.1f);\n\t\t\tbreak;\n\t\t\n\t\tcase PARTICLE_EXPLOSION_LARGE:\n\t\t\tpParticle->m_nColorIntensity -= 30 * (CGeneral::GetRandomNumber() & 1); // mb \"+= -30 * rand\" here ?\n\t\t\tpParticle->m_nAnimationSpeedTimer = CGeneral::GetRandomNumber() & 7;\n\t\t\tpParticle->m_fSize = CGeneral::GetRandomNumberInRange(0.8f, 1.4f);\n\t\t\tpParticle->m_vecPosition.z -= CGeneral::GetRandomNumberInRange(-0.3f, 0.3f);\n\t\t\tbreak;\n\t\t\n\t\tcase PARTICLE_WATER_HYDRANT:\n\t\t\tpParticle->m_vecPosition.z += 20.0f * psystem->m_fPositionRandomError * ms_afRandTable[CGeneral::GetRandomNumber() % RAND_TABLE_SIZE];\n\t\t\tbreak;\n\t\tdefault: break;\n\t}\n\t\n\tif ( fSize != 0.0f )\n\t\tpParticle->m_fSize = fSize;\n\t\n\tm_pUnusedListHead = pParticle->m_pNext;\n\n\tpParticle->m_pNext = psystem->m_pParticles;\n\n\tpsystem->m_pParticles = pParticle;\n\t\n\treturn pParticle;\n}\n\nvoid CParticle::Update()\n{\n\tif ( CTimer::GetIsPaused() )\n\t\treturn;\n\n\tCRGBA color(0, 0, 0, 0);\n\t\n\tfloat fFricDeccel50 = pow(0.50f, CTimer::GetTimeStep());\n\tfloat fFricDeccel80 = pow(0.80f, CTimer::GetTimeStep());\n\tfloat fFricDeccel90 = pow(0.90f, CTimer::GetTimeStep());\n\tfloat fFricDeccel95 = pow(0.95f, CTimer::GetTimeStep());\n\tfloat fFricDeccel96 = pow(0.96f, CTimer::GetTimeStep());\n\tfloat fFricDeccel99 = pow(0.99f, CTimer::GetTimeStep());\n\t\n\tCParticleObject::UpdateAll();\n\t\n\t// ejaculation at 23:00, 23:15, 23:30, 23:45 \n\tif ( CClock::ms_nGameClockHours == 23 &&\n\t\t(\t   CClock::ms_nGameClockMinutes == 0 \n\t\t\t|| CClock::ms_nGameClockMinutes == 15 \n\t\t\t|| CClock::ms_nGameClockMinutes == 30\n\t\t\t|| CClock::ms_nGameClockMinutes == 45 ) )\n\t{\n\t\tAddParticle(PARTICLE_CAR_SPLASH,\n\t\t\t\t\tCVector(557.03f, -4.0f, 151.46f),\n\t\t\t\t\tCVector(0.0f, 0.0f, 2.5f),\n\t\t\t\t\tNULL,\n\t\t\t\t\t2.0f,\n\t\t\t\t\tCRGBA(255, 255, 255, 255),\n\t\t\t\t\t0,\n\t\t\t\t\t0,\n\t\t\t\t\t1,\n\t\t\t\t\t1000);\n\t}\n\n\tfor ( int32 i = 0; i < MAX_PARTICLES; i++ )\n\t{\n\t\ttParticleSystemData *psystem = &mod_ParticleSystemManager.m_aParticles[i];\n\t\tCParticle *particle = psystem->m_pParticles;\n\t\tCParticle *prevParticle = nil;\n\t\tbool bRemoveParticle;\n\t\t\n\t\tif ( particle == nil )\n\t\t\tcontinue;\n\t\t\t\t\n\t\tfor ( ; particle != nil; _Next(particle, prevParticle, psystem, bRemoveParticle) )\n\t\t{\n\t\t\tCVector vecWind(0.0f, 0.0f, 0.0f);\n\t\t\t\n\t\t\tbRemoveParticle = false;\n\n\t\t\tCVector vecMoveStep = particle->m_vecVelocity * CTimer::GetTimeStep();\n\t\t\tCVector vecPos = particle->m_vecPosition;\n\t\t\t\n\t\t\tif ( numWaterDropOnScreen == 0 )\n\t\t\t\tclearWaterDrop = false;\n\t\t\t\n\t\t\tif ( psystem->m_Type == PARTICLE_WATERDROP )\n\t\t\t{\n\t\t\t\tif ( CGame::IsInInterior() || clearWaterDrop == true )\n\t\t\t\t{\n\t\t\t\t\tbRemoveParticle = true;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tstatic uint8 nWaterDropCount;\n\n\t\t\t\tif ( nWaterDropCount == 5 )\n\t\t\t\t{\n\t\t\t\t\tvecMoveStep = CVector(0.0f, 0.0f, 0.0f);\n\t\t\t\t\tparticle->m_nTimeWhenWillBeDestroyed += 1250;\n\t\t\t\t\tnWaterDropCount = 0;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tif ( TheCamera.m_CameraAverageSpeed > 0.35f )\n\t\t\t\t\t{\n\t\t\t\t\t\tif ( vecMoveStep.Magnitude() > 0.5f )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif ( vecMoveStep.Magnitude() > 0.4f && vecMoveStep.Magnitude() < 0.8f )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tvecMoveStep.x += TheCamera.m_CameraAverageSpeed * 1.5f;\n\t\t\t\t\t\t\t\tvecMoveStep.y += TheCamera.m_CameraAverageSpeed * 1.5f;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse if ( vecMoveStep.Magnitude() != 0.0f )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tvecMoveStep.x += CGeneral::GetRandomNumberInRange(0.01f, 0.05f);\n\t\t\t\t\t\t\t\tvecMoveStep.y += CGeneral::GetRandomNumberInRange(0.01f, 0.05f);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tnWaterDropCount++;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif ( vecPos.z <= 1.5f )\n\t\t\t\t\tvecMoveStep.z = 0.0f;\n\t\t\t}\n\t\t\t\n\t\t\tif ( psystem->m_Type == PARTICLE_HEATHAZE || psystem->m_Type == PARTICLE_HEATHAZE_IN_DIST )\n\t\t\t{\n#ifdef FIX_BUGS\n\t\t\t\tint32 nSinCosIndex = (int32(DEGTORAD((float)particle->m_nRotation) * float(SIN_COS_TABLE_SIZE) / TWOPI) + SIN_COS_TABLE_SIZE) % SIN_COS_TABLE_SIZE;\n#else\n\t\t\t\tint32 nSinCosIndex = int32(DEGTORAD((float)particle->m_nRotation) * float(SIN_COS_TABLE_SIZE) / TWOPI) % SIN_COS_TABLE_SIZE;\n#endif\n\t\t\t\tvecMoveStep.x = Sin(nSinCosIndex);\n\t\t\t\tvecMoveStep.y = Sin(nSinCosIndex);\n\t\t\t\t\n\t\t\t\tif ( psystem->m_Type == PARTICLE_HEATHAZE_IN_DIST )\n\t\t\t\t\tparticle->m_nRotation = int16((float)particle->m_nRotation + 0.75f);\n\t\t\t\telse\n\t\t\t\t\tparticle->m_nRotation = int16((float)particle->m_nRotation + 1.0f);\n\t\t\t}\n\t\t\t\n\t\t\tif ( psystem->m_Type == PARTICLE_BEASTIE )\n\t\t\t{\n#ifdef FIX_BUGS\n\t\t\t\tint32 nSinCosIndex = (int32(DEGTORAD((float)particle->m_nRotation) * float(SIN_COS_TABLE_SIZE) / TWOPI) + SIN_COS_TABLE_SIZE) % SIN_COS_TABLE_SIZE;\n#else\n\t\t\t\tint32 nSinCosIndex = int32(DEGTORAD((float)particle->m_nRotation) * float(SIN_COS_TABLE_SIZE) / TWOPI) % SIN_COS_TABLE_SIZE;\n#endif\t\t\t\t\n\t\t\t\tparticle->m_vecVelocity.x = 0.50f * Cos(nSinCosIndex);\n\t\t\t\tparticle->m_vecVelocity.y = Cos(nSinCosIndex);\n\t\t\t\tparticle->m_vecVelocity.z = 0.25f * Sin(nSinCosIndex);\n\t\t\t\t\n\t\t\t\tif ( particle->m_vecVelocity.Magnitude() > 2.0f\n\t\t\t\t\t\t|| vecPos.z > 40.0f\n\t\t\t\t\t\t|| (TheCamera.GetPosition() - vecPos).Magnitude() < 60.0f\n\t\t\t\t\t)\n\t\t\t\t{\n\t\t\t\t\tbRemoveParticle = true;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tvecPos += vecMoveStep;\n\t\t\t\n\t\t\tif ( psystem->m_Type == PARTICLE_FIREBALL )\n\t\t\t{\n\t\t\t\t  AddParticle(PARTICLE_HEATHAZE, particle->m_vecPosition, CVector(0.0f, 0.0f, 0.0f),\n\t\t\t\t\tnil, particle->m_fSize * 5.0f);\n\t\t\t}\n\t\t\t\n\t\t\tif ( psystem->m_Type == PARTICLE_GUNSMOKE2 )\n\t\t\t{\n\t\t\t\tif ( CTimer::GetFrameCounter() & 10 )\n\t\t\t\t{\n#ifdef FIX_BUGS\n\t\t\t\t\tif ( FindPlayerPed() && FindPlayerPed()->GetWeapon()->m_eWeaponType == WEAPONTYPE_MINIGUN )\n#else\n\t\t\t\t\tif ( FindPlayerPed()->GetWeapon()->m_eWeaponType == WEAPONTYPE_MINIGUN )\n#endif\n\t\t\t\t\t{\n\t\t\t\t\t\tAddParticle(PARTICLE_HEATHAZE, particle->m_vecPosition, CVector(0.0f, 0.0f, 0.0f));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tif ( CWeather::Wind > 0.0f )\n\t\t\t{\n\t\t\t\tif ( vecMoveStep.Magnitude() != 0.0f )\n\t\t\t\t{\n\t\t\t\t\tvecWind.x = CGeneral::GetRandomNumberInRange(0.75f, 1.25f) * -CWeather::Wind;\n\t\t\t\t\tvecWind.y = CGeneral::GetRandomNumberInRange(0.75f, 1.25f) * -CWeather::Wind;\n\t\t\t\t\tvecWind *= PARTICLE_WIND_TEST_SCALE * psystem->m_fWindFactor * CTimer::GetTimeStep();\n\t\t\t\t\tparticle->m_vecVelocity += vecWind;\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tif ( psystem->m_Type == PARTICLE_RAINDROP\n\t\t\t\t|| psystem->m_Type == PARTICLE_RAINDROP_SMALL\n\t\t\t\t|| psystem->m_Type == PARTICLE_RAIN_SPLASH\n\t\t\t\t|| psystem->m_Type == PARTICLE_RAIN_SPLASH_BIGGROW\n\t\t\t\t|| psystem->m_Type == PARTICLE_CAR_SPLASH\n\t\t\t\t|| psystem->m_Type == PARTICLE_BOAT_SPLASH\n\t\t\t\t|| psystem->m_Type == PARTICLE_RAINDROP_2D )\n\t\t\t{\n\t\t\t\tint32 nMaxDrops = int32(6.0f * TheCamera.m_CameraAverageSpeed + 1.0f);\n\t\t\t\tfloat fDistToCam = 0.0f;\n\t\t\t\t\n\t\t\t\tif ( psystem->m_Type == PARTICLE_BOAT_SPLASH || psystem->m_Type == PARTICLE_CAR_SPLASH )\n\t\t\t\t{\n\t\t\t\t\tif ( vecPos.z + particle->m_fSize < 5.0f )\n\t\t\t\t\t{\n\t\t\t\t\t\tbRemoveParticle = true;\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tswitch ( TheCamera.GetLookDirection() )\n\t\t\t\t\t{\n\t\t\t\t\t\tcase LOOKING_LEFT:\n\t\t\t\t\t\tcase LOOKING_RIGHT:\n\t\t\t\t\t\tcase LOOKING_FORWARD:\n\t\t\t\t\t\t\tnMaxDrops /= 2;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tnMaxDrops = 0;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tfDistToCam = (TheCamera.GetPosition() - vecPos).Magnitude();\n\t\t\t\t}\n\n\t\t\t\tif ( numWaterDropOnScreen < nMaxDrops && numWaterDropOnScreen < 63\n\t\t\t\t\t&& fDistToCam < 10.0f\n\t\t\t\t\t&& clearWaterDrop == false\n\t\t\t\t\t&& !CGame::IsInInterior() )\n\t\t\t\t{\n\t\t\t\t\tCVector vecWaterdropTarget\n\t\t\t\t\t(\n\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(-0.25f, 0.25f),\n\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(0.1f, 0.75f),\n\t\t\t\t\t\t-0.01f\n\t\t\t\t\t);\n\t\t\t\t\t\n\t\t\t\t\tCVector vecWaterdropPos;\n\t\t\t\t\t\n\t\t\t\t\tif ( TheCamera.m_CameraAverageSpeed < 0.35f )\n\t\t\t\t\t\tvecWaterdropPos.x = (float)CGeneral::GetRandomNumberInRange(50, int32(SCREEN_WIDTH) - 50);\n\t\t\t\t\telse\n\t\t\t\t\t\tvecWaterdropPos.x = (float)CGeneral::GetRandomNumberInRange(200, int32(SCREEN_WIDTH) - 200);\n\t\t\t\t\t\n\t\t\t\t\tif ( psystem->m_Type == PARTICLE_BOAT_SPLASH || psystem->m_Type == PARTICLE_CAR_SPLASH )\n\t\t\t\t\t\tvecWaterdropPos.y = (float)CGeneral::GetRandomNumberInRange(SCREEN_HEIGHT / 2, SCREEN_HEIGHT);\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tif ( TheCamera.m_CameraAverageSpeed < 0.35f )\n\t\t\t\t\t\t\tvecWaterdropPos.y  = (float)CGeneral::GetRandomNumberInRange(0, int32(SCREEN_HEIGHT));\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tvecWaterdropPos.y  = (float)CGeneral::GetRandomNumberInRange(150, int32(SCREEN_HEIGHT) - 200);\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tvecWaterdropPos.z = 2.0f;\n\n\t\t\t\t\tif ( AddParticle(PARTICLE_WATERDROP,\n\t\t\t\t\t\t\t\t\t\tvecWaterdropPos,\n\t\t\t\t\t\t\t\t\t\tvecWaterdropTarget,\n\t\t\t\t\t\t\t\t\t\tnil,\n\t\t\t\t\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(0.1f, 0.15f),\n\t\t\t\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t\t\t\tCGeneral::GetRandomNumber() & 1,\n\t\t\t\t\t\t\t\t\t\t0) != nil )\n\t\t\t\t\t{\n\t\t\t\t\t\tnumWaterDropOnScreen++;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tif (  CTimer::GetTimeInMilliseconds() > particle->m_nTimeWhenWillBeDestroyed || particle->m_nAlpha == 0 )\n\t\t\t{\n\t\t\t\tbRemoveParticle = true;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif ( particle->m_nTimeWhenColorWillBeChanged != 0 )\n\t\t\t{\n\t\t\t\tif ( particle->m_nTimeWhenColorWillBeChanged > CTimer::GetTimeInMilliseconds() )\n\t\t\t\t{\n\t\t\t\t\tfloat colorMul = 1.0f - float(particle->m_nTimeWhenColorWillBeChanged - CTimer::GetTimeInMilliseconds()) / float(psystem->m_ColorFadeTime);\n\t\t\t\t\n\t\t\t\t\tparticle->m_Color.red = clamp(\n\t\t\t\t\t\tpsystem->m_RenderColouring.red + int32(float(psystem->m_FadeDestinationColor.red - psystem->m_RenderColouring.red) * colorMul),\n\t\t\t\t\t\t0, 255);\n\t\t\t\t\t\n\t\t\t\t\tparticle->m_Color.green = clamp(\n\t\t\t\t\t\tpsystem->m_RenderColouring.green + int32(float(psystem->m_FadeDestinationColor.green - psystem->m_RenderColouring.green) * colorMul),\n\t\t\t\t\t\t0, 255);\n\t\t\t\t\t\t\n\t\t\t\t\tparticle->m_Color.blue = clamp(\n\t\t\t\t\t\tpsystem->m_RenderColouring.blue + int32(float(psystem->m_FadeDestinationColor.blue - psystem->m_RenderColouring.blue) * colorMul),\n\t\t\t\t\t\t0, 255);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\tRwRGBAAssign(&particle->m_Color, psystem->m_FadeDestinationColor);\n\t\t\t}\n\t\t\t\n\t\t\tif ( psystem->Flags & CLIPOUT2D )\n\t\t\t{\n\t\t\t\tif ( particle->m_vecPosition.x < -10.0f || particle->m_vecPosition.x > SCREEN_WIDTH + 10.0f\n\t\t\t\t\t|| particle->m_vecPosition.y < -10.0f || particle->m_vecPosition.y > SCREEN_HEIGHT + 10.0f )\n\t\t\t\t{\n\t\t\t\t\tbRemoveParticle = true;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tif ( !(psystem->Flags & SCREEN_TRAIL) )\n\t\t\t{\n\t\t\t\tfloat size;\n\n\t\t\t\tif ( particle->m_fExpansionRate > 0.0f )\n\t\t\t\t{\n\t\t\t\t\tfloat speed = Max(vecWind.Magnitude(), vecMoveStep.Magnitude());\n\t\t\t\t\t\n\t\t\t\t\tif ( psystem->m_Type == PARTICLE_EXHAUST_FUMES || psystem->m_Type == PARTICLE_ENGINE_STEAM )\n\t\t\t\t\t\tspeed *= 2.0f;\n\t\t\t\t\t\n\t\t\t\t\tif ( ( psystem->m_Type == PARTICLE_BOAT_SPLASH || psystem->m_Type == PARTICLE_CAR_SPLASH )\n\t\t\t\t\t\t\t&& particle->m_fSize > 1.2f )\n\t\t\t\t\t{\n\t\t\t\t\t\tsize = particle->m_fSize - (1.0f + speed) * particle->m_fExpansionRate;\n\t\t\t\t\t\tparticle->m_vecVelocity.z -= 0.15f;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t\tsize = particle->m_fSize + (1.0f + speed) * particle->m_fExpansionRate;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\tsize = particle->m_fSize + particle->m_fExpansionRate;\n\t\t\t\t\n\t\t\t\tif ( psystem->m_Type == PARTICLE_WATERDROP )\n\t\t\t\t\tsize = (size - Abs(vecMoveStep.x) * 0.000150000007f) + (Abs(vecMoveStep.z) * 0.0500000007f); //TODO:\n\t\t\t\t\n\t\t\t\tif ( size < 0.0f )\n\t\t\t\t{\n\t\t\t\t\tbRemoveParticle = true;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tparticle->m_fSize = size;\n\t\t\t}\n\t\t\t\n\t\t\tswitch ( psystem->m_nFrictionDecceleration )\n\t\t\t{\n\t\t\t\tcase 50:\n\t\t\t\t\tparticle->m_vecVelocity *= fFricDeccel50;\n\t\t\t\t\tbreak;\n\t\t\n\t\t\t\tcase 80:\n\t\t\t\t\tparticle->m_vecVelocity *= fFricDeccel80;\n\t\t\t\t\tbreak;\n\t\t\n\t\t\t\tcase 90:\n\t\t\t\t\tparticle->m_vecVelocity *= fFricDeccel90;\n\t\t\t\t\tbreak;\n\t\t\n\t\t\t\tcase 95:\n\t\t\t\t\tparticle->m_vecVelocity *= fFricDeccel95;\n\t\t\t\t\tbreak;\n\t\t\n\t\t\t\tcase 96:\n\t\t\t\t\tparticle->m_vecVelocity *= fFricDeccel96;\n\t\t\t\t\tbreak;\n\t\t\n\t\t\t\tcase 99:\n\t\t\t\t\tparticle->m_vecVelocity *= fFricDeccel99;\n\t\t\t\t\tbreak;\t\t\t\t\n\t\t\t}\n\t\t\t\n\t\t\tif ( psystem->m_fGravitationalAcceleration > 0.0f )\n\t\t\t{\n\t\t\t\tif ( -50.0f * psystem->m_fGravitationalAcceleration < particle->m_vecVelocity.z )\n\t\t\t\t\tparticle->m_vecVelocity.z -= psystem->m_fGravitationalAcceleration * CTimer::GetTimeStep();\n\n\t\t\t\tif ( psystem->Flags & ZCHECK_FIRST )\n\t\t\t\t{\n\t\t\t\t\tif ( particle->m_vecPosition.z < particle->m_fZGround )\n\t\t\t\t\t{\n\t\t\t\t\t\tswitch ( psystem->m_Type )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcase PARTICLE_RAINDROP:\n\t\t\t\t\t\t\tcase PARTICLE_RAINDROP_SMALL:\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tbRemoveParticle = true;\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\tif ( CGeneral::GetRandomNumber() & 1 )\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tAddParticle(PARTICLE_RAIN_SPLASH,\n\t\t\t\t\t\t\t\t\t\t\t\t\tCVector\n\t\t\t\t\t\t\t\t\t\t\t\t\t(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tparticle->m_vecPosition.x,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tparticle->m_vecPosition.y,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t0.05f + particle->m_fZGround\n\t\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t\t\tCVector(0.0f, 0.0f, 0.0f), nil, 0.0f, 0, 0, 0, 0);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tAddParticle(PARTICLE_RAIN_SPLASHUP,\n\t\t\t\t\t\t\t\t\t\t\t\t\tCVector\n\t\t\t\t\t\t\t\t\t\t\t\t\t(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tparticle->m_vecPosition.x,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tparticle->m_vecPosition.y,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t0.05f + particle->m_fZGround\n\t\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t\t\tCVector(0.0f, 0.0f, 0.0f), nil, 0.0f, 0, 0, 0, 0);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase PARTICLE_WHEEL_WATER:\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tbRemoveParticle = true;\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\tint32 randVal = CGeneral::GetRandomNumber();\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\tif ( randVal & 1 )\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tif ( (randVal % 5) == 0 )\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tAddParticle(PARTICLE_RAIN_SPLASH,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tCVector\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tparticle->m_vecPosition.x,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tparticle->m_vecPosition.y,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t0.05f + particle->m_fZGround\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tCVector(0.0f, 0.0f, 0.0f), nil, 0.0f, 0, 0, 0, 0);\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tAddParticle(PARTICLE_RAIN_SPLASHUP,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tCVector\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tparticle->m_vecPosition.x,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tparticle->m_vecPosition.y,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t0.05f + particle->m_fZGround\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tCVector(0.0f, 0.0f, 0.0f), nil, 0.0f, 0, 0, 0, 0);\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase PARTICLE_BLOOD:\n\t\t\t\t\t\t\tcase PARTICLE_BLOOD_SMALL:\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tbRemoveParticle = true;\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\tCVector vecPosn = particle->m_vecPosition;\n\t\t\t\t\t\t\t\t\tvecPosn.z += 1.0f;\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\tRandomizer++;\n\t\t\t\t\t\t\t\t\tint32 randVal = int32(Randomizer & 7);\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\tif ( randVal == 5 )\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tCShadows::AddPermanentShadow(SHADOWTYPE_DARK, gpBloodPoolTex, &vecPosn,\n\t\t\t\t\t\t\t\t\t\t\t\t0.1f, 0.0f, 0.0f, -0.1f,\n\t\t\t\t\t\t\t\t\t\t\t\t255,\n\t\t\t\t\t\t\t\t\t\t\t\t255, 0, 0,\n\t\t\t\t\t\t\t\t\t\t\t\t4.0f, (CGeneral::GetRandomNumber() & 4095) + 2000, 1.0f);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\telse if ( randVal == 2 )\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tCShadows::AddPermanentShadow(SHADOWTYPE_DARK, gpBloodPoolTex, &vecPosn,\n\t\t\t\t\t\t\t\t\t\t\t\t0.2f, 0.0f, 0.0f, -0.2f,\n\t\t\t\t\t\t\t\t\t\t\t\t255,\n\t\t\t\t\t\t\t\t\t\t\t\t255, 0, 0,\n\t\t\t\t\t\t\t\t\t\t\t\t4.0f, (CGeneral::GetRandomNumber() & 4095) + 8000, 1.0f);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tdefault: break;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if ( psystem->Flags & ZCHECK_STEP )\n\t\t\t\t{\n\t\t\t\t\tCColPoint point;\n\t\t\t\t\tCEntity *entity;\n\n\t\t\t\t\tif ( CWorld::ProcessVerticalLine(particle->m_vecPosition, vecPos.z, point, entity, \n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttrue, true, false, false, true, false, nil) )\n\t\t\t\t\t{\n\t\t\t\t\t\tif ( vecPos.z <= point.point.z )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tvecPos.z = point.point.z;\n\t\t\t\t\t\t\tif ( psystem->m_Type == PARTICLE_DEBRIS2 )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tparticle->m_vecVelocity.x *= 0.8f;\n\t\t\t\t\t\t\t\tparticle->m_vecVelocity.y *= 0.8f;\n\t\t\t\t\t\t\t\tparticle->m_vecVelocity.z *= -0.4f;\n\t\t\t\t\t\t\t\tif ( particle->m_vecVelocity.z < 0.005f )\n\t\t\t\t\t\t\t\t\tparticle->m_vecVelocity.z = 0.0f;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if ( psystem->Flags & ZCHECK_BUMP )\n\t\t\t\t{\n\t\t\t\t\tif ( particle->m_vecPosition.z < particle->m_fZGround )\n\t\t\t\t\t{\n\t\t\t\t\t\tswitch ( psystem->m_Type )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcase PARTICLE_GUNSHELL_FIRST:\n\t\t\t\t\t\t\tcase PARTICLE_GUNSHELL:\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tbRemoveParticle = true;\n\n\t\t\t\t\t\t\t\t\tAddParticle(PARTICLE_GUNSHELL_BUMP1,\n\t\t\t\t\t\t\t\t\t\t\t\tCVector\n\t\t\t\t\t\t\t\t\t\t\t\t(\n\t\t\t\t\t\t\t\t\t\t\t\t\tparticle->m_vecPosition.x,\n\t\t\t\t\t\t\t\t\t\t\t\t\tparticle->m_vecPosition.y,\n\t\t\t\t\t\t\t\t\t\t\t\t\t0.05f + particle->m_fZGround\n\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t\tCVector\n\t\t\t\t\t\t\t\t\t\t\t\t(\n\t\t\t\t\t\t\t\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(-0.02f, 0.02f),\n\t\t\t\t\t\t\t\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(-0.02f, 0.02f),\n\t\t\t\t\t\t\t\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(0.05f, 0.1f)\n\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t\tnil,\n\t\t\t\t\t\t\t\t\t\t\t\tparticle->m_fSize, color, particle->m_nRotationStep, 0, 0, 0);\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\tPlayOneShotScriptObject(SCRIPT_SOUND_GUNSHELL_DROP, particle->m_vecPosition);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tcase PARTICLE_GUNSHELL_BUMP1:\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tbRemoveParticle = true;\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\tAddParticle(PARTICLE_GUNSHELL_BUMP2,\n\t\t\t\t\t\t\t\t\t\t\t\tCVector\n\t\t\t\t\t\t\t\t\t\t\t\t(\n\t\t\t\t\t\t\t\t\t\t\t\t\tparticle->m_vecPosition.x,\n\t\t\t\t\t\t\t\t\t\t\t\t\tparticle->m_vecPosition.y,\n\t\t\t\t\t\t\t\t\t\t\t\t\t0.05f + particle->m_fZGround\n\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t\tCVector(0.0f, 0.0f, CGeneral::GetRandomNumberInRange(0.03f, 0.06f)),\n\t\t\t\t\t\t\t\t\t\t\t\tnil,\n\t\t\t\t\t\t\t\t\t\t\t\tparticle->m_fSize, color, 0, 0, 0, 0);\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\tPlayOneShotScriptObject(SCRIPT_SOUND_GUNSHELL_DROP_SOFT, particle->m_vecPosition);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tcase PARTICLE_GUNSHELL_BUMP2:\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tbRemoveParticle = true;\n\t\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tdefault: break;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif ( psystem->m_fGravitationalAcceleration < 0.0f )\n\t\t\t\t{\n\t\t\t\t\tif ( -5.0f * psystem->m_fGravitationalAcceleration > particle->m_vecVelocity.z )\n\t\t\t\t\t\tparticle->m_vecVelocity.z -= psystem->m_fGravitationalAcceleration * CTimer::GetTimeStep();\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tif ( psystem->Flags & ZCHECK_STEP )\n\t\t\t\t\t{\n\t\t\t\t\t\tCColPoint point;\n\t\t\t\t\t\tCEntity *entity;\n\t\t\t\n\t\t\t\t\t\tif ( CWorld::ProcessVerticalLine(particle->m_vecPosition, vecPos.z, point, entity,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttrue, false, false, false, true, false, nil) )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif ( vecPos.z <= point.point.z )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tvecPos.z = point.point.z;\n\t\t\t\t\t\t\t\tif ( psystem->m_Type == PARTICLE_HELI_ATTACK )\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tbRemoveParticle = true;\n\t\t\t\t\t\t\t\t\tAddParticle(PARTICLE_STEAM, vecPos, CVector(0.0f, 0.0f, 0.05f), nil, 0.2f, 0, 0, 0, 0);\n\t\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( particle->m_nFadeToBlackTimer != 0 )\n\t\t\t{\n\t\t\t\tparticle->m_nColorIntensity = clamp(particle->m_nColorIntensity - particle->m_nFadeToBlackTimer,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t0, 255);\n\t\t\t}\n\n\t\t\tif ( particle->m_nFadeAlphaTimer != 0 )\n\t\t\t{\n\t\t\t\tparticle->m_nAlpha = clamp(particle->m_nAlpha - particle->m_nFadeAlphaTimer,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t0, 255);\n\t\t\t\tif ( particle->m_nAlpha == 0 )\n\t\t\t\t{\n\t\t\t\t\tbRemoveParticle = true;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tif ( psystem->m_nZRotationAngleChangeAmount != 0 )\n\t\t\t{\n\t\t\t\tif ( particle->m_nZRotationTimer >= psystem->m_nZRotationChangeTime )\n\t\t\t\t{\n\t\t\t\t\tparticle->m_nZRotationTimer = 0;\n\t\t\t\t\tparticle->m_nCurrentZRotation += psystem->m_nZRotationAngleChangeAmount;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\t++particle->m_nZRotationTimer;\n\t\t\t}\n\t\t\t\n\t\t\tif ( psystem->m_fZRadiusChangeAmount != 0.0f )\n\t\t\t{\n\t\t\t\tif ( particle->m_nZRadiusTimer >= psystem->m_nZRadiusChangeTime )\n\t\t\t\t{\n\t\t\t\t\tparticle->m_nZRadiusTimer = 0;\n\t\t\t\t\tparticle->m_fCurrentZRadius += psystem->m_fZRadiusChangeAmount;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\t++particle->m_nZRadiusTimer;\n\t\t\t}\n\n\t\t\tif ( psystem->m_nAnimationSpeed != 0 )\n\t\t\t{\n\t\t\t\tif ( particle->m_nAnimationSpeedTimer > psystem->m_nAnimationSpeed )\n\t\t\t\t{\n\t\t\t\t\tparticle->m_nAnimationSpeedTimer = 0;\n\t\t\t\t\t\n\t\t\t\t\tif ( ++particle->m_nCurrentFrame > psystem->m_nFinalAnimationFrame )\n\t\t\t\t\t{\n\t\t\t\t\t\tif ( psystem->Flags & CYCLE_ANIM )\n\t\t\t\t\t\t\tparticle->m_nCurrentFrame = psystem->m_nStartAnimationFrame;\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\t--particle->m_nCurrentFrame;\n\t\t\t\t\t}\t\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\t++particle->m_nAnimationSpeedTimer;\n\t\t\t}\n\t\t\t\n\t\t\tif ( particle->m_nRotationStep != 0 )\n#ifdef FIX_BUGS\n\t\t\t\tparticle->m_nRotation = CGeneral::LimitAngle(particle->m_nRotation + particle->m_nRotationStep);\n#else\n\t\t\t\tparticle->m_nRotation += particle->m_nRotationStep;\n#endif\n\t\t\t\n\t\t\tif ( particle->m_fCurrentZRadius != 0.0f )\n\t\t\t{\n\t\t\t\tint32 nSinCosIndex = particle->m_nCurrentZRotation % SIN_COS_TABLE_SIZE;\n\t\t\t\t\n\t\t\t\tfloat fX = (Cos(nSinCosIndex) - Sin(nSinCosIndex)) * particle->m_fCurrentZRadius;\n\t\t\t\t\n\t\t\t\tfloat fY = (Sin(nSinCosIndex) + Cos(nSinCosIndex)) * particle->m_fCurrentZRadius;\n\n\t\t\t\tvecPos -= particle->m_vecParticleMovementOffset;\n\n\t\t\t\tvecPos += CVector(fX, fY, 0.0f);\n\t\t\t\t\n\t\t\t\tparticle->m_vecParticleMovementOffset = CVector(fX, fY, 0.0f);\n\t\t\t}\n\t\t\t\n\t\t\tparticle->m_vecPosition = vecPos;\n\t\t}\n\t}\n}\n\nvoid CParticle::Render()\n{\n\tPUSH_RENDERGROUP(\"CParticle::Render\");\n\n\tRwRenderStateSet(rwRENDERSTATETEXTUREADDRESS, (void *)rwTEXTUREADDRESSWRAP);\n\tRwRenderStateSet(rwRENDERSTATETEXTUREPERSPECTIVE, (void *)TRUE);\n\tRwRenderStateSet(rwRENDERSTATEFOGENABLE, (void *)FALSE);\n\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void *)FALSE);\n\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)TRUE);\n\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDSRCALPHA);\n\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDINVSRCALPHA);\n\t\n\tCSprite::InitSpriteBuffer2D();\n\t\n\tuint32 flags = DRAW_OPAQUE;\n\t\n\tRwRaster *prevFrame = nil;\n\t\n\tfor ( int32 i = 0; i < MAX_PARTICLES; i++ )\n\t{\n\t\ttParticleSystemData *psystem = &mod_ParticleSystemManager.m_aParticles[i];\n\t\tbool particleBanned = false;\n\t\tCParticle *particle = psystem->m_pParticles;\n\t\t\n\t\tRwRaster **frames = psystem->m_ppRaster;\n\t\ttParticleType type = psystem->m_Type;\n\n\t\tif ( type == PARTICLE_ENGINE_SMOKE\n\t\t\t|| type == PARTICLE_ENGINE_SMOKE2\n\t\t\t|| type == PARTICLE_ENGINE_STEAM\n\t\t\t|| type == PARTICLE_CARFLAME_SMOKE\n\t\t\t|| type == PARTICLE_RUBBER_SMOKE\n\t\t\t|| type == PARTICLE_BURNINGRUBBER_SMOKE\n\t\t\t|| type == PARTICLE_EXHAUST_FUMES\n\t\t\t|| type == PARTICLE_CARCOLLISION_DUST )\n\t\t{\n\t\t\tparticleBanned = true;\n\t\t}\n\n\t\tif ( particle )\n\t\t{\n\t\t\tif ( (flags & DRAW_OPAQUE) != (psystem->Flags & DRAW_OPAQUE)\n\t\t\t\t|| (flags & DRAW_DARK) != (psystem->Flags & DRAW_DARK) )\n\t\t\t{\n\t\t\t\tCSprite::FlushSpriteBuffer();\n\t\t\t\t\n\t\t\t\tif ( psystem->Flags & DRAW_OPAQUE )\n\t\t\t\t{\n\t\t\t\t\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDSRCALPHA);\n\t\t\t\t\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDINVSRCALPHA);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tif ( psystem->Flags & DRAW_DARK )\n\t\t\t\t\t\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDSRCALPHA);\n\t\t\t\t\telse\n\t\t\t\t\t\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDONE);\n\t\n\t\t\t\t\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDONE);\n\t\t\t\t}\n\n\t\t\t\tflags = psystem->Flags;\n\t\t\t}\n\t\t\t\n\t\t\tif ( frames != nil )\n\t\t\t{\n\t\t\t\tRwRaster *curFrame = *frames;\n\t\t\t\tif ( curFrame != prevFrame )\n\t\t\t\t{\n\t\t\t\t\tCSprite::FlushSpriteBuffer();\n\t\t\t\t\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void *)curFrame);\n\t\t\t\t\tprevFrame = curFrame;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t\n\t\twhile ( particle != nil )\n\t\t{\n\t\t\tbool canDraw = true;\n\n\t\t\tif ( particle->m_nAlpha == 0 )\n\t\t\t\tcanDraw = false;\n\t\t\t\n\t\t\tif ( canDraw && psystem->m_nFinalAnimationFrame != 0 && frames != nil )\n\t\t\t{\n\t\t\t\tRwRaster *curFrame = frames[particle->m_nCurrentFrame];\n\t\t\t\tif ( prevFrame != curFrame )\n\t\t\t\t{\n\t\t\t\t\tCSprite::FlushSpriteBuffer();\n\t\t\t\t\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void *)curFrame);\n\t\t\t\t\tprevFrame = curFrame;\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tif ( canDraw && psystem->Flags & DRAWTOP2D )\n\t\t\t{\n\t\t\t\tfloat screenZ = (particle->m_vecPosition.z - CDraw::GetNearClipZ())\n\t\t\t\t\t* (CSprite::GetFarScreenZ() - CSprite::GetNearScreenZ())\n\t\t\t\t\t* CDraw::GetFarClipZ()\n\t\t\t\t\t/ ( (CDraw::GetFarClipZ() - CDraw::GetNearClipZ()) * particle->m_vecPosition.z )\n\t\t\t\t\t+ CSprite::GetNearScreenZ();\n\t\t\t\t\n\t\t\t\tfloat stretchTexW;\n\t\t\t\tfloat stretchTexH;\n\t\t\t\t\t\n\t\t\t\tif ( i == PARTICLE_RAINDROP || i == PARTICLE_RAINDROP_SMALL || i == PARTICLE_RAINDROP_2D )\n\t\t\t\t{\n\t\t\t\t\tstretchTexW = CGeneral::GetRandomNumberInRange(0.1f, 1.0f) * psystem->m_vecTextureStretch.x * (float)particle->m_nCurrentFrame + 63.0f;\n\t\t\t\t\tstretchTexH = CGeneral::GetRandomNumberInRange(0.1f, 1.0f) * psystem->m_vecTextureStretch.y * (float)particle->m_nCurrentFrame + 63.0f;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tstretchTexW = CGeneral::GetRandomNumberInRange(0.1f, 1.0f) * psystem->m_vecTextureStretch.x + 63.0f;\n\t\t\t\t\tstretchTexH = CGeneral::GetRandomNumberInRange(0.1f, 1.0f) * psystem->m_vecTextureStretch.y + 63.0f;\n\t\t\t\t}\n\n\t\t\t\t\n\t\t\t\tif ( i == PARTICLE_WATERDROP )\n\t\t\t\t{\n\t\t\t\t\tint32 timeLeft = (particle->m_nTimeWhenWillBeDestroyed - CTimer::GetTimeInMilliseconds()) / particle->m_nTimeWhenWillBeDestroyed;\n\t\t\t\t\t\n\t\t\t\t\tstretchTexH += (1.0f - (float)timeLeft ) * psystem->m_vecTextureStretch.y;\n\t\t\t\t\t\n\t\t\t\t\tRwRect rect;\n\t\t\t\t\t\n\t\t\t\t\trect.x = int32(particle->m_vecPosition.x - SCREEN_STRETCH_X(particle->m_fSize * stretchTexW));\n\t\t\t\t\trect.y = int32(particle->m_vecPosition.y - SCREEN_STRETCH_Y(particle->m_fSize * stretchTexH));\n\t\t\t\t\trect.w = int32(particle->m_vecPosition.x + SCREEN_STRETCH_X(particle->m_fSize * stretchTexW));\n\t\t\t\t\trect.h = int32(particle->m_vecPosition.y + SCREEN_STRETCH_Y(particle->m_fSize * stretchTexH));\n\t\t\t\t\t\n\t\t\t\t\tFxType fxtype;\n\n\t\t\t\t\tif ( particle->m_nCurrentFrame != 0 )\n\t\t\t\t\t\tfxtype = FXTYPE_WATER2;\n\t\t\t\t\telse\n\t\t\t\t\t\tfxtype = FXTYPE_WATER1;\n\t\t\n\t\t\t\t\tCMBlur::AddRenderFx(Scene.camera, &rect, screenZ, fxtype);\n\t\t\t\t\t\n\t\t\t\t\tcanDraw = false;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif ( i == PARTICLE_BLOODDROP )\n\t\t\t\t{\n\t\t\t\t\tint32 timeLeft = (particle->m_nTimeWhenWillBeDestroyed - CTimer::GetTimeInMilliseconds()) / particle->m_nTimeWhenWillBeDestroyed;\n\t\t\t\t\t\n\t\t\t\t\tstretchTexH += (1.0f + (float)timeLeft) * psystem->m_vecTextureStretch.y;\n\t\t\t\t\tstretchTexW += (1.0f - (float)timeLeft) * psystem->m_vecTextureStretch.x;\n\n\t\t\t\t\tRwRect rect;\n\n\t\t\t\t\trect.x = int32(particle->m_vecPosition.x - SCREEN_STRETCH_X(particle->m_fSize * stretchTexW));\n\t\t\t\t\trect.y = int32(particle->m_vecPosition.y - SCREEN_STRETCH_Y(particle->m_fSize * stretchTexH));\n\t\t\t\t\trect.w = int32(particle->m_vecPosition.x + SCREEN_STRETCH_X(particle->m_fSize * stretchTexW));\n\t\t\t\t\trect.h = int32(particle->m_vecPosition.y + SCREEN_STRETCH_Y(particle->m_fSize * stretchTexH));\n\t\t\t\t\t\n\t\t\t\t\tFxType fxtype;\n\t\t\t\t\t\n\t\t\t\t\tif ( particle->m_nCurrentFrame )\n\t\t\t\t\t\tfxtype = FXTYPE_BLOOD2;\n\t\t\t\t\telse\n\t\t\t\t\t\tfxtype = FXTYPE_BLOOD1;\n\t\t\t\t\t\n\t\t\t\t\tCMBlur::AddRenderFx(Scene.camera, &rect, screenZ, fxtype);\n\t\t\t\t\t\n\t\t\t\t\tcanDraw = false;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif ( i == PARTICLE_HEATHAZE_IN_DIST )\n\t\t\t\t{\n\t\t\t\t\tRwRect rect;\n\t\t\t\t\t\n\t\t\t\t\trect.x = int32(particle->m_vecPosition.x - SCREEN_STRETCH_X(particle->m_fSize * stretchTexW));\n\t\t\t\t\trect.y = int32(particle->m_vecPosition.y - SCREEN_STRETCH_Y(particle->m_fSize * stretchTexH * 0.15f));\n\t\t\t\t\trect.w = int32(particle->m_vecPosition.x + SCREEN_STRETCH_X(particle->m_fSize * stretchTexW));\n\t\t\t\t\trect.h = int32(particle->m_vecPosition.y + SCREEN_STRETCH_Y(particle->m_fSize * stretchTexH * 0.15f));\n\t\t\t\t\t\n\t\t\t\t\tCMBlur::AddRenderFx(Scene.camera, &rect, screenZ, FXTYPE_HEATHAZE);\n\t\t\t\t\t\n\t\t\t\t\tcanDraw = false;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif ( i == PARTICLE_HEATHAZE )\n\t\t\t\t{\n\t\t\t\t\tRwRect rect;\n\t\t\t\t\t\n\t\t\t\t\tswitch ( TheCamera.GetLookDirection() )\n\t\t\t\t\t{\n\t\t\t\t\t\tcase LOOKING_LEFT:\n\t\t\t\t\t\t\trect.x = int32(particle->m_vecPosition.x - SCREEN_STRETCH_X(particle->m_fSize * psystem->m_vecTextureStretch.x * 2.0f));\n\t\t\t\t\t\t\trect.y = int32(particle->m_vecPosition.y - SCREEN_STRETCH_Y(particle->m_fSize * psystem->m_vecTextureStretch.y));\n\t\t\t\t\t\t\trect.w = int32(particle->m_vecPosition.x - SCREEN_STRETCH_X(particle->m_fSize * psystem->m_vecTextureStretch.x));\n\t\t\t\t\t\t\trect.h = int32(particle->m_vecPosition.y + SCREEN_STRETCH_Y(particle->m_fSize * psystem->m_vecTextureStretch.y));\n\t\t\t\t\t\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase LOOKING_RIGHT:\n\t\t\t\t\t\t\trect.x = int32(particle->m_vecPosition.x + SCREEN_STRETCH_X(particle->m_fSize * psystem->m_vecTextureStretch.x));\n\t\t\t\t\t\t\trect.y = int32(particle->m_vecPosition.y - SCREEN_STRETCH_Y(particle->m_fSize * psystem->m_vecTextureStretch.y));\n\t\t\t\t\t\t\trect.w = int32(particle->m_vecPosition.x + SCREEN_STRETCH_X(particle->m_fSize * psystem->m_vecTextureStretch.x * 4.0f));\n\t\t\t\t\t\t\trect.h = int32(particle->m_vecPosition.y + SCREEN_STRETCH_Y(particle->m_fSize * psystem->m_vecTextureStretch.y));\n\t\t\t\t\t\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\trect.x = int32(particle->m_vecPosition.x - SCREEN_STRETCH_X(particle->m_fSize * psystem->m_vecTextureStretch.x));\n\t\t\t\t\t\t\trect.y = int32(particle->m_vecPosition.y - SCREEN_STRETCH_Y(particle->m_fSize * psystem->m_vecTextureStretch.y));\n\t\t\t\t\t\t\trect.w = int32(particle->m_vecPosition.x + SCREEN_STRETCH_X(particle->m_fSize * psystem->m_vecTextureStretch.x));\n\t\t\t\t\t\t\trect.h = int32(particle->m_vecPosition.y + SCREEN_STRETCH_Y(particle->m_fSize * psystem->m_vecTextureStretch.y));\n\t\t\t\t\t\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t \n\t\t\t\t\tCMBlur::AddRenderFx(Scene.camera, &rect, screenZ, FXTYPE_HEATHAZE);\n\t\t\t\t\t\n\t\t\t\t\tcanDraw = false;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif ( canDraw )\n\t\t\t\t{\n\t\t\t\t\tif ( particle->m_nRotation != 0 )\n\t\t\t\t\t{\n\t\t\t\t\t\tCSprite::RenderBufferedOneXLUSprite2D_Rotate_Dimension(\n\t\t\t\t\t\t\t\tparticle->m_vecPosition.x,\n\t\t\t\t\t\t\t\tparticle->m_vecPosition.y,\n\t\t\t\t\t\t\t\tparticle->m_fSize * stretchTexW,\n\t\t\t\t\t\t\t\tparticle->m_fSize * stretchTexH,\n\t\t\t\t\t\t\t\tparticle->m_Color,\n\t\t\t\t\t\t\t\tparticle->m_nColorIntensity,\n\t\t\t\t\t\t\t\tDEGTORAD((float)particle->m_nRotation),\n\t\t\t\t\t\t\t\tparticle->m_nAlpha);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tCSprite::RenderBufferedOneXLUSprite2D(\n\t\t\t\t\t\t\t\tparticle->m_vecPosition.x,\n\t\t\t\t\t\t\t\tparticle->m_vecPosition.y,\n\t\t\t\t\t\t\t\tparticle->m_fSize * stretchTexW,\n\t\t\t\t\t\t\t\tparticle->m_fSize * stretchTexH,\n\t\t\t\t\t\t\t\tparticle->m_Color,\n\t\t\t\t\t\t\t\tparticle->m_nColorIntensity,\n\t\t\t\t\t\t\t\tparticle->m_nAlpha);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tcanDraw = false;\n\t\t\t}\n\t\t\t\n\t\t\tif ( canDraw )\n\t\t\t{\n\t\t\t\tCVector coors;\n\t\t\t\tfloat w;\n\t\t\t\tfloat h;\n\n\t\t\t\tif ( CSprite::CalcScreenCoors(particle->m_vecPosition, &coors, &w, &h, true) )\n\t\t\t\t{\n\t\t\t\t\t\n\t\t\t\t\tif ( i == PARTICLE_ENGINE_STEAM\n\t\t\t\t\t\t|| i == PARTICLE_ENGINE_SMOKE\n\t\t\t\t\t\t|| i == PARTICLE_ENGINE_SMOKE2\n\t\t\t\t\t\t|| i == PARTICLE_CARFLAME_SMOKE\n\t\t\t\t\t\t|| i == PARTICLE_CARCOLLISION_DUST\n\t\t\t\t\t\t|| i == PARTICLE_EXHAUST_FUMES\n\t\t\t\t\t\t|| i == PARTICLE_RUBBER_SMOKE\n\t\t\t\t\t\t|| i == PARTICLE_BURNINGRUBBER_SMOKE )\n\t\t\t\t\t{\n\t\t\t\t\t\tswitch ( TheCamera.GetLookDirection() )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcase LOOKING_LEFT:\n\t\t\t\t\t\t\tcase LOOKING_RIGHT:\n\t\t\t\t\t\t\t\tw += CGeneral::GetRandomNumberInRange(1.0f, 7.5f) * psystem->m_vecTextureStretch.x;\n\t\t\t\t\t\t\t\th += CGeneral::GetRandomNumberInRange(0.1f, 1.0f) * psystem->m_vecTextureStretch.y;\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\tw += CGeneral::GetRandomNumberInRange(0.1f, 1.0f) * psystem->m_vecTextureStretch.x;\n\t\t\t\t\t\t\t\th += CGeneral::GetRandomNumberInRange(0.1f, 1.0f) * psystem->m_vecTextureStretch.y;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse if ( i == PARTICLE_WATER_HYDRANT )\n\t\t\t\t\t{\n\t\t\t\t\t\tint32 timeLeft = (particle->m_nTimeWhenWillBeDestroyed - CTimer::GetTimeInMilliseconds()) / particle->m_nTimeWhenWillBeDestroyed;\n\t\t\t\t\t\n\t\t\t\t\t\tw += (1.0f - (float)timeLeft) * psystem->m_vecTextureStretch.x;\n\t\t\t\t\t\th += (1.0f - (float)timeLeft) * psystem->m_vecTextureStretch.y;\n\t\t\t\t\t}\n\t\t\t\t\telse if ( i == PARTICLE_FLYERS )\n\t\t\t\t\t{\n\t\t\t\t\t\tw += psystem->m_vecTextureStretch.x;\n\t\t\t\t\t\th += psystem->m_vecTextureStretch.y;\n\t\t\t\t\t\t\n\t\t\t\t\t\tw = Max(w, 12.0f);\n\t\t\t\t\t\th = Max(h, 12.0f);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tw += CGeneral::GetRandomNumberInRange(0.1f, 1.0f) * psystem->m_vecTextureStretch.x;\n\t\t\t\t\t\th += CGeneral::GetRandomNumberInRange(0.1f, 1.0f) * psystem->m_vecTextureStretch.y;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tif ( i == PARTICLE_WATER_HYDRANT\n\t\t\t\t\t\t\t|| (!particleBanned || SCREEN_WIDTH * fParticleScaleLimit >= w)\n\t\t\t\t\t\t\t&& SCREEN_HEIGHT * fParticleScaleLimit >= h )\n\t\t\t\t\t{\n\t\t\t\t\t\tif ( i == PARTICLE_WATER_HYDRANT )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tRwRect rect;\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tif ( w > 0.0f )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\trect.x = int32(coors.x - SCREEN_STRETCH_X(particle->m_fSize * w));\n\t\t\t\t\t\t\t\trect.w = int32(coors.x + SCREEN_STRETCH_X(particle->m_fSize * w));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\trect.w = int32(coors.x - SCREEN_STRETCH_X(particle->m_fSize * w));\n\t\t\t\t\t\t\t\trect.x = int32(coors.x + SCREEN_STRETCH_X(particle->m_fSize * w));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tif ( h > 0.0f )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\trect.y = int32(coors.y - SCREEN_STRETCH_Y(particle->m_fSize * h));\n\t\t\t\t\t\t\t\trect.h = int32(coors.y + SCREEN_STRETCH_Y(particle->m_fSize * h));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\trect.h = int32(coors.y - SCREEN_STRETCH_Y(particle->m_fSize * h));\n\t\t\t\t\t\t\t\trect.y = int32(coors.y + SCREEN_STRETCH_Y(particle->m_fSize * h));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tfloat screenZ = (coors.z - CDraw::GetNearClipZ())\n\t\t\t\t\t\t\t\t* (CSprite::GetFarScreenZ() - CSprite::GetNearScreenZ()) * CDraw::GetFarClipZ()\n\t\t\t\t\t\t\t\t/ ( (CDraw::GetFarClipZ() - CDraw::GetNearClipZ()) * coors.z ) + CSprite::GetNearScreenZ();\n\n\t\t\t\t\t\t\tCMBlur::AddRenderFx(Scene.camera, &rect, screenZ, FXTYPE_SPLASH1);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif ( particle->m_nRotation != 0 && i != PARTICLE_BEASTIE )\n\t\t\t\t\t\t\t{\t\t\t\t\t\n\t\t\t\t\t\t\t\tCSprite::RenderBufferedOneXLUSprite_Rotate_Dimension(coors.x, coors.y, coors.z,\n\t\t\t\t\t\t\t\t\t\tparticle->m_fSize * w, particle->m_fSize * h,\n\t\t\t\t\t\t\t\t\t\tparticle->m_Color.red,\n\t\t\t\t\t\t\t\t\t\tparticle->m_Color.green,\n\t\t\t\t\t\t\t\t\t\tparticle->m_Color.blue,\n\t\t\t\t\t\t\t\t\t\tparticle->m_nColorIntensity,\n\t\t\t\t\t\t\t\t\t\t1.0f / coors.z,\n\t\t\t\t\t\t\t\t\t\tDEGTORAD((float)particle->m_nRotation),\n\t\t\t\t\t\t\t\t\t\tparticle->m_nAlpha);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse if ( psystem->Flags & SCREEN_TRAIL )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tfloat fRotation;\n\t\t\t\t\t\t\t\tfloat fTrailLength;\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\tif ( particle->m_fZGround == 0.0f )\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tfTrailLength = 0.0f;\n\t\t\t\t\t\t\t\t\tfRotation = 0.0f;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tCVector2D vecDist\n\t\t\t\t\t\t\t\t\t(\n\t\t\t\t\t\t\t\t\t\tcoors.x - particle->m_fZGround,\n\t\t\t\t\t\t\t\t\t\tcoors.y - particle->m_fExpansionRate\n\t\t\t\t\t\t\t\t\t);\n\t\n\t\t\t\t\t\t\t\t\tfloat fDist = vecDist.Magnitude();\n\t\n\t\t\t\t\t\t\t\t\tfTrailLength = fDist;\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\tfloat fRot = Asin(vecDist.x / fDist);\n\t\n\t\t\t\t\t\t\t\t\tfRotation = fRot;\n\t\n\t\t\t\t\t\t\t\t\tif ( vecDist.y < 0.0f )\n\t\t\t\t\t\t\t\t\t\tfRotation = -1.0f * fRot + DEGTORAD(180.0f);\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\tfloat fSpeed = particle->m_vecVelocity.Magnitude();\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\tfloat fNewTrailLength = fSpeed * CTimer::GetTimeStep() * w * 2.0f;\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\tif ( fDist > fNewTrailLength )\n\t\t\t\t\t\t\t\t\t\tfTrailLength = fNewTrailLength;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\tCSprite::RenderBufferedOneXLUSprite_Rotate_Dimension(coors.x, coors.y, coors.z,\n\t\t\t\t\t\t\t\t\t\tparticle->m_fSize * w,\n\t\t\t\t\t\t\t\t\t\tparticle->m_fSize * h + fTrailLength * psystem->m_fTrailLengthMultiplier,\n\t\t\t\t\t\t\t\t\t\tparticle->m_Color.red,\n\t\t\t\t\t\t\t\t\t\tparticle->m_Color.green,\n\t\t\t\t\t\t\t\t\t\tparticle->m_Color.blue,\n\t\t\t\t\t\t\t\t\t\tparticle->m_nColorIntensity,\n\t\t\t\t\t\t\t\t\t\t1.0f / coors.z,\n\t\t\t\t\t\t\t\t\t\tfRotation,\n\t\t\t\t\t\t\t\t\t\tparticle->m_nAlpha);\n\t\t\t\t\n\t\t\t\t\t\t\t\tparticle->m_fZGround = coors.x;\t\t\t\t// WTF ?\n\t\t\t\t\t\t\t\tparticle->m_fExpansionRate =  coors.y;\t\t// WTF ?\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse if ( psystem->Flags & SPEED_TRAIL )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tCVector vecPrevPos = particle->m_vecPosition - particle->m_vecVelocity;\n\t\t\t\t\t\t\t\tfloat fRotation;\n\t\t\t\t\t\t\t\tfloat fTrailLength;\n\t\t\t\t\t\t\t\tCVector vecScreenPosition;\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\tif ( CSprite::CalcScreenCoors(vecPrevPos, &vecScreenPosition, &fTrailLength, &fRotation, true) )\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tCVector2D vecDist\n\t\t\t\t\t\t\t\t\t(\n\t\t\t\t\t\t\t\t\t\tcoors.x - vecScreenPosition.x,\n\t\t\t\t\t\t\t\t\t\tcoors.y - vecScreenPosition.y\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\tfloat fDist = vecDist.Magnitude();\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\tfTrailLength = fDist;\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\tfloat fRot = Asin(vecDist.x / fDist);\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\tfRotation = fRot;\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\tif ( vecDist.y < 0.0f )\n\t\t\t\t\t\t\t\t\t\tfRotation = -1.0f * fRot + DEGTORAD(180.0f);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tfRotation = 0.0f;\n\t\t\t\t\t\t\t\t\tfTrailLength = 0.0f;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\tCSprite::RenderBufferedOneXLUSprite_Rotate_Dimension(coors.x, coors.y, coors.z,\n\t\t\t\t\t\t\t\t\t\tparticle->m_fSize * w,\n\t\t\t\t\t\t\t\t\t\tparticle->m_fSize * h + fTrailLength * psystem->m_fTrailLengthMultiplier,\n\t\t\t\t\t\t\t\t\t\tparticle->m_Color.red,\n\t\t\t\t\t\t\t\t\t\tparticle->m_Color.green,\n\t\t\t\t\t\t\t\t\t\tparticle->m_Color.blue,\n\t\t\t\t\t\t\t\t\t\tparticle->m_nColorIntensity,\n\t\t\t\t\t\t\t\t\t\t1.0f / coors.z,\n\t\t\t\t\t\t\t\t\t\tfRotation,\n\t\t\t\t\t\t\t\t\t\tparticle->m_nAlpha);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse if ( psystem->Flags & VERT_TRAIL )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tfloat fTrailLength = fabsf(particle->m_vecVelocity.z * 10.0f);\n\t\n\t\t\t\t\t\t\t\tCSprite::RenderBufferedOneXLUSprite(coors.x, coors.y, coors.z,\n\t\t\t\t\t\t\t\t\t\tparticle->m_fSize * w,\n\t\t\t\t\t\t\t\t\t\t(particle->m_fSize + fTrailLength * psystem->m_fTrailLengthMultiplier) * h,\n\t\t\t\t\t\t\t\t\t\tparticle->m_Color.red,\n\t\t\t\t\t\t\t\t\t\tparticle->m_Color.green,\n\t\t\t\t\t\t\t\t\t\tparticle->m_Color.blue,\n\t\t\t\t\t\t\t\t\t\tparticle->m_nColorIntensity,\n\t\t\t\t\t\t\t\t\t\t1.0f / coors.z,\n\t\t\t\t\t\t\t\t\t\tparticle->m_nAlpha);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse if ( i == PARTICLE_RAINDROP_SMALL )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tCSprite::RenderBufferedOneXLUSprite(coors.x, coors.y, coors.z,\n\t\t\t\t\t\t\t\t\t\tparticle->m_fSize * w * 0.05f,\n\t\t\t\t\t\t\t\t\t\tparticle->m_fSize * h,\n\t\t\t\t\t\t\t\t\t\tparticle->m_Color.red,\n\t\t\t\t\t\t\t\t\t\tparticle->m_Color.green,\n\t\t\t\t\t\t\t\t\t\tparticle->m_Color.blue,\n\t\t\t\t\t\t\t\t\t\tparticle->m_nColorIntensity,\n\t\t\t\t\t\t\t\t\t\t1.0f / coors.z,\n\t\t\t\t\t\t\t\t\t\tparticle->m_nAlpha);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t/*else if ( i == PARTICLE_BOAT_WAKE )*/\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\tCSprite::RenderBufferedOneXLUSprite(coors.x, coors.y, coors.z,\n\t\t\t\t\t\t\t\t\t\tparticle->m_fSize * w,\n\t\t\t\t\t\t\t\t\t\tparticle->m_fSize * h,\n\t\t\t\t\t\t\t\t\t\tparticle->m_Color.red,\n\t\t\t\t\t\t\t\t\t\tparticle->m_Color.green,\n\t\t\t\t\t\t\t\t\t\tparticle->m_Color.blue,\n\t\t\t\t\t\t\t\t\t\tparticle->m_nColorIntensity,\n\t\t\t\t\t\t\t\t\t\t1.0f / coors.z,\n\t\t\t\t\t\t\t\t\t\tparticle->m_nAlpha);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tparticle = particle->m_pNext;\n\t\t}\n\n\t\tCSprite::FlushSpriteBuffer();\n\n\t}\n\t\n\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)FALSE);\n\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void *)TRUE);\n\tRwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)TRUE);\n\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDSRCALPHA);\n\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDINVSRCALPHA);\n\n\tPOP_RENDERGROUP();\n}\n\nvoid CParticle::RemovePSystem(tParticleType type)\n{\n\ttParticleSystemData *psystemdata = &mod_ParticleSystemManager.m_aParticles[type];\n\t\n\tfor ( CParticle *particle = psystemdata->m_pParticles; particle; particle = psystemdata->m_pParticles )\n\t\tRemoveParticle(particle, nil, psystemdata);\n}\n\nvoid CParticle::RemoveParticle(CParticle *pParticle, CParticle *pPrevParticle, tParticleSystemData *pPSystemData)\n{\n\tif ( pPSystemData->m_Type == PARTICLE_WATERDROP )\n\t\t--numWaterDropOnScreen;\n\t\n\tif ( pPrevParticle )\n\t\tpPrevParticle->m_pNext = pParticle->m_pNext;\n\telse\n\t\tpPSystemData->m_pParticles = pParticle->m_pNext;\n\n\tpParticle->m_pNext = m_pUnusedListHead;\n\tm_pUnusedListHead = pParticle;\n}\n\nvoid CParticle::AddJetExplosion(CVector const &vecPos, float fPower, float fSize)\n{\n\tCRGBA color(240, 240, 240, 255);\n\n\tif ( fPower < 1.0f )\n\t\tfPower = 1.0f;\n\t\n\tCVector vecRandOffset\n\t(\n\t\tCGeneral::GetRandomNumberInRange(-0.4f, 0.4f),\n\t\tCGeneral::GetRandomNumberInRange(-0.4f, 0.4f),\n\t\tCGeneral::GetRandomNumberInRange(0.1f, 0.3f)\n\t);\n\t\n\tvecRandOffset *= 2.0f;\n\n\tCVector vecStepPos = vecPos;\n\n\tfor ( int32 i = 0; i < int32(fPower * 4.0f); i++ )\n\t{\n\t\tAddParticle(PARTICLE_EXPLOSION_MFAST,\n\t\t\t\t\tvecStepPos,\n\t\t\t\t\tCVector\n\t\t\t\t\t(\n\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(-0.02f, 0.02f),\n\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(-0.02f, 0.02f),\n\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(-0.02f, 0.0f)\n\t\t\t\t\t),\n\t\t\t\t\tnil,\n\t\t\t\t\tfSize, color, 0, 0, 0, 0);\n\n\t\tAddParticle(PARTICLE_EXPLOSION_MFAST,\n\t\t\t\t\tvecStepPos,\n\t\t\t\t\tCVector\n\t\t\t\t\t(\n\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(-0.04f, 0.04f),\n\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(-0.04f, 0.04f),\n\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(0.0f, 0.07f)\n\t\t\t\t\t),\n\t\t\t\t\tnil,\n\t\t\t\t\tfSize, color, 0, 0, 0, 0);\n\n\t\tAddParticle(PARTICLE_EXPLOSION_MFAST,\n\t\t\t\t\tvecStepPos,\n\t\t\t\t\tCVector\n\t\t\t\t\t(\n\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(-0.04f, 0.04f),\n\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(-0.04f, 0.04f),\n\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(0.0f, 0.07f)\n\t\t\t\t\t),\n\t\t\t\t\tnil,\n\t\t\t\t\tfSize, color, 0, 0, 0, 0);\n\t\t\n\t\tvecStepPos += vecRandOffset;\n\t}\n}\n\nvoid CParticle::AddYardieDoorSmoke(CVector const &vecPos, CMatrix const &matMatrix)\n{\n\tCRGBA color(0, 0, 0, 0);\n\t\n\tCMatrix invMat(Invert(matMatrix));\n\t\n\tCVector vecBasePos = matMatrix * (invMat * vecPos + CVector(0.0f, -1.0f, 0.5f));\n\t\n\tfor ( int32 i = 0; i < 5; i++ )\n\t{\n\t\tCVector pos = vecBasePos;\n\n\t\tpos.x += CGeneral::GetRandomNumberInRange(-0.5f, 0.5f);\n\t\tpos.y += CGeneral::GetRandomNumberInRange(-0.5f, 0.5f);\n\t\t\n\t\tAddParticle(PARTICLE_CARCOLLISION_DUST,\n\t\t\t\t\tpos,\n\t\t\t\t\tCVector(0.0f, 0.0f, 0.0f),\n\t\t\t\t\tnil,\n\t\t\t\t\t0.3f, color, 0, 0, 0, 0);\n\t}\n}\n\nvoid CParticle::CalWindDir(CVector *vecDirIn, CVector *vecDirOut)\n{\n\tvecDirOut->x = (Cos(128) * vecDirIn->x) + (Sin(128) * vecDirIn->y);\n\n\tvecDirOut->x = (Cos(128) * vecDirIn->x) + (Sin(128) * vecDirIn->y) * CWeather::Wind;\n\tvecDirOut->y = (Sin(128) * vecDirIn->x) - (Cos(128) * vecDirIn->y) * CWeather::Wind;\n}\n\nvoid CParticle::HandleShipsAtHorizonStuff()\n{\n\ttParticleSystemData *psystemdata = &mod_ParticleSystemManager.m_aParticles[PARTICLE_SHIP_SIDE];\n\n\tfor ( CParticle *particle = psystemdata->m_pParticles; particle; particle = particle->m_pNext )\n\t{\n\t\tif ( CTimer::GetTimeInMilliseconds() > particle->m_nTimeWhenWillBeDestroyed - 32000 \n\t\t\t\t&& CTimer::GetTimeInMilliseconds() < particle->m_nTimeWhenWillBeDestroyed - 22000 )\n\t\t{\t\t\n\t\t\tparticle->m_nAlpha = Min(particle->m_nAlpha + 1, 96);\n\t\t}\n\t\tif ( CTimer::GetTimeInMilliseconds() > particle->m_nTimeWhenWillBeDestroyed - 10000 )\n\t\t\tparticle->m_nFadeAlphaTimer = 1;\n\t}\n}\n\nvoid CParticle::HandleShootableBirdsStuff(CEntity *entity, CVector const&camPos)\n{\n\tfloat fHeadingRad = entity->GetForward().Heading();\n\tfloat fHeading = RADTODEG(fHeadingRad);\n\tfloat fBirdAngle = ::Cos(DEGTORAD(1.5f));\n\t\n\ttParticleSystemData *psystem = &mod_ParticleSystemManager.m_aParticles[PARTICLE_BIRD_FRONT];\n\tCParticle *particle = psystem->m_pParticles;\n\tCParticle *prevParticle = nil;\n\tbool bRemoveParticle;\n\t\t\t\n\tfor ( ; particle != nil; _Next(particle, prevParticle, psystem, bRemoveParticle) )\n\t{\n\t\tbRemoveParticle = false;\n\t\t\n\t\tCVector2D vecPos(particle->m_vecPosition.x, particle->m_vecPosition.y);\n\t\tCVector2D vecCamPos(camPos.x, camPos.y);\n\n\t\tCVector2D vecDist = vecPos - vecCamPos;\n\t\tvecDist.Normalise();\n\t\t\n\t\tfloat fHead = DEGTORAD(fHeading);\n\n\t\tCVector2D vecDir(-::Sin(fHead), ::Cos(fHead));\n\t\tvecDir.Normalise();\n\t\t\n\t\tfloat fDot = DotProduct2D(vecDir, vecDist);\n\t\t\n\t\tif ( fDot > 0.0f && fDot > fBirdAngle )\n\t\t{\n\t\t\tif ( (camPos - particle->m_vecPosition).MagnitudeSqr() < 40000.0f )\n\t\t\t{\n\t\t\t\tCStats::SeagullsKilled++;\n\t\t\t\t\n\t\t\t\tbRemoveParticle = true;\n\n\t\t\t\tfor ( int32 i = 0; i < 8; i++ )\n\t\t\t\t{\t\n\t\t\t\t\tCParticle *pBirdDerbis = AddParticle(PARTICLE_BIRD_DEBRIS,\n\t\t\t\t\t\t\t\t\t\t\t\tparticle->m_vecPosition,\n\t\t\t\t\t\t\t\t\t\t\t\tCVector\n\t\t\t\t\t\t\t\t\t\t\t\t(\n\t\t\t\t\t\t\t\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(-3.0f, 3.0f),\n\t\t\t\t\t\t\t\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(-3.0f, 3.0f),\n\t\t\t\t\t\t\t\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(-3.0f, 3.0f)\n\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t\tnil,\n\t\t\t\t\t\t\t\t\t\t\t\t0.3f,\n\t\t\t\t\t\t\t\t\t\t\t\tparticle->m_Color,\n\t\t\t\t\t\t\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(20, 40),\n\t\t\t\t\t\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t\t\t\t\t\tCGeneral::GetRandomNumber() & 3,\n\t\t\t\t\t\t\t\t\t\t\t\t200);\n\t\t\t\t\tif ( pBirdDerbis )\n\t\t\t\t\t\tpBirdDerbis->m_nAlpha = particle->m_nAlpha;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\t\n}\n\nvoid\nCEntity::AddSteamsFromGround(CVector *unused)\n{\n\tint i, n;\n\tC2dEffect *effect;\n\tCVector pos;\n\n\tn = CModelInfo::GetModelInfo(GetModelIndex())->GetNum2dEffects();\n\tfor(i = 0; i < n; i++){\n\t\teffect = CModelInfo::GetModelInfo(GetModelIndex())->Get2dEffect(i);\n\t\tif(effect->type != EFFECT_PARTICLE)\n\t\t\tcontinue;\n\n\t\tpos = GetMatrix() * effect->pos;\n\t\tswitch(effect->particle.particleType){\n\t\tcase 0:\n\t\t\tCParticleObject::AddObject(POBJECT_PAVEMENT_STEAM, pos, effect->particle.dir, effect->particle.scale, false);\n\t\t\tbreak;\n\t\tcase 1:\n\t\t\tCParticleObject::AddObject(POBJECT_WALL_STEAM, pos, effect->particle.dir, effect->particle.scale, false);\n\t\t\tbreak;\n\t\tcase 2:\n\t\t\tCParticleObject::AddObject(POBJECT_DRY_ICE, pos, effect->particle.scale, false);\n\t\t\tbreak;\n\t\tcase 3:\n\t\t\tCParticleObject::AddObject(POBJECT_SMALL_FIRE, pos, effect->particle.dir, effect->particle.scale, false);\n\t\t\tbreak;\n\t\tcase 4:\n\t\t\tCParticleObject::AddObject(POBJECT_DARK_SMOKE, pos, effect->particle.dir, effect->particle.scale, false);\n\t\t\tbreak;\n\t\tcase 5:\n\t\t\tCParticleObject::AddObject(POBJECT_WATER_FOUNTAIN_VERT, pos, effect->particle.dir, effect->particle.scale, false);\n\t\t\tbreak;\n\t\tcase 6:\n\t\t\tCParticleObject::AddObject(POBJECT_WATER_FOUNTAIN_HORIZ, pos, effect->particle.dir, effect->particle.scale, false);\n\t\t\tbreak;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/render/Particle.h",
    "content": "#pragma once\n#include \"ParticleMgr.h\"\n\n\nclass CEntity;\n\nclass CParticle\n{\npublic:\n\tenum\n\t{\n\t\tRAND_TABLE_SIZE    = 20,\n\t\tSIN_COS_TABLE_SIZE = 1024\n\t};\n\n\tCVector   m_vecPosition;\n\tCVector   m_vecVelocity;\n\tuint32    m_nTimeWhenWillBeDestroyed;\n\tuint32    m_nTimeWhenColorWillBeChanged;\n\tfloat     m_fZGround;\n\tCVector   m_vecParticleMovementOffset;\n\tint16     m_nCurrentZRotation;\n\tuint16    m_nZRotationTimer;\n\tfloat     m_fCurrentZRadius;\n\tuint16    m_nZRadiusTimer;\n\tuint8     m_nColorIntensity;\n\tuint8     m_nAlpha;\n\tfloat     m_fSize;\n\tfloat     m_fExpansionRate;\n\tint16     m_nFadeToBlackTimer;\n\tint16     m_nFadeAlphaTimer;\n\tint16     m_nAnimationSpeedTimer;\n\tint16     m_nRotationStep;\n\tint16     m_nRotation;\n\tuint8     m_nCurrentFrame;\n\tRwRGBA    m_Color;\n\tCParticle *m_pNext;\n\t\n\tCParticle()\n\t{\n\t\t;\n\t}\n\t\n\t~CParticle()\n\t{\n\t\t;\n\t}\n\n\tstatic float      ms_afRandTable[RAND_TABLE_SIZE];\n\tstatic CParticle *m_pUnusedListHead;\n\t\n\tstatic float      m_SinTable[SIN_COS_TABLE_SIZE];\n\tstatic float      m_CosTable[SIN_COS_TABLE_SIZE];\n\t\n\tstatic float Sin(int32 value) { return m_SinTable[value]; }\n\tstatic float Cos(int32 value) { return m_CosTable[value]; }\n\t\n\tstatic void ReloadConfig();\n\tstatic void Initialise();\n\tstatic void Shutdown();\n\t\n\tstatic void AddParticlesAlongLine(tParticleType type, CVector const &vecStart, CVector const &vecEnd, CVector const &vecDir, float fPower, CEntity *pEntity = nil, float fSize = 0.0f,                     int32 nRotationSpeed = 0, int32 nRotation = 0, int32 nCurFrame = 0, int32 nLifeSpan = 0);\t\n\tstatic void AddParticlesAlongLine(tParticleType type, CVector const &vecStart, CVector const &vecEnd, CVector const &vecDir, float fPower, CEntity *pEntity,       float fSize, RwRGBA const&color,        int32 nRotationSpeed = 0, int32 nRotation = 0, int32 nCurFrame = 0, int32 nLifeSpan = 0);\n\n\tstatic CParticle *AddParticle(tParticleType type, CVector const &vecPos, CVector const &vecDir, CEntity *pEntity = nil, float fSize = 0.0f,               int32 nRotationSpeed = 0, int32 nRotation = 0, int32 nCurFrame = 0, int32 nLifeSpan = 0);\n\tstatic CParticle *AddParticle(tParticleType type, CVector const &vecPos, CVector const &vecDir, CEntity *pEntity,       float fSize, RwRGBA const &color, int32 nRotationSpeed = 0, int32 nRotation = 0, int32 nCurFrame = 0, int32 nLifeSpan = 0);\n\n\tstatic void Update();\n\tstatic void Render();\n\n\tstatic void RemovePSystem(tParticleType type);\n\tstatic void RemoveParticle(CParticle *pParticle, CParticle *pPrevParticle, tParticleSystemData *pPSystemData);\n\t\n\tstatic void _Next(CParticle *&pParticle, CParticle *&pPrevParticle, tParticleSystemData *pPSystemData, bool bRemoveParticle)\n\t{\n\t\tif ( bRemoveParticle )\n\t\t{\n\t\t\tRemoveParticle(pParticle, pPrevParticle, pPSystemData);\n\t\t\t\t\t\n\t\t\tif ( pPrevParticle )\n\t\t\t\tpParticle = pPrevParticle->m_pNext;\n\t\t\telse\n\t\t\t\tpParticle = pPSystemData->m_pParticles;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tpPrevParticle = pParticle;\n\t\t\tpParticle = pParticle->m_pNext;\n\t\t}\n\t}\n\n\tstatic void AddJetExplosion(CVector const &vecPos, float fPower, float fSize);\n\tstatic void AddYardieDoorSmoke(CVector const &vecPos, CMatrix const &matMatrix);\n\tstatic void CalWindDir(CVector *vecDirIn, CVector *vecDirOut);\n\t\n\tstatic void HandleShipsAtHorizonStuff();\n\tstatic void HandleShootableBirdsStuff(CEntity *entity, CVector const&camPos);\n};\n\nextern bool clearWaterDrop;\nextern int32 numWaterDropOnScreen;\nextern RwRaster *gpCarSplashRaster[];\nextern RwRaster *gpHeatHazeRaster;\nextern RwRaster *gpDotRaster;\nextern RwRaster *gpRainDripRaster[];\nextern RwRaster *gpRainDripDarkRaster[];\n\nVALIDATE_SIZE(CParticle, 0x58);\n"
  },
  {
    "path": "src/render/ParticleMgr.cpp",
    "content": "#include \"common.h\"\n\n#include \"main.h\"\n#include \"FileMgr.h\"\n#include \"ParticleMgr.h\"\n\ncParticleSystemMgr mod_ParticleSystemManager;\n\nconst char *ParticleFilename = \"PARTICLE.CFG\";\n\ncParticleSystemMgr::cParticleSystemMgr()\n{\n\tmemset(this, 0, sizeof(*this));\n}\n\nvoid cParticleSystemMgr::Initialise()\n{\n\tLoadParticleData();\n\t\n\tfor ( int32 i = 0; i < MAX_PARTICLES; i++ )\n\t\tm_aParticles[i].m_pParticles = nil;\n}\n\nvoid cParticleSystemMgr::LoadParticleData()\n{\n\tCFileMgr::SetDir(\"DATA\");\n\tCFileMgr::LoadFile(ParticleFilename, work_buff, ARRAY_SIZE(work_buff), \"r\");\n\tCFileMgr::SetDir(\"\");\n\t\n\ttParticleSystemData *entry = nil;\n\tint32 type = PARTICLE_FIRST;\n\t\n\tchar *lineStart = (char *)work_buff;\n\tchar *lineEnd = lineStart + 1;\n\t\n\tchar line[500];\n\tchar delims[4];\n\n\twhile ( true )\n\t{\n\t\tASSERT(lineStart != nil);\n\t\tASSERT(lineEnd != nil);\n\t\t\n\t\twhile ( *lineEnd != '\\n' )\n\t\t\t++lineEnd;\n\t\t\n\t\tint32 lineLength = lineEnd - lineStart;\n\t\t\n\t\tASSERT(lineLength < 500);\n\n\t\tstrncpy(line, lineStart, lineLength);\n\t\t\n\t\tline[lineLength] = '\\0';\n\t\t\n\t\tif ( !strcmp(line, \";the end\") )\n\t\t\tbreak;\n\t\t\n\t\tif ( *line != ';' )\n\t\t{\n\t\t\tint32 param = CFG_PARAM_FIRST;\n\n\t\t\tstrcpy(delims, \" \\t\");\n\t\t\t\n\t\t\tchar *value = strtok(line, delims);\n\t\t\t\n\t\t\tASSERT(value != nil);\n\t\t\t\n\t\t\tdo\n\t\t\t{\t\n\t\t\t\tswitch ( param )\n\t\t\t\t{\n\t\t\t\t\tcase CFG_PARAM_PARTICLE_TYPE_NAME:\n\t\t\t\t\t\tASSERT(type < MAX_PARTICLES);\n\t\t\t\t\t\tentry = &m_aParticles[type];\n\t\t\t\t\t\tASSERT(entry != nil);\n\t\t\t\t\t\tentry->m_Type = (tParticleType)type++;\n\t\t\t\t\t\tstrcpy(entry->m_aName, value);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase CFG_PARAM_RENDER_COLOURING_R:\n\t\t\t\t\t\tentry->m_RenderColouring.red = atoi(value);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase CFG_PARAM_RENDER_COLOURING_G:\n\t\t\t\t\t\tentry->m_RenderColouring.green = atoi(value);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase CFG_PARAM_RENDER_COLOURING_B:\n\t\t\t\t\t\tentry->m_RenderColouring.blue = atoi(value);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase CFG_PARAM_INITIAL_COLOR_VARIATION:\n\t\t\t\t\t\tentry->m_InitialColorVariation = Min(atoi(value), 100);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase CFG_PARAM_FADE_DESTINATION_COLOR_R:\n\t\t\t\t\t\tentry->m_FadeDestinationColor.red = atoi(value);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase CFG_PARAM_FADE_DESTINATION_COLOR_G:\n\t\t\t\t\t\tentry->m_FadeDestinationColor.green = atoi(value);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase CFG_PARAM_FADE_DESTINATION_COLOR_B:\n\t\t\t\t\t\tentry->m_FadeDestinationColor.blue = atoi(value);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase CFG_PARAM_COLOR_FADE_TIME:\n\t\t\t\t\t\tentry->m_ColorFadeTime = atoi(value);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase CFG_PARAM_DEFAULT_INITIAL_RADIUS:\n\t\t\t\t\t\tentry->m_fDefaultInitialRadius = atof(value);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase CFG_PARAM_EXPANSION_RATE:\n\t\t\t\t\t\tentry->m_fExpansionRate = atof(value);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase CFG_PARAM_INITIAL_INTENSITY:\n\t\t\t\t\t\tentry->m_nFadeToBlackInitialIntensity = atoi(value);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase CFG_PARAM_FADE_TIME:\n\t\t\t\t\t\tentry->m_nFadeToBlackTime = atoi(value);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase CFG_PARAM_FADE_AMOUNT:\n\t\t\t\t\t\tentry->m_nFadeToBlackAmount = atoi(value);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase CFG_PARAM_INITIAL_ALPHA_INTENSITY:\n\t\t\t\t\t\tentry->m_nFadeAlphaInitialIntensity = atoi(value);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase CFG_PARAM_FADE_ALPHA_TIME:\n\t\t\t\t\t\tentry->m_nFadeAlphaTime = atoi(value);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase CFG_PARAM_FADE_ALPHA_AMOUNT:\n\t\t\t\t\t\tentry->m_nFadeAlphaAmount = atoi(value);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase CFG_PARAM_INITIAL_ANGLE:\n\t\t\t\t\t\tentry->m_nZRotationInitialAngle = atoi(value);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase CFG_PARAM_CHANGE_TIME:\n\t\t\t\t\t\tentry->m_nZRotationChangeTime = atoi(value);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase CFG_PARAM_ANGLE_CHANGE_AMOUNT:\n\t\t\t\t\t\tentry->m_nZRotationAngleChangeAmount = atoi(value);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase CFG_PARAM_INITIAL_Z_RADIUS:\n\t\t\t\t\t\tentry->m_fInitialZRadius = atof(value);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase CFG_PARAM_Z_RADIUS_CHANGE_TIME:\n\t\t\t\t\t\tentry->m_nZRadiusChangeTime = atoi(value);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase CFG_PARAM_Z_RADIUS_CHANGE_AMOUNT:\n\t\t\t\t\t\tentry->m_fZRadiusChangeAmount = atof(value);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase CFG_PARAM_ANIMATION_SPEED:\n\t\t\t\t\t\tentry->m_nAnimationSpeed = atoi(value);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase CFG_PARAM_START_ANIMATION_FRAME:\n\t\t\t\t\t\tentry->m_nStartAnimationFrame = atoi(value);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase CFG_PARAM_FINAL_ANIMATION_FRAME:\n\t\t\t\t\t\tentry->m_nFinalAnimationFrame = atoi(value);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase CFG_PARAM_ROTATION_SPEED:\n\t\t\t\t\t\tentry->m_nRotationSpeed = atoi(value);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase CFG_PARAM_GRAVITATIONAL_ACCELERATION:\n\t\t\t\t\t\tentry->m_fGravitationalAcceleration = atof(value);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase CFG_PARAM_FRICTION_DECCELERATION:\n\t\t\t\t\t\tentry->m_nFrictionDecceleration = atoi(value);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase CFG_PARAM_LIFE_SPAN:\n\t\t\t\t\t\tentry->m_nLifeSpan = atoi(value);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase CFG_PARAM_POSITION_RANDOM_ERROR:\n\t\t\t\t\t\tentry->m_fPositionRandomError = atof(value);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase CFG_PARAM_VELOCITY_RANDOM_ERROR:\n\t\t\t\t\t\tentry->m_fVelocityRandomError = atof(value);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase CFG_PARAM_EXPANSION_RATE_ERROR:\n\t\t\t\t\t\tentry->m_fExpansionRateError = atof(value);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase CFG_PARAM_ROTATION_RATE_ERROR:\n\t\t\t\t\t\tentry->m_nRotationRateError = atoi(value);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase CFG_PARAM_LIFE_SPAN_ERROR_SHAPE:\n\t\t\t\t\t\tentry->m_nLifeSpanErrorShape = atoi(value);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase CFG_PARAM_TRAIL_LENGTH_MULTIPLIER:\n\t\t\t\t\t\tentry->m_fTrailLengthMultiplier = atof(value);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\n\t\t\t\t\tcase CFG_PARAM_STRETCH_VALUE_X:\n\t\t\t\t\t\tentry->m_vecTextureStretch.x = atof(value);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase CFG_PARAM_STRETCH_VALUE_Y:\n\t\t\t\t\t\tentry->m_vecTextureStretch.y = atof(value);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase CFG_PARAM_WIND_FACTOR:\n\t\t\t\t\t\tentry->m_fWindFactor = atof(value);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase CFG_PARAM_PARTICLE_CREATE_RANGE:\n\t\t\t\t\t\tentry->m_fCreateRange = SQR(atof(value));\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase CFG_PARAM_FLAGS:\n\t\t\t\t\t\tentry->Flags = atoi(value);\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tvalue = strtok(nil, delims);\n\n\t\t\t\tparam++;\n\n\t\t\t\tif ( param > CFG_PARAM_LAST )\n\t\t\t\t\tparam = CFG_PARAM_FIRST;\n\t\t\n\t\t\t} while ( value != nil );\n\t\t}\n\t\t\n\t\tlineEnd++;\n\t\tlineStart = lineEnd;\n\t\tlineEnd++;\n\t}\n}\n"
  },
  {
    "path": "src/render/ParticleMgr.h",
    "content": "#pragma once\n\n#include \"ParticleType.h\"\n\nclass CParticle;\n\nenum\n{\n\tZCHECK_FIRST      = BIT(0),\n\tZCHECK_STEP       = BIT(1),\n\tDRAW_OPAQUE       = BIT(2),\n\tSCREEN_TRAIL      = BIT(3),\n\tSPEED_TRAIL       = BIT(4),\n\tRAND_VERT_V       = BIT(5),\n\tCYCLE_ANIM        = BIT(6),\n\tDRAW_DARK         = BIT(7),\n\tVERT_TRAIL        = BIT(8),\n\t_FLAG9            = BIT(9),\t\t// unused\n\tDRAWTOP2D         = BIT(10),\n\tCLIPOUT2D         = BIT(11),\n\tZCHECK_BUMP       = BIT(12),\n\tZCHECK_BUMP_FIRST = BIT(13)\n};\n\n\nstruct tParticleSystemData\n{\n\ttParticleType m_Type;\n\tchar          m_aName[20];\n\tfloat         m_fCreateRange;\n\tfloat         m_fDefaultInitialRadius;\n\tfloat         m_fExpansionRate;\n\tuint16        m_nZRotationInitialAngle;\n\tint16         m_nZRotationAngleChangeAmount;\n\tuint16        m_nZRotationChangeTime;\n\tuint16        m_nZRadiusChangeTime;\n\tfloat         m_fInitialZRadius;\n\tfloat         m_fZRadiusChangeAmount;\n\tint16         m_nFadeToBlackTime;\n\tuint8         m_nFadeToBlackInitialIntensity;\n\tint16         m_nFadeToBlackAmount;\n\tuint8         m_nFadeAlphaInitialIntensity;\n\tint16         m_nFadeAlphaTime;\n\tint16         m_nFadeAlphaAmount;\n\tuint8         m_nStartAnimationFrame;\n\tuint8         m_nFinalAnimationFrame;\n\tuint16        m_nAnimationSpeed;\n\tuint16        m_nRotationSpeed;\n\tfloat         m_fGravitationalAcceleration;\n\tint32         m_nFrictionDecceleration;\n\tint32         m_nLifeSpan;\n\tfloat         m_fPositionRandomError;\n\tfloat         m_fVelocityRandomError;\n\tfloat         m_fExpansionRateError;\n\tint32         m_nRotationRateError;\n\tuint32        m_nLifeSpanErrorShape;\n\tfloat         m_fTrailLengthMultiplier;\n\tuint32        Flags;\n\tCRGBA         m_RenderColouring;\n\tuint8         m_InitialColorVariation;\n\tCRGBA         m_FadeDestinationColor;\n\tuint32        m_ColorFadeTime;\n\t\n\tCVector2D     m_vecTextureStretch;\n\tfloat         m_fWindFactor;\n\n\tRwRaster      **m_ppRaster;\n\tCParticle     *m_pParticles;\n};\n\nVALIDATE_SIZE(tParticleSystemData, 0x94);\n\nclass cParticleSystemMgr\n{\n\tenum\n\t{\n\t\tCFG_PARAM_PARTICLE_TYPE_NAME = 0,\n\t\tCFG_PARAM_RENDER_COLOURING_R,\n\t\tCFG_PARAM_RENDER_COLOURING_G,\n\t\tCFG_PARAM_RENDER_COLOURING_B,\n\t\tCFG_PARAM_INITIAL_COLOR_VARIATION,\n\t\tCFG_PARAM_FADE_DESTINATION_COLOR_R,\n\t\tCFG_PARAM_FADE_DESTINATION_COLOR_G,\n\t\tCFG_PARAM_FADE_DESTINATION_COLOR_B,\n\t\tCFG_PARAM_COLOR_FADE_TIME,\n\t\tCFG_PARAM_DEFAULT_INITIAL_RADIUS,\n\t\tCFG_PARAM_EXPANSION_RATE,\n\t\tCFG_PARAM_INITIAL_INTENSITY,\n\t\tCFG_PARAM_FADE_TIME,\n\t\tCFG_PARAM_FADE_AMOUNT,\n\t\tCFG_PARAM_INITIAL_ALPHA_INTENSITY,\n\t\tCFG_PARAM_FADE_ALPHA_TIME,\n\t\tCFG_PARAM_FADE_ALPHA_AMOUNT,\n\t\tCFG_PARAM_INITIAL_ANGLE,\n\t\tCFG_PARAM_CHANGE_TIME,\n\t\tCFG_PARAM_ANGLE_CHANGE_AMOUNT,\n\t\tCFG_PARAM_INITIAL_Z_RADIUS,\n\t\tCFG_PARAM_Z_RADIUS_CHANGE_TIME,\n\t\tCFG_PARAM_Z_RADIUS_CHANGE_AMOUNT,\n\t\tCFG_PARAM_ANIMATION_SPEED,\n\t\tCFG_PARAM_START_ANIMATION_FRAME,\n\t\tCFG_PARAM_FINAL_ANIMATION_FRAME,\n\t\tCFG_PARAM_ROTATION_SPEED,\n\t\tCFG_PARAM_GRAVITATIONAL_ACCELERATION,\n\t\tCFG_PARAM_FRICTION_DECCELERATION,\n\t\tCFG_PARAM_LIFE_SPAN,\n\t\tCFG_PARAM_POSITION_RANDOM_ERROR,\n\t\tCFG_PARAM_VELOCITY_RANDOM_ERROR,\n\t\tCFG_PARAM_EXPANSION_RATE_ERROR,\n\t\tCFG_PARAM_ROTATION_RATE_ERROR,\n\t\tCFG_PARAM_LIFE_SPAN_ERROR_SHAPE,\n\t\tCFG_PARAM_TRAIL_LENGTH_MULTIPLIER,\n\t\t\n\t\tCFG_PARAM_STRETCH_VALUE_X,\n\t\tCFG_PARAM_STRETCH_VALUE_Y,\n\t\tCFG_PARAM_WIND_FACTOR,\n\t\t\n\t\tCFG_PARAM_PARTICLE_CREATE_RANGE,\n\t\tCFG_PARAM_FLAGS,\n\n\t\tMAX_CFG_PARAMS,\n\t\tCFG_PARAM_FIRST = CFG_PARAM_PARTICLE_TYPE_NAME,\n\t\tCFG_PARAM_LAST = CFG_PARAM_FLAGS\n\t};\n\npublic:\n\ttParticleSystemData m_aParticles[MAX_PARTICLES];\n\n\tcParticleSystemMgr();\n\n\tvoid Initialise();\n\tvoid LoadParticleData();\n\tvoid RangeCheck(tParticleSystemData *pData) { }\n};\n\nVALIDATE_SIZE(cParticleSystemMgr, 0x2FFC);\n\nextern cParticleSystemMgr mod_ParticleSystemManager;\n"
  },
  {
    "path": "src/render/ParticleType.h",
    "content": "#pragma once\n\nenum tParticleType\n{\n\tPARTICLE_SPARK = 0,\n\tPARTICLE_SPARK_SMALL,\n\tPARTICLE_WATER_SPARK,\n\tPARTICLE_WHEEL_DIRT,\n\tPARTICLE_SAND,\n\tPARTICLE_WHEEL_WATER,\n\tPARTICLE_BLOOD,\n\tPARTICLE_BLOOD_SMALL,\n\tPARTICLE_BLOOD_SPURT,\n\tPARTICLE_DEBRIS,\n\tPARTICLE_DEBRIS2,\n\tPARTICLE_FLYERS,\n\tPARTICLE_WATER,\n\tPARTICLE_FLAME,\n\tPARTICLE_FIREBALL,\n\tPARTICLE_GUNFLASH,\n\tPARTICLE_GUNFLASH_NOANIM,\n\tPARTICLE_GUNSMOKE,\n\tPARTICLE_GUNSMOKE2,\n\tPARTICLE_CIGARETTE_SMOKE,\n\tPARTICLE_SMOKE,\n\tPARTICLE_SMOKE_SLOWMOTION,\n\tPARTICLE_DRY_ICE,\n\tPARTICLE_TEARGAS,\n\tPARTICLE_GARAGEPAINT_SPRAY,\n\tPARTICLE_SHARD,\n\tPARTICLE_SPLASH,\n\tPARTICLE_CARFLAME,\n\tPARTICLE_STEAM,\n\tPARTICLE_STEAM2,\n\tPARTICLE_STEAM_NY,\n\tPARTICLE_STEAM_NY_SLOWMOTION,\n\tPARTICLE_GROUND_STEAM,\n\tPARTICLE_ENGINE_STEAM,\n\tPARTICLE_RAINDROP,\n\tPARTICLE_RAINDROP_SMALL,\n\tPARTICLE_RAIN_SPLASH,\n\tPARTICLE_RAIN_SPLASH_BIGGROW,\n\tPARTICLE_RAIN_SPLASHUP,\n\tPARTICLE_WATERSPRAY,\n\tPARTICLE_WATERDROP,\n\tPARTICLE_BLOODDROP,\n\tPARTICLE_EXPLOSION_MEDIUM,\n\tPARTICLE_EXPLOSION_LARGE,\n\tPARTICLE_EXPLOSION_MFAST,\n\tPARTICLE_EXPLOSION_LFAST,\n\tPARTICLE_CAR_SPLASH,\n\tPARTICLE_BOAT_SPLASH,\n\tPARTICLE_BOAT_THRUSTJET,\n\tPARTICLE_WATER_HYDRANT,\n\tPARTICLE_WATER_CANNON,\n\tPARTICLE_EXTINGUISH_STEAM,\n\tPARTICLE_PED_SPLASH,\n\tPARTICLE_PEDFOOT_DUST,\n\tPARTICLE_CAR_DUST,\n\tPARTICLE_HELI_DUST,\n\tPARTICLE_HELI_ATTACK,\n\tPARTICLE_ENGINE_SMOKE,\n\tPARTICLE_ENGINE_SMOKE2,\n\tPARTICLE_CARFLAME_SMOKE,\n\tPARTICLE_FIREBALL_SMOKE,\n\tPARTICLE_PAINT_SMOKE,\n\tPARTICLE_TREE_LEAVES,\n\tPARTICLE_CARCOLLISION_DUST,\n\tPARTICLE_CAR_DEBRIS,\n\tPARTICLE_BIRD_DEBRIS,\n\tPARTICLE_HELI_DEBRIS,\n\tPARTICLE_EXHAUST_FUMES,\n\tPARTICLE_RUBBER_SMOKE,\n\tPARTICLE_BURNINGRUBBER_SMOKE,\n\tPARTICLE_BULLETHIT_SMOKE,\n\tPARTICLE_GUNSHELL_FIRST,\n\tPARTICLE_GUNSHELL,\n\tPARTICLE_GUNSHELL_BUMP1,\n\tPARTICLE_GUNSHELL_BUMP2,\n\tPARTICLE_ROCKET_SMOKE,\n\tPARTICLE_TEST,\n\tPARTICLE_BIRD_FRONT,\n\tPARTICLE_SHIP_SIDE,\n\tPARTICLE_BEASTIE,\n\tPARTICLE_RAINDROP_2D,\n\tPARTICLE_HEATHAZE,\n\tPARTICLE_HEATHAZE_IN_DIST,\n\t\n\tMAX_PARTICLES,\n\tPARTICLE_FIRST = PARTICLE_SPARK,\n\tPARTICLE_LAST = PARTICLE_HEATHAZE_IN_DIST\n};"
  },
  {
    "path": "src/render/PlayerSkin.cpp",
    "content": "#include \"common.h\"\n\n#include \"main.h\"\n#include \"PlayerSkin.h\"\n#include \"TxdStore.h\"\n#include \"rtbmp.h\"\n#include \"ClumpModelInfo.h\"\n#include \"VisibilityPlugins.h\"\n#include \"World.h\"\n#include \"PlayerInfo.h\"\n#include \"CdStream.h\"\n#include \"FileMgr.h\"\n#include \"Directory.h\"\n#include \"RwHelper.h\"\n#include \"Timer.h\"\n#include \"Lights.h\"\n#include \"MemoryMgr.h\"\n\nRpClump *gpPlayerClump;\nfloat gOldFov;\n\nint CPlayerSkin::m_txdSlot;\n\nvoid\nFindPlayerDff(uint32 &offset, uint32 &size)\n{\n\tint file;\n\tCDirectory::DirectoryInfo info;\n\n\tfile = CFileMgr::OpenFile(\"models\\\\gta3.dir\", \"rb\");\n\n\tdo {\n\t\tif (!CFileMgr::Read(file, (char*)&info, sizeof(CDirectory::DirectoryInfo)))\n\t\t\treturn;\n\t} while (strcasecmp(\"player.dff\", info.name) != 0);\n\n\toffset = info.offset;\n\tsize = info.size;\n}\n\nvoid\nLoadPlayerDff(void)\n{\n\tRwStream *stream;\n\tRwMemory mem;\n\tuint32 offset, size;\n\tuint8 *buffer;\n\tbool streamWasAdded = false;\n\n\tif (CdStreamGetNumImages() == 0) {\n\t\tCdStreamAddImage(\"models\\\\gta3.img\");\n\t\tstreamWasAdded = true;\n\t}\n\n\tFindPlayerDff(offset, size);\n\tbuffer = (uint8*)RwMallocAlign(size << 11, 2048);\n\tCdStreamRead(0, buffer, offset, size);\n\tCdStreamSync(0);\n\n\tmem.start = buffer;\n\tmem.length = size << 11;\n\tstream = RwStreamOpen(rwSTREAMMEMORY, rwSTREAMREAD, &mem);\n\n\tif (RwStreamFindChunk(stream, rwID_CLUMP, nil, nil))\n\t\tgpPlayerClump = RpClumpStreamRead(stream);\n\n\tRwStreamClose(stream, &mem);\n\tRwFreeAlign(buffer);\n\n\tif (streamWasAdded)\n\t\tCdStreamRemoveImages();\n}\n\nvoid\nCPlayerSkin::Initialise(void)\n{\n\t// empty on PS2\n\tm_txdSlot = CTxdStore::AddTxdSlot(\"skin\");\n\tCTxdStore::Create(m_txdSlot);\n\tCTxdStore::AddRef(m_txdSlot);\n}\n\nvoid\nCPlayerSkin::Shutdown(void)\n{\n\t// empty on PS2\n\tCTxdStore::RemoveTxdSlot(m_txdSlot);\n}\n\nRwTexture *\nCPlayerSkin::GetSkinTexture(const char *texName)\n{\n\tRwTexture *tex;\n\tRwRaster *raster;\n\tint32 width, height, depth, format;\n\n\tCTxdStore::PushCurrentTxd();\n\tCTxdStore::SetCurrentTxd(m_txdSlot);\n\ttex = RwTextureRead(texName, NULL);\n\tCTxdStore::PopCurrentTxd();\n\tif (tex != nil) return tex;\n\n\tif (strcmp(DEFAULT_SKIN_NAME, texName) == 0 || texName[0] == '\\0')\n\t\tsprintf(gString, \"models\\\\generic\\\\player.bmp\");\n\telse\n\t\tsprintf(gString, \"skins\\\\%s.bmp\", texName);\n\n\tif (RwImage *image = RtBMPImageRead(gString)) {\n\t\tRwImageFindRasterFormat(image, rwRASTERTYPETEXTURE, &width, &height, &depth, &format);\n\t\traster = RwRasterCreate(width, height, depth, format);\n\t\tRwRasterSetFromImage(raster, image);\n\n\t\ttex = RwTextureCreate(raster);\n\t\tRwTextureSetName(tex, texName);\n\t\tRwTextureSetFilterMode(tex, rwFILTERLINEAR);\n\t\tRwTexDictionaryAddTexture(CTxdStore::GetSlot(m_txdSlot)->texDict, tex);\n\n\t\tRwImageDestroy(image);\n\t}\n\treturn tex;\n}\n\nvoid\nCPlayerSkin::BeginFrontendSkinEdit(void)\n{\n\tLoadPlayerDff();\n\tRpClumpForAllAtomics(gpPlayerClump, CClumpModelInfo::SetAtomicRendererCB, (void*)CVisibilityPlugins::RenderPlayerCB);\n\tCWorld::Players[0].LoadPlayerSkin();\n\tgOldFov = CDraw::GetFOV();\n\tCDraw::SetFOV(30.0f);\n}\n\nvoid\nCPlayerSkin::EndFrontendSkinEdit(void)\n{\n\tRpClumpDestroy(gpPlayerClump);\n\tgpPlayerClump = NULL;\n\tCDraw::SetFOV(gOldFov);\n}\n\nvoid\nCPlayerSkin::RenderFrontendSkinEdit(void)\n{\n\tstatic float rotation = 0.0f;\n\tRwRGBAReal AmbientColor = { 0.65f, 0.65f, 0.65f, 1.0f };\n\tconst RwV3d pos = { 1.35f, 0.35f, 7.725f };\n\tconst RwV3d axis = { 0.0f, 1.0f, 0.0f };\n\tstatic uint32 LastFlash = 0;\n\n\tRwFrame *frame = RpClumpGetFrame(gpPlayerClump);\n\n\tif (CTimer::GetTimeInMillisecondsPauseMode() - LastFlash > 7) {\n\t\trotation += 2.0f;\n\t\tif (rotation > 360.0f)\n\t\t\trotation -= 360.0f;\n\t\tLastFlash = CTimer::GetTimeInMillisecondsPauseMode();\n\t}\n\tRwFrameTransform(frame, RwFrameGetMatrix(RwCameraGetFrame(Scene.camera)), rwCOMBINEREPLACE);\n\tRwFrameTranslate(frame, &pos, rwCOMBINEPRECONCAT);\n\tRwFrameRotate(frame, &axis, rotation, rwCOMBINEPRECONCAT);\n\tRwFrameUpdateObjects(frame);\n\tSetAmbientColours(&AmbientColor);\n\tRpClumpRender(gpPlayerClump);\n}\n"
  },
  {
    "path": "src/render/PlayerSkin.h",
    "content": "#pragma once\n\n#define DEFAULT_SKIN_NAME \"$$\\\"\\\"\"\n\nclass CPlayerSkin\n{\n\tstatic int m_txdSlot;\npublic:\n\tstatic void Initialise();\n\tstatic void Shutdown();\n\tstatic RwTexture *GetSkinTexture(const char *texName);\n\tstatic void BeginFrontendSkinEdit();\n\tstatic void EndFrontendSkinEdit();\n\tstatic void RenderFrontendSkinEdit();\n};"
  },
  {
    "path": "src/render/PointLights.cpp",
    "content": "#include \"common.h\"\n\n#include \"main.h\"\n#include \"CutsceneMgr.h\"\n#include \"Lights.h\"\n#include \"Camera.h\"\n#include \"Weather.h\"\n#include \"World.h\"\n#include \"Collision.h\"\n#include \"Sprite.h\"\n#include \"Timer.h\"\n#include \"PointLights.h\"\n\nint16 CPointLights::NumLights;\nCRegisteredPointLight CPointLights::aLights[NUMPOINTLIGHTS];\nCVector CPointLights::aCachedMapReads[32];\nfloat CPointLights::aCachedMapReadResults[32];\nint32 CPointLights::NextCachedValue;\n\nvoid\nCPointLights::Init(void)\n{\n\tfor(int i = 0; i < ARRAY_SIZE(aCachedMapReads); i++){\n\t\taCachedMapReads[i] = CVector(0.0f, 0.0f, 0.0f);\n\t\taCachedMapReadResults[i] = 0.0f;\n\t}\n\tNextCachedValue = 0;\n}\n\nvoid\nCPointLights::InitPerFrame(void)\n{\n\tNumLights = 0;\n}\n\n#define MAX_DIST 22.0f\n\nvoid\nCPointLights::AddLight(uint8 type, CVector coors, CVector dir, float radius, float red, float green, float blue, uint8 fogType, bool castExtraShadows)\n{\n\tCVector dist;\n\tfloat distance;\n\n\t// The check is done in some weird way in the game\n\t// we're doing it a bit better here\n\tif(NumLights >= NUMPOINTLIGHTS)\n\t\treturn;\n\n\tdist = coors - TheCamera.GetPosition();\n\tif(Abs(dist.x) < MAX_DIST && Abs(dist.y) < MAX_DIST){\n\t\tdistance = dist.Magnitude();\n\t\tif(distance < MAX_DIST){\n\t\t\taLights[NumLights].type = type;\n\t\t\taLights[NumLights].fogType = fogType;\n\t\t\taLights[NumLights].coors = coors;\n\t\t\taLights[NumLights].dir = dir;\n\t\t\taLights[NumLights].radius = radius;\n\t\t\taLights[NumLights].castExtraShadows = castExtraShadows;\n\t\t\tif(distance < MAX_DIST*0.75f){\n\t\t\t\taLights[NumLights].red = red;\n\t\t\t\taLights[NumLights].green = green;\n\t\t\t\taLights[NumLights].blue = blue;\n\t\t\t}else{\n\t\t\t\tfloat fade = 1.0f - (distance/MAX_DIST - 0.75f)*4.0f;\n\t\t\t\taLights[NumLights].red = red * fade;\n\t\t\t\taLights[NumLights].green = green * fade;\n\t\t\t\taLights[NumLights].blue = blue * fade;\n\t\t\t}\n\t\t\tNumLights++;\n\t\t}\n\t}\n}\n\nfloat\nCPointLights::GenerateLightsAffectingObject(Const CVector *objCoors)\n{\n\tint i;\n\tfloat ret;\n\tCVector dist;\n\tfloat radius, distance;\n\n\tret = 1.0f;\n\tfor(i = 0; i < NumLights; i++){\n\t\tif(aLights[i].type == LIGHT_FOGONLY || aLights[i].type == LIGHT_FOGONLY_ALWAYS)\n\t\t\tcontinue;\n\n\t\t// same weird distance calculation. simplified here\n\t\tdist = aLights[i].coors - *objCoors;\n\t\tradius = aLights[i].radius;\n\t\tif(Abs(dist.x) < radius &&\n\t\t   Abs(dist.y) < radius &&\n\t\t   Abs(dist.z) < radius){\n\n\t\t\tdistance = dist.Magnitude();\n\t\t\tif(distance < radius){\n\n\t\t\t\tfloat distNorm = distance/radius;\n\t\t\t\tif(aLights[i].type == LIGHT_DARKEN){\n\t\t\t\t\t// darken the object the closer it is\n\t\t\t\t\tret *= distNorm;\n\t\t\t\t}else{\n\t\t\t\t\tfloat intensity;\n\t\t\t\t\t// distance fade\n\t\t\t\t\tif(distNorm < 0.5f)\n\t\t\t\t\t\tintensity = 1.0f;\n\t\t\t\t\telse\n\t\t\t\t\t\tintensity = 1.0f - (distNorm - 0.5f)/(1.0f - 0.5f);\n\n\t\t\t\t\tif(distance != 0.0f){\n\t\t\t\t\t\tCVector dir = dist / distance;\n\n\t\t\t\t\t\tif(aLights[i].type == LIGHT_DIRECTIONAL){\n\t\t\t\t\t\t\tfloat dot = -DotProduct(dir, aLights[i].dir);\n\t\t\t\t\t\t\tintensity *= Max((dot-0.5f)*2.0f, 0.0f);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif(intensity > 0.0f)\n\t\t\t\t\t\t\tAddAnExtraDirectionalLight(Scene.world,\n\t\t\t\t\t\t\t\tdir.x, dir.y, dir.z,\n\t\t\t\t\t\t\t\taLights[i].red*intensity, aLights[i].green*intensity, aLights[i].blue*intensity);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn ret;\n}\n\nextern RwRaster *gpPointlightRaster;\n\nvoid\nCPointLights::RemoveLightsAffectingObject(void)\n{\n\tRemoveExtraDirectionalLights(Scene.world);\n}\n\n// for directional fog\n#define FOG_AREA_LENGTH 12.0f\n#define FOG_AREA_WIDTH 5.0f\n// for pointlight fog\n#define FOG_AREA_RADIUS 9.0f\n\nfloat FogSizes[8] = { 1.3f, 2.0f, 1.7f, 2.0f, 1.4f, 2.1f, 1.5f, 2.3f };\n\nvoid\nCPointLights::RenderFogEffect(void)\n{\n\tint i;\n\tfloat fogginess;\n\tCColPoint point;\n\tCEntity *entity;\n\tfloat xmin, ymin;\n\tfloat xmax, ymax;\n\tint16 xi, yi;\n\tCVector spriteCoors;\n\tfloat spritew, spriteh;\n\n\tif(CCutsceneMgr::IsRunning())\n\t\treturn;\n\n\tPUSH_RENDERGROUP(\"CPointLights::RenderFogEffect\");\n\n\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);\n\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);\n\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE);\n\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE);\n\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, gpPointlightRaster);\n\n\tCSprite::InitSpriteBuffer();\n\n\tfor(i = 0; i < NumLights; i++){\n\t\tif(aLights[i].fogType != FOG_NORMAL && aLights[i].fogType != FOG_ALWAYS)\n\t\t\tcontinue;\n\n\t\tfogginess = aLights[i].fogType == FOG_NORMAL ? CWeather::Foggyness : 1.0f;\n\t\tif(fogginess == 0.0f)\n\t\t\tcontinue;\n\n\t\tif(aLights[i].type == LIGHT_DIRECTIONAL){\n\n\t\t\t// TODO: test this. haven't found directional fog so far\n\n\t\t\tfloat coors2X = aLights[i].coors.x + FOG_AREA_LENGTH*aLights[i].dir.x;\n\t\t\tfloat coors2Y = aLights[i].coors.y + FOG_AREA_LENGTH*aLights[i].dir.y;\n\n\t\t\tif(coors2X < aLights[i].coors.x){\n\t\t\t\txmin = coors2X;\n\t\t\t\txmax = aLights[i].coors.x;\n\t\t\t}else{\n\t\t\t\txmax = coors2X;\n\t\t\t\txmin = aLights[i].coors.x;\n\t\t\t}\n\t\t\tif(coors2Y < aLights[i].coors.y){\n\t\t\t\tymin = coors2Y;\n\t\t\t\tymax = aLights[i].coors.y;\n\t\t\t}else{\n\t\t\t\tymax = coors2Y;\n\t\t\t\tymin = aLights[i].coors.y;\n\t\t\t}\n\n\t\t\txmin -= 5.0f;\n\t\t\tymin -= 5.0f;\n\t\t\txmax += 5.0f;\n\t\t\tymax += 5.0f;\n\n\t\t\tfor(xi = (int16)xmin - (int16)xmin % 4; xi <= (int16)xmax + 4; xi += 4){\n\t\t\t\tfor(yi = (int16)ymin - (int16)ymin % 4; yi <= (int16)ymax + 4; yi += 4){\n\t\t\t\t\t// Some kind of pseudo random number?\n\t\t\t\t\tint r = (xi ^ yi)>>2 & 0xF;\n\t\t\t\t\tif((r & 1) == 0)\n\t\t\t\t\t\tcontinue;\n\n\t\t\t\t\t// Check if fog effect is close enough to directional line in x and y\n\t\t\t\t\tfloat dx = xi - aLights[i].coors.x;\n\t\t\t\t\tfloat dy = yi - aLights[i].coors.y;\n\t\t\t\t\tfloat dot = dx*aLights[i].dir.x + dy*aLights[i].dir.y;\n\t\t\t\t\tfloat distsq = sq(dx) + sq(dy);\n\t\t\t\t\tfloat linedistsq = distsq - sq(dot);\n\t\t\t\t\tif(dot > 0.0f && dot < FOG_AREA_LENGTH && linedistsq < sq(FOG_AREA_WIDTH)){\n\t\t\t\t\t\tCVector fogcoors(xi, yi, aLights[i].coors.z + 10.0f);\n\t\t\t\t\t\tif(CWorld::ProcessVerticalLine(fogcoors, fogcoors.z - 20.0f,\n\t\t\t\t\t\t\t\tpoint, entity, true, false, false, false, true, false, nil)){\n\t\t\t\t\t\t\t// Now same check again in xyz\n\t\t\t\t\t\t\tfogcoors.z = point.point.z + 1.3f;\n\t\t\t\t\t\t\t// actually we don't have to recalculate x and y, but the game does it that way\n\t\t\t\t\t\t\tdx = xi - aLights[i].coors.x;\n\t\t\t\t\t\t\tdy = yi - aLights[i].coors.y;\n\t\t\t\t\t\t\tfloat dz = fogcoors.z - aLights[i].coors.z;\n\t\t\t\t\t\t\tdot = dx*aLights[i].dir.x + dy*aLights[i].dir.y + dz*aLights[i].dir.z;\n\t\t\t\t\t\t\tdistsq = sq(dx) + sq(dy) + sq(dz);\n\t\t\t\t\t\t\tlinedistsq = distsq - sq(dot);\n\t\t\t\t\t\t\tif(dot > 0.0f && dot < FOG_AREA_LENGTH && linedistsq < sq(FOG_AREA_WIDTH)){\n\t\t\t\t\t\t\t\tfloat intensity = 158.0f * fogginess;\n\t\t\t\t\t\t\t\t// more intensity the smaller the angle\n\t\t\t\t\t\t\t\tintensity *= dot/Sqrt(distsq);\n\t\t\t\t\t\t\t\t// more intensity the closer to light source\n\t\t\t\t\t\t\t\tintensity *= 1.0f - sq(dot/FOG_AREA_LENGTH);\n\t\t\t\t\t\t\t\t// more intensity the closer to line\n\t\t\t\t\t\t\t\tintensity *= 1.0f - sq(Sqrt(linedistsq) / FOG_AREA_WIDTH);\n\n\t\t\t\t\t\t\t\tif(CSprite::CalcScreenCoors(fogcoors, &spriteCoors, &spritew, &spriteh, true)) {\n\t\t\t\t\t\t\t\t\tfloat rotation = (CTimer::GetTimeInMilliseconds()&0x1FFF) * 2*3.14f / 0x2000;\n\t\t\t\t\t\t\t\t\tfloat size = FogSizes[r>>1];\n\t\t\t\t\t\t\t\t\tCSprite::RenderBufferedOneXLUSprite_Rotate_Aspect(spriteCoors.x, spriteCoors.y, spriteCoors.z,\n\t\t\t\t\t\t\t\t\t\tspritew * size, spriteh * size,\n\t\t\t\t\t\t\t\t\t\taLights[i].red * intensity, aLights[i].green * intensity, aLights[i].blue * intensity,\n\t\t\t\t\t\t\t\t\t\tintensity, 1/spriteCoors.z, rotation, 255);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t}else if(aLights[i].type == LIGHT_POINT || aLights[i].type == LIGHT_FOGONLY || aLights[i].type == LIGHT_FOGONLY_ALWAYS){\n\t\t\tfloat groundZ;\n\t\t\tif(ProcessVerticalLineUsingCache(aLights[i].coors, &groundZ)){\n\t\t\t\txmin = aLights[i].coors.x - FOG_AREA_RADIUS;\n\t\t\t\tymin = aLights[i].coors.y - FOG_AREA_RADIUS;\n\t\t\t\txmax = aLights[i].coors.x + FOG_AREA_RADIUS;\n\t\t\t\tymax = aLights[i].coors.y + FOG_AREA_RADIUS;\n\n\t\t\t\tfor(xi = (int16)xmin - (int16)xmin % 2; xi <= (int16)xmax + 2; xi += 2){\n\t\t\t\t\tfor(yi = (int16)ymin - (int16)ymin % 2; yi <= (int16)ymax + 2; yi += 2){\n\t\t\t\t\t\t// Some kind of pseudo random number?\n\t\t\t\t\t\tint r = (xi ^ yi)>>1 & 0xF;\n\t\t\t\t\t\tif((r & 1) == 0)\n\t\t\t\t\t\t\tcontinue;\n\n\t\t\t\t\t\tfloat dx = xi - aLights[i].coors.x;\n\t\t\t\t\t\tfloat dy = yi - aLights[i].coors.y;\n\t\t\t\t\t\tfloat lightdist = Sqrt(sq(dx) + sq(dy));\n\t\t\t\t\t\tif(lightdist < FOG_AREA_RADIUS){\n\t\t\t\t\t\t\tdx = xi - TheCamera.GetPosition().x;\n\t\t\t\t\t\t\tdy = yi - TheCamera.GetPosition().y;\n\t\t\t\t\t\t\tfloat camdist = Sqrt(sq(dx) + sq(dy));\n\t\t\t\t\t\t\tif(camdist < MAX_DIST){\n\t\t\t\t\t\t\t\tfloat intensity;\n\t\t\t\t\t\t\t\t// distance fade\n\t\t\t\t\t\t\t\tif(camdist < MAX_DIST/2)\n\t\t\t\t\t\t\t\t\tintensity = 1.0f;\n\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\tintensity = 1.0f - (camdist - MAX_DIST/2) / (MAX_DIST/2);\n\t\t\t\t\t\t\t\tintensity *= 132.0f * fogginess;\n\t\t\t\t\t\t\t\t// more intensity the closer to light source\n\t\t\t\t\t\t\t\tintensity *= 1.0f - sq(lightdist / FOG_AREA_RADIUS);\n\n\t\t\t\t\t\t\t\tCVector fogcoors(xi, yi, groundZ + 1.6f);\n\t\t\t\t\t\t\t\tif(CSprite::CalcScreenCoors(fogcoors, &spriteCoors, &spritew, &spriteh, true)) {\n\t\t\t\t\t\t\t\t\tfloat rotation = (CTimer::GetTimeInMilliseconds()&0x3FFF) * 2*3.14f / 0x4000;\n\t\t\t\t\t\t\t\t\tfloat size = FogSizes[r>>1];\n\t\t\t\t\t\t\t\t\tCSprite::RenderBufferedOneXLUSprite_Rotate_Aspect(spriteCoors.x, spriteCoors.y, spriteCoors.z,\n\t\t\t\t\t\t\t\t\t\tspritew * size, spriteh * size,\n\t\t\t\t\t\t\t\t\t\taLights[i].red * intensity, aLights[i].green * intensity, aLights[i].blue * intensity,\n\t\t\t\t\t\t\t\t\t\tintensity, 1/spriteCoors.z, rotation, 255);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tCSprite::FlushSpriteBuffer();\n\n\tPOP_RENDERGROUP();\n}\n\nbool\nCPointLights::ProcessVerticalLineUsingCache(CVector coors, float *groundZ)\n{\n\tfor(int i = 0; i < ARRAY_SIZE(aCachedMapReads); i++)\n\t\tif(aCachedMapReads[i] == coors){\n\t\t\t*groundZ = aCachedMapReadResults[i];\n\t\t\treturn true;\n\t\t}\n\n\tCColPoint point;\n\tCEntity *entity;\n\tif(CWorld::ProcessVerticalLine(coors, coors.z - 20.0f, point, entity, true, false, false, false, true, false, nil)){\n\t\taCachedMapReads[NextCachedValue] = coors;\n\t\taCachedMapReadResults[NextCachedValue] = point.point.z;\n\t\tNextCachedValue = (NextCachedValue+1) % ARRAY_SIZE(aCachedMapReads);\n\t\t*groundZ = point.point.z;\n\t\treturn true;\n\t}\n\treturn false;\n}\n"
  },
  {
    "path": "src/render/PointLights.h",
    "content": "#pragma once\n\nclass CRegisteredPointLight\n{\npublic:\n\tCVector coors;\n\tCVector dir;\n\tfloat radius;\n\tfloat red;\n\tfloat green;\n\tfloat blue;\n\tint8 type;\n\tint8 fogType;\n\tbool castExtraShadows;\n};\nVALIDATE_SIZE(CRegisteredPointLight, 0x2C);\n\nclass CPointLights\n{\npublic:\n\tstatic int16 NumLights;\n\tstatic CRegisteredPointLight aLights[NUMPOINTLIGHTS];\n\tstatic CVector aCachedMapReads[32];\n\tstatic float aCachedMapReadResults[32];\n\tstatic int32 NextCachedValue;\n\n\tenum {\n\t\tLIGHT_POINT,\n\t\tLIGHT_DIRECTIONAL,\n\t\tLIGHT_DARKEN,\t// no effects at all\n\t\t// these have only fog, otherwise no difference?\n\t\t// only used by CEntity::ProcessLightsForEntity it seems\n\t\t// and there used together with fog type\n\t\tLIGHT_FOGONLY_ALWAYS,\n\t\tLIGHT_FOGONLY,\n\t};\n\tenum {\n\t\tFOG_NONE,\n\t\tFOG_NORMAL,\t// taken from Foggyness\n\t\tFOG_ALWAYS\n\t};\n\n\tstatic void Init(void);\n\tstatic void InitPerFrame(void);\n\tstatic void AddLight(uint8 type, CVector coors, CVector dir, float radius, float red, float green, float blue, uint8 fogType, bool castExtraShadows);\n\tstatic float GenerateLightsAffectingObject(Const CVector *objCoors);\n\tstatic void RemoveLightsAffectingObject(void);\n\tstatic void RenderFogEffect(void);\n\tstatic bool ProcessVerticalLineUsingCache(CVector coors, float *groundZ);\n};\n"
  },
  {
    "path": "src/render/RenderBuffer.cpp",
    "content": "#include \"common.h\"\n\n#include \"RenderBuffer.h\"\n\nint32 TempBufferVerticesStored;\nint32 TempBufferIndicesStored;\n\nVertexBufferUnion TempVertexBuffer;\nRwImVertexIndex TempBufferRenderIndexList[TEMPBUFFERINDEXSIZE];\n\nint RenderBuffer::VerticesToBeStored;\nint RenderBuffer::IndicesToBeStored;\n\nvoid\nRenderBuffer::ClearRenderBuffer(void)\n{\n\tTempBufferVerticesStored = 0;\n\tTempBufferIndicesStored = 0;\n}\n\nvoid\nRenderBuffer::StartStoring(int numIndices, int numVertices, RwImVertexIndex **indexStart, RwIm3DVertex **vertexStart)\n{\n\tif(TempBufferIndicesStored + numIndices >= TEMPBUFFERINDEXSIZE)\n\t\tRenderStuffInBuffer();\n\tif(TempBufferVerticesStored + numVertices >= TEMPBUFFERVERTSIZE)\n\t\tRenderStuffInBuffer();\n        *indexStart = &TempBufferRenderIndexList[TempBufferIndicesStored];\n        *vertexStart = &TempBufferRenderVertices[TempBufferVerticesStored];\n        IndicesToBeStored = numIndices;\n        VerticesToBeStored = numVertices;\n}\n\nvoid\nRenderBuffer::StopStoring(void)\n{\n\tint i;\n\tfor(i = TempBufferIndicesStored; i < TempBufferIndicesStored+IndicesToBeStored; i++)\n\t\tTempBufferRenderIndexList[i] += TempBufferVerticesStored;\n\tTempBufferIndicesStored += IndicesToBeStored;\n\tTempBufferVerticesStored += VerticesToBeStored;\n}\n\nvoid\nRenderBuffer::RenderStuffInBuffer(void)\n{\n\tif(TempBufferVerticesStored && RwIm3DTransform(TempBufferRenderVertices, TempBufferVerticesStored, nil, rwIM3D_VERTEXUV)){\n\t\tRwIm3DRenderIndexedPrimitive(rwPRIMTYPETRILIST, TempBufferRenderIndexList, TempBufferIndicesStored);\n\t\tRwIm3DEnd();\n\t}\n\tClearRenderBuffer();\n}\n"
  },
  {
    "path": "src/render/RenderBuffer.h",
    "content": "class RenderBuffer\n{\npublic:\n\tstatic int VerticesToBeStored;\n\tstatic int IndicesToBeStored;\n\tstatic void ClearRenderBuffer(void);\n\tstatic void StartStoring(int numIndices, int numVertices, RwImVertexIndex **indexStart, RwIm3DVertex **vertexStart);\n\tstatic void StopStoring(void);\n\tstatic void RenderStuffInBuffer(void);\n};\n\n#define TEMPBUFFERVERTSIZE 512\n#define TEMPBUFFERINDEXSIZE 1024\n\nstruct VertexBufferUnion\n{\n\tRwIm2DVertex im2d[TEMPBUFFERVERTSIZE];\n\tRwIm3DVertex im3d[TEMPBUFFERVERTSIZE];\n};\n\nextern int32 TempBufferVerticesStored;\nextern int32 TempBufferIndicesStored;\nextern VertexBufferUnion TempVertexBuffer;\n#define TempBufferRenderVertices (TempVertexBuffer.im3d)\nextern RwImVertexIndex TempBufferRenderIndexList[TEMPBUFFERINDEXSIZE];"
  },
  {
    "path": "src/render/Renderer.cpp",
    "content": "#define WITHD3D\n#include \"common.h\"\n\n#include \"main.h\"\n#include \"Lights.h\"\n#include \"ModelInfo.h\"\n#include \"Treadable.h\"\n#include \"Ped.h\"\n#include \"Vehicle.h\"\n#include \"Boat.h\"\n#include \"Heli.h\"\n#include \"Bike.h\"\n#include \"Object.h\"\n#include \"PathFind.h\"\n#include \"Collision.h\"\n#include \"VisibilityPlugins.h\"\n#include \"Clock.h\"\n#include \"World.h\"\n#include \"Camera.h\"\n#include \"ModelIndices.h\"\n#include \"Streaming.h\"\n#include \"Shadows.h\"\n#include \"PointLights.h\"\n#include \"Occlusion.h\"\n#include \"Renderer.h\"\n#include \"custompipes.h\"\n#include \"Frontend.h\"\n\nbool gbShowPedRoadGroups;\nbool gbShowCarRoadGroups;\nbool gbShowCollisionPolys;\nbool gbShowCollisionLines;\nbool gbBigWhiteDebugLightSwitchedOn;\n\nbool gbDontRenderBuildings;\nbool gbDontRenderBigBuildings;\nbool gbDontRenderPeds;\nbool gbDontRenderObjects;\nbool gbDontRenderVehicles;\n\n// unused\nint16 TestCloseThings;\nint16 TestBigThings;\n\nstruct EntityInfo\n{\n\tCEntity *ent;\n\tfloat sort;\n};\n\nCLinkList<EntityInfo> gSortedVehiclesAndPeds;\n\nint32 CRenderer::ms_nNoOfVisibleEntities;\nCEntity *CRenderer::ms_aVisibleEntityPtrs[NUMVISIBLEENTITIES];\nCEntity *CRenderer::ms_aInVisibleEntityPtrs[NUMINVISIBLEENTITIES];\nint32 CRenderer::ms_nNoOfInVisibleEntities;\n#ifdef NEW_RENDERER\nint32 CRenderer::ms_nNoOfVisibleVehicles;\nCEntity *CRenderer::ms_aVisibleVehiclePtrs[NUMVISIBLEENTITIES];\nint32 CRenderer::ms_nNoOfVisibleBuildings;\nCEntity *CRenderer::ms_aVisibleBuildingPtrs[NUMVISIBLEENTITIES];\n#endif\n\nCVector CRenderer::ms_vecCameraPosition;\nCVehicle *CRenderer::m_pFirstPersonVehicle;\nbool CRenderer::m_loadingPriority;\nfloat CRenderer::ms_lodDistScale = 1.2f;\n\n// unused\nBlockedRange CRenderer::aBlockedRanges[16];\nBlockedRange* CRenderer::pFullBlockedRanges;\nBlockedRange* CRenderer::pEmptyBlockedRanges;\n\nvoid\nCRenderer::Init(void)\n{\n\tgSortedVehiclesAndPeds.Init(40);\n\tSortBIGBuildings();\n}\n\nvoid\nCRenderer::Shutdown(void)\n{\n\tgSortedVehiclesAndPeds.Shutdown();\n}\n\nvoid\nCRenderer::PreRender(void)\n{\n\tint i;\n\tCLink<CVisibilityPlugins::AlphaObjectInfo> *node;\n\n\tfor(i = 0; i < ms_nNoOfVisibleEntities; i++)\n\t\tms_aVisibleEntityPtrs[i]->PreRender();\n\n#ifdef NEW_RENDERER\n\tif(gbNewRenderer){\n\t\tfor(i = 0; i < ms_nNoOfVisibleVehicles; i++)\n\t\t\tms_aVisibleVehiclePtrs[i]->PreRender();\n\t\t// How is this done with cWorldStream?\n\t\tfor(i = 0; i < ms_nNoOfVisibleBuildings; i++)\n\t\t\tms_aVisibleBuildingPtrs[i]->PreRender();\n\t\tfor(node = CVisibilityPlugins::m_alphaBuildingList.head.next;\n\t\t    node != &CVisibilityPlugins::m_alphaBuildingList.tail;\n\t\t    node = node->next)\n\t\t\t((CEntity*)node->item.entity)->PreRender();\n\t}\n#endif\n\n\tfor (i = 0; i < ms_nNoOfInVisibleEntities; i++) {\n#ifdef SQUEEZE_PERFORMANCE\n\t\tif (ms_aInVisibleEntityPtrs[i]->IsVehicle() && ((CVehicle*)ms_aInVisibleEntityPtrs[i])->IsHeli())\n#endif\n\t\tms_aInVisibleEntityPtrs[i]->PreRender();\n\t}\n\n\tfor(node = CVisibilityPlugins::m_alphaEntityList.head.next;\n\t    node != &CVisibilityPlugins::m_alphaEntityList.tail;\n\t    node = node->next)\n\t\t((CEntity*)node->item.entity)->PreRender();\n\n\tCHeli::SpecialHeliPreRender();\n\tCShadows::RenderExtraPlayerShadows();\n}\n\nvoid\nCRenderer::RenderOneRoad(CEntity *e)\n{\n\tif(gbDontRenderBuildings)\n\t\treturn;\n\tif(gbShowCollisionPolys)\n\t\tCCollision::DrawColModel_Coloured(e->GetMatrix(), *CModelInfo::GetModelInfo(e->GetModelIndex())->GetColModel(), e->GetModelIndex());\n\telse{\n\t\tPUSH_RENDERGROUP(CModelInfo::GetModelInfo(e->GetModelIndex())->GetModelName());\n\n\t\te->Render();\n\n\t\tPOP_RENDERGROUP();\n\t}\n}\n\nvoid\nCRenderer::RenderOneNonRoad(CEntity *e)\n{\n\tCPed *ped;\n\tCVehicle *veh;\n\tint i;\n\tbool resetLights;\n\n#ifndef MASTER\n\tif(gbShowCollisionPolys){\n\t\tif(!e->IsVehicle()){\n\t\t\tCCollision::DrawColModel_Coloured(e->GetMatrix(), *CModelInfo::GetModelInfo(e->GetModelIndex())->GetColModel(), e->GetModelIndex());\n\t\t\treturn;\n\t\t}\n\t}else if(e->IsBuilding()){\n\t\tif(e->bIsBIGBuilding){\n\t\t\tif(gbDontRenderBigBuildings)\n\t\t\t\treturn;\n\t\t}else{\n\t\t\tif(gbDontRenderBuildings)\n\t\t\t\treturn;\n\t\t}\n\t}else\n#endif\n\tif(e->IsPed()){\n#ifndef MASTER\n\t\tif(gbDontRenderPeds)\n\t\t\treturn;\n#endif\n\t\tped = (CPed*)e;\n\t\tif(ped->m_nPedState == PED_DRIVING)\n\t\t\treturn;\n\t}\n#ifndef MASTER\n\telse if(e->IsObject() || e->IsDummy()){\n\t\tif(gbDontRenderObjects)\n\t\t\treturn;\n\t}else if(e->IsVehicle()){\n\t\t// re3 addition\n\t\tif(gbDontRenderVehicles)\n\t\t\treturn;\n\t}\n#endif\n\n\tPUSH_RENDERGROUP(CModelInfo::GetModelInfo(e->GetModelIndex())->GetModelName());\n\n\tresetLights = e->SetupLighting();\n\n\tif(e->IsVehicle()){\n\t\t// unfortunately can't use GetClump here\n\t\tCVisibilityPlugins::SetupVehicleVariables((RpClump*)e->m_rwObject);\n\t\tCVisibilityPlugins::InitAlphaAtomicList();\n\t}\n\n\t// Render Peds in vehicle before vehicle itself\n\tif(e->IsVehicle()){\n\t\tveh = (CVehicle*)e;\n\t\tif(veh->pDriver && veh->pDriver->m_nPedState == PED_DRIVING)\n\t\t\tveh->pDriver->Render();\n\t\tfor(i = 0; i < 8; i++)\n\t\t\tif(veh->pPassengers[i] && veh->pPassengers[i]->m_nPedState == PED_DRIVING)\n\t\t\t\tveh->pPassengers[i]->Render();\n\t\tSetCullMode(rwCULLMODECULLNONE);\n\t}\n\te->Render();\n\n\tif(e->IsVehicle()){\n\t\te->bImBeingRendered = true;\n\t\tCVisibilityPlugins::RenderAlphaAtomics();\n\t\te->bImBeingRendered = false;\n\t\tSetCullMode(rwCULLMODECULLBACK);\n\t}\n\n\te->RemoveLighting(resetLights);\n\n\tPOP_RENDERGROUP();\n}\n\nvoid\nCRenderer::RenderFirstPersonVehicle(void)\n{\n\tif(m_pFirstPersonVehicle == nil)\n\t\treturn;\n\tRwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)TRUE);\n\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);\n\tRwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);\n\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);\n\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);\n\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);\n\tRenderOneNonRoad(m_pFirstPersonVehicle);\n\tRwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE);\n}\n\ninline bool IsRoad(CEntity *e) { return e->IsBuilding() && ((CSimpleModelInfo*)CModelInfo::GetModelInfo(e->GetModelIndex()))->m_wetRoadReflection; }\n\nvoid\nCRenderer::RenderRoads(void)\n{\n\tint i;\n\tCEntity *e;\n\n\tPUSH_RENDERGROUP(\"CRenderer::RenderRoads\");\n\tRwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)TRUE);\n\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);\n\tSetCullMode(rwCULLMODECULLBACK);\n\tDeActivateDirectional();\n\tSetAmbientColours();\n\n\tfor(i = 0; i < ms_nNoOfVisibleEntities; i++){\n\t\te = ms_aVisibleEntityPtrs[i];\n\t\tif(IsRoad(e))\n\t\t\tRenderOneRoad(e);\n\t}\n\tPOP_RENDERGROUP();\n}\n\ninline bool PutIntoSortedVehicleList(CVehicle *veh)\n{\n\tif(veh->IsBoat()){\n\t\tint mode = TheCamera.Cams[TheCamera.ActiveCam].Mode;\n\t\tif(mode == CCam::MODE_WHEELCAM ||\n\t\t   mode == CCam::MODE_1STPERSON && TheCamera.GetLookDirection() != LOOKING_FORWARD && TheCamera.GetLookDirection() != LOOKING_BEHIND ||\n\t\t   CVisibilityPlugins::GetClumpAlpha(veh->GetClump()) != 255)\n\t\t\treturn false;\n\t\treturn true;\n\t}else\n\t\treturn veh->bTouchingWater;\t\t\n}\n\nvoid\nCRenderer::RenderEverythingBarRoads(void)\n{\n\tint i;\n\tCEntity *e;\n\tEntityInfo ei;\n\n\tPUSH_RENDERGROUP(\"CRenderer::RenderEverythingBarRoads\");\n\tRwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)TRUE);\n\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);\n\tSetCullMode(rwCULLMODECULLBACK);\n\tgSortedVehiclesAndPeds.Clear();\n\n\tfor(i = 0; i < ms_nNoOfVisibleEntities; i++){\n\t\te = ms_aVisibleEntityPtrs[i];\n\n\t\tif(IsRoad(e))\n\t\t\tcontinue;\n\n#ifdef EXTENDED_PIPELINES\n\t\tif(CustomPipes::bRenderingEnvMap && (e->IsPed() || e->IsVehicle()))\n\t\t\tcontinue;\n#endif\n\n\t\tif(e->IsVehicle() ||\n\t\t   e->IsPed() && CVisibilityPlugins::GetClumpAlpha((RpClump*)e->m_rwObject) != 255){\n\t\t\tif(e->IsVehicle() && PutIntoSortedVehicleList((CVehicle*)e)){\n\t\t\t\tei.ent = e;\n\t\t\t\tei.sort = (ms_vecCameraPosition - e->GetPosition()).MagnitudeSqr();\n\t\t\t\tgSortedVehiclesAndPeds.InsertSorted(ei);\n\t\t\t}else{\n\t\t\t\tif(!CVisibilityPlugins::InsertEntityIntoSortedList(e, (ms_vecCameraPosition - e->GetPosition()).Magnitude())){\n\t\t\t\t\tprintf(\"Ran out of space in alpha entity list\");\n\t\t\t\t\tRenderOneNonRoad(e);\n\t\t\t\t}\n\t\t\t}\n\t\t}else\n\t\t\tRenderOneNonRoad(e);\n\t}\n\tPOP_RENDERGROUP();\n}\n\nvoid\nCRenderer::RenderBoats(void)\n{\n\tCLink<EntityInfo> *node;\n\n\tPUSH_RENDERGROUP(\"CRenderer::RenderBoats\");\n\tRwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)TRUE);\n\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);\n\tSetCullMode(rwCULLMODECULLBACK);\n\n#ifdef NEW_RENDERER\n\tint i;\n\tCEntity *e;\n\tEntityInfo ei;\n\tif(gbNewRenderer){\n\t\tgSortedVehiclesAndPeds.Clear();\n\t\t// not the real thing\n\t\tfor(i = 0; i < ms_nNoOfVisibleVehicles; i++){\n\t\t\te = ms_aVisibleVehiclePtrs[i];\n\t\t\tif(e->IsVehicle() && PutIntoSortedVehicleList((CVehicle*)e)){\n\t\t\t\tei.ent = e;\n\t\t\t\tei.sort = (ms_vecCameraPosition - e->GetPosition()).MagnitudeSqr();\n\t\t\t\tgSortedVehiclesAndPeds.InsertSorted(ei);\n\t\t\t}\n\t\t}\n\t}\n#endif\n\n\tfor(node = gSortedVehiclesAndPeds.tail.prev;\n\t    node != &gSortedVehiclesAndPeds.head;\n\t    node = node->prev){\n\t\tCVehicle *v = (CVehicle*)node->item.ent;\n\t\tRenderOneNonRoad(v);\n\t}\n\tPOP_RENDERGROUP();\n}\n\n#ifdef NEW_RENDERER\n#ifndef LIBRW\n#error \"Need librw for EXTENDED_PIPELINES\"\n#endif\n#include \"WaterLevel.h\"\n\nenum {\n\t// blend passes\n\tPASS_NOZ,\t// no z-write\n\tPASS_ADD,\t// additive\n\tPASS_BLEND\t// normal blend\n};\n\nstatic void\nSetStencilState(int state)\n{\n\tswitch(state){\n\t// disable stencil\n\tcase 0:\n\t\trw::SetRenderState(rw::STENCILENABLE, FALSE);\n\t\tbreak;\n\t// test against stencil\n\tcase 1:\n\t\trw::SetRenderState(rw::STENCILENABLE, TRUE);\n\t\trw::SetRenderState(rw::STENCILFUNCTION, rw::STENCILNOTEQUAL);\n\t\trw::SetRenderState(rw::STENCILPASS, rw::STENCILKEEP);\n\t\trw::SetRenderState(rw::STENCILFAIL, rw::STENCILKEEP);\n\t\trw::SetRenderState(rw::STENCILZFAIL, rw::STENCILKEEP);\n\t\trw::SetRenderState(rw::STENCILFUNCTIONMASK, 0xFF);\n\t\trw::SetRenderState(rw::STENCILFUNCTIONREF, 0xFF);\n\t\tbreak;\n\t// write to stencil\n\tcase 2:\n\t\trw::SetRenderState(rw::STENCILENABLE, TRUE);\n\t\trw::SetRenderState(rw::STENCILFUNCTION, rw::STENCILALWAYS);\n\t\trw::SetRenderState(rw::STENCILPASS, rw::STENCILREPLACE);\n\t\trw::SetRenderState(rw::STENCILFUNCTIONREF, 0xFF);\n\t\tbreak;\n\t}\n}\n\nvoid\nCRenderer::RenderOneBuilding(CEntity *ent, float camdist)\n{\n\tif(ent->m_rwObject == nil)\n\t\treturn;\n\n\tent->bImBeingRendered = true;\t// TODO: this seems wrong, but do we even need it?\n\n\tassert(RwObjectGetType(ent->m_rwObject) == rpATOMIC);\n\tRpAtomic *atomic = (RpAtomic*)ent->m_rwObject;\n\tCSimpleModelInfo *mi = (CSimpleModelInfo*)CModelInfo::GetModelInfo(ent->GetModelIndex());\n\n\tint pass = PASS_BLEND;\n\tif(mi->m_additive)\t// very questionable\n\t\tpass = PASS_ADD;\n\tif(mi->m_noZwrite)\n\t\tpass = PASS_NOZ;\n\n\tif(ent->bDistanceFade){\n\t\tRpAtomic *lodatm;\n\t\tfloat fadefactor;\n\t\tuint32 alpha;\n\n\t\tlodatm = mi->GetAtomicFromDistance(camdist - FADE_DISTANCE);\n\t\tfadefactor = (mi->GetLargestLodDistance() - (camdist - FADE_DISTANCE))/FADE_DISTANCE;\n\t\tif(fadefactor > 1.0f)\n\t\t\tfadefactor = 1.0f;\n\t\talpha = mi->m_alpha * fadefactor;\n\n\t\tif(alpha == 255)\n\t\t\tWorldRender::AtomicFirstPass(atomic, pass);\n\t\telse{\n\t\t\t// not quite sure what this is about, do we have to do that?\n\t\t\tRpGeometry *geo = RpAtomicGetGeometry(lodatm);\n\t\t\tif(geo != RpAtomicGetGeometry(atomic))\n\t\t\t\tRpAtomicSetGeometry(atomic, geo, rpATOMICSAMEBOUNDINGSPHERE);\n\t\t\tWorldRender::AtomicFullyTransparent(atomic, pass, alpha);\n\t\t}\n\t}else\n\t\tWorldRender::AtomicFirstPass(atomic, pass);\n\n\tent->bImBeingRendered = false;\t// TODO: this seems wrong, but do we even need it?\n}\n\nvoid\nCRenderer::RenderWorld(int pass)\n{\n\tint i;\n\tCEntity *e;\n\tCLink<CVisibilityPlugins::AlphaObjectInfo> *node;\n\n\tRwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)TRUE);\n\tSetCullMode(rwCULLMODECULLBACK);\n\tDeActivateDirectional();\n\tSetAmbientColours();\n\n\t// Temporary...have to figure out sorting better\n\tswitch(pass){\n\tcase 0:\n\t\t// Roads\n\t\tPUSH_RENDERGROUP(\"CRenderer::RenderWorld - Roads\");\n\t\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);\n\t\tfor(i = 0; i < ms_nNoOfVisibleBuildings; i++){\n\t\t\te = ms_aVisibleBuildingPtrs[i];\n\t\t\tif(e->bIsBIGBuilding || IsRoad(e))\n\t\t\t\tRenderOneBuilding(e);\n\t\t}\n\t\tfor(node = CVisibilityPlugins::m_alphaBuildingList.tail.prev;\n\t\t    node != &CVisibilityPlugins::m_alphaBuildingList.head;\n\t\t    node = node->prev){\n\t\t\te = node->item.entity;\n\t\t\tif(e->bIsBIGBuilding || IsRoad(e))\n\t\t\t\tRenderOneBuilding(e, node->item.sort);\n\t\t}\n\t\tPOP_RENDERGROUP();\n\t\tbreak;\n\tcase 1:\n\t\t// Opaque\n\t\tPUSH_RENDERGROUP(\"CRenderer::RenderWorld - Opaque\");\n\t\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);\n\t\tfor(i = 0; i < ms_nNoOfVisibleBuildings; i++){\n\t\t\te = ms_aVisibleBuildingPtrs[i];\n\t\t\tif(!(e->bIsBIGBuilding || IsRoad(e)))\n\t\t\t\tRenderOneBuilding(e);\n\t\t}\n\t\tfor(node = CVisibilityPlugins::m_alphaBuildingList.tail.prev;\n\t\t    node != &CVisibilityPlugins::m_alphaBuildingList.head;\n\t\t    node = node->prev){\n\t\t\te = node->item.entity;\n\t\t\tif(!(e->bIsBIGBuilding || IsRoad(e)))\n\t\t\t\tRenderOneBuilding(e, node->item.sort);\n\t\t}\n\t\t// Now we have iterated through all visible buildings (unsorted and sorted)\n\t\t// and the transparency list is done.\n\n\t\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);\n\t\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE, FALSE);\n\t\tWorldRender::RenderBlendPass(PASS_NOZ);\n\t\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);\n\t\tPOP_RENDERGROUP();\n\t\tbreak;\n\tcase 2:\n\t\t// Transparent\n\t\tPUSH_RENDERGROUP(\"CRenderer::RenderWorld - Transparent\");\n\t\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);\n\t\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE);\n\t\tWorldRender::RenderBlendPass(PASS_ADD);\n\t\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);\n\t\tWorldRender::RenderBlendPass(PASS_BLEND);\n\t\tPOP_RENDERGROUP();\n\t\tbreak;\n\t}\n}\n\nvoid\nCRenderer::RenderPeds(void)\n{\n\tint i;\n\tCEntity *e;\n\n\tPUSH_RENDERGROUP(\"CRenderer::RenderPeds\");\n\tfor(i = 0; i < ms_nNoOfVisibleVehicles; i++){\n\t\te = ms_aVisibleVehiclePtrs[i];\n\t\tif(e->IsPed())\n\t\t\tRenderOneNonRoad(e);\n\t}\n\tPOP_RENDERGROUP();\n}\n\nvoid\nCRenderer::RenderVehicles(void)\n{\n\tint i;\n\tCEntity *e;\n\tEntityInfo ei;\n\tCLink<EntityInfo> *node;\n\n\tPUSH_RENDERGROUP(\"CRenderer::RenderVehicles\");\n\t// not the real thing\n\tfor(i = 0; i < ms_nNoOfVisibleVehicles; i++){\n\t\te = ms_aVisibleVehiclePtrs[i];\n\t\tif(!e->IsVehicle())\n\t\t\tcontinue;\n\t\tif(PutIntoSortedVehicleList((CVehicle*)e))\n\t\t\tcontinue;\t// boats handled elsewhere\n\t\tei.ent = e;\n\t\tei.sort = (ms_vecCameraPosition - e->GetPosition()).MagnitudeSqr();\n\t\tgSortedVehiclesAndPeds.InsertSorted(ei);\n\t}\n\n\tfor(node = gSortedVehiclesAndPeds.tail.prev;\n\t    node != &gSortedVehiclesAndPeds.head;\n\t    node = node->prev)\n\t\tRenderOneNonRoad(node->item.ent);\n\tPOP_RENDERGROUP();\n}\n\nvoid\nCRenderer::RenderTransparentWater(void)\n{\n\tint i;\n\tCEntity *e;\n\n\tPUSH_RENDERGROUP(\"CRenderer::RenderTransparentWater\");\n\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil);\n\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);\n\tRwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE);\n\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDZERO);\n\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE);\n\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);\n\tSetStencilState(2);\n\n\tfor(i = 0; i < ms_nNoOfVisibleVehicles; i++){\n\t\te = ms_aVisibleVehiclePtrs[i];\n\t\tif(e->IsVehicle() && ((CVehicle*)e)->IsBoat())\n\t\t\t((CBoat*)e)->RenderWaterOutPolys();\n\t}\n\n\tRwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)TRUE);\n\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);\n\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);\n\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);\n\tSetStencilState(1);\n\n\tCWaterLevel::RenderTransparentWater();\n\n\tSetStencilState(0);\n\tPOP_RENDERGROUP();\n}\n\nvoid\nCRenderer::ClearForFrame(void)\n{\n\tms_nNoOfVisibleEntities = 0;\n\tms_nNoOfVisibleVehicles = 0;\n\tms_nNoOfVisibleBuildings = 0;\n\tms_nNoOfInVisibleEntities = 0;\n\tgSortedVehiclesAndPeds.Clear();\n\n\tWorldRender::numBlendInsts[PASS_NOZ] = 0;\n\tWorldRender::numBlendInsts[PASS_ADD] = 0;\n\tWorldRender::numBlendInsts[PASS_BLEND] = 0;\n}\n#endif\n\nvoid\nCRenderer::RenderFadingInEntities(void)\n{\n\tPUSH_RENDERGROUP(\"CRenderer::RenderFadingInEntities\");\n\tRwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)TRUE);\n\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);\n\tSetCullMode(rwCULLMODECULLBACK);\n\tDeActivateDirectional();\n\tSetAmbientColours();\n\tCVisibilityPlugins::RenderFadingEntities();\n\tPOP_RENDERGROUP();\n}\n\nvoid\nCRenderer::RenderFadingInUnderwaterEntities(void)\n{\n\tPUSH_RENDERGROUP(\"CRenderer::RenderFadingInUnderwaterEntities\");\n\tDeActivateDirectional();\n\tSetAmbientColours();\n\tCVisibilityPlugins::RenderFadingUnderwaterEntities();\n\tPOP_RENDERGROUP();\n}\n\nvoid\nCRenderer::RenderCollisionLines(void)\n{\n\tint i;\n\n\t// game doesn't draw fading in entities\n\t// this should probably be fixed\n\tfor(i = 0; i < ms_nNoOfVisibleEntities; i++){\n\t\tCEntity *e = ms_aVisibleEntityPtrs[i];\n\t\tif(Abs(e->GetPosition().x - ms_vecCameraPosition.x) < 100.0f &&\n\t\t   Abs(e->GetPosition().y - ms_vecCameraPosition.y) < 100.0f)\n\t\t\tCCollision::DrawColModel(e->GetMatrix(), *e->GetColModel());\n\t}\n}\n\nenum Visbility\n{\n\tVIS_INVISIBLE,\n\tVIS_VISIBLE,\n\tVIS_OFFSCREEN,\n\tVIS_STREAMME\n};\n\n// Time Objects can be time culled if\n//   other == -1 || CModelInfo::GetModelInfo(other)->GetRwObject()\n// i.e. we have to draw even at the wrong time if\n//   other != -1 && CModelInfo::GetModelInfo(other)->GetRwObject() == nil\n\n#define OTHERUNAVAILABLE (other != -1 && CModelInfo::GetModelInfo(other)->GetRwObject() == nil)\n#define CANTIMECULL (!OTHERUNAVAILABLE)\n\nint32\nCRenderer::SetupEntityVisibility(CEntity *ent)\n{\n\tCSimpleModelInfo *mi = (CSimpleModelInfo*)CModelInfo::GetModelInfo(ent->m_modelIndex);\n\tCTimeModelInfo *ti;\n\tint32 other;\n\tfloat dist;\n\n\tbool request = true;\n\tif(mi->GetModelType() == MITYPE_TIME){\n \t\tti = (CTimeModelInfo*)mi;\n\t\tother = ti->GetOtherTimeModel();\n\t\tif(CClock::GetIsTimeInRange(ti->GetTimeOn(), ti->GetTimeOff())){\n\t\t\t// don't fade in, or between time objects\n\t\t\tif(CANTIMECULL)\n\t\t\t\tti->m_alpha = 255;\n\t\t}else{\n\t\t\t// Hide if possible\n\t\t\tif(CANTIMECULL)\n\t\t\t\treturn VIS_INVISIBLE;\n\t\t\t// can't cull, so we'll try to draw this one, but don't request\n\t\t\t// it since what we really want is the other one.\n\t\t\trequest = false;\n\t\t}\n\t}else{\n\t\tif(mi->GetModelType() != MITYPE_SIMPLE && mi->GetModelType() != MITYPE_WEAPON){\n\t\t\tif(FindPlayerVehicle() == ent &&\n\t\t\t   TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_1STPERSON &&\n\t\t\t   !(FindPlayerVehicle()->IsBike() && ((CBike*)FindPlayerVehicle())->bWheelieCam)){\n\t\t\t\t// Player's vehicle in first person mode\n\t\t\t\tCVehicle *veh = (CVehicle*)ent;\n\t\t\t\tint model = veh->GetModelIndex();\n\t\t\t\tint direction = TheCamera.Cams[TheCamera.ActiveCam].DirectionWasLooking;\n\t\t\t\tif(direction == LOOKING_FORWARD ||\n\t\t\t\t   ent->GetModelIndex() == MI_RHINO ||\n\t\t\t\t   ent->GetModelIndex() == MI_COACH ||\n\t\t\t\t   TheCamera.m_bInATunnelAndABigVehicle ||\n\t\t\t\t   direction == LOOKING_BEHIND && veh->pHandling->Flags & HANDLING_UNKNOWN){\n\t\t\t\t\tent->bNoBrightHeadLights = true;\n\t\t\t\t\treturn VIS_OFFSCREEN;\n\t\t\t\t}\n\n\t\t\t\tif(direction != LOOKING_BEHIND ||\n\t\t\t\t   !veh->IsBoat() || model == MI_REEFER || model == MI_TROPIC || model == MI_PREDATOR || model == MI_SKIMMER){\n\t\t\t\t\tm_pFirstPersonVehicle = (CVehicle*)ent;\n\t\t\t\t\tent->bNoBrightHeadLights = false;\n\t\t\t\t\treturn VIS_OFFSCREEN;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// All sorts of Clumps\n\t\t\tif(ent->m_rwObject == nil || !ent->bIsVisible)\n\t\t\t\treturn VIS_INVISIBLE;\n\t\t\tif(!ent->GetIsOnScreen() || ent->IsEntityOccluded())\n\t\t\t\treturn VIS_OFFSCREEN;\n\t\t\tif(ent->bDrawLast){\n\t\t\t\tdist = (ent->GetPosition() - ms_vecCameraPosition).Magnitude();\n\t\t\t\tCVisibilityPlugins::InsertEntityIntoSortedList(ent, dist);\n\t\t\t\tent->bDistanceFade = false;\n\t\t\t\treturn VIS_INVISIBLE;\n\t\t\t}\n\t\t\treturn VIS_VISIBLE;\n\t\t}\n\t\tif(ent->bDontStream){\n\t\t\tif(ent->m_rwObject == nil || !ent->bIsVisible)\n\t\t\t\treturn VIS_INVISIBLE;\n\t\t\tif(!ent->GetIsOnScreen() || ent->IsEntityOccluded())\n\t\t\t\treturn VIS_OFFSCREEN;\n\t\t\tif(ent->bDrawLast){\n\t\t\t\tdist = (ent->GetPosition() - ms_vecCameraPosition).Magnitude();\n\t\t\t\tCVisibilityPlugins::InsertEntityIntoSortedList(ent, dist);\n\t\t\t\tent->bDistanceFade = false;\n\t\t\t\treturn VIS_INVISIBLE;\n\t\t\t}\n\t\t\treturn VIS_VISIBLE;\n\t\t}\n\t}\n\n\t// Simple ModelInfo\n\n\tif(!IsAreaVisible(ent->m_area))\n\t\treturn VIS_INVISIBLE;\n\n\tdist = (ent->GetPosition() - ms_vecCameraPosition).Magnitude();\n\n#ifndef FIX_BUGS\n\t// Whatever this is supposed to do, it breaks fading for objects\n\t// whose draw dist is > LOD_DISTANCE-FADE_DISTANCE, i.e. 280\n\t// because decreasing dist here makes the object visible above LOD_DISTANCE\n\t// before fading normally once below LOD_DISTANCE.\n\t// aha! this must be a workaround for the fact that we're not taking\n\t// the LOD multiplier into account here anywhere\n\tif(LOD_DISTANCE < dist && dist < mi->GetLargestLodDistance() + FADE_DISTANCE)\n\t\tdist += mi->GetLargestLodDistance() - LOD_DISTANCE;\n#endif\n\n\tif(ent->IsObject() && ent->bRenderDamaged)\n\t\tmi->m_isDamaged = true;\n\n\tRpAtomic *a = mi->GetAtomicFromDistance(dist);\n\tif(a){\n\t\tmi->m_isDamaged = false;\n\t\tif(ent->m_rwObject == nil)\n\t\t\tent->CreateRwObject();\n\t\tassert(ent->m_rwObject);\n\t\tRpAtomic *rwobj = (RpAtomic*)ent->m_rwObject;\n\t\t// Make sure our atomic uses the right geometry and not\n\t\t// that of an atomic for another draw distance.\n\t\tif(RpAtomicGetGeometry(a) != RpAtomicGetGeometry(rwobj))\n\t\t\tRpAtomicSetGeometry(rwobj, RpAtomicGetGeometry(a), rpATOMICSAMEBOUNDINGSPHERE); // originally 5 (mistake?)\n\t\tmi->IncreaseAlpha();\n\t\tif(ent->m_rwObject == nil || !ent->bIsVisible)\n\t\t\treturn VIS_INVISIBLE;\n\n\t\tif(!ent->GetIsOnScreen() || ent->IsEntityOccluded()){\n\t\t\tmi->m_alpha = 255;\n\t\t\treturn VIS_OFFSCREEN;\n\t\t}\n\n\t\tif(mi->m_alpha != 255){\n\t\t\tCVisibilityPlugins::InsertEntityIntoSortedList(ent, dist);\n\t\t\tent->bDistanceFade = true;\n\t\t\treturn VIS_INVISIBLE;\n\t\t}\n\n\t\tif(mi->m_drawLast || ent->bDrawLast){\n\t\t\tif(CVisibilityPlugins::InsertEntityIntoSortedList(ent, dist)){\n\t\t\t\tent->bDistanceFade = false;\n\t\t\t\treturn VIS_INVISIBLE;\n\t\t\t}\n\t\t}\n\t\treturn VIS_VISIBLE;\n\t}\n\n\t// Object is not loaded, figure out what to do\n\n\tif(mi->m_noFade){\n\t\tmi->m_isDamaged = false;\n\t\t// request model\n\t\tif(dist - STREAM_DISTANCE < mi->GetLargestLodDistance() && request)\n\t\t\treturn VIS_STREAMME;\n\t\treturn VIS_INVISIBLE;\n\t}\n\n\t// We might be fading\n\n\ta = mi->GetAtomicFromDistance(dist - FADE_DISTANCE);\n\tmi->m_isDamaged = false;\n\tif(a == nil){\n\t\t// request model\n\t\tif(dist - FADE_DISTANCE - STREAM_DISTANCE < mi->GetLargestLodDistance() && request)\n\t\t\treturn VIS_STREAMME;\n\t\treturn VIS_INVISIBLE;\n\t}\n\n\tif(ent->m_rwObject == nil)\n\t\tent->CreateRwObject();\n\tassert(ent->m_rwObject);\n\tRpAtomic *rwobj = (RpAtomic*)ent->m_rwObject;\n\tif(RpAtomicGetGeometry(a) != RpAtomicGetGeometry(rwobj))\n\t\tRpAtomicSetGeometry(rwobj, RpAtomicGetGeometry(a), rpATOMICSAMEBOUNDINGSPHERE); // originally 5 (mistake?)\n\tmi->IncreaseAlpha();\n\tif(ent->m_rwObject == nil || !ent->bIsVisible)\n\t\treturn VIS_INVISIBLE;\n\n\tif(!ent->GetIsOnScreen() || ent->IsEntityOccluded()){\n\t\tmi->m_alpha = 255;\n\t\treturn VIS_OFFSCREEN;\n\t}else{\n\t\tCVisibilityPlugins::InsertEntityIntoSortedList(ent, dist);\n\t\tent->bDistanceFade = true;\n\t\treturn VIS_OFFSCREEN;\t// Why this?\n\t}\n}\n\nint32\nCRenderer::SetupBigBuildingVisibility(CEntity *ent)\n{\n\tCSimpleModelInfo *mi = (CSimpleModelInfo*)CModelInfo::GetModelInfo(ent->m_modelIndex);\n\tCTimeModelInfo *ti;\n\tint32 other;\n\n\tif(!IsAreaVisible(ent->m_area))\n\t\treturn VIS_INVISIBLE;\n\n\tbool request = true;\n\tif(mi->GetModelType() == MITYPE_TIME){\n\t\tti = (CTimeModelInfo*)mi;\n\t\tother = ti->GetOtherTimeModel();\n\t\tif(CClock::GetIsTimeInRange(ti->GetTimeOn(), ti->GetTimeOff())){\n\t\t\t// don't fade in, or between time objects\n\t\t\tif(CANTIMECULL)\n\t\t\t\tti->m_alpha = 255;\n\t\t}else{\n\t\t\t// Hide if possible\n\t\t\tif(CANTIMECULL){\n\t\t\t\tent->DeleteRwObject();\n\t\t\t\treturn VIS_INVISIBLE;\n\t\t\t}\n\t\t\t// can't cull, so we'll try to draw this one, but don't request\n\t\t\t// it since what we really want is the other one.\n\t\t\trequest = false;\n\t\t}\n\t}else if(mi->GetModelType() == MITYPE_VEHICLE)\n\t\treturn ent->IsVisible() ? VIS_VISIBLE : VIS_INVISIBLE;\n\n\tfloat dist = (ms_vecCameraPosition-ent->GetPosition()).Magnitude();\n\tCSimpleModelInfo *nonLOD = mi->GetRelatedModel();\n\n\t// Find out whether to draw below near distance.\n\t// This is only the case if there is a non-LOD which is either not\n\t// loaded or not completely faded in yet.\n\tif(dist < mi->GetNearDistance() && dist < LOD_DISTANCE){\n\t\t// No non-LOD or non-LOD is completely visible.\n\t\tif(nonLOD == nil ||\n\t\t   nonLOD->GetRwObject() && nonLOD->m_alpha == 255)\n\t\t\treturn VIS_INVISIBLE;\n\n\t\t// But if it is a time object, we'd rather draw the wrong\n\t\t// non-LOD than the right LOD.\n\t\tif(nonLOD->GetModelType() == MITYPE_TIME){\n\t\t\tti = (CTimeModelInfo*)nonLOD;\n\t\t\tother = ti->GetOtherTimeModel();\n\t\t\tif(other != -1 && CModelInfo::GetModelInfo(other)->GetRwObject())\n\t\t\t\treturn VIS_INVISIBLE;\n\t\t}\n\t}\n\n\tRpAtomic *a = mi->GetFirstAtomicFromDistance(dist);\n\tif(a){\n\t\tif(ent->m_rwObject == nil)\n\t\t\tent->CreateRwObject();\n\t\tassert(ent->m_rwObject);\n\t\tRpAtomic *rwobj = (RpAtomic*)ent->m_rwObject;\n\n\t\t// Make sure our atomic uses the right geometry and not\n\t\t// that of an atomic for another draw distance.\n\t\tif(RpAtomicGetGeometry(a) != RpAtomicGetGeometry(rwobj))\n\t\t\tRpAtomicSetGeometry(rwobj, RpAtomicGetGeometry(a), rpATOMICSAMEBOUNDINGSPHERE); // originally 5 (mistake?)\n\t\tmi->IncreaseAlpha();\n\t\tif(!ent->IsVisible() || !ent->GetIsOnScreenComplex() || ent->IsEntityOccluded()){\n\t\t\tmi->m_alpha = 255;\n\t\t\treturn VIS_INVISIBLE;\n\t\t}\n\n\t\tif(mi->m_alpha != 255){\n\t\t\tCVisibilityPlugins::InsertEntityIntoSortedList(ent, dist);\n\t\t\tent->bDistanceFade = true;\n\t\t\treturn VIS_INVISIBLE;\n\t\t}\n\n\t\tif(mi->m_drawLast){\n\t\t\tCVisibilityPlugins::InsertEntityIntoSortedList(ent, dist);\n\t\t\tent->bDistanceFade = false;\n\t\t\treturn VIS_INVISIBLE;\n\t\t}\n\t\treturn VIS_VISIBLE;\n\t}\n\n\tif(mi->m_noFade){\n\t\tent->DeleteRwObject();\n\t\treturn VIS_INVISIBLE;\n\t}\n\n\n\t// get faded atomic\n\ta = mi->GetFirstAtomicFromDistance(dist - FADE_DISTANCE);\n\tif(a == nil){\n\t\tif(ent->bStreamBIGBuilding && dist-STREAM_DISTANCE < mi->GetLodDistance(0) && request){\n\t\t\treturn ent->GetIsOnScreen() ? VIS_STREAMME : VIS_INVISIBLE;\n\t\t}else{\n\t\t\tent->DeleteRwObject();\n\t\t\treturn VIS_INVISIBLE;\n\t\t}\n\t}\n\n\t// Fade...\n\tif(ent->m_rwObject == nil)\n\t\tent->CreateRwObject();\n\tassert(ent->m_rwObject);\n\tRpAtomic *rwobj = (RpAtomic*)ent->m_rwObject;\n\tif(RpAtomicGetGeometry(a) != RpAtomicGetGeometry(rwobj))\n\t\tRpAtomicSetGeometry(rwobj, RpAtomicGetGeometry(a), rpATOMICSAMEBOUNDINGSPHERE); // originally 5 (mistake?)\n\tmi->IncreaseAlpha();\n\tif(!ent->IsVisible() || !ent->GetIsOnScreenComplex() || ent->IsEntityOccluded()){\n\t\tmi->m_alpha = 255;\n\t\treturn VIS_INVISIBLE;\n\t}\n\tCVisibilityPlugins::InsertEntityIntoSortedList(ent, dist);\n\tent->bDistanceFade = true;\n\treturn VIS_INVISIBLE;\n}\n\nvoid\nCRenderer::ConstructRenderList(void)\n{\n\tCOcclusion::ProcessBeforeRendering();\n#ifdef NEW_RENDERER\n\tif(!gbNewRenderer)\n#endif\n{\n\tms_nNoOfVisibleEntities = 0;\n\tms_nNoOfInVisibleEntities = 0;\n}\n\tms_vecCameraPosition = TheCamera.GetPosition();\n\n\t// unused\n\tpFullBlockedRanges = nil;\n\tpEmptyBlockedRanges = aBlockedRanges;\n\tfor(int i = 0; i < 16; i++){\n\t\taBlockedRanges[i].prev = &aBlockedRanges[i-1];\n\t\taBlockedRanges[i].next = &aBlockedRanges[i+1];\n\t}\n\taBlockedRanges[0].prev = nil;\n\taBlockedRanges[15].next = nil;\n\n\t// unused\n\tTestCloseThings = 0;\n\tTestBigThings = 0;\n\n\tScanWorld();\n}\n\nvoid\nLimitFrustumVector(CVector &vec1, const CVector &vec2, float l)\n{\n\tfloat f;\n\tf = (l - vec2.z) / (vec1.z - vec2.z);\n\tvec1.x = f*(vec1.x - vec2.x) + vec2.x;\n\tvec1.y = f*(vec1.y - vec2.y) + vec2.y;\n\tvec1.z = f*(vec1.z - vec2.z) + vec2.z;\n}\n\nenum Corners\n{\n\tCORNER_CAM = 0,\n\tCORNER_FAR_TOPLEFT,\n\tCORNER_FAR_TOPRIGHT,\n\tCORNER_FAR_BOTRIGHT,\n\tCORNER_FAR_BOTLEFT,\n\tCORNER_LOD_LEFT,\n\tCORNER_LOD_RIGHT,\n\tCORNER_PRIO_LEFT,\n\tCORNER_PRIO_RIGHT,\n};\n\nvoid\nCRenderer::ScanWorld(void)\n{\n\tfloat f = RwCameraGetFarClipPlane(TheCamera.m_pRwCamera);\n\tRwV2d vw = *RwCameraGetViewWindow(TheCamera.m_pRwCamera);\n\tCVector vectors[9];\n\tRwMatrix *cammatrix;\n\tRwV2d poly[3];\n\n\tmemset(vectors, 0, sizeof(vectors));\n\tvectors[CORNER_FAR_TOPLEFT].x = -vw.x * f;\n\tvectors[CORNER_FAR_TOPLEFT].y = vw.y * f;\n\tvectors[CORNER_FAR_TOPLEFT].z = f;\n\tvectors[CORNER_FAR_TOPRIGHT].x = vw.x * f;\n\tvectors[CORNER_FAR_TOPRIGHT].y = vw.y * f;\n\tvectors[CORNER_FAR_TOPRIGHT].z = f;\n\tvectors[CORNER_FAR_BOTRIGHT].x = vw.x * f;\n\tvectors[CORNER_FAR_BOTRIGHT].y = -vw.y * f;\n\tvectors[CORNER_FAR_BOTRIGHT].z = f;\n\tvectors[CORNER_FAR_BOTLEFT].x = -vw.x * f;\n\tvectors[CORNER_FAR_BOTLEFT].y = -vw.y * f;\n\tvectors[CORNER_FAR_BOTLEFT].z = f;\n\n\tcammatrix = RwFrameGetMatrix(RwCameraGetFrame(TheCamera.m_pRwCamera));\n\n\tm_pFirstPersonVehicle = nil;\n\tCVisibilityPlugins::InitAlphaEntityList();\n\tCWorld::AdvanceCurrentScanCode();\n\n\t// unused\n\tstatic CVector prevPos;\n\tstatic CVector prevFwd;\n\tstatic bool smallMovement;\n\tsmallMovement = (TheCamera.GetPosition() - prevPos).MagnitudeSqr() < SQR(4.0f) &&\n\t\tDotProduct(TheCamera.GetForward(), prevFwd) > 0.98f;\n\tprevPos = TheCamera.GetPosition();\n\tprevFwd = TheCamera.GetForward();\n\n\tif(cammatrix->at.z > 0.0f){\n\t\t// looking up, bottom corners are further away\n\t\tvectors[CORNER_LOD_LEFT] = vectors[CORNER_FAR_BOTLEFT] * LOD_DISTANCE/f;\n\t\tvectors[CORNER_LOD_RIGHT] = vectors[CORNER_FAR_BOTRIGHT] * LOD_DISTANCE/f;\n\t}else{\n\t\t// looking down, top corners are further away\n\t\tvectors[CORNER_LOD_LEFT] = vectors[CORNER_FAR_TOPLEFT] * LOD_DISTANCE/f;\n\t\tvectors[CORNER_LOD_RIGHT] = vectors[CORNER_FAR_TOPRIGHT] * LOD_DISTANCE/f;\n\t}\n\tvectors[CORNER_PRIO_LEFT].x = vectors[CORNER_LOD_LEFT].x * 0.2f;\n\tvectors[CORNER_PRIO_LEFT].y = vectors[CORNER_LOD_LEFT].y * 0.2f;\n\tvectors[CORNER_PRIO_LEFT].z = vectors[CORNER_LOD_LEFT].z;\n\tvectors[CORNER_PRIO_RIGHT].x = vectors[CORNER_LOD_RIGHT].x * 0.2f;\n\tvectors[CORNER_PRIO_RIGHT].y = vectors[CORNER_LOD_RIGHT].y * 0.2f;\n\tvectors[CORNER_PRIO_RIGHT].z = vectors[CORNER_LOD_RIGHT].z;\n\tRwV3dTransformPoints(vectors, vectors, 9, cammatrix);\n\n\tm_loadingPriority = false;\n\tif(TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOPDOWN ||\n#ifdef FIX_BUGS\n\t   TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_GTACLASSIC ||\n#endif\n\t   TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOP_DOWN_PED){\n\t\tCRect rect;\n\t\tint x1, x2, y1, y2;\n\t\tLimitFrustumVector(vectors[CORNER_FAR_TOPLEFT], vectors[CORNER_CAM], -100.0f);\n\t\trect.ContainPoint(vectors[CORNER_FAR_TOPLEFT]);\n\t\tLimitFrustumVector(vectors[CORNER_FAR_TOPRIGHT], vectors[CORNER_CAM], -100.0f);\n\t\trect.ContainPoint(vectors[CORNER_FAR_TOPRIGHT]);\n\t\tLimitFrustumVector(vectors[CORNER_FAR_BOTRIGHT], vectors[CORNER_CAM], -100.0f);\n\t\trect.ContainPoint(vectors[CORNER_FAR_BOTRIGHT]);\n\t\tLimitFrustumVector(vectors[CORNER_FAR_BOTLEFT], vectors[CORNER_CAM], -100.0f);\n\t\trect.ContainPoint(vectors[CORNER_FAR_BOTLEFT]);\n\t\tx1 = CWorld::GetSectorIndexX(rect.left);\n\t\tif(x1 < 0) x1 = 0;\n\t\tx2 = CWorld::GetSectorIndexX(rect.right);\n\t\tif(x2 >= NUMSECTORS_X-1) x2 = NUMSECTORS_X-1;\n\t\ty1 = CWorld::GetSectorIndexY(rect.top);\n\t\tif(y1 < 0) y1 = 0;\n\t\ty2 = CWorld::GetSectorIndexY(rect.bottom);\n\t\tif(y2 >= NUMSECTORS_Y-1) y2 = NUMSECTORS_Y-1;\n\t\tfor(; x1 <= x2; x1++)\n\t\t\tfor(int y = y1; y <= y2; y++)\n\t\t\t\tScanSectorList(CWorld::GetSector(x1, y)->m_lists);\n\t}else{\n#ifdef GTA_TRAIN\n\t\tCVehicle *train = FindPlayerTrain();\n\t\tif(train && train->GetPosition().z < 0.0f){\n\t\t\tpoly[0].x = CWorld::GetSectorX(vectors[CORNER_CAM].x);\n\t\t\tpoly[0].y = CWorld::GetSectorY(vectors[CORNER_CAM].y);\n\t\t\tpoly[1].x = CWorld::GetSectorX(vectors[CORNER_LOD_LEFT].x);\n\t\t\tpoly[1].y = CWorld::GetSectorY(vectors[CORNER_LOD_LEFT].y);\n\t\t\tpoly[2].x = CWorld::GetSectorX(vectors[CORNER_LOD_RIGHT].x);\n\t\t\tpoly[2].y = CWorld::GetSectorY(vectors[CORNER_LOD_RIGHT].y);\n\t\t\tScanSectorPoly(poly, 3, ScanSectorList_Subway);\n\t\t}else\n#endif\n\t\t{\n\t\t\tif(f > LOD_DISTANCE){\n\t\t\t\t// priority\n\t\t\t\tpoly[0].x = CWorld::GetSectorX(vectors[CORNER_CAM].x);\n\t\t\t\tpoly[0].y = CWorld::GetSectorY(vectors[CORNER_CAM].y);\n\t\t\t\tpoly[1].x = CWorld::GetSectorX(vectors[CORNER_PRIO_LEFT].x);\n\t\t\t\tpoly[1].y = CWorld::GetSectorY(vectors[CORNER_PRIO_LEFT].y);\n\t\t\t\tpoly[2].x = CWorld::GetSectorX(vectors[CORNER_PRIO_RIGHT].x);\n\t\t\t\tpoly[2].y = CWorld::GetSectorY(vectors[CORNER_PRIO_RIGHT].y);\n\t\t\t\tScanSectorPoly(poly, 3, ScanSectorList_Priority);\n\n\t\t\t\t// below LOD\n\t\t\t\tpoly[0].x = CWorld::GetSectorX(vectors[CORNER_CAM].x);\n\t\t\t\tpoly[0].y = CWorld::GetSectorY(vectors[CORNER_CAM].y);\n\t\t\t\tpoly[1].x = CWorld::GetSectorX(vectors[CORNER_LOD_LEFT].x);\n\t\t\t\tpoly[1].y = CWorld::GetSectorY(vectors[CORNER_LOD_LEFT].y);\n\t\t\t\tpoly[2].x = CWorld::GetSectorX(vectors[CORNER_LOD_RIGHT].x);\n\t\t\t\tpoly[2].y = CWorld::GetSectorY(vectors[CORNER_LOD_RIGHT].y);\n\t\t\t\tScanSectorPoly(poly, 3, ScanSectorList);\n\t\t\t}else{\n\t\t\t\tpoly[0].x = CWorld::GetSectorX(vectors[CORNER_CAM].x);\n\t\t\t\tpoly[0].y = CWorld::GetSectorY(vectors[CORNER_CAM].y);\n\t\t\t\tpoly[1].x = CWorld::GetSectorX(vectors[CORNER_FAR_TOPLEFT].x);\n\t\t\t\tpoly[1].y = CWorld::GetSectorY(vectors[CORNER_FAR_TOPLEFT].y);\n\t\t\t\tpoly[2].x = CWorld::GetSectorX(vectors[CORNER_FAR_TOPRIGHT].x);\n\t\t\t\tpoly[2].y = CWorld::GetSectorY(vectors[CORNER_FAR_TOPRIGHT].y);\n\t\t\t\tScanSectorPoly(poly, 3, ScanSectorList);\n\t\t\t}\n\t\t\t\n#ifdef NO_ISLAND_LOADING\n\t\t\tif (FrontEndMenuManager.m_PrefsIslandLoading == CMenuManager::ISLAND_LOADING_HIGH) {\n\t\t\t\tScanBigBuildingList(CWorld::GetBigBuildingList(LEVEL_BEACH));\n\t\t\t\tScanBigBuildingList(CWorld::GetBigBuildingList(LEVEL_MAINLAND));\n\t\t\t} else \n#endif\n\t\t\t{\n#ifdef FIX_BUGS\n\t\t\tif(CCollision::ms_collisionInMemory != LEVEL_GENERIC)\n#endif\n\t\t\t\tScanBigBuildingList(CWorld::GetBigBuildingList(CGame::currLevel));\n\t\t\t}\n\t\t\tScanBigBuildingList(CWorld::GetBigBuildingList(LEVEL_GENERIC));\n\t\t}\n\t}\n}\n\nvoid\nCRenderer::RequestObjectsInFrustum(void)\n{\n\tfloat f = RwCameraGetFarClipPlane(TheCamera.m_pRwCamera);\n\tRwV2d vw = *RwCameraGetViewWindow(TheCamera.m_pRwCamera);\n\tCVector vectors[9];\n\tRwMatrix *cammatrix;\n\tRwV2d poly[3];\n\n\tmemset(vectors, 0, sizeof(vectors));\n\tvectors[CORNER_FAR_TOPLEFT].x = -vw.x * f;\n\tvectors[CORNER_FAR_TOPLEFT].y = vw.y * f;\n\tvectors[CORNER_FAR_TOPLEFT].z = f;\n\tvectors[CORNER_FAR_TOPRIGHT].x = vw.x * f;\n\tvectors[CORNER_FAR_TOPRIGHT].y = vw.y * f;\n\tvectors[CORNER_FAR_TOPRIGHT].z = f;\n\tvectors[CORNER_FAR_BOTRIGHT].x = vw.x * f;\n\tvectors[CORNER_FAR_BOTRIGHT].y = -vw.y * f;\n\tvectors[CORNER_FAR_BOTRIGHT].z = f;\n\tvectors[CORNER_FAR_BOTLEFT].x = -vw.x * f;\n\tvectors[CORNER_FAR_BOTLEFT].y = -vw.y * f;\n\tvectors[CORNER_FAR_BOTLEFT].z = f;\n\n\tcammatrix = RwFrameGetMatrix(RwCameraGetFrame(TheCamera.m_pRwCamera));\n\n\tCWorld::AdvanceCurrentScanCode();\n\tms_vecCameraPosition = TheCamera.GetPosition();\n\n\tif(cammatrix->at.z > 0.0f){\n\t\t// looking up, bottom corners are further away\n\t\tvectors[CORNER_LOD_LEFT] = vectors[CORNER_FAR_BOTLEFT] * LOD_DISTANCE/f;\n\t\tvectors[CORNER_LOD_RIGHT] = vectors[CORNER_FAR_BOTRIGHT] * LOD_DISTANCE/f;\n\t}else{\n\t\t// looking down, top corners are further away\n\t\tvectors[CORNER_LOD_LEFT] = vectors[CORNER_FAR_TOPLEFT] * LOD_DISTANCE/f;\n\t\tvectors[CORNER_LOD_RIGHT] = vectors[CORNER_FAR_TOPRIGHT] * LOD_DISTANCE/f;\n\t}\n\tvectors[CORNER_PRIO_LEFT].x = vectors[CORNER_LOD_LEFT].x * 0.2f;\n\tvectors[CORNER_PRIO_LEFT].y = vectors[CORNER_LOD_LEFT].y * 0.2f;\n\tvectors[CORNER_PRIO_LEFT].z = vectors[CORNER_LOD_LEFT].z;\n\tvectors[CORNER_PRIO_RIGHT].x = vectors[CORNER_LOD_RIGHT].x * 0.2f;\n\tvectors[CORNER_PRIO_RIGHT].y = vectors[CORNER_LOD_RIGHT].y * 0.2f;\n\tvectors[CORNER_PRIO_RIGHT].z = vectors[CORNER_LOD_RIGHT].z;\n\tRwV3dTransformPoints(vectors, vectors, 9, cammatrix);\n\n\tif(TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOPDOWN ||\n#ifdef FIX_BUGS\n\t   TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_GTACLASSIC ||\n#endif\n\t   TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOP_DOWN_PED){\n\t\tCRect rect;\n\t\tint x1, x2, y1, y2;\n\t\tLimitFrustumVector(vectors[CORNER_FAR_TOPLEFT], vectors[CORNER_CAM], -100.0f);\n\t\trect.ContainPoint(vectors[CORNER_FAR_TOPLEFT]);\n\t\tLimitFrustumVector(vectors[CORNER_FAR_TOPRIGHT], vectors[CORNER_CAM], -100.0f);\n\t\trect.ContainPoint(vectors[CORNER_FAR_TOPRIGHT]);\n\t\tLimitFrustumVector(vectors[CORNER_FAR_BOTRIGHT], vectors[CORNER_CAM], -100.0f);\n\t\trect.ContainPoint(vectors[CORNER_FAR_BOTRIGHT]);\n\t\tLimitFrustumVector(vectors[CORNER_FAR_BOTLEFT], vectors[CORNER_CAM], -100.0f);\n\t\trect.ContainPoint(vectors[CORNER_FAR_BOTLEFT]);\n\t\tx1 = CWorld::GetSectorIndexX(rect.left);\n\t\tif(x1 < 0) x1 = 0;\n\t\tx2 = CWorld::GetSectorIndexX(rect.right);\n\t\tif(x2 >= NUMSECTORS_X-1) x2 = NUMSECTORS_X-1;\n\t\ty1 = CWorld::GetSectorIndexY(rect.top);\n\t\tif(y1 < 0) y1 = 0;\n\t\ty2 = CWorld::GetSectorIndexY(rect.bottom);\n\t\tif(y2 >= NUMSECTORS_Y-1) y2 = NUMSECTORS_Y-1;\n\t\tfor(; x1 <= x2; x1++)\n\t\t\tfor(int y = y1; y <= y2; y++)\n\t\t\t\tScanSectorList_RequestModels(CWorld::GetSector(x1, y)->m_lists);\n\t}else{\n\t\tpoly[0].x = CWorld::GetSectorX(vectors[CORNER_CAM].x);\n\t\tpoly[0].y = CWorld::GetSectorY(vectors[CORNER_CAM].y);\n\t\tpoly[1].x = CWorld::GetSectorX(vectors[CORNER_LOD_LEFT].x);\n\t\tpoly[1].y = CWorld::GetSectorY(vectors[CORNER_LOD_LEFT].y);\n\t\tpoly[2].x = CWorld::GetSectorX(vectors[CORNER_LOD_RIGHT].x);\n\t\tpoly[2].y = CWorld::GetSectorY(vectors[CORNER_LOD_RIGHT].y);\n\t\tScanSectorPoly(poly, 3, ScanSectorList_RequestModels);\n\t}\n}\n\nbool\nCEntity::SetupLighting(void)\n{\n\treturn false;\n}\n\nvoid\nCEntity::RemoveLighting(bool)\n{\n}\n\nbool\nCPed::SetupLighting(void)\n{\n\tActivateDirectional();\n\tSetAmbientColoursForPedsCarsAndObjects();\n\n#ifndef MASTER\n\t// Originally this was being called through iteration of Sectors, but putting it here is better.\n\tif (GetDebugDisplay() != 0 && !IsPlayer())\n\t\tDebugRenderOnePedText();\n#endif\n\n\tif (bRenderScorched) {\n\t\tWorldReplaceNormalLightsWithScorched(Scene.world, 0.1f);\n\t} else {\n\t\t// Note that this lightMult is only affected by LIGHT_DARKEN. If there's no LIGHT_DARKEN, it will be 1.0.\n\t\tfloat lightMult = CPointLights::GenerateLightsAffectingObject(&GetPosition());\n\t\tif (lightMult != 1.0f) {\n\t\t\tSetAmbientAndDirectionalColours(lightMult);\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n\nvoid\nCPed::RemoveLighting(bool reset)\n{\n\tif (!bRenderScorched) {\n\t\tCRenderer::RemoveVehiclePedLights(this, reset);\n\t\tif (reset)\n\t\t\tReSetAmbientAndDirectionalColours();\n\t}\n\tSetAmbientColours();\n\tDeActivateDirectional();\n}\n\nfloat\nCalcNewDelta(RwV2d *a, RwV2d *b)\n{\n\treturn (b->x - a->x) / (b->y - a->y);\n}\n\n#ifdef FIX_BUGS\n#define TOINT(x) ((int)Floor(x))\n#else\n#define TOINT(x) ((int)(x))\n#endif\n\nvoid\nCRenderer::ScanSectorPoly(RwV2d *poly, int32 numVertices, void (*scanfunc)(CPtrList *))\n{\n\tfloat miny, maxy;\n\tint y, yend;\n\tint x, xstart, xend;\n\tint i;\n\tint a1, a2, b1, b2;\n\tfloat deltaA, deltaB;\n\tfloat xA, xB;\n\n\tminy = poly[0].y;\n\tmaxy = poly[0].y;\n\ta2 = 0;\n\txstart = 9999;\n\txend = -9999;\n\n\tfor(i = 1; i < numVertices; i++){\n\t\tif(poly[i].y > maxy)\n\t\t\tmaxy = poly[i].y;\n\t\tif(poly[i].y < miny){\n\t\t\tminy = poly[i].y;\n\t\t\ta2 = i;\n\t\t}\n\t}\n\ty = TOINT(miny);\n\tyend = TOINT(maxy);\n\n\t// Go left in poly to find first edge b\n\tb2 = a2;\n\tfor(i = 0; i < numVertices; i++){\n\t\tb1 = b2--;\n\t\tif(b2 < 0) b2 = numVertices-1;\n\t\tif(poly[b1].x < xstart)\n\t\t\txstart = TOINT(poly[b1].x);\n\t\tif(TOINT(poly[b1].y) != TOINT(poly[b2].y))\n\t\t\tbreak;\n\t}\n\t// Go right to find first edge a\n\tfor(i = 0; i < numVertices; i++){\n\t\ta1 = a2++;\n\t\tif(a2 == numVertices) a2 = 0;\n\t\tif(poly[a1].x > xend)\n\t\t\txend = TOINT(poly[a1].x);\n\t\tif(TOINT(poly[a1].y) != TOINT(poly[a2].y))\n\t\t\tbreak;\n\t}\n\n\t// prestep x1 and x2 to next integer y\n\tdeltaA = CalcNewDelta(&poly[a1], &poly[a2]);\n\txA = deltaA * (Ceil(poly[a1].y) - poly[a1].y) + poly[a1].x;\n\tdeltaB = CalcNewDelta(&poly[b1], &poly[b2]);\n\txB = deltaB * (Ceil(poly[b1].y) - poly[b1].y) + poly[b1].x;\n\n\tif(y != yend){\n\t\tif(deltaB < 0.0f && TOINT(xB) < xstart)\n\t\t\txstart = TOINT(xB);\n\t\tif(deltaA >= 0.0f && TOINT(xA) > xend)\n\t\t\txend = TOINT(xA);\n\t}\n\n\twhile(y <= yend && y < NUMSECTORS_Y){\n\t\t// scan one x-line\n\t\tif(y >= 0 && xstart < NUMSECTORS_X)\n\t\t\tfor(x = xstart; x <= xend && x != NUMSECTORS_X; x++)\n\t\t\t\tif(x >= 0)\n\t\t\t\t\tscanfunc(CWorld::GetSector(x, y)->m_lists);\n\n\t\t// advance one scan line\n\t\ty++;\n\t\txA += deltaA;\n\t\txB += deltaB;\n\n\t\t// update left side\n\t\tif(y == TOINT(poly[b2].y)){\n\t\t\t// reached end of edge\n\t\t\tif(y == yend){\n\t\t\t\tif(deltaB < 0.0f){\n\t\t\t\t\tdo{\n\t\t\t\t\t\txstart = TOINT(poly[b2--].x);\n\t\t\t\t\t\tif(b2 < 0) b2 = numVertices-1;\n\t\t\t\t\t}while(xstart > TOINT(poly[b2].x));\n\t\t\t\t}else\n\t\t\t\t\txstart = TOINT(xB - deltaB);\n\t\t\t}else{\n\t\t\t\t// switch edges\n\t\t\t\tif(deltaB < 0.0f)\n\t\t\t\t\txstart = TOINT(poly[b2].x);\n\t\t\t\telse\n\t\t\t\t\txstart = TOINT(xB - deltaB);\n\t\t\t\tdo{\n\t\t\t\t\tb1 = b2--;\n\t\t\t\t\tif(b2 < 0) b2 = numVertices-1;\n\t\t\t\t\tif(TOINT(poly[b1].x) < xstart)\n\t\t\t\t\t\txstart = TOINT(poly[b1].x);\n\t\t\t\t}while(y == TOINT(poly[b2].y));\n\t\t\t\tdeltaB = CalcNewDelta(&poly[b1], &poly[b2]);\n\t\t\t\txB = deltaB * (Ceil(poly[b1].y) - poly[b1].y) + poly[b1].x;\n\t\t\t\tif(deltaB < 0.0f && TOINT(xB) < xstart)\n\t\t\t\t\txstart = TOINT(xB);\n\t\t\t}\n\t\t}else{\n\t\t\tif(deltaB < 0.0f)\n\t\t\t\txstart = TOINT(xB);\n\t\t\telse\n\t\t\t\txstart = TOINT(xB - deltaB);\n\t\t}\n\n\t\t// update right side\n\t\tif(y == TOINT(poly[a2].y)){\n\t\t\t// reached end of edge\n\t\t\tif(y == yend){\n\t\t\t\tif(deltaA < 0.0f)\n\t\t\t\t\txend = TOINT(xA - deltaA);\n\t\t\t\telse{\n\t\t\t\t\tdo{\n\t\t\t\t\t\txend = TOINT(poly[a2++].x);\n\t\t\t\t\t\tif(a2 == numVertices) a2 = 0;\n\t\t\t\t\t}while(xend < TOINT(poly[a2].x));\n\t\t\t\t}\n\t\t\t}else{\n\t\t\t\t// switch edges\n\t\t\t\tif(deltaA < 0.0f)\n\t\t\t\t\txend = TOINT(xA - deltaA);\n\t\t\t\telse\n\t\t\t\t\txend = TOINT(poly[a2].x);\n\t\t\t\tdo{\n\t\t\t\t\ta1 = a2++;\n\t\t\t\t\tif(a2 == numVertices) a2 = 0;\n\t\t\t\t\tif(TOINT(poly[a1].x) > xend)\n\t\t\t\t\t\txend = TOINT(poly[a1].x);\n\t\t\t\t}while(y == TOINT(poly[a2].y));\n\t\t\t\tdeltaA = CalcNewDelta(&poly[a1], &poly[a2]);\n\t\t\t\txA = deltaA * (Ceil(poly[a1].y) - poly[a1].y) + poly[a1].x;\n\t\t\t\tif(deltaA >= 0.0f && TOINT(xA) > xend)\n\t\t\t\t\txend = TOINT(xA);\n\t\t\t}\n\t\t}else{\n\t\t\tif(deltaA < 0.0f)\n\t\t\t\txend = TOINT(xA - deltaA);\n\t\t\telse\n\t\t\t\txend = TOINT(xA);\n\t\t}\n\t}\n}\n\nvoid\nCRenderer::InsertEntityIntoList(CEntity *ent)\n{\n#ifdef FIX_BUGS\n\tif (!ent->m_rwObject) return;\n#endif\n\n#ifdef NEW_RENDERER\n\t// TODO: there are more flags being checked here\n\tif(gbNewRenderer && (ent->IsVehicle() || ent->IsPed()))\n\t\tms_aVisibleVehiclePtrs[ms_nNoOfVisibleVehicles++] = ent;\n\telse if(gbNewRenderer && ent->IsBuilding())\n\t\tms_aVisibleBuildingPtrs[ms_nNoOfVisibleBuildings++] = ent;\n\telse\n#endif\n\t\tms_aVisibleEntityPtrs[ms_nNoOfVisibleEntities++] = ent;\n}\n\nvoid\nCRenderer::ScanBigBuildingList(CPtrList &list)\n{\n\tCPtrNode *node;\n\tCEntity *ent;\n\tint vis;\n\n\tint f = CTimer::GetFrameCounter() & 3;\n\tfor(node = list.first; node; node = node->next){\n\t\tent = (CEntity*)node->item;\n\t\tif(ent->bOffscreen || (ent->m_randomSeed&3) != f){\n\t\t\tent->bOffscreen = true;\n\t\t\tvis = SetupBigBuildingVisibility(ent);\n\t\t}else\n\t\t\tvis = VIS_VISIBLE;\n\t\tswitch(vis){\n\t\tcase VIS_VISIBLE:\n\t\t\tInsertEntityIntoList(ent);\n\t\t\tent->bOffscreen = false;\n\t\t\tbreak;\n\t\tcase VIS_STREAMME:\n\t\t\tif(!CStreaming::ms_disableStreaming)\n\t\t\t\tCStreaming::RequestModel(ent->GetModelIndex(), 0);\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\nvoid\nCRenderer::ScanSectorList(CPtrList *lists)\n{\n\tCPtrNode *node;\n\tCPtrList *list;\n\tCEntity *ent;\n\tint i;\n\tfloat dx, dy;\n\n\tfor(i = 0; i < NUMSECTORENTITYLISTS; i++){\n\t\tlist = &lists[i];\n\t\tfor(node = list->first; node; node = node->next){\n\t\t\tent = (CEntity*)node->item;\n\t\t\tif(ent->m_scanCode == CWorld::GetCurrentScanCode())\n\t\t\t\tcontinue;\t// already seen\n\t\t\tent->m_scanCode = CWorld::GetCurrentScanCode();\n\t\t\tent->bOffscreen = false;\n\n\t\t\tswitch(SetupEntityVisibility(ent)){\n\t\t\tcase VIS_VISIBLE:\n\t\t\t\tInsertEntityIntoList(ent);\n\t\t\t\tbreak;\n\t\t\tcase VIS_INVISIBLE:\n\t\t\t\tif(!IsGlass(ent->GetModelIndex()))\n\t\t\t\t\tbreak;\n\t\t\t\t// fall through\n\t\t\tcase VIS_OFFSCREEN:\n\t\t\t\tent->bOffscreen = true;\n\t\t\t\tdx = ms_vecCameraPosition.x - ent->GetPosition().x;\n\t\t\t\tdy = ms_vecCameraPosition.y - ent->GetPosition().y;\n\t\t\t\tif(dx > -30.0f && dx < 30.0f &&\n\t\t\t\t   dy > -30.0f && dy < 30.0f &&\n\t\t\t\t   ms_nNoOfInVisibleEntities < NUMINVISIBLEENTITIES - 1)\n\t\t\t\t\tms_aInVisibleEntityPtrs[ms_nNoOfInVisibleEntities++] = ent;\n\t\t\t\tbreak;\n\t\t\tcase VIS_STREAMME:\n\t\t\t\tif(!CStreaming::ms_disableStreaming)\n\t\t\t\t\tif(!m_loadingPriority || CStreaming::ms_numModelsRequested < 10)\n\t\t\t\t\t\tCStreaming::RequestModel(ent->GetModelIndex(), 0);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nCRenderer::ScanSectorList_Priority(CPtrList *lists)\n{\n\tCPtrNode *node;\n\tCPtrList *list;\n\tCEntity *ent;\n\tint i;\n\tfloat dx, dy;\n\n\tfor(i = 0; i < NUMSECTORENTITYLISTS; i++){\n\t\tlist = &lists[i];\n\t\tfor(node = list->first; node; node = node->next){\n\t\t\tent = (CEntity*)node->item;\n\t\t\tif(ent->m_scanCode == CWorld::GetCurrentScanCode())\n\t\t\t\tcontinue;\t// already seen\n\t\t\tent->m_scanCode = CWorld::GetCurrentScanCode();\n\t\t\tent->bOffscreen = false;\n\n\t\t\tswitch(SetupEntityVisibility(ent)){\n\t\t\tcase VIS_VISIBLE:\n\t\t\t\tInsertEntityIntoList(ent);\n\t\t\t\tbreak;\n\t\t\tcase VIS_INVISIBLE:\n\t\t\t\tif(!IsGlass(ent->GetModelIndex()))\n\t\t\t\t\tbreak;\n\t\t\t\t// fall through\n\t\t\tcase VIS_OFFSCREEN:\n\t\t\t\tent->bOffscreen = true;\n\t\t\t\tdx = ms_vecCameraPosition.x - ent->GetPosition().x;\n\t\t\t\tdy = ms_vecCameraPosition.y - ent->GetPosition().y;\n\t\t\t\tif(dx > -30.0f && dx < 30.0f &&\n\t\t\t\t   dy > -30.0f && dy < 30.0f &&\n\t\t\t\t   ms_nNoOfInVisibleEntities < NUMINVISIBLEENTITIES - 1)\n\t\t\t\t\tms_aInVisibleEntityPtrs[ms_nNoOfInVisibleEntities++] = ent;\n\t\t\t\tbreak;\n\t\t\tcase VIS_STREAMME:\n\t\t\t\tif(!CStreaming::ms_disableStreaming){\n\t\t\t\t\tCStreaming::RequestModel(ent->GetModelIndex(), 0);\n\t\t\t\t\tif(CStreaming::ms_aInfoForModel[ent->GetModelIndex()].m_loadState != STREAMSTATE_LOADED)\n\t\t\t\t\t\tm_loadingPriority = true;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n}\n\n#ifdef GTA_TRAIN\nvoid\nCRenderer::ScanSectorList_Subway(CPtrList *lists)\n{\n\tCPtrNode *node;\n\tCPtrList *list;\n\tCEntity *ent;\n\tint i;\n\tfloat dx, dy;\n\n\tfor(i = 0; i < NUMSECTORENTITYLISTS; i++){\n\t\tlist = &lists[i];\n\t\tfor(node = list->first; node; node = node->next){\n\t\t\tent = (CEntity*)node->item;\n\t\t\tif(ent->m_scanCode == CWorld::GetCurrentScanCode())\n\t\t\t\tcontinue;\t// already seen\n\t\t\tent->m_scanCode = CWorld::GetCurrentScanCode();\n\t\t\tent->bOffscreen = false;\n\t\t\tswitch(SetupEntityVisibility(ent)){\n\t\t\tcase VIS_VISIBLE:\n\t\t\t\tInsertEntityIntoList(ent);\n\t\t\t\tbreak;\n\t\t\tcase VIS_OFFSCREEN:\n\t\t\t\tent->bOffscreen = true;\n\t\t\t\tdx = ms_vecCameraPosition.x - ent->GetPosition().x;\n\t\t\t\tdy = ms_vecCameraPosition.y - ent->GetPosition().y;\n\t\t\t\tif(dx > -30.0f && dx < 30.0f &&\n\t\t\t\t   dy > -30.0f && dy < 30.0f &&\n\t\t\t\t   ms_nNoOfInVisibleEntities < NUMINVISIBLEENTITIES - 1)\n\t\t\t\t\tms_aInVisibleEntityPtrs[ms_nNoOfInVisibleEntities++] = ent;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n}\n#endif\n\nvoid\nCRenderer::ScanSectorList_RequestModels(CPtrList *lists)\n{\n\tCPtrNode *node;\n\tCPtrList *list;\n\tCEntity *ent;\n\tint i;\n\n\tfor(i = 0; i < NUMSECTORENTITYLISTS; i++){\n\t\tlist = &lists[i];\n\t\tfor(node = list->first; node; node = node->next){\n\t\t\tent = (CEntity*)node->item;\n\t\t\tif(ent->m_scanCode == CWorld::GetCurrentScanCode())\n\t\t\t\tcontinue;\t// already seen\n\t\t\tent->m_scanCode = CWorld::GetCurrentScanCode();\n\t\t\tif(ShouldModelBeStreamed(ent, ms_vecCameraPosition))\n\t\t\t\tCStreaming::RequestModel(ent->GetModelIndex(), 0);\n\t\t}\n\t}\n}\n\n// Put big buildings in front\n// This seems pointless because the sector lists shouldn't have big buildings in the first place\nvoid\nCRenderer::SortBIGBuildings(void)\n{\n\tint x, y;\n\tfor(y = 0; y < NUMSECTORS_Y; y++)\n\t\tfor(x = 0; x < NUMSECTORS_X; x++){\n\t\t\tSortBIGBuildingsForSectorList(&CWorld::GetSector(x, y)->m_lists[ENTITYLIST_BUILDINGS]);\n\t\t\tSortBIGBuildingsForSectorList(&CWorld::GetSector(x, y)->m_lists[ENTITYLIST_BUILDINGS_OVERLAP]);\n\t\t}\n}\n\nvoid\nCRenderer::SortBIGBuildingsForSectorList(CPtrList *list)\n{\n\tCPtrNode *node;\n\tCEntity *ent;\n\n\tfor(node = list->first; node; node = node->next){\n\t\tent = (CEntity*)node->item;\n\t\tif(ent->bIsBIGBuilding){\n\t\t\tlist->RemoveNode(node);\n\t\t\tlist->InsertNode(node);\n\t\t}\n\t}\n}\n\nbool\nCRenderer::ShouldModelBeStreamed(CEntity *ent, const CVector &campos)\n{\n\tif(!IsAreaVisible(ent->m_area))\n\t\treturn false;\n\tCTimeModelInfo *mi = (CTimeModelInfo *)CModelInfo::GetModelInfo(ent->GetModelIndex());\n\tif(mi->GetModelType() == MITYPE_TIME)\n\t\tif(!CClock::GetIsTimeInRange(mi->GetTimeOn(), mi->GetTimeOff()))\n\t\t\treturn false;\n\tfloat dist = (ent->GetPosition() - campos).Magnitude();\n\tif(mi->m_noFade)\n\t\treturn dist - STREAM_DISTANCE < mi->GetLargestLodDistance();\n\telse\n\t\treturn dist - FADE_DISTANCE - STREAM_DISTANCE < mi->GetLargestLodDistance();\n}\n\nvoid\nCRenderer::RemoveVehiclePedLights(CEntity *ent, bool reset)\n{\n\tif(!ent->bRenderScorched){\n\t\tCPointLights::RemoveLightsAffectingObject();\n\t\tif(reset)\n\t\t\tReSetAmbientAndDirectionalColours();\n\t}\n\tSetAmbientColours();\n\tDeActivateDirectional();\n}\n"
  },
  {
    "path": "src/render/Renderer.h",
    "content": "#pragma once\n\nclass CEntity;\n\n#ifdef FIX_BUGS\n#define LOD_DISTANCE (300.0f*TheCamera.LODDistMultiplier)\n#else\n#define LOD_DISTANCE 300.0f\n#endif\n#define FADE_DISTANCE 20.0f\n#define STREAM_DISTANCE 30.0f\n\nextern bool gbShowPedRoadGroups;\nextern bool gbShowCarRoadGroups;\nextern bool gbShowCollisionPolys;\nextern bool gbShowCollisionLines;\nextern bool gbBigWhiteDebugLightSwitchedOn;\n\nextern bool gbDontRenderBuildings;\nextern bool gbDontRenderBigBuildings;\nextern bool gbDontRenderPeds;\nextern bool gbDontRenderObjects;\nextern bool gbDontRenderVehicles;\n\nclass CVehicle;\nclass CPtrList;\n\n// unused\nstruct BlockedRange\n{\n\tfloat a, b;\t// unknown\n\tBlockedRange *prev, *next;\n};\n\nclass CRenderer\n{\n\tstatic int32 ms_nNoOfVisibleEntities;\n\tstatic CEntity *ms_aVisibleEntityPtrs[NUMVISIBLEENTITIES];\n\tstatic int32 ms_nNoOfInVisibleEntities;\n\tstatic CEntity *ms_aInVisibleEntityPtrs[NUMINVISIBLEENTITIES];\n#ifdef NEW_RENDERER\n\tstatic int32 ms_nNoOfVisibleVehicles;\n\tstatic CEntity *ms_aVisibleVehiclePtrs[NUMVISIBLEENTITIES];\n\t// for cWorldStream emulation\n\tstatic int32 ms_nNoOfVisibleBuildings;\n\tstatic CEntity *ms_aVisibleBuildingPtrs[NUMVISIBLEENTITIES];\n#endif\n\n\tstatic CVector ms_vecCameraPosition;\n\tstatic CVehicle *m_pFirstPersonVehicle;\n\n\t// unused\n\tstatic BlockedRange aBlockedRanges[16];\n\tstatic BlockedRange *pFullBlockedRanges;\n\tstatic BlockedRange *pEmptyBlockedRanges;\npublic:\n\tstatic float ms_lodDistScale;\n\tstatic bool m_loadingPriority;\n\n\tstatic void Init(void);\n\tstatic void Shutdown(void);\n\tstatic void PreRender(void);\n\n\tstatic void RenderRoads(void);\n\tstatic void RenderFadingInEntities(void);\n\tstatic void RenderFadingInUnderwaterEntities(void);\n\tstatic void RenderEverythingBarRoads(void);\n\tstatic void RenderBoats(void);\n\tstatic void RenderOneRoad(CEntity *);\n\tstatic void RenderOneNonRoad(CEntity *);\n\tstatic void RenderFirstPersonVehicle(void);\n\n\tstatic void RenderCollisionLines(void);\n\n\tstatic int32 SetupEntityVisibility(CEntity *ent);\n\tstatic int32 SetupBigBuildingVisibility(CEntity *ent);\n\n\tstatic void ConstructRenderList(void);\n\tstatic void ScanWorld(void);\n\tstatic void RequestObjectsInFrustum(void);\n\tstatic void ScanSectorPoly(RwV2d *poly, int32 numVertices, void (*scanfunc)(CPtrList *));\n\tstatic void ScanBigBuildingList(CPtrList &list);\n\tstatic void ScanSectorList(CPtrList *lists);\n\tstatic void ScanSectorList_Priority(CPtrList *lists);\n\tstatic void ScanSectorList_Subway(CPtrList *lists);\n\tstatic void ScanSectorList_RequestModels(CPtrList *lists);\n\n\tstatic void SortBIGBuildings(void);\n\tstatic void SortBIGBuildingsForSectorList(CPtrList *list);\n\n\tstatic bool ShouldModelBeStreamed(CEntity *ent, const CVector &campos);\n\n\tstatic void RemoveVehiclePedLights(CEntity *ent, bool reset);\n\n\n#ifdef NEW_RENDERER\n\tstatic void ClearForFrame(void);\n\tstatic void RenderPeds(void);\n\tstatic void RenderVehicles(void);\t// also renders peds in LCS\n\tstatic void RenderOneBuilding(CEntity *ent, float camdist = 0.0f);\n\tstatic void RenderWorld(int pass);\t// like cWorldStream::Render(int)\n\tstatic void RenderTransparentWater(void);\t// keep-out polys and transparent water\n#endif\n\tstatic void InsertEntityIntoList(CEntity *ent);\n};\n"
  },
  {
    "path": "src/render/Rubbish.cpp",
    "content": "#include \"common.h\"\n#include \"main.h\"\n\n#include \"General.h\"\n#include \"Timer.h\"\n#include \"Weather.h\"\n#include \"Camera.h\"\n#include \"World.h\"\n#include \"Vehicle.h\"\n#include \"ZoneCull.h\"\n#include \"Stats.h\"\n#include \"TxdStore.h\"\n#include \"RenderBuffer.h\"\n#include \"Rubbish.h\"\n\n#define RUBBISH_MAX_DIST (23.0f)\n#define RUBBISH_FADE_DIST (20.0f)\n\nRwTexture *gpRubbishTexture[4];\nRwImVertexIndex RubbishIndexList[6];\nbool CRubbish::bRubbishInvisible;\nint CRubbish::RubbishVisibility;\nCOneSheet CRubbish::aSheets[NUM_RUBBISH_SHEETS];\nCOneSheet CRubbish::StartEmptyList;\nCOneSheet CRubbish::EndEmptyList;\nCOneSheet CRubbish::StartStaticsList;\nCOneSheet CRubbish::EndStaticsList;\nCOneSheet CRubbish::StartMoversList;\nCOneSheet CRubbish::EndMoversList;\n\n\nvoid\nCOneSheet::AddToList(COneSheet *list)\n{\n\tthis->m_next = list->m_next;\n\tthis->m_prev = list;\n\tlist->m_next = this;\n\tthis->m_next->m_prev = this;\n}\n\nvoid\nCOneSheet::RemoveFromList(void)\n{\n\tm_next->m_prev = m_prev;\n\tm_prev->m_next = m_next;\n}\n\n\nvoid\nCRubbish::Render(void)\n{\n\tint type;\n\n\tif(RubbishVisibility == 0)\n\t\treturn;\n\n\tPUSH_RENDERGROUP(\"CRubbish::Render\");\n\n\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);\n\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);\n\tRwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)TRUE);\n\n\tfor(type = 0; type < 4; type++){\n\t\tif(type < 3 || CStats::PamphletMissionPassed)\n\t\t\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpRubbishTexture[type]));\n\n\t\tTempBufferIndicesStored = 0;\n\t\tTempBufferVerticesStored = 0;\n\n\t\tCOneSheet *sheet;\n\t\tfor(sheet = &aSheets[type*NUM_RUBBISH_SHEETS / 4];\n\t\t    sheet < &aSheets[(type+1)*NUM_RUBBISH_SHEETS / 4];\n\t\t    sheet++){\n\t\t\tif(sheet->m_state == 0)\n\t\t\t\tcontinue;\n\n\t\t\tuint32 alpha = 100;\n\t\t\tCVector pos;\n\t\t\tif(sheet->m_state == 1){\n\t\t\t\tpos = sheet->m_basePos;\n\t\t\t\tif(!sheet->m_isVisible)\n\t\t\t\t\talpha = 0;\n\t\t\t}else{\n\t\t\t\tpos = sheet->m_animatedPos;\n\t\t\t\t// Not fully visible during animation, calculate current alpha\n\t\t\t\tif(!sheet->m_isVisible || !sheet->m_targetIsVisible){\n\t\t\t\t\tfloat t = (float)(CTimer::GetTimeInMilliseconds() - sheet->m_moveStart)/sheet->m_moveDuration;\n\t\t\t\t\tfloat f1 = sheet->m_isVisible ? 1.0f-t : 0.0f;\n\t\t\t\t\tfloat f2 = sheet->m_targetIsVisible ? t : 0.0f;\n\t\t\t\t\talpha = 100 * (f1+f2);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfloat camDist = (pos - TheCamera.GetPosition()).Magnitude2D();\n\t\t\tif(camDist < RUBBISH_MAX_DIST){\n\t\t\t\tif(camDist >= RUBBISH_FADE_DIST)\n\t\t\t\t\talpha -= alpha*(camDist-RUBBISH_FADE_DIST)/(RUBBISH_MAX_DIST-RUBBISH_FADE_DIST);\n\t\t\t\talpha = (RubbishVisibility*alpha)/256;\n\n\t\t\t\tfloat vx1, vy1, vx2, vy2;\n\t\t\t\tif(type == 0 || type == 1){\n\t\t\t\t\tvx1 = 0.9f*Sin(sheet->m_angle);\n\t\t\t\t\tvy1 = 0.9f*Cos(sheet->m_angle);\n\t\t\t\t\tvx2 = 0.3f*Cos(sheet->m_angle);\n\t\t\t\t\tvy2 = -0.3f*Sin(sheet->m_angle);\n\t\t\t\t}else{\n\t\t\t\t\tvx1 = 0.3f*Sin(sheet->m_angle);\n\t\t\t\t\tvy1 = 0.3f*Cos(sheet->m_angle);\n\t\t\t\t\tvx2 = 0.3f*Cos(sheet->m_angle);\n\t\t\t\t\tvy2 = -0.3f*Sin(sheet->m_angle);\n\t\t\t\t}\n\n\t\t\t\tint v = TempBufferVerticesStored;\n\t\t\t\tRwIm3DVertexSetPos(&TempBufferRenderVertices[v+0], pos.x + vx1 + vx2, pos.y + vy1 + vy2, pos.z);\n\t\t\t\tRwIm3DVertexSetPos(&TempBufferRenderVertices[v+1], pos.x + vx1 - vx2, pos.y + vy1 - vy2, pos.z);\n\t\t\t\tRwIm3DVertexSetPos(&TempBufferRenderVertices[v+2], pos.x - vx1 + vx2, pos.y - vy1 + vy2, pos.z);\n\t\t\t\tRwIm3DVertexSetPos(&TempBufferRenderVertices[v+3], pos.x - vx1 - vx2, pos.y - vy1 - vy2, pos.z);\n\t\t\t\tRwIm3DVertexSetRGBA(&TempBufferRenderVertices[v+0], 255, 255, 255, alpha);\n\t\t\t\tRwIm3DVertexSetRGBA(&TempBufferRenderVertices[v+1], 255, 255, 255, alpha);\n\t\t\t\tRwIm3DVertexSetRGBA(&TempBufferRenderVertices[v+2], 255, 255, 255, alpha);\n\t\t\t\tRwIm3DVertexSetRGBA(&TempBufferRenderVertices[v+3], 255, 255, 255, alpha);\n\t\t\t\tRwIm3DVertexSetU(&TempBufferRenderVertices[v+0], 0.0f);\n\t\t\t\tRwIm3DVertexSetV(&TempBufferRenderVertices[v+0], 0.0f);\n\t\t\t\tRwIm3DVertexSetU(&TempBufferRenderVertices[v+1], 1.0f);\n\t\t\t\tRwIm3DVertexSetV(&TempBufferRenderVertices[v+1], 0.0f);\n\t\t\t\tRwIm3DVertexSetU(&TempBufferRenderVertices[v+2], 0.0f);\n\t\t\t\tRwIm3DVertexSetV(&TempBufferRenderVertices[v+2], 1.0f);\n\t\t\t\tRwIm3DVertexSetU(&TempBufferRenderVertices[v+3], 1.0f);\n\t\t\t\tRwIm3DVertexSetV(&TempBufferRenderVertices[v+3], 1.0f);\n\n\t\t\t\tint i = TempBufferIndicesStored;\n\t\t\t\tTempBufferRenderIndexList[i+0] = RubbishIndexList[0] + TempBufferVerticesStored;\n\t\t\t\tTempBufferRenderIndexList[i+1] = RubbishIndexList[1] + TempBufferVerticesStored;\n\t\t\t\tTempBufferRenderIndexList[i+2] = RubbishIndexList[2] + TempBufferVerticesStored;\n\t\t\t\tTempBufferRenderIndexList[i+3] = RubbishIndexList[3] + TempBufferVerticesStored;\n\t\t\t\tTempBufferRenderIndexList[i+4] = RubbishIndexList[4] + TempBufferVerticesStored;\n\t\t\t\tTempBufferRenderIndexList[i+5] = RubbishIndexList[5] + TempBufferVerticesStored;\n\t\t\t\tTempBufferVerticesStored += 4;\n\t\t\t\tTempBufferIndicesStored += 6;\n\t\t\t}\n\t\t}\n\n\t\tif(TempBufferIndicesStored != 0){\n\t\t\tLittleTest();\n\t\t\tif(RwIm3DTransform(TempBufferRenderVertices, TempBufferVerticesStored, nil, rwIM3D_VERTEXUV)){\n\t\t\t\tRwIm3DRenderIndexedPrimitive(rwPRIMTYPETRILIST, TempBufferRenderIndexList, TempBufferIndicesStored);\n\t\t\t\tRwIm3DEnd();\n\t\t\t}\n\t\t}\n\t}\n\n\tRwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE);\n\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);\n\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);\n\n\tPOP_RENDERGROUP();\n}\n\nvoid\nCRubbish::StirUp(CVehicle *veh)\n{\n\tif((CTimer::GetFrameCounter() ^ (veh->m_randomSeed&3)) == 0)\n\t\treturn;\n\n\tif(Abs(veh->GetPosition().x - TheCamera.GetPosition().x) < 20.0f &&\n\t   Abs(veh->GetPosition().y - TheCamera.GetPosition().y) < 20.0f)\n\t\tif(Abs(veh->GetMoveSpeed().x) > 0.05f || Abs(veh->GetMoveSpeed().y) > 0.05f){\n\t\t\tfloat speed = veh->GetMoveSpeed().Magnitude2D();\n\t\t\tif(speed > 0.05f){\n\t\t\t\tbool movingForward = DotProduct2D(veh->GetMoveSpeed(), veh->GetForward()) > 0.0f;\n\t\t\t\tCOneSheet *sheet = StartStaticsList.m_next;\n\t\t\t\tCVector2D size = veh->GetColModel()->boundingBox.max;\n\n\t\t\t\t// Check all static sheets\n\t\t\t\twhile(sheet != &EndStaticsList){\n\t\t\t\t\tCOneSheet *next = sheet->m_next;\n\t\t\t\t\tCVector2D carToSheet = sheet->m_basePos - veh->GetPosition();\n\t\t\t\t\tfloat distFwd = DotProduct2D(carToSheet, veh->GetForward());\n\n\t\t\t\t\t// sheet has to be a bit behind car\n\t\t\t\t\tif(movingForward && distFwd < -0.5f*size.y && distFwd > -1.5f*size.y ||\n\t\t\t\t\t   !movingForward && distFwd > 0.5f*size.y && distFwd < 1.5f*size.y){\n\t\t\t\t\t\tfloat distSide = Abs(DotProduct2D(carToSheet, veh->GetRight()));\n\t\t\t\t\t\tif(distSide < 1.5*size.x){\n\t\t\t\t\t\t\t// Check with higher speed for sheet directly behind car\n\t\t\t\t\t\t\tfloat speedToCheck = distSide < size.x ? speed : speed*0.5f;\n\t\t\t\t\t\t\tif(speedToCheck > 0.05f){\n\t\t\t\t\t\t\t\tsheet->m_state = 2;\n\t\t\t\t\t\t\t\tif(speedToCheck > 0.15f)\n\t\t\t\t\t\t\t\t\tsheet->m_animationType = 2;\n\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\tsheet->m_animationType = 1;\n\t\t\t\t\t\t\t\tsheet->m_moveDuration = 2000;\n\t\t\t\t\t\t\t\tsheet->m_xDist = veh->GetMoveSpeed().x;\n\t\t\t\t\t\t\t\tsheet->m_yDist = veh->GetMoveSpeed().y;\n\t\t\t\t\t\t\t\tfloat dist = Sqrt(SQR(sheet->m_xDist)+SQR(sheet->m_yDist));\n\t\t\t\t\t\t\t\tsheet->m_xDist *= 25.0f*speed/dist;\n\t\t\t\t\t\t\t\tsheet->m_yDist *= 25.0f*speed/dist;\n\t\t\t\t\t\t\t\tsheet->m_animHeight = 3.0f*speed;\n\t\t\t\t\t\t\t\tsheet->m_moveStart = CTimer::GetTimeInMilliseconds();\n\t\t\t\t\t\t\t\tfloat tx = sheet->m_basePos.x + sheet->m_xDist;\n\t\t\t\t\t\t\t\tfloat ty = sheet->m_basePos.y + sheet->m_yDist;\n\t\t\t\t\t\t\t\tfloat tz = sheet->m_basePos.z + 3.0f;\n\t\t\t\t\t\t\t\tsheet->m_targetZ = CWorld::FindGroundZFor3DCoord(tx, ty, tz, nil) + 0.1f;\n\t\t\t\t\t\t\t\tsheet->RemoveFromList();\n\t\t\t\t\t\t\t\tsheet->AddToList(&StartMoversList);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tsheet = next;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n}\n\nstatic float aAnimations[3][34] = {\n\t{ 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,\n\t  0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f },\n\n\t// Normal move\n\t{ 0.0f, 0.05f, 0.12f, 0.25f, 0.42f, 0.57f, 0.68f, 0.8f, 0.86f, 0.9f, 0.93f, 0.95f, 0.96f, 0.97f, 0.98f, 0.99f, 1.0f,\t// XY movemnt\n\t  0.15f, 0.35f, 0.6f, 0.9f, 1.2f, 1.25f, 1.3f, 1.2f, 1.1f, 0.95f, 0.8f, 0.6f, 0.45f, 0.3f, 0.2f, 0.1f, 0 },\t// Z movement\n\n\t// Stirred up by fast vehicle\n\t{ 0.0f, 0.05f, 0.12f, 0.25f, 0.42f, 0.57f, 0.68f, 0.8f, 0.95f, 1.1f, 1.15f, 1.18f, 1.15f, 1.1f, 1.05f, 1.03f, 1.0f,\n\t  0.15f, 0.35f, 0.6f, 0.9f, 1.2f, 1.25f, 1.3f, 1.2f, 1.1f, 0.95f, 0.8f, 0.6f, 0.45f, 0.3f, 0.2f, 0.1f, 0 }\n};\n\nvoid\nCRubbish::Update(void)\n{\n\tbool foundGround;\n\n\t// FRAMETIME\n\tif(bRubbishInvisible)\n\t\tRubbishVisibility = Max(RubbishVisibility-5, 0);\n\telse\n\t\tRubbishVisibility = Min(RubbishVisibility+5, 255);\n\n\t// Spawn a new sheet\n\tCOneSheet *sheet = StartEmptyList.m_next;\n\tif(sheet != &EndEmptyList){\n\t\tfloat spawnDist;\n\t\tfloat spawnAngle;\n\n\t\tspawnDist = (CGeneral::GetRandomNumber()&0xFF)/256.0f + RUBBISH_MAX_DIST;\n\t\tuint8 r = CGeneral::GetRandomNumber();\n\t\tif(r&1)\n\t\t\tspawnAngle = (CGeneral::GetRandomNumber()&0xFF)/256.0f * 6.28f;\n\t\telse\n\t\t\tspawnAngle = (r-128)/160.0f + TheCamera.Orientation;\n\t\tsheet->m_basePos.x = TheCamera.GetPosition().x + spawnDist*Sin(spawnAngle);\n\t\tsheet->m_basePos.y = TheCamera.GetPosition().y + spawnDist*Cos(spawnAngle);\n\t\tsheet->m_basePos.z = CWorld::FindGroundZFor3DCoord(sheet->m_basePos.x, sheet->m_basePos.y, TheCamera.GetPosition().z, &foundGround) + 0.1f;\n\t\tif(foundGround){\n\t\t\t// Found ground, so add to statics list\n\t\t\tsheet->m_angle = (CGeneral::GetRandomNumber()&0xFF)/256.0f * 6.28f;\n\t\t\tsheet->m_state = 1;\n\t\t\tif(CCullZones::FindAttributesForCoors(sheet->m_basePos, nil) & ATTRZONE_NORAIN)\n\t\t\t\tsheet->m_isVisible = false;\n\t\t\telse\n\t\t\t\tsheet->m_isVisible = true;\n\t\t\tsheet->RemoveFromList();\n\t\t\tsheet->AddToList(&StartStaticsList);\n\t\t}\n\t}\n\n\t// Process animation\n\tsheet = StartMoversList.m_next;\n\twhile(sheet != &EndMoversList){\n\t\tuint32 currentTime = CTimer::GetTimeInMilliseconds() - sheet->m_moveStart;\n\t\tif(currentTime < sheet->m_moveDuration){\n\t\t\t// Animation\n\t\t\tint step = 16 * currentTime / sheet->m_moveDuration;\t// 16 steps in animation\n\t\t\tint stepTime = sheet->m_moveDuration/16;\t// time in each step\n\t\t\tfloat s = (float)(currentTime - stepTime*step) / stepTime;\t// position on step\n\t\t\tfloat t = (float)currentTime / sheet->m_moveDuration;\t// position on total animation\n\t\t\t// factors for xy and z-movment\n\t\t\tfloat fxy = aAnimations[sheet->m_animationType][step]*(1.0f-s) + aAnimations[sheet->m_animationType][step+1]*s;\n\t\t\tfloat fz = aAnimations[sheet->m_animationType][step+17]*(1.0f-s) + aAnimations[sheet->m_animationType][step+1+17]*s;\n\t\t\tsheet->m_animatedPos.x = sheet->m_basePos.x + fxy*sheet->m_xDist;\n\t\t\tsheet->m_animatedPos.y = sheet->m_basePos.y + fxy*sheet->m_yDist;\n\t\t\tsheet->m_animatedPos.z = (1.0f-t)*sheet->m_basePos.z + t*sheet->m_targetZ + fz*sheet->m_animHeight;\n\t\t\tsheet->m_angle += CTimer::GetTimeStep()*0.04f;\n\t\t\tif(sheet->m_angle > 6.28f)\n\t\t\t\tsheet->m_angle -= 6.28f;\n\t\t\tsheet = sheet->m_next;\n\t\t}else{\n\t\t\t// End of animation, back into statics list\n\t\t\tsheet->m_basePos.x += sheet->m_xDist;\n\t\t\tsheet->m_basePos.y += sheet->m_yDist;\n\t\t\tsheet->m_basePos.z = sheet->m_targetZ;\n\t\t\tsheet->m_state = 1;\n\t\t\tsheet->m_isVisible = sheet->m_targetIsVisible;\n\n\t\t\tCOneSheet *next = sheet->m_next;\n\t\t\tsheet->RemoveFromList();\n\t\t\tsheet->AddToList(&StartStaticsList);\n\t\t\tsheet = next;\n\t\t}\n\t}\n\n\t// Stir up a sheet by wind\n\t// FRAMETIME\n\tint freq;\n\tif(CWeather::Wind < 0.1f)\n\t\tfreq = 31;\n\telse if(CWeather::Wind < 0.4f)\n\t\tfreq = 7;\n\telse if(CWeather::Wind < 0.7f)\n\t\tfreq = 1;\n\telse\n\t\tfreq = 0;\n\tif((CTimer::GetFrameCounter() & freq) == 0){\n\t\t// Pick a random sheet and set animation state if static\n\t\tint i = CGeneral::GetRandomNumber() % NUM_RUBBISH_SHEETS;\n\t\tif(aSheets[i].m_state == 1){\n\t\t\taSheets[i].m_moveStart = CTimer::GetTimeInMilliseconds();\n\t\t\taSheets[i].m_moveDuration = CWeather::Wind*1500.0f + 1000.0f;\n\t\t\taSheets[i].m_animHeight = 0.2f;\n\t\t\taSheets[i].m_xDist = 3.0f*CWeather::Wind;\n\t\t\taSheets[i].m_yDist = 3.0f*CWeather::Wind;\n\t\t\t// Check if target position is ok\n\t\t\tfloat tx = aSheets[i].m_basePos.x + aSheets[i].m_xDist;\n\t\t\tfloat ty = aSheets[i].m_basePos.y + aSheets[i].m_yDist;\n\t\t\tfloat tz = aSheets[i].m_basePos.z + 3.0f;\n\t\t\taSheets[i].m_targetZ = CWorld::FindGroundZFor3DCoord(tx, ty, tz, &foundGround) + 0.1f;\n\t\t\tif(CCullZones::FindAttributesForCoors(CVector(tx, ty, aSheets[i].m_targetZ), nil) & ATTRZONE_NORAIN)\n\t\t\t\taSheets[i].m_targetIsVisible = false;\n\t\t\telse\n\t\t\t\taSheets[i].m_targetIsVisible = true;\n\t\t\tif(foundGround){\n\t\t\t\t// start animation\n\t\t\t\taSheets[i].m_state = 2;\n\t\t\t\taSheets[i].m_animationType = 1;\n\t\t\t\taSheets[i].RemoveFromList();\n\t\t\t\taSheets[i].AddToList(&StartMoversList);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Remove sheets that are too far away\n\tint i = (CTimer::GetFrameCounter()%(NUM_RUBBISH_SHEETS/4))*4;\n\tint last = ((CTimer::GetFrameCounter()%(NUM_RUBBISH_SHEETS/4)) + 1)*4;\n\tfor(; i < last; i++){\n\t\tif(aSheets[i].m_state == 1 &&\n\t\t   (aSheets[i].m_basePos - TheCamera.GetPosition()).MagnitudeSqr2D() > SQR(RUBBISH_MAX_DIST+1.0f)){\n\t\t\taSheets[i].m_state = 0;\n\t\t\taSheets[i].RemoveFromList();\n\t\t\taSheets[i].AddToList(&StartEmptyList);\n\t\t}\n\t}\n}\n\nvoid\nCRubbish::SetVisibility(bool visible)\n{\n\tbRubbishInvisible = !visible;\n}\n\nvoid\nCRubbish::Init(void)\n{\n\tint i;\n\tfor(i = 0; i < NUM_RUBBISH_SHEETS; i++){\n\t\taSheets[i].m_state = 0;\n\t\tif(i < NUM_RUBBISH_SHEETS-1)\n\t\t\taSheets[i].m_next = &aSheets[i+1];\n\t\telse\n\t\t\taSheets[i].m_next = &EndEmptyList;\n\t\tif(i > 0)\n\t\t\taSheets[i].m_prev = &aSheets[i-1];\n\t\telse\n\t\t\taSheets[i].m_prev = &StartEmptyList;\n\t}\n\n\tStartEmptyList.m_next = &aSheets[0];\n\tStartEmptyList.m_prev = nil;\n\tEndEmptyList.m_next = nil;\n\tEndEmptyList.m_prev = &aSheets[NUM_RUBBISH_SHEETS-1];\n\n\tStartStaticsList.m_next = &EndStaticsList;\n\tStartStaticsList.m_prev = nil;\n\tEndStaticsList.m_next = nil;\n\tEndStaticsList.m_prev = &StartStaticsList;\n\n\tStartMoversList.m_next = &EndMoversList;\n\tStartMoversList.m_prev = nil;\n\tEndMoversList.m_next = nil;\n\tEndMoversList.m_prev = &StartMoversList;\n\n\tRubbishIndexList[0] = 0;\n\tRubbishIndexList[1] = 1;\n\tRubbishIndexList[2] = 2;\n\tRubbishIndexList[3] = 1;\n\tRubbishIndexList[4] = 3;\n\tRubbishIndexList[5] = 2;\n\n\tCTxdStore::PushCurrentTxd();\n\tint slot = CTxdStore::FindTxdSlot(\"particle\");\n\tCTxdStore::SetCurrentTxd(slot);\n\tgpRubbishTexture[0] = RwTextureRead(\"gameleaf01_64\", nil);\n\tgpRubbishTexture[1] = RwTextureRead(\"gameleaf02_64\", nil);\n\tgpRubbishTexture[2] = RwTextureRead(\"newspaper01_64\", nil);\n\tgpRubbishTexture[3] = RwTextureRead(\"newspaper02_64\", nil);\n\tCTxdStore::PopCurrentTxd();\n\tRubbishVisibility = 255;\n\tbRubbishInvisible = false;\n}\n\nvoid\nCRubbish::Shutdown(void)\n{\n\tRwTextureDestroy(gpRubbishTexture[0]);\n\tgpRubbishTexture[0] = nil;\n\tRwTextureDestroy(gpRubbishTexture[1]);\n\tgpRubbishTexture[1] = nil;\n\tRwTextureDestroy(gpRubbishTexture[2]);\n\tgpRubbishTexture[2] = nil;\n\tRwTextureDestroy(gpRubbishTexture[3]);\n\tgpRubbishTexture[3] = nil;\n}\n"
  },
  {
    "path": "src/render/Rubbish.h",
    "content": "#pragma once\n\nclass CVehicle;\n\nenum {\n\t// NB: not all values are allowed, check the code\n#ifdef SQUEEZE_PERFORMANCE\n\tNUM_RUBBISH_SHEETS = 32\n#else\n\tNUM_RUBBISH_SHEETS = 64\n#endif\n};\n\nclass COneSheet\n{\npublic:\n\tCVector m_basePos;\n\tCVector m_animatedPos;\n\tfloat m_targetZ;\n\tint8 m_state;\n\tint8 m_animationType;\n\tuint32 m_moveStart;\n\tuint32 m_moveDuration;\n\tfloat m_animHeight;\n\tfloat m_xDist;\n\tfloat m_yDist;\n\tfloat m_angle;\n\tbool m_isVisible;\n\tbool m_targetIsVisible;\n\tCOneSheet *m_next;\n\tCOneSheet *m_prev;\n\n\tvoid AddToList(COneSheet *list);\n\tvoid RemoveFromList(void);\n};\n\nclass CRubbish\n{\n\tstatic bool bRubbishInvisible;\n\tstatic int RubbishVisibility;\n\tstatic COneSheet aSheets[NUM_RUBBISH_SHEETS];\n\tstatic COneSheet StartEmptyList;\n\tstatic COneSheet EndEmptyList;\n\tstatic COneSheet StartStaticsList;\n\tstatic COneSheet EndStaticsList;\n\tstatic COneSheet StartMoversList;\n\tstatic COneSheet EndMoversList;\npublic:\n\tstatic void Render(void);\n\tstatic void StirUp(CVehicle *veh);\t// CAutomobile on PS2\n\tstatic void Update(void);\n\tstatic void SetVisibility(bool visible);\n\tstatic void Init(void);\n\tstatic void Shutdown(void);\n};\n\nextern RwTexture *gpRubbishTexture[4];\n"
  },
  {
    "path": "src/render/ShadowCamera.cpp",
    "content": "#include \"common.h\"\n#include \"rwcore.h\"\n#include \"ShadowCamera.h\"\n#include \"RwHelper.h\"\n\n#define TEXELOFFSET 0.5f\n\nRpAtomic *ShadowRenderCallBack(RpAtomic *atomic, void *data)\n{\n\tRpAtomicCallBackRender savedCB = RpAtomicGetRenderCallBack(atomic);\n\tRpAtomicSetRenderCallBack(atomic, AtomicDefaultRenderCallBack);\n\tRpAtomicRender(atomic);\n\tRpAtomicSetRenderCallBack(atomic, savedCB);\t\n\treturn atomic;\n}\n\nCShadowCamera::CShadowCamera()\n{\n\tm_pCamera  = nil;\n\tm_pTexture = nil;\n}\n\nCShadowCamera::~CShadowCamera()\n{\n\tDestroy();\n}\n\nvoid\nCShadowCamera::Destroy()\n{\n\tif ( m_pCamera )\n\t{\n\t\tRwRaster\t\t   *raster;\n\t\tRwFrame\t\t\t   *frame;\n\t\n\t\tframe = RwCameraGetFrame(m_pCamera);\n\t\n\t\tif ( frame )\n\t\t{\n\t\t\tRwCameraSetFrame(m_pCamera, nil);\n\t\t\tRwFrameDestroy(frame);\n\t\t}\n\t\n\t\traster = RwCameraGetZRaster(m_pCamera);\n\t\tif ( raster )\n\t\t{\n\t\t\tRwCameraSetZRaster(m_pCamera, nil);\n\t\t\tRwRasterDestroy(raster);\n\t\t}\n\n\t\traster = RwCameraGetRaster(m_pCamera);\n\t\tif ( raster )\n\t\t{\n\t\t\tRwCameraSetRaster(m_pCamera, nil);\n\t\t\tRwRasterDestroy(raster);\n\t\t}\n\t\t\n\t\tif ( m_pTexture )\n\t\t{\n\t\t\tRwTextureSetRaster(m_pTexture, nil);\n\t\t\tRwTextureDestroy(m_pTexture);\n\t\t\tm_pTexture = nil;\n\t\t}\n\t\t\n\t\tRwCameraDestroy(m_pCamera);\n\t\tm_pCamera = nil;\n\t}\n    return;\n}\n\nRwCamera *\nCShadowCamera::Create(int32 rasterSize)\n{\n\tint32 size = 1 << rasterSize;\n\t\n\tm_pCamera = RwCameraCreate();\n\tASSERT(m_pCamera != nil);\n\t\n\tif ( m_pCamera )\n\t{\n\t\tRwCameraSetFrame(m_pCamera, RwFrameCreate());\n\n\t\tif( RwCameraGetFrame(m_pCamera) )\n\t\t{\n\t\t\tRwRaster *zRaster = RwRasterCreate(size, size, 0, rwRASTERTYPEZBUFFER);\n\t\t\tASSERT(zRaster != nil);\n\t\t\t\n\t\t\tif ( zRaster )\n\t\t\t{\n\t\t\t\tRwCameraSetZRaster(m_pCamera, zRaster);\n\n\t\t\t\tRwRaster *raster = RwRasterCreate(size, size, 0, rwRASTERTYPECAMERATEXTURE);\n\t\t\t\tASSERT(raster != nil);\n\n\t\t\t\tif ( raster )\n\t\t\t\t{\n\t\t\t\t\tRwCameraSetRaster(m_pCamera, raster);\n\t\t\t\t\tm_pTexture = RwTextureCreate(raster);\n\t\t\t\t\tASSERT(m_pTexture != nil);\n\t\t\t\t\t\n\t\t\t\t\tif ( m_pTexture )\n\t\t\t\t\t{\n\t\t\t\t\t\tRwTextureSetAddressing(m_pTexture, rwTEXTUREADDRESSCLAMP);\n\t\t\t\t\t\tRwTextureSetFilterMode(m_pTexture, rwFILTERLINEAR);\n\t\t\t\t\t\tRwCameraSetProjection(m_pCamera,   rwPARALLEL);\n\t\t\t\t\t\treturn (m_pCamera);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tDestroy();\n\n\treturn (nil);\n}\n\nRwCamera *\nCShadowCamera::SetFrustum(float objectRadius)\n{\n\tASSERT(m_pCamera != nil);\n\t\n\tRwV2d vw;\n\n\tRwCameraSetFarClipPlane (m_pCamera, 2.0f   * objectRadius);\n\tRwCameraSetNearClipPlane(m_pCamera, 0.001f * objectRadius);\n\n\tvw.x = objectRadius;\n\tvw.y = objectRadius;\n\tRwCameraSetViewWindow(m_pCamera, &vw);\n\n\treturn m_pCamera;\n}\n\nRwCamera *\nCShadowCamera::SetLight(RpLight *light)\n{\n\tASSERT(light != nil);\n\tASSERT(m_pCamera != nil);\n\t\n\tRwFrame  *camFrame = RwCameraGetFrame(m_pCamera);\n\tRwMatrix *camMatrix = RwFrameGetMatrix(camFrame);\n\tRwFrame  *lightFrame = RpLightGetFrame(light);\n\tRwMatrix *lightMatrix = RwFrameGetMatrix(lightFrame);\n\n\t*RwMatrixGetRight(camMatrix) = *RwMatrixGetRight(lightMatrix);\n\t*RwMatrixGetUp(camMatrix)    = *RwMatrixGetUp(lightMatrix);\n\t*RwMatrixGetAt(camMatrix)    = *RwMatrixGetAt(lightMatrix);\n\t\n\tRwMatrixUpdate(camMatrix);\n\tRwFrameUpdateObjects(camFrame);\n\n\treturn m_pCamera;\n}\n\nRwCamera *\nCShadowCamera::SetCenter(RwV3d *center)\n{\n\tASSERT(center != nil);\n\tASSERT(m_pCamera != nil);\n\t\n\tRwFrame            *camFrame = RwCameraGetFrame(m_pCamera);\n\tRwMatrix           *camMatrix = RwFrameGetMatrix(camFrame);\n\t\n\t*RwMatrixGetPos(camMatrix) = *center;\n\t\n\tRwV3dIncrementScaled(RwMatrixGetPos(camMatrix), RwMatrixGetAt(camMatrix), -0.5f * RwCameraGetFarClipPlane(m_pCamera));  \n\n\tRwMatrixUpdate(camMatrix);\n\tRwFrameUpdateObjects(camFrame);\n\tRwFrameOrthoNormalize(camFrame);\n\n\treturn m_pCamera;\n}\n\nRwCamera *\nCShadowCamera::Update(RpClump *clump)\n{\n\tASSERT(clump != nil);\n\tASSERT(m_pCamera != nil);\n\t\n\tRwUInt32 flags;\n\tRpGeometry *geometry;\n\t\n\tRwRGBA              bgColor = { 255, 255, 255, 0 };\n\t\n\tRwCameraClear(m_pCamera, &bgColor, rwCAMERACLEARZ | rwCAMERACLEARIMAGE);\n\n\tif ( RwCameraBeginUpdate(m_pCamera) )\n\t{\n\t\tgeometry = RpAtomicGetGeometry(GetFirstAtomic(clump));\n\t\tASSERT(geometry != nil);\n\t\t\n\t\tflags = RpGeometryGetFlags(geometry);\n\n\t\tRpGeometrySetFlags(geometry, flags & ~(rpGEOMETRYPRELIT|rpGEOMETRYLIGHT\n\t\t\t\t|rpGEOMETRYTEXTURED|rpGEOMETRYTEXTURED2|rpGEOMETRYMODULATEMATERIALCOLOR));\n\t\t\n\t\tRpClumpForAllAtomics(clump, ShadowRenderCallBack, nil);\t\t\t\t\n\t\t\n\t\tRpGeometrySetFlags(geometry, flags);\n\t\t\n\t\tInvertRaster();\n\t\tRwCameraEndUpdate(m_pCamera);\n\t}\n\t\n\treturn m_pCamera;\n}\n\nRwCamera *\nCShadowCamera::Update(RpAtomic *atomic)\n{\n\tASSERT(atomic != nil);\n\tASSERT(m_pCamera != nil);\n\t\n\tRwUInt32 flags;\n\tRpGeometry *geometry;\n\n\tRwRGBA              bgColor = { 255, 255, 255, 0 };\n\n\tRwCameraClear(m_pCamera, &bgColor, rwCAMERACLEARZ | rwCAMERACLEARIMAGE);\n  \n\tif ( RwCameraBeginUpdate(m_pCamera) )\n\t{\n\t\tgeometry = RpAtomicGetGeometry(atomic);\t\n\t\tASSERT(geometry != nil);\n\t\tflags = RpGeometryGetFlags(geometry);\n\t\t\n\t\tRpGeometrySetFlags(geometry, flags & ~(rpGEOMETRYPRELIT|rpGEOMETRYLIGHT\n\t\t\t\t|rpGEOMETRYTEXTURED|rpGEOMETRYTEXTURED2|rpGEOMETRYMODULATEMATERIALCOLOR|rpGEOMETRYNORMALS));\n\t\t\n\t\tShadowRenderCallBack(atomic, nil);\n\t\t\n\t\tRpGeometrySetFlags(geometry, flags);\n\n\t\tInvertRaster();\n\t\tRwCameraEndUpdate(m_pCamera);\n\t}\n\t\n\treturn m_pCamera;\n}\n\nvoid\nCShadowCamera::InvertRaster()\n{\n\tASSERT(m_pCamera != nil);\n\t\n\tRwIm2DVertex vx[4];\n\tfloat crw, crh;\n\tRwRaster *raster;\n\tfloat recipZ;\n  \n\traster = RwCameraGetRaster(m_pCamera);\n\tASSERT(raster != nil);\n\t\n\tcrw = (float)RwRasterGetWidth(raster);\n\tcrh = (float)RwRasterGetHeight(raster);\n\n\trecipZ = 1.0f / RwCameraGetNearClipPlane(m_pCamera);\n\n\tRwIm2DVertexSetScreenX     (&vx[0], 0.0f);\n\tRwIm2DVertexSetScreenY     (&vx[0], 0.0f);\n\tRwIm2DVertexSetScreenZ     (&vx[0], RwIm2DGetNearScreenZ());\n\tRwIm2DVertexSetRecipCameraZ(&vx[0], recipZ);\n\tRwIm2DVertexSetIntRGBA     (&vx[0], 255, 255, 255, 255);\n\n\tRwIm2DVertexSetScreenX     (&vx[1], 0.0f);\n\tRwIm2DVertexSetScreenY     (&vx[1], crh);\n\tRwIm2DVertexSetScreenZ     (&vx[1], RwIm2DGetNearScreenZ());\n\tRwIm2DVertexSetRecipCameraZ(&vx[1], recipZ);\n\tRwIm2DVertexSetIntRGBA     (&vx[1], 255, 255, 255, 255);\n\n\tRwIm2DVertexSetScreenX     (&vx[2], crw);\n\tRwIm2DVertexSetScreenY     (&vx[2], 0.0f);\n\tRwIm2DVertexSetScreenZ     (&vx[2], RwIm2DGetNearScreenZ());\n\tRwIm2DVertexSetRecipCameraZ(&vx[2], recipZ);\n\tRwIm2DVertexSetIntRGBA     (&vx[2], 255, 255, 255, 255);\n\n\tRwIm2DVertexSetScreenX     (&vx[3], crw);\n\tRwIm2DVertexSetScreenY     (&vx[3], crh);\n\tRwIm2DVertexSetScreenZ     (&vx[3], RwIm2DGetNearScreenZ());\n\tRwIm2DVertexSetRecipCameraZ(&vx[3], recipZ);\n\tRwIm2DVertexSetIntRGBA     (&vx[3], 255, 255, 255, 255);\n\n\n\tRwRenderStateSet(rwRENDERSTATEZTESTENABLE,       (void *)FALSE);\n\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER,     (void *)nil);\n\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)TRUE);\n\tRwRenderStateSet(rwRENDERSTATESRCBLEND,          (void *)rwBLENDINVDESTCOLOR);\n\tRwRenderStateSet(rwRENDERSTATEDESTBLEND,         (void *)rwBLENDZERO);\n\n\tRwIm2DRenderPrimitive(rwPRIMTYPETRISTRIP, vx, 4);\n\n\tRwRenderStateSet(rwRENDERSTATEZTESTENABLE,       (void *)TRUE);\n\tRwRenderStateSet(rwRENDERSTATESRCBLEND,          (void *)rwBLENDSRCALPHA);\n\tRwRenderStateSet(rwRENDERSTATEDESTBLEND,         (void *)rwBLENDINVSRCALPHA);\n}\n\nRwRaster *\nCShadowCamera::MakeGradientRaster()\n{\n\tASSERT(m_pCamera != nil);\n\t\n\tRwIm2DVertex vx[2];\n\n\tif ( !m_pCamera )\n\t\treturn nil;\n\n\tfloat recipCamZ = 1.0f / RwCameraGetNearClipPlane(m_pCamera);\n\n\tRwRaster *raster = RwCameraGetRaster(m_pCamera);\n\tASSERT(raster != nil);\n\t\n\tfloat width = (float)RwRasterGetWidth(raster);\n\tfloat height = (float)RwRasterGetHeight(raster);\n\n\tif ( height < 1 )\n\t\treturn nil;\n      \n\tif ( RwCameraBeginUpdate(m_pCamera) )\n\t{\n\t\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER,     (void *)rwFILTERNAFILTERMODE);\n\t\tRwRenderStateSet(rwRENDERSTATEZTESTENABLE,       (void *)FALSE);\n\t\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)FALSE);\n\t\tRwRenderStateSet(rwRENDERSTATEDESTBLEND,         (void *)rwBLENDZERO);\n\t\tRwRenderStateSet(rwRENDERSTATESRCBLEND,          (void *)rwBLENDINVDESTCOLOR);\n\t\tRwRenderStateSet(rwRENDERSTATESHADEMODE,         (void *)rwSHADEMODEFLAT);\n\n\t\tfloat color = 255.0f;\n\t\tfloat step = (-191.0f / height);\n\n\t\tfor ( int32 i = 0; i < height; i++ )\n\t\t{\n\t\t\tRwIm2DVertexSetScreenX     (&vx[0], 0.0f);\n\t\t\tRwIm2DVertexSetScreenY     (&vx[0], i);\n\t\t\tRwIm2DVertexSetScreenZ     (&vx[0], RwIm2DGetNearScreenZ());\n\t\t\tRwIm2DVertexSetRecipCameraZ(&vx[0], recipCamZ);\n\t\t\tRwIm2DVertexSetIntRGBA     (&vx[0], (uint32)color, (uint32)color, (uint32)color, (uint32)color);\n\t\t\t\n\t\t\tRwIm2DVertexSetScreenX     (&vx[1], width - 1);\n\t\t\tRwIm2DVertexSetScreenY     (&vx[1], i);\n\t\t\tRwIm2DVertexSetScreenZ     (&vx[1], RwIm2DGetNearScreenZ());\n\t\t\tRwIm2DVertexSetRecipCameraZ(&vx[1], recipCamZ);\n\t\t\tRwIm2DVertexSetIntRGBA     (&vx[1], (uint32)color, (uint32)color, (uint32)color, (uint32)color);\n\t\t\t\n\t\t\tRwIm2DRenderLine(vx, 2, 0, 1);\n\t\t\t\n\t\t\tcolor += step;\n\t\t}\n\t\t\n\t\tRwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)TRUE);\n\t\tRwRenderStateSet(rwRENDERSTATEDESTBLEND,   (void *)rwBLENDINVSRCALPHA);\n\t\tRwRenderStateSet(rwRENDERSTATESRCBLEND,    (void *)rwBLENDSRCALPHA);\n\t\tRwRenderStateSet(rwRENDERSTATESHADEMODE,   (void *)rwSHADEMODEGOURAUD);\n\t\t\n\t\tRwCameraEndUpdate(m_pCamera);\n\t}\n\t\n\treturn raster;\n}\n\nRwRaster *\nCShadowCamera::RasterResample(RwRaster *dstRaster)\n{\n\tASSERT(dstRaster != nil);\n\tASSERT(m_pCamera != nil);\n\t\n\tif ( !m_pCamera )\n\t\treturn nil;\n\n\tRwRaster *raster = RwCameraGetRaster(m_pCamera);\n\tASSERT(raster != nil);\n\t\n\tfloat size = (float) RwRasterGetWidth(raster);\n\tfloat uvOffset = TEXELOFFSET / size;\n\tfloat recipCamZ = 1.0f / RwCameraGetNearClipPlane(m_pCamera);\n\n\tif ( RwCameraBeginUpdate(m_pCamera) )\n\t{\n\t\tRwRenderStateSet(rwRENDERSTATESRCBLEND,      (void *)rwBLENDONE);\n\t\tRwRenderStateSet(rwRENDERSTATEDESTBLEND,     (void *)rwBLENDZERO);\n\t\tRwRenderStateSet(rwRENDERSTATEZTESTENABLE,   (void *)FALSE);\n\t\tRwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void *)rwFILTERLINEAR);\n\t\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void *)dstRaster);\n\n\t\tIm2DRenderQuad(0.0f, 0.0f, size, size, RwIm2DGetNearScreenZ(), recipCamZ, uvOffset);\n    \n\t\tRwRenderStateSet(rwRENDERSTATEZTESTENABLE,   (void *)TRUE);\n\t\tRwRenderStateSet(rwRENDERSTATESRCBLEND,      (void *)rwBLENDSRCALPHA);\n\t\tRwRenderStateSet(rwRENDERSTATEDESTBLEND,     (void *)rwBLENDINVSRCALPHA);\n\t\t\n\t\tRwCameraEndUpdate(m_pCamera);\n\t}\n\t\n\treturn raster;\n}\n\nRwRaster *\nCShadowCamera::RasterBlur(RwRaster *dstRaster, int32 numPasses)\n{\n\tASSERT(dstRaster != nil);\n\tASSERT(m_pCamera != nil);\n\t\n\tif ( !m_pCamera )\n\t\treturn nil;\n\n\tRwRaster *raster = RwCameraGetRaster(m_pCamera);\n\tASSERT(raster != nil);\n\t\n\tfloat size = (float) RwRasterGetWidth(dstRaster);\n\tfloat recipCamZ = 1.0f / RwCameraGetNearClipPlane(m_pCamera);\n\n\tfor (int i = 0; i < numPasses; i++ )\n\t{\n\t\tRwCameraSetRaster(m_pCamera, raster);\n\t\t\n\t\tif ( RwCameraBeginUpdate(m_pCamera) )\n\t\t{\n\t\t\tif ( i == 0 )\n\t\t\t{\n\t\t\t\tRwRenderStateSet(rwRENDERSTATESRCBLEND,      (void *)rwBLENDONE);\n\t\t\t\tRwRenderStateSet(rwRENDERSTATEDESTBLEND,     (void *)rwBLENDZERO);\n\t\t\t\tRwRenderStateSet(rwRENDERSTATEZTESTENABLE,   (void *)FALSE);\n\t\t\t\tRwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void *)rwFILTERLINEAR);\n\t\t\t}\n\t\t\t\n\t\t\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER,     (void *)dstRaster);\n\t\t\tIm2DRenderQuad(0.0f, 0.0f, size, size, RwIm2DGetNearScreenZ(), recipCamZ, 1.0f / size);\n\t\t\tRwCameraEndUpdate(m_pCamera);\n\t\t}\n\t\t\n\t\tRwCameraSetRaster(m_pCamera, dstRaster);\n      \n\t\tif ( RwCameraBeginUpdate(m_pCamera) )\n\t\t{\n\t\t\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER,      (void *)raster);\n\t\t\tIm2DRenderQuad(0.0f, 0.0f, size, size, RwIm2DGetNearScreenZ(), recipCamZ, 0);\n        \n\t\t\tif ( i == numPasses - 1 )\n\t\t\t{\n\t\t\t\tRwRenderStateSet(rwRENDERSTATEZTESTENABLE,    (void *)TRUE);\n\t\t\t\tRwRenderStateSet(rwRENDERSTATESRCBLEND,       (void *)rwBLENDSRCALPHA);\n\t\t\t\tRwRenderStateSet(rwRENDERSTATEDESTBLEND,      (void *)rwBLENDINVSRCALPHA);\n\t\t\t}\n\t\t\t\n\t\t\tRwCameraEndUpdate(m_pCamera);\n\t\t}\n\t}\n\n\tRwCameraSetRaster(m_pCamera, raster);\n\n\treturn dstRaster;\n}\n\nRwRaster *\nCShadowCamera::RasterGradient(RwRaster *dstRaster)\n{\n\tASSERT(dstRaster != nil);\n\tASSERT(m_pCamera != nil);\n\t\n\tRwRaster *raster = RwCameraGetRaster(m_pCamera);\n\tASSERT(raster != nil);\n\t\n\tfloat size = (float)RwRasterGetWidth(dstRaster);\n\tfloat recipCamZ = 1.0f / RwCameraGetNearClipPlane(m_pCamera);\n\t\n\tRwCameraSetRaster(m_pCamera, dstRaster);\n\t\n\tif ( RwCameraBeginUpdate(m_pCamera) )\n\t{\n\t\tRwRenderStateSet(rwRENDERSTATESRCBLEND,      (void *)rwBLENDZERO);\n\t\tRwRenderStateSet(rwRENDERSTATEDESTBLEND,     (void *)rwBLENDSRCCOLOR);\n\t\tRwRenderStateSet(rwRENDERSTATEZTESTENABLE,   (void *)FALSE);\n\t\tRwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void *)rwFILTERLINEAR);\n\t\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void *)raster);\n\t\t\n\t\tIm2DRenderQuad(0, 0, size, size, RwIm2DGetNearScreenZ(), recipCamZ, 0);\n\t\t\n\t\tRwRenderStateSet(rwRENDERSTATEZTESTENABLE,   (void *)TRUE);\n\t\tRwRenderStateSet(rwRENDERSTATESRCBLEND,      (void *)rwBLENDSRCALPHA);\n\t\tRwRenderStateSet(rwRENDERSTATEDESTBLEND,     (void *)rwBLENDINVSRCALPHA);\n\t\t\n\t\tRwCameraEndUpdate(m_pCamera);\n\t}\n\n\tRwCameraSetRaster(m_pCamera, raster);\n\n\treturn dstRaster;\n}\n\nRwRaster *CShadowCamera::DrawOutlineBorder(RwRGBA const& color)\n{\n\tASSERT(m_pCamera != nil);\n\t\n\tRwIm2DVertex vx[4];\n\tRwImVertexIndex ix[5];\n\n\tRwRaster *raster = RwCameraGetRaster(m_pCamera);\n\tASSERT(raster != nil);\n\n\tfloat size = (float)RwRasterGetWidth(raster) - 1.0f;\n\tfloat recipCamZ = 1.0f / RwCameraGetNearClipPlane(m_pCamera);\n\t\n\tRwIm2DVertexSetScreenX     (&vx[0], 0.0f);\n\tRwIm2DVertexSetScreenY     (&vx[0], 0.0f);\n\tRwIm2DVertexSetScreenZ     (&vx[0], RwIm2DGetNearScreenZ());\n\tRwIm2DVertexSetIntRGBA     (&vx[0], color.red, color.green, color.blue, color.alpha);\n\tRwIm2DVertexSetRecipCameraZ(&vx[0], recipCamZ);\n\n\tRwIm2DVertexSetScreenX     (&vx[1], size);\n\tRwIm2DVertexSetScreenY     (&vx[1], 0.0f);\n\tRwIm2DVertexSetScreenZ     (&vx[1], RwIm2DGetNearScreenZ());\n\tRwIm2DVertexSetIntRGBA     (&vx[1], color.red, color.green, color.blue, color.alpha);\n\tRwIm2DVertexSetRecipCameraZ(&vx[1], recipCamZ);\n\n\tRwIm2DVertexSetScreenX     (&vx[2], size);\n\tRwIm2DVertexSetScreenY     (&vx[2], size);\n\tRwIm2DVertexSetScreenZ     (&vx[2], RwIm2DGetNearScreenZ());\n\tRwIm2DVertexSetIntRGBA     (&vx[2], color.red, color.green, color.blue, color.alpha);\n\tRwIm2DVertexSetRecipCameraZ(&vx[2], recipCamZ);\n\n\tRwIm2DVertexSetScreenX     (&vx[3], 0.0f);\n\tRwIm2DVertexSetScreenY     (&vx[3], size);\n\tRwIm2DVertexSetScreenZ     (&vx[3], RwIm2DGetNearScreenZ());\n\tRwIm2DVertexSetIntRGBA     (&vx[3], color.red, color.green, color.blue, color.alpha);\n\tRwIm2DVertexSetRecipCameraZ(&vx[3], recipCamZ);\n\n\tix[0] = 0;\n\tix[4] = 0;\n\tix[1] = 1;\n\tix[2] = 2;\n\tix[3] = 3;\n\n\tif ( RwCameraBeginUpdate(m_pCamera) )\n\t{\n\t\tRwRenderStateSet(rwRENDERSTATEZTESTENABLE,       (void *)FALSE);\n\t\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)FALSE);\n\t\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER,     (void *)nil);\n\t\t\n\t\tRwIm2DRenderIndexedPrimitive(rwPRIMTYPEPOLYLINE, vx, 4, ix, 5);\n\t\t\n\t\tRwRenderStateSet(rwRENDERSTATEZTESTENABLE,       (void *)TRUE);\n\t\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)TRUE);\n\t\t\n\t\tRwCameraEndUpdate(m_pCamera);\n\t}\n\n\treturn raster;\n}"
  },
  {
    "path": "src/render/ShadowCamera.h",
    "content": "#pragma once\n\n\nclass CShadowCamera\n{\npublic:\n\tRwCamera *m_pCamera;\n\tRwTexture *m_pTexture;\n\t\n\tCShadowCamera();\n\t~CShadowCamera();\n\n\tRwCamera *Create(int32 rasterSize);\n\tvoid Destroy();\n\t\n\tRwCamera *SetFrustum(float objectRadius);\n\tRwCamera *SetLight(RpLight *light);\n\tRwCamera *SetCenter(RwV3d *center);\n\t\n\tRwCamera *Update(RpClump *clump);\n\tRwCamera *Update(RpAtomic *atomic);\n\t\n\tvoid InvertRaster();\n\t\n\tRwRaster* GetRwRenderRaster()\n\t{\n\t\treturn RwCameraGetRaster(m_pCamera);\n\t}\n\t\n\t// ShadowRasterRender(RwV2d *)\n\t// ApplyAlphaMapToRaster(void)\n\t\n\tRwRaster *MakeGradientRaster();\n\t\n\tRwTexture *GetRwRenderTexture()\n\t{\n\t\treturn m_pTexture;\n\t}\n\t\n\tRwRaster* GetRwZRaster()\n\t{\n\t\treturn RwCameraGetZRaster(m_pCamera);\n\t}\n\t\n\tRwRaster *RasterResample(RwRaster *dstRaster);\n\tRwRaster *RasterBlur(RwRaster *dstRaster, int32 numPasses);\n\tRwRaster *RasterGradient(RwRaster *dstRaster);\n\tRwRaster *DrawOutlineBorder(RwRGBA const& color);\n\n\tRwCamera *GetRwCamera()\n\t{\n\t\treturn m_pCamera;\n\t}\n};"
  },
  {
    "path": "src/render/Shadows.cpp",
    "content": "#include \"common.h\"\n\n#include \"main.h\"\n#include \"TxdStore.h\"\n#include \"Timer.h\"\n#include \"Camera.h\"\n#include \"Timecycle.h\"\n#include \"CutsceneMgr.h\"\n#include \"Automobile.h\"\n#include \"Bike.h\"\n#include \"Ped.h\"\n#include \"PlayerPed.h\"\n#include \"World.h\"\n#include \"Weather.h\"\n#include \"ModelIndices.h\"\n#include \"RenderBuffer.h\"\n#ifdef FIX_BUGS\n#include \"Replay.h\"\n#endif\n#include \"PointLights.h\"\n#include \"SpecialFX.h\"\n#include \"Script.h\"\n#include \"TimeStep.h\"\n#include \"Shadows.h\"\n#include \"CutsceneObject.h\"\n#include \"CutsceneShadow.h\"\n#include \"Clock.h\"\n#include \"VarConsole.h\"\n\n#ifdef DEBUGMENU\n//SETTWEAKPATH(\"Shadows\");\n//TWEAKBOOL(gbPrintShite);\n#endif\n\nRwImVertexIndex ShadowIndexList[24];\n\nRwTexture *gpShadowCarTex;\nRwTexture *gpShadowPedTex;\nRwTexture *gpShadowHeliTex;\nRwTexture *gpShadowBikeTex;\nRwTexture *gpShadowBaronTex;\nRwTexture *gpShadowExplosionTex;\nRwTexture *gpShadowHeadLightsTex;\nRwTexture *gpOutline1Tex;\nRwTexture *gpOutline2Tex;\nRwTexture *gpOutline3Tex;\nRwTexture *gpBloodPoolTex;\nRwTexture *gpReflectionTex;\nRwTexture *gpWalkDontTex;\nRwTexture *gpCrackedGlassTex;\nRwTexture *gpPostShadowTex;\nRwTexture *gpGoalTex;\n\nint16            CShadows::ShadowsStoredToBeRendered;\nCStoredShadow    CShadows::asShadowsStored  [MAX_STOREDSHADOWS];\nCPolyBunch       CShadows::aPolyBunches     [MAX_POLYBUNCHES];\nCStaticShadow    CShadows::aStaticShadows   [MAX_STATICSHADOWS];\nCPolyBunch      *CShadows::pEmptyBunchList;\nCPermanentShadow CShadows::aPermanentShadows[MAX_PERMAMENTSHADOWS];\n\n#ifndef MASTER\nbool gbCountPolysInShadow;\n#endif\n\nvoid\nCShadows::Init(void)\n{\n\tCTxdStore::PushCurrentTxd();\n\n\tint32 slut = CTxdStore::FindTxdSlot(\"particle\");\n\tCTxdStore::SetCurrentTxd(slut);\n\n\tgpShadowCarTex        = RwTextureRead(\"shad_car\",     nil);\n\tgpShadowPedTex        = RwTextureRead(\"shad_ped\",     nil);\n\tgpShadowHeliTex       = RwTextureRead(\"shad_heli\",    nil);\n\tgpShadowBikeTex       = RwTextureRead(\"shad_bike\",    nil);\n\tgpShadowBaronTex      = RwTextureRead(\"shad_rcbaron\", nil);\n\tgpShadowExplosionTex  = RwTextureRead(\"shad_exp\",     nil);\n\tgpShadowHeadLightsTex = RwTextureRead(\"headlight\",    nil);\n\tgpOutline1Tex         = RwTextureRead(\"outline_64\",   nil);\n\tgpOutline2Tex         = RwTextureRead(\"outline2_64\",  nil);\n\tgpOutline3Tex         = RwTextureRead(\"outline3_64\",  nil);\n\tgpBloodPoolTex        = RwTextureRead(\"bloodpool_64\", nil);\n\tgpReflectionTex       = RwTextureRead(\"reflection01\", nil);\n\tgpWalkDontTex         = RwTextureRead(\"walk_dont\",    nil);\n\tgpCrackedGlassTex     = RwTextureRead(\"wincrack_32\",  nil);\n\tgpPostShadowTex       = RwTextureRead(\"lamp_shad_64\", nil);\n\n\tCTxdStore::PopCurrentTxd();\n\n\tASSERT(gpShadowCarTex != nil);\n\tASSERT(gpShadowPedTex != nil);\n\tASSERT(gpShadowHeliTex != nil);\n\tASSERT(gpShadowBikeTex != nil);\n\tASSERT(gpShadowBaronTex != nil);\n\tASSERT(gpShadowExplosionTex != nil);\n\tASSERT(gpShadowHeadLightsTex != nil);\n\tASSERT(gpOutline1Tex != nil);\n\tASSERT(gpOutline2Tex != nil);\n\tASSERT(gpOutline3Tex != nil);\n\tASSERT(gpBloodPoolTex != nil);\n\tASSERT(gpReflectionTex != nil);\n\tASSERT(gpWalkDontTex != nil);\n\tASSERT(gpCrackedGlassTex != nil);\n\tASSERT(gpPostShadowTex != nil);\n\n\n\tShadowIndexList[0] = 0;\n\tShadowIndexList[1] = 2;\n\tShadowIndexList[2] = 1;\n\n\tShadowIndexList[3] = 0;\n\tShadowIndexList[4] = 3;\n\tShadowIndexList[5] = 2;\n\n\tShadowIndexList[6] = 0;\n\tShadowIndexList[7] = 4;\n\tShadowIndexList[8] = 3;\n\n\tShadowIndexList[9] = 0;\n\tShadowIndexList[10] = 5;\n\tShadowIndexList[11] = 4;\n\n\tShadowIndexList[12] = 0;\n\tShadowIndexList[13] = 6;\n\tShadowIndexList[14] = 5;\n\n\tShadowIndexList[15] = 0;\n\tShadowIndexList[16] = 7;\n\tShadowIndexList[17] = 6;\n\n\tShadowIndexList[18] = 0;\n\tShadowIndexList[19] = 8;\n\tShadowIndexList[20] = 7;\n\n\tShadowIndexList[21] = 0;\n\tShadowIndexList[22] = 9;\n\tShadowIndexList[23] = 8;\n\n\n\tfor ( int32 i = 0; i < MAX_STATICSHADOWS; i++ )\n\t{\n\t\taStaticShadows[i].m_nId = 0;\n\t\taStaticShadows[i].m_pPolyBunch = nil;\n\t}\n\n\tpEmptyBunchList = &aPolyBunches[0];\n\n\tfor ( int32 i = 0; i < MAX_POLYBUNCHES; i++ )\n\t{\n\t\tif ( i == MAX_POLYBUNCHES - 1 )\n\t\t\taPolyBunches[i].m_pNext = nil;\n\t\telse\n\t\t\taPolyBunches[i].m_pNext = &aPolyBunches[i + 1];\n\t}\n\n\tfor ( int32 i = 0; i < MAX_PERMAMENTSHADOWS; i++ )\n\t{\n\t\taPermanentShadows[i].m_nType = SHADOWTYPE_NONE;\n\t}\n\n#ifndef MASTER\n\tVarConsole.Add(\"Count polys in shadow\", &gbCountPolysInShadow, true);\n#endif\n}\n\nvoid\nCShadows::Shutdown(void)\n{\n\tASSERT(gpShadowCarTex != nil);\n\tASSERT(gpShadowPedTex != nil);\n\tASSERT(gpShadowHeliTex != nil);\n\tASSERT(gpShadowBikeTex != nil);\n\tASSERT(gpShadowBaronTex != nil);\n\tASSERT(gpShadowExplosionTex != nil);\n\tASSERT(gpShadowHeadLightsTex != nil);\n\tASSERT(gpOutline1Tex != nil);\n\tASSERT(gpOutline2Tex != nil);\n\tASSERT(gpOutline3Tex != nil);\n\tASSERT(gpBloodPoolTex != nil);\n\tASSERT(gpReflectionTex != nil);\n\tASSERT(gpWalkDontTex != nil);\n\tASSERT(gpCrackedGlassTex != nil);\n\tASSERT(gpPostShadowTex != nil);\n\n\tRwTextureDestroy(gpShadowCarTex);\n\tRwTextureDestroy(gpShadowPedTex);\n\tRwTextureDestroy(gpShadowHeliTex);\n\tRwTextureDestroy(gpShadowBikeTex);\n\tRwTextureDestroy(gpShadowBaronTex);\n\tRwTextureDestroy(gpShadowExplosionTex);\n\tRwTextureDestroy(gpShadowHeadLightsTex);\n\tRwTextureDestroy(gpOutline1Tex);\n\tRwTextureDestroy(gpOutline2Tex);\n\tRwTextureDestroy(gpOutline3Tex);\n\tRwTextureDestroy(gpBloodPoolTex);\n\tRwTextureDestroy(gpReflectionTex);\n\tRwTextureDestroy(gpWalkDontTex);\n\tRwTextureDestroy(gpCrackedGlassTex);\n\tRwTextureDestroy(gpPostShadowTex);\n}\n\nvoid\nCShadows::AddPermanentShadow(uint8 ShadowType, RwTexture *pTexture, CVector *pPosn,\n\t\t\t\t\t\t\tfloat fFrontX, float fFrontY, float fSideX, float fSideY,\n\t\t\t\t\t\t\tint16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue,\n\t\t\t\t\t\t\tfloat fZDistance, uint32 nTime, float fScale)\n{\n\tASSERT(pTexture != nil);\n\tASSERT(pPosn != nil);\n\n\n\t// find free slot\n\tint32 nSlot = 0;\n\twhile ( nSlot < MAX_PERMAMENTSHADOWS && aPermanentShadows[nSlot].m_nType != SHADOWTYPE_NONE )\n\t\tnSlot++;\n\n\tif ( nSlot < MAX_PERMAMENTSHADOWS )\n\t{\n\t\taPermanentShadows[nSlot].m_nType        = ShadowType;\n\t\taPermanentShadows[nSlot].m_pTexture     = pTexture;\n\t\taPermanentShadows[nSlot].m_vecPos       = *pPosn;\n\t\taPermanentShadows[nSlot].m_vecFront.x   = fFrontX;\n\t\taPermanentShadows[nSlot].m_vecFront.y   = fFrontY;\n\t\taPermanentShadows[nSlot].m_vecSide.x    = fSideX;\n\t\taPermanentShadows[nSlot].m_vecSide.y    = fSideY;\n\t\taPermanentShadows[nSlot].m_nIntensity   = nIntensity;\n\t\taPermanentShadows[nSlot].m_nRed         = nRed;\n\t\taPermanentShadows[nSlot].m_nGreen       = nGreen;\n\t\taPermanentShadows[nSlot].m_nBlue        = nBlue;\n\t\taPermanentShadows[nSlot].m_fZDistance   = fZDistance;\n\t\taPermanentShadows[nSlot].m_nLifeTime    = nTime;\n\t\taPermanentShadows[nSlot].m_nTimeCreated = CTimer::GetTimeInMilliseconds();\n\t}\n}\n\nbool\nCShadows::StoreStaticShadow(uint32 nID, uint8 ShadowType, RwTexture *pTexture, Const CVector *pPosn,\n\t\t\t\t\t\t\tfloat fFrontX, float fFrontY, float fSideX, float fSideY,\n\t\t\t\t\t\t\tint16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue,\n\t\t\t\t\t\t\tfloat fZDistance, float fScale, float fDrawDistance, bool bTempShadow, float fUpDistance)\n{\n\tASSERT(pPosn != nil);\n\n\tfloat fDistToCamSqr = (*pPosn - TheCamera.GetPosition()).MagnitudeSqr2D();\n\n\tif ( SQR(fDrawDistance) > fDistToCamSqr || fDrawDistance == 0.0f )\n\t{\n\t\tif ( fDrawDistance != 0.0f )\n\t\t{\n\t\t\tfloat fDistToCam = Sqrt(fDistToCamSqr);\n\n\t\t\tif ( fDistToCam >= (fDrawDistance*(1.0f-(1.0f/4.0f))) )\n\t\t\t{\n\t\t\t\t//fDistToCam == 0             -> 4\n\t\t\t\t//fDistToCam == fDrawDistance -> 0\n\t\t\t\tfloat fMult = 1.0f - (4.0f / fDrawDistance) * (fDistToCam - (fDrawDistance*(1.0f-(1.0f/4.0f))));\n\n\t\t\t\tnIntensity = (int32)(nIntensity * fMult);\n\t\t\t\tnRed       = (int32)(nRed       * fMult);\n\t\t\t\tnGreen     = (int32)(nGreen     * fMult);\n\t\t\t\tnBlue      = (int32)(nBlue      * fMult);\n\t\t\t}\n\t\t}\n\n\t\tint32 nSlot;\n\n\t\tnSlot = 0;\n\t\twhile ( nSlot < MAX_STATICSHADOWS && !(nID == aStaticShadows[nSlot].m_nId && aStaticShadows[nSlot].m_pPolyBunch != nil) )\n\t\t\tnSlot++;\n\n\t\tif ( nSlot < MAX_STATICSHADOWS )\n\t\t{\n\t\t\tif (   Abs(pPosn->x - aStaticShadows[nSlot].m_vecPosn.x) < fUpDistance\n\t\t\t\t&& Abs(pPosn->y - aStaticShadows[nSlot].m_vecPosn.y) < fUpDistance )\n\t\t\t{\n\t\t\t\taStaticShadows[nSlot].m_bJustCreated     = true;\n\t\t\t\taStaticShadows[nSlot].m_nType            = ShadowType;\n\t\t\t\taStaticShadows[nSlot].m_pTexture         = pTexture;\n\t\t\t\taStaticShadows[nSlot].m_nIntensity       = nIntensity;\n\t\t\t\taStaticShadows[nSlot].m_nRed             = nRed;\n\t\t\t\taStaticShadows[nSlot].m_nGreen           = nGreen;\n\t\t\t\taStaticShadows[nSlot].m_nBlue            = nBlue;\n\t\t\t\taStaticShadows[nSlot].m_fZDistance       = fZDistance;\n\t\t\t\taStaticShadows[nSlot].m_fScale           = fScale;\n\t\t\t\taStaticShadows[nSlot].m_bTemp            = bTempShadow;\n\t\t\t\taStaticShadows[nSlot].m_nTimeCreated     = CTimer::GetTimeInMilliseconds();\n\t\t\t\t\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\telse if (  Abs(pPosn->x - aStaticShadows[nSlot].m_vecPosn.x) < 0.05f\n\t\t\t\t\t&& Abs(pPosn->y - aStaticShadows[nSlot].m_vecPosn.y) < 0.05f\n\t\t\t\t\t&& Abs(pPosn->z - aStaticShadows[nSlot].m_vecPosn.z) < 2.0f\n\n\t\t\t\t\t&& fFrontX == aStaticShadows[nSlot].m_vecFront.x\n\t\t\t\t\t&& fFrontY == aStaticShadows[nSlot].m_vecFront.y\n\t\t\t\t\t&& fSideX  == aStaticShadows[nSlot].m_vecSide.x\n\t\t\t\t\t&& fSideY  == aStaticShadows[nSlot].m_vecSide.y )\n\t\t\t{\n\t\t\t\taStaticShadows[nSlot].m_bJustCreated     = true;\n\t\t\t\taStaticShadows[nSlot].m_nType            = ShadowType;\n\t\t\t\taStaticShadows[nSlot].m_pTexture         = pTexture;\n\t\t\t\taStaticShadows[nSlot].m_nIntensity       = nIntensity;\n\t\t\t\taStaticShadows[nSlot].m_nRed             = nRed;\n\t\t\t\taStaticShadows[nSlot].m_nGreen           = nGreen;\n\t\t\t\taStaticShadows[nSlot].m_nBlue            = nBlue;\n\t\t\t\taStaticShadows[nSlot].m_fZDistance       = fZDistance;\n\t\t\t\taStaticShadows[nSlot].m_fScale           = fScale;\n\t\t\t\taStaticShadows[nSlot].m_bTemp            = bTempShadow;\n\t\t\t\taStaticShadows[nSlot].m_nTimeCreated     = CTimer::GetTimeInMilliseconds();\n\t\t\t\t\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\taStaticShadows[nSlot].Free();\n\n\t\t\t\taStaticShadows[nSlot].m_nId              = nID;\n\t\t\t\taStaticShadows[nSlot].m_nType            = ShadowType;\n\t\t\t\taStaticShadows[nSlot].m_pTexture         = pTexture;\n\t\t\t\taStaticShadows[nSlot].m_nIntensity       = nIntensity;\n\t\t\t\taStaticShadows[nSlot].m_nRed             = nRed;\n\t\t\t\taStaticShadows[nSlot].m_nGreen           = nGreen;\n\t\t\t\taStaticShadows[nSlot].m_nBlue            = nBlue;\n\t\t\t\taStaticShadows[nSlot].m_fZDistance       = fZDistance;\n\t\t\t\taStaticShadows[nSlot].m_fScale           = fScale;\n\t\t\t\taStaticShadows[nSlot].m_vecPosn          = *pPosn;\n\t\t\t\taStaticShadows[nSlot].m_vecFront.x       = fFrontX;\n\t\t\t\taStaticShadows[nSlot].m_vecFront.y       = fFrontY;\n\t\t\t\taStaticShadows[nSlot].m_vecSide.x        = fSideX;\n\t\t\t\taStaticShadows[nSlot].m_vecSide.y        = fSideY;\n\t\t\t\taStaticShadows[nSlot].m_bJustCreated     = true;\n\t\t\t\taStaticShadows[nSlot].m_bTemp            = bTempShadow;\n\t\t\t\taStaticShadows[nSlot].m_nTimeCreated     = CTimer::GetTimeInMilliseconds();\n\n\t\t\t\tGeneratePolysForStaticShadow(nSlot);\n\t\t\t\t\n\t\t\t\treturn aStaticShadows[nSlot].m_pPolyBunch != nil;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tnSlot = 0;\n\t\t\twhile ( nSlot < MAX_STATICSHADOWS && aStaticShadows[nSlot].m_pPolyBunch != nil )\n\t\t\t\tnSlot++;\n\n\t\t\tif ( nSlot != MAX_STATICSHADOWS )\n\t\t\t{\n\t\t\t\taStaticShadows[nSlot].m_nId              = nID;\n\t\t\t\taStaticShadows[nSlot].m_nType            = ShadowType;\n\t\t\t\taStaticShadows[nSlot].m_pTexture         = pTexture;\n\t\t\t\taStaticShadows[nSlot].m_nIntensity       = nIntensity;\n\t\t\t\taStaticShadows[nSlot].m_nRed             = nRed;\n\t\t\t\taStaticShadows[nSlot].m_nGreen           = nGreen;\n\t\t\t\taStaticShadows[nSlot].m_nBlue            = nBlue;\n\t\t\t\taStaticShadows[nSlot].m_fZDistance       = fZDistance;\n\t\t\t\taStaticShadows[nSlot].m_fScale           = fScale;\n\t\t\t\taStaticShadows[nSlot].m_vecPosn          = *pPosn;\n\t\t\t\taStaticShadows[nSlot].m_vecFront.x       = fFrontX;\n\t\t\t\taStaticShadows[nSlot].m_vecFront.y       = fFrontY;\n\t\t\t\taStaticShadows[nSlot].m_vecSide.x        = fSideX;\n\t\t\t\taStaticShadows[nSlot].m_vecSide.y        = fSideY;\n\t\t\t\taStaticShadows[nSlot].m_bJustCreated     = true;\n\t\t\t\taStaticShadows[nSlot].m_bTemp            = bTempShadow;\n\t\t\t\taStaticShadows[nSlot].m_nTimeCreated     = CTimer::GetTimeInMilliseconds();\n\n\t\t\t\tGeneratePolysForStaticShadow(nSlot);\n\t\t\t\t\n\t\t\t\treturn aStaticShadows[nSlot].m_pPolyBunch != nil;\n\t\t\t}\n\t\t}\n\t}\n\t\n\treturn true;\n}\n\nvoid\nCShadows::StoreShadowToBeRendered(uint8 ShadowTexture, CVector *pPosn,\n\t\t\t\t\t\t\t\tfloat fFrontX, float fFrontY, float fSideX, float fSideY,\n\t\t\t\t\t\t\t\tint16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue)\n{\n\tASSERT(pPosn != nil);\n\n\tswitch ( ShadowTexture )\n\t{\n\t\tcase SHADOWTEX_NONE:\n\t\t{\n\t\t\tbreak;\n\t\t}\n\n\t\tcase SHADOWTEX_CAR:\n\t\t{\n\t\t\tStoreShadowToBeRendered(SHADOWTYPE_DARK, gpShadowCarTex, pPosn,\n\t\t\t\t\tfFrontX, fFrontY, fSideX, fSideY,\n\t\t\t\t\tnIntensity, nRed, nGreen, nBlue,\n\t\t\t\t\t15.0f, false, 1.0f, nil, false);\n\n\t\t\tbreak;\n\t\t}\n\n\t\tcase SHADOWTEX_PED:\n\t\t{\n\t\t\tStoreShadowToBeRendered(SHADOWTYPE_DARK, gpShadowPedTex, pPosn,\n\t\t\t\t\tfFrontX, fFrontY, fSideX, fSideY,\n\t\t\t\t\tnIntensity, nRed, nGreen, nBlue,\n\t\t\t\t\t15.0f, false, 1.0f, nil, false);\n\n\t\t\tbreak;\n\t\t}\n\n\t\tcase SHADOWTEX_EXPLOSION:\n\t\t{\n\t\t\tStoreShadowToBeRendered(SHADOWTYPE_ADDITIVE, gpShadowExplosionTex, pPosn,\n\t\t\t\t\tfFrontX, fFrontY, fSideX, fSideY,\n\t\t\t\t\tnIntensity, nRed, nGreen, nBlue,\n\t\t\t\t\t15.0f, false, 1.0f, nil, false);\n\n\t\t\tbreak;\n\t\t}\n\n\t\tcase SHADOWTEX_HELI:\n\t\t{\n\t\t\tStoreShadowToBeRendered(SHADOWTYPE_DARK, gpShadowHeliTex, pPosn,\n\t\t\t\t\tfFrontX, fFrontY, fSideX, fSideY,\n\t\t\t\t\tnIntensity, nRed, nGreen, nBlue,\n\t\t\t\t\t15.0f, false, 1.0f, nil, false);\n\n\t\t\tbreak;\n\t\t}\n\n\t\tcase SHADOWTEX_HEADLIGHTS:\n\t\t{\n\t\t\tStoreShadowToBeRendered(SHADOWTYPE_ADDITIVE, gpShadowHeadLightsTex, pPosn,\n\t\t\t\t\tfFrontX, fFrontY, fSideX, fSideY,\n\t\t\t\t\tnIntensity, nRed, nGreen, nBlue,\n\t\t\t\t\t15.0f, false, 1.0f, nil, false);\n\n\t\t\tbreak;\n\t\t}\n\n\t\tcase SHADOWTEX_BLOOD:\n\t\t{\n\t\t\tStoreShadowToBeRendered(SHADOWTYPE_DARK, gpBloodPoolTex, pPosn,\n\t\t\t\t\tfFrontX, fFrontY, fSideX, fSideY,\n\t\t\t\t\tnIntensity, nRed, 150, 0,\n\t\t\t\t\t15.0f, false, 1.0f, nil, false);\n\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t//ASSERT(false);\n}\n\nvoid\nCShadows::StoreShadowToBeRendered(uint8 ShadowType, RwTexture *pTexture, CVector *pPosn,\n\t\t\t\t\t\t\t\tfloat fFrontX, float fFrontY, float fSideX, float fSideY,\n\t\t\t\t\t\t\t\tint16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue,\n\t\t\t\t\t\t\t\tfloat fZDistance, bool bDrawOnWater, float fScale, CCutsceneShadow *pShadow, bool bDrawOnBuildings)\n{\n\tASSERT(pTexture != nil);\n\tASSERT(pPosn != nil);\n\n\tif ( ShadowsStoredToBeRendered < MAX_STOREDSHADOWS )\n\t{\n\t\tasShadowsStored[ShadowsStoredToBeRendered].m_ShadowType              = ShadowType;\n\t\tasShadowsStored[ShadowsStoredToBeRendered].m_pTexture                = pTexture;\n\t\tasShadowsStored[ShadowsStoredToBeRendered].m_vecPos                  = *pPosn;\n\t\tasShadowsStored[ShadowsStoredToBeRendered].m_vecFront.x              = fFrontX;\n\t\tasShadowsStored[ShadowsStoredToBeRendered].m_vecFront.y              = fFrontY;\n\t\tasShadowsStored[ShadowsStoredToBeRendered].m_vecSide.x               = fSideX;\n\t\tasShadowsStored[ShadowsStoredToBeRendered].m_vecSide.y               = fSideY;\n\t\tasShadowsStored[ShadowsStoredToBeRendered].m_nIntensity              = nIntensity;\n\t\tasShadowsStored[ShadowsStoredToBeRendered].m_nRed                    = nRed;\n\t\tasShadowsStored[ShadowsStoredToBeRendered].m_nGreen                  = nGreen;\n\t\tasShadowsStored[ShadowsStoredToBeRendered].m_nBlue                   = nBlue;\n\t\tasShadowsStored[ShadowsStoredToBeRendered].m_fZDistance              = fZDistance;\n\t\tasShadowsStored[ShadowsStoredToBeRendered].m_nFlags.bDrawOnWater     = bDrawOnWater;\n\t\tasShadowsStored[ShadowsStoredToBeRendered].m_nFlags.bDrawOnBuildings = bDrawOnBuildings;\n\t\tasShadowsStored[ShadowsStoredToBeRendered].m_fScale                  = fScale;\n\t\tasShadowsStored[ShadowsStoredToBeRendered].m_pCutsceneShadow         = pShadow;\n\n\t\tShadowsStoredToBeRendered++;\n\t}\n}\n\n\nvoid\nCShadows::StoreShadowForVehicle(CVehicle *pCar, VEH_SHD_TYPE type)\n{\n\tASSERT(pCar != nil);\n\n\tif ( CTimeCycle::GetShadowStrength() != 0 )\n\t{\n\t\tCVector CarPos = pCar->GetPosition();\n\t\tfloat fDistToCamSqr = (CarPos - TheCamera.GetPosition()).MagnitudeSqr2D();\n\n\t\tif ( CCutsceneMgr::IsRunning() )\n\t\t\tfDistToCamSqr /= SQR(TheCamera.LODDistMultiplier) * 4.0f;\n\n\t\tfloat fDrawDistance;\n\t\tswitch ( type )\n\t\t{\n\t\t\tcase VEH_SHD_TYPE_SEAPLANE:\n\t\t\tcase VEH_SHD_TYPE_RCPLANE:\n\t\t\t\tfDrawDistance = 144.0f;\n\t\t\t\tbreak;\n\t\t\t\t\n\t\t\tcase VEH_SHD_TYPE_HELI:\n\t\t\t\tfDrawDistance = 144.0f;\n\t\t\t\tbreak;\n\t\t\t\t\n\t\t\tdefault:\n\t\t\t\tfDrawDistance = 18.0f;\n\t\t\t\tbreak;\n\t\t}\n\n\t\tif ( fDistToCamSqr < SQR(fDrawDistance) )\n\t\t{\n\t\t\tfloat fDistToCam = Sqrt(fDistToCamSqr);\n\t\t\t\n\t\t\t//fDistToCam == 0             -> 4\n\t\t\t//fDistToCam == fDrawDistance -> 0\n\t\t\tfloat fMult = 1.0f - (fDistToCam - (fDrawDistance*(1.0f-(1.0f/4.0f)))) / (fDrawDistance*(1.0f/4.0f));\n\n\t\t\tint32 nColorStrength;\n\n\t\t\tif ( fDistToCam >= (fDrawDistance*(1.0f-(1.0f/4.0f))) )\n\t\t\t\tnColorStrength = (int32)(fMult * CTimeCycle::GetShadowStrength());\n\t\t\telse\n\t\t\t\tnColorStrength = CTimeCycle::GetShadowStrength();\n\t\t\t\n\t\t\t\n\t\t\tfloat fVehicleHeight  = pCar->GetColModel()->boundingBox.GetSize().y;\n\t\t\tfloat fVehicleWidth   = pCar->GetColModel()->boundingBox.GetSize().x;\n\t\t\t\n\t\t\tfloat size = 1.0f;\n\t\t\t\n\t\t\tif ( pCar->GetModelIndex() == MI_HUNTER )\n\t\t\t{\n\t\t\t\tfVehicleWidth  *= 3.0f;\n\t\t\t\tfVehicleHeight *= 1.4f;\n\t\t\t\tsize *= 0.5f;\n\t\t\t}\n\t\t\telse if ( pCar->GetModelIndex() == MI_ANGEL )\n\t\t\t{\n\t\t\t\tfVehicleHeight = fVehicleHeight * 1.5f;\n\t\t\t\tsize = 0.03f;\n\t\t\t}\n\t\t\telse if ( pCar->GetModelIndex() == MI_SEASPAR )\n\t\t\t{\n\t\t\t\tfVehicleWidth  *= 3.0f;\n\t\t\t\tfVehicleHeight *= 1.4f;\n\t\t\t\tsize *= 0.5f;\n\t\t\t}\n\t\t\telse if ( pCar->GetModelIndex() == MI_PIZZABOY || pCar->GetModelIndex() == MI_PCJ600 || pCar->GetModelIndex() == MI_FAGGIO )\n\t\t\t{\n\t\t\t\tfVehicleHeight *= 1.2f;\n\t\t\t\tsize = 0.05f;\n\t\t\t}\n\t\t\telse if ( pCar->GetModelIndex() == MI_FREEWAY )\n\t\t\t{\n\t\t\t\tfVehicleHeight *= 1.5f;\n\t\t\t\tsize = 0.03f;\n\t\t\t}\n\t\t\telse if ( pCar->GetModelIndex() == MI_RCRAIDER )\n\t\t\t{\n\t\t\t\tfVehicleHeight *= 1.5f;\n\t\t\t\tfVehicleWidth  *= 2.0f;\n\t\t\t\tsize = 0.2f;\n\t\t\t}\n\t\t\telse if ( pCar->GetModelIndex() == MI_SANCHEZ )\n\t\t\t{\n\t\t\t\tfVehicleHeight *= 1.5f;\n\t\t\t\tsize = 0.03f;\n\t\t\t}\n\t\t\telse if ( pCar->GetModelIndex() == MI_SPARROW || pCar->GetModelIndex() == MI_MAVERICK || pCar->GetModelIndex() == MI_VCNMAV || pCar->GetModelIndex() == MI_POLMAV )\n\t\t\t{\n\t\t\t\tfVehicleWidth  *= 3.0f;\n\t\t\t\tfVehicleHeight *= 1.4f;\n\t\t\t\tsize *= 0.5f;\n\t\t\t}\n\t\t\telse if ( pCar->GetModelIndex() == MI_RCGOBLIN )\n\t\t\t{\n\t\t\t\tfVehicleHeight *= 1.5f;\n\t\t\t\tfVehicleWidth  *= 2.0f;\n\t\t\t\tsize = 0.2f;\n\t\t\t}\n\t\t\telse if ( pCar->GetModelIndex() == MI_DODO )\n\t\t\t{\n\t\t\t\tfVehicleHeight *= 0.9f;\n\t\t\t\tfVehicleWidth  *= 0.4f;\n\t\t\t}\n\t\t\t\n\t\t\tCarPos.x -= pCar->GetForward().x * (((fVehicleHeight/2) - pCar->GetColModel()->boundingBox.max.y)*size);\n\t\t\tCarPos.y -= pCar->GetForward().y * (((fVehicleHeight/2) - pCar->GetColModel()->boundingBox.max.y)*size);\n\t\t\t\n\t\t\tRwTexture *tex = gpShadowCarTex;\n\t\t\tswitch ( type )\n\t\t\t{\n\t\t\t\tcase VEH_SHD_TYPE_BIKE:\n\t\t\t\t{\n\t\t\t\t\tfloat wheelZ = Abs(((CBike*)pCar)->m_fLeanLRAngle);\n\t\t\t\t\tfloat mul = 5.092958f * wheelZ + 1.0f;\n\t\t\t\t\tif (pCar->GetStatus() == STATUS_PHYSICS)\n\t\t\t\t\t{\n\t\t\t\t\t\tfloat z = pCar->GetRight().z;\n\t\t\t\t\t\tif (z > 0.6f)\n\t\t\t\t\t\t\tmul += 4.0f * z;\n\t\t\t\t\t}\n\t\t\t\t\tfVehicleWidth *= mul;\n\t\t\t\t\ttex = gpShadowBikeTex;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tcase VEH_SHD_TYPE_HELI:\n\t\t\t\t\ttex = gpShadowHeliTex;\n\t\t\t\t\tbreak;\n\t\t\t\t\n\t\t\t\tcase VEH_SHD_TYPE_SEAPLANE:\n\t\t\t\t\tnColorStrength = CTimeCycle::GetShadowStrength();\n\t\t\t\t\ttex = gpShadowBaronTex;\n\t\t\t\t\tbreak;\n\t\t\t\t\n\t\t\t\tcase VEH_SHD_TYPE_RCPLANE:\n\t\t\t\t\ttex = gpShadowBaronTex;\n\t\t\t\t\tfVehicleHeight *= 1.5f;\n\t\t\t\t\tfVehicleWidth  *= 2.2f;\n\t\t\t\t\tbreak;\n\t\t\t\t\n\t\t\t\tcase VEH_SHD_TYPE_CAR:\n\t\t\t\t\ttex = gpShadowCarTex;\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\t\n\t\t\tfloat frontx = pCar->GetForward().x;\n\t\t\tfloat fronty = pCar->GetForward().y;\n\t\t\tfloat sidex  = pCar->GetRight().x;\n\t\t\tfloat sidey  = pCar->GetRight().y;\n\t\t\t\n\t\t\tswitch ( type )\n\t\t\t{\n\t\t\t\tcase VEH_SHD_TYPE_BIKE:\n\t\t\t\t\tif ( Abs(pCar->GetRight().z) > 0.6f )\n\t\t\t\t\t{\n\t\t\t\t\t\tsidex = pCar->GetUp().x;\n\t\t\t\t\t\tsidey = pCar->GetUp().y;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t\t\n\t\t\t\tcase VEH_SHD_TYPE_HELI:\n\t\t\t\t\tif ( Abs(pCar->GetRight().z) > 0.57f )\n\t\t\t\t\t{\n\t\t\t\t\t\tsidex = pCar->GetUp().x;\n\t\t\t\t\t\tsidey = pCar->GetUp().y;\n\t\t\t\t\t}\n\t\t\t\t\tif ( Abs(pCar->GetForward().z) > 0.57f )\n\t\t\t\t\t{\n\t\t\t\t\t\tfrontx = pCar->GetUp().x;\n\t\t\t\t\t\tfronty = pCar->GetUp().y;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tbool bDrawOnBuildings = false;\n\t\t\tif (   pCar->GetModelIndex() == MI_RCBANDIT\n\t\t\t\t|| pCar->GetModelIndex() == MI_RCBARON\n\t\t\t\t|| pCar->GetModelIndex() == MI_RCRAIDER\n\t\t\t\t|| pCar->GetModelIndex() == MI_RCGOBLIN\n\t\t\t\t|| pCar == FindPlayerVehicle() )\n\t\t\t{\n\t\t\t\tbDrawOnBuildings = true;\n\t\t\t}\n\t\t\t\n\t\t\tif ( pCar->m_vecMoveSpeed.Magnitude() * CTimeStep::ms_fTimeStep > 0.1f || bDrawOnBuildings )\n\t\t\t{\n\t\t\t\tif ( pCar->GetUp().z > 0.0f )\n\t\t\t\t{\n\t\t\t\t\tStoreShadowToBeRendered(SHADOWTYPE_DARK, tex, &CarPos,\n\t\t\t\t\t\tfrontx * (fVehicleHeight / 2),\n\t\t\t\t\t\tfronty * (fVehicleHeight / 2),\n\t\t\t\t\t\tsidex  * (fVehicleWidth  / 2),\n\t\t\t\t\t\tsidey  * (fVehicleWidth  / 2),\n\t\t\t\t\t\tnColorStrength, nColorStrength, nColorStrength, nColorStrength,\n\t\t\t\t\t\t4.5f, false, 1.0f, nil, bDrawOnBuildings);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tStoreShadowToBeRendered(SHADOWTYPE_DARK, tex, &CarPos,\n\t\t\t\t\t\tfrontx * (fVehicleHeight / 2),\n\t\t\t\t\t\tfronty * (fVehicleHeight / 2),\n\t\t\t\t\t\t-sidex * (fVehicleWidth  / 2),\n\t\t\t\t\t\t-sidey * (fVehicleWidth  / 2),\n\t\t\t\t\t\tnColorStrength, nColorStrength, nColorStrength, nColorStrength,\n\t\t\t\t\t\t4.5f, false, 1.0f, nil, bDrawOnBuildings);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif ( pCar->GetUp().z > 0.0f )\n\t\t\t\t{\n\t\t\t\t\tStoreStaticShadow((uintptr)pCar + 1, SHADOWTYPE_DARK, tex, &CarPos,\n\t\t\t\t\t\tfrontx * (fVehicleHeight / 2),\n\t\t\t\t\t\tfronty * (fVehicleHeight / 2),\n\t\t\t\t\t\tsidex  * (fVehicleWidth  / 2),\n\t\t\t\t\t\tsidey  * (fVehicleWidth  / 2),\n\t\t\t\t\t\tnColorStrength, nColorStrength, nColorStrength, nColorStrength,\n\t\t\t\t\t\t4.5f, 1.0f, 0.0f, false, 0.1f);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tStoreStaticShadow((uintptr)pCar + 1, SHADOWTYPE_DARK, tex, &CarPos,\n\t\t\t\t\t\tfrontx * (fVehicleHeight / 2),\n\t\t\t\t\t\tfronty * (fVehicleHeight / 2),\n\t\t\t\t\t\t-sidex * (fVehicleWidth  / 2),\n\t\t\t\t\t\t-sidey * (fVehicleWidth  / 2),\n\t\t\t\t\t\tnColorStrength, nColorStrength, nColorStrength, nColorStrength,\n\t\t\t\t\t\t4.5f, 1.0f, 0.0f, false, 0.1f);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nCShadows::StoreCarLightShadow(CVehicle *pCar, int32 nID, RwTexture *pTexture, CVector *pPosn,\n\t\t\t\t\t\t\tfloat fFrontX, float fFrontY, float fSideX, float fSideY, uint8 nRed, uint8 nGreen, uint8 nBlue,\n\t\t\t\t\t\t\tfloat fMaxViewAngle)\n{\n\tASSERT(pCar != nil);\n\tASSERT(pPosn != nil);\n\n\tfloat fDistToCamSqr = (*pPosn - TheCamera.GetPosition()).MagnitudeSqr2D();\n\n\tbool bSpecialCam =     TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOPDOWN\n\t\t\t\t\t\t|| TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOP_DOWN_PED\n\t\t\t\t\t\t|| CCutsceneMgr::IsRunning();\n\n\tfloat fDrawDistance = 27.0f;\n\n\tif ( fDistToCamSqr < SQR(fDrawDistance) || bSpecialCam )\n\t{\n\t\tif ( bSpecialCam || DotProduct2D(CVector2D(TheCamera.CamFrontXNorm, TheCamera.CamFrontYNorm),\n\t\t\t\t\t\t\t\t\t\t\t*pPosn - TheCamera.GetPosition() ) > -fMaxViewAngle )\n\t\t{\n\t\t\tfloat fDistToCam = Sqrt(fDistToCamSqr);\n\n\t\t\tif ( fDistToCam >= (fDrawDistance*(1.0f-(1.0f/4.0f))) && !bSpecialCam ) // BUG? must be 3.0?\n\t\t\t{\n\t\t\t\t//fDistToCam == 0             -> 3\n\t\t\t\t//fDistToCam == fDrawDistance -> 0\n\t\t\t\tfloat fMult = 1.0f - (3.0f / fDrawDistance) * (fDistToCam - (fDrawDistance*(1.0f-(1.0f/3.0f))) );\n\n\t\t\t\tnRed   = (int32)(nRed   * fMult);\n\t\t\t\tnGreen = (int32)(nGreen * fMult);\n\t\t\t\tnBlue  = (int32)(nBlue  * fMult);\n\t\t\t}\n\n\t\t\tif ( pCar->m_vecMoveSpeed.Magnitude() * CTimeStep::ms_fTimeStep > 0.4f || pCar == FindPlayerVehicle() )\n\t\t\t{\n\t\t\t\tStoreShadowToBeRendered(SHADOWTYPE_ADDITIVE, pTexture, pPosn,\n\t\t\t\t\t\tfFrontX, fFrontY,\n\t\t\t\t\t\tfSideX, fSideY,\n\t\t\t\t\t\t128, nRed, nGreen, nBlue,\n\t\t\t\t\t\t6.0f, false, 1.0f,\n\t\t\t\t\t\tnil, pCar == FindPlayerVehicle());\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tStoreStaticShadow((uintptr)pCar + nID, SHADOWTYPE_ADDITIVE, pTexture, pPosn,\n\t\t\t\t\t\tfFrontX, fFrontY,\n\t\t\t\t\t\tfSideX, fSideY,\n\t\t\t\t\t\t128, nRed, nGreen, nBlue,\n\t\t\t\t\t\t6.0f, 1.0f, 27.0f,\n\t\t\t\t\t\tfalse, 0.4f);\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n#ifdef USE_CUTSCENE_SHADOW_FOR_PED\nvoid\nStoreShadowForCutscenePedObject(CPed *pObject, float fDisplacementX, float fDisplacementY,\n\t\t\t\t\t\t\t\tfloat fFrontX, float fFrontY, float fSideX, float fSideY)\n{\n\tASSERT(pObject != nil);\n\t\n\tCCutsceneShadow *shadow = pObject->m_pRTShadow;\n\t\n\tif ( shadow == nil )\n\t\treturn;\n\t\n\tif ( !shadow->IsInitialized() )\n\t\treturn;\n\t\n\tCVector pos = pObject->GetPosition();\n\t\n\tfloat fDistToCamSqr = (pos - TheCamera.GetPosition()).MagnitudeSqr2D();\n\t\n\tfloat fDrawDistance = 100.0f;\n\t\n\tif ( fDistToCamSqr < SQR(fDrawDistance*0.5f) )\n\t{\n\t\tif ( (CEntity*)pObject == FindPlayerPed() || TheCamera.IsSphereVisible(pos, 2.0f) )\n\t\t{\n\t\t\tfloat fDistToCam = Sqrt(fDistToCamSqr);\n\t\t\t\n\t\t\tfloat fMult = 1.0f - (4.0f / fDrawDistance) * (fDistToCam - (fDrawDistance*(1.0f/4.0f)));\n\t\t\tint32 nColorStrength;\n\n\t\t\tif ( fDistToCam >= (fDrawDistance*(1.0f/4.0f)) )\n\t\t\t\tnColorStrength = (int32)(CTimeCycle::GetShadowStrength() * fMult);\n\t\t\telse\n\t\t\t\tnColorStrength = CTimeCycle::GetShadowStrength();\n\n\t\t\tint32 color = int32(nColorStrength * 0.8f);\n\t\t\t\n\t\t\tpos.x += fDisplacementX;\n\t\t\tpos.y += fDisplacementY;\n\t\t\t\n\t\t\tRwTexture *texture = shadow->GetShadowRwTexture();\n\t\t\tASSERT(texture);\n\t\t\tRwRGBA bordercolor = {0, 0, 0, 0};\n\t\t\tshadow->DrawBorderAroundTexture(bordercolor);\n\t\t\t\n\t\t\tpos.x -= fDisplacementX;\n\t\t\tpos.y -= fDisplacementY;\n\t\t\t\n\t\t\tfloat angleY = 360.0f - RADTODEG((CClock::ms_nGameClockMinutes\n\t\t\t\t\t+60*CClock::ms_nGameClockHours+CClock::ms_nGameClockSeconds/60)*(HALFPI/360.0f));\n\t\t\t \n\t\t\tRwFrame *frame = shadow->SetLightProperties(angleY, -85.0f, true);\n\t\t\tASSERT(frame);\n\t\t\tCVector at(RwFrameGetMatrix(frame)->at);\n\t\t\tat.Normalise();\n\t\t\t\n\t\t\tCShadows::CalcPedShadowValues(at, &fFrontX, &fFrontY, &fSideX, &fSideY, &fDisplacementX, &fDisplacementY);\n\t\t\t\n\t\t\tpos.x -= 2.5f * fDisplacementX;\n\t\t\tpos.y -= 2.5f * fDisplacementY;\n\t\t\t\n\t\t\tCShadows::StoreShadowToBeRendered(SHADOWTYPE_INVCOLOR, texture, &pos,\n\t\t\t\tfFrontX * 1.5f, fFrontY * 1.5f,\n\t\t\t\tfSideX  * 1.5f, fSideY  * 1.5f,\n\t\t\t\tcolor, color, color, color,\n\t\t\t\t4.0f, false, 1.0f, shadow, false);\n\t\t}\n\t}\n}\n#endif\n\n\nvoid\nCShadows::StoreShadowForPed(CPed *pPed, float fDisplacementX, float fDisplacementY,\n\t\t\t\t\t\t\tfloat fFrontX, float fFrontY, float fSideX, float fSideY)\n{\n\tASSERT(pPed != nil);\n\n\tif ( pPed->bIsVisible )\n\t{\n\t\tif ( !(pPed->bInVehicle && pPed->m_nPedState != PED_DRAG_FROM_CAR && pPed->m_nPedState != PED_EXIT_CAR) )\n\t\t{\n\t\t\tif ( CTimeCycle::GetShadowStrength() != 0 )\n\t\t\t{\n#ifdef USE_CUTSCENE_SHADOW_FOR_PED\n\t\t\t\t\tCCutsceneShadow *pShadow = pPed->m_pRTShadow;\n\t\t\t\t\n\t\t\t\t\tif (pShadow)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (pShadow->IsInitialized())\n\t\t\t\t\t\t\tpShadow->UpdateForCutscene();\n\t\t\t\t\t\t::StoreShadowForCutscenePedObject(pPed, fDisplacementX, fDisplacementY, fFrontX, fFrontY, fSideX, fSideY);\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\treturn;\n#endif\n\n\t\t\t\tStoreShadowForPedObject(pPed,\n\t\t\t\t\tfDisplacementX, fDisplacementY,\n\t\t\t\t\tfFrontX, fFrontY,\n\t\t\t\t\tfSideX, fSideY);\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nCShadows::StoreShadowForPedObject(CEntity *pPedObject, float fDisplacementX, float fDisplacementY,\n\t\t\t\t\t\t\t\tfloat fFrontX, float fFrontY, float fSideX, float fSideY)\n{\t\n\tASSERT(pPedObject != nil);\n\n\tCVector PedPos = pPedObject->GetPosition();\n\n\tfloat fDistToCamSqr = (PedPos - TheCamera.GetPosition()).MagnitudeSqr2D();\n\n\tfloat fDrawDistance = 26.0f;\n\n\tif ( fDistToCamSqr < SQR(fDrawDistance*0.5f) )\n\t{\n\t\tif ( pPedObject == FindPlayerPed() || TheCamera.IsSphereVisible(PedPos, 2.0f) != false )\n\t\t{\n\t\t\tfloat fDistToCam = Sqrt(fDistToCamSqr);\n\n\t\t\t//fDistToCam == 0             ->  2\n\t\t\t//fDistToCam == fDrawDistance -> -2\n\t\t\tfloat fMult = 1.0f - (4.0f / fDrawDistance) * (fDistToCam - (fDrawDistance*(1.0f/4.0f))); // BUG ? negative\n\t\t\tint32 nColorStrength;\n\n\t\t\tif ( fDistToCam >= (fDrawDistance*(1.0f/4.0f)) ) // BUG ? negative\n\t\t\t\tnColorStrength = (int32)(CTimeCycle::GetShadowStrength() * fMult);\n\t\t\telse\n\t\t\t\tnColorStrength = CTimeCycle::GetShadowStrength();\n\n\t\t\tPedPos.x += fDisplacementX;\n\t\t\tPedPos.y += fDisplacementY;\n\n\t\t\tStoreShadowToBeRendered(SHADOWTYPE_DARK, gpShadowPedTex, &PedPos,\n\t\t\t\t\tfFrontX, fFrontY,\n\t\t\t\t\tfSideX, fSideY,\n\t\t\t\t\tnColorStrength, nColorStrength, nColorStrength, nColorStrength,\n\t\t\t\t\t4.0f, false, 1.0f, nil, pPedObject == FindPlayerPed());\n\t\t}\n\t}\n}\n\n\nvoid\nCShadows::StoreShadowForCutscenePedObject(CCutsceneObject *pObject, float fDisplacementX, float fDisplacementY,\n\t\t\t\t\t\t\t\tfloat fFrontX, float fFrontY, float fSideX, float fSideY)\n{\n#ifdef DISABLE_CUTSCENE_SHADOWS\n\treturn;\n#endif\n\tASSERT(pObject != nil);\n\t\n\tCCutsceneShadow *shadow = pObject->m_pShadow;\n\t\n\tif ( shadow == nil )\n\t\treturn;\n\t\n\tif ( !shadow->IsInitialized() )\n\t\treturn;\n\t\n\tCVector pos = pObject->GetPosition();\n\t\n\tfloat fDistToCamSqr = (pos - TheCamera.GetPosition()).MagnitudeSqr2D();\n\t\n\tfloat fDrawDistance = 100.0f;\n\t\n\tif ( fDistToCamSqr < SQR(fDrawDistance*0.5f) )\n\t{\n\t\tif ( (CEntity*)pObject == FindPlayerPed() || TheCamera.IsSphereVisible(pos, 2.0f) )\n\t\t{\n\t\t\tfloat fDistToCam = Sqrt(fDistToCamSqr);\n\t\t\t\n\t\t\tfloat fMult = 1.0f - (4.0f / fDrawDistance) * (fDistToCam - (fDrawDistance*(1.0f/4.0f)));\n\t\t\tint32 nColorStrength;\n\n\t\t\tif ( fDistToCam >= (fDrawDistance*(1.0f/4.0f)) )\n\t\t\t\tnColorStrength = (int32)(CTimeCycle::GetShadowStrength() * fMult);\n\t\t\telse\n\t\t\t\tnColorStrength = CTimeCycle::GetShadowStrength();\n\n\t\t\tint32 color = int32(nColorStrength * 0.8f);\n\t\t\t\n\t\t\tpos.x += fDisplacementX;\n\t\t\tpos.y += fDisplacementY;\n\t\t\t\n\t\t\tRwTexture *texture = shadow->GetShadowRwTexture();\n\t\t\tASSERT(texture);\n\t\t\tRwRGBA bordercolor = {0, 0, 0, 0};\n\t\t\tshadow->DrawBorderAroundTexture(bordercolor);\n\t\t\t\n\t\t\tpos.x -= fDisplacementX;\n\t\t\tpos.y -= fDisplacementY;\n\t\t\t\n\t\t\tfloat angleY = 360.0f - RADTODEG((CClock::ms_nGameClockMinutes+60*\n\t\t\t\t\tCClock::ms_nGameClockHours+CClock::ms_nGameClockSeconds/60)*(HALFPI/360.0f));\n\t\t\t \n\t\t\tRwFrame *frame = shadow->SetLightProperties(angleY, -85.0f, true);\n\t\t\tASSERT(frame);\n\t\t\tCVector at(RwFrameGetMatrix(frame)->at);\n\t\t\tat.Normalise();\n\t\t\t\n\t\t\tCalcPedShadowValues(at, &fFrontX, &fFrontY, &fSideX, &fSideY, &fDisplacementX, &fDisplacementY);\n\t\t\t\n\t\t\tpos.x -= 2.5f * fDisplacementX;\n\t\t\tpos.y -= 2.5f * fDisplacementY;\n\t\t\t\n\t\t\tStoreShadowToBeRendered(SHADOWTYPE_INVCOLOR, texture, &pos,\n\t\t\t\tfFrontX * 1.5f, fFrontY * 1.5f,\n\t\t\t\tfSideX  * 1.5f, fSideY  * 1.5f,\n\t\t\t\tcolor, color, color, color,\n\t\t\t\t4.0f, false, 1.0f, shadow, false);\n\t\t}\n\t}\n}\n\nvoid\nCShadows::StoreShadowForTree(CEntity *pTree)\n{\n\tASSERT(pTree != nil);\n}\n\n\nvoid\nCShadows::StoreShadowForPole(CEntity *pPole, float fOffsetX, float fOffsetY, float fOffsetZ,\n\t\t\t\t\t\t\t\tfloat fPoleHeight, float fPoleWidth, uint32 nID)\n{\n\tASSERT(pPole != nil);\n\n\tif ( CTimeCycle::GetShadowStrength() != 0 )\n\t{\n\t\tif ( pPole->GetUp().z < 0.5f )\n\t\t\treturn;\n\n\t\tCVector PolePos = pPole->GetPosition();\n\n\t\tPolePos.x += fOffsetX * pPole->GetRight().x + fOffsetY * pPole->GetForward().x;\n\t\tPolePos.y += fOffsetX * pPole->GetRight().y + fOffsetY * pPole->GetForward().y;\n\t\tPolePos.z += fOffsetZ;\n\n\t\tPolePos.x += -CTimeCycle::GetSunDirection().x * (fPoleHeight / 2);\n\t\tPolePos.y += -CTimeCycle::GetSunDirection().y * (fPoleHeight / 2);\n\n\t\tStoreStaticShadow((uintptr)pPole + nID + _TODOCONST(51), SHADOWTYPE_DARK, gpPostShadowTex, &PolePos,\n\t\t\t\t-CTimeCycle::GetSunDirection().x * (fPoleHeight / 2),\n\t\t\t\t-CTimeCycle::GetSunDirection().y * (fPoleHeight / 2),\n\t\t\t\tCTimeCycle::GetShadowSideX()    * fPoleWidth,\n\t\t\t\tCTimeCycle::GetShadowSideY()    * fPoleWidth,\n\t\t\t\t2 * (int32)((pPole->GetUp().z - 0.5f) * CTimeCycle::GetShadowStrength() * 2.0f) / 3,\n\t\t\t\t0, 0, 0,\n\t\t\t\t15.0f, 1.0f, 40.0f, false, 0.0f);\n\t}\n}\n\nvoid\nCShadows::SetRenderModeForShadowType(uint8 ShadowType)\n{\n\tswitch ( ShadowType )\n\t{\n\t\tcase SHADOWTYPE_DARK:\n\t\t{\n\t\t\tRwRenderStateSet(rwRENDERSTATESRCBLEND,  (void *)rwBLENDSRCALPHA);\n\t\t\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDINVSRCALPHA);\n\t\t\tbreak;\n\t\t}\n\n\t\tcase SHADOWTYPE_ADDITIVE:\n\t\t{\n\t\t\tRwRenderStateSet(rwRENDERSTATESRCBLEND,  (void *)rwBLENDONE);\n\t\t\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDONE);\n\t\t\tbreak;\n\t\t}\n\n\t\tcase SHADOWTYPE_INVCOLOR:\n\t\t{\n\t\t\tRwRenderStateSet(rwRENDERSTATESRCBLEND,  (void *)rwBLENDZERO);\n\t\t\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDINVSRCCOLOR);\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\n\nvoid\nCShadows::RenderStoredShadows(void)\n{\n\tPUSH_RENDERGROUP(\"CShadows::RenderStoredShadows\");\n\n\tRenderBuffer::ClearRenderBuffer();\n\n\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE,      (void *)FALSE);\n\tRwRenderStateSet(rwRENDERSTATEZTESTENABLE,       (void *)TRUE);\n\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)TRUE);\n\tRwRenderStateSet(rwRENDERSTATETEXTUREADDRESS,    (void *)rwTEXTUREADDRESSCLAMP);\n\n\n\tfor ( int32 i = 0; i < ShadowsStoredToBeRendered; i++ )\n\t\tasShadowsStored[i].m_nFlags.bRendered = false;\n\n\n\tfor ( int32 i = 0; i < ShadowsStoredToBeRendered; i++ )\n\t{\n\t\tif ( !asShadowsStored[i].m_nFlags.bRendered )\n\t\t{\n\t\t\tSetRenderModeForShadowType(asShadowsStored[i].m_ShadowType);\n\n\t\t\tASSERT(asShadowsStored[i].m_pTexture != nil);\n\n\t\t\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(asShadowsStored[i].m_pTexture));\n\n\t\t\tfor ( int32 j = i; j < ShadowsStoredToBeRendered; j++ )\n\t\t\t{\n\t\t\t\tif ( asShadowsStored[i].m_ShadowType   == asShadowsStored[j].m_ShadowType\n\t\t\t\t\t&& asShadowsStored[i].m_pTexture == asShadowsStored[j].m_pTexture )\n\t\t\t\t{\n\t\t\t\t\tfloat fWidth  = Abs(asShadowsStored[j].m_vecFront.x) + Abs(asShadowsStored[j].m_vecSide.x);\n\t\t\t\t\tfloat fHeight = Abs(asShadowsStored[j].m_vecFront.y) + Abs(asShadowsStored[j].m_vecSide.y);\n\n\t\t\t\t\tCVector shadowPos = asShadowsStored[j].m_vecPos;\n\n\t\t\t\t\tfloat fStartX = shadowPos.x - fWidth;\n\t\t\t\t\tfloat fEndX   = shadowPos.x + fWidth;\n\t\t\t\t\tfloat fStartY = shadowPos.y - fHeight;\n\t\t\t\t\tfloat fEndY   = shadowPos.y + fHeight;\n\n\t\t\t\t\tint32 nStartX = Max(CWorld::GetSectorIndexX(fStartX), 0);\n\t\t\t\t\tint32 nStartY = Max(CWorld::GetSectorIndexY(fStartY), 0);\n\t\t\t\t\tint32 nEndX   = Min(CWorld::GetSectorIndexX(fEndX), NUMSECTORS_X-1);\n\t\t\t\t\tint32 nEndY   = Min(CWorld::GetSectorIndexY(fEndY), NUMSECTORS_Y-1);\n\n\t\t\t\t\tCWorld::AdvanceCurrentScanCode();\n\n\t\t\t\t\tfor ( int32 y = nStartY; y <= nEndY; y++ )\n\t\t\t\t\t{\n\t\t\t\t\t\tfor ( int32 x = nStartX; x <= nEndX; x++ )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tCSector *pCurSector = CWorld::GetSector(x, y);\n\n\t\t\t\t\t\t\tASSERT(pCurSector != nil);\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tif ( asShadowsStored[j].m_pCutsceneShadow )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tCastCutsceneShadowSectorList(pCurSector->m_lists[ENTITYLIST_BUILDINGS],\n\t\t\t\t\t\t\t\t\t\tfStartX, fStartY,\n\t\t\t\t\t\t\t\t\t\tfEndX, fEndY,\n\t\t\t\t\t\t\t\t\t\t&shadowPos,\n\t\t\t\t\t\t\t\t\t\tasShadowsStored[j].m_vecFront.x,\n\t\t\t\t\t\t\t\t\t\tasShadowsStored[j].m_vecFront.y,\n\t\t\t\t\t\t\t\t\t\tasShadowsStored[j].m_vecSide.x,\n\t\t\t\t\t\t\t\t\t\tasShadowsStored[j].m_vecSide.y,\n\t\t\t\t\t\t\t\t\t\tasShadowsStored[j].m_nIntensity,\n\t\t\t\t\t\t\t\t\t\tasShadowsStored[j].m_nRed,\n\t\t\t\t\t\t\t\t\t\tasShadowsStored[j].m_nGreen,\n\t\t\t\t\t\t\t\t\t\tasShadowsStored[j].m_nBlue,\n\t\t\t\t\t\t\t\t\t\tasShadowsStored[j].m_fZDistance,\n\t\t\t\t\t\t\t\t\t\tasShadowsStored[j].m_fScale,\n\t\t\t\t\t\t\t\t\t\tnil,\n\t\t\t\t\t\t\t\t\t\tasShadowsStored[j].m_pCutsceneShadow);\n\t\n\t\t\t\t\t\t\t\tCastCutsceneShadowSectorList(pCurSector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP],\n\t\t\t\t\t\t\t\t\t\tfStartX, fStartY,\n\t\t\t\t\t\t\t\t\t\tfEndX, fEndY,\n\t\t\t\t\t\t\t\t\t\t&shadowPos,\n\t\t\t\t\t\t\t\t\t\tasShadowsStored[j].m_vecFront.x,\n\t\t\t\t\t\t\t\t\t\tasShadowsStored[j].m_vecFront.y,\n\t\t\t\t\t\t\t\t\t\tasShadowsStored[j].m_vecSide.x,\n\t\t\t\t\t\t\t\t\t\tasShadowsStored[j].m_vecSide.y,\n\t\t\t\t\t\t\t\t\t\tasShadowsStored[j].m_nIntensity,\n\t\t\t\t\t\t\t\t\t\tasShadowsStored[j].m_nRed,\n\t\t\t\t\t\t\t\t\t\tasShadowsStored[j].m_nGreen,\n\t\t\t\t\t\t\t\t\t\tasShadowsStored[j].m_nBlue,\n\t\t\t\t\t\t\t\t\t\tasShadowsStored[j].m_fZDistance,\n\t\t\t\t\t\t\t\t\t\tasShadowsStored[j].m_fScale,\n\t\t\t\t\t\t\t\t\t\tnil,\n\t\t\t\t\t\t\t\t\t\tasShadowsStored[j].m_pCutsceneShadow);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse if ( asShadowsStored[j].m_nFlags.bDrawOnBuildings )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tCastPlayerShadowSectorList(pCurSector->m_lists[ENTITYLIST_BUILDINGS],\n\t\t\t\t\t\t\t\t\t\tfStartX, fStartY,\n\t\t\t\t\t\t\t\t\t\tfEndX, fEndY,\n\t\t\t\t\t\t\t\t\t\t&shadowPos,\n\t\t\t\t\t\t\t\t\t\tasShadowsStored[j].m_vecFront.x,\n\t\t\t\t\t\t\t\t\t\tasShadowsStored[j].m_vecFront.y,\n\t\t\t\t\t\t\t\t\t\tasShadowsStored[j].m_vecSide.x,\n\t\t\t\t\t\t\t\t\t\tasShadowsStored[j].m_vecSide.y,\n\t\t\t\t\t\t\t\t\t\tasShadowsStored[j].m_nIntensity,\n\t\t\t\t\t\t\t\t\t\tasShadowsStored[j].m_nRed,\n\t\t\t\t\t\t\t\t\t\tasShadowsStored[j].m_nGreen,\n\t\t\t\t\t\t\t\t\t\tasShadowsStored[j].m_nBlue,\n\t\t\t\t\t\t\t\t\t\tasShadowsStored[j].m_fZDistance,\n\t\t\t\t\t\t\t\t\t\tasShadowsStored[j].m_fScale,\n\t\t\t\t\t\t\t\t\t\tnil);\n\t\n\t\t\t\t\t\t\t\tCastPlayerShadowSectorList(pCurSector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP],\n\t\t\t\t\t\t\t\t\t\tfStartX, fStartY,\n\t\t\t\t\t\t\t\t\t\tfEndX, fEndY,\n\t\t\t\t\t\t\t\t\t\t&shadowPos,\n\t\t\t\t\t\t\t\t\t\tasShadowsStored[j].m_vecFront.x,\n\t\t\t\t\t\t\t\t\t\tasShadowsStored[j].m_vecFront.y,\n\t\t\t\t\t\t\t\t\t\tasShadowsStored[j].m_vecSide.x,\n\t\t\t\t\t\t\t\t\t\tasShadowsStored[j].m_vecSide.y,\n\t\t\t\t\t\t\t\t\t\tasShadowsStored[j].m_nIntensity,\n\t\t\t\t\t\t\t\t\t\tasShadowsStored[j].m_nRed,\n\t\t\t\t\t\t\t\t\t\tasShadowsStored[j].m_nGreen,\n\t\t\t\t\t\t\t\t\t\tasShadowsStored[j].m_nBlue,\n\t\t\t\t\t\t\t\t\t\tasShadowsStored[j].m_fZDistance,\n\t\t\t\t\t\t\t\t\t\tasShadowsStored[j].m_fScale,\n\t\t\t\t\t\t\t\t\t\tnil);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tCastShadowSectorList(pCurSector->m_lists[ENTITYLIST_BUILDINGS],\n\t\t\t\t\t\t\t\t\t\tfStartX, fStartY,\n\t\t\t\t\t\t\t\t\t\tfEndX, fEndY,\n\t\t\t\t\t\t\t\t\t\t&shadowPos,\n\t\t\t\t\t\t\t\t\t\tasShadowsStored[j].m_vecFront.x,\n\t\t\t\t\t\t\t\t\t\tasShadowsStored[j].m_vecFront.y,\n\t\t\t\t\t\t\t\t\t\tasShadowsStored[j].m_vecSide.x,\n\t\t\t\t\t\t\t\t\t\tasShadowsStored[j].m_vecSide.y,\n\t\t\t\t\t\t\t\t\t\tasShadowsStored[j].m_nIntensity,\n\t\t\t\t\t\t\t\t\t\tasShadowsStored[j].m_nRed,\n\t\t\t\t\t\t\t\t\t\tasShadowsStored[j].m_nGreen,\n\t\t\t\t\t\t\t\t\t\tasShadowsStored[j].m_nBlue,\n\t\t\t\t\t\t\t\t\t\tasShadowsStored[j].m_fZDistance,\n\t\t\t\t\t\t\t\t\t\tasShadowsStored[j].m_fScale,\n\t\t\t\t\t\t\t\t\t\tnil);\n\t\n\t\t\t\t\t\t\t\tCastShadowSectorList(pCurSector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP],\n\t\t\t\t\t\t\t\t\t\tfStartX, fStartY,\n\t\t\t\t\t\t\t\t\t\tfEndX, fEndY,\n\t\t\t\t\t\t\t\t\t\t&shadowPos,\n\t\t\t\t\t\t\t\t\t\tasShadowsStored[j].m_vecFront.x,\n\t\t\t\t\t\t\t\t\t\tasShadowsStored[j].m_vecFront.y,\n\t\t\t\t\t\t\t\t\t\tasShadowsStored[j].m_vecSide.x,\n\t\t\t\t\t\t\t\t\t\tasShadowsStored[j].m_vecSide.y,\n\t\t\t\t\t\t\t\t\t\tasShadowsStored[j].m_nIntensity,\n\t\t\t\t\t\t\t\t\t\tasShadowsStored[j].m_nRed,\n\t\t\t\t\t\t\t\t\t\tasShadowsStored[j].m_nGreen,\n\t\t\t\t\t\t\t\t\t\tasShadowsStored[j].m_nBlue,\n\t\t\t\t\t\t\t\t\t\tasShadowsStored[j].m_fZDistance,\n\t\t\t\t\t\t\t\t\t\tasShadowsStored[j].m_fScale,\n\t\t\t\t\t\t\t\t\t\tnil);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tasShadowsStored[j].m_nFlags.bRendered = true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tRenderBuffer::RenderStuffInBuffer();\n\t\t}\n\t}\n\n\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)FALSE);\n\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE,      (void *)TRUE);\n\tRwRenderStateSet(rwRENDERSTATEZTESTENABLE,       (void *)TRUE);\n\tRwRenderStateSet(rwRENDERSTATETEXTUREADDRESS,    (void *)rwTEXTUREADDRESSWRAP);\n\n\tShadowsStoredToBeRendered = 0;\n\n\tPOP_RENDERGROUP();\n}\n\n\nvoid\nCShadows::RenderStaticShadows(void)\n{\n\tPUSH_RENDERGROUP(\"CShadows::RenderStaticShadows\");\n\n\tRenderBuffer::ClearRenderBuffer();\n\n\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE,      (void *)FALSE);\n\tRwRenderStateSet(rwRENDERSTATEZTESTENABLE,       (void *)TRUE);\n\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)TRUE);\n\tRwRenderStateSet(rwRENDERSTATEFOGENABLE,         (void *)FALSE);\n\n\tSetAlphaTest(0);\n\n\tfor ( int32 i = 0; i < MAX_STATICSHADOWS; i++ )\n\t\taStaticShadows[i].m_bRendered = false;\n\n\tfor ( int32 i = 0; i < MAX_STATICSHADOWS; i++ )\n\t{\n\t\tif ( aStaticShadows[i].m_pPolyBunch && !aStaticShadows[i].m_bRendered )\n\t\t{\n\t\t\tSetRenderModeForShadowType(aStaticShadows[i].m_nType);\n\t\t\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(aStaticShadows[i].m_pTexture));\n\n\t\t\t// optimization trick, render all shadows with same renderstate and texture\n\t\t\tfor ( int32 j = i; j < MAX_STATICSHADOWS; j++ )\n\t\t\t{\n\t\t\t\tif ( aStaticShadows[j].m_pPolyBunch != nil\n\t\t\t\t\t\t&& aStaticShadows[i].m_nType    == aStaticShadows[j].m_nType\n\t\t\t\t\t\t&& aStaticShadows[i].m_pTexture == aStaticShadows[j].m_pTexture )\n\t\t\t\t{\n\t\t\t\t\tfor ( CPolyBunch *bunch = aStaticShadows[j].m_pPolyBunch; bunch != nil; bunch = bunch->m_pNext )\n\t\t\t\t\t{\n\t\t\t\t\t\tRwImVertexIndex *pIndexes;\n\t\t\t\t\t\tRwIm3DVertex *pVerts;\n\n\t\t\t\t\t\tRenderBuffer::StartStoring(3 * (bunch->m_nNumVerts - 2), bunch->m_nNumVerts, &pIndexes, &pVerts);\n\n\t\t\t\t\t\tASSERT(pIndexes != nil);\n\t\t\t\t\t\tASSERT(pVerts != nil);\n\n\t\t\t\t\t\tfor ( int32 k = 0; k < bunch->m_nNumVerts; k++ )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tRwIm3DVertexSetRGBA(&pVerts[k],\n\t\t\t\t\t\t\t\t\taStaticShadows[j].m_nRed,\n\t\t\t\t\t\t\t\t\taStaticShadows[j].m_nGreen,\n\t\t\t\t\t\t\t\t\taStaticShadows[j].m_nBlue,\n\t\t\t\t\t\t\t\t\t(int32)(aStaticShadows[j].m_nIntensity * (1.0f - CWeather::Foggyness * 0.5f)));\n\n\t\t\t\t\t\t\tRwIm3DVertexSetU  (&pVerts[k], bunch->m_aU[k] / 200.0f);\n\t\t\t\t\t\t\tRwIm3DVertexSetV  (&pVerts[k], bunch->m_aV[k] / 200.0f);\n\t\t\t\t\t\t\tRwIm3DVertexSetPos(&pVerts[k], bunch->m_aVerts[k].x, bunch->m_aVerts[k].y,  bunch->m_aVerts[k].z + 0.03f);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tfor ( int32 k = 0; k < 3 * (bunch->m_nNumVerts - 2); k++ )\n\t\t\t\t\t\t\tpIndexes[k] = ShadowIndexList[k];\n\n\t\t\t\t\t\tRenderBuffer::StopStoring();\n\t\t\t\t\t}\n\n\t\t\t\t\taStaticShadows[j].m_bRendered = true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tRenderBuffer::RenderStuffInBuffer();\n\t\t}\n\t}\n\tRestoreAlphaTest();\n\n\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)FALSE);\n\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE,      (void *)TRUE);\n\n\tPOP_RENDERGROUP();\n}\n\n\nvoid\nCShadows::GeneratePolysForStaticShadow(int16 nStaticShadowID)\n{\n\tfloat fWidth  = Abs(aStaticShadows[nStaticShadowID].m_vecFront.x) + Abs(aStaticShadows[nStaticShadowID].m_vecSide.x);\n\tfloat fHeight = Abs(aStaticShadows[nStaticShadowID].m_vecFront.y) + Abs(aStaticShadows[nStaticShadowID].m_vecSide.y);\n\n\tCVector shadowPos = aStaticShadows[nStaticShadowID].m_vecPosn;\n\n\tfloat fStartX = shadowPos.x - fWidth;\n\tfloat fEndX   = shadowPos.x + fWidth;\n\tfloat fStartY = shadowPos.y - fHeight;\n\tfloat fEndY   = shadowPos.y + fHeight;\n\n\tint32 nStartX = Max(CWorld::GetSectorIndexX(fStartX), 0);\n\tint32 nStartY = Max(CWorld::GetSectorIndexY(fStartY), 0);\n\tint32 nEndX   = Min(CWorld::GetSectorIndexX(fEndX), NUMSECTORS_X-1);\n\tint32 nEndY   = Min(CWorld::GetSectorIndexY(fEndY), NUMSECTORS_Y-1);\n\n\tCWorld::AdvanceCurrentScanCode();\n\n\tfor ( int32 y = nStartY; y <= nEndY; y++ )\n\t{\n\t\tfor ( int32 x = nStartX; x <= nEndX; x++ )\n\t\t{\n\t\t\tCSector *pCurSector = CWorld::GetSector(x, y);\n\n\t\t\tASSERT(pCurSector != nil);\n\n\t\t\tCastShadowSectorList(pCurSector->m_lists[ENTITYLIST_BUILDINGS],\n\t\t\t\t\tfStartX, fStartY,\n\t\t\t\t\tfEndX, fEndY,\n\t\t\t\t\t&shadowPos,\n\t\t\t\t\taStaticShadows[nStaticShadowID].m_vecFront.x,\n\t\t\t\t\taStaticShadows[nStaticShadowID].m_vecFront.y,\n\t\t\t\t\taStaticShadows[nStaticShadowID].m_vecSide.x,\n\t\t\t\t\taStaticShadows[nStaticShadowID].m_vecSide.y,\n\t\t\t\t\t0, 0, 0, 0,\n\t\t\t\t\taStaticShadows[nStaticShadowID].m_fZDistance,\n\t\t\t\t\taStaticShadows[nStaticShadowID].m_fScale,\n\t\t\t\t\t&aStaticShadows[nStaticShadowID].m_pPolyBunch);\n\n\t\t\tCastShadowSectorList(pCurSector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP],\n\t\t\t\t\tfStartX, fStartY,\n\t\t\t\t\tfEndX, fEndY,\n\t\t\t\t\t&shadowPos,\n\t\t\t\t\taStaticShadows[nStaticShadowID].m_vecFront.x,\n\t\t\t\t\taStaticShadows[nStaticShadowID].m_vecFront.y,\n\t\t\t\t\taStaticShadows[nStaticShadowID].m_vecSide.x,\n\t\t\t\t\taStaticShadows[nStaticShadowID].m_vecSide.y,\n\t\t\t\t\t0, 0, 0, 0,\n\t\t\t\t\taStaticShadows[nStaticShadowID].m_fZDistance,\n\t\t\t\t\taStaticShadows[nStaticShadowID].m_fScale,\n\t\t\t\t\t&aStaticShadows[nStaticShadowID].m_pPolyBunch);\n\t\t}\n\t}\n}\n\n\nvoid\nCShadows::CastShadowSectorList(CPtrList &PtrList, float fStartX, float fStartY, float fEndX, float fEndY, CVector *pPosn,\n\t\t\t\t\t\t\t\tfloat fFrontX, float fFrontY, float fSideX, float fSideY,\n\t\t\t\t\t\t\t\tint16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue,\n\t\t\t\t\t\t\t\tfloat fZDistance, float fScale, CPolyBunch **ppPolyBunch)\n{\n\tASSERT(pPosn != nil);\n\n\tCPtrNode *pNode = PtrList.first;\n\n\tCRect Bound;\n\n\twhile ( pNode != nil )\n\t{\n\t\tCEntity *pEntity = (CEntity *)pNode->item;\n\t\tuint16 nScanCode = pEntity->m_scanCode;\n\t\tpNode = pNode->next;\n\n\t\tASSERT( pEntity != nil );\n\n\t\tif ( nScanCode != CWorld::GetCurrentScanCode() )\n\t\t{\n\t\t\tpEntity->m_scanCode = CWorld::GetCurrentScanCode();\n\t\t\t\n\t\t\tif ( pEntity->bUsesCollision && !pEntity->m_flagE2 )\n\t\t\t{\n\t\t\t\tif ( IsAreaVisible(pEntity->m_area) )\n\t\t\t\t{\n\t\t\t\t\tBound = pEntity->GetBoundRect();\n\t\n\t\t\t\t\tif ( fStartX < Bound.right\n\t\t\t\t\t\t&& fEndX > Bound.left\n\t\t\t\t\t\t&& fStartY < Bound.bottom\n\t\t\t\t\t\t&& fEndY > Bound.top )\n\t\t\t\t\t{\n\t\t\t\t\t\tif ( pPosn->z - fZDistance < pEntity->GetPosition().z + pEntity->GetColModel()->boundingBox.max.z\n\t\t\t\t\t\t\t&& pEntity->GetPosition().z + pEntity->GetColModel()->boundingBox.min.z < pPosn->z )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tCastShadowEntityXY(pEntity,\n\t\t\t\t\t\t\t\tfStartX, fStartY,\n\t\t\t\t\t\t\t\tfEndX, fEndY,\n\t\t\t\t\t\t\t\tpPosn,\n\t\t\t\t\t\t\t\tfFrontX, fFrontY,\n\t\t\t\t\t\t\t\tfSideX, fSideY,\n\t\t\t\t\t\t\t\tnIntensity, nRed, nGreen, nBlue,\n\t\t\t\t\t\t\t\tfZDistance, fScale, ppPolyBunch);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n\nvoid\nCShadows::CastPlayerShadowSectorList(CPtrList &PtrList, float fStartX, float fStartY, float fEndX, float fEndY, CVector *pPosn,\n\t\t\t\t\t\t\t\tfloat fFrontX, float fFrontY, float fSideX, float fSideY,\n\t\t\t\t\t\t\t\tint16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue,\n\t\t\t\t\t\t\t\tfloat fZDistance, float fScale, CPolyBunch **ppPolyBunch)\n{\n\tASSERT(pPosn != nil);\n\n\tCPtrNode *pNode = PtrList.first;\n\n\tCRect Bound;\n\n\twhile ( pNode != nil )\n\t{\n\t\tCEntity *pEntity = (CEntity *)pNode->item;\n\t\tuint16 nScanCode = pEntity->m_scanCode;\n\t\tpNode = pNode->next;\n\n\t\tASSERT( pEntity != nil );\n\n\t\tif ( nScanCode != CWorld::GetCurrentScanCode() )\n\t\t{\n\t\t\tpEntity->m_scanCode = CWorld::GetCurrentScanCode();\n\t\t\t\n\t\t\tif ( pEntity->bUsesCollision )\n\t\t\t{\n\t\t\t\tif ( IsAreaVisible(pEntity->m_area) )\n\t\t\t\t{\n\t\t\t\t\tBound = pEntity->GetBoundRect();\n\t\n\t\t\t\t\tif ( fStartX < Bound.right\n\t\t\t\t\t\t&& fEndX > Bound.left\n\t\t\t\t\t\t&& fStartY < Bound.bottom\n\t\t\t\t\t\t&& fEndY > Bound.top )\n\t\t\t\t\t{\n\t\t\t\t\t\tif ( pPosn->z - fZDistance < pEntity->GetPosition().z + pEntity->GetColModel()->boundingBox.max.z\n\t\t\t\t\t\t\t&& pEntity->GetPosition().z + pEntity->GetColModel()->boundingBox.min.z < pPosn->z )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tCastShadowEntityXY(pEntity,\n\t\t\t\t\t\t\t\tfStartX, fStartY,\n\t\t\t\t\t\t\t\tfEndX, fEndY,\n\t\t\t\t\t\t\t\tpPosn,\n\t\t\t\t\t\t\t\tfFrontX, fFrontY,\n\t\t\t\t\t\t\t\tfSideX, fSideY,\n\t\t\t\t\t\t\t\tnIntensity, nRed, nGreen, nBlue,\n\t\t\t\t\t\t\t\tfZDistance, fScale, ppPolyBunch);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n\nvoid\nCShadows::CastCutsceneShadowSectorList(CPtrList &PtrList, float fStartX, float fStartY, float fEndX, float fEndY, CVector *pPosn,\n\t\t\t\t\t\t\t\tfloat fFrontX, float fFrontY, float fSideX, float fSideY,\n\t\t\t\t\t\t\t\tint16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue,\n\t\t\t\t\t\t\t\tfloat fZDistance, float fScale, CPolyBunch **ppPolyBunch, CCutsceneShadow *pShadow)\n{\n\tASSERT(pPosn != nil);\n\tASSERT(pShadow != nil);\n\t\n\tCPtrNode *pNode = PtrList.first;\n\n\tCRect Bound;\n\n\twhile ( pNode != nil )\n\t{\n\t\tCEntity *pEntity = (CEntity *)pNode->item;\n\t\tuint16 nScanCode = pEntity->m_scanCode;\n\t\tpNode = pNode->next;\n\n\t\tASSERT( pEntity != nil );\n\n\t\tif ( nScanCode != CWorld::GetCurrentScanCode() )\n\t\t{\n\t\t\tpEntity->m_scanCode = CWorld::GetCurrentScanCode();\n\t\t\t\n\t\t\tif ( pEntity->bUsesCollision )\n\t\t\t{\n\t\t\t\tif ( IsAreaVisible(pEntity->m_area) )\n\t\t\t\t{\n\t\t\t\t\tBound = pEntity->GetBoundRect();\n\t\n\t\t\t\t\tif ( fStartX < Bound.right\n\t\t\t\t\t\t&& fEndX > Bound.left\n\t\t\t\t\t\t&& fStartY < Bound.bottom\n\t\t\t\t\t\t&& fEndY > Bound.top )\n\t\t\t\t\t{\n\t\t\t\t\t\tif ( pPosn->z - fZDistance < pEntity->GetPosition().z + pEntity->GetColModel()->boundingBox.max.z\n\t\t\t\t\t\t\t&& pEntity->GetPosition().z + pEntity->GetColModel()->boundingBox.min.z < pPosn->z )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tCastShadowEntityXYZ(pEntity, pPosn,\n\t\t\t\t\t\t\t\tfFrontX, fFrontY,\n\t\t\t\t\t\t\t\tfSideX, fSideY,\n\t\t\t\t\t\t\t\tnIntensity, nRed, nGreen, nBlue,\n\t\t\t\t\t\t\t\tfZDistance, fScale, ppPolyBunch, pShadow);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nCShadows::CastShadowEntityXY(CEntity *pEntity,  float fStartX, float fStartY, float fEndX, float fEndY, CVector *pPosn,\n\t\t\t\t\t\t\tfloat fFrontX, float fFrontY, float fSideX, float fSideY,\n\t\t\t\t\t\t\tint16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue,\n\t\t\t\t\t\t\tfloat fZDistance, float fScale, CPolyBunch **ppPolyBunch)\n{\n\tASSERT(pEntity != nil);\n\tASSERT(pPosn != nil);\n\n\tstatic CVector List   [20];\n\tstatic CVector Texture[20];\n\tstatic CVector Points [4];\n\n\tCColModel *pCol = pEntity->GetColModel();\n\tASSERT(pCol != nil);\n\n#ifndef MASTER\n\tif ( gbPrintShite )\n\t\tprintf(\"MI:%d Triangles:%d Coors:%f %f BBoxXY:%f %f\\n\",\n\t\t\tpEntity->GetModelIndex(),\n\t\t\tpCol->numTriangles,\n\t\t\tpEntity->GetPosition().x,\n\t\t\tpEntity->GetPosition().y,\n\t\t\tpCol->boundingBox.GetSize().x,\n\t\t\tpCol->boundingBox.GetSize().y);\n#endif\n\t\n\tCCollision::CalculateTrianglePlanes(pCol);\n\n\tfloat fFrontRight    = DotProduct2D(CVector2D(fFrontX, fFrontY),     pEntity->GetRight());\n\tfloat fFrontForward  = DotProduct2D(CVector2D(fFrontX, fFrontY),     pEntity->GetForward());\n\tfloat fSideRight     = DotProduct2D(CVector2D(fSideX, fSideY),       pEntity->GetRight());\n\tfloat fSideForward   = DotProduct2D(CVector2D(fSideX, fSideY),       pEntity->GetForward());\n\tfloat fLengthRight   = DotProduct2D(*pPosn - pEntity->GetPosition(), pEntity->GetRight());\n\tfloat fLengthForward = DotProduct2D(*pPosn - pEntity->GetPosition(), pEntity->GetForward());\n\n\tPoints[0].x = (fLengthRight   + fFrontRight  )  - fSideRight;\n\tPoints[0].y = (fLengthForward + fFrontForward)  - fSideForward;\n\n\tPoints[1].x = fSideRight      + (fLengthRight   + fFrontRight);\n\tPoints[1].y = fSideForward    + (fLengthForward + fFrontForward);\n                                  \n\tPoints[2].x = fSideRight      + (fLengthRight   - fFrontRight);\n\tPoints[2].y = fSideForward    + (fLengthForward - fFrontForward);\n\n\tPoints[3].x = (fLengthRight   - fFrontRight)    - fSideRight;\n\tPoints[3].y = (fLengthForward - fFrontForward)  - fSideForward;\n\n\tfloat MinX = Min(Min(Points[0].x, Points[1].x), Min(Points[2].x, Points[3].x));\n\tfloat MaxX = Max(Max(Points[0].x, Points[1].x), Max(Points[2].x, Points[3].x));\n\n\tfloat MinY = Min(Min(Points[0].y, Points[1].y), Min(Points[2].y, Points[3].y));\n\tfloat MaxY = Max(Max(Points[0].y, Points[1].y), Max(Points[2].y, Points[3].y));\n\n\tfloat MaxZ = pPosn->z - pEntity->GetPosition().z;\n\tfloat MinZ = MaxZ - fZDistance;\n\n\tfor ( int32 i = 0; i < pCol->numTriangles; i++ )\n\t{\n\t\tCColTrianglePlane *pColTriPlanes = pCol->trianglePlanes;\n\t\tASSERT(pColTriPlanes != nil);\n\n\t\tCVector normal;\n\t\tpColTriPlanes[i].GetNormal(normal);\n\t\tif ( Abs(normal.z) > 0.1f )\n\t\t{\n\t\t\tCColTriangle *pColTri = pCol->triangles;\n\t\t\tASSERT(pColTri != nil);\n\n\t\t\tCVector PointA, PointB, PointC;\n\n\t\t\tpCol->GetTrianglePoint(PointA, pColTri[i].a);\n\t\t\tpCol->GetTrianglePoint(PointB, pColTri[i].b);\n\t\t\tpCol->GetTrianglePoint(PointC, pColTri[i].c);\n\n\t\t\tif (   (PointA.x > MinX || PointB.x > MinX || PointC.x > MinX)\n\t\t\t\t&& (PointA.x < MaxX || PointB.x < MaxX || PointC.x < MaxX)\n\t\t\t\t&& (PointA.y > MinY || PointB.y > MinY || PointC.y > MinY)\n\t\t\t\t&& (PointA.y < MaxY || PointB.y < MaxY || PointC.y < MaxY)\n\t\t\t\t&& (PointA.z < MaxZ || PointB.z < MaxZ || PointC.z < MaxZ)\n\t\t\t\t&& (PointA.z > MinZ || PointB.z > MinZ || PointC.z > MinZ) )\n\n\t\t\t{\n\t\t\t\tList[0].x = Points[0].x;\n\t\t\t\tList[0].y = Points[0].y;\n\n\t\t\t\tList[1].x = Points[1].x;\n\t\t\t\tList[1].y = Points[1].y;\n\n\t\t\t\tList[2].x = Points[2].x;\n\t\t\t\tList[2].y = Points[2].y;\n\n\t\t\t\tList[3].x = Points[3].x;\n\t\t\t\tList[3].y = Points[3].y;\n\n\t\t\t\tTexture[0].x = 0.0f;\n\t\t\t\tTexture[0].y = 0.0f;\n\n\t\t\t\tTexture[1].x = 1.0f;\n\t\t\t\tTexture[1].y = 0.0f;\n\n\t\t\t\tTexture[2].x = 1.0f;\n\t\t\t\tTexture[2].y = 1.0f;\n\n\t\t\t\tTexture[3].x = 0.0f;\n\t\t\t\tTexture[3].y = 1.0f;\n\n\n\t\t\t\tCVector2D start;\n\t\t\t\tCVector2D dist;\n\n\t\t\t\tint32 numVerts1 = 0;\n\t\t\t\tint16 vertType1 = 0;\n\t\t\t\t{\t\t\t\t\t\t\n\t\t\t\t\tfor ( int32 j = 0; j < 4; j++ )\n\t\t\t\t\t{\n\t\t\t\t\t\tstart = PointA;\n\t\t\t\t\t\tdist  = PointB - PointA;\n\t\t\t\t\t\t\n\t\t\t\t\t\tint32 in = j;\n\t\t\t\t\t\t\n\t\t\t\t\t\tfloat cp = CrossProduct2D(CVector2D(List[in]) - start, dist);\n\n\t\t\t\t\t\tif ( cp > 0.0f )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tswitch ( vertType1 )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tcase 0:\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tint32 out = numVerts1++ + 10;\n\n\t\t\t\t\t\t\t\t\tTexture[out].x = Texture[in].x;\n\t\t\t\t\t\t\t\t\tTexture[out].y = Texture[in].y;\n\t\t\t\t\t\t\t\t\tList[out].x    = List[in].x;\n\t\t\t\t\t\t\t\t\tList[out].y    = List[in].y;\n\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tcase 1:\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tint32 out = numVerts1++ + 10;\n\n\t\t\t\t\t\t\t\t\tTexture[out].x = Texture[in].x;\n\t\t\t\t\t\t\t\t\tTexture[out].y = Texture[in].y;\n\t\t\t\t\t\t\t\t\tList[out].x    = List[in].x;\n\t\t\t\t\t\t\t\t\tList[out].y    = List[in].y;\n\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tcase 2:\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tfloat prevcp = CrossProduct2D(CVector2D(List[in-1]) - start, dist);\n\n\t\t\t\t\t\t\t\t\tfloat Scale = Abs(prevcp) / (Abs(prevcp) + Abs(cp));\n\t\t\t\t\t\t\t\t\tfloat Compl = 1.0f - Scale;\n\n\t\t\t\t\t\t\t\t\tint32 out1 = numVerts1++ + 10;\n\t\t\t\t\t\t\t\t\tint32 out2 = numVerts1++ + 10;\n\n\t\t\t\t\t\t\t\t\tTexture[out1].x = Compl*Texture[in-1].x + Scale*Texture[in].x;\n\t\t\t\t\t\t\t\t\tTexture[out1].y = Compl*Texture[in-1].y + Scale*Texture[in].y;\n\t\t\t\t\t\t\t\t\tList[out1].x    = Compl*List[in-1].x    + Scale*List[in].x;\n\t\t\t\t\t\t\t\t\tList[out1].y    = Compl*List[in-1].y    + Scale*List[in].y;\n\n\t\t\t\t\t\t\t\t\tTexture[out2].x = Texture[in].x;\n\t\t\t\t\t\t\t\t\tTexture[out2].y = Texture[in].y;\n\t\t\t\t\t\t\t\t\tList[out2].x    = List[in].x;\n\t\t\t\t\t\t\t\t\tList[out2].y    = List[in].y;\n\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tvertType1 = 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tswitch ( vertType1 )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tcase 1:\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tfloat prevcp = CrossProduct2D(CVector2D(List[in-1]) - start, dist);\n\n\t\t\t\t\t\t\t\t\tfloat Scale = Abs(prevcp) / (Abs(prevcp) + Abs(cp));\n\t\t\t\t\t\t\t\t\tfloat Compl = 1.0f - Scale;\n\n\t\t\t\t\t\t\t\t\tint32 out = numVerts1++ + 10;\n\n\t\t\t\t\t\t\t\t\tTexture[out].x = Compl*Texture[in-1].x + Scale*Texture[in].x;\n\t\t\t\t\t\t\t\t\tTexture[out].y = Compl*Texture[in-1].y + Scale*Texture[in].y;\n\t\t\t\t\t\t\t\t\tList[out].x    = Compl*List[in-1].x    + Scale*List[in].x;\n\t\t\t\t\t\t\t\t\tList[out].y    = Compl*List[in-1].y    + Scale*List[in].y;\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tvertType1 = 2;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tfloat cp1 = CrossProduct2D(CVector2D(List[0]) - start, dist);\n\t\t\t\t\tif ( cp1 > 0.0f && vertType1 == 2 || cp1 <= 0.0f && vertType1 == 1 )\n\t\t\t\t\t{\n\t\t\t\t\t\tfloat cp2 = CrossProduct2D(CVector2D(List[3]) - start, dist);\n\n\t\t\t\t\t\tfloat Scale = Abs(cp2) / (Abs(cp2) + Abs(cp1));\n\t\t\t\t\t\tfloat Compl = 1.0f - Scale;\n\n\t\t\t\t\t\tint32 out = numVerts1++ + 10;\n\n\t\t\t\t\t\tTexture[out].x = Compl*Texture[3].x + Scale*Texture[0].x;\n\t\t\t\t\t\tTexture[out].y = Compl*Texture[3].y + Scale*Texture[0].y;\n\t\t\t\t\t\tList[out].x    = Compl*List[3].x    + Scale*List[0].x;\n\t\t\t\t\t\tList[out].y    = Compl*List[3].y    + Scale*List[0].y;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tint32 numVerts2 = 0;\n\t\t\t\tint16 vertType2 = 0;\n\t\t\t\t{\t\t\t\t\t\t\n\t\t\t\t\tfor ( int32 j = 0; j < numVerts1; j++ )\n\t\t\t\t\t{\n\t\t\t\t\t\tstart = PointB;\n\t\t\t\t\t\tdist  = PointC - PointB;\n\t\t\t\t\t\n\t\t\t\t\t\tint32 in = j + 10;\n\t\t\t\t\t\tfloat cp = CrossProduct2D(CVector2D(List[in]) - start, dist);\n\n\t\t\t\t\t\tif ( cp > 0.0f )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tswitch ( vertType2 )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tcase 0:\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tint32 out = numVerts2++;\n\n\t\t\t\t\t\t\t\t\tTexture[out].x = Texture[in].x;\n\t\t\t\t\t\t\t\t\tTexture[out].y = Texture[in].y;\n\t\t\t\t\t\t\t\t\tList[out].x    = List[in].x;\n\t\t\t\t\t\t\t\t\tList[out].y    = List[in].y;\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tcase 1:\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tint32 out = numVerts2++;\n\n\t\t\t\t\t\t\t\t\tTexture[out].x = Texture[in].x;\n\t\t\t\t\t\t\t\t\tTexture[out].y = Texture[in].y;\n\t\t\t\t\t\t\t\t\tList[out].x    = List[in].x;\n\t\t\t\t\t\t\t\t\tList[out].y    = List[in].y;\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tcase 2:\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tfloat prevcp = CrossProduct2D(CVector2D(List[in-1]) - start, dist);\n\n\t\t\t\t\t\t\t\t\tfloat Scale = Abs(prevcp) / (Abs(prevcp) + Abs(cp));\n\t\t\t\t\t\t\t\t\tfloat Compl = 1.0f - Scale;\n\n\t\t\t\t\t\t\t\t\tint32 out1 = numVerts2++;\n\t\t\t\t\t\t\t\t\tint32 out2 = numVerts2++;\n\n\t\t\t\t\t\t\t\t\tTexture[out1].x = Compl*Texture[in-1].x + Scale*Texture[in].x;\n\t\t\t\t\t\t\t\t\tTexture[out1].y = Compl*Texture[in-1].y + Scale*Texture[in].y;\n\t\t\t\t\t\t\t\t\tList[out1].x    = Compl*List[in-1].x    + Scale*List[in].x;\n\t\t\t\t\t\t\t\t\tList[out1].y    = Compl*List[in-1].y    + Scale*List[in].y;\n\n\t\t\t\t\t\t\t\t\tTexture[out2].x = Texture[in].x;\n\t\t\t\t\t\t\t\t\tTexture[out2].y = Texture[in].y;\n\t\t\t\t\t\t\t\t\tList[out2].x    = List[in].x;\n\t\t\t\t\t\t\t\t\tList[out2].y    = List[in].y;\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tvertType2 = 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tswitch ( vertType2 )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tcase 1:\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tfloat prevcp = CrossProduct2D(CVector2D(List[in-1]) - start, dist);\n\n\t\t\t\t\t\t\t\t\tfloat Scale = Abs(prevcp) / (Abs(prevcp) + Abs(cp));\n\t\t\t\t\t\t\t\t\tfloat Compl = 1.0f - Scale;\n\n\t\t\t\t\t\t\t\t\tint32 out = numVerts2++;\n\n\t\t\t\t\t\t\t\t\tTexture[out].x = Compl*Texture[in-1].x + Scale*Texture[in].x;\n\t\t\t\t\t\t\t\t\tTexture[out].y = Compl*Texture[in-1].y + Scale*Texture[in].y;\n\t\t\t\t\t\t\t\t\tList[out].x    = Compl*List[in-1].x    + Scale*List[in].x;\n\t\t\t\t\t\t\t\t\tList[out].y    = Compl*List[in-1].y    + Scale*List[in].y;\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tvertType2 = 2;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tfloat cp1 = CrossProduct2D(CVector2D(List[10]) - start, dist);\n\t\t\t\t\tif ( cp1 > 0.0f && vertType2 == 2 || cp1 <= 0.0f && vertType2 == 1 )\n\t\t\t\t\t{\n\t\t\t\t\t\tint32 in = numVerts1 + 10;\n\n\t\t\t\t\t\tfloat cp2 = CrossProduct2D(CVector2D(List[in-1]) - start, dist);\n\n\t\t\t\t\t\tfloat Scale = Abs(cp2) / (Abs(cp2) + Abs(cp1));\n\t\t\t\t\t\tfloat Compl = 1.0f - Scale;\n\n\t\t\t\t\t\tint32 out = numVerts2++;\n\n\t\t\t\t\t\tTexture[out].x = Compl*Texture[in-1].x + Scale*Texture[10].x;\n\t\t\t\t\t\tTexture[out].y = Compl*Texture[in-1].y + Scale*Texture[10].y;\n\t\t\t\t\t\tList[out].x    = Compl*List[in-1].x    + Scale*List[10].x;\n\t\t\t\t\t\tList[out].y    = Compl*List[in-1].y    + Scale*List[10].y;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tint32 numVerts3 = 0;\n\t\t\t\tint16 vertType3 = 0;\n\t\t\t\t{\t\t\t\t\t\n\t\t\t\t\tfor ( int32 j = 0; j < numVerts2; j++ )\n\t\t\t\t\t{\n\t\t\t\t\t\tstart = PointC;\n\t\t\t\t\t\tdist  = PointA - PointC;\n\t\t\t\t\t\n\t\t\t\t\t\tint32 in = j;\n\t\t\t\t\t\tfloat cp = CrossProduct2D(CVector2D(List[in]) - start, dist);\n\n\t\t\t\t\t\tif ( cp > 0.0f )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tswitch ( vertType3 )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tcase 0:\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tint32 out = numVerts3++ + 10;\n\n\t\t\t\t\t\t\t\t\tTexture[out].x = Texture[in].x;\n\t\t\t\t\t\t\t\t\tTexture[out].y = Texture[in].y;\n\t\t\t\t\t\t\t\t\tList[out].x    = List[in].x;\n\t\t\t\t\t\t\t\t\tList[out].y    = List[in].y;\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tcase 1:\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tint32 out = numVerts3++ + 10;\n\n\t\t\t\t\t\t\t\t\tTexture[out].x = Texture[in].x;\n\t\t\t\t\t\t\t\t\tTexture[out].y = Texture[in].y;\n\t\t\t\t\t\t\t\t\tList[out].x    = List[in].x;\n\t\t\t\t\t\t\t\t\tList[out].y    = List[in].y;\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tcase 2:\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tfloat prevcp = CrossProduct2D(CVector2D(List[in-1]) - start, dist);\n\n\t\t\t\t\t\t\t\t\tfloat Scale = Abs(prevcp) / (Abs(prevcp) + Abs(cp));\n\t\t\t\t\t\t\t\t\tfloat Compl = 1.0f - Scale;\n\n\t\t\t\t\t\t\t\t\tint32 out1 = numVerts3++ + 10;\n\t\t\t\t\t\t\t\t\tint32 out2 = numVerts3++ + 10;\n\n\t\t\t\t\t\t\t\t\tTexture[out1].x = Compl*Texture[in-1].x + Scale*Texture[in].x;\n\t\t\t\t\t\t\t\t\tTexture[out1].y = Compl*Texture[in-1].y + Scale*Texture[in].y;\n\t\t\t\t\t\t\t\t\tList[out1].x    = Compl*List[in-1].x    + Scale*List[in].x;\n\t\t\t\t\t\t\t\t\tList[out1].y    = Compl*List[in-1].y    + Scale*List[in].y;\n\n\t\t\t\t\t\t\t\t\tTexture[out2].x = Texture[in].x;\n\t\t\t\t\t\t\t\t\tTexture[out2].y = Texture[in].y;\n\t\t\t\t\t\t\t\t\tList[out2].x    = List[in].x;\n\t\t\t\t\t\t\t\t\tList[out2].y    = List[in].y;\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tvertType3 = 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tswitch ( vertType3 )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tcase 1:\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tfloat prevcp = CrossProduct2D(CVector2D(List[in-1]) - start, dist);\n\n\t\t\t\t\t\t\t\t\tfloat Scale = Abs(prevcp) / (Abs(prevcp) + Abs(cp));\n\t\t\t\t\t\t\t\t\tfloat Compl = 1.0f - Scale;\n\n\t\t\t\t\t\t\t\t\tint32 out = numVerts3++ + 10;\n\n\t\t\t\t\t\t\t\t\tTexture[out].x = Compl*Texture[in-1].x + Scale*Texture[in].x;\n\t\t\t\t\t\t\t\t\tTexture[out].y = Compl*Texture[in-1].y + Scale*Texture[in].y;\n\t\t\t\t\t\t\t\t\tList[out].x    = Compl*List[in-1].x    + Scale*List[in].x;\n\t\t\t\t\t\t\t\t\tList[out].y    = Compl*List[in-1].y    + Scale*List[in].y;\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tvertType3 = 2;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tfloat cp1 = CrossProduct2D(CVector2D(List[0]) - start, dist);\n\t\t\t\t\tif ( cp1 > 0.0f && vertType3 == 2 || cp1 <= 0.0f && vertType3 == 1 )\n\t\t\t\t\t{\n\t\t\t\t\t\tint32 in = numVerts2;\n\n\t\t\t\t\t\tfloat cp2 = CrossProduct2D(CVector2D(List[in-1]) - start, dist);\n\n\t\t\t\t\t\tfloat Scale = Abs(cp2) / (Abs(cp2) + Abs(cp1));\n\t\t\t\t\t\tfloat Compl = 1.0f - Scale;\n\n\t\t\t\t\t\tint32 out = numVerts3++ + 10;\n\n\t\t\t\t\t\tTexture[out].x = Compl*Texture[in-1].x + Scale*Texture[0].x;\n\t\t\t\t\t\tTexture[out].y = Compl*Texture[in-1].y + Scale*Texture[0].y;\n\t\t\t\t\t\tList[out].x    = Compl*List[in-1].x    + Scale*List[0].x;\n\t\t\t\t\t\tList[out].y    = Compl*List[in-1].y    + Scale*List[0].y;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\tif ( numVerts3 >= 3 )\n\t\t\t\t{\n\t\t\t\t\tCVector norm;\n\n\t\t\t\t\tpColTriPlanes[i].GetNormal(norm);\n\n\t\t\t\t\tfloat dot = DotProduct(norm, PointA);\n\n\t\t\t\t\tfor ( int32 j = 0; j < numVerts3; j++ )\n\t\t\t\t\t{\n\t\t\t\t\t\tint32 idx = j + 10;\n\n\t\t\t\t\t\tList[idx].z = -(DotProduct2D(norm, List[idx]) - dot) / norm.z;\n\t\t\t\t\t}\n\n\t\t\t\t\tfor ( int32 j = 0; j < numVerts3; j++ )\n\t\t\t\t\t{\n\t\t\t\t\t\tint32 idx = j + 10;\n\n\t\t\t\t\t\tCVector p = List[idx];\n\t\t\t\t\t\t\n\t\t\t\t\t\tList[idx].x = p.y * pEntity->GetForward().x + p.x * pEntity->GetRight().x + pEntity->GetPosition().x;\n\t\t\t\t\t\tList[idx].y = p.y * pEntity->GetForward().y + p.x * pEntity->GetRight().y + pEntity->GetPosition().y;\n\t\t\t\t\t\tList[idx].z = p.z + pEntity->GetPosition().z;\n\t\t\t\t\t}\n\n\t\t\t\t\t\n\t\t\t\t\tif ( ppPolyBunch != nil )\n\t\t\t\t\t{\n\t\t\t\t\t\tif ( pEmptyBunchList != nil )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tCPolyBunch *pBunch = pEmptyBunchList;\n\t\t\t\t\t\t\tASSERT(pBunch != nil);\n\t\t\t\t\t\t\tpEmptyBunchList = pEmptyBunchList->m_pNext;\n\t\t\t\t\t\t\tpBunch->m_pNext = *ppPolyBunch;\n\t\t\t\t\t\t\t*ppPolyBunch = pBunch;\n\t\n\t\t\t\t\t\t\tpBunch->m_nNumVerts = numVerts3;\n\t\n\t\t\t\t\t\t\tfor ( int32 j = 0; j < numVerts3; j++ )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tint32 in = j + 10;\n\t\n\t\t\t\t\t\t\t\tpBunch->m_aVerts[j] = List[in];\n\t\n\t\t\t\t\t\t\t\tpBunch->m_aU[j] = (int32)(Texture[in].x * 200.0f);\n\t\t\t\t\t\t\t\tpBunch->m_aV[j] = (int32)(Texture[in].y * 200.0f);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tRwImVertexIndex *pIndexes;\n\t\t\t\t\t\tRwIm3DVertex *pVerts;\n\n\t\t\t\t\t\tRenderBuffer::StartStoring(3 * (numVerts3 - 2), numVerts3, &pIndexes, &pVerts);\n\n\t\t\t\t\t\tASSERT(pIndexes != nil);\n\t\t\t\t\t\tASSERT(pVerts != nil);\n\n\n\t\t\t\t\t\tfor ( int32 j = 0; j < numVerts3; j++ )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tint32 in = j + 10;\n\n\t\t\t\t\t\t\tRwIm3DVertexSetRGBA(&pVerts[j], nRed, nGreen, nBlue, nIntensity);\n\t\t\t\t\t\t\tRwIm3DVertexSetU   (&pVerts[j], Texture[in].x*fScale);\n\t\t\t\t\t\t\tRwIm3DVertexSetV   (&pVerts[j], Texture[in].y*fScale);\n\t\t\t\t\t\t\tRwIm3DVertexSetPos (&pVerts[j], List[in].x, List[in].y, List[in].z + 0.03f);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tfor ( int32 j = 0; j < 3*(numVerts3 - 2); j++ )\n\t\t\t\t\t\t\tpIndexes[j] = ShadowIndexList[j];\n\n\t\t\t\t\t\tRenderBuffer::StopStoring();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n\ntypedef struct _ProjectionParam\n{\n\tRwV3d               at;     /* Camera at vector */\n\tRwMatrix            invMatrix; /* Transforms to shadow camera space */\n\tRwUInt8             shadowValue; /* Shadow opacity value */\n\tRwBool              fade;   /* Shadow fades with distance */\n\tRwUInt32            numIm3DBatch; /* Number of buffer flushes */\n\tRwMatrix            entityMatrix;\n}\nProjectionParam;\n\nRwV3d *ShadowRenderTriangleCB(RwV3d *points, RwV3d *normal, ProjectionParam *param)\n{\n\tRwV3d vIn[3];\n\tRwV3d vShad[3];\n\t\n\tRwV3dTransformPoints(&vIn[0], points, 3, &param->entityMatrix);\n\t\n\t/*\n\t *  Reject backfacing triangles\n\t *  This reject the triangles parallel to the light as well \n\t */\n\tif (RwV3dDotProduct(normal, &param->at) > 0.0f)\n\t{\n\t\treturn points;\n\t}\n\t\n\tRwV3dTransformPoints(&vShad[0], &vIn[0], 3, &param->invMatrix);\n\t\n\t/*\n\t *  Reject triangles behind the camera (z test). Note that any world \n\t *  triangles lying in front of the camera but before the object may \n\t *  have a shadow applied. To minimize such artefacts, this test could \n\t *  be modified to use a specific value rather than 0.0f, perhaps\n\t *  to reject triangles behind the center plane of the object.\n\t *\n\t *  Reject triangles that lie entirely outside the shadow texture range\n\t *  (x,y test).\n\t */\n\tif (((vShad[0].z < 0.0f) && (vShad[1].z < 0.0f)\n\t\t&& (vShad[2].z < 0.0f)) || ((vShad[0].x < 0.0f)\n\t\t\t\t\t\t\t\t\t&& (vShad[1].x < 0.0f)\n\t\t\t\t\t\t\t\t\t&& (vShad[2].x < 0.0f))\n\t\t|| ((vShad[0].x > 1.0f) && (vShad[1].x > 1.0f)\n\t\t\t&& (vShad[2].x > 1.0f)) || ((vShad[0].y < 0.0f)\n\t\t\t\t\t\t\t\t\t\t&& (vShad[1].y < 0.0f)\n\t\t\t\t\t\t\t\t\t\t&& (vShad[2].y < 0.0f))\n\t\t|| ((vShad[0].y > 1.0f) && (vShad[1].y > 1.0f)\n\t\t\t&& (vShad[2].y > 1.0f)))\n\t{\n\t\treturn points;\n\t}\n\t\n\tRwIm3DVertex *imv = nil;\n\tRwImVertexIndex *imi = nil;\n\t\n\tRenderBuffer::StartStoring(3, 3, &imi, &imv);\n\t\n\t/*\n\t *  Set the immediate mode vertices for this triangle\n\t */\n\t\n\tRwIm3DVertexSetPos(imv, vIn[0].x, vIn[0].y, vIn[0].z);\n\tRwIm3DVertexSetPos(imv + 1, vIn[1].x, vIn[1].y, vIn[1].z);\n\tRwIm3DVertexSetPos(imv + 2, vIn[2].x, vIn[2].y, vIn[2].z);\n\t\n\tRwIm3DVertexSetU(imv, vShad[0].x);\n\tRwIm3DVertexSetU(imv + 1, vShad[1].x);\n\tRwIm3DVertexSetU(imv + 2, vShad[2].x);\n\t\n\tRwIm3DVertexSetV(imv, vShad[0].y);\n\tRwIm3DVertexSetV(imv + 1, vShad[1].y);\n\tRwIm3DVertexSetV(imv + 2, vShad[2].y);\n\t\n\t/*\n\t *  Do we fade out the shadow with distance?\n\t */\n\tif (param->fade)\n\t{\n\t\tRwReal              fadeVal;\n\t\tRwUInt8             val;\n\t\t\n\t\tfadeVal = 1.0f - vShad[0].z * vShad[0].z;\n\t\tval =\n\t\t\t(fadeVal <\n\t\t\t0.0f) ? 0 : (RwUInt8) (fadeVal * param->shadowValue);\n\t\tRwIm3DVertexSetRGBA(imv, val, val, val, val);\n\t\t\n\t\tfadeVal = 1.0f - vShad[1].z * vShad[1].z;\n\t\tval =\n\t\t\t(fadeVal <\n\t\t\t0.0f) ? 0 : (RwUInt8) (fadeVal * param->shadowValue);\n\t\tRwIm3DVertexSetRGBA(imv + 1, val, val, val, val);\n\t\t\n\t\tfadeVal = 1.0f - vShad[2].z * vShad[2].z;\n\t\tval =\n\t\t\t(fadeVal <\n\t\t\t0.0f) ? 0 : (RwUInt8) (fadeVal * param->shadowValue);\n\t\tRwIm3DVertexSetRGBA(imv + 2, val, val, val, val);\n\t}\n\telse\n\t{\n\t\tRwUInt8             val = param->shadowValue;\n\t\t\n\t\tRwIm3DVertexSetRGBA(imv, val, val, val, val);\n\t\tRwIm3DVertexSetRGBA(imv + 1, val, val, val, val);\n\t\tRwIm3DVertexSetRGBA(imv + 2, val, val, val, val);\n\t}\n\n\t/*\n\t *  Update buffer position \n\t */\n\timi[0] = 0;\n\timi[1] = 1;\n\timi[2] = 2;\n\t\n\tRenderBuffer::StopStoring();\n\t\n\treturn points;\n}\n\nvoid\nCShadows::CastShadowEntityXYZ(CEntity *pEntity, CVector *pPosn,\n\t\t\t\t\t\t\t\tfloat fFrontX, float fFrontY, float fSideX, float fSideY,\n\t\t\t\t\t\t\t\tint16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue,\n\t\t\t\t\t\t\t\tfloat fZDistance, float fScale, CPolyBunch **ppPolyBunch, CCutsceneShadow *pShadow)\n{\n\tASSERT(pEntity != nil);\n\tASSERT(pPosn != nil);\n\t\n\tif ( pShadow )\n\t{\n\t\tProjectionParam proj;\n\t\tRwV3d scl;\n\t\tRwV3d tr;\n\t\t\n\t\tCShadowCamera *shadow = pShadow->GetShadowCamera();\n\t\tCColModel *collision  = pEntity->GetColModel();\n\t\t\n\t\tCCollision::CalculateTrianglePlanes(collision);\n\t\t\n\t\tRwMatrix mat;\n\t\tmat = *RwFrameGetMatrix(RwCameraGetFrame(shadow->GetRwCamera()));\n\t\t\n\t\tRwV3d        Xaxis = { 1.0f, 0.0f, 0.0f };\n\n\t\tRwMatrixRotate(&mat, &Xaxis, -45.0f, rwCOMBINEPRECONCAT);\n\t\t\n\t\tproj.at = mat.at;\n\t\tpEntity->GetMatrix().CopyToRwMatrix(&proj.entityMatrix);\n\n\t\tRwMatrixInvert(&proj.invMatrix, &mat);\t\t\n\t\tRwReal radius = RwCameraGetViewWindow(shadow->GetRwCamera())->x;\n\t\t\n\t\tscl.x = scl.y = -0.5f / (radius*0.9f);\n\t\tscl.z = 1.0f / (radius*0.8f);\n\t\tRwMatrixScale(&proj.invMatrix, &scl, rwCOMBINEPOSTCONCAT);\n\t\t\n\t\ttr.x = 0.5f;\n\t\ttr.y = tr.z = 0.0f;\n\t\tRwMatrixTranslate(&proj.invMatrix, &tr, rwCOMBINEPOSTCONCAT);\n\t\t\n\t\tproj.shadowValue = nIntensity;\n\t\tproj.fade = 0;\n\t\t\n\t\tRwMatrix matrix;\n\t\tpEntity->GetMatrix().CopyToRwMatrix(&matrix);\n\t\tRwMatrix invMatrix;\n\t\tRwMatrixInvert(&invMatrix, &matrix);\n\t\t\n\n\t\tCVector center(pShadow->GetBaseSphere().center);\n\t\tcenter += CVector(-fFrontX * 1.1f, -fFrontY * 1.1f, -0.5f);\n\t\t\n\t\tCSphere sphere;\n\t\tsphere.Set(2.0f, center);\n\n\t\tRwV3d point;\n\t\tRwV3dTransformPoints(&point, &center, 1, &invMatrix);\n\t\t\n\t\tCColSphere colSphere;\n\t\tcolSphere.Set(2.0f, CVector(point), 0, 0);\n\t\t\n\t\tint i = 0;\n\t\twhile ( i < collision->numTriangles )\n        {\n\t\t\tCVector p[3];\n\n\t\t\tcollision->GetTrianglePoint(p[0], collision->triangles[i].a);\n\t\t\tcollision->GetTrianglePoint(p[1], collision->triangles[i].b);\n\t\t\tcollision->GetTrianglePoint(p[2], collision->triangles[i].c);\n\t\t\t\n\t\t\tif ( CCollision::TestSphereTriangle(colSphere, collision->vertices, collision->triangles[i], collision->trianglePlanes[i]) )\n\t\t\t{\n\t\t\t\tCVector n(collision->trianglePlanes[i].GetNormalX(), collision->trianglePlanes[i].GetNormalY(), collision->trianglePlanes[i].GetNormalZ());\n\t\t\t\tCVector offset = n * 0.028f;\n\t\t\t\t\n\t\t\t\tp[0] += offset;\n\t\t\t\tp[1] += offset;\n\t\t\t\tp[2] += offset;\n\n\t\t\t\tif ( !ShadowRenderTriangleCB(p, &n, &proj) )\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\ti++;\n\t\t}\n\t}\n}\n\nvoid\nCShadows::UpdateStaticShadows(void)\n{\n\tfor ( int32 i = 0; i < MAX_STATICSHADOWS; i++ )\n\t{\n\t\tif ( aStaticShadows[i].m_pPolyBunch != nil && !aStaticShadows[i].m_bJustCreated\n\t\t\t&& (!aStaticShadows[i].m_bTemp || CTimer::GetTimeInMilliseconds() > aStaticShadows[i].m_nTimeCreated + 5000) )\n\t\t{\n\t\t\taStaticShadows[i].Free();\n\t\t}\n\n\t\taStaticShadows[i].m_bJustCreated = false;\n\t}\n}\n\nvoid\nCShadows::UpdatePermanentShadows(void)\n{\n\tfor ( int32 i = 0; i < MAX_PERMAMENTSHADOWS; i++ )\n\t{\n\t\tif ( aPermanentShadows[i].m_nType != SHADOWTYPE_NONE )\n\t\t{\n\t\t\tuint32 timePassed = CTimer::GetTimeInMilliseconds() - aPermanentShadows[i].m_nTimeCreated;\n\n\t\t\tif ( timePassed >= aPermanentShadows[i].m_nLifeTime )\n\t\t\t\taPermanentShadows[i].m_nType = SHADOWTYPE_NONE;\n\t\t\telse\n\t\t\t{\n\t\t\t\tbool bOk;\n\t\t\t\tif ( timePassed >= (aPermanentShadows[i].m_nLifeTime * 3 / 4) )\n\t\t\t\t{\n\t\t\t\t\t// timePassed == 0                                -> 4\n\t\t\t\t\t// timePassed == aPermanentShadows[i].m_nLifeTime -> 0\n\t\t\t\t\tfloat fMult = 1.0f - float(timePassed - (aPermanentShadows[i].m_nLifeTime * 3 / 4)) / (aPermanentShadows[i].m_nLifeTime / 4);\n\n\t\t\t\t\tbOk = StoreStaticShadow((uintptr)&aPermanentShadows[i],\n\t\t\t\t\t\taPermanentShadows[i].m_nType,\n\t\t\t\t\t\taPermanentShadows[i].m_pTexture,\n\t\t\t\t\t\t&aPermanentShadows[i].m_vecPos,\n\t\t\t\t\t\taPermanentShadows[i].m_vecFront.x,\n\t\t\t\t\t\taPermanentShadows[i].m_vecFront.y,\n\t\t\t\t\t\taPermanentShadows[i].m_vecSide.x,\n\t\t\t\t\t\taPermanentShadows[i].m_vecSide.y,\n\t\t\t\t\t\t(int32)(aPermanentShadows[i].m_nIntensity * fMult),\n\t\t\t\t\t\t(int32)(aPermanentShadows[i].m_nRed       * fMult),\n\t\t\t\t\t\t(int32)(aPermanentShadows[i].m_nGreen     * fMult),\n\t\t\t\t\t\t(int32)(aPermanentShadows[i].m_nBlue      * fMult),\n\t\t\t\t\t\taPermanentShadows[i].m_fZDistance,\n\t\t\t\t\t\t1.0f, 40.0f, false, 0.0f);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tbOk = StoreStaticShadow((uintptr)&aPermanentShadows[i],\n\t\t\t\t\t\taPermanentShadows[i].m_nType,\n\t\t\t\t\t\taPermanentShadows[i].m_pTexture,\n\t\t\t\t\t\t&aPermanentShadows[i].m_vecPos,\n\t\t\t\t\t\taPermanentShadows[i].m_vecFront.x,\n\t\t\t\t\t\taPermanentShadows[i].m_vecFront.y,\n\t\t\t\t\t\taPermanentShadows[i].m_vecSide.x,\n\t\t\t\t\t\taPermanentShadows[i].m_vecSide.y,\n\t\t\t\t\t\taPermanentShadows[i].m_nIntensity,\n\t\t\t\t\t\taPermanentShadows[i].m_nRed,\n\t\t\t\t\t\taPermanentShadows[i].m_nGreen,\n\t\t\t\t\t\taPermanentShadows[i].m_nBlue,\n\t\t\t\t\t\taPermanentShadows[i].m_fZDistance,\n\t\t\t\t\t\t1.0f, 40.0f, false, 0.0f);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif ( !bOk )\n\t\t\t\t\taPermanentShadows[i].m_nType = SHADOWTYPE_NONE;\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nCStaticShadow::Free(void)\n{\n\tif ( m_pPolyBunch != nil )\n\t{\n\t\tCPolyBunch *pFree = CShadows::pEmptyBunchList;\n\t\tCShadows::pEmptyBunchList = m_pPolyBunch;\n\n\t\tCPolyBunch *pUsed = m_pPolyBunch;\n\t\twhile (pUsed->m_pNext != nil)\n\t\t\tpUsed = pUsed->m_pNext;\n\n\t\t\tpUsed->m_pNext = pFree;\n\t}\n\n\tm_pPolyBunch = nil;\n\n\tm_nId = 0;\n}\n\nvoid\nCShadows::CalcPedShadowValues(CVector vecLightDir,\n\t\t\t\t\t\t\tfloat *pfFrontX, float *pfFrontY,\n\t\t\t\t\t\t\tfloat *pfSideX, float *pfSideY,\n\t\t\t\t\t\t\tfloat *pfDisplacementX, float *pfDisplacementY)\n{\n\tASSERT(pfFrontX != nil);\n\tASSERT(pfFrontY != nil);\n\tASSERT(pfSideX != nil);\n\tASSERT(pfSideY != nil);\n\tASSERT(pfDisplacementX != nil);\n\tASSERT(pfDisplacementY != nil);\n\n\t*pfFrontX = -vecLightDir.x;\n\t*pfFrontY = -vecLightDir.y;\n\n\tfloat fDist = Sqrt(*pfFrontY * *pfFrontY + *pfFrontX * *pfFrontX);\n\tfloat fMult = (fDist + 1.0f) / fDist;\n\n\t*pfFrontX *= fMult;\n\t*pfFrontY *= fMult;\n\n\t*pfSideX = -vecLightDir.y / fDist;\n\t*pfSideY =  vecLightDir.x / fDist;\n\n\t*pfDisplacementX = -vecLightDir.x;\n\t*pfDisplacementY = -vecLightDir.y;\n\n\t*pfFrontX /= 2;\n\t*pfFrontY /= 2;\n\n\t*pfSideX /= 2;\n\t*pfSideY /= 2;\n\n\t*pfDisplacementX /= 2;\n\t*pfDisplacementY /= 2;\n\t\n}\n\n\nvoid\nCShadows::RenderExtraPlayerShadows(void)\n{\n#ifdef FIX_BUGS\n\tif (CReplay::IsPlayingBack())\n\t\treturn;\n#endif\n\tif ( CTimeCycle::GetLightShadowStrength() != 0 )\n\t{\n\t\tCVehicle *pCar = FindPlayerVehicle();\n\t\tif ( pCar == nil )\n\t\t\t; // R* cut it out for playerped\n\t\telse\n\t\t{\n\t\t\tif ( pCar->GetModelIndex() != MI_RCBANDIT \n\t\t\t\t&& pCar->GetVehicleAppearance() != VEHICLE_APPEARANCE_BIKE\n\t\t\t\t&& !pCar->IsBike() && !pCar->IsPlane() && !pCar->IsBoat() )\n\t\t\t{\n\t\t\t\tfor ( int32 i = 0; i < CPointLights::NumLights; i++ )\n\t\t\t\t{\n\t\t\t\t\tif (  CPointLights::aLights[i].type == CPointLights::LIGHT_POINT\n\t\t\t\t\t\t&& CPointLights::aLights[i].castExtraShadows\n\t\t\t\t\t\t&&(0.0f != CPointLights::aLights[i].red\n\t\t\t\t\t\t|| 0.0f != CPointLights::aLights[i].green\n\t\t\t\t\t\t|| 0.0f != CPointLights::aLights[i].blue) )\n\t\t\t\t\t{\n\t\t\t\t\t\tCVector vecLight = CPointLights::aLights[i].coors - FindPlayerCoors();\n\t\t\t\t\t\tfloat fLightDist = vecLight.Magnitude();\n\t\t\t\t\t\tfloat fRadius = CPointLights::aLights[i].radius;\n\n\t\t\t\t\t\tif ( fLightDist < fRadius )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// fLightDist == 0       -> 2.0f\n\t\t\t\t\t\t\t// fLightDist == fRadius -> 0.0f\n\t\t\t\t\t\t\tfloat fMult = (1.0f - (2.0f * fLightDist - fRadius) / fRadius);\n\n\t\t\t\t\t\t\tint32 nColorStrength;\n\t\t\t\t\t\t\tif ( fLightDist < fRadius*0.5f )\n\t\t\t\t\t\t\t\tnColorStrength = (5*CTimeCycle::GetLightShadowStrength()/8);\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\tnColorStrength = int32((5*CTimeCycle::GetLightShadowStrength()/8) * fMult);\n\n\t\t\t\t\t\t\tfloat fInv = 1.0f / fLightDist;\n\t\t\t\t\t\t\tvecLight.x *= fInv;\n\t\t\t\t\t\t\tvecLight.y *= fInv;\n\t\t\t\t\t\t\tvecLight.z *= fInv;\n\n\t\t\t\t\t\t\tCVector shadowPos = pCar->GetPosition();\n\n\t\t\t\t\t\t\tshadowPos.x -= vecLight.x * 1.2f;\n\t\t\t\t\t\t\tshadowPos.y -= vecLight.y * 1.2f;\n\n\t\t\t\t\t\t\tfloat fVehicleWidth   = pCar->GetColModel()->boundingBox.GetSize().x;\n\t\t\t\t\t\t\tfloat fVehicleHeight  = pCar->GetColModel()->boundingBox.GetSize().y;\n\n\t\t\t\t\t\t\tshadowPos.x -= ((fVehicleHeight/2) - pCar->GetColModel()->boundingBox.max.y)\n\t\t\t\t\t\t\t\t\t\t\t* pCar->GetForward().x;\n\n\t\t\t\t\t\t\tshadowPos.y -= ((fVehicleHeight/2) - pCar->GetColModel()->boundingBox.max.y)\n\t\t\t\t\t\t\t\t\t\t\t* pCar->GetForward().y;\n\n\t\t\t\t\t\t\tif ( pCar->GetUp().z > 0.0f )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tStoreShadowToBeRendered(SHADOWTYPE_DARK, gpShadowCarTex, &shadowPos,\n\t\t\t\t\t\t\t\t\tpCar->GetForward().x * (fVehicleHeight/2),\n\t\t\t\t\t\t\t\t\tpCar->GetForward().y * (fVehicleHeight/2),\n\t\t\t\t\t\t\t\t\tpCar->GetRight().x   * (fVehicleWidth/3),\n\t\t\t\t\t\t\t\t\tpCar->GetRight().y   * (fVehicleWidth/3),\n\t\t\t\t\t\t\t\t\tnColorStrength, 0, 0, 0,\n\t\t\t\t\t\t\t\t\t4.5f, false, 1.0f, nil, false);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tStoreShadowToBeRendered(SHADOWTYPE_DARK, gpShadowCarTex, &shadowPos,\n\t\t\t\t\t\t\t\t\tpCar->GetForward().x * (fVehicleHeight/2),\n\t\t\t\t\t\t\t\t\tpCar->GetForward().y * (fVehicleHeight/2),\n\t\t\t\t\t\t\t\t\t-pCar->GetRight().x  * (fVehicleWidth/2),\n\t\t\t\t\t\t\t\t\t-pCar->GetRight().y  * (fVehicleWidth/2),\n\t\t\t\t\t\t\t\t\tnColorStrength, 0, 0, 0,\n\t\t\t\t\t\t\t\t\t4.5f, false, 1.0f, nil, false);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nCShadows::TidyUpShadows(void)\n{\n\tfor ( int32 i = 0; i < MAX_PERMAMENTSHADOWS; i++ )\n\t\taPermanentShadows[i].m_nType = SHADOWTYPE_NONE;\n}\n\nvoid\nCShadows::RenderIndicatorShadow(uint32 nID, uint8 ShadowType, RwTexture *pTexture,  CVector *pPosn,\n\t\t\t\t\t\t\t\tfloat fFrontX, float fFrontY, float fSideX, float fSideY,\n\t\t\t\t\t\t\t\tint16 nIntensity)\n{\n\tASSERT(pPosn != nil);\n\n\tC3dMarkers::PlaceMarkerSet(nID, MARKERTYPE_CYLINDER, *pPosn, Max(fFrontX, -fSideY),\n\t\tSPHERE_MARKER_R, SPHERE_MARKER_G, SPHERE_MARKER_B,\n\t\tSPHERE_MARKER_A, SPHERE_MARKER_PULSE_PERIOD, 0.2f, 0);\n}\n"
  },
  {
    "path": "src/render/Shadows.h",
    "content": "#pragma once\n\n#define MAX_STOREDSHADOWS    48\n#define MAX_POLYBUNCHES      380\n#define MAX_STATICSHADOWS    48\n#define MAX_PERMAMENTSHADOWS 48\n\n\n\nclass CEntity;\nclass CPtrList;\nclass CAutomobile;\nclass CVehicle;\nclass CPed;\nclass CCutsceneShadow;\nclass CCutsceneObject;\n\nenum eShadowType\n{\n\tSHADOWTYPE_NONE = 0,\n\tSHADOWTYPE_DARK,\n\tSHADOWTYPE_ADDITIVE,\n\tSHADOWTYPE_INVCOLOR\n};\n\nenum eShadowTextureType\n{\n    SHADOWTEX_NONE = 0,\n    SHADOWTEX_CAR,\n    SHADOWTEX_PED,\n    SHADOWTEX_EXPLOSION,\n    SHADOWTEX_HELI,\n    SHADOWTEX_HEADLIGHTS,\n    SHADOWTEX_BLOOD\n};\n\nenum VEH_SHD_TYPE\n{\n\tVEH_SHD_TYPE_CAR = 0,\n\tVEH_SHD_TYPE_BIKE,\n\tVEH_SHD_TYPE_HELI,\n\tVEH_SHD_TYPE_SEAPLANE,\n\tVEH_SHD_TYPE_RCPLANE,\n};\n\n\nclass CStoredShadow\n{\npublic:\n\tCVector m_vecPos;\n\tCVector2D m_vecFront;\n\tCVector2D m_vecSide;\n\tfloat m_fZDistance;\n\tfloat m_fScale;\n\tRwTexture *m_pTexture;\n\tCCutsceneShadow *m_pCutsceneShadow;\n\tint16 m_nIntensity;\n\tuint8 m_ShadowType;\n\tuint8 m_nRed;\n\tuint8 m_nGreen;\n\tuint8 m_nBlue;\n\tstruct\n\t{\n\t\tuint8 bDrawOnWater      : 1;\n\t\tuint8 bRendered         : 1;\n\t\tuint8 bDrawOnBuildings  : 1;\n\t} m_nFlags;\n\t\n\n    CStoredShadow()\n\t{  }\n};\n\nVALIDATE_SIZE(CStoredShadow, 0x30);\n\nclass CPolyBunch\n{\npublic:\n\tCVector m_aVerts[7];\n\tCPolyBunch *m_pNext;\n\tint16 m_nNumVerts;\n\tuint8 m_aU[7];\n\tuint8 m_aV[7];\n\n    CPolyBunch()\n\t{  }\n};\n\nVALIDATE_SIZE(CPolyBunch, 0x6C);\n\nclass CStaticShadow\n{\npublic:\n\tuint32 m_nId;\n\tCPolyBunch *m_pPolyBunch;\n\tuint32 m_nTimeCreated;\n\tCVector m_vecPosn;\n\tCVector2D m_vecFront;\n\tCVector2D m_vecSide;\n\tfloat m_fZDistance;\n\tfloat m_fScale;\n\tRwTexture *m_pTexture;\n\tint16 m_nIntensity; // unsigned ?\n\tuint8 m_nType;\n\tuint8 m_nRed;\n\tuint8 m_nGreen;\n\tuint8 m_nBlue;\n\tbool m_bJustCreated;\n\tbool m_bRendered;\n\tbool m_bTemp;\n\t\n\n\tCStaticShadow()\n\t{  }\n\n\tvoid Free();\n};\n\nVALIDATE_SIZE(CStaticShadow, 0x40);\n\nclass CPermanentShadow\n{\npublic:\n\tCVector m_vecPos;\n\tCVector2D m_vecFront;\n\tCVector2D m_vecSide;\n\tfloat m_fZDistance;\n\tfloat m_fScale;\n\tuint32 m_nTimeCreated;\n\tuint32 m_nLifeTime;\n\tRwTexture *m_pTexture;\n\tint16 m_nIntensity;\n\tuint8 m_nType;\t// eShadowType\n\tuint8 m_nRed;\n\tuint8 m_nGreen;\n\tuint8 m_nBlue;\n\n\tCPermanentShadow()\n\t{  }\n};\n\nVALIDATE_SIZE(CPermanentShadow, 0x38);\n\nclass CShadows\n{\npublic:\n\tstatic int16            ShadowsStoredToBeRendered;\n\tstatic CStoredShadow    asShadowsStored  [MAX_STOREDSHADOWS];\n\tstatic CPolyBunch       aPolyBunches     [MAX_POLYBUNCHES];\n\tstatic CStaticShadow    aStaticShadows   [MAX_STATICSHADOWS];\n\tstatic CPolyBunch      *pEmptyBunchList;\n\tstatic CPermanentShadow aPermanentShadows[MAX_PERMAMENTSHADOWS];\n\n\tstatic void Init                           (void);\n\tstatic void Shutdown                       (void);\n\tstatic void AddPermanentShadow             (            uint8 ShadowType, RwTexture *pTexture, CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue, float fZDistance, uint32 nTime, float fScale);\n\t\t\t\t\t\t\t\t\t\t\t   \n\tstatic bool StoreStaticShadow              (uint32 nID, uint8 ShadowType, RwTexture *pTexture, Const CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue, float fZDistance,               float fScale, float fDrawDistance, bool bTempShadow, float fUpDistance);\n\tstatic void StoreShadowToBeRendered        (            uint8 ShadowType,                      CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue);\n\tstatic void StoreShadowToBeRendered        (            uint8 ShadowType, RwTexture *pTexture, CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue, float fZDistance, bool bDrawOnWater, float fScale, CCutsceneShadow *pShadow, bool bDrawOnBuildings);\n\tstatic void StoreShadowForVehicle          (CVehicle *pCar, VEH_SHD_TYPE type);\n\tstatic void StoreCarLightShadow            (CVehicle *pCar, int32 nID, RwTexture *pTexture, CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY,                   uint8 nRed, uint8 nGreen, uint8 nBlue, float fMaxViewAngle);\n\tstatic void StoreShadowForPed              (CPed        *pPed,     float fDisplacementX, float fDisplacementY, float fFrontX, float fFrontY, float fSideX, float fSideY);\n\tstatic void StoreShadowForPedObject        (CEntity *pPedObject,   float fDisplacementX, float fDisplacementY, float fFrontX, float fFrontY, float fSideX, float fSideY);\n\tstatic void StoreShadowForCutscenePedObject(CCutsceneObject *pObject, float fDisplacementX, float fDisplacementY, float fFrontX, float fFrontY, float fSideX, float fSideY);\n\tstatic void StoreShadowForTree             (CEntity *pTree);\n\tstatic void StoreShadowForPole             (CEntity *pPole, float fOffsetX, float fOffsetY, float fOffsetZ, float fPoleHeight, float fPoleWidth, uint32 nID);\n\tstatic void SetRenderModeForShadowType     (uint8 ShadowType);\n\tstatic void RenderStoredShadows            (void);\n\tstatic void RenderStaticShadows            (void);\n\t\n\tstatic void GeneratePolysForStaticShadow   (int16 nStaticShadowID);\n\tstatic void CastShadowSectorList           (CPtrList &PtrList, float fStartX, float fStartY, float fEndX, float fEndY,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t     CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue, float fZDistance,               float fScale, CPolyBunch **ppPolyBunch);\n\t\n\tstatic void CastPlayerShadowSectorList     (CPtrList &PtrList, float fStartX, float fStartY, float fEndX, float fEndY,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue, float fZDistance,               float fScale, CPolyBunch **ppPolyBunch);\n\n\tstatic void CastCutsceneShadowSectorList   (CPtrList &PtrList, float fStartX, float fStartY, float fEndX, float fEndY,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue, float fZDistance,               float fScale, CPolyBunch **ppPolyBunch, CCutsceneShadow *pShadow);\n\t\t\t\t\t\t\t\t\n\tstatic void CastShadowEntityXY             (CEntity *pEntity,  float fStartX, float fStartY, float fEndX, float fEndY,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t     CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue, float fZDistance,               float fScale, CPolyBunch **ppPolyBunch);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \n\tstatic void CastShadowEntityXYZ            (CEntity *pEntity, CVector *pPosn,                                float fFrontX, float fFrontY, float fSideX, float fSideY, int16 nIntensity, uint8 nRed, uint8 nGreen, uint8 nBlue, float fZDistance,               float fScale, CPolyBunch **ppPolyBunch, CCutsceneShadow *pShadow);\n\t\t\t\t\t\t\t\t\n\tstatic void UpdateStaticShadows            (void);\n\tstatic void UpdatePermanentShadows         (void);\n\tstatic void CalcPedShadowValues            (CVector vecLightDir, float *pfFrontX, float *pfFrontY, float *pfSideX, float *pfSideY, float *pfDisplacementX, float *pfDisplacementY);\n\tstatic void RenderExtraPlayerShadows       (void);\n\tstatic void TidyUpShadows                  (void);\n\tstatic void RenderIndicatorShadow          (uint32 nID, uint8 ShadowType, RwTexture *pTexture,  CVector *pPosn, float fFrontX, float fFrontY, float fSideX, float fSideY, int16 nIntensity);\n};\n\nextern RwTexture *gpShadowCarTex;\nextern RwTexture *gpShadowPedTex;\nextern RwTexture *gpShadowHeliTex;\nextern RwTexture *gpShadowBikeTex;\nextern RwTexture *gpShadowBaronTex;\nextern RwTexture *gpShadowExplosionTex;\nextern RwTexture *gpShadowHeadLightsTex;\nextern RwTexture *gpOutline1Tex;\nextern RwTexture *gpOutline2Tex;\nextern RwTexture *gpOutline3Tex;\nextern RwTexture *gpBloodPoolTex;\nextern RwTexture *gpReflectionTex;\nextern RwTexture *gpWalkDontTex;\nextern RwTexture *gpCrackedGlassTex;\nextern RwTexture *gpPostShadowTex;\nextern RwTexture *gpGoalTex;\n"
  },
  {
    "path": "src/render/Skidmarks.cpp",
    "content": "#include \"common.h\"\n\n#include \"main.h\"\n#include \"TxdStore.h\"\n#include \"Timer.h\"\n#include \"Replay.h\"\n#include \"Skidmarks.h\"\n\nCSkidmark CSkidmarks::aSkidmarks[NUMSKIDMARKS];\n\nRwImVertexIndex SkidmarkIndexList[SKIDMARK_LENGTH * 6];\nRwIm3DVertex SkidmarkVertices[SKIDMARK_LENGTH * 2];\nRwTexture *gpSkidTex;\n\nvoid\nCSkidmarks::Init(void)\n{\n\tint i, ix, slot;\n\tCTxdStore::PushCurrentTxd();\n\tslot = CTxdStore::FindTxdSlot(\"particle\");\n\tCTxdStore::SetCurrentTxd(slot);\n\tgpSkidTex = RwTextureRead(\"particleskid\", nil);\n\tCTxdStore::PopCurrentTxd();\n\n\tfor(i = 0; i < NUMSKIDMARKS; i++){\n\t\taSkidmarks[i].m_state = 0;\n\t\taSkidmarks[i].m_wasUpdated = false;\n\t}\n\n\tix = 0;\n\tfor(i = 0; i < SKIDMARK_LENGTH; i++){\n\t\tSkidmarkIndexList[i*6+0] = ix+0;\n\t\tSkidmarkIndexList[i*6+1] = ix+2;\n\t\tSkidmarkIndexList[i*6+2] = ix+1;\n\t\tSkidmarkIndexList[i*6+3] = ix+1;\n\t\tSkidmarkIndexList[i*6+4] = ix+2;\n\t\tSkidmarkIndexList[i*6+5] = ix+3;\n\t\tix += 2;\n\t}\n}\n\nvoid\nCSkidmarks::Shutdown(void)\n{\n\tRwTextureDestroy(gpSkidTex);\n\tgpSkidTex = nil;\n}\n\nvoid\nCSkidmarks::Clear(void)\n{\n\tint i;\n\tfor(i = 0; i < NUMSKIDMARKS; i++){\n\t\taSkidmarks[i].m_state = 0;\n\t\taSkidmarks[i].m_wasUpdated = false;\n\t}\n}\n\nvoid\nCSkidmarks::Update(void)\n{\n\tint i;\n\tuint32 t1 = CTimer::GetTimeInMilliseconds() + 2500;\n\tuint32 t2 = CTimer::GetTimeInMilliseconds() + 5000;\n\tuint32 t3 = CTimer::GetTimeInMilliseconds() + 10000;\n\tuint32 t4 = CTimer::GetTimeInMilliseconds() + 20000;\n\tfor(i = 0; i < NUMSKIDMARKS; i++){\n\t\tswitch(aSkidmarks[i].m_state){\n\t\tcase 1:\n\t\t\tif(!aSkidmarks[i].m_wasUpdated){\n\t\t\t\t// Didn't continue this one last time, so finish it and set fade times\n\t\t\t\taSkidmarks[i].m_state = 2;\n\t\t\t\tif(aSkidmarks[i].m_last < 4){\n\t\t\t\t\taSkidmarks[i].m_fadeStart = t1;\n\t\t\t\t\taSkidmarks[i].m_fadeEnd = t2;\n\t\t\t\t}else if(aSkidmarks[i].m_last < 9){\n\t\t\t\t\taSkidmarks[i].m_fadeStart = t2;\n\t\t\t\t\taSkidmarks[i].m_fadeEnd = t3;\n\t\t\t\t}else{\n\t\t\t\t\taSkidmarks[i].m_fadeStart = t3;\n\t\t\t\t\taSkidmarks[i].m_fadeEnd = t4;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\tcase 2:\n\t\t\tif(CTimer::GetTimeInMilliseconds() > aSkidmarks[i].m_fadeEnd)\n\t\t\t\taSkidmarks[i].m_state = 0;\n\t\t\tbreak;\n\t\t}\n\t\taSkidmarks[i].m_wasUpdated = false;\n\t}\n}\n\nvoid\nCSkidmarks::Render(void)\n{\n\tint i, j;\n\n\tPUSH_RENDERGROUP(\"CSkidmarks::Render\");\n\n\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);\n\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);\n\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);\n\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);\n\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpSkidTex));\n\n\tfor(i = 0; i < NUMSKIDMARKS; i++){\n\t\tif(aSkidmarks[i].m_state == 0 || aSkidmarks[i].m_last < 1)\n\t\t\tcontinue;\n\n\t\tCRGBA color(0, 0, 0, 255);\n\t\tswitch(aSkidmarks[i].m_type){\n\t\tcase SKIDMARK_NORMAL: color = CRGBA(0, 0, 0, 255); break;\n\t\tcase SKIDMARK_MUDDY: color = CRGBA(90, 62, 9, 255); break;\n\t\tcase SKIDMARK_SANDY: color = CRGBA(108, 108, 96, 255); break;\n\t\tcase SKIDMARK_BLOODY: color = CRGBA(132, 34, 11, 255); break;\n\t\t}\n\n\t\tuint32 fade, alpha;\n\t\tif(aSkidmarks[i].m_state == 1 || CTimer::GetTimeInMilliseconds() < aSkidmarks[i].m_fadeStart)\n\t\t\tfade = 255;\n\t\telse\n\t\t\tfade = 255*(aSkidmarks[i].m_fadeEnd - CTimer::GetTimeInMilliseconds()) / (aSkidmarks[i].m_fadeEnd - aSkidmarks[i].m_fadeStart);\n\n\t\tfor(j = 0; j <= aSkidmarks[i].m_last; j++){\n\t\t\talpha = 128;\n\t\t\tif(j == 0 || j == aSkidmarks[i].m_last && aSkidmarks[i].m_state == 2)\n\t\t\t\talpha = 0;\n\t\t\talpha = alpha*fade/256;\n\n\t\t\tCVector p1 = aSkidmarks[i].m_pos[j];\n\t\t\tp1.x += aSkidmarks[i].m_sideX[j];\n\t\t\tp1.y += aSkidmarks[i].m_sideY[j];\n\t\t\tCVector p2 = aSkidmarks[i].m_pos[j];\n\t\t\tp2.x -= aSkidmarks[i].m_sideX[j];\n\t\t\tp2.y -= aSkidmarks[i].m_sideY[j];\n\t\t\tRwIm3DVertexSetRGBA(&SkidmarkVertices[j*2+0], color.red, color.green, color.blue, alpha);\n\t\t\tRwIm3DVertexSetPos(&SkidmarkVertices[j*2+0], p1.x, p1.y, p1.z+0.1f);\n\t\t\tRwIm3DVertexSetU(&SkidmarkVertices[j*2+0], 0.0f);\n\t\t\tRwIm3DVertexSetV(&SkidmarkVertices[j*2+0], j*5.01f);\n\t\t\tRwIm3DVertexSetRGBA(&SkidmarkVertices[j*2+1], color.red, color.green, color.blue, alpha);\n\t\t\tRwIm3DVertexSetPos(&SkidmarkVertices[j*2+1], p2.x, p2.y, p2.z+0.1f);\n\t\t\tRwIm3DVertexSetU(&SkidmarkVertices[j*2+1], 1.0f);\n\t\t\tRwIm3DVertexSetV(&SkidmarkVertices[j*2+1], j*5.01f);\n\t\t}\n\n\t\tLittleTest();\n\t\tif(RwIm3DTransform(SkidmarkVertices, 2*(aSkidmarks[i].m_last+1), nil, rwIM3D_VERTEXUV)){\n\t\t\tRwIm3DRenderIndexedPrimitive(rwPRIMTYPETRILIST, SkidmarkIndexList, 6*aSkidmarks[i].m_last);\n\t\t\tRwIm3DEnd();\n\t\t}\n\t}\n\n\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);\n\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);\n\tRwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);\n\n\tPOP_RENDERGROUP();\n}\n\nvoid\nCSkidmarks::RegisterOne(uintptr id, const CVector &pos, float fwdX, float fwdY, bool *isMuddy, bool *isBloody)\n{\n\teSkidmarkType type;\n\tif(*isBloody)\n\t\ttype = SKIDMARK_BLOODY;\n\telse if(*isMuddy)\n\t\ttype = SKIDMARK_MUDDY;\n\telse\n\t\ttype = SKIDMARK_NORMAL;\n\tRegisterOne(id, pos, fwdX, fwdY, type, isBloody);\n}\n\nvoid\nCSkidmarks::RegisterOne(uintptr id, const CVector &pos, float fwdX, float fwdY, eSkidmarkType type, bool *isBloody)\n{\n\tint i;\n\tCVector2D fwd(fwdX, fwdY);\n\n\tif(CReplay::IsPlayingBack())\n\t\treturn;\n\n\t// Find a skidmark to continue\n\tfor(i = 0; i < NUMSKIDMARKS; i++)\n\t\tif(aSkidmarks[i].m_state == 1 && aSkidmarks[i].m_id == id)\n\t\t\tbreak;\n\n\tif(i < NUMSKIDMARKS){\n\t\t// Continue this one\n\n\t\tif((aSkidmarks[i].m_type==SKIDMARK_BLOODY) != *isBloody){\n\t\t\t// Blood-status changed, end this one\n\t\t\taSkidmarks[i].m_state = 2;\n\t\t\taSkidmarks[i].m_fadeStart = CTimer::GetTimeInMilliseconds() + 10000;\n\t\t\taSkidmarks[i].m_fadeEnd = CTimer::GetTimeInMilliseconds() + 20000;\n\t\t\treturn;\n\t\t}\n\n\t\taSkidmarks[i].m_wasUpdated = true;\n\n\t\tif(CTimer::GetTimeInMilliseconds() - aSkidmarks[i].m_lastUpdate <= 100){\n\t\t\t// Last update was recently, just change last coords\n\t\t\taSkidmarks[i].m_pos[aSkidmarks[i].m_last] = pos;\n\t\t\treturn;\n\t\t}\n\t\taSkidmarks[i].m_lastUpdate = CTimer::GetTimeInMilliseconds();\n\n\t\tif(aSkidmarks[i].m_last >= SKIDMARK_LENGTH-1){\n\t\t\t// No space to continue, end it\n\t\t\taSkidmarks[i].m_state = 2;\n\t\t\taSkidmarks[i].m_fadeStart = CTimer::GetTimeInMilliseconds() + 10000;\n\t\t\taSkidmarks[i].m_fadeEnd = CTimer::GetTimeInMilliseconds() + 20000;\n\t\t\t*isBloody = false;\t// stpo blood marks at end\n\t\t\treturn;\n\t\t}\n\t\taSkidmarks[i].m_last++;\n\n\t\taSkidmarks[i].m_pos[aSkidmarks[i].m_last] = pos;\n\n\t\tCVector2D right(aSkidmarks[i].m_pos[aSkidmarks[i].m_last].y - aSkidmarks[i].m_pos[aSkidmarks[i].m_last - 1].y,\n\t\t                aSkidmarks[i].m_pos[aSkidmarks[i].m_last - 1].x - aSkidmarks[i].m_pos[aSkidmarks[i].m_last].x);\n\n\t\tright.Normalise();\n\t\tfwd.Normalise();\n\t\tfloat turn = DotProduct2D(fwd, right);\n\t\tturn = Abs(turn) + 1.0f;\n\t\taSkidmarks[i].m_sideX[aSkidmarks[i].m_last] = right.x * turn * 0.125f;\n\t\taSkidmarks[i].m_sideY[aSkidmarks[i].m_last] = right.y * turn * 0.125f;\n\t\tif(aSkidmarks[i].m_last == 1){\n\t\t\taSkidmarks[i].m_sideX[0] = aSkidmarks[i].m_sideX[1];\n\t\t\taSkidmarks[i].m_sideY[0] = aSkidmarks[i].m_sideY[1];\n\t\t}\n\n\t\tif(aSkidmarks[i].m_last > 8)\n\t\t\t*isBloody = false;\t// stop blood marks after 8\n\t\treturn;\n\t}\n\n\t// Start a new one\n\tfor(i = 0; i < NUMSKIDMARKS; i++)\n\t\tif(aSkidmarks[i].m_state == 0)\n\t\t\tbreak;\n\tif(i < NUMSKIDMARKS){\n\t\t// Found a free slot\n\t\taSkidmarks[i].m_state = 1;\n\t\taSkidmarks[i].m_id = id;\n\t\taSkidmarks[i].m_pos[0] = pos;\n\t\taSkidmarks[i].m_sideX[0] = 0.0f;\n\t\taSkidmarks[i].m_sideY[0] = 0.0f;\n\t\taSkidmarks[i].m_wasUpdated = true;\n\t\taSkidmarks[i].m_last = 0;\n\t\taSkidmarks[i].m_lastUpdate = CTimer::GetTimeInMilliseconds() - 1000;\n\t\tif(*isBloody)\n\t\t\taSkidmarks[i].m_type = SKIDMARK_BLOODY;\n\t\telse\n\t\t\taSkidmarks[i].m_type = type;\n\t}else\n\t\t*isBloody = false;\t// stop blood marks if no space\n}\n"
  },
  {
    "path": "src/render/Skidmarks.h",
    "content": "#pragma once\n\nenum { SKIDMARK_LENGTH = 16 };\n\nenum eSkidmarkType\n{\n\tSKIDMARK_NORMAL,\n\tSKIDMARK_MUDDY,\n\tSKIDMARK_SANDY,\n\tSKIDMARK_BLOODY\n};\n\nclass CSkidmark\n{\npublic:\n\tCVector m_pos[SKIDMARK_LENGTH];\n\tfloat m_sideX[SKIDMARK_LENGTH];\n\tfloat m_sideY[SKIDMARK_LENGTH];\n\tuintptr m_id;\n\tuint32 m_lastUpdate;\n\tuint32 m_fadeStart;\n\tuint32 m_fadeEnd;\n\tuint32 m_type;\n\tint16 m_last;\n\tuint8 m_state;\n\tbool m_wasUpdated;\n};\n\nclass CSkidmarks\n{\n\tstatic CSkidmark aSkidmarks[NUMSKIDMARKS];\npublic:\n\n\tstatic void Init(void);\n\tstatic void Shutdown(void);\n\tstatic void Clear(void);\n\tstatic void Update(void);\n\tstatic void Render(void);\n\tstatic void RegisterOne(uintptr id, const CVector &pos, float fwdX, float fwdY, eSkidmarkType type, bool *isBloody);\n\tstatic void RegisterOne(uintptr id, const CVector &pos, float fwdX, float fwdY, bool *isMuddy, bool *isBloody);\n};\n"
  },
  {
    "path": "src/render/SpecialFX.cpp",
    "content": "#include \"common.h\"\n\n#include \"SpecialFX.h\"\n#include \"RenderBuffer.h\"\n#include \"Timer.h\"\n#include \"Sprite.h\"\n#include \"Font.h\"\n#include \"Text.h\"\n#include \"TxdStore.h\"\n#include \"FileMgr.h\"\n#include \"FileLoader.h\"\n#include \"Timecycle.h\"\n#include \"Lights.h\"\n#include \"ModelIndices.h\"\n#include \"VisibilityPlugins.h\"\n#include \"World.h\"\n#include \"PlayerPed.h\"\n#include \"Particle.h\"\n#include \"Shadows.h\"\n#include \"General.h\"\n#include \"Camera.h\"\n#include \"Shadows.h\"\n#include \"main.h\"\n#include \"ColStore.h\"\n#include \"Coronas.h\"\n#include \"Script.h\"\n#include \"DMAudio.h\"\n\nRwIm3DVertex StreakVertices[4];\nRwImVertexIndex StreakIndexList[12];\n\nRwIm3DVertex TraceVertices[10];\nstatic RwImVertexIndex TraceIndexList[48] = {0, 5, 7, 0, 7, 2, 0, 7, 5, 0, 2, 7, 0, 4, 9, 0,\n\t\t\t\t\t\t\t\t\t\t9, 5, 0, 9, 4, 0, 5, 9, 0, 1, 6, 0, 6, 5, 0, 6,\n\t\t\t\t\t\t\t\t\t\t1, 0, 5, 6, 0, 3, 8, 0, 8, 5, 0, 8, 3, 0, 5, 8 };\n\nbool CSpecialFX::bVideoCam;\nbool CSpecialFX::bLiftCam;\nbool CSpecialFX::bSnapShotActive;\nint32 CSpecialFX::SnapShotFrames;\nstatic RwTexture* gpSmokeTrailTexture;\n\n\nvoid\nCSpecialFX::Init(void)\n{\n\tCBulletTraces::Init();\n\n\tRwIm3DVertexSetU(&TraceVertices[0], 0.0);\n\tRwIm3DVertexSetV(&TraceVertices[0], 0.0);\n\tRwIm3DVertexSetU(&TraceVertices[1], 1.0);\n\tRwIm3DVertexSetV(&TraceVertices[1], 0.0);\n\tRwIm3DVertexSetU(&TraceVertices[2], 1.0);\n\tRwIm3DVertexSetV(&TraceVertices[2], 0.0);\n\tRwIm3DVertexSetU(&TraceVertices[3], 1.0);\n\tRwIm3DVertexSetV(&TraceVertices[3], 0.0);\n\tRwIm3DVertexSetU(&TraceVertices[4], 1.0);\n\tRwIm3DVertexSetV(&TraceVertices[4], 0.0);\n\tRwIm3DVertexSetU(&TraceVertices[5], 0.0);\n\tRwIm3DVertexSetU(&TraceVertices[6], 1.0);\n\tRwIm3DVertexSetU(&TraceVertices[7], 1.0);\n\tRwIm3DVertexSetU(&TraceVertices[8], 1.0);\n\tRwIm3DVertexSetU(&TraceVertices[9], 1.0);\n\n\tRwIm3DVertexSetU(&StreakVertices[0], 0.0f);\n\tRwIm3DVertexSetV(&StreakVertices[0], 0.0f);\n\tRwIm3DVertexSetU(&StreakVertices[1], 1.0f);\n\tRwIm3DVertexSetV(&StreakVertices[1], 0.0f);\n\tRwIm3DVertexSetU(&StreakVertices[2], 0.0f);\n\tRwIm3DVertexSetV(&StreakVertices[2], 0.0f);\n\tRwIm3DVertexSetU(&StreakVertices[3], 1.0f);\n\tRwIm3DVertexSetV(&StreakVertices[3], 0.0f);\n\tStreakIndexList[0] = 0;\n\tStreakIndexList[1] = 1;\n\tStreakIndexList[2] = 2;\n\tStreakIndexList[3] = 1;\n\tStreakIndexList[4] = 3;\n\tStreakIndexList[5] = 2;\n\tStreakIndexList[6] = 0;\n\tStreakIndexList[7] = 2;\n\tStreakIndexList[8] = 1;\n\tStreakIndexList[9] = 1;\n\tStreakIndexList[10] = 2;\n\tStreakIndexList[11] = 3;\n\n\tCMotionBlurStreaks::Init();\n\tCBrightLights::Init();\n\tCShinyTexts::Init();\n\tCMoneyMessages::Init();\n\tC3dMarkers::Init();\n\tCSpecialFX::bSnapShotActive = false;\n\tCSpecialFX::bVideoCam = false;\n\tCSpecialFX::SnapShotFrames = 0;\n\tCSpecialFX::bLiftCam = false;\n\tCTxdStore::PushCurrentTxd();\n\tCTxdStore::SetCurrentTxd(CTxdStore::FindTxdSlot(\"particle\"));\n\tif(gpSmokeTrailTexture == nil)\n\t\tgpSmokeTrailTexture = RwTextureRead(\"smoketrail\", 0);\n\tCTxdStore::PopCurrentTxd();\n}\n\nvoid\nCSpecialFX::AddWeaponStreak(int type)\n{\n\tstatic CMatrix matrix;\n\tCVector start;\n\tCVector end;\n\n\tif (FindPlayerPed() != nil && FindPlayerPed()->m_pWeaponModel != nil) {\n\t\tswitch (type) {\n\t\tcase WEAPONTYPE_BASEBALLBAT:\n\t\t\tmatrix = RwFrameGetLTM(RpAtomicGetFrame(FindPlayerPed()->m_pWeaponModel));\n\t\t\tstart = matrix * CVector(0.02f, 0.05f, 0.07f);\n\t\t\tend = matrix * CVector(0.246f, 0.0325f, 0.796f);\n\t\t\tbreak;\n\t\tcase WEAPONTYPE_GOLFCLUB:\n\t\t\tmatrix = RwFrameGetLTM(RpAtomicGetFrame(FindPlayerPed()->m_pWeaponModel));\n\t\t\tstart = matrix * CVector(0.02f, 0.05f, 0.07f);\n\t\t\tend = matrix * CVector(-0.054f, 0.0325f, 0.796f);\n\t\t\tbreak;\n\t\tcase WEAPONTYPE_KATANA:\n\t\t\tmatrix = RwFrameGetLTM(RpAtomicGetFrame(FindPlayerPed()->m_pWeaponModel));\n\t\t\tstart = matrix * CVector(0.02f, 0.05f, 0.07f);\n\t\t\tend = matrix * CVector(0.096f, -0.0175f, 1.096f);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\treturn;\n\t\t}\n\t\tCMotionBlurStreaks::RegisterStreak((uintptr)FindPlayerPed()->m_pWeaponModel, 100, 100, 100, start, end);\n\t}\n}\n\nRwObject*\nLookForBatCB(RwObject *object, void *data)\n{\n\tstatic CMatrix MatLTM;\n\n\tif(CVisibilityPlugins::GetAtomicModelInfo((RpAtomic*)object) == (CSimpleModelInfo*)data){\n\t\tMatLTM = CMatrix(RwFrameGetLTM(RpAtomicGetFrame((RpAtomic*)object)));\n\t\tCVector p1 = MatLTM * CVector(0.02f, 0.05f, 0.07f);\n\t\tCVector p2 = MatLTM * CVector(0.246f, 0.0325f, 0.796f);\n\t\tCMotionBlurStreaks::RegisterStreak((uintptr)object, 100, 100, 100, p1, p2);\n\t}\n\treturn nil;\n}\n\nvoid\nCSpecialFX::Update(void)\n{\n\tCMotionBlurStreaks::Update();\n\tCBulletTraces::Update();\n}\n\nvoid\nCSpecialFX::Shutdown(void)\n{\n\tC3dMarkers::Shutdown();\n\tif (gpSmokeTrailTexture) {\n\t\tRwTextureDestroy(gpSmokeTrailTexture);\n\t\tgpSmokeTrailTexture = nil;\n\t}\n}\n\nvoid\nCSpecialFX::Render(void)\n{\n\tPUSH_RENDERGROUP(\"CSpecialFX::Render\");\n\tCMotionBlurStreaks::Render();\n\tCBulletTraces::Render();\n\tCBrightLights::Render();\n\tCShinyTexts::Render();\n\tCMoneyMessages::Render();\n#ifdef NEW_RENDERER\n\tif(!(gbNewRenderer && FredIsInFirstPersonCam()))\n#endif\n\tC3dMarkers::Render();\n\tPOP_RENDERGROUP();\n}\n\nvoid\nCSpecialFX::Render2DFXs(void)\n{\n\tif (CSpecialFX::bVideoCam) {\n\t\tCFont::SetScale(SCREEN_SCALE_X(1.5f), SCREEN_SCALE_Y(1.5f));\n\t\tCFont::SetJustifyOff();\n\t\tCFont::SetBackgroundOff();\n\t\tCFont::SetCentreSize(SCREEN_SCALE_X(620.0f)); // unused\n\t\tCFont::SetCentreOff();\n\t\tCFont::SetPropOn();\n\t\tCFont::SetColor(CRGBA(0, 255, 0, 200));\n\t\tCFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD));\n\t\tsprintf(gString, \"%d\", CTimer::GetFrameCounter() & 0x3F); // mb % 63\n\t\tAsciiToUnicode(gString, gUString);\n\t\tCFont::PrintString(SCREEN_WIDTH * 8 / 10, SCREEN_HEIGHT * 8 / 10, gUString);\n\t\tfor (int32 i = 0; i < SCREEN_HEIGHT; i += 4) {\n\t\t\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDONE);\n\t\t\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDONE);\n\t\t\tCSprite2d::Draw2DPolygon(0.0f, i, SCREEN_WIDTH, i, 0.0f, i+1, SCREEN_WIDTH, i+1, CRGBA(0, 100, 0, 100));\n\t\t\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);\n\t\t\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);\n\t\t\tCSprite2d::Draw2DPolygon(0.0f, i+2, SCREEN_WIDTH, i+2, 0.0f, i+3, SCREEN_WIDTH, i+3, CRGBA(0, 0, 0, 150));\n\t\t}\n\t\tint32 tmp = (CTimer::GetTimeInMilliseconds() & 0x7ff) * (SCREEN_HEIGHT + 70.0f) / 2048 - 70.0f; //mb % 2048\n\t\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);\n\t\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);\n\t\tCSprite2d::Draw2DPolygon(0.0, tmp, SCREEN_WIDTH, tmp, 0.0, tmp + 70.0f, SCREEN_WIDTH, tmp + 70.0f , CRGBA(0, 100, 0, 60));\n\t}\n\tif (CSpecialFX::bLiftCam) {\n\t\tCFont::SetScale(SCREEN_SCALE_X(1.5f), SCREEN_SCALE_Y(1.5f));\n\t\tCFont::SetJustifyOff();\n\t\tCFont::SetBackgroundOff();\n\t\tCFont::SetCentreSize(SCREEN_SCALE_X(620.0f)); // unused\n\t\tCFont::SetCentreOff();\n\t\tCFont::SetPropOn();\n\t\tCFont::SetColor(CRGBA(100, 100, 100, 200));\n\t\tCFont::SetFontStyle(FONT_LOCALE(FONT_STANDARD));\n\t\tCFont::PrintString(SCREEN_WIDTH * 8 / 10, SCREEN_HEIGHT * 8 / 10, gUString);\n\t\tfor (int32 i = 0; i < SCREEN_HEIGHT; i += 4) {\n\t\t\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE);\n\t\t\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE);\n\t\t\tCSprite2d::Draw2DPolygon(0.0f, i, SCREEN_WIDTH, i, 0.0f, i + 1, SCREEN_WIDTH, i + 1, CRGBA(100, 100, 100, 100));\n\t\t\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);\n\t\t\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);\n\t\t\tCSprite2d::Draw2DPolygon(0.0f, i + 2, SCREEN_WIDTH, i + 2, 0.0f, i + 3, SCREEN_WIDTH, i + 3, CRGBA(0, 0, 0, 150));\n\t\t}\n\t\tint32 tmp = (CTimer::GetTimeInMilliseconds() & 0x7ff) * (SCREEN_HEIGHT + 70.0f) / 2048 - 70.0f; //mb % 2048\n\t\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);\n\t\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);\n\t\tCSprite2d::Draw2DPolygon(0.0, tmp, SCREEN_WIDTH, tmp, 0.0, tmp + 70.0f, SCREEN_WIDTH, tmp + 70.0f, CRGBA(100, 100, 100, 60));\n\t\tfor (int32 i = 0; i < 200; i++) {\n\t\t\tint32 posX = CGeneral::GetRandomNumber() % (int32)SCREEN_WIDTH;\n\t\t\tint32 posY = CGeneral::GetRandomNumber() % (int32)SCREEN_HEIGHT;\n\t\t\tCSprite2d::DrawRect(CRect(posX, posY + 2, posX+20, posY), CRGBA(255, 255, 255, 64));\n\t\t}\n\t}\n\tif (CSpecialFX::bSnapShotActive) {\n\t\tif (++CSpecialFX::SnapShotFrames > 20) {\n\t\t\tCSpecialFX::bSnapShotActive = false;\n\t\t\tCTimer::SetTimeScale(1.0f);\n\t\t} else {\n\t\t\tCTimer::SetTimeScale(0.0f); //in andro it's 0.00001\n\t\t\tif (CSpecialFX::SnapShotFrames < 10) {\n\t\t\t\tint32 tmp = (255 - 255 * CSpecialFX::SnapShotFrames / 10) * 0.65f;\n\t\t\t\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE);\n\t\t\t\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE);\n\t\t\t\tCSprite2d::Draw2DPolygon(0.0f, 0.0f, SCREEN_WIDTH, 0.0f, 0.0f, SCREEN_HEIGHT, SCREEN_WIDTH, SCREEN_HEIGHT, CRGBA(tmp, tmp, tmp, tmp));\n\t\t\t\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);\n\t\t\t\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);\n\t\t\t}\n\t\t}\n\t}\n}\n\nCRegisteredMotionBlurStreak CMotionBlurStreaks::aStreaks[NUMMBLURSTREAKS];\n\nvoid\nCRegisteredMotionBlurStreak::Update(void)\n{\n\tint i;\n\tbool wasUpdated;\n\tbool lastWasUpdated = false;\n\tfor(i = 2; i > 0; i--){\n\t\tm_pos1[i] = m_pos1[i-1];\n\t\tm_pos2[i] = m_pos2[i-1];\n\t\tm_isValid[i] = m_isValid[i-1];\n\t\twasUpdated = true;\n\t\tif(!lastWasUpdated && !m_isValid[i])\n\t\t\twasUpdated = false;\n\t\tlastWasUpdated = wasUpdated;\n\t}\n\tm_isValid[0] = false;\n\tif(!wasUpdated)\n\t\tm_id = 0;\n}\n\nvoid\nCRegisteredMotionBlurStreak::Render(void)\n{\n\tint i;\n\tint a1, a2;\n\tfor(i = 0; i < 2; i++)\n\t\tif(m_isValid[i] && m_isValid[i+1]){\n\t\t\ta1 = (255/3)*(3-i)/3;\n\t\t\tRwIm3DVertexSetRGBA(&StreakVertices[0], m_red, m_green, m_blue, a1);\n\t\t\tRwIm3DVertexSetRGBA(&StreakVertices[1], m_red, m_green, m_blue, a1);\n\t\t\ta2 = (255/3)*(3-(i+1))/3;\n\t\t\tRwIm3DVertexSetRGBA(&StreakVertices[2], m_red, m_green, m_blue, a2);\n\t\t\tRwIm3DVertexSetRGBA(&StreakVertices[3], m_red, m_green, m_blue, a2);\n\t\t\tRwIm3DVertexSetPos(&StreakVertices[0], m_pos1[i].x, m_pos1[i].y, m_pos1[i].z);\n\t\t\tRwIm3DVertexSetPos(&StreakVertices[1], m_pos2[i].x, m_pos2[i].y, m_pos2[i].z);\n\t\t\tRwIm3DVertexSetPos(&StreakVertices[2], m_pos1[i+1].x, m_pos1[i+1].y, m_pos1[i+1].z);\n\t\t\tRwIm3DVertexSetPos(&StreakVertices[3], m_pos2[i+1].x, m_pos2[i+1].y, m_pos2[i+1].z);\n\t\t\tLittleTest();\n\t\t\tif(RwIm3DTransform(StreakVertices, 4, nil, rwIM3D_VERTEXUV)){\n\t\t\t\tRwIm3DRenderIndexedPrimitive(rwPRIMTYPETRILIST, StreakIndexList, 12);\n\t\t\t\tRwIm3DEnd();\n\t\t\t}\n\t\t}\n}\n\nvoid\nCMotionBlurStreaks::Init(void)\n{\n\tint i;\n\tfor(i = 0; i < NUMMBLURSTREAKS; i++)\n\t\taStreaks[i].m_id = 0;\n}\n\nvoid\nCMotionBlurStreaks::Update(void)\n{\n\tint i;\n\tfor(i = 0; i < NUMMBLURSTREAKS; i++)\n\t\tif(aStreaks[i].m_id != 0)\n\t\t\taStreaks[i].Update();\n}\n\nvoid\nCMotionBlurStreaks::RegisterStreak(uintptr id, uint8 r, uint8 g, uint8 b, CVector p1, CVector p2)\n{\n\tint i;\n\n\tfor(i = 0; i < NUMMBLURSTREAKS; i++){\n\t\tif(aStreaks[i].m_id == id){\n\t\t\t// Found a streak from last frame, update\n\t\t\taStreaks[i].m_red = r;\n\t\t\taStreaks[i].m_green = g;\n\t\t\taStreaks[i].m_blue = b;\n\t\t\taStreaks[i].m_pos1[0] = p1;\n\t\t\taStreaks[i].m_pos2[0] = p2;\n\t\t\taStreaks[i].m_isValid[0] = true;\n\t\t\treturn;\n\t\t}\n\t}\n\n\t// Find free slot\n\tfor(i = 0; aStreaks[i].m_id != 0 ; i++)\n\t\tif(i == NUMMBLURSTREAKS-1)\n\t\t\treturn;\n\n\t// Create a new streak\n\taStreaks[i].m_id = id;\n\taStreaks[i].m_red = r;\n\taStreaks[i].m_green = g;\n\taStreaks[i].m_blue = b;\n\taStreaks[i].m_pos1[0] = p1;\n\taStreaks[i].m_pos2[0] = p2;\n\taStreaks[i].m_isValid[0] = true;\n\taStreaks[i].m_isValid[1] = false;\n\taStreaks[i].m_isValid[2] = false;\n}\n\nvoid\nCMotionBlurStreaks::Render(void)\n{\n\tbool setRenderStates = false;\n\tint i;\n\tfor(i = 0; i < NUMMBLURSTREAKS; i++)\n\t\tif(aStreaks[i].m_id != 0){\n\t\t\tif(!setRenderStates){\n\t\t\t\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);\n\t\t\t\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);\n\t\t\t\tRwRenderStateSet(rwRENDERSTATEFOGENABLE, (void *)TRUE);\n\t\t\t\tRwRenderStateSet(rwRENDERSTATEFOGCOLOR,\n\t\t\t\t\t(void*)RWRGBALONG(CTimeCycle::GetFogRed(), CTimeCycle::GetFogGreen(), CTimeCycle::GetFogBlue(), 255));\n\t\t\t\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);\n\t\t\t\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);\n\t\t\t\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void*)FALSE);\n \t\t\t\tsetRenderStates = true;\n\t\t\t}\n\t\t\taStreaks[i].Render();\n\t\t}\n\tif(setRenderStates){\n\t\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);\n\t\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);\n\t\tRwRenderStateSet(rwRENDERSTATEFOGENABLE, (void *)FALSE);\n\t}\n}\n\n\nCBulletTrace CBulletTraces::aTraces[NUMBULLETTRACES];\n\nvoid CBulletTraces::Init(void)\n{\n\tfor (int i = 0; i < NUMBULLETTRACES; i++)\n\t\taTraces[i].m_bInUse = false;\n}\n\nvoid CBulletTraces::AddTrace(CVector* start, CVector* end, float thickness, uint32 lifeTime, uint8 visibility)\n{\n\tint32 enabledCount;\n\tuint32 modifiedLifeTime;\n\tint32 nextSlot;\n\n\tenabledCount = 0;\n\tfor (int i = 0; i < NUMBULLETTRACES; i++)\n\t\tif (aTraces[i].m_bInUse)\n\t\t\tenabledCount++;\n\tif (enabledCount >= 10)\n\t\tmodifiedLifeTime = lifeTime / 4;\n\telse if (enabledCount >= 5)\n\t\tmodifiedLifeTime = lifeTime / 2;\n\telse\n\t\tmodifiedLifeTime = lifeTime;\n\n\tnextSlot = 0;\n\tfor (int i = 0; nextSlot < NUMBULLETTRACES && aTraces[i].m_bInUse; i++)\n\t\tnextSlot++;\n\tif (nextSlot < 16) {\n\t\taTraces[nextSlot].m_vecStartPos = *start;\n\t\taTraces[nextSlot].m_vecEndPos = *end;\n\t\taTraces[nextSlot].m_bInUse = true;\n\t\taTraces[nextSlot].m_nCreationTime = CTimer::GetTimeInMilliseconds();\n\t\taTraces[nextSlot].m_fVisibility = visibility;\n\t\taTraces[nextSlot].m_fThickness = thickness;\n\t\taTraces[nextSlot].m_nLifeTime = modifiedLifeTime;\n\t}\n\n\tfloat startProjFwd = DotProduct(TheCamera.GetForward(), *start - TheCamera.GetPosition());\n\tfloat endProjFwd = DotProduct(TheCamera.GetForward(), *end - TheCamera.GetPosition());\n\tif (startProjFwd * endProjFwd < 0.0f) { //if one of point behind us and second before us\n\t\tfloat fStartDistFwd = Abs(startProjFwd) / (Abs(startProjFwd) + Abs(endProjFwd));\n\n\t\tfloat startProjUp = DotProduct(TheCamera.GetUp(), *start - TheCamera.GetPosition());\n\t\tfloat endProjUp = DotProduct(TheCamera.GetUp(), *end - TheCamera.GetPosition());\n\t\tfloat distUp = (endProjUp - startProjUp) * fStartDistFwd + startProjUp;\n\n\t\tfloat startProjRight = DotProduct(TheCamera.GetRight(), *start - TheCamera.GetPosition());\n\t\tfloat endProjRight = DotProduct(TheCamera.GetRight(), *end - TheCamera.GetPosition());\n\t\tfloat distRight = (endProjRight - startProjRight) * fStartDistFwd + startProjRight;\n\n\t\tfloat dist = Sqrt(SQR(distUp) + SQR(distRight));\n\t\tif (dist < 2.0f) {\n\t\t\tif(distRight < 0.0f)\n\t\t\t\tDMAudio.PlayFrontEndSound(SOUND_BULLETTRACE_2, 127 * (1.0f - dist * 0.5f));\n\t\t\telse\n\t\t\t\tDMAudio.PlayFrontEndSound(SOUND_BULLETTRACE_1, 127 * (1.0f - dist * 0.5f));\n\t\t}\n\t}\n}\n\nvoid CBulletTraces::AddTrace(CVector* start, CVector* end, int32 weaponType, class CEntity* shooter)\n{\n\tCPhysical* player;\n\tfloat speed;\n\tint16 camMode;\n\t\n\tif (shooter == (CEntity*)FindPlayerPed() || (FindPlayerVehicle() != nil && FindPlayerVehicle() == (CVehicle*)shooter)) {\n\t\tcamMode = TheCamera.Cams[TheCamera.ActiveCam].Mode;\n\t\tif (camMode == CCam::MODE_M16_1STPERSON\n\t\t\t|| camMode == CCam::MODE_CAMERA\n\t\t\t|| camMode == CCam::MODE_SNIPER\n\t\t\t|| camMode == CCam::MODE_M16_1STPERSON_RUNABOUT\n\t\t\t|| camMode == CCam::MODE_ROCKETLAUNCHER\n\t\t\t|| camMode == CCam::MODE_ROCKETLAUNCHER_RUNABOUT\n\t\t\t|| camMode == CCam::MODE_SNIPER_RUNABOUT\n\t\t\t|| camMode == CCam::MODE_HELICANNON_1STPERSON) {\n\n\t\t\tplayer = FindPlayerVehicle() ? (CPhysical*)FindPlayerVehicle() : (CPhysical*)FindPlayerPed();\n\t\t\tspeed = player->m_vecMoveSpeed.Magnitude();\n\t\t\tif (speed < 0.05f)\n\t\t\t\treturn;\n\t\t}\n\t}\n\n\tswitch (weaponType) {\n\tcase WEAPONTYPE_PYTHON:\n\tcase WEAPONTYPE_SHOTGUN:\n\tcase WEAPONTYPE_SPAS12_SHOTGUN:\n\tcase WEAPONTYPE_STUBBY_SHOTGUN:\n\t\tCBulletTraces::AddTrace(start, end, 0.7f, 1000, 200);\n\t\tbreak;\n\tcase WEAPONTYPE_M4:\n\tcase WEAPONTYPE_RUGER:\n\tcase WEAPONTYPE_SNIPERRIFLE:\n\tcase WEAPONTYPE_LASERSCOPE:\n\tcase WEAPONTYPE_M60:\n\tcase WEAPONTYPE_MINIGUN:\n\tcase WEAPONTYPE_HELICANNON:\n\t\tCBulletTraces::AddTrace(start, end, 1.0f, 2000, 220);\n\t\tbreak;\n\tdefault:\n\t\tCBulletTraces::AddTrace(start, end, 0.4f, 750, 150);\n\t\tbreak;\n\t}\n}\n\nvoid CBulletTraces::Render(void)\n{\n\tfor (int i = 0; i < NUMBULLETTRACES; i++) {\n\t\tif (!aTraces[i].m_bInUse)\n\t\t\tcontinue;\n\t\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);\n\t\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);\n\t\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);\n\t\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpSmokeTrailTexture));\n\n\t\tfloat timeAlive = CTimer::GetTimeInMilliseconds() - aTraces[i].m_nCreationTime;\n\n\t\tfloat traceThickness = aTraces[i].m_fThickness * timeAlive / aTraces[i].m_nLifeTime;\n\t\tCVector horizontalOffset = aTraces[i].m_vecEndPos - aTraces[i].m_vecStartPos;\n\t\thorizontalOffset.Normalise();\n\t\thorizontalOffset *= traceThickness;\n\n\t\t//then closer trace to die then it more transparent\n\t\tuint8 nAlphaValue = aTraces[i].m_fVisibility * (aTraces[i].m_nLifeTime - timeAlive) / aTraces[i].m_nLifeTime;\n\n\t\tCVector start = aTraces[i].m_vecStartPos;\n\t\tCVector end = aTraces[i].m_vecEndPos;\n\t\tfloat startProj = DotProduct(start - TheCamera.GetPosition(), TheCamera.GetForward()) - 0.7f;\n\t\tfloat endProj = DotProduct(end - TheCamera.GetPosition(), TheCamera.GetForward()) - 0.7f;\n\t\tif (startProj < 0.0f && endProj < 0.0f) //we dont need render trace behind us\n\t\t\tcontinue;\n\n\t\tif (startProj < 0.0f) { //if strat behind us move it closer\n\t\t\tfloat absStartProj = Abs(startProj);\n\t\t\tfloat absEndProj = Abs(endProj);\n\t\t\tstart = (absEndProj * start + absStartProj * end) / (absStartProj + absEndProj);\n\t\t} else if (endProj < 0.0f) {\n\t\t\tfloat absStartProj = Abs(startProj);\n\t\t\tfloat absEndProj = Abs(endProj);\n\t\t\tend = (absEndProj * start + absStartProj * end) / (absStartProj + absEndProj);\n\t\t}\n\n\t\t//we divide trace at three parts\n\t\tCVector start2 = (7.0f * start + end) / 8;\n\t\tCVector end2 = (7.0f * end + start) / 8;\n\n\t\tRwIm3DVertexSetV(&TraceVertices[5], 10.0f);\n\t\tRwIm3DVertexSetV(&TraceVertices[6], 10.0f);\n\t\tRwIm3DVertexSetV(&TraceVertices[7], 10.0f);\n\t\tRwIm3DVertexSetV(&TraceVertices[8], 10.0f);\n\t\tRwIm3DVertexSetV(&TraceVertices[9], 10.0f);\n\n\t\tRwIm3DVertexSetRGBA(&TraceVertices[0], 255, 255, 255, nAlphaValue);\n\t\tRwIm3DVertexSetRGBA(&TraceVertices[1], 255, 255, 255, nAlphaValue);\n\t\tRwIm3DVertexSetRGBA(&TraceVertices[2], 255, 255, 255, nAlphaValue);\n\t\tRwIm3DVertexSetRGBA(&TraceVertices[3], 255, 255, 255, nAlphaValue);\n\t\tRwIm3DVertexSetRGBA(&TraceVertices[4], 255, 255, 255, nAlphaValue);\n\t\tRwIm3DVertexSetRGBA(&TraceVertices[5], 255, 255, 255, nAlphaValue);\n\t\tRwIm3DVertexSetRGBA(&TraceVertices[6], 255, 255, 255, nAlphaValue);\n\t\tRwIm3DVertexSetRGBA(&TraceVertices[7], 255, 255, 255, nAlphaValue);\n\t\tRwIm3DVertexSetRGBA(&TraceVertices[8], 255, 255, 255, nAlphaValue);\n\t\tRwIm3DVertexSetRGBA(&TraceVertices[9], 255, 255, 255, nAlphaValue);\n\t\t//two points in center\n\t\tRwIm3DVertexSetPos(&TraceVertices[0], start2.x, start2.y, start2.z);\n\t\tRwIm3DVertexSetPos(&TraceVertices[5], end2.x, end2.y, end2.z);\n\t\t//vertical planes\n\t\tRwIm3DVertexSetPos(&TraceVertices[1], start2.x, start2.y, start2.z + traceThickness);\n\t\tRwIm3DVertexSetPos(&TraceVertices[3], start2.x, start2.y, start2.z - traceThickness);\n\t\tRwIm3DVertexSetPos(&TraceVertices[6], end2.x, end2.y, end2.z + traceThickness);\n\t\tRwIm3DVertexSetPos(&TraceVertices[8], end2.x, end2.y, end2.z - traceThickness);\n\t\t//horizontal planes\n\t\tRwIm3DVertexSetPos(&TraceVertices[2], start2.x + horizontalOffset.y, start2.y - horizontalOffset.x, start2.z);\n\t\tRwIm3DVertexSetPos(&TraceVertices[7], end2.x + horizontalOffset.y, end2.y - horizontalOffset.x, end2.z);\n#ifdef FIX_BUGS //this point calculated wrong for some reason\n\t\tRwIm3DVertexSetPos(&TraceVertices[4], start2.x - horizontalOffset.y, start2.y + horizontalOffset.x, start2.z);\n\t\tRwIm3DVertexSetPos(&TraceVertices[9], end2.x - horizontalOffset.y, end2.y + horizontalOffset.x, end2.z);\n#else\n\t\tRwIm3DVertexSetPos(&TraceVertices[4], start2.x - horizontalOffset.y, start2.y - horizontalOffset.y, start2.z);\n\t\tRwIm3DVertexSetPos(&TraceVertices[9], end2.x - horizontalOffset.y, end2.y - horizontalOffset.y, end2.z);\n#endif\n\n\t\tif (RwIm3DTransform(TraceVertices, ARRAY_SIZE(TraceVertices), nil, 1)) {\n\t\t\tRwIm3DRenderIndexedPrimitive(rwPRIMTYPETRILIST, TraceIndexList, ARRAY_SIZE(TraceIndexList));\n\t\t\tRwIm3DEnd();\n\t\t}\n\n\t\tRwIm3DVertexSetV(&TraceVertices[5], 2.0f);\n\t\tRwIm3DVertexSetV(&TraceVertices[6], 2.0f);\n\t\tRwIm3DVertexSetV(&TraceVertices[7], 2.0f);\n\t\tRwIm3DVertexSetV(&TraceVertices[8], 2.0f);\n\t\tRwIm3DVertexSetV(&TraceVertices[9], 2.0f);\n\t\tRwIm3DVertexSetRGBA(&TraceVertices[0], 255, 255, 255, 0);\n\t\tRwIm3DVertexSetRGBA(&TraceVertices[1], 255, 255, 255, 0);\n\t\tRwIm3DVertexSetRGBA(&TraceVertices[2], 255, 255, 255, 0);\n\t\tRwIm3DVertexSetRGBA(&TraceVertices[3], 255, 255, 255, 0);\n\t\tRwIm3DVertexSetRGBA(&TraceVertices[4], 255, 255, 255, 0);\n\n\t\tRwIm3DVertexSetPos(&TraceVertices[0], start.x, start.y, start.z);\n\t\tRwIm3DVertexSetPos(&TraceVertices[1], start.x, start.y, start.z + traceThickness);\n\t\tRwIm3DVertexSetPos(&TraceVertices[3], start.x, start.y, start.z - traceThickness);\n\t\tRwIm3DVertexSetPos(&TraceVertices[2], start.x + horizontalOffset.y, start.y - horizontalOffset.x, start.z);\n\n\t\tRwIm3DVertexSetPos(&TraceVertices[5], start2.x, start2.y, start2.z);\n\t\tRwIm3DVertexSetPos(&TraceVertices[6], start2.x, start2.y, start2.z + traceThickness);\n\t\tRwIm3DVertexSetPos(&TraceVertices[8], start2.x, start2.y, start2.z - traceThickness);\n\t\tRwIm3DVertexSetPos(&TraceVertices[7], start2.x + horizontalOffset.y, start2.y - horizontalOffset.x, start2.z);\n#ifdef FIX_BUGS\n\t\tRwIm3DVertexSetPos(&TraceVertices[4], start.x - horizontalOffset.y, start.y + horizontalOffset.x, start.z);\n\t\tRwIm3DVertexSetPos(&TraceVertices[9], start2.x - horizontalOffset.y, start2.y + horizontalOffset.x, start2.z);\n#else\n\t\tRwIm3DVertexSetPos(&TraceVertices[4], start.x - horizontalOffset.y, start.y - horizontalOffset.y, start.z);\n\t\tRwIm3DVertexSetPos(&TraceVertices[9], start2.x - horizontalOffset.y, start2.y - horizontalOffset.y, start2.z);\n#endif\n\n\t\tif (RwIm3DTransform(TraceVertices, ARRAY_SIZE(TraceVertices), nil, rwIM3D_VERTEXUV)) {\n\t\t\tRwIm3DRenderIndexedPrimitive(rwPRIMTYPETRILIST, TraceIndexList, ARRAY_SIZE(TraceIndexList));\n\t\t\tRwIm3DEnd();\n\t\t}\n\n\t\tRwIm3DVertexSetPos(&TraceVertices[1], end.x, end.y, end.z);\n\t\tRwIm3DVertexSetPos(&TraceVertices[2], end.x, end.y, end.z + traceThickness);\n\t\tRwIm3DVertexSetPos(&TraceVertices[4], end.x, end.y, end.z - traceThickness);\n\t\tRwIm3DVertexSetPos(&TraceVertices[3], end.x + horizontalOffset.y, end.y - horizontalOffset.x, end.z);\n\n\t\tRwIm3DVertexSetPos(&TraceVertices[5], end2.x, end2.y, end2.z);\n\t\tRwIm3DVertexSetPos(&TraceVertices[6], end2.x, end2.y, end2.z + traceThickness);\n\t\tRwIm3DVertexSetPos(&TraceVertices[8], end2.x, end2.y, end2.z - traceThickness);\n\t\tRwIm3DVertexSetPos(&TraceVertices[7], end2.x + horizontalOffset.y, end2.y - horizontalOffset.x, end2.z);\n#ifdef FIX_BUGS\n\t\tRwIm3DVertexSetPos(&TraceVertices[5], end.x - horizontalOffset.y, end.y + horizontalOffset.x, end.z);\n\t\tRwIm3DVertexSetPos(&TraceVertices[9], end2.x - horizontalOffset.y, end2.y + horizontalOffset.x, end2.z);\n#else\n\t\tRwIm3DVertexSetPos(&TraceVertices[5], end.x - horizontalOffset.y, end.y - horizontalOffset.y, end.z);\n\t\tRwIm3DVertexSetPos(&TraceVertices[9], end2.x - horizontalOffset.y, end2.y - horizontalOffset.y, end2.z);\n#endif\n\n\t\tif (RwIm3DTransform(TraceVertices, ARRAY_SIZE(TraceVertices), nil, rwIM3D_VERTEXUV)) {\n\t\t\tRwIm3DRenderIndexedPrimitive(rwPRIMTYPETRILIST, TraceIndexList, ARRAY_SIZE(TraceIndexList));\n\t\t\tRwIm3DEnd();\n\t\t}\n\t}\n\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);\n\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);\n\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);\n}\n\nvoid CBulletTraces::Update(void)\n{\n\tfor (int i = 0; i < NUMBULLETTRACES; i++) {\n\t\tif (aTraces[i].m_bInUse)\n\t\t\taTraces[i].Update();\n\t}\n}\n\nvoid CBulletTrace::Update(void)\n{\n\tif (CTimer::GetTimeInMilliseconds() - m_nCreationTime >= m_nLifeTime)\n\t\tm_bInUse = false;\n}\n\nRpAtomic *\nMarkerAtomicCB(RpAtomic *atomic, void *data)\n{\n\t*(RpAtomic**)data = atomic;\n\treturn atomic;\n}\n\nbool\nC3dMarker::AddMarker(uint32 identifier, uint16 type, float fSize, uint8 r, uint8 g, uint8 b, uint8 a, uint16 pulsePeriod, float pulseFraction, int16 rotateRate)\n{\n\tm_nIdentifier = identifier;\n\n\tm_Matrix.SetUnity();\n\n\tRpAtomic *origAtomic;\n\torigAtomic = nil;\n\tRpClumpForAllAtomics(C3dMarkers::m_pRpClumpArray[type], MarkerAtomicCB, &origAtomic);\n\n\tRpAtomic *atomic = RpAtomicClone(origAtomic);\n\tRwFrame *frame = RwFrameCreate();\n\tRpAtomicSetFrame(atomic, frame);\n\tCVisibilityPlugins::SetAtomicRenderCallback(atomic, nil);\n\t\n\tRpGeometry *geometry = RpAtomicGetGeometry(atomic);\n\tRpGeometrySetFlags(geometry, RpGeometryGetFlags(geometry) | rpGEOMETRYMODULATEMATERIALCOLOR);\n\n\tm_pAtomic = atomic;\n\tm_Matrix.Attach(RwFrameGetMatrix(RpAtomicGetFrame(m_pAtomic)));\n\tm_pMaterial = RpGeometryGetMaterial(geometry, 0);\n\tm_fSize = fSize;\n\tm_fStdSize = m_fSize;\n\tm_Color.red = r;\n\tm_Color.green = g;\n\tm_Color.blue = b;\n\tm_Color.alpha = a;\n\tm_nPulsePeriod = pulsePeriod;\n\tm_fPulseFraction = pulseFraction;\n\tm_nRotateRate = rotateRate;\n\tm_nStartTime = CTimer::GetTimeInMilliseconds();\n\tm_nType = type;\n\treturn m_pAtomic != nil;\n}\n\nvoid\nC3dMarker::DeleteMarkerObject()\n{\n\tRwFrame *frame;\n\n\tm_nIdentifier = 0;\n\tm_nStartTime = 0;\n\tm_bIsUsed = false;\n\tm_bFindZOnNextPlacement = false;\n\tm_nType = MARKERTYPE_INVALID;\n\n\tframe = RpAtomicGetFrame(m_pAtomic);\n\tRpAtomicDestroy(m_pAtomic);\n\tRwFrameDestroy(frame);\n\tm_pAtomic = nil;\n}\n\nvoid\nC3dMarker::Render()\n{\n\tif (m_pAtomic == nil) return;\n\n\tRpMaterialSetColor(m_pMaterial, &m_Color);\n\n\tm_Matrix.UpdateRW();\n\n\tCMatrix matrix;\n\tmatrix.Attach(m_Matrix.m_attachment);\n\tmatrix.Scale(m_fSize);\n\tmatrix.UpdateRW();\n\n\tRwFrameUpdateObjects(RpAtomicGetFrame(m_pAtomic));\n\tSetBrightMarkerColours(m_fBrightness);\n\tif (m_nType != MARKERTYPE_ARROW)\n\t\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);\n\tRpAtomicRender(m_pAtomic);\n\tif (m_nType != MARKERTYPE_ARROW)\n\t\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);\n\tReSetAmbientAndDirectionalColours();\n}\n\nC3dMarker C3dMarkers::m_aMarkerArray[NUM3DMARKERS];\nint32 C3dMarkers::NumActiveMarkers;\nRpClump* C3dMarkers::m_pRpClumpArray[NUMMARKERTYPES];\n\nvoid\nC3dMarkers::Init()\n{\n\tfor (int i = 0; i < NUM3DMARKERS; i++) {\n\t\tm_aMarkerArray[i].m_pAtomic = nil;\n\t\tm_aMarkerArray[i].m_nType = MARKERTYPE_INVALID;\n\t\tm_aMarkerArray[i].m_bIsUsed = false;\n\t\tm_aMarkerArray[i].m_bFindZOnNextPlacement = false;\n\t\tm_aMarkerArray[i].m_nIdentifier = 0;\n\t\tm_aMarkerArray[i].m_Color.red = 255;\n\t\tm_aMarkerArray[i].m_Color.green = 255;\n\t\tm_aMarkerArray[i].m_Color.blue = 255;\n\t\tm_aMarkerArray[i].m_Color.alpha = 255;\n\t\tm_aMarkerArray[i].m_nPulsePeriod = 1024;\n\t\tm_aMarkerArray[i].m_nRotateRate = 5;\n\t\tm_aMarkerArray[i].m_nStartTime = 0;\n\t\tm_aMarkerArray[i].m_fPulseFraction = 0.25f;\n\t\tm_aMarkerArray[i].m_fStdSize = 1.0f;\n\t\tm_aMarkerArray[i].m_fSize = 1.0f;\n\t\tm_aMarkerArray[i].m_fBrightness = 1.0f;\n\t\tm_aMarkerArray[i].m_fCameraRange = 0.0f;\n\t}\n\tNumActiveMarkers = 0;\n\tint txdSlot = CTxdStore::FindTxdSlot(\"particle\");\n\tCTxdStore::PushCurrentTxd();\n\tCTxdStore::SetCurrentTxd(txdSlot);\n\tCFileMgr::ChangeDir(\"\\\\\");\n\tm_pRpClumpArray[MARKERTYPE_ARROW] = CFileLoader::LoadAtomicFile2Return(\"models/generic/arrow.dff\");\n\tm_pRpClumpArray[MARKERTYPE_CYLINDER] = CFileLoader::LoadAtomicFile2Return(\"models/generic/zonecylb.dff\");\n\tCTxdStore::PopCurrentTxd();\n}\n\nvoid\nC3dMarkers::Shutdown()\n{\n\tfor (int i = 0; i < NUM3DMARKERS; i++) {\n\t\tif (m_aMarkerArray[i].m_pAtomic != nil)\n\t\t\tm_aMarkerArray[i].DeleteMarkerObject();\n\t}\n\n\tfor (int i = 0; i < NUMMARKERTYPES; i++) {\n\t\tif (m_pRpClumpArray[i] != nil)\n\t\t\tRpClumpDestroy(m_pRpClumpArray[i]);\n\t}\n}\n\nvoid\nC3dMarkers::Render()\n{\n\tNumActiveMarkers = 0;\n\tActivateDirectional();\n\tfor (int i = 0; i < NUM3DMARKERS; i++) {\n\t\tif (m_aMarkerArray[i].m_bIsUsed) {\n\t\t\tif (m_aMarkerArray[i].m_fCameraRange < 150.0f) {\n\t\t\t\tm_aMarkerArray[i].Render();\n\t\t\t\tif (m_aMarkerArray[i].m_nType == MARKERTYPE_ARROW) {\n\t\t\t\t\tCCoronas::RegisterCorona((uintptr)&m_aMarkerArray[i],\n\t\t\t\t\t\tSPHERE_MARKER_R, SPHERE_MARKER_G, SPHERE_MARKER_B, 192,\n\t\t\t\t\t\tm_aMarkerArray[i].m_Matrix.GetPosition(), 1.2f * m_aMarkerArray[i].m_fSize, 50.0f * TheCamera.LODDistMultiplier,\n\t\t\t\t\t\tCCoronas::TYPE_STAR, CCoronas::FLARE_NONE, CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_ON, 0.0f, false);\n\t\t\t\t}\n\t\t\t}\n\t\t\tNumActiveMarkers++;\n\t\t\tm_aMarkerArray[i].m_bIsUsed = false;\n\t\t} else if (m_aMarkerArray[i].m_pAtomic != nil) {\n\t\t\tm_aMarkerArray[i].DeleteMarkerObject();\n\t\t}\n\t}\n}\n\nC3dMarker *\nC3dMarkers::PlaceMarker(uint32 identifier, uint16 type, CVector &pos, float size, uint8 r, uint8 g, uint8 b, uint8 a, uint16 pulsePeriod, float pulseFraction, int16 rotateRate)\n{\n\tC3dMarker *pMarker;\n\tCVector2D playerPos = FindPlayerCentreOfWorld(0);\n\tpMarker = nil;\n\tfloat dist = ((CVector2D)pos - playerPos).Magnitude();\n\n\tif (type != MARKERTYPE_ARROW && type != MARKERTYPE_CYLINDER) return nil;\n\n\tfor (int i = 0; i < NUM3DMARKERS; i++) {\n\t\tif (!m_aMarkerArray[i].m_bIsUsed && m_aMarkerArray[i].m_nIdentifier == identifier) {\n\t\t\tpMarker = &m_aMarkerArray[i];\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tif (pMarker == nil) {\n\t\tfor (int i = 0; i < NUM3DMARKERS; i++) {\n\t\t\tif (m_aMarkerArray[i].m_nType == MARKERTYPE_INVALID) {\n\t\t\t\tpMarker = &m_aMarkerArray[i];\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (pMarker == nil && type == MARKERTYPE_ARROW) {\n\t\tfor (int i = 0; i < NUM3DMARKERS; i++) {\n\t\t\tif (dist < m_aMarkerArray[i].m_fCameraRange && m_aMarkerArray[i].m_nType == MARKERTYPE_ARROW && (pMarker == nil || m_aMarkerArray[i].m_fCameraRange > pMarker->m_fCameraRange)) {\n\t\t\t\tpMarker = &m_aMarkerArray[i];\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif (pMarker != nil)\n\t\t\tpMarker->m_nType = MARKERTYPE_INVALID;\n\t}\n\n\tif (pMarker == nil) return pMarker;\n\n\tpMarker->m_fCameraRange = dist;\n\tif (pMarker->m_nIdentifier == identifier && pMarker->m_nType == type) {\n\t\tif (type == MARKERTYPE_ARROW) {\n\t\t\tif (dist < 25.0f) {\n\t\t\t\tif (dist > 5.0f)\n\t\t\t\t\tpMarker->m_fStdSize = size - (25.0f - dist) * (0.3f * size) / 20.0f;\n\t\t\t\telse\n\t\t\t\t\tpMarker->m_fStdSize = size - 0.3f * size;\n\t\t\t} else {\n\t\t\t\tpMarker->m_fStdSize = size;\n\t\t\t}\n\t\t} else if (type == MARKERTYPE_CYLINDER) {\n\t\t\tif (dist < size + 12.0f) {\n\t\t\t\tif (dist > size + 1.0f)\n\t\t\t\t\tpMarker->m_Color.alpha = (1.0f - (size + 12.0f - dist) * 0.7f / 11.0f) * (float)a;\n\t\t\t\telse\n\t\t\t\t\tpMarker->m_Color.alpha = (float)a * 0.3f;\n\t\t\t} else {\n\t\t\t\tpMarker->m_Color.alpha = a;\n\t\t\t}\n\t\t}\n\t\tfloat someSin = Sin(TWOPI * (float)((pMarker->m_nPulsePeriod - 1) & (CTimer::GetTimeInMilliseconds() - pMarker->m_nStartTime)) / (float)pMarker->m_nPulsePeriod);\n\t\tpMarker->m_fSize = pMarker->m_fStdSize - pulseFraction * pMarker->m_fStdSize * someSin;\n\n\t\tif (type == MARKERTYPE_ARROW) {\n\t\t\tpos.z += 0.25f * pMarker->m_fStdSize * someSin;\n\t\t} else if (type == MARKERTYPE_0) {\n\t\t\tif (someSin > 0.0f)\n\t\t\t\tpMarker->m_Color.alpha = (float)a * 0.7f * someSin + a;\n\t\t\telse\n\t\t\t\tpMarker->m_Color.alpha = (float)a * 0.4f * someSin + a;\n\t\t}\n\t\tif (pMarker->m_nRotateRate != 0) {\n\t\t\tCVector pos = pMarker->m_Matrix.GetPosition();\n\t\t\tpMarker->m_Matrix.RotateZ(DEGTORAD(pMarker->m_nRotateRate * CTimer::GetTimeStep()));\n\t\t\tpMarker->m_Matrix.GetPosition() = pos;\n\t\t}\n\t\tif (type == MARKERTYPE_ARROW)\n\t\t\tpMarker->m_Matrix.GetPosition() = pos;\n\n\t\tif (pMarker->m_bFindZOnNextPlacement) {\n\t\t\tif ((playerPos - pos).MagnitudeSqr() < sq(100.f) && CColStore::HasCollisionLoaded(CVector2D(pos))) {\n\t\t\t\tfloat z = CWorld::FindGroundZFor3DCoord(pos.x, pos.y, pos.z + 1.0f, nil);\n\t\t\t\tif (z != 0.0f)\n\t\t\t\t\tpMarker->m_Matrix.GetPosition().z = z - 0.05f * size;\n\t\t\t\tpMarker->m_bFindZOnNextPlacement = false;\n\t\t\t}\n\t\t}\n\t\tpMarker->m_bIsUsed = true;\n\t\treturn pMarker;\n\t}\n\n\tif (pMarker->m_nIdentifier != 0)\n\t\tpMarker->DeleteMarkerObject();\n\n\tpMarker->AddMarker(identifier, type, size, r, g, b, a, pulsePeriod, pulseFraction, rotateRate);\n\tif (type == MARKERTYPE_CYLINDER || type == MARKERTYPE_0 || type == MARKERTYPE_2) {\n\t\tif ((playerPos - pos).MagnitudeSqr() < sq(100.f) && CColStore::HasCollisionLoaded(CVector2D(pos))) {\n\t\t\tfloat z = CWorld::FindGroundZFor3DCoord(pos.x, pos.y, pos.z + 1.0f, nil);\n\t\t\tif (z != 0.0f)\n\t\t\t\tpos.z = z - 0.05f * size;\n\t\t\tpMarker->m_bFindZOnNextPlacement = false;\n\t\t} else {\n\t\t\tpMarker->m_bFindZOnNextPlacement = true;\n\t\t}\n\t}\n\tpMarker->m_Matrix.SetTranslate(pos.x, pos.y, pos.z);\n\tif (type == MARKERTYPE_2) {\n\t\tpMarker->m_Matrix.RotateX(PI);\n\t\tpMarker->m_Matrix.GetPosition() = pos;\n\t}\n\tpMarker->m_Matrix.UpdateRW();\n\tif (type == MARKERTYPE_ARROW) {\n\t\tif (dist < 25.0f) {\n\t\t\tif (dist > 5.0f)\n\t\t\t\tpMarker->m_fStdSize = size - (25.0f - dist) * (0.3f * size) / 20.0f;\n\t\t\telse\n\t\t\t\tpMarker->m_fStdSize = size - 0.3f * size;\n\t\t} else {\n\t\t\tpMarker->m_fStdSize = size;\n\t\t}\n\t} else if (type == MARKERTYPE_CYLINDER) {\n\t\tif (dist < size + 12.0f) {\n\t\t\tif (dist > size + 1.0f)\n\t\t\t\tpMarker->m_Color.alpha = (1.0f - (size + 12.0f - dist) * 0.7f / 11.0f) * (float)a;\n\t\t\telse\n\t\t\t\tpMarker->m_Color.alpha = (float)a * 0.3f;\n\t\t} else {\n\t\t\tpMarker->m_Color.alpha = a;\n\t\t}\n\t}\n\tpMarker->m_bIsUsed = true;\n\treturn pMarker;\n}\n\nvoid\nC3dMarkers::PlaceMarkerSet(uint32 id, uint16 type, CVector &pos, float size, uint8 r, uint8 g, uint8 b, uint8 a, uint16 pulsePeriod, float pulseFraction, int16 rotateRate)\n{\n\tPlaceMarker(id, type, pos, size, r, g, b, a, pulsePeriod, pulseFraction, 1);\n\tPlaceMarker(id, type, pos, size * 0.93f, r, g, b, a, pulsePeriod, pulseFraction, 2);\n\tPlaceMarker(id, type, pos, size * 0.86f, r, g, b, a, pulsePeriod, pulseFraction, -1);\n}\n\n\nvoid\nC3dMarkers::Update()\n{\n}\n\n\n#define BRIGHTLIGHTS_MAX_DIST (60.0f)\t// invisible beyond this\n#define BRIGHTLIGHTS_FADE_DIST (45.0f)\t// strongest between these two\n#define CARLIGHTS_MAX_DIST (30.0f)\n#define CARLIGHTS_FADE_DIST (15.0f)\t// 31 for close lights\n\nint CBrightLights::NumBrightLights;\nCBrightLight CBrightLights::aBrightLights[NUMBRIGHTLIGHTS];\n\nvoid\nCBrightLights::Init(void)\n{\n\tNumBrightLights = 0;\n}\n\nvoid\nCBrightLights::RegisterOne(CVector pos, CVector up, CVector side, CVector front,\n\tuint8 type, uint8 red, uint8 green, uint8 blue)\n{\n\tif(NumBrightLights >= NUMBRIGHTLIGHTS)\n\t\treturn;\n\n\taBrightLights[NumBrightLights].m_camDist = (pos - TheCamera.GetPosition()).Magnitude();\n\tif(aBrightLights[NumBrightLights].m_camDist > BRIGHTLIGHTS_MAX_DIST)\n\t\treturn;\n\n\taBrightLights[NumBrightLights].m_pos = pos;\n\taBrightLights[NumBrightLights].m_up = up;\n\taBrightLights[NumBrightLights].m_side = side;\n\taBrightLights[NumBrightLights].m_front = front;\n\taBrightLights[NumBrightLights].m_type = type;\n\taBrightLights[NumBrightLights].m_red = red;\n\taBrightLights[NumBrightLights].m_green = green;\n\taBrightLights[NumBrightLights].m_blue = blue;\n\n\tNumBrightLights++;\n}\n\nstatic float TrafficLightsSide[6] = { -0.09f, 0.09f, 0.162f, 0.09f, -0.09f, -0.162f };\nstatic float TrafficLightsUp[6] = { 0.162f, 0.162f, 0.0f, -0.162f, -0.162f, 0.0f };\nstatic float LongCarHeadLightsSide[8] = { -0.2f, 0.2f, -0.2f, 0.2f, -0.2f, 0.2f, -0.2f, 0.2f };\nstatic float LongCarHeadLightsFront[8] = { 0.1f, 0.1f, -0.1f, -0.1f, 0.1f, 0.1f, -0.1f, -0.1f };\nstatic float LongCarHeadLightsUp[8] = { 0.1f, 0.1f, 0.1f, 0.1f, -0.1f, -0.1f, -0.1f, -0.1f };\nstatic float SmallCarHeadLightsSide[8] = { -0.08f, 0.08f, -0.08f, 0.08f, -0.08f, 0.08f, -0.08f, 0.08f };\nstatic float SmallCarHeadLightsFront[8] = { 0.08f, 0.08f, -0.08f, -0.08f, 0.08f, 0.08f, -0.08f, -0.08f };\nstatic float SmallCarHeadLightsUp[8] = { 0.08f, 0.08f, 0.08f, 0.08f, -0.08f, -0.08f, -0.08f, -0.08f };\nstatic float BigCarHeadLightsSide[8] = { -0.15f, 0.15f, -0.15f, 0.15f, -0.15f, 0.15f, -0.15f, 0.15f };\nstatic float BigCarHeadLightsFront[8] = { 0.15f, 0.15f, -0.15f, -0.15f, 0.15f, 0.15f, -0.15f, -0.15f };\nstatic float BigCarHeadLightsUp[8] = { 0.15f, 0.15f, 0.15f, 0.15f, -0.15f, -0.15f, -0.15f, -0.15f };\nstatic float TallCarHeadLightsSide[8] = { -0.08f, 0.08f, -0.08f, 0.08f, -0.08f, 0.08f, -0.08f, 0.08f };\nstatic float TallCarHeadLightsFront[8] = { 0.08f, 0.08f, -0.08f, -0.08f, 0.08f, 0.08f, -0.08f, -0.08f };\nstatic float TallCarHeadLightsUp[8] = { 0.2f, 0.2f, 0.2f, 0.2f, -0.2f, -0.2f, -0.2f, -0.2f };\nstatic float SirenLightsSide[6] = { -0.04f, 0.04f, 0.06f, 0.04f, -0.04f, -0.06f };\nstatic float SirenLightsUp[6] = { 0.06f, 0.06f, 0.0f, -0.06f, -0.06f, 0.0f };\nstatic RwImVertexIndex TrafficLightIndices[4*3] = { 0, 1, 5,  1, 2, 3,  1, 3, 4,  1, 4, 5 };\nstatic RwImVertexIndex CubeIndices[12*3] = {\n\t0, 2, 1,  1, 2, 3,  3, 5, 1,  3, 7, 5,\n\t2, 7, 3,  2, 6, 7,  4, 0, 1,  4, 1, 5,\n\t6, 0, 4,  6, 2, 0,  6, 5, 7,  6, 4, 5\n};\n\nvoid\nCBrightLights::Render(void)\n{\n\tint i, j;\n\tCVector pos;\n\n\tif(NumBrightLights == 0)\n\t\treturn;\n\n\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);\n\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);\n\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);\n\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);\n\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil);\n\n\tTempBufferVerticesStored = 0;\n\tTempBufferIndicesStored = 0;\n\n\tfor(i = 0; i < NumBrightLights; i++){\n\t\tif(TempBufferIndicesStored > TEMPBUFFERINDEXSIZE-40 || TempBufferVerticesStored > TEMPBUFFERVERTSIZE-40)\n\t\t\tRenderOutGeometryBuffer();\n\n\t\tint r, g, b, a;\n\t\tfloat flicker = (CGeneral::GetRandomNumber()&0xFF) * 0.2f;\n\t\tswitch(aBrightLights[i].m_type){\n\t\tcase BRIGHTLIGHT_TRAFFIC_GREEN:\n\t\t\tr = flicker; g = 255; b = flicker;\n\t\t\tbreak;\n\t\tcase BRIGHTLIGHT_TRAFFIC_YELLOW:\n\t\t\tr = 255; g = 128; b = flicker;\n\t\t\tbreak;\n\t\tcase BRIGHTLIGHT_TRAFFIC_RED:\n\t\t\tr = 255; g = flicker; b = flicker;\n\t\t\tbreak;\n\n\t\tcase BRIGHTLIGHT_FRONT_LONG:\n\t\tcase BRIGHTLIGHT_FRONT_SMALL:\n\t\tcase BRIGHTLIGHT_FRONT_BIG:\n\t\tcase BRIGHTLIGHT_FRONT_TALL:\n\t\t\tr = 255; g = 255; b = 255;\n\t\t\tbreak;\n\n\t\tcase BRIGHTLIGHT_REAR_LONG:\n\t\tcase BRIGHTLIGHT_REAR_SMALL:\n\t\tcase BRIGHTLIGHT_REAR_BIG:\n\t\tcase BRIGHTLIGHT_REAR_TALL:\n\t\t\tr = 255; g = flicker; b = flicker;\n\t\t\tbreak;\n\n\t\tcase BRIGHTLIGHT_SIREN:\n\t\t\tr = aBrightLights[i].m_red;\n\t\t\tg = aBrightLights[i].m_green;\n\t\t\tb = aBrightLights[i].m_blue;\n\t\t\tbreak;\n#ifdef FIX_BUGS  //just to make sure that color never will be undefined\n\t\tdefault:\n\t\t\treturn;\n#endif\n\t\t}\n\n\t\tif(aBrightLights[i].m_camDist < BRIGHTLIGHTS_FADE_DIST)\n\t\t\ta = 255;\n\t\telse\n\t\t\ta = 255*(1.0f - (aBrightLights[i].m_camDist-BRIGHTLIGHTS_FADE_DIST)/(BRIGHTLIGHTS_MAX_DIST-BRIGHTLIGHTS_FADE_DIST));\n\t\t// fade car lights down to 31 as they come near\n\t\tif(aBrightLights[i].m_type >= BRIGHTLIGHT_FRONT_LONG && aBrightLights[i].m_type <= BRIGHTLIGHT_REAR_TALL){\n\t\t\tif(aBrightLights[i].m_camDist < CARLIGHTS_FADE_DIST)\n\t\t\t\ta = 31;\n\t\t\telse if(aBrightLights[i].m_camDist < CARLIGHTS_MAX_DIST)\n\t\t\t\ta = 31 + (255-31)*((aBrightLights[i].m_camDist-CARLIGHTS_FADE_DIST)/(CARLIGHTS_MAX_DIST-CARLIGHTS_FADE_DIST));\n\t\t}\n\n\t\tswitch(aBrightLights[i].m_type){\n\t\tcase BRIGHTLIGHT_TRAFFIC_GREEN:\n\t\tcase BRIGHTLIGHT_TRAFFIC_YELLOW:\n\t\tcase BRIGHTLIGHT_TRAFFIC_RED:\n\t\t\tfor(j = 0; j < 6; j++){\n\t\t\t\tpos = TrafficLightsSide[j]*aBrightLights[i].m_side +\n\t\t\t\t\tTrafficLightsUp[j]*aBrightLights[i].m_up +\n\t\t\t\t\taBrightLights[i].m_pos;\n\t\t\t\tRwIm3DVertexSetRGBA(&TempBufferRenderVertices[TempBufferVerticesStored+j], r, g, b, a);\n\t\t\t\tRwIm3DVertexSetPos(&TempBufferRenderVertices[TempBufferVerticesStored+j], pos.x, pos.y, pos.z);\n\t\t\t}\n\t\t\tfor(j = 0; j < 4*3; j++)\n\t\t\t\tTempBufferRenderIndexList[TempBufferIndicesStored+j] = TrafficLightIndices[j] + TempBufferVerticesStored;\n\t\t\tTempBufferVerticesStored += 6;\n\t\t\tTempBufferIndicesStored += 4*3;\n\t\t\tbreak;\n\n\t\tcase BRIGHTLIGHT_FRONT_LONG:\n\t\tcase BRIGHTLIGHT_REAR_LONG:\n\t\t\tfor(j = 0; j < 8; j++){\n\t\t\t\tpos = LongCarHeadLightsSide[j]*aBrightLights[i].m_side +\n\t\t\t\t\tLongCarHeadLightsUp[j]*aBrightLights[i].m_up +\n\t\t\t\t\tLongCarHeadLightsFront[j]*aBrightLights[i].m_front +\n\t\t\t\t\taBrightLights[i].m_pos;\n\t\t\t\tRwIm3DVertexSetRGBA(&TempBufferRenderVertices[TempBufferVerticesStored+j], r, g, b, a);\n\t\t\t\tRwIm3DVertexSetPos(&TempBufferRenderVertices[TempBufferVerticesStored+j], pos.x, pos.y, pos.z);\n\t\t\t}\n\t\t\tfor(j = 0; j < 12*3; j++)\n\t\t\t\tTempBufferRenderIndexList[TempBufferIndicesStored+j] = CubeIndices[j] + TempBufferVerticesStored;\n\t\t\tTempBufferVerticesStored += 8;\n\t\t\tTempBufferIndicesStored += 12*3;\n\t\t\tbreak;\n\n\t\tcase BRIGHTLIGHT_FRONT_SMALL:\n\t\tcase BRIGHTLIGHT_REAR_SMALL:\n\t\t\tfor(j = 0; j < 8; j++){\n\t\t\t\tpos = SmallCarHeadLightsSide[j]*aBrightLights[i].m_side +\n\t\t\t\t\tSmallCarHeadLightsUp[j]*aBrightLights[i].m_up +\n\t\t\t\t\tSmallCarHeadLightsFront[j]*aBrightLights[i].m_front +\n\t\t\t\t\taBrightLights[i].m_pos;\n\t\t\t\tRwIm3DVertexSetRGBA(&TempBufferRenderVertices[TempBufferVerticesStored+j], r, g, b, a);\n\t\t\t\tRwIm3DVertexSetPos(&TempBufferRenderVertices[TempBufferVerticesStored+j], pos.x, pos.y, pos.z);\n\t\t\t}\n\t\t\tfor(j = 0; j < 12*3; j++)\n\t\t\t\tTempBufferRenderIndexList[TempBufferIndicesStored+j] = CubeIndices[j] + TempBufferVerticesStored;\n\t\t\tTempBufferVerticesStored += 8;\n\t\t\tTempBufferIndicesStored += 12*3;\n\t\t\tbreak;\n\n\t\tcase BRIGHTLIGHT_FRONT_BIG:\n\t\tcase BRIGHTLIGHT_REAR_BIG:\n\t\t\tfor (j = 0; j < 8; j++) {\n\t\t\t\tpos = BigCarHeadLightsSide[j] * aBrightLights[i].m_side +\n\t\t\t\t\tBigCarHeadLightsUp[j] * aBrightLights[i].m_up +\n\t\t\t\t\tBigCarHeadLightsFront[j] * aBrightLights[i].m_front +\n\t\t\t\t\taBrightLights[i].m_pos;\n\t\t\t\tRwIm3DVertexSetRGBA(&TempBufferRenderVertices[TempBufferVerticesStored + j], r, g, b, a);\n\t\t\t\tRwIm3DVertexSetPos(&TempBufferRenderVertices[TempBufferVerticesStored + j], pos.x, pos.y, pos.z);\n\t\t\t}\n\t\t\tfor (j = 0; j < 12 * 3; j++)\n\t\t\t\tTempBufferRenderIndexList[TempBufferIndicesStored + j] = CubeIndices[j] + TempBufferVerticesStored;\n\t\t\tTempBufferVerticesStored += 8;\n\t\t\tTempBufferIndicesStored += 12 * 3;\n\t\t\tbreak;\n\n\t\tcase BRIGHTLIGHT_FRONT_TALL:\n\t\tcase BRIGHTLIGHT_REAR_TALL:\n\t\t\tfor(j = 0; j < 8; j++){\n\t\t\t\tpos = TallCarHeadLightsSide[j]*aBrightLights[i].m_side +\n\t\t\t\t\tTallCarHeadLightsUp[j]*aBrightLights[i].m_up +\n\t\t\t\t\tTallCarHeadLightsFront[j]*aBrightLights[i].m_front +\n\t\t\t\t\taBrightLights[i].m_pos;\n\t\t\t\tRwIm3DVertexSetRGBA(&TempBufferRenderVertices[TempBufferVerticesStored+j], r, g, b, a);\n\t\t\t\tRwIm3DVertexSetPos(&TempBufferRenderVertices[TempBufferVerticesStored+j], pos.x, pos.y, pos.z);\n\t\t\t}\n\t\t\tfor(j = 0; j < 12*3; j++)\n\t\t\t\tTempBufferRenderIndexList[TempBufferIndicesStored+j] = CubeIndices[j] + TempBufferVerticesStored;\n\t\t\tTempBufferVerticesStored += 8;\n\t\t\tTempBufferIndicesStored += 12*3;\n\t\t\tbreak;\n\n\t\tcase BRIGHTLIGHT_SIREN:\n\t\t\tfor(j = 0; j < 6; j++){\n\t\t\t\tpos = SirenLightsSide[j] * TheCamera.GetRight() +\n\t\t\t\t\tSirenLightsUp[j] * TheCamera.GetUp() +\n\t\t\t\t\taBrightLights[i].m_pos;\n\t\t\t\tRwIm3DVertexSetRGBA(&TempBufferRenderVertices[TempBufferVerticesStored+j], r, g, b, a);\n\t\t\t\tRwIm3DVertexSetPos(&TempBufferRenderVertices[TempBufferVerticesStored+j], pos.x, pos.y, pos.z);\n\t\t\t}\n\t\t\tfor(j = 0; j < 4*3; j++)\n\t\t\t\tTempBufferRenderIndexList[TempBufferIndicesStored+j] = TrafficLightIndices[j] + TempBufferVerticesStored;\n\t\t\tTempBufferVerticesStored += 6;\n\t\t\tTempBufferIndicesStored += 4*3;\n\t\t\tbreak;\n\n\t\t}\n\t}\n\n\tRenderOutGeometryBuffer();\n\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);\n\tNumBrightLights = 0;\n}\n\nvoid\nCBrightLights::RenderOutGeometryBuffer(void)\n{\n\tif(TempBufferIndicesStored != 0){\n\t\tLittleTest();\n\t\tif(RwIm3DTransform(TempBufferRenderVertices, TempBufferVerticesStored, nil, rwIM3D_VERTEXUV)){\n\t\t\tRwIm3DRenderIndexedPrimitive(rwPRIMTYPETRILIST, TempBufferRenderIndexList, TempBufferIndicesStored);\n\t\t\tRwIm3DEnd();\n\t\t}\n\t\tTempBufferVerticesStored = 0;\n\t\tTempBufferIndicesStored = 0;\n\t}\n}\n\nint CShinyTexts::NumShinyTexts;\nCShinyText CShinyTexts::aShinyTexts[NUMSHINYTEXTS];\n\nvoid\nCShinyTexts::Init(void)\n{\n\tNumShinyTexts = 0;\n}\n\nvoid\nCShinyTexts::RegisterOne(CVector p0, CVector p1, CVector p2, CVector p3,\n\tfloat u0, float v0, float u1, float v1, float u2, float v2, float u3, float v3,\n\tuint8 type, uint8 red, uint8 green, uint8 blue, float maxDist)\n{\n\tif(NumShinyTexts >= NUMSHINYTEXTS)\n\t\treturn;\n\n\taShinyTexts[NumShinyTexts].m_camDist = (p0 - TheCamera.GetPosition()).Magnitude();\n\tif(aShinyTexts[NumShinyTexts].m_camDist > maxDist)\n\t\treturn;\n\taShinyTexts[NumShinyTexts].m_verts[0] = p0;\n\taShinyTexts[NumShinyTexts].m_verts[1] = p1;\n\taShinyTexts[NumShinyTexts].m_verts[2] = p2;\n\taShinyTexts[NumShinyTexts].m_verts[3] = p3;\n\taShinyTexts[NumShinyTexts].m_texCoords[0].x = u0;\n\taShinyTexts[NumShinyTexts].m_texCoords[0].y = v0;\n\taShinyTexts[NumShinyTexts].m_texCoords[1].x = u1;\n\taShinyTexts[NumShinyTexts].m_texCoords[1].y = v1;\n\taShinyTexts[NumShinyTexts].m_texCoords[2].x = u2;\n\taShinyTexts[NumShinyTexts].m_texCoords[2].y = v2;\n\taShinyTexts[NumShinyTexts].m_texCoords[3].x = u3;\n\taShinyTexts[NumShinyTexts].m_texCoords[3].y = v3;\n\taShinyTexts[NumShinyTexts].m_type = type;\n\taShinyTexts[NumShinyTexts].m_red = red;\n\taShinyTexts[NumShinyTexts].m_green = green;\n\taShinyTexts[NumShinyTexts].m_blue = blue;\n\t// Fade out at half the max dist\n\tfloat halfDist = maxDist*0.5f;\n\tif(aShinyTexts[NumShinyTexts].m_camDist > halfDist){\n\t\tfloat f = 1.0f - (aShinyTexts[NumShinyTexts].m_camDist - halfDist)/halfDist;\n\t\taShinyTexts[NumShinyTexts].m_red *= f;\n\t\taShinyTexts[NumShinyTexts].m_green *= f;\n\t\taShinyTexts[NumShinyTexts].m_blue *= f;\n\t}\n\n\tNumShinyTexts++;\n}\n\nvoid\nCShinyTexts::Render(void)\n{\n\tint i, ix, v;\n\tRwTexture *lastTex = nil;\n\n\tif(NumShinyTexts == 0)\n\t\treturn;\n\n\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);\n\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);\n\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE);\n\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE);\n\n\tTempBufferVerticesStored = 0;\n\tTempBufferIndicesStored = 0;\n\n\tfor(i = 0; i < NumShinyTexts; i++){\n\t\tif(TempBufferIndicesStored > TEMPBUFFERINDEXSIZE-64 || TempBufferVerticesStored > TEMPBUFFERVERTSIZE-62)\n\t\t\tRenderOutGeometryBuffer();\n\n\t\tuint8 r = aShinyTexts[i].m_red;\n\t\tuint8 g = aShinyTexts[i].m_green;\n\t\tuint8 b = aShinyTexts[i].m_blue;\n\n\t\tswitch(aShinyTexts[i].m_type){\n\t\tcase SHINYTEXT_WALK:\n\t\t\tif(lastTex != gpWalkDontTex){\n\t\t\t\tRenderOutGeometryBuffer();\n\t\t\t\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpWalkDontTex));\n\t\t\t\tlastTex = gpWalkDontTex;\n\t\t\t}\n\tquad:\n\t\t\tv = TempBufferVerticesStored;\n\t\t\tRwIm3DVertexSetRGBA(&TempBufferRenderVertices[v+0], r, g, b, 255);\n\t\t\tRwIm3DVertexSetPos(&TempBufferRenderVertices[v+0], aShinyTexts[i].m_verts[0].x, aShinyTexts[i].m_verts[0].y, aShinyTexts[i].m_verts[0].z);\n\t\t\tRwIm3DVertexSetU(&TempBufferRenderVertices[v+0], aShinyTexts[i].m_texCoords[0].x);\n\t\t\tRwIm3DVertexSetV(&TempBufferRenderVertices[v+0], aShinyTexts[i].m_texCoords[0].y);\n\t\t\tRwIm3DVertexSetRGBA(&TempBufferRenderVertices[v+1], r, g, b, 255);\n\t\t\tRwIm3DVertexSetPos(&TempBufferRenderVertices[v+1], aShinyTexts[i].m_verts[1].x, aShinyTexts[i].m_verts[1].y, aShinyTexts[i].m_verts[1].z);\n\t\t\tRwIm3DVertexSetU(&TempBufferRenderVertices[v+1], aShinyTexts[i].m_texCoords[1].x);\n\t\t\tRwIm3DVertexSetV(&TempBufferRenderVertices[v+1], aShinyTexts[i].m_texCoords[1].y);\n\t\t\tRwIm3DVertexSetRGBA(&TempBufferRenderVertices[v+2], r, g, b, 255);\n\t\t\tRwIm3DVertexSetPos(&TempBufferRenderVertices[v+2], aShinyTexts[i].m_verts[2].x, aShinyTexts[i].m_verts[2].y, aShinyTexts[i].m_verts[2].z);\n\t\t\tRwIm3DVertexSetU(&TempBufferRenderVertices[v+2], aShinyTexts[i].m_texCoords[2].x);\n\t\t\tRwIm3DVertexSetV(&TempBufferRenderVertices[v+2], aShinyTexts[i].m_texCoords[2].y);\n\t\t\tRwIm3DVertexSetRGBA(&TempBufferRenderVertices[v+3], r, g, b, 255);\n\t\t\tRwIm3DVertexSetPos(&TempBufferRenderVertices[v+3], aShinyTexts[i].m_verts[3].x, aShinyTexts[i].m_verts[3].y, aShinyTexts[i].m_verts[3].z);\n\t\t\tRwIm3DVertexSetU(&TempBufferRenderVertices[v+3], aShinyTexts[i].m_texCoords[3].x);\n\t\t\tRwIm3DVertexSetV(&TempBufferRenderVertices[v+3], aShinyTexts[i].m_texCoords[3].y);\n\t\t\tix = TempBufferIndicesStored;\n\t\t\tTempBufferRenderIndexList[ix+0] = 0 + TempBufferVerticesStored;\n\t\t\tTempBufferRenderIndexList[ix+1] = 1 + TempBufferVerticesStored;\n\t\t\tTempBufferRenderIndexList[ix+2] = 2 + TempBufferVerticesStored;\n\t\t\tTempBufferRenderIndexList[ix+3] = 2 + TempBufferVerticesStored;\n\t\t\tTempBufferRenderIndexList[ix+4] = 1 + TempBufferVerticesStored;\n\t\t\tTempBufferRenderIndexList[ix+5] = 3 + TempBufferVerticesStored;\n\t\t\tTempBufferVerticesStored += 4;\n\t\t\tTempBufferIndicesStored += 6;\n\t\t\tbreak;\n\n\t\tcase SHINYTEXT_FLAT:\n\t\t\tif(lastTex != nil){\n\t\t\t\tRenderOutGeometryBuffer();\n\t\t\t\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil);\n\t\t\t\tlastTex = nil;\n\t\t\t}\n\t\t\tgoto quad;\n\t\t}\n\t}\n\n\tRenderOutGeometryBuffer();\n\tNumShinyTexts = 0;\n\n\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);\n\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);\n\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);\n\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);\n}\n\nvoid\nCShinyTexts::RenderOutGeometryBuffer(void)\n{\n\tif(TempBufferIndicesStored != 0){\n\t\tLittleTest();\n\t\tif(RwIm3DTransform(TempBufferRenderVertices, TempBufferVerticesStored, nil, rwIM3D_VERTEXUV)){\n\t\t\tRwIm3DRenderIndexedPrimitive(rwPRIMTYPETRILIST, TempBufferRenderIndexList, TempBufferIndicesStored);\n\t\t\tRwIm3DEnd();\n\t\t}\n\t\tTempBufferVerticesStored = 0;\n\t\tTempBufferIndicesStored = 0;\n\t}\n}\n\n\n\n#define MONEY_MESSAGE_LIFETIME_MS 2000\n\nCMoneyMessage CMoneyMessages::aMoneyMessages[NUMMONEYMESSAGES];\n\nvoid\nCMoneyMessage::Render()\n{\n\tconst float MAX_SCALE = 4.0f;\n\tuint32 nLifeTime = CTimer::GetTimeInMilliseconds() - m_nTimeRegistered;\n\tif (nLifeTime >= MONEY_MESSAGE_LIFETIME_MS) {\n\t\tm_nTimeRegistered = 0;\n\t} else {\n\t\tfloat fLifeTime = (float)nLifeTime / MONEY_MESSAGE_LIFETIME_MS;\n\t\tRwV3d vecOut;\n\t\tfloat fDistX, fDistY;\n\t\tif (CSprite::CalcScreenCoors(m_vecPosition + CVector(0.0f, 0.0f, fLifeTime), &vecOut, &fDistX, &fDistY, true)) {\n\t\t\tfDistX *= (0.7f * fLifeTime + 2.0f) * m_fSize;\n\t\t\tfDistY *= (0.7f * fLifeTime + 2.0f) * m_fSize;\n\t\t\tCFont::SetPropOn();\n\t\t\tCFont::SetBackgroundOff();\n\t\t\tfloat fScaleY = Min(fDistY / 100.0f, MAX_SCALE);\n\t\t\tfloat fScaleX = Min(fDistX / 100.0f, MAX_SCALE);\n\n#ifdef FIX_BUGS\n\t\t\tCFont::SetScale(SCREEN_SCALE_X(fScaleX), SCREEN_SCALE_Y(fScaleY));\n#else\n\t\t\tCFont::SetScale(fScaleX, fScaleY);\n#endif\n\t\t\tCFont::SetCentreOn();\n\t\t\tCFont::SetCentreSize(SCREEN_WIDTH);\n\t\t\tCFont::SetJustifyOff();\n\t\t\tCFont::SetColor(CRGBA(m_Colour.r, m_Colour.g, m_Colour.b, (255.0f - 255.0f * fLifeTime) * m_fOpacity));\n\t\t\tCFont::SetBackGroundOnlyTextOff();\n\t\t\tFONT_LOCALE(FONT_STANDARD);\n\t\t\tCFont::PrintString(vecOut.x, vecOut.y, m_aText);\n\t\t}\n\t}\n}\n\nvoid\nCMoneyMessages::Init()\n{\n\tfor (int32 i = 0; i < NUMMONEYMESSAGES; i++)\n\t\taMoneyMessages[i].m_nTimeRegistered = 0;\n}\n\nvoid\nCMoneyMessages::Render()\n{\n\tfor (int32 i = 0; i < NUMMONEYMESSAGES; i++) {\n\t\tif (aMoneyMessages[i].m_nTimeRegistered != 0)\n\t\t\taMoneyMessages[i].Render();\n\t}\n}\n\nvoid\nCMoneyMessages::RegisterOne(CVector vecPos, const char *pText, uint8 bRed, uint8 bGreen, uint8 bBlue, float fSize, float fOpacity)\n{\n\tuint32 i;\n#ifdef FIX_BUGS\n\tfor(i = 0; i < NUMMONEYMESSAGES && aMoneyMessages[i].m_nTimeRegistered != 0; i++);\n#else\n\tfor(i = 0; aMoneyMessages[i].m_nTimeRegistered != 0 && i < NUMMONEYMESSAGES; i++);\n#endif\n\n\tif(i < NUMMONEYMESSAGES) {\n\t\t// Add data of this money message to the array\n\t\tAsciiToUnicode(pText, aMoneyMessages[i].m_aText);\n\n\t\taMoneyMessages[i].m_nTimeRegistered = CTimer::GetTimeInMilliseconds();\n\t\taMoneyMessages[i].m_vecPosition = vecPos;\n\t\taMoneyMessages[i].m_Colour.red = bRed;\n\t\taMoneyMessages[i].m_Colour.green = bGreen;\n\t\taMoneyMessages[i].m_Colour.blue = bBlue;\n\t\taMoneyMessages[i].m_fSize = fSize;\n\t\taMoneyMessages[i].m_fOpacity = fOpacity;\n\t}\n}\n\nCRGBA FoamColour(255, 255, 255, 255);\nuint32 CSpecialParticleStuff::BoatFromStart;\n\nvoid\nCSpecialParticleStuff::CreateFoamAroundObject(CMatrix* pMatrix, float innerFw, float innerRg, float innerUp, int32 particles)\n{\n\tfloat outerFw = innerFw + 5.0f;\n\tfloat outerRg = innerRg + 5.0f;\n\tfloat outerUp = innerUp + 5.0f;\n\tfor (int attempts = 0; particles > 0 && attempts < 1000; attempts++) {\n\t\tCVector pos;\n\t\tint rnd = CGeneral::GetRandomNumber();\n\t\tpos.x = (int8)(rnd - 128) * innerFw / 110.0f;\n\t\tpos.y = (int8)((rnd >> 8) - 128) * innerFw / 110.0f;\n\t\tpos.z = 0.0f;\n\t\tif (DotProduct2D(pos, TheCamera.GetForward()) >= 0)\n\t\t\tcontinue;\n\t\t// was there any point in adding it here?\n\t\tpos += pMatrix->GetPosition();\n\t\tpos.z = 2.0f;\n\t\tfloat fw = Abs(DotProduct(pMatrix->GetForward(), pos - pMatrix->GetPosition()));\n\t\tif (fw >= outerFw)\n\t\t\tcontinue;\n\t\tfloat rg = Abs(DotProduct(pMatrix->GetRight(), pos - pMatrix->GetPosition()));\n\t\tif (rg >= outerRg)\n\t\t\tcontinue;\n\t\tfloat up = Abs(DotProduct(pMatrix->GetUp(), pos - pMatrix->GetPosition()));\n\t\tif (up >= outerUp)\n\t\t\tcontinue;\n\t\tif (fw > innerFw || rg > innerRg || up > innerUp) {\n\t\t\tCParticle::AddParticle(PARTICLE_STEAM2, pos, CVector(0.0f, 0.0f, 0.0f), nil, 4.0f, FoamColour, 1, 0, 0, 0);\n\t\t\tparticles--;\n\t\t}\n\t}\n}\n\nvoid\nCSpecialParticleStuff::StartBoatFoamAnimation()\n{\n\tBoatFromStart = CTimer::GetTimeInMilliseconds();\n}\n\nvoid\nCSpecialParticleStuff::UpdateBoatFoamAnimation(CMatrix* pMatrix)\n{\n\tstatic int32 FrameInAnimation = 0;\n\tstatic float X, Y, Z, dX, dY, dZ;\n\tCreateFoamAroundObject(pMatrix, 107.0f, 24.1f, 30.5f, 2);\n\tuint32 prev = CTimer::GetPreviousTimeInMilliseconds();\n\tuint32 cur = CTimer::GetTimeInMilliseconds();\n\tif (FrameInAnimation != 0) {\n\t\tX += dX;\n\t\tY += dY;\n\t\tZ += dZ;\n\t\tCVector pos = *pMatrix * CVector(X, Y, Z);\n\t\tCParticle::AddParticle(PARTICLE_STEAM_NY, pos, CVector(0.0f, 0.0f, 0.0f),\n\t\t\tnil, FrameInAnimation * 0.5f + 2.0f, FoamColour, 1, 0, 0, 0);\n\t\tif (++FrameInAnimation > 15)\n\t\t\tFrameInAnimation = 0;\n\t}\n\tif ((cur & 0x3FF) < (prev & 0x3FF)) {\n\t\tFrameInAnimation = 1;\n\t\tint rnd = CGeneral::GetRandomNumber();\n\t\tX = (int8)(rnd - 128) * 0.2f;\n\t\tY = (int8)((rnd >> 8) - 128) * 0.2f;\n\t\tZ = 10.0f;\n\t\trnd = CGeneral::GetRandomNumber();\n\t\tdX = (int8)(rnd - 128) * 0.02f;\n\t\tdY = (int8)((rnd >> 8) - 128) * 0.02f;\n\t\tdZ = 2.0f;\n\t}\n}\n"
  },
  {
    "path": "src/render/SpecialFX.h",
    "content": "#pragma once\n\n//file done\n\nclass CSpecialFX\n{\npublic:\n\tstatic bool bVideoCam;\n\tstatic bool bLiftCam;\n\tstatic bool bSnapShotActive;\n\tstatic int32 SnapShotFrames;\n\n\tstatic void Render(void);\n\tstatic void Update(void);\n\tstatic void Init(void);\n\tstatic void Shutdown(void);\n\tstatic void AddWeaponStreak(int type);\n\tstatic void Render2DFXs();\n};\n\n\nclass CRegisteredMotionBlurStreak\n{\npublic:\n\tuintptr m_id;\n\tuint8 m_red;\n\tuint8 m_green;\n\tuint8 m_blue;\n\tCVector m_pos1[3];\n\tCVector m_pos2[3];\n\tbool m_isValid[3];\n\n\tvoid Update(void);\n\tvoid Render(void);\n};\n\n\nclass CMotionBlurStreaks\n{\n\tstatic CRegisteredMotionBlurStreak aStreaks[NUMMBLURSTREAKS];\npublic:\n\tstatic void Init(void);\n\tstatic void Update(void);\n\tstatic void RegisterStreak(uintptr id, uint8 r, uint8 g, uint8 b, CVector p1, CVector p2);\n\tstatic void Render(void);\n};\n\n\nstruct CBulletTrace\n{\n\tCVector m_vecStartPos;\n\tCVector m_vecEndPos;\n\tbool m_bInUse;\n\tuint32 m_nCreationTime;\n\tuint32 m_nLifeTime;\n\tfloat m_fThickness;\n\tuint8 m_fVisibility;\n\n\tvoid Update(void);\n};\n\n\nclass CBulletTraces\n{\npublic:\n\tstatic CBulletTrace aTraces[NUMBULLETTRACES];\n\n\tstatic void Init(void);\n\tstatic void Render(void);\n\tstatic void Update(void);\n\tstatic void AddTrace(CVector* start, CVector* end, float thickness, uint32 lifeTime, uint8 visibility);\n\tstatic void AddTrace(CVector* start, CVector* end, int32 weaponType, class CEntity* shooter);\n};\n\nenum\n{\n\tMARKERTYPE_0 = 0,\n\tMARKERTYPE_ARROW,\n\tMARKERTYPE_2,\n\tMARKERTYPE_3,\n\tMARKERTYPE_CYLINDER,\n\tNUMMARKERTYPES,\n\n\tMARKERTYPE_INVALID = 0x101\n};\n\n\nclass C3dMarker\n{\npublic:\n\tCMatrix m_Matrix;\n\tRpAtomic *m_pAtomic;\n\tRpMaterial *m_pMaterial;\n\tuint16 m_nType;\n\tbool m_bIsUsed;\n\tbool m_bFindZOnNextPlacement;\n\tuint32 m_nIdentifier;\n\tRwRGBA m_Color;\n\tuint16 m_nPulsePeriod;\n\tint16 m_nRotateRate;\n\tuint32 m_nStartTime;\n\tfloat m_fPulseFraction;\n\tfloat m_fStdSize;\n\tfloat m_fSize;\n\tfloat m_fBrightness;\n\tfloat m_fCameraRange;\n\n\tbool AddMarker(uint32 identifier, uint16 type, float fSize, uint8 r, uint8 g, uint8 b, uint8 a, uint16 pulsePeriod, float pulseFraction, int16 rotateRate);\n\tvoid DeleteMarkerObject();\n\tvoid Render();\n};\n\n\nclass C3dMarkers\n{\npublic:\n\tstatic void Init();\n\tstatic void Shutdown();\n\tstatic C3dMarker *PlaceMarker(uint32 id, uint16 type, CVector &pos, float size, uint8 r, uint8 g, uint8 b, uint8 a, uint16 pulsePeriod, float pulseFraction, int16 rotateRate);\n\tstatic void PlaceMarkerSet(uint32 id, uint16 type, CVector &pos, float size, uint8 r, uint8 g, uint8 b, uint8 a, uint16 pulsePeriod, float pulseFraction, int16 rotateRate);\n\tstatic void Render();\n\tstatic void Update();\n\n\tstatic C3dMarker m_aMarkerArray[NUM3DMARKERS];\n\tstatic int32 NumActiveMarkers;\n\tstatic RpClump* m_pRpClumpArray[NUMMARKERTYPES];\n};\n\nenum\n{\n\tBRIGHTLIGHT_INVALID,\n\tBRIGHTLIGHT_TRAFFIC_GREEN,\n\tBRIGHTLIGHT_TRAFFIC_YELLOW,\n\tBRIGHTLIGHT_TRAFFIC_RED,\n\n\t// white\n\tBRIGHTLIGHT_FRONT_LONG,\n\tBRIGHTLIGHT_FRONT_SMALL,\n\tBRIGHTLIGHT_FRONT_BIG,\n\tBRIGHTLIGHT_FRONT_TALL,\n\n\t// red\n\tBRIGHTLIGHT_REAR_LONG,\n\tBRIGHTLIGHT_REAR_SMALL,\n\tBRIGHTLIGHT_REAR_BIG,\n\tBRIGHTLIGHT_REAR_TALL,\n\n\tBRIGHTLIGHT_SIREN,\t// unused\n\n\tBRIGHTLIGHT_FRONT = BRIGHTLIGHT_FRONT_LONG,\n\tBRIGHTLIGHT_REAR = BRIGHTLIGHT_REAR_LONG,\n};\n\n\nclass CBrightLight\n{\npublic:\n\tCVector m_pos;\n\tCVector m_up;\n\tCVector m_side;\n\tCVector m_front;\n\tfloat m_camDist;\n\tuint8 m_type;\n\tuint8 m_red;\n\tuint8 m_green;\n\tuint8 m_blue;\n};\n\n\nclass CBrightLights\n{\n\tstatic int NumBrightLights;\n\tstatic CBrightLight aBrightLights[NUMBRIGHTLIGHTS];\npublic:\n\tstatic void Init(void);\n\tstatic void RegisterOne(CVector pos, CVector up, CVector side, CVector front,\n\t\tuint8 type, uint8 red = 0, uint8 green = 0, uint8 blue = 0);\n\tstatic void Render(void);\n\tstatic void RenderOutGeometryBuffer(void);\n};\n\n\nenum\n{\n\tSHINYTEXT_WALK = 1,\n\tSHINYTEXT_FLAT\n};\n\n\nclass CShinyText\n{\npublic:\n\tCVector m_verts[4];\n\tCVector2D m_texCoords[4];\n\tfloat m_camDist;\n\tuint8 m_type;\n\tuint8 m_red;\n\tuint8 m_green;\n\tuint8 m_blue;\n};\n\n\nclass CShinyTexts \n{\n\tstatic int NumShinyTexts;\n\tstatic CShinyText aShinyTexts[NUMSHINYTEXTS];\npublic:\n\tstatic void Init(void);\n\tstatic void RegisterOne(CVector p0, CVector p1, CVector p2, CVector p3,\n\t\tfloat u0, float v0, float u1, float v1, float u2, float v2, float u3, float v3,\n\t\tuint8 type, uint8 red, uint8 green, uint8 blue, float maxDist); //not used\n\tstatic void Render(void);\n\tstatic void RenderOutGeometryBuffer(void);\n};\n\n\nclass CMoneyMessage\n{\n\tfriend class CMoneyMessages;\n\n\tuint32\tm_nTimeRegistered;\n\tCVector\tm_vecPosition;\n\twchar\tm_aText[16];\n\tCRGBA\tm_Colour;\n\tfloat\tm_fSize;\n\tfloat\tm_fOpacity;\npublic:\n\tvoid Render();\n};\n\n\nclass CMoneyMessages\n{\n\tstatic CMoneyMessage aMoneyMessages[NUMMONEYMESSAGES];\npublic:\n\tstatic void Init();\n\tstatic void Render();\n\tstatic void\tRegisterOne(CVector vecPos, const char *pText, uint8 bRed, uint8 bGreen, uint8 bBlue, float fSize, float fOpacity);\n};\n\n\nclass CSpecialParticleStuff\n{\n\tstatic uint32 BoatFromStart;\npublic:\n\tstatic void CreateFoamAroundObject(CMatrix*, float, float, float, int32); //not used\n\tstatic void StartBoatFoamAnimation(); //not used\n\tstatic void UpdateBoatFoamAnimation(CMatrix*); //not used\n};\n"
  },
  {
    "path": "src/render/Sprite.cpp",
    "content": "#include \"common.h\"\n\n#include \"main.h\"\n#include \"Draw.h\"\n#include \"Camera.h\"\n#include \"Sprite.h\"\n\nfloat CSprite::m_f2DNearScreenZ;\nfloat CSprite::m_f2DFarScreenZ;\nfloat CSprite::m_fRecipNearClipPlane;\nint32 CSprite::m_bFlushSpriteBufferSwitchZTest;\n\nfloat \nCSprite::CalcHorizonCoors(void)\n{\n\tCVector p = TheCamera.GetPosition() + CVector(TheCamera.CamFrontXNorm, TheCamera.CamFrontYNorm, 0.0f)*3000.0f;\n\tp.z = 0.0f;\n\tp = TheCamera.m_viewMatrix * p;\n\treturn p.y * SCREEN_HEIGHT / p.z;\n}\n\nbool \nCSprite::CalcScreenCoors(const RwV3d &in, RwV3d *out, float *outw, float *outh, bool farclip)\n{\n\tCVector viewvec = TheCamera.m_viewMatrix * in;\n\t*out = viewvec;\n\tif(out->z <= CDraw::GetNearClipZ() + 1.0f) return false;\n\tif(out->z >= CDraw::GetFarClipZ() && farclip) return false;\n\tfloat recip = 1.0f/out->z;\n\tout->x *= SCREEN_WIDTH * recip;\n\tout->y *= SCREEN_HEIGHT * recip;\n\tconst float fov = DefaultFOV;\n\t// this is used to scale correctly if you zoom in with sniper rifle\n\tfloat fovScale = fov / CDraw::GetFOV();\n\n#ifdef FIX_SPRITES\n\t*outw = CDraw::ms_bFixSprites ? (fovScale * recip * SCREEN_HEIGHT) : (fovScale * SCREEN_SCALE_AR(recip) * SCREEN_WIDTH);\n#else\n\t*outw = fovScale * SCREEN_SCALE_AR(recip) * SCREEN_WIDTH;\n#endif\n\t*outh = fovScale * recip * SCREEN_HEIGHT;\n\n\treturn true;\n}\n\n#define SPRITEBUFFERSIZE 64\nstatic int32 nSpriteBufferIndex;\nstatic RwIm2DVertex SpriteBufferVerts[SPRITEBUFFERSIZE*6];\nstatic RwIm2DVertex verts[4];\n\nvoid\nCSprite::InitSpriteBuffer(void)\n{\n\tm_f2DNearScreenZ = RwIm2DGetNearScreenZ();\n\tm_f2DFarScreenZ = RwIm2DGetFarScreenZ();\n}\n\nvoid\nCSprite::InitSpriteBuffer2D(void)\n{\n\tm_fRecipNearClipPlane = 1.0f / RwCameraGetNearClipPlane(Scene.camera);\n\tInitSpriteBuffer();\n}\n\nvoid\nCSprite::FlushSpriteBuffer(void)\n{\n\tif(nSpriteBufferIndex > 0){\n\t\tif(m_bFlushSpriteBufferSwitchZTest){\n\t\t\tRwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE);\n\t\t\tRwIm2DRenderPrimitive(rwPRIMTYPETRILIST, SpriteBufferVerts, nSpriteBufferIndex*6);\n\t\t\tRwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);\n\t\t}else\n\t\t\tRwIm2DRenderPrimitive(rwPRIMTYPETRILIST, SpriteBufferVerts, nSpriteBufferIndex*6);\n\t\tnSpriteBufferIndex = 0;\n\t}\n}\n\nvoid\nCSprite::RenderOneXLUSprite(float x, float y, float z, float w, float h, uint8 r, uint8 g, uint8 b, int16 intens, float recipz, uint8 a)\n{\n\tstatic short indices[] = { 0, 1, 2, 3 };\n\t// 0---3\n\t// |   |\n\t// 1---2\n\tfloat xs[4];\n\tfloat ys[4];\n\tfloat us[4];\n\tfloat vs[4];\n\tint i;\n\n\txs[0] = x-w;\tus[0] = 0.0f;\n\txs[1] = x-w;\tus[1] = 0.0f;\n\txs[2] = x+w;\tus[2] = 1.0f;\n\txs[3] = x+w;\tus[3] = 1.0f;\n\n\tys[0] = y-h;\tvs[0] = 0.0f;\n\tys[1] = y+h;\tvs[1] = 1.0f;\n\tys[2] = y+h;\tvs[2] = 1.0f;\n\tys[3] = y-h;\tvs[3] = 0.0f;\n\n\t// clip\n\tfor(i = 0; i < 4; i++){\n\t\tif(xs[i] < 0.0f){\n\t\t\tus[i] = -xs[i] / (2.0f*w);\n\t\t\txs[i] = 0.0f;\n\t\t}\n\t\tif(xs[i] > SCREEN_WIDTH){\n\t\t\tus[i] = 1.0f - (xs[i]-SCREEN_WIDTH) / (2.0f*w);\n\t\t\txs[i] = SCREEN_WIDTH;\n\t\t}\n\t\tif(ys[i] < 0.0f){\n\t\t\tvs[i] = -ys[i] / (2.0f*h);\n\t\t\tys[i] = 0.0f;\n\t\t}\n\t\tif(ys[i] > SCREEN_HEIGHT){\n\t\t\tvs[i] = 1.0f - (ys[i]-SCREEN_HEIGHT) / (2.0f*h);\n\t\t\tys[i] = SCREEN_HEIGHT;\n\t\t}\n\t}\n\n\t// (DrawZ - DrawNear)/(DrawFar - DrawNear) = (SpriteZ-SpriteNear)/(SpriteFar-SpriteNear)\n\t// So to calculate SpriteZ:\n\tfloat screenz = m_f2DNearScreenZ +\n\t\t(z-CDraw::GetNearClipZ())*(m_f2DFarScreenZ-m_f2DNearScreenZ)*CDraw::GetFarClipZ() /\n\t\t((CDraw::GetFarClipZ()-CDraw::GetNearClipZ())*z);\n\n\tfor(i = 0; i < 4; i++){\n\t\tRwIm2DVertexSetScreenX(&verts[i], xs[i]);\n\t\tRwIm2DVertexSetScreenY(&verts[i], ys[i]);\n\t\tRwIm2DVertexSetScreenZ(&verts[i], screenz);\n\t\tRwIm2DVertexSetCameraZ(&verts[i], z);\n\t\tRwIm2DVertexSetRecipCameraZ(&verts[i], recipz);\n\t\tRwIm2DVertexSetIntRGBA(&verts[i], r*intens>>8, g*intens>>8, b*intens>>8, a);\n\t\tRwIm2DVertexSetU(&verts[i], us[i], recipz);\n\t\tRwIm2DVertexSetV(&verts[i], vs[i], recipz);\n\t}\n\tRwIm2DRenderPrimitive(rwPRIMTYPETRIFAN, verts, 4);\n}\n\nvoid\nCSprite::RenderOneXLUSprite_Rotate_Aspect(float x, float y, float z, float w, float h, uint8 r, uint8 g, uint8 b, int16 intens, float recipz, float rotation, uint8 a)\n{\n\tfloat c = Cos(rotation);\n\tfloat s = Sin(rotation);\n\n\tfloat xs[4];\n\tfloat ys[4];\n\tfloat us[4];\n\tfloat vs[4];\n\tint i;\n\n\t// Fade out when too near\n\t// why not in buffered version?\n\tif(z < 2.3f){\n\t\tif(z < 1.3f)\n\t\t\treturn;\n\t\tint f = (z - 1.3f)/(2.3f-1.3f) * 255;\n\t\tr = f*r >> 8;\n\t\tg = f*g >> 8;\n\t\tb = f*b >> 8;\n\t\tintens = f*intens >> 8;\n\t}\n\n\txs[0] = x + w*(-c-s);\tus[0] = 0.0f;\n\txs[1] = x + w*(-c+s);\tus[1] = 0.0f;\n\txs[2] = x + w*(+c+s);\tus[2] = 1.0f;\n\txs[3] = x + w*(+c-s);\tus[3] = 1.0f;\n\n\tys[0] = y + h*(-c+s);\tvs[0] = 0.0f;\n\tys[1] = y + h*(+c+s);\tvs[1] = 1.0f;\n\tys[2] = y + h*(+c-s);\tvs[2] = 1.0f;\n\tys[3] = y + h*(-c-s);\tvs[3] = 0.0f;\n\n\t// No clipping, just culling\n\tif(xs[0] < 0.0f && xs[1] < 0.0f && xs[2] < 0.0f && xs[3] < 0.0f) return;\n\tif(ys[0] < 0.0f && ys[1] < 0.0f && ys[2] < 0.0f && ys[3] < 0.0f) return;\n\tif(xs[0] > SCREEN_WIDTH && xs[1] > SCREEN_WIDTH &&\n\t   xs[2] > SCREEN_WIDTH && xs[3] > SCREEN_WIDTH) return;\n\tif(ys[0] > SCREEN_HEIGHT && ys[1] > SCREEN_HEIGHT &&\n\t   ys[2] > SCREEN_HEIGHT && ys[3] > SCREEN_HEIGHT) return;\n\n\tfloat screenz = m_f2DNearScreenZ +\n\t\t(z-CDraw::GetNearClipZ())*(m_f2DFarScreenZ-m_f2DNearScreenZ)*CDraw::GetFarClipZ() /\n\t\t((CDraw::GetFarClipZ()-CDraw::GetNearClipZ())*z);\n\n\tfor(i = 0; i < 4; i++){\n\t\tRwIm2DVertexSetScreenX(&verts[i], xs[i]);\n\t\tRwIm2DVertexSetScreenY(&verts[i], ys[i]);\n\t\tRwIm2DVertexSetScreenZ(&verts[i], screenz);\n\t\tRwIm2DVertexSetCameraZ(&verts[i], z);\n\t\tRwIm2DVertexSetRecipCameraZ(&verts[i], recipz);\n\t\tRwIm2DVertexSetIntRGBA(&verts[i], r*intens>>8, g*intens>>8, b*intens>>8, a);\n\t\tRwIm2DVertexSetU(&verts[i], us[i], recipz);\n\t\tRwIm2DVertexSetV(&verts[i], vs[i], recipz);\n\t}\n\tRwIm2DRenderPrimitive(rwPRIMTYPETRIFAN, verts, 4);\n}\n\nvoid\nCSprite::RenderBufferedOneXLUSprite(float x, float y, float z, float w, float h, uint8 r, uint8 g, uint8 b, int16 intens, float recipz, uint8 a)\n{\n\tm_bFlushSpriteBufferSwitchZTest = 0;\n\n\t// 0---3\n\t// |   |\n\t// 1---2\n\tfloat xs[4];\n\tfloat ys[4];\n\tfloat us[4];\n\tfloat vs[4];\n\tint i;\n\n\txs[0] = x-w;\tus[0] = 0.0f;\n\txs[1] = x-w;\tus[1] = 0.0f;\n\txs[2] = x+w;\tus[2] = 1.0f;\n\txs[3] = x+w;\tus[3] = 1.0f;\n\n\tys[0] = y-h;\tvs[0] = 0.0f;\n\tys[1] = y+h;\tvs[1] = 1.0f;\n\tys[2] = y+h;\tvs[2] = 1.0f;\n\tys[3] = y-h;\tvs[3] = 0.0f;\n\n\t// clip\n\tfor(i = 0; i < 4; i++){\n\t\tif(xs[i] < 0.0f){\n\t\t\tus[i] = -xs[i] / (2.0f*w);\n\t\t\txs[i] = 0.0f;\n\t\t}\n\t\tif(xs[i] > SCREEN_WIDTH){\n\t\t\tus[i] = 1.0f - (xs[i]-SCREEN_WIDTH) / (2.0f*w);\n\t\t\txs[i] = SCREEN_WIDTH;\n\t\t}\n\t\tif(ys[i] < 0.0f){\n\t\t\tvs[i] = -ys[i] / (2.0f*h);\n\t\t\tys[i] = 0.0f;\n\t\t}\n\t\tif(ys[i] > SCREEN_HEIGHT){\n\t\t\tvs[i] = 1.0f - (ys[i]-SCREEN_HEIGHT) / (2.0f*h);\n\t\t\tys[i] = SCREEN_HEIGHT;\n\t\t}\n\t}\n\n\tfloat screenz = m_f2DNearScreenZ +\n\t\t(z-CDraw::GetNearClipZ())*(m_f2DFarScreenZ-m_f2DNearScreenZ)*CDraw::GetFarClipZ() /\n\t\t((CDraw::GetFarClipZ()-CDraw::GetNearClipZ())*z);\n\n\tRwIm2DVertex *vert = &SpriteBufferVerts[nSpriteBufferIndex*6];\n\tstatic int indices[6] = { 0, 1, 2, 3, 0, 2 };\n\tfor(i = 0; i < 6; i++){\n\t\tRwIm2DVertexSetScreenX(&vert[i], xs[indices[i]]);\n\t\tRwIm2DVertexSetScreenY(&vert[i], ys[indices[i]]);\n\t\tRwIm2DVertexSetScreenZ(&vert[i], screenz);\n\t\tRwIm2DVertexSetCameraZ(&vert[i], z);\n\t\tRwIm2DVertexSetRecipCameraZ(&vert[i], recipz);\n\t\tRwIm2DVertexSetIntRGBA(&vert[i], r*intens>>8, g*intens>>8, b*intens>>8, a);\n\t\tRwIm2DVertexSetU(&vert[i], us[indices[i]], recipz);\n\t\tRwIm2DVertexSetV(&vert[i], vs[indices[i]], recipz);\n\t}\n\tnSpriteBufferIndex++;\n\tif(nSpriteBufferIndex >= SPRITEBUFFERSIZE)\n\t\tFlushSpriteBuffer();\n}\n\nvoid\nCSprite::RenderBufferedOneXLUSprite_Rotate_Dimension(float x, float y, float z, float w, float h, uint8 r, uint8 g, uint8 b, int16 intens, float recipz, float rotation, uint8 a)\n{\n\tm_bFlushSpriteBufferSwitchZTest = 0;\n\t// TODO: replace with lookup\n\tfloat c = Cos(rotation);\n\tfloat s = Sin(rotation);\n\n\tfloat xs[4];\n\tfloat ys[4];\n\tfloat us[4];\n\tfloat vs[4];\n\tint i;\n\n\txs[0] = x - c*w - s*h;\tus[0] = 0.0f;\n\txs[1] = x - c*w + s*h;\tus[1] = 0.0f;\n\txs[2] = x + c*w + s*h;\tus[2] = 1.0f;\n\txs[3] = x + c*w - s*h;\tus[3] = 1.0f;\n\n\tys[0] = y - c*h + s*w;\tvs[0] = 0.0f;\n\tys[1] = y + c*h + s*w;\tvs[1] = 1.0f;\n\tys[2] = y + c*h - s*w;\tvs[2] = 1.0f;\n\tys[3] = y - c*h - s*w;\tvs[3] = 0.0f;\n\n\t// No clipping, just culling\n\tif(xs[0] < 0.0f && xs[1] < 0.0f && xs[2] < 0.0f && xs[3] < 0.0f) return;\n\tif(ys[0] < 0.0f && ys[1] < 0.0f && ys[2] < 0.0f && ys[3] < 0.0f) return;\n\tif(xs[0] > SCREEN_WIDTH && xs[1] > SCREEN_WIDTH &&\n\t   xs[2] > SCREEN_WIDTH && xs[3] > SCREEN_WIDTH) return;\n\tif(ys[0] > SCREEN_HEIGHT && ys[1] > SCREEN_HEIGHT &&\n\t   ys[2] > SCREEN_HEIGHT && ys[3] > SCREEN_HEIGHT) return;\n\n\tfloat screenz = m_f2DNearScreenZ +\n\t\t(z-CDraw::GetNearClipZ())*(m_f2DFarScreenZ-m_f2DNearScreenZ)*CDraw::GetFarClipZ() /\n\t\t((CDraw::GetFarClipZ()-CDraw::GetNearClipZ())*z);\n\n\tRwIm2DVertex *vert = &SpriteBufferVerts[nSpriteBufferIndex*6];\n\tstatic int indices[6] = { 0, 1, 2, 3, 0, 2 };\n\tfor(i = 0; i < 6; i++){\n\t\tRwIm2DVertexSetScreenX(&vert[i], xs[indices[i]]);\n\t\tRwIm2DVertexSetScreenY(&vert[i], ys[indices[i]]);\n\t\tRwIm2DVertexSetScreenZ(&vert[i], screenz);\n\t\tRwIm2DVertexSetCameraZ(&vert[i], z);\n\t\tRwIm2DVertexSetRecipCameraZ(&vert[i], recipz);\n\t\tRwIm2DVertexSetIntRGBA(&vert[i], r*intens>>8, g*intens>>8, b*intens>>8, a);\n\t\tRwIm2DVertexSetU(&vert[i], us[indices[i]], recipz);\n\t\tRwIm2DVertexSetV(&vert[i], vs[indices[i]], recipz);\n\t}\n\tnSpriteBufferIndex++;\n\tif(nSpriteBufferIndex >= SPRITEBUFFERSIZE)\n\t\tFlushSpriteBuffer();\n}\n\nvoid\nCSprite::RenderBufferedOneXLUSprite_Rotate_Aspect(float x, float y, float z, float w, float h, uint8 r, uint8 g, uint8 b, int16 intens, float recipz, float rotation, uint8 a)\n{\n\tm_bFlushSpriteBufferSwitchZTest = 0;\n\tfloat c = Cos(rotation);\n\tfloat s = Sin(rotation);\n\n\tfloat xs[4];\n\tfloat ys[4];\n\tfloat us[4];\n\tfloat vs[4];\n\tint i;\n\n\txs[0] = x + w*(-c-s);\tus[0] = 0.0f;\n\txs[1] = x + w*(-c+s);\tus[1] = 0.0f;\n\txs[2] = x + w*(+c+s);\tus[2] = 1.0f;\n\txs[3] = x + w*(+c-s);\tus[3] = 1.0f;\n\n\tys[0] = y + h*(-c+s);\tvs[0] = 0.0f;\n\tys[1] = y + h*(+c+s);\tvs[1] = 1.0f;\n\tys[2] = y + h*(+c-s);\tvs[2] = 1.0f;\n\tys[3] = y + h*(-c-s);\tvs[3] = 0.0f;\n\n\t// No clipping, just culling\n\tif(xs[0] < 0.0f && xs[1] < 0.0f && xs[2] < 0.0f && xs[3] < 0.0f) return;\n\tif(ys[0] < 0.0f && ys[1] < 0.0f && ys[2] < 0.0f && ys[3] < 0.0f) return;\n\tif(xs[0] > SCREEN_WIDTH && xs[1] > SCREEN_WIDTH &&\n\t   xs[2] > SCREEN_WIDTH && xs[3] > SCREEN_WIDTH) return;\n\tif(ys[0] > SCREEN_HEIGHT && ys[1] > SCREEN_HEIGHT &&\n\t   ys[2] > SCREEN_HEIGHT && ys[3] > SCREEN_HEIGHT) return;\n\n\tfloat screenz = m_f2DNearScreenZ +\n\t\t(z-CDraw::GetNearClipZ())*(m_f2DFarScreenZ-m_f2DNearScreenZ)*CDraw::GetFarClipZ() /\n\t\t((CDraw::GetFarClipZ()-CDraw::GetNearClipZ())*z);\n\n\tRwIm2DVertex *vert = &SpriteBufferVerts[nSpriteBufferIndex*6];\n\tstatic int indices[6] = { 0, 1, 2, 3, 0, 2 };\n\tfor(i = 0; i < 6; i++){\n\t\tRwIm2DVertexSetScreenX(&vert[i], xs[indices[i]]);\n\t\tRwIm2DVertexSetScreenY(&vert[i], ys[indices[i]]);\n\t\tRwIm2DVertexSetScreenZ(&vert[i], screenz);\n\t\tRwIm2DVertexSetCameraZ(&vert[i], z);\n\t\tRwIm2DVertexSetRecipCameraZ(&vert[i], recipz);\n\t\tRwIm2DVertexSetIntRGBA(&vert[i], r*intens>>8, g*intens>>8, b*intens>>8, a);\n\t\tRwIm2DVertexSetU(&vert[i], us[indices[i]], recipz);\n\t\tRwIm2DVertexSetV(&vert[i], vs[indices[i]], recipz);\n\t}\n\tnSpriteBufferIndex++;\n\tif(nSpriteBufferIndex >= SPRITEBUFFERSIZE)\n\t\tFlushSpriteBuffer();\n}\n\nvoid\nCSprite::RenderBufferedOneXLUSprite_Rotate_2Colours(float x, float y, float z, float w, float h, uint8 r1, uint8 g1, uint8 b1, uint8 r2, uint8 g2, uint8 b2, float cx, float cy, float recipz, float rotation, uint8 a)\n{\n\tm_bFlushSpriteBufferSwitchZTest = 0;\n\tfloat c = Cos(rotation);\n\tfloat s = Sin(rotation);\n\n\tfloat xs[4];\n\tfloat ys[4];\n\tfloat us[4];\n\tfloat vs[4];\n\tfloat cf[4];\n\tint i;\n\n\txs[0] = x + w*(-c-s);\tus[0] = 0.0f;\n\txs[1] = x + w*(-c+s);\tus[1] = 0.0f;\n\txs[2] = x + w*(+c+s);\tus[2] = 1.0f;\n\txs[3] = x + w*(+c-s);\tus[3] = 1.0f;\n\n\tys[0] = y + h*(-c+s);\tvs[0] = 0.0f;\n\tys[1] = y + h*(+c+s);\tvs[1] = 1.0f;\n\tys[2] = y + h*(+c-s);\tvs[2] = 1.0f;\n\tys[3] = y + h*(-c-s);\tvs[3] = 0.0f;\n\n\t// No clipping, just culling\n\tif(xs[0] < 0.0f && xs[1] < 0.0f && xs[2] < 0.0f && xs[3] < 0.0f) return;\n\tif(ys[0] < 0.0f && ys[1] < 0.0f && ys[2] < 0.0f && ys[3] < 0.0f) return;\n\tif(xs[0] > SCREEN_WIDTH && xs[1] > SCREEN_WIDTH &&\n\t   xs[2] > SCREEN_WIDTH && xs[3] > SCREEN_WIDTH) return;\n\tif(ys[0] > SCREEN_HEIGHT && ys[1] > SCREEN_HEIGHT &&\n\t   ys[2] > SCREEN_HEIGHT && ys[3] > SCREEN_HEIGHT) return;\n\n\t// Colour factors, cx/y is the direction in which colours change from rgb1 to rgb2\n\tcf[0] = (cx*(-c-s) + cy*(-c+s))*0.5f + 0.5f;\n\tcf[0] = clamp(cf[0], 0.0f, 1.0f);\n\tcf[1] = (cx*(-c+s) + cy*( c+s))*0.5f + 0.5f;\n\tcf[1] = clamp(cf[1], 0.0f, 1.0f);\n\tcf[2] = (cx*( c+s) + cy*( c-s))*0.5f + 0.5f;\n\tcf[2] = clamp(cf[2], 0.0f, 1.0f);\n\tcf[3] = (cx*( c-s) + cy*(-c-s))*0.5f + 0.5f;\n\tcf[3] = clamp(cf[3], 0.0f, 1.0f);\n\n\tfloat screenz = m_f2DNearScreenZ +\n\t\t(z-CDraw::GetNearClipZ())*(m_f2DFarScreenZ-m_f2DNearScreenZ)*CDraw::GetFarClipZ() /\n\t\t((CDraw::GetFarClipZ()-CDraw::GetNearClipZ())*z);\n\n\tRwIm2DVertex *vert = &SpriteBufferVerts[nSpriteBufferIndex*6];\n\tstatic int indices[6] = { 0, 1, 2, 3, 0, 2 };\n\tfor(i = 0; i < 6; i++){\n\t\tRwIm2DVertexSetScreenX(&vert[i], xs[indices[i]]);\n\t\tRwIm2DVertexSetScreenY(&vert[i], ys[indices[i]]);\n\t\tRwIm2DVertexSetScreenZ(&vert[i], screenz);\n\t\tRwIm2DVertexSetCameraZ(&vert[i], z);\n\t\tRwIm2DVertexSetRecipCameraZ(&vert[i], recipz);\n\t\tRwIm2DVertexSetIntRGBA(&vert[i],\n\t\t\tr1*cf[indices[i]] + r2*(1.0f - cf[indices[i]]),\n\t\t\tg1*cf[indices[i]] + g2*(1.0f - cf[indices[i]]),\n\t\t\tb1*cf[indices[i]] + b2*(1.0f - cf[indices[i]]),\n\t\t\ta);\n\t\tRwIm2DVertexSetU(&vert[i], us[indices[i]], recipz);\n\t\tRwIm2DVertexSetV(&vert[i], vs[indices[i]], recipz);\n\t}\n\tnSpriteBufferIndex++;\n\tif(nSpriteBufferIndex >= SPRITEBUFFERSIZE)\n\t\tFlushSpriteBuffer();\n}\n\nvoid\nCSprite::Set6Vertices2D(RwIm2DVertex *verts, const CRect &r, const CRGBA &c0, const CRGBA &c1, const CRGBA &c2, const CRGBA &c3)\n{\n\tfloat screenz, recipz;\n\tfloat z = RwCameraGetNearClipPlane(Scene.camera);\t// not done by game\n\n\tscreenz = m_f2DNearScreenZ;\n\trecipz = m_fRecipNearClipPlane;\n\n\tRwIm2DVertexSetScreenX(&verts[0], r.left);\n\tRwIm2DVertexSetScreenY(&verts[0], r.top);\n\tRwIm2DVertexSetScreenZ(&verts[0], screenz);\n\tRwIm2DVertexSetCameraZ(&verts[0], z);\n\tRwIm2DVertexSetRecipCameraZ(&verts[0], recipz);\n\tRwIm2DVertexSetIntRGBA(&verts[0], c2.r, c2.g, c2.b, c2.a);\n\tRwIm2DVertexSetU(&verts[0], 0.0f, recipz);\n\tRwIm2DVertexSetV(&verts[0], 0.0f, recipz);\n\n\tRwIm2DVertexSetScreenX(&verts[1], r.right);\n\tRwIm2DVertexSetScreenY(&verts[1], r.top);\n\tRwIm2DVertexSetScreenZ(&verts[1], screenz);\n\tRwIm2DVertexSetCameraZ(&verts[1], z);\n\tRwIm2DVertexSetRecipCameraZ(&verts[1], recipz);\n\tRwIm2DVertexSetIntRGBA(&verts[1], c3.r, c3.g, c3.b, c3.a);\n\tRwIm2DVertexSetU(&verts[1], 1.0f, recipz);\n\tRwIm2DVertexSetV(&verts[1], 0.0f, recipz);\n\n\tRwIm2DVertexSetScreenX(&verts[2], r.right);\n\tRwIm2DVertexSetScreenY(&verts[2], r.bottom);\n\tRwIm2DVertexSetScreenZ(&verts[2], screenz);\n\tRwIm2DVertexSetCameraZ(&verts[2], z);\n\tRwIm2DVertexSetRecipCameraZ(&verts[2], recipz);\n\tRwIm2DVertexSetIntRGBA(&verts[2], c1.r, c1.g, c1.b, c1.a);\n\tRwIm2DVertexSetU(&verts[2], 1.0f, recipz);\n\tRwIm2DVertexSetV(&verts[2], 1.0f, recipz);\n\n\tRwIm2DVertexSetScreenX(&verts[3], r.left);\n\tRwIm2DVertexSetScreenY(&verts[3], r.bottom);\n\tRwIm2DVertexSetScreenZ(&verts[3], screenz);\n\tRwIm2DVertexSetCameraZ(&verts[3], z);\n\tRwIm2DVertexSetRecipCameraZ(&verts[3], recipz);\n\tRwIm2DVertexSetIntRGBA(&verts[3], c0.r, c0.g, c0.b, c0.a);\n\tRwIm2DVertexSetU(&verts[3], 0.0f, recipz);\n\tRwIm2DVertexSetV(&verts[3], 1.0f, recipz);\n\n\tRwIm2DVertexSetScreenX(&verts[4], r.left);\n\tRwIm2DVertexSetScreenY(&verts[4], r.top);\n\tRwIm2DVertexSetScreenZ(&verts[4], screenz);\n\tRwIm2DVertexSetCameraZ(&verts[4], z);\n\tRwIm2DVertexSetRecipCameraZ(&verts[4], recipz);\n\tRwIm2DVertexSetIntRGBA(&verts[4], c2.r, c2.g, c2.b, c2.a);\n\tRwIm2DVertexSetU(&verts[4], 0.0f, recipz);\n\tRwIm2DVertexSetV(&verts[4], 0.0f, recipz);\n\n\tRwIm2DVertexSetScreenX(&verts[5], r.right);\n\tRwIm2DVertexSetScreenY(&verts[5], r.bottom);\n\tRwIm2DVertexSetScreenZ(&verts[5], screenz);\n\tRwIm2DVertexSetCameraZ(&verts[5], z);\n\tRwIm2DVertexSetRecipCameraZ(&verts[5], recipz);\n\tRwIm2DVertexSetIntRGBA(&verts[5], c1.r, c1.g, c1.b, c1.a);\n\tRwIm2DVertexSetU(&verts[5], 1.0f, recipz);\n\tRwIm2DVertexSetV(&verts[5], 1.0f, recipz);\n}\n\nvoid\nCSprite::Set6Vertices2D(RwIm2DVertex *verts, float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4,\n\t\tconst CRGBA &c0, const CRGBA &c1, const CRGBA &c2, const CRGBA &c3)\n{\n\tfloat screenz, recipz;\n\tfloat z = RwCameraGetNearClipPlane(Scene.camera);\t// not done by game\n\n\tscreenz = m_f2DNearScreenZ;\n\trecipz = m_fRecipNearClipPlane;\n\n\tRwIm2DVertexSetScreenX(&verts[0], x3);\n\tRwIm2DVertexSetScreenY(&verts[0], y3);\n\tRwIm2DVertexSetScreenZ(&verts[0], screenz);\n\tRwIm2DVertexSetCameraZ(&verts[0], z);\n\tRwIm2DVertexSetRecipCameraZ(&verts[0], recipz);\n\tRwIm2DVertexSetIntRGBA(&verts[0], c2.r, c2.g, c2.b, c2.a);\n\tRwIm2DVertexSetU(&verts[0], 0.0f, recipz);\n\tRwIm2DVertexSetV(&verts[0], 0.0f, recipz);\n\n\tRwIm2DVertexSetScreenX(&verts[1], x4);\n\tRwIm2DVertexSetScreenY(&verts[1], y4);\n\tRwIm2DVertexSetScreenZ(&verts[1], screenz);\n\tRwIm2DVertexSetCameraZ(&verts[1], z);\n\tRwIm2DVertexSetRecipCameraZ(&verts[1], recipz);\n\tRwIm2DVertexSetIntRGBA(&verts[1], c3.r, c3.g, c3.b, c3.a);\n\tRwIm2DVertexSetU(&verts[1], 1.0f, recipz);\n\tRwIm2DVertexSetV(&verts[1], 0.0f, recipz);\n\n\tRwIm2DVertexSetScreenX(&verts[2], x2);\n\tRwIm2DVertexSetScreenY(&verts[2], y2);\n\tRwIm2DVertexSetScreenZ(&verts[2], screenz);\n\tRwIm2DVertexSetCameraZ(&verts[2], z);\n\tRwIm2DVertexSetRecipCameraZ(&verts[2], recipz);\n\tRwIm2DVertexSetIntRGBA(&verts[2], c1.r, c1.g, c1.b, c1.a);\n\tRwIm2DVertexSetU(&verts[2], 1.0f, recipz);\n\tRwIm2DVertexSetV(&verts[2], 1.0f, recipz);\n\n\tRwIm2DVertexSetScreenX(&verts[3], x1);\n\tRwIm2DVertexSetScreenY(&verts[3], y1);\n\tRwIm2DVertexSetScreenZ(&verts[3], screenz);\n\tRwIm2DVertexSetCameraZ(&verts[3], z);\n\tRwIm2DVertexSetRecipCameraZ(&verts[3], recipz);\n\tRwIm2DVertexSetIntRGBA(&verts[3], c0.r, c0.g, c0.b, c0.a);\n\tRwIm2DVertexSetU(&verts[3], 0.0f, recipz);\n\tRwIm2DVertexSetV(&verts[3], 1.0f, recipz);\n\n\tRwIm2DVertexSetScreenX(&verts[4], x3);\n\tRwIm2DVertexSetScreenY(&verts[4], y3);\n\tRwIm2DVertexSetScreenZ(&verts[4], screenz);\n\tRwIm2DVertexSetCameraZ(&verts[4], z);\n\tRwIm2DVertexSetRecipCameraZ(&verts[4], recipz);\n\tRwIm2DVertexSetIntRGBA(&verts[4], c2.r, c2.g, c2.b, c2.a);\n\tRwIm2DVertexSetU(&verts[4], 0.0f, recipz);\n\tRwIm2DVertexSetV(&verts[4], 0.0f, recipz);\n\n\tRwIm2DVertexSetScreenX(&verts[5], x2);\n\tRwIm2DVertexSetScreenY(&verts[5], y2);\n\tRwIm2DVertexSetScreenZ(&verts[5], screenz);\n\tRwIm2DVertexSetCameraZ(&verts[5], z);\n\tRwIm2DVertexSetRecipCameraZ(&verts[5], recipz);\n\tRwIm2DVertexSetIntRGBA(&verts[5], c1.r, c1.g, c1.b, c1.a);\n\tRwIm2DVertexSetU(&verts[5], 1.0f, recipz);\n\tRwIm2DVertexSetV(&verts[5], 1.0f, recipz);\n}\n\nvoid\nCSprite::RenderBufferedOneXLUSprite2D(float x, float y, float w, float h, const RwRGBA &colour, int16 intens, uint8 alpha)\n{\n\tm_bFlushSpriteBufferSwitchZTest = 1;\n\tCRGBA col(intens * colour.red >> 8, intens * colour.green >> 8, intens * colour.blue >> 8, alpha);\n\tCRect rect(x - w, y - h, x + h, y + h);\n\tSet6Vertices2D(&SpriteBufferVerts[6 * nSpriteBufferIndex], rect, col, col, col, col);\n\tnSpriteBufferIndex++;\n\tif(nSpriteBufferIndex >= SPRITEBUFFERSIZE)\n\t\tFlushSpriteBuffer();\n}\n\nvoid\nCSprite::RenderBufferedOneXLUSprite2D_Rotate_Dimension(float x, float y, float w, float h, const RwRGBA &colour, int16 intens, float rotation, uint8 alpha)\n{\n\tm_bFlushSpriteBufferSwitchZTest = 1;\n\tCRGBA col(intens * colour.red >> 8, intens * colour.green >> 8, intens * colour.blue >> 8, alpha);\n\tfloat c = Cos(rotation);\n\tfloat s = Sin(rotation);\n\n\tSet6Vertices2D(&SpriteBufferVerts[6 * nSpriteBufferIndex],\n\t\tx + c*w - s*h,\n\t\ty - c*h - s*w,\n\t\tx + c*w + s*h,\n\t\ty + c*h - s*w,\n\t\tx - c*w - s*h,\n\t\ty - c*h + s*w,\n\t\tx - c*w + s*h,\n\t\ty + c*h + s*w,\n\t\tcol, col, col, col);\n\tnSpriteBufferIndex++;\n\tif(nSpriteBufferIndex >= SPRITEBUFFERSIZE)\n\t\tFlushSpriteBuffer();\n}\n"
  },
  {
    "path": "src/render/Sprite.h",
    "content": "#pragma once\n\nclass CSprite\n{\n\tstatic float m_f2DNearScreenZ;\n\tstatic float m_f2DFarScreenZ;\n\tstatic float m_fRecipNearClipPlane;\n\tstatic int32 m_bFlushSpriteBufferSwitchZTest;\npublic:\n\tstatic float GetNearScreenZ(void) { return m_f2DNearScreenZ; }\n\tstatic float GetFarScreenZ(void) { return m_f2DFarScreenZ; }\n\n\tstatic float CalcHorizonCoors(void);\n\tstatic bool CalcScreenCoors(const RwV3d &in, RwV3d *out, float *outw, float *outh, bool farclip);\n\tstatic void InitSpriteBuffer(void);\n\tstatic void InitSpriteBuffer2D(void);\n\tstatic void FlushSpriteBuffer(void);\n\tstatic void RenderOneXLUSprite(float x, float y, float z, float w, float h, uint8 r, uint8 g, uint8 b, int16 intens, float recipz, uint8 a);\n\tstatic void RenderOneXLUSprite_Rotate_Aspect(float x, float y, float z, float w, float h, uint8 r, uint8 g, uint8 b, int16 intens, float recipz, float roll, uint8 a);\n\tstatic void RenderBufferedOneXLUSprite(float x, float y, float z, float w, float h, uint8 r, uint8 g, uint8 b, int16 intens, float recipz, uint8 a);\n\tstatic void RenderBufferedOneXLUSprite_Rotate_Dimension(float x, float y, float z, float w, float h, uint8 r, uint8 g, uint8 b, int16 intens, float recipz, float roll, uint8 a);\n\tstatic void RenderBufferedOneXLUSprite_Rotate_Aspect(float x, float y, float z, float w, float h, uint8 r, uint8 g, uint8 b, int16 intens, float recipz, float roll, uint8 a);\n\t// cx/y is the direction in which the colour changes\n\tstatic void RenderBufferedOneXLUSprite_Rotate_2Colours(float x, float y, float z, float w, float h, uint8 r1, uint8 g1, uint8 b1, uint8 r2, uint8 g2, uint8 b2, float cx, float cy, float recipz, float rotation, uint8 a);\n\tstatic void Set6Vertices2D(RwIm2DVertex *verts, const CRect &r, const CRGBA &c0, const CRGBA &c1, const CRGBA &c2, const CRGBA &c3);\n\tstatic void Set6Vertices2D(RwIm2DVertex *verts, float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4,\n\t\tconst CRGBA &c0, const CRGBA &c1, const CRGBA &c2, const CRGBA &c3);\n\tstatic void RenderBufferedOneXLUSprite2D(float x, float y, float w, float h, const RwRGBA &colour, int16 intens, uint8 alpha);\n\tstatic void RenderBufferedOneXLUSprite2D_Rotate_Dimension(float x, float y, float w, float h, const RwRGBA &colour, int16 intens, float rotation, uint8 alpha);\n\n};\n"
  },
  {
    "path": "src/render/Sprite2d.cpp",
    "content": "#include \"common.h\"\n\n#include \"main.h\"\n#include \"Draw.h\"\n#include \"Camera.h\"\n#include \"Sprite2d.h\"\n#include \"Font.h\"\n#include \"RenderBuffer.h\"\n\nfloat CSprite2d::RecipNearClip;\nfloat CSprite2d::NearScreenZ;\nfloat CSprite2d::NearCamZ;\nint CSprite2d::nextBufferVertex;\nint CSprite2d::nextBufferIndex;\nRwIm2DVertex CSprite2d::maVertices[8];\n\nvoid\nCSprite2d::SetRecipNearClip(void)\n{\n\t// Used but empty in VC, instead they set in InitPerFrame. Isn't that great?\n}\n\nvoid\nCSprite2d::InitPerFrame(void)\n{\n\tnextBufferVertex = 0;\n\tnextBufferIndex = 0;\n\tRecipNearClip = 1.0f / RwCameraGetNearClipPlane(Scene.camera);\n\tNearScreenZ = RwIm2DGetNearScreenZ();\n\t// not original but you're supposed to set camera z too\n\t// wrapping all this in FIX_BUGS is too ugly\n\tNearCamZ = RwCameraGetNearClipPlane(Scene.camera);\n}\nvoid\nCSprite2d::Delete(void)\n{\n\tif(m_pTexture){\n\t\tRwTextureDestroy(m_pTexture);\n\t\tm_pTexture = nil;\n\t}\n}\n\nvoid\nCSprite2d::SetTexture(const char *name)\n{\n\tDelete();\n\tif(name)\n\t\tm_pTexture = RwTextureRead(name, nil);\n}\n\nvoid\nCSprite2d::SetTexture(const char *name, const char *mask)\n{\n\tDelete();\n\tif(name)\n\t\tm_pTexture = RwTextureRead(name, mask);\n}\n\nvoid\nCSprite2d::SetAddressing(RwTextureAddressMode addr)\n{\n\tif(m_pTexture)\n\t\tRwTextureSetAddressing(m_pTexture, addr);\n}\n\nvoid\nCSprite2d::SetRenderState(void)\n{\n\tif(m_pTexture)\n\t\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(m_pTexture));\n\telse\n\t\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil);\n}\n\nvoid\nCSprite2d::Draw(float x, float y, float w, float h, const CRGBA &col)\n{\n\tSetVertices(CRect(x, y, x + w, y + h), col, col, col, col);\n\tSetRenderState();\n\tRwIm2DRenderPrimitive(rwPRIMTYPETRIFAN, CSprite2d::maVertices, 4);\n}\n\nvoid\nCSprite2d::Draw(const CRect &rect, const CRGBA &col)\n{\n\tSetVertices(rect, col, col, col, col);\n\tSetRenderState();\n\tRwIm2DRenderPrimitive(rwPRIMTYPETRIFAN, CSprite2d::maVertices, 4);\n}\n\nvoid\nCSprite2d::Draw(const CRect &rect, const CRGBA &col,\n\tfloat u0, float v0, float u1, float v1, float u3, float v3, float u2, float v2)\n{\n\tSetVertices(rect, col, col, col, col, u0, v0, u1, v1, u3, v3, u2, v2);\n\tSetRenderState();\n\tRwIm2DRenderPrimitive(rwPRIMTYPETRIFAN, CSprite2d::maVertices, 4);\n}\n\nvoid\nCSprite2d::Draw(const CRect &rect, const CRGBA &c0, const CRGBA &c1, const CRGBA &c2, const CRGBA &c3)\n{\n\tSetVertices(rect, c0, c1, c2, c3);\n\tSetRenderState();\n\tRwIm2DRenderPrimitive(rwPRIMTYPETRIFAN, CSprite2d::maVertices, 4);\n}\n\nvoid\nCSprite2d::Draw(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4, const CRGBA &col)\n{\n\tSetVertices(x1, y1, x2, y2, x3, y3, x4, y4, col, col, col, col);\n\tSetRenderState();\n\tRwIm2DRenderPrimitive(rwPRIMTYPETRIFAN, CSprite2d::maVertices, 4);\n}\n\n// Arguments:\n// 2---3\n// |   |\n// 0---1\nvoid\nCSprite2d::SetVertices(const CRect &r, const CRGBA &c0, const CRGBA &c1, const CRGBA &c2, const CRGBA &c3)\n{\n\tfloat offset = 1.0f/1024.0f;\n\n\t// This is what we draw:\n\t// 0---1\n\t// | / |\n\t// 3---2\n\tRwIm2DVertexSetScreenX(&maVertices[0], r.left);\n\tRwIm2DVertexSetScreenY(&maVertices[0], r.top);\n\tRwIm2DVertexSetScreenZ(&maVertices[0], NearScreenZ);\n\tRwIm2DVertexSetCameraZ(&maVertices[0], NearCamZ);\n\tRwIm2DVertexSetRecipCameraZ(&maVertices[0], RecipNearClip);\n\tRwIm2DVertexSetIntRGBA(&maVertices[0], c2.r, c2.g, c2.b, c2.a);\n\tRwIm2DVertexSetU(&maVertices[0], 0.0f+offset, RecipNearClip);\n\tRwIm2DVertexSetV(&maVertices[0], 0.0f+offset, RecipNearClip);\n\n\tRwIm2DVertexSetScreenX(&maVertices[1], r.right);\n\tRwIm2DVertexSetScreenY(&maVertices[1], r.top);\n\tRwIm2DVertexSetScreenZ(&maVertices[1], NearScreenZ);\n\tRwIm2DVertexSetCameraZ(&maVertices[1], NearCamZ);\n\tRwIm2DVertexSetRecipCameraZ(&maVertices[1], RecipNearClip);\n\tRwIm2DVertexSetIntRGBA(&maVertices[1], c3.r, c3.g, c3.b, c3.a);\n\tRwIm2DVertexSetU(&maVertices[1], 1.0f+offset, RecipNearClip);\n\tRwIm2DVertexSetV(&maVertices[1], 0.0f+offset, RecipNearClip);\n\n\tRwIm2DVertexSetScreenX(&maVertices[2], r.right);\n\tRwIm2DVertexSetScreenY(&maVertices[2], r.bottom);\n\tRwIm2DVertexSetScreenZ(&maVertices[2], NearScreenZ);\n\tRwIm2DVertexSetCameraZ(&maVertices[2], NearCamZ);\n\tRwIm2DVertexSetRecipCameraZ(&maVertices[2], RecipNearClip);\n\tRwIm2DVertexSetIntRGBA(&maVertices[2], c1.r, c1.g, c1.b, c1.a);\n\tRwIm2DVertexSetU(&maVertices[2], 1.0f+offset, RecipNearClip);\n\tRwIm2DVertexSetV(&maVertices[2], 1.0f+offset, RecipNearClip);\n\n\tRwIm2DVertexSetScreenX(&maVertices[3], r.left);\n\tRwIm2DVertexSetScreenY(&maVertices[3], r.bottom);\n\tRwIm2DVertexSetScreenZ(&maVertices[3], NearScreenZ);\n\tRwIm2DVertexSetCameraZ(&maVertices[3], NearCamZ);\n\tRwIm2DVertexSetRecipCameraZ(&maVertices[3], RecipNearClip);\n\tRwIm2DVertexSetIntRGBA(&maVertices[3], c0.r, c0.g, c0.b, c0.a);\n\tRwIm2DVertexSetU(&maVertices[3], 0.0f+offset, RecipNearClip);\n\tRwIm2DVertexSetV(&maVertices[3], 1.0f+offset, RecipNearClip);\n}\n\nvoid\nCSprite2d::SetVertices(const CRect &r, const CRGBA &c0, const CRGBA &c1, const CRGBA &c2, const CRGBA &c3,\n\tfloat u0, float v0, float u1, float v1, float u3, float v3, float u2, float v2)\n{\n\t// This is what we draw:\n\t// 0---1\n\t// | / |\n\t// 3---2\n\tRwIm2DVertexSetScreenX(&maVertices[0], r.left);\n\tRwIm2DVertexSetScreenY(&maVertices[0], r.top);\n\tRwIm2DVertexSetScreenZ(&maVertices[0], NearScreenZ);\n\tRwIm2DVertexSetCameraZ(&maVertices[0], NearCamZ);\n\tRwIm2DVertexSetRecipCameraZ(&maVertices[0], RecipNearClip);\n\tRwIm2DVertexSetIntRGBA(&maVertices[0], c2.r, c2.g, c2.b, c2.a);\n\tRwIm2DVertexSetU(&maVertices[0], u0, RecipNearClip);\n\tRwIm2DVertexSetV(&maVertices[0], v0, RecipNearClip);\n\n\tRwIm2DVertexSetScreenX(&maVertices[1], r.right);\n\tRwIm2DVertexSetScreenY(&maVertices[1], r.top);\n\tRwIm2DVertexSetScreenZ(&maVertices[1], NearScreenZ);\n\tRwIm2DVertexSetCameraZ(&maVertices[1], NearCamZ);\n\tRwIm2DVertexSetRecipCameraZ(&maVertices[1], RecipNearClip);\n\tRwIm2DVertexSetIntRGBA(&maVertices[1], c3.r, c3.g, c3.b, c3.a);\n\tRwIm2DVertexSetU(&maVertices[1], u1, RecipNearClip);\n\tRwIm2DVertexSetV(&maVertices[1], v1, RecipNearClip);\n\n\tRwIm2DVertexSetScreenX(&maVertices[2], r.right);\n\tRwIm2DVertexSetScreenY(&maVertices[2], r.bottom);\n\tRwIm2DVertexSetScreenZ(&maVertices[2], NearScreenZ);\n\tRwIm2DVertexSetCameraZ(&maVertices[2], NearCamZ);\n\tRwIm2DVertexSetRecipCameraZ(&maVertices[2], RecipNearClip);\n\tRwIm2DVertexSetIntRGBA(&maVertices[2], c1.r, c1.g, c1.b, c1.a);\n\tRwIm2DVertexSetU(&maVertices[2], u2, RecipNearClip);\n\tRwIm2DVertexSetV(&maVertices[2], v2, RecipNearClip);\n\n\tRwIm2DVertexSetScreenX(&maVertices[3], r.left);\n\tRwIm2DVertexSetScreenY(&maVertices[3], r.bottom);\n\tRwIm2DVertexSetScreenZ(&maVertices[3], NearScreenZ);\n\tRwIm2DVertexSetCameraZ(&maVertices[3], NearCamZ);\n\tRwIm2DVertexSetRecipCameraZ(&maVertices[3], RecipNearClip);\n\tRwIm2DVertexSetIntRGBA(&maVertices[3], c0.r, c0.g, c0.b, c0.a);\n\tRwIm2DVertexSetU(&maVertices[3], u3, RecipNearClip);\n\tRwIm2DVertexSetV(&maVertices[3], v3, RecipNearClip);\n}\n\nvoid\nCSprite2d::SetVertices(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4,\n\t\tconst CRGBA &c0, const CRGBA &c1, const CRGBA &c2, const CRGBA &c3)\n{\n\tRwIm2DVertexSetScreenX(&maVertices[0], x3);\n\tRwIm2DVertexSetScreenY(&maVertices[0], y3);\n\tRwIm2DVertexSetScreenZ(&maVertices[0], NearScreenZ);\n\tRwIm2DVertexSetCameraZ(&maVertices[0], NearCamZ);\n\tRwIm2DVertexSetRecipCameraZ(&maVertices[0], RecipNearClip);\n\tRwIm2DVertexSetIntRGBA(&maVertices[0], c2.r, c2.g, c2.b, c2.a);\n\tRwIm2DVertexSetU(&maVertices[0], 0.0f, RecipNearClip);\n\tRwIm2DVertexSetV(&maVertices[0], 0.0f, RecipNearClip);\n\n\tRwIm2DVertexSetScreenX(&maVertices[1], x4);\n\tRwIm2DVertexSetScreenY(&maVertices[1], y4);\n\tRwIm2DVertexSetScreenZ(&maVertices[1], NearScreenZ);\n\tRwIm2DVertexSetCameraZ(&maVertices[1], NearCamZ);\n\tRwIm2DVertexSetRecipCameraZ(&maVertices[1], RecipNearClip);\n\tRwIm2DVertexSetIntRGBA(&maVertices[1], c3.r, c3.g, c3.b, c3.a);\n\tRwIm2DVertexSetU(&maVertices[1], 1.0f, RecipNearClip);\n\tRwIm2DVertexSetV(&maVertices[1], 0.0f, RecipNearClip);\n\n\tRwIm2DVertexSetScreenX(&maVertices[2], x2);\n\tRwIm2DVertexSetScreenY(&maVertices[2], y2);\n\tRwIm2DVertexSetScreenZ(&maVertices[2], NearScreenZ);\n\tRwIm2DVertexSetCameraZ(&maVertices[2], NearCamZ);\n\tRwIm2DVertexSetRecipCameraZ(&maVertices[2], RecipNearClip);\n\tRwIm2DVertexSetIntRGBA(&maVertices[2], c1.r, c1.g, c1.b, c1.a);\n\tRwIm2DVertexSetU(&maVertices[2], 1.0f, RecipNearClip);\n\tRwIm2DVertexSetV(&maVertices[2], 1.0f, RecipNearClip);\n\n\tRwIm2DVertexSetScreenX(&maVertices[3], x1);\n\tRwIm2DVertexSetScreenY(&maVertices[3], y1);\n\tRwIm2DVertexSetScreenZ(&maVertices[3], NearScreenZ);\n\tRwIm2DVertexSetCameraZ(&maVertices[3], NearCamZ);\n\tRwIm2DVertexSetRecipCameraZ(&maVertices[3], RecipNearClip);\n\tRwIm2DVertexSetIntRGBA(&maVertices[3], c0.r, c0.g, c0.b, c0.a);\n\tRwIm2DVertexSetU(&maVertices[3], 0.0f, RecipNearClip);\n\tRwIm2DVertexSetV(&maVertices[3], 1.0f, RecipNearClip);\n}\n\nvoid\nCSprite2d::SetVertices(int n, float *positions, float *uvs, const CRGBA &col)\n{\n\tint i;\n\n\tfor(i = 0; i < n; i++){\n\t\tRwIm2DVertexSetScreenX(&maVertices[i], positions[i*2 + 0]);\n\t\tRwIm2DVertexSetScreenY(&maVertices[i], positions[i*2 + 1]);\n\t\tRwIm2DVertexSetScreenZ(&maVertices[i], NearScreenZ + 0.0001f);\n\t\tRwIm2DVertexSetCameraZ(&maVertices[i], NearCamZ);\n\t\tRwIm2DVertexSetRecipCameraZ(&maVertices[i], RecipNearClip);\n\t\tRwIm2DVertexSetIntRGBA(&maVertices[i], col.r, col.g, col.b, col.a);\n\t\tRwIm2DVertexSetU(&maVertices[i], uvs[i*2 + 0], RecipNearClip);\n\t\tRwIm2DVertexSetV(&maVertices[i], uvs[i*2 + 1], RecipNearClip);\n\t}\n}\n\nvoid\nCSprite2d::SetMaskVertices(int n, float *positions)\n{\n\tint i;\n\n\tfor(i = 0; i < n; i++){\n\t\tRwIm2DVertexSetScreenX(&maVertices[i], positions[i*2 + 0]);\n\t\tRwIm2DVertexSetScreenY(&maVertices[i], positions[i*2 + 1]);\n\t\tRwIm2DVertexSetScreenZ(&maVertices[i], NearScreenZ);\n\t\tRwIm2DVertexSetCameraZ(&maVertices[i], NearCamZ);\n\t\tRwIm2DVertexSetRecipCameraZ(&maVertices[i], RecipNearClip);\n#if !defined(GTA_PS2_STUFF) && defined(RWLIBS)\n\t\tRwIm2DVertexSetIntRGBA(&maVertices[i], 0, 0, 0, 0);\n#else\n\t\tRwIm2DVertexSetIntRGBA(&maVertices[i], 255, 255, 255, 255);\n#endif\n\t}\n}\n\nvoid\nCSprite2d::SetVertices(RwIm2DVertex *verts, const CRect &r, const CRGBA &c0, const CRGBA &c1, const CRGBA &c2, const CRGBA &c3,\n\t\tfloat u0, float v0, float u1, float v1, float u3, float v3, float u2, float v2)\n{\n\tRwIm2DVertexSetScreenX(&verts[0], r.left);\n\tRwIm2DVertexSetScreenY(&verts[0], r.top);\n\tRwIm2DVertexSetScreenZ(&verts[0], NearScreenZ);\n\tRwIm2DVertexSetCameraZ(&verts[0], NearCamZ);\n\tRwIm2DVertexSetRecipCameraZ(&verts[0], RecipNearClip);\n\tRwIm2DVertexSetIntRGBA(&verts[0], c2.r, c2.g, c2.b, c2.a);\n\tRwIm2DVertexSetU(&verts[0], u0, RecipNearClip);\n\tRwIm2DVertexSetV(&verts[0], v0, RecipNearClip);\n\n\tRwIm2DVertexSetScreenX(&verts[1], r.right);\n\tRwIm2DVertexSetScreenY(&verts[1], r.top);\n\tRwIm2DVertexSetScreenZ(&verts[1], NearScreenZ);\n\tRwIm2DVertexSetCameraZ(&verts[1], NearCamZ);\n\tRwIm2DVertexSetRecipCameraZ(&verts[1], RecipNearClip);\n\tRwIm2DVertexSetIntRGBA(&verts[1], c3.r, c3.g, c3.b, c3.a);\n\tRwIm2DVertexSetU(&verts[1], u1, RecipNearClip);\n\tRwIm2DVertexSetV(&verts[1], v1, RecipNearClip);\n\n\tRwIm2DVertexSetScreenX(&verts[2], r.right);\n\tRwIm2DVertexSetScreenY(&verts[2], r.bottom);\n\tRwIm2DVertexSetScreenZ(&verts[2], NearScreenZ);\n\tRwIm2DVertexSetCameraZ(&verts[2], NearCamZ);\n\tRwIm2DVertexSetRecipCameraZ(&verts[2], RecipNearClip);\n\tRwIm2DVertexSetIntRGBA(&verts[2], c1.r, c1.g, c1.b, c1.a);\n\tRwIm2DVertexSetU(&verts[2], u2, RecipNearClip);\n\tRwIm2DVertexSetV(&verts[2], v2, RecipNearClip);\n\n\tRwIm2DVertexSetScreenX(&verts[3], r.left);\n\tRwIm2DVertexSetScreenY(&verts[3], r.bottom);\n\tRwIm2DVertexSetScreenZ(&verts[3], NearScreenZ);\n\tRwIm2DVertexSetCameraZ(&verts[3], NearCamZ);\n\tRwIm2DVertexSetRecipCameraZ(&verts[3], RecipNearClip);\n\tRwIm2DVertexSetIntRGBA(&verts[3], c0.r, c0.g, c0.b, c0.a);\n\tRwIm2DVertexSetU(&verts[3], u3, RecipNearClip);\n\tRwIm2DVertexSetV(&verts[3], v3, RecipNearClip);\n}\n\nvoid\nCSprite2d::DrawRect(const CRect &r, const CRGBA &col)\n{\n\tSetVertices(r, col, col, col, col);\n\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil);\n\tRwRenderStateSet(rwRENDERSTATESHADEMODE, (void*)rwSHADEMODEFLAT);\n\tRwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE);\n\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);\n\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)(col.a != 255));\n\tRwIm2DRenderPrimitive(rwPRIMTYPETRIFAN, maVertices, 4);\n\tRwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);\n\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);\n\tRwRenderStateSet(rwRENDERSTATESHADEMODE, (void*)rwSHADEMODEGOURAUD);\n}\n\nvoid\nCSprite2d::DrawRect(const CRect &r, const CRGBA &c0, const CRGBA &c1, const CRGBA &c2, const CRGBA &c3)\n{\n\tSetVertices(r, c0, c1, c2, c3);\n\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil);\n\tRwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE);\n\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);\n\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);\n\tRwIm2DRenderPrimitive(rwPRIMTYPETRIFAN, maVertices, 4);\n\tRwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);\n\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);\n}\n\nvoid\nCSprite2d::DrawRectXLU(const CRect &r, const CRGBA &c0, const CRGBA &c1, const CRGBA &c2, const CRGBA &c3)\n{\n\tSetVertices(r, c0, c1, c2, c3);\n\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil);\n\tRwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE);\n\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);\n\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);\n\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);\n\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);\n\tRwIm2DRenderPrimitive(rwPRIMTYPETRIFAN, CSprite2d::maVertices, 4);\n\tRwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);\n\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);\n}\n\nvoid\nCSprite2d::DrawAnyRect(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4,\n\t\tconst CRGBA &c0, const CRGBA &c1, const CRGBA &c2, const CRGBA &c3)\n{\n\tSetVertices(x1, y1, x2, y2, x3, y3, x4, y4, c0, c1, c2, c3);\n\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil);\n\tRwRenderStateSet(rwRENDERSTATESHADEMODE, (void*)rwSHADEMODEGOURAUD);\n\tRwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE);\n\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);\n\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)(c0.alpha != 255 || c1.alpha != 255 || c2.alpha != 255 || c3.alpha != 255));\n\tRwIm2DRenderPrimitive(rwPRIMTYPETRIFAN, CSprite2d::maVertices, 4);\n\tRwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);\n\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);\n\tRwRenderStateSet(rwRENDERSTATESHADEMODE, (void*)rwSHADEMODEGOURAUD);\n}\n\nvoid CSprite2d::Draw2DPolygon(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4, const CRGBA &color)\n{\n\tSetVertices(x1, y1, x2, y2, x3, y3, x4, y4, color, color, color, color);\n\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, 0);\n\tRwRenderStateSet(rwRENDERSTATESHADEMODE, (void*)rwSHADEMODEFLAT);\n\tRwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE);\n\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);\n\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)(color.a != 255));\n\tRwIm2DRenderPrimitive(rwPRIMTYPETRIFAN, CSprite2d::maVertices, 4);\n\tRwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);\n\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);\n\tRwRenderStateSet(rwRENDERSTATESHADEMODE, (void*)rwSHADEMODEGOURAUD);\n}\n\nvoid\nCSprite2d::AddToBuffer(const CRect &r, const CRGBA &c, float u0, float v0, float u1, float v1, float u3, float v3, float u2, float v2)\n{\n\tSetVertices(&TempVertexBuffer.im2d[nextBufferVertex], r, c, c, c, c, u0, v0, u1, v1, u3, v3, u2, v2);\n\tRwImVertexIndex *pIndexList = &TempBufferRenderIndexList[nextBufferIndex];\n\tpIndexList[0] = nextBufferVertex;\n\tpIndexList[1] = nextBufferVertex + 1;\n\tpIndexList[2] = nextBufferVertex + 2;\n\tpIndexList[3] = nextBufferVertex + 3;\n\tpIndexList[4] = nextBufferVertex;\n\tpIndexList[5] = nextBufferVertex + 2;\n\tnextBufferIndex += 6;\n\tnextBufferVertex += 4;\n\tif (IsVertexBufferFull())\n\t\tRenderVertexBuffer();\n}\n\nbool\nCSprite2d::IsVertexBufferFull()\n{\n\treturn (nextBufferVertex > TEMPBUFFERVERTSIZE-128-4 || nextBufferIndex > ARRAY_SIZE(TempBufferRenderIndexList)-6);\n}\n\nvoid\nCSprite2d::RenderVertexBuffer()\n{\n\tif (nextBufferVertex > 0) {\n\t\tRwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR);\n\t\tRwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, TempVertexBuffer.im2d, nextBufferVertex, TempBufferRenderIndexList, nextBufferIndex);\n\t\tnextBufferVertex = 0;\n\t\tnextBufferIndex = 0;\n\t}\n}"
  },
  {
    "path": "src/render/Sprite2d.h",
    "content": "#pragma once\n\nclass CSprite2d\n{\n\tstatic float RecipNearClip;\n\tstatic float NearScreenZ;\n\tstatic float NearCamZ;\t// not original\n\tstatic int nextBufferVertex;\n\tstatic int nextBufferIndex;\n\tstatic RwIm2DVertex maVertices[8];\npublic:\n\tRwTexture *m_pTexture;\n\n\tstatic void SetRecipNearClip(void);\n\tstatic void InitPerFrame(void);\n\n\tCSprite2d(void) : m_pTexture(nil) {};\n\t~CSprite2d(void) { Delete(); };\n\tvoid Delete(void);\n\tvoid SetRenderState(void);\n\tvoid SetTexture(const char *name);\n\tvoid SetTexture(const char *name, const char *mask);\n\tvoid SetAddressing(RwTextureAddressMode addr);\n\tvoid Draw(float x, float y, float w, float h, const CRGBA &col);\n\tvoid Draw(const CRect &rect, const CRGBA &col);\n\tvoid Draw(const CRect &rect, const CRGBA &col,\n\t\tfloat u0, float v0, float u1, float v1, float u3, float v3, float u2, float v2);\n\tvoid Draw(const CRect &rect, const CRGBA &c0, const CRGBA &c1, const CRGBA &c2, const CRGBA &c3);\n\tvoid Draw(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4, const CRGBA &col);\n\n\tstatic void SetVertices(const CRect &r, const CRGBA &c0, const CRGBA &c1, const CRGBA &c2, const CRGBA &c3);\n\tstatic void SetVertices(const CRect &r, const CRGBA &c0, const CRGBA &c1, const CRGBA &c2, const CRGBA &c3,\n\t\tfloat u0, float v0, float u1, float v1, float u3, float v3, float u2, float v2);\n\tstatic void SetVertices(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4,\n\t\tconst CRGBA &c0, const CRGBA &c1, const CRGBA &c2, const CRGBA &c3);\n\tstatic void SetVertices(int n, float *positions, float *uvs, const CRGBA &col);\n\tstatic void SetMaskVertices(int n, float *positions);\n\tstatic void SetVertices(RwIm2DVertex *verts, const CRect &r, const CRGBA &c0, const CRGBA &c1, const CRGBA &c2, const CRGBA &c3,\n\t\tfloat u0, float v0, float u1, float v1, float u3, float v3, float u2, float v2);\n\n\tstatic void DrawRect(const CRect &r, const CRGBA &c0, const CRGBA &c1, const CRGBA &c2, const CRGBA &c3);\n\tstatic void DrawRect(const CRect &r, const CRGBA &col);\n\tstatic void DrawRectXLU(const CRect &r, const CRGBA &c0, const CRGBA &c1, const CRGBA &c2, const CRGBA &c3);\n\tstatic void DrawAnyRect(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4,\n\t\tconst CRGBA &c0, const CRGBA &c1, const CRGBA &c2, const CRGBA &c3);\n\n\tstatic void Draw2DPolygon(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4, const CRGBA &color);\n\n\tstatic RwIm2DVertex* GetVertices() { return maVertices; };\n\n\tstatic bool IsVertexBufferFull();\n\tstatic void AddToBuffer(const CRect &a1, const CRGBA &a2, float a3, float a4, float a5, float a6, float a7, float a8, float a9, float a10);\n\tstatic void RenderVertexBuffer();\n};\n"
  },
  {
    "path": "src/render/TexList.cpp",
    "content": "#include \"common.h\"\n#include \"TexList.h\"\n#include \"rtbmp.h\"\n#include \"FileMgr.h\"\n\nbool CTexList::ms_nTexUsed[MAX_TEXUSED];\n\nvoid\nCTexList::Initialise()\n{}\n\nvoid\nCTexList::Shutdown()\n{}\n\nRwTexture *\nCTexList::SetTexture(int32 slot, char *name)\n{\n\treturn nil;\n}\n\nint32\nCTexList::GetFirstFreeTexture()\n{\n\tfor (int32 i = 0; i < MAX_TEXUSED; i++)\n\t\tif (!ms_nTexUsed[i])\n\t\t\treturn i;\n\treturn -1;\n}\n\nRwTexture *\nCTexList::LoadFileNameTexture(char *name)\n{\n\treturn SetTexture(GetFirstFreeTexture(), name);\n}\n\nvoid\nCTexList::LoadGlobalTextureList()\n{\n\tCFileMgr::SetDir(\"TEXTURES\");\n}"
  },
  {
    "path": "src/render/TexList.h",
    "content": "#pragma once\n\nclass CTexList\n{\n\tenum { MAX_TEXUSED = 400, };\n\tstatic bool ms_nTexUsed[MAX_TEXUSED];\npublic:\n\tstatic void Initialise();\n\tstatic void Shutdown();\n\tstatic RwTexture *SetTexture(int32 slot, char *name);\n\tstatic int32 GetFirstFreeTexture();\n\tstatic RwTexture *LoadFileNameTexture(char *name);\n\tstatic void LoadGlobalTextureList();\n};"
  },
  {
    "path": "src/render/Timecycle.cpp",
    "content": "#include \"common.h\"\n\n#include \"main.h\"\n#include \"Clock.h\"\n#include \"Weather.h\"\n#include \"Camera.h\"\n#include \"Shadows.h\"\n#include \"ZoneCull.h\"\n#include \"CutsceneMgr.h\"\n#include \"FileMgr.h\"\n#include \"Timecycle.h\"\n\nuint8 CTimeCycle::m_nAmbientRed[NUMHOURS][NUMWEATHERS];\nuint8 CTimeCycle::m_nAmbientGreen[NUMHOURS][NUMWEATHERS];\nuint8 CTimeCycle::m_nAmbientBlue[NUMHOURS][NUMWEATHERS];\nuint8 CTimeCycle::m_nAmbientRed_Obj[NUMHOURS][NUMWEATHERS];\nuint8 CTimeCycle::m_nAmbientGreen_Obj[NUMHOURS][NUMWEATHERS];\nuint8 CTimeCycle::m_nAmbientBlue_Obj[NUMHOURS][NUMWEATHERS];\nuint8 CTimeCycle::m_nAmbientRed_Bl[NUMHOURS][NUMWEATHERS];\nuint8 CTimeCycle::m_nAmbientGreen_Bl[NUMHOURS][NUMWEATHERS];\nuint8 CTimeCycle::m_nAmbientBlue_Bl[NUMHOURS][NUMWEATHERS];\nuint8 CTimeCycle::m_nAmbientRed_Obj_Bl[NUMHOURS][NUMWEATHERS];\nuint8 CTimeCycle::m_nAmbientGreen_Obj_Bl[NUMHOURS][NUMWEATHERS];\nuint8 CTimeCycle::m_nAmbientBlue_Obj_Bl[NUMHOURS][NUMWEATHERS];\nuint8 CTimeCycle::m_nDirectionalRed[NUMHOURS][NUMWEATHERS];\nuint8 CTimeCycle::m_nDirectionalGreen[NUMHOURS][NUMWEATHERS];\nuint8 CTimeCycle::m_nDirectionalBlue[NUMHOURS][NUMWEATHERS];\nuint8 CTimeCycle::m_nSkyTopRed[NUMHOURS][NUMWEATHERS];\nuint8 CTimeCycle::m_nSkyTopGreen[NUMHOURS][NUMWEATHERS];\nuint8 CTimeCycle::m_nSkyTopBlue[NUMHOURS][NUMWEATHERS];\nuint8 CTimeCycle::m_nSkyBottomRed[NUMHOURS][NUMWEATHERS];\nuint8 CTimeCycle::m_nSkyBottomGreen[NUMHOURS][NUMWEATHERS];\nuint8 CTimeCycle::m_nSkyBottomBlue[NUMHOURS][NUMWEATHERS];\nuint8 CTimeCycle::m_nSunCoreRed[NUMHOURS][NUMWEATHERS];\nuint8 CTimeCycle::m_nSunCoreGreen[NUMHOURS][NUMWEATHERS];\nuint8 CTimeCycle::m_nSunCoreBlue[NUMHOURS][NUMWEATHERS];\nuint8 CTimeCycle::m_nSunCoronaRed[NUMHOURS][NUMWEATHERS];\nuint8 CTimeCycle::m_nSunCoronaGreen[NUMHOURS][NUMWEATHERS];\nuint8 CTimeCycle::m_nSunCoronaBlue[NUMHOURS][NUMWEATHERS];\nint8 CTimeCycle::m_fSunSize[NUMHOURS][NUMWEATHERS];\nint8 CTimeCycle::m_fSpriteSize[NUMHOURS][NUMWEATHERS];\nint8 CTimeCycle::m_fSpriteBrightness[NUMHOURS][NUMWEATHERS];\nuint8 CTimeCycle::m_nShadowStrength[NUMHOURS][NUMWEATHERS];\nuint8 CTimeCycle::m_nLightShadowStrength[NUMHOURS][NUMWEATHERS];\nuint8 CTimeCycle::m_nPoleShadowStrength[NUMHOURS][NUMWEATHERS];\nint16 CTimeCycle::m_fFogStart[NUMHOURS][NUMWEATHERS];\nint16 CTimeCycle::m_fFarClip[NUMHOURS][NUMWEATHERS];\nuint8 CTimeCycle::m_fLightsOnGroundBrightness[NUMHOURS][NUMWEATHERS];\nuint8 CTimeCycle::m_nLowCloudsRed[NUMHOURS][NUMWEATHERS];\nuint8 CTimeCycle::m_nLowCloudsGreen[NUMHOURS][NUMWEATHERS];\nuint8 CTimeCycle::m_nLowCloudsBlue[NUMHOURS][NUMWEATHERS];\nuint8 CTimeCycle::m_nFluffyCloudsTopRed[NUMHOURS][NUMWEATHERS];\nuint8 CTimeCycle::m_nFluffyCloudsTopGreen[NUMHOURS][NUMWEATHERS];\nuint8 CTimeCycle::m_nFluffyCloudsTopBlue[NUMHOURS][NUMWEATHERS];\nuint8 CTimeCycle::m_nFluffyCloudsBottomRed[NUMHOURS][NUMWEATHERS];\nuint8 CTimeCycle::m_nFluffyCloudsBottomGreen[NUMHOURS][NUMWEATHERS];\nuint8 CTimeCycle::m_nFluffyCloudsBottomBlue[NUMHOURS][NUMWEATHERS];\nuint8 CTimeCycle::m_fBlurRed[NUMHOURS][NUMWEATHERS];\nuint8 CTimeCycle::m_fBlurGreen[NUMHOURS][NUMWEATHERS];\nuint8 CTimeCycle::m_fBlurBlue[NUMHOURS][NUMWEATHERS];\nuint8 CTimeCycle::m_fWaterRed[NUMHOURS][NUMWEATHERS];\nuint8 CTimeCycle::m_fWaterGreen[NUMHOURS][NUMWEATHERS];\nuint8 CTimeCycle::m_fWaterBlue[NUMHOURS][NUMWEATHERS];\nuint8 CTimeCycle::m_fWaterAlpha[NUMHOURS][NUMWEATHERS];\n\n\nfloat CTimeCycle::m_fCurrentAmbientRed;\nfloat CTimeCycle::m_fCurrentAmbientGreen;\nfloat CTimeCycle::m_fCurrentAmbientBlue;\nfloat CTimeCycle::m_fCurrentAmbientRed_Obj;\nfloat CTimeCycle::m_fCurrentAmbientGreen_Obj;\nfloat CTimeCycle::m_fCurrentAmbientBlue_Obj;\nfloat CTimeCycle::m_fCurrentAmbientRed_Bl;\nfloat CTimeCycle::m_fCurrentAmbientGreen_Bl;\nfloat CTimeCycle::m_fCurrentAmbientBlue_Bl;\nfloat CTimeCycle::m_fCurrentAmbientRed_Obj_Bl;\nfloat CTimeCycle::m_fCurrentAmbientGreen_Obj_Bl;\nfloat CTimeCycle::m_fCurrentAmbientBlue_Obj_Bl;\nfloat CTimeCycle::m_fCurrentDirectionalRed;\nfloat CTimeCycle::m_fCurrentDirectionalGreen;\nfloat CTimeCycle::m_fCurrentDirectionalBlue;\nint32 CTimeCycle::m_nCurrentSkyTopRed;\nint32 CTimeCycle::m_nCurrentSkyTopGreen;\nint32 CTimeCycle::m_nCurrentSkyTopBlue;\nint32 CTimeCycle::m_nCurrentSkyBottomRed;\nint32 CTimeCycle::m_nCurrentSkyBottomGreen;\nint32 CTimeCycle::m_nCurrentSkyBottomBlue;\nint32 CTimeCycle::m_nCurrentSunCoreRed;\nint32 CTimeCycle::m_nCurrentSunCoreGreen;\nint32 CTimeCycle::m_nCurrentSunCoreBlue;\nint32 CTimeCycle::m_nCurrentSunCoronaRed;\nint32 CTimeCycle::m_nCurrentSunCoronaGreen;\nint32 CTimeCycle::m_nCurrentSunCoronaBlue;\nfloat CTimeCycle::m_fCurrentSunSize;\nfloat CTimeCycle::m_fCurrentSpriteSize;\nfloat CTimeCycle::m_fCurrentSpriteBrightness;\nint32 CTimeCycle::m_nCurrentShadowStrength;\nint32 CTimeCycle::m_nCurrentLightShadowStrength;\nint32 CTimeCycle::m_nCurrentPoleShadowStrength;\nfloat CTimeCycle::m_fCurrentFogStart;\nfloat CTimeCycle::m_fCurrentFarClip;\nfloat CTimeCycle::m_fCurrentLightsOnGroundBrightness;\nint32 CTimeCycle::m_nCurrentLowCloudsRed;\nint32 CTimeCycle::m_nCurrentLowCloudsGreen;\nint32 CTimeCycle::m_nCurrentLowCloudsBlue;\nint32 CTimeCycle::m_nCurrentFluffyCloudsTopRed;\nint32 CTimeCycle::m_nCurrentFluffyCloudsTopGreen;\nint32 CTimeCycle::m_nCurrentFluffyCloudsTopBlue;\nint32 CTimeCycle::m_nCurrentFluffyCloudsBottomRed;\nint32 CTimeCycle::m_nCurrentFluffyCloudsBottomGreen;\nint32 CTimeCycle::m_nCurrentFluffyCloudsBottomBlue;\nfloat CTimeCycle::m_fCurrentBlurRed;\nfloat CTimeCycle::m_fCurrentBlurGreen;\nfloat CTimeCycle::m_fCurrentBlurBlue;\nfloat CTimeCycle::m_fCurrentWaterRed;\nfloat CTimeCycle::m_fCurrentWaterGreen;\nfloat CTimeCycle::m_fCurrentWaterBlue;\nfloat CTimeCycle::m_fCurrentWaterAlpha;\nint32 CTimeCycle::m_nCurrentFogColourRed;\nint32 CTimeCycle::m_nCurrentFogColourGreen;\nint32 CTimeCycle::m_nCurrentFogColourBlue;\n\nint32 CTimeCycle::m_FogReduction;\nint32 CTimeCycle::m_bExtraColourOn;\nint32 CTimeCycle::m_ExtraColour;\nfloat CTimeCycle::m_ExtraColourInter;\n\nint32 CTimeCycle::m_CurrentStoredValue;\nCVector CTimeCycle::m_VectorToSun[16];\nfloat CTimeCycle::m_fShadowFrontX[16];\nfloat CTimeCycle::m_fShadowFrontY[16];\nfloat CTimeCycle::m_fShadowSideX[16];\nfloat CTimeCycle::m_fShadowSideY[16];\nfloat CTimeCycle::m_fShadowDisplacementX[16];\nfloat CTimeCycle::m_fShadowDisplacementY[16];\n\nvoid\nCTimeCycle::Initialise(void)\n{\n\tint w, h;\n\tint li, bi;\n\tchar line[1040];\n\n\tint ambR, ambG, ambB;\n\tint ambobjR, ambobjG, ambobjB;\n\tint ambblR, ambblG, ambblB;\n\tint ambobjblR, ambobjblG, ambobjblB;\n\tint dirR, dirG, dirB;\n\tint skyTopR, skyTopG, skyTopB;\n\tint skyBotR, skyBotG, skyBotB;\n\tint sunCoreR, sunCoreG, sunCoreB;\n\tint sunCoronaR, sunCoronaG, sunCoronaB;\n\tfloat sunSz, sprSz, sprBght;\n\tint shad, lightShad, poleShad;\n\tfloat farClp, fogSt, lightGnd;\n\tint cloudR, cloudG, cloudB;\n\tint fluffyTopR, fluffyTopG, fluffyTopB;\n\tint fluffyBotR, fluffyBotG, fluffyBotB;\n\tfloat blurR, blurG, blurB;\n\tfloat waterR, waterG, waterB, waterA;\n\n\tdebug(\"Intialising CTimeCycle...\\n\");\n\n\tCFileMgr::SetDir(\"DATA\");\n\tCFileMgr::LoadFile(\"TIMECYC.DAT\", work_buff, sizeof(work_buff), \"rb\");\n\tCFileMgr::SetDir(\"\");\n\n\tline[0] = '\\0';\n\tbi = 0;\n\tfor(w = 0; w < NUMWEATHERS; w++)\n\t\tfor(h = 0; h < NUMHOURS; h++){\n\t\t\tli = 0;\n\t\t\twhile(work_buff[bi] == '/' || work_buff[bi] == '\\n' ||\n\t\t\t      work_buff[bi] == '\\0' || work_buff[bi] == ' ' || work_buff[bi] == '\\r'){\n\t\t\t\twhile(work_buff[bi] != '\\n' && work_buff[bi] != '\\0' && work_buff[bi] != '\\r')\n\t\t\t\t\tbi++;\n\t\t\t\tbi++;\n\t\t\t}\n\t\t\twhile(work_buff[bi] != '\\n'\n#ifdef FIX_BUGS\n\t\t\t&& work_buff[bi] != '\\0'\n#endif\n\t\t\t)\n\t\t\t\tline[li++] = work_buff[bi++];\n\t\t\tline[li] = '\\0';\n\t\t\tbi++;\n\n\t\t\tsscanf(line, \"%d %d %d  %d %d %d  %d %d %d  %d %d %d \"\n\t\t\t             \"%d %d %d  %d %d %d  %d %d %d \"\n\t\t\t             \"%d %d %d  %d %d %d  %f %f %f %d %d %d %f %f %f \"\n\t\t\t             \"%d %d %d  %d %d %d  %d %d %d  %f %f %f  %f %f %f %f\",\n\t\t\t\t&ambR, &ambG, &ambB,\n\t\t\t\t &ambobjR, &ambobjG, &ambobjB,\n\t\t\t\t &ambblR, &ambblG, &ambblB,\n\t\t\t\t &ambobjblR, &ambobjblG, &ambobjblB,\n\t\t\t\t&dirR, &dirG, &dirB,\n\t\t\t\t &skyTopR, &skyTopG, &skyTopB,\n\t\t\t\t &skyBotR, &skyBotG, &skyBotB,\n\t\t\t\t&sunCoreR, &sunCoreG, &sunCoreB,\n\t\t\t\t &sunCoronaR, &sunCoronaG, &sunCoronaB,\n\t\t\t\t &sunSz, &sprSz, &sprBght,\n\t\t\t\t &shad, &lightShad, &poleShad,\n\t\t\t\t &farClp, &fogSt, &lightGnd,\n\t\t\t\t&cloudR, &cloudG, &cloudB,\n\t\t\t\t &fluffyTopR, &fluffyTopG, &fluffyTopB,\n\t\t\t\t &fluffyBotR, &fluffyBotG, &fluffyBotB,\n\t\t\t\t &blurR, &blurG, &blurB,\n\t\t\t\t &waterR, &waterG, &waterB, &waterA);\n\n\t\t\tm_nAmbientRed[h][w] = ambR;\n\t\t\tm_nAmbientGreen[h][w] = ambG;\n\t\t\tm_nAmbientBlue[h][w] = ambB;\n\t\t\tm_nAmbientRed_Obj[h][w] = ambobjR;\n\t\t\tm_nAmbientGreen_Obj[h][w] = ambobjG;\n\t\t\tm_nAmbientBlue_Obj[h][w] = ambobjB;\n\t\t\tm_nAmbientRed_Bl[h][w] = ambblR;\n\t\t\tm_nAmbientGreen_Bl[h][w] = ambblG;\n\t\t\tm_nAmbientBlue_Bl[h][w] = ambblB;\n\t\t\tm_nAmbientRed_Obj_Bl[h][w] = ambobjblR;\n\t\t\tm_nAmbientGreen_Obj_Bl[h][w] = ambobjblG;\n\t\t\tm_nAmbientBlue_Obj_Bl[h][w] = ambobjblB;\n\t\t\tm_nDirectionalRed[h][w] = dirR;\n\t\t\tm_nDirectionalGreen[h][w] = dirG;\n\t\t\tm_nDirectionalBlue[h][w] = dirB;\n\t\t\tm_nSkyTopRed[h][w] = skyTopR;\n\t\t\tm_nSkyTopGreen[h][w] = skyTopG;\n\t\t\tm_nSkyTopBlue[h][w] = skyTopB;\n\t\t\tm_nSkyBottomRed[h][w] = skyBotR;\n\t\t\tm_nSkyBottomGreen[h][w] = skyBotG;\n\t\t\tm_nSkyBottomBlue[h][w] = skyBotB;\n\t\t\tm_nSunCoreRed[h][w] = sunCoreR;\n\t\t\tm_nSunCoreGreen[h][w] = sunCoreG;\n\t\t\tm_nSunCoreBlue[h][w] = sunCoreB;\n\t\t\tm_nSunCoronaRed[h][w] = sunCoronaR;\n\t\t\tm_nSunCoronaGreen[h][w] = sunCoronaG;\n\t\t\tm_nSunCoronaBlue[h][w] = sunCoronaB;\n\t\t\tm_fSunSize[h][w] = sunSz * 10.0f;\n\t\t\tm_fSpriteSize[h][w] = sprSz * 10.0f;\n\t\t\tm_fSpriteBrightness[h][w] = sprBght * 10.0f;\n\t\t\tm_nShadowStrength[h][w] = shad;\n\t\t\tm_nLightShadowStrength[h][w] = lightShad;\n\t\t\tm_nPoleShadowStrength[h][w] = poleShad;\n\t\t\tm_fFarClip[h][w] = farClp;\n\t\t\tm_fFogStart[h][w] = fogSt;\n\t\t\tm_fLightsOnGroundBrightness[h][w] = lightGnd * 10.0f;\n\t\t\tm_nLowCloudsRed[h][w] = cloudR;\n\t\t\tm_nLowCloudsGreen[h][w] = cloudG;\n\t\t\tm_nLowCloudsBlue[h][w] = cloudB;\n\t\t\tm_nFluffyCloudsTopRed[h][w] = fluffyTopR;\n\t\t\tm_nFluffyCloudsTopGreen[h][w] = fluffyTopG;\n\t\t\tm_nFluffyCloudsTopBlue[h][w] = fluffyTopB;\n\t\t\tm_nFluffyCloudsBottomRed[h][w] = fluffyBotR;\n\t\t\tm_nFluffyCloudsBottomGreen[h][w] = fluffyBotG;\n\t\t\tm_nFluffyCloudsBottomBlue[h][w] = fluffyBotB;\n\t\t\tm_fBlurRed[h][w] = blurR;\n\t\t\tm_fBlurGreen[h][w] = blurG;\n\t\t\tm_fBlurBlue[h][w] = blurB;\n\t\t\tm_fWaterRed[h][w] = waterR;\n\t\t\tm_fWaterGreen[h][w] = waterG;\n\t\t\tm_fWaterBlue[h][w] = waterB;\n\t\t\tm_fWaterAlpha[h][w] = waterA;\n\t\t}\n\n\tm_FogReduction = 0;\n\n\tdebug(\"CTimeCycle ready\\n\");\n}\n\nstatic float interp_c0, interp_c1, interp_c2, interp_c3;\n\nfloat CTimeCycle::Interpolate(int8 *a, int8 *b)\n{\n\treturn a[CWeather::OldWeatherType] * interp_c0 +\n\t\tb[CWeather::OldWeatherType] * interp_c1 +\n\t\ta[CWeather::NewWeatherType] * interp_c2 +\n\t\tb[CWeather::NewWeatherType] * interp_c3;\n}\n\nfloat CTimeCycle::Interpolate(uint8 *a, uint8 *b)\n{\n\treturn a[CWeather::OldWeatherType] * interp_c0 +\n\t\tb[CWeather::OldWeatherType] * interp_c1 +\n\t\ta[CWeather::NewWeatherType] * interp_c2 +\n\t\tb[CWeather::NewWeatherType] * interp_c3;\n}\n\nfloat CTimeCycle::Interpolate(int16 *a, int16 *b)\n{\n\treturn a[CWeather::OldWeatherType] * interp_c0 +\n\t\tb[CWeather::OldWeatherType] * interp_c1 +\n\t\ta[CWeather::NewWeatherType] * interp_c2 +\n\t\tb[CWeather::NewWeatherType] * interp_c3;\n}\n\nvoid\nCTimeCycle::StartExtraColour(int32 c, bool fade)\n{\n\tm_bExtraColourOn = true;\n\tm_ExtraColour = c;\n\tif(fade)\n\t\tm_ExtraColourInter = 0.0f;\n\telse\n\t\tm_ExtraColourInter = 1.0f;\n}\n\nvoid\nCTimeCycle::StopExtraColour(bool fade)\n{\n\tm_bExtraColourOn = false;\n\tif(!fade)\n\t\tm_ExtraColourInter = 0.0f;\n}\n\nvoid\nCTimeCycle::Update(void)\n{\n\tint h1 = CClock::GetHours();\n\tint h2 = (h1+1)%24;\n\tint w1 = CWeather::OldWeatherType;\n\tint w2 = CWeather::NewWeatherType;\n\tfloat timeInterp = (CClock::GetMinutes() + CClock::GetSeconds()/60.0f)/60.0f;\n\t// coefficients for a bilinear interpolation\n\tinterp_c0 = (1.0f-timeInterp) * (1.0f-CWeather::InterpolationValue);\n\tinterp_c1 = timeInterp * (1.0f-CWeather::InterpolationValue);\n\tinterp_c2 = (1.0f-timeInterp) * CWeather::InterpolationValue;\n\tinterp_c3 = timeInterp * CWeather::InterpolationValue;\n\n#define INTERP(v) Interpolate(v[h1], v[h2])\n\n\tm_nCurrentSkyTopRed = INTERP(m_nSkyTopRed);\n\tm_nCurrentSkyTopGreen = INTERP(m_nSkyTopGreen);\n\tm_nCurrentSkyTopBlue = INTERP(m_nSkyTopBlue);\n\n\tm_nCurrentSkyBottomRed = INTERP(m_nSkyBottomRed);\n\tm_nCurrentSkyBottomGreen = INTERP(m_nSkyBottomGreen);\n\tm_nCurrentSkyBottomBlue = INTERP(m_nSkyBottomBlue);\n\n\tm_fCurrentAmbientRed = INTERP(m_nAmbientRed);\n\tm_fCurrentAmbientGreen = INTERP(m_nAmbientGreen);\n\tm_fCurrentAmbientBlue = INTERP(m_nAmbientBlue);\n\n\tm_fCurrentAmbientRed_Obj = INTERP(m_nAmbientRed_Obj);\n\tm_fCurrentAmbientGreen_Obj = INTERP(m_nAmbientGreen_Obj);\n\tm_fCurrentAmbientBlue_Obj = INTERP(m_nAmbientBlue_Obj);\n\n\tm_fCurrentAmbientRed_Bl = INTERP(m_nAmbientRed_Bl);\n\tm_fCurrentAmbientGreen_Bl = INTERP(m_nAmbientGreen_Bl);\n\tm_fCurrentAmbientBlue_Bl = INTERP(m_nAmbientBlue_Bl);\n\n\tm_fCurrentAmbientRed_Obj_Bl = INTERP(m_nAmbientRed_Obj_Bl);\n\tm_fCurrentAmbientGreen_Obj_Bl = INTERP(m_nAmbientGreen_Obj_Bl);\n\tm_fCurrentAmbientBlue_Obj_Bl = INTERP(m_nAmbientBlue_Obj_Bl);\n\n\tm_fCurrentDirectionalRed = INTERP(m_nDirectionalRed);\n\tm_fCurrentDirectionalGreen = INTERP(m_nDirectionalGreen);\n\tm_fCurrentDirectionalBlue = INTERP(m_nDirectionalBlue);\n\n\tm_nCurrentSunCoreRed = INTERP(m_nSunCoreRed);\n\tm_nCurrentSunCoreGreen = INTERP(m_nSunCoreGreen);\n\tm_nCurrentSunCoreBlue = INTERP(m_nSunCoreBlue);\n\n\tm_nCurrentSunCoronaRed = INTERP(m_nSunCoronaRed);\n\tm_nCurrentSunCoronaGreen = INTERP(m_nSunCoronaGreen);\n\tm_nCurrentSunCoronaBlue = INTERP(m_nSunCoronaBlue);\n\n\tm_fCurrentSunSize = INTERP(m_fSunSize)/10.0f;\n\tm_fCurrentSpriteSize = INTERP(m_fSpriteSize)/10.0f;\n\tm_fCurrentSpriteBrightness = INTERP(m_fSpriteBrightness)/10.0f;\n\tm_nCurrentShadowStrength = INTERP(m_nShadowStrength);\n\tm_nCurrentLightShadowStrength = INTERP(m_nLightShadowStrength);\n\tm_nCurrentPoleShadowStrength = INTERP(m_nPoleShadowStrength);\n\tm_fCurrentFarClip = INTERP(m_fFarClip);\n\tm_fCurrentFogStart = INTERP(m_fFogStart);\n\tm_fCurrentLightsOnGroundBrightness = INTERP(m_fLightsOnGroundBrightness)/10.0f;\n\n\tm_nCurrentLowCloudsRed = INTERP(m_nLowCloudsRed);\n\tm_nCurrentLowCloudsGreen = INTERP(m_nLowCloudsGreen);\n\tm_nCurrentLowCloudsBlue = INTERP(m_nLowCloudsBlue);\n\n\tm_nCurrentFluffyCloudsTopRed = INTERP(m_nFluffyCloudsTopRed);\n\tm_nCurrentFluffyCloudsTopGreen = INTERP(m_nFluffyCloudsTopGreen);\n\tm_nCurrentFluffyCloudsTopBlue = INTERP(m_nFluffyCloudsTopBlue);\n\n\tm_nCurrentFluffyCloudsBottomRed = INTERP(m_nFluffyCloudsBottomRed);\n\tm_nCurrentFluffyCloudsBottomGreen = INTERP(m_nFluffyCloudsBottomGreen);\n\tm_nCurrentFluffyCloudsBottomBlue = INTERP(m_nFluffyCloudsBottomBlue);\n\n\tm_fCurrentBlurRed = INTERP(m_fBlurRed);\n\tm_fCurrentBlurGreen = INTERP(m_fBlurGreen);\n\tm_fCurrentBlurBlue = INTERP(m_fBlurBlue);\n\n\tm_fCurrentWaterRed = INTERP(m_fWaterRed);\n\tm_fCurrentWaterGreen = INTERP(m_fWaterGreen);\n\tm_fCurrentWaterBlue = INTERP(m_fWaterBlue);\n\tm_fCurrentWaterAlpha = INTERP(m_fWaterAlpha);\n#undef INTERP\n\n\tif(m_FogReduction != 0)\n\t\tm_fCurrentFarClip = Max(m_fCurrentFarClip, m_FogReduction/64.0f * 650.0f);\n\n\tm_CurrentStoredValue = (m_CurrentStoredValue+1)&0xF;\n\n\tfloat sunAngle = 2*PI*(CClock::GetSeconds()/60.0f + CClock::GetMinutes() + CClock::GetHours()*60)/(24*60);\n\tCVector &sunPos = GetSunDirection();\n\tsunPos.x = Sin(sunAngle);\n\tsunPos.y = 1.0f;\n\tsunPos.z = 0.2f - Cos(sunAngle);\n\tsunPos.Normalise();\n\n\tif(m_bExtraColourOn)\n\t\tm_ExtraColourInter = Min(1.0f, m_ExtraColourInter + CTimer::GetTimeStep()/120.0f);\n\telse\n\t\tm_ExtraColourInter = Max(-.0f, m_ExtraColourInter - CTimer::GetTimeStep()/120.0f);\n\tif(m_ExtraColourInter > 0.0f){\n#define INTERP(extra,cur) (m_ExtraColourInter*extra[m_ExtraColour][WEATHER_EXTRACOLOURS] + (1.0f-m_ExtraColourInter)*cur)\n#define INTERPscl(extra,scl,cur) (m_ExtraColourInter*extra[m_ExtraColour][WEATHER_EXTRACOLOURS]/scl + (1.0f-m_ExtraColourInter)*cur)\n\t\tif(m_nSkyTopRed[m_ExtraColour][WEATHER_EXTRACOLOURS] != 0 ||\n\t\t   m_nSkyTopGreen[m_ExtraColour][WEATHER_EXTRACOLOURS] != 0 ||\n\t\t   m_nSkyTopBlue[m_ExtraColour][WEATHER_EXTRACOLOURS] != 0){\n\t\t\tm_nCurrentSkyTopRed = INTERP(m_nSkyTopRed,m_nCurrentSkyTopRed);\n\t\t\tm_nCurrentSkyTopGreen = INTERP(m_nSkyTopGreen,m_nCurrentSkyTopGreen);\n\t\t\tm_nCurrentSkyTopBlue = INTERP(m_nSkyTopBlue,m_nCurrentSkyTopBlue);\n\n\t\t\tm_nCurrentSkyBottomRed = INTERP(m_nSkyBottomRed,m_nCurrentSkyBottomRed);\n\t\t\tm_nCurrentSkyBottomGreen = INTERP(m_nSkyBottomGreen,m_nCurrentSkyBottomGreen);\n\t\t\tm_nCurrentSkyBottomBlue = INTERP(m_nSkyBottomBlue,m_nCurrentSkyBottomBlue);\n\n\t\t\tm_nCurrentSunCoreRed = INTERP(m_nSunCoreRed,m_nCurrentSunCoreRed);\n\t\t\tm_nCurrentSunCoreGreen = INTERP(m_nSunCoreGreen,m_nCurrentSunCoreGreen);\n\t\t\tm_nCurrentSunCoreBlue = INTERP(m_nSunCoreBlue,m_nCurrentSunCoreBlue);\n\n\t\t\tm_nCurrentSunCoronaRed = INTERP(m_nSunCoronaRed,m_nCurrentSunCoronaRed);\n\t\t\tm_nCurrentSunCoronaGreen = INTERP(m_nSunCoronaGreen,m_nCurrentSunCoronaGreen);\n\t\t\tm_nCurrentSunCoronaBlue = INTERP(m_nSunCoronaBlue,m_nCurrentSunCoronaBlue);\n\n\t\t\tm_fCurrentSunSize = INTERPscl(m_fSunSize,10.0f,m_fCurrentSunSize);\n\n\t\t\tm_nCurrentLowCloudsRed = INTERP(m_nLowCloudsRed,m_nCurrentLowCloudsRed);\n\t\t\tm_nCurrentLowCloudsGreen = INTERP(m_nLowCloudsGreen,m_nCurrentLowCloudsGreen);\n\t\t\tm_nCurrentLowCloudsBlue = INTERP(m_nLowCloudsBlue,m_nCurrentLowCloudsBlue);\n\n\t\t\tm_nCurrentFluffyCloudsTopRed = INTERP(m_nFluffyCloudsTopRed,m_nCurrentFluffyCloudsTopRed);\n\t\t\tm_nCurrentFluffyCloudsTopGreen = INTERP(m_nFluffyCloudsTopGreen,m_nCurrentFluffyCloudsTopGreen);\n\t\t\tm_nCurrentFluffyCloudsTopBlue = INTERP(m_nFluffyCloudsTopBlue,m_nCurrentFluffyCloudsTopBlue);\n\n\t\t\tm_nCurrentFluffyCloudsBottomRed = INTERP(m_nFluffyCloudsBottomRed,m_nCurrentFluffyCloudsBottomRed);\n\t\t\tm_nCurrentFluffyCloudsBottomGreen = INTERP(m_nFluffyCloudsBottomGreen,m_nCurrentFluffyCloudsBottomGreen);\n\t\t\tm_nCurrentFluffyCloudsBottomBlue = INTERP(m_nFluffyCloudsBottomBlue,m_nCurrentFluffyCloudsBottomBlue);\n\n\t\t\tm_fCurrentWaterRed = INTERP(m_fWaterRed,m_fCurrentWaterRed);\n\t\t\tm_fCurrentWaterGreen = INTERP(m_fWaterGreen,m_fCurrentWaterGreen);\n\t\t\tm_fCurrentWaterBlue = INTERP(m_fWaterBlue,m_fCurrentWaterBlue);\n\t\t\tm_fCurrentWaterAlpha = INTERP(m_fWaterAlpha,m_fCurrentWaterAlpha);\n\t\t}\n\n\t\tm_fCurrentAmbientRed = INTERP(m_nAmbientRed,m_fCurrentAmbientRed);\n\t\tm_fCurrentAmbientGreen = INTERP(m_nAmbientGreen,m_fCurrentAmbientGreen);\n\t\tm_fCurrentAmbientBlue = INTERP(m_nAmbientBlue,m_fCurrentAmbientBlue);\n\n\t\tm_fCurrentAmbientRed_Obj = INTERP(m_nAmbientRed_Obj,m_fCurrentAmbientRed_Obj);\n\t\tm_fCurrentAmbientGreen_Obj = INTERP(m_nAmbientGreen_Obj,m_fCurrentAmbientGreen_Obj);\n\t\tm_fCurrentAmbientBlue_Obj = INTERP(m_nAmbientBlue_Obj,m_fCurrentAmbientBlue_Obj);\n\n\t\tm_fCurrentAmbientRed_Bl = INTERP(m_nAmbientRed_Bl,m_fCurrentAmbientRed_Bl);\n\t\tm_fCurrentAmbientGreen_Bl = INTERP(m_nAmbientGreen_Bl,m_fCurrentAmbientGreen_Bl);\n\t\tm_fCurrentAmbientBlue_Bl = INTERP(m_nAmbientBlue_Bl,m_fCurrentAmbientBlue_Bl);\n\n\t\tm_fCurrentAmbientRed_Obj_Bl = INTERP(m_nAmbientRed_Obj_Bl,m_fCurrentAmbientRed_Obj_Bl);\n\t\tm_fCurrentAmbientGreen_Obj_Bl = INTERP(m_nAmbientGreen_Obj_Bl,m_fCurrentAmbientGreen_Obj_Bl);\n\t\tm_fCurrentAmbientBlue_Obj_Bl = INTERP(m_nAmbientBlue_Obj_Bl,m_fCurrentAmbientBlue_Obj_Bl);\n\n\t\tm_fCurrentDirectionalRed = INTERP(m_nDirectionalRed,m_fCurrentDirectionalRed);\n\t\tm_fCurrentDirectionalGreen = INTERP(m_nDirectionalGreen,m_fCurrentDirectionalGreen);\n\t\tm_fCurrentDirectionalBlue = INTERP(m_nDirectionalBlue,m_fCurrentDirectionalBlue);\n\n\t\tm_fCurrentSpriteSize = INTERPscl(m_fSpriteSize,10.0f,m_fCurrentSpriteSize);\n\t\tm_fCurrentSpriteBrightness = INTERPscl(m_fSpriteBrightness,10.0f,m_fCurrentSpriteBrightness);\n\t\tm_nCurrentShadowStrength = INTERP(m_nShadowStrength,m_nCurrentShadowStrength);\n\t\tm_nCurrentLightShadowStrength = INTERP(m_nLightShadowStrength,m_nCurrentLightShadowStrength);\n\t\tm_nCurrentPoleShadowStrength = INTERP(m_nPoleShadowStrength,m_nCurrentPoleShadowStrength);\n\t\tm_fCurrentFarClip = INTERP(m_fFarClip,m_fCurrentFarClip);\n\t\tm_fCurrentFogStart = INTERP(m_fFogStart,m_fCurrentFogStart);\n\t\tm_fCurrentLightsOnGroundBrightness = INTERPscl(m_fLightsOnGroundBrightness,10.0f,m_fCurrentLightsOnGroundBrightness);\n\n\t\tm_fCurrentBlurRed = INTERP(m_fBlurRed,m_fCurrentBlurRed);\n\t\tm_fCurrentBlurGreen = INTERP(m_fBlurGreen,m_fCurrentBlurGreen);\n\t\tm_fCurrentBlurBlue = INTERP(m_fBlurBlue,m_fCurrentBlurBlue);\n\n#undef INTERP\n#undef INTERPscl\n\t}\n\n\tif(TheCamera.m_BlurType == MOTION_BLUR_NONE || TheCamera.m_BlurType == MOTION_BLUR_LIGHT_SCENE)\n\t\tTheCamera.SetMotionBlur(m_fCurrentBlurRed, m_fCurrentBlurGreen, m_fCurrentBlurBlue, 5, MOTION_BLUR_LIGHT_SCENE);\n\n\tm_nCurrentFogColourRed = (m_nCurrentSkyTopRed + 2*m_nCurrentSkyBottomRed) / 3;\n\tm_nCurrentFogColourGreen = (m_nCurrentSkyTopGreen + 2*m_nCurrentSkyBottomGreen) / 3;\n\tm_nCurrentFogColourBlue = (m_nCurrentSkyTopBlue + 2*m_nCurrentSkyBottomBlue) / 3;\n\n\tm_fCurrentAmbientRed /= 255.0f;\n\tm_fCurrentAmbientGreen /= 255.0f;\n\tm_fCurrentAmbientBlue /= 255.0f;\n\tm_fCurrentAmbientRed_Obj /= 255.0f;\n\tm_fCurrentAmbientGreen_Obj /= 255.0f;\n\tm_fCurrentAmbientBlue_Obj /= 255.0f;\n\tm_fCurrentAmbientRed_Bl /= 255.0f;\n\tm_fCurrentAmbientGreen_Bl /= 255.0f;\n\tm_fCurrentAmbientBlue_Bl /= 255.0f;\n\tm_fCurrentAmbientRed_Obj_Bl /= 255.0f;\n\tm_fCurrentAmbientGreen_Obj_Bl /= 255.0f;\n\tm_fCurrentAmbientBlue_Obj_Bl /= 255.0f;\n\tm_fCurrentDirectionalRed /= 255.0f;\n\tm_fCurrentDirectionalGreen /= 255.0f;\n\tm_fCurrentDirectionalBlue /= 255.0f;\n\n\tCShadows::CalcPedShadowValues(sunPos, \n\t\t&m_fShadowFrontX[m_CurrentStoredValue], &m_fShadowFrontY[m_CurrentStoredValue],\n\t\t&m_fShadowSideX[m_CurrentStoredValue], &m_fShadowSideY[m_CurrentStoredValue],\n\t\t&m_fShadowDisplacementX[m_CurrentStoredValue], &m_fShadowDisplacementY[m_CurrentStoredValue]);\n\n\tif(TheCamera.GetForward().z < -0.9f ||\n\t   !CWeather::bScriptsForceRain && (CCullZones::PlayerNoRain() || CCullZones::CamNoRain() || CCutsceneMgr::IsRunning()))\n\t\tm_FogReduction = Min(m_FogReduction+1, 64);\n\telse\n\t\tm_FogReduction = Max(m_FogReduction-1, 0);\n}\n"
  },
  {
    "path": "src/render/Timecycle.h",
    "content": "#pragma once\n\nclass CTimeCycle\n{\n\tstatic uint8 m_nAmbientRed[NUMHOURS][NUMWEATHERS];\n\tstatic uint8 m_nAmbientGreen[NUMHOURS][NUMWEATHERS];\n\tstatic uint8 m_nAmbientBlue[NUMHOURS][NUMWEATHERS];\n\tstatic uint8 m_nAmbientRed_Obj[NUMHOURS][NUMWEATHERS];\n\tstatic uint8 m_nAmbientGreen_Obj[NUMHOURS][NUMWEATHERS];\n\tstatic uint8 m_nAmbientBlue_Obj[NUMHOURS][NUMWEATHERS];\n\tstatic uint8 m_nAmbientRed_Bl[NUMHOURS][NUMWEATHERS];\n\tstatic uint8 m_nAmbientGreen_Bl[NUMHOURS][NUMWEATHERS];\n\tstatic uint8 m_nAmbientBlue_Bl[NUMHOURS][NUMWEATHERS];\n\tstatic uint8 m_nAmbientRed_Obj_Bl[NUMHOURS][NUMWEATHERS];\n\tstatic uint8 m_nAmbientGreen_Obj_Bl[NUMHOURS][NUMWEATHERS];\n\tstatic uint8 m_nAmbientBlue_Obj_Bl[NUMHOURS][NUMWEATHERS];\n\tstatic uint8 m_nDirectionalRed[NUMHOURS][NUMWEATHERS];\n\tstatic uint8 m_nDirectionalGreen[NUMHOURS][NUMWEATHERS];\n\tstatic uint8 m_nDirectionalBlue[NUMHOURS][NUMWEATHERS];\n\tstatic uint8 m_nSkyTopRed[NUMHOURS][NUMWEATHERS];\n\tstatic uint8 m_nSkyTopGreen[NUMHOURS][NUMWEATHERS];\n\tstatic uint8 m_nSkyTopBlue[NUMHOURS][NUMWEATHERS];\n\tstatic uint8 m_nSkyBottomRed[NUMHOURS][NUMWEATHERS];\n\tstatic uint8 m_nSkyBottomGreen[NUMHOURS][NUMWEATHERS];\n\tstatic uint8 m_nSkyBottomBlue[NUMHOURS][NUMWEATHERS];\n\tstatic uint8 m_nSunCoreRed[NUMHOURS][NUMWEATHERS];\n\tstatic uint8 m_nSunCoreGreen[NUMHOURS][NUMWEATHERS];\n\tstatic uint8 m_nSunCoreBlue[NUMHOURS][NUMWEATHERS];\n\tstatic uint8 m_nSunCoronaRed[NUMHOURS][NUMWEATHERS];\n\tstatic uint8 m_nSunCoronaGreen[NUMHOURS][NUMWEATHERS];\n\tstatic uint8 m_nSunCoronaBlue[NUMHOURS][NUMWEATHERS];\n\tstatic int8 m_fSunSize[NUMHOURS][NUMWEATHERS];\n\tstatic int8 m_fSpriteSize[NUMHOURS][NUMWEATHERS];\n\tstatic int8 m_fSpriteBrightness[NUMHOURS][NUMWEATHERS];\n\tstatic uint8 m_nShadowStrength[NUMHOURS][NUMWEATHERS];\n\tstatic uint8 m_nLightShadowStrength[NUMHOURS][NUMWEATHERS];\n\tstatic uint8 m_nPoleShadowStrength[NUMHOURS][NUMWEATHERS];\n\tstatic int16 m_fFogStart[NUMHOURS][NUMWEATHERS];\n\tstatic int16 m_fFarClip[NUMHOURS][NUMWEATHERS];\n\tstatic uint8 m_fLightsOnGroundBrightness[NUMHOURS][NUMWEATHERS];\n\tstatic uint8 m_nLowCloudsRed[NUMHOURS][NUMWEATHERS];\n\tstatic uint8 m_nLowCloudsGreen[NUMHOURS][NUMWEATHERS];\n\tstatic uint8 m_nLowCloudsBlue[NUMHOURS][NUMWEATHERS];\n\tstatic uint8 m_nFluffyCloudsTopRed[NUMHOURS][NUMWEATHERS];\n\tstatic uint8 m_nFluffyCloudsTopGreen[NUMHOURS][NUMWEATHERS];\n\tstatic uint8 m_nFluffyCloudsTopBlue[NUMHOURS][NUMWEATHERS];\n\tstatic uint8 m_nFluffyCloudsBottomRed[NUMHOURS][NUMWEATHERS];\n\tstatic uint8 m_nFluffyCloudsBottomGreen[NUMHOURS][NUMWEATHERS];\n\tstatic uint8 m_nFluffyCloudsBottomBlue[NUMHOURS][NUMWEATHERS];\n\tstatic uint8 m_fBlurRed[NUMHOURS][NUMWEATHERS];\n\tstatic uint8 m_fBlurGreen[NUMHOURS][NUMWEATHERS];\n\tstatic uint8 m_fBlurBlue[NUMHOURS][NUMWEATHERS];\n\tstatic uint8 m_fWaterRed[NUMHOURS][NUMWEATHERS];\n\tstatic uint8 m_fWaterGreen[NUMHOURS][NUMWEATHERS];\n\tstatic uint8 m_fWaterBlue[NUMHOURS][NUMWEATHERS];\n\tstatic uint8 m_fWaterAlpha[NUMHOURS][NUMWEATHERS];\n\n\tstatic float m_fCurrentAmbientRed;\n\tstatic float m_fCurrentAmbientGreen;\n\tstatic float m_fCurrentAmbientBlue;\n\tstatic float m_fCurrentAmbientRed_Obj;\n\tstatic float m_fCurrentAmbientGreen_Obj;\n\tstatic float m_fCurrentAmbientBlue_Obj;\n\tstatic float m_fCurrentAmbientRed_Bl;\n\tstatic float m_fCurrentAmbientGreen_Bl;\n\tstatic float m_fCurrentAmbientBlue_Bl;\n\tstatic float m_fCurrentAmbientRed_Obj_Bl;\n\tstatic float m_fCurrentAmbientGreen_Obj_Bl;\n\tstatic float m_fCurrentAmbientBlue_Obj_Bl;\n\tstatic float m_fCurrentDirectionalRed;\n\tstatic float m_fCurrentDirectionalGreen;\n\tstatic float m_fCurrentDirectionalBlue;\n\tstatic int32 m_nCurrentSkyTopRed;\n\tstatic int32 m_nCurrentSkyTopGreen;\n\tstatic int32 m_nCurrentSkyTopBlue;\n\tstatic int32 m_nCurrentSkyBottomRed;\n\tstatic int32 m_nCurrentSkyBottomGreen;\n\tstatic int32 m_nCurrentSkyBottomBlue;\n\tstatic int32 m_nCurrentSunCoreRed;\n\tstatic int32 m_nCurrentSunCoreGreen;\n\tstatic int32 m_nCurrentSunCoreBlue;\n\tstatic int32 m_nCurrentSunCoronaRed;\n\tstatic int32 m_nCurrentSunCoronaGreen;\n\tstatic int32 m_nCurrentSunCoronaBlue;\n\tstatic float m_fCurrentSunSize;\n\tstatic float m_fCurrentSpriteSize;\n\tstatic float m_fCurrentSpriteBrightness;\n\tstatic int32 m_nCurrentShadowStrength;\n\tstatic int32 m_nCurrentLightShadowStrength;\n\tstatic int32 m_nCurrentPoleShadowStrength;\n\tstatic float m_fCurrentFogStart;\n\tstatic float m_fCurrentFarClip;\n\tstatic float m_fCurrentLightsOnGroundBrightness;\n\tstatic int32 m_nCurrentLowCloudsRed;\n\tstatic int32 m_nCurrentLowCloudsGreen;\n\tstatic int32 m_nCurrentLowCloudsBlue;\n\tstatic int32 m_nCurrentFluffyCloudsTopRed;\n\tstatic int32 m_nCurrentFluffyCloudsTopGreen;\n\tstatic int32 m_nCurrentFluffyCloudsTopBlue;\n\tstatic int32 m_nCurrentFluffyCloudsBottomRed;\n\tstatic int32 m_nCurrentFluffyCloudsBottomGreen;\n\tstatic int32 m_nCurrentFluffyCloudsBottomBlue;\n\tstatic float m_fCurrentBlurRed;\n\tstatic float m_fCurrentBlurGreen;\n\tstatic float m_fCurrentBlurBlue;\n\tstatic float m_fCurrentWaterRed;\n\tstatic float m_fCurrentWaterGreen;\n\tstatic float m_fCurrentWaterBlue;\n\tstatic float m_fCurrentWaterAlpha;\n\tstatic int32 m_nCurrentFogColourRed;\n\tstatic int32 m_nCurrentFogColourGreen;\n\tstatic int32 m_nCurrentFogColourBlue;\n\n\tstatic int32 m_FogReduction;\n\npublic:\n\tstatic int32 m_bExtraColourOn;\n\tstatic int32 m_ExtraColour;\n\tstatic float m_ExtraColourInter;\n\tstatic int32 m_CurrentStoredValue;\n\tstatic CVector m_VectorToSun[16];\n\tstatic float m_fShadowFrontX[16];\n\tstatic float m_fShadowFrontY[16];\n\tstatic float m_fShadowSideX[16];\n\tstatic float m_fShadowSideY[16];\n\tstatic float m_fShadowDisplacementX[16];\n\tstatic float m_fShadowDisplacementY[16];\n\n\tstatic float GetAmbientRed(void) { return m_fCurrentAmbientRed; }\n\tstatic float GetAmbientGreen(void) { return m_fCurrentAmbientGreen; }\n\tstatic float GetAmbientBlue(void) { return m_fCurrentAmbientBlue; }\n\tstatic float GetAmbientRed_Obj(void) { return m_fCurrentAmbientRed_Obj; }\n\tstatic float GetAmbientGreen_Obj(void) { return m_fCurrentAmbientGreen_Obj; }\n\tstatic float GetAmbientBlue_Obj(void) { return m_fCurrentAmbientBlue_Obj; }\n\tstatic float GetAmbientRed_Bl(void) { return m_fCurrentAmbientRed_Bl; }\n\tstatic float GetAmbientGreen_Bl(void) { return m_fCurrentAmbientGreen_Bl; }\n\tstatic float GetAmbientBlue_Bl(void) { return m_fCurrentAmbientBlue_Bl; }\n\tstatic float GetAmbientRed_Obj_Bl(void) { return m_fCurrentAmbientRed_Obj_Bl; }\n\tstatic float GetAmbientGreen_Obj_Bl(void) { return m_fCurrentAmbientGreen_Obj_Bl; }\n\tstatic float GetAmbientBlue_Obj_Bl(void) { return m_fCurrentAmbientBlue_Obj_Bl; }\n\tstatic float GetDirectionalRed(void) { return m_fCurrentDirectionalRed; }\n\tstatic float GetDirectionalGreen(void) { return m_fCurrentDirectionalGreen; }\n\tstatic float GetDirectionalBlue(void) { return m_fCurrentDirectionalBlue; }\n\tstatic int32 GetSkyTopRed(void) { return m_nCurrentSkyTopRed; }\n\tstatic int32 GetSkyTopGreen(void) { return m_nCurrentSkyTopGreen; }\n\tstatic int32 GetSkyTopBlue(void) { return m_nCurrentSkyTopBlue; }\n\tstatic int32 GetSkyBottomRed(void) { return m_nCurrentSkyBottomRed; }\n\tstatic int32 GetSkyBottomGreen(void) { return m_nCurrentSkyBottomGreen; }\n\tstatic int32 GetSkyBottomBlue(void) { return m_nCurrentSkyBottomBlue; }\n\tstatic int32 GetSunCoreRed(void) { return m_nCurrentSunCoreRed; }\n\tstatic int32 GetSunCoreGreen(void) { return m_nCurrentSunCoreGreen; }\n\tstatic int32 GetSunCoreBlue(void) { return m_nCurrentSunCoreBlue; }\n\tstatic int32 GetSunCoronaRed(void) { return m_nCurrentSunCoronaRed; }\n\tstatic int32 GetSunCoronaGreen(void) { return m_nCurrentSunCoronaGreen; }\n\tstatic int32 GetSunCoronaBlue(void) { return m_nCurrentSunCoronaBlue; }\n\tstatic float GetSunSize(void) { return m_fCurrentSunSize; }\n\tstatic float GetSpriteBrightness(void) { return m_fCurrentSpriteBrightness; }\n\tstatic float GetSpriteSize(void) { return m_fCurrentSpriteSize; }\n\tstatic int32 GetShadowStrength(void) { return m_nCurrentShadowStrength; }\n\tstatic int32 GetLightShadowStrength(void) { return m_nCurrentLightShadowStrength; }\n\tstatic float GetLightOnGroundBrightness(void) { return m_fCurrentLightsOnGroundBrightness; }\n\tstatic float GetFarClip(void) { return m_fCurrentFarClip; }\n\tstatic float GetFogStart(void) { return m_fCurrentFogStart; }\n\n\tstatic int32 GetLowCloudsRed(void) { return m_nCurrentLowCloudsRed; }\n\tstatic int32 GetLowCloudsGreen(void) { return m_nCurrentLowCloudsGreen; }\n\tstatic int32 GetLowCloudsBlue(void) { return m_nCurrentLowCloudsBlue; }\n\tstatic int32 GetFluffyCloudsTopRed(void) { return m_nCurrentFluffyCloudsTopRed; }\n\tstatic int32 GetFluffyCloudsTopGreen(void) { return m_nCurrentFluffyCloudsTopGreen; }\n\tstatic int32 GetFluffyCloudsTopBlue(void) { return m_nCurrentFluffyCloudsTopBlue; }\n\tstatic int32 GetFluffyCloudsBottomRed(void) { return m_nCurrentFluffyCloudsBottomRed; }\n\tstatic int32 GetFluffyCloudsBottomGreen(void) { return m_nCurrentFluffyCloudsBottomGreen; }\n\tstatic int32 GetFluffyCloudsBottomBlue(void) { return m_nCurrentFluffyCloudsBottomBlue; }\n\tstatic int32 GetFogRed(void) { return m_nCurrentFogColourRed; }\n\tstatic int32 GetFogGreen(void) { return m_nCurrentFogColourGreen; }\n\tstatic int32 GetFogBlue(void) { return m_nCurrentFogColourBlue; }\n\tstatic int32 GetFogReduction(void) { return m_FogReduction; }\n\n\tstatic int32 GetBlurRed(void) { return m_fCurrentBlurRed; }\n\tstatic int32 GetBlurGreen(void) { return m_fCurrentBlurGreen; }\n\tstatic int32 GetBlurBlue(void) { return m_fCurrentBlurBlue; }\n\tstatic int32 GetWaterRed(void) { return m_fCurrentWaterRed; }\n\tstatic int32 GetWaterGreen(void) { return m_fCurrentWaterGreen; }\n\tstatic int32 GetWaterBlue(void) { return m_fCurrentWaterBlue; }\n\tstatic int32 GetWaterAlpha(void) { return m_fCurrentWaterAlpha; }\n\n\tstatic void Initialise(void);\n\tstatic void Update(void);\n\tstatic float Interpolate(int8 *a, int8 *b);\n\tstatic float Interpolate(uint8 *a, uint8 *b);\n\tstatic float Interpolate(int16 *a, int16 *b);\n\tstatic void StartExtraColour(int32 c, bool fade);\n\tstatic void StopExtraColour(bool fade);\n\tstatic CVector &GetSunDirection(void) { return m_VectorToSun[m_CurrentStoredValue]; }\n\tstatic float GetShadowFrontX(void) { return m_fShadowFrontX[m_CurrentStoredValue]; }\n\tstatic float GetShadowFrontY(void) { return m_fShadowFrontY[m_CurrentStoredValue]; }\n\tstatic float GetShadowSideX(void) { return m_fShadowSideX[m_CurrentStoredValue]; }\n\tstatic float GetShadowSideY(void) { return m_fShadowSideY[m_CurrentStoredValue]; }\n\tstatic float GetShadowDisplacementX(void) { return m_fShadowDisplacementX[m_CurrentStoredValue]; }\n\tstatic float GetShadowDisplacementY(void) { return m_fShadowDisplacementY[m_CurrentStoredValue]; }\n};\n"
  },
  {
    "path": "src/render/VarConsole.cpp",
    "content": "#include \"common.h\"\n#include \"VarConsole.h\"\n#include \"Font.h\"\n#include \"Pad.h\"\n\n#define VAR_CONSOLE_PAD 1\n\nCVarConsole VarConsole;\n\nvoid\nCVarConsole::Initialise()\n{\n\tm_nCountEntries = 0;\n\tm_nCurPage = 1;\n\tm_bIsOpen = false;\n\tm_nCurEntry = 0;\n\tm_nFirstEntryOnPage = 0;\n}\n\nvoid\nCVarConsole::Add(char *text, int8 *pVal, uint8 step, int8 min, int8 max, bool8 isVar)\n{\n\tint i;\n\tfor (i = 0; i < m_nCountEntries; i++) {\n\t\tif (m_aEntries[i].text == text)\n\t\t\treturn;\n\t}\n\n\tm_aEntries[i].text = text;\n\tm_aEntries[i].pInt8Value = pVal;\n\tm_aEntries[i].bAllowExceedBounds = isVar;\n\tm_aEntries[i].VarType = VCE_TYPE_INT8;\n\tm_aEntries[i].I8_step = step;\n\tm_aEntries[i].I8_min = min;\n\tm_aEntries[i].I8_max = max;\n\tm_nCountEntries++;\n}\n\nvoid\nCVarConsole::Add(char *text, int16 *pVal, uint16 step, int16 min, int16 max, bool8 isVar)\n{\n\tint i;\n\tfor (i = 0; i < m_nCountEntries; i++) {\n\t\tif (m_aEntries[i].text == text)\n\t\t\treturn;\n\t}\n\n\tm_aEntries[i].text = text;\n\tm_aEntries[i].pInt16Value = pVal;\n\tm_aEntries[i].bAllowExceedBounds = isVar;\n\tm_aEntries[i].VarType = VCE_TYPE_INT16;\n\tm_aEntries[i].I16_step = step;\n\tm_aEntries[i].I16_min = min;\n\tm_aEntries[i].I16_max = max;\n\tm_nCountEntries++;\n}\n\nvoid\nCVarConsole::Add(char *text, int32 *pVal, uint32 step, int32 min, int32 max, bool8 isVar)\n{\n\tint i;\n\tfor (i = 0; i < m_nCountEntries; i++) {\n\t\tif (m_aEntries[i].text == text)\n\t\t\treturn;\n\t}\n\n\tm_aEntries[i].text = text;\n\tm_aEntries[i].pInt32Value = pVal;\n\tm_aEntries[i].bAllowExceedBounds = isVar;\n\tm_aEntries[i].VarType = VCE_TYPE_INT32;\n\tm_aEntries[i].I32_step = step;\n\tm_aEntries[i].I32_min = min;\n\tm_aEntries[i].I32_max = max;\n\tm_nCountEntries++;\n}\n\nvoid\nCVarConsole::Add(char *text, int64 *pVal, uint64 step, int64 min, int64 max, bool8 isVar)\n{\n\tint i;\n\tfor (i = 0; i < m_nCountEntries; i++) {\n\t\tif (m_aEntries[i].text == text)\n\t\t\treturn;\n\t}\n\n\tm_aEntries[i].text = text;\n\tm_aEntries[i].pInt64Value = pVal;\n\tm_aEntries[i].bAllowExceedBounds = isVar;\n\tm_aEntries[i].VarType = VCE_TYPE_INT64;\n\tm_aEntries[i].I64_step = step;\n\tm_aEntries[i].I64_min = min;\n\tm_aEntries[i].I64_max = max;\n\tm_nCountEntries++;\n}\n\nvoid\nCVarConsole::Add(char *text, uint8 *pVal, uint8 step, int8 min, int8 max, bool8 isVar)\n{\n\tint i;\n\tfor (i = 0; i < m_nCountEntries; i++) {\n\t\tif (m_aEntries[i].text == text)\n\t\t\treturn;\n\t}\n\n\tm_aEntries[i].text = text;\n\tm_aEntries[i].pUint8Value = pVal;\n\tm_aEntries[i].bAllowExceedBounds = isVar;\n\tm_aEntries[i].VarType = VCE_TYPE_UINT8;\n\tm_aEntries[i].I8_step = step;\n\tm_aEntries[i].I8_min = min;\n\tm_aEntries[i].I8_max = max;\n\tm_nCountEntries++;\n}\n\nvoid\nCVarConsole::Add(char *text, uint16 *pVal, uint16 step, int16 min, int16 max, bool8 isVar)\n{\n\tint i;\n\tfor (i = 0; i < m_nCountEntries; i++) {\n\t\tif (m_aEntries[i].text == text)\n\t\t\treturn;\n\t}\n\n\tm_aEntries[i].text = text;\n\tm_aEntries[i].pUint16Value = pVal;\n\tm_aEntries[i].bAllowExceedBounds = isVar;\n\tm_aEntries[i].VarType = VCE_TYPE_UINT16;\n\tm_aEntries[i].I16_step = step;\n\tm_aEntries[i].I16_min = min;\n\tm_aEntries[i].I16_max = max;\n\tm_nCountEntries++;\n}\n\nvoid\nCVarConsole::Add(char *text, uint32 *pVal, uint32 step, int32 min, int32 max, bool8 isVar)\n{\n\tint i;\n\tfor (i = 0; i < m_nCountEntries; i++) {\n\t\tif (m_aEntries[i].text == text)\n\t\t\treturn;\n\t}\n\n\tm_aEntries[i].text = text;\n\tm_aEntries[i].pUint32Value = pVal;\n\tm_aEntries[i].bAllowExceedBounds = isVar;\n\tm_aEntries[i].VarType = VCE_TYPE_UINT32;\n\tm_aEntries[i].I32_step = step;\n\tm_aEntries[i].I32_min = min;\n\tm_aEntries[i].I32_max = max;\n\tm_nCountEntries++;\n}\n\nvoid\nCVarConsole::Add(char *text, uint64 *pVal, uint64 step, int64 min, int64 max, bool8 isVar)\n{\n\tint i;\n\tfor (i = 0; i < m_nCountEntries; i++) {\n\t\tif (m_aEntries[i].text == text)\n\t\t\treturn;\n\t}\n\n\tm_aEntries[i].text = text;\n\tm_aEntries[i].pUint64Value = pVal;\n\tm_aEntries[i].bAllowExceedBounds = isVar;\n\tm_aEntries[i].VarType = VCE_TYPE_UINT64;\n\tm_aEntries[i].I64_step = step;\n\tm_aEntries[i].I64_min = min;\n\tm_aEntries[i].I64_max = max;\n\tm_nCountEntries++;\n}\n\nvoid\nCVarConsole::Add(char *text, float *pVal, float step, float min, float max, bool8 isVar)\n{\n\tint i;\n\tfor (i = 0; i < m_nCountEntries; i++) {\n\t\tif (m_aEntries[i].text == text)\n\t\t\treturn;\n\t}\n\n\tm_aEntries[i].text = text;\n\tm_aEntries[i].pFloatValue = pVal;\n\tm_aEntries[i].bAllowExceedBounds = isVar;\n\tm_aEntries[i].VarType = VCE_TYPE_FLOAT;\n\tm_aEntries[i].F_step = step;\n\tm_aEntries[i].F_min = min;\n\tm_aEntries[i].F_max = max;\n\tm_nCountEntries++;\n}\n\nvoid\nCVarConsole::Add(char *text, bool *pVal, bool8 isVar)\n{\n\tint i;\n\tfor (i = 0; i < m_nCountEntries; i++) {\n\t\tif (m_aEntries[i].text == text)\n\t\t\treturn;\n\t}\n\n\tm_aEntries[i].text = text;\n\tm_aEntries[i].pBoolValue = pVal;\n\tm_aEntries[i].bAllowExceedBounds = isVar;\n\tm_aEntries[i].VarType = VCE_TYPE_BOOL;\n\tm_nCountEntries++;\n}\n\nvoid\nCVarConsole::Add(char *text, bool8 *pVal, bool8 isVar)\n{\n\tint i;\n\tfor (i = 0; i < m_nCountEntries; i++) {\n\t\tif (m_aEntries[i].text == text)\n\t\t\treturn;\n\t}\n\n\tm_aEntries[i].text = text;\n\tm_aEntries[i].pUint8Value = pVal;\n\tm_aEntries[i].bAllowExceedBounds = isVar;\n\tm_aEntries[i].VarType = VCE_TYPE_BOOL8;\n\tm_nCountEntries++;\n}\n\nvoid\nCVarConsole::Add(char *text, bool16 *pVal, bool8 isVar)\n{\n\tint i;\n\tfor (i = 0; i < m_nCountEntries; i++) {\n\t\tif (m_aEntries[i].text == text)\n\t\t\treturn;\n\t}\n\n\tm_aEntries[i].text = text;\n\tm_aEntries[i].pUint16Value = pVal;\n\tm_aEntries[i].bAllowExceedBounds = isVar;\n\tm_aEntries[i].VarType = VCE_TYPE_BOOL16;\n\tm_nCountEntries++;\n}\n\nvoid\nCVarConsole::Add(char *text, bool32 *pVal, bool8 isVar)\n{\n\tint i;\n\tfor (i = 0; i < m_nCountEntries; i++) {\n\t\tif (m_aEntries[i].text == text)\n\t\t\treturn;\n\t}\n\n\tm_aEntries[i].text = text;\n\tm_aEntries[i].pUint32Value = pVal;\n\tm_aEntries[i].bAllowExceedBounds = isVar;\n\tm_aEntries[i].VarType = VCE_TYPE_BOOL32;\n\tm_nCountEntries++;\n}\n\nvoid\nCVarConsole::Add(char *text, void (*pCallback)(void))\n{\n\tint i;\n\tfor (i = 0; i < m_nCountEntries; i++) {\n\t\tif (m_aEntries[i].text == text)\n\t\t\treturn;\n\t}\n\n\tm_aEntries[i].text = text;\n\tm_aEntries[i].pCallback = pCallback;\n\tm_aEntries[i].VarType = VCE_TYPE_FUNCTION;\n\tm_nCountEntries++;\n}\n\nvoid\nCVarConsole::Remove(char *text)\n{\n\tint i;\n\tfor (i = 0; i < m_nCountEntries; i++) {\n\t\tif (m_aEntries[i].text == text)\n\t\t{\n\t\t\tfor (int j = i; j < m_nCountEntries-1; j++)\n\t\t\t\tm_aEntries[j] = m_aEntries[j+1];\n\t\t\tm_nCountEntries--;\n\t\t\treturn;\n\t\t}\n\t}\n}\n\nvoid\nCVarConsole::SortPages()\n{\n\tm_nNumPages = m_nCountEntries / 30 + 1;\n}\n\nvoid\nCVarConsole::Display()\n{\n\tchar s[256];\n\twchar ws[256];\n\n\tCFont::SetColor(CRGBA(200, 200, 200, 255));\n\tCFont::SetFontStyle(FONT_STANDARD);\n\tCFont::SetScale(SCREEN_SCALE_X(0.5f), SCREEN_SCALE_Y(0.6f));\n\tCFont::SetDropShadowPosition(2);\n\tCFont::SetDropColor(CRGBA(0, 0, 0, 255));\n\tCFont::SetPropOn();\n\tCFont::SetWrapx(SCREEN_SCALE_X(DEFAULT_SCREEN_WIDTH));\n\tCFont::SetRightJustifyWrap(0.0f);\n\tsprintf(s, \"PAGE %d\", m_nCurPage);\n\tAsciiToUnicode(s, ws);\n\tCFont::SetRightJustifyOn();\n\tCFont::PrintString(SCREEN_SCALE_X(310.0f), SCREEN_SCALE_Y(30.0f), ws);\n\tCFont::SetRightJustifyOff();\n\tint y = 45;\n\tfor (int i = m_nFirstEntryOnPage; i < m_nCountEntries && i < m_nFirstEntryOnPage + 30; i++)\n\t{\n\t\tswitch (m_aEntries[i].VarType)\n\t\t{\n\t\tcase VCE_TYPE_INT8:\n\t\t\tsprintf(s, \"(%d) %s:I8:%d\", i + 1, m_aEntries[i].text, *m_aEntries[i].pInt8Value);\n\t\t\tbreak;\n\t\tcase VCE_TYPE_INT16:\n\t\t\tsprintf(s, \"(%d) %s:I16:%d\", i + 1, m_aEntries[i].text, *m_aEntries[i].pInt16Value);\n\t\t\tbreak;\n\t\tcase VCE_TYPE_INT32:\n\t\t\tsprintf(s, \"(%d) %s:I32:%d\", i + 1, m_aEntries[i].text, *m_aEntries[i].pInt32Value);\n\t\t\tbreak;\n\t\tcase VCE_TYPE_INT64:\n#ifdef FIX_BUGS  \n\t\t\tsprintf(s, \"(%d) %s:I64:%lld\", i + 1, m_aEntries[i].text, *m_aEntries[i].pInt64Value);\n#else\n\t\t\tsprintf(s, \"(%d) %s:I64:%d\", i + 1, m_aEntries[i].text, (int32)*m_aEntries[i].pInt64Value);\n#endif\n\t\t\tbreak;\n\t\tcase VCE_TYPE_UINT8:\n\t\t\tsprintf(s, \"(%d) %s:U8:%d\", i + 1, m_aEntries[i].text, *m_aEntries[i].pUint8Value);\n\t\t\tbreak;\n\t\tcase VCE_TYPE_UINT16:\n\t\t\tsprintf(s, \"(%d) %s:U6:%d\", i + 1, m_aEntries[i].text, *m_aEntries[i].pUint16Value);\n\t\t\tbreak;\n\t\tcase VCE_TYPE_UINT32:\n\t\t\tsprintf(s, \"(%d) %s:U32:%d\", i + 1, m_aEntries[i].text, *m_aEntries[i].pUint32Value);\n\t\t\tbreak;\n\t\tcase VCE_TYPE_UINT64:\n#ifdef FIX_BUGS\n\t\t\tsprintf(s, \"(%d) %s:U64:%llu\", i + 1, m_aEntries[i].text, *m_aEntries[i].pUint64Value);\n#else\n\t\t\tsprintf(s, \"(%d) %s:U64:%d\", i + 1, m_aEntries[i].text, (uint32)*m_aEntries[i].pUint64Value);\n#endif\n\t\t\tbreak;\n\t\tcase VCE_TYPE_FLOAT:\n\t\t\tsprintf(s, \"(%d) %s:F:%f\", i + 1, m_aEntries[i].text, *m_aEntries[i].pFloatValue);\n\t\t\tbreak;\n\t\tcase VCE_TYPE_BOOL:\n\t\t\tif (*m_aEntries[i].pBoolValue)\n\t\t\t\tsprintf(s, \"(%d) %s:B:TRUE\", i + 1, m_aEntries[i].text);\n\t\t\telse\n\t\t\t\tsprintf(s, \"(%d) %s:B : FALSE\", i + 1, m_aEntries[i].text);\n\t\t\tbreak;\n\t\tcase VCE_TYPE_BOOL8:\n\t\t\tif (*m_aEntries[i].pUint8Value == FALSE)\n\t\t\t\tsprintf(s, \"(%d) %s:B8:FALSE\", i + 1, m_aEntries[i].text);\n\t\t\telse\n\t\t\t\tsprintf(s, \"(%d) %s:B8:TRUE\", i + 1, m_aEntries[i].text);\n\t\t\tbreak;\n\t\tcase VCE_TYPE_BOOL16:\n\t\t\tif (*m_aEntries[i].pUint16Value == FALSE)\n\t\t\t\tsprintf(s, \"(%d) %s:B16:FALSE\", i + 1, m_aEntries[i].text);\n\t\t\telse\n\t\t\t\tsprintf(s, \"(%d) %s:B16:TRUE\", i + 1, m_aEntries[i].text);\n\t\t\tbreak;\n\t\tcase VCE_TYPE_BOOL32:\n\t\t\tif (*m_aEntries[i].pUint32Value == FALSE)\n\t\t\t\tsprintf(s, \"(%d) %s:B32:FALSE\", i + 1, m_aEntries[i].text);\n\t\t\telse\n\t\t\t\tsprintf(s, \"(%d) %s:B32:TRUE\", i + 1, m_aEntries[i].text);\n\t\t\tbreak;\n\t\tcase VCE_TYPE_FUNCTION:\n\t\t\tsprintf(s, \"(%d) %s:FUNCTION:call this function?\", i + 1, m_aEntries[i].text);\n\t\t\tbreak;\n\t\t}\n\t\tAsciiToUnicode(s, ws);\n\t\tif (m_nCurEntry == i) {\n\t\t\tCFont::SetBackgroundOn();\n#ifdef FIX_BUGS\n\t\t\tCFont::SetBackgroundColor(CRGBA(128, 128, 128, 128));\n#endif\n\t\t}\n#ifdef FIX_BUGS\n\t\telse\n\t\t\tCFont::SetBackgroundColor(CRGBA(128, 128, 128, 0));\n#endif\n\n\t\tCFont::SetColor(CRGBA(200, 200, 200, 255));\n\t\tCFont::PrintString(SCREEN_SCALE_X(30.0f), SCREEN_SCALE_Y(y), ws);\n\t\tif (m_nCurEntry == i)\n\t\t\tCFont::SetBackgroundOff();\n\t\ty += 12;\n\t}\n}\n\nvoid\nCVarConsole::ModifyLeft()\n{\n\tCVarConsoleEntry &entry = m_aEntries[m_nCurEntry];\n\tswitch (entry.VarType)\n\t{\n\tcase VCE_TYPE_INT8:\n\t\t*entry.pInt8Value -= entry.I8_step;\n\t\tif (entry.bAllowExceedBounds) {\n\t\t\tif (*entry.pInt8Value < entry.I8_min)\n\t\t\t\t*entry.pInt8Value = entry.I8_max;\n\t\t} else {\n\t\t\tif (*entry.pInt8Value < entry.I8_min)\n\t\t\t\t*entry.pInt8Value = entry.I8_min;\n\t\t}\n\t\tbreak;\n\tcase VCE_TYPE_INT16:\n\t\t*entry.pInt16Value -= entry.I16_step;\n\t\tif (entry.bAllowExceedBounds) {\n\t\t\tif (*entry.pInt16Value < entry.I16_min)\n\t\t\t\t*entry.pInt16Value = entry.I16_max;\n\t\t}\n\t\telse {\n\t\t\tif (*entry.pInt16Value < entry.I16_min)\n\t\t\t\t*entry.pInt16Value = entry.I16_min;\n\t\t}\n\t\tbreak;\n\tcase VCE_TYPE_INT32:\n\t\t*entry.pInt32Value -= entry.I32_step;\n\t\tif (entry.bAllowExceedBounds) {\n\t\t\tif (*entry.pInt32Value < entry.I32_min)\n\t\t\t\t*entry.pInt32Value = entry.I32_max;\n\t\t}\n\t\telse {\n\t\t\tif (*entry.pInt32Value < entry.I32_min)\n\t\t\t\t*entry.pInt32Value = entry.I32_min;\n\t\t}\n\t\tbreak;\n\tcase VCE_TYPE_INT64:\n\t\t*entry.pInt64Value -= entry.I64_step;\n\t\tif (entry.bAllowExceedBounds) {\n\t\t\tif (*entry.pInt64Value < entry.I64_min)\n\t\t\t\t*entry.pInt64Value = entry.I64_max;\n\t\t}\n\t\telse {\n\t\t\tif (*entry.pInt64Value < entry.I64_min)\n\t\t\t\t*entry.pInt64Value = entry.I64_min;\n\t\t}\n\t\tbreak;\n\tcase VCE_TYPE_UINT8:\n\t\t*entry.pUint8Value -= entry.I8_step;\n\t\tif (entry.bAllowExceedBounds) {\n\t\t\tif (*(int8*)entry.pUint8Value < entry.I8_min)\n\t\t\t\t*entry.pUint8Value = entry.I8_max;\n\t\t}\n\t\telse {\n\t\t\tif (*(int8*)entry.pUint8Value < entry.I8_min)\n\t\t\t\t*entry.pUint8Value = entry.I8_min;\n\t\t}\n\t\tbreak;\n\tcase VCE_TYPE_UINT16:\n\t\t*entry.pUint16Value -= entry.I16_step;\n\t\tif (entry.bAllowExceedBounds) {\n\t\t\tif (*(int16*)entry.pUint16Value < entry.I16_min)\n\t\t\t\t*entry.pUint16Value = entry.I16_max;\n\t\t}\n\t\telse {\n\t\t\tif (*(int16*)entry.pUint16Value < entry.I16_min)\n\t\t\t\t*entry.pUint16Value = entry.I16_min;\n\t\t}\n\t\tbreak;\n\tcase VCE_TYPE_UINT32:\n\t\t*entry.pUint32Value -= entry.I32_step;\n\t\tif (entry.bAllowExceedBounds) {\n\t\t\tif (*(int32*)entry.pUint32Value < entry.I32_min)\n\t\t\t\t*entry.pUint32Value = entry.I32_max;\n\t\t}\n\t\telse {\n\t\t\tif (*(int32*)entry.pUint32Value < entry.I32_min)\n\t\t\t\t*entry.pUint32Value = entry.I32_min;\n\t\t}\n\t\tbreak;\n\tcase VCE_TYPE_UINT64:\n\t\t*entry.pUint64Value -= entry.I64_step;\n\t\tif (entry.bAllowExceedBounds) {\n\t\t\tif (*(int64*)entry.pUint64Value < entry.I64_min)\n\t\t\t\t*entry.pUint64Value = entry.I64_max;\n\t\t}\n\t\telse {\n\t\t\tif (*(int64*)entry.pUint64Value < entry.I64_min)\n\t\t\t\t*entry.pUint64Value = entry.I64_min;\n\t\t}\n\t\tbreak;\n\tcase VCE_TYPE_FLOAT:\n\t\t*entry.pFloatValue -= entry.F_step;\n\t\tif (entry.bAllowExceedBounds) {\n\t\t\tif (*entry.pFloatValue < entry.F_min)\n\t\t\t\t*entry.pFloatValue = entry.F_max;\n\t\t}\n\t\telse {\n\t\t\tif (*entry.pFloatValue < entry.F_min)\n\t\t\t\t*entry.pFloatValue = entry.F_min;\n\t\t}\n\t\tbreak;\n\tcase VCE_TYPE_BOOL:\n\t\tif (entry.bAllowExceedBounds)\n\t\t\t*entry.pBoolValue ^= true;\n\t\telse\n\t\t\t*entry.pBoolValue = false;\n\t\tbreak;\n\tcase VCE_TYPE_BOOL8:\n\t\tif (entry.bAllowExceedBounds)\n\t\t\t*entry.pUint8Value = *entry.pUint8Value == false;\n\t\telse\n\t\t\t*entry.pUint8Value = false;\n\t\tbreak;\n\tcase VCE_TYPE_BOOL16:\n\t\tif (entry.bAllowExceedBounds)\n\t\t\t*entry.pUint16Value = *entry.pUint16Value == false;\n\t\telse\n\t\t\t*entry.pUint16Value = false;\n\t\tbreak;\n\tcase VCE_TYPE_BOOL32:\n\t\tif (entry.bAllowExceedBounds)\n\t\t\t*entry.pUint32Value = *entry.pUint32Value == false;\n\t\telse\n\t\t\t*entry.pUint32Value = false;\n\t\tbreak;\n\tcase VCE_TYPE_FUNCTION:\n\t\tentry.pCallback();\n\t\tbreak;\n\tdefault:\n\t\treturn;\n\t}\n}\n\nvoid\nCVarConsole::ModifyRight()\n{\n\tCVarConsoleEntry &entry = m_aEntries[m_nCurEntry];\n\tswitch (entry.VarType)\n\t{\n\tcase VCE_TYPE_INT8:\n\t\t*entry.pInt8Value += entry.I8_step;\n\t\tif (entry.bAllowExceedBounds) {\n\t\t\tif (*entry.pInt8Value > entry.I8_max)\n\t\t\t\t*entry.pInt8Value = entry.I8_min;\n\t\t}\n\t\telse {\n\t\t\tif (*entry.pInt8Value > entry.I8_max)\n\t\t\t\t*entry.pInt8Value = entry.I8_max;\n\t\t}\n\t\tbreak;\n\tcase VCE_TYPE_INT16:\n\t\t*entry.pInt16Value += entry.I16_step;\n\t\tif (entry.bAllowExceedBounds) {\n\t\t\tif (*entry.pInt16Value > entry.I16_max)\n\t\t\t\t*entry.pInt16Value = entry.I16_min;\n\t\t}\n\t\telse {\n\t\t\tif (*entry.pInt16Value > entry.I16_max)\n\t\t\t\t*entry.pInt16Value = entry.I16_max;\n\t\t}\n\t\tbreak;\n\tcase VCE_TYPE_INT32:\n\t\t*entry.pInt32Value += entry.I32_step;\n\t\tif (entry.bAllowExceedBounds) {\n\t\t\tif (*entry.pInt32Value > entry.I32_max)\n\t\t\t\t*entry.pInt32Value = entry.I32_min;\n\t\t}\n\t\telse {\n\t\t\tif (*entry.pInt32Value > entry.I32_max)\n\t\t\t\t*entry.pInt32Value = entry.I32_max;\n\t\t}\n\t\tbreak;\n\tcase VCE_TYPE_INT64:\n\t\t*entry.pInt64Value += entry.I64_step;\n\t\tif (entry.bAllowExceedBounds) {\n\t\t\tif (*entry.pInt64Value > entry.I64_max)\n\t\t\t\t*entry.pInt64Value = entry.I64_min;\n\t\t}\n\t\telse {\n\t\t\tif (*entry.pInt64Value > entry.I64_max)\n\t\t\t\t*entry.pInt64Value = entry.I64_max;\n\t\t}\n\t\tbreak;\n\tcase VCE_TYPE_UINT8:\n\t\t*entry.pUint8Value += entry.I8_step;\n\t\tif (entry.bAllowExceedBounds) {\n\t\t\tif (*entry.pUint8Value > (uint8)entry.I8_max)\n\t\t\t\t*entry.pUint8Value = entry.I8_min;\n\t\t}\n\t\telse {\n\t\t\tif (*entry.pUint8Value > (uint8)entry.I8_max)\n\t\t\t\t*entry.pUint8Value = entry.I8_max;\n\t\t}\n\t\tbreak;\n\tcase VCE_TYPE_UINT16:\n\t\t*entry.pUint16Value += entry.I16_step;\n\t\tif (entry.bAllowExceedBounds) {\n\t\t\tif (*entry.pUint16Value > (uint16)entry.I16_max)\n\t\t\t\t*entry.pUint16Value = entry.I16_min;\n\t\t}\n\t\telse {\n\t\t\tif (*entry.pUint16Value > (uint16)entry.I16_max)\n\t\t\t\t*entry.pUint16Value = entry.I16_max;\n\t\t}\n\t\tbreak;\n\tcase VCE_TYPE_UINT32:\n\t\t*entry.pUint32Value += entry.I32_step;\n\t\tif (entry.bAllowExceedBounds) {\n\t\t\tif (*entry.pUint32Value > (uint32)entry.I32_max)\n\t\t\t\t*entry.pUint32Value = entry.I32_min;\n\t\t}\n\t\telse {\n\t\t\tif (*entry.pUint32Value > (uint32)entry.I32_max)\n\t\t\t\t*entry.pUint32Value = entry.I32_max;\n\t\t}\n\t\tbreak;\n\tcase VCE_TYPE_UINT64:\n\t\t*entry.pUint64Value += entry.I64_step;\n\t\tif (entry.bAllowExceedBounds) {\n\t\t\tif (*entry.pUint64Value > (uint64)entry.I64_max)\n\t\t\t\t*entry.pUint64Value = entry.I64_min;\n\t\t}\n\t\telse {\n\t\t\tif (*entry.pUint64Value > (uint64)entry.I64_max)\n\t\t\t\t*entry.pUint64Value = entry.I64_max;\n\t\t}\n\t\tbreak;\n\tcase VCE_TYPE_FLOAT:\n\t\t*entry.pFloatValue += entry.F_step;\n\t\tif (entry.bAllowExceedBounds) {\n\t\t\tif (*entry.pFloatValue > entry.F_max)\n\t\t\t\t*entry.pFloatValue = entry.F_min;\n\t\t}\n\t\telse {\n\t\t\tif (*entry.pFloatValue > entry.F_max)\n\t\t\t\t*entry.pFloatValue = entry.F_max;\n\t\t}\n\t\tbreak;\n\tcase VCE_TYPE_BOOL:\n\t\tif (entry.bAllowExceedBounds)\n\t\t\t*entry.pBoolValue ^= true;\n\t\telse\n\t\t\t*entry.pBoolValue = true;\n\t\tbreak;\n\tcase VCE_TYPE_BOOL8:\n\t\tif (entry.bAllowExceedBounds)\n\t\t\t*entry.pUint8Value = *entry.pUint8Value == false;\n\t\telse\n\t\t\t*entry.pUint8Value = true;\n\t\tbreak;\n\tcase VCE_TYPE_BOOL16:\n\t\tif (entry.bAllowExceedBounds)\n\t\t\t*entry.pUint16Value = *entry.pUint16Value == false;\n\t\telse\n\t\t\t*entry.pUint16Value = true;\n\t\tbreak;\n\tcase VCE_TYPE_BOOL32:\n\t\tif (entry.bAllowExceedBounds)\n\t\t\t*entry.pUint32Value = *entry.pUint32Value == false;\n\t\telse\n\t\t\t*entry.pUint32Value = true;\n\t\tbreak;\n\tcase VCE_TYPE_FUNCTION:\n\t\tentry.pCallback();\n\t\tbreak;\n\tdefault:\n\t\treturn;\n\t}\n}\n\nvoid\nCVarConsole::Enter()\n{\n\tm_bIsOpen = true;\n}\n\nvoid\nCVarConsole::Exit()\n{\n\tm_bIsOpen = false;\n}\n\nvoid\nCVarConsole::Input()\n{\n\tif (CPad::GetPad(VAR_CONSOLE_PAD)->GetDPadDownJustDown() || CPad::GetPad(VAR_CONSOLE_PAD)->GetAnaloguePadDown())\n\t{\n\t\tm_nCurEntry++;\n\t\tif (m_nCurEntry < m_nCountEntries)\n\t\t{\n\t\t\tif (m_nCurEntry > m_nFirstEntryOnPage + 29)\n\t\t\t{\n\t\t\t\tm_nFirstEntryOnPage = m_nCurEntry;\n\t\t\t\t++m_nCurPage;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tm_nCurEntry = m_nCountEntries - 1;\n\t\t}\n\t}\n\n\tif (CPad::GetPad(VAR_CONSOLE_PAD)->GetDPadUpJustDown() || CPad::GetPad(VAR_CONSOLE_PAD)->GetAnaloguePadUp())\n\t{\n\t\tm_nCurEntry--;\n\t\tif (m_nCurEntry < m_nFirstEntryOnPage)\n\t\t{\n\t\t\tm_nFirstEntryOnPage = m_nCurEntry - 29;\n\t\t\t--m_nCurPage;\n\t\t}\n\t\tif (m_nFirstEntryOnPage < 0)\n\t\t{\n\t\t\tm_nCurEntry = 0;\n\t\t\tm_nFirstEntryOnPage = 0;\n\t\t\tm_nCurPage = 1;\n\t\t}\n\t}\n\tif (CPad::GetPad(VAR_CONSOLE_PAD)->GetSquare())\n\t\tModifyLeft();\n\tif (CPad::GetPad(VAR_CONSOLE_PAD)->GetTriangle())\n\t\tModifyRight();\n\n\tif (CPad::GetPad(VAR_CONSOLE_PAD)->GetDPadLeftJustDown() || CPad::GetPad(VAR_CONSOLE_PAD)->GetAnaloguePadLeft())\n\t\tModifyLeft();\n\n\tif (CPad::GetPad(VAR_CONSOLE_PAD)->GetDPadRightJustDown() || CPad::GetPad(VAR_CONSOLE_PAD)->GetAnaloguePadRight())\n\t\tModifyRight();\n\n\tif (CPad::GetPad(VAR_CONSOLE_PAD)->GetLeftShoulder2JustDown())\n\t{\n\t\tif (m_nCurPage > 1)\n\t\t{\n\t\t\tm_nCurPage--;\n\t\t\tm_nFirstEntryOnPage -= 30;\n\t\t\tm_nCurEntry = m_nFirstEntryOnPage;\n\t\t\tif (m_nFirstEntryOnPage < 0)\n\t\t\t{\n\t\t\t\tm_nFirstEntryOnPage = 0;\n\t\t\t\tm_nCurEntry = m_nFirstEntryOnPage;\n\t\t\t\tm_nCurPage = 1;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (CPad::GetPad(VAR_CONSOLE_PAD)->GetRightShoulder2JustDown())\n\t{\n\t\tif (m_nCurPage < m_nNumPages)\n\t\t{\n\t\t\tm_nCurPage++;\n\t\t\tm_nFirstEntryOnPage += 30;\n\t\t\tm_nCurEntry = m_nFirstEntryOnPage;\n\t\t\tif (m_nFirstEntryOnPage >= m_nCountEntries)\n\t\t\t{\n\t\t\t\tm_nFirstEntryOnPage -= 30;\n\t\t\t\tm_nCurEntry = m_nFirstEntryOnPage;\n\t\t\t\tm_nCurPage--;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (CPad::GetPad(VAR_CONSOLE_PAD)->GetRightShoulder1JustDown() && CPad::GetPad(VAR_CONSOLE_PAD)->GetLeftShoulder1JustDown())\n\t\tExit();\n}\n\nvoid\nCVarConsole::Process()\n{\n\tInput();\n\tSortPages();\n\tDisplay();\n}\n\nbool8 \nCVarConsole::Open()\n{\n\treturn m_bIsOpen;\n}\n\nvoid\nCVarConsole::Check()\n{\n\tif (Open())\n\t\tProcess();\n\telse if (CPad::GetPad(VAR_CONSOLE_PAD)->GetRightShoulder1JustDown() && CPad::GetPad(VAR_CONSOLE_PAD)->GetLeftShoulder1JustDown())\n\t\tEnter();\n}"
  },
  {
    "path": "src/render/VarConsole.h",
    "content": "#pragma once\n\nenum eVarConsoleEntryType\n{\n\tVCE_TYPE_INT8,\n\tVCE_TYPE_INT16,\n\tVCE_TYPE_INT32,\n\tVCE_TYPE_INT64,\n\tVCE_TYPE_UINT8,\n\tVCE_TYPE_UINT16,\n\tVCE_TYPE_UINT32,\n\tVCE_TYPE_UINT64,\n\tVCE_TYPE_FLOAT,\n\tVCE_TYPE_BOOL,\n\tVCE_TYPE_BOOL8,\n\tVCE_TYPE_BOOL16,\n\tVCE_TYPE_BOOL32,\n\tVCE_TYPE_FUNCTION,\n};\n\nstruct CVarConsoleEntry\n{\n\tchar *text;\n\tint8 *pInt8Value;\n\tint16 *pInt16Value;\n\tint32 *pInt32Value;\n\tint64 *pInt64Value;\n\tuint8 *pUint8Value;\n\tuint16 *pUint16Value;\n\tuint32 *pUint32Value;\n\tuint64 *pUint64Value;\n\tfloat *pFloatValue;\n\tbool *pBoolValue;\n\tvoid (*pCallback)(void);\n\tint8 I8_step, I8_max, I8_min;\n\tint16 I16_step, I16_max, I16_min;\n\tint32 I32_step, I32_max, I32_min;\n\tint64 I64_step, I64_max, I64_min;\n\tfloat F_step, F_max, F_min;\n\tbool8 bAllowExceedBounds;\n\tuint8 VarType;\n};\n\n\nclass CVarConsole\n{\n\tint32 m_nCountEntries;\n\tbool8 m_bIsOpen;\n\tint32 m_nCurEntry;\n\tint32 m_nFirstEntryOnPage;\n\tint32 m_nCurPage;\n\tint32 m_nNumPages;\n\tCVarConsoleEntry m_aEntries[91];\npublic:\n#ifdef FIX_BUGS\n\tCVarConsole() { Initialise(); }\n#endif\n\tvoid Initialise();\n\tvoid Add(char *text, int8 *pVal, uint8 step, int8 min, int8 max, bool8 isVar);\n\tvoid Add(char *text, int16 *pVal, uint16 step, int16 min, int16 max, bool8 isVar);\n\tvoid Add(char *text, int32 *pVal, uint32 step, int32 min, int32 max, bool8 isVar);\n\tvoid Add(char *text, int64 *pVal, uint64 step, int64 min, int64 max, bool8 isVar);\n\tvoid Add(char *text, uint8 *pVal, uint8 step, int8 min, int8 max, bool8 isVar);\n\tvoid Add(char *text, uint16 *pVal, uint16 step, int16 min, int16 max, bool8 isVar);\n\tvoid Add(char *text, uint32 *pVal, uint32 step, int32 min, int32 max, bool8 isVar);\n\tvoid Add(char *text, uint64 *pVal, uint64 step, int64 min, int64 max, bool8 isVar);\n\tvoid Add(char *text, float *pVal, float step, float min, float max, bool8 isVar);\n\tvoid Add(char *text, bool *pVal, bool8 isVar);\n\tvoid Add(char *text, bool8 *pVal, bool8 isVar);\n\tvoid Add(char *text, bool16 *pVal, bool8 isVar);\n\tvoid Add(char *text, bool32 *pVal, bool8 isVar);\n\tvoid Add(char *text, void (*pVar)(void));\n\n\tvoid Remove(char *text);\n\n\tvoid SortPages();\n\tvoid Display();\n\n\tvoid ModifyLeft();\n\tvoid ModifyRight();\n\n\tvoid Enter();\n\tvoid Exit();\n\n\tvoid Input();\n\tvoid Process();\n\n\tbool8 Open();\n\tvoid Check();\n};\n\nextern CVarConsole VarConsole;"
  },
  {
    "path": "src/render/WaterCannon.cpp",
    "content": "#include \"common.h\"\n\n#include \"WaterCannon.h\"\n#include \"Vector.h\"\n#include \"General.h\"\n#include \"main.h\"\n#include \"Timer.h\"\n#include \"Pools.h\"\n#include \"Ped.h\"\n#include \"AnimManager.h\"\n#include \"Fire.h\"\n#include \"WaterLevel.h\"\n#include \"Camera.h\"\n#include \"Particle.h\"\n\n#define WATERCANNONVERTS 4\n#define WATERCANNONINDEXES 12\n\nRwIm3DVertex WaterCannonVertices[WATERCANNONVERTS];\nRwImVertexIndex WaterCannonIndexList[WATERCANNONINDEXES];\n\nCWaterCannon CWaterCannons::aCannons[NUM_WATERCANNONS];\n\nvoid CWaterCannon::Init(void)\n{\n\tm_nId = 0;\n\tm_nCur = 0;\n\tm_nTimeCreated = CTimer::GetTimeInMilliseconds();\n\t\n\tfor ( int32 i = 0; i < NUM_SEGMENTPOINTS; i++ )\n\t\tm_abUsed[i] = false;\n\t\n\tRwIm3DVertexSetU(&WaterCannonVertices[0], 0.0f);\n\tRwIm3DVertexSetV(&WaterCannonVertices[0], 0.0f);\n\t\n\tRwIm3DVertexSetU(&WaterCannonVertices[1], 1.0f);\n\tRwIm3DVertexSetV(&WaterCannonVertices[1], 0.0f);\n\t\n\tRwIm3DVertexSetU(&WaterCannonVertices[2], 0.0f);\n\tRwIm3DVertexSetV(&WaterCannonVertices[2], 0.0f);\n\t\n\tRwIm3DVertexSetU(&WaterCannonVertices[3], 1.0f);\n\tRwIm3DVertexSetV(&WaterCannonVertices[3], 0.0f);\n\t\n\tWaterCannonIndexList[0]  = 0;\n\tWaterCannonIndexList[1]  = 1;\n\tWaterCannonIndexList[2]  = 2;\n\t\n\tWaterCannonIndexList[3]  = 1;\n\tWaterCannonIndexList[4]  = 3;\n\tWaterCannonIndexList[5]  = 2;\n\t\n\tWaterCannonIndexList[6]  = 0;\n\tWaterCannonIndexList[7]  = 2;\n\tWaterCannonIndexList[8]  = 1;\n\t\n\tWaterCannonIndexList[9]  = 1;\n\tWaterCannonIndexList[10] = 2;\n\tWaterCannonIndexList[11] = 3;\n}\n\nvoid CWaterCannon::Update_OncePerFrame(int16 index)\n{\n\tASSERT(index < NUM_WATERCANNONS);\n\t\n\tif (CTimer::GetTimeInMilliseconds() > m_nTimeCreated + WATERCANNON_LIFETIME )\n\t{\n\t\tm_nCur = (m_nCur + 1) % NUM_SEGMENTPOINTS;\n\t\tm_abUsed[m_nCur] = false;\n\t}\n\t\n\tfor ( int32 i = 0; i < NUM_SEGMENTPOINTS; i++ )\n\t{\n\t\tif ( m_abUsed[i] )\n\t\t{\n\t\t\tm_avecVelocity[i].z += -WATERCANNON_GRAVITY * CTimer::GetTimeStep();\n\t\t\tm_avecPos[i]        += m_avecVelocity[i]    * CTimer::GetTimeStep();\n\t\t}\n\t}\n\t\n\tfor ( int32 i = 0; i < NUM_SEGMENTPOINTS; i++ )\n\t{\n\t\tif ( m_abUsed[i] && gFireManager.ExtinguishPointWithWater(m_avecPos[i], 4.0f) )\n\t\t{\n\t\t\tbreak;\n\t\t}\n\t}\n\t\n\tif ( ((index + CTimer::GetFrameCounter()) & 3) == 0 )\n\t\tPushPeds();\n\t\n\t// free if unused\n\t\n\tint32 i = 0;\n\twhile ( 1 )\n\t{\n\t\tif ( m_abUsed[i] )\n\t\t\tbreak;\n\t\t\n\t\tif ( ++i >= NUM_SEGMENTPOINTS )\n\t\t{\n\t\t\tm_nId = 0;\n\t\t\treturn;\n\t\t}\n\t}\n}\n\nvoid CWaterCannon::Update_NewInput(CVector *pos, CVector *dir)\n{\n\tASSERT(pos != NULL);\n\tASSERT(dir != NULL);\n\t\n\tm_avecPos[m_nCur]      = *pos;\n\tm_avecVelocity[m_nCur] = *dir;\n\tm_abUsed[m_nCur]       = true;\n}\n\nvoid CWaterCannon::Render(void)\n{\n\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE,      (void *)FALSE);\n\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)TRUE);\n\tRwRenderStateSet(rwRENDERSTATEFOGENABLE,         (void *)TRUE);\n\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER,     (void *)gpWaterRaster);\n\t\n\tfloat v = float(CGeneral::GetRandomNumber() & 255) / 256;\n\t\t\n\tRwIm3DVertexSetV(&WaterCannonVertices[0], v);\n\tRwIm3DVertexSetV(&WaterCannonVertices[1], v);\n\tRwIm3DVertexSetV(&WaterCannonVertices[2], v);\n\tRwIm3DVertexSetV(&WaterCannonVertices[3], v);\n\t\n\tint16 pointA = m_nCur % NUM_SEGMENTPOINTS;\n\t\n\tint16 pointB = pointA - 1;\n\tif ( pointB < 0 )\n\t\tpointB += NUM_SEGMENTPOINTS;\n\n\tbool bInit = false;\n\tCVector norm;\n\t\n\tfor ( int32 i = 0; i < NUM_SEGMENTPOINTS - 1; i++ )\n\t{\n\t\tif ( m_abUsed[pointA] && m_abUsed[pointB] )\n\t\t{\n\t\t\tif ( !bInit )\n\t\t\t{\n\t\t\t\tCVector cp = CrossProduct(m_avecPos[pointB] - m_avecPos[pointA], TheCamera.GetForward());\n\t\t\t\tnorm = cp * (0.05f / cp.Magnitude());\n\t\t\t\tbInit = true;\n\t\t\t}\n\t\t\t\n\t\t\tfloat dist       = float(i*i*i) / 300.0f + 1.0f;\n\t\t\tfloat brightness = float(i) / NUM_SEGMENTPOINTS;\n\t\t\t\n\t\t\tint32 color = (int32)((1.0f - brightness*brightness) * 255.0f);\n\t\t\tCVector offset = dist * norm;\n\t\t\t\n\t\t\tRwIm3DVertexSetRGBA(&WaterCannonVertices[0], color, color, color, color);\n\t\t\tRwIm3DVertexSetPos (&WaterCannonVertices[0], m_avecPos[pointA].x - offset.x, m_avecPos[pointA].y - offset.y, m_avecPos[pointA].z - offset.z);\n\t\t\t\t\n\t\t\tRwIm3DVertexSetRGBA(&WaterCannonVertices[1], color, color, color, color);\n\t\t\tRwIm3DVertexSetPos (&WaterCannonVertices[1], m_avecPos[pointA].x + offset.x, m_avecPos[pointA].y + offset.y, m_avecPos[pointA].z + offset.z);\n\t\t\t\n\t\t\tRwIm3DVertexSetRGBA(&WaterCannonVertices[2], color, color, color, color);\n\t\t\tRwIm3DVertexSetPos (&WaterCannonVertices[2], m_avecPos[pointB].x - offset.x, m_avecPos[pointB].y - offset.y, m_avecPos[pointB].z - offset.z);\n\t\t\t\n\t\t\tRwIm3DVertexSetRGBA(&WaterCannonVertices[3], color, color, color, color);\n\t\t\tRwIm3DVertexSetPos (&WaterCannonVertices[3], m_avecPos[pointB].x + offset.x, m_avecPos[pointB].y + offset.y, m_avecPos[pointB].z + offset.z);\n\t\t\t\n\t\t\tLittleTest();\n\n\t\t\tif ( RwIm3DTransform(WaterCannonVertices, WATERCANNONVERTS, NULL, rwIM3D_VERTEXUV) )\n\t\t\t{\n\t\t\t\tRwIm3DRenderIndexedPrimitive(rwPRIMTYPETRILIST, WaterCannonIndexList, WATERCANNONINDEXES);\n\t\t\t\tRwIm3DEnd();\n\t\t\t}\n\t\t}\n\t\t\n\t\tpointA = pointB--;\n\t\tif ( pointB < 0 )\n\t\t\tpointB += NUM_SEGMENTPOINTS;\n\t}\n\t\n\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE,      (void *)TRUE);\n\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)FALSE);\n\tRwRenderStateSet(rwRENDERSTATEFOGENABLE,         (void *)FALSE);\n}\n\nvoid CWaterCannon::PushPeds(void)\n{\n\tfloat minx = 10000.0f;\n\tfloat maxx = -10000.0f;\n\tfloat miny = 10000.0f;\n\tfloat maxy = -10000.0f;\n\tfloat minz = 10000.0f;\n\tfloat maxz = -10000.0f;\n  \n\tfor ( int32 i = 0; i < NUM_SEGMENTPOINTS; i++ )\n\t{\n\t\tif ( m_abUsed[i] )\n\t\t{\n\t\t\tminx = Min(minx, m_avecPos[i].x);\n\t\t\tmaxx = Max(maxx, m_avecPos[i].x);\n\t\t\t\n\t\t\tminy = Min(miny, m_avecPos[i].y);\n\t\t\tmaxy = Max(maxy, m_avecPos[i].y);\n\t\t\t\n\t\t\tminz = Min(minz, m_avecPos[i].z);\n\t\t\tmaxz = Max(maxz, m_avecPos[i].z);\n\t\t}\n\t}\n\t\n\tfor ( int32 i = CPools::GetPedPool()->GetSize() - 1; i >= 0; i--)\n\t{\n\t\tCPed *ped = CPools::GetPedPool()->GetSlot(i);\n\t\tif ( ped )\n\t\t{\n\t\t\tif (   ped->GetPosition().x > minx && ped->GetPosition().x < maxx\n\t\t\t\t&& ped->GetPosition().y > miny && ped->GetPosition().y < maxy\n\t\t\t\t&& ped->GetPosition().z > minz && ped->GetPosition().z < maxz )\n\t\t\t{\n\t\t\t\tfor ( int32 j = 0; j < NUM_SEGMENTPOINTS; j++ )\n\t\t\t\t{\n\t\t\t\t\tif ( m_abUsed[j] )\n\t\t\t\t\t{\n\t\t\t\t\t\tCVector dist = m_avecPos[j] - ped->GetPosition();\n\t\t\t\t\t\t\n\t\t\t\t\t\tif ( dist.MagnitudeSqr() < 5.0f )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tint32 localDir = ped->GetLocalDirection(CVector2D(1.0f, 0.0f));\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tped->bIsStanding = false;\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tped->ApplyMoveForce(0.0f, 0.0f, 2.0f * CTimer::GetTimeStep());\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tped->m_vecMoveSpeed.x = (0.6f * m_avecVelocity[j].x + ped->m_vecMoveSpeed.x) * 0.5f;\n\t\t\t\t\t\t\tped->m_vecMoveSpeed.y = (0.6f * m_avecVelocity[j].y + ped->m_vecMoveSpeed.y) * 0.5f;\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tfloat pedSpeed2D = ped->m_vecMoveSpeed.Magnitude2D();\n\n\t\t\t\t\t\t\tif ( pedSpeed2D > 0.2f ) {\n\t\t\t\t\t\t\t\tped->m_vecMoveSpeed.x *= (0.2f / pedSpeed2D);\n\t\t\t\t\t\t\t\tped->m_vecMoveSpeed.y *= (0.2f / pedSpeed2D);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tped->SetFall(2000, (AnimationId)(localDir + ANIM_STD_HIGHIMPACT_FRONT), 0);\n\t\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_STEAM_NY_SLOWMOTION, ped->GetPosition(), ped->m_vecMoveSpeed * 0.3f, 0, 0.5f);\n\t\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_CAR_SPLASH, ped->GetPosition(), ped->m_vecMoveSpeed * -0.3f + CVector(0.f, 0.f, 0.5f), 0, 0.5f,\n\t\t\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(0.f, 10.f), CGeneral::GetRandomNumberInRange(0.f, 90.f), 1);\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tj = NUM_SEGMENTPOINTS;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\t\n}\n\nvoid CWaterCannons::Init(void)\n{\n\tfor ( int32 i = 0; i < NUM_WATERCANNONS; i++ )\n\t\taCannons[i].Init();\n}\n\nvoid CWaterCannons::UpdateOne(uint32 id, CVector *pos, CVector *dir)\n{\n\tASSERT(pos != NULL);\n\tASSERT(dir != NULL);\n\t\n\t// find the one by id\n\t{\n\t\tint32 n = 0;\n\t\twhile ( n < NUM_WATERCANNONS && id != aCannons[n].m_nId )\n\t\t\tn++;\n\t\t\n\t\tif ( n < NUM_WATERCANNONS )\n\t\t{\n\t\t\taCannons[n].Update_NewInput(pos, dir);\n\t\t\treturn;\n\t\t}\n\t}\n\t\n\t// if no luck then find a free one\n\t{\n\t\tint32 n = 0;\n\t\twhile ( n < NUM_WATERCANNONS && 0 != aCannons[n].m_nId )\n\t\t\tn++;\n\t\t\n\t\tif ( n < NUM_WATERCANNONS )\n\t\t{\n\t\t\taCannons[n].Init();\n\t\t\taCannons[n].m_nId = id;\n\t\t\taCannons[n].Update_NewInput(pos, dir);\n\t\t\treturn;\n\t\t}\n\t}\n}\n\nvoid CWaterCannons::Update(void)\n{\n\tfor ( int32 i = 0; i < NUM_WATERCANNONS; i++ )\n\t{\n\t\tif ( aCannons[i].m_nId != 0 )\n\t\t\taCannons[i].Update_OncePerFrame(i);\n\t}\n}\n\nvoid CWaterCannons::Render(void)\n{\n\tPUSH_RENDERGROUP(\"CWaterCannons::Render\");\n\tfor ( int32 i = 0; i < NUM_WATERCANNONS; i++ )\n\t{\n\t\tif ( aCannons[i].m_nId != 0 )\n\t\t\taCannons[i].Render();\n\t}\n\tPOP_RENDERGROUP();\n}\n"
  },
  {
    "path": "src/render/WaterCannon.h",
    "content": "#pragma once\n\n#define WATERCANNON_GRAVITY (0.009f)\n#define WATERCANNON_LIFETIME (150)\n\nclass CWaterCannon\n{\npublic:\n\tenum\n\t{\n\t\tNUM_SEGMENTPOINTS = 16,\n\t};\n\t\n\tint32 m_nId;\n\tint16 m_nCur;\n\tuint32 m_nTimeCreated;\n\tCVector m_avecPos[NUM_SEGMENTPOINTS];\n\tCVector m_avecVelocity[NUM_SEGMENTPOINTS];\n\tbool m_abUsed[NUM_SEGMENTPOINTS];\n\t\n\tvoid Init(void);\n\tvoid Update_OncePerFrame(int16 index);\n\tvoid Update_NewInput(CVector *pos, CVector *dir);\n\tvoid Render(void);\n\tvoid PushPeds(void);\n};\n\nVALIDATE_SIZE(CWaterCannon, 412);\n\nclass CWaterCannons\n{\npublic:\n\tstatic CWaterCannon aCannons[NUM_WATERCANNONS];\n\t\n\tstatic void Init(void);\n\tstatic void UpdateOne(uint32 id, CVector *pos, CVector *dir);\n\tstatic void Update();\n\tstatic void Render(void);\n};"
  },
  {
    "path": "src/render/WaterCreatures.cpp",
    "content": "#include \"common.h\"\n#include \"WaterCreatures.h\"\n#include \"ModelIndices.h\"\n#include \"World.h\"\n#include \"WaterLevel.h\"\n#include \"Camera.h\"\n#include \"PlayerPed.h\"\n#include \"General.h\"\n#include \"Object.h\"\n\nint CWaterCreatures::nNumActiveSeaLifeForms;\nCWaterCreature CWaterCreatures::aWaterCreatures[NUM_WATER_CREATURES];\n\nstruct WaterCreatureProperties aProperties[65] = {\n\t{ &MI_FISH1SINGLE,\t0.04f, 1.0f, 0.0008f, 3.0f },\n\t{ &MI_FISH2S,\t\t0.04f, 1.5f, 0.0008f, 3.0f },\n\t{ &MI_FISH2SINGLE,\t0.04f, 1.0f, 0.0008f, 3.0f },\n\t{ &MI_FISH2S,\t\t0.04f, 1.5f, 0.0008f, 3.0f },\n\t{ &MI_FISH3SINGLE,\t0.04f, 1.0f, 0.0008f, 3.0f },\n\t{ &MI_FISH3S,\t\t0.04f, 1.5f, 0.0008f, 3.0f },\n\t{ &MI_FISH1SINGLE,\t0.04f, 1.0f, 0.0008f, 3.0f },\n\t{ &MI_FISH2S,\t\t0.04f, 1.5f, 0.0008f, 3.0f },\n\t{ &MI_FISH2SINGLE,\t0.04f, 1.0f, 0.0008f, 3.0f },\n\t{ &MI_FISH2S,\t\t0.04f, 1.5f, 0.0008f, 3.0f },\n\t{ &MI_FISH3SINGLE,\t0.04f, 1.0f, 0.0008f, 3.0f },\n\t{ &MI_FISH3S,\t\t0.04f, 1.5f, 0.0008f, 3.0f },\n\t{ &MI_JELLYFISH,\t0.01f, 2.2f, 0.0005f, 3.5f },\n\t{ &MI_JELLYFISH01,\t0.01f, 2.2f, 0.0005f, 3.5f },\n\t{ &MI_FISH1SINGLE,\t0.04f, 1.0f, 0.0008f, 3.0f },\n\t{ &MI_FISH2S,\t\t0.04f, 1.5f, 0.0008f, 3.0f },\n\t{ &MI_FISH2SINGLE,\t0.04f, 1.0f, 0.0008f, 3.0f },\n\t{ &MI_FISH2S,\t\t0.04f, 1.5f, 0.0008f, 3.0f },\n\t{ &MI_FISH3SINGLE,\t0.04f, 1.0f, 0.0008f, 3.0f },\n\t{ &MI_FISH3S,\t\t0.04f, 1.5f, 0.0008f, 3.0f },\n\t{ &MI_FISH1SINGLE,\t0.04f, 1.0f, 0.0008f, 3.0f },\n\t{ &MI_FISH2S,\t\t0.04f, 1.5f, 0.0008f, 3.0f },\n\t{ &MI_FISH2SINGLE,\t0.04f, 1.0f, 0.0008f, 3.0f },\n\t{ &MI_FISH2S,\t\t0.04f, 1.5f, 0.0008f, 3.0f },\n\t{ &MI_FISH3SINGLE,\t0.04f, 1.0f, 0.0008f, 3.0f },\n\t{ &MI_FISH3S,\t\t0.04f, 1.5f, 0.0008f, 3.0f },\n\t{ &MI_TURTLE,\t\t0.01f, 2.0f, 0.0005f, 4.0f },\n\t{ &MI_FISH1SINGLE,\t0.04f, 1.0f, 0.0008f, 3.0f },\n\t{ &MI_FISH2S,\t\t0.04f, 1.5f, 0.0008f, 3.0f },\n\t{ &MI_FISH2SINGLE,\t0.04f, 1.0f, 0.0008f, 3.0f },\n\t{ &MI_FISH2S,\t\t0.04f, 1.5f, 0.0008f, 3.0f },\n\t{ &MI_FISH3SINGLE,\t0.04f, 1.0f, 0.0008f, 3.0f },\n\t{ &MI_FISH3S,\t\t0.04f, 1.5f, 0.0008f, 3.0f },\n\t{ &MI_FISH1SINGLE,\t0.04f, 1.0f, 0.0008f, 3.0f },\n\t{ &MI_FISH2S,\t\t0.04f, 1.5f, 0.0008f, 3.0f },\n\t{ &MI_FISH2SINGLE,\t0.04f, 1.0f, 0.0008f, 3.0f },\n\t{ &MI_FISH2S,\t\t0.04f, 1.5f, 0.0008f, 3.0f },\n\t{ &MI_FISH3SINGLE,\t0.04f, 1.0f, 0.0008f, 3.0f },\n\t{ &MI_FISH3S,\t\t0.04f, 1.5f, 0.0008f, 3.0f },\n\t{ &MI_DOLPHIN,\t\t0.03f, 1.5f, 0.0005f, 4.0f },\n\t{ &MI_FISH1SINGLE,\t0.04f, 1.0f, 0.0008f, 3.0f },\n\t{ &MI_FISH2S,\t\t0.04f, 1.5f, 0.0008f, 3.0f },\n\t{ &MI_FISH2SINGLE,\t0.04f, 1.0f, 0.0008f, 3.0f },\n\t{ &MI_FISH2S,\t\t0.04f, 1.5f, 0.0008f, 3.0f },\n\t{ &MI_FISH3SINGLE,\t0.04f, 1.0f, 0.0008f, 3.0f },\n\t{ &MI_FISH3S,\t\t0.04f, 1.5f, 0.0008f, 3.0f },\n\t{ &MI_FISH1SINGLE,\t0.04f, 1.0f, 0.0008f, 3.0f },\n\t{ &MI_FISH2S,\t\t0.04f, 1.5f, 0.0008f, 3.0f },\n\t{ &MI_FISH2SINGLE,\t0.04f, 1.0f, 0.0008f, 3.0f },\n\t{ &MI_FISH2S,\t\t0.04f, 1.5f, 0.0008f, 3.0f },\n\t{ &MI_FISH3SINGLE,\t0.04f, 1.0f, 0.0008f, 3.0f },\n\t{ &MI_FISH3S,\t\t0.04f, 1.5f, 0.0008f, 3.0f },\n\t{ &MI_SHARK,\t\t0.03f, 0.4f, 0.0005f, 4.0f },\n\t{ &MI_FISH1SINGLE,\t0.04f, 1.0f, 0.0008f, 3.0f },\n\t{ &MI_FISH2S,\t\t0.04f, 1.5f, 0.0008f, 3.0f },\n\t{ &MI_FISH2SINGLE,\t0.04f, 1.0f, 0.0008f, 3.0f },\n\t{ &MI_FISH2S,\t\t0.04f, 1.5f, 0.0008f, 3.0f },\n\t{ &MI_FISH3SINGLE,\t0.04f, 1.0f, 0.0008f, 3.0f },\n\t{ &MI_FISH3S,\t\t0.04f, 1.5f, 0.0008f, 3.0f },\n\t{ &MI_FISH1SINGLE,\t0.04f, 1.0f, 0.0008f, 3.0f },\n\t{ &MI_FISH2S,\t\t0.04f, 1.5f, 0.0008f, 3.0f },\n\t{ &MI_FISH2SINGLE,\t0.04f, 1.0f, 0.0008f, 3.0f },\n\t{ &MI_FISH2S,\t\t0.04f, 1.5f, 0.0008f, 3.0f },\n\t{ &MI_FISH3SINGLE,\t0.04f, 1.0f, 0.0008f, 3.0f },\n\t{ &MI_FISH3S,\t\t0.04f, 1.5f, 0.0008f, 3.0f },\n};\n\nCWaterCreature::CWaterCreature() {\n\tFree();\n}\n\nvoid CWaterCreature::Initialise(CObject *pObj, float fFwdSpeed, float fZTurnSpeed, float fWaterDepth, uint32 alpha, eFishSlotState state) {\n\tthis->m_pObj = pObj;\n\tthis->m_fFwdSpeed = fFwdSpeed;\n\tthis->m_fZTurnSpeed = fZTurnSpeed;\n\tthis->m_fWaterDepth = fWaterDepth;\n\tthis->m_alpha = alpha;\n\tthis->m_state = state;\n}\n\nvoid CWaterCreature::Allocate(CObject *pObj, float fFwdSpeed, float fZTurnSpeed, float fWaterDepth, uint32 alpha, eFishSlotState state) {\n\tCWaterCreature::Initialise(pObj, fFwdSpeed, fZTurnSpeed, fWaterDepth, alpha, state);\n}\n\nvoid CWaterCreature::Free() {\n\tCWaterCreature::Initialise(nil, 0.0f, 0.0f, 0.0f, 0, WATER_CREATURE_DISABLED);\n}\n\nCWaterCreature *CWaterCreatures::GetFishStructSlot() {\n\tfor (int i = 0; i < NUM_WATER_CREATURES; i++)\n\t\tif (aWaterCreatures[i].m_state == WATER_CREATURE_DISABLED)\n\t\t\treturn &aWaterCreatures[i];\n\t\n\treturn nil;\n}\n\nCObject *CWaterCreatures::CreateSeaLifeForm(CVector const& pos, int16 modelID, int32 zRotAngle) {\n\tif (CObject::nNoTempObjects >= NUMTEMPOBJECTS)\n\t\treturn nil;\n\n\tCObject *pObj = new CObject(modelID, true);\n\n\tif (!pObj) return nil;\n\t\n\tpObj->SetPosition(pos);\n\tpObj->GetMatrix().UpdateRW();\n\tpObj->m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);\n\tpObj->m_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f);\n\tpObj->GetMatrix().SetRotateZOnly(DEGTORAD(zRotAngle));\n\tpObj->GetMatrix().UpdateRW();\n\tpObj->ObjectCreatedBy = CONTROLLED_SUB_OBJECT;\n\tpObj->bIsStatic = false;\n\n\tif (pObj->ObjectCreatedBy == TEMP_OBJECT) {\n\t\tCObject::nNoTempObjects++;\n\t\tpObj->m_nEndOfLifeTime = CTimer::GetTimeInMilliseconds() + 60000;\n\t}\n\n\tpObj->bTouchingWater = true;\n\tpObj->bUnderwater = true;\n\tCWorld::Add(pObj);\n\n\treturn pObj;\n}\n\nbool CWaterCreatures::IsSpaceForMoreWaterCreatures() {\n\treturn nNumActiveSeaLifeForms < NUM_WATER_CREATURES;\n}\n\nfloat CWaterCreatures::CalculateFishHeading(CVector const& pos1, CVector const& pos2) {\n\tCVector delta = pos1 - pos2;\n\tdelta.Normalise();\n\n\treturn CGeneral::GetRandomNumberInRange(-90, 90) +\n\t\tRADTODEG(delta.Heading() + HALFPI + PI);\n}\n\nvoid CWaterCreatures::CreateOne(CVector const& pos, int32 modelID) {\n\tif (!IsSpaceForMoreWaterCreatures())\n\t\treturn;\n\n\tCVector playerPos = FindPlayerPed()->GetPosition();\n\tCVector fishPos = pos;\n\tfloat fDepth, fLevelNoWaves;\n\tif (!TheCamera.IsSphereVisible(fishPos, 3.0f)\n\t\t&& CWaterLevel::GetWaterDepth(fishPos, &fDepth, &fLevelNoWaves, nil) && fDepth > 4.5f) {\n\t\t\n\t\tif (modelID == -1 || modelID < 0 || modelID > 64)\n\t\t\tmodelID = CGeneral::GetRandomNumberInRange(0, 64);\n\n\t\tWaterCreatureProperties *creature = &aProperties[modelID];\n\t\tfishPos.z = fLevelNoWaves - creature->fLevel;\n\t\tfloat fFwdSpeed = CGeneral::GetRandomNumberInRange(0.0f, creature->fFwdSpeed) + 0.01f;\n\t\tfloat angle = CWaterCreatures::CalculateFishHeading(playerPos, fishPos);\n\t\t\n\t\tCObject *fish = CreateSeaLifeForm(fishPos, *creature->modelID, angle);\n\t\tif (!fish) return;\n\n\t\tfish->SetRwObjectAlpha(255); \n\t\tCWaterCreature *wc = GetFishStructSlot();\n\t\twc->Allocate(fish, fFwdSpeed, 0.0f, creature->fWaterDepth, 255, WATER_CREATURE_INIT);\n\t\tnNumActiveSeaLifeForms++;\n\t}\n}\n\nvoid CWaterCreatures::FreeFishStructSlot(CWaterCreature *wc) {\n\twc->Free();\n}\n\nvoid CWaterCreatures::UpdateAll() {\n\tif (nNumActiveSeaLifeForms == 0)\n\t\treturn;\n\n\tCVector playerPos = FindPlayerPed()->GetPosition();\n\tfor (int i = 0; i < NUM_WATER_CREATURES; i++) {\n\t\tswitch (aWaterCreatures[i].m_state) {\n\t\tcase WATER_CREATURE_ACTIVE:\n\t\t\t// is this even reachable?\n\t\t\taWaterCreatures[i].m_pObj->m_nEndOfLifeTime = CTimer::GetTimeInMilliseconds() + 40000;\n\t\t\tif (!aWaterCreatures[i].m_pObj->GetIsOnScreen()) {\n\t\t\t\taWaterCreatures[i].m_pObj->SetRwObjectAlpha(0);\n\t\t\t\taWaterCreatures[i].m_state = WATER_CREATURE_REMOVE;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t// fall through\n\t\tcase WATER_CREATURE_INIT: {\n\t\t\tif ((playerPos - aWaterCreatures[i].m_pObj->GetPosition()).MagnitudeSqr() < SQR(75.0f)) {\n\t\t\t\tif (aWaterCreatures[i].m_alpha < 255)\n\t\t\t\t\taWaterCreatures[i].m_alpha = Min(aWaterCreatures[i].m_alpha + 4, 255);\n\t\t\t\taWaterCreatures[i].m_pObj->SetRwObjectAlpha(aWaterCreatures[i].m_alpha);\n\t\t\t\tCVector fwd = aWaterCreatures[i].m_pObj->GetRight();\t// for some reason they used x for forward\n\t\t\t\tfwd.Normalise();\n\t\t\t\taWaterCreatures[i].m_pObj->m_vecMoveSpeed = fwd * aWaterCreatures[i].m_fFwdSpeed;\n\t\t\t\taWaterCreatures[i].m_pObj->m_vecTurnSpeed = CVector(0.0f, 0.0f, aWaterCreatures[i].m_fZTurnSpeed);\n\t\t\t\taWaterCreatures[i].m_pObj->bIsStatic = false;\n\t\t\t\tfloat fDepth = 0.0;\n\t\t\t\tCWaterLevel::GetWaterDepth(aWaterCreatures[i].m_pObj->GetPosition(), &fDepth, nil, nil);\n\t\t\t\tif (aWaterCreatures[i].m_fWaterDepth < fDepth) {\n\t\t\t\t\t// it looks like this can never be true initially, looks like a BUG\n\t\t\t\t\tif (aWaterCreatures[i].m_pObj->m_nEndOfLifeTime - 40000 <= CTimer::GetTimeInMilliseconds())\n\t\t\t\t\t\taWaterCreatures[i].m_state = WATER_CREATURE_ACTIVE;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\t// creature is deeper than water\n\t\t\t\t\taWaterCreatures[i].m_state = WATER_CREATURE_FADE_OUT;\n\t\t\t\t}\n\n\t\t\t}\n\t\t\telse {\n\t\t\t\taWaterCreatures[i].m_state = WATER_CREATURE_REMOVE;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tcase WATER_CREATURE_FADE_OUT: {\n\t\t\taWaterCreatures[i].m_pObj->m_nEndOfLifeTime = CTimer::GetTimeInMilliseconds() + 40000;\n\t\t\tif (aWaterCreatures[i].m_alpha <= 0) {\n\t\t\t\taWaterCreatures[i].m_state = WATER_CREATURE_REMOVE;\n\t\t\t}\n\t\t\telse {\n\t\t\t\taWaterCreatures[i].m_alpha = Max(aWaterCreatures[i].m_alpha - 6, 0);\n\t\t\t\taWaterCreatures[i].m_pObj->SetRwObjectAlpha(aWaterCreatures[i].m_alpha);\n\t\t\t\tCVector speed = aWaterCreatures[i].m_pObj->GetRight();\n\t\t\t\tspeed.Normalise();\n\t\t\t\tspeed.x *= aWaterCreatures[i].m_fFwdSpeed;\n\t\t\t\tspeed.y *= aWaterCreatures[i].m_fFwdSpeed;\n\t\t\t\tspeed.z = -0.015f;\n\t\t\t\taWaterCreatures[i].m_pObj->m_vecMoveSpeed = speed;\n\n\t\t\t\tif (!aWaterCreatures[i].m_pObj->GetIsOnScreen())\n\t\t\t\t\taWaterCreatures[i].m_state = WATER_CREATURE_REMOVE;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tcase WATER_CREATURE_REMOVE: \n\t\t\tif (aWaterCreatures[i].m_pObj){\n\t\t\t\tCWorld::Remove(aWaterCreatures[i].m_pObj);\n\t\t\t\tdelete aWaterCreatures[i].m_pObj;\n\t\t\t}\n\t\t\tFreeFishStructSlot(&aWaterCreatures[i]);\n\t\t\tnNumActiveSeaLifeForms--;\n\t\t\taWaterCreatures[i].m_state = WATER_CREATURE_DISABLED;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\nvoid CWaterCreatures::RemoveAll() {\n\tfor (int i = 0; i < NUM_WATER_CREATURES; i++) {\n\t\tif (aWaterCreatures[i].m_state != WATER_CREATURE_DISABLED) {\n\t\t\tif (aWaterCreatures[i].m_pObj){\n\t\t\t\tCWorld::Remove(aWaterCreatures[i].m_pObj);\n\t\t\t\tdelete aWaterCreatures[i].m_pObj;\n\t\t\t}\n\t\t\tFreeFishStructSlot(&aWaterCreatures[i]);\n\t\t\taWaterCreatures[i].m_state = WATER_CREATURE_DISABLED;\n\t\t\tnNumActiveSeaLifeForms--;\n\t\t}\n\t}\n}"
  },
  {
    "path": "src/render/WaterCreatures.h",
    "content": "#pragma once\n\nclass CObject;\n\nenum eFishSlotState {\n\tWATER_CREATURE_INIT = 0,\n\tWATER_CREATURE_ACTIVE,\n\tWATER_CREATURE_FADE_OUT,\n\tWATER_CREATURE_REMOVE,\n\tWATER_CREATURE_DISABLED\n};\n\nclass CWaterCreature {\npublic:\n\tCObject *m_pObj;\n\tfloat m_fFwdSpeed;\n\tfloat m_fZTurnSpeed;\n\tint32 m_alpha;\n\tfloat m_fWaterDepth;\n\tint32 m_state;\n\n\tCWaterCreature();\n\tvoid Allocate(CObject *pObj, float fFwdSpeed, float fZTurnSpeed, float fWaterDepth, uint32 alpha, eFishSlotState state);\n\tvoid Free();\n\tvoid Initialise(CObject *pObj, float fFwdSpeed, float fZTurnSpeed, float fWaterDepth, uint32 alpha, eFishSlotState state);\n};\n\nclass CWaterCreatures {\n\npublic:\n\tstatic CWaterCreature aWaterCreatures[NUM_WATER_CREATURES];\n\tstatic int32 nNumActiveSeaLifeForms;\n\tstatic CObject *CreateSeaLifeForm(CVector const& pos, int16 modelID, int32 zRotAngle);\n\tstatic void CreateOne(CVector const& pos, int32 modelID);\n\tstatic void UpdateAll();\n\tstatic void FreeFishStructSlot(CWaterCreature *wc);\n\tstatic bool IsSpaceForMoreWaterCreatures();\n\tstatic float CalculateFishHeading(CVector const& pos1, CVector const& pos2);\n\tstatic void RemoveAll();\n\tstatic CWaterCreature* GetFishStructSlot();\n};\n\nstruct WaterCreatureProperties {\n\tint16 *modelID;\n\tfloat fFwdSpeed;\n\tfloat fLevel;\n\tfloat fUnknown; //unused\n\tfloat fWaterDepth;\n};"
  },
  {
    "path": "src/render/WaterLevel.cpp",
    "content": "#include \"common.h\"\n#include \"main.h\"\n#include \"FileMgr.h\"\n#include \"FileLoader.h\"\n#include \"TxdStore.h\"\n#include \"Timer.h\"\n#include \"Weather.h\"\n#include \"Camera.h\"\n#include \"Vehicle.h\"\n#include \"PlayerPed.h\"\n#include \"Boat.h\"\n#include \"World.h\"\n#include \"General.h\"\n#include \"Timecycle.h\"\n#include \"ZoneCull.h\"\n#include \"Clock.h\"\n#include \"Particle.h\"\n#include \"ParticleMgr.h\"\n#include \"RwHelper.h\"\n#include \"Streaming.h\"\n#include \"ColStore.h\"\n#include \"CdStream.h\"\n#include \"Pad.h\"\n#include \"RenderBuffer.h\"\n#include <rwcore.h>\n#include <rpworld.h>\n#include <rpmatfx.h>\n#include \"Occlusion.h\"\n#include \"Replay.h\"\n#include \"WaterLevel.h\"\n#include \"SurfaceTable.h\"\n#include \"WaterCreatures.h\"\n\n#define RwIm3DVertexSet_RGBA(vert, rgba) RwIm3DVertexSetRGBA(vert, rgba.red, rgba.green, rgba.blue, rgba.alpha) // (RwRGBAAssign(&(_dst)->color, &_src))\n\nfloat TEXTURE_ADDU;\nfloat TEXTURE_ADDV;\n\nfloat _TEXTURE_MASK_ADDU;\nfloat _TEXTURE_MASK_ADDV;\n\nfloat _TEXTURE_WAKE_ADDU;\nfloat _TEXTURE_WAKE_ADDV;\n\nint32 CWaterLevel::ms_nNoOfWaterLevels;\nfloat CWaterLevel::ms_aWaterZs[48];\nCRect CWaterLevel::ms_aWaterRects[48];\nint8 CWaterLevel::aWaterBlockList[MAX_LARGE_SECTORS][MAX_LARGE_SECTORS];\nint8 CWaterLevel::aWaterFineBlockList[MAX_SMALL_SECTORS][MAX_SMALL_SECTORS];\nbool CWaterLevel::WavesCalculatedThisFrame;\n\n\nbool CWaterLevel::RequireWavySector;\nbool CWaterLevel::MaskCalculatedThisFrame;\nCVector CWaterLevel::PreCalculatedMaskPosn;\nbool CWaterLevel::m_bRenderSeaBed;\nint32 CWaterLevel::m_nRenderWaterLayers;\n\nRpAtomic *CWaterLevel::ms_pWavyAtomic;\nRpAtomic *CWaterLevel::ms_pMaskAtomic;\n//\"Custom\" Don't Render Water Toggle\nbool gbDontRenderWater;\n\n\nRwTexture *gpWaterTex;\nRwTexture *gpWaterEnvTex;\nRwTexture *gpWaterEnvBaseTex;\nRwTexture *gpWaterWakeTex;\n\nRwRaster *gpWaterRaster;\nRwRaster *gpWaterEnvRaster;\nRwRaster *gpWaterEnvBaseRaster;\nRwRaster *gpWaterWakeRaster;\n\nbool _bSeaLife;\nfloat _fWaterZOffset = WATER_Z_OFFSET;\n\n#ifdef PC_WATER\nfloat fEnvScale               = 0.25f;\n#else\nfloat fEnvScale               = 0.5f;\n#endif\nfloat fWave2InvLength         = 0.03f;\nfloat fWave2NormScale         = 0.5f;\nfloat fWave2Ampl              = 0.1f;\nuint8 nWaterAlpha             = 192;\nuint8 nWakeAlpha              = 192;\nfloat fUnder1                 = 4.0;\nfloat fUnder2                 = 2.5;\nfloat fUnder3                 = 1.5;\nint nMaskAlpha                = 230;\nfloat fAdd1                   = 180.0f;\nfloat fAdd2                   = 80.0;\nfloat fRedMult                = 0.6f;\nfloat fGreenMult              = 1.0f;\nfloat fBlueMult               = 1.4f;\nfloat fAlphaMult              = 500.0f;\nfloat fAlphaBase              = 30.0f;\nfloat fRandomMoveDiv          = 8.0f;\nfloat fRandomDamp             = 0.99f;\nfloat fNormMult               = 2.0f;\nfloat fNormMultB              = 1.0f;\nfloat fBumpScale              = 1.5;\nfloat fBumpTexRepeat          = 2.0;\nfloat fNormalDirectionScalar1 = 2.0f;\nfloat fNormalDirectionScalar2 = 1.0f;\nbool bTestDoNormals           = true;\nfloat fSeaBedZ                =  25.0f;\nfloat aAlphaFade[5]           = { 0.4f, 1.0f, 0.2f, 1.0f, 0.4f};\t//CWaterLevel::RenderWakeSegment\nfloat fFlatWaterBlendRange    = 0.05f;\nfloat fStartBlendDistanceAdd  = 64.0f;\nfloat fMinWaterAlphaMult      = -30.0f;\n\n\nvoid\nCWaterLevel::Initialise(Const char *pWaterDat)\n{\n\tms_nNoOfWaterLevels = 0;\n\t\n#ifdef MASTER\n\tint32 hFile = -1;\n\n\tdo\n\t{\n\t\thFile = CFileMgr::OpenFile(\"DATA\\\\waterpro.dat\", \"rb\");\n\t}\n\twhile ( hFile < 0 );\n#else\n\tint32 hFile = CFileMgr::OpenFile(\"DATA\\\\waterpro.dat\", \"rb\");\n#endif\n\t\n\tif (hFile > 0)\n\t{\n\t\tCFileMgr::Read(hFile, (char *)&ms_nNoOfWaterLevels, sizeof(ms_nNoOfWaterLevels));\n\t\tCFileMgr::Read(hFile, (char *)ms_aWaterZs,\tsizeof(ms_aWaterZs));\n\t\tCFileMgr::Read(hFile, (char *)ms_aWaterRects, sizeof(ms_aWaterRects));\n\t\tCFileMgr::Read(hFile, (char *)aWaterBlockList, sizeof(aWaterBlockList));\n\t\tCFileMgr::Read(hFile, (char *)aWaterFineBlockList, sizeof(aWaterFineBlockList));\n\t\tCFileMgr::CloseFile(hFile);\n\t}\n#ifndef MASTER\n\telse\n\t{\n\t\tprintf(\"Init waterlevels\\n\");\n\n\t\t// collision is streamed in VC\n\t\tCColStore::LoadAllCollision();\n\n\t\tCFileMgr::SetDir(\"\");\n\t\thFile = CFileMgr::OpenFile(pWaterDat, \"r\");\n\n\t\tchar *line;\n\n\t\twhile ((line = CFileLoader::LoadLine(hFile)))\n\t\t{\n\t\t\tif (*line && *line != ';' && !strstr(line, \"* ;end of file\"))\n\t\t\t{\n\t\t\t\tfloat z, l, b, r, t;\n\t\t\t\tsscanf(line, \"%f %f %f %f %f\", &z, &l, &b, &r, &t);\n\t\t\t\tAddWaterLevel(l, b, r, t, z);\n\t\t\t}\n\t\t}\n\n\t\tCFileMgr::CloseFile(hFile);\n\n\t\tfor (int32 x = 0; x < MAX_SMALL_SECTORS; x++)\n\t\t{\n\t\t\tfor (int32 y = 0; y < MAX_SMALL_SECTORS; y++)\n\t\t\t{\n\t\t\t\taWaterFineBlockList[x][y] = NO_WATER;\n\t\t\t}\n\t\t}\n\n\t\t// rasterize water rects read from file\n\t\tfor (int32 i = 0; i < ms_nNoOfWaterLevels; i++)\n\t\t{\n\t\t\tint32 l = WATER_HUGE_X(ms_aWaterRects[i].left + WATER_X_OFFSET);\n\t\t\tint32 r = WATER_HUGE_X(ms_aWaterRects[i].right + WATER_X_OFFSET) + 1.0f;\n\t\t\tint32 t = WATER_HUGE_Y(ms_aWaterRects[i].top);\n\t\t\tint32 b = WATER_HUGE_Y(ms_aWaterRects[i].bottom) + 1.0f;\n\n\t\t\tl = clamp(l, 0, MAX_SMALL_SECTORS - 1);\n\t\t\tr = clamp(r, 0, MAX_SMALL_SECTORS - 1);\n\t\t\tt = clamp(t, 0, MAX_SMALL_SECTORS - 1);\n\t\t\tb = clamp(b, 0, MAX_SMALL_SECTORS - 1);\n\n\t\t\tfor (int32 x = l; x <= r; x++)\n\t\t\t{\n\t\t\t\tfor (int32 y = t; y <= b; y++)\n\t\t\t\t{\n\t\t\t\t\taWaterFineBlockList[x][y] = i;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// remove tiles that are obscured by land\n\t\tfor (int32 x = 0; x < MAX_SMALL_SECTORS; x++)\n\t\t{\n\t\t\tfloat worldX = WATER_START_X + x * SMALL_SECTOR_SIZE - WATER_X_OFFSET;\n\n\t\t\tfor (int32 y = 0; y < MAX_SMALL_SECTORS; y++)\n\t\t\t{\n\t\t\t\tif (CWaterLevel::aWaterFineBlockList[x][y] >= 0)\n\t\t\t\t{\n\t\t\t\t\tfloat worldY = WATER_START_Y + y * SMALL_SECTOR_SIZE;\n\n\t\t\t\t\tint32 i;\n\t\t\t\t\tfor (i = 0; i <= 8; i++)\n\t\t\t\t\t{\n\t\t\t\t\t\tfor (int32 j = 0; j <= 8; j++)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tCVector worldPos = CVector(worldX + i * (SMALL_SECTOR_SIZE / 8), worldY + j * (SMALL_SECTOR_SIZE / 8), ms_aWaterZs[aWaterFineBlockList[x][y]]);\n\n\t\t\t\t\t\t\tif ((worldPos.x > WORLD_MIN_X && worldPos.x < WORLD_MAX_X) && (worldPos.y > WORLD_MIN_Y && worldPos.y < WORLD_MAX_Y) &&\n\t\t\t\t\t\t\t\t(!WaterLevelAccordingToRectangles(worldPos.x, worldPos.y) || TestVisibilityForFineWaterBlocks(worldPos)))\n\t\t\t\t\t\t\t\tcontinue;\n\n\t\t\t\t\t\t\t// at least one point in the tile wasn't blocked, so don't remove water\n\t\t\t\t\t\t\ti = 1000;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (i < 1000)\n\t\t\t\t\t\taWaterFineBlockList[x][y] = NO_WATER;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tRemoveIsolatedWater();\n\n\t\t// calculate coarse tiles from fine tiles\n\t\tfor (int32 x = 0; x < MAX_LARGE_SECTORS; x++)\n\t\t{\n\t\t\tfor (int32 y = 0; y < MAX_LARGE_SECTORS; y++)\n\t\t\t{\n\t\t\t\tif (aWaterFineBlockList[x * 2][y * 2] >= 0)\n\t\t\t\t{\n\t\t\t\t\taWaterBlockList[x][y] = aWaterFineBlockList[x * 2][y * 2];\n\t\t\t\t}\n\t\t\t\telse if (aWaterFineBlockList[x * 2 + 1][y * 2] >= 0)\n\t\t\t\t{\n\t\t\t\t\taWaterBlockList[x][y] = aWaterFineBlockList[x * 2 + 1][y * 2];\n\t\t\t\t}\n\t\t\t\telse if (aWaterFineBlockList[x * 2][y * 2 + 1] >= 0)\n\t\t\t\t{\n\t\t\t\t\taWaterBlockList[x][y] = aWaterFineBlockList[x * 2][y * 2 + 1];\n\t\t\t\t}\n\t\t\t\telse if (aWaterFineBlockList[x * 2 + 1][y * 2 + 1] >= 0)\n\t\t\t\t{\n\t\t\t\t\taWaterBlockList[x][y] = aWaterFineBlockList[x * 2 + 1][y * 2 + 1];\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\taWaterBlockList[x][y] = NO_WATER;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\thFile = CFileMgr::OpenFileForWriting(\"data\\\\waterpro.dat\");\n\n\t\tif (hFile > 0)\n\t\t{\n\t\t\tCFileMgr::Write(hFile, (char *)&ms_nNoOfWaterLevels, sizeof(ms_nNoOfWaterLevels));\n\t\t\tCFileMgr::Write(hFile, (char *)ms_aWaterZs, sizeof(ms_aWaterZs));\n\t\t\tCFileMgr::Write(hFile, (char *)ms_aWaterRects, sizeof(ms_aWaterRects));\n\t\t\tCFileMgr::Write(hFile, (char *)aWaterBlockList, sizeof(aWaterBlockList));\n\t\t\tCFileMgr::Write(hFile, (char *)aWaterFineBlockList, sizeof(aWaterFineBlockList));\n\n\t\t\tCFileMgr::CloseFile(hFile);\n\t\t}\n\n\t\t// collision is streamed in VC\n\t\tCColStore::RemoveAllCollision();\n\t}\n#endif\n\t\n\tCTxdStore::PushCurrentTxd();\n\n\tint32 slot = CTxdStore::FindTxdSlot(\"particle\");\n\tCTxdStore::SetCurrentTxd(slot);\n\t\n\tif ( gpWaterTex == nil )\n\t\tgpWaterTex = RwTextureRead(\"waterclear256\", nil);\n\tgpWaterRaster = RwTextureGetRaster(gpWaterTex);\n\t\n\tif ( gpWaterEnvTex == nil )\n\t\tgpWaterEnvTex = RwTextureRead(\"waterreflection2\", nil);\n\tgpWaterEnvRaster = RwTextureGetRaster(gpWaterEnvTex);\n\t\n#ifdef PC_WATER\n\tif ( gpWaterEnvBaseTex == nil )\n\t\tgpWaterEnvBaseTex = RwTextureRead(\"sandywater\", nil);\n\tgpWaterEnvBaseRaster = RwTextureGetRaster(gpWaterEnvBaseTex);\n#endif\n\t\n\tif ( gpWaterWakeTex == nil )\n\t\tgpWaterWakeTex = RwTextureRead(\"waterwake\", nil);\n\tgpWaterWakeRaster = RwTextureGetRaster(gpWaterWakeTex);\n\t\n\tCTxdStore::PopCurrentTxd();\n\n\tCreateWavyAtomic();\n\t\n\tprintf(\"Done Initing waterlevels\\n\");\n}\n\nvoid\nCWaterLevel::Shutdown()\n{\n\tDestroyWavyAtomic();\n\n#define _DELETE_TEXTURE(t) if ( t )\t\\\n\t\t{ \\\n\t\t\tRwTextureDestroy(t); \\\n\t\t\tt = nil; \\\n\t\t}\n\n\t_DELETE_TEXTURE(gpWaterTex);\n\t_DELETE_TEXTURE(gpWaterEnvTex);\n\t_DELETE_TEXTURE(gpWaterWakeTex);\n\t_DELETE_TEXTURE(gpWaterEnvBaseTex);\n\n#undef _DELETE_TEXTURE\n}\n\nvoid\nCWaterLevel::CreateWavyAtomic()\n{\n\tRpGeometry *wavyGeometry;\n\tRpGeometry *maskGeometry;\n\tRpMaterial *wavyMaterial;\n\tRpMaterial *maskMaterial;\n\t\n\tRpTriangle *wavytlist;\n\tRpTriangle *masktlist;\n\t\n\tRpMorphTarget *wavyMorphTarget;\n\tRpMorphTarget *maskMorphTarget;\n\t\n\tRwSphere boundingSphere;\n\t\n\tRwV3d *wavyVert;\n\tRwV3d *wavyNormal;\n\t\n\tRwV3d *maskVert;\n\tRwV3d *maskNormal;\n\t\n\tRwFrame *wavyFrame;\n\tRwFrame *maskFrame;\n\t\n\t{\n\t\twavyGeometry = RpGeometryCreate(17*17, 512, rpGEOMETRYTRISTRIP\n\t\t\t\t\t\t\t\t\t\t\t\t\t|rpGEOMETRYTEXTURED\n\t\t\t\t\t\t\t\t\t\t\t\t\t|rpGEOMETRYPRELIT\n\t\t\t\t\t\t\t\t\t\t\t\t\t|rpGEOMETRYNORMALS\n\t\t\t\t\t\t\t\t\t\t\t\t\t|rpGEOMETRYMODULATEMATERIALCOLOR);\n#ifdef PC_WATER\n\t\tRpGeometryAddMorphTarget(wavyGeometry);\n#endif\n\t}\n\n\t{\n\t\tmaskGeometry = RpGeometryCreate(33*33, 2048, rpGEOMETRYTRISTRIP\n\t\t\t\t\t\t\t\t\t\t\t\t\t|rpGEOMETRYTEXTURED\n\t\t\t\t\t\t\t\t\t\t\t\t\t|rpGEOMETRYPRELIT\n\t\t\t\t\t\t\t\t\t\t\t\t\t|rpGEOMETRYNORMALS\n\t\t\t\t\t\t\t\t\t\t\t\t\t|rpGEOMETRYMODULATEMATERIALCOLOR);\n#ifdef PC_WATER\n\t\tRpGeometryAddMorphTarget(maskGeometry);\n#endif\n\t}\n\t\n\t{\n\t\twavyMaterial = RpMaterialCreate();\n\t\tRpMaterialSetTexture(wavyMaterial, gpWaterTex);\n\t\tRwRGBA watercolor = { 255, 255, 255, 192 };\n\t\tRpMaterialSetColor(wavyMaterial, &watercolor);\n\t}\n\t\n\t{\n\t\tmaskMaterial = RpMaterialCreate();\n#ifdef PC_WATER\n\t\tRpMaterialSetTexture(maskMaterial, gpWaterEnvBaseTex);\n#else\n\t\tRpMaterialSetTexture(maskMaterial, gpWaterTex);\n#endif\n\t\tRwRGBA watercolor = { 255, 255, 255, 192 };\n\t\tRpMaterialSetColor(maskMaterial, &watercolor);\n\t}\n\t\n\t{\n\t\twavytlist = RpGeometryGetTriangles(wavyGeometry);\n\t\t\n\t\tfor ( int32 i = 0; i < 16; i++ )\n\t\t{\n\t\t\tfor ( int32 j = 0; j < 16; j++ )\n\t\t\t{\n\t\t\t\tconst RwUInt16 base = (RwUInt16)((16 + 1)*i+j);\n\t\n\t\t\t\tRpGeometryTriangleSetVertexIndices(wavyGeometry, \n\t\t\t\t\t\twavytlist,     (RwInt16)base, (RwInt16)(base+1),    (RwInt16)(base+16+2));\n\n\t\t\t\tRpGeometryTriangleSetVertexIndices(wavyGeometry, \n\t\t\t\t\t\t(wavytlist+1), (RwInt16)base, (RwInt16)(base+16+2), (RwInt16)(base+16+1));\n\t\n\t\t\t\tRpGeometryTriangleSetMaterial(wavyGeometry, wavytlist,     wavyMaterial);\n\n\t\t\t\tRpGeometryTriangleSetMaterial(wavyGeometry, (wavytlist+1), wavyMaterial);\n\t\t\t\t\n\t\t\t\twavytlist+=2;\n\t\t\t}\n\t\t}\n\t}\n\t\n\t{\n\t\tmasktlist = RpGeometryGetTriangles(maskGeometry);\n\t\t\n\t\tfor ( int32 i = 0; i < 32; i++ )\n\t\t{\n\t\t\tfor ( int32 j = 0; j < 32; j++ )\n\t\t\t{\n\t\t\t\tconst RwUInt16 base = (RwUInt16)((32 + 1)*i+j);\n\t\n\t\t\t\tRpGeometryTriangleSetVertexIndices(maskGeometry, \n\t\t\t\t\t\tmasktlist,     (RwInt16)base, (RwInt16)(base+1),    (RwInt16)(base+32+2));\n\n\t\t\t\tRpGeometryTriangleSetVertexIndices(maskGeometry,\n\t\t\t\t\t\t(masktlist+1), (RwInt16)base, (RwInt16)(base+32+2), (RwInt16)(base+32+1));\n\t\n\t\t\t\tRpGeometryTriangleSetMaterial(maskGeometry, masktlist,     maskMaterial);\n\n\t\t\t\tRpGeometryTriangleSetMaterial(maskGeometry, (masktlist+1), maskMaterial);\n\t\t\t\t\n\t\t\t\tmasktlist+=2;\n\t\t\t}\n\t\t}\n\t}\n\n\t{\n\t\twavyMorphTarget = RpGeometryGetMorphTarget(wavyGeometry, 0);\n\t\twavyVert = RpMorphTargetGetVertices(wavyMorphTarget);\n\t\twavyNormal = RpMorphTargetGetVertexNormals(wavyMorphTarget);\n\t\t\n\t\tfor ( int32 i = 0; i < 17; i++ )\n\t\t{\n\t\t\tfor ( int32 j = 0; j < 17; j++ )\n\t\t\t{\n\t\t\t\t(*wavyVert).x = (float)i * 2.0f;\n\t\t\t\t(*wavyVert).y = (float)j * 2.0f;\n\t\t\t\t(*wavyVert).z = 0.0f;\n\t\t\t\t\n\t\t\t\t(*wavyNormal).x = 0.0f;\n\t\t\t\t(*wavyNormal).y = 0.0f;\n\t\t\t\t(*wavyNormal).z = 1.0f;\n\t\t\t\t\n\t\t\t\twavyVert++;\n\t\t\t\twavyNormal++;\n\t\t\t}\n\t\t}\n\t\t\n\t\tRpMorphTargetCalcBoundingSphere(wavyMorphTarget, &boundingSphere);\n\t\tRpMorphTargetSetBoundingSphere(wavyMorphTarget, &boundingSphere);\n\t\tRpGeometryUnlock(wavyGeometry);\n\t}\n\t\n\t{\n\t\tmaskMorphTarget = RpGeometryGetMorphTarget(maskGeometry, 0);\n\t\tmaskVert = RpMorphTargetGetVertices(maskMorphTarget);\n\t\tmaskNormal = RpMorphTargetGetVertexNormals(maskMorphTarget);\n\t\t\n\t\tfor ( int32 i = 0; i < 33; i++ )\n\t\t{\n\t\t\tfor ( int32 j = 0; j < 33; j++ )\n\t\t\t{\n\t\t\t\t(*maskVert).x = (float)i * 2.0f;\n\t\t\t\t(*maskVert).y = (float)j * 2.0f;\n\t\t\t\t(*maskVert).z = 0.0f;\n\t\t\t\t\n\t\t\t\t(*maskNormal).x = 0.0f;\n\t\t\t\t(*maskNormal).y = 0.0f;\n\t\t\t\t(*maskNormal).z = 1.0f;\n\t\t\t\t\n\t\t\t\tmaskVert++;\n\t\t\t\tmaskNormal++;\n\t\t\t}\n\t\t}\n\t\t\n\t\tRpMorphTargetCalcBoundingSphere(maskMorphTarget, &boundingSphere);\n\t\tRpMorphTargetSetBoundingSphere(maskMorphTarget, &boundingSphere);\n\t\tRpGeometryUnlock(maskGeometry);\n\t}\n\t\n\t{\n\t\twavyFrame = RwFrameCreate();\n\t\tms_pWavyAtomic = RpAtomicCreate();\n\t\tRpAtomicSetGeometry(ms_pWavyAtomic, wavyGeometry, 0);\n\t\tRpAtomicSetFrame(ms_pWavyAtomic, wavyFrame);\n\t\tRpMaterialDestroy(wavyMaterial);\n\t\tRpGeometryDestroy(wavyGeometry);\n\t}\n\t\n\t{\n\t\tmaskFrame = RwFrameCreate();\n\t\tms_pMaskAtomic = RpAtomicCreate();\n\t\tRpAtomicSetGeometry(ms_pMaskAtomic, maskGeometry, 0);\n\t\tRpAtomicSetFrame(ms_pMaskAtomic, maskFrame);\n\t\tRpMaterialDestroy(maskMaterial);\n\t\tRpGeometryDestroy(maskGeometry);\n\t}\n\t\n\tstatic RwFrame *wakeEnvFrame;\n\t\n\tif ( wakeEnvFrame == nil )\n\t{\n\t\twakeEnvFrame = RwFrameCreate();\n\t\tRwMatrixSetIdentity(RwFrameGetMatrix(wakeEnvFrame));\n\t\tRwFrameUpdateObjects(wakeEnvFrame);\n\t}\n\t\n\tRpMatFXMaterialSetEffects(maskMaterial, rpMATFXEFFECTENVMAP);\n\tRpMatFXMaterialSetupEnvMap(maskMaterial, gpWaterEnvTex, wakeEnvFrame, TRUE, fEnvScale);\n\tRpMatFXAtomicEnableEffects(ms_pMaskAtomic);\n}\n\nvoid\nCWaterLevel::DestroyWavyAtomic()\n{\n#define _DELETE_ATOMIC(a) \\\n\t\t{ \\\n\t\t\tRwFrame *frame; \\\n\t\t\tframe = RpAtomicGetFrame(a); \\\n\t\t\tRpAtomicDestroy(a); \\\n\t\t\tRwFrameDestroy(frame); \\\n\t\t}\n\n\t_DELETE_ATOMIC(ms_pWavyAtomic);\n\t_DELETE_ATOMIC(ms_pMaskAtomic);\n\t\n#undef _DELETE_ATOMIC\n}\n\n#ifndef MASTER\nvoid\nCWaterLevel::AddWaterLevel(float fXLeft, float fYBottom, float fXRight, float fYTop, float fLevel)\n{\n\tms_aWaterRects[ms_nNoOfWaterLevels] = CRect(fXLeft, fYBottom, fXRight, fYTop);\n\tms_aWaterZs[ms_nNoOfWaterLevels] = fLevel;\n\tms_nNoOfWaterLevels++;\n}\n\nbool\nCWaterLevel::WaterLevelAccordingToRectangles(float fX, float fY, float *pfOutLevel)\n{\n\tif (ms_nNoOfWaterLevels <= 0) return false;\n\n\tfor (int32 i = 0; i < ms_nNoOfWaterLevels; i++)\n\t{\n\t\tif (fX >= ms_aWaterRects[i].left && fX <= ms_aWaterRects[i].right\n\t\t\t&& fY >= ms_aWaterRects[i].top && fY <= ms_aWaterRects[i].bottom)\n\t\t{\n\t\t\tif (pfOutLevel) *pfOutLevel = ms_aWaterZs[i];\n\n\t\t\treturn true;\n\t\t}\n\t}\n\n\treturn false;\n}\n\nbool\nCWaterLevel::TestVisibilityForFineWaterBlocks(const CVector &worldPos)\n{\n\tstatic CVector2D tab[] =\n\t{\n\t\t{ 50.0f, 50.0f },\n\t\t{ -50.0f, 50.0f },\n\t\t{ -50.0f, -50.0f },\n\t\t{ 50.0f, -50.0f },\n\t\t{ 50.0f, 0.0f },\n\t\t{ -50.0f, 0.0f },\n\t\t{ 0.0f, -50.0f },\n\t\t{ 0.0f, 50.0f },\n\t};\n\n\tCEntity *entity;\n\tCColPoint col;\n\tCVector lineStart, lineEnd;\n\n\tlineStart = worldPos;\n\n\tif (!CWorld::ProcessVerticalLine(lineStart, lineStart.z + 100.0f, col, entity, true, false, false, false, true, false, nil))\n\t{\n\t\tlineStart.x += 0.4f;\n\t\tlineStart.y += 0.4f;\n\n\t\tif (!CWorld::ProcessVerticalLine(lineStart, lineStart.z + 100.0f, col, entity, true, false, false, false, true, false, nil))\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tfor (int32 i = 0; i < ARRAY_SIZE(tab); i++)\n\t{\n\t\tlineStart = worldPos;\n\t\tlineEnd = worldPos;\n\n\t\tlineEnd.x += tab[i].x;\n\t\tlineEnd.y += tab[i].y;\n\t\tlineEnd.z += 100.0f;\n\n\t\tif ((lineEnd.x > WORLD_MIN_X && lineEnd.x < WORLD_MAX_X) && (lineEnd.y > WORLD_MIN_Y && lineEnd.y < WORLD_MAX_Y))\n\t\t{\n\t\t\tif (!CWorld::ProcessLineOfSight(lineStart, lineEnd, col, entity, true, false, false, false, true, false))\n\t\t\t{\n\t\t\t\tlineStart.x += 0.4f;\n\t\t\t\tlineStart.y += 0.4f;\n\t\t\t\tlineEnd.x += 0.4f;\n\t\t\t\tlineEnd.y += 0.4f;\n\n\t\t\t\tif (!CWorld::ProcessLineOfSight(lineStart, lineEnd, col, entity, true, false, false, false, true, false))\n\t\t\t\t{\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn true;\n}\n\nvoid\nCWaterLevel::RemoveIsolatedWater()\n{\n\tbool (*isConnected)[MAX_SMALL_SECTORS] = new bool[MAX_SMALL_SECTORS][MAX_SMALL_SECTORS];\n\n\tfor (int32 x = 0; x < MAX_SMALL_SECTORS; x++)\n\t{\n\t\tfor (int32 y = 0; y < MAX_SMALL_SECTORS; y++)\n\t\t{\n\t\t\tisConnected[x][y] = false;\n\t\t}\n\t}\n\n\tisConnected[0][0] = true;\n\tbool keepGoing;\n\n\tdo\n\t{\n\t\tkeepGoing = false;\n\n\t\tfor (int32 x = 0; x < MAX_SMALL_SECTORS; x++)\n\t\t{\n\t\t\tfor (int32 y = 0; y < MAX_SMALL_SECTORS; y++)\n\t\t\t{\n\t\t\t\tif (aWaterFineBlockList[x][y] < 0 || isConnected[x][y])\n\t\t\t\t\tcontinue;\n\n\t\t\t\tif (x > 0 && isConnected[x - 1][y])\n\t\t\t\t{\n\t\t\t\t\tisConnected[x][y] = true;\n\t\t\t\t\tkeepGoing = true;\n\t\t\t\t}\n\n\t\t\t\tif (y > 0 && isConnected[x][y - 1])\n\t\t\t\t{\n\t\t\t\t\tisConnected[x][y] = true;\n\t\t\t\t\tkeepGoing = true;\n\t\t\t\t}\n\n\t\t\t\tif (x + 1 < MAX_SMALL_SECTORS && isConnected[x + 1][y])\n\t\t\t\t{\n\t\t\t\t\tisConnected[x][y] = true;\n\t\t\t\t\tkeepGoing = true;\n\t\t\t\t}\n\n\t\t\t\tif (y + 1 < MAX_SMALL_SECTORS && isConnected[x][y + 1])\n\t\t\t\t{\n\t\t\t\t\tisConnected[x][y] = true;\n\t\t\t\t\tkeepGoing = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\twhile (keepGoing);\n\n\tint32 numRemoved = 0;\n\n\tfor (int32 x = 0; x < MAX_SMALL_SECTORS; x++)\n\t{\n\t\tfor (int32 y = 0; y < MAX_SMALL_SECTORS; y++)\n\t\t{\n\t\t\tif (aWaterFineBlockList[x][y] >= 0 && !isConnected[x][y] && ms_aWaterZs[aWaterFineBlockList[x][y]] == 6.0f)\n\t\t\t{\n\t\t\t\tnumRemoved++;\n\t\t\t\taWaterFineBlockList[x][y] = NO_WATER;\n\t\t\t}\n\t\t}\n\t}\n\n\tprintf(\"Removed %d isolated patches of water\\n\", numRemoved);\n\n\tdelete[] isConnected;\n}\n#endif\n\nbool\nCWaterLevel::GetWaterLevel(float fX, float fY, float fZ, float *pfOutLevel, bool bDontCheckZ)\n{\n\tint32 x = WATER_TO_SMALL_SECTOR_X(fX + WATER_X_OFFSET);\n\tint32 y = WATER_TO_SMALL_SECTOR_Y(fY);\n\t\t\n#ifdef FIX_BUGS\n\tif ( x < 0 || x >= MAX_SMALL_SECTORS ) return false;\n\tif ( y < 0 || y >= MAX_SMALL_SECTORS ) return false;\n#endif\n\n\tint8 nBlock = aWaterFineBlockList[x][y];\n\n\tif ( nBlock == NO_WATER )\n\t\treturn false;\n\n\tASSERT( pfOutLevel != nil );\n\t*pfOutLevel = ms_aWaterZs[nBlock];\n\n\tfloat fAngle = (CTimer::GetTimeInMilliseconds() & 4095) * (TWOPI / 4096.0f);\n\t\n\tfloat fWave = Sin\n\t(\n\t\t( WATER_UNSIGN_Y(fY)                  - y*SMALL_SECTOR_SIZE\n\t\t+ WATER_UNSIGN_X(fX + WATER_X_OFFSET) - x*SMALL_SECTOR_SIZE )\n\t\t\n\t\t* (TWOPI / SMALL_SECTOR_SIZE ) + fAngle\n\t);\n\n\tfloat fWindFactor = CWeather::WindClipped * 0.4f + 0.2f;\n\t\n\t*pfOutLevel += fWave * fWindFactor;\n\n\tif ( bDontCheckZ == false && (*pfOutLevel - fZ) > 3.0f )\n\t{\n\t\t*pfOutLevel = 0.0f;\n\t\treturn false;\n\t}\n\n\treturn true;\n}\n\nbool\nCWaterLevel::GetWaterLevelNoWaves(float fX, float fY, float fZ, float *pfOutLevel)\n{\n\tint32 x = WATER_TO_SMALL_SECTOR_X(fX + WATER_X_OFFSET);\n\tint32 y = WATER_TO_SMALL_SECTOR_Y(fY);\n\t\t\n#ifdef FIX_BUGS\n\tif ( x < 0 || x >= MAX_SMALL_SECTORS ) return false;\n\tif ( y < 0 || y >= MAX_SMALL_SECTORS ) return false;\n#endif\n\t\n\tint8 nBlock = aWaterFineBlockList[x][y];\n\t\t\n\tif ( nBlock == NO_WATER )\n\t\treturn false;\n\t\n\tASSERT( pfOutLevel != nil );\n\t*pfOutLevel = ms_aWaterZs[nBlock];\n\n\treturn true;\n}\n\nfloat\nCWaterLevel::GetWaterWavesOnly(short x, short y)\n{\n\tfloat fAngle = (CTimer::GetTimeInMilliseconds() & 4095) * (TWOPI / 4096.0f);\n\t\n\tfloat fWindFactor = CWeather::WindClipped * 0.7f + 0.3f;\n\t\n\tfloat fWave = Sin( float(float(4 * y + 4 * x) * (TWOPI / SMALL_SECTOR_SIZE )) + fAngle );\n\t\n\treturn fWave * fWindFactor;\n}\n\t   \nCVector\nCWaterLevel::GetWaterNormal(float fX, float fY)\n{\n\t//TODO: BUG ? no x offset\n\t\n\tint32 x = WATER_TO_SMALL_SECTOR_X(fX);\n\tint32 y = WATER_TO_SMALL_SECTOR_Y(fY);\n\t\n\tfloat fAngle = (CTimer::GetTimeInMilliseconds() & 4095) * (TWOPI / 4096.0f);\n\tfloat fWindFactor = CWeather::WindClipped * 0.4f + 0.2f;\n\t\n\tfloat _fWave = (WATER_UNSIGN_Y(fY) - y*SMALL_SECTOR_SIZE + WATER_UNSIGN_X(fX) - x*SMALL_SECTOR_SIZE)\n\t\t\t* (TWOPI / SMALL_SECTOR_SIZE ) + fAngle;\n\n\tCVector vA(1.0f, 0.0f, fWindFactor * (TWOPI / SMALL_SECTOR_SIZE ) * Cos(_fWave));\n\tCVector vB(0.0f, 1.0f, fWindFactor * (TWOPI / SMALL_SECTOR_SIZE ) * Cos(_fWave));\n\t\n\tCVector norm = CrossProduct(vA, vB);\n\t\n\tnorm.Normalise();\n\t\n\treturn norm;\n}\n\n\ninline float\n_GetWaterDrawDist()\n{\n\tif     ( TheCamera.GetPosition().z < 15.0f  ) return 1200.0f;\n\tif     ( TheCamera.GetPosition().z > 60.0f  ) return 2000.0f;\n\treturn ( TheCamera.GetPosition().z + -15.0f ) * 800.0f / 45.0f + 1200.0f;\n}\n\ninline float\n_GetWavyDrawDist()\n{\n\tif ( FindPlayerVehicle() && FindPlayerVehicle()->IsBoat() )\n\t\treturn 120.0f;\n\telse\n\t\treturn 70.0f;\n}\n\ninline void\n_GetCamBounds(bool *bUseCamStartY, bool *bUseCamEndY, bool *bUseCamStartX, bool *bUseCamEndX)\n{\n\tif ( TheCamera.GetForward().z > -0.8f )\n\t{\n\t\tif ( Abs(TheCamera.GetForward().x) > Abs(TheCamera.GetForward().y) )\n\t\t{\n\t\t\tif ( TheCamera.GetForward().x > 0.0f )\n\t\t\t\t*bUseCamStartX = true;\n\t\t\telse\n\t\t\t\t*bUseCamEndX = true;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif ( TheCamera.GetForward().y > 0.0f )\n\t\t\t\t*bUseCamStartY = true;\n\t\t\telse\n\t\t\t\t*bUseCamEndY = true;\n\t\t}\n\t}\n}\n\n\ninline bool \n_IsColideWithBlock(int32 x, int32 y, int32 &block)\n{\n\tblock = CWaterLevel::aWaterFineBlockList[x + 0][y + 0];\n\tif (block >= 0)\n\t\treturn true;\n\n\tblock = CWaterLevel::aWaterFineBlockList[x + 0][y + 1];\n\tif (block >= 0)\n\t{\n\t\tblock = CWaterLevel::aWaterFineBlockList[x + 0][y + 2];\n\t\tif (block >= 0)\n\t\t\treturn true;\n\t}\n\n\tblock = CWaterLevel::aWaterFineBlockList[x + 1][y + 0];\n\tif (block >= 0)\n\t\treturn true;\n\n\tblock = CWaterLevel::aWaterFineBlockList[x + 1][y + 1];\n\tif (block >= 0)\n\t{\n\t\tblock = CWaterLevel::aWaterFineBlockList[x + 1][y + 2];\n\t\tif (block >= 0)\n\t\t\treturn true;\n\t}\n\n\tblock = CWaterLevel::aWaterFineBlockList[x + 2][y + 0];\n\tif (block >= 0)\n\t\treturn true;\n\n\tblock = CWaterLevel::aWaterFineBlockList[x + 2][y + 1];\n\tif (block >= 0)\n\t{\n\t\tblock = CWaterLevel::aWaterFineBlockList[x + 2][y + 2];\n\t\tif (block >= 0)\n\t\t\treturn true;\n\t}\n\n\treturn false;\n}\n\ninline float\nSectorRadius(float fSize)\n{\n\treturn Sqrt(Pow(fSize, 2) + Pow(fSize, 2));\n}\n\nvoid\nCWaterLevel::RenderWater()\n{\n//\"Custom\" Don't Render Water Toggle\n#ifndef MASTER\n\tif (gbDontRenderWater)\n\t\treturn;\n#endif\n\tbool bUseCamEndX   = false;\n\tbool bUseCamStartY = false;\n\t\n\tbool bUseCamStartX = false;\n\tbool bUseCamEndY   = false;\n\t\n\tif ( !CGame::CanSeeWaterFromCurrArea() )\n\t\treturn;\n\t\n\t_GetCamBounds(&bUseCamStartY, &bUseCamEndY, &bUseCamStartX, &bUseCamEndX);\n\n\tfloat fHugeSectorMaxRenderDist    = _GetWaterDrawDist();\n\tfloat fHugeSectorMaxRenderDistSqr = SQR(fHugeSectorMaxRenderDist);\n\t\n\tfloat windAddUV = CWeather::WindClipped * 0.0005f + 0.0006f;\n\t\n\tfloat fAngle = (CTimer::GetTimeInMilliseconds() & 4095) * (TWOPI / 4096.0f);\n\t\n\tif ( !CTimer::GetIsPaused() )\n\t{\n\t\tTEXTURE_ADDU       += windAddUV;\n\t\tTEXTURE_ADDV       += windAddUV;\n\t\t\n\t\t_TEXTURE_MASK_ADDU += Sin(fAngle) \t\t * 0.0005f + 1.1f * windAddUV;\n\t\t_TEXTURE_MASK_ADDV -= Cos(fAngle * 1.3f) * 0.0005f + 1.2f * windAddUV;\n\t\t\n\t\t_TEXTURE_WAKE_ADDU -= Sin(fAngle) \t\t * 0.0003f + windAddUV;\n\t\t_TEXTURE_WAKE_ADDV += Cos(fAngle * 0.7f) * 0.0003f + windAddUV;\n\t}\n\t\n\tif ( _TEXTURE_MASK_ADDU >= 1.0f )\n\t\t_TEXTURE_MASK_ADDU = 0.0f;\n\tif ( _TEXTURE_MASK_ADDV >= 1.0f )\n\t\t_TEXTURE_MASK_ADDV = 0.0f;\n\t\n\tif ( _TEXTURE_WAKE_ADDU >= 1.0f )\n\t\t_TEXTURE_WAKE_ADDU = 0.0f;\n\tif ( _TEXTURE_WAKE_ADDV >= 1.0f )\n\t\t_TEXTURE_WAKE_ADDV = 0.0f;\n\t\n\tif ( TEXTURE_ADDU >= 1.0f )\n\t\tTEXTURE_ADDU = 0.0f;\n\tif ( TEXTURE_ADDV >= 1.0f )\n\t\tTEXTURE_ADDV = 0.0f;\n\t\n#ifdef PC_WATER\n\t_fWaterZOffset = CWeather::WindClipped * 0.5f + 0.25f;\n#endif\n\n\tRwRGBA color = { 0, 0, 0, 255 };\n\n\tcolor.red   = CTimeCycle::GetWaterRed();\n\tcolor.green = CTimeCycle::GetWaterGreen();\n\tcolor.blue  = CTimeCycle::GetWaterBlue();\n\n#ifndef PC_WATER\n\tRwRGBA colorUnderwater = { 0, 0, 0, 255 };\n\tcolorUnderwater.red = (uint32)(0.8f * (float)colorUnderwater.red);\n\tcolorUnderwater.green = (uint32)(0.8f * (float)colorUnderwater.green);\n\tcolorUnderwater.blue = (uint32)(0.8f * (float)colorUnderwater.blue);\n#endif\n\n\tTempBufferVerticesStored = 0;\n\tTempBufferIndicesStored = 0;\n\n#ifndef PC_WATER\n\tWavesCalculatedThisFrame = false;\n#endif\n\t\n\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void *)gpWaterRaster);\n\tRwRenderStateSet(rwRENDERSTATEFOGENABLE,     (void *)TRUE);\n\tRwRenderStateSet(rwRENDERSTATESRCBLEND,      (void *)rwBLENDONE);\n\tRwRenderStateSet(rwRENDERSTATEDESTBLEND,     (void *)rwBLENDZERO);\n\t\n\tCVector2D camPos(TheCamera.GetPosition().x, TheCamera.GetPosition().y);\n\n\tint32 nStartX = WATER_TO_HUGE_SECTOR_X(camPos.x - fHugeSectorMaxRenderDist + WATER_X_OFFSET);\n\tint32 nEndX   = WATER_TO_HUGE_SECTOR_X(camPos.x + fHugeSectorMaxRenderDist + WATER_X_OFFSET) + 1;\n\tint32 nStartY = WATER_TO_HUGE_SECTOR_Y(camPos.y - fHugeSectorMaxRenderDist);\n\tint32 nEndY   = WATER_TO_HUGE_SECTOR_Y(camPos.y + fHugeSectorMaxRenderDist) + 1;\n\t\n\tif ( bUseCamStartX )\n\t\tnStartX = WATER_TO_HUGE_SECTOR_X(camPos.x + WATER_X_OFFSET);\n\tif ( bUseCamEndX )\n\t\tnEndX   = WATER_TO_HUGE_SECTOR_X(camPos.x + WATER_X_OFFSET);\n\tif ( bUseCamStartY )\n\t\tnStartY = WATER_TO_HUGE_SECTOR_Y(camPos.y);\n\tif ( bUseCamEndY )                             \n\t\tnEndY   = WATER_TO_HUGE_SECTOR_Y(camPos.y);\n\n\tnStartX = clamp(nStartX, 0, MAX_HUGE_SECTORS - 1);\n\tnEndX   = clamp(nEndX,   0, MAX_HUGE_SECTORS - 1);\n\tnStartY = clamp(nStartY, 0, MAX_HUGE_SECTORS - 1);\n\tnEndY   = clamp(nEndY,   0, MAX_HUGE_SECTORS - 1);\n\t\n\tfor ( int32 x = nStartX; x <= nEndX; x++ )\n\t{\n\t\tfor ( int32 y = nStartY; y <= nEndY; y++ )\n\t\t{\n\t\t\tif (   aWaterBlockList[2*x+0][2*y+0] >= 0\n\t\t\t\t|| aWaterBlockList[2*x+1][2*y+0] >= 0\n\t\t\t\t|| aWaterBlockList[2*x+0][2*y+1] >= 0\n\t\t\t\t|| aWaterBlockList[2*x+1][2*y+1] >= 0 )\n\t\t\t{\n\t\t\t\tfloat fX = WATER_FROM_HUGE_SECTOR_X(x) - WATER_X_OFFSET;\n\t\t\t\tfloat fY = WATER_FROM_HUGE_SECTOR_Y(y);\n\n\t\t\t\tCVector2D vecHugeSectorCentre(fX + HUGE_SECTOR_SIZE/2,fY + HUGE_SECTOR_SIZE/2);\n\n\t\t\t\tfloat fHugeSectorDistToCamSqr = (camPos - vecHugeSectorCentre).MagnitudeSqr();\n\t\t\t\t\n\t\t\t\tif ( fHugeSectorMaxRenderDistSqr > fHugeSectorDistToCamSqr )\n\t\t\t\t{\n\t\t\t\t\tif ( TheCamera.IsSphereVisible(CVector(vecHugeSectorCentre.x, vecHugeSectorCentre.y, 0.0f), SectorRadius(HUGE_SECTOR_SIZE), &TheCamera.GetCameraMatrix()) )\n\t\t\t\t\t{\n#ifndef PC_WATER\n\t\t\t\t\t\tWavesCalculatedThisFrame = true;\n#endif\n\n\n\t\t\t\t\t\tfloat fZ;\n\n\t\t\t\t\t\tif ( aWaterBlockList[2*x+0][2*y+0] >= 0 )\n\t\t\t\t\t\t\tfZ = ms_aWaterZs[ aWaterBlockList[2*x+0][2*y+0] ];\n\n\t\t\t\t\t\tif ( aWaterBlockList[2*x+1][2*y+0] >= 0 )\n\t\t\t\t\t\t\tfZ = ms_aWaterZs[ aWaterBlockList[2*x+1][2*y+0] ];\n\n\t\t\t\t\t\tif ( aWaterBlockList[2*x+0][2*y+1] >= 0 )\n\t\t\t\t\t\t\tfZ = ms_aWaterZs[ aWaterBlockList[2*x+0][2*y+1] ];\n\n\t\t\t\t\t\tif ( aWaterBlockList[2*x+1][2*y+1] >= 0 )\n\t\t\t\t\t\t\tfZ = ms_aWaterZs[ aWaterBlockList[2*x+1][2*y+1] ];\n\t\t\t\t\t\t\n\t\t\t\t\t\tif ( fHugeSectorDistToCamSqr >= SQR(500.0f) )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tRenderOneFlatHugeWaterPoly(fX, fY, fZ, color);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n#ifndef PC_WATER\n\t\t\t\t\t\t\tif (m_bRenderSeaBed)\n\t\t\t\t\t\t\t\tRenderOneSlopedUnderWaterPoly(fX, fY, fZ, colorUnderwater);\n#endif\n\t\t\t\t\t\t\t// see RenderTransparentWater()\n\t\t\t\t\t\t\t;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\t\n\t/*\n\t -----------      ----------------------       ----------------------\n\t|    [N]    |    |       [ EndY ]       |     |       [  top ]       |\n\t|           |    |                      |     |                      |\n\t|[W] [0] [E]|    |[StartX]  []  [ EndX ]|     |[ left ]  []  [ right]|\n\t|           |    |                      |     |                      |\n\t|    [S]    |    |       [StartY]       |     |       [bottom]       |\n\t -----------      ----------------------       ----------------------\n\t\n\t\n\t[S] [StartY]  [bottom]\n\t[N] [EndY]    [top]\n\t[W] [StartX]  [left]\n\t[E] [EndX]    [right]\n\t\n\t[S]    -> [N] && [W]  -> [E]\n\tbottom -> top && left -> right\n\t*/\n\n\tfor ( int32 x = 0; x < 26; x++ )\n\t{\n\t\tfor ( int32 y = 0; y < 5; y++ )\n\t\t{\n\t\t\tfloat fX = WATER_SIGN_X(float(x) * EXTRAHUGE_SECTOR_SIZE) - 1280.0f - WATER_X_OFFSET;\n\t\t\tfloat fY = WATER_SIGN_Y(float(y) * EXTRAHUGE_SECTOR_SIZE) - 1280.0f;\n\t\t\t\n\t\t\tif ( !bUseCamStartY )\n\t\t\t{\n\t\t\t\tCVector2D vecExtraHugeSectorCentre(fX + EXTRAHUGE_SECTOR_SIZE/2, fY + EXTRAHUGE_SECTOR_SIZE/2);\n\t\t\t\t\n\t\t\t\tfloat fCamDistToSector = (vecExtraHugeSectorCentre - camPos).Magnitude();\n\t\t\t\t\n\t\t\t\tif ( fCamDistToSector < fHugeSectorMaxRenderDistSqr )\n\t\t\t\t{\n\t\t\t\t\tif ( TheCamera.IsSphereVisible(CVector(vecExtraHugeSectorCentre.x, vecExtraHugeSectorCentre.y, 0.0f), SectorRadius(EXTRAHUGE_SECTOR_SIZE), &TheCamera.GetCameraMatrix()) )\n\t\t\t\t\t{\n\t\t\t\t\t\tRenderOneFlatExtraHugeWaterPoly(\n\t\t\t\t\t\t\tvecExtraHugeSectorCentre.x - EXTRAHUGE_SECTOR_SIZE/2,\n\t\t\t\t\t\t\tvecExtraHugeSectorCentre.y - EXTRAHUGE_SECTOR_SIZE/2,\n\t\t\t\t\t\t\t0.0f,\n\t\t\t\t\t\t\tcolor);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tif ( !bUseCamEndY )\n\t\t\t{\n\t\t\t\tCVector2D vecExtraHugeSectorCentre(fX + EXTRAHUGE_SECTOR_SIZE/2, -(fY + EXTRAHUGE_SECTOR_SIZE/2));\n\t\t\t\t\n\t\t\t\tfloat fCamDistToSector = (vecExtraHugeSectorCentre - camPos).Magnitude();\n\t\t\t\t\n\t\t\t\tif ( fCamDistToSector < fHugeSectorMaxRenderDistSqr )\n\t\t\t\t{\n\t\t\t\t\tif ( TheCamera.IsSphereVisible(CVector(vecExtraHugeSectorCentre.x, vecExtraHugeSectorCentre.y, 0.0f), SectorRadius(EXTRAHUGE_SECTOR_SIZE), &TheCamera.GetCameraMatrix()) )\n\t\t\t\t\t{\n\t\t\t\t\t\tRenderOneFlatExtraHugeWaterPoly(\n\t\t\t\t\t\t\tvecExtraHugeSectorCentre.x - EXTRAHUGE_SECTOR_SIZE/2,\n\t\t\t\t\t\t\tvecExtraHugeSectorCentre.y - EXTRAHUGE_SECTOR_SIZE/2,\n\t\t\t\t\t\t\t0.0f,\n\t\t\t\t\t\t\tcolor);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\t\n\tfor ( int32 y = 5; y < 21; y++ )\n\t{\n\t\tfor ( int32 x = 0; x < 5; x++ )\n\t\t{\n\t\t\tfloat fX = WATER_SIGN_X(float(x) * EXTRAHUGE_SECTOR_SIZE)  - 1280.0f - WATER_X_OFFSET;\n\t\t\tfloat fX2 = WATER_SIGN_X(float(x) * EXTRAHUGE_SECTOR_SIZE) - 1280.0f + WATER_X_OFFSET;\n\t\t\tfloat fY = WATER_SIGN_Y(float(y) * EXTRAHUGE_SECTOR_SIZE)  - 1280.0f;\n\t\t\t\n\t\t\tif ( !bUseCamStartX )\n\t\t\t{\n\t\t\t\tCVector2D vecExtraHugeSectorCentre(fX + EXTRAHUGE_SECTOR_SIZE/2, fY + EXTRAHUGE_SECTOR_SIZE/2);\n\t\t\t\t\n\t\t\t\tfloat fCamDistToSector = (vecExtraHugeSectorCentre - camPos).Magnitude();\n\t\t\t\t\n\t\t\t\tif ( fCamDistToSector < fHugeSectorMaxRenderDistSqr )\n\t\t\t\t{\n\t\t\t\t\tif ( TheCamera.IsSphereVisible(CVector(vecExtraHugeSectorCentre.x, vecExtraHugeSectorCentre.y, 0.0f), SectorRadius(EXTRAHUGE_SECTOR_SIZE), &TheCamera.GetCameraMatrix()) )\n\t\t\t\t\t{\n\t\t\t\t\t\tRenderOneFlatExtraHugeWaterPoly(\n\t\t\t\t\t\t\tvecExtraHugeSectorCentre.x - EXTRAHUGE_SECTOR_SIZE/2,\n\t\t\t\t\t\t\tvecExtraHugeSectorCentre.y - EXTRAHUGE_SECTOR_SIZE/2,\n\t\t\t\t\t\t\t0.0f,\n\t\t\t\t\t\t\tcolor);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tif ( !bUseCamEndX )\n\t\t\t{\n\t\t\t\tCVector2D vecExtraHugeSectorCentre(-(fX2 + EXTRAHUGE_SECTOR_SIZE/2), fY + EXTRAHUGE_SECTOR_SIZE/2);\n\t\t\t\t\n\t\t\t\tfloat fCamDistToSector = (vecExtraHugeSectorCentre - camPos).Magnitude();\n\t\t\t\t\n\t\t\t\tif ( fCamDistToSector < fHugeSectorMaxRenderDistSqr )\n\t\t\t\t{\n\t\t\t\t\tif ( TheCamera.IsSphereVisible(CVector(vecExtraHugeSectorCentre.x, vecExtraHugeSectorCentre.x, 0.0f), SectorRadius(EXTRAHUGE_SECTOR_SIZE), &TheCamera.GetCameraMatrix()) )\n\t\t\t\t\t{\n\t\t\t\t\t\tRenderOneFlatExtraHugeWaterPoly(\n\t\t\t\t\t\t\tvecExtraHugeSectorCentre.x - EXTRAHUGE_SECTOR_SIZE/2,\n\t\t\t\t\t\t\tvecExtraHugeSectorCentre.y - EXTRAHUGE_SECTOR_SIZE/2,\n\t\t\t\t\t\t\t0.0f,\n\t\t\t\t\t\t\tcolor);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\t\n\tRenderAndEmptyRenderBuffer();\n\n\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDSRCALPHA);\n\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDINVSRCALPHA);\n\t\n\tif ( WavesCalculatedThisFrame )\n\t{\n\t\tRenderSeaBirds();\n\t\tRenderShipsOnHorizon();\n\t\tCParticle::HandleShipsAtHorizonStuff();\n\t\tHandleBeachToysStuff();\n\t}\n\t\n\tif ( _bSeaLife )\n\t\tHandleSeaLifeForms();\n\n\tDefinedState();\n}\n\n\nvoid\nCWaterLevel::RenderTransparentWater(void)\n{\n\tbool bUseCamEndX  = false;\n\tbool bUseCamStartY = false;\n\t\n\tbool bUseCamStartX = false;\n\tbool bUseCamEndY   = false;\n\t\n\t_bSeaLife = false;\n\t\n\tif ( !CGame::CanSeeWaterFromCurrArea() )\n\t\treturn;\n\t\n\tPUSH_RENDERGROUP(\"CWaterLevel::RenderTransparentWater\");\n\n\tfloat fWaterDrawDist      = _GetWavyDrawDist();\n\tfloat fWaterDrawDistLarge = fWaterDrawDist + 90.0f;\n\tfloat fWavySectorMaxRenderDistSqr   = SQR(fWaterDrawDist);\n\t\n\t_GetCamBounds(&bUseCamStartY, &bUseCamEndY, &bUseCamStartX, &bUseCamEndX);\n\n\tfloat fHugeSectorMaxRenderDist    = _GetWaterDrawDist();\n\tfloat fHugeSectorMaxRenderDistSqr = SQR(fHugeSectorMaxRenderDist);\n\t\n\tRenderBoatWakes();\n\t\n\tRwRGBA color;\n\t\n\tcolor.red   = CTimeCycle::GetWaterRed();\n\tcolor.green = CTimeCycle::GetWaterGreen();\n\tcolor.blue  = CTimeCycle::GetWaterBlue();\n\tcolor.alpha = 255;\n\t\n\tRwRGBA colorTrans;\n\t\n\tcolorTrans.red   = CTimeCycle::GetWaterRed();\n\tcolorTrans.green = CTimeCycle::GetWaterGreen();\n\tcolorTrans.blue  = CTimeCycle::GetWaterBlue();\n\tcolorTrans.alpha = CTimeCycle::GetWaterAlpha();\n\t\n\tTempBufferVerticesStored = 0;\n\tTempBufferIndicesStored = 0;\n\n#ifndef PC_WATER\n\tWavesCalculatedThisFrame = false;\n#endif\n\t\n\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void *)gpWaterRaster);\n#ifndef PC_WATER\n\tRwRenderStateSet(rwRENDERSTATEFOGENABLE, (void *)TRUE);\n\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDSRCALPHA);\n\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDINVSRCALPHA);\n#endif\n\t\n\tCVector2D camPos(TheCamera.GetPosition().x, TheCamera.GetPosition().y);\n\n\tint32 nStartX = WATER_TO_HUGE_SECTOR_X(camPos.x - fHugeSectorMaxRenderDist + WATER_X_OFFSET);\n\tint32 nEndX   = WATER_TO_HUGE_SECTOR_X(camPos.x + fHugeSectorMaxRenderDist + WATER_X_OFFSET) + 1;\n\tint32 nStartY = WATER_TO_HUGE_SECTOR_Y(camPos.y - fHugeSectorMaxRenderDist         );\n\tint32 nEndY   = WATER_TO_HUGE_SECTOR_Y(camPos.y + fHugeSectorMaxRenderDist         ) + 1;\n\n\tif ( bUseCamStartX )\n\t\tnStartX = WATER_TO_HUGE_SECTOR_X(camPos.x + WATER_X_OFFSET);\n\tif ( bUseCamEndX )\n\t\tnEndX   = WATER_TO_HUGE_SECTOR_X(camPos.x + WATER_X_OFFSET);\n\tif ( bUseCamStartY )\n\t\tnStartY = WATER_TO_HUGE_SECTOR_Y(camPos.y         );\n\tif ( bUseCamEndY )                                      \n\t\tnEndY   = WATER_TO_HUGE_SECTOR_Y(camPos.y         );\n\t\n\tnStartX = clamp(nStartX, 0, MAX_HUGE_SECTORS - 1);\n\tnEndX   = clamp(nEndX,   0, MAX_HUGE_SECTORS - 1);\n\tnStartY = clamp(nStartY, 0, MAX_HUGE_SECTORS - 1);\n\tnEndY   = clamp(nEndY,   0, MAX_HUGE_SECTORS - 1);\n\t\n\t\n\tfor ( int32 x = nStartX; x <= nEndX; x++ )\n\t{\n\t\tfor ( int32 y = nStartY; y <= nEndY; y++ )\n\t\t{\n\t\t\tif (   aWaterBlockList[2*x+0][2*y+0] >= 0\n\t\t\t\t|| aWaterBlockList[2*x+1][2*y+0] >= 0\n\t\t\t\t|| aWaterBlockList[2*x+0][2*y+1] >= 0\n\t\t\t\t|| aWaterBlockList[2*x+1][2*y+1] >= 0 )\n\t\t\t{\n\t\t\t\tfloat fX = WATER_FROM_HUGE_SECTOR_X(x) - WATER_X_OFFSET;\n\t\t\t\tfloat fY = WATER_FROM_HUGE_SECTOR_Y(y);\n\n\t\t\t\tCVector2D vecHugeSectorCentre\n\t\t\t\t(\n\t\t\t\t\tfX + HUGE_SECTOR_SIZE/2,\n\t\t\t\t\tfY + HUGE_SECTOR_SIZE/2\n\t\t\t\t);\n\n\t\t\t\tfloat fHugeSectorDistToCamSqr = (camPos - vecHugeSectorCentre).MagnitudeSqr();\n\t\t\t\t\n\t\t\t\tif ( fHugeSectorMaxRenderDistSqr > fHugeSectorDistToCamSqr )\n\t\t\t\t{\n\t\t\t\t\tif ( TheCamera.IsSphereVisible(CVector(vecHugeSectorCentre.x, vecHugeSectorCentre.y, 0.0f), SectorRadius(HUGE_SECTOR_SIZE), &TheCamera.GetCameraMatrix()) )\n\t\t\t\t\t{\n\t\t\t\t\t\tif ( fHugeSectorDistToCamSqr >= SQR(500.0f) )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// see RenderWater()\n\t\t\t\t\t\t\t;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tfor ( int32 x2 = 2*x; x2 <= 2*x+1; x2++ )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tfor ( int32 y2 = 2*y; y2 <= 2*y+1; y2++ )\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tif ( aWaterBlockList[x2][y2] >= 0 )\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tfloat fLargeX = WATER_FROM_LARGE_SECTOR_X(x2) - WATER_X_OFFSET;\n\t\t\t\t\t\t\t\t\t\tfloat fLargeY = WATER_FROM_LARGE_SECTOR_Y(y2);\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\tCVector2D vecLargeSectorCentre(fLargeX + LARGE_SECTOR_SIZE/2, fLargeY + LARGE_SECTOR_SIZE/2);\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\tfloat fLargeSectorDistToCamSqr = (camPos - vecLargeSectorCentre).MagnitudeSqr();\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\tif ( fLargeSectorDistToCamSqr < fHugeSectorMaxRenderDistSqr )\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tif ( TheCamera.IsSphereVisible(CVector(vecLargeSectorCentre.x, vecLargeSectorCentre.y, 0.0f), SectorRadius(LARGE_SECTOR_SIZE), &TheCamera.GetCameraMatrix()) )\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t// Render four small(32x32) sectors, or one large(64x64).\n\n\t\t\t\t\t\t\t\t\t\t\t\t//\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t//\t       [N]\n\t\t\t\t\t\t\t\t\t\t\t\t//\t    ---------\n\t\t\t\t\t\t\t\t\t\t\t\t//\t    |0x1|1x1|\n\t\t\t\t\t\t\t\t\t\t\t\t//\t[W] --------- [E]\n\t\t\t\t\t\t\t\t\t\t\t\t//\t    |0x0|1x0|\n\t\t\t\t\t\t\t\t\t\t\t\t//\t    ---------\n\t\t\t\t\t\t\t\t\t\t\t\t//\t       [S]\n\t\t\t\t\t\t\t\t\t\t\t\t//\t\n\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\tfloat fLargeSectorDrawDistSqr = SQR((fWaterDrawDistLarge + 16.0f));\n\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\tif ( fLargeSectorDistToCamSqr < fLargeSectorDrawDistSqr )\n\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t_bSeaLife = true;\n\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\tfloat fZ;\n\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t// WS\n\t\t\t\t\t\t\t\t\t\t\t\t\tif ( aWaterFineBlockList[2*x2+0][2*y2+0] >= 0 )\n\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tfloat fSmallX = fLargeX;\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tfloat fSmallY = fLargeY;\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tCVector2D vecSmallSectorCentre(fSmallX + SMALL_SECTOR_SIZE/2, fSmallY + SMALL_SECTOR_SIZE/2);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tfloat fSmallSectorDistToCamSqr = (camPos - vecSmallSectorCentre).MagnitudeSqr();\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tfZ = ms_aWaterZs[ aWaterFineBlockList[2*x2+0][2*y2+0] ];\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tif ( fSmallSectorDistToCamSqr < fWavySectorMaxRenderDistSqr )\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tRenderOneWavySector(fSmallX, fSmallY, fZ, colorTrans);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tRenderOneFlatSmallWaterPolyBlended(fSmallX, fSmallY, fZ, camPos.x, camPos.y, color, colorTrans, fWaterDrawDist);\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t// SE\n\t\t\t\t\t\t\t\t\t\t\t\t\tif ( aWaterFineBlockList[2*x2+1][2*y2+0] >= 0 )\n\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tfloat fSmallX = fLargeX + (LARGE_SECTOR_SIZE/2);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tfloat fSmallY = fLargeY;\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tCVector2D vecSmallSectorCentre(fSmallX + SMALL_SECTOR_SIZE/2, fSmallY + SMALL_SECTOR_SIZE/2);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tfloat fSmallSectorDistToCamSqr = (camPos - vecSmallSectorCentre).MagnitudeSqr();\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tfZ = ms_aWaterZs[ aWaterFineBlockList[2*x2+1][2*y2+0] ];\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tif ( fSmallSectorDistToCamSqr < fWavySectorMaxRenderDistSqr )\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tRenderOneWavySector(fSmallX, fSmallY, fZ, colorTrans);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tRenderOneFlatSmallWaterPolyBlended(fSmallX, fSmallY, fZ, camPos.x, camPos.y, color, colorTrans, fWaterDrawDist);\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t// WN\n\t\t\t\t\t\t\t\t\t\t\t\t\tif ( aWaterFineBlockList[2*x2+0][2*y2+1] >= 0 )\n\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tfloat fSmallX = fLargeX;\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tfloat fSmallY = fLargeY + (LARGE_SECTOR_SIZE/2);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tCVector2D vecSmallSectorCentre(fSmallX + SMALL_SECTOR_SIZE/2,fSmallY + SMALL_SECTOR_SIZE/2);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tfloat fSmallSectorDistToCamSqr = (camPos - vecSmallSectorCentre).MagnitudeSqr();\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tfZ = ms_aWaterZs[ aWaterFineBlockList[2*x2+0][2*y2+1] ];\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tif ( fSmallSectorDistToCamSqr < fWavySectorMaxRenderDistSqr )\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tRenderOneWavySector(fSmallX, fSmallY, fZ, colorTrans);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tRenderOneFlatSmallWaterPolyBlended(fSmallX, fSmallY, fZ, camPos.x, camPos.y, color, colorTrans, fWaterDrawDist);\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t//NE\n\t\t\t\t\t\t\t\t\t\t\t\t\tif ( aWaterFineBlockList[2*x2+1][2*y2+1] >= 0 )\n\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tfloat fSmallX = fLargeX + (LARGE_SECTOR_SIZE/2);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tfloat fSmallY = fLargeY + (LARGE_SECTOR_SIZE/2);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tCVector2D vecSmallSectorCentre(fSmallX + SMALL_SECTOR_SIZE/2, fSmallY + SMALL_SECTOR_SIZE/2);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tfloat fSmallSectorDistToCamSqr = (camPos - vecSmallSectorCentre).MagnitudeSqr();\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tfZ = ms_aWaterZs[ aWaterFineBlockList[2*x2+1][2*y2+1] ];\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tif ( fSmallSectorDistToCamSqr < fWavySectorMaxRenderDistSqr )\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tRenderOneWavySector(fSmallX, fSmallY, fZ, colorTrans);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tRenderOneFlatSmallWaterPolyBlended(fSmallX, fSmallY, fZ, camPos.x, camPos.y, color, colorTrans, fWaterDrawDist);\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\tfloat fZ;\n                                                \n\t\t\t\t\t\t\t\t\t\t\t\t\tfZ = ms_aWaterZs[ aWaterBlockList[x2][y2] ];\n                                                \n\t\t\t\t\t\t\t\t\t\t\t\t\tRenderOneFlatLargeWaterPoly(fLargeX, fLargeY, fZ, color);\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\t\n\tRenderAndEmptyRenderBuffer();\n\t\n#ifdef PC_WATER\n\tif ( MaskCalculatedThisFrame\n\t\t&& (m_nRenderWaterLayers == 0 || m_nRenderWaterLayers == 2 || m_nRenderWaterLayers == 3) )\n\t{\n\t\tRwV3d pos = { 0.0f, 0.0f, 0.0f };\n\n\t\tpos.x = PreCalculatedMaskPosn.x;\n\t\tpos.y = PreCalculatedMaskPosn.y;\n\t\tpos.z = PreCalculatedMaskPosn.z;\n\n\t\tRpMatFXMaterialSetEnvMapFrame(RpGeometryGetMaterial(RpAtomicGetGeometry(ms_pMaskAtomic), 0),\n\t\t\t\t\t\t\t\t\t\tRwCameraGetFrame(RwCameraGetCurrentCamera()));\n\n\t\tRwFrameTranslate(RpAtomicGetFrame(ms_pMaskAtomic), &pos, rwCOMBINEREPLACE);\n\t\t\t\t\n\t\tRpAtomicRender(ms_pMaskAtomic);\n\t}\n#else\n\tif (!CCullZones::WaterFudge())\n\t{\n\t\tint32 signX = 0;\n\t\tint32 signY = 0;\n\n\t\tfloat fCamX = camPos.x - SMALL_SECTOR_SIZE;\n\t\tfloat fCamY = camPos.y - SMALL_SECTOR_SIZE;\n\n\t\tif (TheCamera.GetForward().x > 0.3f)\n\t\t\tsignX = 1;\n\t\telse if (TheCamera.GetForward().x < -0.3f)\n\t\t\tsignX = -1;\n\n\t\tfCamX += 0.3f * (float)signX * float(SMALL_SECTOR_SIZE * 2.0f); // 19.2f\n\n\t\tif (TheCamera.GetForward().y > 0.3f)\n\t\t\tsignY = 1;\n\t\telse if (TheCamera.GetForward().y < -0.3f)\n\t\t\tsignY = -1;\n\n\t\tfCamY += 0.3f * (float)signY * float(SMALL_SECTOR_SIZE * 2.0f); // 19.2f\n\n\t\tint32 nBlock;\n\n\t\tint32 BlockX = WATER_TO_SMALL_SECTOR_X(fCamX + WATER_X_OFFSET) + 1;\n\t\tint32 BlockY = WATER_TO_SMALL_SECTOR_Y(fCamY) + 1;\n\n\t\tif (_IsColideWithBlock(BlockX, BlockY, nBlock))\n\t\t{\n\t\t\tif (m_nRenderWaterLayers != 1 && m_nRenderWaterLayers != 6)\n\t\t\t{\n\t\t\t\tfloat fMaskX = Floor(fCamX / 2.0f) * 2.0f;\n\t\t\t\tfloat fMaskY = Floor(fCamY / 2.0f) * 2.0f;\n\t\t\t\tfloat fWaterZ = CWaterLevel::ms_aWaterZs[nBlock];\n\t\t\t\tfloat fSectorX = WATER_FROM_SMALL_SECTOR_X(BlockX) - WATER_X_OFFSET;\n\t\t\t\tfloat fSectorY = WATER_FROM_SMALL_SECTOR_Y(BlockY);\n\n\t\t\t\tRenderWavyMask(fMaskX, fMaskY, fWaterZ,\n\t\t\t\t\tfSectorX, fSectorY,\n\t\t\t\t\tsignX, signY, colorTrans);\n\t\t\t}\n\t\t}\n\t}\n\n\tDefinedState();\n#endif\n\n\tPOP_RENDERGROUP();\n}\n\nvoid CWaterLevel::RenderOneFlatSmallWaterPoly(float fX, float fY, float fZ, RwRGBA const &color)\n{\n\tif ( TempBufferIndicesStored >= TEMPBUFFERINDEXSIZE-6 || TempBufferVerticesStored >= TEMPBUFFERVERTSIZE-4 )\n\t\tRenderAndEmptyRenderBuffer();\n\t\n\tint32 vidx = TempBufferVerticesStored;\n\t\n\tRwIm3DVertexSetPos  (&TempBufferRenderVertices[vidx + 0], fX, fY, fZ - _fWaterZOffset);\n\tRwIm3DVertexSetU    (&TempBufferRenderVertices[vidx + 0], TEXTURE_ADDU);\n\tRwIm3DVertexSetV    (&TempBufferRenderVertices[vidx + 0], TEXTURE_ADDV);\n\tRwIm3DVertexSet_RGBA(&TempBufferRenderVertices[vidx + 0], color);\n\n\tRwIm3DVertexSetPos  (&TempBufferRenderVertices[vidx + 1], fX, fY + SMALL_SECTOR_SIZE, fZ - _fWaterZOffset);\n\tRwIm3DVertexSetU    (&TempBufferRenderVertices[vidx + 1], TEXTURE_ADDU);\n\tRwIm3DVertexSetV    (&TempBufferRenderVertices[vidx + 1], TEXTURE_ADDV + 1.0f);\n\tRwIm3DVertexSet_RGBA(&TempBufferRenderVertices[vidx + 1], color);\n\n\tRwIm3DVertexSetPos  (&TempBufferRenderVertices[vidx + 2], fX + SMALL_SECTOR_SIZE, fY + SMALL_SECTOR_SIZE, fZ - _fWaterZOffset);\n\tRwIm3DVertexSetU    (&TempBufferRenderVertices[vidx + 2], TEXTURE_ADDU + 1.0f);\n\tRwIm3DVertexSetV    (&TempBufferRenderVertices[vidx + 2], TEXTURE_ADDV + 1.0f);\n\tRwIm3DVertexSet_RGBA(&TempBufferRenderVertices[vidx + 2], color);\n\n\tRwIm3DVertexSetPos  (&TempBufferRenderVertices[vidx + 3], fX + SMALL_SECTOR_SIZE, fY, fZ - _fWaterZOffset);\n\tRwIm3DVertexSetU    (&TempBufferRenderVertices[vidx + 3], TEXTURE_ADDU + 1.0f);\n\tRwIm3DVertexSetV    (&TempBufferRenderVertices[vidx + 3], TEXTURE_ADDV);\n\tRwIm3DVertexSet_RGBA(&TempBufferRenderVertices[vidx + 3], color);\n\t\n\t\n\tint32 iidx = TempBufferIndicesStored;\n\n\tTempBufferRenderIndexList[iidx + 0] = TempBufferVerticesStored + 0;\n\tTempBufferRenderIndexList[iidx + 1] = TempBufferVerticesStored + 2;\n\tTempBufferRenderIndexList[iidx + 2] = TempBufferVerticesStored + 1;\n\tTempBufferRenderIndexList[iidx + 3] = TempBufferVerticesStored + 0;\n\tTempBufferRenderIndexList[iidx + 4] = TempBufferVerticesStored + 3;\n\tTempBufferRenderIndexList[iidx + 5] = TempBufferVerticesStored + 2;\n\t\n\tTempBufferVerticesStored += 4;\n\tTempBufferIndicesStored += 6;\n}\n\nvoid\nCWaterLevel::RenderOneFlatLargeWaterPoly(float fX, float fY, float fZ, RwRGBA const &color)\n{\n\tif ( TempBufferIndicesStored >= TEMPBUFFERINDEXSIZE-6 || TempBufferVerticesStored >= TEMPBUFFERVERTSIZE-4 )\n\t\tRenderAndEmptyRenderBuffer();\n\t\n\tint32 vidx = TempBufferVerticesStored;\n\t\n\tRwIm3DVertexSetPos  (&TempBufferRenderVertices[vidx + 0], fX, fY, fZ - _fWaterZOffset);\n\tRwIm3DVertexSetU    (&TempBufferRenderVertices[vidx + 0], TEXTURE_ADDU);\n\tRwIm3DVertexSetV    (&TempBufferRenderVertices[vidx + 0], TEXTURE_ADDV);\n\tRwIm3DVertexSet_RGBA(&TempBufferRenderVertices[vidx + 0], color);\n\n\tRwIm3DVertexSetPos  (&TempBufferRenderVertices[vidx + 1], fX, fY + LARGE_SECTOR_SIZE, fZ - _fWaterZOffset);\n\tRwIm3DVertexSetU    (&TempBufferRenderVertices[vidx + 1], TEXTURE_ADDU);\n\tRwIm3DVertexSetV    (&TempBufferRenderVertices[vidx + 1], TEXTURE_ADDV + 2.0f);\n\tRwIm3DVertexSet_RGBA(&TempBufferRenderVertices[vidx + 1], color);\n\n\tRwIm3DVertexSetPos  (&TempBufferRenderVertices[vidx + 2], fX + LARGE_SECTOR_SIZE, fY + LARGE_SECTOR_SIZE, fZ - _fWaterZOffset);\n\tRwIm3DVertexSetU    (&TempBufferRenderVertices[vidx + 2], TEXTURE_ADDU + 2.0f);\n\tRwIm3DVertexSetV    (&TempBufferRenderVertices[vidx + 2], TEXTURE_ADDV + 2.0f);\n\tRwIm3DVertexSet_RGBA(&TempBufferRenderVertices[vidx + 2], color);\n\n\tRwIm3DVertexSetPos  (&TempBufferRenderVertices[vidx + 3], fX + LARGE_SECTOR_SIZE, fY, fZ - _fWaterZOffset);\n\tRwIm3DVertexSetU    (&TempBufferRenderVertices[vidx + 3], TEXTURE_ADDU + 2.0f);\n\tRwIm3DVertexSetV    (&TempBufferRenderVertices[vidx + 3], TEXTURE_ADDV);\n\tRwIm3DVertexSet_RGBA(&TempBufferRenderVertices[vidx + 3], color);\n\n\n\tint32 iidx = TempBufferIndicesStored;\n\n\tTempBufferRenderIndexList[iidx + 0] = TempBufferVerticesStored + 0;\n\tTempBufferRenderIndexList[iidx + 1] = TempBufferVerticesStored + 2;\n\tTempBufferRenderIndexList[iidx + 2] = TempBufferVerticesStored + 1;\n\tTempBufferRenderIndexList[iidx + 3] = TempBufferVerticesStored + 0;\n\tTempBufferRenderIndexList[iidx + 4] = TempBufferVerticesStored + 3;\n\tTempBufferRenderIndexList[iidx + 5] = TempBufferVerticesStored + 2;\n\t\n\tTempBufferVerticesStored += 4;\n\tTempBufferIndicesStored += 6;\n}\n\nvoid\nCWaterLevel::RenderOneFlatHugeWaterPoly(float fX, float fY, float fZ, RwRGBA const &color)\n{\n\tif ( TempBufferIndicesStored >= TEMPBUFFERINDEXSIZE-6 || TempBufferVerticesStored >= TEMPBUFFERVERTSIZE-4 )\n\t\tRenderAndEmptyRenderBuffer();\n\t\n\tint32 vidx = TempBufferVerticesStored;\n\t\n\tRwRGBA c;\n\t\n\tc.red = color.red;\n\tc.green = color.green;\n\tc.blue = color.blue;\n\tc.alpha = 255;\n\t\n\tRwIm3DVertexSetPos  (&TempBufferRenderVertices[vidx + 0], fX, fY, fZ - _fWaterZOffset);\n\tRwIm3DVertexSetU    (&TempBufferRenderVertices[vidx + 0], TEXTURE_ADDU);\n\tRwIm3DVertexSetV    (&TempBufferRenderVertices[vidx + 0], TEXTURE_ADDV);\n\tRwIm3DVertexSet_RGBA(&TempBufferRenderVertices[vidx + 0], c);\n\n\tRwIm3DVertexSetPos  (&TempBufferRenderVertices[vidx + 1], fX, fY + HUGE_SECTOR_SIZE, fZ - _fWaterZOffset);\n\tRwIm3DVertexSetU    (&TempBufferRenderVertices[vidx + 1], TEXTURE_ADDU);\n\tRwIm3DVertexSetV    (&TempBufferRenderVertices[vidx + 1], TEXTURE_ADDV + 4.0f);\n\tRwIm3DVertexSet_RGBA(&TempBufferRenderVertices[vidx + 1], c);\n\n\tRwIm3DVertexSetPos  (&TempBufferRenderVertices[vidx + 2], fX + HUGE_SECTOR_SIZE, fY + HUGE_SECTOR_SIZE, fZ - _fWaterZOffset);\n\tRwIm3DVertexSetU    (&TempBufferRenderVertices[vidx + 2], TEXTURE_ADDU + 4.0f);\n\tRwIm3DVertexSetV    (&TempBufferRenderVertices[vidx + 2], TEXTURE_ADDV + 4.0f);\n\tRwIm3DVertexSet_RGBA(&TempBufferRenderVertices[vidx + 2], c);\n\n\tRwIm3DVertexSetPos  (&TempBufferRenderVertices[vidx + 3], fX + HUGE_SECTOR_SIZE, fY, fZ - _fWaterZOffset);\n\tRwIm3DVertexSetU    (&TempBufferRenderVertices[vidx + 3], TEXTURE_ADDU + 4.0f);\n\tRwIm3DVertexSetV    (&TempBufferRenderVertices[vidx + 3], TEXTURE_ADDV);\n\tRwIm3DVertexSet_RGBA(&TempBufferRenderVertices[vidx + 3], c);\n\n\n\tint32 iidx = TempBufferIndicesStored;\n\n\tTempBufferRenderIndexList[iidx + 0] = TempBufferVerticesStored + 0;\n\tTempBufferRenderIndexList[iidx + 1] = TempBufferVerticesStored + 2;\n\tTempBufferRenderIndexList[iidx + 2] = TempBufferVerticesStored + 1;\n\tTempBufferRenderIndexList[iidx + 3] = TempBufferVerticesStored + 0;\n\tTempBufferRenderIndexList[iidx + 4] = TempBufferVerticesStored + 3;\n\tTempBufferRenderIndexList[iidx + 5] = TempBufferVerticesStored + 2;\n\t\n\tTempBufferVerticesStored += 4;\n\tTempBufferIndicesStored += 6;\n}\n\nvoid\nCWaterLevel::RenderOneFlatExtraHugeWaterPoly(float fX, float fY, float fZ, RwRGBA const &color)\n{\n\tif ( TempBufferIndicesStored >= TEMPBUFFERINDEXSIZE-6 || TempBufferVerticesStored >= TEMPBUFFERVERTSIZE-4 )\n\t\tRenderAndEmptyRenderBuffer();\n\t\n\tint32 vidx = TempBufferVerticesStored;\n\t\n\tRwRGBA c;\n\t\n\tc.red = color.red;\n\tc.green = color.green;\n\tc.blue = color.blue;\n\tc.alpha = 255;\n\t\n\tRwIm3DVertexSetPos  (&TempBufferRenderVertices[vidx + 0], fX, fY, fZ - _fWaterZOffset);\n\tRwIm3DVertexSetU    (&TempBufferRenderVertices[vidx + 0], TEXTURE_ADDU);\n\tRwIm3DVertexSetV    (&TempBufferRenderVertices[vidx + 0], TEXTURE_ADDV);\n\tRwIm3DVertexSet_RGBA(&TempBufferRenderVertices[vidx + 0], c);\n\n\tRwIm3DVertexSetPos  (&TempBufferRenderVertices[vidx + 1], fX, fY + EXTRAHUGE_SECTOR_SIZE, fZ - _fWaterZOffset);\n\tRwIm3DVertexSetU    (&TempBufferRenderVertices[vidx + 1], TEXTURE_ADDU);\n\tRwIm3DVertexSetV    (&TempBufferRenderVertices[vidx + 1], TEXTURE_ADDV + 8.0f);\n\tRwIm3DVertexSet_RGBA(&TempBufferRenderVertices[vidx + 1], c);\n\n\tRwIm3DVertexSetPos  (&TempBufferRenderVertices[vidx + 2], fX + EXTRAHUGE_SECTOR_SIZE, fY + EXTRAHUGE_SECTOR_SIZE, fZ - _fWaterZOffset);\n\tRwIm3DVertexSetU    (&TempBufferRenderVertices[vidx + 2], TEXTURE_ADDU + 8.0f);\n\tRwIm3DVertexSetV    (&TempBufferRenderVertices[vidx + 2], TEXTURE_ADDV + 8.0f);\n\tRwIm3DVertexSet_RGBA(&TempBufferRenderVertices[vidx + 2], c);\n\t\n\tRwIm3DVertexSetPos  (&TempBufferRenderVertices[vidx + 3], fX + EXTRAHUGE_SECTOR_SIZE, fY, fZ - _fWaterZOffset);\n\tRwIm3DVertexSetU    (&TempBufferRenderVertices[vidx + 3], TEXTURE_ADDU + 8.0f);\n\tRwIm3DVertexSetV    (&TempBufferRenderVertices[vidx + 3], TEXTURE_ADDV);\n\tRwIm3DVertexSet_RGBA(&TempBufferRenderVertices[vidx + 3], c);\n\n\n\tint32 iidx = TempBufferIndicesStored;\n\n\tTempBufferRenderIndexList[iidx + 0] = TempBufferVerticesStored + 0;\n\tTempBufferRenderIndexList[iidx + 1] = TempBufferVerticesStored + 2;\n\tTempBufferRenderIndexList[iidx + 2] = TempBufferVerticesStored + 1;\n\tTempBufferRenderIndexList[iidx + 3] = TempBufferVerticesStored + 0;\n\tTempBufferRenderIndexList[iidx + 4] = TempBufferVerticesStored + 3;\n\tTempBufferRenderIndexList[iidx + 5] = TempBufferVerticesStored + 2;\n\t\n\tTempBufferVerticesStored += 4;\n\tTempBufferIndicesStored += 6;\n}\n\nvoid\nCWaterLevel::RenderOneWavySector(float fX, float fY, float fZ, RwRGBA const &color, bool bDontRender)\n{\n\tCVector vecSectorPos(fX + (SMALL_SECTOR_SIZE/2), fY + (SMALL_SECTOR_SIZE/2), fZ + 2.0f);\n\n\tif ( COcclusion::IsAABoxOccluded(vecSectorPos, SMALL_SECTOR_SIZE, SMALL_SECTOR_SIZE, 4.0f) )\n\t\treturn;\n\n#ifdef PC_WATER\n\tRequireWavySector = true;\n#else\n\tif (!WavesCalculatedThisFrame)\n\t{\n\t\tWavesCalculatedThisFrame = true;\n\n\t\tfloat fAngle = (CTimer::GetTimeInMilliseconds() & 4095) * (TWOPI / 4096.0f);\n\n\t\tRpGeometry *wavyGeometry = RpAtomicGetGeometry(ms_pWavyAtomic);\n\t\tRwTexCoords *wavyTexCoords = RpGeometryGetVertexTexCoords(wavyGeometry, rwTEXTURECOORDINATEINDEX0);\n\t\tRpMorphTarget *wavyMorph = RpGeometryGetMorphTarget(wavyGeometry, 0);\n\t\tRwRGBA *wavyPreLight = RpGeometryGetPreLightColors(wavyGeometry);\n\t\tRwV3d *wavyMorphVerts = RpMorphTargetGetVertices(wavyMorph);\n\t\tRwV3d *wavyMorphNormals = RpMorphTargetGetVertexNormals(wavyMorph);\n\n\t\tRpGeometryLock(wavyGeometry, rpGEOMETRYLOCKVERTICES | rpGEOMETRYLOCKNORMALS | rpGEOMETRYLOCKPRELIGHT | rpGEOMETRYLOCKTEXCOORDS);\n\n\t\tRwMatrix *camMat = RwFrameGetLTM(RwCameraGetFrame(RwCameraGetCurrentCamera())); //or curWorld\n\n\t\tfloat randomDampInv2 = (1.0f - fRandomDamp) * 2.0f;\n\n\t\tfloat move = 1.0f / 16.0f;\n\t\tfloat randomMove = 1.0f / (16.0f * fRandomMoveDiv);\n\n\t\tfloat vertMul = 0.5f;\n\n\t\tfloat wind = CWeather::WindClipped * 0.4f + 0.2f;\n\t\tfloat waveWind = CWeather::WindClipped * fWave2Ampl + 0.05f;\n\n\t\tfloat waveA = (TWOPI / 16.0f)\n\t\t\t* ((fNormalDirectionScalar1 * Abs(camMat->at.x + camMat->at.y) + fNormMult) * (CWeather::WindClipped * 0.4f + 0.2f));\n\n\t\tfloat waveB = TWOPI / (16.0f * fWave2NormScale)\n\t\t\t* ((fNormalDirectionScalar2 * Abs(camMat->at.y - camMat->at.x) + fNormMultB) * (CWeather::WindClipped * 0.2f + 0.1f));\n\n\t\tCVector vA(1.0f, 0.0f, 0.0f);\n\t\tCVector vB(0.0f, 1.0f, 0.0f);\n\n\t\tfor ( int32 i = 0; i < 17; i++ )\n\t\t{\n\t\t\tfor ( int32 j = 0; j < 17; j++ )\n\t\t\t{\n\t\t\t\twavyTexCoords->u = float(i) * move + TEXTURE_ADDV;\n\t\t\t\twavyTexCoords->v = float(j) * move + TEXTURE_ADDU;\n\n\t\t\t\tRwRGBAAssign(wavyPreLight, &color);\n\n\t\t\t\tif (i > 0 && i < 16 && j > 0 && j < 16)\n\t\t\t\t{\n\t\t\t\t\twavyMorphVerts->x += CGeneral::GetRandomNumberInRange(-1.0f, 1.0f) * randomMove;\n\t\t\t\t\twavyMorphVerts->x *= fRandomDamp;\n\t\t\t\t\twavyMorphVerts->x += float(i) * randomDampInv2;\n\n\t\t\t\t\twavyMorphVerts->y += CGeneral::GetRandomNumberInRange(-1.0f, 1.0f) * randomMove;\n\t\t\t\t\twavyMorphVerts->y *= fRandomDamp;\n\t\t\t\t\twavyMorphVerts->y += float(j) * randomDampInv2;\n\t\t\t\t}\n\n\t\t\t\tfloat morphVertXHalf = (i == 16) ? 0.0f : vertMul * wavyMorphVerts->x;\n\t\t\t\tfloat morphVertYHalf = (j == 16) ? 0.0f : vertMul * wavyMorphVerts->y;\n\n\t\t\t\tfloat waveMulA = (morphVertYHalf + morphVertXHalf) * (TWOPI / 16.0f) + fAngle;\n\t\t\t\tfloat waveMulB = (morphVertYHalf - morphVertXHalf) * (TWOPI / (16.0f * fWave2InvLength)) + fAngle;\n\n\t\t\t\twavyMorphVerts->z = wind * Sin(waveMulA) + waveWind * Sin(waveMulB);\n\n\t\t\t\tvA.z = (waveA * Cos(waveMulA)) - (waveB * Cos(waveMulB));\n\t\t\t\tvB.z = (waveA * Cos(waveMulA)) + (waveB * Cos(waveMulB));\n\n\t\t\t\tCVector norm = CrossProduct(vA, vB);\n\t\t\t\tnorm.Normalise();\n\n\t\t\t\twavyMorphNormals->x = norm.x;\n\t\t\t\twavyMorphNormals->y = norm.y;\n\t\t\t\twavyMorphNormals->z = norm.z;\n\n\t\t\t\t++wavyPreLight;\n\t\t\t\t++wavyTexCoords;\n\n\t\t\t\t++wavyMorphVerts;\n\t\t\t\t++wavyMorphNormals;\n\t\t\t}\n\t\t}\n\n\t\tRpGeometryUnlock(wavyGeometry);\n\t}\n\n\tfloat fCentreX = fX + (SMALL_SECTOR_SIZE / 2);\n\tfloat fCentreY = fY + (SMALL_SECTOR_SIZE / 2);\n#endif\n\t\n#ifdef PC_WATER\n\tif ( WavesCalculatedThisFrame )\n#endif\n\t{\n\t\tif (bDontRender == false\n\t\t\t&& m_nRenderWaterLayers != 2\n\t\t\t&& m_nRenderWaterLayers != 4\n\t\t\t&& m_nRenderWaterLayers != 6 )\n\t\t{\n\t\t\tRwV3d pos = { 0.0f, 0.0f, 0.0f };\n\n\t\t\tpos.x = fX;\n\t\t\tpos.y = fY;\n\t\t\tpos.z = fZ;\n\t\n\t\t\tRwFrameTranslate(RpAtomicGetFrame(ms_pWavyAtomic), &pos, rwCOMBINEREPLACE);\n\t\t\n\t\t\tRpAtomicRender(ms_pWavyAtomic);\n\t\t}\n\t}\n}\n\t\t\nint16\n_RoundValue(int32 v)\n{\n\tint16 result = v;\n\t\n\twhile ( result < 0 )  result += 16;\n\twhile ( result > 16 ) result -= 16;\n\t\n\treturn result;\n}\n\nvoid\nCWaterLevel::RenderWavyMask(float fX, float fY, float fZ,\n\t\tfloat fSectorX, float fSectorY,\n#ifdef PC_WATER\n\t\tfloat fCamPosX, float fCamPosY,\n\t\tfloat fCamDirX, float fCamDirY, RwRGBA const&color)\n#else\n\t\tint32 nCamDirX, int32 nCamDirY, RwRGBA const&color)\n#endif\n{\n#ifndef PC_WATER\n\tbool bRender = true;\n\tif (m_nRenderWaterLayers != 0 && m_nRenderWaterLayers != 2 && m_nRenderWaterLayers != 3)\n\t\tbRender = false;\n#endif\n\tCVector vecSectorPos(fX + (LARGE_SECTOR_SIZE/2), fY + (LARGE_SECTOR_SIZE/2), fZ + 2.0f);\n\n\tif ( COcclusion::IsAABoxOccluded(vecSectorPos, LARGE_SECTOR_SIZE, LARGE_SECTOR_SIZE, 4.0f) )\n\t\treturn;\n\n#ifndef PC_WATER\n\tfloat fUOffset = fX - (MAX_LARGE_SECTORS * (int32)Floor(fX / MAX_LARGE_SECTORS));\n\tfloat fVOffset = fY - (MAX_LARGE_SECTORS * (int32)Floor(fY / MAX_LARGE_SECTORS));\n\n\tint32 nSecsX = (int32)((fX - fSectorX) / 2.0f);\n\tint32 nSecsY = (int32)((fY - fSectorY) / 2.0f);\n#endif\n\t\n\tRpGeometry    *wavyGeometry  = RpAtomicGetGeometry(ms_pWavyAtomic);\n\tRpMorphTarget *wavyMorph     = RpGeometryGetMorphTarget(wavyGeometry, 0);\n\tRwV3d *wavyMorphVerts        = RpMorphTargetGetVertices(wavyMorph);\n\tRwV3d *wavyMorphNormals      = RpMorphTargetGetVertexNormals(wavyMorph);\n\n\tRpGeometry    *maskGeometry  = RpAtomicGetGeometry(ms_pMaskAtomic);\n\tRwTexCoords   *maskTexCoords = RpGeometryGetVertexTexCoords(maskGeometry, rwTEXTURECOORDINATEINDEX0);\n\tRwRGBA        *maskPreLight  = RpGeometryGetPreLightColors(maskGeometry);\n\tRpMorphTarget *maskMorph     = RpGeometryGetMorphTarget(maskGeometry, 0);\n\tRwV3d *maskMorphVerts        = RpMorphTargetGetVertices(maskMorph);\n\tRwV3d *maskMorphNormals      = RpMorphTargetGetVertexNormals(maskMorph);\n\n\tRpGeometryLock(maskGeometry, rpGEOMETRYLOCKVERTICES|rpGEOMETRYLOCKNORMALS|rpGEOMETRYLOCKPRELIGHT|rpGEOMETRYLOCKTEXCOORDS);\n\t\n#ifndef PC_WATER\n\tRpMaterial *maskMat = RpGeometryGetMaterial(maskGeometry, 0);\n\tRpMatFXMaterialSetEnvMapFrame(maskMat, RwCameraGetFrame(RwCameraGetCurrentCamera()));\n\tRpMatFXMaterialSetEnvMapCoefficient(maskMat, fEnvScale);\n\tRpMatFXMaterialSetEnvMapFrameBufferAlpha(maskMat, TRUE);\n#endif\n\t\n#ifndef PC_WATER\n\tfloat fMinSparkZ = (CWeather::WindClipped * fWave2Ampl + 0.05f +\n\t\tCWeather::WindClipped * 0.4f + 0.2) * (1.0f - 0.04f * CWeather::SunGlare);\n\n\tint32 randval = CGeneral::GetRandomNumber();\n\n\tfloat fUVStep = 0.125f;\n\tfloat f27 = 2.0f;\n\n\tfloat fMinU = (fUOffset / 16.0f) + _TEXTURE_MASK_ADDU;\n\tfloat fMinV = (fVOffset / 16.0f) + _TEXTURE_MASK_ADDV;\n\n\tfloat fAlphaMul = ((float)color.alpha * 0.4f) / 16.0f;\n\n\tfloat fXOffset = 16.0f;\n\tif (nCamDirX > 0)\n\t\tfXOffset = 6.4f;\n\telse if (nCamDirX < 0)\n\t\tfXOffset = 25.6f;\n\n\tfloat fYOffset = 16.0f;\n\tif (nCamDirY > 0)\n\t\tfYOffset = 6.4f;\n\telse if (nCamDirY < 0)\n\t\tfYOffset = 25.6f;\n\n\tint16 nX = _RoundValue(nSecsX - 1);\n\tint16 nY = _RoundValue(nSecsY - 1);\n#else\n\tfloat fMinSparkZ = (fWave2Ampl * CWeather::WindClipped + 0.05f + \n\t\t\t0.4f * CWeather::WindClipped + 0.2) * (1.0f - 0.02f * CWeather::SunGlare);\n\n\tint32 randval = CGeneral::GetRandomNumber() & 255;\n\n\tint16 nX = _RoundValue((int32)((fX - fSectorX) * 0.5f) - 1);\n\tint16 nY = _RoundValue((int32)((fY - fSectorY) * 0.5f) - 1);\n#endif\n\tint16 idxX = nX;\n\t\n\tfor ( int32 i = 0; i < 17; i++ )\n\t{\n\t\tint16 idxY = nY;\n\n\t\tif ( ++idxX > 16 )\n\t\t\t\tidxX -= 16;\n\t\t\t\n\t\tfor ( int32 j = 0; j < 17; j++ )\n\t\t{\n\t\t\tif ( ++idxY > 16 )\n\t\t\t\tidxY -= 16;\n\t\t\t\n\t\t\tconst int32 a = (0*16);\n\t\t\tconst int32 b = (1*16);\n\t\t\tconst int32 c = (33*16);\n\t\t\tconst int32 d = (34*16);\n\t\t\t\n\t\t\tint32 base = (i*33+j);\n\t\t\t\n#ifndef  PC_WATER\n\t\t\tmaskTexCoords[base + a].u = fMinU + ((float)i * fUVStep);\n\t\t\tmaskTexCoords[base + a].v = fMinV + ((float)j * fUVStep);\n\n\t\t\tmaskTexCoords[base + b].u = maskTexCoords[base + a].u;\n\t\t\tmaskTexCoords[base + b].v = maskTexCoords[base + a].v + (16.0f * fUVStep);\n\n\t\t\tmaskTexCoords[base + c].u = maskTexCoords[base + a].u + (16.0f * fUVStep);\n\t\t\tmaskTexCoords[base + c].v = maskTexCoords[base + a].v;\n\n\t\t\tmaskTexCoords[base + d].u = maskTexCoords[base + a].u + (16.0f * fUVStep);\n\t\t\tmaskTexCoords[base + d].v = maskTexCoords[base + a].v + (16.0f * fUVStep);\n#else\n\t\t\tmaskTexCoords[base+a].v = float(j) / SMALL_SECTOR_SIZE + ((fCamPosY - fY) / 64);\n\t\t\tmaskTexCoords[base+c].v = maskTexCoords[base+a].v;\n\t\t\tmaskTexCoords[base+d].v = maskTexCoords[base+a].v + 0.5f;\n\t\t\tmaskTexCoords[base+b].v = maskTexCoords[base+d].v;\n\t\t\t\n\t\t\tmaskTexCoords[base+a].u = float(i) / SMALL_SECTOR_SIZE + ((fCamPosX - fX) / 64);\n\t\t\tmaskTexCoords[base+b].u = maskTexCoords[base+a].u;\n\t\t\tmaskTexCoords[base+d].u = maskTexCoords[base+a].u + 0.5f;\n\t\t\tmaskTexCoords[base+c].u = maskTexCoords[base+d].u;\n#endif\n\t\t\t\n\t\t\tmaskMorphVerts[base+a].x = (wavyMorphVerts[idxY + (17 * idxX)].x - (float)idxX * 2.0f) + (float(i) * 2.0f);\n\t\t\tmaskMorphVerts[base+b].x = maskMorphVerts[base+a].x;\n\t\t\tmaskMorphVerts[base+c].x = maskMorphVerts[base+a].x + SMALL_SECTOR_SIZE;\n\t\t\tmaskMorphVerts[base+d].x = maskMorphVerts[base+c].x;\n\t\t\t\n\t\t\tmaskMorphVerts[base+a].y = (wavyMorphVerts[idxY + (17 * idxX)].y - (float)idxY * 2.0f) + (float(j) * 2.0f);\n\t\t\tmaskMorphVerts[base+c].y = maskMorphVerts[base+a].y;\n\t\t\tmaskMorphVerts[base+b].y = maskMorphVerts[base+a].y + SMALL_SECTOR_SIZE;\n\t\t\tmaskMorphVerts[base+d].y = maskMorphVerts[base+b].y;\n\t\t\t\n\t\t\tmaskMorphVerts[base+a].z = wavyMorphVerts[idxY + (17 * idxX)].z;\n\t\t\tmaskMorphVerts[base+d].z = maskMorphVerts[base+a].z;\n\t\t\tmaskMorphVerts[base+c].z = maskMorphVerts[base+d].z;\n\t\t\tmaskMorphVerts[base+b].z = maskMorphVerts[base+c].z;\n\t\t\t\n#ifndef PC_WATER\n\t\t\tif (maskMorphVerts[base].z >= fMinSparkZ)\n#else\n\t\t\tif ( maskMorphVerts[base].z > fMinSparkZ )\n#endif\n\t\t\t{\n\t\t\t\tswitch ( (i + j + randval) & 3 )\n\t\t\t\t{\n\t\t\t\t\tcase 0:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tCVector vecPos\n\t\t\t\t\t\t\t(\n\t\t\t\t\t\t\t\tfX + maskMorphVerts[base+a].x,\n\t\t\t\t\t\t\t\tfY + maskMorphVerts[base+a].y,\n\t\t\t\t\t\t\t\tfZ + maskMorphVerts[base+a].z + 0.12f\n\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\tvecPos -= 0.05f * TheCamera.GetForward();\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_WATER_SPARK,\n\t\t\t\t\t\t\t\tvecPos,\n\t\t\t\t\t\t\t\tCVector(0.0f, 0.0f, 0.0f),\n\t\t\t\t\t\t\t\tnil,\n\t\t\t\t\t\t\t\t0.0f,\n\t\t\t\t\t\t\t\t15,\n\t\t\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(-90, 90),\n\t\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t\t0);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 1:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tCVector vecPos\n\t\t\t\t\t\t\t(\n\t\t\t\t\t\t\t\tfX + maskMorphVerts[base+c].x,\n\t\t\t\t\t\t\t\tfY + maskMorphVerts[base+c].y,\n\t\t\t\t\t\t\t\tfZ + maskMorphVerts[base+c].z + 0.12f\n\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\tvecPos -= 0.05f * TheCamera.GetForward();\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_WATER_SPARK,\n\t\t\t\t\t\t\t\tvecPos,\n\t\t\t\t\t\t\t\tCVector(0.0f, 0.0f, 0.0f),\n\t\t\t\t\t\t\t\tnil,\n\t\t\t\t\t\t\t\t0.0f,\n\t\t\t\t\t\t\t\t15,\n\t\t\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(-90, 90),\n\t\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t\t0);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 2:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tCVector vecPos\n\t\t\t\t\t\t\t(\n\t\t\t\t\t\t\t\tfX + maskMorphVerts[base+b].x,\n\t\t\t\t\t\t\t\tfY + maskMorphVerts[base+b].y,\n\t\t\t\t\t\t\t\tfZ + maskMorphVerts[base+b].z + 0.12f\n\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\tvecPos -= 0.05f * TheCamera.GetForward();\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_WATER_SPARK,\n\t\t\t\t\t\t\t\tvecPos,\n\t\t\t\t\t\t\t\tCVector(0.0f, 0.0f, 0.0f),\n\t\t\t\t\t\t\t\tnil,\n\t\t\t\t\t\t\t\t0.0f,\n\t\t\t\t\t\t\t\t15,\n\t\t\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(-90, 90),\n\t\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t\t0);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 3:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tCVector vecPos\n\t\t\t\t\t\t\t(\n\t\t\t\t\t\t\t\tfX + maskMorphVerts[base+d].x,\n\t\t\t\t\t\t\t\tfY + maskMorphVerts[base+d].y,\n\t\t\t\t\t\t\t\tfZ + maskMorphVerts[base+d].z + 0.12f\n\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\tvecPos -= 0.05f * TheCamera.GetForward();\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_WATER_SPARK,\n\t\t\t\t\t\t\t\tvecPos,\n\t\t\t\t\t\t\t\tCVector(0.0f, 0.0f, 0.0f),\n\t\t\t\t\t\t\t\tnil,\n\t\t\t\t\t\t\t\t0.0f,\n\t\t\t\t\t\t\t\t15,\n\t\t\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(-90, 90),\n\t\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t\t0);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tmaskMorphNormals[base+a].x = wavyMorphNormals[idxY + (17 * idxX)].x;\n\t\t\tmaskMorphNormals[base+a].y = wavyMorphNormals[idxY + (17 * idxX)].y;\n\t\t\tmaskMorphNormals[base+a].z = wavyMorphNormals[idxY + (17 * idxX)].z;\n\t\t\t\n\t\t\tmaskMorphNormals[base+d].x = maskMorphNormals[base+a].x;\n\t\t\tmaskMorphNormals[base+d].y = maskMorphNormals[base+a].y;\n\t\t\tmaskMorphNormals[base+d].z = maskMorphNormals[base+a].z;\n\t\t\t\n\t\t\tmaskMorphNormals[base+c].x = maskMorphNormals[base+d].x;\n\t\t\tmaskMorphNormals[base+c].y = maskMorphNormals[base+d].y;\n\t\t\tmaskMorphNormals[base+c].z = maskMorphNormals[base+d].z;\n\t\t\t\n\t\t\tmaskMorphNormals[base+b].x = maskMorphNormals[base+c].x;\n\t\t\tmaskMorphNormals[base+b].y = maskMorphNormals[base+c].y;\n\t\t\tmaskMorphNormals[base+b].z = maskMorphNormals[base+c].z;\n\t  \n\t\t\tmaskPreLight[base+a].red   = color.red;\n\t\t\tmaskPreLight[base+a].green = color.green;\n\t\t\tmaskPreLight[base+a].blue  = color.blue;\n\t\t\tmaskPreLight[base+a].alpha = color.alpha;\n\t\t\t\n\t\t\tmaskPreLight[base+d].red   = maskPreLight[base+a].red;\n\t\t\tmaskPreLight[base+d].green = maskPreLight[base+a].green;\n\t\t\tmaskPreLight[base+d].blue  = maskPreLight[base+a].blue;\n\t\t\tmaskPreLight[base+d].alpha = maskPreLight[base+a].alpha;\n\t\t\t\n\t\t\tmaskPreLight[base+c].red   = maskPreLight[base+d].red;\n\t\t\tmaskPreLight[base+c].green = maskPreLight[base+d].green;\n\t\t\tmaskPreLight[base+c].blue  = maskPreLight[base+d].blue;\n\t\t\tmaskPreLight[base+c].alpha = maskPreLight[base+d].alpha;\n\t\t\t\n\t\t\tmaskPreLight[base+b].red   = maskPreLight[base+c].red;\n\t\t\tmaskPreLight[base+b].green = maskPreLight[base+c].green;\n\t\t\tmaskPreLight[base+b].blue  = maskPreLight[base+c].blue;\n\t\t\tmaskPreLight[base+b].alpha = maskPreLight[base+c].alpha;\n\n#ifndef PC_WATER\n\t\t\tmaskPreLight[base + a].alpha = Max(0, (int32)((float)color.alpha - (fAlphaMul * (Abs((float)i - fXOffset) + Abs((float)j - fYOffset)))));\n\t\t\tmaskPreLight[base + b].alpha = Max(0, (int32)((float)color.alpha - (fAlphaMul * (Abs((float)i - fXOffset) + Abs(16.0f + (float)j - fYOffset)))));\n\t\t\tmaskPreLight[base + c].alpha = Max(0, (int32)((float)color.alpha - (fAlphaMul * (Abs(16.0f + (float)i - fXOffset) + Abs((float)j - fYOffset)))));\n\t\t\tmaskPreLight[base + d].alpha = Max(0, (int32)((float)color.alpha - (fAlphaMul * (Abs(16.0f + (float)i - fXOffset) + Abs(16.0f + (float)j - fYOffset)))));\n#endif\n\t\t}\n\t}\n\t\n\tRpGeometryUnlock(maskGeometry);\n\n#ifndef PC_WATER\n\t{\n\t\tRwV3d pos = { 0.0f, 0.0f, 0.0f };\n\n\t\tpos.x = fX;\n\t\tpos.y = fY;\n\t\tpos.z = fZ + 0.05f;\n\n\t\tRwFrameTranslate(RpAtomicGetFrame(ms_pMaskAtomic), &pos, rwCOMBINEREPLACE);\n\n\t\tif (bRender)\n\t\t{\n#ifdef PS2\n\t\t\tRpSkyTexCacheFlush();\n#endif\n\t\t\tRpAtomicRender(ms_pMaskAtomic);\n\t\t}\n\t}\n#endif\n}\n\n#ifdef PC_WATER\nvoid\nCWaterLevel::PreCalcWaterGeometry(void)\n{\n\tif ( !RequireWavySector )\n\t{\n\t\tWavesCalculatedThisFrame = false;\n\t\tMaskCalculatedThisFrame = false;\n\t\treturn;\n\t}\n\t\n\tRequireWavySector = false;\n\tWavesCalculatedThisFrame = true;\n\t\n\tRwRGBA color;\n\t\n\tcolor.red   = CTimeCycle::GetWaterRed();\n\tcolor.green = CTimeCycle::GetWaterGreen();\n\tcolor.blue  = CTimeCycle::GetWaterBlue();\n\tcolor.alpha = CTimeCycle::GetWaterAlpha();\n\t\n\tPreCalcWavySector(color);\n\t\n\tif ( CCullZones::WaterFudge() )\n\t{\n\t\tMaskCalculatedThisFrame = false;\n\t\treturn;\n\t}\n\t\n\tCVector CamFwdDir = TheCamera.GetForward();\n\tCamFwdDir.z = 0.0f;\n\tCamFwdDir.Normalise();\n\t\n\tfloat fCamX = TheCamera.GetPosition().x - SMALL_SECTOR_SIZE;\n\tfloat fCamY = TheCamera.GetPosition().y - SMALL_SECTOR_SIZE;\n\t\n\t//1.4144272f; 1.4144f;\n\tfloat signX = CamFwdDir.x * 1.4144272f;\n\tfloat signY = CamFwdDir.y * 1.4144272f;\n\t\n\tsignX = clamp(signX, -1.0f, 1.0f);\n\tfCamX += 0.4f * signX * float(SMALL_SECTOR_SIZE * 2.0f);\n\n\tsignY = clamp(signY, -1.0f, 1.0f);\n\tfCamY += 0.4f * signY * float(SMALL_SECTOR_SIZE * 2.0f);\n\t\n\tint32 nBlock;\n\t\n\tint32 BlockX = WATER_TO_SMALL_SECTOR_X(fCamX + WATER_X_OFFSET) + 1;\n\tint32 BlockY = WATER_TO_SMALL_SECTOR_Y(fCamY                 ) + 1;\n\t\n\tASSERT( BlockX >= 0 && BlockX < MAX_SMALL_SECTORS );\n\tASSERT( BlockY >= 0 && BlockY < MAX_SMALL_SECTORS );\n\t\n\tif ( _IsColideWithBlock(BlockX, BlockY, nBlock) )\n\t{\n\t\tfloat fMaskX = Floor(fCamX / 2.0f) * 2.0f;\n\t\tfloat fMaskY = Floor(fCamY / 2.0f) * 2.0f;\n\n\t\tfloat fSectorX = WATER_FROM_SMALL_SECTOR_X(BlockX) - WATER_X_OFFSET;\n\t\tfloat fSectorY = WATER_FROM_SMALL_SECTOR_Y(BlockY);\n\t\t\n\t\tif ( PreCalcWavyMask( fMaskX, fMaskY, ms_aWaterZs[nBlock],\n\t\t\t\tfSectorX, fSectorY, fCamX, fCamY, CamFwdDir.x, CamFwdDir.y, color ) )\n        {\n\t\t\tPreCalculatedMaskPosn.x = fMaskX;\n\t\t\tPreCalculatedMaskPosn.y = fMaskY;\n\t\t\tPreCalculatedMaskPosn.z = ms_aWaterZs[nBlock] + 0.05f;\n\t\t\t\n\t\t\tMaskCalculatedThisFrame = true;\n\t\t}\n\t\telse\n\t\t\tMaskCalculatedThisFrame = false;\n\t}\n\telse\n\t\tMaskCalculatedThisFrame = false;\n}\n\nbool\nCWaterLevel::PreCalcWavySector(RwRGBA const &color)\n{\t\n\tfloat fAngle = (CTimer::GetTimeInMilliseconds() & 4095) * (TWOPI / 4096.0f);\n\t\n\tRpGeometry *wavyGeometry   = RpAtomicGetGeometry(ms_pWavyAtomic);\n\n\tRwTexCoords *wavyTexCoords = RpGeometryGetVertexTexCoords(wavyGeometry, rwTEXTURECOORDINATEINDEX0);\n\tRpMorphTarget *wavyMorph   = RpGeometryGetMorphTarget(wavyGeometry, 0);\n\t\n\tRwRGBA *wavyPreLight       = RpGeometryGetPreLightColors(wavyGeometry);\n\tRwV3d *wavyMorphVerts      = RpMorphTargetGetVertices(wavyMorph);\n\tRwV3d *wavyMorphNormals    = RpMorphTargetGetVertexNormals(wavyMorph);\n\t\n\tif ( !m_bRenderSeaBed )\n\t\tRpGeometryLock(wavyGeometry, rpGEOMETRYLOCKVERTICES\n\t\t\t\t\t\t\t\t\t|rpGEOMETRYLOCKNORMALS\n\t\t\t\t\t\t\t\t\t|rpGEOMETRYLOCKPRELIGHT\n\t\t\t\t\t\t\t\t\t|rpGEOMETRYLOCKTEXCOORDS);\n\t\n\tCVector camPosUp = TheCamera.GetForward();\n\t\t\n\tfloat randomDampInv2 = (1.0f - fRandomDamp) * 2.0f;\n\t\n\tfloat randomMove = 1.0f / (16.0f * fRandomMoveDiv);\n\t\n\tfloat wind     = CWeather::WindClipped * 0.4f + 0.2f;\n\tfloat waveWind = CWeather::WindClipped * fWave2Ampl + 0.05f;\n\n\tfloat waveA = (TWOPI / 16.0f)\n\t\t* ((CWeather::WindClipped * 0.4f + 0.2f) * (fNormalDirectionScalar1 * Abs(camPosUp.x + camPosUp.y) + fNormMult));\n\t\t\n\tfloat waveB = TWOPI / (16.0f * fWave2NormScale)\n\t\t* ((CWeather::WindClipped * 0.2f + 0.1f) * (fNormalDirectionScalar2 * Abs(camPosUp.y - camPosUp.x) + fNormMultB));\n\n\t\n\tCVector vA(1.0f, 0.0f, 0.0f);\n\tCVector vB(0.0f, 1.0f, 0.0f);\n\t\t\t\n\tfor ( int32 i = 0; i < 17; i++ )\n\t{\n\t\tfor ( int32 j = 0; j < 17; j++ )\n\t\t{\n\t\t\twavyTexCoords->u = (float(i) / 16.0f) + TEXTURE_ADDV;\n\t\t\twavyTexCoords->v = (float(j) / 16.0f) + TEXTURE_ADDU;\n\n\t\t\tRwRGBAAssign(wavyPreLight, &color);\n\t\t\t\n\t\t\tif ( i > 0 && i < 16 && j > 0 && j < 16 )\n\t\t\t{\n\t\t\t\twavyMorphVerts->x += CGeneral::GetRandomNumberInRange(-1.0f, 1.0f) * randomMove;\n\t\t\t\twavyMorphVerts->x *= fRandomDamp;\n\t\t\t\twavyMorphVerts->x += float(i) * randomDampInv2;\n\t\t\t\t\n\t\t\t\twavyMorphVerts->y += CGeneral::GetRandomNumberInRange(-1.0f, 1.0f) * randomMove;\n\t\t\t\twavyMorphVerts->y *= fRandomDamp;\n\t\t\t\twavyMorphVerts->y += float(j) * randomDampInv2;\n\t\t\t}\n\t\t\t\n\t\t\tfloat morphVertXHalf = ( i == 16 ) ? 0.0f : 0.5f * wavyMorphVerts->x;\n\t\t\tfloat morphVertYHalf = ( j == 16 ) ? 0.0f : 0.5f * wavyMorphVerts->y;\n\t\t\t\n\t\t\tfloat waveMulA = (morphVertYHalf + morphVertXHalf) * (TWOPI / 16.0f) + fAngle;\t  \n\t\t\tfloat waveMulB = (morphVertYHalf - morphVertXHalf) * (TWOPI / (16.0f * fWave2InvLength)) + fAngle;\t\t\n\t\n\t\t\twavyMorphVerts->z = wind * Sin(waveMulA) + waveWind * Sin(waveMulB);\n\t\t\t\n\t\t\tvA.z = (waveA * Cos(waveMulA)) - (waveB * Cos(waveMulB));\n\t\t\tvB.z = (waveA * Cos(waveMulA)) + (waveB * Cos(waveMulB));\n\n\t\t\tCVector norm = CrossProduct(vA, vB);\n\t\t\tnorm.Normalise();\n\n\t\t\twavyMorphNormals->x = norm.x;\n\t\t\twavyMorphNormals->y = norm.y;\n\t\t\twavyMorphNormals->z = norm.z;\n\n\t\t\t++wavyPreLight;\n\t\t\t++wavyTexCoords;\n\n\t\t\t++wavyMorphVerts;\n\t\t\t++wavyMorphNormals;\n\t\t}\n\t}\n\n\tRpGeometryUnlock(wavyGeometry);\n\t\n\treturn true;\n}\n\nbool\nCWaterLevel::PreCalcWavyMask(float fX, float fY, float fZ,\n\t\tfloat fSectorX, float fSectorY,\n\t\tfloat fCamPosX, float fCamPosY,\n\t\tfloat fCamDirX, float fCamDirY,\n\t\tRwRGBA const&color)\n{\n\tCVector vecSectorPos(fX + (MAX_LARGE_SECTORS/2), fY + (MAX_LARGE_SECTORS/2), fZ + 2.0f);\n\t\n\tif ( COcclusion::IsAABoxOccluded(vecSectorPos, MAX_LARGE_SECTORS, MAX_LARGE_SECTORS, 4.0f) )\n\t\treturn false;\n\t\n\tFloor(fX / MAX_LARGE_SECTORS);\n\tFloor(fY / MAX_LARGE_SECTORS);\n\t\n\tRpGeometry    *wavyGeometry  = RpAtomicGetGeometry(ms_pWavyAtomic);\n\tRpMorphTarget *wavyMorph     = RpGeometryGetMorphTarget(wavyGeometry, 0);\n\tRwV3d *wavyMorphVerts        = RpMorphTargetGetVertices(wavyMorph);\n\tRwV3d *wavyMorphNormals      = RpMorphTargetGetVertexNormals(wavyMorph);\n\t\n\tRpGeometry    *maskGeometry  = RpAtomicGetGeometry(ms_pMaskAtomic);\n\tRwTexCoords   *maskTexCoords = RpGeometryGetVertexTexCoords(maskGeometry, rwTEXTURECOORDINATEINDEX0);\n\tRwRGBA        *maskPreLight  = RpGeometryGetPreLightColors(maskGeometry);\n\tRpMorphTarget *maskMorph     = RpGeometryGetMorphTarget(maskGeometry, 0);\n\tRwV3d *maskMorphVerts        = RpMorphTargetGetVertices(maskMorph);\n\tRwV3d *maskMorphNormals      = RpMorphTargetGetVertexNormals(maskMorph);\n\n\tif ( !m_bRenderSeaBed )\n\t\tRpGeometryLock(maskGeometry, rpGEOMETRYLOCKVERTICES | rpGEOMETRYLOCKNORMALS | rpGEOMETRYLOCKPRELIGHT | rpGEOMETRYLOCKTEXCOORDS);\n\t\n\t\n\tfloat fMinSparkZ = (fWave2Ampl * CWeather::WindClipped + 0.05f + \n\t\t\t0.4f * CWeather::WindClipped + 0.2) * (1.0f - 0.02f * CWeather::SunGlare);\n\t\n\tint32 randval = CGeneral::GetRandomNumber() & 255;\n\n\tint16 nX = _RoundValue((int32)((fX - fSectorX) * 0.5f) - 1);\n\tint16 nY = _RoundValue((int32)((fY - fSectorY) * 0.5f) - 1);\n\t\n\tint16 idxX = nX;\n\n\tfor ( int32 i = 0; i < 17; i++ )\n\t{\t\t\n\t\tint16 idxY = nY;\n\n\t\tif ( ++idxX > 16 )\n\t\t\t\tidxX -= 16;\n\t\t\t\n\t\tfor ( int32 j = 0; j < 17; j++ )\n\t\t{\n\t\t\tif ( ++idxY > 16 )\n\t\t\t\tidxY -= 16;\n\t\t\t\n\t\t\tconst int32 a = (0*16);\n\t\t\tconst int32 b = (1*16);\n\t\t\tconst int32 c = (33*16);\n\t\t\tconst int32 d = (34*16);\n\t\t\t\n\t\t\tint32 base = (i*33+j);\n\t\t\t\n\t\t\tmaskTexCoords[base+a].v = float(j) / 32 + ((fCamPosY - fY) / 64);\n\t\t\tmaskTexCoords[base+c].v = maskTexCoords[base+a].v;\n\t\t\tmaskTexCoords[base+d].v = maskTexCoords[base+a].v + 0.5f;\n\t\t\tmaskTexCoords[base+b].v = maskTexCoords[base+d].v;\n\t\t\t\n\t\t\tmaskTexCoords[base+a].u = float(i) / 32 + ((fCamPosX - fX) / 64);\n\t\t\tmaskTexCoords[base+b].u = maskTexCoords[base+a].u;\n\t\t\tmaskTexCoords[base+d].u = maskTexCoords[base+a].u + 0.5f;\n\t\t\tmaskTexCoords[base+c].u = maskTexCoords[base+d].u;\n\t\t\t\n\t\t\tmaskMorphVerts[base+a].x = (wavyMorphVerts[idxY + (17 * idxX)].x - (float)idxX * 2.0f) + (float(i) * 2.0f);\n\t\t\tmaskMorphVerts[base+b].x = maskMorphVerts[base+a].x;\n\t\t\tmaskMorphVerts[base+c].x = maskMorphVerts[base+a].x + SMALL_SECTOR_SIZE;\n\t\t\tmaskMorphVerts[base+d].x = maskMorphVerts[base+c].x;\n\t\t\t\n\t\t\tmaskMorphVerts[base+a].y = (wavyMorphVerts[idxY + (17 * idxX)].y - (float)idxY * 2.0f) + (float(j) * 2.0f);\n\t\t\tmaskMorphVerts[base+c].y = maskMorphVerts[base+a].y;\n\t\t\tmaskMorphVerts[base+b].y = maskMorphVerts[base+a].y + SMALL_SECTOR_SIZE;\n\t\t\tmaskMorphVerts[base+d].y = maskMorphVerts[base+b].y;\n\t\t\t\n\t\t\tmaskMorphVerts[base+a].z = wavyMorphVerts[idxY + (17 * idxX)].z;\n\t\t\tmaskMorphVerts[base+d].z = maskMorphVerts[base+a].z;\n\t\t\tmaskMorphVerts[base+c].z = maskMorphVerts[base+d].z;\n\t\t\tmaskMorphVerts[base+b].z = maskMorphVerts[base+c].z;\n\t\t\t\n\t\t\tif ( maskMorphVerts[base].z > fMinSparkZ )\n\t\t\t{\n\t\t\t\tswitch ( (i + j + randval) & 3 )\n\t\t\t\t{\n\t\t\t\t\tcase 0:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tCVector vecPos\n\t\t\t\t\t\t\t(\n\t\t\t\t\t\t\t\tfX + maskMorphVerts[base+a].x,\n\t\t\t\t\t\t\t\tfY + maskMorphVerts[base+a].y,\n\t\t\t\t\t\t\t\tfZ + maskMorphVerts[base+a].z + 0.12f\n\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\tvecPos -= 0.05f * TheCamera.GetForward();\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_WATER_SPARK,\n\t\t\t\t\t\t\t\tvecPos,\n\t\t\t\t\t\t\t\tCVector(0.0f, 0.0f, 0.0f),\n\t\t\t\t\t\t\t\tnil,\n\t\t\t\t\t\t\t\t0.0f,\n\t\t\t\t\t\t\t\t15,\n\t\t\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(-90, 90),\n\t\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t\t0);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 1:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tCVector vecPos\n\t\t\t\t\t\t\t(\n\t\t\t\t\t\t\t\tfX + maskMorphVerts[base+c].x,\n\t\t\t\t\t\t\t\tfY + maskMorphVerts[base+c].y,\n\t\t\t\t\t\t\t\tfZ + maskMorphVerts[base+c].z + 0.12f\n\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\tvecPos -= 0.05f * TheCamera.GetForward();\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_WATER_SPARK,\n\t\t\t\t\t\t\t\tvecPos,\n\t\t\t\t\t\t\t\tCVector(0.0f, 0.0f, 0.0f),\n\t\t\t\t\t\t\t\tnil,\n\t\t\t\t\t\t\t\t0.0f,\n\t\t\t\t\t\t\t\t15,\n\t\t\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(-90, 90),\n\t\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t\t0);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 2:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tCVector vecPos\n\t\t\t\t\t\t\t(\n\t\t\t\t\t\t\t\tfX + maskMorphVerts[base+b].x,\n\t\t\t\t\t\t\t\tfY + maskMorphVerts[base+b].y,\n\t\t\t\t\t\t\t\tfZ + maskMorphVerts[base+b].z + 0.12f\n\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\tvecPos -= 0.05f * TheCamera.GetForward();\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_WATER_SPARK,\n\t\t\t\t\t\t\t\tvecPos,\n\t\t\t\t\t\t\t\tCVector(0.0f, 0.0f, 0.0f),\n\t\t\t\t\t\t\t\tnil,\n\t\t\t\t\t\t\t\t0.0f,\n\t\t\t\t\t\t\t\t15,\n\t\t\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(-90, 90),\n\t\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t\t0);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 3:\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tCVector vecPos\n\t\t\t\t\t\t\t(\n\t\t\t\t\t\t\t\tfX + maskMorphVerts[base+d].x,\n\t\t\t\t\t\t\t\tfY + maskMorphVerts[base+d].y,\n\t\t\t\t\t\t\t\tfZ + maskMorphVerts[base+d].z + 0.12f\n\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\tvecPos -= 0.05f * TheCamera.GetForward();\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_WATER_SPARK,\n\t\t\t\t\t\t\t\tvecPos,\n\t\t\t\t\t\t\t\tCVector(0.0f, 0.0f, 0.0f),\n\t\t\t\t\t\t\t\tnil,\n\t\t\t\t\t\t\t\t0.0f,\n\t\t\t\t\t\t\t\t15,\n\t\t\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(-90, 90),\n\t\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t\t0);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tmaskMorphNormals[base+a].x = wavyMorphNormals[idxY + (17 * idxX)].x;\n\t\t\tmaskMorphNormals[base+a].y = wavyMorphNormals[idxY + (17 * idxX)].y;\n\t\t\tmaskMorphNormals[base+a].z = wavyMorphNormals[idxY + (17 * idxX)].z;\n\t\t\t\n\t\t\tmaskMorphNormals[base+d].x = maskMorphNormals[base+a].x;\n\t\t\tmaskMorphNormals[base+d].y = maskMorphNormals[base+a].y;\n\t\t\tmaskMorphNormals[base+d].z = maskMorphNormals[base+a].z;\n\t\t\t\n\t\t\tmaskMorphNormals[base+c].x = maskMorphNormals[base+d].x;\n\t\t\tmaskMorphNormals[base+c].y = maskMorphNormals[base+d].y;\n\t\t\tmaskMorphNormals[base+c].z = maskMorphNormals[base+d].z;\n\t\t\t\n\t\t\tmaskMorphNormals[base+b].x = maskMorphNormals[base+c].x;\n\t\t\tmaskMorphNormals[base+b].y = maskMorphNormals[base+c].y;\n\t\t\tmaskMorphNormals[base+b].z = maskMorphNormals[base+c].z;\n\t  \n\t\t\tmaskPreLight[base+a].red   = color.red;\n\t\t\tmaskPreLight[base+a].green = color.green;\n\t\t\tmaskPreLight[base+a].blue  = color.blue;\n\t\t\tmaskPreLight[base+a].alpha = color.alpha;\n\t\t\t\n\t\t\tmaskPreLight[base+d].red   = maskPreLight[base+a].red;\n\t\t\tmaskPreLight[base+d].green = maskPreLight[base+a].green;\n\t\t\tmaskPreLight[base+d].blue  = maskPreLight[base+a].blue;\n\t\t\tmaskPreLight[base+d].alpha = maskPreLight[base+a].alpha;\n\t\t\t\n\t\t\tmaskPreLight[base+c].red   = maskPreLight[base+d].red;\n\t\t\tmaskPreLight[base+c].green = maskPreLight[base+d].green;\n\t\t\tmaskPreLight[base+c].blue  = maskPreLight[base+d].blue;\n\t\t\tmaskPreLight[base+c].alpha = maskPreLight[base+d].alpha;\n\t\t\t\n\t\t\tmaskPreLight[base+b].red   = maskPreLight[base+c].red;\n\t\t\tmaskPreLight[base+b].green = maskPreLight[base+c].green;\n\t\t\tmaskPreLight[base+b].blue  = maskPreLight[base+c].blue;\n\t\t\tmaskPreLight[base+b].alpha = maskPreLight[base+c].alpha;\n\t\t}\n\t}\n\t\n\tRpGeometryUnlock(maskGeometry);\n\treturn true;\n}\n#endif\n\nvoid\nCWaterLevel::RenderBoatWakes(void)\n{\n\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void *)gpWaterWakeRaster);\n#ifndef PC_WATER\n\tRwRenderStateSet(rwRENDERSTATEFOGENABLE, (void *)TRUE);\n\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDSRCALPHA);\n\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDINVSRCALPHA);\n#endif\n\n#ifdef _XBOX\n\t// TODO save and restore rwRENDERSTATESRCBLEND rwRENDERSTATEDESTBLEND\n#endif\n\n\tCBoat::FillBoatList();\n\t\n\tfloat fWakeZ = 5.97f;\n\tfloat fWakeLifeTimeMult = 0.01f / CBoat::WAKE_LIFETIME;\n\t\n\tfor ( int32 idx = 0; idx < ARRAY_SIZE(CBoat::apFrameWakeGeneratingBoats); idx++ )\n\t{\n\t\tCBoat *pBoat = CBoat::apFrameWakeGeneratingBoats[idx];\n\n\t\tif ( pBoat == nil )\n\t\t\tbreak;\n\n\t\tCVector2D vecDistA(pBoat->GetForward().x, pBoat->GetForward().y);\n\n\n\t\tfloat fSize = pBoat->GetColModel()->boundingBox.max.z\n\t\t\t\t* 0.65f;\n\t\t\n\t\tif ( pBoat->GetModelIndex() == MI_SKIMMER)\n\t\t\tfSize *= 0.4f;\n\t\t\n\t\tfloat fAplhaA = 255.0f;\n\t\tfloat fSizeA = fSize;\n\t\tfloat fAplhaB;\n\t\tfloat fSizeB;\n\t\t\n\t\tfor ( int32 wake = 1; wake < pBoat->m_nNumWakePoints; wake++ )\n\t\t{\n\t\t\tbool bRender = true;\n\t\t\t\n\t\t\tfloat fTimeleft = CBoat::WAKE_LIFETIME - pBoat->m_afWakePointLifeTime[wake];\n\n\t\t\tfloat fWakeSizeB = ((float)wake * 0.19f) + fSize - fWakeLifeTimeMult * Max(fTimeleft, 0.0f);\n\t\t\t\n\t\t\tfSizeB = fWakeSizeB / CBoat::MIN_WAKE_INTERVAL;\n\t\t\tif ( fSizeB < 0.0f )\n\t\t\t\tfSizeB = 1.0f;\n\t\t\t\n\t\t\tif ( wake == pBoat->m_nNumWakePoints - 1 )\n\t\t\t{\n\t\t\t\t// set alpha to 0 if it's last point\n\t\t\t\tfAplhaB = 0.0f;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// clip (-100, 500), less lifetime - less val\n\t\t\t\tfloat val = 500.0f - (CBoat::WAKE_LIFETIME - pBoat->m_afWakePointLifeTime[wake])\n\t\t\t\t\t\t* 600.0f / CBoat::WAKE_LIFETIME;\n\t\t\t\t\t\t\n\t\t\t\tfAplhaB = clamp(val, 0.0f, 255.0f);\n\t\t\t}\n\n\t\t\tCVector2D vecDistB = pBoat->m_avec2dWakePoints[wake - 1] - pBoat->m_avec2dWakePoints[wake];\n\n\t\t\tfloat fScal = vecDistB.MagnitudeSqr();\n\t\t\t\n\t\t\t// normalize if distance between points is greater than 3\n\n\t\t\tif ( fScal > SQR(3.0f) )\n\t\t\t{\t\t\t\t\n\t\t\t\tfloat fNorm = 1.0f / sqrt(fScal);\n\t\t\t\t\n\t\t\t\tvecDistB.x *= fNorm;\n\t\t\t\tvecDistB.y *= fNorm;\n\t\t\t\t\n\t\t\t\t// disable render if distance between points too big\n\t\t\t\t\n\t\t\t\tif ( sqrt(fScal) > 13.0f )\n\t\t\t\t\tbRender = false;\n\t\t\t}\n\t\t\t\n\t\t\tCVector2D vecAA\n\t\t\t(\n\t\t\t\tpBoat->m_avec2dWakePoints[wake - 1].x - (fSizeA * vecDistA.y),\n\t\t\t\tpBoat->m_avec2dWakePoints[wake - 1].y + (fSizeA * vecDistA.x)\n\t\t\t);\n\t\t\tCVector2D vecAB\n\t\t\t(\n\t\t\t\tpBoat->m_avec2dWakePoints[wake - 1].x + (fSizeA * vecDistA.y),\n\t\t\t\tpBoat->m_avec2dWakePoints[wake - 1].y - (fSizeA * vecDistA.x)\n\t\t\t);\n\t\t\tCVector2D vecBA\n\t\t\t(\n\t\t\t\tpBoat->m_avec2dWakePoints[wake].x     + (fSizeB * vecDistB.y),\n\t\t\t\tpBoat->m_avec2dWakePoints[wake].y     - (fSizeB * vecDistB.x)\n\t\t\t);                                                                            \n\t\t\tCVector2D vecBB                         \n\t\t\t(                                       \n\t\t\t\tpBoat->m_avec2dWakePoints[wake].x     - (fSizeB * vecDistB.y),\n\t\t\t\tpBoat->m_avec2dWakePoints[wake].y     + (fSizeB * vecDistB.x)\n\t\t\t);\n\t\t\t\n\t\t\tif ( bRender )\n\t\t\t\tRenderWakeSegment(vecAA, vecAB, vecBA, vecBB, fSizeA, fSizeB, fAplhaA, fAplhaB, fWakeZ);\n\t\t\t\n\t\t\tvecDistA = vecDistB;\n\t\t\tfSizeA = fSizeB;\n\t\t\t\n\t\t\tfAplhaB = fAplhaA;\n\t\t}\n\t}\n\t\n\tRenderAndEmptyRenderBuffer();\n}\n\ninline float\n_GetWindedWave(float fX, float fY)\n{\n\tfloat fAngle = (CTimer::GetTimeInMilliseconds() & 4095) * (TWOPI / 4096.0f);\t\n\tfloat x = WATER_HUGE_X(fX + WATER_X_OFFSET);\n\tfloat y = WATER_HUGE_Y(fY);\n\t\n\tfloat fWindFactor (CWeather::WindClipped * 0.4f + 0.2f);\n\tfloat fWave = Sin(( (x - Floor(x)) + (y - Floor(y)) ) * TWOPI + fAngle);\n\n\treturn fWindFactor * fWave;\n}\n\nvoid\nCWaterLevel::RenderWakeSegment(CVector2D &vecA, CVector2D &vecB, CVector2D &vecC, CVector2D &vecD,\n\t\tfloat &fSizeA, float &fSizeB, \n\t\tfloat &fAlphaA, float &fAlphaB, \n\t\tfloat &fWakeZ)\n{\n\tfor ( int32 i = 0; i < 4; i++ )\n\t{\n\t\tif ( TempBufferIndicesStored >= TEMPBUFFERINDEXSIZE-6 || TempBufferVerticesStored >= TEMPBUFFERVERTSIZE-4 )\n\t\t\tRenderAndEmptyRenderBuffer();\n\t\t\n\t\tfloat fCurStep = (float)i       / 4;\n\t\tfloat fNxtStep = (float)(i + 1) / 4;\n\t\t\n\t\tfloat fLeftCurStep = 1.0f - fCurStep;\n\t\tfloat fLeftNxtStep = 1.0f - fNxtStep;\n\n\t\tuint8 AlphaA = (uint32)(fAlphaA * aAlphaFade[i]    );\n\t\tuint8 AlphaB = (uint32)(fAlphaA * aAlphaFade[i + 1]);\n\t\tuint8 AlphaC = (uint32)(fAlphaB * aAlphaFade[i + 1]);\n\t\tuint8 AlphaD = (uint32)(fAlphaB * aAlphaFade[i]    );\n\n\t\tCVector2D PosA = vecB*fCurStep + vecA*fLeftCurStep;\n\t\tCVector2D PosB = vecB*fNxtStep + vecA*fLeftNxtStep;\n\t\tCVector2D PosC = vecC*fNxtStep + vecD*fLeftNxtStep;\n\t\tCVector2D PosD = vecC*fCurStep + vecD*fLeftCurStep;\n\n\t\tfloat fUA = (PosA.x / 4) + _TEXTURE_WAKE_ADDU;\n\t\tfloat fVA = (PosA.y / 4) + _TEXTURE_WAKE_ADDV;\n\n\t\tfloat fUB = (PosB.x / 4) + _TEXTURE_WAKE_ADDU;\n\t\tfloat fVB = (PosB.y / 4) + _TEXTURE_WAKE_ADDV;\n\n\t\tfloat fUC = (PosC.x / 4) + _TEXTURE_WAKE_ADDU;\n\t\tfloat fVC = (PosC.y / 4) + _TEXTURE_WAKE_ADDV;\n\n\t\tfloat fUD = (PosD.x / 4) + _TEXTURE_WAKE_ADDU;\n\t\tfloat fVD = (PosD.y / 4) + _TEXTURE_WAKE_ADDV;\n\t\t\n#define MIN4(a, b, c, d) (Min((a), Min((b), Min((c), (d)))))\n\t\tfloat fMinU = Floor(MIN4(fUA, fUB, fUC, fUD));\n\t\tfloat fMinV = Floor(MIN4(fVA, fVB, fVC, fVD));\n#undef MIN4\n\n\t\tfloat fZA = _GetWindedWave(PosA.x, PosA.y) + fWakeZ;\n\t\tfloat fZB = _GetWindedWave(PosB.x, PosB.y) + fWakeZ;\n\t\tfloat fZC = _GetWindedWave(PosC.x, PosC.y) + fWakeZ;\n\t\tfloat fZD = _GetWindedWave(PosD.x, PosD.y) + fWakeZ;\n\t\n\t\tint32 vidx = TempBufferVerticesStored;\n\t\n\t\tRwIm3DVertexSetPos  (&TempBufferRenderVertices[vidx + 0], PosA.x, PosA.y, fZA);\n\t\tRwIm3DVertexSetU    (&TempBufferRenderVertices[vidx + 0], fUA - fMinU);\n\t\tRwIm3DVertexSetV    (&TempBufferRenderVertices[vidx + 0], fVA - fMinV);\n\t\tRwIm3DVertexSetRGBA (&TempBufferRenderVertices[vidx + 0], 255, 255, 255, AlphaA);\n\n\t\tRwIm3DVertexSetPos  (&TempBufferRenderVertices[vidx + 1], PosB.x, PosB.y, fZB);\n\t\tRwIm3DVertexSetU    (&TempBufferRenderVertices[vidx + 1], fUB - fMinU);\n\t\tRwIm3DVertexSetV    (&TempBufferRenderVertices[vidx + 1], fVB - fMinV);\n\t\tRwIm3DVertexSetRGBA (&TempBufferRenderVertices[vidx + 1], 255, 255, 255, AlphaB);\n\n\t\tRwIm3DVertexSetPos  (&TempBufferRenderVertices[vidx + 2], PosC.x, PosC.y, fZC);\n\t\tRwIm3DVertexSetU    (&TempBufferRenderVertices[vidx + 2], fUC - fMinU);\n\t\tRwIm3DVertexSetV    (&TempBufferRenderVertices[vidx + 2], fVC - fMinV);\n\t\tRwIm3DVertexSetRGBA (&TempBufferRenderVertices[vidx + 2], 255, 255, 255, AlphaC);\n\n\t\tRwIm3DVertexSetPos  (&TempBufferRenderVertices[vidx + 3], PosD.x, PosD.y, fZD);\n\t\tRwIm3DVertexSetU    (&TempBufferRenderVertices[vidx + 3], fUD - fMinU);\n\t\tRwIm3DVertexSetV    (&TempBufferRenderVertices[vidx + 3], fVD - fMinV);\n\t\tRwIm3DVertexSetRGBA (&TempBufferRenderVertices[vidx + 3], 255, 255, 255, AlphaD);\n\t\t\n\t\tint32 iidx = TempBufferIndicesStored;\n\t\n\t\tTempBufferRenderIndexList[iidx + 0] = TempBufferVerticesStored + 0;\n\t\tTempBufferRenderIndexList[iidx + 1] = TempBufferVerticesStored + 2;\n\t\tTempBufferRenderIndexList[iidx + 2] = TempBufferVerticesStored + 1;\n\t\tTempBufferRenderIndexList[iidx + 3] = TempBufferVerticesStored + 0;\n\t\tTempBufferRenderIndexList[iidx + 4] = TempBufferVerticesStored + 3;\n\t\tTempBufferRenderIndexList[iidx + 5] = TempBufferVerticesStored + 2;\n\t\t\n\t\tTempBufferVerticesStored += 4;\n\t\n\t\tTempBufferIndicesStored += 6;\n\t}\n}\n\nvoid\nCWaterLevel::RenderOneSlopedUnderWaterPoly(float fX, float fY, float fZ, RwRGBA const&color)\n{\n\tCVector2D camPos(TheCamera.GetPosition().x, TheCamera.GetPosition().y);\n\t\n\tfloat fDistA = (CVector2D(fX, fY) - camPos).Magnitude()                                       + -140.0f;\n\tfloat fDistB = (CVector2D(fX, fY + HUGE_SECTOR_SIZE) - camPos).Magnitude()                    + -140.0f;\n\tfloat fDistC = (CVector2D(fX + HUGE_SECTOR_SIZE, fY + HUGE_SECTOR_SIZE) - camPos).Magnitude() + -140.0f;\n\tfloat fDistD = (CVector2D(fX + HUGE_SECTOR_SIZE, fY) - camPos).Magnitude()                    + -140.0f;\n\t\n#ifndef PC_WATER\n#define CALCSEABED(v, d) \\\n\t\t{ \\\n\t\t\tif ( d < 0.0f ) \\\n\t\t\t\tv = 0.1f + fSeaBedZ; \\\n\t\t\telse if ( d > 240.0f ) \\\n\t\t\t\tv = 0.1f; \\\n\t\t\telse \\\n\t\t\t\tv = 0.1f + ((fSeaBedZ * (240.0f - d)) / 240.0f); \\\n\t\t}\n#else\n\t#define CALCSEABED(v, d)\t\\\n\t\t{\t\\\n\t\tv = 0.1f;\t\\\n\t\tif ( d < 0.0f )\t\\\n\t\t\tv += fSeaBedZ;\t\\\n\t\telse if ( d <= 240.0f )\t\\\n\t\t\tv += (fSeaBedZ / 240.0f) * (240.0f - d);\t\\\n\t\t}\n#endif\n\tfloat fSeaBedA, fSeaBedB, fSeaBedC, fSeaBedD;\n\t\n\tCALCSEABED(fSeaBedA, fDistA);\n\tCALCSEABED(fSeaBedB, fDistB);\n\tCALCSEABED(fSeaBedC, fDistC);\n\tCALCSEABED(fSeaBedD, fDistD);\n\t\n\t#undef CALCSEABED\n\t\n\tif ( TempBufferIndicesStored >= TEMPBUFFERINDEXSIZE-6 || TempBufferVerticesStored >= TEMPBUFFERVERTSIZE-4 )\n\t\tRenderAndEmptyRenderBuffer();\n\t\n\tint32 vidx = TempBufferVerticesStored;\n\t\n\tRwIm3DVertexSetPos  (&TempBufferRenderVertices[vidx + 0], fX, fY, fZ - _fWaterZOffset - fSeaBedA);\n\tRwIm3DVertexSetU    (&TempBufferRenderVertices[vidx + 0], 0.0f);\n\tRwIm3DVertexSetV    (&TempBufferRenderVertices[vidx + 0], 0.0f);\n\tRwIm3DVertexSetRGBA(&TempBufferRenderVertices[vidx + 0], color.red, color.green, color.blue, 255);\n\t\n\tRwIm3DVertexSetPos  (&TempBufferRenderVertices[vidx + 1], fX, fY + HUGE_SECTOR_SIZE, fZ - _fWaterZOffset - fSeaBedB);\n\tRwIm3DVertexSetU    (&TempBufferRenderVertices[vidx + 1], 0.0f);\n\tRwIm3DVertexSetV    (&TempBufferRenderVertices[vidx + 1], 4.0f);\n\tRwIm3DVertexSetRGBA(&TempBufferRenderVertices[vidx + 1], color.red, color.green, color.blue, 255);\n\t\n\tRwIm3DVertexSetPos  (&TempBufferRenderVertices[vidx + 2], fX + HUGE_SECTOR_SIZE, fY + HUGE_SECTOR_SIZE, fZ - _fWaterZOffset - fSeaBedC);\n\tRwIm3DVertexSetU    (&TempBufferRenderVertices[vidx + 2], 4.0f);\n\tRwIm3DVertexSetV    (&TempBufferRenderVertices[vidx + 2], 4.0f);\n\tRwIm3DVertexSetRGBA(&TempBufferRenderVertices[vidx + 2], color.red, color.green, color.blue, 255);\n\t\n\tRwIm3DVertexSetPos  (&TempBufferRenderVertices[vidx + 3], fX + HUGE_SECTOR_SIZE, fY, fZ - _fWaterZOffset - fSeaBedD);\n\tRwIm3DVertexSetU    (&TempBufferRenderVertices[vidx + 3], 4.0f);\n\tRwIm3DVertexSetV    (&TempBufferRenderVertices[vidx + 3], 0.0f);\n\tRwIm3DVertexSetRGBA(&TempBufferRenderVertices[vidx + 3], color.red, color.green, color.blue, 255);\n\t\n\tint32 iidx = TempBufferIndicesStored;\n\n\tTempBufferRenderIndexList[iidx + 0] = TempBufferVerticesStored + 0;\n\tTempBufferRenderIndexList[iidx + 1] = TempBufferVerticesStored + 2;\n\tTempBufferRenderIndexList[iidx + 2] = TempBufferVerticesStored + 1;\n\tTempBufferRenderIndexList[iidx + 3] = TempBufferVerticesStored + 0;\n\tTempBufferRenderIndexList[iidx + 4] = TempBufferVerticesStored + 3;\n\tTempBufferRenderIndexList[iidx + 5] = TempBufferVerticesStored + 2;\n\t\n\tTempBufferVerticesStored += 4;\n\n\tTempBufferIndicesStored += 6;\n}\n\nvoid\nCWaterLevel::RenderOneFlatSmallWaterPolyBlended(float fX, float fY, float fZ, float fCamX, float fCamY,\n\t\tRwRGBA const &color, RwRGBA const &colorTrans,\n\t\tfloat fDrawDist)\n{\n\tif ( TempBufferIndicesStored >= TEMPBUFFERINDEXSIZE-6 || TempBufferVerticesStored >= TEMPBUFFERVERTSIZE-4 )\n\t\tRenderAndEmptyRenderBuffer();\n\t\n\tint32 vidx = TempBufferVerticesStored;\n\t\n\tfloat fBlendDrawDist = fDrawDist + fStartBlendDistanceAdd;\n\t\n\tfloat fDistStartX = SQR(fX                       - fCamX);\n\tfloat fDistStartY = SQR(fY                       - fCamY);\n\tfloat fDistEndX   = SQR((fX + SMALL_SECTOR_SIZE) - fCamX);\n\tfloat fDistEndY   = SQR((fY + SMALL_SECTOR_SIZE) - fCamY);\n\t\n\t\n\tfloat fAlphaBlendMulA \n\t\t\t= Min(fFlatWaterBlendRange * Max(sqrt(fDistStartX + fDistStartY) - fBlendDrawDist, fMinWaterAlphaMult), 1.0f);\n\tfloat fAlphaBlendMulB\n\t\t\t= Min(fFlatWaterBlendRange * Max(sqrt(fDistStartX + fDistEndY  ) - fBlendDrawDist, fMinWaterAlphaMult), 1.0f);\n\tfloat fAlphaBlendMulC\n\t\t\t= Min(fFlatWaterBlendRange * Max(sqrt(fDistEndX   + fDistEndY  ) - fBlendDrawDist, fMinWaterAlphaMult), 1.0f);\n\tfloat fAlphaBlendMulD\n\t\t\t= Min(fFlatWaterBlendRange * Max(sqrt(fDistEndX   + fDistStartY) - fBlendDrawDist, fMinWaterAlphaMult), 1.0f);\n\n\n\tRwIm3DVertexSetPos  (&TempBufferRenderVertices[vidx + 0], fX, fY, fZ - _fWaterZOffset);\n\tRwIm3DVertexSetU    (&TempBufferRenderVertices[vidx + 0], TEXTURE_ADDU);\n\tRwIm3DVertexSetV    (&TempBufferRenderVertices[vidx + 0], TEXTURE_ADDV);\n\tRwIm3DVertexSetRGBA(&TempBufferRenderVertices[vidx + 0], color.red, color.green, color.blue,\n\t\t(colorTrans.alpha + (color.alpha - colorTrans.alpha) * (uint8)(int32)fAlphaBlendMulA));\n\t\n\tRwIm3DVertexSetPos  (&TempBufferRenderVertices[vidx + 1], fX, fY + SMALL_SECTOR_SIZE, fZ - _fWaterZOffset);\n\tRwIm3DVertexSetU    (&TempBufferRenderVertices[vidx + 1], TEXTURE_ADDU);\n\tRwIm3DVertexSetV    (&TempBufferRenderVertices[vidx + 1], TEXTURE_ADDV + 1.0f);\n\tRwIm3DVertexSetRGBA(&TempBufferRenderVertices[vidx + 1], color.red, color.green, color.blue,\n\t\t(colorTrans.alpha + (color.alpha - colorTrans.alpha) * (uint8)(int32)fAlphaBlendMulB));\n\t\n\tRwIm3DVertexSetPos  (&TempBufferRenderVertices[vidx + 2], fX + SMALL_SECTOR_SIZE, fY + SMALL_SECTOR_SIZE, fZ - _fWaterZOffset);\n\tRwIm3DVertexSetU    (&TempBufferRenderVertices[vidx + 2], TEXTURE_ADDU + 1.0f);\n\tRwIm3DVertexSetV    (&TempBufferRenderVertices[vidx + 2], TEXTURE_ADDV + 1.0f);\n\tRwIm3DVertexSetRGBA(&TempBufferRenderVertices[vidx + 2], color.red, color.green, color.blue,\n\t\t(colorTrans.alpha + (color.alpha - colorTrans.alpha) * (uint8)(int32)fAlphaBlendMulC));\n\t\n\tRwIm3DVertexSetPos  (&TempBufferRenderVertices[vidx + 3], fX + SMALL_SECTOR_SIZE, fY, fZ - _fWaterZOffset);\n\tRwIm3DVertexSetU    (&TempBufferRenderVertices[vidx + 3], TEXTURE_ADDU + 1.0f);\n\tRwIm3DVertexSetV    (&TempBufferRenderVertices[vidx + 3], TEXTURE_ADDV);\n\tRwIm3DVertexSetRGBA(&TempBufferRenderVertices[vidx + 3], color.red, color.green, color.blue,\n\t\t(colorTrans.alpha + (color.alpha - colorTrans.alpha) * (uint8)(int32)fAlphaBlendMulD));\n\n\n\tint32 iidx = TempBufferIndicesStored;\n\n\tTempBufferRenderIndexList[iidx + 0] = TempBufferVerticesStored + 0;\n\tTempBufferRenderIndexList[iidx + 1] = TempBufferVerticesStored + 2;\n\tTempBufferRenderIndexList[iidx + 2] = TempBufferVerticesStored + 1;\n\tTempBufferRenderIndexList[iidx + 3] = TempBufferVerticesStored + 0;\n\tTempBufferRenderIndexList[iidx + 4] = TempBufferVerticesStored + 3;\n\tTempBufferRenderIndexList[iidx + 5] = TempBufferVerticesStored + 2;\n\t\n\tTempBufferVerticesStored += 4;\n\n\tTempBufferIndicesStored += 6;\n}\n\nfloat\nCWaterLevel::CalcDistanceToWater(float fX, float fY)\n{\n\tconst float fSectorMaxRenderDist = 250.0f;\n\t\n\tint32 nStartX = WATER_TO_SMALL_SECTOR_X(fX - fSectorMaxRenderDist + WATER_X_OFFSET) - 1;\n\tint32 nEndX   = WATER_TO_SMALL_SECTOR_X(fX + fSectorMaxRenderDist + WATER_X_OFFSET) + 1;\n\tint32 nStartY = WATER_TO_SMALL_SECTOR_Y(fY - fSectorMaxRenderDist) - 1;\n\tint32 nEndY   = WATER_TO_SMALL_SECTOR_Y(fY + fSectorMaxRenderDist) + 1;\n\t\n\tnStartX = clamp(nStartX, 0, MAX_SMALL_SECTORS - 1);\n\tnEndX   = clamp(nEndX,   0, MAX_SMALL_SECTORS - 1);\n\tnStartY = clamp(nStartY, 0, MAX_SMALL_SECTORS - 1);\n\tnEndY   = clamp(nEndY,   0, MAX_SMALL_SECTORS - 1);\n\t\n\tfloat fDistSqr = 1.0e10f;\n\t\n\tfor ( int32 x = nStartX; x <= nEndX; x++ )\n\t{\n\t\tfor ( int32 y = nStartY; y <= nEndY; y++ )\n\t\t{\n\t\t\tif ( aWaterFineBlockList[x][y] >= 0 )\n\t\t\t{\t\t\t\t\n\t\t\t\tfloat fSectorX = WATER_FROM_SMALL_SECTOR_X(x) - WATER_X_OFFSET;\n\t\t\t\tfloat fSectorY = WATER_FROM_SMALL_SECTOR_Y(y);\n\t\t\t\t\n\t\t\t\tCVector2D vecDist\n\t\t\t\t(\n\t\t\t\t\tfSectorX + SMALL_SECTOR_SIZE - fX,\n\t\t\t\t\tfSectorY + SMALL_SECTOR_SIZE - fY\n\t\t\t\t);\n\t\t\t\t\n\t\t\t\tfDistSqr = Min(vecDist.MagnitudeSqr(), fDistSqr);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn clamp(Sqrt(fDistSqr) - 23.0f, 0.0f, fSectorMaxRenderDist);\n}\n\nvoid\nCWaterLevel::RenderAndEmptyRenderBuffer()\n{\n\tif ( TempBufferVerticesStored )\n\t{\n\t\tLittleTest();\n\n\t\tif ( RwIm3DTransform(TempBufferRenderVertices, TempBufferVerticesStored, nil, rwIM3D_VERTEXUV) )\n\t\t{\n\t\t\tRwIm3DRenderIndexedPrimitive(rwPRIMTYPETRILIST, TempBufferRenderIndexList, TempBufferIndicesStored);\n\t\t\tRwIm3DEnd();\n\t\t}\n\t}\n\t\n\tTempBufferIndicesStored = 0;\n\tTempBufferVerticesStored = 0;\n}\n\nbool\nCWaterLevel::GetGroundLevel(CVector const &vecPosn, float *pfOutLevel, ColData *pData, float fDistance)\n{\n\tCColPoint point;\n\tCEntity *entity;\n\t\n\tif ( !CWorld::ProcessVerticalLine(vecPosn + CVector(0.0f, 0.0f, fDistance),\n\t\t\t-fDistance, point, entity, true, false, false, false, true, false, nil) )\n\t\treturn false;\n\t\t\n\t*pfOutLevel = point.point.z;\n\t\n\tif ( pData != nil )\n\t{\n\t\tpData->SurfaceType = point.surfaceB;\n\t\tpData->PieceType   = point.pieceB;\n\t}\n\t\n\treturn true;\n}\n\nbool\nCWaterLevel::IsLocationOutOfWorldBounds_WS(CVector const &vecPosn, int nOffset)\n{\n\tint32 x = int32((vecPosn.x / 50.0f) + 48.0f);\n\tint32 y = int32((vecPosn.y / 50.0f) + 40.0f);\n\t\n\treturn x < nOffset || x >= 80 - nOffset || y < nOffset || y >= 80 - nOffset;\n}\n\nbool\nCWaterLevel::GetGroundLevel_WS(CVector const &vecPosn, float *pfOutLevel, ColData *pData, float fDistance)\n{\n\tif ( IsLocationOutOfWorldBounds_WS(vecPosn, 0) )\n\t\treturn false;\n\telse\n\t\treturn GetGroundLevel(vecPosn, pfOutLevel, pData, fDistance);\n}\n\nbool\nCWaterLevel::GetWaterDepth(CVector const &vecPosn, float *pfDepth, float *pfLevelNoWaves, float *pfGroundLevel)\n{\n\tfloat fLevelNoWaves;\n\tfloat fGroundLevel;\n\t\n\tif ( !GetWaterLevelNoWaves(vecPosn.x, vecPosn.y, vecPosn.z, &fLevelNoWaves) )\n\t\treturn false;\n\t\n\tif ( !GetGroundLevel(vecPosn, &fGroundLevel, nil, 30.0f) )\n\t\tfGroundLevel = -100.0;\n\t\n\tif ( pfDepth != nil )\n\t\t*pfDepth = fLevelNoWaves - fGroundLevel;\n\n\tif ( pfLevelNoWaves != nil )\n\t\t*pfLevelNoWaves = fLevelNoWaves;\n\n\tif ( pfGroundLevel != nil )\n\t\t*pfGroundLevel = fGroundLevel;\n\t\n\treturn true;\n}\n\nvoid\nCWaterLevel::RenderSeaBirds()\n{\n\tCVector cur_pos = TheCamera.GetPosition();\n\t\n\tif ( !CCullZones::CamNoRain()\n\t\t&& !CCullZones::PlayerNoRain()\n\t\t&& (CWeather::NewWeatherType == WEATHER_SUNNY || CWeather::NewWeatherType == WEATHER_EXTRA_SUNNY)\n\t\t&& CClock::ms_nGameClockHours > 6 && CClock::ms_nGameClockHours < 20 )\n\t{\n\t\tstatic CVector prev_pos(0.0f, 0.0f, 0.0f);\n\t\tstatic CVector prev_front(0.0f, 0.0f, 0.0f);\n\t\tstatic int32 timecounter;\n\n\t\tif ( Abs(prev_pos.x - cur_pos.x) + Abs(prev_pos.y - cur_pos.y) + Abs(prev_pos.z - cur_pos.z) > 1.5f )\n\t\t{\n\t\t\tprev_pos = cur_pos;\n\t\t\ttimecounter = CTimer::GetTimeInMilliseconds();\n\t\t}\n\t\telse if ( (CTimer::GetTimeInMilliseconds() - timecounter) > 5000 )\n\t\t{\n\t\t\tstatic int32 birdgenTime = 0;\n\t\t\t\n\t\t\tif ( (CTimer::GetTimeInMilliseconds() - birdgenTime) > 1000 )\n\t\t\t{\n\t\t\t\tbirdgenTime = CTimer::GetTimeInMilliseconds();\n\t\t\t\t\n\t\t\t\tCVector vecPos = cur_pos;\n\t\t\t\t\n\t\t\t\tfloat fAngle = CGeneral::GetRandomNumberInRange(90.0f, 150.0f);\n\t\t\t\t\n\t\t\t\tuint16 nSinCosIdx = CGeneral::GetRandomNumber() % (CParticle::SIN_COS_TABLE_SIZE-1);\n\t\t\t\t\n\t\t\t\tfloat fCos = CParticle::Cos(nSinCosIdx);\n\t\t\t\tfloat fSin = CParticle::Sin(nSinCosIdx);\n\n\t\t\t\tvecPos.x += (fCos - fSin) * fAngle;\n\t\t\t\tvecPos.y += (fSin + fCos) * fAngle;\n\t\t\t\tvecPos.z += CGeneral::GetRandomNumberInRange(10.0f, 30.0f);\n\t\t\t\t\n\t\t\t\tCVector vecDir(CGeneral::GetRandomNumberInRange(-1.0f, 1.0f),\n\t\t\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(-1.0f, 1.0f),\n\t\t\t\t\t\t\t\t0.0f);\n\t\t\t\t\n\t\t\t\tCParticle::AddParticle(PARTICLE_BIRD_FRONT, vecPos, vecDir, nil, 0.0f, 0, 0, 0, 0);\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nCWaterLevel::RenderShipsOnHorizon()\n{\n#ifdef FIX_BUGS\n\tCVector cur_pos = FindPlayerCoors();\n#else\n\tCVector cur_pos = FindPlayerPed()->GetPosition();\n#endif\n\n\tstatic CVector prev_pos(0.0f, 0.0f, 0.0f);\n\tstatic CVector prev_front(0.0f, 0.0f, 0.0f);\n\tstatic int32 timecounter;\n\n\tif ( Abs(prev_pos.x - cur_pos.x) + Abs(prev_pos.y - cur_pos.y) + Abs(prev_pos.z - cur_pos.z) > 1.5f )\n\t{\n\t\tprev_pos = cur_pos;\n\t\ttimecounter = CTimer::GetTimeInMilliseconds();\n\t}\n\telse if ( (CTimer::GetTimeInMilliseconds() - timecounter) > 5000 )\n\t{\n\t\tstatic int32 shipgenTime = 0;\n\t\t\n\t\tif ( (CTimer::GetTimeInMilliseconds() - shipgenTime) > 4000 )\n\t\t{\n\t\t\tshipgenTime = CTimer::GetTimeInMilliseconds();\n\t\t\t\n\t\t\tCVector vecPos = cur_pos;\n\t\t\t\n\t\t\tfloat fAngle = CGeneral::GetRandomNumberInRange(450.0f, 750.0f);\n\t\t\t\n\t\t\tuint16 nSinCosIdx = CGeneral::GetRandomNumber() % (CParticle::SIN_COS_TABLE_SIZE-1);\n\t\t\t\n\t\t\tfloat fCos = CParticle::Cos(nSinCosIdx);\n\t\t\tfloat fSin = CParticle::Sin(nSinCosIdx);\n\n\t\t\tvecPos.x += (fCos - fSin) * fAngle;\n\t\t\tvecPos.y += (fSin + fCos) * fAngle;\n\t\t\t\n\t\t\tfloat fLevelNoWaves;\n\t\t\t\n\t\t\tif ( GetWaterLevelNoWaves(vecPos.x, vecPos.y, vecPos.z, &fLevelNoWaves) )\n\t\t\t{\n\t\t\t\tif ( IsLocationOutOfWorldBounds_WS(vecPos, 1) )\n\t\t\t\t{\n\t\t\t\t\tvecPos.z  = fLevelNoWaves + 9.5f;\n\t\t\t\t\t\n\t\t\t\t\tCVector vecDir\n\t\t\t\t\t(\n\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(-0.1f, 0.1f),\n\t\t\t\t\t\t0.0f,\n\t\t\t\t\t\t0.0f\n\t\t\t\t\t);\n\t\t\t\t\t\n\t\t\t\t\tCParticle::AddParticle(PARTICLE_SHIP_SIDE, vecPos, vecDir,\n\t\t\t\t\t\tnil, 0.0f, 0, 0, CGeneral::GetRandomNumber() & 7, 0);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nCWaterLevel::HandleSeaLifeForms()\n{\n\tif ( CReplay::IsPlayingBack() )\n\t\treturn;\n\t\n\tCVector cur_pos = FindPlayerPed()->GetPosition();\n\n\tstatic CVector prev_pos(0.0f, 0.0f, 0.0f);\n\tstatic int32 timecounter;\n\t\n\tif ( Abs(prev_pos.x - cur_pos.x) + Abs(prev_pos.y - cur_pos.y) + Abs(prev_pos.z - cur_pos.z) > 1.5f )\n\t{\n\t\tprev_pos = cur_pos;\n\t\ttimecounter = CTimer::GetTimeInMilliseconds();\n\t}\n\telse if ( (CTimer::GetTimeInMilliseconds() - timecounter) > 5000 )\n\t{\n\tif ( CWaterCreatures::IsSpaceForMoreWaterCreatures() )\n\t\t{\n\t\t\tfor ( int32 i = 0; i < 3; i++ )\n\t\t\t{\n\t\t\t\tCVector vecPos = cur_pos;\n\t\t\t\t\n\t\t\t\tfloat fAngle = CGeneral::GetRandomNumberInRange(15.0f, 30.0f);\n\t\t\t\t\n\t\t\t\tuint16 nSinCosIdx = CGeneral::GetRandomNumber() % (CParticle::SIN_COS_TABLE_SIZE-1);\n\t\t\t\t\n\t\t\t\tfloat fCos = CParticle::Cos(nSinCosIdx);\n\t\t\t\tfloat fSin = CParticle::Sin(nSinCosIdx);\n\t\t\t\t\n\t\t\t\tvecPos.x += (fCos - fSin) * fAngle;\n\t\t\t\tvecPos.y += (fSin + fCos) * fAngle;\n\t\t\t\t\n\t\t\t\tCWaterCreatures::CreateOne(vecPos, -1);\n\t\t\t}\n\t\t}\n\t}\n\t\n\tCWaterCreatures::UpdateAll();\n}\n\nvoid\nCWaterLevel::HandleBeachToysStuff(void)\n{\n#ifdef FIX_BUGS\n\tCVector cur_pos = FindPlayerCoors();\n#else\n\tCVector cur_pos = FindPlayerPed()->GetPosition();\n#endif\n\t\n\tstatic bool bBeachBallInit = true;\n\tstatic CVector FirstBeachBallPos = cur_pos;\n\tstatic bool bLoungeInit = true;\n\tstatic CVector FirstLoungePos = cur_pos;\n\tstatic CVector prev_pos(0.0f, 0.0f, 0.0f);\n\tstatic int32 timecounter;\n\n\tif ( Abs(prev_pos.x - cur_pos.x) + Abs(prev_pos.y - cur_pos.y) + Abs(prev_pos.z - cur_pos.z) > 1.5f )\n\t{\n\t\tprev_pos = cur_pos;\n\t\ttimecounter = CTimer::GetTimeInMilliseconds();\n\t}\n\telse if ( (CTimer::GetTimeInMilliseconds() - timecounter) > 5000 )\n\t{\n\t\tstatic int32 toygenTime = CTimer::GetTimeInMilliseconds();\n\t\t\n\t\tif ( (CTimer::GetTimeInMilliseconds() - toygenTime) > 20000 )\n\t\t{\n\t\t\ttoygenTime = CTimer::GetTimeInMilliseconds();\n\t\t\t\n\t\t\tif ( bBeachBallInit ||  (cur_pos - FirstBeachBallPos).MagnitudeSqr() > 6400.0f )\n\t\t\t{\n\t\t\t\tfor ( int32 i = 0; i < 3; i++ )\n\t\t\t\t{\n\t\t\t\t\tCVector vecPos = cur_pos;\n\t\t\t\t\t\n\t\t\t\t\tfloat fAngle = CGeneral::GetRandomNumberInRange(20.0f, 35.0f);\n\t\t\t\t\t\n\t\t\t\t\tuint16 nSinCosIdx = CGeneral::GetRandomNumber() % (CParticle::SIN_COS_TABLE_SIZE-1);\n\t\t\t\t\t\n\t\t\t\t\tfloat fCos = CParticle::Cos(nSinCosIdx);\n\t\t\t\t\tfloat fSin = CParticle::Sin(nSinCosIdx);\n\t\t\t\t\t\n\t\t\t\t\tvecPos.x += (fCos - fSin) * fAngle;\n\t\t\t\t\tvecPos.y += (fSin + fCos) * fAngle;\n\t\t\t\t\t\n\t\t\t\t\tif ( TheCamera.IsSphereVisible(vecPos, 1.0f, &TheCamera.GetCameraMatrix()) )\n\t\t\t\t\t{\n\t\t\t\t\t\tfloat fWaterLevel;\n\t\t\t\t\t\t\n\t\t\t\t\t\tif ( !GetWaterLevel(vecPos.x, vecPos.y, vecPos.z, &fWaterLevel, false) )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tfloat fGroundLevel;\n\t\t\t\t\t\t\tColData coldata;\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tif ( GetGroundLevel(vecPos, &fGroundLevel, &coldata, 30.0f) )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tif ( coldata.SurfaceType == SURFACE_SAND )\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tCEntity *toy = CreateBeachToy(vecPos, BEACHTOY_BALL);\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\tif ( toy )\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tFirstBeachBallPos = cur_pos;\n\t\t\t\t\t\t\t\t\t\tbBeachBallInit = false;\n\t\t\t\t\t\t\t\t\t\ti = 10;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tif ( bLoungeInit ||  (cur_pos - FirstLoungePos).MagnitudeSqr() > 6400.0f )\n\t\t\t{\n\t\t\t\tfor ( int32 i = 0; i < 5; i++ )\n\t\t\t\t{\n\t\t\t\t\tCVector vecPos = cur_pos;\n\t\t\t\t\t\n\t\t\t\t\tfloat fAngle = CGeneral::GetRandomNumberInRange(20.0f, 35.0f);\n\t\t\t\t\t\n\t\t\t\t\tuint16 nSinCosIdx = CGeneral::GetRandomNumber() % (CParticle::SIN_COS_TABLE_SIZE-1);\n\t\t\t\t\t\n\t\t\t\t\tfloat fCos = CParticle::Cos(nSinCosIdx);\n\t\t\t\t\tfloat fSin = CParticle::Sin(nSinCosIdx);\n\t\t\t\t\t\n\t\t\t\t\tvecPos.x += (fCos - fSin) * fAngle;\n\t\t\t\t\tvecPos.y += (fSin + fCos) * fAngle;\n\t\t\t\t\t\n\t\t\t\t\tif ( TheCamera.IsSphereVisible(vecPos, 2.0f, &TheCamera.GetCameraMatrix()) )\n\t\t\t\t\t{\n\t\t\t\t\t\tfloat fWaterLevel;\n\t\t\t\t\t\t\n\t\t\t\t\t\tif ( !GetWaterLevel(vecPos.x, vecPos.y, vecPos.z, &fWaterLevel, false) )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tfloat fGroundLevel;\n\t\t\t\t\t\t\tColData coldata;\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tif ( GetGroundLevel(vecPos, &fGroundLevel, &coldata, 30.0f) )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tif ( coldata.SurfaceType == SURFACE_SAND )\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tCEntity *toy = CreateBeachToy(vecPos, BEACHTOY_ANY_LOUNGE);\n\t\t\t\t\t\t\t\t\tif ( toy )\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\ttoy->SetHeading(DEGTORAD(CGeneral::GetRandomNumberInRange(0.0f, 359.0f)));\n\t\t\t\t\t\t\t\t\t\tFirstLoungePos = cur_pos;\n\t\t\t\t\t\t\t\t\t\tbLoungeInit = false;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nCEntity *\nCWaterLevel::CreateBeachToy(CVector const &vec, eBeachToy beachtoy)\n{\n\tif (CObject::nNoTempObjects >= NUMTEMPOBJECTS)\n\t\treturn nil;\n\n\tint finalToy = beachtoy;\n\tbool isStatic = false;\n\tint model = MI_BEACHBALL;\n\tswitch (beachtoy) {\n\t\tcase BEACHTOY_ANY_LOUNGE:\n\t\t\tswitch ( CGeneral::GetRandomNumber() & 7 ) {\n\t\t\t\tcase 1:\n\t\t\t\tcase 7:\n\t\t\t\t\tfinalToy = BEACHTOY_LOUNGE_WOOD_UP;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 3:\n\t\t\t\tcase 5:\n\t\t\t\t\tfinalToy = BEACHTOY_LOUNGE_TOWEL_UP;\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tfinalToy = BEACHTOY_LOUNGE_WOOD_ON;\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase BEACHTOY_ANY_TOWEL:\n\t\t\tswitch ( CGeneral::GetRandomNumber() & 7 ) {\n\t\t\t\tcase 1:\n\t\t\t\tcase 7:\n\t\t\t\t\tfinalToy = BEACHTOY_TOWEL2;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 2:\n\t\t\t\tcase 6:\n\t\t\t\t\tfinalToy = BEACHTOY_TOWEL3;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 3:\n\t\t\t\tcase 5:\n\t\t\t\t\tfinalToy = BEACHTOY_TOWEL4;\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tfinalToy = BEACHTOY_TOWEL1;\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (CObject::nNoTempObjects >= 35) {\n\t\t\t\treturn nil;\n\t\t\t}\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\tswitch (finalToy) {\n\t\tcase BEACHTOY_BALL:\n\t\t\tisStatic = false;\n\t\t\tmodel = MI_BEACHBALL;\n\t\t\tbreak;\n\t\tcase BEACHTOY_LOUNGE_WOOD_UP:\n\t\t\tisStatic = false;\n\t\t\tmodel = MI_LOUNGE_WOOD_UP;\n\t\t\tbreak;\n\t\tcase BEACHTOY_LOUNGE_TOWEL_UP:\n\t\t\tisStatic = false;\n\t\t\tmodel = MI_LOUNGE_TOWEL_UP;\n\t\t\tbreak;\n\t\tcase BEACHTOY_LOUNGE_WOOD_ON:\n\t\t\tisStatic = false;\n\t\t\tmodel = MI_LOUNGE_WOOD_DN;\n\t\t\tbreak;\n\t\tcase BEACHTOY_LOTION:\n\t\t\tmodel = MI_LOTION;\n\t\t\tisStatic = true;\n\t\t\tbreak;\n\t\tcase BEACHTOY_TOWEL1:\n\t\t\tmodel = MI_BEACHTOWEL01;\n\t\t\tisStatic = true;\n\t\t\tbreak;\n\t\tcase BEACHTOY_TOWEL2:\n\t\t\tmodel = MI_BEACHTOWEL02;\n\t\t\tisStatic = true;\n\t\t\tbreak;\n\t\tcase BEACHTOY_TOWEL3:\n\t\t\tmodel = MI_BEACHTOWEL03;\n\t\t\tisStatic = true;\n\t\t\tbreak;\n\t\tcase BEACHTOY_TOWEL4:\n\t\t\tmodel = MI_BEACHTOWEL04;\n\t\t\tisStatic = true;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\tCObject *toy = new CObject(model, true);\n\tif (toy) {\n\t\ttoy->SetPosition(vec);\n\t\ttoy->GetMatrix().UpdateRW();\n\t\ttoy->m_vecMoveSpeed = CVector(0.f, 0.f, 0.f);\n\t\ttoy->m_vecTurnSpeed = CVector(0.f, 0.f, 0.f);\n\t\ttoy->ObjectCreatedBy = TEMP_OBJECT;\n\t\ttoy->bIsStatic = isStatic;\n\t\tCObject::nNoTempObjects++;\n\t\ttoy->m_nEndOfLifeTime = CTimer::GetTimeInMilliseconds() + 43200000;\n\t\tCWorld::Add(toy);\n\t\treturn toy;\n\t} else\n\t\treturn nil;\n}"
  },
  {
    "path": "src/render/WaterLevel.h",
    "content": "#pragma once\n\n#define WATER_X_OFFSET (400.0f)\n\n#define WATER_Z_OFFSET (0.5f)\n\n#define NO_WATER -128\n\n#define MAX_SMALL_SECTORS      128\n#define MAX_LARGE_SECTORS      64\n#define MAX_HUGE_SECTORS       32\n#define MAX_EXTRAHUGE_SECTORS  16\n\n#define SMALL_SECTOR_SIZE      32\n#define LARGE_SECTOR_SIZE      64\n#define HUGE_SECTOR_SIZE       128\n#define EXTRAHUGE_SECTOR_SIZE  256\n\n#define WATER_START_X -2048.0f\n#define WATER_END_X    2048.0f\n\n#define WATER_START_Y -2048.0f\n#define WATER_END_Y    2048.0f\n\n#define WATER_WIDTH\t\t((WATER_END_X - WATER_START_X))\n#define WATER_HEIGHT\t((WATER_END_Y - WATER_START_Y))\n\n#define WATER_UNSIGN_X(x)                   ( (x) + (WATER_WIDTH /2) )\n#define WATER_UNSIGN_Y(y)                   ( (y) + (WATER_HEIGHT/2) )\n#define WATER_SIGN_X(x)                     ( (x) - (WATER_WIDTH /2) )\n#define WATER_SIGN_Y(y)                     ( (y) - (WATER_HEIGHT/2) )\n\n// 64x64 Large blocks 64x64 each\n#define WATER_TO_BLOCK_X(x)             ( WATER_UNSIGN_X(x) / WATER_BLOCK_SECTORS )\n#define WATER_TO_BLOCK_Y(x)             ( WATER_UNSIGN_Y(x) / WATER_BLOCK_SECTORS ) \n\n// 128x128 Small blocks 32x32 each\n#define WATER_TO_FINEBLOCK_X(x)         ( WATER_UNSIGN_X(x) / WATER_FINEBLOCK_SECTORS )\n#define WATER_TO_FINEBLOCK_Y(x)         ( WATER_UNSIGN_Y(x) / WATER_FINEBLOCK_SECTORS ) \n\n// 32\n#define WATER_SMALL_X(x)                    ( WATER_UNSIGN_X(x)\t\t\t\t\t/ MAX_SMALL_SECTORS     )\n#define WATER_SMALL_Y(y)                    ( WATER_UNSIGN_Y(y)\t\t\t\t\t/ MAX_SMALL_SECTORS     )\n#define WATER_FROM_SMALL_SECTOR_X(x)        ( ((x) - (MAX_SMALL_SECTORS/2)    ) * SMALL_SECTOR_SIZE     )\n#define WATER_FROM_SMALL_SECTOR_Y(y)        ( ((y) - (MAX_SMALL_SECTORS/2)    ) * SMALL_SECTOR_SIZE     )\n#define WATER_TO_SMALL_SECTOR_X(x)          ( WATER_UNSIGN_X(x)\t\t\t\t\t/ SMALL_SECTOR_SIZE     )\n#define WATER_TO_SMALL_SECTOR_Y(y)          ( WATER_UNSIGN_Y(y)\t\t\t\t\t/ SMALL_SECTOR_SIZE     )\n\t\t\t\n// 64\t\t\t\n#define WATER_LARGE_X(x)                    ( WATER_UNSIGN_X(x)\t\t\t\t\t/ MAX_LARGE_SECTORS     )\n#define WATER_LARGE_Y(y)                    ( WATER_UNSIGN_Y(y)\t\t\t\t\t/ MAX_LARGE_SECTORS     )\n#define WATER_FROM_LARGE_SECTOR_X(x)        ( ((x) - (MAX_LARGE_SECTORS/2)    ) * LARGE_SECTOR_SIZE     )\n#define WATER_FROM_LARGE_SECTOR_Y(y)        ( ((y) - (MAX_LARGE_SECTORS/2)    ) * LARGE_SECTOR_SIZE     )\n#define WATER_TO_LARGE_SECTOR_X(x)          ( WATER_UNSIGN_X(x)\t\t\t\t\t/ LARGE_SECTOR_SIZE     )\n#define WATER_TO_LARGE_SECTOR_Y(y)          ( WATER_UNSIGN_Y(y)\t\t\t\t\t/ LARGE_SECTOR_SIZE     )\n\t\t\t\t\n// 128\t\t\t\t\n#define WATER_HUGE_X(x)                     ( WATER_UNSIGN_X(x)\t\t\t\t\t/ MAX_HUGE_SECTORS      )\n#define WATER_HUGE_Y(y)                     ( WATER_UNSIGN_Y(y)\t\t\t\t\t/ MAX_HUGE_SECTORS      )\n#define WATER_FROM_HUGE_SECTOR_X(x)         ( ((x) - (MAX_HUGE_SECTORS/2)     ) * HUGE_SECTOR_SIZE      )\n#define WATER_FROM_HUGE_SECTOR_Y(y)         ( ((y) - (MAX_HUGE_SECTORS/2)     ) * HUGE_SECTOR_SIZE      )\n#define WATER_TO_HUGE_SECTOR_X(x)           ( WATER_UNSIGN_X(x)\t\t\t\t\t/ HUGE_SECTOR_SIZE      )\n#define WATER_TO_HUGE_SECTOR_Y(y)           ( WATER_UNSIGN_Y(y)\t\t\t\t\t/ HUGE_SECTOR_SIZE      )\n\n// 256\t\n#define WATER_EXTRAHUGE_X(x)                ( WATER_UNSIGN_X(x)\t\t\t\t\t/ MAX_EXTRAHUGE_SECTORS )\n#define WATER_EXTRAHUGE_Y(y)                ( WATER_UNSIGN_Y(y)\t\t\t\t\t/ MAX_EXTRAHUGE_SECTORS )\n#define WATER_FROM_EXTRAHUGE_SECTOR_X(x)    ( ((x) - (MAX_EXTRAHUGE_SECTORS/2)) * EXTRAHUGE_SECTOR_SIZE )\n#define WATER_FROM_EXTRAHUGE_SECTOR_Y(y)    ( ((y) - (MAX_EXTRAHUGE_SECTORS/2)) * EXTRAHUGE_SECTOR_SIZE )\n#define WATER_TO_EXTRAHUGE_SECTOR_X(x)      ( WATER_UNSIGN_X(x)\t\t\t\t\t/ EXTRAHUGE_SECTOR_SIZE )\n#define WATER_TO_EXTRAHUGE_SECTOR_Y(y)      ( WATER_UNSIGN_Y(y)\t\t\t\t\t/ EXTRAHUGE_SECTOR_SIZE )\n\nstruct ColData\n{\n\tuint8 SurfaceType;\n\tuint8 PieceType;\n};\n\nenum eBeachToy\n{\n\tBEACHTOY_0 = 0,\n\tBEACHTOY_BALL,\n\tBEACHTOY_LOUNGE_WOOD_UP,\n\tBEACHTOY_LOUNGE_TOWEL_UP,\n\tBEACHTOY_LOUNGE_WOOD_ON,\n\tBEACHTOY_ANY_LOUNGE,\n\tBEACHTOY_LOTION,\n\tBEACHTOY_TOWEL1,\n\tBEACHTOY_TOWEL2,\n\tBEACHTOY_TOWEL3,\n\tBEACHTOY_TOWEL4,\n\tBEACHTOY_ANY_TOWEL,\n};\n\nextern RwRaster* gpWaterRaster;\nextern bool gbDontRenderWater;\n\nclass CEntity;\n\nclass CWaterLevel\n{\npublic:\n\tstatic int32       ms_nNoOfWaterLevels;\n\tstatic float       ms_aWaterZs[48];\n\tstatic CRect       ms_aWaterRects[48];\n\tstatic int8        aWaterBlockList[MAX_LARGE_SECTORS][MAX_LARGE_SECTORS];\t\t\t\t// 64x64 Large blocks 64x64 each\n\tstatic int8        aWaterFineBlockList[MAX_SMALL_SECTORS][MAX_SMALL_SECTORS];\t\t\t// 128x128 Small blocks 32x32 each\n\tstatic bool        WavesCalculatedThisFrame;\n\n\tstatic bool        RequireWavySector;\n\tstatic bool        MaskCalculatedThisFrame;\n\tstatic CVector     PreCalculatedMaskPosn;\n\tstatic bool        m_bRenderSeaBed;\n\tstatic int32       m_nRenderWaterLayers;\n\n\tstatic RpAtomic    *ms_pWavyAtomic;\n\tstatic RpAtomic    *ms_pMaskAtomic;\n\n\tstatic void    Initialise(Const char *pWaterDat); // out of class in III PC and later because of SecuROM\n\tstatic void    Shutdown();\n\n\tstatic void    CreateWavyAtomic();\n\tstatic void    DestroyWavyAtomic();\n\n\tstatic void    AddWaterLevel(float fXLeft, float fYBottom, float fXRight, float fYTop, float fLevel);\n\tstatic bool    WaterLevelAccordingToRectangles(float fX, float fY, float *pfOutLevel = nil);\n\tstatic bool    TestVisibilityForFineWaterBlocks(const CVector &worldPos);\n\tstatic void    RemoveIsolatedWater();\n\n\tstatic bool    GetWaterLevel(float fX, float fY, float fZ, float *pfOutLevel, bool bDontCheckZ);\n\tstatic bool    GetWaterLevel(CVector coors, float *pfOutLevel, bool bDontCheckZ) { return GetWaterLevel(coors.x, coors.y, coors.z, pfOutLevel, bDontCheckZ); }\n\tstatic bool    GetWaterLevelNoWaves(float fX, float fY, float fZ, float *pfOutLevel);\n\tstatic float   GetWaterWavesOnly(short x, short y);\t// unused\n\tstatic CVector GetWaterNormal(float fX, float fY);\n\n\tstatic void    RenderWater();\n\tstatic void    RenderTransparentWater(void);\n\t// unused \n\tstatic void RenderOneFlatSmallWaterPoly    (float fX, float fY, float fZ, RwRGBA const &color);\n\t// inlined\n\tstatic void RenderOneFlatLargeWaterPoly    (float fX, float fY, float fZ, RwRGBA const &color);\t\n\tstatic void RenderOneFlatHugeWaterPoly     (float fX, float fY, float fZ, RwRGBA const &color);\n\tstatic void RenderOneFlatExtraHugeWaterPoly(float fX, float fY, float fZ, RwRGBA const &color);\n\t// inlined\n\tstatic void RenderOneWavySector            (float fX, float fY, float fZ, RwRGBA const &color, bool bDontRender = false);\n\t// unused\n#ifdef PC_WATER\n\tstatic void RenderWavyMask(float fX, float fY, float fZ, float fSectorX, float fSectorY, float fCamPosX, float fCamPosY, float fCamDirX, float fCamDirY, RwRGBA const&color);\n#else\n\tstatic void RenderWavyMask(float fX, float fY, float fZ, float fSectorX, float fSectorY, int32 nCamDirX, int32 nCamDirY, RwRGBA const&color);\n#endif\n\n#ifdef PC_WATER\n\tstatic void PreCalcWaterGeometry(void);\n\tstatic bool PreCalcWavySector(RwRGBA const &color);\t//fucked up\n\tstatic bool PreCalcWavyMask(float fX, float fY, float fZ, float fSectorX, float fSectorY, float fCamPosX, float fCamPosY, float fCamDirX, float fCamDirY, RwRGBA const&color);\n#endif\n\n\n\tstatic void RenderBoatWakes(void);\n\tstatic void RenderWakeSegment(CVector2D &vecA, CVector2D &vecB, CVector2D &vecC, CVector2D &vecD, float &fSizeA, float &fSizeB, float &fAlphaA, float &fAlphaB, float &fWakeZ);\n\n\t// unused\n\tstatic void RenderOneSlopedUnderWaterPoly(float fX, float fY, float fZ, RwRGBA const&color); // UNUSED\n\tstatic void RenderOneFlatSmallWaterPolyBlended(float fX, float fY, float fZ, float fCamX, float fCamY, RwRGBA const &color, RwRGBA const &colorTrans, float fDrawDist);\n\tstatic float CalcDistanceToWater(float fX, float fY);\n\tstatic void RenderAndEmptyRenderBuffer();\n\t\n\tstatic bool GetGroundLevel(CVector const &vecPosn, float *pfOutLevel, ColData *pData, float fDistance);\n\n\t// unused\n\tstatic bool IsLocationOutOfWorldBounds_WS(CVector const &vecPosn, int nOffset);\n\t// unused\n\tstatic bool GetGroundLevel_WS(CVector const & vecPosn, float *pfOutLevel, ColData *pData, float fDistance);\n\tstatic bool GetWaterDepth(CVector const &vecPosn, float *pfDepth, float *pfLevelNoWaves, float *pfGroundLevel);\n\n\tstatic void RenderSeaBirds();\n\tstatic void RenderShipsOnHorizon();\n\n\tstatic void HandleSeaLifeForms();\n\n\tstatic void HandleBeachToysStuff(void);\n\tstatic CEntity *CreateBeachToy(CVector const &vec, eBeachToy beachtoy);\n};\n"
  },
  {
    "path": "src/render/Weather.cpp",
    "content": "#include \"common.h\"\n\n#include \"Weather.h\"\n\n#include \"Camera.h\"\n#include \"Clock.h\"\n#include \"CutsceneMgr.h\"\n#include \"DMAudio.h\"\n#include \"General.h\"\n#include \"Pad.h\"\n#include \"PlayerPed.h\"\n#include \"Particle.h\"\n#include \"RenderBuffer.h\"\n#include \"Stats.h\"\n#include \"Shadows.h\"\n#include \"Timecycle.h\"\n#include \"Timer.h\"\n#include \"Vehicle.h\"\n#include \"World.h\"\n#include \"ZoneCull.h\"\n#include \"SpecialFX.h\"\n#include \"Replay.h\"\n\nint32 CWeather::SoundHandle = -1;\n\nint32 CWeather::WeatherTypeInList;\nint16 CWeather::OldWeatherType;\nint16 CWeather::NewWeatherType;\nint16 CWeather::ForcedWeatherType;\n\nbool CWeather::LightningFlash;\nbool CWeather::LightningBurst;\nuint32 CWeather::LightningStart;\nuint32 CWeather::LightningFlashLastChange;\nuint32 CWeather::WhenToPlayLightningSound;\nuint32 CWeather::LightningDuration;\nint32 CWeather::StreamAfterRainTimer;\n\nfloat CWeather::ExtraSunnyness;\nfloat CWeather::Foggyness;\nfloat CWeather::CloudCoverage;\nfloat CWeather::Wind;\nfloat CWeather::Rain;\nfloat CWeather::InterpolationValue;\nfloat CWeather::WetRoads;\nfloat CWeather::Rainbow;\nfloat CWeather::SunGlare;\nfloat CWeather::WindClipped;\nfloat CWeather::TrafficLightBrightness;\n\nbool CWeather::bScriptsForceRain;\n\ntRainStreak Streaks[NUM_RAIN_STREAKS];\n\nint16 WeatherTypesList[] = {\n\tWEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY,\n\tWEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY,\n\tWEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_EXTRA_SUNNY,\n\tWEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY,\n\tWEATHER_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY,\n\tWEATHER_EXTRA_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_EXTRA_SUNNY,\n\tWEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY,\n\tWEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY,\n\tWEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY,\n\tWEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY,\n\tWEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_CLOUDY,\n\tWEATHER_RAINY, WEATHER_RAINY, WEATHER_RAINY, WEATHER_RAINY,\n\tWEATHER_CLOUDY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY,\n\tWEATHER_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY,\n\tWEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY,\n\tWEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY\n};\n\nint16 WeatherTypesList_WithHurricanes[] = {\n\tWEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY,\n\tWEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY,\n\tWEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_EXTRA_SUNNY,\n\tWEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY,\n\tWEATHER_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_CLOUDY,\n\tWEATHER_HURRICANE, WEATHER_HURRICANE, WEATHER_CLOUDY, WEATHER_SUNNY,\n\tWEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY,\n\tWEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY,\n\tWEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY,\n\tWEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY,\n\tWEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY,\n\tWEATHER_CLOUDY, WEATHER_HURRICANE, WEATHER_HURRICANE, WEATHER_HURRICANE,\n\tWEATHER_CLOUDY, WEATHER_SUNNY, WEATHER_SUNNY, WEATHER_SUNNY,\n\tWEATHER_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY,\n\tWEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY,\n\tWEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY, WEATHER_EXTRA_SUNNY\n};\n\nconst float Windyness[] = {\n\t0.25f,// WEATHER_SUNNY\n\t0.7f, // WEATHER_CLOUDY\n\t1.0f, // WEATHER_RAINY\n\t0.0f, // WEATHER_FOGGY\n\t0.0f, // WEATHER_EXTRA_SUNNY\n\t2.0f, // WEATHER_HURRICANE\n\t0.0f\n};\n\n#define MIN_TIME_BETWEEN_LIGHTNING_FLASH_CHANGES (50)\n\n#define RAIN_CHANGE_SPEED (0.003f)\n\n#define DROPLETS_LEFT_OFFSET (10.0f)\n#define DROPLETS_RIGHT_OFFSET (10.0f)\n#define DROPLETS_TOP_OFFSET (10.0f)\n#define DROPLETS_BOTTOM_OFFSET (10.0f)\n\n#define STREAK_U (10.0f)\n#define STREAK_V (18.0f)\n#define LARGE_STREAK_COEFFICIENT (1.23f)\n#define STREAK_MIN_DISTANCE (8.0f)\n#define STREAK_MAX_DISTANCE (16.0f)\n\n#define SPLASH_CHECK_RADIUS (7.0f)\n#define SPLASH_OFFSET_RADIUS (2.0f)\n\n#define STREAK_LIFETIME (4.0f)\n#define STREAK_INTEROLATION_TIME (0.3f)\n\n#define RAIN_COLOUR_R (200)\n#define RAIN_COLOUR_G (200)\n#define RAIN_COLOUR_B (256)\n#define RAIN_ALPHA (255)\n\nvoid CWeather::Init(void)\n{\n\tNewWeatherType = WEATHER_EXTRA_SUNNY;\n\tbScriptsForceRain = false;\n\tOldWeatherType = WEATHER_EXTRA_SUNNY;\n\tInterpolationValue = 0.0f;\n\tWhenToPlayLightningSound = 0;\n\tWeatherTypeInList = 0;\n\tForcedWeatherType = WEATHER_RANDOM;\n\tSoundHandle = DMAudio.CreateEntity(AUDIOTYPE_WEATHER, (void*)1);\n\tif (SoundHandle >= 0)\n\t\tDMAudio.SetEntityStatus(SoundHandle, true);\n}\n\nvoid CWeather::Update(void)\n{\n\tif(!CReplay::IsPlayingBack()){\n\t\tfloat fNewInterpolation = (CClock::GetMinutes() + CClock::GetSeconds()/60.0f)/60.0f;\n\t\tif (fNewInterpolation < InterpolationValue) {\n\t\t\t// new hour\n\t\t\tOldWeatherType = NewWeatherType;\n\t\t\tif (ForcedWeatherType >= 0)\n\t\t\t\tNewWeatherType = ForcedWeatherType;\n\t\t\telse {\n\t\t\t\tWeatherTypeInList = (WeatherTypeInList + 1) % ARRAY_SIZE(WeatherTypesList);\n\t\t\t\tNewWeatherType = CStats::NoMoreHurricanes ? WeatherTypesList[WeatherTypeInList] : WeatherTypesList_WithHurricanes[WeatherTypeInList];\n\t\t\t}\n\t\t}\n\t\tInterpolationValue = fNewInterpolation;\n\t}\n\n#ifndef FINAL\n\tif (CPad::GetPad(1)->GetRightShockJustDown()) {\n\t\tNewWeatherType = (NewWeatherType + 1) % WEATHER_TOTAL;\n\t\tOldWeatherType = NewWeatherType;\n\t}\n#endif\n\n\t// Lightning\n\tif (NewWeatherType != WEATHER_RAINY || OldWeatherType != WEATHER_RAINY) {\n\t\tLightningFlash = false;\n\t\tLightningBurst = false;\n\t}\n\telse{\n\t\tif (LightningBurst) {\n\t\t\tif ((CGeneral::GetRandomNumber() & 255) >= 32) {\n\t\t\t\t// 0.875 probability\n\t\t\t\tif (CTimer::GetTimeInMilliseconds() - LightningFlashLastChange > MIN_TIME_BETWEEN_LIGHTNING_FLASH_CHANGES) {\n\t\t\t\t\tbool bOldLightningFlash = LightningFlash;\n\t\t\t\t\tLightningFlash = CGeneral::GetRandomTrueFalse();\n\t\t\t\t\tif (LightningFlash != bOldLightningFlash)\n\t\t\t\t\t\tLightningFlashLastChange = CTimer::GetTimeInMilliseconds();\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\t// 0.125 probability\n\t\t\t\tLightningBurst = false;\n\t\t\t\tLightningDuration = Min(CTimer::GetFrameCounter() - LightningStart, 20);\n\t\t\t\tLightningFlash = false;\n\t\t\t\tWhenToPlayLightningSound = CTimer::GetTimeInMilliseconds() + 150 * (20 - LightningDuration);\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tif (CGeneral::GetRandomNumber() >= 200) {\n\t\t\t\t// lower probability on PC due to randomness bug\n\t\t\t\tLightningFlash = false;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tLightningBurst = true;\n\t\t\t\tLightningStart = CTimer::GetFrameCounter();\n\t\t\t\tLightningFlashLastChange = CTimer::GetTimeInMilliseconds();\n\t\t\t\tLightningFlash = true;\n\t\t\t}\n\t\t}\n\t}\n\tif (WhenToPlayLightningSound && CTimer::GetTimeInMilliseconds() > WhenToPlayLightningSound) {\n\t\tDMAudio.PlayOneShot(SoundHandle, SOUND_LIGHTNING, LightningDuration);\n\t\tCPad::GetPad(0)->StartShake(40 * LightningDuration + 100, 2 * LightningDuration + 80);\n\t\tWhenToPlayLightningSound = 0;\n\t}\n\n\t// Wet roads\n\tif (OldWeatherType == WEATHER_RAINY || OldWeatherType == WEATHER_HURRICANE) {\n\t\tif (NewWeatherType == WEATHER_RAINY || NewWeatherType == WEATHER_HURRICANE)\n\t\t\tWetRoads = 1.0f;\n\t\telse\n\t\t\tWetRoads = 1.0f - InterpolationValue;\n\t}\n\telse {\n\t\tif (NewWeatherType == WEATHER_RAINY || NewWeatherType == WEATHER_HURRICANE)\n\t\t\tWetRoads = InterpolationValue;\n\t\telse\n\t\t\tWetRoads = 0.0f;\n\t}\n\n\t// Rain\n\tfloat fNewRain;\n\tif (NewWeatherType == WEATHER_RAINY || NewWeatherType == WEATHER_HURRICANE) {\n\t\t// if raining for >1 hour, values: 0, 0.33, switching every ~16.5s\n\t\tfNewRain = (((uint16)CTimer::GetTimeInMilliseconds() >> 14) & 1) * 0.33f;\n\t\tif (OldWeatherType != WEATHER_RAINY && OldWeatherType != WEATHER_HURRICANE) {\n\t\t\tif (InterpolationValue < 0.4f)\n\t\t\t\t// if rain has just started (<24 minutes), always 0.5\n\t\t\t\tfNewRain = 0.5f;\n\t\t\telse\n\t\t\t\t// if rain is ongoing for >24 minutes, values: 0.25, 0.5, switching every ~16.5s\n\t\t\t\tfNewRain = 0.25f + (((uint16)CTimer::GetTimeInMilliseconds() >> 14) & 1) * 0.25f;\n\t\t}\n\t\tfNewRain = Max(fNewRain, 0.5f);\n\t}\n\telse\n\t\tfNewRain = 0.0f;\n\tRain = fNewRain;\n\n\t// Clouds\n\tif (OldWeatherType != WEATHER_SUNNY && OldWeatherType != WEATHER_EXTRA_SUNNY)\n\t\tCloudCoverage = 1.0f - InterpolationValue;\n\telse\n\t\tCloudCoverage = 0.0f;\n\tif (NewWeatherType != WEATHER_SUNNY && OldWeatherType != WEATHER_EXTRA_SUNNY)\n\t\tCloudCoverage += InterpolationValue;\n\t\n\t// Fog\n\tif (OldWeatherType == WEATHER_FOGGY)\n\t\tFoggyness = 1.0f - InterpolationValue;\n\telse\n\t\tFoggyness = 0.0f;\n\tif (NewWeatherType == WEATHER_FOGGY)\n\t\tFoggyness += InterpolationValue;\n\n\t// Extra Sunnyness\n\tif (OldWeatherType == WEATHER_EXTRA_SUNNY)\n\t\tExtraSunnyness = 1.0f - InterpolationValue;\n\telse\n\t\tExtraSunnyness = 0.0f;\n\tif (NewWeatherType == WEATHER_EXTRA_SUNNY)\n\t\tExtraSunnyness += InterpolationValue;\n\n\t// Rainbow\n\tif (OldWeatherType == WEATHER_CLOUDY && (NewWeatherType == WEATHER_SUNNY || NewWeatherType == WEATHER_EXTRA_SUNNY) &&\n\t\tInterpolationValue < 0.5f && CClock::GetHours() > 6 && CClock::GetHours() < 21)\n\t\tRainbow = 1.0f - 4.0f * Abs(InterpolationValue - 0.25f) / 4.0f;\n\telse\n\t\tRainbow = 0.0f;\n\n\t// Sun Glare\n\tif (OldWeatherType == WEATHER_EXTRA_SUNNY)\n\t\tSunGlare = 1.0f - InterpolationValue;\n\telse\n\t\tSunGlare = 0.0f;\n\tif (NewWeatherType == WEATHER_EXTRA_SUNNY)\n\t\tSunGlare += InterpolationValue;\n\n\tif (SunGlare > 0.0f) {\n\t\tSunGlare *= Min(1.0f, 7.0 * CTimeCycle::GetSunDirection().z);\n\t\tSunGlare = clamp(SunGlare, 0.0f, 1.0f);\n\t\tif (!CSpecialFX::bSnapShotActive)\n\t\t\tSunGlare *= (1.0f - (CGeneral::GetRandomNumber()&0x1F)*0.007f);\n\t}\n\n\tWind = InterpolationValue * Windyness[NewWeatherType] + (1.0f - InterpolationValue) * Windyness[OldWeatherType];\n\tWindClipped = Min(1.0f, Wind);\n\n\tif (CClock::GetHours() > 20)\n\t\tTrafficLightBrightness = 1.0f;\n\telse if (CClock::GetHours() > 19)\n\t\tTrafficLightBrightness = CClock::GetMinutes() / 60.0f;\n\telse if (CClock::GetHours() > 6)\n\t\tTrafficLightBrightness = 0.0f;\n\telse if (CClock::GetHours() > 5)\n\t\tTrafficLightBrightness = 1.0f - CClock::GetMinutes() / 60.0f;\n\telse\n\t\tTrafficLightBrightness = 1.0f;\n\tTrafficLightBrightness = Max(WetRoads, TrafficLightBrightness);\n\tTrafficLightBrightness = Max(Foggyness, TrafficLightBrightness);\n\tTrafficLightBrightness = Max(Rain, TrafficLightBrightness);\n\n\tAddRain();\n\n\tif ((NewWeatherType == WEATHER_SUNNY || NewWeatherType == WEATHER_EXTRA_SUNNY) &&\n\t\t!CGame::IsInInterior() && !CCutsceneMgr::IsRunning() && (CTimer::GetFrameCounter() & 7) == 0) {\n#ifdef FIX_BUGS\n\t\tif (FindPlayerPed() && (!FindPlayerPed()->CheckIfInTheAir() || FindPlayerPed()->CheckIfInTheAir() && FindPlayerPed()->GetPosition().z < 7.5f &&\n\t\t\tCClock::GetHours() > 6 && CClock::GetHours() < 18))\n#else\n\t\tif (!FindPlayerPed()->CheckIfInTheAir() || FindPlayerPed()->CheckIfInTheAir() && FindPlayerPed()->GetPosition().z < 7.5f &&\n\t\t\tCClock::GetHours() > 6 && CClock::GetHours() < 18)\n#endif\n\t\t\tAddHeatHaze();\n\t}\n\n\tif ((NewWeatherType == WEATHER_SUNNY || NewWeatherType == WEATHER_EXTRA_SUNNY) && !CGame::IsInInterior() && !CCutsceneMgr::IsRunning())\n\t\tAddBeastie();\n}\n\nvoid CWeather::AddHeatHaze()\n{\n\tif(TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOPDOWN ||\n\t   TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOP_DOWN_PED)\n\t\treturn;\n\tCVector pos;\n\tpos.x = SCREEN_WIDTH*0.5f;\n\tif(TheCamera.GetLookingForwardFirstPerson())\n\t\tpos.y = CGeneral::GetRandomNumberInRange(SCREEN_HEIGHT*0.25f, SCREEN_HEIGHT*0.9f);\n\telse\n\t\tpos.y = CGeneral::GetRandomNumberInRange(SCREEN_HEIGHT*0.4f, SCREEN_HEIGHT*0.9f);\n\tpos.z = 100.0f;\n\tCParticle::AddParticle(PARTICLE_HEATHAZE_IN_DIST, pos, CVector(0.0f, 0.0f, 0.0f));\n}\n\nvoid CWeather::AddBeastie()\n{\n\tif(FindPlayerVehicle() || CTimer::GetFrameCounter()%10 || (CGeneral::GetRandomNumber()&5) == 0)\n\t\treturn;\n\tCVector pos = TheCamera.GetPosition();\n\tfloat dist = CGeneral::GetRandomNumberInRange(90.0f, 60.0f);\n\tint angle = CGeneral::GetRandomNumber() % CParticle::SIN_COS_TABLE_SIZE;\n\tfloat c = CParticle::m_CosTable[angle];\n\tfloat s = CParticle::m_SinTable[angle];\n\tpos.x += dist*(c - s);\n\tpos.y += dist*(c + s);\n\tpos.z += CGeneral::GetRandomNumberInRange(7.5f, 30.0f);\n\tCParticle::AddParticle(PARTICLE_BEASTIE, pos, CVector(0.0f, 0.0f, 0.0f));\n}\n\nvoid CWeather::ForceWeather(int16 weather)\n{\n\tForcedWeatherType = weather;\n}\n\nvoid CWeather::ForceWeatherNow(int16 weather)\n{\n\tOldWeatherType = weather;\n\tNewWeatherType = weather;\n\tForcedWeatherType = weather;\n}\n\nvoid CWeather::ReleaseWeather()\n{\n\tForcedWeatherType = -1;\n}\n\nvoid CWeather::AddSplashesDuringHurricane()\n{\n\tRwRGBA colour = { 255, 255, 255, 32 };\n\tCVector pos = TheCamera.pTargetEntity ? TheCamera.pTargetEntity->GetPosition() : TheCamera.GetPosition();\n\tbool foundGround;\n\tfloat groundZ = CWorld::FindGroundZFor3DCoord(pos.x, pos.y, pos.z, &foundGround) + 0.1f;\n\tif(!foundGround)\n\t\tgroundZ = pos.z + 0.5f;\n\tfor(int i = 0; i < 20; i++){\n\t\tfloat dist = (CGeneral::GetRandomNumber()&0xFF)/255.0f +\n\t\t\tCGeneral::GetRandomNumberInRange(-10.0f, 30.0f);\n\t\tfloat angle;\n\t\tuint8 rnd = CGeneral::GetRandomNumber();\n\t\tif(rnd&1)\n\t\t\tangle = (CGeneral::GetRandomNumber()&0x7F)/128.0f * TWOPI;\n\t\telse\n\t\t\tangle = TheCamera.Orientation + (rnd-128)/160.0f;\n\t\tpos.x = TheCamera.GetPosition().x + dist*Sin(angle);\n\t\tpos.y = TheCamera.GetPosition().y + dist*Cos(angle);\n\t\tpos.z = groundZ;\n\t\tif(foundGround)\n\t\t\tCParticle::AddParticle(PARTICLE_GROUND_STEAM, pos, CVector(-0.002f, -0.002f, 0.015f), nil, 0.0f, colour);\n\t}\n}\n\nstatic int startStreamAfterRain;\n\nvoid CWeather::AddStreamAfterRain()\n{\n\tif(CClock::GetHours() > 6 && CClock::GetHours() < 18){\n\t\tRwRGBA colour = { 255, 255, 255, 24 };\n\t\tCVector pos = TheCamera.pTargetEntity ? TheCamera.pTargetEntity->GetPosition() : TheCamera.GetPosition();\n\t\tbool foundGround;\n\t\tfloat groundZ = CWorld::FindGroundZFor3DCoord(pos.x, pos.y, pos.z, &foundGround) + 0.2f;\n\t\tif(!foundGround)\n\t\t\tgroundZ = pos.z + 0.75f;\n\t\tfor(int i = 0; i < 20; i++){\n\t\t\tfloat dist = (CGeneral::GetRandomNumber()&0xFF)/255.0f +\n\t\t\t\tCGeneral::GetRandomNumberInRange(-10.0f, 30.0f);\n\t\t\tfloat angle;\n\t\t\tuint8 rnd = CGeneral::GetRandomNumber();\n\t\t\tif(rnd&1)\n\t\t\t\tangle = (CGeneral::GetRandomNumber()&0x7F)/128.0f * TWOPI;\n\t\t\telse\n\t\t\t\tangle = TheCamera.Orientation + (rnd-128)/160.0f;\n\t\t\tpos.x = TheCamera.GetPosition().x + dist*Sin(angle);\n\t\t\tpos.y = TheCamera.GetPosition().y + dist*Cos(angle);\n\t\t\tpos.z = groundZ;\n\t\t\tCParticle::AddParticle(PARTICLE_GROUND_STEAM, pos, CVector(0.0f, 0.0f, 0.015f), nil, 0.0f, colour);\n\t\t}\n\t}else{\n\t\tstartStreamAfterRain = 0;\n\t\tStreamAfterRainTimer = 800;\n\t}\n}\n\nvoid CWeather::AddRain()\n{\n\tif (CCullZones::CamNoRain() || CCullZones::PlayerNoRain())\n\t\treturn;\n\tif (TheCamera.GetLookingLRBFirstPerson()) {\n\t\tCVehicle* pVehicle = FindPlayerVehicle();\n\t\tif (pVehicle && pVehicle->CarHasRoof()) {\n\t\t\tCParticle::RemovePSystem(PARTICLE_RAINDROP_2D);\n\t\t\treturn;\n\t\t}\n\t}\n\n\tif(Rain > 0.0){\n\t\tstartStreamAfterRain = 1;\n\t\tStreamAfterRainTimer = 800;\n\t}else if(startStreamAfterRain){\n\t\tif(StreamAfterRainTimer > 0){\n\t\t\tAddStreamAfterRain();\n\t\t\tStreamAfterRainTimer--;\n\t\t}else{\n\t\t\tstartStreamAfterRain = 0;\n\t\t\tStreamAfterRainTimer = 800;\n\t\t}\n\t}\n\n\tif (Wind > 1.1f)\n\t\tAddSplashesDuringHurricane();\n\n\tif (Rain <= 0.1f)\n\t\treturn;\n\tstatic RwRGBA colour;\n\tint numDrops = 5.0f * Rain;\n\tint numSplashes = 2.0f * Rain;\n\tCVector pos, dir;\n\tfor(int i = 0; i < numDrops; i++){\n\t\tpos.x = CGeneral::GetRandomNumberInRange(0, (int)SCREEN_WIDTH);\n\t\tpos.y = CGeneral::GetRandomNumberInRange(0, (int)SCREEN_HEIGHT/5);\n\t\tpos.z = 0.0f;\n\t\tdir.x = 0.0f;\n\t\tdir.y = CGeneral::GetRandomNumberInRange(30.0f, 40.0f);\n\t\tdir.z = 0.0f;\n\t\tCParticle::AddParticle(PARTICLE_RAINDROP_2D, pos, dir, nil, CGeneral::GetRandomNumberInRange(0.1f, 0.75f), 0, 0, (int)Rain&3, 0);\n\n\t\tpos.x = CGeneral::GetRandomNumberInRange(0, (int)SCREEN_WIDTH);\n\t\tpos.y = CGeneral::GetRandomNumberInRange((int)SCREEN_HEIGHT/5, (int)SCREEN_HEIGHT/2);\n\t\tpos.z = 0.0f;\n\t\tdir.x = 0.0f;\n\t\tdir.y = CGeneral::GetRandomNumberInRange(30.0f, 40.0f);\n\t\tdir.z = 0.0f;\n\t\tCParticle::AddParticle(PARTICLE_RAINDROP_2D, pos, dir, nil, CGeneral::GetRandomNumberInRange(0.1f, 0.75f), 0, 0, (int)Rain&3, 0);\n\n\t\tpos.x = CGeneral::GetRandomNumberInRange(0, (int)SCREEN_WIDTH);\n\t\tpos.y = 0.0f;\n\t\tpos.z = 0.0f;\n\t\tdir.x = 0.0f;\n\t\tdir.y = CGeneral::GetRandomNumberInRange(30.0f, 40.0f);\n\t\tdir.z = 0.0f;\n\t\tCParticle::AddParticle(PARTICLE_RAINDROP_2D, pos, dir, nil, CGeneral::GetRandomNumberInRange(0.1f, 0.75f), 0, 0, (int)Rain&3, 0);\n\n\t\tfloat dist = CGeneral::GetRandomNumberInRange(0.0f, Max(10.0f*Rain, 40.0f)/2.0f);\n\t\tfloat angle;\n\t\tuint8 rnd = CGeneral::GetRandomNumber();\n\t\tif(rnd&1)\n\t\t\tangle = (CGeneral::GetRandomNumber()&0x7F)/128.0f * TWOPI;\n\t\telse\n\t\t\tangle = TheCamera.Orientation + (rnd-128)/160.0f;\n\t\tpos.x = TheCamera.GetPosition().x + dist*Sin(angle);\n\t\tpos.y = TheCamera.GetPosition().y + dist*Cos(angle);\n\t\tpos.z = 0.0f;\n\t\tCColPoint point;\n\t\tCEntity *ent;\n\t\tif(CWorld::ProcessVerticalLine(pos+CVector(0.0f, 0.0f, 40.0f), -40.0f, point, ent, true, false, false, false, true, false, nil)){\n\t\t\tpos.z = point.point.z;\n\t\t\tfor(int j = 0; j < numSplashes+15; j++){\n\t\t\t\tCVector pos2 = pos;\n\t\t\t\tpos2.x += CGeneral::GetRandomNumberInRange(-15.0f, 15.0f);\n\t\t\t\tpos2.y += CGeneral::GetRandomNumberInRange(-15.0f, 15.0f);\n\t\t\t\tif(CGeneral::GetRandomNumber() & 1)\n\t\t\t\t\tCParticle::AddParticle(PARTICLE_RAIN_SPLASH, pos2, CVector(0.0f, 0.0f, 0.0f), nil, 0.0f, colour);\n\t\t\t\telse\n\t\t\t\t\tCParticle::AddParticle(PARTICLE_RAIN_SPLASHUP, pos2, CVector(0.0f, 0.0f, 0.0f), nil, 0.0f, colour);\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid RenderOneRainStreak(CVector pos, CVector unused, int intensity, bool scale, float distance)\n{\n\tstatic float RandomTex;\n\tstatic float RandomTexX;\n\tstatic float RandomTexY;\n\tTempBufferRenderIndexList[TempBufferIndicesStored + 0] = TempBufferVerticesStored + 0;\n\tTempBufferRenderIndexList[TempBufferIndicesStored + 1] = TempBufferVerticesStored + 2;\n\tTempBufferRenderIndexList[TempBufferIndicesStored + 2] = TempBufferVerticesStored + 1;\n\tTempBufferRenderIndexList[TempBufferIndicesStored + 3] = TempBufferVerticesStored + 0;\n\tTempBufferRenderIndexList[TempBufferIndicesStored + 4] = TempBufferVerticesStored + 3;\n\tTempBufferRenderIndexList[TempBufferIndicesStored + 5] = TempBufferVerticesStored + 2;\n\tTempBufferRenderIndexList[TempBufferIndicesStored + 6] = TempBufferVerticesStored + 1;\n\tTempBufferRenderIndexList[TempBufferIndicesStored + 7] = TempBufferVerticesStored + 2;\n\tTempBufferRenderIndexList[TempBufferIndicesStored + 8] = TempBufferVerticesStored + 4;\n\tTempBufferRenderIndexList[TempBufferIndicesStored + 9] = TempBufferVerticesStored + 2;\n\tTempBufferRenderIndexList[TempBufferIndicesStored + 10] = TempBufferVerticesStored + 3;\n\tTempBufferRenderIndexList[TempBufferIndicesStored + 11] = TempBufferVerticesStored + 4;\n\tRwIm3DVertexSetRGBA(&TempBufferRenderVertices[TempBufferVerticesStored + 0], 0, 0, 0, 0);\n\tRwIm3DVertexSetPos(&TempBufferRenderVertices[TempBufferVerticesStored + 0], pos.x + 11.0f * TheCamera.GetUp().x, pos.y + 11.0f * TheCamera.GetUp().y, pos.z + 11.0f * TheCamera.GetUp().z);\n\tRwIm3DVertexSetRGBA(&TempBufferRenderVertices[TempBufferVerticesStored + 1], 0, 0, 0, 0);\n\tRwIm3DVertexSetPos(&TempBufferRenderVertices[TempBufferVerticesStored + 1], pos.x - 9.0f * TheCamera.GetRight().x, pos.y - 9.0f * TheCamera.GetRight().y, pos.z - 9.0f * TheCamera.GetRight().z);\n\tRwIm3DVertexSetRGBA(&TempBufferRenderVertices[TempBufferVerticesStored + 2], RAIN_COLOUR_R * intensity / 256, RAIN_COLOUR_G * intensity / 256, RAIN_COLOUR_B * intensity / 256, RAIN_ALPHA);\n\tRwIm3DVertexSetPos(&TempBufferRenderVertices[TempBufferVerticesStored + 2], pos.x, pos.y, pos.z);\n\tRwIm3DVertexSetRGBA(&TempBufferRenderVertices[TempBufferVerticesStored + 3], 0, 0, 0, 0);\n\tRwIm3DVertexSetPos(&TempBufferRenderVertices[TempBufferVerticesStored + 3], pos.x + 9.0f * TheCamera.GetRight().x, pos.y + 9.0f * TheCamera.GetRight().y, pos.z + 9.0f * TheCamera.GetRight().z);\n\tRwIm3DVertexSetRGBA(&TempBufferRenderVertices[TempBufferVerticesStored + 4], 0, 0, 0, 0); \n\tRwIm3DVertexSetPos(&TempBufferRenderVertices[TempBufferVerticesStored + 4], pos.x - 11.0f * TheCamera.GetUp().x, pos.y - 11.0f * TheCamera.GetUp().y, pos.z - 11.0f * TheCamera.GetUp().z);\n\tfloat u = STREAK_U;\n\tfloat v = STREAK_V;\n\tif (scale) {\n\t\tu *= LARGE_STREAK_COEFFICIENT;\n\t\tv *= LARGE_STREAK_COEFFICIENT;\n\t}\n\tfloat distance_coefficient;\n\tif (distance < STREAK_MIN_DISTANCE)\n\t\tdistance_coefficient = 1.0f;\n\telse if (distance > STREAK_MAX_DISTANCE)\n\t\tdistance_coefficient = 0.5f;\n\telse\n\t\tdistance_coefficient = 1.0f - 0.5f * (distance - STREAK_MIN_DISTANCE) / (STREAK_MAX_DISTANCE - STREAK_MIN_DISTANCE);\n\tu *= distance_coefficient;\n\tv *= distance_coefficient;\n\tif (!CTimer::GetIsPaused()) {\n\t\tRandomTex = 0.0f;\n\t\tRandomTexX = 0.0f;\n\t\tRandomTexY = 0.0f;\n\t}\n\tRwIm3DVertexSetU(&TempBufferRenderVertices[TempBufferVerticesStored + 0], 0.5f * u - RandomTex + RandomTexX);\n\tRwIm3DVertexSetV(&TempBufferRenderVertices[TempBufferVerticesStored + 0], -v * 0.5f + RandomTexY);\n\tRwIm3DVertexSetU(&TempBufferRenderVertices[TempBufferVerticesStored + 1], RandomTexX);\n\tRwIm3DVertexSetV(&TempBufferRenderVertices[TempBufferVerticesStored + 1], RandomTexY);\n\tRwIm3DVertexSetU(&TempBufferRenderVertices[TempBufferVerticesStored + 2], 0.5f * u + RandomTexX);\n\tRwIm3DVertexSetV(&TempBufferRenderVertices[TempBufferVerticesStored + 2], RandomTexY);\n\tRwIm3DVertexSetU(&TempBufferRenderVertices[TempBufferVerticesStored + 3], u + RandomTexX);\n\tRwIm3DVertexSetV(&TempBufferRenderVertices[TempBufferVerticesStored + 3], RandomTexY);\n\tRwIm3DVertexSetU(&TempBufferRenderVertices[TempBufferVerticesStored + 4], 0.5f * u + RandomTex + RandomTexX);\n\tRwIm3DVertexSetV(&TempBufferRenderVertices[TempBufferVerticesStored + 5], 0.5f * v + RandomTexY);\n\tTempBufferIndicesStored += 12;\n\tTempBufferVerticesStored += 5;\n}\n\nvoid CWeather::RenderRainStreaks(void)\n{\n\tif (CTimer::GetIsCodePaused())\n\t\treturn;\n\tint base_intensity = (64.0f - CTimeCycle::GetFogReduction()) / 64.0f * int(255 * Rain);\n\tif (base_intensity == 0)\n\t\treturn;\n\tif (TheCamera.m_CameraAverageSpeed > 1.75f)\n\t\treturn;\n\tTempBufferIndicesStored = 0;\n\tTempBufferVerticesStored = 0;\n\tfor (int i = 0; i < NUM_RAIN_STREAKS; i++) {\n\t\tif (Streaks[i].timer) {\n\t\t\tfloat secondsElapsed = (CTimer::GetTimeInMilliseconds() - Streaks[i].timer) / 1024.0f;\n\t\t\tif (secondsElapsed > STREAK_LIFETIME)\n\t\t\t\tStreaks[i].timer = 0;\n\t\t\telse{\n\t\t\t\tint intensity;\n\t\t\t\tif (secondsElapsed < STREAK_INTEROLATION_TIME)\n\t\t\t\t\tintensity = base_intensity * 0.25f * secondsElapsed / STREAK_INTEROLATION_TIME;\n\t\t\t\telse if (secondsElapsed > (STREAK_LIFETIME - STREAK_INTEROLATION_TIME))\n\t\t\t\t\tintensity = (STREAK_LIFETIME - secondsElapsed) * 0.25f * base_intensity / STREAK_INTEROLATION_TIME;\n\t\t\t\telse\n\t\t\t\t\tintensity = base_intensity * 0.25f;\n\t\t\t\tCVector dir = Streaks[i].direction;\n\t\t\t\tdir.Normalise();\n\t\t\t\tCVector pos = Streaks[i].position + secondsElapsed * Streaks[i].direction;\n\t\t\t\tRenderOneRainStreak(pos, dir, intensity, false, (pos - TheCamera.GetPosition()).Magnitude());\n#ifndef FIX_BUGS // remove useless code\n\t\t\t\tif (secondsElapsed > 1.0f && secondsElapsed < STREAK_LIFETIME - 1.0f) {\n\t\t\t\t\tCGeneral::GetRandomNumber(), CGeneral::GetRandomNumber();\n\t\t\t\t}\n#endif\n\t\t\t}\n\t\t}\n\t\telse if ((CGeneral::GetRandomNumber() & 0xF00) == 0){\n\t\t\t// 1/16 probability\n\t\t\tStreaks[i].direction = CVector(0.0f, 0.0f, -12.0f);\n\t\t\tStreaks[i].position = 6.0f * TheCamera.GetForward() + TheCamera.GetPosition() + CVector(-1.8f * Streaks[i].direction.x, -1.8f * Streaks[i].direction.y, 8.0f);\n\t\t\tif (!CCutsceneMgr::IsRunning()) {\n\t\t\t\tStreaks[i].position.x += 2.0f * FindPlayerSpeed().x * 60.0f;\n\t\t\t\tStreaks[i].position.y += 2.0f * FindPlayerSpeed().y * 60.0f;\n\t\t\t}\n\t\t\telse\n\t\t\t\tStreaks[i].position += (TheCamera.GetPosition() - TheCamera.m_RealPreviousCameraPosition) * 20.0f;\n\t\t\tStreaks[i].position.x += ((CGeneral::GetRandomNumber() & 255) - 128) * 0.04f;\n\t\t\tStreaks[i].position.y += ((CGeneral::GetRandomNumber() & 255) - 128) * 0.04f;\n\t\t\tStreaks[i].timer = CTimer::GetTimeInMilliseconds();\n\t\t}\n\t}\n\tif (TempBufferIndicesStored){\n\t\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);\n\t\tRwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);\n\t\tRwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE);\n\t\tRwRenderStateSet(rwRENDERSTATEFOGTYPE, (void*)rwFOGTYPELINEAR);\n\t\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE);\n\t\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE);\n\t\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);\n\t\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpRainDropTex));\n\t\tif (RwIm3DTransform(TempBufferRenderVertices, TempBufferVerticesStored, nil, 1))\n\t\t{\n\t\t\tRwIm3DRenderIndexedPrimitive(rwPRIMTYPETRILIST, TempBufferRenderIndexList, TempBufferIndicesStored);\n\t\t\tRwIm3DEnd();\n\t\t}\n\t\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);\n\t\tRwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);\n\t\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);\n\t\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);\n\t\tRwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE);\n\t\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);\n\t}\n\tTempBufferVerticesStored = 0;\n\tTempBufferIndicesStored = 0;\n}\n\n#ifdef SECUROM\nvoid CWeather::ForceHurricaneWeather()\n{\n\tfor (int i = 0; i < ARRAY_SIZE(WeatherTypesList_WithHurricanes); i++)\n\t{\n\t\tWeatherTypesList[i] = WEATHER_HURRICANE;\n\t\tWeatherTypesList_WithHurricanes[i] = WEATHER_HURRICANE;\n\t}\n\n\tCWeather::OldWeatherType = WEATHER_HURRICANE;\n\tCWeather::NewWeatherType = WEATHER_HURRICANE;\n\tCWeather::ForcedWeatherType = WEATHER_HURRICANE;\n}\n#endif\n"
  },
  {
    "path": "src/render/Weather.h",
    "content": "enum {\n\tWEATHER_RANDOM = -1,\n\tWEATHER_SUNNY = 0,\n\tWEATHER_CLOUDY,\n\tWEATHER_RAINY,\n\tWEATHER_FOGGY,\n\tWEATHER_EXTRA_SUNNY,\n\tWEATHER_HURRICANE,\n\tWEATHER_TOTAL,\n\n\tWEATHER_EXTRACOLOURS = 6\n};\n\nclass CWeather\n{\npublic:\n\tstatic int32 SoundHandle;\n\n\tstatic int32 WeatherTypeInList;\n\tstatic int16 OldWeatherType;\n\tstatic int16 NewWeatherType;\n\tstatic int16 ForcedWeatherType;\n\n\tstatic bool LightningFlash;\n\tstatic bool LightningBurst;\n\tstatic uint32 LightningStart;\n\tstatic uint32 LightningFlashLastChange;\n\tstatic uint32 WhenToPlayLightningSound;\n\tstatic uint32 LightningDuration;\n\tstatic int32 StreamAfterRainTimer;\n\n\tstatic float ExtraSunnyness;\n\tstatic float Foggyness;\n\tstatic float CloudCoverage;\n\tstatic float Wind;\n\tstatic float Rain;\n\tstatic float InterpolationValue;\n\tstatic float WetRoads;\n\tstatic float Rainbow;\n\tstatic float SunGlare;\n\tstatic float WindClipped;\n\tstatic float TrafficLightBrightness;\n\n\tstatic bool bScriptsForceRain;\n\n\tstatic void RenderRainStreaks(void);\n\tstatic void Update(void);\n\tstatic void Init(void);\n\t\n\tstatic void ReleaseWeather();\n\tstatic void ForceWeather(int16);\n\tstatic void ForceWeatherNow(int16);\n\tstatic void AddSplashesDuringHurricane();\n\tstatic void AddStreamAfterRain();\n\tstatic void AddRain();\n\tstatic void AddHeatHaze();\n\tstatic void AddBeastie();\n\n\tstatic void ForceHurricaneWeather();\n};\n\nenum {\n\tNUM_RAIN_STREAKS = 35\n};\n\nstruct tRainStreak\n{\n\tCVector position;\n\tCVector direction;\n\tuint32 timer;\n};\n\nextern RwTexture* gpRainDropTex;"
  },
  {
    "path": "src/render/WindModifiers.cpp",
    "content": "#include \"common.h\"\n#include \"WindModifiers.h\"\n#include \"Camera.h\"\n#include \"General.h\"\n\n#define MAX_HEIGHT_DIST 40.0f\n#define MIN_FADE_DIST 20.0f\n#define MAX_FADE_DIST 50.0f\n\nCWindModifiers Array[16];\nint32 CWindModifiers::Number;\n\nvoid\nCWindModifiers::RegisterOne(CVector pos, int32 type = 1)\n{\n\tif (CWindModifiers::Number < 16 && (pos - TheCamera.GetPosition()).Magnitude() < 100.0f) {\n\t\tArray[Number].m_pos = pos;\n\t\tArray[Number].m_type = type;\n\t\tNumber++;\n\t}\n}\n\nbool\nCWindModifiers::FindWindModifier(CVector pos, float *x, float *y)\n{\n\tbool bWasWindModifierFound = false;\n\tCVector2D dir;\n\tfor (int i = 0; i < Number; i++) {\n\t\tif (Array[i].m_type == 1) {\n\t\t\tfloat zDist = Abs(15.0f + pos.z - Array[i].m_pos.z);\n\n\t\t\tif (zDist < MAX_HEIGHT_DIST) {\n\t\t\t\tfloat dist = (pos - Array[i].m_pos).Magnitude();\n\t\t\t\tif (dist < MAX_FADE_DIST) {\n\t\t\t\t\tfloat distFade = dist < MIN_FADE_DIST ? 1.0f : 1.0f - (dist - MIN_FADE_DIST) / (MAX_FADE_DIST - MIN_FADE_DIST);\n\t\t\t\t\tfloat heightFade = 1.0f - zDist / MAX_HEIGHT_DIST;\n\t\t\t\t\tfloat fade = distFade * heightFade * 0.5f;\n\t\t\t\t\tdir = (pos - Array[i].m_pos) * fade / dist;\n\t\t\t\t\tbWasWindModifierFound = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (bWasWindModifierFound) {\n\t\tfloat directionMult = ((CGeneral::GetRandomNumber() & 0x1F) - 16) * 0.0035f + 1.0f;\n\t\t*x += dir.x * directionMult;\n\t\t*y += dir.y * directionMult;\n\t}\n\n\treturn bWasWindModifierFound;\n}\n"
  },
  {
    "path": "src/render/WindModifiers.h",
    "content": "#pragma once\n\nclass CWindModifiers\n{\n\tCVector m_pos;\n\tint32 m_type;\npublic:\n\tstatic int32 Number;\n\tstatic void RegisterOne(CVector pos, int32 windSourceType);\n\tstatic bool FindWindModifier(CVector pos, float *x, float *y);\n};\n"
  },
  {
    "path": "src/rw/ClumpRead.cpp",
    "content": "#include \"common.h\"\n\nstruct rpGeometryList\n{\n\tRpGeometry **geometries;\n\tint32 numGeoms;\n};\n\nstruct rpAtomicBinary\n{\n\tRwInt32 frameIndex;\n\tRwInt32 geomIndex;\n\tRwInt32 flags;\n\tRwInt32 unused;\n};\n\nstatic int32 numberGeometrys;\nstatic int32 streamPosition;\nstatic rpGeometryList gGeomList;\nstatic rwFrameList gFrameList;\nstatic RpClumpChunkInfo gClumpInfo;\n\nrpGeometryList*\nGeometryListStreamRead1(RwStream *stream, rpGeometryList *geomlist)\n{\n\tint i;\n\tRwUInt32 size, version;\n\tRwInt32 numGeoms;\n\n\tnumberGeometrys = 0;\n\tif(!RwStreamFindChunk(stream, rwID_STRUCT, &size, &version))\n\t\treturn nil;\n\tassert(size == 4);\n\tif(RwStreamRead(stream, &numGeoms, 4) != 4)\n\t\treturn nil;\n\n\tnumberGeometrys = numGeoms/2;\n\tgeomlist->numGeoms = numGeoms;\n\tif(geomlist->numGeoms > 0){\n\t\tgeomlist->geometries = (RpGeometry**)RwMalloc(geomlist->numGeoms * sizeof(RpGeometry*));\n\t\tif(geomlist->geometries == nil)\n\t\t\treturn nil;\n\t\tmemset(geomlist->geometries, 0, geomlist->numGeoms * sizeof(RpGeometry*));\n\t}else\n\t\tgeomlist->geometries = nil;\n\n\tfor(i = 0; i < numberGeometrys; i++){\n\t\tif(!RwStreamFindChunk(stream, rwID_GEOMETRY, nil, &version))\n\t\t\treturn nil;\n\t\tgeomlist->geometries[i] = RpGeometryStreamRead(stream);\n\t\tif(geomlist->geometries[i] == nil)\n\t\t\treturn nil;\n\t}\n\n\treturn geomlist;\n}\n\nrpGeometryList*\nGeometryListStreamRead2(RwStream *stream, rpGeometryList *geomlist)\n{\n\tint i;\n\tRwUInt32 version;\n\n\tfor(i = numberGeometrys; i < geomlist->numGeoms; i++){\n\t\tif(!RwStreamFindChunk(stream, rwID_GEOMETRY, nil, &version))\n\t\t\treturn nil;\n\t\tgeomlist->geometries[i] = RpGeometryStreamRead(stream);\n\t\tif(geomlist->geometries[i] == nil)\n\t\t\treturn nil;\n\t}\n\n\treturn geomlist;\n}\n\nvoid\nGeometryListDeinitialize(rpGeometryList *geomlist)\n{\n\tint i;\n\n\tfor(i = 0; i < geomlist->numGeoms; i++)\n\t\tif(geomlist->geometries[i])\n\t\t\tRpGeometryDestroy(geomlist->geometries[i]);\n\n\tif(geomlist->numGeoms){\n\t\tRwFree(geomlist->geometries);\n\t\tgeomlist->numGeoms = 0;\n\t}\n}\n\nRpAtomic*\nClumpAtomicStreamRead(RwStream *stream, rwFrameList *frmList, rpGeometryList *geomList)\n{\n\tRwUInt32 size, version;\n\trpAtomicBinary a;\n\tRpAtomic *atomic;\n\n\tnumberGeometrys = 0;\n\tif(!RwStreamFindChunk(stream, rwID_STRUCT, &size, &version))\n\t\treturn nil;\n\tassert(size <= sizeof(rpAtomicBinary));\n\tif(RwStreamRead(stream, &a, size) != size)\n\t\treturn nil;\n\n\tatomic = RpAtomicCreate();\n\tif(atomic == nil)\n\t\treturn nil;\n\n\tRpAtomicSetFlags(atomic, a.flags);\n\n\tif(frmList->numFrames){\n\t\tassert(a.frameIndex < frmList->numFrames);\n\t\tRpAtomicSetFrame(atomic, frmList->frames[a.frameIndex]);\n\t}\n\n\tif(geomList->numGeoms){\n\t\tassert(a.geomIndex < geomList->numGeoms);\n\t\tRpAtomicSetGeometry(atomic, geomList->geometries[a.geomIndex], 0);\n\t}else{\n\t\tRpGeometry *geom;\n\t\tif(!RwStreamFindChunk(stream, rwID_GEOMETRY, nil, &version)){\n\t\t\tRpAtomicDestroy(atomic);\n\t\t\treturn nil;\n\t\t}\n\t\tgeom = RpGeometryStreamRead(stream);\n\t\tif(geom == nil){\n\t\t\tRpAtomicDestroy(atomic);\n\t\t\treturn nil;\n\t\t}\n\t\tRpAtomicSetGeometry(atomic, geom, 0);\n\t\tRpGeometryDestroy(geom);\n\t}\n\n\treturn atomic;\n}\n\nbool\nRpClumpGtaStreamRead1(RwStream *stream)\n{\n\tRwUInt32 size, version;\n\n\tif(!RwStreamFindChunk(stream, rwID_STRUCT, &size, &version))\n\t\treturn false;\n\tif(version >= 0x33000){\n\t\tassert(size == 12);\n\t\tif(RwStreamRead(stream, &gClumpInfo, 12) != 12)\n\t\t\treturn false;\n\t}else{\n\t\tassert(size == 4);\n\t\tif(RwStreamRead(stream, &gClumpInfo, 4) != 4)\n\t\t\treturn false;\n\t}\n\n\tif(!RwStreamFindChunk(stream, rwID_FRAMELIST, nil, &version))\n\t\treturn false;\n\tif(rwFrameListStreamRead(stream, &gFrameList) == nil)\n\t\treturn false;\n\n\tif(!RwStreamFindChunk(stream, rwID_GEOMETRYLIST, nil, &version)){\n\t\trwFrameListDeinitialize(&gFrameList);\n\t\treturn false;\n\t}\n\tif(GeometryListStreamRead1(stream, &gGeomList) == nil){\n\t\trwFrameListDeinitialize(&gFrameList);\n\t\treturn false;\n\t}\n\tstreamPosition = STREAMPOS(stream);\n\treturn true;\n}\n\nRpClump*\nRpClumpGtaStreamRead2(RwStream *stream)\n{\n\tint i;\n\tRwUInt32 version;\n\tRpAtomic *atomic;\n\tRpClump *clump;\n\n\tclump = RpClumpCreate();\n\tif(clump == nil)\n\t\treturn nil;\n\n\tRwStreamSkip(stream, streamPosition - STREAMPOS(stream));\n\n\tif(GeometryListStreamRead2(stream, &gGeomList) == nil){\n\t\tGeometryListDeinitialize(&gGeomList);\n\t\trwFrameListDeinitialize(&gFrameList);\n\t\tRpClumpDestroy(clump);\n\t\treturn nil;\n\t}\n\n\tRpClumpSetFrame(clump, gFrameList.frames[0]);\n\n\tfor(i = 0; i < gClumpInfo.numAtomics; i++){\n\t\tif(!RwStreamFindChunk(stream, rwID_ATOMIC, nil, &version)){\n\t\t\tGeometryListDeinitialize(&gGeomList);\n\t\t\trwFrameListDeinitialize(&gFrameList);\n\t\t\tRpClumpDestroy(clump);\n\t\t\treturn nil;\n\t\t}\n\n\t\tatomic = ClumpAtomicStreamRead(stream, &gFrameList, &gGeomList);\n\t\tif(atomic == nil){\n\t\t\tGeometryListDeinitialize(&gGeomList);\n\t\t\trwFrameListDeinitialize(&gFrameList);\n\t\t\tRpClumpDestroy(clump);\n\t\t\treturn nil;\n\t\t}\n\n\t\tRpClumpAddAtomic(clump, atomic);\n\t}\n\n\tGeometryListDeinitialize(&gGeomList);\n\trwFrameListDeinitialize(&gFrameList);\n\treturn clump;\n}\n\nvoid\nRpClumpGtaCancelStream(void)\n{\n\tGeometryListDeinitialize(&gGeomList);\n\trwFrameListDeinitialize(&gFrameList);\n\tgFrameList.numFrames = 0;\n}\n"
  },
  {
    "path": "src/rw/Lights.cpp",
    "content": "#include \"common.h\"\n#include <rwcore.h>\n#include <rpworld.h>\n\n#include \"Lights.h\"\n#include \"Timer.h\"\n#include \"Timecycle.h\"\n#include \"Coronas.h\"\n#include \"Weather.h\"\n#include \"ZoneCull.h\"\n#include \"Frontend.h\"\n#include \"MBlur.h\"\n\nRpLight *pAmbient;\nRpLight *pDirect;\nRpLight *pExtraDirectionals[4] = { nil };\nint LightStrengths[4];\nint NumExtraDirLightsInWorld;\n\nRwRGBAReal AmbientLightColourForFrame;\nRwRGBAReal AmbientLightColourForFrame_PedsCarsAndObjects;\nRwRGBAReal DirectionalLightColourForFrame;\n\nRwRGBAReal AmbientLightColour;\nRwRGBAReal DirectionalLightColour;\n\n#ifdef EXTENDED_COLOURFILTER\n#include \"postfx.h\"\n#define USEBLURCOLORS CPostFX::UseBlurColours()\n#else\n#define USEBLURCOLORS CMBlur::BlurOn\n#endif\n\nvoid\nSetLightsWithTimeOfDayColour(RpWorld *)\n{\n\tCVector vec1, vec2, vecsun;\n\tRwMatrix mat;\n\n\tif(pAmbient){\n\t\tif(USEBLURCOLORS){\n\t\t\tAmbientLightColourForFrame.red = CTimeCycle::GetAmbientRed_Bl() * CCoronas::LightsMult;\n\t\t\tAmbientLightColourForFrame.green = CTimeCycle::GetAmbientGreen_Bl() * CCoronas::LightsMult;\n\t\t\tAmbientLightColourForFrame.blue = CTimeCycle::GetAmbientBlue_Bl() * CCoronas::LightsMult;\n\t\t}else{\n\t\t\tAmbientLightColourForFrame.red = CTimeCycle::GetAmbientRed() * CCoronas::LightsMult;\n\t\t\tAmbientLightColourForFrame.green = CTimeCycle::GetAmbientGreen() * CCoronas::LightsMult;\n\t\t\tAmbientLightColourForFrame.blue = CTimeCycle::GetAmbientBlue() * CCoronas::LightsMult;\n\t\t}\n\n\t\tif(USEBLURCOLORS){\n\t\t\tAmbientLightColourForFrame_PedsCarsAndObjects.red = CTimeCycle::GetAmbientRed_Obj_Bl() * CCoronas::LightsMult;\n\t\t\tAmbientLightColourForFrame_PedsCarsAndObjects.green = CTimeCycle::GetAmbientGreen_Obj_Bl() * CCoronas::LightsMult;\n\t\t\tAmbientLightColourForFrame_PedsCarsAndObjects.blue = CTimeCycle::GetAmbientBlue_Obj_Bl() * CCoronas::LightsMult;\n\t\t}else{\n\t\t\tAmbientLightColourForFrame_PedsCarsAndObjects.red = CTimeCycle::GetAmbientRed_Obj() * CCoronas::LightsMult;\n\t\t\tAmbientLightColourForFrame_PedsCarsAndObjects.green = CTimeCycle::GetAmbientGreen_Obj() * CCoronas::LightsMult;\n\t\t\tAmbientLightColourForFrame_PedsCarsAndObjects.blue = CTimeCycle::GetAmbientBlue_Obj() * CCoronas::LightsMult;\n\t\t}\n\n\t\tif(CWeather::LightningFlash && !CCullZones::CamNoRain()){\n\t\t\tAmbientLightColourForFrame.red = 1.0f;\n\t\t\tAmbientLightColourForFrame.green = 1.0f;\n\t\t\tAmbientLightColourForFrame.blue = 1.0f;\n\n\t\t\tAmbientLightColourForFrame_PedsCarsAndObjects.red = 1.0f;\n\t\t\tAmbientLightColourForFrame_PedsCarsAndObjects.green = 1.0f;\n\t\t\tAmbientLightColourForFrame_PedsCarsAndObjects.blue = 1.0f;\n\t\t}\n\t\tRpLightSetColor(pAmbient, &AmbientLightColourForFrame);\n\t}\n\n\tif(pDirect){\n\t\tDirectionalLightColourForFrame.red = CTimeCycle::GetDirectionalRed() * CCoronas::LightsMult;\n\t\tDirectionalLightColourForFrame.green = CTimeCycle::GetDirectionalGreen() * CCoronas::LightsMult;\n\t\tDirectionalLightColourForFrame.blue = CTimeCycle::GetDirectionalBlue() * CCoronas::LightsMult;\n\t\tRpLightSetColor(pDirect, &DirectionalLightColourForFrame);\n\n\t\tvecsun = CTimeCycle::m_VectorToSun[CTimeCycle::m_CurrentStoredValue];\n\t\tvec1 = CVector(0.0f, 0.0f, 1.0f);\n\t\tvec2 = CrossProduct(vec1, vecsun);\n\t\tvec2.Normalise();\n\t\tvec1 = CrossProduct(vec2, vecsun);\n\t\tmat.at.x = -vecsun.x;\n\t\tmat.at.y = -vecsun.y;\n\t\tmat.at.z = -vecsun.z;\n\t\tmat.right.x = vec1.x;\n\t\tmat.right.y = vec1.y;\n\t\tmat.right.z = vec1.z;\n\t\tmat.up.x = vec2.x;\n\t\tmat.up.y = vec2.y;\n\t\tmat.up.z = vec2.z;\n\t\tRwFrameTransform(RpLightGetFrame(pDirect), &mat, rwCOMBINEREPLACE);\n\t}\n\n\tif(FrontEndMenuManager.m_PrefsBrightness > 256){\n\t\tfloat f1 = 2.0f * (FrontEndMenuManager.m_PrefsBrightness/256.0f - 1.0f) * 0.6f + 1.0f;\n\t\tfloat f2 = 3.0f * (FrontEndMenuManager.m_PrefsBrightness/256.0f - 1.0f) * 0.6f + 1.0f;\n\n\t\tAmbientLightColourForFrame.red = Min(1.0f, AmbientLightColourForFrame.red * f2);\n\t\tAmbientLightColourForFrame.green = Min(1.0f, AmbientLightColourForFrame.green * f2);\n\t\tAmbientLightColourForFrame.blue = Min(1.0f, AmbientLightColourForFrame.blue * f2);\n\t\tAmbientLightColourForFrame_PedsCarsAndObjects.red = Min(1.0f, AmbientLightColourForFrame_PedsCarsAndObjects.red * f1);\n\t\tAmbientLightColourForFrame_PedsCarsAndObjects.green = Min(1.0f, AmbientLightColourForFrame_PedsCarsAndObjects.green * f1);\n\t\tAmbientLightColourForFrame_PedsCarsAndObjects.blue = Min(1.0f, AmbientLightColourForFrame_PedsCarsAndObjects.blue * f1);\n#ifdef FIX_BUGS\n\t\tDirectionalLightColourForFrame.red = Min(1.0f, DirectionalLightColourForFrame.red * f1);\n\t\tDirectionalLightColourForFrame.green = Min(1.0f, DirectionalLightColourForFrame.green * f1);\n\t\tDirectionalLightColourForFrame.blue = Min(1.0f, DirectionalLightColourForFrame.blue * f1);\n#else\n\t\tDirectionalLightColourForFrame.red = Min(1.0f, AmbientLightColourForFrame.red * f1);\n\t\tDirectionalLightColourForFrame.green = Min(1.0f, AmbientLightColourForFrame.green * f1);\n\t\tDirectionalLightColourForFrame.blue = Min(1.0f, AmbientLightColourForFrame.blue * f1);\n#endif\n\t}\n}\n\nRpWorld*\nLightsCreate(RpWorld *world)\n{\n\tint i;\n\tRwRGBAReal color;\n\tRwFrame *frame;\n\n\tif(world == nil)\n\t\treturn nil;\n\n\tpAmbient = RpLightCreate(rpLIGHTAMBIENT);\n\tRpLightSetFlags(pAmbient, rpLIGHTLIGHTATOMICS);\n\tcolor.red = 0.25f;\n\tcolor.green = 0.25f;\n\tcolor.blue = 0.2f;\n\tRpLightSetColor(pAmbient, &color);\n\n\tpDirect = RpLightCreate(rpLIGHTDIRECTIONAL);\n\tRpLightSetFlags(pDirect, rpLIGHTLIGHTATOMICS);\n\tcolor.red = 1.0f;\n\tcolor.green = 0.85f;\n\tcolor.blue = 0.45f;\n\tRpLightSetColor(pDirect, &color);\n\tRpLightSetRadius(pDirect, 2.0f);\n\tframe = RwFrameCreate();\n\tRpLightSetFrame(pDirect, frame);\n\tRwV3d axis = { 1.0f, 1.0f, 0.0f };\n\tRwFrameRotate(frame, &axis, 160.0f, rwCOMBINEPRECONCAT);\n\n\tRpWorldAddLight(world, pAmbient);\n\tRpWorldAddLight(world, pDirect);\n\n\tfor(i = 0; i < NUMEXTRADIRECTIONALS; i++){\n\t\tpExtraDirectionals[i] = RpLightCreate(rpLIGHTDIRECTIONAL);\n\t\tRpLightSetFlags(pExtraDirectionals[i], 0);\n\t\tcolor.red = 1.0f;\n\t\tcolor.green = 0.5f;\n\t\tcolor.blue = 0.0f;\n\t\tRpLightSetColor(pExtraDirectionals[i], &color);\n\t\tRpLightSetRadius(pExtraDirectionals[i], 2.0f);\n\t\tframe = RwFrameCreate();\n\t\tRpLightSetFrame(pExtraDirectionals[i], frame);\n\t\tRpWorldAddLight(world, pExtraDirectionals[i]);\n\t}\n\n\treturn world;\n}\n\nvoid\nLightsDestroy(RpWorld *world)\n{\n\tint i;\n\n\tif(world == nil)\n\t\treturn;\n\n\tif(pAmbient){\n\t\tRpWorldRemoveLight(world, pAmbient);\n\t\tRpLightDestroy(pAmbient);\n\t\tpAmbient = nil;\n\t}\n\n\tif(pDirect){\n\t\tRpWorldRemoveLight(world, pDirect);\n\t\tRwFrameDestroy(RpLightGetFrame(pDirect));\n\t\tRpLightDestroy(pDirect);\n\t\tpDirect = nil;\n\t}\n\n\tfor(i = 0; i < NUMEXTRADIRECTIONALS; i++)\n\t\tif(pExtraDirectionals[i]){\n\t\t\tRpWorldRemoveLight(world, pExtraDirectionals[i]);\n\t\t\tRwFrameDestroy(RpLightGetFrame(pExtraDirectionals[i]));\n\t\t\tRpLightDestroy(pExtraDirectionals[i]);\n\t\t\tpExtraDirectionals[i] = nil;\n\t\t}\n}\n\nvoid\nWorldReplaceNormalLightsWithScorched(RpWorld *world, float l)\n{\n\tRwRGBAReal color;\n\tcolor.red = l;\n\tcolor.green = l;\n\tcolor.blue = l;\n\tRpLightSetColor(pAmbient, &color);\n\tRpLightSetFlags(pDirect, 0);\n}\n\nvoid\nWorldReplaceScorchedLightsWithNormal(RpWorld *world)\n{\n\tRpLightSetColor(pAmbient, &AmbientLightColourForFrame);\n\tRpLightSetFlags(pDirect, rpLIGHTLIGHTATOMICS);\n}\n\nvoid\nAddAnExtraDirectionalLight(RpWorld *world, float dirx, float diry, float dirz, float red, float green, float blue)\n{\n\tfloat strength;\n\tint weakest;\n\tint i, n;\n\tRwRGBAReal color;\n\tRwV3d *dir;\n\n\tstrength = Max(Max(red, green), blue);\n\tn = -1;\n\tif(NumExtraDirLightsInWorld < NUMEXTRADIRECTIONALS)\n\t\tn = NumExtraDirLightsInWorld;\n\telse{\n\t\tweakest = strength;\n\t\tfor(i = 0; i < NUMEXTRADIRECTIONALS; i++)\n\t\t\tif(LightStrengths[i] < weakest){\n\t\t\t\tweakest = LightStrengths[i];\n\t\t\t\tn = i;\n\t\t\t}\n\t}\n\n\tif(n < 0)\n\t\treturn;\n\n\tcolor.red = red;\n\tcolor.green = green;\n\tcolor.blue = blue;\n\tRpLightSetColor(pExtraDirectionals[n], &color);\n\tdir = RwMatrixGetAt(RwFrameGetMatrix(RpLightGetFrame(pExtraDirectionals[n])));\n\tdir->x = -dirx;\n\tdir->y = -diry;\n\tdir->z = -dirz;\n\tRwMatrixUpdate(RwFrameGetMatrix(RpLightGetFrame(pExtraDirectionals[n])));\n\tRwFrameUpdateObjects(RpLightGetFrame(pExtraDirectionals[n]));\n\tRpLightSetFlags(pExtraDirectionals[n], rpLIGHTLIGHTATOMICS);\n\tLightStrengths[n] = strength;\n\tNumExtraDirLightsInWorld = Min(NumExtraDirLightsInWorld+1, NUMEXTRADIRECTIONALS);\n}\n\nvoid\nRemoveExtraDirectionalLights(RpWorld *world)\n{\n\tint i;\n\tfor(i = 0; i < NumExtraDirLightsInWorld; i++)\n\t\tRpLightSetFlags(pExtraDirectionals[i], 0);\n\tNumExtraDirLightsInWorld = 0;\n}\n\nvoid\nSetAmbientAndDirectionalColours(float f)\n{\n\tAmbientLightColour.red = AmbientLightColourForFrame.red * f;\n\tAmbientLightColour.green = AmbientLightColourForFrame.green * f;\n\tAmbientLightColour.blue = AmbientLightColourForFrame.blue * f;\n\n\tDirectionalLightColour.red = DirectionalLightColourForFrame.red * f;\n\tDirectionalLightColour.green = DirectionalLightColourForFrame.green * f;\n\tDirectionalLightColour.blue = DirectionalLightColourForFrame.blue * f;\n\n\tRpLightSetColor(pAmbient, &AmbientLightColour);\n\tRpLightSetColor(pDirect, &DirectionalLightColour);\n}\n\n// unused\nvoid\nSetFlashyColours(float f)\n{\n\tif(CTimer::GetTimeInMilliseconds() & 0x100){\n\t\tAmbientLightColour.red = 1.0f;\n\t\tAmbientLightColour.green = 1.0f;\n\t\tAmbientLightColour.blue = 1.0f;\n\n\t\tDirectionalLightColour.red = DirectionalLightColourForFrame.red;\n\t\tDirectionalLightColour.green = DirectionalLightColourForFrame.green;\n\t\tDirectionalLightColour.blue = DirectionalLightColourForFrame.blue;\n\n\t\tRpLightSetColor(pAmbient, &AmbientLightColour);\n\t\tRpLightSetColor(pDirect, &DirectionalLightColour);\n\t}else{\n\t\tSetAmbientAndDirectionalColours(f * 0.75f);\n\t}\n}\n\n// unused\nvoid\nSetFlashyColours_Mild(float f)\n{\n\tif(CTimer::GetTimeInMilliseconds() & 0x100){\n\t\tAmbientLightColour.red = 0.65f;\n\t\tAmbientLightColour.green = 0.65f;\n\t\tAmbientLightColour.blue = 0.65f;\n\n\t\tDirectionalLightColour.red = DirectionalLightColourForFrame.red;\n\t\tDirectionalLightColour.green = DirectionalLightColourForFrame.green;\n\t\tDirectionalLightColour.blue = DirectionalLightColourForFrame.blue;\n\n\t\tRpLightSetColor(pAmbient, &AmbientLightColour);\n\t\tRpLightSetColor(pDirect, &DirectionalLightColour);\n\t}else{\n\t\tSetAmbientAndDirectionalColours(f * 0.9f);\n\t}\n}\n\nvoid\nSetBrightMarkerColours(float f)\n{\n\tAmbientLightColour.red = 0.6f;\n\tAmbientLightColour.green = 0.6f;\n\tAmbientLightColour.blue = 0.6f;\n\n\tDirectionalLightColour.red = (1.0f - DirectionalLightColourForFrame.red) * 0.4f + DirectionalLightColourForFrame.red;\n\tDirectionalLightColour.green = (1.0f - DirectionalLightColourForFrame.green) * 0.4f + DirectionalLightColourForFrame.green;\n\tDirectionalLightColour.blue = (1.0f - DirectionalLightColourForFrame.blue) * 0.4f + DirectionalLightColourForFrame.blue;\n\n\tRpLightSetColor(pAmbient, &AmbientLightColour);\n\tRpLightSetColor(pDirect, &DirectionalLightColour);\n}\n\nvoid\nReSetAmbientAndDirectionalColours(void)\n{\n\tRpLightSetColor(pAmbient, &AmbientLightColourForFrame);\n\tRpLightSetColor(pDirect, &DirectionalLightColourForFrame);\n}\n\nvoid\nDeActivateDirectional(void)\n{\n\tRpLightSetFlags(pDirect, 0);\n}\n\nvoid\nActivateDirectional(void)\n{\n\tRpLightSetFlags(pDirect, rpLIGHTLIGHTATOMICS);\n}\n\nRwRGBAReal FullLight = { 1.0f, 1.0f, 1.0f, 1.0f };\n\nvoid\nSetFullAmbient(void)\n{\n\tRpLightSetColor(pAmbient, &FullLight);\n}\n\nvoid\nSetAmbientColours(void)\n{\n\tRpLightSetColor(pAmbient, &AmbientLightColourForFrame);\n}\n\nvoid\nSetAmbientColoursForPedsCarsAndObjects(void)\n{\n\tRpLightSetColor(pAmbient, &AmbientLightColourForFrame_PedsCarsAndObjects);\n}\n\nuint8 IndicateR[] = { 0, 255, 0, 0, 255, 255, 0 };\nuint8 IndicateG[] = { 0, 0, 255, 0, 255, 0, 255 };\nuint8 IndicateB[] = { 0, 0, 0, 255, 0, 255, 255 };\n\nvoid\nSetAmbientColoursToIndicateRoadGroup(int i)\n{\n\tAmbientLightColour.red   = IndicateR[i%7]/255.0f;\n\tAmbientLightColour.green = IndicateG[i%7]/255.0f;\n\tAmbientLightColour.blue  = IndicateB[i%7]/255.0f;\n\tRpLightSetColor(pAmbient, &AmbientLightColour);\n}\n\nvoid\nSetAmbientColours(RwRGBAReal *color)\n{\n\tRpLightSetColor(pAmbient, color);\n}\n"
  },
  {
    "path": "src/rw/Lights.h",
    "content": "#pragma once\n\nextern RpLight *pAmbient;\nextern RpLight *pDirect;\nextern RpLight *pExtraDirectionals[4];\nextern int LightStrengths[4];\nextern int NumExtraDirLightsInWorld;\n\nvoid SetLightsWithTimeOfDayColour(RpWorld *);\nRpWorld *LightsCreate(RpWorld *world);\nvoid LightsDestroy(RpWorld *world);\nvoid WorldReplaceNormalLightsWithScorched(RpWorld *world, float l);\nvoid WorldReplaceScorchedLightsWithNormal(RpWorld *world);\nvoid AddAnExtraDirectionalLight(RpWorld *world, float dirx, float diry, float dirz, float red, float green, float blue);\nvoid RemoveExtraDirectionalLights(RpWorld *world);\nvoid SetAmbientAndDirectionalColours(float f);\nvoid SetFlashyColours(float f);\nvoid SetFlashyColours_Mild(float f);\nvoid SetBrightMarkerColours(float f);\nvoid ReSetAmbientAndDirectionalColours(void);\nvoid DeActivateDirectional(void);\nvoid ActivateDirectional(void);\nvoid SetAmbientColours(void);\nvoid SetAmbientColoursForPedsCarsAndObjects(void);\nvoid SetAmbientColoursToIndicateRoadGroup(int i);\nvoid SetAmbientColours(RwRGBAReal *color);\nvoid SetFullAmbient(void);\n"
  },
  {
    "path": "src/rw/MemoryHeap.cpp",
    "content": "#include \"common.h\"\n#include \"main.h\"\n#include \"FileMgr.h\"\n#include \"Timer.h\"\n#include \"ModelInfo.h\"\n#include \"Streaming.h\"\n#include \"FileLoader.h\"\n#include \"MemoryHeap.h\"\n\n// TODO(MIAMI)\n\n#ifdef USE_CUSTOM_ALLOCATOR\n\n//#define MEMORYHEAP_ASSERT(cond) { if (!(cond)) { printf(\"ASSERT File:%s Line:%d\\n\", __FILE__, __LINE__); exit(1); } }\n//#define MEMORYHEAP_ASSERT_MESSAGE(cond, message) { if (!(cond)) { printf(\"ASSERT File:%s Line:%d:\\n\\t%s\\n\", __FILE__, __LINE__, message); exit(1); } }\n\n#define MEMORYHEAP_ASSERT(cond) assert(cond)\n#define MEMORYHEAP_ASSERT_MESSAGE(cond, message) assert(cond)\n\n// registered pointers that we keep track of\nvoid **gPtrList[4000];\nint32 numPtrs;\nint32 gPosnInList;\n// indices into the ptr list in here are free\nCStack<int32, 4000> m_ptrListIndexStack;\n// how much memory we've moved\nuint32 memMoved;\n\nCMemoryHeap gMainHeap;\n\nvoid\nCMemoryHeap::Init(uint32 total)\n{\n\tMEMORYHEAP_ASSERT((total != 0xF) != 0);\n\n\tm_totalMemUsed = 0;\n\tm_memUsed = nil;\n\tm_currentMemID = MEMID_FREE;\n\tm_blocksUsed = nil;\n\tm_totalBlocksUsed = 0;\n\tm_unkMemId = -1;\n\n\tuint8 *mem = (uint8*)malloc(total);\n\tassert(((uintptr)mem & 0xF) == 0);\n\tm_start = (HeapBlockDesc*)mem;\n\tm_end = (HeapBlockDesc*)(mem + total - sizeof(HeapBlockDesc));\n\tm_start->m_memId = MEMID_FREE;\n\tm_start->m_size = total - 2*sizeof(HeapBlockDesc);\n\tm_end->m_memId = MEMID_GAME;\n\tm_end->m_size = 0;\n\n\tm_freeList.m_last.m_size = INT_MAX;\n\tm_freeList.Init();\n\tm_freeList.Insert(m_start);\n\n\t// TODO: figure out what these are and use sizeof\n\tm_fixedSize[0].Init(0x10);\n\tm_fixedSize[1].Init(0x20);\n\tm_fixedSize[2].Init(0xE0);\n\tm_fixedSize[3].Init(0x60);\n\tm_fixedSize[4].Init(0x1C0);\n\tm_fixedSize[5].Init(0x50);\n\n\tm_currentMemID = MEMID_FREE;\t// disable registration\n\tm_memUsed = (uint32*)Malloc(NUM_MEMIDS * sizeof(uint32));\n\tm_blocksUsed = (uint32*)Malloc(NUM_MEMIDS * sizeof(uint32));\n\tRegisterMalloc(GetDescFromHeapPointer(m_memUsed));\n\tRegisterMalloc(GetDescFromHeapPointer(m_blocksUsed));\n\n\tm_currentMemID = MEMID_GAME;\n\tfor(int i = 0; i < NUM_MEMIDS; i++){\n\t\tm_memUsed[i] = 0;\n\t\tm_blocksUsed[i] = 0;\n\t}\n}\n\nvoid\nCMemoryHeap::RegisterMalloc(HeapBlockDesc *block)\n{\n\tblock->m_memId = m_currentMemID;\n\tif(m_currentMemID == MEMID_FREE)\n\t\treturn;\n\tm_totalMemUsed += block->m_size + sizeof(HeapBlockDesc);\n\tm_memUsed[m_currentMemID] += block->m_size + sizeof(HeapBlockDesc);\n\tm_blocksUsed[m_currentMemID]++;\n\tm_totalBlocksUsed++;\n}\n\nvoid\nCMemoryHeap::RegisterFree(HeapBlockDesc *block)\n{\n\tif(block->m_memId == MEMID_FREE)\n\t\treturn;\n\tm_totalMemUsed -= block->m_size + sizeof(HeapBlockDesc);\n\tm_memUsed[block->m_memId] -= block->m_size + sizeof(HeapBlockDesc);\n\tm_blocksUsed[block->m_memId]--;\n\tm_totalBlocksUsed--;\n}\n\nvoid*\nCMemoryHeap::Malloc(uint32 size)\n{\n\tstatic int recursion = 0;\n\n\t// weird way to round up\n\tif((size & 0xF) != 0)\n\t\tsize = (size&~0xF) + 0x10;\n\n\trecursion++;\n\n\t// See if we can allocate from one of the fixed-size lists\n\tfor(int i = 0; i < NUM_FIXED_MEMBLOCKS; i++){\n\t\tCommonSize *list = &m_fixedSize[i];\n\t\tif(m_fixedSize[i].m_size == size){\n\t\t\tHeapBlockDesc *block = list->Malloc();\n\t\t\tif(block){\n\t\t\t\tRegisterMalloc(block);\n\t\t\t\trecursion--;\n\t\t\t\treturn block->GetDataPointer();\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t// now try the normal free list\n\tHeapBlockDesc *next;\n\tfor(HeapBlockDesc *block = m_freeList.m_first.m_next;\n\t    block != &m_freeList.m_last;\n\t    block = next){\n\t\tMEMORYHEAP_ASSERT(block->m_memId == MEMID_FREE);\n\t\tMEMORYHEAP_ASSERT_MESSAGE(block >= m_start && block <= m_end, \"Block outside of memory\");\n\n\t\t// make sure block has maximum size\n\t\tuint32 initialsize = block->m_size;\n\t\tuint32 blocksize = CombineFreeBlocks(block);\n#ifdef FIX_BUGS\n\t\t// has to be done here because block can be moved\n\t\tnext = block->m_next;\n#endif\n\t\tif(initialsize != blocksize){\n\t\t\tblock->RemoveHeapFreeBlock();\n\t\t\tHeapBlockDesc *pos = block->m_prev->FindSmallestFreeBlock(block->m_size);\n\t\t\tblock->InsertHeapFreeBlock(pos->m_prev);\n\t\t}\n\t\tif(block->m_size >= size){\n\t\t\t// got space to allocate from!\n\t\t\tblock->RemoveHeapFreeBlock();\n\t\t\tFillInBlockData(block, block->GetNextConsecutive(), size);\n\t\t\trecursion--;\n\t\t\treturn block->GetDataPointer();\n\t\t}\n#ifndef FIX_BUGS\n\t\tnext = block->m_next;\n#endif\n\t}\n\n\t// oh no, we're losing, try to free some stuff\n\tstatic bool removeCollision = false;\n\tstatic bool removeIslands = false;\n\tstatic bool removeBigBuildings = false;\n\tsize_t initialMemoryUsed = CStreaming::ms_memoryUsed;\n\tCStreaming::MakeSpaceFor(0xCFE800 - CStreaming::ms_memoryUsed);\n\tif (recursion > 10)\n\t\tCGame::TidyUpMemory(true, false);\n\telse if (recursion > 6)\n\t\tCGame::TidyUpMemory(false, true);\n\tif (initialMemoryUsed == CStreaming::ms_memoryUsed && recursion > 11) {\n\t\tif (!removeCollision && !CGame::playingIntro) {\n\t\t\tCModelInfo::RemoveColModelsFromOtherLevels(LEVEL_GENERIC);\n\t\t\tremoveCollision = true;\n\t\t}\n\t\telse if (!removeIslands && !CGame::playingIntro) {\n\t\t\tCStreaming::RemoveIslandsNotUsed(LEVEL_INDUSTRIAL);\n\t\t\tCStreaming::RemoveIslandsNotUsed(LEVEL_COMMERCIAL);\n\t\t\tCStreaming::RemoveIslandsNotUsed(LEVEL_SUBURBAN);\n\t\t\tremoveIslands = true;\n\t\t}\n\t\telse if (!removeBigBuildings) {\n\t\t\tCStreaming::RemoveBigBuildings(LEVEL_INDUSTRIAL);\n\t\t\tCStreaming::RemoveBigBuildings(LEVEL_COMMERCIAL);\n\t\t\tCStreaming::RemoveBigBuildings(LEVEL_SUBURBAN);\n\t\t}\n\t\telse {\n\t\t\tLoadingScreen(\"NO MORE MEMORY\", nil, nil);\n\t\t\tLoadingScreen(\"NO MORE MEMORY\", nil, nil);\n\t\t}\n\t\tCGame::TidyUpMemory(true, false);\n\t}\n\tvoid *mem = Malloc(size);\n\tif (removeCollision) {\n\t\tCTimer::Stop();\n\t\t// TODO: different on PS2\n\t\tCFileLoader::LoadCollisionFromDatFile(CCollision::ms_collisionInMemory);\n\t\tremoveCollision = false;\n\t\tCTimer::Update();\n\t}\n\tif (removeBigBuildings || removeIslands) {\n\t\tCTimer::Stop();\n\t\tif (!CGame::playingIntro)\n\t\t\tCStreaming::RequestBigBuildings(CGame::currLevel);\n\t\tCStreaming::LoadAllRequestedModels(true);\n\t\tremoveBigBuildings = false;\n\t\tremoveIslands = false;\n\t\tCTimer::Update();\n\t}\n\trecursion--;\n\treturn mem;\n}\n\nvoid*\nCMemoryHeap::Realloc(void *ptr, uint32 size)\n{\n\tif(ptr == nil)\n\t\treturn Malloc(size);\n\n\t// weird way to round up\n\tif((size & 0xF) != 0)\n\t\tsize = (size&~0xF) + 0x10;\n\n\tHeapBlockDesc *block = GetDescFromHeapPointer(ptr);\n\n#ifdef FIX_BUGS\n\t// better handling of size < block->m_size\n\tif(size == 0){\n\t\tFree(ptr);\n\t\treturn nil;\n\t}\n\tif(block->m_size >= size){\n\t\t// shrink allocated block\n\t\tRegisterFree(block);\n\t\tPushMemId(block->m_memId);\n\t\tFillInBlockData(block, block->GetNextConsecutive(), size);\n\t\tPopMemId();\n\t\treturn ptr;\n\t}\n#else\n\t// not growing. just returning here is a bit cheap though\n\tif(block->m_size >= size)\n\t\treturn ptr;\n#endif\n\n\t// have to grow allocated block\n\tHeapBlockDesc *next = block->GetNextConsecutive();\n\tMEMORYHEAP_ASSERT_MESSAGE(next >= m_start && next <= m_end, \"Block outside of memory\");\n\tif(next->m_memId == MEMID_FREE){\n\t\t// try to grow the current block\n\t\t// make sure the next free block has maximum size\n\t\tuint32 freespace = CombineFreeBlocks(next);\n\t\tHeapBlockDesc *end = next->GetNextConsecutive();\n\t\tMEMORYHEAP_ASSERT_MESSAGE(end >= m_start && end <= m_end, \"Block outside of memory\");\n\t\t// why the sizeof here?\n\t\tif(block->m_size + next->m_size + sizeof(HeapBlockDesc) >= size){\n\t\t\t// enough space to grow\n\t\t\tnext->RemoveHeapFreeBlock();\n\t\t\tRegisterFree(block);\n\t\t\tPushMemId(block->m_memId);\n\t\t\tFillInBlockData(block, next->GetNextConsecutive(), size);\n\t\t\tPopMemId();\n\t\t\treturn ptr;\n\t\t}\n\t}\n\n\t// can't grow the existing block, have to get a new one and copy\n\tPushMemId(block->m_memId);\n\tvoid *dst = Malloc(size);\n\tPopMemId();\n\tmemcpy(dst, ptr, block->m_size);\n\tFree(ptr);\n\treturn dst;\n}\n\nvoid\nCMemoryHeap::Free(void *ptr)\n{\n\tHeapBlockDesc *block = GetDescFromHeapPointer(ptr);\n\tMEMORYHEAP_ASSERT_MESSAGE(block->m_memId != MEMID_FREE, \"MemoryHeap corrupt\");\n\tMEMORYHEAP_ASSERT(m_unkMemId == -1 || m_unkMemId == block->m_memId);\n\n\tRegisterFree(block);\n\tblock->m_memId = MEMID_FREE;\n\tCombineFreeBlocks(block);\n\tFreeBlock(block);\n\tif(block->m_ptrListIndex != -1){\n\t\tint32 idx = block->m_ptrListIndex;\n\t\tgPtrList[idx] = nil;\n\t\tm_ptrListIndexStack.push(idx);\n\t}\n\tblock->m_ptrListIndex = -1;\n}\n\n// allocate 'size' bytes from 'block'\nvoid\nCMemoryHeap::FillInBlockData(HeapBlockDesc *block, HeapBlockDesc *end, uint32 size)\n{\n\tblock->m_size = size;\n\tblock->m_ptrListIndex = -1;\n\tHeapBlockDesc *remainder = block->GetNextConsecutive();\n\tMEMORYHEAP_ASSERT(remainder <= end);\n\n\tif(remainder < end-1){\n\t\tRegisterMalloc(block);\n\n\t\t// can fit another block in the remaining space\n\t\tremainder->m_size = GetSizeBetweenBlocks(remainder, end);\n\t\tremainder->m_memId = MEMID_FREE;\n\t\tMEMORYHEAP_ASSERT(remainder->m_size != 0);\n\t\tFreeBlock(remainder);\n\t}else{\n\t\t// fully allocate this one\n\t\tif(remainder < end)\n\t\t\t// no gaps allowed\n\t\t\tblock->m_size = GetSizeBetweenBlocks(block, end);\n\t\tRegisterMalloc(block);\n\t}\n}\n\n// Make sure free block has no other free blocks after it\nuint32\nCMemoryHeap::CombineFreeBlocks(HeapBlockDesc *block)\n{\n\tHeapBlockDesc *next = block->GetNextConsecutive();\n\tif(next->m_memId != MEMID_FREE)\n\t\treturn block->m_size;\n\t// get rid of free blocks after this one and adjust size\n\tfor(; next->m_memId == MEMID_FREE; next = next->GetNextConsecutive())\n\t\tnext->RemoveHeapFreeBlock();\n\tblock->m_size = GetSizeBetweenBlocks(block, next);\n\treturn block->m_size;\n}\n\n// Try to move all registered memory blocks into more optimal location\nvoid\nCMemoryHeap::TidyHeap(void)\n{\n\tfor(int i = 0; i < numPtrs; i++){\n\t\tif(gPtrList[i] == nil || *gPtrList[i] == nil)\n\t\t\tcontinue;\n\t\tHeapBlockDesc *newblock = WhereShouldMemoryMove(*gPtrList[i]);\n\t\tif(newblock)\n\t\t\t*gPtrList[i] = MoveHeapBlock(newblock, GetDescFromHeapPointer(*gPtrList[i]));\n\t}\n}\n\n// MIAMI: this is empty\nvoid\nCMemoryHeap::RegisterMemPointer(void *ptr)\n{\n\tHeapBlockDesc *block = GetDescFromHeapPointer(*(void**)ptr);\n\n\tif(block->m_ptrListIndex != -1)\n\t\treturn;\t\t// already registered\n\n\tint index;\n\tif(m_ptrListIndexStack.sp > 0){\n\t\t// re-use a previously free'd index\n\t\tindex = m_ptrListIndexStack.pop();\n\t}else{\n\t\t// have to find a new index\n\t\tindex = gPosnInList;\n\n\t\tvoid **pp = gPtrList[index];\n\t\t// we're replacing an old pointer here??\n\t\tif(pp && *pp && *pp != (void*)0xDDDDDDDD)\n\t\t\tGetDescFromHeapPointer(*pp)->m_ptrListIndex = -1;\n\n\t\tgPosnInList++;\n\t\tif(gPosnInList == 4000)\n\t\t\tgPosnInList = 0;\n\t\tif(numPtrs < 4000)\n\t\t\tnumPtrs++;\n\t}\n\tgPtrList[index] = (void**)ptr;\n\tblock->m_ptrListIndex = index;\n}\n\nvoid*\nCMemoryHeap::MoveMemory(void *ptr)\n{\n\tHeapBlockDesc *newblock = WhereShouldMemoryMove(ptr);\n\tif(newblock)\n\t\treturn MoveHeapBlock(newblock, GetDescFromHeapPointer(ptr));\n\telse\n\t\treturn ptr;\n}\n\nHeapBlockDesc*\nCMemoryHeap::WhereShouldMemoryMove(void *ptr)\n{\n\tHeapBlockDesc *block = GetDescFromHeapPointer(ptr);\n\tMEMORYHEAP_ASSERT(block->m_memId != MEMID_FREE);\n\n\tHeapBlockDesc *next = block->GetNextConsecutive();\n\tif(next->m_memId != MEMID_FREE)\n\t\treturn nil;\n\n\t// we want to move the block into another block\n\t// such that the free space between this and the next block can be minimized\n\tHeapBlockDesc *newblock = m_freeList.m_first.FindSmallestFreeBlock(block->m_size);\n\t// size of free space wouldn't decrease, so return\n\tif(newblock->m_size >= block->m_size + next->m_size)\n\t\treturn nil;\n\t// size of free space wouldn't decrease enough\n\tif(newblock->m_size >= 16 + 1.125f*block->m_size)\t// what are 16 and 1.125 here? sizeof(HeapBlockDesc)?\n\t\treturn nil;\n\treturn newblock;\n}\n\nvoid*\nCMemoryHeap::MoveHeapBlock(HeapBlockDesc *dst, HeapBlockDesc *src)\n{\n\tPushMemId(src->m_memId);\n\tdst->RemoveHeapFreeBlock();\n\tFillInBlockData(dst, dst->GetNextConsecutive(), src->m_size);\n\tPopMemId();\n\tmemcpy(dst->GetDataPointer(), src->GetDataPointer(), src->m_size);\n\tmemMoved += src->m_size;\n\tdst->m_ptrListIndex = src->m_ptrListIndex;\n\tsrc->m_ptrListIndex = -1;\n\tFree(src->GetDataPointer());\n\treturn dst->GetDataPointer();\n}\n\nuint32\nCMemoryHeap::GetMemoryUsed(int32 id)\n{\n\treturn m_memUsed[id];\n}\n\nuint32\nCMemoryHeap::GetBlocksUsed(int32 id)\n{\n\treturn m_blocksUsed[id];\n}\n\nvoid\nCMemoryHeap::PopMemId(void)\n{\n\tassert(m_idStack.sp > 0);\n\tm_currentMemID = m_idStack.pop();\n\tassert(m_currentMemID != MEMID_FREE);\n}\n\nvoid\nCMemoryHeap::PushMemId(int32 id)\n{\n\tMEMORYHEAP_ASSERT(id != MEMID_FREE);\n\tassert(m_idStack.sp < 16);\n\tm_idStack.push(m_currentMemID);\n\tm_currentMemID = id;\n}\n\nvoid\nCMemoryHeap::ParseHeap(void)\n{\n\tchar tmp[16];\n\tint fd = CFileMgr::OpenFileForWriting(\"heap.txt\");\n\tCTimer::Stop();\n\n\t// CMemoryHeap::IntegrityCheck();\n\n\tuint32 addrQW = 0;\n\tfor(HeapBlockDesc *block = m_start; block < m_end; block = block->GetNextConsecutive()){\n\t\tchar chr = '*';\t// free\n\t\tif(block->m_memId != MEMID_FREE)\n\t\t\tchr = block->m_memId-1 + 'A';\n\t\tint numQW = block->m_size>>4;\n\n\t\tif((addrQW & 0x3F) == 0){\n\t\t\tsprintf(tmp, \"\\n%5dK:\", addrQW>>6);\n\t\t\tCFileMgr::Write(fd, tmp, 8);\n\t\t}\n\t\tCFileMgr::Write(fd, \"#\", 1);\t// the descriptor, has to be 16 bytes!!!!\n\t\taddrQW++;\n\n\t\twhile(numQW--){\n\t\t\tif((addrQW & 0x3F) == 0){\n\t\t\t\tsprintf(tmp, \"\\n%5dK:\", addrQW>>6);\n\t\t\t\tCFileMgr::Write(fd, tmp, 8);\n\t\t\t}\n\t\t\tCFileMgr::Write(fd, &chr, 1);\n\t\t\taddrQW++;\n\t\t}\n\t}\n\n\tCTimer::Update();\n\tCFileMgr::CloseFile(fd);\n}\n\n\nvoid\nCommonSize::Init(uint32 size)\n{\n\tm_freeList.Init();\n\tm_size = size;\n\tm_failed = 0;\n\tm_remaining = 0;\n}\n\n#endif\n"
  },
  {
    "path": "src/rw/MemoryHeap.h",
    "content": "#pragma once\n\n// some windows shit\n#ifdef MoveMemory\n#undef MoveMemory\n#endif\n\n#ifdef USE_CUSTOM_ALLOCATOR\n#define PUSH_MEMID(id) gMainHeap.PushMemId(id)\n#define POP_MEMID() gMainHeap.PopMemId()\n#define REGISTER_MEMPTR(ptr) gMainHeap.RegisterMemPointer(ptr)\n#else\n#define PUSH_MEMID(id)\n#define POP_MEMID()\n#define REGISTER_MEMPTR(ptr)\n#endif\n\nenum {\n\tMEMID_FREE,\n\tMEMID_GAME = 1,\t// \"Game\"\n\tMEMID_WORLD = 2,\t// \"World\"\n\tMEMID_ANIMATION = 3,\t// \"Animation\"\n\tMEMID_POOLS = 4,\t// \"Pools\"\n\tMEMID_DEF_MODELS = 5,\t// \"Default Models\"\n\tMEMID_STREAM = 6,\t// \"Streaming\"\n\tMEMID_STREAM_MODELS = 7,\t// \"Streamed Models\"\n\tMEMID_STREAM_LODS = 8,\t// \"Streamed LODs\"\n\tMEMID_STREAM_TEXUTRES = 9,\t// \"Streamed Textures\"\n\tMEMID_STREAM_COLLISION = 10,\t// \"Streamed Collision\"\n\tMEMID_STREAM_ANIMATION = 11,\t// \"Streamed Animation\"\n\tMEMID_TEXTURES = 12,\t// \"Textures\"\n\tMEMID_COLLISION = 13,\t// \"Collision\"\n\tMEMID_PRE_ALLOC = 14,\t// \"PreAlloc\"\n\tMEMID_GAME_PROCESS = 15,\t// \"Game Process\"\n\tMEMID_SCRIPT = 16,\t// \"Script\"\n\tMEMID_CARS = 17,\t// \"Cars\"\n\tMEMID_RENDER = 18,\t// \"Render\"\n\tMEMID_PED_ATTR = 19,\t// \"Ped Attr\"\n\tNUM_MEMIDS,\n\n\tNUM_FIXED_MEMBLOCKS = 6\n};\n\ntemplate<typename T, uint32 N>\nclass CStack\n{\npublic:\n\tT values[N];\n\tuint32 sp;\n\n\tCStack() : sp(0) {}\n\tvoid push(const T& val) { values[sp++] = val; }\n\tT& pop() { return values[--sp]; }\n};\n\n\nstruct HeapBlockDesc\n{\n\tuint32 m_size;\n\tint16 m_memId;\n\tint16 m_ptrListIndex;\n\tHeapBlockDesc *m_next;\n\tHeapBlockDesc *m_prev;\n\n\tHeapBlockDesc *GetNextConsecutive(void)\n\t{\n\t\treturn (HeapBlockDesc*)((uintptr)this + sizeof(HeapBlockDesc) + m_size);\n\t}\n\n\tvoid *GetDataPointer(void)\n\t{\n\t\treturn (void*)((uintptr)this + sizeof(HeapBlockDesc));\n\t}\n\n\tvoid RemoveHeapFreeBlock(void)\n\t{\n\t\tm_next->m_prev = m_prev;\n\t\tm_prev->m_next = m_next;\n\t}\n\n\t// after node\n\tvoid InsertHeapFreeBlock(HeapBlockDesc *node)\n\t{\n\t\tm_next = node->m_next;\n\t\tnode->m_next->m_prev = this;\n\t\tm_prev = node;\n\t\tnode->m_next = this;\n\t}\n\n\tHeapBlockDesc *FindSmallestFreeBlock(uint32 size)\n\t{\n\t\tHeapBlockDesc *b;\n\t\tfor(b = m_next; b->m_size < size; b = b->m_next);\n\t\treturn b;\n\t}\n};\n\n#ifdef USE_CUSTOM_ALLOCATOR\n// TODO: figure something out for 64 bit pointers\nstatic_assert(sizeof(HeapBlockDesc) == 0x10, \"HeapBlockDesc must have 0x10 size otherwise most of assumptions don't make sense\");\n#endif\n\nstruct HeapBlockList\n{\n\tHeapBlockDesc m_first;\n\tHeapBlockDesc m_last;\n\n\tvoid Init(void)\n\t{\n\t\tm_first.m_next = &m_last;\n\t\tm_last.m_prev = &m_first;\n\t}\n\n\tvoid Insert(HeapBlockDesc *node)\n\t{\n\t\tnode->InsertHeapFreeBlock(&m_first);\n\t}\n};\n\nstruct CommonSize\n{\n\tHeapBlockList m_freeList;\n\tuint32 m_size;\n\tuint32 m_failed;\n\tuint32 m_remaining;\n\n\tvoid Init(uint32 size);\n\tvoid Free(HeapBlockDesc *node)\n\t{\n\t\tm_freeList.Insert(node);\n\t\tm_remaining++;\n\t}\n\tHeapBlockDesc *Malloc(void)\n\t{\n\t\tif(m_freeList.m_first.m_next == &m_freeList.m_last){\n\t\t\tm_failed++;\n\t\t\treturn nil;\n\t\t}\n\t\tHeapBlockDesc *block = m_freeList.m_first.m_next;\n\t\tm_remaining--;\n\t\tblock->RemoveHeapFreeBlock();\n\t\tblock->m_ptrListIndex = -1;\n\t\treturn block;\n\t}\n};\n\nclass CMemoryHeap\n{\npublic:\n\tHeapBlockDesc *m_start;\n\tHeapBlockDesc *m_end;\n\tHeapBlockList m_freeList;\n\tCommonSize m_fixedSize[NUM_FIXED_MEMBLOCKS];\n\tuint32 m_totalMemUsed;\n\tCStack<int32, 16> m_idStack;\n\tuint32 m_currentMemID;\n\tuint32 *m_memUsed;\n\tuint32 m_totalBlocksUsed;\n\tuint32 *m_blocksUsed;\n\tuint32 m_unkMemId;\n\n\tCMemoryHeap(void) : m_start(nil) {}\n\tvoid Init(uint32 total);\n\tvoid RegisterMalloc(HeapBlockDesc *block);\n\tvoid RegisterFree(HeapBlockDesc *block);\n\tvoid *Malloc(uint32 size);\n\tvoid *Realloc(void *ptr, uint32 size);\n\tvoid Free(void *ptr);\n\tvoid FillInBlockData(HeapBlockDesc *block, HeapBlockDesc *end, uint32 size);\n\tuint32 CombineFreeBlocks(HeapBlockDesc *block);\n\tvoid *MoveMemory(void *ptr);\n\tHeapBlockDesc *WhereShouldMemoryMove(void *ptr);\n\tvoid *MoveHeapBlock(HeapBlockDesc *dst, HeapBlockDesc *src);\n\tvoid PopMemId(void);\n\tvoid PushMemId(int32 id);\n\tvoid RegisterMemPointer(void *ptr);\n\tvoid TidyHeap(void);\n\tuint32 GetMemoryUsed(int32 id);\n\tuint32 GetBlocksUsed(int32 id);\n\tint32 GetLargestFreeBlock(void) { return m_freeList.m_last.m_prev->m_size; }\n\n\tvoid ParseHeap(void);\n\n\tHeapBlockDesc *GetDescFromHeapPointer(void *block)\n\t{\n\t\treturn (HeapBlockDesc*)((uintptr)block - sizeof(HeapBlockDesc));\n\t}\n\tuint32 GetSizeBetweenBlocks(HeapBlockDesc *first, HeapBlockDesc *second)\n\t{\n\t\treturn (uintptr)second - (uintptr)first - sizeof(HeapBlockDesc);\n\t}\n\tvoid FreeBlock(HeapBlockDesc *block){\n\t\tfor(int i = 0; i < NUM_FIXED_MEMBLOCKS; i++){\n\t\t\tif(m_fixedSize[i].m_size == block->m_size){\n\t\t\t\tm_fixedSize[i].Free(block);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\tHeapBlockDesc *b = m_freeList.m_first.FindSmallestFreeBlock(block->m_size);\n\t\tblock->InsertHeapFreeBlock(b->m_prev);\n\t}\n};\n\nextern CMemoryHeap gMainHeap;\n"
  },
  {
    "path": "src/rw/MemoryMgr.cpp",
    "content": "#include \"common.h\"\n#include \"MemoryHeap.h\"\n#include \"MemoryMgr.h\"\n\n\nuint8 *pMemoryTop;\n\nvoid\nInitMemoryMgr(void)\n{\n#ifdef USE_CUSTOM_ALLOCATOR\n#ifdef GTA_PS2\n#error \"finish this\"\n#else\n\t// randomly allocate 128mb\n\tgMainHeap.Init(128*1024*1024);\n#endif\n#endif\n}\n\n\nRwMemoryFunctions memFuncs = {\n\tMemoryMgrMalloc,\n\tMemoryMgrFree,\n\tMemoryMgrRealloc,\n\tMemoryMgrCalloc\n};\n\n#ifdef USE_CUSTOM_ALLOCATOR\n// game seems to be using heap directly here, but this is nicer\nvoid *operator new(size_t sz) { return MemoryMgrMalloc(sz); }\nvoid *operator new[](size_t sz) { return MemoryMgrMalloc(sz); }\nvoid operator delete(void *ptr) noexcept { MemoryMgrFree(ptr); }\nvoid operator delete[](void *ptr) noexcept { MemoryMgrFree(ptr); }\n#endif\n\nvoid*\nMemoryMgrMalloc(size_t size)\n{\n#ifdef USE_CUSTOM_ALLOCATOR\n\tvoid *mem = gMainHeap.Malloc(size);\n#else\n\tvoid *mem = malloc(size);\n#endif\n\tif((uint8*)mem + size > pMemoryTop)\n\t\tpMemoryTop = (uint8*)mem + size ;\n\treturn mem;\n}\n\nvoid*\nMemoryMgrRealloc(void *ptr, size_t size)\n{\n#ifdef USE_CUSTOM_ALLOCATOR\n\tvoid *mem = gMainHeap.Realloc(ptr, size);\n#else\n\tvoid *mem = realloc(ptr, size);\n#endif\n\tif((uint8*)mem + size  > pMemoryTop)\n\t\tpMemoryTop = (uint8*)mem + size ;\n\treturn mem;\n}\n\nvoid*\nMemoryMgrCalloc(size_t num, size_t size)\n{\n#ifdef USE_CUSTOM_ALLOCATOR\n\tvoid *mem = gMainHeap.Malloc(num*size);\n#else\n\tvoid *mem = calloc(num, size);\n#endif\n\tif((uint8*)mem + size  > pMemoryTop)\n\t\tpMemoryTop = (uint8*)mem + size ;\n#ifdef FIX_BUGS\n\tmemset(mem, 0, num*size);\n#endif\n\treturn mem;\n}\n\nvoid\nMemoryMgrFree(void *ptr)\n{\n#ifdef USE_CUSTOM_ALLOCATOR\n#ifdef FIX_BUGS\n\t// i don't suppose this is handled by RW?\n\tif(ptr == nil) return;\n#endif\n\tgMainHeap.Free(ptr);\n#else\n\tfree(ptr);\n#endif\n}\n\nvoid *\nRwMallocAlign(RwUInt32 size, RwUInt32 align)\n{\n#if defined (FIX_BUGS) || defined(FIX_BUGS_64)\n\tuintptr ptralign = align-1;\n\tvoid *mem = (void *)MemoryMgrMalloc(size + sizeof(uintptr) + ptralign);\n\n\tASSERT(mem != nil);\n\n\tvoid *addr = (void *)((((uintptr)mem) + sizeof(uintptr) + ptralign) & ~ptralign);\n\n\tASSERT(addr != nil);\n#else\n\tvoid *mem = (void *)MemoryMgrMalloc(size + align);\n\n\tASSERT(mem != nil);\n\n\tvoid *addr = (void *)((((uintptr)mem) + align) & ~(align - 1));\n\n\tASSERT(addr != nil);\n#endif\n\n\t*(((void **)addr) - 1) = mem;\n\n\treturn addr;\n}\n\nvoid\nRwFreeAlign(void *mem)\n{\n\tASSERT(mem != nil);\n\n\tvoid *addr = *(((void **)mem) - 1);\n\n\tASSERT(addr != nil);\n\n\tMemoryMgrFree(addr);\n}\n"
  },
  {
    "path": "src/rw/MemoryMgr.h",
    "content": "#pragma once\n\nextern RwMemoryFunctions memFuncs;\nvoid InitMemoryMgr(void);\n\nvoid *MemoryMgrMalloc(size_t size);\nvoid *MemoryMgrRealloc(void *ptr, size_t size);\nvoid *MemoryMgrCalloc(size_t num, size_t size);\nvoid MemoryMgrFree(void *ptr);\n\nvoid *RwMallocAlign(RwUInt32 size, RwUInt32 align);\nvoid RwFreeAlign(void *mem);\n"
  },
  {
    "path": "src/rw/NodeName.cpp",
    "content": "#include \"common.h\"\n\n#include \"NodeName.h\"\n\nstatic int32 gPluginOffset;\n\nenum\n{\n\tID_NODENAME = MAKECHUNKID(rwVENDORID_ROCKSTAR, 0xFE),\n};\n\n#define NODENAMEEXT(o) (RWPLUGINOFFSET(char, o, gPluginOffset))\n\nvoid*\nNodeNameConstructor(void *object, RwInt32 offsetInObject, RwInt32 sizeInObject)\n{\n\tif(gPluginOffset > 0)\n\t\tNODENAMEEXT(object)[0] = '\\0';\n\treturn object;\n}\n\nvoid*\nNodeNameDestructor(void *object, RwInt32 offsetInObject, RwInt32 sizeInObject)\n{\n\treturn object;\n}\n\nvoid*\nNodeNameCopy(void *dstObject, const void *srcObject, RwInt32 offsetInObject, RwInt32 sizeInObject)\n{\n\tstrncpy(NODENAMEEXT(dstObject), NODENAMEEXT(srcObject), 23);\n\treturn nil;\n}\n\nRwStream*\nNodeNameStreamRead(RwStream *stream, RwInt32 binaryLength, void *object, RwInt32 offsetInObject, RwInt32 sizeInObject)\n{\n\tRwStreamRead(stream, NODENAMEEXT(object), binaryLength);\n\tNODENAMEEXT(object)[binaryLength] = '\\0';\n\treturn stream;\n}\n\nRwStream*\nNodeNameStreamWrite(RwStream *stream, RwInt32 binaryLength, const void *object, RwInt32 offsetInObject, RwInt32 sizeInObject)\n{\n\tRwStreamWrite(stream, NODENAMEEXT(object), binaryLength);\n\treturn stream;\n}\n\nRwInt32\nNodeNameStreamGetSize(const void *object, RwInt32 offsetInObject, RwInt32 sizeInObject)\n{\n\tchar *name = NODENAMEEXT(object);\t// can't be nil\n\treturn name ? (RwInt32)rwstrlen(name) : 0;\n}\n\nbool\nNodeNamePluginAttach(void)\n{\n\tgPluginOffset = RwFrameRegisterPlugin(24, ID_NODENAME,\n                                NodeNameConstructor,\n                                NodeNameDestructor,\n                                NodeNameCopy);\n\tRwFrameRegisterPluginStream(ID_NODENAME,\n\t\tNodeNameStreamRead,\n\t\tNodeNameStreamWrite,\n\t\tNodeNameStreamGetSize);\n\treturn gPluginOffset != -1;\n}\n\nchar*\nGetFrameNodeName(RwFrame *frame)\n{\n\tif(gPluginOffset < 0)\n\t\treturn nil;\n\treturn NODENAMEEXT(frame);\n}\n"
  },
  {
    "path": "src/rw/NodeName.h",
    "content": "#pragma once\n\nbool NodeNamePluginAttach(void);\nchar *GetFrameNodeName(RwFrame *frame);\n"
  },
  {
    "path": "src/rw/RwHelper.cpp",
    "content": "#define WITHD3D\n#include \"common.h\"\n\n#include \"Timecycle.h\"\n#include \"skeleton.h\"\n#include \"Debug.h\"\n#if !defined(FINAL) || defined(DEBUGMENU)\n#include \"rtcharse.h\"\n#endif\n#ifndef FINAL\nRtCharset *debugCharset;\nbool bDebugRenderGroups;\n#endif\n\n#ifdef PS2_ALPHA_TEST\nbool gPS2alphaTest = true;\n#else\nbool gPS2alphaTest = false;\n#endif\nbool gBackfaceCulling = true;\n\n#if !defined(FINAL) || defined(DEBUGMENU)\nstatic bool charsetOpen;\nvoid OpenCharsetSafe()\n{\n\tif(!charsetOpen)\n\t\tRtCharsetOpen();\n\tcharsetOpen = true;\n}\n#endif\n\nvoid CreateDebugFont()\n{\n#ifndef FINAL\n\tRwRGBA color = { 255, 255, 128, 255 };\n\tRwRGBA colorbg = { 0, 0, 0, 0 };\n\tOpenCharsetSafe();\n\tdebugCharset = RtCharsetCreate(&color, &colorbg);\n#endif\n}\n\nvoid DestroyDebugFont()\n{\n#ifndef FINAL\n\tRtCharsetDestroy(debugCharset);\n\tRtCharsetClose();\n\tcharsetOpen = false;\n#endif\n}\n\nvoid ObrsPrintfString(const char *str, short x, short y)\n{\n#ifndef FINAL\n\tRtCharsetPrintBuffered(debugCharset, str, x*8, y*16, true);\n#endif\n}\n\nvoid FlushObrsPrintfs()\n{\n#ifndef FINAL\n\tRtCharsetBufferFlush();\n#endif\n}\n\nvoid\nDefinedState(void)\n{\n\tRwRenderStateSet(rwRENDERSTATETEXTUREADDRESS, (void*)rwTEXTUREADDRESSWRAP);\n\tRwRenderStateSet(rwRENDERSTATETEXTUREPERSPECTIVE, (void*)TRUE);\n\tRwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);\n\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);\n\tRwRenderStateSet(rwRENDERSTATESHADEMODE, (void*)rwSHADEMODEGOURAUD);\n\tRwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERLINEAR);\n\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);\n\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);\n\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);\n\t//RwRenderStateSet(rwRENDERSTATEALPHAPRIMITIVEBUFFER, (void*)FALSE);\n\tRwRenderStateSet(rwRENDERSTATEBORDERCOLOR, (void*)RWRGBALONG(0, 0, 0, 255));\n\tRwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE);\n\tRwRenderStateSet(rwRENDERSTATEFOGCOLOR,\n\t\t(void*)RWRGBALONG(CTimeCycle::GetFogRed(), CTimeCycle::GetFogGreen(), CTimeCycle::GetFogBlue(), 255));\n\tRwRenderStateSet(rwRENDERSTATEFOGTYPE, (void*)rwFOGTYPELINEAR);\n\tRwRenderStateSet(rwRENDERSTATECULLMODE, (void*)rwCULLMODECULLNONE);\n\n#ifdef LIBRW\n\trw::SetRenderState(rw::ALPHATESTFUNC, rw::ALPHAGREATEREQUAL);\n\trw::SetRenderState(rw::ALPHATESTREF, 3);\n\n\trw::SetRenderState(rw::GSALPHATEST, gPS2alphaTest);\n#else\n\t// D3D stuff\n\tRwD3D8SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATER);\n\tRwD3D8SetRenderState(D3DRS_ALPHAREF, 2);\n#endif\n}\n\nvoid\nSetCullMode(uint32 mode)\n{\n\tif(gBackfaceCulling)\n\t\tRwRenderStateSet(rwRENDERSTATECULLMODE, (void*)mode);\n\telse\n\t\tRwRenderStateSet(rwRENDERSTATECULLMODE, (void*)rwCULLMODECULLNONE);\n}\n\n#ifndef FINAL\nvoid\nPushRendergroup(const char *name)\n{\n\tif(!bDebugRenderGroups)\n\t\treturn;\n#if defined(RW_OPENGL)\n\tif(GLAD_GL_KHR_debug)\n\t\tglPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 0, -1, name);\n#elif defined(RW_D3D9)\n\tstatic WCHAR tmp[256];\n\tMultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, tmp, sizeof(tmp));\n\tD3DPERF_BeginEvent(0xFFFFFFFF, tmp);\n#endif\n}\n\nvoid\nPopRendergroup(void)\n{\n\tif(!bDebugRenderGroups)\n\t\treturn;\n#if defined(RW_OPENGL)\n\tif(GLAD_GL_KHR_debug)\n\t\tglPopDebugGroup();\n#elif defined(RW_D3D9)\n\tD3DPERF_EndEvent();\n#endif\n}\n#endif\n\nRwFrame*\nGetFirstFrameCallback(RwFrame *child, void *data)\n{\n\t*(RwFrame**)data = child;\n\treturn nil;\n}\n\nRwFrame*\nGetFirstChild(RwFrame *frame)\n{\n\tRwFrame *child;\n\n\tchild = nil;\n\tRwFrameForAllChildren(frame, GetFirstFrameCallback, &child);\n\treturn child;\n}\n\nRwObject*\nGetFirstObjectCallback(RwObject *object, void *data)\n{\n\t*(RwObject**)data = object;\n\treturn nil;\n}\n\nRwObject*\nGetFirstObject(RwFrame *frame)\n{\n\tRwObject *obj;\n\n\tobj = nil;\n\tRwFrameForAllObjects(frame, GetFirstObjectCallback, &obj);\n\treturn obj;\n}\n\nRpAtomic*\nGetFirstAtomicCallback(RpAtomic *atm, void *data)\n{\n\t*(RpAtomic**)data = atm;\n\treturn nil;\n}\n\nRpAtomic*\nGetFirstAtomic(RpClump *clump)\n{\n\tRpAtomic *atm;\n\n\tatm = nil;\n\tRpClumpForAllAtomics(clump, GetFirstAtomicCallback, &atm);\n\treturn atm;\n}\n\nRwTexture*\nGetFirstTextureCallback(RwTexture *tex, void *data)\n{\n\t*(RwTexture**)data = tex;\n\treturn nil;\n}\n\nRwTexture*\nGetFirstTexture(RwTexDictionary *txd)\n{\n\tRwTexture *tex;\n\n\ttex = nil;\n\tRwTexDictionaryForAllTextures(txd, GetFirstTextureCallback, &tex);\n\treturn tex;\n}\n\nbool\nIsClumpSkinned(RpClump *clump)\n{\n\tRpAtomic *atomic = GetFirstAtomic(clump);\n\treturn atomic ? RpSkinGeometryGetSkin(RpAtomicGetGeometry(atomic)) : nil;\n}\n\nstatic RpAtomic*\nGetAnimHierarchyCallback(RpAtomic *atomic, void *data)\n{\n\t*(RpHAnimHierarchy**)data = RpSkinAtomicGetHAnimHierarchy(atomic);\n\treturn nil;\n}\n\nRpHAnimHierarchy*\nGetAnimHierarchyFromSkinClump(RpClump *clump)\n{\n\tRpHAnimHierarchy *hier = nil;\n\tRpClumpForAllAtomics(clump, GetAnimHierarchyCallback, &hier);\n\treturn hier;\n}\n\nstatic RwFrame*\nGetAnimHierarchyFromClumpCB(RwFrame *frame, void *data)\n{\n\tRpHAnimHierarchy *hier = RpHAnimFrameGetHierarchy(frame);\n\tif(hier){\n\t\t*(RpHAnimHierarchy**)data = hier;\n\t\treturn nil;\n\t}\n\tRwFrameForAllChildren(frame, GetAnimHierarchyFromClumpCB, data);\n\treturn frame;\n}\n\nRpHAnimHierarchy*\nGetAnimHierarchyFromClump(RpClump *clump)\n{\n\tRpHAnimHierarchy *hier = nil;\n\tRwFrameForAllChildren(RpClumpGetFrame(clump), GetAnimHierarchyFromClumpCB, &hier);\n\treturn hier;\n}\n\nvoid\nSkinGetBonePositionsToTable(RpClump *clump, RwV3d *boneTable)\n{\n\tint i, parent;\n\tRpAtomic *atomic;\n\tRpSkin *skin;\n\tRpHAnimHierarchy *hier;\n\tint numBones;\n\tRwMatrix m, invmat;\n\tint stack[32];\n\tint sp;\n\n\tif(boneTable == nil)\n\t\treturn;\n\n\tatomic = GetFirstAtomic(clump);\t\t// mobile, also VC\n\tassert(atomic);\n\tskin = RpSkinGeometryGetSkin(RpAtomicGetGeometry(atomic));\n\tassert(skin);\n\thier = GetAnimHierarchyFromSkinClump(clump);\n\tassert(hier);\n\tboneTable[0].x = 0.0f;\n\tboneTable[0].y = 0.0f;\n\tboneTable[0].z = 0.0f;\n\tnumBones = RpSkinGetNumBones(skin);\n\tparent = 0;\n\tsp = 0;\n#ifdef FIX_BUGS\n\tstack[0] = 0;\t// i think this is ok\n#endif\n\tfor(i = 1; i < numBones; i++){\n\t\tRwMatrixCopy(&m, &RpSkinGetSkinToBoneMatrices(skin)[i]);\n\t\tRwMatrixInvert(&invmat, &m);\n\t\tconst RwMatrix *x = RpSkinGetSkinToBoneMatrices(skin);\n\t\tRwV3dTransformPoints(&boneTable[i], &invmat.pos, 1, &x[parent]);\n\t\tif(HIERNODEINFO(hier)[i].flags & rpHANIMPUSHPARENTMATRIX)\n\t\t\tstack[++sp] = parent;\n\t\tif(HIERNODEINFO(hier)[i].flags & rpHANIMPOPPARENTMATRIX)\n\t\t\tparent = stack[sp--];\n\t\telse\n\t\t\tparent = i;\n\n\t\t//assert(parent >= 0 && parent < numBones);\n\t}\n}\n\nRpHAnimAnimation*\nHAnimAnimationCreateForHierarchy(RpHAnimHierarchy *hier)\n{\n\tint i;\n#if defined FIX_BUGS || defined LIBRW\n\tint numNodes = hier->numNodes*2;\t// you're supposed to have at least two KFs per node\n#else\n\tint numNodes = hier->numNodes;\n#endif\n\tRpHAnimAnimation *anim = RpHAnimAnimationCreate(rpHANIMSTDKEYFRAMETYPEID, numNodes, 0, 0.0f);\n\tif(anim == nil)\n\t\treturn nil;\n\tRpHAnimStdKeyFrame *frame;\n\tfor(i = 0; i < numNodes; i++){\n\t\tframe = (RpHAnimStdKeyFrame*)HANIMFRAME(anim, i);\t// games uses struct size here, not safe\n\t\tframe->q.real = 1.0f;\n\t\tframe->q.imag.x = frame->q.imag.y = frame->q.imag.z = 0.0f;\n\t\tframe->t.x = frame->t.y = frame->t.z = 0.0f;\n#if defined FIX_BUGS || defined LIBRW\n\t\t// times are subtracted and divided giving NaNs\n\t\t// so they can't both be 0\n\t\tframe->time = i/hier->numNodes;\n#else\n\t\tframe->time = 0.0f;\n#endif\n\t\tframe->prevFrame = nil;\n\t}\n\treturn anim;\n}\n\nvoid\nRenderSkeleton(RpHAnimHierarchy *hier)\n{\n\tint i;\n\tint sp;\n\tint stack[32];\n\tint par;\n\tCVector p1, p2;\n\tint numNodes = hier->numNodes;\n\tRwMatrix *mats = RpHAnimHierarchyGetMatrixArray(hier);\n\tp1 = mats[0].pos;\n\n\tpar = 0;\n\tsp = 0;\n\tstack[sp++] = par;\n\tfor(i = 1; i < numNodes; i++){\n\t\tp1 = mats[par].pos;\n\t\tp2 = mats[i].pos;\n\t\tCDebug::AddLine(p1, p2, 0xFFFFFFFF, 0xFFFFFFFF);\n\t\tif(HIERNODEINFO(hier)[i].flags & rpHANIMPUSHPARENTMATRIX)\n\t\t\tstack[sp++] = par;\n\t\tpar = i;\n\t\tif(HIERNODEINFO(hier)[i].flags & rpHANIMPOPPARENTMATRIX)\n\t\t\tpar = stack[--sp];\n\t}\n}\n\n\nRwBool Im2DRenderQuad(RwReal x1, RwReal y1, RwReal x2, RwReal y2, RwReal z, RwReal recipCamZ, RwReal uvOffset)\n{\n    RwIm2DVertex        vx[4];\n\n    /*\n     *  Render an opaque white 2D quad at the given coordinates and\n     *  spanning a whole texture.\n     */\n\n    RwIm2DVertexSetScreenX(&vx[0], x1);\n    RwIm2DVertexSetScreenY(&vx[0], y1);\n    RwIm2DVertexSetScreenZ(&vx[0], z);\n    RwIm2DVertexSetIntRGBA(&vx[0], 255, 255, 255, 255);\n    RwIm2DVertexSetRecipCameraZ(&vx[0], recipCamZ);\n    RwIm2DVertexSetU(&vx[0], uvOffset, recipCamZ);\n    RwIm2DVertexSetV(&vx[0], uvOffset, recipCamZ);\n\n    RwIm2DVertexSetScreenX(&vx[1], x1);\n    RwIm2DVertexSetScreenY(&vx[1], y2);\n    RwIm2DVertexSetScreenZ(&vx[1], z);\n    RwIm2DVertexSetIntRGBA(&vx[1], 255, 255, 255, 255);\n    RwIm2DVertexSetRecipCameraZ(&vx[1], recipCamZ);\n    RwIm2DVertexSetU(&vx[1], uvOffset, recipCamZ);\n    RwIm2DVertexSetV(&vx[1], 1.0f + uvOffset, recipCamZ);\n\n    RwIm2DVertexSetScreenX(&vx[2], x2);\n    RwIm2DVertexSetScreenY(&vx[2], y1);\n    RwIm2DVertexSetScreenZ(&vx[2], z);\n    RwIm2DVertexSetIntRGBA(&vx[2], 255, 255, 255, 255);\n    RwIm2DVertexSetRecipCameraZ(&vx[2], recipCamZ);\n    RwIm2DVertexSetU(&vx[2], 1.0f + uvOffset, recipCamZ);\n    RwIm2DVertexSetV(&vx[2], uvOffset, recipCamZ);\n\n    RwIm2DVertexSetScreenX(&vx[3], x2);\n    RwIm2DVertexSetScreenY(&vx[3], y2);\n    RwIm2DVertexSetScreenZ(&vx[3], z);\n    RwIm2DVertexSetIntRGBA(&vx[3], 255, 255, 255, 255);\n    RwIm2DVertexSetRecipCameraZ(&vx[3], recipCamZ);\n    RwIm2DVertexSetU(&vx[3], 1.0f + uvOffset, recipCamZ);\n    RwIm2DVertexSetV(&vx[3], 1.0f + uvOffset, recipCamZ);\n\n    RwIm2DRenderPrimitive(rwPRIMTYPETRISTRIP, vx, 4);\n\n    return TRUE;\n}\n\nbool b_cbsUseLTM = true;\n\nRpAtomic *cbsCalcMeanBSphereRadiusCB(RpAtomic *atomic, void *data)\n{\n\tRwV3d atomicPos;\n\n\tif ( b_cbsUseLTM )\n\t\tRwV3dTransformPoints(&atomicPos, &RpAtomicGetBoundingSphere(atomic)->center, 1, RwFrameGetLTM(RpClumpGetFrame(atomic->clump)));\n\telse\n\t\tRwV3dTransformPoints(&atomicPos, &RpAtomicGetBoundingSphere(atomic)->center, 1, RwFrameGetMatrix(RpClumpGetFrame(atomic->clump)));\n\n\tRwV3d temp;\n\tRwV3dSub(&temp, &atomicPos, &((RwSphere *)data)->center);\t\n\tRwReal radius = RwV3dLength(&temp) + RpAtomicGetBoundingSphere(atomic)->radius;\n\t\n\tif ( ((RwSphere *)data)->radius < radius )\n\t\t((RwSphere *)data)->radius = radius;\n\n\treturn atomic;\n}\n\nRpAtomic *cbsCalcMeanBSphereCenterCB(RpAtomic *atomic, void *data)\n{\n\tRwV3d atomicPos;\n\n\tif ( b_cbsUseLTM )\n\t\tRwV3dTransformPoints(&atomicPos, &RpAtomicGetBoundingSphere(atomic)->center, 1, RwFrameGetLTM(RpClumpGetFrame(atomic->clump)));\n\telse\n\t\tRwV3dTransformPoints(&atomicPos, &RpAtomicGetBoundingSphere(atomic)->center, 1, RwFrameGetMatrix(RpClumpGetFrame(atomic->clump)));\n\t\n\tRwV3dAdd(&((RwSphere *)data)->center, &((RwSphere *)data)->center, &atomicPos);\n\t\n\treturn atomic;\n}\n\nRpClump *RpClumpGetBoundingSphere(RpClump *clump, RwSphere *sphere, bool useLTM)\n{\n\tRwMatrix matrix;\n\tRwSphere result = { 0.0f, 0.0f, 0.0f, 0.0f };\n\t\n\tb_cbsUseLTM = useLTM;\n \n\tif ( clump == nil || sphere == nil )\n\t\treturn nil;\n  \n\tsphere->radius = 0.0f;\n\tsphere->center.x = 0.0f;\n\tsphere->center.y = 0.0f;\n\tsphere->center.z = 0.0f;\n    \n\tRwInt32 numAtomics = RpClumpGetNumAtomics(clump);\n\tif ( numAtomics < 1.0f )\n\t\treturn nil;\n\t\n\tRpClumpForAllAtomics(clump, cbsCalcMeanBSphereCenterCB, &result);\n\t\n\tRwV3dScale(&result.center, &result.center, 1.0f/numAtomics);\n\t\n\tRpClumpForAllAtomics(clump, cbsCalcMeanBSphereRadiusCB, &result);\n\t\n\tif ( b_cbsUseLTM )\n\t\tRwMatrixInvert(&matrix, RwFrameGetLTM(RpClumpGetFrame(clump)));\n\telse\n\t\tRwMatrixInvert(&matrix, RwFrameGetMatrix(RpClumpGetFrame(clump)));\n\t\n\tRwV3dTransformPoints(&result.center, &result.center, 1, &matrix);\n\n\t*sphere = result;\n\t\n\treturn clump;\n}\n\nvoid\nCameraSize(RwCamera * camera, RwRect * rect,\n\t\t   RwReal viewWindow, RwReal aspectRatio)\n{\n\tif (camera)\n\t{\n\t\tRwVideoMode         videoMode;\n\t\tRwRect              r;\n\t\tRwRect              origSize = { 0, 0, 0, 0 };\t// FIX just to make the compier happy\n\t\tRwV2d               vw;\n\n\t\tRwEngineGetVideoModeInfo(&videoMode,\n\t\t\t\t\t\t\t\t RwEngineGetCurrentVideoMode());\n\n\t\torigSize.w  = RwRasterGetWidth(RwCameraGetRaster(camera));\n\t\torigSize.h = RwRasterGetHeight(RwCameraGetRaster(camera));\n\n\t\tif (!rect)\n\t\t{\n\t\t\tif (videoMode.flags & rwVIDEOMODEEXCLUSIVE)\n\t\t\t{\n\t\t\t\t/* For full screen applications, resizing the camera just doesn't\n\t\t\t\t * make sense, use the video mode size.\n\t\t\t\t */\n\n\t\t\t\tr.x = r.y = 0;\n\t\t\t\tr.w = videoMode.width;\n\t\t\t\tr.h = videoMode.height;\n\t\t\t\trect = &r;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t/*\n\t\t\t\trect not specified - reuse current values\n\t\t\t\t*/\n\t\t\t\tr.w = RwRasterGetWidth(RwCameraGetRaster(camera));\n\t\t\t\tr.h = RwRasterGetHeight(RwCameraGetRaster(camera));\n\t\t\t\tr.x = r.y = 0;\n\t\t\t\trect = &r;\n\t\t\t}\n\t\t}\n\n\t\tif (( origSize.w != rect->w ) || ( origSize.h != rect->h ))\n\t\t{\n\t\t\tRwRaster           *raster;\n\t\t\tRwRaster           *zRaster;\n\n\t\t\t// BUG: game just changes camera raster's sizes, but this is a hack\n#if defined FIX_BUGS || defined LIBRW\n\t\t\t/*\n\t\t\t * Destroy rasters...\n\t\t\t */\n\n\t\t\traster = RwCameraGetRaster(camera);\n\t\t\tif( raster )\n\t\t\t{\n\t\t\t\tRwRasterDestroy(raster);\n\t\t\t\tcamera->frameBuffer = nil;\n\t\t\t}\n\n\t\t\tzRaster = RwCameraGetZRaster(camera);\n\t\t\tif( zRaster )\n\t\t\t{\n\t\t\t\tRwRasterDestroy(zRaster);\n\t\t\t\tcamera->zBuffer = nil;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t * Create new rasters...\n\t\t\t */\n\n\t\t\traster = RwRasterCreate(rect->w, rect->h, 0, rwRASTERTYPECAMERA);\n\t\t\tzRaster = RwRasterCreate(rect->w, rect->h, 0, rwRASTERTYPEZBUFFER);\n\n\t\t\tif( raster && zRaster )\n\t\t\t{\n\t\t\t\tRwCameraSetRaster(camera, raster);\n\t\t\t\tRwCameraSetZRaster(camera, zRaster);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif( raster )\n\t\t\t\t{\n\t\t\t\t\tRwRasterDestroy(raster);\n\t\t\t\t}\n\n\t\t\t\tif( zRaster )\n\t\t\t\t{\n\t\t\t\t\tRwRasterDestroy(zRaster);\n\t\t\t\t}\n\n\t\t\t\trect->x = origSize.x;\n\t\t\t\trect->y = origSize.y;\n\t\t\t\trect->w = origSize.w;\n\t\t\t\trect->h = origSize.h;\n\n\t\t\t\t/*\n\t\t\t\t * Use default values...\n\t\t\t\t */\n\t\t\t\traster =\n\t\t\t\t\tRwRasterCreate(rect->w, rect->h, 0, rwRASTERTYPECAMERA);\n\n\t\t\t\tzRaster =\n\t\t\t\t\tRwRasterCreate(rect->w, rect->h, 0, rwRASTERTYPEZBUFFER);\n\n\t\t\t\tRwCameraSetRaster(camera, raster);\n\t\t\t\tRwCameraSetZRaster(camera, zRaster);\n\t\t\t}\n#else\n\t\t\traster = RwCameraGetRaster(camera);\n\t\t\tzRaster = RwCameraGetZRaster(camera);\n\t\t\t\n\t\t\traster->width = zRaster->width = rect->w;\n\t\t\traster->height = zRaster->height = rect->h;\n#endif\n\t\t}\n\n\t\t/* Figure out the view window */\n\t\tif (videoMode.flags & rwVIDEOMODEEXCLUSIVE)\n\t\t{\n\t\t\t/* derive ratio from aspect ratio */\n\t\t\tvw.x = viewWindow;\n\t\t\tvw.y = viewWindow / aspectRatio;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t/* derive from pixel ratios */\n\t\t\tif (rect->w > rect->h)\n\t\t\t{\n\t\t\t\tvw.x = viewWindow;\n\t\t\t\tvw.y = (rect->h * viewWindow) / rect->w;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tvw.x = (rect->w * viewWindow) / rect->h;\n\t\t\t\tvw.y = viewWindow;\n\t\t\t}\n\t\t}\n\n\t\tRwCameraSetViewWindow(camera, &vw);\n\n\t\tRsGlobal.width  = rect->w;\n\t\tRsGlobal.height = rect->h;\n\t}\n\n\treturn;\n}\n\nvoid\nCameraDestroy(RwCamera *camera)\n{\n\tRwRaster    *raster, *tmpRaster;\n\tRwFrame     *frame;\n\n\tif (camera)\n\t{\n\t\tframe = RwCameraGetFrame(camera);\n\t\tif (frame)\n\t\t{\n\t\t\tRwFrameDestroy(frame);\n\t\t}\n\n\t\traster = RwCameraGetRaster(camera);\n\t\tif (raster)\n\t\t{\n\t\t\ttmpRaster = RwRasterGetParent(raster);\n\n\t\t\tRwRasterDestroy(raster);\n\n\t\t\tif ((tmpRaster != nil) && (tmpRaster != raster))\n\t\t\t{\n\t\t\t\tRwRasterDestroy(tmpRaster);\n\t\t\t}\n\t\t}\n\n\t\traster = RwCameraGetZRaster(camera);\n\t\tif (raster)\n\t\t{\n\t\t\ttmpRaster = RwRasterGetParent(raster);\n\n\t\t\tRwRasterDestroy(raster);\n\n\t\t\tif ((tmpRaster != nil) && (tmpRaster != raster))\n\t\t\t{\n\t\t\t\tRwRasterDestroy(tmpRaster);\n\t\t\t}\n\t\t}\n\n\t\tRwCameraDestroy(camera);\n\t}\n\n\treturn;\n}\n\nRwCamera           *\nCameraCreate(RwInt32 width, RwInt32 height, RwBool zBuffer)\n{\n\tRwCamera           *camera;\n\n\tcamera = RwCameraCreate();\n\n\tif (camera)\n\t{\n\t\tRwCameraSetFrame(camera, RwFrameCreate());\n\t\tRwCameraSetRaster(camera,\n\t\t\t\t\t\t  RwRasterCreate(0, 0, 0, rwRASTERTYPECAMERA));\n\n\t\tif (zBuffer)\n\t\t{\n\t\t\tRwCameraSetZRaster(camera,\n\t\t\t\t\t\t\t   RwRasterCreate(0, 0, 0,\n\t\t\t\t\t\t\t\t\t\t\t  rwRASTERTYPEZBUFFER));\n\t\t}\n\n\t\t/* now check that everything is valid */\n\t\tif (RwCameraGetFrame(camera) &&\n\t\t\tRwCameraGetRaster(camera) &&\n\t\t\tRwRasterGetParent(RwCameraGetRaster(camera)) &&\n\t\t\t(!zBuffer || (RwCameraGetZRaster(camera) &&\n\t\t\t\t\t\t  RwRasterGetParent(RwCameraGetZRaster\n\t\t\t\t\t\t\t\t\t\t\t(camera)))))\n\t\t{\n\t\t\t/* everything OK */\n\t\t\treturn (camera);\n\t\t}\n\t}\n\n\t/* if we're here then an error must have occurred so clean up */\n\n\tCameraDestroy(camera);\n\treturn (nil);\n}\n\n#ifdef LIBRW\n#include <rpmatfx.h>\n#include \"VehicleModelInfo.h\"\n\nint32\nfindPlatform(rw::Atomic *a)\n{\n\trw::Geometry *g = a->geometry;\n\tif(g->instData)\n\t\treturn g->instData->platform;\n\treturn 0;\n}\n\n// Game doesn't read atomic extensions so we never get any other than the default pipe,\n// but we need it for uninstancing\nvoid\nattachPipe(rw::Atomic *atomic)\n{\n\tif(RpSkinGeometryGetSkin(RpAtomicGetGeometry(atomic)))\n\t\tatomic->pipeline = rw::skinGlobals.pipelines[rw::platform];\n\telse{\n\t\tint fx = rpMATFXEFFECTNULL;\n\t\tRpGeometryForAllMaterials(RpAtomicGetGeometry(atomic), CVehicleModelInfo::GetMatFXEffectMaterialCB, &fx);\n\t\tif(fx != rpMATFXEFFECTNULL)\n\t\t\tRpMatFXAtomicEnableEffects(atomic);\n\t}\n}\n\n// Attach pipes for the platform we have native data for so we can uninstance\nvoid\nswitchPipes(rw::Atomic *a, int32 platform)\n{\n\tif(a->pipeline && a->pipeline->platform != platform){\n\t\tuint32 plgid = a->pipeline->pluginID;\n\t\tswitch(plgid){\n\t\t// assume default pipe won't be attached explicitly\n\t\tcase rw::ID_SKIN:\n\t\t\ta->pipeline = rw::skinGlobals.pipelines[platform];\n\t\t\tbreak;\n\t\tcase rw::ID_MATFX:\n\t\t\ta->pipeline = rw::matFXGlobals.pipelines[platform];\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\nRpAtomic*\nConvertPlatformAtomic(RpAtomic *atomic, void *data)\n{\n\tint32 driver = rw::platform;\n\tint32 platform = findPlatform(atomic);\n\tif(platform != 0 && platform != driver){\n\t\tattachPipe(atomic);\t// kludge\n\t\trw::ObjPipeline *origPipe = atomic->pipeline;\n\t\trw::platform = platform;\n\t\tswitchPipes(atomic, rw::platform);\n\t\tif(atomic->geometry->flags & rw::Geometry::NATIVE)\n\t\t\tatomic->uninstance();\n\t\t// no ADC in this game\n\t\t//rw::ps2::unconvertADC(atomic->geometry);\n\t\trw::platform = driver;\n\t\tatomic->pipeline = origPipe;\n\t}\n\treturn atomic;\n}\n#endif\n\n#if defined(FIX_BUGS) && defined(GTA_PC)\nRwUInt32 saved_alphafunc, saved_alpharef;\n\nvoid\nSetAlphaTest(RwUInt32 alpharef)\n{\n#ifdef LIBRW\n\tsaved_alphafunc = rw::GetRenderState(rw::ALPHATESTFUNC);\n\tsaved_alpharef = rw::GetRenderState(rw::ALPHATESTREF);\n\n\trw::SetRenderState(rw::ALPHATESTFUNC, rw::ALPHAGREATEREQUAL);\n\trw::SetRenderState(rw::ALPHATESTREF, 0);\n#else\n\tRwD3D8GetRenderState(D3DRS_ALPHAFUNC, &saved_alphafunc);\n\tRwD3D8GetRenderState(D3DRS_ALPHAREF, &saved_alpharef);\n\t\n\tRwD3D8SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL);\n\tRwD3D8SetRenderState(D3DRS_ALPHAREF, alpharef);\n#endif\n}\n\nvoid\nRestoreAlphaTest()\n{\n#ifdef LIBRW\n\trw::SetRenderState(rw::ALPHATESTFUNC, saved_alphafunc);\n\trw::SetRenderState(rw::ALPHATESTREF, saved_alpharef);\n#else\n\tRwD3D8SetRenderState(D3DRS_ALPHAFUNC, saved_alphafunc);\n\tRwD3D8SetRenderState(D3DRS_ALPHAREF, saved_alpharef);\n#endif\n}\n#endif\n"
  },
  {
    "path": "src/rw/RwHelper.h",
    "content": "#pragma once\n\nextern bool bDebugRenderGroups;\nextern bool gPS2alphaTest;\nextern bool gBackfaceCulling;\n\nvoid OpenCharsetSafe();\nvoid CreateDebugFont();\nvoid DestroyDebugFont();\nvoid ObrsPrintfString(const char *str, short x, short y);\nvoid FlushObrsPrintfs();\nvoid DefinedState(void);\nvoid SetCullMode(uint32 mode);\nRwFrame *GetFirstChild(RwFrame *frame);\nRwObject *GetFirstObject(RwFrame *frame);\nRpAtomic *GetFirstAtomic(RpClump *clump);\nRwTexture *GetFirstTexture(RwTexDictionary *txd);\n\nbool IsClumpSkinned(RpClump *clump);\nRpHAnimHierarchy *GetAnimHierarchyFromSkinClump(RpClump *clump);\t// get from atomic\nRpHAnimHierarchy *GetAnimHierarchyFromClump(RpClump *clump);\t// get from frame\nvoid SkinGetBonePositionsToTable(RpClump *clump, RwV3d *boneTable);\nRpHAnimAnimation *HAnimAnimationCreateForHierarchy(RpHAnimHierarchy *hier);\nRpAtomic *AtomicRemoveAnimFromSkinCB(RpAtomic *atomic, void *data);\nvoid RenderSkeleton(RpHAnimHierarchy *hier);\n\nRwBool Im2DRenderQuad(RwReal x1, RwReal y1, RwReal x2, RwReal y2, RwReal z, RwReal recipCamZ, RwReal uvOffset);\nRpClump *RpClumpGetBoundingSphere(RpClump *clump, RwSphere *sphere, bool useLTM);\n\nRwTexDictionary *RwTexDictionaryGtaStreamRead(RwStream *stream);\nRwTexDictionary *RwTexDictionaryGtaStreamRead1(RwStream *stream);\nRwTexDictionary *RwTexDictionaryGtaStreamRead2(RwStream *stream, RwTexDictionary *texDict);\nvoid ReadVideoCardCapsFile(uint32&, uint32&, uint32&, uint32&);\nbool CheckVideoCardCaps(void);\nvoid WriteVideoCardCapsFile(void);\nbool CanVideoCardDoDXT(void);\nvoid ConvertingTexturesScreen(uint32, uint32, const char*);\nvoid DealWithTxdWriteError(uint32, uint32, const char*);\nbool CreateTxdImageForVideoCard();\n\nbool RpClumpGtaStreamRead1(RwStream *stream);\nRpClump *RpClumpGtaStreamRead2(RwStream *stream);\nvoid RpClumpGtaCancelStream(void);\n\nvoid CameraSize(RwCamera *camera,\n                RwRect *rect,\n                RwReal viewWindow,\n                RwReal aspectRatio);\nvoid CameraDestroy(RwCamera *camera);\nRwCamera *CameraCreate(RwInt32 width,\n                       RwInt32 height,\n                       RwBool zBuffer);\n\n\t\t\t\t\t   \n\nRpAtomic *ConvertPlatformAtomic(RpAtomic *atomic, void *data);\n\n#if defined(FIX_BUGS) && defined (GTA_PC)\nvoid SetAlphaTest(RwUInt32 alpharef);\nvoid RestoreAlphaTest();\n#else\n#define SetAlphaTest(a) (0)\n#define RestoreAlphaTest() (0)\n#endif"
  },
  {
    "path": "src/rw/RwMatFX.cpp",
    "content": "#ifndef LIBRW\n\n#define WITHD3D\n#include \"common.h\"\n#include \"rpmatfx.h\"\n\nstruct MatFXNothing { int pad[5]; int effect; };\n\nstruct MatFXBump\n{\n\tRwFrame *bumpFrame;\n\tRwTexture *bumpedTex;\n\tRwTexture *bumpTex;\n\tfloat negBumpCoefficient;\n\tint pad;\n\tint effect;\n};\n\nstruct MatFXEnv\n{\n\tRwFrame *envFrame;\n\tRwTexture *envTex;\n\tfloat envCoeff;\n\tint envFBalpha;\n\tint pad;\n\tint effect;\n};\n\nstruct MatFXDual\n{\n\tRwTexture *dualTex;\n\tRwInt32 srcBlend;\n\tRwInt32 dstBlend;\n};\n\n\nstruct MatFX\n{\n\tunion {\n\t\tMatFXNothing n;\n\t\tMatFXBump b;\n\t\tMatFXEnv e;\n\t\tMatFXDual d;\n\t} fx[2];\n\tint effects;\n};\n\nextern \"C\" {\n\textern int MatFXMaterialDataOffset;\n\textern int MatFXAtomicDataOffset;\n\n\tvoid _rpMatFXD3D8AtomicMatFXEnvRender(RxD3D8InstanceData* inst, int flags, int sel, RwTexture* texture, RwTexture* envMap);\n\tvoid _rpMatFXD3D8AtomicMatFXRenderBlack(RxD3D8InstanceData *inst);\n\tvoid _rpMatFXD3D8AtomicMatFXBumpMapRender(RxD3D8InstanceData *inst, int flags, RwTexture *texture, RwTexture *bumpMap, RwTexture *envMap);\n\tvoid _rpMatFXD3D8AtomicMatFXDualPassRender(RxD3D8InstanceData *inst, int flags, RwTexture *texture, RwTexture *dualTexture);\n}\n\n\n#ifdef PS2_MATFX\n\nvoid\n_rpMatFXD3D8AtomicMatFXDefaultRender(RxD3D8InstanceData *inst, int flags, RwTexture *texture)\n{\n\tif(flags & (rpGEOMETRYTEXTURED|rpGEOMETRYTEXTURED2) && texture)\n\t\tRwD3D8SetTexture(texture, 0);\n\telse\n\t\tRwD3D8SetTexture(nil, 0);\n\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)(inst->vertexAlpha || inst->material->color.alpha != 0xFF));\n\tRwD3D8SetRenderState(D3DRS_DIFFUSEMATERIALSOURCE, inst->vertexAlpha != 0);\n\tRwD3D8SetPixelShader(0);\n\tRwD3D8SetVertexShader(inst->vertexShader);\n\tRwD3D8SetStreamSource(0, inst->vertexBuffer, inst->stride);\n\n\tif(inst->indexBuffer){\n\t\tRwD3D8SetIndices(inst->indexBuffer, inst->baseIndex);\n\t\tRwD3D8DrawIndexedPrimitive(inst->primType, 0, inst->numVertices, 0, inst->numIndices);\n\t}else\n\t\tRwD3D8DrawPrimitive(inst->primType, inst->baseIndex, inst->numVertices);\n}\n\n// map [-1; -1] -> [0; 1], flip V\nstatic RwMatrix scalenormal = {\n\t{ 0.5f, 0.0f, 0.0f }, 0,\n\t{ 0.0f, -0.5f, 0.0f }, 0,\n\t{ 0.0f, 0.0f, 1.0f }, 0,\n\t{ 0.5f, 0.5f, 0.0f }, 0,\n\t\n};\n\n// flipped U for PS2\nstatic RwMatrix scalenormal_flipU = {\n\t{ -0.5f, 0.0f, 0.0f }, 0,\n\t{ 0.0f, -0.5f, 0.0f }, 0,\n\t{ 0.0f, 0.0f, 1.0f }, 0,\n\t{ 0.5f, 0.5f, 0.0f }, 0,\n\t\n};\n\nvoid\nApplyEnvMapTextureMatrix(RwTexture *tex, int n, RwFrame *frame)\n{\n\tRwD3D8SetTexture(tex, n);\n\tRwD3D8SetTextureStageState(n, D3DRS_ALPHAREF, 2);\n\tRwD3D8SetTextureStageState(n, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACENORMAL);\n\tif(frame){\n\t\tRwMatrix *envframemat = RwMatrixCreate();\n\t\tRwMatrix *tmpmat = RwMatrixCreate();\n\t\tRwMatrix *envmat = RwMatrixCreate();\n\n\t\tRwMatrixInvert(envframemat, RwFrameGetLTM(frame));\n\t\t// PS2\n\t\t// can this be simplified?\n\t\t*tmpmat = *RwFrameGetLTM(RwCameraGetFrame((RwCamera*)RWSRCGLOBAL(curCamera)));\n\t\tRwV3dNegate(&tmpmat->right, &tmpmat->right);\n\t\ttmpmat->flags = 0;\n\t\ttmpmat->pos.x = 0.0f;\n\t\ttmpmat->pos.y = 0.0f;\n\t\ttmpmat->pos.z = 0.0f;\n\t\tRwMatrixMultiply(envmat, tmpmat, envframemat);\n\t\t*tmpmat = *envmat;\n\t\t// important because envframemat can have a translation that we don't like\n\t\ttmpmat->pos.x = 0.0f;\n\t\ttmpmat->pos.y = 0.0f;\n\t\ttmpmat->pos.z = 0.0f;\n\t\t// for some reason we flip in U as well\n\t\tRwMatrixMultiply(envmat, tmpmat, &scalenormal_flipU);\n\n\t\tRwD3D8SetTransform(D3DTS_TEXTURE0+n, envmat);\n\n\t\tRwMatrixDestroy(envmat);\n\t\tRwMatrixDestroy(tmpmat);\n\t\tRwMatrixDestroy(envframemat);\n\t}else\n\t\tRwD3D8SetTransform(D3DTS_TEXTURE0+n, &scalenormal);\n}\n\nvoid\n_rpMatFXD3D8AtomicMatFXEnvRender_ps2(RxD3D8InstanceData *inst, int flags, int sel, RwTexture *texture, RwTexture *envMap)\n{\n\tMatFX *matfx = *RWPLUGINOFFSET(MatFX*, inst->material, MatFXMaterialDataOffset);\n\tMatFXEnv *env = &matfx->fx[sel].e;\n\n\tuint8 intens = (uint8)(env->envCoeff*255.0f);\n\n\tif(intens == 0 || envMap == nil){\n\t\tif(sel == 0)\n\t\t\t_rpMatFXD3D8AtomicMatFXDefaultRender(inst, flags, texture);\n\t\treturn;\n\t}\n\n\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)(inst->vertexAlpha || inst->material->color.alpha != 0xFF));\n\tif(flags & (rpGEOMETRYTEXTURED|rpGEOMETRYTEXTURED2) && texture)\n\t\tRwD3D8SetTexture(texture, 0);\n\telse\n\t\tRwD3D8SetTexture(nil, 0);\n\tRwD3D8SetPixelShader(0);\n\tRwD3D8SetVertexShader(inst->vertexShader);\n\tRwD3D8SetStreamSource(0, inst->vertexBuffer, inst->stride);\n\tRwD3D8SetIndices(inst->indexBuffer, inst->baseIndex);\n\tif(inst->indexBuffer)\n\t\tRwD3D8DrawIndexedPrimitive(inst->primType, 0, inst->numVertices, 0, inst->numIndices);\n\telse\n\t\tRwD3D8DrawPrimitive(inst->primType, inst->baseIndex, inst->numVertices);\n\n\t// Effect pass\n\t\n\tApplyEnvMapTextureMatrix(envMap, 0, env->envFrame);\n\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);\n\tRwUInt32 src, dst, lighting, zwrite, fog, fogcol;\n\tRwRenderStateGet(rwRENDERSTATESRCBLEND, &src);\n\tRwRenderStateGet(rwRENDERSTATEDESTBLEND, &dst);\n\n\t// This is of course not using framebuffer alpha,\n\t// but if the diffuse texture had no alpha, the result should actually be rather the same\n\tif(env->envFBalpha)\n\t\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);\n\telse\n\t\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE);\n\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE);\n\tRwD3D8GetRenderState(D3DRS_LIGHTING, &lighting);\n\tRwD3D8GetRenderState(D3DRS_ZWRITEENABLE, &zwrite);\n\tRwD3D8GetRenderState(D3DRS_FOGENABLE, &fog);\n\tRwD3D8SetRenderState(D3DRS_ZWRITEENABLE, FALSE);\n\tif(fog){\n\t\tRwD3D8GetRenderState(D3DRS_FOGCOLOR, &fogcol);\n\t\tRwD3D8SetRenderState(D3DRS_FOGCOLOR, 0);\n\t}\n\n\tD3DCOLOR texfactor = D3DCOLOR_RGBA(intens, intens, intens, intens);\n\tRwD3D8SetRenderState(D3DRS_TEXTUREFACTOR, texfactor);\n\tRwD3D8SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_MODULATE);\n\tRwD3D8SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_CURRENT);\n\tRwD3D8SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_TFACTOR);\n\t// alpha unused\n\t//RwD3D8SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);\n\t//RwD3D8SetTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_CURRENT);\n\t//RwD3D8SetTextureStageState(1, D3DTSS_ALPHAARG2, D3DTA_TFACTOR);\n\n\tif(inst->indexBuffer)\n\t\tRwD3D8DrawIndexedPrimitive(inst->primType, 0, inst->numVertices, 0, inst->numIndices);\n\telse\n\t\tRwD3D8DrawPrimitive(inst->primType, inst->baseIndex, inst->numVertices);\n\n\t// Reset states\n\n\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);\n\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)src);\n\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)dst);\n\tRwD3D8SetRenderState(D3DRS_LIGHTING, lighting);\n\tRwD3D8SetRenderState(D3DRS_ZWRITEENABLE, zwrite);\n\tif(fog)\n\t\tRwD3D8SetRenderState(D3DRS_FOGCOLOR, fogcol);\n\tRwD3D8SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);\n\tRwD3D8SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);\n\tRwD3D8SetTextureStageState(0, D3DTSS_TEXTURETRANSFORMFLAGS, 0);\n\tRwD3D8SetTextureStageState(0, D3DTSS_TEXCOORDINDEX, 0);\n}\n\nvoid\n_rwD3D8EnableClippingIfNeeded(void *object, RwUInt8 type)\n{\n\tint clip;\n\tif (type == rpATOMIC)\n\t\tclip = !RwD3D8CameraIsSphereFullyInsideFrustum(RwCameraGetCurrentCameraMacro(), RpAtomicGetWorldBoundingSphere((RpAtomic *)object));\n\telse\n\t\tclip = !RwD3D8CameraIsBBoxFullyInsideFrustum(RwCameraGetCurrentCameraMacro(), &((RpWorldSector *)object)->tightBoundingBox);\n\tRwD3D8SetRenderState(D3DRS_CLIPPING, clip);\n}\n\nvoid\n_rwD3D8AtomicMatFXRenderCallback(RwResEntry *repEntry, void *object, RwUInt8 type, RwUInt32 flags)\n{\n\tRwBool lighting;\n\tRwBool forceBlack;\n\tRxD3D8ResEntryHeader *header;\n\tRxD3D8InstanceData *inst;\n\tRwInt32 i;\n\n\tif (flags & rpGEOMETRYPRELIT) {\n\t\tRwD3D8SetRenderState(D3DRS_COLORVERTEX, 1);\n\t\tRwD3D8SetRenderState(D3DRS_EMISSIVEMATERIALSOURCE, D3DMCS_COLOR1);\n\t} else {\n\t\tRwD3D8SetRenderState(D3DRS_COLORVERTEX, 0);\n\t\tRwD3D8SetRenderState(D3DRS_EMISSIVEMATERIALSOURCE, D3DMCS_MATERIAL);\n\t}\n\n\t_rwD3D8EnableClippingIfNeeded(object, type);\n\n\tRwD3D8GetRenderState(D3DRS_LIGHTING, &lighting);\n\tif (lighting || flags & rpGEOMETRYPRELIT) {\n\t\tforceBlack = FALSE;\n\t} else {\n\t\tforceBlack = TRUE;\n\t\tRwD3D8SetTexture(nil, 0);\n\t\tRwD3D8SetRenderState(D3DRS_TEXTUREFACTOR, D3DCOLOR_RGBA(0, 0, 0, 255));\n\t\tRwD3D8SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG2);\n\t\tRwD3D8SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_TFACTOR);\n\t}\n\n\theader = (RxD3D8ResEntryHeader *)(repEntry + 1);\n\tinst = (RxD3D8InstanceData *)(header + 1);\n\tfor (i = 0; i < header->numMeshes; i++) {\n\t\tif (forceBlack)\n\t\t\t_rpMatFXD3D8AtomicMatFXRenderBlack(inst);\n\t\telse {\n\t\t\tif (lighting)\n\t\t\t\tRwD3D8SetSurfaceProperties(&inst->material->color, &inst->material->surfaceProps, flags & rpGEOMETRYMODULATEMATERIALCOLOR);\n\t\t\tMatFX *matfx = *RWPLUGINOFFSET(MatFX *, inst->material, MatFXMaterialDataOffset);\n\t\t\tint effect = matfx ? matfx->effects : rpMATFXEFFECTNULL;\n\t\t\tswitch (effect) {\n\t\t\tcase rpMATFXEFFECTNULL:\n\t\t\tdefault:\n\t\t\t\t_rpMatFXD3D8AtomicMatFXDefaultRender(inst, flags, inst->material->texture);\n\t\t\t\tbreak;\n\t\t\tcase rpMATFXEFFECTBUMPMAP:\n\t\t\t\t_rpMatFXD3D8AtomicMatFXBumpMapRender(inst, flags, inst->material->texture, matfx->fx[0].b.bumpedTex, nil);\n\t\t\t\tbreak;\n\t\t\tcase rpMATFXEFFECTENVMAP:\n\t\t\t{\n\t\t\t\t// TODO: matfx switch in the settings\n\t\t\t\t//_rpMatFXD3D8AtomicMatFXEnvRender(inst, flags, 0, inst->material->texture, matfx->fx[0].e.envTex);\n\t\t\t\t_rpMatFXD3D8AtomicMatFXEnvRender_ps2(inst, flags, 0, inst->material->texture, matfx->fx[0].e.envTex);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase rpMATFXEFFECTBUMPENVMAP:\n\t\t\t\t_rpMatFXD3D8AtomicMatFXBumpMapRender(inst, flags, inst->material->texture, matfx->fx[0].b.bumpedTex, matfx->fx[1].e.envTex);\n\t\t\t\tbreak;\n\t\t\tcase rpMATFXEFFECTDUAL:\n\t\t\t\t_rpMatFXD3D8AtomicMatFXDualPassRender(inst, flags, inst->material->texture, matfx->fx[0].d.dualTex);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tinst++;\n\t}\n\n\tif (forceBlack) {\n\t\tRwD3D8SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG2);\n\t\tRwD3D8SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);\n\t}\n}\n\nvoid\nReplaceMatFxCallback()\n{\n\tRxD3D8AllInOneSetRenderCallBack(\n\t    RxPipelineFindNodeByName(RpMatFXGetD3D8Pipeline(rpMATFXD3D8ATOMICPIPELINE), RxNodeDefinitionGetD3D8AtomicAllInOne()->name, nil, nil),\n\t    _rwD3D8AtomicMatFXRenderCallback);\n\t\n}\n#endif // PS2_MATFX\n\n#endif // !LIBRW\n"
  },
  {
    "path": "src/rw/RwPS2AlphaTest.cpp",
    "content": "#ifndef LIBRW\n\n#define WITHD3D\n#include \"common.h\"\n#ifdef PS2_ALPHA_TEST\n#include \"rwcore.h\"\n\nextern \"C\" {\nRwBool _rwD3D8RenderStateIsVertexAlphaEnable(void);\nRwBool _rwD3D8RenderStateVertexAlphaEnable(RwBool enable);\nRwRaster *_rwD3D8RWGetRasterStage(RwUInt32 stage);\n}\n\nextern bool gPS2alphaTest;\n\nvoid\n_rxD3D8DualPassRenderCallback(RwResEntry *repEntry, void *object, RwUInt8 type, RwUInt32 flags)\n{\n\tRxD3D8ResEntryHeader *resEntryHeader;\n\tRxD3D8InstanceData *instancedData;\n\tRwInt32 numMeshes;\n\tRwBool lighting;\n\tRwBool vertexAlphaBlend;\n\tRwBool forceBlack;\n\tRwUInt32 ditherEnable;\n\tRwUInt32 shadeMode;\n\tvoid *lastVertexBuffer;\n\n\t/* Get lighting state */\n\tRwD3D8GetRenderState(D3DRS_LIGHTING, &lighting);\n\n\tforceBlack = FALSE;\n\n\tif (lighting) {\n\t\tif (flags & rxGEOMETRY_PRELIT) {\n\t\t\t/* Emmisive color from the vertex colors */\n\t\t\tRwD3D8SetRenderState(D3DRS_COLORVERTEX, TRUE);\n\t\t\tRwD3D8SetRenderState(D3DRS_EMISSIVEMATERIALSOURCE, D3DMCS_COLOR1);\n\t\t} else {\n\t\t\t/* Emmisive color from material, set to black in the submit node */\n\t\t\tRwD3D8SetRenderState(D3DRS_COLORVERTEX, FALSE);\n\t\t\tRwD3D8SetRenderState(D3DRS_EMISSIVEMATERIALSOURCE, D3DMCS_MATERIAL);\n\t\t}\n\t} else {\n\t\tif ((flags & rxGEOMETRY_PRELIT) == 0) {\n\t\t\tforceBlack = TRUE;\n\n\t\t\tRwD3D8GetRenderState(D3DRS_DITHERENABLE, &ditherEnable);\n\t\t\tRwD3D8GetRenderState(D3DRS_SHADEMODE, &shadeMode);\n\n\t\t\tRwD3D8SetRenderState(D3DRS_TEXTUREFACTOR, 0xff000000);\n\t\t\tRwD3D8SetRenderState(D3DRS_DITHERENABLE, FALSE);\n\t\t\tRwD3D8SetRenderState(D3DRS_SHADEMODE, D3DSHADE_FLAT);\n\t\t}\n\t}\n\n\t/* Enable clipping */\n\tif (type == rpATOMIC) {\n\t\tRpAtomic *atomic;\n\t\tRwCamera *cam;\n\n\t\tatomic = (RpAtomic *)object;\n\n\t\tcam = RwCameraGetCurrentCamera();\n\t\t// RWASSERT(cam);\n\n\t\tif (RwD3D8CameraIsSphereFullyInsideFrustum(cam, RpAtomicGetWorldBoundingSphere(atomic))) {\n\t\t\tRwD3D8SetRenderState(D3DRS_CLIPPING, FALSE);\n\t\t} else {\n\t\t\tRwD3D8SetRenderState(D3DRS_CLIPPING, TRUE);\n\t\t}\n\t} else {\n\t\tRpWorldSector *worldSector;\n\t\tRwCamera *cam;\n\n\t\tworldSector = (RpWorldSector *)object;\n\n\t\tcam = RwCameraGetCurrentCamera();\n\t\t// RWASSERT(cam);\n\n\t\tif (RwD3D8CameraIsBBoxFullyInsideFrustum(cam, RpWorldSectorGetTightBBox(worldSector))) {\n\t\t\tRwD3D8SetRenderState(D3DRS_CLIPPING, FALSE);\n\t\t} else {\n\t\t\tRwD3D8SetRenderState(D3DRS_CLIPPING, TRUE);\n\t\t}\n\t}\n\n\t/* Set texture to NULL if hasn't any texture flags */\n\tif ((flags & (rxGEOMETRY_TEXTURED | rpGEOMETRYTEXTURED2)) == 0) {\n\t\tRwD3D8SetTexture(NULL, 0);\n\n\t\tif (forceBlack) {\n\t\t\tRwD3D8SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG2);\n\t\t\tRwD3D8SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_TFACTOR);\n\n\t\t\tRwD3D8SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE);\n\t\t}\n\t}\n\n\t/* Get vertex alpha Blend state */\n\tvertexAlphaBlend = _rwD3D8RenderStateIsVertexAlphaEnable();\n\n\t/* Set Last vertex buffer to force the call */\n\tlastVertexBuffer = (void *)0xffffffff;\n\n\t/* Get the instanced data */\n\tresEntryHeader = (RxD3D8ResEntryHeader *)(repEntry + 1);\n\tinstancedData = (RxD3D8InstanceData *)(resEntryHeader + 1);\n\n\t/*\n\t * Data shared between meshes\n\t */\n\n\t/*\n\t * Set the Default Pixel shader\n\t */\n\tRwD3D8SetPixelShader(0);\n\n\t/*\n\t * Vertex shader\n\t */\n\tRwD3D8SetVertexShader(instancedData->vertexShader);\n\n\t/* Get the number of meshes */\n\tnumMeshes = resEntryHeader->numMeshes;\n\twhile (numMeshes--) {\n\t\t// RWASSERT(instancedData->material != NULL);\n\n\t\tif ((flags & (rxGEOMETRY_TEXTURED | rpGEOMETRYTEXTURED2))) {\n\t\t\tRwD3D8SetTexture(instancedData->material->texture, 0);\n\n\t\t\tif (forceBlack) {\n\t\t\t\t/* Only change the colorop, we need to use the texture alpha channel */\n\t\t\t\tRwD3D8SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG2);\n\t\t\t\tRwD3D8SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_TFACTOR);\n\t\t\t}\n\t\t}\n\n\t\tif (instancedData->vertexAlpha || (0xFF != instancedData->material->color.alpha)) {\n\t\t\tif (!vertexAlphaBlend) {\n\t\t\t\tvertexAlphaBlend = TRUE;\n\n\t\t\t\t_rwD3D8RenderStateVertexAlphaEnable(TRUE);\n\t\t\t}\n\t\t} else {\n\t\t\tif (vertexAlphaBlend) {\n\t\t\t\tvertexAlphaBlend = FALSE;\n\n\t\t\t\t_rwD3D8RenderStateVertexAlphaEnable(FALSE);\n\t\t\t}\n\t\t}\n\n\t\tif (lighting) {\n\t\t\tif (instancedData->vertexAlpha) {\n\t\t\t\tRwD3D8SetRenderState(D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_COLOR1);\n\t\t\t} else {\n\t\t\t\tRwD3D8SetRenderState(D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_MATERIAL);\n\t\t\t}\n\n\t\t\tRwD3D8SetSurfaceProperties(&instancedData->material->color, &instancedData->material->surfaceProps, (flags & rxGEOMETRY_MODULATE));\n\t\t}\n\n\t\t/*\n\t\t * Render\n\t\t */\n\n\t\t/* Set the stream source */\n\t\tif (lastVertexBuffer != instancedData->vertexBuffer) {\n\t\t\tRwD3D8SetStreamSource(0, instancedData->vertexBuffer, instancedData->stride);\n\n\t\t\tlastVertexBuffer = instancedData->vertexBuffer;\n\t\t}\n\t\tif (!gPS2alphaTest) {\n\t\t\t/* Set the Index buffer */\n\t\t\tif (instancedData->indexBuffer != NULL) {\n\t\t\t\tRwD3D8SetIndices(instancedData->indexBuffer, instancedData->baseIndex);\n\n\t\t\t\t/* Draw the indexed primitive */\n\t\t\t\tRwD3D8DrawIndexedPrimitive((D3DPRIMITIVETYPE)instancedData->primType, 0, instancedData->numVertices, 0, instancedData->numIndices);\n\t\t\t} else {\n\t\t\t\tRwD3D8DrawPrimitive((D3DPRIMITIVETYPE)instancedData->primType, instancedData->baseIndex, instancedData->numVertices);\n\t\t\t}\n\t\t} else {\n\t\t\tRwD3D8SetIndices(instancedData->indexBuffer, instancedData->baseIndex);\n\n\t\t\tint hasAlpha, alphafunc, alpharef, zwrite;\n\t\t\tRwD3D8GetRenderState(D3DRS_ALPHABLENDENABLE, &hasAlpha);\n\t\t\tRwD3D8GetRenderState(D3DRS_ZWRITEENABLE, &zwrite);\n\t\t\tif (hasAlpha && zwrite) {\n\t\t\t\tRwD3D8GetRenderState(D3DRS_ALPHAFUNC, &alphafunc);\n\t\t\t\tRwD3D8GetRenderState(D3DRS_ALPHAREF, &alpharef);\n\n\t\t\t\tRwD3D8SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL);\n\t\t\t\tRwD3D8SetRenderState(D3DRS_ALPHAREF, 128);\n\n\t\t\t\tif (instancedData->indexBuffer)\n\t\t\t\t\tRwD3D8DrawIndexedPrimitive(instancedData->primType, 0, instancedData->numVertices, 0, instancedData->numIndices);\n\t\t\t\telse\n\t\t\t\t\tRwD3D8DrawPrimitive(instancedData->primType, instancedData->baseIndex, instancedData->numVertices);\n\n\t\t\t\tRwD3D8SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_LESS);\n\t\t\t\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE, FALSE);\n\n\t\t\t\tif (instancedData->indexBuffer)\n\t\t\t\t\tRwD3D8DrawIndexedPrimitive(instancedData->primType, 0, instancedData->numVertices, 0, instancedData->numIndices);\n\t\t\t\telse\n\t\t\t\t\tRwD3D8DrawPrimitive(instancedData->primType, instancedData->baseIndex, instancedData->numVertices);\n\n\t\t\t\tRwD3D8SetRenderState(D3DRS_ALPHAFUNC, alphafunc);\n\t\t\t\tRwD3D8SetRenderState(D3DRS_ALPHAREF, alpharef);\n\t\t\t\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void *)TRUE);\n\t\t\t} else {\n\t\t\t\tif (instancedData->indexBuffer)\n\t\t\t\t\tRwD3D8DrawIndexedPrimitive(instancedData->primType, 0, instancedData->numVertices, 0, instancedData->numIndices);\n\t\t\t\telse\n\t\t\t\t\tRwD3D8DrawPrimitive(instancedData->primType, instancedData->baseIndex, instancedData->numVertices);\n\t\t\t}\n\t\t}\n\n\t\t/* Move onto the next instancedData */\n\t\tinstancedData++;\n\t}\n\n\tif (forceBlack) {\n\t\tRwD3D8SetRenderState(D3DRS_DITHERENABLE, ditherEnable);\n\t\tRwD3D8SetRenderState(D3DRS_SHADEMODE, shadeMode);\n\n\t\tif (_rwD3D8RWGetRasterStage(0)) {\n\t\t\tRwD3D8SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);\n\t\t\tRwD3D8SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);\n\t\t} else {\n\t\t\tRwD3D8SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG2);\n\t\t\tRwD3D8SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);\n\t\t}\n\t}\n}\n\nvoid\nReplaceAtomicPipeCallback()\n{\n\tRxD3D8AllInOneSetRenderCallBack(RxPipelineFindNodeByName(RXPIPELINEGLOBAL(platformAtomicPipeline), RxNodeDefinitionGetD3D8AtomicAllInOne()->name, nil, nil),\n\t                                _rxD3D8DualPassRenderCallback);\n}\n\n#endif // PS2_ALPHA_TEST\n\n#endif // !LIBRW"
  },
  {
    "path": "src/rw/TexRead.cpp",
    "content": "#pragma warning( push )\n#pragma warning( disable : 4005)\n#pragma warning( pop )\n#define FORCE_PC_SCALING\n#ifndef LIBRW\n#define WITHD3D\n#endif\n#include \"common.h\"\n#ifdef ANISOTROPIC_FILTERING\n#include \"rpanisot.h\"\n#endif\n#include \"crossplatform.h\"\n#include \"platform.h\"\n\n#include \"Timer.h\"\n#ifdef GTA_PC\n#include \"FileMgr.h\"\n#include \"Pad.h\"\n#include \"main.h\"\n#include \"Directory.h\"\n#include \"Streaming.h\"\n#include \"TxdStore.h\"\n#include \"CdStream.h\"\n#include \"Font.h\"\n#include \"Sprite2d.h\"\n#include \"Text.h\"\n#include \"RwHelper.h\"\n#include \"Frontend.h\"\n#endif //GTA_PC\n\nfloat texLoadTime;\nint32 texNumLoaded;\n\n#ifdef LIBRW\n#define READNATIVE(stream, tex, size) rwNativeTextureHackRead(stream, tex, size)\n#else\n#define READNATIVE(stream, tex, size) RWSRCGLOBAL(stdFunc[rwSTANDARDNATIVETEXTUREREAD](stream, tex, size))\n#endif\n\nRwTexture*\nRwTextureGtaStreamRead(RwStream *stream)\n{\n\tRwUInt32 size, version;\n\tRwTexture *tex;\n\n\tif(!RwStreamFindChunk(stream, rwID_TEXTURENATIVE, &size, &version))\n\t\treturn nil;\n\n\tfloat preloadTime = (float)CTimer::GetCurrentTimeInCycles() / (float)CTimer::GetCyclesPerMillisecond();\n\n\tif(!READNATIVE(stream, &tex, size))\n\t\treturn nil;\n\n\tif (gGameState == GS_INIT_PLAYING_GAME) {\n\t\ttexLoadTime = (texNumLoaded * texLoadTime + (float)CTimer::GetCurrentTimeInCycles() / (float)CTimer::GetCyclesPerMillisecond() - preloadTime) / (float)(texNumLoaded+1);\n\t\ttexNumLoaded++;\n\t}\n\n#ifdef ANISOTROPIC_FILTERING\n\tif(tex && RpAnisotGetMaxSupportedMaxAnisotropy() > 1)\t// BUG? this was RpAnisotTextureGetMaxAnisotropy, but that doesn't make much sense\n\t\tRpAnisotTextureSetMaxAnisotropy(tex, RpAnisotGetMaxSupportedMaxAnisotropy());\n#endif\n\n\treturn tex;\n}\n\nRwTexture*\ndestroyTexture(RwTexture *texture, void *data)\n{\n\tRwTextureDestroy(texture);\n\treturn texture;\n}\n\nRwTexDictionary*\nRwTexDictionaryGtaStreamRead(RwStream *stream)\n{\n\tRwUInt32 size, version;\n\tRwInt32 numTextures;\n\tRwTexDictionary *texDict;\n\tRwTexture *tex;\n\n\tif(!RwStreamFindChunk(stream, rwID_STRUCT, &size, &version))\n\t\treturn nil;\n\tif(RwStreamRead(stream, &numTextures, size) != size)\n\t\treturn nil;\n\n\ttexDict = RwTexDictionaryCreate();\n\tif(texDict == nil)\n\t\treturn nil;\n\n\twhile(numTextures--){\n\t\ttex = RwTextureGtaStreamRead(stream);\n\t\tif(tex == nil){\n\t\t\tRwTexDictionaryForAllTextures(texDict, destroyTexture, nil);\n\t\t\tRwTexDictionaryDestroy(texDict);\n\t\t\treturn nil;\n\t\t}\n\t\tRwTexDictionaryAddTexture(texDict, tex);\n\t}\n\n\treturn texDict;\n}\n\nstatic int32 numberTextures = -1;\nstatic int32 streamPosition;\n\nRwTexDictionary*\nRwTexDictionaryGtaStreamRead1(RwStream *stream)\n{\n\tRwUInt32 size, version;\n\tRwInt32 numTextures;\n\tRwTexDictionary *texDict;\n\tRwTexture *tex;\n\n\tnumberTextures = 0;\n\tif(!RwStreamFindChunk(stream, rwID_STRUCT, &size, &version))\n\t\treturn nil;\n\tassert(size == 4);\n\tif(RwStreamRead(stream, &numTextures, size) != size)\n\t\treturn nil;\n\n\ttexDict = RwTexDictionaryCreate();\n\tif(texDict == nil)\n\t\treturn nil;\n\n\tnumberTextures = numTextures/2;\n\n\twhile(numTextures > numberTextures){\n\t\tnumTextures--;\n\n\t\ttex = RwTextureGtaStreamRead(stream);\n\t\tif(tex == nil){\n\t\t\tRwTexDictionaryForAllTextures(texDict, destroyTexture, nil);\n\t\t\tRwTexDictionaryDestroy(texDict);\n\t\t\treturn nil;\n\t\t}\n\t\tRwTexDictionaryAddTexture(texDict, tex);\n\t}\n\n\tnumberTextures = numTextures;\n\tstreamPosition = STREAMPOS(stream);\n\n\treturn texDict;\n}\n\nRwTexDictionary*\nRwTexDictionaryGtaStreamRead2(RwStream *stream, RwTexDictionary *texDict)\n{\n\tRwTexture *tex;\n\n\tRwStreamSkip(stream, streamPosition - STREAMPOS(stream));\n\n\twhile(numberTextures--){\n\t\ttex = RwTextureGtaStreamRead(stream);\n\t\tif(tex == nil){\n\t\t\tRwTexDictionaryForAllTextures(texDict, destroyTexture, nil);\n\t\t\tRwTexDictionaryDestroy(texDict);\n\t\t\treturn nil;\n\t\t}\n\t\tRwTexDictionaryAddTexture(texDict, tex);\n\t}\n\n\treturn texDict;\n}\n\n#ifdef GTA_PC\n\n#ifdef LIBRW\n\n#define CAPSVERSION 0\n\nstruct GPUcaps\n{\n\tuint32 version;\t// so we can force regeneration easily\n\tuint32 platform;\n\tuint32 subplatform;\n\tuint32 dxtSupport;\n};\n\nstatic void\nGetGPUcaps(GPUcaps *caps)\n{\n\tcaps->version = CAPSVERSION;\n\tcaps->platform = rw::platform;\n\tcaps->subplatform = 0;\n\tcaps->dxtSupport = 0;\n\t// TODO: more later\n#ifdef RW_GL3\n\tcaps->subplatform = rw::gl3::gl3Caps.gles;\n\tcaps->dxtSupport = rw::gl3::gl3Caps.dxtSupported;\n#endif\n#ifdef RW_D3D9\n\tcaps->dxtSupport = 1;\t// TODO, probably\n#endif\n}\n\nvoid\nReadVideoCardCapsFile(GPUcaps *caps)\n{\n\tmemset(caps, 0, sizeof(GPUcaps));\n\n\tint32 file = CFileMgr::OpenFile(\"DATA\\\\CAPS.DAT\", \"rb\");\n\tif (file != 0) {\n\t\tCFileMgr::Read(file, (char*)&caps->version, 4);\n\t\tCFileMgr::Read(file, (char*)&caps->platform, 4);\n\t\tCFileMgr::Read(file, (char*)&caps->subplatform, 4);\n\t\tCFileMgr::Read(file, (char*)&caps->dxtSupport, 4);\n\t\tCFileMgr::CloseFile(file);\n\t}\n}\n\nbool\nCheckVideoCardCaps(void)\n{\n\tGPUcaps caps, fcaps;\n\tGetGPUcaps(&caps);\n\tReadVideoCardCapsFile(&fcaps);\n\treturn caps.version != fcaps.version ||\n\t\tcaps.platform != fcaps.platform ||\n\t\tcaps.subplatform != fcaps.subplatform ||\n\t\tcaps.dxtSupport != fcaps.dxtSupport;\n}\n\nvoid\nWriteVideoCardCapsFile(void)\n{\n\tGPUcaps caps;\n\tGetGPUcaps(&caps);\n\tint32 file = CFileMgr::OpenFile(\"DATA\\\\CAPS.DAT\", \"wb\");\n\tif (file != 0) {\n\t\tCFileMgr::Write(file, (char*)&caps.version, 4);\n\t\tCFileMgr::Write(file, (char*)&caps.platform, 4);\n\t\tCFileMgr::Write(file, (char*)&caps.subplatform, 4);\n\t\tCFileMgr::Write(file, (char*)&caps.dxtSupport, 4);\n\t\tCFileMgr::CloseFile(file);\n\t}\n}\n\n\n#else\nextern \"C\" RwInt32 _rwD3D8FindCorrectRasterFormat(RwRasterType type, RwInt32 flags);\nextern \"C\" RwBool   _rwD3D8CheckValidTextureFormat(RwInt32 format);\nvoid\nReadVideoCardCapsFile(uint32 &cap32, uint32 &cap24, uint32 &cap16, uint32 &cap8)\n{\n\tcap32 = UINT32_MAX;\n\tcap24 = UINT32_MAX;\n\tcap16 = UINT32_MAX;\n\tcap8 = UINT32_MAX;\n\n\tint32 file = CFileMgr::OpenFile(\"DATA\\\\CAPS.DAT\", \"rb\");\n\tif (file != 0) {\n\t\tCFileMgr::Read(file, (char*)&cap32, 4);\n\t\tCFileMgr::Read(file, (char*)&cap24, 4);\n\t\tCFileMgr::Read(file, (char*)&cap16, 4);\n\t\tCFileMgr::Read(file, (char*)&cap8, 4);\n\t\tCFileMgr::CloseFile(file);\n\t}\n}\n\nbool\nCheckVideoCardCaps(void)\n{\n\tuint32 cap32 = _rwD3D8FindCorrectRasterFormat(rwRASTERTYPETEXTURE, rwRASTERFORMAT8888);\n\tuint32 cap24 = _rwD3D8FindCorrectRasterFormat(rwRASTERTYPETEXTURE, rwRASTERFORMAT888);\n\tuint32 cap16 = _rwD3D8FindCorrectRasterFormat(rwRASTERTYPETEXTURE, rwRASTERFORMAT1555);\n\tuint32 cap8 = _rwD3D8FindCorrectRasterFormat(rwRASTERTYPETEXTURE, rwRASTERFORMATPAL8 | rwRASTERFORMAT8888);\n\tuint32 fcap32, fcap24, fcap16, fcap8;\n\tReadVideoCardCapsFile(fcap32, fcap24, fcap16, fcap8);\n\treturn cap32 != fcap32 || cap24 != fcap24 || cap16 != fcap16 || cap8 != fcap8;\n}\n\nvoid\nWriteVideoCardCapsFile(void)\n{\n\tuint32 cap32 = _rwD3D8FindCorrectRasterFormat(rwRASTERTYPETEXTURE, rwRASTERFORMAT8888);\n\tuint32 cap24 = _rwD3D8FindCorrectRasterFormat(rwRASTERTYPETEXTURE, rwRASTERFORMAT888);\n\tuint32 cap16 = _rwD3D8FindCorrectRasterFormat(rwRASTERTYPETEXTURE, rwRASTERFORMAT1555);\n\tuint32 cap8 = _rwD3D8FindCorrectRasterFormat(rwRASTERTYPETEXTURE, rwRASTERFORMATPAL8 | rwRASTERFORMAT8888);\n\tint32 file = CFileMgr::OpenFile(\"DATA\\\\CAPS.DAT\", \"wb\");\n\tif (file != 0) {\n\t\tCFileMgr::Write(file, (char*)&cap32, 4);\n\t\tCFileMgr::Write(file, (char*)&cap24, 4);\n\t\tCFileMgr::Write(file, (char*)&cap16, 4);\n\t\tCFileMgr::Write(file, (char*)&cap8, 4);\n\t\tCFileMgr::CloseFile(file);\n\t}\n}\n#endif\n\nbool\nCanVideoCardDoDXT(void)\n{\n#ifdef LIBRW\n\t// TODO\n#ifdef RW_OPENGL\n\treturn false;\n#else\n\treturn true;\n#endif\n#else\n\treturn _rwD3D8CheckValidTextureFormat(D3DFMT_DXT1) && _rwD3D8CheckValidTextureFormat(D3DFMT_DXT3);\n#endif\n}\n\nvoid\nConvertingTexturesScreen(uint32 num, uint32 count, const char *text)\n{\n\tHandleExit();\n\n\tCSprite2d *splash = LoadSplash(nil);\n\tif (!DoRWStuffStartOfFrame(0, 0, 0, 0, 0, 0, 255))\n\t\treturn;\n\n\tCSprite2d::SetRecipNearClip();\n\tCSprite2d::InitPerFrame();\n\tCFont::InitPerFrame();\n\tDefinedState();\n\n\tRwRenderStateSet(rwRENDERSTATETEXTUREADDRESS, (void*)rwTEXTUREADDRESSCLAMP);\n\tsplash->Draw(CRect(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT), CRGBA(255, 255, 255, 255));\n\n\tCSprite2d::DrawRect(CRect(SCREEN_SCALE_X(200.0f), SCREEN_SCALE_Y(240.0f), SCREEN_SCALE_FROM_RIGHT(200.0f), SCREEN_SCALE_Y(248.0f)), CRGBA(64, 64, 64, 255));\n#ifdef FIX_BUGS\n\tCSprite2d::DrawRect(CRect(SCREEN_SCALE_X(200.0f), SCREEN_SCALE_Y(240.0f), (SCREEN_SCALE_FROM_RIGHT(200.0f) - SCREEN_SCALE_X(200.0f)) * ((float)num / (float)count) + SCREEN_SCALE_X(200.0f), SCREEN_SCALE_Y(248.0f)), CRGBA(255, 150, 225, 255));\n#else\n\tCSprite2d::DrawRect(CRect(SCREEN_SCALE_X(200.0f), SCREEN_SCALE_Y(240.0f), (SCREEN_SCALE_FROM_RIGHT(200.0f) - SCREEN_SCALE_X(200.0f)) * ((float)num / (float)count) + SCREEN_SCALE_X(200.0f), SCREEN_SCALE_Y(248.0f)), CRGBA(255, 217, 106, 255));\n#endif\n\tCSprite2d::DrawRect(CRect(SCREEN_SCALE_X(120.0f), SCREEN_SCALE_Y(150.0f), SCREEN_SCALE_FROM_RIGHT(120.0f), SCREEN_HEIGHT - SCREEN_SCALE_Y(220.0f)), CRGBA(50, 50, 50, 210));\n\n\tCFont::SetBackgroundOff();\n\tCFont::SetPropOn();\n\tCFont::SetScale(SCREEN_SCALE_X(0.45f), SCREEN_SCALE_Y(0.7f));\n\tCFont::SetCentreOff();\n\tCFont::SetWrapx(SCREEN_SCALE_FROM_RIGHT(170.0f));\n\tCFont::SetJustifyOff();\n#ifdef FIX_BUGS\n\tCFont::SetColor(CRGBA(255, 150, 225, 255));\n#else\n\tCFont::SetColor(CRGBA(255, 217, 106, 255));\n#endif\n\tCFont::SetBackGroundOnlyTextOff();\n\tCFont::SetFontStyle(FONT_STANDARD);\n\tCFont::PrintString(SCREEN_SCALE_X(170.0f), SCREEN_SCALE_Y(160.0f), TheText.Get(text));\n\tCFont::DrawFonts();\n\tDoRWStuffEndOfFrame();\n}\n\nvoid\nDealWithTxdWriteError(uint32 num, uint32 count, const char *text)\n{\n\twhile (!RsGlobal.quit) {\n\t\tConvertingTexturesScreen(num, count, text);\n\t\tCPad::UpdatePads();\n\t\tif (CPad::GetPad(0)->GetEscapeJustDown())\n\t\t\tbreak;\n\t}\n\tRsGlobal.quit = false;\n\tLoadingScreen(nil, nil, nil);\n\tRsGlobal.quit = true;\n}\n\n#ifdef LIBRW\n#define STREAMTELL(str)\tstr->tell()\n#else\n#define STREAMTELL(str) filesys->rwftell((str)->Type.file.fpFile)\n#endif\n\nbool\nCreateTxdImageForVideoCard()\n{\n\tuint8 *buf = new uint8[CDSTREAM_SECTOR_SIZE];\n\tCDirectory *pDir = new CDirectory(TXDSTORESIZE);\n\tCDirectory::DirectoryInfo dirInfo;\n\n\tCStreaming::FlushRequestList();\n\n#ifndef LIBRW\n\tRwFileFunctions *filesys = RwOsGetFileInterface();\n#endif\n\n\tRwStream *img = RwStreamOpen(rwSTREAMFILENAME, rwSTREAMWRITE, \"models\\\\txd.img\");\n\tif (img == nil) {\n\t\t// original code does otherwise and it leaks\n\t\tdelete []buf;\n\t\tdelete pDir;\n\n\t\tif (_dwOperatingSystemVersion == OS_WINNT || _dwOperatingSystemVersion == OS_WIN2000 || _dwOperatingSystemVersion == OS_WINXP)\n\t\t\tDealWithTxdWriteError(0, TXDSTORESIZE, \"CVT_CRT\");\n\n\t\treturn false;\n\t}\n\n#ifdef RW_GL3\n\t// so we can read back DXT with GLES\n\t// only works for textures that are not yet loaded\n\t// so let's hope that is the case for all\n\trw::gl3::needToReadBackTextures = true;\n#endif\n\t\n#ifdef DISABLE_VSYNC_ON_TEXTURE_CONVERSION\n\t// let's disable vsync and frame limiter to speed up texture conversion\n\t// (actually we probably don't need to disable frame limiter in here, but let's do it just in case =P)\n\tint8 vsyncState = FrontEndMenuManager.m_PrefsVsync;\n\tint8 frameLimiterState = FrontEndMenuManager.m_PrefsFrameLimiter;\n\tFrontEndMenuManager.m_PrefsVsync = 0;\n\tFrontEndMenuManager.m_PrefsFrameLimiter = 0;\n#endif\n\n\tint32 i;\n\tfor (i = 0; i < TXDSTORESIZE; i++) {\n\t\tConvertingTexturesScreen(i, TXDSTORESIZE, \"CVT_MSG\");\n\n\t\tif (CTxdStore::GetSlot(i) != nil && CStreaming::IsObjectInCdImage(i + STREAM_OFFSET_TXD)) {\n#ifdef FIX_BUGS\n\t\t\tif(strcmp(CTxdStore::GetTxdName(i), \"generic\") == 0)\n\t\t\t\tcontinue;\n#endif\n\n\t\t\tCStreaming::RequestTxd(i, STREAMFLAGS_KEEP_IN_MEMORY);\n\t\t\tCStreaming::RequestModelStream(0);\n\t\t\tCStreaming::FlushChannels();\n\n\t\t\tchar filename[64];\n\t\t\tsprintf(filename, \"%s.txd\", CTxdStore::GetTxdName(i));\n\n\t\t\tif (CTxdStore::GetSlot(i)->texDict) {\n\n\t\t\t\tint32 pos = STREAMTELL(img);\n\n\t\t\t\tif (RwTexDictionaryStreamWrite(CTxdStore::GetSlot(i)->texDict, img) == nil) {\n\t\t\t\t\tDealWithTxdWriteError(i, TXDSTORESIZE, \"CVT_ERR\");\n\t\t\t\t\tRwStreamClose(img, nil);\n\t\t\t\t\tdelete []buf;\n\t\t\t\t\tdelete pDir;\n\t\t\t\t\tCStreaming::RemoveTxd(i);\n#ifdef RW_GL3\n\t\t\t\t\trw::gl3::needToReadBackTextures = false;\n#endif\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\tint32 size = STREAMTELL(img) - pos;\n\t\t\t\tint32 num = size % CDSTREAM_SECTOR_SIZE;\n\n\t\t\t\tsize /= CDSTREAM_SECTOR_SIZE;\n\t\t\t\tif (num != 0) {\n\t\t\t\t\tsize++;\n\t\t\t\t\tnum = CDSTREAM_SECTOR_SIZE - num;\n\t\t\t\t\tRwStreamWrite(img, buf, num);\n\t\t\t\t}\n\n\t\t\t\tdirInfo.offset = pos / CDSTREAM_SECTOR_SIZE;\n\t\t\t\tdirInfo.size = size;\n\t\t\t\tstrncpy(dirInfo.name, filename, sizeof(dirInfo.name));\n\t\t\t\tpDir->AddItem(dirInfo);\n\t\t\t\tCStreaming::RemoveTxd(i);\n\t\t\t}\n\t\t\tCStreaming::FlushRequestList();\n\t\t}\n\t}\n\n#ifdef DISABLE_VSYNC_ON_TEXTURE_CONVERSION\n\t// restore vsync and frame limiter states\n\tFrontEndMenuManager.m_PrefsVsync = vsyncState;\n\tFrontEndMenuManager.m_PrefsFrameLimiter = frameLimiterState;\n#endif\n\n\tRwStreamClose(img, nil);\n\tdelete []buf;\n\n#ifdef RW_GL3\n\trw::gl3::needToReadBackTextures = false;\n#endif\n\n\tif (!pDir->WriteDirFile(\"models\\\\txd.dir\")) {\n\t\tDealWithTxdWriteError(i, TXDSTORESIZE, \"CVT_ERR\");\n\t\tdelete pDir;\n\t\treturn false;\n\t}\n\n\tdelete pDir;\n\n\tWriteVideoCardCapsFile();\n\treturn true;\n}\n#endif // GTA_PC\n"
  },
  {
    "path": "src/rw/TexturePools.cpp",
    "content": "#ifndef LIBRW\n\n#include <d3d8.h>\n#define WITHD3D\n#include \"common.h\"\n#include \"TexturePools.h\"\n\n// TODO: this needs to be integrated into RW\n\nextern \"C\" LPDIRECT3DDEVICE8 _RwD3DDevice;\n\nCTexturePool aTexturePools[12];\nCPaletteList PaletteList;\nint numTexturePools;\nint MaxPaletteIndex;\nbool bUsePaletteIndex = true;\n\n\nvoid\nCTexturePool::Create(D3DFORMAT _Format, int _size, uint32 mipmapLevels, int32 numTextures)\n{\n\tFormat = _Format;\n\tsize = _size;\n\tlevels = mipmapLevels;\n\tpTextures = new IDirect3DTexture8 *[numTextures];\n\ttexturesMax = numTextures;\n\ttexturesNum = 0;\n\ttexturesUsed = 0;\n}\n\nvoid\nCTexturePool::Release()\n{\n\tint i = 0;\n\twhile (i < texturesNum) {\n\t\tpTextures[i]->Release();\n\t\ti++;\n\t}\n\n\tdelete[] pTextures;\n\n\tpTextures = nil;\n\ttexturesNum = 0;\n\ttexturesUsed = 0;\n}\n\nIDirect3DTexture8 *\nCTexturePool::FindTexture()\n{\n\tif (texturesNum == 0)\n\t\treturn nil;\n\ttexturesUsed--;\n\treturn pTextures[--texturesNum];\n}\n\nbool\nCTexturePool::AddTexture(IDirect3DTexture8 *texture)\n{\n\t++texturesUsed;\n\tif (texturesNum >= texturesMax)\n\t\treturn false;\n\tpTextures[texturesNum] = texture;\n\t++texturesNum;\n\treturn true;\n}\n\nvoid\nCTexturePool::Resize(int numTextures)\n{\n\tif (numTextures == texturesMax)\n\t\treturn;\n\n\tIDirect3DTexture8 **newTextures = new IDirect3DTexture8 *[numTextures];\n\n\tfor (int i = 0; i < texturesNum && i < numTextures; i++)\n\t\tnewTextures[i] = pTextures[i];\n\n\tif (numTextures < texturesNum) {\n\t\tfor (int i = numTextures; i < texturesNum; i++)\n\t\t\tpTextures[i]->Release();\n\t}\n\tdelete[] pTextures;\n\tpTextures = newTextures;\n\ttexturesMax = numTextures;\n}\n\nvoid\nCPaletteList::Alloc(int max)\n{\n\tData = new int[max];\n\tMax = max;\n\tNum = 0;\n}\n\nvoid\nCPaletteList::Free()\n{\n\tdelete[] Data;\n\tData = nil;\n\tNum = 0;\n}\n\nint\nCPaletteList::Find()\n{\n\tif (Num == 0)\n\t\treturn -1;\n\treturn Data[--Num];\n}\n\nvoid\nCPaletteList::Add(int item)\n{\n\tif (Num < Max)\n\t\tData[Num++] = item;\n\telse {\n\t\tResize(2 * Max);\n\t\tAdd(item);\n\t}\n}\n\nvoid\nCPaletteList::Resize(int max)\n{\n\tif (max == Max)\n\t\treturn;\n\n\tint *newData = new int[4 * max];\n\tfor (int i = 0; i < Num && i < max; i++)\n\t\tnewData[i] = Data[i];\n\tdelete[] Data;\n\tData = newData;\n\tMax = max;\n}\n\nHRESULT\nCreateTexture(int width, int height, int levels, D3DFORMAT Format, IDirect3DTexture8 **texture)\n{\n\tif (width == height) {\n\t\tfor (int i = 0; i < numTexturePools; i++) {\n\t\t\tif (width != aTexturePools[i].GetSize() && levels == aTexturePools[i].levels && Format == aTexturePools[i].Format) \n\t\t\t\t*texture = aTexturePools[i].FindTexture();\n\t\t}\n\t}\n\tif (*texture)\n\t\treturn D3D_OK;\n\telse\n\t\treturn _RwD3DDevice->CreateTexture(width, height, levels, 0, Format, D3DPOOL_MANAGED, texture);\n}\n\nvoid\nReleaseTexture(IDirect3DTexture8 *texture)\n{\n\tint levels = 1;\n\tif (texture->GetLevelCount() > 1)\n\t\tlevels = 0;\n\n\tD3DSURFACE_DESC SURFACE_DESC;\n\n\ttexture->GetLevelDesc(0, &SURFACE_DESC);\n\n\tif (SURFACE_DESC.Width == SURFACE_DESC.Height) {\n\t\tfor (int i = 0; i < numTexturePools; i++) {\n\t\t\tif (SURFACE_DESC.Width == aTexturePools[i].GetSize() && SURFACE_DESC.Format == aTexturePools[i].Format && levels == aTexturePools[i].levels) {\n\t\t\t\tif (!aTexturePools[i].AddTexture(texture)) {\n\t\t\t\t\tif (aTexturePools[i].texturesUsed > 3 * aTexturePools[i].texturesMax / 2) {\n\t\t\t\t\t\taTexturePools[i].Resize(2 * aTexturePools[i].texturesMax);\n\t\t\t\t\t\taTexturePools[i].texturesUsed--;\n\t\t\t\t\t\taTexturePools[i].AddTexture(texture);\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttexture->Release();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t}\n\tif (numTexturePools < 12 && bUsePaletteIndex && levels != 0 && SURFACE_DESC.Width == SURFACE_DESC.Height &&\n\t    (SURFACE_DESC.Width == 64 || SURFACE_DESC.Width == 128 || SURFACE_DESC.Width == 256)) {\n\t\taTexturePools[numTexturePools].Create(SURFACE_DESC.Format, SURFACE_DESC.Width, 1, 16);\n\t\taTexturePools[numTexturePools].AddTexture(texture);\n\t\tnumTexturePools++;\n\t} else\n\t\ttexture->Release();\n}\n\nint\nFindAvailablePaletteIndex()\n{\n\tint index = PaletteList.Find();\n\tif (index == -1)\n\t\tindex = MaxPaletteIndex++;\n\treturn index;\n}\n\nvoid\nAddAvailablePaletteIndex(int index)\n{\n\tif (bUsePaletteIndex)\n\t\tPaletteList.Add(index);\n}\n\nvoid\n_TexturePoolsInitialise()\n{\n\tPaletteList.Alloc(100);\n\tMaxPaletteIndex = 0;\n}\n\nvoid\n_TexturePoolsShutdown()\n{\n\tfor (int i = 0; i < numTexturePools; i++)\n\t\taTexturePools[i].Release();\n\n\tnumTexturePools = 0;\n\tbUsePaletteIndex = false;\n\tPaletteList.Free();\n}\n\n#endif // !LIBRW"
  },
  {
    "path": "src/rw/TexturePools.h",
    "content": "#pragma once\n\nclass CTexturePool\n{\npublic:\n\tD3DFORMAT Format;\n\tint size;\n\tuint32 levels;\n\tint32 texturesMax;\n\tint32 texturesUsed;\n\tint32 texturesNum;\n\tIDirect3DTexture8 **pTextures;\n\npublic:\n\tCTexturePool() {}\n\tvoid Create(D3DFORMAT _Format, int size, uint32 mipmapLevels, int32 numTextures);\n\tvoid Release();\n\tIDirect3DTexture8 *FindTexture();\n\tbool AddTexture(IDirect3DTexture8 *texture);\n\tvoid Resize(int numTextures);\n#ifdef FIX_BUGS\n\tint GetSize() { return size; }\n#else\n\tfloat GetSize() { return size; }\n#endif\n};\n\nclass CPaletteList\n{\n\tint Max;\n\tint Num;\n\tint *Data;\npublic:\n\tvoid Alloc(int max);\n\tvoid Free();\n\tint Find();\n\tvoid Add(int item);\n\tvoid Resize(int max);\n};\n\nvoid _TexturePoolsInitialise();\nvoid _TexturePoolsShutdown();"
  },
  {
    "path": "src/rw/TxdStore.cpp",
    "content": "#include \"common.h\"\n\n#include \"templates.h\"\n#include \"General.h\"\n#include \"Streaming.h\"\n#include \"RwHelper.h\"\n#include \"TxdStore.h\"\n\nCPool<TxdDef,TxdDef> *CTxdStore::ms_pTxdPool;\nRwTexDictionary *CTxdStore::ms_pStoredTxd;\n\nvoid\nCTxdStore::Initialise(void)\n{\n\tif(ms_pTxdPool == nil)\n\t\tms_pTxdPool = new CPool<TxdDef,TxdDef>(TXDSTORESIZE, \"TexDictionary\");\n}\n\nvoid\nCTxdStore::Shutdown(void)\n{\n\tif(ms_pTxdPool)\n\t\tdelete ms_pTxdPool;\n}\n\nvoid\nCTxdStore::GameShutdown(void)\n{\n\tint i;\n\n\tfor(i = 0; i < TXDSTORESIZE; i++){\n\t\tTxdDef *def = GetSlot(i);\n\t\tif(def && GetNumRefs(i) == 0)\n\t\t\tRemoveTxdSlot(i);\n\t}\n}\n\nint\nCTxdStore::AddTxdSlot(const char *name)\n{\n\tTxdDef *def = ms_pTxdPool->New();\n\tassert(def);\n\tdef->texDict = nil;\n\tdef->refCount = 0;\n\tstrcpy(def->name, name);\n\treturn ms_pTxdPool->GetJustIndex(def);\n}\n\nvoid\nCTxdStore::RemoveTxdSlot(int slot)\n{\n\tTxdDef *def = GetSlot(slot);\n\tif(def->texDict)\n\t\tRwTexDictionaryDestroy(def->texDict);\n\tms_pTxdPool->Delete(def);\n}\n\nint\nCTxdStore::FindTxdSlot(const char *name)\n{\n\tint size = ms_pTxdPool->GetSize();\n\tfor(int i = 0; i < size; i++){\n\t\tTxdDef *def = GetSlot(i);\n\t\tif(def && !CGeneral::faststricmp(def->name, name))\n\t\t\treturn i;\n\t}\n\treturn -1;\n}\n\nchar*\nCTxdStore::GetTxdName(int slot)\n{\n\treturn GetSlot(slot)->name;\n}\n\nvoid\nCTxdStore::PushCurrentTxd(void)\n{\n\tms_pStoredTxd = RwTexDictionaryGetCurrent();\n}\n\nvoid\nCTxdStore::PopCurrentTxd(void)\n{\n\tRwTexDictionarySetCurrent(ms_pStoredTxd);\n\tms_pStoredTxd = nil;\n}\n\nvoid\nCTxdStore::SetCurrentTxd(int slot)\n{\n\tRwTexDictionarySetCurrent(GetSlot(slot)->texDict);\n}\n\nvoid\nCTxdStore::Create(int slot)\n{\n\tGetSlot(slot)->texDict = RwTexDictionaryCreate();\n}\n\nint\nCTxdStore::GetNumRefs(int slot)\n{\n\treturn GetSlot(slot)->refCount;\n}\n\nvoid\nCTxdStore::AddRef(int slot)\n{\n\tGetSlot(slot)->refCount++;\n}\n\nvoid\nCTxdStore::RemoveRef(int slot)\n{\n\tif(--GetSlot(slot)->refCount <= 0)\n\t\tCStreaming::RemoveTxd(slot);\n}\n\nvoid\nCTxdStore::RemoveRefWithoutDelete(int slot)\n{\n\tGetSlot(slot)->refCount--;\n}\n\nbool\nCTxdStore::LoadTxd(int slot, RwStream *stream)\n{\n\tTxdDef *def = GetSlot(slot);\n\n\tif(RwStreamFindChunk(stream, rwID_TEXDICTIONARY, nil, nil)){\n\t\tdef->texDict = RwTexDictionaryGtaStreamRead(stream);\n\t\treturn def->texDict != nil;\n\t}\n\tprintf(\"Failed to load TXD\\n\");\n\treturn false;\n}\n\nbool\nCTxdStore::LoadTxd(int slot, const char *filename)\n{\n\tRwStream *stream;\n\tbool ret;\n\n\tret = false;\n\t_rwD3D8TexDictionaryEnableRasterFormatConversion(true);\n\tdo\n\t\tstream = RwStreamOpen(rwSTREAMFILENAME, rwSTREAMREAD, filename);\n\twhile(stream == nil);\n\tret = LoadTxd(slot, stream);\n\tRwStreamClose(stream, nil);\n\treturn ret;\n}\n\nbool\nCTxdStore::StartLoadTxd(int slot, RwStream *stream)\n{\n\tTxdDef *def = GetSlot(slot);\n\tif(RwStreamFindChunk(stream, rwID_TEXDICTIONARY, nil, nil)){\n\t\tdef->texDict = RwTexDictionaryGtaStreamRead1(stream);\n\t\treturn def->texDict != nil;\n\t}else{\n\t\tprintf(\"Failed to load TXD\\n\");\n\t\treturn false;\n\t}\n}\n\nbool\nCTxdStore::FinishLoadTxd(int slot, RwStream *stream)\n{\n\tTxdDef *def = GetSlot(slot);\n\tdef->texDict = RwTexDictionaryGtaStreamRead2(stream, def->texDict);\n\treturn def->texDict != nil;\n}\n\nvoid\nCTxdStore::RemoveTxd(int slot)\n{\n\tTxdDef *def = GetSlot(slot);\n\tif(def->texDict)\n\t\tRwTexDictionaryDestroy(def->texDict);\n\tdef->texDict = nil;\n}\n"
  },
  {
    "path": "src/rw/TxdStore.h",
    "content": "#pragma once\n\n#include \"templates.h\"\n\nstruct TxdDef {\n\tRwTexDictionary *texDict;\n\tint refCount;\n\tchar name[20];\n};\n\nclass CTxdStore\n{\n\tstatic CPool<TxdDef,TxdDef> *ms_pTxdPool;\n\tstatic RwTexDictionary *ms_pStoredTxd;\npublic:\n\tstatic void Initialise(void);\n\tstatic void Shutdown(void);\n\tstatic void GameShutdown(void);\n\tstatic int AddTxdSlot(const char *name);\n\tstatic void RemoveTxdSlot(int slot);\n\tstatic int FindTxdSlot(const char *name);\n\tstatic char *GetTxdName(int slot);\n\tstatic void PushCurrentTxd(void);\n\tstatic void PopCurrentTxd(void);\n\tstatic void SetCurrentTxd(int slot);\n\tstatic void Create(int slot);\n\tstatic int GetNumRefs(int slot);\n\tstatic void AddRef(int slot);\n\tstatic void RemoveRef(int slot);\n\tstatic void RemoveRefWithoutDelete(int slot);\n\tstatic bool LoadTxd(int slot, RwStream *stream);\n\tstatic bool LoadTxd(int slot, const char *filename);\n\tstatic bool StartLoadTxd(int slot, RwStream *stream);\n\tstatic bool FinishLoadTxd(int slot, RwStream *stream);\n\tstatic void RemoveTxd(int slot);\n\n\tstatic TxdDef *GetSlot(int slot) {\n\t\tassert(slot >= 0);\n\t\tassert(ms_pTxdPool);\n\t\tassert(slot < ms_pTxdPool->GetSize());\n\t\treturn ms_pTxdPool->GetSlot(slot);\n\t}\n\tstatic bool isTxdLoaded(int slot);\n};\n"
  },
  {
    "path": "src/rw/VisibilityPlugins.cpp",
    "content": "#include \"common.h\"\n\n#include \"RwHelper.h\"\n#include \"templates.h\"\n#include \"main.h\"\n#include \"Entity.h\"\n#include \"ModelInfo.h\"\n#include \"Lights.h\"\n#include \"RwHelper.h\"\n#include \"Renderer.h\"\n#include \"Camera.h\"\n#include \"VisibilityPlugins.h\"\n#include \"World.h\"\n#include \"custompipes.h\"\n#include \"MemoryHeap.h\"\n\nCLinkList<CVisibilityPlugins::AlphaObjectInfo> CVisibilityPlugins::m_alphaList;\nCLinkList<CVisibilityPlugins::AlphaObjectInfo> CVisibilityPlugins::m_alphaBoatAtomicList;\nCLinkList<CVisibilityPlugins::AlphaObjectInfo> CVisibilityPlugins::m_alphaEntityList;\nCLinkList<CVisibilityPlugins::AlphaObjectInfo> CVisibilityPlugins::m_alphaUnderwaterEntityList;\n#ifdef NEW_RENDERER\nCLinkList<CVisibilityPlugins::AlphaObjectInfo> CVisibilityPlugins::m_alphaBuildingList;\n#endif\n\nint32 CVisibilityPlugins::ms_atomicPluginOffset = -1;\nint32 CVisibilityPlugins::ms_framePluginOffset = -1;\nint32 CVisibilityPlugins::ms_clumpPluginOffset = -1;\n\nRwCamera *CVisibilityPlugins::ms_pCamera;\nRwV3d *CVisibilityPlugins::ms_pCameraPosn;\nfloat CVisibilityPlugins::ms_cullCompsDist;\nfloat CVisibilityPlugins::ms_vehicleLod0Dist;\nfloat CVisibilityPlugins::ms_vehicleLod1Dist;\nfloat CVisibilityPlugins::ms_vehicleFadeDist;\nfloat CVisibilityPlugins::ms_bigVehicleLod0Dist;\nfloat CVisibilityPlugins::ms_bigVehicleLod1Dist;\nfloat CVisibilityPlugins::ms_pedLod1Dist;\nfloat CVisibilityPlugins::ms_pedFadeDist;\n\n#define RENDERCALLBACK AtomicDefaultRenderCallBack\n\nvoid\nCVisibilityPlugins::Initialise(void)\n{\n\tm_alphaList.Init(NUMALPHALIST);\n\tm_alphaList.head.item.sort = 0.0f;\n\tm_alphaList.tail.item.sort = 100000000.0f;\n\n\tm_alphaBoatAtomicList.Init(NUMBOATALPHALIST);\n\tm_alphaBoatAtomicList.head.item.sort = 0.0f;\n\tm_alphaBoatAtomicList.tail.item.sort = 100000000.0f;\n\n#ifdef ASPECT_RATIO_SCALE\n\t// default 150 if not enough for bigger FOVs\n\tm_alphaEntityList.Init(NUMALPHAENTITYLIST * 3);\n#else\n\tm_alphaEntityList.Init(NUMALPHAENTITYLIST);\n#endif // ASPECT_RATIO_SCALE\n\tm_alphaEntityList.head.item.sort = 0.0f;\n\tm_alphaEntityList.tail.item.sort = 100000000.0f;\n\n\tm_alphaUnderwaterEntityList.Init(NUMALPHAUNTERWATERENTITYLIST);\n\tm_alphaUnderwaterEntityList.head.item.sort = 0.0f;\n\tm_alphaUnderwaterEntityList.tail.item.sort = 100000000.0f;\n\n#ifdef NEW_RENDERER\n\tm_alphaBuildingList.Init(NUMALPHAENTITYLIST);\n\tm_alphaBuildingList.head.item.sort = 0.0f;\n\tm_alphaBuildingList.tail.item.sort = 100000000.0f;\n#endif\n}\n\nvoid\nCVisibilityPlugins::Shutdown(void)\n{\n\tm_alphaList.Shutdown();\n\tm_alphaBoatAtomicList.Shutdown();\n\tm_alphaEntityList.Shutdown();\n\tm_alphaUnderwaterEntityList.Shutdown();\n#ifdef NEW_RENDERER\n\tm_alphaBuildingList.Shutdown();\n#endif\n}\n\nvoid\nCVisibilityPlugins::InitAlphaEntityList(void)\n{\n\tm_alphaEntityList.Clear();\n\tm_alphaBoatAtomicList.Clear();\n\tm_alphaUnderwaterEntityList.Clear();\n#ifdef NEW_RENDERER\n\tm_alphaBuildingList.Clear();\n#endif\n}\n\nbool\nCVisibilityPlugins::InsertEntityIntoSortedList(CEntity *e, float dist)\n{\n#ifdef FIX_BUGS\n\tif (!e->m_rwObject) return true;\n#endif\n\n\tAlphaObjectInfo item;\n\titem.entity = e;\n\titem.sort = dist;\n#ifdef NEW_RENDERER\n\tif(gbNewRenderer && e->IsBuilding())\n\t\treturn !!m_alphaBuildingList.InsertSorted(item);\n#endif\n\tif(e->bUnderwater && m_alphaUnderwaterEntityList.InsertSorted(item))\n\t\treturn true;\n\treturn !!m_alphaEntityList.InsertSorted(item);\n}\n\nvoid\nCVisibilityPlugins::InitAlphaAtomicList(void)\n{\n\tm_alphaList.Clear();\n}\n\nbool\nCVisibilityPlugins::InsertAtomicIntoSortedList(RpAtomic *a, float dist)\n{\n\tAlphaObjectInfo item;\n\titem.atomic = a;\n\titem.sort = dist;\n\treturn !!m_alphaList.InsertSorted(item);\n}\n\nbool\nCVisibilityPlugins::InsertAtomicIntoBoatSortedList(RpAtomic *a, float dist)\n{\n\tAlphaObjectInfo item;\n\titem.atomic = a;\n\titem.sort = dist;\n\treturn !!m_alphaBoatAtomicList.InsertSorted(item);\n}\n\n// can't increase this yet unfortunately...\n// probably have to fix fading for this so material alpha isn't overwritten\n#define VEHICLE_LODDIST_MULTIPLIER (TheCamera.GenerationDistMultiplier)\n\nvoid\nCVisibilityPlugins::SetRenderWareCamera(RwCamera *camera)\n{\n\tms_pCamera = camera;\n\tms_pCameraPosn = RwMatrixGetPos(RwFrameGetMatrix(RwCameraGetFrame(camera)));\n\n\tif(TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOPDOWN ||\n\t   TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOP_DOWN_PED)\n\t\tms_cullCompsDist = 1000000.0f;\n\telse\n\t\tms_cullCompsDist = sq(TheCamera.LODDistMultiplier * 20.0f);\n\n\tms_vehicleLod0Dist = sq(70.0f * VEHICLE_LODDIST_MULTIPLIER);\n\tms_vehicleLod1Dist = sq(90.0f * VEHICLE_LODDIST_MULTIPLIER);\n\tms_vehicleFadeDist = sq(100.0f * VEHICLE_LODDIST_MULTIPLIER);\n\tms_bigVehicleLod0Dist = sq(60.0f * VEHICLE_LODDIST_MULTIPLIER);\n\tms_bigVehicleLod1Dist = sq(150.0f * VEHICLE_LODDIST_MULTIPLIER);\n\tms_pedLod1Dist = sq(60.0f * TheCamera.LODDistMultiplier);\n\tms_pedFadeDist = sq(70.0f * TheCamera.LODDistMultiplier);\n}\n\nstatic float DistToCameraSq;\nstatic float PitchToCamera;\n\nvoid\nCVisibilityPlugins::SetupVehicleVariables(RpClump *vehicle)\n{\n\tif (RwObjectGetType((RwObject*)vehicle) != rpCLUMP)\n\t\treturn;\n\tDistToCameraSq = GetDistanceSquaredFromCamera(RpClumpGetFrame(vehicle));\n\tRwV3d distToCam;\n\tRwV3dSub(&distToCam, ms_pCameraPosn, &RwFrameGetMatrix(RpClumpGetFrame(vehicle))->pos);\n\tfloat dist2d = Sqrt(SQR(distToCam.x) + SQR(distToCam.y));\n\tPitchToCamera = Atan2(distToCam.z, dist2d);\n}\n\nRpMaterial*\nSetAlphaCB(RpMaterial *material, void *data)\n{\n\t((RwRGBA*)RpMaterialGetColor(material))->alpha = (uint8)(uintptr)data;\n\treturn material;\n}\n\nRpMaterial*\nSetTextureCB(RpMaterial *material, void *data)\n{\n\tRpMaterialSetTexture(material, (RwTexture*)data);\n\treturn material;\n}\n\nvoid\nCVisibilityPlugins::RenderAtomicList(CLinkList<AlphaObjectInfo> &list)\n{\n\tCLink<AlphaObjectInfo> *node;\n\tfor(node = list.tail.prev; node != &list.head; node = node->prev)\n\t\tRENDERCALLBACK(node->item.atomic);\n}\n\nvoid\nCVisibilityPlugins::RenderAlphaAtomics(void)\n{\n\tRenderAtomicList(m_alphaList);\n}\n\nvoid\nCVisibilityPlugins::RenderBoatAlphaAtomics(void)\n{\n\tSetCullMode(rwCULLMODECULLNONE);\n\tRenderAtomicList(m_alphaBoatAtomicList);\n\tSetCullMode(rwCULLMODECULLBACK);\n}\n\nvoid\nCVisibilityPlugins::RenderFadingEntities(CLinkList<AlphaObjectInfo> &list)\n{\n\tCLink<AlphaObjectInfo> *node;\n\tCSimpleModelInfo *mi;\n\tfor(node = list.tail.prev; node != &list.head; node = node->prev){\n\t\tCEntity *e = node->item.entity;\n\t\tif(e->m_rwObject == nil)\n\t\t\tcontinue;\n#ifdef EXTENDED_PIPELINES\n\t\tif(CustomPipes::bRenderingEnvMap && (e->IsPed() || e->IsVehicle()))\n\t\t\tcontinue;\n#endif\n\t\tmi = (CSimpleModelInfo *)CModelInfo::GetModelInfo(e->GetModelIndex());\n\t\tif(mi->GetModelType() == MITYPE_SIMPLE && mi->m_noZwrite)\n\t\t\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE, FALSE);\n\n\t\tif(e->bDistanceFade){\n\t\t\tDeActivateDirectional();\n\t\t\tSetAmbientColours();\n\t\t\te->bImBeingRendered = true;\n\t\t\tPUSH_RENDERGROUP(mi->GetModelName());\n\t\t\tRenderFadingAtomic((RpAtomic*)e->m_rwObject, node->item.sort);\n\t\t\tPOP_RENDERGROUP();\n\t\t\te->bImBeingRendered = false;\n\t\t}else\n\t\t\tCRenderer::RenderOneNonRoad(e);\n\n\t\tif(mi->GetModelType() == MITYPE_SIMPLE && mi->m_noZwrite)\n\t\t\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);\n\t}\n}\n\nvoid\nCVisibilityPlugins::RenderFadingEntities(void)\n{\n\tRenderFadingEntities(m_alphaEntityList);\n\tRenderBoatAlphaAtomics();\n}\n\nvoid\nCVisibilityPlugins::RenderFadingUnderwaterEntities(void)\n{\n\tRenderFadingEntities(m_alphaUnderwaterEntityList);\n}\n\nRpAtomic*\nCVisibilityPlugins::RenderWheelAtomicCB(RpAtomic *atomic)\n{\n\tRpAtomic *lodatm;\n\tfloat len;\n\tCSimpleModelInfo *mi;\n\n\tmi = GetAtomicModelInfo(atomic);\n\tlen = Sqrt(DistToCameraSq);\n\tlodatm = mi->GetAtomicFromDistance(len * TheCamera.LODDistMultiplier / VEHICLE_LODDIST_MULTIPLIER);\n\tif(lodatm){\n\t\tif(RpAtomicGetGeometry(lodatm) != RpAtomicGetGeometry(atomic))\n\t\t\tRpAtomicSetGeometry(atomic, RpAtomicGetGeometry(lodatm), rpATOMICSAMEBOUNDINGSPHERE);\n\t\tRENDERCALLBACK(atomic);\n\t}\n\treturn atomic;\n}\n\nRpAtomic*\nCVisibilityPlugins::RenderObjNormalAtomic(RpAtomic *atomic)\n{\n\tRwMatrix *m;\n\tRwV3d view;\n\tfloat len;\n\n\tm = RwFrameGetLTM(RpAtomicGetFrame(atomic));\n\tRwV3dSub(&view, RwMatrixGetPos(m), ms_pCameraPosn);\n\tlen = RwV3dLength(&view);\n\tif(RwV3dDotProduct(&view, RwMatrixGetUp(m)) < -0.3f*len && len > 8.0f)\n\t\treturn atomic;\n\tRENDERCALLBACK(atomic);\n\treturn atomic;\n}\n\nRpAtomic*\nCVisibilityPlugins::RenderAlphaAtomic(RpAtomic *atomic, int alpha)\n{\n\tRpGeometry *geo;\n\tuint32 flags;\n\n\tgeo = RpAtomicGetGeometry(atomic);\n\tflags = RpGeometryGetFlags(geo);\n\tRpGeometrySetFlags(geo, flags | rpGEOMETRYMODULATEMATERIALCOLOR);\n\tRpGeometryForAllMaterials(geo, SetAlphaCB, (void*)alpha);\n\tRENDERCALLBACK(atomic);\n\tRpGeometryForAllMaterials(geo, SetAlphaCB, (void*)255);\n\tRpGeometrySetFlags(geo, flags);\n\treturn atomic;\n}\n\nRpAtomic*\nCVisibilityPlugins::RenderWeaponCB(RpAtomic *atomic)\n{\n\tRwMatrix *m;\n\tRwV3d view;\n\tfloat maxdist, distsq;\n\tCSimpleModelInfo *mi;\n\n\tmi = GetAtomicModelInfo(atomic);\n\tm = RwFrameGetLTM(RpAtomicGetFrame(atomic));\n\tRwV3dSub(&view, RwMatrixGetPos(m), ms_pCameraPosn);\n\tmaxdist = mi->GetLodDistance(0);\n\tdistsq = RwV3dDotProduct(&view, &view);\n\tif(distsq < maxdist*maxdist)\n\t\tRENDERCALLBACK(atomic);\n\treturn atomic;\n}\n\nRpAtomic*\nCVisibilityPlugins::RenderFadingAtomic(RpAtomic *atomic, float camdist)\n{\n\tRpAtomic *lodatm;\n\tfloat fadefactor;\n\tuint32 alpha;\n\tCSimpleModelInfo *mi;\n\n\tmi = GetAtomicModelInfo(atomic);\n\tlodatm = mi->GetAtomicFromDistance(camdist - FADE_DISTANCE);\n\tif(mi->m_additive)\n\t\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE);\n\n\tfadefactor = (mi->GetLargestLodDistance() - (camdist - FADE_DISTANCE))/FADE_DISTANCE;\n\tif(fadefactor > 1.0f)\n\t\tfadefactor = 1.0f;\n\talpha = mi->m_alpha * fadefactor;\n\tif(alpha == 255)\n\t\tRENDERCALLBACK(atomic);\n\telse{\n\t\tRpGeometry *geo = RpAtomicGetGeometry(lodatm);\n\t\tuint32 flags = RpGeometryGetFlags(geo);\n\t\tRpGeometrySetFlags(geo, flags | rpGEOMETRYMODULATEMATERIALCOLOR);\n\t\tRpGeometryForAllMaterials(geo, SetAlphaCB, (void*)alpha);\n\t\tif(geo != RpAtomicGetGeometry(atomic))\n\t\t\tRpAtomicSetGeometry(atomic, geo, rpATOMICSAMEBOUNDINGSPHERE); // originally 5 (mistake?)\n\t\tRENDERCALLBACK(atomic);\n\t\tRpGeometryForAllMaterials(geo, SetAlphaCB, (void*)255);\n\t\tRpGeometrySetFlags(geo, flags);\n\t}\n\n\tif(mi->m_additive)\n\t\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);\n\n\treturn atomic;\n}\n\n\n\nRpAtomic*\nCVisibilityPlugins::RenderVehicleHiDetailCB(RpAtomic *atomic)\n{\n\tRwFrame *clumpframe;\n\tfloat dot;\n\tuint32 flags;\n\n\tclumpframe = RpClumpGetFrame(RpAtomicGetClump(atomic));\n\tif(DistToCameraSq < ms_vehicleLod0Dist){\n\t\tflags = GetAtomicId(atomic);\n\t\tif(DistToCameraSq > ms_cullCompsDist && (flags & ATOMIC_FLAG_NOCULL) == 0 && PitchToCamera < 0.2f){\n\t\t\tdot = GetDotProductWithCameraVector(RwFrameGetLTM(RpAtomicGetFrame(atomic)),\n\t\t\t\tRwFrameGetLTM(clumpframe), flags);\n\t\t\tif(dot > 0.0f && ((flags & ATOMIC_FLAG_ANGLECULL) || 0.1f*DistToCameraSq < dot*dot))\n\t\t\t\treturn atomic;\n\t\t}\n\t\tRENDERCALLBACK(atomic);\n\t}\n\treturn atomic;\n}\n\nRpAtomic*\nCVisibilityPlugins::RenderVehicleHiDetailAlphaCB(RpAtomic *atomic)\n{\n\tRwFrame *clumpframe;\n\tfloat dot;\n\tuint32 flags;\n\n\tclumpframe = RpClumpGetFrame(RpAtomicGetClump(atomic));\n\tif(DistToCameraSq < ms_vehicleLod0Dist){\n\t\tflags = GetAtomicId(atomic);\n\t\tdot = GetDotProductWithCameraVector(RwFrameGetLTM(RpAtomicGetFrame(atomic)),\n\t\t\tRwFrameGetLTM(clumpframe), flags);\n\t\tif(DistToCameraSq > ms_cullCompsDist && (flags & ATOMIC_FLAG_NOCULL) == 0 && PitchToCamera < 0.2f)\n\t\t\tif(dot > 0.0f && ((flags & ATOMIC_FLAG_ANGLECULL) || 0.1f*DistToCameraSq < dot*dot))\n\t\t\t\treturn atomic;\n\n\t\tif(flags & ATOMIC_FLAG_DRAWLAST){\n\t\t\t// sort before clump\n\t\t\tif(!InsertAtomicIntoSortedList(atomic, DistToCameraSq - 0.0001f))\n\t\t\t\tRENDERCALLBACK(atomic);\n\t\t}else{\n\t\t\tif(!InsertAtomicIntoSortedList(atomic, DistToCameraSq + dot))\n\t\t\t\tRENDERCALLBACK(atomic);\n\t\t}\n\t}\n\treturn atomic;\n}\n\nRpAtomic*\nCVisibilityPlugins::RenderVehicleHiDetailCB_BigVehicle(RpAtomic *atomic)\n{\n\tRwFrame *clumpframe;\n\tfloat dot;\n\tuint32 flags;\n\n\tclumpframe = RpClumpGetFrame(RpAtomicGetClump(atomic));\n\tif(DistToCameraSq < ms_bigVehicleLod0Dist){\n\t\tflags = GetAtomicId(atomic);\n\t\tif(DistToCameraSq > ms_cullCompsDist && (flags & ATOMIC_FLAG_NOCULL) == 0 && PitchToCamera < 0.2f){\n\t\t\tdot = GetDotProductWithCameraVector(RwFrameGetLTM(RpAtomicGetFrame(atomic)),\n\t\t\t\tRwFrameGetLTM(clumpframe), flags);\n\t\t\tif(dot > 0.0f)\n\t\t\t\treturn atomic;\n\t\t}\n\t\tRENDERCALLBACK(atomic);\n\t}\n\treturn atomic;\n}\n\nRpAtomic*\nCVisibilityPlugins::RenderVehicleHiDetailAlphaCB_BigVehicle(RpAtomic *atomic)\n{\n\tRwFrame *clumpframe;\n\tfloat dot;\n\tuint32 flags;\n\n\tclumpframe = RpClumpGetFrame(RpAtomicGetClump(atomic));\n\tif(DistToCameraSq < ms_bigVehicleLod0Dist){\n\t\tflags = GetAtomicId(atomic);\n\t\tdot = GetDotProductWithCameraVector(RwFrameGetLTM(RpAtomicGetFrame(atomic)),\n\t\t\tRwFrameGetLTM(clumpframe), flags);\n\t\tif(DistToCameraSq > ms_cullCompsDist && (flags & ATOMIC_FLAG_NOCULL) == 0 && PitchToCamera < 0.2f)\n\t\t\tif(dot > 0.0f && ((flags & ATOMIC_FLAG_ANGLECULL) || 0.1f*DistToCameraSq < dot*dot))\n\t\t\t\treturn atomic;\n\n\t\tif(!InsertAtomicIntoSortedList(atomic, DistToCameraSq + dot))\n\t\t\tRENDERCALLBACK(atomic);\n\t}\n\treturn atomic;\n}\n\nRpAtomic*\nCVisibilityPlugins::RenderVehicleHiDetailCB_Boat(RpAtomic *atomic)\n{\n\tif(DistToCameraSq < ms_vehicleLod0Dist)\n\t\tRENDERCALLBACK(atomic);\n\treturn atomic;\n}\n\nRpAtomic*\nCVisibilityPlugins::RenderVehicleHiDetailAlphaCB_Boat(RpAtomic *atomic)\n{\n\tif(DistToCameraSq < ms_vehicleLod0Dist){\n\t\tif(GetAtomicId(atomic) & ATOMIC_FLAG_DRAWLAST){\n\t\t\tif(!InsertAtomicIntoBoatSortedList(atomic, DistToCameraSq))\n\t\t\t\tRENDERCALLBACK(atomic);\n\t\t}else\n\t\t\tRENDERCALLBACK(atomic);\n\t}\n\treturn atomic;\n}\n\nRpAtomic*\nCVisibilityPlugins::RenderVehicleLoDetailCB_Boat(RpAtomic *atomic)\n{\n\tRpClump *clump;\n\tint32 alpha;\n\n\tclump = RpAtomicGetClump(atomic);\n\tif(DistToCameraSq >= ms_vehicleLod0Dist){\n\t\talpha = GetClumpAlpha(clump);\n\t\tif(alpha == 255)\n\t\t\tRENDERCALLBACK(atomic);\n\t\telse\n\t\t\tRenderAlphaAtomic(atomic, alpha);\n\t}\n\treturn atomic;\n}\n\nRpAtomic*\nCVisibilityPlugins::RenderVehicleLowDetailCB_BigVehicle(RpAtomic *atomic)\n{\n\tRwFrame *clumpframe;\n\tfloat dot;\n\tuint32 flags;\n\n\tclumpframe = RpClumpGetFrame(RpAtomicGetClump(atomic));\n\tif(DistToCameraSq >= ms_bigVehicleLod0Dist &&\n\t   DistToCameraSq < ms_bigVehicleLod1Dist){\n\t\tflags = GetAtomicId(atomic);\n\t\tif(DistToCameraSq > ms_cullCompsDist && (flags & ATOMIC_FLAG_NOCULL) == 0 && PitchToCamera < 0.2f){\n\t\t\tdot = GetDotProductWithCameraVector(RwFrameGetLTM(RpAtomicGetFrame(atomic)),\n\t\t\t\tRwFrameGetLTM(clumpframe), flags);\n\t\t\tif(dot > 0.0f)\n\t\t\t\treturn atomic;\n\t\t}\n\t\tRENDERCALLBACK(atomic);\n\t}\n\treturn atomic;\n}\n\nRpAtomic*\nCVisibilityPlugins::RenderVehicleLowDetailAlphaCB_BigVehicle(RpAtomic *atomic)\n{\n\tRwFrame *clumpframe;\n\tfloat dot;\n\tuint32 flags;\n\n\tclumpframe = RpClumpGetFrame(RpAtomicGetClump(atomic));\n\tif(DistToCameraSq >= ms_bigVehicleLod0Dist &&\n\t   DistToCameraSq < ms_bigVehicleLod1Dist){\n\t\tflags = GetAtomicId(atomic);\n\t\tdot = GetDotProductWithCameraVector(RwFrameGetLTM(RpAtomicGetFrame(atomic)),\n\t\t\tRwFrameGetLTM(clumpframe), flags);\n\t\tif(dot > 0.0f)\n\t\t\tif(DistToCameraSq > ms_cullCompsDist && (flags & ATOMIC_FLAG_NOCULL) == 0 && PitchToCamera < 0.2f)\n\t\t\t\treturn atomic;\n\n\t\tif(!InsertAtomicIntoSortedList(atomic, DistToCameraSq + dot))\n\t\t\tRENDERCALLBACK(atomic);\n\t}\n\treturn atomic;\n}\n\nRpAtomic*\nCVisibilityPlugins::RenderVehicleReallyLowDetailCB(RpAtomic *atomic)\n{\n\tRpClump *clump;\n\tint32 alpha;\n\n\tclump = RpAtomicGetClump(atomic);\n\tif(DistToCameraSq >= ms_vehicleLod0Dist){\n\t\talpha = GetClumpAlpha(clump);\n\t\tif(alpha == 255)\n\t\t\tRENDERCALLBACK(atomic);\n\t\telse\n\t\t\tRenderAlphaAtomic(atomic, alpha);\n\t}\n\treturn atomic;\n\n}\n\nRpAtomic*\nCVisibilityPlugins::RenderVehicleReallyLowDetailCB_BigVehicle(RpAtomic *atomic)\n{\n\tif(DistToCameraSq >= ms_bigVehicleLod1Dist)\n\t\tRENDERCALLBACK(atomic);\n\treturn atomic;\n}\n\nRpAtomic*\nCVisibilityPlugins::RenderTrainHiDetailCB(RpAtomic *atomic)\n{\n\tRwFrame *clumpframe;\n\tfloat dot;\n\tuint32 flags;\n\n\tclumpframe = RpClumpGetFrame(RpAtomicGetClump(atomic));\n\tif(DistToCameraSq < ms_bigVehicleLod1Dist){\n\t\tflags = GetAtomicId(atomic);\n\t\tif(DistToCameraSq > ms_cullCompsDist && (flags & ATOMIC_FLAG_NOCULL) == 0 && PitchToCamera < 0.2f){\n\t\t\tdot = GetDotProductWithCameraVector(RwFrameGetLTM(RpAtomicGetFrame(atomic)),\n\t\t\t\tRwFrameGetLTM(clumpframe), flags);\n\t\t\tif(dot > 0.0f && ((flags & ATOMIC_FLAG_ANGLECULL) || 0.1f*DistToCameraSq < dot*dot))\n\t\t\t\treturn atomic;\n\t\t}\n\t\tRENDERCALLBACK(atomic);\n\t}\n\treturn atomic;\n}\n\nRpAtomic*\nCVisibilityPlugins::RenderTrainHiDetailAlphaCB(RpAtomic *atomic)\n{\n\tRwFrame *clumpframe;\n\tfloat dot;\n\tuint32 flags;\n\n\tclumpframe = RpClumpGetFrame(RpAtomicGetClump(atomic));\n\tif(DistToCameraSq < ms_bigVehicleLod1Dist){\n\t\tflags = GetAtomicId(atomic);\n\t\tdot = GetDotProductWithCameraVector(RwFrameGetLTM(RpAtomicGetFrame(atomic)),\n\t\t\tRwFrameGetLTM(clumpframe), flags);\n\t\tif(DistToCameraSq > ms_cullCompsDist && (flags & ATOMIC_FLAG_NOCULL) == 0 && PitchToCamera < 0.2f)\n\t\t\tif(dot > 0.0f && ((flags & ATOMIC_FLAG_ANGLECULL) || 0.1f*DistToCameraSq < dot*dot))\n\t\t\t\treturn atomic;\n\n\t\tif(flags & ATOMIC_FLAG_DRAWLAST){\n\t\t\t// sort before clump\n\t\t\tif(!InsertAtomicIntoSortedList(atomic, DistToCameraSq - 0.0001f))\n\t\t\t\tRENDERCALLBACK(atomic);\n\t\t}else{\n\t\t\tif(!InsertAtomicIntoSortedList(atomic, DistToCameraSq + dot))\n\t\t\t\tRENDERCALLBACK(atomic);\n\t\t}\n\t}\n\treturn atomic;\n}\n\nRpAtomic*\nCVisibilityPlugins::RenderVehicleRotorAlphaCB(RpAtomic *atomic)\n{\n\tRwFrame *clumpframe;\n\tfloat dot;\n\tRwV3d cam2atm;\n\n\tclumpframe = RpClumpGetFrame(RpAtomicGetClump(atomic));\n\tif(DistToCameraSq < ms_bigVehicleLod1Dist){\n\t\tRwV3dSub(&cam2atm, &RwFrameGetLTM(RpAtomicGetFrame(atomic))->pos, ms_pCameraPosn);\n\t\tdot = RwV3dDotProduct(&cam2atm, &RwFrameGetLTM(clumpframe)->at);\n\t\tif(!InsertAtomicIntoSortedList(atomic, DistToCameraSq + dot*20.0f))\n\t\t\tRENDERCALLBACK(atomic);\n\t}\n\treturn atomic;\n}\n\nRpAtomic*\nCVisibilityPlugins::RenderVehicleTailRotorAlphaCB(RpAtomic *atomic)\n{\n\tRwMatrix *clumpMat, *atmMat;\n\tfloat dot;\n\tRwV3d cam2atm;\n\n\tif(DistToCameraSq < ms_bigVehicleLod0Dist){\n\t\tatmMat = RwFrameGetLTM(RpAtomicGetFrame(atomic));\n\t\tclumpMat = RwFrameGetLTM(RpClumpGetFrame(RpAtomicGetClump(atomic)));\n\t\tRwV3dSub(&cam2atm, &atmMat->pos, ms_pCameraPosn);\n\t\tdot = RwV3dDotProduct(&cam2atm, &clumpMat->up) + RwV3dDotProduct(&cam2atm, &clumpMat->right);\n\t\tif(!InsertAtomicIntoSortedList(atomic, DistToCameraSq - dot))\n\t\t\tRENDERCALLBACK(atomic);\n\t}\n\treturn atomic;\n}\n\nRpAtomic*\nCVisibilityPlugins::RenderPlayerCB(RpAtomic *atomic)\n{\n\tif(CWorld::Players[0].m_pSkinTexture)\n\t\tRpGeometryForAllMaterials(RpAtomicGetGeometry(atomic), SetTextureCB, CWorld::Players[0].m_pSkinTexture);\n\tRENDERCALLBACK(atomic);\n\treturn atomic;\n}\n\nRpAtomic*\nCVisibilityPlugins::RenderPedCB(RpAtomic *atomic)\n{\n\tint32 alpha;\n\tRwV3d cam2atm;\n\n\tRwV3dSub(&cam2atm, &RwFrameGetLTM(RpAtomicGetFrame(atomic))->pos, ms_pCameraPosn);\n\tif(RwV3dDotProduct(&cam2atm, &cam2atm) < ms_pedLod1Dist){\n\t\talpha = GetClumpAlpha(RpAtomicGetClump(atomic));\n\t\tif(alpha == 255)\n\t\t\tRENDERCALLBACK(atomic);\n\t\telse\n\t\t\tRenderAlphaAtomic(atomic, alpha);\n\t}\n\treturn atomic;\n}\n\nfloat\nCVisibilityPlugins::GetDistanceSquaredFromCamera(RwV3d *pos)\n{\n\tRwV3d dist;\n\tRwV3dSub(&dist, pos, ms_pCameraPosn);\n\treturn RwV3dDotProduct(&dist, &dist);\n}\n\nfloat\nCVisibilityPlugins::GetDistanceSquaredFromCamera(RwFrame *frame)\n{\n\tRwMatrix *m;\n\tRwV3d dist;\n\tm = RwFrameGetLTM(frame);\n\tRwV3dSub(&dist, RwMatrixGetPos(m), ms_pCameraPosn);\n\treturn RwV3dDotProduct(&dist, &dist);\n}\n\nfloat\nCVisibilityPlugins::GetDotProductWithCameraVector(RwMatrix *atomicMat, RwMatrix *clumpMat, uint32 flags)\n{\n\tRwV3d dist;\n\tfloat dot, dotdoor;\n\n\t// Vehicle forward is the y axis (RwMatrix.up)\n\t// Vehicle right is the x axis (RwMatrix.right)\n\n\tRwV3dSub(&dist, RwMatrixGetPos(atomicMat), ms_pCameraPosn);\n\t// forward/backward facing\n\tif(flags & (ATOMIC_FLAG_FRONT | ATOMIC_FLAG_REAR))\n\t\tdot = RwV3dDotProduct(&dist, RwMatrixGetUp(clumpMat));\n\t// left/right facing\n\telse if(flags & (ATOMIC_FLAG_LEFT | ATOMIC_FLAG_RIGHT))\n\t\tdot = RwV3dDotProduct(&dist, RwMatrixGetRight(clumpMat));\n\telse\n\t\tdot = 0.0f;\n\tif(flags & (ATOMIC_FLAG_LEFT | ATOMIC_FLAG_REAR))\n\t\tdot = -dot;\n\n\tif(flags & (ATOMIC_FLAG_REARDOOR | ATOMIC_FLAG_FRONTDOOR)){\n\t\tif(flags & ATOMIC_FLAG_REARDOOR)\n\t\t\tdotdoor = -RwV3dDotProduct(&dist, RwMatrixGetUp(clumpMat));\n\t\telse if(flags & ATOMIC_FLAG_FRONTDOOR)\n\t\t\tdotdoor = RwV3dDotProduct(&dist, RwMatrixGetUp(clumpMat));\n\t\telse\n\t\t\tdotdoor = 0.0f;\n\n\t\tif(dot < 0.0f && dotdoor < 0.0f)\n\t\t\tdot += dotdoor;\n\t\tif(dot > 0.0f && dotdoor > 0.0f)\n\t\t\tdot += dotdoor;\n\t}\n\n\treturn dot;\n}\n\n/* These are all unused */\n\nbool\nCVisibilityPlugins::DefaultVisibilityCB(RpClump *clump)\n{\n\treturn true;\n}\n\nbool\nCVisibilityPlugins::FrustumSphereCB(RpClump *clump)\n{\n\tRwSphere sphere;\n\tRwFrame *frame = RpClumpGetFrame(clump);\n\n\tCClumpModelInfo *modelInfo = (CClumpModelInfo*)GetFrameHierarchyId(frame);\n\tsphere.radius = modelInfo->GetColModel()->boundingSphere.radius;\n\tsphere.center.x = modelInfo->GetColModel()->boundingSphere.center.x;\n\tsphere.center.y = modelInfo->GetColModel()->boundingSphere.center.y;\n\tsphere.center.z = modelInfo->GetColModel()->boundingSphere.center.z;\n\tRwV3dTransformPoints(&sphere.center, &sphere.center, 1, RwFrameGetLTM(frame));\n\treturn RwCameraFrustumTestSphere(ms_pCamera, &sphere) != rwSPHEREOUTSIDE;\n}\n\nbool\nCVisibilityPlugins::VehicleVisibilityCB(RpClump *clump)\n{\n\tif (GetDistanceSquaredFromCamera(RpClumpGetFrame(clump)) <= ms_vehicleLod1Dist)\n\t\treturn FrustumSphereCB(clump);\n\treturn false;\n}\n\nbool\nCVisibilityPlugins::VehicleVisibilityCB_BigVehicle(RpClump *clump)\n{\n\treturn FrustumSphereCB(clump);\n}\n\n\n\n\n//\n// RW Plugins\n//\n\nenum\n{\n\tID_VISIBILITYATOMIC = MAKECHUNKID(rwVENDORID_ROCKSTAR, 0x00),\n\tID_VISIBILITYCLUMP  = MAKECHUNKID(rwVENDORID_ROCKSTAR, 0x01),\n\tID_VISIBILITYFRAME  = MAKECHUNKID(rwVENDORID_ROCKSTAR, 0x02),\n};\n\nbool\nCVisibilityPlugins::PluginAttach(void)\n{\n\tms_atomicPluginOffset = RpAtomicRegisterPlugin(sizeof(AtomicExt),\n\t\tID_VISIBILITYATOMIC,\n\t\tAtomicConstructor, AtomicDestructor, AtomicCopyConstructor);\n\n\tms_framePluginOffset = RwFrameRegisterPlugin(sizeof(FrameExt),\n\t\tID_VISIBILITYFRAME,\n\t\tFrameConstructor, FrameDestructor, FrameCopyConstructor);\n\n\tms_clumpPluginOffset = RpClumpRegisterPlugin(sizeof(ClumpExt),\n\t\tID_VISIBILITYCLUMP,\n\t\tClumpConstructor, ClumpDestructor, ClumpCopyConstructor);\n\treturn ms_atomicPluginOffset != -1 && ms_clumpPluginOffset != -1;\n}\n\n#define ATOMICEXT(o) (RWPLUGINOFFSET(AtomicExt, o, ms_atomicPluginOffset))\n#define FRAMEEXT(o) (RWPLUGINOFFSET(FrameExt, o, ms_framePluginOffset))\n#define CLUMPEXT(o) (RWPLUGINOFFSET(ClumpExt, o, ms_clumpPluginOffset))\n\n//\n// Atomic\n//\n\nvoid*\nCVisibilityPlugins::AtomicConstructor(void *object, int32, int32)\n{\n\tATOMICEXT(object)->modelInfo = nil;\n\treturn object;\n}\n\nvoid*\nCVisibilityPlugins::AtomicDestructor(void *object, int32, int32)\n{\n\treturn object;\n}\n\nvoid*\nCVisibilityPlugins::AtomicCopyConstructor(void *dst, const void *src, int32, int32)\n{\n\t*ATOMICEXT(dst) = *ATOMICEXT(src);\n\treturn dst;\n}\n\nvoid\nCVisibilityPlugins::SetAtomicModelInfo(RpAtomic *atomic,\n                                       CSimpleModelInfo *modelInfo)\n{\n\tAtomicExt *ext = ATOMICEXT(atomic);\n\text->modelInfo = modelInfo;\n}\n\nCSimpleModelInfo*\nCVisibilityPlugins::GetAtomicModelInfo(RpAtomic *atomic)\n{\n\treturn ATOMICEXT(atomic)->modelInfo;\n}\n\nvoid\nCVisibilityPlugins::SetAtomicFlag(RpAtomic *atomic, int f)\n{\n\tATOMICEXT(atomic)->flags |= f;\n}\n\nvoid\nCVisibilityPlugins::ClearAtomicFlag(RpAtomic *atomic, int f)\n{\n\tATOMICEXT(atomic)->flags &= ~f;\n}\n\nint\nCVisibilityPlugins::GetAtomicId(RpAtomic *atomic)\n{\n\treturn ATOMICEXT(atomic)->flags;\n}\n\nvoid\nCVisibilityPlugins::SetAtomicRenderCallback(RpAtomic *atomic, RpAtomicCallBackRender cb)\n{\n\tif(cb == nil)\n\t\tcb = RENDERCALLBACK;\t// not necessary\n\tRpAtomicSetRenderCallBack(atomic, cb);\n}\n\n//\n// Frame\n//\n\nvoid*\nCVisibilityPlugins::FrameConstructor(void *object, int32, int32)\n{\n\tFRAMEEXT(object)->id = 0;\n\treturn object;\n}\n\nvoid*\nCVisibilityPlugins::FrameDestructor(void *object, int32, int32)\n{\n\treturn object;\n}\n\nvoid*\nCVisibilityPlugins::FrameCopyConstructor(void *dst, const void *src, int32, int32)\n{\n\t*FRAMEEXT(dst) = *FRAMEEXT(src);\n\treturn dst;\n}\n\nvoid\nCVisibilityPlugins::SetFrameHierarchyId(RwFrame *frame, intptr id)\n{\n\tFRAMEEXT(frame)->id = id;\n}\n\nintptr\nCVisibilityPlugins::GetFrameHierarchyId(RwFrame *frame)\n{\n\treturn FRAMEEXT(frame)->id;\n}\n\n\n//\n// Clump\n//\n\nvoid*\nCVisibilityPlugins::ClumpConstructor(void *object, int32, int32)\n{\n\tClumpExt *ext = CLUMPEXT(object);\n\text->visibilityCB = DefaultVisibilityCB;\n\text->alpha = 0xFF;\n\treturn object;\n}\n\nvoid*\nCVisibilityPlugins::ClumpDestructor(void *object, int32, int32)\n{\n\treturn object;\n}\n\nvoid*\nCVisibilityPlugins::ClumpCopyConstructor(void *dst, const void *src, int32, int32)\n{\n\tCLUMPEXT(dst)->visibilityCB = CLUMPEXT(src)->visibilityCB;\n\treturn dst;\n}\n\nvoid\nCVisibilityPlugins::SetClumpModelInfo(RpClump *clump, CClumpModelInfo *modelInfo)\n{\n\tCVehicleModelInfo *vmi;\n\tSetFrameHierarchyId(RpClumpGetFrame(clump), (intptr)modelInfo);\n\n\t// Unused\n\tswitch (modelInfo->GetModelType()) {\n\t// ignore MLO\n\tcase MITYPE_VEHICLE:\n\t\tvmi = (CVehicleModelInfo*)modelInfo;\n\t\tif(vmi->m_vehicleType == VEHICLE_TYPE_TRAIN ||\n\t\t   vmi->m_vehicleType == VEHICLE_TYPE_HELI ||\n\t\t   vmi->m_vehicleType == VEHICLE_TYPE_PLANE)\n\t\t\tCLUMPEXT(clump)->visibilityCB = VehicleVisibilityCB_BigVehicle;\n\t\telse\n\t\t\tCLUMPEXT(clump)->visibilityCB = VehicleVisibilityCB;\n\t\tbreak;\n\tdefault: break;\n\t}\n}\n\nvoid\nCVisibilityPlugins::SetClumpAlpha(RpClump *clump, int alpha)\n{\n\tCLUMPEXT(clump)->alpha = alpha;\n}\n\nint\nCVisibilityPlugins::GetClumpAlpha(RpClump *clump)\n{\n\treturn CLUMPEXT(clump)->alpha;\n}\n"
  },
  {
    "path": "src/rw/VisibilityPlugins.h",
    "content": "#pragma once\n\n#include \"templates.h\"\n\nclass CEntity;\nclass CSimpleModelInfo;\nclass CClumpModelInfo;\n\ntypedef bool (*ClumpVisibilityCB)(RpClump*);\n\nclass CVisibilityPlugins\n{\npublic:\n\tstruct AlphaObjectInfo\n\t{\n\t\tunion {\n\t\t\tCEntity *entity;\n\t\t\tRpAtomic *atomic;\n\t\t};\n\t\tfloat sort;\n\t};\n\n\tstatic CLinkList<AlphaObjectInfo> m_alphaList;\n\tstatic CLinkList<AlphaObjectInfo> m_alphaBoatAtomicList;\n\tstatic CLinkList<AlphaObjectInfo> m_alphaEntityList;\n\tstatic CLinkList<AlphaObjectInfo> m_alphaUnderwaterEntityList;\n#ifdef NEW_RENDERER\n\tstatic CLinkList<AlphaObjectInfo> m_alphaBuildingList;\n#endif\n\tstatic RwCamera *ms_pCamera;\n\tstatic RwV3d *ms_pCameraPosn;\n\tstatic float ms_cullCompsDist;\n\tstatic float ms_vehicleLod0Dist;\n\tstatic float ms_vehicleLod1Dist;\n\tstatic float ms_vehicleFadeDist;\n\tstatic float ms_bigVehicleLod0Dist;\n\tstatic float ms_bigVehicleLod1Dist;\n\tstatic float ms_pedLod1Dist;\n\tstatic float ms_pedFadeDist;\n\n\tstatic void Initialise(void);\n\tstatic void Shutdown(void);\n\tstatic void InitAlphaEntityList(void);\n\tstatic bool InsertEntityIntoSortedList(CEntity *e, float dist);\n\tstatic void InitAlphaAtomicList(void);\n\tstatic bool InsertAtomicIntoSortedList(RpAtomic *a, float dist);\n\tstatic bool InsertAtomicIntoBoatSortedList(RpAtomic *a, float dist);\n\n\tstatic void SetRenderWareCamera(RwCamera *camera);\n\tstatic void SetupVehicleVariables(RpClump *vehicle);\n\n\tstatic RpAtomic *RenderWheelAtomicCB(RpAtomic *atomic);\n\tstatic RpAtomic *RenderObjNormalAtomic(RpAtomic *atomic);\n\tstatic RpAtomic *RenderAlphaAtomic(RpAtomic *atomic, int alpha);\n\tstatic RpAtomic *RenderWeaponCB(RpAtomic *atomic);\n\tstatic RpAtomic *RenderFadingAtomic(RpAtomic *atm, float dist);\n\n\tstatic RpAtomic *RenderVehicleHiDetailCB(RpAtomic *atomic);\n\tstatic RpAtomic *RenderVehicleHiDetailAlphaCB(RpAtomic *atomic);\n\tstatic RpAtomic *RenderVehicleHiDetailCB_BigVehicle(RpAtomic *atomic);\n\tstatic RpAtomic *RenderVehicleHiDetailAlphaCB_BigVehicle(RpAtomic *atomic);\n\tstatic RpAtomic *RenderVehicleHiDetailCB_Boat(RpAtomic *atomic);\n\tstatic RpAtomic *RenderVehicleHiDetailAlphaCB_Boat(RpAtomic *atomic);\n\tstatic RpAtomic *RenderVehicleLoDetailCB_Boat(RpAtomic *atomic);\n\tstatic RpAtomic *RenderVehicleLowDetailCB_BigVehicle(RpAtomic *atomic);\n\tstatic RpAtomic *RenderVehicleLowDetailAlphaCB_BigVehicle(RpAtomic *atomic);\n\tstatic RpAtomic *RenderVehicleReallyLowDetailCB(RpAtomic *atomic);\n\tstatic RpAtomic *RenderVehicleReallyLowDetailCB_BigVehicle(RpAtomic *atomic);\n\tstatic RpAtomic *RenderTrainHiDetailCB(RpAtomic *atomic);\n\tstatic RpAtomic *RenderTrainHiDetailAlphaCB(RpAtomic *atomic);\n\tstatic RpAtomic *RenderVehicleRotorAlphaCB(RpAtomic *atomic);\n\tstatic RpAtomic *RenderVehicleTailRotorAlphaCB(RpAtomic *atomic);\n\n\tstatic RpAtomic *RenderPlayerCB(RpAtomic *atomic);\n\tstatic RpAtomic *RenderPedCB(RpAtomic *atomic);\t// for skinned models with only one clump\n\n\tstatic void RenderAtomicList(CLinkList<AlphaObjectInfo> &list);\n\tstatic void RenderAlphaAtomics(void);\n\tstatic void RenderBoatAlphaAtomics(void);\n\tstatic void RenderFadingEntities(CLinkList<AlphaObjectInfo> &list);\n\tstatic void RenderFadingEntities(void);\n\tstatic void RenderFadingUnderwaterEntities(void);\n\n\t// All actually unused\n\tstatic bool DefaultVisibilityCB(RpClump *clump);\n\tstatic bool FrustumSphereCB(RpClump *clump);\n\tstatic bool VehicleVisibilityCB(RpClump *clump);\n\tstatic bool VehicleVisibilityCB_BigVehicle(RpClump *clump);\n\n\tstatic float GetDistanceSquaredFromCamera(RwV3d *pos);\n\tstatic float GetDistanceSquaredFromCamera(RwFrame *frame);\n\tstatic float GetDotProductWithCameraVector(RwMatrix *atomicMat, RwMatrix *clumpMat, uint32 flags);\n\n\t//\n\t// RW Plugins\n\t//\n\n\tunion AtomicExt\n\t{\n\t\tCSimpleModelInfo *modelInfo;\t// used by SimpleModelInfo\n\t\tint flags;\t\t\t// used by ClumpModelInfo\n\t};\n\tstatic void SetAtomicModelInfo(RpAtomic*, CSimpleModelInfo*);\n\tstatic CSimpleModelInfo *GetAtomicModelInfo(RpAtomic *atomic);\n\tstatic void SetAtomicFlag(RpAtomic*, int);\n\tstatic void ClearAtomicFlag(RpAtomic*, int);\n\tstatic int GetAtomicId(RpAtomic *atomic);\n\tstatic void SetAtomicRenderCallback(RpAtomic*, RpAtomicCallBackRender);\n\n\tstatic void *AtomicConstructor(void *object, int32 offset, int32 len);\n\tstatic void *AtomicDestructor(void *object, int32 offset, int32 len);\n\tstatic void *AtomicCopyConstructor(void *dst, const void *src,\n\t                                   int32 offset, int32 len);\n\tstatic int32 ms_atomicPluginOffset;\n\n\tstruct FrameExt\n\t{\n\t\t// BUG: this is abused to hold a pointer by SetClumpModelInfo\n\t\tintptr id;\n\t};\n\tstatic void SetFrameHierarchyId(RwFrame *frame, intptr id);\n\tstatic intptr GetFrameHierarchyId(RwFrame *frame);\n\n\tstatic void *FrameConstructor(void *object, int32 offset, int32 len);\n\tstatic void *FrameDestructor(void *object, int32 offset, int32 len);\n\tstatic void *FrameCopyConstructor(void *dst, const void *src,\n\t                                  int32 offset, int32 len);\n\tstatic int32 ms_framePluginOffset;\n\n\t// Not actually used\n\tstruct ClumpExt\n\t{\n\t\tClumpVisibilityCB visibilityCB;\n\t\tint alpha;\n\t};\n\tstatic void SetClumpModelInfo(RpClump*, CClumpModelInfo*);\n\tstatic void SetClumpAlpha(RpClump*, int);\n\tstatic int GetClumpAlpha(RpClump*);\n\n\tstatic void *ClumpConstructor(void *object, int32 offset, int32 len);\n\tstatic void *ClumpDestructor(void *object, int32 offset, int32 len);\n\tstatic void *ClumpCopyConstructor(void *dst, const void *src,\n\t                                  int32 offset, int32 len);\n\tstatic int32 ms_clumpPluginOffset;\n\n\tstatic bool PluginAttach(void);\n};\n\nRpMaterial *SetAlphaCB(RpMaterial *material, void *data);\n"
  },
  {
    "path": "src/save/Date.cpp",
    "content": "#include \"common.h\"\n#include \"Date.h\"\n\nCDate::CDate()\n{\n\tm_nYear = 0;\n\tm_nSecond = 0;\n\tm_nMinute = 0;\n\tm_nHour = 0;\n\tm_nDay = 0;\n\tm_nMonth = 0;\n}\n\nbool\nCDate::operator>(const CDate &right)\n{\n\tif (m_nYear > right.m_nYear)\n\t\treturn true;\n\tif (m_nYear != right.m_nYear)\n\t\treturn false;\n\n\tif (m_nMonth > right.m_nMonth)\n\t\treturn true;\n\tif (m_nMonth != right.m_nMonth)\n\t\treturn false;\n\n\tif (m_nDay > right.m_nDay)\n\t\treturn true;\n\tif (m_nDay != right.m_nDay)\n\t\treturn false;\n\n\tif (m_nHour > right.m_nHour)\n\t\treturn true;\n\tif (m_nHour != right.m_nHour)\n\t\treturn false;\n\n\tif (m_nMinute > right.m_nMinute)\n\t\treturn true;\n\tif (m_nMinute != right.m_nMinute)\n\t\treturn false;\n\treturn m_nSecond > right.m_nSecond;\n}\n\nbool\nCDate::operator<(const CDate &right)\n{\n\tif (m_nYear < right.m_nYear)\n\t\treturn true;\n\tif (m_nYear != right.m_nYear)\n\t\treturn false;\n\n\tif (m_nMonth < right.m_nMonth)\n\t\treturn true;\n\tif (m_nMonth != right.m_nMonth)\n\t\treturn false;\n\n\tif (m_nDay < right.m_nDay)\n\t\treturn true;\n\tif (m_nDay != right.m_nDay)\n\t\treturn false;\n\n\tif (m_nHour < right.m_nHour)\n\t\treturn true;\n\tif (m_nHour != right.m_nHour)\n\t\treturn false;\n\n\tif (m_nMinute < right.m_nMinute)\n\t\treturn true;\n\tif (m_nMinute != right.m_nMinute)\n\t\treturn false;\n\treturn m_nSecond < right.m_nSecond;\n}\n\nbool\nCDate::operator==(const CDate &right)\n{\n\tif (m_nYear != right.m_nYear || m_nMonth != right.m_nMonth || m_nDay != right.m_nDay || m_nHour != right.m_nHour || m_nMinute != right.m_nMinute)\n\t\treturn false;\n\treturn m_nSecond == right.m_nSecond;\n}\n\nvoid\nCDate::PopulateDateFields(int8 &second, int8 &minute, int8 &hour, int8 &day, int8 &month, int16 year)\n{\n\tm_nSecond = second;\n\tm_nMinute = minute;\n\tm_nHour = hour;\n\tm_nDay = day;\n\tm_nMonth = month;\n\tm_nYear = year;\n}"
  },
  {
    "path": "src/save/Date.h",
    "content": "#pragma once\n\nclass CDate\n{\npublic:\n\tint m_nSecond;\n\tint m_nMinute;\n\tint m_nHour;\n\tint m_nDay;\n\tint m_nMonth;\n\tint m_nYear;\n\t\n\tCDate();\n\tbool operator>(const CDate &right);\n\tbool operator<(const CDate &right);\n\tbool operator==(const CDate &right);\n\tvoid PopulateDateFields(int8 &second, int8 &minute, int8 &hour, int8 &day, int8 &month, int16 year);\n};"
  },
  {
    "path": "src/save/GenericGameStorage.cpp",
    "content": "#define WITHWINDOWS\n#include \"common.h\"\n#include \"crossplatform.h\"\n#include \"main.h\"\n\n#include \"DMAudio.h\"\n#include \"AudioScriptObject.h\"\n#include \"Camera.h\"\n#include \"CarGen.h\"\n#include \"Cranes.h\"\n#include \"Clock.h\"\n#include \"Date.h\"\n#include \"FileMgr.h\"\n#include \"Font.h\"\n#include \"Frontend.h\"\n#include \"GameLogic.h\"\n#include \"Gangs.h\"\n#include \"Garages.h\"\n#include \"GenericGameStorage.h\"\n#include \"Pad.h\"\n#include \"Particle.h\"\n#include \"ParticleObject.h\"\n#include \"PathFind.h\"\n#include \"PCSave.h\"\n#include \"Phones.h\"\n#include \"Pickups.h\"\n#include \"PlayerPed.h\"\n#include \"ProjectileInfo.h\"\n#include \"Pools.h\"\n#include \"Radar.h\"\n#include \"Restart.h\"\n#include \"Script.h\"\n#include \"SetPieces.h\"\n#include \"Stats.h\"\n#include \"Streaming.h\"\n#include \"Timer.h\"\n#include \"TimeStep.h\"\n#include \"Weather.h\"\n#include \"World.h\"\n#include \"Zones.h\"\n#include \"Timecycle.h\"\n#include \"Fluff.h\"\n\n#define BLOCK_COUNT 22\n#define SIZE_OF_SIMPLEVARS 0xE4\n\nconst uint32 SIZE_OF_ONE_GAME_IN_BYTES = 201729;\n\n#ifdef MISSION_REPLAY\nint8 IsQuickSave;\nconst int PAUSE_SAVE_SLOT = SLOT_COUNT;\n#endif\n\nchar DefaultPCSaveFileName[260];\nchar ValidSaveName[260];\nchar LoadFileName[256];\nwchar SlotFileName[SLOT_COUNT][260];\nwchar SlotSaveDate[SLOT_COUNT][70];\nint CheckSum;\neLevelName m_LevelToLoad;\nchar SaveFileNameJustSaved[260];\nint Slots[SLOT_COUNT];\n\nbool b_FoundRecentSavedGameWantToLoad;\nbool JustLoadedDontFadeInYet;\nbool StillToFadeOut;\nuint32 TimeStartedCountingForFade;\nuint32 TimeToStayFadedBeforeFadeOut = 1750;\n\nint32 RadioStationPosition[NUM_RADIOS];\n\nvoid\nInitRadioStationPositionList()\n{\n\tfor (int i = 0; i < NUM_RADIOS; i++)\n\t\tRadioStationPosition[i] = -1;\n}\n\nint32\nGetSavedRadioStationPosition(int32 station)\n{\n\treturn RadioStationPosition[station];\n}\n\nvoid\nPopulateRadioStationPositionList()\n{\n\tfor (int i = 0; i < NUM_RADIOS; i++)\n\t\tRadioStationPosition[i] = DMAudio.GetRadioPosition(i);\n}\n\n#define ReadDataFromBufferPointer(buf, to) memcpy(&to, buf, sizeof(to)); buf += align4bytes(sizeof(to));\n#define WriteDataToBufferPointer(buf, from) memcpy(buf, &from, sizeof(from)); buf += align4bytes(sizeof(from));\n\n#define LoadSaveDataBlock()\\\ndo {\\\n\tif (!ReadDataFromFile(file, (uint8 *) &size, 4))\\\n\t\treturn false;\\\n\tsize = align4bytes(size);\\\n\tif (!ReadDataFromFile(file, work_buff, size))\\\n\t\treturn false;\\\n\tbuf = work_buff;\\\n} while (0)\n\n#define ReadDataFromBlock(msg,load_func)\\\ndo {\\\n\tdebug(msg);\\\n\tReadDataFromBufferPointer(buf, size);\\\n\tload_func(buf, size);\\\n\tsize = align4bytes(size);\\\n\tbuf += size;\\\n} while (0)\n\n#define WriteSaveDataBlock(save_func, msg)\\\ndo {\\\n\tsize = 0;\\\n\tbuf = work_buff;\\\n\treserved = 0;\\\n\tMakeSpaceForSizeInBufferPointer(presize, buf, postsize);\\\n\tsave_func(buf, &size);\\\n\tdebug(msg\"== %i \\n\", size);\\\n\tCopySizeAndPreparePointer(presize, buf, postsize, reserved, size);\\\n\tif (!PcSaveHelper.PcClassSaveRoutine(file, work_buff, buf - work_buff))\\\n\t\treturn false;\\\n\ttotalSize += buf - work_buff;\\\n} while (0)\n\nbool\nGenericSave(int file)\n{\n\tuint8 *buf, *presize, *postsize;\n\tuint32 size;\n\tuint32 reserved;\n\n\tuint32 totalSize;\n\t\n\twchar *lastMissionPassed;\n\twchar suffix[6];\n\twchar saveName[24];\n\tSYSTEMTIME saveTime;\n\tCPad *currPad;\n\n\tCheckSum = 0;\n\tbuf = work_buff;\n\treserved = 0;\n\n\t// Save simple vars\n\tlastMissionPassed = TheText.Get(CStats::LastMissionPassedName[0] ? CStats::LastMissionPassedName : \"ITBEG\");\n\tAsciiToUnicode(\"...'\", suffix);\n\tsuffix[3] = L'\\0';\n#ifdef FIX_BUGS\n\t// fix buffer overflow\n\tint len = UnicodeStrlen(lastMissionPassed);\n\tif (len > ARRAY_SIZE(saveName)-1)\n\t\tlen = ARRAY_SIZE(saveName)-1;\n\tmemcpy(saveName, lastMissionPassed, sizeof(wchar) * len);\n#else\n\tTextCopy(saveName, lastMissionPassed);\n\tint len = UnicodeStrlen(saveName);\n#endif\n\tsaveName[len] = '\\0';\n\tif (len > ARRAY_SIZE(saveName)-2)\n\t\tTextCopy(&saveName[ARRAY_SIZE(saveName)-ARRAY_SIZE(suffix)], suffix);\n\tsaveName[ARRAY_SIZE(saveName)-1] = '\\0';\n\tWriteDataToBufferPointer(buf, saveName);\n\tGetLocalTime(&saveTime);\n\tWriteDataToBufferPointer(buf, saveTime);\n#ifdef MISSION_REPLAY\n\tint32 data = IsQuickSave << 24 | SIZE_OF_ONE_GAME_IN_BYTES;\n\tWriteDataToBufferPointer(buf, data);\n#else\n\tWriteDataToBufferPointer(buf, SIZE_OF_ONE_GAME_IN_BYTES);\n#endif\n\tWriteDataToBufferPointer(buf, CGame::currLevel);\n\tWriteDataToBufferPointer(buf, TheCamera.GetPosition().x);\n\tWriteDataToBufferPointer(buf, TheCamera.GetPosition().y);\n\tWriteDataToBufferPointer(buf, TheCamera.GetPosition().z);\n\tWriteDataToBufferPointer(buf, CClock::ms_nMillisecondsPerGameMinute);\n\tWriteDataToBufferPointer(buf, CClock::ms_nLastClockTick);\n\tWriteDataToBufferPointer(buf, CClock::ms_nGameClockHours);\n\tWriteDataToBufferPointer(buf, CClock::ms_nGameClockMinutes);\n\tcurrPad = CPad::GetPad(0);\n\tWriteDataToBufferPointer(buf, currPad->Mode);\n\tWriteDataToBufferPointer(buf, CTimer::m_snTimeInMilliseconds);\n\tWriteDataToBufferPointer(buf, CTimer::ms_fTimeScale);\n\tWriteDataToBufferPointer(buf, CTimer::ms_fTimeStep);\n\tWriteDataToBufferPointer(buf, CTimer::ms_fTimeStepNonClipped);\n\tWriteDataToBufferPointer(buf, CTimer::m_FrameCounter);\n\tWriteDataToBufferPointer(buf, CTimeStep::ms_fTimeStep);\n\tWriteDataToBufferPointer(buf, CTimeStep::ms_fFramesPerUpdate);\n\tWriteDataToBufferPointer(buf, CTimeStep::ms_fTimeScale);\n\tWriteDataToBufferPointer(buf, CWeather::OldWeatherType);\n\tWriteDataToBufferPointer(buf, CWeather::NewWeatherType);\n\tWriteDataToBufferPointer(buf, CWeather::ForcedWeatherType);\n\tWriteDataToBufferPointer(buf, CWeather::InterpolationValue);\n\tWriteDataToBufferPointer(buf, CWeather::WeatherTypeInList);\n#ifdef COMPATIBLE_SAVES\n\t// converted to float for compatibility with original format\n\t// TODO: maybe remove this? not really gonna break anything vital\n\tfloat f = TheCamera.CarZoomIndicator;\n\tWriteDataToBufferPointer(buf, f);\n\tf = TheCamera.PedZoomIndicator;\n\tWriteDataToBufferPointer(buf, f);\n#else\n\tWriteDataToBufferPointer(buf, TheCamera.CarZoomIndicator);\n\tWriteDataToBufferPointer(buf, TheCamera.PedZoomIndicator);\n#endif\n\tWriteDataToBufferPointer(buf, CGame::currArea);\n\tWriteDataToBufferPointer(buf, CVehicle::bAllTaxisHaveNitro);\n\tWriteDataToBufferPointer(buf, CPad::bInvertLook4Pad);\n\tWriteDataToBufferPointer(buf, CTimeCycle::m_ExtraColour);\n\tWriteDataToBufferPointer(buf, CTimeCycle::m_bExtraColourOn);\n\tWriteDataToBufferPointer(buf, CTimeCycle::m_ExtraColourInter);\n\tPopulateRadioStationPositionList();\n\tWriteDataToBufferPointer(buf, RadioStationPosition);\n\tassert(buf - work_buff == SIZE_OF_SIMPLEVARS);\n\n\t// Save scripts, block is nested within the same block as simple vars for some reason\n\tpresize = buf;\n\tbuf += 4;\n\tpostsize = buf;\n\tCTheScripts::SaveAllScripts(buf, &size);\n\tdebug(\"ScriptSize== %i \\n\", size);\n\tCopySizeAndPreparePointer(presize, buf, postsize, reserved, size);\n\tif (!PcSaveHelper.PcClassSaveRoutine(file, work_buff, buf - work_buff))\n\t\treturn false;\n\n\ttotalSize = buf - work_buff;\n\n\t// Save the rest\n\tWriteSaveDataBlock(CPools::SavePedPool, \"PedPoolSize\");\n\tWriteSaveDataBlock(CGarages::Save, \"GaragesSize\");\n\tWriteSaveDataBlock(CGameLogic::Save, \"GameLogicSize\");\n\tWriteSaveDataBlock(CPools::SaveVehiclePool, \"VehPoolSize\");\n\tWriteSaveDataBlock(CPools::SaveObjectPool, \"ObjectPoolSize\");\n\tWriteSaveDataBlock(ThePaths.Save, \"ThePathsSize\");\n\tWriteSaveDataBlock(CCranes::Save, \"CranesSize\");\n\tWriteSaveDataBlock(CPickups::Save, \"PickUpsSize\");\n\tWriteSaveDataBlock(gPhoneInfo.Save, \"PhoneInfoSize\");\n\tWriteSaveDataBlock(CRestart::SaveAllRestartPoints, \"RestartPointsBufferSize\");\n\tWriteSaveDataBlock(CRadar::SaveAllRadarBlips, \"RadarBlipsBufferSize\");\n\tWriteSaveDataBlock(CTheZones::SaveAllZones, \"AllZonesBufferSize\");\n\tWriteSaveDataBlock(CGangs::SaveAllGangData, \"AllGangDataSize\");\n\tWriteSaveDataBlock(CTheCarGenerators::SaveAllCarGenerators, \"AllCarGeneratorsSize\");\n\tWriteSaveDataBlock(CParticleObject::SaveParticle, \"ParticlesSize\");\n\tWriteSaveDataBlock(cAudioScriptObject::SaveAllAudioScriptObjects, \"AllAudioScriptObjectsSize\");\n\tWriteSaveDataBlock(CScriptPaths::Save, \"ScriptPathsSize\");\n\tWriteSaveDataBlock(CWorld::Players[CWorld::PlayerInFocus].SavePlayerInfo, \"PlayerInfoSize\");\n\tWriteSaveDataBlock(CStats::SaveStats, \"StatsSize\");\n\tWriteSaveDataBlock(CSetPieces::Save, \"SetPiecesSize\");\n\tWriteSaveDataBlock(CStreaming::MemoryCardSave, \"StreamingSize\");\n\tWriteSaveDataBlock(CPedType::Save, \"PedTypeSize\");\n\n\t// Write padding\n\tfor (int i = 0; i < 4; i++) {\n\t\tsize = align4bytes(SIZE_OF_ONE_GAME_IN_BYTES - totalSize - 4);\n\t\tif (size > sizeof(work_buff))\n\t\t\tsize = sizeof(work_buff);\n\t\tif (size > 4) {\n\t\t\tif (!PcSaveHelper.PcClassSaveRoutine(file, work_buff, size))\n\t\t\t\treturn false;\n\t\t\ttotalSize += size;\n\t\t}\n\t}\n\t\n\t// Write checksum and close\n\tCFileMgr::Write(file, (const char *) &CheckSum, sizeof(CheckSum));\n\tif (CFileMgr::GetErrorReadWrite(file)) {\n\t\tPcSaveHelper.nErrorCode = SAVESTATUS_ERR_SAVE_WRITE;\n\t\tif (!CloseFile(file))\n\t\t\tPcSaveHelper.nErrorCode = SAVESTATUS_ERR_SAVE_CLOSE;\n\n\t\treturn false;\n\t}\n\n\tCPad::FixPadsAfterSave();\t\n\treturn true;\n}\n\nbool\nGenericLoad()\n{\n\tuint8 *buf;\n\tint32 file;\n\tuint32 size;\n#ifdef MISSION_REPLAY\n\tint8 qs;\n#endif\n\n\tint32 saveSize;\n\tCPad *currPad;\n\n\t// Load SimpleVars and Scripts\n\tCheckSum = 0;\n\tCDate dummy; // unused\n\tCPad::ResetCheats();\n\tif (!ReadInSizeofSaveFileBuffer(file, size))\n\t\treturn false;\n\tsize = align4bytes(size);\n\tReadDataFromFile(file, work_buff, size);\n\tbuf = (work_buff + 0x40);\n\tReadDataFromBufferPointer(buf, saveSize);\n#ifdef MISSION_REPLAY // a hack to keep compatibility but get new data from save\n\tqs = saveSize >> 24;\n#endif\n\tReadDataFromBufferPointer(buf, CGame::currLevel);\n\tReadDataFromBufferPointer(buf, TheCamera.GetMatrix().GetPosition().x);\n\tReadDataFromBufferPointer(buf, TheCamera.GetMatrix().GetPosition().y);\n\tReadDataFromBufferPointer(buf, TheCamera.GetMatrix().GetPosition().z);\n\tReadDataFromBufferPointer(buf, CClock::ms_nMillisecondsPerGameMinute);\n\tReadDataFromBufferPointer(buf, CClock::ms_nLastClockTick);\n\tReadDataFromBufferPointer(buf, CClock::ms_nGameClockHours);\n\tReadDataFromBufferPointer(buf, CClock::ms_nGameClockMinutes);\n\tcurrPad = CPad::GetPad(0);\n\tReadDataFromBufferPointer(buf, currPad->Mode);\n\tReadDataFromBufferPointer(buf, CTimer::m_snTimeInMilliseconds);\n\tReadDataFromBufferPointer(buf, CTimer::ms_fTimeScale);\n\tReadDataFromBufferPointer(buf, CTimer::ms_fTimeStep);\n\tReadDataFromBufferPointer(buf, CTimer::ms_fTimeStepNonClipped);\n\tReadDataFromBufferPointer(buf, CTimer::m_FrameCounter);\n\tReadDataFromBufferPointer(buf, CTimeStep::ms_fTimeStep);\n\tReadDataFromBufferPointer(buf, CTimeStep::ms_fFramesPerUpdate);\n\tReadDataFromBufferPointer(buf, CTimeStep::ms_fTimeScale);\n\tReadDataFromBufferPointer(buf, CWeather::OldWeatherType);\n\tReadDataFromBufferPointer(buf, CWeather::NewWeatherType);\n\tReadDataFromBufferPointer(buf, CWeather::ForcedWeatherType);\n#ifdef SECUROM\n\tif (CTimer::m_FrameCounter > 72000){\n\t\tbuf += align4bytes(4);\n\t}\n#endif\n\tReadDataFromBufferPointer(buf, CWeather::InterpolationValue);\n\tReadDataFromBufferPointer(buf, CWeather::WeatherTypeInList);\n#ifdef COMPATIBLE_SAVES\n\t// converted to float for compatibility with original format\n\t// TODO: maybe remove this? not really gonna break anything vital\n\tfloat f;\n\tReadDataFromBufferPointer(buf, f);\n\tTheCamera.CarZoomIndicator = f;\n\tReadDataFromBufferPointer(buf, f);\n\tTheCamera.PedZoomIndicator = f;\n#else\n\tReadDataFromBufferPointer(buf, TheCamera.CarZoomIndicator);\n\tReadDataFromBufferPointer(buf, TheCamera.PedZoomIndicator);\n#endif\n\tReadDataFromBufferPointer(buf, CGame::currArea);\n\tReadDataFromBufferPointer(buf, CVehicle::bAllTaxisHaveNitro);\n#ifdef LOAD_INI_SETTINGS\n\tbuf += align4bytes(sizeof(CPad::bInvertLook4Pad));\n#else\n\tReadDataFromBufferPointer(buf, CPad::bInvertLook4Pad);\n#endif\n\tReadDataFromBufferPointer(buf, CTimeCycle::m_ExtraColour);\n\tReadDataFromBufferPointer(buf, CTimeCycle::m_bExtraColourOn);\n\tReadDataFromBufferPointer(buf, CTimeCycle::m_ExtraColourInter);\n\tReadDataFromBufferPointer(buf, RadioStationPosition);\n\tassert(buf - work_buff == SIZE_OF_SIMPLEVARS);\n#ifdef MISSION_REPLAY\n\tWaitForSave = 0;\n\tif (FrontEndMenuManager.m_nCurrSaveSlot == PAUSE_SAVE_SLOT && qs == 3)\n\t\tWaitForMissionActivate = CTimer::GetTimeInMilliseconds() + 2000;\n#endif\n\tReadDataFromBlock(\"Loading Scripts \\n\", CTheScripts::LoadAllScripts);\n\n\t// Load the rest\n\tLoadSaveDataBlock();\n\tReadDataFromBlock(\"Loading PedPool \\n\", CPools::LoadPedPool);\n\tLoadSaveDataBlock();\n\tReadDataFromBlock(\"Loading Garages \\n\", CGarages::Load);\n\tLoadSaveDataBlock();\n\tReadDataFromBlock(\"Loading GameLogic \\n\", CGameLogic::Load);\n\tLoadSaveDataBlock();\n\tReadDataFromBlock(\"Loading Vehicles \\n\", CPools::LoadVehiclePool);\n\tLoadSaveDataBlock();\n\tCProjectileInfo::RemoveAllProjectiles();\n\tCObject::DeleteAllTempObjects();\n\tReadDataFromBlock(\"Loading Objects \\n\", CPools::LoadObjectPool);\n\tLoadSaveDataBlock();\n\tReadDataFromBlock(\"Loading Paths \\n\", ThePaths.Load);\n\tLoadSaveDataBlock();\n\tReadDataFromBlock(\"Loading Cranes \\n\", CCranes::Load);\n\tLoadSaveDataBlock();\n\tReadDataFromBlock(\"Loading Pickups \\n\", CPickups::Load);\n\tLoadSaveDataBlock();\n\tReadDataFromBlock(\"Loading Phoneinfo \\n\", gPhoneInfo.Load);\n\tLoadSaveDataBlock();\n\tReadDataFromBlock(\"Loading Restart \\n\", CRestart::LoadAllRestartPoints);\n\tLoadSaveDataBlock();\n\tReadDataFromBlock(\"Loading Radar Blips \\n\", CRadar::LoadAllRadarBlips);\n\tLoadSaveDataBlock();\n\tReadDataFromBlock(\"Loading Zones \\n\", CTheZones::LoadAllZones);\n\tLoadSaveDataBlock();\n\tReadDataFromBlock(\"Loading Gang Data \\n\", CGangs::LoadAllGangData);\n\tLoadSaveDataBlock();\n\tReadDataFromBlock(\"Loading Car Generators \\n\", CTheCarGenerators::LoadAllCarGenerators);\n\tCParticle::ReloadConfig();\n\tLoadSaveDataBlock();\n\tReadDataFromBlock(\"Loading Particles \\n\", CParticleObject::LoadParticle);\n\tLoadSaveDataBlock();\n\tReadDataFromBlock(\"Loading AudioScript Objects \\n\", cAudioScriptObject::LoadAllAudioScriptObjects);\n\tLoadSaveDataBlock();\n\tReadDataFromBlock(\"Loading ScriptPaths \\n\", CScriptPaths::Load);\n\tLoadSaveDataBlock();\n\tReadDataFromBlock(\"Loading Player Info \\n\", CWorld::Players[CWorld::PlayerInFocus].LoadPlayerInfo);\n\tLoadSaveDataBlock();\n\tReadDataFromBlock(\"Loading Stats \\n\", CStats::LoadStats);\n\tLoadSaveDataBlock();\n\tReadDataFromBlock(\"Loading Set Pieces \\n\", CSetPieces::Load);\n\tLoadSaveDataBlock();\n\tReadDataFromBlock(\"Loading Streaming Stuff \\n\", CStreaming::MemoryCardLoad);\n\tLoadSaveDataBlock();\n\tReadDataFromBlock(\"Loading PedType Stuff \\n\", CPedType::Load);\n\n\tDMAudio.SetMusicMasterVolume(FrontEndMenuManager.m_PrefsMusicVolume);\n\tDMAudio.SetEffectsMasterVolume(FrontEndMenuManager.m_PrefsSfxVolume);\n\tif (!CloseFile(file)) {\n\t\tPcSaveHelper.nErrorCode = SAVESTATUS_ERR_LOAD_CLOSE;\n\t\treturn false;\n\t}\n\n\tDoGameSpecificStuffAfterSucessLoad();\n\tdebug(\"Game successfully loaded \\n\");\n\treturn true;\n}\n\nbool\nReadInSizeofSaveFileBuffer(int32 &file, uint32 &size)\n{\n\tfile = CFileMgr::OpenFile(LoadFileName, \"rb\");\n\tif (file == 0) {\n\t\tPcSaveHelper.nErrorCode = SAVESTATUS_ERR_LOAD_OPEN;\n\t\treturn false;\n\t}\n\tCFileMgr::Read(file, (const char*)&size, sizeof(size));\n\tif (CFileMgr::GetErrorReadWrite(file)) {\n\t\tPcSaveHelper.nErrorCode = SAVESTATUS_ERR_LOAD_READ;\n\t\tif (!CloseFile(file))\n\t\t\tPcSaveHelper.nErrorCode = SAVESTATUS_ERR_LOAD_CLOSE;\n\t\treturn false;\n\t}\n\treturn true;\n}\n\nbool\nReadDataFromFile(int32 file, uint8 *buf, uint32 size)\n{\n\tif (file == 0) {\n\t\tPcSaveHelper.nErrorCode = SAVESTATUS_ERR_LOAD_OPEN;\n\t\treturn false;\n\t}\n\tsize_t read_size = CFileMgr::Read(file, (const char*)buf, size);\n\tif (CFileMgr::GetErrorReadWrite(file) || read_size != size) {\n\t\tPcSaveHelper.nErrorCode = SAVESTATUS_ERR_LOAD_READ;\n\t\tif (!CloseFile(file))\n\t\t\tPcSaveHelper.nErrorCode = SAVESTATUS_ERR_LOAD_CLOSE;\n\t\treturn false;\n\t}\n\treturn true;\n}\n\nbool\nCloseFile(int32 file)\n{\n\treturn CFileMgr::CloseFile(file) == 0;\n}\n\nvoid\nDoGameSpecificStuffAfterSucessLoad()\n{\n\tCCollision::SortOutCollisionAfterLoad();\n\tCStreaming::LoadSceneCollision(TheCamera.GetPosition());\n\tCStreaming::LoadScene(TheCamera.GetPosition());\n\tCGame::TidyUpMemory(true, false);\n\tStillToFadeOut = true;\n\tJustLoadedDontFadeInYet = true;\n\tTheCamera.Fade(0.0f, 0);\n\tCTheScripts::Process();\n}\n\nbool\nCheckSlotDataValid(int32 slot)\n{\n\tPcSaveHelper.nErrorCode = SAVESTATUS_SUCCESSFUL;\n\tif (CheckDataNotCorrupt(slot, LoadFileName)) {\n\t\tCStreaming::DeleteAllRwObjects();\n\t\treturn true;\n\t}\n\n\tPcSaveHelper.nErrorCode = SAVESTATUS_ERR_DATA_INVALID;\n\treturn false;\n}\n\nvoid\nMakeSpaceForSizeInBufferPointer(uint8 *&presize, uint8 *&buf, uint8 *&postsize)\n{\n\tpresize = buf;\n\tbuf += sizeof(uint32);\n\tpostsize = buf;\n}\n\nvoid\nCopySizeAndPreparePointer(uint8 *&buf, uint8 *&postbuf, uint8 *&postbuf2, uint32 &unused, uint32 &size)\n{\n\tmemcpy(buf, &size, sizeof(size));\n\tsize = align4bytes(size);\n\tpostbuf2 += size;\n\tpostbuf = postbuf2;\n}\n\nvoid\nDoGameSpecificStuffBeforeSave()\n{\n\tCGameLogic::PassTime(360);\n\tCPlayerPed *ped = FindPlayerPed();\n\tped->m_fCurrentStamina = ped->m_fMaxStamina;\n\tCGame::TidyUpMemory(true, false);\n}\n\n\nvoid\nMakeValidSaveName(int32 slot)\n{\n\tValidSaveName[0] = '\\0';\n\tsprintf(ValidSaveName, \"%s%i\", DefaultPCSaveFileName, slot + 1);\n\tstrncat(ValidSaveName, \".b\", 5);\n}\n\nwchar *\nGetSavedGameDateAndTime(int32 slot)\n{\n\treturn SlotSaveDate[slot];\n}\n\nwchar *\nGetNameOfSavedGame(int32 slot)\n{\n\treturn SlotFileName[slot];\n}\n\nbool\nCheckDataNotCorrupt(int32 slot, char *name)\n{\n\tchar filename[100];\n\n\tint32 blocknum = 0;\n\teLevelName level = LEVEL_GENERIC;\n\tCheckSum = 0;\n\tuint32 bytes_processed = 0;\n\tsprintf(filename, \"%s%i%s\", DefaultPCSaveFileName, slot + 1, \".b\");\n\tint file = CFileMgr::OpenFile(filename, \"rb\");\n\tif (file == 0)\n\t\treturn false;\n\tstrcpy(name, filename);\n\twhile (SIZE_OF_ONE_GAME_IN_BYTES - sizeof(uint32) > bytes_processed && blocknum < 40) {\n\t\tint32 blocksize;\n\t\tif (!ReadDataFromFile(file, (uint8*)&blocksize, sizeof(blocksize))) {\n\t\t\tCloseFile(file);\n\t\t\treturn false;\n\t\t}\n\t\tif (blocksize > align4bytes(sizeof(work_buff)))\n\t\t\tblocksize = sizeof(work_buff) - sizeof(uint32);\n\t\tif (!ReadDataFromFile(file, work_buff, align4bytes(blocksize))) {\n\t\t\tCloseFile(file);\n\t\t\treturn false;\n\t\t}\n\n\t\tCheckSum += ((uint8*)&blocksize)[0];\n\t\tCheckSum += ((uint8*)&blocksize)[1];\n\t\tCheckSum += ((uint8*)&blocksize)[2];\n\t\tCheckSum += ((uint8*)&blocksize)[3];\n\t\tuint8 *_work_buf = work_buff;\n\t\tfor (int i = 0; i < align4bytes(blocksize); i++) {\n\t\t\tCheckSum += *_work_buf++;\n\t\t\tbytes_processed++;\n\t\t}\n\n\t\tif (blocknum == 0)\n\t\t\tmemcpy(&level, work_buff+4, sizeof(level));\n\t\tblocknum++;\n\t}\n\tint32 _checkSum;\n\tif (ReadDataFromFile(file, (uint8*)&_checkSum, sizeof(_checkSum))) {\n\t\tif (CloseFile(file)) {\n\t\t\tif (CheckSum == _checkSum) {\n\t\t\t\tm_LevelToLoad = level;\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\treturn false;\n\t\t}\n\t\treturn false;\n\t}\n\n\tCloseFile(file);\n\treturn false;\n}\n\nbool\nRestoreForStartLoad()\n{\n\tuint8 buf[999];\n\n\tint file = CFileMgr::OpenFile(LoadFileName, \"rb\");\n\tif (file == 0) {\n\t\tPcSaveHelper.nErrorCode = SAVESTATUS_ERR_LOAD_OPEN;\n\t\treturn false;\n\t}\n\tReadDataFromFile(file, buf, sizeof(buf));\n\tif (CFileMgr::GetErrorReadWrite(file)) {\n\t\tPcSaveHelper.nErrorCode = SAVESTATUS_ERR_LOAD_READ;\n\t\tif (!CloseFile(file))\n\t\t\tPcSaveHelper.nErrorCode = SAVESTATUS_ERR_LOAD_CLOSE;\n\t\treturn false;\n\t} else {\n\t\tuint8 *_buf = buf + sizeof(int32) + sizeof(wchar[24]) + sizeof(SYSTEMTIME) + sizeof(SIZE_OF_ONE_GAME_IN_BYTES);\n\t\tReadDataFromBufferPointer(_buf, CGame::currLevel);\n\t\tReadDataFromBufferPointer(_buf, TheCamera.GetMatrix().GetPosition().x);\n\t\tReadDataFromBufferPointer(_buf, TheCamera.GetMatrix().GetPosition().y);\n\t\tReadDataFromBufferPointer(_buf, TheCamera.GetMatrix().GetPosition().z);\n\t\tCStreaming::RemoveUnusedBigBuildings(CGame::currLevel);\n\t\tCStreaming::RemoveUnusedBuildings(CGame::currLevel);\n\n\t\tif (CloseFile(file)) {\n\t\t\treturn true;\n\t\t} else {\n\t\t\tPcSaveHelper.nErrorCode = SAVESTATUS_ERR_LOAD_CLOSE;\n\t\t\treturn false;\n\t\t}\n\t}\n}\n\nint\nalign4bytes(int32 size)\n{\n\treturn (size + 3) & 0xFFFFFFFC;\n}\n\n#ifdef MISSION_REPLAY\n\nvoid DisplaySaveResult(int unk, char* name)\n{}\n\nbool SaveGameForPause(int type)\n{\n\tif (AllowMissionReplay != 0 || type != 3 && WaitForSave > CTimer::GetTimeInMilliseconds())\n\t\treturn false;\n\tWaitForSave = 0;\n\tif (gGameState != GS_PLAYING_GAME || CTheScripts::IsPlayerOnAMission() || CStats::LastMissionPassedName[0] == '\\0') {\n\t\tDisplaySaveResult(3, CStats::LastMissionPassedName);\n\t\treturn false;\n\t}\n\tIsQuickSave = type;\n\tMissionStartTime = 0;\n\tint res = PcSaveHelper.SaveSlot(PAUSE_SAVE_SLOT);\n\tPcSaveHelper.PopulateSlotInfo();\n\tIsQuickSave = 0;\n\tDisplaySaveResult(res, CStats::LastMissionPassedName);\n\treturn true;\n}\n#endif\n"
  },
  {
    "path": "src/save/GenericGameStorage.h",
    "content": "#pragma once\n\n#include \"Game.h\"\n#include \"PCSave.h\"\n\n#define SLOT_COUNT (8)\n\nvoid InitRadioStationPositionList();\nint32 GetSavedRadioStationPosition(int32 station);\nvoid PopulateRadioStationPositionList();\nbool GenericSave(int file);\nbool GenericLoad();\nbool ReadInSizeofSaveFileBuffer(int32 &file, uint32 &size);\nbool ReadDataFromFile(int32 file, uint8 *buf, uint32 size);\nbool CloseFile(int32 file);\nvoid DoGameSpecificStuffAfterSucessLoad();\nbool CheckSlotDataValid(int32 slot);\nvoid MakeSpaceForSizeInBufferPointer(uint8 *&presize, uint8 *&buf, uint8 *&postsize);\nvoid CopySizeAndPreparePointer(uint8 *&buf, uint8 *&postbuf, uint8 *&postbuf2, uint32 &unused, uint32 &size);\nvoid DoGameSpecificStuffBeforeSave();\nvoid MakeValidSaveName(int32 slot);\nwchar *GetSavedGameDateAndTime(int32 slot);\nwchar *GetNameOfSavedGame(int32 slot);\nbool CheckDataNotCorrupt(int32 slot, char *name);\nbool RestoreForStartLoad();\nint align4bytes(int32 size);\n\nextern char DefaultPCSaveFileName[260];\nextern char ValidSaveName[260];\nextern char LoadFileName[256];\nextern wchar SlotFileName[SLOT_COUNT][260];\nextern wchar SlotSaveDate[SLOT_COUNT][70];\nextern int CheckSum;\nextern enum eLevelName m_LevelToLoad;\nextern int Slots[SLOT_COUNT];\n\nextern bool b_FoundRecentSavedGameWantToLoad;\nextern bool JustLoadedDontFadeInYet;\nextern bool StillToFadeOut;\nextern uint32 TimeStartedCountingForFade;\nextern uint32 TimeToStayFadedBeforeFadeOut;\n\nextern char SaveFileNameJustSaved[260]; // 8F2570\n\nconst char TopLineEmptyFile[] = \"THIS FILE IS NOT VALID YET\";\n\n#ifdef MISSION_REPLAY\nextern int8 IsQuickSave; // originally int\n\nbool SaveGameForPause(int);\n#endif\n"
  },
  {
    "path": "src/save/MemoryCard.cpp",
    "content": "#define WITHWINDOWS\n#include \"common.h\"\n#ifdef PS2_MENU\n#include \"crossplatform.h\"\n#include \"MemoryCard.h\"\n#include \"main.h\"\n#include \"DMAudio.h\"\n#include \"AudioScriptObject.h\"\n#include \"Camera.h\"\n#include \"CarGen.h\"\n#include \"Cranes.h\"\n#include \"Clock.h\"\n#include \"MBlur.h\"\n#include \"Date.h\"\n#include \"Font.h\"\n#include \"FileMgr.h\"\n#include \"Game.h\"\n#include \"GameLogic.h\"\n#include \"Gangs.h\"\n#include \"Garages.h\"\n#include \"GenericGameStorage.h\"\n#include \"Pad.h\"\n#include \"Particle.h\"\n#include \"ParticleObject.h\"\n#include \"PathFind.h\"\n#include \"PCSave.h\"\n#include \"Phones.h\"\n#include \"Pickups.h\"\n#include \"PlayerPed.h\"\n#include \"ProjectileInfo.h\"\n#include \"Pools.h\"\n#include \"Radar.h\"\n#include \"Restart.h\"\n#include \"Script.h\"\n#include \"Stats.h\"\n#include \"Streaming.h\"\n#include \"Sprite2d.h\"\n#include \"Timer.h\"\n#include \"TimeStep.h\"\n#include \"Weather.h\"\n#include \"World.h\"\n#include \"Zones.h\"\n#include \"Frontend_PS2.h\"\n\nCMemoryCard TheMemoryCard;\n\nchar icon_one[16] = \"slime1.ico\";\nchar icon_two[16] = \"slime2.ico\";\nchar icon_three[16] = \"slime3.ico\";\nchar HostFileLocationOfIcons[64] = \"icons\\\\\";\nchar TheGameRootDirectory[64] = \"/BESLES-50330GTA30000\";\n\n#define ReadDataFromBufferPointer(buf, to) memcpy(&to, buf, sizeof(to)); buf += align4bytes(sizeof(to));\n#define WriteDataToBufferPointer(buf, from) memcpy(buf, &from, sizeof(from)); buf += align4bytes(sizeof(from));\n\t\nstatic int\nalign4bytes(int32 size)\n{\n\treturn (size + 3) & 0xFFFFFFFC;\n}\n\nunsigned short ascii_table[3][2] =\n{\n\t{ 0x824F, 0x30 }, /* 0-9  */\n\t{ 0x8260, 0x41 }, /* A-Z  */\n\t{ 0x8281, 0x61 }, /* a-z  */\n};\n\nunsigned short ascii_special[33][2] =\n{\n\t{0x8140, 0x20}, /* \" \" */\n\t{0x8149, 0x21}, /* \"!\" */\n\t{0x8168, 0x22}, /* \"\"\" */\n\t{0x8194, 0x23}, /* \"#\" */\n\t{0x8190, 0x24}, /* \"$\" */\n\t{0x8193, 0x25}, /* \"%\" */\n\t{0x8195, 0x26}, /* \"&\" */\n\t{0x8166, 0x27}, /* \"'\" */\n\t{0x8169, 0x28}, /* \"(\" */\n\t{0x816A, 0x29}, /* \")\" */\n\t{0x8196, 0x2A}, /* \"*\" */\n\t{0x817B, 0x2B}, /* \"+\" */\n\t{0x8143, 0x2C}, /* \",\" */\n\t{0x817C, 0x2D}, /* \"-\" */\n\t{0x8144, 0x2E}, /* \".\" */\n\t{0x815E, 0x2F}, /* \"/\" */\n\t{0x8146, 0x3A}, /* \":\" */\n\t{0x8147, 0x3B}, /* \";\" */\n\t{0x8171, 0x3C}, /* \"<\" */\n\t{0x8181, 0x3D}, /* \"=\" */\n\t{0x8172, 0x3E}, /* \">\" */\n\t{0x8148, 0x3F}, /* \"?\" */\n\t{0x8197, 0x40}, /* \"@\" */\n\t{0x816D, 0x5B}, /* \"[\" */\n\t{0x818F, 0x5C}, /* \"\\\" */\n\t{0x816E, 0x5D}, /* \"]\" */\n\t{0x814F, 0x5E}, /* \"^\" */\n\t{0x8151, 0x5F}, /* \"_\" */\n\t{0x8165, 0x60}, /* \"`\" */\n\t{0x816F, 0x7B}, /* \"{\" */\n\t{0x8162, 0x7C}, /* \"|\" */\n\t{0x8170, 0x7D}, /* \"}\" */\n\t{0x8150, 0x7E}, /* \"~\" */\n};\n\nunsigned short\nAscii2Sjis(unsigned char ascii_code)\n{\n\tunsigned short sjis_code = 0; \n\tunsigned char stmp; \n\tunsigned char stmp2 = 0; \n\n\tif ((ascii_code >= 0x20) && (ascii_code <= 0x2f)) \n\t\tstmp2 = 1; \n\telse \n\tif ((ascii_code >= 0x30) && (ascii_code <= 0x39)) \n\t\tstmp = 0; \n\telse \n\tif ((ascii_code >= 0x3a) && (ascii_code <= 0x40)) \n\t\tstmp2 = 11; \n\telse \n\tif ((ascii_code >= 0x41) && (ascii_code <= 0x5a)) \n\t\tstmp = 1; \n\telse \n\tif ((ascii_code >= 0x5b) && (ascii_code <= 0x60)) \n\t\tstmp2 = 37; \n\telse \n\tif ((ascii_code >= 0x61) && (ascii_code <= 0x7a)) \n\t\tstmp = 2; \n\telse \n\tif ((ascii_code >= 0x7b) && (ascii_code <= 0x7e)) \n\t\tstmp2 = 63; \n\telse { \n\t\tprintf(\"bad ASCII code 0x%x\\n\", ascii_code); \n\t\treturn(0); \n\t} \n \n\tif (stmp2) \n\t\tsjis_code = ascii_special[ascii_code - 0x20 - (stmp2 - 1)][0]; \n\telse \n\t\tsjis_code = ascii_table[stmp][0] + ascii_code - ascii_table[stmp][1]; \n \n\treturn(sjis_code);\n}\n\n#if defined(GTA_PC)\n\nextern \"C\"\n{\n\textern void HandleExit();\n}\n\t\t\t\nchar CardCurDir[MAX_CARDS][260] = { \"\", \"\" };\nchar PCCardsPath[260];\nchar PCCardDir[MAX_CARDS][12] = { \"memcard1\", \"memcard2\" };\n\nconst char* _psGetUserFilesFolder();\nvoid _psCreateFolder(LPCSTR path);\n\nvoid\nPCMCInit()\n{\n\tsprintf(PCCardsPath, \"%s\", _psGetUserFilesFolder());\n\t\n\tchar path[512];\n\t\n\tsprintf(path, \"%s\\\\%s\", PCCardsPath, PCCardDir[CARD_ONE]);\n\t_psCreateFolder(path);\n\t\n\tsprintf(path, \"%s\\\\%s\", PCCardsPath, PCCardDir[CARD_TWO]);\n\t_psCreateFolder(path);\n}\n#endif\n\nCMemoryCardInfo::CMemoryCardInfo(void)\n{\n\ttype = 0;\n\tfree = 0;\n\tformat = 0;\n\t\n\tfor ( int32 i = 0; i < sizeof(dir); i++ )\n\t\tdir[i] = '\\0';\n\t\n\tstrncpy(dir, TheGameRootDirectory, sizeof(dir) - 1);\n}\n\nint32\nCMemoryCard::Init(void)\n{\n#if defined(PS2)\n\tif ( sceMcInit() == sceMcIniSucceed )\n\t{\n\t\tprintf(\"Memory card initialsed\\n\");\n\t\treturn RES_SUCCESS;\n\t}\n\t\n\tprintf(\"Memory Card not being initialised\\n\");\n\treturn RES_FAILED;\n#else\n\tPCMCInit();\n\tprintf(\"Memory card initialsed\\n\");\n\treturn RES_SUCCESS;\n#endif\n}\n\nCMemoryCard::CMemoryCard(void)\n{\n\t_unk0 = 0;\n\tCurrentCard = CARD_ONE;\n\tCards[CARD_ONE].port = 0;\n\tCards[CARD_TWO].port = 1;\n\t\n\tfor ( int32 i = 0; i < sizeof(_unkName3); i++ )\n\t\t_unkName3[i] = '\\0';\n\t\n\tm_bWantToLoad = false;\n\t_bunk2 = false;\n\t_bunk7 = false;\n\tJustLoadedDontFadeInYet = false;\n\tStillToFadeOut = false;\n\tTimeStartedCountingForFade = 0;\n\tTimeToStayFadedBeforeFadeOut = 1750;\n\tb_FoundRecentSavedGameWantToLoad = false;\n\t\n\tchar date[64];\n\tchar time[64];\n\tchar day[8];\n\tchar month[8];\n\tchar year[8];\n\tchar hour[8];\n\tchar minute[8];\n\tchar second[8];\n\t\n\tstrncpy(date, \"Oct  7 2001\", 62);\n\tstrncpy(time, \"15:48:32\",    62);\n\t\n\tstrncpy(month, date, 3);\n\tmonth[3] = '\\0';\n\t\n\tstrncpy(day, &date[4], 2);\n\tday[2] = '\\0';\n\t\n\tstrncpy(year, &date[7], 4);\n\tyear[4] = '\\0';\n\t\n\tstrncpy(hour, time, 2);\n\thour[2] = '\\0';\n\t\n\tstrncpy(minute, &time[3], 2);\n\tminute[2] = '\\0';\n\t\n\tstrncpy(second, &time[6], 2);\n\tsecond[2] = '\\0';\n\t\n\t\n\t#define _CMP(m) strncmp(month, m, sizeof(m)-1)\n\t\n\tif ( !_CMP(\"Jan\") ) CompileDateAndTime.m_nMonth = 1;\n\telse\n\tif ( !_CMP(\"Feb\") ) CompileDateAndTime.m_nMonth = 2;\n\telse\n\tif ( !_CMP(\"Mar\") ) CompileDateAndTime.m_nMonth = 3;\n\telse\n\tif ( !_CMP(\"Apr\") ) CompileDateAndTime.m_nMonth = 4;\n\telse\n\tif ( !_CMP(\"May\") ) CompileDateAndTime.m_nMonth = 5;\n\telse\n\tif ( !_CMP(\"Jun\") ) CompileDateAndTime.m_nMonth = 6;\n\telse\n\tif ( !_CMP(\"Jul\") ) CompileDateAndTime.m_nMonth = 7;\n\telse\n\tif ( !_CMP(\"Aug\") ) CompileDateAndTime.m_nMonth = 8;\n\telse\n\tif ( !_CMP(\"Oct\") ) CompileDateAndTime.m_nMonth = 9;  // BUG: oct and sep is swapped here\n\telse\n\tif ( !_CMP(\"Sep\") ) CompileDateAndTime.m_nMonth = 10;\n\telse\n\tif ( !_CMP(\"Nov\") ) CompileDateAndTime.m_nMonth = 11;\n\telse\n\tif ( !_CMP(\"Dec\") ) CompileDateAndTime.m_nMonth = 12;\n\t\n\t#undef _CMP\n\t\n\tCompileDateAndTime.m_nDay    = atoi(day);\n\tCompileDateAndTime.m_nYear   = atoi(year);\n\tCompileDateAndTime.m_nHour   = atoi(hour);\n\tCompileDateAndTime.m_nMinute = atoi(minute);\n\tCompileDateAndTime.m_nSecond = atoi(second);\n}\n\nint32\nCMemoryCard::RestoreForStartLoad(void)\n{\n\tuint8 buf[30];\n\t\n\tint32 file = OpenMemCardFileForReading(CurrentCard, LoadFileName);\n\tif ( nError != NO_ERR_SUCCESS )\n\t\treturn RES_FAILED;\n\t\n\tReadFromMemCard(file, buf, sizeof(buf) - 1);\n\tif ( nError != NO_ERR_SUCCESS )\n\t\treturn RES_FAILED;\n\t\n\tuint8 *pBuf = buf + sizeof(uint32) + sizeof(uint32);\n\tReadDataFromBufferPointer(pBuf, CGame::currLevel);\n\tReadDataFromBufferPointer(pBuf, TheCamera.GetMatrix().GetPosition().x);\n\tReadDataFromBufferPointer(pBuf, TheCamera.GetMatrix().GetPosition().y);\n\tReadDataFromBufferPointer(pBuf, TheCamera.GetMatrix().GetPosition().z);\n\t\n\tif ( CGame::currLevel != LEVEL_INDUSTRIAL )\n\t\tCStreaming::RemoveBigBuildings(LEVEL_INDUSTRIAL);\n\t\n\tif ( CGame::currLevel != LEVEL_COMMERCIAL )\n\t\tCStreaming::RemoveBigBuildings(LEVEL_COMMERCIAL);\n\t\n\tif ( CGame::currLevel != LEVEL_SUBURBAN )\n\t\tCStreaming::RemoveBigBuildings(LEVEL_SUBURBAN);\n\t\n\tCStreaming::RemoveIslandsNotUsed(CGame::currLevel);\n\tCCollision::SortOutCollisionAfterLoad();\n\tCStreaming::RequestBigBuildings(CGame::currLevel);\n\tCStreaming::LoadAllRequestedModels(false);\n\tCStreaming::HaveAllBigBuildingsLoaded(CGame::currLevel);\n\tCGame::TidyUpMemory(true, false);\n\t\n\tCloseMemCardFile(file);\n\t\n\tif ( nError != NO_ERR_SUCCESS )\n\t\treturn RES_FAILED;\n\t\n\treturn RES_SUCCESS;\n}\n\nint32\nCMemoryCard::LoadSavedGame(void)\n{\n\tCheckSum = 0;\n\tCDate date;\n\t\n\tint32 saveSize = 0;\n\tuint32 size = 0;\n\t\n\tint32 oldLang = CMenuManager::m_PrefsLanguage;\n\t\n\tCPad::ResetCheats();\n\t\n\tChangeDirectory(CurrentCard, Cards[CurrentCard].dir);\n\t\n\tif ( nError != NO_ERR_SUCCESS )\n\t\treturn RES_FAILED;\n\t\n\tint32 file = OpenMemCardFileForReading(CurrentCard, LoadFileName);\n\t\n\tif ( nError != NO_ERR_SUCCESS )\n\t\treturn RES_FAILED;\n\t\n\t\n\t#define LoadSaveDataBlock()\\\n\t\tdo {\\\n\t\t\tReadFromMemCard(file, &size, sizeof(size)); \\\n\t\t\tif ( nError != NO_ERR_SUCCESS ) return RES_FAILED; \\\n\t\t\tsize = align4bytes(size); \\\n\t\t\tReadFromMemCard(file, work_buff, size); \\\n\t\t\tif ( nError != NO_ERR_SUCCESS ) return RES_FAILED; \\\n\t\t\tbuf = work_buff; \\\n\t\t} while (0)\n\t\n\tuint8 *buf;\n\t\n\tLoadSaveDataBlock();\n\t\n\tReadDataFromBufferPointer(buf, saveSize);\n\tReadDataFromBufferPointer(buf, CGame::currLevel);\n\tReadDataFromBufferPointer(buf, TheCamera.GetMatrix().GetPosition().x);\n\tReadDataFromBufferPointer(buf, TheCamera.GetMatrix().GetPosition().y);\n\tReadDataFromBufferPointer(buf, TheCamera.GetMatrix().GetPosition().z);\n\tReadDataFromBufferPointer(buf, CClock::ms_nMillisecondsPerGameMinute);\n\tReadDataFromBufferPointer(buf, CClock::ms_nLastClockTick);\n\tReadDataFromBufferPointer(buf, CClock::ms_nGameClockHours);\n\tReadDataFromBufferPointer(buf, CClock::ms_nGameClockMinutes);\n\tReadDataFromBufferPointer(buf, CPad::GetPad(0)->Mode);\n\tReadDataFromBufferPointer(buf, CTimer::m_snTimeInMilliseconds);\n\tReadDataFromBufferPointer(buf, CTimer::ms_fTimeScale);\n\tReadDataFromBufferPointer(buf, CTimer::ms_fTimeStep);\n\tReadDataFromBufferPointer(buf, CTimer::ms_fTimeStepNonClipped);\n\tReadDataFromBufferPointer(buf, CTimer::m_FrameCounter);\n\tReadDataFromBufferPointer(buf, CTimeStep::ms_fTimeStep);\n\tReadDataFromBufferPointer(buf, CTimeStep::ms_fFramesPerUpdate);\n\tReadDataFromBufferPointer(buf, CTimeStep::ms_fTimeScale);\n\tReadDataFromBufferPointer(buf, CWeather::OldWeatherType);\n\tReadDataFromBufferPointer(buf, CWeather::NewWeatherType);\n\tReadDataFromBufferPointer(buf, CWeather::ForcedWeatherType);\n\tReadDataFromBufferPointer(buf, CWeather::InterpolationValue);\n\tReadDataFromBufferPointer(buf, CMenuManager::m_PrefsMusicVolume);\n\tReadDataFromBufferPointer(buf, CMenuManager::m_PrefsSfxVolume);\n\tReadDataFromBufferPointer(buf, CMenuManager::m_PrefsControllerConfig);\n\tReadDataFromBufferPointer(buf, CMenuManager::m_PrefsUseVibration);\n\tReadDataFromBufferPointer(buf, CMenuManager::m_PrefsStereoMono);\n\tReadDataFromBufferPointer(buf, CMenuManager::m_PrefsRadioStation);\n\tReadDataFromBufferPointer(buf, CMenuManager::m_PrefsBrightness);\n\tReadDataFromBufferPointer(buf, CMenuManager::m_PrefsShowTrails);\n\tReadDataFromBufferPointer(buf, CMenuManager::m_PrefsShowSubtitles);\n\tReadDataFromBufferPointer(buf, CMenuManager::m_PrefsLanguage);\n\tReadDataFromBufferPointer(buf, CMenuManager::m_PrefsUseWideScreen);\n\tReadDataFromBufferPointer(buf, CPad::GetPad(0)->Mode);\n#ifdef PS2\n\tReadDataFromBufferPointer(buf, BlurOn);\n#else\n\tReadDataFromBufferPointer(buf, CMBlur::BlurOn);\n#endif\n\tReadDataFromBufferPointer(buf, date.m_nSecond);\n\tReadDataFromBufferPointer(buf, date.m_nMinute);\n\tReadDataFromBufferPointer(buf, date.m_nHour);\n\tReadDataFromBufferPointer(buf, date.m_nDay);\n\tReadDataFromBufferPointer(buf, date.m_nMonth);\n\tReadDataFromBufferPointer(buf, date.m_nYear);\n\tReadDataFromBufferPointer(buf, CWeather::WeatherTypeInList);\n\tReadDataFromBufferPointer(buf, TheCamera.CarZoomIndicator);\n\tReadDataFromBufferPointer(buf, TheCamera.PedZoomIndicator);\n\t\n\tif ( date > CompileDateAndTime )\n\t\t;\n\telse\n\tif ( date < CompileDateAndTime )\n\t\t;\n\t\n\t#define ReadDataFromBlock(load_func)\\\n\t\tdo {\\\n\t\t\tReadDataFromBufferPointer(buf, size);\\\n\t\t\tload_func(buf, size);\\\n\t\t\tsize = align4bytes(size);\\\n\t\t\tbuf += size;\\\n\t\t} while (0)\n\t\n\t\n\n\tprintf(\"Loading Scripts \\n\");\n\tReadDataFromBlock(CTheScripts::LoadAllScripts);\n\t\n\tprintf(\"Loading PedPool \\n\");\n\tReadDataFromBlock(CPools::LoadPedPool);\n\t\n\tprintf(\"Loading Garages \\n\");\n\tReadDataFromBlock(CGarages::Load);\n\t\n\tprintf(\"Loading Vehicles \\n\");\n\tReadDataFromBlock(CPools::LoadVehiclePool);\n\t\n\tLoadSaveDataBlock();\n\t\n\tCProjectileInfo::RemoveAllProjectiles();\n\tCObject::DeleteAllTempObjects();\n\t\n\tprintf(\"Loading Objects \\n\");\n\tReadDataFromBlock(CPools::LoadObjectPool);\n\t\n\tprintf(\"Loading Paths \\n\");\n\tReadDataFromBlock(ThePaths.Load);\n\t\n\tprintf(\"Loading Cranes \\n\");\n\tReadDataFromBlock(CCranes::Load);\n\t\n\tLoadSaveDataBlock();\n\t\n\tprintf(\"Loading Pickups \\n\");\n\tReadDataFromBlock(CPickups::Load);\n\t\n\tprintf(\"Loading Phoneinfo \\n\");\n\tReadDataFromBlock(gPhoneInfo.Load);\n\t\n\tprintf(\"Loading Restart \\n\");\n\tReadDataFromBlock(CRestart::LoadAllRestartPoints);\n\t\n\tprintf(\"Loading Radar Blips \\n\");\n\tReadDataFromBlock(CRadar::LoadAllRadarBlips);\n\t\n\tprintf(\"Loading Zones \\n\");\n\tReadDataFromBlock(CTheZones::LoadAllZones);\n\t\n\tprintf(\"Loading Gang Data \\n\");\n\tReadDataFromBlock(CGangs::LoadAllGangData);\n\t\n\tprintf(\"Loading Car Generators \\n\");\n\tReadDataFromBlock(CTheCarGenerators::LoadAllCarGenerators);\n\t\n\tprintf(\"Loading Particles \\n\");\n\tReadDataFromBlock(CParticleObject::LoadParticle);\n\t\n\tprintf(\"Loading AudioScript Objects \\n\");\n\tReadDataFromBlock(cAudioScriptObject::LoadAllAudioScriptObjects);\n\t\n\tprintf(\"Loading Player Info \\n\");\n\tReadDataFromBlock(CWorld::Players[CWorld::PlayerInFocus].LoadPlayerInfo);\n\t\n\tprintf(\"Loading Stats \\n\");\n\tReadDataFromBlock(CStats::LoadStats);\n\t\n\tprintf(\"Loading Streaming Stuff \\n\");\n\tReadDataFromBlock(CStreaming::MemoryCardLoad);\n\t\n\tprintf(\"Loading PedType Stuff \\n\");\n\tReadDataFromBlock(CPedType::Load);\n\t\n\t#undef LoadSaveDataBlock\n\t#undef ReadDataFromBlock\n\t\n\tFrontEndMenuManager.SetSoundLevelsForMusicMenu();\n\tFrontEndMenuManager.InitialiseMenuContentsAfterLoadingGame();\n\t\n\tCloseMemCardFile(file);\n\t\n\tif ( nError != NO_ERR_SUCCESS )\n\t\treturn RES_FAILED;\n\t\n\tif ( oldLang != CMenuManager::m_PrefsLanguage )\n\t{\n\t\tTheText.Unload();\n\t\tTheText.Load();\n\t}\n\t\n\tJustLoadedDontFadeInYet = true;\n\tStillToFadeOut = true;\n\t\n\tCTheScripts::Process();\n\t\n\tprintf(\"Game sucessfully loaded \\n\");\n\t\n\treturn RES_SUCCESS;\n}\n\nint32\nCMemoryCard::CheckCardInserted(int32 cardID)\n{\n#if defined(PS2)\n\tint cmd  = sceMcFuncNoCardInfo;\n\tint type = sceMcTypeNoCard;\n\t\n\tCTimer::Stop();\n\t\n\twhile ( sceMcGetInfo(Cards[cardID].port, 0, &type, 0, 0) != sceMcResSucceed )\n\t\t;\n\t\n\tint result;\n\tsceMcSync(0, &cmd, &result);\n\t\n\tif ( type == sceMcTypePS2 )\n\t{\n\t\tif ( result == sceMcResChangedCard || result == sceMcResSucceed )\n\t\t{\n\t\t\tnError = NO_ERR_SUCCESS;\n\t\t\treturn nError;\n\t\t}\n\t\telse if ( result == sceMcResNoFormat )\n\t\t{\n\t\t\tnError = ERR_NOFORMAT;\n\t\t\treturn nError;\n\t\t}\n\t}\n\t\n\tprintf(\"Memory card %i not present\\n\", cardID);\n\t\n\tnError = ERR_NONE;\n\treturn nError;\n#else\n\tnError = NO_ERR_SUCCESS;\n\treturn nError;\n#endif\n}\n\nint32\nCMemoryCard::PopulateCardFlags(int32 cardID, bool bSlotFlag, bool bTypeFlag, bool bFreeFlag, bool bFormatFlag)\n{\n#if defined(PS2)\n\tint cmd = sceMcFuncNoCardInfo;\n\tint type = sceMcTypeNoCard;\n\tint free = 0;\n\tint format = 0;\n\t\n\tCTimer::Stop();\n\t\n\tCards[cardID].type = 0;\n\tCards[cardID].free = 0;\n\tCards[cardID].format = 0;\n\t\n\twhile ( sceMcGetInfo(Cards[cardID].port, 0, &type, &free, &format) != sceMcResSucceed )\n\t\t;\n\t\n\tint result;\n\tsceMcSync(0, &cmd, &result);\n\t\n\tif ( type == sceMcTypePS2 )\n\t{\n\t\tif ( result == sceMcResChangedCard || result == sceMcResSucceed )\n\t\t{\n\t\t\tif ( bSlotFlag )\n\t\t\t\tCards[cardID].slot = 0;\n\t\t\t\n\t\t\t//if ( bTypeFlag )\n\t\t\t\tCards[cardID].type = type;\n\t\t\t\n\t\t\tif ( bFreeFlag )\n\t\t\t\tCards[cardID].free = free;\n\t\t\t\n\t\t\tif ( bFormatFlag )\n\t\t\t\tCards[cardID].format = format;\n\t\t\t\n\t\t\tprintf(\"Memory card %i present\\n\", cardID);\n\t\t\t\n\t\t\tnError = NO_ERR_SUCCESS;\n\t\t\treturn nError;\n\t\t}\n\t\telse if ( result == sceMcResNoFormat )\n\t\t{\n\t\t\tnError = ERR_NOFORMAT;\n\t\t\treturn nError;\n\t\t}\n\t}\n\t\n\tprintf(\"Memory card %i not present\\n\", cardID);\n\t\n\tnError = ERR_NONE;\n\treturn nError;\n#else\n\tCTimer::Stop();\n\t\n\tCards[cardID].type = 0;\n\tCards[cardID].free = 0;\n\tCards[cardID].format = 0;\n\t\n\tif ( bSlotFlag )\n\t\tCards[cardID].slot = 0;\n\t\t\t\n\t//if ( bTypeFlag )\n\t\tCards[cardID].type = 0;\n\t\t\t\n\tif ( bFreeFlag )\n\t\tCards[cardID].free = 1024 * 1024 * 4;\n\t\t\t\n\tif ( bFormatFlag )\n\t\tCards[cardID].format = 0;\n\t\n\tprintf(\"Memory card %i present\\n\", cardID);\n\t\n\tnError = NO_ERR_SUCCESS;\n\treturn nError;\n#endif\n}\n\nint32\nCMemoryCard::FormatCard(int32 cardID)\n{\n\tCTimer::Stop();\n\t\n#if defined(PS2)\n\tint cmd = sceMcFuncNoFormat;\n\t\n\tint32 r = CheckCardInserted(cardID);\n\tif ( r == NO_ERR_SUCCESS )\n\t{\n\t\twhile ( sceMcFormat(Cards[cardID].port, 0) != sceMcResSucceed )\n\t\t\t;\n\t\t\n\t\tint result;\n\t\tsceMcSync(0, &cmd, &result);\n\t\t\n\t\tif ( result < sceMcResSucceed )\n\t\t{\n\t\t\tprintf(\"Memory card %i could not be formatted\\n\", cardID);\n\t\t\t\n\t\t\tnError = ERR_FORMATFAILED;\n\t\t\treturn nError;\n\t\t}\n\t\t\n\t\tprintf(\"Memory card %i present and formatted\\n\", cardID);\n\t\t\t\n\t\tnError = NO_ERR_SUCCESS;\n\t\treturn nError;\n\t}\n\n\treturn r;\n#else\n\tprintf(\"Memory card %i present and formatted\\n\", cardID);\n\n\tnError = NO_ERR_SUCCESS;\n\treturn nError;\n#endif\n}\n\nint32\nCMemoryCard::PopulateFileTable(int32 cardID)\n{\n\tCTimer::Stop();\n\t\n#if defined (PS2)\n\tint cmd = sceMcFuncNoGetDir;\n\t\n\tClearFileTableBuffer(cardID);\n\t\n\twhile ( sceMcGetDir(Cards[cardID].port, 0, \"*\", 0, ARRAY_SIZE(Cards[cardID].table), Cards[cardID].table) != sceMcResSucceed )\n\t\t;\n\t\t\n\tint result;\n\tsceMcSync(0, &cmd, &result);\n\t\n\tif ( result >= sceMcResSucceed )\n\t{\n\t\tprintf(\"Memory card %i present PopulateFileTables function successfull \\n\", cardID);\n\t\t\n\t\tnError = NO_ERR_SUCCESS;\n\t\treturn nError;\n\t}\n\t\n\tif ( result == sceMcResNoFormat )\n\t{\n\t\tprintf(\"Memory card %i PopulateFileTables function successfull. MemoryCard not Formatted  \\n\", cardID);\n\t\t\n\t\tnError = ERR_NOFORMAT;\n\t\treturn nError;\n\t}\n\t\n\tif ( result == sceMcResNoEntry )\n\t{\n\t\tprintf(\"Memory card %i  PopulateFileTables function unsuccessfull. Path does not exist  \\n\", cardID);\n\t\t\n\t\tnError = ERR_FILETABLENOENTRY;\n\t\treturn nError;\n\t}\n\t\n\tprintf(\"Memory card %i not Present\\n\", cardID);\n\t\t\n\tnError = ERR_NONE;\n\treturn nError;\n#else\n\tClearFileTableBuffer(cardID);\n\n\tchar path[512];\n\tsprintf(path, \"%s\\\\%s\\\\%s\\\\*\", PCCardsPath, PCCardDir[cardID], CardCurDir[cardID]);\n\t\n\tmemset(Cards[cardID].table, 0, sizeof(Cards[cardID].table));\n\tWIN32_FIND_DATA fd; HANDLE hFind; int32 num = 0;\n\tif ( (hFind = FindFirstFile(path, &fd)) == INVALID_HANDLE_VALUE )\n\t{\n\t\tprintf(\"Memory card %i not Present\\n\", cardID);\n\t\tnError = ERR_NONE;\n\t\treturn nError;\n\t}\n\tdo\n\t{\n\t\tSYSTEMTIME st;\n\t\tFileTimeToSystemTime(&fd.ftCreationTime, &st);\n\t\tCards[cardID].table[num]._Create.Sec = st.wSecond;Cards[cardID].table[num]._Create.Min = st.wMinute;Cards[cardID].table[num]._Create.Hour = st.wHour;Cards[cardID].table[num]._Create.Day = st.wDay;Cards[cardID].table[num]._Create.Month = st.wMonth;Cards[cardID].table[num]._Create.Year = st.wYear;\n\t\tFileTimeToSystemTime(&fd.ftLastWriteTime, &st);\n\t\tCards[cardID].table[num]._Modify.Sec = st.wSecond;Cards[cardID].table[num]._Modify.Min = st.wMinute;Cards[cardID].table[num]._Modify.Hour = st.wHour;Cards[cardID].table[num]._Modify.Day = st.wDay;Cards[cardID].table[num]._Modify.Month = st.wMonth;Cards[cardID].table[num]._Modify.Year = st.wYear;\n\t\tCards[cardID].table[num].FileSizeByte = fd.nFileSizeLow;\n\t\tstrncpy((char *)Cards[cardID].table[num].EntryName, fd.cFileName, sizeof(Cards[cardID].table[num].EntryName) - 1);\n\t\tnum++;\n\t} while( FindNextFile(hFind, &fd) && num < ARRAY_SIZE(Cards[cardID].table) );\n\tFindClose(hFind);\n\t\n\t//todo errors\n\t\n\tprintf(\"Memory card %i present PopulateFileTables function successfull \\n\", cardID);\n\n\tnError = NO_ERR_SUCCESS;\n\treturn nError;\n#endif\n}\n\nint32\nCMemoryCard::CreateRootDirectory(int32 cardID)\n{\n\tCTimer::Stop();\n#if defined(PS2)\n\tint cmd = sceMcFuncNoMkdir;\n\t\n\twhile ( sceMcMkdir(Cards[cardID].port, 0, Cards[cardID].dir) != sceMcResSucceed )\n\t\t;\n\t\n\tint result;\n\tsceMcSync(0, &cmd, &result);\n\t\n\tif ( result == sceMcResSucceed )\n\t{\n\t\tprintf(\"Memory card %i present. RootDirectory Created\\n\", cardID);\n\t\t\n\t\tnError = NO_ERR_SUCCESS;\n\t\treturn nError;\n\t}\n\t\n\tif ( result == sceMcResNoFormat )\n\t{\n\t\tprintf(\"Memory card %i RootDirectory not created card unformatted\\n\", cardID);\n\t\t\n\t\tnError = ERR_NOFORMAT;\n\t\treturn nError;\n\t}\n\t\n\tif ( result == sceMcResFullDevice )\n\t{\n\t\tprintf(\"Memory card %i RootDirectory not created due to insufficient memory card capacity\\n\", cardID);\n\t\t\n\t\tnError = ERR_DIRFULLDEVICE;\n\t\treturn nError;\n\t}\n\t\n\tif ( result == sceMcResNoEntry )\n\t{\n\t\tprintf(\"Memory card %i RootDirectory not created due to problem with pathname\\n\", cardID);\n\t\t\n\t\tnError = ERR_DIRBADENTRY;\n\t\treturn nError;\n\t}\n\t\n\tprintf(\"Memory card %i not present so RootDirectory not created \\n\", cardID);\n\t\t\n\tnError = ERR_NONE;\n\treturn nError;\n#else\n\tchar path[512];\n\tsprintf(path, \"%s\\\\%s\\\\%s\", PCCardsPath, PCCardDir[cardID], Cards[cardID].dir);\n\t_psCreateFolder(path);\n\t\n\tprintf(\"Memory card %i present. RootDirectory Created\\n\", cardID);\n\n\tnError = NO_ERR_SUCCESS;\n\treturn nError;\t\n#endif\n}\n\nint32\nCMemoryCard::ChangeDirectory(int32 cardID, char *dir)\n{\n\tCTimer::Stop();\n\t\n#if defined(PS2)\n\tint cmd = sceMcFuncNoChDir;\n\t\n\twhile ( sceMcChdir(Cards[cardID].port, 0, dir, 0) != sceMcResSucceed )\n\t\t;\n\t\n\tint result;\n\tsceMcSync(0, &cmd, &result);\n\t\n\tif ( result == sceMcResSucceed )\n\t{\n\t\tprintf(\"Memory Card %i. Changed to the directory %s \\n\", cardID, dir);\n\t\t\n\t\tnError = NO_ERR_SUCCESS;\n\t\treturn nError;\n\t}\n\t\n\tif ( result == sceMcResNoFormat )\n\t{\n\t\tprintf(\"Memory card %i. Couldn't change to the directory %s. MemoryCard not Formatted  \\n\", cardID, dir);\n\t\t\n\t\tnError = ERR_NOFORMAT;\n\t\treturn nError;\n\t}\n\t\n\tif ( result == sceMcResNoEntry )\n\t{\n\t\tprintf(\"Memory card %i  Couldn't change to the directory %s. Path does not exist  \\n\", cardID, dir);\n\t\t\n\t\tnError = ERR_DIRNOENTRY;\n\t\treturn nError;\n\t}\n\t\n\tprintf(\"Memory card %i not Present. So could not change to directory %s.\\n\", cardID, dir);\n\t\n\tnError = ERR_NONE;\n\treturn nError;\n#else\n\t\n\tif ( !strcmp(dir, \"/\" ) )\n\t{\n\t\tstrncpy(CardCurDir[cardID], dir, sizeof(CardCurDir[cardID]) - 1);\n\t\tprintf(\"Memory Card %i. Changed to the directory %s \\n\", cardID, dir);\n\t\tnError = NO_ERR_SUCCESS;\n\t\treturn nError;\n\t}\n\n\tchar path[512];\n\tsprintf(path, \"%s\\\\%s\\\\%s\", PCCardsPath, PCCardDir[cardID], dir);\n\t\n\tWIN32_FIND_DATA fd; HANDLE hFind;\n\tif ( (hFind = FindFirstFile(path, &fd)) == INVALID_HANDLE_VALUE )\n\t{\n\t\tprintf(\"Memory card %i  Couldn't change to the directory %s. Path does not exist  \\n\", cardID, dir);\n\t\t\n\t\tnError = ERR_DIRNOENTRY;\n\t\treturn nError;\n\t}\n\n\tFindClose(hFind);\n\n\tstrncpy(CardCurDir[cardID], dir, sizeof(CardCurDir[cardID]) - 1);\n\tprintf(\"Memory Card %i. Changed to the directory %s \\n\", cardID, dir);\n\tnError = NO_ERR_SUCCESS;\n\treturn nError;\n#endif\n}\n\nint32\nCMemoryCard::CreateIconFiles(int32 cardID, char *icon_one, char *icon_two, char *icon_three)\n{\n#if defined(PS2)\n\tsceMcIconSys icon;\n\tstatic sceVu0IVECTOR bgcolor[4] = {\n\t\t{ 0x80,    0,    0, 0 },\n\t\t{    0, 0x80,    0, 0 },\n\t\t{    0,    0, 0x80, 0 },\n\t\t{ 0x80, 0x80, 0x80, 0 },\n\t};\n\tstatic sceVu0FVECTOR lightdir[3] = {\n\t\t{ 0.5, 0.5, 0.5, 0.0 },\n\t\t{ 0.0,-0.4,-0.1, 0.0 },\n\t\t{-0.5,-0.5, 0.5, 0.0 },\n\t};\n\tstatic sceVu0FVECTOR lightcol[3] = {\n\t\t{ 0.48, 0.48, 0.03, 0.00 },\n\t\t{ 0.50, 0.33, 0.20, 0.00 },\n\t\t{ 0.14, 0.14, 0.38, 0.00 },\n\t};\n\tstatic sceVu0FVECTOR ambient = { 0.50, 0.50, 0.50, 0.00 };\n\tchar head[8]  = \"PS2D\";\n\tchar title[8] = \"GTA3\";\n\t\n\tmemset(&icon, 0, sizeof(icon));\n\t\n\tmemcpy(icon.BgColor,    bgcolor,  sizeof(bgcolor));\n\tmemcpy(icon.LightDir,   lightdir, sizeof(lightdir));\n\tmemcpy(icon.LightColor, lightcol, sizeof(lightcol));\n\tmemcpy(icon.Ambient,    ambient,  sizeof(ambient));\n\t\n\ticon.OffsLF = 24;\n\ticon.TransRate = 0x60;\n\t\n\tunsigned short *titleName = (unsigned short *)icon.TitleName;\n\t\n\tuint32 titlec = 0;\n\twhile ( titlec < strlen(title) )\n\t{\n\t\tunsigned short sjis = Ascii2Sjis(title[titlec]);\n\t\ttitleName[titlec] = (sjis << 8) | (sjis >> 8);\n\t\ttitlec++;\n\t}\n\t\n\ttitleName[titlec] = L'\\0';\n\n\tchar icon1[80];\n\tchar icon2[80];\n\tchar icon3[80];\n\t\n\tstrncpy(icon1, icon_one,   sizeof(icon1) - 1);\n\tstrncpy(icon2, icon_two,   sizeof(icon2) - 1);\n\tstrncpy(icon3, icon_three, sizeof(icon3) - 1);\n\t\n\tstrncpy((char *)icon.FnameView, icon1, sizeof(icon.FnameView) - 1);\n\tstrncpy((char *)icon.FnameCopy, icon2, sizeof(icon.FnameCopy) - 1);\n\tstrncpy((char *)icon.FnameDel,  icon3, sizeof(icon.FnameDel) - 1);\n\tstrncpy((char *)icon.Head, head, sizeof(icon.Head));\n\t\n\tint32 iconFile = CreateMemCardFileReadWrite(Cards[cardID].port, \"icon.sys\");\n\t\n\tif ( nError != NO_ERR_SUCCESS )\n\t\treturn RES_FAILED;\n\t\n\tWritetoMemCard(iconFile, &icon, sizeof(icon));\n\t\n\tif ( nError != NO_ERR_SUCCESS )\n\t\treturn RES_FAILED;\n\t\n\tCloseMemCardFile(iconFile);\n\t\n\tif ( nError != NO_ERR_SUCCESS )\n\t\treturn RES_FAILED;\n\t\n\tif ( LoadIconFiles(Cards[cardID].port, icon_one, icon_two, icon_three) == RES_SUCCESS )\n\t{\n\t\tprintf(\"All Icon files Created and loaded. \\n\");\n\t\treturn RES_SUCCESS;\n\t}\n\t\n\tprintf(\"Could not load all the icon files \\n\");\n\t\n\treturn RES_FAILED;\n#else\n\treturn RES_SUCCESS;\n#endif\n}\n\nint32\nCMemoryCard::LoadIconFiles(int32 cardID, char *icon_one, char *icon_two, char *icon_three)\n{\n#if defined(PS2)\n\tconst uint32 size = 50968;\n\tuint8 *data = new uint8[size];\n\t\n\tchar icon1_path[80];\n\tchar icon2_path[80];\n\tchar icon3_path[80];\n\tchar icon1[32];\n\tchar icon2[32];\n\tchar icon3[32];\n\t\n\tstrncpy(icon1, icon_one, sizeof(icon1) - 1);\n\tstrncpy(icon2, icon_two, sizeof(icon2) - 1);\n\tstrncpy(icon3, icon_three, sizeof(icon3) - 1);\n\t\n\tint hostlen = strlen(HostFileLocationOfIcons);\n\n\tstrncpy(icon1_path, HostFileLocationOfIcons, sizeof(icon1_path) - 1);\n\tstrncpy(icon2_path, HostFileLocationOfIcons, sizeof(icon2_path) - 1);\n\tstrncpy(icon3_path, HostFileLocationOfIcons, sizeof(icon3_path) - 1);\n\t\n\tstrncpy(icon1_path+hostlen, icon_one,   sizeof(icon1_path) - 1 - hostlen);\n\tstrncpy(icon2_path+hostlen, icon_two,   sizeof(icon2_path) - 1 - hostlen);\n\tstrncpy(icon3_path+hostlen, icon_three, sizeof(icon3_path) - 1 - hostlen);\n\t\n\t// ico1 copy\n\tint32 ico1file = CFileMgr::OpenFile(icon1_path);\n\tCFileMgr::Read(ico1file, (char *)data, size);\n\tCFileMgr::CloseFile(ico1file);\n\t\n\tint32 ico1mc = CreateMemCardFileReadWrite(Cards[cardID].port, icon1);\n\t\n\tif ( nError != NO_ERR_SUCCESS )\n\t{\n\t\tdelete [] data;\n\t\treturn RES_FAILED;\n\t}\n\t\n\tWritetoMemCard(ico1mc, data, size);\n\t\n\tif ( nError != NO_ERR_SUCCESS )\n\t{\n\t\tdelete [] data;\n\t\treturn RES_FAILED;\n\t}\n\t\n\tCloseMemCardFile(ico1mc);\n\t\n\tif ( nError != NO_ERR_SUCCESS )\n\t{\n\t\tdelete [] data;\n\t\treturn RES_FAILED;\n\t}\n\t\n\t// ico2 copy\n\tint32 ico2file = CFileMgr::OpenFile(icon2_path);\n\tCFileMgr::Read(ico2file, (char *)data, size);\n\tCFileMgr::CloseFile(ico2file);\n\t\n\tint32 ico2mc = CreateMemCardFileReadWrite(Cards[cardID].port, icon2);\n\t\n\tif ( nError != NO_ERR_SUCCESS )\n\t{\n\t\tdelete [] data;\n\t\treturn RES_FAILED;\n\t}\n\t\n\tWritetoMemCard(ico2mc, data, size);\n\t\n\tif ( nError != NO_ERR_SUCCESS )\n\t{\n\t\tdelete [] data;\n\t\treturn RES_FAILED;\n\t}\n\t\n\tCloseMemCardFile(ico2mc);\n\t\n\tif ( nError != NO_ERR_SUCCESS )\n\t{\n\t\tdelete [] data;\n\t\treturn RES_FAILED;\n\t}\n\t\n\t// ico3 copy\n\tint32 ico3file = CFileMgr::OpenFile(icon3_path);\n\tCFileMgr::Read(ico3file, (char *)data, size);\n\tCFileMgr::CloseFile(ico3file);\n\t\n\tint32 ico3mc = CreateMemCardFileReadWrite(Cards[cardID].port, icon3);\n\t\n\tif ( nError != NO_ERR_SUCCESS )\n\t{\n\t\tdelete [] data;\n\t\treturn RES_FAILED;\n\t}\n\t\n\tWritetoMemCard(ico3mc, data, size);\n\t\n\tif ( nError != NO_ERR_SUCCESS )\n\t{\n\t\tdelete [] data;\n\t\treturn RES_FAILED;\n\t}\n\t\n\tCloseMemCardFile(ico3mc);\n\t\n\tif ( nError != NO_ERR_SUCCESS )\n\t{\n\t\tdelete [] data;\n\t\treturn RES_FAILED;\n\t}\n\t\n\tdelete [] data;\n\t\n\treturn RES_SUCCESS;\n#else\n\treturn RES_SUCCESS;\n#endif\n}\n\nint32\nCMemoryCard::CloseMemCardFile(int32 file)\n{\n\tCTimer::Stop();\n\t\n#if defined(PS2)\n\tint cmd = sceMcFuncNoClose;\n\t\n\twhile ( sceMcClose(file) != sceMcResSucceed )\n\t\t;\n\t\n\tint result;\n\tsceMcSync(0, &cmd, &result);\n\t\n\tif ( result == sceMcResSucceed )\n\t{\n\t\tprintf(\"File %i closed\\n\", file);\n\t\n\t\tnError = NO_ERR_SUCCESS;\n\t\treturn nError;\n\t}\n\t\n\tif ( result == sceMcResNoFormat )\n\t{\n\t\tprintf(\"Memory Card is Unformatted\");\n\t\n\t\tnError = ERR_NOFORMAT;\n\t\treturn nError;\n\t}\n\t\n\tif ( result == sceMcResNoEntry )\n\t{\n\t\tprintf(\"Memory Card File Handle %i has not been opened\", file);\n\t\n\t\tnError = ERR_OPENNOENTRY;\n\t\treturn nError;\n\t}\n\t\n\tnError = ERR_NONE;\n\treturn nError;\n#else\n\tCFileMgr::CloseFile(file);\n\tprintf(\"File %i closed\\n\", file);\n\t\n\tnError = NO_ERR_SUCCESS;\n\treturn nError;\t\n#endif\n}\n\nint32\nCMemoryCard::CreateMemCardFileReadWrite(int32 cardID, char *filename)\n{\n\tCTimer::Stop();\n\t\n#if defined(PS2)\n\tint cmd = sceMcFuncNoOpen;\n\t\n\tchar buff[255];\n\t\n\tstrncpy(buff, filename, sizeof(buff));\n\t\n\twhile ( sceMcOpen(Cards[cardID].port, 0, buff, SCE_RDWR|SCE_CREAT) != sceMcResSucceed )\n\t\t;\n\t\n\tint result;\n\tsceMcSync(0, &cmd, &result);\n\t\n\tif ( result >= sceMcResSucceed )\n\t{\n\t\tprintf(\"%s File Created for MemoryCard. Its File handle is %i. \\n\", buff, result);\n\t\n\t\tnError = NO_ERR_SUCCESS;\n\t\treturn result;\n\t}\n\t\n\tif ( result == sceMcResNoFormat )\n\t{\n\t\tnError = ERR_NOFORMAT;\n\t\treturn nError;\n\t}\n\t\n\tif ( result == sceMcResFullDevice )\n\t{\n\t\tnError = ERR_FILEFULLDEVICE;\n\t\treturn nError;\n\t}\n\t\n\tif ( result == sceMcResNoEntry )\n\t{\n\t\tnError = ERR_FILENOPATHENTRY;\n\t\treturn nError;\n\t}\n\t\n\tif ( result == sceMcResDeniedPermit )\n\t{\n\t\tnError = ERR_FILEDENIED;\n\t\treturn nError;\n\t}\n\t\n\tif ( result == sceMcResUpLimitHandle )\n\t{\n\t\tnError = ERR_FILEUPLIMIT;\n\t\treturn nError;\n\t}\n\t\n\tprintf(\"File %s not created on memory card.\\n\", buff);\n\t\n\treturn ERR_NONE;\n#else\n\tchar path[512];\n\tsprintf(path, \"%s\\\\%s\\\\%s\\\\%s\", PCCardsPath, PCCardDir[cardID], CardCurDir[cardID], filename);\n\tint32 file = CFileMgr::OpenFile(path, \"wb+\");\n\tif (file == 0)\n\t{\n\t\tsprintf(path, \"%s\\\\%s\\\\%s\", PCCardsPath, PCCardDir[cardID], filename);\n\t\tfile = CFileMgr::OpenFile(path, \"wb+\");\n\t}\n\n\tif ( file )\n\t{\n\t\tprintf(\"%s File Created for MemoryCard. Its File handle is %i. \\n\", filename, file);\n\t\tnError = NO_ERR_SUCCESS;\n\t\treturn file;\n\t}\n\t\n\tprintf(\"File %s not created on memory card.\\n\", path);\n\t\n\tnError = ERR_NONE;\n\treturn 0;\n#endif\n}\n\nint32\nCMemoryCard::OpenMemCardFileForReading(int32 cardID, char *filename)\n{\n\tCTimer::Stop();\n\t\n#if defined(PS2)\n\tint cmd = sceMcFuncNoOpen;\n\t\n\tchar buff[255];\n\t\n\tstrncpy(buff, filename, sizeof(buff));\n\t\n\twhile ( sceMcOpen(Cards[cardID].port, 0, buff, SCE_RDONLY) != sceMcResSucceed )\n\t\t;\n\t\n\tint result;\n\tsceMcSync(0, &cmd, &result);\n\t\n\tif ( result >= sceMcResSucceed )\n\t{\n\t\tprintf(\"%s File Created for MemoryCard. Its File handle is %i. \\n\", buff, result);\n\t\n\t\tnError = NO_ERR_SUCCESS;\n\t\treturn result;\n\t}\n\t\n\tif ( result == sceMcResNoFormat )\n\t{\n\t\tnError = ERR_NOFORMAT;\n\t\treturn nError;\n\t}\n\t\n\tif ( result == sceMcResFullDevice )\n\t{\n\t\tnError = ERR_FILEFULLDEVICE;\n\t\treturn nError;\n\t}\n\t\n\tif ( result == sceMcResNoEntry )\n\t{\n\t\tnError = ERR_FILENOPATHENTRY;\n\t\treturn nError;\n\t}\n\t\n\tif ( result == sceMcResDeniedPermit )\n\t{\n\t\tnError = ERR_FILEDENIED;\n\t\treturn nError;\n\t}\n\t\n\tif ( result == sceMcResUpLimitHandle )\n\t{\n\t\tnError = ERR_FILEUPLIMIT;\n\t\treturn nError;\n\t}\n\t\n\tprintf(\"File %s not created on memory card.\\n\", buff);\n\tnError = ERR_NONE;\n\treturn nError;\n#else\t\n\tchar path[512];\n\tsprintf(path, \"%s\\\\%s\\\\%s\\\\%s\", PCCardsPath, PCCardDir[cardID], CardCurDir[cardID], filename);\n\tint32 file = CFileMgr::OpenFile(path, \"rb\");\n\tif (file == 0)\n\t{\n\t\tsprintf(path, \"%s\\\\%s\\\\%s\", PCCardsPath, PCCardDir[cardID], filename);\n\t\tfile = CFileMgr::OpenFile(path, \"rb\");\n\t}\n\n\tif ( file )\n\t{\n\t\tprintf(\"%s File Created for MemoryCard. Its File handle is %i. \\n\", filename, file);\n\t\tnError = NO_ERR_SUCCESS;\n\t\treturn file;\n\t}\n\t\n\tprintf(\"File %s not created on memory card.\\n\", path);\n\tnError = ERR_NONE;\n\treturn 0;\n#endif\n}\n\nint32\nCMemoryCard::ReadFromMemCard(int32 file, void *buff, int32 size)\n{\n\tCTimer::Stop();\n\t\n#if defined(PS2)\n\tint cmd = sceMcFuncNoRead;\n\t\n\twhile ( sceMcRead(file, buff, size) != sceMcResSucceed )\n\t\t;\n\t\n\tint result;\n\tsceMcSync(0, &cmd, &result);\n\t\n\tif ( result >= sceMcResSucceed )\n\t{\n\t\tif ( size >= result )\n\t\t{\n\t\t\tprintf(\"%i Bytes Read for Filehandle %i \\n\", result, file);\n\t\t\t\n\t\t\tnError = NO_ERR_SUCCESS;\n\t\t\treturn result;\n\t\t}\n\t}\n\t\n\tif ( result == sceMcResNoFormat )\n\t{\n\t\tnError = ERR_NOFORMAT;\n\t\treturn nError;\n\t}\n\t\n\tif ( result == sceMcResNoEntry )\n\t{\n\t\tnError = ERR_READNOENTRY;\n\t\treturn nError;\n\t}\n\t\n\tif ( result == sceMcResDeniedPermit )\n\t{\n\t\tnError = ERR_READDENIED;\n\t\treturn nError;\n\t}\n\t\n\tprintf(\"No Bytes Read for Filehandle %i \\n\", file);\n\t\t\t\n\tnError = ERR_NONE;\n\treturn result;\n#else\t\t\n\tint32 s = CFileMgr::Read(file, (const char *)buff, size);\n\tif ( s == size )\n\t{\n\t\tprintf(\"%i Bytes Read for Filehandle %i \\n\", s, file);\n\t\t\n\t\tnError = NO_ERR_SUCCESS;\n\t\treturn s;\n\t}\n\t\n\tprintf(\"No Bytes Read for Filehandle %i \\n\", file);\n\t\n\tnError = ERR_NONE;\n\treturn s;\n#endif\n}\n\nint32\nCMemoryCard::DeleteMemoryCardFile(int32 cardID, char *filename)\n{\n\tCTimer::Stop();\n\t\n#if defined(PS2)\n\tint cmd = sceMcFuncNoDelete;\n\t\n\twhile ( sceMcDelete(Cards[cardID].port, 0, filename) != sceMcResSucceed )\n\t\t;\n\t\n\tint result;\n\tsceMcSync(0, &cmd, &result);\n\t\n\tif ( result == sceMcResSucceed )\n\t{\n\t\tprintf(\"Memory Card %i, %s NO_ERR_SUCCESSfully deleted\", cardID, filename);\n\t\t\t\n\t\tnError = NO_ERR_SUCCESS;\n\t\treturn nError;\n\t}\n\t\n\tif ( result == sceMcResNoFormat )\n\t{\n\t\tprintf(\"Memory Card %i, %s not deleted as memory Card is unformatted\", cardID, filename);\n\t\t\t\n\t\tnError = ERR_NOFORMAT;\n\t\treturn nError;\n\t}\n\t\n\tif ( result == sceMcResNoEntry )\n\t{\n\t\tprintf(\"Memory Card %i, %s attempt made to delete non existing file\", cardID, filename);\n\t\t\t\n\t\tnError = ERR_DELETENOENTRY;\n\t\treturn nError;\n\t}\n\t\n\tif ( result == sceMcResDeniedPermit )\n\t{\n\t\tprintf(\"Memory Card %i, %s not deleted as file is in use or write protected\", cardID, filename);\n\t\t\n\t\tnError = ERR_DELETEDENIED;\n\t\treturn nError;\n\t}\n\t\n\tif ( result == sceMcResNotEmpty )\n\t{\n\t\tprintf(\"Memory Card %i, %s not deleted. Entries remain in subdirectory\", cardID, filename);\n\t\t\n\t\tnError = ERR_DELETEFAILED;\n\t\treturn nError;\n\t}\n\t\n\tnError = ERR_NONE;\n\treturn nError;\n#else\n\tchar path[512];\n\tsprintf(path, \"%s\\\\%s\\\\%s\\\\%s\", PCCardsPath, PCCardDir[cardID], CardCurDir[cardID], filename);\n\tint32 file = CFileMgr::OpenFile(path, \"rb\");\n\tif (file == 0)\n\t{\n\t\tsprintf(path, \"%s\\\\%s\\\\%s\", PCCardsPath, PCCardDir[cardID], filename);\n\t\tfile = CFileMgr::OpenFile(path, \"rb\");\n\t}\n\n\tif ( file )\n\t{\n\t\tCFileMgr::CloseFile(file);\n\t\t\n\t\tDeleteFile(path);\n\t\t\n\t\tprintf(\"Memory Card %i, %s NO_ERR_SUCCESSfully deleted\", cardID, filename);\n\t\t\n\t\tnError = NO_ERR_SUCCESS;\n\t\treturn nError;\n\t}\n\t\n\tprintf(\"Memory Card %i, %s attempt made to delete non existing file\", cardID, filename);\n\tnError = ERR_DELETENOENTRY;\n\t\t\n\t//nError = ERR_NONE;\n\treturn nError;\n\t\t\n#endif\n}\n\nvoid\nCMemoryCard::PopulateErrorMessage()\n{\n\tswitch ( nError )\n\t{\n\t\tcase ERR_WRITEFULLDEVICE:\n\t\tcase ERR_DIRFULLDEVICE:\n\t\t\tpErrorMsg = TheText.Get(\"SLONDR\"); break; // Insufficient space to save. Please insert a Memory Card (PS2) with at least 500KB of free space available into MEMORY CARD slot 1.\n\t\tcase ERR_FORMATFAILED:\n\t\t\tpErrorMsg = TheText.Get(\"SLONFM\"); break; // Error formatting Memory Card (PS2) in MEMORY CARD slot 1.\n\t\tcase ERR_SAVEFAILED:\n\t\t\tpErrorMsg = TheText.Get(\"SLNSP\");  break; // Insufficient space to save. Please insert a Memory Card (PS2) with at least 200KB of free space available into MEMORY CARD slot 1.\n\t\tcase ERR_DELETEDENIED:\n\t\tcase ERR_NOFORMAT:\n\t\t\tpErrorMsg = TheText.Get(\"SLONNF\"); break; // Memory Card (PS2) in MEMORY CARD slot 1 is unformatted.\n\t\tcase ERR_NONE:\n\t\t\tpErrorMsg = TheText.Get(\"SLONNO\"); break; // No Memory Card (PS2) in MEMORY CARD slot 1.\n\t}\n}\n\nint32\nCMemoryCard::WritetoMemCard(int32 file, void *buff, int32 size)\n{\n#if defined(PS2)\n\tint cmd = sceMcFuncNoWrite;\n\tint result = sceMcResSucceed;\n\tint result1 = sceMcResSucceed;\n\t\n\tCTimer::Stop();\n\t\n\twhile ( sceMcWrite(file, buff, size) != sceMcResSucceed )\n\t\t;\n\t\n\tsceMcSync(0, &cmd, &result);\n\t\n\tif ( result == sceMcResNoFormat )\n\t{\n\t\tprintf(\"No Bytes written for Filehandle %i \\n\", file);\n\t\t\n\t\tnError = ERR_NOFORMAT;\n\t\treturn nError;\n\t}\n\t\n\tif ( result == sceMcResFullDevice )\n\t{\n\t\tprintf(\"No Bytes written for Filehandle %i \\n\", file);\n\t\t\n\t\tnError = ERR_WRITEFULLDEVICE;\n\t\treturn nError;\n\t}\n\t\n\tif ( result == sceMcResNoEntry )\n\t{\n\t\tprintf(\"No Bytes written for Filehandle %i \\n\", file);\n\t\t\n\t\tnError = ERR_WRITENOENTRY;\n\t\treturn nError;\n\t}\n\t\n\tif ( result == sceMcResDeniedPermit )\n\t{\n\t\tprintf(\"No Bytes written for Filehandle %i \\n\", file);\n\t\t\n\t\tnError = ERR_WRITEDENIED;\n\t\treturn nError;\n\t}\n\t\n\tif ( result == sceMcResFailReplace )\n\t{\n\t\tprintf(\"No Bytes written for Filehandle %i \\n\", file);\n\t\t\n\t\tnError = ERR_WRITEFAILED;\n\t\treturn nError;\n\t}\n\t\n\tif ( result <= -10 )\n\t{\n\t\tprintf(\"No Bytes written for Filehandle %i \\n\", file);\n\t\t\n\t\tnError = ERR_NONE;\n\t\treturn nError;\n\t}\n\t\n\tcmd = sceMcFuncNoFlush;\n\t\n\twhile ( sceMcFlush(file) != sceMcResSucceed )\n\t\t;\n\t\n\tsceMcSync(0, &cmd, &result1);\n\t\n\tif ( result1 == sceMcResNoFormat )\n\t{\n\t\tprintf(\"No Bytes written for Filehandle %i \\n\", file);\n\t\t\n\t\tnError = ERR_NOFORMAT;\n\t\treturn nError;\n\t}\n\t\n\tif ( result1 == sceMcResNoEntry )\n\t{\n\t\tprintf(\"No Bytes written for Filehandle %i \\n\", file);\n\t\t\n\t\tnError = ERR_FLUSHNOENTRY;\n\t\treturn nError;\n\t}\n\t\n\tif ( result1 <= -10 )\n\t{\n\t\tprintf(\"No Bytes written for Filehandle %i \\n\", file);\n\t\t\n\t\tnError = ERR_NONE;\n\t\treturn nError;\n\t}\n\t\n\tif ( result > 0 && result1 == sceMcResSucceed )\n\t{\n\t\tprintf(\"%i Bytes written for Filehandle %i \\n\", result, file);\n\t}\n\telse if ( result == sceMcResSucceed && result1 == sceMcResSucceed )\n\t{\n\t\tprintf(\"Filehandle %i was flushed\\n\", file);\n\t}\n\t\n\tnError = NO_ERR_SUCCESS;\n\treturn nError;\n#else\n\tCTimer::Stop();\n\n\tint32 s = CFileMgr::Write(file, (const char *)buff, size);\n\tif ( s == size )\n\t{\n\t\tprintf(\"%i Bytes written for Filehandle %i \\n\", s, file);\n\t\tnError = NO_ERR_SUCCESS;\n\t\treturn s;\n\t}\n\t\n\tnError = ERR_NONE;\n\treturn s;\n#endif\n}\n\nstatic inline void\nMakeSpaceForSizeInBufferPointer(uint8 *&presize, uint8 *&buf, uint8 *&postsize)\n{\n\tpresize = buf;\n\tbuf += sizeof(uint32);\n\tpostsize = buf;\n}\n\nstatic inline void\nCopySizeAndPreparePointer(uint8 *&buf, uint8 *&postbuf, uint8 *&postbuf2, uint32 &unused, uint32 &size)\n{\n\tmemcpy(buf, &size, sizeof(size));\n\tsize = align4bytes(size);\n\tpostbuf2 += size;\n\tpostbuf = postbuf2;\n}\n\nbool\nCMemoryCard::SaveGame(void)\n{\n\tuint32 saveSize = 0;\n\tuint32 totalSize = 0;\n\t\n\tCurrentCard = CARD_ONE;\n\t\n\tCheckSum = 0;\n\t\n\tCGameLogic::PassTime(360);\n\tCPlayerPed *ped = FindPlayerPed();\n\tped->m_fCurrentStamina = ped->m_fMaxStamina;\n\tCGame::TidyUpMemory(true, false);\n\t\n\tsaveSize = SAVE_FILE_SIZE;\n\tint32 minfree = 198;\n\t\n\tPopulateCardFlags(CurrentCard, false, false, true, false);\n\t\n\tif ( nError != NO_ERR_SUCCESS )\n\t\treturn false;\n\t\n\tminfree += GetClusterAmountForFileCreation(CurrentCard);\n\t\n\tif ( nError != NO_ERR_SUCCESS )\n\t\treturn false;\n\t\n\tif ( Cards[CurrentCard].free < 200 )\n\t{\n\t\tCTimer::Update();\n\t\tuint32 startTime = CTimer::GetTimeInMillisecondsPauseMode();\n\t\t\n\t\twhile ( CTimer::GetTimeInMillisecondsPauseMode()-startTime < 1250 )\n\t\t{\n\t\t\tfor ( int32 i = 0; i < 1000; i++ )\n\t\t\t\tpowf(3.33f, 3.444f);\n\t\t\t\n\t\t\tCTimer::Update();\n\t\t}\n\t\t\t\n\t\tnError = ERR_SAVEFAILED;\n\t\treturn false;\n\t}\n\t\n\tif ( Cards[CurrentCard].free < minfree )\n\t{\n\t\tCTimer::Update();\n\t\tuint32 startTime = CTimer::GetTimeInMillisecondsPauseMode();\n\t\t\n\t\twhile ( CTimer::GetTimeInMillisecondsPauseMode()-startTime < 1250 )\n\t\t{\n\t\t\tfor ( int32 i = 0; i < 1000; i++ )\n\t\t\t\tpowf(3.33f, 3.444f);\n\t\t\t\n\t\t\tCTimer::Update();\n\t\t}\n\t\t\t\n\t\tnError = ERR_SAVEFAILED;\n\t\treturn false;\n\t}\n\t\n\tuint32 size;\n\tuint8 *buf = work_buff;\n\tuint32 reserved = 0;\n\t\n\tint32 file = CreateMemCardFileReadWrite(CurrentCard, ValidSaveName);\n\t\n\tif ( nError != NO_ERR_SUCCESS )\n\t{\n\t\tstrncpy(SaveFileNameJustSaved, ValidSaveName, sizeof(SaveFileNameJustSaved) - 1);\n\t\treturn false;\n\t}\n\t\n\tWriteDataToBufferPointer(buf, saveSize);\n\tWriteDataToBufferPointer(buf, CGame::currLevel);\n\tWriteDataToBufferPointer(buf, TheCamera.GetPosition().x);\n\tWriteDataToBufferPointer(buf, TheCamera.GetPosition().y);\n\tWriteDataToBufferPointer(buf, TheCamera.GetPosition().z);\n\tWriteDataToBufferPointer(buf, CClock::ms_nMillisecondsPerGameMinute);\n\tWriteDataToBufferPointer(buf, CClock::ms_nLastClockTick);\n\tWriteDataToBufferPointer(buf, CClock::ms_nGameClockHours);\n\tWriteDataToBufferPointer(buf, CClock::ms_nGameClockMinutes);\n\tWriteDataToBufferPointer(buf, CPad::GetPad(0)->Mode);\n\tWriteDataToBufferPointer(buf, CTimer::m_snTimeInMilliseconds);\n\tWriteDataToBufferPointer(buf, CTimer::ms_fTimeScale);\n\tWriteDataToBufferPointer(buf, CTimer::ms_fTimeStep);\n\tWriteDataToBufferPointer(buf, CTimer::ms_fTimeStepNonClipped);\n\tWriteDataToBufferPointer(buf, CTimer::m_FrameCounter);\n\tWriteDataToBufferPointer(buf, CTimeStep::ms_fTimeStep);\n\tWriteDataToBufferPointer(buf, CTimeStep::ms_fFramesPerUpdate);\n\tWriteDataToBufferPointer(buf, CTimeStep::ms_fTimeScale);\n\tWriteDataToBufferPointer(buf, CWeather::OldWeatherType);\n\tWriteDataToBufferPointer(buf, CWeather::NewWeatherType);\n\tWriteDataToBufferPointer(buf, CWeather::ForcedWeatherType);\n\tWriteDataToBufferPointer(buf, CWeather::InterpolationValue);\n\tWriteDataToBufferPointer(buf, CMenuManager::m_PrefsMusicVolume);\n\tWriteDataToBufferPointer(buf, CMenuManager::m_PrefsSfxVolume);\n\tWriteDataToBufferPointer(buf, CMenuManager::m_PrefsControllerConfig);\n\tWriteDataToBufferPointer(buf, CMenuManager::m_PrefsUseVibration);\n\tWriteDataToBufferPointer(buf, CMenuManager::m_PrefsStereoMono);\n\tWriteDataToBufferPointer(buf, CMenuManager::m_PrefsRadioStation);\n\tWriteDataToBufferPointer(buf, CMenuManager::m_PrefsBrightness);\n\tWriteDataToBufferPointer(buf, CMenuManager::m_PrefsShowTrails);\n\tWriteDataToBufferPointer(buf, CMenuManager::m_PrefsShowSubtitles);\n\tWriteDataToBufferPointer(buf, CMenuManager::m_PrefsLanguage);\n\tWriteDataToBufferPointer(buf, CMenuManager::m_PrefsUseWideScreen);\n\tWriteDataToBufferPointer(buf, CPad::GetPad(0)->Mode);\n#ifdef PS2\n\tWriteDataToBufferPointer(buf, BlurOn);\n#else\n\tWriteDataToBufferPointer(buf, CMBlur::BlurOn);\n#endif\n\tWriteDataToBufferPointer(buf, CompileDateAndTime.m_nSecond);\n\tWriteDataToBufferPointer(buf, CompileDateAndTime.m_nMinute);\n\tWriteDataToBufferPointer(buf, CompileDateAndTime.m_nHour);\n\tWriteDataToBufferPointer(buf, CompileDateAndTime.m_nDay);\n\tWriteDataToBufferPointer(buf, CompileDateAndTime.m_nMonth);\n\tWriteDataToBufferPointer(buf, CompileDateAndTime.m_nYear);\n\tWriteDataToBufferPointer(buf, CWeather::WeatherTypeInList);\n\tWriteDataToBufferPointer(buf, TheCamera.CarZoomIndicator);\n\tWriteDataToBufferPointer(buf, TheCamera.PedZoomIndicator);\n\t\n\tif ( nError != NO_ERR_SUCCESS )\n\t{\n\t\tstrncpy(SaveFileNameJustSaved, ValidSaveName, sizeof(SaveFileNameJustSaved) - 1);\n\t\treturn false;\n\t}\n\t\n\tuint8 *presize;\n\tuint8 *postsize;\n\t\n\t#define WriteSaveDataBlock(save_func)\\\n\t\tdo {\\\n\t\t\tMakeSpaceForSizeInBufferPointer(presize, buf, postsize);\\\n\t\t\tsave_func(buf, &size);\\\n\t\t\tCopySizeAndPreparePointer(presize, buf, postsize, reserved, size);\\\n\t\t} while (0)\n\t\n\tWriteSaveDataBlock(CTheScripts::SaveAllScripts);\n\tprintf(\"Script Save Size %d, \\n\", size);\n\t\n\tWriteSaveDataBlock(CPools::SavePedPool);\n\tprintf(\"PedPool Save Size %d, \\n\", size);\n\t\n\tWriteSaveDataBlock(CGarages::Save);\n\tprintf(\"Garage Save Size %d, \\n\", size);\n\t\n\tWriteSaveDataBlock(CPools::SaveVehiclePool);\n\tprintf(\"Vehicle Save Size %d, \\n\", size);\n\t\n\tDoClassSaveRoutine(file, work_buff, buf - work_buff);\n\ttotalSize += buf - work_buff;\n\t\n\tif ( nError != NO_ERR_SUCCESS )\n\t\treturn false;\n\t\n\tbuf = work_buff;\n\treserved = 0;\n\t\n\tWriteSaveDataBlock(CPools::SaveObjectPool);\n\tprintf(\"Object Save Size %d, \\n\", size);\n\t\n\tWriteSaveDataBlock(ThePaths.Save);\n\tprintf(\"The Paths Save Size %d, \\n\", size);\n\t\n\tWriteSaveDataBlock(CCranes::Save);\n\tprintf(\"Cranes Save Size %d, \\n\", size);\n\t\n\tDoClassSaveRoutine(file, work_buff, buf - work_buff);\n\ttotalSize += buf - work_buff;\n\t\n\tif ( nError != NO_ERR_SUCCESS )\n\t\treturn false;\n\t\n\tbuf = work_buff;\n\treserved = 0;\n\t\n\tWriteSaveDataBlock(CPickups::Save);\n\tprintf(\"Pick Ups Save Size %d, \\n\", size);\n\t\n\tWriteSaveDataBlock(gPhoneInfo.Save);\n\tprintf(\"Phones Save Size %d, \\n\", size);\n\t\n\tWriteSaveDataBlock(CRestart::SaveAllRestartPoints);\n\tprintf(\"RestartPoints Save Size %d, \\n\", size);\n\t\n\tWriteSaveDataBlock(CRadar::SaveAllRadarBlips);\n\tprintf(\"Radar Save Size %d, \\n\", size);\n\t\n\tWriteSaveDataBlock(CTheZones::SaveAllZones);\n\tprintf(\"Save Size %d, \\n\", size);\n\t\n\tWriteSaveDataBlock(CGangs::SaveAllGangData);\n\tprintf(\"Gangs Save Size %d, \\n\", size);\n\t\n\tWriteSaveDataBlock(CTheCarGenerators::SaveAllCarGenerators);\n\tprintf(\"Car Gens Save Size %d, \\n\", size);\n\t\n\tWriteSaveDataBlock(CParticleObject::SaveParticle);\n\tprintf(\"Particles Save Size %d, \\n\", size);\n\t\n\tWriteSaveDataBlock(cAudioScriptObject::SaveAllAudioScriptObjects);\n\tprintf(\"Audio Script Save Size %d, \\n\", size);\n\t\n\tWriteSaveDataBlock(CWorld::Players[CWorld::PlayerInFocus].SavePlayerInfo);\n\tprintf(\"Player Info Save Size %d, \\n\", size);\n\t\n\tWriteSaveDataBlock(CStats::SaveStats);\n\tprintf(\"Stats Save Size %d, \\n\", size);\n\t\n\tWriteSaveDataBlock(CStreaming::MemoryCardSave);\n\tprintf(\"Streaming Save Size %d, \\n\", size);\n\t\n\tWriteSaveDataBlock(CPedType::Save);\n\tprintf(\"PedType Save Size %d, \\n\", size);\n\t\n\tDoClassSaveRoutine(file, work_buff, buf - work_buff);\n\ttotalSize += buf - work_buff;\n\t\n\tif ( nError != NO_ERR_SUCCESS )\n\t\treturn false;\n\t\n\tbuf = work_buff;\n\treserved = 0;\n\t\n\tfor (int32 i = 0; i < 3; i++)\n\t{\n\t\tsize = align4bytes(saveSize - totalSize - 4);\n\t\tif (size > sizeof(work_buff))\n\t\t\tsize = sizeof(work_buff);\n\t\tif (size > 4) {\n\t\t\tDoClassSaveRoutine(file, work_buff, size);\n\t\t\ttotalSize += size;\n\t\t}\n\t}\n\n\tWritetoMemCard(file, &CheckSum, sizeof(CheckSum));\n\t\n\tCloseMemCardFile(file);\n\t\n\t#undef WriteSaveDataBlock\n\t\n\tif ( nError != NO_ERR_SUCCESS )\n\t{\n\t\tstrncpy(SaveFileNameJustSaved, ValidSaveName, sizeof(SaveFileNameJustSaved) - 1);\n\t\tDoHackRoundSTUPIDSonyDateTimeStuff(CARD_ONE, ValidSaveName);\n\t\treturn false;\n\t}\n\t\n\tDoHackRoundSTUPIDSonyDateTimeStuff(CARD_ONE, ValidSaveName);\n\tstrncpy(SaveFileNameJustSaved, ValidSaveName, sizeof(SaveFileNameJustSaved) - 1);\n\treturn true;\n}\n\nbool\nCMemoryCard::DoHackRoundSTUPIDSonyDateTimeStuff(int32 port, char *filename)\n{\n#if defined(PS2)\n\tint cmd = sceMcFuncNoFileInfo;\n\tint result = sceMcResSucceed;\n\t\n\tsceCdCLOCK rtc;\n\tsceCdReadClock(&rtc);\n\t\n\tsceScfGetLocalTimefromRTC(&rtc);\n\t\n\t#define ROUNDHACK(a) ( ((a) & 15) + ( ( ( ((a) >> 4) << 2 ) + ((a) >> 4) ) << 1 ) )\n\t\n\tsceMcTblGetDir info;\n\t\n\tinfo._Create.Sec   = ROUNDHACK(rtc.second);\n\tinfo._Create.Min   = ROUNDHACK(rtc.minute);\n\tinfo._Create.Hour  = ROUNDHACK(rtc.hour);\n\tinfo._Create.Day   = ROUNDHACK(rtc.day);\n\tinfo._Create.Month = ROUNDHACK(rtc.month);\n\tinfo._Create.Year  = ROUNDHACK(rtc.year) + 2000;\n\t\n\t#undef ROUNDHACK\n\t\n\twhile ( sceMcSetFileInfo(port, 0, filename, (char *)&info, sceMcFileInfoCreate) != sceMcResSucceed )\n\t\t;\n\t\n\tsceMcSync(0, &cmd, &result);\n\t\n\treturn sceMcResSucceed >= result;\n#else\n\treturn true;\n#endif\n}\n\nint32\nCMemoryCard::LookForRootDirectory(int32 cardID)\n{\n\tCTimer::Stop();\n\t\n#if defined(PS2)\t\n\tint cmd = sceMcFuncNoGetDir;\n\t\n\twhile ( sceMcGetDir(Cards[cardID].port, 0, Cards[cardID].dir, 0, ARRAY_SIZE(Cards[cardID].table), Cards[cardID].table) != sceMcResSucceed )\n\t\t;\n\t\n\tint result;\n\tsceMcSync(0, &cmd, &result);\n\t\n\tif ( result == 0 )\n\t{\n\t\tnError = NO_ERR_SUCCESS;\n\t\treturn ERR_NOROOTDIR;\n\t}\n\t\n\tif ( result > sceMcResSucceed )\n\t{\n\t\tprintf(\"Memory card %i present PopulateFileTables function NO_ERR_SUCCESSfull \\n\", cardID);\n\t\t\n\t\tnError = NO_ERR_SUCCESS;\n\t\treturn nError;\n\t}\n\t\n\tif ( result == sceMcResNoFormat )\n\t{\n\t\tprintf(\"Memory card %i PopulateFileTables function unNO_ERR_SUCCESSfull. MemoryCard not Formatted  \\n\", cardID);\n\t\t\n\t\tnError = ERR_NOFORMAT;\n\t\treturn nError;\n\t}\n\t\n\tif ( result == sceMcResNoEntry )\n\t{\n\t\tprintf(\"Memory card %i  PopulateFileTables function unNO_ERR_SUCCESSfull. Path does not exist  \\n\", cardID);\n\t\t\n\t\tnError = ERR_FILETABLENOENTRY;\n\t\treturn nError;\n\t}\n\t\n\tprintf(\"Memory card %i not Present\\n\", cardID);\n\t\t\n\tnError = ERR_NONE;\n\treturn nError;\n#else\n\tchar path[512];\n\tsprintf(path, \"%s\\\\%s\\\\%s\", PCCardsPath, PCCardDir[cardID], Cards[cardID].dir);\n\t\n\tmemset(Cards[cardID].table, 0, sizeof(Cards[cardID].table));\n\tWIN32_FIND_DATA fd; HANDLE hFind; int32 num = 0;\n\tif ( (hFind = FindFirstFile(path, &fd)) == INVALID_HANDLE_VALUE )\n\t{\n\t\tnError = NO_ERR_SUCCESS;\n\t\treturn ERR_NOROOTDIR;\n\t}\n\tdo\n\t{\n\t\tSYSTEMTIME st;\n\t\tFileTimeToSystemTime(&fd.ftCreationTime, &st);\n\t\tCards[cardID].table[num]._Create.Sec = st.wSecond;Cards[cardID].table[num]._Create.Min = st.wMinute;Cards[cardID].table[num]._Create.Hour = st.wHour;Cards[cardID].table[num]._Create.Day = st.wDay;Cards[cardID].table[num]._Create.Month = st.wMonth;Cards[cardID].table[num]._Create.Year = st.wYear;\n\t\tFileTimeToSystemTime(&fd.ftLastWriteTime, &st);\n\t\tCards[cardID].table[num]._Modify.Sec = st.wSecond;Cards[cardID].table[num]._Modify.Min = st.wMinute;Cards[cardID].table[num]._Modify.Hour = st.wHour;Cards[cardID].table[num]._Modify.Day = st.wDay;Cards[cardID].table[num]._Modify.Month = st.wMonth;Cards[cardID].table[num]._Modify.Year = st.wYear;\n\t\tCards[cardID].table[num].FileSizeByte = fd.nFileSizeLow;\n\t\tstrncpy((char *)Cards[cardID].table[num].EntryName, fd.cFileName, sizeof(Cards[cardID].table[num].EntryName) - 1);\n\t\tnum++;\n\t} while( FindNextFile(hFind, &fd) && num < ARRAY_SIZE(Cards[cardID].table) );\n\tFindClose(hFind);\n\t\n\tif ( num == 0 )\n\t{\n\t\tnError = NO_ERR_SUCCESS;\n\t\treturn ERR_NOROOTDIR;\n\t}\n\t\n\t//todo errors\n\t\n\tprintf(\"Memory card %i present PopulateFileTables function NO_ERR_SUCCESSfull \\n\", cardID);\n\t\n\tnError = NO_ERR_SUCCESS;\n\treturn nError;\n#endif\n}\n\nint32\nCMemoryCard::FillFirstFileWithGuff(int32 cardID)\n{\n\tCTimer::Stop();\n\t\n\tchar buff[80];\n\tstrncpy(buff, Cards[cardID].dir+1, sizeof(buff) - 1);\n\t\n\tint32 file = CreateMemCardFileReadWrite(Cards[cardID].port, buff);\n\t\n\tif ( nError != NO_ERR_SUCCESS )\n\t\treturn RES_FAILED;\n\t\n\tconst int32 kBlockSize = GUFF_FILE_SIZE / 3;\n\t\n\twork_buff[kBlockSize-1] = 5;\n\tWritetoMemCard(file, work_buff, kBlockSize);\n\tWritetoMemCard(file, work_buff, kBlockSize);\n\tWritetoMemCard(file, work_buff, kBlockSize);\n\t\n\tif ( nError != NO_ERR_SUCCESS )\n\t\treturn RES_FAILED;\n\t\n\tCloseMemCardFile(file);\n\t\n\tif ( nError != NO_ERR_SUCCESS )\n\t\treturn RES_FAILED;\n\t\n\treturn RES_SUCCESS;\n}\n\nbool\nCMemoryCard::FindMostRecentFileName(int32 cardID, char *filename)\n{\n\tCDate date1, date2;\n\t\n\tCTimer::Stop();\n\t\n#if defined(PS2)\n\tint cmd = sceMcFuncNoGetDir;\n\t\n\tClearFileTableBuffer(cardID);\n\t\n\twhile ( sceMcGetDir(Cards[cardID].port, 0, \"*\", 0, ARRAY_SIZE(Cards[cardID].table), Cards[cardID].table) != sceMcResSucceed )\n\t\t;\n\t\n\tint result;\n\tsceMcSync(0, &cmd, &result);\n\t\n\tif ( result >= sceMcResSucceed )\n\t{\n\t\tprintf(\"Memory card %i present PopulateFileTables function NO_ERR_SUCCESSfull \\n\", cardID);\n\t\tnError = NO_ERR_SUCCESS;\n\t\t\n\t\tfor ( int32 entry = 7; entry < ARRAY_SIZE(Cards[CARD_ONE].table); entry++ )\n\t\t{\n\t\t\tbool found = false;\n\t\t\t\t\t\t\t\n\t\t\tif (   Cards[CARD_ONE].table[entry]._Modify.Sec   != 0\n\t\t\t\t|| Cards[CARD_ONE].table[entry]._Modify.Min   != 0\n\t\t\t\t|| Cards[CARD_ONE].table[entry]._Modify.Hour  != 0\n\t\t\t\t|| Cards[CARD_ONE].table[entry]._Modify.Day   != 0\n\t\t\t\t|| Cards[CARD_ONE].table[entry]._Modify.Month != 0\n\t\t\t\t|| Cards[CARD_ONE].table[entry]._Modify.Year  != 0 )\n\t\t\t{\n\t\t\t\tdate1.m_nSecond = Cards[CARD_ONE].table[entry]._Modify.Sec;\n\t\t\t\tdate1.m_nMinute = Cards[CARD_ONE].table[entry]._Modify.Min;\n\t\t\t\tdate1.m_nHour   = Cards[CARD_ONE].table[entry]._Modify.Hour; \n\t\t\t\tdate1.m_nDay    = Cards[CARD_ONE].table[entry]._Modify.Day;\n\t\t\t\tdate1.m_nMonth  = Cards[CARD_ONE].table[entry]._Modify.Month;\n\t\t\t\tdate1.m_nYear   = Cards[CARD_ONE].table[entry]._Modify.Year;\n\t\t\t\t\n\t\t\t\tif ( Cards[CARD_ONE].table[entry].FileSizeByte != 0\n\t\t\t\t\t&& Cards[CARD_ONE].table[entry].AttrFile & sceMcFileAttrClosed\n\t\t\t\t\t&& Cards[CARD_ONE].table[entry].FileSizeByte >= SAVE_FILE_SIZE )\n\t\t\t\t{\n\t\t\t\t\tfound = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\tif (   Cards[CARD_ONE].table[entry]._Create.Sec   != 0\n\t\t\t\t|| Cards[CARD_ONE].table[entry]._Create.Min   != 0\n\t\t\t\t|| Cards[CARD_ONE].table[entry]._Create.Hour  != 0\n\t\t\t\t|| Cards[CARD_ONE].table[entry]._Create.Day   != 0\n\t\t\t\t|| Cards[CARD_ONE].table[entry]._Create.Month != 0\n\t\t\t\t|| Cards[CARD_ONE].table[entry]._Create.Year  != 0 )\n\t\t\t{\n\t\t\t\tdate1.m_nSecond = Cards[CARD_ONE].table[entry]._Create.Sec;\n\t\t\t\tdate1.m_nMinute = Cards[CARD_ONE].table[entry]._Create.Min;\n\t\t\t\tdate1.m_nHour   = Cards[CARD_ONE].table[entry]._Create.Hour; \n\t\t\t\tdate1.m_nDay    = Cards[CARD_ONE].table[entry]._Create.Day;\n\t\t\t\tdate1.m_nMonth  = Cards[CARD_ONE].table[entry]._Create.Month;\n\t\t\t\tdate1.m_nYear   = Cards[CARD_ONE].table[entry]._Create.Year;\n\t\t\t\t\n\t\t\t\tif ( Cards[CARD_ONE].table[entry].FileSizeByte != 0\n\t\t\t\t\t&& Cards[CARD_ONE].table[entry].AttrFile & sceMcFileAttrClosed\n\t\t\t\t\t&& Cards[CARD_ONE].table[entry].FileSizeByte >= SAVE_FILE_SIZE )\n\t\t\t\t{\n\t\t\t\t\tfound = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tif ( found )\n\t\t\t{\n\t\t\t\tint32 d;\n\t\t\t\tif ( date1 > date2 )      d = 1;\n\t\t\t\telse if ( date1 < date2 ) d = 2;\n\t\t\t\telse                      d = 0;\n\t\t\t\t\n\t\t\t\tif ( d == 1 )\n\t\t\t\t{\n\t\t\t\t\tchar *entryname = (char *)Cards[CARD_ONE].table[entry].EntryName;\n\t\t\t\t\t\n\t\t\t\t\tdate2 = date1;\n\t\t\t\t\tstrncpy(filename, entryname, 28);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tint32 d;\n\t\t\t\t\tif ( date1 > date2 )      d = 1;\n\t\t\t\t\telse if ( date1 < date2 ) d = 2;\n\t\t\t\t\telse                      d = 0;\n\t\t\t\t\t\n\t\t\t\t\tif ( d == 0 )\n\t\t\t\t\t{\n\t\t\t\t\t\tchar *entryname = (char *)Cards[CARD_ONE].table[entry].EntryName;\n\t\t\t\t\t\tdate2 = date1;\n\t\t\t\t\t\tstrncpy(filename, entryname, 28);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t\n\t\tif (   date2.m_nSecond != 0\n\t\t\t|| date2.m_nMinute != 0\n\t\t\t|| date2.m_nHour   != 0\n\t\t\t|| date2.m_nDay    != 0\n\t\t\t|| date2.m_nMonth  != 0\n\t\t\t|| date2.m_nYear   != 0 )\n\t\t{\n\t\t\treturn true;\n\t\t}\n\t\t\n\t\treturn false;\n\t}\n\t\n\tif ( result == sceMcResNoFormat )\n\t{\n\t\tprintf(\"Memory card %i PopulateFileTables function unNO_ERR_SUCCESSfull. MemoryCard not Formatted  \\n\", cardID);\n\t\tnError = ERR_NOFORMAT;\n\t\treturn false;\n\t}\n\t\n\tif ( result == sceMcResNoEntry )\n\t{\n\t\tprintf(\"Memory card %i  PopulateFileTables function unNO_ERR_SUCCESSfull. Path does not exist  \\n\", cardID);\n\t\tnError = ERR_FILETABLENOENTRY;\n\t\treturn false;\n\t}\n\t\n\tprintf(\"Memory card %i not Present\\n\", cardID);\n\tnError = ERR_NONE;\n\treturn false;\n#else\n\tClearFileTableBuffer(cardID);\n\t\n\tchar path[512];\n\tsprintf(path, \"%s\\\\%s\\\\%s\\\\*\", PCCardsPath, PCCardDir[cardID], CardCurDir[cardID]);\n\t\n\tmemset(Cards[cardID].table, 0, sizeof(Cards[cardID].table));\n\tWIN32_FIND_DATA fd; HANDLE hFind; int32 num = 0;\n\tif ( (hFind = FindFirstFile(path, &fd)) == INVALID_HANDLE_VALUE )\n\t{\n\t\tprintf(\"Memory card %i not Present\\n\", cardID);\n\t\tnError = ERR_NONE;\n\t\treturn nError;\n\t}\n\tdo\n\t{\n\t\tSYSTEMTIME st;\n\t\tFileTimeToSystemTime(&fd.ftCreationTime, &st);\n\t\tCards[cardID].table[num]._Create.Sec = st.wSecond;Cards[cardID].table[num]._Create.Min = st.wMinute;Cards[cardID].table[num]._Create.Hour = st.wHour;Cards[cardID].table[num]._Create.Day = st.wDay;Cards[cardID].table[num]._Create.Month = st.wMonth;Cards[cardID].table[num]._Create.Year = st.wYear;\n\t\tFileTimeToSystemTime(&fd.ftLastWriteTime, &st);\n\t\tCards[cardID].table[num]._Modify.Sec = st.wSecond;Cards[cardID].table[num]._Modify.Min = st.wMinute;Cards[cardID].table[num]._Modify.Hour = st.wHour;Cards[cardID].table[num]._Modify.Day = st.wDay;Cards[cardID].table[num]._Modify.Month = st.wMonth;Cards[cardID].table[num]._Modify.Year = st.wYear;\n\t\tCards[cardID].table[num].FileSizeByte = fd.nFileSizeLow;\n\t\tstrncpy((char *)Cards[cardID].table[num].EntryName, fd.cFileName, sizeof(Cards[cardID].table[num].EntryName) - 1);\n\t\tnum++;\n\t} while( FindNextFile(hFind, &fd) && num < ARRAY_SIZE(Cards[cardID].table) );\n\tFindClose(hFind);\n\t\n\tif ( num > 0 )\n\t{\n\t\tprintf(\"Memory card %i present PopulateFileTables function NO_ERR_SUCCESSfull \\n\", cardID);\n\t\tnError = NO_ERR_SUCCESS;\n\t\t\n\t\tfor ( int32 entry = 0; entry < ARRAY_SIZE(Cards[CARD_ONE].table); entry++ )\n\t\t{\n\t\t\tbool found = false;\n\t\t\t\t\t\t\t\n\t\t\tif (   Cards[CARD_ONE].table[entry]._Modify.Sec   != 0\n\t\t\t\t|| Cards[CARD_ONE].table[entry]._Modify.Min   != 0\n\t\t\t\t|| Cards[CARD_ONE].table[entry]._Modify.Hour  != 0\n\t\t\t\t|| Cards[CARD_ONE].table[entry]._Modify.Day   != 0\n\t\t\t\t|| Cards[CARD_ONE].table[entry]._Modify.Month != 0\n\t\t\t\t|| Cards[CARD_ONE].table[entry]._Modify.Year  != 0 )\n\t\t\t{\n\t\t\t\tdate1.m_nSecond = Cards[CARD_ONE].table[entry]._Modify.Sec;\n\t\t\t\tdate1.m_nMinute = Cards[CARD_ONE].table[entry]._Modify.Min;\n\t\t\t\tdate1.m_nHour   = Cards[CARD_ONE].table[entry]._Modify.Hour; \n\t\t\t\tdate1.m_nDay    = Cards[CARD_ONE].table[entry]._Modify.Day;\n\t\t\t\tdate1.m_nMonth  = Cards[CARD_ONE].table[entry]._Modify.Month;\n\t\t\t\tdate1.m_nYear   = Cards[CARD_ONE].table[entry]._Modify.Year;\n\t\t\t\t\n\t\t\t\tif ( Cards[CARD_ONE].table[entry].FileSizeByte != 0\n\t\t\t\t\t&& Cards[CARD_ONE].table[entry].FileSizeByte >= SAVE_FILE_SIZE )\n\t\t\t\t{\n\t\t\t\t\tfound = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\tif (   Cards[CARD_ONE].table[entry]._Create.Sec   != 0\n\t\t\t\t|| Cards[CARD_ONE].table[entry]._Create.Min   != 0\n\t\t\t\t|| Cards[CARD_ONE].table[entry]._Create.Hour  != 0\n\t\t\t\t|| Cards[CARD_ONE].table[entry]._Create.Day   != 0\n\t\t\t\t|| Cards[CARD_ONE].table[entry]._Create.Month != 0\n\t\t\t\t|| Cards[CARD_ONE].table[entry]._Create.Year  != 0 )\n\t\t\t{\n\t\t\t\tdate1.m_nSecond = Cards[CARD_ONE].table[entry]._Create.Sec;\n\t\t\t\tdate1.m_nMinute = Cards[CARD_ONE].table[entry]._Create.Min;\n\t\t\t\tdate1.m_nHour   = Cards[CARD_ONE].table[entry]._Create.Hour; \n\t\t\t\tdate1.m_nDay    = Cards[CARD_ONE].table[entry]._Create.Day;\n\t\t\t\tdate1.m_nMonth  = Cards[CARD_ONE].table[entry]._Create.Month;\n\t\t\t\tdate1.m_nYear   = Cards[CARD_ONE].table[entry]._Create.Year;\n\t\t\t\t\n\t\t\t\tif ( Cards[CARD_ONE].table[entry].FileSizeByte != 0\n\t\t\t\t\t&& Cards[CARD_ONE].table[entry].FileSizeByte >= SAVE_FILE_SIZE )\n\t\t\t\t{\n\t\t\t\t\tfound = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tif ( found )\n\t\t\t{\n\t\t\t\tint32 d;\n\t\t\t\tif ( date1 > date2 )      d = 1;\n\t\t\t\telse if ( date1 < date2 ) d = 2;\n\t\t\t\telse                      d = 0;\n\t\t\t\t\n\t\t\t\tif ( d == 1 )\n\t\t\t\t{\n\t\t\t\t\tchar *entryname = (char *)Cards[CARD_ONE].table[entry].EntryName;\n\t\t\t\t\t\n\t\t\t\t\tdate2 = date1;\n\t\t\t\t\tstrncpy(filename, entryname, 28);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tint32 d;\n\t\t\t\t\tif ( date1 > date2 )      d = 1;\n\t\t\t\t\telse if ( date1 < date2 ) d = 2;\n\t\t\t\t\telse                      d = 0;\n\t\t\t\t\t\n\t\t\t\t\tif ( d == 0 )\n\t\t\t\t\t{\n\t\t\t\t\t\tchar *entryname = (char *)Cards[CARD_ONE].table[entry].EntryName;\n\t\t\t\t\t\tdate2 = date1;\n\t\t\t\t\t\tstrncpy(filename, entryname, 28);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t\n\t\tif (   date2.m_nSecond != 0\n\t\t\t|| date2.m_nMinute != 0\n\t\t\t|| date2.m_nHour   != 0\n\t\t\t|| date2.m_nDay    != 0\n\t\t\t|| date2.m_nMonth  != 0\n\t\t\t|| date2.m_nYear   != 0 )\n\t\t{\n\t\t\treturn true;\n\t\t}\n\t\t\n\t\treturn false;\n\t}\n\t\n\t//todo errors\n\t\n\tnError = ERR_NONE;\n\treturn false;\n#endif\n}\n\nvoid\nCMemoryCard::ClearFileTableBuffer(int32 cardID)\n{\n\tfor ( int32 i = 0; i < ARRAY_SIZE(Cards[cardID].table); i++ )\n\t{\n\t\tCards[cardID].table[i].FileSizeByte = 0;\n\t\tstrncpy((char *)Cards[cardID].table[i].EntryName, \" \", sizeof(Cards[cardID].table[i].EntryName) - 1);\n\t}\n}\n\nint32\nCMemoryCard::GetClusterAmountForFileCreation(int32 port)\n{\n#if defined(PS2)\n\tint cmd = sceMcFuncNoEntSpace;\n\tint result = 0;\n\t\n\tCTimer::Stop();\n\t\n\twhile ( sceMcGetEntSpace(port, 0, TheGameRootDirectory) != sceMcResSucceed )\n\t\t;\n\t\n\tsceMcSync(0, &cmd, &result);\n\t\n\tif ( result >= sceMcResSucceed )\n\t{\n\t\tnError = NO_ERR_SUCCESS;\n\t\treturn result;\n\t}\n\t\n\tif ( result == sceMcResNoFormat )\n\t{\n\t\tnError = ERR_NOFORMAT;\n\t\treturn nError;\n\t}\n\t\n\tnError = ERR_NONE;\n\treturn nError;\n#else\n\tCTimer::Stop();\n\tnError = NO_ERR_SUCCESS;\n\treturn 0;\n#endif\n}\n\nbool\nCMemoryCard::DeleteEverythingInGameRoot(int32 cardID)\n{\n\tCTimer::Stop();\n\t\n\tChangeDirectory(CurrentCard, Cards[CurrentCard].dir);\n\t\n\tif ( nError != NO_ERR_SUCCESS )\n\t\treturn false;\n\t\n\tPopulateFileTable(cardID);\n\t\n\tfor ( int32 i = ARRAY_SIZE(Cards[cardID].table) - 1; i >= 0; i--)\n\t\tDeleteMemoryCardFile(cardID, (char *)Cards[cardID].table[i].EntryName);\n\t\n\tChangeDirectory(CurrentCard, \"/\");\n\t\n\tDeleteMemoryCardFile(cardID, Cards[CurrentCard].dir);\n\t\n\tif ( nError != NO_ERR_SUCCESS )\n\t\treturn false;\n\t\n\treturn true;\n}\n\nint32\nCMemoryCard::CheckDataNotCorrupt(char *filename)\n{\n\tCheckSum = 0;\n\t\n\tint32 lang = 0;\n\tint32 level = 0;\n\t\n\tLastBlockSize = 0;\n\t\n\tchar buf[100*4];\n\t\n\tfor ( int32 i = 0; i < sizeof(buf); i++ )\n\t\tbuf[i] = '\\0';\n\t\n\tstrncpy(buf, Cards[CurrentCard].dir, sizeof(buf) - 1);\n\tstrncat(buf, \"/\", sizeof(buf) - 1);\n\tstrcat (buf, filename);\n\t\n\tChangeDirectory(CurrentCard, Cards[CurrentCard].dir);\n\t\n\tif ( nError != NO_ERR_SUCCESS )\n\t\treturn RES_FAILED;\n\t\n\tint32 file = OpenMemCardFileForReading(CurrentCard, buf);\n\t\n\tif ( nError != NO_ERR_SUCCESS )\n\t\treturn RES_FAILED;\n\t\n\tint32 bytes_processed = 0;\n\tint32 blocknum = 0; \t\n\tint32 lastblocksize;\n\t\n\twhile ( SAVE_FILE_SIZE - sizeof(int32) > bytes_processed && blocknum < 8 )\n\t{\n\t\tint32 size;\n\t\t\n\t\tReadFromMemCard(file, &size, sizeof(size));\n\t\t\n\t\tif ( nError != NO_ERR_SUCCESS )\n\t\t\treturn RES_FAILED;\n\t\t\n\t\tlastblocksize = ReadFromMemCard(file, work_buff, align4bytes(size));\n\t\t\n\t\tif ( nError != NO_ERR_SUCCESS )\n\t\t\treturn RES_FAILED;\n\t\t\n\t\tuint8 sizebuff[4];\n\t\tmemcpy(sizebuff, &size, sizeof(size));\n\t\t\n\t\tfor ( int32 i = 0; i < ARRAY_SIZE(sizebuff); i++ )\n\t\t\tCheckSum += sizebuff[i];\n\t\t\n\t\tuint8 *pWork_buf = work_buff;\n\t\tfor ( int32 i = 0; i < lastblocksize; i++ )\n\t\t{\n\t\t\tCheckSum += *pWork_buf++;\n\t\t\tbytes_processed++;\n\t\t}\n\t\t\n\t\tif ( blocknum == 0 )\n\t\t{\n\t\t\tuint8 *pBuf = work_buff + sizeof(uint32);\n\t\t\tReadDataFromBufferPointer(pBuf, level);\n\t\t\tpBuf += sizeof(uint32) * 29;\n\t\t\tReadDataFromBufferPointer(pBuf, lang);\n\t\t}\n\t\t\n\t\tblocknum++;\n\t}\n\t\n\tint32 checkSum;\n\tReadFromMemCard(file, &checkSum, sizeof(checkSum));\n\tCloseMemCardFile(file);\n\t\n\tif ( nError != NO_ERR_SUCCESS )\n\t\treturn RES_FAILED;\n\t\n\tif ( CheckSum == checkSum )\n\t{\n\t\tm_LevelToLoad    = level;\n\t\tm_LanguageToLoad = lang;\n\t\tLastBlockSize    = lastblocksize;\n\t\t\n\t\treturn RES_SUCCESS;\n\t}\n\t\n\tnError = ERR_DATACORRUPTED;\n\treturn RES_FAILED;\n}\n\nint32\nCMemoryCard::GetLanguageToLoad(void)\n{\n\treturn m_LanguageToLoad;\n}\n\nint32\nCMemoryCard::GetLevelToLoad(void)\n{\n\treturn m_LevelToLoad;\n}\n\nbool\nCMemoryCard::CreateGameDirectoryFromScratch(int32 cardID)\n{\n\tTheMemoryCard.PopulateCardFlags(cardID, false, false, true, true);\n\t\n\tint32 err = RES_SUCCESS;\n\t\n\tif ( nError != NO_ERR_SUCCESS )\n\t\treturn false;\n\t\n\tif ( Cards[CurrentCard].free < 500 )\n\t{\n\t\tCTimer::Update();\n\t\tuint32 startTime = CTimer::GetTimeInMillisecondsPauseMode();\n\t\t\n\t\twhile ( CTimer::GetTimeInMillisecondsPauseMode()-startTime < 1250 )\n\t\t{\n\t\t\tfor ( int32 i = 0; i < 1000; i++ )\n\t\t\t\tpowf(3.33f, 3.444f);\n\t\t\t\n\t\t\tCTimer::Update();\n\t\t}\n\t\t\t\n\t\tnError = ERR_DIRFULLDEVICE;\n\t\treturn false;\n\t}\n\t\n\tTheMemoryCard.ChangeDirectory(CARD_ONE, \"/\");\n\t\n\tif ( nError != NO_ERR_SUCCESS )\n\t\treturn false;\n\n\tint32 r = LookForRootDirectory(CARD_ONE);\n\t\n\tif ( nError != NO_ERR_SUCCESS )\n\t\treturn false;\n\t\n\tif ( r == ERR_NOROOTDIR )\n\t{\n\t\tCreateRootDirectory(CARD_ONE);\n\t\t\n\t\tif ( nError != NO_ERR_SUCCESS )\n\t\t\tDeleteEverythingInGameRoot(CARD_ONE);\n\t}\n\t\n\tChangeDirectory(CARD_ONE, Cards[CARD_ONE].dir);\n\t\n\tif ( nError != NO_ERR_SUCCESS )\n\t\treturn false;\n\t\n\tPopulateFileTable(CARD_ONE);\n\t\n\tif ( nError != NO_ERR_SUCCESS )\n\t\treturn false;\n\t\n#if defined(PS2)\n\tbool entryExist;\n\t\n\tentryExist = false;\n\tif ( TheMemoryCard.PopulateFileTable(CARD_ONE) == NO_ERR_SUCCESS )\n\t{\n\t\tfor ( int32 i = 0; i < ARRAY_SIZE(TheMemoryCard.Cards[CARD_ONE].table); i++ )\n\t\t{\n\t\t\tif ( !strcmp(\"icon.sys\", (char *)TheMemoryCard.Cards[CARD_ONE].table[i].EntryName) )\n\t\t\t{\n\t\t\t\tentryExist = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\t\n\tif ( !entryExist )\n\t\terr = RES_FAILED;\n\t\n\tif ( nError != NO_ERR_SUCCESS )\n\t\treturn false;\n\t\n\tentryExist = false;\n\tif ( TheMemoryCard.PopulateFileTable(CARD_ONE) == NO_ERR_SUCCESS )\n\t{\n\t\tfor ( int32 i = 0; i < ARRAY_SIZE(TheMemoryCard.Cards[CARD_ONE].table); i++ )\n\t\t{\n\t\t\tif ( !strcmp(icon_one, (char *)TheMemoryCard.Cards[CARD_ONE].table[i].EntryName) )\n\t\t\t{\n\t\t\t\tentryExist = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\t\n\tif ( !entryExist )\n\t\terr = RES_FAILED;\n\t\n\tif ( nError != NO_ERR_SUCCESS )\n\t\treturn false;\n\t\n\tentryExist = false;\n\tif ( TheMemoryCard.PopulateFileTable(CARD_ONE) == NO_ERR_SUCCESS )\n\t{\n\t\tfor ( int32 i = 0; i < ARRAY_SIZE(TheMemoryCard.Cards[CARD_ONE].table); i++ )\n\t\t{\n\t\t\tif ( !strcmp(icon_two, (char *)TheMemoryCard.Cards[CARD_ONE].table[i].EntryName) )\n\t\t\t{\n\t\t\t\tentryExist = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\t\n\tif ( !entryExist )\n\t\terr = RES_FAILED;\n\t\n\tif ( nError != NO_ERR_SUCCESS )\n\t\treturn false;\n\t\n\tentryExist = false;\n\tif ( TheMemoryCard.PopulateFileTable(CARD_ONE) == NO_ERR_SUCCESS )\n\t{\n\t\tfor ( int32 i = 0; i < ARRAY_SIZE(TheMemoryCard.Cards[CARD_ONE].table); i++ )\n\t\t{\n\t\t\tif ( !strcmp(icon_three, (char *)TheMemoryCard.Cards[CARD_ONE].table[i].EntryName) )\n\t\t\t{\n\t\t\t\tentryExist = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\t\n\tif ( !entryExist )\n\t\terr = RES_FAILED;\n\t\n\tif ( nError != NO_ERR_SUCCESS )\n\t\treturn false;\n\t\n\tif ( err != RES_SUCCESS )\n\t{\n\t\tint32 icon = CreateIconFiles(CARD_ONE, icon_one, icon_two, icon_three);\n\t\t\n\t\tif ( nError != NO_ERR_SUCCESS )\n\t\t\treturn false;\n\t\t\n\t\tif ( icon != RES_SUCCESS )\n\t\t\tDeleteEverythingInGameRoot(CARD_ONE);\n\t}\n#endif\n\t\n\tint32 guff = FillFirstFileWithGuff(CARD_ONE);\n\t\n\tif ( nError != NO_ERR_SUCCESS )\n\t\treturn false;\n\t\n\tif ( guff == RES_SUCCESS )\n\t{\n\t\tprintf(\"Game Default directory present\");\n\t\treturn true;\n\t}\n\t\n\tDeleteEverythingInGameRoot(CARD_ONE);\n\t\n\treturn false;\n}\n\nbool\nCMemoryCard::CheckGameDirectoryThere(int32 cardID)\n{\n\tTheMemoryCard.PopulateCardFlags(cardID, false, false, true, true);\n\t\n\tif ( TheMemoryCard.nError != NO_ERR_SUCCESS )\n\t\treturn false;\n\t\n\tTheMemoryCard.ChangeDirectory(cardID, Cards[CARD_ONE].dir);\n\t\n\tif ( TheMemoryCard.nError != NO_ERR_SUCCESS )\n\t\treturn false;\n\t\n\tPopulateFileTable(cardID);\n\t\n\tif ( TheMemoryCard.nError != NO_ERR_SUCCESS )\n\t\treturn false;\n\t\n\n\tbool entryExist;\n\t\n#if defined(PS2)\n\tentryExist = false;\n\tif ( TheMemoryCard.PopulateFileTable(cardID) == NO_ERR_SUCCESS )\n\t{\n\t\tfor ( int32 i = 0; i < ARRAY_SIZE(TheMemoryCard.Cards[cardID].table); i++ )\n\t\t{\n\t\t\tif ( !strcmp(\"icon.sys\", (char *)TheMemoryCard.Cards[cardID].table[i].EntryName) )\n\t\t\t{\n\t\t\t\tentryExist = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\t\n\tif ( !entryExist )\n\t\treturn false;\n\t\n\tentryExist = false;\n\tif ( TheMemoryCard.PopulateFileTable(cardID) == NO_ERR_SUCCESS )\n\t{\n\t\tfor ( int32 i = 0; i < ARRAY_SIZE(TheMemoryCard.Cards[cardID].table); i++ )\n\t\t{\n\t\t\tif ( !strcmp(icon_one, (char *)TheMemoryCard.Cards[cardID].table[i].EntryName) )\n\t\t\t{\n\t\t\t\tentryExist = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\t\n\tif ( !entryExist )\n\t\treturn false;\n\t\n\tentryExist = false;\n\tif ( TheMemoryCard.PopulateFileTable(cardID) == NO_ERR_SUCCESS )\n\t{\n\t\tfor ( int32 i = 0; i < ARRAY_SIZE(TheMemoryCard.Cards[cardID].table); i++ )\n\t\t{\n\t\t\tif ( !strcmp(icon_two, (char *)TheMemoryCard.Cards[cardID].table[i].EntryName) )\n\t\t\t{\n\t\t\t\tentryExist = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\t\n\tif ( !entryExist )\n\t\treturn false;\n\t\n\tentryExist = false;\n\tif ( TheMemoryCard.PopulateFileTable(cardID) == NO_ERR_SUCCESS )\n\t{\n\t\tfor ( int32 i = 0; i < ARRAY_SIZE(TheMemoryCard.Cards[cardID].table); i++ )\n\t\t{\n\t\t\tif ( !strcmp(icon_three, (char *)TheMemoryCard.Cards[cardID].table[i].EntryName) )\n\t\t\t{\n\t\t\t\tentryExist = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\t\n\tif ( !entryExist )\n\t\treturn false;\n#endif\n\t\n\tchar buff[80];\n\t\n\tstrncpy(buff, Cards[cardID].dir+1, sizeof(buff) - 1);\n\n\n\tentryExist = false;\n\tif ( TheMemoryCard.PopulateFileTable(cardID) == NO_ERR_SUCCESS )\n\t{\n\t\tfor ( int32 i = 0; i < ARRAY_SIZE(TheMemoryCard.Cards[cardID].table); i++ )\n\t\t{\n\t\t\tif ( !strcmp(buff, (char *)TheMemoryCard.Cards[cardID].table[i].EntryName) )\n\t\t\t{\n\t\t\t\tentryExist = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\t\n\tif ( !entryExist )\n\t\treturn false;\n\t\n\tprintf(\"Game directory present\");\n\t\n\treturn true;\n}\n\nvoid\nCMemoryCard::PopulateSlotInfo(int32 cardID)\n{\n\tCTimer::Stop();\n\t\n\tfor ( int32 i = 0; i < MAX_SLOTS; i++ )\n\t{\n\t\tSlots[i] = SLOT_NOTPRESENT;\n\t\t\n\t\tfor ( int32 j = 0; j < ARRAY_SIZE(SlotFileName[i]); j++ )\n\t\t\tSlotFileName[i][j] = L'\\0';\n\t\t\n\t\tfor ( int32 j = 0; j < ARRAY_SIZE(SlotSaveDate[i]); j++ )\n\t\t\tSlotSaveDate[i][j] = L'\\0';\n\t\t\n\t\tUnicodeStrcpy(SlotSaveDate[i], TheText.Get(\"DEFDT\"));\n\t}\n\t\n\tTheMemoryCard.PopulateCardFlags(cardID, false, false, true, true);\n\t\n\tif ( nError != NO_ERR_SUCCESS )\n\t\treturn;\n\t\n\tTheMemoryCard.ChangeDirectory(cardID, TheMemoryCard.Cards[CARD_ONE].dir);\n\t\n\tif ( nError != NO_ERR_SUCCESS && nError != ERR_DIRNOENTRY )\n\t\treturn;\n\t\n\tPopulateFileTable(cardID);\n\t\n\tif ( nError != NO_ERR_SUCCESS && nError != ERR_FILETABLENOENTRY )\n\t\treturn;\n\t\n\tfor ( int32 slot = 0; slot < MAX_SLOTS; slot++ )\n\t{\n#if defined(PS2)\n\t\tfor ( int32 entry = 7; entry < ARRAY_SIZE(Cards[cardID].table); entry++ )\n#else\n\t\tfor ( int32 entry = 0; entry < ARRAY_SIZE(Cards[cardID].table); entry++ )\n#endif\n\t\t{\n\t\t\tif ( TheMemoryCard.Cards[CARD_ONE].table[entry].FileSizeByte != 0 )\n\t\t\t{\n\t\t\t\tchar slotnum[30];\n\t\t\t\tchar slotname[30];\n\t\t\t\tchar slotdate[30];\n\t\t\t\t\t\t\n\t\t\t\tif (\n#if defined(PS2)\n\t\t\t\t\tTheMemoryCard.Cards[CARD_ONE].table[entry].AttrFile & sceMcFileAttrClosed &&\n#endif\n\t\t\t\t\tTheMemoryCard.Cards[CARD_ONE].table[entry].FileSizeByte >= SAVE_FILE_SIZE )\n\t\t\t\t{\n\t\t\t\t\tchar *entryname = (char *)Cards[cardID].table[entry].EntryName;\n\t\t\t\t\t\n\t\t\t\t\tbool bFound = false;\n#if defined(PS2)\n\t\t\t\t\tfor ( int32 i = 7; i < ARRAY_SIZE(Cards[cardID].table) && !bFound; i++ )\n#else\n\t\t\t\t\tfor ( int32 i = 0; i < ARRAY_SIZE(Cards[cardID].table) && !bFound; i++ )\n#endif\n\t\t\t\t\t{\n\t\t\t\t\t\tsprintf(slotnum, \"%i \", slot+1);\n\n\t\t\t\t\t\tfor ( int32 j = 0; j < sizeof(slotname); j++ )\n\t\t\t\t\t\t\tslotname[j] = '\\0';\n\t\t\t\t\t\t\t\n\t\t\t\t\t\tstrncat(slotname, slotnum, sizeof(slotnum)-1);\n\t\t\t\t\t\t\n\t\t\t\t\t\tif ( !strncmp(slotname, entryname, 1) )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tbFound = true;\n\n\t\t\t\t\t\t\tSlots[slot] = SLOT_PRESENT;\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tAsciiToUnicode(entryname, SlotFileName[slot]);\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tint32 sec   = Cards[CARD_ONE].table[entry]._Create.Sec;\n\t\t\t\t\t\t\tint32 month = Cards[CARD_ONE].table[entry]._Create.Month;\n\t\t\t\t\t\t\tint32 year  = Cards[CARD_ONE].table[entry]._Create.Year;\n\t\t\t\t\t\t\tint32 min   = Cards[CARD_ONE].table[entry]._Create.Min;\n\t\t\t\t\t\t\tint32 hour  = Cards[CARD_ONE].table[entry]._Create.Hour;\n\t\t\t\t\t\t\tint32 day   = Cards[CARD_ONE].table[entry]._Create.Day;\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tfor ( int32 j = 0; j < ARRAY_SIZE(SlotSaveDate[slot]); j++ )\n\t\t\t\t\t\t\t\tSlotSaveDate[slot][j] = L'\\0';\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tfor ( int32 j = 0; j < ARRAY_SIZE(slotdate); j++ )\n\t\t\t\t\t\t\t\tslotdate[j] = '\\0';\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tchar *monthstr;\n\t\t\t\t\t\t\tswitch ( month )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tcase  1: monthstr = UnicodeToAsciiForMemoryCard(TheText.Get(\"JAN\")); break;\n\t\t\t\t\t\t\t\tcase  2: monthstr = UnicodeToAsciiForMemoryCard(TheText.Get(\"FEB\")); break;\n\t\t\t\t\t\t\t\tcase  3: monthstr = UnicodeToAsciiForMemoryCard(TheText.Get(\"MAR\")); break;\n\t\t\t\t\t\t\t\tcase  4: monthstr = UnicodeToAsciiForMemoryCard(TheText.Get(\"APR\")); break;\n\t\t\t\t\t\t\t\tcase  5: monthstr = UnicodeToAsciiForMemoryCard(TheText.Get(\"MAY\")); break;\n\t\t\t\t\t\t\t\tcase  6: monthstr = UnicodeToAsciiForMemoryCard(TheText.Get(\"JUN\")); break;\n\t\t\t\t\t\t\t\tcase  7: monthstr = UnicodeToAsciiForMemoryCard(TheText.Get(\"JUL\")); break;\n\t\t\t\t\t\t\t\tcase  8: monthstr = UnicodeToAsciiForMemoryCard(TheText.Get(\"AUG\")); break;\n\t\t\t\t\t\t\t\tcase  9: monthstr = UnicodeToAsciiForMemoryCard(TheText.Get(\"SEP\")); break;\n\t\t\t\t\t\t\t\tcase 10: monthstr = UnicodeToAsciiForMemoryCard(TheText.Get(\"OCT\")); break;\n\t\t\t\t\t\t\t\tcase 11: monthstr = UnicodeToAsciiForMemoryCard(TheText.Get(\"NOV\")); break;\n\t\t\t\t\t\t\t\tcase 12: monthstr = UnicodeToAsciiForMemoryCard(TheText.Get(\"DEC\")); break;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tsprintf(slotdate, \"%02d %s %04d %02d:%02d:%02d\", day, monthstr, year, hour, min, sec);\n\t\t\t\t\t\t\tAsciiToUnicode(slotdate, SlotSaveDate[slot]);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tchar *entryname = (char *)Cards[cardID].table[entry].EntryName;\n\t\t\t\t\t\n\t\t\t\t\tbool bFound = false;\n#if defined(PS2)\n\t\t\t\t\tfor ( int32 i = 7; i < ARRAY_SIZE(Cards[cardID].table) && !bFound; i++ ) // again ...\n#else\n\t\t\t\t\tfor ( int32 i = 0; i < ARRAY_SIZE(Cards[cardID].table) && !bFound; i++ ) // again ...\n#endif\n\t\t\t\t\t{\n\t\t\t\t\t\tsprintf(slotnum, \"%i \", slot+1);\n\t\t\t\t\t\t\n\t\t\t\t\t\tfor ( int32 j = 0; j < sizeof(slotname); j++ )\n\t\t\t\t\t\t\tslotname[j] = '\\0';\n\t\t\t\t\t\t\n\t\t\t\t\t\tstrncat(slotname, slotnum, sizeof(slotnum)-1);\n\t\t\t\t\t\t\n\t\t\t\t\t\tif ( !strncmp(slotname, entryname, 1) )\n\t\t\t\t\t\t{\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tbFound = true;\n\n\t\t\t\t\t\t\tSlots[slot] = SLOT_CORRUPTED;\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tAsciiToUnicode(entryname, SlotFileName[slot]);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\t\n\tnError = NO_ERR_SUCCESS;\n\treturn;\n}\n\nint32\nCMemoryCard::GetInfoOnSpecificSlot(int32 slotID)\n{\n\treturn Slots[slotID];\n}\n\nwchar *\nCMemoryCard::GetDateAndTimeOfSavedGame(int32 slotID)\n{\n\treturn SlotSaveDate[slotID];\n}\n\nint32\nCMemoryCard::CheckCardStateAtGameStartUp(int32 cardID)\n{\n\tCheckCardInserted(cardID);\n\tif ( nError == ERR_NOFORMAT )\n\t\treturn MCSTATE_OK;\n\tif ( nError == ERR_NONE )\n\t\treturn MCSTATE_NOCARD;\n\t\n\tif ( !CheckGameDirectoryThere(cardID) )\n\t{\n\t\tif ( nError == ERR_NONE )\n\t\t\treturn MCSTATE_NOCARD;\n\t\t\n\t\tDeleteEverythingInGameRoot(cardID);\n\t\tif ( nError == ERR_NONE )\n\t\t\treturn MCSTATE_NOCARD;\n\t\t\n\t\tTheMemoryCard.PopulateCardFlags(cardID, false, false, true, true);\n\t\tif ( nError == ERR_NONE )\n\t\t\treturn MCSTATE_NOCARD;\n\t\t\n\t\tif ( Cards[CurrentCard].free < 500 )\n\t\t\treturn MCSTATE_NEED_500KB;\n\t\t\n\t\treturn MCSTATE_OK;\n\t}\n\t\n\tTheMemoryCard.CheckCardInserted(CARD_ONE);\n\t\n\tif ( nError == NO_ERR_SUCCESS )\n\t{\n\t\tif ( TheMemoryCard.ChangeDirectory(CARD_ONE, Cards[CARD_ONE].dir) != ERR_NONE )\n\t\t{\n\t\t\tif ( TheMemoryCard.FindMostRecentFileName(CARD_ONE, MostRecentFile) == true )\n\t\t\t{\n\t\t\t\tif ( TheMemoryCard.CheckDataNotCorrupt(MostRecentFile) == RES_FAILED )\n\t\t\t\t{\n\t\t\t\t\tTheMemoryCard.PopulateCardFlags(cardID, false, false, true, true);\n\t\t\t\t\tif ( Cards[CurrentCard].free < 200 )\n\t\t\t\t\t\treturn MCSTATE_NEED_200KB;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tTheMemoryCard.PopulateCardFlags(cardID, false, false, true, true);\n\t\t\t\tif ( Cards[CurrentCard].free < 200 )\n\t\t\t\t\treturn MCSTATE_NEED_200KB;\n\t\t\t}\n\t\t}\n\t}\n\t\n\tif ( TheMemoryCard.CheckCardInserted(CARD_ONE) != NO_ERR_SUCCESS )\n\t\treturn MCSTATE_NOCARD;\n\t\n\treturn MCSTATE_OK;\n}\n\nvoid\nCMemoryCard::SaveSlot(int32 slotID)\n{\n\tbool bSave = true;\n\t\n\tfor ( int32 j = 0; j < sizeof(ValidSaveName); j++ )\n\t\tValidSaveName[j] = '\\0';\n\t\t\t\t\t\t\n\tchar buff[100];\n\t\n\tsprintf(buff, \"%i \", slotID+1);\n\tstrncat(ValidSaveName, buff, sizeof(ValidSaveName) - 1);\n\t\n\tif ( CStats::LastMissionPassedName[0] != '\\0' )\n\t{\n\t\tchar mission[100];\n\t\t\n\t\tstrcpy(mission, UnicodeToAsciiForMemoryCard(TheText.Get(CStats::LastMissionPassedName)));\n\t\t\n#ifdef FIX_BUGS\n\t\tstrncat(ValidSaveName, mission, sizeof(ValidSaveName)-1);\n#else\n\t\tstrncat(ValidSaveName, mission, 21);\n\t\tstrncat(ValidSaveName, \"...\", strlen(\"...\"));\n#endif\n\t}\n\t\n\tif ( !CheckGameDirectoryThere(CARD_ONE) )\n\t{\n\t\tDeleteEverythingInGameRoot(CARD_ONE);\n\t\tbSave = CreateGameDirectoryFromScratch(CARD_ONE);\n\t}\n\t\n\tif ( bSave )\n\t{\n\t\tif ( Slots[slotID] == SLOT_PRESENT )\n\t\t{\n\t\t\tTheMemoryCard.ChangeDirectory(CARD_ONE, Cards[CurrentCard].dir);\n\t\t\tif ( nError == NO_ERR_SUCCESS )\n\t\t\t\tTheMemoryCard.DeleteMemoryCardFile(CARD_ONE, UnicodeToAsciiForMemoryCard(SlotFileName[slotID]));\n\t\t}\n\t\t\n\t\tSaveGame();\n\t}\n\t\n\tCTimer::Stop();\n\tCStreaming::FlushRequestList();\n\tCStreaming::DeleteRwObjectsAfterDeath(FindPlayerPed()->GetPosition());\n\tCStreaming::RemoveUnusedModelsInLoadedList();\n\tCGame::DrasticTidyUpMemory(false);\n\tCTimer::Update();\n}\n\nvoid\nCMemoryCard::DeleteSlot(int32 slotID)\n{\n\tTheMemoryCard.ChangeDirectory(CARD_ONE, Cards[CurrentCard].dir);\n\t\n\tif ( nError == NO_ERR_SUCCESS )\n\t\tTheMemoryCard.DeleteMemoryCardFile(CARD_ONE, UnicodeToAsciiForMemoryCard(SlotFileName[slotID]));\n}\n\nvoid\nCMemoryCard::LoadSlotToBuffer(int32 slotID)\n{\n\tCStreaming::DeleteAllRwObjects();\n\t\n\tstrcpy(LoadFileName, UnicodeToAsciiForMemoryCard(SlotFileName[slotID]));\n\t\n\tTheMemoryCard.ChangeDirectory(CARD_ONE, Cards[CurrentCard].dir);\n\t\n\tif ( nError == NO_ERR_SUCCESS )\n\t\tTheMemoryCard.CheckDataNotCorrupt(LoadFileName);\n}\n\nwchar *\nCMemoryCard::GetNameOfSavedGame(int32 slotID)\n{\n\treturn SlotFileName[slotID];\n}\n\nint32\nCMemoryCard::DoClassSaveRoutine(int32 file, uint8 *data, uint32 size)\n{\n\tWritetoMemCard(file, &size, sizeof(size));\n\t\n\tif ( nError != NO_ERR_SUCCESS )\n\t{\n\t\tstrncpy(SaveFileNameJustSaved, ValidSaveName, sizeof(ValidSaveName) - 1);\n\t\treturn ERR_NONE;\n\t}\n\t\n\tWritetoMemCard(file, data, align4bytes(size));\n\t\n\tuint8 sizebuff[4];\n\tmemcpy(sizebuff, &size, sizeof(size));\n\t\n\tfor ( int32 i = 0; i < ARRAY_SIZE(sizebuff); i++ )\n\t\tCheckSum += sizebuff[i];\n\t\n\tfor ( int32 i = 0; i < align4bytes(size); i++ )\n\t\tCheckSum += *data++;\n\t\n\tif ( nError != NO_ERR_SUCCESS )\n\t{\n\t\tstrncpy(SaveFileNameJustSaved, ValidSaveName, sizeof(ValidSaveName) - 1);\n\t\treturn ERR_NONE;\n\t}\n\t\n\treturn nError;\n}\n\n#endif\n"
  },
  {
    "path": "src/save/MemoryCard.h",
    "content": "#pragma once\n#include \"common.h\"\n#ifdef PS2_MENU\n#include \"Date.h\"\n\n#if defined(PS2)\n#include <libcdvd.h>\n#include <sifdev.h>\n#include <libvu0.h>\n#endif\n\nenum\n{\n\tCARD_ONE = 0,\n\tCARD_TWO,\n\tMAX_CARDS,\n};\n\nclass CMemoryCardInfo\n{\npublic:\n\tint port;\n\tint slot;\n\tint type;\n\tint free;\n\tint format;\n\tchar dir[40];\n#if defined(PS2)\n\tsceMcTblGetDir table[15];\n#else\n\tstruct\n\t{\n\t\ttypedef struct {unsigned char Sec,Min,Hour; unsigned char Day,Month; unsigned short Year;} _time;\n\t\t_time _Create;\n\t\t_time _Modify;\n\t\tunsigned int FileSizeByte;\n\t\tunsigned short AttrFile;\n\t\tunsigned char EntryName[32];\n\t}table[15];\n#endif\n\tCMemoryCardInfo(void);\n};\n\n\n#define GUFF_FILE_SIZE 147096\n#define SAVE_FILE_SIZE 201729\n\nclass CMemoryCard\n{\npublic:\n\tenum\n\t{\n\t\tMAX_SLOTS = 8,\n\t};\n\t\n\tenum MCSTATE\n\t{\n\t\tMCSTATE_OK = 0,\n\t\tMCSTATE_NEED_500KB,\n\t\tMCSTATE_NEED_200KB,\n\t\tMCSTATE_NOCARD,\n\t};\n\t\n\tenum SLOTINFO\n\t{\n\t\tSLOT_PRESENT = 0,\n\t\tSLOT_NOTPRESENT,\n\t\tSLOT_CORRUPTED,\n\t};\n\n\tint             _unk0;\n\tint             _unk1;\n\tbool            m_bWantToLoad;\n\tbool            JustLoadedDontFadeInYet;\n\tbool            StillToFadeOut;\n\tbool            b_FoundRecentSavedGameWantToLoad;\n\tuint32          TimeStartedCountingForFade;\n\tuint32          TimeToStayFadedBeforeFadeOut;\n\tuint32          LastBlockSize;\n\tbool            _bunk2;\n\tchar            ValidSaveName        [30];\n\tchar            MostRecentFile       [30];\n\tchar            _unkName3            [30];\n\tchar            SaveFileNameJustSaved[30];\n\tchar _pad0[3];\n\twchar          *pErrorMsg;\n\tchar            _unk4[32];\n\tbool            _bunk5;\n\tbool            _bunk6;\n\tbool            _bunk7;\n\tbool            _bunk8;\n\tint             nError;\n\twchar           _unk9[30];\n\tchar            LoadFileName[30];\n\tchar _pad1[2];\n\tCDate           CompileDateAndTime;\n\tint             m_LanguageToLoad;\n\tint             m_LevelToLoad;\n\tint             CurrentCard;\n\tCMemoryCardInfo Cards       [MAX_CARDS];\n\tint             Slots       [MAX_SLOTS];\n\twchar           SlotFileName[MAX_SLOTS][30];\n\twchar           SlotSaveDate[MAX_SLOTS][30];\n\tchar            _unk10[32];\n\t\t\t\n\tenum\n\t{\n\t\tERR_NONE = 0,\n\t\tERR_NOFORMAT = 1,\n\t\tERR_DIRNOENTRY = 2,\n\t\tERR_OPENNOENTRY = 3,\n\t\tERR_DELETENOENTRY = 4,\n\t\tERR_DELETEDENIED = 5,\n\t\tERR_DELETEFAILED = 6,\n\t\tERR_WRITEFULLDEVICE = 7,\n\t\tERR_WRITENOENTRY = 8,\n\t\tERR_WRITEDENIED = 9,\n\t\tERR_FLUSHNOENTRY,\n\t\tERR_WRITEFAILED,\n\t\tERR_FORMATFAILED = 12,\n\t\tERR_FILETABLENOENTRY = 13,\n\t\tERR_DIRFULLDEVICE = 14,\n\t\tERR_DIRBADENTRY = 15,\n\t\tERR_FILEFULLDEVICE = 16,\n\t\tERR_FILENOPATHENTRY = 17,\n\t\tERR_FILEDENIED = 18,\n\t\tERR_FILEUPLIMIT = 19,\n\t\tERR_READNOENTRY = 20,\n\t\tERR_READDENIED = 21,\n\t\tERR_LOADFAILED = 22, // unused\n\t\tERR_SAVEFAILED = 23,\n\t\tERR_DATACORRUPTED = 24,\n\t\tERR_NOROOTDIR = 25,\n\t\tNO_ERR_SUCCESS = 26,\n\t};\n\t\n\tenum\n\t{\n\t\tRES_SUCCESS = 1,\n\t\tRES_FAILED  = -1,\n\t};\n\n\tint32 GetError()\n\t{\n\t\treturn nError;\n\t}\n\n\twchar *GetErrorMessage()\n\t{\n\t\treturn pErrorMsg;\n\t}\n\t\n\tint32 Init(void);\n\tCMemoryCard(void);\n\tint32 RestoreForStartLoad(void);\n\tint32 LoadSavedGame(void);\n\tint32 CheckCardInserted(int32 cardID);\n\tint32 PopulateCardFlags(int32 cardID, bool bSlotFlag, bool bTypeFlag, bool bFreeFlag, bool bFormatFlag);\n\tint32 FormatCard(int32 cardID);\n\tint32 PopulateFileTable(int32 cardID);\n\tint32 CreateRootDirectory(int32 cardID);\n\tint32 ChangeDirectory(int32 cardID, char *dir);\n\tint32 CreateIconFiles(int32 cardID, char *icon_one, char *icon_two, char *icon_three);\n\tint32 LoadIconFiles(int32 cardID, char *icon_one, char *icon_two, char *icon_three);\n\tint32 CloseMemCardFile(int32 file);\n\tint32 CreateMemCardFileReadWrite(int32 cardID, char *filename);\n\tint32 OpenMemCardFileForReading(int32 cardID, char *filename);\n\tint32 ReadFromMemCard(int32 file, void *buff, int32 size);\n\tint32 DeleteMemoryCardFile(int32 cardID, char *filename);\n\tvoid PopulateErrorMessage();\n\tint32 WritetoMemCard(int32 file, void *buff, int32 size);\n\tbool SaveGame(void);\n\tbool DoHackRoundSTUPIDSonyDateTimeStuff(int32 port, char *filename);\n\tint32 LookForRootDirectory(int32 cardID);\n\tint32 FillFirstFileWithGuff(int32 cardID);\n\tbool FindMostRecentFileName(int32 cardID, char *filename);\n\tvoid ClearFileTableBuffer(int32 cardID);\n\tint32 GetClusterAmountForFileCreation(int32 port);\n\tbool DeleteEverythingInGameRoot(int32 cardID);\n\tint32 CheckDataNotCorrupt(char *filename);\n\tint32 GetLanguageToLoad(void);\n\tint32 GetLevelToLoad(void);\n\tbool CreateGameDirectoryFromScratch(int32 cardID);\n\tbool CheckGameDirectoryThere(int32 cardID);\n\tvoid PopulateSlotInfo(int32 cardID);\n\tint32 GetInfoOnSpecificSlot(int32 slotID);\n\twchar *GetDateAndTimeOfSavedGame(int32 slotID);\n\tint32 CheckCardStateAtGameStartUp(int32 cardID);\n\tvoid SaveSlot(int32 slotID);\n\tvoid DeleteSlot(int32 slotID);\n\tvoid LoadSlotToBuffer(int32 slotID);\n\twchar *GetNameOfSavedGame(int32 slotID);\n\tint32 DoClassSaveRoutine(int32 file, uint8 *data, uint32 size);\n};\n\nextern CMemoryCard TheMemoryCard;\n#endif"
  },
  {
    "path": "src/save/PCSave.cpp",
    "content": "#define WITHWINDOWS\n#include \"common.h\"\n#include \"crossplatform.h\"\n\n#include \"FileMgr.h\"\n#include \"Font.h\"\n#ifdef MORE_LANGUAGES\n#include \"Game.h\"\n#endif\n#include \"GenericGameStorage.h\"\n#include \"Messages.h\"\n#include \"PCSave.h\"\n#include \"Text.h\"\n\nconst char* _psGetUserFilesFolder();\n\nC_PcSave PcSaveHelper;\n\nvoid\nC_PcSave::SetSaveDirectory(const char *path)\n{\n\tsprintf(DefaultPCSaveFileName, \"%s\\\\%s\", path, \"GTAVCsf\");\n}\n\nbool\nC_PcSave::DeleteSlot(int32 slot)\n{\n\tchar FileName[200];\n\n\tPcSaveHelper.nErrorCode = SAVESTATUS_SUCCESSFUL;\n\tsprintf(FileName, \"%s%i.b\", DefaultPCSaveFileName, slot + 1);\n\tDeleteFile(FileName);\n\tSlotSaveDate[slot][0] = '\\0';\n\treturn true;\n}\n\nint8\nC_PcSave::SaveSlot(int32 slot)\n{\n\tMakeValidSaveName(slot);\n\tPcSaveHelper.nErrorCode = SAVESTATUS_SUCCESSFUL;\n\t_psGetUserFilesFolder();\n\tint file = CFileMgr::OpenFile(ValidSaveName, \"wb\");\n\tif (file != 0) {\n#ifdef MISSION_REPLAY\n\t\tif (!IsQuickSave)\n#endif\n\t\t\tDoGameSpecificStuffBeforeSave();\n\t\tif (GenericSave(file)) {\n\t\t\tif (!!CFileMgr::CloseFile(file))\n\t\t\t\tnErrorCode = SAVESTATUS_ERR_SAVE_CLOSE;\n\t\t\treturn 0;\n\t\t}\n\n\t\treturn 2;\n\t}\n\tPcSaveHelper.nErrorCode = SAVESTATUS_ERR_SAVE_CREATE;\n\treturn false;\n}\n\nbool\nC_PcSave::PcClassSaveRoutine(int32 file, uint8 *data, uint32 size)\n{\n\tCFileMgr::Write(file, (const char*)&size, sizeof(size));\n\tif (CFileMgr::GetErrorReadWrite(file)) {\n\t\tnErrorCode = SAVESTATUS_ERR_SAVE_WRITE;\n\t\tstrncpy(SaveFileNameJustSaved, ValidSaveName, sizeof(ValidSaveName) - 1);\n\t\treturn false;\n\t}\n\n\tCFileMgr::Write(file, (const char*)data, align4bytes(size));\n\tCheckSum += (uint8) size;\n\tCheckSum += (uint8) (size >> 8);\n\tCheckSum += (uint8) (size >> 16);\n\tCheckSum += (uint8) (size >> 24);\n\tfor (int i = 0; i < align4bytes(size); i++) {\n\t\tCheckSum += *data++;\n\t}\n\tif (CFileMgr::GetErrorReadWrite(file)) {\n\t\tnErrorCode = SAVESTATUS_ERR_SAVE_WRITE;\n\t\tstrncpy(SaveFileNameJustSaved, ValidSaveName, sizeof(ValidSaveName) - 1);\n\t\treturn false;\n\t}\n\n\treturn true;\n}\n\nvoid\nC_PcSave::PopulateSlotInfo()\n{\n\tfor (int i = 0; i < SLOT_COUNT; i++) {\n\t\tSlots[i] = SLOT_EMPTY;\n\t\tSlotFileName[i][0] = '\\0';\n\t\tSlotSaveDate[i][0] = '\\0';\n\t}\n\tfor (int i = 0; i < SLOT_COUNT; i++) {\n#ifdef FIX_BUGS\n\t\tchar savename[MAX_PATH];\n#else\n\t\tchar savename[52];\n#endif\n\t\tstruct {\n\t\t\tint size;\n\t\t\twchar FileName[24];\n\t\t\tSYSTEMTIME SaveDateTime;\n\t\t} header;\n\t\tsprintf(savename, \"%s%i%s\", DefaultPCSaveFileName, i + 1, \".b\");\n\t\tint file = CFileMgr::OpenFile(savename, \"rb\");\n\t\tif (file != 0) {\n\t\t\tCFileMgr::Read(file, (char*)&header, sizeof(header));\n\t\t\tif (strncmp((char*)&header, TopLineEmptyFile, sizeof(TopLineEmptyFile)-1) != 0) {\n\t\t\t\tSlots[i] = SLOT_OK;\n\t\t\t\tmemcpy(SlotFileName[i], &header.FileName, sizeof(header.FileName));\n\t\t\t\t\n\t\t\t\tSlotFileName[i][24] = '\\0';\n\t\t\t}\n\t\t\tCFileMgr::CloseFile(file);\n\t\t}\n\t\tif (Slots[i] == SLOT_OK) {\n\t\t\tif (CheckDataNotCorrupt(i, savename)) {\n\t\t\t\tSYSTEMTIME st;\n\t\t\t\tmemcpy(&st, &header.SaveDateTime, sizeof(SYSTEMTIME));\n\t\t\t\tconst char *month;\n\t\t\t\tswitch (st.wMonth)\n\t\t\t\t{\n\t\t\t\tcase 1: month = \"JAN\"; break;\n\t\t\t\tcase 2: month = \"FEB\"; break;\n\t\t\t\tcase 3: month = \"MAR\"; break;\n\t\t\t\tcase 4: month = \"APR\"; break;\n\t\t\t\tcase 5: month = \"MAY\"; break;\n\t\t\t\tcase 6: month = \"JUN\"; break;\n\t\t\t\tcase 7: month = \"JUL\"; break;\n\t\t\t\tcase 8: month = \"AUG\"; break;\n\t\t\t\tcase 9: month = \"SEP\"; break;\n\t\t\t\tcase 10: month = \"OCT\"; break;\n\t\t\t\tcase 11: month = \"NOV\"; break;\n\t\t\t\tcase 12: month = \"DEC\"; break;\n\t\t\t\tdefault: assert(0);\n\t\t\t\t}\n\t\t\t\tchar date[70];\n#ifdef MORE_LANGUAGES\n\t\t\t\tif (CGame::japaneseGame)\n\t\t\t\t\tsprintf(date, \"%02d %02d %04d %02d:%02d:%02d\", st.wDay, st.wMonth, st.wYear, st.wHour, st.wMinute, st.wSecond);\n\t\t\t\telse\n#endif // MORE_LANGUAGES\n\t\t\t\t\tsprintf(date, \"%02d %s %04d %02d:%02d:%02d\", st.wDay, UnicodeToAsciiForSaveLoad(TheText.Get(month)), st.wYear, st.wHour, st.wMinute, st.wSecond);\n\t\t\t\tAsciiToUnicode(date, SlotSaveDate[i]);\n\n\t\t\t} else {\n\t\t\t\tCMessages::InsertNumberInString(TheText.Get(\"FEC_SLC\"), i + 1, -1, -1, -1, -1, -1, SlotFileName[i]);\n\t\t\t\tSlots[i] = SLOT_CORRUPTED;\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/save/PCSave.h",
    "content": "#pragma once\n\nenum eSaveStatus\n{\n\tSAVESTATUS_SUCCESSFUL = 0,\n\tSAVESTATUS_ERR_SAVE_CREATE,\n\tSAVESTATUS_ERR_SAVE_WRITE,\n\tSAVESTATUS_ERR_SAVE_CLOSE,\n\tSAVESTATUS_ERR_LOAD_OPEN,\n\tSAVESTATUS_ERR_LOAD_READ,\n\tSAVESTATUS_ERR_LOAD_CLOSE,\n\tSAVESTATUS_ERR_DATA_INVALID,\n\n\t// unused\n\tSAVESTATUS_DELETEFAILED8,\n\tSAVESTATUS_DELETEFAILED9,\n\tSAVESTATUS_DELETEFAILED10,\n};\n\nenum\n{\n\tSLOT_OK = 0,\n\tSLOT_EMPTY,\n\tSLOT_CORRUPTED\n};\n\nclass C_PcSave\n{\npublic:\n\teSaveStatus nErrorCode;\n\n\tC_PcSave() : nErrorCode(SAVESTATUS_SUCCESSFUL) {}\n\tvoid PopulateSlotInfo();\n\tbool DeleteSlot(int32 slot);\n\tint8 SaveSlot(int32 slot);\n\tbool PcClassSaveRoutine(int32 a2, uint8 *data, uint32 size);\n\tstatic void SetSaveDirectory(const char *path);\n};\n\nextern C_PcSave PcSaveHelper;\n"
  },
  {
    "path": "src/skel/crossplatform.cpp",
    "content": "#include \"common.h\"\n#include \"crossplatform.h\"\n\n// Codes compatible with Windows and Linux\n#ifndef _WIN32\n\n// For internal use\n// wMilliseconds is not needed\nvoid tmToSystemTime(const tm *tm, SYSTEMTIME *out) {\n    out->wYear = tm->tm_year + 1900;\n    out->wMonth = tm->tm_mon + 1;\n    out->wDayOfWeek = tm->tm_wday;\n    out->wDay = tm->tm_mday;\n    out->wHour = tm->tm_hour;\n    out->wMinute = tm->tm_min;\n    out->wSecond = tm->tm_sec;\n}\n\nvoid GetLocalTime_CP(SYSTEMTIME *out) {\n    time_t timestamp = time(nil);\n    tm *localTm = localtime(&timestamp);\n    tmToSystemTime(localTm, out);\n}\n#endif\n\n// Compatible with Linux/POSIX and MinGW on Windows\n#ifndef _WIN32\nHANDLE FindFirstFile(const char* pathname, WIN32_FIND_DATA* firstfile) {\n\tchar pathCopy[MAX_PATH];\n\tstrcpy(pathCopy, pathname);\n\n\tchar *folder = strtok(pathCopy, \"*\");\n\tchar *extension = strtok(NULL, \"*\");\n\n    // because I remember like strtok might not return NULL for last delimiter\n    if (extension && extension - folder == strlen(pathname))\n        extension = nil;\n\t\n\t// Case-sensitivity and backslashes...\n    // Will be freed at the bottom\n    char *realFolder = casepath(folder);\n\tif (realFolder) {\n        folder = realFolder;\n\t}\n\n\tstrncpy(firstfile->folder, folder, sizeof(firstfile->folder));\n\n\tif (extension)\n\t\tstrncpy(firstfile->extension, extension, sizeof(firstfile->extension));\n\telse\n\t\tfirstfile->extension[0] = '\\0';\n\n    if (realFolder)\n        free(realFolder);\n\n\tHANDLE d;\n\tif ((d = (HANDLE)opendir(firstfile->folder)) == NULL || !FindNextFile(d, firstfile))\n\t\treturn NULL;\n\n\treturn d;\n}\n\nbool FindNextFile(HANDLE d, WIN32_FIND_DATA* finddata) {\n\tdirent *file;\n\tstatic struct stat fileStats;\n\tstatic char path[PATH_MAX], relativepath[NAME_MAX + sizeof(finddata->folder) + 1];\n\tint extensionLen = strlen(finddata->extension);\n\twhile ((file = readdir((DIR*)d)) != NULL) {\n\n\t\t// We only want \"DT_REG\"ular Files, but reportedly some FS and OSes gives DT_UNKNOWN as type.\n\t\tif ((file->d_type == DT_UNKNOWN || file->d_type == DT_REG || file->d_type == DT_LNK) &&\n\t\t\t(extensionLen == 0 || strncasecmp(&file->d_name[strlen(file->d_name) - extensionLen], finddata->extension, extensionLen) == 0)) {\n\n\t\t\tsprintf(relativepath, \"%s/%s\", finddata->folder, file->d_name);\n\t\t\trealpath(relativepath, path);\n\t\t\tstat(path, &fileStats);\n\t\t\tstrncpy(finddata->cFileName, file->d_name, sizeof(finddata->cFileName));\n\t\t\tfinddata->ftLastWriteTime = fileStats.st_mtime;\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n\nvoid GetDateFormat(int unused1, int unused2, SYSTEMTIME* in, int unused3, char* out, int size) {\n\ttm linuxTime;\n\tlinuxTime.tm_year = in->wYear - 1900;\n\tlinuxTime.tm_mon = in->wMonth - 1;\n\tlinuxTime.tm_wday = in->wDayOfWeek;\n\tlinuxTime.tm_mday = in->wDay;\n\tlinuxTime.tm_hour = in->wHour;\n\tlinuxTime.tm_min = in->wMinute;\n\tlinuxTime.tm_sec = in->wSecond;\n\tstrftime(out, size, nl_langinfo(D_FMT), &linuxTime);\n}\n\nvoid FileTimeToSystemTime(time_t* writeTime, SYSTEMTIME* out) {\n\ttm *ptm = gmtime(writeTime);\n\ttmToSystemTime(ptm, out);\n}\n#endif\n\n// Because wchar length differs between platforms.\nwchar*\nAllocUnicode(const char* src)\n{\n\twchar *dst = (wchar*)malloc(strlen(src)*2 + 2);\n\twchar *i = dst;\n\twhile((*i++ = (unsigned char)*src++) != '\\0');\n\treturn dst;\n}\n\n// Funcs/features from Windows that we need on other platforms\n#ifndef _WIN32\nchar *strupr(char *s) {\n    char* tmp = s;\n\n    for (;*tmp;++tmp) {\n        *tmp = toupper((unsigned char) *tmp);\n    }\n\n    return s;\n}\nchar *strlwr(char *s) {\n    char* tmp = s;\n\n    for (;*tmp;++tmp) {\n        *tmp = tolower((unsigned char) *tmp);\n    }\n\n    return s;\n}\n\nchar *trim(char *s) {\n    char *ptr;\n    if (!s)\n        return NULL;   // handle NULL string\n    if (!*s)\n        return s;      // handle empty string\n    for (ptr = s + strlen(s) - 1; (ptr >= s) && isspace(*ptr); --ptr);\n    ptr[1] = '\\0';\n    return s;\n}\n\nFILE* _fcaseopen(char const* filename, char const* mode)\n{\n    FILE* result;\n    char* real = casepath(filename);\n    if (!real)\n        result = fopen(filename, mode);\n    else {\n        result = fopen(real, mode);\n        free(real);\n    }\n    return result;\n}\n\n// Case-insensitivity on linux (from https://github.com/OneSadCookie/fcaseopen)\n// Returned string should freed manually (if exists)\nchar* casepath(char const* path, bool checkPathFirst)\n{\n    if (checkPathFirst && access(path, F_OK) != -1) {\n        // File path is correct\n        return nil;\n    }\n\n    size_t l = strlen(path);\n    char* p = (char*)alloca(l + 1);\n    char* out = (char*)malloc(l + 3); // for extra ./\n    strcpy(p, path);\n\n    // my addon: linux doesn't handle filenames with spaces at the end nicely\n    p = trim(p);\n\n    size_t rl = 0;\n\n    DIR* d;\n    if (p[0] == '/' || p[0] == '\\\\')\n    {\n        d = opendir(\"/\");\n    }\n    else\n    {\n        d = opendir(\".\");\n        out[0] = '.';\n        out[1] = 0;\n        rl = 1;\n    }\n\n    bool cantProceed = false; // just convert slashes in what's left in string, don't correct case of letters(because we can't)\n    bool mayBeTrailingSlash = false;\n    char* c;\n    while (c = strsep(&p, \"/\\\\\"))\n    {\n        // May be trailing slash(allow), slash at the start(avoid), or multiple slashes(avoid)\n        if (*c == '\\0')\n        {\n            mayBeTrailingSlash = true;\n            continue;\n        } else {\n            mayBeTrailingSlash = false;\n        }\n\n        out[rl] = '/';\n        rl += 1;\n        out[rl] = 0;\n\n        if (cantProceed)\n        {\n            strcpy(out + rl, c);\n            rl += strlen(c);\n            continue;\n        }\n\n        struct dirent* e;\n        while (e = readdir(d))\n        {\n            if (strcasecmp(c, e->d_name) == 0)\n            {\n                strcpy(out + rl, e->d_name);\n                int reportedLen = (int)strlen(e->d_name);\n                rl += reportedLen;\n                assert(reportedLen == strlen(c) && \"casepath: This is not good at all\");\n\n                closedir(d);\n                d = opendir(out);\n\n                // Either it wasn't a folder, or permission error, I/O error etc.\n                if (!d) {\n                    cantProceed = true;\n                }\n\n                break;\n            }\n        }\n\n        if (!e)\n        {\n            printf(\"casepath couldn't find dir/file \\\"%s\\\", full path was %s\\n\", c, path);\n            // No match, add original name and continue converting further slashes.\n            strcpy(out + rl, c);\n            rl += strlen(c);\n            cantProceed = true;\n        }\n    }\n\n    if (d) closedir(d);\n    if (mayBeTrailingSlash) {\n        out[rl] = '/';  rl += 1;\n        out[rl] = '\\0';\n    }\n\n    if (rl > l + 2) {\n        printf(\"\\n\\ncasepath: Corrected path length is longer then original+2:\\n\\tOriginal: %s (%zu chars)\\n\\tCorrected: %s (%zu chars)\\n\\n\", path, l, out, rl);\n    }\n    return out;\n}\n#endif\n\n#if !defined(_MSC_VER) && !defined(__CWCC__)\nchar *strdate(char *buf) {\n\ttime_t timestamp;\n\ttime(&timestamp);\n\ttm *localTm = localtime(&timestamp);\n\tstrftime(buf, 10, \"%m/%d/%y\", localTm);\n\treturn buf;\n}\n\nchar *_strdate(char *buf) {\n\treturn strdate(buf);\n}\n#endif\n"
  },
  {
    "path": "src/skel/crossplatform.h",
    "content": "#include <time.h>\n\n// This is the common include for platform/renderer specific skeletons(glfw.cpp, win.cpp etc.) and using cross platform things (like Windows directories wrapper, platform specific global arrays etc.) \n// Functions that's different on glfw and win but have same signature, should be located on platform.h.\n\nenum eWinVersion\n{\n    OS_WIN95 = 0,\n    OS_WIN98,\n    OS_WINNT,\n    OS_WIN2000,\n    OS_WINXP,\n};\n\n#if !defined(_MSC_VER) && !defined(__CWCC__)\nchar *_strdate(char *buf);\n#endif\n\n#ifdef _WIN32\n\n// As long as WITHWINDOWS isn't defined / <Windows.h> isn't included, we only need type definitions so let's include <IntSafe.h>.\n// NOTE: It's perfectly fine to include <Windows.h> here, but it can increase build size and time in *some* conditions, and maybe substantially in future if we'll use crossplatform.h more.\n#ifndef _INC_WINDOWS\n\t#ifndef __MWERKS__\n\t\t#include <IntSafe.h>\n\t#else\n\t\t#include <Windows.h>\n\t#endif\n#endif\n#if defined RW_D3D9 || defined RWLIBS\n#include \"win.h\"\n#endif\nextern DWORD _dwOperatingSystemVersion;\n#define fcaseopen fopen\n#else\nchar *strupr(char *str);\nchar *strlwr(char *str);\n\nenum {\n\tLANG_OTHER,\n\tLANG_GERMAN,\n\tLANG_FRENCH,\n\tLANG_ENGLISH,\n\tLANG_ITALIAN,\n\tLANG_SPANISH,\n};\n\nenum {\n\tSUBLANG_OTHER,\n\tSUBLANG_ENGLISH_AUS\n};\n\nextern long _dwOperatingSystemVersion;\nchar *casepath(char const *path, bool checkPathFirst = true);\nFILE *_fcaseopen(char const *filename, char const *mode);\n#define fcaseopen _fcaseopen\n#endif\n\n#ifdef RW_GL3\ntypedef struct\n{\n    GLFWwindow* window;\n    RwBool\t\tfullScreen;\n    RwV2d\t\tlastMousePos;\n    double      mouseWheel; // glfw doesn't cache it\n    bool        cursorIsInWindow;\n    RwInt8        joy1id;\n    RwInt8        joy2id;\n}\npsGlobalType;\n\n#define PSGLOBAL(var) (((psGlobalType *)(RsGlobal.ps))->var)\n\nvoid CapturePad(RwInt32 padID);\nvoid joysChangeCB(int jid, int event);\n#endif\n\n#ifdef DETECT_JOYSTICK_MENU\nextern char gSelectedJoystickName[128];\n#endif\n\nenum eGameState\n{\n    GS_START_UP = 0,\n    GS_INIT_LOGO_MPEG,\n    GS_LOGO_MPEG,\n    GS_INIT_INTRO_MPEG,\n    GS_INTRO_MPEG,\n    GS_INIT_ONCE,\n    GS_INIT_FRONTEND,\n    GS_FRONTEND,\n    GS_INIT_PLAYING_GAME,\n    GS_PLAYING_GAME,\n};\nextern RwUInt32 gGameState;\n\nRwBool IsForegroundApp();\n\n#ifndef MAX_PATH\n    #if !defined _WIN32 || defined __MINGW32__\n    #define MAX_PATH PATH_MAX\n    #else\n    #define MAX_PATH 260\n    #endif\n#endif\n\n// Codes compatible with Windows and Linux\n#ifndef _WIN32\n#define DeleteFile unlink\n\n// Needed for save games\nstruct SYSTEMTIME {\n    RwUInt16 wYear;\n    RwUInt16 wMonth;\n    RwUInt16 wDayOfWeek;\n    RwUInt16 wDay;\n    RwUInt16 wHour;\n    RwUInt16 wMinute;\n    RwUInt16 wSecond;\n    RwUInt16 wMilliseconds;\n};\n\nvoid GetLocalTime_CP(SYSTEMTIME* out);\n#define GetLocalTime GetLocalTime_CP\n#define OutputDebugString(s) re3_debug(\"[DBG-2]: %s\\n\",s)\n#endif\n\n// Compatible with Linux/POSIX and MinGW on Windows\n#ifndef _WIN32\n#include <iostream>\n#include <dirent.h>\n#include <sys/types.h>\n#include <sys/stat.h>\n#include <langinfo.h>\n#include <unistd.h>\n\ntypedef void* HANDLE;\n#define INVALID_HANDLE_VALUE NULL\n#define FindClose(h) \\\n    do { \\\n        if (h != nil) \\\n            closedir((DIR*)h); \\\n    } while(0)\n\n#define LOCALE_USER_DEFAULT 0\n#define DATE_SHORTDATE 0\n\nstruct WIN32_FIND_DATA {\n    char extension[32]; // for searching\n    char folder[32];\t// for searching\n    char cFileName[256]; // because tSkinInfo has it 256\n    time_t ftLastWriteTime;\n};\n\nHANDLE FindFirstFile(const char*, WIN32_FIND_DATA*);\nbool FindNextFile(HANDLE, WIN32_FIND_DATA*);\nvoid FileTimeToSystemTime(time_t*, SYSTEMTIME*);\nvoid GetDateFormat(int, int, SYSTEMTIME*, int, char*, int);\n#endif\n"
  },
  {
    "path": "src/skel/events.cpp",
    "content": "#include \"common.h\"\n#include \"Pad.h\"\n#include \"ControllerConfig.h\"\n#include \"Frontend.h\"\n#include \"Camera.h\"\n\n#include \"rwcore.h\"\n#include \"skeleton.h\"\n#include \"events.h\"\n\n\n/*\n *****************************************************************************\n */\nstatic RsEventStatus \nHandleKeyDown(RsKeyStatus *keyStatus)\n{\n\tCPad *pad0 = CPad::GetPad(0);\n\tCPad *pad1 = CPad::GetPad(1);\n\t\n\tRwInt32 c = keyStatus->keyCharCode;\n\t\n\tif ( c != rsNULL )\n\t{\n\t\tswitch (c)\n\t\t{\n\t\t\tcase rsESC:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.ESC = 255;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\n\t\t\tcase rsINS:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.INS = 255;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsDEL:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.DEL = 255;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsHOME:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.HOME = 255;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsEND:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.END = 255;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsPGUP:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.PGUP = 255;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsPGDN:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.PGDN = 255;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsUP:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.UP = 255;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsDOWN:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.DOWN = 255;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsLEFT:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.LEFT = 255;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsRIGHT:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.RIGHT = 255;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsNUMLOCK:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.NUMLOCK = 255;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsPADDEL:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.DECIMAL = 255;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsPADEND:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.NUM1 = 255;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsPADDOWN:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.NUM2 = 255;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsPADPGDN:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.NUM3 = 255;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsPADLEFT:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.NUM4 = 255;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsPAD5:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.NUM5 = 255;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsPADRIGHT:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.NUM6 = 255;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsPADHOME:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.NUM7 = 255;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsPADUP:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.NUM8 = 255;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsPADPGUP:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.NUM9 = 255;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsPADINS:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.NUM0 = 255;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsDIVIDE:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.DIV = 255;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsTIMES:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.MUL = 255;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsMINUS:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.SUB = 255;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsPADENTER:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.ENTER = 255;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsPLUS:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.ADD = 255;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsENTER:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.EXTENTER = 255;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsSCROLL:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.SCROLLLOCK = 255;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsPAUSE:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.PAUSE = 255;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsBACKSP:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.BACKSP = 255;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsTAB:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.TAB = 255;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsCAPSLK:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.CAPSLOCK = 255;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsLSHIFT:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.LSHIFT = 255;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsSHIFT:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.SHIFT = 255;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsRSHIFT:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.RSHIFT = 255;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsLCTRL:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.LCTRL = 255;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsRCTRL:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.RCTRL = 255;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsLALT:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.LALT = 255;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsRALT:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.RALT = 255;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t\n\t\t\tcase rsLWIN:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.LWIN = 255;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsRWIN:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.RWIN = 255;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsAPPS:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.APPS = 255;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsF1:\n\t\t\tcase rsF2:\n\t\t\tcase rsF3:\n\t\t\tcase rsF4:\n\t\t\tcase rsF5:\n\t\t\tcase rsF6:\n\t\t\tcase rsF7:\n\t\t\tcase rsF8:\n\t\t\tcase rsF9:\n\t\t\tcase rsF10:\n\t\t\tcase rsF11:\n\t\t\tcase rsF12:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.F[c - rsF1] = 255;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tdefault:\n\t\t\t\t{\n\t\t\t\t\tif ( c < 255 )\n\t\t\t\t\t{\n\t\t\t\t\t\tCPad::TempKeyState.VK_KEYS[c] = 255;\n\t\t\t\t\t\tpad0->AddToPCCheatString(c);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t}\n\t\t\n\t\tif ( CPad::m_bMapPadOneToPadTwo )\n\t\t{\n\t\t\tif ( c == 'D' ) pad1->PCTempKeyState.LeftStickX = 128;\n\t\t\tif ( c == 'A' ) pad1->PCTempKeyState.LeftStickX = -128;\n\t\t\tif ( c == 'W' ) pad1->PCTempKeyState.LeftStickY = 128;\n\t\t\tif ( c == 'S' ) pad1->PCTempKeyState.LeftStickY = -128;\n\t\t\tif ( c == 'J' ) pad1->PCTempKeyState.RightStickX = 128;\n\t\t\tif ( c == 'G' ) pad1->PCTempKeyState.RightStickX = -128;\n\t\t\tif ( c == 'Y' ) pad1->PCTempKeyState.RightStickY = 128;\n\t\t\tif ( c == 'H' ) pad1->PCTempKeyState.RightStickY = -128;\n\t\t\tif ( c == 'Z' ) pad1->PCTempKeyState.LeftShoulder1 = 255;\n\t\t\tif ( c == 'X' ) pad1->PCTempKeyState.LeftShoulder2 = 255;\n\t\t\tif ( c == 'C' ) pad1->PCTempKeyState.RightShoulder1 = 255;\n\t\t\tif ( c == 'V' ) pad1->PCTempKeyState.RightShoulder2 = 255;\n\t\t\tif ( c == 'O' ) pad1->PCTempKeyState.DPadUp = 255;\n\t\t\tif ( c == 'L' ) pad1->PCTempKeyState.DPadDown = 255;\n\t\t\tif ( c == 'K' ) pad1->PCTempKeyState.DPadLeft = 255;\n\t\t\tif ( c == ';' ) pad1->PCTempKeyState.DPadRight = 255;\n\t\t\tif ( c == 'B' ) pad1->PCTempKeyState.Start = 255;\n\t\t\tif ( c == 'N' ) pad1->PCTempKeyState.Select = 255;\n\t\t\tif ( c == 'M' ) pad1->PCTempKeyState.Square = 255;\n\t\t\tif ( c == ',' ) pad1->PCTempKeyState.Triangle = 255;\n\t\t\tif ( c == '.' ) pad1->PCTempKeyState.Cross = 255;\n\t\t\tif ( c == '/' ) pad1->PCTempKeyState.Circle = 255;\n\t\t\tif ( c == rsRSHIFT ) pad1->PCTempKeyState.LeftShock = 255;\n\t\t\tif ( c == rsRCTRL ) pad1->PCTempKeyState.RightShock = 255;\n\t\t}\n\t}\n\t\n\treturn rsEVENTPROCESSED;\n}\n\n\nstatic RsEventStatus \nHandleKeyUp(RsKeyStatus *keyStatus)\n{\n\tCPad *pad0 = CPad::GetPad(0);\n\tCPad *pad1 = CPad::GetPad(1);\n\t\n\tRwInt32 c = keyStatus->keyCharCode;\n\t\n\tif ( c != rsNULL )\n\t{\n\t\tswitch (c)\n\t\t{\n\t\t\tcase rsESC:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.ESC = 0;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\n\t\t\tcase rsINS:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.INS = 0;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsDEL:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.DEL = 0;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsHOME:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.HOME = 0;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsEND:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.END = 0;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsPGUP:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.PGUP = 0;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsPGDN:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.PGDN = 0;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsUP:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.UP = 0;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsDOWN:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.DOWN = 0;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsLEFT:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.LEFT = 0;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsRIGHT:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.RIGHT = 0;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsNUMLOCK:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.NUMLOCK = 0;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsPADDEL:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.DECIMAL = 0;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsPADEND:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.NUM1 = 0;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsPADDOWN:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.NUM2 = 0;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsPADPGDN:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.NUM3 = 0;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsPADLEFT:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.NUM4 = 0;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsPAD5:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.NUM5 = 0;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsPADRIGHT:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.NUM6 = 0;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsPADHOME:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.NUM7 = 0;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsPADUP:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.NUM8 = 0;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsPADPGUP:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.NUM9 = 0;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsPADINS:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.NUM0 = 0;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsDIVIDE:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.DIV = 0;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsTIMES:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.MUL = 0;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsMINUS:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.SUB = 0;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsPADENTER:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.ENTER = 0;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsPLUS:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.ADD = 0;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsENTER:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.EXTENTER = 0;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsSCROLL:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.SCROLLLOCK = 0;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsPAUSE:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.PAUSE = 0;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsBACKSP:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.BACKSP = 0;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsTAB:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.TAB = 0;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsCAPSLK:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.CAPSLOCK = 0;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsLSHIFT:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.LSHIFT = 0;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsSHIFT:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.SHIFT = 0;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsRSHIFT:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.RSHIFT = 0;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsLCTRL:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.LCTRL = 0;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsRCTRL:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.RCTRL = 0;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsLALT:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.LALT = 0;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsRALT:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.RALT = 0;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t\n\t\t\tcase rsLWIN:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.LWIN = 0;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsRWIN:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.RWIN = 0;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsAPPS:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.APPS = 0;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tcase rsF1:\n\t\t\tcase rsF2:\n\t\t\tcase rsF3:\n\t\t\tcase rsF4:\n\t\t\tcase rsF5:\n\t\t\tcase rsF6:\n\t\t\tcase rsF7:\n\t\t\tcase rsF8:\n\t\t\tcase rsF9:\n\t\t\tcase rsF10:\n\t\t\tcase rsF11:\n\t\t\tcase rsF12:\n\t\t\t\t{\n\t\t\t\t\tCPad::TempKeyState.F[c - rsF1] = 0;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\tdefault:\n\t\t\t\t{\n\t\t\t\t\tif ( c < 255 )\n\t\t\t\t\t{\n\t\t\t\t\t\tCPad::TempKeyState.VK_KEYS[c] = 0;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t}\n\t\t\n\t\tif ( CPad::m_bMapPadOneToPadTwo )\n\t\t{\n\t\t\tif ( c == 'D' ) pad1->PCTempKeyState.LeftStickX = 0;\n\t\t\tif ( c == 'A' ) pad1->PCTempKeyState.LeftStickX = 0;\n\t\t\tif ( c == 'W' ) pad1->PCTempKeyState.LeftStickY = 0;\n\t\t\tif ( c == 'S' ) pad1->PCTempKeyState.LeftStickY = 0;\n\t\t\tif ( c == 'J' ) pad1->PCTempKeyState.RightStickX = 0;\n\t\t\tif ( c == 'G' ) pad1->PCTempKeyState.RightStickX = 0;\n\t\t\tif ( c == 'Y' ) pad1->PCTempKeyState.RightStickY = 0;\n\t\t\tif ( c == 'H' ) pad1->PCTempKeyState.RightStickY = 0;\n\t\t\tif ( c == 'Z' ) pad1->PCTempKeyState.LeftShoulder1 = 0;\n\t\t\tif ( c == 'X' ) pad1->PCTempKeyState.LeftShoulder2 = 0;\n\t\t\tif ( c == 'C' ) pad1->PCTempKeyState.RightShoulder1 = 0;\n\t\t\tif ( c == 'V' ) pad1->PCTempKeyState.RightShoulder2 = 0;\n\t\t\tif ( c == 'O' ) pad1->PCTempKeyState.DPadUp = 0;\n\t\t\tif ( c == 'L' ) pad1->PCTempKeyState.DPadDown = 0;\n\t\t\tif ( c == 'K' ) pad1->PCTempKeyState.DPadLeft = 0;\n\t\t\tif ( c == ';' ) pad1->PCTempKeyState.DPadRight = 0;\n\t\t\tif ( c == 'B' ) pad1->PCTempKeyState.Start = 0;\n\t\t\tif ( c == 'N' ) pad1->PCTempKeyState.Select = 0;\n\t\t\tif ( c == 'M' ) pad1->PCTempKeyState.Square = 0;\n\t\t\tif ( c == ',' ) pad1->PCTempKeyState.Triangle = 0;\n\t\t\tif ( c == '.' ) pad1->PCTempKeyState.Cross = 0;\n\t\t\tif ( c == '/' ) pad1->PCTempKeyState.Circle = 0;\n\t\t\tif ( c == rsRSHIFT ) pad1->PCTempKeyState.LeftShock = 0;\n\t\t\tif ( c == rsRCTRL ) pad1->PCTempKeyState.RightShock = 0;\n\t\t}\n\t}\n\t\n\treturn rsEVENTPROCESSED;\n}\n\n\n/*\n *****************************************************************************\n */\nstatic RsEventStatus \nKeyboardHandler(RsEvent event, void *param)\n{\n\t/*\n\t * ...then the application events, if necessary...\n\t */\n\tswitch( event )\n\t{\n\t\tcase rsKEYDOWN:\n\t\t{\n\t\t\treturn HandleKeyDown((RsKeyStatus *)param);\n\t\t}\n\n\t\tcase rsKEYUP:\n\t\t{\n\t\t\treturn HandleKeyUp((RsKeyStatus *)param);\n\t\t}\n\n\t\tdefault:\n\t\t{\n\t\t\treturn rsEVENTNOTPROCESSED;\n\t\t}\n\t}\n}\n\n/*\n *****************************************************************************\n */\nstatic RsEventStatus\nHandlePadButtonDown(RsPadButtonStatus *padButtonStatus)\n{\n\tbool bPadTwo = false;\n\tint32 padNumber = padButtonStatus->padID;\n\t\n\tCPad *pad = CPad::GetPad(padNumber);\n\t\n\tif ( CPad::m_bMapPadOneToPadTwo )\n\t\tpadNumber = 1;\n\t\n\tif ( padNumber == 1 )\n\t\tbPadTwo = true;\n\t\n\tControlsManager.UpdateJoyButtonState(padNumber);\n\t\n\tfor ( int32 i = 0; i < _TODOCONST(16); i++ )\n\t{\n\t\tRsPadButtons btn = rsPADNULL;\n\t\tif ( ControlsManager.m_aButtonStates[i] == TRUE )\n\t\t\tbtn = (RsPadButtons)(i + 1);\n\n\t\tif ( FrontEndMenuManager.m_bMenuActive || bPadTwo )\n\t\t\tControlsManager.UpdateJoyInConfigMenus_ButtonDown(btn, padNumber);\n\t\telse\n\t\t\tControlsManager.AffectControllerStateOn_ButtonDown(btn, JOYSTICK);\n\t}\n\t\n\treturn rsEVENTPROCESSED;\n}\n\n\n/*\n *****************************************************************************\n */\nstatic RsEventStatus\nHandlePadButtonUp(RsPadButtonStatus *padButtonStatus)\n{\n\tbool bPadTwo = false;\n\tint32 padNumber = padButtonStatus->padID;\n\n\tCPad *pad = CPad::GetPad(padNumber);\n\t\n\tif ( CPad::m_bMapPadOneToPadTwo )\n\t\tpadNumber = 1;\n\n\tif ( padNumber == 1 )\n\t\tbPadTwo = true;\n\t\n\tbool bCam = false;\n\tint16 mode = TheCamera.Cams[TheCamera.ActiveCam].Mode;\n\tif ( mode == CCam::MODE_FLYBY || mode == CCam::MODE_FIXED )\n\t\tbCam = true;\n\t\n\tControlsManager.UpdateJoyButtonState(padNumber);\n\t\n\tfor ( int32 i = 1; i < _TODOCONST(16); i++ )\n\t{\n\t\tRsPadButtons btn = rsPADNULL;\n\t\tif ( ControlsManager.m_aButtonStates[i] == FALSE )\n\t\t\tbtn = (RsPadButtons)(i + 1); // bug ?, cycle begins from 1(not zero), 1+1==2==rsPADBUTTON2, so we skip rsPADBUTTON1, right ?\n\t\t\n\t\tif ( FrontEndMenuManager.m_bMenuActive || bPadTwo || bCam )\n\t\t\tControlsManager.UpdateJoyInConfigMenus_ButtonUp(btn, padNumber);\n\t\telse\n\t\t\tControlsManager.AffectControllerStateOn_ButtonUp(btn, JOYSTICK);\n\t}\n\n\treturn rsEVENTPROCESSED;\n}\n\n/*\n *****************************************************************************\n */\nstatic RsEventStatus \nPadHandler(RsEvent event, void *param)\n{\n\tswitch( event )\n\t{\n\t\tcase rsPADBUTTONDOWN:\n\t\t{\n\t\t\treturn HandlePadButtonDown((RsPadButtonStatus *)param);\n\t\t}\n\n\t\tcase rsPADBUTTONUP:\n\t\t{\n\t\t\treturn HandlePadButtonUp((RsPadButtonStatus *)param);\n\t\t}\n\n\t\tdefault:\n\t\t{\n\t\t\treturn rsEVENTNOTPROCESSED;\n\t\t}\n\t}\n}\n\n\n/*\n *****************************************************************************\n */\nRwBool\nAttachInputDevices(void)\n{\n\tRsInputDeviceAttach(rsKEYBOARD, KeyboardHandler);\n\n\tRsInputDeviceAttach(rsPAD, PadHandler);\n\n\treturn TRUE;\n}\n"
  },
  {
    "path": "src/skel/events.h",
    "content": "#ifndef EVENTS_H\n#define EVENTS_H\n\n#include <rwcore.h>\n#include \"skeleton.h\"\n\n#endif /* EVENTS_H */\n"
  },
  {
    "path": "src/skel/glfw/glfw.cpp",
    "content": "#if defined RW_GL3 && !defined LIBRW_SDL2\n\n#ifdef _WIN32\n#include <shlobj.h>\n#include <basetsd.h>\n#include <mmsystem.h>\n#include <regstr.h>\n#include <shellapi.h>\n#include <windowsx.h>\n\nDWORD _dwOperatingSystemVersion;\n#include \"resource.h\"\n#else\nlong _dwOperatingSystemVersion;\n#ifndef __APPLE__\n#include <sys/sysinfo.h>\n#else\n#include <mach/mach_host.h>\n#include <sys/sysctl.h>\n#endif\n#include <errno.h>\n#include <locale.h>\n#include <signal.h>\n#include <stddef.h>\n#endif\n\n#include \"common.h\"\n#if (defined(_MSC_VER))\n#include <tchar.h>\n#endif /* (defined(_MSC_VER)) */\n#include <stdio.h>\n#include \"rwcore.h\"\n#include \"skeleton.h\"\n#include \"platform.h\"\n#include \"crossplatform.h\"\n\n#include \"main.h\"\n#include \"FileMgr.h\"\n#include \"Text.h\"\n#include \"Pad.h\"\n#include \"Timer.h\"\n#include \"DMAudio.h\"\n#include \"ControllerConfig.h\"\n#include \"Frontend.h\"\n#include \"Game.h\"\n#include \"PCSave.h\"\n#include \"MemoryCard.h\"\n#include \"Sprite2d.h\"\n#include \"AnimViewer.h\"\n#include \"Font.h\"\n#include \"MemoryMgr.h\"\n\n// We found out that GLFW's keyboard input handling is still pretty delayed/not stable, so now we fetch input from X11 directly on Linux.\n#if !defined _WIN32 && !defined __APPLE__ && !defined __SWITCH__ // && !defined WAYLAND\n#define GET_KEYBOARD_INPUT_FROM_X11\n#endif\n\n#ifdef GET_KEYBOARD_INPUT_FROM_X11\n#include <X11/Xlib.h>\n#include <X11/XKBlib.h>\n#define GLFW_EXPOSE_NATIVE_X11\n#include <GLFW/glfw3native.h>\n#endif\n\n#ifdef _WIN32\n#define GLFW_EXPOSE_NATIVE_WIN32\n#include <GLFW/glfw3native.h>\n#endif\n\n#define MAX_SUBSYSTEMS\t\t(16)\n\nrw::EngineOpenParams openParams;\n\nstatic RwBool\t\t  ForegroundApp = TRUE;\nstatic RwBool\t\t  WindowIconified = FALSE;\nstatic RwBool\t\t  WindowFocused = TRUE;\n\nstatic RwBool\t\t  RwInitialised = FALSE;\n\nstatic RwSubSystemInfo GsubSysInfo[MAX_SUBSYSTEMS];\nstatic RwInt32\t\tGnumSubSystems = 0;\nstatic RwInt32\t\tGcurSel = 0, GcurSelVM = 0;\n\nstatic RwBool useDefault;\n\n// What is that for anyway?\n#ifndef IMPROVED_VIDEOMODE\nstatic RwBool defaultFullscreenRes = TRUE;\n#else\nstatic RwBool defaultFullscreenRes = FALSE;\nstatic RwInt32 bestWndMode = -1;\n#endif\n\nstatic psGlobalType PsGlobal;\n\n\n#define PSGLOBAL(var) (((psGlobalType *)(RsGlobal.ps))->var)\n\nsize_t _dwMemAvailPhys;\nRwUInt32 gGameState;\n\n#ifdef DETECT_JOYSTICK_MENU\nchar gSelectedJoystickName[128] = \"\";\n#endif\n\n/*\n *****************************************************************************\n */\nvoid _psCreateFolder(const char *path)\n{\n#ifdef _WIN32\n\tHANDLE hfle = CreateFile(path, GENERIC_READ, \n\t\t\t\t\t\t\t\t\tFILE_SHARE_READ,\n\t\t\t\t\t\t\t\t\tnil,\n\t\t\t\t\t\t\t\t\tOPEN_EXISTING,\n\t\t\t\t\t\t\t\t\tFILE_FLAG_BACKUP_SEMANTICS | FILE_ATTRIBUTE_NORMAL,\n\t\t\t\t\t\t\t\t\tnil);\n\n\tif ( hfle == INVALID_HANDLE_VALUE )\n\t\tCreateDirectory(path, nil);\n\telse\n\t\tCloseHandle(hfle);\n#else\n\tstruct stat info;\n\tchar fullpath[PATH_MAX];\n\trealpath(path, fullpath);\n\n\tif (lstat(fullpath, &info) != 0) {\n\t\tif (errno == ENOENT || (errno != EACCES && !S_ISDIR(info.st_mode))) {\n\t\t\tmkdir(fullpath, 0755);\n\t\t}\n\t}\n#endif\n}\n\n/*\n *****************************************************************************\n */\nconst char *_psGetUserFilesFolder()\n{\n#if defined USE_MY_DOCUMENTS && defined _WIN32\n\tHKEY hKey = NULL;\n\n\tstatic CHAR szUserFiles[256];\n\n\tif ( RegOpenKeyEx(HKEY_CURRENT_USER,\n\t\t\t\t\t\tREGSTR_PATH_SPECIAL_FOLDERS,\n\t\t\t\t\t\tREG_OPTION_RESERVED,\n\t\t\t\t\t\tKEY_READ,\n\t\t\t\t\t\t&hKey) == ERROR_SUCCESS )\n\t{\n\t\tDWORD KeyType;\n\t\tDWORD KeycbData = sizeof(szUserFiles);\n\t\tif ( RegQueryValueEx(hKey,\n\t\t\t\t\t\t\t\"Personal\",\n\t\t\t\t\t\t\tNULL,\n\t\t\t\t\t\t\t&KeyType,\n\t\t\t\t\t\t\t(LPBYTE)szUserFiles,\n\t\t\t\t\t\t\t&KeycbData) == ERROR_SUCCESS )\n\t\t{\n\t\t\tRegCloseKey(hKey);\n\t\t\tstrcat(szUserFiles, \"\\\\GTA Vice City User Files\");\n\t\t\t_psCreateFolder(szUserFiles);\n\t\t\treturn szUserFiles;\n\t\t}\t\n\n\t\tRegCloseKey(hKey);\t\t\n\t}\n\t\n\tstrcpy(szUserFiles, \"data\");\n\treturn szUserFiles;\n#else\n\tstatic char szUserFiles[256];\n\tstrcpy(szUserFiles, \"userfiles\");\n\t_psCreateFolder(szUserFiles);\n\treturn szUserFiles;\n#endif\n}\n\n/*\n *****************************************************************************\n */\nRwBool\npsCameraBeginUpdate(RwCamera *camera)\n{\n\tif ( !RwCameraBeginUpdate(Scene.camera) )\n\t{\n\t\tForegroundApp = FALSE;\n\t\tRsEventHandler(rsACTIVATE, (void *)FALSE);\n\t\treturn FALSE;\n\t}\n\t\n\treturn TRUE;\n}\n\n/*\n *****************************************************************************\n */\nvoid\npsCameraShowRaster(RwCamera *camera)\n{\n#ifdef LEGACY_MENU_OPTIONS\n\tif (FrontEndMenuManager.m_PrefsVsync || FrontEndMenuManager.m_bMenuActive)\n#else\n\tif (FrontEndMenuManager.m_PrefsFrameLimiter || FrontEndMenuManager.m_bMenuActive)\n#endif\n\t\tRwCameraShowRaster(camera, PSGLOBAL(window), rwRASTERFLIPWAITVSYNC);\n\telse\n\t\tRwCameraShowRaster(camera, PSGLOBAL(window), rwRASTERFLIPDONTWAIT);\n\n\treturn;\n}\n\n/*\n *****************************************************************************\n */\nRwImage *\npsGrabScreen(RwCamera *pCamera)\n{\n#ifndef LIBRW\n\tRwRaster *pRaster = RwCameraGetRaster(pCamera);\n\tif (RwImage *pImage = RwImageCreate(pRaster->width, pRaster->height, 32)) {\n\t\tRwImageAllocatePixels(pImage);\n\t\tRwImageSetFromRaster(pImage, pRaster);\n\t\treturn pImage;\n\t}\n#else\n\trw::Image *image = RwCameraGetRaster(pCamera)->toImage();\n\timage->removeMask();\n\tif(image)\n\t\treturn image;\n#endif\n\treturn nil;\n}\n\n/*\n *****************************************************************************\n */\n#ifdef _WIN32\n#pragma comment( lib, \"Winmm.lib\" ) // Needed for time\nRwUInt32\npsTimer(void)\n{\n\tRwUInt32 time;\n\n\tTIMECAPS TimeCaps;\n\t\n\ttimeGetDevCaps(&TimeCaps, sizeof(TIMECAPS));\n\t\n\ttimeBeginPeriod(TimeCaps.wPeriodMin);\n\t\n\ttime = (RwUInt32) timeGetTime();\n\n\ttimeEndPeriod(TimeCaps.wPeriodMin);\n\t\n\treturn time;\n}\n#else\ndouble\npsTimer(void)\n{\n\tstruct timespec start; \n#if defined(CLOCK_MONOTONIC_RAW)\n\tclock_gettime(CLOCK_MONOTONIC_RAW, &start);\n#elif defined(CLOCK_MONOTONIC_FAST)\n\tclock_gettime(CLOCK_MONOTONIC_FAST, &start);\n#else\n\tclock_gettime(CLOCK_MONOTONIC, &start);\n#endif\n\treturn start.tv_sec * 1000.0 + start.tv_nsec/1000000.0;\n}\n#endif       \n\n\n/*\n *****************************************************************************\n */\nvoid\npsMouseSetPos(RwV2d *pos)\n{\n\tglfwSetCursorPos(PSGLOBAL(window), pos->x, pos->y);\n\t\n\tPSGLOBAL(lastMousePos.x) = (RwInt32)pos->x;\n\n\tPSGLOBAL(lastMousePos.y) = (RwInt32)pos->y;\n\n\treturn;\n}\n\n/*\n *****************************************************************************\n */\nRwMemoryFunctions*\npsGetMemoryFunctions(void)\n{\n#ifdef USE_CUSTOM_ALLOCATOR\n\treturn &memFuncs;\n#else\n\treturn nil;\n#endif\n}\n\n/*\n *****************************************************************************\n */\nRwBool\npsInstallFileSystem(void)\n{\n\treturn (TRUE);\n}\n\n\n/*\n *****************************************************************************\n */\nRwBool\npsNativeTextureSupport(void)\n{\n\treturn true;\n}\n\n/*\n *****************************************************************************\n */\n#ifdef UNDER_CE\n#define CMDSTR\tLPWSTR\n#else\n#define CMDSTR\tLPSTR\n#endif\n\n/*\n *****************************************************************************\n */\nRwBool\npsInitialize(void)\n{\n\tPsGlobal.lastMousePos.x = PsGlobal.lastMousePos.y = 0.0f;\n\n\tRsGlobal.ps = &PsGlobal;\n\t\n\tPsGlobal.fullScreen = FALSE;\n\tPsGlobal.cursorIsInWindow = FALSE;\n\tWindowFocused = TRUE;\n\tWindowIconified = FALSE;\n\t\n\tPsGlobal.joy1id\t= -1;\n\tPsGlobal.joy2id\t= -1;\n\n\tCFileMgr::Initialise();\n\t\n#ifdef PS2_MENU\n\tCPad::Initialise();\n\tCPad::GetPad(0)->Mode = 0;\n\n\tCGame::frenchGame = false;\n\tCGame::germanGame = false;\n\tCGame::nastyGame = true;\n\tCMenuManager::m_PrefsAllowNastyGame = true;\n\n#ifndef _WIN32\n\t// Mandatory for Linux(Unix? Posix?) to set lang. to environment lang.\n\tsetlocale(LC_ALL, \"\");\t\n\n\tchar *systemLang, *keyboardLang;\n\n\tsystemLang = setlocale (LC_ALL, NULL);\n\tkeyboardLang = setlocale (LC_CTYPE, NULL);\n\t\n\tshort lang;\n\tlang = !strncmp(systemLang, \"fr_\",3) ? LANG_FRENCH :\n\t\t\t\t\t!strncmp(systemLang, \"de_\",3) ? LANG_GERMAN :\n\t\t\t\t\t!strncmp(systemLang, \"en_\",3) ? LANG_ENGLISH :\n\t\t\t\t\t!strncmp(systemLang, \"it_\",3) ? LANG_ITALIAN :\n\t\t\t\t\t!strncmp(systemLang, \"es_\",3) ? LANG_SPANISH :\n\t\t\t\t\tLANG_OTHER;\n#else\n\tWORD lang\t= PRIMARYLANGID(GetSystemDefaultLCID());\n#endif\n\n\tif ( lang  == LANG_ITALIAN )\n\t\tCMenuManager::m_PrefsLanguage = CMenuManager::LANGUAGE_ITALIAN;\n\telse if ( lang  == LANG_SPANISH )\n\t\tCMenuManager::m_PrefsLanguage = CMenuManager::LANGUAGE_SPANISH;\n\telse if ( lang  == LANG_GERMAN )\n\t{\n\t\tCGame::germanGame = true;\n\t\tCGame::nastyGame = false;\n\t\tCMenuManager::m_PrefsAllowNastyGame = false;\n\t\tCMenuManager::m_PrefsLanguage = CMenuManager::LANGUAGE_GERMAN;\n\t}\n\telse if ( lang  == LANG_FRENCH )\n\t{\n\t\tCGame::frenchGame = true;\n\t\tCGame::nastyGame = false;\n\t\tCMenuManager::m_PrefsAllowNastyGame = false;\n\t\tCMenuManager::m_PrefsLanguage = CMenuManager::LANGUAGE_FRENCH;\n\t}\n\telse\n\t\tCMenuManager::m_PrefsLanguage = CMenuManager::LANGUAGE_AMERICAN;\n\n\tFrontEndMenuManager.InitialiseMenuContentsAfterLoadingGame();\n\n\tTheMemoryCard.Init();\n#else\n\tC_PcSave::SetSaveDirectory(_psGetUserFilesFolder());\n\t\n\tInitialiseLanguage();\n\n#endif\n\t\n\tgGameState = GS_START_UP;\n\tTRACE(\"gGameState = GS_START_UP\");\n#ifdef _WIN32\n\tOSVERSIONINFO verInfo;\n\tverInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);\n\t\n\tGetVersionEx(&verInfo);\n\t\n\t_dwOperatingSystemVersion = OS_WIN95;\n\t\n\tif ( verInfo.dwPlatformId == VER_PLATFORM_WIN32_NT )\n\t{\n\t\tif ( verInfo.dwMajorVersion == 4 )\n\t\t{\n\t\t\tdebug(\"Operating System is WinNT\\n\");\n\t\t\t_dwOperatingSystemVersion = OS_WINNT;\n\t\t}\n\t\telse if ( verInfo.dwMajorVersion == 5 )\n\t\t{\n\t\t\tdebug(\"Operating System is Win2000\\n\");\n\t\t\t_dwOperatingSystemVersion = OS_WIN2000;\n\t\t}\n\t\telse if ( verInfo.dwMajorVersion > 5 )\n\t\t{\n\t\t\tdebug(\"Operating System is WinXP or greater\\n\");\n\t\t\t_dwOperatingSystemVersion = OS_WINXP;\n\t\t}\n\t}\n\telse if ( verInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS )\n\t{\n\t\tif ( verInfo.dwMajorVersion > 4 || verInfo.dwMajorVersion == 4 && verInfo.dwMinorVersion != 0 )\n\t\t{\n\t\t\tdebug(\"Operating System is Win98\\n\");\n\t\t\t_dwOperatingSystemVersion = OS_WIN98;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tdebug(\"Operating System is Win95\\n\");\n\t\t\t_dwOperatingSystemVersion = OS_WIN95;\n\t\t}\n\t}\n#else\n\t_dwOperatingSystemVersion = OS_WINXP; // To fool other classes\n#endif\n\n\t\n#ifndef PS2_MENU\n\tFrontEndMenuManager.LoadSettings();\n#endif\n\n\n#ifdef _WIN32\n\tMEMORYSTATUS memstats;\n\tGlobalMemoryStatus(&memstats);\n\n\t_dwMemAvailPhys = memstats.dwAvailPhys;\n\n\tdebug(\"Physical memory size %u\\n\", memstats.dwTotalPhys);\n\tdebug(\"Available physical memory %u\\n\", memstats.dwAvailPhys);\n#elif defined (__APPLE__)\n\tuint64_t size = 0;\n\tuint64_t page_size = 0;\n\tsize_t uint64_len = sizeof(uint64_t);\n\tsize_t ull_len = sizeof(unsigned long long);\n\tsysctl((int[]){CTL_HW, HW_PAGESIZE}, 2, &page_size, &ull_len, NULL, 0);\n\tsysctl((int[]){CTL_HW, HW_MEMSIZE}, 2, &size, &uint64_len, NULL, 0);\n\tvm_statistics_data_t vm_stat;\n\tmach_msg_type_number_t count = HOST_VM_INFO_COUNT;\n\thost_statistics(mach_host_self(), HOST_VM_INFO, (host_info_t)&vm_stat, &count);\n\t_dwMemAvailPhys = (uint64_t)(vm_stat.free_count * page_size);\n\tdebug(\"Physical memory size %llu\\n\", _dwMemAvailPhys);\n\tdebug(\"Available physical memory %llu\\n\", size);\n#else\n#ifndef __APPLE__\n \tstruct sysinfo systemInfo;\n\tsysinfo(&systemInfo);\n\t_dwMemAvailPhys = systemInfo.freeram;\n\tdebug(\"Physical memory size %u\\n\", systemInfo.totalram);\n\tdebug(\"Available physical memory %u\\n\", systemInfo.freeram);\n#else\n\tuint64_t size = 0;\n\tuint64_t page_size = 0;\n\tsize_t uint64_len = sizeof(uint64_t);\n\tsize_t ull_len = sizeof(unsigned long long);\n\tsysctl((int[]){CTL_HW, HW_PAGESIZE}, 2, &page_size, &ull_len, NULL, 0);\n\tsysctl((int[]){CTL_HW, HW_MEMSIZE}, 2, &size, &uint64_len, NULL, 0);\n\tvm_statistics_data_t vm_stat;\n\tmach_msg_type_number_t count = HOST_VM_INFO_COUNT;\n\thost_statistics(mach_host_self(), HOST_VM_INFO, (host_info_t)&vm_stat, &count);\n\t_dwMemAvailPhys = (uint64_t)(vm_stat.free_count * page_size);\n\tdebug(\"Physical memory size %llu\\n\", _dwMemAvailPhys);\n\tdebug(\"Available physical memory %llu\\n\", size);\n#endif\n\t_dwOperatingSystemVersion = OS_WINXP; // To fool other classes\n#endif\n  \n  TheText.Unload();\n\n\treturn TRUE;\n}\n\n\n/*\n *****************************************************************************\n */\nvoid\npsTerminate(void)\n{\n\treturn;\n}\n\n/*\n *****************************************************************************\n */\nstatic RwChar **_VMList;\n\nRwInt32 _psGetNumVideModes()\n{\n\treturn RwEngineGetNumVideoModes();\n}\n\n/*\n *****************************************************************************\n */\nRwBool _psFreeVideoModeList()\n{\n\tRwInt32 numModes;\n\tRwInt32 i;\n\t\n\tnumModes = _psGetNumVideModes();\n\t\n\tif ( _VMList == nil )\n\t\treturn TRUE;\n\t\n\tfor ( i = 0; i < numModes; i++ )\n\t{\n\t\tRwFree(_VMList[i]);\n\t}\n\t\n\tRwFree(_VMList);\n\t\n\t_VMList = nil;\n\t\n\treturn TRUE;\n}\n\t\t\t\t\t\t\t\n/*\n *****************************************************************************\n */\t\t\t\t\t\t\t\nRwChar **_psGetVideoModeList()\n{\n\tRwInt32 numModes;\n\tRwInt32 i;\n\t\n\tif ( _VMList != nil )\n\t{\n\t\treturn _VMList;\n\t}\n\t\n\tnumModes = RwEngineGetNumVideoModes();\n\t\n\t_VMList = (RwChar **)RwCalloc(numModes, sizeof(RwChar*));\n\t\n\tfor ( i = 0; i < numModes; i++\t)\n\t{\n\t\tRwVideoMode\t\t\tvm;\n\t\t\n\t\tRwEngineGetVideoModeInfo(&vm, i);\n\t\t\n\t\tif ( vm.flags & rwVIDEOMODEEXCLUSIVE )\n\t\t{\n\t\t\t_VMList[i] = (RwChar*)RwCalloc(100, sizeof(RwChar));\n\t\t\trwsprintf(_VMList[i],\"%d X %d X %d\", vm.width, vm.height, vm.depth);\n\t\t}\n\t\telse\n\t\t\t_VMList[i] = nil;\n\t}\n\t\n\treturn _VMList;\n}\n\n/*\n *****************************************************************************\n */\nvoid _psSelectScreenVM(RwInt32 videoMode)\n{\n\tRwTexDictionarySetCurrent( nil );\n\t\n\tFrontEndMenuManager.UnloadTextures();\n\t\n\tif (!_psSetVideoMode(RwEngineGetCurrentSubSystem(), videoMode))\n\t{\n\t\tRsGlobal.quit = TRUE;\n\n\t\tprintf(\"ERROR: Failed to select new screen resolution\\n\");\n\t}\n\telse\n\t\tFrontEndMenuManager.LoadAllTextures();\n}\n\n/*\n *****************************************************************************\n */\n\nRwBool IsForegroundApp()\n{\n\treturn !!ForegroundApp;\n}\n/*\nUINT GetBestRefreshRate(UINT width, UINT height, UINT depth)\n{\n\tLPDIRECT3D8 d3d = Direct3DCreate8(D3D_SDK_VERSION);\n\t\n\tASSERT(d3d != nil);\n\t\n\tUINT refreshRate = INT_MAX;\n\tD3DFORMAT format;\n\n\tif ( depth == 32 )\n\t\tformat = D3DFMT_X8R8G8B8;\n\telse if ( depth == 24 )\n\t\tformat = D3DFMT_R8G8B8;\n\telse\n\t\tformat = D3DFMT_R5G6B5;\n\t\n\tUINT modeCount = d3d->GetAdapterModeCount(GcurSel);\n\t\n\tfor ( UINT i = 0; i < modeCount; i++ )\n\t{\n\t\tD3DDISPLAYMODE mode;\n\t\t\n\t\td3d->EnumAdapterModes(GcurSel, i, &mode);\n\t\t\n\t\tif ( mode.Width == width && mode.Height == height && mode.Format == format )\n\t\t{\n\t\t\tif ( mode.RefreshRate == 0 )\n\t\t\t\treturn 0;\n\n\t\t\tif ( mode.RefreshRate < refreshRate && mode.RefreshRate >= 60 )\n\t\t\t\trefreshRate = mode.RefreshRate;\n\t\t}\n\t}\n\t\n#ifdef FIX_BUGS\n\td3d->Release();\n#endif\n\t\n\tif ( refreshRate == -1 )\n\t\treturn -1;\n\n\treturn refreshRate;\n}\n*/\n/*\n *****************************************************************************\n */\nRwBool\npsSelectDevice()\n{\n\tRwVideoMode\t\t\tvm;\n\tRwInt32\t\t\t\tsubSysNum;\n\tRwInt32\t\t\t\tAutoRenderer = 0;\n\t\n\n\tRwBool modeFound = FALSE;\n\t\n\tif ( !useDefault )\n\t{\n\t\tGnumSubSystems = RwEngineGetNumSubSystems();\n\t\tif ( !GnumSubSystems )\n\t\t{\n\t\t\t return FALSE;\n\t\t}\n\t\t\n\t\t/* Just to be sure ... */\n\t\tGnumSubSystems = (GnumSubSystems > MAX_SUBSYSTEMS) ? MAX_SUBSYSTEMS : GnumSubSystems;\n\t\t\n\t\t/* Get the names of all the sub systems */\n\t\tfor (subSysNum = 0; subSysNum < GnumSubSystems; subSysNum++)\n\t\t{\n\t\t\tRwEngineGetSubSystemInfo(&GsubSysInfo[subSysNum], subSysNum);\n\t\t}\n\t\t\n\t\t/* Get the default selection */\n\t\tGcurSel = RwEngineGetCurrentSubSystem();\n#ifdef IMPROVED_VIDEOMODE\n\t\tif(FrontEndMenuManager.m_nPrefsSubsystem < GnumSubSystems)\n\t\t\tGcurSel = FrontEndMenuManager.m_nPrefsSubsystem;\n#endif\n\t}\n\t\n\t/* Set the driver to use the correct sub system */\n\tif (!RwEngineSetSubSystem(GcurSel))\n\t{\n\t\treturn FALSE;\n\t}\n\n#ifdef IMPROVED_VIDEOMODE\n\tFrontEndMenuManager.m_nPrefsSubsystem = GcurSel;\n#endif\n\n#ifndef IMPROVED_VIDEOMODE\n\tif ( !useDefault )\n\t{\n\t\tif ( _psGetVideoModeList()[FrontEndMenuManager.m_nDisplayVideoMode] && FrontEndMenuManager.m_nDisplayVideoMode )\n\t\t{\n\t\t\tFrontEndMenuManager.m_nPrefsVideoMode = FrontEndMenuManager.m_nDisplayVideoMode;\n\t\t\tGcurSelVM = FrontEndMenuManager.m_nDisplayVideoMode;\n\t\t}\n\t\telse\n\t\t{\n#ifdef DEFAULT_NATIVE_RESOLUTION\n\t\t\t// get the native video mode\n\t\t\tHDC hDevice = GetDC(NULL);\n\t\t\tint w = GetDeviceCaps(hDevice, HORZRES);\n\t\t\tint h = GetDeviceCaps(hDevice, VERTRES);\n\t\t\tint d = GetDeviceCaps(hDevice, BITSPIXEL);\n#else\n\t\t\tconst int w = 640;\n\t\t\tconst int h = 480;\n\t\t\tconst int d = 16;\n#endif\n\t\t\twhile ( !modeFound && GcurSelVM < RwEngineGetNumVideoModes() )\n\t\t\t{\n\t\t\t\tRwEngineGetVideoModeInfo(&vm, GcurSelVM);\n\t\t\t\tif ( defaultFullscreenRes\t&& vm.width\t != w \n\t\t\t\t\t\t\t\t\t\t\t|| vm.height != h\n\t\t\t\t\t\t\t\t\t\t\t|| vm.depth\t != d\n\t\t\t\t\t\t\t\t\t\t\t|| !(vm.flags & rwVIDEOMODEEXCLUSIVE) )\n\t\t\t\t\t++GcurSelVM;\n\t\t\t\telse\n\t\t\t\t\tmodeFound = TRUE;\n\t\t\t}\n\t\t\t\n\t\t\tif ( !modeFound )\n\t\t\t{\n#ifdef DEFAULT_NATIVE_RESOLUTION\n\t\t\t\tGcurSelVM = 1;\n#else\n\t\t\t\tprintf(\"WARNING: Cannot find 640x480 video mode, selecting device cancelled\\n\");\n\t\t\t\treturn FALSE;\n#endif\n\t\t\t}\n\t\t}\n\t}\n#else\n\tif ( !useDefault )\n\t{\n\t\tif(FrontEndMenuManager.m_nPrefsWidth == 0 ||\n\t\t   FrontEndMenuManager.m_nPrefsHeight == 0 ||\n\t\t   FrontEndMenuManager.m_nPrefsDepth == 0){\n\t\t\t// Defaults if nothing specified\n\t\t\tconst GLFWvidmode *mode = glfwGetVideoMode(glfwGetPrimaryMonitor());\n\t\t\tFrontEndMenuManager.m_nPrefsWidth = mode->width;\n\t\t\tFrontEndMenuManager.m_nPrefsHeight = mode->height;\n\t\t\tFrontEndMenuManager.m_nPrefsDepth = 32;\n\t\t\tFrontEndMenuManager.m_nPrefsWindowed = 0;\n\t\t}\n\n\t\t// Find the videomode that best fits what we got from the settings file\n\t\tRwInt32 bestFsMode = -1;\n\t\tRwInt32 bestWidth = -1;\n\t\tRwInt32 bestHeight = -1;\n\t\tRwInt32 bestDepth = -1;\n\t\tfor(GcurSelVM = 0; GcurSelVM < RwEngineGetNumVideoModes(); GcurSelVM++){\n\t\t\tRwEngineGetVideoModeInfo(&vm, GcurSelVM);\n\n\t\t\tif (!(vm.flags & rwVIDEOMODEEXCLUSIVE)){\n\t\t\t\tbestWndMode = GcurSelVM;\n\t\t\t} else {\n\t\t\t\t// try the largest one that isn't larger than what we wanted\n\t\t\t\tif(vm.width >= bestWidth && vm.width <= FrontEndMenuManager.m_nPrefsWidth &&\n\t\t\t\t   vm.height >= bestHeight && vm.height <= FrontEndMenuManager.m_nPrefsHeight &&\n\t\t\t\t   vm.depth >= bestDepth && vm.depth <= FrontEndMenuManager.m_nPrefsDepth){\n\t\t\t\t\tbestWidth = vm.width;\n\t\t\t\t\tbestHeight = vm.height;\n\t\t\t\t\tbestDepth = vm.depth;\n\t\t\t\t\tbestFsMode = GcurSelVM;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif(bestFsMode < 0){\n\t\t\tprintf(\"WARNING: Cannot find desired video mode, selecting device cancelled\\n\");\n\t\t\treturn FALSE;\n\t\t}\n\t\tGcurSelVM = bestFsMode;\n\n\t\tFrontEndMenuManager.m_nDisplayVideoMode = GcurSelVM;\n\t\tFrontEndMenuManager.m_nPrefsVideoMode = FrontEndMenuManager.m_nDisplayVideoMode;\n\n\t\tFrontEndMenuManager.m_nSelectedScreenMode = FrontEndMenuManager.m_nPrefsWindowed;\n\t}\n#endif\n\n\tRwEngineGetVideoModeInfo(&vm, GcurSelVM);\n\n#ifdef IMPROVED_VIDEOMODE\n\tif (FrontEndMenuManager.m_nPrefsWindowed)\n\t\tGcurSelVM = bestWndMode;\n\n\t// Now GcurSelVM is 0 but vm has sizes(and fullscreen flag) of the video mode we want, that's why we changed the rwVIDEOMODEEXCLUSIVE conditions below\n\tFrontEndMenuManager.m_nPrefsWidth = vm.width;\n\tFrontEndMenuManager.m_nPrefsHeight = vm.height;\n\tFrontEndMenuManager.m_nPrefsDepth = vm.depth;\n#endif\n\n#ifndef PS2_MENU\n\tFrontEndMenuManager.m_nCurrOption = 0;\n#endif\n\t\n\t/* Set up the video mode and set the apps window\n\t* dimensions to match */\n\tif (!RwEngineSetVideoMode(GcurSelVM))\n\t{\n\t\treturn FALSE;\n\t}\n\t/*\n\tTODO\n\tif (vm.flags & rwVIDEOMODEEXCLUSIVE)\n\t{\n\t\tdebug(\"%dx%dx%d\", vm.width, vm.height, vm.depth);\n\t\t\n\t\tUINT refresh = GetBestRefreshRate(vm.width, vm.height, vm.depth);\n\t\t\n\t\tif ( refresh != (UINT)-1 )\n\t\t{\n\t\t\tdebug(\"refresh %d\", refresh);\n\t\t\tRwD3D8EngineSetRefreshRate((RwUInt32)refresh);\n\t\t}\n\t}\n\t*/\n#ifndef IMPROVED_VIDEOMODE\n\tif (vm.flags & rwVIDEOMODEEXCLUSIVE)\n\t{\n\t\tRsGlobal.maximumWidth = vm.width;\n\t\tRsGlobal.maximumHeight = vm.height;\n\t\tRsGlobal.width = vm.width;\n\t\tRsGlobal.height = vm.height;\n\t\t\n\t\tPSGLOBAL(fullScreen) = TRUE;\n\t}\n#else\n\t\tRsGlobal.maximumWidth = FrontEndMenuManager.m_nPrefsWidth;\n\t\tRsGlobal.maximumHeight = FrontEndMenuManager.m_nPrefsHeight;\n\t\tRsGlobal.width = FrontEndMenuManager.m_nPrefsWidth;\n\t\tRsGlobal.height = FrontEndMenuManager.m_nPrefsHeight;\n\t\t\n\t\tPSGLOBAL(fullScreen) = !FrontEndMenuManager.m_nPrefsWindowed;\n#endif\n\n#ifdef MULTISAMPLING\n\tRwD3D8EngineSetMultiSamplingLevels(1 << FrontEndMenuManager.m_nPrefsMSAALevel);\n#endif\n\treturn TRUE;\n}\n\n#ifndef GET_KEYBOARD_INPUT_FROM_X11\nvoid keypressCB(GLFWwindow* window, int key, int scancode, int action, int mods);\n#endif\nvoid resizeCB(GLFWwindow* window, int width, int height);\nvoid scrollCB(GLFWwindow* window, double xoffset, double yoffset);\nvoid cursorCB(GLFWwindow* window, double xpos, double ypos);\nvoid cursorEnterCB(GLFWwindow* window, int entered);\nvoid windowFocusCB(GLFWwindow* window, int focused);\nvoid windowIconifyCB(GLFWwindow* window, int iconified);\nvoid joysChangeCB(int jid, int event);\n\nbool IsThisJoystickBlacklisted(int i)\n{\n#ifndef DETECT_JOYSTICK_MENU\n\treturn false;\n#else\n\tif (glfwJoystickIsGamepad(i))\n\t\treturn false;\n\n\tconst char* joyname = glfwGetJoystickName(i);\n\n\tif (gSelectedJoystickName[0] != '\\0' &&\n\t\tstrncmp(joyname, gSelectedJoystickName, strlen(gSelectedJoystickName)) == 0)\n\t\treturn false;\n\n\treturn true;\n#endif\n}\n\nvoid _InputInitialiseJoys()\n{\n\tPSGLOBAL(joy1id) = -1;\n\tPSGLOBAL(joy2id) = -1;\n\n\t// Load our gamepad mappings.\n#define SDL_GAMEPAD_DB_PATH \"gamecontrollerdb.txt\"\n\tFILE *f = fopen(SDL_GAMEPAD_DB_PATH, \"rb\");\n\tif (f) {\n\t\tfseek(f, 0, SEEK_END);\n\t\tsize_t fsize = ftell(f);\n\t\tfseek(f, 0, SEEK_SET);\n\n\t\tchar *db = (char*)malloc(fsize + 1);\n\t\tif (fread(db, 1, fsize, f) == fsize) {\n\t\t\tdb[fsize] = '\\0';\n\n\t\t\tif (glfwUpdateGamepadMappings(db) == GLFW_FALSE)\n\t\t\t\tError(\"glfwUpdateGamepadMappings didn't succeed, check \" SDL_GAMEPAD_DB_PATH \".\\n\");\n\t\t} else\n\t\t\tError(\"fread on \" SDL_GAMEPAD_DB_PATH \" wasn't successful.\\n\");\n\n\t\tfree(db);\n\t\tfclose(f);\n\t} else\n\t\tprintf(\"You don't seem to have copied \" SDL_GAMEPAD_DB_PATH \" file from re3/gamefiles to GTA3 directory. Some gamepads may not be recognized.\\n\");\n\n#undef SDL_GAMEPAD_DB_PATH\n\n\t// But always overwrite it with the one in SDL_GAMECONTROLLERCONFIG.\n\tchar const* EnvControlConfig = getenv(\"SDL_GAMECONTROLLERCONFIG\");\n\tif (EnvControlConfig != nil) {\n\t\tglfwUpdateGamepadMappings(EnvControlConfig);\n\t}\n\n\tfor (int i = 0; i <= GLFW_JOYSTICK_LAST; i++) {\n\t\tif (glfwJoystickPresent(i) && !IsThisJoystickBlacklisted(i)) {\n\t\t\tif (PSGLOBAL(joy1id) == -1)\n\t\t\t\tPSGLOBAL(joy1id) = i;\n\t\t\telse if (PSGLOBAL(joy2id) == -1)\n\t\t\t\tPSGLOBAL(joy2id) = i;\n\t\t\telse\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tif (PSGLOBAL(joy1id) != -1) {\n\t\tint count;\n\t\tglfwGetJoystickButtons(PSGLOBAL(joy1id), &count);\n#ifdef DETECT_JOYSTICK_MENU\n\t\tstrcpy(gSelectedJoystickName, glfwGetJoystickName(PSGLOBAL(joy1id)));\n#endif\n\t\tControlsManager.InitDefaultControlConfigJoyPad(count);\n\t}\n}\n\nint lastCursorMode = GLFW_CURSOR_HIDDEN;\nlong _InputInitialiseMouse(bool exclusive)\n{\n\t// Disabled = keep cursor centered and hide\n\tlastCursorMode = exclusive ? GLFW_CURSOR_DISABLED : GLFW_CURSOR_HIDDEN;\n\tglfwSetInputMode(PSGLOBAL(window), GLFW_CURSOR, lastCursorMode);\n\treturn 0;\n}\n\nvoid _InputShutdownMouse()\n{\n\t// Not needed\n}\n\n// Not \"needs exclusive\" on GLFW, but more like \"needs to change mode\"\nbool _InputMouseNeedsExclusive()\n{\n\t// That was the cause of infamous mouse bug on Win.\n\t\n\tRwVideoMode vm;\n\tRwEngineGetVideoModeInfo(&vm, GcurSelVM);\n\n\t// If windowed, free the cursor on menu(where this func. is called and DISABLED-HIDDEN transition is done accordingly)\n\t// If it's fullscreen, be sure that it didn't stuck on HIDDEN.\n\treturn !(vm.flags & rwVIDEOMODEEXCLUSIVE) || lastCursorMode == GLFW_CURSOR_HIDDEN;\n}\n\nvoid psPostRWinit(void)\n{\n\tRwVideoMode vm;\n\tRwEngineGetVideoModeInfo(&vm, GcurSelVM);\n\n#ifndef GET_KEYBOARD_INPUT_FROM_X11\n\tglfwSetKeyCallback(PSGLOBAL(window), keypressCB);\n#endif\n\tglfwSetFramebufferSizeCallback(PSGLOBAL(window), resizeCB);\n\tglfwSetScrollCallback(PSGLOBAL(window), scrollCB);\n\tglfwSetCursorPosCallback(PSGLOBAL(window), cursorCB);\n\tglfwSetCursorEnterCallback(PSGLOBAL(window), cursorEnterCB);\n\tglfwSetWindowIconifyCallback(PSGLOBAL(window), windowIconifyCB);\n\tglfwSetWindowFocusCallback(PSGLOBAL(window), windowFocusCB);\n\tglfwSetJoystickCallback(joysChangeCB);\n\n\t_InputInitialiseJoys();\n\t_InputInitialiseMouse(false);\n\n\tif(!(vm.flags & rwVIDEOMODEEXCLUSIVE))\n\t\tglfwSetWindowSize(PSGLOBAL(window), RsGlobal.maximumWidth, RsGlobal.maximumHeight);\n\n\t// Make sure all keys are released\n\tCPad::GetPad(0)->Clear(true);\n\tCPad::GetPad(1)->Clear(true);\n}\n\n/*\n *****************************************************************************\n */\nRwBool _psSetVideoMode(RwInt32 subSystem, RwInt32 videoMode)\n{\n\tRwInitialised = FALSE;\n\t\n\tRsEventHandler(rsRWTERMINATE, nil);\n\t\n\tGcurSel = subSystem;\n\tGcurSelVM = videoMode;\n\t\n\tuseDefault = TRUE;\n\t\n\tif ( RsEventHandler(rsRWINITIALIZE, &openParams) == rsEVENTERROR )\n\t\treturn FALSE;\n\n\tRwInitialised = TRUE;\n\tuseDefault = FALSE;\n\t\n\tRwRect r;\n\t\n\tr.x = 0;\n\tr.y = 0;\n\tr.w = RsGlobal.maximumWidth;\n\tr.h = RsGlobal.maximumHeight;\n\n\tRsEventHandler(rsCAMERASIZE, &r);\n\t\n\tpsPostRWinit();\n\t\n\treturn TRUE;\n}\n \n \n/*\n *****************************************************************************\n */\nstatic RwChar **\nCommandLineToArgv(RwChar *cmdLine, RwInt32 *argCount)\n{\n\tRwInt32 numArgs = 0;\n\tRwBool inArg, inString;\n\tRwInt32 i, len;\n\tRwChar *res, *str, **aptr;\n\n\tlen = strlen(cmdLine);\n\n\t/* \n\t * Count the number of arguments...\n\t */\n\tinString = FALSE;\n\tinArg = FALSE;\n\n\tfor(i=0; i<=len; i++)\n\t{\n\t\tif( cmdLine[i] == '\"' )\n\t\t{\n\t\t\tinString = !inString;\n\t\t}\n\n\t\tif( (cmdLine[i] <= ' ' && !inString) || i == len )\n\t\t{\n\t\t\tif( inArg ) \n\t\t\t{\n\t\t\t\tinArg = FALSE;\n\t\t\t\t\n\t\t\t\tnumArgs++;\n\t\t\t}\n\t\t} \n\t\telse if( !inArg )\n\t\t{\n\t\t\tinArg = TRUE;\n\t\t}\n\t}\n\n\t/* \n\t * Allocate memory for result...\n\t */\n\tres = (RwChar *)malloc(sizeof(RwChar *) * numArgs + len + 1);\n\tstr = res + sizeof(RwChar *) * numArgs;\n\taptr = (RwChar **)res;\n\n\tstrcpy(str, cmdLine);\n\n\t/*\n\t * Walk through cmdLine again this time setting pointer to each arg...\n\t */\n\tinArg = FALSE;\n\tinString = FALSE;\n\n\tfor(i=0; i<=len; i++)\n\t{\n\t\tif( cmdLine[i] == '\"' )\n\t\t{\n\t\t\tinString = !inString;\n\t\t}\n\n\t\tif( (cmdLine[i] <= ' ' && !inString) || i == len )\n\t\t{\n\t\t\tif( inArg ) \n\t\t\t{\n\t\t\t\tif( str[i-1] == '\"' )\n\t\t\t\t{\n\t\t\t\t\tstr[i-1] = '\\0';\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tstr[i] = '\\0';\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tinArg = FALSE;\n\t\t\t}\n\t\t} \n\t\telse if( !inArg && cmdLine[i] != '\"' )\n\t\t{\n\t\t\tinArg = TRUE; \n\t\t\t\n\t\t\t*aptr++ = &str[i];\n\t\t}\n\t}\n\n\t*argCount = numArgs;\n\n\treturn (RwChar **)res;\n}\n\n/*\n *****************************************************************************\n */\nvoid InitialiseLanguage()\n{\n#ifndef _WIN32\n\t// Mandatory for Linux(Unix? Posix?) to set lang. to environment lang.\n\tsetlocale(LC_ALL, \"\");\t\n\n\tchar *systemLang, *keyboardLang;\n\n\tsystemLang = setlocale (LC_ALL, NULL);\n\tkeyboardLang = setlocale (LC_CTYPE, NULL);\n\t\n\tshort primUserLCID, primSystemLCID;\n\tprimUserLCID = primSystemLCID = !strncmp(systemLang, \"fr_\",3) ? LANG_FRENCH :\n\t\t\t\t\t!strncmp(systemLang, \"de_\",3) ? LANG_GERMAN :\n\t\t\t\t\t!strncmp(systemLang, \"en_\",3) ? LANG_ENGLISH :\n\t\t\t\t\t!strncmp(systemLang, \"it_\",3) ? LANG_ITALIAN :\n\t\t\t\t\t!strncmp(systemLang, \"es_\",3) ? LANG_SPANISH :\n\t\t\t\t\tLANG_OTHER;\n\n\tshort primLayout = !strncmp(keyboardLang, \"fr_\",3) ? LANG_FRENCH : (!strncmp(keyboardLang, \"de_\",3) ? LANG_GERMAN : LANG_ENGLISH);\n\n\tshort subUserLCID, subSystemLCID;\n\tsubUserLCID = subSystemLCID = !strncmp(systemLang, \"en_AU\",5) ? SUBLANG_ENGLISH_AUS : SUBLANG_OTHER;\n\tshort subLayout = !strncmp(keyboardLang, \"en_AU\",5) ? SUBLANG_ENGLISH_AUS : SUBLANG_OTHER;\n\n#else\n\tWORD primUserLCID\t= PRIMARYLANGID(GetSystemDefaultLCID());\n\tWORD primSystemLCID = PRIMARYLANGID(GetUserDefaultLCID());\n\tWORD primLayout\t\t= PRIMARYLANGID((DWORD)GetKeyboardLayout(0));\n\t\n\tWORD subUserLCID\t= SUBLANGID(GetSystemDefaultLCID());\n\tWORD subSystemLCID\t= SUBLANGID(GetUserDefaultLCID());\n\tWORD subLayout\t\t= SUBLANGID((DWORD)GetKeyboardLayout(0));\n#endif\n\tif (   primUserLCID\t  == LANG_GERMAN\n\t\t|| primSystemLCID == LANG_GERMAN\n\t\t|| primLayout\t  == LANG_GERMAN )\n\t{\n\t\tCGame::nastyGame = false;\n\t\tFrontEndMenuManager.m_PrefsAllowNastyGame = false;\n\t\tCGame::germanGame = true;\n\t}\n\t\n\tif (   primUserLCID\t  == LANG_FRENCH\n\t\t|| primSystemLCID == LANG_FRENCH\n\t\t|| primLayout\t  == LANG_FRENCH )\n\t{\n\t\tCGame::nastyGame = false;\n\t\tFrontEndMenuManager.m_PrefsAllowNastyGame = false;\n\t\tCGame::frenchGame = true;\n\t}\n\t\n\tif (   subUserLCID\t == SUBLANG_ENGLISH_AUS\n\t\t|| subSystemLCID == SUBLANG_ENGLISH_AUS\n\t\t|| subLayout\t == SUBLANG_ENGLISH_AUS )\n\t\tCGame::noProstitutes = true;\n\n#ifdef NASTY_GAME\n\tCGame::nastyGame = true;\n\tFrontEndMenuManager.m_PrefsAllowNastyGame = true;\n\tCGame::noProstitutes = false;\n#endif\n\t\n\tint32 lang;\n\t\n\tswitch ( primSystemLCID )\n\t{\n\t\tcase LANG_GERMAN:\n\t\t{\n\t\t\tlang = LANG_GERMAN;\n\t\t\tbreak;\n\t\t}\n\t\tcase LANG_FRENCH:\n\t\t{\n\t\t\tlang = LANG_FRENCH;\n\t\t\tbreak;\n\t\t}\n\t\tcase LANG_SPANISH:\n\t\t{\n\t\t\tlang = LANG_SPANISH;\n\t\t\tbreak;\n\t\t}\n\t\tcase LANG_ITALIAN:\n\t\t{\n\t\t\tlang = LANG_ITALIAN;\n\t\t\tbreak;\n\t\t}\n\t\tdefault:\n\t\t{\n\t\t\tlang = ( subSystemLCID == SUBLANG_ENGLISH_AUS ) ? -99 : LANG_ENGLISH;\n\t\t\tbreak;\n\t\t}\n\t}\n\t\n\tFrontEndMenuManager.OS_Language = primUserLCID;\n\n\tswitch ( lang )\n\t{\n\t\tcase LANG_GERMAN:\n\t\t{\n\t\t\tFrontEndMenuManager.m_PrefsLanguage = CMenuManager::LANGUAGE_GERMAN;\n\t\t\tbreak;\n\t\t}\n\t\tcase LANG_SPANISH:\n\t\t{\n\t\t\tFrontEndMenuManager.m_PrefsLanguage = CMenuManager::LANGUAGE_SPANISH;\n\t\t\tbreak;\n\t\t}\n\t\tcase LANG_FRENCH:\n\t\t{\n\t\t\tFrontEndMenuManager.m_PrefsLanguage = CMenuManager::LANGUAGE_FRENCH;\n\t\t\tbreak;\n\t\t}\n\t\tcase LANG_ITALIAN:\n\t\t{\n\t\t\tFrontEndMenuManager.m_PrefsLanguage = CMenuManager::LANGUAGE_ITALIAN;\n\t\t\tbreak;\n\t\t}\n\t\tdefault:\n\t\t{\n\t\t\tFrontEndMenuManager.m_PrefsLanguage = CMenuManager::LANGUAGE_AMERICAN;\n\t\t\tbreak;\n\t\t}\n\t}\n\n#ifndef _WIN32\n\t// TODO this is needed for strcasecmp to work correctly across all languages, but can these cause other problems??\n\tsetlocale(LC_CTYPE, \"C\");\n\tsetlocale(LC_COLLATE, \"C\");\n\tsetlocale(LC_NUMERIC, \"C\");\n#endif\n\n\tTheText.Unload();\n\tTheText.Load();\n}\n\n/*\n *****************************************************************************\n */\n\nvoid HandleExit()\n{\n#ifdef _WIN32\n\tMSG message;\n\twhile ( PeekMessage(&message, nil, 0U, 0U, PM_REMOVE|PM_NOYIELD) )\n\t{\n\t\tif( message.message == WM_QUIT )\n\t\t{\n\t\t\tRsGlobal.quit = TRUE;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tTranslateMessage(&message);\n\t\t\tDispatchMessage(&message);\n\t\t}\n\t}\n#else\n\t// We now handle terminate message always, why handle on some cases?\n\treturn;\n#endif\n}\n\n#ifndef _WIN32\nvoid terminateHandler(int sig, siginfo_t *info, void *ucontext) {\n\tRsGlobal.quit = TRUE;\n}\n\n#ifdef FLUSHABLE_STREAMING\nvoid dummyHandler(int sig){\n\t// Don't kill the app pls\n}\n#endif\n#endif\n\nvoid resizeCB(GLFWwindow* window, int width, int height) {\n\t/*\n\t* Handle event to ensure window contents are displayed during re-size\n\t* as this can be disabled by the user, then if there is not enough\n\t* memory things don't work.\n\t*/\n\t/* redraw window */\n\n\tif (RwInitialised && gGameState == GS_PLAYING_GAME)\n\t{\n\t\tRsEventHandler(rsIDLE, (void *)TRUE);\n\t}\n\n\tif (RwInitialised && height > 0 && width > 0) {\n\t\tRwRect r;\n\n\t\t// TODO fix artifacts of resizing with mouse\n\t\tRsGlobal.maximumHeight = height;\n\t\tRsGlobal.maximumWidth = width;\n\n\t\tr.x = 0;\n\t\tr.y = 0;\n\t\tr.w = width;\n\t\tr.h = height;\n\n\t\tRsEventHandler(rsCAMERASIZE, &r);\n\t}\n//\tglfwSetWindowPos(window, 0, 0);\n}\n\nvoid scrollCB(GLFWwindow* window, double xoffset, double yoffset) {\n\tPSGLOBAL(mouseWheel) = yoffset;\n}\n\nbool lshiftStatus = false;\nbool rshiftStatus = false;\n\n#ifndef GET_KEYBOARD_INPUT_FROM_X11\nint keymap[GLFW_KEY_LAST + 1];\n\nstatic void\ninitkeymap(void)\n{\n\tint i;\n\tfor (i = 0; i < GLFW_KEY_LAST + 1; i++)\n\t\tkeymap[i] = rsNULL;\n\n\tkeymap[GLFW_KEY_SPACE] = ' ';\n\tkeymap[GLFW_KEY_APOSTROPHE] = '\\'';\n\tkeymap[GLFW_KEY_COMMA] = ',';\n\tkeymap[GLFW_KEY_MINUS] = '-';\n\tkeymap[GLFW_KEY_PERIOD] = '.';\n\tkeymap[GLFW_KEY_SLASH] = '/';\n\tkeymap[GLFW_KEY_0] = '0';\n\tkeymap[GLFW_KEY_1] = '1';\n\tkeymap[GLFW_KEY_2] = '2';\n\tkeymap[GLFW_KEY_3] = '3';\n\tkeymap[GLFW_KEY_4] = '4';\n\tkeymap[GLFW_KEY_5] = '5';\n\tkeymap[GLFW_KEY_6] = '6';\n\tkeymap[GLFW_KEY_7] = '7';\n\tkeymap[GLFW_KEY_8] = '8';\n\tkeymap[GLFW_KEY_9] = '9';\n\tkeymap[GLFW_KEY_SEMICOLON] = ';';\n\tkeymap[GLFW_KEY_EQUAL] = '=';\n\tkeymap[GLFW_KEY_A] = 'A';\n\tkeymap[GLFW_KEY_B] = 'B';\n\tkeymap[GLFW_KEY_C] = 'C';\n\tkeymap[GLFW_KEY_D] = 'D';\n\tkeymap[GLFW_KEY_E] = 'E';\n\tkeymap[GLFW_KEY_F] = 'F';\n\tkeymap[GLFW_KEY_G] = 'G';\n\tkeymap[GLFW_KEY_H] = 'H';\n\tkeymap[GLFW_KEY_I] = 'I';\n\tkeymap[GLFW_KEY_J] = 'J';\n\tkeymap[GLFW_KEY_K] = 'K';\n\tkeymap[GLFW_KEY_L] = 'L';\n\tkeymap[GLFW_KEY_M] = 'M';\n\tkeymap[GLFW_KEY_N] = 'N';\n\tkeymap[GLFW_KEY_O] = 'O';\n\tkeymap[GLFW_KEY_P] = 'P';\n\tkeymap[GLFW_KEY_Q] = 'Q';\n\tkeymap[GLFW_KEY_R] = 'R';\n\tkeymap[GLFW_KEY_S] = 'S';\n\tkeymap[GLFW_KEY_T] = 'T';\n\tkeymap[GLFW_KEY_U] = 'U';\n\tkeymap[GLFW_KEY_V] = 'V';\n\tkeymap[GLFW_KEY_W] = 'W';\n\tkeymap[GLFW_KEY_X] = 'X';\n\tkeymap[GLFW_KEY_Y] = 'Y';\n\tkeymap[GLFW_KEY_Z] = 'Z';\n\tkeymap[GLFW_KEY_LEFT_BRACKET] = '[';\n\tkeymap[GLFW_KEY_BACKSLASH] = '\\\\';\n\tkeymap[GLFW_KEY_RIGHT_BRACKET] = ']';\n\tkeymap[GLFW_KEY_GRAVE_ACCENT] = '`';\n\tkeymap[GLFW_KEY_ESCAPE] = rsESC;\n\tkeymap[GLFW_KEY_ENTER] = rsENTER;\n\tkeymap[GLFW_KEY_TAB] = rsTAB;\n\tkeymap[GLFW_KEY_BACKSPACE] = rsBACKSP;\n\tkeymap[GLFW_KEY_INSERT] = rsINS;\n\tkeymap[GLFW_KEY_DELETE] = rsDEL;\n\tkeymap[GLFW_KEY_RIGHT] = rsRIGHT;\n\tkeymap[GLFW_KEY_LEFT] = rsLEFT;\n\tkeymap[GLFW_KEY_DOWN] = rsDOWN;\n\tkeymap[GLFW_KEY_UP] = rsUP;\n\tkeymap[GLFW_KEY_PAGE_UP] = rsPGUP;\n\tkeymap[GLFW_KEY_PAGE_DOWN] = rsPGDN;\n\tkeymap[GLFW_KEY_HOME] = rsHOME;\n\tkeymap[GLFW_KEY_END] = rsEND;\n\tkeymap[GLFW_KEY_CAPS_LOCK] = rsCAPSLK;\n\tkeymap[GLFW_KEY_SCROLL_LOCK] = rsSCROLL;\n\tkeymap[GLFW_KEY_NUM_LOCK] = rsNUMLOCK;\n\tkeymap[GLFW_KEY_PRINT_SCREEN] = rsNULL;\n\tkeymap[GLFW_KEY_PAUSE] = rsPAUSE;\n\n\tkeymap[GLFW_KEY_F1] = rsF1;\n\tkeymap[GLFW_KEY_F2] = rsF2;\n\tkeymap[GLFW_KEY_F3] = rsF3;\n\tkeymap[GLFW_KEY_F4] = rsF4;\n\tkeymap[GLFW_KEY_F5] = rsF5;\n\tkeymap[GLFW_KEY_F6] = rsF6;\n\tkeymap[GLFW_KEY_F7] = rsF7;\n\tkeymap[GLFW_KEY_F8] = rsF8;\n\tkeymap[GLFW_KEY_F9] = rsF9;\n\tkeymap[GLFW_KEY_F10] = rsF10;\n\tkeymap[GLFW_KEY_F11] = rsF11;\n\tkeymap[GLFW_KEY_F12] = rsF12;\n\tkeymap[GLFW_KEY_F13] = rsNULL;\n\tkeymap[GLFW_KEY_F14] = rsNULL;\n\tkeymap[GLFW_KEY_F15] = rsNULL;\n\tkeymap[GLFW_KEY_F16] = rsNULL;\n\tkeymap[GLFW_KEY_F17] = rsNULL;\n\tkeymap[GLFW_KEY_F18] = rsNULL;\n\tkeymap[GLFW_KEY_F19] = rsNULL;\n\tkeymap[GLFW_KEY_F20] = rsNULL;\n\tkeymap[GLFW_KEY_F21] = rsNULL;\n\tkeymap[GLFW_KEY_F22] = rsNULL;\n\tkeymap[GLFW_KEY_F23] = rsNULL;\n\tkeymap[GLFW_KEY_F24] = rsNULL;\n\tkeymap[GLFW_KEY_F25] = rsNULL;\n\tkeymap[GLFW_KEY_KP_0] = rsPADINS;\n\tkeymap[GLFW_KEY_KP_1] = rsPADEND;\n\tkeymap[GLFW_KEY_KP_2] = rsPADDOWN;\n\tkeymap[GLFW_KEY_KP_3] = rsPADPGDN;\n\tkeymap[GLFW_KEY_KP_4] = rsPADLEFT;\n\tkeymap[GLFW_KEY_KP_5] = rsPAD5;\n\tkeymap[GLFW_KEY_KP_6] = rsPADRIGHT;\n\tkeymap[GLFW_KEY_KP_7] = rsPADHOME;\n\tkeymap[GLFW_KEY_KP_8] = rsPADUP;\n\tkeymap[GLFW_KEY_KP_9] = rsPADPGUP;\n\tkeymap[GLFW_KEY_KP_DECIMAL] = rsPADDEL;\n\tkeymap[GLFW_KEY_KP_DIVIDE] = rsDIVIDE;\n\tkeymap[GLFW_KEY_KP_MULTIPLY] = rsTIMES;\n\tkeymap[GLFW_KEY_KP_SUBTRACT] = rsMINUS;\n\tkeymap[GLFW_KEY_KP_ADD] = rsPLUS;\n\tkeymap[GLFW_KEY_KP_ENTER] = rsPADENTER;\n\tkeymap[GLFW_KEY_KP_EQUAL] = rsNULL;\n\tkeymap[GLFW_KEY_LEFT_SHIFT] = rsLSHIFT;\n\tkeymap[GLFW_KEY_LEFT_CONTROL] = rsLCTRL;\n\tkeymap[GLFW_KEY_LEFT_ALT] = rsLALT;\n\tkeymap[GLFW_KEY_LEFT_SUPER] = rsLWIN;\n\tkeymap[GLFW_KEY_RIGHT_SHIFT] = rsRSHIFT;\n\tkeymap[GLFW_KEY_RIGHT_CONTROL] = rsRCTRL;\n\tkeymap[GLFW_KEY_RIGHT_ALT] = rsRALT;\n\tkeymap[GLFW_KEY_RIGHT_SUPER] = rsRWIN;\n\tkeymap[GLFW_KEY_MENU] = rsNULL;\n}\n\nvoid\nkeypressCB(GLFWwindow* window, int key, int scancode, int action, int mods)\n{\n\tif (key >= 0 && key <= GLFW_KEY_LAST && action != GLFW_REPEAT) {\n\t\tRsKeyCodes ks = (RsKeyCodes)keymap[key];\n\n\t\tif (key == GLFW_KEY_LEFT_SHIFT)\n\t\t\tlshiftStatus = action != GLFW_RELEASE;\n\n\t\tif (key == GLFW_KEY_RIGHT_SHIFT)\n\t\t\trshiftStatus = action != GLFW_RELEASE;\n\n\t\tif (action == GLFW_RELEASE) RsKeyboardEventHandler(rsKEYUP, &ks);\n\t\telse if (action == GLFW_PRESS) RsKeyboardEventHandler(rsKEYDOWN, &ks);\n\t}\n}\n\n#else\n\nuint32 keymap[512]; // 256 ascii + 256 KeySyms between 0xff00 - 0xffff\nbool keyStates[512];\nuint32 keyCodeToKeymapIndex[256]; // cache for physical keys\n\n#define KEY_MAP_OFFSET (0xff00 - 256)\nstatic void\ninitkeymap(void)\n{\n\tDisplay *display = glfwGetX11Display();\n\tint i;\n\n\tfor (i = 0; i < ARRAY_SIZE(keymap); i++)\n\t\tkeymap[i] = rsNULL;\n\n\t// You can add new ASCII mappings to here freely (but beware that if right hand side of assignment isn't supported on CFont, it'll be blank/won't work on binding screen)\n\t// Right hand side of assigments should always be uppercase counterpart of character\n\tkeymap[XK_space] = ' ';\n\tkeymap[XK_apostrophe] = '\\'';\n\tkeymap[XK_ampersand] = '&';\n\tkeymap[XK_percent] = '%';\n\tkeymap[XK_dollar] = '$';\n\tkeymap[XK_comma] = ',';\n\tkeymap[XK_minus] = '-';\n\tkeymap[XK_period] = '.';\n\tkeymap[XK_slash] = '/';\n\tkeymap[XK_question] = '?';\n\tkeymap[XK_exclam] = '!';\n\tkeymap[XK_quotedbl] = '\"';\n\tkeymap[XK_colon] = ':';\n\tkeymap[XK_semicolon] = ';';\n\tkeymap[XK_equal] = '=';\n\tkeymap[XK_bracketleft] = '[';\n\tkeymap[XK_backslash] = '\\\\';\n\tkeymap[XK_bracketright] = ']';\n\tkeymap[XK_grave] = '`';\n\tkeymap[XK_0] = '0';\n\tkeymap[XK_1] = '1';\n\tkeymap[XK_2] = '2';\n\tkeymap[XK_3] = '3';\n\tkeymap[XK_4] = '4';\n\tkeymap[XK_5] = '5';\n\tkeymap[XK_6] = '6';\n\tkeymap[XK_7] = '7';\n\tkeymap[XK_8] = '8';\n\tkeymap[XK_9] = '9';\n\tkeymap[XK_a] = 'A';\n\tkeymap[XK_b] = 'B';\n\tkeymap[XK_c] = 'C';\n\tkeymap[XK_d] = 'D';\n\tkeymap[XK_e] = 'E';\n\tkeymap[XK_f] = 'F';\n\tkeymap[XK_g] = 'G';\n\tkeymap[XK_h] = 'H';\n\tkeymap[XK_i] = 'I';\n\tkeymap[XK_I] = 'I'; // Turkish I problem\n\tkeymap[XK_j] = 'J';\n\tkeymap[XK_k] = 'K';\n\tkeymap[XK_l] = 'L';\n\tkeymap[XK_m] = 'M';\n\tkeymap[XK_n] = 'N';\n\tkeymap[XK_o] = 'O';\n\tkeymap[XK_p] = 'P';\n\tkeymap[XK_q] = 'Q';\n\tkeymap[XK_r] = 'R';\n\tkeymap[XK_s] = 'S';\n\tkeymap[XK_t] = 'T';\n\tkeymap[XK_u] = 'U';\n\tkeymap[XK_v] = 'V';\n\tkeymap[XK_w] = 'W';\n\tkeymap[XK_x] = 'X';\n\tkeymap[XK_y] = 'Y';\n\tkeymap[XK_z] = 'Z';\n\n\t// Some of regional but ASCII characters that GTA supports\n\tkeymap[XK_agrave] = 0x00c0;\n\tkeymap[XK_aacute] = 0x00c1;\n\tkeymap[XK_acircumflex] = 0x00c2;\n\tkeymap[XK_adiaeresis] = 0x00c4;\n\n\tkeymap[XK_ae] = 0x00c6;\n\n\tkeymap[XK_egrave] = 0x00c8;\n\tkeymap[XK_eacute] = 0x00c9;\n\tkeymap[XK_ecircumflex] = 0x00ca;\n\tkeymap[XK_ediaeresis] = 0x00cb;\n\n\tkeymap[XK_igrave] = 0x00cc;\n\tkeymap[XK_iacute] = 0x00cd;\n\tkeymap[XK_icircumflex] = 0x00ce;\n\tkeymap[XK_idiaeresis] = 0x00cf;\n\n\tkeymap[XK_ccedilla] = 0x00c7;\n\tkeymap[XK_odiaeresis] = 0x00d6;\n\tkeymap[XK_udiaeresis] = 0x00dc;\n\n\t// These are 0xff00 - 0xffff range of KeySym's, and subtracting KEY_MAP_OFFSET is needed\n\tkeymap[XK_Escape - KEY_MAP_OFFSET] = rsESC;\n\tkeymap[XK_Return - KEY_MAP_OFFSET] = rsENTER;\n\tkeymap[XK_Tab - KEY_MAP_OFFSET] = rsTAB;\n\tkeymap[XK_BackSpace - KEY_MAP_OFFSET] = rsBACKSP;\n\tkeymap[XK_Insert - KEY_MAP_OFFSET] = rsINS;\n\tkeymap[XK_Delete - KEY_MAP_OFFSET] = rsDEL;\n\tkeymap[XK_Right - KEY_MAP_OFFSET] = rsRIGHT;\n\tkeymap[XK_Left - KEY_MAP_OFFSET] = rsLEFT;\n\tkeymap[XK_Down - KEY_MAP_OFFSET] = rsDOWN;\n\tkeymap[XK_Up - KEY_MAP_OFFSET] = rsUP;\n\tkeymap[XK_Page_Up - KEY_MAP_OFFSET] = rsPGUP;\n\tkeymap[XK_Page_Down - KEY_MAP_OFFSET] = rsPGDN;\n\tkeymap[XK_Home - KEY_MAP_OFFSET] = rsHOME;\n\tkeymap[XK_End - KEY_MAP_OFFSET] = rsEND;\n\tkeymap[XK_Caps_Lock - KEY_MAP_OFFSET] = rsCAPSLK;\n\tkeymap[XK_Scroll_Lock - KEY_MAP_OFFSET] = rsSCROLL;\n\tkeymap[XK_Num_Lock - KEY_MAP_OFFSET] = rsNUMLOCK;\n\tkeymap[XK_Pause - KEY_MAP_OFFSET] = rsPAUSE;\n\n\tkeymap[XK_F1 - KEY_MAP_OFFSET] = rsF1;\n\tkeymap[XK_F2 - KEY_MAP_OFFSET] = rsF2;\n\tkeymap[XK_F3 - KEY_MAP_OFFSET] = rsF3;\n\tkeymap[XK_F4 - KEY_MAP_OFFSET] = rsF4;\n\tkeymap[XK_F5 - KEY_MAP_OFFSET] = rsF5;\n\tkeymap[XK_F6 - KEY_MAP_OFFSET] = rsF6;\n\tkeymap[XK_F7 - KEY_MAP_OFFSET] = rsF7;\n\tkeymap[XK_F8 - KEY_MAP_OFFSET] = rsF8;\n\tkeymap[XK_F9 - KEY_MAP_OFFSET] = rsF9;\n\tkeymap[XK_F10 - KEY_MAP_OFFSET] = rsF10;\n\tkeymap[XK_F11 - KEY_MAP_OFFSET] = rsF11;\n\tkeymap[XK_F12 - KEY_MAP_OFFSET] = rsF12;\n\tkeymap[XK_F13 - KEY_MAP_OFFSET] = rsNULL;\n\tkeymap[XK_F14 - KEY_MAP_OFFSET] = rsNULL;\n\tkeymap[XK_F15 - KEY_MAP_OFFSET] = rsNULL;\n\tkeymap[XK_F16 - KEY_MAP_OFFSET] = rsNULL;\n\tkeymap[XK_F17 - KEY_MAP_OFFSET] = rsNULL;\n\tkeymap[XK_F18 - KEY_MAP_OFFSET] = rsNULL;\n\tkeymap[XK_F19 - KEY_MAP_OFFSET] = rsNULL;\n\tkeymap[XK_F20 - KEY_MAP_OFFSET] = rsNULL;\n\tkeymap[XK_F21 - KEY_MAP_OFFSET] = rsNULL;\n\tkeymap[XK_F22 - KEY_MAP_OFFSET] = rsNULL;\n\tkeymap[XK_F23 - KEY_MAP_OFFSET] = rsNULL;\n\tkeymap[XK_F24 - KEY_MAP_OFFSET] = rsNULL;\n\tkeymap[XK_F25 - KEY_MAP_OFFSET] = rsNULL;\n\n\tkeymap[XK_KP_0 - KEY_MAP_OFFSET] = rsPADINS;\n\tkeymap[XK_KP_1 - KEY_MAP_OFFSET] = rsPADEND;\n\tkeymap[XK_KP_2 - KEY_MAP_OFFSET] = rsPADDOWN;\n\tkeymap[XK_KP_3 - KEY_MAP_OFFSET] = rsPADPGDN;\n\tkeymap[XK_KP_4 - KEY_MAP_OFFSET] = rsPADLEFT;\n\tkeymap[XK_KP_5 - KEY_MAP_OFFSET] = rsPAD5;\n\tkeymap[XK_KP_6 - KEY_MAP_OFFSET] = rsPADRIGHT;\n\tkeymap[XK_KP_7 - KEY_MAP_OFFSET] = rsPADHOME;\n\tkeymap[XK_KP_8 - KEY_MAP_OFFSET] = rsPADUP;\n\tkeymap[XK_KP_9 - KEY_MAP_OFFSET] = rsPADPGUP;\n\tkeymap[XK_KP_Insert - KEY_MAP_OFFSET] = rsPADINS;\n\tkeymap[XK_KP_End - KEY_MAP_OFFSET] = rsPADEND;\n\tkeymap[XK_KP_Down - KEY_MAP_OFFSET] = rsPADDOWN;\n\tkeymap[XK_KP_Page_Down - KEY_MAP_OFFSET] = rsPADPGDN;\n\tkeymap[XK_KP_Left - KEY_MAP_OFFSET] = rsPADLEFT;\n\tkeymap[XK_KP_Begin - KEY_MAP_OFFSET] = rsPAD5;\n\tkeymap[XK_KP_Right - KEY_MAP_OFFSET] = rsPADRIGHT;\n\tkeymap[XK_KP_Home - KEY_MAP_OFFSET] = rsPADHOME;\n\tkeymap[XK_KP_Up - KEY_MAP_OFFSET] = rsPADUP;\n\tkeymap[XK_KP_Page_Up - KEY_MAP_OFFSET] = rsPADPGUP;\n\n\tkeymap[XK_KP_Decimal - KEY_MAP_OFFSET] = rsPADDEL;\n\tkeymap[XK_KP_Divide - KEY_MAP_OFFSET] = rsDIVIDE;\n\tkeymap[XK_KP_Multiply - KEY_MAP_OFFSET] = rsTIMES;\n\tkeymap[XK_KP_Subtract - KEY_MAP_OFFSET] = rsMINUS;\n\tkeymap[XK_KP_Add - KEY_MAP_OFFSET] = rsPLUS;\n\tkeymap[XK_KP_Enter - KEY_MAP_OFFSET] = rsPADENTER;\n\tkeymap[XK_KP_Equal - KEY_MAP_OFFSET] = rsNULL;\n\tkeymap[XK_Shift_L - KEY_MAP_OFFSET] = rsLSHIFT;\n\tkeymap[XK_Control_L - KEY_MAP_OFFSET] = rsLCTRL;\n\tkeymap[XK_Alt_L - KEY_MAP_OFFSET] = rsLALT;\n\tkeymap[XK_Super_L - KEY_MAP_OFFSET] = rsLWIN;\n\tkeymap[XK_Shift_R - KEY_MAP_OFFSET] = rsRSHIFT;\n\tkeymap[XK_Control_R - KEY_MAP_OFFSET] = rsRCTRL;\n\tkeymap[XK_Alt_R - KEY_MAP_OFFSET] = rsRALT;\n\tkeymap[XK_Super_R - KEY_MAP_OFFSET] = rsRWIN;\n\tkeymap[XK_Menu - KEY_MAP_OFFSET] = rsNULL;\n\n\t// Cache the key codes' key symbol equivelants, otherwise we will have to do it on each frame\n\t// KeyCode is always in [0,255], and represents a physical key\n\n\tint min_keycode, max_keycode, keysyms_per_keycode;\n\tKeySym *keymap, *origkeymap;\n\n\tchar *keyboardLang = setlocale (LC_CTYPE, NULL);\n\tsetlocale(LC_CTYPE, \"\");\n\n\tXDisplayKeycodes(display, &min_keycode, &max_keycode);\n\torigkeymap = XGetKeyboardMapping(display, min_keycode, (max_keycode - min_keycode + 1), &keysyms_per_keycode);\n\tkeymap = origkeymap;\n\tfor (int i = min_keycode; i <= max_keycode; i++) {\n\t\tint  j, lastKeysym;\n\n\t\tlastKeysym = keysyms_per_keycode - 1;\n\t\twhile ((lastKeysym >= 0) && (keymap[lastKeysym] == NoSymbol))\n\t\t\tlastKeysym--;\n\n\t\tfor (j = 0; j <= lastKeysym; j++) {\n\t\t\tKeySym ks = keymap[j];\n\n\t\t\tif (ks == NoSymbol)\n\t\t\t\tcontinue;\n\n\t\t\tif (ks < 256) {\n\t\t\t\tkeyCodeToKeymapIndex[i] = ks;\n\t\t\t\tbreak;\n\t\t\t} else if (ks >= 0xff00 && ks < 0xffff) {\n\t\t\t\tkeyCodeToKeymapIndex[i] = ks - KEY_MAP_OFFSET;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tkeymap += keysyms_per_keycode;\n\t}\n\tXFree(origkeymap);\n\n\tsetlocale(LC_CTYPE, keyboardLang);\n}\n#undef KEY_MAP_OFFSET\n\nvoid checkKeyPresses()\n{\n\tDisplay *display = glfwGetX11Display();\n\tchar keys[32];\n\tXQueryKeymap(display, keys);\n\tfor (int i = 0; i < sizeof(keys); i++) {\n\t\tfor (int j = 0; j < 8; j++) {\n\t\t\tKeyCode keycode = 8 * i + j;\n\t\t\tuint32 keymapIndex = keyCodeToKeymapIndex[keycode];\n\t\t\tif (keymapIndex != 0) {\n\t\t\t\tint rsCode = keymap[keymapIndex];\n\t\t\t\tif (rsCode == rsNULL)\n\t\t\t\t\tcontinue;\n\n\t\t\t\tbool pressed = WindowFocused && !!(keys[i] & (1 << j));\n\n\t\t\t\t// idk why R* does that\n\t\t\t\tif (rsCode == rsLSHIFT)\n\t\t\t\t\tlshiftStatus = pressed;\n\t\t\t\telse if (rsCode == rsRSHIFT)\n\t\t\t\t\trshiftStatus = pressed;\n\n\t\t\t\tif (keyStates[keymapIndex] != pressed) {\n\t\t\t\t\tif (pressed) {\n\t\t\t\t\t\tRsKeyboardEventHandler(rsKEYDOWN, &rsCode);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tRsKeyboardEventHandler(rsKEYUP, &rsCode);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tkeyStates[keymapIndex] = pressed;\n\t\t\t}\n\t\t}\n\t}\n\n}\n#endif\n\n// R* calls that in ControllerConfig, idk why\nvoid\n_InputTranslateShiftKeyUpDown(RsKeyCodes *rs) {\n\tRsKeyboardEventHandler(lshiftStatus ? rsKEYDOWN : rsKEYUP, &(*rs = rsLSHIFT));\n\tRsKeyboardEventHandler(rshiftStatus ? rsKEYDOWN : rsKEYUP, &(*rs = rsRSHIFT));\n}\n\n// TODO this only works in frontend(and luckily only frontend use this). Fun fact: if I get pos manually in game, glfw reports that it's > 32000\nvoid\ncursorCB(GLFWwindow* window, double xpos, double ypos) {\n\tif (!FrontEndMenuManager.m_bMenuActive)\n\t\treturn;\n\t\n\tint winw, winh;\n\tglfwGetWindowSize(PSGLOBAL(window), &winw, &winh);\n\tFrontEndMenuManager.m_nMouseTempPosX = xpos * (RsGlobal.maximumWidth / winw);\n\tFrontEndMenuManager.m_nMouseTempPosY = ypos * (RsGlobal.maximumHeight / winh);\n}\n\nvoid\ncursorEnterCB(GLFWwindow* window, int entered) {\n\tPSGLOBAL(cursorIsInWindow) = !!entered;\n}\n\nvoid\nwindowFocusCB(GLFWwindow* window, int focused) {\n\tWindowFocused = !!focused;\n}\n\nvoid\nwindowIconifyCB(GLFWwindow* window, int iconified) {\n\tWindowIconified = !!iconified;\n}\n\n/*\n *****************************************************************************\n */\n#ifdef _WIN32\nint PASCAL\nWinMain(HINSTANCE instance,\n\tHINSTANCE prevInstance\t__RWUNUSED__,\n\tCMDSTR cmdLine,\n\tint cmdShow)\n{\n\n\tRwInt32 argc;\n\tRwChar** argv;\n\tSystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, nil, SPIF_SENDCHANGE);\n\n#ifndef MASTER\n\tif (strstr(cmdLine, \"-console\"))\n\t{\n\t\tAllocConsole();\n\t\tfreopen(\"CONIN$\", \"r\", stdin);\n\t\tfreopen(\"CONOUT$\", \"w\", stdout);\n\t\tfreopen(\"CONOUT$\", \"w\", stderr);\n\t}\n#endif\n\n#else\nint\nmain(int argc, char *argv[])\n{\n#endif\n\tRwV2d pos;\n\tRwInt32 i;\n\n#ifdef USE_CUSTOM_ALLOCATOR\n\tInitMemoryMgr();\n#endif\n\n#ifndef _WIN32\n\tstruct sigaction act;\n\tact.sa_sigaction = terminateHandler;\n\tact.sa_flags = SA_SIGINFO;\n\tsigaction(SIGTERM, &act, NULL);\n#ifdef FLUSHABLE_STREAMING\n\tstruct sigaction sa;\n\tsigemptyset(&sa.sa_mask);\n\tsa.sa_handler = dummyHandler;\n\tsa.sa_flags = 0;\n\tsigaction(SIGUSR1, &sa, NULL);\n#endif\n#endif\n\n\t/* \n\t * Initialize the platform independent data.\n\t * This will in turn initialize the platform specific data...\n\t */\n\tif( RsEventHandler(rsINITIALIZE, nil) == rsEVENTERROR )\n\t{\n\t\treturn FALSE;\n\t}\n\n#ifdef _WIN32\n\t/*\n\t * Get proper command line params, cmdLine passed to us does not\n\t * work properly under all circumstances...\n\t */\n\tcmdLine = GetCommandLine();\n\n\t/*\n\t * Parse command line into standard (argv, argc) parameters...\n\t */\n\targv = CommandLineToArgv(cmdLine, &argc);\n\n\n\t/* \n\t * Parse command line parameters (except program name) one at \n\t * a time BEFORE RenderWare initialization...\n\t */\n#endif\n\tfor(i=1; i<argc; i++)\n\t{\n\t\tRsEventHandler(rsPREINITCOMMANDLINE, argv[i]);\n\t}\n\n\t/*\n\t * Parameters to be used in RwEngineOpen / rsRWINITIALISE event\n\t */\n\n\topenParams.width = RsGlobal.maximumWidth;\n\topenParams.height = RsGlobal.maximumHeight;\n\topenParams.windowtitle = RsGlobal.appName;\n\topenParams.window = &PSGLOBAL(window);\n\t\n\tControlsManager.MakeControllerActionsBlank();\n\tControlsManager.InitDefaultControlConfiguration();\n\n\t/* \n\t * Initialize the 3D (RenderWare) components of the app...\n\t */\n\tif( rsEVENTERROR == RsEventHandler(rsRWINITIALIZE, &openParams) )\n\t{\n\t\tRsEventHandler(rsTERMINATE, nil);\n\n\t\treturn 0;\n\t}\n\n#ifdef _WIN32\n\tHWND wnd = glfwGetWin32Window(PSGLOBAL(window));\n\n\tHICON icon = LoadIcon(instance, MAKEINTRESOURCE(IDI_MAIN_ICON));\n\n\tSendMessage(wnd, WM_SETICON, ICON_BIG, (LPARAM)icon);\n\tSendMessage(wnd, WM_SETICON, ICON_SMALL, (LPARAM)icon);\n#endif\n\n\tpsPostRWinit();\n\n\tControlsManager.InitDefaultControlConfigMouse(MousePointerStateHelper.GetMouseSetUp());\n\n//\tglfwSetWindowPos(PSGLOBAL(window), 0, 0);\n\n\t/* \n\t * Parse command line parameters (except program name) one at \n\t * a time AFTER RenderWare initialization...\n\t */\n\tfor(i=1; i<argc; i++)\n\t{\n\t\tRsEventHandler(rsCOMMANDLINE, argv[i]);\n\t}\n\n\t/* \n\t * Force a camera resize event...\n\t */\n\t{\n\t\tRwRect r;\n\n\t\tr.x = 0;\n\t\tr.y = 0;\n\t\tr.w = RsGlobal.maximumWidth;\n\t\tr.h = RsGlobal.maximumHeight;\n\n\t\tRsEventHandler(rsCAMERASIZE, &r);\n\t}\n#ifdef _WIN32\n\tSystemParametersInfo(SPI_SETPOWEROFFACTIVE, FALSE, nil, SPIF_SENDCHANGE);\n\tSystemParametersInfo(SPI_SETLOWPOWERACTIVE, FALSE, nil, SPIF_SENDCHANGE);\n\t\n\n\tSTICKYKEYS SavedStickyKeys;\n\tSavedStickyKeys.cbSize = sizeof(STICKYKEYS);\n\t\n\tSystemParametersInfo(SPI_GETSTICKYKEYS, sizeof(STICKYKEYS), &SavedStickyKeys, SPIF_SENDCHANGE);\n\t\n\tSTICKYKEYS NewStickyKeys;\n\tNewStickyKeys.cbSize = sizeof(STICKYKEYS);\n\tNewStickyKeys.dwFlags = SKF_TWOKEYSOFF;\n\t\n\tSystemParametersInfo(SPI_SETSTICKYKEYS, sizeof(STICKYKEYS), &NewStickyKeys, SPIF_SENDCHANGE);\n#endif\n\n\t{\n\t\tCFileMgr::SetDirMyDocuments();\n\t\t\n#ifdef LOAD_INI_SETTINGS\n\t\t// At this point InitDefaultControlConfigJoyPad must have set all bindings to default and ms_padButtonsInited to number of detected buttons.\n\t\t// We will load stored bindings below, but let's cache ms_padButtonsInited before LoadINIControllerSettings and LoadSettings clears it,\n\t\t// so we can add new joy bindings **on top of** stored bindings.\n\t\tint connectedPadButtons = ControlsManager.ms_padButtonsInited;\n#endif\n\n\t\tint32 gta3set = CFileMgr::OpenFile(\"gta_vc.set\", \"r\");\n\t\t\n\t\tif ( gta3set )\n\t\t{\n\t\t\tControlsManager.LoadSettings(gta3set);\n\t\t\tCFileMgr::CloseFile(gta3set);\n\t\t}\n\t\t\n\t\tCFileMgr::SetDir(\"\");\n\n#ifdef LOAD_INI_SETTINGS\n\t\tLoadINIControllerSettings();\n\t\tif (connectedPadButtons != 0) {\n\t\t\tControlsManager.InitDefaultControlConfigJoyPad(connectedPadButtons);\n\t\t\tSaveINIControllerSettings();\n\t\t}\n#endif\n\t}\n\t\n#ifdef _WIN32\n\tSetErrorMode(SEM_FAILCRITICALERRORS);\n#endif\n\n#ifdef PS2_MENU\n\tint32 r = TheMemoryCard.CheckCardStateAtGameStartUp(CARD_ONE);\n\tif (   r == CMemoryCard::ERR_DIRNOENTRY  || r == CMemoryCard::ERR_NOFORMAT\n\t\t&& r != CMemoryCard::ERR_OPENNOENTRY && r != CMemoryCard::ERR_NONE )\n\t{\n\t\tLoadingScreen(nil, nil, \"loadsc0\");\n\t\t\n\t\tTheText.Unload();\n\t\tTheText.Load();\n\t\t\n\t\tCFont::Initialise();\n\t\t\n\t\tFrontEndMenuManager.DrawMemoryCardStartUpMenus();\n\t}\n#endif\n\t\n\tinitkeymap();\n\n\twhile ( TRUE )\n\t{\n\t\tRwInitialised = TRUE;\n\t\t\n\t\t/* \n\t\t* Set the initial mouse position...\n\t\t*/\n\t\tpos.x = RsGlobal.maximumWidth * 0.5f;\n\t\tpos.y = RsGlobal.maximumHeight * 0.5f;\n\n\t\tRsMouseSetPos(&pos);\n\t\t\n\t\t/*\n\t\t* Enter the message processing loop...\n\t\t*/\n\n#ifndef MASTER\n\t\tif (gbModelViewer) {\n\t\t\t// This is TheModelViewer in LCS\n\t\t\tLoadingScreen(\"Loading the ModelViewer\", NULL, GetRandomSplashScreen());\n\t\t\tCAnimViewer::Initialise();\n\t\t\tCTimer::Update();\n#ifndef PS2_MENU\n\t\t\tFrontEndMenuManager.m_bGameNotLoaded = false;\n#endif\n\t\t}\n#endif\n\n#ifdef PS2_MENU\n\t\tif (TheMemoryCard.m_bWantToLoad)\n\t\t\tLoadSplash(GetLevelSplashScreen(CGame::currLevel));\n\t\t\n\t\tTheMemoryCard.m_bWantToLoad = false;\n\t\t\n\t\tCTimer::Update();\n\t\t\n\t\twhile( !RsGlobal.quit && !(FrontEndMenuManager.m_bWantToRestart || TheMemoryCard.b_FoundRecentSavedGameWantToLoad) && !glfwWindowShouldClose(PSGLOBAL(window)) )\n#else\n\t\twhile( !RsGlobal.quit && !FrontEndMenuManager.m_bWantToRestart && !glfwWindowShouldClose(PSGLOBAL(window)))\n#endif\n\t\t{\n\t\t\tglfwPollEvents();\n#ifdef GET_KEYBOARD_INPUT_FROM_X11\n\t\t\tcheckKeyPresses();\n#endif\n#ifndef MASTER\n\t\t\tif (gbModelViewer) {\n\t\t\t\t// This is TheModelViewerCore in LCS\n\t\t\t\tTheModelViewer();\n\t\t\t} else\n#endif\n\t\t\tif ( ForegroundApp )\n\t\t\t{\n\t\t\t\tswitch ( gGameState )\n\t\t\t\t{\n\t\t\t\t\tcase GS_START_UP:\n\t\t\t\t\t{\n#ifdef NO_MOVIES\n\t\t\t\t\t\tgGameState = GS_INIT_ONCE;\n#else\n\t\t\t\t\t\tgGameState = GS_INIT_LOGO_MPEG;\n#endif\n\t\t\t\t\t\tTRACE(\"gGameState = GS_INIT_ONCE\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t    case GS_INIT_LOGO_MPEG:\n\t\t\t\t\t{\n\t\t\t\t\t    //if (!startupDeactivate)\n\t\t\t\t\t\t//    PlayMovieInWindow(cmdShow, \"movies\\\\Logo.mpg\");\n\t\t\t\t\t    gGameState = GS_LOGO_MPEG;\n\t\t\t\t\t    TRACE(\"gGameState = GS_LOGO_MPEG;\");\n\t\t\t\t\t    break;\n\t\t\t\t    }\n\n\t\t\t\t    case GS_LOGO_MPEG:\n\t\t\t\t\t{\n//\t\t\t\t\t    CPad::UpdatePads();\n\n//\t\t\t\t\t    if (startupDeactivate || ControlsManager.GetJoyButtonJustDown() != 0)\n\t\t\t\t\t\t    ++gGameState;\n//\t\t\t\t\t    else if (CPad::GetPad(0)->GetLeftMouseJustDown())\n//\t\t\t\t\t\t    ++gGameState;\n//\t\t\t\t\t    else if (CPad::GetPad(0)->GetEnterJustDown())\n//\t\t\t\t\t\t    ++gGameState;\n//\t\t\t\t\t    else if (CPad::GetPad(0)->GetCharJustDown(' '))\n//\t\t\t\t\t\t    ++gGameState;\n//\t\t\t\t\t    else if (CPad::GetPad(0)->GetAltJustDown())\n//\t\t\t\t\t\t    ++gGameState;\n//\t\t\t\t\t    else if (CPad::GetPad(0)->GetTabJustDown())\n//\t\t\t\t\t\t    ++gGameState;\n\n\t\t\t\t\t    break;\n\t\t\t\t    }\n\n\t\t\t\t    case GS_INIT_INTRO_MPEG:\n\t\t\t\t\t{\n//#ifndef NO_MOVIES\n//\t\t\t\t\t    CloseClip();\n//\t\t\t\t\t    CoUninitialize();\n//#endif\n//\n//\t\t\t\t\t    if (CMenuManager::OS_Language == LANG_FRENCH || CMenuManager::OS_Language == LANG_GERMAN)\n//\t\t\t\t\t\t    PlayMovieInWindow(cmdShow, \"movies\\\\GTAtitlesGER.mpg\");\n//\t\t\t\t\t    else\n//\t\t\t\t\t\t    PlayMovieInWindow(cmdShow, \"movies\\\\GTAtitles.mpg\");\n\n\t\t\t\t\t    gGameState = GS_INTRO_MPEG;\n\t\t\t\t\t    TRACE(\"gGameState = GS_INTRO_MPEG;\");\n\t\t\t\t\t    break;\n\t\t\t\t    }\n\n\t\t\t\t    case GS_INTRO_MPEG:\n\t\t\t\t\t{\n//\t\t\t\t\t    CPad::UpdatePads();\n//\n//\t\t\t\t\t    if (startupDeactivate || ControlsManager.GetJoyButtonJustDown() != 0)\n\t\t\t\t\t\t    ++gGameState;\n//\t\t\t\t\t    else if (CPad::GetPad(0)->GetLeftMouseJustDown())\n//\t\t\t\t\t\t    ++gGameState;\n//\t\t\t\t\t    else if (CPad::GetPad(0)->GetEnterJustDown())\n//\t\t\t\t\t\t    ++gGameState;\n//\t\t\t\t\t    else if (CPad::GetPad(0)->GetCharJustDown(' '))\n//\t\t\t\t\t\t    ++gGameState;\n//\t\t\t\t\t    else if (CPad::GetPad(0)->GetAltJustDown())\n//\t\t\t\t\t\t    ++gGameState;\n//\t\t\t\t\t    else if (CPad::GetPad(0)->GetTabJustDown())\n//\t\t\t\t\t\t    ++gGameState;\n\n\t\t\t\t\t    break;\n\t\t\t\t    }\n\n\t\t\t\t\tcase GS_INIT_ONCE:\n\t\t\t\t\t{\n\t\t\t\t\t\t//CoUninitialize();\n\t\t\t\t\t\t\n#ifdef PS2_MENU\n\t\t\t\t\t\textern char version_name[64];\n\t\t\t\t\t\tif ( CGame::frenchGame || CGame::germanGame )\n\t\t\t\t\t\t\tLoadingScreen(NULL, version_name, \"loadsc24\");\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tLoadingScreen(NULL, version_name, \"loadsc0\");\n\t\t\t\t\t\t\n\t\t\t\t\t\tprintf(\"Into TheGame!!!\\n\");\n#else\t\t\t\t\n\t\t\t\t\t\tLoadingScreen(nil, nil, \"loadsc0\");\n\t\t\t\t\t\t// LoadingScreen(nil, nil, \"loadsc0\"); // duplicate\n#endif\n\t\t\t\t\t\tif ( !CGame::InitialiseOnceAfterRW() )\n\t\t\t\t\t\t\tRsGlobal.quit = TRUE;\n\t\t\t\t\t\t\n#ifdef PS2_MENU\n\t\t\t\t\t\tgGameState = GS_INIT_PLAYING_GAME;\n#else\n\t\t\t\t\t\tgGameState = GS_INIT_FRONTEND;\n\t\t\t\t\t\tTRACE(\"gGameState = GS_INIT_FRONTEND;\");\n#endif\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n#ifndef PS2_MENU\n\t\t\t\t\tcase GS_INIT_FRONTEND:\n\t\t\t\t\t{\n\t\t\t\t\t\tLoadingScreen(nil, nil, \"loadsc0\");\n\t\t\t\t\t\t// LoadingScreen(nil, nil, \"loadsc0\"); // duplicate\n\t\t\t\t\t\t\n\t\t\t\t\t\tFrontEndMenuManager.m_bGameNotLoaded = true;\n\t\t\t\t\t\t\n\t\t\t\t\t\tFrontEndMenuManager.m_bStartUpFrontEndRequested = true;\n\t\t\t\t\t\t\n\t\t\t\t\t\tif ( defaultFullscreenRes )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tdefaultFullscreenRes = FALSE;\n\t\t\t\t\t\t\tFrontEndMenuManager.m_nPrefsVideoMode = GcurSelVM;\n\t\t\t\t\t\t\tFrontEndMenuManager.m_nDisplayVideoMode = GcurSelVM;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\tgGameState = GS_FRONTEND;\n\t\t\t\t\t\tTRACE(\"gGameState = GS_FRONTEND;\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tcase GS_FRONTEND:\n\t\t\t\t\t{\n\t\t\t\t\t\tif(!WindowIconified)\n\t\t\t\t\t\t\tRsEventHandler(rsFRONTENDIDLE, nil);\n\n#ifdef PS2_MENU\n\t\t\t\t\t\tif ( !FrontEndMenuManager.m_bMenuActive || TheMemoryCard.m_bWantToLoad )\n#else\n\t\t\t\t\t\tif ( !FrontEndMenuManager.m_bMenuActive || FrontEndMenuManager.m_bWantToLoad )\n#endif\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tgGameState = GS_INIT_PLAYING_GAME;\n\t\t\t\t\t\t\tTRACE(\"gGameState = GS_INIT_PLAYING_GAME;\");\n\t\t\t\t\t\t}\n\n#ifdef PS2_MENU\n\t\t\t\t\t\tif (TheMemoryCard.m_bWantToLoad )\n#else\n\t\t\t\t\t\tif ( FrontEndMenuManager.m_bWantToLoad )\n#endif\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tInitialiseGame();\n\t\t\t\t\t\t\tFrontEndMenuManager.m_bGameNotLoaded = false;\n\t\t\t\t\t\t\tgGameState = GS_PLAYING_GAME;\n\t\t\t\t\t\t\tTRACE(\"gGameState = GS_PLAYING_GAME;\");\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n#endif\n\t\t\t\t\t\n\t\t\t\t\tcase GS_INIT_PLAYING_GAME:\n\t\t\t\t\t{\n#ifdef PS2_MENU\n\t\t\t\t\t\tCGame::Initialise(\"DATA\\\\GTA3.DAT\");\n\t\t\t\t\t\t\n\t\t\t\t\t\t//LoadingScreen(\"Starting Game\", NULL, GetRandomSplashScreen());\n\t\t\t\t\t\n\t\t\t\t\t\tif (   TheMemoryCard.CheckCardInserted(CARD_ONE) == CMemoryCard::NO_ERR_SUCCESS\n\t\t\t\t\t\t\t&& TheMemoryCard.ChangeDirectory(CARD_ONE, TheMemoryCard.Cards[CARD_ONE].dir)\n\t\t\t\t\t\t\t&& TheMemoryCard.FindMostRecentFileName(CARD_ONE, TheMemoryCard.MostRecentFile) == true\n\t\t\t\t\t\t\t&& TheMemoryCard.CheckDataNotCorrupt(TheMemoryCard.MostRecentFile))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tstrcpy(TheMemoryCard.LoadFileName, TheMemoryCard.MostRecentFile);\n\t\t\t\t\t\t\tTheMemoryCard.b_FoundRecentSavedGameWantToLoad = true;\n\t\t\t\t\t\n\t\t\t\t\t\t\tif (CMenuManager::m_PrefsLanguage != TheMemoryCard.GetLanguageToLoad())\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tCMenuManager::m_PrefsLanguage = TheMemoryCard.GetLanguageToLoad();\n\t\t\t\t\t\t\t\tTheText.Unload();\n\t\t\t\t\t\t\t\tTheText.Load();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\t\t\tCGame::currLevel = (eLevelName)TheMemoryCard.GetLevelToLoad();\n\t\t\t\t\t\t}\n#else\n\t\t\t\t\t\tInitialiseGame();\n\n\t\t\t\t\t\tFrontEndMenuManager.m_bGameNotLoaded = false;\n#endif\n\t\t\t\t\t\tgGameState = GS_PLAYING_GAME;\n\t\t\t\t\t\tTRACE(\"gGameState = GS_PLAYING_GAME;\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tcase GS_PLAYING_GAME:\n\t\t\t\t\t{\n\t\t\t\t\t\tfloat ms = (float)CTimer::GetCurrentTimeInCycles() / (float)CTimer::GetCyclesPerMillisecond();\n\t\t\t\t\t\tif ( RwInitialised )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (!FrontEndMenuManager.m_PrefsFrameLimiter || (1000.0f / (float)RsGlobal.maxFPS) < ms)\n\t\t\t\t\t\t\t\tRsEventHandler(rsIDLE, (void *)TRUE);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif ( RwCameraBeginUpdate(Scene.camera) )\n\t\t\t\t{\n\t\t\t\t\tRwCameraEndUpdate(Scene.camera);\n\t\t\t\t\tForegroundApp = TRUE;\n\t\t\t\t\tRsEventHandler(rsACTIVATE, (void *)TRUE);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t}\n\t\t}\n\n\t\t\n\t\t/* \n\t\t* About to shut down - block resize events again...\n\t\t*/\n\t\tRwInitialised = FALSE;\n\t\t\n\t\tFrontEndMenuManager.UnloadTextures();\n#ifdef PS2_MENU\t\n\t\tif ( !(FrontEndMenuManager.m_bWantToRestart || TheMemoryCard.b_FoundRecentSavedGameWantToLoad))\n\t\t\tbreak;\n#else\n\t\tif ( !FrontEndMenuManager.m_bWantToRestart )\n\t\t\tbreak;\n#endif\n\t\t\n\t\tCPad::ResetCheats();\n\t\tCPad::StopPadsShaking();\n\t\t\n\t\tDMAudio.ChangeMusicMode(MUSICMODE_DISABLE);\n\t\t\n#ifdef PS2_MENU\n\t\tCGame::ShutDownForRestart();\n#endif\n\t\t\n\t\tCTimer::Stop();\n\t\t\n#ifdef PS2_MENU\n\t\tif (FrontEndMenuManager.m_bWantToRestart || TheMemoryCard.b_FoundRecentSavedGameWantToLoad)\n\t\t{\n\t\t\tif (TheMemoryCard.b_FoundRecentSavedGameWantToLoad)\n\t\t\t{\n\t\t\t\tFrontEndMenuManager.m_bWantToRestart = true;\n\t\t\t\tTheMemoryCard.m_bWantToLoad = true;\n\t\t\t}\n\n\t\t\tCGame::InitialiseWhenRestarting();\n\t\t\tDMAudio.ChangeMusicMode(MUSICMODE_GAME);\n\t\t\tFrontEndMenuManager.m_bWantToRestart = false;\n\t\t\t\n\t\t\tcontinue;\n\t\t}\n\t\t\n\t\tCGame::ShutDown();\t\n\t\tCTimer::Stop();\n\t\t\n\t\tbreak;\n#else\n\t\tif ( FrontEndMenuManager.m_bWantToLoad )\n\t\t{\n\t\t\tCGame::ShutDownForRestart();\n\t\t\tCGame::InitialiseWhenRestarting();\n\t\t\tDMAudio.ChangeMusicMode(MUSICMODE_GAME);\n\t\t\tLoadSplash(GetLevelSplashScreen(CGame::currLevel));\n\t\t\tFrontEndMenuManager.m_bWantToLoad = false;\n\t\t}\n\t\telse\n\t\t{\n#ifndef MASTER\n\t\t\tif ( gbModelViewer )\n\t\t\t\tCAnimViewer::Shutdown();\n\t\t\telse\n#endif\n\t\t\tif ( gGameState == GS_PLAYING_GAME )\n\t\t\t\tCGame::ShutDown();\n\t\t\t\n\t\t\tCTimer::Stop();\n\t\t\t\n\t\t\tif ( FrontEndMenuManager.m_bFirstTime == true )\n\t\t\t{\n\t\t\t\tgGameState = GS_INIT_FRONTEND;\n\t\t\t\tTRACE(\"gGameState = GS_INIT_FRONTEND;\");\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tgGameState = GS_INIT_PLAYING_GAME;\n\t\t\t\tTRACE(\"gGameState = GS_INIT_PLAYING_GAME;\");\n\t\t\t}\n\t\t}\n\t\t\n\t\tFrontEndMenuManager.m_bFirstTime = false;\n\t\tFrontEndMenuManager.m_bWantToRestart = false;\n#endif\n\t}\n\t\n#ifndef MASTER\n\tif ( gbModelViewer )\n\t\tCAnimViewer::Shutdown();\n\telse\n#endif\n\tif ( gGameState == GS_PLAYING_GAME )\n\t\tCGame::ShutDown();\n\n\tDMAudio.Terminate();\n\t\n\t_psFreeVideoModeList();\n\n\n\t/*\n\t * Tidy up the 3D (RenderWare) components of the application...\n\t */\n\tRsEventHandler(rsRWTERMINATE, nil);\n\n\t/*\n\t * Free the platform dependent data...\n\t */\n\tRsEventHandler(rsTERMINATE, nil);\n\n#ifdef _WIN32\n\t/* \n\t * Free the argv strings...\n\t */\n\tfree(argv);\n\t\n\tSystemParametersInfo(SPI_SETSTICKYKEYS, sizeof(STICKYKEYS), &SavedStickyKeys, SPIF_SENDCHANGE);\n\tSystemParametersInfo(SPI_SETPOWEROFFACTIVE, TRUE, nil, SPIF_SENDCHANGE);\n\tSystemParametersInfo(SPI_SETLOWPOWERACTIVE, TRUE, nil, SPIF_SENDCHANGE);\n\tSetErrorMode(0);\n#endif\n\n\treturn 0;\n}\n\n/*\n *****************************************************************************\n */\n\nRwV2d leftStickPos;\nRwV2d rightStickPos;\n\nvoid CapturePad(RwInt32 padID)\n{\n\tint8 glfwPad = -1;\n\n\tif( padID == 0 )\n\t\tglfwPad = PSGLOBAL(joy1id);\n\telse if( padID == 1)\n\t\tglfwPad = PSGLOBAL(joy2id);\n\telse\n\t\tassert(\"invalid padID\");\n\t\n\tif ( glfwPad == -1 )\n\t\treturn;\n\t\n\tint numButtons, numAxes;\n\tconst uint8 *buttons = glfwGetJoystickButtons(glfwPad, &numButtons);\n\tconst float *axes = glfwGetJoystickAxes(glfwPad, &numAxes);\n\tGLFWgamepadstate gamepadState;\n\n\tif (ControlsManager.m_bFirstCapture == false) {\n\t\tmemcpy(&ControlsManager.m_OldState, &ControlsManager.m_NewState, sizeof(ControlsManager.m_NewState));\n\t} else {\n\t\t// In case connected gamepad doesn't have L-R trigger axes.\n\t\tControlsManager.m_NewState.mappedButtons[15] = ControlsManager.m_NewState.mappedButtons[16] = 0;\n\t}\n\n\tControlsManager.m_NewState.buttons = (uint8*)buttons;\n\tControlsManager.m_NewState.numButtons = numButtons;\n\tControlsManager.m_NewState.id = glfwPad;\n\tControlsManager.m_NewState.isGamepad = glfwGetGamepadState(glfwPad, &gamepadState);\n\tif (ControlsManager.m_NewState.isGamepad) {\n\t\tmemcpy(&ControlsManager.m_NewState.mappedButtons, gamepadState.buttons, sizeof(gamepadState.buttons));\n\t\tfloat lt = gamepadState.axes[GLFW_GAMEPAD_AXIS_LEFT_TRIGGER], rt = gamepadState.axes[GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER];\n\n\t\t// glfw returns 0.0 for non-existent axises(which is bullocks) so we treat it as deadzone, and keep value of previous frame.\n\t\t// otherwise if this axis is present, -1 = released, 1 = pressed\n\t\tif (lt != 0.0f)\n\t\t\tControlsManager.m_NewState.mappedButtons[15] = lt > -0.8f;\n\n\t\tif (rt != 0.0f)\n\t\t\tControlsManager.m_NewState.mappedButtons[16] = rt > -0.8f;\n\t}\n\t// TODO? L2-R2 axes(not buttons-that's fine) on joysticks that don't have SDL gamepad mapping AREN'T handled, and I think it's impossible to do without mapping.\n\n\tif (ControlsManager.m_bFirstCapture == true) {\n\t\tmemcpy(&ControlsManager.m_OldState, &ControlsManager.m_NewState, sizeof(ControlsManager.m_NewState));\n\t\t\n\t\tControlsManager.m_bFirstCapture = false;\n\t}\n\n\tRsPadButtonStatus bs;\n\tbs.padID = padID;\n\n\tRsPadEventHandler(rsPADBUTTONUP, (void *)&bs);\n\t\n\t// Gamepad axes are guaranteed to return 0.0f if that particular gamepad doesn't have that axis.\n\t// And that's really good for sticks, because gamepads return 0.0 for them when sticks are in released state.\n\tif ( glfwPad != -1 ) {\n\t\tleftStickPos.x = ControlsManager.m_NewState.isGamepad ? gamepadState.axes[GLFW_GAMEPAD_AXIS_LEFT_X] : numAxes >= 1 ? axes[0] : 0.0f;\n\t\tleftStickPos.y = ControlsManager.m_NewState.isGamepad ? gamepadState.axes[GLFW_GAMEPAD_AXIS_LEFT_Y] : numAxes >= 2 ? axes[1] : 0.0f;\n\n\t\trightStickPos.x = ControlsManager.m_NewState.isGamepad ? gamepadState.axes[GLFW_GAMEPAD_AXIS_RIGHT_X] : numAxes >= 3 ? axes[2] : 0.0f;\n\t\trightStickPos.y = ControlsManager.m_NewState.isGamepad ? gamepadState.axes[GLFW_GAMEPAD_AXIS_RIGHT_Y] : numAxes >= 4 ? axes[3] : 0.0f;\n\t}\n\t\n\t{\n\t\tif (CPad::m_bMapPadOneToPadTwo)\n\t\t\tbs.padID = 1;\n\t\t\n\t\tRsPadEventHandler(rsPADBUTTONUP,   (void *)&bs);\n\t\tRsPadEventHandler(rsPADBUTTONDOWN, (void *)&bs);\n\t}\n\t\n\t{\n\t\tif (CPad::m_bMapPadOneToPadTwo)\n\t\t\tbs.padID = 1;\n\t\t\n\t\tCPad *pad = CPad::GetPad(bs.padID);\n\n\t\tif ( Abs(leftStickPos.x)  > 0.3f )\n\t\t\tpad->PCTempJoyState.LeftStickX\t= (int32)(leftStickPos.x  * 128.0f);\n\t\t\n\t\tif ( Abs(leftStickPos.y)  > 0.3f )\n\t\t\tpad->PCTempJoyState.LeftStickY\t= (int32)(leftStickPos.y  * 128.0f);\n\t\t\n\t\tif ( Abs(rightStickPos.x) > 0.3f )\n\t\t\tpad->PCTempJoyState.RightStickX = (int32)(rightStickPos.x * 128.0f);\n\n\t\tif ( Abs(rightStickPos.y) > 0.3f )\n\t\t\tpad->PCTempJoyState.RightStickY = (int32)(rightStickPos.y * 128.0f);\n\t}\n\t\n\treturn;\n}\n\nvoid joysChangeCB(int jid, int event)\n{\n\tif (event == GLFW_CONNECTED && !IsThisJoystickBlacklisted(jid)) {\n\t\tif (PSGLOBAL(joy1id) == -1) {\n\t\t\tPSGLOBAL(joy1id) = jid;\n#ifdef DETECT_JOYSTICK_MENU\n\t\t\tstrcpy(gSelectedJoystickName, glfwGetJoystickName(jid));\n#endif\n\t\t\t// This is behind LOAD_INI_SETTINGS, because otherwise the Init call below will destroy/overwrite your bindings.\n#ifdef LOAD_INI_SETTINGS\n\t\t\tint count;\n\t\t\tglfwGetJoystickButtons(PSGLOBAL(joy1id), &count);\n\t\t\tControlsManager.InitDefaultControlConfigJoyPad(count);\n#endif\n\t\t} else if (PSGLOBAL(joy2id) == -1)\n\t\t\tPSGLOBAL(joy2id) = jid;\n\n\t} else if (event == GLFW_DISCONNECTED) {\n\t\tif (PSGLOBAL(joy1id) == jid) {\n\t\t\tPSGLOBAL(joy1id) = -1;\n\t\t} else if (PSGLOBAL(joy2id) == jid)\n\t\t\tPSGLOBAL(joy2id) = -1;\n\t}\n}\n\n#if (defined(_MSC_VER))\nint strcasecmp(const char* str1, const char* str2)\n{\n\treturn _strcmpi(str1, str2);\n}\nint strncasecmp(const char *str1, const char *str2, size_t len)\n{\n\treturn _strnicmp(str1, str2, len);\n}\n#endif\n#endif\n"
  },
  {
    "path": "src/skel/platform.h",
    "content": "#ifndef PLATFORM_H\n#define PLATFORM_H\n\n// Functions that's different on glfw/win etc. but have same signature (but if a function only used in win.cpp you can keep in win.h)\n\n#include \"rwcore.h\"\n#include \"skeleton.h\"\n\n#ifdef    __cplusplus\nextern \"C\"\n{\n#endif                          /* __cplusplus */\n\n#ifdef _WIN32\nextern RwUInt32 psTimer(void);\n#else\nextern double psTimer(void);\n#endif\n\nextern RwBool psInitialize(void);\nextern void   psTerminate(void);\n\nextern void psCameraShowRaster(RwCamera *camera);\nextern RwBool psCameraBeginUpdate(RwCamera *camera);\nextern RwImage *psGrabScreen(RwCamera *camera);\n\nextern void psMouseSetPos(RwV2d *pos);\n\nextern RwBool psSelectDevice();\n\nextern RwMemoryFunctions *psGetMemoryFunctions(void);\n\n/* install the platform specific file system */\nextern RwBool psInstallFileSystem(void);\n\n\n/* Handle native texture support */\nextern RwBool psNativeTextureSupport(void);\n\nextern void _InputTranslateShiftKeyUpDown(RsKeyCodes* rs);\nextern long _InputInitialiseMouse(bool exclusive); // returns HRESULT on Windows actually\nextern void _InputShutdownMouse();\nextern bool _InputMouseNeedsExclusive();\nextern void _InputInitialiseJoys();\n\nextern void HandleExit();\n\nextern void _psSelectScreenVM(RwInt32 videoMode);\n\nextern void InitialiseLanguage();\n\nextern RwBool _psSetVideoMode(RwInt32 subSystem, RwInt32 videoMode);\n\nextern RwChar** _psGetVideoModeList();\n\nextern RwInt32 _psGetNumVideModes();\n#ifdef    __cplusplus\n}\n#endif                          /* __cplusplus */\n\n#endif /* PLATFORM_H */\n"
  },
  {
    "path": "src/skel/skeleton.cpp",
    "content": "#include \"common.h\"\n\n\n#include <stdio.h>\n#include <math.h>\n#include <ctype.h>\n#include <string.h>\n\n#include \"rwcore.h\"\n\n#include \"skeleton.h\"\n#include \"platform.h\"\n#include \"main.h\"\n#include \"MemoryHeap.h\"\n\nstatic RwBool               DefaultVideoMode = TRUE;\n\nRsGlobalType                RsGlobal;\n\n#ifdef _WIN32\nRwUInt32    \n#else\ndouble\n#endif\nRsTimer(void)\n{\n\treturn psTimer();\n}\n\n\n/*\n *****************************************************************************\n */\nvoid\nRsCameraShowRaster(RwCamera * camera)\n{\n\tpsCameraShowRaster(camera);\n\n\treturn;\n}\n\n/*\n *****************************************************************************\n */\nRwBool\nRsCameraBeginUpdate(RwCamera * camera)\n{\n\treturn psCameraBeginUpdate(camera);\n}\n\n/*\n *****************************************************************************\n */\nRwImage*\nRsGrabScreen(RwCamera *camera)\n{\n\treturn psGrabScreen(camera);\n}\n\n/*\n *****************************************************************************\n */\nRwBool\nRsRegisterImageLoader(void)\n{\n\treturn TRUE;\n}\n\n/*\n *****************************************************************************\n */\nstatic              RwBool\nRsSetDebug(void)\n{\n\treturn TRUE;\n}\n\n/*\n *****************************************************************************\n */\nvoid\nRsMouseSetPos(RwV2d * pos)\n{\n\tpsMouseSetPos(pos);\n\n\treturn;\n}\n\n/*\n *****************************************************************************\n */\nRwBool\nRsSelectDevice(void)\n{\n\treturn psSelectDevice();\n}\n\n/*\n *****************************************************************************\n */\nRwBool\nRsInputDeviceAttach(RsInputDeviceType inputDevice,\n\t\t\t\t\tRsInputEventHandler inputEventHandler)\n{\n\tswitch (inputDevice)\n\t{\n\t\tcase rsKEYBOARD:\n\t\t\t{\n\t\t\t\tRsGlobal.keyboard.inputEventHandler = inputEventHandler;\n\t\t\t\tRsGlobal.keyboard.used = TRUE;\n\t\t\t\tbreak;\n\t\t\t}\n\t\tcase rsMOUSE:\n\t\t\t{\n\t\t\t\tRsGlobal.mouse.inputEventHandler = inputEventHandler;\n\t\t\t\tRsGlobal.mouse.used = TRUE;\n\t\t\t\tbreak;\n\t\t\t}\n\t\tcase rsPAD:\n\t\t\t{\n\t\t\t\tRsGlobal.pad.inputEventHandler = inputEventHandler;\n\t\t\t\tRsGlobal.pad.used = TRUE;\n\t\t\t\tbreak;\n\t\t\t}\n\t\tdefault:\n\t\t\t{\n\t\t\t\treturn FALSE;\n\t\t\t}\n\t}\n\n\treturn TRUE;\n}\n\n\n/*\n *****************************************************************************\n */\nstatic RwBool\nrsCommandLine(RwChar *arg)\n{\n\tRsEventHandler(rsFILELOAD, arg);\n\n\treturn TRUE;\n}\n\n\n/*\n *****************************************************************************\n */\nstatic RwBool\nrsPreInitCommandLine(RwChar *arg)\n{\n\tif( !strcmp(arg, RWSTRING(\"-vms\")) )\n\t{\n\t\tDefaultVideoMode = FALSE;\n\n\t\treturn TRUE;\n\t}\n#ifndef MASTER\n\tif (!strcmp(arg, RWSTRING(\"-animviewer\")))\n\t{\n\t\tgbModelViewer = TRUE;\n\n\t\treturn TRUE;\n\t}\n#endif\n\treturn FALSE;\n}\n\n/*\n *****************************************************************************\n */\nRsEventStatus\nRsKeyboardEventHandler(RsEvent event, void *param)\n{\n\tif (RsGlobal.keyboard.used)\n\t{\n\t\treturn RsGlobal.keyboard.inputEventHandler(event, param);\n\t}\n\n\treturn rsEVENTNOTPROCESSED;\n}\n\n/*\n *****************************************************************************\n */\nRsEventStatus\nRsPadEventHandler(RsEvent event, void *param)\n{\n\tif (RsGlobal.pad.used)\n\t{\n\t\treturn RsGlobal.pad.inputEventHandler(event, param);\n\t}\n\n\treturn rsEVENTNOTPROCESSED;\n}\n\n/*\n *****************************************************************************\n */\nRsEventStatus\nRsEventHandler(RsEvent event, void *param)\n{\n\tRsEventStatus       result;\n\tRsEventStatus       es;\n  \n\t/*\n\t * Give the application an opportunity to override any events...\n\t */\n\tes = AppEventHandler(event, param);\n\n\t/*\n\t * We never allow the app to replace the quit behaviour,\n\t * only to intercept...\n\t */\n\tif (event == rsQUITAPP)\n\t{\n\t\t/*\n\t\t * Set the flag which causes the event loop to exit...\n\t\t */\n\t\tRsGlobal.quit = TRUE;\n\t}\n\n\tif (es == rsEVENTNOTPROCESSED)\n\t{\n\t\tswitch (event)\n\t\t{\n\t\t\tcase rsSELECTDEVICE:\n\t\t\t\tresult =\n\t\t\t\t\t(RsSelectDevice()? rsEVENTPROCESSED : rsEVENTERROR);\n\t\t\t\tbreak;\n\n\t\t\tcase rsCOMMANDLINE:\n\t\t\t\tresult = (rsCommandLine((RwChar *) param) ?\n\t\t\t\t\t\t  rsEVENTPROCESSED : rsEVENTERROR);\n\t\t\t\tbreak;\n\t\t\tcase rsPREINITCOMMANDLINE:\n\t\t\t\tresult = (rsPreInitCommandLine((RwChar *) param) ?\n\t\t\t\t\t\t  rsEVENTPROCESSED : rsEVENTERROR);\n\t\t\t\tbreak;\n\t\t\tcase rsINITDEBUG:\n\t\t\t\tresult =\n\t\t\t\t\t(RsSetDebug()? rsEVENTPROCESSED : rsEVENTERROR);\n\t\t\t\tbreak;\n\n\t\t\tcase rsREGISTERIMAGELOADER:\n\t\t\t\tresult = (RsRegisterImageLoader()?\n\t\t\t\t\t\t  rsEVENTPROCESSED : rsEVENTERROR);\n\t\t\t\tbreak;\n\n\t\t\tcase rsRWTERMINATE:\n\t\t\t\tRsRwTerminate();\n\t\t\t\tresult = (rsEVENTPROCESSED);\n\t\t\t\tbreak;\n\n\t\t\tcase rsRWINITIALIZE:\n\t\t\t\tresult = (RsRwInitialize(param) ?\n\t\t\t\t\t\t  rsEVENTPROCESSED : rsEVENTERROR);\n\t\t\t\tbreak;\n\n\t\t\tcase rsTERMINATE:\n\t\t\t\tRsTerminate();\n\t\t\t\tresult = (rsEVENTPROCESSED);\n\t\t\t\tbreak;\n\n\t\t\tcase rsINITIALIZE:\n\t\t\t\tresult =\n\t\t\t\t\t(RsInitialize()? rsEVENTPROCESSED : rsEVENTERROR);\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tresult = (es);\n\t\t\t\tbreak;\n\n\t\t}\n\t}\n\telse\n\t{\n\t\tresult = (es);\n\t}\n\n\treturn result;\n}\n\n/*\n *****************************************************************************\n */\nvoid\nRsRwTerminate(void)\n{\n\t/* Close RenderWare */\n\n\tRwEngineStop();\n\tRwEngineClose();\n\tRwEngineTerm();\n\n\treturn;\n}\n\n/*\n *****************************************************************************\n */\nRwBool\nRsRwInitialize(void *displayID)\n{\n\tRwEngineOpenParams  openParams;\n\n\t/*\n\t * Start RenderWare...\n\t */\n\t \n\tif (!RwEngineInit(psGetMemoryFunctions(), 0, rsRESOURCESDEFAULTARENASIZE))\n\t{\n\t\treturn (FALSE);\n\t}\n\n\t/*\n\t * Install any platform specific file systems...\n\t */\n\tpsInstallFileSystem();\n\t\n\t/*\n\t * Initialize debug message handling...\n\t */\n\tRsEventHandler(rsINITDEBUG, nil);\n\n\t/*\n\t * Attach all plugins...\n\t */\n\tif (RsEventHandler(rsPLUGINATTACH, nil) == rsEVENTERROR)\n\t{\n\t\treturn (FALSE);\n\t}\n\n\t/*\n\t * Attach input devices...\n\t */\n\tif (RsEventHandler(rsINPUTDEVICEATTACH, nil) == rsEVENTERROR)\n\t{\n\t\treturn (FALSE);\n\t}\n\t\n\topenParams.displayID = displayID;\n\n\tif (!RwEngineOpen(&openParams))\n\t{\n\t\tRwEngineTerm();\n\t\treturn (FALSE);\n\t}\n\t\n\tif (RsEventHandler(rsSELECTDEVICE, displayID) == rsEVENTERROR)\n\t{\n\t\tRwEngineClose();\n\t\tRwEngineTerm();\n\t\treturn (FALSE);\n\t}\n\t\n\tif (!RwEngineStart())\n\t{\n\t\tRwEngineClose();\n\t\tRwEngineTerm();\n\t\treturn (FALSE);\n\t}\n\n\t/*\n\t * Register loaders for an image with a particular file extension...\n\t */\n\tRsEventHandler(rsREGISTERIMAGELOADER, nil);\n\n\tpsNativeTextureSupport();\n\n\tRwTextureSetAutoMipmapping(TRUE);\n\tRwTextureSetMipmapping(FALSE);\n\n\treturn TRUE;\n}\n\n/*\n *****************************************************************************\n */\nvoid\nRsTerminate(void)\n{\n\tpsTerminate();\n\n\treturn;\n}\n\n/*\n *****************************************************************************\n */\nRwBool\nRsInitialize(void)\n{\n\t/*\n\t * Initialize Platform independent data...\n\t */\n\tRwBool              result;\n\n\tRsGlobal.appName = RWSTRING(\"GTA: Vice City\");\n\tRsGlobal.maximumWidth = DEFAULT_SCREEN_WIDTH;\n\tRsGlobal.maximumHeight = DEFAULT_SCREEN_HEIGHT;\n\tRsGlobal.width = DEFAULT_SCREEN_WIDTH;\n\tRsGlobal.height = DEFAULT_SCREEN_HEIGHT;\n\t\n\tRsGlobal.maxFPS = 30;\n\t \n\tRsGlobal.quit = FALSE;\n\n\t/* setup the keyboard */\n\tRsGlobal.keyboard.inputDeviceType = rsKEYBOARD;\n\tRsGlobal.keyboard.inputEventHandler = nil;\n\tRsGlobal.keyboard.used = FALSE;\n\n\t/* setup the mouse */\n\tRsGlobal.mouse.inputDeviceType = rsMOUSE;\n\tRsGlobal.mouse.inputEventHandler = nil;\n\tRsGlobal.mouse.used = FALSE;\n\n\t/* setup the pad */\n\tRsGlobal.pad.inputDeviceType = rsPAD;\n\tRsGlobal.pad.inputEventHandler = nil;\n\tRsGlobal.pad.used = FALSE;\n\n\tresult = psInitialize();\n\n\treturn result;\n}\n"
  },
  {
    "path": "src/skel/skeleton.h",
    "content": "#ifndef SKELETON_H\n#define SKELETON_H\n\n#include \"rwcore.h\"\n\n/* Default arena size depending on platform. */\n#define rsRESOURCESDEFAULTARENASIZE (1 << 20)\n\n#if (!defined(RsSprintf))\n#define RsSprintf rwsprintf\n#endif /* (!defined(RsSprintf)) */\n\n#ifdef    __cplusplus\nextern \"C\"\n{\n#endif                          /* __cplusplus */\n\n#if (!defined(RSASSERT))\n#define RSASSERT(_condition) /* No-op */\n#endif /* (!defined(RSASSERT)) */\n\n#define RSASSERTISTYPE(_f, _t) \\\n   RSASSERT( (!(_f)) || ((((const RwObject *)(_f))->type)==(_t)) )\n\nenum RsInputDeviceType\n{\n\trsKEYBOARD,\n\trsMOUSE,\n\trsPAD\n};\ntypedef enum RsInputDeviceType RsInputDeviceType;\n\nenum RsEventStatus\n{\n\trsEVENTERROR,\n\trsEVENTPROCESSED,\n\trsEVENTNOTPROCESSED\n};\ntypedef enum RsEventStatus RsEventStatus;\n\nenum RsEvent\n{\n\trsCAMERASIZE,\n\trsCOMMANDLINE,\n\trsFILELOAD,\n\trsINITDEBUG,\n\trsINPUTDEVICEATTACH,\n\trsLEFTBUTTONDOWN,\n\trsLEFTBUTTONUP,\n\trsMOUSEMOVE,\n\trsMOUSEWHEELMOVE,\n\trsPLUGINATTACH,\n\trsREGISTERIMAGELOADER,\n\trsRIGHTBUTTONDOWN,\n\trsRIGHTBUTTONUP,\n\t_rs_13,\n\t_rs_14,\n\t_rs_15,\n\t_rs_16,\n\t_rs_17,\n\t_rs_18,\n\t_rs_19,\n\t_rs_20,\n\trsRWINITIALIZE,\n\trsRWTERMINATE,\n\trsSELECTDEVICE,\n\trsINITIALIZE,\n\trsTERMINATE,\n\trsIDLE,\n\trsFRONTENDIDLE,\n\trsKEYDOWN,\n\trsKEYUP,\n\trsQUITAPP,\n\trsPADBUTTONDOWN,\n\trsPADBUTTONUP,\n\trsPADANALOGUELEFT,\n\trsPADANALOGUELEFTRESET,\n\trsPADANALOGUERIGHT,\n\trsPADANALOGUERIGHTRESET,\n\trsPREINITCOMMANDLINE,\n\trsACTIVATE,\n};\n\ntypedef enum RsEvent RsEvent;\n\ntypedef RsEventStatus (*RsInputEventHandler)(RsEvent event, void *param);\n\ntypedef struct RsInputDevice RsInputDevice;\nstruct RsInputDevice\n{\n\tRsInputDeviceType inputDeviceType;\n\tRwBool used;\n\tRsInputEventHandler inputEventHandler;\n};\n\ntypedef struct RsGlobalType RsGlobalType;\nstruct RsGlobalType\n{\n\tconst RwChar *appName;\n\tRwInt32 width;\n\tRwInt32 height;\n\tRwInt32 maximumWidth;\n\tRwInt32 maximumHeight;\n\tRwInt32 maxFPS;\n\tRwBool  quit;\n\n\tvoid   *ps; /* platform specific data */\n\n\tRsInputDevice keyboard;\n\tRsInputDevice mouse;\n\tRsInputDevice pad;\n};\n\nenum RsKeyCodes\n{\n\trsESC            = 1000,\n\t\n\trsF1             = 1001,\n\trsF2             = 1002,\n\trsF3             = 1003,\n\trsF4             = 1004,\n\trsF5             = 1005,\n\trsF6             = 1006,\n\trsF7             = 1007,\n\trsF8             = 1008,\n\trsF9             = 1009,\n\trsF10            = 1010,\n\trsF11            = 1011,\n\trsF12            = 1012,\n\t\n\trsINS            = 1013,\n\trsDEL            = 1014,\n\trsHOME           = 1015,\n\trsEND            = 1016,\n\trsPGUP           = 1017,\n\trsPGDN           = 1018,\n\t\n\trsUP             = 1019,\n\trsDOWN           = 1020,\n\trsLEFT           = 1021,\n\trsRIGHT          = 1022,\n\t\n\trsDIVIDE         = 1023,\n\trsTIMES          = 1024,\n\trsPLUS           = 1025,\n\trsMINUS          = 1026,\n\trsPADDEL         = 1027,\n\trsPADEND         = 1028,\n\trsPADDOWN        = 1029,\n\trsPADPGDN        = 1030,\n\trsPADLEFT        = 1031,\n\trsPAD5           = 1032,\n\trsNUMLOCK        = 1033,\n\trsPADRIGHT       = 1034,\n\trsPADHOME        = 1035,\n\trsPADUP          = 1036,\n\trsPADPGUP        = 1037,\n\trsPADINS         = 1038,\n\trsPADENTER       = 1039,\n\t\n\trsSCROLL         = 1040,\n\trsPAUSE          = 1041,\n\t\n\trsBACKSP         = 1042,\n\trsTAB            = 1043,\n\trsCAPSLK         = 1044,\n\trsENTER          = 1045,\n\trsLSHIFT         = 1046,\n\trsRSHIFT         = 1047,\n\trsSHIFT          = 1048,\n\trsLCTRL          = 1049,\n\trsRCTRL          = 1050,\n\trsLALT           = 1051,\n\trsRALT           = 1052,\n\trsLWIN           = 1053,\n\trsRWIN           = 1054,\n\trsAPPS           = 1055,\n\t\n\trsNULL           = 1056,\n\n\trsMOUSELEFTBUTTON      = 1,\n\trsMOUSMIDDLEBUTTON     = 2,\n\trsMOUSERIGHTBUTTON     = 3,\n\trsMOUSEWHEELUPBUTTON   = 4,\n\trsMOUSEWHEELDOWNBUTTON = 5,\n\trsMOUSEX1BUTTON        = 6,\n\trsMOUSEX2BUTTON        = 7,\n};\ntypedef enum RsKeyCodes RsKeyCodes;\n\ntypedef struct RsKeyStatus RsKeyStatus;\nstruct RsKeyStatus\n{\n\tRwInt32     keyCharCode;\n};\n\ntypedef struct RsPadButtonStatus RsPadButtonStatus;\nstruct RsPadButtonStatus\n{\n\tRwInt32     padID;\n};\n\nenum RsPadButtons\n{\n\trsPADNULL       = 0,\n\t\n\trsPADBUTTON1    = 1,\n\trsPADBUTTON2    = 2,\n\trsPADBUTTON3    = 3,\n\trsPADBUTTON4    = 4,\n\t\n\trsPADBUTTON5    = 5,\n\trsPADBUTTON6    = 6,\n\trsPADBUTTON7    = 7,\n\trsPADBUTTON8    = 8,\n\t\n\trsPADSELECT     = 9,\n\t\n\trsPADBUTTONA1   = 10,\n\trsPADBUTTONA2   = 11,\n\t\n\trsPADSTART      = 12,\n\t\n\trsPADDPADUP     = 13,\n\trsPADDPADRIGHT  = 14,\n\trsPADDPADDOWN   = 15,\n\trsPADDPADLEFT   = 16,\n};\ntypedef enum RsPadButtons RsPadButtons;\n\n\nextern RsGlobalType RsGlobal;\n\nextern RsEventStatus AppEventHandler(RsEvent event, void *param);\nextern RwBool        AttachInputDevices(void);\n\nextern RsEventStatus RsEventHandler(RsEvent event, void *param);\nextern RsEventStatus RsKeyboardEventHandler(RsEvent event, void *param);\nextern RsEventStatus RsPadEventHandler(RsEvent event, void *param);\n\nextern RwBool\nRsInitialize(void);\n\nextern RwBool\nRsRegisterImageLoader(void);\n\nextern RwBool\nRsRwInitialize(void *param);\n\nextern RwBool\nRsSelectDevice(void);\n\nextern RwBool\nRsInputDeviceAttach(RsInputDeviceType inputDevice,\n\t\t\t\t\tRsInputEventHandler inputEventHandler);\n\n#ifdef _WIN32\nextern RwUInt32    \n#else\nextern double\n#endif             \nRsTimer(void);\n\nextern void                     \nRsCameraShowRaster(RwCamera *camera);\n\nextern RwBool                     \nRsCameraBeginUpdate(RwCamera *camera);\n\n//TODO\n//extern void                     \n//RsMouseSetVisibility(RwBool visible);\n\nextern RwImage*\nRsGrabScreen(RwCamera *camera);\n\nextern void                     \nRsMouseSetPos(RwV2d *pos);\n\nextern void                     \nRsRwTerminate(void);\n\nextern void                     \nRsTerminate(void);\n\n#ifdef    __cplusplus\n}\n#endif                          /* __cplusplus */\n\n#endif /* SKELETON_H */\n"
  },
  {
    "path": "src/skel/win/resource.h",
    "content": "//{{NO_DEPENDENCIES}}\n// Microsoft Developer Studio generated include file.\n// Used by dungeon.rc\n//\n#define IDD_DIALOG1                     104\n#define IDC_DEVICESEL                   1000\n#define IDC_VIDMODE                     1001\n#define IDEXIT                          1002\n#define IDC_SELECTDEVICE                1005\n\n#define IDI_MAIN_ICON                   100\n// Next default values for new objects\n// \n#ifdef APSTUDIO_INVOKED\n#ifndef APSTUDIO_READONLY_SYMBOLS\n#define _APS_NEXT_RESOURCE_VALUE        104\n#define _APS_NEXT_COMMAND_VALUE         40001\n#define _APS_NEXT_CONTROL_VALUE         1000\n#define _APS_NEXT_SYMED_VALUE           101\n#endif\n#endif\n"
  },
  {
    "path": "src/skel/win/win.cpp",
    "content": "#if defined RW_D3D9 || defined RWLIBS || defined __MWERKS__\n\n#define _WIN32_WINDOWS 0x0500\n#define WINVER 0x0500\n\n#include <winerror.h>\n#include <windows.h>\n#include <mmsystem.h>\n#include <shellapi.h>\n\n#include <windowsx.h>\n#include <basetsd.h>\n\n#include <regstr.h>\n#include <shlobj.h>\n\n#include <dbt.h>\n\n#pragma warning( push )\n#pragma warning( disable : 4005)\n\n#ifdef __MWERKS__\n#define MAPVK_VK_TO_CHAR (2) // this is missing from codewarrior win32 headers - but it gets used ... how?\n#endif\n\n#include <ddraw.h>\n#include <DShow.h>\n#pragma warning( pop )\n\n#define WM_GRAPHNOTIFY\tWM_USER+13\n\n#ifndef USE_D3D9\n#pragma comment( lib, \"d3d8.lib\" )\n#endif\n#pragma comment( lib, \"ddraw.lib\" )\n#pragma comment( lib, \"Winmm.lib\" )\n#pragma comment( lib, \"dxguid.lib\" )\n#pragma comment( lib, \"strmiids.lib\" )\n#pragma comment( lib, \"dinput8.lib\" )\n\n#define WITHD3D\n#define WITHDINPUT\n#include \"common.h\"\n#if (defined(_MSC_VER))\n#include <tchar.h>\n#endif /* (defined(_MSC_VER)) */\n#include <stdio.h>\n#include \"rwcore.h\"\n#include \"resource.h\"\n#include \"skeleton.h\"\n#include \"platform.h\"\n#include \"crossplatform.h\"\n\n#define MAX_SUBSYSTEMS\t\t(16)\n\nstatic RwBool\t\t  ForegroundApp = TRUE;\n\nstatic RwBool\t\t  RwInitialised = FALSE;\n\nstatic RwSubSystemInfo GsubSysInfo[MAX_SUBSYSTEMS];\nstatic RwInt32\t\tGnumSubSystems = 0;\nstatic RwInt32\t\tGcurSel = 0, GcurSelVM = 0;\n\nstatic RwBool startupDeactivate;\n\nstatic RwBool useDefault;\n\n/* Class name for the MS Window's window class. */\n\nstatic const RwChar *AppClassName = RWSTRING(\"Grand theft auto 3\");\n\nstatic psGlobalType PsGlobal;\n\n\n#define PSGLOBAL(var) (((psGlobalType *)(RsGlobal.ps))->var)\n\n#undef MAKEPOINTS\n#define MAKEPOINTS(l)\t\t(*((POINTS /*FAR*/ *)&(l)))\n\n#define SAFE_RELEASE(x) { if (x) x->Release(); x = NULL; }\n#define JIF(x) if (FAILED(hr=(x))) \\\n\t{debug(TEXT(\"FAILED(hr=0x%x) in \") TEXT(#x) TEXT(\"\\n\"), hr); return;}\n\n#include \"main.h\"\n#include \"FileMgr.h\"\n#include \"Text.h\"\n#include \"Pad.h\"\n#include \"Timer.h\"\n#include \"DMAudio.h\"\n#include \"ControllerConfig.h\"\n#include \"Frontend.h\"\n#include \"Game.h\"\n#include \"PCSave.h\"\n#include \"AnimViewer.h\"\n#include \"MemoryMgr.h\"\n\n#ifdef PS2_MENU\n#include \"MemoryCard.h\"\n#include \"Font.h\"\n#endif\n\t\nVALIDATE_SIZE(psGlobalType, 0x28);\n\n// DirectShow interfaces\nIGraphBuilder *pGB = nil;\nIMediaControl *pMC = nil;\nIMediaEventEx *pME = nil;\nIVideoWindow  *pVW = nil;\nIMediaSeeking *pMS = nil;\n\nDWORD dwDXVersion;\nSIZE_T _dwMemTotalPhys;\nsize_t _dwMemAvailPhys;\nSIZE_T _dwMemTotalVirtual;\nSIZE_T _dwMemAvailVirtual;\nDWORD _dwMemTotalVideo;\nDWORD _dwMemAvailVideo;\nDWORD _dwOperatingSystemVersion;\n\nRwUInt32 gGameState;\nCJoySticks AllValidWinJoys;\n\n#ifdef DETECT_JOYSTICK_MENU\nchar gSelectedJoystickName[128] = \"\";\n#endif\n\n// What is that for anyway?\n#ifndef IMPROVED_VIDEOMODE\nstatic RwBool defaultFullscreenRes = TRUE;\n#else\nstatic RwBool defaultFullscreenRes = FALSE;\nstatic RwInt32 bestWndMode = -1;\n#endif\n\nCJoySticks::CJoySticks()\n{\n\tfor (int i = 0; i < MAX_JOYSTICKS; i++)\n\t{\n\t\tClearJoyInfo(i);\n\t}\n}\n\nvoid CJoySticks::ClearJoyInfo(int joyID)\n{\n\tm_aJoys[joyID].m_State = JOYPAD_UNUSED;\n\tm_aJoys[joyID].m_bInitialised = false;\n\tm_aJoys[joyID].m_bHasAxisZ = false;\n\tm_aJoys[joyID].m_bHasAxisR = false;\n}\n\n\n\n/*\n *****************************************************************************\n */\nvoid _psCreateFolder(LPCSTR path)\n{\n\tHANDLE hfle = CreateFile(path, GENERIC_READ, \n\t\t\t\t\t\t\t\t\tFILE_SHARE_READ,\n\t\t\t\t\t\t\t\t\tnil,\n\t\t\t\t\t\t\t\t\tOPEN_EXISTING,\n\t\t\t\t\t\t\t\t\tFILE_FLAG_BACKUP_SEMANTICS | FILE_ATTRIBUTE_NORMAL,\n\t\t\t\t\t\t\t\t\tnil);\n\n\tif ( hfle == INVALID_HANDLE_VALUE )\n\t\tCreateDirectory(path, nil);\n\telse\n\t\tCloseHandle(hfle);\n}\n\n/*\n *****************************************************************************\n */\nconst char *_psGetUserFilesFolder()\n{\n#ifdef USE_MY_DOCUMENTS\n\tHKEY hKey = NULL;\n\n\tstatic CHAR szUserFiles[256];\n\n\tif ( RegOpenKeyEx(HKEY_CURRENT_USER,\n\t\t\t\t\t\tREGSTR_PATH_SPECIAL_FOLDERS,\n\t\t\t\t\t\tREG_OPTION_RESERVED,\n\t\t\t\t\t\tKEY_READ,\n\t\t\t\t\t\t&hKey) == ERROR_SUCCESS )\n\t{\n\t\tDWORD KeyType;\n\t\tDWORD KeycbData = sizeof(szUserFiles);\n\t\tif ( RegQueryValueEx(hKey,\n\t\t\t\t\t\t\t\"Personal\",\n\t\t\t\t\t\t\tNULL,\n\t\t\t\t\t\t\t&KeyType,\n\t\t\t\t\t\t\t(LPBYTE)szUserFiles,\n\t\t\t\t\t\t\t&KeycbData) == ERROR_SUCCESS )\n\t\t{\n\t\t\tRegCloseKey(hKey);\n\t\t\tstrcat(szUserFiles, \"\\\\GTA Vice City User Files\");\n\t\t\t_psCreateFolder(szUserFiles);\n\t\t\treturn szUserFiles;\n\t\t}\t\n\n\t\tRegCloseKey(hKey);\t\t\n\t}\n\t\n\tstrcpy(szUserFiles, \"data\");\n\treturn szUserFiles;\n#else\n\tstatic CHAR szUserFiles[256];\n\tstrcpy(szUserFiles, \"userfiles\");\n\t_psCreateFolder(szUserFiles);\n\treturn szUserFiles;\n#endif\n}\n\n/*\n *****************************************************************************\n */\nRwBool\npsCameraBeginUpdate(RwCamera *camera)\n{\n\tif ( !RwCameraBeginUpdate(Scene.camera) )\n\t{\n\t\tForegroundApp = FALSE;\n\t\tRsEventHandler(rsACTIVATE, (void *)FALSE);\n\t\treturn FALSE;\n\t}\n\t\n\treturn TRUE;\n}\n\n/*\n *****************************************************************************\n */\nvoid\npsCameraShowRaster(RwCamera *camera)\n{\n#ifdef LEGACY_MENU_OPTIONS\n\tif (FrontEndMenuManager.m_PrefsVsync || FrontEndMenuManager.m_bMenuActive)\n#else\n\tif (FrontEndMenuManager.m_PrefsFrameLimiter || FrontEndMenuManager.m_bMenuActive)\n#endif\n\t\tRwCameraShowRaster(camera, PSGLOBAL(window), rwRASTERFLIPWAITVSYNC);\n\telse\n\t\tRwCameraShowRaster(camera, PSGLOBAL(window), rwRASTERFLIPDONTWAIT);\n\n\treturn;\n}\n\n\n/*\n *****************************************************************************\n */\nRwImage *\npsGrabScreen(RwCamera *pCamera)\n{\n#ifndef LIBRW\n\tRwRaster *pRaster = RwCameraGetRaster(pCamera);\n\tif (RwImage *pImage = RwImageCreate(pRaster->width, pRaster->height, 32)) {\n\t\tRwImageAllocatePixels(pImage);\n\t\tRwImageSetFromRaster(pImage, pRaster);\n\t\treturn pImage;\n\t}\n#else\n\trw::Image *image = RwCameraGetRaster(pCamera)->toImage();\n\timage->removeMask();\n\tif(image)\n\t\treturn image;\n#endif\n\treturn nil;\n}\n\n/*\n *****************************************************************************\n */\nRwUInt32\npsTimer(void)\n{\n\tRwUInt32 time;\n\n\tTIMECAPS TimeCaps;\n\t\n\ttimeGetDevCaps(&TimeCaps, sizeof(TIMECAPS));\n\t\n\ttimeBeginPeriod(TimeCaps.wPeriodMin);\n\t\n\ttime = (RwUInt32) timeGetTime();\n\n\ttimeEndPeriod(TimeCaps.wPeriodMin);\n\t\n\treturn time;\n}\n\n/*\n *****************************************************************************\n */\nvoid\npsMouseSetPos(RwV2d *pos)\n{\n\tPOINT point;\n\n\tpoint.x = (RwInt32) pos->x;\n\tpoint.y = (RwInt32) pos->y;\n\n\tClientToScreen(PSGLOBAL(window), &point);\n\n\tSetCursorPos(point.x, point.y);\n\t\n\tPSGLOBAL(lastMousePos.x) = (RwInt32)pos->x;\n\n\tPSGLOBAL(lastMousePos.y) = (RwInt32)pos->y;\n\n\treturn;\n}\n\n/*\n *****************************************************************************\n */\nRwMemoryFunctions*\npsGetMemoryFunctions(void)\n{\n#ifdef USE_CUSTOM_ALLOCATOR\n\treturn &memFuncs;\n#else\n\treturn nil;\n#endif\n}\n\n/*\n *****************************************************************************\n */\nRwBool\npsInstallFileSystem(void)\n{\n\treturn (TRUE);\n}\n\n\n/*\n *****************************************************************************\n */\nRwBool\npsNativeTextureSupport(void)\n{\n\treturn RwD3D8DeviceSupportsDXTTexture();\n}\n\n/*\n *****************************************************************************\n */\nstatic HWND\nInitInstance(HANDLE instance)\n{\n\t/*\n\t * Perform any necessary initialization for this instance of the \n\t * application.\n\t *\n\t * Create the MS Window's window instance for this application. The\n\t * initial window size is given by the defined camera size. The window \n\t * is not given a title as we set it during Init3D() with information \n\t * about the version of RenderWare being used.\n\t */\n\n\tRECT rect;\n\n\trect.left = rect.top = 0;\n\trect.right = RsGlobal.maximumWidth;\n\trect.bottom = RsGlobal.maximumHeight;\n\n\tAdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, FALSE);\n\n\treturn CreateWindow(AppClassName, RsGlobal.appName,\n\t\t\t\t\t\tWS_OVERLAPPEDWINDOW,\n\t\t\t\t\t\tCW_USEDEFAULT, CW_USEDEFAULT,\n\t\t\t\t\t\trect.right - rect.left, rect.bottom - rect.top,\n\t\t\t\t\t\t(HWND)nil, (HMENU)nil, (HINSTANCE)instance, nil);\n}\n\nvoid _GetVideoMemInfo(LPDWORD total, LPDWORD avaible)\n{\n\tHRESULT hr;\n\tLPDIRECTDRAW7 pDD7;\n\t\n\thr = DirectDrawCreateEx(nil, (VOID**)&pDD7, IID_IDirectDraw7, nil);\n\t\n\tif ( FAILED(hr) )\n\t\treturn;\n\t\n\tDDSCAPS2 caps;\n\t\n\tZeroMemory(&caps, sizeof(DDSCAPS2));\n\tcaps.dwCaps = DDSCAPS_VIDEOMEMORY;\n\t\n\tpDD7->GetAvailableVidMem(&caps, total, avaible);\n\t\n\tpDD7->Release();\n}\n\n/*\n *****************************************************************************\n */\ntypedef HRESULT(WINAPI * DIRECTDRAWCREATEEX)( GUID*, VOID**, REFIID, IUnknown* );\n\n\n//-----------------------------------------------------------------------------\n// Name: GetDXVersion()\n// Desc: This function returns the DirectX version number as follows:\n//\t\t\t0x0000 = No DirectX installed\n//\t\t\t0x0700 = At least DirectX 7 installed.\n//\t\t\t0x0800 = At least DirectX 8 installed.\n// \n//\t\t Please note that this code is intended as a general guideline. Your\n//\t\t app will probably be able to simply query for functionality (via\n//\t\t QueryInterface) for one or two components.\n//\n//\t\t Please also note:\n//\t\t\t\"if( dwDXVersion != 0x500 ) return FALSE;\" is VERY BAD. \n//\t\t\t\"if( dwDXVersion <\t0x500 ) return FALSE;\" is MUCH BETTER.\n//\t\t to ensure your app will run on future releases of DirectX.\n//-----------------------------------------------------------------------------\nDWORD GetDXVersion()\n{\n\tDIRECTDRAWCREATEEX\t DirectDrawCreateEx = NULL;\n\tHINSTANCE\t\t\t hDDrawDLL\t\t\t= nil;\n\tHINSTANCE\t\t\t hD3D8DLL\t\t\t= nil;\n\tHINSTANCE\t\t\t hDPNHPASTDLL\t\t= NULL;\n\tDWORD\t\t\t\t dwDXVersion\t\t= 0;\n\t//HRESULT\t\t\t   hr;\n\n\t// First see if DDRAW.DLL even exists.\n\thDDrawDLL = LoadLibrary( \"DDRAW.DLL\" );\n\tif( hDDrawDLL == nil )\n\t{\n\t\tdwDXVersion = 0;\n\t\tOutputDebugString( \"Couldn't LoadLibrary DDraw\\r\\n\" );\n\t\treturn dwDXVersion;\n\t}\n\n\n\t//-------------------------------------------------------------------------\n\t// DirectX 7.0 Checks\n\t//-------------------------------------------------------------------------\n\n\t// Check for DirectX 7 by creating a DDraw7 object\n\tLPDIRECTDRAW7 pDD7;\n\tDirectDrawCreateEx = (DIRECTDRAWCREATEEX)GetProcAddress( hDDrawDLL,\n\t\t\t\t\t\t\t\t\t\t\t\t\t   \"DirectDrawCreateEx\" );\n\tif( nil == DirectDrawCreateEx )\n\t{\n\t\tFreeLibrary( hDDrawDLL );\n\t\tOutputDebugString( \"Couldn't GetProcAddress DirectDrawCreateEx\\r\\n\" );\n\t\treturn dwDXVersion;\n\t}\n\n\tif( FAILED( DirectDrawCreateEx( nil, (VOID**)&pDD7, IID_IDirectDraw7,\n\t\t\t\t\t\t\t\t\tnil ) ) )\n\t{\n\t\tFreeLibrary( hDDrawDLL );\n\t\tOutputDebugString( \"Couldn't DirectDrawCreateEx\\r\\n\" );\n\t\treturn dwDXVersion;\n\t}\n\n\t// DDraw7 was created successfully. We must be at least DX7.0\n\tdwDXVersion = 0x700;\n\tpDD7->Release();\n\n#ifdef USE_D3D9\n\tHINSTANCE hD3D9DLL = LoadLibrary(\"D3D9.DLL\");\n\tif (hD3D9DLL != nil) {\n\t\tFreeLibrary(hDDrawDLL);\n\t\tFreeLibrary(hD3D9DLL);\n\n\t\tdwDXVersion = 0x900;\n\t\treturn dwDXVersion;\n\t}\n#endif\n\n\t//-------------------------------------------------------------------------\n\t// DirectX 8.0 Checks\n\t//-------------------------------------------------------------------------\n\n\t// Simply see if D3D8.dll exists.\n\thD3D8DLL = LoadLibrary( \"D3D8.DLL\" );\n\tif( hD3D8DLL == nil )\n\t{\n\t\tFreeLibrary( hDDrawDLL );\n\t\tOutputDebugString( \"Couldn't LoadLibrary D3D8.DLL\\r\\n\" );\n\t\treturn dwDXVersion;\n\t}\n\n\t// D3D8.dll exists. We must be at least DX8.0\n\tdwDXVersion = 0x800;\n\n\n\t//-------------------------------------------------------------------------\n\t// DirectX 8.1 Checks\n\t//-------------------------------------------------------------------------\n\n\t// Simply see if dpnhpast.dll exists.\n\thDPNHPASTDLL = LoadLibrary( \"dpnhpast.dll\" );\n\tif( hDPNHPASTDLL == nil )\n\t{\n\t\tFreeLibrary( hDPNHPASTDLL );\n\t\tOutputDebugString( \"Couldn't LoadLibrary dpnhpast.dll\\r\\n\" );\n\t\treturn dwDXVersion;\n\t}\n\n\t// dpnhpast.dll exists. We must be at least DX8.1\n\tdwDXVersion = 0x801;\n\n\n\t//-------------------------------------------------------------------------\n\t// End of checking for versions of DirectX \n\t//-------------------------------------------------------------------------\n\n\t// Close open libraries and return\n\tFreeLibrary( hDDrawDLL );\n\tFreeLibrary( hD3D8DLL );\n\t\n\treturn dwDXVersion;\n}\n\n/*\n *****************************************************************************\n */\n#ifndef _WIN64\nstatic char cpuvendor[16] = \"UnknownVendr\";\n__declspec(naked)  const char * _psGetCpuVendr()\n{\n\t__asm\n\t{\n\t\tpush\tebx\n\t\txor\t\teax, eax\n\t\tcpuid\n\t\tmov\t\tdword ptr [cpuvendor+0], ebx\n\t\tmov\t\tdword ptr [cpuvendor+4], edx\n\t\tmov\t\tdword ptr [cpuvendor+8], ecx\n\t\tmov\t\teax, offset cpuvendor\n\t\tpop\t\tebx\n\t\tretn\n\t}\n}\n\n/*\n *****************************************************************************\n */\n__declspec(naked) RwUInt32 _psGetCpuFeatures()\n{\n\t__asm\n\t{\n\t\tmov\t\teax, 1\n\t\tcpuid\n\t\tmov\t\teax, edx\n\t\tretn\n\t}\n}\n\n/*\n *****************************************************************************\n */\n__declspec(naked) RwUInt32 _psGetCpuFeaturesEx()\n{\n\t__asm\n\t{\n\t\tmov\t\teax, 80000000h\n\t\tcpuid\n\n\t\tcmp\t\teax, 80000000h\n\t\tjbe\t\tshort _NOEX\n\n\t\tmov\t\teax, 80000001h\n\t\tcpuid\n\n\t\tmov\t\teax, edx\n\t\tjmp\t\tshort _RETEX\n\n_NOEX:\n\t\txor\t\teax, eax\n\t\tmov\t\teax, eax\n\t\t\n_RETEX:\n\t\tretn   \n\t}\n}\n\n#ifdef __MWERKS__\n#pragma dont_inline on\n#endif\nvoid _psPrintCpuInfo()\n{\n\tRwUInt32 features\t= _psGetCpuFeatures();\n\tRwUInt32 FeaturesEx = _psGetCpuFeaturesEx();\n\n\tdebug(\"Running on a %s\", _psGetCpuVendr());\n\n\tif ( features & 0x800000 )\n\t\tdebug(\"with MMX\");\n\tif ( features & 0x2000000 )\n\t\tdebug(\"with SSE\");\n\tif ( FeaturesEx & 0x80000000 )\n\t\tdebug(\"with 3DNow\");\n}\n#ifdef __MWERKS__\n#pragma dont_inline off\n#endif\n#endif\n\n/*\n *****************************************************************************\n */\n#ifdef UNDER_CE\n#define CMDSTR\tLPWSTR\n#else\n#define CMDSTR\tLPSTR\n#endif\n\n/*\n *****************************************************************************\n */\nRwBool\npsInitialize(void)\n{\n\tPsGlobal.lastMousePos.x = PsGlobal.lastMousePos.y = 0.0f;\n\n\tRsGlobal.ps = &PsGlobal;\n\t\n\tPsGlobal.fullScreen = FALSE;\n\t\n\tPsGlobal.dinterface = nil;\n\tPsGlobal.mouse\t   = nil;\n\tPsGlobal.joy1\t= nil;\n\tPsGlobal.joy2\t= nil;\n\n\tCFileMgr::Initialise();\n\n#ifdef PS2_MENU\n\tCPad::Initialise();\n\tCPad::GetPad(0)->Mode = 0;\n\t\n\tCGame::frenchGame = false;\n\tCGame::germanGame = false;\n\tCGame::nastyGame = true;\n\tCMenuManager::m_PrefsAllowNastyGame = true;\n\t\n\tWORD lang\t= PRIMARYLANGID(GetSystemDefaultLCID());\n\tif ( lang  == LANG_ITALIAN )\n\t\tCMenuManager::m_PrefsLanguage = CMenuManager::LANGUAGE_ITALIAN;\n\telse if ( lang  == LANG_SPANISH )\n\t\tCMenuManager::m_PrefsLanguage = CMenuManager::LANGUAGE_SPANISH;\n\telse if ( lang  == LANG_GERMAN )\n\t{\n\t\tCGame::germanGame = true;\n\t\tCGame::nastyGame = false;\n\t\tCMenuManager::m_PrefsAllowNastyGame = false;\n\t\tCMenuManager::m_PrefsLanguage = CMenuManager::LANGUAGE_GERMAN;\n\t}\n\telse if ( lang  == LANG_FRENCH )\n\t{\n\t\tCGame::frenchGame = true;\n\t\tCGame::nastyGame = false;\n\t\tCMenuManager::m_PrefsAllowNastyGame = false;\n\t\tCMenuManager::m_PrefsLanguage = CMenuManager::LANGUAGE_FRENCH;\n\t}\n\telse\n\t\tCMenuManager::m_PrefsLanguage = CMenuManager::LANGUAGE_AMERICAN;\n\t\n\tFrontEndMenuManager.InitialiseMenuContentsAfterLoadingGame();\n\t\n\tTheMemoryCard.Init();\n#else\n\tC_PcSave::SetSaveDirectory(_psGetUserFilesFolder());\n\t\n\tInitialiseLanguage();\n#endif\n\t\n\tgGameState = GS_START_UP;\n\tTRACE(\"gGameState = GS_START_UP\");\n#ifndef _WIN64\n\t_psPrintCpuInfo();\n#endif\n\tOSVERSIONINFO verInfo;\n\tverInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);\n\t\n\tGetVersionEx(&verInfo);\n\t\n\t_dwOperatingSystemVersion = OS_WIN95;\n\t\n\tif ( verInfo.dwPlatformId == VER_PLATFORM_WIN32_NT )\n\t{\n\t\tif ( verInfo.dwMajorVersion == 4 )\n\t\t{\n\t\t\tdebug(\"Operating System is WinNT\\n\");\n\t\t\t_dwOperatingSystemVersion = OS_WINNT;\n\t\t}\n\t\telse if ( verInfo.dwMajorVersion == 5 )\n\t\t{\n\t\t\tdebug(\"Operating System is Win2000\\n\");\n\t\t\t_dwOperatingSystemVersion = OS_WIN2000;\n\t\t}\n\t\telse if ( verInfo.dwMajorVersion > 5 )\n\t\t{\n\t\t\tdebug(\"Operating System is WinXP or greater\\n\");\n\t\t\t_dwOperatingSystemVersion = OS_WINXP;\n\t\t}\n\t}\n\telse if ( verInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS )\n\t{\n\t\tif ( verInfo.dwMajorVersion > 4 || verInfo.dwMajorVersion == 4 && verInfo.dwMinorVersion != 0 )\n\t\t{\n\t\t\tdebug(\"Operating System is Win98\\n\");\n\t\t\t_dwOperatingSystemVersion = OS_WIN98;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tdebug(\"Operating System is Win95\\n\");\n\t\t\t_dwOperatingSystemVersion = OS_WIN95;\n\t\t}\n\t}\n\n#ifndef PS2_MENU\n\tFrontEndMenuManager.LoadSettings();\n#endif\n\n\tdwDXVersion = GetDXVersion();\n\tdebug(\"DirectX version 0x%x\\n\", dwDXVersion);\n\t\n\tif ( _dwOperatingSystemVersion == OS_WIN95 )\n\t{\n\t\tMessageBoxW(nil,\n\t\t\t\t\t(LPCWSTR)TheText.Get(\"WIN_95\"),\t // Grand Theft Auto III cannot run on Windows 95\n\t\t\t\t\t(LPCWSTR)TheText.Get(\"WIN_TTL\"), // Grand Theft Auto III\n\t\t\t\t\tMB_OK);\n\n\t\treturn FALSE;\n\t}\n\t\n\tif ( dwDXVersion < 0x801 )\n\t{\n\t\tMessageBoxW(nil,\n\t\t\t\t\t(LPCWSTR)TheText.Get(\"WIN_DX\"),\t // Grand Theft Auto III requires at least DirectX version 8.1\n\t\t\t\t\t(LPCWSTR)TheText.Get(\"WIN_TTL\"), // Grand Theft Auto III\n\t\t\t\t\tMB_OK);\n\n\t\treturn FALSE;\n\t}\n\t\n\tMEMORYSTATUS memstats;\n\tGlobalMemoryStatus(&memstats);\n\t\n\t_dwMemTotalPhys\t   = memstats.dwTotalPhys;\n\t_dwMemAvailPhys\t   = memstats.dwAvailPhys;\n\t_dwMemTotalVirtual = memstats.dwTotalVirtual;\n\t_dwMemAvailVirtual = memstats.dwAvailVirtual;\n\t\n\t_GetVideoMemInfo(&_dwMemTotalVideo, &_dwMemAvailVideo);\n#ifdef FIX_BUGS\n\tdebug(\"Physical memory size %lu\\n\", _dwMemTotalPhys);\n\tdebug(\"Available physical memory %lu\\n\", _dwMemAvailPhys);\n\tdebug(\"Video memory size %lu\\n\", _dwMemTotalVideo);\n\tdebug(\"Available video memory %lu\\n\", _dwMemAvailVideo);\n#else\n\tdebug(\"Physical memory size %d\\n\", _dwMemTotalPhys);\n\tdebug(\"Available physical memory %d\\n\", _dwMemAvailPhys);\n\tdebug(\"Video memory size %d\\n\", _dwMemTotalVideo);\n\tdebug(\"Available video memory %d\\n\", _dwMemAvailVideo);\n#endif\n\t\n\tif ( _dwMemAvailVideo < (12 * 1024 * 1024) /*12 MB*/ )\n\t{\n\t\tMessageBoxW(nil,\n\t\t\t\t\t(LPCWSTR)TheText.Get(\"WIN_VDM\"), // Grand Theft Auto III requires at least 12MB of available video memory\n\t\t\t\t\t(LPCWSTR)TheText.Get(\"WIN_TTL\"), // Grand Theft Auto III\n\t\t\t\t\tMB_OK);\n\n\t\treturn FALSE;\n\t}\n\t\n\tTheText.Unload();\n\n\treturn TRUE;\n}\n\n\n/*\n *****************************************************************************\n */\nvoid\npsTerminate(void)\n{\n\treturn;\n}\n\n/*\n *****************************************************************************\n */\nstatic RwChar **_VMList;\n\nRwInt32 _psGetNumVideModes()\n{\n\treturn RwEngineGetNumVideoModes();\n}\n\n/*\n *****************************************************************************\n */\nRwBool _psFreeVideoModeList()\n{\n\tRwInt32 numModes;\n\tRwInt32 i;\n\t\n\tnumModes = _psGetNumVideModes();\n\t\n\tif ( _VMList == nil )\n\t\treturn TRUE;\n\t\n\tfor ( i = 0; i < numModes; i++ )\n\t{\n\t\tRwFree(_VMList[i]);\n\t}\n\t\n\tRwFree(_VMList);\n\t\n\t_VMList = nil;\n\t\n\treturn TRUE;\n}\n\t\t\t\t\t\t\t\n/*\n *****************************************************************************\n */\t\t\t\t\t\t\t\nRwChar **_psGetVideoModeList()\n{\n\tRwInt32 numModes;\n\tRwInt32 i;\n\t\n\tif ( _VMList != nil )\n\t{\n\t\treturn _VMList;\n\t}\n\t\n\tnumModes = RwEngineGetNumVideoModes();\n\t\n\t_VMList = (RwChar **)RwCalloc(numModes, sizeof(RwChar*));\n\t\n\tfor ( i = 0; i < numModes; i++\t)\n\t{\n\t\tRwVideoMode\t\t\tvm;\n\t\t\n\t\tRwEngineGetVideoModeInfo(&vm, i);\n\t\t\n\t\tif ( vm.flags & rwVIDEOMODEEXCLUSIVE )\n\t\t{\n\t\t\tif (   vm.width >= 640\n\t\t\t\t&& vm.height >= 480\n\t\t\t\t&& (vm.width == 640\n\t\t\t\t&& vm.height == 480) \n\t\t\t\t|| !(vm.flags & rwVIDEOMODEEXCLUSIVE)\n\t\t\t\t|| (_dwMemTotalVideo - vm.depth * vm.height * vm.width / 8) > (12 * 1024 * 1024)/*12 MB*/ )\n\t\t\t{\n\t\t\t\t_VMList[i] = (RwChar*)RwCalloc(100, sizeof(RwChar));\n\t\t\t\trwsprintf(_VMList[i],\"%lu X %lu X %lu\", vm.width, vm.height, vm.depth);\n\t\t\t}\n\t\t\telse\n\t\t\t\t_VMList[i] = nil;\n\t\t}\n\t\telse\n\t\t\t_VMList[i] = nil;\n\t}\n\t\n\treturn _VMList;\n}\n\n/*\n *****************************************************************************\n */\nvoid _psSelectScreenVM(RwInt32 videoMode)\n{\n\tRwTexDictionarySetCurrent( nil );\n\t\n\tFrontEndMenuManager.UnloadTextures();\n\t\n\tif ( !_psSetVideoMode(RwEngineGetCurrentSubSystem(), videoMode) )\n\t{\n\t\tRsGlobal.quit = TRUE;\n\t\t\n\t\tShowWindow(PSGLOBAL(window), SW_HIDE);\n\n\t\tMessageBoxW(nil,\n\t\t\t(LPCWSTR)TheText.Get(\"WIN_RSZ\"), // Failed to select new screen resolution\n\t\t\t(LPCWSTR)TheText.Get(\"WIN_TTL\"), // Grand Theft Auto III\n\t\t\tMB_OK);\t\t\n\t}\n\telse\n\t\tFrontEndMenuManager.LoadAllTextures();\n}\n\n/*\n *****************************************************************************\n */\nvoid WaitForState(FILTER_STATE State)\n{\n\tHRESULT hr;\n\t\n\tASSERT(pMC != nil);\n\t\n\t// Make sure we have switched to the required state\n\tLONG   lfs;\n\tdo\n\t{\n\t\thr = pMC->GetState(10, &lfs);\n\t} while (State != lfs);\n}\n\n/*\n *****************************************************************************\n */\nvoid HandleGraphEvent(void)\n{\n\tLONG evCode, evParam1, evParam2;\n\tHRESULT hr=S_OK;\n\t\n\tASSERT(pME != nil);\n\n\t// Process all queued events\n\twhile (SUCCEEDED(pME->GetEvent(&evCode, (LONG_PTR *)&evParam1,\n\t\t(LONG_PTR *)&evParam2, 0)))\n\t{\n\t\t// Free memory associated with callback, since we're not using it\n\t\thr = pME->FreeEventParams(evCode, evParam1, evParam2);\n\n\t\t// If this is the end of the clip, reset to beginning\n\t\tif (EC_COMPLETE == evCode)\n\t\t{\n\t\t\tswitch (gGameState)\n\t\t\t{\n\t\t\t\tcase GS_LOGO_MPEG:\n\t\t\t\t{\n\t\t\t\t\tgGameState = GS_INIT_INTRO_MPEG;\n\t\t\t\t\tTRACE(\"gGameState = GS_INIT_INTRO_MPEG\");\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase GS_INTRO_MPEG:\n\t\t\t\t{\n\t\t\t\t\tgGameState = GS_INIT_ONCE;\n\t\t\t\t\tTRACE(\"gGameState = GS_INIT_ONCE\");\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tdefault:\n\t\t\t\t{\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tpME->SetNotifyWindow((OAHWND)NULL, 0, 0);\n\t\t}\n\t}\n}\n\n/*\n *****************************************************************************\n */ \nLRESULT CALLBACK\nMainWndProc(HWND window, UINT message, WPARAM wParam, LPARAM lParam)\n{\n\tPOINTS points;\n\tstatic BOOL noMemory = FALSE;\n\n\t\n\tswitch( message )\n\t{\n\t\tcase WM_SETCURSOR:\n\t\t{\n\t\t\tShowCursor(FALSE);\n\t\t\t\n\t\t\tSetCursor(nil);\n\t\t\t\n\t\t\tbreak; // is this correct ?\n\t\t}\n\t\t\n\t\tcase WM_SIZE:\n\t\t{\n\t\t\tRwRect r;\n\n\t\t\tr.x = 0;\n\t\t\tr.y = 0;\n\t\t\tr.w = LOWORD(lParam);\n\t\t\tr.h = HIWORD(lParam);\n\n\t\t\tif (RwInitialised && r.h > 0 && r.w > 0)\n\t\t\t{\n\t\t\t\tRsEventHandler(rsCAMERASIZE, &r);\n\n\t\t\t\tif (r.w != LOWORD(lParam) && r.h != HIWORD(lParam))\n\t\t\t\t{\n\t\t\t\t\tWINDOWPLACEMENT\t\twp;\n\n\t\t\t\t\t/* failed to create window of required size */\n\t\t\t\t\tnoMemory = TRUE;\n\n\t\t\t\t\t/* stop re-sizing */\n\t\t\t\t\tReleaseCapture();\n\n\t\t\t\t\t/* handle maximised window */\n\t\t\t\t\tGetWindowPlacement(window, &wp);\n\t\t\t\t\tif (wp.showCmd == SW_SHOWMAXIMIZED)\n\t\t\t\t\t{\n\t\t\t\t\t\tSendMessage(window, WM_WINDOWPOSCHANGED, 0, 0);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tnoMemory = FALSE;\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\treturn 0L;\n\t\t}\n\n\t\tcase WM_SIZING:\n\t\t{\n\t\t\t/* \n\t\t\t * Handle event to ensure window contents are displayed during re-size\n\t\t\t * as this can be disabled by the user, then if there is not enough \n\t\t\t * memory things don't work.\n\t\t\t */\n\t\t\tRECT\t\t\t   *newPos = (LPRECT) lParam;\n\t\t\tRECT\t\t\t\trect;\n\n\t\t\t/* redraw window */\n\n\t\t\tif (RwInitialised && gGameState == GS_PLAYING_GAME)\n\t\t\t{\n\t\t\t\tRsEventHandler(rsIDLE, (void *)TRUE);\n\t\t\t}\n\n\t\t\t/* Manually resize window */\n\t\t\trect.left = rect.top = 0;\n\t\t\trect.bottom = newPos->bottom - newPos->top;\n\t\t\trect.right = newPos->right - newPos->left;\n\n\t\t\tSetWindowPos(window, HWND_TOP, rect.left, rect.top,\n\t\t\t\t\t\t (rect.right - rect.left),\n\t\t\t\t\t\t (rect.bottom - rect.top), SWP_NOMOVE);\n\n\t\t\treturn 0L;\n\t\t}\n\n\t\tcase WM_LBUTTONDOWN:\n\t\t{\n\t\t\tSetCapture(window);\n\n\t\t\treturn 0L;\n\t\t}\n\n\t\tcase WM_RBUTTONDOWN:\n\t\t{\n\t\t\tSetCapture(window);\n\n\t\t\treturn 0L;\n\t\t}\n\t\t\n\t\tcase WM_MBUTTONDOWN:\n\t\t{\n\t\t\tSetCapture(window);\n\n\t\t\treturn 0L;\n\t\t}\n\n\t\tcase WM_MOUSEWHEEL:\n\t\t{\n\t\t\treturn 0L;\n\t\t}\n\n\t\tcase WM_MOUSEMOVE:\n\t\t{\n\t\t\tpoints = MAKEPOINTS(lParam);\n\n\t\t\tFrontEndMenuManager.m_nMouseTempPosX = points.x;\n\t\t\tFrontEndMenuManager.m_nMouseTempPosY = points.y;\n\n\t\t\treturn 0L;\n\t\t}\n\n\t\tcase WM_LBUTTONUP:\n\t\t{\n\t\t\tReleaseCapture();\n\n\t\t\treturn 0L;\n\t\t}\n\n\t\tcase WM_RBUTTONUP:\n\t\t{\n\t\t\tReleaseCapture();\n\n\t\t\treturn 0L;\n\t\t}\n\t\t\n\t\tcase WM_MBUTTONUP:\n\t\t{\n\t\t\tReleaseCapture();\n\n\t\t\treturn 0L;\n\t\t}\n\n\t\tcase WM_KEYDOWN:\n\t\t{\n\t\t\tRsKeyCodes ks;\n\t\t\t\n\t\t\tif ( _InputTranslateKey(&ks, lParam, wParam) )\n\t\t\t\tRsKeyboardEventHandler(rsKEYDOWN, &ks);\n\n\t\t\tif ( wParam == VK_SHIFT )\n\t\t\t\t_InputTranslateShiftKeyUpDown(&ks);\n#ifdef FIX_BUGS\n\t\t\tbreak;\n#else\n\t\t\treturn 0L;\n#endif\n\t\t}\n\n\t\tcase WM_KEYUP:\n\t\t{\n\t\t\tRsKeyCodes ks;\n\n\t\t\tif ( _InputTranslateKey(&ks, lParam, wParam) )\n\t\t\t\tRsKeyboardEventHandler(rsKEYUP, &ks);\n\n\t\t\tif ( wParam == VK_SHIFT )\n\t\t\t\t_InputTranslateShiftKeyUpDown(&ks);\n\n#ifdef FIX_BUGS\n\t\t\tbreak;\n#else\n\t\t\treturn 0L;\n#endif\n\t\t}\n\n\t\tcase WM_SYSKEYDOWN:\n\t\t{\n\t\t\tRsKeyCodes ks;\n\t\t\t\n\t\t\tif ( _InputTranslateKey(&ks, lParam, wParam) )\n\t\t\t\tRsKeyboardEventHandler(rsKEYDOWN, &ks);\n\n\t\t\tif ( wParam == VK_SHIFT )\n\t\t\t\t_InputTranslateShiftKeyUpDown(&ks);\n\n#ifdef FIX_BUGS\n\t\t\tbreak;\n#else\n\t\t\treturn 0L;\n#endif\n\t\t}\n\n\t\tcase WM_SYSKEYUP:\n\t\t{\n\t\t\tRsKeyCodes ks;\n\n\t\t\tif ( _InputTranslateKey(&ks, lParam, wParam) )\n\t\t\t\tRsKeyboardEventHandler(rsKEYUP, &ks);\n\n\t\t\tif ( wParam == VK_SHIFT )\n\t\t\t\t_InputTranslateShiftKeyUpDown(&ks);\n\n#ifdef FIX_BUGS\n\t\t\tbreak;\n#else\n\t\t\treturn 0L;\n#endif\n\t\t}\n\n\t\tcase WM_ACTIVATEAPP:\n\t\t{\n\t\t\tswitch ( gGameState )\n\t\t\t{\n\t\t\t\tcase GS_LOGO_MPEG:\n\t\t\t\tcase GS_INTRO_MPEG:\n\t\t\t\t{\n\t\t\t\t\tASSERT(pMC != nil);\n\t\t\t\t\t\n\t\t\t\t\tLONG state;\n\t\t\t\t\tpMC->GetState(10, &state);\n\t\t\t\t\t\n\t\t\t\t\tif ( !(BOOL)wParam ) // losing activation\n\t\t\t\t\t{\n\t\t\t\t\t\tif ( state == State_Running && pMC != nil )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tHRESULT hr = pMC->Pause();\n\n\t\t\t\t\t\t\tif (hr == S_FALSE)\n\t\t\t\t\t\t\t\tOutputDebugString(\"Failed to pause the MPEG\");\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\tWaitForState(State_Paused);\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\tCenterVideo();\n\t\t\t\t\t\t\n\t\t\t\t\t\tif ( state != State_Running && pMC != nil )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tHRESULT hr = pMC->Run();\n\n\t\t\t\t\t\t\tif ( hr == S_FALSE )\n\t\t\t\t\t\t\t\tOutputDebugString(\"Failed to run the MPEG\");\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tWaitForState(State_Running);\n\t\t\t\t\t\t\t\tSetFocus(PSGLOBAL(window));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tcase GS_START_UP:\n\t\t\t\t{\n\t\t\t\t\tif ( !(BOOL)wParam && PSGLOBAL(fullScreen) ) // losing activation\n\t\t\t\t\t\tstartupDeactivate = TRUE;\n\t\t\t\t\t\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tCPad::GetPad(0)->Clear(false);\n\t\t\tCPad::GetPad(1)->Clear(false);\n\t\t\t\n\t\t\treturn 0L;\n\t\t}\n\t\t\n\t\tcase WM_TIMER:\n\t\t{\n\t\t\treturn 0L;\n\t\t}\n\t\t\n\t\tcase WM_GRAPHNOTIFY:\n\t\t{\n\t\t\tif (gGameState == GS_INTRO_MPEG || gGameState == GS_LOGO_MPEG)\n\t\t\t\tHandleGraphEvent();\n\n\t\t\tbreak;\n\t\t}\n\n\t\tcase WM_CLOSE:\n\t\tcase WM_DESTROY:\n\t\t{\n\t\t\t/*\n\t\t\t * Quit message handling.\n\t\t\t */\n\t\t\tClipCursor(nil);\n\t\t\t\n\t\t\t_InputShutdown();\n\n\t\t\tPostQuitMessage(0);\n\n\t\t\treturn 0L;\n\t\t}\n\t\t\n\t\tcase WM_DEVICECHANGE:\n\t\t{\n\t\t\tif( wParam == DBT_DEVICEREMOVECOMPLETE )\n\t\t\t{\n\t\t\t\tPDEV_BROADCAST_HDR pDev = (PDEV_BROADCAST_HDR)lParam;\n\t\t\t\t\n\t\t\t\tif (pDev->dbch_devicetype != DBT_DEVTYP_VOLUME)\n\t\t\t\t\tbreak;\n\n\t\t\t\tif ( DMAudio.IsAudioInitialised() )\n\t\t\t\t{\n\t\t\t\t\tPDEV_BROADCAST_VOLUME pVol = (PDEV_BROADCAST_VOLUME)pDev;\n\t\t\t\t\tif ( pVol->dbcv_flags & DBTF_MEDIA )\n\t\t\t\t\t{\n\t\t\t\t\t\tchar c = DMAudio.GetCDAudioDriveLetter();\n\t\t\t\t\t\t\n\t\t\t\t\t\tif ( c >= 'A' && pVol->dbcv_unitmask & (1 << (c - 'A')) )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tOutputDebugString(\"About to check CD drive...\");\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\twhile ( true )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tFrontEndMenuManager.WaitForUserCD();\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\tif ( !FrontEndMenuManager.m_bQuitGameNoCD )\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tif ( DMAudio.CheckForAnAudioFileOnCD() )\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tOutputDebugString(\"GTA3 Audio CD has been inserted\");\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tOutputDebugString(\"Exiting game as Audio CD was not inserted\");\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tbreak;\n\t\t}\n\n#ifdef FIX_BUGS // game turns on menu when focus is re-gained rather than lost\n\t\tcase WM_KILLFOCUS:\n#else\n\t\tcase WM_SETFOCUS:\n#endif\n\t\t{\n\t\t\tCGame::InitAfterFocusLoss();\n\t\t\tbreak;\n\t\t}\n\n\t}\n\n\t/*\n\t * Let Windows handle all other messages.\n\t */\n\treturn DefWindowProc(window, message, wParam, lParam);\n}\n\n/*\n *****************************************************************************\n */\nstatic BOOL\nInitApplication(HANDLE instance)\n{\n\t/*\n\t * Perform any necessary MS Windows application initialization. Basically,\n\t * this means registering the window class for this application.\n\t */\n\n\tWNDCLASS windowClass;\n\n\twindowClass.style = CS_BYTEALIGNWINDOW;\n\twindowClass.lpfnWndProc = (WNDPROC)MainWndProc;\n\twindowClass.cbClsExtra = 0;\n\twindowClass.cbWndExtra = 0;\n\twindowClass.hInstance = (HINSTANCE)instance;\n\twindowClass.hIcon = LoadIcon((HINSTANCE)instance, (LPCSTR)IDI_MAIN_ICON);\n\twindowClass.hCursor = LoadCursor(nil, IDC_ARROW);\n\twindowClass.hbrBackground = nil;\n\twindowClass.lpszMenuName = NULL;\n\twindowClass.lpszClassName = AppClassName;\n\n\treturn RegisterClass(&windowClass);\n}\n\n\n/*\n *****************************************************************************\n */\n\nRwBool IsForegroundApp()\n{\n\treturn !!ForegroundApp;\n}\n\nUINT GetBestRefreshRate(UINT width, UINT height, UINT depth)\n{\n#ifdef USE_D3D9\n\tLPDIRECT3D9 d3d = Direct3DCreate9(D3D_SDK_VERSION);\n#else\n\tLPDIRECT3D8 d3d = Direct3DCreate8(D3D_SDK_VERSION);\n#endif\n\tASSERT(d3d != nil);\n\t\n\tUINT refreshRate = INT_MAX;\n\tD3DFORMAT format;\n\n\tif ( depth == 32 )\n\t\tformat = D3DFMT_X8R8G8B8;\n\telse if ( depth == 24 )\n\t\tformat = D3DFMT_R8G8B8;\n\telse\n\t\tformat = D3DFMT_R5G6B5;\n\t\n#ifdef USE_D3D9\n\tUINT modeCount = d3d->GetAdapterModeCount(GcurSel, format);\n#else\n\tUINT modeCount = d3d->GetAdapterModeCount(GcurSel);\n#endif\n\n\tfor ( UINT i = 0; i < modeCount; i++ )\n\t{\n\t\tD3DDISPLAYMODE mode;\n\t\t\n#ifdef USE_D3D9\n\t\td3d->EnumAdapterModes(GcurSel, format, i, &mode);\n#else\n\t\td3d->EnumAdapterModes(GcurSel, i, &mode);\n#endif\t\n\t\tif ( mode.Width == width && mode.Height == height && mode.Format == format )\n\t\t{\n\t\t\tif ( mode.RefreshRate == 0 ) {\n\t\t\t\td3d->Release();\n\t\t\t\treturn 0;\n\t\t\t}\n\n\t\t\tif ( mode.RefreshRate < refreshRate && mode.RefreshRate >= 60 )\n\t\t\t\trefreshRate = mode.RefreshRate;\n\t\t}\n\t}\n\t\n\td3d->Release();\n\t\n\tif ( refreshRate == -1 )\n\t\treturn -1;\n\n\treturn refreshRate;\n}\n\n/*\n *****************************************************************************\n */\nRwBool\npsSelectDevice()\n{\n\tRwVideoMode\t\t\tvm;\n\tRwInt32\t\t\t\tsubSysNum;\n\tRwInt32\t\t\t\tAutoRenderer = 0;\n\t\n\n\tRwBool modeFound = FALSE;\n\t\n\tif ( !useDefault )\n\t{\n\t\tGnumSubSystems = RwEngineGetNumSubSystems();\n\t\tif ( !GnumSubSystems )\n\t\t{\n\t\t\t return FALSE;\n\t\t}\n\t\t\n\t\t/* Just to be sure ... */\n\t\tGnumSubSystems = (GnumSubSystems > MAX_SUBSYSTEMS) ? MAX_SUBSYSTEMS : GnumSubSystems;\n\t\t\n\t\t/* Get the names of all the sub systems */\n\t\tfor (subSysNum = 0; subSysNum < GnumSubSystems; subSysNum++)\n\t\t{\n\t\t\tRwEngineGetSubSystemInfo(&GsubSysInfo[subSysNum], subSysNum);\n\t\t}\n\t\t\n\t\t/* Get the default selection */\n\t\tGcurSel = RwEngineGetCurrentSubSystem();\n#ifdef IMPROVED_VIDEOMODE\n\t\tif(FrontEndMenuManager.m_nPrefsSubsystem < GnumSubSystems)\n\t\t\tGcurSel = FrontEndMenuManager.m_nPrefsSubsystem;\n#endif\n\t}\n\t\n\t/* Set the driver to use the correct sub system */\n\tif (!RwEngineSetSubSystem(GcurSel))\n\t{\n\t\treturn FALSE;\n\t}\n\n#ifdef IMPROVED_VIDEOMODE\n\tFrontEndMenuManager.m_nPrefsSubsystem = GcurSel;\n#endif\n\n#ifndef IMPROVED_VIDEOMODE\n\tif ( !useDefault )\n\t{\n\t\tif ( _psGetVideoModeList()[FrontEndMenuManager.m_nDisplayVideoMode] && FrontEndMenuManager.m_nDisplayVideoMode )\n\t\t{\n\t\t\tFrontEndMenuManager.m_nPrefsVideoMode = FrontEndMenuManager.m_nDisplayVideoMode;\n\t\t\tGcurSelVM = FrontEndMenuManager.m_nDisplayVideoMode;\n\t\t}\n\t\telse\n\t\t{\n#ifdef DEFAULT_NATIVE_RESOLUTION\n\t\t\t// get the native video mode\n\t\t\tHDC hDevice = GetDC(NULL);\n\t\t\tint w = GetDeviceCaps(hDevice, HORZRES);\n\t\t\tint h = GetDeviceCaps(hDevice, VERTRES);\n\t\t\tint d = GetDeviceCaps(hDevice, BITSPIXEL);\n#else\n\t\t\tconst int w = 640;\n\t\t\tconst int h = 480;\n\t\t\tconst int d = 16;\n#endif\n\t\t\twhile ( !modeFound && GcurSelVM < RwEngineGetNumVideoModes() )\n\t\t\t{\n\t\t\t\tRwEngineGetVideoModeInfo(&vm, GcurSelVM);\n\t\t\t\tif ( defaultFullscreenRes\t&& vm.width\t != w \n\t\t\t\t\t\t\t\t\t\t\t|| vm.height != h\n\t\t\t\t\t\t\t\t\t\t\t|| vm.depth\t != d\n\t\t\t\t\t\t\t\t\t\t\t|| !(vm.flags & rwVIDEOMODEEXCLUSIVE) )\n\t\t\t\t\t++GcurSelVM;\n\t\t\t\telse\n\t\t\t\t\tmodeFound = TRUE;\n\t\t\t}\n\t\t\t\n\t\t\tif ( !modeFound )\n\t\t\t{\n#ifdef DEFAULT_NATIVE_RESOLUTION\n\t\t\t\tGcurSelVM = 1;\n#else\n\t\t\t\tMessageBox(nil, \"Cannot find 640x480 video mode\", \"GTA3\", MB_OK);\n\t\t\t\treturn FALSE;\n#endif\n\t\t\t}\n\t\t}\n\t}\n#else\n\tif ( !useDefault )\n\t{\n\t\tif(FrontEndMenuManager.m_nPrefsWidth == 0 ||\n\t\t\tFrontEndMenuManager.m_nPrefsHeight == 0 ||\n\t\t\tFrontEndMenuManager.m_nPrefsDepth == 0){\n\t\t\t// Defaults if nothing specified\n\t\t\tFrontEndMenuManager.m_nPrefsWidth = GetSystemMetrics(SM_CXSCREEN);\n\t\t\tFrontEndMenuManager.m_nPrefsHeight = GetSystemMetrics(SM_CYSCREEN);\n\t\t\tFrontEndMenuManager.m_nPrefsDepth = 32;\n\t\t\tFrontEndMenuManager.m_nPrefsWindowed = 0;\n\t\t}\n\n\t\t// Find the videomode that best fits what we got from the settings file\n\t\tRwInt32 bestFsMode = -1;\n\t\tRwInt32 bestWidth = -1;\n\t\tRwInt32 bestHeight = -1;\n\t\tRwInt32 bestDepth = -1;\n\t\tfor (GcurSelVM = 0; GcurSelVM < RwEngineGetNumVideoModes(); GcurSelVM++) {\n\t\t\tRwEngineGetVideoModeInfo(&vm, GcurSelVM);\n\n\t\t\tif (!(vm.flags & rwVIDEOMODEEXCLUSIVE)) {\n\t\t\t\tbestWndMode = GcurSelVM;\n\t\t\t} else {\n\t\t\t\t// try the largest one that isn't larger than what we wanted\n\t\t\t\tif (vm.width >= bestWidth && vm.width <= FrontEndMenuManager.m_nPrefsWidth &&\n\t\t\t\t\tvm.height >= bestHeight && vm.height <= FrontEndMenuManager.m_nPrefsHeight &&\n\t\t\t\t\tvm.depth >= bestDepth && vm.depth <= FrontEndMenuManager.m_nPrefsDepth){\n\t\t\t\t\tbestWidth = vm.width;\n\t\t\t\t\tbestHeight = vm.height;\n\t\t\t\t\tbestDepth = vm.depth;\n\t\t\t\t\tbestFsMode = GcurSelVM;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif(bestFsMode < 0){\n\t\t\tMessageBox(nil, \"Cannot find desired video mode\", \"GTA3\", MB_OK);\n\t\t\treturn FALSE;\n\t\t}\n\t\tGcurSelVM = bestFsMode;\n\n\t\tFrontEndMenuManager.m_nDisplayVideoMode = GcurSelVM;\n\t\tFrontEndMenuManager.m_nPrefsVideoMode = FrontEndMenuManager.m_nDisplayVideoMode;\n\n\t\tFrontEndMenuManager.m_nSelectedScreenMode = FrontEndMenuManager.m_nPrefsWindowed;\n\t}\n#endif\n\n\tRwEngineGetVideoModeInfo(&vm, GcurSelVM);\n\n#ifdef IMPROVED_VIDEOMODE\n\tif (FrontEndMenuManager.m_nPrefsWindowed)\n\t\tGcurSelVM = bestWndMode;\n\n\t// Now GcurSelVM is 0 but vm has sizes(and fullscreen flag) of the video mode we want, that's why we changed the rwVIDEOMODEEXCLUSIVE conditions below\n\tFrontEndMenuManager.m_nPrefsWidth = vm.width;\n\tFrontEndMenuManager.m_nPrefsHeight = vm.height;\n\tFrontEndMenuManager.m_nPrefsDepth = vm.depth;\n#endif\n\n#ifndef PS2_MENU\n\tFrontEndMenuManager.m_nCurrOption = 0;\n#endif\n\t\n\t/* Set up the video mode and set the apps window\n\t* dimensions to match */\n\tif (!RwEngineSetVideoMode(GcurSelVM))\n\t{\n\t\treturn FALSE;\n\t}\n\n#ifdef IMPROVED_VIDEOMODE\n\tif (!FrontEndMenuManager.m_nPrefsWindowed)\n#else\n\tif (vm.flags & rwVIDEOMODEEXCLUSIVE)\n#endif\n\t{\n\t\tdebug(\"%dx%dx%d\", vm.width, vm.height, vm.depth);\n\t\t\n\t\tUINT refresh = GetBestRefreshRate(vm.width, vm.height, vm.depth);\n\t\t\n\t\tif ( refresh != (UINT)-1 )\n\t\t{\n\t\t\tdebug(\"refresh %d\", refresh);\n\t\t\tRwD3D8EngineSetRefreshRate((RwUInt32)refresh);\n\t\t}\n\t}\n\t\n#ifdef IMPROVED_VIDEOMODE\n\tif (!FrontEndMenuManager.m_nPrefsWindowed)\n#else\n\tif (vm.flags & rwVIDEOMODEEXCLUSIVE)\n#endif\n\t{\n\t\tRsGlobal.maximumWidth = vm.width;\n\t\tRsGlobal.maximumHeight = vm.height;\n\t\tRsGlobal.width = vm.width;\n\t\tRsGlobal.height = vm.height;\n\t\t\n\t\tPSGLOBAL(fullScreen) = TRUE;\n\n#ifdef IMPROVED_VIDEOMODE\n\t\tSetWindowLong(PSGLOBAL(window), GWL_STYLE, WS_POPUP);\n\t\tSetWindowPos(PSGLOBAL(window), nil, 0, 0, 0, 0,\n\t\t\t\t\tSWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|\n\t\t\t\t\tSWP_FRAMECHANGED);\n\t}else{\n\t\tRECT rect;\n\t\trect.left = rect.top = 0;\n\t\trect.right = FrontEndMenuManager.m_nPrefsWidth;\n\t\trect.bottom = FrontEndMenuManager.m_nPrefsHeight;\n\t\tAdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, FALSE);\n\n\t\t// center it\n\t\tint spaceX = GetSystemMetrics(SM_CXSCREEN) - (rect.right-rect.left);\n\t\tint spaceY = GetSystemMetrics(SM_CYSCREEN) - (rect.bottom-rect.top);\n\n\t\tSetWindowLong(PSGLOBAL(window), GWL_STYLE, WS_VISIBLE | WS_OVERLAPPEDWINDOW);\n\t\tSetWindowPos(PSGLOBAL(window), HWND_NOTOPMOST, spaceX/2, spaceY/2,\n\t\t\t(rect.right - rect.left),\n\t\t\t(rect.bottom - rect.top), 0);\n\n\t\t// Have to get actual size because the window perhaps didn't fit\n\t\tGetClientRect(PSGLOBAL(window), &rect);\n\t\tRsGlobal.maximumWidth = rect.right;\n\t\tRsGlobal.maximumHeight = rect.bottom;\n\t\tRsGlobal.width = rect.right;\n\t\tRsGlobal.height = rect.bottom;\n\t\t\n\t\tPSGLOBAL(fullScreen) = FALSE;\n#endif\n\t}\n#ifdef MULTISAMPLING\n\tRwD3D8EngineSetMultiSamplingLevels(1 << FrontEndMenuManager.m_nPrefsMSAALevel);\n#endif\n\treturn TRUE;\n}\n\n/*\n *****************************************************************************\n */\nRwBool _psSetVideoMode(RwInt32 subSystem, RwInt32 videoMode)\n{\n\tRwInitialised = FALSE;\n\t\n\tRsEventHandler(rsRWTERMINATE, nil);\n\t\n\tGcurSel = subSystem;\n\tGcurSelVM = videoMode;\n\t\n\tuseDefault = TRUE;\n\t\n\tif ( RsEventHandler(rsRWINITIALIZE, PSGLOBAL(window)) == rsEVENTERROR )\n\t\treturn FALSE;\n\t\n\tRwInitialised = TRUE;\n\tuseDefault = FALSE;\n\t\n\tRwRect r;\n\t\n\tr.x = 0;\n\tr.y = 0;\n\tr.w = RsGlobal.maximumWidth;\n\tr.h = RsGlobal.maximumHeight;\n\n\tRsEventHandler(rsCAMERASIZE, &r);\n\t\n\treturn TRUE;\n}\n \n/*\n *****************************************************************************\n */\nstatic RwChar **\nCommandLineToArgv(RwChar *cmdLine, RwInt32 *argCount)\n{\n\tRwInt32 numArgs = 0;\n\tRwBool inArg, inString;\n\tRwInt32 i, len;\n\tRwChar *res, *str, **aptr;\n\n\tlen = (int)strlen(cmdLine);\n\n\t/* \n\t * Count the number of arguments...\n\t */\n\tinString = FALSE;\n\tinArg = FALSE;\n\n\tfor(i=0; i<=len; i++)\n\t{\n\t\tif( cmdLine[i] == '\"' )\n\t\t{\n\t\t\tinString = !inString;\n\t\t}\n\n\t\tif( (cmdLine[i] <= ' ' && !inString) || i == len )\n\t\t{\n\t\t\tif( inArg ) \n\t\t\t{\n\t\t\t\tinArg = FALSE;\n\t\t\t\t\n\t\t\t\tnumArgs++;\n\t\t\t}\n\t\t} \n\t\telse if( !inArg )\n\t\t{\n\t\t\tinArg = TRUE;\n\t\t}\n\t}\n\n\t/* \n\t * Allocate memory for result...\n\t */\n\tres = (RwChar *)malloc(sizeof(RwChar *) * numArgs + len + 1);\n\tstr = res + sizeof(RwChar *) * numArgs;\n\taptr = (RwChar **)res;\n\n\tstrcpy(str, cmdLine);\n\n\t/*\n\t * Walk through cmdLine again this time setting pointer to each arg...\n\t */\n\tinArg = FALSE;\n\tinString = FALSE;\n\n\tfor(i=0; i<=len; i++)\n\t{\n\t\tif( cmdLine[i] == '\"' )\n\t\t{\n\t\t\tinString = !inString;\n\t\t}\n\n\t\tif( (cmdLine[i] <= ' ' && !inString) || i == len )\n\t\t{\n\t\t\tif( inArg ) \n\t\t\t{\n\t\t\t\tif( str[i-1] == '\"' )\n\t\t\t\t{\n\t\t\t\t\tstr[i-1] = '\\0';\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tstr[i] = '\\0';\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tinArg = FALSE;\n\t\t\t}\n\t\t} \n\t\telse if( !inArg && cmdLine[i] != '\"' )\n\t\t{\n\t\t\tinArg = TRUE; \n\t\t\t\n\t\t\t*aptr++ = &str[i];\n\t\t}\n\t}\n\n\t*argCount = numArgs;\n\n\treturn (RwChar **)res;\n}\n\n/*\n *****************************************************************************\n */\nvoid InitialiseLanguage()\n{\n\tWORD primUserLCID\t= PRIMARYLANGID(GetSystemDefaultLCID());\n\tWORD primSystemLCID = PRIMARYLANGID(GetUserDefaultLCID());\n\tWORD primLayout\t\t= PRIMARYLANGID((DWORD_PTR)GetKeyboardLayout(0));\n\t\n\tWORD subUserLCID\t= SUBLANGID(GetSystemDefaultLCID());\n\tWORD subSystemLCID\t= SUBLANGID(GetUserDefaultLCID());\n\tWORD subLayout\t\t= SUBLANGID((DWORD_PTR)GetKeyboardLayout(0));\n\t\n\tif (   primUserLCID\t  == LANG_GERMAN\n\t\t|| primSystemLCID == LANG_GERMAN\n\t\t|| primLayout\t  == LANG_GERMAN )\n\t{\n\t\tCGame::nastyGame = false;\n\t\tFrontEndMenuManager.m_PrefsAllowNastyGame = false;\n\t\tCGame::germanGame = true;\n\t}\n\t\n\tif (   primUserLCID\t  == LANG_FRENCH\n\t\t|| primSystemLCID == LANG_FRENCH\n\t\t|| primLayout\t  == LANG_FRENCH )\n\t{\n\t\tCGame::nastyGame = false;\n\t\tFrontEndMenuManager.m_PrefsAllowNastyGame = false;\n\t\tCGame::frenchGame = true;\n\t}\n\t\n\tif (   subUserLCID\t == SUBLANG_ENGLISH_AUS\n\t\t|| subSystemLCID == SUBLANG_ENGLISH_AUS\n\t\t|| subLayout\t == SUBLANG_ENGLISH_AUS )\n\t\tCGame::noProstitutes = true;\n\n#ifdef NASTY_GAME\n\tCGame::nastyGame = true;\n\tFrontEndMenuManager.m_PrefsAllowNastyGame = true;\n\tCGame::noProstitutes = false;\n#endif\n\t\n\tint32 lang;\n\t\n\tswitch ( primSystemLCID )\n\t{\n\t\tcase LANG_GERMAN:\n\t\t{\n\t\t\tlang = LANG_GERMAN;\n\t\t\tbreak;\n\t\t}\n\t\tcase LANG_FRENCH:\n\t\t{\n\t\t\tlang = LANG_FRENCH;\n\t\t\tbreak;\n\t\t}\n\t\tcase LANG_SPANISH:\n\t\t{\n\t\t\tlang = LANG_SPANISH;\n\t\t\tbreak;\n\t\t}\n\t\tcase LANG_ITALIAN:\n\t\t{\n\t\t\tlang = LANG_ITALIAN;\n\t\t\tbreak;\n\t\t}\n\t\tdefault:\n\t\t{\n\t\t\tlang = ( subSystemLCID == SUBLANG_ENGLISH_AUS ) ? -99 : LANG_ENGLISH;\n\t\t\tbreak;\n\t\t}\n\t}\n\t\n\tFrontEndMenuManager.OS_Language = primUserLCID;\n\n\tswitch ( lang )\n\t{\n\t\tcase LANG_GERMAN:\n\t\t{\n\t\t\tFrontEndMenuManager.m_PrefsLanguage = CMenuManager::LANGUAGE_GERMAN;\n\t\t\tbreak;\n\t\t}\n\t\tcase LANG_SPANISH:\n\t\t{\n\t\t\tFrontEndMenuManager.m_PrefsLanguage = CMenuManager::LANGUAGE_SPANISH;\n\t\t\tbreak;\n\t\t}\n\t\tcase LANG_FRENCH:\n\t\t{\n\t\t\tFrontEndMenuManager.m_PrefsLanguage = CMenuManager::LANGUAGE_FRENCH;\n\t\t\tbreak;\n\t\t}\n\t\tcase LANG_ITALIAN:\n\t\t{\n\t\t\tFrontEndMenuManager.m_PrefsLanguage = CMenuManager::LANGUAGE_ITALIAN;\n\t\t\tbreak;\n\t\t}\n\t\tdefault:\n\t\t{\n\t\t\tFrontEndMenuManager.m_PrefsLanguage = CMenuManager::LANGUAGE_AMERICAN;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tTheText.Unload();\n\tTheText.Load();\n}\n\n/*\n *****************************************************************************\n */\nvoid CenterVideo(void)\n{\n\tHRESULT hr = S_OK;\n\tRECT rect;\n\n\tASSERT(pVW != nil);\n\t\n\tGetClientRect(PSGLOBAL(window), &rect);\n\n\tJIF(pVW->SetWindowPosition(rect.left, rect.top, rect.right, rect.bottom));\n\n\tJIF(pVW->put_MessageDrain((OAHWND) PSGLOBAL(window)));\n\n\tSetFocus(PSGLOBAL(window));\n}\n\n/*\n *****************************************************************************\n */\nvoid PlayMovieInWindow(int cmdShow, const char* szFile)\n{\n\tWCHAR wFileName[256];\n\tHRESULT hr;\n\n\t// Clear open dialog remnants before calling RenderFile()\n\tUpdateWindow(PSGLOBAL(window));\n\n\t// Convert filename to wide character string\n\tMultiByteToWideChar(CP_ACP, 0, szFile, -1, wFileName, sizeof(wFileName) - 1);\n\n\t// Initialize COM\n#ifdef FIX_BUGS // will also return S_FALSE if it has already been inited in the same thread\n\tCoInitialize(nil);\n#else\n\tJIF(CoInitialize(nil));\n#endif\n\n\t// Get the interface for DirectShow's GraphBuilder\n\tJIF(CoCreateInstance(CLSID_FilterGraph, nil, CLSCTX_INPROC, \n\t\t\t\t\t\t IID_IGraphBuilder, (void **)&pGB));\n\n\tif(SUCCEEDED(hr))\n\t{\n\t\t// Have the graph builder construct its the appropriate graph automatically\n\t\tJIF(pGB->RenderFile(&wFileName[0], nil));\n\n\t\t// QueryInterface for DirectShow interfaces\n\t\tJIF(pGB->QueryInterface(IID_IMediaControl, (void **)&pMC));\n\t\tJIF(pGB->QueryInterface(IID_IMediaEventEx, (void **)&pME));\n\t\tJIF(pGB->QueryInterface(IID_IMediaSeeking, (void **)&pMS));\n\n\t\t// Query for video interfaces, which may not be relevant for audio files\n\t\tJIF(pGB->QueryInterface(IID_IVideoWindow, (void **)&pVW));\n\n\t\tJIF(pVW->put_Owner((OAHWND) PSGLOBAL(window)));\n\t\tJIF(pVW->put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN));\n\n\t\t// Have the graph signal event via window callbacks for performance\n\t\tJIF(pME->SetNotifyWindow((OAHWND)PSGLOBAL(window), WM_GRAPHNOTIFY, 0));\n\n\t\tCenterVideo();\n\n\t\t// Run the graph to play the media file\n\t\tJIF(pMC->Run());\n\n\t\tSetFocus(PSGLOBAL(window));\n\t}\n\t\n\tASSERT(pGB != nil);\n\tASSERT(pVW != nil);\n\tASSERT(pME != nil);\n\tASSERT(pMC != nil);\n\n\tif(FAILED(hr))\n\t\tCloseClip();\n}\n\n/*\n *****************************************************************************\n */\nvoid CloseInterfaces(void)\n{\n\t// Release and zero DirectShow interfaces\n\tSAFE_RELEASE(pME);\n\tSAFE_RELEASE(pMS);\n\tSAFE_RELEASE(pMC);\n\tSAFE_RELEASE(pVW);\n\tSAFE_RELEASE(pGB);\n}\n\n/*\n *****************************************************************************\n */\nvoid CloseClip(void)\n{\n\tHRESULT hr;\n\n\t// Stop playback\n\tif(pMC)\n\t\thr = pMC->Stop();\n\n\t// Free DirectShow interfaces\n\tCloseInterfaces();\n}\n\n/*\n *****************************************************************************\n */\nvoid HandleExit()\n{\n\tMSG message;\n\twhile ( PeekMessage(&message, nil, 0U, 0U, PM_REMOVE|PM_NOYIELD) )\n\t{\n\t\tif( message.message == WM_QUIT )\n\t\t{\n\t\t\tRsGlobal.quit = TRUE;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tTranslateMessage(&message);\n\t\t\tDispatchMessage(&message);\n\t\t}\n\t}\n}\n \n/*\n *****************************************************************************\n */\nint PASCAL\nWinMain(HINSTANCE instance, \n\t\tHINSTANCE prevInstance\t__RWUNUSED__, \n\t\tCMDSTR cmdLine, \n\t\tint cmdShow)\n{\n\tMSG message;\n\tRwV2d pos;\n\tRwInt32 argc, i;\n\tRwChar **argv;\n\tSystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, nil, SPIF_SENDCHANGE);\n\n#ifndef MASTER\n\tif (strstr(cmdLine, \"-console\"))\n\t{\n\t\tAllocConsole();\n\t\tfreopen(\"CONIN$\", \"r\", stdin);\n\t\tfreopen(\"CONOUT$\", \"w\", stdout);\n\t\tfreopen(\"CONOUT$\", \"w\", stderr);\n\t}\n#endif\n\n#ifdef USE_CUSTOM_ALLOCATOR\n\tInitMemoryMgr();\n#endif\n\n\t/* \n\t * Initialize the platform independent data.\n\t * This will in turn initialize the platform specific data...\n\t */\n\tif( RsEventHandler(rsINITIALIZE, nil) == rsEVENTERROR )\n\t{\n\t\treturn FALSE;\n\t}\n\n\t/*\n\t * Register the window class...\n\t */\n\tif( !InitApplication(instance) )\n\t{\n\t\treturn FALSE;\n\t}\n\n\t/*\n\t * Get proper command line params, cmdLine passed to us does not\n\t * work properly under all circumstances...\n\t */\n\tcmdLine = GetCommandLine();\n\n\t/*\n\t * Parse command line into standard (argv, argc) parameters...\n\t */\n\targv = CommandLineToArgv(cmdLine, &argc);\n\n\n\t/* \n\t * Parse command line parameters (except program name) one at \n\t * a time BEFORE RenderWare initialization...\n\t */\n\tfor(i=1; i<argc; i++)\n\t{\n\t\tRsEventHandler(rsPREINITCOMMANDLINE, argv[i]);\n\t}\n\n\t/*\n\t * Create the window...\n\t */\n\tPSGLOBAL(window) = InitInstance(instance);\n\tif( PSGLOBAL(window) == nil )\n\t{\n\t\treturn FALSE;\n\t}\n\n\tPSGLOBAL(instance) = instance;\n\t\n\tControlsManager.MakeControllerActionsBlank();\n\tControlsManager.InitDefaultControlConfiguration();\n\t\n\tif ( _InputInitialise() == S_OK )\n\t{\n\t\t_InputInitialiseMouse(false);\n\t\t_InputInitialiseJoys();\n\t}\n\t\n\tControlsManager.InitDefaultControlConfigMouse(MousePointerStateHelper.GetMouseSetUp());\n\n#ifndef IMPROVED_VIDEOMODE\n\tSetWindowLong(PSGLOBAL(window), GWL_STYLE, WS_POPUP);\n\tSetWindowPos(PSGLOBAL(window), nil, 0, 0, 0, 0,\n\t\t\t\tSWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|\n\t\t\t\tSWP_FRAMECHANGED);\n#endif\n\n\t/* \n\t * Initialize the 3D (RenderWare) components of the app...\n\t */\n\tif( rsEVENTERROR == RsEventHandler(rsRWINITIALIZE, PSGLOBAL(window)) )\n\t{\n\t\tDestroyWindow(PSGLOBAL(window));\n\n\t\tRsEventHandler(rsTERMINATE, nil);\n\n\t\treturn FALSE;\n\t}\n\n\t/* \n\t * Parse command line parameters (except program name) one at \n\t * a time AFTER RenderWare initialization...\n\t */\n\tfor(i=1; i<argc; i++)\n\t{\n\t\tRsEventHandler(rsCOMMANDLINE, argv[i]);\n\t}\n\n\t/* \n\t * Force a camera resize event...\n\t */\n\t{\n\t\tRwRect r;\n\n\t\tr.x = 0;\n\t\tr.y = 0;\n\t\tr.w = RsGlobal.maximumWidth;\n\t\tr.h = RsGlobal.maximumHeight;\n\n\t\tRsEventHandler(rsCAMERASIZE, &r);\n\t}\n\t\n\tSystemParametersInfo(SPI_SETSCREENSAVEACTIVE, FALSE, nil, SPIF_SENDCHANGE);\n\tSystemParametersInfo(SPI_SETPOWEROFFACTIVE, FALSE, nil, SPIF_SENDCHANGE);\n\tSystemParametersInfo(SPI_SETLOWPOWERACTIVE, FALSE, nil, SPIF_SENDCHANGE);\n\t\n\n\tSTICKYKEYS SavedStickyKeys;\n\tSavedStickyKeys.cbSize = sizeof(STICKYKEYS);\n\t\n\tSystemParametersInfo(SPI_GETSTICKYKEYS, sizeof(STICKYKEYS), &SavedStickyKeys, SPIF_SENDCHANGE);\n\t\n\tSTICKYKEYS NewStickyKeys;\n\tNewStickyKeys.cbSize = sizeof(STICKYKEYS);\n\tNewStickyKeys.dwFlags = SKF_TWOKEYSOFF;\n\t\n\tSystemParametersInfo(SPI_SETSTICKYKEYS, sizeof(STICKYKEYS), &NewStickyKeys, SPIF_SENDCHANGE);\n\t\n\n\t/*\n\t * Show the window, and refresh it...\n\t */\n\tShowWindow(PSGLOBAL(window), cmdShow);\n\tUpdateWindow(PSGLOBAL(window));\n\t\n\t{\n\t\tCFileMgr::SetDirMyDocuments();\n\t\t\n#ifdef LOAD_INI_SETTINGS\n\t\t// At this point InitDefaultControlConfigJoyPad must have set all bindings to default and ms_padButtonsInited to number of detected buttons.\n\t\t// We will load stored bindings below, but let's cache ms_padButtonsInited before LoadINIControllerSettings and LoadSettings clears it,\n\t\t// so we can add new joy bindings **on top of** stored bindings.\n\t\tint connectedPadButtons = ControlsManager.ms_padButtonsInited;\n#endif\n\n\t\tint32 gta3set = CFileMgr::OpenFile(\"gta_vc.set\", \"r\");\n\n\t\tif ( gta3set )\n\t\t{\n\t\t\tControlsManager.LoadSettings(gta3set);\n\t\t\tCFileMgr::CloseFile(gta3set);\n\t\t}\n\t\t\n\t\tCFileMgr::SetDir(\"\");\n\n#ifdef LOAD_INI_SETTINGS\n\t\tLoadINIControllerSettings();\n\t\tif (connectedPadButtons != 0) {\n\t\t\tControlsManager.InitDefaultControlConfigJoyPad(connectedPadButtons);\n\t\t\tSaveINIControllerSettings();\n\t\t}\n#endif\n\t}\n\t\n\tSetErrorMode(SEM_FAILCRITICALERRORS);\n\n\t\t\t\n#ifdef PS2_MENU\n\tint32 r = TheMemoryCard.CheckCardStateAtGameStartUp(CARD_ONE);\n\tif (   r == CMemoryCard::ERR_DIRNOENTRY  || r == CMemoryCard::ERR_NOFORMAT\n\t\t&& r != CMemoryCard::ERR_OPENNOENTRY && r != CMemoryCard::ERR_NONE )\n\t{\n\t\tLoadingScreen(nil, nil, \"loadsc0\");\n\t\t\n\t\tTheText.Unload();\n\t\tTheText.Load();\n\t\t\n\t\tCFont::Initialise();\n\t\t\n\t\tFrontEndMenuManager.DrawMemoryCardStartUpMenus();\n\t}\n#endif\n\n#ifndef MASTER\n\tif (gbModelViewer) {\n\t\t// This is TheModelViewer in LCS\n\t\tLoadingScreen(\"Loading the ModelViewer\", NULL, GetRandomSplashScreen());\n\t\tCAnimViewer::Initialise();\n\t\tCTimer::Update();\n#ifndef PS2_MENU\n\t\tFrontEndMenuManager.m_bGameNotLoaded = false;\n#endif\n\t}\n#endif\n\n\twhile ( TRUE )\n\t{\n\t\tRwInitialised = TRUE;\n\t\t\n\t\t/* \n\t\t* Set the initial mouse position...\n\t\t*/\n\t\tpos.x = RsGlobal.maximumWidth * 0.5f;\n\t\tpos.y = RsGlobal.maximumHeight * 0.5f;\n\n\t\tRsMouseSetPos(&pos);\n\t\t\n\t\tWINDOWPLACEMENT\t\twp;\n\t\twp.length = sizeof(WINDOWPLACEMENT);\n\n\t\t/*\n\t\t* Enter the message processing loop...\n\t\t*/\n#ifdef PS2_MENU\n\t\tif (TheMemoryCard.m_bWantToLoad)\n\t\t\tLoadSplash(GetLevelSplashScreen(CGame::currLevel));\n\t\t\n\t\tTheMemoryCard.m_bWantToLoad = false;\n\t\t\n\t\tCTimer::Update();\n\t\t\n\t\twhile( !RsGlobal.quit && !(FrontEndMenuManager.m_bWantToRestart || TheMemoryCard.b_FoundRecentSavedGameWantToLoad) )\n#else\n\t\twhile( !RsGlobal.quit && !FrontEndMenuManager.m_bWantToRestart )\n#endif\n\t\t{\n\t\t\tif( PeekMessage(&message, nil, 0U, 0U, PM_REMOVE|PM_NOYIELD) )\n\t\t\t{\n\t\t\t\tif( message.message == WM_QUIT )\n\t\t\t\t{\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tTranslateMessage(&message);\n\t\t\t\t\tDispatchMessage(&message);\n\t\t\t\t}\n\t\t\t}\n#ifndef MASTER\n\t\t\telse if (gbModelViewer) {\n\t\t\t\t// This is TheModelViewerCore in LCS\n\t\t\t\tTheModelViewer();\n\t\t\t}\n#endif\n\t\t\telse if( ForegroundApp )\n\t\t\t{\n\t\t\t\tswitch ( gGameState )\n\t\t\t\t{\n\t\t\t\t\tcase GS_START_UP:\n\t\t\t\t\t{\n#ifdef NO_MOVIES\n\t\t\t\t\t\tgGameState = gbNoMovies ? GS_INIT_ONCE : GS_INIT_LOGO_MPEG;\n#else\n\t\t\t\t\t\tgGameState = GS_INIT_LOGO_MPEG;\n#endif\n\t\t\t\t\t\tTRACE(\"gGameState = GS_INIT_LOGO_MPEG\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tcase GS_INIT_LOGO_MPEG:\n\t\t\t\t\t{\n\t\t\t\t\t\tif ( !startupDeactivate )\n\t\t\t\t\t\t\tPlayMovieInWindow(cmdShow, \"movies\\\\Logo.mpg\");\n\t\t\t\t\t\tgGameState = GS_LOGO_MPEG;\n\t\t\t\t\t\tTRACE(\"gGameState = GS_LOGO_MPEG;\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tcase GS_LOGO_MPEG:\n\t\t\t\t\t{\n\t\t\t\t\t\tCPad::UpdatePads();\n\n\t\t\t\t\t\tif ( startupDeactivate || ControlsManager.GetJoyButtonJustDown() != 0 )\n\t\t\t\t\t\t\t++gGameState;\n\t\t\t\t\t\telse if ( CPad::GetPad(0)->NewState.CheckForInput() )\n\t\t\t\t\t\t\t++gGameState;\n\t\t\t\t\t\telse if ( CPad::GetPad(0)->GetLeftMouseJustDown() )\n\t\t\t\t\t\t\t++gGameState;\n\t\t\t\t\t\telse if ( CPad::GetPad(0)->GetEnterJustDown() )\n\t\t\t\t\t\t\t++gGameState;\n\t\t\t\t\t\telse if ( CPad::GetPad(0)->GetCharJustDown(' ') )\n\t\t\t\t\t\t\t++gGameState;\n\t\t\t\t\t\telse if ( CPad::GetPad(0)->GetAltJustDown() )\n\t\t\t\t\t\t\t++gGameState;\n\t\t\t\t\t\telse if ( CPad::GetPad(0)->GetTabJustDown() )\n\t\t\t\t\t\t\t++gGameState;\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tcase GS_INIT_INTRO_MPEG:\n\t\t\t\t\t{\n#ifdef NO_MOVIES\n\t\t\t\t\t\tif (!gbNoMovies)\n#endif\n\t\t\t\t\t\tCloseClip();\n#ifndef FIX_BUGS\n\t\t\t\t\t\tCoUninitialize();\n#endif\n\t\t\t\t\t\t\n\t\t\t\t\t\tif ( FrontEndMenuManager.OS_Language == LANG_FRENCH || FrontEndMenuManager.OS_Language == LANG_GERMAN )\n\t\t\t\t\t\t\tPlayMovieInWindow(cmdShow, \"movies\\\\GTAtitlesGER.mpg\");\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tPlayMovieInWindow(cmdShow, \"movies\\\\GTAtitles.mpg\");\n\t\t\t\t\t\t\n\t\t\t\t\t\tgGameState = GS_INTRO_MPEG;\n\t\t\t\t\t\tTRACE(\"gGameState = GS_INTRO_MPEG;\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tcase GS_INTRO_MPEG:\n\t\t\t\t\t{\n\t\t\t\t\t\tCPad::UpdatePads();\n\n\t\t\t\t\t\tif ( startupDeactivate || ControlsManager.GetJoyButtonJustDown() != 0 )\n\t\t\t\t\t\t\t++gGameState;\n\t\t\t\t\t\telse if ( CPad::GetPad(0)->NewState.CheckForInput() )\n\t\t\t\t\t\t\t++gGameState;\n\t\t\t\t\t\telse if ( CPad::GetPad(0)->GetLeftMouseJustDown() )\n\t\t\t\t\t\t\t++gGameState;\n\t\t\t\t\t\telse if ( CPad::GetPad(0)->GetEnterJustDown() )\n\t\t\t\t\t\t\t++gGameState;\n\t\t\t\t\t\telse if ( CPad::GetPad(0)->GetCharJustDown(' ') )\n\t\t\t\t\t\t\t++gGameState;\n\t\t\t\t\t\telse if ( CPad::GetPad(0)->GetAltJustDown() )\n\t\t\t\t\t\t\t++gGameState;\n\t\t\t\t\t\telse if ( CPad::GetPad(0)->GetTabJustDown() )\n\t\t\t\t\t\t\t++gGameState;\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tcase GS_INIT_ONCE:\n\t\t\t\t\t{\n#ifdef NO_MOVIES\n\t\t\t\t\t\tif (!gbNoMovies)\n#endif\n\t\t\t\t\t\tCloseClip();\n#ifndef FIX_BUGS\n\t\t\t\t\t\tCoUninitialize();\n#endif\n\t\t\t\t\t\t\n#ifdef FIX_BUGS\n\t\t\t\t\t\t// draw one frame because otherwise we'll end up looking at black screen for a while if vsync is on\n\t\t\t\t\t\tRsCameraShowRaster(Scene.camera);\n#endif\n\n#ifdef PS2_MENU\n\t\t\t\t\t\textern char version_name[64];\n\t\t\t\t\t\tif ( CGame::frenchGame || CGame::germanGame )\n\t\t\t\t\t\t\tLoadingScreen(NULL, version_name, \"loadsc24\");\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tLoadingScreen(NULL, version_name, \"loadsc0\");\n\t\t\t\t\t\t\n\t\t\t\t\t\tprintf(\"Into TheGame!!!\\n\");\n#else\t\t\t\t\n\t\t\t\t\t\tLoadingScreen(nil, nil, \"loadsc0\");\n\t\t\t\t\t\t// LoadingScreen(nil, nil, \"loadsc0\"); // duplicate\n#endif\n\t\t\t\t\t\tif ( !CGame::InitialiseOnceAfterRW() )\n\t\t\t\t\t\t\tRsGlobal.quit = TRUE;\n\t\t\t\t\n#ifdef PS2_MENU\n\t\t\t\t\t\tgGameState = GS_INIT_PLAYING_GAME;\n#else\n\t\t\t\t\t\tgGameState = GS_INIT_FRONTEND;\n\t\t\t\t\t\tTRACE(\"gGameState = GS_INIT_FRONTEND;\");\n#endif\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\t\n#ifndef PS2_MENU\n\t\t\t\t\tcase GS_INIT_FRONTEND:\n\t\t\t\t\t{\n\t\t\t\t\t\tLoadingScreen(nil, nil, \"loadsc0\");\n\t\t\t\t\t\t// LoadingScreen(nil, nil, \"loadsc0\"); // duplicate\n\t\t\t\t\t\t\n\t\t\t\t\t\tFrontEndMenuManager.m_bGameNotLoaded = true;\n\t\t\t\t\t\t\n\t\t\t\t\t\tFrontEndMenuManager.m_bStartUpFrontEndRequested = true;\n\t\t\t\t\t\t\n\t\t\t\t\t\tif ( defaultFullscreenRes )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tdefaultFullscreenRes = FALSE;\n\t\t\t\t\t\t\tFrontEndMenuManager.m_nPrefsVideoMode = GcurSelVM;\n\t\t\t\t\t\t\tFrontEndMenuManager.m_nDisplayVideoMode = GcurSelVM;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\tgGameState = GS_FRONTEND;\n\t\t\t\t\t\tTRACE(\"gGameState = GS_FRONTEND;\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tcase GS_FRONTEND:\n\t\t\t\t\t{\n\t\t\t\t\t\tGetWindowPlacement(PSGLOBAL(window), &wp);\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (wp.showCmd != SW_SHOWMINIMIZED)\n\t\t\t\t\t\t\tRsEventHandler(rsFRONTENDIDLE, nil);\n\n#ifdef PS2_MENU\n\t\t\t\t\t\tif ( !FrontEndMenuManager.m_bMenuActive || TheMemoryCard.m_bWantToLoad )\n#else\n\t\t\t\t\t\tif ( !FrontEndMenuManager.m_bMenuActive || FrontEndMenuManager.m_bWantToLoad )\n#endif\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tgGameState = GS_INIT_PLAYING_GAME;\n\t\t\t\t\t\t\tTRACE(\"gGameState = GS_INIT_PLAYING_GAME;\");\n\t\t\t\t\t\t}\n\n#ifdef PS2_MENU\n\t\t\t\t\t\tif (TheMemoryCard.m_bWantToLoad )\n#else\n\t\t\t\t\t\tif ( FrontEndMenuManager.m_bWantToLoad )\n#endif\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tInitialiseGame();\n\t\t\t\t\t\t\tFrontEndMenuManager.m_bGameNotLoaded = false;\n\t\t\t\t\t\t\tgGameState = GS_PLAYING_GAME;\n\t\t\t\t\t\t\tTRACE(\"gGameState = GS_PLAYING_GAME;\");\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n#endif\n\t\t\t\t\t\n\t\t\t\t\tcase GS_INIT_PLAYING_GAME:\n\t\t\t\t\t{\n#ifdef PS2_MENU\n\t\t\t\t\t\tCGame::Initialise(\"DATA\\\\GTA3.DAT\");\n\t\t\t\t\t\t\n\t\t\t\t\t\t//LoadingScreen(\"Starting Game\", NULL, GetRandomSplashScreen());\n\t\t\t\t\t\n\t\t\t\t\t\tif (   TheMemoryCard.CheckCardInserted(CARD_ONE) == CMemoryCard::NO_ERR_SUCCESS\n\t\t\t\t\t\t\t&& TheMemoryCard.ChangeDirectory(CARD_ONE, TheMemoryCard.Cards[CARD_ONE].dir)\n\t\t\t\t\t\t\t&& TheMemoryCard.FindMostRecentFileName(CARD_ONE, TheMemoryCard.MostRecentFile) == true\n\t\t\t\t\t\t\t&& TheMemoryCard.CheckDataNotCorrupt(TheMemoryCard.MostRecentFile))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tstrcpy(TheMemoryCard.LoadFileName, TheMemoryCard.MostRecentFile);\n\t\t\t\t\t\t\tTheMemoryCard.b_FoundRecentSavedGameWantToLoad = true;\n\t\t\t\t\t\n\t\t\t\t\t\t\tif (CMenuManager::m_PrefsLanguage != TheMemoryCard.GetLanguageToLoad())\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tCMenuManager::m_PrefsLanguage = TheMemoryCard.GetLanguageToLoad();\n\t\t\t\t\t\t\t\tTheText.Unload();\n\t\t\t\t\t\t\t\tTheText.Load();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\t\t\tCGame::currLevel = (eLevelName)TheMemoryCard.GetLevelToLoad();\n\t\t\t\t\t\t}\n#else\n\t\t\t\t\t\tInitialiseGame();\n\n\t\t\t\t\t\tFrontEndMenuManager.m_bGameNotLoaded = false;\n#endif\n\t\t\t\t\t\tgGameState = GS_PLAYING_GAME;\n\t\t\t\t\t\tTRACE(\"gGameState = GS_PLAYING_GAME;\");\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tcase GS_PLAYING_GAME:\n\t\t\t\t\t{\n\t\t\t\t\t\tfloat ms = (float)CTimer::GetCurrentTimeInCycles() / (float)CTimer::GetCyclesPerMillisecond();\n\t\t\t\t\t\tif ( RwInitialised )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (!FrontEndMenuManager.m_PrefsFrameLimiter || (1000.0f / (float)RsGlobal.maxFPS) < ms)\n\t\t\t\t\t\t\t\tRsEventHandler(rsIDLE, (void *)TRUE);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif ( RwCameraBeginUpdate(Scene.camera) )\n\t\t\t\t{\n\t\t\t\t\tRwCameraEndUpdate(Scene.camera);\n\t\t\t\t\tForegroundApp = TRUE;\n\t\t\t\t\tRsEventHandler(rsACTIVATE, (void *)TRUE);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tWaitMessage();\n\t\t\t}\n\t\t}\n\n\t\t\n\t\t/* \n\t\t* About to shut down - block resize events again...\n\t\t*/\n\t\tRwInitialised = FALSE;\n\t\t\n\t\tFrontEndMenuManager.UnloadTextures();\n#ifdef PS2_MENU\t\n\t\tif ( !(FrontEndMenuManager.m_bWantToRestart || TheMemoryCard.b_FoundRecentSavedGameWantToLoad))\n\t\t\tbreak;\n#else\n\t\tif ( !FrontEndMenuManager.m_bWantToRestart )\n\t\t\tbreak;\n#endif\n\t\t\n\t\tCPad::ResetCheats();\n\t\tCPad::StopPadsShaking();\n\t\t\n\t\tDMAudio.ChangeMusicMode(MUSICMODE_DISABLE);\n\t\t\n#ifdef PS2_MENU\n\t\tCGame::ShutDownForRestart();\n#endif\n\t\tCTimer::Stop();\n\t\t\n#ifdef PS2_MENU\n\t\tif (FrontEndMenuManager.m_bWantToRestart || TheMemoryCard.b_FoundRecentSavedGameWantToLoad)\n\t\t{\n\t\t\tif (TheMemoryCard.b_FoundRecentSavedGameWantToLoad)\n\t\t\t{\n\t\t\t\tFrontEndMenuManager.m_bWantToRestart = true;\n\t\t\t\tTheMemoryCard.m_bWantToLoad = true;\n\t\t\t}\n\n\t\t\tCGame::InitialiseWhenRestarting();\n\t\t\tDMAudio.ChangeMusicMode(MUSICMODE_GAME);\n\t\t\tFrontEndMenuManager.m_bWantToRestart = false;\n\t\t\t\n\t\t\tcontinue;\n\t\t}\n\t\t\n\t\tCGame::ShutDown();\t\n\t\tCTimer::Stop();\n\t\t\n\t\tbreak;\n#else\n\t\tif ( FrontEndMenuManager.m_bWantToLoad )\n\t\t{\n\t\t\tCGame::ShutDownForRestart();\n\t\t\tCGame::InitialiseWhenRestarting();\n\t\t\tDMAudio.ChangeMusicMode(MUSICMODE_GAME);\n\t\t\tLoadSplash(GetLevelSplashScreen(CGame::currLevel));\n\t\t\tFrontEndMenuManager.m_bWantToLoad = false;\n\t\t}\n\t\telse\n\t\t{\n#ifndef MASTER\n\t\t\tif ( gbModelViewer )\n\t\t\t\tCAnimViewer::Shutdown();\n\t\t\telse\n#endif\n\t\t\tif ( gGameState == GS_PLAYING_GAME )\n\t\t\t\tCGame::ShutDown();\n\n\t\t\tCTimer::Stop();\n\t\t\t\n\t\t\tif ( FrontEndMenuManager.m_bFirstTime == true )\n\t\t\t{\n\t\t\t\tgGameState = GS_INIT_FRONTEND;\n\t\t\t\tTRACE(\"gGameState = GS_INIT_FRONTEND;\");\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tgGameState = GS_INIT_PLAYING_GAME;\n\t\t\t\tTRACE(\"gGameState = GS_INIT_PLAYING_GAME;\");\n\t\t\t}\n\t\t}\n\t\t\n\t\tFrontEndMenuManager.m_bFirstTime = false;\n\t\tFrontEndMenuManager.m_bWantToRestart = false;\n#endif\n\t}\n\t\n\n#ifndef MASTER\n\tif ( gbModelViewer )\n\t\tCAnimViewer::Shutdown();\n\telse\n#endif\n\tif ( gGameState == GS_PLAYING_GAME )\n\t\tCGame::ShutDown();\n\n\tDMAudio.Terminate();\n\t\n\t_psFreeVideoModeList();\n\n\n\t/*\n\t * Tidy up the 3D (RenderWare) components of the application...\n\t */\n\tRsEventHandler(rsRWTERMINATE, nil);\n\n\t/*\n\t * Kill the window...\n\t */\n\tDestroyWindow(PSGLOBAL(window));\n\n\t/*\n\t * Free the platform dependent data...\n\t */\n\tRsEventHandler(rsTERMINATE, nil);\n\n\t/* \n\t * Free the argv strings...\n\t */\n\tfree(argv);\n\t\n\tShowCursor(TRUE);\n\t\n\tSystemParametersInfo(SPI_SETSTICKYKEYS, sizeof(STICKYKEYS), &SavedStickyKeys, SPIF_SENDCHANGE);\n\tSystemParametersInfo(SPI_SETPOWEROFFACTIVE, TRUE, nil, SPIF_SENDCHANGE);\n\tSystemParametersInfo(SPI_SETLOWPOWERACTIVE, TRUE, nil, SPIF_SENDCHANGE);\n\tSystemParametersInfo(SPI_SETSCREENSAVEACTIVE, TRUE, nil, SPIF_SENDCHANGE);\n\n\tSetErrorMode(0);\n\n\treturn message.wParam;\n}\n\n/*\n *****************************************************************************\n */\n\n#define DEVICE_AXIS_MIN -2000\n#define DEVICE_AXIS_MAX 2000\n\n\nHRESULT _InputInitialise()\n{\n\tHRESULT hr;\n\n\t// Create a DInput object\n\tif( FAILED( hr = DirectInput8Create( GetModuleHandle(nil), DIRECTINPUT_VERSION, \n\t\t\t\t\t\t\t\t\t\tIID_IDirectInput8, (VOID**)&PSGLOBAL(dinterface), nil ) ) )\n\t\treturn hr;\n\t\t\n\treturn S_OK;\n}\n\nHRESULT _InputInitialiseMouse(bool exclusive)\n{\n\tHRESULT hr;\n\n\t// Obtain an interface to the system mouse device.\n\tif( FAILED( hr = PSGLOBAL(dinterface)->CreateDevice( GUID_SysMouse, &PSGLOBAL(mouse), nil ) ) )\n\t\treturn hr;\n\t\n\t// Set the data format to \"mouse format\" - a predefined data format \n\t//\n\t// A data format specifies which controls on a device we\n\t// are interested in, and how they should be reported.\n\t//\n\t// This tells DirectInput that we will be passing a\n\t// DIMOUSESTATE2 structure to IDirectInputDevice::GetDeviceState.\n\tif( FAILED( hr = PSGLOBAL(mouse)->SetDataFormat( &c_dfDIMouse2 ) ) )\n\t\treturn hr;\n\t\n\tif( FAILED( hr = PSGLOBAL(mouse)->SetCooperativeLevel( PSGLOBAL(window), (exclusive ? DISCL_EXCLUSIVE : DISCL_NONEXCLUSIVE) | DISCL_FOREGROUND ) ) )\n\t\treturn hr;\n\t\n\t// Acquire the newly created device\n\tPSGLOBAL(mouse)->Acquire();\n\t\n\treturn S_OK;\n}\n\nRwV2d leftStickPos;\nRwV2d rightStickPos;\n\nHRESULT CapturePad(RwInt32 padID)\n{\n\tHRESULT\t\thr;\n\tDIJOYSTATE2 js; \n\tLPDIRECTINPUTDEVICE8 *pPad = nil;\n\n\tif( padID == 0 )\n\t\tpPad = &PSGLOBAL(joy1);\n\telse if( padID == 1)\n\t\tpPad = &PSGLOBAL(joy2);\n\telse\n\t\tassert(\"invalid padID\");\n\t\n\tif ( nil == (*pPad) )\n\t\treturn S_OK;\n\t\n\t// Poll the device to read the current state\n\thr = (*pPad)->Poll();\n\t\n\tif( FAILED(hr) )\n\t{\n\t\t// DInput is telling us that the input stream has been\n\t\t// interrupted. We aren't tracking any state between polls, so\n\t\t// we don't have any special reset that needs to be done. We\n\t\t// just re-acquire and try again.\n\t\thr = (*pPad)->Acquire();\n\t\twhile( hr == DIERR_INPUTLOST ) \n\t\t\thr = (*pPad)->Acquire();\n\n\t\t// hr may be DIERR_OTHERAPPHASPRIO or other errors.\t This\n\t\t// may occur when the app is minimized or in the process of \n\t\t// switching, so just try again later \n\t\t\n\t\tif( FAILED(hr) )\n\t\t\treturn hr; \n\t\t\n\t\thr = (*pPad)->Poll();\n\t\tif( FAILED(hr) )\n\t\t\treturn hr; \n\t}\n\t\n\t// Get the input's device state\n\tif( FAILED( hr = (*pPad)->GetDeviceState( sizeof(DIJOYSTATE2), &js ) ) )\n\t\treturn hr; // The device should have been acquired during the Poll()\n\t\n\tif ( ControlsManager.m_bFirstCapture == true )\n\t{\n\t\tmemcpy(&ControlsManager.m_OldState, &js, sizeof(DIJOYSTATE2));\n\t\tmemcpy(&ControlsManager.m_NewState, &js, sizeof(DIJOYSTATE2));\n\t\t\n\t\tControlsManager.m_bFirstCapture = false;\n\t}\n\telse\n\t{\n\t\tmemcpy(&ControlsManager.m_OldState, &ControlsManager.m_NewState, sizeof(DIJOYSTATE2));\n\t\tmemcpy(&ControlsManager.m_NewState, &js, sizeof(DIJOYSTATE2));\n\t}\n\n\tRsPadButtonStatus bs;\n\tbs.padID = padID;\n\n\tRsPadEventHandler(rsPADBUTTONUP, (void *)&bs);\n\t\n\tbool deviceAvailable = (*pPad) != nil;\n\t\n\tif ( deviceAvailable )\n\t{\n\t\tleftStickPos.x = (float)js.lX / (float)((DEVICE_AXIS_MAX - DEVICE_AXIS_MIN) / 2);\n\t\tleftStickPos.y = (float)js.lY / (float)((DEVICE_AXIS_MAX - DEVICE_AXIS_MIN) / 2);\n\t\t\n\t\tif (LOWORD(js.rgdwPOV[0]) != 0xFFFF)\n\t\t{\n\t\t\tfloat angle = DEGTORAD((float)js.rgdwPOV[0] / 100.0f);\n\n\t\t\tleftStickPos.x = Sin(angle);\n\t\t\tleftStickPos.y = -Cos(angle);\n\t\t}\n\t\t\n\t\tif ( AllValidWinJoys.m_aJoys[bs.padID].m_bHasAxisR && AllValidWinJoys.m_aJoys[bs.padID].m_bHasAxisZ )\n\t\t{\n\t\t\trightStickPos.x = (float)js.lZ\t/ (float)((DEVICE_AXIS_MAX - DEVICE_AXIS_MIN) / 2);\n\t\t\trightStickPos.y = (float)js.lRz / (float)((DEVICE_AXIS_MAX - DEVICE_AXIS_MIN) / 2);\n\t\t}\n\t}\n\t\n\t{\n\t\tif (CPad::m_bMapPadOneToPadTwo)\n\t\t\tbs.padID = 1;\n\t\t\n\t\tRsPadEventHandler(rsPADBUTTONUP,   (void *)&bs);\n\t\tRsPadEventHandler(rsPADBUTTONDOWN, (void *)&bs);\n\t}\n\t\n\t{\n\t\tif (CPad::m_bMapPadOneToPadTwo)\n\t\t\tbs.padID = 1;\n\t\t\n\t\tCPad *pad = CPad::GetPad(bs.padID);\n\n\t\tif ( Abs(leftStickPos.x)  > 0.3f )\n\t\t\tpad->PCTempJoyState.LeftStickX\t= (int32)(leftStickPos.x  * 128.0f);\n\t\t\n\t\tif ( Abs(leftStickPos.y)  > 0.3f )\n\t\t\tpad->PCTempJoyState.LeftStickY\t= (int32)(leftStickPos.y  * 128.0f);\n\t\t\n\t\tif ( Abs(rightStickPos.x) > 0.3f )\n\t\t\tpad->PCTempJoyState.RightStickX = (int32)(rightStickPos.x * 128.0f);\n\n\t\tif ( Abs(rightStickPos.y) > 0.3f )\n\t\t\tpad->PCTempJoyState.RightStickY = (int32)(rightStickPos.y * 128.0f);\n\t}\n\t\n\treturn S_OK;\n}\n\nvoid _InputInitialiseJoys()\n{\n\tDIPROPDWORD prop;\n\tDIDEVCAPS devCaps;\n\n\tfor ( int32 i = 0; i < _TODOCONST(2); i++ )\n\t\tAllValidWinJoys.ClearJoyInfo(i);\n\t\n\t_InputAddJoys();\n\t\n\tif ( PSGLOBAL(joy1) != nil )\n\t{\n\t\tdevCaps.dwSize = sizeof(DIDEVCAPS);\n\t\tPSGLOBAL(joy1)->GetCapabilities(&devCaps);\n\n\t\tprop.diph.dwSize = sizeof(DIPROPDWORD);\n\t\tprop.diph.dwHeaderSize = sizeof(DIPROPHEADER);\n\t\tprop.diph.dwObj = 0;\n\t\tprop.diph.dwHow = 0;\n\t\t\n\t\tPSGLOBAL(joy1)->GetProperty(DIPROP_VIDPID, (LPDIPROPHEADER)&prop);\n\t\tAllValidWinJoys.m_aJoys[0].m_nVendorID = LOWORD(prop.dwData);\n\t\tAllValidWinJoys.m_aJoys[0].m_nProductID = HIWORD(prop.dwData);\n\t\tAllValidWinJoys.m_aJoys[0].m_bInitialised = true;\n\t\t\n\t\tControlsManager.InitDefaultControlConfigJoyPad(devCaps.dwButtons);\n\t}\n\t\t\n\tif ( PSGLOBAL(joy2) != nil )\n\t{\n\t\tPSGLOBAL(joy2)->GetProperty(DIPROP_VIDPID, (LPDIPROPHEADER)&prop);\n\t\tAllValidWinJoys.m_aJoys[1].m_nVendorID = LOWORD(prop.dwData);\n\t\tAllValidWinJoys.m_aJoys[1].m_nProductID = HIWORD(prop.dwData);\n\t\tAllValidWinJoys.m_aJoys[1].m_bInitialised = true;\n\t}\n}\n\nvoid _InputAddJoyStick(LPDIRECTINPUTDEVICE8 lpDevice, INT num)\n{\n\tDIDEVICEOBJECTINSTANCE objInst;\n\n\tobjInst.dwSize = sizeof( DIDEVICEOBJECTINSTANCE );\n\n\tDIPROPRANGE range;\n\trange.diph.dwSize = sizeof(DIPROPRANGE);\n\trange.diph.dwHeaderSize = sizeof(DIPROPHEADER);\n\trange.lMin = DEVICE_AXIS_MIN;\n\trange.lMax = DEVICE_AXIS_MAX;\n\trange.diph.dwHow = DIPH_BYOFFSET;\n\n\t// get the info about the object from the device\n\n\trange.diph.dwObj = DIJOFS_X;\n\tif ( lpDevice != nil )\n\t{\n\t\tif ( SUCCEEDED( lpDevice->GetObjectInfo( &objInst,\tDIJOFS_X, DIPH_BYOFFSET ) ) )\n\t\t{\n\t\t\tif( FAILED( lpDevice->SetProperty( DIPROP_RANGE, (LPCDIPROPHEADER)&range ) ) ) \n\t\t\t\treturn;\n\t\t\telse\n\t\t\t\t;\n\t\t}\n\t}\n\t\n\trange.diph.dwObj = DIJOFS_Y;\n\tif ( lpDevice != nil )\n\t{\n\t\tif ( SUCCEEDED( lpDevice->GetObjectInfo( &objInst,\tDIJOFS_Y, DIPH_BYOFFSET ) ) )\n\t\t{\n\t\t\tif( FAILED( lpDevice->SetProperty( DIPROP_RANGE, (LPCDIPROPHEADER)&range ) ) ) \n\t\t\t\treturn;\n\t\t\telse\n\t\t\t\t;\n\t\t}\n\t}\n\t\n\trange.diph.dwObj = DIJOFS_Z;\n\tif ( lpDevice != nil )\n\t{\n\t\tif ( SUCCEEDED( lpDevice->GetObjectInfo( &objInst,\tDIJOFS_Z, DIPH_BYOFFSET ) ) )\n\t\t{\n\t\t\tif( FAILED( lpDevice->SetProperty( DIPROP_RANGE, (LPCDIPROPHEADER)&range ) ) ) \n\t\t\t\treturn;\n\t\t\telse\n\t\t\t\tAllValidWinJoys.m_aJoys[num].m_bHasAxisZ = true; // z rightStickPos.x\n\t\t}\n\t}\n\t\n\trange.diph.dwObj = DIJOFS_RZ;\n\tif ( lpDevice != nil )\n\t{\n\t\tif ( SUCCEEDED( lpDevice->GetObjectInfo( &objInst,\tDIJOFS_RZ, DIPH_BYOFFSET ) ) )\n\t\t{\n\t\t\tif( FAILED( lpDevice->SetProperty( DIPROP_RANGE, (LPCDIPROPHEADER)&range ) ) ) \n\t\t\t\treturn;\n\t\t\telse\n\t\t\t\tAllValidWinJoys.m_aJoys[num].m_bHasAxisR = true; // r rightStickPos.y\n\t\t}\n\t}\n}\n\nHRESULT _InputAddJoys()\n{\n\tHRESULT hr;\n\t\n\thr = PSGLOBAL(dinterface)->EnumDevices(DI8DEVCLASS_GAMECTRL,  _InputEnumDevicesCallback, nil, DIEDFL_ATTACHEDONLY );\n\t \n\tif( FAILED(hr) )\n\t\treturn hr;\n\t\n\tif ( PSGLOBAL(joy1) == nil )\n\t\treturn S_FALSE;\n\t\n\t_InputAddJoyStick(PSGLOBAL(joy1), 0);\n\t\n\tif ( PSGLOBAL(joy2) == nil )\n\t\treturn S_OK;\t// we have one device already so return OK and ignore second\n\t\n\t_InputAddJoyStick(PSGLOBAL(joy2), 1);\n\t\n\treturn S_OK;\n}\n\nHRESULT _InputGetMouseState(DIMOUSESTATE2 *state)\n{\n\tHRESULT\t\t  hr;\n\t\n\tif ( PSGLOBAL(mouse) == nil )\n\t\treturn S_FALSE;\n\t\n\t// Get the input's device state, and put the state in dims\n\tZeroMemory( state, sizeof(DIMOUSESTATE2) );\n\t\n\thr = PSGLOBAL(mouse)->GetDeviceState( sizeof(DIMOUSESTATE2), state );\n\n\tif( FAILED(hr) ) \n\t{\n\t\t // DirectInput may be telling us that the input stream has been\n\t\t// interrupted.\t We aren't tracking any state between polls, so\n\t\t// we don't have any special reset that needs to be done.\n\t\t// We just re-acquire and try again.\n\t\t\n\t\t// If input is lost then acquire and keep trying \n\t\thr = PSGLOBAL(mouse)->Acquire();\n\t\twhile( hr == DIERR_INPUTLOST ) \n\t\t\thr = PSGLOBAL(mouse)->Acquire();\n\t\t\n\t\tZeroMemory( state, sizeof(DIMOUSESTATE2) );\n\t\thr = PSGLOBAL(mouse)->GetDeviceState( sizeof(DIMOUSESTATE2), state );\n\t\t\n\t\treturn hr;\n\t}\n\t\n\treturn S_OK;\n}\n\nvoid _InputShutdown()\n{\n\tSAFE_RELEASE(PSGLOBAL(dinterface));\n}\n\nvoid _InputShutdownMouse()\n{\n\tif (PSGLOBAL(mouse) == nil)\n\t\treturn;\n\n\tPSGLOBAL(mouse)->Unacquire();\n\tSAFE_RELEASE(PSGLOBAL(mouse));\n}\n\nbool _InputMouseNeedsExclusive(void)\n{\n\t// FIX: I don't know why R* needed that, but it causes infamous mouse bug on modern systems.\n\t//\t\tProbably DirectInput bug, since Acquire() and GetDeviceState() reports everything A-OK.\n#ifdef FIX_BUGS\n\treturn false;\n#endif\n\tRwVideoMode vm;\n\tRwEngineGetVideoModeInfo(&vm, GcurSelVM);\n\n\treturn vm.flags & rwVIDEOMODEEXCLUSIVE;\n}\n\nBOOL CALLBACK _InputEnumDevicesCallback( const DIDEVICEINSTANCE* pdidInstance, VOID* pContext )\n{\n\tHRESULT hr;\n\t \n\tstatic INT Count = 0;\n\t\n\tLPDIRECTINPUTDEVICE8 *pJoystick = nil;\n\t\n\tif ( Count == 0 )\n\t\tpJoystick = &PSGLOBAL(joy1);\n\telse if ( Count == 1 )\n\t\tpJoystick = &PSGLOBAL(joy2);\n\telse\n\t\tassert(\"too many pads\");\n\t\n\t// Obtain an interface to the enumerated joystick. \n\thr = PSGLOBAL(dinterface)->CreateDevice( pdidInstance->guidInstance, pJoystick, nil );\n\t\n\t// If it failed, then we can't use this joystick. (Maybe the user unplugged\n\t// it while we were in the middle of enumerating it.)\n\tif( hr != S_OK )\n\t\treturn DIENUM_CONTINUE;\n\n\thr = (*pJoystick)->SetDataFormat( &c_dfDIJoystick2 );\n\tif( hr != S_OK )\n\t{\n\t\t(*pJoystick)->Release();\n\t\treturn DIENUM_CONTINUE;\n\t}\n\t\n\t++Count;\n\n\thr = (*pJoystick)->SetCooperativeLevel( PSGLOBAL(window), DISCL_NONEXCLUSIVE|DISCL_FOREGROUND );\n\tif( hr != S_OK )\n\t{\n\t\t(*pJoystick)->Release();\n#ifdef FIX_BUGS\n\t\t// BUG: enum will be called with Count == 2, which will write to a null pointer\n\t\t// So decrement count again since we're not using this pad\n\t\t--Count;\n#endif\n\t\treturn DIENUM_CONTINUE;\n\t}\n\t\n\t// Stop enumeration. Note: we're just taking the first two joysticks we get. You\n\t// could store all the enumerated joysticks and let the user pick.\n\tif ( Count == 2 )\n\t\treturn DIENUM_STOP;\n\t\n\treturn DIENUM_CONTINUE;\n}\n\nBOOL _InputTranslateKey(RsKeyCodes *rs, UINT flag, UINT key)\n{\n\t*rs = rsNULL;\n\t\n\tswitch ( key )\n\t{\n\t\tcase VK_SHIFT:\n\t\t{\n\t\t\tif ( _dwOperatingSystemVersion == OS_WIN98 )\n\t\t\t\t*rs = rsSHIFT;\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\tcase VK_RETURN:\n\t\t{\n\t\t\tif ( _InputIsExtended(flag) )\n\t\t\t\t*rs = rsPADENTER;\n\t\t\telse\n\t\t\t\t*rs = rsENTER;\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\tcase VK_CONTROL:\n\t\t{\n\t\t\tif ( _InputIsExtended(flag) )\n\t\t\t\t*rs = rsRCTRL;\n\t\t\telse\n\t\t\t\t*rs = rsLCTRL;\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\tcase VK_MENU:\n\t\t{\n\t\t\tif ( _InputIsExtended(flag) )\n\t\t\t\t*rs = rsRALT;\n\t\t\telse\n\t\t\t\t*rs = rsLALT;\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\tcase VK_APPS:\n\t\t{\n\t\t\t*rs = rsAPPS;\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\tcase VK_PAUSE:\n\t\t{\n\t\t\t*rs = rsPAUSE;\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\tcase VK_CAPITAL:\n\t\t{\n\t\t\t*rs = rsCAPSLK;\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\tcase VK_ESCAPE:\n\t\t{\n\t\t\t*rs = rsESC;\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\tcase VK_PRIOR:\n\t\t{\n\t\t\tif ( _InputIsExtended(flag) )\n\t\t\t\t*rs = rsPGUP;\n\t\t\telse\n\t\t\t\t*rs = rsPADPGUP;\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\tcase VK_NEXT:\n\t\t{\n\t\t\tif ( _InputIsExtended(flag) )\n\t\t\t\t*rs = rsPGDN;\n\t\t\telse\n\t\t\t\t*rs = rsPADPGDN;\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\tcase VK_END:\n\t\t{\n\t\t\tif ( _InputIsExtended(flag) )\n\t\t\t\t*rs = rsEND;\n\t\t\telse\n\t\t\t\t*rs = rsPADEND;\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\tcase VK_HOME:\n\t\t{\n\t\t\tif ( _InputIsExtended(flag) )\n\t\t\t\t*rs = rsHOME;\n\t\t\telse\n\t\t\t\t*rs = rsPADHOME;\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\tcase VK_LEFT:\n\t\t{\n\t\t\tif ( _InputIsExtended(flag) )\n\t\t\t\t*rs = rsLEFT;\n\t\t\telse\n\t\t\t\t*rs = rsPADLEFT;\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\tcase VK_UP:\n\t\t{\n\t\t\tif ( _InputIsExtended(flag) )\n\t\t\t\t*rs = rsUP;\n\t\t\telse\n\t\t\t\t*rs = rsPADUP;\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\tcase VK_RIGHT:\n\t\t{\n\t\t\tif ( _InputIsExtended(flag) )\n\t\t\t\t*rs = rsRIGHT;\n\t\t\telse\n\t\t\t\t*rs = rsPADRIGHT;\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\tcase VK_DOWN:\n\t\t{\n\t\t\tif ( _InputIsExtended(flag) )\n\t\t\t\t*rs = rsDOWN;\n\t\t\telse\n\t\t\t\t*rs = rsPADDOWN;\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\tcase VK_INSERT:\n\t\t{\n\t\t\tif ( _InputIsExtended(flag) )\n\t\t\t\t*rs = rsINS;\n\t\t\telse\n\t\t\t\t*rs = rsPADINS;\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\tcase VK_DELETE:\n\t\t{\n\t\t\tif ( _InputIsExtended(flag) )\n\t\t\t\t*rs = rsDEL;\n\t\t\telse\n\t\t\t\t*rs = rsPADDEL;\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\tcase VK_LWIN:\n\t\t{\n\t\t\t*rs = rsLWIN;\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\tcase VK_RWIN:\n\t\t{\n\t\t\t*rs = rsRWIN;\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\tcase VK_NUMPAD0:\n\t\t{\n\t\t\t*rs = rsPADINS;\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\tcase VK_NUMPAD1:\n\t\t{\n\t\t\t*rs = rsPADEND;\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\tcase VK_NUMPAD2:\n\t\t{\n\t\t\t*rs = rsPADDOWN;\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\tcase VK_NUMPAD3:\n\t\t{\n\t\t\t*rs = rsPADPGDN;\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\tcase VK_NUMPAD4:\n\t\t{\n\t\t\t*rs = rsPADLEFT;\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\tcase VK_NUMPAD5:\n\t\t{\n\t\t\t*rs = rsPAD5;\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\tcase VK_NUMPAD6:\n\t\t{\n\t\t\t*rs = rsPADRIGHT;\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\tcase VK_NUMPAD7:\n\t\t{\n\t\t\t*rs = rsPADHOME;\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\tcase VK_NUMPAD8:\n\t\t{\n\t\t\t*rs = rsPADUP;\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\tcase VK_NUMPAD9:\n\t\t{\n\t\t\t*rs = rsPADPGUP;\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\tcase VK_MULTIPLY:\n\t\t{\n\t\t\t*rs = rsTIMES;\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\tcase VK_DIVIDE:\n\t\t{\n\t\t\t*rs = rsDIVIDE;\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\tcase VK_ADD:\n\t\t{\n\t\t\t*rs = rsPLUS;\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\tcase VK_SUBTRACT:\n\t\t{\n\t\t\t*rs = rsMINUS;\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\tcase VK_DECIMAL:\n\t\t{\n\t\t\t*rs = rsPADDEL;\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\tcase VK_F1:\n\t\t{\n\t\t\t*rs = rsF1;\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\tcase VK_F2:\n\t\t{\n\t\t\t*rs = rsF2;\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\tcase VK_F3:\n\t\t{\n\t\t\t*rs = rsF3;\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\tcase VK_F4:\n\t\t{\n\t\t\t*rs = rsF4;\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\tcase VK_F5:\n\t\t{\n\t\t\t*rs = rsF5;\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\tcase VK_F6:\n\t\t{\n\t\t\t*rs = rsF6;\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\tcase VK_F7:\n\t\t{\n\t\t\t*rs = rsF7;\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\tcase VK_F8:\n\t\t{\n\t\t\t*rs = rsF8;\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\tcase VK_F9:\t\n\t\t{\n\t\t\t*rs = rsF9;\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\tcase VK_F10:\n\t\t{\n\t\t\t*rs = rsF10;\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\tcase VK_F11:\n\t\t{\n\t\t\t*rs = rsF11;\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\tcase VK_F12:\n\t\t{\n\t\t\t*rs = rsF12;\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\tcase VK_NUMLOCK:\n\t\t{\n\t\t\t*rs = rsNUMLOCK;\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\tcase VK_SCROLL:\n\t\t{\n\t\t\t*rs = rsSCROLL;\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\tcase VK_BACK:\n\t\t{\n\t\t\t*rs = rsBACKSP;\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\tcase VK_TAB:\n\t\t{\n\t\t\t*rs = rsTAB;\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\tdefault:\n\t\t{\n\t\t\tUINT vkey = MapVirtualKey(key, MAPVK_VK_TO_CHAR) & 0xFFFF;\n\t\t\tif ( vkey < 255 )\n\t\t\t\t*rs = (RsKeyCodes)vkey;\n\t\t\tbreak;\n\t\t}\n\t}\n\t\n\treturn *rs != rsNULL;\n}\n\nvoid _InputTranslateShiftKeyUpDown(RsKeyCodes *rs)\n{\n\tif ( _dwOperatingSystemVersion != OS_WIN98 )\n\t{\n\t\tif ( _InputTranslateShiftKey(rs, VK_LSHIFT, TRUE) )\n\t\t\tRsKeyboardEventHandler(rsKEYDOWN, rs);\n\t\tif ( _InputTranslateShiftKey(rs, VK_RSHIFT, TRUE) )\n\t\t\tRsKeyboardEventHandler(rsKEYDOWN, rs);\n\t\tif ( _InputTranslateShiftKey(rs, VK_LSHIFT, FALSE) )\n\t\t\tRsKeyboardEventHandler(rsKEYUP, rs);\n\t\tif ( _InputTranslateShiftKey(rs, VK_RSHIFT, FALSE) )\n\t\t\tRsKeyboardEventHandler(rsKEYUP, rs);\n\t}\n}\n\nBOOL _InputTranslateShiftKey(RsKeyCodes *rs, UINT key, BOOLEAN bDown)\n{\n\t*rs = rsNULL;\n\tswitch ( key )\n\t{\n\t\tcase VK_LSHIFT:\n\t\t{\n\t\t\tif ( bDown == (GetKeyState(VK_LSHIFT) & 0x8000) >> 15 )\n\t\t\t\t*rs = rsLSHIFT;\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\tcase VK_RSHIFT:\n\t\t{\n\t\t\tif ( bDown == (GetKeyState(VK_RSHIFT) & 0x8000) >> 15 )\n\t\t\t\t*rs = rsRSHIFT;\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\tdefault:\n\t\t{\n\t\t\treturn *rs != rsNULL;\n\t\t}\n\t}\n\t\n\treturn TRUE;\n}\n\nBOOL _InputIsExtended(INT flag)\n{\n\treturn (flag & 0x1000000) != 0;\n}\n\n#if (defined(_MSC_VER))\nint strcasecmp(const char *str1, const char *str2)\n{\n\treturn _strcmpi(str1, str2);\n}\nint strncasecmp(const char *str1, const char *str2, size_t len)\n{\n\treturn _strnicmp(str1, str2, len);\n}\n#endif\n#endif\n"
  },
  {
    "path": "src/skel/win/win.h",
    "content": "\n// DON'T include directly. crossplatform.h includes this if you're using D3D9 backend(win.cpp).\n\n#if (!defined(_PLATFORM_WIN_H))\n#define _PLATFORM_WIN_H\n\n#if (!defined(RSREGSETBREAKALLOC))\n#define RSREGSETBREAKALLOC(_name) /* No op */\n#endif /* (!defined(RSREGSETBREAKALLOC)) */\n\n#ifdef __DINPUT_INCLUDED__\n/* platform specfic global data */\ntypedef struct\n{\n\tHWND\t\twindow;\n\tHINSTANCE\tinstance;\n\tRwBool\t\tfullScreen;\n\tRwV2d\t\tlastMousePos;\n\t\n\tDWORD field_14;\n\n\tLPDIRECTINPUT8\t\t dinterface;\n\tLPDIRECTINPUTDEVICE8 mouse;\n\tLPDIRECTINPUTDEVICE8 joy1;\n\tLPDIRECTINPUTDEVICE8 joy2;\n}\npsGlobalType;\n\n#define PSGLOBAL(var) (((psGlobalType *)(RsGlobal.ps))->var)\n\nenum eJoypads\n{\n\tJOYSTICK1 = 0,\n\tJOYSTICK2,\n\tMAX_JOYSTICKS\n};\n\nenum eJoypadState\n{\n\tJOYPAD_UNUSED,\n\tJOYPAD_ATTACHED,\n};\n\nstruct tJoy\n{\n\teJoypadState m_State;\n\tbool         m_bInitialised;\n\tbool         m_bHasAxisZ;\n\tbool         m_bHasAxisR;\n\tint          m_nVendorID;\n\tint          m_nProductID;\n};\n\nclass CJoySticks\n{\npublic:\n\ttJoy m_aJoys[MAX_JOYSTICKS];\n\t\n\tCJoySticks();\n\tvoid ClearJoyInfo(int joyID);\n};\n\nextern CJoySticks AllValidWinJoys;\n#endif\n\n#ifdef    __cplusplus\nextern \"C\"\n{\n#endif                          /* __cplusplus */\n\n#ifdef __DINPUT_INCLUDED__\nHRESULT _InputInitialise();\nHRESULT CapturePad(RwInt32 padID);\nvoid _InputAddJoyStick(LPDIRECTINPUTDEVICE8 lpDevice, INT num);\nHRESULT _InputAddJoys();\nHRESULT _InputGetMouseState(DIMOUSESTATE2 *state);\nvoid _InputShutdown();\nBOOL CALLBACK _InputEnumDevicesCallback( const DIDEVICEINSTANCE* pdidInstance, VOID* pContext );\nBOOL _InputTranslateKey(RsKeyCodes *rs, UINT flag, UINT key);\nBOOL _InputTranslateShiftKey(RsKeyCodes *rs, UINT key, BOOLEAN bDown);\nBOOL _InputIsExtended(INT flag);\n#endif\n\nvoid CenterVideo(void);\nvoid CloseClip(void);\n\n#ifdef    __cplusplus\n}\n#endif                          /* __cplusplus */\n\n#endif /* (!defined(_PLATFORM_WIN_H)) */\n"
  },
  {
    "path": "src/skel/win/win.rc",
    "content": "#include \"resource.h\"\n\n/////////////////////////////////////////////////////////////////////////////\n//\n// Generated from the TEXTINCLUDE 2 resource.\n//\n//#if !defined(__GNU_C__)\n//#include \"afxres.h\"\n//#else\n#include \"winresrc.h\"\n//#endif /* !defined(__GNU_C__) */\n\n/////////////////////////////////////////////////////////////////////////////\n#undef APSTUDIO_READONLY_SYMBOLS\n\n/////////////////////////////////////////////////////////////////////////////\n//\n// Dialog\n//\n\nIDD_DIALOG1 DIALOG DISCARDABLE  0, 0, 186, 90\nSTYLE DS_MODALFRAME | DS_CENTER | DS_CENTERMOUSE | WS_POPUP | WS_CAPTION |\n      WS_SYSMENU\nCAPTION \"Device Selection\"\nFONT 8, \"MS Sans Serif\"\nBEGIN\n    COMBOBOX        IDC_DEVICESEL,7,25,172,33,CBS_DROPDOWNLIST | WS_VSCROLL | \n                    WS_TABSTOP\n    COMBOBOX        IDC_VIDMODE,7,46,172,74,CBS_DROPDOWNLIST | WS_VSCROLL | \n                    WS_TABSTOP\n    DEFPUSHBUTTON   \"EXIT\",IDEXIT,103,69,52,14\n    DEFPUSHBUTTON   \"OK\",IDOK,28,69,50,14\n    LTEXT           \"Please select the Device To Use:\",IDC_SELECTDEVICE,7,7,\n                    137,8\nEND\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_MAIN_ICON           ICON    DISCARDABLE     \"gtavc.ico\"\n\n/////////////////////////////////////////////////////////////////////////////"
  },
  {
    "path": "src/text/Messages.cpp",
    "content": "#include \"common.h\"\n\n#include \"Messages.h\"\n#include \"RwHelper.h\"\n#include \"Hud.h\"\n#include \"User.h\"\n#include \"Timer.h\"\n#include \"Text.h\"\n\n#include \"ControllerConfig.h\"\n\n#include \"Font.h\"\n\ntMessage CMessages::BriefMessages[NUMBRIEFMESSAGES];\ntPreviousBrief CMessages::PreviousBriefs[NUMPREVIOUSBRIEFS];\ntBigMessage CMessages::BIGMessages[NUMBIGMESSAGES];\nchar CMessages::PreviousMissionTitle[16]; // unused\n\nvoid\nCMessages::Init()\n{\n\tClearMessages();\n\n\tfor (int32 i = 0; i < NUMPREVIOUSBRIEFS; i++) {\n\t\tPreviousBriefs[i].m_pText = nil;\n\t\tPreviousBriefs[i].m_pString = nil;\n\t}\n}\n\nuint16\nCMessages::GetWideStringLength(wchar *src)\n{\n\tuint16 length = 0;\n\twhile (*(src++)) length++;\n\treturn length;\n}\n\nvoid\nCMessages::WideStringCopy(wchar *dst, wchar *src, uint16 size)\n{\n\tint32 i = 0;\n\tif (src) {\n\t\twhile (i < size - 1) {\n\t\t\tif (!src[i]) break;\n\t\t\tdst[i] = src[i];\n\t\t\ti++;\n\t\t}\n\t} else {\n\t\twhile (i < size - 1)\n\t\t\tdst[i++] = '\\0';\n\t}\n\tdst[i] = '\\0';\n}\n\nwchar FixupChar(wchar c)\n{\n#ifdef MORE_LANGUAGES\n\tif (CFont::IsJapanese())\n\t\treturn c & 0x7fff;\n#endif\n\treturn c;\n}\n\nbool\nCMessages::WideStringCompare(wchar *str1, wchar *str2, uint16 size)\n{\n\tuint16 len1 = GetWideStringLength(str1);\n\tuint16 len2 = GetWideStringLength(str2);\n\tif (len1 != len2 && (len1 < size || len2 < size))\n\t\treturn false;\n\n\tfor (int32 i = 0; i < size && FixupChar(str1[i]) != '\\0'; i++) {\n\t\tif (FixupChar(str1[i]) != FixupChar(str2[i]))\n\t\t\treturn false;\n\t}\n\treturn true;\n}\n\nvoid\nCMessages::Process()\n{\n\tfor (int32 style = 0; style < 6; style++) {\n\t\tif (BIGMessages[style].m_Stack[0].m_pText != nil && CTimer::GetTimeInMilliseconds() > BIGMessages[style].m_Stack[0].m_nTime + BIGMessages[style].m_Stack[0].m_nStartTime) {\n\t\t\tBIGMessages[style].m_Stack[0].m_pText = nil;\n\n\t\t\tint32 i = 0;\n\t\t\twhile (i < 3) {\n\t\t\t\tif (BIGMessages[style].m_Stack[i + 1].m_pText == nil) break;\n\t\t\t\tBIGMessages[style].m_Stack[i] = BIGMessages[style].m_Stack[i + 1];\n\t\t\t\ti++;\n\t\t\t}\n\n\t\t\tBIGMessages[style].m_Stack[i].m_pText = nil;\n\t\t\tBIGMessages[style].m_Stack[0].m_nStartTime = CTimer::GetTimeInMilliseconds();\n\t\t}\n\t}\n\n\tif (BriefMessages[0].m_pText != nil && CTimer::GetTimeInMilliseconds() > BriefMessages[0].m_nTime + BriefMessages[0].m_nStartTime) {\n\t\tBriefMessages[0].m_pText = nil;\n\t\tint32 i;\n\t\tfor (i = 0; i < NUMBRIEFMESSAGES-1 && BriefMessages[i + 1].m_pText != nil; i++) {\n\t\t\tBriefMessages[i] = BriefMessages[i + 1];\n\t\t}\n\t\tCMessages::BriefMessages[i].m_pText = nil;\n\t\tCMessages::BriefMessages[0].m_nStartTime = CTimer::GetTimeInMilliseconds();\n\t\tif (BriefMessages[0].m_pText != nil)\n\t\t\tAddToPreviousBriefArray(\n\t\t\t\tBriefMessages[0].m_pText,\n\t\t\t\tBriefMessages[0].m_nNumber[0],\n\t\t\t\tBriefMessages[0].m_nNumber[1],\n\t\t\t\tBriefMessages[0].m_nNumber[2],\n\t\t\t\tBriefMessages[0].m_nNumber[3],\n\t\t\t\tBriefMessages[0].m_nNumber[4],\n\t\t\t\tBriefMessages[0].m_nNumber[5],\n\t\t\t\tBriefMessages[0].m_pString);\n\t}\n}\n\nvoid\nCMessages::Display()\n{\n\twchar outstr[256];\n\n\tDefinedState();\n\n\tfor (int32 i = 0; i < NUMBIGMESSAGES; i++) {\n\t\tInsertNumberInString(\n\t\t\tBIGMessages[i].m_Stack[0].m_pText,\n\t\t\tBIGMessages[i].m_Stack[0].m_nNumber[0],\n\t\t\tBIGMessages[i].m_Stack[0].m_nNumber[1],\n\t\t\tBIGMessages[i].m_Stack[0].m_nNumber[2],\n\t\t\tBIGMessages[i].m_Stack[0].m_nNumber[3],\n\t\t\tBIGMessages[i].m_Stack[0].m_nNumber[4],\n\t\t\tBIGMessages[i].m_Stack[0].m_nNumber[5],\n\t\t\toutstr);\n\t\tInsertStringInString(outstr, BIGMessages[i].m_Stack[0].m_pString);\n\t\tInsertPlayerControlKeysInString(outstr);\n\t\tCHud::SetBigMessage(outstr, i);\n\t}\n\n\tInsertNumberInString(\n\t\tBriefMessages[0].m_pText,\n\t\tBriefMessages[0].m_nNumber[0],\n\t\tBriefMessages[0].m_nNumber[1],\n\t\tBriefMessages[0].m_nNumber[2],\n\t\tBriefMessages[0].m_nNumber[3],\n\t\tBriefMessages[0].m_nNumber[4],\n\t\tBriefMessages[0].m_nNumber[5],\n\t\toutstr);\n\tInsertStringInString(outstr, BriefMessages[0].m_pString);\n\tInsertPlayerControlKeysInString(outstr);\n\tCHud::SetMessage(outstr);\n}\n\nvoid\nCMessages::AddMessage(wchar *msg, uint32 time, uint16 flag)\n{\n\twchar outstr[512]; // unused\n\tWideStringCopy(outstr, msg, 256);\n\tInsertPlayerControlKeysInString(outstr);\n\tGetWideStringLength(outstr);\n\n\tint32 i = 0;\n\twhile (i < NUMBRIEFMESSAGES && BriefMessages[i].m_pText != nil)\n\t\ti++;\n\tif (i >= NUMBRIEFMESSAGES) return;\n\n\tBriefMessages[i].m_pText = msg;\n\tBriefMessages[i].m_nFlag = flag;\n\tBriefMessages[i].m_nTime = time;\n\tBriefMessages[i].m_nStartTime = CTimer::GetTimeInMilliseconds();\n\tBriefMessages[i].m_nNumber[0] = -1;\n\tBriefMessages[i].m_nNumber[1] = -1;\n\tBriefMessages[i].m_nNumber[2] = -1;\n\tBriefMessages[i].m_nNumber[3] = -1;\n\tBriefMessages[i].m_nNumber[4] = -1;\n\tBriefMessages[i].m_nNumber[5] = -1;\n\tBriefMessages[i].m_pString = nil;\n\tif (i == 0)\n\t\tAddToPreviousBriefArray(\n\t\t\tBriefMessages[0].m_pText,\n\t\t\tBriefMessages[0].m_nNumber[0],\n\t\t\tBriefMessages[0].m_nNumber[1],\n\t\t\tBriefMessages[0].m_nNumber[2],\n\t\t\tBriefMessages[0].m_nNumber[3],\n\t\t\tBriefMessages[0].m_nNumber[4],\n\t\t\tBriefMessages[0].m_nNumber[5],\n\t\t\tBriefMessages[0].m_pString);\n}\n\nvoid\nCMessages::AddMessageJumpQ(wchar *msg, uint32 time, uint16 flag)\n{\n\twchar outstr[512]; // unused\n\tWideStringCopy(outstr, msg, 256);\n\tInsertPlayerControlKeysInString(outstr);\n\tGetWideStringLength(outstr);\n\n\tBriefMessages[0].m_pText = msg;\n\tBriefMessages[0].m_nFlag = flag;\n\tBriefMessages[0].m_nTime = time;\n\tBriefMessages[0].m_nStartTime = CTimer::GetTimeInMilliseconds();\n\tBriefMessages[0].m_nNumber[0] = -1;\n\tBriefMessages[0].m_nNumber[1] = -1;\n\tBriefMessages[0].m_nNumber[2] = -1;\n\tBriefMessages[0].m_nNumber[3] = -1;\n\tBriefMessages[0].m_nNumber[4] = -1;\n\tBriefMessages[0].m_nNumber[5] = -1;\n\tBriefMessages[0].m_pString = nil;\n\tAddToPreviousBriefArray(msg, -1, -1, -1, -1, -1, -1, 0);\n}\n\nvoid\nCMessages::AddMessageSoon(wchar *msg, uint32 time, uint16 flag)\n{\n\twchar outstr[512]; // unused\n\tWideStringCopy(outstr, msg, 256);\n\tInsertPlayerControlKeysInString(outstr);\n\tGetWideStringLength(outstr);\n\n\tif (BriefMessages[0].m_pText != nil) {\n\t\tfor (int i = NUMBRIEFMESSAGES-1; i > 1; i--)\n\t\t\tBriefMessages[i] = BriefMessages[i-1];\n\n\t\tBriefMessages[1].m_pText = msg;\n\t\tBriefMessages[1].m_nFlag = flag;\n\t\tBriefMessages[1].m_nTime = time;\n\t\tBriefMessages[1].m_nStartTime = CTimer::GetTimeInMilliseconds();\n\t\tBriefMessages[1].m_nNumber[0] = -1;\n\t\tBriefMessages[1].m_nNumber[1] = -1;\n\t\tBriefMessages[1].m_nNumber[2] = -1;\n\t\tBriefMessages[1].m_nNumber[3] = -1;\n\t\tBriefMessages[1].m_nNumber[4] = -1;\n\t\tBriefMessages[1].m_nNumber[5] = -1;\n\t\tBriefMessages[1].m_pString = nil;\n\t}else{\n\t\tBriefMessages[0].m_pText = msg;\n\t\tBriefMessages[0].m_nFlag = flag;\n\t\tBriefMessages[0].m_nTime = time;\n\t\tBriefMessages[0].m_nStartTime = CTimer::GetTimeInMilliseconds();\n\t\tBriefMessages[0].m_nNumber[0] = -1;\n\t\tBriefMessages[0].m_nNumber[1] = -1;\n\t\tBriefMessages[0].m_nNumber[2] = -1;\n\t\tBriefMessages[0].m_nNumber[3] = -1;\n\t\tBriefMessages[0].m_nNumber[4] = -1;\n\t\tBriefMessages[0].m_nNumber[5] = -1;\n\t\tBriefMessages[0].m_pString = nil;\n\t\tAddToPreviousBriefArray(msg, -1, -1, -1, -1, -1, -1, nil);\n\t}\n}\n\nvoid\nCMessages::ClearMessages()\n{\n\tfor (int32 i = 0; i < NUMBIGMESSAGES; i++) {\n\t\tfor (int32 j = 0; j < 4; j++) {\n\t\t\tBIGMessages[i].m_Stack[j].m_pText = nil;\n\t\t\tBIGMessages[i].m_Stack[j].m_pString = nil;\n\t\t}\n\t}\n\tClearSmallMessagesOnly();\n}\n\nvoid\nCMessages::ClearSmallMessagesOnly()\n{\n\tfor (int32 i = 0; i < NUMBRIEFMESSAGES; i++) {\n\t\tBriefMessages[i].m_pText = nil;\n\t\tBriefMessages[i].m_pString = nil;\n\t}\n}\n\nvoid\nCMessages::AddBigMessage(wchar *msg, uint32 time, uint16 style)\n{\n\twchar outstr[512]; // unused\n\tWideStringCopy(outstr, msg, 256);\n\tInsertPlayerControlKeysInString(outstr);\n\tGetWideStringLength(outstr);\n\n\tBIGMessages[style].m_Stack[0].m_pText = msg;\n\tBIGMessages[style].m_Stack[0].m_nFlag = 0;\n\tBIGMessages[style].m_Stack[0].m_nTime = time;\n\tBIGMessages[style].m_Stack[0].m_nStartTime = CTimer::GetTimeInMilliseconds();\n\tBIGMessages[style].m_Stack[0].m_nNumber[0] = -1;\n\tBIGMessages[style].m_Stack[0].m_nNumber[1] = -1;\n\tBIGMessages[style].m_Stack[0].m_nNumber[2] = -1;\n\tBIGMessages[style].m_Stack[0].m_nNumber[3] = -1;\n\tBIGMessages[style].m_Stack[0].m_nNumber[4] = -1;\n\tBIGMessages[style].m_Stack[0].m_nNumber[5] = -1;\n\tBIGMessages[style].m_Stack[0].m_pString = nil;\n}\n\nvoid\nCMessages::AddBigMessageQ(wchar *msg, uint32 time, uint16 style)\n{\n\twchar outstr[512]; // unused\n\tWideStringCopy(outstr, msg, 256);\n\tInsertPlayerControlKeysInString(outstr);\n\tGetWideStringLength(outstr);\n\n\tint32 i = 0;\n\twhile (i < 4 && BIGMessages[style].m_Stack[i].m_pText != nil)\n\t\ti++;\n\n\tif (i >= 4) return;\n\n\tBIGMessages[style].m_Stack[i].m_pText = msg;\n\tBIGMessages[style].m_Stack[i].m_nFlag = 0;\n\tBIGMessages[style].m_Stack[i].m_nTime = time;\n\tBIGMessages[style].m_Stack[i].m_nStartTime = CTimer::GetTimeInMilliseconds();\n\tBIGMessages[style].m_Stack[i].m_nNumber[0] = -1;\n\tBIGMessages[style].m_Stack[i].m_nNumber[1] = -1;\n\tBIGMessages[style].m_Stack[i].m_nNumber[2] = -1;\n\tBIGMessages[style].m_Stack[i].m_nNumber[3] = -1;\n\tBIGMessages[style].m_Stack[i].m_nNumber[4] = -1;\n\tBIGMessages[style].m_Stack[i].m_nNumber[5] = -1;\n\tBIGMessages[style].m_Stack[i].m_pString = nil;\n}\n\nvoid\nCMessages::AddToPreviousBriefArray(wchar *text, int32 n1, int32 n2, int32 n3, int32 n4, int32 n5, int32 n6, wchar *string)\n{\n\tint32 i;\n\tfor (i = 0; i < NUMPREVIOUSBRIEFS && PreviousBriefs[i].m_pText != nil; i++) {\n\t\tif (PreviousBriefs[i].m_nNumber[0] == n1\n\t\t\t&& PreviousBriefs[i].m_nNumber[1] == n2\n\t\t\t&& PreviousBriefs[i].m_nNumber[2] == n3\n\t\t\t&& PreviousBriefs[i].m_nNumber[3] == n4\n\t\t\t&& PreviousBriefs[i].m_nNumber[4] == n5\n\t\t\t&& PreviousBriefs[i].m_nNumber[5] == n6\n\t\t\t&& PreviousBriefs[i].m_pText == text\n\t\t\t&& PreviousBriefs[i].m_pString == string)\n\t\t\treturn;\n\t}\n\n\tif (i != 0) {\n\t\tif (i == NUMPREVIOUSBRIEFS) i -= 2;\n\t\telse i--;\n\n\t\twhile (i >= 0) {\n\t\t\tPreviousBriefs[i + 1] = PreviousBriefs[i];\n\t\t\ti--;\n\t\t}\n\t}\n\tPreviousBriefs[0].m_pText = text;\n\tPreviousBriefs[0].m_nNumber[0] = n1;\n\tPreviousBriefs[0].m_nNumber[1] = n2;\n\tPreviousBriefs[0].m_nNumber[2] = n3;\n\tPreviousBriefs[0].m_nNumber[3] = n4;\n\tPreviousBriefs[0].m_nNumber[4] = n5;\n\tPreviousBriefs[0].m_nNumber[5] = n6;\n\tPreviousBriefs[0].m_pString = string;\n}\n\nvoid\nCMessages::InsertNumberInString(wchar *str, int32 n1, int32 n2, int32 n3, int32 n4, int32 n5, int32 n6, wchar *outstr)\n{\n\tchar numStr[10];\n\twchar wNumStr[10];\n\n\tif (str == nil) {\n\t\t*outstr = '\\0';\n\t\treturn;\n\t}\n\n\tsprintf(numStr, \"%d\", n1);\n\tsize_t outLen = strlen(numStr);\n\tAsciiToUnicode(numStr, wNumStr);\n\tif (str[0] == 0) {\n\t\t*outstr = '\\0';\n\t\treturn;\n\t}\n\n\tint32 size = GetWideStringLength(str);\n\n\tint32 i = 0;\n\n\tfor (int32 c = 0; c < size;) {\n#ifdef MORE_LANGUAGES\n\t\tif ((CFont::IsJapanese() && str[c] == (0x8000 | '~') && str[c + 1] == (0x8000 | '1') && str[c + 2] == (0x8000 | '~')) ||\n\t\t\t(!CFont::IsJapanese() && str[c] == '~' && str[c + 1] == '1' && str[c + 2] == '~')) {\n#else\n\t\tif (str[c] == '~' && str[c + 1] == '1' && str[c + 2] == '~') {\n#endif\n\t\t\tc += 3;\n\t\t\tfor (int j = 0; j < outLen; )\n\t\t\t\t*(outstr++) = wNumStr[j++];\n\n\t\t\ti++;\n\t\t\tswitch (i) {\n\t\t\tcase 1: sprintf(numStr, \"%d\", n2); break;\n\t\t\tcase 2: sprintf(numStr, \"%d\", n3); break;\n\t\t\tcase 3: sprintf(numStr, \"%d\", n4); break;\n\t\t\tcase 4: sprintf(numStr, \"%d\", n5); break;\n\t\t\tcase 5: sprintf(numStr, \"%d\", n6); break;\n\t\t\t}\n\t\t\toutLen = strlen(numStr);\n\t\t\tAsciiToUnicode(numStr, wNumStr);\n\t\t} else {\n\t\t\t*(outstr++) = str[c++];\n\t\t}\n\t}\n\t*outstr = '\\0';\n}\n\nvoid\nCMessages::InsertStringInString(wchar *str1, wchar *str2)\n{\n\twchar tempstr[256];\n\n\tif (!str1 || !str2) return;\n\n\tint32 str1_size = GetWideStringLength(str1);\n\tint32 str2_size = GetWideStringLength(str2);\n\tint32 total_size = str1_size + str2_size;\n\t\n\twchar *_str1 = str1;\n\tuint16 i;\n\tfor (i = 0; i < total_size; ) {\n#ifdef MORE_LANGUAGES\n\t\tif ((CFont::IsJapanese() && *_str1 == (0x8000 | '~') && *(_str1 + 1) == (0x8000 | 'a') && *(_str1 + 2) == (0x8000 | '~'))\n\t\t\t|| (*_str1 == '~' && *(_str1 + 1) == 'a' && *(_str1 + 2) == '~')) {\n#else\n\t\tif (*_str1 == '~' && *(_str1 + 1) == 'a' && *(_str1 + 2) == '~') {\n#endif\n\t\t\t_str1 += 3;\n\t\t\tfor (int j = 0; j < str2_size; j++) {\n\t\t\t\ttempstr[i++] = str2[j];\n\t\t\t}\n\t\t} else {\n\t\t\ttempstr[i++] = *(_str1++);\n\t\t}\n\t}\n\ttempstr[i] = '\\0';\n\n\tfor (i = 0; i < total_size; i++)\n\t\tstr1[i] = tempstr[i];\n\n\twhile (i < 256)\n\t\tstr1[i++] = '\\0';\n}\n\nvoid\nCMessages::InsertPlayerControlKeysInString(wchar *str)\n{\n\tuint16 i;\n\twchar outstr[256];\n\twchar keybuf[256];\n\n\tif (!str) return;\n\tuint16 strSize = GetWideStringLength(str);\n\tmemset(keybuf, 0, 256*sizeof(wchar));\n\n\twchar *_outstr = outstr;\n\tfor (i = 0; i < strSize;) {\n#ifdef MORE_LANGUAGES\n\t\tif ((CFont::IsJapanese() && str[i] == (0x8000 | '~') && str[i + 1] == (0x8000 | 'k') && str[i + 2] == (0x8000 | '~')) ||\n\t\t\t(!CFont::IsJapanese() && str[i] == '~' && str[i + 1] == 'k' && str[i + 2] == '~')) {\n#else\n\t\tif (str[i] == '~' && str[i + 1] == 'k' && str[i + 2] == '~') {\n#endif\n\t\t\ti += 4;\n\t\t\tbool done = false;\n\t\t\tfor (int32 cont = 0; cont < MAX_CONTROLLERACTIONS && !done; cont++) {\n\t\t\t\tuint16 contSize = GetWideStringLength(ControlsManager.m_aActionNames[cont]);\n\t\t\t\tif (contSize != 0) {\n\t\t\t\t\tif (WideStringCompare(&str[i], ControlsManager.m_aActionNames[cont], contSize)) {\n\t\t\t\t\t\tdone = true;\n\t\t\t\t\t\tControlsManager.GetWideStringOfCommandKeys(cont, keybuf, 256);\n\t\t\t\t\t\tuint16 keybuf_size = GetWideStringLength(keybuf);\n\t\t\t\t\t\tfor (uint16 j = 0; j < keybuf_size; j++) {\n\t\t\t\t\t\t\t*(_outstr++) = keybuf[j];\n\t\t\t\t\t\t\tkeybuf[j] = '\\0';\n\t\t\t\t\t\t}\n\t\t\t\t\t\ti += contSize + 1;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\t*(_outstr++) = str[i++];\n\t\t}\n\t}\n\t*_outstr = '\\0';\n\n\tfor (i = 0; i < GetWideStringLength(outstr); i++)\n\t\tstr[i] = outstr[i];\n\n\twhile (i < 256)\n\t\tstr[i++] = '\\0';\n}\n\nvoid\nCMessages::AddMessageWithNumber(wchar *str, uint32 time, uint16 flag, int32 n1, int32 n2, int32 n3, int32 n4, int32 n5, int32 n6)\n{\n\twchar outstr[512]; // unused\n\tInsertNumberInString(str, n1, n2, n3, n4, n5, n6, outstr);\n\tInsertPlayerControlKeysInString(outstr);\n\tGetWideStringLength(outstr);\n\n\tuint16 i = 0;\n\twhile (i < NUMBRIEFMESSAGES && BriefMessages[i].m_pText != nil)\n\t\ti++;\n\n\tif (i >= NUMBRIEFMESSAGES) return;\n\n\tBriefMessages[i].m_pText = str;\n\tBriefMessages[i].m_nFlag = flag;\n\tBriefMessages[i].m_nTime = time;\n\tBriefMessages[i].m_nStartTime = CTimer::GetTimeInMilliseconds();\n\tBriefMessages[i].m_nNumber[0] = n1;\n\tBriefMessages[i].m_nNumber[1] = n2;\n\tBriefMessages[i].m_nNumber[2] = n3;\n\tBriefMessages[i].m_nNumber[3] = n4;\n\tBriefMessages[i].m_nNumber[4] = n5;\n\tBriefMessages[i].m_nNumber[5] = n6;\n\tBriefMessages[i].m_pString = nil;\n\tif (i == 0)\n\t\tAddToPreviousBriefArray(\n\t\t\tBriefMessages[0].m_pText,\n\t\t\tBriefMessages[0].m_nNumber[0],\n\t\t\tBriefMessages[0].m_nNumber[1],\n\t\t\tBriefMessages[0].m_nNumber[2],\n\t\t\tBriefMessages[0].m_nNumber[3],\n\t\t\tBriefMessages[0].m_nNumber[4],\n\t\t\tBriefMessages[0].m_nNumber[5],\n\t\t\tBriefMessages[0].m_pString);\n}\n\nvoid \nCMessages::AddMessageJumpQWithNumber(wchar *str, uint32 time, uint16 flag, int32 n1, int32 n2, int32 n3, int32 n4, int32 n5, int32 n6)\n{\n\twchar outstr[512]; // unused\n\tInsertNumberInString(str, n1, n2, n3, n4, n5, n6, outstr);\n\tInsertPlayerControlKeysInString(outstr);\n\tGetWideStringLength(outstr);\n\n\tBriefMessages[0].m_pText = str;\n\tBriefMessages[0].m_nFlag = flag;\n\tBriefMessages[0].m_nTime = time;\n\tBriefMessages[0].m_nStartTime = CTimer::GetTimeInMilliseconds();\n\tBriefMessages[0].m_nNumber[0] = n1;\n\tBriefMessages[0].m_nNumber[1] = n2;\n\tBriefMessages[0].m_nNumber[2] = n3;\n\tBriefMessages[0].m_nNumber[3] = n4;\n\tBriefMessages[0].m_nNumber[4] = n5;\n\tBriefMessages[0].m_nNumber[5] = n6;\n\tBriefMessages[0].m_pString = nil;\n\tAddToPreviousBriefArray(str, n1, n2, n3, n4, n5, n6, nil);\n}\n\nvoid\nCMessages::AddMessageSoonWithNumber(wchar *str, uint32 time, uint16 flag, int32 n1, int32 n2, int32 n3, int32 n4, int32 n5, int32 n6)\n{\n\twchar outstr[512]; // unused\n\tInsertNumberInString(str, n1, n2, n3, n4, n5, n6, outstr);\n\tInsertPlayerControlKeysInString(outstr);\n\tGetWideStringLength(outstr);\n\n\tif (BriefMessages[0].m_pText != nil) {\n\t\tfor (int32 i = NUMBRIEFMESSAGES-1; i > 1; i--)\n\t\t\tBriefMessages[i] = BriefMessages[i-1];\n\n\t\tBriefMessages[1].m_pText = str;\n\t\tBriefMessages[1].m_nFlag = flag;\n\t\tBriefMessages[1].m_nTime = time;\n\t\tBriefMessages[1].m_nStartTime = CTimer::GetTimeInMilliseconds();\n\t\tBriefMessages[1].m_nNumber[0] = n1;\n\t\tBriefMessages[1].m_nNumber[1] = n2;\n\t\tBriefMessages[1].m_nNumber[2] = n3;\n\t\tBriefMessages[1].m_nNumber[3] = n4;\n\t\tBriefMessages[1].m_nNumber[4] = n5;\n\t\tBriefMessages[1].m_nNumber[5] = n6;\n\t\tBriefMessages[1].m_pString = nil;\n\t} else {\n\t\tBriefMessages[0].m_pText = str;\n\t\tBriefMessages[0].m_nFlag = flag;\n\t\tBriefMessages[0].m_nTime = time;\n\t\tBriefMessages[0].m_nStartTime = CTimer::GetTimeInMilliseconds();\n\t\tBriefMessages[0].m_nNumber[0] = n1;\n\t\tBriefMessages[0].m_nNumber[1] = n2;\n\t\tBriefMessages[0].m_nNumber[2] = n3;\n\t\tBriefMessages[0].m_nNumber[3] = n4;\n\t\tBriefMessages[0].m_nNumber[4] = n5;\n\t\tBriefMessages[0].m_nNumber[5] = n6;\n\t\tBriefMessages[0].m_pString = nil;\n\t\tAddToPreviousBriefArray(str, n1, n2, n3, n4, n5, n6, nil);\n\t}\n}\n\nvoid\nCMessages::AddBigMessageWithNumber(wchar *str, uint32 time, uint16 style, int32 n1, int32 n2, int32 n3, int32 n4, int32 n5, int32 n6)\n{\n\twchar outstr[512]; // unused\n\tInsertNumberInString(str, n1, n2, n3, n4, n5, n6, outstr);\n\tInsertPlayerControlKeysInString(outstr);\n\tGetWideStringLength(outstr);\n\n\tBIGMessages[style].m_Stack[0].m_pText = str;\n\tBIGMessages[style].m_Stack[0].m_nFlag = 0;\n\tBIGMessages[style].m_Stack[0].m_nTime = time;\n\tBIGMessages[style].m_Stack[0].m_nStartTime = CTimer::GetTimeInMilliseconds();\n\tBIGMessages[style].m_Stack[0].m_nNumber[0] = n1;\n\tBIGMessages[style].m_Stack[0].m_nNumber[1] = n2;\n\tBIGMessages[style].m_Stack[0].m_nNumber[2] = n3;\n\tBIGMessages[style].m_Stack[0].m_nNumber[3] = n4;\n\tBIGMessages[style].m_Stack[0].m_nNumber[4] = n5;\n\tBIGMessages[style].m_Stack[0].m_nNumber[5] = n6;\n\tBIGMessages[style].m_Stack[0].m_pString = nil;\n}\n\nvoid\nCMessages::AddBigMessageWithNumberQ(wchar *str, uint32 time, uint16 style, int32 n1, int32 n2, int32 n3, int32 n4, int32 n5, int32 n6)\n{\n\twchar outstr[512]; // unused\n\tInsertNumberInString(str, n1, n2, n3, n4, n5, n6, outstr);\n\tInsertPlayerControlKeysInString(outstr);\n\tGetWideStringLength(outstr);\n\n\tint32 i = 0;\n\n\twhile (i < 4 && BIGMessages[style].m_Stack[i].m_pText != nil)\n\t\ti++;\n\n\tif (i >= 4) return;\n\n\tBIGMessages[style].m_Stack[i].m_pText = str;\n\tBIGMessages[style].m_Stack[i].m_nFlag = 0;\n\tBIGMessages[style].m_Stack[i].m_nTime = time;\n\tBIGMessages[style].m_Stack[i].m_nStartTime = CTimer::GetTimeInMilliseconds();\n\tBIGMessages[style].m_Stack[i].m_nNumber[0] = n1;\n\tBIGMessages[style].m_Stack[i].m_nNumber[1] = n2;\n\tBIGMessages[style].m_Stack[i].m_nNumber[2] = n3;\n\tBIGMessages[style].m_Stack[i].m_nNumber[3] = n4;\n\tBIGMessages[style].m_Stack[i].m_nNumber[4] = n5;\n\tBIGMessages[style].m_Stack[i].m_nNumber[5] = n6;\n\tBIGMessages[style].m_Stack[i].m_pString = nil;\n}\n\nvoid\nCMessages::AddMessageWithString(wchar *text, uint32 time, uint16 flag, wchar *str)\n{\n\twchar outstr[512]; // unused\n\tWideStringCopy(outstr, text, 256);\n\tInsertStringInString(outstr, str);\n\tInsertPlayerControlKeysInString(outstr);\n\tGetWideStringLength(outstr);\n\n\tint32 i = 0;\n\twhile (i < NUMBRIEFMESSAGES && BriefMessages[i].m_pText != nil)\n\t\ti++;\n\n\tif (i >= NUMBRIEFMESSAGES) return;\n\n\tBriefMessages[i].m_pText = text;\n\tBriefMessages[i].m_nFlag = flag;\n\tBriefMessages[i].m_nTime = time;\n\tBriefMessages[i].m_nStartTime = CTimer::GetTimeInMilliseconds();\n\tBriefMessages[i].m_nNumber[0] = -1;\n\tBriefMessages[i].m_nNumber[1] = -1;\n\tBriefMessages[i].m_nNumber[2] = -1;\n\tBriefMessages[i].m_nNumber[3] = -1;\n\tBriefMessages[i].m_nNumber[4] = -1;\n\tBriefMessages[i].m_nNumber[5] = -1;\n\tBriefMessages[i].m_pString = str;\n\tif (i == 0)\n\t\tAddToPreviousBriefArray(\n\t\t\tBriefMessages[0].m_pText,\n\t\t\tBriefMessages[0].m_nNumber[0],\n\t\t\tBriefMessages[0].m_nNumber[1],\n\t\t\tBriefMessages[0].m_nNumber[2],\n\t\t\tBriefMessages[0].m_nNumber[3],\n\t\t\tBriefMessages[0].m_nNumber[4],\n\t\t\tBriefMessages[0].m_nNumber[5],\n\t\t\tBriefMessages[0].m_pString);\n}\n\nvoid\nCMessages::AddMessageJumpQWithString(wchar *text, uint32 time, uint16 flag, wchar *str)\n{\n\twchar outstr[512]; // unused\n\tWideStringCopy(outstr, text, 256);\n\tInsertStringInString(outstr, str);\n\tInsertPlayerControlKeysInString(outstr);\n\tGetWideStringLength(outstr);\n\n\tBriefMessages[0].m_pText = text;\n\tBriefMessages[0].m_nFlag = flag;\n\tBriefMessages[0].m_nTime = time;\n\tBriefMessages[0].m_nStartTime = CTimer::GetTimeInMilliseconds();\n\tBriefMessages[0].m_nNumber[0] = -1;\n\tBriefMessages[0].m_nNumber[1] = -1;\n\tBriefMessages[0].m_nNumber[2] = -1;\n\tBriefMessages[0].m_nNumber[3] = -1;\n\tBriefMessages[0].m_nNumber[4] = -1;\n\tBriefMessages[0].m_nNumber[5] = -1;\n\tBriefMessages[0].m_pString = str;\n\tAddToPreviousBriefArray(text, -1, -1, -1, -1, -1, -1, str);\n}\n\ninline bool\nFastWideStringComparison(wchar *str1, wchar *str2)\n{\n\twhile (*str1 == *str2) {\n\t\t++str1;\n\t\t++str2;\n\t\tif (!*str1 && !*str2) return true;\n\t}\n\treturn false;\n}\n\nvoid\nCMessages::ClearThisPrint(wchar *str)\n{\n\tbool equal;\n\n\tdo {\n\t\tequal = false;\n\t\tuint16 i;\n\t\tfor (i = 0; i < NUMBRIEFMESSAGES && BriefMessages[i].m_pText != nil; i++) {\n\t\t\tequal = FastWideStringComparison(str, BriefMessages[i].m_pText);\n\n\t\t\tif (equal) break;\n\t\t}\n\n\t\tif (equal) {\n\t\t\tif (i != 0) {\n\t\t\t\tBriefMessages[i].m_pText = nil;\n\t\t\t\tfor (; i < NUMBRIEFMESSAGES-1 && BriefMessages[i+1].m_pText != nil; i++) {\n\t\t\t\t\tBriefMessages[i] = BriefMessages[i + 1];\n\t\t\t\t}\n\t\t\t\tBriefMessages[i].m_pText = nil;\n\t\t\t} else {\n\t\t\t\tBriefMessages[0].m_pText = nil;\n\t\t\t\tfor (; i < NUMBRIEFMESSAGES-1 && BriefMessages[i+1].m_pText != nil; i++) {\n\t\t\t\t\tBriefMessages[i] = BriefMessages[i + 1];\n\t\t\t\t}\n\t\t\t\tBriefMessages[i].m_pText = nil;\n\t\t\t\tBriefMessages[0].m_nStartTime = CTimer::GetTimeInMilliseconds();\n\t\t\t\tif (BriefMessages[0].m_pText != nil)\n\t\t\t\t\tAddToPreviousBriefArray(\n\t\t\t\t\t\tBriefMessages[0].m_pText,\n\t\t\t\t\t\tBriefMessages[0].m_nNumber[0],\n\t\t\t\t\t\tBriefMessages[0].m_nNumber[1],\n\t\t\t\t\t\tBriefMessages[0].m_nNumber[2],\n\t\t\t\t\t\tBriefMessages[0].m_nNumber[3],\n\t\t\t\t\t\tBriefMessages[0].m_nNumber[4],\n\t\t\t\t\t\tBriefMessages[0].m_nNumber[5],\n\t\t\t\t\t\tBriefMessages[0].m_pString);\n\t\t\t}\n\t\t}\n\t} while (equal);\n}\n\nvoid\nCMessages::ClearThisBigPrint(wchar *str)\n{\n\tbool equal;\n\n\tdo {\n\t\tuint16 i = 0;\n\t\tequal = false;\n\t\tuint16 style = 0;\n\t\twhile (style < NUMBIGMESSAGES)\n\t\t{\n\t\t\tif (i >= 4)\n\t\t\t\tbreak;\n\n\t\t\tif (CMessages::BIGMessages[style].m_Stack[i].m_pText == nil || equal)\n\t\t\t\tbreak;\n\n\t\t\tequal = FastWideStringComparison(str, BIGMessages[style].m_Stack[i].m_pText);\n\n\t\t\tif (!equal && ++i == 4) {\n\t\t\t\ti = 0;\n\t\t\t\tstyle++;\n\t\t\t}\n\t\t}\n\t\tif (equal) {\n\t\t\tif (i != 0) {\n\t\t\t\tBIGMessages[style].m_Stack[i].m_pText = nil;\n\t\t\t\twhile (i < 3) {\n\t\t\t\t\tif (BIGMessages[style].m_Stack[i + 1].m_pText == nil)\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tBIGMessages[style].m_Stack[i] = BIGMessages[style].m_Stack[i + 1];\n\t\t\t\t\ti++;\n\t\t\t\t}\n\t\t\t\tBIGMessages[style].m_Stack[i].m_pText = nil;\n\t\t\t} else {\n\t\t\t\tBIGMessages[style].m_Stack[0].m_pText = nil;\n\t\t\t\ti = 0;\n\t\t\t\twhile (i < 3) {\n\t\t\t\t\tif (BIGMessages[style].m_Stack[i + 1].m_pText == nil)\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tBIGMessages[style].m_Stack[i] = BIGMessages[style].m_Stack[i + 1];\n\t\t\t\t\ti++;\n\t\t\t\t}\n\t\t\t\tBIGMessages[style].m_Stack[i].m_pText = nil;\n\t\t\t\tBIGMessages[style].m_Stack[0].m_nStartTime = CTimer::GetTimeInMilliseconds();\n\t\t\t}\n\t\t}\n\t} while (equal);\n}\n\nvoid\nCMessages::ClearAllMessagesDisplayedByGame()\n{\n\tClearMessages();\n\tfor (int32 i = 0; i < NUMPREVIOUSBRIEFS; i++) {\n\t\tPreviousBriefs[i].m_pText = nil;\n\t\tPreviousBriefs[i].m_pString = nil;\n\t}\n\tCHud::GetRidOfAllHudMessages();\n\tCUserDisplay::Pager.ClearMessages();\n}\n"
  },
  {
    "path": "src/text/Messages.h",
    "content": "#pragma once\n\nstruct tMessage \n{\n\twchar *m_pText;\n\tuint16 m_nFlag;\n\tuint32 m_nTime;\n\tuint32 m_nStartTime;\n\tint32 m_nNumber[6];\n\twchar *m_pString;\n};\n\nstruct tBigMessage \n{\n\ttMessage m_Stack[4];\n};\n\nstruct tPreviousBrief \n{\n\twchar *m_pText;\n\tint32 m_nNumber[6];\n\twchar *m_pString;\n};\n\n#define NUMBRIEFMESSAGES 8\n#define NUMBIGMESSAGES 6\n#define NUMPREVIOUSBRIEFS 5\n\nclass CMessages \n{\npublic:\n\tstatic tMessage BriefMessages[NUMBRIEFMESSAGES];\n\tstatic tBigMessage BIGMessages[NUMBIGMESSAGES];\n\tstatic tPreviousBrief PreviousBriefs[NUMPREVIOUSBRIEFS];\n\tstatic char PreviousMissionTitle[16]; // unused\npublic:\n\tstatic void Init(void);\n\tstatic uint16 GetWideStringLength(wchar *src);\n\tstatic void WideStringCopy(wchar *dst, wchar *src, uint16 size);\n\tstatic bool WideStringCompare(wchar *str1, wchar *str2, uint16 size);\n\tstatic void Process(void);\n\tstatic void Display(void);\n\tstatic void AddMessage(wchar *key, uint32 time, uint16 pos);\n\tstatic void AddMessageJumpQ(wchar *key, uint32 time, uint16 pos);\n\tstatic void AddMessageSoon(wchar *key, uint32 time, uint16 pos);\n\tstatic void ClearMessages(void);\n\tstatic void ClearSmallMessagesOnly(void);\n\tstatic void AddBigMessage(wchar *key, uint32 time, uint16 pos);\n\tstatic void AddBigMessageQ(wchar *key, uint32 time, uint16 pos);\n\tstatic void AddToPreviousBriefArray(wchar *text, int32 n1, int32 n2, int32 n3, int32 n4, int32 n5, int32 n6, wchar *string);\n\tstatic void InsertNumberInString(wchar *src, int32 n1, int32 n2, int32 n3, int32 n4, int32 n5, int32 n6, wchar *dst);\n\tstatic void InsertStringInString(wchar *str1, wchar *str2);\n\tstatic void InsertPlayerControlKeysInString(wchar *src);\n\tstatic void AddMessageWithNumber(wchar *key, uint32 time, uint16 pos, int32 n1, int32 n2, int32 n3, int32 n4, int32 n5, int32 n6);\n\tstatic void AddMessageJumpQWithNumber(wchar *key, uint32 time, uint16 pos, int32 n1, int32 n2, int32 n3, int32 n4, int32 n5, int32 n6);\n\tstatic void AddMessageSoonWithNumber(wchar *key, uint32 time, uint16 pos, int32 n1, int32 n2, int32 n3, int32 n4, int32 n5, int32 n6);\n\tstatic void AddBigMessageWithNumber(wchar *key, uint32 time, uint16 pos, int32 n1, int32 n2, int32 n3, int32 n4, int32 n5, int32 n6);\n\tstatic void AddBigMessageWithNumberQ(wchar *key, uint32 time, uint16 pos, int32 n1, int32 n2, int32 n3, int32 n4, int32 n5, int32 n6);\n\tstatic void AddMessageWithString(wchar *text, uint32 time, uint16 flag, wchar *str);\n\tstatic void AddMessageJumpQWithString(wchar *text, uint32 time, uint16 flag, wchar *str);\n\tstatic void ClearThisPrint(wchar *str);\n\tstatic void ClearThisBigPrint(wchar *str);\n\tstatic void ClearAllMessagesDisplayedByGame(void);\n\n\t// unused or cut\n\t//static void AddMessageSoonWithString(wchar*, uint32, uint16, wchar*);\n\t//static void CutString(int16, char*, char**);\n\t//static void PrintString(char*, int16, int16, int16);\n};\n"
  },
  {
    "path": "src/text/Pager.cpp",
    "content": "#include \"common.h\"\n\n#include \"Pager.h\"\n#include \"Timer.h\"\n#include \"Messages.h\"\n#include \"Hud.h\"\n#include \"Camera.h\"\n\nvoid\nCPager::Init()\n{\n\tClearMessages();\n\tm_nNumDisplayLetters = 8;\n}\n\nvoid\nCPager::Process()\n{\n\tif (m_messages[0].m_pText != nil && m_messages[0].m_nCurrentPosition >= (int32)m_messages[0].m_nStringLength) {\n\t\tm_messages[0].m_pText = nil;\n\t\tuint16 i = 0;\n\t\twhile (i < NUMPAGERMESSAGES-1) {\n\t\t\tif (m_messages[i + 1].m_pText == nil) break;\n\t\t\tm_messages[i] = m_messages[i + 1];\n\t\t\ti++;\n\t\t}\n\t\tm_messages[i].m_pText = nil;\n\t\tif (m_messages[0].m_pText != nil)\n\t\t\tCMessages::AddToPreviousBriefArray(\n\t\t\t\tm_messages[0].m_pText,\n\t\t\t\tm_messages[0].m_nNumber[0],\n\t\t\t\tm_messages[0].m_nNumber[1],\n\t\t\t\tm_messages[0].m_nNumber[2],\n\t\t\t\tm_messages[0].m_nNumber[3],\n\t\t\t\tm_messages[0].m_nNumber[4],\n\t\t\t\tm_messages[0].m_nNumber[5],\n\t\t\t\t0);\n\t}\n\tDisplay();\n\tif (m_messages[0].m_pText != nil) {\n\t\tif (TheCamera.m_WideScreenOn || !CHud::m_Wants_To_Draw_Hud || CHud::m_BigMessage[0][0] || CHud::m_BigMessage[2][0]) {\n\t\t\tRestartCurrentMessage();\n\t\t} else {\n\t\t\tif (CTimer::GetTimeInMilliseconds() > m_messages[0].m_nTimeToChangePosition) {\n\t\t\t\tm_messages[0].m_nCurrentPosition++;\n\t\t\t\tm_messages[0].m_nTimeToChangePosition = CTimer::GetTimeInMilliseconds() + m_messages[0].m_nSpeedMs;\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nCPager::Display()\n{\n\twchar outstr1[256];\n\twchar outstr2[260];\n\n\twchar *pText = m_messages[0].m_pText;\n\tuint16 i = 0;\n\tif (pText != nil) {\n\t\tCMessages::InsertNumberInString(\n\t\t\tpText,\n\t\t\tm_messages[0].m_nNumber[0],\n\t\t\tm_messages[0].m_nNumber[1],\n\t\t\tm_messages[0].m_nNumber[2],\n\t\t\tm_messages[0].m_nNumber[3],\n\t\t\tm_messages[0].m_nNumber[4],\n\t\t\tm_messages[0].m_nNumber[5],\n\t\t\toutstr1);\n\t\tfor (; i < m_nNumDisplayLetters; i++) {\n\t\t\tint pos = m_messages[0].m_nCurrentPosition + i;\n\t\t\tif (pos >= 0) {\n\t\t\t\tif (!outstr1[pos]) break;\n\n\t\t\t\toutstr2[i] = outstr1[pos];\n\t\t\t} else {\n\t\t\t\toutstr2[i] = ' ';\n\t\t\t}\n\t\t}\n\t}\n\toutstr2[i] = '\\0';\n\tCHud::SetPagerMessage(outstr2);\n}\n\nvoid\nCPager::AddMessage(wchar *str, uint16 speed, uint16 priority, uint16 a5)\n{\n\tuint16 size = CMessages::GetWideStringLength(str);\n\tfor (int32 i = 0; i < NUMPAGERMESSAGES; i++) {\n\t\tif (m_messages[i].m_pText) {\n\t\t\tif (m_messages[i].m_nPriority >= priority)\n\t\t\t\tcontinue;\n\n\t\t\tfor (int j = NUMPAGERMESSAGES-1; j > i; j--)\n\t\t\t\tm_messages[j] = m_messages[j-1];\n\n\t\t}\n\t\tm_messages[i].m_pText = str;\n\t\tm_messages[i].m_nSpeedMs = speed;\n\t\tm_messages[i].m_nPriority = priority;\n\t\tm_messages[i].unused = a5;\n\t\tm_messages[i].m_nCurrentPosition = -(m_nNumDisplayLetters + 10);\n\t\tm_messages[i].m_nTimeToChangePosition = CTimer::GetTimeInMilliseconds() + speed;\n\t\tm_messages[i].m_nStringLength = size;\n\t\tm_messages[i].m_nNumber[0] = -1;\n\t\tm_messages[i].m_nNumber[1] = -1;\n\t\tm_messages[i].m_nNumber[2] = -1;\n\t\tm_messages[i].m_nNumber[3] = -1;\n\t\tm_messages[i].m_nNumber[4] = -1;\n\t\tm_messages[i].m_nNumber[5] = -1;\n\n\t\tif (i == 0)\n\t\t\tCMessages::AddToPreviousBriefArray(\n\t\t\t\tm_messages[0].m_pText,\n\t\t\t\tm_messages[0].m_nNumber[0],\n\t\t\t\tm_messages[0].m_nNumber[1],\n\t\t\t\tm_messages[0].m_nNumber[2],\n\t\t\t\tm_messages[0].m_nNumber[3],\n\t\t\t\tm_messages[0].m_nNumber[4],\n\t\t\t\tm_messages[0].m_nNumber[5],\n\t\t\t\tnil);\n\t\t\treturn;\n\t}\n}\n\nvoid\nCPager::AddMessageWithNumber(wchar *str, int32 n1, int32 n2, int32 n3, int32 n4, int32 n5, int32 n6, uint16 speed, uint16 priority, uint16 a11)\n{\n\twchar nstr[520];\n\n\tCMessages::InsertNumberInString(str, n1, n2, n3, n4, n5, n6, nstr);\n\tuint16 size = CMessages::GetWideStringLength(nstr);\n\tfor (int32 i = 0; i < NUMPAGERMESSAGES; i++) {\n\t\tif (m_messages[i].m_pText) {\n\t\t\tif (m_messages[i].m_nPriority >= priority)\n\t\t\t\tcontinue;\n\n\t\t\tfor (int j = NUMPAGERMESSAGES-1; j > i; j--)\n\t\t\t\tm_messages[j] = m_messages[j - 1];\n\n\t\t}\n\t\tm_messages[i].m_pText = str;\n\t\tm_messages[i].m_nSpeedMs = speed;\n\t\tm_messages[i].m_nPriority = priority;\n\t\tm_messages[i].unused = a11;\n\t\tm_messages[i].m_nCurrentPosition = -(m_nNumDisplayLetters + 10);\n\t\tm_messages[i].m_nTimeToChangePosition = CTimer::GetTimeInMilliseconds() + speed;\n\t\tm_messages[i].m_nStringLength = size;\n\t\tm_messages[i].m_nNumber[0] = n1;\n\t\tm_messages[i].m_nNumber[1] = n2;\n\t\tm_messages[i].m_nNumber[2] = n3;\n\t\tm_messages[i].m_nNumber[3] = n4;\n\t\tm_messages[i].m_nNumber[4] = n5;\n\t\tm_messages[i].m_nNumber[5] = n6;\n\n\t\tif (i == 0)\n\t\t\tCMessages::AddToPreviousBriefArray(\n\t\t\t\tm_messages[0].m_pText,\n\t\t\t\tm_messages[0].m_nNumber[0],\n\t\t\t\tm_messages[0].m_nNumber[1],\n\t\t\t\tm_messages[0].m_nNumber[2],\n\t\t\t\tm_messages[0].m_nNumber[3],\n\t\t\t\tm_messages[0].m_nNumber[4],\n\t\t\t\tm_messages[0].m_nNumber[5],\n\t\t\t\tnil);\n\t\treturn;\n\t}\n}\n\nvoid\nCPager::ClearMessages()\n{\n\tfor (int32 i = 0; i < NUMPAGERMESSAGES; i++)\n\t\tm_messages[i].m_pText = nil;\n}\n\nvoid\nCPager::RestartCurrentMessage()\n{\n\tif (m_messages[0].m_pText != nil) {\n\t\tm_messages[0].m_nCurrentPosition = -(m_nNumDisplayLetters + 10);\n\t\tm_messages[0].m_nTimeToChangePosition = CTimer::GetTimeInMilliseconds() + m_messages[0].m_nSpeedMs;\n\t}\n}"
  },
  {
    "path": "src/text/Pager.h",
    "content": "#pragma once\n\nstruct PagerMessage {\n\twchar *m_pText;\n\tuint16 m_nSpeedMs;\n\tint16 m_nCurrentPosition;\n\tuint16 m_nStringLength;\n\tuint16 m_nPriority;\n\tuint32 m_nTimeToChangePosition;\n\tint16 unused; // but still set in SCM. importance? ringtone?\n\tint32 m_nNumber[6];\n};\n\n#define NUMPAGERMESSAGES 8\n\nclass CPager\n{\n\tint16 m_nNumDisplayLetters;\n\tPagerMessage m_messages[NUMPAGERMESSAGES];\npublic:\n\tvoid Init();\n\tvoid Process();\n\tvoid Display();\n\tvoid AddMessage(wchar*, uint16, uint16, uint16);\n\tvoid AddMessageWithNumber(wchar *str, int32 n1, int32 n2, int32 n3, int32 n4, int32 n5, int32 n6, uint16 speed, uint16 priority, uint16 a11);\n\tvoid ClearMessages();\n\tvoid RestartCurrentMessage();\n};"
  },
  {
    "path": "src/text/Text.cpp",
    "content": "#include \"common.h\"\n\n#include \"FileMgr.h\"\n#ifdef MORE_LANGUAGES\n#include \"Game.h\"\n#endif\n#include \"Frontend.h\"\n#include \"Messages.h\"\n#include \"Text.h\"\n#include \"Timer.h\"\n\nwchar WideErrorString[25];\n\nCText TheText;\n\nCText::CText(void)\n{\n\tencoding = 'e';\n\tbHasMissionTextOffsets = false;\n\tbIsMissionTextLoaded = false;\n\tmemset(szMissionTableName, 0, sizeof(szMissionTableName));\n\tmemset(WideErrorString, 0, sizeof(WideErrorString));\n}\n\nvoid\nCText::Load(void)\n{\n\tchar filename[32];\n\tsize_t offset;\n\tint file;\n\tbool tkey_loaded = false, tdat_loaded = false;\n\tChunkHeader m_ChunkHeader;\n\n\tbIsMissionTextLoaded = false;\n\tbHasMissionTextOffsets = false;\n\n\tUnload();\n\n\tCFileMgr::SetDir(\"TEXT\");\n\tswitch(FrontEndMenuManager.m_PrefsLanguage){\n\tcase CMenuManager::LANGUAGE_AMERICAN:\n\t\tsprintf(filename, \"AMERICAN.GXT\");\n\t\tbreak;\n\tcase CMenuManager::LANGUAGE_FRENCH:\n\t\tsprintf(filename, \"FRENCH.GXT\");\n\t\tbreak;\n\tcase CMenuManager::LANGUAGE_GERMAN:\n\t\tsprintf(filename, \"GERMAN.GXT\");\n\t\tbreak;\n\tcase CMenuManager::LANGUAGE_ITALIAN:\n\t\tsprintf(filename, \"ITALIAN.GXT\");\n\t\tbreak;\n\tcase CMenuManager::LANGUAGE_SPANISH:\n\t\tsprintf(filename, \"SPANISH.GXT\");\n\t\tbreak;\n#ifdef MORE_LANGUAGES\n\tcase CMenuManager::LANGUAGE_POLISH:\n\t\tsprintf(filename, \"POLISH.GXT\");\n\t\tbreak;\n\tcase CMenuManager::LANGUAGE_RUSSIAN:\n\t\tsprintf(filename, \"RUSSIAN.GXT\");\n\t\tbreak;\n\tcase CMenuManager::LANGUAGE_JAPANESE:\n\t\tsprintf(filename, \"JAPANESE.GXT\");\n\t\tbreak;\n#endif\n\t}\n\n\tfile = CFileMgr::OpenFile(filename, \"rb\");\n\n\toffset = 0;\n\twhile (!tkey_loaded || !tdat_loaded) {\n\t\tReadChunkHeader(&m_ChunkHeader, file, &offset);\n\t\tif (m_ChunkHeader.size != 0) {\n\t\t\tif (strncmp(m_ChunkHeader.magic, \"TABL\", 4) == 0) {\n\t\t\t\tMissionTextOffsets.Load(m_ChunkHeader.size, file, &offset, 0x58000);\n\t\t\t\tbHasMissionTextOffsets = true;\n\t\t\t} else if (strncmp(m_ChunkHeader.magic, \"TKEY\", 4) == 0) {\n\t\t\t\tthis->keyArray.Load(m_ChunkHeader.size, file, &offset);\n\t\t\t\ttkey_loaded = true;\n\t\t\t} else if (strncmp(m_ChunkHeader.magic, \"TDAT\", 4) == 0) {\n\t\t\t\tthis->data.Load(m_ChunkHeader.size, file, &offset);\n\t\t\t\ttdat_loaded = true;\n\t\t\t} else {\n\t\t\t\tCFileMgr::Seek(file, m_ChunkHeader.size, SEEK_CUR);\n\t\t\t\toffset += m_ChunkHeader.size;\n\t\t\t}\n\t\t}\n\t}\n\n\tkeyArray.Update(data.chars);\n\tCFileMgr::CloseFile(file);\n\tCFileMgr::SetDir(\"\");\n}\n\nvoid\nCText::Unload(void)\n{\n\tCMessages::ClearAllMessagesDisplayedByGame();\n\tkeyArray.Unload();\n\tdata.Unload();\n\tmission_keyArray.Unload();\n\tmission_data.Unload();\n\tbIsMissionTextLoaded = false;\n\tmemset(szMissionTableName, 0, sizeof(szMissionTableName));\n}\n\nwchar*\nCText::Get(const char *key)\n{\n\tuint8 result = false;\n#if defined (FIX_BUGS) || defined(FIX_BUGS_64)\n\twchar *outstr = keyArray.Search(key, data.chars, &result);\n#else\n\twchar *outstr = keyArray.Search(key, &result);\n#endif\n\n\tif (!result && bHasMissionTextOffsets && bIsMissionTextLoaded)\n#if defined (FIX_BUGS) || defined(FIX_BUGS_64)\n\t\toutstr = mission_keyArray.Search(key, mission_data.chars, &result);\n#else\n\t\toutstr = mission_keyArray.Search(key, &result);\n#endif\n\treturn outstr;\n}\n\nwchar UpperCaseTable[128] = {\n\t128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138,\n\t139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149,\n\t150, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137,\n\t138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148,\n\t149, 173, 173, 175, 176, 177, 178, 179, 180, 181, 182,\n\t183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193,\n\t194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204,\n\t205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215,\n\t216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226,\n\t227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237,\n\t238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248,\n\t249, 250, 251, 252, 253, 254, 255\n};\n\nwchar FrenchUpperCaseTable[128] = {\n\t128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138,\n\t139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149,\n\t150, 65, 65, 65, 65, 132, 133, 69, 69, 69, 69, 73, 73,\n\t73, 73, 79, 79, 79, 79, 85, 85, 85, 85, 173, 173, 175,\n\t176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186,\n\t187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197,\n\t198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208,\n\t209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219,\n\t220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230,\n\t231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241,\n\t242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252,\n\t253, 254, 255\n};\n\nwchar\nCText::GetUpperCase(wchar c)\n{\n\tswitch (encoding)\n\t{\n\tcase 'e':\n\t\tif (c >= 'a' && c <= 'z')\n\t\t\treturn c - 32;\n\t\tbreak;\n\tcase 'f':\n\t\tif (c >= 'a' && c <= 'z')\n\t\t\treturn c - 32;\n\n\t\tif (c >= 128 && c <= 255)\n\t\t\treturn FrenchUpperCaseTable[c-128];\n\t\tbreak;\n\tcase 'g':\n\tcase 'i':\n\tcase 's':\n\t\tif (c >= 'a' && c <= 'z')\n\t\t\treturn c - 32;\n\n\t\tif (c >= 128 && c <= 255)\n\t\t\treturn UpperCaseTable[c-128];\n\t\tbreak;\n\tdefault:\n\t\tbreak;\n\t}\n\treturn c;\n}\n\nvoid\nCText::UpperCase(wchar *s)\n{\n\twhile(*s){\n\t\t*s = GetUpperCase(*s);\n\t\ts++;\n\t}\n}\n\nvoid\nCText::GetNameOfLoadedMissionText(char *outName)\n{\n\tstrcpy(outName, szMissionTableName);\n}\n\nvoid\nCText::ReadChunkHeader(ChunkHeader *buf, int32 file, size_t *offset)\n{\n#ifdef THIS_IS_STUPID\n\tchar *_buf = (char*)buf;\n\tfor (int i = 0; i < sizeof(ChunkHeader); i++) {\n\t\tCFileMgr::Read(file, &_buf[i], 1);\n\t\t(*offset)++;\n\t}\n#else\n\t// original code loops 8 times to read 1 byte with CFileMgr::Read, that's retarded\n\tCFileMgr::Read(file, (char*)buf, sizeof(ChunkHeader));\n\t*offset += sizeof(ChunkHeader);\n#endif\n}\n\nvoid\nCText::LoadMissionText(char *MissionTableName)\n{\n\tchar filename[32];\n\tCMessages::ClearAllMessagesDisplayedByGame();\n\n\tmission_keyArray.Unload();\n\tmission_data.Unload();\n\n\tbool search_result = false;\n\tint missionTableId = 0;\n\n\tfor (missionTableId = 0; missionTableId < MissionTextOffsets.size; missionTableId++) {\n\t\tif (strncmp(MissionTextOffsets.data[missionTableId].szMissionName, MissionTableName, strlen(MissionTextOffsets.data[missionTableId].szMissionName)) == 0) {\n\t\t\tsearch_result = true;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tif (!search_result) {\n\t\tprintf(\"CText::LoadMissionText - couldn't find %s\", MissionTableName);\n\t\treturn;\n\t}\n\n\tCFileMgr::SetDir(\"TEXT\");\n\tswitch (FrontEndMenuManager.m_PrefsLanguage) {\n\tcase CMenuManager::LANGUAGE_AMERICAN:\n\t\tsprintf(filename, \"AMERICAN.GXT\");\n\t\tbreak;\n\tcase CMenuManager::LANGUAGE_FRENCH:\n\t\tsprintf(filename, \"FRENCH.GXT\");\n\t\tbreak;\n\tcase CMenuManager::LANGUAGE_GERMAN:\n\t\tsprintf(filename, \"GERMAN.GXT\");\n\t\tbreak;\n\tcase CMenuManager::LANGUAGE_ITALIAN:\n\t\tsprintf(filename, \"ITALIAN.GXT\");\n\t\tbreak;\n\tcase CMenuManager::LANGUAGE_SPANISH:\n\t\tsprintf(filename, \"SPANISH.GXT\");\n\t\tbreak;\n#ifdef MORE_LANGUAGES\n\tcase CMenuManager::LANGUAGE_POLISH:\n\t\tsprintf(filename, \"POLISH.GXT\");\n\t\tbreak;\n\tcase CMenuManager::LANGUAGE_RUSSIAN:\n\t\tsprintf(filename, \"RUSSIAN.GXT\");\n\t\tbreak;\n\tcase CMenuManager::LANGUAGE_JAPANESE:\n\t\tsprintf(filename, \"JAPANESE.GXT\");\n\t\tbreak;\n#endif\n\t}\n\tCTimer::Suspend();\n\tint file = CFileMgr::OpenFile(filename, \"rb\");\n\tCFileMgr::Seek(file, MissionTextOffsets.data[missionTableId].offset, SEEK_SET);\n\n\tchar TableCheck[8];\n\tCFileMgr::Read(file, TableCheck, 8);\n\tif (strncmp(TableCheck, MissionTableName, 8) != 0)\n\t\tprintf(\"CText::LoadMissionText - expected to find %s in the text file\", MissionTableName);\n\n\tbool tkey_loaded = false, tdat_loaded = false;\n\tChunkHeader m_ChunkHeader;\n\twhile (!tkey_loaded || !tdat_loaded) {\n\t\tsize_t bytes_read = 0;\n\t\tReadChunkHeader(&m_ChunkHeader, file, &bytes_read);\n\t\tif (m_ChunkHeader.size != 0) {\n\t\t\tif (strncmp(m_ChunkHeader.magic, \"TKEY\", 4) == 0) {\n\t\t\t\tsize_t bytes_read = 0;\n\t\t\t\tmission_keyArray.Load(m_ChunkHeader.size, file, &bytes_read);\n\t\t\t\ttkey_loaded = true;\n\t\t\t} else if (strncmp(m_ChunkHeader.magic, \"TDAT\", 4) == 0) {\n\t\t\t\tsize_t bytes_read = 0;\n\t\t\t\tmission_data.Load(m_ChunkHeader.size, file, &bytes_read);\n\t\t\t\ttdat_loaded = true;\n\t\t\t} else\n\t\t\t\tCFileMgr::Seek(file, m_ChunkHeader.size, SEEK_CUR);\n\t\t}\n\t}\n\n\tmission_keyArray.Update(mission_data.chars);\n\tCFileMgr::CloseFile(file);\n\tCTimer::Resume();\n\tCFileMgr::SetDir(\"\");\n\tstrcpy(szMissionTableName, MissionTableName);\n\tbIsMissionTextLoaded = true;\n}\n\n\nvoid\nCKeyArray::Load(size_t length, int file, size_t* offset)\n{\n\tchar *rawbytes;\n\n\t// You can make numEntries size_t if you want to exceed 32-bit boundaries, everything else should be ready.\n\tnumEntries = (int)(length / sizeof(CKeyEntry));\n\tentries = new CKeyEntry[numEntries];\n\trawbytes = (char*)entries;\n\n#ifdef THIS_IS_STUPID\n\tfor (uint32 i = 0; i < length; i++) {\n\t\tCFileMgr::Read(file, &rawbytes[i], 1);\n\t\t(*offset)++;\n\t}\n#else\n\tCFileMgr::Read(file, rawbytes, length);\n\t*offset += length;\n#endif\n}\n\nvoid\nCKeyArray::Unload(void)\n{\n\tdelete[] entries;\n\tentries = nil;\n\tnumEntries = 0;\n}\n\nvoid\nCKeyArray::Update(wchar *chars)\n{\n#if !defined(FIX_BUGS) && !defined(FIX_BUGS_64)\n\tint i;\n\tfor(i = 0; i < numEntries; i++)\n\t\tentries[i].value = (wchar*)((uint8*)chars + (uintptr)entries[i].value);\n#endif\n}\n\nCKeyEntry*\nCKeyArray::BinarySearch(const char *key, CKeyEntry *entries, int16 low, int16 high)\n{\n\tint mid;\n\tint diff;\n\n\tif(low > high)\n\t\treturn nil;\n\n\tmid = (low + high)/2;\n\tdiff = strcmp(key, entries[mid].key);\n\tif(diff == 0)\n\t\treturn &entries[mid];\n\tif(diff < 0)\n\t\treturn BinarySearch(key, entries, low, mid-1);\n\tif(diff > 0)\n\t\treturn BinarySearch(key, entries, mid+1, high);\n\treturn nil;\n}\n\nwchar*\n#if defined (FIX_BUGS) || defined(FIX_BUGS_64)\nCKeyArray::Search(const char *key, wchar *data, uint8 *result)\n#else\nCKeyArray::Search(const char *key, uint8 *result)\n#endif\n{\n\tCKeyEntry *found;\n\tchar errstr[25];\n\tint i;\n\n#if defined (FIX_BUGS) || defined(FIX_BUGS_64)\n\tfound = BinarySearch(key, entries, 0, numEntries-1);\n\tif (found) {\n\t\t*result = true;\n\t\treturn (wchar*)((uint8*)data + found->valueOffset);\n\t}\n#else\n\tfound = BinarySearch(key, entries, 0, numEntries-1);\n\tif (found) {\n\t\t*result = true;\n\t\treturn found->value;\n\t}\n#endif\n\t*result = false;\n#ifdef MASTER\n\tsprintf(errstr, \"\");\n#else\n\tsprintf(errstr, \"%s missing\", key);\n#endif // MASTER\n\tfor(i = 0; i < 25; i++)\n\t\tWideErrorString[i] = errstr[i];\n\treturn WideErrorString;\n}\n\nvoid\nCData::Load(size_t length, int file, size_t * offset)\n{\n\tchar *rawbytes;\n\n\t// You can make numChars size_t if you want to exceed 32-bit boundaries, everything else should be ready.\n\tnumChars = (int)(length / sizeof(wchar));\n\tchars = new wchar[numChars];\n\trawbytes = (char*)chars;\n\n#ifdef THIS_IS_STUPID\n\tfor(uint32 i = 0; i < length; i++){\n\t\tCFileMgr::Read(file, &rawbytes[i], 1);\n\t\t(*offset)++;\n\t}\n#else\n\tCFileMgr::Read(file, rawbytes, length);\n\t*offset += length;\n#endif\n}\n\nvoid\nCData::Unload(void)\n{\n\tdelete[] chars;\n\tchars = nil;\n\tnumChars = 0;\n}\n\nvoid\nCMissionTextOffsets::Load(size_t table_size, int file, size_t *offset, int)\n{\n#ifdef THIS_IS_STUPID\n\tsize_t num_of_entries = table_size / sizeof(CMissionTextOffsets::Entry);\n\tfor (size_t mi = 0; mi < num_of_entries; mi++) {\n\t\tfor (uint32 i = 0; i < sizeof(data[mi].szMissionName); i++) {\n\t\t\tCFileMgr::Read(file, &data[i].szMissionName[i], 1);\n\t\t\t(*offset)++;\n\t\t}\n\t\tchar* _buf = (char*)&data[mi].offset;\n\t\tfor (uint32 i = 0; i < sizeof(data[mi].offset); i++) {\n\t\t\tCFileMgr::Read(file, &_buf[i], 1);\n\t\t\t(*offset)++;\n\t\t}\n\t}\n\tsize = (uint16)num_of_entries;\n#else\n\t// not exact VC code but smaller and better :P\n\n\t// You can make this size_t if you want to exceed 32-bit boundaries, everything else should be ready.\n\tsize = (uint16) (table_size / sizeof(CMissionTextOffsets::Entry));\n\tCFileMgr::Read(file, (char*)data, sizeof(CMissionTextOffsets::Entry) * size);\n\t*offset += sizeof(CMissionTextOffsets::Entry) * size;\n#endif\n}\n\nchar*\nUnicodeToAscii(wchar *src)\n{\n\tstatic char aStr[256];\n\tint len;\n\tfor(len = 0; *src != '\\0' && len < 256-1; len++, src++)\n#ifdef MORE_LANGUAGES\n\t\tif(*src < 128 || ((CGame::russianGame || CGame::japaneseGame) && *src < 256))\n#else\n\t\tif(*src < 128)\n#endif\n\t\t\taStr[len] = *src;\n\t\t// convert to CP1252\n\t\telse if(*src <= 131)\n\t\t\taStr[len] = *src + 64;\n\t\telse if (*src <= 141)\n\t\t\taStr[len] = *src + 66;\n\t\telse if (*src <= 145)\n\t\t\taStr[len] = *src + 68;\n\t\telse if (*src <= 149)\n\t\t\taStr[len] = *src + 71;\n\t\telse if (*src <= 154)\n\t\t\taStr[len] = *src + 73;\n\t\telse if (*src <= 164)\n\t\t\taStr[len] = *src + 75;\n\t\telse if (*src <= 168)\n\t\t\taStr[len] = *src + 77;\n\t\telse if (*src <= 204)\n\t\t\taStr[len] = *src + 80;\n\t\telse switch (*src) {\n\t\tcase 205: aStr[len] = 209; break;\n\t\tcase 206: aStr[len] = 241; break;\n\t\tcase 207: aStr[len] = 191; break;\n\t\tdefault: aStr[len] = '#'; break;\n\t\t}\n\taStr[len] = '\\0';\n\treturn aStr;\n}\n\nchar*\nUnicodeToAsciiForSaveLoad(wchar *src)\n{\n\tstatic char aStr[256];\n\tint len;\n\tfor(len = 0; *src != '\\0' && len < 256; len++, src++)\n\t\tif(*src < 256)\n\t\t\taStr[len] = *src;\n\t\telse\n\t\t\taStr[len] = '#';\n\taStr[len] = '\\0';\n\treturn aStr;\n}\n\nchar*\nUnicodeToAsciiForMemoryCard(wchar *src)\n{\n\tstatic char aStr[256];\n\tint len;\n\tfor(len = 0; *src != '\\0' && len < 256; len++, src++)\n\t\tif(*src < 256)\n\t\t\taStr[len] = *src;\n\t\telse\n\t\t\taStr[len] = '#';\n\taStr[len] = '\\0';\n\treturn aStr;\n}\n\nvoid\nTextCopy(wchar *dst, const wchar *src)\n{\n\twhile((*dst++ = *src++) != '\\0');\n}\n"
  },
  {
    "path": "src/text/Text.h",
    "content": "#pragma once\n\nchar *UnicodeToAscii(wchar *src);\nchar *UnicodeToAsciiForSaveLoad(wchar *src);\nchar *UnicodeToAsciiForMemoryCard(wchar *src);\nvoid TextCopy(wchar *dst, const wchar *src);\n\nstruct CKeyEntry\n{\n#if defined(FIX_BUGS) || defined(FIX_BUGS_64)\n\tuint32 valueOffset;\n#else\n\twchar *value;\n#endif\n\tchar key[8];\n};\n\n// If this fails, CKeyArray::Load will have to be fixed\nVALIDATE_SIZE(CKeyEntry, 12);\n\nclass CKeyArray\n{\npublic:\n\tCKeyEntry *entries;\n\tint numEntries;\t// You can make this size_t if you want to exceed 32-bit boundaries, everything else should be ready.\n\n\tCKeyArray(void) : entries(nil), numEntries(0) {}\n\t~CKeyArray(void) { Unload(); }\n\tvoid Load(size_t length, int file, size_t *offset);\n\tvoid Unload(void);\n\tvoid Update(wchar *chars);\n\tCKeyEntry *BinarySearch(const char *key, CKeyEntry *entries, int16 low, int16 high);\n#if defined (FIX_BUGS) || defined(FIX_BUGS_64)\n\twchar *Search(const char *key, wchar *data, uint8 *result);\n#else\n\twchar *Search(const char *key, uint8* result);\n#endif\n};\n\nclass CData\n{\npublic:\n\twchar *chars;\n\tint numChars; // You can make this size_t if you want to exceed 32-bit boundaries, everything else should be ready.\n\n\tCData(void) : chars(nil), numChars(0) {}\n\t~CData(void) { Unload(); }\n\tvoid Load(size_t length, int file, size_t* offset);\n\tvoid Unload(void);\n};\n\nclass CMissionTextOffsets\n{\npublic:\n\tstruct Entry\n\t{\n\t\tchar szMissionName[8];\n\t\tuint32 offset;\n\t};\n\n\tenum {MAX_MISSION_TEXTS = 90}; // beware that LCS has more\n\n\tEntry data[MAX_MISSION_TEXTS];\n\tuint16 size; // You can make this size_t if you want to exceed 32-bit boundaries, everything else should be ready.\n\n\tCMissionTextOffsets(void) : size(0) {}\n\tvoid Load(size_t table_size, int file, size_t* bytes_read, int);\n};\n\nstruct ChunkHeader\n{\n\tchar magic[4];\n\tint size;\n};\n\nclass CText\n{\n\tCKeyArray keyArray;\n\tCData data;\n\tCKeyArray mission_keyArray;\n\tCData mission_data;\n\tchar encoding;\n\tbool bHasMissionTextOffsets;\n\tbool bIsMissionTextLoaded;\n\tchar szMissionTableName[8];\n\tCMissionTextOffsets MissionTextOffsets;\npublic:\n\tCText(void);\n\tvoid Load(void);\n\tvoid Unload(void);\n\twchar *Get(const char *key);\n\twchar GetUpperCase(wchar c);\n\tvoid UpperCase(wchar *s);\n\tvoid GetNameOfLoadedMissionText(char *outName);\n\tvoid ReadChunkHeader(ChunkHeader *buf, int32 file, size_t *bytes_read);\n\tvoid LoadMissionText(char *MissionTableName);\n};\n\nextern CText TheText;\n"
  },
  {
    "path": "src/vehicles/Automobile.cpp",
    "content": "#include \"common.h\"\n#include \"main.h\"\n\n#include \"General.h\"\n#include \"RwHelper.h\"\n#include \"Pad.h\"\n#include \"ModelIndices.h\"\n#include \"VisibilityPlugins.h\"\n#include \"DMAudio.h\"\n#include \"Clock.h\"\n#include \"Timecycle.h\"\n#include \"ZoneCull.h\"\n#include \"Camera.h\"\n#include \"Darkel.h\"\n#include \"Rubbish.h\"\n#include \"Fire.h\"\n#include \"Explosion.h\"\n#include \"Particle.h\"\n#include \"ParticleObject.h\"\n#include \"Glass.h\"\n#include \"Antennas.h\"\n#include \"Skidmarks.h\"\n#include \"WindModifiers.h\"\n#include \"Shadows.h\"\n#include \"PointLights.h\"\n#include \"Coronas.h\"\n#include \"SpecialFX.h\"\n#include \"WaterCannon.h\"\n#include \"WaterLevel.h\"\n#include \"Floater.h\"\n#include \"World.h\"\n#include \"SurfaceTable.h\"\n#include \"Weather.h\"\n#include \"HandlingMgr.h\"\n#include \"Record.h\"\n#include \"Remote.h\"\n#include \"Population.h\"\n#include \"CarCtrl.h\"\n#include \"CarAI.h\"\n#include \"Stats.h\"\n#include \"Garages.h\"\n#include \"PathFind.h\"\n#include \"Replay.h\"\n#include \"AnimManager.h\"\n#include \"RpAnimBlend.h\"\n#include \"AnimBlendAssociation.h\"\n#include \"Ped.h\"\n#include \"PlayerPed.h\"\n#include \"Object.h\"\n#include \"Automobile.h\"\n#include \"Bike.h\"\n#include \"Wanted.h\"\n\nbool bAllCarCheat;\n\nRwObject *GetCurrentAtomicObjectCB(RwObject *object, void *data);\n\nbool CAutomobile::m_sAllTaxiLights;\n\nconst uint32 CAutomobile::nSaveStructSize =\n#ifdef COMPATIBLE_SAVES\n\t1500;\n#else\n\tsizeof(CAutomobile);\n#endif\n\nCAutomobile::CAutomobile(int32 id, uint8 CreatedBy)\n : CVehicle(CreatedBy)\n{\n\tint i;\n\n\tm_vehType = VEHICLE_TYPE_CAR;\n\n\tCVehicleModelInfo *mi = (CVehicleModelInfo*)CModelInfo::GetModelInfo(id);\n\tm_fFireBlowUpTimer = 0.0f;\n\tm_doingBurnout = 0;\n\tbTaxiLight = m_sAllTaxiLights;\n\tbFixedColour = false;\n\tbBigWheels = false;\n\tbWaterTight = false;\n\n\tSetModelIndex(id);\n\n\t// Already done in CVehicle...\n\tswitch(GetModelIndex()){\n\tcase MI_HUNTER:\n\tcase MI_ANGEL:\n\tcase MI_FREEWAY:\n\t\tm_nRadioStation = V_ROCK;\n\t\tbreak;\n\tcase MI_RCBARON:\n\tcase MI_RCBANDIT:\n\tcase MI_RCRAIDER:\n\tcase MI_RCGOBLIN:\n\tcase MI_TOPFUN:\n\tcase MI_CADDY:\n\tcase MI_BAGGAGE:\n\t\tm_nRadioStation = RADIO_OFF;\n\t\tbreak;\n\t}\n\n\tpHandling = mod_HandlingManager.GetHandlingData((tVehicleType)mi->m_handlingId);\n\tpFlyingHandling =  mod_HandlingManager.GetFlyingPointer((tVehicleType)mi->m_handlingId);\n\n\tm_auto_unused1 = 20.0f;\n\tm_auto_unused2 = 0;\n\n\tmi->ChooseVehicleColour(m_currentColour1, m_currentColour2);\n\n\tbIsVan = !!(pHandling->Flags & HANDLING_IS_VAN);\n\tbIsBig = !!(pHandling->Flags & HANDLING_IS_BIG);\n\tbIsBus = !!(pHandling->Flags & HANDLING_IS_BUS);\n\tbLowVehicle = !!(pHandling->Flags & HANDLING_IS_LOW);\n\n\t// Doors\n\tif(bIsBus){\n\t\tDoors[DOOR_FRONT_LEFT].Init(-HALFPI, 0.0f, 0, 2);\n\t\tDoors[DOOR_FRONT_RIGHT].Init(0.0f, HALFPI, 1, 2);\n\t}else{\n\t\tDoors[DOOR_FRONT_LEFT].Init(-PI*0.4f, 0.0f, 0, 2);\n\t\tDoors[DOOR_FRONT_RIGHT].Init(0.0f, PI*0.4f, 1, 2);\n\t}\n\tif(bIsVan){\n\t\tDoors[DOOR_REAR_LEFT].Init(-HALFPI, 0.0f, 1, 2);\n\t\tDoors[DOOR_REAR_RIGHT].Init(0.0f, HALFPI, 0, 2);\n\t}else{\n\t\tDoors[DOOR_REAR_LEFT].Init(-PI*0.4f, 0.0f, 0, 2);\n\t\tDoors[DOOR_REAR_RIGHT].Init(0.0f, PI*0.4f, 1, 2);\n\t}\n\tif(pHandling->Flags & HANDLING_REV_BONNET)\n\t\tDoors[DOOR_BONNET].Init(-PI*0.3f, 0.0f, 1, 0);\n\telse\n\t\tDoors[DOOR_BONNET].Init(0.0f, PI*0.3f, 1, 0);\n\tif(pHandling->Flags & HANDLING_HANGING_BOOT)\n\t\tDoors[DOOR_BOOT].Init(-PI*0.4f, 0.0f, 0, 0);\n\telse if(pHandling->Flags & HANDLING_TAILGATE_BOOT)\n\t\tDoors[DOOR_BOOT].Init(0.0, HALFPI, 1, 0);\n\telse\n\t\tDoors[DOOR_BOOT].Init(-PI*0.3f, 0.0f, 1, 0);\n\tif(pHandling->Flags & HANDLING_NO_DOORS){\n\t\tDamage.SetDoorStatus(DOOR_FRONT_LEFT, DOOR_STATUS_MISSING);\n\t\tDamage.SetDoorStatus(DOOR_FRONT_RIGHT, DOOR_STATUS_MISSING);\n\t\tDamage.SetDoorStatus(DOOR_REAR_LEFT, DOOR_STATUS_MISSING);\n\t\tDamage.SetDoorStatus(DOOR_REAR_RIGHT, DOOR_STATUS_MISSING);\n\t}\n\n\tfor(i = 0; i < 6; i++)\n\t\tm_randomValues[i] = CGeneral::GetRandomNumberInRange(-0.15f, 0.15f);\n\n\tm_fMass = pHandling->fMass;\n\tm_fTurnMass = pHandling->fTurnMass;\n\tm_vecCentreOfMass = pHandling->CentreOfMass;\n\tm_fAirResistance = pHandling->Dimension.x*pHandling->Dimension.z/m_fMass;\n\tm_fElasticity = 0.05f;\n\tm_fBuoyancy = pHandling->fBuoyancy;\n\n\tm_fOrientation = m_fPlaneSteer = 0.0f;\n\n\tm_nBusDoorTimerEnd = 0;\n\tm_nBusDoorTimerStart = 0;\n\n\tm_fSteerAngle = 0.0f;\n\tm_fGasPedal = 0.0f;\n\tm_fBrakePedal = 0.0f;\n\tm_pSetOnFireEntity = nil;\n\tm_fGasPedalAudio = 0.0f;\n\tbNotDamagedUpsideDown = false;\n\tbMoreResistantToDamage = false;\n\tbTankDetonateCars = true;\n\tbStuckInSand = false;\n\tbHeliDestroyed = false;\n\tm_fVelocityChangeForAudio = 0.0f;\n\tm_hydraulicState = 0;\n\n\tfor(i = 0; i < 4; i++){\n\t\tm_aGroundPhysical[i] = nil;\n\t\tm_aGroundOffset[i] = CVector(0.0f, 0.0f, 0.0f);\n\t\tm_aSuspensionSpringRatioPrev[i] = m_aSuspensionSpringRatio[i] = 1.0f;\n\t\tm_aWheelTimer[i] = 0.0f;\n\t\tm_aWheelRotation[i] = 0.0f;\n\t\tm_aWheelSpeed[i] = 0.0f;\n\t\tm_aWheelState[i] = WHEEL_STATE_NORMAL;\n\t\tm_aWheelSkidmarkType[i] = SKIDMARK_NORMAL;\n\t\tm_aWheelSkidmarkBloody[i] = false;\n\t}\n\n\tm_nWheelsOnGround = 0;\n\tm_nDriveWheelsOnGround = 0;\n\tm_nDriveWheelsOnGroundPrev = 0;\n\tm_fHeightAboveRoad = 0.0f;\n\tm_fTraction = 1.0f;\n\tm_fTireTemperature = 1.0f;\n\n\tCColModel *colModel = mi->GetColModel();\n\tif(colModel->lines == nil){\n\t\tcolModel->lines = (CColLine*)RwMalloc(4*sizeof(CColLine));\n\t\tcolModel->numLines = 4;\n\t}\n\n\tSetupSuspensionLines();\n\n\tSetStatus(STATUS_SIMPLE);\n\tbUseCollisionRecords = true;\n\n\tm_nNumPassengers = 0;\n\n\tif(m_nDoorLock == CARLOCK_UNLOCKED &&\n\t   (id == MI_POLICE || id == MI_ENFORCER || id == MI_RHINO))\n\t\tm_nDoorLock = CARLOCK_LOCKED_INITIALLY;\n\n\tm_fCarGunLR = 0.0f;\n\tm_fCarGunUD = 0.05f;\n\tm_fPropellerRotation = 0.0f;\n\tm_fHeliOrientation = -1.0f;\n\tm_weaponDoorTimerLeft = 0.0f;\n\tm_weaponDoorTimerRight = m_weaponDoorTimerLeft;\n\n\tif(GetModelIndex() == MI_DODO){\n\t\tRpAtomicSetFlags((RpAtomic*)GetFirstObject(m_aCarNodes[CAR_WHEEL_LF]), 0);\n\t\tCMatrix mat1;\n\t\tmat1.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_RF]));\n\t\tCMatrix mat2(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_LF]));\n\t\tmat1.GetPosition() += CVector(mat2.GetPosition().x + 0.1f, 0.0f, mat2.GetPosition().z);\n\t\tmat1.UpdateRW();\n\t}else if(GetModelIndex() == MI_HUNTER){\n\t\tRpAtomicSetFlags((RpAtomic*)GetFirstObject(m_aCarNodes[CAR_WHEEL_LB]), 0);\n\t\tRpAtomicSetFlags((RpAtomic*)GetFirstObject(m_aCarNodes[CAR_WHEEL_RB]), 0);\n\t}else if(IsRealHeli()){\n\t\tRpAtomicSetFlags((RpAtomic*)GetFirstObject(m_aCarNodes[CAR_WHEEL_LF]), 0);\n\t\tRpAtomicSetFlags((RpAtomic*)GetFirstObject(m_aCarNodes[CAR_WHEEL_RF]), 0);\n\t\tRpAtomicSetFlags((RpAtomic*)GetFirstObject(m_aCarNodes[CAR_WHEEL_LB]), 0);\n\t\tRpAtomicSetFlags((RpAtomic*)GetFirstObject(m_aCarNodes[CAR_WHEEL_RB]), 0);\n\t}else if(GetModelIndex() == MI_RHINO){\n\t\tbExplosionProof = true;\n\t\tbBulletProof = true;\n\t}\n}\n\nvoid\nCAutomobile::SetModelIndex(uint32 id)\n{\n\tCVehicle::SetModelIndex(id);\n\tSetupModelNodes();\n}\n\n#define SAND_SLOWDOWN (0.01f)\nfloat CAR_BALANCE_MULT = 0.3f;\nCVector vecSeaSparrowGunPos(-0.5f, 2.4f, -0.785f);\nCVector vecHunterGunPos(0.0f, 4.8f, -1.3f);\nCVector vecHunterRocketPos(2.5f, 1.0f, -0.5f);\nCVector vecDAMAGE_ENGINE_POS_SMALL(-0.1f, -0.1f, 0.0f);\nCVector vecDAMAGE_ENGINE_POS_BIG(-0.5f, -0.3f, 0.0f);\n\n#pragma optimize(\"\", off) // a workaround for another compiler bug\n\nvoid\nCAutomobile::ProcessControl(void)\n{\n\tint i;\n\tfloat wheelRot;\n\tCColModel *colModel;\n\tfloat brake = 0.0f;\n\n\tif(bUsingSpecialColModel)\n\t\tcolModel = &CWorld::Players[CWorld::PlayerInFocus].m_ColModel;\n\telse\n\t\tcolModel = GetColModel();\n\tbool drivingInSand = false;\n\tbWarnedPeds = false;\n\tm_doingBurnout = 0;\n\tbStuckInSand = false;\n\tbRestingOnPhysical = false;\n\n\tbool carHasNitro = bAllTaxisHaveNitro && GetStatus() == STATUS_PLAYER && IsTaxi();\n\n\tif(CReplay::IsPlayingBack())\n\t\treturn;\n\n\t// Heli wind\n\tif(IsRealHeli())\n\t\tif((GetStatus() == STATUS_PLAYER || GetStatus() == STATUS_PHYSICS) && m_aWheelSpeed[1] > 0.075f ||\n\t\t   GetStatus() == STATUS_SIMPLE)\n\t\t\tCWindModifiers::RegisterOne(GetPosition(), 1);\n\n\tUpdatePassengerList();\n\n\t// Improve grip of vehicles in certain cases\n\tbool strongGrip1 = false;\n\tbool strongGrip2 = false;\n\tif(FindPlayerVehicle() && this != FindPlayerVehicle() && FindPlayerPed()->m_pWanted->GetWantedLevel() > 3 &&\n\t   (AutoPilot.m_nCarMission == MISSION_RAMPLAYER_FARAWAY || AutoPilot.m_nCarMission == MISSION_RAMPLAYER_CLOSE ||\n\t    AutoPilot.m_nCarMission == MISSION_BLOCKPLAYER_FARAWAY || AutoPilot.m_nCarMission == MISSION_BLOCKPLAYER_CLOSE) &&\n\t\tFindPlayerSpeed().Magnitude() > 0.3f){\n\n\t\tstrongGrip1 = true;\n\t\tif(FindPlayerSpeed().Magnitude() > 0.4f &&\n\t\t\tm_vecMoveSpeed.Magnitude() < 0.3f)\n\t\t\tstrongGrip2 = true;\n\t\telse if((GetPosition() - FindPlayerCoors()).Magnitude() > 50.0f)\n\t\t\tstrongGrip2 = true;\n\t}else if(GetModelIndex() == MI_RCBANDIT && GetStatus() != STATUS_PLAYER_REMOTE)\n\t\tstrongGrip1 = true;\n\n\tif(bIsBus)\n\t\tProcessAutoBusDoors();\n\n\tProcessCarAlarm();\n\n\t// Scan if this car sees the player committing any crimes\n\tif(GetStatus() != STATUS_ABANDONED && GetStatus() != STATUS_WRECKED &&\n\t   GetStatus() != STATUS_PLAYER && GetStatus() != STATUS_PLAYER_REMOTE && GetStatus() != STATUS_PLAYER_DISABLED){\n\t\tswitch(GetModelIndex())\n\t\tcase MI_FBIRANCH:\n\t\tcase MI_POLICE:\n\t\tcase MI_ENFORCER:\n\t\tcase MI_SECURICA:\n\t\tcase MI_RHINO:\n\t\tcase MI_BARRACKS:\n\t\t\tScanForCrimes();\n\t}\n\n\t// Process driver\n\tif(pDriver)\n\t\tif(IsUpsideDown() && CanPedEnterCar()){\n\t\t\tif(!pDriver->IsPlayer() &&\n\t\t\t   !(pDriver->m_leader && pDriver->m_leader->bInVehicle) &&\n\t\t\t   pDriver->CharCreatedBy != MISSION_CHAR)\n\t\t\t\tpDriver->SetObjective(OBJECTIVE_LEAVE_CAR, this);\n\t\t}\n\n\tActivateBombWhenEntered();\n\n\t// Process passengers\n\tif(m_nNumPassengers != 0 && IsUpsideDown() && CanPedEnterCar()){\n\t\tfor(i = 0; i < m_nNumMaxPassengers; i++)\n\t\t\tif(pPassengers[i])\n\t\t\t\tif(!pPassengers[i]->IsPlayer() &&\n\t\t\t\t   !(pPassengers[i]->m_leader && pPassengers[i]->m_leader->bInVehicle) &&\n\t\t\t\t   pPassengers[i]->CharCreatedBy != MISSION_CHAR)\n\t\t\t\t\tpPassengers[i]->SetObjective(OBJECTIVE_LEAVE_CAR, this);\n\t}\n\n\tCRubbish::StirUp(this);\n\n\tUpdateClumpAlpha();\n\n\tAutoPilot.m_bSlowedDownBecauseOfCars = false;\n\tAutoPilot.m_bSlowedDownBecauseOfPeds = false;\n\n\t// Set Center of Mass to make car more stable\n\tif(strongGrip1 || bCheat3)\n\t\tm_vecCentreOfMass.z = 0.3f*m_aSuspensionSpringLength[0] + -1.0f*m_fHeightAboveRoad;\n\telse if(pHandling->Flags & HANDLING_NONPLAYER_STABILISER && GetStatus() == STATUS_PHYSICS)\n\t\tm_vecCentreOfMass.z = pHandling->CentreOfMass.z - 0.2f*pHandling->Dimension.z;\n\telse\n\t\tm_vecCentreOfMass = pHandling->CentreOfMass;\n\n\t// Park car\n\tif(bCanPark && !bParking && VehicleCreatedBy != MISSION_VEHICLE && AutoPilot.m_nCarMission == MISSION_CRUISE &&\n\t   ((CTimer::GetFrameCounter() + m_randomSeed)&0xF) == 0 && !IsTaxi()){\n\t\tCVector parkPosition = GetPosition() + 3.0f*GetRight() + 10.0f*GetForward();\n\t\tCEntity *ent = nil;\n\t\tCColPoint colpoint;\n\t\tif(!CWorld::ProcessLineOfSight(GetPosition(), parkPosition, colpoint, ent, true, true, true, false, false, false) ||\n\t\t   ent == this)\n\t\t\tCCarAI::GetCarToParkAtCoors(this, &parkPosition);\n\t}\n\n\t// Process depending on status\n\n\tbool playerRemote = false;\n\tswitch(GetStatus()){\n\tcase STATUS_PLAYER_REMOTE:\n#ifdef FIX_BUGS\n\t\tif(CPad::GetPad(0)->CarGunJustDown() && !bDisableRemoteDetonation){\n#else\n\t\tif(CPad::GetPad(0)->WeaponJustDown() && !bDisableRemoteDetonation){\n#endif\n\t\t\tBlowUpCar(FindPlayerPed());\n\t\t\tCRemote::TakeRemoteControlledCarFromPlayer();\n\t\t}\n\n\t\tif(GetModelIndex() == MI_RCBANDIT && !bDisableRemoteDetonationOnContact){\n\t\t\t//CVector pos = GetPosition();\n\t\t\t// FindPlayerCoors unused\n\t\t\tif(RcbanditCheckHitWheels() || bIsInWater){\n\t\t\t\tCRemote::TakeRemoteControlledCarFromPlayer();\n\t\t\t\tBlowUpCar(FindPlayerPed());\n\t\t\t}\n\t\t}\n\n\t\tif(CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle == this)\n\t\t\tplayerRemote = true;\n\t\t// fall through\n\tcase STATUS_PLAYER:\n\t\tif(playerRemote ||\n\t\t   pDriver && pDriver->GetPedState() != PED_EXIT_CAR && pDriver->GetPedState() != PED_DRAG_FROM_CAR && pDriver->GetPedState() != PED_ARRESTED){\n\t\t\t// process control input if controlled by player\n\t\t\tif(playerRemote || pDriver->m_nPedType == PEDTYPE_PLAYER1)\n\t\t\t\tProcessControlInputs(0);\n\n\t\t\tPruneReferences();\n\n\t\t\tif(GetStatus() == STATUS_PLAYER && !CRecordDataForChase::IsRecording())\n\t\t\t\tDoDriveByShootings();\n\n\t\t\t// Tweak center on mass when driving on two wheels\n\t\t\tint twoWheelTime = CWorld::Players[CWorld::PlayerInFocus].m_nTimeNotFullyOnGround;\n\t\t\tif(twoWheelTime > 500 && !IsRealHeli() && !IsRealPlane()){\n\t\t\t\tfloat tweak = Min(twoWheelTime-500, 1000)/500.0f;\n\t\t\t\tif(GetUp().z > 0.0f){\n\t\t\t\t\t// positive when on left wheels, negative on right wheels\n\t\t\t\t\tif(GetRight().z <= 0.0f)\n\t\t\t\t\t\ttweak *= -1.0f;\n\t\t\t\t\tm_vecCentreOfMass.z = pHandling->CentreOfMass.z +\n\t\t\t\t\t\tCPad::GetPad(0)->GetSteeringLeftRight()/128.0f *\n\t\t\t\t\t\tCAR_BALANCE_MULT * tweak * colModel->boundingBox.max.z;\n\t\t\t\t}\n\t\t\t}else\n\t\t\t\tm_vecCentreOfMass.z = pHandling->CentreOfMass.z;\n\n\t\t\tif(bHoverCheat)\n\t\t\t\tDoHoverSuspensionRatios();\n\n\t\t\tif(m_aSuspensionSpringRatio[0] < 1.0f && CSurfaceTable::GetAdhesionGroup(m_aWheelColPoints[0].surfaceB) == ADHESIVE_SAND ||\n\t\t\t   m_aSuspensionSpringRatio[1] < 1.0f && CSurfaceTable::GetAdhesionGroup(m_aWheelColPoints[1].surfaceB) == ADHESIVE_SAND ||\n\t\t\t   m_aSuspensionSpringRatio[2] < 1.0f && CSurfaceTable::GetAdhesionGroup(m_aWheelColPoints[2].surfaceB) == ADHESIVE_SAND ||\n\t\t\t   m_aSuspensionSpringRatio[3] < 1.0f && CSurfaceTable::GetAdhesionGroup(m_aWheelColPoints[3].surfaceB) == ADHESIVE_SAND){\n\t\t\t\tif(GetModelIndex() != MI_RCBANDIT && GetModelIndex() != MI_RHINO){\n\t\t\t\t\tfloat slowdown;\n\t\t\t\t\tCVector parallelSpeed = m_vecMoveSpeed - DotProduct(m_vecMoveSpeed, GetUp())*GetUp();\n\t\t\t\t\tfloat fSpeed = parallelSpeed.MagnitudeSqr();\n\t\t\t\t\tif(fSpeed > SQR(0.3f)){\n\t\t\t\t\t\tfSpeed = Sqrt(fSpeed);\n\t\t\t\t\t\tparallelSpeed *= 0.3f / fSpeed;\n\t\t\t\t\t\tslowdown = SAND_SLOWDOWN * Max(1.0f - 2.0f*fSpeed, 0.2f);\n\t\t\t\t\t}else{\n\t\t\t\t\t\tbStuckInSand = true;\n\t\t\t\t\t\tslowdown = SAND_SLOWDOWN;\n\t\t\t\t\t}\n\t\t\t\t\tif(pHandling->Flags & HANDLING_GOOD_INSAND)\n\t\t\t\t\t\tslowdown *= 0.5f;\n\t\t\t\t\tif(CWeather::WetRoads > 0.2f)\n\t\t\t\t\t\tslowdown *= (1.2f - CWeather::WetRoads);\n\t\t\t\t\tApplyMoveForce(parallelSpeed * -CTimer::GetTimeStep()*slowdown*m_fMass);\n\t\t\t\t\tdrivingInSand = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}else if(pDriver && pDriver->IsPlayer() &&\n\t\t         (pDriver->GetPedState() == PED_ARRESTED ||\n\t\t          pDriver->GetPedState() == PED_DRAG_FROM_CAR ||\n\t\t          (pDriver->GetPedState() == PED_EXIT_CAR || pDriver->m_objective == OBJECTIVE_LEAVE_CAR) && !CanPedJumpOutCar())){\n\t\t\tbIsHandbrakeOn = true;\n\t\t\tm_fBrakePedal = 1.0f;\n\t\t\tm_fGasPedal = 0.0f;\n\t\t}\n\t\tif(CPad::GetPad(0)->CarGunJustDown())\n\t\t\tActivateBomb();\n\t\tbreak;\n\n\tcase STATUS_SIMPLE:\n\t\tCCarAI::UpdateCarAI(this);\n\t\tCPhysical::ProcessControl();\n\t\tCCarCtrl::UpdateCarOnRails(this);\n\n\t\tm_nWheelsOnGround = 4;\n\t\tm_nDriveWheelsOnGroundPrev = m_nDriveWheelsOnGround;\n\t\tm_nDriveWheelsOnGround = 4;\n\n\t\tpHandling->Transmission.CalculateGearForSimpleCar(AutoPilot.m_fMaxTrafficSpeed/50.0f, m_nCurrentGear);\n\n\t\twheelRot = ProcessWheelRotation(WHEEL_STATE_NORMAL, GetForward(), m_vecMoveSpeed, 0.35f);\n\t\tfor(i = 0; i < 4; i++)\n\t\t\tm_aWheelRotation[i] += wheelRot;\n\n\t\tPlayHornIfNecessary();\n\t\tReduceHornCounter();\n\t\tbVehicleColProcessed = false;\n\t\tbAudioChangingGear = false;\n\t\t// that's all we do for simple vehicles\n\t\treturn;\n\n\tcase STATUS_PHYSICS:\n\t\tCCarAI::UpdateCarAI(this);\n\t\tCCarCtrl::SteerAICarWithPhysics(this);\n\t\tPlayHornIfNecessary();\n\n\t\tif(bIsBeingCarJacked){\n\t\t\tm_fGasPedal = 0.0f;\n\t\t\tm_fBrakePedal = 1.0f;\n\t\t\tbIsHandbrakeOn = true;\n\t\t}\n\n\t\tif(m_aSuspensionSpringRatio[0] < 1.0f && CSurfaceTable::GetAdhesionGroup(m_aWheelColPoints[0].surfaceB) == ADHESIVE_SAND ||\n\t\t   m_aSuspensionSpringRatio[1] < 1.0f && CSurfaceTable::GetAdhesionGroup(m_aWheelColPoints[1].surfaceB) == ADHESIVE_SAND ||\n\t\t   m_aSuspensionSpringRatio[2] < 1.0f && CSurfaceTable::GetAdhesionGroup(m_aWheelColPoints[2].surfaceB) == ADHESIVE_SAND ||\n\t\t   m_aSuspensionSpringRatio[3] < 1.0f && CSurfaceTable::GetAdhesionGroup(m_aWheelColPoints[3].surfaceB) == ADHESIVE_SAND){\n\t\t\tif(GetModelIndex() != MI_RCBANDIT && GetModelIndex() != MI_SANDKING && GetModelIndex() != MI_BFINJECT){\n\t\t\t\tbStuckInSand = true;\n\t\t\t\tif(CWeather::WetRoads > 0.0f)\n\t\t\t\t\tApplyMoveForce(m_vecMoveSpeed * -CTimer::GetTimeStep()*SAND_SLOWDOWN*m_fMass * (1.0f-CWeather::WetRoads));\n\t\t\t\telse\n\t\t\t\t\tApplyMoveForce(m_vecMoveSpeed * -CTimer::GetTimeStep()*SAND_SLOWDOWN*m_fMass);\n\t\t\t}\n\t\t}\n\t\tbreak;\n\n\tcase STATUS_ABANDONED:\n\t\tif(m_vecMoveSpeed.MagnitudeSqr() < SQR(0.1f))\n\t\t\tm_fBrakePedal = 0.2f;\n\t\telse\n\t\t\tm_fBrakePedal = 0.0f;\n\t\tbIsHandbrakeOn = false;\n\n\t\tm_fSteerAngle = 0.0f;\n\t\tm_fGasPedal = 0.0f;\n\t\tif(!IsAlarmOn())\n\t\t\tm_nCarHornTimer = 0;\n\n\t\tif(bIsBeingCarJacked){\n\t\t\tm_fGasPedal = 0.0f;\n\t\t\tm_fBrakePedal = 1.0f;\n\t\t\tbIsHandbrakeOn = true;\n\t\t}\n\t\tbreak;\n\n\tcase STATUS_WRECKED:\n\t\tm_fBrakePedal = 0.05f;\n\t\tbIsHandbrakeOn = true;\n\n\t\tm_fSteerAngle = 0.0f;\n\t\tm_fGasPedal = 0.0f;\n\t\tif(!IsAlarmOn())\n\t\t\tm_nCarHornTimer = 0;\n\t\tbreak;\n\n\tcase STATUS_PLAYER_DISABLED:\n\t\tif(m_vecMoveSpeed.MagnitudeSqr() < SQR(0.1f) ||\n\t\t   (pDriver && pDriver->IsPlayer() &&\n\t\t    (pDriver->GetPedState() == PED_ARRESTED ||\n\t\t     pDriver->GetPedState() == PED_DRAG_FROM_CAR ||\n\t\t     (pDriver->GetPedState() == PED_EXIT_CAR || pDriver->m_objective == OBJECTIVE_LEAVE_CAR) && !CanPedJumpOutCar()))){\n\t\t\tbIsHandbrakeOn = true;\n\t\t\tm_fBrakePedal = 1.0f;\n\t\t\tm_fGasPedal = 0.0f;\n\t\t}else{\n\t\t\tm_fBrakePedal = 0.0f;\n\t\t\tbIsHandbrakeOn = false;\n\t\t}\n\n\t\tm_fSteerAngle = 0.0f;\n\t\tm_fGasPedal = 0.0f;\n\t\tif(!IsAlarmOn())\n\t\t\tm_nCarHornTimer = 0;\n\t\tbreak;\n\tdefault: break;\n\t}\n\n\t// Skip physics if object is found to have been static recently\n\tbool skipPhysics = false;\n\tif(!bIsStuck && (GetStatus() == STATUS_ABANDONED || GetStatus() == STATUS_WRECKED)){\n\t\tbool makeStatic = false;\n\t\tfloat moveSpeedLimit, turnSpeedLimit, distanceLimit;\n\n\t\tif(!bVehicleColProcessed &&\n\t\t   m_vecMoveSpeed.IsZero() &&\n\t\t// BUG? m_aSuspensionSpringRatioPrev[3] is checked twice in the game. also, why 3?\n\t\t   m_aSuspensionSpringRatioPrev[3] != 1.0f)\n\t\t\tmakeStatic = true;\n\n\t\tif(GetStatus() == STATUS_WRECKED){\n\t\t\tmoveSpeedLimit = 0.006f;\n\t\t\tturnSpeedLimit = 0.0015f;\n\t\t\tdistanceLimit = 0.015f;\n\t\t}else{\n\t\t\tmoveSpeedLimit = 0.003f;\n\t\t\tturnSpeedLimit = 0.0009f;\n\t\t\tdistanceLimit = 0.005f;\n\t\t}\n\n\t\tm_vecMoveSpeedAvg = (m_vecMoveSpeedAvg + m_vecMoveSpeed)/2.0f;\n\t\tm_vecTurnSpeedAvg = (m_vecTurnSpeedAvg + m_vecTurnSpeed)/2.0f;\n\n\t\tif(m_vecMoveSpeedAvg.MagnitudeSqr() <= sq(moveSpeedLimit*CTimer::GetTimeStep()) &&\n\t\t   m_vecTurnSpeedAvg.MagnitudeSqr() <= sq(turnSpeedLimit*CTimer::GetTimeStep()) &&\n\t\t   m_fDistanceTravelled < distanceLimit &&\n\t\t   !(m_fDamageImpulse > 0.0f && m_pDamageEntity && m_pDamageEntity->IsPed()) ||\n\t\t   makeStatic){\n\t\t\tm_nStaticFrames++;\n\n\t\t\tif(m_nStaticFrames > 10 || makeStatic)\n\t\t\t\tif(!CCarCtrl::MapCouldMoveInThisArea(GetPosition().x, GetPosition().y)){\n\t\t\t\t\tif(!makeStatic || m_nStaticFrames > 10)\n\t\t\t\t\t\tm_nStaticFrames = 10;\n\n\t\t\t\t\tskipPhysics = true;\n\n\t\t\t\t\tm_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);\n\t\t\t\t\tm_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f);\n\t\t\t\t}\n\t\t}else\n\t\t\tm_nStaticFrames = 0;\n\t\tif(IsRealHeli() && m_aWheelSpeed[1] > 0.0f){\n\t\t\tskipPhysics = false;\n\t\t\tm_nStaticFrames = 0;\n\t\t}\n\t}\n\n\t// Postpone\n\tfor(i = 0; i < 4; i++)\n\t\tif(m_aGroundPhysical[i]){\n\t\t\tbRestingOnPhysical = true;\n\t\t\tif(!CWorld::bForceProcessControl && m_aGroundPhysical[i]->bIsInSafePosition){\n\t\t\t\tbWasPostponed = true;\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\tif(bRestingOnPhysical){\n\t\tskipPhysics = false;\n\t\tm_nStaticFrames = 0;\n\t}\n\n\tVehicleDamage(0.0f, 0);\n\n\t// special control\n\tswitch(GetModelIndex()){\n\tcase MI_FIRETRUCK:\n\t\tFireTruckControl();\n\t\tbreak;\n\tcase MI_RHINO:\n\t\tTankControl();\n\t\tBlowUpCarsInPath();\n\t\tbreak;\n\tcase MI_VOODOO:\n\t\tHydraulicControl();\n\t\tbreak;\n\tdefault:\n\t\tif(CVehicle::bCheat3 || carHasNitro){\n\t\t\t// Make vehicle jump when horn is sounded\n\t\t\tif(GetStatus() == STATUS_PLAYER && m_vecMoveSpeed.MagnitudeSqr() > sq(0.2f) &&\n\t\t\t// BUG: game checks [0] four times, instead of all wheels\n\t\t\t   m_aSuspensionSpringRatio[0] < 1.0f &&\n\t\t\t   CPad::GetPad(0)->HornJustDown()){\n\n\t\t\t\tDMAudio.PlayOneShot(m_audioEntityId, SOUND_CAR_HYDRAULIC_1, 0.0f);\n\t\t\t\tDMAudio.PlayOneShot(m_audioEntityId, SOUND_CAR_JUMP, 1.0f);\n\n\t\t\t\tCParticle::AddParticle(PARTICLE_ENGINE_STEAM,\n\t\t\t\t\tm_aWheelColPoints[0].point + 0.5f*GetUp(),\n\t\t\t\t\t1.3f*m_vecMoveSpeed, nil, 2.5f);\n\t\t\t\tCParticle::AddParticle(PARTICLE_ENGINE_SMOKE,\n\t\t\t\t\tm_aWheelColPoints[0].point + 0.5f*GetUp(),\n\t\t\t\t\t1.2f*m_vecMoveSpeed, nil, 2.0f);\n\n\t\t\t\tCParticle::AddParticle(PARTICLE_ENGINE_STEAM,\n\t\t\t\t\tm_aWheelColPoints[2].point + 0.5f*GetUp(),\n\t\t\t\t\t1.3f*m_vecMoveSpeed, nil, 2.5f);\n\t\t\t\tCParticle::AddParticle(PARTICLE_ENGINE_SMOKE,\n\t\t\t\t\tm_aWheelColPoints[2].point + 0.5f*GetUp(),\n\t\t\t\t\t1.2f*m_vecMoveSpeed, nil, 2.0f);\n\n\t\t\t\tCParticle::AddParticle(PARTICLE_ENGINE_STEAM,\n\t\t\t\t\tm_aWheelColPoints[0].point + 0.5f*GetUp() - GetForward(),\n\t\t\t\t\t1.3f*m_vecMoveSpeed, nil, 2.5f);\n\t\t\t\tCParticle::AddParticle(PARTICLE_ENGINE_SMOKE,\n\t\t\t\t\tm_aWheelColPoints[0].point + 0.5f*GetUp() - GetForward(),\n\t\t\t\t\t1.2f*m_vecMoveSpeed, nil, 2.0f);\n\n\t\t\t\tCParticle::AddParticle(PARTICLE_ENGINE_STEAM,\n\t\t\t\t\tm_aWheelColPoints[2].point + 0.5f*GetUp() - GetForward(),\n\t\t\t\t\t1.3f*m_vecMoveSpeed, nil, 2.5f);\n\t\t\t\tCParticle::AddParticle(PARTICLE_ENGINE_SMOKE,\n\t\t\t\t\tm_aWheelColPoints[2].point + 0.5f*GetUp() - GetForward(),\n\t\t\t\t\t1.2f*m_vecMoveSpeed, nil, 2.0f);\n\n\t\t\t\tApplyMoveForce(CVector(0.0f, 0.0f, 1.0f)*m_fMass*0.4f);\n\t\t\t\tApplyTurnForce(GetUp()*m_fTurnMass*0.01f, GetForward()*1.0f);\n\t\t\t}\n\t\t}\n\t\tbreak;\n\t}\n\n\tif(GetStatus() == STATUS_PHYSICS || GetStatus() == STATUS_SIMPLE)\n\t\tif(AutoPilot.m_nCarMission == MISSION_HELI_FLYTOCOORS ||\n\t\t   AutoPilot.m_nCarMission == MISSION_PLANE_FLYTOCOORS)\n\t\t\tskipPhysics = true;\n\n\tif(skipPhysics){\n\t\tbHasContacted = false;\n\t\tbIsInSafePosition = false;\n\t\tbWasPostponed = false;\n\t\tbHasHitWall = false;\n\t\tm_nCollisionRecords = 0;\n\t\tbHasCollided = false;\n\t\tbVehicleColProcessed = false;\n\t\tbAudioChangingGear = false;\n\t\tm_nDamagePieceType = 0;\n\t\tm_fDamageImpulse = 0.0f;\n\t\tm_pDamageEntity = nil;\n\t\tm_vecTurnFriction = CVector(0.0f, 0.0f, 0.0f);\n\t\tm_vecMoveFriction = CVector(0.0f, 0.0f, 0.0f);\n\t\tm_fTireTemperature = 1.0f;\n\t}else{\n\n\t\t// This has to be done if ProcessEntityCollision wasn't called\n\t\tif(!bVehicleColProcessed){\n\t\t\tCMatrix mat(GetMatrix());\n\t\t\tbIsStuck = false;\n\t\t\tbHasContacted = false;\n\t\t\tbIsInSafePosition = false;\n\t\t\tbWasPostponed = false;\n\t\t\tbHasHitWall = false;\n\t\t\tm_fDistanceTravelled = 0.0f;\n\t\t\tm_bIsVehicleBeingShifted = false;\n\t\t\tbSkipLineCol = false;\n\t\t\tApplyMoveSpeed();\n\t\t\tApplyTurnSpeed();\n\t\t\tfor(i = 0; CheckCollision() && i < 5; i++){\n\t\t\t\tGetMatrix() = mat;\n\t\t\t\tApplyMoveSpeed();\n\t\t\t\tApplyTurnSpeed();\n\t\t\t}\n\t\t\tbIsInSafePosition = true;\n\t\t\tbIsStuck = false;\t\t\t\n\t\t}\n\n\t\tCPhysical::ProcessControl();\n\n\t\tProcessBuoyancy();\n\n\t\t// Rescale spring ratios, i.e. subtract wheel radius\n\t\tfor(i = 0; i < 4; i++){\n\t\t\t// wheel radius in relation to suspension line\n\t\t\tfloat wheelRadius = 1.0f - m_aSuspensionSpringLength[i]/m_aSuspensionLineLength[i];\n\t\t\t// rescale such that 0.0 is fully compressed and 1.0 is fully extended\n\t\t\tm_aSuspensionSpringRatio[i] = (m_aSuspensionSpringRatio[i]-wheelRadius)/(1.0f-wheelRadius);\n\t\t}\n\n\t\tfloat fwdSpeed = Abs(DotProduct(m_vecMoveSpeed, GetForward()));\n\t\tCVector contactPoints[4];\t// relative to model\n\t\tCVector contactSpeeds[4];\t// speed at contact points\n\t\tCVector springDirections[4];\t// normalized, in world space\n\n\t\tfor(i = 0; i < 4; i++){\n\t\t\t// Set spring under certain circumstances\n\t\t\tif(Damage.GetWheelStatus(i) == WHEEL_STATUS_MISSING)\n\t\t\t\tm_aSuspensionSpringRatio[i] = 1.0f;\n\t\t\telse if(Damage.GetWheelStatus(i) == WHEEL_STATUS_BURST){\n\t\t\t\t// wheel more bumpy the faster we are\n\t\t\t\tif(CGeneral::GetRandomNumberInRange(0, (uint16)(40*fwdSpeed) + 98) < 100){\n\t\t\t\t\tm_aSuspensionSpringRatio[i] += 0.3f*(m_aSuspensionLineLength[i]-m_aSuspensionSpringLength[i])/m_aSuspensionSpringLength[i];\n\t\t\t\t\tif(m_aSuspensionSpringRatio[i] > 1.0f)\n\t\t\t\t\t\tm_aSuspensionSpringRatio[i] = 1.0f;\n\t\t\t\t}\n\t\t\t}else if(CSurfaceTable::GetAdhesionGroup(m_aWheelColPoints[i].surfaceB) == ADHESIVE_SAND &&\n\t\t\t         GetModelIndex() != MI_RHINO){\n\t\t\t\tfwdSpeed *= 0.7f;\n\t\t\t\tfloat f = 1.0f - fwdSpeed/0.3f - 0.7f*CWeather::WetRoads;\n\t\t\t\tf = Max(f, 0.4f);\n\t\t\t\tm_aSuspensionSpringRatio[i] += 0.35f*f*(m_aSuspensionLineLength[i]-m_aSuspensionSpringLength[i])/m_aSuspensionSpringLength[i];\n\t\t\t\tif(m_aSuspensionSpringRatio[i] > 1.0f)\n\t\t\t\t\tm_aSuspensionSpringRatio[i] = 1.0f;\n\t\t\t}\n\n\t\t\t// get points and directions if spring is compressed\n\t\t\tif(m_aSuspensionSpringRatio[i] < 1.0f){\n\t\t\t\tcontactPoints[i] = m_aWheelColPoints[i].point - GetPosition();\n\t\t\t\tspringDirections[i] = Multiply3x3(GetMatrix(), colModel->lines[i].p1 - colModel->lines[i].p0);\n\t\t\t\tspringDirections[i].Normalise();\n\t\t\t}\n\t\t}\n\n\t\t// Make springs push up vehicle\n\t\tfor(i = 0; i < 4; i++){\n\t\t\tif(m_aSuspensionSpringRatio[i] < 1.0f){\n\t\t\t\tfloat bias = pHandling->fSuspensionBias;\n\t\t\t\tif(i == CARWHEEL_REAR_LEFT || i == CARWHEEL_REAR_RIGHT)\n\t\t\t\t\tbias = 1.0f - bias;\n\n\t\t\t\tApplySpringCollisionAlt(pHandling->fSuspensionForceLevel,\n\t\t\t\t\tspringDirections[i], contactPoints[i],\n\t\t\t\t\tm_aSuspensionSpringRatio[i], bias, m_aWheelColPoints[i].normal);\n\n\t\t\t\tm_aWheelSkidmarkUnk[i] = false;\n\t\t\t\tif(m_aWheelColPoints[i].surfaceB == SURFACE_GRASS ||\n\t\t\t\t   m_aWheelColPoints[i].surfaceB == SURFACE_MUD_DRY)\n\t\t\t\t\tm_aWheelSkidmarkType[i] = SKIDMARK_MUDDY;\n\t\t\t\telse if(m_aWheelColPoints[i].surfaceB == SURFACE_SAND ||\n\t\t\t\t        m_aWheelColPoints[i].surfaceB == SURFACE_SAND_BEACH){\n\t\t\t\t\tm_aWheelSkidmarkType[i] = SKIDMARK_SANDY;\n\t\t\t\t\tm_aWheelSkidmarkUnk[i] = true;\n\t\t\t\t}else\n\t\t\t\t\tm_aWheelSkidmarkType[i] = SKIDMARK_NORMAL;\n\t\t\t}else{\n\t\t\t\tcontactPoints[i] = Multiply3x3(GetMatrix(), colModel->lines[i].p1);\n\t\t\t}\n\t\t}\n\n\t\t// Get speed at contact points\n\t\tfor(i = 0; i < 4; i++){\n\t\t\tcontactSpeeds[i] = GetSpeed(contactPoints[i]);\n\t\t\tif(m_aGroundPhysical[i]){\n\t\t\t\t// subtract movement of physical we're standing on\n\t\t\t\tcontactSpeeds[i] -= m_aGroundPhysical[i]->GetSpeed(m_aGroundOffset[i]);\n#ifndef FIX_BUGS\n\t\t\t\t// this shouldn't be reset because we still need it below\n\t\t\t\tm_aGroundPhysical[i] = nil;\n#endif\n\t\t\t}\n\t\t\tif(m_aSuspensionSpringRatio[i] < 1.0f && m_aWheelColPoints[i].normal.z > 0.35f)\n\t\t\t\tspringDirections[i] = -m_aWheelColPoints[i].normal;\n\t\t}\n\n\t\t// dampen springs\n\t\tfor(i = 0; i < 4; i++)\n\t\t\tif(m_aSuspensionSpringRatio[i] < 0.99999f)\n\t\t\t\tApplySpringDampening(pHandling->fSuspensionDampingLevel,\n\t\t\t\t\tspringDirections[i], contactPoints[i], contactSpeeds[i]);\n\n\t\t// Get speed at contact points again\n\t\tfor(i = 0; i < 4; i++){\n\t\t\tcontactSpeeds[i] = GetSpeed(contactPoints[i]);\n\t\t\tif(m_aGroundPhysical[i]){\n\t\t\t\t// subtract movement of physical we're standing on\n\t\t\t\tcontactSpeeds[i] -= m_aGroundPhysical[i]->GetSpeed(m_aGroundOffset[i]);\n\t\t\t\tm_aGroundPhysical[i] = nil;\n\t\t\t}\n\t\t}\n\n\t\tbool gripCheat = true;\n\t\tfwdSpeed = DotProduct(m_vecMoveSpeed, GetForward());\n\t\tif(!strongGrip1 && !CVehicle::bCheat3)\n\t\t\tgripCheat = false;\n\t\tfloat acceleration = pHandling->Transmission.CalculateDriveAcceleration(m_fGasPedal, m_nCurrentGear, m_fChangeGearTime, fwdSpeed, gripCheat);\n\t\tacceleration /= m_fForceMultiplier;\n\n\t\tif(IsRealHeli() || IsRealPlane())\n\t\t\tacceleration = 0.0f;\n\n\t\tif(bAudioChangingGear && m_fGasPedal > 0.4f && m_fBrakePedal < 0.1f && fwdSpeed > 0.15f &&\n\t\t   this == FindPlayerVehicle() && TheCamera.Cams[TheCamera.ActiveCam].Mode != CCam::MODE_1STPERSON){\n\t\t\tif(GetStatus() == STATUS_PLAYER && !(pHandling->Flags & HANDLING_IS_BUS)){\n\t\t\t\tif(m_nBusDoorTimerEnd == 0)\n\t\t\t\t\tm_nBusDoorTimerEnd = 1000;\n\t\t\t\telse {\n\t\t\t\t\tuint32 timeStepInMs = CTimer::GetTimeStepInMilliseconds();\n\t\t\t\t\tif(m_nBusDoorTimerEnd > timeStepInMs)\n\t\t\t\t\t\tm_nBusDoorTimerEnd -= timeStepInMs;\n\t\t\t\t\telse\n\t\t\t\t\t\tm_nBusDoorTimerEnd = 0;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif((m_aSuspensionSpringRatio[0] < 1.0f || m_aSuspensionSpringRatio[2] < 1.0f) &&\n\t\t\t   (m_aSuspensionSpringRatio[1] < 1.0f || m_aSuspensionSpringRatio[3] < 1.0f))\n\t\t\t\tApplyTurnForce(-GRAVITY*Min(m_fTurnMass, 2500.0f)*GetUp(), -1.0f*GetForward());\n\t\t}\n\n\t\tbrake = m_fBrakePedal * pHandling->fBrakeDeceleration * CTimer::GetTimeStep();\n\t\tbool neutralHandling = GetStatus() != STATUS_PLAYER && GetStatus() != STATUS_PLAYER_REMOTE && (pHandling->Flags & HANDLING_NEUTRALHANDLING);\n\t\tfloat brakeBiasFront = neutralHandling ? 1.0f : 2.0f*pHandling->fBrakeBias;\n\t\tfloat brakeBiasRear  = neutralHandling ? 1.0f : 2.0f-pHandling->fBrakeBias;\t// looks like a bug, but it was correct in III...\n\t\tfloat tractionBiasFront = neutralHandling ? 1.0f : 2.0f*pHandling->fTractionBias;\n\t\tfloat tractionBiasRear  = neutralHandling ? 1.0f : 2.0f-tractionBiasFront;\n\n\t\t// Count how many wheels are touching the ground\n\n\t\tm_nWheelsOnGround = 0;\n\t\tm_nDriveWheelsOnGroundPrev = m_nDriveWheelsOnGround;\n\t\tm_nDriveWheelsOnGround = 0;\n\n\t\tfor(i = 0; i < 4; i++){\n\t\t\tif(m_aSuspensionSpringRatio[i] < 1.0f)\n\t\t\t\tm_aWheelTimer[i] = 4.0f;\n\t\t\telse\n\t\t\t\tm_aWheelTimer[i] = Max(m_aWheelTimer[i]-CTimer::GetTimeStep(), 0.0f);\n\n\t\t\tif(m_aWheelTimer[i] > 0.0f){\n\t\t\t\tm_nWheelsOnGround++;\n\t\t\t\tswitch(pHandling->Transmission.nDriveType){\n\t\t\t\tcase '4':\n\t\t\t\t\tm_nDriveWheelsOnGround++;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'F':\n\t\t\t\t\tif(i == CARWHEEL_FRONT_LEFT || i == CARWHEEL_FRONT_RIGHT)\n\t\t\t\t\t\tm_nDriveWheelsOnGround++;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'R':\n\t\t\t\t\tif(i == CARWHEEL_REAR_LEFT || i == CARWHEEL_REAR_RIGHT)\n\t\t\t\t\t\tm_nDriveWheelsOnGround++;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfloat traction;\n\t\tif(GetStatus() == STATUS_PHYSICS)\n\t\t\ttraction = 0.004f * m_fTraction;\n\t\telse\n\t\t\ttraction = 0.004f;\n\t\ttraction *= pHandling->fTractionMultiplier / 4.0f;\n\t\ttraction /= m_fForceMultiplier;\n\t\tif(CVehicle::bCheat3)\n\t\t\ttraction *= 4.0f;\n\n\t\tif(FindPlayerVehicle() != this && (strongGrip1 || CVehicle::bCheat3)){\n\t\t\ttraction *= 1.2f;\n\t\t\tacceleration *= 1.4f;\n\t\t\tif(strongGrip2 || CVehicle::bCheat3){\n\t\t\t\ttraction *= 1.3f;\n\t\t\t\tacceleration *= 1.4f;\n\t\t\t}\n\t\t}\n\n\t\tstatic float fThrust;\n\t\tstatic tWheelState WheelState[4];\n\n\t\tbool rearWheelsFirst = !!(pHandling->Flags & HANDLING_REARWHEEL_1ST);\n\n\t\t// Process front wheels on ground - first try\n\n\t\tif(!rearWheelsFirst){\n\t\tif(m_aWheelTimer[CARWHEEL_FRONT_LEFT] > 0.0f || m_aWheelTimer[CARWHEEL_FRONT_RIGHT] > 0.0f){\n\t\t\tfloat s = Sin(m_fSteerAngle);\n\t\t\tfloat c = Cos(m_fSteerAngle);\n\n\t\t\tCVector wheelFwd, wheelRight, tmp;\n\n\t\t\tif(m_aWheelTimer[CARWHEEL_FRONT_LEFT] > 0.0f){\n\t\t\t\tif(mod_HandlingManager.HasFrontWheelDrive(pHandling->nIdentifier))\n\t\t\t\t\tfThrust = acceleration;\n\t\t\t\telse\n\t\t\t\t\tfThrust = 0.0f;\n\n\t\t\t\twheelFwd = GetForward();\n\t\t\t\twheelFwd -= DotProduct(wheelFwd, m_aWheelColPoints[CARWHEEL_FRONT_LEFT].normal)*m_aWheelColPoints[CARWHEEL_FRONT_LEFT].normal;\n\t\t\t\twheelFwd.Normalise();\n\t\t\t\twheelRight = CrossProduct(wheelFwd, m_aWheelColPoints[CARWHEEL_FRONT_LEFT].normal);\n\t\t\t\twheelRight.Normalise();\n\t\t\t\ttmp = c*wheelFwd - s*wheelRight;\n\t\t\t\twheelRight = s*wheelFwd + c*wheelRight;\n\t\t\t\twheelFwd = tmp;\n\n\t\t\t\tm_aWheelColPoints[CARWHEEL_FRONT_LEFT].surfaceA = SURFACE_WHEELBASE;\n\t\t\t\tfloat adhesion = CSurfaceTable::GetAdhesiveLimit(m_aWheelColPoints[CARWHEEL_FRONT_LEFT])*traction;\n\t\t\t\tif(GetStatus() == STATUS_PLAYER)\n\t\t\t\t\tadhesion *= CSurfaceTable::GetWetMultiplier(m_aWheelColPoints[CARWHEEL_FRONT_LEFT].surfaceB);\n\t\t\t\tWheelState[CARWHEEL_FRONT_LEFT] = m_aWheelState[CARWHEEL_FRONT_LEFT];\n\n\t\t\t\tif(Damage.GetWheelStatus(CARWHEEL_FRONT_LEFT) == WHEEL_STATUS_BURST)\n\t\t\t\t\tProcessWheel(wheelFwd, wheelRight,\n\t\t\t\t\t\tcontactSpeeds[CARWHEEL_FRONT_LEFT], contactPoints[CARWHEEL_FRONT_LEFT],\n\t\t\t\t\t\tm_nWheelsOnGround, fThrust,\n\t\t\t\t\t\tbrake*brakeBiasFront,\n\t\t\t\t\t\tadhesion*tractionBiasFront*Damage.m_fWheelDamageEffect,\n\t\t\t\t\t\tCARWHEEL_FRONT_LEFT,\n\t\t\t\t\t\t&m_aWheelSpeed[CARWHEEL_FRONT_LEFT],\n\t\t\t\t\t\t&WheelState[CARWHEEL_FRONT_LEFT],\n\t\t\t\t\t\tWHEEL_STATUS_BURST);\n\t\t\t\telse\n\t\t\t\t\tProcessWheel(wheelFwd, wheelRight,\n\t\t\t\t\t\tcontactSpeeds[CARWHEEL_FRONT_LEFT], contactPoints[CARWHEEL_FRONT_LEFT],\n\t\t\t\t\t\tm_nWheelsOnGround, fThrust,\n\t\t\t\t\t\tbrake*brakeBiasFront,\n\t\t\t\t\t\tadhesion*tractionBiasFront,\n\t\t\t\t\t\tCARWHEEL_FRONT_LEFT,\n\t\t\t\t\t\t&m_aWheelSpeed[CARWHEEL_FRONT_LEFT],\n\t\t\t\t\t\t&WheelState[CARWHEEL_FRONT_LEFT],\n\t\t\t\t\t\tWHEEL_STATUS_OK);\n\t\t\t}\n\n\t\t\tif(m_aWheelTimer[CARWHEEL_FRONT_RIGHT] > 0.0f){\n\t\t\t\tif(mod_HandlingManager.HasFrontWheelDrive(pHandling->nIdentifier))\n\t\t\t\t\tfThrust = acceleration;\n\t\t\t\telse\n\t\t\t\t\tfThrust = 0.0f;\n\n\t\t\t\twheelFwd = GetForward();\n\t\t\t\twheelFwd -= DotProduct(wheelFwd, m_aWheelColPoints[CARWHEEL_FRONT_RIGHT].normal)*m_aWheelColPoints[CARWHEEL_FRONT_RIGHT].normal;\n\t\t\t\twheelFwd.Normalise();\n\t\t\t\twheelRight = CrossProduct(wheelFwd, m_aWheelColPoints[CARWHEEL_FRONT_RIGHT].normal);\n\t\t\t\twheelRight.Normalise();\n\t\t\t\ttmp = c*wheelFwd - s*wheelRight;\n\t\t\t\twheelRight = s*wheelFwd + c*wheelRight;\n\t\t\t\twheelFwd = tmp;\n\n\t\t\t\tm_aWheelColPoints[CARWHEEL_FRONT_RIGHT].surfaceA = SURFACE_WHEELBASE;\n\t\t\t\tfloat adhesion = CSurfaceTable::GetAdhesiveLimit(m_aWheelColPoints[CARWHEEL_FRONT_RIGHT])*traction;\n\t\t\t\tif(GetStatus() == STATUS_PLAYER)\n\t\t\t\t\tadhesion *= CSurfaceTable::GetWetMultiplier(m_aWheelColPoints[CARWHEEL_FRONT_RIGHT].surfaceB);\n\t\t\t\tWheelState[CARWHEEL_FRONT_RIGHT] = m_aWheelState[CARWHEEL_FRONT_RIGHT];\n\n\t\t\t\tif(Damage.GetWheelStatus(CARWHEEL_FRONT_RIGHT) == WHEEL_STATUS_BURST)\n\t\t\t\t\tProcessWheel(wheelFwd, wheelRight,\n\t\t\t\t\t\tcontactSpeeds[CARWHEEL_FRONT_RIGHT], contactPoints[CARWHEEL_FRONT_RIGHT],\n\t\t\t\t\t\tm_nWheelsOnGround, fThrust,\n\t\t\t\t\t\tbrake*brakeBiasFront,\n\t\t\t\t\t\tadhesion*tractionBiasFront*Damage.m_fWheelDamageEffect,\n\t\t\t\t\t\tCARWHEEL_FRONT_RIGHT,\n\t\t\t\t\t\t&m_aWheelSpeed[CARWHEEL_FRONT_RIGHT],\n\t\t\t\t\t\t&WheelState[CARWHEEL_FRONT_RIGHT],\n\t\t\t\t\t\tWHEEL_STATUS_BURST);\n\t\t\t\telse\n\t\t\t\t\tProcessWheel(wheelFwd, wheelRight,\n\t\t\t\t\t\tcontactSpeeds[CARWHEEL_FRONT_RIGHT], contactPoints[CARWHEEL_FRONT_RIGHT],\n\t\t\t\t\t\tm_nWheelsOnGround, fThrust,\n\t\t\t\t\t\tbrake*brakeBiasFront,\n\t\t\t\t\t\tadhesion*tractionBiasFront,\n\t\t\t\t\t\tCARWHEEL_FRONT_RIGHT,\n\t\t\t\t\t\t&m_aWheelSpeed[CARWHEEL_FRONT_RIGHT],\n\t\t\t\t\t\t&WheelState[CARWHEEL_FRONT_RIGHT],\n\t\t\t\t\t\tWHEEL_STATUS_OK);\n\t\t\t}\n\t\t}\n\n\t\t// Process front wheels off ground\n\n\t\tif(!IsRealHeli()){\n\t\t\tif(m_aWheelTimer[CARWHEEL_FRONT_LEFT] <= 0.0f){\n\t\t\t\tif(mod_HandlingManager.HasFrontWheelDrive(pHandling->nIdentifier) && acceleration != 0.0f){\n\t\t\t\t\tif(acceleration > 0.0f){\n\t\t\t\t\t\tif(m_aWheelSpeed[CARWHEEL_FRONT_LEFT] < 2.0f)\n\t\t\t\t\t\t\tm_aWheelSpeed[CARWHEEL_FRONT_LEFT] -= 0.2f;\n\t\t\t\t\t}else{\n\t\t\t\t\t\tif(m_aWheelSpeed[CARWHEEL_FRONT_LEFT] > -2.0f)\n\t\t\t\t\t\t\tm_aWheelSpeed[CARWHEEL_FRONT_LEFT] += 0.1f;\n\t\t\t\t\t}\n\t\t\t\t}else{\n\t\t\t\t\tm_aWheelSpeed[CARWHEEL_FRONT_LEFT] *= 0.95f;\n\t\t\t\t}\n\t\t\t\tm_aWheelRotation[CARWHEEL_FRONT_LEFT] += m_aWheelSpeed[CARWHEEL_FRONT_LEFT];\n\t\t\t}\n\t\t\tif(m_aWheelTimer[CARWHEEL_FRONT_RIGHT] <= 0.0f){\n\t\t\t\tif(mod_HandlingManager.HasFrontWheelDrive(pHandling->nIdentifier) && acceleration != 0.0f){\n\t\t\t\t\tif(acceleration > 0.0f){\n\t\t\t\t\t\tif(m_aWheelSpeed[CARWHEEL_FRONT_RIGHT] < 2.0f)\n\t\t\t\t\t\t\tm_aWheelSpeed[CARWHEEL_FRONT_RIGHT] -= 0.2f;\n\t\t\t\t\t}else{\n\t\t\t\t\t\tif(m_aWheelSpeed[CARWHEEL_FRONT_RIGHT] > -2.0f)\n\t\t\t\t\t\t\tm_aWheelSpeed[CARWHEEL_FRONT_RIGHT] += 0.1f;\n\t\t\t\t\t}\n\t\t\t\t}else{\n\t\t\t\t\tm_aWheelSpeed[CARWHEEL_FRONT_RIGHT] *= 0.95f;\n\t\t\t\t}\n\t\t\t\tm_aWheelRotation[CARWHEEL_FRONT_RIGHT] += m_aWheelSpeed[CARWHEEL_FRONT_RIGHT];\n\t\t\t}\n\t\t}\n\t\t}\n\n\t\t// Process rear wheels\n\n\t\tif(m_aWheelTimer[CARWHEEL_REAR_LEFT] > 0.0f || m_aWheelTimer[CARWHEEL_REAR_RIGHT] > 0.0f){\n\t\t\tCVector wheelFwd = GetForward();\n\t\t\tCVector wheelRight = GetRight();\t// overwritten for resp. wheel\n\n\t\t\tfloat rearBrake = brake;\n\t\t\tfloat rearTraction = traction;\n\t\t\tif(bIsHandbrakeOn){\n#ifdef FIX_BUGS\n\t\t\t\t// Not sure if this is needed, but brake usually has timestep as a factor\n\t\t\t\trearBrake = 20000.0f * CTimer::GetTimeStepFix();\n#else\n\t\t\t\trearBrake = 20000.0f;\n#endif\n\t\t\t\tif(fwdSpeed > 0.1f && pHandling->Flags & HANDLING_HANDBRAKE_TYRE){\n\t\t\t\t\tm_fTireTemperature += 0.005*CTimer::GetTimeStep();\n\t\t\t\t\tif(m_fTireTemperature > 2.0f)\n\t\t\t\t\t\tm_fTireTemperature = 2.0f;\n\t\t\t\t}\n\t\t\t}else if(m_doingBurnout && mod_HandlingManager.HasRearWheelDrive(pHandling->nIdentifier)){\n\t\t\t\trearBrake = 0.0f;\n\t\t\t\trearTraction = 0.0f;\n\t\t\t\t// BUG: missing timestep\n\t\t\t\tApplyTurnForce(contactPoints[CARWHEEL_REAR_LEFT], -0.001f*m_fTurnMass*m_fSteerAngle*GetRight());\n\t\t\t}else if(m_fTireTemperature > 1.0f){\n\t\t\t\trearTraction *= m_fTireTemperature;\n\t\t\t}\n\n\t\t\tif(m_aWheelTimer[CARWHEEL_REAR_LEFT] > 0.0f){\n\t\t\t\tif(mod_HandlingManager.HasRearWheelDrive(pHandling->nIdentifier))\n\t\t\t\t\tfThrust = acceleration;\n\t\t\t\telse\n\t\t\t\t\tfThrust = 0.0f;\n\n\t\t\t\twheelFwd -= DotProduct(wheelFwd, m_aWheelColPoints[CARWHEEL_REAR_LEFT].normal)*m_aWheelColPoints[CARWHEEL_REAR_LEFT].normal;\n\t\t\t\twheelFwd.Normalise();\n\t\t\t\twheelRight = CrossProduct(wheelFwd, m_aWheelColPoints[CARWHEEL_REAR_LEFT].normal);\n\t\t\t\twheelRight.Normalise();\n\n\t\t\t\tm_aWheelColPoints[CARWHEEL_REAR_LEFT].surfaceA = SURFACE_WHEELBASE;\n\t\t\t\tfloat adhesion = CSurfaceTable::GetAdhesiveLimit(m_aWheelColPoints[CARWHEEL_REAR_LEFT])*rearTraction;\n\t\t\t\tif(GetStatus() == STATUS_PLAYER)\n\t\t\t\t\tadhesion *= CSurfaceTable::GetWetMultiplier(m_aWheelColPoints[CARWHEEL_REAR_LEFT].surfaceB);\n\t\t\t\tWheelState[CARWHEEL_REAR_LEFT] = m_aWheelState[CARWHEEL_REAR_LEFT];\n\n\t\t\t\tif(Damage.GetWheelStatus(CARWHEEL_REAR_LEFT) == WHEEL_STATUS_BURST)\n\t\t\t\t\tProcessWheel(wheelFwd, wheelRight,\n\t\t\t\t\t\tcontactSpeeds[CARWHEEL_REAR_LEFT], contactPoints[CARWHEEL_REAR_LEFT],\n\t\t\t\t\t\tm_nWheelsOnGround, fThrust,\n\t\t\t\t\t\trearBrake*brakeBiasRear,\n\t\t\t\t\t\tadhesion*tractionBiasRear*Damage.m_fWheelDamageEffect,\n\t\t\t\t\t\tCARWHEEL_REAR_LEFT,\n\t\t\t\t\t\t&m_aWheelSpeed[CARWHEEL_REAR_LEFT],\n\t\t\t\t\t\t&WheelState[CARWHEEL_REAR_LEFT],\n\t\t\t\t\t\tWHEEL_STATUS_BURST);\n\t\t\t\telse\n\t\t\t\t\tProcessWheel(wheelFwd, wheelRight,\n\t\t\t\t\t\tcontactSpeeds[CARWHEEL_REAR_LEFT], contactPoints[CARWHEEL_REAR_LEFT],\n\t\t\t\t\t\tm_nWheelsOnGround, fThrust,\n\t\t\t\t\t\trearBrake*brakeBiasRear,\n\t\t\t\t\t\tadhesion*tractionBiasRear,\n\t\t\t\t\t\tCARWHEEL_REAR_LEFT,\n\t\t\t\t\t\t&m_aWheelSpeed[CARWHEEL_REAR_LEFT],\n\t\t\t\t\t\t&WheelState[CARWHEEL_REAR_LEFT],\n\t\t\t\t\t\tWHEEL_STATUS_OK);\n\t\t\t}\n\n#ifdef FIX_BUGS\n\t\t\t// Shouldn't we reset these after the left wheel?\n\t\t\twheelFwd = GetForward();\n\t\t\twheelRight = GetRight();\t// actually useless\n#endif\n\n\t\t\tif(m_aWheelTimer[CARWHEEL_REAR_RIGHT] > 0.0f){\n\t\t\t\tif(mod_HandlingManager.HasRearWheelDrive(pHandling->nIdentifier))\n\t\t\t\t\tfThrust = acceleration;\n\t\t\t\telse\n\t\t\t\t\tfThrust = 0.0f;\n\n\t\t\t\twheelFwd -= DotProduct(wheelFwd, m_aWheelColPoints[CARWHEEL_REAR_RIGHT].normal)*m_aWheelColPoints[CARWHEEL_REAR_RIGHT].normal;\n\t\t\t\twheelFwd.Normalise();\n\t\t\t\twheelRight = CrossProduct(wheelFwd, m_aWheelColPoints[CARWHEEL_REAR_RIGHT].normal);\n\t\t\t\twheelRight.Normalise();\n\n\t\t\t\tm_aWheelColPoints[CARWHEEL_REAR_RIGHT].surfaceA = SURFACE_WHEELBASE;\n\t\t\t\tfloat adhesion = CSurfaceTable::GetAdhesiveLimit(m_aWheelColPoints[CARWHEEL_REAR_RIGHT])*rearTraction;\n\t\t\t\tif(GetStatus() == STATUS_PLAYER)\n\t\t\t\t\tadhesion *= CSurfaceTable::GetWetMultiplier(m_aWheelColPoints[CARWHEEL_REAR_RIGHT].surfaceB);\n\t\t\t\tWheelState[CARWHEEL_REAR_RIGHT] = m_aWheelState[CARWHEEL_REAR_RIGHT];\n\n\t\t\t\tif(Damage.GetWheelStatus(CARWHEEL_REAR_RIGHT) == WHEEL_STATUS_BURST)\n\t\t\t\t\tProcessWheel(wheelFwd, wheelRight,\n\t\t\t\t\t\tcontactSpeeds[CARWHEEL_REAR_RIGHT], contactPoints[CARWHEEL_REAR_RIGHT],\n\t\t\t\t\t\tm_nWheelsOnGround, fThrust,\n\t\t\t\t\t\trearBrake*brakeBiasRear,\n\t\t\t\t\t\tadhesion*tractionBiasRear*Damage.m_fWheelDamageEffect,\n\t\t\t\t\t\tCARWHEEL_REAR_RIGHT,\n\t\t\t\t\t\t&m_aWheelSpeed[CARWHEEL_REAR_RIGHT],\n\t\t\t\t\t\t&WheelState[CARWHEEL_REAR_RIGHT],\n\t\t\t\t\t\tWHEEL_STATUS_BURST);\n\t\t\t\telse\n\t\t\t\t\tProcessWheel(wheelFwd, wheelRight,\n\t\t\t\t\t\tcontactSpeeds[CARWHEEL_REAR_RIGHT], contactPoints[CARWHEEL_REAR_RIGHT],\n\t\t\t\t\t\tm_nWheelsOnGround, fThrust,\n\t\t\t\t\t\trearBrake*brakeBiasRear,\n\t\t\t\t\t\tadhesion*tractionBiasRear,\n\t\t\t\t\t\tCARWHEEL_REAR_RIGHT,\n\t\t\t\t\t\t&m_aWheelSpeed[CARWHEEL_REAR_RIGHT],\n\t\t\t\t\t\t&WheelState[CARWHEEL_REAR_RIGHT],\n\t\t\t\t\t\tWHEEL_STATUS_OK);\n\t\t\t}\n\t\t}\n\n\t\tif(m_doingBurnout && mod_HandlingManager.HasRearWheelDrive(pHandling->nIdentifier) &&\n\t           (m_aWheelState[CARWHEEL_REAR_LEFT] == WHEEL_STATE_SPINNING || m_aWheelState[CARWHEEL_REAR_RIGHT] == WHEEL_STATE_SPINNING)){\n\t\t\tm_fTireTemperature += 0.001f*CTimer::GetTimeStep();\n\t\t\tif(m_fTireTemperature > 3.0f)\n\t\t\t\tm_fTireTemperature = 3.0f;\n\t\t}else if(m_fTireTemperature > 1.0f){\n\t\t\tm_fTireTemperature = (m_fTireTemperature - 1.0f)*Pow(0.995f, CTimer::GetTimeStep()) + 1.0f;\n\t\t}\n\n\t\t// Process rear wheels off ground\n\n\t\tif(!IsRealHeli()){\n\t\t\tif(m_aWheelTimer[CARWHEEL_REAR_LEFT] <= 0.0f){\n\t\t\t\tif(bIsHandbrakeOn)\n\t\t\t\t\tm_aWheelSpeed[CARWHEEL_REAR_LEFT] = 0.0f;\n\t\t\t\telse if(mod_HandlingManager.HasRearWheelDrive(pHandling->nIdentifier) && acceleration != 0.0f){\n\t\t\t\t\tif(acceleration > 0.0f){\n\t\t\t\t\t\tif(m_aWheelSpeed[CARWHEEL_REAR_LEFT] < 2.0f)\n\t\t\t\t\t\t\tm_aWheelSpeed[CARWHEEL_REAR_LEFT] -= 0.2f;\n\t\t\t\t\t}else{\n\t\t\t\t\t\tif(m_aWheelSpeed[CARWHEEL_REAR_LEFT] > -2.0f)\n\t\t\t\t\t\t\tm_aWheelSpeed[CARWHEEL_REAR_LEFT] += 0.1f;\n\t\t\t\t\t}\n\t\t\t\t}else{\n\t\t\t\t\tm_aWheelSpeed[CARWHEEL_REAR_LEFT] *= 0.95f;\n\t\t\t\t}\n\t\t\t\tm_aWheelRotation[CARWHEEL_REAR_LEFT] += m_aWheelSpeed[CARWHEEL_REAR_LEFT];\n\t\t\t}\n\t\t\tif(m_aWheelTimer[CARWHEEL_REAR_RIGHT] <= 0.0f){\n\t\t\t\tif(bIsHandbrakeOn)\n\t\t\t\t\tm_aWheelSpeed[CARWHEEL_REAR_RIGHT] = 0.0f;\n\t\t\t\telse if(mod_HandlingManager.HasRearWheelDrive(pHandling->nIdentifier) && acceleration != 0.0f){\n\t\t\t\t\tif(acceleration > 0.0f){\n\t\t\t\t\t\tif(m_aWheelSpeed[CARWHEEL_REAR_RIGHT] < 2.0f)\n\t\t\t\t\t\t\tm_aWheelSpeed[CARWHEEL_REAR_RIGHT] -= 0.2f;\n\t\t\t\t\t}else{\n\t\t\t\t\t\tif(m_aWheelSpeed[CARWHEEL_REAR_RIGHT] > -2.0f)\n\t\t\t\t\t\t\tm_aWheelSpeed[CARWHEEL_REAR_RIGHT] += 0.1f;\n\t\t\t\t\t}\n\t\t\t\t}else{\n\t\t\t\t\tm_aWheelSpeed[CARWHEEL_REAR_RIGHT] *= 0.95f;\n\t\t\t\t}\n\t\t\t\tm_aWheelRotation[CARWHEEL_REAR_RIGHT] += m_aWheelSpeed[CARWHEEL_REAR_RIGHT];\n\t\t\t}\n\t\t}\n\n\t\t// Process front wheels on ground - second try\n\n\t\tif(rearWheelsFirst){\n\t\tif(m_aWheelTimer[CARWHEEL_FRONT_LEFT] > 0.0f || m_aWheelTimer[CARWHEEL_FRONT_RIGHT] > 0.0f){\n\t\t\tfloat s = Sin(m_fSteerAngle);\n\t\t\tfloat c = Cos(m_fSteerAngle);\n\n\t\t\tCVector wheelFwd, wheelRight, tmp;\n\n\t\t\tif(m_aWheelTimer[CARWHEEL_FRONT_LEFT] > 0.0f){\n\t\t\t\tif(mod_HandlingManager.HasFrontWheelDrive(pHandling->nIdentifier))\n\t\t\t\t\tfThrust = acceleration;\n\t\t\t\telse\n\t\t\t\t\tfThrust = 0.0f;\n\n\t\t\t\twheelFwd = GetForward();\n\t\t\t\twheelFwd -= DotProduct(wheelFwd, m_aWheelColPoints[CARWHEEL_FRONT_LEFT].normal)*m_aWheelColPoints[CARWHEEL_FRONT_LEFT].normal;\n\t\t\t\twheelFwd.Normalise();\n\t\t\t\twheelRight = CrossProduct(wheelFwd, m_aWheelColPoints[CARWHEEL_FRONT_LEFT].normal);\n\t\t\t\twheelRight.Normalise();\n\t\t\t\ttmp = c*wheelFwd - s*wheelRight;\n\t\t\t\twheelRight = s*wheelFwd + c*wheelRight;\n\t\t\t\twheelFwd = tmp;\n\n\t\t\t\tm_aWheelColPoints[CARWHEEL_FRONT_LEFT].surfaceA = SURFACE_WHEELBASE;\n\t\t\t\tfloat adhesion = CSurfaceTable::GetAdhesiveLimit(m_aWheelColPoints[CARWHEEL_FRONT_LEFT])*traction;\n\t\t\t\tif(GetStatus() == STATUS_PLAYER)\n\t\t\t\t\tadhesion *= CSurfaceTable::GetWetMultiplier(m_aWheelColPoints[CARWHEEL_FRONT_LEFT].surfaceB);\n\t\t\t\tWheelState[CARWHEEL_FRONT_LEFT] = m_aWheelState[CARWHEEL_FRONT_LEFT];\n\n\t\t\t\tif(Damage.GetWheelStatus(CARWHEEL_FRONT_LEFT) == WHEEL_STATUS_BURST)\n\t\t\t\t\tProcessWheel(wheelFwd, wheelRight,\n\t\t\t\t\t\tcontactSpeeds[CARWHEEL_FRONT_LEFT], contactPoints[CARWHEEL_FRONT_LEFT],\n\t\t\t\t\t\tm_nWheelsOnGround, fThrust,\n\t\t\t\t\t\tbrake*brakeBiasFront,\n\t\t\t\t\t\tadhesion*tractionBiasFront*Damage.m_fWheelDamageEffect,\n\t\t\t\t\t\tCARWHEEL_FRONT_LEFT,\n\t\t\t\t\t\t&m_aWheelSpeed[CARWHEEL_FRONT_LEFT],\n\t\t\t\t\t\t&WheelState[CARWHEEL_FRONT_LEFT],\n\t\t\t\t\t\tWHEEL_STATUS_BURST);\n\t\t\t\telse\n\t\t\t\t\tProcessWheel(wheelFwd, wheelRight,\n\t\t\t\t\t\tcontactSpeeds[CARWHEEL_FRONT_LEFT], contactPoints[CARWHEEL_FRONT_LEFT],\n\t\t\t\t\t\tm_nWheelsOnGround, fThrust,\n\t\t\t\t\t\tbrake*brakeBiasFront,\n\t\t\t\t\t\tadhesion*tractionBiasFront,\n\t\t\t\t\t\tCARWHEEL_FRONT_LEFT,\n\t\t\t\t\t\t&m_aWheelSpeed[CARWHEEL_FRONT_LEFT],\n\t\t\t\t\t\t&WheelState[CARWHEEL_FRONT_LEFT],\n\t\t\t\t\t\tWHEEL_STATUS_OK);\n\t\t\t}\n\n\t\t\tif(m_aWheelTimer[CARWHEEL_FRONT_RIGHT] > 0.0f){\n\t\t\t\tif(mod_HandlingManager.HasFrontWheelDrive(pHandling->nIdentifier))\n\t\t\t\t\tfThrust = acceleration;\n\t\t\t\telse\n\t\t\t\t\tfThrust = 0.0f;\n\n\t\t\t\twheelFwd = GetForward();\n\t\t\t\twheelFwd -= DotProduct(wheelFwd, m_aWheelColPoints[CARWHEEL_FRONT_RIGHT].normal)*m_aWheelColPoints[CARWHEEL_FRONT_RIGHT].normal;\n\t\t\t\twheelFwd.Normalise();\n\t\t\t\twheelRight = CrossProduct(wheelFwd, m_aWheelColPoints[CARWHEEL_FRONT_RIGHT].normal);\n\t\t\t\twheelRight.Normalise();\n\t\t\t\ttmp = c*wheelFwd - s*wheelRight;\n\t\t\t\twheelRight = s*wheelFwd + c*wheelRight;\n\t\t\t\twheelFwd = tmp;\n\n\t\t\t\tm_aWheelColPoints[CARWHEEL_FRONT_RIGHT].surfaceA = SURFACE_WHEELBASE;\n\t\t\t\tfloat adhesion = CSurfaceTable::GetAdhesiveLimit(m_aWheelColPoints[CARWHEEL_FRONT_RIGHT])*traction;\n\t\t\t\tif(GetStatus() == STATUS_PLAYER)\n\t\t\t\t\tadhesion *= CSurfaceTable::GetWetMultiplier(m_aWheelColPoints[CARWHEEL_FRONT_RIGHT].surfaceB);\n\t\t\t\tWheelState[CARWHEEL_FRONT_RIGHT] = m_aWheelState[CARWHEEL_FRONT_RIGHT];\n\n\t\t\t\tif(Damage.GetWheelStatus(CARWHEEL_FRONT_RIGHT) == WHEEL_STATUS_BURST)\n\t\t\t\t\tProcessWheel(wheelFwd, wheelRight,\n\t\t\t\t\t\tcontactSpeeds[CARWHEEL_FRONT_RIGHT], contactPoints[CARWHEEL_FRONT_RIGHT],\n\t\t\t\t\t\tm_nWheelsOnGround, fThrust,\n\t\t\t\t\t\tbrake*brakeBiasFront,\n\t\t\t\t\t\tadhesion*tractionBiasFront*Damage.m_fWheelDamageEffect,\n\t\t\t\t\t\tCARWHEEL_FRONT_RIGHT,\n\t\t\t\t\t\t&m_aWheelSpeed[CARWHEEL_FRONT_RIGHT],\n\t\t\t\t\t\t&WheelState[CARWHEEL_FRONT_RIGHT],\n\t\t\t\t\t\tWHEEL_STATUS_BURST);\n\t\t\t\telse\n\t\t\t\t\tProcessWheel(wheelFwd, wheelRight,\n\t\t\t\t\t\tcontactSpeeds[CARWHEEL_FRONT_RIGHT], contactPoints[CARWHEEL_FRONT_RIGHT],\n\t\t\t\t\t\tm_nWheelsOnGround, fThrust,\n\t\t\t\t\t\tbrake*brakeBiasFront,\n\t\t\t\t\t\tadhesion*tractionBiasFront,\n\t\t\t\t\t\tCARWHEEL_FRONT_RIGHT,\n\t\t\t\t\t\t&m_aWheelSpeed[CARWHEEL_FRONT_RIGHT],\n\t\t\t\t\t\t&WheelState[CARWHEEL_FRONT_RIGHT],\n\t\t\t\t\t\tWHEEL_STATUS_OK);\n\t\t\t}\n\t\t}\n\n\t\t// Process front wheels off ground\n\n\t\tif (!IsRealHeli()) {\n\t\t\tif(m_aWheelTimer[CARWHEEL_FRONT_LEFT] <= 0.0f){\n\t\t\t\tif(mod_HandlingManager.HasFrontWheelDrive(pHandling->nIdentifier) && acceleration != 0.0f){\n\t\t\t\t\tif(acceleration > 0.0f){\n\t\t\t\t\t\tif(m_aWheelSpeed[CARWHEEL_FRONT_LEFT] < 2.0f)\n\t\t\t\t\t\t\tm_aWheelSpeed[CARWHEEL_FRONT_LEFT] -= 0.2f;\n\t\t\t\t\t}else{\n\t\t\t\t\t\tif(m_aWheelSpeed[CARWHEEL_FRONT_LEFT] > -2.0f)\n\t\t\t\t\t\t\tm_aWheelSpeed[CARWHEEL_FRONT_LEFT] += 0.1f;\n\t\t\t\t\t}\n\t\t\t\t}else{\n\t\t\t\t\tm_aWheelSpeed[CARWHEEL_FRONT_LEFT] *= 0.95f;\n\t\t\t\t}\n\t\t\t\tm_aWheelRotation[CARWHEEL_FRONT_LEFT] += m_aWheelSpeed[CARWHEEL_FRONT_LEFT];\n\t\t\t}\n\t\t\tif(m_aWheelTimer[CARWHEEL_FRONT_RIGHT] <= 0.0f){\n\t\t\t\tif(mod_HandlingManager.HasFrontWheelDrive(pHandling->nIdentifier) && acceleration != 0.0f){\n\t\t\t\t\tif(acceleration > 0.0f){\n\t\t\t\t\t\tif(m_aWheelSpeed[CARWHEEL_FRONT_RIGHT] < 2.0f)\n\t\t\t\t\t\t\tm_aWheelSpeed[CARWHEEL_FRONT_RIGHT] -= 0.2f;\n\t\t\t\t\t}else{\n\t\t\t\t\t\tif(m_aWheelSpeed[CARWHEEL_FRONT_RIGHT] > -2.0f)\n\t\t\t\t\t\t\tm_aWheelSpeed[CARWHEEL_FRONT_RIGHT] += 0.1f;\n\t\t\t\t\t}\n\t\t\t\t}else{\n\t\t\t\t\tm_aWheelSpeed[CARWHEEL_FRONT_RIGHT] *= 0.95f;\n\t\t\t\t}\n\t\t\t\tm_aWheelRotation[CARWHEEL_FRONT_RIGHT] += m_aWheelSpeed[CARWHEEL_FRONT_RIGHT];\n\t\t\t}\n\t\t}\n\t\t}\n\n\t\tfor(i = 0; i < 4; i++){\n\t\t\tfloat wheelPos = colModel->lines[i].p0.z;\n\t\t\tif(m_aSuspensionSpringRatio[i] > 0.0f)\n\t\t\t\twheelPos -= m_aSuspensionSpringRatio[i]*m_aSuspensionSpringLength[i];\n\t\t\tif(GetModelIndex() == MI_VOODOO && bUsingSpecialColModel)\n\t\t\t\tm_aWheelPosition[i] = wheelPos;\n\t\t\telse\n\t\t\t\tm_aWheelPosition[i] += (wheelPos - m_aWheelPosition[i])*0.75f;\n\t\t}\n\t\tfor(i = 0; i < 4; i++)\n\t\t\tm_aWheelState[i] = WheelState[i];\n\t\tif(m_fGasPedal < 0.0f){\n\t\t\tif(m_aWheelState[CARWHEEL_REAR_LEFT] == WHEEL_STATE_SPINNING)\n\t\t\t\tm_aWheelState[CARWHEEL_REAR_LEFT] = WHEEL_STATE_NORMAL;\n\t\t\tif(m_aWheelState[CARWHEEL_REAR_RIGHT] == WHEEL_STATE_SPINNING)\n\t\t\t\tm_aWheelState[CARWHEEL_REAR_RIGHT] = WHEEL_STATE_NORMAL;\n\t\t}\n\n\t\t// Process horn\n\n\t\tif(GetStatus() != STATUS_PLAYER){\n\t\t\tif(!IsAlarmOn())\n\t\t\t\tReduceHornCounter();\n\t\t}else{\n\t\t\tif(UsesSiren()){\n\t\t\t\tif(Pads[0].bHornHistory[Pads[0].iCurrHornHistory]){\n\t\t\t\t\tif(Pads[0].bHornHistory[(Pads[0].iCurrHornHistory+4) % 5] &&\n\t\t\t\t\t   Pads[0].bHornHistory[(Pads[0].iCurrHornHistory+3) % 5])\n\t\t\t\t\t\tm_nCarHornTimer = 1;\n\t\t\t\t\telse\n\t\t\t\t\t\tm_nCarHornTimer = 0;\n\t\t\t\t}else if(Pads[0].bHornHistory[(Pads[0].iCurrHornHistory+4) % 5] &&\n\t\t\t\t         !Pads[0].bHornHistory[(Pads[0].iCurrHornHistory+1) % 5]){\n\t\t\t\t\tm_nCarHornTimer = 0;\n\t\t\t\t\tm_bSirenOrAlarm = !m_bSirenOrAlarm;\n\t\t\t\t}else\n\t\t\t\t\tm_nCarHornTimer = 0;\n\t\t\t}else if(GetModelIndex() != MI_VOODOO && !CVehicle::bCheat3 && !carHasNitro){\n\t\t\t\tif(!IsAlarmOn()){\n\t\t\t\t\tif(Pads[0].GetHorn())\n\t\t\t\t\t\tm_nCarHornTimer = 1;\n\t\t\t\t\telse\n\t\t\t\t\t\tm_nCarHornTimer = 0;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Flying\n\n\t\tbool playRotorSound = false;\n\t\tbool isPlane = GetModelIndex() == MI_DODO || bAllDodosCheat;\n#ifdef FIX_BUGS\n\t\tisPlane = isPlane && !IsRealHeli();\n#endif\n\t\tif(GetStatus() != STATUS_PLAYER && GetStatus() != STATUS_PLAYER_REMOTE && GetStatus() != STATUS_PHYSICS){\n\t\t\tif(IsRealHeli()){\n\t\t\t\tbEngineOn = false;\n\t\t\t\tm_aWheelSpeed[1] = Max(m_aWheelSpeed[1]-0.0005f, 0.0f);\n\t\t\t\tif(GetModelIndex() != MI_RCRAIDER && GetModelIndex() != MI_RCGOBLIN)\n\t\t\t\t\tif(m_aWheelSpeed[1] < 0.154f && m_aWheelSpeed[1] > 0.0044f)\n\t\t\t\t\t\tplayRotorSound = true;\n\t\t\t}\n\t\t}else if(isPlane && m_vecMoveSpeed.Magnitude() > 0.0f && CTimer::GetTimeStep() > 0.0f){\n\t\t\tif(GetModelIndex() == MI_DODO)\n\t\t\t\tFlyingControl(FLIGHT_MODEL_DODO);\n\t\t\telse\n\t\t\t\tFlyingControl(FLIGHT_MODEL_PLANE);\n\t\t}else if(GetModelIndex() == MI_RCBARON){\n\t\t\tFlyingControl(FLIGHT_MODEL_RCPLANE);\n\t\t}else if(IsRealHeli() || bAllCarCheat){\n#ifdef RESTORE_ALLCARSHELI_CHEAT\n\t\t\tif (bAllCarCheat)\n\t\t\t\tFlyingControl(FLIGHT_MODEL_HELI);\n\t\t\telse\n#endif\n\t\t\t{\n\t\t\t\t// Speed up rotor\n\t\t\t\tif (m_aWheelSpeed[1] < 0.22f && !bIsInWater) {\n\t\t\t\t\tif (GetModelIndex() == MI_RCRAIDER || GetModelIndex() == MI_RCGOBLIN)\n\t\t\t\t\t\tm_aWheelSpeed[1] += 0.003f;\n\t\t\t\t\telse\n\t\t\t\t\t\tm_aWheelSpeed[1] += 0.001f;\n\t\t\t\t}\n\n\t\t\t\t// Fly\n\t\t\t\tif (m_aWheelSpeed[1] > 0.15f) {\n\t\t\t\t\tif (GetModelIndex() == MI_RCRAIDER || GetModelIndex() == MI_RCGOBLIN)\n\t\t\t\t\t\tFlyingControl(FLIGHT_MODEL_RCHELI);\n\t\t\t\t\telse if (m_nWheelsOnGround < 4 && !(GetModelIndex() == MI_SEASPAR && bTouchingWater) ||\n\t\t\t\t\t\tCPad::GetPad(0)->GetAccelerate() != 0 ||\n#ifndef FREE_CAM\n\t\t\t\t\t\tCPad::GetPad(0)->GetCarGunUpDown() > 1.0f ||\n#else\n\t\t\t\t\t\t((!CCamera::bFreeCam || (CCamera::bFreeCam && !CPad::IsAffectedByController)) && CPad::GetPad(0)->GetCarGunUpDown() > 1.0f) ||\n#endif\n\t\t\t\t\t\tAbs(m_vecMoveSpeed.x) > 0.02f ||\n\t\t\t\t\t\tAbs(m_vecMoveSpeed.y) > 0.02f ||\n\t\t\t\t\t\tAbs(m_vecMoveSpeed.z) > 0.02f)\n\t\t\t\t\t\tFlyingControl(FLIGHT_MODEL_HELI);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Blade collision\n\t\t\tif(m_aWheelSpeed[1] > 0.015f && m_aCarNodes[CAR_BONNET]){\n\t\t\t\tCMatrix mat;\n\t\t\t\tmat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_BONNET]));\n\t\t\t\tif(GetModelIndex() == MI_RCRAIDER || GetModelIndex() == MI_RCGOBLIN)\n\t\t\t\t\tDoBladeCollision(mat.GetPosition(), GetMatrix(), ROTOR_TOP, 0.72f, 0.9f);\n\t\t\t\telse if(GetModelIndex() == MI_SPARROW || GetModelIndex() == MI_SEASPAR)\n\t\t\t\t\tDoBladeCollision(mat.GetPosition(), GetMatrix(), ROTOR_TOP, 5.15f, 0.8f);\n\t\t\t\telse if(GetModelIndex() == MI_HUNTER)\n\t\t\t\t\tDoBladeCollision(mat.GetPosition(), GetMatrix(), ROTOR_TOP, 6.15f, 0.5f);\n\t\t\t\telse\n\t\t\t\t\tDoBladeCollision(mat.GetPosition(), GetMatrix(), ROTOR_TOP, 6.15f, 1.0f);\n\t\t\t}\n\n\t\t\t// Heli weapons\n\t\t\tif(GetModelIndex() == MI_HUNTER && GetStatus() == STATUS_PLAYER){\n\t\t\t\t// Hunter rockets\n\t\t\t\tif(CPad::GetPad(0)->CarGunJustDown() && CTimer::GetTimeInMilliseconds() > m_nGunFiringTime+350){\n\t\t\t\t\tCWeapon gun(WEAPONTYPE_ROCKETLAUNCHER, 100);\n\t\t\t\t\tCVector source = vecHunterRocketPos;\n\t\t\t\t\tsource = GetMatrix()*source + Max(DotProduct(m_vecMoveSpeed, GetForward()), 0.0f)*GetForward()*CTimer::GetTimeStep();\n\t\t\t\t\tgun.FireProjectile(this, &source, 0.0f);\n\n\t\t\t\t\tsource = vecHunterRocketPos;\n\t\t\t\t\tsource.x = -source.x;\n\t\t\t\t\tsource = GetMatrix()*source + Max(DotProduct(m_vecMoveSpeed, GetForward()), 0.0f)*GetForward()*CTimer::GetTimeStep();\n\t\t\t\t\tgun.FireProjectile(this, &source, 0.0f);\n\n\t\t\t\t\tCStats::RoundsFiredByPlayer++;\n\t\t\t\t\tDMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_SHOT_FIRED, 0.0f);\n\t\t\t\t\tm_nGunFiringTime = CTimer::GetTimeInMilliseconds();\n\t\t\t\t// Hunter gun\n\t\t\t\t}else if(CPad::GetPad(0)->GetHandBrake() && CTimer::GetTimeInMilliseconds() > m_nGunFiringTime+60){\n\t\t\t\t\tCWeapon gun(WEAPONTYPE_HELICANNON, 5000);\n\t\t\t\t\tCVector source = vecHunterGunPos;\n\t\t\t\t\tsource = GetMatrix()*source + m_vecMoveSpeed*CTimer::GetTimeStep();\n\t\t\t\t\tgun.FireInstantHit(this, &source);\n\t\t\t\t\tgun.AddGunshell(this, source, CVector2D(0.0f, 0.1f), 0.025f);\n\t\t\t\t\tCStats::RoundsFiredByPlayer++;\n\t\t\t\t\tDMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_SHOT_FIRED, 0.0f);\n\t\t\t\t\tm_nGunFiringTime = CTimer::GetTimeInMilliseconds();\n\t\t\t\t}\n\t\t\t}else if(GetModelIndex() == MI_SEASPAR && GetStatus() == STATUS_PLAYER){\n\t\t\t\t// Sea sparrow gun\n\t\t\t\tif(CPad::GetPad(0)->GetHandBrake() && CTimer::GetTimeInMilliseconds() > m_nGunFiringTime+40){\n\t\t\t\t\tCWeapon gun(WEAPONTYPE_M4, 5000);\n\t\t\t\t\tCVector source = vecSeaSparrowGunPos;\n\t\t\t\t\tsource = GetMatrix()*source + m_vecMoveSpeed*CTimer::GetTimeStep();\n\t\t\t\t\tgun.FireInstantHit(this, &source);\n\t\t\t\t\tgun.AddGunshell(this, source, CVector2D(0.0f, 0.1f), 0.025f);\n\t\t\t\t\tCStats::RoundsFiredByPlayer++;\n\t\t\t\t\tDMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_SHOT_FIRED, 0.0f);\n\t\t\t\t\tm_nGunFiringTime = CTimer::GetTimeInMilliseconds();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif(GetModelIndex() != MI_RCRAIDER && GetModelIndex() != MI_RCGOBLIN)\n\t\t\t\tif(m_aWheelSpeed[1] < 0.154f && m_aWheelSpeed[1] > 0.0044f)\n\t\t\t\t\tplayRotorSound = true;\n\t\t}\n\n\t\t// Play rotor sound\n\t\tif(playRotorSound && m_aCarNodes[CAR_BONNET]){\n\t\t\tCVector camDist = TheCamera.GetPosition() - GetPosition();\n\t\t\tfloat distSq = camDist.MagnitudeSqr();\n\t\t\tif(distSq < SQR(20.0f) && Abs(m_fPropellerRotation - m_aWheelRotation[1]) > DEGTORAD(30.0f)){\n\t\t\t\tCMatrix mat;\n\t\t\t\tmat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_BONNET]));\n\t\t\t\tCVector blade = mat.GetRight();\n\t\t\t\tblade = Multiply3x3(blade, GetMatrix());\n\t\t\t\tcamDist /= Max(Sqrt(distSq), 0.01f);\n\t\t\t\tif(Abs(DotProduct(camDist, blade)) > 0.95f){\n\t\t\t\t\tDMAudio.PlayOneShot(m_audioEntityId, SOUND_HELI_BLADE, 0.0f);\n\t\t\t\t\tm_fPropellerRotation = m_aWheelRotation[1];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\n\n\t// Process car on fire\n\t// A similar calculation of damagePos is done elsewhere for smoke\n\n\tuint8 engineStatus = Damage.GetEngineStatus();\n\tCVector damagePos = ((CVehicleModelInfo*)CModelInfo::GetModelInfo(GetModelIndex()))->m_positions[CAR_POS_HEADLIGHTS];\n\n\tswitch(Damage.GetDoorStatus(DOOR_BONNET)){\n\tcase DOOR_STATUS_OK:\n\tcase DOOR_STATUS_SMASHED:\n\t\t// Bonnet is still there, smoke comes out at the edge\n\t\tdamagePos += vecDAMAGE_ENGINE_POS_SMALL;\n\t\tbreak;\n\tcase DOOR_STATUS_SWINGING:\n\tcase DOOR_STATUS_MISSING:\n\t\t// Bonnet is gone, smoke comes out at the engine\n\t\tdamagePos += vecDAMAGE_ENGINE_POS_BIG;\n\t\tbreak;\n\t}\n\n\t// move fire forward if in first person\n\tif(this == FindPlayerVehicle() && TheCamera.GetLookingForwardFirstPerson())\n\t\tif(m_fHealth < 250.0f && GetStatus() != STATUS_WRECKED){\n\t\t\tif(GetModelIndex() == MI_FIRETRUCK)\n\t\t\t\tdamagePos += CVector(0.0f, 3.0f, -0.2f);\n\t\t\telse\n\t\t\t\tdamagePos += CVector(0.0f, 1.2f, -0.8f);\n\t\t}\n\n\tdamagePos = GetMatrix()*damagePos;\n\tdamagePos.z += 0.15f;\n\n\tif(m_fHealth < 250.0f && GetStatus() != STATUS_WRECKED){\n\t\t// Car is on fire\n\n\t\tCParticle::AddParticle(PARTICLE_CARFLAME, damagePos,\n\t\t\tCVector(0.0f, 0.0f, CGeneral::GetRandomNumberInRange(0.01125f, 0.09f)),\n\t\t\tnil, 0.63f);\n\n\t\tCVector coors = damagePos;\n\t\tcoors.x += CGeneral::GetRandomNumberInRange(-0.5625f, 0.5625f),\n\t\tcoors.y += CGeneral::GetRandomNumberInRange(-0.5625f, 0.5625f),\n\t\tcoors.z += CGeneral::GetRandomNumberInRange(0.5625f, 2.25f);\n\t\tCParticle::AddParticle(PARTICLE_CARFLAME_SMOKE, coors, CVector(0.0f, 0.0f, 0.0f));\n\n\t\tCParticle::AddParticle(PARTICLE_ENGINE_SMOKE2, damagePos, CVector(0.0f, 0.0f, 0.0f), nil, 0.5f);\n\n\t\t// Blow up car after 5 seconds\n\t\tm_fFireBlowUpTimer += CTimer::GetTimeStepInMilliseconds();\n\t\tif(m_fFireBlowUpTimer > 5000.0f)\n\t\t\tBlowUpCar(m_pSetOnFireEntity);\n\t}else\n\t\tm_fFireBlowUpTimer = 0.0f;\n\n\t// Decrease car health if engine is damaged badly\n\tif(engineStatus > ENGINE_STATUS_ON_FIRE && m_fHealth > 250.0f)\n\t\tm_fHealth -= 2.0f;\n\n\tProcessDelayedExplosion();\n\n\n\tif(m_bSirenOrAlarm && (CTimer::GetFrameCounter()&7) == 5 &&\n\t   UsesSiren() && GetModelIndex() != MI_MRWHOOP)\n\t\tCCarAI::MakeWayForCarWithSiren(this);\n\n\n\t// Find out how much to shake the pad depending on suspension and ground surface\n\n\tfloat suspShake = 0.0f;\n\tfloat surfShake = 0.0f;\n\tfloat speedsq = m_vecMoveSpeed.MagnitudeSqr();\n\tfor(i = 0; i < 4; i++){\n\t\tfloat suspChange = m_aSuspensionSpringRatioPrev[i] - m_aSuspensionSpringRatio[i];\n\t\tif(suspChange > 0.3f && !drivingInSand && speedsq > 0.04f){\n\t\t\tif(Damage.GetWheelStatus(i) == WHEEL_STATUS_BURST)\n\t\t\t\tDMAudio.PlayOneShot(m_audioEntityId, SOUND_CAR_JUMP_2, suspChange);\n\t\t\telse\n\t\t\t\tDMAudio.PlayOneShot(m_audioEntityId, SOUND_CAR_JUMP, suspChange);\n\t\t\tif(suspChange > suspShake)\n\t\t\t\tsuspShake = suspChange;\n\t\t}\n\n\t\tuint8 surf = m_aWheelColPoints[i].surfaceB;\n\t\tif(surf == SURFACE_GRAVEL || surf == SURFACE_WATER || surf == SURFACE_HEDGE){\n\t\t\tif(surfShake < 0.2f)\n\t\t\t\tsurfShake = 0.3f;\n\t\t}else if(surf == SURFACE_MUD_DRY){\n\t\t\tif(surfShake < 0.1f)\n\t\t\t\tsurfShake = 0.2f;\n\t\t}else if(surf == SURFACE_GRASS){\n\t\t\tif(surfShake < 0.05f)\n\t\t\t\tsurfShake = 0.1f;\n\t\t}\n\n\t\tif(this == FindPlayerVehicle())\n// BUG: this only observes one of the wheels\n\t\t\tTheCamera.m_bVehicleSuspenHigh = Abs(suspChange) > 0.05f;\n\n\t\tm_aSuspensionSpringRatioPrev[i] = m_aSuspensionSpringRatio[i];\n\t\tm_aSuspensionSpringRatio[i] = 1.0f;\n\t}\n\n\t// Shake pad\n\n\tif(!drivingInSand && (suspShake > 0.0f || surfShake > 0.0f) && GetStatus() == STATUS_PLAYER){\n\t\tfloat speed = m_vecMoveSpeed.MagnitudeSqr();\n\t\tif(speed > sq(0.1f)){\n\t\t\tspeed = Sqrt(speed);\n\t\t\tif(suspShake > 0.0f){\n\t\t\t\tuint8 freq = Min(200.0f*suspShake*speed*2000.0f/m_fMass + 100.0f, 250.0f);\n\t\t\t\tCPad::GetPad(0)->StartShake(20000.0f*CTimer::GetTimeStep()/freq, freq);\n\t\t\t}else{\n\t\t\t\tuint8 freq = Min(200.0f*surfShake*speed*2000.0f/m_fMass + 40.0f, 150.0f);\n\t\t\t\tCPad::GetPad(0)->StartShake(5000.0f*CTimer::GetTimeStep()/freq, freq);\n\t\t\t}\n\t\t}\n\t}\n\n\tbVehicleColProcessed = false;\n\tbAudioChangingGear = false;\n\n\tif(!bWarnedPeds && GetVehicleAppearance() != VEHICLE_APPEARANCE_HELI && GetVehicleAppearance() != VEHICLE_APPEARANCE_PLANE)\n\t\tCCarCtrl::ScanForPedDanger(this);\n\n\n\t// Turn around at the edge of the world\n\t// TODO: make the numbers defines\n\n\tfloat heading;\n\tif(GetPosition().x > 1950.0f-400.0f){\n\t\tif(m_vecMoveSpeed.x > 0.0f)\n\t\t\tm_vecMoveSpeed.x *= -1.0f;\n\t\theading = GetForward().Heading();\n\t\tif(heading > 0.0f)\t// going west\n\t\t\tSetHeading(-heading);\n\t}else if(GetPosition().x < -1950.0f-400.0f){\n\t\tif(m_vecMoveSpeed.x < 0.0f)\n\t\t\tm_vecMoveSpeed.x *= -1.0f;\n\t\theading = GetForward().Heading();\n\t\tif(heading < 0.0f)\t// going east\n\t\t\tSetHeading(-heading);\n\t}\n\tif(GetPosition().y > 1950.0f){\n\t\tif(m_vecMoveSpeed.y > 0.0f)\n\t\t\tm_vecMoveSpeed.y *= -1.0f;\n\t\theading = GetForward().Heading();\n\t\tif(heading < HALFPI && heading > 0.0f)\n\t\t\tSetHeading(PI-heading);\n\t\telse if(heading > -HALFPI && heading < 0.0f)\n\t\t\tSetHeading(-PI-heading);\n\t}else if(GetPosition().y < -1950.0f){\n\t\tif(m_vecMoveSpeed.y < 0.0f)\n\t\t\tm_vecMoveSpeed.y *= -1.0f;\n\t\theading = GetForward().Heading();\n\t\tif(heading > HALFPI)\n\t\t\tSetHeading(PI-heading);\n\t\telse if(heading < -HALFPI)\n\t\t\tSetHeading(-PI-heading);\n\t}\n\n\tif(bInfiniteMass){\n\t\tm_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);\n\t\tm_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f);\n\t\tm_vecMoveFriction = CVector(0.0f, 0.0f, 0.0f);\n\t\tm_vecTurnFriction = CVector(0.0f, 0.0f, 0.0f);\n\t}else if(!skipPhysics &&\n\t         (m_fGasPedal == 0.0f && brake == 0.0f || GetStatus() == STATUS_WRECKED)){\n\t\tif(Abs(m_vecMoveSpeed.x) < 0.005f &&\n\t\t   Abs(m_vecMoveSpeed.y) < 0.005f &&\n\t\t   Abs(m_vecMoveSpeed.z) < 0.005f &&\n\t\t   !(m_fDamageImpulse > 0.0f && m_pDamageEntity == FindPlayerPed()) &&\n\t\t   (m_aSuspensionSpringRatioPrev[0] < 1.0f || m_aSuspensionSpringRatioPrev[1] < 1.0f ||\n\t\t    m_aSuspensionSpringRatioPrev[2] < 1.0f || m_aSuspensionSpringRatioPrev[3] < 1.0f)){\n\t\t\tm_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);\n\t\t\tm_vecTurnSpeed.z = 0.0f;\n\t\t}\n\t}\n\n\tif(IsRealHeli() && bHeliDestroyed && !bRenderScorched){\n\t\tApplyMoveForce(0.0f, 0.0f, -2.0f*CTimer::GetTimeStep());\n\t\tm_vecTurnSpeed.z += -0.002f*CTimer::GetTimeStep();\n\t\tm_vecTurnSpeed.x += -0.0002f*CTimer::GetTimeStep();\n\n\t\tRwRGBA col = { 84, 84, 84, 255 };\n\t\tCParticle::AddParticle(PARTICLE_ENGINE_SMOKE, GetMatrix()*CVector(0.0f, 0.0f, -10.0f),\n\t\t\tCVector(0.0f, 0.0f, 0.0f), nil, 0.7f, col, 0, 0, 0, 3000);\n\n\t\tif(CWorld::TestSphereAgainstWorld(GetPosition(), 10.0f, this, true, false, false, false, false, false) ||\n\t\t   GetPosition().z < 6.0f)\n\t\t\tif(!bRenderScorched){\t// we already know this is true...\n\t\t\t\tCExplosion::AddExplosion(this, nil, EXPLOSION_CAR, GetPosition(), 0);\n\t\t\t\tbRenderScorched = true;\n\t\t\t}\n\t}\n}\n\n#pragma optimize(\"\", on)\n\nvoid\nCAutomobile::Teleport(CVector pos)\n{\n\tCWorld::Remove(this);\n\n\tSetPosition(pos);\n\tSetOrientation(0.0f, 0.0f, 0.0f);\n\tSetMoveSpeed(0.0f, 0.0f, 0.0f);\n\tSetTurnSpeed(0.0f, 0.0f, 0.0f);\n\n\tResetSuspension();\n\n\tCWorld::Add(this);\n}\n\nvoid\nCAutomobile::PreRender(void)\n{\n\tint i, j, n;\n\tCVehicleModelInfo *mi = (CVehicleModelInfo*)CModelInfo::GetModelInfo(GetModelIndex());\n\n\tif(GetModelIndex() == MI_RHINO && m_aCarNodes[CAR_WINDSCREEN]){\n\t\t// Rotate Rhino turret\n\t\tCMatrix m;\n\t\tCVector p;\n\t\tm.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WINDSCREEN]));\n\t\tp = m.GetPosition();\n\t\tm.SetRotateZ(m_fCarGunLR);\n\t\tm.Translate(p);\n\t\tm.UpdateRW();\n\t}\n\n\tif(GetModelIndex() == MI_RCBANDIT){\n\t\tCVector pos = GetMatrix() * CVector(0.218f, -0.444f, 0.391f);\n\t\tCAntennas::RegisterOne((uintptr)this, GetUp(), pos, 1.0f);\n\t}\n\n\tfloat fwdSpeed = DotProduct(m_vecMoveSpeed, GetForward())*180.0f;\n\n\n\t// Wheel particles\n\n\tif(GetModelIndex() == MI_DODO || GetVehicleAppearance() != VEHICLE_APPEARANCE_CAR){\n\t\t; // nothing\n\t}else if(GetModelIndex() == MI_RCBANDIT){\n\t\tfor(i = 0; i < 4; i++){\n\t\t\t// Game has same code three times here\n\t\t\tswitch(m_aWheelState[i]){\n\t\t\tcase WHEEL_STATE_SPINNING:\n\t\t\tcase WHEEL_STATE_SKIDDING:\n\t\t\tcase WHEEL_STATE_FIXED:\n\t\t\t\tCParticle::AddParticle(PARTICLE_RUBBER_SMOKE,\n\t\t\t\t\tm_aWheelColPoints[i].point + CVector(0.0f, 0.0f, 0.05f),\n\t\t\t\t\tCVector(0.0f, 0.0f, 0.0f), nil, 0.1f);\n\t\t\t\tbreak;\n\t\t\tdefault: break;\n\t\t\t}\n\t\t}\n\t}else{\n\t\tif(GetStatus() == STATUS_SIMPLE){\n\t\t\tCMatrix mat;\n\t\t\tCVector pos;\n\n\t\t\tmat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_RB]));\n\t\t\tpos = mat.GetPosition();\n\t\t\tpos.z = 1.5f*m_aWheelPosition[CARWHEEL_REAR_RIGHT];\n\t\t\tm_aWheelColPoints[CARWHEEL_REAR_RIGHT].point = GetMatrix() * pos;\n\t\t\tm_aWheelColPoints[CARWHEEL_REAR_RIGHT].surfaceB = SURFACE_DEFAULT;\n\n\t\t\tmat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_LB]));\n\t\t\tpos = mat.GetPosition();\n\t\t\tpos.z = 1.5f*m_aWheelPosition[CARWHEEL_REAR_LEFT];\n\t\t\tm_aWheelColPoints[CARWHEEL_REAR_LEFT].point = GetMatrix() * pos;\n\t\t\tm_aWheelColPoints[CARWHEEL_REAR_LEFT].surfaceB = SURFACE_DEFAULT;\n\n\t\t\tmat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_RF]));\n\t\t\tpos = mat.GetPosition();\n\t\t\tpos.z = 1.5f*m_aWheelPosition[CARWHEEL_FRONT_RIGHT];\n\t\t\tm_aWheelColPoints[CARWHEEL_FRONT_RIGHT].point = GetMatrix() * pos;\n\t\t\tm_aWheelColPoints[CARWHEEL_FRONT_RIGHT].surfaceB = SURFACE_DEFAULT;\n\n\t\t\tmat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_LF]));\n\t\t\tpos = mat.GetPosition();\n\t\t\tpos.z = 1.5f*m_aWheelPosition[CARWHEEL_FRONT_LEFT];\n\t\t\tm_aWheelColPoints[CARWHEEL_FRONT_LEFT].point = GetMatrix() * pos;\n\t\t\tm_aWheelColPoints[CARWHEEL_FRONT_LEFT].surfaceB = SURFACE_DEFAULT;\n\t\t}\n\n\t\tint drawParticles = Abs(fwdSpeed) < 90.0f;\n\t\tif(GetStatus() == STATUS_SIMPLE || GetStatus() == STATUS_PHYSICS ||\n\t\t   GetStatus() == STATUS_PLAYER || GetStatus() == STATUS_PLAYER_PLAYBACKFROMBUFFER){\n\t\t\tbool rearSkidding = false;\n\t\t\tif(m_aWheelState[CARWHEEL_REAR_LEFT] == WHEEL_STATE_SKIDDING ||\n\t\t\t   m_aWheelState[CARWHEEL_REAR_RIGHT] == WHEEL_STATE_SKIDDING)\n\t\t\t\trearSkidding = true;\n\n\t\t\tfor(i = 0; i < 4; i++){\n\t\t\t\tif(m_aSuspensionSpringRatioPrev[i] < 1.0f && m_aWheelColPoints[i].surfaceB != SURFACE_WATER)\n\t\t\t\tswitch(m_aWheelState[i]){\n\t\t\t\tcase WHEEL_STATE_SPINNING:\n\t\t\t\t\tif(AddWheelDirtAndWater(&m_aWheelColPoints[i], drawParticles)){\n\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_BURNINGRUBBER_SMOKE,\n\t\t\t\t\t\t\tm_aWheelColPoints[i].point + CVector(0.0f, 0.0f, 0.25f),\n\t\t\t\t\t\t\tCVector(0.0f, 0.0f, 0.0f));\n\n\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_BURNINGRUBBER_SMOKE,\n\t\t\t\t\t\t\tm_aWheelColPoints[i].point + CVector(0.0f, 0.0f, 0.25f),\n\t\t\t\t\t\t\tCVector(0.0f, 0.0f, 0.05f));\n\t\t\t\t\t}\n\n\t\t\t\t\tCParticle::AddParticle(PARTICLE_RUBBER_SMOKE,\n\t\t\t\t\t\tm_aWheelColPoints[i].point + CVector(0.0f, 0.0f, 0.25f),\n\t\t\t\t\t\tCVector(0.0f, 0.0f, 0.0f));\n\n\t\t\t\t\tif(m_aWheelTimer[i] > 0.0f)\n\t\t\t\t\t\tCSkidmarks::RegisterOne((uintptr)this + i, m_aWheelColPoints[i].point,\n\t\t\t\t\t\t\tGetForward().x, GetForward().y,\n\t\t\t\t\t\t\tm_aWheelSkidmarkType[i], &m_aWheelSkidmarkBloody[i]);\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase WHEEL_STATE_SKIDDING:\n\t\t\t\t\tif(i == CARWHEEL_REAR_LEFT || i == CARWHEEL_REAR_RIGHT || rearSkidding){\n\t\t\t\t\t\t// same as below\n\n\t\t\t\t\t\tif(Abs(fwdSpeed) > 5.0f){\n\t\t\t\t\t\t\tAddWheelDirtAndWater(&m_aWheelColPoints[i], drawParticles);\n\n\t\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_RUBBER_SMOKE,\n\t\t\t\t\t\t\t\tm_aWheelColPoints[i].point + CVector(0.0f, 0.0f, 0.25f),\n\t\t\t\t\t\t\t\tCVector(0.0f, 0.0f, 0.0f));\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif(m_aWheelTimer[i] > 0.0f)\n\t\t\t\t\t\t\tCSkidmarks::RegisterOne((uintptr)this + i, m_aWheelColPoints[i].point,\n\t\t\t\t\t\t\t\tGetForward().x, GetForward().y,\n\t\t\t\t\t\t\t\tm_aWheelSkidmarkType[i], &m_aWheelSkidmarkBloody[i]);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase WHEEL_STATE_FIXED:\n\t\t\t\t\tif(Abs(fwdSpeed) > 5.0f){\n\t\t\t\t\t\tAddWheelDirtAndWater(&m_aWheelColPoints[i], drawParticles);\n\n\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_RUBBER_SMOKE,\n\t\t\t\t\t\t\tm_aWheelColPoints[i].point + CVector(0.0f, 0.0f, 0.25f),\n\t\t\t\t\t\t\tCVector(0.0f, 0.0f, 0.0f));\n\t\t\t\t\t}\n\n\t\t\t\t\tif(m_aWheelTimer[i] > 0.0f)\n\t\t\t\t\t\tCSkidmarks::RegisterOne((uintptr)this + i, m_aWheelColPoints[i].point,\n\t\t\t\t\t\t\tGetForward().x, GetForward().y,\n\t\t\t\t\t\t\tm_aWheelSkidmarkType[i], &m_aWheelSkidmarkBloody[i]);\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\tif(Abs(fwdSpeed) > 0.5f)\n\t\t\t\t\t\tAddWheelDirtAndWater(&m_aWheelColPoints[i], drawParticles);\n\t\t\t\t\tif((m_aWheelSkidmarkBloody[i] || m_aWheelSkidmarkUnk[i]) && m_aWheelTimer[i] > 0.0f)\n\t\t\t\t\t\tCSkidmarks::RegisterOne((uintptr)this + i, m_aWheelColPoints[i].point,\n\t\t\t\t\t\t\tGetForward().x, GetForward().y,\n\t\t\t\t\t\t\tm_aWheelSkidmarkType[i], &m_aWheelSkidmarkBloody[i]);\n\t\t\t\t}\n\n\t\t\t\t// Sparks for friction of burst wheels\n\t\t\t\tif(Damage.GetWheelStatus(i) == WHEEL_STATUS_BURST && m_aSuspensionSpringRatioPrev[i] < 1.0f){\n\t\t\t\t\tstatic float speedSq;\n\t\t\t\t\tspeedSq = m_vecMoveSpeed.MagnitudeSqr();\n\t\t\t\t\tif(speedSq > SQR(0.1f) &&\n\t\t\t\t\t   m_aWheelColPoints[i].surfaceB != SURFACE_GRASS &&\n\t\t\t\t\t   m_aWheelColPoints[i].surfaceB != SURFACE_MUD_DRY &&\n\t\t\t\t\t   m_aWheelColPoints[i].surfaceB != SURFACE_SAND &&\n\t\t\t\t\t   m_aWheelColPoints[i].surfaceB != SURFACE_SAND_BEACH &&\n\t\t\t\t\t   m_aWheelColPoints[i].surfaceB != SURFACE_WATER){\n\t\t\t\t\t\tCVector normalSpeed = m_aWheelColPoints[i].normal * DotProduct(m_aWheelColPoints[i].normal, m_vecMoveSpeed);\n\t\t\t\t\t\tCVector frictionSpeed = m_vecMoveSpeed - normalSpeed;\n\t\t\t\t\t\tif(i == CARWHEEL_FRONT_LEFT || i == CARWHEEL_REAR_LEFT)\n\t\t\t\t\t\t\tfrictionSpeed -= 0.05f*GetRight();\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tfrictionSpeed += 0.05f*GetRight();\n\t\t\t\t\t\tCVector unusedRight = 0.15f*GetRight();\n\t\t\t\t\t\tCVector sparkDir = 0.25f*frictionSpeed;\n\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_SPARK_SMALL, m_aWheelColPoints[i].point, sparkDir);\n\n\t\t\t\t\t\tif(speedSq > 0.04f)\n\t\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_SPARK_SMALL, m_aWheelColPoints[i].point, sparkDir);\n\t\t\t\t\t\tif(speedSq > 0.16f){\n\t\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_SPARK_SMALL, m_aWheelColPoints[i].point, sparkDir);\n\t\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_SPARK_SMALL, m_aWheelColPoints[i].point, sparkDir);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif(m_aCarNodes[CAR_WHEEL_RM]){\n\t\t// assume middle wheels are two units before rear ones\n\t\tCVector offset = GetForward()*2.0f;\n\n\t\tswitch(m_aWheelState[CARWHEEL_REAR_LEFT]){\n\t\t// Game has same code three times here\n\t\tcase WHEEL_STATE_SPINNING:\n\t\tcase WHEEL_STATE_SKIDDING:\n\t\tcase WHEEL_STATE_FIXED:\n\t\t\tCParticle::AddParticle(PARTICLE_RUBBER_SMOKE,\n\t\t\t\tm_aWheelColPoints[CARWHEEL_REAR_LEFT].point + CVector(0.0f, 0.0f, 0.25f) + offset,\n\t\t\t\tCVector(0.0f, 0.0f, 0.0f));\n\n\t\t\tif(m_aWheelTimer[CARWHEEL_REAR_LEFT] > 0.0f)\n\t\t\t\tCSkidmarks::RegisterOne((uintptr)this + CARWHEEL_REAR_LEFT,\n\t\t\t\t\tm_aWheelColPoints[CARWHEEL_REAR_LEFT].point + offset,\n\t\t\t\t\tGetForward().x, GetForward().y,\n\t\t\t\t\tm_aWheelSkidmarkType[CARWHEEL_REAR_LEFT], &m_aWheelSkidmarkBloody[CARWHEEL_REAR_LEFT]);\n\t\t\tbreak;\n\t\tdefault: break;\n\t\t}\n\n\t\tswitch(m_aWheelState[CARWHEEL_REAR_RIGHT]){\n\t\t// Game has same code three times here\n\t\tcase WHEEL_STATE_SPINNING:\n\t\tcase WHEEL_STATE_SKIDDING:\n\t\tcase WHEEL_STATE_FIXED:\n\t\t\tCParticle::AddParticle(PARTICLE_RUBBER_SMOKE,\n\t\t\t\tm_aWheelColPoints[CARWHEEL_REAR_RIGHT].point + CVector(0.0f, 0.0f, 0.25f) + offset,\n\t\t\t\tCVector(0.0f, 0.0f, 0.0f));\n\n\t\t\tif(m_aWheelTimer[CARWHEEL_REAR_RIGHT] > 0.0f)\n\t\t\t\tCSkidmarks::RegisterOne((uintptr)this + CARWHEEL_REAR_RIGHT,\n\t\t\t\t\tm_aWheelColPoints[CARWHEEL_REAR_RIGHT].point + offset,\n\t\t\t\t\tGetForward().x, GetForward().y,\n\t\t\t\t\tm_aWheelSkidmarkType[CARWHEEL_REAR_RIGHT], &m_aWheelSkidmarkBloody[CARWHEEL_REAR_RIGHT]);\n\t\t\tbreak;\n\t\t\tdefault: break;\n\t\t}\n\t}\n\n\n\t// Rain on roof\n\tif(!CCullZones::CamNoRain() && !CCullZones::PlayerNoRain() &&\n\t   Abs(fwdSpeed) < 20.0f && CWeather::Rain > 0.02f){\n\t\tCColModel *colModel = GetColModel();\n\n\t\tfor(i = 0; i < colModel->numTriangles; i++){\n\t\t\tCVector p1, p2, p3, c;\n\n\t\t\tcolModel->GetTrianglePoint(p1, colModel->triangles[i].a);\n\t\t\tp1 = GetMatrix() * p1;\n\t\t\tcolModel->GetTrianglePoint(p2, colModel->triangles[i].b);\n\t\t\tp2 = GetMatrix() * p2;\n\t\t\tcolModel->GetTrianglePoint(p3, colModel->triangles[i].c);\n\t\t\tp3 = GetMatrix() * p3;\n\t\t\tc = (p1 + p2 + p3)/3.0f;\n\n\t\t\tn = 6.0f*CWeather::Rain;\n\t\t\tfor(j = 0; j <= n; j++)\n\t\t\t\tCParticle::AddParticle(PARTICLE_RAIN_SPLASHUP,\n\t\t\t\t\tc + CVector(CGeneral::GetRandomNumberInRange(-0.4f, 0.4f), CGeneral::GetRandomNumberInRange(-0.4f, 0.4f), 0.0f),\n\t\t\t\t\tCVector(0.0f, 0.0f, 0.0f),\n\t\t\t\t\tnil, 0.0f, 0, 0, CGeneral::GetRandomNumber() & 1);\n\t\t}\n\t}\n\n\tAddDamagedVehicleParticles();\n\n\t// Exhaust smoke\n\tif(bEngineOn && !(pHandling->Flags & HANDLING_NO_EXHAUST) && fwdSpeed < 130.0f){\n\t\tCVector exhaustPos = mi->m_positions[CAR_POS_EXHAUST];\n\t\tCVector pos1, pos2, dir1, dir2;\n\n\t\tif(exhaustPos != CVector(0.0f, 0.0f, 0.0f)){\n\t\t\tdir1.z = 0.0f;\n\t\t\tdir2.z = 0.0f;\n\t\t\tif(fwdSpeed < 10.0f){\n\t\t\t\tCVector steerFwd(-Sin(m_fSteerAngle), Cos(m_fSteerAngle), 0.0f);\n\t\t\t\tsteerFwd = Multiply3x3(GetMatrix(), steerFwd);\n\t\t\t\tfloat r = CGeneral::GetRandomNumberInRange(-0.06f, -0.03f);\n\t\t\t\tdir1.x = steerFwd.x * r;\n\t\t\t\tdir1.y = steerFwd.y * r;\n\t\t\t}else{\n\t\t\t\tdir1.x = m_vecMoveSpeed.x;\n\t\t\t\tdir1.y = m_vecMoveSpeed.y;\n\t\t\t}\n\n\t\t\tbool dblExhaust = false;\n\t\t\tpos1 = GetMatrix() * exhaustPos;\n\t\t\tif(pHandling->Flags & HANDLING_DBL_EXHAUST){\n\t\t\t\tdblExhaust = true;\n\t\t\t\tpos2 = exhaustPos;\n\t\t\t\tpos2.x = -pos2.x;\n\t\t\t\tpos2 = GetMatrix() * pos2;\n\t\t\t\tdir2 = dir1;\n\t\t\t}\n\n\t\t\tstatic float fumesLimit = 2.0f;\n\t\t\tif(CGeneral::GetRandomNumberInRange(1.0f, 3.0f)*(m_fGasPedal+1.1f) > fumesLimit)\n\t\t\t\tfor(i = 0; i < 4;){\n\t\t\t\t\tCParticle::AddParticle(PARTICLE_EXHAUST_FUMES, pos1, dir1);\n\t\t\t\t\tif(pHandling->Flags & HANDLING_DBL_EXHAUST)\n\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_EXHAUST_FUMES, pos2, dir2);\n\n\t\t\t\t\tstatic float extraFumesLimit = 0.5f;\n\t\t\t\t\tif(m_fGasPedal > extraFumesLimit && m_nCurrentGear < 3){\n\t\t\t\t\t\tif(CGeneral::GetRandomNumber() & 1)\n\t\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_EXHAUST_FUMES, pos1, dir1);\n\t\t\t\t\t\telse if(pHandling->Flags & HANDLING_DBL_EXHAUST)\n\t\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_EXHAUST_FUMES, pos2, dir2);\n\t\t\t\t\t}\n\n\t\t\t\t\t// Fire on Cuban hermes\n\t\t\t\t\tif(GetModelIndex() == MI_CUBAN && i == 1 && m_fGasPedal > 0.9f){\n\t\t\t\t\t\tif(m_nCurrentGear == 1 || m_nCurrentGear == 3 && (CTimer::GetTimeInMilliseconds()%1500) > 750){\n\t\t\t\t\t\t\tif(CGeneral::GetRandomNumber() & 1){\n\t\t\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_FIREBALL, pos1, dir1, nil, 0.05f, 0, 0, 2, 200);\n\t\t\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_FIREBALL, pos1, dir1, nil, 0.05f, 0, 0, 2, 200);\n\t\t\t\t\t\t\t}else{\n\t\t\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_FIREBALL, pos2, dir2, nil, 0.05f, 0, 0, 2, 200);\n\t\t\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_FIREBALL, pos2, dir2, nil, 0.05f, 0, 0, 2, 200);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif(GetStatus() == STATUS_PLAYER && (CTimer::GetFrameCounter()&3) == 0 &&\n\t\t\t\t\t   CWeather::Rain == 0.0f && i == 0){\n\t\t\t\t\t\tCVector camDist = GetPosition() - TheCamera.GetPosition();\n\t\t\t\t\t\tif(DotProduct(GetForward(), camDist) > 0.0f ||\n\t\t\t\t\t\t   TheCamera.GetLookDirection() == LOOKING_LEFT ||\n\t\t\t\t\t\t   TheCamera.GetLookDirection() == LOOKING_RIGHT){\n\t\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_HEATHAZE, pos1, CVector(0.0f, 0.0f, 0.0f));\n\t\t\t\t\t\t\tif(pHandling->Flags & HANDLING_DBL_EXHAUST)\n\t\t\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_HEATHAZE, pos2, CVector(0.0f, 0.0f, 0.0f));\n\n\t\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_HEATHAZE, pos1, CVector(0.0f, 0.0f, 0.0f));\n\t\t\t\t\t\t\tif(pHandling->Flags & HANDLING_DBL_EXHAUST)\n\t\t\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_HEATHAZE, pos2, CVector(0.0f, 0.0f, 0.0f));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif(GetModelIndex() == MI_CUBAN && i < 1){\n\t\t\t\t\t\ti = 1;\n\t\t\t\t\t\tpos1 = GetMatrix() * CVector(1.134f, -1.276f, -0.56f);\n\t\t\t\t\t\tpos2 = GetMatrix() * CVector(-1.134f, -1.276f, -0.56f);\n\t\t\t\t\t\tdir1 += 0.05f*GetRight();\n\t\t\t\t\t\tdir2 -= 0.05f*GetRight();\n\t\t\t\t\t}else\n\t\t\t\t\t\ti = 99;\n\t\t\t\t}\n\t\t}\n\t}\n\n\n\t// Siren and taxi lights\n\tswitch(GetModelIndex()){\n\tcase MI_FIRETRUCK:\n\tcase MI_AMBULAN:\n\tcase MI_POLICE:\n\tcase MI_ENFORCER:\n\t\tif(m_bSirenOrAlarm){\n\t\t\tCVector pos1, pos2;\n\t\t\tuint8 r1, g1, b1;\n\t\t\tuint8 r2, g2, b2;\n\t\t\tuint8 r, g, b;\n\n\t\t\tswitch(GetModelIndex()){\n\t\t\tcase MI_FIRETRUCK:\n\t\t\t\tpos1 = CVector(1.1f,  1.7f, 2.0f);\n\t\t\t\tpos2 = CVector(-1.1f, 1.7f, 2.0f);\n\t\t\t\tr1 = 255; g1 = 0; b1 = 0;\n\t\t\t\tr2 = 255; g2 = 255; b2 = 0;\n\t\t\t\tbreak;\n\t\t\tcase MI_AMBULAN:\n\t\t\t\tpos1 = CVector(1.1f,  0.9f, 1.6f);\n\t\t\t\tpos2 = CVector(-1.1f, 0.9f, 1.6f);\n\t\t\t\tr1 = 255; g1 = 0; b1 = 0;\n\t\t\t\tr2 = 255; g2 = 255; b2 = 255;\n\t\t\t\tbreak;\n\t\t\tcase MI_POLICE:\n\t\t\t\tpos1 = CVector(0.7f,  -0.4f, 1.0f);\n\t\t\t\tpos2 = CVector(-0.7f, -0.4f, 1.0f);\n\t\t\t\tr1 = 255; g1 = 0; b1 = 0;\n\t\t\t\tr2 = 0; g2 = 0; b2 = 255;\n\t\t\t\tbreak;\n\t\t\tcase MI_ENFORCER:\n\t\t\t\tpos1 = CVector(1.1f,  0.8f, 1.2f);\n\t\t\t\tpos2 = CVector(-1.1f, 0.8f, 1.2f);\n\t\t\t\tr1 = 255; g1 = 0; b1 = 0;\n\t\t\t\tr2 = 0; g2 = 0; b2 = 255;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tuint32 t = CTimer::GetTimeInMilliseconds() & 0x3FF; // 1023\n\t\t\tif(t < 512){\n\t\t\t\tr = r1/6;\n\t\t\t\tg = g1/6;\n\t\t\t\tb = b1/6;\n\t\t\t}else{\n\t\t\t\tr = r2/6;\n\t\t\t\tg = g2/6;\n\t\t\t\tb = b2/6;\n\t\t\t}\n\n\t\t\tt = CTimer::GetTimeInMilliseconds() & 0x1FF; // 511\n\t\t\tif(t < 100){\n\t\t\t\tfloat f = t/100.0f;\n\t\t\t\tr *= f;\n\t\t\t\tg *= f;\n\t\t\t\tb *= f;\n\t\t\t}else if(t > 412){\n\t\t\t\tfloat f = (512-t)/100.0f;\n\t\t\t\tr *= f;\n\t\t\t\tg *= f;\n\t\t\t\tb *= f;\n\t\t\t}\n\n\t\t\tCVector pos = GetPosition();\n\t\t\tfloat angle = (CTimer::GetTimeInMilliseconds() & 0x3FF)*TWOPI/0x3FF;\n\t\t\tfloat s = 8.0f*Sin(angle);\n\t\t\tfloat c = 8.0f*Cos(angle);\n\t\t\t//CShadows::StoreCarLightShadow(this, (uintptr)this + 21, gpShadowHeadLightsTex,\n\t\t\t//\t&pos, c, s, s, -c, r, g, b, 8.0f);\n\n\t\t\tCPointLights::AddLight(CPointLights::LIGHT_POINT,\n\t\t\t\tpos + GetUp()*2.0f, CVector(0.0f, 0.0f, 0.0f), 12.0f,\n\t\t\t\tr*0.02f, g*0.02f, b*0.02f, CPointLights::FOG_NONE, true);\n\n\t\t\tpos1 = GetMatrix() * pos1;\n\t\t\tpos2 = GetMatrix() * pos2;\n\n\t\t\tfor(i = 0; i < 4; i++){\n\t\t\t\tuint8 sirenTimer = ((CTimer::GetTimeInMilliseconds() + (i<<6))>>8) & 3;\n\t\t\t\tpos = (pos1*i + pos2*(3.0f-i))/3.0f;\n\n\t\t\t\tswitch(sirenTimer){\n\t\t\t\tcase 0:\n\t\t\t\t\tCCoronas::RegisterCorona((uintptr)this + 21 + i,\n\t\t\t\t\t\tr1, g1, b1, 255,\n\t\t\t\t\t\tpos, 0.4f, 50.0f,\n\t\t\t\t\t\tCCoronas::TYPE_STAR,\n\t\t\t\t\t\ti == 1 ? CCoronas::FLARE_HEADLIGHTS : CCoronas::FLARE_NONE,\n\t\t\t\t\t\tCCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 2:\n\t\t\t\t\tCCoronas::RegisterCorona((uintptr)this + 21 + i,\n\t\t\t\t\t\tr2, g2, b2, 255,\n\t\t\t\t\t\tpos, 0.4f, 50.0f,\n\t\t\t\t\t\tCCoronas::TYPE_STAR,\n\t\t\t\t\t\tCCoronas::FLARE_NONE,\n\t\t\t\t\t\tCCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tCCoronas::UpdateCoronaCoors((uintptr)this + 21 + i, pos, 50.0f, 0.0f);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tbreak;\n\n\tcase MI_FBIRANCH:\n\tcase MI_VICECHEE:\n\t\tif(m_bSirenOrAlarm){\n\t\t\tCVector pos = GetMatrix() * CVector(0.4f, 0.6f, 0.3f);\n\t\t\tif(CTimer::GetTimeInMilliseconds() & 0x100 &&\n\t\t\t   DotProduct(GetForward(), GetPosition() - TheCamera.GetPosition()) < 0.0f)\n\t\t\t\tif(GetModelIndex() == MI_VICECHEE)\n\t\t\t\t\tCCoronas::RegisterCorona((uintptr)this + 21,\n\t\t\t\t\t\t255, 70, 70, 255,\n\t\t\t\t\t\tpos, 0.4f, 50.0f,\n\t\t\t\t\t\tCCoronas::TYPE_STAR,\n\t\t\t\t\t\tCCoronas::FLARE_NONE,\n\t\t\t\t\t\tCCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);\n\t\t\t\telse\n\t\t\t\t\tCCoronas::RegisterCorona((uintptr)this + 21,\n\t\t\t\t\t\t0, 0, 255, 255,\n\t\t\t\t\t\tpos, 0.4f, 50.0f,\n\t\t\t\t\t\tCCoronas::TYPE_STAR,\n\t\t\t\t\t\tCCoronas::FLARE_NONE,\n\t\t\t\t\t\tCCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);\n\t\t\telse\n\t\t\t\tCCoronas::UpdateCoronaCoors((uintptr)this + 21, pos, 50.0f, 0.0f);\n\t\t}\n\t\tbreak;\n\n\tcase MI_TAXI:\n\tcase MI_CABBIE:\n\tcase MI_ZEBRA:\n\tcase MI_KAUFMAN:\n\t\tif(bTaxiLight){\n\t\t\tCVector pos = GetPosition() + GetUp()*0.95f;\n\t\t\tCCoronas::RegisterCorona((uintptr)this + 21,\n\t\t\t\t128, 128, 0, 255,\n\t\t\t\tpos, 0.8f, 50.0f,\n\t\t\t\tCCoronas::TYPE_NORMAL,\n\t\t\t\tCCoronas::FLARE_NONE,\n\t\t\t\tCCoronas::REFLECTION_ON, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);\n\t\t\tCPointLights::AddLight(CPointLights::LIGHT_POINT,\n\t\t\t\tpos, CVector(0.0f, 0.0f, 0.0f), 10.0f,\n\t\t\t\t1.0f, 1.0f, 0.5f, CPointLights::FOG_NONE, true);\n\t\t}\n\t\tbreak;\n\t}\n\n\tif(GetModelIndex() != MI_RCBANDIT && GetModelIndex() != MI_DODO &&\n\t   GetModelIndex() != MI_RHINO && GetModelIndex() != MI_RCBARON &&\n\t   GetVehicleAppearance() != VEHICLE_APPEARANCE_HELI) {\n\t// Process lights\n\n\t// Turn lights on/off\n\tbool shouldLightsBeOn = \n\t\tCClock::GetHours() > 20 ||\n\t\tCClock::GetHours() > 19 && CClock::GetMinutes() > (m_randomSeed & 0x3F) ||\n\t\tCClock::GetHours() < 7 ||\n\t\tCClock::GetHours() < 8 && CClock::GetMinutes() < (m_randomSeed & 0x3F) ||\n\t\tm_randomSeed/50000.0f < CWeather::Foggyness ||\n\t\tm_randomSeed/50000.0f < CWeather::WetRoads;\n\tif(shouldLightsBeOn != bLightsOn && GetStatus() != STATUS_WRECKED){\n\t\tif(GetStatus() == STATUS_ABANDONED){\n\t\t\t// Turn off lights on abandoned vehicles only when we they're far away\n\t\t\tif(bLightsOn &&\n\t\t\t   Abs(TheCamera.GetPosition().x - GetPosition().x) + Abs(TheCamera.GetPosition().y - GetPosition().y) > 100.0f)\n\t\t\t\tbLightsOn = false;\n\t\t}else\n\t\t\tbLightsOn = shouldLightsBeOn;\n\t}\n\n\t// Actually render the lights\n\tbool alarmOn = false;\n\tbool alarmOff = false;\n\tif(IsAlarmOn()){\n\t\tif(CTimer::GetTimeInMilliseconds() & 0x100)\n\t\t\talarmOn = true;\n\t\telse\n\t\t\talarmOff = true;\n\t}\n\tif(bEngineOn && bLightsOn || alarmOn || alarmOff){\n\t\tCVector lookVector = GetPosition() - TheCamera.GetPosition();\n\t\tfloat camDist = lookVector.Magnitude();\n\t\tif(camDist != 0.0f)\n\t\t\tlookVector *= 1.0f/camDist;\n\t\telse\n\t\t\tlookVector = CVector(1.0f, 0.0f, 0.0f);\n\n\t\t// 1.0 if directly behind car, -1.0 if in front\n\t\tfloat behindness = DotProduct(lookVector, GetForward());\n\t\tbehindness = clamp(behindness, -1.0f, 1.0f);\t// shouldn't be necessary\n\t\t// 0.0 if behind car, PI if in front\n\t\t// Abs not necessary\n\t\tfloat angle = Abs(Acos(behindness));\n\n\t\t// Headlights\n\n\t\tCVector headLightPos = mi->m_positions[CAR_POS_HEADLIGHTS];\n\t\tCVector lightR = GetMatrix() * headLightPos;\n\t\tCVector lightL = lightR;\n\t\tlightL -= GetRight()*2.0f*headLightPos.x;\n\n\t\t// Headlight coronas\n\t\tif(DotProduct(lightR-TheCamera.GetPosition(), GetForward()) < 0.0f &&\n\t\t   (TheCamera.Cams[TheCamera.ActiveCam].Mode != CCam::MODE_1STPERSON || this != FindPlayerVehicle())){\n\t\t\t// In front of car\n\t\t\tfloat intensity = -0.5f*behindness + 0.3f;\n\t\t\tfloat size = 1.0f - behindness;\n\n\t\t\tif(behindness < -0.97f && camDist < 30.0f){\n\t\t\t\t// Directly in front and not too far away\n\t\t\t\tif(pHandling->Flags & HANDLING_HALOGEN_LIGHTS){\n\t\t\t\t\tif(Damage.GetLightStatus(VEHLIGHT_FRONT_LEFT) == LIGHT_STATUS_OK)\n\t\t\t\t\t\tCCoronas::RegisterCorona((uintptr)this + 6, 150, 150, 195, 255,\n\t\t\t\t\t\t\tlightL, 1.2f, 45.0f*TheCamera.LODDistMultiplier,\n\t\t\t\t\t\t\tCCoronas::TYPE_HEADLIGHT, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON,\n\t\t\t\t\t\t\tCCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, angle);\n\t\t\t\t\tif(Damage.GetLightStatus(VEHLIGHT_FRONT_RIGHT) == LIGHT_STATUS_OK)\n\t\t\t\t\t\tCCoronas::RegisterCorona((uintptr)this + 7, 150, 150, 195, 255,\n\t\t\t\t\t\t\tlightR, 1.2f, 45.0f*TheCamera.LODDistMultiplier,\n\t\t\t\t\t\t\tCCoronas::TYPE_HEADLIGHT, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON,\n\t\t\t\t\t\t\tCCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, angle);\n\t\t\t\t}else{\n\t\t\t\t\tif(Damage.GetLightStatus(VEHLIGHT_FRONT_LEFT) == LIGHT_STATUS_OK)\n\t\t\t\t\t\tCCoronas::RegisterCorona((uintptr)this + 6, 160, 160, 140, 255,\n\t\t\t\t\t\t\tlightL, 1.2f, 45.0f*TheCamera.LODDistMultiplier,\n\t\t\t\t\t\t\tCCoronas::TYPE_HEADLIGHT, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON,\n\t\t\t\t\t\t\tCCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, angle);\n\t\t\t\t\tif(Damage.GetLightStatus(VEHLIGHT_FRONT_RIGHT) == LIGHT_STATUS_OK)\n\t\t\t\t\t\tCCoronas::RegisterCorona((uintptr)this + 7, 160, 160, 140, 255,\n\t\t\t\t\t\t\tlightR, 1.2f, 45.0f*TheCamera.LODDistMultiplier,\n\t\t\t\t\t\t\tCCoronas::TYPE_HEADLIGHT, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON,\n\t\t\t\t\t\t\tCCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, angle);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif(alarmOff){\n\t\t\t\tif(Damage.GetLightStatus(VEHLIGHT_FRONT_LEFT) == LIGHT_STATUS_OK)\n\t\t\t\t\tCCoronas::RegisterCorona((uintptr)this, 0, 0, 0, 0,\n\t\t\t\t\t\tlightL, size, 0.0f,\n\t\t\t\t\t\tCCoronas::TYPE_STREAK, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON,\n\t\t\t\t\t\tCCoronas::LOSCHECK_OFF, CCoronas::STREAK_ON, angle);\n\t\t\t\tif(Damage.GetLightStatus(VEHLIGHT_FRONT_RIGHT) == LIGHT_STATUS_OK)\n\t\t\t\t\tCCoronas::RegisterCorona((uintptr)this + 1, 0, 0, 0, 0,\n\t\t\t\t\t\tlightR, size, 0.0f,\n\t\t\t\t\t\tCCoronas::TYPE_STREAK, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON,\n\t\t\t\t\t\tCCoronas::LOSCHECK_OFF, CCoronas::STREAK_ON, angle);\n\t\t\t}else{\n\t\t\t\tif(pHandling->Flags & HANDLING_HALOGEN_LIGHTS){\n\t\t\t\t\tif(Damage.GetLightStatus(VEHLIGHT_FRONT_LEFT) == LIGHT_STATUS_OK)\n\t\t\t\t\t\tCCoronas::RegisterCorona((uintptr)this, 190*intensity, 190*intensity, 255*intensity, 255,\n\t\t\t\t\t\t\tlightL, size, 50.0f*TheCamera.LODDistMultiplier,\n\t\t\t\t\t\t\tCCoronas::TYPE_STREAK, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON,\n\t\t\t\t\t\t\tCCoronas::LOSCHECK_OFF, CCoronas::STREAK_ON, angle);\n\t\t\t\t\tif(Damage.GetLightStatus(VEHLIGHT_FRONT_RIGHT) == LIGHT_STATUS_OK)\n\t\t\t\t\t\tCCoronas::RegisterCorona((uintptr)this + 1, 190*intensity, 190*intensity, 255*intensity, 255,\n\t\t\t\t\t\t\tlightR, size, 50.0f*TheCamera.LODDistMultiplier,\n\t\t\t\t\t\t\tCCoronas::TYPE_STREAK, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON,\n\t\t\t\t\t\t\tCCoronas::LOSCHECK_OFF, CCoronas::STREAK_ON, angle);\n\t\t\t\t}else{\n\t\t\t\t\tif(Damage.GetLightStatus(VEHLIGHT_FRONT_LEFT) == LIGHT_STATUS_OK)\n\t\t\t\t\t\tCCoronas::RegisterCorona((uintptr)this, 210*intensity, 210*intensity, 195*intensity, 255,\n\t\t\t\t\t\t\tlightL, size, 50.0f*TheCamera.LODDistMultiplier,\n\t\t\t\t\t\t\tCCoronas::TYPE_STREAK, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON,\n\t\t\t\t\t\t\tCCoronas::LOSCHECK_OFF, CCoronas::STREAK_ON, angle);\n\t\t\t\t\tif(Damage.GetLightStatus(VEHLIGHT_FRONT_RIGHT) == LIGHT_STATUS_OK)\n\t\t\t\t\t\tCCoronas::RegisterCorona((uintptr)this + 1, 210*intensity, 210*intensity, 195*intensity, 255,\n\t\t\t\t\t\t\tlightR, size, 50.0f*TheCamera.LODDistMultiplier,\n\t\t\t\t\t\t\tCCoronas::TYPE_STREAK, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON,\n\t\t\t\t\t\t\tCCoronas::LOSCHECK_OFF, CCoronas::STREAK_ON, angle);\n\t\t\t\t}\n\t\t\t}\n\t\t}else{\n\t\t\t// Behind car\n\t\t\tif(Damage.GetLightStatus(VEHLIGHT_FRONT_LEFT) == LIGHT_STATUS_OK)\n\t\t\t\tCCoronas::UpdateCoronaCoors((uintptr)this, lightL, 50.0f*TheCamera.LODDistMultiplier, angle);\n\t\t\tif(Damage.GetLightStatus(VEHLIGHT_FRONT_RIGHT) == LIGHT_STATUS_OK)\n\t\t\t\tCCoronas::UpdateCoronaCoors((uintptr)this + 1, lightR, 50.0f*TheCamera.LODDistMultiplier, angle);\n\t\t}\n\n\t\t// bright lights\n\t\tif(Damage.GetLightStatus(VEHLIGHT_FRONT_LEFT) == LIGHT_STATUS_OK && !bNoBrightHeadLights)\n\t\t\tCBrightLights::RegisterOne(lightL, GetUp(), GetRight(), GetForward(), pHandling->FrontLights + BRIGHTLIGHT_FRONT);\n\t\tif(Damage.GetLightStatus(VEHLIGHT_FRONT_RIGHT) == LIGHT_STATUS_OK && !bNoBrightHeadLights)\n\t\t\tCBrightLights::RegisterOne(lightR, GetUp(), GetRight(), GetForward(), pHandling->FrontLights + BRIGHTLIGHT_FRONT);\n\n\t\t// Taillights\n\n\t\tCVector tailLightPos = mi->m_positions[CAR_POS_TAILLIGHTS];\n\t\tlightR = GetMatrix() * tailLightPos;\n\t\tlightL = lightR;\n\t\tlightL -= GetRight()*2.0f*tailLightPos.x;\n\n\t\t// Taillight coronas\n\t\tif(DotProduct(lightR-TheCamera.GetPosition(), GetForward()) > 0.0f){\n\t\t\t// Behind car\n\t\t\tfloat intensity = 0.4f*behindness + 0.4f;\n\t\t\tfloat size = (behindness + 1.0f)/2.0f;\n\n\t\t\tif(m_fGasPedal < 0.0f){\n\t\t\t\t// reversing\n\t\t\t\tintensity += 0.4f;\n\t\t\t\tsize += 0.3f;\n\t\t\t\tif(Damage.GetLightStatus(VEHLIGHT_REAR_LEFT) == LIGHT_STATUS_OK)\n\t\t\t\t\tCCoronas::RegisterCorona((uintptr)this + 2, 128*intensity, 128*intensity, 128*intensity, 255,\n\t\t\t\t\t\tlightL, size, 50.0f*TheCamera.LODDistMultiplier,\n\t\t\t\t\t\tCCoronas::TYPE_STREAK, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON,\n\t\t\t\t\t\tCCoronas::LOSCHECK_OFF, CCoronas::STREAK_ON, angle);\n\t\t\t\tif(Damage.GetLightStatus(VEHLIGHT_REAR_RIGHT) == LIGHT_STATUS_OK)\n\t\t\t\t\tCCoronas::RegisterCorona((uintptr)this + 3, 128*intensity, 128*intensity, 128*intensity, 255,\n\t\t\t\t\t\tlightR, size, 50.0f*TheCamera.LODDistMultiplier,\n\t\t\t\t\t\tCCoronas::TYPE_STREAK, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON,\n\t\t\t\t\t\tCCoronas::LOSCHECK_OFF, CCoronas::STREAK_ON, angle);\n\t\t\t}else{\n\t\t\t\tif(m_fBrakePedal > 0.0f){\n\t\t\t\t\tintensity += 0.4f;\n\t\t\t\t\tsize += 0.3f;\n\t\t\t\t}\n\n\t\t\t\tif(alarmOff){\n\t\t\t\t\tif(Damage.GetLightStatus(VEHLIGHT_REAR_LEFT) == LIGHT_STATUS_OK)\n\t\t\t\t\t\tCCoronas::RegisterCorona((uintptr)this + 2, 0, 0, 0, 0,\n\t\t\t\t\t\t\tlightL, size, 0.0f,\n\t\t\t\t\t\t\tCCoronas::TYPE_STREAK, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON,\n\t\t\t\t\t\t\tCCoronas::LOSCHECK_OFF, CCoronas::STREAK_ON, angle);\n\t\t\t\t\tif(Damage.GetLightStatus(VEHLIGHT_REAR_RIGHT) == LIGHT_STATUS_OK)\n\t\t\t\t\t\tCCoronas::RegisterCorona((uintptr)this + 3, 0, 0, 0, 0,\n\t\t\t\t\t\t\tlightR, size, 0.0f,\n\t\t\t\t\t\t\tCCoronas::TYPE_STREAK, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON,\n\t\t\t\t\t\t\tCCoronas::LOSCHECK_OFF, CCoronas::STREAK_ON, angle);\n\t\t\t\t}else{\n\t\t\t\t\tif(Damage.GetLightStatus(VEHLIGHT_REAR_LEFT) == LIGHT_STATUS_OK)\n\t\t\t\t\t\tCCoronas::RegisterCorona((uintptr)this + 2, 128*intensity, 0, 0, 255,\n\t\t\t\t\t\t\tlightL, size, 50.0f*TheCamera.LODDistMultiplier,\n\t\t\t\t\t\t\tCCoronas::TYPE_STREAK, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON,\n\t\t\t\t\t\t\tCCoronas::LOSCHECK_OFF, CCoronas::STREAK_ON, angle);\n\t\t\t\t\tif(Damage.GetLightStatus(VEHLIGHT_REAR_RIGHT) == LIGHT_STATUS_OK)\n\t\t\t\t\t\tCCoronas::RegisterCorona((uintptr)this + 3, 128*intensity, 0, 0, 255,\n\t\t\t\t\t\t\tlightR, size, 50.0f*TheCamera.LODDistMultiplier,\n\t\t\t\t\t\t\tCCoronas::TYPE_STREAK, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON,\n\t\t\t\t\t\t\tCCoronas::LOSCHECK_OFF, CCoronas::STREAK_ON, angle);\n\t\t\t\t}\n\t\t\t}\n\t\t}else{\n\t\t\t// In front of car\n\t\t\tif(Damage.GetLightStatus(VEHLIGHT_REAR_LEFT) == LIGHT_STATUS_OK)\n\t\t\t\tCCoronas::UpdateCoronaCoors((uintptr)this + 2, lightL, 50.0f*TheCamera.LODDistMultiplier, angle);\n\t\t\tif(Damage.GetLightStatus(VEHLIGHT_REAR_RIGHT) == LIGHT_STATUS_OK)\n\t\t\t\tCCoronas::UpdateCoronaCoors((uintptr)this + 3, lightR, 50.0f*TheCamera.LODDistMultiplier, angle);\n\t\t}\n\n\t\t// bright lights\n\t\tif(Damage.GetLightStatus(VEHLIGHT_REAR_LEFT) == LIGHT_STATUS_OK)\n\t\t\tCBrightLights::RegisterOne(lightL, GetUp(), GetRight(), GetForward(), pHandling->RearLights + BRIGHTLIGHT_REAR);\n\t\tif(Damage.GetLightStatus(VEHLIGHT_REAR_RIGHT) == LIGHT_STATUS_OK)\n\t\t\tCBrightLights::RegisterOne(lightR, GetUp(), GetRight(), GetForward(), pHandling->RearLights + BRIGHTLIGHT_REAR);\n\n\t\t// Light shadows\n\t\tif(!alarmOff){\n\t\t\tCVector pos = GetPosition();\n\t\t\tCVector2D fwd(GetForward());\n\t\t\tfwd.Normalise();\n\t\t\tfloat f = headLightPos.y + 6.0f;\n\t\t\tpos += CVector(f*fwd.x, f*fwd.y, 2.0f);\n\n\t\t\tif(Damage.GetLightStatus(VEHLIGHT_FRONT_LEFT) == LIGHT_STATUS_OK ||\n\t\t\t   Damage.GetLightStatus(VEHLIGHT_FRONT_RIGHT) == LIGHT_STATUS_OK)\n\t\t\t\tCShadows::StoreCarLightShadow(this, (uintptr)this + 22, gpShadowHeadLightsTex, &pos,\n\t\t\t\t\t7.0f*fwd.x, 7.0f*fwd.y, 5.5f*fwd.y, -5.5f*fwd.x, 45, 45, 45, 7.0f);\n\n\t\t\tf = (tailLightPos.y - 2.5f) - (headLightPos.y + 6.0f);\n\t\t\tpos += CVector(f*fwd.x, f*fwd.y, 0.0f);\n\t\t\tif(Damage.GetLightStatus(VEHLIGHT_REAR_LEFT) == LIGHT_STATUS_OK ||\n\t\t\t   Damage.GetLightStatus(VEHLIGHT_REAR_RIGHT) == LIGHT_STATUS_OK)\n\t\t\t\tCShadows::StoreCarLightShadow(this, (uintptr)this + 25, gpShadowExplosionTex, &pos,\n\t\t\t\t\t3.0f, 0.0f, 0.0f, -3.0f, 35, 0, 0, 4.0f);\n\t\t}\n\n\t\tif(this == FindPlayerVehicle() && !alarmOff){\n\t\t\tif(Damage.GetLightStatus(VEHLIGHT_FRONT_LEFT) == LIGHT_STATUS_OK ||\n\t\t\t   Damage.GetLightStatus(VEHLIGHT_FRONT_RIGHT) == LIGHT_STATUS_OK)\n\t\t\t\tCPointLights::AddLight(CPointLights::LIGHT_DIRECTIONAL, GetPosition(), GetForward(),\n\t\t\t\t\t20.0f, 1.0f, 1.0f, 1.0f,\n\t\t\t\t\tFindPlayerVehicle()->m_vecMoveSpeed.MagnitudeSqr2D() < sq(0.45f) ? CPointLights::FOG_NORMAL : CPointLights::FOG_NONE,\n\t\t\t\t\tfalse);\n\t\t\tCVector pos = GetPosition() - 4.0f*GetForward();\n\t\t\tif(Damage.GetLightStatus(VEHLIGHT_REAR_LEFT) == LIGHT_STATUS_OK ||\n\t\t\t   Damage.GetLightStatus(VEHLIGHT_REAR_RIGHT) == LIGHT_STATUS_OK) {\n\t\t\t\tif(m_fBrakePedal > 0.0f)\n\t\t\t\t\tCPointLights::AddLight(CPointLights::LIGHT_POINT, pos, CVector(0.0f, 0.0f, 0.0f),\n\t\t\t\t\t\t10.0f, 1.0f, 0.0f, 0.0f,\n\t\t\t\t\t\tCPointLights::FOG_NONE, false);\n\t\t\t\telse\n\t\t\t\t\tCPointLights::AddLight(CPointLights::LIGHT_POINT, pos, CVector(0.0f, 0.0f, 0.0f),\n\t\t\t\t\t\t7.0f, 0.6f, 0.0f, 0.0f,\n\t\t\t\t\t\tCPointLights::FOG_NONE, false);\n\t\t\t}\n\t\t}\n\t}else if(GetStatus() != STATUS_ABANDONED && GetStatus() != STATUS_WRECKED){\n\t\t// Lights off\n\n\t\tCVector lightPos = mi->m_positions[CAR_POS_TAILLIGHTS];\n\t\tCVector lightR = GetMatrix() * lightPos;\n\t\tCVector lightL = lightR;\n\t\tlightL -= GetRight()*2.0f*lightPos.x;\n\n\t\tif(m_fBrakePedal > 0.0f || m_fGasPedal < 0.0f){\n\t\t\tCVector lookVector = GetPosition() - TheCamera.GetPosition();\n\t\t\tlookVector.Normalise();\n\t\t\tfloat behindness = DotProduct(lookVector, GetForward());\n\t\t\tif(behindness > 0.0f){\n\t\t\t\tif(m_fGasPedal < 0.0f){\n\t\t\t\t\t// reversing\n\t\t\t\t\tif(Damage.GetLightStatus(VEHLIGHT_REAR_LEFT) == LIGHT_STATUS_OK)\n\t\t\t\t\t\tCCoronas::RegisterCorona((uintptr)this + 2, 120, 120, 120, 255,\n\t\t\t\t\t\t\tlightL, 1.2f, 50.0f*TheCamera.LODDistMultiplier,\n\t\t\t\t\t\t\tCCoronas::TYPE_STAR, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON,\n\t\t\t\t\t\t\tCCoronas::LOSCHECK_OFF, CCoronas::STREAK_ON, 0.0f);\n\t\t\t\t\tif(Damage.GetLightStatus(VEHLIGHT_REAR_RIGHT) == LIGHT_STATUS_OK)\n\t\t\t\t\t\tCCoronas::RegisterCorona((uintptr)this + 3, 120, 120, 120, 255,\n\t\t\t\t\t\t\tlightR, 1.2f, 50.0f*TheCamera.LODDistMultiplier,\n\t\t\t\t\t\t\tCCoronas::TYPE_STAR, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON,\n\t\t\t\t\t\t\tCCoronas::LOSCHECK_OFF, CCoronas::STREAK_ON, 0.0f);\n\t\t\t\t\tif(Damage.GetLightStatus(VEHLIGHT_REAR_LEFT) == LIGHT_STATUS_OK)\n\t\t\t\t\t\tCBrightLights::RegisterOne(lightL, GetUp(), GetRight(), GetForward(), pHandling->RearLights + BRIGHTLIGHT_FRONT);\n\t\t\t\t\tif(Damage.GetLightStatus(VEHLIGHT_REAR_RIGHT) == LIGHT_STATUS_OK)\n\t\t\t\t\t\tCBrightLights::RegisterOne(lightR, GetUp(), GetRight(), GetForward(), pHandling->RearLights + BRIGHTLIGHT_FRONT);\n\t\t\t\t}else{\n\t\t\t\t\t// braking\n\t\t\t\t\tif(Damage.GetLightStatus(VEHLIGHT_REAR_LEFT) == LIGHT_STATUS_OK)\n\t\t\t\t\t\tCCoronas::RegisterCorona((uintptr)this + 2, 120, 0, 0, 255,\n\t\t\t\t\t\t\tlightL, 1.2f, 50.0f*TheCamera.LODDistMultiplier,\n\t\t\t\t\t\t\tCCoronas::TYPE_STAR, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON,\n\t\t\t\t\t\t\tCCoronas::LOSCHECK_OFF, CCoronas::STREAK_ON, 0.0f);\n\t\t\t\t\tif(Damage.GetLightStatus(VEHLIGHT_REAR_RIGHT) == LIGHT_STATUS_OK)\n\t\t\t\t\t\tCCoronas::RegisterCorona((uintptr)this + 3, 120, 0, 0, 255,\n\t\t\t\t\t\t\tlightR, 1.2f, 50.0f*TheCamera.LODDistMultiplier,\n\t\t\t\t\t\t\tCCoronas::TYPE_STAR, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON,\n\t\t\t\t\t\t\tCCoronas::LOSCHECK_OFF, CCoronas::STREAK_ON, 0.0f);\n\t\t\t\t\tif(Damage.GetLightStatus(VEHLIGHT_REAR_LEFT) == LIGHT_STATUS_OK)\n\t\t\t\t\t\tCBrightLights::RegisterOne(lightL, GetUp(), GetRight(), GetForward(), pHandling->RearLights + BRIGHTLIGHT_REAR);\n\t\t\t\t\tif(Damage.GetLightStatus(VEHLIGHT_REAR_RIGHT) == LIGHT_STATUS_OK)\n\t\t\t\t\t\tCBrightLights::RegisterOne(lightR, GetUp(), GetRight(), GetForward(), pHandling->RearLights + BRIGHTLIGHT_REAR);\n\t\t\t\t}\n\t\t\t}else{\n\t\t\t\tif(Damage.GetLightStatus(VEHLIGHT_REAR_LEFT) == LIGHT_STATUS_OK)\n\t\t\t\t\tCCoronas::UpdateCoronaCoors((uintptr)this + 2, lightL, 50.0f*TheCamera.LODDistMultiplier, 0.0f);\n\t\t\t\tif(Damage.GetLightStatus(VEHLIGHT_REAR_RIGHT) == LIGHT_STATUS_OK)\n\t\t\t\t\tCCoronas::UpdateCoronaCoors((uintptr)this + 3, lightR, 50.0f*TheCamera.LODDistMultiplier, 0.0f);\n\t\t\t}\n\t\t}else{\n\t\t\tif(Damage.GetLightStatus(VEHLIGHT_REAR_LEFT) == LIGHT_STATUS_OK)\n\t\t\t\tCCoronas::UpdateCoronaCoors((uintptr)this + 2, lightL, 50.0f*TheCamera.LODDistMultiplier, 0.0f);\n\t\t\tif(Damage.GetLightStatus(VEHLIGHT_REAR_RIGHT) == LIGHT_STATUS_OK)\n\t\t\t\tCCoronas::UpdateCoronaCoors((uintptr)this + 3, lightR, 50.0f*TheCamera.LODDistMultiplier, 0.0f);\n\t\t}\n\t}\n\t// end of lights\n\t}\n\n\tif (IsRealHeli())\n\t\tCShadows::StoreShadowForVehicle(this, VEH_SHD_TYPE_HELI);\n\telse if ( GetModelIndex() == MI_RCBARON)\n\t\tCShadows::StoreShadowForVehicle(this, VEH_SHD_TYPE_RCPLANE);\n\telse\n\t\tCShadows::StoreShadowForVehicle(this, VEH_SHD_TYPE_CAR);\n\n\tDoSunGlare();\n\n\t// Heli dust\n\tif(IsRealHeli() && m_aWheelSpeed[1] > 0.1125f && GetPosition().z < 30.0f){\n\t\tbool foundGround = false;\n\t\tfloat waterZ = -1000.0f;\n\t\tfloat groundZ = CWorld::FindGroundZFor3DCoord(GetPosition().x, GetPosition().y, GetPosition().z, &foundGround);\n\t\tif(!CWaterLevel::GetWaterLevel(GetPosition(), &waterZ, false))\n\t\t\twaterZ = 0.0f;\n\t\tgroundZ = Max(groundZ, waterZ);\n\t\tfloat rnd = (m_aWheelSpeed[1]-0.1125f)*((int)Max(16.0f-4.0f*CTimer::GetTimeStep(),2.0f))*400.0f/43.0f;\n\t\tfloat radius = 10.0f;\n\t\tif(GetModelIndex() == MI_RCGOBLIN || GetModelIndex() == MI_RCRAIDER)\n\t\t\tradius = 3.0f;\n\t\tif(GetPosition().z - groundZ < radius)\n\t\t\tHeliDustGenerate(this, radius-(GetPosition().z - groundZ), groundZ, Ceil(rnd));\n\t}\n\n\tCMatrix mat;\n\tCVector pos;\n\n\tbool onlyFrontWheels = false;\n\tif(IsRealHeli()){\n\t\t// top rotor\n\t\tm_aWheelRotation[1] += m_aWheelSpeed[1]*CTimer::GetTimeStep();\n\t\tif(m_aWheelRotation[1] > TWOPI) m_aWheelRotation[1] -= TWOPI;\n\t\t// rear rotor\n\t\tm_aWheelRotation[3] += m_aWheelSpeed[1]*CTimer::GetTimeStep();\n\t\tif(m_aWheelRotation[3] > TWOPI) m_aWheelRotation[3] -= TWOPI;\n\t\tonlyFrontWheels = true;\n\t}\n\n\tCVector contactPoints[4];\t// relative to model\n\tCVector contactSpeeds[4];\t// speed at contact points\n\tCVector frontWheelFwd = Multiply3x3(GetMatrix(), CVector(-Sin(m_fSteerAngle), Cos(m_fSteerAngle), 0.0f));\n\tCVector rearWheelFwd = GetForward();\n\tfor(i = 0; i < 4; i++){\n\t\tif (m_aWheelTimer[i] > 0.0f && (!onlyFrontWheels || i == CARWHEEL_FRONT_LEFT || i == CARWHEEL_FRONT_RIGHT)) {\n\t\t\tcontactPoints[i] = m_aWheelColPoints[i].point - GetPosition();\n\t\t\tcontactSpeeds[i] = GetSpeed(contactPoints[i]);\n\t\t\tif (i == CARWHEEL_FRONT_LEFT || i == CARWHEEL_FRONT_RIGHT)\n\t\t\t\tm_aWheelSpeed[i] = ProcessWheelRotation(m_aWheelState[i], frontWheelFwd, contactSpeeds[i], 0.5f*mi->m_wheelScale);\n\t\t\telse\n\t\t\t\tm_aWheelSpeed[i] = ProcessWheelRotation(m_aWheelState[i], rearWheelFwd, contactSpeeds[i], 0.5f*mi->m_wheelScale);\n\t\t\tm_aWheelRotation[i] += m_aWheelSpeed[i];\n\t\t}\n\t}\n\n\tRwRGBA hoverParticleCol = { 255, 255, 255, 32 };\n\n\t// Rear right wheel\n\tmat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_RB]));\n\tpos = mat.GetPosition();\n\tpos.z = m_aWheelPosition[CARWHEEL_REAR_RIGHT];\n\tif(Damage.GetWheelStatus(CARWHEEL_REAR_RIGHT) == WHEEL_STATUS_BURST)\n\t\tmat.SetRotate(m_aWheelRotation[CARWHEEL_REAR_RIGHT], 0.0f, 0.3f*Sin(m_aWheelRotation[CARWHEEL_REAR_RIGHT]));\n\telse\n\t\tmat.SetRotateX(m_aWheelRotation[CARWHEEL_REAR_RIGHT]);\n\tif(GetStatus() == STATUS_PLAYER){\n\t\tif(bHoverCheat && m_aSuspensionSpringRatioPrev[CARWHEEL_REAR_RIGHT] < 1.0f &&\n\t\t   m_aWheelColPoints[CARWHEEL_REAR_RIGHT].surfaceB == SURFACE_WATER){\n\t\t\t// hovering on water\n\t\t\tmat.RotateY(-HALFPI);\n\t\t\tif((CTimer::GetFrameCounter()+CARWHEEL_REAR_RIGHT) & 1){\n\t\t\t\tCParticle::AddParticle(PARTICLE_STEAM_NY_SLOWMOTION, m_aWheelColPoints[CARWHEEL_REAR_RIGHT].point,\n\t\t\t\t\t0.5f*m_vecMoveSpeed+0.1f*GetRight(), nil, 0.4f, hoverParticleCol);\n\t\t\t}else{\n\t\t\t\tCParticle::AddParticle(PARTICLE_CAR_SPLASH, m_aWheelColPoints[CARWHEEL_REAR_RIGHT].point,\n\t\t\t\t\t0.3f*m_vecMoveSpeed+0.15f*GetRight()+CVector(0.0f, 0.0f, 0.1f), nil, 0.15f, hoverParticleCol,\n\t\t\t\t\tCGeneral::GetRandomNumberInRange(0.0f, 90.0f),\n\t\t\t\t\tCGeneral::GetRandomNumberInRange(0.0f, 10.0f), 1);\n\t\t\t}\n#ifdef BETTER_ALLCARSAREDODO_CHEAT\n\t\t} else if (bAllDodosCheat && m_nDriveWheelsOnGround == 0 && m_nDriveWheelsOnGroundPrev == 0) {\n\t\t\tmat.RotateY(-HALFPI);\n#endif\n\t\t}else{\n\t\t\t// tilt wheel depending oh how much it presses on ground\n\t\t\tfloat groundOffset = pos.z + m_fHeightAboveRoad - 0.5f*mi->m_wheelScale;\n\t\t\tif(GetModelIndex() == MI_VOODOO)\n\t\t\t\tgroundOffset *= 0.6f;\n\t\t\tmat.RotateY(Asin(clamp(-groundOffset, -1.0f, 1.0f)));\n\t\t}\n\t}\n\tif(pHandling->Flags & HANDLING_FAT_REARW)\n\t\tmat.Scale(1.15f*mi->m_wheelScale, mi->m_wheelScale, mi->m_wheelScale);\n\telse\n\t\tmat.Scale(mi->m_wheelScale);\n\tmat.Translate(pos);\n\tmat.UpdateRW();\n\n\t// Rear left wheel\n\tmat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_LB]));\n\tpos = mat.GetPosition();\n\tpos.z = m_aWheelPosition[CARWHEEL_REAR_LEFT];\n\tif(Damage.GetWheelStatus(CARWHEEL_REAR_LEFT) == WHEEL_STATUS_BURST)\n\t\tmat.SetRotate(-m_aWheelRotation[CARWHEEL_REAR_LEFT], 0.0f, PI+0.3f*Sin(m_aWheelRotation[CARWHEEL_REAR_LEFT]));\n\telse\n\t\tmat.SetRotate(-m_aWheelRotation[CARWHEEL_REAR_LEFT], 0.0f, PI);\n\tif(GetStatus() == STATUS_PLAYER){\n\t\tif(bHoverCheat && m_aSuspensionSpringRatioPrev[CARWHEEL_REAR_LEFT] < 1.0f &&\n\t\t   m_aWheelColPoints[CARWHEEL_REAR_LEFT].surfaceB == SURFACE_WATER){\n\t\t\t// hovering on water\n\t\t\tmat.RotateY(HALFPI);\n\t\t\tif((CTimer::GetFrameCounter()+CARWHEEL_REAR_LEFT) & 1){\n\t\t\t\tCParticle::AddParticle(PARTICLE_STEAM_NY_SLOWMOTION, m_aWheelColPoints[CARWHEEL_REAR_LEFT].point,\n\t\t\t\t\t0.5f*m_vecMoveSpeed-0.1f*GetRight(), nil, 0.4f, hoverParticleCol);\n\t\t\t}else{\n\t\t\t\tCParticle::AddParticle(PARTICLE_CAR_SPLASH, m_aWheelColPoints[CARWHEEL_REAR_LEFT].point,\n\t\t\t\t\t0.3f*m_vecMoveSpeed-0.15f*GetRight()+CVector(0.0f, 0.0f, 0.1f), nil, 0.15f, hoverParticleCol,\n\t\t\t\t\tCGeneral::GetRandomNumberInRange(0.0f, 90.0f),\n\t\t\t\t\tCGeneral::GetRandomNumberInRange(0.0f, 10.0f), 1);\n\t\t\t}\n#ifdef BETTER_ALLCARSAREDODO_CHEAT\n\t\t} else if (bAllDodosCheat && m_nDriveWheelsOnGround == 0 && m_nDriveWheelsOnGroundPrev == 0) {\n\t\t\tmat.RotateY(HALFPI);\n#endif\n\t\t}else{\n\t\t\t// tilt wheel depending oh how much it presses on ground\n\t\t\tfloat groundOffset = pos.z + m_fHeightAboveRoad - 0.5f*mi->m_wheelScale;\n\t\t\tif(GetModelIndex() == MI_VOODOO)\n\t\t\t\tgroundOffset *= 0.6f;\n\t\t\tmat.RotateY(Asin(clamp(groundOffset, -1.0f, 1.0f)));\n\t\t}\n\t}\n\tif(pHandling->Flags & HANDLING_FAT_REARW)\n\t\tmat.Scale(1.15f*mi->m_wheelScale, mi->m_wheelScale, mi->m_wheelScale);\n\telse\n\t\tmat.Scale(mi->m_wheelScale);\n\tmat.Translate(pos);\n\tmat.UpdateRW();\n\n\t// Mid right wheel\n\tif(m_aCarNodes[CAR_WHEEL_RM]){\n\t\tmat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_RM]));\n\t\tpos = mat.GetPosition();\n\t\tpos.z = m_aWheelPosition[CARWHEEL_REAR_RIGHT];\n\t\tif(Damage.GetWheelStatus(CARWHEEL_REAR_RIGHT) == WHEEL_STATUS_BURST)\n\t\t\tmat.SetRotate(m_aWheelRotation[CARWHEEL_REAR_RIGHT], 0.0f, 0.3f*Sin(m_aWheelRotation[CARWHEEL_REAR_RIGHT]));\n\t\telse\n\t\t\tmat.SetRotateX(m_aWheelRotation[CARWHEEL_REAR_RIGHT]);\n\t\tif(GetStatus() == STATUS_PLAYER){\n\t\t\tif(bHoverCheat && m_aSuspensionSpringRatioPrev[CARWHEEL_REAR_RIGHT] < 1.0f &&\n\t\t\t   m_aWheelColPoints[CARWHEEL_REAR_RIGHT].surfaceB == SURFACE_WATER){\n\t\t\t\t// hovering on water\n\t\t\t\tmat.RotateY(-HALFPI);\n#ifdef BETTER_ALLCARSAREDODO_CHEAT\n\t\t\t} else if (bAllDodosCheat && m_nDriveWheelsOnGround == 0 && m_nDriveWheelsOnGroundPrev == 0) {\n\t\t\t\tmat.RotateY(-HALFPI);\n#endif\n\t\t\t}else{\n\t\t\t\t// tilt wheel depending oh how much it presses on ground\n\t\t\t\tfloat groundOffset = pos.z + m_fHeightAboveRoad - 0.5f*mi->m_wheelScale;\n\t\t\t\tif(GetModelIndex() == MI_VOODOO)\n\t\t\t\t\tgroundOffset *= 0.6f;\n\t\t\t\tmat.RotateY(Asin(clamp(-groundOffset, -1.0f, 1.0f)));\n\t\t\t}\n\t\t}\n\t\tif(pHandling->Flags & HANDLING_FAT_REARW)\n\t\t\tmat.Scale(1.15f*mi->m_wheelScale, mi->m_wheelScale, mi->m_wheelScale);\n\t\telse\n\t\t\tmat.Scale(mi->m_wheelScale);\n\t\tmat.Translate(pos);\n\t\tmat.UpdateRW();\n\t}\n\n\t// Mid left wheel\n\tif(m_aCarNodes[CAR_WHEEL_LM]){\n\t\tmat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_LM]));\n\t\tpos = mat.GetPosition();\n\t\tpos.z = m_aWheelPosition[CARWHEEL_REAR_LEFT];\n\t\tif(Damage.GetWheelStatus(CARWHEEL_REAR_LEFT) == WHEEL_STATUS_BURST)\n\t\t\tmat.SetRotate(-m_aWheelRotation[CARWHEEL_REAR_LEFT], 0.0f, PI+0.3f*Sin(m_aWheelRotation[CARWHEEL_REAR_LEFT]));\n\t\telse\n\t\t\tmat.SetRotate(-m_aWheelRotation[CARWHEEL_REAR_LEFT], 0.0f, PI);\n\t\tif(GetStatus() == STATUS_PLAYER){\n\t\t\tif(bHoverCheat && m_aSuspensionSpringRatioPrev[CARWHEEL_REAR_LEFT] < 1.0f &&\n\t\t\t   m_aWheelColPoints[CARWHEEL_REAR_LEFT].surfaceB == SURFACE_WATER){\n\t\t\t\t// hovering on water\n\t\t\t\tmat.RotateY(HALFPI);\n#ifdef BETTER_ALLCARSAREDODO_CHEAT\n\t\t\t} else if (bAllDodosCheat && m_nDriveWheelsOnGround == 0 && m_nDriveWheelsOnGroundPrev == 0) {\n\t\t\t\tmat.RotateY(HALFPI);\n#endif\n\t\t\t}else{\n\t\t\t\t// tilt wheel depending oh how much it presses on ground\n\t\t\t\tfloat groundOffset = pos.z + m_fHeightAboveRoad - 0.5f*mi->m_wheelScale;\n\t\t\t\tif(GetModelIndex() == MI_VOODOO)\n\t\t\t\t\tgroundOffset *= 0.6f;\n\t\t\t\tmat.RotateY(Asin(clamp(groundOffset, -1.0f, 1.0f)));\n\t\t\t}\n\t\t}\n\t\tif(pHandling->Flags & HANDLING_FAT_REARW)\n\t\t\tmat.Scale(1.15f*mi->m_wheelScale, mi->m_wheelScale, mi->m_wheelScale);\n\t\telse\n\t\t\tmat.Scale(mi->m_wheelScale);\n\t\tmat.Translate(pos);\n\t\tmat.UpdateRW();\n\t}\n\n\tif(GetModelIndex() == MI_DODO){\n\t\t// Front wheel\n\t\tmat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_RF]));\n\t\tpos = mat.GetPosition();\n\t\tpos.z = m_aWheelPosition[CARWHEEL_FRONT_RIGHT];\n\t\tif(Damage.GetWheelStatus(CARWHEEL_FRONT_RIGHT) == WHEEL_STATUS_BURST)\n\t\t\tmat.SetRotate(m_aWheelRotation[CARWHEEL_FRONT_RIGHT], 0.0f, m_fSteerAngle+0.3f*Sin(m_aWheelRotation[CARWHEEL_FRONT_RIGHT]));\n\t\telse\n\t\t\tmat.SetRotate(m_aWheelRotation[CARWHEEL_FRONT_RIGHT], 0.0f, m_fSteerAngle);\n\t\tmat.Scale(mi->m_wheelScale);\n\t\tmat.Translate(pos);\n\t\tmat.UpdateRW();\n\n\t\t// Rotate propeller\n\t\tif(m_aCarNodes[CAR_WINDSCREEN]){\n\t\t\tmat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WINDSCREEN]));\n\t\t\tpos = mat.GetPosition();\n\t\t\tmat.SetRotateY(m_fPropellerRotation);\n\t\t\tmat.Translate(pos);\n\t\t\tmat.UpdateRW();\n\n\t\t\tm_fPropellerRotation += m_fGasPedal != 0.0f ? TWOPI/13.0f : TWOPI/26.0f;\n\t\t\tif(m_fPropellerRotation > TWOPI)\n\t\t\t\tm_fPropellerRotation -= TWOPI;\n\t\t}\n\n\t\t// Rudder\n\t\tif(Damage.GetDoorStatus(DOOR_BOOT) != DOOR_STATUS_MISSING && m_aCarNodes[CAR_BOOT]){\n\t\t\tmat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_BOOT]));\n\t\t\tpos = mat.GetPosition();\n\t\t\tmat.SetRotate(0.0f, 0.0f, -m_fSteerAngle);\n\t\t\tmat.Rotate(0.0f, Sin(m_fSteerAngle)*DEGTORAD(22.0f), 0.0f);\n\t\t\tmat.Translate(pos);\n\t\t\tmat.UpdateRW();\n\t\t}\n\n\t\tProcessSwingingDoor(CAR_DOOR_LF, DOOR_FRONT_LEFT);\n\t\tProcessSwingingDoor(CAR_DOOR_RF, DOOR_FRONT_RIGHT);\n\t}else if(GetModelIndex() == MI_RHINO){\n\t\t// Front right wheel\n\t\tmat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_RF]));\n\t\tpos = mat.GetPosition();\n\t\tpos.z = m_aWheelPosition[CARWHEEL_FRONT_RIGHT];\n\t\t// no damaged wheels or steering\n\t\tmat.SetRotate(m_aWheelRotation[CARWHEEL_FRONT_RIGHT], 0.0f, 0.0f);\n\t\tmat.Scale(mi->m_wheelScale);\n\t\tmat.Translate(pos);\n\t\tmat.UpdateRW();\n\n\t\t// Front left wheel\n\t\tmat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_LF]));\n\t\tpos = mat.GetPosition();\n\t\tpos.z = m_aWheelPosition[CARWHEEL_FRONT_LEFT];\n\t\t// no damaged wheels or steering\n\t\tmat.SetRotate(-m_aWheelRotation[CARWHEEL_FRONT_LEFT], 0.0f, PI);\n\t\tmat.Scale(mi->m_wheelScale);\n\t\tmat.Translate(pos);\n\t\tmat.UpdateRW();\n\t}else if(IsRealHeli()){\n\t\t// Top rotor\n\t\tif(m_aCarNodes[CAR_BONNET]){\n\t\t\tmat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_BONNET]));\n\t\t\tpos = mat.GetPosition();\n\t\t\tmat.SetRotateZ(m_aWheelRotation[1]);\n\t\t\tmat.Translate(pos);\n\t\t\tmat.UpdateRW();\n\t\t}\n\t\t// Blurred top rotor\n\t\tif(m_aCarNodes[CAR_WINDSCREEN]){\n\t\t\tmat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WINDSCREEN]));\n\t\t\tpos = mat.GetPosition();\n\t\t\tmat.SetRotateZ(-m_aWheelRotation[1]);\n\t\t\tmat.Translate(pos);\n\t\t\tmat.UpdateRW();\n\t\t}\n\t\t// Rear rotor\n\t\tif(m_aCarNodes[CAR_BOOT]){\n\t\t\tmat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_BOOT]));\n\t\t\tpos = mat.GetPosition();\n\t\t\tmat.SetRotateX(m_aWheelRotation[3]);\n\t\t\tmat.Translate(pos);\n\t\t\tmat.UpdateRW();\n\t\t}\n\t\t// Blurred rear rotor\n\t\tif(m_aCarNodes[CAR_BUMP_REAR]){\n\t\t\tmat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_BUMP_REAR]));\n\t\t\tpos = mat.GetPosition();\n\t\t\tmat.SetRotateX(-m_aWheelRotation[3]);\n\t\t\tmat.Translate(pos);\n\t\t\tmat.UpdateRW();\n\t\t}\n\t}else{\n\t\t// Front right wheel\n\t\tmat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_RF]));\n\t\tpos = mat.GetPosition();\n\t\tpos.z = m_aWheelPosition[CARWHEEL_FRONT_RIGHT];\n\t\tif(Damage.GetWheelStatus(CARWHEEL_FRONT_RIGHT) == WHEEL_STATUS_BURST)\n\t\t\tmat.SetRotate(m_aWheelRotation[CARWHEEL_FRONT_RIGHT], 0.0f, m_fSteerAngle+0.3f*Sin(m_aWheelRotation[CARWHEEL_FRONT_RIGHT]));\n\t\telse\n\t\t\tmat.SetRotate(m_aWheelRotation[CARWHEEL_FRONT_RIGHT], 0.0f, m_fSteerAngle);\n\t\tif(GetStatus() == STATUS_PLAYER){\n\t\t\tif(bHoverCheat && m_aSuspensionSpringRatioPrev[CARWHEEL_FRONT_RIGHT] < 1.0f &&\n\t\t\t   m_aWheelColPoints[CARWHEEL_FRONT_RIGHT].surfaceB == SURFACE_WATER){\n\t\t\t\t// hovering on water\n\t\t\t\tmat.RotateY(-HALFPI);\n\t\t\t\tif((CTimer::GetFrameCounter()+CARWHEEL_FRONT_RIGHT) & 1){\n\t\t\t\t\tCParticle::AddParticle(PARTICLE_STEAM_NY_SLOWMOTION, m_aWheelColPoints[CARWHEEL_FRONT_RIGHT].point,\n\t\t\t\t\t\t0.5f*m_vecMoveSpeed+0.1f*GetRight(), nil, 0.4f, hoverParticleCol);\n\t\t\t\t}else{\n\t\t\t\t\tCParticle::AddParticle(PARTICLE_CAR_SPLASH, m_aWheelColPoints[CARWHEEL_FRONT_RIGHT].point,\n\t\t\t\t\t\t0.3f*m_vecMoveSpeed+0.15f*GetRight()+CVector(0.0f, 0.0f, 0.1f), nil, 0.15f, hoverParticleCol,\n\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(0.0f, 90.0f),\n\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(0.0f, 10.0f), 1);\n\t\t\t\t}\n#ifdef BETTER_ALLCARSAREDODO_CHEAT\n\t\t\t} else if (bAllDodosCheat && m_nDriveWheelsOnGround == 0 && m_nDriveWheelsOnGroundPrev == 0) {\n\t\t\t\tmat.RotateY(-HALFPI);\n#endif\n\t\t\t}else{\n\t\t\t\t// tilt wheel depending oh how much it presses on ground\n\t\t\t\tfloat groundOffset = pos.z + m_fHeightAboveRoad - 0.5f*mi->m_wheelScale;\n\t\t\t\tif(GetModelIndex() == MI_VOODOO)\n\t\t\t\t\tgroundOffset *= 0.6f;\n\t\t\t\tmat.RotateY(Asin(clamp(-groundOffset, -1.0f, 1.0f)));\n\t\t\t}\n\t\t}\n\t\tif(pHandling->Flags & HANDLING_NARROW_FRONTW)\n\t\t\tmat.Scale(0.7f*mi->m_wheelScale, mi->m_wheelScale, mi->m_wheelScale);\n\t\telse\n\t\t\tmat.Scale(mi->m_wheelScale);\n\t\tmat.Translate(pos);\n\t\tmat.UpdateRW();\n\n\t\t// Front left wheel\n\t\tmat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_LF]));\n\t\tpos = mat.GetPosition();\n\t\tpos.z = m_aWheelPosition[CARWHEEL_FRONT_LEFT];\n\t\tif(Damage.GetWheelStatus(CARWHEEL_FRONT_LEFT) == WHEEL_STATUS_BURST)\n\t\t\tmat.SetRotate(-m_aWheelRotation[CARWHEEL_FRONT_LEFT], 0.0f, PI+m_fSteerAngle+0.3f*Sin(m_aWheelRotation[CARWHEEL_FRONT_LEFT]));\n\t\telse\n\t\t\tmat.SetRotate(-m_aWheelRotation[CARWHEEL_FRONT_LEFT], 0.0f, PI+m_fSteerAngle);\n\t\tif(GetStatus() == STATUS_PLAYER){\n\t\t\tif(bHoverCheat && m_aSuspensionSpringRatioPrev[CARWHEEL_FRONT_LEFT] < 1.0f &&\n\t\t\t   m_aWheelColPoints[CARWHEEL_FRONT_LEFT].surfaceB == SURFACE_WATER){\n\t\t\t\t// hovering on water\n\t\t\t\tmat.RotateY(HALFPI);\n\t\t\t\tif((CTimer::GetFrameCounter()+CARWHEEL_FRONT_LEFT) & 1){\n\t\t\t\t\tCParticle::AddParticle(PARTICLE_STEAM_NY_SLOWMOTION, m_aWheelColPoints[CARWHEEL_FRONT_LEFT].point,\n\t\t\t\t\t\t0.5f*m_vecMoveSpeed-0.1f*GetRight(), nil, 0.4f, hoverParticleCol);\n\t\t\t\t}else{\n\t\t\t\t\tCParticle::AddParticle(PARTICLE_CAR_SPLASH, m_aWheelColPoints[CARWHEEL_FRONT_LEFT].point,\n\t\t\t\t\t\t0.3f*m_vecMoveSpeed-0.15f*GetRight()+CVector(0.0f, 0.0f, 0.1f), nil, 0.15f, hoverParticleCol,\n\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(0.0f, 90.0f),\n\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(0.0f, 10.0f), 1);\n\t\t\t\t}\n#ifdef BETTER_ALLCARSAREDODO_CHEAT\n\t\t\t} else if (bAllDodosCheat && m_nDriveWheelsOnGround == 0 && m_nDriveWheelsOnGroundPrev == 0) {\n\t\t\t\tmat.RotateY(HALFPI);\n#endif\n\t\t\t}else{\n\t\t\t\t// tilt wheel depending oh how much it presses on ground\n\t\t\t\tfloat groundOffset = pos.z + m_fHeightAboveRoad - 0.5f*mi->m_wheelScale;\n\t\t\t\tif(GetModelIndex() == MI_VOODOO)\n\t\t\t\t\tgroundOffset *= 0.6f;\n\t\t\t\tmat.RotateY(Asin(clamp(groundOffset, -1.0f, 1.0f)));\n\t\t\t}\n\t\t}\n\t\tif(pHandling->Flags & HANDLING_NARROW_FRONTW)\n\t\t\tmat.Scale(0.7f*mi->m_wheelScale, mi->m_wheelScale, mi->m_wheelScale);\n\t\telse\n\t\t\tmat.Scale(mi->m_wheelScale);\n\t\tmat.Translate(pos);\n\t\tmat.UpdateRW();\n\n\t\tProcessSwingingDoor(CAR_DOOR_LF, DOOR_FRONT_LEFT);\n\t\tProcessSwingingDoor(CAR_DOOR_RF, DOOR_FRONT_RIGHT);\n\t\tProcessSwingingDoor(CAR_DOOR_LR, DOOR_REAR_LEFT);\n\t\tProcessSwingingDoor(CAR_DOOR_RR, DOOR_REAR_RIGHT);\n\t\tProcessSwingingDoor(CAR_BONNET, DOOR_BONNET);\n\t\tProcessSwingingDoor(CAR_BOOT, DOOR_BOOT);\n\t}\n\n\tif((GetModelIndex() == MI_PHEONIX || GetModelIndex() == MI_BFINJECT) &&\n\t   GetStatus() == STATUS_PLAYER && m_aCarNodes[CAR_WING_LR]){\n\t\tfloat rotation = 0.0f;\n\n\t\tif(GetModelIndex() == MI_BFINJECT)\n\t\t\tif(m_fPropellerRotation > TWOPI) m_fPropellerRotation -= TWOPI;\n\n\t\tif(Abs(m_fGasPedal) > 0.0f){\n\t\t\tif(GetModelIndex() == MI_BFINJECT){\n\t\t\t\tm_fPropellerRotation += 0.2f*CTimer::GetTimeStep();\n\t\t\t\trotation = m_fPropellerRotation;\n\t\t\t}else{\n\t\t\t\tif(m_fPropellerRotation < 1.3f){\n\t\t\t\t\tm_fPropellerRotation = Min(m_fPropellerRotation+0.1f*CTimer::GetTimeStep(), 1.3f);\n\t\t\t\t\trotation = m_fPropellerRotation;\n\t\t\t\t}else{\n\t\t\t\t\tfloat wave = Sin((CTimer::GetTimeInMilliseconds()%10000)/70.0f);\n\t\t\t\t\trotation = m_fPropellerRotation + 0.13*wave;\n\t\t\t\t}\n\t\t\t}\n\t\t}else{\n\t\t\tif(GetModelIndex() == MI_BFINJECT){\n\t\t\t\tm_fPropellerRotation += 0.1f*CTimer::GetTimeStep();\n\t\t\t\trotation = m_fPropellerRotation;\n\t\t\t}else{\n\t\t\t\tif(m_fPropellerRotation > 0.0f){\n\t\t\t\t\tm_fPropellerRotation = Max(m_fPropellerRotation-0.05f*CTimer::GetTimeStep(), 0.0f);\n\t\t\t\t\trotation = m_fPropellerRotation;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tmat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WING_LR]));\n\t\tpos = mat.GetPosition();\n\t\tif(GetModelIndex() == MI_BFINJECT)\n\t\t\tmat.SetRotateY(rotation);\n\t\telse\n\t\t\tmat.SetRotateX(rotation);\n\t\tmat.Translate(pos);\n\t\tmat.UpdateRW();\n\t}\n}\n\nvoid\nCAutomobile::Render(void)\n{\n\tCVehicleModelInfo *mi = (CVehicleModelInfo*)CModelInfo::GetModelInfo(GetModelIndex());\n\n\tmi->SetVehicleColour(m_currentColour1, m_currentColour2);\n\n\tif(IsRealHeli()){\n\t\tRpAtomic *atomic = nil;\n\t\tint rotorAlpha = (1.5f - Min(1.7f*Max(m_aWheelSpeed[1],0.0f)/0.22f, 1.5f))*255.0f;\n\t\trotorAlpha = Min(rotorAlpha, 255);\n\t\tint blurAlpha = Max(1.5f*m_aWheelSpeed[1]/0.22f - 0.4f, 0.0f)*150.0f;\n\t\tblurAlpha = Min(blurAlpha, 150);\n\n\t\t// Top rotor\n\t\tif(m_aCarNodes[CAR_BONNET]){\n\t\t\tRwFrameForAllObjects(m_aCarNodes[CAR_BONNET], GetCurrentAtomicObjectCB, &atomic);\n\t\t\tif(atomic)\n\t\t\t\tSetComponentAtomicAlpha(atomic, rotorAlpha);\n\t\t}\n\t\tatomic = nil;\n\t\t// Rear rotor\n\t\tif(m_aCarNodes[CAR_BOOT]){\n\t\t\tRwFrameForAllObjects(m_aCarNodes[CAR_BOOT], GetCurrentAtomicObjectCB, &atomic);\n\t\t\tif(atomic)\n\t\t\t\tSetComponentAtomicAlpha(atomic, rotorAlpha);\n\t\t}\n\t\tatomic = nil;\n\t\t// Blurred top rotor\n\t\tif(m_aCarNodes[CAR_WINDSCREEN]){\n\t\t\tRwFrameForAllObjects(m_aCarNodes[CAR_WINDSCREEN], GetCurrentAtomicObjectCB, &atomic);\n\t\t\tif(atomic)\n\t\t\t\tSetComponentAtomicAlpha(atomic, blurAlpha);\n\t\t}\n\t\tatomic = nil;\n\t\t// Blurred rear rotor\n\t\tif(m_aCarNodes[CAR_BUMP_REAR]){\n\t\t\tRwFrameForAllObjects(m_aCarNodes[CAR_BUMP_REAR], GetCurrentAtomicObjectCB, &atomic);\n\t\t\tif(atomic)\n\t\t\t\tSetComponentAtomicAlpha(atomic, blurAlpha);\n\t\t}\n\t}\n\n\tif(CVehicle::bWheelsOnlyCheat){\n\t\tRpAtomicRender((RpAtomic*)GetFirstObject(m_aCarNodes[CAR_WHEEL_RB]));\n\t\tRpAtomicRender((RpAtomic*)GetFirstObject(m_aCarNodes[CAR_WHEEL_LB]));\n\t\tRpAtomicRender((RpAtomic*)GetFirstObject(m_aCarNodes[CAR_WHEEL_RF]));\n\t\tRpAtomicRender((RpAtomic*)GetFirstObject(m_aCarNodes[CAR_WHEEL_LF]));\n\t\tif(m_aCarNodes[CAR_WHEEL_RM])\n\t\t\tRpAtomicRender((RpAtomic*)GetFirstObject(m_aCarNodes[CAR_WHEEL_RM]));\n\t\tif(m_aCarNodes[CAR_WHEEL_LM])\n\t\t\tRpAtomicRender((RpAtomic*)GetFirstObject(m_aCarNodes[CAR_WHEEL_LM]));\n\t}else\n\t\tCEntity::Render();\n}\n\nint32\nCAutomobile::ProcessEntityCollision(CEntity *ent, CColPoint *colpoints)\n{\n\tint i;\n\tCColModel *colModel;\n\n\tif(GetStatus() != STATUS_SIMPLE)\n\t\tbVehicleColProcessed = true;\n\n\tif(bUsingSpecialColModel)\n\t\tcolModel = &CWorld::Players[CWorld::PlayerInFocus].m_ColModel;\n\telse\n\t\tcolModel = GetColModel();\n\n\tint numWheelCollisions = 0;\n\tfloat prevRatios[4] = { 0.0f, 0.0f, 0.0f, 0.0f};\n\tfor(i = 0; i < 4; i++)\n\t\tprevRatios[i] = m_aSuspensionSpringRatio[i];\n\n\tif(m_bIsVehicleBeingShifted || bSkipLineCol || ent->IsPed() ||\n\t   GetModelIndex() == MI_DODO && ent->IsVehicle())\n\t\tcolModel->numLines = 0;\n\n\tint numCollisions = CCollision::ProcessColModels(GetMatrix(), *colModel,\n\t\tent->GetMatrix(), *ent->GetColModel(),\n\t\tcolpoints,\n\t\tm_aWheelColPoints, m_aSuspensionSpringRatio);\n\n\t// m_aSuspensionSpringRatio are now set to the point where the tyre touches ground.\n\t// In ProcessControl these will be re-normalized to ignore the tyre radius.\n\n\tif(colModel->numLines){\n\t\tfor(i = 0; i < 4; i++)\n\t\t\tif(m_aSuspensionSpringRatio[i] < 1.0f && m_aSuspensionSpringRatio[i] < prevRatios[i]){\n\t\t\t\tnumWheelCollisions++;\n\n\t\t\t\t// wheel is touching a physical\n\t\t\t\tif(ent->IsVehicle() || ent->IsObject()){\n\t\t\t\t\tCPhysical *phys = (CPhysical*)ent;\n\n\t\t\t\t\tm_aGroundPhysical[i] = phys;\n\t\t\t\t\tphys->RegisterReference((CEntity**)&m_aGroundPhysical[i]);\n\t\t\t\t\tm_aGroundOffset[i] = m_aWheelColPoints[i].point - phys->GetPosition();\n\t\t\t\t}\n\n\t\t\t\tm_nSurfaceTouched = m_aWheelColPoints[i].surfaceB;\n\t\t\t\tif(ent->IsBuilding())\n\t\t\t\t\tm_pCurGroundEntity = ent;\n\t\t\t}\n\t}else\n\t\tcolModel->numLines = 4;\n\n\tif(numCollisions > 0 || numWheelCollisions > 0){\n\t\tAddCollisionRecord(ent);\n\t\tif(!ent->IsBuilding())\n\t\t\t((CPhysical*)ent)->AddCollisionRecord(this);\n\n\t\tif(numCollisions > 0)\n\t\t\tif(ent->IsBuilding() ||\n\t\t\t   ent->IsObject() && ((CPhysical*)ent)->bInfiniteMass)\n\t\t\t\tbHasHitWall = true;\n\t}\n\n\treturn numCollisions;\n}\n\nstatic int16 nLastControlInput;\nstatic float fMouseCentreRange = 0.35f;\nstatic float fMouseSteerSens = -0.0035f;\nstatic float fMouseCentreMult = 0.975f;\n\nvoid\nCAutomobile::ProcessControlInputs(uint8 pad)\n{\n\tfloat speed = DotProduct(m_vecMoveSpeed, GetForward());\n\n\tif(!CPad::GetPad(pad)->GetExitVehicle() ||\n\t   pDriver && pDriver->m_pVehicleAnim && (pDriver->m_pVehicleAnim->animId == ANIM_STD_ROLLOUT_LHS ||\n\t                                          pDriver->m_pVehicleAnim->animId == ANIM_STD_ROLLOUT_RHS))\n\t\tbIsHandbrakeOn = !!CPad::GetPad(pad)->GetHandBrake();\n\telse\n\t\tbIsHandbrakeOn = true;\n\n\t// Steer left/right\n\tif(CCamera::m_bUseMouse3rdPerson && !CVehicle::m_bDisableMouseSteering){\n\t\tif(CPad::GetPad(pad)->GetMouseX() != 0.0f){\n\t\t\tm_fSteerInput += fMouseSteerSens*CPad::GetPad(pad)->GetMouseX();\n\t\t\tnLastControlInput = 2;\n\t\t\tif(Abs(m_fSteerInput) < fMouseCentreRange)\n\t\t\t\tm_fSteerInput *= Pow(fMouseCentreMult, CTimer::GetTimeStep());\n\t\t}else if(CPad::GetPad(pad)->GetSteeringLeftRight() || nLastControlInput != 2){\n\t\t\t// mouse hasn't move, steer with pad like below\n\t\t\tm_fSteerInput += (-CPad::GetPad(pad)->GetSteeringLeftRight()/128.0f - m_fSteerInput)*\n\t\t\t\t0.2f*CTimer::GetTimeStep();\n\t\t\tnLastControlInput = 0;\n\t\t}\n\t}else{\n\t\tm_fSteerInput += (-CPad::GetPad(pad)->GetSteeringLeftRight()/128.0f - m_fSteerInput)*\n\t\t\t0.2f*CTimer::GetTimeStep();\n\t\tnLastControlInput = 0;\n\t}\n\tm_fSteerInput = clamp(m_fSteerInput, -1.0f, 1.0f);\n\n\t// Accelerate/Brake\n\tfloat acceleration = (CPad::GetPad(pad)->GetAccelerate() - CPad::GetPad(pad)->GetBrake())/255.0f;\n\tif(GetModelIndex() == MI_DODO && acceleration < 0.0f)\n\t\tacceleration *= 0.3f;\n\tif(Abs(speed) < 0.01f){\n\t\t// standing still, go into direction we want\n\t\tif(CPad::GetPad(pad)->GetAccelerate() > 150.0f && CPad::GetPad(pad)->GetBrake() > 150.0f){\n\t\t\tm_fGasPedal = CPad::GetPad(pad)->GetAccelerate()/255.0f;\n\t\t\tm_fBrakePedal = CPad::GetPad(pad)->GetBrake()/255.0f;\n\t\t\tm_doingBurnout = 1;\n\t\t}else{\n\t\t\tm_fGasPedal = acceleration;\n\t\t\tm_fBrakePedal = 0.0f;\n\t\t}\n\t}else{\n#if 1\n\t\t// simpler than the code below\n\t\tif(speed * acceleration < 0.0f){\n\t\t\t// if opposite directions, have to brake first\n\t\t\tm_fGasPedal = 0.0f;\n\t\t\tm_fBrakePedal = Abs(acceleration);\n\t\t}else{\n\t\t\t// accelerating in same direction we were already going\n\t\t\tm_fGasPedal = acceleration;\n\t\t\tm_fBrakePedal = 0.0f;\n\t\t}\n#else\n\t\tif(speed < 0.0f){\n\t\t\t// moving backwards currently\n\t\t\tif(acceleration < 0.0f){\n\t\t\t\t// still go backwards\n\t\t\t\tm_fGasPedal = acceleration;\n\t\t\t\tm_fBrakePedal = 0.0f;\n\t\t\t}else{\n\t\t\t\t// want to go forwards, so brake\n\t\t\t\tm_fGasPedal = 0.0f;\n\t\t\t\tm_fBrakePedal = acceleration;\n\t\t\t}\n\t\t}else{\n\t\t\t// moving forwards currently\n\t\t\tif(acceleration < 0.0f){\n\t\t\t\t// want to go backwards, so brake\n\t\t\t\tm_fGasPedal = 0.0f;\n\t\t\t\tm_fBrakePedal = -acceleration;\n\t\t\t}else{\n\t\t\t\t// still go forwards\n\t\t\t\tm_fGasPedal = acceleration;\n\t\t\t\tm_fBrakePedal = 0.0f;\n\t\t\t}\n\t\t}\n#endif\n\t}\n\n\t// Actually turn wheels\n\tstatic float fValue;\t// why static?\n\tif(m_fSteerInput < 0.0f)\n\t\tfValue = -sq(m_fSteerInput);\n\telse\n\t\tfValue = sq(m_fSteerInput);\n\tm_fSteerAngle = DEGTORAD(pHandling->fSteeringLock) * fValue;\n\n\tif(bComedyControls){\n\t\tint rnd = CGeneral::GetRandomNumber() % 10;\n\t\tswitch(m_comedyControlState){\n\t\tcase 0:\n\t\t\tif(rnd < 2)\n\t\t\t\tm_comedyControlState = 1;\n\t\t\telse if(rnd < 4)\n\t\t\t\tm_comedyControlState = 2;\n\t\t\tbreak;\n\t\tcase 1:\n\t\t\tm_fSteerAngle += 0.05f;\n\t\t\tif(rnd < 2)\n\t\t\t\tm_comedyControlState = 0;\n\t\t\tbreak;\n\t\tcase 2:\n\t\t\tm_fSteerAngle -= 0.05f;\n\t\t\tif(rnd < 2)\n\t\t\t\tm_comedyControlState = 0;\n\t\t\tbreak;\n\t\t}\n\t}else\n\t\tm_comedyControlState = 0;\n\n\t// Brake if player isn't in control\n\t// BUG: game always uses pad 0 here\n#ifdef FIX_BUGS\n\tif(CPad::GetPad(pad)->ArePlayerControlsDisabled()){\n#else\n\tif(CPad::GetPad(0)->ArePlayerControlsDisabled()){\n#endif\n\t\tm_fBrakePedal = 1.0f;\n\t\tbIsHandbrakeOn = true;\n\t\tm_fGasPedal = 0.0f;\n\n\t\tFindPlayerPed()->KeepAreaAroundPlayerClear();\n\n\t\t// slow down car immediately\n\t\tspeed = m_vecMoveSpeed.Magnitude();\n\t\tif(speed > 0.28f)\n\t\t\tm_vecMoveSpeed *= 0.28f/speed;\n\t}\n}\n\nvoid\nCAutomobile::FireTruckControl(void)\n{\n\tif(this == FindPlayerVehicle()){\n\t\tif(!CPad::GetPad(0)->GetCarGunFired())\n\t\t\treturn;\n#ifdef FREE_CAM\n\t\tif (!CCamera::bFreeCam)\n#endif \n\t\t{\n\t\t\tm_fCarGunLR += CPad::GetPad(0)->GetCarGunLeftRight() * 0.00025f * CTimer::GetTimeStep();\n\t\t\tm_fCarGunUD += CPad::GetPad(0)->GetCarGunUpDown() * 0.0001f * CTimer::GetTimeStep();\n\t\t}\n\t\tm_fCarGunUD = clamp(m_fCarGunUD, 0.05f, 0.3f);\n\n\n\t\tCVector cannonPos(0.0f, 1.5f, 1.9f);\n\t\tcannonPos = GetMatrix() * cannonPos;\n\t\tCVector cannonDir(\n\t\t\tSin(m_fCarGunLR) * Cos(m_fCarGunUD),\n\t\t\tCos(m_fCarGunLR) * Cos(m_fCarGunUD),\n\t\t\tSin(m_fCarGunUD));\n\t\tcannonDir = Multiply3x3(GetMatrix(), cannonDir);\n\t\tcannonDir.z += (CGeneral::GetRandomNumber()&0xF)/1000.0f;\n\t\tCWaterCannons::UpdateOne((uintptr)this, &cannonPos, &cannonDir);\n\t}else if(GetStatus() == STATUS_PHYSICS){\n\t\tCFire *fire = gFireManager.FindFurthestFire_NeverMindFireMen(GetPosition(), 10.0f, 35.0f);\n\t\tif(fire == nil)\n\t\t\treturn;\n\n\t\t// Target cannon onto fire\n\t\tfloat targetAngle = CGeneral::GetATanOfXY(fire->m_vecPos.x-GetPosition().x, fire->m_vecPos.y-GetPosition().y);\n\t\tfloat fwdAngle = CGeneral::GetATanOfXY(GetForward().x, GetForward().y);\n\t\tfloat targetCannonAngle = fwdAngle - targetAngle;\n\t\tfloat angleDelta = CTimer::GetTimeStep()*0.01f;\n\t\tfloat cannonDelta = targetCannonAngle - m_fCarGunLR;\n\t\twhile(cannonDelta < PI) cannonDelta += TWOPI;\n\t\twhile(cannonDelta > PI) cannonDelta -= TWOPI;\n\t\tif(Abs(cannonDelta) < angleDelta)\n\t\t\tm_fCarGunLR = targetCannonAngle;\n\t\telse if(cannonDelta > 0.0f)\n\t\t\tm_fCarGunLR += angleDelta;\n\t\telse\n\t\t\tm_fCarGunLR -= angleDelta;\n\n\t\t// Go up and down a bit\n\t\tfloat upDown = Sin((float)(CTimer::GetTimeInMilliseconds() & 0xFFF)/0x1000 * TWOPI);\n\t\tm_fCarGunUD = 0.2f + 0.2f*upDown;\n\n\t\t// Spray water every once in a while\n\t\tif((CTimer::GetTimeInMilliseconds()>>10) & 3){\n\t\t\tCVector cannonPos(0.0f, 0.0f, 2.2f);\t// different position than player's firetruck!\n\t\t\tcannonPos = GetMatrix() * cannonPos;\n\t\t\tCVector cannonDir(\n\t\t\t\tSin(m_fCarGunLR) * Cos(m_fCarGunUD),\n\t\t\t\tCos(m_fCarGunLR) * Cos(m_fCarGunUD),\n\t\t\t\tSin(m_fCarGunUD));\n\t\t\tcannonDir = Multiply3x3(GetMatrix(), cannonDir);\n\t\t\tcannonDir.z += (CGeneral::GetRandomNumber()&0xF)/1000.0f;\n\t\t\tCWaterCannons::UpdateOne((uintptr)this, &cannonPos, &cannonDir);\n\t\t}\n\t}\n}\n\nvoid\nCAutomobile::TankControl(void)\n{\n\tint i;\n\n\t// These coords are 1 unit higher then they should be relative to model center\n\tCVector turrentBase(0.0f, -1.394f, 2.296f);\n\tCVector gunEnd(0.0f, 1.813f, 2.979f);\n\tCVector baseToEnd = gunEnd - turrentBase;\n\n\tif(this != FindPlayerVehicle())\n\t\treturn;\n\tif(CWorld::Players[CWorld::PlayerInFocus].m_WBState != WBSTATE_PLAYING)\n\t\treturn;\n\n\t// Rotate turret\n\tfloat prevAngle = m_fCarGunLR;\n#ifdef FREE_CAM\n\tif(!CCamera::bFreeCam)\n#endif\n\t\tm_fCarGunLR -= CPad::GetPad(0)->GetCarGunLeftRight() * 0.00015f * CTimer::GetTimeStep();\n\n\tif(m_fCarGunLR < 0.0f)\n\t\tm_fCarGunLR += TWOPI;\n\tif(m_fCarGunLR > TWOPI)\n\t\tm_fCarGunLR -= TWOPI;\n\tif(m_fCarGunLR != prevAngle)\n\t\tDMAudio.PlayOneShot(m_audioEntityId, SOUND_CAR_TANK_TURRET_ROTATE, Abs(m_fCarGunLR - prevAngle));\n\n\t// Shoot\n\tif(CPad::GetPad(0)->CarGunJustDown() &&\n\t   CTimer::GetTimeInMilliseconds() > CWorld::Players[CWorld::PlayerInFocus].m_nTimeTankShotGun + 800){\n\t\tCWorld::Players[CWorld::PlayerInFocus].m_nTimeTankShotGun = CTimer::GetTimeInMilliseconds();\n\n\t\t// more like -sin(angle), cos(angle), i.e. rotated (0,1,0)\n\t\tCVector turretDir = CVector(Sin(-m_fCarGunLR), Cos(-m_fCarGunLR), 0.0f);\n\t\tturretDir = Multiply3x3(GetMatrix(), turretDir);\n\n\t\tfloat c = Cos(m_fCarGunLR);\n\t\tfloat s = Sin(m_fCarGunLR);\n\t\tCVector rotatedEnd(\n\t\t\tc*baseToEnd.x - s*baseToEnd.y,\n\t\t\ts*baseToEnd.x + c*baseToEnd.y,\n\t\t\tbaseToEnd.z - 1.0f);\t// correct offset here\n\t\trotatedEnd += turrentBase;\n\n\t\tCVector point1 = GetMatrix() * rotatedEnd;\n\t\tCVector point2 = point1 + 60.0f*turretDir;\n\t\tm_vecMoveSpeed -= 0.06f*turretDir;\n\t\tm_vecMoveSpeed.z += 0.05f;\n\n\t\tCWeapon::DoTankDoomAiming(FindPlayerVehicle(), FindPlayerPed(), &point1, &point2);\n\t\tCColPoint colpoint;\n\t\tCEntity *entity = nil;\n\t\tCWorld::ProcessLineOfSight(point1, point2, colpoint, entity, true, true, true, true, true, true, false);\n\t\tif(entity)\n\t\t\tpoint2 = colpoint.point - 0.04f*(colpoint.point - point1);\n\n\t\tCExplosion::AddExplosion(nil, FindPlayerPed(), EXPLOSION_TANK_GRENADE, point2, 0);\n\n\t\t// Add particles on the way to the explosion;\n\t\tfloat shotDist = (point2 - point1).Magnitude();\n\t\tint n = shotDist/4.0f;\n\t\tRwRGBA black = { 0, 0, 0, 0 };\n\t\tfor(i = 0; i < n; i++){\n\t\t\tfloat f = (float)i/n;\n\t\t\tCParticle::AddParticle(PARTICLE_HELI_DUST,\n\t\t\t\tpoint1 + f*(point2 - point1),\n\t\t\t\tCVector(0.0f, 0.0f, 0.0f),\n\t\t\t\tnil, 0.1f, black);\n\t\t}\n\n\t\t// More particles\n\t\tCVector shotDir = point2 - point1;\n\t\tshotDir.Normalise();\n\t\tfor(i = 0; i < 15; i++){\n\t\t\tfloat f = i/15.0f;\n\t\t\tCParticle::AddParticle(PARTICLE_GUNSMOKE2, point1,\n\t\t\t\tshotDir*CGeneral::GetRandomNumberInRange(0.3f, 1.0f)*f,\n\t\t\t\tnil, CGeneral::GetRandomNumberInRange(0.5f, 1.5f)*f, black);\n\t\t}\n\n\t\t// And some gun flashes near the gun\n\t\tCVector flashPos = point1;\n\t\tCVector nullDir(0.0f, 0.0f, 0.0f);\n\t\tint lifeSpan = 250;\n\t\tif(m_vecMoveSpeed.Magnitude() > 0.08f){\n\t\t\tlifeSpan = 125;\n\t\t\tflashPos.x += 5.0f*m_vecMoveSpeed.x;\n\t\t\tflashPos.y += 5.0f*m_vecMoveSpeed.y;\n\t\t}\n\t\tCParticle::AddParticle(PARTICLE_GUNFLASH, flashPos, nullDir, nil, 0.4f, black, 0, 0, 0, lifeSpan);\n\t\tflashPos += 0.3f*shotDir;\n\t\tCParticle::AddParticle(PARTICLE_GUNFLASH, flashPos, nullDir, nil, 0.2f, black, 0, 0, 0, lifeSpan);\n\t\tflashPos += 0.1f*shotDir;\n\t\tCParticle::AddParticle(PARTICLE_GUNFLASH, flashPos, nullDir, nil, 0.15f, black, 0, 0, 0, lifeSpan);\n\t}\n}\n\n#define HYDRAULIC_UPPER_EXT (-0.16f)\n#define HYDRAULIC_LOWER_EXT (0.16f)\n\nvoid\nCAutomobile::HydraulicControl(void)\n{\n\tint i;\n\tfloat wheelPositions[4];\n\tCVehicleModelInfo *mi = (CVehicleModelInfo*)CModelInfo::GetModelInfo(GetModelIndex());\n\tCColModel *normalColModel = mi->GetColModel();\n\tfloat wheelRadius = 0.5f*mi->m_wheelScale;\n\tCPlayerInfo *playerInfo = &CWorld::Players[CWorld::PlayerInFocus];\n\tCColModel *specialColModel = &playerInfo->m_ColModel;\n\n\tif(GetStatus() != STATUS_PLAYER){\n\t\t// reset hydraulics for non-player cars\n\n\t\tif(!bUsingSpecialColModel)\n\t\t\treturn;\n\t\tif(specialColModel != nil)\t// this is always true\n\t\t\tfor(i = 0; i < 4; i++)\n\t\t\t\twheelPositions[i] = specialColModel->lines[i].p0.z - m_aSuspensionSpringRatio[i]*m_aSuspensionLineLength[i];\n\t\tfor(i = 0; i < 4; i++){\n\t\t\tm_aSuspensionSpringLength[i] = pHandling->fSuspensionUpperLimit - pHandling->fSuspensionLowerLimit;\n\t\t\tm_aSuspensionLineLength[i] = normalColModel->lines[i].p0.z - normalColModel->lines[i].p1.z;\n\t\t\tm_aSuspensionSpringRatio[i] = (normalColModel->lines[i].p0.z - wheelPositions[i]) / m_aSuspensionLineLength[i];\n\t\t\tif(m_aSuspensionSpringRatio[i] > 1.0f)\n\t\t\t\tm_aSuspensionSpringRatio[i] = 1.0f;\n\t\t}\n\n\t\tif(m_hydraulicState == 0)\n\t\t\tDMAudio.PlayOneShot(m_audioEntityId, SOUND_CAR_HYDRAULIC_1, 0.0f);\n\t\telse if(m_hydraulicState >= 100)\n\t\t\tDMAudio.PlayOneShot(m_audioEntityId, SOUND_CAR_HYDRAULIC_2, 0.0f);\n\n\t\tif(playerInfo->m_pVehicleEx == this)\n\t\t\tplayerInfo->m_pVehicleEx = nil;\n\t\tbUsingSpecialColModel = false;\n\t\tm_hydraulicState = 0;\n\t\treturn;\n\t}\n\n\t// Player car\n\n\tfloat normalUpperLimit = pHandling->fSuspensionUpperLimit;\n\tfloat normalLowerLimit = pHandling->fSuspensionLowerLimit;\n\tfloat normalSpringLength = normalUpperLimit - normalLowerLimit;\n\tfloat extendedUpperLimit = normalUpperLimit - 0.2f;\n\tfloat extendedLowerLimit = normalLowerLimit - 0.2f;\n\tfloat extendedSpringLength = extendedUpperLimit - extendedLowerLimit;\n\n\tif(!bUsingSpecialColModel){\n\t\t// Init special col model\n\n\t\tif(playerInfo->m_pVehicleEx && playerInfo->m_pVehicleEx == this)\n\t\t\tplayerInfo->m_pVehicleEx->bUsingSpecialColModel = false;\n\t\tplayerInfo->m_pVehicleEx = this;\n\t\tplayerInfo->m_ColModel = *normalColModel;\n\t\tbUsingSpecialColModel = true;\n\t\tspecialColModel = &playerInfo->m_ColModel;\n\n\t\tif(m_fVelocityChangeForAudio > 0.1f)\n\t\t\tm_hydraulicState = 20;\n\t\telse{\n\t\t\tm_hydraulicState = 0;\n\t\t\tnormalUpperLimit += HYDRAULIC_UPPER_EXT;\n\t\t\tnormalSpringLength = normalUpperLimit - (normalLowerLimit+HYDRAULIC_LOWER_EXT);\n\t\t\tDMAudio.PlayOneShot(m_audioEntityId, SOUND_CAR_HYDRAULIC_2, 0.0f);\n\t\t}\n\n\t\t// Setup suspension\n\t\tfloat normalLineLength = normalSpringLength + wheelRadius;\n\t\tCVector pos;\n\t\tfor(i = 0; i < 4; i++){\n\t\t\twheelPositions[i] = normalColModel->lines[i].p0.z - m_aSuspensionSpringRatio[i]*m_aSuspensionLineLength[i];\n\t\t\tmi->GetWheelPosn(i, pos);\n\t\t\tpos.z += normalUpperLimit;\n\t\t\tspecialColModel->lines[i].p0 = pos;\n\t\t\tpos.z -= normalLineLength;\n\t\t\tspecialColModel->lines[i].p1 = pos;\n\t\t\tm_aSuspensionSpringLength[i] = normalSpringLength;\n\t\t\tm_aSuspensionLineLength[i] = normalLineLength;\n\n\t\t\tif(m_aSuspensionSpringRatio[i] < 1.0f){\n\t\t\t\tm_aSuspensionSpringRatio[i] = (specialColModel->lines[i].p0.z - wheelPositions[i])/m_aSuspensionLineLength[i];\n\t\t\t\tif(m_aSuspensionSpringRatio[i] > 1.0f)\n\t\t\t\t\tm_aSuspensionSpringRatio[i] = 1.0f;\n\t\t\t}\n\t\t}\n\t\tDMAudio.PlayOneShot(m_audioEntityId, SOUND_CAR_HYDRAULIC_2, 0.0f);\n\n\t\t// Adjust col model\n\t\tmi->GetWheelPosn(0, pos);\n\t\tfloat minz = pos.z + extendedLowerLimit - wheelRadius;\n\t\tif(minz < specialColModel->boundingBox.min.z)\n\t\t\tspecialColModel->boundingBox.min.z = minz;\n\t\tfloat radius = Max(specialColModel->boundingBox.min.Magnitude(), specialColModel->boundingBox.max.Magnitude());\n\t\tif(specialColModel->boundingSphere.radius < radius)\n\t\t\tspecialColModel->boundingSphere.radius = radius;\n\t\treturn;\n\t}\n\n\tif(playerInfo->m_WBState != WBSTATE_PLAYING)\n\t\treturn;\n\n\tbool setPrevRatio = false;\n\tif(m_hydraulicState < 20 && m_fVelocityChangeForAudio > 0.2f){\n\t\tif(m_hydraulicState == 0){\n\t\t\tm_hydraulicState = 20;\n\t\t\tDMAudio.PlayOneShot(m_audioEntityId, SOUND_CAR_HYDRAULIC_1, 0.0f);\n\t\t\tsetPrevRatio = true;\n\t\t}else{\n\t\t\tm_hydraulicState++;\n\t\t}\n\t}else if(m_hydraulicState != 0){\t// must always be true\n\t\tif(m_hydraulicState < 21 && m_fVelocityChangeForAudio < 0.1f){\n\t\t\tm_hydraulicState--;\n\t\t\tif(m_hydraulicState == 0)\n\t\t\t\tDMAudio.PlayOneShot(m_audioEntityId, SOUND_CAR_HYDRAULIC_2, 0.0f);\n\t\t}\n\t}\n\n\tif(CPad::GetPad(0)->HornJustDown()){\n\t\t// Switch between normal and extended\n\n\t\tif(m_hydraulicState < 100)\n\t\t\tm_hydraulicState = 100;\n\t\telse{\n\t\t\tif(m_fVelocityChangeForAudio > 0.1f)\n\t\t\t\tm_hydraulicState = 20;\n\t\t\telse\n\t\t\t\tm_hydraulicState = 0;\n\t\t}\n\n\t\tif(m_hydraulicState < 100){\n\t\t\tif(m_hydraulicState == 0){\n\t\t\t\tnormalUpperLimit += HYDRAULIC_UPPER_EXT;\n\t\t\t\tnormalLowerLimit += HYDRAULIC_LOWER_EXT;\n\t\t\t\tnormalSpringLength = normalUpperLimit - normalLowerLimit;\n\t\t\t}\n\n\t\t\t// Reset suspension to normal\n\t\t\tfloat normalLineLength = normalSpringLength + wheelRadius;\n\t\t\tCVector pos;\n\t\t\tfor(i = 0; i < 4; i++){\n\t\t\t\twheelPositions[i] = specialColModel->lines[i].p0.z - m_aSuspensionSpringRatio[i]*m_aSuspensionLineLength[i];\n\t\t\t\tmi->GetWheelPosn(i, pos);\n\t\t\t\tpos.z += normalUpperLimit;\n\t\t\t\tspecialColModel->lines[i].p0 = pos;\n\t\t\t\tpos.z -= normalLineLength;\n\t\t\t\tspecialColModel->lines[i].p1 = pos;\n\t\t\t\tm_aSuspensionSpringLength[i] = normalSpringLength;\n\t\t\t\tm_aSuspensionLineLength[i] = normalLineLength;\n\n\t\t\t\tif(m_aSuspensionSpringRatio[i] < 1.0f){\n\t\t\t\t\tm_aSuspensionSpringRatio[i] = (specialColModel->lines[i].p0.z - wheelPositions[i])/m_aSuspensionLineLength[i];\n\t\t\t\t\tif(m_aSuspensionSpringRatio[i] > 1.0f)\n\t\t\t\t\t\tm_aSuspensionSpringRatio[i] = 1.0f;\n\t\t\t\t}\n\t\t\t}\n\t\t\tDMAudio.PlayOneShot(m_audioEntityId, SOUND_CAR_HYDRAULIC_2, 0.0f);\n\t\t}else{\n\t\t\t// Reset suspension to extended\n\t\t\tfloat extendedLineLength = extendedSpringLength + wheelRadius;\n\t\t\tCVector pos;\n\t\t\tfor(i = 0; i < 4; i++){\n\t\t\t\twheelPositions[i] = specialColModel->lines[i].p0.z - m_aSuspensionSpringRatio[i]*m_aSuspensionLineLength[i];\n\t\t\t\tmi->GetWheelPosn(i, pos);\n\t\t\t\tpos.z += extendedUpperLimit;\n\t\t\t\tspecialColModel->lines[i].p0 = pos;\n\t\t\t\tpos.z -= extendedLineLength;\n\t\t\t\tspecialColModel->lines[i].p1 = pos;\n\t\t\t\tm_aSuspensionSpringLength[i] = extendedSpringLength;\n\t\t\t\tm_aSuspensionLineLength[i] = extendedLineLength;\n\n\t\t\t\tif(m_aSuspensionSpringRatio[i] < 1.0f){\n\t\t\t\t\tm_aSuspensionSpringRatio[i] = (specialColModel->lines[i].p0.z - wheelPositions[i])/m_aSuspensionLineLength[i];\n\t\t\t\t\tif(m_aSuspensionSpringRatio[i] > 1.0f)\n\t\t\t\t\t\tm_aSuspensionSpringRatio[i] = 1.0f;\n\t\t\t\t}\n\n\t\t\t\tsetPrevRatio = true;\n\t\t\t}\n\t\t\tDMAudio.PlayOneShot(m_audioEntityId, SOUND_CAR_HYDRAULIC_2, 0.0f);\n\t\t}\n\t}else{\n\t\tfloat suspChange[4];\n\t\tfloat maxDelta = 0.0f;\n\t\tfloat rear = CPad::GetPad(0)->GetCarGunUpDown()/128.0f;\n\t\tfloat front = -rear;\n\t\tfloat right = CPad::GetPad(0)->GetCarGunLeftRight()/128.0f;\n\t\tfloat left = -right;\n\t\tsuspChange[CARWHEEL_FRONT_LEFT] = Max(front+left, 0.0f);\n\t\tsuspChange[CARWHEEL_REAR_LEFT] = Max(rear+left, 0.0f);\n\t\tsuspChange[CARWHEEL_FRONT_RIGHT] = Max(front+right, 0.0f);\n\t\tsuspChange[CARWHEEL_REAR_RIGHT] = Max(rear+right, 0.0f);\n\n\t\tif(m_hydraulicState < 100){\n\t\t\t// Lowered, move wheels up\n\n\t\t\tif(m_hydraulicState == 0){\n\t\t\t\tnormalUpperLimit += HYDRAULIC_UPPER_EXT;\n\t\t\t\tnormalLowerLimit += HYDRAULIC_LOWER_EXT;\n\t\t\t\tnormalSpringLength = normalUpperLimit - normalLowerLimit;\n\t\t\t}\n\n\t\t\t// Set suspension\n\t\t\tCVector pos;\n\t\t\tfor(i = 0; i < 4; i++){\n\t\t\t\tif(suspChange[i] > 1.0f)\n\t\t\t\t\tsuspChange[i] = 1.0f;\n\n\t\t\t\tfloat upperLimit = suspChange[i]*(extendedUpperLimit-normalUpperLimit) + normalUpperLimit;\n\t\t\t\tfloat springLength = suspChange[i]*(extendedSpringLength-normalSpringLength) + normalSpringLength;\n\t\t\t\tfloat lineLength = springLength + wheelRadius;\n\n\t\t\t\twheelPositions[i] = specialColModel->lines[i].p0.z - m_aSuspensionSpringRatio[i]*m_aSuspensionLineLength[i];\n\t\t\t\tmi->GetWheelPosn(i, pos);\n\t\t\t\tpos.z += upperLimit;\n\t\t\t\tspecialColModel->lines[i].p0 = pos;\n\t\t\t\tpos.z -= lineLength;\n\t\t\t\tif(Abs(pos.z - specialColModel->lines[i].p1.z) > Abs(maxDelta))\n\t\t\t\t\tmaxDelta = pos.z - specialColModel->lines[i].p1.z;\n\t\t\t\tspecialColModel->lines[i].p1 = pos;\n\t\t\t\tm_aSuspensionSpringLength[i] = springLength;\n\t\t\t\tm_aSuspensionLineLength[i] = lineLength;\n\n\t\t\t\tif(m_aSuspensionSpringRatio[i] < 1.0f){\n\t\t\t\t\tm_aSuspensionSpringRatio[i] = (specialColModel->lines[i].p0.z - wheelPositions[i])/m_aSuspensionLineLength[i];\n\t\t\t\t\tif(m_aSuspensionSpringRatio[i] > 1.0f)\n\t\t\t\t\t\tm_aSuspensionSpringRatio[i] = 1.0f;\n\t\t\t\t}\n\t\t\t}\n\t\t}else{\n\t\t\tif(m_hydraulicState < 104)\n\t\t\t\tm_hydraulicState++;\n\n\t\t\tif(m_fVelocityChangeForAudio < 0.1f){\n\t\t\t\tnormalUpperLimit += HYDRAULIC_UPPER_EXT;\n\t\t\t\tnormalLowerLimit += HYDRAULIC_LOWER_EXT;\n\t\t\t\tnormalSpringLength = normalUpperLimit - normalLowerLimit;\n\t\t\t}\n\n\t\t\t// Set suspension\n\t\t\tCVector pos;\n\t\t\tfor(i = 0; i < 4; i++){\n\t\t\t\tif(suspChange[i] > 1.0f)\n\t\t\t\t\tsuspChange[i] = 1.0f;\n\n\t\t\t\tfloat upperLimit = suspChange[i]*(normalUpperLimit-extendedUpperLimit) + extendedUpperLimit;\n\t\t\t\tfloat springLength = suspChange[i]*(normalSpringLength-extendedSpringLength) + extendedSpringLength;\n\t\t\t\tfloat lineLength = springLength + wheelRadius;\n\n\t\t\t\twheelPositions[i] = specialColModel->lines[i].p0.z - m_aSuspensionSpringRatio[i]*m_aSuspensionLineLength[i];\n\t\t\t\tmi->GetWheelPosn(i, pos);\n\t\t\t\tpos.z += upperLimit;\n\t\t\t\tspecialColModel->lines[i].p0 = pos;\n\t\t\t\tpos.z -= lineLength;\n\t\t\t\tif(Abs(pos.z - specialColModel->lines[i].p1.z) > Abs(maxDelta))\n\t\t\t\t\tmaxDelta = pos.z - specialColModel->lines[i].p1.z;\n\t\t\t\tspecialColModel->lines[i].p1 = pos;\n\t\t\t\tm_aSuspensionSpringLength[i] = springLength;\n\t\t\t\tm_aSuspensionLineLength[i] = lineLength;\n\n\t\t\t\tif(m_aSuspensionSpringRatio[i] < 1.0f){\n\t\t\t\t\tm_aSuspensionSpringRatio[i] = (specialColModel->lines[i].p0.z - wheelPositions[i])/m_aSuspensionLineLength[i];\n\t\t\t\t\tif(m_aSuspensionSpringRatio[i] > 1.0f)\n\t\t\t\t\t\tm_aSuspensionSpringRatio[i] = 1.0f;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfloat limitDiff = extendedLowerLimit - normalLowerLimit;\n\t\tif(limitDiff != 0.0f && Abs(maxDelta/limitDiff) > 0.01f){\n\t\t\tfloat f = (maxDelta + limitDiff)/2.0f/limitDiff;\n\t\t\tf = clamp(f, 0.0f, 1.0f);\n\t\t\tDMAudio.PlayOneShot(m_audioEntityId, SOUND_CAR_HYDRAULIC_3, f);\n\t\t\tif(f < 0.4f || f > 0.6f)\n\t\t\t\tsetPrevRatio = true;\n\t\t\tif(f < 0.25f)\n\t\t\t\tDMAudio.PlayOneShot(m_audioEntityId, SOUND_CAR_HYDRAULIC_2, 0.0f);\n\t\t\telse if(f > 0.75f)\n\t\t\t\tDMAudio.PlayOneShot(m_audioEntityId, SOUND_CAR_HYDRAULIC_1, 0.0f);\n\t\t}\n\t}\n\n\tif(setPrevRatio)\n\t\tfor(i = 0; i < 4; i++){\n\t\t\t// wheel radius in relation to suspension line\n\t\t\tfloat wheelRadius = 1.0f - m_aSuspensionSpringLength[i]/m_aSuspensionLineLength[i];\n\t\t\tm_aSuspensionSpringRatioPrev[i] = (m_aSuspensionSpringRatio[i]-wheelRadius)/(1.0f-wheelRadius);\n\t\t}\n}\n\nvoid\nCAutomobile::ProcessBuoyancy(void)\t\n{\n\tint i;\n\tCVector impulse, point;\n\n\tif(mod_Buoyancy.ProcessBuoyancy(this, m_fBuoyancy, &point, &impulse)){\n\t\tfloat timeStep = Max(CTimer::GetTimeStep(), 0.01f);\n\t\tfloat impulseRatio = impulse.z / (GRAVITY * m_fMass * timeStep);\n\t\tfloat waterResistance = Pow(1.0f - 0.05f*impulseRatio, CTimer::GetTimeStep());\n\t\tm_vecMoveSpeed *= waterResistance;\n\t\tm_vecTurnSpeed *= waterResistance;\n\n\t\tbool heliHitWaterHard = false;\n\t\tif(IsRealHeli() && m_aWheelSpeed[1] > 0.15f){\n\t\t\tif(GetModelIndex() == MI_SEASPAR){\n\t\t\t\tif(impulseRatio > 3.0f){\n\t\t\t\t\tm_aWheelSpeed[1] = 0.0f;\n\t\t\t\t\theliHitWaterHard = true;\n\t\t\t\t}\n\t\t\t}else{\n\t\t\t\tfloat strength = 1.0f/Max(8.0f*impulseRatio, 1.0f);\n\t\t\t\tApplyMoveForce(-2.0f*impulse/strength);\n\t\t\t\tApplyTurnForce(-impulse/strength, point);\n\t\t\t\tif(impulseRatio > 0.9f){\n\t\t\t\t\tm_aWheelSpeed[1] = 0.0f;\n\t\t\t\t\theliHitWaterHard = true;\n\t\t\t\t}else\n\t\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tbTouchingWater = true;\n\t\tApplyMoveForce(impulse);\n\t\tApplyTurnForce(impulse, point);\n\t\tCVector initialSpeed = m_vecMoveSpeed;\n\n\t\tif(m_modelIndex == MI_SEASPAR && impulseRatio < 3.0f && (GetUp().z > -0.5f || impulseRatio < 0.6f) ||\n\t\t   CVehicle::bHoverCheat && GetStatus() == STATUS_PLAYER && GetUp().z > 0.1f){\n\t\t\tbIsInWater = false;\n\t\t\tbIsDrowning = false;\n\t\t}else if(heliHitWaterHard || impulseRatio > 1.0f ||\n\t\t         impulseRatio > 0.6f && (m_aSuspensionSpringRatio[0] == 1.0f ||\n\t\t                                 m_aSuspensionSpringRatio[1] == 1.0f ||\n\t\t                                 m_aSuspensionSpringRatio[2] == 1.0f ||\n\t\t                                 m_aSuspensionSpringRatio[3] == 1.0f)){\n\t\t\tbIsInWater = true;\n\t\t\tbIsDrowning = true;\n\t\t\tif(m_vecMoveSpeed.z < -0.1f)\n\t\t\t\tm_vecMoveSpeed.z = -0.1f;\n\n\t\t\tif(pDriver){\n\t\t\t\tpDriver->bIsInWater = true;\n\t\t\t\tif(pDriver->IsPlayer() || !bWaterTight)\n\t\t\t\t\tpDriver->InflictDamage(nil, WEAPONTYPE_DROWNING, CTimer::GetTimeStep(), PEDPIECE_TORSO, 0);\n\t\t\t}\n\t\t\tfor(i = 0; i < m_nNumMaxPassengers; i++)\n\t\t\t\tif(pPassengers[i]){\n\t\t\t\t\tpPassengers[i]->bIsInWater = true;\n\t\t\t\t\tif(pPassengers[i]->IsPlayer() || !bWaterTight)\n\t\t\t\t\t\tpPassengers[i]->InflictDamage(nil, WEAPONTYPE_DROWNING, CTimer::GetTimeStep(), PEDPIECE_TORSO, 0);\n\t\t\t\t}\n\t\t}else{\n\t\t\tbIsInWater = false;\n\t\t\tbIsDrowning = false;\n\t\t}\n\n\t\tstatic uint32 nGenerateRaindrops = 0;\n\t\tstatic uint32 nGenerateWaterCircles = 0;\n\n\t\tif(initialSpeed.z < -0.1f && impulse.z > 0.3f || heliHitWaterHard){\n\t\t\tRwRGBA color;\n\t\t\tcolor.red = (0.5f * CTimeCycle::GetDirectionalRed() + CTimeCycle::GetAmbientRed_Obj())*0.45f*255;\n\t\t\tcolor.green = (0.5f * CTimeCycle::GetDirectionalGreen() + CTimeCycle::GetAmbientGreen_Obj())*0.45f*255;\n\t\t\tcolor.blue = (0.5f * CTimeCycle::GetDirectionalBlue() + CTimeCycle::GetAmbientBlue_Obj())*0.45f*255;\n\t\t\tcolor.alpha = CGeneral::GetRandomNumberInRange(0, 32) + 128;\n\t\t\tCVector target = CVector(0.0f, 0.0f, CGeneral::GetRandomNumberInRange(0.15f, 0.45f));\n\t\t\tCParticleObject::AddObject(POBJECT_CAR_WATER_SPLASH, GetPosition(),\n\t\t\t\ttarget, 0.0f, 75, color, true);\n\n\t\t\tnGenerateRaindrops = CTimer::GetTimeInMilliseconds() + 300;\n\t\t\tnGenerateWaterCircles = CTimer::GetTimeInMilliseconds() + 60;\n\n\t\t\tif(heliHitWaterHard){\n\t\t\t\tCVector right = CrossProduct(GetForward(), CVector(0.0f, 0.0f, 1.0f));\n\t\t\t\tCParticleObject::AddObject(POBJECT_CAR_WATER_SPLASH, GetPosition() + right,\n\t\t\t\t\ttarget, 0.0f, 75, color, true);\n\t\t\t\tCParticleObject::AddObject(POBJECT_CAR_WATER_SPLASH, GetPosition() - right,\n\t\t\t\t\ttarget, 0.0f, 75, color, true);\n\t\t\t}\n\n\t\t\tif(m_vecMoveSpeed.z < -0.2f)\n\t\t\t\tm_vecMoveSpeed.z = -0.2f;\n\t\t\tDMAudio.PlayOneShot(m_audioEntityId, SOUND_WATER_FALL, 0.0f);\n\t\t}\n\n\t\tif(nGenerateWaterCircles > 0 && nGenerateWaterCircles <= CTimer::GetTimeInMilliseconds()){\n\t\t\tCVector pos = GetPosition();\n\t\t\tfloat waterLevel = 0.0f;\n\t\t\tif(CWaterLevel::GetWaterLevel(pos.x, pos.y, pos.z, &waterLevel, false))\n\t\t\t\tpos.z = waterLevel;\n\t\t\tstatic RwRGBA black;\n\t\t\tif(pos.z != 0.0f){\n\t\t\t\tnGenerateWaterCircles = 0;\n\t\t\t\tpos.z += 1.0f;\n\t\t\t\tfor(i = 0; i < 4; i++){\n\t\t\t\t\tCVector p = pos;\n\t\t\t\t\tp.x += CGeneral::GetRandomNumberInRange(-2.5f, 2.5f);\n\t\t\t\t\tp.y += CGeneral::GetRandomNumberInRange(-2.5f, 2.5f);\n\t\t\t\t\tCParticle::AddParticle(PARTICLE_RAIN_SPLASH_BIGGROW,\n\t\t\t\t\t\tp, CVector(0.0f, 0.0f, 0.0f),\n\t\t\t\t\t\tnil, 0.0f, black, 0, 0, 0, 0);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif(nGenerateRaindrops > 0 && nGenerateRaindrops <= CTimer::GetTimeInMilliseconds()){\n\t\t\tCVector pos = GetPosition();\n\t\t\tfloat waterLevel = 0.0f;\n\t\t\tif(CWaterLevel::GetWaterLevel(pos.x, pos.y, pos.z, &waterLevel, false))\n\t\t\t\tpos.z = waterLevel;\n\t\t\tstatic RwRGBA black;\n\t\t\tif(pos.z >= 0.0f){\n\t\t\t\tnGenerateRaindrops = 0;\n\t\t\t\tpos.z += 0.5f;\n\t\t\t\tCParticleObject::AddObject(POBJECT_SPLASHES_AROUND,\n\t\t\t\t\tpos, CVector(0.0f, 0.0f, 0.0f), 6.5f, 2500, black, true);\n\t\t\t}\n\t\t}\n\t}else{\n\t\tbIsInWater = false;\n\t\tbIsDrowning = false;\n\t\tbTouchingWater = false;\n\n\t\tstatic RwRGBA splashCol = {155, 155, 185, 196};\n\t\tstatic RwRGBA smokeCol = {255, 255, 255, 255};\n\n\t\tfor(i = 0; i < 4; i++){\n\t\t\tif(m_aSuspensionSpringRatio[i] < 1.0f && m_aWheelColPoints[i].surfaceB == SURFACE_WATER){\n\t\t\t\tCVector pos = m_aWheelColPoints[i].point + 0.3f*GetUp() - GetPosition();\n\t\t\t\tCVector vSpeed = GetSpeed(pos);\n\t\t\t\tvSpeed.z = 0.0f;\n\t\t\t\tfloat fSpeed = vSpeed.MagnitudeSqr();\n\t\t\t\tif(fSpeed > sq(0.05f)){\n\t\t\t\t\tfSpeed = Sqrt(fSpeed);\n\n\t\t\t\t\tfloat size = Min((fSpeed < 0.15f ? 0.25f : 0.75f)*fSpeed, 0.6f);\n\t\t\t\t\tCVector right = 0.2f*fSpeed*GetRight() + 0.2f*vSpeed;\n\n\t\t\t\t\tCParticle::AddParticle(PARTICLE_PED_SPLASH,\n\t\t\t\t\t\tpos + GetPosition(), -0.5f*right,\n\t\t\t\t\t\tnil, size, splashCol,\n\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(0.0f, 10.0f),\n\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(0.0f, 90.0f), 1, 0);\n\n\t\t\t\t\tCParticle::AddParticle(PARTICLE_RUBBER_SMOKE,\n\t\t\t\t\t\tpos + GetPosition(), -0.6f*right,\n\t\t\t\t\t\tnil, size, smokeCol, 0, 0, 0, 0);\n\t\t\t\t\n\t\t\t\t\tif((CTimer::GetFrameCounter() & 0xF) == 0)\n\t\t\t\t\t\tDMAudio.PlayOneShot(m_audioEntityId, SOUND_CAR_SPLASH, 2000.0f*fSpeed);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nCAutomobile::DoDriveByShootings(void)\n{\n\tCAnimBlendAssociation *anim = nil;\n\tCPlayerInfo* playerInfo = ((CPlayerPed*)pDriver)->GetPlayerInfoForThisPlayerPed();\n\tif (playerInfo && !playerInfo->m_bDriveByAllowed)\n\t\treturn;\n\n\tCWeapon *weapon = pDriver->GetWeapon();\n\tif(CWeaponInfo::GetWeaponInfo(weapon->m_eWeaponType)->m_nWeaponSlot != WEAPONSLOT_SUBMACHINEGUN)\n\t\treturn;\n\n\tweapon->Update(pDriver->m_audioEntityId, nil);\n\n\tbool lookingLeft = false;\n\tbool lookingRight = false;\n\tif(TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOPDOWN ||\n\t   TheCamera.m_bObbeCinematicCarCamOn){\n\t\tif(CPad::GetPad(0)->GetLookLeft())\n\t\t\tlookingLeft = true;\n\t\tif(CPad::GetPad(0)->GetLookRight())\n\t\t\tlookingRight = true;\n\t}else{\n\t\tif(TheCamera.Cams[TheCamera.ActiveCam].LookingLeft)\n\t\t\tlookingLeft = true;\n\t\tif(TheCamera.Cams[TheCamera.ActiveCam].LookingRight)\n\t\t\tlookingRight = true;\n\t}\n\n\tAnimationId rightAnim = ANIM_STD_CAR_DRIVEBY_RIGHT;\n\tAnimationId leftAnim = ANIM_STD_CAR_DRIVEBY_LEFT;\n\tif (pDriver->m_pMyVehicle->bLowVehicle) {\n\t\trightAnim = ANIM_STD_CAR_DRIVEBY_RIGHT_LO;\n\t\tleftAnim = ANIM_STD_CAR_DRIVEBY_LEFT_LO;\n\t}\n\n\tif(lookingLeft || lookingRight){\n\t\tif(lookingLeft){\n\t\t\tanim = RpAnimBlendClumpGetAssociation(pDriver->GetClump(), rightAnim);\n\t\t\tif(anim)\n\t\t\t\tanim->blendDelta = -1000.0f;\n\t\t\tanim = RpAnimBlendClumpGetAssociation(pDriver->GetClump(), leftAnim);\n\t\t\tif(anim == nil || anim->blendDelta < 0.0f)\n\t\t\t\tanim = CAnimManager::AddAnimation(pDriver->GetClump(), ASSOCGRP_STD, leftAnim);\n\t\t}else if(pDriver->m_pMyVehicle->pPassengers[0] == nil || TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_1STPERSON){\n\t\t\tanim = RpAnimBlendClumpGetAssociation(pDriver->GetClump(), leftAnim);\n\t\t\tif(anim)\n\t\t\t\tanim->blendDelta = -1000.0f;\n\t\t\tanim = RpAnimBlendClumpGetAssociation(pDriver->GetClump(), rightAnim);\n\t\t\tif(anim == nil || anim->blendDelta < 0.0f)\n\t\t\t\tanim = CAnimManager::AddAnimation(pDriver->GetClump(), ASSOCGRP_STD, rightAnim);\n\t\t}\n\n\t\tif (!anim || !anim->IsRunning()) {\n\t\t\tif (CPad::GetPad(0)->GetCarGunFired() && CTimer::GetTimeInMilliseconds() > weapon->m_nTimer) {\n\t\t\t\tweapon->FireFromCar(this, lookingLeft, true);\n\t\t\t\tweapon->m_nTimer = CTimer::GetTimeInMilliseconds() + 70;\n\t\t\t}\n\t\t}\n\t}else{\n\t\tweapon->Reload();\n\t\tanim = RpAnimBlendClumpGetAssociation(pDriver->GetClump(), leftAnim);\n\t\tif(anim)\n\t\t\tanim->blendDelta = -1000.0f;\n\t\tanim = RpAnimBlendClumpGetAssociation(pDriver->GetClump(), rightAnim);\n\t\tif(anim)\n\t\t\tanim->blendDelta = -1000.0f;\n\t}\n\n\t// TODO: what is this?\n\tif(!lookingLeft && m_weaponDoorTimerLeft > 0.0f){\n\t\tm_weaponDoorTimerLeft = Max(m_weaponDoorTimerLeft - CTimer::GetTimeStep()*0.1f, 0.0f);\n\t\tProcessOpenDoor(CAR_DOOR_LF, ANIM_STD_NUM, m_weaponDoorTimerLeft);\n\t}\n\tif(!lookingRight && m_weaponDoorTimerRight > 0.0f){\n\t\tm_weaponDoorTimerRight = Max(m_weaponDoorTimerRight - CTimer::GetTimeStep()*0.1f, 0.0f);\n\t\tProcessOpenDoor(CAR_DOOR_RF, ANIM_STD_NUM, m_weaponDoorTimerRight);\n\t}\n}\n\nvoid\nCAutomobile::DoHoverSuspensionRatios(void)\n{\n\tint i;\n\n\tif(GetUp().z < 0.1f)\n\t\treturn;\n\n\tCColModel *colmodel = GetColModel();\n\tfor(i = 0; i < 4; i++){\n\t\tfloat z, waterZ;\n\t\tCVector upper = GetMatrix() * colmodel->lines[i].p0;\n\t\tCVector lower = GetMatrix() * colmodel->lines[i].p1;\n\t\tif(m_aSuspensionSpringRatio[i] < 1.0f)\n\t\t\tz = m_aWheelColPoints[i].point.z;\n\t\telse\n\t\t\tz = -100.0f;\n\t\t// see if touching water\n\t\tif(CWaterLevel::GetWaterLevel(lower, &waterZ, false) &&\n\t\t   waterZ > z && lower.z-1.0f < waterZ){\n\t\t\t// compress spring\n\t\t\tif(lower.z < waterZ){\n\t\t\t\tif(upper.z < waterZ)\n\t\t\t\t\tm_aSuspensionSpringRatio[i] = 0.0f;\n\t\t\t\telse\n\t\t\t\t\tm_aSuspensionSpringRatio[i] = (upper.z - waterZ)/(upper.z - lower.z);\n\t\t\t}else\n\t\t\t\tm_aSuspensionSpringRatio[i] = 0.99999f;\n\n\t\t\tm_aWheelColPoints[i].point.x = (lower.x - upper.x)*m_aSuspensionSpringRatio[i] + upper.x;\n\t\t\tm_aWheelColPoints[i].point.y = (lower.y - upper.y)*m_aSuspensionSpringRatio[i] + upper.y;\n\t\t\tm_aWheelColPoints[i].point.z = waterZ;\n\t\t\tm_aWheelColPoints[i].normal = CVector(0.01f, 0.0f, 1.0f);\n\t\t\tm_aWheelColPoints[i].surfaceB = SURFACE_WATER;\n\t\t}\n\t}\n}\n\nint32\nCAutomobile::RcbanditCheckHitWheels(void)\n{\n\tint x, xmin, xmax;\n\tint y, ymin, ymax;\n\n\txmin = CWorld::GetSectorIndexX(GetPosition().x - 2.0f);\n\tif(xmin < 0) xmin = 0;\n\txmax = CWorld::GetSectorIndexX(GetPosition().x + 2.0f);\n\tif(xmax > NUMSECTORS_X-1) xmax = NUMSECTORS_X-1;\n\tymin = CWorld::GetSectorIndexY(GetPosition().y - 2.0f);\n\tif(ymin < 0) ymin = 0;\n\tymax = CWorld::GetSectorIndexY(GetPosition().y + 2.0f);\n\tif(ymax > NUMSECTORS_Y-1) ymax = NUMSECTORS_X-1;\n\n\tCWorld::AdvanceCurrentScanCode();\n\n\tfor(y = ymin; y <= ymax; y++)\n\t\tfor(x = xmin; x <= xmax; x++){\n\t\t\tCSector *s = CWorld::GetSector(x, y);\n\t\t\tif(RcbanditCheck1CarWheels(s->m_lists[ENTITYLIST_VEHICLES]) ||\n\t\t\t   RcbanditCheck1CarWheels(s->m_lists[ENTITYLIST_VEHICLES_OVERLAP]))\n\t\t\t\treturn 1;\n\t\t}\n\treturn 0;\n}\n\nint32\nCAutomobile::RcbanditCheck1CarWheels(CPtrList &list)\n{\n\tstatic CMatrix matW2B;\n\tint i;\n\tCPtrNode *node;\n\tCAutomobile *car;\n\tCColModel *colModel = GetColModel();\n\tCVehicleModelInfo *mi;\n\n\tfor(node = list.first; node; node = node->next){\n\t\tcar = (CAutomobile*)node->item;\n\t\tif(this != car && car->IsCar() && car->GetModelIndex() != MI_RCBANDIT &&\n\t\t   car->m_scanCode != CWorld::GetCurrentScanCode()){\n\t\t\tcar->m_scanCode = CWorld::GetCurrentScanCode();\n\n\t\t\tif(Abs(this->GetPosition().x - car->GetPosition().x) < 10.0f &&\n\t\t\t   Abs(this->GetPosition().y - car->GetPosition().y) < 10.0f){\n\t\t\t\tmi = (CVehicleModelInfo*)CModelInfo::GetModelInfo(car->GetModelIndex());\n\n\t\t\t\tfor(i = 0; i < 4; i++){\n\t\t\t\t\tif(car->m_aSuspensionSpringRatioPrev[i] < 1.0f || car->GetStatus() == STATUS_SIMPLE){\n\t\t\t\t\t\tCVector wheelPos;\n\t\t\t\t\t\tCColSphere sph;\n\t\t\t\t\t\tmi->GetWheelPosn(i, wheelPos);\n\t\t\t\t\t\tmatW2B = Invert(GetMatrix());\n\t\t\t\t\t\tsph.center = matW2B * (car->GetMatrix() * wheelPos);\n\t\t\t\t\t\tsph.radius = mi->m_wheelScale*0.25f;\n\t\t\t\t\t\tif(CCollision::TestSphereBox(sph, colModel->boundingBox))\n\t\t\t\t\t\t\treturn 1;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn 0;\n}\n\nvoid\nCAutomobile::PlaceOnRoadProperly(void)\n{\n\tCColPoint point;\n\tCEntity *entity;\n\tCColModel *colModel = GetColModel();\n\tfloat lenFwd, lenBack;\n\tfloat frontZ, rearZ;\n\n\tlenFwd = colModel->boundingBox.max.y;\n\tlenBack = -colModel->boundingBox.min.y;\n\n\tCVector front(GetPosition().x + GetForward().x*lenFwd,\n\t              GetPosition().y + GetForward().y*lenFwd,\n\t              GetPosition().z + 5.0f);\n\tif(CWorld::ProcessVerticalLine(front, GetPosition().z - 5.0f, point, entity,\n\t\t\ttrue, false, false, false, false, false, nil)){\n\t\tfrontZ = point.point.z;\n\t\tm_pCurGroundEntity = entity;\n\t}else{\n\t\tfrontZ = m_fMapObjectHeightAhead;\n\t}\n\n\tCVector rear(GetPosition().x - GetForward().x*lenBack,\n\t             GetPosition().y - GetForward().y*lenBack,\n\t             GetPosition().z + 5.0f);\n\tif(CWorld::ProcessVerticalLine(rear, GetPosition().z - 5.0f, point, entity,\n\t\t\ttrue, false, false, false, false, false, nil)){\n\t\trearZ = point.point.z;\n\t\tm_pCurGroundEntity = entity;\n\t}else{\n\t\trearZ = m_fMapObjectHeightBehind;\n\t}\n\n\tfloat len = lenFwd + lenBack;\n\tfloat angle = Atan((frontZ - rearZ)/len);\n\tfloat c = Cos(angle);\n\tfloat s = Sin(angle);\n\n\tGetMatrix().GetRight() = CVector((front.y - rear.y) / len, -(front.x - rear.x) / len, 0.0f);\n\tGetMatrix().GetForward() = CVector(-c * GetRight().y, c * GetRight().x, s);\n\tGetMatrix().GetUp() = CrossProduct(GetRight(), GetForward());\n\tGetMatrix().GetPosition() = CVector((front.x + rear.x) / 2.0f, (front.y + rear.y) / 2.0f, (frontZ + rearZ) / 2.0f + GetHeightAboveRoad());\n}\n\nvoid\nCAutomobile::VehicleDamage(float impulse, uint16 damagedPiece)\n{\n\tint i;\n\tfloat damageMultiplier = 0.333f;\n\n\tif(impulse == 0.0f){\n\t\timpulse = m_fDamageImpulse;\n\t\tdamagedPiece = m_nDamagePieceType;\n\t\tdamageMultiplier = 1.0f;\n\t}\n\n\tif(GetStatus() == STATUS_PLAYER && CStats::GetPercentageProgress() >= 100.0f)\n\t\timpulse *= 0.5f;\n\n\tCVector pos(0.0f, 0.0f, 0.0f);\n\n\tif(!bCanBeDamaged)\n\t\treturn;\n\n\tif(m_pDamageEntity && m_pDamageEntity->IsPed() && ((CPed*)m_pDamageEntity)->bIsStanding){\n\t\tfloat speed = ((CPed*)m_pDamageEntity)->m_vecAnimMoveDelta.y * DotProduct(GetForward(), m_vecDamageNormal);\n\t\tif(speed < 0.0f)\n\t\t\timpulse = Max(impulse + ((CPed*)m_pDamageEntity)->m_fMass * speed, 0.0f);\n\t}\n\n\t// damage flipped over car\n\tif(GetUp().z < 0.0f && this != FindPlayerVehicle()){\n\t\tif(bNotDamagedUpsideDown || GetStatus() == STATUS_PLAYER_REMOTE || bIsInWater)\n\t\t\treturn;\n\t\tif(GetStatus() != STATUS_WRECKED)\n\t\t\tm_fHealth = Max(m_fHealth - 4.0f*CTimer::GetTimeStep(), 0.0f);\n\t}\n\n\tfloat minImpulse = GetModelIndex() == MI_RCRAIDER || GetModelIndex() == MI_RCGOBLIN ? 1.0f : 25.0f;\n\tif(impulse > minImpulse && GetStatus() != STATUS_WRECKED){\n\t\tif(bIsLawEnforcer &&\n\t\t   FindPlayerVehicle() && FindPlayerVehicle() == m_pDamageEntity &&\n\t\t   GetStatus() != STATUS_ABANDONED &&\n\t\t   FindPlayerVehicle()->m_vecMoveSpeed.Magnitude() >= m_vecMoveSpeed.Magnitude() &&\n\t\t   FindPlayerVehicle()->m_vecMoveSpeed.Magnitude() > 0.1f)\n\t\t\tFindPlayerPed()->SetWantedLevelNoDrop(1);\n\n\t\tif(GetStatus() == STATUS_PLAYER && impulse > 50.0f){\n\t\t\tuint8 freq = Min(0.4f*impulse*2000.0f/m_fMass + 100.0f, 250.0f);\n\t\t\tCPad::GetPad(0)->StartShake(40000/freq, freq);\n\t\t}\n\n\t\tif(GetStatus() != STATUS_PLAYER && bOnlyDamagedByPlayer){\n\t\t\tif(m_pDamageEntity != FindPlayerPed() &&\n\t\t\t   m_pDamageEntity != FindPlayerVehicle())\n\t\t\t\treturn;\n\t\t}\n\n\t\tif(m_pDamageEntity && m_pDamageEntity->IsVehicle()){\n\t\t\tm_nLastWeaponDamage = WEAPONTYPE_RAMMEDBYCAR;\n\t\t\tm_pLastDamageEntity = m_pDamageEntity;\n\t\t}\n\n\t\tif(bCollisionProof)\n\t\t\treturn;\n\n\t\tif(m_pDamageEntity){\n\t\t\tif(m_pDamageEntity->IsBuilding() &&\n\t\t\t   DotProduct(m_vecDamageNormal, GetUp()) > 0.6f)\n\t\t\t\treturn;\n\t\t}\n\n\t\tint oldLightStatus[4];\n\t\tfor(i = 0; i < 4; i++)\n\t\t\toldLightStatus[i] = Damage.GetLightStatus((eLights)i);\n\n\t\tif(GetUp().z > 0.0f || m_vecMoveSpeed.MagnitudeSqr() > 0.1f){\n\t\t\tfloat impulseMult = bMoreResistantToDamage ? 0.5f : 4.0f;\n\n\t\t\tswitch(damagedPiece){\n\t\t\tcase CAR_PIECE_BUMP_FRONT:\n\t\t\t\tGetComponentWorldPosition(CAR_BUMP_FRONT, pos);\n\t\t\t\tdmgDrawCarCollidingParticles(pos, impulse*damageMultiplier);\n\t\t\t\tif(Damage.ApplyDamage(COMPONENT_BUMPER_FRONT, impulse*impulseMult, pHandling->fCollisionDamageMultiplier))\n\t\t\t\t\tSetBumperDamage(CAR_BUMP_FRONT, VEHBUMPER_FRONT);\n\t\t\t\tif(m_aCarNodes[CAR_BONNET] && Damage.GetPanelStatus(VEHBUMPER_FRONT) == PANEL_STATUS_MISSING){\n\t\t\tcase CAR_PIECE_BONNET:\n\t\t\t\t\tGetComponentWorldPosition(CAR_BONNET, pos);\n\t\t\t\t\tdmgDrawCarCollidingParticles(pos, impulse*damageMultiplier);\n\t\t\t\t\tif(GetModelIndex() != MI_DODO)\n\t\t\t\t\tif(Damage.ApplyDamage(COMPONENT_DOOR_BONNET, impulse*impulseMult, pHandling->fCollisionDamageMultiplier))\n\t\t\t\t\t\tSetDoorDamage(CAR_BONNET, DOOR_BONNET);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase CAR_PIECE_BUMP_REAR:\n\t\t\t\tGetComponentWorldPosition(CAR_BUMP_REAR, pos);\n\t\t\t\tdmgDrawCarCollidingParticles(pos, impulse*damageMultiplier);\n\t\t\t\tif(Damage.ApplyDamage(COMPONENT_BUMPER_REAR, impulse*impulseMult, pHandling->fCollisionDamageMultiplier))\n\t\t\t\t\tSetBumperDamage(CAR_BUMP_REAR, VEHBUMPER_REAR);\n\t\t\t\tif(m_aCarNodes[CAR_BOOT] && Damage.GetPanelStatus(VEHBUMPER_REAR) == PANEL_STATUS_MISSING){\n\t\t\tcase CAR_PIECE_BOOT:\n\t\t\t\t\tGetComponentWorldPosition(CAR_BOOT, pos);\n\t\t\t\t\tdmgDrawCarCollidingParticles(pos, impulse*damageMultiplier);\n\t\t\t\t\tif(Damage.ApplyDamage(COMPONENT_DOOR_BOOT, impulse*impulseMult, pHandling->fCollisionDamageMultiplier))\n\t\t\t\t\t\tSetDoorDamage(CAR_BOOT, DOOR_BOOT);\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase CAR_PIECE_DOOR_LF:\n\t\t\t\tGetComponentWorldPosition(CAR_DOOR_LF, pos);\n\t\t\t\tdmgDrawCarCollidingParticles(pos, impulse*damageMultiplier);\n\t\t\t\tif(Damage.ApplyDamage(COMPONENT_DOOR_FRONT_LEFT, impulse*impulseMult, pHandling->fCollisionDamageMultiplier))\n\t\t\t\t\tSetDoorDamage(CAR_DOOR_LF, DOOR_FRONT_LEFT);\n\t\t\t\tbreak;\n\t\t\tcase CAR_PIECE_DOOR_RF:\n\t\t\t\tGetComponentWorldPosition(CAR_DOOR_RF, pos);\n\t\t\t\tdmgDrawCarCollidingParticles(pos, impulse*damageMultiplier);\n\t\t\t\tif(Damage.ApplyDamage(COMPONENT_DOOR_FRONT_RIGHT, impulse*impulseMult, pHandling->fCollisionDamageMultiplier))\n\t\t\t\t\tSetDoorDamage(CAR_DOOR_RF, DOOR_FRONT_RIGHT);\n\t\t\t\tbreak;\n\t\t\tcase CAR_PIECE_DOOR_LR:\n\t\t\t\tGetComponentWorldPosition(CAR_DOOR_LR, pos);\n\t\t\t\tdmgDrawCarCollidingParticles(pos, impulse*damageMultiplier);\n\t\t\t\tif(Damage.ApplyDamage(COMPONENT_DOOR_REAR_LEFT, impulse*impulseMult, pHandling->fCollisionDamageMultiplier))\n\t\t\t\t\tSetDoorDamage(CAR_DOOR_LR, DOOR_REAR_LEFT);\n\t\t\t\tbreak;\n\t\t\tcase CAR_PIECE_DOOR_RR:\n\t\t\t\tGetComponentWorldPosition(CAR_DOOR_RR, pos);\n\t\t\t\tdmgDrawCarCollidingParticles(pos, impulse*damageMultiplier);\n\t\t\t\tif(Damage.ApplyDamage(COMPONENT_DOOR_REAR_RIGHT, impulse*impulseMult, pHandling->fCollisionDamageMultiplier))\n\t\t\t\t\tSetDoorDamage(CAR_DOOR_RR, DOOR_REAR_RIGHT);\n\t\t\t\tbreak;\n\n\t\t\tcase CAR_PIECE_WING_LF:\n\t\t\t\tGetComponentWorldPosition(CAR_WING_LF, pos);\n\t\t\t\tdmgDrawCarCollidingParticles(pos, impulse*damageMultiplier);\n\t\t\t\tif(Damage.ApplyDamage(COMPONENT_PANEL_FRONT_LEFT, impulse*impulseMult, pHandling->fCollisionDamageMultiplier))\n\t\t\t\t\tSetPanelDamage(CAR_WING_LF, VEHPANEL_FRONT_LEFT);\n\t\t\t\tbreak;\n\t\t\tcase CAR_PIECE_WING_RF:\n\t\t\t\tGetComponentWorldPosition(CAR_WING_RF, pos);\n\t\t\t\tdmgDrawCarCollidingParticles(pos, impulse*damageMultiplier);\n\t\t\t\tif(Damage.ApplyDamage(COMPONENT_PANEL_FRONT_RIGHT, impulse*impulseMult, pHandling->fCollisionDamageMultiplier))\n\t\t\t\t\tSetPanelDamage(CAR_WING_RF, VEHPANEL_FRONT_RIGHT);\n\t\t\t\tbreak;\n\t\t\tcase CAR_PIECE_WING_LR:\n\t\t\t\tGetComponentWorldPosition(CAR_WING_LR, pos);\n\t\t\t\tdmgDrawCarCollidingParticles(pos, impulse*damageMultiplier);\n\t\t\t\tif(Damage.ApplyDamage(COMPONENT_PANEL_REAR_LEFT, impulse*impulseMult, pHandling->fCollisionDamageMultiplier))\n\t\t\t\t\tSetPanelDamage(CAR_WING_LR, VEHPANEL_REAR_LEFT);\n\t\t\t\tbreak;\n\t\t\tcase CAR_PIECE_WING_RR:\n\t\t\t\tGetComponentWorldPosition(CAR_WING_RR, pos);\n\t\t\t\tdmgDrawCarCollidingParticles(pos, impulse*damageMultiplier);\n\t\t\t\tif(Damage.ApplyDamage(COMPONENT_PANEL_REAR_RIGHT, impulse*impulseMult, pHandling->fCollisionDamageMultiplier))\n\t\t\t\t\tSetPanelDamage(CAR_WING_RR, VEHPANEL_REAR_RIGHT);\n\t\t\t\tbreak;\n\n\t\t\tcase CAR_PIECE_WHEEL_LF:\n\t\t\tcase CAR_PIECE_WHEEL_LR:\n\t\t\tcase CAR_PIECE_WHEEL_RF:\n\t\t\tcase CAR_PIECE_WHEEL_RR:\n\t\t\t\tbreak;\n\n\t\t\tcase CAR_PIECE_WINDSCREEN:\n\t\t\t\tif(Damage.ApplyDamage(COMPONENT_PANEL_WINDSCREEN, impulse*impulseMult, pHandling->fCollisionDamageMultiplier)){\n\t\t\t\t\tuint8 oldStatus = Damage.GetPanelStatus(VEHPANEL_WINDSCREEN);\n\t\t\t\t\tSetPanelDamage(CAR_WINDSCREEN, VEHPANEL_WINDSCREEN);\n\t\t\t\t\tif(oldStatus != Damage.GetPanelStatus(VEHPANEL_WINDSCREEN)){\n\t\t\t\t\t//\tDMAudio.PlayOneShot(m_audioEntityId, SOUND_CAR_WINDSHIELD_CRACK, 0.0f);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tfloat damage = (impulse-minImpulse)*pHandling->fCollisionDamageMultiplier*0.6f*damageMultiplier;\n\n\t\tif(GetModelIndex() == MI_SECURICA && m_pDamageEntity && m_pDamageEntity->GetStatus() == STATUS_PLAYER)\n\t\t\tdamage *= 7.0f;\n\n\t\tif(GetModelIndex() == MI_RCGOBLIN || GetModelIndex() == MI_RCRAIDER)\n\t\t\tdamage *= 30.0f;\n\n\t\tif(damage > 0.0f){\n\t\t\tif(damage > 5.0f &&\n\t\t\t   pDriver &&\n\t\t\t   m_pDamageEntity && m_pDamageEntity->IsVehicle() &&\n\t\t\t   (this != FindPlayerVehicle() || ((CVehicle*)m_pDamageEntity)->VehicleCreatedBy == MISSION_VEHICLE) &&\n\t\t\t   ((CVehicle*)m_pDamageEntity)->pDriver){\n\t\t\t\tif(GetVehicleAppearance() == VEHICLE_APPEARANCE_CAR)\n\t\t\t\t\tpDriver->Say(SOUND_PED_CRASH_CAR);\n\t\t\t\telse\n\t\t\t\t\tpDriver->Say(SOUND_PED_CRASH_VEHICLE);\n\t\t\t}\n\n\t\t\tint oldHealth = m_fHealth;\n\t\t\tif(this == FindPlayerVehicle())\n\t\t\t\tm_fHealth -= bTakeLessDamage ? damage/6.0f : damage/2.0f;\n\t\t\telse if(bTakeLessDamage)\n\t\t\t\tm_fHealth -= damage/12.0f;\n\t\t\telse if(m_pDamageEntity && m_pDamageEntity == FindPlayerVehicle())\n\t\t\t\tm_fHealth -= damage/1.5f;\n\t\t\telse\n\t\t\t\tm_fHealth -= damage/4.0f;\n\t\t\tif(m_fHealth <= 0.0f && oldHealth > 0)\n\t\t\t\tm_fHealth = 1.0f;\n\t\t}\n\n\t\t// play sound if a light broke\n\t\tfor(i = 0; i < 4; i++)\n\t\t\tif(oldLightStatus[i] != 1 && Damage.GetLightStatus((eLights)i) == 1){\n\t\t\t\tDMAudio.PlayOneShot(m_audioEntityId, SOUND_CAR_LIGHT_BREAK, i);\t// BUG? i?\n\t\t\t\tbreak;\n\t\t\t}\n\t}\n\n\tif(m_fHealth < 250.0f){\n\t\t// Car is on fire\n\t\tif(Damage.GetEngineStatus() < ENGINE_STATUS_ON_FIRE){\n\t\t\t// Set engine on fire and remember who did this\n\t\t\tDamage.SetEngineStatus(ENGINE_STATUS_ON_FIRE);\n\t\t\tm_fFireBlowUpTimer = 0.0f;\n\t\t\tm_pSetOnFireEntity = m_pDamageEntity;\n\t\t\tif(m_pSetOnFireEntity)\n\t\t\t\tm_pSetOnFireEntity->RegisterReference(&m_pSetOnFireEntity);\n\t\t}\n\t}else{\n\t\tif(GetModelIndex() == MI_BFINJECT){\n\t\t\tif(m_fHealth < 400.0f)\n\t\t\t\tDamage.SetEngineStatus(200);\n\t\t\telse if(m_fHealth < 600.0f)\n\t\t\t\tDamage.SetEngineStatus(100);\n\t\t}\n\t}\n}\n\nvoid\nCAutomobile::dmgDrawCarCollidingParticles(const CVector &pos, float amount)\n{\n\tint i, n;\n\n\tif(!GetIsOnScreen())\n\t\treturn;\n\n\t// FindPlayerSpeed() unused\n\n\tn = (int)amount/20;\n\n\tfor(i = 0; i < ((n+4)&0x1F); i++)\n\t\tCParticle::AddParticle(PARTICLE_SPARK_SMALL, pos,\n\t\t\tCVector(CGeneral::GetRandomNumberInRange(-0.1f, 0.1f),\n\t\t\t        CGeneral::GetRandomNumberInRange(-0.1f, 0.1f),\n\t\t\t        0.006f));\n\n\tfor(i = 0; i < n+2; i++)\n\t\tCParticle::AddParticle(PARTICLE_CARCOLLISION_DUST,\n\t\t\tCVector(CGeneral::GetRandomNumberInRange(-1.2f, 1.2f) + pos.x,\n\t\t\t        CGeneral::GetRandomNumberInRange(-1.2f, 1.2f) + pos.y,\n\t\t\t        pos.z),\n\t\t\tCVector(0.0f, 0.0f, 0.0f), nil, 0.5f);\n\n\tn = (int)amount/50 + 1;\n\tfor(i = 0; i < n; i++)\n\t\tCParticle::AddParticle(PARTICLE_CAR_DEBRIS, pos,\n\t\t\tCVector(CGeneral::GetRandomNumberInRange(-0.25f, 0.25f),\n\t\t\t        CGeneral::GetRandomNumberInRange(-0.25f, 0.25f),\n\t\t\t        CGeneral::GetRandomNumberInRange(0.1f, 0.25f)),\n\t\t\tnil,\n\t\t\tCGeneral::GetRandomNumberInRange(0.02f, 0.08f),\n\t\t\tCVehicleModelInfo::ms_vehicleColourTable[m_currentColour1],\n\t\t\tCGeneral::GetRandomNumberInRange(-40.0f, 40.0f),\n\t\t\t0,\n\t\t\tCGeneral::GetRandomNumberInRange(0.0f, 4.0f));\n}\n\nvoid\nCAutomobile::AddDamagedVehicleParticles(void)\n{\n\tint i, n;\n\n\tif(this == FindPlayerVehicle() && TheCamera.GetLookingForwardFirstPerson())\n\t\treturn;\n\tif(this != FindPlayerVehicle() && (CTimer::GetFrameCounter() + m_randomSeed) & 1)\n\t\treturn;\n\tif(m_fHealth >= 650.0f)\n\t\treturn;\n\n\tCVector direction = 0.85f*m_vecMoveSpeed;\n\tCVector damagePos = ((CVehicleModelInfo*)CModelInfo::GetModelInfo(GetModelIndex()))->m_positions[CAR_POS_HEADLIGHTS];\n\n\tswitch(Damage.GetDoorStatus(DOOR_BONNET)){\n\tcase DOOR_STATUS_OK:\n\tcase DOOR_STATUS_SMASHED:\n\t\t// Bonnet is still there, smoke comes out at the edge\n\t\tdamagePos += vecDAMAGE_ENGINE_POS_SMALL;\n\t\tbreak;\n\tcase DOOR_STATUS_SWINGING:\n\tcase DOOR_STATUS_MISSING:\n\t\t// Bonnet is gone, smoke comes out at the engine\n\t\tdamagePos += vecDAMAGE_ENGINE_POS_BIG;\n\t\tbreak;\n\t}\n\n\tif(GetModelIndex() == MI_BFINJECT)\n\t\tdamagePos = CVector(0.3f, -1.5f, -0.1f);\n\telse if(GetModelIndex() == MI_CADDY)\n\t\tdamagePos = CVector(0.6f, -1.0f, -0.25f);\n\telse if(IsRealHeli()){\n\t\tdamagePos.x = 0.4f*GetColModel()->boundingBox.max.x;\n\t\tdamagePos.y = 0.2f*GetColModel()->boundingBox.min.y;\n\t\tdamagePos.z = 0.3f*GetColModel()->boundingBox.max.z;\n\t}else\n\t\tdamagePos.z += 0.4f*(GetColModel()->boundingBox.max.z-damagePos.z) * DotProduct(GetForward(), m_vecMoveSpeed);\n\tdamagePos = GetMatrix()*damagePos;\n\tdamagePos.z += 0.15f;\n\n\tbool electric = pHandling->Transmission.nEngineType == 'E';\n\n\tif(electric && m_fHealth < 320.0f && m_fHealth > 1.0f){\n\t\tdirection = 0.85f*m_vecMoveSpeed;\n\t\tdirection += GetRight() * CGeneral::GetRandomNumberInRange(0.0f, 0.04f) * (1.0f - 2.0f*m_vecMoveSpeed.Magnitude());\n\t\tdirection.z += 0.001f;\n\t\tn = (CGeneral::GetRandomNumber() & 7) + 2;\n\t\tfor(i = 0; i < n; i++)\n\t\t\tCParticle::AddParticle(PARTICLE_SPARK_SMALL, damagePos, direction);\n\t\tif(((CTimer::GetFrameCounter() + m_randomSeed) & 7) == 0)\n\t\t\tCParticle::AddParticle(PARTICLE_ENGINE_SMOKE2, damagePos, 0.8f*m_vecMoveSpeed, nil, 0.1f, 0, 0, 0, 1000);\n\t}else if(electric && m_fHealth < 460.0f){\n\t\tdirection = 0.85f*m_vecMoveSpeed;\n\t\tdirection += GetRight() * CGeneral::GetRandomNumberInRange(0.0f, 0.04f) * (1.0f - 2.0f*m_vecMoveSpeed.Magnitude());\n\t\tdirection.z += 0.001f;\n\t\tn = (CGeneral::GetRandomNumber() & 3) + 2;\n\t\tfor(i = 0; i < n; i++)\n\t\t\tCParticle::AddParticle(PARTICLE_SPARK_SMALL, damagePos, direction);\n\t\tif(((CTimer::GetFrameCounter() + m_randomSeed) & 0xF) == 0)\n\t\t\tCParticle::AddParticle(PARTICLE_ENGINE_SMOKE, damagePos, 0.8f*m_vecMoveSpeed, nil, 0.1f, 0, 0, 0, 1000);\n\t}else if(m_fHealth < 250.0f){\n\t\t// nothing\n\t}else if(m_fHealth < 320.0f){\n\t\tCParticle::AddParticle(PARTICLE_ENGINE_SMOKE2, damagePos, 0.8f*direction);\n\t}else if(m_fHealth < 390.0f){\n\t\tCParticle::AddParticle(PARTICLE_ENGINE_STEAM, damagePos, 0.75f*direction);\n\t\tCParticle::AddParticle(PARTICLE_ENGINE_SMOKE, damagePos, 0.85f*direction);\n\t}else if(m_fHealth < 460.0f){\n\t\tint rnd = CTimer::GetFrameCounter() + m_randomSeed;\n\t\tif(rnd < 10 ||\n\t\t   rnd < 70 && rnd > 25 ||\n\t\t   rnd < 160 && rnd > 100 ||\n\t\t   rnd < 200 && rnd > 175 ||\n\t\t   rnd > 235)\n\t\t\treturn;\n\t\tdirection.z += 0.05f*Max(1.0f - 1.6f*m_vecMoveSpeed.Magnitude(), 0.0f);\n\t\tif(electric){\n\t\t\t// BUG. we had that case already\n\t\t\tdirection = 0.85f*m_vecMoveSpeed;\n\t\t\tdirection += GetRight() * CGeneral::GetRandomNumberInRange(0.0f, 0.04f) * (1.0f - 2.0f*m_vecMoveSpeed.Magnitude());\n\t\t\tdirection.z += 0.001f;\n\t\t\tn = (CGeneral::GetRandomNumber() & 2) + 2;\n\t\t\tfor(i = 0; i < n; i++)\n\t\t\t\tCParticle::AddParticle(PARTICLE_SPARK_SMALL, damagePos, direction);\n\t\t\tif(((CTimer::GetFrameCounter() + m_randomSeed) & 0xF) == 0)\n\t\t\t\tCParticle::AddParticle(PARTICLE_ENGINE_SMOKE, damagePos, 0.8f*m_vecMoveSpeed, nil, 0.1f, 0, 0, 0, 1000);\n\t\t}else{\n\t\t\tif(TheCamera.GetLookDirection() != LOOKING_FORWARD)\n\t\t\t\tCParticle::AddParticle(PARTICLE_ENGINE_STEAM, damagePos, 0.75f*direction);\n\t\t\telse if(((CTimer::GetFrameCounter() + m_randomSeed) & 1) == 0)\n\t\t\t\tCParticle::AddParticle(PARTICLE_ENGINE_STEAM, damagePos, 0.85f*m_vecMoveSpeed);\n\t\t}\n\t}else if(((CTimer::GetFrameCounter() + m_randomSeed) & 3) == 0 ||\n\t         ((CTimer::GetFrameCounter() + m_randomSeed) & 3) == 2){\n\t\tCParticle::AddParticle(PARTICLE_ENGINE_STEAM, damagePos, 0.9f*direction);\n\t}\n}\n\nint32\nCAutomobile::AddWheelDirtAndWater(CColPoint *colpoint, uint32 belowEffectSpeed)\n{\n\tint i;\n\tCVector dir;\n\tstatic RwRGBA grassCol = { 8, 24, 8, 255 };\n\tstatic RwRGBA gravelCol = { 64, 64, 64, 255 };\n\tstatic RwRGBA mudCol = { 64, 32, 16, 255 };\n\tstatic RwRGBA sandCol = { 170, 165, 140, 255 };\n\tstatic RwRGBA waterCol = { 48, 48, 64, 0 };\n\n\tif(!belowEffectSpeed &&\n\t   colpoint->surfaceB != SURFACE_SAND && colpoint->surfaceB != SURFACE_SAND_BEACH)\n\t\treturn 0;\n\n\tswitch(colpoint->surfaceB){\n\tcase SURFACE_GRASS:\n\t\tdir.x = -0.05f*m_vecMoveSpeed.x;\n\t\tdir.y = -0.05f*m_vecMoveSpeed.y;\n\t\tfor(i = 0; i < 4; i++){\n\t\t\tdir.z = CGeneral::GetRandomNumberInRange(0.03f, 0.06f);\n\t\t\tCParticle::AddParticle(PARTICLE_WHEEL_DIRT, colpoint->point, dir, nil,\n\t\t\t\tCGeneral::GetRandomNumberInRange(0.02f, 0.1f), grassCol);\n\t\t}\n\t\treturn 0;\n\tcase SURFACE_GRAVEL:\n\t\tdir.x = -0.05f*m_vecMoveSpeed.x;\n\t\tdir.y = -0.05f*m_vecMoveSpeed.y;\n\t\tfor(i = 0; i < 4; i++){\n\t\t\tdir.z = CGeneral::GetRandomNumberInRange(0.03f, 0.06f);\n\t\t\tCParticle::AddParticle(PARTICLE_WHEEL_DIRT, colpoint->point, dir, nil,\n\t\t\t\tCGeneral::GetRandomNumberInRange(0.05f, 0.09f), gravelCol);\n\t\t}\n\t\treturn 1;\n\tcase SURFACE_MUD_DRY:\n\t\tdir.x = -0.05f*m_vecMoveSpeed.x;\n\t\tdir.y = -0.05f*m_vecMoveSpeed.y;\n\t\tfor(i = 0; i < 4; i++){\n\t\t\tdir.z = CGeneral::GetRandomNumberInRange(0.03f, 0.06f);\n\t\t\tCParticle::AddParticle(PARTICLE_WHEEL_DIRT, colpoint->point, dir, nil,\n\t\t\t\tCGeneral::GetRandomNumberInRange(0.02f, 0.06f), mudCol);\n\t\t}\n\t\treturn 0;\n\tcase SURFACE_SAND:\n\tcase SURFACE_SAND_BEACH:\n\t\tif(CTimer::GetFrameCounter() & 2 ||\n\t\t   CGeneral::GetRandomNumberInRange(CWeather::WetRoads, 1.01f) > 0.5f)\n\t\t\treturn 0;\n\t\tdir.x = 0.5f*m_vecMoveSpeed.x;\n\t\tdir.y = 0.5f*m_vecMoveSpeed.y;\n\t\tfor(i = 0; i < 1; i++){\n\t\t\tdir.z = CGeneral::GetRandomNumberInRange(0.02f, 0.055f);\n\t\t\tCParticle::AddParticle(PARTICLE_SAND, colpoint->point, dir, nil,\n\t\t\t\t2.0f*m_vecMoveSpeed.Magnitude(), sandCol);\n\t\t}\n\t\treturn 0;\n\tdefault:\n\t\tif(CWeather::WetRoads > 0.01f){\n\t\t\tif(CTimer::GetFrameCounter() & 1)\n\t\t\t\tCParticle::AddParticle(\n\t\t\t\t\tPARTICLE_WATERSPRAY,\n\t\t\t\t\tcolpoint->point + CVector(0.0f, 0.0f, 0.25f+0.25f),\n\t\t\t\t\tCVector(0.0f, 0.0f, CGeneral::GetRandomNumberInRange(0.005f, 0.04f)),\n\t\t\t\t\tnil,\n\t\t\t\t\tCGeneral::GetRandomNumberInRange(0.1f, 0.5f), waterCol);\n\t\t\treturn 0;\n\t\t}\n\t\treturn 1;\n\t}\n}\n\nvoid\nCAutomobile::GetComponentWorldPosition(int32 component, CVector &pos)\n{\n\tif(m_aCarNodes[component] == nil){\n\t\tprintf(\"CarNode missing: %d %d\\n\", GetModelIndex(), component);\n\t\treturn;\n\t}\n\tRwMatrix *ltm = RwFrameGetLTM(m_aCarNodes[component]);\n\tpos = *RwMatrixGetPos(ltm);\n}\n\nbool\nCAutomobile::IsComponentPresent(int32 comp)\n{\n\treturn m_aCarNodes[comp] != nil;\n}\n\nvoid\nCAutomobile::SetComponentRotation(int32 component, CVector rotation)\n{\n\tCMatrix mat(RwFrameGetMatrix(m_aCarNodes[component]));\n\tCVector pos = mat.GetPosition();\n\t// BUG: all these set the whole matrix\n\tmat.SetRotateX(DEGTORAD(rotation.x));\n\tmat.SetRotateY(DEGTORAD(rotation.y));\n\tmat.SetRotateZ(DEGTORAD(rotation.z));\n\tmat.Translate(pos);\n\tmat.UpdateRW();\n}\n\nvoid\nCAutomobile::OpenDoor(int32 component, eDoors door, float openRatio)\n{\n\tCMatrix mat(RwFrameGetMatrix(m_aCarNodes[component]));\n\tCVector pos = mat.GetPosition();\n\tfloat axes[3] = { 0.0f, 0.0f, 0.0f };\n\tfloat wasClosed = false;\n\n\tif(Doors[door].IsClosed()){\n\t\t// enable angle cull for closed doors\n\t\tRwFrameForAllObjects(m_aCarNodes[component], CVehicleModelInfo::ClearAtomicFlagCB, (void*)ATOMIC_FLAG_NOCULL);\n\t\twasClosed = true;\n\t}\n\n\tDoors[door].Open(openRatio);\n\n\tif(wasClosed && Doors[door].RetAngleWhenClosed() != Doors[door].m_fAngle){\n\t\t// door opened\n\t\tHideAllComps();\n\t\t// turn off angle cull for swinging door\n\t\tRwFrameForAllObjects(m_aCarNodes[component], CVehicleModelInfo::SetAtomicFlagCB, (void*)ATOMIC_FLAG_NOCULL);\n\t\tDMAudio.PlayOneShot(m_audioEntityId, SOUND_CAR_DOOR_OPEN_BONNET + door, 0.0f);\n\t}\n\n\tif(!wasClosed && openRatio == 0.0f){\n\t\t// door closed\n\t\tif(Damage.GetDoorStatus(door) == DOOR_STATUS_SWINGING)\n\t\t\tDamage.SetDoorStatus(door, DOOR_STATUS_OK);\t// huh?\n\t\tShowAllComps();\n\t\tDMAudio.PlayOneShot(m_audioEntityId, SOUND_CAR_DOOR_CLOSE_BONNET + door, 0.0f);\n\t}\n\n\taxes[Doors[door].m_nAxis] = Doors[door].m_fAngle;\n\tmat.SetRotate(axes[0], axes[1], axes[2]);\n\tmat.Translate(pos);\n\tmat.UpdateRW();\n}\n\ninline void ProcessDoorOpenAnimation(CAutomobile *car, uint32 component, eDoors door, float time, float start, float end)\n{\n\tif(time > start && time < end){\n\t\tfloat ratio = (time - start)/(end - start);\n\t\tif(car->Doors[door].GetAngleOpenRatio() < ratio)\n\t\t\tcar->OpenDoor(component, door, ratio);\n\t}else if(time > end){\n\t\tcar->OpenDoor(component, door, 1.0f);\n\t}\n}\n\ninline void ProcessDoorCloseAnimation(CAutomobile *car, uint32 component, eDoors door, float time, float start, float end)\n{\n\tif(time > start && time < end){\n\t\tfloat ratio = 1.0f - (time - start)/(end - start);\n\t\tif(car->Doors[door].GetAngleOpenRatio() > ratio)\n\t\t\tcar->OpenDoor(component, door, ratio);\n\t}else if(time > end){\n\t\tcar->OpenDoor(component, door, 0.0f);\n\t}\n}\n\ninline void ProcessDoorOpenCloseAnimation(CAutomobile *car, uint32 component, eDoors door, float time, float start, float mid, float end)\n{\n\tif(time > start && time < mid){\n\t\t// open\n\t\tfloat ratio = (time - start)/(mid - start);\n\t\tif(car->Doors[door].GetAngleOpenRatio() < ratio)\n\t\t\tcar->OpenDoor(component, door, ratio);\n\t}else if(time > mid && time < end){\n\t\t// close\n\t\tfloat ratio = 1.0f - (time - mid)/(end - mid);\n\t\tif(car->Doors[door].GetAngleOpenRatio() > ratio)\n\t\t\tcar->OpenDoor(component, door, ratio);\n\t}else if(time > end){\n\t\tcar->OpenDoor(component, door, 0.0f);\n\t}\n}\n\nvoid\nCAutomobile::ProcessOpenDoor(uint32 component, uint32 anim, float time)\n{\n\teDoors door;\n\n\tswitch(component){\n\tcase CAR_DOOR_RF: door = DOOR_FRONT_RIGHT; break;\n\tcase CAR_DOOR_RR: door = DOOR_REAR_RIGHT; break;\n\tcase CAR_DOOR_LF: door = DOOR_FRONT_LEFT; break;\n\tcase CAR_DOOR_LR: door = DOOR_REAR_LEFT; break;\n\tdefault: assert(0);\n\t}\n\n\tif(IsDoorMissing(door))\n\t\treturn;\n\n\tswitch(anim){\n\tcase ANIM_STD_QUICKJACK:\n\tcase ANIM_STD_CAR_OPEN_DOOR_LHS:\n\tcase ANIM_STD_CAR_OPEN_DOOR_RHS:\n\t\tProcessDoorOpenAnimation(this, component, door, time, 0.41f, 0.89f);\n\t\tbreak;\n\tcase ANIM_STD_CAR_CLOSE_DOOR_LHS:\n\tcase ANIM_STD_CAR_CLOSE_DOOR_LO_LHS:\n\tcase ANIM_STD_CAR_CLOSE_DOOR_RHS:\n\tcase ANIM_STD_CAR_CLOSE_DOOR_LO_RHS:\n\t\tProcessDoorCloseAnimation(this, component, door, time, 0.2f, 0.45f);\n\t\tbreak;\n\tcase ANIM_STD_CAR_CLOSE_DOOR_ROLLING_LHS:\n\tcase ANIM_STD_CAR_CLOSE_DOOR_ROLLING_LO_LHS:\n\t\tProcessDoorOpenCloseAnimation(this, component, door, time, 0.1f, 0.6f, 0.95f);\n\t\tbreak;\n\tcase ANIM_STD_GETOUT_LHS:\n\tcase ANIM_STD_GETOUT_LO_LHS:\n\tcase ANIM_STD_GETOUT_RHS:\n\tcase ANIM_STD_GETOUT_LO_RHS:\n\t\tProcessDoorOpenAnimation(this, component, door, time, 0.06f, 0.43f);\n\t\tbreak;\n\tcase ANIM_STD_CAR_CLOSE_LHS:\n\tcase ANIM_STD_CAR_CLOSE_RHS:\n\t\tProcessDoorCloseAnimation(this, component, door, time, 0.1f, 0.23f);\n\t\tbreak;\n\tcase ANIM_STD_CAR_PULL_OUT_PED_RHS:\n\tcase ANIM_STD_CAR_PULL_OUT_PED_LO_RHS:\n\t\tOpenDoor(component, door, 1.0f);\n\t\tbreak;\n\tcase ANIM_STD_COACH_OPEN_LHS:\n\tcase ANIM_STD_COACH_OPEN_RHS:\n\t\tProcessDoorOpenAnimation(this, component, door, time, 0.66f, 0.8f);\n\t\tbreak;\n\tcase ANIM_STD_COACH_GET_OUT_LHS:\n\t\tProcessDoorOpenAnimation(this, component, door, time, 0.0f, 0.3f);\n\t\tbreak;\n\tcase ANIM_STD_VAN_OPEN_DOOR_REAR_LHS:\n\tcase ANIM_STD_VAN_OPEN_DOOR_REAR_RHS:\n\t\tProcessDoorOpenAnimation(this, component, door, time, 0.37f, 0.55f);\n\t\tbreak;\n\tcase ANIM_STD_VAN_CLOSE_DOOR_REAR_LHS:\n\tcase ANIM_STD_VAN_CLOSE_DOOR_REAR_RHS:\n\t\tProcessDoorCloseAnimation(this, component, door, time, 0.5f, 0.8f);\n\t\tbreak;\n\tcase ANIM_STD_VAN_GET_OUT_REAR_LHS:\n\tcase ANIM_STD_VAN_GET_OUT_REAR_RHS:\n\t\tProcessDoorOpenAnimation(this, component, door, time, 0.5f, 0.6f);\n\t\tbreak;\n\tcase ANIM_STD_NUM:\n\t\tOpenDoor(component, door, time);\n\t\tbreak;\n\t}\n}\n\nbool\nCAutomobile::IsDoorReady(eDoors door)\n{\n\tif(Doors[door].IsClosed() || IsDoorMissing(door))\n\t\treturn true;\n\tint doorflag = 0;\n\tswitch(door){\n\tcase DOOR_FRONT_LEFT: doorflag = CAR_DOOR_FLAG_LF; break;\n\tcase DOOR_FRONT_RIGHT: doorflag = CAR_DOOR_FLAG_RF; break;\n\tcase DOOR_REAR_LEFT: doorflag = CAR_DOOR_FLAG_LR; break;\n\tcase DOOR_REAR_RIGHT: doorflag = CAR_DOOR_FLAG_RR; break;\n\tdefault: break;\n\t}\n\treturn (doorflag & m_nGettingInFlags) == 0;\n}\n\nbool\nCAutomobile::IsDoorFullyOpen(eDoors door)\n{\n\treturn Doors[door].IsFullyOpen() || IsDoorMissing(door);\n}\n\nbool\nCAutomobile::IsDoorClosed(eDoors door)\n{\n\treturn !!Doors[door].IsClosed();\n}\n\nbool\nCAutomobile::IsDoorMissing(eDoors door)\n{\n\treturn Damage.GetDoorStatus(door) == DOOR_STATUS_MISSING;\n}\n\nbool\nCAutomobile::IsDoorReady(uint32 door)\n{\n\tswitch(door){\n\tcase CAR_DOOR_RF: return IsDoorReady(DOOR_FRONT_RIGHT);\n\tcase CAR_DOOR_RR: return IsDoorReady(DOOR_REAR_RIGHT);\n\tcase CAR_DOOR_LF: return IsDoorReady(DOOR_FRONT_LEFT);\n\tcase CAR_DOOR_LR: return IsDoorReady(DOOR_REAR_LEFT);\n\tdefault:\n\t\treturn false;\n\t}\n}\n\nbool\nCAutomobile::IsDoorMissing(uint32 door)\n{\n\tswitch(door){\n\tcase CAR_DOOR_RF: return IsDoorMissing(DOOR_FRONT_RIGHT);\n\tcase CAR_DOOR_RR: return IsDoorMissing(DOOR_REAR_RIGHT);\n\tcase CAR_DOOR_LF: return IsDoorMissing(DOOR_FRONT_LEFT);\n\tcase CAR_DOOR_LR: return IsDoorMissing(DOOR_REAR_LEFT);\n\tdefault:\n\t\treturn false;\n\t}\n}\n\nbool\nCAutomobile::IsOpenTopCar(void)\n{\n\treturn GetModelIndex() == MI_STINGER ||\n\t\t// component 0 is assumed to be a roof\n\t\tGetModelIndex() == MI_COMET && m_aExtras[0] != 0 && m_aExtras[1] != 0 ||\n\t\tGetModelIndex() == MI_STALLION && m_aExtras[0] != 0 && m_aExtras[1] != 0;\n}\n\nvoid\nCAutomobile::RemoveRefsToVehicle(CEntity *ent)\n{\n\tint i;\n\tfor(i = 0; i < 4; i++)\n\t\tif(m_aGroundPhysical[i] == ent)\n\t\t\tm_aGroundPhysical[i] = nil;\n}\n\nvoid\nCAutomobile::BlowUpCar(CEntity *culprit)\n{\n\tRpAtomic *atomic;\n\n\tif(!bCanBeDamaged)\n\t\treturn;\n\n\tif(culprit == FindPlayerPed() || culprit == FindPlayerVehicle()){\n\t\tCWorld::Players[CWorld::PlayerInFocus].m_nHavocLevel += 20;\n\t\tCWorld::Players[CWorld::PlayerInFocus].m_fMediaAttention += 10.0f;\n\t\tCStats::PropertyDestroyed += CGeneral::GetRandomNumber()%6000 + 4000;\n\t}\n\n\t// explosion pushes vehicle up\n\tm_vecMoveSpeed.z += 0.13f;\n\tSetStatus(STATUS_WRECKED);\n\tbRenderScorched = true;\n\tm_nTimeOfDeath = CTimer::GetTimeInMilliseconds();\n\tDamage.FuckCarCompletely();\n\n\tif(GetModelIndex() != MI_RCBANDIT){\n\t\tSetBumperDamage(CAR_BUMP_FRONT, VEHBUMPER_FRONT);\n\t\tSetBumperDamage(CAR_BUMP_REAR, VEHBUMPER_REAR);\n\t\tSetDoorDamage(CAR_BONNET, DOOR_BONNET);\n\t\tSetDoorDamage(CAR_BOOT, DOOR_BOOT);\n\t\tSetDoorDamage(CAR_DOOR_LF, DOOR_FRONT_LEFT);\n\t\tSetDoorDamage(CAR_DOOR_RF, DOOR_FRONT_RIGHT);\n\t\tSetDoorDamage(CAR_DOOR_LR, DOOR_REAR_LEFT);\n\t\tSetDoorDamage(CAR_DOOR_RR, DOOR_REAR_RIGHT);\n\t\tSpawnFlyingComponent(CAR_WHEEL_LF, COMPGROUP_WHEEL);\n\t\tatomic = nil;\n\t\tRwFrameForAllObjects(m_aCarNodes[CAR_WHEEL_LF], GetCurrentAtomicObjectCB, &atomic);\n\t\tif(atomic)\n\t\t\tRpAtomicSetFlags(atomic, 0);\n\t}\n\n\tm_fHealth = 0.0f;\n\tm_nBombTimer = 0;\n\tm_bombType = CARBOMB_NONE;\n\n\tTheCamera.CamShake(0.7f, GetPosition().x, GetPosition().y, GetPosition().z);\n\n\tKillPedsInVehicle();\n\n\tbEngineOn = false;\n\tbLightsOn = false;\n\tm_bSirenOrAlarm = false;\n\tbTaxiLight = false;\n\tif(bIsAmbulanceOnDuty){\n\t\tbIsAmbulanceOnDuty = false;\n\t\tCCarCtrl::NumAmbulancesOnDuty--;\n\t}\n\tif(bIsFireTruckOnDuty){\n\t\tbIsFireTruckOnDuty = false;\n\t\tCCarCtrl::NumFiretrucksOnDuty--;\n\t}\n\tChangeLawEnforcerState(false);\n\n\tgFireManager.StartFire(this, culprit, 0.8f, true);\n\tCDarkel::RegisterCarBlownUpByPlayer(this);\n\tif(GetModelIndex() == MI_RCBANDIT)\n\t\tCExplosion::AddExplosion(this, culprit, EXPLOSION_CAR_QUICK, GetPosition(), 0);\n\telse\n\t\tCExplosion::AddExplosion(this, culprit, EXPLOSION_CAR, GetPosition(), 0);\n}\n\nbool\nCAutomobile::SetUpWheelColModel(CColModel *colModel)\n{\n\tCVehicleModelInfo *mi = (CVehicleModelInfo*)CModelInfo::GetModelInfo(GetModelIndex());\n\tCColModel *vehColModel = mi->GetColModel();\n\n\tif(GetVehicleAppearance() == VEHICLE_APPEARANCE_HELI ||\n\t   GetVehicleAppearance() == VEHICLE_APPEARANCE_PLANE)\n\t\treturn false;\n\n\tcolModel->boundingSphere = vehColModel->boundingSphere;\n\tcolModel->boundingBox = vehColModel->boundingBox;\n\n\tCMatrix mat;\n\tmat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_LF]));\n\tcolModel->spheres[0].Set(mi->m_wheelScale / 2, mat.GetPosition(), SURFACE_RUBBER, CAR_PIECE_WHEEL_LF);\n\tmat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_LB]));\n\tcolModel->spheres[1].Set(mi->m_wheelScale / 2, mat.GetPosition(), SURFACE_RUBBER, CAR_PIECE_WHEEL_LR);\n\tmat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_RF]));\n\tcolModel->spheres[2].Set(mi->m_wheelScale / 2, mat.GetPosition(), SURFACE_RUBBER, CAR_PIECE_WHEEL_RF);\n\tmat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_RB]));\n\tcolModel->spheres[3].Set(mi->m_wheelScale / 2, mat.GetPosition(), SURFACE_RUBBER, CAR_PIECE_WHEEL_RR);\n\n\tif(m_aCarNodes[CAR_WHEEL_LM] != nil && m_aCarNodes[CAR_WHEEL_RM] != nil){\n\t\tmat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_LM]));\n\t\tcolModel->spheres[4].Set(mi->m_wheelScale / 2, mat.GetPosition(), SURFACE_RUBBER, CAR_PIECE_WHEEL_LR);\n\t\tmat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_RM]));\n\t\tcolModel->spheres[5].Set(mi->m_wheelScale / 2, mat.GetPosition(), SURFACE_RUBBER, CAR_PIECE_WHEEL_RR);\n\t\tcolModel->numSpheres = 6;\n\t}else\n\t\tcolModel->numSpheres = 4;\n\n\treturn true;\n}\n\nvoid\nCAutomobile::BurstTyre(uint8 wheel, bool applyForces)\n{\n\tif(GetModelIndex() == MI_RHINO || bTyresDontBurst)\n\t\treturn;\n\n\tswitch(wheel){\n\tcase CAR_PIECE_WHEEL_LF: wheel = CARWHEEL_FRONT_LEFT; break;\n\tcase CAR_PIECE_WHEEL_RF: wheel = CARWHEEL_FRONT_RIGHT; break;\n\tcase CAR_PIECE_WHEEL_LR: wheel = CARWHEEL_REAR_LEFT; break;\n\tcase CAR_PIECE_WHEEL_RR: wheel = CARWHEEL_REAR_RIGHT; break;\n\t}\n\n\tint status = Damage.GetWheelStatus(wheel);\n\tif(status == WHEEL_STATUS_OK){\n\t\tDamage.SetWheelStatus(wheel, WHEEL_STATUS_BURST);\n\t\tCStats::TyresPopped++;\n\t\tDMAudio.PlayOneShot(m_audioEntityId, SOUND_CAR_TYRE_POP, 0.0f);\n\n\t\tif(GetStatus() == STATUS_SIMPLE){\n\t\t\tSetStatus(STATUS_PHYSICS);\n\t\t\tCCarCtrl::SwitchVehicleToRealPhysics(this);\n\t\t}\n\n\t\tif(applyForces){\n\t\t\tApplyMoveForce(GetRight() * m_fMass * CGeneral::GetRandomNumberInRange(-0.03f, 0.03f));\n\t\t\tApplyTurnForce(GetRight() * m_fTurnMass * CGeneral::GetRandomNumberInRange(-0.03f, 0.03f), GetForward());\n\t\t}\n\t}\n}\n\nbool\nCAutomobile::IsRoomForPedToLeaveCar(uint32 component, CVector *doorOffset)\n{\n\tCColPoint colpoint;\n\tCEntity *ent;\n\tcolpoint.point = CVector(0.0f, 0.0f, 0.0f);\n\tCVehicleModelInfo *mi = (CVehicleModelInfo*)CModelInfo::GetModelInfo(GetModelIndex());\n\n\tCVector seatPos;\n\tswitch(component){\n\tcase CAR_DOOR_RF:\n\t\tseatPos = mi->GetFrontSeatPosn();\n\t\tbreak;\n\tcase CAR_DOOR_LF:\n\t\tseatPos = mi->GetFrontSeatPosn();\n\t\tseatPos.x = -seatPos.x;\n\t\tbreak;\n\tcase CAR_DOOR_RR:\n\t\tseatPos = mi->m_positions[CAR_POS_BACKSEAT];\n\t\tbreak;\n\tcase CAR_DOOR_LR:\n\t\tseatPos = mi->m_positions[CAR_POS_BACKSEAT];\n\t\tseatPos.x = -seatPos.x;\n\t\tbreak;\n\t}\n\tseatPos = GetMatrix() * seatPos;\n\n\tCVector doorPos = CPed::GetPositionToOpenCarDoor(this, component);\n\tif(doorOffset){\n\t\tCVector off = *doorOffset;\n\t\tif(component == CAR_DOOR_RF || component == CAR_DOOR_RR)\n\t\t\toff.x = -off.x;\n\t\tdoorPos += Multiply3x3(GetMatrix(), off);\n\t}\n\n\tif(GetUp().z < 0.0f){\n\t\tseatPos.z += 0.5f;\n\t\tdoorPos.z += 0.5f;\n\t}\n\n\tCVector dist = doorPos - seatPos;\n\n\t// Removing that makes thiProcessEntityCollisions func. return false for van doors.\n\tdoorPos.z += 0.5f;\n\tfloat length = dist.Magnitude();\n\tCVector pedPos = seatPos + dist*((length+0.6f)/length);\n\n\tif(!CWorld::GetIsLineOfSightClear(seatPos, pedPos, true, false, false, true, false, false))\n\t\treturn false;\n\tif(CWorld::TestSphereAgainstWorld(doorPos, 0.6f, this, true, true, false, true, false, false))\n\t\treturn false;\n\tif(CWorld::ProcessVerticalLine(doorPos, 1000.0f, colpoint, ent, true, false, false, true, false, false, nil))\n\t\tif(colpoint.point.z > doorPos.z && colpoint.point.z < doorPos.z + 0.6f)\n\t\t\treturn false;\n\tfloat upperZ = colpoint.point.z;\n\tif(!CWorld::ProcessVerticalLine(doorPos, -1000.0f, colpoint, ent, true, false, false, true, false, false, nil))\n\t\treturn false;\n\tif(upperZ != 0.0f && upperZ < colpoint.point.z)\n\t\treturn false;\n\treturn true;\n}\n\nfloat\nCAutomobile::GetHeightAboveRoad(void)\n{\n\treturn m_fHeightAboveRoad;\n}\n\nvoid\nCAutomobile::PlayCarHorn(void)\n{\n\tint r;\n\n\tif (IsAlarmOn() || m_nCarHornTimer != 0)\n\t\treturn;\n\n\tif (m_nCarHornDelay) {\n\t\tm_nCarHornDelay--;\n\t\treturn;\n\t}\n\n\tm_nCarHornDelay = (CGeneral::GetRandomNumber() & 0x7F) + 150;\n\tr = m_nCarHornDelay & 7;\n\tif(r < 2){\n\t\tm_nCarHornTimer = 45;\n\t}else if(r < 4){\n\t\tif(pDriver)\n\t\t\tpDriver->Say(SOUND_PED_ANNOYED_DRIVER);\n\t\tm_nCarHornTimer = 45;\n\t}else{\n\t\tif(pDriver)\n\t\t\tpDriver->Say(SOUND_PED_ANNOYED_DRIVER);\n\t}\n}\n\nvoid\nCAutomobile::PlayHornIfNecessary(void)\n{\n\tif(AutoPilot.m_bSlowedDownBecauseOfPeds ||\n\t   AutoPilot.m_bSlowedDownBecauseOfCars)\n\t\tif(!HasCarStoppedBecauseOfLight())\n\t\t\tPlayCarHorn();\n}\n\nvoid\nCAutomobile::ResetSuspension(void)\n{\n\tint i;\n\tfor(i = 0; i < 4; i++){\n\t\tm_aSuspensionSpringRatio[i] = 1.0f;\n\t\tm_aWheelTimer[i] = 0.0f;\n\t\tm_aWheelRotation[i] = 0.0f;\n\t\tm_aWheelState[i] = WHEEL_STATE_NORMAL;\n\t}\n}\n\nvoid\nCAutomobile::SetupSuspensionLines(void)\n{\n\tint i;\n\tCVector posn;\n\tCVehicleModelInfo *mi = (CVehicleModelInfo*)CModelInfo::GetModelInfo(GetModelIndex());\n\tCColModel *colModel = mi->GetColModel();\n\n\t// Each suspension line starts at the uppermost wheel position\n\t// and extends down to the lowermost point on the tyre\n\tfor(i = 0; i < 4; i++){\n\t\tmi->GetWheelPosn(i, posn);\n\t\tm_aWheelPosition[i] = posn.z;\n\n\t\t// uppermost wheel position\n\t\tposn.z += pHandling->fSuspensionUpperLimit;\n\t\tcolModel->lines[i].p0 = posn;\n\n\t\t// lowermost wheel position\n\t\tposn.z += pHandling->fSuspensionLowerLimit - pHandling->fSuspensionUpperLimit;\n\t\t// lowest point on tyre\n\t\tposn.z -= mi->m_wheelScale*0.5f;\n\t\tcolModel->lines[i].p1 = posn;\n\n\t\t// this is length of the spring at rest\n\t\tm_aSuspensionSpringLength[i] = pHandling->fSuspensionUpperLimit - pHandling->fSuspensionLowerLimit;\n\t\tm_aSuspensionLineLength[i] = colModel->lines[i].p0.z - colModel->lines[i].p1.z;\n\t}\n\n\t// Compress spring somewhat to get normal height on road\n\tm_fHeightAboveRoad = m_aSuspensionSpringLength[0]*(1.0f - 1.0f/(4.0f*pHandling->fSuspensionForceLevel))\n\t\t\t- colModel->lines[0].p0.z + mi->m_wheelScale*0.5f;\n\tfor(i = 0; i < 4; i++)\n\t\tm_aWheelPosition[i] = mi->m_wheelScale*0.5f - m_fHeightAboveRoad;\n\n\t// adjust col model to include suspension lines\n\tif(colModel->boundingBox.min.z > colModel->lines[0].p1.z)\n\t\tcolModel->boundingBox.min.z = colModel->lines[0].p1.z;\n\tfloat radius = Max(colModel->boundingBox.min.Magnitude(), colModel->boundingBox.max.Magnitude());\n\tif(colModel->boundingSphere.radius < radius)\n\t\tcolModel->boundingSphere.radius = radius;\n\n\tif(GetModelIndex() == MI_RCBANDIT){\n\t\tcolModel->boundingSphere.radius = 2.0f;\n\t\tfor(i = 0; i < colModel->numSpheres; i++)\n\t\t\tcolModel->spheres[i].radius = 0.3f;\n\t}\n}\n\n// called on police cars\nvoid\nCAutomobile::ScanForCrimes(void)\n{\n\tif(FindPlayerVehicle() && FindPlayerVehicle()->IsCar())\n\t\tif(FindPlayerVehicle()->IsAlarmOn())\n\t\t\t// if player's alarm is on, increase wanted level\n\t\t\tif((FindPlayerVehicle()->GetPosition() - GetPosition()).MagnitudeSqr() < sq(20.0f))\n\t\t\t\tCWorld::Players[CWorld::PlayerInFocus].m_pPed->SetWantedLevelNoDrop(1);\n}\n\nvoid\nCAutomobile::BlowUpCarsInPath(void)\n{\n\tint i;\n\n\tif(m_vecMoveSpeed.Magnitude() > 0.1f && bTankDetonateCars)\n\t\tfor(i = 0; i < m_nCollisionRecords; i++)\n\t\t\tif(m_aCollisionRecords[i] &&\n\t\t\t   m_aCollisionRecords[i]->IsVehicle() &&\n\t\t\t   m_aCollisionRecords[i]->GetModelIndex() != MI_RHINO &&\n\t\t\t   !m_aCollisionRecords[i]->bRenderScorched){\n\t\t\t\tif(this == FindPlayerVehicle())\n\t\t\t\t\tCEventList::RegisterEvent(EVENT_EXPLOSION, EVENT_ENTITY_VEHICLE, m_aCollisionRecords[i], FindPlayerPed(), 2000);\n\t\t\t\t((CVehicle*)m_aCollisionRecords[i])->BlowUpCar(this);\n\t\t\t}\n}\n\nbool\nCAutomobile::HasCarStoppedBecauseOfLight(void)\n{\n\tint i;\n\n\tif(GetStatus() != STATUS_SIMPLE && GetStatus() != STATUS_PHYSICS)\n\t\treturn false;\n\n\tif(AutoPilot.m_nCurrentRouteNode && AutoPilot.m_nNextRouteNode){\n\t\tCPathNode *curnode = &ThePaths.m_pathNodes[AutoPilot.m_nCurrentRouteNode];\n\t\tfor(i = 0; i < curnode->numLinks; i++)\n\t\t\tif(ThePaths.ConnectedNode(curnode->firstLink + i) == AutoPilot.m_nNextRouteNode)\n\t\t\t\tbreak;\n\t\tif(i < curnode->numLinks &&\n\t\t   ThePaths.m_carPathLinks[ThePaths.m_carPathConnections[curnode->firstLink + i]].trafficLightType & 3)\n\t\t\treturn true;\n\t}\n\n\tif(AutoPilot.m_nCurrentRouteNode && AutoPilot.m_nPrevRouteNode){\n\t\tCPathNode *curnode = &ThePaths.m_pathNodes[AutoPilot.m_nCurrentRouteNode];\n\t\tfor(i = 0; i < curnode->numLinks; i++)\n\t\t\tif(ThePaths.ConnectedNode(curnode->firstLink + i) == AutoPilot.m_nPrevRouteNode)\n\t\t\t\tbreak;\n\t\tif(i < curnode->numLinks &&\n\t\t   ThePaths.m_carPathLinks[ThePaths.m_carPathConnections[curnode->firstLink + i]].trafficLightType & 3)\n\t\t\treturn true;\n\t}\n\n\treturn false;\n}\n\nvoid\nCPed::DeadPedMakesTyresBloody(void)\n{\n\tint minX = CWorld::GetSectorIndexX(GetPosition().x - 2.0f);\n\tif (minX < 0) minX = 0;\n\tint minY = CWorld::GetSectorIndexY(GetPosition().y - 2.0f);\n\tif (minY < 0) minY = 0;\n\tint maxX = CWorld::GetSectorIndexX(GetPosition().x + 2.0f);\n\tif (maxX > NUMSECTORS_X-1) maxX = NUMSECTORS_X-1;\n\tint maxY = CWorld::GetSectorIndexY(GetPosition().y + 2.0f);\n\tif (maxY > NUMSECTORS_Y-1) maxY = NUMSECTORS_Y-1;\n\n\tCWorld::AdvanceCurrentScanCode();\n\n\tfor (int curY = minY; curY <= maxY; curY++) {\n\t\tfor (int curX = minX; curX <= maxX; curX++) {\n\t\t\tCSector *sector = CWorld::GetSector(curX, curY);\n\t\t\tMakeTyresMuddySectorList(sector->m_lists[ENTITYLIST_VEHICLES]);\n\t\t\tMakeTyresMuddySectorList(sector->m_lists[ENTITYLIST_VEHICLES_OVERLAP]);\n\t\t}\n\t}\n}\n\nvoid\nCPed::MakeTyresMuddySectorList(CPtrList &list)\n{\n\tCAutomobile *car = nil;\n\tCBike *bike = nil;\n\tfor (CPtrNode *node = list.first; node; node = node->next) {\n\t\tCVehicle *veh = (CVehicle*)node->item;\n\t\tif (veh->m_scanCode != CWorld::GetCurrentScanCode()) {\n\t\t\tveh->m_scanCode = CWorld::GetCurrentScanCode();\n\n\t\t\tif (Abs(GetPosition().x - veh->GetPosition().x) < 10.0f && Abs(GetPosition().y - veh->GetPosition().y) < 10.0f) {\t\t\t\t\n\t\t\t\tif (veh->IsCar()) {\n\t\t\t\t\tbike = nil;\n\t\t\t\t\tcar = (CAutomobile*)veh;\n\t\t\t\t} else if (veh->IsBike()) {\n\t\t\t\t\tbike = (CBike*)veh;\n\t\t\t\t\tcar = nil;\n\t\t\t\t}\n\t\t\t\tif (veh->m_vecMoveSpeed.MagnitudeSqr2D() > 0.05f) {\n\t\t\t\t\tif (car) {\n\t\t\t\t\t\tfor (int wheel = 0; wheel < 4; wheel++) {\n\t\t\t\t\t\t\tif (!car->m_aWheelSkidmarkBloody[wheel] && car->m_aSuspensionSpringRatio[wheel] < 1.0f) {\n\n\t\t\t\t\t\t\t\tCColModel* vehCol = car->GetModelInfo()->GetColModel();\n\t\t\t\t\t\t\t\tCVector approxWheelOffset;\n\t\t\t\t\t\t\t\tswitch (wheel) {\n\t\t\t\t\t\t\t\tcase 0:\n\t\t\t\t\t\t\t\t\tapproxWheelOffset = CVector(-vehCol->boundingBox.max.x, vehCol->boundingBox.max.y, 0.0f);\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase 1:\n\t\t\t\t\t\t\t\t\tapproxWheelOffset = CVector(-vehCol->boundingBox.max.x, vehCol->boundingBox.min.y, 0.0f);\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase 2:\n\t\t\t\t\t\t\t\t\tapproxWheelOffset = CVector(vehCol->boundingBox.max.x, vehCol->boundingBox.max.y, 0.0f);\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase 3:\n\t\t\t\t\t\t\t\t\tapproxWheelOffset = CVector(vehCol->boundingBox.max.x, vehCol->boundingBox.min.y, 0.0f);\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// I hope so\n\t\t\t\t\t\t\t\tCVector wheelPos = car->GetMatrix() * approxWheelOffset;\n\t\t\t\t\t\t\t\tif (Abs(wheelPos.z - GetPosition().z) < 2.0f) {\n\n\t\t\t\t\t\t\t\t\tif ((wheelPos - GetPosition()).MagnitudeSqr2D() < 1.0f) {\n\t\t\t\t\t\t\t\t\t\tif (CGame::nastyGame) {\n\t\t\t\t\t\t\t\t\t\t\tcar->m_aWheelSkidmarkBloody[wheel] = true;\n\t\t\t\t\t\t\t\t\t\t\tDMAudio.PlayOneShot(car->m_audioEntityId, SOUND_SPLATTER, 0.0f);\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\tif (car->m_fMass > 500.f) {\n\t\t\t\t\t\t\t\t\t\t\tcar->ApplyMoveForce(CVector(0.0f, 0.0f, 50.0f * Min(1.0f, m_fMass * 0.001f)));\n\n\t\t\t\t\t\t\t\t\t\t\tCVector vehAndWheelDist = wheelPos - car->GetPosition();\n\t\t\t\t\t\t\t\t\t\t\tcar->ApplyTurnForce(CVector(0.0f, 0.0f, 50.0f * Min(1.0f, m_fTurnMass * 0.0005f)), vehAndWheelDist);\n\t\t\t\t\t\t\t\t\t\t\tif (car == FindPlayerVehicle()) {\n\t\t\t\t\t\t\t\t\t\t\t\tCPad::GetPad(0)->StartShake(300, 70);\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (bike) {\n\t\t\t\t\t\tfor (int wheel = 0; wheel < 2; wheel++) {\n\t\t\t\t\t\t\tif (!bike->m_aWheelSkidmarkBloody[wheel] && bike->m_aSuspensionSpringRatio[wheel] < 1.0f) {\n\n\t\t\t\t\t\t\t\tCColModel* vehCol = bike->GetModelInfo()->GetColModel();\n\t\t\t\t\t\t\t\tCVector approxWheelOffset;\n\t\t\t\t\t\t\t\tswitch (wheel) {\n\t\t\t\t\t\t\t\tcase 0:\n\t\t\t\t\t\t\t\t\tapproxWheelOffset = CVector(0.0f, 0.8f * vehCol->boundingBox.max.y, 0.0f);\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase 1:\n\t\t\t\t\t\t\t\t\tapproxWheelOffset = CVector(0.0f, 0.8f * vehCol->boundingBox.min.y, 0.0f);\n\t\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// I hope so\n\t\t\t\t\t\t\t\tCVector wheelPos = bike->GetMatrix() * approxWheelOffset;\n\t\t\t\t\t\t\t\tif (Abs(wheelPos.z - GetPosition().z) < 2.0f) {\n\n\t\t\t\t\t\t\t\t\tif ((wheelPos - GetPosition()).MagnitudeSqr2D() < 1.0f) {\n\t\t\t\t\t\t\t\t\t\tif (CGame::nastyGame) {\n\t\t\t\t\t\t\t\t\t\t\tbike->m_aWheelSkidmarkBloody[wheel] = true;\n\t\t\t\t\t\t\t\t\t\t\tDMAudio.PlayOneShot(bike->m_audioEntityId, SOUND_SPLATTER, 0.0f);\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\tif (bike->m_fMass > 100.0f) {\n\t\t\t\t\t\t\t\t\t\t\tbike->ApplyMoveForce(CVector(0.0f, 0.0f, 10.0f));\n\n\t\t\t\t\t\t\t\t\t\t\tCVector vehAndWheelDist = wheelPos - bike->GetPosition();\n\t\t\t\t\t\t\t\t\t\t\tbike->ApplyTurnForce(CVector(0.0f, 0.0f, 10.0f), vehAndWheelDist);\n\n\t\t\t\t\t\t\t\t\t\t\tif (bike == FindPlayerVehicle()) {\n\t\t\t\t\t\t\t\t\t\t\t\tCPad::GetPad(0)->StartShake(300, 70);\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nCAutomobile::SetBusDoorTimer(uint32 timer, uint8 type)\n{\n\tif(timer < 1000)\n\t\ttimer = 1000;\n\tif(type == 0)\n\t\t// open and close\n\t\tm_nBusDoorTimerStart = CTimer::GetTimeInMilliseconds();\n\telse\n\t\t// only close\n\t\tm_nBusDoorTimerStart = CTimer::GetTimeInMilliseconds() - 500;\n\tm_nBusDoorTimerEnd = m_nBusDoorTimerStart + timer;\n}\n\nvoid\nCAutomobile::ProcessAutoBusDoors(void)\n{\n\tif(CTimer::GetTimeInMilliseconds() < m_nBusDoorTimerEnd){\n\t\tif(m_nBusDoorTimerEnd != 0 && CTimer::GetTimeInMilliseconds() > m_nBusDoorTimerEnd-500){\n\t\t\t// close door\n\t\t\tif(!IsDoorMissing(DOOR_FRONT_LEFT) && (m_nGettingInFlags & CAR_DOOR_FLAG_LF) == 0){\n\t\t\t\tif(IsDoorClosed(DOOR_FRONT_LEFT)){\n\t\t\t\t\tm_nBusDoorTimerEnd = CTimer::GetTimeInMilliseconds();\n\t\t\t\t\tOpenDoor(CAR_DOOR_LF, DOOR_FRONT_LEFT, 0.0f);\n\t\t\t\t}else{\n\t\t\t\t\tOpenDoor(CAR_DOOR_LF, DOOR_FRONT_LEFT,\n\t\t\t\t\t\t1.0f - (CTimer::GetTimeInMilliseconds() - (m_nBusDoorTimerEnd-500))/500.0f);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif(!IsDoorMissing(DOOR_FRONT_RIGHT) && (m_nGettingInFlags & CAR_DOOR_FLAG_RF) == 0){\n\t\t\t\tif(IsDoorClosed(DOOR_FRONT_RIGHT)){\n\t\t\t\t\tm_nBusDoorTimerEnd = CTimer::GetTimeInMilliseconds();\n\t\t\t\t\tOpenDoor(CAR_DOOR_RF, DOOR_FRONT_RIGHT, 0.0f);\n\t\t\t\t}else{\n\t\t\t\t\tOpenDoor(CAR_DOOR_RF, DOOR_FRONT_RIGHT,\n\t\t\t\t\t\t1.0f - (CTimer::GetTimeInMilliseconds() - (m_nBusDoorTimerEnd-500))/500.0f);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}else{\n\t\t// ended\n\t\tif(m_nBusDoorTimerStart){\n\t\t\tif(!IsDoorMissing(DOOR_FRONT_LEFT) && (m_nGettingInFlags & CAR_DOOR_FLAG_LF) == 0)\n\t\t\t\tOpenDoor(CAR_DOOR_LF, DOOR_FRONT_LEFT, 0.0f);\n\t\t\tif(!IsDoorMissing(DOOR_FRONT_RIGHT) && (m_nGettingInFlags & CAR_DOOR_FLAG_RF) == 0)\n\t\t\t\tOpenDoor(CAR_DOOR_RF, DOOR_FRONT_RIGHT, 0.0f);\n\t\t\tm_nBusDoorTimerStart = 0;\n\t\t\tm_nBusDoorTimerEnd = 0;\n\t\t}\n\t}\n}\n\nvoid\nCAutomobile::ProcessSwingingDoor(int32 component, eDoors door)\n{\n\tif(Damage.GetDoorStatus(door) != DOOR_STATUS_SWINGING)\n\t\treturn;\n\n\tif (m_aCarNodes[component] == nil)\n\t\treturn;\n\n\tCMatrix mat(RwFrameGetMatrix(m_aCarNodes[component]));\n\tCVector pos = mat.GetPosition();\n\tfloat axes[3] = { 0.0f, 0.0f, 0.0f };\n\n\tDoors[door].Process(this);\n\taxes[Doors[door].m_nAxis] = Doors[door].m_fAngle;\n\tmat.SetRotate(axes[0], axes[1], axes[2]);\n\tmat.Translate(pos);\n\tmat.UpdateRW();\n\n\t// make wind rip off bonnet\n\tif(door == DOOR_BONNET && Doors[door].m_nDoorState == DOORST_OPEN &&\n\t   DotProduct(m_vecMoveSpeed, GetForward()) > 0.4f){\n#ifdef FIX_BUGS\n\t\tCObject *comp = SpawnFlyingComponent(CAR_BONNET, COMPGROUP_BONNET);\n#else\n\t\tCObject *comp = SpawnFlyingComponent(CAR_BONNET, COMPGROUP_DOOR);\n#endif\n\t\t// make both doors invisible on car\n\t\tSetComponentVisibility(m_aCarNodes[CAR_BONNET], ATOMIC_FLAG_NONE);\n\t\tDamage.SetDoorStatus(DOOR_BONNET, DOOR_STATUS_MISSING);\n\n\t\tif(comp){\n\t\t\tif(CGeneral::GetRandomNumber() & 1)\n\t\t\t\tcomp->m_vecMoveSpeed = 0.4f*m_vecMoveSpeed + 0.1f*GetRight() + 0.5f*GetUp();\n\t\t\telse\n\t\t\t\tcomp->m_vecMoveSpeed = 0.4f*m_vecMoveSpeed - 0.1f*GetRight() + 0.5f*GetUp();\n\t\t\tcomp->ApplyTurnForce(10.0f*GetUp(), GetForward());\n\t\t}\n\t}\n}\n\nvoid\nCAutomobile::Fix(void)\n{\n\tint component;\n\n\tDamage.ResetDamageStatus();\n\n\tif(pHandling->Flags & HANDLING_NO_DOORS){\n\t\tDamage.SetDoorStatus(DOOR_FRONT_LEFT, DOOR_STATUS_MISSING);\n\t\tDamage.SetDoorStatus(DOOR_FRONT_RIGHT, DOOR_STATUS_MISSING);\n\t\tDamage.SetDoorStatus(DOOR_REAR_LEFT, DOOR_STATUS_MISSING);\n\t\tDamage.SetDoorStatus(DOOR_REAR_RIGHT, DOOR_STATUS_MISSING);\n\t}\n\n\tbIsDamaged = false;\n\tRpClumpForAllAtomics((RpClump*)m_rwObject, CVehicleModelInfo::HideAllComponentsAtomicCB, (void*)ATOMIC_FLAG_DAM);\n\n\tfor(component = CAR_BUMP_FRONT; component < NUM_CAR_NODES; component++){\n\t\tif(m_aCarNodes[component]){\n\t\t\tCMatrix mat(RwFrameGetMatrix(m_aCarNodes[component]));\n\t\t\tmat.SetTranslate(mat.GetPosition());\n\t\t\tmat.UpdateRW();\n\t\t}\n\t}\n\n\tfor(component = 0; component < 4; component++)\n\t\tDamage.SetWheelStatus(component, WHEEL_STATUS_OK);\n\n\tif(GetModelIndex() == MI_HUNTER){\n\t\tRpAtomicSetFlags((RpAtomic*)GetFirstObject(m_aCarNodes[CAR_WHEEL_LB]), 0);\n\t\tRpAtomicSetFlags((RpAtomic*)GetFirstObject(m_aCarNodes[CAR_WHEEL_RB]), 0);\n\t}else if(IsRealHeli()){\n\t\tRpAtomicSetFlags((RpAtomic*)GetFirstObject(m_aCarNodes[CAR_WHEEL_LF]), 0);\n\t\tRpAtomicSetFlags((RpAtomic*)GetFirstObject(m_aCarNodes[CAR_WHEEL_RF]), 0);\n\t\tRpAtomicSetFlags((RpAtomic*)GetFirstObject(m_aCarNodes[CAR_WHEEL_LB]), 0);\n\t\tRpAtomicSetFlags((RpAtomic*)GetFirstObject(m_aCarNodes[CAR_WHEEL_RB]), 0);\n\t}\n}\n\nvoid\nCAutomobile::SetupDamageAfterLoad(void)\n{\n\tif(m_aCarNodes[CAR_BUMP_FRONT])\n\t\tSetBumperDamage(CAR_BUMP_FRONT, VEHBUMPER_FRONT);\n\tif(m_aCarNodes[CAR_BONNET])\n\t\tSetDoorDamage(CAR_BONNET, DOOR_BONNET);\n\tif(m_aCarNodes[CAR_BUMP_REAR])\n\t\tSetBumperDamage(CAR_BUMP_REAR, VEHBUMPER_REAR);\n\tif(m_aCarNodes[CAR_BOOT])\n\t\tSetDoorDamage(CAR_BOOT, DOOR_BOOT);\n\tif(m_aCarNodes[CAR_DOOR_LF])\n\t\tSetDoorDamage(CAR_DOOR_LF, DOOR_FRONT_LEFT);\n\tif(m_aCarNodes[CAR_DOOR_RF])\n\t\tSetDoorDamage(CAR_DOOR_RF, DOOR_FRONT_RIGHT);\n\tif(m_aCarNodes[CAR_DOOR_LR])\n\t\tSetDoorDamage(CAR_DOOR_LR, DOOR_REAR_LEFT);\n\tif(m_aCarNodes[CAR_DOOR_RR])\n\t\tSetDoorDamage(CAR_DOOR_RR, DOOR_REAR_RIGHT);\n\tif(m_aCarNodes[CAR_WING_LF])\n\t\tSetPanelDamage(CAR_WING_LF, VEHPANEL_FRONT_LEFT);\n\tif(m_aCarNodes[CAR_WING_RF])\n\t\tSetPanelDamage(CAR_WING_RF, VEHPANEL_FRONT_RIGHT);\n\tif(m_aCarNodes[CAR_WING_LR])\n\t\tSetPanelDamage(CAR_WING_LR, VEHPANEL_REAR_LEFT);\n\tif(m_aCarNodes[CAR_WING_RR])\n\t\tSetPanelDamage(CAR_WING_RR, VEHPANEL_REAR_RIGHT);\n}\n\nRwObject*\nGetCurrentAtomicObjectCB(RwObject *object, void *data)\n{\n\tRpAtomic *atomic = (RpAtomic*)object;\n\tassert(RwObjectGetType(object) == rpATOMIC);\n\tif(RpAtomicGetFlags(atomic) & rpATOMICRENDER)\n\t\t*(RpAtomic**)data = atomic;\n\treturn object;\n}\n\nCObject*\nCAutomobile::SpawnFlyingComponent(int32 component, uint32 type)\n{\n\tRpAtomic *atomic;\n\tRwFrame *frame;\n\tRwMatrix *matrix;\n\tCObject *obj;\n\n\tif(CObject::nNoTempObjects >= NUMTEMPOBJECTS)\n\t\treturn nil;\n\n\tatomic = nil;\n\tRwFrameForAllObjects(m_aCarNodes[component], GetCurrentAtomicObjectCB, &atomic);\n\tif(atomic == nil)\n\t\treturn nil;\n\n\tobj = new CObject();\n\tif(obj == nil)\n\t\treturn nil;\n\n\tif(component == CAR_WINDSCREEN){\n\t\tobj->SetModelIndexNoCreate(MI_CAR_BONNET);\n\t}else switch(type){\n\tcase COMPGROUP_BUMPER:\n\t\tobj->SetModelIndexNoCreate(MI_CAR_BUMPER);\n\t\tbreak;\n\tcase COMPGROUP_WHEEL:\n\t\tobj->SetModelIndexNoCreate(MI_CAR_WHEEL);\n\t\tbreak;\n\tcase COMPGROUP_DOOR:\n\t\tobj->SetModelIndexNoCreate(MI_CAR_DOOR);\n\t\tobj->SetCenterOfMass(0.0f, -0.5f, 0.0f);\n\t\tobj->bDrawLast = true;\n\t\tbreak;\n\tcase COMPGROUP_BONNET:\n\t\tobj->SetModelIndexNoCreate(MI_CAR_BONNET);\n\t\tobj->SetCenterOfMass(0.0f, 0.4f, 0.0f);\n\t\tbreak;\n\tcase COMPGROUP_BOOT:\n\t\tobj->SetModelIndexNoCreate(MI_CAR_BOOT);\n\t\tobj->SetCenterOfMass(0.0f, -0.3f, 0.0f);\n\t\tbreak;\n\tcase COMPGROUP_PANEL:\n\tdefault:\n\t\tobj->SetModelIndexNoCreate(MI_CAR_PANEL);\n\t\tbreak;\n\t}\n\n\t// object needs base model\n\tobj->RefModelInfo(GetModelIndex());\n\n\t// create new atomic\n\tmatrix = RwFrameGetLTM(m_aCarNodes[component]);\n\tframe = RwFrameCreate();\n\tatomic = RpAtomicClone(atomic);\n\t*RwFrameGetMatrix(frame) = *matrix;\n\tRpAtomicSetFrame(atomic, frame);\n\tCVisibilityPlugins::SetAtomicRenderCallback(atomic, nil);\n\tobj->AttachToRwObject((RwObject*)atomic);\n\tobj->bDontStream = true;\n\n\t// init object\n\tobj->m_fMass = 10.0f;\n\tobj->m_fTurnMass = 25.0f;\n\tobj->m_fAirResistance = 0.97f;\n\tobj->m_fElasticity = 0.1f;\n\tobj->m_fBuoyancy = obj->m_fMass*GRAVITY/0.75f;\n\tobj->ObjectCreatedBy = TEMP_OBJECT;\n\tobj->SetIsStatic(false);\n\tobj->bIsPickup = false;\n\tobj->bUseVehicleColours = true;\n\tobj->m_colour1 = m_currentColour1;\n\tobj->m_colour2 = m_currentColour2;\n\n\t// life time - the more objects the are, the shorter this one will live\n\tCObject::nNoTempObjects++;\n\tif(CObject::nNoTempObjects > 20)\n\t\tobj->m_nEndOfLifeTime = CTimer::GetTimeInMilliseconds() + 20000/5.0f;\n\telse if(CObject::nNoTempObjects > 10)\n\t\tobj->m_nEndOfLifeTime = CTimer::GetTimeInMilliseconds() + 20000/2.0f;\n\telse\n\t\tobj->m_nEndOfLifeTime = CTimer::GetTimeInMilliseconds() + 20000;\n\n\tobj->m_vecMoveSpeed = m_vecMoveSpeed;\n\tif(obj->m_vecMoveSpeed.z > 0.0f){\n\t\tobj->m_vecMoveSpeed.z *= 1.5f;\n\t}else if(GetUp().z > 0.0f &&\n\t         (component == COMPGROUP_BONNET || component == COMPGROUP_BOOT || component == CAR_WINDSCREEN)){\n\t\tobj->m_vecMoveSpeed.z *= -1.5f;\n\t\tobj->m_vecMoveSpeed.z += 0.04f;\n\t}else{\n\t\tobj->m_vecMoveSpeed.z *= 0.25f;\n\t}\n\tobj->m_vecMoveSpeed.x *= 0.75f;\n\tobj->m_vecMoveSpeed.y *= 0.75f;\n\n\tobj->m_vecTurnSpeed = m_vecTurnSpeed*2.0f;\n\n\t// push component away from car\n\tCVector dist = obj->GetPosition() - GetPosition();\n\tdist.Normalise();\n\tif(component == COMPGROUP_BONNET || component == COMPGROUP_BOOT || component == CAR_WINDSCREEN){\n\t\t// push these up some\n\t\tdist += GetUp();\n\t\tif(GetUp().z > 0.0f){\n\t\t\t// simulate fast upward movement if going fast\n\t\t\tfloat speed = CVector2D(m_vecMoveSpeed).Magnitude();\n\t\t\tobj->GetMatrix().Translate(GetUp()*speed);\n\t\t}\n\t}\n\tobj->ApplyMoveForce(dist);\n\n\tif(type == COMPGROUP_WHEEL){\n\t\tobj->m_fTurnMass = 5.0f;\n\t\tobj->m_vecTurnSpeed.x = 0.5f;\n\t\tobj->m_fAirResistance = 0.99f;\n\t}\n\n\tif(GetStatus() == STATUS_WRECKED && IsVisible() && DotProduct(dist, TheCamera.GetPosition() - GetPosition()) > -0.5f){\n\t\tdist = TheCamera.GetPosition() - GetPosition();\n\t\tdist.Normalise();\n\t\tdist.z += 0.3f;\n\t\tApplyMoveForce(5.0f*dist);\n\t}\n\n\tif(CCollision::ProcessColModels(obj->GetMatrix(), *obj->GetColModel(),\n\t\t\tthis->GetMatrix(), *this->GetColModel(),\n\t\t\tCWorld::m_aTempColPts, nil, nil) > 0)\n\t\tobj->m_pCollidingEntity = this;\n\n\tif(bRenderScorched)\n\t\tobj->bRenderScorched = true;\n\n\tCWorld::Add(obj);\n\n\treturn obj;\n}\n\nCObject*\nCAutomobile::RemoveBonnetInPedCollision(void)\n{\n\tCObject *obj;\n\n\tif(Damage.GetDoorStatus(DOOR_BONNET) == DOOR_STATUS_SWINGING &&\n\t   Doors[DOOR_BONNET].RetAngleWhenOpen()*0.4f < Doors[DOOR_BONNET].m_fAngle){\n#ifdef FIX_BUGS\n\t\tobj = SpawnFlyingComponent(CAR_BONNET, COMPGROUP_BONNET);\n#else\n\t\tobj = SpawnFlyingComponent(CAR_BONNET, COMPGROUP_DOOR);\n#endif\n\t\t// make both doors invisible on car\n\t\tSetComponentVisibility(m_aCarNodes[CAR_BONNET], ATOMIC_FLAG_NONE);\n\t\tDamage.SetDoorStatus(DOOR_BONNET, DOOR_STATUS_MISSING);\n\t\treturn obj;\n\t}\n\treturn nil;\n}\n\nvoid\nCAutomobile::SetPanelDamage(int32 component, ePanels panel, bool noFlyingComponents)\n{\n\tint status = Damage.GetPanelStatus(panel);\n\tif(m_aCarNodes[component] == nil)\n\t\treturn;\n\tif(status == PANEL_STATUS_SMASHED1){\n\t\tDMAudio.PlayOneShot(m_audioEntityId, SOUND_CAR_WINDSHIELD_CRACK, 0.0f);\n\t\t// show damaged part\n\t\tSetComponentVisibility(m_aCarNodes[component], ATOMIC_FLAG_DAM);\n\t}else if(status == PANEL_STATUS_MISSING){\n\t\tif(!noFlyingComponents)\n\t\t\tSpawnFlyingComponent(component, COMPGROUP_PANEL);\n\t\telse\n\t\t\tCGlass::CarWindscreenShatters(this, false);\n\t\t// hide both\n\t\tSetComponentVisibility(m_aCarNodes[component], ATOMIC_FLAG_NONE);\n\t}\n}\n\nvoid\nCAutomobile::SetBumperDamage(int32 component, ePanels panel, bool noFlyingComponents)\n{\n\tint status = Damage.GetPanelStatus(panel);\n\tif(m_aCarNodes[component] == nil){\n\t\tprintf(\"Trying to damage component %d of %s\\n\",\n\t\t\tcomponent, CModelInfo::GetModelInfo(GetModelIndex())->GetModelName());\n\t\treturn;\n\t}\n\tif(status == PANEL_STATUS_SMASHED1){\n\t\t// show damaged part\n\t\tSetComponentVisibility(m_aCarNodes[component], ATOMIC_FLAG_DAM);\n\t}else if(status == PANEL_STATUS_MISSING){\n\t\tif(!noFlyingComponents)\n\t\t\tSpawnFlyingComponent(component, COMPGROUP_BUMPER);\n\t\t// hide both\n\t\tSetComponentVisibility(m_aCarNodes[component], ATOMIC_FLAG_NONE);\n\t}\n}\n\nvoid\nCAutomobile::SetDoorDamage(int32 component, eDoors door, bool noFlyingComponents)\n{\n\tint status = Damage.GetDoorStatus(door);\n\tif(m_aCarNodes[component] == nil){\n\t\tprintf(\"Trying to damage component %d of %s\\n\",\n\t\t\tcomponent, CModelInfo::GetModelInfo(GetModelIndex())->GetModelName());\n\t\treturn;\n\t}\n\n\tif(!CanDoorsBeDamaged() && status > DOOR_STATUS_SMASHED && door != DOOR_BONNET && door != DOOR_BOOT){\n\t\tDamage.SetDoorStatus(door, DOOR_STATUS_SMASHED);\n\t\tstatus = DOOR_STATUS_SMASHED;\n\t}\n\n\tif(door == DOOR_BOOT && status == DOOR_STATUS_SWINGING && pHandling->Flags & HANDLING_NOSWING_BOOT){\n\t\tDamage.SetDoorStatus(DOOR_BOOT, DOOR_STATUS_MISSING);\n\t\tstatus = DOOR_STATUS_MISSING;\n\t}\n\n\tswitch(status){\n\tcase DOOR_STATUS_SMASHED:\n\t\t// show damaged part\n\t\tSetComponentVisibility(m_aCarNodes[component], ATOMIC_FLAG_DAM);\n\t\tbreak;\n\tcase DOOR_STATUS_SWINGING:\n\t\t// turn off angle cull for swinging doors\n\t\tRwFrameForAllObjects(m_aCarNodes[component], CVehicleModelInfo::SetAtomicFlagCB, (void*)ATOMIC_FLAG_NOCULL);\n\t\tbreak;\n\tcase DOOR_STATUS_MISSING:\n\t\tif(!noFlyingComponents){\n\t\t\tif(door == DOOR_BONNET)\n\t\t\t\tSpawnFlyingComponent(component, COMPGROUP_BONNET);\n\t\t\telse if(door == DOOR_BOOT)\n\t\t\t\tSpawnFlyingComponent(component, COMPGROUP_BOOT);\n\t\t\telse\n\t\t\t\tSpawnFlyingComponent(component, COMPGROUP_DOOR);\n\t\t}\n\t\t// hide both\n\t\tSetComponentVisibility(m_aCarNodes[component], ATOMIC_FLAG_NONE);\n\t\tbreak;\n\t}\n}\n\n\nstatic RwObject*\nSetVehicleAtomicVisibilityCB(RwObject *object, void *data)\n{\n\tuint32 flags = (uint32)(uintptr)data;\n\tRpAtomic *atomic = (RpAtomic*)object;\n\tif((CVisibilityPlugins::GetAtomicId(atomic) & (ATOMIC_FLAG_OK|ATOMIC_FLAG_DAM)) == flags)\n\t\tRpAtomicSetFlags(atomic, rpATOMICRENDER);\n\telse\n\t\tRpAtomicSetFlags(atomic, 0);\n\treturn object;\n}\n\nvoid\nCAutomobile::SetComponentVisibility(RwFrame *frame, uint32 flags)\n{\n\tHideAllComps();\n\tbIsDamaged = true;\n\tRwFrameForAllObjects(frame, SetVehicleAtomicVisibilityCB, (void*)flags);\n}\n\nvoid\nCAutomobile::SetupModelNodes(void)\n{\n\tint i;\n\tfor(i = 0; i < NUM_CAR_NODES; i++)\n\t\tm_aCarNodes[i] = nil;\n\tCClumpModelInfo::FillFrameArray(GetClump(), m_aCarNodes);\n}\n\nvoid\nCAutomobile::SetTaxiLight(bool light)\n{\n\tbTaxiLight = light;\n}\n\nbool\nCAutomobile::GetAllWheelsOffGround(void)\n{\n\treturn m_nDriveWheelsOnGround == 0;\n}\n\nvoid\nCAutomobile::HideAllComps(void)\n{\n\t// empty\n}\n\nvoid\nCAutomobile::ShowAllComps(void)\n{\n\t// empty\n}\n\nvoid\nCAutomobile::ReduceHornCounter(void)\n{\n\tif(m_nCarHornTimer != 0)\n\t\tm_nCarHornTimer--;\n}\n\nvoid\nCAutomobile::SetAllTaxiLights(bool set)\n{\n\tm_sAllTaxiLights = set;\n}\n\nvoid\nCAutomobile::TellHeliToGoToCoors(float x, float y, float z, uint8 speed)\n{\n\tAutoPilot.m_nCarMission = MISSION_HELI_FLYTOCOORS;\n\tAutoPilot.m_vecDestinationCoors.x = x;\n\tAutoPilot.m_vecDestinationCoors.y = y;\n\tAutoPilot.m_vecDestinationCoors.z = z;\n\tAutoPilot.m_nCruiseSpeed = speed;\n\tSetStatus(STATUS_PHYSICS);\n\n\tif(m_fOrientation == 0.0f){\n\t\tm_fOrientation = CGeneral::GetATanOfXY(GetForward().x, GetForward().y) + PI;\n\t\twhile(m_fOrientation > TWOPI) m_fOrientation -= TWOPI;\n\t}\n}\n\nvoid\nCAutomobile::TellPlaneToGoToCoors(float x, float y, float z, uint8 speed)\n{\n\tAutoPilot.m_nCarMission = MISSION_PLANE_FLYTOCOORS;\n\tAutoPilot.m_vecDestinationCoors.x = x;\n\tAutoPilot.m_vecDestinationCoors.y = y;\n\tAutoPilot.m_vecDestinationCoors.z = z;\n\tAutoPilot.m_nCruiseSpeed = speed;\n\tSetStatus(STATUS_PHYSICS);\n\n\tif(m_fOrientation == 0.0f)\n\t\tm_fOrientation = CGeneral::GetATanOfXY(GetForward().x, GetForward().y);\n}\n\nvoid\nCAutomobile::PopBoot(void)\n{\n\tswitch(Damage.GetDoorStatus(DOOR_BOOT)){\n\tcase DOOR_STATUS_OK:\n\tcase DOOR_STATUS_SMASHED:\n\t\tDoors[DOOR_BOOT].m_fAngle = Doors[DOOR_BOOT].m_fMinAngle;\n\t\tCMatrix mat(RwFrameGetMatrix(m_aCarNodes[CAR_BOOT]));\n\t\tCVector pos = mat.GetPosition();\n\t\tfloat axes[3] = { 0.0f, 0.0f, 0.0f };\n\t\taxes[Doors[DOOR_BOOT].m_nAxis] = Doors[DOOR_BOOT].m_fAngle;\n\t\tmat.SetRotate(axes[0], axes[1], axes[2]);\n\t\tmat.Translate(pos);\n\t\tmat.UpdateRW();\n\t}\n}\n\nvoid\nCAutomobile::PopBootUsingPhysics(void)\n{\n\tswitch(Damage.GetDoorStatus(DOOR_BOOT))\n\tcase DOOR_STATUS_OK:\n\tcase DOOR_STATUS_SMASHED:\n\t\tDamage.SetDoorStatus(DOOR_BOOT, DOOR_STATUS_SWINGING);\n\tDoors[DOOR_BOOT].m_fAngVel = -2.0f;\n}\n\nvoid\nCAutomobile::CloseAllDoors(void)\n{\n\tCVehicleModelInfo *mi = (CVehicleModelInfo*)CModelInfo::GetModelInfo(GetModelIndex());\n\tif(!IsDoorMissing(DOOR_FRONT_LEFT))\n\t\tOpenDoor(CAR_DOOR_LF, DOOR_FRONT_LEFT, 0.0f);\n\tif(mi->m_numDoors > 1){\n\t\tif(!IsDoorMissing(DOOR_FRONT_RIGHT))\n\t\t\tOpenDoor(CAR_DOOR_RF, DOOR_FRONT_RIGHT, 0.0f);\n\t\tif(mi->m_numDoors > 2){\n\t\t\tif(!IsDoorMissing(DOOR_REAR_LEFT))\n\t\t\t\tOpenDoor(CAR_DOOR_LR, DOOR_REAR_LEFT, 0.0f);\n\t\t\tif(!IsDoorMissing(DOOR_REAR_RIGHT))\n\t\t\t\tOpenDoor(CAR_DOOR_RR, DOOR_REAR_RIGHT, 0.0f);\n\t\t}\n\t}\n}\n\nvoid\nCAutomobile::KnockPedOutCar(eWeaponType weapon, uint16 door, CPed *ped)\n{\n\tAnimationId anim = ANIM_STD_KO_FRONT;\n\tif(ped == nil)\n\t\treturn;\n\n\tped->m_vehDoor = door;\n\tped->SetPedState(PED_IDLE);\n\tCAnimManager::BlendAnimation(ped->GetClump(), ped->m_animGroup, ANIM_STD_IDLE, 100.0f);\n\tCPed::PedSetOutCarCB(nil, ped);\n\tped->SetMoveState(PEDMOVE_STILL);\n\tif(GetUp().z < 0.0f)\n\t\tped->SetHeading(CGeneral::LimitRadianAngle(GetForward().Heading() + PI));\n\telse\n\t\tped->SetHeading(GetForward().Heading());\n\n\tswitch(weapon){\n\tcase WEAPONTYPE_UNARMED:\n\tcase WEAPONTYPE_UNIDENTIFIED:\n\t\tped->m_vecMoveSpeed = m_vecMoveSpeed;\n\t\tped->m_pCollidingEntity = this;\n\t\tanim = ANIM_STD_NUM;\n\t\tbreak;\n\n\tcase WEAPONTYPE_BASEBALLBAT:\n\tcase WEAPONTYPE_RAMMEDBYCAR:\n\tcase WEAPONTYPE_FALL:\n\t\tped->m_vecMoveSpeed = m_vecMoveSpeed;\n\t\tanim = ANIM_STD_SPINFORWARD_LEFT;\n\t\tApplyMoveForce(4.0f*GetUp() + 8.0f*GetRight());\n\t\tbreak;\n\t}\n\n\tif(weapon != WEAPONTYPE_UNARMED){\n\t\tped->SetFall(1000, anim, 0);\n\t\tped->bIsStanding = false;\n\t\tped->m_headingRate = 0.0f;\n\t}\n\tped->m_pMyVehicle = nil;\n}\n\n#ifdef COMPATIBLE_SAVES\nvoid\nCAutomobile::Save(uint8*& buf)\n{\n\tCVehicle::Save(buf);\n\tWriteSaveBuf<CDamageManager>(buf, Damage);\n\tSkipSaveBuf(buf, 1500 - 672 - sizeof(CDamageManager));\n}\n\nvoid\nCAutomobile::Load(uint8*& buf)\n{\n\tCVehicle::Load(buf);\n\tDamage = ReadSaveBuf<CDamageManager>(buf);\n\tSkipSaveBuf(buf, 1500 - 672 - sizeof(CDamageManager));\n\tSetupDamageAfterLoad();\n}\n#endif\n"
  },
  {
    "path": "src/vehicles/Automobile.h",
    "content": "#pragma once\n\n#include \"Vehicle.h\"\n#include \"DamageManager.h\"\n#include \"Door.h\"\n#include \"Skidmarks.h\"\n\nclass CObject;\n\nenum {\n\tCARWHEEL_FRONT_LEFT,\n\tCARWHEEL_REAR_LEFT,\n\tCARWHEEL_FRONT_RIGHT,\n\tCARWHEEL_REAR_RIGHT\n};\n\n\nclass CAutomobile : public CVehicle\n{\npublic:\n\tCDamageManager Damage;\n\tCDoor Doors[6];\n\tRwFrame *m_aCarNodes[NUM_CAR_NODES];\n\tCColPoint m_aWheelColPoints[4];\n\tfloat m_aSuspensionSpringRatio[4];\n\tfloat m_aSuspensionSpringRatioPrev[4];\n\tfloat m_aWheelTimer[4];\t\t// set to 4.0 when wheel is touching ground, then decremented\n\tfloat m_auto_unused1;\n\teSkidmarkType m_aWheelSkidmarkType[4];\n\tbool m_aWheelSkidmarkBloody[4];\n\tbool m_aWheelSkidmarkUnk[4];\n\tfloat m_aWheelRotation[4];\n\tfloat m_aWheelPosition[4];\n\tfloat m_aWheelSpeed[4];\n\tuint8 m_auto_unused2;\n#if (defined GTA_PS2 && !defined FIX_BUGS)\n\tuint8 m_bombType : 3;\n#endif\n\tuint8 bTaxiLight : 1;\n\tuint8 bFixedColour : 1;\n\tuint8 bBigWheels : 1;\n\tuint8 bWaterTight : 1;\t// no damage for non-player peds\n\tuint8 bNotDamagedUpsideDown : 1;\n\tuint8 bMoreResistantToDamage : 1;\n\tuint8 bTankDetonateCars : 1;\n\tuint8 bStuckInSand : 1;\n\tuint8 bHeliDestroyed : 1;\n#if (defined GTA_PS2 && !defined FIX_BUGS)\n\tCEntity* m_pBombRigger;\n#endif\n\tint16 m_doingBurnout;\n\tuint16 m_hydraulicState;\n\tuint32 m_nBusDoorTimerEnd;\n\tuint32 m_nBusDoorTimerStart;\n\tfloat m_aSuspensionSpringLength[4];\n\tfloat m_aSuspensionLineLength[4];\n\tfloat m_fHeightAboveRoad;\n\tfloat m_fTraction;\n\tfloat m_fTireTemperature;\n\tfloat m_fOrientation;\t// for heli and plane go-to\n\tfloat m_fPlaneSteer;\t// related to the above\n\tfloat m_fVelocityChangeForAudio;\n\tfloat m_randomValues[6];\t// used for what?\n\tfloat m_fFireBlowUpTimer;\n\tCPhysical *m_aGroundPhysical[4];\t// physicals touching wheels\n\tCVector m_aGroundOffset[4];\t\t// from ground object to colpoint\n\tCEntity *m_pSetOnFireEntity;\n\tfloat m_weaponDoorTimerLeft;\t// still don't know what exactly this is\n\tfloat m_weaponDoorTimerRight;\n\tfloat m_fCarGunLR;\n\tfloat m_fCarGunUD;\n\tfloat m_fHeliOrientation;\n\tfloat m_fPropellerRotation;\n\tuint8 stuff4[4];\n\tuint8 m_nWheelsOnGround;\n\tuint8 m_nDriveWheelsOnGround;\n\tuint8 m_nDriveWheelsOnGroundPrev;\n\tfloat m_fGasPedalAudio;\n\ttWheelState m_aWheelState[4];\n\n\tstatic bool m_sAllTaxiLights;\n\n\tCAutomobile(int32 id, uint8 CreatedBy);\n\n\t// from CEntity\n\tvoid SetModelIndex(uint32 id);\n\tvoid ProcessControl(void);\n\tvoid Teleport(CVector v);\n\tvoid PreRender(void);\n\tvoid Render(void);\n\n\t// from CPhysical\n\tint32 ProcessEntityCollision(CEntity *ent, CColPoint *colpoints);\n\n\t// from CVehicle\n\tvoid ProcessControlInputs(uint8);\n\tvoid GetComponentWorldPosition(int32 component, CVector &pos);\n\tbool IsComponentPresent(int32 component);\n\tvoid SetComponentRotation(int32 component, CVector rotation);\n\tvoid OpenDoor(int32 component, eDoors door, float openRatio);\n\tvoid ProcessOpenDoor(uint32, uint32, float);\n\tbool IsDoorReady(eDoors door);\n\tbool IsDoorFullyOpen(eDoors door);\n\tbool IsDoorClosed(eDoors door);\n\tbool IsDoorMissing(eDoors door);\n\tbool IsDoorReady(uint32 door);\n\tbool IsDoorMissing(uint32 door);\n\tbool IsOpenTopCar(void);\n\tvoid RemoveRefsToVehicle(CEntity *ent);\n\tvoid BlowUpCar(CEntity *ent);\n\tbool SetUpWheelColModel(CColModel *colModel);\n\tvoid BurstTyre(uint8 tyre, bool applyForces);\n\tbool IsRoomForPedToLeaveCar(uint32 component, CVector *doorOffset);\n\tfloat GetHeightAboveRoad(void);\n\tvoid PlayCarHorn(void);\n\n\tvoid FireTruckControl(void);\n\tvoid TankControl(void);\n\tvoid HydraulicControl(void);\n\tvoid VehicleDamage(float impulse, uint16 damagedPiece);\n\tvoid ProcessBuoyancy(void);\n\tvoid DoDriveByShootings(void);\n\tvoid DoHoverSuspensionRatios(void);\n\tint32 RcbanditCheckHitWheels(void);\n\tint32 RcbanditCheck1CarWheels(CPtrList &list);\n\tvoid PlaceOnRoadProperly(void);\n\tvoid dmgDrawCarCollidingParticles(const CVector &pos, float amount);\n\tvoid AddDamagedVehicleParticles(void);\n\tint32 AddWheelDirtAndWater(CColPoint *colpoint, uint32 belowEffectSpeed);\n\tvoid PlayHornIfNecessary(void);\n\tvoid ResetSuspension(void);\n\tvoid SetupSuspensionLines(void);\n\tvoid ScanForCrimes(void);\n\tvoid BlowUpCarsInPath(void);\n\tbool HasCarStoppedBecauseOfLight(void);\n\tvoid SetBusDoorTimer(uint32 timer, uint8 type);\n\tvoid ProcessAutoBusDoors(void);\n\tvoid ProcessSwingingDoor(int32 component, eDoors door);\n\tvoid SetupDamageAfterLoad(void);\n\tCObject *SpawnFlyingComponent(int32 component, uint32 type);\n\tCObject *RemoveBonnetInPedCollision(void);\n\tvoid SetPanelDamage(int32 component, ePanels panel, bool noFlyingComponents = false);\n\tvoid SetBumperDamage(int32 component, ePanels panel, bool noFlyingComponents = false);\n\tvoid SetDoorDamage(int32 component, eDoors door, bool noFlyingComponents = false);\n\n\tvoid TellHeliToGoToCoors(float x, float y, float z, uint8 speed);\n\tvoid TellPlaneToGoToCoors(float x, float y, float z, uint8 speed);\n\tvoid SetHeliOrientation(float orient) { m_fHeliOrientation = orient; }\n\tvoid ClearHeliOrientation(void) { m_fHeliOrientation = -1.0f; }\n\n\tvoid Fix(void);\n\tvoid SetComponentVisibility(RwFrame *frame, uint32 flags);\n\tvoid SetupModelNodes(void);\n\tvoid SetTaxiLight(bool light);\n\tbool GetAllWheelsOffGround(void);\n\tvoid HideAllComps(void);\n\tvoid ShowAllComps(void);\n\tvoid ReduceHornCounter(void);\n\n\tvoid PopBoot(void);\n\tvoid PopBootUsingPhysics(void);\n\tvoid CloseAllDoors(void);\n\tvoid KnockPedOutCar(eWeaponType weapon, uint16 door, CPed *ped);\n\n#ifdef COMPATIBLE_SAVES\n\tvirtual void Save(uint8*& buf);\n\tvirtual void Load(uint8*& buf);\n#endif\n\tstatic const uint32 nSaveStructSize;\n\n\tstatic void SetAllTaxiLights(bool set);\n};\n\nextern CVector vecHunterGunPos;\nextern bool bAllCarCheat;"
  },
  {
    "path": "src/vehicles/Bike.cpp",
    "content": "#include \"common.h\"\n#include \"General.h\"\n#include \"Pad.h\"\n#include \"DMAudio.h\"\n#include \"Clock.h\"\n#include \"Timecycle.h\"\n#include \"ZoneCull.h\"\n#include \"Camera.h\"\n#include \"Darkel.h\"\n#include \"Rubbish.h\"\n#include \"Explosion.h\"\n#include \"Particle.h\"\n#include \"ParticleObject.h\"\n#include \"Shadows.h\"\n#include \"PointLights.h\"\n#include \"Coronas.h\"\n#include \"SpecialFX.h\"\n#include \"WaterLevel.h\"\n#include \"Floater.h\"\n#include \"World.h\"\n#include \"SurfaceTable.h\"\n#include \"Weather.h\"\n#include \"Record.h\"\n#include \"CarCtrl.h\"\n#include \"CarAI.h\"\n#include \"Script.h\"\n#include \"Stats.h\"\n#include \"Replay.h\"\n#include \"AnimManager.h\"\n#include \"RpAnimBlend.h\"\n#include \"AnimBlendAssociation.h\"\n#include \"Ped.h\"\n#include \"PlayerPed.h\"\n#include \"DamageManager.h\"\n#include \"Vehicle.h\"\n#include \"Automobile.h\"\n#include \"Bike.h\"\n#include \"Debug.h\"\n\nconst uint32 CBike::nSaveStructSize =\n#ifdef COMPATIBLE_SAVES\n\t1260;\n#else\n\tsizeof(CBoat);\n#endif\n\n\n// TODO: maybe put this somewhere else\ninline void\nGetRelativeMatrix(RwMatrix *mat, RwFrame *frm, RwFrame *end)\n{\n\t*mat = *RwFrameGetMatrix(frm);\n\tfrm = RwFrameGetParent(frm);\n\twhile(frm){\n\t\tRwMatrixTransform(mat, RwFrameGetMatrix(frm), rwCOMBINEPOSTCONCAT);\n\t\tfrm = RwFrameGetParent(frm);\n\t\tif(frm == end)\n\t\t\tfrm = nil;\n\t}\n}\n\n#define FAKESUSPENSION (99999.992f)\n\nCBike::CBike(int32 id, uint8 CreatedBy)\n : CVehicle(CreatedBy)\n{\n\tint i;\n\tCVehicleModelInfo *mi = (CVehicleModelInfo*)CModelInfo::GetModelInfo(id);\n\tswitch(id){\n\tcase MI_ANGEL:\n\tcase MI_FREEWAY:\n\t\tm_bikeAnimType = ASSOCGRP_BIKE_HARLEY;\n\t\tbreak;\n\tcase MI_PIZZABOY:\n\tcase MI_FAGGIO:\n\t\tm_bikeAnimType = ASSOCGRP_BIKE_VESPA;\n\t\tbreak;\n\tcase MI_PCJ600:\n\t\tm_bikeAnimType = ASSOCGRP_BIKE_STANDARD;\n\t\tbreak;\n\tcase MI_SANCHEZ:\n\t\tm_bikeAnimType = ASSOCGRP_BIKE_DIRT;\n\t\tbreak;\n\tdefault: assert(0 && \"invalid bike model ID\");\n\t}\n\tm_vehType = VEHICLE_TYPE_BIKE;\n\n\tm_fFireBlowUpTimer = 0.0f;\n\tm_doingBurnout = 0;\n\tm_bike_flag01 = false;\n\n\tSetModelIndex(id);\n\n\tpHandling = mod_HandlingManager.GetHandlingData((tVehicleType)mi->m_handlingId);\n\tpBikeHandling = mod_HandlingManager.GetBikePointer((tVehicleType)mi->m_handlingId);\n\tpFlyingHandling = mod_HandlingManager.GetFlyingPointer((tVehicleType)mi->m_handlingId);\n\n\tm_bike_unused1 = 20.0f;\n\tm_bike_unused2 = 0;\n\n\tmi->ChooseVehicleColour(m_currentColour1, m_currentColour2);\n\n\tm_fRearForkLength = 0.0f;\n\tm_fFrontForkY = 0.0;\n\tm_fFrontForkZ = 0.0;\n\tm_fFrontForkSlope = Tan(DEGTORAD(mi->m_bikeSteerAngle));\n\n\tm_fMass = pHandling->fMass;\n\tm_fTurnMass = pHandling->fTurnMass;\n\tm_vecCentreOfMass = pHandling->CentreOfMass;\n\tm_vecCentreOfMass.z = 0.1f;\n\tm_fAirResistance = pHandling->Dimension.x*pHandling->Dimension.z/m_fMass;\n\tm_fElasticity = 0.05f;\n\tm_fBuoyancy = pHandling->fBuoyancy;\n\n\tm_fSteerAngle = 0.0f;\n\tm_fWheelAngle = 0.0f;\n\tm_fLeanLRAngle = 0.0f;\n\tm_fLeanLRAngle2 = 0.0f;\n\tm_fGasPedal = 0.0f;\n\tm_fBrakePedal = 0.0f;\n\tm_fLeanInput = 0.0f;\n\tm_fPedLeanAmountLR = 0.0f;\n\tm_fPedLeanAmountUD = 0.0f;\n\tm_pSetOnFireEntity = nil;\n\tm_pBombRigger = nil;\n\tm_fGasPedalAudio = 0.0f;\n\tm_bike_flag02 = false;\n\tbWaterTight = false;\n\tbIsBeingPickedUp = false;\n\tbIsStanding = false;\n\tbExtraSpeed = false;\n\tbIsOnFire = false;\n\tbWheelieCam = false;\n\n\tm_fTireTemperature = 1.0f;\n\tm_fBrakeDestabilization = 0.0f;\n\tm_fVelocityChangeForAudio = 0;\n\n\tfor(i = 0; i < 2; i++){\n\t\tm_aWheelRotation[i] = 0.0f;\n\t\tm_aWheelSpeed[i] = 0.0f;\n\t\tm_aWheelState[i] = WHEEL_STATE_NORMAL;\n\t\tm_aWheelSkidmarkType[i] = SKIDMARK_NORMAL;\n\t\tm_aWheelSkidmarkBloody[i] = false;\n\t\tm_aWheelSkidmarkUnk[0] = false;\n\t\tm_wheelStatus[i] = WHEEL_STATUS_OK;\n\t}\n\n\tfor(i = 0; i < 4; i++){\n\t\tm_aGroundPhysical[i] = nil;\n\t\tm_aGroundOffset[i] = CVector(0.0f, 0.0f, 0.0f);\n\t\tm_aSuspensionSpringRatioPrev[i] = m_aSuspensionSpringRatio[i] = 1.0f;\n\t\tm_aWheelTimer[i] = 0.0f;\n\t}\n\n\tm_nWheelsOnGround = 0;\n\tm_nDriveWheelsOnGround = 0;\n\tm_nDriveWheelsOnGroundPrev = 0;\n\tm_fHeightAboveRoad = 0.0f;\n\tm_fTraction = 1.0f;\n\n\tCColModel *colModel = mi->GetColModel();\n\tif(colModel->lines == nil){\n\t\tcolModel->lines = (CColLine*)RwMalloc(4*sizeof(CColLine));\n\t\tcolModel->numLines = 4;\n\t}\n\t// BUG? this would make more sense in the if above\n\tcolModel->lines[0].p0.z = FAKESUSPENSION;\n\n\tSetupSuspensionLines();\n\n\tAutoPilot.m_nCarMission = MISSION_NONE;\n\tAutoPilot.m_nTempAction = TEMPACT_NONE;\n\tAutoPilot.m_nTimeToStartMission = CTimer::GetTimeInMilliseconds();\n\tAutoPilot.m_bStayInCurrentLevel = false;\n\n\tSetStatus(STATUS_SIMPLE);\n\tbUseCollisionRecords = true;\n\tm_nNumPassengers = 0;\n\tbIsVan = false;\n\tbIsBus = false;\n\tbIsBig = false;\n\tbLowVehicle = false;\n\tbPedPhysics = false;\n\n\tbLeanMatrixClean = false;\n\tm_leanMatrix = GetMatrix();\n}\n\nvoid\nCBike::SetModelIndex(uint32 id)\n{\n\tCVehicle::SetModelIndex(id);\n\tSetupModelNodes();\n}\n\n#define SAND_SLOWDOWN (0.02f)\nCVector vecTestResistance(0.9995f, 0.9f, 0.95f);\nfloat fDAxisX = 1.0f;\nfloat fDAxisXExtra = 100.0f;\nfloat fDAxisY = 1000.0f;\nfloat fInAirXRes = 0.98f;\nfloat fFlySpeedMult = -0.6f;\n\n#pragma optimize(\"\", off) // a workaround for another compiler bug =P, original had optimize off for this function too though\n\nvoid\nCBike::ProcessControl(void)\n{\n\tint i;\n\tfloat wheelRot;\n\tfloat acceleration = 0.0f;\n\tbool bBalancedByRider = false;\n\tbool bStuckInSand = false;\n\tfloat brake = 0.0f;\n\tCColModel *colModel = GetColModel();\n\tfloat wheelScale = ((CVehicleModelInfo*)CModelInfo::GetModelInfo(GetModelIndex()))->m_wheelScale;\n\tbWarnedPeds = false;\n\tbLeanMatrixClean = false;\n\tm_doingBurnout = 0;\n\tbExtraSpeed = false;\n\tbRestingOnPhysical = false;\n\n\tif(CReplay::IsPlayingBack())\n\t\treturn;\n\n\tProcessCarAlarm();\n\n\tActivateBombWhenEntered();\n\n\tCRubbish::StirUp(this);\n\n\tUpdateClumpAlpha();\n\n\tAutoPilot.m_bSlowedDownBecauseOfCars = false;\n\tAutoPilot.m_bSlowedDownBecauseOfPeds = false;\n\n\tswitch(GetStatus()){\n\tcase STATUS_PLAYER:\n\t\tbBalancedByRider = true;\n\t\tbIsBeingPickedUp = false;\n\t\tif(FindPlayerPed()->GetPedState() != PED_EXIT_CAR && FindPlayerPed()->GetPedState() != PED_DRAG_FROM_CAR){\n\t\t\tProcessControlInputs(0);\n\n\t\t\tif(m_fLeanInput < 0.0f){\n\t\t\t\tm_vecCentreOfMass.y = pHandling->CentreOfMass.y + pBikeHandling->fLeanBakCOM*m_fLeanInput;\n\t\t\t\tCVector com = m_vecCentreOfMass;\n#ifdef FIX_BUGS\n\t\t\t\t// center of mass has to have world space orientation. unfortunately we can't do wheelies\n\t\t\t\t// at high speed then, flipping y here is like riding south without this fix where wheelies work\n\t\t\t\tcom.y = -com.y;\n\t\t\t\tcom = Multiply3x3(GetMatrix(), com);\n#endif\n\t\t\t\tif(m_fBrakePedal == 0.0f && !bIsHandbrakeOn || m_nWheelsOnGround == 0){\n\t\t\t\t\tif(GetModelIndex() == MI_SANCHEZ){\n\t\t\t\t\t\tfloat force = m_fLeanInput*m_fTurnMass*pBikeHandling->fLeanBackForce*Min(m_vecMoveSpeed.Magnitude(), 0.1f);\n\t\t\t\t\t\tforce *= 0.7f*m_fGasPedal + 0.3f;\n\t\t\t\t\t\tApplyTurnForce(-force*CTimer::GetTimeStep()*GetUp(), com+GetForward());\n\t\t\t\t\t}else{\n\t\t\t\t\t\tfloat force = m_fLeanInput*m_fTurnMass*pBikeHandling->fLeanBackForce*Min(m_vecMoveSpeed.Magnitude(), 0.1f);\n\t\t\t\t\t\tforce *= 0.5f*m_fGasPedal + 0.5f;\n\t\t\t\t\t\tApplyTurnForce(-force*CTimer::GetTimeStep()*GetUp(), com+GetForward());\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}else{\n\t\t\t\tm_vecCentreOfMass.y = pHandling->CentreOfMass.y + pBikeHandling->fLeanFwdCOM*m_fLeanInput;\n\t\t\t\tCVector com = m_vecCentreOfMass;\n#ifdef FIX_BUGS\n\t\t\t\t// see above\n\t\t\t\tcom.y = -com.y;\n\t\t\t\tcom = Multiply3x3(GetMatrix(), com);\n#endif\n\t\t\t\tif(m_fBrakePedal < 0.0f || m_nWheelsOnGround == 0){\n\t\t\t\t\tfloat force = m_fLeanInput*m_fTurnMass*pBikeHandling->fLeanFwdForce*Min(m_vecMoveSpeed.Magnitude(), 0.1f);\n\t\t\t\t\tApplyTurnForce(-force*CTimer::GetTimeStep()*GetUp(), com+GetForward());\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tPruneReferences();\n\n\t\t\tif(GetStatus() == STATUS_PLAYER && !CRecordDataForChase::IsRecording())\n\t\t\t\tDoDriveByShootings();\n\n\t\t\tif(m_aSuspensionSpringRatio[0] < 1.0f && CSurfaceTable::GetAdhesionGroup(m_aWheelColPoints[0].surfaceB) == ADHESIVE_SAND ||\n\t\t\t   m_aSuspensionSpringRatio[1] < 1.0f && CSurfaceTable::GetAdhesionGroup(m_aWheelColPoints[1].surfaceB) == ADHESIVE_SAND ||\n\t\t\t   m_aSuspensionSpringRatio[2] < 1.0f && CSurfaceTable::GetAdhesionGroup(m_aWheelColPoints[2].surfaceB) == ADHESIVE_SAND ||\n\t\t\t   m_aSuspensionSpringRatio[3] < 1.0f && CSurfaceTable::GetAdhesionGroup(m_aWheelColPoints[3].surfaceB) == ADHESIVE_SAND){\n\t\t\t\tCVector parallelSpeed = m_vecMoveSpeed - DotProduct(m_vecMoveSpeed, GetUp())*GetUp();\n\t\t\t\tif(m_fGasPedal > 0.3f){\n\t\t\t\t\tif(parallelSpeed.MagnitudeSqr() < SQR(0.3f))\n\t\t\t\t\t\tbStuckInSand = true;\n\t\t\t\t\tparallelSpeed -= DotProduct(parallelSpeed, GetForward())*GetForward();\n\t\t\t\t}\n\t\t\t\tApplyMoveForce(parallelSpeed * -CTimer::GetTimeStep()*SAND_SLOWDOWN*m_fMass);\n\t\t\t}\n\t\t}\n\t\tif(CPad::GetPad(0)->WeaponJustDown())\n\t\t\tActivateBomb();\n\t\tbreak;\n\n\tcase STATUS_PLAYER_PLAYBACKFROMBUFFER:\n\t\tbBalancedByRider = true;\n\t\tbreak;\n\n\tcase STATUS_SIMPLE:\n\t\tCCarAI::UpdateCarAI(this);\n\t\tCPhysical::ProcessControl();\n\t\tCCarCtrl::UpdateCarOnRails(this);\n\n\t\tm_nWheelsOnGround = 2;\n\t\tm_nDriveWheelsOnGroundPrev = m_nDriveWheelsOnGround;\n\t\tm_nDriveWheelsOnGround = 2;\n\n\t\tpHandling->Transmission.CalculateGearForSimpleCar(AutoPilot.m_fMaxTrafficSpeed/50.0f, m_nCurrentGear);\n\n\t\twheelRot = ProcessWheelRotation(WHEEL_STATE_NORMAL, GetForward(), m_vecMoveSpeed, 0.5f*wheelScale);\n\t\tfor(i = 0; i < 2; i++)\n\t\t\tm_aWheelRotation[i] += wheelRot;\n\n\t\tPlayHornIfNecessary();\n\t\tReduceHornCounter();\n\t\tbVehicleColProcessed = false;\n\t\tbAudioChangingGear = false;\n\t\tbWheelieCam = false;\n\t\t// that's all we do for simple vehicles\n\t\treturn;\n\n\tcase STATUS_PHYSICS:\n\t\tCCarAI::UpdateCarAI(this);\n\t\tCCarCtrl::SteerAICarWithPhysics(this);\n\t\tPlayHornIfNecessary();\n\n\t\tbBalancedByRider = true;\n\t\tbWheelieCam = false;\n\n\t\tif(bIsBeingCarJacked){\n\t\t\tm_fGasPedal = 0.0f;\n\t\t\tm_fBrakePedal = 1.0f;\n\t\t\tbIsHandbrakeOn = true;\n\t\t}else\n\t\t\tbIsBeingPickedUp = false;\n\t\tbreak;\n\n\tcase STATUS_ABANDONED:\n\t\tm_fBrakePedal = 0.0f;\n\t\tif(m_vecMoveSpeed.MagnitudeSqr() < SQR(0.1f) || bIsStanding)\n\t\t\tbIsHandbrakeOn = true;\n\t\telse\t\n\t\t\tbIsHandbrakeOn = false;\n\n\t\tm_fGasPedal = 0.0f;\n#ifdef FIX_BUGS\n\t\tif(!IsAlarmOn())\n#endif\n\t\t\tm_nCarHornTimer = 0;\n\n\t\tbBalancedByRider = (pDriver || pPassengers[0] || bIsBeingCarJacked) && !bIsStanding;\n\t\tm_fPedLeanAmountLR = 0.0f;\n\t\tm_fPedLeanAmountUD = 0.0f;\n\t\tbWheelieCam = false;\n\n\t\tif(bIsBeingCarJacked){\n\t\t\tm_fGasPedal = 0.0f;\n\t\t\tm_fBrakePedal = 1.0f;\n\t\t\tbIsHandbrakeOn = true;\n\t\t}\n\t\tbreak;\n\n\tcase STATUS_WRECKED:\n\t\tm_fBrakePedal = 0.05f;\n\t\tbIsHandbrakeOn = true;\n\n\t\tm_fSteerAngle = 0.0f;\n\t\tm_fGasPedal = 0.0f;\n#ifdef FIX_BUGS\n\t\tif(!IsAlarmOn())\n#endif\n\t\t\tm_nCarHornTimer = 0;\n\n\t\tbBalancedByRider = false;\n\t\tbWheelieCam = false;\n\t\tm_fPedLeanAmountLR = 0.0f;\n\t\tm_fPedLeanAmountUD = 0.0f;\n\t\tbreak;\n\n\tcase STATUS_PLAYER_DISABLED:\n\t\tif(m_vecMoveSpeed.MagnitudeSqr() < SQR(0.1f)){\n\t\t\tm_fBrakePedal = 1.0f;\n\t\t\tbIsHandbrakeOn = true;\n\t\t}else{\n\t\t\tm_fBrakePedal = 0.0f;\n\t\t\tbIsHandbrakeOn = false;\n\t\t}\n\n\t\tm_fSteerAngle = 0.0f;\n\t\tm_fGasPedal = 0.0f;\n#ifdef FIX_BUGS\n\t\tif(!IsAlarmOn())\n#endif\n\t\t\tm_nCarHornTimer = 0;\n\n\t\tbBalancedByRider = true;\n\t\tbWheelieCam = false;\n\t\tbreak;\n\t}\n\n\tif(bIsStanding)\n\t\tif(Abs(GetRight().z) > 0.35f || Abs(GetForward().z) > 0.5f)\n\t\t\tbIsStanding = false;\n\n\tif(bBalancedByRider || bIsBeingPickedUp || bIsStanding){\n\t\tfloat fDx = fDAxisX;\n\t\tCVector res = vecTestResistance;\n\t\tCVector localTurnSpeed = Multiply3x3(m_vecTurnSpeed, GetMatrix());\n\n\t\tif(GetStatus() == STATUS_PLAYER){\n\t\t\tif(m_aWheelTimer[BIKESUSP_F1] == 0.0f && m_aWheelTimer[BIKESUSP_F2] == 0.0f){\n\t\t\t\tfDx = fDAxisXExtra;\n\t\t\t\tif(!(m_aWheelTimer[BIKESUSP_R1] == 0.0f && m_aWheelTimer[BIKESUSP_R2] == 0.0f) &&\n\t\t\t\t   GetForward().z > 0.0f)\n\t\t\t\t\tres.x -= Min(0.25f*Abs(pBikeHandling->fWheelieAng-GetForward().z), 0.07f);\n\t\t\t\telse\n\t\t\t\t\tres.x = fInAirXRes;\n\t\t\t}else if(m_aWheelTimer[BIKESUSP_R1] == 0.0f && m_aWheelTimer[BIKESUSP_R2] == 0.0f){\n\t\t\t\tfDx = fDAxisXExtra;\n\t\t\t\tif(GetForward().z < 0.0f)\n\t\t\t\t\tres.x *= Min(0.3f*Abs(pBikeHandling->fStoppieAng-GetForward().z), 0.1f) + 0.9f;\n\t\t\t}\n\t\t}\n\n\t\tres.x *= 1.0f/(fDx*SQR(localTurnSpeed.x) + 1.0f);\n\t\tres.y *= 1.0f/(fDAxisY*SQR(localTurnSpeed.y) + 1.0f);\n\t\tres.x = Pow(res.x, CTimer::GetTimeStep());\n\t\tres.y = Pow(res.y, CTimer::GetTimeStep());\n\t\tfloat turnX = localTurnSpeed.x*(res.x - 1.0f);\n\t\tfloat turnY = localTurnSpeed.y*(res.y - 1.0f);\n\n\t\tres = -GetUp() * turnY * m_fTurnMass;\n\t\tApplyTurnForce(res, GetRight() + Multiply3x3(GetMatrix(), m_vecCentreOfMass));\n\n\t\tres = GetUp() * turnX * m_fTurnMass;\n\t\tApplyTurnForce(res, GetForward() + Multiply3x3(GetMatrix(), m_vecCentreOfMass));\n\n\t\tif(GetStatus() != STATUS_PLAYER)\n\t\t\tm_vecCentreOfMass = pHandling->CentreOfMass;\n\t}else{\n\t\tm_vecCentreOfMass = pHandling->CentreOfMass;\n\t\tm_vecCentreOfMass.z = pBikeHandling->fNoPlayerCOMz;\n\t}\n\n\t// Skip physics if object is found to have been static recently\n\tbool skipPhysics = false;\n\tif(!bIsStuck && (GetStatus() == STATUS_ABANDONED || GetStatus() == STATUS_WRECKED) && !bIsBeingPickedUp){\n\t\tbool makeStatic = false;\n\t\tfloat moveSpeedLimit, turnSpeedLimit, distanceLimit;\n\n\t\tif(!bVehicleColProcessed &&\n\t\t   m_vecMoveSpeed.IsZero() &&\n\t\t// BUG? m_aSuspensionSpringRatioPrev[3] is checked twice in the game. also, why 3?\n\t\t   m_aSuspensionSpringRatioPrev[3] != 1.0f)\n\t\t\tmakeStatic = true;\n\n\t\tif(GetStatus() == STATUS_WRECKED){\n\t\t\tmoveSpeedLimit = 0.006f;\n\t\t\tturnSpeedLimit = 0.0015f;\n\t\t\tdistanceLimit = 0.015f;\n\t\t}else{\n\t\t\tmoveSpeedLimit = 0.003f;\n\t\t\tturnSpeedLimit = 0.0009f;\n\t\t\tdistanceLimit = 0.005f;\n\t\t}\n\n\t\tm_vecMoveSpeedAvg = (m_vecMoveSpeedAvg + m_vecMoveSpeed)/2.0f;\n\t\tm_vecTurnSpeedAvg = (m_vecTurnSpeedAvg + m_vecTurnSpeed)/2.0f;\n\n\t\tif(m_vecMoveSpeedAvg.MagnitudeSqr() <= sq(moveSpeedLimit*CTimer::GetTimeStep()) &&\n\t\t   m_vecTurnSpeedAvg.MagnitudeSqr() <= sq(turnSpeedLimit*CTimer::GetTimeStep()) &&\n\t\t   m_fDistanceTravelled < distanceLimit ||\n\t\t   makeStatic){\n\t\t\tm_nStaticFrames++;\n\n\t\t\tif(m_nStaticFrames > 10 || makeStatic)\n\t\t\t\tif(!CCarCtrl::MapCouldMoveInThisArea(GetPosition().x, GetPosition().y)){\n\t\t\t\t\tif(!makeStatic || m_nStaticFrames > 10)\n\t\t\t\t\t\tm_nStaticFrames = 10;\n\n\t\t\t\t\tskipPhysics = true;\n\n\t\t\t\t\tm_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);\n\t\t\t\t\tm_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f);\n\t\t\t\t}\n\t\t}else\n\t\t\tm_nStaticFrames = 0;\n\t}\n\n\t// Postpone\n\tfor(i = 0; i < 4; i++)\n\t\tif(m_aGroundPhysical[i]){\n\t\t\tbRestingOnPhysical = true;\n\t\t\tif(!CWorld::bForceProcessControl && m_aGroundPhysical[i]->bIsInSafePosition){\n\t\t\t\tbWasPostponed = true;\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\tif(bRestingOnPhysical){\n\t\tskipPhysics = false;\n\t\tm_nStaticFrames = 0;\n\t}\n\n\tVehicleDamage();\n\n\tif(skipPhysics){\n\t\tbHasContacted = false;\n\t\tbIsInSafePosition = false;\n\t\tbWasPostponed = false;\n\t\tbHasHitWall = false;\n\t\tm_nCollisionRecords = 0;\n\t\tbHasCollided = false;\n\t\tbVehicleColProcessed = false;\n\t\tbAudioChangingGear = false;\n\t\tm_nDamagePieceType = 0;\n\t\tm_fDamageImpulse = 0.0f;\n\t\tm_pDamageEntity = nil;\n\t\tm_vecTurnFriction = CVector(0.0f, 0.0f, 0.0f);\n\t\tm_vecMoveFriction = CVector(0.0f, 0.0f, 0.0f);\n// missing. BUG?\n//\t\tm_fTireTemperature = 1.0f;\n\n\t\tif(bIsStanding && m_fWheelAngle < DEGTORAD(20.0f))\n\t\t\tm_fWheelAngle += DEGTORAD(1.0f)*CTimer::GetTimeStep();\n\t\tif(bIsStanding){\n\t\t\tfloat f = Pow(0.97f, CTimer::GetTimeStep());\n\t\t\tm_fLeanLRAngle2 = m_fLeanLRAngle2*f - (Asin(clamp(GetRight().z,-1.0f,1.0f))+DEGTORAD(15.0f))*(1.0f-f);\n\t\t\tm_fLeanLRAngle = m_fLeanLRAngle2;\n\t\t}\n\t}else{\n\n\t\t// This has to be done if ProcessEntityCollision wasn't called\n\t\tif(!bVehicleColProcessed){\n\t\t\tCMatrix mat(GetMatrix());\n\t\t\tbIsStuck = false;\n\t\t\tbHasContacted = false;\n\t\t\tbIsInSafePosition = false;\n\t\t\tbWasPostponed = false;\n\t\t\tbHasHitWall = false;\n\t\t\tm_fDistanceTravelled = 0.0f;\n\t\t\tm_bIsVehicleBeingShifted = false;\n\t\t\tbSkipLineCol = false;\n\t\t\tApplyMoveSpeed();\n\t\t\tApplyTurnSpeed();\n\t\t\tfor(i = 0; CheckCollision() && i < 5; i++){\n\t\t\t\tGetMatrix() = mat;\n\t\t\t\tApplyMoveSpeed();\n\t\t\t\tApplyTurnSpeed();\n\t\t\t}\n\t\t\tbIsInSafePosition = true;\n\t\t\tbIsStuck = false;\t\t\t\n\t\t}\n\n\t\tif(!(bBalancedByRider || bIsBeingPickedUp || bIsStanding)){\n\t\t\tif(GetRight().z < 0.0f){\n\t\t\t\tif(m_fSteerAngle > -DEGTORAD(25.0f))\n\t\t\t\t\tm_fSteerAngle -= DEGTORAD(0.5f)*CTimer::GetTimeStep();\n\t\t\t}else{\n\t\t\t\tif(m_fSteerAngle < DEGTORAD(25.0f))\n\t\t\t\t\tm_fSteerAngle += DEGTORAD(0.5f)*CTimer::GetTimeStep();\n\t\t\t}\n\t\t}\n\n\t\t// Lean forward speed up\n\t\tfloat savedAirResistance = m_fAirResistance;\n\t\tif(GetStatus() == STATUS_PLAYER && pDriver){\n\t\t\tCAnimBlendAssociation *assoc = RpAnimBlendClumpGetAssociation(pDriver->GetClump(), ANIM_BIKE_LEANF);\n\t\t\tif(assoc && assoc->blendAmount > 0.5f &&\n\t\t\t   assoc->currentTime > 0.06f && assoc->currentTime < 0.14f){\n\t\t\t\tm_fAirResistance *= 0.6f;\n\t\t\t\tif(m_fGasPedal > 0.5f && DotProduct(m_vecMoveSpeed, GetForward()) > 0.25f){\n\t\t\t\t\tApplyMoveForce(0.2f*m_fMass*GRAVITY*CTimer::GetTimeStep()*GetForward());\n\t\t\t\t\tbExtraSpeed = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tCPhysical::ProcessControl();\n\t\tm_fAirResistance = savedAirResistance;\n\n\t\tProcessBuoyancy();\n\n\t\t// Rescale spring ratios, i.e. subtract wheel radius\n\t\tfor(i = 0; i < 4; i++){\n\t\t\t// wheel radius in relation to suspension line\n\t\t\tfloat wheelRadius = 1.0f - m_aSuspensionSpringLength[i]/m_aSuspensionLineLength[i];\n\t\t\t// rescale such that 0.0 is fully compressed and 1.0 is fully extended\n\t\t\tm_aSuspensionSpringRatio[i] = (m_aSuspensionSpringRatio[i]-wheelRadius)/(1.0f-wheelRadius);\n\t\t}\n\n\t\tint rnd = 0;\n\t\tfloat fwdSpeed = Abs(DotProduct(m_vecMoveSpeed, GetForward()));\n\t\tCVector contactPoints[4];\t// relative to model\n\t\tCVector contactSpeeds[4];\t// speed at contact points\n\t\tCVector springDirections[4];\t// normalized, in model space\n\n\t\tfor(i = 0; i < 4; i++){\n\t\t\t// Set spring under certain circumstances\n\t\t\tif(m_wheelStatus[i/2] == WHEEL_STATUS_MISSING)\n\t\t\t\tm_aSuspensionSpringRatio[i] = 1.0f;\n\t\t\telse if(m_wheelStatus[i/2] == WHEEL_STATUS_BURST){\n\t\t\t\t// wheel more bumpy the faster we are\n\t\t\t\tif(i == BIKESUSP_F1 || i == BIKESUSP_R1)\n\t\t\t\t\trnd = CGeneral::GetRandomNumberInRange(0, (uint16)(40*fwdSpeed) + 98) < 100;\n\t\t\t\tif(rnd){\n\t\t\t\t\tm_aSuspensionSpringRatio[i] += 0.3f*(m_aSuspensionLineLength[i]-m_aSuspensionSpringLength[i])/m_aSuspensionSpringLength[i];\n\t\t\t\t\tif(m_aSuspensionSpringRatio[i] > 1.0f)\n\t\t\t\t\t\tm_aSuspensionSpringRatio[i] = 1.0f;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// get points and directions if spring is compressed\n\t\t\tif(m_aSuspensionSpringRatio[i] < 1.0f){\n\t\t\t\tcontactPoints[i] = m_aWheelColPoints[i].point - GetPosition();\n\t\t\t\tspringDirections[i] = Multiply3x3(GetMatrix(), colModel->lines[i].p1 - colModel->lines[i].p0);\n\t\t\t\tspringDirections[i].Normalise();\n\t\t\t}\n\t\t}\n\n\t\tm_aWheelSkidmarkType[0] = m_aWheelSkidmarkType[1] = SKIDMARK_NORMAL;\n\t\tm_aWheelSkidmarkUnk[0] = m_aWheelSkidmarkUnk[1] = false;\n\n\t\t// Make springs push up vehicle\n\t\tfor(i = 0; i < 4; i++){\n\t\t\tif(m_aSuspensionSpringRatio[i] < 1.0f){\n\t\t\t\tfloat bias = pHandling->fSuspensionBias;\n\t\t\t\tif(i == BIKESUSP_R1 || i == BIKESUSP_R2)\n\t\t\t\t\tbias = 1.0f - bias;\n\n\t\t\t\tif(m_aWheelColPoints[i].normal.z > 0.35f)\n\t\t\t\t\tApplySpringCollisionAlt(pHandling->fSuspensionForceLevel,\n\t\t\t\t\t\tspringDirections[i], contactPoints[i],\n\t\t\t\t\t\tm_aSuspensionSpringRatio[i], bias, m_aWheelColPoints[i].normal);\n\t\t\t\telse\n\t\t\t\t\tApplySpringCollision(pHandling->fSuspensionForceLevel,\n\t\t\t\t\t\tspringDirections[i], contactPoints[i],\n\t\t\t\t\t\tm_aSuspensionSpringRatio[i], bias);\n\n\t\t\t\tif(m_aWheelColPoints[i].surfaceB == SURFACE_GRASS ||\n\t\t\t\t   m_aWheelColPoints[i].surfaceB == SURFACE_MUD_DRY){\n\t\t\t\t\tif(i < 2)\n\t\t\t\t\t\tm_aWheelSkidmarkType[0] = SKIDMARK_MUDDY;\n\t\t\t\t\telse\n\t\t\t\t\t\tm_aWheelSkidmarkType[1] = SKIDMARK_MUDDY;\n\t\t\t\t}else if(m_aWheelColPoints[i].surfaceB == SURFACE_SAND ||\n\t\t\t\t         m_aWheelColPoints[i].surfaceB == SURFACE_SAND_BEACH){\n\t\t\t\t\tif(i < 2){\n\t\t\t\t\t\tm_aWheelSkidmarkType[0] = SKIDMARK_SANDY;\n\t\t\t\t\t\tm_aWheelSkidmarkUnk[0] = true;\n\t\t\t\t\t}else{\n\t\t\t\t\t\tm_aWheelSkidmarkType[1] = SKIDMARK_SANDY;\n\t\t\t\t\t\tm_aWheelSkidmarkUnk[1] = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}else{\n\t\t\t\tcontactPoints[i] = Multiply3x3(GetMatrix(), colModel->lines[i].p1);\n\t\t\t}\n\t\t}\n\n\t\t// Get speed at contact points\n\t\tfor(i = 0; i < 4; i++){\n\t\t\tcontactSpeeds[i] = GetSpeed(contactPoints[i]);\n\t\t\tif(m_aGroundPhysical[i]){\n\t\t\t\t// subtract movement of physical we're standing on\n\t\t\t\tcontactSpeeds[i] -= m_aGroundPhysical[i]->GetSpeed(m_aGroundOffset[i]);\n#ifndef FIX_BUGS\n\t\t\t\t// this shouldn't be reset because we still need it below\n\t\t\t\tm_aGroundPhysical[i] = nil;\n#endif\n\t\t\t}\n\t\t}\n\n\t\tCVector normal;\n\t\tif(m_aSuspensionSpringRatio[0] < 1.0f || m_aSuspensionSpringRatio[1] < 1.0f){\n\t\t\tnormal = m_aSuspensionSpringRatio[0] < 1.0f ? m_aWheelColPoints[0].normal : m_aWheelColPoints[1].normal;\n\t\t\tif(normal.z > 0.35f)\n\t\t\t\tspringDirections[0] = -normal;\n\t\t\tnormal = m_aSuspensionSpringRatio[1] < 1.0f ? m_aWheelColPoints[1].normal : m_aWheelColPoints[0].normal;\n\t\t\tif(normal.z > 0.35f)\n\t\t\t\tspringDirections[1] = -normal;\n\t\t}\n\t\tif(m_aSuspensionSpringRatio[2] < 1.0f || m_aSuspensionSpringRatio[3] < 1.0f){\n\t\t\tnormal = m_aSuspensionSpringRatio[2] < 1.0f ? m_aWheelColPoints[2].normal : m_aWheelColPoints[3].normal;\n\t\t\tif(normal.z > 0.35f)\n\t\t\t\tspringDirections[2] = -normal;\n\t\t\tnormal = m_aSuspensionSpringRatio[3] < 1.0f ? m_aWheelColPoints[3].normal : m_aWheelColPoints[2].normal;\n\t\t\tif(normal.z > 0.35f)\n\t\t\t\tspringDirections[3] = -normal;\n\t\t}\n\n\t\t// game has dead code here if m_vecMoveSpeed.Magnitude() < 0.01f\n\n\t\t// dampen springs\n\t\tfor(i = 0; i < 4; i++)\n\t\t\tif(m_aSuspensionSpringRatio[i] < 1.0f)\n\t\t\t\tApplySpringDampening(pHandling->fSuspensionDampingLevel,\n\t\t\t\t\tspringDirections[i], contactPoints[i], contactSpeeds[i]);\n\n\t\t// Get speed at contact points again\n\t\tfor(i = 0; i < 4; i++){\n\t\t\tcontactSpeeds[i] = GetSpeed(contactPoints[i]);\n\t\t\tif(m_aGroundPhysical[i]){\n\t\t\t\t// subtract movement of physical we're standing on\n\t\t\t\tcontactSpeeds[i] -= m_aGroundPhysical[i]->GetSpeed(m_aGroundOffset[i]);\n\t\t\t\tm_aGroundPhysical[i] = nil;\n\t\t\t}\n\t\t}\n\n\t\tbool gripCheat = true;\n\t\tfwdSpeed = DotProduct(m_vecMoveSpeed, GetForward());\n\t\tif(!CVehicle::bCheat3)\n\t\t\tgripCheat = false;\n\t\tacceleration = pHandling->Transmission.CalculateDriveAcceleration(m_fGasPedal, m_nCurrentGear, m_fChangeGearTime, fwdSpeed, gripCheat);\n\t\tacceleration /= m_fForceMultiplier;\n\n\t\tbrake = m_fBrakePedal * pHandling->fBrakeDeceleration * CTimer::GetTimeStep();\n\t\tbool neutralHandling = GetStatus() != STATUS_PLAYER && GetStatus() != STATUS_PLAYER_REMOTE && (pHandling->Flags & HANDLING_NEUTRALHANDLING);\n\t\tfloat brakeBiasFront = neutralHandling ? 1.0f : 2.0f*pHandling->fBrakeBias;\n\t\tfloat brakeBiasRear  = neutralHandling ? 1.0f : 2.0f*(1.0f-pHandling->fBrakeBias);\n\t\tfloat tractionBiasFront = neutralHandling ? 1.0f : 2.0f*pHandling->fTractionBias;\n\t\tfloat tractionBiasRear  = neutralHandling ? 1.0f : 2.0f-tractionBiasFront;\n\n\t\t// Count how many wheels are touching the ground\n\n\t\tm_nWheelsOnGround = 0;\n\t\tm_nDriveWheelsOnGroundPrev = m_nDriveWheelsOnGround;\n\t\tm_nDriveWheelsOnGround = 0;\n\n\t\tfor(i = 0; i < 4; i++){\n\t\t\tif(m_aSuspensionSpringRatio[i] < 1.0f)\n\t\t\t\tm_aWheelTimer[i] = 4.0f;\n\t\t\telse\n\t\t\t\tm_aWheelTimer[i] = Max(m_aWheelTimer[i]-CTimer::GetTimeStep(), 0.0f);\n\n\t\t\tif(m_aWheelTimer[i] > 0.0f){\n\t\t\t\tm_nWheelsOnGround++;\n\t\t\t\tif(i == BIKESUSP_R1 || i == BIKESUSP_R2)\n\t\t\t\t\tm_nDriveWheelsOnGround = 1;\n\t\t\t\tif(m_nWheelsOnGround == 1)\n\t\t\t\t\tm_vecAvgSurfaceNormal = m_aWheelColPoints[i].normal;\n\t\t\t\telse\n\t\t\t\t\tm_vecAvgSurfaceNormal += m_aWheelColPoints[i].normal;\n\t\t\t}\n\t\t}\n\n\t\tif(m_nWheelsOnGround == 0)\n\t\t\tm_vecAvgSurfaceNormal = CVector(0.0f, 0.0f, 1.0f);\n\t\telse{\n\t\t\tm_vecAvgSurfaceNormal /= m_nWheelsOnGround;\n\t\t\tif(DotProduct(m_vecAvgSurfaceNormal, GetUp()) < -0.5f)\n\t\t\t\tm_vecAvgSurfaceNormal *= -1.0f;\n\t\t}\n\n\t\t// Find contact points for wheel processing\n\t\tint frontLine = m_aSuspensionSpringRatio[BIKESUSP_F1] < m_aSuspensionSpringRatio[BIKESUSP_F2] ?\n\t\t\tBIKESUSP_F1 : BIKESUSP_F2;\n\t\tCVector frontContact(0.0f,\n\t\t\tcolModel->lines[BIKESUSP_F1].p0.y,\n\t\t\tcolModel->lines[BIKESUSP_F1].p0.z - m_aSuspensionSpringRatio[frontLine]*m_aSuspensionSpringLength[BIKESUSP_F1] - 0.5f*wheelScale);\n\t\tfrontContact = Multiply3x3(GetMatrix(), frontContact);\n\n\t\tint rearLine = m_aSuspensionSpringRatio[BIKESUSP_R1] < m_aSuspensionSpringRatio[BIKESUSP_R2] ?\n\t\t\tBIKESUSP_R1 : BIKESUSP_R2;\n\t\tCVector rearContact(0.0f,\n\t\t\tcolModel->lines[BIKESUSP_R1].p0.y,\n\t\t\tcolModel->lines[BIKESUSP_R1].p0.z - m_aSuspensionSpringRatio[rearLine]*m_aSuspensionSpringLength[BIKESUSP_R1] - 0.5f*wheelScale);\n\t\trearContact = Multiply3x3(GetMatrix(), rearContact);\n\n\t\tfloat traction = 0.004f * m_fTraction;\n\t\ttraction *= pHandling->fTractionMultiplier / 4.0f;\n\n\t\t// Turn wheel\n\t\tif(GetStatus() == STATUS_PLAYER || !bIsStanding || bIsBeingPickedUp){\n\t\t\tif(Abs(m_vecMoveSpeed.x) < 0.01f && Abs(m_vecMoveSpeed.y) < 0.01f && m_fSteerAngle == 0.0f){\n\t\t\t\tm_fWheelAngle *= Pow(0.96f, CTimer::GetTimeStep());\n\t\t\t}else{\n\t\t\t\tfloat f;\n\t\t\t\tif(fwdSpeed > 0.01f && m_aWheelTimer[BIKESUSP_F1] > 0.0f && m_aWheelTimer[BIKESUSP_F2] > 0.0f && GetStatus() == STATUS_PLAYER){\n\t\t\t\t\tCColPoint point;\n\t\t\t\t\tpoint.surfaceA = SURFACE_WHEELBASE;\n\t\t\t\t\tpoint.surfaceB = SURFACE_TARMAC;\n\t\t\t\t\tfloat steer = CSurfaceTable::GetAdhesiveLimit(point)*4.0f*pBikeHandling->fSpeedSteer*traction;\n\t\t\t\t\tif(CSurfaceTable::GetAdhesionGroup(m_aWheelColPoints[rearLine].surfaceB) == ADHESIVE_LOOSE ||\n\t\t\t\t\t   CSurfaceTable::GetAdhesionGroup(m_aWheelColPoints[rearLine].surfaceB) == ADHESIVE_SAND)\n\t\t\t\t\t\tsteer *= pBikeHandling->fSlipSteer;\n\t\t\t\t\tf = Asin(Min(steer/SQR(fwdSpeed), 1.0))/DEGTORAD(pHandling->fSteeringLock);\n\t\t\t\t\tif(m_fSteerAngle < 0.0f && m_fLeanLRAngle < 0.0f ||\n\t\t\t\t\t   m_fSteerAngle > 0.0f && m_fLeanLRAngle > 0.0f)\n\t\t\t\t\t\tf *= 2.0f;\n\t\t\t\t\tf = Min(f, 1.0f);\n\t\t\t\t}else{\n\t\t\t\t\tf = 1.0f;\n\t\t\t\t}\n\t\t\t\tif(GetStatus() != STATUS_PLAYER)\n\t\t\t\t\tf = 1.0f;\n\t\t\t\tm_fWheelAngle = m_fSteerAngle*f;\n\t\t\t}\n\t\t}else if(m_fWheelAngle < DEGTORAD(20.0f))\n\t\t\tm_fWheelAngle += DEGTORAD(1.5f)*CTimer::GetTimeStep();\n\n\t\tstatic float fThrust;\n\t\tstatic tWheelState WheelState[2];\n\t\tCVector initialMoveSpeed = m_vecMoveSpeed;\n\t\tbool rearWheelsFirst = !!(pHandling->Flags & HANDLING_REARWHEEL_1ST);\n\n\t\t// Process front wheel - first try\n\n\t\tif(!rearWheelsFirst){\n\t\t\tif(m_aWheelTimer[BIKESUSP_F1] > 0.0f || m_aWheelTimer[BIKESUSP_F2] > 0.0f){\n\t\t\t\t// Wheel on ground\n\t\t\t\teBikeWheelSpecial spec;\n\t\t\t\tif(m_aWheelTimer[BIKESUSP_R1] > 0.0f || m_aWheelTimer[BIKESUSP_R2] > 0.0f)\n\t\t\t\t\tspec = BIKE_WHEELSPEC_0;\n\t\t\t\telse\n\t\t\t\t\tspec = BIKE_WHEELSPEC_2;\n\t\t\t\tCVector wheelFwd = Multiply3x3(GetMatrix(), CVector(-Sin(m_fWheelAngle), Cos(m_fWheelAngle), 0.0f));\n\t\t\t\twheelFwd -= DotProduct(wheelFwd, m_aWheelColPoints[frontLine].normal)*m_aWheelColPoints[frontLine].normal;\n\t\t\t\twheelFwd.Normalise();\n\t\t\t\tCVector wheelRight = CrossProduct(wheelFwd, m_aWheelColPoints[frontLine].normal);\n\t\t\t\twheelRight.Normalise();\n\n\t\t\t\tfThrust = 0.0f;\n\t\t\t\tm_aWheelColPoints[frontLine].surfaceA = SURFACE_WHEELBASE;\n\t\t\t\tfloat adhesion = CSurfaceTable::GetAdhesiveLimit(m_aWheelColPoints[frontLine])*traction;\n\t\t\t\tfloat adhesionDestab = 1.0f;\n\t\t\t\tif(m_fBrakeDestabilization > 0.0f)\n\t\t\t\t\tswitch(CSurfaceTable::GetAdhesionGroup(m_aWheelColPoints[frontLine].surfaceB)){\n\t\t\t\t\tcase ADHESIVE_HARD:\n\t\t\t\t\tcase ADHESIVE_LOOSE:\n\t\t\t\t\t\tadhesionDestab = 0.9f;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase ADHESIVE_ROAD:\n\t\t\t\t\t\tadhesionDestab = 0.7f;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\tif(GetStatus() == STATUS_PLAYER)\n\t\t\t\t\tadhesion *= CSurfaceTable::GetWetMultiplier(m_aWheelColPoints[frontLine].surfaceB);\n\t\t\t\tif(m_wheelStatus[BIKEWHEEL_FRONT] == WHEEL_STATUS_BURST)\n\t\t\t\t\tadhesion *= 0.4f;\n\t\t\t\tWheelState[BIKEWHEEL_FRONT] = m_aWheelState[BIKEWHEEL_FRONT];\n\t\t\t\tCVector contactSpeed = GetSpeed(frontContact);\n\t\t\t\tProcessBikeWheel(wheelFwd, wheelRight,\n\t\t\t\t\tcontactSpeed, frontContact,\n\t\t\t\t\t2, fThrust,\n\t\t\t\t\tbrake*brakeBiasFront,\n\t\t\t\t\tadhesion*tractionBiasFront, adhesionDestab,\n\t\t\t\t\tBIKEWHEEL_FRONT,\n\t\t\t\t\t&m_aWheelSpeed[BIKEWHEEL_FRONT],\n\t\t\t\t\t&WheelState[BIKEWHEEL_FRONT],\n\t\t\t\t\tspec,\n\t\t\t\t\tm_wheelStatus[BIKEWHEEL_FRONT]);\n\t\t\t\tif(bStuckInSand && (WheelState[BIKEWHEEL_FRONT] == WHEEL_STATE_SPINNING || WheelState[BIKEWHEEL_FRONT] == WHEEL_STATE_SKIDDING))\n\t\t\t\t\tWheelState[BIKEWHEEL_FRONT] = WHEEL_STATE_NORMAL;\n\t\t\t}else{\n\t\t\t\t// Wheel in the air\n\t\t\t\tm_aWheelSpeed[BIKEWHEEL_FRONT] *= 0.95f;\n\t\t\t\tm_aWheelRotation[BIKEWHEEL_FRONT] += m_aWheelSpeed[BIKEWHEEL_FRONT];\n\t\t\t}\n\t\t}\n\n\t\t// Process rear wheel\n\n\t\tif(m_aWheelTimer[BIKESUSP_R1] > 0.0f || m_aWheelTimer[BIKESUSP_R2] > 0.0f){\n\t\t\t// Wheel on ground\n\t\t\tfloat rearBrake = brake;\n\t\t\tfloat rearTraction = traction;\n\n\t\t\tCVector wheelFwd = GetForward();\n\t\t\tCVector wheelRight = GetRight();\n\t\t\twheelFwd -= DotProduct(wheelFwd, m_aWheelColPoints[rearLine].normal)*m_aWheelColPoints[rearLine].normal;\n\t\t\twheelFwd.Normalise();\n\t\t\twheelRight = CrossProduct(wheelFwd, m_aWheelColPoints[rearLine].normal);\n\t\t\twheelRight.Normalise();\n\n\t\t\tif(bIsHandbrakeOn){\n#ifdef FIX_BUGS\n\t\t\t\t// Not sure if this is needed, but brake usually has timestep as a factor\n\t\t\t\trearBrake = 20000.0f * CTimer::GetTimeStepFix();\n#else\n\t\t\t\trearBrake = 20000.0f;\n#endif\n\t\t\t\tm_fTireTemperature = 1.0f;\n\t\t\t}else if(m_doingBurnout){\n\t\t\t\trearBrake = 0.0f;\n\t\t\t\trearTraction = 0.0f;\n\t\t\t\tApplyTurnForce(contactPoints[BIKESUSP_R1], -0.0007f*m_fTurnMass*m_fSteerAngle*GetRight()*CTimer::GetTimeStep());\n\t\t\t}else if(m_fTireTemperature < 1.0f && m_fGasPedal > 0.75f){\n\t\t\t\trearTraction *= m_fTireTemperature;\n\t\t\t\tApplyTurnForce(contactPoints[BIKESUSP_R1], (1.0f-m_fTireTemperature)*-0.0007f*m_fTurnMass*m_fSteerAngle*GetRight()*CTimer::GetTimeStep());\n\t\t\t}\n\n\t\t\tif(fThrust > 0.0f && brake > 0.0f)\n\t\t\t\tbrake = 0.0f;\t// only affects next front wheel. is this intended?\n\t\t\tfThrust = acceleration;\n\t\t\tm_aWheelColPoints[rearLine].surfaceA = SURFACE_WHEELBASE;\n\t\t\tfloat adhesion = CSurfaceTable::GetAdhesiveLimit(m_aWheelColPoints[rearLine])*rearTraction;\n\t\t\tfloat adhesionDestab = 1.0f;\n\t\t\tif(m_fBrakeDestabilization > 0.0f)\n\t\t\t\tswitch(CSurfaceTable::GetAdhesionGroup(m_aWheelColPoints[rearLine].surfaceB)){\n\t\t\t\tcase ADHESIVE_HARD:\n\t\t\t\tcase ADHESIVE_LOOSE:\n\t\t\t\t\tadhesionDestab = 0.9f;\n\t\t\t\t\tbreak;\n\t\t\t\tcase ADHESIVE_ROAD:\n\t\t\t\t\tadhesionDestab = 0.7f;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\tif(GetStatus() == STATUS_PLAYER)\n\t\t\t\tadhesion *= CSurfaceTable::GetWetMultiplier(m_aWheelColPoints[rearLine].surfaceB);\n\t\t\tif(m_wheelStatus[BIKEWHEEL_REAR] == WHEEL_STATUS_BURST)\n\t\t\t\tadhesion *= 0.4f;\n\t\t\tWheelState[BIKEWHEEL_REAR] = m_aWheelState[BIKEWHEEL_REAR];\n\t\t\tCVector contactSpeed = GetSpeed(rearContact);\n\t\t\tProcessBikeWheel(wheelFwd, wheelRight,\n\t\t\t\tcontactSpeed, rearContact,\n\t\t\t\t2, fThrust,\n\t\t\t\trearBrake*brakeBiasRear,\n\t\t\t\tadhesion*tractionBiasRear, adhesionDestab,\n\t\t\t\tBIKEWHEEL_REAR,\n\t\t\t\t&m_aWheelSpeed[BIKEWHEEL_REAR],\n\t\t\t\t&WheelState[BIKEWHEEL_REAR],\n\t\t\t\tBIKE_WHEELSPEC_1,\n\t\t\t\tm_wheelStatus[BIKEWHEEL_REAR]);\n\t\t\tif(bStuckInSand && (WheelState[BIKEWHEEL_REAR] == WHEEL_STATE_SPINNING || WheelState[BIKEWHEEL_REAR] == WHEEL_STATE_SKIDDING))\n\t\t\t\tWheelState[BIKEWHEEL_REAR] = WHEEL_STATE_NORMAL;\n\t\t}else{\n\t\t\t// Wheel in the air\n\t\t\tif(bIsHandbrakeOn)\n\t\t\t\tm_aWheelSpeed[BIKEWHEEL_REAR] = 0.0f;\n\t\t\telse{\n\t\t\t\tif(acceleration > 0.0f){\n\t\t\t\t\tif(m_aWheelSpeed[BIKEWHEEL_REAR] < 2.0f)\n\t\t\t\t\t\tm_aWheelSpeed[BIKEWHEEL_REAR] -= 0.2f;\n\t\t\t\t}else{\n\t\t\t\t\tif(m_aWheelSpeed[BIKEWHEEL_REAR] > -2.0f)\n\t\t\t\t\t\tm_aWheelSpeed[BIKEWHEEL_REAR] += 0.1f;\n\t\t\t\t}\n\t\t\t}\n\t\t\tm_aWheelRotation[BIKEWHEEL_REAR] += m_aWheelSpeed[BIKEWHEEL_REAR];\n\t\t}\n\n\t\tif(m_doingBurnout && m_aWheelState[BIKEWHEEL_REAR] == WHEEL_STATE_SPINNING){\n\t\t\tm_fTireTemperature += 0.001f*CTimer::GetTimeStep();\n\t\t\tif(m_fTireTemperature > 3.0f)\n\t\t\t\tm_fTireTemperature = 3.0f;\n\t\t}else if(m_fTireTemperature > 1.0f){\n\t\t\tm_fTireTemperature = (m_fTireTemperature - 1.0f)*Pow(0.995f, CTimer::GetTimeStep()) + 1.0f;\n\t\t}\n\n\t\t// Process front wheel - second try\n\n\t\tif(rearWheelsFirst){\n\t\t\tif(m_aWheelTimer[BIKESUSP_F1] > 0.0f || m_aWheelTimer[BIKESUSP_F2] > 0.0f){\n\t\t\t\t// Wheel on ground\n\t\t\t\teBikeWheelSpecial spec;\n\t\t\t\tif(m_aWheelTimer[BIKESUSP_R1] > 0.0f || m_aWheelTimer[BIKESUSP_R2] > 0.0f)\n\t\t\t\t\tspec = BIKE_WHEELSPEC_0;\n\t\t\t\telse\n\t\t\t\t\tspec = BIKE_WHEELSPEC_2;\n\t\t\t\tCVector wheelFwd = GetMatrix() * CVector(-Sin(m_fWheelAngle), Cos(m_fWheelAngle), 0.0f);\n\t\t\t\twheelFwd -= DotProduct(wheelFwd, m_aWheelColPoints[frontLine].normal)*m_aWheelColPoints[frontLine].normal;\n\t\t\t\twheelFwd.Normalise();\n\t\t\t\tCVector wheelRight = CrossProduct(wheelFwd, m_aWheelColPoints[frontLine].normal);\n\t\t\t\twheelRight.Normalise();\n\n\t\t\t\tfThrust = 0.0f;\n\t\t\t\tm_aWheelColPoints[frontLine].surfaceA = SURFACE_WHEELBASE;\n\t\t\t\tfloat adhesion = CSurfaceTable::GetAdhesiveLimit(m_aWheelColPoints[frontLine])*traction;\n\t\t\t\tfloat adhesionDestab = 1.0f;\n\t\t\t\tif(m_fBrakeDestabilization > 0.0f)\n\t\t\t\t\tswitch(CSurfaceTable::GetAdhesionGroup(m_aWheelColPoints[frontLine].surfaceB)){\n\t\t\t\t\tcase ADHESIVE_HARD:\n\t\t\t\t\tcase ADHESIVE_LOOSE:\n\t\t\t\t\t\tadhesionDestab = 0.9f;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase ADHESIVE_ROAD:\n\t\t\t\t\t\tadhesionDestab = 0.7f;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\tif(GetStatus() == STATUS_PLAYER)\n\t\t\t\t\tadhesion *= CSurfaceTable::GetWetMultiplier(m_aWheelColPoints[frontLine].surfaceB);\n\t\t\t\tif(m_wheelStatus[BIKEWHEEL_FRONT] == WHEEL_STATUS_BURST)\n\t\t\t\t\tadhesion *= 0.4f;\n\t\t\t\tWheelState[BIKEWHEEL_FRONT] = m_aWheelState[BIKEWHEEL_FRONT];\n\t\t\t\tCVector contactSpeed = GetSpeed(frontContact);\n\t\t\t\tProcessBikeWheel(wheelFwd, wheelRight,\n\t\t\t\t\tcontactSpeed, frontContact,\n\t\t\t\t\t2, fThrust,\n\t\t\t\t\tbrake*brakeBiasFront,\n\t\t\t\t\tadhesion*tractionBiasFront, adhesionDestab,\n\t\t\t\t\tBIKEWHEEL_FRONT,\n\t\t\t\t\t&m_aWheelSpeed[BIKEWHEEL_FRONT],\n\t\t\t\t\t&WheelState[BIKEWHEEL_FRONT],\n\t\t\t\t\tspec,\n\t\t\t\t\tm_wheelStatus[BIKEWHEEL_FRONT]);\n\t\t\t\tif(bStuckInSand && (WheelState[BIKEWHEEL_FRONT] == WHEEL_STATE_SPINNING || WheelState[BIKEWHEEL_FRONT] == WHEEL_STATE_SKIDDING))\n\t\t\t\t\tWheelState[BIKEWHEEL_FRONT] = WHEEL_STATE_NORMAL;\n\t\t\t}else{\n\t\t\t\t// Wheel in the air\n\t\t\t\tm_aWheelSpeed[BIKEWHEEL_FRONT] *= 0.95f;\n\t\t\t\tm_aWheelRotation[BIKEWHEEL_FRONT] += m_aWheelSpeed[BIKEWHEEL_FRONT];\n\t\t\t}\n\t\t}\n\n\t\t// Process leaning\n\t\tfloat idleAngle = 0.0f;\n\t\tif(pDriver){\n\t\t\tCAnimBlendAssociation *assoc = RpAnimBlendClumpGetAssociation(pDriver->GetClump(), ANIM_BIKE_READY);\n\t\t\tif(assoc)\n\t\t\t\tidleAngle = DEGTORAD(10.0f) * assoc->blendAmount;\n\t\t}\n\t\tif(bBalancedByRider || bIsBeingPickedUp){\n\t\t\tm_vecAvgSurfaceRight = CrossProduct(GetForward(), m_vecAvgSurfaceNormal);\n\t\t\tm_vecAvgSurfaceRight.Normalise();\n\t\t\tfloat lean;\n\t\t\tif(m_nWheelsOnGround == 0)\n\t\t\t\tlean = -(m_fSteerAngle/DEGTORAD(pHandling->fSteeringLock))*0.5f*GRAVITY*CTimer::GetTimeStep();\n\t\t\telse\n\t\t\t\tlean = DotProduct(m_vecMoveSpeed-initialMoveSpeed, m_vecAvgSurfaceRight);\n\t\t\tlean /= GRAVITY*Max(CTimer::GetTimeStep(), 0.01f);\n\t\t\tif(m_wheelStatus[BIKEWHEEL_FRONT] == WHEEL_STATUS_BURST)\n\t\t\t\tlean = clamp(lean, -0.4f*pBikeHandling->fMaxLean, 0.4f*pBikeHandling->fMaxLean);\n\t\t\telse\n\t\t\t\tlean = clamp(lean, -pBikeHandling->fMaxLean, pBikeHandling->fMaxLean);\n\t\t\tfloat f = Pow(pBikeHandling->fDesLean, CTimer::GetTimeStep());\n\t\t\tm_fLeanLRAngle2 = (Asin(lean) - idleAngle)*(1.0f-f) + m_fLeanLRAngle2*f;\n\t\t}else{\n\t\t\tif(bIsStanding){\n\t\t\t\tfloat f = Pow(0.97f, CTimer::GetTimeStep());\n\t\t\t\tm_fLeanLRAngle2 = m_fLeanLRAngle2*f - (Asin(GetRight().z) + DEGTORAD(15.0f) + idleAngle)*(1.0f-f);\n\t\t\t}else{\n\t\t\t\tfloat f = Pow(0.95f, CTimer::GetTimeStep());\n\t\t\t\tm_fLeanLRAngle2 = m_fLeanLRAngle2*f;\n\t\t\t}\n\t\t}\n\t\tm_fLeanLRAngle = m_fLeanLRAngle2;\n\n\t\t// Destabilize steering when braking\n\t\tif((m_aSuspensionSpringRatio[BIKESUSP_F1] < 1.0f || m_aSuspensionSpringRatio[BIKESUSP_F2] < 1.0f) &&\n\t\t   m_fBrakePedal - m_fGasPedal > 0.9f &&\n\t\t   fwdSpeed > 0.02f &&\n\t\t   !bIsHandbrakeOn){\n\t\t\tm_fBrakeDestabilization += CGeneral::GetRandomNumberInRange(0.5f, 1.0f)*0.2f*CTimer::GetTimeStep();\n\t\t\tif(m_aSuspensionSpringRatio[BIKESUSP_R1] < 1.0f || m_aSuspensionSpringRatio[BIKESUSP_R2] < 1.0f){\n\t\t\t\t// BUG: this clamp makes no sense and the arguments seem swapped too\n\t\t\t\tApplyTurnForce(contactPoints[BIKESUSP_R1],\n\t\t\t\t\tm_fTurnMass*Sin(m_fBrakeDestabilization)*clamp(fwdSpeed, 0.5f, 0.2f)*0.013f*GetRight()*CTimer::GetTimeStep());\n\t\t\t}else{\n\t\t\t\t// BUG: this clamp makes no sense and the arguments seem swapped too\n\t\t\t\tApplyTurnForce(contactPoints[BIKESUSP_R1],\n\t\t\t\t\tm_fTurnMass*Sin(m_fBrakeDestabilization)*clamp(fwdSpeed, 0.5f, 0.2f)*0.003f*GetRight()*CTimer::GetTimeStep());\n\t\t\t}\n\t\t}else\n\t\t\tm_fBrakeDestabilization = 0.0f;\n\n\t\t// Update wheel positions from suspension\n\t\tfloat frontWheelPos = colModel->lines[frontLine].p0.z;\n\t\tif(m_aSuspensionSpringRatio[frontLine] > 0.0f)\n\t\t\tfrontWheelPos -= m_aSuspensionSpringRatio[frontLine]*m_aSuspensionSpringLength[frontLine];\n\t\tm_aWheelPosition[BIKEWHEEL_FRONT] += (frontWheelPos - m_aWheelPosition[BIKEWHEEL_FRONT])*0.75f;\n\n\t\tfloat rearWheelPos = colModel->lines[rearLine].p0.z;\n\t\tif(m_aSuspensionSpringRatio[rearLine] > 0.0f)\n\t\t\trearWheelPos -= m_aSuspensionSpringRatio[rearLine]*m_aSuspensionSpringLength[rearLine];\n\t\tm_aWheelPosition[BIKEWHEEL_REAR] += (rearWheelPos - m_aWheelPosition[BIKEWHEEL_REAR])*0.75f;\n\n\t\tfor(i = 0; i < 2; i++)\n\t\t\tm_aWheelState[i] = WheelState[i];\n\t\t// never spin when moving backwards\n\t\tif(m_fGasPedal < 0.0f && m_aWheelState[BIKEWHEEL_REAR] == WHEEL_STATE_SPINNING)\n\t\t\tm_aWheelState[BIKEWHEEL_REAR] = WHEEL_STATE_NORMAL;\n\n\t\t// Process horn\n\n\t\tif(GetStatus() != STATUS_PLAYER){\n#ifdef FIX_BUGS\n\t\t\tif(!IsAlarmOn())\n#endif\n\t\t\t\tReduceHornCounter();\n\t\t}else{\n#ifdef FIX_BUGS\n\t\t\tif(!IsAlarmOn())\n#endif\n\t\t\t{\n\t\t\t\tif(Pads[0].GetHorn())\n\t\t\t\t\tm_nCarHornTimer = 1;\n\t\t\t\telse\n\t\t\t\t\tm_nCarHornTimer = 0;\n\t\t\t}\n\t\t}\n\t}\n\n\tif(m_fHealth < 250.0f && GetStatus() != STATUS_WRECKED){\n\t\t// Car is on fire\n\n\t\tCVector damagePos, fireDir;\n\n\t\t// move fire forward if in first person\n\t\tif(this == FindPlayerVehicle() && TheCamera.GetLookingForwardFirstPerson()){\n\t\t\tdamagePos = CVector(0.0f, 1.2f, -0.4f);\n\t\t\tfireDir = CVector(0.0f, 0.0f, CGeneral::GetRandomNumberInRange(0.01125f, 0.09f));\n\t\t}else{\n\t\t\tdamagePos = ((CVehicleModelInfo*)CModelInfo::GetModelInfo(GetModelIndex()))->m_positions[CAR_POS_BACKSEAT];\n\t\t\tdamagePos.z -= 0.3f;\n\t\t\tfireDir = CGeneral::GetRandomNumberInRange(0.02025f, 0.09f) * GetRight();\n\t\t\tfireDir -= CGeneral::GetRandomNumberInRange(0.02025f, 0.18f) * GetForward();\n\t\t\tfireDir.z = CGeneral::GetRandomNumberInRange(0.00225f, 0.018f);\n\t\t}\n\n\t\tdamagePos = GetMatrix()*damagePos;\n\t\tCParticle::AddParticle(PARTICLE_CARFLAME, damagePos, fireDir,\n\t\t\tnil, 0.9f);\n\n\t\tCParticle::AddParticle(PARTICLE_ENGINE_SMOKE2, damagePos, CVector(0.0f, 0.0f, 0.0f), nil, 0.5f);\n\n\t\tdamagePos.x += CGeneral::GetRandomNumberInRange(-0.5625f, 0.5625f),\n\t\tdamagePos.y += CGeneral::GetRandomNumberInRange(-0.5625f, 0.5625f),\n\t\tdamagePos.z += CGeneral::GetRandomNumberInRange(0.5625f, 2.25f);\n\t\tCParticle::AddParticle(PARTICLE_CARFLAME_SMOKE, damagePos, CVector(0.0f, 0.0f, 0.0f));\n\n\t\t// Blow up car after 5 seconds\n\t\tm_fFireBlowUpTimer += CTimer::GetTimeStepInMilliseconds();\n\t\tif(m_fFireBlowUpTimer > 5000.0f)\n\t\t\tBlowUpCar(m_pSetOnFireEntity);\n\t}else\n\t\tm_fFireBlowUpTimer = 0.0f;\n\n\tProcessDelayedExplosion();\n\n\t// Find out how much to shake the pad depending on suspension and ground surface\n\n\tfloat suspShake = 0.0f;\n\tfloat surfShake = 0.0f;\n\tfloat speedsq = m_vecMoveSpeed.MagnitudeSqr();\n\tfor(i = 0; i < 4; i++){\n\t\tfloat suspChange = m_aSuspensionSpringRatioPrev[i] - m_aSuspensionSpringRatio[i];\n\t\tif(suspChange > 0.3f && (i == BIKESUSP_F1 || i == BIKESUSP_R1) && speedsq > 0.04f){\n\t\t\tif(GetStatus() == STATUS_PLAYER || GetStatus() == STATUS_PHYSICS){\n#ifdef FIX_BUGS\n\t\t\t\t// only two wheels but 4 suspensions\n\t\t\t\tif(m_wheelStatus[i/2] == WHEEL_STATUS_BURST)\n#else\n\t\t\t\tif(m_wheelStatus[i] == WHEEL_STATUS_BURST)\n#endif\n\t\t\t\t\tDMAudio.PlayOneShot(m_audioEntityId, SOUND_CAR_JUMP_2, suspChange);\n\t\t\t\telse\n\t\t\t\t\tDMAudio.PlayOneShot(m_audioEntityId, SOUND_CAR_JUMP, suspChange);\n\t\t\t\tif(suspChange > suspShake)\n\t\t\t\t\tsuspShake = suspChange;\n\t\t\t}\n\t\t}\n\n\t\tif(this == FindPlayerVehicle()){\n\t\t\tuint8 surf = m_aWheelColPoints[i].surfaceB;\n\t\t\tif(surf == SURFACE_GRAVEL || surf == SURFACE_WATER || surf == SURFACE_HEDGE){\n\t\t\t\tif(surfShake < 0.2f)\n\t\t\t\t\tsurfShake = 0.3f;\n\t\t\t}else if(surf == SURFACE_MUD_DRY || surf == SURFACE_SAND || surf == SURFACE_SAND_BEACH){\n\t\t\t\tif(surfShake < 0.1f)\n\t\t\t\t\tsurfShake = 0.2f;\n\t\t\t}else if(surf == SURFACE_GRASS){\n\t\t\t\tif(surfShake < 0.05f)\n\t\t\t\t\tsurfShake = 0.1f;\n\t\t\t}\n\n// BUG: this only observes one of the wheels\n\t\t\tTheCamera.m_bVehicleSuspenHigh = Abs(suspChange) > 0.05f;\n\t\t}\n\n\t\tm_aSuspensionSpringRatioPrev[i] = m_aSuspensionSpringRatio[i];\n\t\tm_aSuspensionSpringRatio[i] = 1.0f;\n\t}\n\n\t// Shake pad\n\n\tif((suspShake > 0.0f || surfShake > 0.0f) && GetStatus() == STATUS_PLAYER){\n\t\tfloat speed = m_vecMoveSpeed.MagnitudeSqr();\n\t\tif(speed > sq(0.1f)){\n\t\t\tspeed = Sqrt(speed);\n\t\t\tif(suspShake > 0.0f){\n\t\t\t\tuint8 freq = Min(200.0f*suspShake*speed*2000.0f/m_fMass + 100.0f, 250.0f);\n\t\t\t\tCPad::GetPad(0)->StartShake(20000.0f*CTimer::GetTimeStep()/freq, freq);\n\t\t\t}else{\n\t\t\t\tuint8 freq = Min(200.0f*surfShake*speed*2000.0f/m_fMass + 40.0f, 150.0f);\n\t\t\t\tCPad::GetPad(0)->StartShake(5000.0f*CTimer::GetTimeStep()/freq, freq);\n\t\t\t}\n\t\t}\n\t}\n\n\tbVehicleColProcessed = false;\n\tbAudioChangingGear = false;\n\n\tif(!bWarnedPeds)\n\t\tCCarCtrl::ScanForPedDanger(this);\n\n\tif(bInfiniteMass){\n\t\tm_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);\n\t\tm_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f);\n\t\tm_vecMoveFriction = CVector(0.0f, 0.0f, 0.0f);\n\t\tm_vecTurnFriction = CVector(0.0f, 0.0f, 0.0f);\n\t}else if(!skipPhysics &&\n\t         (acceleration == 0.0f && brake == 0.0f || GetStatus() == STATUS_WRECKED)){\n\t\tif(Abs(m_vecMoveSpeed.x) < 0.005f &&\n\t\t   Abs(m_vecMoveSpeed.y) < 0.005f &&\n\t\t   Abs(m_vecMoveSpeed.z) < 0.005f){\n\t\t\tm_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);\n\t\t\tm_vecTurnSpeed.z = 0.0f;\n\t\t}\n\t}\n\n\t// Balance bike\n\tif(bBalancedByRider || bIsBeingPickedUp || bIsStanding){\n\t\tfloat onSideness = DotProduct(GetRight(), m_vecAvgSurfaceNormal);\n\t\tonSideness = clamp(onSideness, -1.0f, 1.0f);\n\t\tCVector worldCOM = Multiply3x3(GetMatrix(), m_vecCentreOfMass);\n\t\t// Keep bike upright\n\t\tif(bBalancedByRider){\n\t\t\tApplyTurnForce(-0.07f*onSideness*m_fTurnMass*GetUp()*CTimer::GetTimeStep(), worldCOM+GetRight());\n\t\t\tbIsStanding = false;\n\t\t}else\n\t\t\tApplyTurnForce(-0.1f*onSideness*m_fTurnMass*GetUp()*CTimer::GetTimeStep(), worldCOM+GetRight());\n\n\t\t// Wheelie/Stoppie stabilization\n\t\tif(GetStatus() == STATUS_PLAYER){\n\t\t\tif(m_aWheelTimer[BIKESUSP_F1] == 0.0f && m_aWheelTimer[BIKESUSP_F2] == 0.0f && GetForward().z > 0.0 &&\n\t\t\t   !(m_aWheelTimer[BIKESUSP_R1] == 0.0f && m_aWheelTimer[BIKESUSP_R2] == 0.0f)){\n\t\t\t\t// Wheelie\n\t\t\t\tfloat wheelie = pBikeHandling->fWheelieAng - GetForward().z;\n\t\t\t\tif(wheelie > 0.15f)\n\t\t\t\t\t// below wheelie angle\n\t\t\t\t\twheelie = Max(0.3f - wheelie, 0.0f);\n\t\t\t\telse if(wheelie < -0.08f)\n\t\t\t\t\t// above wheelie angle\n\t\t\t\t\twheelie = Min(-0.15f - wheelie, 0.0f);\n\t\t\t\tfloat wheelieStab = pBikeHandling->fWheelieStabMult * Min(m_vecMoveSpeed.Magnitude(), 0.1f) * wheelie;\n\t\t\t\tApplyTurnForce(0.5f*CTimer::GetTimeStep()*wheelieStab*m_fTurnMass*GetUp(), worldCOM+GetForward());\n\t\t\t\tApplyTurnForce(0.5f*CTimer::GetTimeStep()*m_fWheelAngle*pBikeHandling->fWheelieSteer*m_fTurnMass*GetRight(), worldCOM+GetForward());\n\t\t\t}else if(m_aWheelTimer[BIKESUSP_R1] == 0.0f && m_aWheelTimer[BIKESUSP_R2] == 0.0f && GetForward().z < 0.0 &&\n\t\t\t         !(m_aWheelTimer[BIKESUSP_F1] == 0.0f && m_aWheelTimer[BIKESUSP_F2] == 0.0f)){\n\t\t\t\t// Stoppie\n\t\t\t\tfloat stoppie = pBikeHandling->fStoppieAng - GetForward().z;\n\t\t\t\tif(stoppie > 0.15f)\n\t\t\t\t\t// below stoppie angle\n\t\t\t\t\tstoppie = Max(0.3f - stoppie, 0.0f);\n\t\t\t\telse if(stoppie < -0.15f)\n\t\t\t\t\t// above stoppie angle\n\t\t\t\t\tstoppie = Min(-0.3f - stoppie, 0.0f);\n\t\t\t\tfloat speed = m_vecMoveSpeed.Magnitude();\n\t\t\t\tfloat stoppieStab = pBikeHandling->fStoppieStabMult * Min(speed, 0.1f) * stoppie;\n\t\t\t\tApplyTurnForce(0.5f*CTimer::GetTimeStep()*stoppieStab*m_fTurnMass*GetUp(), worldCOM+GetForward());\n\t\t\t\tApplyTurnForce(0.5f*Min(5.0f*speed,1.0f)*CTimer::GetTimeStep()*m_fWheelAngle*pBikeHandling->fWheelieSteer*m_fTurnMass*GetRight(), worldCOM+GetForward());\n\t\t\t}\n\t\t}\n\t}\n}\n\n#pragma optimize(\"\", on)\n\nvoid\nCBike::Teleport(CVector pos)\n{\n\tCWorld::Remove(this);\n\n\tSetPosition(pos);\n\tSetOrientation(0.0f, 0.0f, 0.0f);\n\tSetMoveSpeed(0.0f, 0.0f, 0.0f);\n\tSetTurnSpeed(0.0f, 0.0f, 0.0f);\n\n\tResetSuspension();\n\n\tCWorld::Add(this);\n}\n\nvoid\nCBike::PreRender(void)\n{\n\tint i;\n\tCVehicleModelInfo *mi = (CVehicleModelInfo*)CModelInfo::GetModelInfo(GetModelIndex());\n\n\t// Wheel particles\n\n\tif(m_aWheelState[BIKEWHEEL_REAR] != WHEEL_STATE_NORMAL &&\n\t   m_aWheelColPoints[BIKESUSP_R2].surfaceB != SURFACE_WATER && m_aWheelTimer[BIKESUSP_R2] > 0.0f){\n\t\tstatic float smokeSize = 0.2f;\n\t\tCVector groundPos = m_aWheelColPoints[BIKESUSP_R2].point;\n\t\tif(m_aSuspensionSpringRatioPrev[BIKESUSP_R1] < 1.0f)\n\t\t\tgroundPos = (groundPos + m_aWheelColPoints[BIKESUSP_R1].point)/2.0f;\n\t\tgroundPos += Sin(m_fLeanLRAngle) * 0.8f*GetColModel()->boundingBox.min.z * GetRight();\n\t\tCParticle::AddParticle(PARTICLE_RUBBER_SMOKE,\n\t\t\tgroundPos + CVector(0.0f, 0.0f, 0.25f), CVector(0.0f, 0.0f, 0.0f),\n\t\t\tnil, smokeSize);\n\n\t\tCSkidmarks::RegisterOne((uintptr)this, groundPos, GetForward().x, GetForward().y,\n\t\t\tm_aWheelSkidmarkType[BIKEWHEEL_REAR], &m_aWheelSkidmarkBloody[BIKEWHEEL_REAR]);\n\n\t\tif(m_aWheelState[BIKEWHEEL_REAR] == WHEEL_STATE_SPINNING &&\n\t\t   (CSurfaceTable::GetAdhesionGroup(m_aWheelColPoints[BIKESUSP_R2].surfaceB) == ADHESIVE_HARD ||\n\t\t    CSurfaceTable::GetAdhesionGroup(m_aWheelColPoints[BIKESUSP_R2].surfaceB) == ADHESIVE_ROAD)){\n\t\t\tCParticle::AddParticle(PARTICLE_BURNINGRUBBER_SMOKE,\n\t\t\t\tgroundPos + CVector(0.0f, 0.0f, 0.25f),\n\t\t\t\tCVector(0.0f, 0.0f, 0.0f));\n\t\t\tCParticle::AddParticle(PARTICLE_BURNINGRUBBER_SMOKE,\n\t\t\t\tgroundPos + CVector(0.0f, 0.0f, 0.25f),\n\t\t\t\tCVector(0.0f, 0.0f, 0.05f));\n\t\t}\n\t}else if(m_aWheelSkidmarkBloody[BIKEWHEEL_REAR] || m_aWheelSkidmarkUnk[BIKEWHEEL_REAR]){\n\t\tCVector groundPos = m_aWheelColPoints[BIKESUSP_R2].point;\n\t\tgroundPos += Sin(m_fLeanLRAngle) * 0.8f*GetColModel()->boundingBox.min.z * GetRight();\n\n\t\tCSkidmarks::RegisterOne((uintptr)this, groundPos, GetForward().x, GetForward().y,\n\t\t\tm_aWheelSkidmarkType[BIKEWHEEL_REAR], &m_aWheelSkidmarkBloody[BIKEWHEEL_REAR]);\n\t}\n\n\t// Process lights\n\n\t// Turn lights on/off\n\tbool shouldLightsBeOn = \n\t\tCClock::GetHours() > 20 ||\n\t\tCClock::GetHours() > 19 && CClock::GetMinutes() > (m_randomSeed & 0x3F) ||\n\t\tCClock::GetHours() < 7 ||\n\t\tCClock::GetHours() < 8 && CClock::GetMinutes() < (m_randomSeed & 0x3F) ||\n\t\tm_randomSeed/50000.0f < CWeather::Foggyness ||\n\t\tm_randomSeed/50000.0f < CWeather::WetRoads;\n\tif(shouldLightsBeOn != bLightsOn && GetStatus() != STATUS_WRECKED){\n\t\tif(GetStatus() == STATUS_ABANDONED){\n\t\t\t// Turn off lights on abandoned vehicles only when we they're far away\n\t\t\tif(bLightsOn &&\n\t\t\t   Abs(TheCamera.GetPosition().x - GetPosition().x) + Abs(TheCamera.GetPosition().y - GetPosition().y) > 100.0f)\n\t\t\t\tbLightsOn = false;\n\t\t}else\n\t\t\tbLightsOn = shouldLightsBeOn;\n\t}\n\n\t// Actually render the lights\n\tbool alarmOn = false;\n\tbool alarmOff = false;\n\tif(IsAlarmOn()){\n\t\tif(CTimer::GetTimeInMilliseconds() & 0x100)\n\t\t\talarmOn = true;\n\t\telse\n\t\t\talarmOff = true;\n\t}\n\tif(bEngineOn && bLightsOn || alarmOn || alarmOff){\n\t\tCalculateLeanMatrix();\n\t\tCVector lookVector = GetPosition() - TheCamera.GetPosition();\n\t\tfloat camDist = lookVector.Magnitude();\n\t\tif(camDist != 0.0f)\n\t\t\tlookVector *= 1.0f/camDist;\n\t\telse\n\t\t\tlookVector = CVector(1.0f, 0.0f, 0.0f);\n\n\t\t// 1.0 if directly behind car, -1.0 if in front\n\t\tfloat behindness = DotProduct(lookVector, GetForward());\n\t\t// 0.0 if behind car, PI if in front\n\t\tfloat angle = Abs(Acos(Abs(behindness)));\n\n\t\t// Headlight\n\n\t\tCMatrix mat;\n\t\tCVector headLightPos = mi->m_positions[CAR_POS_HEADLIGHTS];\n\t\tif(GetModelIndex() == 152){\t// this is the bobcat in VC, but we don't want that effect anyway\n\t\t\tmat.SetUnity();\n\t\t\tmat.RotateZ(m_fWheelAngle);\n\t\t\tmat = m_leanMatrix * mat;\n\t\t}else\n\t\t\tmat = m_leanMatrix;\n\t\tCVector light = mat * headLightPos;\n\t\tif(behindness < 0.0f){\n\t\t\t// In front of bike\n\t\t\tfloat intensity = -0.5f*behindness + 0.3f;\n\t\t\tfloat size = 1.0f - behindness;\n\n\t\t\tif(behindness < -0.97f && camDist < 30.0f){\n\t\t\t\t// Directly in front and not too far away\n\t\t\t\tif(pHandling->Flags & HANDLING_HALOGEN_LIGHTS){\n\t\t\t\t\tCCoronas::RegisterCorona((uintptr)this + 6, 150, 150, 195, 255,\n\t\t\t\t\t\tlight, 1.2f, 45.0f*TheCamera.LODDistMultiplier,\n\t\t\t\t\t\tCCoronas::TYPE_HEADLIGHT, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON,\n\t\t\t\t\t\tCCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, angle);\n\t\t\t\t}else{\n\t\t\t\t\tCCoronas::RegisterCorona((uintptr)this + 6, 160, 160, 140, 255,\n\t\t\t\t\t\tlight, 1.2f, 45.0f*TheCamera.LODDistMultiplier,\n\t\t\t\t\t\tCCoronas::TYPE_HEADLIGHT, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON,\n\t\t\t\t\t\tCCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, angle);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif(alarmOff){\n\t\t\t\tCCoronas::RegisterCorona((uintptr)this, 0, 0, 0, 0,\n\t\t\t\t\tlight, size, 0.0f,\n\t\t\t\t\tCCoronas::TYPE_STREAK, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON,\n\t\t\t\t\tCCoronas::LOSCHECK_OFF, CCoronas::STREAK_ON, angle);\n\t\t\t}else{\n\t\t\t\tif(pHandling->Flags & HANDLING_HALOGEN_LIGHTS){\n\t\t\t\t\tCCoronas::RegisterCorona((uintptr)this + 1, 190*intensity, 190*intensity, 255*intensity, 255,\n\t\t\t\t\t\tlight, size, 50.0f*TheCamera.LODDistMultiplier,\n\t\t\t\t\t\tCCoronas::TYPE_STREAK, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON,\n\t\t\t\t\t\tCCoronas::LOSCHECK_OFF, CCoronas::STREAK_ON, angle);\n\t\t\t\t}else{\n\t\t\t\t\tCCoronas::RegisterCorona((uintptr)this + 1, 210*intensity, 210*intensity, 195*intensity, 255,\n\t\t\t\t\t\tlight, size, 50.0f*TheCamera.LODDistMultiplier,\n\t\t\t\t\t\tCCoronas::TYPE_STREAK, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON,\n\t\t\t\t\t\tCCoronas::LOSCHECK_OFF, CCoronas::STREAK_ON, angle);\n\t\t\t\t}\n\t\t\t}\n\t\t}else{\n\t\t\tCCoronas::UpdateCoronaCoors((uintptr)this, light, 50.0f*TheCamera.LODDistMultiplier, angle);\n\t\t}\n\n\t\t// bright light\n\t\tCBrightLights::RegisterOne(light, GetUp(), GetRight(), GetForward(), pHandling->FrontLights + BRIGHTLIGHT_FRONT);\n\n\t\t// Taillight\n\n\t\tCVector tailLightPos = mi->m_positions[CAR_POS_TAILLIGHTS];\n\t\tlight = m_leanMatrix * tailLightPos;\n\n\t\t// Taillight corona\n\t\tif(behindness > 0.0f){\n\t\t\t// Behind car\n\t\t\tfloat intensity = 0.4f*behindness + 0.4f;\n\t\t\tfloat size = (behindness + 1.0f)/2.0f;\n\n\t\t\tif(m_fGasPedal < 0.0f){\n\t\t\t\t// reversing\n\t\t\t\t// no lights in this case\n\t\t\t}else{\n\t\t\t\tif(m_fBrakePedal > 0.0f){\n\t\t\t\t\tintensity += 0.4f;\n\t\t\t\t\tsize += 0.3f;\n\t\t\t\t}\n\n\t\t\t\tif(alarmOff){\n\t\t\t\t\tCCoronas::RegisterCorona((uintptr)this + 14, 0, 0, 0, 0,\n\t\t\t\t\t\tlight, size, 0.0f,\n\t\t\t\t\t\tCCoronas::TYPE_STREAK, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON,\n\t\t\t\t\t\tCCoronas::LOSCHECK_OFF, CCoronas::STREAK_ON, angle);\n\t\t\t\t}else{\n\t\t\t\t\tCCoronas::RegisterCorona((uintptr)this + 14, 128*intensity, 0, 0, 255,\n\t\t\t\t\t\tlight, size, 50.0f*TheCamera.LODDistMultiplier,\n\t\t\t\t\t\tCCoronas::TYPE_STREAK, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON,\n\t\t\t\t\t\tCCoronas::LOSCHECK_OFF, CCoronas::STREAK_ON, angle);\n\t\t\t\t}\n\t\t\t}\n\t\t}else{\n\t\t\tCCoronas::UpdateCoronaCoors((uintptr)this + 14, light, 50.0f*TheCamera.LODDistMultiplier, angle);\n\t\t}\n\n\t\t// bright light\n\t\tCBrightLights::RegisterOne(light, GetUp(), GetRight(), GetForward(), pHandling->RearLights + BRIGHTLIGHT_REAR);\n\n\t\t// Light shadows\n\t\tif(!alarmOff){\n\t\t\tCVector pos = GetPosition();\n\t\t\tCVector2D fwd(GetForward());\n\t\t\tfwd.Normalise();\n\t\t\tfloat f = headLightPos.y + 6.0f;\n\t\t\tpos += CVector(f*fwd.x, f*fwd.y, 2.0f);\n\t\t\tCShadows::StoreCarLightShadow(this, (uintptr)this + 22, gpShadowExplosionTex, &pos,\n\t\t\t\t7.0f*fwd.x, 7.0f*fwd.y, 3.5f*fwd.y, -3.5f*fwd.x, 45, 45, 45, 7.0f);\n\n\t\t\tf = (tailLightPos.y - 2.5f) - (headLightPos.y + 6.0f);\n\t\t\tpos += CVector(f*fwd.x, f*fwd.y, 0.0f);\n\t\t\tCShadows::StoreCarLightShadow(this, (uintptr)this + 25, gpShadowExplosionTex, &pos,\n\t\t\t\t3.0f, 0.0f, 0.0f, -3.0f, 35, 0, 0, 4.0f);\n\t\t}\n\n\t\tif(this == FindPlayerVehicle() && !alarmOff){\n\t\t\tCPointLights::AddLight(CPointLights::LIGHT_DIRECTIONAL, GetPosition(), GetForward(),\n\t\t\t\t20.0f, 1.0f, 1.0f, 1.0f,\n\t\t\t\tFindPlayerVehicle()->m_vecMoveSpeed.MagnitudeSqr2D() < sq(0.45f) ? CPointLights::FOG_NORMAL : CPointLights::FOG_NONE,\n\t\t\t\tfalse);\n\t\t\tCVector pos = GetPosition() - 4.0f*GetForward();\n\t\t\tif(m_fBrakePedal > 0.0f)\n\t\t\t\tCPointLights::AddLight(CPointLights::LIGHT_POINT, pos, CVector(0.0f, 0.0f, 0.0f),\n\t\t\t\t\t10.0f, 1.0f, 0.0f, 0.0f,\n\t\t\t\t\tCPointLights::FOG_NONE, false);\n\t\t\telse\n\t\t\t\tCPointLights::AddLight(CPointLights::LIGHT_POINT, pos, CVector(0.0f, 0.0f, 0.0f),\n\t\t\t\t\t7.0f, 0.6f, 0.0f, 0.0f,\n\t\t\t\t\tCPointLights::FOG_NONE, false);\n\t\t}\n\t}else if(GetStatus() != STATUS_ABANDONED && GetStatus() != STATUS_WRECKED){\n\t\t// Lights off\n\t\tCalculateLeanMatrix();\n\n\t\tCVector tailLightPos = mi->m_positions[CAR_POS_TAILLIGHTS];\n\t\tCVector light = m_leanMatrix * tailLightPos;\n\n\t\tif(m_fBrakePedal > 0.0f || m_fGasPedal < 0.0f){\n\t\t\tCVector lookVector = GetPosition() - TheCamera.GetPosition();\n\t\t\tlookVector.Normalise();\n\t\t\tfloat behindness = DotProduct(lookVector, GetForward());\n\t\t\tif(behindness > 0.0f){\n\t\t\t\tif(m_fGasPedal < 0.0f){\n\t\t\t\t\t// reversing\n\t\t\t\t\t// no lights in this case\n\t\t\t\t}else{\n\t\t\t\t\t// braking\n\t\t\t\t\tCCoronas::RegisterCorona((uintptr)this + 14, 120, 0, 0, 255,\n\t\t\t\t\t\tlight, 1.2f, 50.0f*TheCamera.LODDistMultiplier,\n\t\t\t\t\t\tCCoronas::TYPE_STAR, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON,\n\t\t\t\t\t\tCCoronas::LOSCHECK_OFF, CCoronas::STREAK_ON, 0.0f);\n\t\t\t\t\tCBrightLights::RegisterOne(light, GetUp(), GetRight(), GetForward(), pHandling->RearLights + BRIGHTLIGHT_REAR);\n\t\t\t\t}\n\t\t\t}else{\n\t\t\t\tCCoronas::UpdateCoronaCoors((uintptr)this + 14, light, 50.0f*TheCamera.LODDistMultiplier, 0.0f);\n\t\t\t}\n\t\t}else{\n\t\t\tCCoronas::UpdateCoronaCoors((uintptr)this + 14, light, 50.0f*TheCamera.LODDistMultiplier, 0.0f);\n\t\t}\n\t}\n\n\n\t// Wheel particles\n\n\tfloat fwdSpeed = DotProduct(m_vecMoveSpeed, GetForward())*180.0f;\n\tint drawParticles = Abs(fwdSpeed) < 90.0f;\n\tint susp = BIKESUSP_F1;\n\tfor(i = 0; i < 2; i++){\n\t\tif(i == BIKEWHEEL_REAR)\n\t\t\tsusp = BIKESUSP_R1;\n\n\t\tstatic float speedSq;\n\t\t// Sparks for friction of burst wheels\n\t\tif(m_wheelStatus[i] == WHEEL_STATUS_BURST && m_aSuspensionSpringRatioPrev[susp] < 1.0f &&\n\t\t   (speedSq = m_vecMoveSpeed.MagnitudeSqr(), speedSq > SQR(0.1f)) &&\n\t\t   m_aWheelColPoints[susp].surfaceB != SURFACE_GRASS &&\n\t\t   m_aWheelColPoints[susp].surfaceB != SURFACE_MUD_DRY &&\n\t\t   m_aWheelColPoints[susp].surfaceB != SURFACE_SAND &&\n\t\t   m_aWheelColPoints[susp].surfaceB != SURFACE_SAND_BEACH){\n\t\t\tCVector normalSpeed = m_aWheelColPoints[susp].normal * DotProduct(m_aWheelColPoints[susp].normal, m_vecMoveSpeed);\n\t\t\tCVector frictionSpeed = m_vecMoveSpeed - normalSpeed;\n\t\t\tCVector sparkDir = 0.25f*frictionSpeed;\n\t\t\tCParticle::AddParticle(PARTICLE_SPARK_SMALL, m_aWheelColPoints[susp].point, sparkDir);\n\n\t\t\tif(speedSq > 0.04f)\n\t\t\t\tCParticle::AddParticle(PARTICLE_SPARK_SMALL, m_aWheelColPoints[susp].point, sparkDir);\n\t\t\tif(speedSq > 0.16f){\n\t\t\t\tCParticle::AddParticle(PARTICLE_SPARK_SMALL, m_aWheelColPoints[susp].point, sparkDir);\n\t\t\t\tCParticle::AddParticle(PARTICLE_SPARK_SMALL, m_aWheelColPoints[susp].point, sparkDir);\n\t\t\t}\n\t\t}else if(m_aSuspensionSpringRatioPrev[i] < 1.0f &&\n\t\t         (fwdSpeed > 0.2f || m_aWheelState[i] == WHEEL_STATE_SPINNING)){\n\t\t\tif(m_aWheelColPoints[susp].surfaceB == SURFACE_GRASS ||\n\t\t\t   m_aWheelColPoints[susp].surfaceB == SURFACE_MUD_DRY ||\n\t\t\t   m_aWheelColPoints[susp].surfaceB == SURFACE_SAND ||\n\t\t\t   m_aWheelColPoints[susp].surfaceB == SURFACE_SAND_BEACH)\n\t\t\t\tAddWheelDirtAndWater(&m_aWheelColPoints[susp], drawParticles);\n\t\t}\n\t}\n\n\tAddDamagedVehicleParticles();\n\tCShadows::StoreShadowForVehicle(this, VEH_SHD_TYPE_BIKE);\n\n\tCMatrix mat;\n\tCVector pos;\n\tCColModel *colModel = mi->GetColModel();\n\n\t// Wheel rotation\n\tCVector frontWheelFwd = Multiply3x3(GetMatrix(), CVector(-Sin(m_fSteerAngle), Cos(m_fSteerAngle), 0.0f));\n\tCVector rearWheelFwd = GetForward();\n\tif(m_aWheelTimer[BIKESUSP_F1] > 0.0f || m_aWheelTimer[BIKESUSP_F2] > 0.0f){\n\t\tfloat springRatio = Min(m_aSuspensionSpringRatioPrev[BIKESUSP_F1], m_aSuspensionSpringRatioPrev[BIKESUSP_F2]);\n\t\tCVector contactPoint(0.0f,\n\t\t\t(colModel->lines[BIKESUSP_F1].p0.y - colModel->lines[BIKESUSP_F2].p0.y)/2.0f,\n\t\t\tcolModel->lines[BIKESUSP_F1].p0.z - m_aSuspensionSpringLength[BIKESUSP_F1]*springRatio - 0.5f*mi->m_wheelScale);\n\t\tCVector contactSpeed = GetSpeed(contactPoint);\n\t\t// Why is wheel state always normal?\n\t\tm_aWheelSpeed[BIKEWHEEL_FRONT] = ProcessWheelRotation(WHEEL_STATE_NORMAL, frontWheelFwd, contactSpeed, 0.5f*mi->m_wheelScale);\n\t\tm_aWheelRotation[BIKEWHEEL_FRONT] += m_aWheelSpeed[BIKEWHEEL_FRONT];\n\t}\n\tif(m_aWheelTimer[BIKESUSP_R1] > 0.0f || m_aWheelTimer[BIKESUSP_R2] > 0.0f){\n\t\tfloat springRatio = Min(m_aSuspensionSpringRatioPrev[BIKESUSP_R1], m_aSuspensionSpringRatioPrev[BIKESUSP_R2]);\n\t\tCVector contactPoint(0.0f,\n\t\t\t(colModel->lines[BIKESUSP_R1].p0.y - colModel->lines[BIKESUSP_R2].p0.y)/2.0f,\n\t\t\tcolModel->lines[BIKESUSP_R1].p0.z - m_aSuspensionSpringLength[BIKESUSP_R1]*springRatio - 0.5f*mi->m_wheelScale);\n\t\tCVector contactSpeed = GetSpeed(contactPoint);\n\t\tm_aWheelSpeed[BIKEWHEEL_REAR] = ProcessWheelRotation(m_aWheelState[BIKEWHEEL_REAR], rearWheelFwd, contactSpeed, 0.5f*mi->m_wheelScale);\n\t\tm_aWheelRotation[BIKEWHEEL_REAR] += m_aWheelSpeed[BIKEWHEEL_REAR];\n\t}\n\n\t// Front fork\n\tif(m_aBikeNodes[BIKE_FORKS_FRONT]){\n\t\tmat.Attach(RwFrameGetMatrix(m_aBikeNodes[BIKE_FORKS_FRONT]));\n\t\tpos = mat.GetPosition();\n\n\t\tRwMatrix rwrot;\n\t\t// TODO: this looks like some weird ctor we don't have\n\t\tCMatrix rot;\n\t\trot.m_attachment = &rwrot;\n\t\trot.SetUnity();\n\t\trot.UpdateRW();\n\n\t\t// Make rotation matrix with front fork as axis\n\t\tCVector forkAxis(0.0f, Sin(DEGTORAD(mi->m_bikeSteerAngle)), -Cos(DEGTORAD(mi->m_bikeSteerAngle)));\n\t\tforkAxis.Normalise();\t// as if that's not already the case\n\t\tCQuaternion quat;\n\t\tquat.Set(&forkAxis, -m_fWheelAngle);\n\t\tquat.Get(rot.m_attachment);\n\t\trot.Update();\n\n\t\t// Transform fork\n\t\tmat.SetUnity();\n\t\tmat = mat * rot;\n\t\tmat.Translate(pos);\n\t\tmat.UpdateRW();\n\n\t\tif(m_aBikeNodes[BIKE_HANDLEBARS]){\n\t\t\t// Transform handle\n\t\t\tmat.Attach(RwFrameGetMatrix(m_aBikeNodes[BIKE_HANDLEBARS]));\n\t\t\tpos = mat.GetPosition();\n\t\t\tif(GetStatus() == STATUS_ABANDONED || GetStatus() == STATUS_WRECKED){\n\t\t\t\tmat.SetUnity();\n\t\t\t\tmat = mat * rot;\n\t\t\t\tmat.Translate(pos);\n\t\t\t}else\n\t\t\t\tmat.SetTranslate(mat.GetPosition());\n\t\t\tmat.UpdateRW();\n\t\t}\n\t}\n\n\t// Rear fork\n\tif(m_aBikeNodes[BIKE_FORKS_REAR]){\n\t\tfloat sine = (m_aWheelPosition[BIKEWHEEL_REAR] - m_aWheelBasePosition[BIKEWHEEL_REAR])/m_fRearForkLength;\n\t\tmat.Attach(RwFrameGetMatrix(m_aBikeNodes[BIKE_FORKS_REAR]));\n\t\tpos = mat.GetPosition();\n\t\tmat.SetRotate(-Asin(sine), 0.0f, 0.0f);\n\t\tmat.Translate(pos);\n\t\tmat.UpdateRW();\n\t}\n\n\t// Front wheel\n\tmat.Attach(RwFrameGetMatrix(m_aBikeNodes[BIKE_WHEEL_FRONT]));\n\tpos.x = mat.GetPosition().x;\n\tpos.z = m_aWheelPosition[BIKEWHEEL_FRONT] - m_fFrontForkZ;\n\tfloat y = (colModel->lines[BIKESUSP_F1].p0.y+colModel->lines[BIKESUSP_F2].p0.y)/2.0f - m_fFrontForkY;\n\tpos.y = y - (m_aWheelPosition[BIKEWHEEL_FRONT] - m_aWheelBasePosition[BIKEWHEEL_FRONT])*m_fFrontForkSlope;\n\tif(m_wheelStatus[BIKEWHEEL_FRONT] == WHEEL_STATUS_BURST)\n\t\tmat.SetRotate(m_aWheelRotation[BIKEWHEEL_FRONT], 0.0f, 0.05f*Sin(m_aWheelRotation[BIKEWHEEL_FRONT]));\n\telse\n\t\tmat.SetRotateX(m_aWheelRotation[BIKEWHEEL_FRONT]);\n\tmat.Translate(pos);\n\tmat.UpdateRW();\n\t// and mudguard\n\tmat.Attach(RwFrameGetMatrix(m_aBikeNodes[BIKE_MUDGUARD]));\n\tmat.SetTranslateOnly(pos);\n\tmat.UpdateRW();\n\n\t// Rear wheel\n\tmat.Attach(RwFrameGetMatrix(m_aBikeNodes[BIKE_WHEEL_REAR]));\n\tpos = mat.GetPosition();\n\tif(m_wheelStatus[BIKEWHEEL_REAR] == WHEEL_STATUS_BURST)\n\t\tmat.SetRotate(m_aWheelRotation[BIKEWHEEL_REAR], 0.0f, 0.07f*Sin(m_aWheelRotation[BIKEWHEEL_REAR]));\n\telse\n\t\tmat.SetRotateX(m_aWheelRotation[BIKEWHEEL_REAR]);\n\tmat.Translate(pos);\n\tmat.UpdateRW();\n\n\t// Chassis\n\tif(m_aBikeNodes[BIKE_CHASSIS]){\n\t\tmat.Attach(RwFrameGetMatrix(m_aBikeNodes[BIKE_CHASSIS]));\n\t\tpos = mat.GetPosition();\n\t\tpos.z = (1.0f - Cos(m_fLeanLRAngle)) * (0.9*colModel->boundingBox.min.z);\n\t\tmat.SetRotateX(-0.05f*Abs(m_fLeanLRAngle));\n\t\tmat.RotateY(m_fLeanLRAngle);\n\t\tmat.Translate(pos);\n\t\tmat.UpdateRW();\n\t}\n\n\t// Exhaust smoke\n\tif(bEngineOn && !(pHandling->Flags & HANDLING_NO_EXHAUST) && fwdSpeed < 130.0f){\n\t\tCVector exhaustPos = mi->m_positions[CAR_POS_EXHAUST];\n\t\tCVector pos1, pos2, dir;\n\n\t\tif(exhaustPos != CVector(0.0f, 0.0f, 0.0f)){\n\t\t\tdir.z = 0.0f;\n\t\t\tif(fwdSpeed < 10.0f){\n\t\t\t\tCVector steerFwd(-Sin(m_fSteerAngle), Cos(m_fSteerAngle), 0.0f);\n\t\t\t\tsteerFwd = Multiply3x3(GetMatrix(), steerFwd);\n\t\t\t\tfloat r = CGeneral::GetRandomNumberInRange(-0.06f, -0.03f);\n\t\t\t\tdir.x = steerFwd.x * r;\n\t\t\t\tdir.y = steerFwd.y * r;\n\t\t\t}else{\n\t\t\t\tdir.x = m_vecMoveSpeed.x;\n\t\t\t\tdir.y = m_vecMoveSpeed.y;\n\t\t\t}\n\n\t\t\tbool dblExhaust = false;\n\t\t\tpos1 = GetMatrix() * exhaustPos;\n\t\t\tif(pHandling->Flags & HANDLING_DBL_EXHAUST){\n\t\t\t\tdblExhaust = true;\n\t\t\t\tpos2 = exhaustPos;\n\t\t\t\tpos2.x = -pos2.x;\n\t\t\t\tpos2 = GetMatrix() * pos2;\n\t\t\t}\n\n\t\t\tstatic float fumesLimit = 2.0f;\n\t\t\tif(CGeneral::GetRandomNumberInRange(1.0f, 3.0f)*(m_fGasPedal+1.1f) > fumesLimit){\n\t\t\t\tCParticle::AddParticle(PARTICLE_EXHAUST_FUMES, pos1, dir);\n\t\t\t\tif(dblExhaust)\n\t\t\t\t\tCParticle::AddParticle(PARTICLE_EXHAUST_FUMES, pos2, dir);\n\n\t\t\t\tif(GetStatus() == STATUS_PLAYER && (CTimer::GetFrameCounter()&3) == 0 &&\n\t\t\t\t   CWeather::Rain == 0.0f){\n\t\t\t\t\tCVector camDist = GetPosition() - TheCamera.GetPosition();\n\t\t\t\t\tif(DotProduct(GetForward(), camDist) > 0.0f ||\n\t\t\t\t\t   TheCamera.GetLookDirection() == LOOKING_LEFT ||\n\t\t\t\t\t   TheCamera.GetLookDirection() == LOOKING_RIGHT){\n\t\t\t\t\t\tif(dblExhaust)\n\t\t\t\t\t\t\tpos1 = 0.5f*pos1 + 0.5f*pos2;\n\n\t\t\t\t\t\tif(TheCamera.GetLookDirection() == LOOKING_LEFT ||\n\t\t\t\t\t\t   TheCamera.GetLookDirection() == LOOKING_RIGHT)\n\t\t\t\t\t\t\tpos1 -= 0.2f*GetForward();\n\n\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_HEATHAZE, pos1, CVector(0.0f, 0.0f, 0.0f));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nCBike::Render(void)\n{\n\tCVehicleModelInfo *mi = (CVehicleModelInfo*)CModelInfo::GetModelInfo(GetModelIndex());\n\n\tm_nSetPieceExtendedRangeTime = CTimer::GetTimeInMilliseconds() + 3000;\n\tmi->SetVehicleColour(m_currentColour1, m_currentColour2);\n\tCEntity::Render();\n}\n\nint32\nCBike::ProcessEntityCollision(CEntity *ent, CColPoint *colpoints)\n{\n\tint i;\n\tCColModel *colModel;\n\n\tif(GetStatus() != STATUS_SIMPLE)\n\t\tbVehicleColProcessed = true;\n\n\tcolModel = GetColModel();\n\n\tint numWheelCollisions = 0;\n\tfloat prevRatios[4] = { 0.0f, 0.0f, 0.0f, 0.0f};\n\tfor(i = 0; i < 4; i++)\n\t\tprevRatios[i] = m_aSuspensionSpringRatio[i];\n\n\tif(m_bIsVehicleBeingShifted || bSkipLineCol || ent->IsPed() ||\n\t   GetModelIndex() == MI_DODO && ent->IsVehicle())\n\t\tcolModel->numLines = 0;\n\n\tint numCollisions = CCollision::ProcessColModels(GetMatrix(), *colModel,\n\t\tent->GetMatrix(), *ent->GetColModel(),\n\t\tcolpoints,\n\t\tm_aWheelColPoints, m_aSuspensionSpringRatio);\n\n\t// m_aSuspensionSpringRatio are now set to the point where the tyre touches ground.\n\t// In ProcessControl these will be re-normalized to ignore the tyre radius.\n\tif(colModel->numLines){\n\t\tfor(i = 0; i < 4; i++){\n\t\t\tif(m_aSuspensionSpringRatio[i] < 1.0f && m_aSuspensionSpringRatio[i] < prevRatios[i]){\n\t\t\t\tnumWheelCollisions++;\n\n\t\t\t\t// wheel is touching a physical\n\t\t\t\tif(ent->IsVehicle() || ent->IsObject()){\n\t\t\t\t\tCPhysical *phys = (CPhysical*)ent;\n\n\t\t\t\t\tm_aGroundPhysical[i] = phys;\n\t\t\t\t\tphys->RegisterReference((CEntity**)&m_aGroundPhysical[i]);\n\t\t\t\t\tm_aGroundOffset[i] = m_aWheelColPoints[i].point - phys->GetPosition();\n\t\t\t\t}\n\n\t\t\t\tm_nSurfaceTouched = m_aWheelColPoints[i].surfaceB;\n\t\t\t\tif(ent->IsBuilding())\n\t\t\t\t\tm_pCurGroundEntity = ent;\n\t\t\t}\n\t\t}\n\t}else\n\t\tcolModel->numLines = 4;\n\n\tif(numCollisions > 0 || numWheelCollisions > 0){\n\t\tAddCollisionRecord(ent);\n\t\tif(!ent->IsBuilding())\n\t\t\t((CPhysical*)ent)->AddCollisionRecord(this);\n\n\t\tif(numCollisions > 0)\n\t\t\tif(ent->IsBuilding() ||\n\t\t\t   ent->IsObject() && ((CPhysical*)ent)->bInfiniteMass)\n\t\t\t\tbHasHitWall = true;\n\t}\n\n\treturn numCollisions;\n}\n\nstatic int16 nLastControlInput;\nstatic float fMouseCentreRange = 0.35f;\nstatic float fMouseSteerSens = -0.0035f;\nstatic float fMouseCentreMult = 0.975f;\n\nvoid\nCBike::ProcessControlInputs(uint8 pad)\n{\n\tfloat speed = DotProduct(m_vecMoveSpeed, GetForward());\n\n\tif(CPad::GetPad(pad)->GetExitVehicle())\n\t\tbIsHandbrakeOn = true;\n\telse\n\t\tbIsHandbrakeOn = !!CPad::GetPad(pad)->GetHandBrake();\n\n\t// Steer left/right\n#ifdef FIX_BUGS\n\tif(CCamera::m_bUseMouse3rdPerson && !CVehicle::m_bDisableMouseSteering){\n\t\tif(CPad::GetPad(pad)->GetMouseX() != 0.0f){\n\t\t\tm_fSteerInput += fMouseSteerSens*CPad::GetPad(pad)->GetMouseX();\n\t\t\tnLastControlInput = 2;\n\t\t\tif(Abs(m_fSteerInput) < fMouseCentreRange)\n\t\t\t\tm_fSteerInput *= Pow(fMouseCentreMult, CTimer::GetTimeStep());\n\t\t}else if(CPad::GetPad(pad)->GetSteeringLeftRight() || nLastControlInput != 2){\n\t\t\t// mouse hasn't move, steer with pad like below\n\t\t\tm_fSteerInput += (-CPad::GetPad(pad)->GetSteeringLeftRight()/128.0f - m_fSteerInput)*\n\t\t\t\t0.2f*CTimer::GetTimeStep();\n\t\t\tnLastControlInput = 0;\n\t\t}\n\t}else\n#endif\n\t{\n\t\tm_fSteerInput += (-CPad::GetPad(pad)->GetSteeringLeftRight()/128.0f - m_fSteerInput)*\n\t\t\t0.2f*CTimer::GetTimeStep();\n\t\tnLastControlInput = 0;\n\t}\n\tm_fSteerInput = clamp(m_fSteerInput, -1.0f, 1.0f);\n\n\t// Lean forward/backward\n\tfloat updown;\n#ifdef FREE_CAM\n\tif (CCamera::bFreeCam) updown = CPad::IsAffectedByController ? -CPad::GetPad(pad)->GetSteeringUpDown()/128.0f : CPad::GetPad(pad)->GetCarGunUpDown()/128.0f;\n\telse\n#endif\n\tupdown = -CPad::GetPad(pad)->GetSteeringUpDown()/128.0f + CPad::GetPad(pad)->GetCarGunUpDown()/128.0f;\n\tm_fLeanInput += (updown - m_fLeanInput)*0.2f*CTimer::GetTimeStep();\n\tm_fLeanInput = clamp(m_fLeanInput, -1.0f, 1.0f);\n\n\t// Accelerate/Brake\n\tfloat acceleration = (CPad::GetPad(pad)->GetAccelerate() - CPad::GetPad(pad)->GetBrake())/255.0f;\n\tif(GetModelIndex() == MI_DODO && acceleration < 0.0f)\n\t\tacceleration *= 0.3f;\n\tif(Abs(speed) < 0.01f){\n\t\t// standing still, go into direction we want\n\t\tif(CPad::GetPad(pad)->GetAccelerate() > 150.0f && CPad::GetPad(pad)->GetBrake() > 150.0f){\n\t\t\tm_fGasPedal = CPad::GetPad(pad)->GetAccelerate()/255.0f;\n\t\t\tm_fBrakePedal = CPad::GetPad(pad)->GetBrake()/255.0f;\n\t\t\tm_doingBurnout = 1;\n\t\t}else{\n\t\t\tm_fGasPedal = acceleration;\n\t\t\tm_fBrakePedal = 0.0f;\n\t\t}\n\t}else{\n#if 1\n\t\t// simpler than the code below\n\t\tif(speed * acceleration < 0.0f){\n\t\t\t// if opposite directions, have to brake first\n\t\t\tm_fGasPedal = 0.0f;\n\t\t\tm_fBrakePedal = Abs(acceleration);\n\t\t}else{\n\t\t\t// accelerating in same direction we were already going\n\t\t\tm_fGasPedal = acceleration;\n\t\t\tm_fBrakePedal = 0.0f;\n\t\t}\n#else\n\t\tif(speed < 0.0f){\n\t\t\t// moving backwards currently\n\t\t\tif(acceleration < 0.0f){\n\t\t\t\t// still go backwards\n\t\t\t\tm_fGasPedal = acceleration;\n\t\t\t\tm_fBrakePedal = 0.0f;\n\t\t\t}else{\n\t\t\t\t// want to go forwards, so brake\n\t\t\t\tm_fGasPedal = 0.0f;\n\t\t\t\tm_fBrakePedal = acceleration;\n\t\t\t}\n\t\t}else{\n\t\t\t// moving forwards currently\n\t\t\tif(acceleration < 0.0f){\n\t\t\t\t// want to go backwards, so brake\n\t\t\t\tm_fGasPedal = 0.0f;\n\t\t\t\tm_fBrakePedal = -acceleration;\n\t\t\t}else{\n\t\t\t\t// still go forwards\n\t\t\t\tm_fGasPedal = acceleration;\n\t\t\t\tm_fBrakePedal = 0.0f;\n\t\t\t}\n\t\t}\n#endif\n\t}\n\n\t// Actually turn wheels\n\tstatic float fValue;\t// why static?\n\tif(m_fSteerInput < 0.0f)\n\t\tfValue = -sq(m_fSteerInput);\n\telse\n\t\tfValue = sq(m_fSteerInput);\n\tm_fSteerAngle = DEGTORAD(pHandling->fSteeringLock) * fValue;\n\n\tif(bComedyControls){\n\t\tif(((CTimer::GetTimeInMilliseconds() >> 10) & 0xF) < 12)\n\t\t\tm_fGasPedal = 1.0f;\n\t\tif((((CTimer::GetTimeInMilliseconds() >> 10)+6) & 0xF) < 12)\n\t\t\tm_fBrakePedal = 0.0f;\n\t\tbIsHandbrakeOn = false;\n\t\tif(CTimer::GetTimeInMilliseconds() & 0x800)\n\t\t\tm_fSteerAngle += 0.08f;\n\t\telse\n\t\t\tm_fSteerAngle -= 0.03f;\n\t}\n\n\t// Brake if player isn't in control\n\t// BUG: game always uses pad 0 here\n\tif(CPad::GetPad(pad)->ArePlayerControlsDisabled()){\n\t\tm_fBrakePedal = 1.0f;\n\t\tbIsHandbrakeOn = true;\n\t\tm_fGasPedal = 0.0f;\n\n\t\tFindPlayerPed()->KeepAreaAroundPlayerClear();\n\n\t\t// slow down car immediately\n\t\tspeed = m_vecMoveSpeed.Magnitude();\n\t\tif(speed > 0.28f)\n\t\t\tm_vecMoveSpeed *= 0.28f/speed;\n\t}\n}\n\nvoid\nCBike::ProcessBuoyancy(void)\n{\n\tint i;\n\tCVector impulse, point;\n\n\tif(mod_Buoyancy.ProcessBuoyancy(this, m_fBuoyancy, &point, &impulse)){\n\t\tbTouchingWater = true;\n\t\tApplyMoveForce(impulse);\n\t\tApplyTurnForce(impulse, point);\n\n\t\tfloat timeStep = Max(CTimer::GetTimeStep(), 0.01f);\n\t\tfloat impulseRatio = impulse.z / (GRAVITY * m_fMass * timeStep);\n\t\tfloat waterResistance = Pow(1.0f - 0.05f*impulseRatio, CTimer::GetTimeStep());\n\t\tm_vecMoveSpeed *= waterResistance;\n\t\tm_vecTurnSpeed *= waterResistance;\n\n\t\tif(impulseRatio > 0.8f ||\n\t\t   impulseRatio > 0.4f && (m_aSuspensionSpringRatio[0] == 1.0f ||\n\t\t                           m_aSuspensionSpringRatio[1] == 1.0f ||\n\t\t                           m_aSuspensionSpringRatio[2] == 1.0f ||\n\t\t                           m_aSuspensionSpringRatio[3] == 1.0f)){\n\t\t\tbIsInWater = true;\n\t\t\tbIsDrowning = true;\n\t\t\tif(m_vecMoveSpeed.z < -0.1f)\n\t\t\t\tm_vecMoveSpeed.z = -0.1f;\n\n\t\t\tif(pDriver){\n\t\t\t\tpDriver->bIsInWater = true;\n\t\t\t\tif(pDriver->IsPlayer() || !bWaterTight){\n\t\t\t\t\tif(m_aSuspensionSpringRatio[0] < 1.0f ||\n\t\t\t\t\t   m_aSuspensionSpringRatio[1] < 1.0f ||\n\t\t\t\t\t   m_aSuspensionSpringRatio[2] < 1.0f ||\n\t\t\t\t\t   m_aSuspensionSpringRatio[3] < 1.0f)\n\t\t\t\t\t\tpDriver->InflictDamage(nil, WEAPONTYPE_DROWNING, CTimer::GetTimeStep(), PEDPIECE_TORSO, 0);\n\t\t\t\t\telse\n\t\t\t\t\t\tKnockOffRider(WEAPONTYPE_DROWNING, 0, pDriver, false);\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor(i = 0; i < m_nNumMaxPassengers; i++)\n\t\t\t\tif(pPassengers[i]){\n\t\t\t\t\tpPassengers[i]->bIsInWater = true;\n\t\t\t\t\tif(pPassengers[i]->IsPlayer() || !bWaterTight){\n\t\t\t\t\t\tif(m_aSuspensionSpringRatio[0] < 1.0f ||\n\t\t\t\t\t\t   m_aSuspensionSpringRatio[1] < 1.0f ||\n\t\t\t\t\t\t   m_aSuspensionSpringRatio[2] < 1.0f ||\n\t\t\t\t\t\t   m_aSuspensionSpringRatio[3] < 1.0f)\n\t\t\t\t\t\t\tpPassengers[i]->InflictDamage(nil, WEAPONTYPE_DROWNING, CTimer::GetTimeStep(), PEDPIECE_TORSO, 0);\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tKnockOffRider(WEAPONTYPE_DROWNING, 0, pPassengers[i], false);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t}else{\n\t\t\tbIsInWater = false;\n\t\t\tbIsDrowning = false;\n\t\t}\n\t}else{\n\t\tbIsInWater = false;\n\t\tbIsDrowning = false;\n\t\tbTouchingWater = false;\n\t}\n}\n\nvoid\nCBike::DoDriveByShootings(void)\n{\n\tCAnimBlendAssociation *anim;\n\tCPlayerInfo* playerInfo = ((CPlayerPed*)pDriver)->GetPlayerInfoForThisPlayerPed();\n\tif (playerInfo && !playerInfo->m_bDriveByAllowed)\n\t\treturn;\n\n\tCWeapon *weapon = pDriver->GetWeapon();\n\tif(CWeaponInfo::GetWeaponInfo(weapon->m_eWeaponType)->m_nWeaponSlot != 5)\n\t\treturn;\n\n\tweapon->Update(pDriver->m_audioEntityId, nil);\n\n\tbool lookingLeft = false;\n\tbool lookingRight = false;\n\tif(TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOPDOWN ||\n\t   TheCamera.m_bObbeCinematicCarCamOn){\n\t\tif(CPad::GetPad(0)->GetLookLeft())\n\t\t\tlookingLeft = true;\n\t\tif(CPad::GetPad(0)->GetLookRight())\n\t\t\tlookingRight = true;\n\t}else{\n\t\tif(TheCamera.Cams[TheCamera.ActiveCam].LookingLeft)\n\t\t\tlookingLeft = true;\n\t\tif(TheCamera.Cams[TheCamera.ActiveCam].LookingRight)\n\t\t\tlookingRight = true;\n\t}\n\n\tif(lookingLeft || lookingRight || CPad::GetPad(0)->GetCarGunFired()){\n\t\tif(lookingLeft){\n\t\t\tanim = RpAnimBlendClumpGetAssociation(pDriver->GetClump(), ANIM_BIKE_DRIVEBY_RHS);\n\t\t\tif(anim)\n\t\t\t\tanim->blendDelta = -1000.0f;\n\t\t\tanim = RpAnimBlendClumpGetAssociation(pDriver->GetClump(), ANIM_BIKE_DRIVEBY_FORWARD);\n\t\t\tif(anim)\n\t\t\t\tanim->blendDelta = -1000.0f;\n\t\t\tanim = RpAnimBlendClumpGetAssociation(pDriver->GetClump(), ANIM_BIKE_DRIVEBY_LHS);\n\t\t\tif(anim == nil || anim->blendDelta < 0.0f)\n\t\t\t\tanim = CAnimManager::AddAnimation(pDriver->GetClump(), m_bikeAnimType, ANIM_BIKE_DRIVEBY_LHS);\n\t\t}else if(lookingRight){\n\t\t\tanim = RpAnimBlendClumpGetAssociation(pDriver->GetClump(), ANIM_BIKE_DRIVEBY_LHS);\n\t\t\tif(anim)\n\t\t\t\tanim->blendDelta = -1000.0f;\n\t\t\tanim = RpAnimBlendClumpGetAssociation(pDriver->GetClump(), ANIM_BIKE_DRIVEBY_FORWARD);\n\t\t\tif(anim)\n\t\t\t\tanim->blendDelta = -1000.0f;\n\t\t\tanim = RpAnimBlendClumpGetAssociation(pDriver->GetClump(), ANIM_BIKE_DRIVEBY_RHS);\n\t\t\tif(anim == nil || anim->blendDelta < 0.0f)\n\t\t\t\tanim = CAnimManager::AddAnimation(pDriver->GetClump(), m_bikeAnimType, ANIM_BIKE_DRIVEBY_RHS);\n\t\t}else{\n\t\t\tanim = RpAnimBlendClumpGetAssociation(pDriver->GetClump(), ANIM_BIKE_DRIVEBY_RHS);\n\t\t\tif(anim)\n\t\t\t\tanim->blendDelta = -1000.0f;\n\t\t\tanim = RpAnimBlendClumpGetAssociation(pDriver->GetClump(), ANIM_BIKE_DRIVEBY_LHS);\n\t\t\tif(anim)\n\t\t\t\tanim->blendDelta = -1000.0f;\n\t\t\tanim = RpAnimBlendClumpGetAssociation(pDriver->GetClump(), ANIM_BIKE_DRIVEBY_FORWARD);\n\t\t\tif(anim == nil || anim->blendDelta < 0.0f)\n\t\t\t\tanim = CAnimManager::AddAnimation(pDriver->GetClump(), m_bikeAnimType, ANIM_BIKE_DRIVEBY_FORWARD);\n\t\t}\n\n\t\tif (!anim || !anim->IsRunning()) {\n\t\t\tif (CPad::GetPad(0)->GetCarGunFired() && CTimer::GetTimeInMilliseconds() > weapon->m_nTimer) {\n\t\t\t\tweapon->FireFromCar(this, lookingLeft, lookingRight);\n\t\t\t\tweapon->m_nTimer = CTimer::GetTimeInMilliseconds() + 70;\n\t\t\t}\n\t\t}\n\t}else{\n\t\tweapon->Reload();\n\t\tanim = RpAnimBlendClumpGetAssociation(pDriver->GetClump(), ANIM_BIKE_DRIVEBY_LHS);\n\t\tif(anim)\n\t\t\tanim->blendDelta = -1000.0f;\n\t\tanim = RpAnimBlendClumpGetAssociation(pDriver->GetClump(), ANIM_BIKE_DRIVEBY_RHS);\n\t\tif(anim)\n\t\t\tanim->blendDelta = -1000.0f;\n\t\tanim = RpAnimBlendClumpGetAssociation(pDriver->GetClump(), ANIM_BIKE_DRIVEBY_FORWARD);\n\t\tif(anim)\n\t\t\tanim->blendDelta = -1000.0f;\n\t}\n}\n\nvoid\nCBike::VehicleDamage(void)\n{\n\tfloat impulse = m_fDamageImpulse;\n\tfloat colSpeed = 800.0f*impulse/m_fMass;\n\tif(GetStatus() == STATUS_PLAYER)\n\t\tcolSpeed *= 0.65f;\n\telse if(VehicleCreatedBy == MISSION_VEHICLE)\n\t\tcolSpeed *= 0.4f;\n\n\tif(!bCanBeDamaged)\n\t\treturn;\n\n\tif(GetStatus() == STATUS_PLAYER && CStats::GetPercentageProgress() >= 100.0f)\n\t\timpulse *= 0.5f;\n\n\tif(bIsStanding && impulse > 20.0f)\n\t\tbIsStanding = false;\n\n\t// Inflict damage on the driver and passenger\n\tif(pDriver && pDriver->GetPedState() == PED_DRIVING && colSpeed > 10.0f){\n\t\tfloat fwd = 0.6f;\n\t\tif(Abs(DotProduct(m_vecDamageNormal, GetForward())) > 0.85f){\n\t\t\tfloat u = Max(DotProduct(m_vecDamageNormal, CVector(0.0f, 0.0f, 1.0f)), 0.0f);\n\t\t\tif(u < 0.85f)\n\t\t\t\tu = 0.0f;\n\t\t\tfwd += 7.0f * SQR(u);\n\t\t}\n\t\tfloat up = 0.05f;\n\n\t\tif(GetModelIndex() == MI_SANCHEZ){\n\t\t\tfwd *= 0.65f;\n\t\t\tup *= 0.75f;\n\t\t}\n\n\t\tfloat total = fwd*Abs(DotProduct(m_vecDamageNormal, GetForward())) +\n\t\t\t0.45f*Abs(DotProduct(m_vecDamageNormal, GetRight())) +\n\t\t\tup*Max(DotProduct(m_vecDamageNormal, GetUp()), 0.0f);\n\t\tfloat damage = (total - 1.5f*Min(DotProduct(m_vecDamageNormal, GetUp()), 0.0f))*colSpeed;\n\n\t\tif(pDriver->IsPlayer() && CCullZones::CamStairsForPlayer() && CCullZones::FindZoneWithStairsAttributeForPlayer())\n\t\t\tdamage = 0.0f;\n\n\t\tif(damage > 75.0f){\n\t\t\tint dir = -10;\n\t\t\tif(pDriver){\n\t\t\t\tdir = pDriver->GetLocalDirection(-m_vecDamageNormal);\n\t\t\t\tif(pDriver->m_fHealth > 0.0f)\n\t\t\t\t\tpDriver->InflictDamage(m_pDamageEntity, WEAPONTYPE_RAMMEDBYCAR, 0.05f*damage, PEDPIECE_TORSO, dir);\n\t\t\t\tif(pDriver && pDriver->GetPedState() == PED_DRIVING)\n\t\t\t\t\tKnockOffRider(WEAPONTYPE_RAMMEDBYCAR, dir, pDriver, false);\n\t\t\t}\n\t\t\tif(pPassengers[0]){\n\t\t\t\tdir = pPassengers[0]->GetLocalDirection(-m_vecDamageNormal);\n\t\t\t\tif(pPassengers[0]->m_fHealth > 0.0f)\n\t\t\t\t\tpPassengers[0]->InflictDamage(m_pDamageEntity, WEAPONTYPE_RAMMEDBYCAR, 0.05f*damage, PEDPIECE_TORSO, dir);\n\t\t\t\tif(pPassengers[0] && pPassengers[0]->GetPedState() == PED_DRIVING)\n\t\t\t\t\tKnockOffRider(WEAPONTYPE_RAMMEDBYCAR, dir, pPassengers[0], false);\n\t\t\t}\n\t\t}\n\t}\n\n\tif(impulse > 25.0f && GetStatus() != STATUS_WRECKED){\n\t\tfloat damage = (impulse-25.0f)*pHandling->fCollisionDamageMultiplier;\n\t\tif(damage > 0.0f){\n\t\t\tif(damage > 5.0f &&\n\t\t\t   pDriver &&\n\t\t\t   m_pDamageEntity && m_pDamageEntity->IsVehicle() &&\n\t\t\t   (this != FindPlayerVehicle() || ((CVehicle*)m_pDamageEntity)->VehicleCreatedBy == MISSION_VEHICLE) &&\n\t\t\t   ((CVehicle*)m_pDamageEntity)->pDriver)\n\t\t\t\t\tpDriver->Say(SOUND_PED_CRASH_VEHICLE);\n\n\t\t\tint oldHealth = m_fHealth;\n\t\t\tif(this == FindPlayerVehicle())\n\t\t\t\tm_fHealth -= bTakeLessDamage ? damage/6.0f : damage/2.0f;\n\t\t\telse if(bTakeLessDamage)\n\t\t\t\tm_fHealth -= damage/12.0f;\n\t\t\telse if(m_pDamageEntity && m_pDamageEntity == FindPlayerVehicle())\n\t\t\t\tm_fHealth -= damage/1.5f;\n\t\t\telse\n\t\t\t\tm_fHealth -= damage/4.0f;\n\t\t\tif(m_fHealth <= 0.0f && oldHealth > 0)\n\t\t\t\tm_fHealth = 1.0f;\n\t\t}\n\t}\n\n\tif(m_fHealth < 250.0f){\n\t\t// Car is on fire\n\t\tif(!bIsOnFire){\n\t\t\t// Set engine on fire and remember who did this\n\t\t\tbIsOnFire = true;\n\t\t\tm_fFireBlowUpTimer = 0.0f;\n\t\t\tm_pSetOnFireEntity = m_pDamageEntity;\n\t\t\tif(m_pSetOnFireEntity)\n\t\t\t\tm_pSetOnFireEntity->RegisterReference(&m_pSetOnFireEntity);\n\t\t}\n\t}\n}\n\nvoid\nCBike::AddDamagedVehicleParticles(void)\n{\n\tif(this == FindPlayerVehicle() && TheCamera.GetLookingForwardFirstPerson())\n\t\treturn;\n\tif(this != FindPlayerVehicle() && (CTimer::GetFrameCounter() + m_randomSeed) & 1)\n\t\treturn;\n\tif(m_fHealth >= 650.0f)\n\t\treturn;\n\n\tCVector direction = 0.5f*m_vecMoveSpeed;\n\tCVector damagePos = ((CVehicleModelInfo*)CModelInfo::GetModelInfo(GetModelIndex()))->GetFrontSeatPosn();\n\n\tdamagePos.z -= 0.4f;\n\tdamagePos = GetMatrix()*damagePos;\n\n\tCalculateLeanMatrix();\n\n\tif(m_fHealth < 250.0f){\n\t\t// fire, done in processControl\n\t}else if(m_fHealth < 320.0f){\n\t\tdirection *= 0.2f;\n\t\tCParticle::AddParticle(PARTICLE_ENGINE_SMOKE2, damagePos, direction + 0.02f*m_leanMatrix.GetRight());\n\t}else if(m_fHealth < 390.0f){\n\t\tif(((CTimer::GetFrameCounter() + m_randomSeed) & 3) == 0 ||\n\t\t   ((CTimer::GetFrameCounter() + m_randomSeed) & 3) == 2)\n\t\t\tCParticle::AddParticle(PARTICLE_ENGINE_STEAM, damagePos, direction + 0.05f*m_leanMatrix.GetRight());\n\t\tdirection *= 0.3f;\n\t\tCParticle::AddParticle(PARTICLE_ENGINE_SMOKE, damagePos, direction + 0.04f*m_leanMatrix.GetRight());\n\t}else if(m_fHealth < 460.0f){\n\t\tint rnd = CTimer::GetFrameCounter() + m_randomSeed;\n\t\tif(rnd < 10 ||\n\t\t   rnd < 70 && rnd > 25 ||\n\t\t   rnd < 160 && rnd > 100 ||\n\t\t   rnd < 200 && rnd > 175 ||\n\t\t   rnd > 235)\n\t\t\treturn;\n\t\tdirection.z += 0.05f;\n\t\tif(TheCamera.GetLookDirection() != LOOKING_FORWARD){\n\t\t\tCParticle::AddParticle(PARTICLE_ENGINE_STEAM, damagePos, direction + 0.08f*m_leanMatrix.GetRight(), nil, 0.1f, 0, 0, 0, 1000);\n\t\t}else if(((CTimer::GetFrameCounter() + m_randomSeed) & 1) == 0){\n\t\t\tdirection = 0.8f*m_vecMoveSpeed;\n\t\t\tCParticle::AddParticle(PARTICLE_ENGINE_STEAM, damagePos, direction + 0.07f*m_leanMatrix.GetRight(), nil, 0.1f, 0, 0, 0, 1000);\n\t\t}\n\t}else if(((CTimer::GetFrameCounter() + m_randomSeed) & 3) == 0 ||\n\t         ((CTimer::GetFrameCounter() + m_randomSeed) & 3) == 2){\n\t\tCParticle::AddParticle(PARTICLE_ENGINE_STEAM, damagePos + 0.06f*m_leanMatrix.GetRight(), direction);\n\t}\n}\n\nint32\nCBike::AddWheelDirtAndWater(CColPoint *colpoint, uint32 belowEffectSpeed)\n{\n\tint i;\n\tCVector dir;\n\tstatic float minSize = 0.02f;\n\tstatic float maxSize = 0.04f;\n\tstatic RwRGBA grassCol = { 8, 24, 8, 255 };\n\tstatic RwRGBA gravelCol = { 64, 64, 64, 255 };\n\tstatic RwRGBA mudCol = { 64, 32, 16, 255 };\n\tstatic RwRGBA sandCol = { 170, 165, 140, 255 };\n\tstatic RwRGBA waterCol = { 48, 48, 64, 0 };\n\n\tif(!belowEffectSpeed &&\n\t   colpoint->surfaceB != SURFACE_SAND && colpoint->surfaceB != SURFACE_SAND_BEACH)\n\t\treturn 0;\n\n\tswitch(colpoint->surfaceB){\n\tcase SURFACE_GRASS:\n\t\tdir.x = -0.05f*m_vecMoveSpeed.x;\n\t\tdir.y = -0.05f*m_vecMoveSpeed.y;\n\t\tfor(i = 0; i < 4; i++){\n\t\t\tdir.z = CGeneral::GetRandomNumberInRange(0.03f, 0.04f);\n\t\t\tCParticle::AddParticle(PARTICLE_WHEEL_DIRT, colpoint->point, dir, nil,\n\t\t\t\tCGeneral::GetRandomNumberInRange(minSize, maxSize), grassCol);\n\t\t}\n\t\treturn 0;\n\tcase SURFACE_GRAVEL:\n\t\tdir.x = -0.05f*m_vecMoveSpeed.x;\n\t\tdir.y = -0.05f*m_vecMoveSpeed.y;\n\t\tfor(i = 0; i < 4; i++){\n\t\t\tdir.z = CGeneral::GetRandomNumberInRange(0.03f, 0.04f);\n\t\t\tCParticle::AddParticle(PARTICLE_WHEEL_DIRT, colpoint->point, dir, nil,\n\t\t\t\tCGeneral::GetRandomNumberInRange(minSize, maxSize), gravelCol);\n\t\t}\n\t\treturn 1;\n\tcase SURFACE_MUD_DRY:\n\t\tdir.x = -0.05f*m_vecMoveSpeed.x;\n\t\tdir.y = -0.05f*m_vecMoveSpeed.y;\n\t\tfor(i = 0; i < 4; i++){\n\t\t\tdir.z = CGeneral::GetRandomNumberInRange(0.03f, 0.04f);\n\t\t\tCParticle::AddParticle(PARTICLE_WHEEL_DIRT, colpoint->point, dir, nil,\n\t\t\t\tCGeneral::GetRandomNumberInRange(minSize, maxSize), mudCol);\n\t\t}\n\t\treturn 0;\n\tcase SURFACE_SAND:\n\tcase SURFACE_SAND_BEACH:\n\t\tif(CTimer::GetFrameCounter() & 2)\n\t\t\treturn 0;\n\t\tdir.x = 0.75f*m_vecMoveSpeed.x;\n\t\tdir.y = 0.75f*m_vecMoveSpeed.y;\n\t\tfor(i = 0; i < 1; i++){\n\t\t\tdir.z = CGeneral::GetRandomNumberInRange(0.02f, 0.055f);\n\t\t\tCParticle::AddParticle(PARTICLE_SAND, colpoint->point, dir, nil,\n\t\t\t\t0.8f*m_vecMoveSpeed.Magnitude(), sandCol);\n\t\t}\n\t\treturn 0;\n\tdefault:\n\t\tif(CWeather::WetRoads > 0.01f){\n\t\t\tCParticle::AddParticle(\n\t\t\t\tPARTICLE_WATERSPRAY,\n\t\t\t\tcolpoint->point + CVector(0.0f, 0.0f, 0.25f+0.25f),\n\t\t\t\tCVector(0.0f, 0.0f, CGeneral::GetRandomNumberInRange(0.005f, 0.04f)),\n\t\t\t\tnil,\n\t\t\t\tCGeneral::GetRandomNumberInRange(0.1f, 0.5f), waterCol);\n\t\t\treturn 0;\n\t\t}\t\n\t\treturn 1;\n\t}\n\n\treturn 0;\n}\n\nvoid\nCBike::GetComponentWorldPosition(int32 component, CVector &pos)\n{\n\tif(m_aBikeNodes[component] == nil){\n\t\tprintf(\"BikeNode missing: %d %d\\n\", GetModelIndex(), component);\n\t\treturn;\n\t}\n\tRwMatrix *ltm = RwFrameGetLTM(m_aBikeNodes[component]);\n\tpos = *RwMatrixGetPos(ltm);\n}\n\nbool\nCBike::IsComponentPresent(int32 component)\n{\n\treturn m_aBikeNodes[component] != nil;\n}\n\nvoid\nCBike::SetComponentRotation(int32 component, CVector rotation)\n{\n\tCMatrix mat(RwFrameGetMatrix(m_aBikeNodes[component]));\n\tCVector pos = mat.GetPosition();\n\t// BUG: all these set the whole matrix\n\tmat.SetRotateX(DEGTORAD(rotation.x));\n\tmat.SetRotateY(DEGTORAD(rotation.y));\n\tmat.SetRotateZ(DEGTORAD(rotation.z));\n\tmat.Translate(pos);\n\tmat.UpdateRW();\n}\n\nbool\nCBike::IsDoorReady(eDoors door)\n{\n\treturn true;\n}\n\nbool\nCBike::IsDoorFullyOpen(eDoors door)\n{\n\treturn false;\n}\n\nbool\nCBike::IsDoorClosed(eDoors door)\n{\n\treturn false;\n}\n\nbool\nCBike::IsDoorMissing(eDoors door)\n{\n\treturn true;\n}\n\nvoid\nCBike::RemoveRefsToVehicle(CEntity *ent)\n{\n\tint i;\n\tfor(i = 0; i < 4; i++)\n\t\tif(m_aGroundPhysical[i] == ent)\n\t\t\tm_aGroundPhysical[i] = nil;\n}\n\nvoid\nCBike::BlowUpCar(CEntity *culprit)\n{\n\tif(!bCanBeDamaged)\n\t\treturn;\n\n#ifdef FIX_BUGS\n\t// taken from CAutomobile. maybe tweak values?\n\tif(culprit == FindPlayerPed() || culprit == FindPlayerVehicle()){\n\t\tCWorld::Players[CWorld::PlayerInFocus].m_nHavocLevel += 20;\n\t\tCWorld::Players[CWorld::PlayerInFocus].m_fMediaAttention += 10.0f;\n\t\tCStats::PropertyDestroyed += CGeneral::GetRandomNumber()%6000 + 4000;\n\t}\n#endif\n\n\t// explosion pushes vehicle up\n\tm_vecMoveSpeed.z += 0.13f;\n\tSetStatus(STATUS_WRECKED);\n\tbRenderScorched = true;\n\n\tm_fHealth = 0.0f;\n\tm_nBombTimer = 0;\n\n\tTheCamera.CamShake(0.7f, GetPosition().x, GetPosition().y, GetPosition().z);\n\n\tKillPedsInVehicle();\n\n\tbEngineOn = false;\n\tbLightsOn = false;\n\tChangeLawEnforcerState(false);\n\n\tCExplosion::AddExplosion(this, culprit, EXPLOSION_CAR, GetPosition(), 0);\n\tCDarkel::RegisterCarBlownUpByPlayer(this);\n}\n\nbool\nCBike::SetUpWheelColModel(CColModel *colModel)\n{\n\tRwMatrix *mat = RwMatrixCreate();\n\tCVehicleModelInfo *mi = (CVehicleModelInfo*)CModelInfo::GetModelInfo(GetModelIndex());\n\tCColModel *vehColModel = mi->GetColModel();\n\n\tcolModel->boundingSphere = vehColModel->boundingSphere;\n\tcolModel->boundingBox = vehColModel->boundingBox;\n\n\tGetRelativeMatrix(mat, m_aBikeNodes[BIKE_WHEEL_FRONT], m_aBikeNodes[BIKE_CHASSIS]);\n\tcolModel->spheres[0].Set(0.5f*mi->m_wheelScale, *RwMatrixGetPos(mat), SURFACE_RUBBER, CAR_PIECE_WHEEL_LF);\n\tGetRelativeMatrix(mat, m_aBikeNodes[BIKE_WHEEL_REAR], m_aBikeNodes[BIKE_CHASSIS]);\n\tcolModel->spheres[1].Set(0.5f*mi->m_wheelScale, *RwMatrixGetPos(mat), SURFACE_RUBBER, CAR_PIECE_WHEEL_LR);\n\tcolModel->numSpheres = 2;\n#ifdef FIX_BUGS\n\tRwMatrixDestroy(mat);\n#endif\n\treturn true;\n}\n\nfloat fBikeBurstForceMult = 0.02f;\nfloat fBikeBurstFallSpeed = 0.3f;\nfloat fBikeBurstFallSpeedPlayer = 0.55f;\n\nvoid\nCBike::BurstTyre(uint8 wheel, bool applyForces)\n{\n\tif(bTyresDontBurst)\n\t\treturn;\n\n\tswitch(wheel){\n\tcase CAR_PIECE_WHEEL_LF: wheel = BIKEWHEEL_FRONT; break;\n\tcase CAR_PIECE_WHEEL_LR: wheel = BIKEWHEEL_REAR; break;\n\t}\n\n\tif(m_wheelStatus[wheel] == WHEEL_STATUS_OK){\n\t\tm_wheelStatus[wheel] = WHEEL_STATUS_BURST;\n#ifdef FIX_BUGS\n\t\tCStats::TyresPopped++;\n#endif\n\t\tDMAudio.PlayOneShot(m_audioEntityId, SOUND_CAR_TYRE_POP, 0.0f);\n\n\t\tif(GetStatus() == STATUS_SIMPLE){\n\t\t\tSetStatus(STATUS_PHYSICS);\n\t\t\tCCarCtrl::SwitchVehicleToRealPhysics(this);\n\t\t}\n\n\t\tif(applyForces){\n\t\t\tApplyMoveForce(GetRight() * m_fMass * CGeneral::GetRandomNumberInRange(-0.02f, 0.02f));\n\t\t\tApplyTurnForce(GetRight() * m_fTurnMass * CGeneral::GetRandomNumberInRange(-0.02f, 0.02f), GetForward());\n\t\t}\n\n\t\t// This code checks piece types originally so it is never triggered\n\t\t// as we have converted them to wheel indices above already.\n\t\tif(pDriver){\n#ifdef FIX_SIGNIFICANT_BUGS\n\t\t\tif(wheel == BIKEWHEEL_FRONT && (m_aSuspensionSpringRatioPrev[BIKESUSP_F1] < 1.0f || m_aSuspensionSpringRatioPrev[BIKESUSP_F2] < 1.0f) ||\n\t\t\t   wheel == BIKEWHEEL_REAR && (m_aSuspensionSpringRatioPrev[BIKESUSP_R1] < 1.0f || m_aSuspensionSpringRatioPrev[BIKESUSP_R2] < 1.0f)){\n#else\n\t\t\tif(wheel == CAR_PIECE_WHEEL_LF && (m_aSuspensionSpringRatioPrev[BIKESUSP_F1] < 1.0f || m_aSuspensionSpringRatioPrev[BIKESUSP_F2] < 1.0f) ||\n\t\t\t   wheel == CAR_PIECE_WHEEL_LR && (m_aSuspensionSpringRatioPrev[BIKESUSP_R1] < 1.0f || m_aSuspensionSpringRatioPrev[BIKESUSP_R2] < 1.0f)){\n#endif\n\t\t\t\tfloat speedSq = m_vecMoveSpeed.MagnitudeSqr();\n\t\t\t\tif(speedSq > fBikeBurstFallSpeed &&\n\t\t\t\t   (GetStatus() != STATUS_PLAYER || speedSq > fBikeBurstFallSpeedPlayer)){\n#ifdef FIX_SIGNIFICANT_BUGS\n\t\t\t\t\tif(wheel == BIKEWHEEL_FRONT){\n#else\n\t\t\t\t\tif(wheel == CAR_PIECE_WHEEL_LF){\n#endif\n\t\t\t\t\t\tKnockOffRider(WEAPONTYPE_RAMMEDBYCAR, 0, pDriver, false);\n\t\t\t\t\t\tif(pPassengers[0])\n\t\t\t\t\t\t\tKnockOffRider(WEAPONTYPE_RAMMEDBYCAR, 0, pPassengers[0], false);\n\t\t\t\t\t}else\n\t\t\t\t\t\tApplyTurnForce(2.0f*fBikeBurstForceMult*m_fTurnMass*GetRight(), GetForward());\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nbool\nCBike::IsRoomForPedToLeaveCar(uint32 component, CVector *doorOffset)\n{\n\tCColPoint colpoint;\n\tCEntity *ent;\n\tcolpoint.point = CVector(0.0f, 0.0f, 0.0f);\n\tCVehicleModelInfo *mi = (CVehicleModelInfo*)CModelInfo::GetModelInfo(GetModelIndex());\n\n\tCVector seatPos = mi->GetFrontSeatPosn();\n\tif(component == CAR_DOOR_RR || component == CAR_DOOR_LR)\n\t\tseatPos = mi->m_positions[CAR_POS_BACKSEAT];\n\tif(component == CAR_DOOR_LF || component == CAR_DOOR_LR)\n\t\tseatPos.x = -seatPos.x;\n\tseatPos = GetMatrix() * seatPos;\n\n\tCVector doorPos = CPed::GetPositionToOpenCarDoor(this, component);\n\tif(doorOffset){\n\t\tCVector off = *doorOffset;\n\t\tif(component == CAR_DOOR_RF || component == CAR_DOOR_RR)\n\t\t\toff.x = -off.x;\n\t\tdoorPos += Multiply3x3(GetMatrix(), off);\n\t}\n\n\tif(GetUp().z < 0.0f){\n\t\tseatPos.z += 0.5f;\n\t\tdoorPos.z += 0.5f;\n\t}\n\n\tCVector dist = doorPos - seatPos;\n\n\t// Removing that makes thiProcessEntityCollisions func. return false for van doors.\n\tdoorPos.z += 0.5f;\n\tfloat length = dist.Magnitude();\n\tCVector pedPos = seatPos + dist*((length+0.6f)/length);\n\n\tif(!CWorld::GetIsLineOfSightClear(seatPos, pedPos, true, false, false, true, false, false))\n\t\treturn false;\n\tif(CWorld::TestSphereAgainstWorld(doorPos, 0.6f, this, true, true, false, true, false, false))\n\t\treturn false;\n\tif(CWorld::ProcessVerticalLine(doorPos, 1000.0f, colpoint, ent, true, false, false, true, false, false, nil))\n\t\tif(colpoint.point.z > doorPos.z && colpoint.point.z < doorPos.z + 0.6f)\n\t\t\treturn false;\n\tfloat upperZ = colpoint.point.z;\n\tif(!CWorld::ProcessVerticalLine(doorPos, -1000.0f, colpoint, ent, true, false, false, true, false, false, nil))\n\t\treturn false;\n\tif(upperZ != 0.0f && upperZ < colpoint.point.z)\n\t\treturn false;\n\treturn true;\n}\n\nfloat\nCBike::GetHeightAboveRoad(void)\n{\n\treturn m_fHeightAboveRoad;\n}\n\nvoid\nCBike::PlayCarHorn(void)\n{\n\tint r;\n\n\tif (IsAlarmOn() || m_nCarHornTimer != 0)\n\t\treturn;\n\n\tif (m_nCarHornDelay) {\n\t\tm_nCarHornDelay--;\n\t\treturn;\n\t}\n\n\tm_nCarHornDelay = (CGeneral::GetRandomNumber() & 0x7F) + 150;\n\tr = m_nCarHornDelay & 7;\n\tif(r < 2){\n\t\tm_nCarHornTimer = 45;\n\t}else if(r < 4){\n\t\tif(pDriver)\n\t\t\tpDriver->Say(SOUND_PED_ANNOYED_DRIVER);\n\t\tm_nCarHornTimer = 45;\n\t}else{\n\t\tif(pDriver)\n\t\t\tpDriver->Say(SOUND_PED_ANNOYED_DRIVER);\n\t}\n}\n\nvoid\nCBike::KnockOffRider(eWeaponType weapon, uint8 direction, CPed *ped, bool bGetBackOn)\n{\n\tAnimationId anim = ANIM_STD_KO_FRONT;\n\tif(ped == nil)\n\t\treturn;\n\n\tif(!ped->IsPlayer()){\n\t\tif(bGetBackOn){\n\t\t\tif(ped->m_pedStats->m_temper > ped->m_pedStats->m_fear &&\n\t\t\t   ped->CharCreatedBy != MISSION_CHAR && ped->m_pMyVehicle->VehicleCreatedBy != MISSION_VEHICLE &&\n\t\t\t   FindPlayerPed()->m_carInObjective == ped->m_pMyVehicle &&\n\t\t\t   !CTheScripts::IsPlayerOnAMission())\n\t\t\t\tped->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, ped->m_pMyVehicle);\n\t\t\telse if(ped->m_pedStats->m_temper > ped->m_pedStats->m_fear &&\n\t\t\t   ped->CharCreatedBy != MISSION_CHAR && ped->m_pMyVehicle->VehicleCreatedBy != MISSION_VEHICLE &&\n\t\t\t   !CTheScripts::IsPlayerOnAMission())\n\t\t\t\tped->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, ped->m_pMyVehicle);\n\t\t\telse if(ped->m_pedStats->m_temper <= ped->m_pedStats->m_fear &&\n\t\t\t   ped->CharCreatedBy != MISSION_CHAR && ped->m_pMyVehicle->VehicleCreatedBy != MISSION_VEHICLE &&\n\t\t\t   !CTheScripts::IsPlayerOnAMission()){\n\t\t\t\tped->SetObjective(OBJECTIVE_WANDER, ped->m_pMyVehicle);\n\t\t\t\tped->m_nPathDir = CGeneral::GetRandomNumberInRange(0, 8);\n\t\t\t}\n\t\t}else if(ped->m_leader == nil){\n\t\t\tif(pDriver == ped)\n\t\t\t\tped->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, this);\n\t\t\telse\n\t\t\t\tped->SetObjective(OBJECTIVE_ENTER_CAR_AS_PASSENGER, this);\n\t\t}\n\t}\n\n\tif(ped->IsPed()){\n\t\tCAnimBlendAssociation *assoc;\n\t\tfor(assoc = RpAnimBlendClumpGetFirstAssociation(ped->GetClump(), ASSOC_DRIVING);\n\t\t    assoc;\n\t\t    assoc = RpAnimBlendGetNextAssociation(assoc))\n\t\t\tassoc->flags |= ASSOC_DELETEFADEDOUT;\n\t}\n\n\tped->SetPedState(PED_IDLE);\n\tCAnimManager::BlendAnimation(ped->GetClump(), ped->m_animGroup, ANIM_STD_IDLE, 100.0f);\n\tped->m_vehDoor = CAR_DOOR_LF;\n\tCPed::PedSetOutCarCB(nil, ped);\n\tped->SetMoveState(PEDMOVE_STILL);\n\tif(GetUp().z < 0.0f)\n\t\tped->SetHeading(CGeneral::LimitRadianAngle(GetForward().Heading() + PI));\n\telse\n\t\tped->SetHeading(GetForward().Heading());\n\n\tswitch(weapon){\n\tcase WEAPONTYPE_UNARMED:\n\tcase WEAPONTYPE_UNIDENTIFIED:\n\t\tped->m_vecMoveSpeed = m_vecMoveSpeed;\n\t\tped->m_pCollidingEntity = this;\n\t\tanim = ANIM_STD_NUM;\n\t\tbreak;\n\n\tcase WEAPONTYPE_BASEBALLBAT:\n\tdefault:\n\t\tswitch(direction){\n\t\tcase 0:\n\t\t\tanim = ANIM_STD_BIKE_FALLBACK;\n\t\t\tped->m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.1f);\n\t\t\tif(m_vecMoveSpeed.MagnitudeSqr() < SQR(0.3f))\n\t\t\t\tped->ApplyMoveForce(5.0f*GetUp() - 6.0f*GetForward());\n\t\t\tped->m_pCollidingEntity = this;\n\t\t\tbreak;\n\t\tcase 1:\n\t\tcase 2:\n\t\t\tif(m_vecMoveSpeed.MagnitudeSqr() > SQR(0.3f)){\n\t\t\t\tanim = ANIM_STD_HIGHIMPACT_LEFT;\n\t\t\t\tped->m_vecMoveSpeed = 0.3f*m_vecMoveSpeed;\n\t\t\t\tped->ApplyMoveForce(5.0f*GetUp() + 6.0f*GetRight());\n\t\t\t}else{\n\t\t\t\tanim = ANIM_STD_SPINFORWARD_LEFT;\n\t\t\t\tped->m_vecMoveSpeed = m_vecMoveSpeed;\n\t\t\t\tped->ApplyMoveForce(4.0f*GetUp() + 8.0f*GetRight());\n\t\t\t}\n\t\t\t// BUG or is it intentionally missing?\n\t\t\t//ped->m_pCollidingEntity = this;\n\t\t\tbreak;\n\t\tcase 3:\n\t\t\tif(m_vecMoveSpeed.MagnitudeSqr() > SQR(0.3f)){\n\t\t\t\tanim = ANIM_STD_HIGHIMPACT_RIGHT;\n\t\t\t\tped->m_vecMoveSpeed = 0.3f*m_vecMoveSpeed;\n\t\t\t\tped->ApplyMoveForce(5.0f*GetUp() - 6.0f*GetRight());\n\t\t\t}else{\n\t\t\t\tanim = ANIM_STD_SPINFORWARD_RIGHT;\n\t\t\t\tped->m_vecMoveSpeed = m_vecMoveSpeed;\n\t\t\t\tped->ApplyMoveForce(4.0f*GetUp() - 8.0f*GetRight());\n\t\t\t}\n\t\t\t// BUG or is it intentionally missing?\n\t\t\t//ped->m_pCollidingEntity = this;\n\t\t\tbreak;\n\t\t}\n\t\tbreak;\n\n\tcase WEAPONTYPE_DROWNING:{\n\t\tRwRGBA color;\n\t\tanim = ANIM_STD_FALL;\n\t\tped->m_vecMoveSpeed = m_vecMoveSpeed*0.2f;\n\t\tped->m_vecMoveSpeed.z = 0.0f;\n\t\tped->m_pCollidingEntity = this;\n\t\tcolor.red = (0.5f * CTimeCycle::GetDirectionalRed() + CTimeCycle::GetAmbientRed_Obj())*0.45f*255;\n\t\tcolor.green = (0.5f * CTimeCycle::GetDirectionalGreen() + CTimeCycle::GetAmbientGreen_Obj())*0.45f*255;\n\t\tcolor.blue = (0.5f * CTimeCycle::GetDirectionalBlue() + CTimeCycle::GetAmbientBlue_Obj())*0.45f*255;\n\t\tcolor.alpha = CGeneral::GetRandomNumberInRange(48, 96);\n\t\tDMAudio.PlayOneShot(m_audioEntityId, SOUND_SPLASH, 0.0f);\n\t\tCVector splashPos = ped->GetPosition() + 2.2f*ped->m_vecMoveSpeed;\n\t\tfloat waterZ = 0.0f;\n\t\tif(CWaterLevel::GetWaterLevel(splashPos, &waterZ, false))\n\t\t\tsplashPos.z = waterZ;\n\t\tCParticleObject::AddObject(POBJECT_PED_WATER_SPLASH, splashPos, CVector(0.0f, 0.0f, 0.1f),\n\t\t\t0.0f, 200, color, true);\n\t\tbreak;\n\t}\n\n\tcase WEAPONTYPE_FALL: {\n\t\tped->m_vecMoveSpeed = ped->m_pMyVehicle->m_vecMoveSpeed;\n\t\tfloat forceXY = -0.6*m_fDamageImpulse * ped->m_fMass / m_fMass;\n\t\tped->ApplyMoveForce(m_vecDamageNormal.x*forceXY, m_vecDamageNormal.y*forceXY,\n\t\t\tCGeneral::GetRandomNumberInRange(3.0f, 7.0f));\n\t\tped->m_pCollidingEntity = this;\n\t\tswitch(direction){\n\t\tcase 0: anim = ANIM_STD_HIGHIMPACT_BACK; break;\n\t\tcase 1: anim = ANIM_STD_SPINFORWARD_RIGHT; break;\n\t\tcase 2: anim = ANIM_STD_BIKE_FALLBACK; break;\n\t\tcase 3: anim = ANIM_STD_SPINFORWARD_LEFT; break;\n\t\t}\n\t\tif(m_nWheelsOnGround == 0)\n\t\t\tped->bKnockedOffBike = true;\n\t\tbreak;\n\t}\n\n\tcase WEAPONTYPE_RAMMEDBYCAR: {\n\t\tped->m_vecMoveSpeed = ped->m_pMyVehicle->m_vecMoveSpeed;\n\t\tstatic float minForceZ = 8.0f;\n\t\tstatic float maxForceZ = 15.0f;\n\t\tfloat forceXY = -0.6*m_fDamageImpulse * ped->m_fMass / m_fMass;\n\t\tped->ApplyMoveForce(m_vecDamageNormal.x*forceXY, m_vecDamageNormal.y*forceXY,\n\t\t\tCGeneral::GetRandomNumberInRange(minForceZ, maxForceZ));\n\t\tped->m_pCollidingEntity = this;\n\t\tswitch(direction){\n\t\tcase 0: anim = ANIM_STD_HIGHIMPACT_BACK; break;\n\t\tcase 1: anim = ANIM_STD_SPINFORWARD_RIGHT; break;\n\t\tcase 2: anim = ANIM_STD_HIGHIMPACT_FRONT; break;\n\t\tcase 3: anim = ANIM_STD_SPINFORWARD_LEFT; break;\n\t\t}\n\t\tped->bKnockedOffBike = true;\n\t\tif(ped->IsPlayer())\n\t\t\tped->Say(SOUND_PED_DAMAGE);\n\t\tbreak;\n\t}\n\t}\n\n\tif(weapon == WEAPONTYPE_DROWNING){\n\t\tped->bIsStanding = false;\n\t\tped->bWasStanding = false;\n\t\tped->bIsInTheAir = true;\n\t\tped->bIsInWater = true;\n\t\tped->bTouchingWater = true;\n\t\tCAnimManager::BlendAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_STD_FALL, 4.0f);\n\t}else if(weapon != WEAPONTYPE_UNARMED){\n\t\tif(ped->m_fHealth > 0.0f)\n\t\t\tped->SetFall(1000, anim, 0);\n\t\telse\n\t\t\tped->SetDie(anim);\n\t\tped->bIsStanding = false;\n\t}\n\n\tCEntity *ent = CWorld::TestSphereAgainstWorld(ped->GetPosition()+CVector(0.0f, 0.0, 0.5f), 0.4f, nil, true, false, false, false, false, false);\n\tif(ent == nil)\n\t\tent = CWorld::TestSphereAgainstWorld(ped->GetPosition()+CVector(0.0f, 0.0, 0.8f), 0.4f, nil, true, false, false, false, false, false);\n\tif(ent == nil)\n\t\tent = CWorld::TestSphereAgainstWorld(ped->GetPosition()+CTimer::GetTimeStep()*ped->m_vecMoveSpeed+CVector(0.0f, 0.0, 0.5f), 0.4f, nil, true, false, false, false, false, false);\n\tif(ent == nil)\n\t\tent = CWorld::TestSphereAgainstWorld(ped->GetPosition()+CTimer::GetTimeStep()*ped->m_vecMoveSpeed+CVector(0.0f, 0.0, 0.8f), 0.4f, nil, true, false, false, false, false, false);\n\tif(ent){\n\t\tCColPoint point;\n\t\tent = nil;\n\t\tif(CWorld::ProcessVerticalLine(ped->GetPosition(), ped->GetPosition().z-2.0f, point, ent, true, false, false, false, false, false, nil)){\n\t\t\tif(ped->m_pMyVehicle == nil){\n\t\t\t\tped->m_pMyVehicle = this;\n\t\t\t\tped->PositionPedOutOfCollision();\n\t\t\t\tped->m_pMyVehicle = nil;\n\t\t\t}else\n\t\t\t\tped->PositionPedOutOfCollision();\n\t\t}else\n\t\t\tped->GetMatrix().Translate(CVector(0.0f, 0.0f, -2.0f));\n\t\tped->m_pCollidingEntity = ped->m_pMyVehicle;\n\t\tped->bKnockedOffBike = true;\n\t\tped->bHeadStuckInCollision = true;\n\t}else if(weapon == WEAPONTYPE_RAMMEDBYCAR){\n\t\tif(CWorld::TestSphereAgainstWorld(ped->GetPosition()+CVector(0.0f, 0.0, 1.3f), 0.6f, nil, true, false, false, false, false, false) == nil)\n\t\t\tped->GetMatrix().Translate(CVector(0.0f, 0.0f, 0.5f));\n\t}\n\tped->m_pMyVehicle = nil;\n}\n\nvoid\nCBike::PlayHornIfNecessary(void)\n{\n\tif(AutoPilot.m_bSlowedDownBecauseOfPeds ||\n\t   AutoPilot.m_bSlowedDownBecauseOfCars)\n\t\tPlayCarHorn();\n}\n\nvoid\nCBike::ResetSuspension(void)\n{\n\tint i;\n\tfor(i = 0; i < 2; i++){\n\t\tm_aWheelRotation[i] = 0.0f;\n\t\tm_aWheelState[i] = WHEEL_STATE_NORMAL;\n\t}\n\tfor(i = 0; i < 4; i++){\n\t\tm_aSuspensionSpringRatio[i] = 1.0f;\n\t\tm_aWheelTimer[i] = 0.0f;\n\t}\n}\n\nvoid\nCBike::SetupSuspensionLines(void)\n{\n\tint i;\n\tCVector posn;\n\tfloat suspOffset = 0.0f;\n\tRwFrame *node = nil;\n\tCVehicleModelInfo *mi = (CVehicleModelInfo*)CModelInfo::GetModelInfo(GetModelIndex());\n\tCColModel *colModel = mi->GetColModel();\n\tRwMatrix *mat = RwMatrixCreate();\n\n\tbool initialized = colModel->lines[0].p0.z != FAKESUSPENSION;\n\n\tfor(i = 0; i < 4; i++){\n\t\tif(initialized){\n\t\t\tposn = colModel->lines[i].p0;\n\t\t\tif(i < 2)\n\t\t\t\tposn.z = m_aWheelBasePosition[0];\n\t\t\telse\n\t\t\t\tposn.z = m_aWheelBasePosition[1];\n\t\t}else{\n\t\t\tswitch(i){\n\t\t\tcase BIKESUSP_F1:\n\t\t\t\tnode = m_aBikeNodes[BIKE_WHEEL_FRONT];\n\t\t\t\tsuspOffset = 0.25f*mi->m_wheelScale;\n\t\t\t\tbreak;\n\t\t\tcase BIKESUSP_F2:\n\t\t\t\tnode = m_aBikeNodes[BIKE_WHEEL_FRONT];\n\t\t\t\tsuspOffset = -0.25f*mi->m_wheelScale;\n\t\t\t\tbreak;\n\t\t\tcase BIKESUSP_R1:\n\t\t\t\tnode = m_aBikeNodes[BIKE_WHEEL_REAR];\n\t\t\t\tsuspOffset = 0.25f*mi->m_wheelScale;\n\t\t\t\tbreak;\n\t\t\tcase BIKESUSP_R2:\n\t\t\t\tnode = m_aBikeNodes[BIKE_WHEEL_REAR];\n\t\t\t\tsuspOffset = -0.25f*mi->m_wheelScale;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tGetRelativeMatrix(mat, node, node);\n\t\t\tposn = *RwMatrixGetPos(mat);\n\t\t\tif(i == BIKESUSP_F1)\n\t\t\t\tm_aWheelBasePosition[BIKEWHEEL_FRONT] = posn.z;\n\t\t\telse if(i == BIKESUSP_R1){\n\t\t\t\tm_aWheelBasePosition[BIKEWHEEL_REAR] = posn.z;\n\n\t\t\t\tGetRelativeMatrix(mat, m_aBikeNodes[BIKE_FORKS_REAR], m_aBikeNodes[BIKE_FORKS_REAR]);\n\t\t\t\tfloat dz = posn.z - RwMatrixGetPos(mat)->z;\n\t\t\t\tfloat dy = posn.y - RwMatrixGetPos(mat)->y;\n\t\t\t\tm_fRearForkLength = Sqrt(SQR(dy) + SQR(dz));\n\t\t\t\tassert(m_fRearForkLength != 0.0f);\t// we want to divide by this\n\t\t\t}\n\t\t\tposn.y += suspOffset;\n\t\t}\n\n\t\t// uppermost wheel position\n\t\tposn.z += pHandling->fSuspensionUpperLimit;\n\t\tcolModel->lines[i].p0 = posn;\n\n\t\t// lowermost wheel position\n\t\tposn.z += pHandling->fSuspensionLowerLimit - pHandling->fSuspensionUpperLimit;\n\t\t// lowest point on tyre\n\t\tposn.z -= mi->m_wheelScale*0.5f;\n\t\tcolModel->lines[i].p1 = posn;\n\n\t\t// this is length of the spring at rest\n\t\tm_aSuspensionSpringLength[i] = pHandling->fSuspensionUpperLimit - pHandling->fSuspensionLowerLimit;\n\t\tm_aSuspensionLineLength[i] = colModel->lines[i].p0.z - colModel->lines[i].p1.z;\n\t}\n\n\tif(!initialized){\n\t\tGetRelativeMatrix(mat, m_aBikeNodes[BIKE_FORKS_FRONT], m_aBikeNodes[BIKE_FORKS_FRONT]);\n\t\tm_fFrontForkY = RwMatrixGetPos(mat)->y;\n\t\tm_fFrontForkZ = RwMatrixGetPos(mat)->z;\n\t}\n\n\t// Compress spring somewhat to get normal height on road\n\tm_fHeightAboveRoad = m_aSuspensionSpringLength[0]*(1.0f - 1.0f/(4.0f*pHandling->fSuspensionForceLevel))\n\t\t\t- colModel->lines[0].p0.z + mi->m_wheelScale*0.5f;\n\tfor(i = 0; i < 2; i++)\n\t\tm_aWheelPosition[i] = mi->m_wheelScale*0.5f - m_fHeightAboveRoad;\n\n\t// adjust col model to include suspension lines\n\tif(colModel->boundingBox.min.z > colModel->lines[0].p1.z)\n\t\tcolModel->boundingBox.min.z = colModel->lines[0].p1.z;\n\tfloat radius = Max(colModel->boundingBox.min.Magnitude(), colModel->boundingBox.max.Magnitude());\n\tif(colModel->boundingSphere.radius < radius)\n\t\tcolModel->boundingSphere.radius = radius;\n\n#ifdef FIX_BUGS\n\tRwMatrixDestroy(mat);\n#endif\n}\n\nvoid\nCBike::CalculateLeanMatrix(void)\n{\n\tif(bLeanMatrixClean)\n\t\treturn;\n\n\tCMatrix mat;\n\tmat.SetRotateX(-0.05f*Abs(m_fLeanLRAngle));\n\tmat.RotateY(m_fLeanLRAngle);\n\tm_leanMatrix = GetMatrix();\n\tm_leanMatrix = m_leanMatrix * mat;\n\t// place wheel back on ground\n\tm_leanMatrix.GetPosition() += GetUp()*(1.0f-Cos(m_fLeanLRAngle))*GetColModel()->boundingBox.min.z;\n\tbLeanMatrixClean = true;\n}\n\nvoid\nCBike::GetCorrectedWorldDoorPosition(CVector &pos, CVector p1, CVector p2)\n{\n\tCVector &fwd = GetForward();\n\tCVector rightWorld = CrossProduct(fwd, CVector(0.0f, 0.0f, 1.0f));\n\tCVector upWorld = CrossProduct(rightWorld, fwd);\n\tCColModel *colModel = GetColModel();\n\tfloat onSide = DotProduct(GetUp(), rightWorld);\n\tfloat diff = Max(colModel->boundingBox.max.z-colModel->boundingBox.max.x, 0.0f);\n\tpos = CVector(0.0f, 0.0f, 0.0f);\n\tfloat y = p2.y - p1.y;\n\tfloat x = onSide*diff + p2.x + p1.x;\n\tfloat z = p2.z - p1.z;\n\tpos = x*rightWorld + y*fwd + z*upWorld + GetPosition();\n}\n\nvoid\nCBike::Fix(void)\n{\n\tbIsDamaged = false;\n\tbIsOnFire = false;\n\tm_wheelStatus[0] = WHEEL_STATUS_OK;\n\tm_wheelStatus[1] = WHEEL_STATUS_OK;\n}\n\nvoid\nCBike::SetupModelNodes(void)\n{\n\tint i;\n\tfor(i = 0; i < BIKE_NUM_NODES; i++)\n\t\tm_aBikeNodes[i] = nil;\n\tCClumpModelInfo::FillFrameArray(GetClump(), m_aBikeNodes);\n}\n\nvoid\nCBike::ReduceHornCounter(void)\n{\n\tif(m_nCarHornTimer != 0)\n\t\tm_nCarHornTimer--;\n}\n\n#ifdef COMPATIBLE_SAVES\nvoid\nCBike::Save(uint8*& buf)\n{\n\tCVehicle::Save(buf);\n\tSkipSaveBuf(buf, 1260 - 672);\n}\n\nvoid\nCBike::Load(uint8*& buf)\n{\n\tCVehicle::Load(buf);\n\tSkipSaveBuf(buf, 1260 - 672);\n}\n#endif\n"
  },
  {
    "path": "src/vehicles/Bike.h",
    "content": "#pragma once\n\n#include \"Vehicle.h\"\n#include \"Skidmarks.h\"\n#include \"AnimManager.h\"\n\nenum eBikeNodes {\n\tBIKE_NODE_NONE,\n\tBIKE_CHASSIS,\n\tBIKE_FORKS_FRONT,\n\tBIKE_FORKS_REAR,\n\tBIKE_WHEEL_FRONT,\n\tBIKE_WHEEL_REAR,\n\tBIKE_MUDGUARD,\n\tBIKE_HANDLEBARS,\n\tBIKE_NUM_NODES\n};\n\nenum {\n\tBIKEWHEEL_FRONT,\n\tBIKEWHEEL_REAR,\n};\n\nenum {\n\tBIKESUSP_F1,\n\tBIKESUSP_F2,\n\tBIKESUSP_R1,\n\tBIKESUSP_R2,\n};\n\nclass CBike : public CVehicle\n{\npublic:\n\tRwFrame *m_aBikeNodes[BIKE_NUM_NODES];\n\tbool bLeanMatrixClean;\n\tCMatrix m_leanMatrix;\n\tCVector m_vecAvgSurfaceNormal;\n\tCVector m_vecAvgSurfaceRight;\n\ttBikeHandlingData *pBikeHandling;\n\tAssocGroupId m_bikeAnimType;\n\tuint8 m_wheelStatus[2];\n\tCColPoint m_aWheelColPoints[4];\n\tfloat m_aSuspensionSpringRatio[4];\n\tfloat m_aSuspensionSpringRatioPrev[4];\n\tfloat m_aWheelTimer[4];\n\tfloat m_bike_unused1;\n\teSkidmarkType m_aWheelSkidmarkType[2];\n\tbool m_aWheelSkidmarkBloody[2];\n\tbool m_aWheelSkidmarkUnk[2];\n\tfloat m_aWheelRotation[2];\n\tfloat m_aWheelSpeed[2];\n\tfloat m_aWheelPosition[2];\n\tfloat m_aWheelBasePosition[2];\n\tfloat m_aSuspensionSpringLength[4];\n\tfloat m_aSuspensionLineLength[4];\n\tfloat m_fHeightAboveRoad;\n\tfloat m_fTraction;\n\tfloat m_fRearForkLength;\n\tfloat m_fFrontForkY;\n\tfloat m_fFrontForkZ;\n\tfloat m_fFrontForkSlope;\n\tfloat m_fWheelAngle;\n\tfloat m_fLeanLRAngle;\n\tfloat m_fLeanLRAngle2;\n\tfloat m_fLeanInput;\n\tfloat m_fPedLeanAmountLR;\n\tfloat m_fPedLeanAmountUD;\n\tuint8 m_bike_unused2;\n\tuint8 unused[3];\t// looks like padding..but for what?\n\tuint8 m_bike_flag01 : 1;\n\tuint8 m_bike_flag02 : 1;\n\tuint8 bWaterTight : 1;\n\tuint8 bIsBeingPickedUp : 1;\n\tuint8 bIsStanding : 1;\n\tuint8 bExtraSpeed : 1;\t// leaning forward\n\tuint8 bIsOnFire : 1;\n\tuint8 bWheelieCam : 1;\n\tint16 m_doingBurnout;\n\tfloat m_fTireTemperature;\n\tfloat m_fBrakeDestabilization;\n\tfloat m_fVelocityChangeForAudio;\n\tfloat m_fFireBlowUpTimer;\n\tCPhysical *m_aGroundPhysical[4];\n\tCVector m_aGroundOffset[4];\n\tCEntity *m_pSetOnFireEntity;\n\tuint8 m_nWheelsOnGround;\n\tuint8 m_nDriveWheelsOnGround;\n\tuint8 m_nDriveWheelsOnGroundPrev;\n\tfloat m_fGasPedalAudio;\n\ttWheelState m_aWheelState[2];\n\n\tCBike(int32 id, uint8 CreatedBy);\n\n\t// from CEntity\n\tvoid SetModelIndex(uint32 id);\n\tvoid ProcessControl(void);\n\tvoid Teleport(CVector v);\n\tvoid PreRender(void);\n\tvoid Render(void);\n\n\t// from CPhysical\n\tint32 ProcessEntityCollision(CEntity *ent, CColPoint *colpoints);\n\n\t// from CVehicle\n\tvoid ProcessControlInputs(uint8);\n\tvoid GetComponentWorldPosition(int32 component, CVector &pos);\n\tbool IsComponentPresent(int32 component);\n\tvoid SetComponentRotation(int32 component, CVector rotation);\n\tbool IsDoorReady(eDoors door);\n\tbool IsDoorFullyOpen(eDoors door);\n\tbool IsDoorClosed(eDoors door);\n\tbool IsDoorMissing(eDoors door);\n\tvoid RemoveRefsToVehicle(CEntity *ent);\n\tvoid BlowUpCar(CEntity *ent);\n\tbool SetUpWheelColModel(CColModel *colModel);\n\tvoid BurstTyre(uint8 tyre, bool applyForces);\n\tbool IsRoomForPedToLeaveCar(uint32 component, CVector *doorOffset);\n\tfloat GetHeightAboveRoad(void);\n\tvoid PlayCarHorn(void);\n\n\tvoid KnockOffRider(eWeaponType weapon, uint8 direction, CPed *ped, bool bGetBackOn);\n\tvoid VehicleDamage(void);\n\tvoid ProcessBuoyancy(void);\n\tvoid DoDriveByShootings(void);\n\tvoid AddDamagedVehicleParticles(void);\n\tint32 AddWheelDirtAndWater(CColPoint *colpoint, uint32 belowEffectSpeed);\n\tvoid PlayHornIfNecessary(void);\n\tvoid ResetSuspension(void);\n\tvoid SetupSuspensionLines(void);\n\tvoid CalculateLeanMatrix(void);\n\tvoid GetCorrectedWorldDoorPosition(CVector &pos, CVector p1, CVector p2);\n\n\tvoid Fix(void);\n\tvoid SetupModelNodes(void);\n\tvoid ReduceHornCounter(void);\n\n#ifdef COMPATIBLE_SAVES\n\tvirtual void Save(uint8*& buf);\n\tvirtual void Load(uint8*& buf);\n#endif\n\tstatic const uint32 nSaveStructSize;\n};\n\n// These functions and function names are made up\n\ninline int8 GetBikeDoorFlag(int32 carnode) {\n\tswitch (carnode) {\n\tcase CAR_DOOR_RR:\n\tcase CAR_DOOR_LR:\n\t\treturn CAR_DOOR_FLAG_RR | CAR_DOOR_FLAG_LR;\n\tcase CAR_DOOR_RF:\n\tcase CAR_DOOR_LF:\n\t\treturn CAR_DOOR_FLAG_RF | CAR_DOOR_FLAG_LF;\n\tdefault:\n\t\treturn CAR_DOOR_FLAG_UNKNOWN;\n\t}\n}\n\n// for m_nGettingOutFlags\ninline int8 GetBikeDoorFlagInclJumpInFromFront(int32 carnode) {\n\tswitch (carnode) {\n\t\tcase CAR_DOOR_RR:\n\t\tcase CAR_DOOR_LR:\n\t\t\treturn CAR_DOOR_FLAG_RR | CAR_DOOR_FLAG_LR;\n\t\tcase CAR_DOOR_RF:\n\t\tcase CAR_DOOR_LF:\n\t\tcase CAR_WINDSCREEN:\n\t\t\treturn CAR_DOOR_FLAG_RF | CAR_DOOR_FLAG_LF;\n\t\tdefault:\n\t\t\treturn CAR_DOOR_FLAG_UNKNOWN;\n\t}\n}"
  },
  {
    "path": "src/vehicles/Boat.cpp",
    "content": "#include \"common.h\"\n\n#include \"main.h\"\n#include \"General.h\"\n#include \"Timecycle.h\"\n#include \"Weather.h\"\n#include \"HandlingMgr.h\"\n#include \"CarAI.h\"\n#include \"CarCtrl.h\"\n#include \"RwHelper.h\"\n#include \"ModelIndices.h\"\n#include \"VisibilityPlugins.h\"\n#include \"DMAudio.h\"\n#include \"Camera.h\"\n#include \"Darkel.h\"\n#include \"Explosion.h\"\n#include \"Particle.h\"\n#include \"ParticleObject.h\"\n#include \"WaterLevel.h\"\n#include \"Floater.h\"\n#include \"World.h\"\n#include \"Stats.h\"\n#include \"Pools.h\"\n#include \"Pad.h\"\n#include \"Boat.h\"\n#include \"AnimBlendAssociation.h\"\n#include \"RpAnimBlend.h\"\n#include \"Record.h\"\n#include \"Shadows.h\"\n#include \"Wanted.h\"\n\n#define INVALID_ORIENTATION (-9999.99f)\n\nfloat CBoat::MAX_WAKE_LENGTH = 50.0f;\nfloat CBoat::MIN_WAKE_INTERVAL = 2.0f;\nfloat CBoat::WAKE_LIFETIME = 150.0f;\n\nfloat fShapeLength = 0.4f;\nfloat fShapeTime = 0.05f;\nfloat fRangeMult = 0.6f;\nfloat fTimeMult = 1.2f/CBoat::WAKE_LIFETIME;\n\nCBoat *CBoat::apFrameWakeGeneratingBoats[4];\n\nconst uint32 CBoat::nSaveStructSize =\n#ifdef COMPATIBLE_SAVES\n\t1216;\n#else\n\tsizeof(CBoat);\n#endif\n\nCBoat::CBoat(int mi, uint8 owner) : CVehicle(owner)\n{\n\tCVehicleModelInfo *minfo = (CVehicleModelInfo*)CModelInfo::GetModelInfo(mi);\n\tm_vehType = VEHICLE_TYPE_BOAT;\n\tm_fAccelerate = 0.0f;\n\tm_fBrake = 0.0f;\n\tm_fSteeringLeftRight = 0.0f;\n\tm_nPadID = 0;\n\tm_fMovingRotation = 0.0f;\n\tm_fMovingSpeed = 0.0f;\n\tm_skimmerThingTimer = 0.0f;\n\tm_nPoliceShoutTimer = CTimer::GetTimeInMilliseconds();\n\tSetModelIndex(mi);\n\n\tpHandling = mod_HandlingManager.GetHandlingData((tVehicleType)minfo->m_handlingId);\n\tpFlyingHandling = mod_HandlingManager.GetFlyingPointer((tVehicleType)minfo->m_handlingId);\n\tpBoatHandling = mod_HandlingManager.GetBoatPointer((tVehicleType)minfo->m_handlingId);\n\tminfo->ChooseVehicleColour(m_currentColour1, m_currentColour2);\n\n\tm_fMass = pHandling->fMass;\n\tm_fTurnMass = pHandling->fTurnMass / 2.0f;\n\tm_vecCentreOfMass = pHandling->CentreOfMass;\n\tm_fAirResistance = pHandling->Dimension.x * pHandling->Dimension.z / m_fMass;\n\tm_fElasticity = 0.1f;\n\tm_fBuoyancy = pHandling->fBuoyancy;\n\tm_fSteerAngle = 0.0f;\n\tm_fGasPedal = 0.0f;\n\tm_fBrakePedal = 0.0f;\n\n\tm_boat_unused3 = false;\n\n\tm_fVolumeUnderWater = 7.0f;\n\tm_fPrevVolumeUnderWater = 7.0f;\n\tm_vecBuoyancePoint = CVector(0.0f, 0.0f, 0.0f);\n\n\tm_nDeltaVolumeUnderWater = 0;\n\tbBoatInWater = true;\n\tbPropellerInWater = true;\n\n\tbIsInWater = true;\n\n\tm_phys_unused1 = 0.0f;\n\tm_boat_unused2 = 0;\n\tm_bIsAnchored = true;\n\tm_fOrientation = INVALID_ORIENTATION;\n\tbTouchingWater = true;\n\tm_fDamage = 0.0f;\n\tm_pSetOnFireEntity = nil;\n\tm_nNumWakePoints = 0;\n\n\tfor (int16 i = 0; i < ARRAY_SIZE(m_afWakePointLifeTime); i++)\n\t\tm_afWakePointLifeTime[i] = 0.0f;\n\n\tm_nAmmoInClip = 20;\n\n\tif(GetModelIndex() == MI_MARQUIS)\n\t\tm_boom.Init(-PI/10.0f, PI/10.0f, 0, 2);\n\telse\n\t\tm_boom.Init(-PI/5.0f, PI/5.0f, 0, 2);\n}\n\nvoid\nCBoat::SetModelIndex(uint32 id)\n{\n\tCVehicle::SetModelIndex(id);\n\tSetupModelNodes();\n}\n\nvoid\nCBoat::GetComponentWorldPosition(int32 component, CVector &pos)\n{\n\tpos = *RwMatrixGetPos(RwFrameGetLTM(m_aBoatNodes[component]));\n}\n\nvoid\nCBoat::ProcessControl(void)\n{\n\tbool onLand = m_fDamageImpulse > 0.0f && m_vecDamageNormal.z > 0.1f;\n\n\tPruneWakeTrail();\n\n\tif(bRenderScorched)\n\t\tm_fBuoyancy *= 0.99f;\n\n#ifdef FIX_BUGS\n\tif(FindPlayerPed() && FindPlayerPed()->m_pWanted->GetWantedLevel() > 0 && GetModelIndex() == MI_PREDATOR){\n#else\n\tif(FindPlayerPed()->m_pWanted->GetWantedLevel() > 0 && GetModelIndex() == MI_PREDATOR){\n#endif\n\t\tCVehicle *playerVeh = FindPlayerVehicle();\n\t\tif(playerVeh && playerVeh->GetVehicleAppearance() == VEHICLE_APPEARANCE_BOAT &&\n\t\t   (AutoPilot.m_nCarMission == MISSION_RAMPLAYER_FARAWAY || \n\t\t    AutoPilot.m_nCarMission == MISSION_RAMPLAYER_CLOSE || \n\t\t    AutoPilot.m_nCarMission == MISSION_BLOCKPLAYER_FARAWAY || \n\t\t    AutoPilot.m_nCarMission == MISSION_BLOCKPLAYER_CLOSE || \n\t\t    AutoPilot.m_nCarMission == MISSION_ATTACKPLAYER) &&\n\t\t   CTimer::GetTimeInMilliseconds() > m_nPoliceShoutTimer){\n\t\t\tDMAudio.PlayOneShot(m_audioEntityId, SOUND_PED_VCPA_PLAYER_FOUND, 0.0f);\n\t\t\tm_nPoliceShoutTimer = CTimer::GetTimeInMilliseconds() + 4500 + (CGeneral::GetRandomNumber()&0xFFF);\n\t\t}\n\t}\n\n\tint r, g, b;\n\tRwRGBA dropColor = { 0, 0, 0, 0 };\n\tRwRGBA splashColor, jetColor;\n\tr = 127.5f*(CTimeCycle::GetAmbientRed_Obj() + 0.5f*CTimeCycle::GetDirectionalRed());\n\tg = 127.5f*(CTimeCycle::GetAmbientGreen_Obj() + 0.5f*CTimeCycle::GetDirectionalGreen());\n\tb = 127.5f*(CTimeCycle::GetAmbientBlue_Obj() + 0.5f*CTimeCycle::GetDirectionalBlue());\n\tr = clamp(r, 0, 255);\n\tg = clamp(g, 0, 255);\n\tb = clamp(b, 0, 255);\n\tsplashColor.red = r;\n\tsplashColor.green = g;\n\tsplashColor.blue = b;\n\tsplashColor.alpha = CGeneral::GetRandomNumberInRange(160, 196);\n\n\tr = 229.5f*(CTimeCycle::GetAmbientRed() + 0.85f*CTimeCycle::GetDirectionalRed());\n\tg = 229.5f*(CTimeCycle::GetAmbientGreen() + 0.85f*CTimeCycle::GetDirectionalGreen());\n\tb = 229.5f*(CTimeCycle::GetAmbientBlue() + 0.85f*CTimeCycle::GetDirectionalBlue());\n\tr = clamp(r, 0, 255);\n\tg = clamp(g, 0, 255);\n\tb = clamp(b, 0, 255);\n\tjetColor.red = r;\n\tjetColor.green = g;\n\tjetColor.blue = b;\n\tjetColor.alpha = CGeneral::GetRandomNumberInRange(196, 228);\n\n\tCGeneral::GetRandomNumber();\t// unused\n\n\tUpdateClumpAlpha();\n\tProcessCarAlarm();\n\n\tswitch(GetStatus()){\n\tcase STATUS_PLAYER:\n\t\tm_bIsAnchored = false;\n\t\tm_fOrientation = INVALID_ORIENTATION;\n\t\tProcessControlInputs(0);\n\t\tif(GetModelIndex() == MI_PREDATOR)\n\t\t\tDoFixedMachineGuns();\n\n\t\tif (!CRecordDataForChase::IsRecording())\n\t\t\tDoDriveByShootings();\n\t\tbreak;\n\tcase STATUS_SIMPLE:\n\t\tm_bIsAnchored = false;\n\t\tm_fOrientation = INVALID_ORIENTATION;\n\t\tCCarAI::UpdateCarAI(this);\n\t\tCPhysical::ProcessControl();\n\t\tbBoatInWater = true;\n\t\tbPropellerInWater = true;\n\t\tbIsInWater = true;\n\t\treturn;\n\tcase STATUS_PHYSICS:\n\t\tm_bIsAnchored = false;\n\t\tm_fOrientation = INVALID_ORIENTATION;\n\t\tCCarAI::UpdateCarAI(this);\n\t\tCCarCtrl::SteerAICarWithPhysics(this);\n\t\tbreak;\n\tcase STATUS_ABANDONED:\n\tcase STATUS_WRECKED:\n\t\tbBoatInWater = true;\n\t\tbPropellerInWater = true;\n\t\tbIsInWater = true;\n\t\tm_fSteerAngle = 0.0;\n\t\tbIsHandbrakeOn = false;\n\t\tm_fBrakePedal = 0.5f;\n\t\tm_fGasPedal = 0.0f;\n\t\tif((GetPosition() - FindPlayerCentreOfWorld_NoSniperShift()).Magnitude() > 150.0f){\n\t\t\tm_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);\n\t\t\tm_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f);\n\t\t\treturn;\n\t\t}\n\t\tbreak;\n\tdefault: break;\n\t}\n\n\tfloat collisionDamage = pHandling->fCollisionDamageMultiplier * m_fDamageImpulse;\n#ifdef FIX_BUGS\n\tif(GetStatus() == STATUS_PLAYER && CStats::GetPercentageProgress() >= 100.0f)\n\t\tcollisionDamage *= 0.5f;\n\tif (collisionDamage > 25.0f && GetStatus() != STATUS_WRECKED && !bCollisionProof) {\n#else\n\tif(collisionDamage > 25.0f && GetStatus() != STATUS_WRECKED){\n#endif\n\t\tfloat prevHealth = m_fHealth;\n\t\tif(prevHealth >= 250.0f){\n#ifndef FIX_BUGS\n\t\t\t// if collisionDamage < 50 we actually increase health here...\n\t\t\tif(GetStatus() == STATUS_PLAYER && CStats::GetPercentageProgress() >= 100.0f)\n\t\t\t\tcollisionDamage *= 0.5f;\n#endif\n\t\t\tif(this == FindPlayerVehicle()){\n\t\t\t\tif(bTakeLessDamage)\n\t\t\t\t\tm_fHealth -= (collisionDamage-25.0f)/6.0f;\n\t\t\t\telse\n\t\t\t\t\tm_fHealth -= (collisionDamage-25.0f)/2.0f;\n\t\t\t}else{\n\t\t\t\tif(collisionDamage > 60.0f && pDriver)\n\t\t\t\t\tpDriver->Say(SOUND_PED_ANNOYED_DRIVER);\n\t\t\t\tif(bTakeLessDamage)\n\t\t\t\t\tm_fHealth -= (collisionDamage-25.0f)/12.0f;\n\t\t\t\telse\n\t\t\t\t\tm_fHealth -= (collisionDamage-25.0f)/4.0f;\n\t\t\t}\n\n\t\t\tif(m_fHealth <= 0.0f && prevHealth > 0.0f){\n\t\t\t\tm_fHealth = 1.0f;\n\t\t\t\tm_pSetOnFireEntity = m_pDamageEntity;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Damage particles\n\tif(m_fHealth <= 460.0f && GetStatus() != STATUS_WRECKED &&\n\t   Abs(GetPosition().x - TheCamera.GetPosition().x) < 200.0f &&\n\t   Abs(GetPosition().y - TheCamera.GetPosition().y) < 200.0f){\n\t\tfloat speedSq = m_vecMoveSpeed.MagnitudeSqr();\n\t\tCVector smokeDir = 0.8f*m_vecMoveSpeed;\n\t\tCVector smokePos;\n\t\tswitch(GetModelIndex()){\n\t\tcase MI_SPEEDER:\n\t\t\tsmokePos = CVector(0.4f, -2.4f, 0.8f);\n\t\t\tsmokeDir += 0.05f*GetRight();\n\t\t\tsmokeDir.z += 0.2f*m_vecMoveSpeed.z;\n\t\t\tbreak;\n\t\tcase MI_REEFER:\n\t\t\tsmokePos = CVector(2.0f, -1.0f, 0.5f);\n\t\t\tsmokeDir += 0.07f*GetRight();\n\t\t\tbreak;\n\t\tcase MI_PREDATOR:\n\t\tdefault:\n\t\t\tsmokePos = CVector(-1.5f, -0.5f, 1.2f);\n\t\t\tsmokeDir += -0.08f*GetRight();\n\t\t\tbreak;\n\t\t}\n\n\t\tsmokePos = GetMatrix() * smokePos;\n\n\t\t// On fire\n\t\tif(m_fHealth < 250.0f){\n\t\t\tCParticle::AddParticle(PARTICLE_CARFLAME, smokePos,\n\t\t\t\tCVector(0.0f, 0.0f, CGeneral::GetRandomNumberInRange(2.25f/200.0f, 0.09f)),\n\t\t\t\tnil, 0.9f);\n\t\t\tCVector smokePos2 = smokePos;\n\t\t\tsmokePos2.x += CGeneral::GetRandomNumberInRange(-2.25f/4.0f, 2.25f/4.0f);\n\t\t\tsmokePos2.y += CGeneral::GetRandomNumberInRange(-2.25f/4.0f, 2.25f/4.0f);\n\t\t\tsmokePos2.z += CGeneral::GetRandomNumberInRange(2.25f/4.0f, 2.25f);\n\t\t\tCParticle::AddParticle(PARTICLE_ENGINE_SMOKE2, smokePos2, CVector(0.0f, 0.0f, 0.0f));\n\n\t\t\tm_fDamage += CTimer::GetTimeStepInMilliseconds();\n\t\t\tif(m_fDamage > 5000.0f)\n\t\t\t\tBlowUpCar(m_pSetOnFireEntity);\n\t\t}\n\n\t\tif(speedSq < 0.25f && (CTimer::GetFrameCounter() + m_randomSeed) & 1)\n\t\t\tCParticle::AddParticle(PARTICLE_ENGINE_STEAM, smokePos, smokeDir);\n\t\tif(speedSq < 0.25f && m_fHealth <= 390.0f)\n\t\t\tCParticle::AddParticle(PARTICLE_ENGINE_SMOKE, smokePos, 1.25f*smokeDir);\n\t}\n\n\tbool bSeparateTurnForce = bHasHitWall;\n\tCPhysical::ProcessControl();\n\n\tCVector buoyanceImpulse(0.0f, 0.0f, 0.0f);\n\tCVector buoyancePoint(0.0f, 0.0f, 0.0f);\n\tif(mod_Buoyancy.ProcessBuoyancyBoat(this, pHandling->fBuoyancy, &buoyancePoint, &buoyanceImpulse, bSeparateTurnForce)){\n\t\t// Process boat in water\n\t\tif(0.1f * m_fMass * GRAVITY*CTimer::GetTimeStep() < buoyanceImpulse.z){\n\t\t\tbBoatInWater = true;\n\t\t\tbIsInWater = true;\n\t\t\tif (GetUp().z < -0.6f && Abs(GetMoveSpeed().x) < 0.05 && Abs(GetMoveSpeed().y) < 0.05) {\n\t\t\t\tbIsDrowning = true;\n\t\t\t\tif (pDriver){\n\t\t\t\t\tpDriver->bTouchingWater = true;\n\t\t\t\t\tpDriver->InflictDamage(nil, WEAPONTYPE_DROWNING, CTimer::GetTimeStep(), PEDPIECE_TORSO, 0);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t\tbIsDrowning = false;\n\t\t}else{\n\t\t\tbBoatInWater = false;\n\t\t\tbIsInWater = false;\n\t\t\tbIsDrowning = false;\n\t\t}\n\n\t\tm_fVolumeUnderWater = mod_Buoyancy.m_volumeUnderWater;\n\t\tm_vecBuoyancePoint = buoyancePoint;\n\t\tif(GetModelIndex() == MI_SKIMMER && GetUp().z < -0.5f && Abs(m_vecMoveSpeed.x) < 0.2f && Abs(m_vecMoveSpeed.y) < 0.2f)\n\t\t\tApplyMoveForce(0.03f*buoyanceImpulse);\n\t\telse\n\t\t\tApplyMoveForce(buoyanceImpulse);\n\t\tif(bSeparateTurnForce)\n\t\t\tApplyTurnForce(0.4f*buoyanceImpulse, buoyancePoint);\n\n\t\t// TODO: what is this?\n\t\tif(GetModelIndex() == MI_SKIMMER)\n\t\t\tif(m_skimmerThingTimer != 0.0f ||\n\t\t\t   GetForward().z < -0.5f && GetUp().z > -0.5f && m_vecMoveSpeed.z < -0.15f &&\n\t\t\t   buoyanceImpulse.z > 0.01f*m_fMass * GRAVITY*CTimer::GetTimeStep() &&\n\t\t\t   buoyanceImpulse.z < 0.4f*m_fMass * GRAVITY*CTimer::GetTimeStep()){\n\t\t\t\tfloat turnImpulse = -0.00017f*GetForward().z*buoyanceImpulse.z * m_fMass*CTimer::GetTimeStep();\n\t\t\t\tApplyTurnForce(turnImpulse*GetForward(), GetUp());\n\t\t\t\tbBoatInWater = false;\n\t\t\t\t//BUG? aren't we forgetting the timestep here?\n\t\t\t\tfloat moveImpulse = -0.5f*DotProduct(m_vecMoveSpeed, GetForward()) * m_fMass;\n\t\t\t\tApplyMoveForce(moveImpulse*GetForward());\n\t\t\t\tif(m_skimmerThingTimer == 0.0f)\n\t\t\t\t\tm_skimmerThingTimer = CTimer::GetTimeInMilliseconds() + 300.0f;\n\t\t\t\telse if(m_skimmerThingTimer < CTimer::GetTimeInMilliseconds())\n\t\t\t\t\tm_skimmerThingTimer = 0.0f;\n\t\t\t}\n\n\t\tif(!onLand && bBoatInWater && GetUp().z > 0.0f){\n\t\t\tfloat impulse = m_vecMoveSpeed.MagnitudeSqr()*pBoatHandling->fAqPlaneForce*buoyanceImpulse.z*CTimer::GetTimeStep()*0.5f;\n\t\t\tif(GetModelIndex() == MI_SKIMMER)\n\t\t\t\timpulse *= 1.0f + m_fGasPedal;\n\t\t\telse if(m_fGasPedal > 0.05f)\n\t\t\t\timpulse *= m_fGasPedal;\n\t\t\telse\n\t\t\t\timpulse = 0.0f;\n\t\t\timpulse = Min(impulse, GRAVITY*pBoatHandling->fAqPlaneLimit*m_fMass*CTimer::GetTimeStep());\n\t\t\tApplyMoveForce(impulse*GetUp());\n\t\t\tApplyTurnForce(impulse*GetUp(), buoyancePoint - pBoatHandling->fAqPlaneOffset*GetForward());\n\t\t}\n\n\t\t// Handle boat moving forward\n\t\tfloat fwdSpeed = 1.0f;\n\t\tif(Abs(m_fGasPedal) > 0.05f || (fwdSpeed = m_vecMoveSpeed.Magnitude2D()) > 0.01f){\n\t\t\tif(bBoatInWater && fwdSpeed > 0.05f)\n\t\t\t\tAddWakePoint(GetPosition());\n\n\t\t\tfloat steerFactor = 1.0f;\n\t\t\tif(GetStatus() == STATUS_PLAYER){\n\t\t\t\tfloat steerLoss = DotProduct(m_vecMoveSpeed, GetForward())*pHandling->fTractionBias;\n\t\t\t\tif(CPad::GetPad(0)->GetHandBrake())\n\t\t\t\t\tsteerLoss *= 0.5f;\n\t\t\t\tsteerFactor -= steerLoss;\n\t\t\t\tsteerFactor = clamp(steerFactor, 0.0f, 1.0f);\n\t\t\t}\n\n\t\t\tCVector boundMin = GetColModel()->boundingBox.min;\n\t\t\tCVector propeller(0.0f, boundMin.y*pBoatHandling->fThrustY, boundMin.z*pBoatHandling->fThrustZ);\n\t\t\tpropeller = Multiply3x3(GetMatrix(), propeller);\n\t\t\tCVector propellerWorld = GetPosition() + propeller;\n\n\t\t\tfloat steerSin = Sin(-m_fSteerAngle * steerFactor);\n\t\t\tfloat steerCos = Cos(-m_fSteerAngle * steerFactor);\n\t\t\tfloat waterLevel;\n\t\t\tCWaterLevel::GetWaterLevel(propellerWorld, &waterLevel, true);\n\t\t\tif(propellerWorld.z-0.5f < waterLevel){\n\t\t\t\tfloat propellerDepth = waterLevel - (propellerWorld.z - 0.5f);\n\t\t\t\tif(propellerDepth > 1.0f)\n\t\t\t\t\tpropellerDepth = 1.0f;\n\t\t\t\telse\n\t\t\t\t\tpropellerDepth = SQR(propellerDepth);\n\t\t\t\tbPropellerInWater = true;\n\n\t\t\t\tbool bSlowAhead = false;\n\t\t\t\tif(Abs(m_fGasPedal) > 0.01f && GetModelIndex() != MI_SKIMMER){\n\t\t\t\t\tif(Abs(m_fGasPedal) < 0.05f)\n\t\t\t\t\t\tbSlowAhead = true;\n\n\t\t\t\t\tCVector forceDir = Multiply3x3(GetMatrix(), CVector(-steerSin, steerCos, -Abs(m_fSteerAngle)));\n\t\t\t\t\tCVector force = propellerDepth * m_fGasPedal * 40.0f * pHandling->Transmission.fEngineAcceleration * pHandling->fMass * forceDir;\n\t\t\t\t\tif(force.z > 0.2f)\n\t\t\t\t\t\tforce.z = SQR(1.2f - force.z) + 0.2f;\n\t\t\t\t\tif(onLand){\n\t\t\t\t\t\tif(m_fGasPedal < 0.0f){\n\t\t\t\t\t\t\tforce.x *= 5.0f;\n\t\t\t\t\t\t\tforce.y *= 5.0f;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif(force.z < 0.0f)\n\t\t\t\t\t\t\tforce.z = 0.0f;\n\t\t\t\t\t\tApplyMoveForce(force * CTimer::GetTimeStep());\n\t\t\t\t\t}else{\n\t\t\t\t\t\tApplyMoveForce(force * CTimer::GetTimeStep());\n\t\t\t\t\t\tApplyTurnForce(force * CTimer::GetTimeStep(), propeller - pBoatHandling->fThrustAppZ*GetUp());\n\t\t\t\t\t\tfloat rightForce = -DotProduct(GetRight(), force)*pHandling->fTractionMultiplier;\n\t\t\t\t\t\tApplyTurnForce(rightForce*GetRight() * CTimer::GetTimeStep(), GetUp());\n\t\t\t\t\t}\n\n\t\t\t\t\t// Spray some particles\n\t\t\t\t\tCVector jetDir = -0.04f * force;\n\t\t\t\t\tif(m_fGasPedal > 0.0f){\n\t\t\t\t\t\tif(GetStatus() == STATUS_PLAYER){\n\t\t\t\t\t\t\tCVector sternPos = GetColModel()->boundingBox.min;\n\t\t\t\t\t\t\tsternPos.x = 0.0f;\n\t\t\t\t\t\t\tsternPos.z = 0.0f;\n\t\t\t\t\t\t\tsternPos = Multiply3x3(GetMatrix(), sternPos);\n\n\t\t\t\t\t\t\tCVector wakePos = GetPosition() + sternPos;\n\t\t\t\t\t\t\t// no actual particles for player...\n\t\t\t\t\t\t}else if(IsVisible() && ((CTimer::GetFrameCounter() + m_randomSeed) & 1) &&\n\t\t\t\t\t\t         CVisibilityPlugins::GetDistanceSquaredFromCamera(&propellerWorld) < SQR(70.0f * TheCamera.GenerationDistMultiplier)){\n\t\t\t\t\t\t\tjetDir.z = 0.015f;\n\t\t\t\t\t\t\tjetDir.x *= 3.5f;\n\t\t\t\t\t\t\tjetDir.y *= 3.5f;\n\t\t\t\t\t\t\tpropellerWorld.z += 0.5f;\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_BOAT_SPLASH, propellerWorld, jetDir, nil, 1.25f, jetColor,\n\t\t\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(0, 5),\n\t\t\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(0, 90), 1, 500);\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_CAR_SPLASH, propellerWorld, 0.75f * jetDir, nil, 0.5f, splashColor,\n\t\t\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(0, 30),\n\t\t\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(0, 45), 3, 500);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}else\n\t\t\t\t\tbSlowAhead = true;\n\n\t\t\t\tif(!onLand && bSlowAhead){\n\t\t\t\t\tfloat force = pHandling->fTractionLoss*DotProduct(m_vecMoveSpeed, GetForward());\n\t\t\t\t\tforce = Min(force, 0.01f*m_fTurnMass);\n\t\t\t\t\tif(m_fGasPedal > 0.01f){\n\t\t\t\t\t\tif(GetStatus() == STATUS_PLAYER)\n\t\t\t\t\t\t\tforce *= (0.55f - Abs(m_fGasPedal)) * 1.3f;\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tforce *= (0.55f - Abs(m_fGasPedal)) * 2.5f;\n\t\t\t\t\t}\n\t\t\t\t\tif(m_fGasPedal < 0.0f && force > 0.0f || m_fGasPedal > 0.0f && force < 0.0f)\n\t\t\t\t\t\tforce *= -1.0f;\n\t\t\t\t\tCVector propellerForce = propellerDepth * Multiply3x3(GetMatrix(), force*CVector(-steerSin, 0.0f, 0.0f));\n\t\t\t\t\tApplyMoveForce(propellerForce * CTimer::GetTimeStep());\n\t\t\t\t\tApplyTurnForce(propellerForce * CTimer::GetTimeStep(), propeller);\n\t\t\t\t\tfloat rightForce = -steerSin * force * 0.75f/steerFactor * Max(CTimer::GetTimeStep(), 0.01f);\n\t\t\t\t\tApplyTurnForce(GetRight() * rightForce, GetUp());\n\t\t\t\t}\n\t\t\t}else\n\t\t\t\tbPropellerInWater = false;\n\n\t\t\tif(pHandling->fSuspensionBias != 0.0f){\n\t\t\t\tCVector right = CrossProduct(GetForward(), CVector(0.0f, 0.0f, 1.0f));\n\t\t\t\tfloat rightSpeed = DotProduct(m_vecMoveSpeed, right);\n\t\t\t\tfloat impulse = 0.1f*pHandling->fSuspensionBias * m_fMass * m_fVolumeUnderWater * rightSpeed * CTimer::GetTimeStep();\n\t\t\t\tApplyMoveForce(right - impulse * 0.3f * CVector(-right.y, right.x, 0.0f));\n\t\t\t}\n\n\t\t\tif(GetStatus() == STATUS_PLAYER && CPad::GetPad(0)->GetHandBrake()){\n\t\t\t\tfloat fwdSpeed = DotProduct(m_vecMoveSpeed, GetForward());\n\t\t\t\tif(fwdSpeed > 0.0f){\n\t\t\t\t\tfloat impulse = -0.1f*pHandling->fSuspensionLowerLimit * m_fMass * m_fVolumeUnderWater * fwdSpeed * CTimer::GetTimeStep();\n\t\t\t\t\tApplyMoveForce(impulse * GetForward());\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Slow down or push down boat as it approaches the world limits\n\t\tm_vecMoveSpeed.x = Min(m_vecMoveSpeed.x, -(GetPosition().x - (WORLD_MAX_X-100.0f))*0.01f);\t// east\n\t\tm_vecMoveSpeed.x = Max(m_vecMoveSpeed.x, -(GetPosition().x - (WORLD_MIN_X+100.0f))*0.01f);\t// west\n\t\tm_vecMoveSpeed.y = Min(m_vecMoveSpeed.y, -(GetPosition().y - (WORLD_MAX_Y-100.0f))*0.01f);\t// north\n\t\tm_vecMoveSpeed.y = Max(m_vecMoveSpeed.y, -(GetPosition().y - (WORLD_MIN_Y+100.0f))*0.01f);\t// south\n\n\t\tif(!onLand && bBoatInWater && !bSeparateTurnForce)\n\t\t\tApplyWaterResistance();\n\n\t\tif((GetModelIndex() != MI_SKIMMER || m_skimmerThingTimer == 0.0f) && !bSeparateTurnForce){\n\t\t\t// No idea what exactly is going on here besides drag in YZ\n\t\t\tfloat fx = Pow(pBoatHandling->vecTurnRes.x, CTimer::GetTimeStep());\n\t\t\tfloat fy = Pow(pBoatHandling->vecTurnRes.y, CTimer::GetTimeStep());\n\t\t\tfloat fz = Pow(pBoatHandling->vecTurnRes.z, CTimer::GetTimeStep());\n\t\t\tm_vecTurnSpeed = Multiply3x3(m_vecTurnSpeed, GetMatrix());\t// invert - to local space\n\t\t\t// TODO: figure this out\n\t\t\tfloat magic = 1.0f/(1000.0f * SQR(m_vecTurnSpeed.x) + 1.0f) * fx;\n\t\t\tm_vecTurnSpeed.y *= fy;\n\t\t\tm_vecTurnSpeed.z *= fz;\n\t\t\tfloat forceUp = (magic - 1.0f) * m_vecTurnSpeed.x * m_fTurnMass;\n\t\t\tm_vecTurnSpeed = Multiply3x3(GetMatrix(), m_vecTurnSpeed);\t// back to world\n\t\t\tCVector com = Multiply3x3(GetMatrix(), m_vecCentreOfMass);\n\t\t\tApplyTurnForce(forceUp*GetUp(), com + GetForward());\n\t\t}\n\n\t\tm_nDeltaVolumeUnderWater = (m_fVolumeUnderWater-m_fPrevVolumeUnderWater)*10000;\n\n\t\t// Falling into water\n\t\tif(!onLand && bBoatInWater && GetUp().z > 0.0f){\n\t\t\tfloat splashVol = m_nDeltaVolumeUnderWater*pBoatHandling->fWaveAudioMult;\n\t\t\tif(splashVol > 200.0f)\n\t\t\t\tDMAudio.PlayOneShot(m_audioEntityId, SOUND_CAR_SPLASH, splashVol);\n\n\t\t\tif(m_nDeltaVolumeUnderWater > 200){\n\t\t\t\tfloat speedUp = m_vecMoveSpeed.MagnitudeSqr() * m_nDeltaVolumeUnderWater * 0.001f;\n\t\t\t\tif(speedUp + m_vecMoveSpeed.z > pHandling->fBrakeDeceleration)\n\t\t\t\t\tspeedUp = pHandling->fBrakeDeceleration - m_vecMoveSpeed.z;\n\t\t\t\tif(speedUp < 0.0f) speedUp = 0.0f;\n\t\t\t\tfloat speedFwd = DotProduct(m_vecMoveSpeed, GetForward());\n\t\t\t\tspeedFwd *= -m_nDeltaVolumeUnderWater * 0.01f * pHandling->fBrakeBias;\n\t\t\t\tCVector speed = speedFwd*GetForward() + CVector(0.0f, 0.0f, speedUp);\n\t\t\t\tCVector splashImpulse = speed * m_fMass;\n\t\t\t\tApplyMoveForce(splashImpulse);\n\t\t\t\tApplyTurnForce(splashImpulse, buoyancePoint);\n\t\t\t}\n\t\t}\n\n\t\t// Splashes\n\t\tfloat speed = m_vecMoveSpeed.Magnitude();\n\t\tif(speed > 0.05f && GetUp().x > 0.0f && !TheCamera.GetLookingForwardFirstPerson() && IsVisible() &&\n\t\t   (AutoPilot.m_nCarMission != MISSION_CRUISE || (CTimer::GetFrameCounter()&2) == 0)){\n\t\t\tCVector splashPos, splashDir;\n\t\t\tfloat splashSize, front, waterLevel;\n\n\t\t\tswitch(GetModelIndex()){\n\t\t\tcase MI_RIO:\n\t\t\t\tsplashSize = speed;\n\t\t\t\tfront = 0.9f * GetColModel()->boundingBox.max.y;\n\t\t\t\tsplashDir = -0.5f * m_vecMoveSpeed;\n\t\t\t\tsplashDir.z += 0.25f*speed;\n\t\t\t\tsplashDir += 0.35f*speed*GetRight();\n\t\t\t\tsplashPos = GetPosition() + 1.85f*GetRight() + front*GetForward();\n\t\t\t\tsplashPos.z += 0.5f;\n\t\t\t\tbreak;\n\t\t\tcase MI_SQUALO:\n\t\t\t\tsplashSize = speed;\n\t\t\t\tfront = 0.75f * GetColModel()->boundingBox.max.y;\n\t\t\t\tsplashDir = -0.125f * m_vecMoveSpeed;\n\t\t\t\tsplashDir.z += 0.15f*speed;\n\t\t\t\tsplashDir += 0.25f*speed*GetRight();\n\t\t\t\tsplashPos = GetPosition() + m_vecBuoyancePoint + 0.5f*GetRight() + front*GetForward();\n\t\t\t\tsplashPos.z += 0.5f;\n\t\t\t\tbreak;\n\t\t\tcase MI_REEFER:\n\t\t\t\tsplashSize = speed;\n\t\t\t\tfront = 0.75f * GetColModel()->boundingBox.max.y;\n\t\t\t\tsplashDir = -0.5f * m_vecMoveSpeed;\n\t\t\t\tsplashDir.z += 0.15f*speed;\n\t\t\t\tsplashDir += 0.5f*speed*GetRight();\n\t\t\t\tsplashPos = GetPosition() + m_vecBuoyancePoint + 1.3f*GetRight() + front*GetForward();\n\t\t\t\tbreak;\n\t\t\tcase MI_COASTG:\n\t\t\t\tsplashSize = 0.25f*speed;\n\t\t\t\tfront = 0.8f * GetColModel()->boundingBox.max.y;\n\t\t\t\tsplashDir = 0.165f * m_vecMoveSpeed;\n\t\t\t\tsplashDir.z += 0.25f*speed;\n\t\t\t\tsplashDir += 0.15f*speed*GetRight();\n\t\t\t\tsplashPos = GetPosition() + 0.65f*GetRight() + front*GetForward();\n\t\t\t\tsplashPos.z += 0.5f;\n\t\t\t\tbreak;\n\t\t\tcase MI_DINGHY:\n\t\t\t\tsplashSize = 0.25f*speed;\n\t\t\t\tfront = 0.9f * GetColModel()->boundingBox.max.y;\n\t\t\t\tsplashDir = 0.35f * m_vecMoveSpeed;\n\t\t\t\tsplashDir.z += 0.25f*speed;\n\t\t\t\tsplashDir += 0.25f*speed*GetRight();\n\t\t\t\tsplashPos = GetPosition() + 0.6f*GetRight() + front*GetForward();\n\t\t\t\tsplashPos.z += 0.5f;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tsplashSize = speed;\n\t\t\t\tfront = 0.9f * GetColModel()->boundingBox.max.y;\n\t\t\t\tsplashDir = -0.5f * m_vecMoveSpeed;\n\t\t\t\tsplashDir.z += 0.25f*speed;\n\t\t\t\tsplashDir += 0.35f*speed*GetRight();\n\t\t\t\tsplashPos = GetPosition() + m_vecBuoyancePoint + 0.5f*GetRight() + front*GetForward();\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif(splashSize > 0.75f) splashSize = 0.75f;\n\t\t\tif(AutoPilot.m_nCarMission == MISSION_CRUISE)\n\t\t\t\tsplashDir *= 1.5f;\n\t\t\tstatic float lifeMult = 1000.0f;\n\t\t\tstatic float lifeBase = 300.0f;\n\t\t\tsplashDir.z += 0.0003f*m_nDeltaVolumeUnderWater;\n\t\t\tCWaterLevel::GetWaterLevel(splashPos, &waterLevel, true);\n\t\t\tif(splashPos.z-waterLevel < 3.0f &&\n\t\t\t   CVisibilityPlugins::GetDistanceSquaredFromCamera(&splashPos) < SQR(70.0f * TheCamera.GenerationDistMultiplier)){\n\t\t\t\tsplashPos.z = waterLevel + 0.1f;\n\t\t\t\tCParticle::AddParticle(PARTICLE_CAR_SPLASH, splashPos, 0.75f*splashDir, nil, splashSize+0.1f,  splashColor,\n\t\t\t\t\tCGeneral::GetRandomNumberInRange(0.0f, 10.0f), CGeneral::GetRandomNumberInRange(0.0f, 90.0f),\n\t\t\t\t\t1, lifeBase + splashDir.z*lifeMult);\n\t\t\t\tCParticle::AddParticle(PARTICLE_BOAT_SPLASH, splashPos, splashDir, nil, splashSize,  jetColor,\n\t\t\t\t\tCGeneral::GetRandomNumberInRange(0.0f, 0.4f), CGeneral::GetRandomNumberInRange(0.0f, 45.0f),\n\t\t\t\t\t0, lifeBase + splashDir.z*lifeMult);\n\t\t\t}\n\n\t\t\tswitch(GetModelIndex()){\n\t\t\tcase MI_RIO:\n\t\t\t\tsplashDir = -0.5f * m_vecMoveSpeed;\n\t\t\t\tsplashDir.z += 0.25f*speed;\n\t\t\t\tsplashDir -= 0.35f*speed*GetRight();\n\t\t\t\tsplashPos = GetPosition() - 1.85f*GetRight() + front*GetForward();\n\t\t\t\tsplashPos.z += 0.5f;\n\t\t\t\tbreak;\n\t\t\tcase MI_SQUALO:\n\t\t\t\tsplashDir = -0.125f * m_vecMoveSpeed;\n\t\t\t\tsplashDir.z += 0.15f*speed;\n\t\t\t\tsplashDir -= 0.25f*speed*GetRight();\n\t\t\t\tsplashPos = GetPosition() + m_vecBuoyancePoint - 0.5f*GetRight() + front*GetForward();\n\t\t\t\tsplashPos.z += 0.5f;\n\t\t\t\tbreak;\n\t\t\tcase MI_REEFER:\n\t\t\t\tsplashDir = -0.5f * m_vecMoveSpeed;\n\t\t\t\tsplashDir.z += 0.15f*speed;\n\t\t\t\tsplashDir -= 0.5f*speed*GetRight();\n\t\t\t\tsplashPos = GetPosition() + m_vecBuoyancePoint - 1.3f*GetRight() + front*GetForward();\n\t\t\t\tbreak;\n\t\t\tcase MI_COASTG:\n\t\t\t\tsplashDir = 0.165f * m_vecMoveSpeed;\n\t\t\t\tsplashDir.z += 0.25f*speed;\n\t\t\t\tsplashDir -= 0.15f*speed*GetRight();\n\t\t\t\tsplashPos = GetPosition() - 0.65f*GetRight() + front*GetForward();\n\t\t\t\tsplashPos.z += 0.5f;\n\t\t\t\tbreak;\n\t\t\tcase MI_DINGHY:\n\t\t\t\tsplashDir = 0.35f * m_vecMoveSpeed;\n\t\t\t\tsplashDir.z += 0.25f*speed;\n\t\t\t\tsplashDir -= 0.25f*speed*GetRight();\n\t\t\t\tsplashPos = GetPosition() - 0.6f*GetRight() + front*GetForward();\n\t\t\t\tsplashPos.z += 0.5f;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tsplashDir = -0.5f * m_vecMoveSpeed;\n\t\t\t\tsplashDir.z += 0.25f*speed;\n\t\t\t\tsplashDir -= 0.35f*speed*GetRight();\n\t\t\t\tsplashPos = GetPosition() + m_vecBuoyancePoint - 0.5f*GetRight() + front*GetForward();\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif(AutoPilot.m_nCarMission == MISSION_CRUISE)\n\t\t\t\tsplashDir *= 1.5f;\n\t\t\tsplashDir.z += 0.0003f*m_nDeltaVolumeUnderWater;\n\t\t\tCWaterLevel::GetWaterLevel(splashPos, &waterLevel, true);\n\t\t\tif(splashPos.z-waterLevel < 3.0f &&\n\t\t\t   CVisibilityPlugins::GetDistanceSquaredFromCamera(&splashPos) < SQR(70.0f * TheCamera.GenerationDistMultiplier)){\n\t\t\t\tsplashPos.z = waterLevel + 0.1f;\n\t\t\t\tCParticle::AddParticle(PARTICLE_CAR_SPLASH, splashPos, 0.75f*splashDir, nil, splashSize+0.1f,  splashColor,\n\t\t\t\t\tCGeneral::GetRandomNumberInRange(0.0f, 10.0f), CGeneral::GetRandomNumberInRange(0.0f, 90.0f),\n\t\t\t\t\t1, lifeBase + splashDir.z*lifeMult);\n\t\t\t\tCParticle::AddParticle(PARTICLE_BOAT_SPLASH, splashPos, splashDir, nil, splashSize,  jetColor,\n\t\t\t\t\tCGeneral::GetRandomNumberInRange(0.0f, 0.4f), CGeneral::GetRandomNumberInRange(0.0f, 45.0f),\n\t\t\t\t\t0, lifeBase + splashDir.z*lifeMult);\n\t\t\t}\n\t\t}\n\n\t\t// Spray waterdrops on screen\n\t\tif(TheCamera.GetLookingForwardFirstPerson() && FindPlayerVehicle() && FindPlayerVehicle()->IsBoat() &&\n\t\t   m_nDeltaVolumeUnderWater > 0 && numWaterDropOnScreen < 20){\n\t\t\tCVector dropPos;\n\t\t\tCVector dropDir(CGeneral::GetRandomNumberInRange(-0.25f, 0.25f), CGeneral::GetRandomNumberInRange(1.0f, 0.75f), 0.0f);\n\n\t\t\tint frm = CGeneral::GetRandomNumber() & 1;\n\t\t\tif(TheCamera.m_CameraAverageSpeed < 0.35f){\n\t\t\t\tdropPos.x = CGeneral::GetRandomNumberInRange(50, (int)SCREEN_WIDTH-50);\n\t\t\t\tdropPos.y = CGeneral::GetRandomNumberInRange(50, (int)SCREEN_HEIGHT-50);\n\t\t\t}else{\n\t\t\t\tdropPos.x = CGeneral::GetRandomNumberInRange(200, (int)SCREEN_WIDTH-200);\n\t\t\t\tdropPos.y = CGeneral::GetRandomNumberInRange(150, (int)SCREEN_HEIGHT-150);\n\t\t\t}\n\t\t\tdropPos.z = 1.0f;\n\n\t\t\tif(TheCamera.m_CameraAverageSpeed > 0.35f){\n\t\t\t\tif((int)SCREEN_WIDTH / 2 < dropPos.x)\n\t\t\t\t\tdropPos.x += CGeneral::GetRandomNumberInRange(0.35f, TheCamera.m_CameraAverageSpeed)*7.5f;\n\t\t\t\telse\n\t\t\t\t\tdropPos.x -= CGeneral::GetRandomNumberInRange(0.35f, TheCamera.m_CameraAverageSpeed)*7.5f;\n\n\t\t\t\tif((int)SCREEN_HEIGHT / 2 < dropPos.y)\n\t\t\t\t\tdropPos.y += CGeneral::GetRandomNumberInRange(0.35f, TheCamera.m_CameraAverageSpeed)*7.5f;\n\t\t\t\telse\n\t\t\t\t\tdropPos.y -= CGeneral::GetRandomNumberInRange(0.35f, TheCamera.m_CameraAverageSpeed)*7.5f;\n\t\t\t}\n\n\t\t\tif(CParticle::AddParticle(PARTICLE_WATERDROP, dropPos, dropDir, nil,\n\t\t\t\t\tCGeneral::GetRandomNumberInRange(0.1f, 0.15f), dropColor, 0, 0, frm))\n\t\t\t\tnumWaterDropOnScreen++;\n\t\t}\n\n\t\tif(m_fPrevVolumeUnderWater == 0.0f && m_fVolumeUnderWater > 0.0f && GetModelIndex() == MI_SKIMMER){\n\t\t\tCVector splashDir(0.0f, 0.0f, 0.25f*speed);\n\t\t\tCVector splashPos = GetPosition();\n\t\t\tfloat level;\n\t\t\tCWaterLevel::GetWaterLevel(splashPos, &level, true);\n\t\t\tsplashPos.z = level;\n\t\t\tCParticleObject::AddObject(POBJECT_CAR_WATER_SPLASH, splashPos, splashDir, 0.0f, 65, splashColor, true);\n\t\t}\n\n\t\tm_fPrevVolumeUnderWater = m_fVolumeUnderWater;\n\t}else{\n\t\tbBoatInWater = false;\n\t\tbIsInWater = false;\n#ifdef FIX_BUGS\n\t\tbIsDrowning = false;\n#endif\n\t}\n\n\tif(m_modelIndex == MI_SKIMMER && CTimer::GetTimeStep() > 0.0f){\n\t\tif(GetStatus() == STATUS_PLAYER){\n\t\t\tif(m_fMovingSpeed < 0.22f)\n\t\t\t\tm_fMovingSpeed += 0.001f*CTimer::GetTimeStep();\n\t\t\tFlyingControl(FLIGHT_MODEL_SEAPLANE);\n\t\t}else{\n\t\t\tif(m_fMovingSpeed > 0.0005f*CTimer::GetTimeStep())\n\t\t\t\tm_fMovingSpeed -= 0.0005f*CTimer::GetTimeStep();\n\t\t\telse\n\t\t\t\tm_fMovingSpeed = 0.0f;\n\t\t}\n\t}else if(bCheat8)\n\t\tFlyingControl(FLIGHT_MODEL_PLANE);\n\n\tif(m_bIsAnchored){\n\t\tm_vecMoveSpeed.x = 0.0f;\n\t\tm_vecMoveSpeed.y = 0.0f;\n\n\t\tif(m_fOrientation == INVALID_ORIENTATION){\n\t\t\tm_fOrientation = GetForward().Heading();\n\t\t}else{\n\t\t\t// is this some inlined CPlaceable method?\n\t\t\tCVector pos = GetPosition();\n\t\t\tGetMatrix().RotateZ(m_fOrientation - GetForward().Heading());\n\t\t\tGetMatrix().SetTranslateOnly(pos);\n\t\t}\n\t}\n\n\tProcessDelayedExplosion();\n}\n\nvoid\nCBoat::ProcessControlInputs(uint8 pad)\n{\n\tm_nPadID = pad;\n\tif(m_nPadID > 3)\n\t\tm_nPadID = 3;\n\n\tm_fBrake += (CPad::GetPad(pad)->GetBrake()/255.0f - m_fBrake)*0.1f;\n\tm_fBrake = clamp(m_fBrake, 0.0f, 1.0f);\n\n\tif(m_fBrake < 0.05f){\n\t\tm_fBrake = 0.0f;\n\t\tm_fAccelerate += (CPad::GetPad(pad)->GetAccelerate()/255.0f - m_fAccelerate)*0.1f;\n\t\tm_fAccelerate = clamp(m_fAccelerate, 0.0f, 1.0f);\n\t}else\n\t\tm_fAccelerate = -m_fBrake*0.3f;\n\n\tm_fSteeringLeftRight += (-CPad::GetPad(pad)->GetSteeringLeftRight()/128.0f - m_fSteeringLeftRight)*0.2f;\n\tm_fSteeringLeftRight = clamp(m_fSteeringLeftRight, -1.0f, 1.0f);\n\n\tfloat steeringSq = m_fSteeringLeftRight < 0.0f ? -SQR(m_fSteeringLeftRight) : SQR(m_fSteeringLeftRight);\n\tm_fSteerAngle = pHandling->fSteeringLock * DEGTORAD(steeringSq);\n\tm_fGasPedal = m_fAccelerate;\n}\n\nfloat fSeaPlaneWaterResistance = 30.0f;\n\nvoid\nCBoat::ApplyWaterResistance(void)\n{\n\t// TODO: figure out how this works\n\tfloat resistance = 0.001f * pHandling->fSuspensionForceLevel * SQR(m_fVolumeUnderWater) * m_fMass;\n\tif(GetModelIndex() == MI_SKIMMER)\n\t\tresistance *= fSeaPlaneWaterResistance;\n\tfloat fwdSpeed = DotProduct(GetMoveSpeed(), GetForward());\n\tfloat magic = (SQR(fwdSpeed) + 0.05f) * resistance + 1.0f;\n\tmagic = Abs(magic);\n\tfloat fx = Pow(pBoatHandling->vecMoveRes.x/magic, 0.5f*CTimer::GetTimeStep());\n\tfloat fy = Pow(pBoatHandling->vecMoveRes.y/magic, 0.5f*CTimer::GetTimeStep());\n\tfloat fz = Pow(pBoatHandling->vecMoveRes.z/magic, 0.5f*CTimer::GetTimeStep());\n\n\tm_vecMoveSpeed = Multiply3x3(m_vecMoveSpeed, GetMatrix());\t// invert - to local space\n\tm_vecMoveSpeed.x *= fx;\n\tm_vecMoveSpeed.y *= fy;\n\tm_vecMoveSpeed.z *= fz;\n\tfloat force = (fy - 1.0f) * m_vecMoveSpeed.y * m_fMass;\n\tm_vecMoveSpeed = Multiply3x3(GetMatrix(), m_vecMoveSpeed);\t// back to world\n\n\tApplyTurnForce(force*GetForward(), -GetUp());\n\n\tif(m_vecMoveSpeed.z > 0.0f)\n\t\tm_vecMoveSpeed.z *= fz;\n\telse\n\t\tm_vecMoveSpeed.z *= (1.0f - fz)*0.5f + fz;\n}\n\nRwObject*\nGetBoatAtomicObjectCB(RwObject *object, void *data)\n{\n\tRpAtomic *atomic = (RpAtomic*)object;\n\tassert(RwObjectGetType(object) == rpATOMIC);\n\tif(RpAtomicGetFlags(atomic) & rpATOMICRENDER)\n\t\t*(RpAtomic**)data = atomic;\n\treturn object;\n\n\t\n}\n\nvoid\nCBoat::BlowUpCar(CEntity *culprit)\n{\n\tRpAtomic *atomic;\n\tRwFrame *frame;\n\tRwMatrix *matrix;\n\tCObject *obj;\n\n\tif(!bCanBeDamaged)\n\t\treturn;\n\n\t// explosion pushes vehicle up\n\tm_vecMoveSpeed.z += 0.13f;\n\tSetStatus(STATUS_WRECKED);\n\tbRenderScorched = true;\n\n\tm_fHealth = 0.0;\n\tm_nBombTimer = 0;\n\tTheCamera.CamShake(0.7f, GetPosition().x, GetPosition().y, GetPosition().z);\n\n\tKillPedsInVehicle();\n\n\tbEngineOn = false;\n\tbLightsOn = false;\n\tChangeLawEnforcerState(false);\n\n\tCExplosion::AddExplosion(this, culprit, EXPLOSION_BOAT, GetPosition(), 0);\n\tCDarkel::RegisterCarBlownUpByPlayer(this);\n\tif(m_aBoatNodes[BOAT_MOVING] == nil)\n\t\treturn;\n\n\t// much like CAutomobile::SpawnFlyingComponent from here on\n\n\tatomic = nil;\n\tRwFrameForAllObjects(m_aBoatNodes[BOAT_MOVING], GetBoatAtomicObjectCB, &atomic);\n\tif(atomic == nil)\n\t\treturn;\n\n\tobj = new CObject();\n\tif(obj == nil)\n\t\treturn;\n\n\tobj->SetModelIndexNoCreate(MI_CAR_WHEEL);\n\n\t// object needs base model\n\tobj->RefModelInfo(GetModelIndex());\n\n\t// create new atomic\n\tmatrix = RwFrameGetLTM(m_aBoatNodes[BOAT_MOVING]);\n\tframe = RwFrameCreate();\n\tatomic = RpAtomicClone(atomic);\n\t*RwFrameGetMatrix(frame) = *matrix;\n\tRpAtomicSetFrame(atomic, frame);\n\tCVisibilityPlugins::SetAtomicRenderCallback(atomic, nil);\n\tobj->AttachToRwObject((RwObject*)atomic);\n\tobj->bDontStream = true;\n\n\t// init object\n\tobj->m_fMass = 10.0f;\n\tobj->m_fTurnMass = 25.0f;\n\tobj->m_fAirResistance = 0.99f;\n\tobj->m_fElasticity = 0.1f;\n\tobj->m_fBuoyancy = obj->m_fMass*GRAVITY/0.75f;\n\tobj->ObjectCreatedBy = TEMP_OBJECT;\n\tobj->SetIsStatic(false);\n\tobj->bIsPickup = false;\n\n\t// life time\n\tCObject::nNoTempObjects++;\n\tobj->m_nEndOfLifeTime = CTimer::GetTimeInMilliseconds() + 20000;\n\n\tobj->m_vecMoveSpeed = m_vecMoveSpeed;\n\tif(GetUp().z > 0.0f)\n\t\tobj->m_vecMoveSpeed.z = 0.3f;\n\telse\n\t\tobj->m_vecMoveSpeed.z = 0.0f;\n\n\tobj->m_vecTurnSpeed = m_vecTurnSpeed*2.0f;\n\tobj->m_vecTurnSpeed.x = 0.5f;\n\n\t// push component away from boat\n\tCVector dist = obj->GetPosition() - GetPosition();\n\tdist.Normalise();\n\tif(GetUp().z > 0.0f)\n\t\tdist += GetUp();\n\tobj->GetMatrix().GetPosition() += dist;\n\n\tCWorld::Add(obj);\n\n\tatomic = nil;\n\tRwFrameForAllObjects(m_aBoatNodes[BOAT_MOVING], GetBoatAtomicObjectCB, &atomic);\n\tif(atomic)\n\t\tRpAtomicSetFlags(atomic, 0);\n}\n\nvoid\nCBoat::PreRender(void)\n{\n\tCMatrix matrix;\n\tCVector pos;\n\tRpAtomic *atomic;\n\n\tif(GetModelIndex() == MI_SKIMMER){\n\t\tm_fMovingRotation += m_fMovingSpeed*CTimer::GetTimeStep();\n\t\tif(m_fMovingRotation > TWOPI) m_fMovingRotation -= TWOPI;\n\t\tint alpha = (1.0f - Min(2.0f*m_fMovingSpeed*8.0f/PI, 1.0f))*255.0f;\n\t\tif(GetStatus() == STATUS_PLAYER || GetStatus() == STATUS_PLAYER_REMOTE || GetStatus() == STATUS_PLAYER_PLAYBACKFROMBUFFER){\n\t\t\tif(m_aBoatNodes[BOAT_RUDDER]){\n\t\t\t\tfloat sine = Sin(m_fSteerAngle);\n\t\t\t\tmatrix.Attach(RwFrameGetMatrix(m_aBoatNodes[BOAT_RUDDER]));\n\t\t\t\tpos = matrix.GetPosition();\n\t\t\t\tmatrix.SetRotate(0.0f, 0.0f, -m_fSteerAngle);\n\t\t\t\tmatrix.Rotate(0.0f, DEGTORAD(22.0f)*sine, 0.0f);\n\t\t\t\tmatrix.Translate(pos);\n\t\t\t\tmatrix.UpdateRW();\n\t\t\t}\n\t\t\tif(m_aBoatNodes[BOAT_FLAP_LEFT]){\n\t\t\t\tmatrix.Attach(RwFrameGetMatrix(m_aBoatNodes[BOAT_FLAP_LEFT]));\n\t\t\t\tpos = matrix.GetPosition();\n\t\t\t\tmatrix.SetRotateX(-m_fSteerAngle);\n\t\t\t\tmatrix.Translate(pos);\n\t\t\t\tmatrix.UpdateRW();\n\t\t\t}\n\t\t\tif(m_aBoatNodes[BOAT_FLAP_RIGHT]){\n\t\t\t\tmatrix.Attach(RwFrameGetMatrix(m_aBoatNodes[BOAT_FLAP_RIGHT]));\n\t\t\t\tpos = matrix.GetPosition();\n\t\t\t\tmatrix.SetRotateX(m_fSteerAngle);\n\t\t\t\tmatrix.Translate(pos);\n\t\t\t\tmatrix.UpdateRW();\n\t\t\t}\n\t\t\t// FIX: Planes can also be controlled with GetCarGunUpDown\n#ifdef FIX_BUGS\n\t\t\tstatic float steeringUpDown = 0.0f;\n#ifdef FREE_CAM\n\t\t\tif(!CCamera::bFreeCam || (CCamera::bFreeCam && !CPad::IsAffectedByController))\n#endif\n\t\t\tsteeringUpDown += ((Abs(CPad::GetPad(0)->GetCarGunUpDown()) > 1.0f ? (-CPad::GetPad(0)->GetCarGunUpDown()/128.0f) : (-CPad::GetPad(0)->GetSteeringUpDown()/128.0f)) - steeringUpDown) * Min(1.f, CTimer::GetTimeStep()/5.f);\n#ifdef FREE_CAM\n\t\t\telse\n\t\t\t\tsteeringUpDown = -CPad::GetPad(0)->GetSteeringUpDown()/128.0f;\n#endif\n#else\n\t\t\tfloat steeringUpDown = -CPad::GetPad(0)->GetSteeringUpDown()/128.0f;\n#endif\n\t\t\tif(m_aBoatNodes[BOAT_REARFLAP_LEFT]){\n\t\t\t\tmatrix.Attach(RwFrameGetMatrix(m_aBoatNodes[BOAT_REARFLAP_LEFT]));\n\t\t\t\tpos = matrix.GetPosition();\n\t\t\t\tmatrix.SetRotateX(steeringUpDown);\n\t\t\t\tmatrix.Translate(pos);\n\t\t\t\tmatrix.UpdateRW();\n\t\t\t}\n\t\t\tif(m_aBoatNodes[BOAT_REARFLAP_RIGHT]){\n\t\t\t\tmatrix.Attach(RwFrameGetMatrix(m_aBoatNodes[BOAT_REARFLAP_RIGHT]));\n\t\t\t\tpos = matrix.GetPosition();\n\t\t\t\tmatrix.SetRotateX(steeringUpDown);\n\t\t\t\tmatrix.Translate(pos);\n\t\t\t\tmatrix.UpdateRW();\n\t\t\t}\n\t\t}\n\t\tif(m_aBoatNodes[BOAT_MOVING]){\n\t\t\tmatrix.Attach(RwFrameGetMatrix(m_aBoatNodes[BOAT_MOVING]));\n\t\t\tpos = matrix.GetPosition();\n\t\t\tmatrix.SetRotateY(m_fMovingRotation);\n\t\t\tmatrix.Translate(pos);\n\t\t\tmatrix.UpdateRW();\n\n\t\t\tatomic = nil;\n\t\t\tRwFrameForAllObjects(m_aBoatNodes[BOAT_MOVING], GetBoatAtomicObjectCB, &atomic);\n\t\t\tif(atomic)\n\t\t\t\tSetComponentAtomicAlpha(atomic, alpha);\n\t\t}\n\t\tif(m_aBoatNodes[BOAT_WINDSCREEN]){\n\t\t\tmatrix.Attach(RwFrameGetMatrix(m_aBoatNodes[BOAT_WINDSCREEN]));\n\t\t\tpos = matrix.GetPosition();\n\t\t\tmatrix.SetRotateY(-m_fMovingRotation);\n\t\t\tmatrix.Translate(pos);\n\t\t\tmatrix.UpdateRW();\n\n\t\t\tatomic = nil;\n\t\t\tRwFrameForAllObjects(m_aBoatNodes[BOAT_WINDSCREEN], GetBoatAtomicObjectCB, &atomic);\n\t\t\tif(atomic)\n\t\t\t\tSetComponentAtomicAlpha(atomic, Max(150-alpha, 0));\n\t\t}\n\t\tCShadows::StoreShadowForVehicle(this, VEH_SHD_TYPE_SEAPLANE);\n\t}else if(GetModelIndex() == MI_COASTG || GetModelIndex() == MI_DINGHY || GetModelIndex() == MI_RIO ||\n\t         GetModelIndex() == MI_SQUALO || GetModelIndex() == MI_MARQUIS){\n\t\tif(m_aBoatNodes[BOAT_RUDDER]){\n\t\t\tmatrix.Attach(RwFrameGetMatrix(m_aBoatNodes[BOAT_RUDDER]));\n\t\t\tpos = matrix.GetPosition();\n\t\t\tmatrix.SetRotateZ(-m_fSteerAngle);\n\t\t\tmatrix.Translate(pos);\n\t\t\tmatrix.UpdateRW();\n\t\t}\n\t\tif(m_aBoatNodes[BOAT_REARFLAP_LEFT]){\n\t\t\tmatrix.Attach(RwFrameGetMatrix(m_aBoatNodes[BOAT_REARFLAP_LEFT]));\n\t\t\tpos = matrix.GetPosition();\n\t\t\tmatrix.SetRotateZ(-m_fSteerAngle);\n\t\t\tmatrix.Translate(pos);\n\t\t\tmatrix.UpdateRW();\n\t\t}\n\t\tif(m_aBoatNodes[BOAT_REARFLAP_RIGHT]){\n\t\t\tmatrix.Attach(RwFrameGetMatrix(m_aBoatNodes[BOAT_REARFLAP_RIGHT]));\n\t\t\tpos = matrix.GetPosition();\n\t\t\tmatrix.SetRotateZ(-m_fSteerAngle);\n\t\t\tmatrix.Translate(pos);\n\t\t\tmatrix.UpdateRW();\n\t\t}\n\t}\n\n\tif(GetModelIndex() == MI_RIO || GetModelIndex() == MI_MARQUIS){\n\t\tfloat axes[3] = { 0.0f, 0.0f, 0.0f };\n\t\tm_boom.Process(this);\n\t\taxes[m_boom.m_nAxis] = m_boom.m_fAngle;\n\t\tmatrix.Attach(RwFrameGetMatrix(m_aBoatNodes[BOAT_FLAP_LEFT]));\n\t\tpos = matrix.GetPosition();\n\t\tmatrix.SetRotate(axes[0], axes[1], axes[2]);\n\t\tmatrix.Translate(pos);\n\t\tmatrix.UpdateRW();\n\t}\n\n\tif(GetModelIndex() == MI_RIO){\n\t\t// That little wind propeller\n\t\tif(m_aBoatNodes[BOAT_FLAP_RIGHT]){\n\t\t\tmatrix.Attach(RwFrameGetMatrix(m_aBoatNodes[BOAT_FLAP_RIGHT]));\n\t\t\tpos = matrix.GetPosition();\n\n\t\t\tfloat flapHeading = matrix.GetForward().Heading();\n\t\t\tfloat boatHeading = GetForward().Heading();\n\t\t\tfloat rot = -DEGTORAD(45.0f) - (flapHeading + boatHeading);\n\t\t\t// eh what?\n\t\t\trot = CGeneral::LimitRadianAngle(rot);\n\t\t\tif(rot > HALFPI) rot = PI;\n\t\t\telse if(rot < -HALFPI) rot = -PI;\n\t\t\trot = clamp(rot, -DEGTORAD(63.0f), DEGTORAD(63.0f));\n\t\t\tm_fMovingSpeed += (0.008f * CWeather::Wind + 0.002f) * rot;\n\t\t\tm_fMovingSpeed *= Pow(0.9985f, CTimer::GetTimeStep())/(500.0f*SQR(m_fMovingSpeed) + 1.0f);\n\n\t\t\tmatrix.SetRotateZ(flapHeading + m_fMovingSpeed*CTimer::GetTimeStep());\n\t\t\tmatrix.Translate(pos);\n\t\t\tmatrix.UpdateRW();\n\t\t}\n\t\tif(m_aBoatNodes[BOAT_MOVING]){\n\t\t\tmatrix.Attach(RwFrameGetMatrix(m_aBoatNodes[BOAT_MOVING]));\n\t\t\tpos = matrix.GetPosition();\n\t\t\tmatrix.SetRotateY(m_fMovingRotation);\n\t\t\tmatrix.Translate(pos);\n\t\t\tmatrix.UpdateRW();\n\n\t\t\tCVector wind  = CVector(0.707f, 0.707f, 0.0f) * (CWeather::Wind + 0.15f)*0.4f;\n\t\t\tm_fMovingRotation += (m_vecMoveSpeed + wind).Magnitude()*CTimer::GetTimeStep();\n\t\t}\n\t}else if(GetModelIndex() == MI_PREDATOR || GetModelIndex() == MI_REEFER){\n\t\tif (m_aBoatNodes[BOAT_MOVING] != nil) {\n\t\t\tmatrix.Attach(RwFrameGetMatrix(m_aBoatNodes[BOAT_MOVING]));\n\n\t\t\tCVector pos = matrix.GetPosition();\n\t\t\tmatrix.SetRotateZ(m_fMovingRotation);\n\t\t\tmatrix.Translate(pos);\n\n\t\t\tmatrix.UpdateRW();\n\t\t\tif (CVehicle::bWheelsOnlyCheat) {\n\t\t\t\tRpAtomicRender((RpAtomic*)GetFirstObject(m_aBoatNodes[BOAT_MOVING]));\n\t\t\t}\n\t\t}\n\t\tm_fMovingRotation += 0.02f * CTimer::GetTimeStep();\n\t}\n}\n\nRwIm3DVertex KeepWaterOutVertices[4];\nRwImVertexIndex KeepWaterOutIndices[6];\n\nvoid\nCBoat::Render()\n{\n\t((CVehicleModelInfo*)CModelInfo::GetModelInfo(GetModelIndex()))->SetVehicleColour(m_currentColour1, m_currentColour2);\n\tm_nSetPieceExtendedRangeTime = CTimer::GetTimeInMilliseconds() + 3000;\n\tif (!CVehicle::bWheelsOnlyCheat)\n\t\tCEntity::Render();\n#ifdef NEW_RENDERER\n\tif(!gbNewRenderer)\n#endif\n\tRenderWaterOutPolys();\t// not separate function in VC\n}\n\nvoid\nCBoat::RenderWaterOutPolys(void)\n{\n\tif(GetModelIndex() == MI_SKIMMER)\n\t\treturn;\n\tKeepWaterOutIndices[0] = 0;\n\tKeepWaterOutIndices[1] = 2;\n\tKeepWaterOutIndices[2] = 1;\n\tKeepWaterOutIndices[3] = 1;\n\tKeepWaterOutIndices[4] = 2;\n\tKeepWaterOutIndices[5] = 3;\n\tRwIm3DVertexSetRGBA(&KeepWaterOutVertices[0], 255, 255, 255, 255);\n\tRwIm3DVertexSetRGBA(&KeepWaterOutVertices[1], 255, 255, 255, 255);\n\tRwIm3DVertexSetRGBA(&KeepWaterOutVertices[2], 255, 255, 255, 255);\n\tRwIm3DVertexSetRGBA(&KeepWaterOutVertices[3], 255, 255, 255, 255);\n\tswitch (GetModelIndex()) {\n\tcase MI_RIO:\n\t\tRwIm3DVertexSetPos(&KeepWaterOutVertices[0], -1.3f, -1.016f, 0.51f);\n\t\tRwIm3DVertexSetPos(&KeepWaterOutVertices[1],  1.3f, -1.016f, 0.51f);\n\t\tRwIm3DVertexSetPos(&KeepWaterOutVertices[2], -1.3f, -2.832f, 0.51f);\n\t\tRwIm3DVertexSetPos(&KeepWaterOutVertices[3],  1.3f, -2.832f, 0.51f);\n\t\tbreak;\n\tcase MI_SQUALO:\n\t\tRwIm3DVertexSetPos(&KeepWaterOutVertices[0], -1.222f,  2.004f, 0.846f);\n\t\tRwIm3DVertexSetPos(&KeepWaterOutVertices[1],  1.222f,  2.004f, 0.846f);\n\t\tRwIm3DVertexSetPos(&KeepWaterOutVertices[2], -1.24f,  -1.367f, 0.846f);\n\t\tRwIm3DVertexSetPos(&KeepWaterOutVertices[3],  1.24f,  -1.367f, 0.846f);\n\t\tbreak;\n\tcase MI_SPEEDER:\n\t\tRwIm3DVertexSetPos(&KeepWaterOutVertices[0], -1.15f, 3.61f, 1.03f);\n\t\tRwIm3DVertexSetPos(&KeepWaterOutVertices[1],  1.15f, 3.61f, 1.03f);\n\t\tRwIm3DVertexSetPos(&KeepWaterOutVertices[2], -1.15f, 0.06f, 1.03f);\n\t\tRwIm3DVertexSetPos(&KeepWaterOutVertices[3],  1.15f, 0.06f, 1.03f);\n\t\tbreak;\n\tcase MI_REEFER:\n\t\tRwIm3DVertexSetPos(&KeepWaterOutVertices[0], -1.9f,   2.83f, 1.0f);\n\t\tRwIm3DVertexSetPos(&KeepWaterOutVertices[1],  1.9f,   2.83f, 1.0f);\n\t\tRwIm3DVertexSetPos(&KeepWaterOutVertices[2], -1.66f, -4.48f, 0.83f);\n\t\tRwIm3DVertexSetPos(&KeepWaterOutVertices[3],  1.66f, -4.48f, 0.83f);\n\t\tbreak;\n\tcase MI_PREDATOR:\n\t\tRwIm3DVertexSetPos(&KeepWaterOutVertices[0], -1.45f,   1.9f, 0.96f);\n\t\tRwIm3DVertexSetPos(&KeepWaterOutVertices[1],  1.45f,   1.9f, 0.96f);\n\t\tRwIm3DVertexSetPos(&KeepWaterOutVertices[2], -1.45f, -3.75f, 0.96f);\n\t\tRwIm3DVertexSetPos(&KeepWaterOutVertices[3],  1.45f, -3.75f, 0.96f);\n\t\tbreak;\n\tcase MI_TROPIC:\n\t\tRwIm3DVertexSetPos(&KeepWaterOutVertices[0], -1.886f, -2.347f, 0.787f);\n\t\tRwIm3DVertexSetPos(&KeepWaterOutVertices[1],  1.886f, -2.347f, 0.787f);\n\t\tRwIm3DVertexSetPos(&KeepWaterOutVertices[2], -1.886f, -4.67f,  0.842f);\n\t\tRwIm3DVertexSetPos(&KeepWaterOutVertices[3],  1.886f, -4.67f,  0.842f);\n\t\tbreak;\n\tcase MI_COASTG:\n\t\tRwIm3DVertexSetPos(&KeepWaterOutVertices[0], -0.663f, 3.565f, 0.382f);\n\t\tRwIm3DVertexSetPos(&KeepWaterOutVertices[1],  0.663f, 3.565f, 0.382f);\n\t\tRwIm3DVertexSetPos(&KeepWaterOutVertices[2], -1.087f, 0.83f,  0.381f);\n\t\tRwIm3DVertexSetPos(&KeepWaterOutVertices[3],  1.087f, 0.83f,  0.381f);\n\t\tbreak;\n\tcase MI_DINGHY:\n\t\tRwIm3DVertexSetPos(&KeepWaterOutVertices[0], -0.797f,  1.641f, 0.573f);\n\t\tRwIm3DVertexSetPos(&KeepWaterOutVertices[1],  0.797f,  1.641f, 0.573f);\n\t\tRwIm3DVertexSetPos(&KeepWaterOutVertices[2], -0.865f, -1.444f, 0.509f);\n\t\tRwIm3DVertexSetPos(&KeepWaterOutVertices[3],  0.865f, -1.444f, 0.509f);\n\t\tbreak;\n\tcase MI_MARQUIS:\n\t\tRwIm3DVertexSetPos(&KeepWaterOutVertices[0], -1.246f, -1.373f, 0.787f);\n\t\tRwIm3DVertexSetPos(&KeepWaterOutVertices[1],  1.246f, -1.373f, 0.787f);\n\t\tRwIm3DVertexSetPos(&KeepWaterOutVertices[2], -1.023f, -5.322f, 0.787f);\n\t\tRwIm3DVertexSetPos(&KeepWaterOutVertices[3],  1.023f, -5.322f, 0.787f);\n\t\tbreak;\n\tdefault:\n\t\treturn;\n\t}\n\tKeepWaterOutVertices[0].u = 0.0f;\n\tKeepWaterOutVertices[0].v = 0.0f;\n\tKeepWaterOutVertices[1].u = 1.0f;\n\tKeepWaterOutVertices[1].v = 0.0f;\n\tKeepWaterOutVertices[2].u = 0.0f;\n\tKeepWaterOutVertices[2].v = 1.0f;\n\tKeepWaterOutVertices[3].u = 1.0f;\n\tKeepWaterOutVertices[3].v = 1.0f;\n#ifdef NEW_RENDERER\n\tif(!gbNewRenderer)\n#endif\n{\n\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER, gpWaterRaster);\n\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);\n\tRwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE);\n\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDZERO);\n\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE);\n}\n\tif (!CVehicle::bWheelsOnlyCheat && RwIm3DTransform(KeepWaterOutVertices, 4, GetMatrix().m_attachment, rwIM3D_VERTEXUV)) {\n\t\tRwIm3DRenderIndexedPrimitive(rwPRIMTYPETRILIST, KeepWaterOutIndices, 6);\n\t\tRwIm3DEnd();\n\t}\n\tbool drawAnotherRect = false;\n\tif(GetModelIndex() == MI_COASTG){\n\t\tdrawAnotherRect = true;\n\t\tRwIm3DVertexSetPos(&KeepWaterOutVertices[0], -1.087f,  0.831f, 0.381f);\n\t\tRwIm3DVertexSetPos(&KeepWaterOutVertices[1],  1.087f,  0.831f, 0.381f);\n\t\tRwIm3DVertexSetPos(&KeepWaterOutVertices[2], -1.097f, -2.977f, 0.381f);\n\t\tRwIm3DVertexSetPos(&KeepWaterOutVertices[3],  1.097f, -2.977f, 0.381f);\n\t}\n\tif(drawAnotherRect){\n\t\tKeepWaterOutVertices[0].u = 0.0f;\n\t\tKeepWaterOutVertices[0].v = 0.0f;\n\t\tKeepWaterOutVertices[1].u = 1.0f;\n\t\tKeepWaterOutVertices[1].v = 0.0f;\n\t\tKeepWaterOutVertices[2].u = 0.0f;\n\t\tKeepWaterOutVertices[2].v = 1.0f;\n\t\tKeepWaterOutVertices[3].u = 1.0f;\n\t\tKeepWaterOutVertices[3].v = 1.0f;\n\t\tif (!CVehicle::bWheelsOnlyCheat && RwIm3DTransform(KeepWaterOutVertices, 4, GetMatrix().m_attachment, rwIM3D_VERTEXUV)) {\n\t\t\tRwIm3DRenderIndexedPrimitive(rwPRIMTYPETRILIST, KeepWaterOutIndices, 6);\n\t\t\tRwIm3DEnd();\n\t\t}\n\t}\n#ifdef NEW_RENDERER\n\tif(!gbNewRenderer)\n#endif\n{\n\tRwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)TRUE);\n\tRwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);\n\tRwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);\n}\n}\n\nvoid\nCBoat::Teleport(CVector v)\n{\n\tCWorld::Remove(this);\n\tSetPosition(v);\n\tSetOrientation(0.0f, 0.0f, 0.0f);\n\tSetMoveSpeed(0.0f, 0.0f, 0.0f);\n\tSetTurnSpeed(0.0f, 0.0f, 0.0f);\n\tCWorld::Add(this);\n}\n\n// unused\nbool\nCBoat::IsSectorAffectedByWake(CVector2D sector, float fSize, CBoat **apBoats)\n{\n\tuint8 numVerts = 0;\n\t\n\tif ( apFrameWakeGeneratingBoats[0] == NULL )\n\t\treturn false;\n\t\n\tfor ( int32 i = 0; i < 4; i++ )\n\t{\n\t\tCBoat *pBoat = apFrameWakeGeneratingBoats[i];\n\t\tif ( !pBoat )\n\t\t\tbreak;\n\t\t\n\t\tfor ( int j = 0; j < pBoat->m_nNumWakePoints; j++ )\n\t\t{\n\t\t\t float fDist = (WAKE_LIFETIME - pBoat->m_afWakePointLifeTime[j]) * fShapeTime + float(j) * fShapeLength + fSize;\n\t\t\t \n\t\t\t if ( Abs(pBoat->m_avec2dWakePoints[j].x - sector.x) < fDist\n\t\t\t\t&& Abs(pBoat->m_avec2dWakePoints[i].y - sector.y) < fDist )\n\t\t\t {\n\t\t\t\t apBoats[numVerts] = pBoat;\n\t\t\t\t numVerts = 1; // += ?\n\t\t\t\t break;\n\t\t\t }\n\t\t}\n\t}\n\t\n\treturn numVerts != 0;\n}\n\n// unused\nfloat\nCBoat::IsVertexAffectedByWake(CVector vecVertex, CBoat *pBoat)\n{\n\tfor ( int i = 0; i < pBoat->m_nNumWakePoints; i++ )\n\t{\n\t\tfloat fMaxDist = (WAKE_LIFETIME - pBoat->m_afWakePointLifeTime[i]) * fShapeTime + float(i) * fShapeLength;\n\t\t\n\t\tCVector2D vecDist = pBoat->m_avec2dWakePoints[i] - CVector2D(vecVertex);\n\t\t\n\t\tfloat fDist = vecDist.MagnitudeSqr();\n\t\t\n\t\tif ( fDist < SQR(fMaxDist) )\n\t\t\treturn 1.0f - Min(fRangeMult * Sqrt(fDist / SQR(fMaxDist)) + (WAKE_LIFETIME - pBoat->m_afWakePointLifeTime[i]) * fTimeMult, 1.0f);\n\t}\n\n\treturn 0.0f;\n}\n\nvoid\nCBoat::SetupModelNodes()\n{\n\tint i;\n\tfor(i = 0; i < ARRAY_SIZE(m_aBoatNodes); i++)\n\t\tm_aBoatNodes[i] = nil;\n\tCClumpModelInfo::FillFrameArray(GetClump(), m_aBoatNodes);\n}\n\nvoid\nCBoat::FillBoatList()\n{\n\tint16 frameId = 0;\n\t\n\tapFrameWakeGeneratingBoats[0] = nil;\n\tapFrameWakeGeneratingBoats[1] = nil;\n\tapFrameWakeGeneratingBoats[2] = nil;\n\tapFrameWakeGeneratingBoats[3] = nil;\n\tCVector2D camPos = TheCamera.GetPosition();\n\tCVector2D camFwd = TheCamera.GetForward();\n\tfloat camDist = camFwd.Magnitude();\n\tif(camDist > 0.0f)\n\t\tcamFwd /= camDist;\n\tfor (int i = CPools::GetVehiclePool()->GetSize() - 1; i >= 0; i--) {\n\t\tCBoat *boat = (CBoat *)(CPools::GetVehiclePool()->GetSlot(i));\n\t\tif (boat && boat->m_vehType == VEHICLE_TYPE_BOAT) {\n\t\t\tif (boat->m_nNumWakePoints != 0) {\n\t\t\t\tCVector2D camToBoat = CVector2D(boat->GetPosition()) - camPos;\n\t\t\t\tfloat distToCam = DotProduct2D(camFwd, camToBoat);\n\t\t\t\tif(distToCam > 100.0f || distToCam < -15.0f)\n\t\t\t\t\tcontinue;\n\t\t\t\tfloat distSq = camToBoat.MagnitudeSqr();\n\t\t\t\tif(distSq > SQR(70.0f))\n\t\t\t\t\tcontinue;\n\t\t\t\tif (frameId >= ARRAY_SIZE(apFrameWakeGeneratingBoats)) {\n\t\t\t\t\tfloat nearest = 999999.88f;\n\t\t\t\t\tint16 frameId2 = -1;\n\t\t\t\t\tfor (int16 j = 0; j < ARRAY_SIZE(apFrameWakeGeneratingBoats); j++) {\n\t\t\t\t\t\tfloat tmpDistSq = (CVector2D(apFrameWakeGeneratingBoats[j]->GetPosition()) - camPos).MagnitudeSqr();\n\t\t\t\t\t\tif (tmpDistSq < nearest) {\n\t\t\t\t\t\t\tnearest = tmpDistSq;\n\t\t\t\t\t\t\tframeId2 = j;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (frameId2 != -1 &&\n\t\t\t\t\t    (distSq < nearest || boat->GetStatus() == STATUS_PLAYER))\n\t\t\t\t\t\tapFrameWakeGeneratingBoats[frameId2] = boat;\n\t\t\t\t} else {\n\t\t\t\t\tapFrameWakeGeneratingBoats[frameId++] = boat;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid\nCBoat::PruneWakeTrail(void)\n{\n\tint i;\n\n\tfor(i = 0; i < ARRAY_SIZE(m_afWakePointLifeTime); i++){\n\t\tif(m_afWakePointLifeTime[i] <= 0.0f)\n\t\t\tbreak;\n\t\tif(m_afWakePointLifeTime[i] <= CTimer::GetTimeStep()){\n\t\t\tm_afWakePointLifeTime[i] = 0.0f;\n\t\t\tbreak;\n\t\t}\n\t\tm_afWakePointLifeTime[i] -= CTimer::GetTimeStep();\n\t}\n\tm_nNumWakePoints = i;\n}\n\nvoid\nCBoat::AddWakePoint(CVector point)\n{\n\tint i;\n\tif(m_afWakePointLifeTime[0] > 0.0f){\n\t\tif((CVector2D(GetPosition()) - m_avec2dWakePoints[0]).MagnitudeSqr() < SQR(2.0f)) {\n\t\t\tif(GetStatus() == STATUS_PLAYER){\n\t\t\t\tif(m_nNumWakePoints >= 31)\n\t\t\t\t\tm_nNumWakePoints = 31;\n\t\t\t}else if(VehicleCreatedBy == MISSION_VEHICLE){\n\t\t\t\tif(m_nNumWakePoints >= 20)\n\t\t\t\t\tm_nNumWakePoints = 20;\n\t\t\t}else{\n\t\t\t\tif(m_nNumWakePoints >= 15)\n\t\t\t\t\tm_nNumWakePoints = 15;\n\t\t\t}\n\t\t\tfor(i = m_nNumWakePoints; i != 0; i--){\n\t\t\t\tm_avec2dWakePoints[i] = m_avec2dWakePoints[i-1];\n\t\t\t\tm_afWakePointLifeTime[i] = m_afWakePointLifeTime[i-1];\n\t\t\t}\n\t\t\tm_avec2dWakePoints[0] = point;\n\t\t\tm_afWakePointLifeTime[0] = 150.0f;\n\t\t\tif(m_nNumWakePoints < ARRAY_SIZE(m_afWakePointLifeTime))\n\t\t\t\tm_nNumWakePoints++;\n\t\t}\n\t}else{\n\t\tm_avec2dWakePoints[0] = point;\n\t\tm_afWakePointLifeTime[0] = 150.0f;\n\t\tm_nNumWakePoints = 1;\n\t}\n}\n\nvoid\nCBoat::DoDriveByShootings(void)\n{\n\tCAnimBlendAssociation *anim = nil;\n\tCPlayerInfo* playerInfo = ((CPlayerPed*)pDriver)->GetPlayerInfoForThisPlayerPed();\n\tif (playerInfo && !playerInfo->m_bDriveByAllowed)\n\t\treturn;\n\n\tCWeapon *weapon = pDriver->GetWeapon();\n\tif(CWeaponInfo::GetWeaponInfo(weapon->m_eWeaponType)->m_nWeaponSlot != 5)\n\t\treturn;\n\n\tweapon->Update(pDriver->m_audioEntityId, nil);\n\n\tbool lookingLeft = false;\n\tbool lookingRight = false;\n\tif(TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOPDOWN ||\n\t   TheCamera.m_bObbeCinematicCarCamOn){\n\t\tif(CPad::GetPad(0)->GetLookLeft())\n\t\t\tlookingLeft = true;\n\t\tif(CPad::GetPad(0)->GetLookRight())\n\t\t\tlookingRight = true;\n\t}else{\n\t\tif(TheCamera.Cams[TheCamera.ActiveCam].LookingLeft)\n\t\t\tlookingLeft = true;\n\t\tif(TheCamera.Cams[TheCamera.ActiveCam].LookingRight)\n\t\t\tlookingRight = true;\n\t}\n\n\tif(lookingLeft || lookingRight){\n\t\tif(lookingLeft){\n\t\t\tanim = RpAnimBlendClumpGetAssociation(pDriver->GetClump(), ANIM_STD_CAR_DRIVEBY_RIGHT);\n\t\t\tif(anim)\n\t\t\t\tanim->blendDelta = -1000.0f;\n\t\t\tanim = RpAnimBlendClumpGetAssociation(pDriver->GetClump(), ANIM_STD_CAR_DRIVEBY_LEFT);\n\t\t\tif(anim == nil || anim->blendDelta < 0.0f)\n\t\t\t\tanim = CAnimManager::AddAnimation(pDriver->GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_DRIVEBY_LEFT);\n\t\t}else if(pDriver->m_pMyVehicle->pPassengers[0] == nil || TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_1STPERSON){\n\t\t\tanim = RpAnimBlendClumpGetAssociation(pDriver->GetClump(), ANIM_STD_CAR_DRIVEBY_LEFT);\n\t\t\tif(anim)\n\t\t\t\tanim->blendDelta = -1000.0f;\n\t\t\tanim = RpAnimBlendClumpGetAssociation(pDriver->GetClump(), ANIM_STD_CAR_DRIVEBY_RIGHT);\n\t\t\tif(anim == nil || anim->blendDelta < 0.0f)\n\t\t\t\tanim = CAnimManager::AddAnimation(pDriver->GetClump(), ASSOCGRP_STD, ANIM_STD_CAR_DRIVEBY_RIGHT);\n\t\t}\n\n\t\tif (!anim || !anim->IsRunning()) {\n\t\t\tif (CPad::GetPad(0)->GetCarGunFired() && CTimer::GetTimeInMilliseconds() > weapon->m_nTimer) {\n\t\t\t\tweapon->FireFromCar(this, lookingLeft, true);\n\t\t\t\tweapon->m_nTimer = CTimer::GetTimeInMilliseconds() + 70;\n\t\t\t}\n\t\t}\n\t}else{\n\t\tweapon->Reload();\n\t\tanim = RpAnimBlendClumpGetAssociation(pDriver->GetClump(), ANIM_STD_CAR_DRIVEBY_LEFT);\n\t\tif(anim)\n\t\t\tanim->blendDelta = -1000.0f;\n\t\tanim = RpAnimBlendClumpGetAssociation(pDriver->GetClump(), ANIM_STD_CAR_DRIVEBY_RIGHT);\n\t\tif(anim)\n\t\t\tanim->blendDelta = -1000.0f;\n\t}\n}\n\n#ifdef COMPATIBLE_SAVES\nvoid\nCBoat::Save(uint8*& buf)\n{\n\tCVehicle::Save(buf);\n\tSkipSaveBuf(buf, 1216 - 672);\n}\n\nvoid\nCBoat::Load(uint8*& buf)\n{\n\tCVehicle::Load(buf);\n\tSkipSaveBuf(buf, 1216 - 672);\n}\n#endif\n"
  },
  {
    "path": "src/vehicles/Boat.h",
    "content": "#pragma once\n\n#include \"Vehicle.h\"\n#include \"Door.h\"\n\nenum eBoatNodes\n{\n\tBOAT_MOVING = 1,\n\tBOAT_WINDSCREEN,\n\tBOAT_RUDDER,\n\tBOAT_FLAP_LEFT,\n\tBOAT_FLAP_RIGHT,\n\tBOAT_REARFLAP_LEFT,\n\tBOAT_REARFLAP_RIGHT,\n\tNUM_BOAT_NODES\n};\n\nclass CBoat : public CVehicle\n{\npublic:\n\tfloat m_fMovingRotation;\n\tfloat m_fMovingSpeed;\n\tint32 m_boat_unused1;\n\tRwFrame *m_aBoatNodes[NUM_BOAT_NODES];\n\tCDoor m_boom;\n\ttBoatHandlingData *pBoatHandling;\n\tuint8 bBoatInWater : 1;\n\tuint8 bPropellerInWater : 1;\n\tbool m_bIsAnchored;\n\tfloat m_fOrientation;\n\tuint32 m_nPoliceShoutTimer;\n\tint32 m_boat_unused2;\n\tfloat m_fDamage;\n\tCEntity *m_pSetOnFireEntity;\n\tfloat m_skimmerThingTimer;\n\tbool m_boat_unused3;\n\tfloat m_fAccelerate;\n\tfloat m_fBrake;\n\tfloat m_fSteeringLeftRight;\n\tuint8 m_nPadID;\n\tint32 m_boat_unused4;\n\tfloat m_fVolumeUnderWater;\n\tCVector m_vecBuoyancePoint;\n\tfloat m_fPrevVolumeUnderWater;\n\tint16 m_nDeltaVolumeUnderWater;\n\tuint16 m_nNumWakePoints;\n\tCVector2D m_avec2dWakePoints[32];\n\tfloat m_afWakePointLifeTime[32];\n\n\tstatic float MAX_WAKE_LENGTH;\n\tstatic float MIN_WAKE_INTERVAL;\n\tstatic float WAKE_LIFETIME;\n\n\tCBoat(int, uint8);\n\n\tvirtual void SetModelIndex(uint32 id);\n\tvirtual void ProcessControl();\n\tvirtual void Teleport(CVector v);\n\tvirtual void PreRender(void);\n\tvirtual void Render(void);\n\tvirtual void ProcessControlInputs(uint8);\n\tvirtual void GetComponentWorldPosition(int32 component, CVector &pos);\n\tvirtual bool IsComponentPresent(int32 component) { return true; }\n\tvirtual void BlowUpCar(CEntity *ent);\n\n\tvoid RenderWaterOutPolys(void);\n\tvoid ApplyWaterResistance(void);\n\tvoid SetupModelNodes();\n\tvoid PruneWakeTrail(void);\n\tvoid AddWakePoint(CVector point);\n\tvoid DoDriveByShootings(void);\n\n\tstatic CBoat *apFrameWakeGeneratingBoats[4];\n\t\n\tstatic bool IsSectorAffectedByWake(CVector2D sector, float fSize, CBoat **apBoats);\n\tstatic float IsVertexAffectedByWake(CVector vecVertex, CBoat *pBoat);\n\tstatic void FillBoatList(void);\n\n#ifdef COMPATIBLE_SAVES\n\tvirtual void Save(uint8*& buf);\n\tvirtual void Load(uint8*& buf);\n#endif\n\tstatic const uint32 nSaveStructSize;\n\n};"
  },
  {
    "path": "src/vehicles/CarGen.cpp",
    "content": "#include \"common.h\"\n\n#include \"CarGen.h\"\n\n#include \"Automobile.h\"\n#include \"Bike.h\"\n#include \"Boat.h\"\n#include \"Camera.h\"\n#include \"CarCtrl.h\"\n#include \"CutsceneMgr.h\"\n#include \"General.h\"\n#include \"Pools.h\"\n#include \"Streaming.h\"\n#include \"Timer.h\"\n#include \"Vehicle.h\"\n#include \"VisibilityPlugins.h\"\n#include \"World.h\"\n#include \"Zones.h\"\n#include \"Occlusion.h\"\n\nuint8 CTheCarGenerators::ProcessCounter;\nuint32 CTheCarGenerators::NumOfCarGenerators;\nCCarGenerator CTheCarGenerators::CarGeneratorArray[NUM_CARGENS];\nuint8 CTheCarGenerators::GenerateEvenIfPlayerIsCloseCounter;\nuint32 CTheCarGenerators::CurrentActiveCount;\n\nvoid CCarGenerator::SwitchOff()\n{\n#ifdef FIX_BUGS\n\tif (m_nUsesRemaining != 0)\n#endif\n\t{\n\t\tm_nUsesRemaining = 0;\n\t\t--CTheCarGenerators::CurrentActiveCount;\n\t}\n}\n\nvoid CCarGenerator::SwitchOn()\n{\n\tm_nUsesRemaining = UINT16_MAX;\n\tm_nTimer = CalcNextGen();\n\t++CTheCarGenerators::CurrentActiveCount;\n}\n\nuint32 CCarGenerator::CalcNextGen()\n{\n\treturn CTimer::GetTimeInMilliseconds() + 4;\n}\n\nvoid CCarGenerator::DoInternalProcessing()\n{\n\tint mi;\n\tif (CCarCtrl::NumParkedCars >= 10)\n\t\treturn;\n\tif (m_nModelIndex >= 0) {\n\t\tif (CheckForBlockage(m_nModelIndex)) {\n\t\t\tm_nTimer += 4;\n\t\t\treturn;\n\t\t}\n\t\tCStreaming::RequestModel(m_nModelIndex, STREAMFLAGS_DEPENDENCY);\n\t\tmi = m_nModelIndex;\n\t}\n\telse {\n\t\tmi = -m_nModelIndex;\n\t\tif (m_nModelIndex == -1 || !CStreaming::HasModelLoaded(mi)) {\n\t\t\tCZoneInfo pZone;\n\t\t\tCVector pos = FindPlayerCoors();\n\t\t\tCTheZones::GetZoneInfoForTimeOfDay(&pos, &pZone);\n\t\t\tmi = CCarCtrl::ChooseCarModel(CCarCtrl::ChooseCarRating(&pZone));\n\t\t\tif (mi < 0)\n\t\t\t\treturn;\n\t\t\tm_nModelIndex = -mi;\n\t\t\tm_nColor1 = -1;\n\t\t\tm_nColor2 = -1;\n\t\t}\n\t\tif (CheckForBlockage(mi)) {\n\t\t\tm_nTimer += 4;\n\t\t\treturn;\n\t\t}\n\t}\n\tif (!CStreaming::HasModelLoaded(mi))\n\t\treturn;\n\tCVehicle* pVehicle;\n\n\tCVector pos;\n\tif (CModelInfo::IsBoatModel(mi)){\n\t\tCBoat* pBoat = new CBoat(mi, PARKED_VEHICLE);\n\t\tpos = m_vecPos;\n\t\tpVehicle = pBoat;\n\t\tif (pos.z <= -100.0f)\n\t\t\tpos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);\n\t\tpBoat->bExtendedRange = true;\n\t}else{\n\t\tbool groundFound;\n\t\tpos = m_vecPos;\n\t\tif (pos.z > -100.0f){\n\t\t\tpos.z = CWorld::FindGroundZFor3DCoord(pos.x, pos.y, pos.z, &groundFound);\n\t\t}else{\n\t\t\tgroundFound = false;\n\t\t\tCColPoint cp;\n\t\t\tCEntity* pEntity;\n\t\t\tgroundFound = CWorld::ProcessVerticalLine(CVector(pos.x, pos.y, 1000.0f), -1000.0f,\n\t\t\t\tcp, pEntity, true, false, false, false, false, false, nil);\n\t\t\tif (groundFound)\n\t\t\t\tpos.z = cp.point.z;\n\t\t}\n\t\tif (!groundFound) {\n\t\t\tdebug(\"CCarGenerator::DoInternalProcessing - can't find ground z for new car x = %f y = %f \\n\", m_vecPos.x, m_vecPos.y);\n\t\t\treturn;\n\t\t}\n\t\tif (((CVehicleModelInfo*)CModelInfo::GetModelInfo(mi))->m_vehicleType == VEHICLE_TYPE_BIKE) {\n\t\t\tCBike* pBike = new CBike(mi, PARKED_VEHICLE);\n\t\t\tpBike->bIsStanding = true;\n\t\t\tpVehicle = pBike;\n\t\t}\n\t\telse {\n\t\t\tCAutomobile* pCar = new CAutomobile(mi, PARKED_VEHICLE);\n\t\t\tpVehicle = pCar;\n\t\t}\n\t\t// pVehicle->GetDistanceFromCentreOfMassToBaseOfModel();\n\t\tpVehicle->bLightsOn = false;\n\t}\n\tpVehicle->bIsStatic = false;\n\tpVehicle->bEngineOn = false;\n\tpos.z += pVehicle->GetDistanceFromCentreOfMassToBaseOfModel();\n\tpVehicle->SetPosition(pos);\n\tpVehicle->SetOrientation(0.0f, 0.0f, DEGTORAD(m_fAngle));\n\tpVehicle->SetStatus(STATUS_ABANDONED);\n\tpVehicle->m_nDoorLock = CARLOCK_UNLOCKED;\n\tCWorld::Add(pVehicle);\n\tif (CGeneral::GetRandomNumberInRange(0, 100) < m_nAlarm)\n\t\tpVehicle->m_nAlarmState = -1;\n\tif (CGeneral::GetRandomNumberInRange(0, 100) < m_nDoorlock)\n\t\tpVehicle->m_nDoorLock = CARLOCK_LOCKED;\n\tif (m_nColor1 != -1 && m_nColor2 != -1) {\n\t\tpVehicle->m_currentColour1 = m_nColor1;\n\t\tpVehicle->m_currentColour2 = m_nColor2;\n\t}\n\telse if (m_nModelIndex < -1) {\n\t\tm_nColor1 = pVehicle->m_currentColour1;\n\t\tm_nColor2 = pVehicle->m_currentColour2;\n\t}\n\tCVisibilityPlugins::SetClumpAlpha(pVehicle->GetClump(), 0);\n\tm_nVehicleHandle = CPools::GetVehiclePool()->GetIndex(pVehicle);\n\t/* I don't think this is a correct comparasion */\n#ifdef FIX_BUGS\n\tif (m_nUsesRemaining < UINT16_MAX)\n\t\t--m_nUsesRemaining;\n#else\n\tif (m_nUsesRemaining < ~0)\n\t\t--m_nUsesRemaining;\n#endif\n\tm_nTimer = CalcNextGen();\n\tif (m_nUsesRemaining == 0)\n\t\t--CTheCarGenerators::CurrentActiveCount;\n}\n\nvoid CCarGenerator::Process()\n{\n\tif (m_nVehicleHandle == -1 && \n\t\t(CTheCarGenerators::GenerateEvenIfPlayerIsCloseCounter || CTimer::GetTimeInMilliseconds() >= m_nTimer) &&\n\t\tm_nUsesRemaining != 0 && CheckIfWithinRangeOfAnyPlayers())\n\t\tDoInternalProcessing();\n\tif (m_nVehicleHandle == -1)\n\t\treturn;\n\tCVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(m_nVehicleHandle);\n\tif (!pVehicle){\n\t\tm_nVehicleHandle = -1;\n\t\treturn;\n\t}\n\tif (pVehicle->GetStatus() != STATUS_PLAYER)\n\t\treturn;\n\tm_nTimer += 60000;\n\tm_nVehicleHandle = -1;\n\tm_bIsBlocking = true;\n\tpVehicle->bExtendedRange = false;\n\tif (m_nModelIndex < 0)\n\t\tm_nModelIndex = -1;\n}\n\nvoid CCarGenerator::Setup(float x, float y, float z, float angle, int32 mi, int16 color1, int16 color2, uint8 force, uint8 alarm, uint8 lock, uint16 min_delay, uint16 max_delay)\n{\n\tCMatrix m1, m2, m3; /* Unused but present on stack, so I'll leave them. */\n\tm_vecPos = CVector(x, y, z);\n\tm_fAngle = angle;\n\tm_nModelIndex = mi;\n\tm_nColor1 = color1;\n\tm_nColor2 = color2;\n\tm_bForceSpawn = force;\n\tm_nAlarm = alarm;\n\tm_nDoorlock = lock;\n\tm_nMinDelay = min_delay;\n\tm_nMaxDelay = max_delay;\n\tm_nVehicleHandle = -1;\n\tm_nTimer = CTimer::GetTimeInMilliseconds() + 1;\n\tm_nUsesRemaining = 0;\n\tm_bIsBlocking = false;\n}\n\nbool CCarGenerator::CheckForBlockage(int32 mi)\n{\n\tint16 entities;\n\tCEntity* pEntities[8];\n\tCColModel* pColModel = CModelInfo::GetModelInfo(mi)->GetColModel();\n\tCWorld::FindObjectsKindaColliding(CVector(m_vecPos), pColModel->boundingSphere.radius, 1, &entities, 8, pEntities, false, true, true, false, false);\n\tfor (int i = 0; i < entities; i++) {\n\t\tif (m_vecPos.z + pColModel->boundingBox.min.z < pEntities[i]->GetPosition().z + pEntities[i]->GetColModel()->boundingBox.max.z + 1.0f &&\n\t\t\tm_vecPos.z + pColModel->boundingBox.max.z > pEntities[i]->GetPosition().z + pEntities[i]->GetColModel()->boundingBox.min.z - 1.0f) {\n\t\t\tm_bIsBlocking = true;\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n\nbool CCarGenerator::CheckIfWithinRangeOfAnyPlayers()\n{\n\tCVector2D direction = FindPlayerCentreOfWorld(CWorld::PlayerInFocus) - m_vecPos;\n\tfloat distance = direction.Magnitude();\n\tfloat farclip = 110.0f * TheCamera.GenerationDistMultiplier;\n\tfloat nearclip = farclip - 20.0f;\n\tbool canBeRemoved = (m_nModelIndex > 0 && CModelInfo::IsBoatModel(m_nModelIndex) && 165.0f * TheCamera.GenerationDistMultiplier > distance &&\n\t\tTheCamera.IsSphereVisible(m_vecPos, 0.0f) && !COcclusion::IsPositionOccluded(m_vecPos, 0.0f)); \n\tif (distance >= farclip && !canBeRemoved){\n\t\tif (m_bIsBlocking)\n\t\t\tm_bIsBlocking = false;\n\t\treturn false;\n\t}\n\tif (CTheCarGenerators::GenerateEvenIfPlayerIsCloseCounter)\n\t\treturn true;\n\tif (m_bIsBlocking)\n\t\treturn false;\n\tif (distance < nearclip && !m_bForceSpawn)\n\t\treturn false;\n\treturn DotProduct2D(direction, FindPlayerSpeed()) <= 0;\n}\n\nvoid CTheCarGenerators::Process()\n{\n\tif (FindPlayerTrain() || CCutsceneMgr::IsCutsceneProcessing())\n\t\treturn;\n\tif (++CTheCarGenerators::ProcessCounter == 4)\n\t\tCTheCarGenerators::ProcessCounter = 0;\n\tfor (uint32 i = ProcessCounter; i < NumOfCarGenerators; i += 4)\n\t\tCTheCarGenerators::CarGeneratorArray[i].Process();\n\tif (GenerateEvenIfPlayerIsCloseCounter)\n\t\tGenerateEvenIfPlayerIsCloseCounter--;\n}\n\nint32 CTheCarGenerators::CreateCarGenerator(float x, float y, float z, float angle, int32 mi, int16 color1, int16 color2, uint8 force, uint8 alarm, uint8 lock, uint16 min_delay, uint16 max_delay)\n{\n\tif (NumOfCarGenerators < NUM_CARGENS)\n\t\tCarGeneratorArray[NumOfCarGenerators++].Setup(x, y, z, angle, mi, color1, color2, force, alarm, lock, min_delay, max_delay);\n\treturn NumOfCarGenerators - 1;\n}\n\nvoid CTheCarGenerators::Init()\n{\n\tGenerateEvenIfPlayerIsCloseCounter = 0;\n\tNumOfCarGenerators = 0;\n\tProcessCounter = 0;\n\tCurrentActiveCount = 0;\n}\n\nvoid CTheCarGenerators::SaveAllCarGenerators(uint8 *buffer, uint32 *size)\n{\n\tconst uint32 nGeneralDataSize = sizeof(NumOfCarGenerators) + sizeof(CurrentActiveCount) + sizeof(ProcessCounter) + sizeof(GenerateEvenIfPlayerIsCloseCounter) + sizeof(int16);\n\t*size = sizeof(int) + nGeneralDataSize + sizeof(uint32) + sizeof(CarGeneratorArray) + SAVE_HEADER_SIZE;\nINITSAVEBUF\n\tWriteSaveHeader(buffer, 'C','G','N','\\0', *size - SAVE_HEADER_SIZE);\n\n\tWriteSaveBuf(buffer, nGeneralDataSize);\n\tWriteSaveBuf(buffer, NumOfCarGenerators);\n\tWriteSaveBuf(buffer, CurrentActiveCount);\n\tWriteSaveBuf(buffer, ProcessCounter);\n\tWriteSaveBuf(buffer, GenerateEvenIfPlayerIsCloseCounter);\n\tWriteSaveBuf(buffer, (int16)0); // alignment\n\tWriteSaveBuf(buffer, (uint32)sizeof(CarGeneratorArray));\n\tfor (int i = 0; i < NUM_CARGENS; i++)\n\t\tWriteSaveBuf(buffer, CarGeneratorArray[i]);\nVALIDATESAVEBUF(*size)\n}\n\nvoid CTheCarGenerators::LoadAllCarGenerators(uint8* buffer, uint32 size)\n{\n\tNumOfCarGenerators = 0;\n\tGenerateEvenIfPlayerIsCloseCounter = 0;\n\tCurrentActiveCount = 0;\n\tProcessCounter = 0;\n\n\tconst int32 nGeneralDataSize = sizeof(NumOfCarGenerators) + sizeof(CurrentActiveCount) + sizeof(ProcessCounter) + sizeof(GenerateEvenIfPlayerIsCloseCounter) + sizeof(int16);\n\tInit();\nINITSAVEBUF\n\tCheckSaveHeader(buffer, 'C','G','N','\\0', size - SAVE_HEADER_SIZE);\n\tassert(ReadSaveBuf<uint32>(buffer) == nGeneralDataSize);\n\tNumOfCarGenerators = ReadSaveBuf<uint32>(buffer);\n\tCurrentActiveCount = ReadSaveBuf<uint32>(buffer);\n\tProcessCounter = ReadSaveBuf<uint8>(buffer);\n\tGenerateEvenIfPlayerIsCloseCounter = ReadSaveBuf<uint8>(buffer);\n\tReadSaveBuf<int16>(buffer); // alignment\n\tassert(ReadSaveBuf<uint32>(buffer) == sizeof(CarGeneratorArray));\n\tfor (int i = 0; i < NUM_CARGENS; i++) \n\t\tCarGeneratorArray[i] = ReadSaveBuf<CCarGenerator>(buffer);\nVALIDATESAVEBUF(size)\n}\n"
  },
  {
    "path": "src/vehicles/CarGen.h",
    "content": "#pragma once\n#include \"common.h\"\n#include \"config.h\"\n\nenum {\n\tCARGEN_MAXACTUALLIMIT = 100\n};\n\nclass CCarGenerator\n{\n\tint32 m_nModelIndex;\n\tCVector m_vecPos;\n\tfloat m_fAngle;\n\tint16 m_nColor1;\n\tint16 m_nColor2;\n\tuint8 m_bForceSpawn;\n\tuint8 m_nAlarm;\n\tuint8 m_nDoorlock;\n\tint16 m_nMinDelay;\n\tint16 m_nMaxDelay;\n\tuint32 m_nTimer;\n\tint32 m_nVehicleHandle;\n\tuint16 m_nUsesRemaining;\n\tbool m_bIsBlocking;\npublic:\n\tvoid SwitchOff();\n\tvoid SwitchOn();\n\tuint32 CalcNextGen();\n\tvoid DoInternalProcessing();\n\tvoid Process();\n\tvoid Setup(float x, float y, float z, float angle, int32 mi, int16 color1, int16 color2, uint8 force, uint8 alarm, uint8 lock, uint16 min_delay, uint16 max_delay);\n\tbool CheckForBlockage(int32 mi);\n\tbool CheckIfWithinRangeOfAnyPlayers();\n\tvoid SetUsesRemaining(uint16 uses) { m_nUsesRemaining = uses; }\n};\n\nclass CTheCarGenerators\n{\npublic:\n\tstatic uint8 ProcessCounter;\n\tstatic uint32 NumOfCarGenerators;\n\tstatic CCarGenerator CarGeneratorArray[NUM_CARGENS];\n\tstatic uint8 GenerateEvenIfPlayerIsCloseCounter;\n\tstatic uint32 CurrentActiveCount;\n\n\tstatic void Process();\n\tstatic int32 CreateCarGenerator(float x, float y, float z, float angle, int32 mi, int16 color1, int16 color2, uint8 force, uint8 alarm, uint8 lock, uint16 min_delay, uint16 max_delay);\n\tstatic void Init();\n\tstatic void SaveAllCarGenerators(uint8 *, uint32 *);\n\tstatic void LoadAllCarGenerators(uint8 *, uint32);\n};\n"
  },
  {
    "path": "src/vehicles/Cranes.cpp",
    "content": "#include \"common.h\"\n\n#include \"Cranes.h\"\n\n#include \"Camera.h\"\n#include \"DMAudio.h\"\n#include \"Garages.h\"\n#include \"General.h\"\n#include \"Entity.h\"\n#include \"ModelIndices.h\"\n#include \"Replay.h\"\n#include \"Object.h\"\n#include \"World.h\"\n\n#define MAX_DISTANCE_TO_FIND_CRANE (10.0f)\n#define CRANE_UPDATE_RADIUS (300.0f)\n#define CRANE_MOVEMENT_PROCESSING_RADIUS (150.0f)\n#define CRUSHER_Z (-0.951f)\n#define MILITARY_Z (10.7862f)\n#define DISTANCE_FROM_PLAYER_TO_REMOVE_VEHICLE (5.0f)\n#define DISTANCE_FROM_HOOK_TO_VEHICLE_TO_COLLECT (0.5f)\n#define CAR_REWARD_MILITARY_CRANE (1500)\n#define CAR_MOVING_SPEED_THRESHOLD (0.01f)\n#define CRANE_SLOWDOWN_MULTIPLIER (0.3f)\n\n#define OSCILLATION_SPEED (0.002f)\n#define CAR_ROTATION_SPEED (0.0035f)\n#define CRANE_MOVEMENT_SPEED (0.001f)\n#define HOOK_ANGLE_MOVEMENT_SPEED (0.004f)\n#define HOOK_OFFSET_MOVEMENT_SPEED (0.1f)\n#define HOOK_HEIGHT_MOVEMENT_SPEED (0.06f)\n\n#define MESSAGE_SHOW_DURATION (4000)\n\n#define MAX_DISTANCE (99999.9f)\n#define MIN_VALID_POSITION (-10000.0f)\n#define DEFAULT_OFFSET (20.0f)\n\nuint32 TimerForCamInterpolation;\n\nuint32 CCranes::CarsCollectedMilitaryCrane;\nint32 CCranes::NumCranes;\nCCrane CCranes::aCranes[NUM_CRANES];\n\nvoid CCranes::InitCranes(void)\n{\n\tCarsCollectedMilitaryCrane = 0;\n\tNumCranes = 0;\n\tfor (int i = 0; i < NUMSECTORS_X; i++) {\n\t\tfor (int j = 0; j < NUMSECTORS_Y; j++) {\n\t\t\tfor (CPtrNode* pNode = CWorld::GetSector(i, j)->m_lists[ENTITYLIST_BUILDINGS].first; pNode; pNode = pNode->next) {\n\t\t\t\tCEntity* pEntity = (CEntity*)pNode->item;\n\t\t\t\tif (MODELID_CRANE_1 == pEntity->GetModelIndex() ||\n\t\t\t\t\tMODELID_CRANE_2 == pEntity->GetModelIndex() ||\n\t\t\t\t\tMODELID_CRANE_3 == pEntity->GetModelIndex() ||\n\t\t\t\t\tMODELID_CRANE_4 == pEntity->GetModelIndex() ||\n\t\t\t\t\tMODELID_CRANE_5 == pEntity->GetModelIndex() ||\n\t\t\t\t\tMODELID_CRANE_6 == pEntity->GetModelIndex())\n\t\t\t\t\tAddThisOneCrane(pEntity);\n\t\t\t}\n\t\t}\n\t}\n\tfor (CPtrNode* pNode = CWorld::GetBigBuildingList(LEVEL_MAINLAND).first; pNode; pNode = pNode->next) {\n\t\tCEntity* pEntity = (CEntity*)pNode->item;\n\t\tif (MODELID_CRANE_1 == pEntity->GetModelIndex() ||\n\t\t\tMODELID_CRANE_2 == pEntity->GetModelIndex() ||\n\t\t\tMODELID_CRANE_3 == pEntity->GetModelIndex() ||\n\t\t\tMODELID_CRANE_4 == pEntity->GetModelIndex() ||\n\t\t\tMODELID_CRANE_5 == pEntity->GetModelIndex() ||\n\t\t\tMODELID_CRANE_6 == pEntity->GetModelIndex())\n\t\t\tAddThisOneCrane(pEntity);\n\t}\n}\n\nvoid CCranes::AddThisOneCrane(CEntity* pEntity)\n{\n\tpEntity->GetMatrix().ResetOrientation();\n\tif (NumCranes >= NUM_CRANES)\n\t\treturn;\n\tCCrane* pCrane = &aCranes[NumCranes];\n\tpCrane->Init();\n\tpCrane->m_pCraneEntity = (CBuilding*)pEntity;\n\tpCrane->m_nCraneStatus = CCrane::NONE;\n\tpCrane->m_fHookAngle = NumCranes; // lol wtf\n\twhile (pCrane->m_fHookAngle > TWOPI)\n\t\tpCrane->m_fHookAngle -= TWOPI;\n\tpCrane->m_fHookOffset = DEFAULT_OFFSET;\n\tpCrane->m_fHookHeight = DEFAULT_OFFSET;\n\tpCrane->m_nTimeForNextCheck = 0;\n\tpCrane->m_nCraneState = CCrane::IDLE;\n\tpCrane->m_bWasMilitaryCrane = false;\n\tpCrane->m_bIsTop = (MODELID_CRANE_1 != pEntity->GetModelIndex());\n\tpCrane->m_pHook = nil;\n\tNumCranes++;\n}\n\nvoid CCranes::ActivateCrane(float fInfX, float fSupX, float fInfY, float fSupY, float fDropOffX, float fDropOffY, float fDropOffZ, float fHeading, bool bIsCrusher, bool bIsMilitary, float fPosX, float fPosY)\n{\n\tfloat fMinDistance = MAX_DISTANCE;\n\tfloat X = fPosX, Y = fPosY;\n\tif (X <= MIN_VALID_POSITION || Y <= MIN_VALID_POSITION) {\n\t\tX = fDropOffX;\n\t\tY = fDropOffY;\n\t}\n\tint index = 0;\n\tfor (int i = 0; i < NumCranes; i++) {\n\t\tfloat distance = (CVector2D(X, Y) - aCranes[i].m_pCraneEntity->GetPosition()).Magnitude();\n\t\tif (distance < fMinDistance && distance < MAX_DISTANCE_TO_FIND_CRANE) {\n\t\t\tfMinDistance = distance;\n\t\t\tindex = i;\n\t\t}\n\t}\n#ifdef FIX_BUGS // classic\n\tif (fMinDistance == MAX_DISTANCE)\n\t\treturn;\n#endif\n\tCCrane* pCrane = &aCranes[index];\n\tpCrane->m_fPickupX1 = fInfX;\n\tpCrane->m_fPickupX2 = fSupX;\n\tpCrane->m_fPickupY1 = fInfY;\n\tpCrane->m_fPickupY2 = fSupY;\n\tpCrane->m_vecDropoffTarget.x = fDropOffX;\n\tpCrane->m_vecDropoffTarget.y = fDropOffY;\n\tpCrane->m_vecDropoffTarget.z = fDropOffZ;\n\tpCrane->m_nCraneStatus = CCrane::ACTIVATED;\n\tpCrane->m_pVehiclePickedUp = nil;\n\tpCrane->m_nVehiclesCollected = 0;\n\tpCrane->m_fDropoffHeading = fHeading;\n\tpCrane->m_bIsCrusher = bIsCrusher;\n\tpCrane->m_bIsMilitaryCrane = bIsMilitary;\n\tbool military = true;\n\tif (!bIsMilitary && !pCrane->m_bWasMilitaryCrane)\n\t\tmilitary = false;\n\tpCrane->m_bWasMilitaryCrane = military;\n\tpCrane->m_nTimeForNextCheck = 0;\n\tpCrane->m_nCraneState = CCrane::IDLE;\n\tfloat Z;\n\tif (bIsCrusher)\n\t\tZ = CRUSHER_Z;\n\telse if (bIsMilitary)\n\t\tZ = MILITARY_Z;\n\telse\n\t\tZ = CWorld::FindGroundZForCoord((fInfX + fSupX) / 2, (fInfY + fSupY) / 2);\n\tpCrane->FindParametersForTarget((fInfX + fSupX) / 2, (fInfY + fSupY) / 2, Z, &pCrane->m_fPickupAngle, &pCrane->m_fPickupDistance, &pCrane->m_fPickupHeight);\n\tpCrane->FindParametersForTarget(fDropOffX, fDropOffY, fDropOffZ, &pCrane->m_fDropoffAngle, &pCrane->m_fDropoffDistance, &pCrane->m_fDropoffHeight);\n}\n\nvoid CCranes::DeActivateCrane(float X, float Y)\n{\n\tfloat fMinDistance = MAX_DISTANCE;\n\tint index = 0;\n\tfor (int i = 0; i < NumCranes; i++) {\n\t\tfloat distance = (CVector2D(X, Y) - aCranes[i].m_pCraneEntity->GetPosition()).Magnitude();\n\t\tif (distance < fMinDistance && distance < MAX_DISTANCE_TO_FIND_CRANE) {\n\t\t\tfMinDistance = distance;\n\t\t\tindex = i;\n\t\t}\n\t}\n#ifdef FIX_BUGS // classic\n\tif (fMinDistance == MAX_DISTANCE)\n\t\treturn;\n#endif\n\taCranes[index].m_nCraneStatus = CCrane::DEACTIVATED;\n\taCranes[index].m_nCraneState = CCrane::IDLE;\n}\n\nbool CCranes::IsThisCarPickedUp(float X, float Y, CVehicle* pVehicle)\n{\n\tint index = 0;\n\tbool result = false;\n\tfor (int i = 0; i < NumCranes; i++) {\n\t\tfloat distance = (CVector2D(X, Y) - aCranes[i].m_pCraneEntity->GetPosition()).Magnitude();\n\t\tif (distance < MAX_DISTANCE_TO_FIND_CRANE && aCranes[i].m_pVehiclePickedUp == pVehicle) {\n\t\t\tif (aCranes[i].m_nCraneState == CCrane::LIFTING_TARGET || aCranes[i].m_nCraneState == CCrane::ROTATING_TARGET)\n\t\t\t\tresult = true;\n\t\t}\n\t}\n\treturn result;\n}\n\nvoid CCranes::UpdateCranes(void)\n{\n\tfor (int i = 0; i < NumCranes; i++) {\n\t\tif (aCranes[i].m_bIsTop || aCranes[i].m_bIsCrusher ||\n\t\t\t(TheCamera.GetPosition().x + CRANE_UPDATE_RADIUS > aCranes[i].m_pCraneEntity->GetPosition().x &&\n\t\t\t\tTheCamera.GetPosition().x - CRANE_UPDATE_RADIUS < aCranes[i].m_pCraneEntity->GetPosition().x &&\n\t\t\t\tTheCamera.GetPosition().y + CRANE_UPDATE_RADIUS > aCranes[i].m_pCraneEntity->GetPosition().y &&\n\t\t\t\tTheCamera.GetPosition().y + CRANE_UPDATE_RADIUS < aCranes[i].m_pCraneEntity->GetPosition().y))\n\t\t\taCranes[i].Update();\n\t}\n}\n\nvoid CCrane::Update(void)\n{\n\tif (CReplay::IsPlayingBack())\n\t\treturn;\n\tif (((m_nCraneStatus == ACTIVATED || m_nCraneStatus == DEACTIVATED) &&\n\t\tAbs(TheCamera.GetGameCamPosition().x - m_pCraneEntity->GetPosition().x) < CRANE_MOVEMENT_PROCESSING_RADIUS &&\n\t\tAbs(TheCamera.GetGameCamPosition().y - m_pCraneEntity->GetPosition().y) < CRANE_MOVEMENT_PROCESSING_RADIUS) ||\n\t\tm_nCraneState != IDLE) {\n\t\tswitch (m_nCraneState) {\n\t\tcase IDLE:\n\t\t\tif (GoTowardsTarget(m_fPickupAngle, m_fPickupDistance, GetHeightToPickup()) &&\n\t\t\t\tCTimer::GetTimeInMilliseconds() > m_nTimeForNextCheck) {\n\t\t\t\tCWorld::AdvanceCurrentScanCode();\n#ifdef FIX_BUGS\n\t\t\t\tint xstart = Max(0, CWorld::GetSectorIndexX(m_fPickupX1));\n\t\t\t\tint xend = Min(NUMSECTORS_X - 1, CWorld::GetSectorIndexX(m_fPickupX2));\n\t\t\t\tint ystart = Max(0, CWorld::GetSectorIndexY(m_fPickupY1));\n\t\t\t\tint yend = Min(NUMSECTORS_Y - 1, CWorld::GetSectorIndexY(m_fPickupY2));\n#else\n\t\t\t\tint xstart = CWorld::GetSectorIndexX(m_fPickupX1);\n\t\t\t\tint xend = CWorld::GetSectorIndexX(m_fPickupX2);\n\t\t\t\tint ystart = CWorld::GetSectorIndexY(m_fPickupY1);\n\t\t\t\tint yend = CWorld::GetSectorIndexY(m_fPickupY1);\n#endif\n\t\t\t\tassert(xstart <= xend);\n\t\t\t\tassert(ystart <= yend);\n\t\t\t\tfor (int i = xstart; i <= xend; i++) {\n\t\t\t\t\tfor (int j = ystart; j <= yend; j++) {\n\t\t\t\t\t\tFindCarInSectorList(&CWorld::GetSector(i, j)->m_lists[ENTITYLIST_VEHICLES]);\n\t\t\t\t\t\tFindCarInSectorList(&CWorld::GetSector(i, j)->m_lists[ENTITYLIST_VEHICLES_OVERLAP]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\tcase GOING_TOWARDS_TARGET:\n\t\t\tif (m_pVehiclePickedUp){\n\t\t\t\tif (m_pVehiclePickedUp->GetPosition().x < m_fPickupX1 ||\n\t\t\t\t\tm_pVehiclePickedUp->GetPosition().x > m_fPickupX2 ||\n\t\t\t\t\tm_pVehiclePickedUp->GetPosition().y < m_fPickupY1 ||\n\t\t\t\t\tm_pVehiclePickedUp->GetPosition().y > m_fPickupY2 ||\n\t\t\t\t\tm_pVehiclePickedUp->pDriver ||\n\t\t\t\t\tAbs(m_pVehiclePickedUp->GetMoveSpeed().x) > CAR_MOVING_SPEED_THRESHOLD ||\n\t\t\t\t\tAbs(m_pVehiclePickedUp->GetMoveSpeed().y) > CAR_MOVING_SPEED_THRESHOLD ||\n\t\t\t\t\tAbs(m_pVehiclePickedUp->GetMoveSpeed().z) > CAR_MOVING_SPEED_THRESHOLD ||\n\t\t\t\t\t(FindPlayerPed()->GetPedState() == PED_ENTER_CAR\n#ifdef FIX_BUGS\n\t\t\t\t\t|| FindPlayerPed()->GetPedState() == PED_CARJACK\n#endif\n\t\t\t\t\t) && FindPlayerPed()->m_pSeekTarget == m_pVehiclePickedUp) {\n\t\t\t\t\tm_pVehiclePickedUp = nil;\n\t\t\t\t\tm_nCraneState = IDLE;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tfloat fAngle, fOffset, fHeight;\n\t\t\t\t\tFindParametersForTarget(\n\t\t\t\t\t\tm_pVehiclePickedUp->GetPosition().x,\n\t\t\t\t\t\tm_pVehiclePickedUp->GetPosition().y,\n\t\t\t\t\t\tm_pVehiclePickedUp->GetPosition().z + m_pVehiclePickedUp->GetColModel()->boundingBox.max.z,\n\t\t\t\t\t\t&fAngle, &fOffset, &fHeight);\n\t\t\t\t\tif (GoTowardsTarget(fAngle, fOffset, fHeight)) {\n\t\t\t\t\t\tCVector distance = m_pVehiclePickedUp->GetPosition() - m_vecHookCurPos;\n\t\t\t\t\t\tdistance.z += m_pVehiclePickedUp->GetColModel()->boundingBox.max.z;\n\t\t\t\t\t\tif (distance.MagnitudeSqr() < SQR(DISTANCE_FROM_HOOK_TO_VEHICLE_TO_COLLECT)) {\n\t\t\t\t\t\t\tm_nCraneState = GOING_TOWARDS_TARGET_ONLY_HEIGHT;\n\t\t\t\t\t\t\tm_vecHookVelocity *= 0.4f;\n\t\t\t\t\t\t\tm_pVehiclePickedUp->bLightsOn = false;\n\t\t\t\t\t\t\tm_pVehiclePickedUp->bUsesCollision = false;\n\t\t\t\t\t\t\tif (m_bIsCrusher)\n\t\t\t\t\t\t\t\tm_pVehiclePickedUp->bCollisionProof = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t\tm_nCraneState = IDLE;\n\t\t\tbreak;\n\t\tcase LIFTING_TARGET:\n\t\t\tRotateCarriedCarProperly();\n\t\t\tif (GoTowardsTarget(m_fDropoffAngle, m_fDropoffDistance, GetHeightToDropoff(), CRANE_SLOWDOWN_MULTIPLIER))\n\t\t\t\tm_nCraneState = ROTATING_TARGET;\n\t\t\tif (!m_pVehiclePickedUp || m_pVehiclePickedUp->pDriver) {\n\t\t\t\tm_pVehiclePickedUp = nil;\n\t\t\t\tm_nCraneState = IDLE;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase GOING_TOWARDS_TARGET_ONLY_HEIGHT:\n\t\t\tRotateCarriedCarProperly();\n\t\t\tif (GoTowardsHeightTarget(GetHeightToPickupHeight(), CRANE_SLOWDOWN_MULTIPLIER))\n\t\t\t\tm_nCraneState = LIFTING_TARGET;\n\t\t\tTimerForCamInterpolation = CTimer::GetTimeInMilliseconds();\n\t\t\tif (!m_pVehiclePickedUp || m_pVehiclePickedUp->pDriver) {\n\t\t\t\tm_pVehiclePickedUp = nil;\n\t\t\t\tm_nCraneState = IDLE;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase ROTATING_TARGET:\n\t\t{\n\t\t\tbool bRotateFinished = RotateCarriedCarProperly();\n\t\t\tbool bMovementFinished = GoTowardsTarget(m_fDropoffAngle, m_fDropoffDistance, m_fDropoffHeight, 0.3f);\n\t\t\tif (bMovementFinished && bRotateFinished) {\n\t\t\t\tfloat fDistanceFromPlayer = m_pVehiclePickedUp ? ((CVector2D)FindPlayerCoors() - (CVector2D)m_pVehiclePickedUp->GetPosition()).Magnitude() : 0.0f;\n\t\t\t\tif (fDistanceFromPlayer > DISTANCE_FROM_PLAYER_TO_REMOVE_VEHICLE || !m_bWasMilitaryCrane) {\n\t\t\t\t\tm_nCraneState = DROPPING_TARGET;\n\t\t\t\t\tif (m_pVehiclePickedUp) {\n\t\t\t\t\t\tm_pVehiclePickedUp->bUsesCollision = true;\n\t\t\t\t\t\tm_pVehiclePickedUp->m_nStaticFrames = 0;\n\t\t\t\t\t\t++m_nVehiclesCollected;\n\t\t\t\t\t\tif (m_bIsMilitaryCrane) {\n\t\t\t\t\t\t\tCCranes::RegisterCarForMilitaryCrane(m_pVehiclePickedUp->GetModelIndex());\n\t\t\t\t\t\t\tif (!CCranes::HaveAllCarsBeenCollectedByMilitaryCrane()) {\n\t\t\t\t\t\t\t\tCWorld::Players[CWorld::PlayerInFocus].m_nMoney += CAR_REWARD_MILITARY_CRANE;\n\t\t\t\t\t\t\t\tCGarages::TriggerMessage(\"GA_10\", CAR_REWARD_MILITARY_CRANE, MESSAGE_SHOW_DURATION, -1);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tCWorld::Remove(m_pVehiclePickedUp);\n\t\t\t\t\t\t\tdelete m_pVehiclePickedUp;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tm_pVehiclePickedUp = nil;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tcase DROPPING_TARGET:\n\t\t\tif (GoTowardsTarget(m_fDropoffAngle, m_fDropoffDistance, GetHeightToDropoffHeight(), CRANE_SLOWDOWN_MULTIPLIER)) {\n\t\t\t\tm_nCraneState = IDLE;\n\t\t\t\tm_nTimeForNextCheck = CTimer::GetTimeInMilliseconds() + 10000;\n\t\t\t}\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\t\tCVector vecHook;\n\t\tCalcHookCoordinates(&vecHook.x, &vecHook.y, &vecHook.z);\n\t\tm_vecHookVelocity += ((CVector2D)vecHook - (CVector2D)m_vecHookCurPos) * CTimer::GetTimeStep() * CRANE_MOVEMENT_SPEED;\n\t\tm_vecHookVelocity *= Pow(0.98f, CTimer::GetTimeStep());\n\t\tm_vecHookCurPos.x += m_vecHookVelocity.x * CTimer::GetTimeStep();\n\t\tm_vecHookCurPos.y += m_vecHookVelocity.y * CTimer::GetTimeStep();\n\t\tm_vecHookCurPos.z = vecHook.z;\n\t\tswitch (m_nCraneState) {\n\t\tcase LIFTING_TARGET:\n\t\tcase GOING_TOWARDS_TARGET_ONLY_HEIGHT:\n\t\tcase ROTATING_TARGET:\n\t\t\tif (m_pVehiclePickedUp) {\n\t\t\t\tm_pVehiclePickedUp->SetPosition(m_vecHookCurPos.x, m_vecHookCurPos.y, m_vecHookCurPos.z - m_pVehiclePickedUp->GetColModel()->boundingBox.max.z);\n\t\t\t\tm_pVehiclePickedUp->SetMoveSpeed(0.0f, 0.0f, 0.0f);\n\t\t\t\tCVector up(vecHook.x - m_vecHookCurPos.x, vecHook.y - m_vecHookCurPos.y, 20.0f);\n\t\t\t\tup.Normalise();\n\t\t\t\tm_pVehiclePickedUp->GetRight() = CrossProduct(m_pVehiclePickedUp->GetForward(), up);\n\t\t\t\tm_pVehiclePickedUp->GetForward() = CrossProduct(up, m_pVehiclePickedUp->GetRight());\n\t\t\t\tm_pVehiclePickedUp->GetUp() = up;\n\t\t\t}\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\t}\n\telse {\n\t\tint16 rnd = (m_pCraneEntity->m_randomSeed + (CTimer::GetTimeInMilliseconds() >> 11)) & 0xF;\n\t\t// 16 options, lasting 2048 ms each\n\t\t// a bit awkward: why there are 4 periods for -= and 6 for +=? is it a bug?\n\t\tif (rnd < 4) {\n\t\t\tm_fHookAngle -= OSCILLATION_SPEED * CTimer::GetTimeStep();\n\t\t\tif (m_fHookAngle < 0.0f)\n\t\t\t\tm_fHookAngle += TWOPI;\n\t\t}\n\t\telse if (rnd > 5 && rnd < 12) {\n\t\t\tm_fHookAngle += OSCILLATION_SPEED * CTimer::GetTimeStep();\n\t\t\tif (m_fHookAngle > TWOPI)\n\t\t\t\tm_fHookAngle -= TWOPI;\n\t\t}\n\t\tCalcHookCoordinates(&m_vecHookCurPos.x, &m_vecHookCurPos.y, &m_vecHookCurPos.z);\n\t\tm_vecHookVelocity.x = m_vecHookVelocity.y = 0.0f;\n\t}\n\tfloat fCos = Cos(m_fHookAngle);\n\tfloat fSin = Sin(m_fHookAngle);\n\tm_pCraneEntity->GetRight().x = fCos;\n\tm_pCraneEntity->GetForward().y = fCos;\n\tm_pCraneEntity->GetRight().y = fSin;\n\tm_pCraneEntity->GetForward().x = -fSin;\n\tm_pCraneEntity->GetMatrix().UpdateRW();\n\tm_pCraneEntity->UpdateRwFrame();\n\tSetHookMatrix();\n}\n\nbool CCrane::RotateCarriedCarProperly()\n{\n\tif (m_fDropoffHeading <= 0.0f)\n\t\treturn true;\n\tif (!m_pVehiclePickedUp)\n\t\treturn true;\n\tfloat fAngleDelta = m_fDropoffHeading - CGeneral::GetATanOfXY(m_pVehiclePickedUp->GetForward().x, m_pVehiclePickedUp->GetForward().y);\n\twhile (fAngleDelta < -HALFPI)\n\t\tfAngleDelta += PI;\n\twhile (fAngleDelta > HALFPI)\n\t\tfAngleDelta -= PI;\n\tfloat fDeltaThisFrame = CAR_ROTATION_SPEED * CTimer::GetTimeStep();\n\tif (Abs(fAngleDelta) <= fDeltaThisFrame) // no rotation is actually applied?\n\t\treturn true;\n\tm_pVehiclePickedUp->GetMatrix().RotateZ(fAngleDelta < 0 ? -fDeltaThisFrame : fDeltaThisFrame);\n\treturn false;\n}\n\nvoid CCrane::FindCarInSectorList(CPtrList* pList)\n{\n\tCPtrNode* node;\n\tfor (node = pList->first; node; node = node->next) {\n\t\tCVehicle* pVehicle = (CVehicle*)node->item;\n\t\tif (pVehicle->m_scanCode == CWorld::GetCurrentScanCode())\n\t\t\tcontinue;\n\t\tpVehicle->m_scanCode = CWorld::GetCurrentScanCode();\n\t\tif (pVehicle->GetPosition().x < m_fPickupX1 || pVehicle->GetPosition().x > m_fPickupX2 ||\n\t\t\tpVehicle->GetPosition().y < m_fPickupY1 || pVehicle->GetPosition().y > m_fPickupY2)\n\t\t\tcontinue;\n\t\tif (pVehicle->pDriver)\n\t\t\tcontinue;\n\t\tif (Abs(pVehicle->GetMoveSpeed().x) >= CAR_MOVING_SPEED_THRESHOLD ||\n\t\t\tAbs(pVehicle->GetMoveSpeed().y) >= CAR_MOVING_SPEED_THRESHOLD ||\n\t\t\tAbs(pVehicle->GetMoveSpeed().z) >= CAR_MOVING_SPEED_THRESHOLD)\n\t\t\tcontinue;\n\t\tif (!pVehicle->IsCar() || pVehicle->GetStatus() == STATUS_WRECKED || pVehicle->m_fHealth < 250.0f)\n\t\t\tcontinue;\n\t\tif (!DoesCranePickUpThisCarType(pVehicle->GetModelIndex()) ||\n\t\t\tm_bIsMilitaryCrane && CCranes::DoesMilitaryCraneHaveThisOneAlready(pVehicle->GetModelIndex())) {\n\t\t\tif (!pVehicle->bCraneMessageDone) {\n\t\t\t\tpVehicle->bCraneMessageDone = true;\n\t\t\t\tif (!m_bIsMilitaryCrane)\n\t\t\t\t\tCGarages::TriggerMessage(\"CR_1\", -1, MESSAGE_SHOW_DURATION, -1); // Crane cannot lift this vehicle.\n\t\t\t\telse if (DoesCranePickUpThisCarType(pVehicle->GetModelIndex()))\n\t\t\t\t\tCGarages::TriggerMessage(\"GA_20\", -1, MESSAGE_SHOW_DURATION, -1); // We got more of these than we can shift. Sorry man, no deal.\n\t\t\t\telse\n\t\t\t\t\tCGarages::TriggerMessage(\"GA_19\", -1, MESSAGE_SHOW_DURATION, -1); // We're not interested in that model.\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tm_pVehiclePickedUp = pVehicle;\n\t\t\tpVehicle->RegisterReference((CEntity**)&m_pVehiclePickedUp);\n\t\t\tm_nCraneState = GOING_TOWARDS_TARGET;\n\t\t}\n\t}\n}\n\nbool CCrane::DoesCranePickUpThisCarType(uint32 mi)\n{\n\tif (m_bIsCrusher) {\n\t\treturn mi != MI_FIRETRUCK &&\n\t\t\tmi != MI_TRASH &&\n#ifdef FIX_BUGS\n\t\t\tmi != MI_COACH &&\n#endif\n\t\t\tmi != MI_SECURICA &&\n\t\t\tmi != MI_BUS &&\n\t\t\tmi != MI_DODO &&\n\t\t\tmi != MI_RHINO;\n\t}\n\tif (m_bIsMilitaryCrane) {\n\t\treturn mi == MI_FIRETRUCK ||\n\t\t\tmi == MI_AMBULAN ||\n\t\t\tmi == MI_ENFORCER ||\n\t\t\tmi == MI_FBIRANCH ||\n\t\t\tmi == MI_RHINO ||\n\t\t\tmi == MI_BARRACKS ||\n\t\t\tmi == MI_POLICE;\n\t}\n\treturn true;\n}\n\nbool CCranes::DoesMilitaryCraneHaveThisOneAlready(uint32 mi)\n{\n\tswitch (mi) {\n\tcase MI_FIRETRUCK: return (CarsCollectedMilitaryCrane & 1);\n\tcase MI_AMBULAN: return (CarsCollectedMilitaryCrane & 2);\n\tcase MI_ENFORCER: return (CarsCollectedMilitaryCrane & 4);\n\tcase MI_FBIRANCH: return (CarsCollectedMilitaryCrane & 8);\n\tcase MI_RHINO: return (CarsCollectedMilitaryCrane & 0x10);\n\tcase MI_BARRACKS: return (CarsCollectedMilitaryCrane & 0x20);\n\tcase MI_POLICE: return (CarsCollectedMilitaryCrane & 0x40);\n\tdefault: break;\n\t}\n\treturn false;\n}\n\nvoid CCranes::RegisterCarForMilitaryCrane(uint32 mi)\n{\n\tswitch (mi) {\n\tcase MI_FIRETRUCK: CarsCollectedMilitaryCrane |= 1; break;\n\tcase MI_AMBULAN: CarsCollectedMilitaryCrane |= 2; break;\n\tcase MI_ENFORCER: CarsCollectedMilitaryCrane |= 4; break;\n\tcase MI_FBIRANCH: CarsCollectedMilitaryCrane |= 8; break;\n\tcase MI_RHINO: CarsCollectedMilitaryCrane |= 0x10; break;\n\tcase MI_BARRACKS: CarsCollectedMilitaryCrane |= 0x20; break;\n\tcase MI_POLICE: CarsCollectedMilitaryCrane |= 0x40; break;\n\tdefault: break;\n\t}\n}\n\nbool CCranes::HaveAllCarsBeenCollectedByMilitaryCrane()\n{\n\treturn (CarsCollectedMilitaryCrane & 0x7F) == 0x7F;\n}\n\nbool CCrane::GoTowardsTarget(float fAngleToTarget, float fDistanceToTarget, float fTargetHeight, float fSpeedMultiplier)\n{\n\tbool bAngleMovementFinished, bOffsetMovementFinished, bHeightMovementFinished;\n\tfloat fHookAngleDelta = fAngleToTarget - m_fHookAngle;\n\twhile (fHookAngleDelta > PI)\n\t\tfHookAngleDelta -= TWOPI;\n\twhile (fHookAngleDelta < -PI)\n\t\tfHookAngleDelta += TWOPI;\n\tfloat fHookAngleChangeThisFrame = fSpeedMultiplier * CTimer::GetTimeStep() * HOOK_ANGLE_MOVEMENT_SPEED;\n\tif (Abs(fHookAngleDelta) < fHookAngleChangeThisFrame) {\n\t\tm_fHookAngle = fAngleToTarget;\n\t\tbAngleMovementFinished = true;\n\t} else {\n\t\tif (fHookAngleDelta < 0.0f) {\n\t\t\tm_fHookAngle -= fHookAngleChangeThisFrame;\n\t\t\tif (m_fHookAngle < 0.0f)\n\t\t\t\tm_fHookAngle += TWOPI;\n\t\t}\n\t\telse {\n\t\t\tm_fHookAngle += fHookAngleChangeThisFrame;\n\t\t\tif (m_fHookAngle > TWOPI)\n\t\t\t\tm_fHookAngle -= TWOPI;\n\t\t}\n\t\tbAngleMovementFinished = false;\n\t}\n\tfloat fHookOffsetDelta = fDistanceToTarget - m_fHookOffset;\n\tfloat fHookOffsetChangeThisFrame = fSpeedMultiplier * CTimer::GetTimeStep() * HOOK_OFFSET_MOVEMENT_SPEED;\n\tif (Abs(fHookOffsetDelta) < fHookOffsetChangeThisFrame) {\n\t\tm_fHookOffset = fDistanceToTarget;\n\t\tbOffsetMovementFinished = true;\n\t} else {\n\t\tif (fHookOffsetDelta < 0.0f)\n\t\t\tm_fHookOffset -= fHookOffsetChangeThisFrame;\n\t\telse\n\t\t\tm_fHookOffset += fHookOffsetChangeThisFrame;\n\t\tbOffsetMovementFinished = false;\n\t}\n\tfloat fHookHeightDelta = fTargetHeight - m_fHookHeight;\n\tfloat fHookHeightChangeThisFrame = fSpeedMultiplier * CTimer::GetTimeStep() * HOOK_HEIGHT_MOVEMENT_SPEED;\n\tif (Abs(fHookHeightDelta) < fHookHeightChangeThisFrame) {\n\t\tm_fHookHeight = fTargetHeight;\n\t\tbHeightMovementFinished = true;\n\t} else {\n\t\tif (fHookHeightDelta < 0.0f)\n\t\t\tm_fHookHeight -= fHookHeightChangeThisFrame;\n\t\telse\n\t\t\tm_fHookHeight += fHookHeightChangeThisFrame;\n\t\tbHeightMovementFinished = false;\n\t}\n\treturn bAngleMovementFinished && bOffsetMovementFinished && bHeightMovementFinished;\n}\n\nbool CCrane::GoTowardsHeightTarget(float fTargetHeight, float fSpeedMultiplier)\n{\n\tbool bHeightMovementFinished;\n\tfloat fHookHeightDelta = fTargetHeight - m_fHookHeight;\n\tfloat fHookHeightChangeThisFrame = fSpeedMultiplier * CTimer::GetTimeStep() * HOOK_HEIGHT_MOVEMENT_SPEED;\n\tif (Abs(fHookHeightDelta) < fHookHeightChangeThisFrame) {\n\t\tm_fHookHeight = fTargetHeight;\n\t\tbHeightMovementFinished = true;\n\t} else {\n\t\tif (fHookHeightDelta < 0.0f)\n\t\t\tm_fHookHeight -= fHookHeightChangeThisFrame;\n\t\telse\n\t\t\tm_fHookHeight += fHookHeightChangeThisFrame;\n\t\tbHeightMovementFinished = false;\n\t}\n\treturn bHeightMovementFinished;\n}\n\nvoid CCrane::FindParametersForTarget(float X, float Y, float Z, float* pAngle, float* pDistance, float* pHeight)\n{\n\t*pAngle = CGeneral::GetATanOfXY(X - m_pCraneEntity->GetPosition().x, Y - m_pCraneEntity->GetPosition().y);\n\t*pDistance = ((CVector2D(X, Y) - (CVector2D)m_pCraneEntity->GetPosition())).Magnitude();\n\t*pHeight = Z;\n}\n\nvoid CCrane::CalcHookCoordinates(float* pX, float* pY, float* pZ)\n{\n\t*pX = Cos(m_fHookAngle) * m_fHookOffset + m_pCraneEntity->GetPosition().x;\n\t*pY = Sin(m_fHookAngle) * m_fHookOffset + m_pCraneEntity->GetPosition().y;\n\t*pZ = m_fHookHeight;\n}\n\nvoid CCrane::SetHookMatrix()\n{\n\tif (m_pHook == nil)\n\t\treturn;\n\tm_pHook->SetPosition(m_vecHookCurPos);\n\tCVector up(m_vecHookInitPos.x - m_vecHookCurPos.x, m_vecHookInitPos.y - m_vecHookCurPos.y, 20.0f);\n\tup.Normalise();\n\tm_pHook->GetRight() = CrossProduct(CVector(0.0f, 1.0f, 0.0f), up);\n\tm_pHook->GetForward() = CrossProduct(up, m_pHook->GetRight());\n\tm_pHook->GetUp() = up;\n\tm_pHook->SetOrientation(0.0f, 0.0f, -HALFPI);\n\tm_pHook->GetMatrix().UpdateRW();\n\tm_pHook->UpdateRwFrame();\n\tCWorld::Remove(m_pHook);\n\tCWorld::Add(m_pHook);\n}\n\nbool CCranes::IsThisCarBeingCarriedByAnyCrane(CVehicle* pVehicle)\n{\n\tfor (int i = 0; i < NumCranes; i++) {\n\t\tif (pVehicle == aCranes[i].m_pVehiclePickedUp) {\n\t\t\tswitch (aCranes[i].m_nCraneState) {\n\t\t\tcase CCrane::GOING_TOWARDS_TARGET_ONLY_HEIGHT:\n\t\t\tcase CCrane::LIFTING_TARGET:\n\t\t\tcase CCrane::ROTATING_TARGET:\n\t\t\t\treturn true;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\treturn false;\n}\n\nbool CCranes::IsThisCarBeingTargettedByAnyCrane(CVehicle* pVehicle)\n{\n\tfor (int i = 0; i < NumCranes; i++) {\n\t\tif (pVehicle == aCranes[i].m_pVehiclePickedUp)\n\t\t\treturn true;\n\t}\n\treturn false;\n}\n\nvoid CCranes::Save(uint8* buf, uint32* size)\n{\n\tINITSAVEBUF\n\n\t*size = 2 * sizeof(uint32) + sizeof(aCranes);\n\tWriteSaveBuf(buf, NumCranes);\n\tWriteSaveBuf(buf, CarsCollectedMilitaryCrane);\n\tfor (int i = 0; i < NUM_CRANES; i++) {\n\t\tCCrane *pCrane = WriteSaveBuf(buf, aCranes[i]);\n\t\tif (pCrane->m_pCraneEntity != nil)\n\t\t\tpCrane->m_pCraneEntity = (CBuilding*)(CPools::GetBuildingPool()->GetJustIndex_NoFreeAssert(pCrane->m_pCraneEntity) + 1);\n\t\tif (pCrane->m_pHook != nil)\n\t\t\tpCrane->m_pHook = (CObject*)(CPools::GetObjectPool()->GetJustIndex_NoFreeAssert(pCrane->m_pHook) + 1);\n\t\tif (pCrane->m_pVehiclePickedUp != nil)\n\t\t\tpCrane->m_pVehiclePickedUp = (CVehicle*)(CPools::GetVehiclePool()->GetJustIndex_NoFreeAssert(pCrane->m_pVehiclePickedUp) + 1);\n\t}\n\n\tVALIDATESAVEBUF(*size);\n}\n\nvoid CCranes::Load(uint8* buf, uint32 size)\n{\n\tINITSAVEBUF\n\n\tNumCranes = ReadSaveBuf<int32>(buf);\n\tCarsCollectedMilitaryCrane = ReadSaveBuf<uint32>(buf);\n\tfor (int i = 0; i < NUM_CRANES; i++)\n\t\taCranes[i] = ReadSaveBuf<CCrane>(buf);\n\tfor (int i = 0; i < NUM_CRANES; i++) {\n\t\tCCrane *pCrane = &aCranes[i];\n\t\tif (pCrane->m_pCraneEntity != nil)\n\t\t\tpCrane->m_pCraneEntity = CPools::GetBuildingPool()->GetSlot((uintptr)pCrane->m_pCraneEntity - 1);\n\t\tif (pCrane->m_pHook != nil)\n\t\t\tpCrane->m_pHook = CPools::GetObjectPool()->GetSlot((uintptr)pCrane->m_pHook - 1);\n\t\tif (pCrane->m_pVehiclePickedUp != nil)\n\t\t\tpCrane->m_pVehiclePickedUp = CPools::GetVehiclePool()->GetSlot((uintptr)pCrane->m_pVehiclePickedUp - 1);\n\t}\n\n\tVALIDATESAVEBUF(size);\n}\n"
  },
  {
    "path": "src/vehicles/Cranes.h",
    "content": "#pragma once\n#include \"common.h\"\n\n#include \"World.h\"\n\nclass CVehicle;\nclass CEntity;\nclass CObject;\nclass CBuilding;\n\nclass CCrane\n{\npublic:\n\tenum CraneState {\n\t\tIDLE = 0,\n\t\tGOING_TOWARDS_TARGET = 1,\n\t\tLIFTING_TARGET = 2,\n\t\tGOING_TOWARDS_TARGET_ONLY_HEIGHT = 3,\n\t\tROTATING_TARGET = 4,\n\t\tDROPPING_TARGET = 5\n\t};\n\tenum CraneStatus {\n\t\tNONE = 0,\n\t\tACTIVATED = 1,\n\t\tDEACTIVATED = 2\n\t};\n\tCBuilding *m_pCraneEntity;\n\tCObject *m_pHook;\n\tfloat m_fPickupX1;\n\tfloat m_fPickupX2;\n\tfloat m_fPickupY1;\n\tfloat m_fPickupY2;\n\tCVector m_vecDropoffTarget;\n\tfloat m_fDropoffHeading;\n\tfloat m_fPickupAngle;\n\tfloat m_fDropoffAngle;\n\tfloat m_fPickupDistance;\n\tfloat m_fDropoffDistance;\n\tfloat m_fPickupHeight;\n\tfloat m_fDropoffHeight;\n\tfloat m_fHookAngle;\n\tfloat m_fHookOffset;\n\tfloat m_fHookHeight;\n\tCVector m_vecHookInitPos;\n\tCVector m_vecHookCurPos;\n\tCVector2D m_vecHookVelocity;\n\tCVehicle *m_pVehiclePickedUp;\n\tuint32 m_nTimeForNextCheck;\n\tuint8 m_nCraneStatus;\n\tuint8 m_nCraneState;\n\tuint8 m_nVehiclesCollected;\n\tbool m_bIsCrusher;\n\tbool m_bIsMilitaryCrane;\n\tbool m_bWasMilitaryCrane;\n\tbool m_bIsTop;\n\n\tvoid Init(void) { memset(this, 0, sizeof(*this)); }\n\tvoid Update(void);\n\tbool RotateCarriedCarProperly(void);\n\tvoid FindCarInSectorList(CPtrList* pList);\n\tbool DoesCranePickUpThisCarType(uint32 mi);\n\tbool GoTowardsTarget(float fAngleToTarget, float fDistanceToTarget, float fTargetHeight, float fSpeedMultiplier = 1.0f);\n\tbool GoTowardsHeightTarget(float fTargetHeight, float fSpeedMultiplier = 1.0f);\n\tvoid FindParametersForTarget(float X, float Y, float Z, float* pAngle, float* pDistance, float* pHeight);\n\tvoid CalcHookCoordinates(float* pX, float* pY, float* pZ);\n\tvoid SetHookMatrix(void);\n\n\tfloat GetHeightToPickup() { return 4.0f + m_fPickupHeight + (m_bIsCrusher ? 4.5f : 0.0f); };\n\tfloat GetHeightToDropoff() { return m_bIsCrusher ? (2.0f + m_fDropoffHeight + 3.0f) : (2.0f + m_fDropoffHeight); }\n\tfloat GetHeightToPickupHeight() { return m_fPickupHeight + (m_bIsCrusher ? 7.0f : 4.0f); }\n\tfloat GetHeightToDropoffHeight() { return m_fDropoffHeight + (m_bIsCrusher ? 7.0f : 2.0f); }\n};\n\nVALIDATE_SIZE(CCrane, 128);\n\nclass CCranes\n{\npublic:\n\tstatic void InitCranes(void);\n\tstatic void AddThisOneCrane(CEntity* pCraneEntity);\n\tstatic void ActivateCrane(float fInfX, float fSupX, float fInfY, float fSupY, float fDropOffX, float fDropOffY, float fDropOffZ, float fHeading, bool bIsCrusher, bool bIsMilitary, float fPosX, float fPosY);\n\tstatic void DeActivateCrane(float fX, float fY);\n\tstatic bool IsThisCarPickedUp(float fX, float fY, CVehicle* pVehicle);\n\tstatic void UpdateCranes(void);\n\tstatic bool DoesMilitaryCraneHaveThisOneAlready(uint32 mi);\n\tstatic void RegisterCarForMilitaryCrane(uint32 mi);\n\tstatic bool HaveAllCarsBeenCollectedByMilitaryCrane(void);\n\tstatic bool IsThisCarBeingCarriedByAnyCrane(CVehicle* pVehicle);\n\tstatic bool IsThisCarBeingTargettedByAnyCrane(CVehicle* pVehicle);\n\tstatic void Save(uint8* buf, uint32* size);\n\tstatic void Load(uint8* buf, uint32 size); // out of class in III PC and later because of SecuROM\n\n\tstatic uint32 CarsCollectedMilitaryCrane;\n\tstatic int32 NumCranes;\n\tstatic CCrane aCranes[NUM_CRANES];\n};\n"
  },
  {
    "path": "src/vehicles/DamageManager.cpp",
    "content": "#include \"common.h\"\n\n#include \"General.h\"\n#include \"Vehicle.h\"\n#include \"DamageManager.h\"\n\n\nfloat G_aComponentDamage[] = { 2.5f, 1.25f, 3.2f, 1.4f, 2.5f, 2.8f, 0.5f };\n\nCDamageManager::CDamageManager(void)\n{\n\tResetDamageStatus();\n\tm_fWheelDamageEffect = 0.5f;\n\tfield_18 = 1;\n}\n\nvoid\nCDamageManager::ResetDamageStatus(void)\n{\n\tint i;\n\tm_fWheelDamageEffect = 0.0f;\n\tm_engineStatus = 0;\n\tfor(i = 0; i < ARRAY_SIZE(m_wheelStatus); i++) m_wheelStatus[i] = 0;\n\tfor(i = 0; i < ARRAY_SIZE(m_doorStatus); i++) m_doorStatus[i] = 0;\n\tm_lightStatus = 0;\n\tm_panelStatus = 0;\n}\n\nvoid\nCDamageManager::FuckCarCompletely(void)\n{\n\tint i;\n\n\tm_wheelStatus[0] = WHEEL_STATUS_MISSING;\n\t// wheels 1-3 not reset?\n\n\tfor(i = 0; i < ARRAY_SIZE(m_doorStatus); i++)\n\t\tm_doorStatus[i] = DOOR_STATUS_MISSING;\n\n\tfor(i = 0; i < 3; i++){\n#ifdef FIX_BUGS\n\t\tProgressPanelDamage(VEHBUMPER_FRONT);\n\t\tProgressPanelDamage(VEHBUMPER_REAR);\n#else\n\t\t// this can't be right\n\t\tProgressPanelDamage(COMPONENT_BUMPER_FRONT);\n\t\tProgressPanelDamage(COMPONENT_BUMPER_REAR);\n#endif\n\t}\n\t// Why set to no damage?\n#ifndef FIX_BUGS\n\tm_lightStatus = 0;\n\tm_panelStatus = 0;\n#endif\n\tSetEngineStatus(250);\n}\n\nbool\nCDamageManager::ApplyDamage(tComponent component, float damage, float unused)\n{\n\ttComponentGroup group;\n\tuint8 subComp;\n\n\tGetComponentGroup(component, &group, &subComp);\n\tdamage *= G_aComponentDamage[group];\n\tif(component == COMPONENT_PANEL_WINDSCREEN)\n\t\tdamage *= 0.6f;\n\tif(damage > 150.0f){\n\t\tswitch(group){\n\t\tcase COMPGROUP_WHEEL:\n\t\t\tProgressWheelDamage(subComp);\n\t\t\tbreak;\n\t\tcase COMPGROUP_DOOR:\n\t\tcase COMPGROUP_BOOT:\n\t\t\tProgressDoorDamage(subComp);\n\t\t\tbreak;\n\t\tcase COMPGROUP_BONNET:\n\t\t\tif(damage > 220.0f)\n\t\t\t\tProgressEngineDamage();\n\t\t\tProgressDoorDamage(subComp);\n\t\t\tbreak;\n\t\tcase COMPGROUP_PANEL:\n\t\t\t// so windscreen is a light?\n\t\t\tSetLightStatus((eLights)subComp, 1);\n\t\t\t// fall through\n\t\tcase COMPGROUP_BUMPER:\n\t\t\tif(damage > 220.0f &&\n\t\t\t   (component == COMPONENT_PANEL_FRONT_LEFT ||\n\t\t\t    component == COMPONENT_PANEL_FRONT_RIGHT ||\n\t\t\t    component == COMPONENT_PANEL_WINDSCREEN))\n\t\t\t\tProgressEngineDamage();\n\t\t\tProgressPanelDamage(subComp);\n\t\t\tbreak;\n\t\tdefault: break;\n\t\t}\n\t\treturn true;\n\t}\n\treturn false;\n}\n\nbool\nCDamageManager::GetComponentGroup(tComponent component, tComponentGroup *componentGroup, uint8 *subComp)\n{\n\t*subComp = -2;\t// ??\n\n\t// This is done very strangely in the game, maybe an optimized switch?\n\tif(component >= COMPONENT_PANEL_FRONT_LEFT){\n\t\tif(component >= COMPONENT_BUMPER_FRONT)\n\t\t\t*componentGroup = COMPGROUP_BUMPER;\n\t\telse\n\t\t\t*componentGroup = COMPGROUP_PANEL;\n\t\t*subComp = component - COMPONENT_PANEL_FRONT_LEFT;\n\t\treturn true;\n\t}else if(component >= COMPONENT_DOOR_BONNET){\n\t\tif(component == COMPONENT_DOOR_BONNET)\n\t\t\t*componentGroup = COMPGROUP_BONNET;\n\t\telse if(component == COMPONENT_DOOR_BOOT)\n\t\t\t*componentGroup = COMPGROUP_BOOT;\n\t\telse\n\t\t\t*componentGroup = COMPGROUP_DOOR;\n\t\t*subComp = component - COMPONENT_DOOR_BONNET;\n\t\treturn true;\n\t}else if(component >= COMPONENT_WHEEL_FRONT_LEFT){\n\t\t*componentGroup = COMPGROUP_WHEEL;\n\t\t*subComp = component - COMPONENT_WHEEL_FRONT_LEFT;\n\t\treturn true;\n\t}else if(component >= COMPONENT_DEFAULT){\n\t\t*componentGroup = COMPGROUP_DEFAULT;\n\t\t*subComp = COMPONENT_DEFAULT;\n\t\treturn true;\n\t}else\n\t\treturn false;\n}\n\nvoid\nCDamageManager::SetDoorStatus(int32 door, uint32 status)\n{\n\tm_doorStatus[door] = status;\n}\n\nint32\nCDamageManager::GetDoorStatus(int32 door)\n{\n\treturn m_doorStatus[door];\n}\n\nbool\nCDamageManager::ProgressDoorDamage(uint8 door)\n{\n\tint status = GetDoorStatus(door);\n\tif(status == PANEL_STATUS_MISSING)\n\t\treturn false;\n\tSetDoorStatus(door, status+1);\n\treturn true;\n}\n\nvoid\nCDamageManager::SetPanelStatus(int32 panel, uint32 status)\n{\n\tm_panelStatus = dpb(status, panel*4, 4, m_panelStatus);\n}\n\nint32\nCDamageManager::GetPanelStatus(int32 panel)\n{\n\treturn ldb(panel*4, 4, m_panelStatus);\n}\n\nbool\nCDamageManager::ProgressPanelDamage(uint8 panel)\n{\n\tint status = GetPanelStatus(panel);\n\tif(status == DOOR_STATUS_MISSING)\n\t\treturn false;\n\tSetPanelStatus(panel, status+1);\n\treturn true;\n}\n\nvoid\nCDamageManager::SetLightStatus(eLights light, uint32 status)\n{\n\tm_lightStatus = dpb(status, light*2, 2, m_lightStatus);\n}\n\nint32\nCDamageManager::GetLightStatus(eLights light)\n{\n\treturn ldb(light*2, 2, m_lightStatus);\n}\n\nvoid\nCDamageManager::SetWheelStatus(int32 wheel, uint32 status)\n{\n\tm_wheelStatus[wheel] = status;\n}\n\nint32\nCDamageManager::GetWheelStatus(int32 wheel)\n{\n\treturn m_wheelStatus[wheel];\n}\n\nbool\nCDamageManager::ProgressWheelDamage(uint8 wheel)\n{\n\tint status = GetWheelStatus(wheel);\n\tif(status == WHEEL_STATUS_MISSING)\n\t\treturn false;\n\tSetWheelStatus(wheel, status+1);\n\treturn true;\n}\n\nvoid\nCDamageManager::SetEngineStatus(uint32 status)\n{\n\tif(status > 250)\n\t\tm_engineStatus = 250;\n\telse\n\t\tm_engineStatus = status;\n}\n\nint32\nCDamageManager::GetEngineStatus(void)\n{\n\treturn m_engineStatus;\n}\n\nbool\nCDamageManager::ProgressEngineDamage(void)\n{\n\t// gone in VC\n\treturn false;\n}\n"
  },
  {
    "path": "src/vehicles/DamageManager.h",
    "content": "#pragma once\n\n#include \"common.h\"\n\n// TODO: move some of this into Vehicle.h\n\nenum eEngineStatus\n{\n\tENGINE_STATUS_STEAM1 = 100,\n\tENGINE_STATUS_STEAM2 = 150,\n\tENGINE_STATUS_SMOKE = 200,\n\tENGINE_STATUS_ON_FIRE = 225\n};\n\nenum eDoorStatus\n{\n\tDOOR_STATUS_OK,\n\tDOOR_STATUS_SMASHED,\n\tDOOR_STATUS_SWINGING,\n\tDOOR_STATUS_MISSING\n};\n\nenum ePanelStatus\n{\n\tPANEL_STATUS_OK,\n\tPANEL_STATUS_SMASHED1,\n\tPANEL_STATUS_SMASHED2,\n\tPANEL_STATUS_MISSING,\n};\n\nenum eWheelStatus\n{\n\tWHEEL_STATUS_OK,\n\tWHEEL_STATUS_BURST,\n\tWHEEL_STATUS_MISSING\n};\n\nenum eLightStatus\n{\n\tLIGHT_STATUS_OK,\n\tLIGHT_STATUS_BROKEN\n};\n\nenum tComponent\n{\n\tCOMPONENT_DEFAULT,\n\tCOMPONENT_WHEEL_FRONT_LEFT,\n\tCOMPONENT_WHEEL_FRONT_RIGHT,\n\tCOMPONENT_WHEEL_REAR_LEFT,\n\tCOMPONENT_WHEEL_REAR_RIGHT,\n\tCOMPONENT_DOOR_BONNET,\n\tCOMPONENT_DOOR_BOOT,\n\tCOMPONENT_DOOR_FRONT_LEFT,\n\tCOMPONENT_DOOR_FRONT_RIGHT,\n\tCOMPONENT_DOOR_REAR_LEFT,\n\tCOMPONENT_DOOR_REAR_RIGHT,\n\tCOMPONENT_PANEL_FRONT_LEFT,\n\tCOMPONENT_PANEL_FRONT_RIGHT,\n\tCOMPONENT_PANEL_REAR_LEFT,\n\tCOMPONENT_PANEL_REAR_RIGHT,\n\tCOMPONENT_PANEL_WINDSCREEN,\n\tCOMPONENT_BUMPER_FRONT,\n\tCOMPONENT_BUMPER_REAR,\n};\n\nenum tComponentGroup\n{\n\tCOMPGROUP_BUMPER,\n\tCOMPGROUP_WHEEL,\n\tCOMPGROUP_DOOR,\n\tCOMPGROUP_BONNET,\n\tCOMPGROUP_BOOT,\n\tCOMPGROUP_PANEL,\n\tCOMPGROUP_DEFAULT,\n};\n\nenum eLights;\n\nclass CDamageManager\n{\npublic:\n\n\tfloat m_fWheelDamageEffect;\n\tuint8 m_engineStatus;\n\tuint8 m_wheelStatus[4];\n\tuint8 m_doorStatus[6];\n\tuint32 m_lightStatus;\n\tuint32 m_panelStatus;\n\tuint8 field_18;\n\n\tCDamageManager(void);\n\n\tvoid ResetDamageStatus(void);\n\tvoid FuckCarCompletely(void);\n\tbool ApplyDamage(tComponent component, float damage, float unused);\n\tbool GetComponentGroup(tComponent component, tComponentGroup *componentGroup, uint8 *foo);\n\n\tvoid SetDoorStatus(int32 door, uint32 status);\n\tint32 GetDoorStatus(int32 door);\n\tbool ProgressDoorDamage(uint8 door);\n\tvoid SetPanelStatus(int32 panel, uint32 status);\n\tint32 GetPanelStatus(int32 panel);\n\tbool ProgressPanelDamage(uint8 panel);\n\t// needed for CReplay\n\tstatic int32 GetPanelStatus(uint32 panelstatus, int32 panel) { return ldb(panel*4, 4, panelstatus); }\n\tvoid SetLightStatus(eLights light, uint32 status);\n\tint32 GetLightStatus(eLights light);\n\tvoid SetWheelStatus(int32 wheel, uint32 status);\n\tint32 GetWheelStatus(int32 wheel);\n\tbool ProgressWheelDamage(uint8 wheel);\n\tvoid SetEngineStatus(uint32 status);\n\tint32 GetEngineStatus(void);\n\tbool ProgressEngineDamage(void);\n};\nVALIDATE_SIZE(CDamageManager, 0x1C);\n"
  },
  {
    "path": "src/vehicles/Door.cpp",
    "content": "#include \"common.h\"\n\n#include \"Vehicle.h\"\n#include \"Door.h\"\n\nCDoor::CDoor(void)\n{\n\tmemset(this, 0, sizeof(*this));\n}\n\nvoid\nCDoor::Open(float ratio)\n{\n\tfloat open;\n\n\tm_fPrevAngle = m_fAngle;\n\topen = RetAngleWhenOpen();\n\tif(ratio < 1.0f){\n\t\tm_fAngle = open*ratio;\n\t\tif(m_fAngle == 0.0f)\n\t\t\tm_fAngVel = 0.0f;\n\t}else{\n\t\tm_nDoorState = DOORST_OPEN;\n\t\tm_fAngle = open;\n\t}\n}\n\nvoid\nCDoor::Process(CVehicle *vehicle)\n{\n\tstatic CVector vecOffset(1.0f, 0.0f, 0.0f);\n\tCVector speed = vehicle->GetSpeed(vecOffset);\n\tCVector vecSpeedDiff = speed - m_vecSpeed;\n\tvecSpeedDiff = Multiply3x3(vecSpeedDiff, vehicle->GetMatrix());\n\n\t// air resistance\n\tfloat fSpeedDiff = 0.0f;\t// uninitialized in game\n\tswitch(m_nAxis){\n\tcase 0:\t// x-axis\n\t\tif(m_nDirn)\n\t\t\tfSpeedDiff = vecSpeedDiff.y + vecSpeedDiff.z;\n\t\telse\n\t\t\tfSpeedDiff = -(vecSpeedDiff.y + vecSpeedDiff.z);\n\t\tbreak;\n\n\t// we don't support y axis apparently?\n\n\tcase 2:\t// z-axis\n\t\tif(m_nDirn)\n\t\t\tfSpeedDiff = -(vecSpeedDiff.y + vecSpeedDiff.x);\n\t\telse\n\t\t\tfSpeedDiff = vecSpeedDiff.y - vecSpeedDiff.x;\n\t\tbreak;\n\t}\n\tfSpeedDiff = clamp(fSpeedDiff, -0.2f, 0.2f);\n\tif(Abs(fSpeedDiff) > 0.002f)\n\t\tm_fAngVel += fSpeedDiff;\n\tm_fAngVel *= 0.945f;\n\tm_fAngVel = clamp(m_fAngVel, -0.3f, 0.3f);\n\n\tm_fAngle += m_fAngVel;\n\tm_nDoorState = DOORST_SWINGING;\n\tif(m_fAngle > m_fMaxAngle){\n\t\tm_fAngle = m_fMaxAngle;\n\t\tm_fAngVel *= -0.8f;\n\t\tm_nDoorState = DOORST_OPEN;\n\t}\n\tif(m_fAngle < m_fMinAngle){\n\t\tm_fAngle = m_fMinAngle;\n\t\tm_fAngVel *= -0.8f;\n\t\tm_nDoorState = DOORST_CLOSED;\n\t}\n\tm_vecSpeed = speed;\n}\n\nfloat\nCDoor::RetAngleWhenClosed(void)\n{\n\tif(Abs(m_fMaxAngle) < Abs(m_fMinAngle))\n\t\treturn m_fMaxAngle;\n\telse\n\t\treturn m_fMinAngle;\n}\n\nfloat\nCDoor::RetAngleWhenOpen(void)\n{\n\tif(Abs(m_fMaxAngle) < Abs(m_fMinAngle))\n\t\treturn m_fMinAngle;\n\telse\n\t\treturn m_fMaxAngle;\n}\n\nfloat\nCDoor::GetAngleOpenRatio(void)\n{\n\tfloat open = RetAngleWhenOpen();\n\tif(open == 0.0f)\n\t\treturn 0.0f;\n\treturn m_fAngle/open;\n}\n\nbool\nCDoor::IsFullyOpen(void)\n{\n\t// why -0.5? that's around 28 deg less than fully open\n\tif(Abs(m_fAngle) < Abs(RetAngleWhenOpen()) - 0.5f)\n\t\treturn false;\n\treturn true;\n}\n\nbool\nCDoor::IsClosed(void)\n{\n\treturn m_fAngle == RetAngleWhenClosed();\n}\n\n\nCTrainDoor::CTrainDoor(void)\n{\n\tmemset(this, 0, sizeof(*this));\n}\n\nvoid\nCTrainDoor::Open(float ratio)\n{\n\tfloat open;\n\n\tm_fPrevPosn = m_fPosn;\n\topen = RetTranslationWhenOpen();\n\tif(ratio < 1.0f){\n\t\tm_fPosn = open*ratio;\n\t}else{\n\t\tm_nDoorState = DOORST_OPEN;\n\t\tm_fPosn = open;\n\t}\n}\n\nfloat\nCTrainDoor::RetTranslationWhenClosed(void)\n{\n\tif(Abs(m_fClosedPosn) < Abs(m_fOpenPosn))\n\t\treturn m_fClosedPosn;\n\telse\n\t\treturn m_fOpenPosn;\n}\n\nfloat\nCTrainDoor::RetTranslationWhenOpen(void)\n{\n\tif(Abs(m_fClosedPosn) < Abs(m_fOpenPosn))\n\t\treturn m_fOpenPosn;\n\telse\n\t\treturn m_fClosedPosn;\n}\n\nbool\nCTrainDoor::IsFullyOpen(void)\n{\n\t// 0.5f again...\n\tif(Abs(m_fPosn) < Abs(RetTranslationWhenOpen()) - 0.5f)\n\t\treturn false;\n\treturn true;\n}\n\nbool\nCTrainDoor::IsClosed(void)\n{\n\treturn m_fPosn == RetTranslationWhenClosed();\n}\n"
  },
  {
    "path": "src/vehicles/Door.h",
    "content": "#pragma once\n\nclass CVehicle;\n\nenum eDoorState\n{\n\tDOORST_SWINGING,\n\t// actually wrong though,\n\t// OPEN is really MAX_ANGLE and CLOSED is MIN_ANGLE\n\tDOORST_OPEN,\n\tDOORST_CLOSED\n};\n\nclass CDoor\n{\npublic:\n\tfloat m_fMaxAngle;\n\tfloat m_fMinAngle;\n\t// direction of rotation for air resistance\n\tint8 m_nDirn;\n\t// axis in which this door rotates\n\tint8 m_nAxis;\n\tint8 m_nDoorState;\n\tfloat m_fAngle;\n\tfloat m_fPrevAngle;\n\tfloat m_fAngVel;\n\tCVector m_vecSpeed;\n\n\tCDoor(void);\n\tvoid Init(float minAngle, float maxAngle, int8 dir, int8 axis) {\n\t\tm_fMinAngle = minAngle;\n\t\tm_fMaxAngle = maxAngle;\n\t\tm_nDirn = dir;\n\t\tm_nAxis = axis;\n\t}\n\tvoid Open(float ratio);\n\tvoid Process(CVehicle *veh);\n\tfloat RetAngleWhenClosed(void);\t// dead\n\tfloat RetAngleWhenOpen(void);\n\tfloat GetAngleOpenRatio(void);\n\tbool IsFullyOpen(void);\n\tbool IsClosed(void);\t// dead\n};\n\nclass CTrainDoor\n{\npublic:\n\tfloat m_fClosedPosn;\n\tfloat m_fOpenPosn;\n\tint8 m_nDirn;\n\tint8 m_nDoorState;\t// same enum as above?\n\tint8 m_nAxis;\n\tfloat m_fPosn;\n\tfloat m_fPrevPosn;\n\tint field_14;\t// unused?\n\n\tCTrainDoor(void);\n\tvoid Init(float open, float closed, int8 dir, int8 axis) {\n\t\tm_fOpenPosn = open;\n\t\tm_fClosedPosn = closed;\n\t\tm_nDirn = dir;\n\t\tm_nAxis = axis;\n\t}\n\tbool IsClosed(void);\n\tbool IsFullyOpen(void);\n\tfloat RetTranslationWhenClosed(void);\n\tfloat RetTranslationWhenOpen(void);\n\tvoid Open(float ratio);\n};\n"
  },
  {
    "path": "src/vehicles/Floater.cpp",
    "content": "#include \"common.h\"\n\n#include \"Timer.h\"\n#include \"WaterLevel.h\"\n#include \"ModelIndices.h\"\n#include \"Physical.h\"\n#include \"Vehicle.h\"\n#include \"Floater.h\"\n\ncBuoyancy mod_Buoyancy;\n\nfloat fVolMultiplier = 1.0f;\n// amount of boat volume in bounding box\n// 1.0-volume is the empty space in the bbox\nfloat fBoatVolumeDistribution[9] = {\n\t// rear\n\t0.75f, 0.9f, 0.75f,\n\t0.95f, 1.0f, 0.95f,\n\t0.4f, 0.7f, 0.4f\n\t// bow\n};\nfloat fBoatVolumeDistributionCat[9] = {\n\t0.9f, 0.3f, 0.9f,\n\t1.0f, 0.5f, 1.0f,\n\t0.95f, 0.4f, 0.95f\n};\nfloat fBoatVolumeDistributionSail[9] = {\n\t0.55f, 0.95f, 0.55f,\n\t0.75f, 1.1f, 0.75f,\n\t0.3f, 0.8f, 0.3f\n};\nfloat fBoatVolumeDistributionDinghy[9] = {\n\t0.65f, 0.85f, 0.65f,\n\t0.85f, 1.1f, 0.85f,\n\t0.65f, 0.95f, 0.65f\n};\nfloat fBoatVolumeDistributionSpeed[9] = {\n\t0.7f, 0.9f, 0.7f,\n\t0.95f, 1.0f, 0.95f,\n\t0.6f, 0.7f, 0.6f\n};\n\nbool\ncBuoyancy::ProcessBuoyancy(CPhysical *phys, float buoyancy, CVector *point, CVector *impulse)\n{\n\tm_numSteps = 2.0f;\n\n\tif(!CWaterLevel::GetWaterLevel(phys->GetPosition(), &m_waterlevel, phys->bTouchingWater))\n\t\treturn false;\n\tm_matrix = phys->GetMatrix();\n\n\tPreCalcSetup(phys, buoyancy);\n\tSimpleCalcBuoyancy();\n\tfloat f = CalcBuoyancyForce(phys, point, impulse);\n\tif(m_isBoat)\n\t\treturn true;\n\treturn f != 0.0f;\n}\n\nbool\ncBuoyancy::ProcessBuoyancyBoat(CVehicle *veh, float buoyancy, CVector *point, CVector *impulse, bool bNoTurnForce)\n{\n\tm_numSteps = 2.0f;\n\n\tif(!CWaterLevel::GetWaterLevel(veh->GetPosition(), &m_waterlevel, veh->bTouchingWater))\n\t\treturn false;\n\tm_matrix = veh->GetMatrix();\n\tPreCalcSetup(veh, buoyancy);\n\n\n\tfloat x, y;\n\tint ix, i;\n\ttWaterLevel waterPosition;\n\tCVector waterNormal;\n\n\t// Floater is divided into 3x3 parts. Process and sum each of them\n\tfloat volDiv = 1.0f/((m_dimMax.z - m_dimMin.z)*sq(m_numSteps+1.0f));\n\tix = 0;\n\tfor(x = m_dimMin.x; x <= m_dimMax.x; x += m_step.x){\n\t\ti = ix;\n\t\tfor(y = m_dimMin.y; y <= m_dimMax.y; y += m_step.y){\n\t\t\tCVector waterLevel(x, y, 0.0f);\n\t\t\tFindWaterLevelNorm(m_positionZ, &waterLevel, &waterPosition, &waterNormal);\n\t\t\tswitch(veh->GetModelIndex()){\n\t\t\tcase MI_RIO:\n\t\t\t\tfVolMultiplier = fBoatVolumeDistributionCat[i];\n\t\t\t\tbreak;\n\t\t\tcase MI_SQUALO:\n\t\t\tcase MI_SPEEDER:\n\t\t\tcase MI_JETMAX:\n\t\t\t\tfVolMultiplier = fBoatVolumeDistributionSpeed[i];\n\t\t\t\tbreak;\n\t\t\tcase MI_COASTG:\n\t\t\tcase MI_DINGHY:\n\t\t\t\tfVolMultiplier = fBoatVolumeDistributionDinghy[i];\n\t\t\t\tbreak;\n\t\t\tcase MI_MARQUIS:\n\t\t\t\tfVolMultiplier = fBoatVolumeDistributionSail[i];\n\t\t\t\tbreak;\n\t\t\tcase MI_PREDATOR:\n\t\t\tcase MI_SKIMMER:\n\t\t\tcase MI_REEFER:\n\t\t\tcase MI_TROPIC:\n\t\t\tdefault:\n\t\t\t\tfVolMultiplier = fBoatVolumeDistribution[i];\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif(waterPosition != FLOATER_ABOVE_WATER){\n\t\t\t\tfloat volume = SimpleSumBuoyancyData(waterLevel, waterPosition);\n\t\t\t\tfloat upImpulse = volume * volDiv * buoyancy * CTimer::GetTimeStep();\n\t\t\t\tCVector speed = veh->GetSpeed(Multiply3x3(veh->GetMatrix(), CVector(x, y, 0.0f)));\n\t\t\t\tfloat damp = 1.0f - DotProduct(speed, waterNormal)*veh->pHandling->fSuspensionDampingLevel;\n\t\t\t\tfloat finalImpulse = upImpulse*Max(damp, 0.0f);\n\t\t\t\timpulse->z += finalImpulse;\n\t\t\t\tif(!bNoTurnForce)\n\t\t\t\t\tveh->ApplyTurnForce(finalImpulse*waterNormal, Multiply3x3(m_matrix, waterLevel));\n\t\t\t}\n\t\t\ti += 3;\n\t\t}\n\t\tix++;\n\t}\n\n\tm_volumeUnderWater *= volDiv;\n\n\t*point = Multiply3x3(m_matrix, m_impulsePoint);\n\treturn m_isBoat || m_haveVolume;\n\n}\n\nvoid\ncBuoyancy::PreCalcSetup(CPhysical *phys, float buoyancy)\n{\n\tCColModel *colModel;\n\n\tm_isBoat = phys->IsVehicle() && ((CVehicle*)phys)->IsBoat();\n\tcolModel = phys->GetColModel();\n\tm_dimMin = colModel->boundingBox.min;\n\tm_dimMax = colModel->boundingBox.max;\n\n\tif(m_isBoat){\n\t\tswitch(phys->GetModelIndex()){\n\t\tcase MI_PREDATOR:\n\t\tdefault:\n\t\t\tm_dimMax.y *= 1.05f;\n\t\t\tm_dimMin.y *= 0.9f;\n\t\t\tbreak;\n\t\tcase MI_SPEEDER:\n\t\t\tm_dimMax.y *= 1.25f;\n\t\t\tm_dimMin.y *= 0.83f;\n\t\t\tbreak;\n\t\tcase MI_REEFER:\n\t\t\tm_dimMin.y *= 0.9f;\n\t\t\tbreak;\n\t\tcase MI_RIO:\n\t\t\tm_dimMax.y *= 0.9f;\n\t\t\tm_dimMin.y *= 0.9f;\n\t\t\tm_dimMax.z += 0.25f;\n\t\t\tm_dimMin.z -= 0.2f;\n\t\t\tbreak;\n\t\tcase MI_SQUALO:\n\t\t\tm_dimMax.y *= 0.9f;\n\t\t\tm_dimMin.y *= 0.9f;\n\t\t\tbreak;\n\t\tcase MI_TROPIC:\n\t\t\tm_dimMax.y *= 1.3f;\n\t\t\tm_dimMin.y *= 0.82f;\n\t\t\tm_dimMin.z -= 0.2f;\n\t\t\tbreak;\n\t\tcase MI_SKIMMER:\n\t\t\tm_dimMin.y = -m_dimMax.y;\n\t\t\tm_dimMax.y *= 1.2f;\n\t\t\tbreak;\n\t\tcase MI_COASTG:\n\t\t\tm_dimMax.y *= 1.1f;\n\t\t\tm_dimMin.y *= 0.9f;\n\t\t\tm_dimMin.z -= 0.3f;\n\t\t\tbreak;\n\t\tcase MI_DINGHY:\n\t\t\tm_dimMax.y *= 1.3f;\n\t\t\tm_dimMin.y *= 0.9f;\n\t\t\tm_dimMin.z -= 0.2f;\n\t\t\tbreak;\n\t\tcase MI_MARQUIS:\n\t\t\tm_dimMax.y *= 1.3f;\n\t\t\tm_dimMin.y *= 0.9f;\n\t\t\tbreak;\n\t\tcase MI_JETMAX:\n\t\t\tm_dimMin.y *= 0.9f;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tm_step = (m_dimMax - m_dimMin)/m_numSteps;\n\n\tif(m_step.z > m_step.x && m_step.z > m_step.y){\n\t\tm_stepRatio.x = m_step.x/m_step.z;\n\t\tm_stepRatio.y = m_step.y/m_step.z;\n\t\tm_stepRatio.z = 1.0f;\n\t}else if(m_step.y > m_step.x && m_step.y > m_step.z){\n\t\tm_stepRatio.x = m_step.x/m_step.y;\n\t\tm_stepRatio.y = 1.0f;\n\t\tm_stepRatio.z = m_step.z/m_step.y;\n\t}else{\n\t\tm_stepRatio.x = 1.0f;\n\t\tm_stepRatio.y = m_step.y/m_step.x;\n\t\tm_stepRatio.z = m_step.z/m_step.x;\n\t}\n\n\tm_haveVolume = false;\n\tm_numPartialVolumes = 1.0f;\n\tm_volumeUnderWater = 0.0f;\n\tm_impulsePoint = CVector(0.0f, 0.0f, 0.0f);\n\tm_position = phys->GetPosition();\n\tm_positionZ = CVector(0.0f, 0.0f, m_position.z);\n\tm_buoyancy = buoyancy;\n\tm_waterlevel += m_waterLevelInc;\n}\n\nvoid\ncBuoyancy::SimpleCalcBuoyancy(void)\n{\n\tfloat x, y;\n\ttWaterLevel waterPosition;\n\n\t// Floater is divided into 3x3 parts. Process and sum each of them\n\tfor(x = m_dimMin.x; x <= m_dimMax.x; x += m_step.x){\n\t\tfor(y = m_dimMin.y; y <= m_dimMax.y; y += m_step.y){\n\t\t\tCVector waterLevel(x, y, 0.0f);\n\t\t\tFindWaterLevel(m_positionZ, &waterLevel, &waterPosition);\n\t\t\tfVolMultiplier = 1.0f;\n\t\t\tif(waterPosition != FLOATER_ABOVE_WATER)\n\t\t\t\tSimpleSumBuoyancyData(waterLevel, waterPosition);\n\t\t}\n\t}\n\n\tm_volumeUnderWater /= (m_dimMax.z - m_dimMin.z)*sq(m_numSteps+1.0f);\n}\n\nfloat\ncBuoyancy::SimpleSumBuoyancyData(CVector &waterLevel, tWaterLevel waterPosition)\n{\n\tstatic float fThisVolume;\n\tstatic CVector AverageOfWaterLevel;\n\tstatic float fFraction;\n\tstatic float fRemainingSlice;\n\n\tfloat submerged = Abs(waterLevel.z - m_dimMin.z);\n\t// subtract empty space from submerged volume\n\tfThisVolume = submerged - (1.0f - fVolMultiplier);\n\tif(fThisVolume < 0.0f)\n\t\treturn 0.0f;\n\n\tif(m_isBoat){\n\t\tfThisVolume *= fVolMultiplier;\n\t\tfThisVolume = sq(fThisVolume);\n\t}\n\n\tm_volumeUnderWater += fThisVolume;\n\n\tAverageOfWaterLevel.x = waterLevel.x * m_stepRatio.x;\n\tAverageOfWaterLevel.y = waterLevel.y * m_stepRatio.y;\n\tAverageOfWaterLevel.z = (waterLevel.z+m_dimMin.z)/2.0f * m_stepRatio.z;\n\n\tif(m_flipAverage)\n\t\tAverageOfWaterLevel = -AverageOfWaterLevel;\n\n\tfFraction = 1.0f/m_numPartialVolumes;\n\tfRemainingSlice = 1.0f - fFraction;\n\tm_impulsePoint = m_impulsePoint*fRemainingSlice + AverageOfWaterLevel*fThisVolume*fFraction;\n\tm_numPartialVolumes += 1.0f;\n\tm_haveVolume = true;\n\treturn fThisVolume;\n}\n\nvoid\ncBuoyancy::FindWaterLevel(const CVector &zpos, CVector *waterLevel, tWaterLevel *waterPosition)\n{\n\t*waterPosition = FLOATER_IN_WATER;\n\t// waterLevel is a local x,y point\n\t// m_position is the global position of our floater\n\t// zpos is the global z coordinate of our floater\n\tCVector xWaterLevel = Multiply3x3(m_matrix, *waterLevel);\n\tCWaterLevel::GetWaterLevel(xWaterLevel.x + m_position.x, xWaterLevel.y + m_position.y, m_position.z,\n\t\t&waterLevel->z, true);\n\twaterLevel->z -= xWaterLevel.z + zpos.z;\t// make local\n\tif(waterLevel->z > m_dimMax.z){\n\t\twaterLevel->z = m_dimMax.z;\n\t\t*waterPosition = FLOATER_UNDER_WATER;\n\t}else if(waterLevel->z < m_dimMin.z){\n\t\twaterLevel->z = m_dimMin.z;\n\t\t*waterPosition = FLOATER_ABOVE_WATER;\n\t}\n}\n\n// Same as above but also get normal\nvoid\ncBuoyancy::FindWaterLevelNorm(const CVector &zpos, CVector *waterLevel, tWaterLevel *waterPosition, CVector *normal)\n{\n\t*waterPosition = FLOATER_IN_WATER;\n\tCVector xWaterLevel = Multiply3x3(m_matrix, *waterLevel);\n\tCWaterLevel::GetWaterLevel(xWaterLevel.x + m_position.x, xWaterLevel.y + m_position.y, m_position.z,\n\t\t&waterLevel->z, true);\n\twaterLevel->z -= xWaterLevel.z + zpos.z;\t// make local\n\tif(waterLevel->z >= m_dimMin.z)\n\t\t*normal = CWaterLevel::GetWaterNormal(xWaterLevel.x + m_position.x, xWaterLevel.y + m_position.y);\n\tif(waterLevel->z > m_dimMax.z){\n\t\twaterLevel->z = m_dimMax.z;\n\t\t*waterPosition = FLOATER_UNDER_WATER;\n\t}else if(waterLevel->z < m_dimMin.z){\n\t\twaterLevel->z = m_dimMin.z;\n\t\t*waterPosition = FLOATER_ABOVE_WATER;\n\t}\n}\n\nbool\ncBuoyancy::CalcBuoyancyForce(CPhysical *phys, CVector *point, CVector *impulse)\n{\n\tif(!m_haveVolume)\n\t\treturn false;\n\n\t*point = Multiply3x3(m_matrix, m_impulsePoint);\n\t*impulse = CVector(0.0f, 0.0f, m_volumeUnderWater*m_buoyancy*CTimer::GetTimeStep());\n\treturn true;\n}\n"
  },
  {
    "path": "src/vehicles/Floater.h",
    "content": "#pragma once\n\nclass CPhysical;\n\nenum tWaterLevel\n{\n\tFLOATER_ABOVE_WATER,\n\tFLOATER_IN_WATER,\n\tFLOATER_UNDER_WATER,\n};\n\nclass cBuoyancy\n{\npublic:\n\tCVector m_position;\n\tCMatrix m_matrix;\n\tint m_field_54;\n\tCVector m_positionZ;\n\tfloat m_waterlevel;\n\tfloat m_waterLevelInc;\n\tfloat m_buoyancy;\n\tCVector m_dimMax;\n\tCVector m_dimMin;\n\tfloat m_numPartialVolumes;\n\tint m_field_8C;\n\tint m_field_90;\n\tint m_field_94;\n\tbool m_haveVolume;\n\tCVector m_step;\n\tCVector m_stepRatio;\n\tfloat m_numSteps;\n\tbool m_flipAverage;\n\tchar m_field_B9;\n\tbool m_isBoat;\n\tfloat m_volumeUnderWater;\n\tCVector m_impulsePoint;\n\n\tbool ProcessBuoyancy(CPhysical *phys, float buoyancy, CVector *point, CVector *impulse);\n\tbool ProcessBuoyancyBoat(CVehicle *phys, float buoyancy, CVector *point, CVector *impulse, bool bNoTurnForce);\n\tvoid PreCalcSetup(CPhysical *phys, float buoyancy);\n\tvoid SimpleCalcBuoyancy(void);\n\tfloat SimpleSumBuoyancyData(CVector &waterLevel, tWaterLevel waterPosition);\n\tvoid FindWaterLevel(const CVector &zpos, CVector *waterLevel, tWaterLevel *waterPosition);\n\tvoid FindWaterLevelNorm(const CVector &zpos, CVector *waterLevel, tWaterLevel *waterPosition, CVector *normal);\n\tbool CalcBuoyancyForce(CPhysical *phys, CVector *impulse, CVector *point);\n};\nextern cBuoyancy mod_Buoyancy;\n"
  },
  {
    "path": "src/vehicles/HandlingMgr.cpp",
    "content": "#include \"common.h\"\n\n#include \"main.h\"\n#include \"FileMgr.h\"\n#include \"Physical.h\"\n#include \"HandlingMgr.h\"\n\ncHandlingDataMgr mod_HandlingManager;\n\nconst char *HandlingFilename = \"HANDLING.CFG\";\n\nconst char VehicleNames[NUMHANDLINGS][14] = {\n\t\"LANDSTAL\",\n\t\"IDAHO\",\n\t\"STINGER\",\n\t\"LINERUN\",\n\t\"PEREN\",\n\t\"SENTINEL\",\n\t\"PATRIOT\",\n\t\"FIRETRUK\",\n\t\"TRASH\",\n\t\"STRETCH\",\n\t\"MANANA\",\n\t\"INFERNUS\",\n\t\"PONY\",\n\t\"MULE\",\n\t\"CHEETAH\",\n\t\"AMBULAN\",\n\t\"FBICAR\",\n\t\"MOONBEAM\",\n\t\"ESPERANT\",\n\t\"TAXI\",\n\t\"KURUMA\",\n\t\"BOBCAT\",\n\t\"MRWHOOP\",\n\t\"BFINJECT\",\n\t\"POLICE\",\n\t\"ENFORCER\",\n\t\"SECURICA\",\n\t\"BANSHEE\",\n\t\"BUS\",\n\t\"RHINO\",\n\t\"BARRACKS\",\n\t\"TRAIN\",\n\t\"HELI\",\n\t\"DODO\",\n\t\"COACH\",\n\t\"CABBIE\",\n\t\"STALLION\",\n\t\"RUMPO\",\n\t\"RCBANDIT\",\n\t\"MAFIA\",\n\t\"AIRTRAIN\",\n\t\"DEADDODO\",\n\t\"FLATBED\",\n\t\"YANKEE\",\n\t\"GOLFCART\",\n\t\"VOODOO\",\n\t\"WASHING\",\n\t\"CUBAN\",\n\t\"ROMERO\",\n\t\"PACKER\",\n\t\"ADMIRAL\",\n\t\"GANGBUR\",\n\t\"ZEBRA\",\n\t\"TOPFUN\",\n\t\"GLENDALE\",\n\t\"OCEANIC\",\n\t\"HERMES\",\n\t\"SABRE1\",\n\t\"SABRETUR\",\n\t\"PHEONIX\",\n\t\"WALTON\",\n\t\"REGINA\",\n\t\"COMET\",\n\t\"DELUXO\",\n\t\"BURRITO\",\n\t\"SPAND\",\n\t\"BAGGAGE\",\n\t\"KAUFMAN\",\n\t\"RANCHER\",\n\t\"FBIRANCH\",\n\t\"VIRGO\",\n\t\"GREENWOO\",\n\t\"HOTRING\",\n\t\"SANDKING\",\n\t\"BLISTAC\",\n\t\"BOXVILLE\",\n\t\"BENSON\",\n\t\"DESPERAD\",\n\t\"LOVEFIST\",\n\t\"BLOODRA\",\n\t\"BLOODRB\",\n\t\"BIKE\",\n\t\"MOPED\",\n\t\"DIRTBIKE\",\n\t\"ANGEL\",\n\t\"FREEWAY\",\n\t\"PREDATOR\",\n\t\"SPEEDER\",\n\t\"REEFER\",\n\t\"RIO\",\n\t\"SQUALO\",\n\t\"TROPIC\",\n\t\"COASTGRD\",\n\t\"DINGHY\",\n\t\"MARQUIS\",\n\t\"CUPBOAT\",\n\t\"SEAPLANE\",\n\t\"SPARROW\",\n\t\"SEASPAR\",\n\t\"MAVERICK\",\n\t\"COASTMAV\",\n\t\"POLMAV\",\n\t\"HUNTER\",\n\t\"RCBARON\",\n\t\"RCGOBLIN\",\n\t\"RCCOPTER\"\n};\n\ncHandlingDataMgr::cHandlingDataMgr(void)\n{\n\tmemset(this, 0, sizeof(*this));\n}\n\nvoid\ncHandlingDataMgr::Initialise(void)\n{\n\tLoadHandlingData();\n\tfield_0 = 0.1f;\n\tfWheelFriction = 0.9f;\n\tfield_8 = 1.0f;\n\tfield_C = 0.8f;\n\tfield_10 = 0.98f;\n}\n\nvoid\ncHandlingDataMgr::LoadHandlingData(void)\n{\n\tchar *start, *end;\n\tchar line[201];\t// weird value\n\tchar delim[4];\t// not sure\n\tchar *word;\n\tint field, handlingId;\n\tint keepGoing;\n\ttHandlingData *handling;\n\ttFlyingHandlingData *flyingHandling;\n\ttBoatHandlingData *boatHandling;\n\ttBikeHandlingData *bikeHandling;\n\n\tCFileMgr::SetDir(\"DATA\");\n\tCFileMgr::LoadFile(HandlingFilename, work_buff, sizeof(work_buff), \"r\");\n\tCFileMgr::SetDir(\"\");\n\n\tstart = (char*)work_buff;\n\tend = start+1;\n\thandling = nil;\n\tflyingHandling = nil;\n\tboatHandling = nil;\n\tbikeHandling = nil;\n\tkeepGoing = 1;\n\n\twhile(keepGoing){\n\t\t// find end of line\n\t\twhile(*end != '\\n') end++;\n\n\t\t// get line\n\t\tstrncpy(line, start, end - start);\n\t\tline[end - start] = '\\0';\n\t\tstart = end+1;\n\t\tend = start+1;\n\n\t\t// yeah, this is kinda crappy\n\t\tif(strcmp(line, \";the end\") == 0)\n\t\t\tkeepGoing = 0;\n\t\telse if(line[0] != ';'){\n\t\t\tif(line[0] == '!'){\n\t\t\t\t// Bike data\n\t\t\t\tfield = 0;\n\t\t\t\tstrcpy(delim, \" \\t\");\n\t\t\t\t// FIX: game seems to use a do-while loop here\n\t\t\t\tfor(word = strtok(line, delim); word; word = strtok(nil, delim)){\n\t\t\t\t\tswitch(field){\n\t\t\t\t\tcase  0: break;\n\t\t\t\t\tcase  1:\n\t\t\t\t\t\thandlingId = FindExactWord(word, (const char*)VehicleNames, 14, NUMHANDLINGS);\n\t\t\t\t\t\tassert(handlingId >= 0 && handlingId < NUMHANDLINGS);\n\t\t\t\t\t\tbikeHandling = GetBikePointer(handlingId);\n\t\t\t\t\t\tbikeHandling->nIdentifier = (tVehicleType)handlingId;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase  2: bikeHandling->fLeanFwdCOM = atof(word); break;\n\t\t\t\t\tcase  3: bikeHandling->fLeanFwdForce = atof(word); break;\n\t\t\t\t\tcase  4: bikeHandling->fLeanBakCOM = atof(word); break;\n\t\t\t\t\tcase  5: bikeHandling->fLeanBackForce = atof(word); break;\n\t\t\t\t\tcase  6: bikeHandling->fMaxLean = atof(word); break;\n\t\t\t\t\tcase  7: bikeHandling->fFullAnimLean = atof(word); break;\n\t\t\t\t\tcase  8: bikeHandling->fDesLean = atof(word); break;\n\t\t\t\t\tcase  9: bikeHandling->fSpeedSteer = atof(word); break;\n\t\t\t\t\tcase 10: bikeHandling->fSlipSteer = atof(word); break;\n\t\t\t\t\tcase 11: bikeHandling->fNoPlayerCOMz = atof(word); break;\n\t\t\t\t\tcase 12: bikeHandling->fWheelieAng = atof(word); break;\n\t\t\t\t\tcase 13: bikeHandling->fStoppieAng = atof(word); break;\n\t\t\t\t\tcase 14: bikeHandling->fWheelieSteer = atof(word); break;\n\t\t\t\t\tcase 15: bikeHandling->fWheelieStabMult = atof(word); break;\n\t\t\t\t\tcase 16: bikeHandling->fStoppieStabMult = atof(word); break;\n\t\t\t\t\t}\n\t\t\t\t\tfield++;\n\t\t\t\t}\n\t\t\t\tConvertBikeDataToGameUnits(bikeHandling);\n\t\t\t}else if(line[0] == '$'){\n\t\t\t\t// Flying data\n\t\t\t\tfield = 0;\n\t\t\t\tstrcpy(delim, \" \\t\");\n\t\t\t\t// FIX: game seems to use a do-while loop here\n\t\t\t\tfor(word = strtok(line, delim); word; word = strtok(nil, delim)){\n\t\t\t\t\tswitch(field){\n\t\t\t\t\tcase  0: break;\n\t\t\t\t\tcase  1:\n\t\t\t\t\t\thandlingId = FindExactWord(word, (const char*)VehicleNames, 14, NUMHANDLINGS);\n\t\t\t\t\t\tassert(handlingId >= 0 && handlingId < NUMHANDLINGS);\n\t\t\t\t\t\tflyingHandling = GetFlyingPointer(handlingId);\n\t\t\t\t\t\tflyingHandling->nIdentifier = (tVehicleType)handlingId;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase  2: flyingHandling->fThrust = atof(word); break;\n\t\t\t\t\tcase  3: flyingHandling->fThrustFallOff = atof(word); break;\n\t\t\t\t\tcase  4: flyingHandling->fYaw = atof(word); break;\n\t\t\t\t\tcase  5: flyingHandling->fYawStab = atof(word); break;\n\t\t\t\t\tcase  6: flyingHandling->fSideSlip = atof(word); break;\n\t\t\t\t\tcase  7: flyingHandling->fRoll = atof(word); break;\n\t\t\t\t\tcase  8: flyingHandling->fRollStab = atof(word); break;\n\t\t\t\t\tcase  9: flyingHandling->fPitch = atof(word); break;\n\t\t\t\t\tcase 10: flyingHandling->fPitchStab = atof(word); break;\n\t\t\t\t\tcase 11: flyingHandling->fFormLift = atof(word); break;\n\t\t\t\t\tcase 12: flyingHandling->fAttackLift = atof(word); break;\n\t\t\t\t\tcase 13: flyingHandling->fMoveRes = atof(word); break;\n\t\t\t\t\tcase 14: flyingHandling->vecTurnRes.x = atof(word); break;\n\t\t\t\t\tcase 15: flyingHandling->vecTurnRes.y = atof(word); break;\n\t\t\t\t\tcase 16: flyingHandling->vecTurnRes.z = atof(word); break;\n\t\t\t\t\tcase 17: flyingHandling->vecSpeedRes.x = atof(word); break;\n\t\t\t\t\tcase 18: flyingHandling->vecSpeedRes.y = atof(word); break;\n\t\t\t\t\tcase 19: flyingHandling->vecSpeedRes.z = atof(word); break;\n\t\t\t\t\t}\n\t\t\t\t\tfield++;\n\t\t\t\t}\n\t\t\t}else if(line[0] == '%'){\n\t\t\t\t// Boat data\n\t\t\t\tfield = 0;\n\t\t\t\tstrcpy(delim, \" \\t\");\n\t\t\t\t// FIX: game seems to use a do-while loop here\n\t\t\t\tfor(word = strtok(line, delim); word; word = strtok(nil, delim)){\n\t\t\t\t\tswitch(field){\n\t\t\t\t\tcase  0: break;\n\t\t\t\t\tcase  1:\n\t\t\t\t\t\thandlingId = FindExactWord(word, (const char*)VehicleNames, 14, NUMHANDLINGS);\n\t\t\t\t\t\tassert(handlingId >= 0 && handlingId < NUMHANDLINGS);\n\t\t\t\t\t\tboatHandling = GetBoatPointer(handlingId);\n\t\t\t\t\t\tboatHandling->nIdentifier = (tVehicleType)handlingId;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase  2: boatHandling->fThrustY = atof(word); break;\n\t\t\t\t\tcase  3: boatHandling->fThrustZ = atof(word); break;\n\t\t\t\t\tcase  4: boatHandling->fThrustAppZ = atof(word); break;\n\t\t\t\t\tcase  5: boatHandling->fAqPlaneForce = atof(word); break;\n\t\t\t\t\tcase  6: boatHandling->fAqPlaneLimit = atof(word); break;\n\t\t\t\t\tcase  7: boatHandling->fAqPlaneOffset = atof(word); break;\n\t\t\t\t\tcase  8: boatHandling->fWaveAudioMult = atof(word); break;\n\t\t\t\t\tcase  9: boatHandling->vecMoveRes.x = atof(word); break;\n\t\t\t\t\tcase 10: boatHandling->vecMoveRes.y = atof(word); break;\n\t\t\t\t\tcase 11: boatHandling->vecMoveRes.z = atof(word); break;\n\t\t\t\t\tcase 12: boatHandling->vecTurnRes.x = atof(word); break;\n\t\t\t\t\tcase 13: boatHandling->vecTurnRes.y = atof(word); break;\n\t\t\t\t\tcase 14: boatHandling->vecTurnRes.z = atof(word); break;\n\t\t\t\t\tcase 15: boatHandling->fLook_L_R_BehindCamHeight = atof(word); break;\n\t\t\t\t\t}\n\t\t\t\t\tfield++;\n\t\t\t\t}\n\t\t\t}else{\n\t\t\t\tfield = 0;\n\t\t\t\tstrcpy(delim, \" \\t\");\n\t\t\t\t// FIX: game seems to use a do-while loop here\n\t\t\t\tfor(word = strtok(line, delim); word; word = strtok(nil, delim)){\n\t\t\t\t\tswitch(field){\n\t\t\t\t\tcase  0:\n\t\t\t\t\t\thandlingId = FindExactWord(word, (const char*)VehicleNames, 14, NUMHANDLINGS);\n\t\t\t\t\t\tassert(handlingId >= 0 && handlingId < NUMHANDLINGS);\n\t\t\t\t\t\thandling = &HandlingData[handlingId];\n\t\t\t\t\t\thandling->nIdentifier = (tVehicleType)handlingId;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase  1: handling->fMass = atof(word); break;\n\t\t\t\t\tcase  2: handling->Dimension.x = atof(word); break;\n\t\t\t\t\tcase  3: handling->Dimension.y = atof(word); break;\n\t\t\t\t\tcase  4: handling->Dimension.z = atof(word); break;\n\t\t\t\t\tcase  5: handling->CentreOfMass.x = atof(word); break;\n\t\t\t\t\tcase  6: handling->CentreOfMass.y = atof(word); break;\n\t\t\t\t\tcase  7: handling->CentreOfMass.z = atof(word); break;\n\t\t\t\t\tcase  8: handling->nPercentSubmerged = atoi(word); break;\n\t\t\t\t\tcase  9: handling->fTractionMultiplier = atof(word); break;\n\t\t\t\t\tcase 10: handling->fTractionLoss = atof(word); break;\n\t\t\t\t\tcase 11: handling->fTractionBias = atof(word); break;\n\t\t\t\t\tcase 12: handling->Transmission.nNumberOfGears = atoi(word); break;\n\t\t\t\t\tcase 13: handling->Transmission.fMaxVelocity = atof(word); break;\n\t\t\t\t\tcase 14: handling->Transmission.fEngineAcceleration = atof(word) * 0.4; break;\n\t\t\t\t\tcase 15: handling->Transmission.nDriveType = word[0]; break;\n\t\t\t\t\tcase 16: handling->Transmission.nEngineType = word[0]; break;\n\t\t\t\t\tcase 17: handling->fBrakeDeceleration = atof(word); break;\n\t\t\t\t\tcase 18: handling->fBrakeBias = atof(word); break;\n\t\t\t\t\tcase 19: handling->bABS = !!atoi(word); break;\n\t\t\t\t\tcase 20: handling->fSteeringLock = atof(word); break;\n\t\t\t\t\tcase 21: handling->fSuspensionForceLevel = atof(word); break;\n\t\t\t\t\tcase 22: handling->fSuspensionDampingLevel = atof(word); break;\n\t\t\t\t\tcase 23: handling->fSeatOffsetDistance = atof(word); break;\n\t\t\t\t\tcase 24: handling->fCollisionDamageMultiplier = atof(word); break;\n\t\t\t\t\tcase 25: handling->nMonetaryValue = atoi(word); break;\n\t\t\t\t\tcase 26: handling->fSuspensionUpperLimit = atof(word); break;\n\t\t\t\t\tcase 27: handling->fSuspensionLowerLimit = atof(word); break;\n\t\t\t\t\tcase 28: handling->fSuspensionBias = atof(word); break;\n\t\t\t\t\tcase 29: handling->fSuspensionAntidiveMultiplier = atof(word); break;\n\t\t\t\t\tcase 30:\n\t\t\t\t\t\tsscanf(word, \"%x\", &handling->Flags);\n\t\t\t\t\t\thandling->Transmission.Flags = handling->Flags;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 31: handling->FrontLights = atoi(word); break;\n\t\t\t\t\tcase 32: handling->RearLights = atoi(word); break;\n\t\t\t\t\t}\n\t\t\t\t\tfield++;\n\t\t\t\t}\n\t\t\t\tConvertDataToGameUnits(handling);\n\t\t\t}\n\t\t}\n\t}\n}\n\nint\ncHandlingDataMgr::FindExactWord(const char *word, const char *words, int wordLen, int numWords)\n{\n\tint i;\n\n\tfor(i = 0; i < numWords; i++){\n\t\t// BUG: the game does something really stupid here, it's fixed here\n\t\tif(strncmp(word, words, wordLen) == 0)\n\t\t\treturn i;\n\t\twords += wordLen;\n\t}\n\treturn numWords;\n}\n\n\nvoid\ncHandlingDataMgr::ConvertDataToGameUnits(tHandlingData *handling)\n{\n\t// convert distance to m, time to 1/50s\n\tfloat velocity, a, b;\n\n\thandling->Transmission.fEngineAcceleration *= 1.0f/(50.0f*50.0f);\n\thandling->Transmission.fMaxVelocity *= 1000.0f/(60.0f*60.0f * 50.0f);\n\thandling->fBrakeDeceleration *= 1.0f/(50.0f*50.0f);\n\thandling->fTurnMass = (sq(handling->Dimension.x) + sq(handling->Dimension.y)) * handling->fMass / 12.0f;\n\tif(handling->fTurnMass < 10.0f)\n\t\thandling->fTurnMass *= 5.0f;\n\thandling->fInvMass = 1.0f/handling->fMass;\n\thandling->fCollisionDamageMultiplier *= 2000.0f/handling->fMass;\n\thandling->fBuoyancy = 100.0f/handling->nPercentSubmerged * GRAVITY*handling->fMass;\n\n\t// Don't quite understand this. What seems to be going on is that\n\t// we calculate a drag (air resistance) deceleration for a given velocity and\n\t// find the intersection between that and the max engine acceleration.\n\t// at that point the car cannot accelerate any further and we've found the max velocity.\n\ta = 0.0f;\n\tb = 100.0f;\n\tvelocity = handling->Transmission.fMaxVelocity;\n\twhile(a < b && velocity > 0.0f){\n\t\tvelocity -= 0.01f;\n\t\t// what's the 1/6?\n\t\ta = handling->Transmission.fEngineAcceleration/6.0f;\n\t\t// no density or drag coefficient here...\n\t\tfloat a_drag = 0.5f*SQR(velocity) * handling->Dimension.x*handling->Dimension.z / handling->fMass;\n\t\t// can't make sense of this... maybe  v - v/(drag + 1)  ? but that doesn't make so much sense either\n\t\tb = -velocity * (1.0f/(a_drag + 1.0f) - 1.0f);\n\t}\n\n\tif(handling->nIdentifier == HANDLING_RCBANDIT){\n\t\thandling->Transmission.fMaxCruiseVelocity = handling->Transmission.fMaxVelocity;\n\t\thandling->Transmission.fMaxReverseVelocity = -handling->Transmission.fMaxVelocity;\n\t}else if(handling->nIdentifier >= HANDLING_BIKE && handling->nIdentifier <= HANDLING_FREEWAY){\n\t\thandling->Transmission.fMaxCruiseVelocity = velocity;\n\t\thandling->Transmission.fMaxVelocity = velocity * 1.2f;\n\t\thandling->Transmission.fMaxReverseVelocity = -0.05f;\n\t}else{\n\t\thandling->Transmission.fMaxCruiseVelocity = velocity;\n\t\thandling->Transmission.fMaxVelocity = velocity * 1.2f;\n\t\thandling->Transmission.fMaxReverseVelocity = -0.2f;\n\t}\n\n\tif(handling->Transmission.nDriveType == '4')\n\t\thandling->Transmission.fEngineAcceleration /= 4.0f;\n\telse\n\t\thandling->Transmission.fEngineAcceleration /= 2.0f;\n\n\thandling->Transmission.InitGearRatios();\n}\n\nvoid\ncHandlingDataMgr::ConvertBikeDataToGameUnits(tBikeHandlingData *handling)\n{\n\thandling->fMaxLean = Sin(DEGTORAD(handling->fMaxLean));\n\thandling->fFullAnimLean = DEGTORAD(handling->fFullAnimLean);\n\thandling->fWheelieAng = Sin(DEGTORAD(handling->fWheelieAng));\n\thandling->fStoppieAng = Sin(DEGTORAD(handling->fStoppieAng));\n}\n\nint32\ncHandlingDataMgr::GetHandlingId(const char *name)\n{\n\tint i;\n\tfor(i = 0; i < NUMHANDLINGS; i++)\n\t\tif(strncmp(VehicleNames[i], name, 14) == 0)\n\t\t\tbreak;\n\treturn i;\n}\n\ntFlyingHandlingData*\ncHandlingDataMgr::GetFlyingPointer(uint8 id)\n{\n\tif(id >= HANDLING_SEAPLANE && id <= HANDLING_RCCOPTER)\n\t\treturn &FlyingHandlingData[id-HANDLING_SEAPLANE];\n\treturn &FlyingHandlingData[0];\n}\n\ntBoatHandlingData*\ncHandlingDataMgr::GetBoatPointer(uint8 id)\n{\n\tif(id >= HANDLING_PREDATOR && id <= HANDLING_SEAPLANE)\n\t\treturn &BoatHandlingData[id-HANDLING_PREDATOR];\n\treturn &BoatHandlingData[0];\n}\n"
  },
  {
    "path": "src/vehicles/HandlingMgr.h",
    "content": "#pragma once\n\n#include \"Transmission.h\"\n\nenum tVehicleType\n{\n\tHANDLING_LANDSTAL,\n\tHANDLING_IDAHO,\n\tHANDLING_STINGER,\n\tHANDLING_LINERUN,\n\tHANDLING_PEREN,\n\tHANDLING_SENTINEL,\n\tHANDLING_PATRIOT,\n\tHANDLING_FIRETRUK,\n\tHANDLING_TRASH,\n\tHANDLING_STRETCH,\n\tHANDLING_MANANA,\n\tHANDLING_INFERNUS,\n\tHANDLING_PONY,\n\tHANDLING_MULE,\n\tHANDLING_CHEETAH,\n\tHANDLING_AMBULAN,\n\tHANDLING_FBICAR,\n\tHANDLING_MOONBEAM,\n\tHANDLING_ESPERANT,\n\tHANDLING_TAXI,\n\tHANDLING_KURUMA,\n\tHANDLING_BOBCAT,\n\tHANDLING_MRWHOOP,\n\tHANDLING_BFINJECT,\n\tHANDLING_POLICE,\n\tHANDLING_ENFORCER,\n\tHANDLING_SECURICA,\n\tHANDLING_BANSHEE,\n\tHANDLING_BUS,\n\tHANDLING_RHINO,\n\tHANDLING_BARRACKS,\n\tHANDLING_TRAIN,\n\tHANDLING_HELI,\n\tHANDLING_DODO,\n\tHANDLING_COACH,\n\tHANDLING_CABBIE,\n\tHANDLING_STALLION,\n\tHANDLING_RUMPO,\n\tHANDLING_RCBANDIT,\n\tHANDLING_MAFIA,\n\tHANDLING_AIRTRAIN,\n\tHANDLING_DEADDODO,\n\tHANDLING_FLATBED,\n\tHANDLING_YANKEE,\n\tHANDLING_GOLFCART,\n\tHANDLING_VOODOO,\n\tHANDLING_WASHING,\n\tHANDLING_CUBAN,\n\tHANDLING_ROMERO,\n\tHANDLING_PACKER,\n\tHANDLING_ADMIRAL,\n\tHANDLING_GANGBUR,\n\tHANDLING_ZEBRA,\n\tHANDLING_TOPFUN,\n\tHANDLING_GLENDALE,\n\tHANDLING_OCEANIC,\n\tHANDLING_HERMES,\n\tHANDLING_SABRE1,\n\tHANDLING_SABRETUR,\n\tHANDLING_PHEONIX,\n\tHANDLING_WALTON,\n\tHANDLING_REGINA,\n\tHANDLING_COMET,\n\tHANDLING_DELUXO,\n\tHANDLING_BURRITO,\n\tHANDLING_SPAND,\n\tHANDLING_BAGGAGE,\n\tHANDLING_KAUFMAN,\n\tHANDLING_RANCHER,\n\tHANDLING_FBIRANCH,\n\tHANDLING_VIRGO,\n\tHANDLING_GREENWOO,\n\tHANDLING_HOTRING,\n\tHANDLING_SANDKING,\n\tHANDLING_BLISTAC,\n\tHANDLING_BOXVILLE,\n\tHANDLING_BENSON,\n\tHANDLING_DESPERAD,\n\tHANDLING_LOVEFIST,\n\tHANDLING_BLOODRA,\n\tHANDLING_BLOODRB,\n\n\tHANDLING_BIKE,\n\tHANDLING_MOPED,\n\tHANDLING_DIRTBIKE,\n\tHANDLING_ANGEL,\n\tHANDLING_FREEWAY,\n\n\tHANDLING_PREDATOR,\n\tHANDLING_SPEEDER,\n\tHANDLING_REEFER,\n\tHANDLING_RIO,\n\tHANDLING_SQUALO,\n\tHANDLING_TROPIC,\n\tHANDLING_COASTGRD,\n\tHANDLING_DINGHY,\n\tHANDLING_MARQUIS,\n\tHANDLING_CUPBOAT,\n\tHANDLING_SEAPLANE,\t// both boat and plane!\n\tHANDLING_SPARROW,\n\tHANDLING_SEASPAR,\n\tHANDLING_MAVERICK,\n\tHANDLING_COASTMAV,\n\tHANDLING_POLMAV,\n\tHANDLING_HUNTER,\n\tHANDLING_RCBARON,\n\tHANDLING_RCGOBLIN,\n\tHANDLING_RCCOPTER,\n\n\tNUMHANDLINGS,\n\n\tNUMBIKEHANDLINGS = HANDLING_FREEWAY+1 - HANDLING_BIKE,\n\tNUMFLYINGHANDLINGS = HANDLING_RCCOPTER+1 - HANDLING_SEAPLANE,\n\tNUMBOATHANDLINGS = HANDLING_SEAPLANE+1 - HANDLING_PREDATOR,\n};\n\nenum tField // most likely a handling field enum, never used so :shrug:\n{\n\n};\n\nenum\n{\n\tHANDLING_1G_BOOST = 1,\n\tHANDLING_2G_BOOST = 2,\n\tHANDLING_REV_BONNET = 4,\n\tHANDLING_HANGING_BOOT = 8,\n\tHANDLING_NO_DOORS = 0x10,\n\tHANDLING_IS_VAN = 0x20,\n\tHANDLING_IS_BUS = 0x40,\n\tHANDLING_IS_LOW = 0x80,\n\tHANDLING_DBL_EXHAUST = 0x100,\n\tHANDLING_TAILGATE_BOOT = 0x200,\n\tHANDLING_NOSWING_BOOT = 0x400,\n\tHANDLING_NONPLAYER_STABILISER = 0x800,\n\tHANDLING_NEUTRALHANDLING = 0x1000,\n\tHANDLING_HAS_NO_ROOF = 0x2000,\n\tHANDLING_IS_BIG = 0x4000,\n\tHANDLING_HALOGEN_LIGHTS = 0x8000,\n\tHANDLING_IS_BIKE = 0x10000,\n\tHANDLING_IS_HELI = 0x20000,\n\tHANDLING_IS_PLANE = 0x40000,\n\tHANDLING_IS_BOAT = 0x80000,\n\tHANDLING_NO_EXHAUST = 0x100000,\n\tHANDLING_REARWHEEL_1ST = 0x200000,\n\tHANDLING_HANDBRAKE_TYRE = 0x400000,\n\tHANDLING_SIT_IN_BOAT = 0x800000,\n\tHANDLING_FAT_REARW = 0x1000000,\n\tHANDLING_NARROW_FRONTW = 0x2000000,\n\tHANDLING_GOOD_INSAND = 0x4000000,\n\tHANDLING_UNKNOWN = 0x8000000,\t// something for helis and planes\n};\n\nstruct tHandlingData\n{\n\ttVehicleType nIdentifier;\n\tfloat fMass;\n\tfloat fInvMass;\n\tfloat fTurnMass;\n\tCVector Dimension;\n\tCVector CentreOfMass;\n\tint8 nPercentSubmerged;\n\tfloat fBuoyancy;\n\tfloat fTractionMultiplier;\n\tcTransmission Transmission;\n\tfloat fBrakeDeceleration;\n\tfloat fBrakeBias;\n\tint8 bABS;\n\tfloat fSteeringLock;\n\tfloat fTractionLoss;\n\tfloat fTractionBias;\n\tfloat fUnused;\n\tfloat fSuspensionForceLevel;\n\tfloat fSuspensionDampingLevel;\n\tfloat fSuspensionUpperLimit;\n\tfloat fSuspensionLowerLimit;\n\tfloat fSuspensionBias;\n\tfloat fSuspensionAntidiveMultiplier;\n\tfloat fCollisionDamageMultiplier;\n\tuint32 Flags;\n\tfloat fSeatOffsetDistance;\n\tint32 nMonetaryValue;\n\tint8 FrontLights;\n\tint8 RearLights;\n};\n\nstruct tBikeHandlingData\n{\n\ttVehicleType nIdentifier;\n\tfloat fLeanFwdCOM;\n\tfloat fLeanFwdForce;\n\tfloat fLeanBakCOM;\n\tfloat fLeanBackForce;\n\tfloat fMaxLean;\n\tfloat fFullAnimLean;\n\tfloat fDesLean;\n\tfloat fSpeedSteer;\n\tfloat fSlipSteer;\n\tfloat fNoPlayerCOMz;\n\tfloat fWheelieAng;\n\tfloat fStoppieAng;\n\tfloat fWheelieSteer;\n\tfloat fWheelieStabMult;\n\tfloat fStoppieStabMult;\n};\n\nstruct tBoatHandlingData\n{\n\ttVehicleType nIdentifier;\n\tfloat fThrustY;\n\tfloat fThrustZ;\n\tfloat fThrustAppZ;\n\tfloat fAqPlaneForce;\n\tfloat fAqPlaneLimit;\n\tfloat fAqPlaneOffset;\n\tfloat fWaveAudioMult;\n\tfloat fLook_L_R_BehindCamHeight;\n\tCVector vecMoveRes;\n\tCVector vecTurnRes;\n};\n\nstruct  tFlyingHandlingData\n{\n\ttVehicleType nIdentifier;\n\tfloat fThrust;\n\tfloat fThrustFallOff;\n\tfloat fYaw;\n\tfloat fYawStab;\n\tfloat fSideSlip;\n\tfloat fRoll;\n\tfloat fRollStab;\n\tfloat fPitch;\n\tfloat fPitchStab;\n\tfloat fFormLift;\n\tfloat fAttackLift;\n\tfloat fMoveRes;\n\tCVector vecTurnRes;\n\tCVector vecSpeedRes;\n};\n\nclass CVehicle;\n\nclass cHandlingDataMgr\n{\n\tfloat field_0;\t// unused it seems\npublic:\n\tfloat fWheelFriction;\t// wheel related\nprivate:\n\tfloat field_8;\t//\n\tfloat field_C;\t// unused it seems\n\tfloat field_10;\t//\n\ttHandlingData HandlingData[NUMHANDLINGS];\n\ttBikeHandlingData BikeHandlingData[NUMBIKEHANDLINGS];\n\ttFlyingHandlingData FlyingHandlingData[NUMFLYINGHANDLINGS];\n\ttBoatHandlingData BoatHandlingData[NUMBOATHANDLINGS];\n\npublic:\n\tcHandlingDataMgr(void);\n\tvoid Initialise(void);\n\tvoid LoadHandlingData(void);\n\tint FindExactWord(const char *word, const char *words, int wordLen, int numWords);\n\tvoid ConvertDataToWorldUnits(tHandlingData *handling);\n\tvoid ConvertDataToGameUnits(tHandlingData *handling);\n\tvoid ConvertBikeDataToGameUnits(tBikeHandlingData *handling);\n\tint32 GetHandlingId(const char *name);\n\ttHandlingData *GetHandlingData(tVehicleType id) { return &HandlingData[id]; }\n\ttBikeHandlingData *GetBikePointer(uint8 id) { return &BikeHandlingData[id-HANDLING_BIKE]; }\n\ttFlyingHandlingData *GetFlyingPointer(uint8 id);\n\ttBoatHandlingData *GetBoatPointer(uint8 id);\n\tbool HasRearWheelDrive(tVehicleType id) { return HandlingData[id].Transmission.nDriveType != 'F'; }\n\tbool HasFrontWheelDrive(tVehicleType id) { return HandlingData[id].Transmission.nDriveType != 'R'; }\n};\nextern cHandlingDataMgr mod_HandlingManager;\n"
  },
  {
    "path": "src/vehicles/Heli.cpp",
    "content": "#include \"common.h\"\n#include \"main.h\"\n\n#include \"General.h\"\n#include \"Darkel.h\"\n#include \"Stats.h\"\n#include \"SurfaceTable.h\"\n#include \"ModelIndices.h\"\n#include \"Streaming.h\"\n#include \"Camera.h\"\n#include \"VisibilityPlugins.h\"\n#include \"ZoneCull.h\"\n#include \"Particle.h\"\n#include \"Shadows.h\"\n#include \"Coronas.h\"\n#include \"Explosion.h\"\n#include \"WindModifiers.h\"\n#include \"Timecycle.h\"\n#include \"TempColModels.h\"\n#include \"World.h\"\n#include \"WaterLevel.h\"\n#include \"Population.h\"\n#include \"PlayerPed.h\"\n#include \"CopPed.h\"\n#include \"Wanted.h\"\n#include \"DMAudio.h\"\n#include \"Object.h\"\n#include \"HandlingMgr.h\"\n#include \"Ropes.h\"\n#include \"Heli.h\"\n#ifdef FIX_BUGS\n#include \"Replay.h\"\n#endif\n\nenum\n{\n\tHELI_STATUS_HOVER,\n\tHELI_STATUS_CHASE_PLAYER,\n\tHELI_STATUS_FLY_AWAY,\n\tHELI_STATUS_SHOT_DOWN,\n\tHELI_STATUS_HOVER2,\n};\n\nCHeli *CHeli::pHelis[NUM_HELIS];\nint16 CHeli::NumRandomHelis;\nuint32 CHeli::TestForNewRandomHelisTimer;\nbool CHeli::CatalinaHeliOn;\nbool CHeli::CatalinaHasBeenShotDown;\nbool CHeli::ScriptHeliOn;\n\nCHeli::CHeli(int32 id, uint8 CreatedBy)\n : CVehicle(CreatedBy)\n{\n\tint i;\n\n\tCVehicleModelInfo *mi = (CVehicleModelInfo*)CModelInfo::GetModelInfo(id);\n\tm_vehType = VEHICLE_TYPE_HELI;\n\tpHandling = mod_HandlingManager.GetHandlingData((tVehicleType)mi->m_handlingId);\n\tSetModelIndex(id);\n\tm_heliStatus = HELI_STATUS_HOVER;\n\tm_pathState = 0;\n\n\tm_fMass = 100000000.0f;\n\tm_fTurnMass = 100000000.0f;\n\tm_fAirResistance = 0.9994f;\n\tm_fElasticity = 0.05f;\n\n\tm_nHeliId = 0;\n\tm_fRotorRotation = 0.0f;\n\tm_nBulletDamage = 0;\n\tm_fAngularSpeed = 0.0f;\n\tm_fRotation = 0.0f;\n\n\tm_numSwat = 4;\n\n\tm_nSearchLightTimer = CTimer::GetTimeInMilliseconds();\n\tfor(i = 0; i < 6; i++){\n\t\tm_aSearchLightHistoryX[i] = 0.0f;\n\t\tm_aSearchLightHistoryY[i] = 0.0f;\n\t}\n\n\tfor(i = 0; i < 8; i++)\n\t\tm_fHeliDustZ[i] = -50.0f;\n\n\tm_nPoliceShoutTimer = CTimer::GetTimeInMilliseconds();\n\tSetStatus(STATUS_HELI);\n\tm_bTestRight = true;\n\tm_fTargetOffset = 0.0f;\n\tm_fSearchLightX = m_fSearchLightY = 0.0f;\n\n\tm_aSwatState[0] = m_aSwatState[1] = m_aSwatState[2] = m_aSwatState[3] = 0;\n\n\t// BUG: not in game but gets initialized to CDCDCDCD in debug\n\tm_nLastShotTime = 0;\n}\n\nvoid\nCHeli::SetModelIndex(uint32 id)\n{\n\tint i;\n\n\tCVehicle::SetModelIndex(id);\n\tfor(i = 0; i < NUM_HELI_NODES; i++)\n\t\tm_aHeliNodes[i] = nil;\n\tCClumpModelInfo::FillFrameArray(GetClump(), m_aHeliNodes);\n}\n\nstatic float CatalinaTargetX[7] = { -478.0, -677.0, -907.0, -1095.0, -1152.0, -1161.0, -1161.0 };\nstatic float CatalinaTargetY[7] = { 227.0, 206.0, 210.0, 242.0, 278.0, 341.0, 341.0 };\nstatic float CatalinaTargetZ[7] = { 77.0, 66.0, 60.0, 53.0, 51.0, 46.0, 30.0 };\nstatic float DamPathX[6] = { -1191.0, -1176.0, -1128.0, -1072.0, -1007.0, -971.0 };\nstatic float DamPathY[6] = { 350.0, 388.0, 429.0, 447.0, 449.0, 416.0 };\nstatic float DamPathZ[6] = { 42.0, 37.0, 28.0, 28.0, 31.0, 33.0 };\nstatic float ShortPathX[4] = { -974.0, -1036.0, -1112.0, -1173.0 };\nstatic float ShortPathY[4] = { 340.0, 312.0, 317.0, 294.0 };\nstatic float ShortPathZ[4] = { 41.0, 38.0, 32.0, 39.0 };\nstatic float LongPathX[7] = { -934.0, -905.0, -906.0, -1063.0, -1204.0, -1233.0, -1207.0 };\nstatic float LongPathY[7] = { 371.0, 362.0, 488.0, 548.0, 451.0, 346.0, 308.0 };\nstatic float LongPathZ[7] = { 57.0, 90.0, 105.0, 100.0, 81.0, 79.0, 70.0 };\n\nstatic int PathPoint;\n\nvoid\nCHeli::ProcessControl(void)\n{\n\tint i;\n\n\tif(gbModelViewer)\n\t\treturn;\n\n\tCWindModifiers::RegisterOne(GetPosition(), 1);\n\n\t// Find target\n\tCVector target(0.0f, 0.0f, 0.0f);\n\tCVector2D vTargetDist;\n\tif(m_heliType == HELI_TYPE_CATALINA && m_heliStatus != HELI_STATUS_SHOT_DOWN){\n\t\tswitch(m_pathState){\n\t\tcase 0:\n\t\tcase 1:\n\t\tcase 2:\n\t\tcase 3:\n\t\tcase 4:\n\t\tcase 5:\n\t\t\ttarget.x = CatalinaTargetX[m_pathState];\n\t\t\ttarget.y = CatalinaTargetY[m_pathState];\n\t\t\ttarget.z = CatalinaTargetZ[m_pathState];\n\t\t\tif((target - GetPosition()).Magnitude() < 9.0f)\n\t\t\t\tm_pathState++;\n\t\t\tbreak;\n\t\tcase 6:\n\t\t\ttarget.x = CatalinaTargetX[m_pathState];\n\t\t\ttarget.y = CatalinaTargetY[m_pathState];\n\t\t\ttarget.z = CatalinaTargetZ[m_pathState];\n\t\t\tif(GetPosition().z > 31.55f)\n\t\t\t\tbreak;\n\t\t\tm_pathState = 7;\n\t\t\tGetMatrix().GetPosition().z = 31.55f;\n\t\t\tm_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);\n\t\t\tbreak;\n\t\tcase 7:\n\t\t\tGetMatrix().GetPosition().z = 31.55f;\n\t\t\ttarget = GetPosition();\n\t\t\tbreak;\n\n\n\t\t// Take off\n\t\tcase 8:\n\t\t\ttarget.x = GetPosition().x;\n\t\t\ttarget.y = GetPosition().y;\n\t\t\ttarget.z = 74.0f;\n\t\t\tif(GetPosition().z < 40.0f)\n\t\t\t\tbreak;\n\t\t\tPathPoint = 2;\n\t\t\tm_pathState = 9;\n\t\t\tbreak;\n\t\t// Circle around dam\n\t\tcase 9:\n\t\t\ttarget.x = DamPathX[PathPoint];\n\t\t\ttarget.y = DamPathY[PathPoint];\n\t\t\ttarget.z = DamPathZ[PathPoint];\n\t\t\tif((target - GetPosition()).Magnitude() < 9.0f){\n\t\t\t\tPathPoint++;\n\t\t\t\tif(PathPoint >= 6){\n\t\t\t\t\tm_pathState = 10;\n\t\t\t\t\tPathPoint = 0;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\tcase 10:\n\t\t\ttarget.x = ShortPathX[PathPoint];\n\t\t\ttarget.y = ShortPathY[PathPoint];\n\t\t\ttarget.z = ShortPathZ[PathPoint];\n\t\t\tif((target - GetPosition()).Magnitude() < 9.0f){\n\t\t\t\tPathPoint++;\n\t\t\t\tif(PathPoint >= 3){\n\t\t\t\t\tm_pathState = 9;\n\t\t\t\t\tPathPoint = 1;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\t// how do we get here?\n\t\tcase 11:\n\t\t\ttarget.x = LongPathX[PathPoint];\n\t\t\ttarget.y = LongPathY[PathPoint];\n\t\t\ttarget.z = LongPathZ[PathPoint];\n\t\t\tif((target - GetPosition()).Magnitude() < 9.0f){\n\t\t\t\tPathPoint++;\n\t\t\t\tif(PathPoint >= 7){\n\t\t\t\t\tm_pathState = 9;\n\t\t\t\t\tPathPoint = 0;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\n\t\t// Fly away\n\t\tcase 12:\n\t\t\ttarget.x = GetPosition().x;\n\t\t\ttarget.y = GetPosition().y;\n\t\t\ttarget.z = 200.0f;\n\t\t\tbreak;\n\t\t}\n\n\t\tvTargetDist = target - GetPosition();\n\t\tm_fTargetZ = target.z;\n\t\tif(m_pathState == 6){\n\t\t\tGetMatrix().GetPosition().x = GetMatrix().GetPosition().x*0.99f + target.x*0.01f;\n\t\t\tGetMatrix().GetPosition().y = GetMatrix().GetPosition().y*0.99f + target.y*0.01f;\n\t\t}\n\t}else{\n\t\tvTargetDist = FindPlayerCoors() - GetPosition();\n\t\tm_fTargetZ = FindPlayerCoors().z;\n\n\t\t// Heli flies away to (0, 0)\n\t\tif(m_heliStatus == HELI_STATUS_FLY_AWAY && GetPosition().z > 20.0f){\n\t\t\tvTargetDist.x = 0.0f - GetPosition().x;\n\t\t\tvTargetDist.y = 0.0f - GetPosition().y;\n\t\t}\n\n\t\tfloat groundZ;\n\t\tswitch(m_heliStatus){\n\t\tcase HELI_STATUS_HOVER:\n\t\t\tgroundZ = CWorld::FindGroundZFor3DCoord(GetPosition().x, GetPosition().y, 1000.0f, nil);\n\t\t\tm_fTargetZ = Max(groundZ, m_fTargetZ) + 8.0f;\n\t\t\tbreak;\n\t\tcase HELI_STATUS_SHOT_DOWN:\n\t\t\tgroundZ = CWorld::FindGroundZFor3DCoord(GetPosition().x, GetPosition().y, 1000.0f, nil);\n\t\t\tm_fTargetZ = Max(groundZ, m_fTargetZ) + 8.0f + m_fTargetOffset;\n\t\t\tbreak;\n\t\tcase HELI_STATUS_HOVER2:\n\t\t\tgroundZ = CWorld::FindGroundZFor3DCoord(GetPosition().x, GetPosition().y, 1000.0f, nil);\n\t\t\tm_fTargetZ = Max(groundZ, m_fTargetZ) + 8.0f + m_fTargetOffset;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tgroundZ = CWorld::FindGroundZFor3DCoord(GetPosition().x, GetPosition().y, 1000.0f, nil);\n\t\t\tm_fTargetZ = Max(groundZ, m_fTargetZ) + 12.0f;\n\t\t\tbreak;\n\t\t}\n\n\t\t// Move up if too low\n\t\tif(GetPosition().z - 2.0f < groundZ && m_heliStatus != HELI_STATUS_SHOT_DOWN)\n\t\t\tm_vecMoveSpeed.z += CTimer::GetTimeStep()*0.01f;\n\t\tm_vecMoveSpeed.z = clamp(m_vecMoveSpeed.z, -0.3f, 0.3f);\n\t}\n\n\tfloat fTargetDist = vTargetDist.Magnitude();\n\n\tswitch(m_heliStatus){\n\tcase HELI_STATUS_HOVER:\n\tcase HELI_STATUS_HOVER2:{\n\t\tfloat targetHeight;\n\t\tif(m_heliType == HELI_TYPE_CATALINA)\n\t\t\ttargetHeight = 8.0f;\n\t\telse\n\t\t\ttargetHeight = 40.0f - m_nHeliId*10.0f;\n\t\tif(fTargetDist > targetHeight)\n\t\t\tm_heliStatus = HELI_STATUS_CHASE_PLAYER;\n\t\t}\n\t\tif(m_numSwat)\n\t\t\tSendDownSwat();\n\t\tbreak;\n\tcase HELI_STATUS_CHASE_PLAYER:{\n\t\tfloat targetHeight;\n\t\tif(m_heliType == HELI_TYPE_CATALINA)\n\t\t\ttargetHeight = 4.0f;\n\t\telse\n\t\t\ttargetHeight = 30.0f - m_nHeliId*7.5f;\n\t\tif(fTargetDist < 1.0f ||\n\t\t   fTargetDist < targetHeight && CWorld::GetIsLineOfSightClear(GetPosition(), FindPlayerCoors(), true, false, false, false, false, false))\n\t\t\tm_heliStatus = HELI_STATUS_HOVER;\n\t\t}\n\t\tbreak;\n\t}\n\n\t// Find xy speed\n\tfloat speed;\n\tif(fTargetDist > 100.0f)\n\t\tspeed = 1.0f;\n\telse if(fTargetDist > 75.0f)\n\t\tspeed = 0.7f;\n\telse\n\t\tspeed = 0.4f;\n\tif(m_heliStatus == HELI_STATUS_HOVER || m_heliStatus == HELI_STATUS_HOVER2 || m_heliStatus == HELI_STATUS_SHOT_DOWN)\n\t\tspeed = 0.0f;\n\n\tif(fTargetDist != 0.0f)\n\t\tvTargetDist /= fTargetDist;\n\telse\n\t\tvTargetDist.x = 1.0f;\n\tCVector2D targetSpeed = vTargetDist * speed;\n\n\tif(m_heliStatus == HELI_STATUS_HOVER2 || m_heliStatus == HELI_STATUS_SHOT_DOWN){\n\t\tbool force = !!((CTimer::GetFrameCounter() + m_randomSeed) & 8);\n\t\tif(m_bTestRight){\n\t\t\tif(force || CWorld::TestSphereAgainstWorld(GetPosition() + 4.0f*GetRight(), 2.0f, this, true, false, false, false, false, false) == nil){\n\t\t\t\tif(m_heliStatus == HELI_STATUS_SHOT_DOWN){\n\t\t\t\t\tm_fTargetOffset -= CTimer::GetTimeStep()*0.05f;\n\t\t\t\t\ttargetSpeed.x -= -vTargetDist.x*0.15f;\n\t\t\t\t\ttargetSpeed.y -= vTargetDist.y*0.15f;\n\t\t\t\t}else{\n\t\t\t\t\ttargetSpeed.x -= -vTargetDist.x*0.05f;\n\t\t\t\t\ttargetSpeed.y -= vTargetDist.y*0.05f;\n\t\t\t\t}\n\t\t\t}else{\n\t\t\t\tm_bTestRight = false;\n\t\t\t\tif(m_heliStatus == HELI_STATUS_HOVER2)\n\t\t\t\t\tm_fTargetOffset += 5.0f;\n\t\t\t\telse\n\t\t\t\t\tm_fTargetOffset -= 5.0f;\n\t\t\t}\n\t\t}else{\n\t\t\tif(force || CWorld::TestSphereAgainstWorld(GetPosition() - 4.0f*GetRight(), 2.0f, this, true, false, false, false, false, false) == nil){\n\t\t\t\tif(m_heliStatus == HELI_STATUS_SHOT_DOWN){\n\t\t\t\t\tm_fTargetOffset -= CTimer::GetTimeStep()*0.05f;\n\t\t\t\t\ttargetSpeed.x += -vTargetDist.x*0.15f;\n\t\t\t\t\ttargetSpeed.y += vTargetDist.y*0.15f;\n\t\t\t\t}else{\n\t\t\t\t\ttargetSpeed.x += -vTargetDist.x*0.05f;\n\t\t\t\t\ttargetSpeed.y += vTargetDist.y*0.05f;\n\t\t\t\t}\n\t\t\t}else{\n\t\t\t\tm_bTestRight = true;\n\t\t\t\tif(m_heliStatus == HELI_STATUS_HOVER2)\n\t\t\t\t\tm_fTargetOffset += 5.0f;\n\t\t\t\telse\n\t\t\t\t\tm_fTargetOffset -= 5.0f;\n\t\t\t}\n\t\t}\n\n\t\tif(m_fTargetOffset > 30.0f)\n\t\t\tm_fTargetOffset = 30.0f;\n\n\t\tif(m_heliStatus == HELI_STATUS_SHOT_DOWN && force){\n\t\t\tif(CWorld::TestSphereAgainstWorld(GetPosition() + 1.5f*GetForward(), 2.0f, this, true, false, false, false, false, false) ||\n\t\t\t   CWorld::TestSphereAgainstWorld(GetPosition() - 1.5f*GetForward(), 2.0f, this, true, false, false, false, false, false))\n\t\t\t\tm_nExplosionTimer = CTimer::GetPreviousTimeInMilliseconds();\n\t\t}\n\t}else\n\t\tif(m_fTargetOffset >= 2.0f)\n\t\t\tm_fTargetOffset -= 2.0f;\n\n\tCVector2D speedDir = targetSpeed - m_vecMoveSpeed;\n\tfloat speedDiff = speedDir.Magnitude();\n\tif(speedDiff != 0.0f)\n\t\tspeedDir /= speedDiff;\n\telse\n\t\tspeedDir.x = 1.0f;\n\tfloat speedInc = CTimer::GetTimeStep()*0.002f;\n\tif(speedDiff < speedInc){\n\t\tm_vecMoveSpeed.x = targetSpeed.x;\n\t\tm_vecMoveSpeed.y = targetSpeed.y;\n\t}else{\n\t\tm_vecMoveSpeed.x += speedDir.x*speedInc;\n\t\tm_vecMoveSpeed.y += speedDir.y*speedInc;\n\t}\n\tGetMatrix().GetPosition().x += m_vecMoveSpeed.x*CTimer::GetTimeStep();\n\tGetMatrix().GetPosition().y += m_vecMoveSpeed.y*CTimer::GetTimeStep();\n\n\t// Find z target\n\tif(m_heliStatus == HELI_STATUS_FLY_AWAY)\n\t\tm_fTargetZ = 1000.0f;\n\tif((CTimer::GetTimeInMilliseconds() + 800*m_nHeliId) & 0x800)\n\t\tm_fTargetZ += 2.0f;\n\tm_fTargetZ += m_nHeliId*5.0f;\n\n\t// Find z speed\n\tfloat targetSpeedZ = (m_fTargetZ - GetPosition().z)*0.01f;\n\tfloat speedDiffZ = targetSpeedZ - m_vecMoveSpeed.z;\n\tfloat speedIncZ = CTimer::GetTimeStep()*0.001f;\n\tif(m_heliStatus == HELI_STATUS_FLY_AWAY)\n\t\tspeedIncZ *= 1.5f;\n\tif(Abs(speedDiffZ) < speedIncZ)\n\t\tm_vecMoveSpeed.z = targetSpeedZ;\n\telse if(speedDiffZ < 0.0f)\n\t\tm_vecMoveSpeed.z -= speedIncZ;\n\telse\n\t\tm_vecMoveSpeed.z += speedIncZ*1.5f;\n\tGetMatrix().GetPosition().z += m_vecMoveSpeed.z*CTimer::GetTimeStep();\n\n\t// Find angular speed\n\tfloat targetAngularSpeed;\n\tm_fAngularSpeed *= Pow(0.995f, CTimer::GetTimeStep());\n\tif(fTargetDist < 8.0f)\n\t\ttargetAngularSpeed = 0.0f;\n\telse{\n\t\tfloat rotationDiff = CGeneral::GetATanOfXY(vTargetDist.x, vTargetDist.y) - m_fRotation;\n\t\twhile(rotationDiff < -3.14f) rotationDiff += 6.28f;\n\t\twhile(rotationDiff > 3.14f) rotationDiff -= 6.28f;\n\t\tif(Abs(rotationDiff) > 0.4f){\n\t\t\tif(rotationDiff < 0.0f)\n\t\t\t\ttargetAngularSpeed = -0.2f;\n\t\t\telse\n\t\t\t\ttargetAngularSpeed = 0.2f;\n\t\t}else\n\t\t\ttargetAngularSpeed = 0.0f;\n\t}\n\tfloat angularSpeedDiff = targetAngularSpeed - m_fAngularSpeed;\n\tfloat angularSpeedInc = CTimer::GetTimeStep()*0.0001f;\n\tif(Abs(angularSpeedDiff) < angularSpeedInc)\n\t\tm_fAngularSpeed = targetAngularSpeed;\n\telse if(angularSpeedDiff < 0.0f)\n\t\tm_fAngularSpeed -= angularSpeedInc;\n\telse\n\t\tm_fAngularSpeed += angularSpeedInc;\n\tm_fRotation += m_fAngularSpeed * CTimer::GetTimeStep();\n\n\t// Set matrix\n\tCVector up(3.0f*m_vecMoveSpeed.x, 3.0f*m_vecMoveSpeed.y, 1.0f);\n\tup.Normalise();\n\tCVector fwd(-Cos(m_fRotation), -Sin(m_fRotation), 0.0f);\t// not really forward\n\tCVector right = CrossProduct(up, fwd);\n\tfwd = CrossProduct(up, right);\n\tGetRight() = right;\n\tGetForward() = fwd;\n\tGetUp() = up;\n\n\t// Search light and shooting\n\tif(m_heliStatus == HELI_STATUS_FLY_AWAY || m_heliType == HELI_TYPE_CATALINA || CCullZones::PlayerNoRain())\n\t\tm_fSearchLightIntensity = 0.0f;\n\telse {\n\t\t// Update search light history once every 1000ms\n\t\tint timeDiff = CTimer::GetTimeInMilliseconds() - m_nSearchLightTimer;\n\t\twhile (timeDiff > 1000) {\n\t\t\tfor (i = 5; i > 0; i--) {\n\t\t\t\tm_aSearchLightHistoryX[i] = m_aSearchLightHistoryX[i - 1];\n\t\t\t\tm_aSearchLightHistoryY[i] = m_aSearchLightHistoryY[i - 1];\n\t\t\t}\n\t\t\tm_aSearchLightHistoryX[0] = FindPlayerCoors().x + FindPlayerSpeed().x * 50.0f * (m_nHeliId + 2);\n\t\t\tm_aSearchLightHistoryY[0] = FindPlayerCoors().y + FindPlayerSpeed().y * 50.0f * (m_nHeliId + 2);\n\n\t\t\ttimeDiff -= 1000;\n\t\t\tm_nSearchLightTimer += 1000;\n\t\t}\n\t\tassert(timeDiff <= 1000);\n\t\tfloat f1 = timeDiff / 1000.0f;\n\t\tfloat f2 = 1.0f - f1;\n\t\tm_fSearchLightX = m_aSearchLightHistoryX[m_nHeliId + 2] * f2 + m_aSearchLightHistoryX[m_nHeliId + 2 - 1] * f1;\n\t\tm_fSearchLightY = m_aSearchLightHistoryY[m_nHeliId + 2] * f2 + m_aSearchLightHistoryY[m_nHeliId + 2 - 1] * f1;\n\n\t\tfloat searchLightDist = (CVector2D(m_fSearchLightX, m_fSearchLightY) - GetPosition()).Magnitude();\n\t\tif (searchLightDist > 60.0f)\n\t\t\tm_fSearchLightIntensity = 0.0f;\n\t\telse if (searchLightDist < 40.0f)\n\t\t\tm_fSearchLightIntensity = 1.0f;\n\t\telse\n\t\t\tm_fSearchLightIntensity = 1.0f - (40.0f - searchLightDist) / (60.0f-40.0f);\n\n\t\tif (m_fSearchLightIntensity < 0.9f || sq(FindPlayerCoors().x - m_fSearchLightX) + sq(FindPlayerCoors().y - m_fSearchLightY) > sq(7.0f))\n\t\t\tm_nShootTimer = CTimer::GetTimeInMilliseconds();\n\t\telse if (CTimer::GetTimeInMilliseconds() > m_nPoliceShoutTimer) {\n\t\t\tDMAudio.PlayOneShot(m_audioEntityId, SOUND_PED_HELI_PLAYER_FOUND, 0.0f);\n\t\t\tm_nPoliceShoutTimer = CTimer::GetTimeInMilliseconds() + 4500 + (CGeneral::GetRandomNumber() & 0xFFF);\n\t\t}\n#ifdef FIX_BUGS\n\t\tif (!CReplay::IsPlayingBack())\n#endif\n\t\t{\n\t\t\t// Shoot\n\t\t\tint shootTimeout;\n\t\t\tif (m_heliType == HELI_TYPE_RANDOM) {\n\t\t\t\tswitch (FindPlayerPed()->m_pWanted->GetWantedLevel()) {\n\t\t\t\tcase 0:\n\t\t\t\tcase 1:\n\t\t\t\tcase 2: shootTimeout = 999999; break;\n\t\t\t\tcase 3: shootTimeout = 10000; break;\n\t\t\t\tcase 4: shootTimeout = 5000; break;\n\t\t\t\tcase 5: shootTimeout = 3500; break;\n\t\t\t\tcase 6: shootTimeout = 2000; break;\n\t\t\t\t}\n\t\t\t\tif (CCullZones::NoPolice())\n\t\t\t\t\tshootTimeout /= 2;\n\t\t\t}\n\t\t\telse\n\t\t\t\tshootTimeout = 1500;\n\n\t\t\tif (FindPlayerPed()->m_pWanted->IsIgnored())\n\t\t\t\tm_nShootTimer = CTimer::GetTimeInMilliseconds();\n\t\t\telse {\n\t\t\t\t// Check if line of sight is clear\n\t\t\t\tif (CTimer::GetTimeInMilliseconds() > m_nShootTimer + shootTimeout &&\n\t\t\t\t\tCTimer::GetPreviousTimeInMilliseconds() <= m_nShootTimer + shootTimeout) {\n\t\t\t\t\tif (CWorld::GetIsLineOfSightClear(GetPosition(), FindPlayerCoors(), true, false, false, false, false, false)) {\n\t\t\t\t\t\tif (m_heliStatus == HELI_STATUS_HOVER2)\n\t\t\t\t\t\t\tm_heliStatus = HELI_STATUS_HOVER;\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tm_nShootTimer = CTimer::GetTimeInMilliseconds();\n\t\t\t\t\t\tif (m_heliStatus == HELI_STATUS_HOVER)\n\t\t\t\t\t\t\tm_heliStatus = HELI_STATUS_HOVER2;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Shoot!\n\t\t\t\tif (CTimer::GetTimeInMilliseconds() > m_nShootTimer + shootTimeout &&\n\t\t\t\t\tCTimer::GetTimeInMilliseconds() > m_nLastShotTime + 200) {\n\t\t\t\t\tCVector shotTarget = FindPlayerCoors();\n\t\t\t\t\t// some inaccuracy\n\t\t\t\t\tshotTarget.x += ((CGeneral::GetRandomNumber() & 0xFF) - 128) / 50.0f;\n\t\t\t\t\tshotTarget.y += ((CGeneral::GetRandomNumber() & 0xFF) - 128) / 50.0f;\n\t\t\t\t\tCVector direction = FindPlayerCoors() - GetPosition();\n\t\t\t\t\tdirection.Normalise();\n\t\t\t\t\tshotTarget += 3.0f * direction;\n\t\t\t\t\tCVector shotSource = GetPosition();\n\t\t\t\t\tshotSource += 3.0f * direction;\n\t\t\t\t\tFireOneInstantHitRound(&shotSource, &shotTarget, 20);\n\t\t\t\t\tDMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_SHOT_FIRED, 0.0f);\n\t\t\t\t\tm_nLastShotTime = CTimer::GetTimeInMilliseconds();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Process ropes\n\tfor(i = 0; i < 4; i++){\n\t\tif(m_aSwatState[i] == 0)\n\t\t\tcontinue;\n\n\t\tm_aSwatState[i]--;\n\t\tCRopes::RegisterRope((uintptr)this + i, GetMatrix()*FindSwatPositionRelativeToHeli(i), false);\n\t\tif(m_aSwatState[i] == 0){\n\t\t\tCVector speed = Multiply3x3(GetMatrix(), 0.05f*FindSwatPositionRelativeToHeli(i));\n\t\t\tspeed.z = 0.0f;\n\t\t\tCRopes::SetSpeedOfTopNode((uintptr)this + i, speed);\n\t\t}\n\t}\n\n\tRemoveAndAdd();\n\tbIsInSafePosition = true;\n\tGetMatrix().UpdateRW();\n\tUpdateRwFrame();\n}\n\nvoid\nCHeli::PreRender(void)\n{\n\tfloat radius = (GetPosition().z - FindPlayerCoors().z - 10.0f - 1.0f) * 0.3f + 10.0f;\n\tHeliDustGenerate(this, radius, FindPlayerCoors().z, Max(16.0f - 4.0f*CTimer::GetTimeStep(), 2.0f));\n\tCShadows::StoreShadowForVehicle(this, VEH_SHD_TYPE_HELI);\n}\n\nvoid\nCHeli::Render(void)\n{\n\tCMatrix mat;\n\tCVector pos;\n\n\tmat.Attach(RwFrameGetMatrix(m_aHeliNodes[HELI_TOPROTOR]));\n\tpos = mat.GetPosition();\n\tmat.SetRotateZ(m_fRotorRotation);\n\tmat.Translate(pos);\n\tmat.UpdateRW();\n\n\tm_fRotorRotation += 3.14f/6.5f;\n\tif(m_fRotorRotation > 6.28f)\n\t\tm_fRotorRotation -= 6.28f;\n\n\tmat.Attach(RwFrameGetMatrix(m_aHeliNodes[HELI_BACKROTOR]));\n\tpos = mat.GetPosition();\n\tmat.SetRotateX(m_fRotorRotation);\n\tmat.Translate(pos);\n\tmat.UpdateRW();\n\n\tCEntity::Render();\n}\n\nvoid\nCHeli::PreRenderAlways(void)\n{\n\tCVector shadowPos(m_fSearchLightX, m_fSearchLightY, GetPosition().z);\n\tif(m_fSearchLightIntensity > 0.0f){\n\t\tCShadows::StoreShadowToBeRendered(SHADOWTYPE_ADDITIVE, gpShadowExplosionTex, &shadowPos,\n\t\t\t6.0f, 0.0f, 0.0f, -6.0f,\n\t\t\t80*m_fSearchLightIntensity, 80*m_fSearchLightIntensity, 80*m_fSearchLightIntensity, 80*m_fSearchLightIntensity,\n\t\t\t50.0f, true, 1.0f, nil, false);\n\n\t\tCVector front = GetMatrix() * CVector(0.0f, 7.0f, 0.0f);\n\t\tCVector toPlayer = FindPlayerCoors() - front;\n\t\ttoPlayer.Normalise();\n\t\tfloat intensity = m_fSearchLightIntensity*sq(CTimeCycle::GetSpriteBrightness());\n\t\tif(DotProduct(toPlayer, TheCamera.GetForward()) < -0.8f)\n\t\t\tCCoronas::RegisterCorona((uintptr)this, 255*intensity, 255*intensity, 255*intensity, 255,\n\t\t\t\tfront, 10.0f, 60.0f, CCoronas::TYPE_STAR,\n\t\t\t\tCCoronas::FLARE_HEADLIGHTS, CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);\n\t\telse\n\t\t\tCCoronas::RegisterCorona((uintptr)this, 200*intensity, 200*intensity, 200*intensity, 255,\n\t\t\t\tfront, 8.0f, 60.0f, CCoronas::TYPE_STAR,\n\t\t\t\tCCoronas::FLARE_HEADLIGHTS, CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);\n\t}\n\n\tCVector back = GetMatrix() * CVector(0.0f, -9.0f, 0.0f);\n\tif(CTimer::GetTimeInMilliseconds() & 0x100)\n\t\tCCoronas::RegisterCorona((uintptr)this + 2, 255, 0, 0, 255,\n\t\t\tback, 1.0f, 60.0f, CCoronas::TYPE_STAR,\n\t\t\tCCoronas::FLARE_NONE, CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);\n\telse\n\t\tCCoronas::RegisterCorona((uintptr)this + 2, 0, 0, 0, 255,\n\t\t\tback, 1.0f, 60.0f, CCoronas::TYPE_STAR,\n\t\t\tCCoronas::FLARE_NONE, CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);\n}\n\nRwObject*\nGetHeliAtomicObjectCB(RwObject *object, void *data)\n{\n\tRpAtomic *atomic = (RpAtomic*)object;\n\tassert(RwObjectGetType(object) == rpATOMIC);\n\tif(RpAtomicGetFlags(atomic) & rpATOMICRENDER)\n\t\t*(RpAtomic**)data = atomic;\n\treturn object;\n}\n\nCObject*\nCHeli::SpawnFlyingComponent(int32 component)\n{\n\tRpAtomic *atomic;\n\tRwFrame *frame;\n\tRwMatrix *matrix;\n\tCObject *obj;\n\n\tif(m_aHeliNodes[component] == nil)\n\t\treturn nil;\n\n\tatomic = nil;\n\tRwFrameForAllObjects(m_aHeliNodes[component], GetHeliAtomicObjectCB, &atomic);\n\tif(atomic == nil)\n\t\treturn nil;\n\n\tobj = new CObject;\n\tif(obj == nil)\n\t\treturn nil;\n\n\tobj->SetModelIndexNoCreate(MI_CAR_WHEEL);\n\t// object needs base model\n\tobj->RefModelInfo(GetModelIndex());\n\n\t// create new atomic\n\tmatrix = RwFrameGetLTM(m_aHeliNodes[component]);\n\tframe = RwFrameCreate();\n\tatomic = RpAtomicClone(atomic);\n\t*RwFrameGetMatrix(frame) = *matrix;\n\tRpAtomicSetFrame(atomic, frame);\n\tCVisibilityPlugins::SetAtomicRenderCallback(atomic, nil);\n\tobj->AttachToRwObject((RwObject*)atomic);\n\tobj->bDontStream = true;\n\n\t// init object\n\tobj->m_fMass = 10.0f;\n\tobj->m_fTurnMass = 25.0f;\n\tobj->m_fAirResistance = 0.99f;\n\tobj->m_fElasticity = 0.1f;\n\tobj->m_fBuoyancy = obj->m_fMass*GRAVITY/0.75f;\n\tobj->ObjectCreatedBy = TEMP_OBJECT;\n\tobj->SetIsStatic(false);\n\tobj->bIsPickup = false;\n\n\t// life time\n\tCObject::nNoTempObjects++;\n\tif(component == HELI_TOPROTOR)\n\t\tobj->m_nEndOfLifeTime = CTimer::GetTimeInMilliseconds() + 1000;\n\telse\n\t\tobj->m_nEndOfLifeTime = CTimer::GetTimeInMilliseconds() + 3000;\n\n\tobj->m_vecMoveSpeed = m_vecMoveSpeed;\n\tif(obj->m_vecMoveSpeed.z > 0.0f)\n\t\tobj->m_vecMoveSpeed.z = 0.3f;\n\telse\n\t\tobj->m_vecMoveSpeed.z = 0.0f;\n\n\tobj->m_vecTurnSpeed = m_vecTurnSpeed*2.0f;\n\n\tif(component == HELI_BACKROTOR)\n\t\tobj->m_vecTurnSpeed.x = 0.5f;\n\telse if(component == HELI_TOPROTOR || component == HELI_TOPKNOT)\n\t\tobj->m_vecTurnSpeed.z = 0.5f;\n\telse\n\t\tobj->m_vecTurnSpeed.y = 0.5f;\n\n\tobj->bRenderScorched = true;\n\n\tCWorld::Add(obj);\n\n\tatomic = nil;\n\tRwFrameForAllObjects(m_aHeliNodes[component], GetHeliAtomicObjectCB, &atomic);\n\tif(atomic)\n\t\tRpAtomicSetFlags(atomic, 0);\n\n\treturn obj;\n}\n\nCVector\nCHeli::FindSwatPositionRelativeToHeli(int n)\n{\n\tswitch(n){\n\tcase 0: return CVector(-1.2f, -1.0f, -0.5f);\n\tcase 1: return CVector( 1.2f, -1.0f, -0.5f);\n\tcase 2: return CVector(-1.2f,  1.0f, -0.5f);\n\tcase 3: return CVector( 1.2f,  1.0f, -0.5f);\n\tdefault: return CVector(0.0f, 0.0f, 0.0f);\n\t}\n}\n\nbool\nCHeli::SendDownSwat(void)\n{\n\tif(m_numSwat == 0 || !CStreaming::HasModelLoaded(MI_SWAT) ||\n\t   CGeneral::GetRandomNumber() & 0x7F || (GetPosition() - FindPlayerCoors()).Magnitude() > 50.0f)\n\t\treturn false;\n\n\tCMatrix mat(GetMatrix());\n\tCVector pos = Multiply3x3(mat, FindSwatPositionRelativeToHeli(m_numSwat-1)) + GetPosition();\n\n\tfloat groundZ = CWorld::FindGroundZFor3DCoord(pos.x, pos.y, pos.z, nil);\n\tif(Abs(FindPlayerCoors().z - groundZ) < 2.5f && CRopes::RegisterRope((uintptr)this + m_numSwat-1, pos, false)){\n\t\tCCopPed *swat = (CCopPed*)CPopulation::AddPed(PEDTYPE_COP, COP_HELI_SWAT, pos);\n\t\tswat->bUsesCollision = false;\n\t\tswat->m_pRopeEntity = this;\n\t\tRegisterReference(&swat->m_pRopeEntity);\n\t\tm_numSwat--;\n\t\tswat->m_nRopeID = (uintptr)this + m_numSwat;\n\t\tm_aSwatState[m_numSwat] = 255;\n\t\tCAnimManager::BlendAnimation(swat->GetClump(), ASSOCGRP_STD, ANIM_STD_ABSEIL, 4.0f);\n\t\treturn true;\n\t}\n\treturn false;\n}\n\n\nvoid\nCHeli::InitHelis(void)\n{\n\tint i;\n\n\tNumRandomHelis = 0;\n\tTestForNewRandomHelisTimer = 0;\n\tCatalinaHeliOn = false;\n\tScriptHeliOn = false;\n\tfor(i = 0; i < NUM_HELIS; i++)\n\t\tpHelis[i] = nil;\n\n\t((CVehicleModelInfo*)CModelInfo::GetModelInfo(MI_CHOPPER))->SetColModel(&CTempColModels::ms_colModelPed1);\n}\n\nCHeli*\nCHeli::GenerateHeli(bool catalina)\n{\n\tCHeli *heli;\n\tCVector heliPos;\n\tint i;\n\n\tif(catalina)\n\t\tassert(0 && \"can't create catalina's heli\");\n\telse\n\t\theli = new CHeli(MI_CHOPPER, PERMANENT_VEHICLE);\n\n\tif(catalina)\n\t\theliPos = CVector(-224.0f, 201.0f, 83.0f);\n\telse{\n\t\theliPos = FindPlayerCoors();\n\t\tfloat angle = (float)(CGeneral::GetRandomNumber() & 0xFF)/0x100 * 6.28f;\n\t\theliPos.x += 250.0f*Sin(angle);\n\t\theliPos.y += 250.0f*Cos(angle);\n\t\tif(heliPos.x < -2000.0f-400.0f || heliPos.x > 2000.0f-400.0f || heliPos.y < -2000.0f || heliPos.y > 2000.0f){\n\t\t\theliPos = FindPlayerCoors();\n\t\t\theliPos.x -= 250.0f*Sin(angle);\n\t\t\theliPos.y -= 250.0f*Cos(angle);\n\t\t}\n\t\theliPos.z += 50.0f;\n\t}\n\theli->GetMatrix().SetTranslate(heliPos);\n\tif(catalina)\n\t\theli->GetMatrix().SetRotateZOnly(DEGTORAD(270.0f));\t// game actually uses 3.14 here\n\n\theli->SetStatus(STATUS_ABANDONED);\n\theli->bIsLocked = true;\n\n\tint id = -1;\n\tbool found = false;\n\twhile(!found){\n\t\tid++;\n\t\tfound = true;\n\t\tfor(i = 0; i < 4; i++)\n\t\t\tif(pHelis[i] && pHelis[i]->m_nHeliId == id)\n\t\t\t\tfound = false;\n\t}\n\theli->m_nHeliId = id;\n\n\tCWorld::Add(heli);\n\n\treturn heli;\n}\n\nvoid\nCHeli::UpdateHelis(void)\n{\n\tint i, j;\n\n\t// Spawn new police helis\n\tint numHelisRequired = \n#ifdef FIX_BUGS\n\t\tCReplay::IsPlayingBack() ? 0 :\n#endif\n\t\tFindPlayerPed()->m_pWanted->NumOfHelisRequired();\n\tif(CCullZones::PlayerNoRain() || CGame::IsInInterior())\n\t\tnumHelisRequired = 0;\n\tif(CStreaming::HasModelLoaded(MI_CHOPPER) && CTimer::GetTimeInMilliseconds() > TestForNewRandomHelisTimer){\n\t\t// Spawn a police heli\n\t\tTestForNewRandomHelisTimer = CTimer::GetTimeInMilliseconds() + 15000;\n\t\tif(NumRandomHelis < numHelisRequired){\n\t\t\tNumRandomHelis++;\n\t\t\tCHeli *heli = GenerateHeli(false);\n\t\t\theli->m_heliType = HELI_TYPE_RANDOM;\n\t\t\tif(pHelis[HELI_RANDOM0] == nil)\n\t\t\t\tpHelis[HELI_RANDOM0] = heli;\n\t\t\telse if(pHelis[HELI_RANDOM1] == nil)\n\t\t\t\tpHelis[HELI_RANDOM1] = heli;\n\t\t\telse\n\t\t\t\tassert(0 && \"too many helis\");\n\t\t}\n\t}\n\n\t// Handle script heli\n\tif(ScriptHeliOn){\n\t\tif(CStreaming::HasModelLoaded(MI_CHOPPER) && pHelis[HELI_SCRIPT] == nil){\n\t\t\tpHelis[HELI_SCRIPT] = GenerateHeli(false);\n\t\t\tpHelis[HELI_SCRIPT]->m_heliType = HELI_TYPE_SCRIPT;\n\t\t}else\n\t\t\tCStreaming::RequestModel(MI_CHOPPER, 0);\n\t}else{\n\t\tif(pHelis[HELI_SCRIPT])\n\t\t\tpHelis[HELI_SCRIPT]->m_heliStatus = HELI_STATUS_FLY_AWAY;\n\t}\n\n\t// Delete helis that we no longer need\n\tfor(i = 0; i < NUM_HELIS; i++)\n\t\tif(pHelis[i] && pHelis[i]->m_heliStatus == HELI_STATUS_FLY_AWAY && pHelis[i]->GetPosition().z > 150.0f){\n\t\t\tCWorld::Remove(pHelis[i]);\n\t\t\tdelete pHelis[i];\n\t\t\tpHelis[i] = nil;\n\t\t\tif(i != HELI_SCRIPT && i != HELI_CATALINA)\n\t\t\t\tNumRandomHelis--;\n\t\t}\n\n\t// Handle explosions\n\tfor(i = 0; i < NUM_HELIS; i++){\n\t\tif(pHelis[i] && pHelis[i]->m_heliStatus == HELI_STATUS_SHOT_DOWN && CTimer::GetTimeInMilliseconds() > pHelis[i]->m_nExplosionTimer){\n\t\t\t// Second part of explosion\n\t\t\tstatic int nFrameGen;\n\t\t\tCRGBA colors[8];\n\n\t\t\tTheCamera.CamShake(0.7f, pHelis[i]->GetPosition().x, pHelis[i]->GetPosition().y, pHelis[i]->GetPosition().z);\n\n\t\t\tcolors[0] = CRGBA(0, 0, 0, 255);\n\t\t\tcolors[1] = CRGBA(224, 224, 224, 255);\n\t\t\tcolors[2] = CRGBA(0, 0, 0, 255);\n\t\t\tcolors[3] = CRGBA(0, 0, 0, 255);\n\t\t\tcolors[4] = CRGBA(66, 162, 252, 255);\n\t\t\tcolors[5] = CRGBA(0, 0, 0, 255);\n\t\t\tcolors[6] = CRGBA(0, 0, 0, 255);\n\t\t\tcolors[7] = CRGBA(0, 0, 0, 255);\n\n\t\t\tCVector pos = pHelis[i]->GetPosition();\n\t\t\tCVector dir;\n\t\t\tfor(j = 0; j < 40; j++){\n\t\t\t\tdir.x = CGeneral::GetRandomNumberInRange(-2.0f, 2.0f);\n\t\t\t\tdir.y = CGeneral::GetRandomNumberInRange(-2.0f, 2.0f);\n\t\t\t\tdir.z = CGeneral::GetRandomNumberInRange(0.0f, 2.0f);\n\t\t\t\tint rotSpeed = CGeneral::GetRandomNumberInRange(10, 30);\n\t\t\t\tif(CGeneral::GetRandomNumber() & 1)\n\t\t\t\t\trotSpeed = -rotSpeed;\n\t\t\t\tint f = ++nFrameGen & 3;\n\t\t\t\tCParticle::AddParticle(PARTICLE_HELI_DEBRIS, pos, dir,\n\t\t\t\t\tnil, CGeneral::GetRandomNumberInRange(0.1f, 1.0f),\n\t\t\t\t\tcolors[nFrameGen&7], rotSpeed, 0, f, 0);\n\t\t\t}\n\n\t\t\tCExplosion::AddExplosion(nil, nil, EXPLOSION_HELI, pos, 0);\n\n\t\t\tpHelis[i]->SpawnFlyingComponent(HELI_SKID_LEFT);\n\t\t\tpHelis[i]->SpawnFlyingComponent(HELI_SKID_RIGHT);\n\t\t\tpHelis[i]->SpawnFlyingComponent(HELI_TOPROTOR);\n\n\t\t\tCDarkel::RegisterCarBlownUpByPlayer(pHelis[i]);\n\t\t\tCWorld::Remove(pHelis[i]);\n\t\t\tdelete pHelis[i];\n\t\t\tpHelis[i] = nil;\n\t\t\tif(i != HELI_SCRIPT && i != HELI_CATALINA)\n\t\t\t\tNumRandomHelis--;\n\t\t\tif(i == HELI_CATALINA)\n\t\t\t\tCatalinaHasBeenShotDown = true;\n\n\t\t\tCStats::PeopleKilledByPlayer += 2;\n\t\t\tCStats::PedsKilledOfThisType[PEDTYPE_COP] += 2;\n\t\t\tCWorld::Players[CWorld::PlayerInFocus].m_nMoney += 250;\n\t\t\tpos = CWorld::Players[CWorld::PlayerInFocus].m_pPed->GetPosition();\n\t\t\tCWorld::Players[CWorld::PlayerInFocus].m_pPed->m_pWanted->RegisterCrime_Immediately(CRIME_SHOOT_HELI,\n\t\t\t\tpos, i + 19843, false);\n\n\t\t\tTestForNewRandomHelisTimer = CTimer::GetTimeInMilliseconds() + 50000;\n\t\t}else if(pHelis[i] && pHelis[i]->m_heliStatus == HELI_STATUS_SHOT_DOWN && CTimer::GetTimeInMilliseconds()+7000 > pHelis[i]->m_nExplosionTimer){\n\t\t\t// First part of explosion\n\t\t\tif(CTimer::GetPreviousTimeInMilliseconds()+7000 < pHelis[i]->m_nExplosionTimer){\n\t\t\t\tpHelis[i]->SpawnFlyingComponent(HELI_BACKROTOR);\n\t\t\t\tpHelis[i]->SpawnFlyingComponent(HELI_TAIL);\n\t\t\t\tpHelis[i]->m_fAngularSpeed *= -2.5f;\n\t\t\t\tpHelis[i]->bRenderScorched = true;\n\n\t\t\t\tTheCamera.CamShake(0.4f, pHelis[i]->GetPosition().x, pHelis[i]->GetPosition().y, pHelis[i]->GetPosition().z);\n\n\t\t\t\tCVector pos = pHelis[i]->GetPosition() - 2.5f*pHelis[i]->GetForward();\n\t\t\t\tCExplosion::AddExplosion(nil, nil, EXPLOSION_HELI2, pos, 0);\n\t\t\t}else\n\t\t\t\tpHelis[i]->m_fAngularSpeed *= 1.03f;\n\t\t}\n\t}\n\n\t// Find police helis to remove\n\tfor(i = 0; i < 2; i++)\n\t\tif(pHelis[i] && pHelis[i]->m_heliStatus != HELI_STATUS_FLY_AWAY){\n\t\t\tif(numHelisRequired > 0)\n\t\t\t\tnumHelisRequired--;\n\t\t\telse\n\t\t\t\tpHelis[i]->m_heliStatus = HELI_STATUS_FLY_AWAY;\n\t\t}\n\n\t// Remove all helis if in a tunnel or under water\n\tif(FindPlayerCoors().z < - 2.0f)\n\t\tfor(i = 0; i < NUM_HELIS; i++)\n\t\t\tif(pHelis[i] && pHelis[i]->m_heliStatus != HELI_STATUS_SHOT_DOWN)\n\t\t\t\tpHelis[i]->m_heliStatus = HELI_STATUS_FLY_AWAY;\n}\n\nvoid\nCHeli::SpecialHeliPreRender(void)\n{\n\tint i;\n\tfor(i = 0; i < NUM_HELIS; i++)\n\t\tif(pHelis[i])\n\t\t\tpHelis[i]->PreRenderAlways();\n}\n\nbool\nCHeli::TestRocketCollision(CVector *rocketPos)\n{\n\tint i;\n\tbool hit = false;\n\n\tfor(i = 0; i < NUM_HELIS; i++){\n\t\tif(pHelis[i] && !pHelis[i]->bExplosionProof && (*rocketPos - pHelis[i]->GetPosition()).MagnitudeSqr() < sq(8.0f)){\n\t\t\tpHelis[i]->m_fAngularSpeed = CGeneral::GetRandomTrueFalse() ? 0.05f : -0.05f;\n\t\t\tpHelis[i]->m_heliStatus = HELI_STATUS_SHOT_DOWN;\n\t\t\tpHelis[i]->m_nExplosionTimer = CTimer::GetTimeInMilliseconds() + 10000;\n\t\t\thit = true;\n\t\t}\n\t}\n\treturn hit;\n}\n\nbool\nCHeli::TestBulletCollision(CVector *line0, CVector *line1, CVector *bulletPos, int32 damage)\n{\n\tint i;\n\tbool hit = false;\n\n\tfor(i = 0; i < NUM_HELIS; i++)\n\t\tif(pHelis[i] && !pHelis[i]->bBulletProof && CCollision::DistToLine(line0, line1, &pHelis[i]->GetPosition()) < 5.0f){\n\t\t\t// Find bullet position\n\t\t\tfloat distToHeli = (pHelis[i]->GetPosition() - *line0).Magnitude();\n\t\t\tCVector line = (*line1 - *line0);\n\t\t\tfloat lineLength = line.Magnitude();\n\t\t\t*bulletPos = *line0 + line*Max(1.0f, distToHeli-5.0f)/lineLength;\n\n\t\t\tpHelis[i]->m_nBulletDamage += damage;\n\n\t\t\tif(pHelis[i]->m_heliType == HELI_CATALINA && pHelis[i]->m_nBulletDamage > 400 ||\n\t\t\t   pHelis[i]->m_heliType != HELI_CATALINA && pHelis[i]->m_nBulletDamage > 700){\n\t\t\t\tpHelis[i]->m_fAngularSpeed = CGeneral::GetRandomTrueFalse() ? 0.05f : -0.05f;\n\t\t\t\tpHelis[i]->m_heliStatus = HELI_STATUS_SHOT_DOWN;\n\t\t\t\tpHelis[i]->m_nExplosionTimer = CTimer::GetTimeInMilliseconds() + 10000;\n\t\t\t}\n\n\t\t\thit = true;\n\t\t}\n\treturn hit;\n}\n\nbool\nCHeli::TestSniperCollision(CVector *line0, CVector *line1)\n{\n\tint i;\n\tbool hit = false;\n\n\tfor(i = 0; i < NUM_HELIS; i++){\n\t\tif(pHelis[i] && !pHelis[i]->bBulletProof) {\n\t\t\tCVector pilotPos = pHelis[i]->GetMatrix() * CVector(-0.43f, 1.49f, 1.5f);\n\t\t\tif(CCollision::DistToLine(line0, line1, &pilotPos) < 0.8f){\n\t\t\t\tpHelis[i]->m_fAngularSpeed = CGeneral::GetRandomTrueFalse() ? 0.05f : -0.05f;\n\t\t\t\tpHelis[i]->m_heliStatus = HELI_STATUS_SHOT_DOWN;\n\t\t\t\tpHelis[i]->m_nExplosionTimer = CTimer::GetTimeInMilliseconds() + 9999999;\n\t\t\t\tpHelis[i]->m_numSwat = 0;\n\n\t\t\t\thit = true;\n\t\t\t}\n\t\t}\n\t}\n\treturn hit;\n}\n\nvoid CHeli::StartCatalinaFlyBy(void)\n{\n\tCatalinaHeliOn = true;\n\tCatalinaHasBeenShotDown = false;\n}\n\nvoid\nCHeli::RemoveCatalinaHeli(void)\n{\n\tCatalinaHeliOn = false;\n\tif(pHelis[HELI_CATALINA]){\n\t\tCWorld::Remove(pHelis[HELI_CATALINA]);\n\t\tdelete pHelis[HELI_CATALINA];\n\t\tpHelis[HELI_CATALINA] = nil;\n\t}\n}\n\nCHeli *CHeli::FindPointerToCatalinasHeli(void) { return pHelis[HELI_CATALINA]; }\nvoid CHeli::CatalinaTakeOff(void) { pHelis[HELI_CATALINA]->m_pathState = 8; }\nvoid CHeli::MakeCatalinaHeliFlyAway(void) { pHelis[HELI_CATALINA]->m_pathState = 12; }\nbool CHeli::HasCatalinaBeenShotDown(void) { return CatalinaHasBeenShotDown; }\n\nvoid CHeli::ActivateHeli(bool activate) { ScriptHeliOn = activate; }\n"
  },
  {
    "path": "src/vehicles/Heli.h",
    "content": "#pragma once\n\n#include \"Vehicle.h\"\n\nclass CObject;\n\nenum eHeliNodes\n{\n\tHELI_CHASSIS = 1,\n\tHELI_TOPROTOR,\n\tHELI_BACKROTOR,\n\tHELI_TAIL,\n\tHELI_TOPKNOT,\n\tHELI_SKID_LEFT,\n\tHELI_SKID_RIGHT,\n\tNUM_HELI_NODES\n};\n\nenum\n{\n\tHELI_RANDOM0,\n\tHELI_RANDOM1,\n\tHELI_SCRIPT,\n\tHELI_CATALINA,\t// TODO 2 in VC\n\tNUM_HELIS\n};\n\nenum\n{\n\tHELI_TYPE_RANDOM,\n\tHELI_TYPE_SCRIPT,\n\tHELI_TYPE_CATALINA,\n};\n\n\nclass CHeli : public CVehicle\n{\npublic:\n\tRwFrame *m_aHeliNodes[NUM_HELI_NODES];\n\tint8 m_heliStatus;\n\tfloat m_fSearchLightX;\n\tfloat m_fSearchLightY;\n\tuint32 m_nExplosionTimer;\n\tfloat m_fRotation;\n\tfloat m_fAngularSpeed;\n\tfloat m_fTargetZ;\n\tfloat m_fSearchLightIntensity;\n\tint8 m_nHeliId;\n\tint8 m_heliType;\n\tint8 m_pathState;\n\tint8 m_numSwat;\n\tuint8 m_aSwatState[4];\n\tfloat m_aSearchLightHistoryX[6];\n\tfloat m_aSearchLightHistoryY[6];\n\tuint32 m_nSearchLightTimer;\n\tuint32 m_nShootTimer;\n\tuint32 m_nLastShotTime;\n\tuint32 m_nBulletDamage;\n\tfloat m_fRotorRotation;\n\tfloat m_fHeliDustZ[8];\n\tuint32 m_nPoliceShoutTimer;\n\tfloat m_fTargetOffset;\n\tbool m_bTestRight;\n\n\tstatic CHeli *pHelis[NUM_HELIS];\n\tstatic int16 NumRandomHelis;\n\tstatic uint32 TestForNewRandomHelisTimer;\n\tstatic bool CatalinaHeliOn;\n\tstatic bool CatalinaHasBeenShotDown;\n\tstatic bool ScriptHeliOn;\n\n\tCHeli(int32 id, uint8 CreatedBy);\n\n\t// from CEntity\n\tvoid SetModelIndex(uint32 id);\n\tvoid ProcessControl(void);\n\tvoid PreRender(void);\n\tvoid Render(void);\n\n\tvoid PreRenderAlways(void);\n\tCObject *SpawnFlyingComponent(int32 component);\n\tCVector FindSwatPositionRelativeToHeli(int n);\n\tbool SendDownSwat(void);\n\n\tstatic void InitHelis(void);\n\tstatic CHeli *GenerateHeli(bool catalina); // out of class in III PC and later because of SecuROM\n\tstatic void UpdateHelis(void);\n\tstatic void SpecialHeliPreRender(void);\n\tstatic bool TestRocketCollision(CVector *coors);\n\tstatic bool TestBulletCollision(CVector *line0, CVector *line1, CVector *bulletPos, int32 damage);\n\tstatic bool TestSniperCollision(CVector *line0, CVector *line1);\n\n\tstatic void StartCatalinaFlyBy(void); // out of class in III PC and later because of SecuROM\n\tstatic void RemoveCatalinaHeli(void);\n\tstatic CHeli *FindPointerToCatalinasHeli(void);\n\tstatic void CatalinaTakeOff(void);\n\tstatic void MakeCatalinaHeliFlyAway(void);\n\tstatic bool HasCatalinaBeenShotDown(void);\n\n\tstatic void ActivateHeli(bool activate);\n};\n"
  },
  {
    "path": "src/vehicles/Plane.cpp",
    "content": "#include \"common.h\"\n#include \"main.h\"\n\n#include \"General.h\"\n#include \"CutsceneMgr.h\"\n#include \"ModelIndices.h\"\n#include \"FileMgr.h\"\n#include \"Streaming.h\"\n#include \"Replay.h\"\n#include \"Camera.h\"\n#include \"DMAudio.h\"\n#include \"Wanted.h\"\n#include \"Coronas.h\"\n#include \"Particle.h\"\n#include \"Explosion.h\"\n#include \"Fluff.h\"\n#include \"World.h\"\n#include \"HandlingMgr.h\"\n#include \"Heli.h\"\n#include \"Plane.h\"\n#include \"MemoryHeap.h\"\n\nCPlaneNode *pPathNodes;\nCPlaneNode *pPath2Nodes;\nCPlaneNode *pPath3Nodes;\nCPlaneNode *pPath4Nodes;\nint32 NumPathNodes;\nint32 NumPath2Nodes;\nint32 NumPath3Nodes;\nint32 NumPath4Nodes;\nfloat TotalLengthOfFlightPath;\nfloat TotalLengthOfFlightPath2;\nfloat TotalLengthOfFlightPath3;\nfloat TotalLengthOfFlightPath4;\nfloat TotalDurationOfFlightPath;\nfloat TotalDurationOfFlightPath2;\nfloat TotalDurationOfFlightPath3;\nfloat TotalDurationOfFlightPath4;\nfloat LandingPoint;\nfloat TakeOffPoint;\nCPlaneInterpolationLine aPlaneLineBits[6];\n\nfloat PlanePathPosition[3];\nfloat OldPlanePathPosition[3];\nfloat PlanePathSpeed[3];\nfloat PlanePath2Position[5];\nfloat PlanePath3Position[4];\nfloat PlanePath2Speed[5];\nfloat PlanePath3Speed[4];\n\n\nenum\n{\n\tCESNA_STATUS_NONE,\t// doesn't even exist\n\tCESNA_STATUS_FLYING,\n\tCESNA_STATUS_DESTROYED,\n\tCESNA_STATUS_LANDED,\n};\n\nint32 CesnaMissionStatus;\nint32 CesnaMissionStartTime;\nCPlane *pDrugRunCesna;\nint32 DropOffCesnaMissionStatus;\nint32 DropOffCesnaMissionStartTime;\nCPlane *pDropOffCesna;\n\nCPlane::CPlane(int32 id, uint8 CreatedBy)\n : CVehicle(CreatedBy)\n{\n\tCVehicleModelInfo *mi = (CVehicleModelInfo*)CModelInfo::GetModelInfo(id);\n\tm_vehType = VEHICLE_TYPE_PLANE;\n\tpHandling = mod_HandlingManager.GetHandlingData((tVehicleType)mi->m_handlingId);\n\tSetModelIndex(id);\n\n\tm_fMass = 100000000.0f;\n\tm_fTurnMass = 100000000.0f;\n\tm_fAirResistance = 0.9994f;\n\tm_fElasticity = 0.05f;\n\n\tbUsesCollision = false;\n\tm_bHasBeenHit = false;\n\tm_bIsDrugRunCesna = false;\n\tm_bIsDropOffCesna = false;\n\tm_bTempPlane = false;\n\n\tSetStatus(STATUS_PLANE);\n\tbIsBIGBuilding = true;\n\tm_level = LEVEL_GENERIC;\n\n\tm_isFarAway = false;\n#ifdef CPLANE_ROTORS\n\tm_fRotorRotation = 0.0f;\n#endif\n}\n\nCPlane::~CPlane()\n{\n\tDeleteRwObject();\n}\n\nvoid\nCPlane::SetModelIndex(uint32 id)\n{\n\tCVehicle::SetModelIndex(id);\n#ifdef CPLANE_ROTORS\n\tint i;\n\tfor(i = 0; i < NUM_PLANE_NODES; i++)\n\t\tm_aPlaneNodes[i] = nil;\n\tif(GetModelIndex() == MI_CHOPPER){\n\t\t// This is surprisingly annoying...\n\t\tRwFrame *heliNodes[NUM_HELI_NODES];\n\t\tfor(i = 0; i < NUM_HELI_NODES; i++)\n\t\t\theliNodes[i] = nil;\n\t\tCClumpModelInfo::FillFrameArray(GetClump(), heliNodes);\n\t\tm_aPlaneNodes[PLANE_TOPROTOR] = heliNodes[HELI_TOPROTOR];\n\t\tm_aPlaneNodes[PLANE_BACKROTOR] = heliNodes[HELI_BACKROTOR];\n\t}else\n\t\tCClumpModelInfo::FillFrameArray(GetClump(), m_aPlaneNodes);\n#endif\n}\n\nvoid\nCPlane::DeleteRwObject(void)\n{\n\tif(m_rwObject && RwObjectGetType(m_rwObject) == rpATOMIC){\n\t\tm_matrix.Detach();\n\t\tif(RwObjectGetType(m_rwObject) == rpATOMIC){\t// useless check\n\t\t\tRwFrame *f = RpAtomicGetFrame((RpAtomic*)m_rwObject);\n\t\t\tRpAtomicDestroy((RpAtomic*)m_rwObject);\n\t\t\tRwFrameDestroy(f);\n\t\t}\n\t\tm_rwObject = nil;\n\t}\n\tCEntity::DeleteRwObject();\n}\n\n// There's a LOT of copy and paste in here. Maybe this could be refactored somehow\nvoid\nCPlane::ProcessControl(void)\n{\n\tint i;\n\tCVector pos;\n\n\tif(CReplay::IsPlayingBack())\n\t\treturn;\n\n\tif(GetModelIndex() == MI_AIRTRAIN){\n\t\tif(GetPosition().z > 100.0f)\n\t\t\tCPlaneTrails::RegisterPoint(GetPosition(), m_nPlaneId);\n\t}else if(GetModelIndex() == MI_DEADDODO)\n\t\tCPlaneBanners::RegisterPoint(GetPosition(), m_nPlaneId);\n\n\t// Explosion\n\tif(m_bHasBeenHit){\n\t\t// BUG: since this is all based on frames, you can skip the explosion processing when you go into the menu\n\t\tif(GetModelIndex() == MI_AIRTRAIN){\n\t\t\tint frm = CTimer::GetFrameCounter() - m_nFrameWhenHit;\n\t\t\tif(frm == 20){\n\t\t\t\tstatic int nFrameGen;\n\t\t\t\tCRGBA colors[8];\n\n\t\t\t\tCExplosion::AddExplosion(nil, FindPlayerPed(), EXPLOSION_HELI, GetMatrix() * CVector(0.0f, 0.0f, 0.0f), 0);\n\n\t\t\t\tcolors[0] = CRGBA(0, 0, 0, 255);\n\t\t\t\tcolors[1] = CRGBA(224, 230, 238, 255);\n\t\t\t\tcolors[2] = CRGBA(224, 230, 238, 255);\n\t\t\t\tcolors[3] = CRGBA(0, 0, 0, 255);\n\t\t\t\tcolors[4] = CRGBA(224, 230, 238, 255);\n\t\t\t\tcolors[5] = CRGBA(0, 0, 0, 255);\n\t\t\t\tcolors[6] = CRGBA(0, 0, 0, 255);\n\t\t\t\tcolors[7] = CRGBA(224, 230, 238, 255);\n\n\t\t\t\tCVector dir;\n\t\t\t\tfor(i = 0; i < 40; i++){\n\t\t\t\t\tdir.x = CGeneral::GetRandomNumberInRange(-2.0f, 2.0f);\n\t\t\t\t\tdir.y = CGeneral::GetRandomNumberInRange(-2.0f, 2.0f);\n\t\t\t\t\tdir.z = CGeneral::GetRandomNumberInRange(0.0f, 2.0f);\n\t\t\t\t\tint rotSpeed = CGeneral::GetRandomNumberInRange(10, 30);\n\t\t\t\t\tif(CGeneral::GetRandomNumber() & 1)\n\t\t\t\t\t\trotSpeed = -rotSpeed;\n\t\t\t\t\tint f = ++nFrameGen & 3;\n\t\t\t\t\tCParticle::AddParticle(PARTICLE_HELI_DEBRIS, GetMatrix() * CVector(0.0f, 0.0f, 0.0f), dir,\n\t\t\t\t\t\tnil, CGeneral::GetRandomNumberInRange(0.1f, 1.0f),\n\t\t\t\t\t\tcolors[nFrameGen&7], rotSpeed, 0, f, 0);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif(frm >= 40 && frm <= 80 && frm & 1){\n\t\t\t\tif(frm & 1){\n\t\t\t\t\tpos.x = ((CGeneral::GetRandomNumber() & 0x3F) - 32) * 0.2f;\n\t\t\t\t\tpos.z = ((CGeneral::GetRandomNumber() & 0x3F) - 32) * 0.2f;\n\t\t\t\t\tpos.y = frm - 40;\n\t\t\t\t\tpos = GetMatrix() * pos;\n\t\t\t\t}else{\n\t\t\t\t\tpos.x = ((CGeneral::GetRandomNumber() & 0x3F) - 32) * 0.2f;\n\t\t\t\t\tpos.z = ((CGeneral::GetRandomNumber() & 0x3F) - 32) * 0.2f;\n\t\t\t\t\tpos.y = 40 - frm;\n\t\t\t\t\tpos = GetMatrix() * pos;\n\t\t\t\t}\n\t\t\t\tCExplosion::AddExplosion(nil, FindPlayerPed(), EXPLOSION_HELI, pos, 0);\n\t\t\t}\n\t\t\tif(frm == 60)\n\t\t\t\tbRenderScorched = true;\n\t\t\tif(frm == 82){\n\t\t\t\tTheCamera.SetFadeColour(255, 255, 255);\n\t\t\t\tTheCamera.Fade(0.0f, FADE_OUT);\n\t\t\t\tTheCamera.ProcessFade();\n\t\t\t\tTheCamera.Fade(1.0f, FADE_IN);\n\t\t\t\tFlagToDestroyWhenNextProcessed();\n\t\t\t}\n\t\t}else{\n\t\t\tint frm = CTimer::GetFrameCounter() - m_nFrameWhenHit;\n\t\t\tif(frm == 20){\n\t\t\t\tstatic int nFrameGen;\n\t\t\t\tCRGBA colors[8];\n\n\t\t\t\tCExplosion::AddExplosion(nil, FindPlayerPed(), EXPLOSION_HELI, GetMatrix() * CVector(0.0f, 0.0f, 0.0f), 0);\n\n\t\t\t\tcolors[0] = CRGBA(0, 0, 0, 255);\n\t\t\t\tcolors[1] = CRGBA(224, 230, 238, 255);\n\t\t\t\tcolors[2] = CRGBA(224, 230, 238, 255);\n\t\t\t\tcolors[3] = CRGBA(0, 0, 0, 255);\n\t\t\t\tcolors[4] = CRGBA(252, 66, 66, 255);\n\t\t\t\tcolors[5] = CRGBA(0, 0, 0, 255);\n\t\t\t\tcolors[6] = CRGBA(0, 0, 0, 255);\n\t\t\t\tcolors[7] = CRGBA(252, 66, 66, 255);\n\n\t\t\t\tCVector dir;\n\t\t\t\tfor(i = 0; i < 40; i++){\n\t\t\t\t\tdir.x = CGeneral::GetRandomNumberInRange(-2.0f, 2.0f);\n\t\t\t\t\tdir.y = CGeneral::GetRandomNumberInRange(-2.0f, 2.0f);\n\t\t\t\t\tdir.z = CGeneral::GetRandomNumberInRange(0.0f, 2.0f);\n\t\t\t\t\tint rotSpeed = CGeneral::GetRandomNumberInRange(30.0f, 20.0f);\n\t\t\t\t\tif(CGeneral::GetRandomNumber() & 1)\n\t\t\t\t\t\trotSpeed = -rotSpeed;\n\t\t\t\t\tint f = ++nFrameGen & 3;\n\t\t\t\t\tCParticle::AddParticle(PARTICLE_HELI_DEBRIS, GetMatrix() * CVector(0.0f, 0.0f, 0.0f), dir,\n\t\t\t\t\t\tnil, CGeneral::GetRandomNumberInRange(0.1f, 1.0f),\n\t\t\t\t\t\tcolors[nFrameGen&7], rotSpeed, 0, f, 0);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif(frm >= 40 && frm <= 60 && frm & 1){\n\t\t\t\tif(frm & 1){\n\t\t\t\t\tpos.x = ((CGeneral::GetRandomNumber() & 0x3F) - 32) * 0.1f;\n\t\t\t\t\tpos.z = ((CGeneral::GetRandomNumber() & 0x3F) - 32) * 0.1f;\n\t\t\t\t\tpos.y = (frm - 40)*0.3f;\n\t\t\t\t\tpos = GetMatrix() * pos;\n\t\t\t\t}else{\n\t\t\t\t\tpos.x = ((CGeneral::GetRandomNumber() & 0x3F) - 32) * 0.1f;\n\t\t\t\t\tpos.z = ((CGeneral::GetRandomNumber() & 0x3F) - 32) * 0.1f;\n\t\t\t\t\tpos.y = (40 - frm)*0.3f;\n\t\t\t\t\tpos = GetMatrix() * pos;\n\t\t\t\t}\n\t\t\t\tCExplosion::AddExplosion(nil, FindPlayerPed(), EXPLOSION_HELI, pos, 0);\n\t\t\t}\n\t\t\tif(frm == 30)\n\t\t\t\tbRenderScorched = true;\n\t\t\tif(frm == 62){\n\t\t\t\tTheCamera.SetFadeColour(200, 200, 200);\n\t\t\t\tTheCamera.Fade(0.0f, FADE_OUT);\n\t\t\t\tTheCamera.ProcessFade();\n\t\t\t\tTheCamera.Fade(1.0f, FADE_IN);\n\t\t\t\tif(m_bIsDrugRunCesna){\n\t\t\t\t\tCesnaMissionStatus = CESNA_STATUS_DESTROYED;\n\t\t\t\t\tpDrugRunCesna = nil;\n\t\t\t\t}\n\t\t\t\tif(m_bIsDropOffCesna){\n\t\t\t\t\tDropOffCesnaMissionStatus = CESNA_STATUS_DESTROYED;\n\t\t\t\t\tpDropOffCesna = nil;\n\t\t\t\t}\n\t\t\t\tFlagToDestroyWhenNextProcessed();\n\t\t\t}\n\t\t}\n\t}\n\n\t// Update plane position and speed\n\tif(GetModelIndex() == MI_AIRTRAIN || !m_isFarAway || ((CTimer::GetFrameCounter() + m_randomSeed) & 7) == 0){\n\t\tif(GetModelIndex() == MI_AIRTRAIN){\n\t\t\tfloat pathPositionRear = PlanePathPosition[m_nPlaneId] - 30.0f;\n\t\t\tif(pathPositionRear < 0.0f)\n\t\t\t\tpathPositionRear += TotalLengthOfFlightPath;\n\t\t\tfloat pathPosition = pathPositionRear + 30.0f;\n\n\t\t\tfloat pitch = 0.0f;\n\t\t\tfloat distSinceTakeOff = pathPosition - TakeOffPoint;\n\t\t\tif(distSinceTakeOff <= 0.0f && distSinceTakeOff > -70.0f){\n\t\t\t\t// shortly before take off\n\t\t\t\tpitch = 1.0f - distSinceTakeOff/-70.0f;\n\t\t\t}else if(distSinceTakeOff >= 0.0f && distSinceTakeOff < 100.0f){\n\t\t\t\t// shortly after take off\n\t\t\t\tpitch = 1.0f - distSinceTakeOff/100.0f;\n\t\t\t}\n\n\t\t\tfloat distSinceLanding = pathPosition - LandingPoint;\n\t\t\tif(distSinceLanding <= 0.0f && distSinceLanding > -200.0f){\n\t\t\t\t// shortly before landing\n\t\t\t\tpitch = 1.0f - distSinceLanding/-200.0f;\n\t\t\t}else if(distSinceLanding >= 0.0f && distSinceLanding < 70.0f){\n\t\t\t\t// shortly after landing\n\t\t\t\tpitch = 1.0f - distSinceLanding/70.0f;\n\t\t\t}\n\n\n\t\t\t// Advance current node to appropriate position\n\t\t\tfloat pos1, pos2;\n\t\t\tint nextTrackNode = m_nCurPathNode + 1;\n\t\t\tpos1 = pPathNodes[m_nCurPathNode].t;\n\t\t\tif(nextTrackNode < NumPathNodes)\n\t\t\t\tpos2 = pPathNodes[nextTrackNode].t;\n\t\t\telse{\n\t\t\t\tnextTrackNode = 0;\n\t\t\t\tpos2 = TotalLengthOfFlightPath;\n\t\t\t}\n\t\t\twhile(pathPositionRear < pos1 || pathPositionRear > pos2){\n\t\t\t\tm_nCurPathNode = (m_nCurPathNode+1) % NumPathNodes;\n\t\t\t\tnextTrackNode = m_nCurPathNode + 1;\n\t\t\t\tpos1 = pPathNodes[m_nCurPathNode].t;\n\t\t\t\tif(nextTrackNode < NumPathNodes)\n\t\t\t\t\tpos2 = pPathNodes[nextTrackNode].t;\n\t\t\t\telse{\n\t\t\t\t\tnextTrackNode = 0;\n\t\t\t\t\tpos2 = TotalLengthOfFlightPath;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbool bothOnGround = pPathNodes[m_nCurPathNode].bOnGround && pPathNodes[nextTrackNode].bOnGround;\n\t\t\tif(PlanePathPosition[m_nPlaneId] >= LandingPoint && OldPlanePathPosition[m_nPlaneId] < LandingPoint)\n\t\t\t\tDMAudio.PlayOneShot(m_audioEntityId, SOUND_PLANE_ON_GROUND, 0.0f);\n\t\t\tfloat dist = pPathNodes[nextTrackNode].t - pPathNodes[m_nCurPathNode].t;\n\t\t\tif(dist < 0.0f)\n\t\t\t\tdist += TotalLengthOfFlightPath;\n\t\t\tfloat f = (pathPositionRear - pPathNodes[m_nCurPathNode].t)/dist;\n\t\t\tCVector posRear = (1.0f - f)*pPathNodes[m_nCurPathNode].p + f*pPathNodes[nextTrackNode].p;\n\n\t\t\t// Same for the front\n\t\t\tfloat pathPositionFront = pathPositionRear + 60.0f;\n\t\t\tif(pathPositionFront > TotalLengthOfFlightPath)\n\t\t\t\tpathPositionFront -= TotalLengthOfFlightPath;\n\t\t\tint curPathNodeFront = m_nCurPathNode;\n\t\t\tint nextPathNodeFront = curPathNodeFront + 1;\n\t\t\tpos1 = pPathNodes[curPathNodeFront].t;\n\t\t\tif(nextPathNodeFront < NumPathNodes)\n\t\t\t\tpos2 = pPathNodes[nextPathNodeFront].t;\n\t\t\telse{\n\t\t\t\tnextPathNodeFront = 0;\n\t\t\t\tpos2 = TotalLengthOfFlightPath;\n\t\t\t}\n\t\t\twhile(pathPositionFront < pos1 || pathPositionFront > pos2){\n\t\t\t\tcurPathNodeFront = (curPathNodeFront+1) % NumPathNodes;\n\t\t\t\tnextPathNodeFront = curPathNodeFront + 1;\n\t\t\t\tpos1 = pPathNodes[curPathNodeFront].t;\n\t\t\t\tif(nextPathNodeFront < NumPathNodes)\n\t\t\t\t\tpos2 = pPathNodes[nextPathNodeFront].t;\n\t\t\t\telse{\n\t\t\t\t\tnextPathNodeFront = 0;\n\t\t\t\t\tpos2 = TotalLengthOfFlightPath;\n\t\t\t\t}\n\t\t\t}\n\t\t\tdist = pPathNodes[nextPathNodeFront].t - pPathNodes[curPathNodeFront].t;\n\t\t\tif(dist < 0.0f)\n\t\t\t\tdist += TotalLengthOfFlightPath;\n\t\t\tf = (pathPositionFront - pPathNodes[curPathNodeFront].t)/dist;\n\t\t\tCVector posFront = (1.0f - f)*pPathNodes[curPathNodeFront].p + f*pPathNodes[nextPathNodeFront].p;\n\n\t\t\t// And for another point 60 units in front of the plane, used to calculate roll\n\t\t\tfloat pathPositionFront2 = pathPositionFront + 60.0f;\n\t\t\tif(pathPositionFront2 > TotalLengthOfFlightPath)\n\t\t\t\tpathPositionFront2 -= TotalLengthOfFlightPath;\n\t\t\tint curPathNodeFront2 = m_nCurPathNode;\n\t\t\tint nextPathNodeFront2 = curPathNodeFront2 + 1;\n\t\t\tpos1 = pPathNodes[curPathNodeFront2].t;\n\t\t\tif(nextPathNodeFront2 < NumPathNodes)\n\t\t\t\tpos2 = pPathNodes[nextPathNodeFront2].t;\n\t\t\telse{\n\t\t\t\tnextPathNodeFront2 = 0;\n\t\t\t\tpos2 = TotalLengthOfFlightPath;\n\t\t\t}\n\t\t\twhile(pathPositionFront2 < pos1 || pathPositionFront2 > pos2){\n\t\t\t\tcurPathNodeFront2 = (curPathNodeFront2+1) % NumPathNodes;\n\t\t\t\tnextPathNodeFront2 = curPathNodeFront2 + 1;\n\t\t\t\tpos1 = pPathNodes[curPathNodeFront2].t;\n\t\t\t\tif(nextPathNodeFront2 < NumPathNodes)\n\t\t\t\t\tpos2 = pPathNodes[nextPathNodeFront2].t;\n\t\t\t\telse{\n\t\t\t\t\tnextPathNodeFront2 = 0;\n\t\t\t\t\tpos2 = TotalLengthOfFlightPath;\n\t\t\t\t}\n\t\t\t}\n\t\t\tdist = pPathNodes[nextPathNodeFront2].t - pPathNodes[curPathNodeFront2].t;\n\t\t\tif(dist < 0.0f)\n\t\t\t\tdist += TotalLengthOfFlightPath;\n\t\t\tf = (pathPositionFront2 - pPathNodes[curPathNodeFront2].t)/dist;\n\t\t\tCVector posFront2 = (1.0f - f)*pPathNodes[curPathNodeFront2].p + f*pPathNodes[nextPathNodeFront2].p;\n\n\t\t\t// Now set matrix\n\t\t\tGetMatrix().SetTranslateOnly((posRear + posFront) / 2.0f);\n\t\t\tGetMatrix().GetPosition().z += 4.3f;\n\t\t\tCVector fwd = posFront - posRear;\n\t\t\tfwd.Normalise();\n\t\t\tif(pitch != 0.0f){\n\t\t\t\tfwd.z += 0.4f*pitch;\n\t\t\t\tfwd.Normalise();\n\t\t\t}\n\t\t\tCVector fwd2 = posFront2 - posRear;\n\t\t\tfwd2.Normalise();\n\t\t\tCVector roll = CrossProduct(fwd, fwd2);\n\t\t\tCVector right = CrossProduct(fwd, CVector(0.0f, 0.0f, 1.0f));\n\t\t\tif(!bothOnGround)\n\t\t\t\tright.z += 3.0f*roll.z;\n\t\t\tright.Normalise();\n\t\t\tCVector up = CrossProduct(right, fwd);\n\t\t\tGetMatrix().GetRight() = right;\n\t\t\tGetMatrix().GetUp() = up;\n\t\t\tGetMatrix().GetForward() = fwd;\n\t\t\t// Set speed\n\t\t\tm_vecMoveSpeed = fwd*PlanePathSpeed[m_nPlaneId]/60.0f;\n\t\t\tm_fSpeed = PlanePathSpeed[m_nPlaneId]/60.0f;\n\t\t\tm_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f);\n\n\t\t\tm_isFarAway = !((posFront - TheCamera.GetPosition()).MagnitudeSqr2D() < sq(300.0f));\n\t\t}else{\n\t\t\tfloat planePathPosition;\n\t\t\tfloat totalLengthOfFlightPath;\n\t\t\tCPlaneNode *pathNodes;\n\t\t\tfloat planePathSpeed;\n\t\t\tint numPathNodes;\n\n\t\t\tif(GetModelIndex() == MI_CHOPPER){\n\t\t\t\tplanePathPosition = PlanePath3Position[m_nPlaneId];\n\t\t\t\ttotalLengthOfFlightPath = TotalLengthOfFlightPath3;\n\t\t\t\tpathNodes = pPath3Nodes;\n\t\t\t\tplanePathSpeed = PlanePath3Speed[m_nPlaneId];\n\t\t\t\tnumPathNodes = NumPath3Nodes;\n\t\t\t}else{\n\t\t\t\tplanePathPosition = PlanePath2Position[m_nPlaneId];\n\t\t\t\ttotalLengthOfFlightPath = TotalLengthOfFlightPath2;\n\t\t\t\tpathNodes = pPath2Nodes;\n\t\t\t\tplanePathSpeed = PlanePath2Speed[m_nPlaneId];\n\t\t\t\tnumPathNodes = NumPath2Nodes;\n\t\t\t}\n\n\t\t\t// Advance current node to appropriate position\n\t\t\tfloat pathPositionRear = planePathPosition - 10.0f;\n\t\t\tif(pathPositionRear < 0.0f)\n\t\t\t\tpathPositionRear += totalLengthOfFlightPath;\n\t\t\tfloat pos1, pos2;\n\t\t\tint nextTrackNode = m_nCurPathNode + 1;\n\t\t\tpos1 = pathNodes[m_nCurPathNode].t;\n\t\t\tif(nextTrackNode < numPathNodes)\n\t\t\t\tpos2 = pathNodes[nextTrackNode].t;\n\t\t\telse{\n\t\t\t\tnextTrackNode = 0;\n\t\t\t\tpos2 = totalLengthOfFlightPath;\n\t\t\t}\n\t\t\twhile(pathPositionRear < pos1 || pathPositionRear > pos2){\n\t\t\t\tm_nCurPathNode = (m_nCurPathNode+1) % numPathNodes;\n\t\t\t\tnextTrackNode = m_nCurPathNode + 1;\n\t\t\t\tpos1 = pathNodes[m_nCurPathNode].t;\n\t\t\t\tif(nextTrackNode < numPathNodes)\n\t\t\t\t\tpos2 = pathNodes[nextTrackNode].t;\n\t\t\t\telse{\n\t\t\t\t\tnextTrackNode = 0;\n\t\t\t\t\tpos2 = totalLengthOfFlightPath;\n\t\t\t\t}\n\t\t\t}\n\t\t\tfloat dist = pathNodes[nextTrackNode].t - pathNodes[m_nCurPathNode].t;\n\t\t\tif(dist < 0.0f)\n\t\t\t\tdist += totalLengthOfFlightPath;\n\t\t\tfloat f = (pathPositionRear - pathNodes[m_nCurPathNode].t)/dist;\n\t\t\tCVector posRear = (1.0f - f)*pathNodes[m_nCurPathNode].p + f*pathNodes[nextTrackNode].p;\n\n\t\t\t// Same for the front\n\t\t\tfloat pathPositionFront = pathPositionRear + 20.0f;\n\t\t\tif(pathPositionFront > totalLengthOfFlightPath)\n\t\t\t\tpathPositionFront -= totalLengthOfFlightPath;\n\t\t\tint curPathNodeFront = m_nCurPathNode;\n\t\t\tint nextPathNodeFront = curPathNodeFront + 1;\n\t\t\tpos1 = pathNodes[curPathNodeFront].t;\n\t\t\tif(nextPathNodeFront < numPathNodes)\n\t\t\t\tpos2 = pathNodes[nextPathNodeFront].t;\n\t\t\telse{\n\t\t\t\tnextPathNodeFront = 0;\n\t\t\t\tpos2 = totalLengthOfFlightPath;\n\t\t\t}\n\t\t\twhile(pathPositionFront < pos1 || pathPositionFront > pos2){\n\t\t\t\tcurPathNodeFront = (curPathNodeFront+1) % numPathNodes;\n\t\t\t\tnextPathNodeFront = curPathNodeFront + 1;\n\t\t\t\tpos1 = pathNodes[curPathNodeFront].t;\n\t\t\t\tif(nextPathNodeFront < numPathNodes)\n\t\t\t\t\tpos2 = pathNodes[nextPathNodeFront].t;\n\t\t\t\telse{\n\t\t\t\t\tnextPathNodeFront = 0;\n\t\t\t\t\tpos2 = totalLengthOfFlightPath;\n\t\t\t\t}\n\t\t\t}\n\t\t\tdist = pathNodes[nextPathNodeFront].t - pathNodes[curPathNodeFront].t;\n\t\t\tif(dist < 0.0f)\n\t\t\t\tdist += totalLengthOfFlightPath;\n\t\t\tf = (pathPositionFront - pathNodes[curPathNodeFront].t)/dist;\n\t\t\tCVector posFront = (1.0f - f)*pathNodes[curPathNodeFront].p + f*pathNodes[nextPathNodeFront].p;\n\n\t\t\t// And for another point 30 units in front of the plane, used to calculate roll\n\t\t\tfloat pathPositionFront2 = pathPositionFront + 30.0f;\n\t\t\tif(pathPositionFront2 > totalLengthOfFlightPath)\n\t\t\t\tpathPositionFront2 -= totalLengthOfFlightPath;\n\t\t\tint curPathNodeFront2 = m_nCurPathNode;\n\t\t\tint nextPathNodeFront2 = curPathNodeFront2 + 1;\n\t\t\tpos1 = pathNodes[curPathNodeFront2].t;\n\t\t\tif(nextPathNodeFront2 < numPathNodes)\n\t\t\t\tpos2 = pathNodes[nextPathNodeFront2].t;\n\t\t\telse{\n\t\t\t\tnextPathNodeFront2 = 0;\n\t\t\t\tpos2 = totalLengthOfFlightPath;\n\t\t\t}\n\t\t\twhile(pathPositionFront2 < pos1 || pathPositionFront2 > pos2){\n\t\t\t\tcurPathNodeFront2 = (curPathNodeFront2+1) % numPathNodes;\n\t\t\t\tnextPathNodeFront2 = curPathNodeFront2 + 1;\n\t\t\t\tpos1 = pathNodes[curPathNodeFront2].t;\n\t\t\t\tif(nextPathNodeFront2 < numPathNodes)\n\t\t\t\t\tpos2 = pathNodes[nextPathNodeFront2].t;\n\t\t\t\telse{\n\t\t\t\t\tnextPathNodeFront2 = 0;\n\t\t\t\t\tpos2 = totalLengthOfFlightPath;\n\t\t\t\t}\n\t\t\t}\n\t\t\tdist = pathNodes[nextPathNodeFront2].t - pathNodes[curPathNodeFront2].t;\n\t\t\tif(dist < 0.0f)\n\t\t\t\tdist += totalLengthOfFlightPath;\n\t\t\tf = (pathPositionFront2 - pathNodes[curPathNodeFront2].t)/dist;\n\t\t\tCVector posFront2 = (1.0f - f)*pathNodes[curPathNodeFront2].p + f*pathNodes[nextPathNodeFront2].p;\n\n\t\t\t// Now set matrix\n\t\t\tGetMatrix().SetTranslateOnly((posRear + posFront) / 2.0f);\n\t\t\tGetMatrix().GetPosition().z += 1.0f;\n\t\t\tCVector fwd = posFront - posRear;\n\t\t\tfwd.Normalise();\n\t\t\tCVector fwd2 = posFront2 - posRear;\n\t\t\tfwd2.Normalise();\n\t\t\tCVector roll = CrossProduct(fwd, fwd2);\n\t\t\tCVector right = CrossProduct(fwd, CVector(0.0f, 0.0f, 1.0f));\n\t\t\tright.z += 3.0f*roll.z;\n\t\t\tright.Normalise();\n\t\t\tCVector up = CrossProduct(right, fwd);\n\t\t\tGetMatrix().GetRight() = right;\n\t\t\tGetMatrix().GetUp() = up;\n\t\t\tGetMatrix().GetForward() = fwd;\n\n\t\t\t// Set speed\n\t\t\tm_vecMoveSpeed = fwd*planePathSpeed/60.0f;\n\t\t\tm_fSpeed = planePathSpeed/60.0f;\n\t\t\tm_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f);\n\n\t\t\tm_isFarAway = !((posFront - TheCamera.GetPosition()).MagnitudeSqr2D() < sq(300.0f));\n\t\t}\n\t}\n\n\tbIsInSafePosition = true;\n\tGetMatrix().UpdateRW();\n\tUpdateRwFrame();\n\n\t// Handle streaming and such\n\tCVehicleModelInfo *mi = (CVehicleModelInfo*)CModelInfo::GetModelInfo(GetModelIndex());\n\tif(m_isFarAway){\n\t\t// Switch to LOD model\n\t\tif(m_rwObject && RwObjectGetType(m_rwObject) == rpCLUMP){\n\t\t\tDeleteRwObject();\n\t\t\tif(mi->m_planeLodId != -1){\n\t\t\t\tPUSH_MEMID(MEMID_WORLD);\n\t\t\t\tm_rwObject = CModelInfo::GetModelInfo(mi->m_planeLodId)->CreateInstance();\n\t\t\t\tPOP_MEMID();\n\t\t\t\tif(m_rwObject)\n\t\t\t\t\tm_matrix.AttachRW(RwFrameGetMatrix(RpAtomicGetFrame((RpAtomic*)m_rwObject)));\n\t\t\t}\n\t\t}\n\t}else if(CStreaming::HasModelLoaded(GetModelIndex())){\n\t\tif(m_rwObject && RwObjectGetType(m_rwObject) == rpATOMIC){\n\t\t\t// Get rid of LOD model\n\t\t\tm_matrix.Detach();\n\t\t\tif(m_rwObject){\t// useless check\n\t\t\t\tif(RwObjectGetType(m_rwObject) == rpATOMIC){\t// useless check\n\t\t\t\t\tRwFrame *f = RpAtomicGetFrame((RpAtomic*)m_rwObject);\n\t\t\t\t\tRpAtomicDestroy((RpAtomic*)m_rwObject);\n\t\t\t\t\tRwFrameDestroy(f);\n\t\t\t\t}\n\t\t\t\tm_rwObject = nil;\n\t\t\t}\n\t\t}\n\t\t// Set high detail model\n\t\tif(m_rwObject == nil){\n\t\t\tint id = GetModelIndex();\n\t\t\tm_modelIndex = -1;\n\t\t\tSetModelIndex(id);\n\t\t}\n\t}else{\n\t\tCStreaming::RequestModel(GetModelIndex(), STREAMFLAGS_DEPENDENCY);\n\t}\n}\n\nvoid\nCPlane::PreRender(void)\n{\n\tCVehicleModelInfo *mi = (CVehicleModelInfo*)CModelInfo::GetModelInfo(GetModelIndex());\n\n\tCVector lookVector = GetPosition() - TheCamera.GetPosition();\n\tfloat camDist = lookVector.Magnitude();\n\tif(camDist != 0.0f)\n\t\tlookVector *= 1.0f/camDist;\n\telse\n\t\tlookVector = CVector(1.0f, 0.0f, 0.0f);\n\tfloat behindness = DotProduct(lookVector, GetForward());\n\n\t// Wing lights\n\tif(behindness < 0.0f){\n\t\t// in front of plane\n\t\tCVector lightPos = mi->m_positions[PLANE_POS_LIGHT_RIGHT];\n\t\tCVector lightR = GetMatrix() * lightPos;\n\t\tCVector lightL = lightR;\n\t\tlightL -= GetRight()*2.0f*lightPos.x;\n\n\t\tfloat intensity = -0.6f*behindness + 0.4f;\n\t\tfloat size = 1.0f - behindness;\n\n\t\tif(behindness < -0.9f && camDist < 50.0f){\n\t\t\t// directly in front\n\t\t\tCCoronas::RegisterCorona((uintptr)this + 10, 255*intensity, 255*intensity, 255*intensity, 255,\n\t\t\t\tlightL, size, 240.0f,\n\t\t\t\tCCoronas::TYPE_NORMAL, CCoronas::FLARE_HEADLIGHTS, CCoronas::REFLECTION_ON,\n\t\t\t\tCCoronas::LOSCHECK_OFF, CCoronas::STREAK_ON, 0.0f);\n\t\t\tCCoronas::RegisterCorona((uintptr)this + 11, 255*intensity, 255*intensity, 255*intensity, 255,\n\t\t\t\tlightR, size, 240.0f,\n\t\t\t\tCCoronas::TYPE_NORMAL, CCoronas::FLARE_HEADLIGHTS, CCoronas::REFLECTION_ON,\n\t\t\t\tCCoronas::LOSCHECK_OFF, CCoronas::STREAK_ON, 0.0f);\n\t\t}else{\n\t\t\tCCoronas::RegisterCorona((uintptr)this + 10, 255*intensity, 255*intensity, 255*intensity, 255,\n\t\t\t\tlightL, size, 240.0f,\n\t\t\t\tCCoronas::TYPE_NORMAL, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON,\n\t\t\t\tCCoronas::LOSCHECK_OFF, CCoronas::STREAK_ON, 0.0f);\n\t\t\tCCoronas::RegisterCorona((uintptr)this + 11, 255*intensity, 255*intensity, 255*intensity, 255,\n\t\t\t\tlightR, size, 240.0f,\n\t\t\t\tCCoronas::TYPE_NORMAL, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON,\n\t\t\t\tCCoronas::LOSCHECK_OFF, CCoronas::STREAK_ON, 0.0f);\n\t\t}\n\t}\n\n\t// Tail light\n\tif(CTimer::GetTimeInMilliseconds() & 0x200){\n\t\tCVector pos = GetMatrix() * mi->m_positions[PLANE_POS_LIGHT_TAIL];\n\n\t\tCCoronas::RegisterCorona((uintptr)this + 12, 255, 0, 0, 255,\n\t\t\tpos, 1.0f, 120.0f,\n\t\t\tCCoronas::TYPE_NORMAL, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON,\n\t\t\tCCoronas::LOSCHECK_OFF, CCoronas::STREAK_ON, 0.0f);\n\t}\n\n#ifdef CPLANE_ROTORS\n\tCMatrix mat;\n\tCVector pos;\n\tm_fRotorRotation += 3.14f/6.5f;\n\tif(m_fRotorRotation > 6.28f)\n\t\tm_fRotorRotation -= 6.28f;\n\n\tif(m_aPlaneNodes[PLANE_TOPROTOR]){\n\t\tmat.Attach(RwFrameGetMatrix(m_aPlaneNodes[PLANE_TOPROTOR]));\n\t\tpos = mat.GetPosition();\n\t\tmat.SetRotateZ(m_fRotorRotation);\n\t\tmat.Translate(pos);\n\t\tmat.UpdateRW();\n\t}\n\tif(m_aPlaneNodes[PLANE_BACKROTOR]){\n\t\tmat.Attach(RwFrameGetMatrix(m_aPlaneNodes[PLANE_BACKROTOR]));\n\t\tpos = mat.GetPosition();\n\t\tmat.SetRotateX(m_fRotorRotation);\n\t\tmat.Translate(pos);\n\t\tmat.UpdateRW();\n\t}\n#endif\n}\n\nvoid\nCPlane::Render(void)\n{\n\tif(!CCutsceneMgr::IsRunning())\n\t\tCEntity::Render();\n}\n\n#define CRUISE_SPEED (50.0f)\n#define TAXI_SPEED (5.0f)\n\nvoid\nCPlane::InitPlanes(void)\n{\n\tint i;\n\n\tCesnaMissionStatus = CESNA_STATUS_NONE;\n\n\t// Jumbo\n\tif(pPathNodes == nil){\n\t\tpPathNodes = LoadPath(\"data\\\\paths\\\\flight.dat\", NumPathNodes, TotalLengthOfFlightPath, true);\n\n\t\t// Figure out which nodes are on ground\n\t\tfor(i = 0; i < NumPathNodes; i++){\n\t\t\tif(pPathNodes[i].p.z < 14.0f){\n\t\t\t\tpPathNodes[i].p.z = 14.0f;\n\t\t\t\tpPathNodes[i].bOnGround = true;\n\t\t\t}else\n\t\t\t\tpPathNodes[i].bOnGround = false;\n\t\t}\n\n\t\t// Find lading and takeoff points\n\t\tLandingPoint = -1.0f;\n\t\tTakeOffPoint = -1.0f;\n\t\tbool lastOnGround = pPathNodes[NumPathNodes-1].bOnGround;\n\t\tfor(i = 0; i < NumPathNodes; i++){\n\t\t\tif(pPathNodes[i].bOnGround && !lastOnGround)\n\t\t\t\tLandingPoint = pPathNodes[i].t;\n\t\t\telse if(!pPathNodes[i].bOnGround && lastOnGround)\n\t\t\t\tTakeOffPoint = pPathNodes[i].t;\n\t\t\tlastOnGround = pPathNodes[i].bOnGround;\n\t\t}\n\n\t\t// Animation\n\t\tfloat time = 0.0f;\n\t\tfloat position = 0.0f;\n\t\t// Start on ground with slow speed\n\t\taPlaneLineBits[0].type = 1;\n\t\taPlaneLineBits[0].time = time;\n\t\taPlaneLineBits[0].position = position;\n\t\taPlaneLineBits[0].speed = TAXI_SPEED;\n\t\taPlaneLineBits[0].acceleration = 0.0f;\n\t\tfloat dist = (TakeOffPoint-500.0f) - position;\n\t\ttime += dist/TAXI_SPEED;\n\t\tposition += dist;\n\n\t\t// Accelerate to take off\n\t\taPlaneLineBits[1].type = 2;\n\t\taPlaneLineBits[1].time = time;\n\t\taPlaneLineBits[1].position = position;\n\t\taPlaneLineBits[1].speed = TAXI_SPEED;\n\t\taPlaneLineBits[1].acceleration = 618.75f/500.0f;\n\t\ttime += 500.0f/((CRUISE_SPEED+TAXI_SPEED)/2.0f);\n\t\tposition += 500.0f;\n\n\t\t// Fly at cruise speed\n\t\taPlaneLineBits[2].type = 1;\n\t\taPlaneLineBits[2].time = time;\n\t\taPlaneLineBits[2].position = position;\n\t\taPlaneLineBits[2].speed = CRUISE_SPEED;\n\t\taPlaneLineBits[2].acceleration = 0.0f;\n\t\tdist = LandingPoint - TakeOffPoint;\n\t\ttime += dist/CRUISE_SPEED;\n\t\tposition += dist;\n\n\t\t// Brake after landing\n\t\taPlaneLineBits[3].type = 2;\n\t\taPlaneLineBits[3].time = time;\n\t\taPlaneLineBits[3].position = position;\n\t\taPlaneLineBits[3].speed = CRUISE_SPEED;\n\t\taPlaneLineBits[3].acceleration = -618.75f/500.0f;\n\t\ttime += 500.0f/((CRUISE_SPEED+TAXI_SPEED)/2.0f);\n\t\tposition += 500.0f;\n\n\t\t// Taxi\n\t\taPlaneLineBits[4].type = 1;\n\t\taPlaneLineBits[4].time = time;\n\t\taPlaneLineBits[4].position = position;\n\t\taPlaneLineBits[4].speed = TAXI_SPEED;\n\t\taPlaneLineBits[4].acceleration = 0.0f;\n\t\ttime += (TotalLengthOfFlightPath - position)/TAXI_SPEED;\n\n\t\t// end\n\t\taPlaneLineBits[5].time = time;\n\t\tTotalDurationOfFlightPath = time;\n\t}\n\n\t// Dodo\n\tif(pPath2Nodes == nil){\n\t\tpPath2Nodes = LoadPath(\"data\\\\paths\\\\flight2.dat\", NumPath2Nodes, TotalLengthOfFlightPath2, true);\n\t\tTotalDurationOfFlightPath2 = TotalLengthOfFlightPath2/CRUISE_SPEED;\n\t}\n\n\t// Heli\n\tif(pPath3Nodes == nil){\n\t\tpPath3Nodes = LoadPath(\"data\\\\paths\\\\flight3.dat\", NumPath3Nodes, TotalLengthOfFlightPath3, false);\n\t\tTotalDurationOfFlightPath3 = TotalLengthOfFlightPath3/CRUISE_SPEED;\n\t}\n\n\tCStreaming::LoadAllRequestedModels(false);\n\tCStreaming::RequestModel(MI_AIRTRAIN, 0);\n\tCStreaming::LoadAllRequestedModels(false);\n\n\t// NB: 3 hardcoded also in CPlaneTrails\n\tfor(i = 0; i < 3; i++){\n\t\tCPlane *plane = new CPlane(MI_AIRTRAIN, PERMANENT_VEHICLE);\n\t\tplane->GetMatrix().SetTranslate(0.0f, 0.0f, 0.0f);\n\t\tplane->SetStatus(STATUS_ABANDONED);\n\t\tplane->bIsLocked = true;\n\t\tplane->m_nPlaneId = i;\n\t\tplane->m_nCurPathNode = 0;\n\t\tCWorld::Add(plane);\n\t}\n}\n\nvoid\nCPlane::Shutdown(void)\n{\n\tdelete[] pPathNodes;\n\tdelete[] pPath2Nodes;\n\tdelete[] pPath3Nodes;\n\tdelete[] pPath4Nodes;\n\tpPathNodes = nil;\n\tpPath2Nodes = nil;\n\tpPath3Nodes = nil;\n\tpPath4Nodes = nil;\n}\n\nCPlaneNode*\nCPlane::LoadPath(char const *filename, int32 &numNodes, float &totalLength, bool loop)\n{\n\tint bp, lp;\n\tint i;\n\n\tCFileMgr::LoadFile(filename, work_buff, sizeof(work_buff), \"r\");\n\t*gString = '\\0';\n\tfor(bp = 0, lp = 0; work_buff[bp] != '\\n'; bp++, lp++)\n\t\tgString[lp] = work_buff[bp];\n\tbp++;\n\tgString[lp] = '\\0';\n\tsscanf(gString, \"%d\", &numNodes);\n\tCPlaneNode *nodes = new CPlaneNode[numNodes];\n\n\tfor(i = 0; i < numNodes; i++){\n\t\tfor(lp = 0; work_buff[bp] != '\\n' && work_buff[bp] != '\\0'; bp++, lp++)\n\t\t\tgString[lp] = work_buff[bp];\n\t\tbp++;\n\t\t// BUG: game doesn't terminate string\n\t\tgString[lp] = '\\0';\n\t\tsscanf(gString, \"%f %f %f\", &nodes[i].p.x, &nodes[i].p.y, &nodes[i].p.z);\n\t}\n\n\t// Calculate length of segments and path\n\ttotalLength = 0.0f;\n\tfor(i = 0; i < numNodes; i++){\n\t\tnodes[i].t = totalLength;\n\t\tfloat l = (nodes[(i+1) % numNodes].p - nodes[i].p).Magnitude2D();\n\t\tif(!loop && i == numNodes-1)\n\t\t\tl = 0.0f;\n\t\ttotalLength += l;\n\t}\n\n\treturn nodes;\n}\n\nint32 LastTimeInPlane, LastTimeNotInPlane;\nbool bCesnasActivated;\nbool bHelisActivated;\n\nvoid\nCPlane::UpdatePlanes(void)\n{\n\tint i, j;\n\tuint32 time;\n\tfloat t, deltaT;\n\n\tif(CReplay::IsPlayingBack())\n\t\treturn;\n\n\t// Jumbo jets\n\ttime = CTimer::GetTimeInMilliseconds();\n\tfor(i = 0; i < 3; i++){\n\t\tt = TotalDurationOfFlightPath * (float)(time & 0x7FFFF)/0x80000;\n\t\t// find current frame\n\t\tfor(j = 0; t > aPlaneLineBits[j+1].time; j++);\n\n\t\tOldPlanePathPosition[i] = PlanePathPosition[i];\n\t\tdeltaT = t - aPlaneLineBits[j].time;\n\t\tswitch(aPlaneLineBits[j].type){\n\t\tcase 0:\t// standing still\n\t\t\tPlanePathPosition[i] = aPlaneLineBits[j].position;\n\t\t\tPlanePathSpeed[i] = 0.0f;\n\t\t\tbreak;\n\t\tcase 1:\t// moving with constant speed\n\t\t\tPlanePathPosition[i] = aPlaneLineBits[j].position + aPlaneLineBits[j].speed*deltaT;\n\t\t\tPlanePathSpeed[i] = (TotalDurationOfFlightPath*1000.0f/0x80000) * aPlaneLineBits[j].speed;\n\t\t\tbreak;\n\t\tcase 2:\t// accelerating/braking\n\t\t\tPlanePathPosition[i] = aPlaneLineBits[j].position + (aPlaneLineBits[j].speed + aPlaneLineBits[j].acceleration*deltaT)*deltaT;\n\t\t\tPlanePathSpeed[i] = (TotalDurationOfFlightPath*1000.0f/0x80000)*aPlaneLineBits[j].speed + 2.0f*aPlaneLineBits[j].acceleration*deltaT;\n\t\t\tbreak;\n\t\t}\n\n\t\t// time offset for each plane\n\t\ttime += 0x80000/3;\n\t}\n\n\ttime = CTimer::GetTimeInMilliseconds();\n\n\tt = TotalDurationOfFlightPath2/0x80000;\n\tPlanePath2Position[0] = CRUISE_SPEED * (time & 0x7FFFF)*t;\n\tPlanePath2Position[1] = CRUISE_SPEED * ((time + 0x80000/5) & 0x7FFFF)*t;\n\tPlanePath2Position[2] = CRUISE_SPEED * ((time + 0x80000/5*2) & 0x7FFFF)*t;\n\tPlanePath2Position[3] = CRUISE_SPEED * ((time + 0x80000/5*3) & 0x7FFFF)*t;\n\tPlanePath2Position[4] = CRUISE_SPEED * ((time + 0x80000/5*4) & 0x7FFFF)*t;\n\tPlanePath2Speed[0] = CRUISE_SPEED*t;\n\tPlanePath2Speed[1] = CRUISE_SPEED*t;\n\tPlanePath2Speed[2] = CRUISE_SPEED*t;\n\tPlanePath2Speed[3] = CRUISE_SPEED*t;\n\tPlanePath2Speed[4] = CRUISE_SPEED*t;\n\n\tt = TotalDurationOfFlightPath3/0x80000;\n\tPlanePath3Position[0] = CRUISE_SPEED * (time & 0x7FFFF)*t;\n\tPlanePath3Position[1] = CRUISE_SPEED * ((time + 0x80000/4) & 0x7FFFF)*t;\n\tPlanePath3Position[2] = CRUISE_SPEED * ((time + 0x80000/4*2) & 0x7FFFF)*t;\n\tPlanePath3Position[3] = CRUISE_SPEED * ((time + 0x80000/4*3) & 0x7FFFF)*t;\n\tPlanePath3Speed[0] = CRUISE_SPEED*t;\n\tPlanePath3Speed[1] = CRUISE_SPEED*t;\n\tPlanePath3Speed[2] = CRUISE_SPEED*t;\n\tPlanePath3Speed[3] = CRUISE_SPEED*t;\n\n\tif(FindPlayerVehicle() && (FindPlayerVehicle()->GetVehicleAppearance() == VEHICLE_APPEARANCE_HELI ||\n\t                           FindPlayerVehicle()->GetVehicleAppearance() == VEHICLE_APPEARANCE_PLANE))\n\t\tLastTimeInPlane = CTimer::GetTimeInMilliseconds();\n\telse\n\t\tLastTimeNotInPlane = CTimer::GetTimeInMilliseconds();\n\n\tif(CTimer::GetTimeInMilliseconds() - LastTimeNotInPlane > 10000){\n\t\tif(!bCesnasActivated){\n\t\t\tif(CStreaming::HasModelLoaded(MI_DEADDODO)){\n\t\t\t\tfor(i = 0; i < 5; i++){\n\t\t\t\t\tCPlane *plane = new CPlane(MI_DEADDODO, PERMANENT_VEHICLE);\n\t\t\t\t\tplane->GetMatrix().SetTranslate(0.0f, 0.0f, 0.0f);\n\t\t\t\t\tplane->SetStatus(STATUS_ABANDONED);\n\t\t\t\t\tplane->bIsLocked = true;\n\t\t\t\t\tplane->m_nPlaneId = i;\n\t\t\t\t\tplane->m_nCurPathNode = 0;\n\t\t\t\t\tplane->m_bTempPlane = true;\n\t\t\t\t\tCWorld::Add(plane);\n\t\t\t\t}\n\t\t\t\tbCesnasActivated = true;\n\t\t\t}else\n\t\t\t\tCStreaming::RequestModel(MI_DEADDODO, 0);\n\t\t}\n\n\t\tif(!bHelisActivated){\n\t\t\tif(CStreaming::HasModelLoaded(MI_CHOPPER)){\n\t\t\t\tfor(i = 0; i < 4; i++){\n\t\t\t\t\tCPlane *plane = new CPlane(MI_CHOPPER, PERMANENT_VEHICLE);\n\t\t\t\t\tplane->GetMatrix().SetTranslate(0.0f, 0.0f, 0.0f);\n\t\t\t\t\tplane->SetStatus(STATUS_ABANDONED);\n\t\t\t\t\tplane->bIsLocked = true;\n\t\t\t\t\tplane->m_nPlaneId = i;\n\t\t\t\t\tplane->m_nCurPathNode = 0;\n\t\t\t\t\tplane->m_bTempPlane = true;\n\t\t\t\t\tCWorld::Add(plane);\n\t\t\t\t}\n\t\t\t\tbHelisActivated = true;\n\t\t\t}else\n\t\t\t\tCStreaming::RequestModel(MI_CHOPPER, 0);\n\t\t}\n\t}else if(CTimer::GetTimeInMilliseconds() - LastTimeInPlane > 10000)\n\t\tRemoveTemporaryPlanes();\n}\n\nvoid\nCPlane::RemoveTemporaryPlanes(void)\n{\n\tint i;\n\tif(!bHelisActivated && !bCesnasActivated)\n\t\treturn;\n\n\ti = CPools::GetVehiclePool()->GetSize();\n\twhile(--i >= 0){\n\t\tCPlane *plane = (CPlane*)CPools::GetVehiclePool()->GetSlot(i);\n\t\tif(plane && plane->IsPlane() && plane->m_bTempPlane){\n\t\t\tCWorld::Remove(plane);\n\t\t\tdelete plane;\n\t\t}\n\t}\n\tbCesnasActivated = false;\n\tbHelisActivated = false;\n}\n\nbool\nCPlane::TestRocketCollision(CVector *rocketPos)\n{\n\tint i;\n\n\ti = CPools::GetVehiclePool()->GetSize();\n\twhile(--i >= 0){\n\t\tCPlane *plane = (CPlane*)CPools::GetVehiclePool()->GetSlot(i);\n\t\tif(plane &&\n#ifdef EXPLODING_AIRTRAIN\n\t\t   (plane->GetModelIndex() == MI_AIRTRAIN || plane->GetModelIndex() == MI_DEADDODO) &&\n#else\n\t\t   plane->GetModelIndex() != MI_AIRTRAIN && plane->GetModelIndex() == MI_DEADDODO &&\t// strange check\n#endif\n\t\t   !plane->m_bHasBeenHit && (*rocketPos - plane->GetPosition()).Magnitude() < 25.0f){\n\t\t\tplane->m_nFrameWhenHit = CTimer::GetFrameCounter();\n\t\t\tplane->m_bHasBeenHit = true;\n\t\t\tCWorld::Players[CWorld::PlayerInFocus].m_pPed->m_pWanted->RegisterCrime_Immediately(CRIME_DESTROYED_CESSNA,\n\t\t\t\tplane->GetPosition(), i+1983, false);\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n\n// unused\n// BUG: not in CPlane in the game\nvoid\nCPlane::CreateIncomingCesna(void)\n{\n\tif(CesnaMissionStatus == CESNA_STATUS_FLYING){\n\t\tCWorld::Remove(pDrugRunCesna);\n\t\tdelete pDrugRunCesna;\n\t\tpDrugRunCesna = nil;\n\t}\n\tpDrugRunCesna = new CPlane(MI_DEADDODO, PERMANENT_VEHICLE);\n\tpDrugRunCesna->GetMatrix().SetTranslate(0.0f, 0.0f, 0.0f);\n\tpDrugRunCesna->SetStatus(STATUS_ABANDONED);\n\tpDrugRunCesna->bIsLocked = true;\n\tpDrugRunCesna->m_nPlaneId = 0;\n\tpDrugRunCesna->m_nCurPathNode = 0;\n\tpDrugRunCesna->m_bIsDrugRunCesna = true;\n\tCWorld::Add(pDrugRunCesna);\n\n        CesnaMissionStatus = CESNA_STATUS_FLYING;\n        CesnaMissionStartTime = CTimer::GetTimeInMilliseconds();\n        printf(\"CPlane::CreateIncomingCesna(void)\\n\");\n}\n\n// unused\nvoid\nCPlane::CreateDropOffCesna(void)\n{\n\tif(DropOffCesnaMissionStatus == CESNA_STATUS_FLYING){\n\t\tCWorld::Remove(pDropOffCesna);\n\t\tdelete pDropOffCesna;\n\t\tpDropOffCesna = nil;\n\t}\n\tpDropOffCesna = new CPlane(MI_DEADDODO, PERMANENT_VEHICLE);\n\tpDropOffCesna->GetMatrix().SetTranslate(0.0f, 0.0f, 0.0f);\n\tpDropOffCesna->SetStatus(STATUS_ABANDONED);\n\tpDropOffCesna->bIsLocked = true;\n\tpDropOffCesna->m_nPlaneId = 0;\n\tpDropOffCesna->m_nCurPathNode = 0;\n\tpDropOffCesna->m_bIsDropOffCesna = true;\n\tCWorld::Add(pDropOffCesna);\n\n        DropOffCesnaMissionStatus = CESNA_STATUS_FLYING;\n        DropOffCesnaMissionStartTime = CTimer::GetTimeInMilliseconds();\n        printf(\"CPlane::CreateDropOffCesna(void)\\n\");\n}\n\n// all unused\nconst CVector CPlane::FindDrugPlaneCoordinates(void) { return pDrugRunCesna->GetPosition(); }\nconst CVector CPlane::FindDropOffCesnaCoordinates(void) { return pDropOffCesna->GetPosition(); }\nbool CPlane::HasCesnaLanded(void) { return CesnaMissionStatus == CESNA_STATUS_LANDED; }\nbool CPlane::HasCesnaBeenDestroyed(void) { return CesnaMissionStatus == CESNA_STATUS_DESTROYED; }\nbool CPlane::HasDropOffCesnaBeenShotDown(void) { return DropOffCesnaMissionStatus == CESNA_STATUS_DESTROYED; }\n\nvoid\nCPlane::Load(void)\n{\n\tRemoveTemporaryPlanes();\n}\n\nvoid\nCPlane::Save(void)\n{\n\tRemoveTemporaryPlanes();\n}\n"
  },
  {
    "path": "src/vehicles/Plane.h",
    "content": "#pragma once\n\n#include \"Vehicle.h\"\n\nenum ePlaneNodes\n{\n#ifdef CPLANE_ROTORS\n\t// for heli\n\tPLANE_TOPROTOR,\n\tPLANE_BACKROTOR,\n#endif\n\tPLANE_WHEEL_FRONT = 2,\n\tPLANE_WHEEL_READ,\n\tNUM_PLANE_NODES\n};\n\nstruct CPlaneNode\n{\n\tCVector p;\t// position\n\tfloat t;\t// xy-distance from start on path\n\tbool bOnGround;\t// i.e. not flying\n};\n\nstruct CPlaneInterpolationLine\n{\n\tuint8 type;\n\tfloat time;\t// when does this keyframe start\n\t// initial values at start of frame\n\tfloat position;\n\tfloat speed;\n\tfloat acceleration;\n};\n\nclass CPlane : public CVehicle\n{\npublic:\n#ifdef CPLANE_ROTORS\n\tRwFrame *m_aPlaneNodes[NUM_PLANE_NODES];\n\tfloat m_fRotorRotation;\n#endif\n\tint16 m_nPlaneId;\n\tint16 m_isFarAway;\n\tint16 m_nCurPathNode;\n\tfloat m_fSpeed;\n\tuint32 m_nFrameWhenHit;\n\tbool m_bHasBeenHit;\n\tbool m_bIsDrugRunCesna;\n\tbool m_bIsDropOffCesna;\n\tbool m_bTempPlane;\n\n\tCPlane(int32 id, uint8 CreatedBy);\n\t~CPlane(void);\n\n\t// from CEntity\n\tvoid SetModelIndex(uint32 id);\n\tvoid DeleteRwObject(void);\n\tvoid ProcessControl(void);\n\tvoid PreRender(void);\n\tvoid Render(void);\n\tvoid FlagToDestroyWhenNextProcessed() { bRemoveFromWorld = true; }\n\n\tstatic void InitPlanes(void);\n\tstatic void Shutdown(void);\n\tstatic CPlaneNode *LoadPath(char const *filename, int32 &numNodes, float &totalLength, bool loop);\n\tstatic void RemoveTemporaryPlanes(void);\n\tstatic void UpdatePlanes(void);\n\tstatic bool TestRocketCollision(CVector *rocketPos);\n\tstatic void CreateIncomingCesna(void);\n\tstatic void CreateDropOffCesna(void);\n\tstatic const CVector FindDrugPlaneCoordinates(void);\n\tstatic const CVector FindDropOffCesnaCoordinates(void);\n\tstatic bool HasCesnaLanded(void);\n\tstatic bool HasCesnaBeenDestroyed(void);\n\tstatic bool HasDropOffCesnaBeenShotDown(void);\n\tstatic void Load(void);\n\tstatic void Save(void);\n};\n\nextern float LandingPoint;\nextern float TakeOffPoint;\nextern float PlanePathPosition[3];\n"
  },
  {
    "path": "src/vehicles/Train.cpp",
    "content": "#include \"common.h\"\n#include \"main.h\"\n\n#include \"Timer.h\"\n#include \"ModelIndices.h\"\n#include \"FileMgr.h\"\n#include \"Streaming.h\"\n#include \"Pad.h\"\n#include \"Camera.h\"\n#include \"Coronas.h\"\n#include \"World.h\"\n#include \"Ped.h\"\n#include \"DMAudio.h\"\n#include \"HandlingMgr.h\"\n#include \"Train.h\"\n#include \"AudioScriptObject.h\"\n\nstatic CTrainNode* pTrackNodes;\nstatic int16 NumTrackNodes;\nstatic float StationDist[3] = { 873.0f, 1522.0f, 2481.0f };\nstatic float TotalLengthOfTrack;\nstatic float TotalDurationOfTrack;\nstatic CTrainInterpolationLine aLineBits[17];\nstatic float EngineTrackPosition[2];\nstatic float EngineTrackSpeed[2];\n\nstatic CTrainNode* pTrackNodes_S;\nstatic int16 NumTrackNodes_S;\nstatic float StationDist_S[4] = { 55.0f, 1388.0f, 2337.0f, 3989.0f };\nstatic float TotalLengthOfTrack_S;\nstatic float TotalDurationOfTrack_S;\nstatic CTrainInterpolationLine aLineBits_S[18];\nstatic float EngineTrackPosition_S[4];\nstatic float EngineTrackSpeed_S[4];\n\nCVector CTrain::aStationCoors[3];\nCVector CTrain::aStationCoors_S[4];\n\nstatic bool bTrainArrivalAnnounced[3] = {false, false, false};\n\nCTrain::CTrain(int32 id, uint8 CreatedBy)\n : CVehicle(CreatedBy)\n{\n#ifdef GTA_TRAIN\n\tCVehicleModelInfo *mi = (CVehicleModelInfo*)CModelInfo::GetModelInfo(id);\n\tm_vehType = VEHICLE_TYPE_TRAIN;\n\tpHandling = mod_HandlingManager.GetHandlingData((tVehicleType)mi->m_handlingId);\n\tSetModelIndex(id);\n\n\tDoors[0].Init(0.8f, 0.0f, 1, 0);\n\tDoors[1].Init(-0.8f, 0.0f, 0, 0);\n\n\tm_fMass = 100000000.0f;\n\tm_fTurnMass = 100000000.0f;\n\tm_fAirResistance = 0.9994f;\n\tm_fElasticity = 0.05f;\n\n\tm_bProcessDoor = true;\n\tm_bTrainStopping = false;\n\tm_nTrackId = TRACK_ELTRAIN;\n\tm_nNumMaxPassengers = 5;\n\tm_nDoorTimer = CTimer::GetTimeInMilliseconds();\n\tm_nDoorState = TRAIN_DOOR_CLOSED;\n\n\tbUsesCollision = true;\n\tSetStatus(STATUS_TRAIN_MOVING);\n\n#ifdef FIX_BUGS\n\tm_isFarAway = true;\n#endif\n#else\n\tassert(0 && \"No trains in this game\");\n#endif\n}\n\nvoid\nCTrain::SetModelIndex(uint32 id)\n{\n#ifdef GTA_TRAIN\n\tint i;\n\n\tCVehicle::SetModelIndex(id);\n\tfor(i = 0; i < NUM_TRAIN_NODES; i++)\n\t\tm_aTrainNodes[i] = nil;\n\tCClumpModelInfo::FillFrameArray(GetClump(), m_aTrainNodes);\n#endif\n}\n\nvoid\nCTrain::ProcessControl(void)\n{\n#ifdef GTA_TRAIN\n\tif(gbModelViewer || m_isFarAway && (CTimer::GetFrameCounter() + m_nWagonId) & 0xF)\n\t\treturn;\n\n\tCTrainNode *trackNodes;\n\tint16 numTrackNodes;\n\tfloat totalLengthOfTrack;\n\tfloat *engineTrackPosition;\n\tfloat *engineTrackSpeed;\n\n\tif(m_nTrackId == TRACK_SUBWAY){\n\t\ttrackNodes = pTrackNodes_S;\n\t\tnumTrackNodes = NumTrackNodes_S;\n\t\ttotalLengthOfTrack = TotalLengthOfTrack_S;\n\t\tengineTrackPosition = EngineTrackPosition_S;\n\t\tengineTrackSpeed = EngineTrackSpeed_S;\n\t}else{\n\t\ttrackNodes = pTrackNodes;\n\t\tnumTrackNodes = NumTrackNodes;\n\t\ttotalLengthOfTrack = TotalLengthOfTrack;\n\t\tengineTrackPosition = EngineTrackPosition;\n\t\tengineTrackSpeed = EngineTrackSpeed;\n\t}\n\n\tfloat trackPositionRear = engineTrackPosition[m_nWagonGroup] - m_fWagonPosition;\n\tif(trackPositionRear < 0.0f)\n\t\ttrackPositionRear += totalLengthOfTrack;\n\n\t// Advance current node to appropriate position\n\tfloat pos1, pos2;\n\tint nextTrackNode = m_nCurTrackNode + 1;\n\tpos1 = trackNodes[m_nCurTrackNode].t;\n\tif(nextTrackNode < numTrackNodes)\n\t\tpos2 = trackNodes[nextTrackNode].t;\n\telse{\n\t\tnextTrackNode = 0;\n\t\tpos2 = totalLengthOfTrack;\n\t}\n\twhile(trackPositionRear < pos1 || trackPositionRear > pos2){\n\t\tm_nCurTrackNode = (m_nCurTrackNode+1) % numTrackNodes;\n\t\tnextTrackNode = m_nCurTrackNode + 1;\n\t\tpos1 = trackNodes[m_nCurTrackNode].t;\n\t\tif(nextTrackNode < numTrackNodes)\n\t\t\tpos2 = trackNodes[nextTrackNode].t;\n\t\telse{\n\t\t\tnextTrackNode = 0;\n\t\t\tpos2 = totalLengthOfTrack;\n\t\t}\n\t}\n\tfloat dist = trackNodes[nextTrackNode].t - trackNodes[m_nCurTrackNode].t;\n\tif(dist < 0.0f)\n\t\tdist += totalLengthOfTrack;\n\tfloat f = (trackPositionRear - trackNodes[m_nCurTrackNode].t)/dist;\n\tCVector posRear = (1.0f - f)*trackNodes[m_nCurTrackNode].p + f*trackNodes[nextTrackNode].p;\n\n\t// Now same again for the front\n\tfloat trackPositionFront = trackPositionRear + 20.0f;\n\tif(trackPositionFront > totalLengthOfTrack)\n\t\ttrackPositionFront -= totalLengthOfTrack;\n\tint curTrackNodeFront = m_nCurTrackNode;\n\tint nextTrackNodeFront = curTrackNodeFront + 1;\n\tpos1 = trackNodes[curTrackNodeFront].t;\n\tif(nextTrackNodeFront < numTrackNodes)\n\t\tpos2 = trackNodes[nextTrackNodeFront].t;\n\telse{\n\t\tnextTrackNodeFront = 0;\n\t\tpos2 = totalLengthOfTrack;\n\t}\n\twhile(trackPositionFront < pos1 || trackPositionFront > pos2){\n\t\tcurTrackNodeFront = (curTrackNodeFront+1) % numTrackNodes;\n\t\tnextTrackNodeFront = curTrackNodeFront + 1;\n\t\tpos1 = trackNodes[curTrackNodeFront].t;\n\t\tif(nextTrackNodeFront < numTrackNodes)\n\t\t\tpos2 = trackNodes[nextTrackNodeFront].t;\n\t\telse{\n\t\t\tnextTrackNodeFront = 0;\n\t\t\tpos2 = totalLengthOfTrack;\n\t\t}\n\t}\n\tdist = trackNodes[nextTrackNodeFront].t - trackNodes[curTrackNodeFront].t;\n\tif(dist < 0.0f)\n\t\tdist += totalLengthOfTrack;\n\tf = (trackPositionFront - trackNodes[curTrackNodeFront].t)/dist;\n\tCVector posFront = (1.0f - f)*trackNodes[curTrackNodeFront].p + f*trackNodes[nextTrackNodeFront].p;\n\n\t// Now set matrix\n\tSetPosition((posRear + posFront)/2.0f);\n\tCVector fwd = posFront - posRear;\n\tfwd.Normalise();\n\tCVector right = CrossProduct(fwd, CVector(0.0f, 0.0f, 1.0f));\n\tright.Normalise();\n\tCVector up = CrossProduct(right, fwd);\n\tGetRight() = right;\n\tGetUp() = up;\n\tGetForward() = fwd;\n\n\t// Set speed\n\tm_vecMoveSpeed = fwd*engineTrackSpeed[m_nWagonGroup]/60.0f;\n\tm_fSpeed = engineTrackSpeed[m_nWagonGroup]/60.0f;\n\tm_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f);\n\n\tif(engineTrackSpeed[m_nWagonGroup] > 0.001f){\n\t\tSetStatus(STATUS_TRAIN_MOVING);\n\t\tm_bTrainStopping = false;\n\t\tm_bProcessDoor = true;\n\t}else{\n\t\tSetStatus(STATUS_TRAIN_NOT_MOVING);\n\t\tm_bTrainStopping = true;\n\t}\n\n\tm_isFarAway = !((posFront - TheCamera.GetPosition()).Magnitude2D() < sq(250.0f));\n\n\tif(m_fWagonPosition == 20.0f && m_fSpeed > 0.0001f)\n\t\tif(Abs(TheCamera.GetPosition().z - GetPosition().z) < 15.0f)\n\t\t\tCPad::GetPad(0)->StartShake_Train(GetPosition().x, GetPosition().y);\n\n\tif(m_bProcessDoor)\n\t\tswitch(m_nDoorState){\n\t\tcase TRAIN_DOOR_CLOSED:\n\t\t\tif(m_bTrainStopping){\n\t\t\t\tm_nDoorTimer = CTimer::GetTimeInMilliseconds() + 1000;\n\t\t\t\tm_nDoorState = TRAIN_DOOR_OPENING;\n\t\t\t\tDMAudio.PlayOneShot(m_audioEntityId, SOUND_TRAIN_DOOR_CLOSE, 0.0f);\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase TRAIN_DOOR_OPENING:\n\t\t\tif(CTimer::GetTimeInMilliseconds() < m_nDoorTimer){\n\t\t\t\tOpenTrainDoor(1.0f - (m_nDoorTimer - CTimer::GetTimeInMilliseconds())/1000.0f);\n\t\t\t}else{\n\t\t\t\tOpenTrainDoor(1.0f);\n\t\t\t\tm_nDoorState = TRAIN_DOOR_OPEN;\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase TRAIN_DOOR_OPEN:\n\t\t\tif(!m_bTrainStopping){\n\t\t\t\tm_nDoorTimer = CTimer::GetTimeInMilliseconds() + 1000;\n\t\t\t\tm_nDoorState = TRAIN_DOOR_CLOSING;\n\t\t\t\tDMAudio.PlayOneShot(m_audioEntityId, SOUND_TRAIN_DOOR_OPEN, 0.0f);\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase TRAIN_DOOR_CLOSING:\n\t\t\tif(CTimer::GetTimeInMilliseconds() < m_nDoorTimer){\n\t\t\t\tOpenTrainDoor((m_nDoorTimer - CTimer::GetTimeInMilliseconds())/1000.0f);\n\t\t\t}else{\n\t\t\t\tOpenTrainDoor(0.0f);\n\t\t\t\tm_nDoorState = TRAIN_DOOR_CLOSED;\n\t\t\t\tm_bProcessDoor = false;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\tGetMatrix().UpdateRW();\n\tUpdateRwFrame();\n\tRemoveAndAdd();\n\n\tbIsStuck = false;\n\tbIsInSafePosition = true;\n\tbWasPostponed = false;\n\n\t// request/remove model\n\tif(m_isFarAway){\n\t\tif(m_rwObject)\n\t\t\tDeleteRwObject();\n\t}else if(CStreaming::HasModelLoaded(MI_TRAIN)){\n\t\tif(m_rwObject == nil){\n\t\t\tm_modelIndex = -1;\n\t\t\tSetModelIndex(MI_TRAIN);\n\t\t}\n\t}else{\n\t\tif(FindPlayerCoors().z * GetPosition().z >= 0.0f)\n\t\t\tCStreaming::RequestModel(MI_TRAIN, STREAMFLAGS_DEPENDENCY);\n\t}\n\n\t// Hit stuff\n\tif(m_bIsFirstWagon && GetStatus()== STATUS_TRAIN_MOVING){\n\t\tCVector front = GetPosition() + GetForward()*GetColModel()->boundingBox.max.y + m_vecMoveSpeed*CTimer::GetTimeStep();\n\n\t\tint x, xmin, xmax;\n\t\tint y, ymin, ymax;\n\n\t\txmin = CWorld::GetSectorIndexX(front.x - 3.0f);\n\t\tif(xmin < 0) xmin = 0;\n\t\txmax = CWorld::GetSectorIndexX(front.x + 3.0f);\n\t\tif(xmax > NUMSECTORS_X-1) xmax = NUMSECTORS_X-1;\n\t\tymin = CWorld::GetSectorIndexY(front.y - 3.0f);\n\t\tif(ymin < 0) ymin = 0;\n\t\tymax = CWorld::GetSectorIndexY(front.y + 3.0f);\n\t\tif(ymax > NUMSECTORS_Y-1) ymax = NUMSECTORS_X-1;\n\n\t\tCWorld::AdvanceCurrentScanCode();\n\n\t\tfor(y = ymin; y <= ymax; y++)\n\t\t\tfor(x = xmin; x <= xmax; x++){\n\t\t\t\tCSector *s = CWorld::GetSector(x, y);\n\t\t\t\tTrainHitStuff(s->m_lists[ENTITYLIST_VEHICLES]);\n\t\t\t\tTrainHitStuff(s->m_lists[ENTITYLIST_VEHICLES_OVERLAP]);\n\t\t\t\tTrainHitStuff(s->m_lists[ENTITYLIST_PEDS]);\n\t\t\t\tTrainHitStuff(s->m_lists[ENTITYLIST_PEDS_OVERLAP]);\n\t\t\t}\n\t}\n#endif GTA_TRAIN\n}\n\nvoid\nCTrain::PreRender(void)\n{\n#ifdef GTA_TRAIN\n\tCVehicleModelInfo *mi = (CVehicleModelInfo*)CModelInfo::GetModelInfo(GetModelIndex());\n\n\tif(m_bIsFirstWagon){\n\t\tCVector lookVector = GetPosition() - TheCamera.GetPosition();\n\t\tfloat camDist = lookVector.Magnitude();\n\t\tif(camDist != 0.0f)\n\t\t\tlookVector *= 1.0f/camDist;\n\t\telse\n\t\t\tlookVector = CVector(1.0f, 0.0f, 0.0f);\n\t\tfloat behindness = DotProduct(lookVector, GetForward());\n\n\t\tif(behindness < 0.0f){\n\t\t\t// In front of train\n\t\t\tCVector lightPos = mi->m_positions[TRAIN_POS_LIGHT_FRONT];\n\t\t\tCVector lightR = GetMatrix() * lightPos;\n\t\t\tCVector lightL = lightR;\n\t\t\tlightL -= GetRight()*2.0f*lightPos.x;\n\n\t\t\tfloat intensity = -0.4f*behindness + 0.2f;\n\t\t\tfloat size = 1.0f - behindness;\n\n\t\t\tif(behindness < -0.9f && camDist < 35.0f){\n\t\t\t\t// directly in front\n\t\t\t\tCCoronas::RegisterCorona((uintptr)this + 10, 255*intensity, 255*intensity, 255*intensity, 255,\n\t\t\t\t\tlightL, size, 80.0f,\n\t\t\t\t\tCCoronas::TYPE_NORMAL, CCoronas::FLARE_HEADLIGHTS, CCoronas::REFLECTION_ON,\n\t\t\t\t\tCCoronas::LOSCHECK_OFF, CCoronas::STREAK_ON, 0.0f);\n\t\t\t\tCCoronas::RegisterCorona((uintptr)this + 11, 255*intensity, 255*intensity, 255*intensity, 255,\n\t\t\t\t\tlightR, size, 80.0f,\n\t\t\t\t\tCCoronas::TYPE_NORMAL, CCoronas::FLARE_HEADLIGHTS, CCoronas::REFLECTION_ON,\n\t\t\t\t\tCCoronas::LOSCHECK_OFF, CCoronas::STREAK_ON, 0.0f);\n\t\t\t}else{\n\t\t\t\tCCoronas::RegisterCorona((uintptr)this + 10, 255*intensity, 255*intensity, 255*intensity, 255,\n\t\t\t\t\tlightL, size, 80.0f,\n\t\t\t\t\tCCoronas::TYPE_NORMAL, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON,\n\t\t\t\t\tCCoronas::LOSCHECK_OFF, CCoronas::STREAK_ON, 0.0f);\n\t\t\t\tCCoronas::RegisterCorona((uintptr)this + 11, 255*intensity, 255*intensity, 255*intensity, 255,\n\t\t\t\t\tlightR, size, 80.0f,\n\t\t\t\t\tCCoronas::TYPE_NORMAL, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON,\n\t\t\t\t\tCCoronas::LOSCHECK_OFF, CCoronas::STREAK_ON, 0.0f);\n\t\t\t}\n\t\t}\n\t}\n\n\tif(m_bIsLastWagon){\n\t\tCVector lightPos = mi->m_positions[TRAIN_POS_LIGHT_REAR];\n\t\tCVector lightR = GetMatrix() * lightPos;\n\t\tCVector lightL = lightR;\n\t\tlightL -= GetRight()*2.0f*lightPos.x;\n\n\t\tCCoronas::RegisterCorona((uintptr)this + 12, 255, 0, 0, 255,\n\t\t\tlightL, 1.0f, 80.0f,\n\t\t\tCCoronas::TYPE_NORMAL, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON,\n\t\t\tCCoronas::LOSCHECK_OFF, CCoronas::STREAK_ON, 0.0f);\n\t\tCCoronas::RegisterCorona((uintptr)this + 13, 255, 0, 0, 255,\n\t\t\tlightR, 1.0f, 80.0f,\n\t\t\tCCoronas::TYPE_NORMAL, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON,\n\t\t\tCCoronas::LOSCHECK_OFF, CCoronas::STREAK_ON, 0.0f);\n\t}\n#endif\n}\n\nvoid\nCTrain::Render(void)\n{\n#ifdef GTA_TRAIN\n\tCEntity::Render();\n#endif\n}\n\nvoid\nCTrain::TrainHitStuff(CPtrList &list)\n{\n#ifdef GTA_TRAIN\n\tCPtrNode *node;\n\tCPhysical *phys;\n\n\tfor(node = list.first; node; node = node->next){\n\t\tphys = (CPhysical*)node->item;\n\t\tif(phys != this && Abs(this->GetPosition().z - phys->GetPosition().z) < 1.5f)\n\t\t\tphys->bHitByTrain = true;\n\t}\n#endif\n}\n\nvoid\nCTrain::AddPassenger(CPed *ped)\n{\n#ifdef GTA_TRAIN\n\tint i = ped->m_vehDoor;\n\tif((i == TRAIN_POS_LEFT_ENTRY || i == TRAIN_POS_MID_ENTRY || i == TRAIN_POS_RIGHT_ENTRY) && pPassengers[i] == nil){\n\t\tpPassengers[i] = ped;\n\t\tm_nNumPassengers++;\n\t}else{\n\t\tfor(i = 0; i < 6; i++)\n\t\t\tif(pPassengers[i] == nil){\n\t\t\t\tpPassengers[i] = ped;\n\t\t\t\tm_nNumPassengers++;\n\t\t\t\treturn;\n\t\t\t}\n\t}\n#endif\n}\n\nvoid\nCTrain::OpenTrainDoor(float ratio)\n{\n#ifdef GTA_TRAIN\n\tif(m_rwObject == nil)\n\t\treturn;\n\n\tCMatrix doorL(RwFrameGetMatrix(m_aTrainNodes[TRAIN_DOOR_LHS]));\n\tCMatrix doorR(RwFrameGetMatrix(m_aTrainNodes[TRAIN_DOOR_RHS]));\n\tCVector posL = doorL.GetPosition();\n\tCVector posR = doorR.GetPosition();\n\n\tbool isClosed = Doors[0].IsClosed();\t// useless\n\n\tDoors[0].Open(ratio);\n\tDoors[1].Open(ratio);\n\n\tif(isClosed)\n\t\tDoors[0].RetTranslationWhenClosed();\t// useless\n\n\tposL.y = Doors[0].m_fPosn;\n\tposR.y = Doors[1].m_fPosn;\n\n\tdoorL.SetTranslate(posL);\n\tdoorR.SetTranslate(posR);\n\n\tdoorL.UpdateRW();\n\tdoorR.UpdateRW();\n#endif\n}\n\n\n\nvoid\nCTrain::InitTrains(void)\n{\n#ifdef GTA_TRAIN\n\tint i, j;\n\tCTrain *train;\n\n\t// El train\n\tif(pTrackNodes == nil)\n\t\tReadAndInterpretTrackFile(\"data\\\\paths\\\\tracks.dat\", &pTrackNodes, &NumTrackNodes, 3, StationDist,\n\t\t\t&TotalLengthOfTrack, &TotalDurationOfTrack, aLineBits, false);\n\t// Subway\n\tif(pTrackNodes_S == nil)\n\t\tReadAndInterpretTrackFile(\"data\\\\paths\\\\tracks2.dat\", &pTrackNodes_S, &NumTrackNodes_S, 4, StationDist_S,\n\t\t\t&TotalLengthOfTrack_S, &TotalDurationOfTrack_S, aLineBits_S, true);\n\n\tint trainId;\n\tCStreaming::LoadAllRequestedModels(false);\n\tif(CModelInfo::GetModelInfo(\"train\", &trainId))\n\t\tCStreaming::RequestModel(trainId, 0);\n\tCStreaming::LoadAllRequestedModels(false);\n\n\t// El-Train wagons\n\tfloat wagonPositions[] = { 0.0f, 20.0f, 40.0f,  0.0f, 20.0f };\n\tint8 firstWagon[]  = { 1, 0, 0,  1, 0 };\n\tint8 lastWagon[]   = { 0, 0, 1,  0, 1 };\n\tint16 wagonGroup[] = { 0, 0, 0,  1, 1 };\n\tfor(i = 0; i < 5; i++){\n\t\ttrain = new CTrain(MI_TRAIN, PERMANENT_VEHICLE);\n\t\ttrain->GetMatrix().SetTranslate(0.0f, 0.0f, 0.0f);\n\t\ttrain->SetStatus(STATUS_ABANDONED);\n\t\ttrain->bIsLocked = true;\n\t\ttrain->m_fWagonPosition = wagonPositions[i];\n\t\ttrain->m_bIsFirstWagon = firstWagon[i];\n\t\ttrain->m_bIsLastWagon = lastWagon[i];\n\t\ttrain->m_nWagonGroup = wagonGroup[i];\n\t\ttrain->m_nWagonId = i;\n\t\ttrain->m_nCurTrackNode = 0;\n\t\tCWorld::Add(train);\n\t}\n\n\t// Subway wagons\n\tfloat wagonPositions_S[] = { 0.0f, 20.0f,  0.0f, 20.0f,  0.0f, 20.0f,  0.0f, 20.0f };\n\tint8 firstWagon_S[]  = { 1, 0,  1, 0,  1, 0,  1, 0 };\n\tint8 lastWagon_S[]   = { 0, 1,  0, 1,  0, 1,  0, 1 };\n\tint16 wagonGroup_S[] = { 0, 0,  1, 1,  2, 2,  3, 3 };\n\tfor(i = 0; i < 8; i++){\n\t\ttrain = new CTrain(MI_TRAIN, PERMANENT_VEHICLE);\n\t\ttrain->GetMatrix().SetTranslate(0.0f, 0.0f, 0.0f);\n\t\ttrain->SetStatus(STATUS_ABANDONED);\n\t\ttrain->bIsLocked = true;\n\t\ttrain->m_fWagonPosition = wagonPositions_S[i];\n\t\ttrain->m_bIsFirstWagon = firstWagon_S[i];\n\t\ttrain->m_bIsLastWagon = lastWagon_S[i];\n\t\ttrain->m_nWagonGroup = wagonGroup_S[i];\n\t\ttrain->m_nWagonId = i;\n\t\ttrain->m_nCurTrackNode = 0;\n\t\ttrain->m_nTrackId = TRACK_SUBWAY;\n\t\tCWorld::Add(train);\n\t}\n\n\t// This code is actually useless, it seems it was used for announcements once\n\tfor(i = 0; i < 3; i++){\n\t\tfor(j = 0; pTrackNodes[j].t < StationDist[i]; j++);\n\t\taStationCoors[i] = pTrackNodes[j].p;\n\t}\n\tfor(i = 0; i < 4; i++){\n\t\tfor(j = 0; pTrackNodes_S[j].t < StationDist_S[i]; j++);\n\t\taStationCoors_S[i] = pTrackNodes_S[j].p;\n\t}\n#endif\n}\n\nvoid\nCTrain::Shutdown(void)\n{\n#ifdef GTA_TRAIN\n\tdelete[] pTrackNodes;\n\tdelete[] pTrackNodes_S;\n\tpTrackNodes = nil;\n\tpTrackNodes_S = nil;\n#endif\n}\n\nvoid\nCTrain::ReadAndInterpretTrackFile(Const char *filename, CTrainNode **nodes, int16 *numNodes, int32 numStations, float *stationDists,\n\t\tfloat *totalLength, float *totalDuration, CTrainInterpolationLine *interpLines, bool rightRail)\n{\n#ifdef GTA_TRAIN\n\tbool readingFile = false;\n\tint bp, lp;\n\tint i, tmp;\n\n\tif(*nodes == nil){\n\t\treadingFile = true;\n\n\t\tCFileMgr::LoadFile(filename, work_buff, sizeof(work_buff), \"r\");\n\t\t*gString = '\\0';\n\t\tfor(bp = 0, lp = 0; work_buff[bp] != '\\n'; bp++, lp++)\n\t\t\tgString[lp] = work_buff[bp];\n\t\tbp++;\n\t\t// BUG: game doesn't terminate string and uses numNodes in sscanf directly\n\t\tgString[lp] = '\\0';\n\t\tsscanf(gString, \"%d\", &tmp);\n\t\t*numNodes = tmp;\n\t\t*nodes = new CTrainNode[*numNodes];\n\n\t\tfor(i = 0; i < *numNodes; i++){\n\t\t\t*gString = '\\0';\n\t\t\tfor(lp = 0; work_buff[bp] != '\\n'; bp++, lp++)\n\t\t\t\tgString[lp] = work_buff[bp];\n\t\t\tbp++;\n\t\t\t// BUG: game doesn't terminate string\n\t\t\tgString[lp] = '\\0';\n\t\t\tsscanf(gString, \"%f %f %f\", &(*nodes)[i].p.x, &(*nodes)[i].p.y, &(*nodes)[i].p.z);\n\t\t}\n\n\t\t// Coordinates are of one of the rails, but we want the center\n\t\tfloat toCenter = rightRail ? 0.9f : -0.9f;\n\t\tCVector fwd;\n\t\tfor(i = 0; i < *numNodes; i++){\n\t\t\tif(i == *numNodes-1)\n\t\t\t\tfwd = (*nodes)[0].p - (*nodes)[i].p;\n\t\t\telse\n\t\t\t\tfwd = (*nodes)[i+1].p - (*nodes)[i].p;\n\t\t\tCVector right = CrossProduct(fwd, CVector(0.0f, 0.0f, 1.0f));\n\t\t\tright.Normalise();\n\t\t\t(*nodes)[i].p -= right*toCenter;\n\t\t}\n\t}\n\n\t// Calculate length of segments and track\n\tfloat t = 0.0f;\n\tfor(i = 0; i < *numNodes; i++){\n\t\t(*nodes)[i].t = t;\n\t\tt += ((*nodes)[(i+1) % (*numNodes)].p - (*nodes)[i].p).Magnitude2D();\n\t}\n\t*totalLength = t;\n\n\t// Find correct z values\n\tif(readingFile){\n\t\tCColPoint colpoint;\n\t\tCEntity *entity;\n\t\tfor(i = 0; i < *numNodes; i++){\n\t\t\tCVector p = (*nodes)[i].p;\n\t\t\tp.z += 1.0f;\n\t\t\tif(CWorld::ProcessVerticalLine(p, p.z-0.5f, colpoint, entity, true, false, false, false, true, false, nil))\n\t\t\t\t(*nodes)[i].p.z = colpoint.point.z;\n\t\t\t(*nodes)[i].p.z += 0.2f;\n\t\t}\n\t}\n\n\t// Create animation for stopping at stations\n\t// TODO: figure out magic numbers?\n\tfloat position = 0.0f;\n\tfloat time = 0.0f;\n\tint j = 0;\n\tfor(i = 0; i < numStations; i++){\n\t\t// Start at full speed\n\t\tinterpLines[j].type = 1;\n\t\tinterpLines[j].time = time;\n\t\tinterpLines[j].position = position;\n\t\tinterpLines[j].speed = 15.0f;\n\t\tinterpLines[j].acceleration = 0.0f;\n\t\tj++;\n\t\t// distance to next keyframe\n\t\tfloat dist = (stationDists[i]-40.0f) - position;\n\t\ttime += dist/15.0f;\n\t\tposition += dist;\n\n\t\t// Now slow down 40 units before stop\n\t\tinterpLines[j].type = 2;\n\t\tinterpLines[j].time = time;\n\t\tinterpLines[j].position = position;\n\t\tinterpLines[j].speed = 15.0f;\n\t\tinterpLines[j].acceleration = -45.0f/32.0f;\n\t\tj++;\n\t\ttime += 80.0f/15.0f;\n\t\tposition += 40.0f;\t// at station\n\n\t\t// stopping\n\t\tinterpLines[j].type = 0;\n\t\tinterpLines[j].time = time;\n\t\tinterpLines[j].position = position;\n\t\tinterpLines[j].speed = 0.0f;\n\t\tinterpLines[j].acceleration = 0.0f;\n\t\tj++;\n\t\ttime += 25.0f;\n\n\t\t// accelerate again\n\t\tinterpLines[j].type = 2;\n\t\tinterpLines[j].time = time;\n\t\tinterpLines[j].position = position;\n\t\tinterpLines[j].speed = 0.0f;\n\t\tinterpLines[j].acceleration = 45.0f/32.0f;\n\t\tj++;\n\t\ttime += 80.0f/15.0f;\n\t\tposition += 40.0f;\t// after station\n\t}\n\t// last keyframe\n\tinterpLines[j].type = 1;\n\tinterpLines[j].time = time;\n\tinterpLines[j].position = position;\n\tinterpLines[j].speed = 15.0f;\n\tinterpLines[j].acceleration = 0.0f;\n\tj++;\n\t*totalDuration = time + (*totalLength - position)/15.0f;\n\n\t// end\n\tinterpLines[j].time = *totalDuration;\n#endif\n}\n\nvoid\nPlayAnnouncement(uint8 sound, uint8 station)\n{\n\t// this was gone in a PC version but inlined on PS2\n\tcAudioScriptObject *obj = new cAudioScriptObject;\n\tobj->AudioId = sound;\n\tobj->Posn = CTrain::aStationCoors[station];\n\tobj->AudioEntity = AEHANDLE_NONE;\n\tDMAudio.CreateOneShotScriptObject(obj);\n}\n\nvoid\nProcessTrainAnnouncements(void)\n{\n#ifdef GTA_TRAIN\n\tfor (int i = 0; i < ARRAY_SIZE(StationDist); i++) {\n\t\tfor (int j = 0; j < ARRAY_SIZE(EngineTrackPosition); j++) {\n\t\t\tif (!bTrainArrivalAnnounced[i]) {\n\t\t\t\tfloat preDist = StationDist[i] - 100.0f;\n\t\t\t\tif (preDist < 0.0f)\n\t\t\t\t\tpreDist += TotalLengthOfTrack;\n\t\t\t\tif (EngineTrackPosition[j] > preDist && EngineTrackPosition[j] < StationDist[i]) {\n\t\t\t\t\tbTrainArrivalAnnounced[i] = true;\n\t\t\t\t\tPlayAnnouncement(SCRIPT_SOUND_TRAIN_ANNOUNCEMENT_1, i);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfloat postDist = StationDist[i] + 10.0f;\n#ifdef FIX_BUGS\n\t\t\t\tif (postDist > TotalLengthOfTrack)\n\t\t\t\t\tpostDist -= TotalLengthOfTrack;\n#else\n\t\t\t\tif (postDist < 0.0f) // does this even make sense here?\n\t\t\t\t\tpostDist += TotalLengthOfTrack;\n#endif\n\t\t\t\tif (EngineTrackPosition[j] > StationDist[i] && EngineTrackPosition[j] < postDist) {\n\t\t\t\t\tbTrainArrivalAnnounced[i] = false;\n\t\t\t\t\tPlayAnnouncement(SCRIPT_SOUND_TRAIN_ANNOUNCEMENT_2, i);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n#endif\n}\n\nvoid\nCTrain::UpdateTrains(void)\n{\n#ifdef GTA_TRAIN\n\tint i, j;\n\tuint32 time;\n\tfloat t, deltaT;\n\n\tif(TheCamera.GetPosition().x > 200.0f && TheCamera.GetPosition().x < 1600.0f &&\n\t   TheCamera.GetPosition().y > -1000.0f && TheCamera.GetPosition().y < 500.0f){\n\t\t// Update El-Train\n\n\t\ttime = CTimer::GetTimeInMilliseconds();\n\t\tfor(i = 0; i < 2; i++){\n\t\t\tt = TotalDurationOfTrack * (float)(time & 0x1FFFF)/0x20000;\n\t\t\t// find current frame\n\t\t\tfor(j = 0; t > aLineBits[j+1].time; j++);\n\n\t\t\tdeltaT = t - aLineBits[j].time;\n\t\t\tswitch(aLineBits[j].type){\n\t\t\tcase 0:\t// standing still\n\t\t\t\tEngineTrackPosition[i] = aLineBits[j].position;\n\t\t\t\tEngineTrackSpeed[i] = 0.0f;\n\t\t\t\tbreak;\n\t\t\tcase 1:\t// moving with constant speed\n\t\t\t\tEngineTrackPosition[i] = aLineBits[j].position + aLineBits[j].speed*deltaT;\n\t\t\t\tEngineTrackSpeed[i] = (TotalDurationOfTrack*1000.0f/0x20000) * aLineBits[j].speed;\n\t\t\t\tbreak;\n\t\t\tcase 2:\t// accelerating/braking\n\t\t\t\tEngineTrackPosition[i] = aLineBits[j].position + (aLineBits[j].speed + aLineBits[j].acceleration*deltaT)*deltaT;\n\t\t\t\tEngineTrackSpeed[i] = (TotalDurationOfTrack*1000.0f/0x20000)*aLineBits[j].speed + 2.0f*aLineBits[j].acceleration*deltaT;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t// time offset for each train\n\t\t\ttime += 0x20000/2;\n\t\t}\n\n\t\tProcessTrainAnnouncements();\n\t}\n\n\t// Update Subway\n\ttime = CTimer::GetTimeInMilliseconds();\n\tfor(i = 0; i < 4; i++){\n\t\tt = TotalDurationOfTrack_S * (float)(time & 0x3FFFF)/0x40000;\n\t\t// find current frame\n\t\tfor(j = 0; t > aLineBits_S[j+1].time; j++);\n\n\t\tdeltaT = t - aLineBits_S[j].time;\n\t\tswitch(aLineBits_S[j].type){\n\t\tcase 0:\t// standing still\n\t\t\tEngineTrackPosition_S[i] = aLineBits_S[j].position;\n\t\t\tEngineTrackSpeed_S[i] = 0.0f;\n\t\t\tbreak;\n\t\tcase 1:\t// moving with constant speed\n\t\t\tEngineTrackPosition_S[i] = aLineBits_S[j].position + aLineBits_S[j].speed*deltaT;\n\t\t\tEngineTrackSpeed_S[i] = (TotalDurationOfTrack*1000.0f/0x40000) * aLineBits_S[j].speed;\n\t\t\tbreak;\n\t\tcase 2:\t// accelerating/braking\n\t\t\tEngineTrackPosition_S[i] = aLineBits_S[j].position + (aLineBits_S[j].speed + aLineBits_S[j].acceleration*deltaT)*deltaT;\n\t\t\tEngineTrackSpeed_S[i] = (TotalDurationOfTrack*1000.0f/0x40000)*aLineBits_S[j].speed + 2.0f*aLineBits_S[j].acceleration*deltaT;\n\t\t\tbreak;\n\t\t}\n\n\t\t// time offset for each train\n\t\ttime += 0x40000/4;\n\t}\n#endif\n}\n"
  },
  {
    "path": "src/vehicles/Train.h",
    "content": "#pragma once\n\n#include \"Vehicle.h\"\n#include \"Door.h\"\n\nenum\n{\n\tTRACK_ELTRAIN,\n\tTRACK_SUBWAY\n};\n\nenum\n{\n\tTRAIN_DOOR_CLOSED,\n\tTRAIN_DOOR_OPENING,\n\tTRAIN_DOOR_OPEN,\n\tTRAIN_DOOR_CLOSING\n};\n\nenum eTrainNodes\n{\n\tTRAIN_DOOR_LHS = 1,\n\tTRAIN_DOOR_RHS,\n\tNUM_TRAIN_NODES\n};\n\nstruct CTrainNode\n{\n\tCVector p;\t// position\n\tfloat t;\t// xy-distance from start on track\n};\n\nstruct CTrainInterpolationLine\n{\n\tuint8 type;\n\tfloat time;\t// when does this keyframe start\n\t// initial values at start of frame\n\tfloat position;\n\tfloat speed;\n\tfloat acceleration;\n};\n\nclass CTrain : public CVehicle\n{\npublic:\n\t// 0x288\n\tfloat m_fWagonPosition;\n\tint16 m_nWagonId;\n\tint16 m_isFarAway;\t// don't update so often?\n\tint16 m_nCurTrackNode;\n\tint16 m_nWagonGroup;\n\tfloat m_fSpeed;\n\tbool m_bProcessDoor;\n\tbool m_bTrainStopping;\n\tbool m_bIsFirstWagon;\n\tbool m_bIsLastWagon;\n\tuint8 m_nTrackId;\t// or m_bUsesSubwayTracks?\n\tuint32 m_nDoorTimer;\n\tint16 m_nDoorState;\n\tCTrainDoor Doors[2];\n\tRwFrame *m_aTrainNodes[NUM_TRAIN_NODES];\n\n\t// unused\n\tstatic CVector aStationCoors[3];\n\tstatic CVector aStationCoors_S[4];\n\n\tCTrain(int32 id, uint8 CreatedBy);\n\n\t// from CEntity\n\tvoid SetModelIndex(uint32 id);\n\tvoid ProcessControl(void);\n\tvoid PreRender(void);\n\tvoid Render(void);\n\n\tvoid AddPassenger(CPed *ped);\n\tvoid OpenTrainDoor(float ratio);\n\tvoid TrainHitStuff(CPtrList &list);\n\n\tstatic void InitTrains(void);\n\tstatic void Shutdown(void);\n\tstatic void ReadAndInterpretTrackFile(Const char *filename, CTrainNode **nodes, int16 *numNodes, int32 numStations, float *stationDists,\n\t\tfloat *totalLength, float *totalDuration, CTrainInterpolationLine *interpLines, bool rightRail);\n\tstatic void UpdateTrains(void);\n};\n"
  },
  {
    "path": "src/vehicles/Transmission.cpp",
    "content": "#include \"common.h\"\n\n#include \"Timer.h\"\n#include \"HandlingMgr.h\"\n#include \"Transmission.h\"\n\nvoid\ncTransmission::InitGearRatios(void)\n{\n\tstatic tGear *pGearRatio0 = nil;\n\tstatic tGear *pGearRatio1 = nil;\n\tint i;\n\tfloat velocityDiff;\n\n\tmemset(Gears, 0, sizeof(Gears));\n\n\tfor(i = 1; i <= nNumberOfGears; i++){\n\t\tpGearRatio0 = &Gears[i-1];\n\t\tpGearRatio1 = &Gears[i];\n\n\t\tpGearRatio1->fMaxVelocity = (float)i / nNumberOfGears * fMaxVelocity;\n\n\t\tvelocityDiff = pGearRatio1->fMaxVelocity - pGearRatio0->fMaxVelocity;\n\n\t\tif(i >= nNumberOfGears){\n\t\t\tpGearRatio1->fShiftUpVelocity = fMaxVelocity;\n\t\t}else{\n\t\t\tGears[i+1].fShiftDownVelocity = velocityDiff*0.42f + pGearRatio0->fMaxVelocity;\n\t\t\tpGearRatio1->fShiftUpVelocity = velocityDiff*0.6667f + pGearRatio0->fMaxVelocity;\n\t\t}\n\t}\n\n\t// Reverse gear\n\tGears[0].fMaxVelocity = fMaxReverseVelocity;\n\tGears[0].fShiftUpVelocity = -0.01f;\n\tGears[0].fShiftDownVelocity = fMaxReverseVelocity;\n\n\tGears[1].fShiftDownVelocity = -0.01f;\n}\n\nvoid\ncTransmission::CalculateGearForSimpleCar(float speed, uint8 &gear)\n{\n\tstatic tGear *pGearRatio;\n\n\tpGearRatio = &Gears[gear];\n\tfCurVelocity = speed;\n\tif(speed > pGearRatio->fShiftUpVelocity)\n\t\tgear++;\n\telse if(speed < pGearRatio->fShiftDownVelocity){\n\t\tif(gear - 1 < 0)\n\t\t\tgear = 0;\n\t\telse\n\t\t\tgear--;\n\t}\n}\n\nfloat\ncTransmission::CalculateDriveAcceleration(const float &gasPedal, uint8 &gear, float &time, const float &velocity, bool cheat)\n{\n\tstatic float fAcceleration = 0.0f;\n\tstatic float fVelocity;\n\tstatic float fCheat;\n\tstatic tGear *pGearRatio;\n\n\tfVelocity = velocity;\n\tif(fVelocity < fMaxReverseVelocity){\n\t\tfVelocity = fMaxReverseVelocity;\n\t\treturn 0.0f;\n\t}\n\tif(fVelocity > fMaxVelocity){\n\t\tfVelocity = fMaxVelocity;\n\t\treturn 0.0f;\n\t}\n\tfCurVelocity = fVelocity;\n\n\tassert(gear <= nNumberOfGears);\n\n\tpGearRatio = &Gears[gear];\n\tif(fVelocity > pGearRatio->fShiftUpVelocity){\n\t\tif(gear != 0 || gasPedal > 0.0f){\n\t\t\tgear++;\n\t\t\treturn CalculateDriveAcceleration(gasPedal, gear, time, fVelocity, false);\n\t\t}\n\t}else if(fVelocity < pGearRatio->fShiftDownVelocity && gear != 0){\n\t\tif(gear != 1 || gasPedal < 0.0f){\n\t\t\tgear--;\n\t\t\treturn CalculateDriveAcceleration(gasPedal, gear, time, fVelocity, false);\n\t\t}\n\t}\n\n\tfloat speedMul, accelMul;\n\n\tif(gear < 1){\n\t\t// going reverse\n\t\taccelMul = (Flags & HANDLING_2G_BOOST) ? 2.0f : 1.0f;\n\t\tspeedMul = -1.0f;\n\t}else if(nNumberOfGears == 1){\n\t\taccelMul = 1.0f;\n\t\tspeedMul = 1.0f;\n\t}else{\n\t\t// BUG or not? this is 1.0 normally but 0.0 in the highest gear\n\t\tfloat f = 1.0f - (gear-1)/(nNumberOfGears-1);\n\t\tspeedMul = 3.0f*sq(f) + 1.0f;\n\t\t// This is pretty ugly, could be written more clearly\n\t\tif(Flags & HANDLING_2G_BOOST){\n\t\t\tif(gear == 1)\n\t\t\t\taccelMul = (Flags & HANDLING_1G_BOOST) ? 2.0f : 1.6f;\n\t\t\telse if(gear == 2)\n\t\t\t\taccelMul = 1.3f;\n\t\t\telse\n\t\t\t\taccelMul = 1.0f;\n\t\t}else if(Flags & HANDLING_1G_BOOST && gear == 1){\n\t\t\taccelMul = 2.0f;\n\t\t}else\n\t\t\taccelMul = 1.0f;\n\t}\n\n\tif(cheat)\n\t\tfCheat = 1.2f;\n\telse\n\t\tfCheat = 1.0f;\n\tfloat targetVelocity = Gears[gear].fMaxVelocity*speedMul*fCheat;\n\tfloat accel = (targetVelocity - fVelocity) * (fEngineAcceleration*accelMul) / Abs(targetVelocity);\n\tif(Abs(fVelocity) < Abs(Gears[gear].fMaxVelocity*fCheat))\n\t\tfAcceleration = gasPedal * accel * CTimer::GetTimeStep();\n\telse\n\t\tfAcceleration = 0.0f;\n\treturn fAcceleration;\n}\n"
  },
  {
    "path": "src/vehicles/Transmission.h",
    "content": "#pragma once\n\nstruct tGear\n{\n\tfloat fMaxVelocity;\n\tfloat fShiftUpVelocity;\n\tfloat fShiftDownVelocity;\n};\n\nclass cTransmission\n{\npublic:\n\t// Gear 0 is reverse, 1-5 are forward\n\ttGear Gears[6];\n\tchar nDriveType;\n\tchar nEngineType;\n\tint8 nNumberOfGears;\n\tuint8 Flags;\n\tfloat fEngineAcceleration;\n\tfloat fMaxVelocity;\n\tfloat fMaxCruiseVelocity;\n\tfloat fMaxReverseVelocity;\n\tfloat fCurVelocity;\n\n\tvoid InitGearRatios(void);\n\tvoid CalculateGearForSimpleCar(float speed, uint8 &gear);\n\tfloat CalculateDriveAcceleration(const float &gasPedal, uint8 &gear, float &time, const float &velocity, bool cheat);\n};\n"
  },
  {
    "path": "src/vehicles/Vehicle.cpp",
    "content": "#include \"common.h\"\n#include \"main.h\"\n\n#include \"General.h\"\n#include \"Timer.h\"\n#include \"Pad.h\"\n#include \"Vehicle.h\"\n#include \"Bike.h\"\n#include \"Automobile.h\"\n#include \"Pools.h\"\n#include \"HandlingMgr.h\"\n#include \"CarCtrl.h\"\n#include \"Population.h\"\n#include \"ModelIndices.h\"\n#include \"World.h\"\n#include \"Lights.h\"\n#include \"PointLights.h\"\n#include \"Renderer.h\"\n#include \"VisibilityPlugins.h\"\n#include \"DMAudio.h\"\n#include \"Radar.h\"\n#include \"Fire.h\"\n#include \"Darkel.h\"\n#include \"Streaming.h\"\n#include \"Camera.h\"\n#include \"Stats.h\"\n#include \"Garages.h\"\n#include \"Wanted.h\"\n#include \"SurfaceTable.h\"\n#include \"Particle.h\"\n#include \"WaterLevel.h\"\n#include \"Timecycle.h\"\n#include \"Weather.h\"\n#include \"Coronas.h\"\n\nbool CVehicle::bWheelsOnlyCheat;\nbool CVehicle::bAllDodosCheat;\nbool CVehicle::bCheat3;\nbool CVehicle::bCheat4;\nbool CVehicle::bCheat5;\nbool CVehicle::bCheat8;\nbool CVehicle::bCheat9;\nbool CVehicle::bCheat10;\nbool CVehicle::bHoverCheat;\nbool CVehicle::bAllTaxisHaveNitro;\nbool CVehicle::m_bDisableMouseSteering = true;\nbool CVehicle::bDisableRemoteDetonation;\nbool CVehicle::bDisableRemoteDetonationOnContact;\n#ifndef MASTER\nbool CVehicle::m_bDisplayHandlingInfo;\n#endif\n\nvoid *CVehicle::operator new(size_t sz) { return CPools::GetVehiclePool()->New();  }\nvoid *CVehicle::operator new(size_t sz, int handle) { return CPools::GetVehiclePool()->New(handle); }\nvoid CVehicle::operator delete(void *p, size_t sz) { CPools::GetVehiclePool()->Delete((CVehicle*)p); }\nvoid CVehicle::operator delete(void *p, int handle) { CPools::GetVehiclePool()->Delete((CVehicle*)p); }\n\n#ifdef FIX_BUGS\n// I think they meant that\n#define DAMAGE_FLEE_IN_CAR_PROBABILITY_VALUE (MYRAND_MAX * 35 / 100)\n#define DAMAGE_FLEE_ON_FOOT_PROBABILITY_VALUE (MYRAND_MAX * 70 / 100)\n#else\n#define DAMAGE_FLEE_IN_CAR_PROBABILITY_VALUE (35000)\n#define DAMAGE_FLEE_ON_FOOT_PROBABILITY_VALUE (70000)\n#endif\n#define DAMAGE_HEALTH_TO_FLEE_ALWAYS (200.0f)\n#define DAMAGE_HEALTH_TO_CATCH_FIRE (250.0f)\n\n\nCVehicle::CVehicle(uint8 CreatedBy)\n{\n\tint i;\n\n\tm_nCurrentGear = 1;\n\tm_fChangeGearTime = 0.0f;\n\tm_fSteerInput = 0.0f;\n\tm_type = ENTITY_TYPE_VEHICLE;\n\tVehicleCreatedBy = CreatedBy;\n\tm_nRouteSeed = 0;\n\tbIsLocked = false;\n\tbIsLawEnforcer = false;\n\tbIsAmbulanceOnDuty = false;\n\tbIsFireTruckOnDuty = false;\n#ifdef FIX_BUGS\n\tbIsHandbrakeOn = false;\n#endif\n\tCCarCtrl::UpdateCarCount(this, false);\n\tm_fHealth = 1000.0f;\n\tbEngineOn = true;\n\tbFreebies = true;\n\tpDriver = nil;\n\tm_nNumPassengers = 0;\n\tm_nNumGettingIn = 0;\n\tm_nGettingInFlags = 0;\n\tm_nGettingOutFlags = 0;\n\tm_nNumMaxPassengers = ARRAY_SIZE(pPassengers);\n\tfor(i = 0; i < m_nNumMaxPassengers; i++)\n\t\tpPassengers[i] = nil;\n\tm_nBombTimer = 0;\n\tm_pBlowUpEntity = nil;\n\tm_nPacManPickupsCarried = 0;\n\tbComedyControls = false;\n\tbCraneMessageDone = false;\n\tbExtendedRange = false;\n\tbTakeLessDamage = false;\n\tbIsDamaged = false;\n\tbFadeOut = false;\n\tbIsBeingCarJacked = false;\n\tm_nTimeOfDeath = 0;\n\tm_pCarFire = nil;\n\tbHasBeenOwnedByPlayer = false;\n\tbCreateRoadBlockPeds = false;\n\tbCanBeDamaged = true;\n\tbUsingSpecialColModel = false;\n\tbOccupantsHaveBeenGenerated = false;\n\tbGunSwitchedOff = false;\n\tm_nGunFiringTime = 0;\n\tm_nTimeBlocked = 0;\n\tbLightsOn = false;\n\tbVehicleColProcessed = false;\n\tm_numPedsUseItAsCover = 0;\n\tbIsCarParkVehicle = false;\n\tbHasAlreadyBeenRecorded = false;\n\tm_bSirenOrAlarm = false;\n\tm_nCarHornTimer = 0;\n\tm_nCarHornPattern = 0;\n\tm_nCarHornDelay = 0;\n\tbPartOfConvoy = false;\n\tbHeliMinimumTilt = false;\n\tbAudioChangingGear = false;\n\tbIsDrowning = false;\n\tbTyresDontBurst = false;\n\tbCreatedAsPoliceVehicle = false;\n\tbRestingOnPhysical = false;\n\tbParking = false;\n\tbCanPark = CGeneral::GetRandomNumberInRange(0.0f, 1.0f) < 0.0f;\t// never true. probably doesn't work very well\n\tbIsVan = false;\n\tbIsBus = false;\n\tbIsBig = false;\n\tbLowVehicle = false;\n\n\tm_bombType = CARBOMB_NONE;\n\tbDriverLastFrame = false;\n\tm_pBombRigger = nil;\n\n\tm_nSetPieceExtendedRangeTime = 0;\n\tm_nAlarmState = 0;\n\tm_nDoorLock = CARLOCK_UNLOCKED;\n\tm_nLastWeaponDamage = -1;\n\tm_pLastDamageEntity = nil;\n\tm_fMapObjectHeightAhead = m_fMapObjectHeightBehind = 0.0f;\n\tm_audioEntityId = DMAudio.CreateEntity(AUDIOTYPE_PHYSICAL, this);\n\tif(m_audioEntityId >= 0)\n\t\tDMAudio.SetEntityStatus(m_audioEntityId, true);\n\t//m_nRadioStation = CGeneral::GetRandomNumber() % NUM_RADIOS;\n\tswitch(GetModelIndex()){\n\tcase MI_HUNTER:\n\tcase MI_ANGEL:\n\tcase MI_FREEWAY:\n\t\tm_nRadioStation = V_ROCK;\n\t\tbreak;\n\tcase MI_RCBARON:\n\tcase MI_RCBANDIT:\n\tcase MI_RCRAIDER:\n\tcase MI_RCGOBLIN:\n\tcase MI_TOPFUN:\n\tcase MI_CADDY:\n\tcase MI_BAGGAGE:\n\t\tm_nRadioStation = RADIO_OFF;\n\t\tbreak;\n\tdefault:\n\t\tm_nRadioStation = CGeneral::GetRandomNumber() % NUM_RADIOS;\n\t\tbreak;\n\t}\n\tm_pCurGroundEntity = nil;\n\tm_bRainAudioCounter = 0;\n\tm_bRainSamplesCounter = 0;\n\tm_comedyControlState = 0;\n\tm_aCollPolys[0].valid = false;\n\tm_aCollPolys[1].valid = false;\n\tAutoPilot.m_nCarMission = MISSION_NONE;\n\tAutoPilot.m_nTempAction = TEMPACT_NONE;\n\tAutoPilot.m_nTimeToStartMission = CTimer::GetTimeInMilliseconds();\n\tAutoPilot.m_bStayInCurrentLevel = false;\n\tAutoPilot.m_bIgnorePathfinding = false;\n\tAutoPilot.m_nSwitchDistance = 20;\n}\n\nCVehicle::~CVehicle()\n{\n\tm_nAlarmState = 0;\n\tif (m_audioEntityId >= 0){\n\t\tDMAudio.DestroyEntity(m_audioEntityId);\n\t\tm_audioEntityId = -5;\n\t}\n\tCRadar::ClearBlipForEntity(BLIP_CAR, CPools::GetVehiclePool()->GetIndex(this));\n\tif (pDriver)\n\t\tpDriver->FlagToDestroyWhenNextProcessed();\n\tfor (int i = 0; i < m_nNumMaxPassengers; i++){\n\t\tif (pPassengers[i])\n\t\t\tpPassengers[i]->FlagToDestroyWhenNextProcessed();\n\t}\n\tif (m_pCarFire)\n\t\tm_pCarFire->Extinguish();\n\tCCarCtrl::UpdateCarCount(this, true);\n\tif (bIsAmbulanceOnDuty){\n\t\tCCarCtrl::NumAmbulancesOnDuty--;\n\t\tbIsAmbulanceOnDuty = false;\n\t}\n\tif (bIsFireTruckOnDuty){\n\t\tCCarCtrl::NumFiretrucksOnDuty--;\n\t\tbIsFireTruckOnDuty = false;\n\t}\n}\n\nvoid\nCVehicle::SetModelIndex(uint32 id)\n{\n\tCEntity::SetModelIndex(id);\n\tm_aExtras[0] = CVehicleModelInfo::ms_compsUsed[0];\n\tm_aExtras[1] = CVehicleModelInfo::ms_compsUsed[1];\n\tm_nNumMaxPassengers = CVehicleModelInfo::GetMaximumNumberOfPassengersFromNumberOfDoors(id);\n}\n\nbool\nCVehicle::SetupLighting(void)\n{\n\tActivateDirectional();\n\tSetAmbientColoursForPedsCarsAndObjects();\n\n\tif(bRenderScorched){\n\t\tWorldReplaceNormalLightsWithScorched(Scene.world, 0.1f);\n\t}else{\n\t\tCVector coors = GetPosition();\n\t\tfloat lighting = CPointLights::GenerateLightsAffectingObject(&coors);\n\t\tif(lighting != 1.0f){\n\t\t\tSetAmbientAndDirectionalColours(lighting);\n\t\t\treturn true;\n\t\t}\n\t}\n\n\treturn false;\n}\n\nvoid\nCVehicle::RemoveLighting(bool reset)\n{\n\tCRenderer::RemoveVehiclePedLights(this, reset);\n}\n\nbool\nCVehicle::IsClearToDriveAway(void)\n{\n\tCColPoint point;\n\tfloat length = GetColModel()->boundingBox.GetSize().y;\n\tCEntity *ent = nil;\n\tCVector front = GetForward() * (length*0.5f + 3.0f);\n\treturn !CWorld::ProcessLineOfSight(GetPosition() + front, GetPosition(),\n\t\t\tpoint, ent, true, true, false, false, false, true, true) ||\n\t\tent == this;\n}\n\nfloat\nCVehicle::GetHeightAboveRoad(void)\n{\n\treturn -1.0f * GetColModel()->boundingBox.min.z;\n}\n\nvoid\nCVehicle::FlyingControl(eFlightModel flightModel)\n{\n\tif(pFlyingHandling == nil)\n\t\treturn;\n\n\tswitch(flightModel){\n\tcase FLIGHT_MODEL_DODO:\n\t{\n\t\t// This seems pretty magic\n\n\t\t// Move Left/Right\n\t\tfloat moveSpeed = m_vecMoveSpeed.Magnitude();\n\t\tfloat sideSpeed = DotProduct(m_vecMoveSpeed, GetRight());\n\t\tfloat sideImpulse = -1.0f * sideSpeed / moveSpeed;\n\t\tfloat fwdSpeed = DotProduct(m_vecMoveSpeed, GetForward());\n\t\tfloat magic = m_vecMoveSpeed.MagnitudeSqr() * sq(fwdSpeed);\n\t\tfloat turnImpulse = (sideImpulse*0.003f + m_fSteerAngle*0.001f) *\n\t\t\tmagic*m_fTurnMass*CTimer::GetTimeStep();\n\t\tApplyTurnForce(turnImpulse*GetRight(), -4.0f*GetForward());\n\n\t\tfloat impulse = sideImpulse*0.2f *\n\t\t\tmagic*m_fMass*CTimer::GetTimeStep();\n\t\tApplyMoveForce(impulse*GetRight());\n\t\tApplyTurnForce(impulse*GetRight(), 2.0f*GetUp());\n\n\n\t\t// Move Up/Down\n\t\tmoveSpeed = m_vecMoveSpeed.Magnitude();\n\t\tfloat upSpeed = DotProduct(m_vecMoveSpeed, GetUp());\n\t\tfloat upImpulse = -1.0f * upSpeed / moveSpeed;\n\t\tturnImpulse = (upImpulse*0.002f + -CPad::GetPad(0)->GetSteeringUpDown()/128.0f*0.001f) *\n\t\t\tmagic*m_fTurnMass*CTimer::GetTimeStep();\n\t\tApplyTurnForce(turnImpulse*GetUp(), -4.0f*GetForward());\n\n\t\timpulse = (upImpulse*3.5f + 0.5f)*0.05f *\n\t\t\tmagic*m_fMass*CTimer::GetTimeStep();\n\t\tif(GRAVITY*m_fMass*CTimer::GetTimeStep() < impulse &&\n\t\t   GetPosition().z > 100.0f)\n\t\t\timpulse = 0.9f*GRAVITY*m_fMass*CTimer::GetTimeStep();\n\t\tCVector com = Multiply3x3(GetMatrix(), m_vecCentreOfMass);\n\t\tApplyMoveForce(impulse*GetUp());\n\t\tApplyTurnForce(impulse*GetUp(), 2.0f*GetUp() + com);\n\n\n\t\tm_vecTurnSpeed.y *= Pow(0.9f, CTimer::GetTimeStep());\n\n\n\t\tmoveSpeed = m_vecMoveSpeed.MagnitudeSqr();\n\t\tif(moveSpeed > SQR(1.5f))\n\t\t\tm_vecMoveSpeed *= 1.5f/Sqrt(moveSpeed);\n\n\t\tfloat turnSpeed = m_vecTurnSpeed.MagnitudeSqr();\n\t\tif(turnSpeed > SQR(0.2f))\n\t\t\tm_vecTurnSpeed *= 0.2f/Sqrt(turnSpeed);\n\t\tbreak;\n\t}\n\n\tcase FLIGHT_MODEL_RCPLANE:\n\tcase FLIGHT_MODEL_SEAPLANE:\n\tcase FLIGHT_MODEL_PLANE_UNUSED:\n\tcase FLIGHT_MODEL_PLANE:\n\t{\n\t\tfloat fSteerLR = CPad::GetPad(0)->GetSteeringLeftRight() / 128.0f;\n\t\tfloat fSteerUD = CPad::GetPad(0)->GetSteeringUpDown() / 128.0f;\n\t\tfloat fGunUD = Abs(CPad::GetPad(0)->GetCarGunUpDown());\n#ifdef FREE_CAM\n\t\tif(!CCamera::bFreeCam || (CCamera::bFreeCam && !CPad::IsAffectedByController))\n#endif\n\t\tif(fGunUD > 1.0f)\n\t\t\tfSteerUD = -CPad::GetPad(0)->GetCarGunUpDown() / 128.0f;\n\n\t\tfloat fSteerAngle = Atan2(fSteerUD, fSteerLR);\n\t\tfloat fSteerMult = 1.0f;\n\t\tif(fSteerAngle > -PI/4.0f && fSteerAngle <= PI/4.0f)\n\t\t\tfSteerMult = 1.0f/Cos(fSteerAngle);\n\t\telse if(fSteerAngle > PI/4.0f && fSteerAngle <= PI*3.0f/4.0f)\n\t\t\tfSteerMult = 1.0f/Cos(fSteerAngle - HALFPI);\n\t\telse if(fSteerAngle > PI*3.0f/4.0f)\n\t\t\tfSteerMult = 1.0f/Cos(fSteerAngle - PI);\n\t\telse if(fSteerAngle <= -PI*3.0f/4.0f)\n\t\t\tfSteerMult = 1.0f/Cos(fSteerAngle + PI);\n\t\telse if(fSteerAngle > -PI*3.0f/4.0f && fSteerAngle < -PI/4.0f)\n\t\t\tfSteerMult = 1.0f/Cos(fSteerAngle + HALFPI);\n\n\t\tfSteerLR *= fSteerMult;\n\t\tfSteerUD *= -fSteerMult;\n\n\t\t// thrust\n\t\tfloat fThrust = pFlyingHandling->fThrust;\n\t\tfloat fThrustFallOff = pFlyingHandling->fThrustFallOff;\n\t\tfloat fThrustFallOffBack = pFlyingHandling->fThrustFallOff * 8.0f;\n#ifdef BETTER_ALLCARSAREDODO_CHEAT\n\t\tif (bAllDodosCheat && !IsRealPlane()) {\n\t\t\tfThrust = pHandling->Transmission.fEngineAcceleration\n\t\t\t\t* (pHandling->Transmission.nDriveType == '4' ? 4.0f : 2.0f);\n\t\t\tfThrust = 5.0f * Max(fThrust, pFlyingHandling->fThrust); //tweak: (cars engines too weak to thrust car on air)\n\t\t\tfThrustFallOff = Min(0.7f / pHandling->Transmission.fMaxVelocity, fThrustFallOff); //tweak: (use 0.7 instead of 1.0 to make cars 30% faster)\n\t\t\tfThrustFallOffBack = -1.0f / pHandling->Transmission.fMaxReverseVelocity;\n\t\t}\n#endif\n\t\tfloat fForwSpeed = DotProduct(GetMoveSpeed(), GetForward());\n\t\tCVector vecTail = GetColModel()->boundingBox.min.y * GetForward();\n\t\tfloat fPedalState = (CPad::GetPad(0)->GetAccelerate() - CPad::GetPad(0)->GetBrake()) / 255.0f;\n\t\tfloat fThrustAccel;\n\t\tif(fForwSpeed > 0.0f || fPedalState > 0.0f)\n\t\t\tfThrustAccel = (fPedalState - fThrustFallOff * fForwSpeed) * fThrust;\n\t\telse\n\t\t\tfThrustAccel = Min(fPedalState - fThrustFallOffBack * fForwSpeed, 0.0f) * fThrust;\n\t\tif(flightModel == FLIGHT_MODEL_PLANE_UNUSED)\n\t\t\tfThrustAccel *= 0.3f;\n\t\telse if(flightModel == FLIGHT_MODEL_PLANE)\n\t\t\tfThrustAccel *= 0.1f;\n\t\tApplyMoveForce(fThrustAccel * GetForward() * m_fMass * CTimer::GetTimeStep());\n\n\t\t// left/right\n\t\tfloat fSideSpeed = -DotProduct(GetMoveSpeed(), GetRight());\n\t\tfloat fSideSlipAccel = pFlyingHandling->fSideSlip * fSideSpeed * Abs(fSideSpeed);\n\t\tApplyMoveForce(m_fMass * GetRight() * fSideSlipAccel * CTimer::GetTimeStep());\n\n\t\tfloat fYaw = -DotProduct(GetSpeed(vecTail), GetRight());\n\t\tfloat fYawAccel = pFlyingHandling->fYawStab * fYaw * Abs(fYaw) + pFlyingHandling->fYaw * fSteerLR * fForwSpeed;\n\t\tApplyTurnForce(fYawAccel * GetRight() * m_fTurnMass * CTimer::GetTimeStep(), vecTail);\n\n\t\tfloat fRollAccel;\n\t\tif (flightModel == FLIGHT_MODEL_RCPLANE) {\n\t\t\tfloat fDirectionMultiplier = CPad::GetPad(0)->GetLookRight();\n\t\t\tif (CPad::GetPad(0)->GetLookLeft())\n\t\t\t\tfDirectionMultiplier = -1;\n\t\t\tfRollAccel = (0.5f * fDirectionMultiplier + fSteerLR) * pFlyingHandling->fRoll;\n\t\t}\n\t\telse\n\t\t\tfRollAccel = fSteerLR * pFlyingHandling->fRoll;\n\t\tApplyTurnForce(GetRight() * fRollAccel * fForwSpeed * m_fTurnMass * CTimer::GetTimeStep(), GetUp());\n\n\t\tCVector vecFRight = CrossProduct(GetForward(), CVector(0.0f, 0.0f, 1.0f));\n\t\tCVector vecStabilise = (GetUp().z > 0.0f) ? vecFRight : -vecFRight;\n\t\tfloat fStabiliseDirection = (GetRight().z > 0.0f) ? -1.0f : 1.0f;\n\t\tfloat fStabiliseSpeed = pFlyingHandling->fRollStab * fStabiliseDirection * (1.0f - DotProduct(GetRight(), vecStabilise)) * (1.0f - Abs(GetForward().z));\n\t\tApplyTurnForce(fStabiliseSpeed * m_fTurnMass * GetRight(), GetUp()); // no CTimer::GetTimeStep(), is it right?\n\n\t\t// up/down\n\t\tfloat fTail = -DotProduct(GetSpeed(vecTail), GetUp());\n\t\tfloat fPitchAccel = pFlyingHandling->fPitchStab * fTail * Abs(fTail) + pFlyingHandling->fPitch * fSteerUD * fForwSpeed;\n\t\tApplyTurnForce(fPitchAccel * m_fTurnMass * GetUp() * CTimer::GetTimeStep(), vecTail);\n\n\t\tfloat fLift = DotProduct(GetMoveSpeed(), GetUp()) / Max(0.01f, GetMoveSpeed().Magnitude()); //accel*angle\n\t\tfloat fLiftAccel = (pFlyingHandling->fFormLift - pFlyingHandling->fAttackLift * fLift) * SQR(fForwSpeed);\n\t\tfloat fLiftImpulse = fLiftAccel * m_fMass * CTimer::GetTimeStep();\n\t\tif (GRAVITY * CTimer::GetTimeStep() * m_fMass < fLiftImpulse) {\n\t\t\tif (flightModel == FLIGHT_MODEL_RCPLANE && GetPosition().z > 50.0f)\n\t\t\t\tfLiftImpulse = CTimer::GetTimeStep() * 0.9f*GRAVITY * m_fMass;\n\t\t\telse if (flightModel == FLIGHT_MODEL_SEAPLANE && GetPosition().z > 80.0f)\n\t\t\t\tfLiftImpulse = CTimer::GetTimeStep() * 0.9f*GRAVITY * m_fMass;\n#ifdef BETTER_ALLCARSAREDODO_CHEAT\n\t\t\telse if(bAllDodosCheat && GetPosition().z > 170.0f)\n\t\t\t\tfLiftImpulse = CTimer::GetTimeStep() * 0.9f * GRAVITY * m_fMass;\n#endif\n\t\t}\n\t\tApplyMoveForce(fLiftImpulse * GetUp());\n\n\t\tCVector vecResistance;\n\t\tvecResistance = pFlyingHandling->vecTurnRes;\n\t\tfloat rX = Pow(vecResistance.x, CTimer::GetTimeStep());\n\t\tfloat rY = Pow(vecResistance.y, CTimer::GetTimeStep());\n\t\tfloat rZ = Pow(vecResistance.z, CTimer::GetTimeStep());\n\t\tCVector vecTurnSpeed = Multiply3x3(m_vecTurnSpeed, GetMatrix());\n\t\tvecTurnSpeed.x *= rX;\n\t\tfloat fResistance = vecTurnSpeed.y * (1.0f / (pFlyingHandling->vecSpeedRes.y * SQR(vecTurnSpeed.y) + 1.0f)) * rY - vecTurnSpeed.y;\n\t\tvecTurnSpeed.z *= rZ;\n\t\tm_vecTurnSpeed = Multiply3x3(GetMatrix(), vecTurnSpeed);\n\t\tApplyTurnForce(-GetUp() * fResistance * m_fTurnMass, GetRight() + Multiply3x3(GetMatrix(), m_vecCentreOfMass));\n\n\n\t\tfloat fMoveSpeed = m_vecMoveSpeed.MagnitudeSqr();\n\t\tif(fMoveSpeed > SQR(1.5f))\n\t\t\tm_vecMoveSpeed *= 1.5f/Sqrt(fMoveSpeed);\n\n\t\tfloat fTurnSpeed = m_vecTurnSpeed.MagnitudeSqr();\n\t\tif(fTurnSpeed > SQR(0.2f))\n\t\t\tm_vecTurnSpeed *= 0.2f/Sqrt(fTurnSpeed);\n\t\tbreak;\n\t}\n\tcase FLIGHT_MODEL_RCHELI:\n\tcase FLIGHT_MODEL_HELI:\n\t{\n#ifdef RESTORE_ALLCARSHELI_CHEAT\n\t\ttFlyingHandlingData* flyingHandling = bAllCarCheat && !IsRealHeli() ? mod_HandlingManager.GetFlyingPointer(HANDLING_MAVERICK) : pFlyingHandling;\n#else\n\t\ttFlyingHandlingData* flyingHandling = pFlyingHandling;\n#endif\n\t\tfloat rm = Pow(flyingHandling->fMoveRes, CTimer::GetTimeStep());\n\t\tm_vecMoveSpeed *= rm;\n\t\tif (GetStatus() != STATUS_PLAYER && GetStatus() != STATUS_PLAYER_REMOTE)\n\t\t\treturn;\n\t\tfloat fUpSpeed = DotProduct(m_vecMoveSpeed, GetUp());\n\t\tfloat fThrust = (CPad::GetPad(0)->GetAccelerate() - CPad::GetPad(0)->GetBrake()) / 255.0f;\n\t\tif(fThrust < 0.0f)\n\t\t\tfThrust *= 2.0f;\n\t\tif(flightModel == FLIGHT_MODEL_RCHELI){\n\t\t\tfThrust = flyingHandling->fThrust * fThrust + 0.45f;\n\t\t\tApplyMoveForce(GRAVITY * CVector(0.0f, 0.0f, 0.5f) * m_fMass * CTimer::GetTimeStep());\n\t\t}else\n\t\t\tfThrust = flyingHandling->fThrust * fThrust + 0.95f;\n\t\tfThrust -= flyingHandling->fThrustFallOff * fUpSpeed;\n\t\tif(flightModel == FLIGHT_MODEL_RCHELI && GetPosition().z > 40.0f)\n\t\t\tfThrust *= 10.0f/(GetPosition().z - 30.0f);\n\t\telse if(GetPosition().z > 80.0f)\n\t\t\tfThrust *= 10.0f/(GetPosition().z - 70.0f);\n\t\tApplyMoveForce(GRAVITY * GetUp() * fThrust * m_fMass * CTimer::GetTimeStep());\n\n\t\tif (GetUp().z > 0.0f){\n\t\t\tfloat upRight = clamp(GetRight().z, -flyingHandling->fFormLift, flyingHandling->fFormLift);\n\t\t\tfloat upImpulseRight = -upRight * flyingHandling->fAttackLift * m_fTurnMass * CTimer::GetTimeStep();\n\t\t\tApplyTurnForce(upImpulseRight * GetUp(), GetRight());\n\n\t\t\tfloat upFwd = clamp(GetForward().z, -flyingHandling->fFormLift, flyingHandling->fFormLift);\n\t\t\tfloat upImpulseFwd = -upFwd * flyingHandling->fAttackLift * m_fTurnMass * CTimer::GetTimeStep();\n\t\t\tApplyTurnForce(upImpulseFwd * GetUp(), GetForward());\n\t\t}else{\n\t\t\tfloat upRight = GetRight().z < 0.0f ? -flyingHandling->fFormLift : flyingHandling->fFormLift;\n\t\t\tfloat upImpulseRight = -upRight * flyingHandling->fAttackLift * m_fTurnMass * CTimer::GetTimeStep();\n\t\t\tApplyTurnForce(upImpulseRight * GetUp(), GetRight());\n\n\t\t\tfloat upFwd = GetForward().z < 0.0f ? -flyingHandling->fFormLift : flyingHandling->fFormLift;\n\t\t\tfloat upImpulseFwd = -upFwd * flyingHandling->fAttackLift * m_fTurnMass * CTimer::GetTimeStep();\n\t\t\tApplyTurnForce(upImpulseFwd * GetUp(), GetForward());\n\t\t}\n\n\t\tfloat fRoll, fPitch, fYaw;\n\t\tif (bCheat5) {\n\t\t\tfPitch = CPad::GetPad(0)->GetSteeringUpDown() / 128.0f;\n\t\t\tfRoll = CPad::GetPad(0)->GetLookLeft();\n\t\t\tif (CPad::GetPad(0)->GetLookRight())\n\t\t\t\tfRoll = -1.0f;\n\t\t\tfYaw = CPad::GetPad(0)->GetSteeringLeftRight() / 128.0f;\n\t\t} else {\n\t\t\tfPitch = CPad::GetPad(0)->GetSteeringUpDown() / 128.0f;\n\t\t\tfRoll = -CPad::GetPad(0)->GetSteeringLeftRight() / 128.0f;\n\t\t\tfYaw = CPad::GetPad(0)->GetLookRight();\n\t\t\tif (CPad::GetPad(0)->GetLookLeft())\n\t\t\t\tfYaw = -1.0f;\n#ifdef FREE_CAM\n\t\t\tif (!CCamera::bFreeCam || (CCamera::bFreeCam && !CPad::IsAffectedByController))\n#endif\n\t\t\tif(Abs(CPad::GetPad(0)->GetCarGunLeftRight()) > 1.0f)\n\t\t\t\tfYaw = CPad::GetPad(0)->GetCarGunLeftRight() / 128.0f;\n\t\t}\n#ifdef FREE_CAM\n\t\tif(!CCamera::bFreeCam || (CCamera::bFreeCam && !CPad::IsAffectedByController))\n#endif\n\t\tif(Abs(CPad::GetPad(0)->GetCarGunUpDown()) > 1.0f)\n\t\t\tfPitch = -CPad::GetPad(0)->GetCarGunUpDown() / 128.0f;\n\t\tif (CPad::GetPad(0)->GetHorn()) {\n\t\t\tfYaw = 0.0f;\n\t\t\tfPitch = clamp(flyingHandling->fPitchStab * DotProduct(m_vecMoveSpeed, GetForward()), -200.0f, 1.3f);\n\t\t\tfRoll = clamp(flyingHandling->fRollStab * DotProduct(m_vecMoveSpeed, GetRight()), -200.0f, 1.3f);\n\t\t}\n\t\tApplyTurnForce(fPitch * GetUp() * flyingHandling->fPitch * m_fTurnMass * CTimer::GetTimeStep(), GetForward());\n\t\tApplyTurnForce(fRoll * GetUp() * flyingHandling->fRoll * m_fTurnMass * CTimer::GetTimeStep(), GetRight());\n\n\t\tfloat fSideSpeed = -DotProduct(GetMoveSpeed(), GetRight());\n\t\tfloat fSideSlipAccel = flyingHandling->fSideSlip * fSideSpeed * Abs(fSideSpeed);\n\t\tApplyMoveForce(m_fMass * GetRight() * fSideSlipAccel * CTimer::GetTimeStep());\n\t\tfloat fYawAccel = flyingHandling->fYawStab * fSideSpeed * Abs(fSideSpeed) + flyingHandling->fYaw * fYaw;\n\t\tApplyTurnForce(fYawAccel * GetRight() * m_fTurnMass * CTimer::GetTimeStep(), -GetForward());\n\n\t\tApplyTurnForce(fYaw * GetForward() * flyingHandling->fYaw * m_fTurnMass * CTimer::GetTimeStep(), GetRight());\n\n\t\tfloat rX = Pow(flyingHandling->vecTurnRes.x, CTimer::GetTimeStep());\n\t\tfloat rY = Pow(flyingHandling->vecTurnRes.y, CTimer::GetTimeStep());\n\t\tfloat rZ = Pow(flyingHandling->vecTurnRes.z, CTimer::GetTimeStep());\n\t\tCVector vecTurnSpeed = Multiply3x3(m_vecTurnSpeed, GetMatrix());\n\t\tfloat fResistanceMultiplier = Pow(1.0f / (flyingHandling->vecSpeedRes.z * SQR(vecTurnSpeed.z) + 1.0f) * rZ, CTimer::GetTimeStep());\n\t\tfloat fResistance = vecTurnSpeed.z * fResistanceMultiplier - vecTurnSpeed.z;\n\t\tvecTurnSpeed.x *= rX;\n\t\tvecTurnSpeed.y *= rY;\n\t\tvecTurnSpeed.z *= fResistanceMultiplier;\n\t\tm_vecTurnSpeed = Multiply3x3(GetMatrix(), vecTurnSpeed);\n\t\tApplyTurnForce(-GetRight() * fResistance * m_fTurnMass, GetForward() + Multiply3x3(GetMatrix(), m_vecCentreOfMass));\n\t\tbreak;\n\t}\n\t}\n}\n\nstatic CColModel rotorColModel;\nstatic CColSphere rotorColSphere;\nfloat ROTOR_SEMI_THICKNESS = 0.05f;\nfloat ROTOR_TURN_SPEED = 0.2f;\nfloat ROTOR_DISGUARD_MULT = 0.3f;\nfloat ROTOR_COL_ELASTICITY = 1.0f;\nfloat ROTOR_COL_TURNMULT = -0.001f;\nfloat ROTOR_DEFAULT_DAMAGE = 100.0f;\n\nbool\nCVehicle::DoBladeCollision(CVector pos, CMatrix &matrix, int16 rotorType, float radius, float damageMult)\n{\n\tCVector max(radius, radius, radius);\n\tCVector min(-radius, -radius, -radius);\n\n\tswitch(rotorType){\n\tcase ROTOR_TOP:\n\tcase ROTOR_BOTTOM:\n\t\tmin.z = -ROTOR_SEMI_THICKNESS;\n\t\tmax.z = ROTOR_SEMI_THICKNESS;\n\t\tbreak;\n\tcase ROTOR_FRONT:\n\tcase ROTOR_BACK:\n\t\tmin.y = -ROTOR_SEMI_THICKNESS;\n\t\tmax.y = ROTOR_SEMI_THICKNESS;\n\t\tbreak;\n\tcase ROTOR_RIGHT:\n\tcase ROTOR_LEFT:\n\t\tmin.x = -ROTOR_SEMI_THICKNESS;\n\t\tmax.x = ROTOR_SEMI_THICKNESS;\n\t\tbreak;\n\t}\n\n\tmin += pos;\n\tmax += pos;\n\trotorColModel.boundingBox.Set(min, max);\n\trotorColModel.boundingSphere.Set(radius, pos);\n\trotorColSphere.Set(radius, pos, 0, 0);\n\trotorColModel.spheres = &rotorColSphere;\n\trotorColModel.numSpheres = 1;\n\n\tpos = matrix * pos;\n\tbool hadCollision = false;\n\tint minX = CWorld::GetSectorIndexX(pos.x - radius);\n\tif(minX <= 0) minX = 0;\n\n\tint minY = CWorld::GetSectorIndexY(pos.y - radius);\n\tif(minY <= 0) minY = 0;\n\n\tint maxX = CWorld::GetSectorIndexX(pos.x + radius);\n#ifdef FIX_BUGS\n\tif(maxX >= NUMSECTORS_X) maxX = NUMSECTORS_X - 1;\n#else\n\tif(maxX >= NUMSECTORS_X) maxX = NUMSECTORS_X;\n#endif\n\n\tint maxY = CWorld::GetSectorIndexY(pos.y + radius);\n#ifdef FIX_BUGS\n\tif(maxY >= NUMSECTORS_Y) maxY = NUMSECTORS_Y - 1;\n#else\n\tif(maxY >= NUMSECTORS_Y) maxY = NUMSECTORS_Y;\n#endif\n\n\tCWorld::AdvanceCurrentScanCode();\n\tfor(int curY = minY; curY <= maxY; curY++) {\n\t\tfor(int curX = minX; curX <= maxX; curX++) {\n\t\t\tCSector *sector = CWorld::GetSector(curX, curY);\n\t\t\tif(BladeColSectorList(sector->m_lists[ENTITYLIST_BUILDINGS], rotorColModel, matrix, rotorType, damageMult))\n\t\t\t\thadCollision = true;\n\t\t\tif(BladeColSectorList(sector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP], rotorColModel, matrix, rotorType, damageMult))\n\t\t\t\thadCollision = true;\n\t\t\tif(BladeColSectorList(sector->m_lists[ENTITYLIST_VEHICLES], rotorColModel, matrix, rotorType, damageMult))\n\t\t\t\thadCollision = true;\n\t\t\tif(BladeColSectorList(sector->m_lists[ENTITYLIST_VEHICLES_OVERLAP], rotorColModel, matrix, rotorType, damageMult))\n\t\t\t\thadCollision = true;\n\t\t\tif(BladeColSectorList(sector->m_lists[ENTITYLIST_PEDS], rotorColModel, matrix, rotorType, 0.0f))\n\t\t\t\thadCollision = true;\n\t\t\tif(BladeColSectorList(sector->m_lists[ENTITYLIST_PEDS_OVERLAP], rotorColModel, matrix, rotorType, 0.0f))\n\t\t\t\thadCollision = true;\n\t\t\tif(BladeColSectorList(sector->m_lists[ENTITYLIST_OBJECTS], rotorColModel, matrix, rotorType, damageMult))\n\t\t\t\thadCollision = true;\n\t\t\tif(BladeColSectorList(sector->m_lists[ENTITYLIST_OBJECTS_OVERLAP], rotorColModel, matrix, rotorType, damageMult))\n\t\t\t\thadCollision = true;\n\t\t}\n\t}\n\trotorColModel.spheres = nil;\n\trotorColModel.numSpheres = 0;\n\n\treturn hadCollision;\n}\n\nbool\nCVehicle::BladeColSectorList(CPtrList &list, CColModel &rotorColModel, CMatrix &matrix, int16 rotorType, float damageMult)\n{\n\tint i;\n\tCVector axis;\n\tCVector turnSpeed(0.0f, 0.0f, 0.0f);\n\tswitch(rotorType){\n\tcase ROTOR_TOP:\n\t\tturnSpeed.z = -ROTOR_TURN_SPEED;\n\t\taxis = -matrix.GetUp();\n\t\tbreak;\n\tcase ROTOR_BOTTOM:\n\t\tturnSpeed.z = ROTOR_TURN_SPEED;\n\t\taxis = matrix.GetUp();\n\t\tbreak;\n\n\tcase ROTOR_FRONT:\n\t\tturnSpeed.y = -ROTOR_TURN_SPEED;\n\t\taxis = -matrix.GetForward();\n\t\tbreak;\n\tcase ROTOR_BACK:\n\t\tturnSpeed.y = ROTOR_TURN_SPEED;\n\t\taxis = matrix.GetForward();\n\t\tbreak;\n\n\tcase ROTOR_RIGHT:\n\t\tturnSpeed.x = -ROTOR_TURN_SPEED;\n\t\taxis = -matrix.GetRight();\n\t\tbreak;\n\tcase ROTOR_LEFT:\n\t\tturnSpeed.x = ROTOR_TURN_SPEED;\n\t\taxis = matrix.GetRight();\n\t\tbreak;\n\t}\n\tturnSpeed = Multiply3x3(matrix, turnSpeed);\n\tCVector center = rotorColModel.boundingSphere.center;\n\tcenter = matrix*center;\n\n\tfor(CPtrNode *node = list.first; node; node = node->next) {\n\t\tCEntity *entity = (CEntity *)node->item;\n\t\tif(entity == (CEntity*)this ||\n\t\t   !entity->bUsesCollision ||\n\t\t   entity->m_scanCode == CWorld::GetCurrentScanCode())\n\t\t\tcontinue;\n\n\t\tentity->m_scanCode = CWorld::GetCurrentScanCode();\n\n\t\tint numCollisions;\n\t\tCColModel *entityCol;\n\t\tif(entity->IsPed())\n\t\t\tentityCol = ((CPedModelInfo*)CModelInfo::GetModelInfo(entity->GetModelIndex()))->AnimatePedColModelSkinned(entity->GetClump());\n\t\telse\n\t\t\tentityCol = entity->GetColModel();\n\t\tif(entityCol)\n\t\t\tnumCollisions = CCollision::ProcessColModels(matrix, rotorColModel, entity->GetMatrix(), *entityCol,\n\t\t\t\tCWorld::m_aTempColPts, nil, nil);\n\t\telse\n\t\t\tnumCollisions = 0;\n\n\t\tif(numCollisions > 0 && entity->IsPed()){\n\t\t\tCPed *ped = (CPed*)entity;\n\t\t\tCVector2D dirToRotor = GetPosition() - entity->GetPosition();\n\t\t\tdirToRotor.Normalise();\n\t\t\tint localDir = ped->GetLocalDirection(dirToRotor);\n\t\t\tif(ped->m_attachedTo == nil){\n\t\t\t\tped->bIsStanding = false;\n\t\t\t\tped->ApplyMoveForce(-5.0f*dirToRotor.x, -5.0f*dirToRotor.y, 5.0f);\n\t\t\t}\n\t\t\tped->InflictDamage(this, WEAPONTYPE_RUNOVERBYCAR, 1000.0f, PEDPIECE_TORSO, localDir);\n\n\t\t\tif(CGame::nastyGame && ped->GetIsOnScreen()){\n\t\t\t\tfor(i = 0; i < 16; i++)\n\t\t\t\t\tCParticle::AddParticle(PARTICLE_BLOOD_SMALL, ped->GetPosition(), CVector(dirToRotor.x, dirToRotor.y, 1.0f) * 0.01f);\n\t\t\t\tCParticle::AddParticle(PARTICLE_TEST, ped->GetPosition(), CVector(0.0f, 0.0f, 0.02f), nil, 0.1f);\n\t\t\t\tCParticle::AddParticle(PARTICLE_TEST, ped->GetPosition()+CVector(0.0f, 0.0f, 0.2f), CVector(0.0f, 0.0f, -0.01f), nil, 0.1f);\n\t\t\t}\n\t\t}else if(numCollisions > 0 && entity->GetModelIndex() != MI_MISSILE){\n\t\t\tfloat impulse = 0.0f;\n\t\t\tbool hadCollision = false;\n\t\t\tfloat savedElasticity = m_fElasticity;\n\t\t\tm_fElasticity = ROTOR_COL_ELASTICITY;\n\n\t\t\tfor(i = 0; i < numCollisions; i++){\n\t\t\t\tCVector colpos = CWorld::m_aTempColPts[i].point;\n\t\t\t\tCVector localColpos = colpos - center;\n\t\t\t\tfloat axisDir = DotProduct(axis, localColpos);\n\t\t\t\tfloat colDir = DotProduct(CWorld::m_aTempColPts[i].normal, localColpos);\n\n\t\t\t\tif(2.0f*ROTOR_SEMI_THICKNESS < Abs(axisDir) &&\n\t\t\t\t   ROTOR_DISGUARD_MULT*Abs(colDir) < Abs(axisDir))\n\t\t\t\t\tcontinue;\n\n\t\t\t\thadCollision = true;\n\t\t\t\tcolpos -= axisDir*axis;\t// get rid of axis component\n\n\t\t\t\tCVector tangentSpeed = CrossProduct(turnSpeed, colpos - center);\n\n\t\t\t\t// Particles\n\t\t\t\tfor(int j = 0; j < 4; j++){\n\t\t\t\t\tCParticle::AddParticle(PARTICLE_SPARK_SMALL, colpos, (tangentSpeed+m_vecMoveSpeed)/2.0f);\n\t\t\t\t\tCParticle::AddParticle(PARTICLE_SPARK, colpos, 0.1f*CWorld::m_aTempColPts[i].normal);\n\t\t\t\t}\n\n\t\t\t\t// Apply Collision\n\t\t\t\tif(IsCar()){\n\t\t\t\t\tCAutomobile *heli = (CAutomobile*)this;\n\t\t\t\t\tif(heli->m_aWheelSpeed[1] > 0.15f){\n\t\t\t\t\t\tApplyCollision(CWorld::m_aTempColPts[i], impulse);\n\t\t\t\t\t\tApplyTurnForce(m_fTurnMass*ROTOR_COL_TURNMULT*tangentSpeed, colpos - center);\n\t\t\t\t\t\theli->m_aWheelSpeed[1] = 0.15f;\n\t\t\t\t\t}else if(heli->m_aWheelSpeed[1] < 0.075f && heli->m_aWheelSpeed[1] > 0.0f)\n\t\t\t\t\t\theli->m_aWheelSpeed[1] *= -1.0f;\n\t\t\t\t}\n\n\t\t\t\tfloat damageImpulse = damageMult * Max(impulse, ROTOR_DEFAULT_DAMAGE*m_fMass/3000.0f);\n\t\t\t\tif(damageImpulse > m_fDamageImpulse)\n\t\t\t\t\tSetDamagedPieceRecord(0, damageImpulse, entity, CWorld::m_aTempColPts[i].normal);\n\n\t\t\t}\n\n\t\t\tif(hadCollision && !entity->IsPed())\n\t\t\t\tDMAudio.ReportCollision(this, entity, SURFACE_CAR_PANEL, SURFACE_TARMAC, 50.0f, 0.09f);\n\t\t\tm_fElasticity = savedElasticity;\n\t\t}\n\t}\n\treturn false;\n}\n\n\nfloat fBurstSpeedMax = 0.3f;\nfloat fBurstTyreMod = 0.13f;\n\nvoid\nCVehicle::ProcessWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelContactSpeed, CVector &wheelContactPoint,\n\tint32 wheelsOnGround, float thrust, float brake, float adhesion, int8 wheelId, float *wheelSpeed, tWheelState *wheelState, uint16 wheelStatus)\n{\n\t// BUG: using statics here is probably a bad idea\n\tstatic bool bAlreadySkidding = false;\t// this is never reset\n\tstatic bool bBraking;\n\tstatic bool bDriving;\n\n#ifdef FIX_SIGNIFICANT_BUGS\n\tbAlreadySkidding = false;\n#endif\n\n\t// how much force we want to apply in these axes\n\tfloat fwd = 0.0f;\n\tfloat right = 0.0f;\n\n\tbBraking = brake != 0.0f;\n\tif(bBraking)\n\t\tthrust = 0.0f;\n\tbDriving = thrust != 0.0f;\n\n\tfloat contactSpeedFwd = DotProduct(wheelContactSpeed, wheelFwd);\n\tfloat contactSpeedRight = DotProduct(wheelContactSpeed, wheelRight);\n\n\tif(*wheelState != WHEEL_STATE_NORMAL)\n\t\tbAlreadySkidding = true;\n\t*wheelState = WHEEL_STATE_NORMAL;\n\n\tadhesion *= CTimer::GetTimeStep();\n\tif(bAlreadySkidding)\n\t\tadhesion *= pHandling->fTractionLoss;\n\n\t// moving sideways\n\tif(contactSpeedRight != 0.0f){\n\t\t// exert opposing force\n\t\tright = -contactSpeedRight/wheelsOnGround;\n#ifdef FIX_BUGS\n\t\t// contactSpeedRight is independent of framerate but right has timestep as a factor\n\t\t// so we probably have to fix this\n\t\tright *= CTimer::GetTimeStepFix();\n#endif\n\n\t\tif(wheelStatus == WHEEL_STATUS_BURST){\n\t\t\tfloat fwdspeed = Min(contactSpeedFwd, fBurstSpeedMax);\n\t\t\tright += fwdspeed * CGeneral::GetRandomNumberInRange(-fBurstTyreMod, fBurstTyreMod);\n\t\t}\n\t}\n\n\tif(bDriving){\n\t\tfwd = thrust;\n\n\t\t// limit sideways force (why?)\n\t\tif(right > 0.0f){\n\t\t\tif(right > adhesion)\n\t\t\t\tright = adhesion;\n\t\t}else{\n\t\t\tif(right < -adhesion)\n\t\t\t\tright = -adhesion;\n\t\t}\n\t}else if(contactSpeedFwd != 0.0f){\n\t\tfwd = -contactSpeedFwd/wheelsOnGround;\n#ifdef FIX_BUGS\n\t\t// contactSpeedFwd is independent of framerate but fwd has timestep as a factor\n\t\t// so we probably have to fix this\n\t\tfwd *= CTimer::GetTimeStepFix();\n#endif\n\n\t\tif(!bBraking){\n\t\t\tif(m_fGasPedal < 0.01f){\n\t\t\t\tif(IsBike())\n\t\t\t\t\tbrake = 0.6f * mod_HandlingManager.fWheelFriction / (pHandling->fMass + 200.0f);\n\t\t\t\telse if(pHandling->fMass < 500.0f)\n\t\t\t\t\tbrake = 0.2f * mod_HandlingManager.fWheelFriction / pHandling->fMass;\n\t\t\t\telse if(GetModelIndex() == MI_RCBANDIT)\n\t\t\t\t\tbrake = 0.2f * mod_HandlingManager.fWheelFriction / pHandling->fMass;\n\t\t\t\telse\n\t\t\t\t\tbrake = mod_HandlingManager.fWheelFriction / pHandling->fMass;\n#ifdef FIX_BUGS\n\t\t\t\tbrake *= CTimer::GetTimeStepFix();\n#endif\n\t\t\t}\n\t\t}\n\n\t\tif(brake > adhesion){\n\t\t\tif(Abs(contactSpeedFwd) > 0.005f)\n\t\t\t\t*wheelState = WHEEL_STATE_FIXED;\n\t\t}else {\n\t\t\tif(fwd > 0.0f){\n\t\t\t\tif(fwd > brake)\n\t\t\t\t\tfwd = brake;\n\t\t\t}else{\n\t\t\t\tif(fwd < -brake)\n\t\t\t\t\tfwd = -brake;\n\t\t\t}\n\t\t}\n\t}\n\n\tfloat speedSq = sq(right) + sq(fwd);\n\tif(sq(adhesion) < speedSq){\n\t\tif(*wheelState != WHEEL_STATE_FIXED){\n\t\t\tif(bDriving && contactSpeedFwd < 0.2f)\n\t\t\t\t*wheelState = WHEEL_STATE_SPINNING;\n\t\t\telse\n\t\t\t\t*wheelState = WHEEL_STATE_SKIDDING;\n\t\t}\n\n\t\tfloat l = Sqrt(speedSq);\n\t\tfloat tractionLoss = bAlreadySkidding ? 1.0f : pHandling->fTractionLoss;\n\t\tright *= adhesion * tractionLoss / l;\n\t\tfwd *= adhesion * tractionLoss / l;\n\t}\n\n\tif(fwd != 0.0f || right != 0.0f){\n\t\tCVector totalSpeed = fwd*wheelFwd + right*wheelRight;\n\n\t\tCVector turnDirection = totalSpeed;\n\t\tbool separateTurnForce = false;\t// BUG: not initialized on PC\n\t\tif(pHandling->fSuspensionAntidiveMultiplier > 0.0f){\n\t\t\tif(bBraking){\n\t\t\t\tseparateTurnForce = true;\n\t\t\t\tturnDirection = totalSpeed - pHandling->fSuspensionAntidiveMultiplier*fwd*wheelFwd;\n\t\t\t}else if(bDriving){\n\t\t\t\tseparateTurnForce = true;\n\t\t\t\tturnDirection = totalSpeed - 0.5f*pHandling->fSuspensionAntidiveMultiplier*fwd*wheelFwd;\n\t\t\t}\n\t\t}\n\n\t\tCVector direction = totalSpeed;\n\n\t\tfloat speed = totalSpeed.Magnitude();\n\t\tfloat turnSpeed;\n\t\tif(separateTurnForce)\n\t\t\tturnSpeed = turnDirection.Magnitude();\n\t\telse\n\t\t\tturnSpeed = speed;\n\t\tdirection.Normalise();\n\t\tif(separateTurnForce)\n\t\t\tturnDirection.Normalise();\n\t\telse\n\t\t\tturnDirection = direction;\n\n\t\tfloat impulse = speed*m_fMass;\n\t\tfloat turnImpulse = turnSpeed*GetMass(wheelContactPoint, turnDirection);\n\n\t\tApplyMoveForce(impulse * direction);\n\t\tApplyTurnForce(turnImpulse * turnDirection, wheelContactPoint);\n\t}\n}\n\nfloat fBurstBikeSpeedMax = 0.12f;\nfloat fBurstBikeTyreMod = 0.05f;\nfloat fTweakBikeWheelTurnForce = 2.0f;\n\nvoid\nCVehicle::ProcessBikeWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelContactSpeed, CVector &wheelContactPoint,\n\tint32 wheelsOnGround, float thrust, float brake, float adhesion, float destabTraction, int8 wheelId, float *wheelSpeed, tWheelState *wheelState, eBikeWheelSpecial special, uint16 wheelStatus)\n{\n\t// BUG: using statics here is probably a bad idea\n\tstatic bool bAlreadySkidding = false;\t// this is never reset\n\tstatic bool bBraking;\n\tstatic bool bDriving;\n\tstatic bool bReversing;\n\n#ifdef FIX_SIGNIFICANT_BUGS\n\tbAlreadySkidding = false;\n#endif\n\n\t// how much force we want to apply in these axes\n\tfloat fwd = 0.0f;\n\tfloat right = 0.0f;\n\n\tbBraking = brake != 0.0f;\n\tif(bBraking)\n\t\tthrust = 0.0f;\n\tbDriving = thrust != 0.0f;\n\tbReversing = thrust < 0.0f;\n\n\tfloat contactSpeedFwd = DotProduct(wheelContactSpeed, wheelFwd);\n\tfloat contactSpeedRight;\n\n\tif(*wheelState != WHEEL_STATE_NORMAL)\n\t\tbAlreadySkidding = true;\n\t*wheelState = WHEEL_STATE_NORMAL;\n\n\tadhesion *= CTimer::GetTimeStep();\n\tif(bAlreadySkidding)\n\t\tadhesion *= pHandling->fTractionLoss;\n\n\tif(special == BIKE_WHEELSPEC_2 || special == BIKE_WHEELSPEC_3)\n\t\tcontactSpeedRight = 0.0f;\n\telse\n\t\tcontactSpeedRight = DotProduct(wheelContactSpeed, wheelRight);\n\n\t// moving sideways\n\tif(contactSpeedRight != 0.0f){\n\t\t// exert opposing force\n\t\tright = -contactSpeedRight/wheelsOnGround;\n#ifdef FIX_BUGS\n\t\t// contactSpeedRight is independent of framerate but right has timestep as a factor\n\t\t// so we probably have to fix this\n\t\tright *= CTimer::GetTimeStepFix();\n#endif\n\n\t\tif(wheelStatus == WHEEL_STATUS_BURST){\n\t\t\tfloat fwdspeed = Min(contactSpeedFwd, fBurstBikeSpeedMax);\n\t\t\tright += fwdspeed * CGeneral::GetRandomNumberInRange(-fBurstBikeTyreMod, fBurstBikeTyreMod);\n\t\t}\n\t}\n\n\tif(bDriving){\n\t\tfwd = thrust;\n\n\t\t// limit sideways force (why?)\n\t\tif(right > 0.0f){\n\t\t\tif(right > adhesion)\n\t\t\t\tright = adhesion;\n\t\t}else{\n\t\t\tif(right < -adhesion)\n\t\t\t\tright = -adhesion;\n\t\t}\n\t}else if(contactSpeedFwd != 0.0f){\n\t\tfwd = -contactSpeedFwd/wheelsOnGround;\n#ifdef FIX_BUGS\n\t\t// contactSpeedFwd is independent of framerate but fwd has timestep as a factor\n\t\t// so we probably have to fix this\n\t\tfwd *= CTimer::GetTimeStepFix();\n#endif\n\n\t\tif(!bBraking){\n\t\t\tif(m_fGasPedal < 0.01f){\n\t\t\t\tif(IsBike())\n\t\t\t\t\tbrake = 0.6f * mod_HandlingManager.fWheelFriction / (pHandling->fMass + 200.0f);\n\t\t\t\telse if(pHandling->fMass < 500.0f)\n\t\t\t\t\tbrake = mod_HandlingManager.fWheelFriction / m_fMass;\n\t\t\t\telse if(GetModelIndex() == MI_RCBANDIT)\n\t\t\t\t\tbrake = 0.2f * mod_HandlingManager.fWheelFriction / m_fMass;\n\t\t\t\telse\n\t\t\t\t\tbrake = mod_HandlingManager.fWheelFriction / m_fMass;\n#ifdef FIX_BUGS\n\t\t\t\tbrake *= CTimer::GetTimeStepFix();\n#endif\n\t\t\t}\n\t\t}\n\n\t\tif(brake > adhesion){\n\t\t\tif(Abs(contactSpeedFwd) > 0.005f)\n\t\t\t\t*wheelState = WHEEL_STATE_FIXED;\n\t\t}else {\n\t\t\tif(fwd > 0.0f){\n\t\t\t\tif(fwd > brake)\n\t\t\t\t\tfwd = brake;\n\t\t\t}else{\n\t\t\t\tif(fwd < -brake)\n\t\t\t\t\tfwd = -brake;\n\t\t\t}\n\t\t}\n\t}\n\n\tfloat speedSq = sq(right) + sq(fwd);\n\tif(sq(adhesion) < speedSq){\n\t\tif(*wheelState != WHEEL_STATE_FIXED){\n\t\t\tif(bDriving && contactSpeedFwd < 0.2f)\n\t\t\t\t*wheelState = WHEEL_STATE_SPINNING;\n\t\t\telse\n\t\t\t\t*wheelState = WHEEL_STATE_SKIDDING;\n\t\t}\n\n\t\tfloat l = Sqrt(speedSq);\n\t\tfloat tractionLoss = bAlreadySkidding ? 1.0f : pHandling->fTractionLoss;\n\t\tright *= adhesion * tractionLoss / l;\n\t\tfwd *= adhesion * tractionLoss / l;\n\n\t\tif(destabTraction < 1.0f)\n\t\t\tright *= destabTraction;\n\t}else if(destabTraction < 1.0f){\n\t\tif(!bAlreadySkidding)\n\t\t\tdestabTraction *= pHandling->fTractionLoss;\n\t\tif(sq(adhesion*destabTraction) < speedSq){\n\t\t\tfloat l = Sqrt(speedSq);\n\t\t\tright *= adhesion * destabTraction / l;\n\t\t}\n\t}\n\n\tif(fwd != 0.0f || right != 0.0f){\n\t\tCVector direction = fwd*wheelFwd + right*wheelRight;\n\n\t\tfloat speed = direction.Magnitude();\n\t\tdirection.Normalise();\n\n\t\tfloat impulse = speed*m_fMass;\n\t\tfloat turnImpulse = speed*GetMass(wheelContactPoint, direction);\n\t\tCVector vTurnImpulse = turnImpulse * direction;\n\t\tApplyMoveForce(impulse * direction);\n\n\t\tfloat turnRight = DotProduct(vTurnImpulse, GetRight());\n\t\tfloat contactRight = DotProduct(wheelContactPoint, GetRight());\n\t\tfloat contactFwd = DotProduct(wheelContactPoint, GetForward());\n\n\t\tif(wheelId != BIKEWHEEL_REAR || !bBraking && !bReversing)\n\t\t\tApplyTurnForce((vTurnImpulse - turnRight*GetRight()) * fTweakBikeWheelTurnForce,\n\t\t\t\twheelContactPoint - contactRight*GetRight());\n\n\t\tApplyTurnForce(turnRight*GetRight(), contactFwd*GetForward());\n\t}\n}\n\nfloat\nCVehicle::ProcessWheelRotation(tWheelState state, const CVector &fwd, const CVector &speed, float radius)\n{\n\tfloat angularVelocity;\n\tswitch(state){\n\tcase WHEEL_STATE_SPINNING:\n\t\tangularVelocity = -1.1f;\t// constant speed forward\n\t\tbreak;\n\tcase WHEEL_STATE_FIXED:\n\t\tangularVelocity = 0.0f;\t\t// not moving\n\t\tbreak;\n\tdefault:\n\t\tangularVelocity = -DotProduct(fwd, speed) / radius;\t// forward speed\n\t\tbreak;\n\t}\n\treturn angularVelocity * CTimer::GetTimeStep();\n}\n\nint\nCVehicle::FindTyreNearestPoint(float x, float y)\n{\n\tCVector pos = CVector(x - GetPosition().x, y - GetPosition().y, 0.0f);\n\tfloat fwd = DotProduct(GetForward(), pos);\n\tfloat right = DotProduct(GetRight(), pos);\n\n\tint piece;\n\tif(IsBike()){\n\t\tpiece = fwd > 0.0f ? CAR_PIECE_WHEEL_LF : CAR_PIECE_WHEEL_LR;\n\t}else{\n\t\tpiece = fwd > 0.0f ?\n\t\t\tright > 0.0f ? CAR_PIECE_WHEEL_RF : CAR_PIECE_WHEEL_LF :\n\t\t\tright > 0.0f ? CAR_PIECE_WHEEL_RR : CAR_PIECE_WHEEL_LR;\n\t}\n\treturn piece - CAR_PIECE_WHEEL_LF;\n}\n\nvoid\nCVehicle::InflictDamage(CEntity *damagedBy, eWeaponType weaponType, float damage, CVector pos)\n{\n\tif (!bCanBeDamaged)\n\t\treturn;\n\tif(GetStatus() == STATUS_PLAYER && CStats::GetPercentageProgress() >= 100.0f)\n\t\tdamage *= 0.5f;\n\tif (GetStatus() != STATUS_PLAYER && bOnlyDamagedByPlayer && (damagedBy != FindPlayerPed() && damagedBy != FindPlayerVehicle()))\n\t\treturn;\n\n\tif(damage > 10.0f && (damagedBy == FindPlayerPed() || damagedBy == FindPlayerVehicle()) && GetStatus() != STATUS_WRECKED){\n\t\tCWorld::Players[CWorld::PlayerInFocus].m_nHavocLevel += 2;\n\t\tCWorld::Players[CWorld::PlayerInFocus].m_fMediaAttention += 1.0f;\n\t\tCStats::PropertyDestroyed += CGeneral::GetRandomNumberInRange(5, 25);\n\t}\n\n\tbool bFrightensDriver = false;\n\tswitch (weaponType) {\n\tcase WEAPONTYPE_UNARMED:\n\tcase WEAPONTYPE_BRASSKNUCKLE:\n\tcase WEAPONTYPE_SCREWDRIVER:\n\tcase WEAPONTYPE_GOLFCLUB:\n\tcase WEAPONTYPE_NIGHTSTICK:\n\tcase WEAPONTYPE_KNIFE:\n\tcase WEAPONTYPE_BASEBALLBAT:\n\tcase WEAPONTYPE_HAMMER:\n\tcase WEAPONTYPE_CLEAVER:\n\tcase WEAPONTYPE_MACHETE:\n\tcase WEAPONTYPE_KATANA:\n\tcase WEAPONTYPE_CHAINSAW:\n\t\tif (bMeleeProof)\n\t\t\treturn;\n\t\tbreak;\n\tcase WEAPONTYPE_COLT45:\n\tcase WEAPONTYPE_PYTHON:\n\tcase WEAPONTYPE_SHOTGUN:\n\tcase WEAPONTYPE_SPAS12_SHOTGUN:\n\tcase WEAPONTYPE_STUBBY_SHOTGUN:\n\tcase WEAPONTYPE_TEC9:\n\tcase WEAPONTYPE_UZI:\n\tcase WEAPONTYPE_SILENCED_INGRAM:\n\tcase WEAPONTYPE_MP5:\n\tcase WEAPONTYPE_M4:\n\tcase WEAPONTYPE_RUGER:\n\tcase WEAPONTYPE_SNIPERRIFLE:\n\tcase WEAPONTYPE_LASERSCOPE:\n\tcase WEAPONTYPE_M60:\n\tcase WEAPONTYPE_MINIGUN:\n\tcase WEAPONTYPE_HELICANNON:\n\tcase WEAPONTYPE_UZI_DRIVEBY:\n\t\tif (bBulletProof)\n\t\t\treturn;\n\t\tbFrightensDriver = true;\n\t\tbreak;\n\tcase WEAPONTYPE_GRENADE:\n\tcase WEAPONTYPE_MOLOTOV:\n\tcase WEAPONTYPE_ROCKET:\n\tcase WEAPONTYPE_EXPLOSION:\n\t\tif (bExplosionProof)\n\t\t\treturn;\n\t\tbFrightensDriver = true;\n\t\tbreak;\n\tcase WEAPONTYPE_FLAMETHROWER:\n\t\tif (bFireProof)\n\t\t\treturn;\n\t\tbreak;\n\tcase WEAPONTYPE_RAMMEDBYCAR:\n\t\tif (bCollisionProof)\n\t\t\treturn;\n\t\tbreak;\n\tdefault:\n\t\tbreak;\n\t}\n\n\tif(bFrightensDriver && GetStatus() == STATUS_PLAYER && m_fHealth < 250.0f)\n\t\treturn;\n\n\t// Pop tires\n\tif(damagedBy && damagedBy->IsPed() && (IsCar() || IsBike())){\n\t\tint accuracy = 0;\n\t\tswitch(weaponType){\n\t\tcase WEAPONTYPE_COLT45:\n\t\t\taccuracy = 10;\n\t\t\tbreak;\n\t\tcase WEAPONTYPE_PYTHON:\n\t\t\tif(!((CPed*)damagedBy)->IsPlayer())\n\t\t\t\taccuracy = 64;\n\t\t\tbreak;\n\t\tcase WEAPONTYPE_SHOTGUN:\n\t\tcase WEAPONTYPE_STUBBY_SHOTGUN:\n\t\tcase WEAPONTYPE_M60:\n\t\tcase WEAPONTYPE_HELICANNON:\n\t\t\taccuracy = 25;\n\t\t\tbreak;\n\t\tcase WEAPONTYPE_TEC9:\n\t\tcase WEAPONTYPE_UZI:\n\t\tcase WEAPONTYPE_SILENCED_INGRAM:\n\t\tcase WEAPONTYPE_MP5:\n\t\tcase WEAPONTYPE_UZI_DRIVEBY:\n\t\t\taccuracy = 15;\n\t\t\tbreak;\n\t\tcase WEAPONTYPE_M4:\n\t\tcase WEAPONTYPE_RUGER:\n\t\t\tif(!((CPed*)damagedBy)->IsPlayer())\n\t\t\t\taccuracy = 15;\n\t\t\tbreak;\n\t\t}\n\n\t\tif(((CPed*)damagedBy)->IsPlayer() && (CCamera::m_bUseMouse3rdPerson || TheCamera.Using1stPersonWeaponMode()))\n\t\t\taccuracy = 0;\n\n\t\tif(accuracy != 0 && !bTyresDontBurst && (CGeneral::GetRandomNumber()&0x7F) < accuracy){\n\t\t\tif(IsBike())\n\t\t\t\tBurstTyre(FindTyreNearestPoint(pos.x, pos.y) + CAR_PIECE_WHEEL_LF, false);\n\t\t\telse if(GetVehicleAppearance() == VEHICLE_APPEARANCE_CAR)\n\t\t\t\tBurstTyre(FindTyreNearestPoint(pos.x, pos.y) + CAR_PIECE_WHEEL_LF, true);\n\t\t}\n\t}\n\n\tif (m_fHealth > 0.0f) {\n\t\tif (VehicleCreatedBy == RANDOM_VEHICLE && pDriver &&\n\t\t\t(GetStatus() == STATUS_SIMPLE || GetStatus() == STATUS_PHYSICS) &&\n\t\t\tAutoPilot.m_nCarMission == MISSION_CRUISE) {\n\t\t\tif (m_randomSeed < DAMAGE_FLEE_IN_CAR_PROBABILITY_VALUE) {\n\t\t\t\tCCarCtrl::SwitchVehicleToRealPhysics(this);\n\t\t\t\tAutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS;\n\t\t\t\tAutoPilot.m_nCruiseSpeed = GAME_SPEED_TO_CARAI_SPEED * pHandling->Transmission.fMaxCruiseVelocity;\n\t\t\t\tSetStatus(STATUS_PHYSICS);\n\t\t\t}\n\t\t}\n\t\tm_nLastWeaponDamage = weaponType;\n\t\tm_pLastDamageEntity = damagedBy;\n\t\tfloat oldHealth = m_fHealth;\n\t\tif (m_fHealth > damage) {\n\t\t\tm_fHealth -= damage;\n\t\t\tif (VehicleCreatedBy == RANDOM_VEHICLE && !IsBoat()){\n\t\t\t\tswitch (GetStatus()) {\n\t\t\t\tcase STATUS_SIMPLE:\n\t\t\t\tcase STATUS_PHYSICS:\n\t\t\t\t\tif(AutoPilot.m_nDrivingStyle == DRIVINGSTYLE_PLOUGH_THROUGH ||\n\t\t\t\t\t   CGeneral::GetRandomNumberInRange(0.0f, 1.0f) > 0.5f && AutoPilot.m_nCarMission == MISSION_CRUISE){\n\t\t\t\t\t\t// Drive away like a maniac\n\t\t\t\t\t\tif(pDriver && pDriver->m_objective != OBJECTIVE_LEAVE_CAR){\n\t\t\t\t\t\t\tif(AutoPilot.m_nDrivingStyle != DRIVINGSTYLE_PLOUGH_THROUGH)\n\t\t\t\t\t\t\t\tAutoPilot.m_nCruiseSpeed *= 1.5f;\n\t\t\t\t\t\t\tAutoPilot.m_nDrivingStyle = DRIVINGSTYLE_PLOUGH_THROUGH;\n\t\t\t\t\t\t}\n\t\t\t\t\t}else{\n\t\t\t\t\t\t// Leave vehicle\n\t\t\t\t\t\tif (pDriver && pDriver->CharCreatedBy != MISSION_CHAR) {\n\t\t\t\t\t\t\tSetStatus(STATUS_ABANDONED);\n\t\t\t\t\t\t\tpDriver->bFleeAfterExitingCar = true;\n\t\t\t\t\t\t\tpDriver->SetObjective(OBJECTIVE_LEAVE_CAR, this);\n\t\t\t\t\t\t\tpDriver->Say(SOUND_PED_FLEE_SPRINT);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tint time = 200;\n\t\t\t\t\t\tfor (int i = 0; i < m_nNumMaxPassengers; i++) {\n\t\t\t\t\t\t\tif (pPassengers[i] &&\n\t\t\t\t\t\t\t    pPassengers[i]->m_objective != OBJECTIVE_LEAVE_CAR &&\n\t\t\t\t\t\t\t    pPassengers[i]->CharCreatedBy != MISSION_CHAR) {\n\t\t\t\t\t\t\t\tpPassengers[i]->bFleeAfterExitingCar = true;\n\t\t\t\t\t\t\t\tpPassengers[i]->SetObjective(OBJECTIVE_LEAVE_CAR, this);\n\t\t\t\t\t\t\t\tpPassengers[i]->m_objectiveTimer = CTimer::GetTimeInMilliseconds() + time;\n\t\t\t\t\t\t\t\tpPassengers[i]->Say(SOUND_PED_FLEE_SPRINT);\n\t\t\t\t\t\t\t\ttime += 200;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (oldHealth >= DAMAGE_HEALTH_TO_CATCH_FIRE && m_fHealth < DAMAGE_HEALTH_TO_CATCH_FIRE) {\n\t\t\t\tif (IsCar()) {\n\t\t\t\t\tCAutomobile* pThisCar = (CAutomobile*)this;\n\t\t\t\t\tpThisCar->Damage.SetEngineStatus(ENGINE_STATUS_ON_FIRE);\n\t\t\t\t\tpThisCar->m_pSetOnFireEntity = damagedBy;\n\t\t\t\t\tif (damagedBy)\n\t\t\t\t\t\tdamagedBy->RegisterReference((CEntity**)&pThisCar->m_pSetOnFireEntity);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tm_fHealth = 0.0f;\n\t\t\tif (weaponType == WEAPONTYPE_EXPLOSION) {\n\t\t\t\t// between 1000 and 3047. Also not very nice: can't be saved by respray or cheat\n\t\t\t\tm_nBombTimer = 1000 + CGeneral::GetRandomNumber() & 0x7FF;\n\t\t\t\tm_pBlowUpEntity = damagedBy;\n\t\t\t\tif (damagedBy)\n\t\t\t\t\tdamagedBy->RegisterReference((CEntity**)&m_pBlowUpEntity);\n\t\t\t}\n\t\t\telse\n\t\t\t\tBlowUpCar(damagedBy);\n\t\t}\n\t}\n#ifdef FIX_BUGS // removing dumb case when shooting police car in player's own garage gives wanted level\n\tif (GetModelIndex() == MI_POLICE && damagedBy == FindPlayerPed() && damagedBy != nil && !bHasBeenOwnedByPlayer)\n#else\n\tif (GetModelIndex() == MI_POLICE && damagedBy == FindPlayerPed())\n#endif\n\t\tFindPlayerPed()->SetWantedLevelNoDrop(1);\n}\n\nvoid\nCVehicle::DoFixedMachineGuns(void)\n{\n\tif(TheCamera.Cams[TheCamera.ActiveCam].DirectionWasLooking == LOOKING_FORWARD){\n\t\tif(CPad::GetPad(0)->GetCarGunFired() && !bGunSwitchedOff){\n\t\t\tFireFixedMachineGuns();\n\t\t}else{\n\t\t\tif(CTimer::GetTimeInMilliseconds() > m_nGunFiringTime + 1400)\n\t\t\t\tm_nAmmoInClip = 20;\n\t\t}\n\t}\n}\n\nvoid\nCVehicle::FireFixedMachineGuns(void)\n{\n\tif (CTimer::GetTimeInMilliseconds() <= m_nGunFiringTime + 150)\n\t\treturn;\n\tCVector source, target;\n\tfloat dx, dy, len;\n\n\tdx = GetForward().x;\n\tdy = GetForward().y;\n\tlen = Sqrt(SQR(dx) + SQR(dy));\n\tif (len < 0.1f) len = 0.1f;\n\tdx /= len;\n\tdy /= len;\n\n\tm_nGunFiringTime = CTimer::GetTimeInMilliseconds();\n\n\tsource = GetMatrix() * CVector(2.0f, 2.5f, 1.0f);\n\ttarget = source + CVector(dx, dy, 0.0f) * 60.0f;\n\ttarget += CVector(\n\t\t((CGeneral::GetRandomNumber() & 0xFF) - 128) * 0.015f,\n\t\t((CGeneral::GetRandomNumber() & 0xFF) - 128) * 0.015f,\n\t\t((CGeneral::GetRandomNumber() & 0xFF) - 128) * 0.02f);\n\tCWeapon::DoTankDoomAiming(this, pDriver, &source, &target);\n\tFireOneInstantHitRound(&source, &target, 15);\n\n\tsource = GetMatrix() * CVector(-2.0f, 2.5f, 1.0f);\n\ttarget = source + CVector(dx, dy, 0.0f) * 60.0f;\n\ttarget += CVector(\n\t\t((CGeneral::GetRandomNumber() & 0xFF) - 128) * 0.015f,\n\t\t((CGeneral::GetRandomNumber() & 0xFF) - 128) * 0.015f,\n\t\t((CGeneral::GetRandomNumber() & 0xFF) - 128) * 0.02f);\n\tCWeapon::DoTankDoomAiming(this, pDriver, &source, &target);\n\tFireOneInstantHitRound(&source, &target, 15);\n\n\tDMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_SHOT_FIRED, 0.0f);\n\n\tm_nAmmoInClip--;\n\tif (m_nAmmoInClip == 0) {\n\t\tm_nAmmoInClip = 20;\n\t\tm_nGunFiringTime = CTimer::GetTimeInMilliseconds() + 1400;\n\t}\n}\n\nvoid\nCVehicle::ActivateBomb(void)\n{\n\tif(m_bombType == CARBOMB_TIMED){\n\t\tm_bombType = CARBOMB_TIMEDACTIVE;\n\t\tm_nBombTimer = 7000;\n\t\tm_pBlowUpEntity = FindPlayerPed();\n\t\tCGarages::TriggerMessage(\"GA_12\", -1, 3000, -1);\n\t\tDMAudio.PlayOneShot(m_audioEntityId, SOUND_BOMB_TIMED_ACTIVATED, 1.0f);\n\t}else if(m_bombType == CARBOMB_ONIGNITION){\n\t\tm_bombType = CARBOMB_ONIGNITIONACTIVE;\n\t\tCGarages::TriggerMessage(\"GA_12\", -1, 3000, -1);\n\t\tDMAudio.PlayOneShot(m_audioEntityId, SOUND_BOMB_ONIGNITION_ACTIVATED, 1.0f);\n\t}\n}\n\nvoid\nCVehicle::ActivateBombWhenEntered(void)\n{\n\tif(pDriver){\n\t\tif(!bDriverLastFrame && m_bombType == CARBOMB_ONIGNITIONACTIVE){\n\t\t\t// If someone enters the car and there is a bomb, detonate\n\t\t\tm_nBombTimer = 1000;\n\t\t\tm_pBlowUpEntity = m_pBombRigger;\n\t\t\tif(m_pBlowUpEntity)\n\t\t\t\tm_pBlowUpEntity->RegisterReference((CEntity**)&m_pBlowUpEntity);\n\t\t\tDMAudio.PlayOneShot(m_audioEntityId, SOUND_BOMB_TICK, 1.0f);\n\t\t}\n\t\tbDriverLastFrame = true;\n\t}else\n\t\tbDriverLastFrame = false;\n}\n\nvoid\nCVehicle::ExtinguishCarFire(void)\n{\n\tif(GetStatus() != STATUS_WRECKED)\n\t\tm_fHealth = Max(m_fHealth, 300.0f);\n\tif(m_pCarFire)\n\t\tm_pCarFire->Extinguish();\n\tif(IsCar()){\n\t\tCAutomobile *car = (CAutomobile*)this;\n\t\tif(car->Damage.GetEngineStatus() >= ENGINE_STATUS_ON_FIRE)\n\t\t\tcar->Damage.SetEngineStatus(ENGINE_STATUS_ON_FIRE-10);\n\t\tcar->m_fFireBlowUpTimer = 0.0f;\n\t}\n}\n\nbool\nCVehicle::ShufflePassengersToMakeSpace(void)\n{\n\tif (m_nNumPassengers >= m_nNumMaxPassengers)\n\t\treturn false;\n\tif (pPassengers[1] &&\n\t\t!(m_nGettingInFlags & CAR_DOOR_FLAG_LR) &&\n\t\tIsRoomForPedToLeaveCar(CAR_DOOR_LR, nil)) {\n\t\tif (!pPassengers[2] && !(m_nGettingInFlags & CAR_DOOR_FLAG_RR)) {\n\t\t\tpPassengers[2] = pPassengers[1];\n\t\t\tpPassengers[1] = nil;\n\t\t\tpPassengers[2]->m_vehDoor = CAR_DOOR_RR;\n\t\t\treturn true;\n\t\t}\n\t\tif (!pPassengers[0] && !(m_nGettingInFlags & CAR_DOOR_FLAG_RF)) {\n\t\t\tpPassengers[0] = pPassengers[1];\n\t\t\tpPassengers[1] = nil;\n\t\t\tpPassengers[0]->m_vehDoor = CAR_DOOR_RF;\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\tif (pPassengers[2] &&\n\t\t!(m_nGettingInFlags & CAR_DOOR_FLAG_RR) &&\n\t\tIsRoomForPedToLeaveCar(CAR_DOOR_RR, nil)) {\n\t\tif (!pPassengers[1] && !(m_nGettingInFlags & CAR_DOOR_FLAG_LR)) {\n\t\t\tpPassengers[1] = pPassengers[2];\n\t\t\tpPassengers[2] = nil;\n\t\t\tpPassengers[1]->m_vehDoor = CAR_DOOR_LR;\n\t\t\treturn true;\n\t\t}\n\t\tif (!pPassengers[0] && !(m_nGettingInFlags & CAR_DOOR_FLAG_RF)) {\n\t\t\tpPassengers[0] = pPassengers[2];\n\t\t\tpPassengers[2] = nil;\n\t\t\tpPassengers[0]->m_vehDoor = CAR_DOOR_RF;\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\tif (pPassengers[0] &&\n\t\t!(m_nGettingInFlags & CAR_DOOR_FLAG_RF) &&\n\t\tIsRoomForPedToLeaveCar(CAR_DOOR_RF, nil)) {\n\t\tif (!pPassengers[1] && !(m_nGettingInFlags & CAR_DOOR_FLAG_LR)) {\n\t\t\tpPassengers[1] = pPassengers[0];\n\t\t\tpPassengers[0] = nil;\n\t\t\tpPassengers[1]->m_vehDoor = CAR_DOOR_LR;\n\t\t\treturn true;\n\t\t}\n\t\tif (!pPassengers[2] && !(m_nGettingInFlags & CAR_DOOR_FLAG_RR)) {\n\t\t\tpPassengers[2] = pPassengers[0];\n\t\t\tpPassengers[0] = nil;\n\t\t\tpPassengers[2]->m_vehDoor = CAR_DOOR_RR;\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\treturn false;\n}\n\nvoid\nCVehicle::MakeNonDraggedPedsLeaveVehicle(CPed *ped1, CPed *ped2, CPlayerPed *&player, CCopPed *&cop)\n{\n\tint i;\n\tplayer = nil;\n\tcop = nil;\n\n\tif(ped1->IsPlayer() && ped2->m_nPedType == PEDTYPE_COP &&\n\t   ((CPlayerPed*)ped1)->m_pWanted->GetWantedLevel() > 0 &&\n\t   ped2->m_pedInObjective == ped1){\n\t\tplayer = (CPlayerPed*)ped1;\n\t\tcop = (CCopPed*)ped2;\n\t\treturn;\n\t}\n\n\tbool ped1IsDriver = ped1 == pDriver;\n\n\t// Just what the hell is this weird code?\n\tCPed *peds[9];\n\tCPed *peds2[9];\n\tint numPeds = 0;\n\tint numPeds2 = 0;\n\tfor(i = 0; i < m_nNumMaxPassengers; i++){\n\t\tCPed *p = pPassengers[i];\n\t\tif(p && p != ped1 && !p->bStayInCarOnJack){\n\t\t\tpeds[numPeds++] = p;\n\t\t\t// uhh what?\n\t\t\tif(i < 1 && !ped1IsDriver)\n\t\t\t\tcontinue;\n\t\t\tpeds2[numPeds2++] = p;\n\t\t}\n\t}\n\n\t// So we're copying this array for no reason...\n\tCPed *peds3[9];\n\tint numPeds3 = 0;\n\tfor(i = 0; i < numPeds; i++){\n\t\tif(peds[i]->IsPlayer() && ped2->m_nPedType == PEDTYPE_COP &&\n\t\t   ((CPlayerPed*)peds[i])->m_pWanted->GetWantedLevel() > 0 &&\n\t\t   ped2->m_pedInObjective == peds[i]){\n\t\t\tplayer = (CPlayerPed*)peds[i];\n\t\t\tcop = (CCopPed*)ped2;\n\t\t\treturn;\n\t\t}\n\t\tpeds3[numPeds3++] = peds[i];\n\t}\n\n\tint time = 1800;\n\tfor(i = 0; i < numPeds3; i++){\n\t\tpeds3[i]->m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + time;\n\t\tpeds3[i]->SetObjective(OBJECTIVE_LEAVE_CAR, this);\n\t\ttime += CGeneral::GetRandomNumberInRange(300.0f, 600.0f);\n\t}\n\n\tif(IsCar() && numPeds2 > 0 && CGeneral::GetRandomTrueFalse())\n\t\tfor(i = 0; i < numPeds2; i++)\n\t\t\tif(peds2[i]->IsFemale() || CGeneral::GetRandomTrueFalse()){\n\t\t\t\tpeds2[i]->m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + 10000;\n\t\t\t\tpeds2[i]->bHeldHostageInCar = true;\n\t\t\t\tpeds2[i]->bFleeAfterExitingCar = true;\n\t\t\t}\n}\n\nvoid\nCVehicle::ProcessDelayedExplosion(void)\n{\n\tif(m_nBombTimer == 0)\n\t\treturn;\n\n\tint tick = CTimer::GetTimeStep()/60.0f*1000.0f;\n\tint16 prev = m_nBombTimer;\n\tif(tick > m_nBombTimer)\n\t\tm_nBombTimer = 0;\n\telse\n\t\tm_nBombTimer -= tick;\n\n\tif(IsCar() && ((CAutomobile*)this)->m_bombType == CARBOMB_TIMEDACTIVE && (m_nBombTimer & 0xFE00) != (prev & 0xFE00))\n\t\tDMAudio.PlayOneShot(m_audioEntityId, SOUND_CAR_BOMB_TICK, 0.0f);\n\n\tif (m_nBombTimer != 0)\n\t\treturn;\n\n\tBlowUpCar(m_pBlowUpEntity);\n}\n\nbool\nCVehicle::IsLawEnforcementVehicle(void)\n{\n\tswitch(GetModelIndex()){\n\tcase MI_POLICE:\n\tcase MI_ENFORCER:\n\tcase MI_PREDATOR:\n\tcase MI_RHINO:\n\tcase MI_BARRACKS:\n\tcase MI_FBIRANCH:\n\tcase MI_VICECHEE:\n\t\treturn true;\n\tdefault:\n\t\treturn false;\n\t}\n}\n\nbool\nCVehicle::UsesSiren(void)\n{\n\tswitch(GetModelIndex()){\n\tcase MI_FIRETRUCK:\n\tcase MI_AMBULAN:\n\tcase MI_FBICAR:\n\tcase MI_MRWHOOP:\n\tcase MI_POLICE:\n\tcase MI_ENFORCER:\n\tcase MI_PREDATOR:\n\tcase MI_FBIRANCH:\n\tcase MI_VICECHEE:\n\t\treturn true;\n\tdefault:\n\t\treturn false;\n\t}\n}\n\nbool\nCVehicle::IsVehicleNormal(void)\n{\n\tif (!pDriver || m_nNumPassengers != 0 || GetStatus() == STATUS_WRECKED)\n\t\treturn false;\n\treturn GetModelInfo()->m_vehicleClass != -1;\n}\n\nbool\nCVehicle::CarHasRoof(void)\n{\n\tif((pHandling->Flags & HANDLING_HAS_NO_ROOF) == 0)\n\t\treturn true;\n\t// component 0 is assumed to be a roof\n\treturn m_aExtras[0] == 0 || m_aExtras[1] == 0;\n}\n\nbool\nCVehicle::IsUpsideDown(void)\n{\n\tif(GetUp().z > -0.9f)\n\t\treturn false;\n\treturn true;\n}\n\nbool\nCVehicle::IsOnItsSide(void)\n{\n\tif(GetRight().z < 0.8f && GetRight().z > -0.8f)\n\t\treturn false;\n\treturn true;\n}\n\nbool\nCVehicle::CanBeDeleted(void)\n{\n\tint i;\n\n\tif(m_nNumGettingIn || m_nGettingOutFlags)\n\t\treturn false;\n\n\tif(pDriver){\n\t\t// This looks like it was inlined\n\t\tif(pDriver->CharCreatedBy == MISSION_CHAR)\n\t\t\treturn false;\n\t\tif(pDriver->GetPedState() != PED_DRIVING &&\n\t\t   pDriver->GetPedState() != PED_DEAD)\n\t\t\treturn false;\n\t}\n\n\tfor(i = 0; i < ARRAY_SIZE(pPassengers); i++){\n\t\t// Same check as above\n\t\tif(pPassengers[i]){\n\t\t\tif(pPassengers[i]->CharCreatedBy == MISSION_CHAR)\n\t\t\t\treturn false;\n\t\t\tif(pPassengers[i]->GetPedState() != PED_DRIVING &&\n\t\t\t   pPassengers[i]->GetPedState() != PED_DEAD)\n\t\t\t\treturn false;\n\t\t}\n\t\t// and then again... probably because something was inlined\n\t\tif(pPassengers[i]){\n\t\t\tif(pPassengers[i]->GetPedState() != PED_DRIVING &&\n\t\t\t   pPassengers[i]->GetPedState() != PED_DEAD)\n\t\t\t\treturn false;\n\t\t}\n\t}\n\n\tswitch(VehicleCreatedBy){\n\tcase RANDOM_VEHICLE: return true;\n\tcase MISSION_VEHICLE: return false;\n\tcase PARKED_VEHICLE: return true;\n\tcase PERMANENT_VEHICLE: return false;\n\t}\n\treturn true;\n}\n\nbool\nCVehicle::CanPedOpenLocks(CPed *ped)\n{\n\tif(m_nDoorLock == CARLOCK_LOCKED ||\n\t   m_nDoorLock == CARLOCK_LOCKED_INITIALLY ||\n\t   m_nDoorLock == CARLOCK_LOCKED_PLAYER_INSIDE ||\n\t   m_nDoorLock == CARLOCK_SKIP_SHUT_DOORS)\n\t\treturn false;\n\tif(ped->IsPlayer() && m_nDoorLock == CARLOCK_LOCKOUT_PLAYER_ONLY)\n\t\treturn false;\n\treturn true;\n}\n\nbool\nCVehicle::CanDoorsBeDamaged(void)\n{\n\treturn m_nDoorLock == CARLOCK_NOT_USED ||\n\t\tm_nDoorLock == CARLOCK_UNLOCKED ||\n\t\tm_nDoorLock == CARLOCK_SKIP_SHUT_DOORS;\n}\n\nbool\nCVehicle::CanPedEnterCar(void)\n{\n\t// can't enter when car is on side\n\tif(IsBike() || GetUp().z > 0.1f ||  GetUp().z < -0.1f){\n\t\t// also when car is moving too fast\n\t\tif(m_vecMoveSpeed.MagnitudeSqr() > sq(0.2f))\n\t\t\treturn false;\n\t\tif(m_vecTurnSpeed.MagnitudeSqr() > sq(0.2f))\n\t\t\treturn false;\n\t\treturn true;\n\t}\n\treturn false;\n}\n\nbool\nCVehicle::CanPedExitCar(bool jumpExit)\n{\n\tCVector up = GetUp();\n\tif(up.z > 0.1f || up.z < -0.1f){\n\t\tif (IsBoat())\n\t\t\treturn true;\n\t\t// can't exit when car is moving too fast\n\t\tif(m_vecMoveSpeed.MagnitudeSqr() > 0.005f && !jumpExit)\n\t\t\treturn false;\n\t\t// if car is slow enough, check turn speed\n\t\tif(Abs(m_vecTurnSpeed.x) > 0.01f ||\n\t\t   Abs(m_vecTurnSpeed.y) > 0.01f ||\n\t\t   Abs(m_vecTurnSpeed.z) > 0.01f)\n\t\t\treturn false;\n\t\treturn true;\n\t}else{\n\t\t// What is this? just > replaced by >= ??\n\n\t\t// can't exit when car is moving too fast\n\t\tif(m_vecMoveSpeed.MagnitudeSqr() >= 0.005f)\n\t\t\treturn false;\n\t\t// if car is slow enough, check turn speed\n\t\tif(Abs(m_vecTurnSpeed.x) >= 0.01f ||\n\t\t   Abs(m_vecTurnSpeed.y) >= 0.01f ||\n\t\t   Abs(m_vecTurnSpeed.z) >= 0.01f)\n\t\t\treturn false;\n\t\treturn true;\n\t}\n}\n\nbool\nCVehicle::CanPedJumpOutCar(void)\n{\n\tif(GetUp().z < 0.3f)\n\t\treturn false;\n\tfloat speed = m_vecMoveSpeed.MagnitudeSqr();\n\treturn speed < 0.1f || speed > 0.5f ? false : true;\n}\n\nbool\nCVehicle::CanPedJumpOffBike(void)\n{\n\tif(pPassengers[0])\n\t\treturn false;\n\treturn m_vecMoveSpeed.MagnitudeSqr() < 0.07f ? false : true;\n}\n\nvoid\nCVehicle::ChangeLawEnforcerState(uint8 enable)\n{\n\tif (enable) {\n\t\tif (!bIsLawEnforcer) {\n\t\t\tbIsLawEnforcer = true;\n\t\t\tCCarCtrl::NumLawEnforcerCars++;\n\t\t}\n\t} else {\n\t\tif (bIsLawEnforcer) {\n\t\t\tbIsLawEnforcer = false;\n\t\t\tCCarCtrl::NumLawEnforcerCars--;\n\t\t}\n\t}\n}\n\nCPed*\nCVehicle::SetUpDriver(void)\n{\n\tif(pDriver)\n\t\treturn pDriver;\n\tif(VehicleCreatedBy != RANDOM_VEHICLE)\n\t\treturn nil;\n\n\tpDriver = CPopulation::AddPedInCar(this, true);\n\tpDriver->m_pMyVehicle = this;\n\tpDriver->m_pMyVehicle->RegisterReference((CEntity**)&pDriver->m_pMyVehicle);\n\tpDriver->bInVehicle = true;\n\tpDriver->SetPedState(PED_DRIVING);\n\tif(bIsBus)\n\t\tpDriver->bRenderPedInCar = false;\n\treturn pDriver;\n}\n\nCPed*\nCVehicle::SetupPassenger(int n)\n{\n\tint i;\n\n\tif(pPassengers[n])\n\t\treturn pPassengers[n];\n\n\tif((IsTaxi() || IsLimo()) && n == 0)\n\t\tpPassengers[0] = nil;\n\telse{\n\t\tCPed *passenger = CPopulation::AddPedInCar(this, false);\n\t\tpPassengers[n] = passenger;\n\t\tpassenger->m_pMyVehicle = this;\n\t\tpassenger->m_pMyVehicle->RegisterReference((CEntity**)&pPassengers[n]->m_pMyVehicle);\n\t\tpassenger->bInVehicle = true;\n\t\tpassenger->SetPedState(PED_DRIVING);\n\n\t\tif(passenger->m_nPedType == PEDTYPE_CIVMALE || passenger->m_nPedType == PEDTYPE_CIVFEMALE)\n\t\t\tfor(i = 0; i < n; i++)\n\t\t\t\tif(pPassengers[i] && pPassengers[n] &&\n\t\t\t\t   (pPassengers[i]->m_nPedType == PEDTYPE_CIVMALE || pPassengers[i]->m_nPedType == PEDTYPE_CIVFEMALE) &&\n\t\t\t\t   passenger->GetModelIndex() == pPassengers[i]->GetModelIndex()){\n\t\t\t\t\tpPassengers[n] = nil;\n\t\t\t\t\tCPopulation::RemovePed(passenger);\n\t\t\t\t}\n\t}\n\tif(bIsBus && pPassengers[n])\n\t\tpPassengers[n]->bRenderPedInCar = false;\n\t++m_nNumPassengers;\n\treturn pPassengers[n];\n}\n\nvoid\nCVehicle::SetDriver(CPed *driver)\n{\n\tpDriver = driver;\n\tpDriver->RegisterReference((CEntity**)&pDriver);\n\n\tif(bFreebies && driver == FindPlayerPed()){\n\t\tbFreebies = false;\n\t\tswitch(GetModelIndex()){\n\t\tcase MI_AMBULAN:\n\t\t\tFindPlayerPed()->m_fHealth = Max(FindPlayerPed()->m_fHealth, Min(FindPlayerPed()->m_fHealth + 20.0f, CWorld::Players[0].m_nMaxHealth));\n\t\t\tbreak;\n\n\t\tcase MI_TAXI:\n\t\tcase MI_CABBIE:\n\t\tcase MI_ZEBRA:\n\t\tcase MI_KAUFMAN:\n\t\t\tCWorld::Players[CWorld::PlayerInFocus].m_nMoney += 12;\n\t\t\tbreak;\n\n\t\tcase MI_POLICE:\n\t\t\tCStreaming::RequestModel(MI_SHOTGUN, STREAMFLAGS_DONT_REMOVE);\n\t\t\tbFreebies = true;\n\t\t\tbreak;\n\n\t\tcase MI_ENFORCER:\n\t\t\tdriver->m_fArmour = Max(driver->m_fArmour, CWorld::Players[0].m_nMaxArmour);\n\t\t\tbreak;\n\n\t\tcase MI_CADDY:\n\t\t\tif(!(driver->IsPlayer() && ((CPlayerPed*)driver)->DoesPlayerWantNewWeapon(WEAPONTYPE_GOLFCLUB, true)))\n\t\t\t\tCStreaming::RequestModel(MI_GOLFCLUB, STREAMFLAGS_DONT_REMOVE);\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tif(IsBike())\n\t\tApplyMoveForce(-0.02f*driver->m_fMass * GetUp());\n\telse\n\t\tApplyTurnForce(0.0f, 0.0f, -0.02f*driver->m_fMass,\n\t\t\tdriver->GetPosition().x - GetPosition().x,\n\t\t\tdriver->GetPosition().y - GetPosition().y,\n\t\t\t0.0f);\n}\n\nbool\nCVehicle::AddPassenger(CPed *passenger)\n{\n\tint i;\n\n\tif(IsBike())\n\t\tApplyTurnForce(-0.02f*passenger->m_fMass * GetUp(), -0.1f*GetForward());\n\telse\n\t\tApplyTurnForce(0.0f, 0.0f, -0.2f*passenger->m_fMass,\n\t\t\tpassenger->GetPosition().x - GetPosition().x,\n\t\t\tpassenger->GetPosition().y - GetPosition().y,\n\t\t\t0.0f);\n\n\tfor(i = 0; i < m_nNumMaxPassengers; i++)\n\t\tif(pPassengers[i] == nil){\n\t\t\tpPassengers[i] = passenger;\n\t\t\tm_nNumPassengers++;\n\t\t\treturn true;\n\t\t}\n\treturn false;\n}\n\nbool\nCVehicle::AddPassenger(CPed *passenger, uint8 n)\n{\n\tif(bIsBus)\n\t\treturn AddPassenger(passenger);\n\n\tif(IsBike())\n\t\tApplyTurnForce(-0.02f*passenger->m_fMass * GetUp(), -0.1f*GetForward());\n\telse\n\t\tApplyTurnForce(0.0f, 0.0f, -0.2f*passenger->m_fMass,\n\t\t\tpassenger->GetPosition().x - GetPosition().x,\n\t\t\tpassenger->GetPosition().y - GetPosition().y,\n\t\t\t0.0f);\n\n\tif(n < m_nNumMaxPassengers && pPassengers[n] == nil){\n\t\tpPassengers[n] = passenger;\n\t\tm_nNumPassengers++;\n\t\treturn true;\n\t}\n\treturn false;\n}\n\nvoid\nCVehicle::RemoveDriver(void)\n{\n#ifdef FIX_BUGS\n\tif (GetStatus() != STATUS_WRECKED)\n#endif\n\t\tSetStatus(STATUS_ABANDONED);\n\tif(pDriver == FindPlayerPed()){\n\t\tif(GetModelIndex() == MI_POLICE && CStreaming::HasModelLoaded(MI_SHOTGUN)){\n\t\t\tif(bFreebies){\n\t\t\t\tif(((CPlayerPed*)pDriver)->DoesPlayerWantNewWeapon(WEAPONTYPE_SHOTGUN, true))\n\t\t\t\t\tpDriver->GiveWeapon(WEAPONTYPE_SHOTGUN, 5, true);\n\t\t\t\telse\n\t\t\t\t\tpDriver->GrantAmmo(WEAPONTYPE_SHOTGUN, 5);\n\t\t\t\tbFreebies = false;\n\t\t\t}\n\t\t\tCStreaming::SetModelIsDeletable(MI_SHOTGUN);\n\t\t}else if(GetModelIndex() == MI_CADDY && CStreaming::HasModelLoaded(MI_GOLFCLUB)){\n\t\t\tif(((CPlayerPed*)pDriver)->DoesPlayerWantNewWeapon(WEAPONTYPE_GOLFCLUB, true))\n\t\t\t\tpDriver->GiveWeapon(WEAPONTYPE_GOLFCLUB, 1, true);\n\t\t\tCStreaming::SetModelIsDeletable(MI_GOLFCLUB);\n\t\t}\n\t}\n\tpDriver = nil;\n}\n\nvoid\nCVehicle::RemovePassenger(CPed *p)\n{\n\tif (IsTrain()){\n\t\tfor (int i = 0; i < ARRAY_SIZE(pPassengers); i++){\n\t\t\tif (pPassengers[i] == p) {\n\t\t\t\tpPassengers[i] = nil;\n\t\t\t\tm_nNumPassengers--;\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\treturn;\n\t}\n\tfor (int i = 0; i < m_nNumMaxPassengers; i++){\n\t\tif (pPassengers[i] == p){\n\t\t\tpPassengers[i] = nil;\n\t\t\tm_nNumPassengers--;\n\t\t\treturn;\n\t\t}\n\t}\n}\n\nbool\nCVehicle::IsDriver(CPed *ped)\n{\n\tif(ped == nil)\n\t\treturn false;\n\treturn ped == pDriver;\n}\n\nbool\nCVehicle::IsDriver(int32 model)\n{\n\treturn pDriver && pDriver->GetModelIndex() == model;\n}\n\nbool\nCVehicle::IsPassenger(CPed *ped)\n{\n\tint i;\n\tif(ped == nil)\n\t\treturn false;\n\tfor(i = 0; i < 8; i++)\n\t\tif(pPassengers[i] == ped)\n\t\t\treturn true;\n\treturn false;\n}\n\nbool\nCVehicle::IsPassenger(int32 model)\n{\n\tint i;\n\tfor(i = 0; i < 8; i++)\n\t\tif(pPassengers[i] && pPassengers[i]->GetModelIndex() == model)\n\t\t\treturn true;\n\treturn false;\n}\n\nvoid\nCVehicle::UpdatePassengerList(void)\n{\n\tint i;\n\tbool hasPassenger = false;\n\tif(m_nNumPassengers)\n\t\tfor(i = 0; i < 8; i++)\n\t\t\tif(pPassengers[i]){\n\t\t\t\thasPassenger = true;\n\t\t\t\tbreak;\n\t\t\t}\n\tif(!hasPassenger)\n\t\tm_nNumPassengers = 0;\n}\n\nvoid\nCVehicle::ProcessCarAlarm(void)\n{\n\tuint32 step;\n\n\tif(!IsAlarmOn())\n\t\treturn;\n\n\tstep = CTimer::GetTimeStepInMilliseconds();\n\tif((uint16)m_nAlarmState < step){\n\t\tm_nAlarmState = 0;\n\t\tm_nCarHornTimer = 0;\n\t}else\n\t\tm_nAlarmState -= step;\n}\n\nbool\nCVehicle::IsSphereTouchingVehicle(float sx, float sy, float sz, float radius)\n{\n\tfloat x, y, z;\n\t// sphere relative to vehicle\n\tCVector sph = CVector(sx, sy, sz) - GetPosition();\n\tCColModel *colmodel = GetColModel();\n\n\tx = DotProduct(sph, GetRight());\n\tif(colmodel->boundingBox.min.x - radius > x ||\n\t   colmodel->boundingBox.max.x + radius < x)\n\t\treturn false;\n\ty = DotProduct(sph, GetForward());\n\tif(colmodel->boundingBox.min.y - radius > y ||\n\t   colmodel->boundingBox.max.y + radius < y)\n\t\treturn false;\n\tz = DotProduct(sph, GetUp());\n\tif(colmodel->boundingBox.min.z - radius > z ||\n\t   colmodel->boundingBox.max.z + radius < z)\n\t\treturn false;\n\n\treturn true;\n}\n\nRpMaterial*\nSetCompAlphaCB(RpMaterial *material, void *data)\n{\n\tuint32 alpha = (uint32)(uintptr)data;\n\tRwRGBA *col = (RwRGBA*)RpMaterialGetColor(material);\t// get rid of const\n\tcol->alpha = alpha;\n\treturn material;\n}\n\nvoid\nCVehicle::SetComponentAtomicAlpha(RpAtomic *atomic, int32 alpha)\n{\n\tRpGeometry *geo = RpAtomicGetGeometry(atomic);\n\tRpGeometrySetFlags(geo, RpGeometryGetFlags(geo) | rpGEOMETRYMODULATEMATERIALCOLOR);\n\tRpGeometryForAllMaterials(geo, SetCompAlphaCB, (void*)alpha);\n}\n\nvoid\nCVehicle::UpdateClumpAlpha(void)\n{\n\tint clumpAlpha = CVisibilityPlugins::GetClumpAlpha((RpClump*)m_rwObject);\n\tif(bFadeOut){\n\t\tclumpAlpha -= 8;\n\t\tif(clumpAlpha < 0)\n\t\t\tclumpAlpha = 0;\n\t}else if(clumpAlpha < 255){\n\t\tclumpAlpha += 16;\n\t\tif(clumpAlpha > 255)\n\t\t\tclumpAlpha = 255;\n\t}\n\tCVisibilityPlugins::SetClumpAlpha((RpClump*)m_rwObject, clumpAlpha);\n}\n\nvoid\nCVehicle::HeliDustGenerate(CEntity *heli, float radius, float ground, int rnd)\n{\n\tint i;\n\tfloat angle;\n\tCColPoint point;\n\tCEntity *entity;\n\tuint8 r, g, b;\n\n\tif(heli == nil)\n\t\treturn;\n\n\tuint8 surface = SURFACE_TARMAC;\n\tint frm = CTimer::GetFrameCounter() & 7;\n\tfloat testLowZ = ground - 10.0f;\n\tfloat dustSize = 0.0f;\n\tfloat baseSize = 1.0f;\n\tfloat offset = 1.0f;\t// when heli is tilted\n\tfloat particleZ = -101.0f;\n\tint n = 0;\n\n\tif(heli->GetModelIndex() == MI_RCGOBLIN || heli->GetModelIndex() == MI_RCRAIDER){\n\t\tradius = 3.0f;\n\t\tdustSize = 0.04f;\n\t\tbaseSize = 0.07f;\n\t\toffset = 0.3f;\n\t}\n\n\tCVector heliPos = heli->GetPosition();\n\n\tif(heli->IsVehicle() && ((CVehicle*)heli)->IsCar()){\n\t\theliPos.x -= (heliPos.z - ground)*heli->GetUp().x*offset*0.5f;\n\t\theliPos.y -= (heliPos.z - ground)*heli->GetUp().y*offset*0.5f;\n\t}\n\n\tfloat steamSize = 0.25f * radius * baseSize;\n\tfloat splashSize = 0.3f * radius * baseSize;\n\n\ti = 0;\n\tfor(i = 0; i < 32+rnd; i++){\n\t\tangle = i * TWOPI/32.0f;\n\t\tCVector pos(radius*Cos(angle), radius*Sin(angle), 0.0f);\n\t\tCVector dir = CVector(pos.x, pos.y, 1.0f)*0.01f;\n\t\tpos += heliPos;\n\n\t\tif(i < 32 && i == 4*frm){\n\t\t\tif(CWorld::ProcessVerticalLine(pos, testLowZ, point, entity, true, false, false, false, true, false, nil)){\n\t\t\t\tn = rnd;\n\t\t\t\tparticleZ = point.point.z;\n\t\t\t\tsurface = point.surfaceB;\n\t\t\t}else\n\t\t\t\tn = 0;\n\n\t\t\tfloat waterLevel = 0.0f;\n\t\t\tif(CWaterLevel::GetWaterLevel(pos, &waterLevel, false) && waterLevel > particleZ){\n\t\t\t\tsurface = SURFACE_WATER;\n\t\t\t\tn = rnd;\n\t\t\t\tparticleZ = waterLevel;\n\t\t\t}\n\t\t}\n\n\t\tif(n){\n\t\t\tpos.z = particleZ;\n\t\t\tif(surface == SURFACE_WATER){\n\t\t\t\tfloat red = (0.3*CTimeCycle::GetDirectionalRed() + CTimeCycle::GetAmbientRed_Obj())*255.0f/4.0f;\n\t\t\t\tfloat green = (0.3*CTimeCycle::GetDirectionalGreen() + CTimeCycle::GetAmbientGreen_Obj())*255.0f/4.0f;\n\t\t\t\tfloat blue = (0.3*CTimeCycle::GetDirectionalBlue() + CTimeCycle::GetAmbientBlue_Obj())*255.0f/4.0f;\n\t\t\t\tr = clamp(red, 0.0f, 255.0f);\n\t\t\t\tg = clamp(green, 0.0f, 255.0f);\n\t\t\t\tb = clamp(blue, 0.0f, 255.0f);\n\t\t\t\tRwRGBA col1 = { r, g, b, (RwUInt8)CGeneral::GetRandomNumberInRange(8, 32) };\n\t\t\t\tRwRGBA col2 = { 255, 255, 255, 32 };\n\n\t\t\t\tif(n&1)\n\t\t\t\t\tCParticle::AddParticle(PARTICLE_STEAM_NY_SLOWMOTION, pos, dir, nil, steamSize, col2);\n\t\t\t\telse\n\t\t\t\t\tCParticle::AddParticle(PARTICLE_CAR_SPLASH, pos, dir, nil, splashSize, col1,\n\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(0.0f, 10.0f),\n\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(0.0f, 90.0f), 1);\n\t\t\t}else{\n\t\t\t\tswitch(surface){\n\t\t\t\tdefault:\n\t\t\t\tcase SURFACE_TARMAC:\n\t\t\t\t\tr = 10;\n\t\t\t\t\tg = 10;\n\t\t\t\t\tb = 10;\n\t\t\t\t\tbreak;\n\t\t\t\tcase SURFACE_GRASS:\n\t\t\t\t\tr = 10;\n\t\t\t\t\tg = 10;\n\t\t\t\t\tb = 3;\n\t\t\t\t\tbreak;\n\t\t\t\tcase SURFACE_GRAVEL:\n\t\t\t\t\tr = 10;\n\t\t\t\t\tg = 8;\n\t\t\t\t\tb = 7;\n\t\t\t\t\tbreak;\n\t\t\t\tcase SURFACE_MUD_DRY:\n\t\t\t\t\tr = 10;\n\t\t\t\t\tg = 6;\n\t\t\t\t\tb = 3;\n\t\t\t\t\tbreak;\n\t\t\t\tcase SURFACE_SAND:\n\t\t\t\tcase SURFACE_SAND_BEACH:\n\t\t\t\t\tr = 10;\n\t\t\t\t\tg = 10;\n\t\t\t\t\tb = 7;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tRwRGBA col = { r, g, b, 32 };\n\t\t\t\tif(heliPos.z - pos.z < 20.0f)\n\t\t\t\t\tCParticle::AddParticle(PARTICLE_HELI_DUST, pos, dir, nil, dustSize, col);\n\t\t\t}\n\n\t\t\tn--;\n\t\t}\n\t}\n}\n\n#define GLARE_MIN_DIST (13.0f)\n#define GLARE_FULL_DIST (30.0f)\n#define GLARE_MIN_ANGLE (0.99f)\n#define GLARE_FULL_ANGLE (0.995f)\n\nvoid\nCVehicle::DoSunGlare(void)\n{\n\tif(bRenderScorched || GetPosition().z < 0.0f ||\n\t   GetVehicleAppearance() != VEHICLE_APPEARANCE_CAR || CWeather::SunGlare <= 0.0f)\n\t\treturn;\n\n\tCVector camDir = TheCamera.GetPosition() - GetPosition();\n\tfloat dist = camDir.Magnitude();\n\tcamDir *= 2.0f/dist;\n\tCVector glareVec = camDir + CTimeCycle::GetSunDirection();\n\tCVector localGlareVec;\n\tlocalGlareVec.x = DotProduct(glareVec, GetRight());\n\tlocalGlareVec.y = DotProduct(glareVec, GetForward());\n\tlocalGlareVec.z = 0.0;\n\tlocalGlareVec.Normalise();\n\n\tCVector2D fwd2D = GetForward();\n\tfwd2D.Normalise();\n\tCVector2D camDir2D = camDir;\n\tcamDir2D.Normalise();\n\tfloat fwdness = Abs(DotProduct2D(fwd2D, camDir2D));\n\n\t// check angle\n\tfloat strength;\n\tif(fwdness > GLARE_FULL_ANGLE)\n\t\tstrength = 1.0f;\n\telse if(fwdness > GLARE_MIN_ANGLE)\n\t\tstrength = (fwdness - GLARE_MIN_ANGLE)/(GLARE_FULL_ANGLE-GLARE_MIN_ANGLE);\n\telse\n\t\treturn;\n\t// check distance\n\tif(dist > GLARE_FULL_DIST){\n\t\t// no max distance\n\t}else if(dist > GLARE_MIN_DIST)\n\t\tstrength *= (dist - GLARE_MIN_DIST)/(GLARE_FULL_DIST - GLARE_MIN_DIST);\n\telse\n\t\treturn;\n\n\tfloat intens = 0.8f * strength * CWeather::SunGlare;\n\tint r = intens * (CTimeCycle::GetSunCoreRed() + 2*255)/3.0f;\n\tint g = intens * (CTimeCycle::GetSunCoreGreen() + 2*255)/3.0f;\n\tint b = intens * (CTimeCycle::GetSunCoreBlue() + 2*255)/3.0f;\n\n\tCColModel *colmodel = GetColModel();\n\tCCollision::CalculateTrianglePlanes(colmodel);\n\n\tint i;\n\tfor(i = 0; i < colmodel->numTriangles-2; i += 2){\n\t\tint a1 = colmodel->triangles[i].a;\n\t\tint b1 = colmodel->triangles[i].b;\n\t\tint c1 = colmodel->triangles[i].c;\n\t\tint a2 = colmodel->triangles[i+1].a;\n\t\tint b2 = colmodel->triangles[i+1].b;\n\t\tint c2 = colmodel->triangles[i+1].c;\n\t\tCVector vert1 = colmodel->vertices[a1].Get();\n\t\tCVector vert4;\n\t\t// Need an upward surface\n\t\tif(vert1.z <= 0.0f)\n\t\t\tcontinue;\n\n\t\t// trying to find a quad here\n\t\tint numTri2Verts = 0;\n\t\tif(a2 != a1 && a2 != b1 && a2 != c1){\n\t\t\t// a2 is not in tri1\n\t\t\tnumTri2Verts++;\n\t\t\tvert4 = colmodel->vertices[a2].Get();\n\t\t}\n\t\tif(b2 != a1 && b2 != b1 && b2 != c1){\n\t\t\t// b2 is not in tri1\n\t\t\tnumTri2Verts++;\n\t\t\tvert4 = colmodel->vertices[b2].Get();\n\t\t}\n\t\tif(c2 != a1 && c2 != b1 && c2 != c1){\n\t\t\t// c2 is not in tri1\n\t\t\tnumTri2Verts++;\n\t\t\tvert4 = colmodel->vertices[c2].Get();\n\t\t}\n\t\t// Need exactly one vertex from tri2 for a quad with tri1\n\t\tif(numTri2Verts != 1)\n\t\t\tcontinue;\n\n\t\tCVector mid = (vert1 + colmodel->vertices[b1].Get() + colmodel->vertices[c1].Get() + vert4)/4.0f;\n\t\tfloat dy = mid.y - vert1.y;\n\t\tfloat dx = mid.x - vert1.x;\n\t\tfloat dist = 1.4f * Min(Abs(dx), Abs(dy));\n\t\tif(dist > 0.6f){\n\t\t\tCVector pos = GetMatrix() * (dist * localGlareVec + mid) + camDir;\n\t\t\tCCoronas::RegisterCorona((uintptr)this + 27 + i,\n\t\t\t\tr, g, b, 255,\n\t\t\t\tpos, 0.9f*CWeather::SunGlare, 90.0f,\n\t\t\t\tCCoronas::TYPE_STAR, CCoronas::FLARE_NONE,\n\t\t\t\tCCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF,\n\t\t\t\tCCoronas::STREAK_OFF, 0.0f);\n\t\t}\n\t}\n}\n\nvoid\nCVehicle::KillPedsInVehicle(void)\n{\n\tint i;\n\tif(pDriver){\n\t\tCDarkel::RegisterKillByPlayer(pDriver, WEAPONTYPE_EXPLOSION);\n\t\tif(pDriver->GetPedState() == PED_DRIVING){\n\t\t\tpDriver->SetDead();\n\t\t\tif(!pDriver->IsPlayer())\n\t\t\t\tpDriver->FlagToDestroyWhenNextProcessed();\n\t\t}else\n\t\t\tpDriver->SetDie();\n\t}\n\tfor(i = 0; i < m_nNumMaxPassengers; i++){\n\t\tif(pPassengers[i]){\n\t\t\tCDarkel::RegisterKillByPlayer(pPassengers[i], WEAPONTYPE_EXPLOSION);\n\t\t\tif(pPassengers[i]->GetPedState() == PED_DRIVING){\n\t\t\t\tpPassengers[i]->SetDead();\n\t\t\t\tif(!pPassengers[i]->IsPlayer())\n\t\t\t\t\tpPassengers[i]->FlagToDestroyWhenNextProcessed();\n\t\t\t}else\n\t\t\t\tpPassengers[i]->SetDie();\n\t\t}\n\t}\n}\n\nvoid\nDestroyVehicleAndDriverAndPassengers(CVehicle* pVehicle)\n{\n\tif (pVehicle->pDriver) {\n\t\tCDarkel::RegisterKillByPlayer(pVehicle->pDriver, WEAPONTYPE_UNIDENTIFIED);\n\t\tpVehicle->pDriver->FlagToDestroyWhenNextProcessed();\n\t}\n\tfor (int i = 0; i < pVehicle->m_nNumMaxPassengers; i++) {\n\t\tif (pVehicle->pPassengers[i]) {\n\t\t\tCDarkel::RegisterKillByPlayer(pVehicle->pPassengers[i], WEAPONTYPE_UNIDENTIFIED);\n\t\t\tpVehicle->pPassengers[i]->FlagToDestroyWhenNextProcessed();\n\t\t}\n\t}\n\tCWorld::Remove(pVehicle);\n\tdelete pVehicle;\n}\n\n#ifdef COMPATIBLE_SAVES\nvoid\nCVehicle::Save(uint8*& buf)\n{\n\tSkipSaveBuf(buf, 4);\n\tWriteSaveBuf<float>(buf, GetRight().x);\n\tWriteSaveBuf<float>(buf, GetRight().y);\n\tWriteSaveBuf<float>(buf, GetRight().z);\n\tSkipSaveBuf(buf, 4);\n\tWriteSaveBuf<float>(buf, GetForward().x);\n\tWriteSaveBuf<float>(buf, GetForward().y);\n\tWriteSaveBuf<float>(buf, GetForward().z);\n\tSkipSaveBuf(buf, 4);\n\tWriteSaveBuf<float>(buf, GetUp().x);\n\tWriteSaveBuf<float>(buf, GetUp().y);\n\tWriteSaveBuf<float>(buf, GetUp().z);\n\tSkipSaveBuf(buf, 4);\n\tWriteSaveBuf<float>(buf, GetPosition().x);\n\tWriteSaveBuf<float>(buf, GetPosition().y);\n\tWriteSaveBuf<float>(buf, GetPosition().z);\n\tSkipSaveBuf(buf, 16);\n\tSaveEntityFlags(buf);\n\tSkipSaveBuf(buf, 208);\n\tAutoPilot.Save(buf);\n\tWriteSaveBuf<int8>(buf, m_currentColour1);\n\tWriteSaveBuf<int8>(buf, m_currentColour2);\n\tSkipSaveBuf(buf, 2);\n\tWriteSaveBuf<int16>(buf, m_nAlarmState);\n\tSkipSaveBuf(buf, 42);\n\tWriteSaveBuf<uint8>(buf, m_nNumMaxPassengers);\n\tSkipSaveBuf(buf, 3);\n\tWriteSaveBuf<float>(buf, field_1D0[0]);\n\tWriteSaveBuf<float>(buf, field_1D0[1]);\n\tWriteSaveBuf<float>(buf, field_1D0[2]);\n\tWriteSaveBuf<float>(buf, field_1D0[3]);\n\tSkipSaveBuf(buf, 8);\n\tWriteSaveBuf<float>(buf, m_fSteerAngle);\n\tWriteSaveBuf<float>(buf, m_fGasPedal);\n\tWriteSaveBuf<float>(buf, m_fBrakePedal);\n\tWriteSaveBuf<uint8>(buf, VehicleCreatedBy);\n\tuint8 flags = 0;\n\tif (bIsLawEnforcer) flags |= BIT(0);\n\tif (bIsLocked) flags |= BIT(3);\n\tif (bEngineOn) flags |= BIT(4);\n\tif (bIsHandbrakeOn) flags |= BIT(5);\n\tif (bLightsOn) flags |= BIT(6);\n\tif (bFreebies) flags |= BIT(7);\n\tWriteSaveBuf<uint8>(buf, flags);\n\tSkipSaveBuf(buf, 10);\n\tWriteSaveBuf<float>(buf, m_fHealth);\n\tWriteSaveBuf<uint8>(buf, m_nCurrentGear);\n\tSkipSaveBuf(buf, 3);\n\tWriteSaveBuf<float>(buf, m_fChangeGearTime);\n\tSkipSaveBuf(buf, 12);\n\tWriteSaveBuf<uint32>(buf, m_nTimeOfDeath);\n\tSkipSaveBuf(buf, 2);\n\tWriteSaveBuf<int16>(buf, m_nBombTimer);\n\tSkipSaveBuf(buf, 12);\n\tWriteSaveBuf<int8>(buf, m_nDoorLock);\n\tSkipSaveBuf(buf, 111);\n}\n\nvoid\nCVehicle::Load(uint8*& buf)\n{\n\tCMatrix tmp;\n\tSkipSaveBuf(buf, 4);\n\ttmp.GetRight().x = ReadSaveBuf<float>(buf);\n\ttmp.GetRight().y = ReadSaveBuf<float>(buf);\n\ttmp.GetRight().z = ReadSaveBuf<float>(buf);\n\tSkipSaveBuf(buf, 4);\n\ttmp.GetForward().x = ReadSaveBuf<float>(buf);\n\ttmp.GetForward().y = ReadSaveBuf<float>(buf);\n\ttmp.GetForward().z = ReadSaveBuf<float>(buf);\n\tSkipSaveBuf(buf, 4);\n\ttmp.GetUp().x = ReadSaveBuf<float>(buf);\n\ttmp.GetUp().y = ReadSaveBuf<float>(buf);\n\ttmp.GetUp().z = ReadSaveBuf<float>(buf);\n\tSkipSaveBuf(buf, 4);\n\ttmp.GetPosition().x = ReadSaveBuf<float>(buf);\n\ttmp.GetPosition().y = ReadSaveBuf<float>(buf);\n\ttmp.GetPosition().z = ReadSaveBuf<float>(buf);\n\tm_matrix = tmp;\n\tSkipSaveBuf(buf, 16);\n\tLoadEntityFlags(buf);\n\tSkipSaveBuf(buf, 208);\n\tAutoPilot.Load(buf);\n\tm_currentColour1 = ReadSaveBuf<int8>(buf);\n\tm_currentColour2 = ReadSaveBuf<int8>(buf);\n\tSkipSaveBuf(buf, 2);\n\tm_nAlarmState = ReadSaveBuf<int16>(buf);\n\tSkipSaveBuf(buf, 42);\n\tm_nNumMaxPassengers = ReadSaveBuf<int8>(buf);\n\tSkipSaveBuf(buf, 3);\n\tfield_1D0[0] = ReadSaveBuf<float>(buf);\n\tfield_1D0[1] = ReadSaveBuf<float>(buf);\n\tfield_1D0[2] = ReadSaveBuf<float>(buf);\n\tfield_1D0[3] = ReadSaveBuf<float>(buf);\n\tSkipSaveBuf(buf, 8);\n\tm_fSteerAngle = ReadSaveBuf<float>(buf);\n\tm_fGasPedal = ReadSaveBuf<float>(buf);\n\tm_fBrakePedal = ReadSaveBuf<float>(buf);\n\tVehicleCreatedBy = ReadSaveBuf<uint8>(buf);\n\tuint8 flags = ReadSaveBuf<uint8>(buf);\n\tbIsLawEnforcer = !!(flags & BIT(0));\n\tbIsLocked = !!(flags & BIT(3));\n\tbEngineOn = !!(flags & BIT(4));\n\tbIsHandbrakeOn = !!(flags & BIT(5));\n\tbLightsOn = !!(flags & BIT(6));\n\tbFreebies = !!(flags & BIT(7));\n\tSkipSaveBuf(buf, 10);\n\tm_fHealth = ReadSaveBuf<float>(buf);\n\tm_nCurrentGear = ReadSaveBuf<uint8>(buf);\n\tSkipSaveBuf(buf, 3);\n\tm_fChangeGearTime = ReadSaveBuf<float>(buf);\n\tSkipSaveBuf(buf, 12);\n\tm_nTimeOfDeath = ReadSaveBuf<uint32>(buf);\n\tSkipSaveBuf(buf, 2);\n\tm_nBombTimer = ReadSaveBuf<int16>(buf);\n\tSkipSaveBuf(buf, 12);\n\tm_nDoorLock = (eCarLock)ReadSaveBuf<int8>(buf);\n\tSkipSaveBuf(buf, 111);\n}\n#endif\n\neVehicleAppearance\nCVehicle::GetVehicleAppearance(void)\n{\n\tuint32 flags = pHandling->Flags & 0xF0000;\n\tif (flags == 0)\n\t\treturn VEHICLE_APPEARANCE_CAR;\n\tif (flags == HANDLING_IS_BIKE)\n\t\treturn VEHICLE_APPEARANCE_BIKE;\n\tif (flags == HANDLING_IS_HELI)\n\t\treturn VEHICLE_APPEARANCE_HELI;\n\tif (flags == HANDLING_IS_PLANE)\n\t\treturn VEHICLE_APPEARANCE_PLANE;\n\tif (flags == HANDLING_IS_BOAT)\n\t\treturn VEHICLE_APPEARANCE_BOAT;\n\treturn VEHICLE_APPEARANCE_NONE;\n}\n\nbool\nIsVehiclePointerValid(CVehicle* pVehicle)\n{\n\tif (!pVehicle)\n\t\treturn false;\n\tint index = CPools::GetVehiclePool()->GetJustIndex_NoFreeAssert(pVehicle);\n#ifdef FIX_BUGS\n\tif (index < 0 || index >= NUMVEHICLES)\n#else\n\tif (index < 0 || index > NUMVEHICLES)\n#endif\n\t\treturn false;\n\treturn pVehicle->m_vehType == VEHICLE_TYPE_PLANE || pVehicle->m_entryInfoList.first;\n}\n"
  },
  {
    "path": "src/vehicles/Vehicle.h",
    "content": "#pragma once\n\n#include \"Physical.h\"\n#include \"AutoPilot.h\"\n#include \"ModelIndices.h\"\n#include \"AnimationId.h\"\n#include \"WeaponType.h\"\n#include \"Collision.h\"\n#include \"HandlingMgr.h\"\n\nclass CPed;\nclass CPlayerPed;\nclass CCopPed;\nclass CFire;\n\nenum {\n\tRANDOM_VEHICLE = 1,\n\tMISSION_VEHICLE = 2,\n\tPARKED_VEHICLE = 3,\n\tPERMANENT_VEHICLE = 4,\n};\n\nenum eCarNodes\n{\n\tCAR_WHEEL_RF = 1,\n\tCAR_WHEEL_RM,\n\tCAR_WHEEL_RB,\n\tCAR_WHEEL_LF,\n\tCAR_WHEEL_LM,\n\tCAR_WHEEL_LB,\n\tCAR_BUMP_FRONT,\n\tCAR_BUMP_REAR,\n\tCAR_WING_RF,\n\tCAR_WING_RR,\n\tCAR_DOOR_RF,\n\tCAR_DOOR_RR,\n\tCAR_WING_LF,\n\tCAR_WING_LR,\n\tCAR_DOOR_LF,\n\tCAR_DOOR_LR,\n\tCAR_BONNET,\n\tCAR_BOOT,\n\tCAR_WINDSCREEN,\n\tNUM_CAR_NODES,\n};\n\nenum {\n\tCAR_DOOR_FLAG_UNKNOWN = 0x0,\n\tCAR_DOOR_FLAG_LF = 0x1,\n\tCAR_DOOR_FLAG_LR = 0x2,\n\tCAR_DOOR_FLAG_RF = 0x4,\n\tCAR_DOOR_FLAG_RR = 0x8\n};\n\nenum eCarLock {\n\tCARLOCK_NOT_USED,\n\tCARLOCK_UNLOCKED,\n\tCARLOCK_LOCKED,\n\tCARLOCK_LOCKOUT_PLAYER_ONLY,\n\tCARLOCK_LOCKED_PLAYER_INSIDE,\n\tCARLOCK_LOCKED_INITIALLY,\n\tCARLOCK_FORCE_SHUT_DOORS,\n\tCARLOCK_SKIP_SHUT_DOORS\n};\n\nenum eBombType\n{\n\tCARBOMB_NONE,\n\tCARBOMB_TIMED,\n\tCARBOMB_ONIGNITION,\n\tCARBOMB_REMOTE,\n\tCARBOMB_TIMEDACTIVE,\n\tCARBOMB_ONIGNITIONACTIVE,\n};\n\nenum eDoors\n{\n\tDOOR_BONNET = 0,\n\tDOOR_BOOT,\n\tDOOR_FRONT_LEFT,\n\tDOOR_FRONT_RIGHT,\n\tDOOR_REAR_LEFT,\n\tDOOR_REAR_RIGHT\n};\n\nenum ePanels\n{\n\tVEHPANEL_FRONT_LEFT,\n\tVEHPANEL_FRONT_RIGHT,\n\tVEHPANEL_REAR_LEFT,\n\tVEHPANEL_REAR_RIGHT,\n\tVEHPANEL_WINDSCREEN,\n\tVEHBUMPER_FRONT,\n\tVEHBUMPER_REAR,\n};\n\nenum eLights\n{\n\tVEHLIGHT_FRONT_LEFT,\n\tVEHLIGHT_FRONT_RIGHT,\n\tVEHLIGHT_REAR_LEFT,\n\tVEHLIGHT_REAR_RIGHT,\n};\n\nenum\n{\n\tCAR_PIECE_BONNET = 1,\n\tCAR_PIECE_BOOT,\n\tCAR_PIECE_BUMP_FRONT,\n\tCAR_PIECE_BUMP_REAR,\n\tCAR_PIECE_DOOR_LF,\n\tCAR_PIECE_DOOR_RF,\n\tCAR_PIECE_DOOR_LR,\n\tCAR_PIECE_DOOR_RR,\n\tCAR_PIECE_WING_LF,\n\tCAR_PIECE_WING_RF,\n\tCAR_PIECE_WING_LR,\n\tCAR_PIECE_WING_RR,\n\tCAR_PIECE_WHEEL_LF,\n\tCAR_PIECE_WHEEL_RF,\n\tCAR_PIECE_WHEEL_LR,\n\tCAR_PIECE_WHEEL_RR,\n\tCAR_PIECE_WINDSCREEN,\n};\n\nenum tWheelState\n{\n\tWHEEL_STATE_NORMAL,\t// standing still or rolling normally\n\tWHEEL_STATE_SPINNING,\t// rotating but not moving\n\tWHEEL_STATE_SKIDDING,\n\tWHEEL_STATE_FIXED,\t// not rotating\n};\n\nenum eFlightModel\n{\n\tFLIGHT_MODEL_DODO,\n\tFLIGHT_MODEL_RCPLANE,\n\tFLIGHT_MODEL_RCHELI,\n\tFLIGHT_MODEL_SEAPLANE,\n\tFLIGHT_MODEL_PLANE_UNUSED,\n\tFLIGHT_MODEL_PLANE,\n\tFLIGHT_MODEL_HELI\n};\n\nenum eVehicleAppearance\n{\n\tVEHICLE_APPEARANCE_NONE,\n\tVEHICLE_APPEARANCE_CAR,\n\tVEHICLE_APPEARANCE_BIKE,\n\tVEHICLE_APPEARANCE_HELI,\n\tVEHICLE_APPEARANCE_BOAT,\n\tVEHICLE_APPEARANCE_PLANE,\n};\n\n// TODO: what is this even?\nenum eBikeWheelSpecial\n{\n\tBIKE_WHEELSPEC_0,\t// both wheels on ground\n\tBIKE_WHEELSPEC_1,\t// rear wheel on ground\n\tBIKE_WHEELSPEC_2,\t// only front wheel on ground\n\tBIKE_WHEELSPEC_3,\t// can't happen\n};\n\nenum\n{\n\tROTOR_TOP = 3,\n\tROTOR_FRONT = 4,\n\tROTOR_RIGHT = 5,\n\tROTOR_LEFT = 7,\n\tROTOR_BACK = 8,\n\tROTOR_BOTTOM = 9,\n};\n\nclass CVehicle : public CPhysical\n{\npublic:\n\ttHandlingData *pHandling;\n\ttFlyingHandlingData *pFlyingHandling;\n\tCAutoPilot AutoPilot;\n\tuint8 m_currentColour1;\n\tuint8 m_currentColour2;\n\tint8 m_aExtras[2];\n\tint16 m_nAlarmState;\n\tint16 m_nRouteSeed;\n\tCPed *pDriver;\n\tCPed *pPassengers[8];\n\tuint8 m_nNumPassengers;\n\tint8 m_nNumGettingIn;\n\tint8 m_nGettingInFlags;\n\tint8 m_nGettingOutFlags;\n\tuint8 m_nNumMaxPassengers;\n\tfloat field_1D0[4];\n\tCEntity *m_pCurGroundEntity;\n\tCFire *m_pCarFire;\n\tfloat m_fSteerAngle;\n\tfloat m_fGasPedal;\n\tfloat m_fBrakePedal;\n\tuint8 VehicleCreatedBy;\n\n\t// cf. https://github.com/DK22Pac/plugin-sdk/blob/master/plugin_sa/game_sa/CVehicle.h from R*\n\tuint8 bIsLawEnforcer: 1; // Is this guy chasing the player at the moment\n\tuint8 bIsAmbulanceOnDuty: 1; // Ambulance trying to get to an accident\n\tuint8 bIsFireTruckOnDuty: 1; // Firetruck trying to get to a fire\n\tuint8 bIsLocked: 1; // Is this guy locked by the script (cannot be removed)\n\tuint8 bEngineOn: 1; // For sound purposes. Parked cars have their engines switched off (so do destroyed cars)\n\tuint8 bIsHandbrakeOn: 1; // How's the handbrake doing ?\n\tuint8 bLightsOn: 1; // Are the lights switched on ?\n\tuint8 bFreebies: 1; // Any freebies left in this vehicle ?\n\n\tuint8 bIsVan: 1; // Is this vehicle a van (doors at back of vehicle)\n\tuint8 bIsBus: 1; // Is this vehicle a bus\n\tuint8 bIsBig: 1; // Is this vehicle a bus\n\tuint8 bLowVehicle: 1; // Need this for sporty type cars to use low getting-in/out anims\n\tuint8 bComedyControls : 1; // Will make the car hard to control (hopefully in a funny way)\n\tuint8 bWarnedPeds : 1; // Has scan and warn peds of danger been processed?\n\tuint8 bCraneMessageDone : 1; // A crane message has been printed for this car allready\n\tuint8 bExtendedRange : 1; // This vehicle needs to be a bit further away to get deleted\n\n\tuint8 bTakeLessDamage : 1; // This vehicle is stronger (takes about 1/4 of damage)\n\tuint8 bIsDamaged : 1; // This vehicle has been damaged and is displaying all its components\n\tuint8 bHasBeenOwnedByPlayer : 1;// To work out whether stealing it is a crime\n\tuint8 bFadeOut : 1; // Fade vehicle out\n\tuint8 bIsBeingCarJacked : 1; // Fade vehicle out\n\tuint8 bCreateRoadBlockPeds : 1; // If this vehicle gets close enough we will create peds (coppers or gang members) round it\n\tuint8 bCanBeDamaged : 1; // Set to FALSE during cut scenes to avoid explosions\n\tuint8 bUsingSpecialColModel : 1;// Is player vehicle using special collision model, stored in player strucure\n\n\tuint8 bOccupantsHaveBeenGenerated : 1;  // Is true if the occupants have already been generated. (Shouldn't happen again)\n\tuint8 bGunSwitchedOff : 1;  // Level designers can use this to switch off guns on boats\n\tuint8 bVehicleColProcessed : 1;// Has ProcessEntityCollision been processed for this car?\n\tuint8 bIsCarParkVehicle : 1; // Car has been created using the special CAR_PARK script command\n\tuint8 bHasAlreadyBeenRecorded : 1; // Used for replays\n\tuint8 bPartOfConvoy : 1;\n\tuint8 bHeliMinimumTilt : 1; // This heli should have almost no tilt really\n\tuint8 bAudioChangingGear : 1; // sounds like vehicle is changing gear\n\n\tuint8 bIsDrowning : 1; // is vehicle occupants taking damage in water (i.e. vehicle is dead in water)\n\tuint8 bTyresDontBurst : 1; // If this is set the tyres are invincible\n\tuint8 bCreatedAsPoliceVehicle : 1;// True if this guy was created as a police vehicle (enforcer, policecar, miamivice car etc)\n\tuint8 bRestingOnPhysical : 1; // Dont go static cause car is sitting on a physical object that might get removed\n\tuint8 bParking : 1;\n\tuint8 bCanPark : 1;\n#if (!defined GTA_PS2 || defined FIX_BUGS)\n\tuint8 m_bombType : 3;\n#endif\n\tuint8 bDriverLastFrame : 1;\n\n\tint8 m_numPedsUseItAsCover;\n\tuint8 m_nAmmoInClip;    // Used to make the guns on boat do a reload (20 by default)\n\tint8 m_nPacManPickupsCarried;\n\tuint8 m_nRoadblockType;\n\tfloat m_fHealth;           // 1000.0f = full health. 250.0f = fire. 0 -> explode\n\tuint8 m_nCurrentGear;\n\tfloat m_fChangeGearTime;\n#if (!defined GTA_PS2 || defined FIX_BUGS)\n\tCEntity* m_pBombRigger;\n#endif\n\tuint32 m_nSetPieceExtendedRangeTime;\n\tuint32 m_nGunFiringTime;    // last time when gun on vehicle was fired (used on boats)\n\tuint32 m_nTimeOfDeath;\n\tuint16 m_nTimeBlocked;\n\tint16 m_nBombTimer;        // goes down with each frame\n\tCEntity *m_pBlowUpEntity;\n\tfloat m_fMapObjectHeightAhead;\t// front Z?\n\tfloat m_fMapObjectHeightBehind;\t// rear Z?\n\teCarLock m_nDoorLock;\n\tint8 m_nLastWeaponDamage; // see eWeaponType, -1 if no damage\n\tCEntity *m_pLastDamageEntity;\n\tuint8 m_nRadioStation;\n\tuint8 m_bRainAudioCounter;\n\tuint8 m_bRainSamplesCounter;\n\tuint32 m_nCarHornTimer;\n\tuint8 m_nCarHornPattern;\n\tbool m_bSirenOrAlarm;\n\tuint8 m_nCarHornDelay;\n\tint8 m_comedyControlState;\n\tCStoredCollPoly m_aCollPolys[2];     // poly which is under front/rear part of car\n\tfloat m_fSteerInput;\n\tuint8 m_vehType;\n\n\tstatic void *operator new(size_t);\n\tstatic void *operator new(size_t sz, int slot);\n\tstatic void operator delete(void*, size_t);\n\tstatic void operator delete(void*, int);\n\n\tCVehicle(void) {}\t// FAKE\n\tCVehicle(uint8 CreatedBy);\n\t~CVehicle(void);\n\t// from CEntity\n\tvoid SetModelIndex(uint32 id);\n\tbool SetupLighting(void);\n\tvoid RemoveLighting(bool);\n\tvoid FlagToDestroyWhenNextProcessed(void) {}\n\n\tvirtual void ProcessControlInputs(uint8) {}\n\tvirtual void GetComponentWorldPosition(int32 component, CVector &pos) {}\n\tvirtual bool IsComponentPresent(int32 component) { return false; }\n\tvirtual void SetComponentRotation(int32 component, CVector rotation) {}\n\tvirtual void OpenDoor(int32, eDoors door, float) {}\n\tvirtual void ProcessOpenDoor(uint32, uint32, float) {}\n\tvirtual bool IsDoorReady(eDoors door) { return false; }\n\tvirtual bool IsDoorFullyOpen(eDoors door) { return false; }\n\tvirtual bool IsDoorClosed(eDoors door) { return false; }\n\tvirtual bool IsDoorMissing(eDoors door) { return false; }\n\tvirtual bool IsDoorReady(uint32 door) { return false; }\n\tvirtual bool IsDoorMissing(uint32 door) { return false; }\n\tvirtual bool IsOpenTopCar(void) { return false; }\n\tvirtual void RemoveRefsToVehicle(CEntity *ent) {}\n\tvirtual void BlowUpCar(CEntity *ent) {}\n\tvirtual bool SetUpWheelColModel(CColModel *colModel) { return false; }\n\tvirtual void BurstTyre(uint8 tyre, bool applyForces) {}\n\tvirtual bool IsRoomForPedToLeaveCar(uint32 component, CVector *forcedDoorPos) { return false; }\n\tvirtual bool IsClearToDriveAway(void);\n\tvirtual float GetHeightAboveRoad(void);\n\tvirtual void PlayCarHorn(void) {}\n#ifdef COMPATIBLE_SAVES\n\tvirtual void Save(uint8*& buf);\n\tvirtual void Load(uint8*& buf);\n#endif\n\n\teVehicleAppearance GetVehicleAppearance(void);\n\tbool IsCar(void) { return m_vehType == VEHICLE_TYPE_CAR; }\n\tbool IsBoat(void) { return m_vehType == VEHICLE_TYPE_BOAT; }\n\tbool IsTrain(void) { return m_vehType == VEHICLE_TYPE_TRAIN; }\n\tbool IsHeli(void) { return m_vehType == VEHICLE_TYPE_HELI; }\n\tbool IsPlane(void) { return m_vehType == VEHICLE_TYPE_PLANE; }\n\tbool IsBike(void) { return m_vehType == VEHICLE_TYPE_BIKE; }\n\n\tvoid FlyingControl(eFlightModel flightModel);\n\tbool DoBladeCollision(CVector pos, CMatrix &matrix, int16 rotorType, float radius, float damageMult);\n\tbool BladeColSectorList(CPtrList &list, CColModel &rotorColModel, CMatrix &matrix, int16 rotorType, float damageMult);\n\n\tvoid ProcessWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelContactSpeed, CVector &wheelContactPoint,\n\t\tint32 wheelsOnGround, float thrust, float brake, float adhesion, int8 wheelId, float *wheelSpeed, tWheelState *wheelState, uint16 wheelStatus);\n\tvoid ProcessBikeWheel(CVector &wheelFwd, CVector &wheelRight, CVector &wheelContactSpeed, CVector &wheelContactPoint,\n\t\tint32 wheelsOnGround, float thrust, float brake, float adhesion, float destabTraction, int8 wheelId, float *wheelSpeed, tWheelState *wheelState, eBikeWheelSpecial special, uint16 wheelStatus);\n\tvoid ExtinguishCarFire(void);\n\tvoid ProcessDelayedExplosion(void);\n\tfloat ProcessWheelRotation(tWheelState state, const CVector &fwd, const CVector &speed, float radius);\n\tint FindTyreNearestPoint(float x, float y);\n\tbool IsLawEnforcementVehicle(void);\n\tvoid ChangeLawEnforcerState(uint8 enable);\n\tbool UsesSiren(void);\n\tbool IsVehicleNormal(void);\n\tbool CarHasRoof(void);\n\tbool IsUpsideDown(void);\n\tbool IsOnItsSide(void);\n\tbool CanBeDeleted(void);\n\tbool CanPedOpenLocks(CPed *ped);\n\tbool CanDoorsBeDamaged(void);\n\tbool CanPedEnterCar(void);\n\tbool CanPedExitCar(bool jumpExit);\n\tbool CanPedJumpOutCar(void);\n\tbool CanPedJumpOffBike(void);\n\t// do these two actually return something?\n\tCPed *SetUpDriver(void);\n\tCPed *SetupPassenger(int n);\n\tvoid SetDriver(CPed *driver);\n\tbool AddPassenger(CPed *passenger);\n\tbool AddPassenger(CPed *passenger, uint8 n);\n\tvoid RemovePassenger(CPed *passenger);\n\tvoid RemoveDriver(void);\n\tbool IsDriver(CPed *ped);\n\tbool IsDriver(int32 model);\n\tbool IsPassenger(CPed *ped);\n\tbool IsPassenger(int32 model);\n\tvoid UpdatePassengerList(void);\n\tvoid ProcessCarAlarm(void);\n\tbool IsSphereTouchingVehicle(float sx, float sy, float sz, float radius);\n\tbool ShufflePassengersToMakeSpace(void);\n\tvoid MakeNonDraggedPedsLeaveVehicle(CPed *ped1, CPed *ped2, CPlayerPed *&player, CCopPed *&cop);\n\tvoid InflictDamage(CEntity *damagedBy, eWeaponType weaponType, float damage, CVector pos = CVector(0.0f, 0.0f, 0.0f));\n\tvoid DoFixedMachineGuns(void);\n\tvoid FireFixedMachineGuns(void);\n\tvoid ActivateBomb(void);\n\tvoid ActivateBombWhenEntered(void);\n\tvoid KillPedsInVehicle(void);\n\n\tvoid SetComponentAtomicAlpha(RpAtomic *atomic, int32 alpha);\n\tvoid UpdateClumpAlpha(void);\n\n\tstatic void HeliDustGenerate(CEntity *heli, float radius, float ground, int rnd);\n\tvoid DoSunGlare(void);\n\n\tbool IsAlarmOn(void) { return m_nAlarmState != 0 && m_nAlarmState != -1 && GetStatus() != STATUS_WRECKED; }\n\tCVehicleModelInfo* GetModelInfo() { return (CVehicleModelInfo*)CModelInfo::GetModelInfo(GetModelIndex()); }\n\tbool IsTaxi(void) { return GetModelIndex() == MI_TAXI || GetModelIndex() == MI_CABBIE || GetModelIndex() == MI_ZEBRA || GetModelIndex() == MI_KAUFMAN; }\n\tbool IsLimo(void) { return GetModelIndex() == MI_STRETCH || GetModelIndex() == MI_LOVEFIST; }\n\tbool IsRealHeli(void) { return !!(pHandling->Flags & HANDLING_IS_HELI); }\n\tbool IsRealPlane(void) { return !!(pHandling->Flags & HANDLING_IS_PLANE); }\n\n\tstatic bool bWheelsOnlyCheat;\n\tstatic bool bAllDodosCheat;\n\tstatic bool bCheat3;\n\tstatic bool bCheat4;\n\tstatic bool bCheat5;\n\tstatic bool bCheat8;\n\tstatic bool bCheat9;\n\tstatic bool bCheat10;\n\tstatic bool bHoverCheat;\n\tstatic bool bAllTaxisHaveNitro;\n\tstatic bool m_bDisableMouseSteering;\n\tstatic bool bDisableRemoteDetonation;\n\tstatic bool bDisableRemoteDetonationOnContact;\n#ifndef MASTER\n\tstatic bool m_bDisplayHandlingInfo;\n#endif\n};\n\nvoid DestroyVehicleAndDriverAndPassengers(CVehicle* pVehicle);\nbool IsVehiclePointerValid(CVehicle* pVehicle);\n\n// Names of functions below are made up by us.\n\n// Used in III and VC.\ninline int8 GetCarDoorFlag(int32 carnode) {\n\tswitch (carnode) {\n\tcase CAR_DOOR_LF:\n\t\treturn CAR_DOOR_FLAG_LF;\n\tcase CAR_DOOR_LR:\n\t\treturn CAR_DOOR_FLAG_LR;\n\tcase CAR_DOOR_RF:\n\t\treturn CAR_DOOR_FLAG_RF;\n\tcase CAR_DOOR_RR:\n\t\treturn CAR_DOOR_FLAG_RR;\n\tdefault:\n\t\treturn CAR_DOOR_FLAG_UNKNOWN;\n\t}\n}\n\n// VC. Accounts the case numMaxPassengers == 0, only for m_nGettingInFlags.\ninline int8 GetEnterCarDoorFlag(int32 carnode, uint8 numMaxPassengers) {\n\tswitch (carnode) {\n\tcase CAR_DOOR_RF:\n\t\treturn CAR_DOOR_FLAG_RF;\n\tcase CAR_DOOR_RR:\n\t\treturn CAR_DOOR_FLAG_RR;\n\tcase CAR_DOOR_LF:\n\t\tif (numMaxPassengers != 0)\n\t\t\treturn CAR_DOOR_FLAG_LF;\n\t\telse\n\t\t\treturn CAR_DOOR_FLAG_LF | CAR_DOOR_FLAG_LR;\n\tcase CAR_DOOR_LR:\n\t\tif (numMaxPassengers != 0)\n\t\t\treturn CAR_DOOR_FLAG_LR;\n\t\telse\n\t\t\treturn CAR_DOOR_FLAG_LF | CAR_DOOR_FLAG_LR;\n\tdefault:\n\t\treturn CAR_DOOR_FLAG_UNKNOWN;\n\t}\n}\n"
  },
  {
    "path": "src/weapons/BulletInfo.cpp",
    "content": "#include \"common.h\"\n\n#include \"BulletInfo.h\"\n\n#include \"AnimBlendAssociation.h\"\n#include \"DMAudio.h\"\n#include \"AudioScriptObject.h\"\n#ifdef FIX_BUGS\n#include \"Collision.h\"\n#endif\n#include \"RpAnimBlend.h\"\n#include \"Entity.h\"\n#include \"EventList.h\"\n#include \"Fire.h\"\n#include \"Glass.h\"\n#include \"Particle.h\"\n#include \"Ped.h\"\n#include \"Object.h\"\n#include \"Stats.h\"\n#include \"Timer.h\"\n#include \"Vehicle.h\"\n#include \"Weapon.h\"\n#include \"WeaponInfo.h\"\n#include \"World.h\"\n#include \"SurfaceTable.h\"\n#include \"Heli.h\"\n\n#ifdef SQUEEZE_PERFORMANCE\nuint32 bulletInfoInUse;\n#endif\n\n#define BULLET_LIFETIME (1000)\n#define NUM_PED_BLOOD_PARTICLES (8)\n#define BLOOD_PARTICLE_OFFSET (CVector(0.0f, 0.0f, 0.0f))\n#define NUM_VEHICLE_SPARKS (16)\n#define NUM_TYRE_POP_SMOKES (4)\n#define NUM_OTHER_SPARKS (8)\n#define BULLET_HIT_FORCE (7.5f)\n\n#define BULLET_BOUNDARY_MIN_X -2400.0f\n#define BULLET_BOUNDARY_MAX_X 1600.0f\n#define BULLET_BOUNDARY_MIN_Y -2000.0f\n#define BULLET_BOUNDARY_MAX_Y 2000.0f\n\nCBulletInfo gaBulletInfo[CBulletInfo::NUM_BULLETS];\nbool bPlayerSniperBullet;\nCVector PlayerSniperBulletStart;\nCVector PlayerSniperBulletEnd;\n\nvoid CBulletInfo::Initialise(void)\n{\n\tdebug(\"Initialising CBulletInfo...\\n\");\n\tfor (int i = 0; i < NUM_BULLETS; i++) {\n\t\tgaBulletInfo[i].m_bInUse = false;\n\t\tgaBulletInfo[i].m_eWeaponType = WEAPONTYPE_COLT45;\n\t\tgaBulletInfo[i].m_fTimer = 0.0f;\n\t\tgaBulletInfo[i].m_pSource = nil;\n\t}\n\tdebug(\"CBulletInfo ready\\n\");\n#ifdef SQUEEZE_PERFORMANCE\n\tbulletInfoInUse = 0;\n#endif\n}\n\nvoid CBulletInfo::Shutdown(void)\n{\n\tdebug(\"Shutting down CBulletInfo...\\n\");\n\tdebug(\"CBulletInfo shut down\\n\");\n}\n\nbool CBulletInfo::AddBullet(CEntity* pSource, eWeaponType type, CVector vecPosition, CVector vecSpeed)\n{\n\tint i;\n\tfor (i = 0; i < NUM_BULLETS; i++) {\n\t\tif (!gaBulletInfo[i].m_bInUse)\n\t\t\tbreak;\n\t}\n\tif (i == NUM_BULLETS)\n\t\treturn false;\n\tgaBulletInfo[i].m_pSource = pSource;\n\tgaBulletInfo[i].m_eWeaponType = type;\n\tgaBulletInfo[i].m_nDamage = CWeaponInfo::GetWeaponInfo(type)->m_nDamage;\n\tgaBulletInfo[i].m_vecPosition = vecPosition;\n\tgaBulletInfo[i].m_vecSpeed = vecSpeed;\n\tgaBulletInfo[i].m_fTimer = CTimer::GetTimeInMilliseconds() + BULLET_LIFETIME;\n\tgaBulletInfo[i].m_bInUse = true;\n\n#ifdef SQUEEZE_PERFORMANCE\n\tbulletInfoInUse++;\n#endif\n\treturn true;\n}\n\nvoid CBulletInfo::Update(void)\n{\n#ifdef SQUEEZE_PERFORMANCE\n\tif (bulletInfoInUse == 0)\n\t\treturn;\n#endif\n\tbPlayerSniperBullet = false;\n\tfor (int i = 0; i < NUM_BULLETS; i++) {\n\t\tCBulletInfo* pBullet = &gaBulletInfo[i];\n\t\tif (pBullet->m_pSource && pBullet->m_pSource->IsPed() && !((CPed*)pBullet->m_pSource)->IsPointerValid())\n\t\t\tpBullet->m_pSource = nil;\n\t\tif (!pBullet->m_bInUse)\n\t\t\tcontinue;\n\t\tif (CTimer::GetTimeInMilliseconds() > pBullet->m_fTimer) {\n\t\t\tpBullet->m_bInUse = false;\n#ifdef SQUEEZE_PERFORMANCE\n\t\t\tbulletInfoInUse--;\n#endif\n\t\t}\n\t\tCVector vecOldPos = pBullet->m_vecPosition;\n\t\tCVector vecNewPos = pBullet->m_vecPosition + pBullet->m_vecSpeed * CTimer::GetTimeStep() * 0.5f;\n\n\t\tif ( vecNewPos.x <= BULLET_BOUNDARY_MIN_X || vecNewPos.x >= BULLET_BOUNDARY_MAX_X || vecNewPos.y <= BULLET_BOUNDARY_MIN_Y || vecNewPos.y >= BULLET_BOUNDARY_MAX_Y ) {\n\t\t\tpBullet->m_bInUse = false;\n\t\t\tcontinue;\n\t\t}\n\t\tCWorld::bIncludeDeadPeds = true;\n\t\tCWorld::bIncludeBikers = true;\n\t\tCWorld::bIncludeCarTyres = true;\n\t\tCWorld::pIgnoreEntity = pBullet->m_pSource;\n\t\tCColPoint point;\n\t\tCEntity* pHitEntity;\n\t\tif (CWorld::ProcessLineOfSight(vecOldPos, vecNewPos, point, pHitEntity, true, true, true, true, true, false, false, true)) {\n\n\t\t\tCWeapon::CheckForShootingVehicleOccupant(&pHitEntity, &point, pBullet->m_eWeaponType, vecOldPos, vecNewPos);\n\t\t\tif (pHitEntity->IsPed()) {\n\t\t\t\tCPed* pPed = (CPed*)pHitEntity;\n\t\t\t\tif (!pPed->DyingOrDead() && pPed != pBullet->m_pSource) {\n\t\t\t\t\tif (pPed->IsPedInControl() && !pPed->bIsDucking) {\n\t\t\t\t\t\tpPed->ClearAttackByRemovingAnim();\n\t\t\t\t\t\tCAnimBlendAssociation* pAnim = CAnimManager::AddAnimation(pPed->GetClump(), ASSOCGRP_STD, ANIM_STD_HITBYGUN_FRONT);\n\t\t\t\t\t\tpAnim->SetBlend(0.0f, 8.0f);\n\t\t\t\t\t}\n\t\t\t\t\tpPed->InflictDamage(pBullet->m_pSource, pBullet->m_eWeaponType, pBullet->m_nDamage, (ePedPieceTypes)point.pieceB, pPed->GetLocalDirection(pPed->GetPosition() - point.point));\n\t\t\t\t\tCEventList::RegisterEvent(pPed->m_nPedType == PEDTYPE_COP ? EVENT_SHOOT_COP : EVENT_SHOOT_PED, EVENT_ENTITY_PED, pPed, (CPed*)pBullet->m_pSource, 1000);\n\t\t\t\t\tpBullet->m_bInUse = false;\n#ifdef SQUEEZE_PERFORMANCE\n\t\t\t\t\tbulletInfoInUse--;\n#endif\n\t\t\t\t\tvecNewPos = point.point;\n\t\t\t\t}\n\t\t\t\tif (CGame::nastyGame) {\n\t\t\t\t\tCVector vecParticleDirection = (point.point - pPed->GetPosition()) * 0.01f;\n\t\t\t\t\tvecParticleDirection.z = 0.01f;\n\t\t\t\t\tif (pPed->GetIsOnScreen()) {\n\t\t\t\t\t\tfor (int j = 0; j < NUM_PED_BLOOD_PARTICLES; j++)\n\t\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_BLOOD_SMALL, point.point + BLOOD_PARTICLE_OFFSET, vecParticleDirection);\n\t\t\t\t\t}\n\t\t\t\t\tif (pPed->GetPedState() == PED_DEAD) {\n\t\t\t\t\t\tCAnimBlendAssociation* pAnim;\n\t\t\t\t\t\tif (RpAnimBlendClumpGetFirstAssociation(pPed->GetClump(), ASSOC_FRONTAL))\n\t\t\t\t\t\t\tpAnim = CAnimManager::BlendAnimation(pPed->GetClump(), ASSOCGRP_STD, ANIM_STD_HIT_FLOOR_FRONT, 8.0f);\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tpAnim = CAnimManager::BlendAnimation(pPed->GetClump(), ASSOCGRP_STD, ANIM_STD_HIT_FLOOR, 8.0f);\n\t\t\t\t\t\tif (pAnim) {\n\t\t\t\t\t\t\tpAnim->SetCurrentTime(0.0f);\n\t\t\t\t\t\t\tpAnim->flags |= ASSOC_RUNNING;\n\t\t\t\t\t\t\tpAnim->flags &= ~ASSOC_FADEOUTWHENDONE;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tpBullet->m_bInUse = false;\n#ifdef SQUEEZE_PERFORMANCE\n\t\t\t\t\tbulletInfoInUse--;\n#endif\n\t\t\t\t\tvecNewPos = point.point;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (pHitEntity->IsVehicle()) {\n\t\t\t\tCEntity *source = pBullet->m_pSource;\n\t\t\t\tif ( !source || !source->IsPed() || ((CPed*)source)->m_attachedTo != pHitEntity) {\n\t\t\t\t\tif ( point.pieceB >= CAR_PIECE_WHEEL_LF && point.pieceB <= CAR_PIECE_WHEEL_RR ) {\n\t\t\t\t\t\t((CVehicle*)pHitEntity)->BurstTyre(point.pieceB, true);\n\t\t\t\t\t\tfor (int j=0; j<NUM_TYRE_POP_SMOKES; j++) {\n\t\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_BULLETHIT_SMOKE, point.point, point.normal / 20);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// CVector sth(0.0f, 0.0f, 0.0f); // unused\n\t\t\t\t\t\t((CVehicle*)pHitEntity)->InflictDamage(source, pBullet->m_eWeaponType, pBullet->m_nDamage);\n\t\t\t\t\t\tif ( pBullet->m_eWeaponType == WEAPONTYPE_FLAMETHROWER ) {\n\t\t\t\t\t\t\tgFireManager.StartFire(pHitEntity, pBullet->m_pSource, 0.8f, 1);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tfor (int j=0; j<NUM_VEHICLE_SPARKS; j++) {\n\t\t\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_SPARK, point.point, point.normal / 20);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n#ifdef FIX_BUGS\n\t\t\t\tpBullet->m_bInUse = false;\n#ifdef SQUEEZE_PERFORMANCE\n\t\t\t\tbulletInfoInUse--;\n#endif\n\t\t\t\tvecNewPos = point.point;\n#endif\n\t\t\t} else {\n\t\t\t\tfor (int j = 0; j < NUM_OTHER_SPARKS; j++)\n\t\t\t\t\tCParticle::AddParticle(PARTICLE_SPARK, point.point, point.normal / 20);\n\t\t\t\tCEntity *source = pBullet->m_pSource;\n\t\t\t\tif ( !source || !source->IsPed() || ((CPed*)source)->m_attachedTo != pHitEntity) {\n\t\t\t\t\tif (pHitEntity->IsObject()) {\n\t\t\t\t\t\tCObject *pHitObject = (CObject*)pHitEntity;\n\t\t\t\t\t\tif ( !pHitObject->bInfiniteMass && pHitObject->m_fCollisionDamageMultiplier < 99.9f) {\n\t\t\t\t\t\t\tbool notStatic = !pHitObject->GetIsStatic();\n\t\t\t\t\t\t\tif (notStatic && pHitObject->m_fUprootLimit <= 0.0f) {\n\t\t\t\t\t\t\t\tpHitObject->bIsStatic = false;\n\t\t\t\t\t\t\t\tpHitObject->AddToMovingList();\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tnotStatic = !pHitObject->GetIsStatic();\n\t\t\t\t\t\t\tif (!notStatic) {\n\t\t\t\t\t\t\t\tCVector moveForce = point.normal * -BULLET_HIT_FORCE;\n\t\t\t\t\t\t\t\tpHitObject->ApplyMoveForce(moveForce.x, moveForce.y, moveForce.z);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if (pHitObject->m_nCollisionDamageEffect >= DAMAGE_EFFECT_SMASH_COMPLETELY) {\n\t\t\t\t\t\t\tpHitObject->ObjectDamage(50.f);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n#ifdef FIX_BUGS\n\t\t\t\tpBullet->m_bInUse = false;\n#ifdef SQUEEZE_PERFORMANCE\n\t\t\t\tbulletInfoInUse--;\n#endif\n\t\t\t\tvecNewPos = point.point;\n#endif\n\t\t\t}\n\t\t\tif (pBullet->m_eWeaponType == WEAPONTYPE_SNIPERRIFLE || pBullet->m_eWeaponType == WEAPONTYPE_LASERSCOPE) {\n\t\t\t\tcAudioScriptObject* pAudio;\n\t\t\t\tswitch (pHitEntity->GetType()) {\n\t\t\t\t\tcase ENTITY_TYPE_BUILDING:\n\t\t\t\t\t\tif (!DMAudio.IsAudioInitialised())\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tpAudio = new cAudioScriptObject();\n\t\t\t\t\t\tif (pAudio)\n\t\t\t\t\t\t\tpAudio->Reset();\n\t\t\t\t\t\tpAudio->Posn = pHitEntity->GetPosition();\n\t\t\t\t\t\tpAudio->AudioId = SCRIPT_SOUND_BULLET_HIT_GROUND_1;\n\t\t\t\t\t\tpAudio->AudioEntity = AEHANDLE_NONE;\n\t\t\t\t\t\tDMAudio.CreateOneShotScriptObject(pAudio);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase ENTITY_TYPE_OBJECT:\n\t\t\t\t\t\tif (!DMAudio.IsAudioInitialised())\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tpAudio = new cAudioScriptObject();\n\t\t\t\t\t\tif (pAudio)\n\t\t\t\t\t\t\tpAudio->Reset();\n\t\t\t\t\t\tpAudio->Posn = pHitEntity->GetPosition();\n\t\t\t\t\t\tpAudio->AudioId = SCRIPT_SOUND_BULLET_HIT_GROUND_2;\n\t\t\t\t\t\tpAudio->AudioEntity = AEHANDLE_NONE;\n\t\t\t\t\t\tDMAudio.CreateOneShotScriptObject(pAudio);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase ENTITY_TYPE_DUMMY:\n\t\t\t\t\t\tif (!DMAudio.IsAudioInitialised())\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tpAudio = new cAudioScriptObject();\n\t\t\t\t\t\tif (pAudio)\n\t\t\t\t\t\t\tpAudio->Reset();\n\t\t\t\t\t\tpAudio->Posn = pHitEntity->GetPosition();\n\t\t\t\t\t\tpAudio->AudioId = SCRIPT_SOUND_BULLET_HIT_GROUND_3;\n\t\t\t\t\t\tpAudio->AudioEntity = AEHANDLE_NONE;\n\t\t\t\t\t\tDMAudio.CreateOneShotScriptObject(pAudio);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase ENTITY_TYPE_PED:\n\t\t\t\t\t\t++CStats::BulletsThatHit;\n\t\t\t\t\t\tDMAudio.PlayOneShot(((CPed*)pHitEntity)->m_audioEntityId, SOUND_WEAPON_HIT_PED, 1.0f);\n\t\t\t\t\t\t((CPed*)pHitEntity)->Say(SOUND_PED_BULLET_HIT);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase ENTITY_TYPE_VEHICLE:\n\t\t\t\t\t\t++CStats::BulletsThatHit;\n\t\t\t\t\t\tDMAudio.PlayOneShot(((CVehicle*)pHitEntity)->m_audioEntityId, SOUND_WEAPON_HIT_VEHICLE, 1.0f);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tdefault: break;\n\t\t\t\t}\n\t\t\t}\n\t\t\tCGlass::WasGlassHitByBullet(pHitEntity, point.point);\n\t\t\tCWeapon::BlowUpExplosiveThings(pHitEntity);\n\t\t}\n\t\tCWorld::pIgnoreEntity = nil;\n\t\tCWorld::bIncludeDeadPeds = false;\n\t\tCWorld::bIncludeCarTyres = false;\n\t\tCWorld::bIncludeBikers = false;\n\t\tif (pBullet->m_eWeaponType == WEAPONTYPE_SNIPERRIFLE || pBullet->m_eWeaponType == WEAPONTYPE_LASERSCOPE) {\n\t\t\tbPlayerSniperBullet = true;\n\t\t\tPlayerSniperBulletStart = pBullet->m_vecPosition;\n\t\t\tPlayerSniperBulletEnd = vecNewPos;\n\t\t}\n\t\tpBullet->m_vecPosition = vecNewPos;\n\t\tCHeli::TestSniperCollision(&PlayerSniperBulletStart, &PlayerSniperBulletEnd);\n\t}\n}\n\nbool CBulletInfo::TestForSniperBullet(float x1, float x2, float y1, float y2, float z1, float z2)\n{\n\tif (!bPlayerSniperBullet)\n\t\treturn false;\n#ifdef FIX_BUGS // original code is not going work anyway...\n\tCColLine line(PlayerSniperBulletStart, PlayerSniperBulletEnd);\n\tCColBox box;\n\tbox.Set(CVector(x1, y1, z1), CVector(x2, y2, z2), SURFACE_DEFAULT, 0);\n\treturn CCollision::TestLineBox(line, box);\n#else\n\tfloat minP = 0.0f;\n\tfloat maxP = 1.0f;\n\tfloat minX = Min(PlayerSniperBulletStart.x, PlayerSniperBulletEnd.x);\n\tfloat maxX = Max(PlayerSniperBulletStart.x, PlayerSniperBulletEnd.x);\n\tif (minX < x2 || maxX > x1) {\n\t\tif (minX < x1)\n\t\t\tminP = Min(minP, (x1 - minX) / (maxX - minX));\n\t\tif (maxX > x2)\n\t\t\tmaxP = Max(maxP, (maxX - x2) / (maxX - minX));\n\t}\n\telse\n\t\treturn false;\n\tfloat minY = Min(PlayerSniperBulletStart.y, PlayerSniperBulletEnd.y);\n\tfloat maxY = Max(PlayerSniperBulletStart.y, PlayerSniperBulletEnd.y);\n\tif (minY < y2 || maxY > y1) {\n\t\tif (minY < y1)\n\t\t\tminP = Min(minP, (y1 - minY) / (maxY - minY));\n\t\tif (maxY > y2)\n\t\t\tmaxP = Max(maxP, (maxY - y2) / (maxY - minY));\n\t}\n#ifdef FIX_BUGS\n\telse\n\t\treturn false;\n#endif\n\tfloat minZ = Min(PlayerSniperBulletStart.z, PlayerSniperBulletEnd.z);\n\tfloat maxZ = Max(PlayerSniperBulletStart.z, PlayerSniperBulletEnd.z);\n\tif (minZ < z2 || maxZ > z1) {\n\t\tif (minZ < z1)\n\t\t\tminP = Min(minP, (z1 - minZ) / (maxZ - minZ));\n\t\tif (maxZ > z2)\n\t\t\tmaxP = Max(maxP, (maxZ - z2) / (maxZ - minZ));\n\t}\n\telse\n\t\treturn false;\n\treturn minP <= maxP;\n#endif\n}\n"
  },
  {
    "path": "src/weapons/BulletInfo.h",
    "content": "#pragma once\n\n#include \"WeaponType.h\"\n\nclass CEntity;\n\nclass CBulletInfo\n{\n\teWeaponType m_eWeaponType;\n\tCEntity* m_pSource;\n\tfloat m_fTimer; // big mistake\n\tbool m_bInUse;\n\tCVector m_vecPosition;\n\tCVector m_vecSpeed;\n\tint16 m_nDamage;\npublic:\n\tenum {\n\t\tNUM_BULLETS = 100\n\t};\n\tstatic void Initialise(void);\n\tstatic void Shutdown(void);\n\tstatic bool AddBullet(CEntity* pSource, eWeaponType type, CVector vecPosition, CVector vecSpeed);\n\tstatic void Update(void);\n\tstatic bool TestForSniperBullet(float x1, float x2, float y1, float y2, float z1, float z2);\n};"
  },
  {
    "path": "src/weapons/Explosion.cpp",
    "content": "#include \"common.h\"\n\n#include \"Automobile.h\"\n#include \"Bike.h\"\n#include \"Camera.h\"\n#include \"Coronas.h\"\n#include \"DMAudio.h\"\n#include \"Entity.h\"\n#include \"EventList.h\"\n#include \"Explosion.h\"\n#include \"General.h\"\n#include \"Fire.h\"\n#include \"Pad.h\"\n#include \"Particle.h\"\n#include \"PointLights.h\"\n#include \"Shadows.h\"\n#include \"Timer.h\"\n#include \"Vehicle.h\"\n#include \"WaterLevel.h\"\n#include \"World.h\"\n\nCExplosion gaExplosion[NUM_EXPLOSIONS];\n\n// these two were not initialised in original code, I'm really not sure what were they meant to be\nRwRGBA colMedExpl = { 0, 0, 0, 0 };\nRwRGBA colUpdate = { 0, 0, 0, 0 };\n\nconst RwRGBA colAddExplosion = { 160, 160, 160, 255 };\nconst RwRGBA colGrenade = { 96, 96, 96, 255 };\n\nint AudioHandle = AEHANDLE_NONE;\n\nvoid\nCExplosion::Initialise()\n{\n\tdebug(\"Initialising CExplosion...\\n\");\n\tClearAllExplosions();\n\tAudioHandle = DMAudio.CreateEntity(AUDIOTYPE_EXPLOSION, (void*)1);\n\tif (AudioHandle >= 0)\n\t\tDMAudio.SetEntityStatus(AudioHandle, true);\n\tdebug(\"CExplosion ready\\n\");\n}\n\nvoid\nCExplosion::ClearAllExplosions()\n{\n\tfor (int i = 0; i < ARRAY_SIZE(gaExplosion); i++) {\n\t\tgaExplosion[i].m_ExplosionType = EXPLOSION_GRENADE;\n\t\tgaExplosion[i].m_vecPosition = CVector(0.0f, 0.0f, 0.0f);\n\t\tgaExplosion[i].m_fRadius = 1.0f;\n\t\tgaExplosion[i].m_fPropagationRate = 0.0f;\n\t\tgaExplosion[i].m_fZshift = 0.0f;\n\t\tgaExplosion[i].m_pCreatorEntity = nil;\n\t\tgaExplosion[i].m_pVictimEntity = nil;\n\t\tgaExplosion[i].m_fStopTime = 0.0f;\n\t\tgaExplosion[i].m_nIteration = 0;\n\t\tgaExplosion[i].m_fStartTime = 0.0f;\n\t\tgaExplosion[i].m_bIsBoat = false;\n\t\tgaExplosion[i].m_bMakeSound = true;\n\t}\n}\n\nvoid\nCExplosion::Shutdown()\n{\n\tdebug(\"Shutting down CExplosion...\\n\");\n\tif (AudioHandle >= 0) {\n\t\tDMAudio.DestroyEntity(AudioHandle);\n\t\tAudioHandle = AEHANDLE_NONE;\n\t}\n\tdebug(\"CExplosion shut down\\n\");\n}\n\nint8\nCExplosion::GetExplosionActiveCounter(uint8 id)\n{\n\treturn gaExplosion[id].m_nActiveCounter;\n}\n\nvoid\nCExplosion::ResetExplosionActiveCounter(uint8 id)\n{\n\tgaExplosion[id].m_nActiveCounter = 0;\n}\n\nuint8\nCExplosion::GetExplosionType(uint8 id)\n{\n\treturn gaExplosion[id].m_ExplosionType;\n}\n\nbool\nCExplosion::DoesExplosionMakeSound(uint8 id)\n{ \n\treturn gaExplosion[id].m_bMakeSound; \n};\n\nCVector *\nCExplosion::GetExplosionPosition(uint8 id)\n{\n\treturn &gaExplosion[id].m_vecPosition;\n}\n\nbool\nCExplosion::AddExplosion(CEntity *explodingEntity, CEntity *culprit, eExplosionType type, const CVector &pos, uint32 lifetime, bool makeSound)\n{\n\tCVector pPosn;\n\tCVector posGround;\n\n\tRwRGBA colorMedium = colMedExpl;\n\tRwRGBA color = colAddExplosion;\n\tRwRGBA colorGrenade = colGrenade;\n\tbool bDontExplode = false;\n\tpPosn = pos;\n\tpPosn.z += 5.0f;\n#ifdef FIX_BUGS\n\tCShadows::AddPermanentShadow(SHADOWTEX_CAR, gpShadowHeliTex, &pPosn, 8.0f, 0.0f, 0.0f, -8.0f, 200, 0, 0, 0, 10.0f, 30000, 1.0f);\n#else\n\t// last two arguments are swapped resulting in no shadow\n\tCShadows::AddPermanentShadow(SHADOWTEX_CAR, gpShadowHeliTex, &pPosn, 8.0f, 0.0f, 0.0f, -8.0f, 200, 0, 0, 0, 10.0f, 1, 30000.0f);\n#endif\n\n\tint n = 0;\n#ifdef FIX_BUGS\n\twhile (n < ARRAY_SIZE(gaExplosion) && gaExplosion[n].m_nIteration != 0)\n#else\n\t// array overrun is UB\n\twhile (gaExplosion[n].m_nIteration != 0 && n < ARRAY_SIZE(gaExplosion))\n#endif\n\t\tn++;\n\tif (n == ARRAY_SIZE(gaExplosion))\n\t\treturn false;\n\n\tCExplosion &explosion = gaExplosion[n];\n\texplosion.m_ExplosionType = type;\n\texplosion.m_vecPosition = pos;\n\texplosion.m_fRadius = 1.0f;\n\texplosion.m_fZshift = 0.0f;\n\texplosion.m_pCreatorEntity = culprit;\n\tif (culprit != nil)\n\t\tculprit->RegisterReference(&explosion.m_pCreatorEntity);\n\texplosion.m_pVictimEntity = explodingEntity;\n\tif (explodingEntity != nil)\n\t\texplodingEntity->RegisterReference(&explosion.m_pVictimEntity);\n\texplosion.m_nIteration = 1;\n\texplosion.m_nActiveCounter = 1;\n\texplosion.m_bIsBoat = false;\n\texplosion.m_bMakeSound = makeSound;\n\texplosion.m_nParticlesExpireTime = lifetime != 0 ? CTimer::GetTimeInMilliseconds() + lifetime : 0;\n\tswitch (type)\n\t{\n\tcase EXPLOSION_GRENADE:\n\t\texplosion.m_fRadius = 9.0f;\n\t\texplosion.m_fPower = 300.0f;\n\t\texplosion.m_fStopTime = lifetime + CTimer::GetTimeInMilliseconds() + 750;\n\t\texplosion.m_fPropagationRate = 0.5f;\n\t\tposGround = pos;\n\t\tposGround.z = CWorld::FindGroundZFor3DCoord(posGround.x, posGround.y, posGround.z + 3.0f, nil);\n\t\tCEventList::RegisterEvent(EVENT_EXPLOSION, posGround, 250);\n\t\tif (Distance(explosion.m_vecPosition, TheCamera.GetPosition()) < 40.0f) {\n\t\t\tuint8 tmp = CGeneral::GetRandomNumberInRange(0, 64) - 64;\n\t\t\tcolorGrenade.green += tmp;\n\t\t\tcolorGrenade.blue += tmp;\n\t\t\tCParticle::AddParticle(PARTICLE_EXPLOSION_LFAST, explosion.m_vecPosition, CVector(0.0f, 0.0f, 0.0f), nil, 4.5f, colorGrenade);\n\t\t}\n\t\tbreak;\n\tcase EXPLOSION_MOLOTOV:\n\t{\n\t\texplosion.m_fRadius = 6.0f;\n\t\texplosion.m_fPower = 0.0f;\n\t\texplosion.m_fStopTime = lifetime + CTimer::GetTimeInMilliseconds() + 3000;\n\t\texplosion.m_fPropagationRate = 0.5f;\n\t\tposGround = pos;\n\t\tbool found;\n\t\tfloat tmp = CWorld::FindGroundZFor3DCoord(posGround.x, posGround.y, posGround.z + 3.0f, &found);\n\t\tif (found)\n\t\t\tposGround.z = tmp;\n\n\t\tfloat waterLevel;\n\t\tif (CWaterLevel::GetWaterLevelNoWaves(posGround.x, posGround.y, posGround.z, &waterLevel)\n\t\t\t&& posGround.z < waterLevel && waterLevel - 6.0f < posGround.z) { // some subway/tunnels check?\n\t\t\tbDontExplode = true;\n\t\t} else if (found) {\n\t\t\tgFireManager.StartFire(posGround, 1.8f, false);\n\t\t}\n\t\tbreak;\n\t}\n\tcase EXPLOSION_ROCKET:\n\t\texplosion.m_fRadius = 10.0f;\n\t\texplosion.m_fPower = 300.0f;\n\t\texplosion.m_fStopTime = lifetime + CTimer::GetTimeInMilliseconds() + 750;\n\t\texplosion.m_fPropagationRate = 0.5f;\n\t\tCEventList::RegisterEvent(EVENT_EXPLOSION, pos, 250);\n\t\tif (Distance(explosion.m_vecPosition, TheCamera.GetPosition()) < 40.0f)\n\t\t\tCParticle::AddParticle(PARTICLE_EXPLOSION_LFAST, explosion.m_vecPosition, CVector(0.0f, 0.0f, 0.0f), nil, 5.5f, color);\n\t\tbreak;\n\tcase EXPLOSION_CAR:\n\tcase EXPLOSION_CAR_QUICK:\n\tcase EXPLOSION_BOAT:\n\t\texplosion.m_fRadius = 9.0f;\n\t\texplosion.m_fPower = 300.0f;\n\t\texplosion.m_fStopTime = lifetime + CTimer::GetTimeInMilliseconds() + 4250;\n\t\texplosion.m_fPropagationRate = 0.5f;\n\t\texplosion.m_fStartTime = CTimer::GetTimeInMilliseconds();\n\t\tif (explosion.m_pVictimEntity != nil) {\n\t\t\tif (explosion.m_pVictimEntity->IsVehicle() && ((CVehicle*)explosion.m_pVictimEntity)->IsBoat())\n\t\t\t\texplosion.m_bIsBoat = true;\n\t\t\tCEventList::RegisterEvent(EVENT_EXPLOSION, EVENT_ENTITY_VEHICLE, explosion.m_pVictimEntity, nil, 1000);\n\t\t} else {\n\t\t\tCEventList::RegisterEvent(EVENT_EXPLOSION, pos, 1000);\n\t\t}\n\n\t\tif (explosion.m_pVictimEntity != nil && !explosion.m_bIsBoat) {\n\t\t\tCVehicle *veh = (CVehicle*)explosion.m_pVictimEntity;\n\t\t\tCVector componentPos;\n\n\t\t\tif (veh->IsBike()) {\n\t\t\t\tveh->GetComponentWorldPosition(BIKE_FORKS_REAR, componentPos);\n\t\t\t} else if (veh->IsComponentPresent(CAR_BUMP_REAR) && veh->IsComponentPresent(CAR_WHEEL_LB)) { //mb it's another enum\n\t\t\t\tCVector tmpVec;\n\t\t\t\tveh->GetComponentWorldPosition(CAR_BUMP_REAR, componentPos);\n\t\t\t\tveh->GetComponentWorldPosition(CAR_WHEEL_LB, tmpVec);\n\t\t\t\tcomponentPos += tmpVec;\n\t\t\t\tcomponentPos /= 2.0f;\n\t\t\t} else if (veh->IsComponentPresent(CAR_BOOT)) {\n\t\t\t\tveh->GetComponentWorldPosition(CAR_BOOT, componentPos);\n\t\t\t}\n\t\t\tif (componentPos.x != 0.0f) {\n\t\t\t\tint rn = (CGeneral::GetRandomNumber() & 1) + 1;\n\t\t\t\tfor (int i = 0; i < rn; i++)\n\t\t\t\t\tCParticle::AddJetExplosion(componentPos, (CGeneral::GetRandomNumber() & 7) / 7.0f  + 1.5f, 0.5f);\n\t\t\t}\n\t\t}\n\t\tbreak;\n\tcase EXPLOSION_HELI:\n\tcase EXPLOSION_HELI2:\n\t\tif (type == EXPLOSION_HELI2) {\n\t\t\texplosion.m_fRadius = 12.0f;\n\t\t\texplosion.m_fPower = 500.0f;\n\t\t} else {\n\t\t\texplosion.m_fRadius = 6.0f;\n\t\t\texplosion.m_fPower = 300.0f;\n\t\t}\n\t\texplosion.m_fStopTime = lifetime + CTimer::GetTimeInMilliseconds() + 750;\n\t\texplosion.m_fPropagationRate = 0.5f;\n\t\texplosion.m_fStartTime = CTimer::GetTimeInMilliseconds();\n\t\tfor (int i = 0; i < 10; i++) {\n\t\t\tCVector randpos;\n\n\t\t\trandpos.x = CGeneral::GetRandomNumber();\n\t\t\trandpos.y = CGeneral::GetRandomNumber();\n\t\t\trandpos.z = CGeneral::GetRandomNumber();\n\t\t\trandpos -= CVector(128, 128, 128);\n\t\t\trandpos /= 20.0f;\n\t\t\trandpos += pos;\n\n\t\t\tCParticle::AddParticle(PARTICLE_EXPLOSION_MFAST, randpos, CVector(0.0f, 0.0f, 0.0f), nil, 2.5f, color);\n\n\t\t\trandpos.x = CGeneral::GetRandomNumber();\n\t\t\trandpos.y = CGeneral::GetRandomNumber();\n\t\t\trandpos.z = CGeneral::GetRandomNumber();\n\t\t\trandpos -= CVector(128, 128, 128);\n\t\t\trandpos /= 20.0f;\n\t\t\trandpos += pos;\n\n\t\t\tCParticle::AddParticle(PARTICLE_EXPLOSION_LFAST, randpos, CVector(0.0f, 0.0f, 0.0f), nil, 5.0f, color);\n\n\t\t\trandpos.x = CGeneral::GetRandomNumber();\n\t\t\trandpos.y = CGeneral::GetRandomNumber();\n\t\t\trandpos.z = CGeneral::GetRandomNumber();\n\t\t\trandpos -= CVector(128, 128, 128);\n\t\t\trandpos /= 20.0f;\n\t\t\trandpos += pos;\n\n\t\t\tCParticle::AddJetExplosion(randpos, 1.4f, 3.0f);\n\t\t}\n\t\tCEventList::RegisterEvent(EVENT_EXPLOSION, pos, 1000);\n\t\tbreak;\n\tcase EXPLOSION_MINE:\n\t\texplosion.m_fRadius = 10.0f;\n\t\texplosion.m_fPower = 150.0f;\n\t\texplosion.m_fStopTime = lifetime + CTimer::GetTimeInMilliseconds() + 750;\n\t\texplosion.m_fPropagationRate = 0.5f;\n\t\tposGround = pos;\n\t\t//posGround.z = \n\t\t\tCWorld::FindGroundZFor3DCoord(pos.x, pos.y, pos.z + 4.0f, nil); // BUG? result is unused\n\t\tCEventList::RegisterEvent(EVENT_EXPLOSION, posGround, 250);\n\t\tbreak;\n\tcase EXPLOSION_BARREL:\n\t\texplosion.m_fRadius = 7.0f;\n\t\texplosion.m_fPower = 150.0f;\n\t\texplosion.m_fStopTime = lifetime + CTimer::GetTimeInMilliseconds() + 750;\n\t\texplosion.m_fPropagationRate = 0.5f;\n\t\tfor (int i = 0; i < 6; i++) {\n\t\t\tCVector randpos;\n\t\t\trandpos.x = CGeneral::GetRandomNumber();\n\t\t\trandpos.y = CGeneral::GetRandomNumber();\n\t\t\trandpos.z = CGeneral::GetRandomNumber();\n\t\t\trandpos -= CVector(128, 128, 128);\n\t\t\trandpos.x /= 50.0f;\n\t\t\trandpos.y /= 50.0f;\n\t\t\trandpos.z /= 25.0f;\n\t\t\trandpos += pos;\n\t\t\tCParticle::AddParticle(PARTICLE_EXPLOSION_MEDIUM, randpos, CVector(0.0f, 0.0f, 0.0f), nil, 0.0f, colorMedium);\n\t\t}\n\t\tposGround = pos;\n\t\t//posGround.z = \n\t\t\tCWorld::FindGroundZFor3DCoord(pos.x, pos.y, pos.z + 4.0f, nil); // BUG? result is unused\n\t\tCEventList::RegisterEvent(EVENT_EXPLOSION, posGround, 250);\n\t\tbreak;\n\tcase EXPLOSION_TANK_GRENADE:\n\t\texplosion.m_fRadius = 10.0f;\n\t\texplosion.m_fPower = 150.0f;\n\t\texplosion.m_fStopTime = lifetime + CTimer::GetTimeInMilliseconds() + 750;\n\t\texplosion.m_fPropagationRate = 0.5f;\n\t\tposGround = pos;\n\t\t//posGround.z = \n\t\t\tCWorld::FindGroundZFor3DCoord(pos.x, pos.y, pos.z + 4.0f, nil); // BUG? result is unused\n\t\tCEventList::RegisterEvent(EVENT_EXPLOSION, posGround, 250);\n\t\tbreak;\n\tcase EXPLOSION_HELI_BOMB:\n\t\texplosion.m_fRadius = 8.0f;\n\t\texplosion.m_fPower = 50.0f;\n\t\texplosion.m_fStopTime = lifetime + CTimer::GetTimeInMilliseconds() + 750;\n\t\texplosion.m_fPropagationRate = 0.5f;\n\t\tposGround = pos;\n\t\t//posGround.z = \n\t\t\tCWorld::FindGroundZFor3DCoord(pos.x, pos.y, pos.z + 4.0f, nil); // BUG? result is unused\n\t\tCEventList::RegisterEvent(EVENT_EXPLOSION, posGround, 250);\n\t\tbreak;\n\tdefault:\n\t\tdebug(\"Undefined explosion type, AddExplosion, Explosion.cpp\");\n\t\tbreak;\n\t}\n\n\tif (bDontExplode) {\n\t\texplosion.m_nIteration = 0;\n\t\treturn false;\n\t}\n\n\tif (explosion.m_fPower != 0.0f && explosion.m_nParticlesExpireTime == 0)\n\t\tCWorld::TriggerExplosion(pos, explosion.m_fRadius, explosion.m_fPower, culprit, (type == EXPLOSION_ROCKET || type == EXPLOSION_CAR_QUICK || type == EXPLOSION_MINE || type == EXPLOSION_BARREL || type == EXPLOSION_TANK_GRENADE || type == EXPLOSION_HELI_BOMB));\n\n\tif (type == EXPLOSION_MOLOTOV) {\n\t\tTheCamera.CamShake(0.2f, pos.x, pos.y, pos.z);\n\t} else {\n\t\tTheCamera.CamShake(0.6f, pos.x, pos.y, pos.z);\n\t\tCPad::GetPad(0)->StartShake_Distance(300, 128, pos.x, pos.y, pos.z);\n\t}\n\treturn true;\n}\n\nvoid\nCExplosion::Update()\n{\n\tRwRGBA color = colUpdate;\n\tfor (int i = 0; i < ARRAY_SIZE(gaExplosion); i++) {\n\t\tCExplosion &explosion = gaExplosion[i];\n\t\tif (explosion.m_nIteration == 0) continue;\n\n\t\tif (explosion.m_nParticlesExpireTime != 0) {\n\t\t\tif (CTimer::GetTimeInMilliseconds() > explosion.m_nParticlesExpireTime) {\n\t\t\t\texplosion.m_nParticlesExpireTime = 0;\n\t\t\t\tif (explosion.m_fPower != 0.0f)\n\t\t\t\t\tCWorld::TriggerExplosion(explosion.m_vecPosition, explosion.m_fRadius, explosion.m_fPower, explosion.m_pCreatorEntity, (explosion.m_ExplosionType == EXPLOSION_ROCKET || explosion.m_ExplosionType == EXPLOSION_CAR_QUICK || explosion.m_ExplosionType == EXPLOSION_MINE || explosion.m_ExplosionType == EXPLOSION_BARREL || explosion.m_ExplosionType == EXPLOSION_TANK_GRENADE || explosion.m_ExplosionType == EXPLOSION_HELI_BOMB));\n\t\t\t}\n\t\t} else {\n\t\t\texplosion.m_fRadius += explosion.m_fPropagationRate * CTimer::GetTimeStep();\n\t\t\tint32 someTime = explosion.m_fStopTime - CTimer::GetTimeInMilliseconds();\n\t\t\tswitch (explosion.m_ExplosionType)\n\t\t\t{\n\t\t\tcase EXPLOSION_GRENADE:\n\t\t\tcase EXPLOSION_ROCKET:\n\t\t\tcase EXPLOSION_HELI:\n\t\t\tcase EXPLOSION_HELI2:\n\t\t\tcase EXPLOSION_MINE:\n\t\t\tcase EXPLOSION_BARREL:\n\t\t\t\tif (CTimer::GetFrameCounter() & 1) {\n\t\t\t\t\tCPointLights::AddLight(CPointLights::LIGHT_POINT, explosion.m_vecPosition, CVector(0.0f, 0.0f, 0.0f), 20.0f, 1.0f, 1.0f, 0.5f, CPointLights::FOG_NONE, true);\n\t\t\t\t\tCCoronas::RegisterCorona((uintptr)&explosion, 255, 255, 200, 255, explosion.m_vecPosition, 8.0f, 120.0f, gpCoronaTexture[0], CCoronas::TYPE_NORMAL, CCoronas::REFLECTION_ON, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);\n\t\t\t\t} else\n\t\t\t\t\tCCoronas::RegisterCorona((uintptr)&explosion, 128, 128, 100, 255, explosion.m_vecPosition, 8.0f, 120.0f, gpCoronaTexture[0], CCoronas::TYPE_NORMAL, CCoronas::REFLECTION_ON, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);\n\t\t\t\tCCoronas::RegisterCorona((uintptr)&explosion + 1, 30, 30, 25, 255, explosion.m_vecPosition, explosion.m_fRadius, 120.0f, gpCoronaTexture[7], CCoronas::TYPE_STAR, CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);\n\t\t\t\tbreak;\n\t\t\tcase EXPLOSION_MOLOTOV:\n\t\t\t\tCWorld::SetPedsOnFire(explosion.m_vecPosition.x, explosion.m_vecPosition.y, explosion.m_vecPosition.z, 6.0f, explosion.m_pCreatorEntity);\n\t\t\t\tCWorld::SetCarsOnFire(explosion.m_vecPosition.x, explosion.m_vecPosition.y, explosion.m_vecPosition.z, 6.0f, explosion.m_pCreatorEntity);\n\t\t\t\tif (explosion.m_nIteration < 10) {\n\t\t\t\t\tif (explosion.m_nIteration == 1) {\n\t\t\t\t\t\tCVector point1 = explosion.m_vecPosition;\n\t\t\t\t\t\tpoint1.z += 5.0f;\n\t\t\t\t\t\tCColPoint colPoint;\n\t\t\t\t\t\tCEntity *pEntity;\n\t\t\t\t\t\tif (CWorld::ProcessVerticalLine(point1, -1000.0f, colPoint, pEntity, true, false, false, false, true, false, nil))\n\t\t\t\t\t\t\texplosion.m_fZshift = colPoint.point.z;\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\texplosion.m_fZshift = explosion.m_vecPosition.z;\n\t\t\t\t\t}\n\t\t\t\t\tfloat ff = ((float)explosion.m_nIteration * 0.55f);\n\t\t\t\t\tfor (int i = 0; i < 5 * ff; i++) {\n\t\t\t\t\t\tfloat angle = CGeneral::GetRandomNumber() / 256.0f * 6.28f;\n\n\t\t\t\t\t\tCVector pos = explosion.m_vecPosition;\n\t\t\t\t\t\tpos.x += ff * Sin(angle);\n\t\t\t\t\t\tpos.y += ff * Cos(angle);\n\t\t\t\t\t\tpos.z = explosion.m_fZshift + 0.5f;\n\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_EXPLOSION_MEDIUM, pos, CVector(0.0f, 0.0f, 0.0f), nil, 0.0f, color, CGeneral::GetRandomNumberInRange(-3.0f, 3.0f), CGeneral::GetRandomNumberInRange(-180.0f, 180.0f));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase EXPLOSION_CAR:\n\t\t\tcase EXPLOSION_CAR_QUICK:\n\t\t\tcase EXPLOSION_BOAT:\n\t\t\t\tif (someTime >= 3500) {\n\t\t\t\t\tif (explosion.m_pVictimEntity != nil) {\n\t\t\t\t\t\tif ((CGeneral::GetRandomNumber() & 0xF) == 0 && !explosion.m_bIsBoat) {\n\t\t\t\t\t\t\tCVehicle *veh = (CVehicle*)explosion.m_pVictimEntity;\n\t\t\t\t\t\t\tuint8 component = CAR_WING_LR;\n\n\t\t\t\t\t\t\t// miami leftover\n\t\t\t\t\t\t\tif (veh->IsBike())\n\t\t\t\t\t\t\t\tcomponent = BIKE_FORKS_REAR;\n\n\t\t\t\t\t\t\tif (veh->IsComponentPresent(component)) {\n\t\t\t\t\t\t\t\tCVector componentPos;\n\t\t\t\t\t\t\t\tveh->GetComponentWorldPosition(component, componentPos);\n\t\t\t\t\t\t\t\tCParticle::AddJetExplosion(componentPos, 0.5f, 0.0f);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (CTimer::GetTimeInMilliseconds() > explosion.m_fStartTime) {\n\t\t\t\t\t\t\texplosion.m_fStartTime = CTimer::GetTimeInMilliseconds() + 125 + (CGeneral::GetRandomNumber() & 0x7F);\n\t\t\t\t\t\t\tCVector pos = explosion.m_pVictimEntity->GetPosition();\n\t\t\t\t\t\t\tfor (int i = 0; i < (CGeneral::GetRandomNumber() & 1) + 1; i++)\n\t\t\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_EXPLOSION_MEDIUM, pos, CVector(0.0f, 0.0f, 0.0f), nil, 3.5f, color);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (CTimer::GetFrameCounter() & 1) {\n\t\t\t\t\t\tCPointLights::AddLight(CPointLights::LIGHT_POINT, explosion.m_vecPosition, CVector(0.0f, 0.0f, 0.0f), 15.0f, 1.0f, 0.0f, 0.0f, CPointLights::FOG_NONE, true);\n\t\t\t\t\t\tCCoronas::RegisterCorona((uintptr)&explosion, 200, 100, 0, 255, explosion.m_vecPosition, 6.0f, 80.0f, gpCoronaTexture[0], CCoronas::TYPE_NORMAL, CCoronas::REFLECTION_ON, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);\n\t\t\t\t\t} else\n\t\t\t\t\t\tCCoronas::RegisterCorona((uintptr)&explosion, 128, 0, 0, 255, explosion.m_vecPosition, 8.0f, 80.0f, gpCoronaTexture[0], CCoronas::TYPE_NORMAL, CCoronas::REFLECTION_ON, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);\n\n\t\t\t\t\tCCoronas::RegisterCorona((uintptr)&explosion + 1, 30, 15, 0, 255, explosion.m_vecPosition, explosion.m_fRadius, 80.0f, gpCoronaTexture[7], CCoronas::TYPE_STAR, CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);\n\t\t\t\t} else if (explosion.m_nIteration & 1) {\n\t\t\t\t\tif (explosion.m_pVictimEntity != nil)\n\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_ENGINE_SMOKE2, explosion.m_pVictimEntity->GetPosition(), CVector(0.0f, 0.0f, 0.0f), nil, CGeneral::GetRandomNumberInRange(0.5f, 0.8f), color);\n\t\t\t\t\tCVector pos = explosion.m_vecPosition;\n\t\t\t\t\tpos.z += 1.0f;\n\t\t\t\t\tCParticle::AddParticle(PARTICLE_ENGINE_SMOKE2, pos, CVector(0.0f, 0.0f, 0.11f), nil, CGeneral::GetRandomNumberInRange(0.5f, 2.0f), color);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase EXPLOSION_TANK_GRENADE:\n\t\t\tcase EXPLOSION_HELI_BOMB:\n\t\t\t\tif (explosion.m_nIteration < 5) {\n\t\t\t\t\tfloat ff = ((float)explosion.m_nIteration * 0.65f);\n\t\t\t\t\tfor (int i = 0; i < 10 * ff; i++) {\n\t\t\t\t\t\tuint8 x = CGeneral::GetRandomNumber(), y = CGeneral::GetRandomNumber(), z = CGeneral::GetRandomNumber();\n\t\t\t\t\t\tCVector pos(x - 128, y - 128, (z % 128) + 1);\n\n\t\t\t\t\t\tpos.Normalise();\n\t\t\t\t\t\tpos *= (explosion.m_nIteration + 1) * ff / 5.0f;\n\t\t\t\t\t\tpos += explosion.m_vecPosition;\n\t\t\t\t\t\tpos.z += 0.5f;\n\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_EXPLOSION_LARGE, pos, CVector(0.0f, 0.0f, 0.0f), nil, 0.0f, color, CGeneral::GetRandomNumberInRange(-3.0f, 3.0f), CGeneral::GetRandomNumberInRange(-180.0f, 180.0f));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (someTime > 0)\n\t\t\t\texplosion.m_nIteration++;\n\t\t\telse\n\t\t\t\texplosion.m_nIteration = 0;\n\t\t}\n\t}\n}\n\nbool\nCExplosion::TestForExplosionInArea(eExplosionType type, float x1, float x2, float y1, float y2, float z1, float z2)\n{\n\tfor (int i = 0; i < ARRAY_SIZE(gaExplosion); i++) {\n\t\tif (gaExplosion[i].m_nIteration != 0) {\n\t\t\tif (type == gaExplosion[i].m_ExplosionType) {\n\t\t\t\tif (gaExplosion[i].m_vecPosition.x >= x1 && gaExplosion[i].m_vecPosition.x <= x2) {\n\t\t\t\t\tif (gaExplosion[i].m_vecPosition.y >= y1 && gaExplosion[i].m_vecPosition.y <= y2) {\n\t\t\t\t\t\tif (gaExplosion[i].m_vecPosition.z >= z1 && gaExplosion[i].m_vecPosition.z <= z2)\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn false;\n}\n\nvoid\nCExplosion::RemoveAllExplosionsInArea(CVector pos, float radius)\n{\n\tfor (int i = 0; i < ARRAY_SIZE(gaExplosion); i++) {\n\t\tif (gaExplosion[i].m_nIteration != 0) {\n\t\t\tif ((pos - gaExplosion[i].m_vecPosition).MagnitudeSqr() < SQR(radius))\n\t\t\t\tgaExplosion[i].m_nIteration = 0;\n\t\t}\n\t}\n}"
  },
  {
    "path": "src/weapons/Explosion.h",
    "content": "#pragma once\n\nclass CEntity;\nclass CVector;\n\nenum eExplosionType\n{\n\tEXPLOSION_GRENADE,\n\tEXPLOSION_MOLOTOV,\n\tEXPLOSION_ROCKET,\n\tEXPLOSION_CAR,\n\tEXPLOSION_CAR_QUICK,\n\tEXPLOSION_BOAT,\n\tEXPLOSION_HELI,\n\tEXPLOSION_HELI2,\n\tEXPLOSION_MINE,\n\tEXPLOSION_BARREL,\n\tEXPLOSION_TANK_GRENADE,\n\tEXPLOSION_HELI_BOMB\n};\n\nclass CExplosion\n{\n\teExplosionType m_ExplosionType;\n\tCVector m_vecPosition;\n\tfloat m_fRadius;\n\tfloat m_fPropagationRate;\n\tCEntity *m_pCreatorEntity;\n\tCEntity *m_pVictimEntity;\n\tfloat m_fStopTime;\n\tuint8 m_nIteration;\n\tuint8 m_nActiveCounter;\n\tbool m_bIsBoat;\n\tbool m_bMakeSound;\n\tfloat m_fStartTime;\n\tuint32 m_nParticlesExpireTime;\n\tfloat m_fPower;\n\tfloat m_fZshift;\npublic:\n\tstatic bool AddExplosion(CEntity *explodingEntity, CEntity *culprit, eExplosionType type, const CVector &pos, uint32 lifetime, bool makeSound = true); //done(new parametr in android ver is fix for one mission)\n\tstatic void ClearAllExplosions(); //done\n\tstatic bool DoesExplosionMakeSound(uint8 id); //done\n\tstatic int8 GetExplosionActiveCounter(uint8 id); //done\n\tstatic CVector *GetExplosionPosition(uint8 id); //done\n\tstatic uint8 GetExplosionType(uint8 id); //done, mb need change type to tExplosionType\n\tstatic void Initialise(); //done\n\tstatic void RemoveAllExplosionsInArea(CVector pos, float radius); //done\n\tstatic void ResetExplosionActiveCounter(uint8 id); //done\n\tstatic void Shutdown(); //done\n\tstatic void Update(); //done\n\tstatic bool TestForExplosionInArea(eExplosionType type, float x1, float x2, float y1, float y2, float z1, float z2); //done, not used\n};\n\nextern CExplosion gaExplosion[NUM_EXPLOSIONS];"
  },
  {
    "path": "src/weapons/ProjectileInfo.cpp",
    "content": "#include \"common.h\"\n\n#include \"Camera.h\"\n#include \"General.h\"\n#include \"Heli.h\"\n#include \"ModelIndices.h\"\n#include \"Particle.h\"\n#include \"Ped.h\"\n#include \"Plane.h\"\n#include \"ProjectileInfo.h\"\n#include \"Projectile.h\"\n#include \"Explosion.h\"\n#include \"Weapon.h\"\n#include \"World.h\"\n\n#ifdef SQUEEZE_PERFORMANCE\nuint32 projectileInUse;\n#endif\n\nCProjectileInfo gaProjectileInfo[NUM_PROJECTILES];\nCProjectile *CProjectileInfo::ms_apProjectile[NUM_PROJECTILES];\n\n#define PROJECTILE_BOUNDARY_MIN_X -2390.0f\n#define PROJECTILE_BOUNDARY_MAX_X 1590.0f\n#define PROJECTILE_BOUNDARY_MIN_Y -1990.0f\n#define PROJECTILE_BOUNDARY_MAX_Y 1990.0f\n\nvoid\nCProjectileInfo::Initialise()\n{\n\tdebug(\"Initialising CProjectileInfo...\\n\");\n\n\tfor (int i = 0; i < ARRAY_SIZE(ms_apProjectile); i++) {\n\t\tms_apProjectile[i] = nil;\n\t\tgaProjectileInfo[i].m_eWeaponType = WEAPONTYPE_GRENADE;\n\t\tgaProjectileInfo[i].m_pSource = nil;\n\t\tgaProjectileInfo[i].m_nExplosionTime = 0;\n\t\tgaProjectileInfo[i].m_bInUse = false;\n\t}\n\n\tdebug(\"CProjectileInfo ready\\n\");\n\n#ifdef SQUEEZE_PERFORMANCE\n\tprojectileInUse = 0;\n#endif\n}\n\nvoid\nCProjectileInfo::Shutdown()\n{\n\tdebug(\"Shutting down CProjectileInfo...\\n\");\n\tdebug(\"CProjectileInfo shut down\\n\");\n}\n\nCProjectileInfo*\nCProjectileInfo::GetProjectileInfo(int32 id)\n{\n\treturn &gaProjectileInfo[id];\n}\n\nbool\nCProjectileInfo::AddProjectile(CEntity *entity, eWeaponType weapon, CVector pos, float speed)\n{\n\tint8 SpecialCollisionResponseCase = COLLRESPONSE_NONE;\n\tbool gravity = true;\n\tCMatrix matrix;\n\tfloat elasticity = 0.75f;\n\tCPed* ped = (CPed*)entity;\n\tint time;\n\tCVector velocity;\n\n\tswitch (weapon)\n\t{\n\t\tcase WEAPONTYPE_ROCKET:\n\t\t{\n\t\t\tfloat vy = 0.35f;\n\t\t\ttime = CTimer::GetTimeInMilliseconds() + 2000;\n\t\t\tif (entity->GetModelIndex() == MI_SPARROW || entity->GetModelIndex() == MI_HUNTER || entity->GetModelIndex() == MI_SENTINEL) {\n\t\t\t\tmatrix = ped->GetMatrix();\n\t\t\t\tmatrix.GetPosition() = pos;\n\t\t\t\tCVector vecSpeed = ((CPhysical*)entity)->m_vecMoveSpeed;\n\t\t\t\tvy += Max(0.0f, DotProduct(vecSpeed, entity->GetForward())) + Max(0.0f, DotProduct(vecSpeed, entity->GetUp()));\n\t\t\t} else {\n\t\t\t\tif (ped->IsPlayer()) {\n\t\t\t\t\tmatrix.GetForward() = TheCamera.Cams[TheCamera.ActiveCam].Front;\n\t\t\t\t\tmatrix.GetUp() = TheCamera.Cams[TheCamera.ActiveCam].Up;\n\t\t\t\t\tmatrix.GetRight() = CrossProduct(TheCamera.Cams[TheCamera.ActiveCam].Up, TheCamera.Cams[TheCamera.ActiveCam].Front);\n\t\t\t\t\tmatrix.GetPosition() = pos;\n\t\t\t\t} else if (ped->m_pSeekTarget != nil) {\n\t\t\t\t\tfloat ry = CGeneral::GetRadianAngleBetweenPoints(1.0f, ped->m_pSeekTarget->GetPosition().z, 1.0f, pos.z);\n\t\t\t\t\tfloat rz = Atan2(-ped->GetForward().x, ped->GetForward().y);\n\t\t\t\t\tvy = 0.35f * speed + 0.15f;\n\t\t\t\t\tmatrix.SetTranslate(0.0f, 1.0f, 1.0f);\n\t\t\t\t\tmatrix.Rotate(0.0f, ry, rz);\n\t\t\t\t\tmatrix.GetPosition() += pos;\n\t\t\t\t} else {\n\t\t\t\t\tmatrix = ped->GetMatrix();\n\t\t\t\t}\n\t\t\t}\n\t\t\tvelocity = Multiply3x3(matrix, CVector(0.0f, vy, 0.0f));\n\t\t\tgravity = false;\n\t\t\tbreak;\n\t\t}\n\t\tcase WEAPONTYPE_MOLOTOV:\n\t\t{\n\t\t\ttime = CTimer::GetTimeInMilliseconds() + 2000;\n\t\t\tfloat scale = 0.22f * speed + 0.15f;\n\t\t\tif (scale < 0.2f)\n\t\t\t\tscale = 0.2f;\n\t\t\tfloat angle = Atan2(-ped->GetForward().x, ped->GetForward().y);\n\t\t\tmatrix.SetTranslate(0.0f, 0.0f, 0.0f);\n\t\t\tmatrix.RotateZ(angle);\n\t\t\tmatrix.GetPosition() += pos;\n\t\t\tvelocity.x = -1.0f * scale * Sin(angle);\n\t\t\tvelocity.y = scale * Cos(angle);\n\t\t\tvelocity.z = (0.2f * speed + 0.4f) * scale;\n\t\t\tbreak;\n\t\t}\n\t\tcase WEAPONTYPE_TEARGAS:\n\t\t{\n\t\t\ttime = CTimer::GetTimeInMilliseconds() + 20000;\n\t\t\tfloat scale = 0.0f;\n\t\t\tif (speed != 0.0f)\n\t\t\t\tscale = 0.22f * speed + 0.15f;\n\t\t\tfloat angle = Atan2(-ped->GetForward().x, ped->GetForward().y);\n\t\t\tmatrix.SetTranslate(0.0f, 0.0f, 0.0f);\n\t\t\tmatrix.RotateZ(angle);\n\t\t\tmatrix.GetPosition() += pos;\n\t\t\tSpecialCollisionResponseCase = COLLRESPONSE_UNKNOWN5;\n\t\t\tvelocity.x = -1.0f * scale * Sin(angle);\n\t\t\tvelocity.y = scale * Cos(angle);\n\t\t\tvelocity.z = (0.4f * speed + 0.4f) * scale;\n\t\t\telasticity = 0.5f;\n\t\t\tbreak;\n\t\t}\n\t\tcase WEAPONTYPE_GRENADE:\n\t\tcase WEAPONTYPE_DETONATOR_GRENADE:\n\t\t{\n\t\t\ttime = CTimer::GetTimeInMilliseconds() + 2000;\n\t\t\tfloat scale = 0.0f;\n\t\t\tif (speed != 0.0f)\n\t\t\t\tscale = 0.22f * speed + 0.15f;\n\t\t\tfloat angle = Atan2(-ped->GetForward().x, ped->GetForward().y);\n\t\t\tmatrix.SetTranslate(0.0f, 0.0f, 0.0f);\n\t\t\tmatrix.RotateZ(angle);\n\t\t\tmatrix.GetPosition() += pos;\n\t\t\tSpecialCollisionResponseCase = COLLRESPONSE_UNKNOWN5;\n\t\t\tvelocity.x = -1.0f * scale * Sin(angle);\n\t\t\tvelocity.y = scale * Cos(angle);\n\t\t\tvelocity.z = (0.4f * speed + 0.4f) * scale;\n\t\t\telasticity = 0.5f;\n\t\t\tbreak;\n\t\t}\n\t\tdefault:\n\t\tError(\"Undefined projectile type, AddProjectile, ProjectileInfo.cpp\");\n\t\tbreak;\n\t}\n\n\tint i = 0;\n#ifdef FIX_BUGS\n\twhile (i < ARRAY_SIZE(gaProjectileInfo) && gaProjectileInfo[i].m_bInUse) i++;\n#else\n\t// array overrun is UB\n\twhile (gaProjectileInfo[i].m_bInUse && i < ARRAY_SIZE(gaProjectileInfo)) i++;\n#endif\n\tif (i == ARRAY_SIZE(gaProjectileInfo))\n\t\treturn false;\n\n\tswitch (weapon)\n\t{\n\t\tcase WEAPONTYPE_ROCKET:\n\t\tms_apProjectile[i] = new CProjectile(MI_MISSILE);\n\t\tbreak;\n\t\tcase WEAPONTYPE_TEARGAS:\n\t\tms_apProjectile[i] = new CProjectile(MI_TEARGAS);\n\t\tbreak;\n\t\tcase WEAPONTYPE_MOLOTOV:\n\t\tms_apProjectile[i] = new CProjectile(MI_MOLOTOV);\n\t\tbreak;\n\t\tcase WEAPONTYPE_GRENADE:\n\t\tcase WEAPONTYPE_DETONATOR_GRENADE:\n\t\tms_apProjectile[i] = new CProjectile(MI_GRENADE);\n\t\tbreak;\n\t\tdefault: break;\n\t}\n\n\tif (ms_apProjectile[i] == nil)\n\t\treturn false;\n\n\tgaProjectileInfo[i].m_eWeaponType = weapon;\n\tgaProjectileInfo[i].m_pSource = ped;\n\tms_apProjectile[i]->GetMatrix() = matrix;\n\tms_apProjectile[i]->SetMoveSpeed(velocity);\n\tms_apProjectile[i]->bAffectedByGravity = gravity;\n\n\tgaProjectileInfo[i].m_nExplosionTime = time;\n\tms_apProjectile[i]->m_fElasticity = elasticity;\n\tms_apProjectile[i]->m_nSpecialCollisionResponseCases = SpecialCollisionResponseCase;\n\n#ifdef SQUEEZE_PERFORMANCE\n\tprojectileInUse++;\n#endif\n\n\tgaProjectileInfo[i].m_bInUse = true;\n\tCWorld::Add(ms_apProjectile[i]);\n\n\tgaProjectileInfo[i].m_vecPos = ms_apProjectile[i]->GetPosition();\n\n\tif (entity && entity->IsPed() && !ped->m_pCollidingEntity) {\n\t\tped->m_pCollidingEntity = ms_apProjectile[i];\n\t}\n\treturn true;\n}\n\nvoid\nCProjectileInfo::RemoveProjectile(CProjectileInfo *info, CProjectile *projectile)\n{\n\t// TODO(Miami): New parameter: 1\n\tswitch (info->m_eWeaponType) {\n\t\tcase WEAPONTYPE_GRENADE:\n\t\t\tCExplosion::AddExplosion(nil, info->m_pSource, EXPLOSION_GRENADE, projectile->GetPosition(), 0);\n\t\t\tbreak;\n\t\tcase WEAPONTYPE_MOLOTOV:\n\t\t\tCExplosion::AddExplosion(nil, info->m_pSource, EXPLOSION_MOLOTOV, projectile->GetPosition(), 0);\n\t\t\tbreak;\n\t\tcase WEAPONTYPE_ROCKET:\n\t\t\tCExplosion::AddExplosion(nil, info->m_pSource->IsVehicle() ? ((CVehicle*)info->m_pSource)->pDriver : info->m_pSource, EXPLOSION_ROCKET, projectile->GetPosition(), 0);\n\t\t\tbreak;\n\t}\n#ifdef SQUEEZE_PERFORMANCE\n\tprojectileInUse--;\n#endif\n\n\tinfo->m_bInUse = false;\n\tCWorld::Remove(projectile);\n\tdelete projectile;\n}\n\nvoid\nCProjectileInfo::RemoveNotAdd(CEntity *entity, eWeaponType weaponType, CVector pos)\n{\n\t// TODO(Miami): New parameter: 1\n\tswitch (weaponType) {\n\t\tcase WEAPONTYPE_GRENADE:\n\t\t\tCExplosion::AddExplosion(nil, entity, EXPLOSION_GRENADE, pos, 0);\n\t\t\tbreak;\n\t\tcase WEAPONTYPE_MOLOTOV:\n\t\t\tCExplosion::AddExplosion(nil, entity, EXPLOSION_MOLOTOV, pos, 0);\n\t\t\tbreak;\n\t\tcase WEAPONTYPE_ROCKET:\n\t\t\tCExplosion::AddExplosion(nil, entity, EXPLOSION_ROCKET, pos, 0);\n\t\t\tbreak;\n\t}\n}\n\nvoid\nCProjectileInfo::Update()\n{\n#ifdef SQUEEZE_PERFORMANCE\n\tif (projectileInUse == 0)\n\t\treturn;\n#endif\n\n\tint tearGasOffset = -0.0f; // unused\n\t\n\tfor (int i = 0; i < ARRAY_SIZE(gaProjectileInfo); i++) {\n\t\tif (!gaProjectileInfo[i].m_bInUse) continue;\n\n\t\tCPed *ped = (CPed*)gaProjectileInfo[i].m_pSource;\n\t\tif (ped != nil && ped->IsPed() && !ped->IsPointerValid())\n\t\t\tgaProjectileInfo[i].m_pSource = nil;\n\n\t\tif (ms_apProjectile[i] == nil) {\n#ifdef SQUEEZE_PERFORMANCE\n\t\t\tprojectileInUse--;\n#endif\n\n\t\t\tgaProjectileInfo[i].m_bInUse = false;\n\t\t\tcontinue;\n\t\t}\n\t\tif ( (gaProjectileInfo[i].m_eWeaponType == WEAPONTYPE_DETONATOR_GRENADE || gaProjectileInfo[i].m_eWeaponType == WEAPONTYPE_TEARGAS) && ms_apProjectile[i]->m_fElasticity > 0.1f ) {\n\t\t\tif ( Abs(ms_apProjectile[i]->m_vecMoveSpeed.x) < 0.05f && Abs(ms_apProjectile[i]->m_vecMoveSpeed.y) < 0.05f && Abs(ms_apProjectile[i]->m_vecMoveSpeed.z) < 0.05f ) {\n\t\t\t\tms_apProjectile[i]->m_fElasticity = 0.03f;\n\t\t\t}\n\t\t}\n\t\tconst CVector &projectilePos = ms_apProjectile[i]->GetPosition();\n\t\tCVector nextPos = CTimer::GetTimeStep() * ms_apProjectile[i]->m_vecMoveSpeed + projectilePos;\n\n\t\tif ( nextPos.x <= PROJECTILE_BOUNDARY_MIN_X || nextPos.x >= PROJECTILE_BOUNDARY_MAX_X || nextPos.y <= PROJECTILE_BOUNDARY_MIN_Y || nextPos.y >= PROJECTILE_BOUNDARY_MAX_Y ) {\n\t\t\t// Not RemoveProjectile, because we don't want no explosion\n\t\t\tgaProjectileInfo[i].m_bInUse = false;\n\t\t\tCWorld::Remove(ms_apProjectile[i]);\n\t\t\tdelete ms_apProjectile[i];\n        \tcontinue;\n\t\t}\n\t\tif ( gaProjectileInfo[i].m_eWeaponType == WEAPONTYPE_TEARGAS && CTimer::GetTimeInMilliseconds() > gaProjectileInfo[i].m_nExplosionTime - 19500 ) {\n\t\t\tCParticle::AddParticle(PARTICLE_TEARGAS, projectilePos, CVector(0.2f, tearGasOffset, 0.0f), 0, 0.0f, 0, 0, 0, 0);\n\t\t\tCParticle::AddParticle(PARTICLE_TEARGAS, projectilePos, CVector(-0.2f, tearGasOffset, 0.0f), 0, 0.0f, 0, 0, 0, 0);\n\t\t\tCParticle::AddParticle(PARTICLE_TEARGAS, projectilePos, CVector(tearGasOffset, tearGasOffset, 0.0f), 0, 0.0f, 0, 0, 0, 0);\n\n\t\t\tif ( CTimer::GetTimeInMilliseconds() & 0x200 )\n\t\t\t\tCWorld::SetPedsChoking(projectilePos.x, projectilePos.y, projectilePos.z, 6.0f, gaProjectileInfo[i].m_pSource);\n\t\t}\n\n\t\tif (gaProjectileInfo[i].m_eWeaponType == WEAPONTYPE_ROCKET) {\n\t\t\tCParticle::AddParticlesAlongLine(PARTICLE_ROCKET_SMOKE, gaProjectileInfo[i].m_vecPos, projectilePos, CVector(0.0f, 0.0f, 0.0f), 0.7f, 0, 0, 0, 3000);\n\t\t}\n\n\t\tif (CTimer::GetTimeInMilliseconds() <= gaProjectileInfo[i].m_nExplosionTime || gaProjectileInfo[i].m_nExplosionTime == 0) {\n\t\t\tif (gaProjectileInfo[i].m_eWeaponType == WEAPONTYPE_ROCKET) {\n\t\t\t\tCVector pos = ms_apProjectile[i]->GetPosition();\n\t\t\t\tCWorld::pIgnoreEntity = ms_apProjectile[i];\n\t\t\t\tif (ms_apProjectile[i]->bHasCollided\n\t\t\t\t\t|| !CWorld::GetIsLineOfSightClear(gaProjectileInfo[i].m_vecPos, pos, true, true, true, true, false, false)\n\t\t\t\t\t|| CHeli::TestRocketCollision(&pos) || CPlane::TestRocketCollision(&pos)) {\n\t\t\t\t\tRemoveProjectile(&gaProjectileInfo[i], ms_apProjectile[i]);\n\t\t\t\t}\n\t\t\t\tCWorld::pIgnoreEntity = nil;\n\t\t\t\tms_apProjectile[i]->m_vecMoveSpeed *= 1.07f;\n\n\t\t\t} else if (gaProjectileInfo[i].m_eWeaponType == WEAPONTYPE_MOLOTOV) {\n\t\t\t\tCVector pos = ms_apProjectile[i]->GetPosition();\n\t\t\t\tCWorld::pIgnoreEntity = ms_apProjectile[i];\n\n\t\t\t\tif (gaProjectileInfo[i].m_pSource == nil \n\t\t\t\t\t|| ((gaProjectileInfo[i].m_vecPos - gaProjectileInfo[i].m_pSource->GetPosition()).MagnitudeSqr() >= 2.0f))\n\t\t\t\t{\n\t\t\t\t\tif (ms_apProjectile[i]->bHasCollided\n\t\t\t\t\t\t|| !CWorld::GetIsLineOfSightClear(gaProjectileInfo[i].m_vecPos, pos, true, true, true, true, false, false)) {\n\t\t\t\t\t\tRemoveProjectile(&gaProjectileInfo[i], ms_apProjectile[i]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tCWorld::pIgnoreEntity = nil;\n\t\t\t}\n\t\t} else {\n\t\t\tif (gaProjectileInfo[i].m_eWeaponType == WEAPONTYPE_DETONATOR_GRENADE) {\n\t\t\t\tCEntity *ent = gaProjectileInfo[i].m_pSource;\n\t\t\t\tif (ent->IsPed() && ((CPed*)ped)->IsPlayer()) {\n\t\t\t\t\tCPed *ped = (CPed*)ent;\n\t\t\t\t\tif (ped->GetWeapon(ped->GetWeaponSlot(WEAPONTYPE_DETONATOR)).m_eWeaponType != WEAPONTYPE_DETONATOR\n\t\t\t\t\t\t|| ped->GetWeapon(ped->GetWeaponSlot(WEAPONTYPE_DETONATOR)).m_nAmmoTotal == 0) {\n\t\t\t\t\t\tgaProjectileInfo[i].m_nExplosionTime = 0;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tRemoveProjectile(&gaProjectileInfo[i], ms_apProjectile[i]);\n\t\t\t}\n\t\t}\n\n\t\tgaProjectileInfo[i].m_vecPos = ms_apProjectile[i]->GetPosition();\n\t}\n}\n\nbool\nCProjectileInfo::IsProjectileInRange(float x1, float x2, float y1, float y2, float z1, float z2, bool remove)\n{\n\tbool result = false;\n\tfor (int i = 0; i < ARRAY_SIZE(ms_apProjectile); i++) {\n\t\tif (gaProjectileInfo[i].m_bInUse) {\n\t\t\tif (gaProjectileInfo[i].m_eWeaponType == WEAPONTYPE_ROCKET || gaProjectileInfo[i].m_eWeaponType == WEAPONTYPE_MOLOTOV || gaProjectileInfo[i].m_eWeaponType == WEAPONTYPE_GRENADE) {\n\t\t\t\tconst CVector &pos = ms_apProjectile[i]->GetPosition();\n\t\t\t\tif (pos.x >= x1 && pos.x <= x2 && pos.y >= y1 && pos.y <= y2 && pos.z >= z1 && pos.z <= z2) {\n\t\t\t\t\tresult = true;\n\t\t\t\t\tif (remove) {\n#ifdef SQUEEZE_PERFORMANCE\n\t\t\t\t\t\tprojectileInUse--;\n#endif\n\n\t\t\t\t\t\tgaProjectileInfo[i].m_bInUse = false;\n\t\t\t\t\t\tCWorld::Remove(ms_apProjectile[i]);\n\t\t\t\t\t\tdelete ms_apProjectile[i];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn result;\n}\n\nvoid\nCProjectileInfo::RemoveDetonatorProjectiles()\n{\n\tfor (int i = 0; i < ARRAY_SIZE(ms_apProjectile); i++) {\n\t\tif (gaProjectileInfo[i].m_bInUse && gaProjectileInfo[i].m_eWeaponType == WEAPONTYPE_DETONATOR_GRENADE) {\n\t\t\tCExplosion::AddExplosion(nil, gaProjectileInfo[i].m_pSource, EXPLOSION_GRENADE, gaProjectileInfo[i].m_vecPos, 0); // TODO(Miami): New parameter: 1\n\t\t\tgaProjectileInfo[i].m_bInUse = false;\n\t\t\tCWorld::Remove(ms_apProjectile[i]);\n\t\t\tdelete ms_apProjectile[i];\n\t\t}\n\t}\n}\n\nvoid\nCProjectileInfo::RemoveAllProjectiles()\n{\n#ifdef SQUEEZE_PERFORMANCE\n\tif (projectileInUse == 0)\n\t\treturn;\n#endif\n\n\tfor (int i = 0; i < ARRAY_SIZE(ms_apProjectile); i++) {\n\t\tif (gaProjectileInfo[i].m_bInUse) {\n#ifdef SQUEEZE_PERFORMANCE\n\t\t\tprojectileInUse--;\n#endif\n\n\t\t\tgaProjectileInfo[i].m_bInUse = false;\n\t\t\tCWorld::Remove(ms_apProjectile[i]);\n\t\t\tdelete ms_apProjectile[i];\n\t\t}\n\t}\n}\n\nbool\nCProjectileInfo::RemoveIfThisIsAProjectile(CObject *object)\n{\n#ifdef SQUEEZE_PERFORMANCE\n\tif (projectileInUse == 0)\n\t\treturn false;\n#endif\n\n\tint i = 0;\n\twhile (ms_apProjectile[i++] != object) {\n\t\tif (i >= ARRAY_SIZE(ms_apProjectile))\n\t\t\treturn false;\n\t}\n\n#ifdef SQUEEZE_PERFORMANCE\n\tprojectileInUse--;\n#endif\n\n\tgaProjectileInfo[i].m_bInUse = false;\n\tCWorld::Remove(ms_apProjectile[i]);\n\tdelete ms_apProjectile[i];\n\tms_apProjectile[i] = nil;\n\treturn true;\n}\n"
  },
  {
    "path": "src/weapons/ProjectileInfo.h",
    "content": "#pragma once\n\n#include \"WeaponType.h\"\n\nclass CEntity;\nclass CObject;\nclass CProjectile;\n\nclass CProjectileInfo\n{\npublic:\n\teWeaponType m_eWeaponType;\n\tCEntity *m_pSource;\n\tuint32 m_nExplosionTime;\n\tbool m_bInUse;\n\tCVector m_vecPos;\n\npublic:\n\tstatic CProjectileInfo *GetProjectileInfo(int32 id);\n\tstatic CProjectile *ms_apProjectile[NUM_PROJECTILES];\n\n\tstatic void Initialise();\n\tstatic void Shutdown();\n\tstatic bool AddProjectile(CEntity *ped, eWeaponType weapon, CVector pos, float speed);\n\tstatic void RemoveProjectile(CProjectileInfo *info, CProjectile *projectile);\n\tstatic void RemoveNotAdd(CEntity *entity, eWeaponType weaponType, CVector pos);\n\tstatic bool RemoveIfThisIsAProjectile(CObject *pObject);\n\tstatic void RemoveAllProjectiles();\n\tstatic void RemoveDetonatorProjectiles();\n\tstatic void Update();\n\tstatic bool IsProjectileInRange(float x1, float x2, float y1, float y2, float z1, float z2, bool remove);\n};\n\nextern CProjectileInfo gaProjectileInfo[NUM_PROJECTILES];"
  },
  {
    "path": "src/weapons/ShotInfo.cpp",
    "content": "#include \"common.h\"\n\n#include \"ShotInfo.h\"\n#include \"Entity.h\"\n#include \"Weapon.h\"\n#include \"World.h\"\n#include \"WeaponInfo.h\"\n#include \"General.h\"\n#include \"Timer.h\"\n#include \"Ped.h\"\n#include \"Fire.h\"\n\nCShotInfo gaShotInfo[NUMSHOTINFOS];\nfloat CShotInfo::ms_afRandTable[20];\n\n#ifdef SQUEEZE_PERFORMANCE\nuint32 shotInfoInUse;\n#endif\n\n/*\n\tUsed for flamethrower. I don't know why it's name is CShotInfo.\n\tHas no relation with any visual, just calculates the area fire affects\n\t(including spreading and slowing of fire) and make entities burn/flee.\n*/\n\nvoid\nCShotInfo::Initialise()\n{\n\tdebug(\"Initialising CShotInfo...\\n\");\n\tfor(int i=0; i<ARRAY_SIZE(gaShotInfo); i++) {\n\t\tgaShotInfo[i].m_inUse = false;\n\t\tgaShotInfo[i].m_weapon = WEAPONTYPE_COLT45;\n\t\tgaShotInfo[i].m_startPos = CVector(0.0f, 0.0f, 0.0f);\n\t\tgaShotInfo[i].m_areaAffected = CVector(0.0f, 0.0f, 0.0f);\n\t\tgaShotInfo[i].m_radius = 1.0f;\n\t\tgaShotInfo[i].m_sourceEntity = nil;\n\t\tgaShotInfo[i].m_timeout = 0;\n\t}\n\n\t// Not random for sure\n\tfloat nextVal = -0.05f;\n\tfor (int i = 0; i < ARRAY_SIZE(ms_afRandTable); i++) {\n\t\tms_afRandTable[i] = nextVal;\n\t\tnextVal += 0.005f;\n\t}\n\tdebug(\"CShotInfo ready\\n\");\n#ifdef SQUEEZE_PERFORMANCE\n\tshotInfoInUse = 0;\n#endif\n}\n\nbool\nCShotInfo::AddShot(CEntity *sourceEntity, eWeaponType weapon, CVector startPos, CVector endPos)\n{\n\tCWeaponInfo *weaponInfo = CWeaponInfo::GetWeaponInfo(weapon);\n\n\tint slot;\n\tfor (slot = 0; slot < ARRAY_SIZE(gaShotInfo) && gaShotInfo[slot].m_inUse; slot++);\n\n\tif (slot == ARRAY_SIZE(gaShotInfo))\n\t\treturn false;\n\n#ifdef SQUEEZE_PERFORMANCE\n\tshotInfoInUse++;\n#endif\n\n\tgaShotInfo[slot].m_inUse = true;\n\tgaShotInfo[slot].m_weapon = weapon;\n\tgaShotInfo[slot].m_startPos = startPos;\n\tgaShotInfo[slot].m_areaAffected = endPos - startPos;\n\tgaShotInfo[slot].m_radius = weaponInfo->m_fRadius;\n\n\tif (weaponInfo->m_fSpread != 0.0f) {\n\t\tgaShotInfo[slot].m_areaAffected.x += CShotInfo::ms_afRandTable[CGeneral::GetRandomNumber() % ARRAY_SIZE(ms_afRandTable)] * weaponInfo->m_fSpread;\n\t\tgaShotInfo[slot].m_areaAffected.y += CShotInfo::ms_afRandTable[CGeneral::GetRandomNumber() % ARRAY_SIZE(ms_afRandTable)] * weaponInfo->m_fSpread;\n\t\tgaShotInfo[slot].m_areaAffected.z += CShotInfo::ms_afRandTable[CGeneral::GetRandomNumber() % ARRAY_SIZE(ms_afRandTable)];\n\t}\n\tgaShotInfo[slot].m_areaAffected.Normalise();\n\tif (weaponInfo->IsFlagSet(WEAPONFLAG_RAND_SPEED))\n\t\tgaShotInfo[slot].m_areaAffected *= CShotInfo::ms_afRandTable[CGeneral::GetRandomNumber() % ARRAY_SIZE(ms_afRandTable)] + weaponInfo->m_fSpeed;\n\telse\n\t\tgaShotInfo[slot].m_areaAffected *= weaponInfo->m_fSpeed;\n\n\tgaShotInfo[slot].m_sourceEntity = sourceEntity;\n\tgaShotInfo[slot].m_timeout = CTimer::GetTimeInMilliseconds() + weaponInfo->m_fLifespan;\n\n\treturn true;\n}\n\nvoid\nCShotInfo::Shutdown()\n{\n\tdebug(\"Shutting down CShotInfo...\\n\");\n\tdebug(\"CShotInfo shut down\\n\");\n}\n\nvoid\nCShotInfo::Update()\n{\n#ifdef SQUEEZE_PERFORMANCE\n\tif (shotInfoInUse == 0)\n\t\treturn;\n#endif\n\tfor (int slot = 0; slot < ARRAY_SIZE(gaShotInfo); slot++) {\n\t\tCShotInfo &shot = gaShotInfo[slot];\n\t\tif (shot.m_sourceEntity && shot.m_sourceEntity->IsPed() && !((CPed*)shot.m_sourceEntity)->IsPointerValid())\n\t\t\tshot.m_sourceEntity = nil;\n\n\t\tif (!shot.m_inUse)\n\t\t\tcontinue;\n\n\t\tCWeaponInfo *weaponInfo = CWeaponInfo::GetWeaponInfo(shot.m_weapon);\n\t\tif (CTimer::GetTimeInMilliseconds() > shot.m_timeout) {\n#ifdef SQUEEZE_PERFORMANCE\n\t\t\tshotInfoInUse--;\n#endif\n\t\t\tshot.m_inUse = false;\n\t\t}\n\n\t\tif (weaponInfo->IsFlagSet(WEAPONFLAG_SLOWS_DOWN))\n\t\t\tshot.m_areaAffected *= pow(0.96, CTimer::GetTimeStep()); // FRAMERATE\n\n\t\tif (weaponInfo->IsFlagSet(WEAPONFLAG_EXPANDS))\n\t\t\tshot.m_radius += 0.075f * CTimer::GetTimeStep();\n\n\t\tshot.m_startPos += CTimer::GetTimeStep() * shot.m_areaAffected;\n\t\tif (shot.m_sourceEntity) {\n\t\t\tassert(shot.m_sourceEntity->IsPed());\n\t\t\tCPed *ped = (CPed*) shot.m_sourceEntity;\n\t\t\tfloat radius = Max(1.0f, shot.m_radius);\n\n\t\t\tfor (int i = 0; i < ped->m_numNearPeds; ++i) {\n\t\t\t\tCPed *nearPed = ped->m_nearPeds[i];\n\t\t\t\tif (nearPed->IsPointerValid()) {\n\t\t\t\t\tif (nearPed->IsPedInControl() && (nearPed->GetPosition() - shot.m_startPos).MagnitudeSqr() < radius && !nearPed->bFireProof) {\n\n\t\t\t\t\t\tif (!nearPed->IsPlayer()) {\n\t\t\t\t\t\t\tnearPed->SetFindPathAndFlee(shot.m_sourceEntity, 10000);\n\t\t\t\t\t\t\tnearPed->SetMoveState(PEDMOVE_SPRINT);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tgFireManager.StartFire(nearPed, shot.m_sourceEntity, 0.8f, true);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (!((CTimer::GetFrameCounter() + slot) & 3))\n\t\t\tCWorld::SetCarsOnFire(shot.m_startPos.x, shot.m_startPos.y, shot.m_startPos.z, 4.0f, shot.m_sourceEntity);\n\t}\n}\n"
  },
  {
    "path": "src/weapons/ShotInfo.h",
    "content": "#pragma once\n\n#include \"WeaponType.h\"\n\nclass CEntity;\n\nclass CShotInfo\n{\npublic:\n\teWeaponType m_weapon;\n\tCVector m_startPos;\n\tCVector m_areaAffected;\n\tfloat m_radius;\n\tCEntity *m_sourceEntity;\n\tfloat m_timeout;\n\tbool m_inUse;\n\n\tstatic float ms_afRandTable[20];\n\n\tstatic void Initialise(void);\n\tstatic bool AddShot(CEntity*, eWeaponType, CVector, CVector);\n\tstatic void Shutdown(void);\n\tstatic void Update(void);\n};\n"
  },
  {
    "path": "src/weapons/Weapon.cpp",
    "content": "#include \"common.h\"\n\n#include \"Weapon.h\"\n#include \"AnimBlendAssociation.h\"\n#include \"AudioManager.h\"\n#include \"BulletInfo.h\"\n#include \"Camera.h\"\n#include \"Coronas.h\"\n#include \"DMAudio.h\"\n#include \"Explosion.h\"\n#include \"General.h\"\n#include \"Glass.h\"\n#include \"Heli.h\"\n#include \"ModelIndices.h\"\n#include \"Object.h\"\n#include \"Pad.h\"\n#include \"Particle.h\"\n#include \"Ped.h\"\n#include \"PointLights.h\"\n#include \"Pools.h\"\n#include \"ProjectileInfo.h\"\n#include \"RpAnimBlend.h\"\n#include \"ShotInfo.h\"\n#include \"SpecialFX.h\"\n#include \"Stats.h\"\n#include \"TempColModels.h\"\n#include \"Timer.h\"\n#include \"Automobile.h\"\n#include \"Boat.h\"\n#include \"WaterLevel.h\"\n#include \"WeaponInfo.h\"\n#include \"World.h\"\n#include \"SurfaceTable.h\"\n#include \"Bike.h\"\n#include \"Glass.h\"\n#include \"Sprite.h\"\n#include \"Pickups.h\"\n\nfloat fReloadAnimSampleFraction[5] = {  0.5f,  0.7f,  0.75f,  0.75f,  0.7f };\nfloat fSeaSparrowAimingAngle = 10.0f;\nfloat fHunterAimingAngle = 30.0f;\nfloat fPlayerAimScaleDist = 5.0f; \nfloat fPlayerAimScale = 2.5f;\n\nbool CWeapon::bPhotographHasBeenTaken;\n\n#ifdef SECUROM\nint32 sniperPirateCheck = 0x00797743; // 'Cwy\\0' ???\n#endif\n\nCWeaponInfo *\nCWeapon::GetInfo()\n{\n\tCWeaponInfo *info = CWeaponInfo::GetWeaponInfo(m_eWeaponType);\n\tASSERT(info!=nil);\n\treturn info;\n}\n\nCWeapon::CWeapon(eWeaponType type, int32 ammo)\n{\n\tm_eWeaponType = type;\n\tm_eWeaponState = WEAPONSTATE_READY;\n\tm_nAmmoTotal = Min(ammo, 99999);\n\tm_nAmmoInClip = 0;\n\tReload();\n\tm_nTimer = 0;\n\tm_bAddRotOffset = false;\n}\n\nvoid\nCWeapon::InitialiseWeapons(void)\n{\n\tCWeaponInfo::Initialise();\n\tCShotInfo::Initialise();\n\tCExplosion::Initialise();\n\tCProjectileInfo::Initialise();\n\tCBulletInfo::Initialise();\n\tbPhotographHasBeenTaken = false;\n}\n\nvoid\nCWeapon::ShutdownWeapons(void)\n{\n\tCWeaponInfo::Shutdown();\n\tCShotInfo::Shutdown();\n\tCExplosion::Shutdown();\n\tCProjectileInfo::Shutdown();\n\tCBulletInfo::Shutdown();\n}\n\nvoid\nCWeapon::UpdateWeapons(void)\n{\n\tCShotInfo::Update();\n\tCExplosion::Update();\n\tCProjectileInfo::Update();\n\tCBulletInfo::Update();\n}\n\n\nvoid\nCWeapon::Initialise(eWeaponType type, int32 ammo)\n{\n\tm_eWeaponType = type;\n\tm_eWeaponState = WEAPONSTATE_READY;\n\tm_nAmmoTotal = Min(ammo, 99999);\n\tm_nAmmoInClip = 0;\n\tReload();\n\tm_nTimer = 0;\n\tint32 modelId = CWeaponInfo::GetWeaponInfo(m_eWeaponType)->m_nModelId;\n\tint32 model2Id = CWeaponInfo::GetWeaponInfo(m_eWeaponType)->m_nModel2Id;\n\t\n\tif ( modelId != -1 )\n\t\tCModelInfo::GetModelInfo(modelId)->AddRef();\n\tif ( model2Id != -1 )\n\t\tCModelInfo::GetModelInfo(model2Id)->AddRef();\n}\n\nvoid\nCWeapon::Shutdown()\n{\n\tint32 modelId = CWeaponInfo::GetWeaponInfo(m_eWeaponType)->m_nModelId;\n\tif (modelId != -1)\n\t\tCModelInfo::GetModelInfo(modelId)->RemoveRef();\n\n\tint32 model2Id = CWeaponInfo::GetWeaponInfo(m_eWeaponType)->m_nModel2Id;\n\tif (model2Id != -1)\n\t\tCModelInfo::GetModelInfo(model2Id)->RemoveRef();\n\n\tm_eWeaponType = WEAPONTYPE_UNARMED;\n\tm_eWeaponState = WEAPONSTATE_READY;\n\tm_nAmmoInClip = 0;\n\tm_nAmmoTotal = 0;\n\tm_nTimer = 0;\n}\n\nbool\nCWeapon::Fire(CEntity *shooter, CVector *fireSource)\n{\n\tASSERT(shooter!=nil);\n\n\tCVector fireOffset(0.0f, 0.0f, 0.6f);\n\tCVector *source = fireSource;\n#ifdef FIX_BUGS\n\tstatic CVector shooterSource;\n#else\n\tCVector shooterSource;\n#endif\n\n\tif ( !fireSource )\n\t{\n\t\tshooterSource = shooter->GetMatrix() * fireOffset;\n\t\tsource = &shooterSource;\n\t}\n\t\t\n\tif ( m_bAddRotOffset )\n\t{\n\t\tfloat heading = RADTODEG(shooter->GetForward().Heading());\n\t\tfloat angle   = DEGTORAD(heading);\n\t\t(*source).x += -Sin(angle) * 0.15f;\n\t\t(*source).y +=  Cos(angle) * 0.15f;\n\t}\n\n\tif ( m_eWeaponState != WEAPONSTATE_READY && m_eWeaponState != WEAPONSTATE_FIRING )\n\t\treturn false;\n\n\tbool fired;\n\tbool addFireRateAsDelay = true;\n\n\tif ( GetInfo()->m_eWeaponFire != WEAPON_FIRE_MELEE )\n\t{\n\t\tif (m_nAmmoInClip <= 0) {\n\t\t\tif (m_nAmmoTotal <= 0 || m_eWeaponState == WEAPONSTATE_RELOADING)\n\t\t\t\treturn false;\n\n\t\t\tReload();\n\t\t}\n\n\t\tswitch ( m_eWeaponType )\n\t\t{\n\t\t\tcase WEAPONTYPE_SHOTGUN:\n\t\t\tcase WEAPONTYPE_SPAS12_SHOTGUN:\n\t\t\tcase WEAPONTYPE_STUBBY_SHOTGUN:\n\t\t\t{\n\t\t\t\taddFireRateAsDelay = true;\n\t\t\t\tfired = FireShotgun(shooter, source);\n\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase WEAPONTYPE_SNIPERRIFLE:\n\t\t\tcase WEAPONTYPE_LASERSCOPE:\n\t\t\t{\n\t\t\t\tif (shooter == FindPlayerPed())\n\t\t\t\t\tfired = FireSniper(shooter);\n\t\t\t\telse\n\t\t\t\t\tfired = FireInstantHit(shooter, source);\n\t\t\t\t\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t\n\t\t\tcase WEAPONTYPE_COLT45:\n\t\t\tcase WEAPONTYPE_PYTHON:\n\t\t\tcase WEAPONTYPE_UZI:\n\t\t\tcase WEAPONTYPE_TEC9:\n\t\t\tcase WEAPONTYPE_SILENCED_INGRAM:\n\t\t\tcase WEAPONTYPE_MP5:\n\t\t\tcase WEAPONTYPE_M4:\n\t\t\tcase WEAPONTYPE_RUGER:\n\t\t\tcase WEAPONTYPE_M60:\n\t\t\tcase WEAPONTYPE_MINIGUN:\n\t\t\tcase WEAPONTYPE_HELICANNON:\n\t\t\t{\n\t\t\t\tif ((TheCamera.PlayerWeaponMode.Mode == CCam::MODE_HELICANNON_1STPERSON || TheCamera.PlayerWeaponMode.Mode == CCam::MODE_M16_1STPERSON)\n\t\t\t\t\t&& shooter == FindPlayerPed()) {\n\t\t\t\t\taddFireRateAsDelay = true;\n\t\t\t\t\tfired = FireM16_1stPerson(shooter);\n\t\t\t\t} else {\n\t\t\t\t\taddFireRateAsDelay = false;\n\t\t\t\t\tfired = FireInstantHit(shooter, source);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase WEAPONTYPE_ROCKETLAUNCHER:\n\t\t\t{\n\t\t\t\tif ( shooter->IsPed() && ((CPed*)shooter)->m_pSeekTarget != nil )\n\t\t\t\t{\n\t\t\t\t\tfloat distToTarget = (shooter->GetPosition() - ((CPed*)shooter)->m_pSeekTarget->GetPosition()).Magnitude();\n\n\t\t\t\t\tif ( distToTarget > 8.0f || ((CPed*)shooter)->IsPlayer() )\n\t\t\t\t\t\tfired = FireProjectile(shooter, source, 0.0f);\n\t\t\t\t\telse\n\t\t\t\t\t\tfired = false;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\tfired = FireProjectile(shooter, source, 0.0f);\n\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase WEAPONTYPE_MOLOTOV:\n\t\t\tcase WEAPONTYPE_GRENADE:\n\t\t\tcase WEAPONTYPE_DETONATOR_GRENADE:\n\t\t\tcase WEAPONTYPE_TEARGAS:\n\t\t\t{\n\t\t\t\tif ( shooter == FindPlayerPed() )\n\t\t\t\t{\n\t\t\t\t\tfired = FireProjectile(shooter, source, ((CPlayerPed*)shooter)->m_fAttackButtonCounter*0.0375f);\n\t\t\t\t}\n\t\t\t\telse if ( shooter->IsPed() && ((CPed*)shooter)->m_pSeekTarget != nil )\n\t\t\t\t{\n\t\t\t\t\tfloat distToTarget = (shooter->GetPosition() - ((CPed*)shooter)->m_pSeekTarget->GetPosition()).Magnitude();\n\t\t\t\t\tfloat power = clamp((distToTarget-10.0f)*0.02f, 0.2f, 1.0f);\n\n\t\t\t\t\tfired = FireProjectile(shooter, source, power);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\tfired = FireProjectile(shooter, source, 0.3f);\n\n\t\t\t\tif (m_eWeaponType == WEAPONTYPE_DETONATOR_GRENADE) {\n\t\t\t\t\t((CPed*)shooter)->GiveWeapon(WEAPONTYPE_DETONATOR, 1, true);\n\t\t\t\t\t((CPed*)shooter)->GetWeapon(((CPed*)shooter)->GetWeaponSlot(WEAPONTYPE_DETONATOR)).m_eWeaponState = WEAPONSTATE_READY;\n\t\t\t\t\t((CPed*)shooter)->SetCurrentWeapon(WEAPONTYPE_DETONATOR);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase WEAPONTYPE_FLAMETHROWER:\n\t\t\t{\n\t\t\t\tfired = FireAreaEffect(shooter, source);\n\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase WEAPONTYPE_DETONATOR:\n\t\t\t{\n\t\t\t\tCWorld::UseDetonator(shooter);\n\t\t\t\tm_nAmmoTotal  = 1;\n\t\t\t\tm_nAmmoInClip = m_nAmmoTotal;\n\t\t\t\tfired = true;\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t\n\t\t\tcase WEAPONTYPE_CAMERA:\n\t\t\t{\n\t\t\t\tfired = TakePhotograph(shooter);\n\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tdefault:\n\t\t\t{\n\t\t\t\tdebug(\"Unknown weapon type, Weapon.cpp\");\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif (fired)\n\t\t{\n\t\t\tbool isPlayer = false;\n\n\t\t\tif (shooter->IsPed())\n\t\t\t{\n\t\t\t\tCPed* shooterPed = (CPed*)shooter;\n\t\t\t\t\n\t\t\t\tif ( m_eWeaponType != WEAPONTYPE_CAMERA )\n\t\t\t\t{\n\t\t\t\t\tshooterPed->bIsShooting = true;\n\t\n\t\t\t\t\tif (shooterPed->IsPlayer())\n\t\t\t\t\t\tisPlayer = true;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tDMAudio.PlayOneShot(shooterPed->m_audioEntityId, SOUND_WEAPON_SHOT_FIRED, 0.0f);\n\t\t\t\t\n\t\t\t\tif ( isPlayer )\n\t\t\t\t{\n\t\t\t\t\tCPed *aimPed = (CPed *)shooterPed->m_pSeekTarget;\n\t\t\t\t\tif ( aimPed )\n\t\t\t\t\t{\n\t\t\t\t\t\tif ( aimPed->IsPed() )\n\t\t\t\t\t\t\tshooterPed->Say(SOUND_PED_ON_FIRE);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tswitch ( m_eWeaponType )\n\t\t\t{\n\t\t\t\tcase WEAPONTYPE_COLT45:\n\t\t\t\tcase WEAPONTYPE_PYTHON:\n\t\t\t\tcase WEAPONTYPE_SHOTGUN:\n\t\t\t\tcase WEAPONTYPE_SPAS12_SHOTGUN:\n\t\t\t\tcase WEAPONTYPE_STUBBY_SHOTGUN:\n\t\t\t\tcase WEAPONTYPE_TEC9:\n\t\t\t\tcase WEAPONTYPE_UZI:\n\t\t\t\tcase WEAPONTYPE_SILENCED_INGRAM:\n\t\t\t\tcase WEAPONTYPE_MP5:\n\t\t\t\tcase WEAPONTYPE_M4:\n\t\t\t\tcase WEAPONTYPE_RUGER:\n\t\t\t\tcase WEAPONTYPE_SNIPERRIFLE:\n\t\t\t\tcase WEAPONTYPE_LASERSCOPE:\n\t\t\t\tcase WEAPONTYPE_M60:\n\t\t\t\tcase WEAPONTYPE_MINIGUN:\n\t\t\t\t\tCStats::RoundsFiredByPlayer++;\n\t\t\t\t\tbreak;\n\t\t\t\t\t\n\t\t\t\tcase WEAPONTYPE_GRENADE:\n\t\t\t\tcase WEAPONTYPE_DETONATOR_GRENADE:\n\t\t\t\tcase WEAPONTYPE_MOLOTOV:\n\t\t\t\tcase WEAPONTYPE_ROCKET:\n\t\t\t\tcase WEAPONTYPE_ROCKETLAUNCHER:\n\t\t\t\tcase WEAPONTYPE_DETONATOR:\n\t\t\t\tcase WEAPONTYPE_HELICANNON:\n\t\t\t\t\tCStats::KgsOfExplosivesUsed++;\n\t\t\t\t\tbreak;\n\t\t\t}\n\t  \n\n\t\t\tif (m_nAmmoInClip > 0)\n\t\t\t\tm_nAmmoInClip--;\n\n\t\t\tif (m_nAmmoTotal > 0 && (m_nAmmoTotal < 25000 || isPlayer) && (!isPlayer || CStats::GetPercentageProgress() < 100.0f || m_eWeaponType == WEAPONTYPE_DETONATOR))\n\t\t\t\tm_nAmmoTotal--;\n\n\t\t\tif (m_eWeaponState == WEAPONSTATE_READY && m_eWeaponType == WEAPONTYPE_FLAMETHROWER)\n\t\t\t\tDMAudio.PlayOneShot(((CPhysical*)shooter)->m_audioEntityId, SOUND_WEAPON_FLAMETHROWER_FIRE, 0.0f);\n\n\t\t\tm_eWeaponState = WEAPONSTATE_FIRING;\n\n\t\t\tif (m_nAmmoInClip == 0)\n\t\t\t{\n\t\t\t\tif (m_nAmmoTotal == 0) {\n\t\t\t\t\tif (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_CAMERA)\n\t\t\t\t\t\tCPad::GetPad(0)->Clear(false);\n\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\tm_eWeaponState = WEAPONSTATE_RELOADING;\n\t\t\t\tm_nTimer = CTimer::GetTimeInMilliseconds() + GetInfo()->m_nReload;\n\n\t\t\t\tif (shooter == FindPlayerPed())\n\t\t\t\t{\n\t\t\t\t\tif (CWorld::Players[CWorld::PlayerInFocus].m_bFastReload)\n\t\t\t\t\t\tm_nTimer = CTimer::GetTimeInMilliseconds() + GetInfo()->m_nReload / 4;\n\t\t\t\t}\n\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\tif ( addFireRateAsDelay )\n\t\t\t\tm_nTimer = CTimer::GetTimeInMilliseconds() + GetInfo()->m_nFiringRate;\n\t\t\telse\n\t\t\t\tm_nTimer = CTimer::GetTimeInMilliseconds();\n\t\t}\n\t}\n\telse\n\t{\n\t\tif ( m_eWeaponState != WEAPONSTATE_FIRING )\n\t\t{\n\t\t\tm_nTimer = CTimer::GetTimeInMilliseconds() + GetInfo()->m_nReload;\n\t\t\tm_eWeaponState = WEAPONSTATE_FIRING;\n\n\t\t\tif (shooter->IsPed() && m_eWeaponType != WEAPONTYPE_CHAINSAW)\n\t\t\t{\n\t\t\t\tDMAudio.PlayOneShot(((CPed*)shooter)->m_audioEntityId, SOUND_MELEE_ATTACK_START, m_eWeaponType << 8);\n\t\t\t}\n\t\t}\n\n\t\tfired = FireMelee(shooter, *source);\n\t}\n\n\tif ( m_eWeaponType == WEAPONTYPE_UNARMED || m_eWeaponType == WEAPONTYPE_BASEBALLBAT )\n\t\treturn true;\n\telse\n\t\treturn fired;\n}\n\nbool\nCWeapon::FireFromCar(CVehicle *shooter, bool left, bool right)\n{\n\tASSERT(shooter!=nil);\n\n\tif ( m_eWeaponState != WEAPONSTATE_READY && m_eWeaponState != WEAPONSTATE_FIRING )\n\t\treturn false;\n\n\tif ( m_nAmmoInClip <= 0 )\n\t\treturn false;\n\n\tif ( FireInstantHitFromCar(shooter, left, right) )\n\t{\n\t\tDMAudio.PlayOneShot(shooter->m_audioEntityId, SOUND_WEAPON_SHOT_FIRED, 0.0f);\n\n\t\tif ( m_nAmmoInClip > 0 )\n\t\t\tm_nAmmoInClip--;\n\n\t\tif ( m_nAmmoTotal < 25000 && m_nAmmoTotal > 0 && (!shooter || shooter->GetStatus() != STATUS_PLAYER || CStats::GetPercentageProgress() < 100.f))\n\t\t\tm_nAmmoTotal--;\n\n\t\tm_eWeaponState = WEAPONSTATE_FIRING;\n\n\t\tif ( m_nAmmoInClip == 0 )\n\t\t{\n\t\t\tif ( m_nAmmoTotal == 0 )\n\t\t\t\treturn true;\n\n\t\t\tm_eWeaponState = WEAPONSTATE_RELOADING;\n\t\t\tm_nTimer = CTimer::GetTimeInMilliseconds() + GetInfo()->m_nReload;\n\n\t\t\treturn true;\n\t\t}\n\n\t\tm_nTimer = CTimer::GetTimeInMilliseconds() + 1000;\n\t}\n\n\treturn true;\n}\n\nbool\nCWeapon::FireMelee(CEntity *shooter, CVector &fireSource)\n{\n\tASSERT(shooter!=nil);\n\n\tCWeaponInfo *info = GetInfo();\n\n\tbool anim2Playing = false;\n\t\n\tif ( CPed::GetFireAnimGround(info, false) != (AnimationId)0 )\n\t{\n\t\tif ( RpAnimBlendClumpGetAssociation(shooter->GetClump(), CPed::GetFireAnimGround(info, false)) )\n\t\t\tanim2Playing = true;\n\t}\n\t\n\tASSERT(shooter->IsPed());\n\n\tCPed *shooterPed = (CPed*)shooter;\n\n\tif (shooterPed == FindPlayerPed())\n\t{\n\t\tif (m_eWeaponType == WEAPONTYPE_GOLFCLUB || m_eWeaponType == WEAPONTYPE_NIGHTSTICK ||\n\t\t\t(m_eWeaponType >= WEAPONTYPE_BASEBALLBAT && m_eWeaponType <= WEAPONTYPE_CHAINSAW))\n\t\t{\t\n\t\t\tCGlass::BreakGlassPhysically(fireSource, info->m_fRadius);\n\t\t\t\n\t\t\tif (m_eWeaponType == WEAPONTYPE_CHAINSAW)\n\t\t\t\tCEventList::RegisterEvent(EVENT_GUNSHOT, EVENT_ENTITY_PED, FindPlayerPed(), FindPlayerPed(), 1000);\n\t\t}\n\t}\n\n\tint damageEntityRegistered = 0;\n\n\tfor ( int32 i = 0; i < shooterPed->m_numNearPeds; i++ )\n\t{\n\t\tCPed *victimPed = shooterPed->m_nearPeds[i];\n\t\tASSERT(victimPed!=nil);\n\n\t\tif ( (victimPed->m_nPedType != shooterPed->m_nPedType || victimPed == shooterPed->m_pSeekTarget)\n\t\t\t\t&& victimPed != shooterPed->m_leader || !(CGeneral::GetRandomNumber() & 31)\n\t\t\t\t&& (!shooterPed->IsGangMember() || victimPed->CanBeDamagedByThisGangMember(shooterPed)) )\n\t\t{\n\t\t\tbool collided = false;\n\n\t\t\tif (victimPed->m_nPedState == PED_DRIVING && (m_eWeaponType == WEAPONTYPE_UNARMED || m_eWeaponType == WEAPONTYPE_BRASSKNUCKLE\n\t\t\t\t|| info->IsFlagSet(WEAPONFLAG_FIGHTMODE)))\n\t\t\t\tcontinue;\n\n\t\t\tfloat victimPedRadius = victimPed->GetBoundRadius() + info->m_fRadius;\n\t\t\tif ( victimPed->bUsesCollision || victimPed->Dead() || victimPed->Driving() )\n\t\t\t{\n\t\t\t\tCVector victimPedPos = victimPed->GetPosition();\n\t\t\t\tif ( SQR(victimPedRadius) > (victimPedPos-fireSource).MagnitudeSqr() )\n\t\t\t\t{\n\t\t\t\t\tCVector collisionDist;\n\t\t\t\t\tCColModel* victimPedCol = &CTempColModels::ms_colModelPed1;\n\t\t\t\t\tbool useLocalPos = false;\n\t\t\t\t\tif (victimPed->m_nPedState == PED_FALL\n\t\t\t\t\t\t|| victimPed->m_nPedState == PED_DIE && victimPed->bIsPedDieAnimPlaying\n\t\t\t\t\t\t|| victimPed->m_nWaitState == WAITSTATE_SIT_IDLE\n\t\t\t\t\t\t|| victimPed->m_nWaitState == WAITSTATE_SUN_BATHE_IDLE)\n\t\t\t\t\t{\n\t\t\t\t\t\tuseLocalPos = true;\n\t\t\t\t\t\tvictimPedCol = ((CPedModelInfo*)CModelInfo::GetModelInfo(victimPed->GetModelIndex()))->AnimatePedColModelSkinnedWorld(victimPed->GetClump());\n\t\t\t\t\t} else if (victimPed->DyingOrDead()) {\n\t\t\t\t\t\tvictimPedCol = &CTempColModels::ms_colModelPedGroundHit;\n\t\t\t\t\t}\n\n\t\t\t\t\tint32 s = 0;\n\t\t\t\t\twhile ( s < victimPedCol->numSpheres )\n\t\t\t\t\t{\n\t\t\t\t\t\tCColSphere *sphere = &victimPedCol->spheres[s];\n\n\t\t\t\t\t\tif (useLocalPos)\n\t\t\t\t\t\t\tcollisionDist = sphere->center - fireSource;\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tcollisionDist = victimPedPos + sphere->center - fireSource;\n\n\t\t\t\t\t\tif ( SQR(sphere->radius + info->m_fRadius) > collisionDist.MagnitudeSqr() )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcollided = true;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\ts++;\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( !(victimPed->IsPlayer() && victimPed->GetPedState() == PED_GETUP) )\n\t\t\t\t\t{\n\t\t\t\t\t\tif ( collided )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tfloat victimPedHealth = victimPed->m_fHealth;\n\t\t\t\t\t\t\tCVector bloodPos = fireSource + (collisionDist*0.7f);\n\n\t\t\t\t\t\t\tCVector2D posOffset(shooterPed->GetPosition().x-victimPedPos.x, shooterPed->GetPosition().y-victimPedPos.y);\n\n\t\t\t\t\t\t\tint32 localDir = victimPed->GetLocalDirection(posOffset);\n\n\t\t\t\t\t\t\tbool isHeavy = m_eWeaponType >= WEAPONTYPE_GOLFCLUB && m_eWeaponType <= WEAPONTYPE_KATANA && m_eWeaponType != WEAPONTYPE_HAMMER;\n\n\t\t\t\t\t\t\tif (shooterPed->m_fDamageImpulse == 0.0f)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tshooterPed->m_pDamageEntity = victimPed;\n\t\t\t\t\t\t\t\tvictimPed->RegisterReference(&shooterPed->m_pDamageEntity);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tdamageEntityRegistered = 3;\n\t\t\t\t\t\t\tif (victimPed->bInVehicle)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tCVehicle *victimVeh = victimPed->m_pMyVehicle;\n\t\t\t\t\t\t\t\tif (victimVeh)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tif (victimVeh->IsBike())\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tCBike *victimBike = (CBike*)victimVeh;\n\t\t\t\t\t\t\t\t\t\tvictimBike->KnockOffRider(m_eWeaponType, localDir, victimPed, false);\n\t\t\t\t\t\t\t\t\t\tif (victimBike->pDriver)\n\t\t\t\t\t\t\t\t\t\t\tvictimBike->pDriver->ReactToAttack(shooterPed);\n\t\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tif (victimVeh->pPassengers[0])\n\t\t\t\t\t\t\t\t\t\t\t\tvictimVeh->pPassengers[0]->ReactToAttack(shooterPed);\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif ( !victimPed->DyingOrDead() )\n\t\t\t\t\t\t\t\tvictimPed->ReactToAttack(shooterPed);\n\n\t\t\t\t\t\t\tuint8 hitLevel = HITLEVEL_HIGH;\n\t\t\t\t\t\t\tif ( isHeavy && (victimPed->OnGround() || victimPed->m_nWaitState == WAITSTATE_SUN_BATHE_IDLE))\n\t\t\t\t\t\t\t\thitLevel = HITLEVEL_GROUND;\n\n\t\t\t\t\t\t\tvictimPed->StartFightDefend(localDir, hitLevel, 10);\n\n\t\t\t\t\t\t\tif ( !victimPed->DyingOrDead() )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tif ( shooterPed->IsPlayer() && isHeavy && anim2Playing )\n\t\t\t\t\t\t\t\t\tvictimPed->InflictDamage(shooterPed, m_eWeaponType, 100.0f, PEDPIECE_TORSO, localDir);\n\t\t\t\t\t\t\t\telse if ( shooterPed->IsPlayer() && ((CPlayerPed*)shooterPed)->m_bAdrenalineActive )\n\t\t\t\t\t\t\t\t\tvictimPed->InflictDamage(shooterPed, m_eWeaponType, 3.5f*info->m_nDamage, PEDPIECE_TORSO, localDir);\n\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tif ( victimPed->IsPlayer() && isHeavy ) // wtf, it's not fair\n\t\t\t\t\t\t\t\t\t\tvictimPed->InflictDamage(shooterPed, m_eWeaponType, 2.0f*info->m_nDamage, PEDPIECE_TORSO, localDir);\n\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t\tvictimPed->InflictDamage(shooterPed, m_eWeaponType,      info->m_nDamage, PEDPIECE_TORSO, localDir);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif ( CGame::nastyGame && victimPed->GetIsOnScreen() )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tCVector dir = collisionDist * RecipSqrt(1.0f, 10.0f*collisionDist.MagnitudeSqr());\n\n\t\t\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_BLOOD, bloodPos, dir);\n\t\t\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_BLOOD, bloodPos, dir);\n\t\t\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_BLOOD, bloodPos, dir);\n\n\t\t\t\t\t\t\t\tif ( isHeavy )\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tdir.x += CGeneral::GetRandomNumberInRange(-0.05f, 0.05f);\n\t\t\t\t\t\t\t\t\tdir.y += CGeneral::GetRandomNumberInRange(-0.05f, 0.05f);\n\t\t\t\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_BLOOD, bloodPos, dir);\n\n\t\t\t\t\t\t\t\t\tdir.x += CGeneral::GetRandomNumberInRange(-0.05f, 0.05f);\n\t\t\t\t\t\t\t\t\tdir.y += CGeneral::GetRandomNumberInRange(-0.05f, 0.05f);\n\t\t\t\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_BLOOD, bloodPos, dir);\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tif (m_eWeaponType == WEAPONTYPE_CHAINSAW)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tif (victimPed->m_nPedState != PED_DEAD && !((CTimer::GetFrameCounter() + 17) & 1)\n\t\t\t\t\t\t\t\t\t\t|| victimPed->m_nPedState == PED_DEAD && !((CTimer::GetFrameCounter() + 17) & 3))\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_TEST, bloodPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.2f);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tCVector newDir(dir);\n\t\t\t\t\t\t\t\t\tnewDir.z += 0.2f;\n\t\t\t\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_BLOOD_SMALL, bloodPos, newDir);\n\t\t\t\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_BLOOD, bloodPos, newDir);\n\t\t\t\t\t\t\t\t\tnewDir.z = dir.z + 0.1f;\n\t\t\t\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_BLOOD, bloodPos, newDir);\n\t\t\t\t\t\t\t\t\tnewDir.x = 0.0f;\n\t\t\t\t\t\t\t\t\tnewDir.y = 0.0f;\n\t\t\t\t\t\t\t\t\tnewDir.z = 0.01f;\n\t\t\t\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_DEBRIS2, bloodPos, newDir);\n\n\t\t\t\t\t\t\t\t\tCVector dropDir(CGeneral::GetRandomNumberInRange(-0.15f, 0.15f), CGeneral::GetRandomNumberInRange(0.1f, 0.35f), 0.f);\n\t\t\t\t\t\t\t\t\tCVector dropPos(CGeneral::GetRandomNumberInRange(SCREEN_STRETCH_X(50.0f), SCREEN_STRETCH_FROM_RIGHT(50.0f)),\n\t\t\t\t\t\t\t\t\t\tCGeneral::GetRandomNumberInRange(SCREEN_STRETCH_Y(50.0f), SCREEN_STRETCH_FROM_BOTTOM(50.0f)), 1.f);\n\t\t\t\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_BLOODDROP, dropPos, dropDir, nil, CGeneral::GetRandomNumberInRange(0.1f, 0.15f),\n\t\t\t\t\t\t\t\t\t\tCRGBA(0, 0, 0, 0), 0, 0, CGeneral::GetRandomNumber() & 1, 0);\n\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (info->m_AnimToPlay == ASSOCGRP_KNIFE)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tdir += 0.1f * shooterPed->GetUp() + 0.05f * shooterPed->GetRight();\n\t\t\t\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_BLOOD_SPURT, bloodPos, dir);\n\t\t\t\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_BLOOD_SPURT, bloodPos, dir);\n\t\t\t\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_BLOOD_SPURT, bloodPos, dir);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif ( !victimPed->OnGround() )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tif ( victimPed->m_fHealth > 0.0f\n\t\t\t\t\t\t\t\t\t&& (victimPed->m_fHealth < 30.0f && victimPedHealth > 30.0f ||\n\t\t\t\t\t\t\t\t\t\t(isHeavy || m_eWeaponType == WEAPONTYPE_BRASSKNUCKLE) && !victimPed->IsPlayer()) )\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tposOffset.Normalise();\n\t\t\t\t\t\t\t\t\tvictimPed->bIsStanding = false;\n\t\t\t\t\t\t\t\t\tif(m_eWeaponType == WEAPONTYPE_CHAINSAW)\n\t\t\t\t\t\t\t\t\t\tvictimPed->ApplyMoveForce(posOffset.x*-2.0f, posOffset.y*-2.0f, 2.0f);\n\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t\tvictimPed->ApplyMoveForce(posOffset.x*-5.0f, posOffset.y*-5.0f, 3.0f);\n\n\t\t\t\t\t\t\t\t\tif ( isHeavy && victimPed->IsPlayer() )\n\t\t\t\t\t\t\t\t\t\tvictimPed->SetFall(3000, AnimationId(ANIM_STD_HIGHIMPACT_FRONT + localDir), false);\n\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t\tvictimPed->SetFall(1500, AnimationId(ANIM_STD_HIGHIMPACT_FRONT + localDir), false);\n\n\t\t\t\t\t\t\t\t\tshooterPed->m_pSeekTarget = victimPed;\n\t\t\t\t\t\t\t\t\tshooterPed->m_pSeekTarget->RegisterReference(&shooterPed->m_pSeekTarget);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse if (victimPed->Dying() && !anim2Playing)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tposOffset.Normalise();\n\t\t\t\t\t\t\t\tvictimPed->bIsStanding = false;\n\t\t\t\t\t\t\t\tif(m_eWeaponType == WEAPONTYPE_CHAINSAW)\n\t\t\t\t\t\t\t\t\tvictimPed->ApplyMoveForce(posOffset.x*-1.0f, posOffset.y*-1.0f, 1.0f);\n\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\tvictimPed->ApplyMoveForce(posOffset.x*-5.0f, posOffset.y*-5.0f, 3.0f);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tm_eWeaponState = WEAPONSTATE_MELEE_MADECONTACT;\n\n\t\t\t\t\t\t\tif (m_eWeaponType != WEAPONTYPE_KNIFE && m_eWeaponType != WEAPONTYPE_MACHETE\n\t\t\t\t\t\t\t\t&& m_eWeaponType != WEAPONTYPE_KATANA && m_eWeaponType != WEAPONTYPE_CHAINSAW) {\n\n\t\t\t\t\t\t\t\tif (victimPed->m_nPedType == PEDTYPE_COP)\n\t\t\t\t\t\t\t\t\tCEventList::RegisterEvent(EVENT_ASSAULT_POLICE, EVENT_ENTITY_PED, victimPed, shooterPed, 2000);\n\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\tCEventList::RegisterEvent(EVENT_ASSAULT, EVENT_ENTITY_PED, victimPed, shooterPed, 2000);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tif (victimPed->m_nPedType == PEDTYPE_COP)\n\t\t\t\t\t\t\t\t\tCEventList::RegisterEvent(EVENT_ASSAULT_NASTYWEAPON_POLICE, EVENT_ENTITY_PED, victimPed, shooterPed, 2000);\n\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\tCEventList::RegisterEvent(EVENT_ASSAULT_NASTYWEAPON, EVENT_ENTITY_PED, victimPed, shooterPed, 2000);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tCVehicle *nearVeh = (CVehicle*)CWorld::TestSphereAgainstWorld(fireSource, info->m_fRadius, nil, false, true, false, false, false, false);\n\tif (nearVeh && nearVeh->IsCar())\n\t{\n\t\tCAutomobile *nearCar = (CAutomobile*)nearVeh;\n\t\tm_eWeaponState = WEAPONSTATE_MELEE_MADECONTACT;\n\t\tif (shooterPed == FindPlayerPed())\n\t\t{\n\t\t\tif (nearCar->IsLawEnforcementVehicle())\n\t\t\t{\n\t\t\t\tFindPlayerPed()->SetWantedLevelNoDrop(1);\n\t\t\t}\n\t\t\tCEventList::RegisterEvent(EVENT_ASSAULT, EVENT_ENTITY_VEHICLE, nearCar, shooterPed, 2000);\n\t\t}\n\t\tfloat oldHealth = nearCar->m_fHealth;\n\t\tif (m_eWeaponType == WEAPONTYPE_CHAINSAW)\n\t\t{\n\t\t\tfor( int32 i=0; i<4; i++ )\n\t\t\t{\n\t\t\t\tCParticle::AddParticle(PARTICLE_SPARK_SMALL, gaTempSphereColPoints[0].point, CVector(0.0f, 0.0f, 0.3f));\n\t\t\t\tCParticle::AddParticle(PARTICLE_SPARK, gaTempSphereColPoints[0].point, gaTempSphereColPoints[0].normal * 0.1f);\n\t\t\t}\n\t\t}\n\t\tif (m_eWeaponType == WEAPONTYPE_CHAINSAW)\n\t\t{\n\t\t\tnearCar->VehicleDamage(info->m_nDamage * (0.00075f * nearCar->pHandling->fMass), gaTempSphereColPoints[0].pieceB);\n\n\t\t\tCParticle::AddParticle(PARTICLE_HEATHAZE, gaTempSphereColPoints[0].point, CVector(0.0f, 0.0f, 0.0f), 0, 0.0f, 0, 0, 0, 0);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tnearCar->VehicleDamage(info->m_nDamage* (0.01f * nearCar->pHandling->fMass), gaTempSphereColPoints[0].pieceB);\n\t\t}\n\t\tif (nearCar->m_fHealth < oldHealth)\n\t\t{\n\t\t\tnearCar->m_nLastWeaponDamage = m_eWeaponType;\n\t\t\tnearCar->m_pLastDamageEntity = shooterPed;\n\t\t}\n\t\tif (shooterPed->m_fDamageImpulse == 0.0f)\n\t\t{\n\t\t\tshooterPed->m_pDamageEntity = nearCar;\n\t\t\tnearCar->RegisterReference(&shooterPed->m_pDamageEntity);\n\t\t}\n\t\tdamageEntityRegistered = 2;\n\t\tif (FindPlayerPed()->GetWeapon() == this && nearCar->VehicleCreatedBy != MISSION_VEHICLE)\n\t\t{\n\t\t\tif (nearCar->AutoPilot.m_nDrivingStyle != DRIVINGSTYLE_PLOUGH_THROUGH\n\t\t\t\t&& (CGeneral::GetRandomTrueFalse() || nearCar->AutoPilot.m_nCarMission != MISSION_CRUISE))\n\t\t\t{\n\t\t\t\tint leaveCarDelay = 200;\n\t\t\t\tCPed *driver = nearCar->pDriver;\n\t\t\t\tif (driver && driver->CharCreatedBy != MISSION_CHAR)\n\t\t\t\t{\n\t\t\t\t\tif (driver->m_pedStats->m_temper <= driver->m_pedStats->m_fear)\n\t\t\t\t\t{\n\t\t\t\t\t\tdriver->SetObjective(OBJECTIVE_FLEE_ON_FOOT_TILL_SAFE);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tdriver->SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, FindPlayerPed());\n\t\t\t\t\t\tdriver->m_objectiveTimer = CTimer::GetTimeInMilliseconds() + 10000;\n\t\t\t\t\t\tdriver->m_prevObjective = OBJECTIVE_KILL_CHAR_ON_FOOT;\n\t\t\t\t\t}\n\t\t\t\t\tdriver->m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + 200;\n\t\t\t\t\tleaveCarDelay = 400;\n\t\t\t\t}\n\t\t\t\tfor (int j = 0; j < nearCar->m_nNumPassengers; ++j)\n\t\t\t\t{\n\t\t\t\t\tCPed *passenger = nearCar->pPassengers[j];\n\t\t\t\t\tif (passenger && passenger->CharCreatedBy != MISSION_CHAR)\n\t\t\t\t\t{\n\t\t\t\t\t\tnearCar->pPassengers[j]->SetObjective(OBJECTIVE_FLEE_ON_FOOT_TILL_SAFE);\n\t\t\t\t\t\tpassenger->m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + leaveCarDelay;\n\t\t\t\t\t\tleaveCarDelay += 200;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tCPed *driver = nearCar->pDriver;\n\t\t\t\tif (driver)\n\t\t\t\t{\n\t\t\t\t\tif (driver->m_objective != OBJECTIVE_LEAVE_CAR && driver->m_objective != OBJECTIVE_KILL_CHAR_ON_FOOT &&\n\t\t\t\t\t\tdriver->m_objective != OBJECTIVE_FLEE_ON_FOOT_TILL_SAFE)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (nearCar->AutoPilot.m_nDrivingStyle != DRIVINGSTYLE_PLOUGH_THROUGH)\n\t\t\t\t\t\t\tnearCar->AutoPilot.m_nCruiseSpeed = nearCar->AutoPilot.m_nCruiseSpeed * 1.5f;\n\n\t\t\t\t\t\tnearCar->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_PLOUGH_THROUGH;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tif (m_eWeaponType == WEAPONTYPE_CHAINSAW)\n\t{\n\t\tCEntity *nearStatic = (CObject*)CWorld::TestSphereAgainstWorld(fireSource, info->m_fRadius, nil, true, false, false, true, false, false);\n\t\tif (nearStatic)\n\t\t{\n\t\t\tfor(int i=0; i < 4; i++) {\n\t\t\t\tCParticle::AddParticle(PARTICLE_SPARK_SMALL, gaTempSphereColPoints[0].point, CVector(0.0f, 0.0f, 0.3f), 0, 0.0f, 0, 0, 0, 0);\n\t\t\t\tCParticle::AddParticle(PARTICLE_SPARK, gaTempSphereColPoints[0].point, 0.1f * gaTempSphereColPoints[0].normal, 0, 0.0f, 0, 0, 0, 0);\n\t\t\t}\n\n\t\t\tCParticle::AddParticle(PARTICLE_HEATHAZE, gaTempSphereColPoints[0].point, CVector(0.0f, 0.0f, 0.0f), 0, 0.0f, 0, 0, 0, 0);\n\t\t\t\n\t\t\tif (!damageEntityRegistered)\n\t\t\t{\n\t\t\t\tm_eWeaponState = WEAPONSTATE_MELEE_MADECONTACT;\n\t\t\t\tif (shooterPed->m_fDamageImpulse == 0.0f)\n\t\t\t\t{\n\t\t\t\t\tshooterPed->m_pDamageEntity = nearStatic;\n\t\t\t\t\tnearStatic->RegisterReference(&shooterPed->m_pDamageEntity);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (nearStatic->IsObject() && ((CObject*)nearStatic)->m_nCollisionDamageEffect >= DAMAGE_EFFECT_SMASH_COMPLETELY)\n\t\t\t\t((CObject*)nearStatic)->ObjectDamage(200.0f);\n\t\t}\n\t}\n\n\treturn true;\n}\n\nbool\nCWeapon::FireInstantHit(CEntity *shooter, CVector *fireSource)\n{\n\tASSERT(shooter!=nil);\n\tASSERT(fireSource!=nil);\n\n\tCWeaponInfo *info = GetInfo();\n\n\tCVector source, target;\n\tCColPoint point;\n\tCEntity *victim = nil;\n\n\tfloat heading = RADTODEG(shooter->GetForward().Heading());\n\tfloat angle   = DEGTORAD(heading);\n\n\tCVector2D ahead(-Sin(angle), Cos(angle));\n\tahead.Normalise();\n\n\tCVector vel = ((CPed *)shooter)->m_vecMoveSpeed;\n\tint32 shooterMoving = false;\n\tif ( Abs(vel.x) > 0.0f && Abs(vel.y) > 0.0f )\n\t\tshooterMoving = true;\n\n\tif ( shooter == FindPlayerPed() )\n\t{\n\t\tstatic float prev_heading = 0.0f;\n\t\tprev_heading = ((CPed*)shooter)->m_fRotationCur;\n\t}\n\n\tif ( shooter->IsPed() && ((CPed *)shooter)->m_pPointGunAt )\n\t{\n\t\tCPed *shooterPed = (CPed *)shooter;\n\t\tif ( shooterPed->m_pedIK.m_flags & CPedIK::GUN_POINTED_SUCCESSFULLY )\n\t\t{\n\t\t\tint32 accuracy   = shooterPed->m_wepAccuracy;\n\t\t\tint32 inaccuracy = 100-accuracy;\n\n\t\t\tCPed *threatAttack = (CPed*)shooterPed->m_pPointGunAt;\n\t\t\tif ( threatAttack->IsPed() )\n\t\t\t{\n\t\t\t\tthreatAttack->m_pedIK.GetComponentPosition(target, PED_MID);\n\t\t\t\tthreatAttack->ReactToPointGun(shooter);\n\t\t\t}\n\t\t\telse\n\t\t\t\ttarget = threatAttack->GetPosition();\n\n\t\t\ttarget -= *fireSource;\n\t\t\tfloat distToTarget = Max(target.Magnitude(), 0.01f);\n\t\t\ttarget *= info->m_fRange / distToTarget;\n\t\t\ttarget += *fireSource;\n\n\t\t\tif (shooter == FindPlayerPed() && inaccuracy != 0.f)\n\t\t\t{\n\t\t\t\tfloat newInaccuracy = fPlayerAimScale * FindPlayerPed()->m_fAttackButtonCounter * (inaccuracy * Min(1.f, fPlayerAimScaleDist / distToTarget));\n\t\t\t\tif (FindPlayerPed()->bIsDucking)\n\t\t\t\t\tnewInaccuracy *= 0.4f;\n\n\t\t\t\ttarget.x += CGeneral::GetRandomNumberInRange(-0.15f, 0.15f) * newInaccuracy;\n\t\t\t\ttarget.y += CGeneral::GetRandomNumberInRange(-0.15f, 0.15f) * newInaccuracy;\n\t\t\t\ttarget.z += CGeneral::GetRandomNumberInRange(-0.2f, 0.2f) * newInaccuracy;\n\t\t\t\tFindPlayerPed()->m_fAttackButtonCounter += info->m_nDamage * 0.04f;\n\t\t\t}\n\t\t\telse if (inaccuracy > 0.f)\n\t\t\t{\n\t\t\t\tif (threatAttack == FindPlayerPed())\n\t\t\t\t{\n\t\t\t\t\tfloat speed = Min(0.33f, FindPlayerPed()->m_vecMoveSpeed.Magnitude());\n\t\t\t\t\tinaccuracy *= (0.3f * speed * 100.f / 33.f + 0.8f);\n\t\t\t\t}\n\t\t\t\ttarget.x += CGeneral::GetRandomNumberInRange(-0.2f, 0.2f) * inaccuracy;\n\t\t\t\ttarget.y += CGeneral::GetRandomNumberInRange(-0.2f, 0.2f) * inaccuracy;\n\t\t\t\ttarget.z += CGeneral::GetRandomNumberInRange(-0.1f, 0.1f) * inaccuracy;\n\t\t\t}\n\n\t\t\tif (shooter == FindPlayerPed())\n\t\t\t\tCWorld::bIncludeDeadPeds = true;\n\n\t\t\tCWorld::bIncludeBikers = true;\n\t\t\tProcessLineOfSight(*fireSource, target, point, victim, m_eWeaponType, shooter, true, true, true, true, true, false, false);\n\t\t\tCWorld::bIncludeDeadPeds = false;\n\t\t\tCWorld::bIncludeBikers = false;\n\t\t}\n\t\telse\n\t\t{\n\t\t\ttarget.x = info->m_fRange;\n\t\t\ttarget.y = 0.0f;\n\t\t\ttarget.z = 0.0f;\n\n\t\t\tshooterPed->TransformToNode(target, PED_HANDR);\n\n\t\t\tCWorld::bIncludeBikers = true;\n\t\t\tProcessLineOfSight(*fireSource, target, point, victim, m_eWeaponType, shooter, true, true, true, true, true, false, false);\n\t\t\tCWorld::bIncludeBikers = false;\n\t\t}\n\t}\n\telse if ( shooter == FindPlayerPed() && TheCamera.Cams[0].Using3rdPersonMouseCam()  )\n\t{\n\t\tTheCamera.Find3rdPersonCamTargetVector(info->m_fRange, *fireSource, source, target);\n\n\t\tCWorld::bIncludeBikers = true;\n\t\tCWorld::bIncludeDeadPeds = true;\n\t\tCWorld::bIncludeCarTyres = true;\n\t\tProcessLineOfSight(source, target, point, victim, m_eWeaponType, shooter, true, true, true, true, true, false, false);\n\t\tCWorld::bIncludeBikers = false;\n\t\tCWorld::bIncludeDeadPeds = false;\n\t\tCWorld::bIncludeCarTyres = false;\n\n\t\tif (victim)\n\t\t\tCheckForShootingVehicleOccupant(&victim, &point, m_eWeaponType, source, target);\n\n\t\tint32 rotSpeed = 1;\n\t\tif ( m_eWeaponType == WEAPONTYPE_M4 )\n\t\t\trotSpeed = 4;\n\n\t\tCVector bulletPos;\n\t\tif ( CHeli::TestBulletCollision(&source, &target, &bulletPos, 4) )\n\t\t{\n\t\t\tfor ( int32 i = 0; i < 16; i++ )\n\t\t\t\tCParticle::AddParticle(PARTICLE_SPARK, bulletPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.0f, rotSpeed);\n\t\t}\n\t}\n\telse\n\t{\n\t\tuint32 model = shooter->GetModelIndex();\n\t\tif (model == MI_HUNTER || model == MI_SEASPAR || model == MI_SPARROW)\n\t\t{\n\t\t\tfloat inaccuracyMult = 0.6f;\n\t\t\ttarget = shooter->GetForward();\n\t\t\tif (shooter->GetStatus() == STATUS_PLAYER)\n\t\t\t{\n\t\t\t\ttarget *= info->m_fRange;\n\t\t\t\ttarget += *fireSource;\n\t\t\t\tCWeapon::DoDriveByAutoAiming(FindPlayerPed(), (CVehicle*)shooter, fireSource, &target);\n\t\t\t\ttarget -= *fireSource;\n\t\t\t\ttarget.Normalise();\n\t\t\t\tif (model == MI_SEASPAR || model == MI_SPARROW)\n\t\t\t\t\tinaccuracyMult = 0.1f;\n\t\t\t\telse\n\t\t\t\t\tinaccuracyMult = 0.3f;\n\t\t\t}\n\t\t\ttarget.x += CGeneral::GetRandomNumberInRange(-0.2f, 0.2f) * inaccuracyMult;\n\t\t\ttarget.y += CGeneral::GetRandomNumberInRange(-0.2f, 0.2f) * inaccuracyMult;\n\t\t\ttarget.z += CGeneral::GetRandomNumberInRange(-0.1f, 0.1f) * inaccuracyMult;\n\n\t\t\ttarget.Normalise();\n\t\t\ttarget *= info->m_fRange;\n\t\t\ttarget += *fireSource;\n\t\t\tCWorld::pIgnoreEntity = shooter;\n\t\t\tProcessLineOfSight(*fireSource, target, point, victim, m_eWeaponType, shooter, true, true, true, true, true, true, false);\n\t\t\tCWorld::pIgnoreEntity = nil;\n\n\t\t\tint32 rotSpeed = 1;\n\t\t\tif (m_eWeaponType == WEAPONTYPE_M4)\n\t\t\t\trotSpeed = 4;\n\n\t\t\tCVector bulletPos;\n\t\t\tif (CHeli::TestBulletCollision(fireSource, &target, &bulletPos, 4))\n\t\t\t{\n\t\t\t\tfor (int32 i = 0; i < 16; i++)\n\t\t\t\t\tCParticle::AddParticle(PARTICLE_SPARK, bulletPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.0f, rotSpeed);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tfloat shooterHeading = RADTODEG(shooter->GetForward().Heading());\n\t\t\tfloat shooterAngle = DEGTORAD(shooterHeading);\n\n\t\t\tCVector2D rotOffset(-Sin(shooterAngle), Cos(shooterAngle));\n\t\t\trotOffset.Normalise();\n\n\t\t\ttarget = *fireSource;\n\t\t\ttarget.x += rotOffset.x * info->m_fRange;\n\t\t\ttarget.y += rotOffset.y * info->m_fRange;\n\n\t\t\tCParticle::HandleShootableBirdsStuff(shooter, *fireSource);\n\t\t\tif (shooter->IsPed() && ((CPed*)shooter)->bDoomAim && (shooter != FindPlayerPed() || !info->IsFlagSet(WEAPONFLAG_CANAIM)))\n\t\t\t{\n\t\t\t\tCWeapon::DoDoomAiming(shooter, fireSource, &target);\n\t\t\t}\n\n\t\t\tCWorld::bIncludeBikers = true;\n\t\t\tProcessLineOfSight(*fireSource, target, point, victim, m_eWeaponType, shooter, true, true, true, true, true, false, false);\n\t\t\tCWorld::bIncludeBikers = false;\n\n\t\t\tint32 rotSpeed = 1;\n\t\t\tif (m_eWeaponType == WEAPONTYPE_M4)\n\t\t\t\trotSpeed = 4;\n\n\t\t\tCVector bulletPos;\n\t\t\tif (CHeli::TestBulletCollision(fireSource, &target, &bulletPos, 4))\n\t\t\t{\n\t\t\t\tfor (int32 i = 0; i < 16; i++)\n\t\t\t\t\tCParticle::AddParticle(PARTICLE_SPARK, bulletPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.0f, rotSpeed);\n\t\t\t}\n\t\t}\n\t}\n\n\tif ( shooter->IsPed() && victim)\n\t{\n\t\tif (victim == ((CPed*)shooter)->m_leader)\n\t\t\treturn false;\n\n\t\tif (victim->IsPed() && ((CPed*)shooter)->IsGangMember() && !((CPed*)victim)->CanBeDamagedByThisGangMember((CPed*)shooter))\n\t\t\treturn false;\n\t}\n\n\tif (shooter->IsPed())\n\t\tCEventList::RegisterEvent(EVENT_GUNSHOT, EVENT_ENTITY_PED, shooter, (CPed*)shooter, 1000);\n\telse if (shooter->IsVehicle() && ((CVehicle*)shooter)->pDriver)\n\t\tCEventList::RegisterEvent(EVENT_GUNSHOT, EVENT_ENTITY_VEHICLE, shooter, ((CVehicle*)shooter)->pDriver, 1000);\n\n\tif ( shooter == FindPlayerPed() )\n\t{\n\t\tif ( !(CTimer::GetFrameCounter() & 3) )\n\t\t\tMakePedsJumpAtShot((CPhysical*)shooter, fireSource, &target);\n\t}\n\n\tswitch ( m_eWeaponType )\n\t{\n\t\tcase WEAPONTYPE_M4:\n\t\tcase WEAPONTYPE_RUGER:\n\t\tcase WEAPONTYPE_M60:\n\t\tcase WEAPONTYPE_MINIGUN:\n\t\tcase WEAPONTYPE_HELICANNON:\n\t\t{\n\t\t\tstatic uint8 counter = 0;\n\n\t\t\tif ( info->m_nFiringRate >= 50 || !(++counter & 1) )\n\t\t\t{\n\t\t\t\tAddGunFlashBigGuns(*fireSource, *fireSource + target);\n\n\t\t\t\tCVector gunshellPos = *fireSource;\n\t\t\t\tgunshellPos -= CVector(0.65f*ahead.x, 0.65f*ahead.y, 0.0f);\n\t\t\t\tCVector dir = CrossProduct(CVector(ahead.x, ahead.y, 0.0f), CVector(0.0f, 0.0f, 5.0f));\n\t\t\t\tdir.Normalise2D();\n\t\t\t\tAddGunshell(shooter, gunshellPos, CVector2D(dir.x, dir.y), 0.02f);\n\t\t\t}\n\n\t\t\tbreak;\n\t\t}\n\n\t\tcase WEAPONTYPE_UZI:\n\t\tcase WEAPONTYPE_TEC9:\n\t\tcase WEAPONTYPE_SILENCED_INGRAM:\n\t\tcase WEAPONTYPE_MP5:\n\t\t{\n\t\t\tCPointLights::AddLight(CPointLights::LIGHT_POINT,\n\t\t\t\t\t*fireSource, CVector(0.0f, 0.0f, 0.0f), 5.0f,\n\t\t\t\t\t1.0f, 0.8f, 0.0f, CPointLights::FOG_NONE, false);\n\n\t\t\tCVector gunflashPos = *fireSource;\n\n\t\t\tif ( shooterMoving )\n\t\t\t\tgunflashPos += CVector(1.5f*vel.x, 1.5f*vel.y, 0.0f);\n\n\t\t\tCParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.07f);\n\t\t\tgunflashPos += CVector(0.06f*ahead.x, 0.06f*ahead.y, 0.0f);\n\t\t\tCParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.05f);\n\t\t\tgunflashPos += CVector(0.04f*ahead.x, 0.04f*ahead.y, 0.0f);\n\t\t\tCParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.04f);\n\t\t\tgunflashPos += CVector(0.04f*ahead.x, 0.04f*ahead.y, 0.0f);\n\t\t\tCParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.03f);\n\t\t\tgunflashPos += CVector(0.03f*ahead.x, 0.03f*ahead.y, 0.0f);\n\t\t\tCParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.03f);\n\t\t\tgunflashPos += CVector(0.03f*ahead.x, 0.03f*ahead.y, 0.0f);\n\t\t\tCParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.02f);\n\t\t\tgunflashPos += CVector(0.02f*ahead.x, 0.02f*ahead.y, 0.0f);\n\t\t\tCParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.01f);\n\n\t\t\tCVector gunsmokePos = *fireSource;\n\t\t\tfloat rnd = CGeneral::GetRandomNumberInRange(0.05f, 0.25f);\n\t\t\tCParticle::AddParticle(PARTICLE_GUNSMOKE2, gunsmokePos, CVector(ahead.x*rnd, ahead.y*rnd, 0.0f));\n\n\t\t\tCVector gunshellPos = *fireSource;\n\t\t\tgunshellPos -= CVector(0.2f*ahead.x, 0.2f*ahead.y, 0.0f);\n\t\t\tCVector dir = CrossProduct(CVector(ahead.x, ahead.y, 0.0f), CVector(0.0f, 0.0f, 5.0f));\n\t\t\tdir.Normalise2D();\n\t\t\tAddGunshell(shooter, gunshellPos, CVector2D(dir.x, dir.y), 0.015f);\n\n\t\t\tbreak;\n\t\t}\n\n\t\tcase WEAPONTYPE_COLT45:\n\t\tcase WEAPONTYPE_PYTHON:\n\t\tcase WEAPONTYPE_SNIPERRIFLE:\n\t\tcase WEAPONTYPE_LASERSCOPE:\n\t\t{\n\t\t\tCPointLights::AddLight(CPointLights::LIGHT_POINT,\n\t\t\t\t\t*fireSource, CVector(0.0f, 0.0f, 0.0f), 5.0f,\n\t\t\t\t\t1.0f, 0.8f, 0.0f, CPointLights::FOG_NONE, false);\n\n\t\t\tCVector gunflashPos = *fireSource;\n\n\t\t\tif ( shooterMoving )\n\t\t\t\tgunflashPos += CVector(1.5f*vel.x, 1.5f*vel.y, 0.0f);\n\n\t\t\tCParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.06f);\n\t\t\tgunflashPos += CVector(0.06f*ahead.x, 0.06f*ahead.y, 0.0f);\n\t\t\tCParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.04f);\n\t\t\tgunflashPos += CVector(0.04f*ahead.x, 0.04f*ahead.y, 0.0f);\n\t\t\tCParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.02f);\n\n\t\t\tCVector gunsmokePos = *fireSource;\n\t\t\tCParticle::AddParticle(PARTICLE_GUNSMOKE2, gunsmokePos, CVector(ahead.x*0.10f, ahead.y*0.10f, 0.0f), nil, 0.005f);\n\t\t\tCParticle::AddParticle(PARTICLE_GUNSMOKE2, gunsmokePos, CVector(ahead.x*0.15f, ahead.y*0.15f, 0.0f), nil, 0.015f);\n\t\t\tCParticle::AddParticle(PARTICLE_GUNSMOKE2, gunsmokePos, CVector(ahead.x*0.20f, ahead.y*0.20f, 0.0f), nil, 0.025f);\n\n\t\t\tCVector gunshellPos = *fireSource;\n\t\t\tgunshellPos -= CVector(0.2f*ahead.x, 0.2f*ahead.y, 0.0f);\n\t\t\tCVector dir = CrossProduct(CVector(ahead.x, ahead.y, 0.0f), CVector(0.0f, 0.0f, 5.0f));\n\t\t\tdir.Normalise2D();\n\t\t\tAddGunshell(shooter, gunshellPos, CVector2D(dir.x, dir.y), 0.015f);\n\n\t\t\tbreak;\n\t\t}\n\t\tdefault: break;\n\t}\n\n\tDoBulletImpact(shooter, victim, fireSource, &target, &point, ahead);\n\n\treturn true;\n}\n\nvoid\nCWeapon::AddGunFlashBigGuns(CVector start, CVector end)\n{\n\tCPointLights::AddLight(CPointLights::LIGHT_POINT,\n\t\tstart, CVector(0.0f, 0.0f, 0.0f), 5.0f,\n\t\t1.0f, 0.8f, 0.0f, CPointLights::FOG_NONE, false);\n\tCVector gunflashPos = start;\n\n\tCVector shootVec = end - start;\n\n\t// Wtf did you do there R*?\n\tshootVec.Normalise();\n\tCVector2D ahead = shootVec;\n\tahead.Normalise();\n\n\tCParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.08f);\n\tgunflashPos += CVector(0.06f * ahead.x, 0.06f * ahead.y, 0.0f);\n\tCParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.06f);\n\tgunflashPos += CVector(0.06f * ahead.x, 0.06f * ahead.y, 0.0f);\n\tCParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.06f);\n\n\tgunflashPos = start;\n\tgunflashPos += CVector(-0.1f * ahead.x, -0.1f * ahead.y, 0.0f);\n\tgunflashPos.z += 0.04f;\n\tCParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.04f);\n\tgunflashPos.z += 0.04f;\n\tCParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.02f);\n\tgunflashPos.z += 0.03f;\n\tCParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.02f);\n\n\tgunflashPos = start;\n\tgunflashPos += CVector(-0.1f * ahead.x, -0.1f * ahead.y, 0.0f);\n\tgunflashPos.z -= 0.04f;\n\tCParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.04f);\n\tgunflashPos.z -= 0.04f;\n\tCParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.02f);\n\tgunflashPos.z -= 0.03f;\n\tCParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.02f);\n\n\tCVector offset = CrossProduct(CVector(ahead.x, ahead.y, 0.0f), CVector(0.0f, 0.0f, 5.0f));\n\toffset.Normalise2D();\n\n\tgunflashPos = start;\n\tgunflashPos += CVector(-0.1f * ahead.x, -0.1f * ahead.y, 0.0f);\n\tgunflashPos += CVector(0.06f * offset.x, 0.06f * offset.y, 0.0f);\n\tCParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.04f);\n\tgunflashPos += CVector(0.04f * offset.x, 0.04f * offset.y, 0.0f);\n\tCParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.03f);\n\tgunflashPos += CVector(0.03f * offset.x, 0.03f * offset.y, 0.0f);\n\tCParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.02f);\n\n\tgunflashPos = start;\n\tgunflashPos += CVector(-0.1f * ahead.x, -0.1f * ahead.y, 0.0f);\n\tgunflashPos -= CVector(0.06f * offset.x, 0.06f * offset.y, 0.0f);\n\tCParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.04f);\n\tgunflashPos -= CVector(0.04f * offset.x, 0.04f * offset.y, 0.0f);\n\tCParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.03f);\n\tgunflashPos -= CVector(0.03f * offset.x, 0.03f * offset.y, 0.0f);\n\tCParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.02f);\n\n\tCVector gunsmokePos = start;\n\tfloat rnd = CGeneral::GetRandomNumberInRange(0.05f, 0.25f);\n\tCParticle::AddParticle(PARTICLE_GUNSMOKE2, gunsmokePos, CVector(ahead.x * rnd, ahead.y * rnd, 0.0f));\n}\n\nvoid\nCWeapon::AddGunshell(CEntity *shooter, CVector const &source, CVector2D const &direction, float size)\n{\n\tASSERT(shooter!=nil);\n\n\tif ( shooter == nil)\n\t\treturn;\n\n\tCVector dir(direction.x*0.05f, direction.y*0.05f, CGeneral::GetRandomNumberInRange(0.02f, 0.08f));\n\n\tstatic CVector prevEntityPosition(0.0f, 0.0f, 0.0f);\n\tCVector entityPosition = shooter->GetPosition();\n\n\tCVector diff = entityPosition - prevEntityPosition;\n\n\tif ( Abs(diff.x)+Abs(diff.y)+Abs(diff.z) > 1.5f )\n\t{\n\t\tprevEntityPosition = entityPosition;\n\n\t\tCParticle::AddParticle(PARTICLE_GUNSHELL_FIRST,\n\t\t\tsource, dir, nil, size, CGeneral::GetRandomNumberInRange(-20.0f, 20.0f));\n\t}\n\telse\n\t{\n\t\tCParticle::AddParticle(PARTICLE_GUNSHELL,\n\t\t\tsource, dir, nil, size, CGeneral::GetRandomNumberInRange(-20.0f, 20.0f));\n\t}\n}\n\n\nvoid\nCWeapon::DoBulletImpact(CEntity *shooter, CEntity *victim,\n\t\tCVector *source, CVector *target, CColPoint *point, CVector2D ahead)\n{\n\tASSERT(shooter!=nil);\n\tASSERT(source!=nil);\n\tASSERT(target!=nil);\n\tASSERT(point!=nil);\n\n\tCWeaponInfo *info = GetInfo();\n\n\tif ( victim )\n\t{\n\t\tif (shooter)\n\t\t{\n\t\t\tif (shooter && shooter->IsPed() && ((CPed*)shooter)->m_attachedTo == victim)\n\t\t\t\treturn;\n\n\t\t\tif (shooter->IsPed() && !((CPed*)shooter)->IsPlayer())\n\t\t\t{\n\t\t\t\tCPed* shooterPed = (CPed*)shooter;\n\t\t\t\tCEntity* guyWePointGun = shooterPed->m_pPointGunAt;\n\t\t\t\tif (guyWePointGun)\n\t\t\t\t{\n\t\t\t\t\tif (victim != guyWePointGun)\n\t\t\t\t\t{\n\t\t\t\t\t\tfloat distWithAim = (guyWePointGun->GetPosition() - shooter->GetPosition()).Magnitude();\n\t\t\t\t\t\tfloat distWithBullet = (point->point - shooter->GetPosition()).Magnitude();\n\t\t\t\t\t\tif (distWithAim > 0.1f && distWithBullet > 0.1f)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// Normalize\n\t\t\t\t\t\t\tCVector aimDir = (guyWePointGun->GetPosition() - shooter->GetPosition()) * (1.0f / distWithAim);\n\t\t\t\t\t\t\tCVector bulletDir = (point->point - shooter->GetPosition()) * (1.0f / distWithBullet);\n\n\t\t\t\t\t\t\tfloat dotProd = DotProduct(aimDir, bulletDir);\n\t\t\t\t\t\t\tfloat aimAndBulletAngle;\n\t\t\t\t\t\t\tif (dotProd <= 0.35f)\n\t\t\t\t\t\t\t\taimAndBulletAngle = PI;\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\taimAndBulletAngle = Acos(dotProd);\n\n\t\t\t\t\t\t\tif (aimAndBulletAngle <= DEGTORAD(45.0f) && (aimAndBulletAngle <= DEGTORAD(15.0f) || distWithBullet / distWithAim >= 0.75f) && distWithBullet / distWithAim >= 0.99f)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tshooterPed->bObstacleShowedUpDuringKillObjective = false;\n\t\t\t\t\t\t\t\tshooterPed->m_shotTime = 0;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tshooterPed->bObstacleShowedUpDuringKillObjective = true;\n\t\t\t\t\t\t\t\tshooterPed->m_shootTimer = 0;\n\t\t\t\t\t\t\t\tshooterPed->m_shotTime = CTimer::GetTimeInMilliseconds();\n\t\t\t\t\t\t\t\tif (distWithAim < 10.0f)\n\t\t\t\t\t\t\t\t\tshooterPed->SetAttackTimer(1500);\n\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\tshooterPed->SetAttackTimer(3000);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tCGlass::WasGlassHitByBullet(victim, point->point);\n\n\t\tCVector traceTarget = point->point;\n\t\tCBulletTraces::AddTrace(source, &traceTarget, m_eWeaponType, shooter);\n\n\t\tif (victim->IsPed() && shooter->IsVehicle() && ((CVehicle*)shooter)->pDriver)\n\t\t\tshooter = ((CVehicle*)shooter)->pDriver;\n\n\t\tif ( victim->IsPed() && shooter->IsPed() &&\n\t\t\t(((CPed*)shooter)->m_nPedType != ((CPed*)victim)->m_nPedType || ((CPed*)shooter)->m_nPedType == PEDTYPE_PLAYER2 ||\n\t\t\t\t!((CPed*)shooter)->IsGangMember() && ((CPed*)shooter)->m_nPedType != PEDTYPE_COP))\n\t\t{\n\t\t\tCPed *victimPed = (CPed *)victim;\n\t\t\tif ( !victimPed->DyingOrDead() && victim != shooter )\n\t\t\t{\n\t\t\t\tCVector pos = victimPed->GetPosition();\n\n\t\t\t\tCVector2D posOffset(source->x-pos.x, source->y-pos.y);\n\t\t\t\tint32 localDir = victimPed->GetLocalDirection(posOffset);\n\n\t\t\t\tvictimPed->ReactToAttack(shooter);\n\n\t\t\t\tif ( !victimPed->IsPedInControl() || victimPed->bIsDucking )\n\t\t\t\t{\n\t\t\t\t\tvictimPed->InflictDamage(shooter, m_eWeaponType, info->m_nDamage, (ePedPieceTypes)point->pieceB, localDir);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tif ( victimPed->bCanBeShotInVehicle && (IsShotgun(m_eWeaponType) ||\n\t\t\t\t\t\t(!victimPed->IsPlayer() && (m_eWeaponType == WEAPONTYPE_HELICANNON || m_eWeaponType == WEAPONTYPE_M60 || m_eWeaponType == WEAPONTYPE_PYTHON))))\n\t\t\t\t\t{\n\t\t\t\t\t\tposOffset.Normalise();\n\t\t\t\t\t\tvictimPed->bIsStanding = false;\n\n\t\t\t\t\t\tvictimPed->ApplyMoveForce(posOffset.x*-5.0f, posOffset.y*-5.0f, 5.0f);\n\t\t\t\t\t\tvictimPed->SetFall(1500, AnimationId(ANIM_STD_HIGHIMPACT_FRONT + localDir), false);\n\n\t\t\t\t\t\tvictimPed->InflictDamage(shooter, m_eWeaponType, info->m_nDamage, (ePedPieceTypes)point->pieceB, localDir);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tif ( victimPed->IsPlayer() )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tCPlayerPed *victimPlayer = (CPlayerPed *)victimPed;\n\t\t\t\t\t\t\tif ( victimPlayer->m_nHitAnimDelayTimer < CTimer::GetTimeInMilliseconds() && victimPed->m_nPedState != PED_DRIVING )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tvictimPed->ClearAttackByRemovingAnim();\n\n\t\t\t\t\t\t\t\tCAnimBlendAssociation *asoc = CAnimManager::AddAnimation(victimPed->GetClump(), ASSOCGRP_STD, AnimationId(ANIM_STD_HITBYGUN_FRONT + localDir));\n\t\t\t\t\t\t\t\tASSERT(asoc!=nil);\n\n\t\t\t\t\t\t\t\tasoc->blendAmount = 0.0f;\n\t\t\t\t\t\t\t\tasoc->blendDelta  = 8.0f;\n\n\t\t\t\t\t\t\t\tif ( m_eWeaponType == WEAPONTYPE_M4 )\n\t\t\t\t\t\t\t\t\tvictimPlayer->m_nHitAnimDelayTimer = CTimer::GetTimeInMilliseconds() + 2500;\n\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\tvictimPlayer->m_nHitAnimDelayTimer = CTimer::GetTimeInMilliseconds() + 1000;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tvictimPed->ClearAttackByRemovingAnim();\n\n\t\t\t\t\t\t\tCAnimBlendAssociation *asoc = CAnimManager::AddAnimation(victimPed->GetClump(), ASSOCGRP_STD, AnimationId(ANIM_STD_HITBYGUN_FRONT + localDir));\n\t\t\t\t\t\t\tASSERT(asoc!=nil);\n\n\t\t\t\t\t\t\tasoc->blendAmount = 0.0f;\n\t\t\t\t\t\t\tasoc->blendDelta  = 8.0f;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tvictimPed->InflictDamage(shooter, m_eWeaponType, info->m_nDamage, (ePedPieceTypes)point->pieceB, localDir);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( victimPed->m_nPedType == PEDTYPE_COP )\n\t\t\t\t\tCEventList::RegisterEvent(EVENT_SHOOT_COP, EVENT_ENTITY_PED, victim, (CPed*)shooter, 10000);\n\t\t\t\telse\n\t\t\t\t\tCEventList::RegisterEvent(EVENT_SHOOT_PED, EVENT_ENTITY_PED, victim, (CPed*)shooter, 10000);\n\n\t\t\t\tif ( CGame::nastyGame )\n\t\t\t\t{\n\t\t\t\t\tuint8 bloodAmount = 8;\n\t\t\t\t\tif ( IsShotgun(m_eWeaponType) || m_eWeaponType == WEAPONTYPE_HELICANNON )\n\t\t\t\t\t\tbloodAmount = 32;\n\n\t\t\t\t\tCVector dir = (point->point - victim->GetPosition()) * 0.01f;\n\t\t\t\t\tdir.z = 0.01f;\n\n\t\t\t\t\tif ( victimPed->GetIsOnScreen() )\n\t\t\t\t\t{\n\t\t\t\t\t\tfor ( uint8 i = 0; i < bloodAmount; i++ )\n\t\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_BLOOD_SMALL, point->point, dir);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (m_eWeaponType == WEAPONTYPE_MINIGUN)\n\t\t\t\t\t{\n\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_TEST, point->point, CVector(0.f, 0.f, 0.f), nil, 0.f, 0, 0, 0, 0);\n\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_TEST, point->point + CVector(0.2f, -0.2f, 0.f), CVector(0.f, 0.f, 0.f), nil, 0.f, 0, 0, 0, 0);\n\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_TEST, point->point + CVector(-0.2f, 0.2f, 0.f), CVector(0.f, 0.f, 0.f), nil, 0.f, 0, 0, 0, 0);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif ( CGame::nastyGame )\n\t\t\t\t{\n\t\t\t\t\tCVector dir = (point->point - victim->GetPosition()) * 0.01f;\n\t\t\t\t\tdir.z = 0.01f;\n\n\t\t\t\t\tif ( victim->GetIsOnScreen() )\n\t\t\t\t\t{\n\t\t\t\t\t\tfor ( int32 i = 0; i < 8; i++ )\n\t\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_BLOOD_SMALL, point->point + CVector(0.0f, 0.0f, 0.15f), dir);\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( victimPed->Dead() )\n\t\t\t\t\t{\n\t\t\t\t\t\tCAnimBlendAssociation *asoc;\n\t\t\t\t\t\tif ( RpAnimBlendClumpGetFirstAssociation(victimPed->GetClump(), ASSOC_FRONTAL) )\n\t\t\t\t\t\t\tasoc = CAnimManager::BlendAnimation(victimPed->GetClump(), ASSOCGRP_STD, ANIM_STD_HIT_FLOOR_FRONT, 8.0f);\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tasoc = CAnimManager::BlendAnimation(victimPed->GetClump(), ASSOCGRP_STD, ANIM_STD_HIT_FLOOR,   8.0f);\n\n\t\t\t\t\t\tif ( asoc )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tasoc->SetCurrentTime(0.0f);\n\t\t\t\t\t\t\tasoc->flags |= ASSOC_RUNNING;\n\t\t\t\t\t\t\tasoc->flags &= ~ASSOC_FADEOUTWHENDONE;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tswitch ( victim->GetType() )\n\t\t\t{\n\t\t\t\tcase ENTITY_TYPE_BUILDING:\n\t\t\t\t{\n\t\t\t\t\tfor ( int32 i = 0; i < 16; i++ )\n\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_SPARK, point->point, point->normal*0.05f);\n\n#ifndef FIX_BUGS\n\t\t\t\t\tCVector dist = point->point - (*source);\n\t\t\t\t\tfloat distMagnitude = dist.Magnitude();\n\t\t\t\t\tCVector smokePos = point->point - Max(distMagnitude / 10.0f, 0.2f) * dist / distMagnitude;\n#else\n\t\t\t\t    CVector smokePos = point->point;\n#endif // !FIX_BUGS\n\n\t\t\t\t\tsmokePos.x += CGeneral::GetRandomNumberInRange(-0.2f, 0.2f);\n\t\t\t\t\tsmokePos.y += CGeneral::GetRandomNumberInRange(-0.2f, 0.2f);\n\t\t\t\t\tsmokePos.z += CGeneral::GetRandomNumberInRange(-0.2f, 0.2f);\n\n\t\t\t\t\tCParticle::AddParticle(PARTICLE_BULLETHIT_SMOKE, smokePos, CVector(0.0f, 0.0f, 0.0f));\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase ENTITY_TYPE_VEHICLE:\n\t\t\t\t{\n\t\t\t\t\tif (point->pieceB >= CAR_PIECE_WHEEL_LF && point->pieceB <= CAR_PIECE_WHEEL_RR) {\n\t\t\t\t\t\t((CVehicle*)victim)->BurstTyre(point->pieceB, true);\n\n\t\t\t\t\t\tfor (int32 i = 0; i < 4; i++)\n\t\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_BULLETHIT_SMOKE, point->point, point->normal * 0.05f);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t((CVehicle*)victim)->InflictDamage(shooter, m_eWeaponType, info->m_nDamage);\n\n\t\t\t\t\t\tfor (int32 i = 0; i < 16; i++)\n\t\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_SPARK, point->point, point->normal * 0.05f);\n\n#ifndef FIX_BUGS\n\t\t\t\t\t\tCVector dist = point->point - (*source);\n\t\t\t\t\t\tCVector offset = dist - Max(0.2f * dist.Magnitude(), 0.5f) * CVector(ahead.x, ahead.y, 0.0f);\n\t\t\t\t\t\tCVector smokePos = *source + offset;\n#else\n\t\t\t\t\t\tCVector smokePos = point->point;\n#endif\n\n\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_BULLETHIT_SMOKE, smokePos, CVector(0.0f, 0.0f, 0.0f));\n\t\t\t\t\t}\n\n\n\t\t\t\t\tif ( shooter->IsPed() )\n\t\t\t\t\t{\n\t\t\t\t\t\tCPed *shooterPed = (CPed *)shooter;\n\n\t\t\t\t\t\tif ( shooterPed->bNotAllowedToDuck )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif ( shooterPed->bKindaStayInSamePlace && victim != shooterPed->m_pPointGunAt )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tshooterPed->bKindaStayInSamePlace = false;\n\t\t\t\t\t\t\t\tshooterPed->m_duckAndCoverTimer   = CTimer::GetTimeInMilliseconds() + 15000;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase ENTITY_TYPE_OBJECT:\n\t\t\t\t{\n\t\t\t\t\tfor ( int32 i = 0; i < 8; i++ )\n\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_SPARK, point->point, point->normal*0.05f);\n\n\t\t\t\t\tCObject *victimObject = (CObject *)victim;\n\n\t\t\t\t\tif ( !victimObject->bInfiniteMass && victimObject->m_fCollisionDamageMultiplier < 99.9f)\n\t\t\t\t\t{\n\t\t\t\t\t\tbool notStatic = !victimObject->GetIsStatic();\n\t\t\t\t\t\tif (notStatic && victimObject->m_fUprootLimit <= 0.0f)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tvictimObject->SetIsStatic(false);\n\t\t\t\t\t\t\tvictimObject->AddToMovingList();\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tnotStatic = !victimObject->GetIsStatic();\n\t\t\t\t\t\tif (!notStatic)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tCVector moveForce = point->normal * -4.0f;\n\t\t\t\t\t\t\tvictimObject->ApplyMoveForce(moveForce.x, moveForce.y, moveForce.z);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (victimObject->m_nCollisionDamageEffect >= DAMAGE_EFFECT_SMASH_COMPLETELY) {\n\t\t\t\t\t\tvictimObject->ObjectDamage(50.f);\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tdefault: break;\n\t\t\t}\n\t\t}\n\n\t\tswitch ( victim->GetType() )\n\t\t{\n\t\t\tcase ENTITY_TYPE_BUILDING:\n\t\t\t{\n\t\t\t\tPlayOneShotScriptObject(SCRIPT_SOUND_BULLET_HIT_GROUND_1, point->point);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase ENTITY_TYPE_VEHICLE:\n\t\t\t{\n\t\t\t\tCStats::BulletsThatHit++;\n\t\t\t\tDMAudio.PlayOneShot(((CPhysical*)victim)->m_audioEntityId, SOUND_WEAPON_HIT_VEHICLE, 1.0f);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase ENTITY_TYPE_PED:\n\t\t\t{\n\t\t\t\tCStats::BulletsThatHit++;\n\t\t\t\tDMAudio.PlayOneShot(((CPhysical*)victim)->m_audioEntityId, SOUND_WEAPON_HIT_PED, 1.0f);\n\t\t\t\t((CPed*)victim)->Say(SOUND_PED_BULLET_HIT);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase ENTITY_TYPE_OBJECT:\n\t\t\t{\n\t\t\t\tCStats::BulletsThatHit++;\n\t\t\t\tPlayOneShotScriptObject(SCRIPT_SOUND_BULLET_HIT_GROUND_2, point->point);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase ENTITY_TYPE_DUMMY:\n\t\t\t{\n\t\t\t\tPlayOneShotScriptObject(SCRIPT_SOUND_BULLET_HIT_GROUND_3, point->point);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tdefault: break;\n\t\t}\n\t}\n\telse\n\t\tCBulletTraces::AddTrace(source, target, m_eWeaponType, shooter);\n\n\tif ( shooter == FindPlayerPed() )\n\t\tCPad::GetPad(0)->StartShake_Distance(240, 128, FindPlayerPed()->GetPosition().x, FindPlayerPed()->GetPosition().y, FindPlayerPed()->GetPosition().z);\n\n\tBlowUpExplosiveThings(victim);\n}\n\n\nbool\nCWeapon::FireShotgun(CEntity *shooter, CVector *fireSource)\n{\n\tASSERT(shooter!=nil);\n\tASSERT(fireSource!=nil);\n\n\tCWeaponInfo *info = GetInfo();\n\n\tfloat heading = RADTODEG(shooter->GetForward().Heading());\n\tfloat angle   = DEGTORAD(heading);\n\n\tCVector2D rotOffset(-Sin(angle), Cos(angle));\n\trotOffset.Normalise();\n\n\tCVector gunflashPos = *fireSource;\n\tgunflashPos += CVector(rotOffset.x*0.1f, rotOffset.y*0.1f, 0.0f);\n\tCParticle::AddParticle(PARTICLE_GUNFLASH, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.0f);\n\tgunflashPos += CVector(rotOffset.x*0.1f, rotOffset.y*0.1f, 0.0f);\n\tCParticle::AddParticle(PARTICLE_GUNFLASH, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.15f);\n\tgunflashPos += CVector(rotOffset.x*0.1f, rotOffset.y*0.1f, 0.0f);\n\tCParticle::AddParticle(PARTICLE_GUNFLASH, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.2f);\n\tCParticle::AddParticle(PARTICLE_GUNFLASH, *fireSource, CVector(0.0f, 0.0f, 0.0f), nil, 0.0f);\n\n\tCVector gunsmokePos = *fireSource;\n\tCParticle::AddParticle(PARTICLE_GUNSMOKE2, gunsmokePos, CVector(rotOffset.x*0.10f, rotOffset.y*0.10f, 0.0f), nil, 0.1f);\n\tCParticle::AddParticle(PARTICLE_GUNSMOKE2, gunsmokePos, CVector(rotOffset.x*0.15f, rotOffset.y*0.15f, 0.0f), nil, 0.1f);\n\tCParticle::AddParticle(PARTICLE_GUNSMOKE2, gunsmokePos, CVector(rotOffset.x*0.20f, rotOffset.y*0.20f, 0.0f), nil, 0.1f);\n\tCParticle::AddParticle(PARTICLE_GUNSMOKE2, gunsmokePos, CVector(rotOffset.x*0.25f, rotOffset.y*0.25f, 0.0f), nil, 0.1f);\n\n\tCEventList::RegisterEvent(EVENT_GUNSHOT, EVENT_ENTITY_PED, shooter, (CPed*)shooter, 1000);\n\n\tCPointLights::AddLight(CPointLights::LIGHT_POINT, *fireSource, CVector(0.0, 0.0, 0.0), 5.0f,\n\t\t\t\t\t\t\t1.0f, 0.8f, 0.0f, CPointLights::FOG_NONE, false);\n\n\tfloat shooterAngle;\n\n\tif ( shooter->IsPed() && ((CPed*)shooter)->m_pPointGunAt != nil )\n\t{\n\t\tCEntity *threatAttack = ((CPed*)shooter)->m_pPointGunAt;\n\t\tshooterAngle = CGeneral::GetAngleBetweenPoints(threatAttack->GetPosition().x, threatAttack->GetPosition().y,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t(*fireSource).x, (*fireSource).y);\n\t}\n\telse\n\t\tshooterAngle = RADTODEG(shooter->GetForward().Heading());\n\n\tint shootsAtOnce;\n\tint checkObstacleOnShootNo;\n\tfloat angleRange;\n\tswitch (m_eWeaponType) {\n\t\tcase WEAPONTYPE_SHOTGUN:\n\t\t\tangleRange = DEGTORAD(9.0f);\n\t\t\tcheckObstacleOnShootNo = 1;\n\t\t\tshootsAtOnce = 3;\n\t\t\tbreak;\n\t\tcase WEAPONTYPE_SPAS12_SHOTGUN:\n\t\t\tangleRange = DEGTORAD(6.0f);\n\t\t\tcheckObstacleOnShootNo = 1;\n\t\t\tshootsAtOnce = 3;\n\t\t\tbreak;\n\t\tcase WEAPONTYPE_STUBBY_SHOTGUN:\n\t\t\tangleRange = DEGTORAD(18.0f);\n\t\t\tcheckObstacleOnShootNo = 2;\n\t\t\tshootsAtOnce = 5;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\tbool statUpdated = false;\n\tfloat halfAngleRange = angleRange / 2.f;\n\tfloat angleBetweenTwoShot = angleRange / (shootsAtOnce - 1.f);\n\n\tfor ( int32 i = 0; i < shootsAtOnce; i++ )\n\t{\n\t\tfloat shootAngle = DEGTORAD(RADTODEG(halfAngleRange - angleBetweenTwoShot * i) + shooterAngle);\n\t\tCVector2D shootRot(-Sin(shootAngle), Cos(shootAngle));\n\t\tshootRot.Normalise();\n\n\t\tCVector source, target;\n\t\tCColPoint point;\n\t\tCEntity *victim;\n\n\t\tif ( shooter == FindPlayerPed() && TheCamera.Cams[0].Using3rdPersonMouseCam() )\n\t\t{\n\t\t\tTheCamera.Find3rdPersonCamTargetVector(1.0f, *fireSource, source, target);\n\t\t\tCVector Left = CrossProduct(TheCamera.Cams[TheCamera.ActiveCam].Front, TheCamera.Cams[TheCamera.ActiveCam].Up);\n\n\t\t\tfloat f = (i - (shootsAtOnce / 2)) * angleBetweenTwoShot;\n\t\t\ttarget  = f * Left + target - source;\n\t\t\ttarget *= info->m_fRange;\n\t\t\ttarget += source;\n\t\t\tCWorld::bIncludeCarTyres = true;\n\t\t\tCWorld::bIncludeBikers = true;\n\t\t\tCWorld::bIncludeDeadPeds = true;\n\t\t\tProcessLineOfSight(source, target, point, victim, m_eWeaponType, shooter, true, true, true, true, true, false, false);\n\t\t\tCWorld::bIncludeDeadPeds = false;\n\t\t\tCWorld::bIncludeCarTyres = false;\n\t\t}\n\t\telse\n\t\t{\n\t\t\ttarget = *fireSource;\n\t\t\ttarget.x += shootRot.x * info->m_fRange;\n\t\t\ttarget.y += shootRot.y * info->m_fRange;\n\n\t\t\tif ( shooter->IsPed() )\n\t\t\t{\n\t\t\t\tCPed *shooterPed = (CPed *)shooter;\n\n\t\t\t\tif ( shooterPed->m_pPointGunAt == nil )\n\t\t\t\t\tDoDoomAiming(shooter, fireSource, &target);\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tCVector pos;\n\t\t\t\t\tif (shooterPed->m_pPointGunAt->IsPed()) {\n\t\t\t\t\t\t((CPed*)shooterPed->m_pPointGunAt)->m_pedIK.GetComponentPosition(pos, PED_MID);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tpos = ((CPed*)shooterPed->m_pPointGunAt)->GetPosition();\n\t\t\t\t\t}\n\n\t\t\t\t\tfloat distToTarget = (pos - (*fireSource)).Magnitude2D();\n\t\t\t\t\ttarget.z += info->m_fRange / distToTarget * (pos.z - target.z);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (shooter == FindPlayerPed())\n\t\t\t\tCWorld::bIncludeDeadPeds = true;\n\n\t\t\tCWorld::bIncludeBikers = true;\n\t\t\tProcessLineOfSight(*fireSource, target, point, victim, m_eWeaponType, shooter, true, true, true, true, true, false, false);\n\t\t\tCWorld::bIncludeDeadPeds = false;\n\t\t}\n\t\tCWorld::bIncludeBikers = false;\n\n\t\tif ( victim )\n\t\t{\n\t\t\tCGlass::WasGlassHitByBullet(victim, point.point);\n\t\t\tCWeapon::BlowUpExplosiveThings(victim);\n\t\t\tif (i == checkObstacleOnShootNo)\n\t\t\t{\n\t\t\t\tif (shooter)\n\t\t\t\t{\n\t\t\t\t\tif (shooter->IsPed() && !((CPed*)shooter)->IsPlayer())\n\t\t\t\t\t{\n\t\t\t\t\t\tCPed *shooterPed = (CPed*)shooter;\n\t\t\t\t\t\tCEntity *guyWePointGun = shooterPed->m_pPointGunAt;\n\t\t\t\t\t\tif (guyWePointGun)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (victim != guyWePointGun)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tfloat distWithAim = (guyWePointGun->GetPosition() - shooter->GetPosition()).Magnitude();\n\t\t\t\t\t\t\t\tfloat distWithBullet = (point.point - shooter->GetPosition()).Magnitude();\n\t\t\t\t\t\t\t\tif (distWithAim > 0.1f && distWithBullet > 0.1f)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t// Normalize\n\t\t\t\t\t\t\t\t\tCVector aimDir = (guyWePointGun->GetPosition() - shooter->GetPosition()) * (1.0f / distWithAim);\n\t\t\t\t\t\t\t\t\tCVector bulletDir = (point.point - shooter->GetPosition()) * (1.0f / distWithBullet);\n\n\t\t\t\t\t\t\t\t\tfloat dotProd = DotProduct(aimDir, bulletDir);\n\t\t\t\t\t\t\t\t\tfloat aimAndBulletAngle;\n\t\t\t\t\t\t\t\t\tif (dotProd <= 0.35f)\n\t\t\t\t\t\t\t\t\t\taimAndBulletAngle = PI;\n\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t\taimAndBulletAngle = Acos(dotProd);\n\n\t\t\t\t\t\t\t\t\tif (aimAndBulletAngle <= DEGTORAD(45.0f) && (aimAndBulletAngle <= DEGTORAD(15.0f) || distWithBullet / distWithAim >= 0.75f) && distWithBullet / distWithAim >= 0.99f)\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tshooterPed->bObstacleShowedUpDuringKillObjective = false;\n\t\t\t\t\t\t\t\t\t\tshooterPed->m_shotTime = 0;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tshooterPed->bObstacleShowedUpDuringKillObjective = true;\n\t\t\t\t\t\t\t\t\t\tshooterPed->m_shootTimer = 0;\n\t\t\t\t\t\t\t\t\t\tshooterPed->m_shotTime = CTimer::GetTimeInMilliseconds();\n\t\t\t\t\t\t\t\t\t\tif (distWithAim < 10.0f)\n\t\t\t\t\t\t\t\t\t\t\tshooterPed->SetAttackTimer(1500);\n\t\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t\t\tshooterPed->SetAttackTimer(3000);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tCBulletTraces::AddTrace(fireSource, &point.point, m_eWeaponType, shooter);\n\n\t\t\tif ( victim->IsPed() )\n\t\t\t{\n\t\t\t\tCPed *victimPed = (CPed *)victim;\n\t\t\t\tif ( !victimPed->DyingOrDead() && victim != shooter )\n\t\t\t\t{\n\t\t\t\t\tbool cantStandup = true;\n\n\t\t\t\t\tCVector pos = victimPed->GetPosition();\n\n\t\t\t\t\tCVector2D posOffset((*fireSource).x-pos.x, (*fireSource).y-pos.y);\n\t\t\t\t\tint32 localDir = victimPed->GetLocalDirection(posOffset);\n\n\t\t\t\t\tvictimPed->ReactToAttack(FindPlayerPed());\n\n\t\t\t\t\tposOffset.Normalise();\n\n\t\t\t\t\tif ( victimPed->m_getUpTimer > (CTimer::GetTimeInMilliseconds() - 3000) || \n\t\t\t\t\t\t!victimPed->bCanBeShotInVehicle)\n\t\t\t\t\t\tcantStandup = false;\n\n\t\t\t\t\tif ( victimPed->bIsStanding && cantStandup )\n\t\t\t\t\t{\n\t\t\t\t\t\tvictimPed->bIsStanding = false;\n\n\t\t\t\t\t\tvictimPed->ApplyMoveForce(posOffset.x*-6.0f, posOffset.y*-6.0f, 5.0f);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t\tvictimPed->ApplyMoveForce(posOffset.x*-2.0f, posOffset.y*-2.0f, 0.0f);\n\n\t\t\t\t\tif ( cantStandup )\n\t\t\t\t\t\tvictimPed->SetFall(1500, AnimationId(ANIM_STD_HIGHIMPACT_FRONT + localDir), false);\n\n\t\t\t\t\tvictimPed->InflictDamage(shooter, m_eWeaponType, info->m_nDamage, (ePedPieceTypes)point.pieceB, localDir);\n\n\t\t\t\t\tif ( victimPed->m_nPedType == PEDTYPE_COP )\n\t\t\t\t\t\tCEventList::RegisterEvent(EVENT_SHOOT_COP, EVENT_ENTITY_PED, victim, (CPed*)shooter, 10000);\n\t\t\t\t\telse\n\t\t\t\t\t\tCEventList::RegisterEvent(EVENT_SHOOT_PED, EVENT_ENTITY_PED, victim, (CPed*)shooter, 10000);\n\n\t\t\t\t\tif ( CGame::nastyGame )\n\t\t\t\t\t{\n\t\t\t\t\t\tuint8 bloodAmount = 8;\n\t\t\t\t\t\tif ( IsShotgun(m_eWeaponType) )\n\t\t\t\t\t\t\tbloodAmount = 32;\n\n\t\t\t\t\t\tCVector dir = (point.point - victim->GetPosition()) * 0.01f;\n\t\t\t\t\t\tdir.z = 0.01f;\n\n\t\t\t\t\t\tif ( victimPed->GetIsOnScreen() )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tfor ( uint8 i = 0; i < bloodAmount; i++ )\n\t\t\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_BLOOD_SMALL, point.point, dir);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (CGame::nastyGame)\n\t\t\t\t\t{\n\t\t\t\t\t\tCVector dir = (point.point - victim->GetPosition()) * 0.01f;\n\t\t\t\t\t\tdir.z = 0.01f;\n\n\t\t\t\t\t\tif (victimPed->GetIsOnScreen())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tfor (uint8 i = 0; i < 8; i++)\n\t\t\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_BLOOD_SMALL, point.point + CVector(0.0f, 0.0f, 0.15f), dir);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (victimPed->Dead())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tCAnimBlendAssociation *hitAssoc;\n\t\t\t\t\t\t\tif (RpAnimBlendClumpGetFirstAssociation(victimPed->GetClump(), ASSOC_FRONTAL))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\thitAssoc = CAnimManager::BlendAnimation(victimPed->GetClump(), ASSOCGRP_STD, ANIM_STD_HIT_FLOOR_FRONT, 8.0f);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\thitAssoc = CAnimManager::BlendAnimation(victimPed->GetClump(), ASSOCGRP_STD, ANIM_STD_HIT_FLOOR, 8.0f);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (hitAssoc)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\thitAssoc->SetCurrentTime(0.0f);\n\t\t\t\t\t\t\t\thitAssoc->SetRun();\n\t\t\t\t\t\t\t\thitAssoc->flags &= ~ASSOC_DELETEFADEDOUT;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tswitch ( victim->GetType() )\n\t\t\t\t{\n\t\t\t\t\tcase ENTITY_TYPE_VEHICLE:\n\t\t\t\t\t{\n\t\t\t\t\t\tif (point.pieceB >= CAR_PIECE_WHEEL_LF && point.pieceB <= CAR_PIECE_WHEEL_RR) {\n\t\t\t\t\t\t\t((CVehicle*)victim)->BurstTyre(point.pieceB, true);\n\n\t\t\t\t\t\t\tfor (int32 i = 0; i < 4; i++)\n\t\t\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_BULLETHIT_SMOKE, point.point, point.normal * 0.05f);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t((CVehicle*)victim)->InflictDamage(shooter, m_eWeaponType, info->m_nDamage);\n\n\t\t\t\t\t\t\tfor (int32 i = 0; i < 16; i++)\n\t\t\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_SPARK, point.point, point.normal * 0.05f);\n\n#ifndef FIX_BUGS\n\t\t\t\t\t\t\tCVector dist = point.point - (*fireSource);\n\t\t\t\t\t\t\tCVector offset = dist - Max(0.2f * dist.Magnitude(), 2.0f) * CVector(shootRot.x, shootRot.y, 0.0f);\n\t\t\t\t\t\t\tCVector smokePos = *fireSource + offset;\n#else\n\t\t\t\t\t\t\tCVector smokePos = point.point;\n#endif\n\n\t\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_BULLETHIT_SMOKE, smokePos, CVector(0.0f, 0.0f, 0.0f));\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tcase ENTITY_TYPE_BUILDING:\n\t\t\t\t\tcase ENTITY_TYPE_OBJECT:\n\t\t\t\t\t{\n\t\t\t\t\t\tfor ( int32 i = 0; i < 16; i++ )\n\t\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_SPARK, point.point, point.normal*0.05f);\n\n#ifndef FIX_BUGS\n\t\t\t\t\t\tCVector dist = point.point - (*fireSource);\n\t\t\t\t\t\tCVector offset = dist - Max(0.2f*dist.Magnitude(), 2.0f) * CVector(shootRot.x, shootRot.y, 0.0f);\n\t\t\t\t\t    CVector smokePos = *fireSource + offset;\n#else\n\t\t\t\t\t    CVector smokePos = point.point;\n#endif\n\n\t\t\t\t\t\tsmokePos.x += CGeneral::GetRandomNumberInRange(-0.2f, 0.2f);\n\t\t\t\t\t\tsmokePos.y += CGeneral::GetRandomNumberInRange(-0.2f, 0.2f);\n\t\t\t\t\t\tsmokePos.z += CGeneral::GetRandomNumberInRange(-0.2f, 0.2f);\n\n\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_BULLETHIT_SMOKE, smokePos, CVector(0.0f, 0.0f, 0.0f));\n\n\t\t\t\t\t\tif ( victim->IsObject() )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tCObject *victimObject = (CObject *)victim;\n\n\t\t\t\t\t\t\tif ( !victimObject->bInfiniteMass )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tbool notStatic = !victimObject->GetIsStatic();\n\t\t\t\t\t\t\t\tif ( notStatic && victimObject->m_fUprootLimit <= 0.0f )\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tvictimObject->SetIsStatic(false);\n\t\t\t\t\t\t\t\t\tvictimObject->AddToMovingList();\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tnotStatic = !victimObject->GetIsStatic();\n\t\t\t\t\t\t\t\tif ( !notStatic )\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tCVector moveForce = point.normal*-5.0f;\n\t\t\t\t\t\t\t\t\tvictimObject->ApplyMoveForce(moveForce.x, moveForce.y, moveForce.z);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tdefault: break;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tswitch ( victim->GetType() )\n\t\t\t{\n\t\t\t\tcase ENTITY_TYPE_BUILDING:\n\t\t\t\t{\n\t\t\t\t\tPlayOneShotScriptObject(SCRIPT_SOUND_BULLET_HIT_GROUND_1, point.point);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase ENTITY_TYPE_VEHICLE:\n\t\t\t\t{\n\t\t\t\t\tif (!statUpdated) {\n\t\t\t\t\t\tCStats::BulletsThatHit++;\n\t\t\t\t\t\tstatUpdated = true;\n\t\t\t\t\t}\n\t\t\t\t\tDMAudio.PlayOneShot(((CPhysical*)victim)->m_audioEntityId, SOUND_WEAPON_HIT_VEHICLE, 1.0f);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase ENTITY_TYPE_PED:\n\t\t\t\t{\n\t\t\t\t\tif (!statUpdated) {\n\t\t\t\t\t\tCStats::BulletsThatHit++;\n\t\t\t\t\t\tstatUpdated = true;\n\t\t\t\t\t}\n\t\t\t\t\tDMAudio.PlayOneShot(((CPhysical*)victim)->m_audioEntityId, SOUND_WEAPON_HIT_PED, 1.0f);\n\t\t\t\t\t((CPed*)victim)->Say(SOUND_PED_BULLET_HIT);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase ENTITY_TYPE_OBJECT:\n\t\t\t\t{\n\t\t\t\t\tif (!statUpdated) {\n\t\t\t\t\t\tCStats::BulletsThatHit++;\n\t\t\t\t\t\tstatUpdated = true;\n\t\t\t\t\t}\n\t\t\t\t\tPlayOneShotScriptObject(SCRIPT_SOUND_BULLET_HIT_GROUND_2, point.point);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase ENTITY_TYPE_DUMMY:\n\t\t\t\t{\n\t\t\t\t\tPlayOneShotScriptObject(SCRIPT_SOUND_BULLET_HIT_GROUND_3, point.point);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tdefault: break;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tCVector traceTarget = *fireSource;\n\t\t\ttraceTarget += (target - (*fireSource)) * Min(info->m_fRange, 30.0f) / info->m_fRange;\n\t\t\tCBulletTraces::AddTrace(fireSource, &traceTarget, m_eWeaponType, shooter);\n\t\t}\n\t}\n\n\tif ( shooter == FindPlayerPed() )\n\t\tCPad::GetPad(0)->StartShake_Distance(240, 128, FindPlayerPed()->GetPosition().x, FindPlayerPed()->GetPosition().y, FindPlayerPed()->GetPosition().z);\n\n\treturn true;\n}\n\nbool\nCWeapon::FireProjectile(CEntity *shooter, CVector *fireSource, float power)\n{\n\tASSERT(shooter!=nil);\n\tASSERT(fireSource!=nil);\n\n\tCVector source, target;\n\teWeaponType projectileType = m_eWeaponType;\n\n\tif ( m_eWeaponType == WEAPONTYPE_ROCKETLAUNCHER )\n\t{\n\t\tsource = *fireSource;\n\t\tprojectileType = WEAPONTYPE_ROCKET;\n\n\t\tif ( shooter->IsPed() && ((CPed*)shooter)->IsPlayer() )\n\t\t{\n\t\t\tint16 mode = TheCamera.Cams[TheCamera.ActiveCam].Mode;\n\t\t\tif (!( mode == CCam::MODE_M16_1STPERSON\n\t\t\t\t|| mode == CCam::MODE_SNIPER\n\t\t\t\t|| mode == CCam::MODE_ROCKETLAUNCHER\n\t\t\t\t|| mode == CCam::MODE_M16_1STPERSON_RUNABOUT\n\t\t\t\t|| mode == CCam::MODE_SNIPER_RUNABOUT\n\t\t\t\t|| mode == CCam::MODE_ROCKETLAUNCHER_RUNABOUT) )\n\t\t\t{\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t*fireSource += TheCamera.Cams[TheCamera.ActiveCam].Front;\n\t\t}\n\t\telse\n\t\t\t*fireSource += shooter->GetForward();\n\n\t\ttarget = *fireSource;\n\t}\n\telse\n\t{\n\t\tfloat dot = DotProduct(*fireSource-shooter->GetPosition(), shooter->GetForward());\n\n\t\tif ( dot < 0.3f )\n\t\t\t*fireSource += (0.3f-dot) * shooter->GetForward();\n\n\t\ttarget = *fireSource;\n\n\t\tif ( target.z - shooter->GetPosition().z > 0.0f )\n\t\t\ttarget += 0.6f*shooter->GetForward();\n\n\t\tsource = *fireSource - shooter->GetPosition();\n\n\t\tsource = *fireSource - DotProduct(source, shooter->GetForward()) * shooter->GetForward();\n\t}\n\n\tif ( !CWorld::GetIsLineOfSightClear(source, target, true, true, false, true, false, false, false) )\n\t{\n\t\tif ( m_eWeaponType != WEAPONTYPE_GRENADE )\n\t\t\tCProjectileInfo::RemoveNotAdd(shooter, projectileType, *fireSource);\n\t\telse\n\t\t{\n\t\t\tif ( shooter->IsPed() )\n\t\t\t{\n\t\t\t\tsource    = shooter->GetPosition() - shooter->GetForward();\n\t\t\t\tsource.z -= 0.4f;\n\n\t\t\t\tif ( !CWorld::TestSphereAgainstWorld(source, 0.5f, nil, false, false, true, false, false, false) )\n\t\t\t\t\tCProjectileInfo::AddProjectile(shooter, WEAPONTYPE_GRENADE, source, 0.0f);\n\t\t\t\telse\n\t\t\t\t\tCProjectileInfo::RemoveNotAdd(shooter, WEAPONTYPE_GRENADE, *fireSource);\n\t\t\t}\n\t\t}\n\t}\n\telse\n\t\tCProjectileInfo::AddProjectile(shooter, projectileType, *fireSource, power);\n\t\n\t\t\t\n\tCWorld::pIgnoreEntity = nil;\n\t\t\n\tif ( shooter->IsPed() )\n\t\tCEventList::RegisterEvent(EVENT_GUNSHOT, EVENT_ENTITY_PED,     shooter, (CPed *)shooter,                1000);\n\telse if ( shooter->IsVehicle() && ((CVehicle*)shooter)->pDriver )\n\t\tCEventList::RegisterEvent(EVENT_GUNSHOT, EVENT_ENTITY_VEHICLE, shooter, ((CVehicle*)shooter)->pDriver,  1000);\n\n\treturn true;\n}\n\nvoid\nCWeapon::GenerateFlameThrowerParticles(CVector pos, CVector dir)\n{\n\tdir *= 0.7f;\n\tCParticle::AddParticle(PARTICLE_FIREBALL, pos, dir);\n\n\tdir *= 0.7f;\n\tCParticle::AddParticle(PARTICLE_FIREBALL, pos, dir);\n\n\tdir *= 0.7f;\n\tCParticle::AddParticle(PARTICLE_FIREBALL, pos, dir);\n\n\tdir *= 0.7f;\n\tCParticle::AddParticle(PARTICLE_FIREBALL, pos, dir);\n\n\tdir *= 0.7f;\n\tCParticle::AddParticle(PARTICLE_FIREBALL, pos, dir);\n}\n\nbool\nCWeapon::FireAreaEffect(CEntity *shooter, CVector *fireSource)\n{\n\tASSERT(shooter!=nil);\n\tASSERT(fireSource!=nil);\n\n\tCWeaponInfo *info = GetInfo();\n\n\tfloat heading = RADTODEG(shooter->GetForward().Heading());\n\n\tCVector source;\n\tCVector target;\n\tCVector dir;\n\n\tif ( shooter == FindPlayerPed() && TheCamera.Cams[0].Using3rdPersonMouseCam() )\n\t{\n\t\tTheCamera.Find3rdPersonCamTargetVector(info->m_fRange, *fireSource, source, target);\n\t\tfloat norm = (1.0f / info->m_fRange);\n\t\tdir = (target - source) * norm;\n\t}\n\telse\n\t{\n\t\tfloat angle = DEGTORAD(heading);\n\t\tdir         = CVector(-Sin(angle)*0.5f, Cos(angle)*0.5f, 0.0f);\n\t\ttarget      = *fireSource + dir;\n\t}\n\n\tCShotInfo::AddShot(shooter, m_eWeaponType, *fireSource, target);\n\tCWeapon::GenerateFlameThrowerParticles(*fireSource, dir);\n\t\t\n\tif ( shooter == (CEntity *)FindPlayerPed() )\n\t{\n\t\tfor ( int32 i = 0; i < FindPlayerPed()->m_numNearPeds; i++ )\n\t\t{\n\t\t\tif ( FindPlayerPed()->m_nearPeds[i]->CharCreatedBy == RANDOM_CHAR )\n\t\t\t{\n\t\t\t\tif ( FindPlayerPed()->m_nearPeds[i]->IsPedInControl() && FindPlayerPed()->m_nearPeds[i]->m_nPedState != PED_FLEE_ENTITY )\n\t\t\t\t\tFindPlayerPed()->m_nearPeds[i]->SetFlee(shooter, 10000);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn true;\n}\n\nbool\nCWeapon::LaserScopeDot(CVector *pOutPos, float *pOutSize)\n{\n\tCWeaponInfo *info = GetInfo();\n\t\n\tfloat range = info->m_fRange;\n\t\n\tCVector source, target;\n\tCEntity *foundEnt = nil;\n\tCColPoint foundCol;\n\t\n\tsource = 0.5f * TheCamera.Cams[TheCamera.ActiveCam].Front + TheCamera.Cams[TheCamera.ActiveCam].Source;\n\ttarget = TheCamera.Cams[TheCamera.ActiveCam].Front;\n\ttarget.Normalise();\n\ttarget *= range;\n\ttarget += source;\n\t\n\tif ( CWorld::ProcessLineOfSight(source, target, foundCol, foundEnt, true, true, true, true, false, false, false) )\n\t{\n\t\tCVector pos = foundCol.point;\n\t\tfloat w, h;\n\t\t\n\t\tif ( CSprite::CalcScreenCoors(foundCol.point, &pos, &w, &h, true) )\n\t\t{\n\t\t\t*pOutPos = pos;\n\t\t\t*pOutSize = w * 0.05f;\n\t\t\t\n\t\t\tCCoronas::RegisterCorona((uintptr)this + 7, 128, 0, 0, 255, pos, 1.2f, 50.0f, CCoronas::TYPE_STAR, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_ON, 0.0f);\n\t\t\t\n\t\t\treturn true;\n\t\t}\n\t}\n\t\t\n\treturn false;\n}\n\nbool\nCWeapon::FireSniper(CEntity *shooter)\n{\n\tASSERT(shooter!=nil);\n\t\n\tif ( (CEntity *)FindPlayerPed() == shooter )\n\t{\n\t\tint16 mode = TheCamera.Cams[TheCamera.ActiveCam].Mode;\n\t\tif (!( mode == CCam::MODE_M16_1STPERSON\n\t\t\t|| mode == CCam::MODE_SNIPER\n\t\t\t|| mode == CCam::MODE_CAMERA\n\t\t\t|| mode == CCam::MODE_ROCKETLAUNCHER\n\t\t\t|| mode == CCam::MODE_M16_1STPERSON_RUNABOUT\n\t\t\t|| mode == CCam::MODE_SNIPER_RUNABOUT\n\t\t\t|| mode == CCam::MODE_ROCKETLAUNCHER_RUNABOUT) )\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t}\n\n#ifdef SECUROM\n\tif (sniperPirateCheck){\n\t\t// if not pirated game\n\t\t// sniperPirateCheck = 0;\n\t}\n#endif\n\n#ifndef FIX_BUGS\n\tCWeaponInfo *info = GetInfo(); //unused\n#endif\n\n\tCCam *cam = &TheCamera.Cams[TheCamera.ActiveCam];\n\tASSERT(cam!=nil);\n\n\tCVector source = cam->Source;\n\tCVector dir    = cam->Front;\n\n\tif ( DotProduct(dir, CVector(0.0f, -0.9894f, 0.145f)) > 0.997f )\n\t\tCCoronas::MoonSize = (CCoronas::MoonSize+1) & 7;\n\n\tdir.Normalise();\n\tdir *= 16.0f;\n\n#ifdef SECUROM\n\tif (sniperPirateCheck) return true;\n#endif\n\n\tCBulletInfo::AddBullet(shooter, m_eWeaponType, source, dir);\n\n\tif ( shooter == FindPlayerPed() )\n\t{\n\t\tCPad::GetPad(0)->StartShake_Distance(240, 128,\n\t\t\tFindPlayerPed()->GetPosition().x,\n\t\t\tFindPlayerPed()->GetPosition().y,\n\t\t\tFindPlayerPed()->GetPosition().z);\n\t\t\t\n\t\tCParticle::HandleShootableBirdsStuff(shooter, source);\n\n\t\tCamShakeNoPos(&TheCamera, 0.2f);\n\t}\n\n\tif ( shooter->IsPed() )\n\t\tCEventList::RegisterEvent(EVENT_GUNSHOT, EVENT_ENTITY_PED,     shooter, (CPed*)shooter,                1000);\n\telse if ( shooter->IsVehicle() && ((CVehicle*)shooter)->pDriver )\n\t\tCEventList::RegisterEvent(EVENT_GUNSHOT, EVENT_ENTITY_VEHICLE, shooter, ((CVehicle*)shooter)->pDriver, 1000);\n\n\treturn true;\n}\n\nbool\nCWeapon::TakePhotograph(CEntity *shooter)\n{\n\tif ( TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_CAMERA )\n\t{\n\t\tCSpecialFX::bSnapShotActive = true;\n\t\tCSpecialFX::SnapShotFrames = 0;\n\t\tCStats::PhotosTaken++;\n\t\tbPhotographHasBeenTaken = true;\n\t\t\n\t\tfor ( int32 i = CPools::GetPedPool()->GetSize() - 1; i >= 0; i--)\n\t\t{\n\t\t\tCPed *ped = CPools::GetPedPool()->GetSlot(i);\n\t\t\tif ( ped )\n\t\t\t{\n\t\t\t\tif ( (ped->GetPosition() - TheCamera.GetPosition()).Magnitude() < 125.0f )\n\t\t\t\t{\n\t\t\t\t\tCVector pedPos = ped->GetPosition();\n\t\t\t\t\tpedPos.z += 0.8f;\n\t\t\t\t\t\n\t\t\t\t\tCVector pos;\n\t\t\t\t\tfloat w, h;\n\t\t\t\t\t\n\t\t\t\t\tif ( CSprite::CalcScreenCoors(pedPos, &pos, &w, &h, false) )\n\t\t\t\t\t{\n\t\t\t\t\t\tif (   SCREEN_WIDTH  * 0.1f < pos.x && SCREEN_WIDTH  * 0.9f > pos.x\n\t\t\t\t\t\t\t&& SCREEN_HEIGHT * 0.1f < pos.y && SCREEN_HEIGHT * 0.9f > pos.y )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tCVector source, target;\n\t\t\t\t\t\t\tCEntity *foundEnt = nil;\n\t\t\t\t\t\t\tCColPoint foundCol;\n\t\n\t\t\t\t\t\t\ttarget = pedPos;\n\t\t\t\t\t\t\tsource = TheCamera.GetForward() * 2.0f + TheCamera.GetPosition();\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tif ( CWorld::ProcessLineOfSight(source, target, foundCol, foundEnt, true, true, true, true, true, true, false) )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tif ( foundEnt != (CEntity*)ped )\n\t\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tped->bHasBeenPhotographed = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t\n\t\treturn true;\n\t}\n\t\n\treturn false;\n}\n\nbool\nCWeapon::FireM16_1stPerson(CEntity *shooter)\n{\n\tASSERT(shooter!=nil);\n\n\tint16 mode = TheCamera.Cams[TheCamera.ActiveCam].Mode;\n\n\tif (!( mode == CCam::MODE_M16_1STPERSON\n\t\t|| mode == CCam::MODE_SNIPER\n\t\t|| mode == CCam::MODE_CAMERA\n\t\t|| mode == CCam::MODE_ROCKETLAUNCHER\n\t\t|| mode == CCam::MODE_M16_1STPERSON_RUNABOUT\n\t\t|| mode == CCam::MODE_SNIPER_RUNABOUT\n\t\t|| mode == CCam::MODE_ROCKETLAUNCHER_RUNABOUT\n\t\t|| mode == CCam::MODE_HELICANNON_1STPERSON) )\n\t{\n\t\treturn false;\n\t}\n\n\tCWeaponInfo *info = GetInfo();\n\n\tCWorld::bIncludeCarTyres = true;\n\tCWorld::bIncludeBikers   = true;\n\n\tCColPoint point;\n\tCEntity *victim;\n\n\tCWorld::pIgnoreEntity = shooter;\n\tCWorld::bIncludeDeadPeds = true;\n\n\tCCam *cam = &TheCamera.Cams[TheCamera.ActiveCam];\n\tASSERT(cam!=nil);\n\n\tCVector source = cam->Source;\n\tCVector target = cam->Front*info->m_fRange + source;\n\n\tif (ProcessLineOfSight(source, target, point, victim, m_eWeaponType, shooter, true, true, true, true, true, true, false)) {\n\t\tCheckForShootingVehicleOccupant(&victim, &point, m_eWeaponType, source, target);\n\t}\n\tCWorld::pIgnoreEntity = nil;\n\tCWorld::bIncludeDeadPeds = false;\n\tCWorld::bIncludeBikers = false;\n\tCWorld::bIncludeCarTyres = false;\n\n\tCVector2D front(cam->Front.x, cam->Front.y);\n\tfront.Normalise();\n\n\tDoBulletImpact(shooter, victim, &source, &target, &point, front);\n\n\tCVector bulletPos;\n\n\tif ( CHeli::TestBulletCollision(&source, &target, &bulletPos, (m_eWeaponType == WEAPONTYPE_M60 || m_eWeaponType == WEAPONTYPE_HELICANNON ? 20 : 4)) )\n\t{\n\t\tfor ( int32 i = 0; i < 16; i++ )\n\t\t\tCParticle::AddParticle(PARTICLE_SPARK, bulletPos, CVector(0.0f, 0.0f, 0.0f));\n\t}\n\n\tif ( shooter == FindPlayerPed() )\n\t{\n\t\tfloat mult;\n\t\tswitch (m_eWeaponType) {\n\t\t\tcase WEAPONTYPE_M4:\n\t\t\t\tmult = 0.0003f;\n\t\t\t\tbreak;\n\t\t\tcase WEAPONTYPE_RUGER:\n\t\t\t\tmult = 0.00015f;\n\t\t\t\tbreak;\n\t\t\tcase WEAPONTYPE_HELICANNON:\n\t\t\tcase WEAPONTYPE_M60:\n\t\t\t\tmult = 0.0003f;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tmult = 0.0002f;\n\t\t\t\tbreak;\n\t\t}\n\n\t\tif (FindPlayerPed()->bIsDucking || FindPlayerPed()->m_attachedTo)\n\t\t\tmult *= 0.3f;\n\n\t\tTheCamera.Cams[TheCamera.ActiveCam].Beta  += float((CGeneral::GetRandomNumber() & 127) - 64) * mult;\n\t\tTheCamera.Cams[TheCamera.ActiveCam].Alpha += float((CGeneral::GetRandomNumber() & 127) - 64) * mult;\n\n\t\t// yes, double\n\t\tdouble notFiringRate = (20.0 - info->m_nFiringRate) / 80.0;\n\t\tdouble raisedNotFiringRate = Max(1.0, Max(0.0, notFiringRate));\n\n\t\tuint8 shakeFreq = 80.0 * raisedNotFiringRate + 130.0;\n\t\tCPad::GetPad(0)->StartShake(20000.0f * CTimer::GetTimeStep() / shakeFreq, shakeFreq);\n\t}\n\n\treturn true;\n}\n\nbool\nCWeapon::FireInstantHitFromCar(CVehicle *shooter, bool left, bool right)\n{\n\tCWeaponInfo *info = GetInfo();\n\n\tCVehicleModelInfo *modelInfo = shooter->GetModelInfo();\n\t\n\tCVector source, target;\n\t\n\tif ( shooter->IsBike() )\n\t{\n\t\tif ( shooter->pDriver )\n\t\t{\n\t\t\tsource = info->m_vecFireOffset;\n\t\t\t\n\t\t\tshooter->pDriver->TransformToNode(source, PED_HANDR);\n\t\t\tsource += CTimer::GetTimeStep() * shooter->m_vecMoveSpeed;\n\t\t\t\n\t\t\tif ( left )\n\t\t\t\ttarget = source - info->m_fRange * shooter->GetRight();\n\t\t\telse if ( right )\n\t\t\t\ttarget = source + info->m_fRange * shooter->GetRight();\n\t\t\telse\n\t\t\t\ttarget = source + info->m_fRange * shooter->GetForward();\n\t\t\t\t\n\t\t}\n\t\telse if ( left )\n\t\t{\n\t\t\tsource = shooter->GetMatrix() * CVector(-shooter->GetColModel()->boundingBox.max.x + -0.25f,\n\t\t\t\t\t\t\t\t\t\t\t\t\tfloat(CGeneral::GetRandomNumber() & 255) * 0.001f + modelInfo->GetFrontSeatPosn().y - 0.05f,\n\t\t\t\t\t\t\t\t\t\t\t\t\tmodelInfo->GetFrontSeatPosn().z + 0.63f);\n\t\t\tsource += CTimer::GetTimeStep() * shooter->m_vecMoveSpeed;\n\t\n\t\n\t\t\ttarget = shooter->GetMatrix() * CVector(-info->m_fRange,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tmodelInfo->GetFrontSeatPosn().y,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tmodelInfo->GetFrontSeatPosn().z + 0.6f);\n\t\t}\n\t\telse if ( right )\n\t\t{\n\t\t\tsource = shooter->GetMatrix() * CVector(shooter->GetColModel()->boundingBox.max.x + 0.25f,\n\t\t\t\t\t\t\t\t\t\t\t\t\tfloat(CGeneral::GetRandomNumber() & 255) * 0.001f + modelInfo->GetFrontSeatPosn().y - 0.18f,\n\t\t\t\t\t\t\t\t\t\t\t\t\tmodelInfo->GetFrontSeatPosn().z + 0.52f);\n\t\t\tsource += CTimer::GetTimeStep() * shooter->m_vecMoveSpeed;\n\t\n\t\t\ttarget = shooter->GetMatrix() * CVector(info->m_fRange,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tmodelInfo->GetFrontSeatPosn().y,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tmodelInfo->GetFrontSeatPosn().z + 0.5f);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tsource = shooter->GetMatrix() * CVector(float(CGeneral::GetRandomNumber() & 255) * 0.001f + -0.4f,\n\t\t\t\t\t\t\t\t\t\t\t\t\tmodelInfo->GetFrontSeatPosn().y + shooter->GetColModel()->boundingBox.max.y + 0.2f,\n\t\t\t\t\t\t\t\t\t\t\t\t\tmodelInfo->GetFrontSeatPosn().z + 0.55f);\n\t\t\tsource += CTimer::GetTimeStep() * shooter->m_vecMoveSpeed;\n\t\n\t\t\ttarget = shooter->GetMatrix() * CVector(0.0f,\n\t\t\t\t\t\t\t\t\t\t\t\t\tinfo->m_fRange,\n\t\t\t\t\t\t\t\t\t\t\t\t\tmodelInfo->GetFrontSeatPosn().z + 0.5f);\n\t\t}\n\t}\n\telse\n\t{\n\t\tif ( left )\n\t\t\tsource = info->m_vecFireOffset;\n\t\telse\n\t\t{\n\t\t\tsource    = 1.8f * info->m_vecFireOffset;\n\t\t\tsource.z -= 0.1f;\n\t\t}\n\t\t\n\t\tshooter->pDriver->TransformToNode(source, PED_HANDR);\n\t\tsource += CTimer::GetTimeStep() * shooter->m_vecMoveSpeed;\n\t\t\n\t\tif ( left )\n\t\t\ttarget = source - info->m_fRange * shooter->GetRight();\n\t\telse\n\t\t\ttarget = source + info->m_fRange * shooter->GetRight();\n\t}\n\n\ttarget += CVector(float(CGeneral::GetRandomNumber()&255)*0.01f-1.28f,\n\t\t\t\t\t\tfloat(CGeneral::GetRandomNumber()&255)*0.01f-1.28f,\n\t\t\t\t\t\tfloat(CGeneral::GetRandomNumber()&255)*0.01f-1.28f);\n\n\tDoDriveByAutoAiming(FindPlayerPed(), shooter, &source, &target);\n\n\tCEventList::RegisterEvent(EVENT_GUNSHOT, EVENT_ENTITY_PED, FindPlayerPed(), FindPlayerPed(), 1000);\n\n\tif ( !TheCamera.GetLookingLRBFirstPerson() )\n\t{\n\t\tif ( !shooter->IsBike() )\n\t\t\tCParticle::AddParticle(PARTICLE_GUNFLASH, source, CVector(0.0f, 0.0f, 0.0f));\n\t\telse\n\t\t\tCParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, source, 1.4f*shooter->m_vecMoveSpeed);\n\t}\n\telse\n\t\tCParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, source, 1.6f*shooter->m_vecMoveSpeed, nil, 0.18f);\n\n\tCEventList::RegisterEvent(EVENT_GUNSHOT, EVENT_ENTITY_VEHICLE, shooter, FindPlayerPed(), 1000);\n\n\tCPointLights::AddLight(CPointLights::LIGHT_POINT, source, CVector(0.0f, 0.0f, 0.0f), 5.0f,\n\t\t1.0f, 0.8f, 0.0f, CPointLights::FOG_NONE, false);\n\n\tCColPoint point;\n\tCEntity *victim;\n\t\n\tCWorld::bIncludeBikers = true;\n\tCWorld::pIgnoreEntity = shooter;  \n\tProcessLineOfSight(source, target, point, victim, m_eWeaponType, shooter, true, true, true, true, true, true, false);\n\tCWorld::pIgnoreEntity = NULL;\n\tCWorld::bIncludeBikers = false;\n\n\tif ( !(CTimer::GetFrameCounter() & 3) )\n\t\tMakePedsJumpAtShot(shooter, &source, &target);\n\n\tif ( victim )\n\t{\n\t\tCVector traceTarget = point.point;\n\t\tCBulletTraces::AddTrace(&source, &traceTarget, m_eWeaponType, shooter);\n\n\t\tif ( victim->IsPed() )\n\t\t{\n\t\t\tCPed *victimPed = (CPed*)victim;\n\n\t\t\tif ( !victimPed->DyingOrDead() && victim != (CEntity *)shooter )\n\t\t\t{\n\t\t\t\tCVector pos = victimPed->GetPosition();\n\n\t\t\t\tCVector2D posOffset(source.x-pos.x, source.y-pos.y);\n\t\t\t\tint32 localDir = victimPed->GetLocalDirection(posOffset);\n\n\t\t\t\tvictimPed->ReactToAttack(FindPlayerPed());\n\t\t\t\tvictimPed->ClearAttackByRemovingAnim();\n\n\t\t\t\tCAnimBlendAssociation *asoc = CAnimManager::AddAnimation(victimPed->GetClump(), ASSOCGRP_STD, AnimationId(ANIM_STD_HITBYGUN_FRONT + localDir));\n\t\t\t\tASSERT(asoc!=nil);\n\t\t\t\tasoc->blendAmount = 0.0f;\n\t\t\t\tasoc->blendDelta  = 8.0f;\n\n\t\t\t\tvictimPed->InflictDamage(shooter, WEAPONTYPE_UZI_DRIVEBY, 3*info->m_nDamage, (ePedPieceTypes)point.pieceB, localDir);\n\n\t\t\t\tpos.z += 0.8f;\n\n\t\t\t\tif ( victimPed->GetIsOnScreen() )\n\t\t\t\t{\n\t\t\t\t\tif ( CGame::nastyGame )\n\t\t\t\t\t{\n\t\t\t\t\t\tfor ( int32 i = 0; i < 4; i++ )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tCVector dir;\n\t\t\t\t\t\t\tdir.x = CGeneral::GetRandomNumberInRange(-0.1f, 0.1f);\n\t\t\t\t\t\t\tdir.y = CGeneral::GetRandomNumberInRange(-0.1f, 0.1f);\n\t\t\t\t\t\t\tdir.z = CGeneral::GetRandomNumberInRange(-0.1f, 0.1f);\n\n\t\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_BLOOD, pos, dir);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( victimPed->m_nPedType == PEDTYPE_COP )\n\t\t\t\t\tCEventList::RegisterEvent(EVENT_SHOOT_COP, EVENT_ENTITY_PED, victimPed, FindPlayerPed(), 10000);\n\t\t\t\telse\n\t\t\t\t\tCEventList::RegisterEvent(EVENT_SHOOT_PED, EVENT_ENTITY_PED, victimPed, FindPlayerPed(), 10000);\n\t\t\t}\n\t\t}\n\t\telse if ( victim->IsVehicle() )\n\t\t\t((CVehicle *)victim)->InflictDamage(FindPlayerPed(), WEAPONTYPE_UZI_DRIVEBY, info->m_nDamage);\n\t\telse\n\t\t\tCGlass::WasGlassHitByBullet(victim, point.point);\n\n\t\tswitch ( victim->GetType() )\n\t\t{\n\t\t\tcase ENTITY_TYPE_BUILDING:\n\t\t\t{\n\t\t\t\tPlayOneShotScriptObject(SCRIPT_SOUND_BULLET_HIT_GROUND_1, point.point);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase ENTITY_TYPE_VEHICLE:\n\t\t\t{\n\t\t\t\tDMAudio.PlayOneShot(((CPhysical*)victim)->m_audioEntityId, SOUND_WEAPON_HIT_VEHICLE, 1.0f);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase ENTITY_TYPE_PED:\n\t\t\t{\n\t\t\t\tDMAudio.PlayOneShot(((CPhysical*)victim)->m_audioEntityId, SOUND_WEAPON_HIT_PED, 1.0f);\n\t\t\t\t((CPed*)victim)->Say(SOUND_PED_BULLET_HIT);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase ENTITY_TYPE_OBJECT:\n\t\t\t{\n\t\t\t\tPlayOneShotScriptObject(SCRIPT_SOUND_BULLET_HIT_GROUND_2, point.point);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase ENTITY_TYPE_DUMMY:\n\t\t\t{\n\t\t\t\tPlayOneShotScriptObject(SCRIPT_SOUND_BULLET_HIT_GROUND_3, point.point);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tdefault: break;\n\t\t}\n\t}\n\telse\n\t{\n\t\tfloat norm = 30.0f/info->m_fRange;\n\t\tCVector traceTarget = (target-source)*norm + source;\n\t\tCBulletTraces::AddTrace(&source, &traceTarget, m_eWeaponType, shooter);\n\t}\n\n\tif ( shooter == FindPlayerVehicle() )\n\t\tCPad::GetPad(0)->StartShake_Distance(240, 128, FindPlayerVehicle()->GetPosition().x, FindPlayerVehicle()->GetPosition().y, FindPlayerVehicle()->GetPosition().z);\n\n\treturn true;\n}\n\nvoid\nCWeapon::DoDoomAiming(CEntity *shooter, CVector *source, CVector *target)\n{\n\tASSERT(shooter!=nil);\n\tASSERT(source!=nil);\n\tASSERT(target !=nil);\n\n#ifndef FIX_BUGS\n\tCEntity entity; // unused\n#endif\n\n\tCPed *shooterPed = (CPed*)shooter;\n\n\tint16 lastEntity;\n\tCEntity *entities[16];\n\tCWorld::FindObjectsInRange(*source, (*target-*source).Magnitude(), true, &lastEntity, 15, entities, false, true, true, false, false);\n\n\tfloat closestEntityDist = 10000.0f;\n\tint16 closestEntity;\n\n\tfor ( int32 i = 0; i < lastEntity; i++ )\n\t{\n\t\tCEntity *victim = entities[i];\n\t\tASSERT(victim!=nil);\n\n\t\tif ( (CEntity*)shooterPed != victim && shooterPed->CanSeeEntity(victim, DEGTORAD(22.5f)) )\n\t\t{\n\t\t\tif ( !(victim->GetStatus() == STATUS_TRAIN_MOVING\n\t\t\t\t|| victim->GetStatus() == STATUS_TRAIN_NOT_MOVING\n\t\t\t\t|| victim->GetStatus() == STATUS_HELI\n\t\t\t\t|| victim->GetStatus() == STATUS_PLANE\n\t\t\t\t|| victim->GetStatus() == STATUS_WRECKED) )\n\t\t\t{\n\t\t\t\tfloat distToVictim   = (shooterPed->GetPosition()-victim->GetPosition()).Magnitude2D();\n\t\t\t\tfloat distToVictimZ  = Abs(shooterPed->GetPosition().z-victim->GetPosition().z);\n\n\t\t\t\tif ( 1.5f*distToVictimZ < distToVictim )\n\t\t\t\t{\n\t\t\t\t\tfloat entityDist = Sqrt(SQR(distToVictim) + SQR(distToVictimZ));\n\n\t\t\t\t\tif ( entityDist < closestEntityDist )\n\t\t\t\t\t{\n\t\t\t\t\t\tclosestEntityDist = entityDist;\n\t\t\t\t\t\tclosestEntity = i;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tCColPoint foundCol;\n\tCEntity *foundEnt;\n\tif (closestEntityDist < DOOMAUTOAIMING_MAXDIST\n\t\t&& !CWorld::ProcessLineOfSight(*source, entities[closestEntity]->GetPosition(), foundCol, foundEnt, true, false, false, false, false, false, false, true))\n\t{\n\t\tCEntity *victim = entities[closestEntity];\n\t\tASSERT(victim !=nil);\n\n\t\tfloat distToTarget = (*target - *source).Magnitude2D();\n\t\tfloat distToSource = (victim->GetPosition() - *source).Magnitude2D();\n\n\t\tfloat victimZ = victim->GetPosition().z + 0.3f;\n\t\tif ( victim->IsPed() )\n\t\t{\n\t\t\tif ( ((CPed*)victim)->bIsDucking )\n\t\t\t\tvictimZ -= 0.8f;\n\t\t}\n\n\t\t(*target).z = (distToTarget / distToSource) * (victimZ - (*source).z) + (*source).z;\n\t}\n}\n\nvoid\nCWeapon::DoTankDoomAiming(CEntity *shooter, CEntity *driver, CVector *source, CVector *target)\n{\n\tASSERT(shooter!=nil);\n\tASSERT(driver!=nil);\n\tASSERT(source!=nil);\n\tASSERT(target!=nil);\n\n#ifndef FIX_BUGS\n\tCEntity entity; // unused\n#endif\n\n\tint16 lastEntity;\n\tCEntity *entities[16];\n\tCWorld::FindObjectsInRange(*source, (*target-*source).Magnitude(), true, &lastEntity, 15, entities, false, true, false, false, false);\n\n\tfloat closestEntityDist = 10000.0f;\n\tint16 closestEntity;\n\n\tfloat normZ = (target->z - source->z) / (*target-*source).Magnitude();\n\n\tfor ( int32 i = 0; i < lastEntity; i++ )\n\t{\n\t\tCEntity *victim = entities[i];\n\n\t\tASSERT(victim!=nil);\n\n\t\tif ( shooter != victim && driver != victim )\n\t\t{\n\t\t\tif ( !(victim->GetStatus() == STATUS_TRAIN_MOVING\n\t\t\t\t|| victim->GetStatus() == STATUS_TRAIN_NOT_MOVING\n\t\t\t\t|| victim->GetStatus() == STATUS_HELI\n\t\t\t\t|| victim->GetStatus() == STATUS_PLANE) )\n\t\t\t{\n\t\t\t\tif ( !(victim->IsVehicle() && victim->bRenderScorched) )\n\t\t\t\t{\n\t\t\t\t\tfloat distToVictim  = (shooter->GetPosition()-victim->GetPosition()).Magnitude2D();\n\t\t\t\t\tfloat distToVictimZ = Abs(shooter->GetPosition().z - (distToVictim*normZ + victim->GetPosition().z));\n\n\t\t\t\t\tif ( 3.0f*distToVictimZ < distToVictim )\n\t\t\t\t\t{\n\t\t\t\t\t\tCVector tmp = CVector(victim->GetPosition().x, victim->GetPosition().y, 0.0f);\n\t\t\t\t\t\tif ( CCollision::DistToLine(source, target,\n\t\t\t\t\t\t\t\t&tmp) < victim->GetBoundRadius()*3.0f )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tfloat vehicleDist = Sqrt(SQR(distToVictim) + SQR(distToVictimZ));\n\t\t\t\t\t\t\tif ( vehicleDist < closestEntityDist )\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tclosestEntityDist = vehicleDist;\n\t\t\t\t\t\t\t\tclosestEntity = i;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif ( closestEntityDist < DOOMAUTOAIMING_MAXDIST )\n\t{\n\t\tCEntity *victim = entities[closestEntity];\n\t\tASSERT(victim!=nil);\n\n\t\tfloat distToTarget = (*target - *source).Magnitude2D();\n\t\tfloat distToSource = (victim->GetPosition() - *source).Magnitude2D();\n\n\t\t(*target).z = (distToTarget / distToSource) * (0.3f + victim->GetPosition().z - (*source).z) + (*source).z;\n\t}\n}\n\n\nvoid\nCWeapon::DoDriveByAutoAiming(CEntity *driver, CVehicle *vehicle, CVector *source, CVector *target)\n{\n\tASSERT(driver!=nil);\n\tASSERT(source!=nil);\n\tASSERT(target!=nil);\n\n#ifndef FIX_BUGS\n\tCEntity entity; // unused\n#endif\n\n\tCPed *shooterPed = (CPed*)driver;\n\n\tint16 lastEntity;\n\tCEntity *peds[16];\n\tCWorld::FindObjectsInRange(*source, (*target-*source).Magnitude(), true, &lastEntity, 15, peds, false, false, true, false, false);\n\n\tfloat closestEntityDist = 10000.0f;\n\tint16 closestEntity;\n\n\tfor ( int32 i = 0; i < lastEntity; i++ )\n\t{\n\t\tCPed *victim = (CPed*)peds[i];\n\t\tASSERT(victim!=nil);\n\n\t\tif (driver != victim && !victim->DyingOrDead() && victim->m_attachedTo != vehicle)\n\t\t{\n\t\t\tfloat lineDist = CCollision::DistToLine(source, target, &victim->GetPosition());\n\n\t\t\tuint32 model = vehicle->GetModelIndex();\n\t\t\tfloat pedDist;\n\t\t\tif (model == MI_HUNTER || model == MI_SEASPAR || model == MI_SPARROW)\n\t\t\t{\n\t\t\t\tfloat distToVictim = (victim->GetPosition() - vehicle->GetPosition()).Magnitude();\n\t\t\t\tpedDist = lineDist / Max(5.f, distToVictim);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tfloat distToVictim = (victim->GetPosition() - driver->GetPosition()).Magnitude();\n\t\t\t\tpedDist = 0.15f * distToVictim + lineDist;\n\t\t\t}\n\n\t\t\tif ( DotProduct((*target-*source), victim->GetPosition()-*source) > 0.0f && pedDist < closestEntityDist)\n\t\t\t{\n\t\t\t\tclosestEntity = i;\n\t\t\t\tclosestEntityDist = pedDist;\n\t\t\t}\n\t\t}\n\t}\n\tuint32 model = vehicle->GetModelIndex();\n\tfloat maxAimDistance = CAR_DRIVEBYAUTOAIMING_MAXDIST;\n\tif (model == MI_HUNTER)\n\t{\n\t\tmaxAimDistance = Tan(DEGTORAD(fHunterAimingAngle));\n\t}\n\telse if (model == MI_SEASPAR || model == MI_SPARROW)\n\t{\n\t\tmaxAimDistance = Tan(DEGTORAD(fSeaSparrowAimingAngle));\n\t}\n\n\tif ( closestEntityDist < maxAimDistance )\n\t{\n\t\tCEntity *victim = peds[closestEntity];\n\t\tASSERT(victim!=nil);\n\n\t\tfloat distToTarget = (*source - *target).Magnitude();\n\t\tfloat distToSource = (*source - victim->GetPosition()).Magnitude();\n\t\t*target = (distToTarget / distToSource) * (victim->GetPosition() - *source) + *source;\n\t}\n}\n\nvoid\nCWeapon::Reload(void)\n{\n\tif (m_nAmmoTotal == 0)\n\t\treturn;\n\n\tCWeaponInfo *info = GetInfo();\n\n\tif (m_nAmmoTotal >= info->m_nAmountofAmmunition)\n\t\tm_nAmmoInClip = info->m_nAmountofAmmunition;\n\telse\n\t\tm_nAmmoInClip = m_nAmmoTotal;\n}\n\nvoid\nCWeapon::Update(int32 audioEntity, CPed *pedToAdjustSound)\n{\n\tCWeaponInfo *info = GetInfo();\n\n\tswitch ( m_eWeaponState )\n\t{\n\t\tcase WEAPONSTATE_MELEE_MADECONTACT:\n\t\t{\n\t\t\tm_eWeaponState = WEAPONSTATE_READY;\n\t\t\tbreak;\n\t\t}\n\n\t\tcase WEAPONSTATE_FIRING:\n\t\t{\n\t\t\tif ( IsShotgun(m_eWeaponType) && AEHANDLE_IS_OK(audioEntity) )\n\t\t\t{\n\t\t\t\tuint32 timePassed = m_nTimer - CWeaponInfo::ms_aReloadSampleTime[m_eWeaponType];\n\t\t\t\tif ( CTimer::GetPreviousTimeInMilliseconds() < timePassed && CTimer::GetTimeInMilliseconds() >= timePassed )\n\t\t\t\t\tDMAudio.PlayOneShot(audioEntity, SOUND_WEAPON_RELOAD, 0.0f);\n\t\t\t}\n\n\t\t\tif ( CTimer::GetTimeInMilliseconds() > m_nTimer )\n\t\t\t{\n\t\t\t\tif ( GetInfo()->m_eWeaponFire != WEAPON_FIRE_MELEE && m_nAmmoTotal == 0 ) {\n\t\t\t\t\tm_eWeaponState = WEAPONSTATE_OUT_OF_AMMO;\n\t\t\t\t\tCPickups::RemoveAllPickupsOfACertainWeaponGroupWithNoAmmo(m_eWeaponType);\n\t\t\t\t} else\n\t\t\t\t\tm_eWeaponState = WEAPONSTATE_READY;\n\t\t\t}\n\n\t\t\tbreak;\n\t\t}\n\n\t\tcase WEAPONSTATE_RELOADING:\n\t\t{\n\t\t\tif  ( AEHANDLE_IS_OK(audioEntity) && m_eWeaponType < WEAPONTYPE_TOTALWEAPONS)\n\t\t\t{\n\t\t\t\tCAnimBlendAssociation *reloadAssoc = nil;\n\t\t\t\tif (pedToAdjustSound) {\n\t\t\t\t\tif (CPed::GetReloadAnim(info) && (!CWorld::Players[CWorld::PlayerInFocus].m_bFastReload || !pedToAdjustSound->IsPlayer())) {\n\t\t\t\t\t\treloadAssoc = RpAnimBlendClumpGetAssociation(pedToAdjustSound->GetClump(), CPed::GetReloadAnim(info));\n\t\t\t\t\t\tif (!reloadAssoc) {\n\t\t\t\t\t\t\treloadAssoc = RpAnimBlendClumpGetAssociation(pedToAdjustSound->GetClump(), CPed::GetCrouchReloadAnim(info));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (reloadAssoc && reloadAssoc->IsRunning() && reloadAssoc->blendAmount > 0.2f) {\n\t\t\t\t\tfloat soundStart = 0.75f;\n\t\t\t\t\tswitch (info->m_AnimToPlay) {\n\t\t\t\t\t\tcase ASSOCGRP_PYTHON:\n\t\t\t\t\t\t\tsoundStart = fReloadAnimSampleFraction[0];\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase ASSOCGRP_COLT:\n\t\t\t\t\t\tcase ASSOCGRP_TEC:\n\t\t\t\t\t\t\tsoundStart = fReloadAnimSampleFraction[1];\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase ASSOCGRP_UZI:\n\t\t\t\t\t\t\tsoundStart = fReloadAnimSampleFraction[2];\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase ASSOCGRP_RIFLE:\n\t\t\t\t\t\t\tsoundStart = fReloadAnimSampleFraction[3];\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase ASSOCGRP_M60:\n\t\t\t\t\t\t\tsoundStart = fReloadAnimSampleFraction[4];\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tif (reloadAssoc->GetProgress() >= soundStart && (reloadAssoc->currentTime - reloadAssoc->timeStep) / reloadAssoc->hierarchy->totalLength < soundStart)\n\t\t\t\t\t\tDMAudio.PlayOneShot(audioEntity, SOUND_WEAPON_RELOAD, m_eWeaponType);\n\t\t\t\t\tif (CTimer::GetTimeInMilliseconds() > m_nTimer && reloadAssoc->GetProgress() < 0.9f) {\n\t\t\t\t\t\tm_nTimer = CTimer::GetTimeInMilliseconds();\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tuint32 timePassed = m_nTimer - CWeaponInfo::ms_aReloadSampleTime[m_eWeaponType];\n\t\t\t\t\tif (CTimer::GetPreviousTimeInMilliseconds() < timePassed && CTimer::GetTimeInMilliseconds() >= timePassed)\n\t\t\t\t\t\tDMAudio.PlayOneShot(audioEntity, SOUND_WEAPON_RELOAD, m_eWeaponType);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( CTimer::GetTimeInMilliseconds() > m_nTimer )\n\t\t\t{\n\t\t\t\tReload();\n\t\t\t\tm_eWeaponState = WEAPONSTATE_READY;\n\t\t\t}\n\n\t\t\tbreak;\n\t\t}\n\t\tdefault: break;\n\t}\n}\n\nvoid\nFireOneInstantHitRound(CVector *source, CVector *target, int32 damage)\n{\n\tASSERT(source!=nil);\n\tASSERT(target!=nil);\n\n\tCParticle::AddParticle(PARTICLE_GUNFLASH, *source, CVector(0.0f, 0.0f, 0.0f));\n\n\tCPointLights::AddLight(CPointLights::LIGHT_POINT,\n\t\t*source, CVector(0.0f, 0.0f, 0.0f), 5.0f,\n\t\t1.0f, 0.8f, 0.0f, CPointLights::FOG_NONE, false);\n\n\tCColPoint point;\n\tCEntity *victim;\n\tCWorld::ProcessLineOfSight(*source, *target, point, victim, true, true, true, true, true, true, false);\n\n\tCParticle::AddParticle(PARTICLE_HELI_ATTACK, *source, ((*target) - (*source)) * 0.15f);\n\n\tif ( victim )\n\t{\n\t\tif ( victim->IsPed() )\n\t\t{\n\t\t\tCPed *victimPed = (CPed *)victim;\n\t\t\tif ( !victimPed->DyingOrDead() )\n\t\t\t{\n\t\t\t\tCVector pos = victimPed->GetPosition();\n\n\t\t\t\tCVector2D posOffset((*source).x-pos.x, (*source).y-pos.y);\n\t\t\t\tint32 localDir = victimPed->GetLocalDirection(posOffset);\n\n\t\t\t\tvictimPed->ClearAttackByRemovingAnim();\n\n\t\t\t\tCAnimBlendAssociation *asoc = CAnimManager::AddAnimation(victimPed->GetClump(), ASSOCGRP_STD, AnimationId(ANIM_STD_HITBYGUN_FRONT + localDir));\n\t\t\t\tASSERT(asoc!=nil);\n\t\t\t\tasoc->blendAmount = 0.0f;\n\t\t\t\tasoc->blendDelta  = 8.0f;\n\n\t\t\t\tvictimPed->InflictDamage(nil, WEAPONTYPE_UZI, damage, (ePedPieceTypes)point.pieceB, localDir);\n\n\t\t\t\tpos.z += 0.8f;\n\n\t\t\t\tif ( victimPed->GetIsOnScreen() )\n\t\t\t\t{\n\t\t\t\t\tif ( CGame::nastyGame )\n\t\t\t\t\t{\n\t\t\t\t\t\tfor ( int32 i = 0; i < 4; i++ )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tCVector dir;\n\t\t\t\t\t\t\tdir.x = CGeneral::GetRandomNumberInRange(-0.1f, 0.1f);\n\t\t\t\t\t\t\tdir.y = CGeneral::GetRandomNumberInRange(-0.1f, 0.1f);\n\t\t\t\t\t\t\tdir.z = CGeneral::GetRandomNumberInRange(-0.1f, 0.1f);\n\n\t\t\t\t\t\t\tCParticle::AddParticle(PARTICLE_BLOOD, pos, dir);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse if ( victim->IsVehicle() )\n\t\t\t((CVehicle *)victim)->InflictDamage(nil, WEAPONTYPE_UZI, damage);\n\t\t//BUG ? no CGlass::WasGlassHitByBullet\n\n\t\tswitch ( victim->GetType() )\n\t\t{\n\t\t\tcase ENTITY_TYPE_BUILDING:\n\t\t\t{\n\t\t\t\tPlayOneShotScriptObject(SCRIPT_SOUND_BULLET_HIT_GROUND_1, point.point);\n\t\t\t\tCParticle::AddParticle(PARTICLE_SMOKE, point.point, CVector(0.0f, 0.0f, 0.01f));\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase ENTITY_TYPE_VEHICLE:\n\t\t\t{\n\t\t\t\tCStats::BulletsThatHit++;\n\t\t\t\tDMAudio.PlayOneShot(((CPhysical*)victim)->m_audioEntityId, SOUND_WEAPON_HIT_VEHICLE, 1.0f);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase ENTITY_TYPE_PED:\n\t\t\t{\n\t\t\t\tCStats::BulletsThatHit++;\n\t\t\t\tDMAudio.PlayOneShot(((CPhysical*)victim)->m_audioEntityId, SOUND_WEAPON_HIT_PED, 1.0f);\n\t\t\t\t((CPed*)victim)->Say(SOUND_PED_BULLET_HIT);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase ENTITY_TYPE_OBJECT:\n\t\t\t{\n\t\t\t\tCStats::BulletsThatHit++;\n\t\t\t\tPlayOneShotScriptObject(SCRIPT_SOUND_BULLET_HIT_GROUND_2, point.point);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase ENTITY_TYPE_DUMMY:\n\t\t\t{\n\t\t\t\tPlayOneShotScriptObject(SCRIPT_SOUND_BULLET_HIT_GROUND_3, point.point);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tdefault: break;\n\t\t}\n\t}\n\telse\n\t{\n\t\tfloat waterLevel;\n\t\tif ( CWaterLevel::GetWaterLevel((*target).x, (*target).y, (*target).z + 10.0f, &waterLevel, false) )\n\t\t{\n\t\t\tCParticle::AddParticle(PARTICLE_BOAT_SPLASH, CVector((*target).x, (*target).y, waterLevel), CVector(0.0f, 0.0f, 0.01f));\n\t\t\tPlayOneShotScriptObject(SCRIPT_SOUND_BULLET_HIT_WATER, point.point); // no sound(empty)\n\t\t}\n\t}\n}\n\nbool\nCWeapon::IsTypeMelee(void)\n{\n\treturn CWeaponInfo::GetWeaponInfo(m_eWeaponType)->m_eWeaponFire == WEAPON_FIRE_MELEE;\n}\n\nbool\nCWeapon::IsType2Handed(void)\n{\n\treturn m_eWeaponType == WEAPONTYPE_FLAMETHROWER || m_eWeaponType == WEAPONTYPE_HELICANNON || m_eWeaponType == WEAPONTYPE_M60 ||\n\t\tm_eWeaponType == WEAPONTYPE_M4 || IsShotgun(m_eWeaponType) ||\n\t\tm_eWeaponType == WEAPONTYPE_RUGER || m_eWeaponType == WEAPONTYPE_SNIPERRIFLE || m_eWeaponType == WEAPONTYPE_LASERSCOPE;\n}\n\nvoid\nCWeapon::MakePedsJumpAtShot(CPhysical *shooter, CVector *source, CVector *target)\n{\n\tASSERT(shooter!=nil);\n\tASSERT(source!=nil);\n\tASSERT(target!=nil);\n\n\tfloat minx = Min(source->x, target->x) - 2.0f;\n\tfloat maxx = Max(source->x, target->x) + 2.0f;\n\tfloat miny = Min(source->y, target->y) - 2.0f;\n\tfloat maxy = Max(source->y, target->y) + 2.0f;\n\tfloat minz = Min(source->z, target->z) - 2.0f;\n\tfloat maxz = Max(source->z, target->z) + 2.0f;\n\n\tfor ( int32 i = CPools::GetPedPool()->GetSize() - 1; i >= 0; i--)\n\t{\n\t\tCPed *ped = CPools::GetPedPool()->GetSlot(i);\n\n\t\tif ( ped )\n\t\t{\n\t\t\tif (   ped->GetPosition().x > minx && ped->GetPosition().x < maxx\n\t\t\t\t&& ped->GetPosition().y > miny && ped->GetPosition().y < maxy\n\t\t\t\t&& ped->GetPosition().z > minz && ped->GetPosition().z < maxz )\n\t\t\t{\n\t\t\t\tif ( ped != FindPlayerPed() && !((uint8)(ped->m_randomSeed ^ CGeneral::GetRandomNumber()) & 31) )\n\t\t\t\t\tped->SetEvasiveDive(shooter, 1);\n\t\t\t}\n\t\t}\n\t}\n}\n\nbool\nCWeapon::HitsGround(CEntity *holder, CVector *fireSource, CEntity *aimingTo)\n{\n\tASSERT(holder!=nil);\n\tASSERT(aimingTo!=nil);\n\n\tif (!holder->IsPed() || !((CPed*)holder)->m_pSeekTarget)\n\t\treturn false;\n\n\tCWeaponInfo *info = GetInfo();\n\n\tCVector adjustedOffset = info->m_vecFireOffset;\n\tadjustedOffset.z += 0.6f;\n\n\tCVector source, target;\n\tCEntity *foundEnt = nil;\n\tCColPoint foundCol;\n\n\tif (fireSource)\n\t\tsource = *fireSource;\n\telse\n\t\tsource = holder->GetMatrix() * adjustedOffset;\n\n\tCEntity *aimEntity = aimingTo ? aimingTo : ((CPed*)holder)->m_pSeekTarget;\n\tASSERT(aimEntity!=nil);\n\n\ttarget = aimEntity->GetPosition();\n\ttarget.z += 0.6f;\n\n\tCWorld::ProcessLineOfSight(source, target, foundCol, foundEnt, true, false, false, false, false, false, false);\n\tif (foundEnt && foundEnt->IsBuilding()) {\n\t\t// That was supposed to be Magnitude, according to leftover code in assembly\n\t\tfloat diff = (foundCol.point.z - source.z);\n\t\tif (diff < 0.0f && diff > -3.0f)\n\t\t\treturn true;\n\t}\n\n\treturn false;\n}\n\nvoid\nCWeapon::BlowUpExplosiveThings(CEntity *thing)\n{\n\tif ( thing )\n\t{\n\t\tCObject *object = (CObject*)thing;\n\t\tint32 mi = object->GetModelIndex();\n\t\tif ( IsExplosiveThingModel(mi) && !object->bHasBeenDamaged && object->IsObject() )\n\t\t{\n\t\t\tobject->bHasBeenDamaged = true;\n\n\t\t\tCExplosion::AddExplosion(object, FindPlayerPed(), EXPLOSION_BARREL, object->GetPosition()+CVector(0.0f,0.0f,0.5f), 100);\n\n\t\t\tif ( MI_EXPLODINGBARREL == mi )\n\t\t\t\tobject->m_vecMoveSpeed.z += 0.55f;\n\t\t\telse\n\t\t\t\tobject->m_vecMoveSpeed.z += 0.45f;\n\n\t\t\tobject->m_vecMoveSpeed.x += float((CGeneral::GetRandomNumber()&255) - 128) * 0.0002f;\n\t\t\tobject->m_vecMoveSpeed.y += float((CGeneral::GetRandomNumber()&255) - 128) * 0.0002f;\n\n\t\t\tif ( object->GetIsStatic())\n\t\t\t{\n\t\t\t\tobject->SetIsStatic(false);\n\t\t\t\tobject->AddToMovingList();\n\t\t\t}\n\t\t}\n\t}\n}\n\nbool\nCWeapon::HasWeaponAmmoToBeUsed(void)\n{\n\t// FIX: This is better (not bug tho)\n//#if 0\n\tif (m_eWeaponType <= WEAPONTYPE_CHAINSAW)\n//#else\n//\tif (CWeaponInfo::GetWeaponInfo(m_eWeaponType)->m_eWeaponFire == WEAPON_FIRE_MELEE)\n//#endif\n\t\treturn true;\n\telse\n\t\treturn m_nAmmoTotal != 0;\n}\n\nbool\nCPed::IsPedDoingDriveByShooting(void)\n{\n#ifdef FIX_BUGS\n\tif (FindPlayerPed() == this && CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->m_nWeaponSlot == 5) {\n#else\n\tif (FindPlayerPed() == this && GetWeapon()->m_eWeaponType == WEAPONTYPE_UZI) {\n#endif\n\t\tif (TheCamera.Cams[TheCamera.ActiveCam].LookingLeft || TheCamera.Cams[TheCamera.ActiveCam].LookingRight)\n\t\t\treturn true;\n\t}\n\treturn false;\n}\n\nbool\nCWeapon::ProcessLineOfSight(CVector const &point1, CVector const &point2, CColPoint &point, CEntity *&entity, eWeaponType type, CEntity *shooter, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSeeThrough, bool ignoreSomeObjects)\n{\n\treturn CWorld::ProcessLineOfSight(point1, point2, point, entity, checkBuildings, checkVehicles, checkPeds, checkObjects, checkDummies, false, ignoreSomeObjects, true);\n}\n\n\nvoid\nCWeapon::CheckForShootingVehicleOccupant(CEntity **victim, CColPoint *point, eWeaponType weapon, CVector const& source, CVector const& target)\n{\n\tif (!(*victim)->IsVehicle())\n\t\treturn;\n\n\tCColSphere headSphere;\n\n\tCVehicle *veh = (CVehicle*)*victim;\n\tCColPoint origPoint(*point);\n\tfloat radius = 1.0f;\n\tbool found = false;\n\tCColLine shootLine(source, target);\n\n\tif (veh->pDriver && veh->pDriver->bCanBeShotInVehicle) {\n\t\tCVector pos(0.f, 0.f, 0.f);\n\t\tveh->pDriver->TransformToNode(pos, PED_HEAD);\n\t\theadSphere.Set(0.2f, pos + CVector(0.f, 0.f, 0.1f), 0, PEDPIECE_HEAD);\n\t\tif (CCollision::ProcessLineSphere(shootLine, headSphere, *point, radius)) {\n\t\t\t*victim = veh->pDriver;\n\t\t\tfound = true;\n\t\t}\n\t}\n\t\n\tfor(int i = 0; i < ARRAY_SIZE(veh->pPassengers); i++) {\n\t\tCPed *passenger = veh->pPassengers[i];\n\t\tif (passenger && passenger->bCanBeShotInVehicle) {\n\t\t\tCVector pos(0.f, 0.f, 0.f);\n\t\t\tpassenger->TransformToNode(pos, PED_HEAD);\n\t\t\theadSphere.Set(0.2f, pos + CVector(0.f, 0.f, 0.1f), 0, PEDPIECE_HEAD);\n\t\t\tif (CCollision::ProcessLineSphere(shootLine, headSphere, *point, radius)) {\n\t\t\t\t*victim = passenger;\n\t\t\t\tfound = true;\n\t\t\t}\n\t\t}\n\t}\n\tif (veh->IsCar()) {\n\t\tCVector distVec = target - source;\n\t\tif (DotProduct(distVec, veh->GetForward()) < 0.0f && DotProduct(distVec, veh->GetUp()) <= 0.0f) {\n\t\t\tCColModel *colModel = veh->GetColModel();\n\t\t\tif (colModel->numTriangles > 0) {\n\t\t\t\tbool passesGlass = false;\n\t\t\t\tCMatrix invVehMat;\n\t\t\t\tInvert(veh->GetMatrix(), invVehMat);\n\t\t\t\tshootLine.p0 = invVehMat * shootLine.p0;\n\t\t\t\tshootLine.p1 = invVehMat * shootLine.p1;\n\t\t\t\tCCollision::CalculateTrianglePlanes(colModel);\n\t\t\t\tfor (int i = 0; i < colModel->numTriangles; i++) {\n\t\t\t\t\tif (colModel->triangles[i].surface == SURFACE_GLASS &&\n\t\t\t\t\t\tCCollision::TestLineTriangle(shootLine, colModel->vertices, colModel->triangles[i], colModel->trianglePlanes[i])) {\n\t\t\t\t\t\tpassesGlass = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tCAutomobile *car = (CAutomobile*)veh;\n\n\t\t\t\t// No need to damage windscreen if there isn't one.\n\t\t\t\tif (passesGlass && car->Damage.ProgressPanelDamage(VEHPANEL_WINDSCREEN)) {\n\t\t\t\t\tif (car->Damage.GetPanelStatus(VEHPANEL_WINDSCREEN) == PANEL_STATUS_SMASHED2)\n\t\t\t\t\t\tcar->Damage.ProgressPanelDamage(VEHPANEL_WINDSCREEN);\n\n\t\t\t\t\tcar->SetPanelDamage(CAR_WINDSCREEN, VEHPANEL_WINDSCREEN, true);\n\t\t\t\t\tDMAudio.PlayOneShot(veh->m_audioEntityId, SOUND_CAR_WINDSHIELD_CRACK, 0.f);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (!found) {\n\t\t*victim = veh;\n\t\t*point = origPoint;\n\t}\n}\n\n#ifdef COMPATIBLE_SAVES\n#define CopyFromBuf(buf, data) memcpy(&data, buf, sizeof(data)); SkipSaveBuf(buf, sizeof(data));\n#define CopyToBuf(buf, data) memcpy(buf, &data, sizeof(data)); SkipSaveBuf(buf, sizeof(data));\nvoid\nCWeapon::Save(uint8*& buf)\n{\n\tCopyToBuf(buf, m_eWeaponType);\n\tCopyToBuf(buf, m_eWeaponState);\n\tCopyToBuf(buf, m_nAmmoInClip);\n\tCopyToBuf(buf, m_nAmmoTotal);\n\tCopyToBuf(buf, m_nTimer);\n\tCopyToBuf(buf, m_bAddRotOffset);\n\tSkipSaveBuf(buf, 3);\n}\n\nvoid\nCWeapon::Load(uint8*& buf)\n{\n\tCopyFromBuf(buf, m_eWeaponType);\n\tCopyFromBuf(buf, m_eWeaponState);\n\tCopyFromBuf(buf, m_nAmmoInClip);\n\tCopyFromBuf(buf, m_nAmmoTotal);\n\tCopyFromBuf(buf, m_nTimer);\n\tCopyFromBuf(buf, m_bAddRotOffset);\n\tSkipSaveBuf(buf, 3);\n}\n\n#undef CopyFromBuf\n#undef CopyToBuf\n#endif\n"
  },
  {
    "path": "src/weapons/Weapon.h",
    "content": "#pragma once\n\n#include \"WeaponType.h\"\n\n#define CAR_DRIVEBYAUTOAIMING_MAXDIST (2.5f)\n#define DOOMAUTOAIMING_MAXDIST    (9000.0f)\n\nclass CEntity;\nclass CPhysical;\nclass CVehicle;\nclass CPed;\nstruct CColPoint;\nclass CWeaponInfo;\n\nclass CWeapon\n{\npublic:\n\teWeaponType m_eWeaponType;\n\teWeaponState m_eWeaponState;\n\tint32 m_nAmmoInClip;\n\tint32 m_nAmmoTotal;\n\tuint32 m_nTimer;\n\tbool m_bAddRotOffset;\n\t\n\tstatic bool bPhotographHasBeenTaken;\n\t\n\tCWeapon() {\n\t\tm_bAddRotOffset = false;\n\t}\n\tCWeapon(eWeaponType type, int32 ammo);\n\t\n\tCWeaponInfo *GetInfo();\n\n\tstatic void InitialiseWeapons(void);\n\tstatic void ShutdownWeapons  (void);\n\tstatic void UpdateWeapons    (void);\n\t\n\tvoid Initialise(eWeaponType type, int32 ammo);\n\tvoid Shutdown();\n\t\n\tbool Fire          (CEntity *shooter, CVector *fireSource);\n\tbool FireFromCar   (CVehicle *shooter, bool left, bool right);\n\tbool FireMelee     (CEntity *shooter, CVector &fireSource);\n\tbool FireInstantHit(CEntity *shooter, CVector *fireSource);\n\t\n\tstatic void AddGunFlashBigGuns(CVector start, CVector end);\n\tvoid AddGunshell   (CEntity *shooter, CVector const &source, CVector2D const &direction, float size);\n\tvoid DoBulletImpact(CEntity *shooter, CEntity *victim, CVector *source, CVector *target, CColPoint *point, CVector2D ahead);\n\t\n\tbool FireShotgun   (CEntity *shooter, CVector *fireSource);\n\tbool FireProjectile(CEntity *shooter, CVector *fireSource, float power);\n\t\n\tstatic void GenerateFlameThrowerParticles(CVector pos, CVector dir);\n\t\n\tbool FireAreaEffect       (CEntity *shooter, CVector *fireSource);\n\tbool LaserScopeDot        (CVector *pOutPos, float *pOutSize);\n\tbool FireSniper           (CEntity *shooter);\n\tbool TakePhotograph       (CEntity *shooter);\n\tbool FireM16_1stPerson    (CEntity *shooter);\n\tbool FireInstantHitFromCar(CVehicle *shooter, bool left, bool right);\n\t\n\tstatic void DoDoomAiming       (CEntity *shooter, CVector *source,   CVector *target);\n\tstatic void DoTankDoomAiming   (CEntity *shooter, CEntity *driver,   CVector *source, CVector *target);\n\tstatic void DoDriveByAutoAiming(CEntity *driver,  CVehicle *vehicle, CVector *source, CVector *target);\n\t\n\tvoid Reload(void);\n\tvoid Update(int32 audioEntity, CPed *pedToAdjustSound);\n\tbool IsTypeMelee  (void);\n\tbool IsType2Handed(void);\n\t\n\tstatic void MakePedsJumpAtShot(CPhysical *shooter, CVector *source, CVector *target);\n\t\n\tbool HitsGround(CEntity *holder, CVector *fireSource, CEntity *aimingTo);\n\tstatic void BlowUpExplosiveThings(CEntity *thing);\n\tbool HasWeaponAmmoToBeUsed(void);\n\t\n\tstatic bool IsShotgun(int weapon) { return weapon == WEAPONTYPE_SHOTGUN || weapon == WEAPONTYPE_SPAS12_SHOTGUN || weapon == WEAPONTYPE_STUBBY_SHOTGUN; }\n\n\tstatic bool ProcessLineOfSight(CVector const &point1, CVector const &point2, CColPoint &point, CEntity *&entity, eWeaponType type, CEntity *shooter, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSeeThrough, bool ignoreSomeObjects);\n\n\tstatic void CheckForShootingVehicleOccupant(CEntity **victim, CColPoint *point, eWeaponType weapon, CVector const& source, CVector const& target);\n\n#ifdef COMPATIBLE_SAVES\n\tvoid Save(uint8*& buf);\n\tvoid Load(uint8*& buf);\n#endif\n};\nVALIDATE_SIZE(CWeapon, 0x18);\n\nvoid FireOneInstantHitRound(CVector *source, CVector *target, int32 damage);"
  },
  {
    "path": "src/weapons/WeaponEffects.cpp",
    "content": "#include \"common.h\"\n\n#include \"main.h\"\n#include \"WeaponEffects.h\"\n#include \"TxdStore.h\"\n#include \"Sprite.h\"\n#include \"PlayerPed.h\"\n#include \"World.h\"\n#include \"WeaponType.h\"\n\nRwTexture *gpCrossHairTex;\n\nCWeaponEffects gCrossHair;\n\nCWeaponEffects::CWeaponEffects()\n{\n\t\n}\n\nCWeaponEffects::~CWeaponEffects()\n{\n\t\n}\n\nvoid\nCWeaponEffects::Init(void)\n{\n\tgCrossHair.m_bActive = false;\n\tgCrossHair.m_vecPos = CVector(0.0f, 0.0f, 0.0f);\n\tgCrossHair.m_nRed = 255;\n\tgCrossHair.m_nGreen = 0;\n\tgCrossHair.m_nBlue = 0;\n\tgCrossHair.m_nAlpha = 127;\n\tgCrossHair.m_fSize = 1.0f;\n\tgCrossHair.m_fRotation = 0.0f;\n\t\n\t\n\tCTxdStore::PushCurrentTxd();\n\tint32 slot = CTxdStore::FindTxdSlot(\"particle\");\n\tCTxdStore::SetCurrentTxd(slot);\n\t\n\tgpCrossHairTex    = RwTextureRead(\"target256\", \"target256m\");\n\t\n\tCTxdStore::PopCurrentTxd();\n}\n\nvoid\nCWeaponEffects::Shutdown(void)\n{\n\tRwTextureDestroy(gpCrossHairTex);\n\tgpCrossHairTex = nil;\n}\n\nvoid\nCWeaponEffects::MarkTarget(CVector pos, uint8 red, uint8 green, uint8 blue, uint8 alpha, float size)\n{\n\tgCrossHair.m_bActive = true;\n\tgCrossHair.m_vecPos = pos;\n\tgCrossHair.m_fSize = size;\n}\n\nvoid\nCWeaponEffects::ClearCrossHair(void)\n{\n\tgCrossHair.m_bActive = false;\n}\n\nvoid\nCWeaponEffects::Render(void)\n{\n\tstatic float aCrossHairSize[WEAPONTYPE_TOTALWEAPONS] =\n\t{\n\t\t1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,\n\t\t0.4f, 0.4f,\n\t\t0.5f,\n\t\t0.3f,\n\t\t0.9f, 0.9f, 0.9f,\n\t\t0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f,\n\t\t0.1f, 0.1f,\n\t\t1.0f,\n\t\t0.6f,\n\t\t0.7f,\n\t\t0.0f, 0.0f\n\t};\n\n\n\n\tif ( gCrossHair.m_bActive )\n\t{\n\t\tfloat size = aCrossHairSize[FindPlayerPed()->GetWeapon()->m_eWeaponType];\n\t\t\n\t\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE,      (void *)FALSE);\n\t\tRwRenderStateSet(rwRENDERSTATEZTESTENABLE,       (void *)FALSE);\n\t\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)TRUE);\n\t\tRwRenderStateSet(rwRENDERSTATESRCBLEND,          (void *)rwBLENDSRCALPHA);\n#ifdef FIX_BUGS\n\t\tRwRenderStateSet(rwRENDERSTATEDESTBLEND,         (void *)rwBLENDINVSRCALPHA);\n#else\n\t\tRwRenderStateSet(rwRENDERSTATEDESTBLEND,         (void *)rwBLENDINVDESTALPHA);\n#endif\n\t\tRwRenderStateSet(rwRENDERSTATETEXTURERASTER,     (void *)RwTextureGetRaster(gpCrossHairTex));\n\n\t\tRwV3d pos;\n\t\tfloat w, h;\n\t\tif ( CSprite::CalcScreenCoors(gCrossHair.m_vecPos, &pos, &w, &h, true) )\n\t\t{\n\t\t\tPUSH_RENDERGROUP(\"CWeaponEffects::Render\");\n\n\t\t\tfloat recipz = 1.0f / pos.z;\n\t\t\tCSprite::RenderOneXLUSprite_Rotate_Aspect(pos.x, pos.y, pos.z,\n\t\t\t\tw, h,\n\t\t\t\t255, 88, 100, 158,\n\t\t\t\trecipz, gCrossHair.m_fRotation, gCrossHair.m_nAlpha);\n\t\t\t\t\n\t\t\tfloat recipz2 = 1.0f / pos.z;\n\t\t\t\n\t\t\tCSprite::RenderOneXLUSprite_Rotate_Aspect(pos.x, pos.y, pos.z,\n\t\t\t\tsize*w, size*h,\n\t\t\t\t107, 134, 247, 158,\n\t\t\t\trecipz2, TWOPI - gCrossHair.m_fRotation, gCrossHair.m_nAlpha);\n\t\t\t\t\t\t\n\t\t\tgCrossHair.m_fRotation += 0.02f;\n\t\t\tif ( gCrossHair.m_fRotation > TWOPI )\n\t\t\t\tgCrossHair.m_fRotation = 0.0;\n\n\t\t\tPOP_RENDERGROUP();\n\t\t}\n\t\t\t\n\t\tRwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)FALSE);\n\t\tRwRenderStateSet(rwRENDERSTATEZWRITEENABLE,      (void *)TRUE);\n\t\tRwRenderStateSet(rwRENDERSTATEZTESTENABLE,       (void *)TRUE);\n\t}\n}"
  },
  {
    "path": "src/weapons/WeaponEffects.h",
    "content": "#pragma once\n\nclass CWeaponEffects\n{\npublic:\n\tbool m_bActive;\n\tCVector m_vecPos;\n\tuint8 m_nRed;\n\tuint8 m_nGreen;\n\tuint8 m_nBlue;\n\tuint8 m_nAlpha;\n\tfloat m_fSize;\n\tfloat m_fRotation;\n\npublic:\n\tCWeaponEffects();\n\t~CWeaponEffects();\n\n\tstatic void Init(void);\n\tstatic void Shutdown(void);\n\tstatic void MarkTarget(CVector pos, uint8 red, uint8 green, uint8 blue, uint8 alpha, float size);\n\tstatic void ClearCrossHair(void);\n\tstatic void Render(void);\n};\n\nVALIDATE_SIZE(CWeaponEffects, 0x1C);"
  },
  {
    "path": "src/weapons/WeaponInfo.cpp",
    "content": "#include \"common.h\"\n\n#include \"main.h\"\n#include \"FileMgr.h\"\n#include \"WeaponInfo.h\"\n#include \"AnimManager.h\"\n#include \"AnimBlendAssociation.h\"\n#include \"Weapon.h\"\n#include \"ModelInfo.h\"\n#include \"ModelIndices.h\"\n\nuint16 CWeaponInfo::ms_aReloadSampleTime[WEAPONTYPE_TOTALWEAPONS] =\n{\n\t0,\t\t\t// UNARMED\n\t0,\n\t0,\n\t0,\n\t0,\n\t0,\n\t0,\n\t0,\n\t0,\n\t0,\n\t0,\n\t0,\n\t0,\t\t\t// GRENADE\n\t0,\t\t\t// DETONATEGRENADE\n\t0,\t\t\t// TEARGAS\n\t0,\t\t\t// MOLOTOV\n\t0,\t\t\t// ROCKET\n\t250,\t\t// COLT45\n\t250,\t\t// PYTHON\n\t650,\t\t// SHOTGUN\n\t650,\t\t// SPAS12 SHOTGUN\n\t650,\t\t// STUBBY SHOTGUN\n\t400,\t\t// TEC9\n\t400,\t\t// UZIhec\n\t400,\t\t// SILENCED_INGRAM\n\t400,\t\t// MP5\n\t300,\t\t// M16\n\t300,\t\t// AK47\n\t423,\t\t// SNIPERRIFLE\n\t423,\t\t// LASERSCOPE\n\t400,\t\t// ROCKETLAUNCHER\n\t0,\t\t\t// FLAMETHROWER\n\t0,\t\t\t// M60\n\t0,\t\t\t// MINIGUN\n\t0,\t\t\t// DETONATOR\n\t0,\t\t\t// HELICANNON\n\t0\t\t\t// CAMERA\n};\n\n// Yeah...\nint32 CWeaponInfo::ms_aMaxAmmoForWeapon[WEAPONTYPE_TOTALWEAPONS] =\n{\n\t-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n\t-1, -1, -1, -1, -1, -1, -1, -1, -1\n};\n\nCWeaponInfo aWeaponInfo[WEAPONTYPE_TOTALWEAPONS];\nchar CWeaponInfo::ms_aWeaponNames[WEAPONTYPE_TOTALWEAPONS][32] =\n{\n\t\"Unarmed\",\n\t\"BrassKnuckle\",\n\t\"ScrewDriver\",\n\t\"GolfClub\",\n\t\"NightStick\",\n\t\"Knife\",\n\t\"BaseballBat\",\n\t\"Hammer\",\n\t\"Cleaver\",\n\t\"Machete\",\n\t\"Katana\",\n\t\"Chainsaw\",\n\t\"Grenade\",\n\t\"DetonateGrenade\",\n\t\"TearGas\",\n\t\"Molotov\",\n\t\"Rocket\",\n\t\"Colt45\",\n\t\"Python\",\n\t\"Shotgun\",\n\t\"Spas12Shotgun\",\n\t\"StubbyShotgun\",\n\t\"Tec9\",\n\t\"Uzi\",\n\t\"SilencedIngram\",\n\t\"Mp5\",\n\t\"m4\",\n\t\"Ruger\",\n\t\"SniperRifle\",\n\t\"LaserScope\",\n\t\"RocketLauncher\",\n\t\"FlameThrower\",\n\t\"M60\",\n\t\"Minigun\",\n\t\"Detonator\",\n\t\"HeliCannon\",\n\t\"Camera\",\n};\n\nCWeaponInfo*\nCWeaponInfo::GetWeaponInfo(eWeaponType weaponType)\n{\n\treturn &aWeaponInfo[weaponType];\n}\n\nvoid\nCWeaponInfo::Initialise(void)\n{\n\tdebug(\"Initialising CWeaponInfo...\\n\");\n\tfor (int i = 0; i < WEAPONTYPE_TOTALWEAPONS; i++) {\n\t\taWeaponInfo[i].m_eWeaponFire = WEAPON_FIRE_INSTANT_HIT;\n\t\taWeaponInfo[i].m_fRange = 0.0f;\n\t\taWeaponInfo[i].m_nFiringRate = 0;\n\t\taWeaponInfo[i].m_nReload = 0;\n\t\taWeaponInfo[i].m_nAmountofAmmunition = 0;\n\t\taWeaponInfo[i].m_nDamage = 0;\n\t\taWeaponInfo[i].m_fSpeed = 0.0f;\n\t\taWeaponInfo[i].m_fRadius = 0.0f;\n\t\taWeaponInfo[i].m_fLifespan = 0.0f;\n\t\taWeaponInfo[i].m_fSpread = 0.0f;\n\t\taWeaponInfo[i].m_vecFireOffset = CVector(0.0f, 0.0f, 0.0f);\n\t\taWeaponInfo[i].m_AnimToPlay = ASSOCGRP_UNARMED;\n\t\taWeaponInfo[i].m_fAnimLoopStart = 0.0f;\n\t\taWeaponInfo[i].m_fAnimLoopEnd = 0.0f;\n\t\taWeaponInfo[i].m_fAnimFrameFire = 0.0f;\n\t\taWeaponInfo[i].m_fAnim2LoopStart = 0.0f;\n\t\taWeaponInfo[i].m_fAnim2LoopEnd = 0.0f;\n\t\taWeaponInfo[i].m_fAnim2FrameFire = 0.0f;\n\t\taWeaponInfo[i].m_fAnimBreakout = 0.0f;\n\t\taWeaponInfo[i].m_Flags = WEAPONFLAG_USE_GRAVITY | WEAPONFLAG_SLOWS_DOWN | WEAPONFLAG_RAND_SPEED | WEAPONFLAG_EXPANDS | WEAPONFLAG_EXPLODES;\n\t\taWeaponInfo[i].m_nWeaponSlot = WEAPONSLOT_UNARMED;\n\t}\n\tdebug(\"Loading weapon data...\\n\");\n\tLoadWeaponData();\n\tdebug(\"CWeaponInfo ready\\n\");\n}\n\nvoid\nCWeaponInfo::LoadWeaponData(void)\n{\n\tfloat spread, speed, lifeSpan, radius;\n\tfloat range, fireOffsetX, fireOffsetY, fireOffsetZ;\n\tfloat anim2LoopStart, anim2LoopEnd, delayBetweenAnim2AndFire, animBreakout;\n\tfloat delayBetweenAnimAndFire, animLoopStart, animLoopEnd;\n\tint flags, ammoAmount, damage, reload, weaponType;\n\tint firingRate, modelId, modelId2, weaponSlot;\n\tchar line[256], weaponName[32], fireType[32];\n\tchar animToPlay[32];\n\n\tsize_t bp, buflen;\n\tint lp, linelen;\n\t\t\n\tCFileMgr::SetDir(\"DATA\");\n\tbuflen = CFileMgr::LoadFile(\"WEAPON.DAT\", work_buff, sizeof(work_buff), \"r\");\n\n\tfor (bp = 0; bp < buflen; ) {\n\t\t// read file line by line\n\t\tfor (linelen = 0; work_buff[bp] != '\\n' && bp < buflen; bp++) {\n\t\t\tline[linelen++] = work_buff[bp];\n\t\t}\n\t\tbp++;\n\t\tline[linelen] = '\\0';\n\n\t\t// skip white space\n\t\tfor (lp = 0; line[lp] <= ' ' && line[lp] != '\\0'; lp++);\n\n\t\tif (line[lp] == '\\0' || line[lp] == '#')\n\t\t\tcontinue;\n\n\t\tspread = 0.0f;\n\t\tflags = 0;\n\t\tspeed = 0.0f;\n\t\tammoAmount = 0;\n\t\tlifeSpan = 0.0f;\n\t\tradius = 0.0f;\n\t\trange = 0.0f;\n\t\tdamage = 0;\n\t\treload = 0;\n\t\tfiringRate = 0;\n\t\tfireOffsetX = 0.0f;\n\t\tweaponName[0] = '\\0';\n\t\tfireType[0] = '\\0';\n\t\tfireOffsetY = 0.0f;\n\t\tfireOffsetZ = 0.0f;\n\t\tsscanf(\n\t\t\t&line[lp],\n\t\t\t\"%s %s %f %d %d %d %d %f %f %f %f %f %f %f %s %f %f %f %f %f %f %f %d %d %x %d\",\n\t\t\tweaponName,\n\t\t\tfireType,\n\t\t\t&range,\n\t\t\t&firingRate,\n\t\t\t&reload,\n\t\t\t&ammoAmount,\n\t\t\t&damage,\n\t\t\t&speed,\n\t\t\t&radius,\n\t\t\t&lifeSpan,\n\t\t\t&spread,\n\t\t\t&fireOffsetX,\n\t\t\t&fireOffsetY,\n\t\t\t&fireOffsetZ,\n\t\t\tanimToPlay,\n\t\t\t&animLoopStart,\n\t\t\t&animLoopEnd,\n\t\t\t&delayBetweenAnimAndFire,\n\t\t\t&anim2LoopStart,\n\t\t\t&anim2LoopEnd,\n\t\t\t&delayBetweenAnim2AndFire,\n\t\t\t&animBreakout,\n\t\t\t&modelId,\n\t\t\t&modelId2,\n\t\t\t&flags,\n\t\t\t&weaponSlot);\n\n\t\tif (strncmp(weaponName, \"ENDWEAPONDATA\", 13) == 0)\n\t\t\treturn;\n\n\t\tweaponType = FindWeaponType(weaponName);\n\n\t\tCVector vecFireOffset(fireOffsetX, fireOffsetY, fireOffsetZ);\n\n\t\taWeaponInfo[weaponType].m_eWeaponFire = FindWeaponFireType(fireType);\n\t\taWeaponInfo[weaponType].m_fRange = range;\n\t\taWeaponInfo[weaponType].m_nFiringRate = firingRate;\n\t\taWeaponInfo[weaponType].m_nReload = reload;\n\t\taWeaponInfo[weaponType].m_nAmountofAmmunition = ammoAmount;\n\t\taWeaponInfo[weaponType].m_nDamage = damage;\n\t\taWeaponInfo[weaponType].m_fSpeed = speed;\n\t\taWeaponInfo[weaponType].m_fRadius = radius;\n\t\taWeaponInfo[weaponType].m_fLifespan = lifeSpan;\n\t\taWeaponInfo[weaponType].m_fSpread = spread;\n\t\taWeaponInfo[weaponType].m_vecFireOffset = vecFireOffset;\n\t\taWeaponInfo[weaponType].m_fAnimLoopStart = animLoopStart / 30.0f;\n\t\taWeaponInfo[weaponType].m_fAnimLoopEnd = animLoopEnd / 30.0f;\n\t\taWeaponInfo[weaponType].m_fAnim2LoopStart = anim2LoopStart / 30.0f;\n\t\taWeaponInfo[weaponType].m_fAnim2LoopEnd = anim2LoopEnd / 30.0f;\n\t\taWeaponInfo[weaponType].m_fAnimFrameFire = delayBetweenAnimAndFire / 30.0f;\n\t\taWeaponInfo[weaponType].m_fAnim2FrameFire = delayBetweenAnim2AndFire / 30.0f;\n\t\taWeaponInfo[weaponType].m_fAnimBreakout = animBreakout / 30.0f;\n\t\taWeaponInfo[weaponType].m_nModelId = modelId;\n\t\taWeaponInfo[weaponType].m_nModel2Id = modelId2;\n\t\taWeaponInfo[weaponType].m_Flags = flags;\n\t\taWeaponInfo[weaponType].m_nWeaponSlot = weaponSlot;\n\n\t\tif (animLoopEnd < 98.0f && weaponType != WEAPONTYPE_FLAMETHROWER && !CWeapon::IsShotgun(weaponType))\n\t\t\taWeaponInfo[weaponType].m_nFiringRate = ((aWeaponInfo[weaponType].m_fAnimLoopEnd - aWeaponInfo[weaponType].m_fAnimLoopStart) * 900.0f);\n\n\t\tif (weaponType == WEAPONTYPE_DETONATOR || weaponType == WEAPONTYPE_HELICANNON)\n\t\t\tmodelId = -1;\n\t\telse if (weaponType == WEAPONTYPE_DETONATOR_GRENADE)\n\t\t\tmodelId = MI_BOMB;\n\n\t\tif (modelId != -1)\n\t\t\t((CWeaponModelInfo*)CModelInfo::GetModelInfo(modelId))->SetWeaponInfo(weaponType);\n\n\t\tfor (int i = 0; i < NUM_ANIM_ASSOC_GROUPS; i++) {\n\t\t\tif (!strcmp(animToPlay, CAnimManager::GetAnimGroupName((AssocGroupId)i))) {\n\t\t\t\taWeaponInfo[weaponType].m_AnimToPlay = (AssocGroupId)i;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n}\n\neWeaponType\nCWeaponInfo::FindWeaponType(char *name)\n{\n\tfor (int i = 0; i < WEAPONTYPE_TOTALWEAPONS; i++) {\n\t\tif (strcmp(ms_aWeaponNames[i], name) == 0) {\n\t\t\treturn static_cast<eWeaponType>(i);\n\t\t}\n\t}\n\treturn WEAPONTYPE_UNARMED;\n}\n\neWeaponFire\nCWeaponInfo::FindWeaponFireType(char *name)\n{\n\tif (strcmp(name, \"MELEE\") == 0) return WEAPON_FIRE_MELEE;\n\tif (strcmp(name, \"INSTANT_HIT\") == 0) return WEAPON_FIRE_INSTANT_HIT;\n\tif (strcmp(name, \"PROJECTILE\") == 0) return WEAPON_FIRE_PROJECTILE;\n\tif (strcmp(name, \"AREA_EFFECT\") == 0) return WEAPON_FIRE_AREA_EFFECT;\n\tif (strcmp(name, \"CAMERA\") == 0) return WEAPON_FIRE_CAMERA;\n\tError(\"Unknown weapon fire type, WeaponInfo.cpp\");\n\treturn WEAPON_FIRE_INSTANT_HIT;\n}\n\nvoid\nCWeaponInfo::Shutdown(void)\n{\n\tdebug(\"Shutting down CWeaponInfo...\\n\");\n\tdebug(\"CWeaponInfo shut down\\n\");\n}\n"
  },
  {
    "path": "src/weapons/WeaponInfo.h",
    "content": "#pragma once\n\n#include \"AnimManager.h\"\n#include \"AnimationId.h\"\n#include \"WeaponType.h\"\n\nenum\n{\n\tWEAPONFLAG_USE_GRAVITY = 1,\n\tWEAPONFLAG_SLOWS_DOWN = 1 << 1,\n\tWEAPONFLAG_DISSIPATES = 1 << 2,\n\tWEAPONFLAG_RAND_SPEED = 1 << 3,\n\tWEAPONFLAG_EXPANDS = 1 << 4,\n\tWEAPONFLAG_EXPLODES = 1 << 5,\n\tWEAPONFLAG_CANAIM = 1 << 6,\n\tWEAPONFLAG_CANAIM_WITHARM = 1 << 7,\n\tWEAPONFLAG_1ST_PERSON = 1 << 8,\n\tWEAPONFLAG_HEAVY = 1 << 9,\n\tWEAPONFLAG_THROW = 1 << 10,\n\tWEAPONFLAG_RELOAD_LOOP2START = 1 << 11,\n\tWEAPONFLAG_USE_2ND = 1 << 12,\n\tWEAPONFLAG_GROUND_2ND = 1 << 13,\n\tWEAPONFLAG_FINISH_3RD = 1 << 14,\n\tWEAPONFLAG_RELOAD = 1 << 15,\n\tWEAPONFLAG_FIGHTMODE = 1 << 16,\n\tWEAPONFLAG_CROUCHFIRE = 1 << 17,\n\tWEAPONFLAG_COP3_RD = 1 << 18,\n\tWEAPONFLAG_GROUND_3RD = 1 << 19,\n\tWEAPONFLAG_PARTIALATTACK = 1 << 20,\n\tWEAPONFLAG_ANIMDETONATE = 1 << 21,\n};\n\nclass CWeaponInfo {\n\tstatic char ms_aWeaponNames[WEAPONTYPE_TOTALWEAPONS][32];\npublic:\n\tstatic uint16 ms_aReloadSampleTime[WEAPONTYPE_TOTALWEAPONS];\n\tstatic int32 ms_aMaxAmmoForWeapon[WEAPONTYPE_TOTALWEAPONS];\n\n\teWeaponFire m_eWeaponFire;\n\tfloat m_fRange;\n\tuint32 m_nFiringRate;\n\tuint32 m_nReload;\n\tint32 m_nAmountofAmmunition;\n\tuint32 m_nDamage;\n\tfloat m_fSpeed;\n\tfloat m_fRadius;\n\tfloat m_fLifespan;\n\tfloat m_fSpread;\n\tCVector m_vecFireOffset;\n\tAssocGroupId m_AnimToPlay;\n\tfloat m_fAnimLoopStart;\n\tfloat m_fAnimLoopEnd;\n\tfloat m_fAnimFrameFire;\n\tfloat m_fAnim2LoopStart;\n\tfloat m_fAnim2LoopEnd;\n\tfloat m_fAnim2FrameFire;\n\tfloat m_fAnimBreakout;\n\tint32 m_nModelId;\n\tint32 m_nModel2Id;\n\tuint32 m_Flags;\n\n\tuint32 m_nWeaponSlot;\n\n\tstatic void Initialise(void);\n\tstatic void LoadWeaponData(void);\n\tstatic CWeaponInfo *GetWeaponInfo(eWeaponType weaponType);\n\tstatic eWeaponFire FindWeaponFireType(char *name);\n\tstatic eWeaponType FindWeaponType(char *name);\n\tstatic void Shutdown(void);\n\tstatic bool IsWeaponSlotAmmoMergeable(uint32 slot) { return slot == WEAPONSLOT_SHOTGUN || slot == WEAPONSLOT_SUBMACHINEGUN || slot == WEAPONSLOT_RIFLE; }\n\tbool IsFlagSet(uint32 flag) const { return (m_Flags & flag) != 0; }\n};\n\nVALIDATE_SIZE(CWeaponInfo, 0x64);\n"
  },
  {
    "path": "src/weapons/WeaponType.h",
    "content": "#pragma once\n\nenum eWeaponType\n{\n\tWEAPONTYPE_UNARMED,\n\tWEAPONTYPE_BRASSKNUCKLE,\n\tWEAPONTYPE_SCREWDRIVER,\n\tWEAPONTYPE_GOLFCLUB,\n\tWEAPONTYPE_NIGHTSTICK,\n\tWEAPONTYPE_KNIFE,\n\tWEAPONTYPE_BASEBALLBAT,\n\tWEAPONTYPE_HAMMER,\n\tWEAPONTYPE_CLEAVER,\n\tWEAPONTYPE_MACHETE,\n\tWEAPONTYPE_KATANA,\n\tWEAPONTYPE_CHAINSAW,\n\tWEAPONTYPE_GRENADE,\n\tWEAPONTYPE_DETONATOR_GRENADE,\n\tWEAPONTYPE_TEARGAS,\n\tWEAPONTYPE_MOLOTOV,\n\tWEAPONTYPE_ROCKET,\n\tWEAPONTYPE_COLT45,\n\tWEAPONTYPE_PYTHON,\n\tWEAPONTYPE_SHOTGUN,\n\tWEAPONTYPE_SPAS12_SHOTGUN,\n\tWEAPONTYPE_STUBBY_SHOTGUN,\n\tWEAPONTYPE_TEC9,\n\tWEAPONTYPE_UZI,\n\tWEAPONTYPE_SILENCED_INGRAM,\n\tWEAPONTYPE_MP5,\n\tWEAPONTYPE_M4,\n\tWEAPONTYPE_RUGER,\n\tWEAPONTYPE_SNIPERRIFLE,\n\tWEAPONTYPE_LASERSCOPE,\n\tWEAPONTYPE_ROCKETLAUNCHER,\n\tWEAPONTYPE_FLAMETHROWER,\n\tWEAPONTYPE_M60,\n\tWEAPONTYPE_MINIGUN,\n\tWEAPONTYPE_DETONATOR,\n\tWEAPONTYPE_HELICANNON,\n\tWEAPONTYPE_CAMERA,\n\tWEAPONTYPE_TOTALWEAPONS = 37,\n\tWEAPONTYPE_HEALTH = 37,\n\tWEAPONTYPE_ARMOUR,\n\tWEAPONTYPE_RAMMEDBYCAR,\n\tWEAPONTYPE_RUNOVERBYCAR,\n\tWEAPONTYPE_EXPLOSION,\n\tWEAPONTYPE_UZI_DRIVEBY,\n\tWEAPONTYPE_DROWNING,\n\tWEAPONTYPE_FALL,\n\tWEAPONTYPE_UNIDENTIFIED,\n\tWEAPONTYPE_ANYMELEE,\n\tWEAPONTYPE_ANYWEAPON\n};\n\nenum {\n\tWEAPONSLOT_UNARMED = 0,\n\tWEAPONSLOT_MELEE,\n\tWEAPONSLOT_PROJECTILE,\n\tWEAPONSLOT_HANDGUN,\n\tWEAPONSLOT_SHOTGUN,\n\tWEAPONSLOT_SUBMACHINEGUN,\n\tWEAPONSLOT_RIFLE,\n\tWEAPONSLOT_HEAVY,\n\tWEAPONSLOT_SNIPER,\n\tWEAPONSLOT_OTHER,\n\tTOTAL_WEAPON_SLOTS\n};\n\nenum eWeaponFire {\n\tWEAPON_FIRE_MELEE,\n\tWEAPON_FIRE_INSTANT_HIT,\n\tWEAPON_FIRE_PROJECTILE,\n\tWEAPON_FIRE_AREA_EFFECT,\n\tWEAPON_FIRE_CAMERA\n};\n\n// Taken from MTA SA, seems it's unchanged\nenum eWeaponState\n{\n\tWEAPONSTATE_READY,\n\tWEAPONSTATE_FIRING,\n\tWEAPONSTATE_RELOADING,\n\tWEAPONSTATE_OUT_OF_AMMO,\n\tWEAPONSTATE_MELEE_MADECONTACT\n};"
  },
  {
    "path": "utils/gxt/american.txt",
    "content": "﻿[IN_VEH]\n~g~Hey! Get back in the vehicle!\n\n[HEY]\n~g~Don't go solo, keep your posse together!\n\n[HELP3]\nYou can only sprint for short periods before becoming tired.\n\n[HELP4_D]\nPush the right analog stick up to ~h~accelerate.\n\n[HELP5_D]\nPull the right analog stick back to brake, or to reverse if the vehicle has stopped.\n\n[HELP7_A]\nPress and hold the~h~ ~k~~PED_LOCK_TARGET~ button ~w~to ~h~target~w~ with the sniper rifle.\n\n[HELP7_D]\nPress and hold the~h~ ~k~~PED_LOCK_TARGET~ button ~w~to ~h~target ~w~with the sniper rifle.\n\n[HELP10]\nThis badge indicates you have a police wanted level.\n\n[HELP11]\nThe more badges the higher your wanted level.\n\n[HELP13]\nSometimes you may need to use pathways not shown on the radar.\n\n[TIMER]\nThis is a timed mission, you must complete it before the timer counts down to zero.\n\n[HORN]\n~g~Sound the horn.\n\n[NOMONEY]\n~g~You need more cash!\n\n[REWARD]\nREWARD $~1~\n\n[M_FAIL]\nMISSION FAILED!\n\n[M_PASS]\nMISSION PASSED! $~1~\n\n[DEAD]\nWASTED!\n\n[BUSTED]\nBUSTED!\n\n[WEATHE1]\nFORCE WEATHER SUNNY\n\n[WEATHE2]\nFORCE WEATHER EXTRA SUNNY\n\n[WEATHE3]\nFORCE WEATHER CLOUDY\n\n[WEATHE4]\nFORCE WEATHER RAINY\n\n[WEATHE5]\nFORCE WEATHER FOGGY\n\n[WEATHE6]\nWEATHER NORMAL\n\n[NUMBER]\n~1~\n\n[LOADCAR]\nLOADING VEHICLE... (PRESS L1 TO CANCEL)\n\n[CARSOFF]\nCars turned off.\n\n[CARS_ON]\nCars turned on.\n\n[TEXTXYZ]\nWriting coordinates to file...\n\n[CHEATON]\nCheat mode ON\n\n[CHEATOF]\nCheat mode OFF\n\n[IMPORT1]\nGo outside and wait for your vehicle.\n\n[PAGEB11]\nFlamethrower delivered to hideout.\n\n[WANT_A]\nYou will only be arrested if you have a ~h~wanted level.\n\n[WANT_B]\nYour ~h~wanted level~w~ is represented by the row of stars in the top right of the screen.\n\n[WANT_C]\nYou now have a ~h~wanted level~w~ of one...\n\n[WANT_D]\ntwo...\n\n[WANT_E]\nthree...\n\n[WANT_F]\nAs your ~h~wanted level~w~ increases you will attract more powerful forms of law enforcement.\n\n[WANT_G]\nWhen you are ~h~'busted'~w~ you are returned to the nearest police station.\n\n[WANT_H]\nThe cops will take all your weapons and some of your cash as a bribe.\n\n[WANT_I]\nAny mission you were on will be failed.\n\n[WANT_J]\nYou will find ways of reducing your wanted level the more you play.\n\n[WANT_K]\nIf you are in a car, ~h~SPRAY SHOPS~w~ will ~h~clear your wanted level.\n\n[HEAL_B]\nWhen you are ~h~'wasted'~w~ you are returned to the nearest hospital.\n\n[HEAL_C]\nYou will lose your weapons and the doctors will take some cash for patching you up.\n\n[HEAL_E]\nYou will find ways of healing or protecting yourself the more you play the game.\n\n[SAVE1]\nWalk into the corona to ~h~Save the game~w~. You cannot save during a mission.\n\n[SAVE2]\nAny vehicle left in this garage will be stored when the game is saved.\n\n[AMMU]\nGo inside Ammu-Nation to buy a weapon.\n\n[R_TIME]\nRACE TIME:\n\n[PROP_1]\nYou don't have enough cash for this property\n\n[PROP_2]\nYou cannot buy property whilst on a mission\n\n[IND_ZON]\nVice City Beach\n\n[COM_ZON]\nVice City Mainland\n\n[BEACH1]\nOcean Beach\n\n[BEACH2]\nWashington Beach\n\n[BEACH3]\nVice Point\n\n[GOLFC]\nLeaf Links\n\n[STARI]\nStarfish Island\n\n[DOCKS]\nViceport\n\n[HAVANA]\nLittle Havana\n\n[HAITI]\nLittle Haiti\n\n[PORNI]\nPrawn Island\n\n[DTOWN]\nDowntown\n\n[VICE_C]\nVice City\n\n[A_PORT]\nEscobar International\n\n[JUNKY]\nJunk Yard\n\n[PISTOL]\nPistol\n\n[PYTHON]\n.357\n\n[UZI]\nUz-1\n\n[TEC9]\nTec 9\n\n[M4]\nM4\n\n[INGRAM]\nMac\n\n[MP5]\nMP\n\n[RUGER]\nKruger\n\n[SNIPE]\nSniper rifle\n\n[GRENADE]\nGrenades\n\n[SHOTGN1]\nShotgun\n\n[SHOTGN2]\nS.P.A.S. 12\n\n[SHOTGN3]\nStubby shotgun\n\n[ARMOUR]\nBody Armor\n\n[LASER]\n.308 Sniper\n\n[BASEBAT]\nBaseball bat\n\n[HAMMER]\nHammer\n\n[SCREWD]\nScrewdriver\n\n[CLEVER]\nMeat Cleaver\n\n[MACHETE]\nMachete\n\n[KNIFE]\nKnife\n\n[KATANA]\nKatana\n\n[CHAINSA]\nChainsaw\n\n[G_COST]\nCost: $~1~\n\n[CAR_1]\nAmbulance\n\n[MALIBU]\nThe Malibu Club\n\n[MANSION]\nDiaz's Mansion\n\n[TMANS]\nVercetti Estate\n\n[STRIP]\nThe 'Pole Position Club'\n\n[MALL1]\nNorth Point Mall\n\n[BANKINT]\nEl Banco Corrupto Grande\n\n[RANGE]\nRifle Range\n\n[POL_HQ]\nVCPD HQ\n\n[INT_B]\nAn Old Friend\n\n[INTB_1]\n~g~Go to the Lawyer's office.\n\n[LAW_1]\nThe Party\n\n[LAW_2]\nBack Alley Brawl\n\n[LAW_3]\nJury Fury\n\n[LAW_4]\nRiot\n\n[COL_1]\nTreacherous Swine\n\n[COL_2]\nMall Shootout\n\n[COL_3]\nGuardian Angels\n\n[COL_4]\nSir, Yes Sir!\n\n[COL_5]\nAll Hands On Deck!\n\n[COK_1]\nThe Chase\n\n[COK_2]\nPhnom Penh '86\n\n[COK_3]\nThe Fastest Boat\n\n[COK_4]\nSupply & Demand\n\n[KENT_1]\nDeath Row\n\n[ASS_1]\nRub Out\n\n[BUD_1]\nShakedown\n\n[BUD_2]\nBar Brawl\n\n[BUD_3]\nCop Land\n\n[CAP_1]\nCap the Collector\n\n[FIN_1]\nKeep your Friends Close...\n\n[BANK_1]\nNo Escape?\n\n[BANK_2]\nThe Shootist\n\n[BANK_3]\nThe Driver\n\n[BANK_4]\nThe Job\n\n[CNT_1]\nSpilling the Beans\n\n[CNT_2]\nHit the Courier\n\n[PORN_1]\nRecruitment Drive\n\n[PORN_2]\nDildo Dodo\n\n[PORN_3]\nMartha's Mug Shot\n\n[PORN_4]\nG-spotlight\n\n[TAX_1]\nKaufman Cabs\n\n[TAXI_1]\nV.I.P.\n\n[TAXI_2]\nFriendly Rivalry\n\n[TAXI_3]\nCabmaggedon\n\n[ICE_1]\nDistribution\n\n[TEX_1]\nFour Iron\n\n[TEX_2]\nTwo Bit Hit\n\n[TEX_3]\nDemolition Man\n\n[PHIL_1]\nGun Runner\n\n[PHIL_2]\nBoomshine Saigon\n\n[BIKE_1]\nAlloy Wheels of Steel\n\n[BIKE_2]\nMessing with the Man\n\n[BIKE_3]\nHog Tied\n\n[ROCK_1]\nLove Juice\n\n[ROCK_2]\nPsycho Killer\n\n[ROCK_3]\nPublicity Tour\n\n[ROCK_4]\nLove Fist!!\n\n[HAT_1]\nJuju Scramble\n\n[HAT_2]\nBombs Away!\n\n[HAT_3]\nDirty Lickin's\n\n[CUB_1]\nStunt Boat Challenge\n\n[CUB_2]\nCannon Fodder\n\n[CUB_3]\nNaval Engagement\n\n[CUB_4]\nTrojan Voodoo\n\n[JOB_1]\nRoad Kill\n\n[JOB_2]\nWaste the Wife\n\n[JOB_3]\nAutocide\n\n[JOB_4]\nCheck Out at the Check In\n\n[JOB_5]\nLoose Ends\n\n[ANSWER]\nPress the ~h~~k~~PED_ANSWER_PHONE~~w~ to answer your cell phone.\n\n[MOB_01A]\nAwright me ol'china! It's Paul. I might have a little result for you, but I need to speak to you in person.\n\n[MOB_01B]\nI'm enjoying a little R&R at the Club Malibu.\n\n[MOB_01C]\nReckon you're gonna owe me a favor or two after this, sunshine. I'll see you later.\n\n[MOB_02A]\nSsssnniiiiffffff Hey! Hello, Tommy? Tommy!\n\n[MOB_02B]\nWe got a situation over at the Print Works. You better go and check it out.\n\n[MOB_02C]\nSome kind of mess or other. Things are messed up. I gotta go.\n\n[MOB_03A]\nMr. Vercetti? I have here a signed piece of crap stating\n\n[MOB_03B]\nthat you have taken on all of BJ's Auto's debts.\n\n[MOB_03C]\nWith BJ's sudden disappearance I have no choice\n\n[MOB_03D]\nbut to hold you responsible for his financial insecurities.\n\n[MOB_03E]\nUntil this account is settled in full\n\n[MOB_03F]\nyou should consider Vice City's streets to be very unfriendly.\n\n[MOB_04A]\nHow you doin' mate? It's Paulo again.\n\n[MOB_04B]\nLook Tommy, I forgot to mention we're going to need some extra muscle for the concert. A bit of security.\n\n[MOB_04C]\nThere's a biker gang led by Mitch Baker, it would be great publicity. Very rock and roll, baby.\n\n[MOB_04D]\nSort this out for me and I'll get you some back stage passes for the gig, awright?\n\n[MOB_05A]\nHey, it's Mitch. You did good Tommy, it's good to have the old girl back.\n\n[MOB_05B]\nYou tell Kent Paul he'll get his security for the gig.\n\n[MOB_05C]\nYou have my word on that.\n\n[MOB_05D]\nNow keep yourself out of trouble.\n\n[MOB_06A]\nTommy, 'nuf dead man been chattin' about you, my dear.\n\n[MOB_06B]\nThought you might need something to make you feel better. So Auntie Poulet make you some stew, aye?\n\n[MOB_06C]\nCome by me kitchen some time, ok Tommy?\n\n[MOB_08A]\nHey Tommy, I thought you might need some business advice.\n\n[MOB_08B]\nOnce you got an operation up and running, you'll need to drop by and take the week's cash.\n\n[MOB_08C]\nLet the guys think they got the run of the place and they'll try shaving the profits - ok?\n\n[MOB_08D]\nHey, I know how to handle business, Ken, ok?\n\n[MOB_08E]\nOk, ok. I know, you know. I know. I was,\n\n[MOB_08F]\nI was just, you know, telling you I know, that you know, that I know.\n\n[MOB_08G]\nJust keeping it sharp baby!\n\n[MOB_08H]\nWhatever, Ken, whatever...\n\n[MOB_09A]\nHey Leo! I got some work for you!\n\n[MOB_09B]\nThis ain't Leo.\n\n[MOB_09C]\nHey, if Leo knows you got his phone, he gonna kill you!\n\n[MOB_09E]\nYou killed Leo? You must have big cojones - wanna work for me?!\n\n[MOB_09F]\nDrop by my father's cafe in Little Havana and we'll talk mano a mano.\n\n[MOB_10A]\nTommy! Look, I gotta ask you a favor.\n\n[MOB_10B]\nSteve! How's filming going!\n\n[MOB_10C]\nFine, fine. I, heh, WE need a car chase scene, but our budget can't stretch to it.\n\n[MOB_10D]\nI've left some wheels around town. You'll know what to do.\n\n[MOB_10E]\nOk Steve, I'll keep an eye out. Catch you later.\n\n[MOB_11A]\nHowdy son, just thought I'd ring you up and give you some advice.\n\n[MOB_11B]\nHey, Avery. What's eating you?\n\n[MOB_11C]\nThere's a lot of opportunity in this town if you own the right real estate, you catch my drift?\n\n[MOB_11D]\nI reckon so...\n\n[MOB_11E]\nAll I'm saying is keep your eyes open and you might find the perfect business opportunity. I'll catch y'later.\n\n[MOB_11F]\nLater, Avery.\n\n[MOB12_A]\nHey Tommy, it's Avery! Now listen, I got me all tied up at the moment\n\n[MOB12_B]\nand I have a representative of mine needs chaperoning out to the Gator Keys.\n\n[MOB12_C]\nI'm after some land out that way, so I'm sending someone out to sweeten the deal.\n\n[MOB12_D]\nCould you do me a favor and make sure he gets there ok?\n\n[MOB12_E]\nYeah, sure thing Avery. Where'd you want me to pick him up?\n\n[MOB12_F]\nHe's just finishing some business at the building site. I said you'd pick him up from there.\n\n[MOB12_G]\nNo problem. See you later, Avery.\n\n[MOB13_A]\nVercetti? VERCETTI!! Damn you man, you've got to help me!\n\n[MOB13_B]\nMr. Moffat? How's family life?\n\n[MOB13_C]\nDamn you to hell, HELL, do hear me?!\n\n[MOB13_D]\nWell it was nice chatting...\n\n[MOB13_E]\nWAIT! Wait, Vercetti - Tommy, can I call you Tommy?\n\n[MOB13_F]\nWe're both businessmen, yeah? You know a good deal when you hear one, ok?\n\n[MOB13_G]\nI don't have time to chat, get to the point.\n\n[MOB13_H]\nMONEY. Money is the goddamned point.\n\n[MOB13_I]\nI've escaped the coop again, but it's never long before they track me down - they think it's a damned game!\n\n[MOB13_J]\nI'm at a pay phone somewhere in this god forsaken shit hole.\n\n[MOB13_K]\nGet me out of here before they take me back and...and..oh go-o-od...\n\n[MOB13_L]\nWell, I'm busy for the next -\n\n[MOB13_M]\nNo! Don't shit with me here, have a heart! No man should have to do such, such things.\n\n[MOB13_N]\nI'm on my knees here Tommy, in the dirt begging you please...\n\n[MOB13_O]\nI guess I could swing by that way, see if I can spot you...\n\n[MOB13_P]\nOh god, they're coming. For the love of Christ hurry, hurry!\n\n[MOB_14A]\nHey there Tommy, you're gonna love me mate.\n\n[MOB_14B]\nA little birdy told me that Vice City SWAT Division has a deposit box at a certain rather large banking establishment,\n\n[MOB_14C]\nwhere they keep all the bribes they've taken over the years,\n\n[MOB_14D]\nlike some kind of old boys' retirement fund.\n\n[MOB_14E]\nOf course, if this information should ever help you acquire any of that cash,\n\n[MOB_14F]\nI guess you'd feel obliged to push some of it my way?\n\n[MOB_14G]\nI'll bear that in mind, thanks Kent.\n\n[MOB_14H]\nIt's Paul. I'm from Kent, near London, you prat.\n\n[MOB_14I]\nMy provincial English geography ain't what it was.\n\n[MOB15_A]\nTommy, mate, it's Paul, from Kent,\n\n[MOB15_B]\na couple of proper sorts have your name written all over them, down at the Malibu.\n\n[MOB15_C]\nWhat are you talking about?\n\n[MOB15_D]\nSorts. Birds. You know. Girls. Tastey ones, don't think they're brasses or nothing.\n\n[MOB15_E]\nYou gotta come check them out.\n\n[MOB16_A]\nTommy, Paulo here, que pasa amigo?\n\n[MOB16_B]\nWhat do you want Paul. I don't want any fake label clothes.\n\n[MOB16_C]\nVery funny, mate, but you know I don't touch bent gear.\n\n[MOB16_D]\nNah, I was just calling to see if I get a part in one your movies,\n\n[MOB16_E]\nback in England I did a lot of blue stuff, mate.\n\n[MOB16_F]\nI'm packing more heat than you, my son.\n\n[MOB16_G]\nPaul, thanks for the offer, I'll bear it in mind.\n\n[MOB16_H]\nSeriously, don't forget about me, after all I done for you.\n\n[MOB16_I]\nThat's what I'm trying to forget about.\n\n[MOB19_A]\nTommy V, It's KP here. Kent Paul. Word on the street is people want to rip you off.\n\n[MOB19_B]\nKeep your eye's peeled, my son. And remember, I didn't say nothing to you about this.\n\n[MOB_20A]\nAlright, Tommy, it's Paul. I just heard from a mush that you've been a real naughty boy.\n\n[MOB_20B]\nSomebody has taken offense to you acting like the big guy all of a sudden, giving it the big shot thing.\n\n[MOB_20C]\nWell, don't say I never warned you or nothing. Boasting is a mug's game, son.\n\n[MOB_20D]\nAnyway, I heard there's some price been put on your head and someone's going to have a crack at you,\n\n[MOB_20E]\nso watch yourself, and remember me, mate.\n\n[MOB21_A]\nTommy, Thomas, it's Cortez. Que pasa?\n\n[MOB21_B]\nThings are interesting. How are you, my friend?\n\n[MOB21_G]\nI wanted to ask you about Mercedes.\n\n[MOB21_H]\nOk, what about her?\n\n[MOB21_I]\nOh Tommy, Tommy. I, I hear these stories, all these stories - I don't know what to think.\n\n[MOB21_K]\nMaybe she thinks she can do what she likes, but Tommy, tell me, is it true?\n\n[MOB21_M]\nIs what true?\n\n[MOB21_N]\nThese stories I hear. Is she really going to be a lawyer?\n\n[MOB21_O]\nOh Tommy, the shame, the shame! You know, we Cortez's are a proud family.\n\n[MOB21_P]\nWe would never allow a daughter of ours to become a lawyer. Please tell me it isn't so. I don't think I could take it.\n\n[MOB21_Q]\nOh Colonel, I can assure you Mercedes is never going to become a lawyer. Don't worry about it.\n\n[MOB21_R]\nOh thank you, Tommy. Tommy, thank you. The shame would be unbearable. She is a lady, not a parasite, you know.\n\n[MOB21_S]\nI know, colonel.\n\n[MOB21_T]\nAnyway, Tommy, you must excuse me, the new minister of the interior has arrived.\n\n[MOB21_U]\nMany years ago, I killed his father in a failed coup so I must be polite. Good day, amigo.\n\n[MOB21_C]\nTommy, it is always a struggle here. Excuse the poor line, we have just had another failed coup.\n\n[MOB21_D]\nThe people are the most demanding mistress of all.\n\n[MOB21_E]\nSo far, we have had three revolutions and four coups since I return from Vice City.\n\n[MOB21_F]\nLuckily, I have been promoted each time.\n\n[MOB21_J]\nMaybe everyone is humiliating me.\n\n[MOB21_L]\nbut tell me Tommy, is it true?\n\n[MOB22_A]\nTommy, you are proving very useful, my friend.\n\n[MOB22_B]\nThanks, Cortez. What about my deal?\n\n[MOB22_C]\nTommy, I am working tirelessly on your behalf to ensue we get to the bottom of this trench of stinking lies and deceit,\n\n[MOB22_D]\nyou have my word on that, but in the meantime,\n\n[MOB22_E]\nplease accept the esteemed thanks of my people for your work on our behalf.\n\n[MOB_25A]\nTommy, Thomas it's Cortez. Look, the French are giving me all kinds of trouble, amigo.\n\n[MOB_25B]\nDamn hypocrites. They spend a hundred years stealing from poor countries and they call me a thief!\n\n[MOB_25C]\nI am going to need your help as soon as possible, amigo.\n\n[MOB_25D]\nSo please hurry, Tommy, I need you, all right? I hate the damn French.\n\n[MOB_26A]\nHello, Tommy?\n\n[MOB_26B]\nYeah?\n\n[MOB_26C]\nIt's Baker. I just wanted to say I really enjoyed the show.\n\n[MOB_26D]\nMe and the boys want to thank you, and remind you,\n\n[MOB_26E]\nyou got our respect. Good day. Keep riding hard, son.\n\n[MOB_29A]\nHello, is this Mr. Tommy Vercetti?\n\n[MOB_29B]\nYes.\n\n[MOB_29C]\nWell, I hear through the vine of grapes you the man when someone got a vermin infestation.\n\n[MOB_29D]\nMaybe...\n\n[MOB_29E]\nWell, I got a real vermin infestation. Haitians everywhere.\n\n[MOB_29F]\nMy name is Umberto Robina and I want you to meet me at the Cafe Robina as soon as you can,\n\n[MOB_29G]\n'cause I tell you, these damn Haitians gone too far this time.\n\n[MOB_29H]\nTest\n\n[MOB_30A]\nTommy, is Umberto Robina\n\n[MOB_30B]\nHey, how's the cafe?\n\n[MOB_30C]\nOh, wonderful. Incredible. Tommy, incredible. No wimps, Tommy, just real men, and the beautiful women!\n\n[MOB_30D]\nAnyway, I wanted to tell you, me and Papi, to us, you Cuban.\n\n[MOB_30E]\nYou have proved yourself, man. You got big cojones.\n\n[MOB_30F]\nWell thank you, Umberto. Nobody's said that to me since I left jail. I'll see you around.\n\n[MOB_33A]\nTommy, it's Phil, now cut out all the reminiscing crap and listen to me, you hear?\n\n[MOB_33B]\nGood. I got me some extra strength boomshine nearing fermentation time and I was wondering if you'd fancy having a shot.\n\n[MOB_33C]\nSeriously, Tommy, if you like a drink, or if you need to strip paint, this stuff'll make a man out of you.\n\n[MOB_33D]\nSure did out of me, even though I can't see out of one eye. I'll be waiting for you, y'hear.\n\n[MOB_34A]\nTommy, I really enjoyed working with you. Ain't had so much fun since the ridge in Nam, pal.\n\n[MOB_34B]\nAnyhows, you need anything, you call on me, you hear?\n\n[MOB_34C]\nI always remember those I served with,\n\n[MOB_34D]\nand I am sure I can help you out, you hear?\n\n[MOB_35A]\nTommy, the wound is healing well. Funny thing is,\n\n[MOB_35B]\nI have fought in 6 battle zones and always walked away without a scratch, and now this!\n\n[MOB_35C]\nOne armed Phil. Still, I got me a healthy selection of one handed fire power so I'll never be unarmed Phil, you hear.\n\n[MOB_35D]\nAny way son, cut out the sentimental crap and go buy yourself a drink, you hear!\n\n[MOB_36A]\nTommy, it's Phil, I want to thank you for helping me out back there son,\n\n[MOB_36B]\nDamn Charlie, he'll always ambush you somewhere or other,\n\n[MOB_36C]\nAnyway the wound is healing well, and it means I'll no longer be defrauding the government on my disability check.\n\n[MOB_40A]\nHey Tommy, it's Sonny. How's the sun tan?\n\n[MOB_40B]\nI ain't got no sun tan.\n\n[MOB_40C]\nWell, you ain't got my money, either, so I'm wondering to myself,\n\n[MOB_40D]\nwhat are you doing? So, tell me, Tommy, what are you doing?\n\n[MOB_40E]\nI'm looking for the money, Sonny. Don't worry.\n\n[MOB_40F]\nI am worrying, Tommy, that's my style,\n\n[MOB_40G]\nbecause I seem to have this problem in my life with unreliable people.\n\n[MOB_40H]\nDon't be an unreliable person, Tommy, please.\n\n[MOB_40I]\nDo us both a favor. I'm looking forward to hearing from you.\n\n[MOB_41A]\nTommy, remember me?\n\n[MOB_41B]\nHello Sonny.\n\n[MOB_41C]\nThat's right, Sonny. We're old friends,\n\n[MOB_41D]\nYou never write me, you never call. Don't you want to be friends no more?\n\n[MOB_41E]\nI've been busy trying to sort things out. You didn't give me a lot of support down here, Sonny.\n\n[MOB_41F]\nOh, my fault is it? We'll I've heard you been busy all right.\n\n[MOB_41G]\nBusy killing drugs barons. Busy taking over.\n\n[MOB_41H]\nDon't forget about us, Tommy, 'cause I can assure you, I ain't forgotten about you.\n\n[MOB_42A]\nTommy.\n\n[MOB_42B]\nSonny.\n\n[MOB_42C]\nObviously you are suffering from hearing problems, so I'll try again.\n\n[MOB_42D]\nWhere's the goddamned money, where's the goddamned stuff, and where's my cut of your new action?\n\n[MOB_42E]\nYou are making an idiot out of me, Tommy, and I'm not laughing yet.\n\n[MOB_43A]\nTommy, Tommy, Tommy, I had Sonny on the phone, ok, are you with me?.\n\n[MOB_43B]\nI don't know about you, but there's something about a man threatening to murder my family\n\n[MOB_43C]\nwhich really scares the crap out of me. What are you going to do?\n\n[MOB_43D]\nKen, take it easy.\n\n[MOB_43E]\nI AM calm, calm as a man can be when he's fearing for his life!\n\n[MOB_43F]\nStay off the idiot fuel and look after yourself.\n\n[MOB_43G]\nNo one's gonna take us out. I'll see you later.\n\n[MOB_43H]\nI am calm. Don't I sound calm? Must be impending death that is doing this to my voice.\n\n[MOB45_A]\nTommy We gotta talk about stuff.\n\n[MOB45_B]\nWhat's the problem Lance?\n\n[MOB45_C]\nIt's you, my friend, I feel you're not giving me a fair slice.\n\n[MOB45_D]\nAnd more than that, you been embarrassing me in front of the boys. I can't have that.\n\n[MOB45_E]\nLance, it ain't like that. You've been making mistakes.\n\n[MOB45_F]\nTommy, I'm not your message boy. I'm not your running boy.\n\n[MOB45_G]\nLance, don't screw up, and we won't have any problems. I screw up, you can lay into me any time.\n\n[MOB45_H]\nTommy, I've done everything for you, you treat me like a fool. Don't do that.\n\n[MOB45_I]\nLance, I won't rip you off or stab you in the back, okay?\n\n[MOB45_J]\nJust take it easy. This is tough enough without you getting all emotional on me.\n\n[MOB45_K]\nTrust me. Do you hear me, do you hear me?\n\n[MOB45_L]\nI hear you, Tommy, but I can't take this much more.\n\n[MOB45_M]\nLance, don't be like this. Now I'm warning you.\n\n[MOB45_N]\nDo you hear me? Just relax, take a few days off. Okay? I'll talk to you.\n\n[MOB46_A]\nYo, Tommy! It's Lance.\n\n[MOB46_B]\nYeah?\n\n[MOB46_C]\nOh, nice to hear from you, Lance. Come on, man, be cool, be cool.\n\n[MOB46_D]\nI'm in the middle of something. What do you want?\n\n[MOB46_E]\nNothing. Just to say, you know. Look Tommy, we can do this thing.\n\n[MOB46_F]\nYou and me, no problem. You know what I mean?\n\n[MOB46_G]\nWe're going to have to do it, 'cause otherwise, we're going to be dead, Lance.\n\n[MOB46_H]\nWe're in too far now. But thanks for the call. I'll speak to you later.\n\n[MOB_47A]\nTommy, Lance, we got big problems. Come down here. Right away.\n\n[MOB52_A]\nHey Leo, I think we got a buyer for Diaz's merchandise.\n\n[MOB52_B]\nYou gotta give him a ring, man, set up the deal, you know?\n\n[MOB52_C]\nWhere are you now?\n\n[MOB52_D]\nYou ok Leo? You sound kinda different.\n\n[MOB52_E]\nJust tell me where you are.\n\n[MOB52_F]\nWho the hell is this? Put Leo on, man!\n\n[MOB52_G]\nLeo's gone away for a while, he left me in charge.\n\n[MOB52_H]\nScrew you, man!\n\n[MOB54_A]\nHiya Tommy!\n\n[MOB54_B]\nHi Mercedes, howyadoin'?\n\n[MOB54_C]\nI got a new apartment up in Vice Point\n\n[MOB54_D]\n- thought you might want to drop by sometime.\n\n[MOB54_E]\nI'd love to. I'll catch you later.\n\n[MOB55_A]\nTommy, it's me.\n\n[MOB55_B]\nHi Mercedes.\n\n[MOB55_C]\nTommy, I so bored, when we going to have some fun?\n\n[MOB55_D]\nWhat do you mean?\n\n[MOB55_E]\nWell, I know you're busy fighting and killing and corrupting people,\n\n[MOB55_F]\nbut I just want to have some fun. So don't forget about me, you hear?\n\n[MOB56_A]\nTommy, I hear you kill Ricardo Diaz.\n\n[MOB56_B]\nthere was an unfortunate fire at his mansion.\n\n[MOB56_C]\nI think he burnt to death in an acrylic shirt.\n\n[MOB56_D]\nTommy, I so proud of you. I knew you were a real man.\n\n[MOB56_E]\nHe awful trouser stain of a man, you make me so proud to be your friend.\n\n[MOB56_F]\nNo, I know you going to be busy trying to take over this town,\n\n[MOB56_G]\nbut don't forget about me, you hear?\n\n[MOB57_A]\nIt's merceedes. I no longer love you Tommy.\n\n[MOB57_B]\nI no longer do. Honest. 'cause you no longer nice to Mercedes.\n\n[MOB57_C]\nYou no longer treat her like a lady. You ignore me and I hate you.\n\n[MOB57_D]\nI insist you come to see me right away!\n\n[MOB58_A]\nTommy.\n\n[MOB58_B]\nHey Mercedes.\n\n[MOB58_C]\nHey indeed Mr. Tough Guy. I real angry with you Tommy.\n\n[MOB58_D]\nNever make me hang out with Jezz Torrent again.\n\n[MOB58_E]\nHe is pathetic. Half way through he starts crying about his doggie\n\n[MOB58_F]\nthat died when he was 7 years old and that his mommy never loved him.\n\n[MOB58_G]\nAnd Tommy. He wear a wig and a bra in private.\n\n[MOB58_H]\nI not very happy with you!\n\n[MOB59_A]\nOoh Tommy, its Mercedes.\n\n[MOB59_B]\nI just want to say, I have so much fun on that film set.\n\n[MOB59_C]\nAnything else you have like that, you let me know.\n\n[MOB59_D]\nI really mean that. I always wanted to be an actress.\n\n[MOB59_E]\nI think I learn a lot about the dramatic process.\n\n[MOB59_F]\nIt so enlightening! Thank you. Thank you. I see you real soon. Adios.\n\n[MOB_99]\nGet to the payphone at location.\n\n[MOB_98]\nGet to the payphone at location.\n\n[MOB_97]\nGet to the payphone at location.\n\n[MOB_96]\nGet to the payphone at location.\n\n[MOB_95]\nGet to the payphone at location.\n\n[A_TIME]\n+~1~ seconds\n\n[DODO_FT]\nYou flew for ~1~ seconds!\n\n[GA_8]\nUse the detonator to activate the bomb.\n\n[GA_10]\nNice one. Here's your $~1~\n\n[GA_11]\nWe got these wheels already. It's worthless to us!\n\n[GA_12]\nBomb armed\n\n[GA_13]\nDelivered like a pro. Complete the list and there'll be a bonus for you.\n\n[GA_14]\nAll the cars. NICE! Here's a little something.\n\n[GA_15]\nHope you like the new color.\n\n[GA_16]\nRespray is complementary.\n\n[GA_19]\nWe're not interested in that model.\n\n[GA_20]\nWe got more of these than we can shift. Sorry man, no deal.\n\n[CHASE]\nHighest media attention\n\n[CHASE1]\nIgnored\n\n[CHASE2]\nBoring\n\n[CHASE3]\nVaguely interesting\n\n[CHASE4]\nLocal paper Page 7\n\n[CHASE5]\nFront page of local paper\n\n[CHASE6]\nVice Courier Page 2\n\n[CHASE7]\nVice Courier Front page\n\n[CHASE8]\nLocal TV 3am\n\n[CHASE9]\nLocal TV news\n\n[CHASE10]\nLocal TV Live coverage\n\n[CHASE11]\nUFA Today page 12\n\n[CHASE12]\nUFA Today page 4\n\n[CHASE13]\nPicture in UFA Today\n\n[CHASE14]\nNational TV 4am\n\n[CHASE15]\nNational TV news\n\n[CHASE16]\nNational TV live coverage\n\n[CHASE17]\nInternational news\n\n[CHASE18]\nNational crisis\n\n[CHASE19]\nInternational crisis\n\n[CHASE20]\nWorld event\n\n[CHASE21]\nStuff of legends\n\n[CR_1]\nCrane cannot lift this vehicle.\n\n[PU_MONY]\nYou don't have enough cash.\n\n[CO_ALL]\nYou got all of them. Here's a little something...\n\n[FEM_ON]\nON\n\n[FEM_OFF]\nOFF\n\n[FEM_YES]\nYes\n\n[FEM_NO]\nNo\n\n[FEC_NA]\nNA\n\n[FEC_CWL]\nCycle Weapon left\n\n[FEC_CWR]\nCycle Weapon right\n\n[FEC_LOF]\nLook forward\n\n[FEC_TAR]\nTarget\n\n[FEC_MOV]\nMovement\n\n[FEC_CAM]\nCamera modes\n\n[FEC_PAU]\nPause\n\n[FEC_ENV]\nEnter vehicle\n\n[FEC_JUM]\nJump\n\n[FEC_ATT]\nAttack or Fire weapon\n\n[FEC_RUN]\nRun\n\n[FEC_FPC]\nFirst person camera\n\n[FEC_LL]\nLook left\n\n[FEC_LB]\nLook behind\n\n[FEC_LR]\nLook right\n\n[FEC_HOR]\nHorn\n\n[FEC_VES]\nVehicle control\n\n[FEC_BRA]\nBrake or Reverse\n\n[FEC_HAB]\nHand brake\n\n[FEC_CAW]\nCar weapon\n\n[FEC_ACC]\nAccelerate\n\n[FEC_CCF]\nConfiguration\n\n[FEC_CF1]\nSetup 1\n\n[FEC_CF2]\nSetup 2\n\n[FEC_CF3]\nSetup 3\n\n[FEC_CF4]\nSetup 4\n\n[FEC_CDP]\nController Display\n\n[FEC_ONF]\nOn foot\n\n[FEC_INC]\nIn car\n\n[FEC_VIB]\nVibration\n\n[FEL_ENG]\nEnglish\n\n[FEL_FRE]\nFrench\n\n[FEL_GER]\nGerman\n\n[FEL_ITA]\nItalian\n\n[FEL_SPA]\nSpanish\n\n[FED_DBG]\nMenu Debug\n\n[FED_RID]\nReload IDE\n\n[FED_RIP]\nReload IPL\n\n[FED_PAH]\nParse Heap\n\n[FED_DFL]\nCTheScripts::DbgFlag\n\n[FED_DLS]\nBig White Debug Light Switched\n\n[FED_SPR]\nShow Ped Road Groups\n\n[FED_SCR]\nShow Car Road Grups\n\n[FED_SCZ]\nShow Cull Zones\n\n[FED_DSR]\nDebug Streaming Requests\n\n[FED_SCP]\ngbShowCollisionPolys\n\n[PL_STAT]\nPlayer stats\n\n[PE_WAST]\nPeople you've wasted\n\n[PE_WSOT]\nPeople wasted by others\n\n[TM_BUST]\nTimes busted\n\n[GNG_WST]\nGang members wasted\n\n[DED_CRI]\nCriminals wasted\n\n[PER_COM]\nPercentage completed\n\n[KGS_EXP]\nKgs of explosives used\n\n[ACCURA]\nAccuracy\n\n[ST_WEAP]\nWeapon Budget\n\n[ST_PROP]\nProperty Budget\n\n[ST_AUTO]\nAuto Repair and Painting Budget\n\n[ST_PHOT]\nPhotographs Taken\n\n[ST_LOAN]\nVisits From Loan Sharks\n\n[ST_STOR]\nStores Knocked Off\n\n[ST_MOVI]\nMovie Stunts\n\n[ST_PIZZ]\nPizza's Delivered\n\n[ST_GARB]\nGarbage Pickups Made\n\n[TOP_SHO]\nTop Shooting Range Score\n\n[SHO_RAN]\nShooting Range Rank\n\n[SEAGULL]\nSeagulls Sniped\n\n[PROPOWN]\nProperty Owned\n\n[ST_TIME]\nPlaying Time\n\n[ST_FTIM]\nFlight hours\n\n[ST_PRAN]\nPilot Ranking\n\n[ST_RAN0]\nLearner\n\n[ST_RAN1]\nNavigator\n\n[ST_RAN2]\nCo Pilot\n\n[ST_RAN3]\nJunior\n\n[ST_RAN4]\nCompetent\n\n[ST_RAN5]\nSenior\n\n[ST_RAN6]\nAce\n\n[ST_RAN7]\nRed baron\n\n[ST_DRWN]\nFishes Fed\n\n[ST_FASH]\nFashion Budget\n\n[ST_DAMA]\nProperty Destroyed\n\n[TM_DED]\nHospital visits\n\n[DAYSPS]\nDays passed in game\n\n[NUMSHV]\nSafehouse visits\n\n[MXCARD]\nMax. INSANE Jump dist. (ft)\n\n[MXCARJ]\nMax. INSANE Jump height (ft)\n\n[MXCARDM]\nMax. INSANE Jump dist. (m)\n\n[MXCARJM]\nMax. INSANE Jump height (m)\n\n[MXFLIP]\nMax. INSANE Jump flips\n\n[MXJUMP]\nMax. INSANE Jump rotation\n\n[BUL_FIR]\nBullets fired\n\n[BUL_HIT]\nBullets that hit\n\n[SPRAYIN]\nSprayings\n\n[BSTSTU]\nBest INSANE stunt so far\n\n[INSTUN]\nInsane stunt\n\n[PRINST]\nPerfect insane stunt\n\n[DBINST]\nDouble insane stunt\n\n[DBPINS]\nPerfect double insane stunt\n\n[TRINST]\nTriple insane stunt\n\n[PRTRST]\nPerfect triple insane stunt\n\n[QUINST]\nQuadruple insane stunt\n\n[PQUINS]\nPerfect quadruple insane stunt\n\n[NOSTUC]\nNo INSANE stunts completed\n\n[NOUNIF]\nUnique Jumps completed\n\n[NMISON]\nMission attempts\n\n[PASDRO]\nPassengers dropped off\n\n[MONTAX]\nCash made in taxi\n\n[DAYPLC]\nDaily police spending\n\n[CRIMRA]\nCriminal rating:\n\n[STPR_1]\nThe Malibu\n\n[STPR_2]\nPrint Works\n\n[STPR_3]\nFilm Studio\n\n[STPR_4]\nIce Cream Factory\n\n[STPR_5]\nCar Showroom\n\n[STPR_6]\nTaxi Company\n\n[STPR_7]\nBoatyard\n\n[SET1EN]\nSetUp 1. Enabled\n\n[GMSAVE]\nSave Game\n\n[FEDS_TB]\nBack\n\n[FEST_OO]\nout of\n\n[FEC_TUC]\nTurret control\n\n[FEC_RS3]\nRadio station cycle (L3 button)\n\n[FEC_HO3]\nHorn (L3 button)\n\n[C_FAIL]\nVigilante mission ended!\n\n[C_ESCP]\n~r~The suspect has escaped!\n\n[C_VIGIL]\nVIGILANTE BONUS!!\n\n[HEAL_A]\nYour ~h~health~w~ is displayed in orange in the top right of the screen.\n\n[WRONGCD]\nIncorrect disc. Please insert correct disc.\n\n[NOCD]\nThe disc tray is empty. Please insert disc.\n\n[OPENCD]\nThe disc tray is open. Please close the disc tray.\n\n[CDERROR]\nError reading the Grand Theft Auto: Vice City DVD\n\n[RESTART]\nStarting new game\n\n[GA_3]\nNo more freebies. $100 to respray!\n\n[GA_1]\nWhoa! I don't touch nothing THAT hot!\n\n[GA_1A]\nCome back when you're not so busy...\n\n[HELP9_C]\nPress the~h~ ~k~~PED_FIREWEAPON~ ~w~button to ~h~fire~w~ the sniper rifle.\n\n[TAXI2]\n~r~You're out of time!\n\n[PAGEB13]\nHealth delivered to hideout\n\n[PAGEB14]\nAdrenaline delivered to hideout\n\n[FESZ_CA]\nCancel\n\n[FES_NGA]\nNew Game\n\n[FES_CAN]\nCancel\n\n[FESZ_QL]\nAll unsaved progress in your current game will be lost. Proceed with loading?\n\n[FESZ_QD]\nProceed with deleting this save game?\n\n[FESZ_QO]\nProceed with overwriting this save game?\n\n[T4X4_1]\n'PCJ Playground'\n\n[BMX_1]\n'Trial by Dirt'\n\n[BMX_2]\n'Test Track'\n\n[BMXFAIL]\n~r~You failed to set a new record!\n\n[BMX_REC]\n~g~New Record Set:~1~ !!\n\n[T4X4_3]\n'GRIPPED!'\n\n[MM_1]\n'CONE CRAZY'\n\n[T4X4_F]\n~r~You bailed! Too tough for you?!\n\n[LANDSTK]\nLandstalker\n\n[IDAHO]\nIdaho\n\n[STINGER]\nStinger\n\n[LINERUN]\nLinerunner\n\n[PEREN]\nPerennial\n\n[SENTINL]\nSentinel\n\n[RIO]\nRio\n\n[PATRIOT]\nPatriot\n\n[FIRETRK]\nFiretruck\n\n[TRASHM]\nTrashmaster\n\n[STRETCH]\nStretch\n\n[MANANA]\nManana\n\n[INFERNS]\nInfernus\n\n[VOODOO]\nVoodoo\n\n[PONY]\nPony\n\n[MULE]\nMule\n\n[CHEETAH]\nCheetah\n\n[AMBULAN]\nAmbulance\n\n[FBICAR]\nFBI Washington\n\n[MOONBM]\nMoonbeam\n\n[ESPERAN]\nEsperanto\n\n[TAXI]\nTaxi\n\n[WASHING]\nWashington\n\n[BOBCAT]\nBobcat\n\n[WHOOPEE]\nMr. Whoopee\n\n[BFINJC]\nBF Injection\n\n[HUNTER]\nHunter\n\n[POLICAR]\nPolice\n\n[ENFORCR]\nEnforcer\n\n[SECURI]\nSecuricar\n\n[BANSHEE]\nBanshee\n\n[PREDATR]\nPredator\n\n[BUS]\nBus\n\n[RHINO]\nRhino\n\n[BARRCKS]\nBarracks OL\n\n[CUBAN]\nCuban Hermes\n\n[HELI]\nHelicopter\n\n[DODO]\nDodo\n\n[COACH]\nCoach\n\n[CABBIE]\nCabbie\n\n[STALION]\nStallion\n\n[RUMPO]\nRumpo\n\n[RCBANDT]\nRC Bandit\n\n[ROMERO]\nRomero's Hearse\n\n[PACKER]\nPacker\n\n[ADMIRAL]\nAdmiral\n\n[SQUALO]\nSqualo\n\n[SEASPAR]\nSea Sparrow\n\n[PIZZABO]\nPizza Boy\n\n[GANGBUR]\nGang Burrito\n\n[TROPIC]\nTropic\n\n[SPEEDER]\nSpeeder\n\n[REEFER]\nReefer\n\n[FLATBED]\nFlatbed\n\n[YANKEE]\nYankee\n\n[CADDY]\nCaddy\n\n[ZEBRA]\nZebra Cab\n\n[TOPFUN]\nTop Fun\n\n[SKIMMER]\nSkimmer\n\n[PCJ600]\nPCJ 600\n\n[PHOENIX]\nPhoenix\n\n[FAGGIO]\nFaggio\n\n[FREEWAY]\nFreeway\n\n[RCBARON]\nRC Baron\n\n[RCRAIDE]\nRC Raider\n\n[GLENDAL]\nGlendale\n\n[OCEANIC]\nOceanic\n\n[SANCHEZ]\nSanchez\n\n[SPARROW]\nSparrow\n\n[LOVEFIS]\nLove Fist\n\n[COASTG]\nCoast Guard\n\n[DINGHY]\nDinghy\n\n[HERMES]\nHermes\n\n[SABRE]\nSabre\n\n[SABRETU]\nSabre Turbo\n\n[WALTON]\nWalton\n\n[REGINA]\nRegina\n\n[COMET]\nComet\n\n[DELUXO]\nDeluxo\n\n[BURRITO]\nBurrito\n\n[SPAND]\nSpand Express\n\n[MARQUIS]\nMarquis\n\n[BAGGAGE]\nBaggage Handler\n\n[KAUFMAN]\nKaufman Cab\n\n[COASTMA]\nCoastguard Maverick\n\n[MAVERIC]\nMaverick\n\n[RANCHER]\nRancher\n\n[FBIRANC]\nFBI Rancher\n\n[VIRGO]\nVirgo\n\n[GREENWO]\nGreenwood\n\n[HOTRING]\nHotring Racer\n\n[BLISTAC]\nBlista Compact\n\n[FEST_DF]\nDist. traveled on foot (miles)\n\n[FEST_DC]\nDist. traveled by car (miles)\n\n[FESTDFM]\nDistance traveled on foot (m)\n\n[FESTDCM]\nDistance traveled by car (m)\n\n[TOT_DIS]\nTotal distance traveled (miles)\n\n[TOTDISM]\nTotal distance traveled (m)\n\n[DISTHEL]\nDist. traveled by helicopter (miles)\n\n[DISTHEM]\nDistance traveled by helicopter (m)\n\n[DISTBOA]\nDist. traveled by boat (miles)\n\n[DISTBOM]\nDistance traveled by boat (m)\n\n[FEST_LS]\nPeople saved in an Ambulance\n\n[FEST_CC]\nCriminals killed on Vigilante Mission\n\n[FEST_FE]\nTotal fires extinguished\n\n[FEST_RP]\nRampages passed\n\n[FEST_MP]\nMissions passed\n\n[FEST_BB]\nBling-bling Scramble:\n\n[FEST_H0]\nMost checkpoints\n\n[FEST_GC]\nGang Cars Totaled:\n\n[FEST_H1]\nDiablo destruction\n\n[FEST_H2]\nMafia Massacre\n\n[FEST_H3]\nCasino Calamity\n\n[FEST_H4]\nRumpo Wrecker\n\n[USJ]\nUNIQUE STUNT BONUS!\n\n[RATNG1]\nUpstanding Citizen\n\n[RATNG2]\nNobody Special\n\n[RATNG3]\nLitterer\n\n[RATNG4]\nShoplifter\n\n[RATNG5]\nVandal\n\n[RATNG6]\nDo boy\n\n[RATNG7]\nPickpocket\n\n[RATNG8]\nClepto\n\n[RATNG9]\nSnitch\n\n[RATNG10]\nRat\n\n[RATNG11]\nLeece\n\n[RATNG12]\nScam Artist\n\n[RATNG13]\nTrickster\n\n[RATNG14]\nNumbers Runner\n\n[RATNG15]\nHustler\n\n[RATNG16]\nBully\n\n[RATNG17]\nRiff-Raff\n\n[RATNG18]\nScalawag\n\n[RATNG19]\nRuffian\n\n[RATNG20]\nOutlaw\n\n[RATNG21]\nThug\n\n[RATNG22]\nDrop Man\n\n[RATNG23]\nSA Goon\n\n[RATNG24]\nGoon\n\n[RATNG25]\nJailbird\n\n[RATNG26]\nEx-Con\n\n[RATNG27]\nFelon\n\n[RATNG28]\nBag Man\n\n[RATNG29]\nWiseguy\n\n[RATNG30]\nWheelman\n\n[RATNG31]\nHired Muscle\n\n[RATNG32]\nHatchetman\n\n[RATNG33]\nHeadhunter\n\n[RATNG34]\nEnforcer\n\n[RATNG35]\nRonin\n\n[RATNG36]\nFixer\n\n[RATNG37]\nHitman\n\n[RATNG38]\nAssociate\n\n[RATNG39]\nButcher\n\n[RATNG40]\nCleaner\n\n[RATNG41]\nAssassin\n\n[RATNG42]\nConsigliere\n\n[RATNG43]\nMade Man\n\n[RATNG44]\nRight-Hand Man\n\n[RATNG45]\nExecutioner\n\n[RATNG46]\nLieutenant\n\n[RATNG47]\nUnderboss\n\n[RATNG48]\nCapo\n\n[RATNG49]\nBoss\n\n[RATNG50]\nKingpin\n\n[RATNG51]\nDon\n\n[RATNG52]\nGodfather\n\n[PAGE_00]\n.\n\n[WELCOME]\nWELCOME TO\n\n[TSCORE]\nEARNINGS: $~1~\n\n[PBOAT_2] { reVC update }\nPress the ~h~~k~~VEHICLE_FIREWEAPON~ ~w~button to fire the boat cannons.\n\n[HJSTAT]\nDistance: ~1~.~1~m Height: ~1~.~1~m Flips: ~1~ Rotation: ~1~_\n\n[HJSTATW]\nDistance: ~1~.~1~m Height: ~1~.~1~m Flips: ~1~ Rotation: ~1~_ And what a great landing!\n\n[ATUTOR]\nPress the ~h~~k~~TOGGLE_SUBMISSIONS~ ~w~button to toggle Paramedic missions on or off.\n\n[FEST_HA]\nHighest Paramedic Mission level\n\n[C_KILLS]\nCRIMINALS KILLED: ~1~\n\n[HJSTATF]\nDistance: ~1~ft Height: ~1~ft Flips: ~1~ Rotation: ~1~_\n\n[HJSTAWF]\nDistance: ~1~ft Height: ~1~ft Flips: ~1~ Rotation: ~1~_ And what a great landing!\n\n[CINCAM]\nCinematic Camera\n\n[RC4]\n'RUMPO RAMPAGE'\n\n[LEGAL]\n~g~Eliminate the criminal threat!\n\n[GA_2]\nNew engine and paint job. The cops won't recognize you!\n\n[HELP15]\nWhen on foot press the ~h~~k~~PED_LOOKBEHIND~ ~w~button to ~h~look behind~w~.\n\n[FEC_LB4]\nLook behind (R3 button)\n\n[PERPIC]\nHidden Packages found\n\n[CO_ONE]\nHidden Package ~1~ of ~1~\n\n[GA_21]\nYou cannot store any more cars in this garage.\n\n[CHEAT1]\nCheat activated\n\n[CHEAT2]\nWeapon cheat\n\n[CHEAT3]\nHealth cheat\n\n[CHEAT4]\nArmor cheat\n\n[CHEAT5]\nWanted level cheat\n\n[CHEAT6]\nMoney cheat\n\n[CHEAT7]\nWeather cheat\n\n[USJ_ALL]\nALL UNIQUE STUNTS COMPLETED!\n\n[JAN]\nJan\n\n[FEB]\nFeb\n\n[MAR]\nMar\n\n[APR]\nApr\n\n[MAY]\nMay\n\n[JUN]\nJun\n\n[JUL]\nJul\n\n[AUG]\nAug\n\n[SEP]\nSept\n\n[OCT]\nOct\n\n[NOV]\nNov\n\n[DEC]\nDec\n\n[DEFDT]\n--:---:---- --:--:--\n\n[BONUS]\n~g~BONUS $~1~\n\n[HORN1]\nPress the ~h~~k~~VEHICLE_HORN~ ~w~button to activate the ~h~horn.\n\n[HORN2]\nPress the ~h~~k~~VEHICLE_HORN~ ~w~button to activate the ~h~horn\n\n[HORN3]\nPress the ~h~~k~~VEHICLE_HORN~ ~w~button to activate the ~h~horn\n\n[FEC_EXV]\nEnter and exit vehicle\n\n[TAXI_M]\n'TAXI DRIVER'\n\n[COP_M]\n'VIGILANTE'\n\n[FIRE_M]\n'FIREFIGHTER'\n\n[AMBUL_M]\n'PARAMEDIC'\n\n[HJ_IS]\nINSANE STUNT BONUS: $~1~\n\n[HJ_PIS]\nPERFECT INSANE STUNT BONUS: $~1~\n\n[HJ_DIS]\nDOUBLE INSANE STUNT BONUS: $~1~\n\n[HJ_PDIS]\nPERFECT DOUBLE INSANE STUNT BONUS: $~1~\n\n[HJ_TIS]\nTRIPLE INSANE STUNT BONUS: $~1~\n\n[HJ_PTIS]\nPERFECT TRIPLE INSANE STUNT BONUS: $~1~\n\n[HJ_QIS]\nQUADRUPLE INSANE STUNT BONUS: $~1~\n\n[HJ_PQIS]\nPERFECT QUADRUPLE INSANE STUNT BONUS: $~1~\n\n[FESZ_LS]\nLoad Successful.\n\n[HELI_1A]\nTest your skills with the Sparrow, see how quickly you can complete the course.\n\n[HELI_1B]\nCourse Complete! $ ~1~\n\n[HELIODD]\nHelicopter odd jobs\n\n[LAW]\nTHE LAWYER MISSIONS\n\n[LAW1_1]\n~g~Go get some new threads from Rafael's clothes shop.\n\n[LAW4_6]\nBurn the management!\n\n[LAW4_7]\nKill the bosses!\n\n[LAW4_8]\nFight, Fight, Fight, Fight.\n\n[LAW4_9]\nMore Holiday, Less Work!\n\n[LAW4_11]\nFight! Fight! Fight! Fight!\n\n[LAW4_12]\nViva la revolution!\n\n[GENERAL]\nTHE COLONEL MISSIONS\n\n[GEN3_4]\nTommy Vercetti. Let's go...\n\n[GEN3_13]\nWhat's the matter with you man?! Get on the roof across the yard before they turn up!\n\n[GEN3_17]\nSheeit! You trying to kill me?!\n\n[GEN3_21]\n~g~He got Diaz's money! Chase him down and get it back!\n\n[GEN3_24]\n~r~Diaz died! You failed to protect him!\n\n[GEN3_26]\n~r~You shot Diaz!\n\n[GEN3_27]\n~r~You shot Diaz's bodyguards!\n\n[GEN3_31]\n~g~Now go to the drop off and watch over Diaz.\n\n[GEN3_32]\n~g~Get to your vantage point on the roof of the building opposite Lance.\n\n[COKE]\nTHE COKE BARON MISSIONS\n\n[COK1_3]\nHope you fall and break your neck!\n\n[COK1_6]\nI'm sick of these pricks.\n\n[COK2_7]\nSee those marker boys? Try taking out the lights!\n\n[COK2_10]\nYou sure is better at shooting than talking.\n\n[COK2_11]\nThanks. You're a real charmer yourself.\n\n[COK2_12]\nI Know, Tommy.\n\n[COK2_18]\nYou cool with Kenny Loggins\n\n[COK2_19]\nHell, I love this record\n\n[COK2_26]\n~r~You killed Lance!\n\n[COK3_1]\nDon't shoot, dude!\n\n[COK3_2]\nWhat's in this stuff?\n\n[COK3_3]\nHe's taking the boat. Bummer.\n\n[COK3_4]\nHelp! Some square's stealing the boat, man!\n\n[COK4_W]\nUugghh! That's the last of them.\n\n[COK4_X]\nI'm going to start her up.\n\n[COK4_Y]\nI think we've got some new friends.\n\n[COK4_2]\nYeah.\n\n[COK4_6]\nDo you know where we're going?\n\n[COK4_7]\nAre we lost?\n\n[COK4_8]\nWe got some competition!\n\n[COK4_9]\nTake 'em out!\n\n[COK4_9A]\nIt's time for the Lance Vance Dance!\n\n[COK4_10]\nThey're matchwood! And fish food.\n\n[COK4_11]\nWe made it! Those other boats ain't VIP class.\n\n[COK4_17]\nThey're getting desperate!\n\n[COK4_18]\nMy damn feet are wet! WE'RE TAKING ON WATER!\n\n[COK4_21]\nBridge coming up!\n\n[COK4_22]\nBail out, she's about to blow!\n\n[COK4_23]\nGood shooting.\n\n[COK4_29]\n~r~You killed Lance!\n\n[ASS1_6]\nGo on Tommy, I'll be ok!\n\n[ASS1_7]\nEat this, you murdering bastards!!\n\n[ASS1_8]\nI'm pinned down!\n\n[ASS1_9]\nI got you covered Tommy!\n\n[ASS1_10]\nHey, this is a real nice herbaceous border\n\n[ASS1_11]\nHey Tommy, can my room have a view of the bay?\n\n[ASS1_12]\nBeautiful high ceilings in here...\n\n[ASS1_3]\nLance! I need cover!\n\n[ASS1_4]\nDiaz must be inside!\n\n[ASS1_5]\nLance!\n\n[TAXWAR]\nTAXI WAR MISSIONS\n\n[NOTAXI]\n~g~You need a Kaufman Cab to activate this mission.\n\n[TAXW1_5]\n~g~You need to be in a Kaufman cab!\n\n[TAX2_4]\nGo on, Tommy.\n\n[TAX2_5]\nBeat the hell out of him.\n\n[TAX2_6]\nHe hasn't even got a license.\n\n[TAX2_7]\nDamn limo services.\n\n[TAXW3_1]\n~g~Go and pick up Mercedes.\n\n[RACE1]\n~g~3..2..1.. GO GO GO!\n\n[RACE2]\n~g~3\n\n[RACE3]\n~g~2\n\n[RACE4]\n~g~1\n\n[RACE5]\n~g~GO!\n\n[FIRST]\n~b~1st\n\n[SECOND]\n~b~2nd\n\n[THIRD]\n~b~3rd\n\n[FOURTH]\n~b~4th\n\n[RACETM]\n~b~RACE TIME: ~1~:~1~\n\n[RACETM2]\n~b~RACE TIME: ~1~:0~1~\n\n[RACEFA]\n~r~You failed to win the race!\n\n[TEX1_5]\n~r~He got away!\n\n[SEG3_2]\n~g~Get to the van that contains the RC Raider and remote timed bombs.\n\n[SEG3_3]\n~g~You must use the RC RAIDER to transport 4 bombs to 4 target zones on the building site.\n\n[SERG3_5]\n~g~You can only carry one bomb at a time and cannot pick up successfully planted bombs.\n\n[SEG3_7]\n~g~Once you have dropped the FIRST bomb successfully in a target zone the detonation timer will start; you must then drop all the bombs within this time period.\n\n[SEG3_8]\n~g~All 4 bombs must be located at the 4 target zones to pass the mission and demolish the building.\n\n[SEG3_9]\n~g~You hit the target! 3 more to go.\n\n[SEG3_10]\n~g~You hit the target! 2 more to go.\n\n[SEG3_11]\n~g~You hit the target! Just 1 more to go!\n\n[SEG3_12]\n~r~You missed the target! Go get a bomb!\n\n[SEG3_13]\n~g~Drop the bomb at a target zone.\n\n[SEG3_14]\n~r~You ran out of time and failed to demolish the building.\n\n[SEG3_15]\n~r~Your RC Raider has been destroyed! How you gonna transport the bombs now?\n\n[AVERY]\nAVERY MISSIONS\n\n[ASM]\nASSASSIN MISSIONS\n\n[ASM_1]\nASSASSIN MISSION 1\n\n[ASM1_1]\n~g~Mr. Teal, your help in eradicating those out-of-towners was invaluable to business. I have more work for you with a more 'hands-on' approach. Your next job is taped under the phone.\n\n[ASM1_2]\n~g~Get to the payphone outside the Mall in Washington.\n\n[ASM1_3]\n~g~Carl Pearson, Pizza Delivery Man. He must not complete his deliveries.\n\n[ASM1_4]\n~g~Kill the Pizza Delivery Man before he completes his deliveries.\n\n[ASM_2]\nASSASSIN MISSION 2\n\n[ASM_3]\nASSASSIN MISSION 3\n\n[ASM3_A]\nTEXT NO LONGER NEEDED\n\n[ASM3_B]\nTEXT NO LONGER NEEDED\n\n[ASM3_1]\n~g~Go and get the weapon Mr. Black has left for you.\n\n[ASM3_2]\n~g~Don't get too close to the target or he may spot you!\n\n[ASM3_3]\n~g~For a quick safe kill find a secluded spot nearby with a clear view of your target.\n\n[ASM3_4]\n~g~He's seen you! Better waste him any way you can!\n\n[ASM3_5]\n~g~Marcus Hammond is working on an advertising board in Washington.\n\n[ASM3_6]\n~g~Franco Carter is working for DBP Security off Ocean Drive.\n\n[ASM3_7]\n~g~Dick Tanner is situated near the Jewelry shop in Vice Point.\n\n[ASM3_8]\n~g~Nick Kong is situated near Washington Beach.\n\n[ASM3_9]\n~g~Stuntman Driver is situated in Washington.\n\n[ASM3_10]\n~r~You failed to kill them all.\n\n[ASM_4]\nASSASSIN MISSION 4\n\n[ASM4_1]\n~g~Go get the rifle left for you in the foliage outside the airport terminal.\n\n[ASM4_2]\n~g~Don't miss your target or you may alert his bodyguards, and remember keep your distance so he does not spot you.\n\n[ASM4_3]\n~g~Watch the woman on the balcony above the check-in desks inside the airport terminal. DO NOT KILL HER.\n\n[ASM4_4]\n~g~Kill the man she hands the briefcase to but only AFTER HE PICKS IT UP. Then retrieve the briefcase and take it to Ammu-Nation in Downtown.\n\n[ASM4_5]\n~g~Get the briefcase!\n\n[ASM4_6]\n~g~Take the briefcase to Ammu-Nation in Downtown.\n\n[ASM4_7]\n~r~You killed the woman, you fool!\n\n[ASM4_8]\n~r~The target heard you firing your weapon! The deal is off!\n\n[ASM4_9]\n~r~The target has boarded his flight!\n\n[ASM4_11]\n~r~The target has seen you! The deal is off!\n\n[ASM4_13]\n~g~He's spotted you and is making a run for it, nail him and get the briefcase!\n\n[ASM4_14]\n~g~The distance bar in the upper right of the screen gives you an indication to how close you are to your target do not let it fill or he will see you.\n\n[ASM_5]\nASSASSIN MISSION 5\n\n[KICK]\nKICKSTART\n\n[KICK1_3]\n~g~Number of times foot put down: ~1~\n\n[KICK1_4]\n~g~Time penalty: ~1~ seconds\n\n[BANK]\nBANKJOB MISSIONS\n\n[BANK1]\nBANKJOB MISSION 1\n\n[BANK2]\nBANKJOB MISSION 2\n\n[BJM2_21]\n~g~Hit as many targets as you can while your ammo lasts.\n\n[BANK3]\nBANKJOB MISSION 3\n\n[BJM3_1]\n~g~Get a fast car and get to the starting grid.\n\n[BNK4_2A]\nBoys at the car lot did a great job on this baby.\n\n[BNK4_3G]\nOh crap, now the cops are onto us!\n\n[BNK4_3H]\n- and we're not even there yet.\n\n[BNK4_3K]\nWe'll have to lose the cops first...\n\n[BNK4_3L]\nChrist Tommy, you trying to kill us all!?\n\n[BNK4_3N]\nEverything I care about gets trashed!\n\n[BNK4_26]\nHot damn! Here they come!\n\n[BNK4_32]\nUse explosives to open the deposit boxes!\n\n[BNK4_36]\nWhere's Cam?\n\n[BNK4_37]\nHistory...\n\n[BNK4_38]\nThat's the last of them. GO! GO! GO!\n\n[BNK_39]\nShit! Where's Hilary?\n\n[BK4_40A]\nI'll give him abandonment issues!\n\n[BNK4_42]\nHey guys! Get in! I got you covered!\n\n[BNK4_43]\nI've got our asses covered, DRIVE!\n\n[BNK4_44]\nWe made it! We're rich! RICH!\n\n[BNK4_45]\nShame Cam didn't make it, he was a good guy!\n\n[BNK4_46]\nYeah. Still... more for us!\n\n[BNK4_47]\nDamned straight! YEEEEHAAAH!\n\n[BNK4_48]\nTommy, would you like a massage?\n\n[BNK4_49]\nWell, Hi there, Mercedes! Yeah, I'm a little tense...\n\n[BNK450A]\nWhat'd I tell you Tommy? What'd I tell you? Bent SWAT better watch out when Kent Paul is in town.\n\n[BNK450B]\nCome on, gimme a bigger slice, mate, c'mon. I gotta get some new threads.\n\n[BNK4_51]\nYou look fine to me.\n\n[KENT]\nKENT PAULS MISSIONS\n\n[KENT1]\nKENT PAUL MISSION1\n\n[COUNT]\nCOUNTERFEITING MISSIONS\n\n[COUNT1]\nCOUNTERFEITING MISSION 1\n\n[COUNT2]\nCOUNTERFEITING MISSION 2\n\n[BIKE]\nTHE BIKER GANG MISSIONS\n\n[BIKE1]\nBIKER MISSION 1\n\n[BIKE2]\nBIKER MISSION 2\n\n[BIKE3]\nBIKER MISSION 3\n\n[GOAWAY1]\n~g~Come back when you have finished the Haitian gang missions.\n\n[HAIT]\nTHE HAITIAN GANG MISSIONS\n\n[HAIT1]\nHAITIAN MISSION 1\n\n[HAIT2]\nHAITIAN MISSION 2\n\n[HAIT3]\nHAITIAN MISSION 3\n\n[HAM3_6]\n~g~Use the sniper rifle I have left to accomplish your task.\n\n[ROCK]\nTHE ROCKBAND GANG MISSIONS\n\n[ROK1_4]\n~g~Ok, I think this is what you were after...\n\n[ROK1_1E]\n~g~It'll cost more than you've got!\n\n[ROK1_1F]\n~g~Come back when you got the money.\n\n[RBM2_6]\n~g~Wow! She's a bloke, stop him!\n\n[ROCK3]\nROCKBAND MISSION 3\n\n[RBM3_5]\n~g~Take Love Fist to the venue.\n\n[CUBANM]\nTHE CUBAN GANG MISSIONS\n\n[CUBAN1]\nCUBAN MISSION 1\n\n[CUBAN2]\nCUBAN MISSION 2\n\n[CUB2_10]\n~r~You are supposed to be killing Haitians, not Cubans.\n\n[CUBAN3]\nCUBAN MISSION 3\n\n[CUBAN4]\nCUBAN MISSION 4\n\n[PROT]\nPROTECTION MISSIONS\n\n[PORN]\nPORN MISSIONS\n\n[PORN1]\nPORN MISSION 1\n\n[POR1_03]\n~r~Candy is dead!\n\n[PORN2]\nPORN MISSION 2\n\n[PORN3]\nPORN MISSION 3\n\n[PORN4]\nPORN MISSION 4\n\n[PHIL]\nPHIL MISSIONS\n\n[PHIL1]\nPHIL MISSION 1\n\n[PHIL2]\nPHIL MISSION 2\n\n[PIZ1_A]\nPIZZA BOY MISSION\n\n[CNTBUY1]\nPrintworks purchased: $~1~\n\n[CARBUY]\nCar Showroom purchased: $~1~\n\n[PORNBUY]\nFilm Studio purchased: $~1~\n\n[ICEBUY]\nIce Cream Factory purchased: $~1~\n\n[TAXIBUY]\nTaxi Firm purchased: $~1~\n\n[BANKBUY]\nThe Malibu purchased: $~1~\n\n[BOATBUY]\nBoatyard purchased: $~1~\n\n[PRNT_NO]\nYou cannot buy the Print Works at this time, come back later.\n\n[CAR_NO]\nYou cannot buy the Car Showroom at this time, come back later.\n\n[PORN_NO]\nYou cannot buy the Film Studio at this time, come back later.\n\n[ICE_NO]\nYou cannot buy the Ice Cream Factory at this time, come back later.\n\n[TAXI_NO]\nYou cannot buy the Taxi Company at this time, come back later.\n\n[BANK_NO]\nYou cannot buy The Malibu at this time, come back later.\n\n[BOAT_NO]\nYou cannot buy the Boatyard at this time, come back later.\n\n[COL2_6]\nFreeze, imperialist American pig!\n\n[COL2_6B]\nZat iz propertay of ze government Francais.\n\n[COL2_6C]\n'And eet over!\n\n[COL3_A]\nThomas I appreciate you coming\n\n[COL3_B]\nForgive me for getting straight to business,\n\n[COL3_C]\nDiaz has asked me to oversee a minor business transaction.\n\n[COL3_D]\nLet's hope it goes better than last time.\n\n[COL3_E]\nWhich is why I thought of you, my friend.\n\n[COL3_F]\nI've dropped some protection at the multistory carpark.\n\n[COL3_G]\nPick it up then go and watch over Diaz's men at the drop off.\n\n[COL4_2]\nDon't know Sir!\n\n[COL4_5]\nSir, Yes Sir!\n\n[COL4_10]\nLets go eat some doughnuts.\n\n[COL4_16]\nSir! Moving vehicle Sir!\n\n[COL4_25]\nVehicle self destruct initiated!\n\n[COL5_6]\nMercedes, that girl will be the death of me.\n\n[COL5_8]\nDamn cockroach!\n\n[COL5_5]\nDie French peegs!\n\n[CNT2_1]\nKill him.\n\n[CNT2_2]\nGet the Plates!\n\n[CNT2_3]\nProtect the courier!\n\n[FINKILL]\nOk boys, kill him!\n\n[FIN_1A]\nCome here you double-crossing piece of shit!\n\n[FIN_1B]\nYou're going down, you back stabbing prick!\n\n[FIN_1C]\nThis is the last dance for lance vance!\n\n[FIN_2B]\nOh you think so!\n\n[FIN_2C]\nI said I had enough of that at school!\n\n[FIN_3]\nNo one to cover your ass now, eh Tommy?\n\n[FIN_4]\nYou're history, Tommy, history\n\n[FIN_5]\nYou picked the wrong side, Lance...\n\n[FIN_6]\nSonny's up with the safe and MY money...\n\n[FIN_10]\nSonny? SONNY! I'm coming for ya!\n\n[FIN_11A]\nYou took fifteen years from me Sonny...\n\n[FIN_11B]\nAnd now I'm gonna make you pay!\n\n[FIN_12A]\nYou still don't get it do you!\n\n[FIN_12B]\nI OWN you, Tommy.\n\n[FIN_12C]\nThose fifteen years were mine to spend!\n\n[FIN_13]\nGet him boys, he never understood a thing.\n\n[RACES_4]\n3\n\n[RACES_5]\n2\n\n[RACES_6]\n1\n\n[RACES_7]\nGO!\n\n[RACES_9]\nTime: ~1~:~1~\n\n[RACES]\nTIME:\n\n[RACES17]\nNew best time: ~1~:~1~\n\n[RACES18]\nYOU HAVE WON: $~1~\n\n[RACES20]\nNew best time: ~1~:0~1~\n\n[RACES21]\nTime: ~1~:0~1~\n\n[RCH1_1]\nNO LONGER NEEDED NO LONGER NEEDED NO LONGER NEEDED NO LONGER NEEDED NO LONGER NEEDED\n\n[RCH1_2]\n~g~The CHECKPOINTS are scattered throughout the airport.\n\n[RCH1_3]\nNO LONGER NEEDED NO LONGER NEEDED NO LONGER NEEDED NO LONGER NEEDED NO LONGER NEEDED\n\n[RCH1_5]\nTime:\n\n[RCRC1_2]\n~g~Get to the starting grid now!\n\n[RCRC1_4]\n~g~3\n\n[RCRC1_5]\n~g~2\n\n[RCRC1_6]\n~g~1\n\n[RCRC1_7]\n~g~GO!\n\n[RCRC1_8]\n~g~Race time: ~1~ seconds\n\n[RCPL1_1]\n~g~Compete in a CHECKPOINT RACE with 3 other RC Baron's\n\n[RCPL1_2]\n~g~You must go through the ~o~CENTRE CORONA ~g~to successfully pass a checkpoint.\n\n[RCPL1_3]\n~g~Get to the starting grid now!\n\n[ICC1_O]\nWhat is wrong with you??\n\n[FEA_2SP]\n2 Speakers\n\n[FEA_4SP]\nMore than 2 speakers\n\n[FEA_EAR]\nHeadphones\n\n[FEA_NAH]\nNO AUDIO HARDWARE\n\n[FET_APP]\nAPPLY\n\n[FES_SKN]\nSKIN NAME\n\n[FES_DAT]\nDATE\n\n[FES_SET]\nUse Skin\n\n[FET_DEF]\nRestore Defaults\n\n[FESZ_QZ]\nAre you sure you want to save this game?\n\n[FES_SCG]\nSave the current game?\n\n[FES_LCG]\nLoad the game and continue playing?\n\n[FEC_FIR]\nFire\n\n[FEC_NWE]\nNext weapon\n\n[FEC_PWE]\nPrevious weapon\n\n[FEC_FOR]\nForward\n\n[FEC_BAC]\nBackwards\n\n[FEC_LEF]\nLeft\n\n[FEC_RIG]\nRight\n\n[FEC_ZIN]\nZoom in\n\n[FEC_ZOT]\nZoom out\n\n[FEC_EEX]\nEnter+exit\n\n[FEC_RAD]\nRadio\n\n[FEC_SUB]\nSub-mission\n\n[FEC_CMR]\nChange camera\n\n[FEC_JMP]\nJump\n\n[FEC_SPN]\nSprint\n\n[FEC_HND]\nHandbrake\n\n[FEC_LOL]\nLook left\n\n[FEC_LOR]\nLook right\n\n[FEC_NTR]\nNext target\n\n[FEC_PTT]\nPrevious target\n\n[FEC_LBA]\nLook behind\n\n[FEC_CEN]\nCenter camera\n\n[FET_CFT]\nON FOOT\n\n[FET_CCR]\nIN CAR\n\n[FET_CAC]\nACTION\n\n[FEC_IBT]\n-\n\n[FEC_MXO]\nMXB1\n\n[FEC_MXT]\nMXB2\n\n[FEC_UNB]\nUNBOUND\n\n[FEC_TFL]\nLook left+Turret L\n\n[FEC_TFR]\nLook right+Turret R\n\n[FEC_MWF]\nMS WHEEL UP\n\n[FEC_MWB]\nMS WHEEL DN\n\n[FEC_ORR]\nor\n\n[FEC_NUS]\nNOT USED\n\n[FEC_LUD]\nLook Up\n\n[FEC_LDU]\nLook Down\n\n[FEC_CMP]\nCOMBO: LOOK L+R\n\n[LAW_1A]\nlaw_1a\n\n[LAW_1B]\nlaw_1b\n\n[LAW_2A]\nlaw_2a\n\n[LAW_2B]\nlaw_2b\n\n[FEH_STA]\nSTATS\n\n[FEH_LOA]\nLOAD\n\n[FEH_CON]\nCONTROLS\n\n[FEH_AUD]\nAUDIO\n\n[FEH_LAN]\nLANGUAGE\n\n[FEH_SGA]\nSTART NEW GAME\n\n[FEO_CON]\nController Setup\n\n[FEO_AUD]\nAudio Setup\n\n[FEO_DIS]\nDisplay Setup\n\n[FEO_LAN]\nLanguage Setup\n\n[FEO_PLA]\nPlayer Setup\n\n[FEA_OUT]\nOutput\n\n[FEA_ST]\nStereo\n\n[FEA_DTS]\nDTS\n\n[FEA_RSS]\nRadio station\n\n[FEA_NON]\nRADIO OFF\n\n[FEA_FM0]\nWILDSTYLE\n\n[FEA_FM1]\nFLASH FM\n\n[FEA_FM2]\nKCHAT\n\n[FEA_FM3]\nFEVER 105\n\n[FEA_FM4]\nVROCK\n\n[FEA_FM5]\nVCPR\n\n[FEA_FM7]\nEMOTION 98.3\n\n[FEA_FM8]\nWAVE 103\n\n[FED_BRI]\nBrightness\n\n[FED_TRA]\nTrails\n\n[FED_SUB]\nSubtitles\n\n[FED_WIS]\nWide Screen\n\n[FED_POS]\nScreen Position\n\n[FEP_RES]\nResume\n\n[FEP_STG]\nStart Game\n\n[FEP_STA]\nStats\n\n[FEP_BRI]\nBriefs\n\n[FEP_OPT]\nOptions\n\n[FEP_QUI]\nQuit Game\n\n[FES_LOA]\nLoad game\n\n[FES_DEL]\nDelete game\n\n[FEC_CSU]\nController Setup\n\n[FEC_RED]\nRedefine Controls\n\n[FEC_MOU]\nMouse Settings\n\n[DISTGOL]\nDist. traveled by golf cart (miles)\n\n[DISTGOM]\nDistance traveled by golf cart (m)\n\n[ST_FAVR]\nFavorite radio station\n\n[ST_WSTR]\nleast favorite radio station\n\n[ST_FAVV]\nFavorite vehicle\n\n[ST_STAR]\nTotal number of wanted stars attained\n\n[ST_HEAD]\nNumber of headshots\n\n[ST_GANG]\nLeast favorite gang\n\n[ST_STGN]\nTotal number of wanted stars evaded\n\n[TYREPOP]\nTires popped with gunfire\n\n[TYRESLA]\nTires slashed with a blade\n\n[ST_BRK]\nNumber of bloodring kills\n\n[ST_LTBR]\nLongest time in bloodring (secs)\n\n[ST_GNG1]\nCubans\n\n[ST_GNG2]\nHaitians\n\n[ST_GNG3]\nStreetwannabe's\n\n[ST_GNG4]\nDiaz's gang\n\n[ST_GNG5]\nSecurity guards\n\n[ST_GNG6]\nBiker gang\n\n[ST_GNG7]\nVercetti gang\n\n[ST_GNG8]\nGolfers\n\n[FEA_FM6]\nESPANTOSO\n\n[ST_ASSI]\nAssassination Contracts Completed\n\n[DISTBIK]\nDist. traveled by bike (miles)\n\n[DISTBIM]\nDistance traveled by bike (m)\n\n[HOTEL]\nOcean View\n\n[KICK1_9]\nCHECKPOINTS:\n\n[FIN_B6]\nYou do not have enough money to start this mission.\n\n[TEX3_9]\n~g~Pickup a bomb by maneuvering the RC helicopter next to it.\n\n[HELP22]\nGo to the green house blip on the radar.\n\n[FES_FMS]\nFormat Successful. Select OK to continue.\n\n[FES_SSC]\nSave Successful. Select OK to continue.\n\n[FES_DSC]\nDelete Successful. Select OK to continue.\n\n[FESZ_QC]\nProceed with overwriting this corrupted save game?\n\n[FES_CHE]\nWarning! One or more cheats have been activated. This may affect your save game. It is recommended that you do not save this game.\n\n[FET_SG]\nSAVE GAME\n\n[FEH_BRI]\nBRIEF\n\n[FEH_DIS]\nDISPLAY\n\n[FEH_MAP]\nMAP\n\n[FEM_OK]\nOK\n\n[FEC_CRO]\nCrouch\n\n[FEC_CR3]\nCrouch (L3 button)\n\n[FEC_SMT]\nSub-mission\n\n[FEC_SM3]\nSub-mission (R3 button)\n\n[FEC_RSC]\nRadio stations\n\n[ST_PR01]\nFlyboy\n\n[ST_PR02]\nAircraftman\n\n[ST_PR03]\nPilot Officer\n\n[ST_PR04]\nCorporal\n\n[ST_PR05]\nLieutenant\n\n[ST_PR06]\nSergeant\n\n[ST_PR07]\nCaptain\n\n[ST_PR08]\nBiggs\n\n[ST_PR09]\nWedge\n\n[ST_PR10]\nRed Baron\n\n[ST_PR11]\nGoose\n\n[ST_PR12]\nViper\n\n[ST_PR13]\nJester\n\n[ST_PR14]\nChappy\n\n[ST_PR15]\nIceman\n\n[ST_PR16]\nMaverick\n\n[ST_PR17]\nNoops\n\n[ST_PR18]\nAir Chief Marshal\n\n[ST_PR19]\nAce\n\n[FET_LG]\nLOAD GAME\n\n[CAR_EXP]\nRoad Vehicles destroyed\n\n[BOA_EXP]\nBoats destroyed\n\n[HEL_DST]\nPlanes & Helicopters destroyed\n\n[STFT_01]\nFastest time on 'Alloy Wheels Of Steel'\n\n[STFT_02]\nFastest time on 'The Driver'\n\n[STFT_03]\nFastest time in Dirt Ring\n\n[STFT_04]\nFastest time on RC Plane Race\n\n[STFT_05]\nFastest time on RC Car Race\n\n[STFT_06]\nFastest time on RC helicopter Pickup\n\n[STFT_07]\nFastest time on 'Terminal Velocity'\n\n[STFT_08]\nFastest time on 'Ocean Drive'\n\n[STFT_09]\nFastest time on 'Border Run'\n\n[STFT_10]\nFastest time on 'Capital Cruise'\n\n[STFT_11]\nFastest time on 'Tour!'\n\n[STFT_12]\nFastest time on 'V.C. Endurance'\n\n[STHC_01]\nHighest score for Shooter\n\n[STHC_02]\nBest Percentage of hits for Shooter\n\n[STHC_03]\nNumber of drug deals made\n\n[HELP24]\nYou can now take jobs from the Colonel.\n\n[HELP25]\nYou can now take jobs from Avery Carrington.\n\n[HELP29]\nYou can visit the clothes store when you're not on a mission.\n\n[HELP30]\nWhen you buy new clothes your wanted level will be set to zero.\n\n[ASM4_24]\ndistance:\n\n[RBM1_6]\n~g~Take Mercedes and the 'Love Juice' to the band at the recording studio.\n\n[RBM1_3]\nNO LONGER NEEDED\n\n[HAM1_5]\nNO LONGER NEEDED\n\n[RBM1_11]\nNO LONGER NEEDED\n\n[HELP31]\nTo do a drive-by, first look left or right using the ~h~~k~~VEHICLE_LOOKLEFT~~w~ or the ~h~~k~~VEHICLE_LOOKRIGHT~.\n\n[HELP34]\nYou must have a sub machine gun to perform a drive-by.\n\n[STRIP_1]\n~r~Not enough cash, you cheap sleazebag.\n\n[EXIT_1]\nPress the ~h~~k~~PED_SPRINT~ ~w~button to exit.\n\n[ASM1_B]\nYour next job is taped under the phone.\n\n[ASM1_C]\nI have more work for you with a more 'hands-on' approach.\n\n[SCARF]\nApartment 3c\n\n[LAW4_10]\nRich management suck!\n\n[RCH1_6]\n~g~Use the RC Helicopter to collect checkpoints scattered throughout the airport.\n\n[RCH1_9]\n~b~TOTAL TIME: ~1~:~1~\n\n[RCH1_10]\n~b~TOTAL TIME: ~1~:0~1~\n\n[WHEEL01]\nTWO WHEELS DOUBLE BONUS: $ ~1~ Distance: ~1~.~1~m Time: ~1~ seconds\n\n[WHEEL02]\nTWO WHEELS DOUBLE BONUS: $ ~1~ Distance: ~1~ feet Time: ~1~ seconds\n\n[WHEEL03]\nTWO WHEELS BONUS: $ ~1~ Time: ~1~ seconds\n\n[WHEEL04]\nTWO WHEELS BONUS: $ ~1~ Distance: ~1~.~1~m\n\n[WHEEL05]\nTWO WHEELS BONUS: $ ~1~ Distance: ~1~ feet\n\n[WHEEL06]\nWHEELIE BONUS: $ ~1~ Distance: ~1~.~1~m Time: ~1~ seconds\n\n[WHEEL07]\nWHEELIE BONUS: $ ~1~ Distance: ~1~ feet Time: ~1~ seconds\n\n[WHEEL08]\nWHEELIE BONUS: $ ~1~ Time: ~1~ seconds\n\n[WHEEL09]\nWHEELIE BONUS: $ ~1~ Distance: ~1~.~1~m\n\n[WHEEL10]\nWHEELIE BONUS: $ ~1~ Distance: ~1~ feet\n\n[WHEEL11]\nSTOPPIE BONUS: $ ~1~ Distance: ~1~.~1~m Time: ~1~ seconds\n\n[WHEEL12]\nSTOPPIE BONUS: $ ~1~ Distance: ~1~ feet Time: ~1~ seconds\n\n[WHEEL13]\nSTOPPIE BONUS: $ ~1~ Time: ~1~ seconds\n\n[WHEEL14]\nSTOPPIE BONUS: $ ~1~ Distance: ~1~.~1~m\n\n[WHEEL15]\nSTOPPIE BONUS: $ ~1~ Distance: ~1~ feet\n\n[ROK3_72]\nLove Fist!\n\n[POR1_19]\nHey!\n\n[DESPERA]\nDesperado\n\n[MOB_99A]\nGet to the payphone next to the mall in Washington.\n\n[MOB_98A]\nGet to the pay phone in Vice Point.\n\n[MOB_96A]\nGet to the payphone at the airport terminal.\n\n[MOB_95A]\nGet to the payphone in Little Havana.\n\n[BNK1_1]\nCan I help you, sir?\n\n[BNK1_2]\nThere's an imposter!\n\n[BNK1_3]\nHe's gone insane!\n\n[BNK1_4]\nWho the hell are you?\n\n[BNK1_5]\nWhere's your badge?\n\n[BNK1_6]\nThere they are! Shoot to kill!\n\n[MOB_24A]\nHola, is this Mr. Vercetti?\n\n[MOB_24B]\nYeah.\n\n[MOB_24C]\nThis is Cortez. You were at my party.\n\n[MOB_24D]\nYeah. I remember.\n\n[MOB_24E]\nMr. Vercetti, it was a most unfortunate incident that happened with your business deal.\n\n[MOB_24F]\nI know.\n\n[MOB_24G]\nI want you to know me and my people are doing their utmost to get to the bottom of it.\n\n[MOB_24H]\nIf you'd like to talk to me more privately, you can find me at the boat, eh? Okay? Good day, senor.\n\n[BNK2_6]\nThis guy's a lunatic!\n\n[ANGEL]\nAngel\n\n[CUBJET]\nCuban Jetmax\n\n[SANDKIN]\nSandking\n\n[POLMAV]\nPolice Maverick\n\n[BOXVILL]\nBoxville\n\n[BENSON]\nBenson\n\n[HOTRINA]\nHotring Racer\n\n[HOTRINB]\nHotring Racer\n\n[BLOODRA]\nBloodring Banger\n\n[BLOODRB]\nBloodring Banger\n\n[MAFIACR]\nMafia Cruiser\n\n[COP_M2]\n'VICE SQUAD'\n\n[COP_M3]\n'BROWN THUNDER'\n\n[BNK3_2]\nI'm not driving for you, no way, I'm sharing this at group.\n\n[FEM_SL1]\nSave File 1 Not Present\n\n[FEM_SL2]\nSave File 2 Not Present\n\n[FEM_SL3]\nSave File 3 Not Present\n\n[FEM_SL4]\nSave File 4 Not Present\n\n[FEM_SL5]\nSave File 5 Not Present\n\n[FEM_SL6]\nSave File 6 Not Present\n\n[FEM_SL7]\nSave File 7 Not Present\n\n[FEM_SL8]\nSave File 8 Not Present\n\n[FEA_CHA]\nChanging audio output to STEREO. Please wait...\n\n[FEA_CHD]\nWarning! You are changing from STEREO output to DTS. Please wait...\n\n[FEI_SEL]\nSelect\n\n[FEI_BAC]\nBack\n\n[FEI_RES]\nResume\n\n[FEI_NAV]\nNavigate\n\n[FEI_BTX]\n/ button -\n\n[FEI_BTT]\n\" button -\n\n[FEI_STA]\nSTART button -\n\n[FEI_BTD]\n; = > < -\n\n[FEI_STO]\nStop\n\n[ST_ICEC]\n'Ice Cream' Sold\n\n[MOB_68A]\nTommy son, have I got a surprise for you\n\n[MOB_68B]\nI'm down at the recording studios with some major artists\n\n[MOB_68C]\nWhy don't you pay us a visit?\n\n[MOB_68D]\nYou know it makes sense, dontcha? See ya later.\n\n[OUTFT1]\nStreet\n\n[OUTFT2]\nSoiree\n\n[OUTFT3]\nCoveralls\n\n[OUTFT4]\nCountry Club\n\n[OUTFT5]\nHavana\n\n[OUTFT6]\nCop\n\n[OUTFT7]\nBank Job\n\n[OUTFT8]\nCasual\n\n[OUTFT9]\nMr Vercetti\n\n[OUTFT10]\nTracksuit\n\n[OUTFT13]\nMC Tommy\n\n[CAR_AS1]\nCAR SHOWROOM ASSET COMPLETED\n\n[CAR_AS2]\n~g~Sunshine Auto's will now generate revenue up to a maximum of $~1~. Make sure you collect it regularly.\n\n[BUYSAVE]\n~g~You can now save your game here when not on a mission.\n\n[BUYGARG]\n~g~You can also store vehicles in this garage.\n\n[STRPBUY]\nPole Position Club purchased: $~1~\n\n[GA_4]\nCar bombs are $500 each\n\n[GA_5]\nYour car is already fitted with a bomb.\n\n[GA_6] { reVC update }\nPark it, prime it by pressing the ~h~~k~~VEHICLE_FIREWEAPON~ ~w~button and LEG IT!\n\n[GA_7] { reVC update }\nArm with the ~h~~k~~VEHICLE_FIREWEAPON~ ~w~button. Bomb will go off when engine is started.\n\n[GA_6B] { reVC update }\nPark it, prime it by pressing the ~h~~k~~VEHICLE_FIREWEAPON~ ~w~button and LEG IT!\n\n[GA_7B] { reVC update }\nArm with the ~h~~k~~VEHICLE_FIREWEAPON~ ~w~button. Bomb will go off when engine is started.\n\n[MOB_70A]\nTommy, it's me, Colonel Cortez. Look senor, I believe you are a man who can get things done. So please help me.\n\n[MOB_70B]\nYou can find me at the boat.\n\n[PICK2]\n.357 delivered to Ocean View Hotel!\n\n[PICK3]\nChainsaw delivered to Ocean View Hotel!\n\n[PICK4]\nFlame Thrower delivered to Ocean View Hotel!\n\n[PICK5]\n.308 Sniper delivered to Ocean View Hotel!\n\n[PICK6]\nMinigun delivered to Ocean View Hotel!\n\n[PICK7]\nRocket Launcher delivered to Ocean View Hotel!\n\n[PICK8]\nSea Sparrow now available from the Mansion on Starfish Island!\n\n[PICK9]\nTank now available from the Army Barracks!\n\n[PICK10]\nHunter now available from the Army Barracks!\n\n[CLOTH1]\nSoiree outfit delivered to Rafael's on Ocean Beach.\n\n[CLOTH2]\nStreet outfit delivered to Safehouses.\n\n[CLOTH3]\nCoveralls outfit delivered to Tooled Up in The North Point Mall.\n\n[CLOTH4]\nCountry Club outfit delivered to The Golf Club in Leaf Links.\n\n[CLOTH5]\nHavana outfit delivered to Little Havana Streetwear in Little Havana.\n\n[CLOTH6]\nCop outfit delivered to Police Station on Washington Beach.\n\n[CLOTH7]\nCasual outfit delivered to Gash in The North Point Mall.\n\n[CLOTH8]\nMr Vercetti outfit delivered to Collar & Cuffs on Ocean Beach.\n\n[CLOTH9]\nTracksuit outfit delivered to Jocksport in Downtown.\n\n[CLOTH10]\nBank Job outfit delivered to Malibu Club in Vice Point.\n\n[MOB_62A]\nTommy, is Ricardo Diaz, I want to thank you for looking out for me my man.\n\n[MOB_62B]\nI ask that prick Cortez, he say you the real deal, my friend, why you not come see me.\n\n[MOB_62C]\nI need a guy like you. All I have now is dickheads,\n\n[MOB_62D]\ndickheads everywhere, yo. I make you real rich.\n\n[GOAWAY2]\n~g~Come back when you have finished the Biker gang missions.\n\n[COL2_9]\nYou American idiot! They followed you here!\n\n[LOADCOL]\nLoading...\n\n[STFT_17]\nFastest time on 'PCJ Playground'\n\n[STFT_18]\nFastest time on 'Trial By Dirt'\n\n[STFT_19]\nFastest time on 'Test Track'\n\n[NEW_REC]\n~g~New Record Set!! ~w~~1~ minutes ~g~and ~w~~1~ seconds.\n\n[BMX_HOW]\n~g~Do two laps of the dirt track, ~y~passing through ~g~the ~y~CHECKPOINTS ~g~as you go!\n\n[BMXREW1]\n~g~Each time you beat your previous record for the two laps\n\n[BMXREW2]\n~g~a larger ~y~REWARD ~g~will be awarded!\n\n[BMXRAIN]\n~g~Looks like rain...\n\n[ITBEG]\nIn the beginning...\n\n[NBMNBUY]\nEl Swanko Casa purchased: $~1~\n\n[LNKVBUY]\nLinks View Apartment purchased: $~1~\n\n[HYCOBUY]\nHyman Condo purchased: $~1~\n\n[BUYGARS]\n~g~You can also store vehicles in these garages.\n\n[OCHEBUY]\nOcean Heights Apartment purchased: $~1~\n\n[WASHBUY]\n1102 Washington Street purchased: $~1~\n\n[VCPTBUY]\n3321 Vice Point purchased: $~1~\n\n[HELP6_C]\nPress the ~h~~k~~VEHICLE_HANDBRAKE~ ~w~button to apply the vehicle's handbrake.\n\n[HELP2_A]\nPress the ~h~~k~~PED_SPRINT~ ~w~button when running to ~h~sprint\n\n[HELP4_A]\nPress the ~h~~k~~VEHICLE_ACCELERATE~ ~w~button to accelerate.\n\n[HELP5_A]\nPress the ~h~~k~~VEHICLE_BRAKE~ ~w~button to brake, or to reverse if the vehicle has stopped.\n\n[HELP8_A]\nPress the~h~ ~k~~PED_SNIPER_ZOOM_IN~ button ~w~to ~h~zoom in ~w~with the rifle and the~h~ ~k~~PED_SNIPER_ZOOM_OUT~ button ~w~to ~h~zoom out ~w~again.\n\n[PBOAT_1] { reVC update }\nPress the ~h~~k~~VEHICLE_FIREWEAPON~ ~w~button to fire the boat cannons.\n\n[SEG3_4] { reVC update }\n~g~You can pick up bombs by simply piloting your RC Raider adjacent to each one, to drop a bomb press the ~h~~k~~VEHICLE_FIREWEAPON~ ~g~button.\n\n[RCR1_3] { reVC update }\n~g~If you wish to quit this mission press the ~h~~k~~VEHICLE_FIREWEAPON~ ~g~button to detonate your RC car.\n\n[HELP32] { reVC update }\nThen fire using the ~h~~k~~VEHICLE_FIREWEAPON~ ~w~button.\n\n[HELP33] { reVC update }\nThen fire using the ~h~~k~~VEHICLE_FIREWEAPON~ ~w~button.\n\n[TTUTOR]\nPress the ~h~~k~~TOGGLE_SUBMISSIONS~ button~w~ to toggle taxi missions on or off.\n\n[TTUTOR2]\nPress the ~h~~k~~TOGGLE_SUBMISSIONS~ button~w~ to toggle taxi missions on or off.\n\n[FTUTOR]\nPress the ~h~~k~~TOGGLE_SUBMISSIONS~ button~w~ to toggle fire truck missions on or off.\n\n[FTUTOR2]\nPress the ~h~~k~~TOGGLE_SUBMISSIONS~ button~w~ to toggle fire truck missions on or off.\n\n[CTUTOR]\nPress the ~h~~k~~TOGGLE_SUBMISSIONS~ button~w~ to toggle Vigilante missions on or off.\n\n[CTUTOR2]\nPress the ~h~~k~~TOGGLE_SUBMISSIONS~ button~w~ to toggle Vigilante missions on or off.\n\n[HELP8_B]\nPress the ~h~~k~~PED_SNIPER_ZOOM_IN~ button ~w~to ~h~zoom in ~w~with the rifle and the~h~ ~k~~PED_SNIPER_ZOOM_OUT~ button ~w~to ~h~zoom out ~w~again.\n\n[ATUTOR3]\nPress the ~h~~k~~TOGGLE_SUBMISSIONS~ button~w~ to toggle Paramedic missions on or off.\n\n[GUN_H1]\n~w~Press the~h~ ~k~~PED_SPRINT~ ~w~button to buy. Press the~h~ ~k~~VEHICLE_ENTER_EXIT~ ~w~button to exit.\n\n[PU_CF3] { reVC update }\nPress the ~h~~k~~PED_ANSWER_PHONE~ ~w~button to replace current weapon in this slot.\n\n[PU_CF4] { reVC update }\nPress the ~h~~k~~PED_ANSWER_PHONE~ ~w~button to replace current weapon in this slot.\n\n[HELP9_B]\nPress the~h~ ~k~~PED_FIREWEAPON~ button ~w~to ~h~fire~w~ the sniper rifle.\n\n[HELP37]\nIf you do not want to enter the vehicle while car jacking someone, press the ~h~~k~~PED_SPRINT~ ~w~button.\n\n[HELP6_A]\nPress the~h~ ~k~~VEHICLE_HANDBRAKE~ button ~w~to apply the vehicle's ~h~handbrake.\n\n[HELP6_D]\nPress the~h~ ~k~~VEHICLE_HANDBRAKE~ button ~w~to apply the vehicle's ~h~handbrake.\n\n[HELP26]\nPress the ~h~~k~~VEHICLE_ENTER_EXIT~ ~w~button to enter or exit a vehicle.\n\n[HELP27]\nPress the ~h~~k~~VEHICLE_TURRETUP~~w~ button and the ~h~~k~~VEHICLE_TURRETDOWN~~w~ button, to shift your weight on a bike.\n\n[HELP28]\nPress the ~h~~k~~VEHICLE_TURRETUP~~w~ button and the ~h~~k~~VEHICLE_TURRETDOWN~~w~ button, to shift your weight on a bike.\n\n[HELP35]\nPress the ~h~~k~~GO_LEFT~~w~, and the ~h~~k~~GO_RIGHT~~w~, to steer the vehicle.\n\n[HELP36]\nPress the ~h~~k~~GO_LEFT~~w~, and the ~h~~k~~GO_RIGHT~~w~, to steer the vehicle.\n\n[HELP42]\nFollow the ~q~pink blip~w~ to find the hotel.\n\n[HELP19]\nWalk into the ~q~pink marker ~w~to continue.\n\n[HELP1]\nStop in the center of the ~q~pink marker.\n\n[HELP12]\nWalk into the center of the ~q~pink marker~w~ to trigger a mission.\n\n[SEG3_6]\n~g~To successfully hit a target zone, you must drop the bomb in the area represented by the ~q~pink marker~w~. You can drop the bombs in any order.\n\n[S_PROMP]\nWhen not on a mission you can save your progress by collecting the ~h~cassette tape pickup.\n\n[HELP16]\nWalk through the front door of the ~h~Ocean View~w~ Hotel to enter the building.\n\n[HELP43]\n~g~Goto the ~h~Ocean View~g~ hotel on Ocean Drive.\n\n[HELI_F1]\n~r~Heli Checkpoint mission cancelled!\n\n[AMMUHLP]\nIf you need any weapons visit ~h~Ammu-Nation~w~. Follow the ~h~Gun blip~w~ on the radar.\n\n[HELI_1]\nDowntown Chopper Checkpoint\n\n[HELI_2]\nOcean Beach Chopper Checkpoint\n\n[HELI_3]\nVice Point Chopper Checkpoint\n\n[HELI_4]\nLittle Haiti Chopper Checkpoint\n\n[FST_MFR]\nMost Favorite Radio Station\n\n[FST_LFR]\nLeast Favorite Radio Station\n\n[FEI_HOL]\nHold\n\n[FEI_ZOO]\nZoom\n\n[FEI_BTR]\n> < -\n\n[FEI_NA]\nN\\A\n\n[MESA]\nMesa Grande\n\n[STRP_NO]\nYou cannot buy the Stripclub at this time, come back later.\n\n[CHSE]\nCHASE\n\n[NBMN_L]\nPress the ~h~~k~~PED_ANSWER_PHONE~ ~w~button to purchase El Swanko Casa for $~1~\n\n[NBMN_T]\nPress the ~h~~k~~PED_ANSWER_PHONE~ ~w~button to purchase El Swanko Casa for $~1~\n\n[NBMN_C]\nPress the ~h~~k~~PED_ANSWER_PHONE~ ~w~button to purchase El Swanko Casa for $~1~\n\n[LNKV_L]\nPress the ~h~~k~~PED_ANSWER_PHONE~ ~w~button to purchase Links View Apartment for $~1~\n\n[LNKV_T]\nPress the ~h~~k~~PED_ANSWER_PHONE~ ~w~button to purchase Links View Apartment for $~1~\n\n[LNKV_C]\nPress the ~h~~k~~PED_ANSWER_PHONE~ ~w~button to purchase Links View Apartment for $~1~\n\n[HYCO_L]\nPress the ~h~~k~~PED_ANSWER_PHONE~ ~w~button to purchase Hyman Condo for $~1~\n\n[HYCO_T]\nPress the ~h~~k~~PED_ANSWER_PHONE~ ~w~button to purchase Hyman Condo for $~1~\n\n[HYCO_C]\nPress the ~h~~k~~PED_ANSWER_PHONE~ ~w~button to purchase Hyman Condo for $~1~\n\n[OCHE_L]\nPress the ~h~~k~~PED_ANSWER_PHONE~ ~w~button to purchase Ocean Heights Apartment for $~1~\n\n[OCHE_T]\nPress the ~h~~k~~PED_ANSWER_PHONE~ ~w~button to purchase Ocean Heights Apartment for $~1~\n\n[OCHE_C]\nPress the ~h~~k~~PED_ANSWER_PHONE~ ~w~button to purchase Ocean Heights Apartment for $~1~\n\n[WASH_L]\nPress the ~h~~k~~PED_ANSWER_PHONE~ ~w~button to purchase 1102 Washington Street for $~1~\n\n[WASH_T]\nPress the ~h~~k~~PED_ANSWER_PHONE~ ~w~button to purchase 1102 Washington Street for $~1~\n\n[WASH_C]\nPress the ~h~~k~~PED_ANSWER_PHONE~ ~w~button to purchase 1102 Washington Street for $~1~\n\n[VCPT_L]\nPress the ~h~~k~~PED_ANSWER_PHONE~ ~w~button to purchase 3321 Vice Point for $~1~\n\n[VCPT_T]\nPress the ~h~~k~~PED_ANSWER_PHONE~ ~w~button to purchase 3321 Vice Point for $~1~\n\n[VCPT_C]\nPress the ~h~~k~~PED_ANSWER_PHONE~ ~w~button to purchase 3321 Vice Point for $~1~\n\n[PRNT_L]\nPress the ~h~~k~~PED_ANSWER_PHONE~ ~w~button to purchase the Print Works for $~1~\n\n[PRNT_T]\nPress the ~h~~k~~PED_ANSWER_PHONE~ ~w~button to purchase the Print Works for $~1~\n\n[PRNT_C]\nPress the ~h~~k~~PED_ANSWER_PHONE~ ~w~button to purchase the Print Works for $~1~\n\n[CAR_L]\nPress the ~h~~k~~PED_ANSWER_PHONE~ ~w~button to purchase the Car Showroom for $~1~\n\n[CAR_T]\nPress the ~h~~k~~PED_ANSWER_PHONE~ ~w~button to purchase the Car Showroom for $~1~\n\n[CAR_C]\nPress the ~h~~k~~PED_ANSWER_PHONE~ ~w~button to purchase the Car Showroom for $~1~\n\n[PORN_L]\nPress the ~h~~k~~PED_ANSWER_PHONE~ ~w~button to purchase the Film Studios for $~1~\n\n[PORN_T]\nPress the ~h~~k~~PED_ANSWER_PHONE~ ~w~button to purchase the Film Studios for $~1~\n\n[PORN_C]\nPress the ~h~~k~~PED_ANSWER_PHONE~ ~w~button to purchase the Film Studios for $~1~\n\n[ICE_L]\nPress the ~h~~k~~PED_ANSWER_PHONE~ ~w~button to purchase the Ice Cream Factory for $~1~\n\n[ICE_T]\nPress the ~h~~k~~PED_ANSWER_PHONE~ ~w~button to purchase the Ice Cream Factory for $~1~\n\n[ICE_C]\nPress the ~h~~k~~PED_ANSWER_PHONE~ ~w~button to purchase the Ice Cream Factory for $~1~\n\n[TAXI_L]\nPress the ~h~~k~~PED_ANSWER_PHONE~ ~w~button to purchase the Taxi Company for $~1~\n\n[TAXI_T]\nPress the ~h~~k~~PED_ANSWER_PHONE~ ~w~button to purchase the Taxi Company for $~1~\n\n[TAXI_C]\nPress the ~h~~k~~PED_ANSWER_PHONE~ ~w~button to purchase the Taxi Company for $~1~\n\n[BANK_L]\nPress the ~h~~k~~PED_ANSWER_PHONE~ ~w~button to purchase The Malibu for $~1~\n\n[BANK_T]\nPress the ~h~~k~~PED_ANSWER_PHONE~ ~w~button to purchase The Malibu for $~1~\n\n[BANK_C]\nPress the ~h~~k~~PED_ANSWER_PHONE~ ~w~button to purchase The Malibu for $~1~\n\n[BOAT_L]\nPress the ~h~~k~~PED_ANSWER_PHONE~ ~w~button to purchase the Boatyard for $~1~\n\n[BOAT_T]\nPress the ~h~~k~~PED_ANSWER_PHONE~ ~w~button to purchase the Boatyard for $~1~\n\n[BOAT_C]\nPress the ~h~~k~~PED_ANSWER_PHONE~ ~w~button to purchase the Boatyard for $~1~\n\n[STRP_L]\nPress the ~h~~k~~PED_ANSWER_PHONE~ ~w~button to purchase the Pole Position Club for $~1~\n\n[STRP_T]\nPress the ~h~~k~~PED_ANSWER_PHONE~ ~w~button to purchase the Pole Position Club for $~1~\n\n[STRP_C]\nPress the ~h~~k~~PED_ANSWER_PHONE~ ~w~button to purchase the Pole Position Club for $~1~\n\n[STOCK]\n~r~out of stock\n\n[HELP14]\nTo find the Lawyer's office, follow the ~h~L blip~w~ on the radar\n\n[RAMPAGE]\nRAMPAGE!!\n\n[RAMP_F]\nRAMPAGE FAILED!!\n\n[RAMP_P]\nRAMPAGE PASSED!!\n\n[RAMP_A]\nALL RAMPAGES COMPLETED!!\n\n[PAGE_01]\nKill ~1~ Gang Members in 2 Minutes!\n\n[PAGE_02]\nDestroy ~1~ Vehicles in 2 Minutes!\n\n[PAGE_03]\nDrive-by and Waste ~1~ Gang Members in 2 Minutes!\n\n[PAGE_04]\nRunover and Kill ~1~ Gang Members in 2 Minutes!\n\n[PAGE_05]\nGun Down ~1~ Gang Members in 2 Minutes!\n\n[SENTXS]\nSentinel XS\n\n[MAP_LEG]\nMap Legend\n\n[VCNMAV]\nVCN Maverick\n\n[LG_01]\nPlayer position\n\n[LG_02]\nAvery Carrington\n\n[LG_03]\nBiker Contact\n\n[LG_04]\nColonel Cortez\n\n[LG_05]\nRicardo Diaz\n\n[LG_06]\nKent Paul\n\n[LG_07]\nLawyer\n\n[LG_08]\nPhil Cassidy\n\n[LG_09]\nBoatyard\n\n[LG_10]\nMalibu Club\n\n[LG_11]\nCubans\n\n[LG_12]\nFilm Studio\n\n[LG_13]\nAmmu-Nation\n\n[LG_14]\nHaitians\n\n[LG_15]\nHardware Store\n\n[LG_16]\nSafe House\n\n[LG_17]\nIce Cream\n\n[LG_18]\nKaufman Cabs\n\n[LG_19]\nLove Fist\n\n[LG_20]\nPrint Works\n\n[LG_21]\nProperty\n\n[LG_22]\nPay 'n' Spray\n\n[LG_23]\nClothes Shop\n\n[LG_24]\nTommy's Mansion\n\n[LG_25]\nTelephone\n\n[LG_26]\nWildstyle Radio Station\n\n[LG_27]\nFlash FM Radio Station\n\n[LG_28]\nKChat Radio Station\n\n[LG_29]\nFever 105 Radio Station\n\n[LG_30]\nVROck Radio Station\n\n[LG_31]\nVCPR Radio Station\n\n[LG_32]\nEspantoso Radio Station\n\n[LG_33]\nEmotion 98.3 Radio Station\n\n[LG_34]\nWave 103 Radio Station\n\n[LG_36]\nSun Yard\n\n[LG_37]\nStrip Club\n\n[MAP_YAH]\nYOU ARE HERE\n\n[TAXSHRT]\n~g~You can use this Kaufman Cab to take you to destinations instead of driving. It will cost you $9.\n\n[MOB_09D]\nMaybe Leo's already dead. Maybe I killed Leo and took his phone - you think of that prick?\n\n[FE_MLG]\nMAP LEGEND\n\n[FED_RDR]\nRADAR MODE\n\n[FED_HUD]\nHUD MODE\n\n[FED_RDB]\nBLIPS ONLY\n\n[FEST_HV]\nHighest Vigilante Mission level\n\n[BRIBE1]\nYou have just picked up a police bribe, this will reduce your wanted level by one star.\n\n[CLOHELP]\nClean Clothes!!\n\n[CRED001]\nROCKSTAR NORTH\n\n[CRD001A]\nSTUDIO DIRECTOR\n\n[CRD001B]\nANDREW SEMPLE\n\n[CRED002]\nPRODUCER\n\n[CRD002A]\nDEVELOPMENT DIRECTOR\n\n[CRED003]\nLESLIE BENZIES\n\n[CRED004]\nART DIRECTOR\n\n[CRED005]\nAARON GARBUT\n\n[CRED006]\nTECHNICAL DIRECTORS\n\n[CRED007]\nOBBE VERMEIJ\n\n[CRED008]\nADAM FOWLER\n\n[CRED010]\nANDREW DUTHIE\n\n[CRED011]\nCRAIG FILSHIE\n\n[CRED012]\nWILLIAM MILLS\n\n[CRED013]\nCHRIS ROTHWELL\n\n[CRD013A]\nIMRAN SARWAR\n\n[CRD013B]\nJAMES WORRALL\n\n[CRD013C]\nJOHN HAIME\n\n[CRED014]\nWRITTEN BY\n\n[CRED015]\nJAMES WORRALL\n\n[CRED016]\nPAUL KUROWSKI\n\n[CRED017]\nDAN HOUSER\n\n[CRED018]\nLEAD CHARACTER DESIGNER\n\n[CRD018A]\nCHARACTER DESIGNER\n\n[CRED019]\nIAN MCQUE\n\n[CRD019A]\nTOKS SOLARIN\n\n[CRD019B]\nALAN DAVIDSON\n\n[CRED020]\nLEAD ANIMATOR\n\n[CRED021]\nALEX HORTON\n\n[CRD022A]\nANIMATORS\n\n[CRED022]\nLEE MONTGOMERY\n\n[CRD022B]\nDUNCAN SHIELDS\n\n[CRD022C]\nGUS BRAID\n\n[CRED023]\nVEHICLE DESIGNERS\n\n[CRD023A]\nJOLYON ORME\n\n[CRD023B]\nALAN DUNCAN\n\n[CRD024A]\nLEAD VEHICLE DESIGNER\n\n[CRED024]\nPAUL KUROWSKI\n\n[CRED025]\nMAP DESIGNERS\n\n[CRED026]\nADAM COCHRANE\n\n[CRED027]\nNIK TAYLOR\n\n[CRED028]\nGARY MCADAM\n\n[CRED029]\nKEIRAN BAILLIE\n\n[CRED030]\nALISDAIR WOOD\n\n[CRED031]\nANDREW SOOSAY\n\n[CRD031A]\nSTEVEN MULHOLLAND\n\n[CRD031B]\nWAYLAND STANDING\n\n[CRD031C]\nCAMPBELL J. DICK\n\n[CRD031D]\nGRAPHIC DESIGNER\n\n[CRD031E]\nSTUART PETRI\n\n[CRED032]\nLEAD PROGRAMMER\n\n[CRD032A]\nPROGRAMMERS\n\n[CRED033]\nALEXANDER ROGER\n\n[CRED034]\nGRAEME WILLIAMSON\n\n[CRED035]\nBARANE CHAN\n\n[CRED036]\nDEREK PAYNE\n\n[CRED037]\nGORDON YEOMAN\n\n[CRD037A]\nALAN CAMPBELL\n\n[CRD037B]\nMARK HANLON\n\n[CRD037C]\nANDRZEJ MADAJCZYK\n\n[CRED038]\nLEAD MUSIC PRODUCER\n\n[CRED039]\nCRAIG CONNER\n\n[CRED040]\nSTUART ROSS\n\n[CRED041]\nLEAD AUDIO ENGINEER\n\n[CRED042]\nALLAN WALKER\n\n[CRD041A]\nAUDIO ENGINEER\n\n[CRD041B]\nAUDIO\n\n[CRD042A]\nWILL MORTON\n\n[CRED043]\nAUDIO PROGRAMMER\n\n[CRED044]\nRAYMOND USHER\n\n[CRED045]\nTEST MANAGER\n\n[CRED046]\nCRAIG ARBUTHNOTT\n\n[CRED047]\nLEAD QA\n\n[CRED048]\nNEIL CORBETT\n\n[CRED049]\nKEVIN WONG\n\n[CRED050]\nQA\n\n[CRED051]\nDAVID BEDDOES\n\n[CRED052]\nDAVID WATSON\n\n[CRED053]\nBARRY CLARK\n\n[CRED054]\nROSS SPARROW\n\n[CRED055]\nJAMES ALLAN\n\n[CRED056]\nNEIL MEIKLE\n\n[CRD056A]\nGEORGE WILLIAMSON\n\n[CRD056B]\nMATT JONES\n\n[CRD056C]\nROB HARBOUR\n\n[CRD056D]\nTOM WHITTAKER\n\n[CRED057]\nLEAD TECHNICAL SUPPORT\n\n[CRED058]\nLORRAINE ROY\n\n[CRD057A]\nTECHNICAL SUPPORT\n\n[CRED059]\nCHRISTINE CHALMERS\n\n[CRD060A]\nOFFICE SUPPORT\n\n[CRD060B]\nKIM GURNEY\n\n[CRD060C]\nCASSIE OLIVER\n\n[CRED060]\nROCKSTAR NEW YORK\n\n[CRED061]\nEXECUTIVE PRODUCER\n\n[CRED062]\nSAM HOUSER\n\n[CRED063]\nPRODUCER\n\n[CRED064]\nDAN HOUSER\n\n[CRED065]\nVP OF DEVELOPMENT\n\n[CRED066]\nJAMIE KING\n\n[CRED067]\nCHIEF TECHNOLOGY OFFICER\n\n[CRED068]\nGARY J. FOREMAN\n\n[CRED069]\nASSOCIATE PRODUCER\n\n[CRED070]\nJEREMY POPE\n\n[CRD071A]\nDIRECTOR OF QUALITY ASSURANCE\n\n[CRD072A]\nJEFF ROSA\n\n[CRED071]\nMUSIC SUPERVISOR\n\n[CRED072]\nTERRY DONOVAN\n\n[CRED073]\nPRODUCTION TEAM\n\n[CRED074]\nTERRY DONOVAN\n\n[CRED075]\nJENNIFER KOLBE\n\n[CRED076]\nJENEFER GROSS\n\n[CRED077]\nLAURA PATERSON\n\n[CRED078]\nJEFF CASTANEDA\n\n[CRED079]\nJERONIMO BARRERA\n\n[CRED080]\nCARLY SLATER\n\n[CRED081]\nJUNG KWAK\n\n[CRED082]\nBRIAN WOOD\n\n[CRED083]\nRENAUD SEBANNE\n\n[CRED084]\nRICHARD KRUGER\n\n[CRD084A]\nDANIEL EINZIG\n\n[CRD084B]\nJACEN BURROWS\n\n[CRD084C]\nLINN PR\n\n[CRD084D]\nCOVER ART\n\n[CRD084E]\nSTEPHEN BLISS\n\n[CRED085]\nKENT PAUL'S 80 NOSTALGIA ZONE\n\n[CRED086]\nWRITTEN BY DAN HOUSER\n\n[CRD086A]\nPRODUCED BY ADAM TEDMAN\n\n[CRED087]\nWWW.KENTPAUL.COM AND WWW.VICECITY.COM\n\n[CRED088]\nCREATED BY\n\n[CRD088A]\nADAM TEDMAN\n\n[CRD088B]\nDAVID YU\n\n[CRD088C]\nJERRY LUNA\n\n[CRD088D]\nSTUART PETRI\n\n[CRD088E]\nMICHAEL CARNEVALE\n\n[CRD088F]\nGREG LAU\n\n[CRD088G]\nFUTABA HAYASHI\n\n[CRED089]\nQA MANAGER\n\n[CRED090]\nCRAIG ARBUTHNOTT\n\n[CRED091]\nLEAD ANALYST\n\n[CRED092]\nADAM DAVIDSON\n\n[CRD092A]\nJOE HOWELL\n\n[CRD092B]\nMARC FERNANDEZ\n\n[CRED093]\nGAME ANALYST\n\n[CRED094]\nRICHARD HUIE\n\n[CRED095]\nROCKSTAR TEST TEAM\n\n[CRED096]\nLANCE WILLIAMS\n\n[CRED097]\nJOE GREENE\n\n[CRED098]\nBRIAN PLANER\n\n[CRD098A]\nELIZABETH SATTERWHITE\n\n[CRD098B]\nJAMEEL VEGA\n\n[CRD098C]\nMIKE HONG\n\n[CRED099]\nLEE CUMMINGS\n\n[CRED100]\nSTORY\n\n[CRED101]\nJAMES WORRALL\n\n[CRED102]\nDAN HOUSER\n\n[CRED103]\nADAM TEDMAN\n\n[CRED104]\nPAUL YEATES\n\n[CRED105]\nJENEFER GROSS\n\n[CRED106]\nLAURA PATERSON\n\n[CRED107]\nCUT SCENES\n\n[CRED108]\nWRITTEN BY DAN HOUSER AND JAMES WORRALL\n\n[CRED109]\nAUDIO DIRECTED BY DAN HOUSER AND NAVID KHONSARI\n\n[CRED110]\nPRODUCED BY JAMIE KING\n\n[CRD110A]\nTALENT PROCUREMENT: JAMIE KING, SEAN MACALUSO\n\n[CRED111]\nCAST\n\n[CRD111A]\nSUPPORTING CHARACTERS\n\n[CRED112]\nTOMMY VERCETTI - RAY LIOTTA\n\n[CRED113]\nKEN ROSENBERG - WILLIAN FICHTNER\n\n[CRED114]\nSONNY FORELLI - TOM SIZEMORE\n\n[CRED115]\nSTEVE SCOTT - DENNIS HOPPER\n\n[CRED116]\nAVERY CARRINGTON - BURT REYNOLDS\n\n[CRED117]\nRICARDO DIAZ - LUIS GUZMAN\n\n[CRED118]\nLANCE VANCE - PHILIP MICHAEL THOMAS\n\n[CRED119]\nCOLONEL JUAN CORTEZ - ROBERT DAVI\n\n[CRED120]\nUMBERTO ROBINA - DANNY TREJO\n\n[CRED121]\nPHIL CASSIDY - GARY BUSEY\n\n[CRED122]\nMITCH BAKER - LEE MAJORS\n\n[CRED123]\nMERCEDES CORTEZ - FAIRUZA BALK\n\n[CRED124]\nKENT PAUL - DANNY DYER\n\n[CRED125]\nJEZZ TORRENT - KEVIN MCKIDD\n\n[CRED126]\nTAXI CONTROLLER - DEBORAH HARRY\n\n[CRED127]\nCANDY SUXXX - JENNA JAMESON\n\n[CRED128]\nBJ SMITH - LAWRENCE TAYLOR\n\n[CRED129]\nAUNTIE POULET - YOUREE CLEOMILI HARRIS\n\n[CRED130]\nSUPPLIER - ARMANDO RIESCO\n\n[CRED131]\nCOUGAR - BLAYNE PERRY\n\n[CRED132]\nHILARY - CHARLES TUCKER\n\n[CRED133]\nCONGRESSMAN ALEX SHRUB - CHRIS LUCAS\n\n[CRED134]\nOLD MAN KELLY - GEORGE DICENZO\n\n[CRD134A]\nCAM JONES - GREG SIMS\n\n[CRD134B]\nPSYCHO - HUNTER PLATIN\n\n[CRD134C]\nMAUDE THE ICE CREAM LADY - JANE GENNARO\n\n[CRD134D]\nJETHRO - JOHN ZURHELLEN\n\n[CRD134E]\nGONZALES - JORGE PUPO\n\n[CRD134F]\nDWAYNE - NAVID KHONSARI\n\n[CRD134G]\nDICK - PETER MCKAY\n\n[CRD134H]\nMIKE THE GOON & PORN GUY - ROBERT CIHRA\n\n[CRD134I]\nPERCY - RUSSELL FOREMAN\n\n[CRED135]\nMOTION CAPTURE\n\n[CRED136]\nANIMATED BY\n\n[CRD136A]\nTECHNICAL DIRECTION BY ALEX HORTON\n\n[CRED137]\nDIRECTED BY\n\n[CRD137A]\nDIRECTED BY NAVID KHONSARI\n\n[CRED138]\nPRODUCED BY\n\n[CRD138A]\nPRODUCED BY JAMIE KING\n\n[CRD138B]\nRENAUD SEBBANE\n\n[CRED139]\nRECORDED AT PERSPECTIVE STUDIOS, BROOKLYN\n\n[CRED140]\nMOTION CAPTURE ACTORS\n\n[CRD140A]\nBLAYNE PERRY\n\n[CRD140B]\nJONATHON SALE\n\n[CRD140C]\nCHARLES TUCKER\n\n[CRD140D]\nEDDIE MARRERO\n\n[CRD140E]\nWILLIAM MCCALL\n\n[CRD140F]\nJORGE PUPO\n\n[CRD140G]\nROBERT JACKSON\n\n[CRD140H]\nTARA RADCLIFFE\n\n[CRD140I]\nJENIFER GAMBETESE\n\n[CRD140J]\nKRIS ACHEVARRIA\n\n[CRD140K]\nALI ORDOUBADI\n\n[CRD140L]\nKAHLEEM POOLE\n\n[CRED141]\nPEDESTRIAN DIALOGUE\n\n[CRD141A]\nWRITTEN BY DAN HOUSER, MARC FERNANDEZ, GILLIAN TELLING AND NAVID KHONSARI\n\n[CRD141B]\nWITH HELP FROM JEREMY POPE, LANCE WILLIAMS, AND JENNY JEMISON\n\n[CRED142]\nWRITTEN BY\n\n[CRD142A]\nDAN HOUSER AND JAMES WORRALL\n\n[CRED143]\nDIRECTED BY DAN HOUSER, CRAIG CONNER, MARC FERNANDEZ, AND ALLAN WALKER\n\n[CRED144]\nPRODUCED BY RENAUD SEBANNE\n\n[CRED145]\nPEDESTRIANS\n\n[CRED146]\nADAM DAVIDSON, ADAM WATKINS, ALEJANDRO K. BROWN, ALEX ANTHONY SIOUKAS, ALEX GARCIA,\n\n[CRED147]\nALICE SALTZMAN, ALISON CIHRA, AMY SALIMA, AMY SALZMAN, ANDREA VIDELA, ANTHONY ATTI,\n\n[CRED148]\nANTHONY RIVERA, BIJAN SHAMS, BLAYNE PERRY, BRETT BISOGNO, BREYE MATA, BRIAN PANEN,\n\n[CRED149]\nBROCK VODER, CAREY BERTINI, CHARISSE LAMBERT, CHRIS DIFAT, CHRIS REISENBERGER,\n\n[CRED150]\nCHRISTOPHER BRODAY, CHRISTOPHER CARRO, CYNTHIA GREENE, DAMARIES LOPEZ, DAN LEE,\n\n[CRED151]\nDAN SCHNEIDER, DAN TOYAMA, DAVID DEAN CHALTFIELD, JR., DAVID HARRISON, DAVID WILEY,\n\n[CRED152]\nDEBORAH COLLINS, DEBRANDA CHANEY-GILES, DEMETRA KOUKOULAS, DENISE ROSADO,\n\n[CRED153]\nDEVIN BENNETT, DEVIN WINTERBOTTOM, DORIS WOO, DOUGLAS HARRISON, DUNCAN COUTTS,\n\n[CRED154]\nDUPE AJAYI, EDWIN AVELLANEDA, ELIZABETH HOWELL, ELIZABETH SATTERWHITE, ERIC NAGLE,\n\n[CRED155]\nESTEBAN KARPLUS, F. FONT, FUTABA HAYASHI, GENE HILGREEN, GERALD COSGROVE,\n\n[CRED156]\nGERARD LUNA, GILLIAN TELLING, GREGG CARLUCCI, GREGORY CLERVOIX, GREGORY SCHWEIZER,\n\n[CRED157]\nHADLEY TOMICKI, J. ROSSETT, JAMEEL VEGA, JASON JONES, JEFF ROSA, JENNIFER JEMISON,\n\n[CRED158]\nJEREMY TAGGERT, JESSICA RIDER, JOSEPH GREENE,JOSEPH HOWELL, KATE DUKICH,\n\n[CRED159]\nKEL O'NEILL, KEVIN HOPKINS, LADAWN JAMES, LANCE WILLIAMS, LAURA BUBBLES,\n\n[CRED160]\nLAURA PATTERSON, LEE CUMMINGS, LETICIA L. YOUNG, LINDSAY KENNEDY, LISA ORITZ,\n\n[CRED161]\nLORNA JORDAN, LUCIO AMADIO, MARCO FERNANDEZ, MARIKO TANAKA, MARLON MATTHEWS,\n\n[CRED162]\nMARY TELLING, MASAYOSHI MITSUYAMA, MATTHEW CHUNG, MAX ALLSTADT, MAX BOGDANOV,\n\n[CRED163]\nMELISSA ALVAREZ, MICHAEL MAY, MICHAEL ROTHSTEIN, MIGUEL VIDAL, MIKE FEDERLINE,\n\n[CRED164]\nNATALIE DESCALZO, N'GAI MEMBERS, NICOLAS MALLO, NOELLE SADLER, NORBERT MORIVAN,\n\n[CRED165]\nOSWALD GREENE, JR., PETER MCKAY, PETER APPEL, PRESTON SAVARESE, RAFAEL GONZALES,\n\n[CRED166]\nRANDY JOHNSON, REY CONCEPCION, RICHARD KROGER, ROB TIBBS, ROBERT JACKSON,\n\n[CRED167]\nROBERT SCHULER, ROSS A. MCINTYRE, RUSSELL FOREMAN, RUTH NUNEZ, SALVADORE SUAZO,\n\n[CRED168]\nSAM WHITE, SANTOS GONZALES, SCOTT SMITH, SEYMOUR FRAILMAN, SPELMAN BRAUMAN,\n\n[CRED169]\nSTEPHANIE TELLING, STEVE KNEZEVICH, STEVE ROBERT, SUMIKO YASUDA, SUSAN LEWIS,\n\n[CRED170]\nSYLVIA COLACIOS, TOMOKO MIYAZAKI, TRON, VERDEL HALE, YVES MONDESIR, ZENO LEINFELDER,\n\n[CRED171]\nDAVID BEDDOES, CHRISTINE CHALMERS, BARRY CLARK, NEIL CORBETT, KIM GURNEY, NEIL MEIKLE,\n\n[CRED172]\nCASSIE OLIVER, LORRAINE ROY, DAVID WATSON, KEVIN WONG, WILL MORTON\n\n[CRED175]\nADAM DAVIDSON\n\n[CRED176]\nLANCE WILLIAMS\n\n[CRED177]\nNEIL MCCAFFREY\n\n[CRED178]\nLAURA PATERSON\n\n[CRED179]\nREY CONCEPCION\n\n[CRED180]\nCHARLES HEROLD\n\n[CRED181]\nANDREW GREENWALD\n\n[CRED182]\nJAMES MIELKE\n\n[CRED183]\nPETER SUCIU\n\n[CRED184]\nALEX ODULIO\n\n[CRED185]\nDON NKRUMAH\n\n[CRED186]\nKENDALL PITTMAN\n\n[CRED187]\nSAL SUAZO\n\n[CRED188]\nEREK MATEO\n\n[CRED189]\nCHRIS DIFATE\n\n[CRED190]\nLEILA MILTON\n\n[CRED191]\nDARREN ZOLTOWSKI\n\n[CRED192]\nVIRGINIA SMITH\n\n[CRED193]\nKEVIN CASSIN\n\n[CRED194]\nJASON SHIGEMORI\n\n[CRED195]\nKELLY KINSELLA\n\n[CRED196]\nMOLLIE STICKNEY\n\n[CRED197]\nSTANTON SARJEANT\n\n[CRED198]\nLAURA WALSH\n\n[CRED199]\nMARK GARONE\n\n[CRED200]\nJOANNA SLY\n\n[CRED201]\nELIZABETH HOWELL\n\n[CRED202]\nANA HERCULES\n\n[CRED203]\nSHIRLEY IRICK\n\n[CRED204]\nKASHONA FIELDS\n\n[CRED205]\nJOEL M. LILJE\n\n[CRED206]\nJOHN DIBENEDETTO\n\n[CRED207]\nNANCY GILES\n\n[CRED208]\nRYAN CROY\n\n[CRED209]\nJENNIFER KOLBE\n\n[CRED210]\nLIAM BURKE\n\n[CRED211]\nSIGRID PREISSL\n\n[CRED212]\nANITA FITZSIMONS\n\n[CRED213]\nPHILIPPA RASELLI\n\n[CRED214]\nWIL QUESNEL\n\n[CRED215]\nFALKO BURKERT\n\n[CRED216]\nSARA SEWELL\n\n[CRED217]\nRADIO STATIONS AND MUSIC\n\n[CRED218]\nMUSIC CONSULTANCY\n\n[CRD218A]\nHEINZ HENN\n\n[CRD218B]\nSTUART ROSS\n\n[CRED219]\nSOUNDTRACK CO-ORDINATOR\n\n[CRED220]\nTERRY DONOVAN\n\n[CRED221]\nPRODUCER FOR ROCKSTAR GAMES\n\n[CRED222]\nDAN HOUSER AND LAZLOW\n\n[CRED223]\nPRODUCER FOR ROCKSTAR NORTH\n\n[CRED224]\nCRAIG CONNER\n\n[CRED225]\nALLAN WALKER\n\n[CRED226]\nLAZLOW\n\n[CRED227]\nDJ BANTER AND IMAGING\n\n[CRED228]\nWRITTEN BY DAN HOUSER AND LAZLOW\n\n[CRED229]\nFLASH FM\n\n[CRD229A]\nTONI-MARIA CHAMBERS\n\n[CRD229B]\nIMAGING VOICE AND PRODUCTION-JEFF BERLIN\n\n[CRED230]\nSPECIAL THANKS TO\n\n[CRED231]\nTOMMY MOTTOLA,\n\n[CRED232]\nMICHELLE ANTHONY,\n\n[CRED233]\nSTEVE BARNETT,\n\n[CRED234]\nCHUCK FLECKENSTEIN,\n\n[CRED235]\nRITA LIBERATOR\n\n[CRED236]\nMARTIN & CLAIRE LOGAN\n\n[CRED237]\nSANDRA HUTTON\n\n[CRED238]\nCHRISTINE DAVIDSON\n\n[CRED239]\nALAN, RED & BIGFOOT\n\n[CRED240]\nLE T\n\n[CRED241]\nCOLIN DONALD\n\n[CRED242]\nKERRY STALLWOOD\n\n[CRED243]\nALAN MCGREGOR\n\n[CRED244]\nCHRIS MORTON\n\n[CRED245]\nEMIL BUSSE\n\n[CRED246]\nEMILY BAILLIE\n\n[CRED247]\nKEVIN ARCHIBALD\n\n[CRED248]\nMORAG KERR\n\n[CRED249]\nCATH WALKER\n\n[CRED250]\nISO BAR\n\n[CRED251]\nWATERLINE\n\n[CRED252]\nNEWS CAFE\n\n[CRD251A]\nTHE POND\n\n[CRD252A]\nPIVO\n\n[CRED253]\nBUDGET VIDEO RENTALS\n\n[CRED254]\nLORNA'S SCOOTER\n\n[CRED255]\nGARETH MURFIN\n\n[CRED256]\nADDITIONAL ART\n\n[CRED257]\nTONY PORTER\n\n[CRED258]\nCRAIG MOORE\n\n[CRED259]\nCUT SCENE LIP-SYNC ANIMATION\n\n[CRED260]\nCOSGROVE HALL FILMS\n\n[CRED261]\nPRODUCER - OWEN BALLHATCHET\n\n[CRED262]\nSENIOR ANIMATOR - JON TURNER\n\n[CRED263]\nANIMATORS - RICHARD DRUMM\n\n[CRED264]\nDAVE BROWN\n\n[CRED265]\nMAIR THOMAS\n\n[CRED266]\nPRASHANT PATEL\n\n[CRED267]\nAUDIO TECHNOLOGY CONSULTANT\n\n[CRED268]\nRIK EDE FOR GAMESOUND LTD.\n\n[CRED269]\nDTS INTEGRATION SUPPORT\n\n[CRED270]\nTED LAVERTY FOR DTS\n\n[CRED271]\nCHRIS GREER FOR DTS\n\n[CRED272]\nJASON PAGE FOR SCEE\n\n[CRED273]\nRESEARCH AND ANALYSIS\n\n[CRED274]\nVROCK\n\n[CRED275]\nDJ: LAZLOW AS HIMSELF\n\n[CRED276]\nIMAGING VOICE-JOE KELLY\n\n[CRED277]\nIMAGING PRODUCTION-JONATHAN HANST\n\n[CRED278]\nWAVE 103\n\n[CRED279]\nDJ: ADAM FIRST-JAMIE CANFIELD\n\n[CRED280]\nIMAGING VOICE-JEN SWEENEY\n\n[CRED281]\nIMAGING PRODUCTION-JONATHAN HANST\n\n[CRED282]\nFEVER 105\n\n[CRED283]\nDJ: OLIVER 'LADYKILLER' BISCUIT-JULIUS DYSON\n\n[CRED284]\nIMAGING VOICE MALE-ED MCMANN\n\n[CRED285]\nIMAGING VOICE FEMALE-SHAWNEE SMITH\n\n[CRED286]\nIMAGING PRODUCTION- LISTEN KITCHEN\n\n[CRED287]\nEMOTION 98.3\n\n[CRED288]\nDJ: FERNANDO- FRANK CHAVEZ\n\n[CRED289]\nIMAGING VOICE-JEN SWEENEY\n\n[CRED290]\nIMAGING PRODUCTION-JONATHAN HANST\n\n[CRED291]\nRADIO ESPANTOSO\n\n[CRED292]\nDJ: PEPE-TONY CHILRODES\n\n[CRED293]\nWILDSTYLE\n\n[CRED294]\nDJ: MISTER MAGIC AS HIMSELF\n\n[CRED295]\nIMAGING VOICE-FRANK SILVESTRO\n\n[CRED296]\nIMAGING PRODUCTION-LAZLOW\n\n[CRED297]\nKCHAT\n\n[CRED298]\nWRITTEN BY DAN HOUSER AND LAZLOW\n\n[CRED299]\nPRODUCED AND EDITED BY LAZLOW\n\n[CRED300]\nDJ AMY SHECKENHAUSEN -LEYNA WEBER\n\n[CRED301]\nJEZ TORRENT-KEVIN MCKIDD\n\n[CRED302]\nMANDY -COLLEEN CORBETT\n\n[CRED303]\nMICHELLE CARAPADIS-MARY BIRDSONG\n\n[CRED304]\nMR.ZOO-CARL DOWLING\n\n[CRED305]\nGETHSEMANEE-LYNN LIPTON\n\n[CRED306]\nCLAUDE MAGINOT-JOHN MAUCERI\n\n[CRED307]\nBJ SMITH-LAWRENCE TAYLOR\n\n[CRED308]\nTHOR-FRANK FAVA\n\n[CRED309]\nRADIO CALLERS\n\n[CRED310]\nCOUZIN ED, JOSH CLARK, JASON BUHRMESTER, JUAN ALLER, WAYNE OLIVER, SUSAN LEWIS, GILLIAN TELLING, TOM MURRAY, MIKE FERRANTE SR., EMMANUEL GOLDSTEIN, DAN HOUSER, NICK MANDELOS, GERRY COSGROVE, MIKE PALERMO, PORKCHOP, KEITH BROADAS\n\n[CRED311]\nLEWIS, GILLIAN TELLING, TOM MURRAY, MIKE FERRANTE SR., EMMANUEL GOLDSTEIN,\n\n[CRED312]\nDAN HOUSER, NICK MANDELOS, GERRY COSGROVE, MIKE PALERMO, PORKCHOP,\n\n[CRED313]\nKEITH BROADAS\n\n[CRED314]\nVCPR\n\n[CRED315]\nWRITTEN BY DAN HOUSER AND LAZLOW\n\n[CRED316]\nPRODUCED BY LAZLOW\n\n[CRED317]\nMAURICE CHAVEZ-PHILLIP ANTHONY RODRIGUEZ\n\n[CRED318]\nJONATHAN FREELOADER- PATRICK OLSEN\n\n[CRED319]\nMICHELLE MONTANIUS-KELLY GUEST\n\n[CRED320]\nREP. ALEX SHRUB- CHRIS LUCAS\n\n[CRED321]\nCALLUM CRAYSHAW- SEAN MODICA\n\n[CRED322]\nJOHN F. HICKORY- LJ GANSEN\n\n[CRED323]\nPASTOR RICHARDS- DAVID GREEN\n\n[CRED324]\nJAN BROWN- MAUREEN SILLIMAN\n\n[CRED325]\nBARRY STARK- RENAUD SEBBANE\n\n[CRED326]\nJENNY LOUISE CRAB- MARY BIRDSONG\n\n[CRED327]\nKONSTANTINOS SMITH- KONSTANTINOS.COM\n\n[CRED328]\nJEREMY ROBARD-PETER SILVESTRO\n\n[CRED329]\nRADIO COMMERCIALS\n\n[CRED330]\nWRITTEN BY DAN HOUSER AND LAZLOW\n\n[CRED331]\nPRODUCED BY LAZLOW\n\n[CRED332]\nADDITIONAL JINGLES PRODUCED BY CRAIG CONNER\n\n[CRED333]\nCOMMERCIAL VOICES:\n\n[CRED334]\nADAM DAVIDSON, ALEX ANTHONY, ALICE SALTZMAN, AMY SALZMAN, KATE DUKICH,\n\n[CRED335]\nARAN RONICLE, BARB JONES, BEN KRECH, BRIAN THOMAS, BROCK YODER, CHRIS\n\n[CRED336]\nFERRANTE, CRAIG CONNER, DAVE RYAN, DAVID GREEN, DORIS WOO, DOUGLAS\n\n[CRED337]\nHARRISON, ED MCMANN, FRANK CHAVEZ, FRANK FAVA, GENE HILGREEN, GREG\n\n[CRED338]\nSCHWEIZER, HUNTER PLATIN, JAMES FERRANTE, JEFF BERLIN, JEFF ROSA, JOE KELLY,\n\n[CRED339]\nJOHN MAUCERI, JOSH CLARK, JULIE WEMYSS, KEVIN STRALEY, KIM GURNEY, LANCE\n\n[CRED340]\nWILLIAMS, LAURA PATERSON, LAZLOW, LISA ORTIZ, LORNA JORDAN, LUCIEN JONES,\n\n[CRED341]\nMAUREEN SILLIMAN, MIKE FERRANTE JR., PETE GUSTIN, PETER SILVESTRO, RAFF\n\n[CRED342]\nCROLLA, RANDY JOHNSON, RICHARD KRUGER, RON REEVE, SHELLEY MILLER, SKY, TJ ALLARD\n\n[CRD344A]\nAUDIO RECORDED AT DIGITAL ARTS STUDIOS,\n\n[CRED344]\nNYC, TRACK 9 STUDIOS, NYC,\n\n[CRED345]\nWEDDINGTON MULTIMEDIA, LOS ANGELES,\n\n[CRD345A]\nSYNC SOUND, NYC AND RADIO LAZLOW, LONG ISLAND.\n\n[CRED346]\nTHANKS TO AXEL ERICSON AND WON LEE AT DIGITAL ARTS, PAUL VASQUEZ AT TRACK 9 STUDIOS, JOHN BOWEN AND JOHN HASSLER AT SYNC SOUND\n\n[CRED347]\nMARK LLOYD\n\n[CRED348]\nTIM BATES\n\n[CRED349]\nKIT BROWN\n\n[CRED350]\nANDY MASON\n\n[CRED351]\nPHIL DEANE\n\n[CRED352]\nPHIL ALEXANDER\n\n[CRED353]\nMATT HEWITT\n\n[CRED354]\nDENBY GRACE\n\n[CRED355]\nANTOINE CABROL\n\n[CRED356]\nJONOTHAN STONES\n\n[CRED357]\nMIKE BLACKBURN\n\n[CRED358]\nTIM MCGAFF\n\n[SUNSHIN]\nSunshine Autos\n\n[CHERRYP]\nCherry Popper Icecreams\n\n[KAUFCAB]\nKaufman Cabs\n\n[BOATYAR]\nThe Boatyard\n\n[WANT_L]\nYour wanted level has been suspended, if you commit a crime whilst the stars are flashing your full wanted level will be reinstated.\n\n[PICK1]\nBody Armor delivered to Ocean View Hotel!\n\n[HOTRNG]\nHOTRING\n\n[BLODRNG]\nBLOODRING\n\n[DIRTRNG]\nDIRTRING\n\n[FEC_ABR]\nAccelerate, Brake or Reverse\n\n[FEI_BTU]\n; = -\n\n[FEI_SCR]\nScroll\n\n[SKUMBUY]\nSkumole Shack purchased: $~1~\n\n[SKUM_L]\nPress the ~h~~k~~PED_ANSWER_PHONE~ ~w~button to purchase Skumole Shack for $~1~\n\n[SKUM_T]\nPress the ~h~~k~~PED_ANSWER_PHONE~ ~w~button to purchase Skumole Shack for $~1~\n\n[SKUM_C]\nPress the ~h~~k~~PED_ANSWER_PHONE~ ~w~button to purchase Skumole Shack for $~1~\n\n[LG_35]\nDestination\n\n[BOAT_AS]\n~g~The Boatyard will now generate revenue up to a maximum of $~1~. Make sure you collect it regularly.\n\n[BOAT_A2]\nBOATYARD ASSET COMPLETED\n\n[BOAT_N]\nCheckpoint Charlie\n\n[BOAT_P]\n~g~collect the packages before the time runs out.\n\n[FEI_R1B]\nR1 \\ R2 button -\n\n[HELP9_A]\nPress the~h~ ~k~~PED_FIREWEAPON~ button ~w~to ~h~fire~w~ the sniper rifle.\n\n[HELP21]\nPress the ~h~~k~~VEHICLE_ENTER_EXIT~ ~w~button to enter or exit a vehicle.\n\n[CREAM]\nDistribution\n\n[UMBERTO]\nCafe Robina\n\n[PU_CF1]\nPress the ~h~~k~~PED_ANSWER_PHONE~ ~w~button to pick up this weapon. It will replace any weapon you have of the same type.\n\n[FED_RDM]\nMAP & BLIPS\n\n[FEC_ILU]\nInvert Look in 1st Person\n\n[NITRO]\nAll taxi's now have a boost jump! Just press the horn button.\n\n[RATNG53]\nUntrustworthy\n\n[RATNG54]\nEmbarrassment\n\n[RATNG55]\nHacker\n\n[RATNG56]\nCheater\n\n[RATNG57]\nTotal Liar\n\n[STHC_04]\nHighest score with Keepie-Uppy beach ball\n\n[STHC_05]\nHotring Best Result\n\n[STFT_13]\nFastest time on Downtown Chopper Checkpoint\n\n[STFT_14]\nFastest time on Ocean Beach Chopper Checkpoint\n\n[STFT_15]\nFastest time on Vice Point Chopper Checkpoint\n\n[STFT_16]\nFastest time on Little Haiti Chopper Checkpoint\n\n[STFT_21]\nFastest time in Hotring\n\n[STFT_22]\nFastest lap time in Hotring\n\n[STFT_20]\nFastest time for 'Cone Crazy'\n\n[HELP44]\nStop in the ~q~pink marker.\n\n[HELP45]\nPress the ~h~~k~~PED_DUCK~~w~ button to duck. This will increase the accuracy of guns you are holding.\n\n[RCR1_5]\nRC Bandit Race\n\n[RCPL1_7]\nRC Baron Race\n\n[RCH1_11]\nRC Raider Pickup\n\n[FEA_CTD]\nWarning! This feature requires DTS compatible hardware to be connected. Proceed?\n\n[FEM_STE]\nUSE STEREO\n\n[GREET]\nGreetings from...\n\n[LANCE_1]\nCome on man, drive more careful!\n\n[LANCE_2]\nHey watch what you're doin!\n\n[LANCE_3]\nHey where are we goin' now?\n\n[LANCE_4]\nWhat are we doin' now?\n\n[LAW4_15]\nMore money!\n\n[MERC_5]\nNice car, Mr. Vercetti.\n\n[MERC_26]\nFASTER, FASTER, FASTER!\n\n[MERC_27]\nCareful, Tommy, I only have a nose job last month.\n\n[MERC_28]\nTommy, drive careful.\n\n[MERC_29]\nTommy, go slower.\n\n[MERC_30]\nTommy, please kill someone other than me.\n\n[MERC_31]\nTommy, baby, don't kill me!\n\n[MERC_32]\nTommy, I'm glad you stole this car!\n\n[MERC_40]\nI had so much fun.\n\n[MERC_43]\nAdios, angel.\n\n[MERC_44]\nYou keep working out, now, you hear.\n\n[MERC_45]\nCiao, beautiful.\n\n[COL5_17]\nOh my god they've got a helicopter!\n\n[COL5_18]\nShoot the helicopter!\n\n[COL5_19]\nTommy, take that chopper out!\n\n[COL5_20]\nHe's coming again! Blow that chopper!\n\n[COL5_21]\nLook at the size of that chopper!\n\n[COL5_22]\nHere he comes again!\n\n[FEA_DSM]\nWarning! This savegame is set to use DTS. This requires DTS compatible hardware to be connected. Please select whether you want to proceed using DTS or STEREO output.\n\n[STFT_23]\nFastest time for Checkpoint Charlie\n\n[HELP50]\nPress the ~h~~k~~PED_ANSWER_PHONE~~w~ button to set the camera behind you.\n\n[HELP51]\nPress the ~h~~k~~PED_ANSWER_PHONE~~w~ button to set the camera behind you.\n\n[HELP52]\nPress the ~h~~k~~PED_ANSWER_PHONE~~w~ button to set the camera behind you.\n\n[HELP53]\nPress ~h~~k~~PED_CYCLE_WEAPON_LEFT~~w~ button or ~h~~k~~PED_CYCLE_WEAPON_RIGHT~~w~ button to cycle through your available weapons.\n\n[HELP46]\nThere are eight different types of weapon.\n\n[HELP47]\nYou can carry one of each type of weapon at a time - one type of pistol, one type of shotgun.\n\n[HELP54]\n~w~Cost: $~1~ ~r~Buying this will replace your current weapon.\n\n[HELP2A2]\nPress the ~h~~k~~PED_SPRINT~~w~ button when running to ~h~sprint\n\n[HLPSN_A]\nThe sniper rifle allows you to zoom in and fire accurately at targets from a distance.\n\n[HLPSN_B]\nPress and hold the~h~ ~k~~PED_LOCK_TARGET~ ~w~button to ~h~target~w~ with the sniper rifle.\n\n[HLPSN_C]\nPress and hold the~h~ ~k~~PED_LOCK_TARGET~ ~w~button to ~h~target~w~ with the sniper rifle.\n\n[HLPSN_D]\nPress the ~h~~k~~PED_SNIPER_ZOOM_IN~~w~ button ~w~to ~h~zoom in ~w~with the rifle and the~h~ ~k~~PED_SNIPER_ZOOM_OUT~ button ~w~to ~h~zoom out ~w~again.\n\n[HLPSN_E]\nPress the ~h~~k~~PED_FIREWEAPON~~w~ button ~w~to ~h~fire~w~ the sniper rifle.\n\n[HLPSN_F]\nPress the ~h~~k~~PED_FIREWEAPON~~w~ button ~w~to ~h~fire~w~ the sniper rifle.\n\n[HLPSN_G]\nPress the ~h~~k~~PED_FIREWEAPON~~w~ button to ~h~fire~w~ the sniper rifle.\n\n[PLANE_H]\nUse the ~h~~k~~VEHICLE_ACCELERATE~~w~ button to accelerate, Left and right to turn.\n\n[PLANE_4] { reVC update }\n{ Use the ~h~~k~~VEHICLE_ACCELERATE~~w~ button to accelerate, Left and right to turn. }\nUse the right analog stick to accelerate, pull back on the left analog stick to climb, push forwards to descend. Left and right to turn.\n\n[HELP55]\nPress the ~h~~k~~PED_FIREWEAPON~~w~ button to attack the chef.\n\n[STPR_8]\nPole Position Club\n\n[STPR_9]\n3321 Vice Point\n\n[STPR_10]\nLinks View Apartment\n\n[STPR_11]\nEl Swanko Casa\n\n[STPR_12]\n1102 Washington Street\n\n[STPR_13]\nOcean Heights Apartment\n\n[STPR_14]\nSkumole Shack\n\n[STPR_15]\nHyman Condo\n\n[RCCANX]\n~r~RC plane cancelled.\n\n[CLT_HL2]\nWhen a Clothes Pickup is collected, a one star or two star wanted level will be cleared.\n\n[CRED009]\nMISSION DESIGN\n\n[CRED359]\nLEE JOHNSON\n\n[CRED360]\nHENDRIK LESSER\n\n[CRED361]\nPASQUALE STACCHIOTTI\n\n[CRED362]\nENRIQUE FERNANDEZ\n\n[CRED363]\nPAUL BYERS\n\n[CRED364]\nMIKE EMENY\n\n[CRED365]\nROB DUNKIN\n\n[CRED366]\nCHARLIE KINLOCH\n\n[CRED367]\nKEVIN HOBSON\n\n[CRED368]\nJIM CREE\n\n[MOB_66A]\nTommy, Tommy why you coming back here for?\n\n[MOB_66B]\nI tell you we don't want to see you around here no more.\n\n[MOB_67A]\nTommy, me thinks you should be staying away, you hear?\n\n[MOB_67B]\nThe Haitian boys not too 'appy with you.\n\n[MOB_18A]\nTommy, it's Paulo, how are you? Right mate, anyway, thought I had to drop you a line.\n\n[MOB_18B]\nOh my good lord, my son, you will not believe the quality of the brass I just encountered.\n\n[MOB_18C]\nStreet walker or something, just down in Little Havana, mate.\n\n[MOB_18D]\nSaid her name was Mercedes or something.\n\n[MOB_18E]\nOh my god, mate. You gotta check this bird out.\n\n[MOB_18F]\nCould strip the lead out of a pencil. Said I was the best she ever had and all.\n\n[MOB_18G]\nKeep you potatoes skinned for her. Be seeing you.\n\n[MOB_72A]\nTommy, it's me, Lance. Keep your mouth shut there Tommy, 'cause I ain't got time to talk.\n\n[MOB_72B]\nI ain't interested in what you got to say. Why should I be? You don't care about me, do you?\n\n[MOB_72C]\nYou gotta look after me a bit better. Give me a fair slice. You know...\n\n[MOB_72D]\nTommy... oh, look, man, I'm sorry. It's just that...\n\n[MOB_72E]\nPeople patronize me all my life, treat me like a little kid.\n\n[MOB_72F]\nMy brother would do that. Please, man, don't do that.\n\n[MOB_72G]\nI gotta go.\n\n[MOB_63A]\nTommy, it's Earnest. Earnest Kelly.\n\n[MOB_63B]\nHow are you?\n\n[MOB_63C]\nI'm doing okay. I'll need a stick to walk, but I should be back at work soon enough.\n\n[MOB_63D]\nGood.\n\n[MOB_63E]\nI heard about Lance. What a little prick, eh?\n\n[MOB_63F]\nYes.\n\n[MOB_63G]\nNever trust a man who walks the streets in his pajamas. That's what I say. Glad you killed him. I hope it was painful for the prick.\n\n[MOB_63H]\nI think it was. I just didn't think he was like that...\n\n[MOB_63I]\nTommy, for a raging lunatic, you're pretty naive. I'll be back at work soon, teach you a thing or two about life, you hear.\n\n[MOB_63J]\nTake your time, Earnest. Look after yourself.\n\n[MOB_16A]\nTommy, Paulo here, que pasa amigo?\n\n[MOB_16B]\nWhat do you want Paul? I don't want any fake label clothes.\n\n[MOB_16C]\nVery funny, mate, but you know I don't touch bent gear. Nah, I was just calling to see if I get a part in one your movies.\n\n[MOB_16D]\nBack in England I did a lot of blue stuff, mate. I'm packing more heat than you, my son.\n\n[MOB_16E]\nPaul, thanks for the offer, I'll bear it in mind.\n\n[MOB_16F]\nSeriously, don't forget about me, after all I done for you.\n\n[MOB_16G]\nThat's what I'm trying to forget about.\n\n[MOB_17A]\nTommy Vercetti, how's it going, Mr. big shot? I hear all these things about you, some kind of player in town, now eh...\n\n[MOB_17B]\nPaul, you're drunk.\n\n[MOB_17C]\nNah, you stupid prat, I ain't drunk. I only had a couple and some treats, ain't been to bed for a couple of days, you know.\n\n[MOB_17D]\nAnyway, don't give me that. I ain't a mug. Who set you up in this town? Who? Me. That's who.\n\n[MOB_17F]\nReally?\n\n[MOB_17G]\nDon't give me that. Don't! I introduced you to people. I showed you the ropes, did a lot of stuff for you, and this is how you repay me.\n\n[MOB_17H]\nYou ignore me. You won't give me a way in, after all I did for you! What do you think I am? A div or something?\n\n[MOB_17I]\nPaul, take it easy. I've been busy, don't be an idiot.\n\n[MOB_17J]\nI ain't no idiot, mush. That's what they said in borstal. Are you asking for trouble son, because you're going to get it!\n\n[MOB_17K]\nTommy, mate. Please. You was my big hope! Please, don't laugh at me!\n\n[MOB_17L]\nPaul, get some sleep, seriously.\n\n[MOB_73A]\nTommy, it's Steve.\n\n[MOB_73B]\nHey, Steve.\n\n[MOB_73C]\nHey indeed, genius. You're a marvel! I'm a marvel! They love us. We are re-writing the record books, pal.\n\n[MOB_73D]\nWe are talking major awards here. Finally, I can put my dad in a home an tell him to shut up.\n\n[MOB_73E]\nEeer, that's cool, Steve.\n\n[MOB_73F]\nCool? It's hot, man. Hot. H. O. T. He never believed in me. Never thought I was an artist, and now I've made it.\n\n[MOB_73G]\nI'm the best damn skin flick director of all time, my friend. I just wanted to say, it's a pleasure to have met you.\n\n[MOB_73H]\nThanks steve.\n\n[MOB_73I]\nI love you, baby. Don't go changing on me, you hear.\n\n[MOB_73J]\nI hear you. Good bye, Steve.\n\n[BOLLOX]\nPress the ~h~~k~~VEHICLE_HANDBRAKE~ ~w~button to drop a bomb. Press the ~h~~k~~VEHICLE_ENTER_EXIT~ ~w~button to cancel.\n\n[BRID_OP]\nStorm warning over, all bridges to the mainland are now open.\n\n[BRID_CL]\nStorm warning: All bridges to the mainland are closed.\n\n[LG_38]\nTarget\n\n[ASSET_C]\nPOLE POSITION ASSET COMPLETED!\n\n[ASSET_D]\n~g~The Pole Position Club will now generate revenue up to a maximum of $~1~ per day. Pick up your cash regularly!\n\n[ST_WHEE]\nLongest Wheelie time (secs)\n\n[ST_STOP]\nLongest Stoppie time (secs)\n\n[ST_2WHE]\nLongest 2 wheels time (secs)\n\n[ST_WHED]\nLongest Wheelie distance (m)\n\n[ST_STOD]\nLongest Stoppie distance (m)\n\n[ST_2WHD]\nLongest 2 wheels distance (m)\n\n[OUTFT11]\nTracksuit\n\n[OUTFT12]\nFrankie\n\n[RELOAD]\n~g~You have won the fast reload ability!\n\n[APACHE]\nHunter delivered to helipad in Ocean Beach.\n\n[CRED369]\nJOHN MCCARDLE\n\n[CRED370]\nDAVID MURDOCH\n\n[CRED371]\nCHRIS BROWN\n\n[CRED372]\nPAUL GREEN\n\n[CRED373]\nKYLE MILNE\n\n[CRED374]\nKEVIN YUN\n\n[CRED375]\nERICK COBBS\n\n[CRED376]\nRANDY BLAKE\n\n[CRED377]\nBRANDON LIM\n\n[CRED378]\nBRANDON FENOL\n\n[CRED379]\nMICHAEL MANOLE\n\n[CRED380]\nALETHEIA SIMONSON\n\n[CRED381]\nJOHN JANSEN\n\n[CUNTY]\nNew clothes delivered to the Vercetti Estate!\n\n[GOODBOY]\n$50 Good Citizen Bonus!\n\n[NEWCONT]\nNew ~h~Contact Point ~w~opened at the marina in Ocean Beach!!\n\n[FIRELVL]\nFire Truck Mission level ~1~\n\n[FEM_RET]\nRETRY\n\n[FESZ_QR]\nAre you sure you want to start a new game? All progress will be lost. Proceed?\n\n[SEG3_1]\nTIME:\n\n[HELP56]\nPress the ~h~~k~~CAMERA_CHANGE_VIEW_ALL_SITUATIONS~~w~ button to change camera modes.\n\n[HELP57]\nPress the ~h~~k~~CAMERA_CHANGE_VIEW_ALL_SITUATIONS~~w~ button to change camera modes.\n\n[HELP58]\nWhile targeting you can press the ~h~~k~~PED_CYCLE_TARGET_LEFT~ button or ~k~~PED_CYCLE_TARGET_RIGHT~ ~w~button to cycle through targets.\n\n[HELP59]\nWhile targeting you can press the ~h~~k~~PED_CYCLE_TARGET_LEFT~ button or ~k~~PED_CYCLE_TARGET_RIGHT~ ~w~button to cycle through targets.\n\n[HELP60]\nIf you press the ~w~~k~~PED_SPRINT~ ~w~button while car jacking, you will not enter that vehicle.\n\n[HELP61]\nYou now have limitless ammo and double health on all vehicles.\n\n[FEC_LB1]\nLook\n\n[FEC_LB2]\nbehind\n\n[FEC_LB3]\nLook behind\n\n[FEC_R3]\n(R3 button)\n\n[FEC_PED]\nControls On Foot\n\n[FEC_VEH]\nControls In Vehicle\n\n[FEC_FPR]\nControls For First Person\n\n[FEC_CMM]\nCommon Controls\n\n[FEC_PWL]\nGo Left\n\n[FEC_PWR]\nGo Right\n\n[FEC_PWF]\nWalk Forward\n\n[FEC_PWT]\nWalk towards camera\n\n[FEC_PLB]\nLook Behind.\n\n[FEC_PFR]\nFire Weapon\n\n[FEC_CLE]\nCycle Weapon Left\n\n[FEC_CRI]\nCycle Weapon Right\n\n[FEC_LKT]\nLock Target\n\n[FEC_PJP]\nPed Jump\n\n[FEC_PSP]\nPed Sprint\n\n[FEC_PSH]\nPed Shoot\n\n[FEC_TLF]\nNext Target To Left\n\n[FEC_TRG]\nNext Target to Right\n\n[FEC_CCM]\nCenter Camera Behind player.\n\n[FEC_SZI]\nSniper Rifle Zoom In\n\n[FEC_SZO]\nSniper Rifle Zoom Out\n\n[FEC_LKL]\nFirst Person Look Left\n\n[FEC_LRT]\nFirst Person Look Right\n\n[FEC_LUP]\n1st Person Look Up\n\n[FEC_LDN]\n1st Person Look Down\n\n[FEC_LBH]\nLook Behind Vehicle\n\n[FEC_LLF]\nLook Left of Vehicle\n\n[FEC_LRG]\nLook Right of Vehicle\n\n[FEC_HRN]\nHorn\n\n[FEC_HBR]\nVehicle Handbrake\n\n[FEC_ACL]\nVehicle Accelerate\n\n[FEC_BRK]\nVehicle Brake\n\n[FEC_TSM]\nToggle SubMissions\n\n[FEC_CRD]\nChange Radio Station\n\n[FEC_ENT]\nEnter/Exit Vehicle\n\n[FEC_WPN]\nFire Weapon\n\n[FEC_PAS]\nPause\n\n[FEC_FPO]\n1st Person Weapons\n\n[FEC_SMS]\nShow mouse pointer\n\n[FEC_CMS]\nChange camera mode all situations.\n\n[FEC_TSS]\nTake Screen Shot\n\n[FEC_DBG]\nDEBUG MENU\n\n[FEC_TGD]\nToggle Pad Game/Debug\n\n[FEC_TDO]\nTurn Debug Camera Off\n\n[FEC_IVH]\nInvert Mouse Horizontally:\n\n[FEC_MSL]\nLMB\n\n[FEC_MSM]\nMMB\n\n[FEC_MSR]\nRMB\n\n[FEC_QUE]\n???\n\n[FEC_TWO]\nOnly Two Keyboard Keys Allowed\n\n[FEC_UMS]\nUnique Mouse Keys only please.\n\n[FEC_OMS]\nOnly One Mouse Keys Allowed\n\n[FEC_UJS]\nUnique Joystick buttons only please.\n\n[FEC_OJS]\nOnly One Joystick Buttons per action allowed\n\n[FEC_PTL]\nUse LockTarget with Weapon Switch Left.\n\n[FEC_PTR]\nUse LockTarget with Weapon Switch Right.\n\n[FEC_LBC]\nUse Look Left With Look Right.\n\n[FEC_JBO]\nJOY ~1~\n\n[FEC_WAR]\nWarning\n\n[FEC_OKK]\nO.K.\n\n[FEC_DLF]\nDelete Failed.\n\n[FEC_SVU]\nSave Unsuccessful.\n\n[FEC_LUN]\nLoad Unsuccessful. File Corrupted, Please delete.\n\n[FEC_PAD]\nGamepad\n\n[FEC_JOY]\nJoystick\n\n[FES_CSA]\nSelect a skin from the list below:\n\n[FET_HRD]\nDEFAULT SETTINGS RESTORED\n\n[FET_MST]\nMOUSE CONTROLLED STEERING\n\n[FEC_STR]\nNUM STAR\n\n[FET_MIG]\nLEFT, RIGHT, MOUSEWHEEL TO ADJUST\n\n[FET_CIG]\nBACKSPACE TO CLEAR - LMB, RETURN TO CHANGE\n\n[FET_DSN]\nDefault Player Skin.bmp\n\n[FET_RSO]\nORIGINAL SETTING RESTORED\n\n[FET_RSC]\nHARDWARE NOT AVAILABLE - ORIGINAL SETTING RESTORED\n\n[FEA_3DH]\nAUDIO HARDWARE\n\n[FEA_SPK]\nSPEAKERS CONFIGURATION\n\n[FEM_LOD]\nDRAW DISTANCE\n\n[FEM_VSC]\nFRAME SYNC\n\n[FEM_FRM]\nFRAME LIMITER\n\n[FEM_MM]\nMAIN MENU\n\n[FED_RES]\nSCREEN RESOLUTION\n\n[FET_CTL]\nCONTROLLER SETUP\n\n[FET_OPT]\nOPTIONS\n\n[FEC_MSH]\nMOUSE SENSITIVITY\n\n[FEC_IVV]\nINVERT MOUSE VERTICALLY\n\n[FEC_FNC]\nF~1~\n\n[FEC_IRT]\nINS\n\n[FEC_DLL]\nDEL\n\n[FEC_HME]\nHOME\n\n[FEC_END]\nEND\n\n[FEC_PGU]\nPGUP\n\n[FEC_PGD]\nPGDN\n\n[FEC_UPA]\nUP\n\n[FEC_DWA]\nDOWN\n\n[FEC_LFA]\nLEFT\n\n[FEC_RFA]\nRIGHT\n\n[FEC_NUM]\nNUM\n\n[FEC_NMN]\nNUM~1~\n\n[FEC_FWS]\nNUM /\n\n[FEC_PLS]\nNUM +\n\n[FEC_MIN]\nNUM -\n\n[FEC_DOT]\nNUM .\n\n[FEC_NLK]\nNUMLOCK\n\n[FEC_ETR]\nENT\n\n[FEC_SLK]\nSCROLL LOCK\n\n[FEC_PSB]\nBREAK\n\n[FEC_BSP]\nBSPACE\n\n[FEC_TAB]\nTAB\n\n[FEC_CLK]\nCAPSLOCK\n\n[FEC_RTN]\nRET\n\n[FEC_LSF]\nLSHIFT\n\n[FEC_RSF]\nRSHIFT\n\n[FEC_LCT]\nLCTRL\n\n[FEC_RCT]\nRCTRL\n\n[FEC_LAL]\nLALT\n\n[FEC_RAL]\nRALT\n\n[FEC_LWD]\nLWIN\n\n[FEC_RWD]\nRWIN\n\n[FEC_WRC]\nWINCLICK\n\n[FEC_SPC]\nSPC\n\n[WIN_TTL]\nGrand Theft Auto VC\n\n[WIN_95]\nGrand Theft Auto VC cannot run on Windows 95\n\n[WIN_DX]\nGrand Theft Auto VC requires at least DirectX version 8.1\n\n[FET_EIG]\nCANNOT SET A CONTROL FOR THIS ACTION\n\n[FET_DAM]\nDYNAMIC ACOUSTIC MODELING\n\n[FEQ_SRE]\nAre you sure you want to quit? All progress since the last save game will be lost. Proceed?\n\n[FEQ_SRW]\nAre you sure you want to quit the game?\n\n[FET_QG]\nQUIT GAME\n\n[FEN_STA]\nSTART GAME\n\n[FET_PAU]\nPAUSE MENU\n\n[REPLAY]\nREPLAY\n\n[FEC_ANS]\nAction\n\n[CVT_MSG]\nConverting textures to optimal format for your video card\n\n[FEC_SFT]\nSHIFT\n\n[FEH_VMP]\nVIEW MAP\n\n[FES_DEE]\nDelete Failed! Please try again.\n\n[FES_CMP]\nSave failed! Please try again.\n\n[FESZ_WR]\nSaving current game. Please wait...\n\n[FELD_WR]\nLoading game. Please wait...\n\n[FEDL_WR]\nDeleting saved game. Please wait...\n\n[PCRESRT]\nStarting new game. Please wait...\n\n[FET_STI]\nStandard Controls\n\n[FET_CTI]\nClassic Controls\n\n[FET_PS]\nPLAYER SKIN SETUP\n\n[FEH_NA]\nOPTION NOT AVAILABLE\n\n[FEH_MPH]\nMOUSE, CURSORS TO MOVE - PGUP, PGDN, MSWHEEL TO ZOOM, L - LEGEND\n\n[FEA_MP3]\nMP3 PLAYER\n\n[NO_PCCD]\nPlease insert your GTA Vice City CD, or press ESC to cancel\n\n[FEH_SSA]\nCURSORS TO MOVE - S TO SAVE TO FILE\n\n[FES_CMI]\nLAST MISSION PASSED\n\n[FET_STS]\nSTATS SAVED TO 'STATS.HTML' + 'STATS.TXT'\n\n[WIN_VDM]\nGrand Theft Auto VC cannot find enough available video memory\n\n[FEC_ERI]\nError! One or more control actions are not bound to a key or button. Please check all control actions are set\n\n[FEC_TFU]\nTurret + Lean Up\n\n[FEC_TFD]\nTurret + Lean Down\n\n[FET_RIG]\nSELECT A NEW CONTROL FOR THIS ACTION\n\n[FEA_NM3]\nNO MP3 FILES FOUND\n\n[FEA_MPB]\nMP3 VOLUME BOOST\n\n[FEA_MUS]\nMUSIC VOLUME\n\n[FEA_SFX]\nSFX VOLUME\n\n[CVT_ERR]\nYou have run out of disk space. Please make some space on your harddisk before continuing. Press ESC to cancel.\n\n[FEA_ADP]\nAUTO-DETECT HARDWARE\n\n{=================================== MISSION TABLE AMBULAE ===================================}\n\n[ATUTOR2:AMBULAE]\n~g~Drive the patients to Hospital CAREFULLY. Each bump reduces their chances of survival.\n\n[A_FULL:AMBULAE]\n~r~Ambulance full!!\n\n[A_FAIL2:AMBULAE]\n~r~Your lack of urgency has been fatal to the patient!\n\n[A_FAIL3:AMBULAE]\n~r~The patient is dead!!\n\n[A_PASS:AMBULAE]\nRescued!\n\n[A_COMP2:AMBULAE]\nYou will never get tired!\n\n[A_CANC:AMBULAE]\n~r~Paramedic mission cancelled!\n\n[A_COMP3:AMBULAE]\nParamedic missions complete! You will never get tired when running!\n\n[ALEVEL:AMBULAE]\nParamedic Mission Level ~1~\n\n[A_FAIL1:AMBULAE]\nParamedic mission ended.\n\n[A_SAVES:AMBULAE]\nPEOPLE SAVED: ~1~\n\n[A_COMP1:AMBULAE]\nParamedic missions complete: $~1~\n\n{=================================== MISSION TABLE ASSIN1 ===================================}\n\n[ASM1_5:ASSIN1]\n~r~Your target completed his deliveries!\n\n[ASM1_6:ASSIN1]\nDeliveries left:\n\n[ASM1_7:ASSIN1]\n~g~Carl Pearson, Pizza Delivery Man. Kill him before he completes his deliveries.\n\n[ASM1_A:ASSIN1]\nMr. Teal, your help in eradicating those out-of-towners was invaluable to business. I have more work for you with a more 'hands-on' approach.\n\n[ASM1_D:ASSIN1]\nMr. Teal, your help in eradicating those out-of-towners was invaluable to business.\n\n{=================================== MISSION TABLE ASSIN2 ===================================}\n\n[ASM2_1:ASSIN2]\n~g~Mrs. Dawson will be leaving the Jewelry shop in Vice Point soon. Kill her. It must look like a car accident.\n\n[ASM2_3:ASSIN2]\n~g~She's gonna blow! Get out of there!\n\n[ASM2_4:ASSIN2]\n~r~You smashed up her car when she wasn't in it! She won't touch it now!\n\n[ASM2_5:ASSIN2]\n~r~She got away!\n\n[ASM2_6:ASSIN2]\n~r~You were too near the scene of the 'accident'!\n\n[ASM2_7:ASSIN2]\n~r~It's supposed to look like an accident! Try ramming her off the road instead!\n\n[ASM2_8:ASSIN2]\n~g~You must make Mrs. Dawson's death look like an accident. Do not use any weapons.\n\n[ASM2_9:ASSIN2]\n~g~You need some wheels for this job!\n\n[ASM2_10:ASSIN2]\n~g~When her car bursts into flames make your self scarce!\n\n[ASM2_11:ASSIN2]\nHelp me!\n\n[ASM2_12:ASSIN2]\nSomebody help me!\n\n[ASM2_13:ASSIN2]\nOh my god!\n\n[ASM2_A:ASSIN2]\nMy compliments on a job well done Mr. Teal. My client was very pleased.\n\n[ASM2_2:ASSIN2]\nhealth:\n\n{=================================== MISSION TABLE ASSIN3 ===================================}\n\n[ASM3_11:ASSIN3]\nTIME:\n\n[ASM3_C:ASSIN3]\nA European gang plans to hit a bank in Vice City. My employers would rather this didn't happen.\n\n[ASM3_D:ASSIN3]\nEach member of the gang has a cover while they are here in Vice City. Some have menial jobs, others are on vacation.\n\n[ASM3_E:ASSIN3]\nEach target and their likely whereabouts are taped under the phone.\n\n[ASM3_14:ASSIN3]\n~g~Dick Tanner is working for DBP Security in Ocean Drive.\n\n[ASM3_15:ASSIN3]\n~g~Marcus Hammond and Franco Carter are located near the Jewelry shop in Vice Point.\n\n[ASM3_16:ASSIN3]\n~g~Nick Kong is cruising off Washington Beach.\n\n[ASM3_18:ASSIN3]\n~g~Don't get too close to the target or he may spot you!\n\n[ASM3_19:ASSIN3]\n~g~He's seen you! Waste him!\n\n[ASM3_20:ASSIN3]\n~g~They have seen you! Make sure you waste them both!\n\n[ASM3_21:ASSIN3]\n~r~You did not kill all the gang members in time!\n\n[ASM3_22:ASSIN3]\n~g~Don't get too close to the targets or they may spot you!\n\n[ASM3_12:ASSIN3]\n~g~A selection of weapons have been left for you nearby if you require them. You have ~h~9 MINUTES ~g~to kill all members of the gang.\n\n[ASM3_13:ASSIN3]\n~g~Mike Griffin is working on an advertising board in Washington.\n\n[ASM3_17:ASSIN3]\n~g~Charlie Dilson is riding in Washington.\n\n{=================================== MISSION TABLE ASSIN4 ===================================}\n\n[ASM4_10:ASSIN4]\n~g~Looks like you're not the only one after the briefcase! Get it to Ammu-Nation, quick time!\n\n[ASM4_12:ASSIN4]\nDistance:\n\n[ASM4_15:ASSIN4]\n~g~Get the sniper rifle to your right.\n\n[ASM4_16:ASSIN4]\n~g~Watch the woman on the balcony, she will walk down the escalators and ask someone the time.\n\n[ASM4_17:ASSIN4]\n~g~Once the conversation has finished kill the person she spoke to, but do not kill her.\n\n[ASM4_18:ASSIN4]\n~g~Once the target is dead retrieve his briefcase and take it to Ammu-Nation in Downtown.\n\n[ASM4_19:ASSIN4]\n~g~Keep your distance from the target! Use the distance bar in the upper right corner of the screen.\n\n[ASM4_20:ASSIN4]\n~g~If it gets full he will see you.\n\n[ASM4_21:ASSIN4]\n~g~Get the briefcase!\n\n[ASM4_22:ASSIN4]\n~g~Take the briefcase to Ammu-Nation in Downtown.\n\n[ASM4_23:ASSIN4]\n~g~He has spotted you! Nail him and get the briefcase!\n\n[ASM4_25:ASSIN4]\n~r~You killed the woman you fool!\n\n[ASM4_26:ASSIN4]\n~r~The target has boarded his flight!\n\n[ASM4_27:ASSIN4]\n~r~The target has seen you! You should have kept your distance!\n\n[ASM4_28:ASSIN4]\n~r~The target heard you firing your weapon!\n\n[ASM4_29:ASSIN4]\n~r~Itchy trigger finger? You killed him too soon!\n\n[ASM4_A:ASSIN4]\nTime to fry bigger fish, Mr. Teal. There's a rifle in the foliage to your right.\n\n[ASM4_B:ASSIN4]\nWatch the woman standing on the balcony above the check-in desks. She will walk through the crowd and ask someone the time.\n\n[ASM4_C:ASSIN4]\nYou must kill that person, retrieve his case and take it to the location taped under the phone.\n\n{=================================== MISSION TABLE ASSIN5 ===================================}\n\n[ASM5_A:ASSIN5]\nThere is a valuable exchange taking place on the roof of the Cherry Popper Ice Cream Company.\n\n[ASM5_B:ASSIN5]\nKill everyone involved, steal the merchandise and take it to the helipad at the airport.\n\n[ASM5_C:ASSIN5]\nThere is a gate to your left that leads to the back of the factory.\n\n[ASM5_1:ASSIN5]\n~g~Enter the compound behind the Cherry Popper Ice Cream Company The deal is taking place on the roof.\n\n[ASM5_2:ASSIN5]\n~g~Get the merchandise and take it to the helipad at the airport!\n\n[ASM5_3:ASSIN5]\n~g~Take the merchandise to the helipad at the airport!\n\n{=================================== MISSION TABLE BANKJ1 ===================================}\n\n[WANTED1:BANKJ1]\n~g~Shake the cops and lose your wanted level!\n\n[BJM1_A:BANKJ1]\nTommy! Hey, Tommy, look at this, this is great! I've got us this minibar installed!\n\n[BJM1_B:BANKJ1]\nWe got a whole bar downstairs, Ken.\n\n[BJM1_C:BANKJ1]\nYeah, yeah, whatever. Well, I got the chalkboard you asked for.\n\n[BJM1_D:BANKJ1]\nAh, that's the benefit of a law school education: the ability to follow instructions.\n\n[BJM1_E:BANKJ1]\nNow, I need a safe man.\n\n[BJM1_F:BANKJ1]\nOh, all right, well, let me think...safe, safe, safe, safe - I got it! This guy will blow you away!\n\n[BJM1_G:BANKJ1]\nAhh, nah, that schmuck. He's on the inside.\n\n[BJM1_H:BANKJ1]\nWhere inside?\n\n[BJM1_I:BANKJ1]\nIn a police headquarter cell awaiting transfer.\n\n[BJM1_J:BANKJ1]\nI think he's about to get paroled....\n\n[BJM1_1:BANKJ1]\n~g~Break Cam Jones out of police custody!\n\n[BJM1_3:BANKJ1]\n~g~You will find something useful in the station's locker room.\n\n[BJM1_21:BANKJ1]\n~g~The key card to the cells can be found upstairs in the station.\n\n[BNK1_7:BANKJ1]\nCam Jones?\n\n[BNK1_8:BANKJ1]\nI'm busting you out!\n\n[BNK1_10:BANKJ1]\nYeah, that's me..\n\n[BNK1_11:BANKJ1]\nWhatever you say!\n\n[BNK1_13:BANKJ1]\nI'm gonna be doing a job and you're my safe cracker.\n\n[BNK1_14:BANKJ1]\nBeats losing my ass in a cell!\n\n[BJM1_22:BANKJ1]\n~g~Get Cam back to his house!\n\n[BJM1_23:BANKJ1]\n~g~You need to get the key card first!\n\n[BNK1_12:BANKJ1]\nLose the heat and get me back to my place!\n\n[BJM1_20:BANKJ1]\nPut the weapon away or face the consequences!\n\n[BJM1_5:BANKJ1]\nOnly authorized personnel beyond this point!\n\n[BJM1_2:BANKJ1]\n~r~You were supposed to bust Cam out, not get him killed!\n\n[BJM1_4:BANKJ1]\nHe's armed! Kill him!\n\n{=================================== MISSION TABLE BANKJ2 ===================================}\n\n[BJM2_A:BANKJ2]\nWe need a stick up man. You know one?\n\n[BJM2_B:BANKJ2]\nHey, Tommy, Tommy, Tommy, this stuff keeps you sharp, man.\n\n[BJM2_C:BANKJ2]\nWoooOOOooo!\n\n[BJM2_D:BANKJ2]\nI could be your stick up man! Stick 'em up! Stick 'em up!\n\n[BJM2_E:BANKJ2]\nYou ain't a stick up man, you're an idiot.\n\n[BJM2_F:BANKJ2]\nNow get yourself a drink and shut up.\n\n[BJM2_G:BANKJ2]\nHey, get outta my way! Yeh yeh yeh - ow ow ow!\n\n[BJM2_H:BANKJ2]\nCam, what do you think?\n\n[BJM2_I:BANKJ2]\nWell, the best shooter in this town is a guy named Cassidy.\n\n[BJM2_J:BANKJ2]\nIs that so?\n\n[BJM2_K:BANKJ2]\nYeah. A military guy, or he thinks he is.\n\n[BJM2_L:BANKJ2]\nI doubt he was ever in the army, but he certainly knows how to get a hold of guns.\n\n[BJM2_M:BANKJ2]\nHe'll be down at the shooting range.\n\n[BJM2_2A:BANKJ2]\nYou Phil Cassidy?\n\n[BJM2_2B:BANKJ2]\nWhy?\n\n[BJM2_2C:BANKJ2]\nI'm looking for a man who can handle a gun. From this setup, I'm not too convinced.\n\n[BJM2_2D:BANKJ2]\nSon, I could shoot a fly off your head at 80 feet.\n\n[BJM2_2E:BANKJ2]\nOh really?\n\n[BJM2_2F:BANKJ2]\nYeah. I learnt in the army.\n\n[BJM2_2G:BANKJ2]\nFly shooting real popular in the army? Glad I don't pay tax.\n\n[BJM2_2H:BANKJ2]\nYou tryin' to be funny kid?\n\n[BJM2_2I:BANKJ2]\nHa ha ha ha ha!\n\n[BJM2_2J:BANKJ2]\nLet's shoot.\n\n[BJM2_1:BANKJ2]\n~g~Go to Ammu-Nation in Downtown and talk to Phil Cassidy.\n\n[BJM2_3:BANKJ2]\nHIT RATE: ~1~%\n\n[BJM2_4:BANKJ2]\nSCORE ROUND ONE: ~1~\n\n[BJM2_6:BANKJ2]\nSCORE ROUND TWO: ~1~\n\n[BJM2_7:BANKJ2]\nTOTAL SCORE FOR SHOOT: ~1~\n\n[BJM2_9:BANKJ2]\n~g~Get to round two's starting point.\n\n[BJM2_11:BANKJ2]\n~r~Phil's dead!\n\n[BJM2_12:BANKJ2]\n~r~One of the shooters is dead!\n\n[BJM2_14:BANKJ2]\n~g~Move on to the next area!\n\n[BJM2_15:BANKJ2]\nSCORE:\n\n[BJM2_17:BANKJ2]\n~g~Go and talk to Phil.\n\n[BJM2_18:BANKJ2]\nSCORE TO BEAT:\n\n[BJM2_19:BANKJ2]\n~g~Hit as many targets as you can in the time limit!\n\n[BJM2_22:BANKJ2]\n~r~You have left the shooting range!\n\n[BJM2_23:BANKJ2]\n~g~If you leave the shooting range during the competition, you will fail the mission.\n\n[BJM2_24:BANKJ2]\n~g~The closest target is worth one point.\n\n[BJM2_25:BANKJ2]\n~g~The middle target is worth two points.\n\n[BJM2_27:BANKJ2]\n~g~All targets this round are worth one point.\n\n[BNK2_2:BANKJ2]\nAIM 3-2-1 FIRE!\n\n[BNK2_3:BANKJ2]\nAREA CLEAR!\n\n[BNK2_4:BANKJ2]\nHoooeee!\n\n[BNK2_5:BANKJ2]\nCouldn't hit a barn door!\n\n[BNK2_7:BANKJ2]\nSo you wanna do me a favor, and help me put together a job?\n\n[BNK2_8:BANKJ2]\nSon, after shooting like that, if you asked me to be your wife, I'd say yes.\n\n[BNK2_9A:BANKJ2]\nSon, you better get your fancy talking and big ideas and shove 'em where there ain't no sun. You can't shoot nothin'!\n\n[BNK2_9B:BANKJ2]\nYou can't shoot nothin'.\n\n[BJM2_28:BANKJ2]\nSCORE ROUND THREE: ~1~\n\n[BJM2_20:BANKJ2]\n~g~When you run out of ~w~time ~g~or ~w~ammunition ~g~the round is over!\n\n[BJM2_26:BANKJ2]\n~g~The far target is worth three points.\n\n[BNK2_1:BANKJ2]\nLIVE AMMUNITION\n\n[RANGE_1:BANKJ2]\nSCORE FOR SHOOT: ~1~\n\n[BJM2_2:BANKJ2]\n~g~To exit the round press the ~h~~k~~PED_JUMPING~ ~g~button.\n\n[BJM2_N:BANKJ2]\nRelax\n\n{=================================== MISSION TABLE BANKJ3 ===================================}\n\n[BJM3_A:BANKJ3]\nThings are starting to come together nicely here.\n\n[BJM3_B:BANKJ3]\nWhat's the plan, Tommy? Que pasa, amigo?\n\n[BJM3_C:BANKJ3]\nThe plan is you keep doing that like a moron. Anyhow, we need a driver.\n\n[BJM3_D:BANKJ3]\nTommy, I'll do it. I can drive.\n\n[BJM3_E:BANKJ3]\nYou want Hilary, mister. Not some smart-talking law school chump.\n\n[BJM3_F:BANKJ3]\nHilary's the real deal. You ain't never seen anyone drive so fast. I'll give him a call here.\n\n[BJM3_G:BANKJ3]\nHey Hil, it's Phil. How's it going? No. don't talk. We'll reminisce later. You want to do me a favor?\n\n[BJM3_H:BANKJ3]\nI got me a guy from up north. No, no, I don't think he was in the service, but he wants a driver.\n\n[BJM3_I:BANKJ3]\nFor a bit of action. Okay, I understand.\n\n[BJM3_J:BANKJ3]\nWhat'd he say?\n\n[BJM3_K:BANKJ3]\nWell, he'll do it, no problem. Well, there might be a little problem - see, he has abandonment issues.\n\n[BJM3_L:BANKJ3]\nSeems he won't work for anyone who can't beat him. Something to do with his momma.\n\n[BJM3_M:BANKJ3]\nAnyway, he wants to race you first, said he'd meet you outside..\n\n[BJM3_2A:BANKJ3]\nYou Tommy? Of course you're Tommy, I mean,\n\n[BJM3_2B:BANKJ3]\nWhy else would anyone want to speak to me?\n\n[BJM3_2C:BANKJ3]\nOK. Consider it this way -\n\n[BJM3_2D:BANKJ3]\nI'll drive for you IF, and only IF, you can drive properly.\n\n[BJM3_2E:BANKJ3]\nLeave me alone - and I'll never forgive you.\n\n[BJM3_2:BANKJ3]\n~r~Hilary is dead!\n\n[BJM3_4:BANKJ3]\n~g~You need a car to take part!\n\n[BNK3_1:BANKJ3]\nOk. I'll drive for you, but please, treat me bad.\n\n[BNK3_3A:BANKJ3]\nIllegal street race in progress at Vice Point.\n\n[BNK3_3B:BANKJ3]\nCalling all officers.\n\n[BNK3_3C:BANKJ3]\nStreet racers, this is illegal and forbidden!\n\n{=================================== MISSION TABLE BANKJ4 ===================================}\n\n[BNK4_A:BANKJ4]\n~w~As you can see, gentlemen, this is going to be the easiest buck we ever made.\n\n[BNK4_B:BANKJ4]\n~w~Tommy, seriously, you gotta consider going into law.\n\n[BNK4_C:BANKJ4]\n~w~What the hell are you smoking, man? This ain't no simple plan!\n\n[BNK4_D:BANKJ4]\n~w~Well, who needs a simple plan anyway?\n\n[BNK4_E:BANKJ4]\n~w~Take communism, now that was a simple plan. Didn't do Russia any favors, huh?\n\n[BNK4_F:BANKJ4]\n~w~Calm down, all right? With a team like this it's going to be no problem.\n\n[BNK4_G:BANKJ4]\n~w~We got Cam on safe. Phil? You and me will handle security, and Hilary'll drive the getaway car.\n\n[BNK4_H:BANKJ4]\n~w~Uh, heh heh, aren't you forgetting somebody? Somebody who helped you to no end in this town? Somebody who...\n\n[BNK4_I:BANKJ4]\n~w~Ken... Ken, that's right. Ken here, he washes the money for us and he keeps the drinks on ice.\n\n[BNK4_J:BANKJ4]\n~w~I don't understand what I am supposed to be doing here.\n\n[BNK4_K:BANKJ4]\n~w~Look, it's easy. Haven't you ever seen a movie?\n\n[BNK4_L:BANKJ4]\n~w~We walk into the bank, we wave the gun around, and leave very rich men.\n\n[P_DEAD:BANKJ4]\n~r~Phil's dead!!\n\n[C_DEAD:BANKJ4]\n~r~Cam's dead!!\n\n[H_DEAD:BANKJ4]\n~r~Hilary's dead!!\n\n[P_HIND:BANKJ4]\n~r~You've lost Phil!\n\n[C_HIND:BANKJ4]\n~r~Cam's been left behind!\n\n[H_HIND:BANKJ4]\n~r~Hilary's been abandoned!\n\n[GETCAR:BANKJ4]\n~g~Get in the getaway car to do the bank job!\n\n[TRASHED:BANKJ4]\n~r~YOU TRASHED THE GETAWAY CAR!!\n\n[BNK4_1:BANKJ4]\nI'll drive.\n\n[BNK4_2:BANKJ4]\nGreat. A passenger. Wait 'til I tell the group about this.\n\n[BNK4_3A:BANKJ4]\nHey, watch the wheels, Tommy!\n\n[BNK4_3B:BANKJ4]\nTommy, Hilary's taking up too much room!\n\n[BNK4_3C:BANKJ4]\nI am not!\n\n[BNK4_3D:BANKJ4]\nAre too!\n\n[BNK4_3E:BANKJ4]\nHey, shut up you two, or you can get out and walk.\n\n[BNK4_3F:BANKJ4]\nYeah - HILARY.\n\n[BNK4_3I:BANKJ4]\nFor god's sake, Phil, stop waving that thing around!\n\n[BNK4_3J:BANKJ4]\nYeah, you'll have somebody's eye out!\n\n[BNK4_3M:BANKJ4]\nThe car's ruined. RUINED!\n\n[BNK4_3O:BANKJ4]\nYou cling to an illusion of permanence.\n\n[BNK4_3P:BANKJ4]\nWhat?\n\n[BNK4_3Q:BANKJ4]\nYou think all things will last.\n\n[BNK4_3R:BANKJ4]\nYouth, loved ones, pizza,\n\n[BNK4_3S:BANKJ4]\nAll will pass or end and you must accept that.\n\n[BNK4_3T:BANKJ4]\nYou're right. Thanks, Cam.\n\n[BNK4_3U:BANKJ4]\nDon't mention it.\n\n[BNK4_3V:BANKJ4]\nHey Tommy, why have we stopped?\n\n[BNK4_4A:BANKJ4]\n~w~Keep driving around the block, OK?\n\n[BNK4_5:BANKJ4]\n~w~Okay, Tommy, Okay.\n\n[BNK4_6:BANKJ4]\n~w~THIS IS A RAID!\n\n[BNK4_7:BANKJ4]\n~w~NOBODY MOVE!\n\n[BNK4_8:BANKJ4]\n~w~EVERYBODY UP AGAINST THAT WALL!\n\n[BNK4_9:BANKJ4]\nPhil, hold down the fort!\n\n[BNK4_10:BANKJ4]\nWilco roger that!\n\n[BNK4_11:BANKJ4]\nCome on Cam, the vault's upstairs...\n\n[BK4_12A:BANKJ4]\nDamn! It's a Flange 9000!\n\n[BK4_12B:BANKJ4]\nThis could take hours to crack,\n\n[BK4_12C:BANKJ4]\nOr five minutes if you could find the manager.\n\n[BNK4_13:BANKJ4]\nI'll go find where he's holed up.\n\n[BK4_14A:BANKJ4]\nPhil, things still sweet?\n\n[BNK4_15:BANKJ4]\nSure. Everything's reeaal quiet.\n\n[BNK4_16:BANKJ4]\nYou - you're coming with me!\n\n[BNK4_17:BANKJ4]\nOk! Ok! Just don't shoot!\n\n[BNK4_18:BANKJ4]\nI SAID NOBODY MOVE!\n\n[BK4_19A:BANKJ4]\nIt's on a time lock,\n\n[BK4_19B:BANKJ4]\nYou might as well give up now!\n\n[BK4_20A:BANKJ4]\nHell, I can bypass the time lock,\n\n[BK4_20B:BANKJ4]\nThen we just need your key code and we're good!\n\n[BNK4_21:BANKJ4]\nStay here. You try anything and you're dead.\n\n[BNK422A:BANKJ4]\nCam, how long?\n\n[BK4_23A:BANKJ4]\nGive me 5 minutes!\n\n[BK4_24A:BANKJ4]\nI'm gonna check on Phil, I'll be right back.\n\n[BK4_24B:BANKJ4]\nI told you not to touch that alarm!\n\n[BNK4_25:BANKJ4]\nThe SWAT team will be here any minute!\n\n[BNK4_27:BANKJ4]\nI could do with some help here, Tommy!\n\n[BNK4_28:BANKJ4]\nVice City S.W.A.T! You are completely surrounded!\n\n[BNK4_29:BANKJ4]\nSurrounded? HA HA HA HAAAAAaaa!\n\n[BNK4_30:BANKJ4]\nThey're crapping themselves, corrupt bastards!\n\n[BK4_31A:BANKJ4]\nTommy! The vault's open!\n\n[BK4_34A:BANKJ4]\nOk, we got the SWAT retirement fund. Let's get out of here!\n\n[BK4_34B:BANKJ4]\nOk, you asked for it! You've had your last chance!\n\n[BK4_35A:BANKJ4]\nThey're storming the place!\n\n[BK4_35B:BANKJ4]\nTake cover!\n\n[BNK4_94:BANKJ4]\n~w~Ok, guys. Nice an easy just as we planned.\n\n[BM_DEAD:BANKJ4]\n~r~You needed the bank manager alive!!\n\n[ASSET_A:BANKJ4]\nBANK HEIST ASSET COMPLETED!\n\n[ASSET_B:BANKJ4]\n~g~The Malibu Club will now generate revenue up to a maximum of $~1~ per day. Pick up your cash regularly!\n\n[IDIOT:BANKJ4]\n~r~ That's right, just wander about dressed like a lunatic and draw attention to yourself, IDIOT!\n\n{=================================== MISSION TABLE BARON1 ===================================}\n\n[COK1_A:BARON1]\nCome on, baby, go! Yeah! Yeah! Arrrrr!\n\n[COK1_B:BARON1]\nStupid horse! I'll chop your head off! Grrrrr...\n\n[COK1_C:BARON1]\nWho is this dickhead?\n\n[COK1_D:BARON1]\nTommy Vercetti. You remember me.\n\n[COK1_E:BARON1]\nExcuse me. I'm a little anxious. Never trust a goddamn horse!\n\n[COK1_F:BARON1]\nYou do a good job - you work for me now.\n\n[COK1_H:BARON1]\nAs I said, amigo, you work for me now. Shut up. Some Judas has betrayed me.\n\n[COK1_I:BARON1]\nHe thinks I don't know how much money I should be making, but stealing 3% is as good as stealing 100%.\n\n[COK1_J:BARON1]\nNo one does this to me. NO ONE!!\n\n[COK1_K:BARON1]\nYou follow him from his apartment and you see where he goes! Later, we will kill him.\n\n[COK1_1:BARON1]\nOoh shit!\n\n[COK1_2:BARON1]\nToo slow grandad!\n\n[COK1_4:BARON1]\nLoser.\n\n[COK1_5:BARON1]\nYou better keep on running, asshole!\n\n[COK1_8:BARON1]\n~g~Quick! Grab some wheels and follow him!\n\n[COK1_9:BARON1]\n~r~You're supposed to follow him, not kill him!\n\n[COK1_10:BARON1]\n~g~Go to the thief's house and find out where he's stashing the money.\n\n[COK1_11:BARON1]\n~g~Have a look through his window.\n\n[COK1_7:BARON1]\n~g~He's escaped to the roof, keep on his tail but don't kill him!\n\n[COK1_G:BARON1]\nI work for money.\n\n{=================================== MISSION TABLE BARON2 ===================================}\n\n[COK2_A:BARON2]\nWhat kind of incompetent fool are you?\n\n[COK2_B:BARON2]\nFOOL! FOOL! FOOL! FOOL!\n\n[COK2_C:BARON2]\nTommy!\n\n[COK2_D:BARON2]\nWhat, Ricardo?\n\n[COK2_E:BARON2]\nThese idiots - they always trying to screw you.\n\n[COK2_F:BARON2]\nThat's the problem with this business.\n\n[COK2_G:BARON2]\nWhat do you think you're doing?\n\n[COK2_H:BARON2]\nThese pricks have failed me miserably,\n\n[COK2_I:BARON2]\nSoon any mom and pop will think they can sell gallo in Vice City.\n\n[COK2_J:BARON2]\nWhat next, huh? The stinking Mafia?!\n\n[COK2_K:BARON2]\nThat gang place is a fortress at ground level,\n\n[COK2_L:BARON2]\nso Quentin here - Quentin! QUENTIN!\n\n[COK2_M:BARON2]\nHe'll fly you over the area!\n\n[COK2_N:BARON2]\nEradicate them!\n\n[COK2_O:BARON2]\nWhat do you think you're doing?\n\n[COK2_P:BARON2]\nWhat are you doing here?\n\n[COK2_Q:BARON2]\nHey, I've been asking around and it's obvious\n\n[COK2_R:BARON2]\nthat Diaz jumped the deal and iced my brother.\n\n[COK2_S:BARON2]\nAnd he'll kill you, too!\n\n[COK2_T:BARON2]\nI can take Diaz!\n\n[COK2_U:BARON2]\nNo - listen to me! I'll handle Diaz -\n\n[COK2_1:BARON2]\nOne thing puzzling me, What's with 'Quentin!?\n\n[COK2_2:BARON2]\nI dunno, I always kinda liked it...Quentin Vance...\n\n[COK2_3:BARON2]\nVance? Your name's Lance Vance?\n\n[COK2_4:BARON2]\nHey! I got enough of that at school!\n\n[COK2_5:BARON2]\nYou ever fired one of those from a whirly?\n\n[COK2_8:BARON2]\nWhere the hell are we headed anyway?\n\n[COK2_9:BARON2]\nPrawn Island.\n\n[COK2_13:BARON2]\nLance Vance. Poor bastard.\n\n[COK2_14:BARON2]\nOk, we're almost there.\n\n[COK2_15:BARON2]\nWe'll make a couple of passes.\n\n[COK2_16:BARON2]\nSo take out as many guns as you can.\n\n[COK2_17:BARON2]\nThen I'll set you down and you're on your way.\n\n[COK2_20:BARON2]\nDamn! This is a war zone! Take out some of those gunmen!\n\n[COK2_21:BARON2]\nWe're taking hits here, man!\n\n[COK2_22:BARON2]\nThis thing ain't cheap to fix! Take them out!\n\n[COK2_23:BARON2]\nOk, you're on your own from here! Good luck, brother!\n\n[COK2_24:BARON2]\nHeli Health:\n\n[COK2_25:BARON2]\n~g~Go and collect the money on the roof.\n\n[COK2_27:BARON2]\nYou're on MY turf asshole!\n\n[COK2_28:BARON2]\nYou're going down!\n\n[COK2_6:BARON2]\nNo. I'll get a bit of practice on the way though.\n\n[OPEN_B:BARON2]\nThe road blocks to the mainland have now been removed\n\n[COK2_V:BARON2]\n- he's beginning to trust me.\n\n{=================================== MISSION TABLE BARON3 ===================================}\n\n[COK3_A:BARON3]\nNot so pleased with your selves NOW, huh!\n\n[COK3_B:BARON3]\nAhahahahaa, Ahahahahaa.\n\n[COK3_C:BARON3]\nWhoa! Watch where you're waving that thing!\n\n[COK3_D:BARON3]\nNo more pigeon shit on MY car, eh Tommy!\n\n[COK3_E:BARON3]\nGuess not.\n\n[COK3_F:BARON3]\nYou're damn right. Now listen,\n\n[COK3_G:BARON3]\nyou know who owns the fastest boat on the east coast?\n\n[COK3_H:BARON3]\nNot off hand, no.\n\n[COK3_I:BARON3]\nME. And I want it to stay that way.\n\n[COK3_J:BARON3]\nEvery smuggler from here to Caracas has one dream, a faster boat.\n\n[COK3_K:BARON3]\nRumor has it the boatyard has just completed such a vessel.\n\n[COK3_L:BARON3]\nfor some Costa Rican dickhead.\n\n[COK3_M:BARON3]\nAnd Tommy...I WANT THAT BOAT!!!\n\n[COK3_N:BARON3]\nI think your pigeons are back.\n\n[COK3_O:BARON3]\nAh! I thought I got you. Where'd you come from?\n\n[COK3_P:BARON3]\nPigeons! Boom! Aaaaah!\n\n[COK3_5:BARON3]\n~g~Find the switch to lower the boat.\n\n[COK3_6:BARON3]\n~g~Get the boat to the mansion.\n\n[COK3_7:BARON3]\n~r~You destroyed the boat!\n\n[COK3_8:BARON3]\n~g~Go to the boatyard at the docks and steal the fastest boat.\n\n[COK3_9:BARON3]\n~g~Now get into the boat.\n\n{=================================== MISSION TABLE BARON4 ===================================}\n\n[COK4_A:BARON4]\nEject! PLASTIC CRAP!\n\n[COK4_B:BARON4]\nYou doing this to me?\n\n[COK4_C:BARON4]\nWho do you think you are, you piece of plastic SHIT? Aaarrgh!\n\n[COK4_D:BARON4]\nSCREW YOU!\n\n[COK4_E:BARON4]\nIt eats my favorite El burro movie, it die!\n\n[COK4_F:BARON4]\nWhat else could I do?\n\n[COK4_G:BARON4]\nIt's probably not plugged in.\n\n[COK4_H:BARON4]\nWhat?\n\n[COK4_I:BARON4]\nDamn - no matter, I can buy a hundred more.\n\n[COK4_J:BARON4]\nNow Tommy,\n\n[COK4_K:BARON4]\neach month a freelancer sails into Vice City and moors his yacht.\n\n[COK4_L:BARON4]\nHe sells his cargo to the first boat.\n\n[COK4_M:BARON4]\nI want you to take the speedboat\n\n[COK4_N:BARON4]\nand beat all the other shitheads to it,\n\n[COK4_O:BARON4]\nthen you bring the cargo here, ok!?\n\n[COK4_P:BARON4]\nLet me guess, you thought I could use a guardian angel.\n\n[COK4_Q:BARON4]\nI'm just saying you need to let me in there, my man.\n\n[COK4_T:BARON4]\nand you're probably gonna wanna kiss me!\n\n[COK4_U:BARON4]\nWacko.\n\n[COK4_V:BARON4]\nHahahahahaha!\n\n[COK4_1:BARON4]\nSo Tommy, we know it was Diaz busted our deal..\n\n[COK4_3:BARON4]\nSo why the hell are we running errands for him?\n\n[COK4_4:BARON4]\nThe more we learn now, the less we have to learn when we take this town over!\n\n[COK4_5:BARON4]\nI like your style, man. Real fresh.\n\n[COK4_12:BARON4]\nWatch yourself, they're coming from all over!\n\n[COK4_13:BARON4]\nGot 'em. Head for Diaz's as fast as you can!\n\n[COK4_14:BARON4]\nYou want some of this?!\n\n[COK4_15:BARON4]\nSleep with the fish!\n\n[COK4_16:BARON4]\nEat it! EAT IT!\n\n[COK4_19:BARON4]\nMore trouble up ahead!\n\n[COK4_20:BARON4]\nThere are gunmen on that jetty!\n\n[COK4_24:BARON4]\nGood shooting, my friend. You're a real, proper, grade A lunatic.\n\n[COK4_25:BARON4]\nWell, thank you.\n\n[COK4_26:BARON4]\nSee you around, Tommy.\n\n[COK4_27:BARON4]\nOkay, Mr. Lance Vance Dance.\n\n[COK4_28:BARON4]\n~g~Get to the yacht before the other boats do!\n\n[COK4_31:BARON4]\n~g~Go to the fastest boat at the jetty!\n\n[COK4_32:BARON4]\n~r~Too slow!\n\n[COK4_33:BARON4]\n~r~You destroyed the boat!\n\n[COK4_34:BARON4]\n~g~Take those boats out!\n\n[COK4_35:BARON4]\nBoat health:\n\n[COK4_R:BARON4]\nNow you can feed me all this 'lonely tough guy' crap,\n\n[COK4_S:BARON4]\nbut I know one day I'm gonna save your ass,\n\n{=================================== MISSION TABLE BARON5 ===================================}\n\n[PROP_A:BARON5]\nPROPERTY ACQUIRED!\n\n[COK4_30:BARON5]\n~r~Lance is dead!\n\n[ASS1_A:BARON5]\nI got us some cannons in the trunk.\n\n[ASS1_B:BARON5]\nHoly shit! Where'd you get all this stuff?\n\n[ASS1_C:BARON5]\nBeen saving it for a rainy day.\n\n[ASS1_D:BARON5]\nYou like?\n\n[ASS1_E:BARON5]\nYeah, I like.\n\n[ASS1_F:BARON5]\nYou stupid pricks...\n\n[ASS1_G:BARON5]\nmy beautiful house\n\n[ASS1_H:BARON5]\nlook what you've done to it!\n\n[ASS1_I:BARON5]\nThis is for my brother!\n\n[ASS1_J:BARON5]\nI trusted you, Tommy.\n\n[ASS1_K:BARON5]\nI woulda had you made...\n\n[ASS1_L:BARON5]\nSay goodnight, Mr. Diaz.\n\n[ASS1_1:BARON5]\nThis place is going to be crawling with assholes...be careful...\n\n[ASS1_2:BARON5]\nDon't worry Tommy, I'll cover you.\n\n[ASS1_13:BARON5]\nDIAZ?! I've come to take over your business!\n\n[ASS1_15:BARON5]\n~g~Storm the mansion and kill Diaz!\n\n[ASS1_16:BARON5]\n~g~Kill Diaz!\n\n[ASS1_17:BARON5]\n~g~There are multiple routes into the mansion.\n\n[BUD1:BARON5]\nLances Health:\n\n[ASS1_18:BARON5]\n~g~The door is locked, try another route.\n\n[ASS1_19:BARON5]\nThis way!\n\n[ASS1_14:BARON5]\nTOMMY! You betrayed me, you idiot! I'm gonna kill you real soon..\n\n[ASS1_20:BARON5]\nTommy, my problem with Quentin, not wit you, man!\n\n{=================================== MISSION TABLE BIKE1 ===================================}\n\n[BM1_A:BIKE1]\nWhere's Baker?\n\n[BM1_B:BIKE1]\nI'm looking for Big Mitch Baker...\n\n[BM1_C:BIKE1]\nWho's lookin'?\n\n[BM1_D:BIKE1]\nTommy Vercetti.\n\n[BM1_E:BIKE1]\nVercetti\n\n[BM1_F:BIKE1]\nYou don't look like the law, so that's bought you a minute.\n\n[BM1_G:BIKE1]\nYou better talk fast.\n\n[BM1_H:BIKE1]\nKent Paul said you might be interested in pulling security for a gig he's got set up.\n\n[BM1_I:BIKE1]\nKent Paul? Sheesh! No wonder he sent ya.\n\n[BM1_J:BIKE1]\nThe last time he was here he left through the window in nothing but his limey birthday suit.\n\n[BM1_K:BIKE1]\nAre you interested or not?\n\n[BM1_L:BIKE1]\nWe only do favors for our own.\n\n[BM1_M:BIKE1]\nHow do I join?\n\n[BM1_N:BIKE1]\nThis ain't no country club, boy. Can you handle a bike?\n\n[BM1_O:BIKE1]\nCan you sit on a stool and drink?\n\n[BM1_P:BIKE1]\nCougar, Zeppelin, go see how this girl handles a bike...\n\n[BM1_3:BIKE1]\n~r~The racers have been attacked!\n\n[BIKE1_1:BIKE1]\nAll right, fancy clothes. Let's see what you can do.\n\n[BM1_1:BIKE1]\n~g~Get a Freeway or an Angel and get to the starting grid.\n\n[BM1_2:BIKE1]\n~g~You need a Freeway or an Angel to compete!\n\n{=================================== MISSION TABLE BIKE2 ===================================}\n\n[BM2_1:BIKE2]\nCHAOSMETER:\n\n[BM2_A:BIKE2]\nAh, got ya again.\n\n[BM2_B:BIKE2]\nHey Vercetti.\n\n[BM2_C:BIKE2]\nCougar says you can handle a bike pretty good.\n\n[BM2_D:BIKE2]\nYeah, how many more errands am I gonna to have to run?\n\n[BM2_E:BIKE2]\nI'm a very busy man.\n\n[BM2_F:BIKE2]\nIf it's a fight that's gonna settle this then bring it on.\n\n[BM2_G:BIKE2]\nBeing one of us ain't just about brawlin'. It's about being part of a family.\n\n[BM2_H:BIKE2]\nYeah, I've been part of a family before alright. It didn't work out.\n\n[BM2_I:BIKE2]\nYeah, right, but this family takes care of its own.\n\n[BM2_J:BIKE2]\nWe don't ask a man to do the dirty work and then let him do fifteen years hard time.\n\n[BM2_K:BIKE2]\nYeah, that's right. I've done my homework.\n\n[BM2_L:BIKE2]\nThis here's the biggest family of misfits, outcasts and badasses.\n\n[BM2_M:BIKE2]\nHell, some of us has even been betrayed by our own country.\n\n[BM2_N:BIKE2]\nI was locked up during 'Nam. Ugly business.\n\n[BM2_O:BIKE2]\nWhich is why I'm gonna ask you to go mess with the man.\n\n[BM2_Q:BIKE2]\nSo get out there, grab a bike and show this city how pissed you are!\n\n[BM2_R:BIKE2]\nAlright, alright.\n\n[BM2_3:BIKE2]\n~g~This sound indicates that you have filled a part of the meter, continue to do so.\n\n[BM2_2:BIKE2]\n~g~You must fill the Chaos Meter in the time given to show us how much of a badass you are!\n\n[BM2_4:BIKE2]\n~r~You failed to fill the Chaos Meter in time!\n\n[BM2_P:BIKE2]\nThis whole damn country needs a kick in the ass, and we're the ones to deliver it.\n\n{=================================== MISSION TABLE BIKE3 ===================================}\n\n[BM3_A:BIKE3]\nHey there, Mitch.\n\n[BM3_B:BIKE3]\nWell, if it ain't 'bad ass' Vercetti.\n\n[BM3_C:BIKE3]\nNow I wanna see how good you can fight for your patch.\n\n[BM3_D:BIKE3]\nA local street gang made the mistake of stealing my hog...\n\n[BM3_E:BIKE3]\nprobably because of some machismo thing or somethin'.\n\n[BM3_F:BIKE3]\nMe and the boys would go over there and teach them a lesson in respect an'all.\n\n[BM3_G:BIKE3]\nAnyways.\n\n[BM3_H:BIKE3]\nThen I got to thinking - this would make a good initiation for you.\n\n[BM3_I:BIKE3]\nYou get my bike back, you can tell Paul he's got his security.\n\n[BM3_2:BIKE3]\n~r~You were supposed to bring the bike back, not destroy it!\n\n[BM3_3:BIKE3]\n~g~Get the bike back to the bar!\n\n[BM3_4:BIKE3]\n~g~Get on the bike!\n\n[INTRUDE:BIKE3]\n~g~You've been spotted!\n\n[BM3_6:BIKE3]\n~g~They are holed up behind Ammu-Nation in the Downtown area.\n\n[BM3_7:BIKE3]\n~g~You will need a fast bike to gain access to the roof.\n\n[BM3_8:BIKE3]\n~g~Use the bike to jump from these stairs to the roof on the far side of the road.\n\n[BM3_1:BIKE3]\n~g~A local gang has stolen Mitch Baker's Angel. Get it back!\n\n[BM3_9:BIKE3]\n~g~Get Mitch's Angel and get out of there!\n\n{=================================== MISSION TABLE BMX_1 ===================================}\n\n[GETBIK2:BMX_1]\n~r~You have ~w~~1~ seconds ~g~to get on a Dirt Bike!\n\n{=================================== MISSION TABLE BOATBUY ===================================}\n\n[DRUG_2:BOATBUY]\nPut it out. There's a dude here.\n\n[DRUG_3:BOATBUY]\nHey suit dude! I guess you're the new owner?\n\n[DRUG_4:BOATBUY]\nYeah. Which one of the boats is the fastest?\n\n[DRUG_5:BOATBUY]\nIt's already in the water, dude,\n\n[DRUG_6:BOATBUY]\nI though you might want to try her out.\n\n[DRUG_7:BOATBUY]\nDude, she's already running with a 300 horse power engine...\n\n[DRUG_8:BOATBUY]\n...and the fiberglass hull, she just shoots through the waves.!\n\n[DRUG_9:BOATBUY]\nShe can do like zero to sixty in four seconds flat dude...\n\n[DRUG_10:BOATBUY]\nand she can hold like twenty bales of the best Jamaican smoke right in the hull!\n\n[DRUG_11:BOATBUY]\nSo go ahead dude, she's ready to fly!\n\n[DRUG_12:BOATBUY]\nYo yo, uh, suit dude, you gotta light?\n\n[DRUG_1:BOATBUY]\nHello? Hel-lo?! Hello?\n\n[DRUG_13:BOATBUY]\nDude?\n\n{=================================== MISSION TABLE CAP_1 ===================================}\n\n[CAP1_B1:CAP_1]\n~g~The Mafia is taxing your businesses. Find them and kill them.\n\n[CAP1_B2:CAP_1]\n~g~The Mafia has taxed the Boatyard!\n\n[CAP1_B3:CAP_1]\n~g~The Mafia has taxed the Ice Cream Factory!\n\n[CAP1_B4:CAP_1]\n~g~The Mafia has taxed the Car Showroom!\n\n[CAP1_B5:CAP_1]\n~g~The Mafia has taxed the Taxi Firm!\n\n[CAP_01:CAP_1]\nOk, what's the emergency?\n\n[CAP_02:CAP_1]\nWHO?\n\n[CAP_03:CAP_1]\nTommy...some mob thugs ...said they'd come to take their cut...\n\n[CAP_04:CAP_1]\n...said it was a Mr. Forello's money...I feel like crap.\n\n[CAP_05:CAP_1]\nForelli? SONNY Forelli?\n\n[CAP_06:CAP_1]\nYeah, that's the guy...I think...they were very insistent...\n\n[CAP_07:CAP_1]\nDon't you worry, pop, I'm not angry with you.\n\n[CAP_08:CAP_1]\nGet him to the hospital.\n\n[CAP_09:CAP_1]\nTommy...rip that guy a new asshole for me...\n\n[CAP_10:CAP_1]\nI'm gonna rip him two!\n\n[CAP1_2:CAP_1]\nYou know the rules, Vercetti!\n\n[CAP1_3:CAP_1]\nMr. Forelli sends his regards!\n\n[CAP1_4:CAP_1]\nIt's the Harwood Butcher!\n\n[CAP1_5:CAP_1]\nYou tell Sonny - stay away!\n\n[CAP1_6:CAP_1]\nVice City is MINE now, NOT his.\n\n[CAP1_7:CAP_1]\nYou think you can take me down, Vercetti?\n\n[CAP1_8:CAP_1]\nWe'll keep coming after you until you die, Vercetti.\n\n[CAP1_9:CAP_1]\nYou don't stand a chance, you psychotic prick.\n\n[CAP1_10:CAP_1]\nI'll murder you Vercetti.\n\n[CAP1_11:CAP_1]\nYou always were a jerk.\n\n[CAP1_12:CAP_1]\nYou're going to die, Vercetti.\n\n[CAP1_B6:CAP_1]\n~g~You have found the collector, kill him.\n\n[CAP1_B7:CAP_1]\n~g~You've lost the collector.\n\n[CAP1_B8:CAP_1]\n~r~The collector has taxed all of your businesses.\n\n[CAP1_B9:CAP_1]\n~g~The mafia has taxed The Malibu!\n\n[CAP1_B0:CAP_1]\n~g~The mafia has taxed the film studio!\n\n[CAP1_C2:CAP_1]\n~g~The Mafia has arrived at the Boatyard!\n\n[CAP1_C3:CAP_1]\n~g~The Mafia has arrived at the Ice Cream Factory!\n\n[CAP1_C4:CAP_1]\n~g~The Mafia has arrived at the Car Showroom!\n\n[CAP1_C5:CAP_1]\n~g~The Mafia has arrived at the Taxi Firm!\n\n[CAP1_C9:CAP_1]\n~g~The Mafia has arrived at The Malibu!\n\n[CAP1_C0:CAP_1]\n~g~The Mafia has arrived at the film studio!\n\n[CAP1_D2:CAP_1]\n~g~The Mafia is leaving the Boatyard!\n\n[CAP1_D3:CAP_1]\n~g~The Mafia is leaving the Ice Cream Factory!\n\n[CAP1_D4:CAP_1]\n~g~The Mafia is leaving the Car Showroom!\n\n[CAP1_D5:CAP_1]\n~g~The Mafia is leaving the Taxi Firm!\n\n[CAP1_D9:CAP_1]\n~g~The Mafia is leaving The Malibu!\n\n[CAP1_D0:CAP_1]\n~g~The Mafia is leaving the film studio!\n\n[CAP1B10:CAP_1]\nYou've capped the Collectors. More are on their way.\n\n{=================================== MISSION TABLE CARBUY ===================================}\n\n[CAR1_1:CARBUY]\nB.J. Smith. And you must be Mr. Vercetti.\n\n[CAR1_2:CARBUY]\nWould you like the tour?\n\n[CAR1_3:CARBUY]\nMight as well.\n\n[CAR1_4:CARBUY]\nWell, I'm very sad to be selling the dealership to y'all.\n\n[CAR1_5:CARBUY]\nThis was my first investment after I turned pro.\n\n[CAR1_6:CARBUY]\nBut now it's time for me to move on.\n\n[CAR1_7:CARBUY]\nYou're leaving town?\n\n[CAR1_8:CARBUY]\nNot in too much of a hurry, I hope?\n\n[CAR1_9:CARBUY]\nNo. I'm just coming out of retirement, and preparing for my future comeback.\n\n[CAR1_10:CARBUY]\nThe business wasn't too strong,\n\n[CAR1_11:CARBUY]\nand my staff took it upon themselves to get a bit more\n\n[CAR1_12:CARBUY]\ncreative with the generation of wealth.\n\n[CAR1_13:CARBUY]\nObviously, I could wind down the business before I hand it over.\n\n[CAR1_14:CARBUY]\nHell, I could burn the place down if I wanted to.\n\n[CAR1_15:CARBUY]\nThis is prime development land.\n\n[CAR1_16:CARBUY]\nOh, I wouldn't worry about any of that.\n\n[CAR1_17:CARBUY]\nThis place seems perfect.\n\n[CAR1_18:CARBUY]\nYeh it does, So I take it we have a deal?\n\n{=================================== MISSION TABLE CARPAR1 ===================================}\n\n[MM_1_A:CARPAR1]\n~g~Collect ~y~5 checkpoints~r~ WITHOUT ~g~smashing any ~r~CONES! ~g~You may collect checkpoints in ~y~ANY ORDER.\n\n[CONE_1:CARPAR1]\n~r~You smashed a cone!!\n\n[MM_1_C:CARPAR1]\n~y~PASS THROUGH~g~ a checkpoint to start the timer. ~g~Each checkpoint will credit you with ~y~~1~ SECONDS~g~.\n\n{=================================== MISSION TABLE COPCAR ===================================}\n\n[KILLS:COPCAR]\nKILLS:\n\n[C_BREIF:COPCAR]\n~g~Suspect last seen in the ~a~ area.\n\n[COPCART:COPCAR]\n~g~You have ~1~ seconds to return to a police vehicle before the mission ends.\n\n[C_CANC:COPCAR]\n~r~Vigilante mission cancelled!\n\n[C_TIME:COPCAR]\n~r~Your time as a law enforcer is over!\n\n[C_COMP1:COPCAR]\nVigilante mission level 12 complete: Your max Body Armor increased to 150\n\n[CLEVEL:COPCAR]\nVigilante Mission Level ~1~\n\n[C_PASS:COPCAR]\nTHREAT ELIMINATED: $ ~1~\n\n{=================================== MISSION TABLE COUNT1 ===================================}\n\n[CM1_A:COUNT1]\nMr. Vercetti? Hey. You bought the old print works?\n\n[CM1_B:COUNT1]\nYeah, my old man used to work on these.\n\n[CM1_C:COUNT1]\nI was going to follow him in his trade, but...I lived a different life.\n\n[CM1_D:COUNT1]\nYou planning on selling the old machinery, breaking it down?\n\n[CM1_E:COUNT1]\nI'm thinking we might print something - a newspaper, a magazine...\n\n[CM1_F:COUNT1]\nOh, crap, sonny, low grade crap. I've always fancied printing money. It ain't too hard.\n\n[CM1_G:COUNT1]\nYou know, I've been doing it on a small scale for years.\n\n[CM1_H:COUNT1]\nReally?\n\n[CM1_I:COUNT1]\nSure. But we'd need some good quality plates.\n\n[CM1_J:COUNT1]\nOf course! There's a counterfeiting syndicate already operating in Florida.\n\n[CM1_K:COUNT1]\nA syndicate?\n\n[CM1_L:COUNT1]\nYeah. Just rumors is all I've heard.\n\n[CM1_M:COUNT1]\nI know a man who's good with rumors...\n\n[CM1_N:COUNT1]\nI used to spend the evenings with him, cleaning the rollers...\n\n[CM1_2A:COUNT1]\nLook at the arse on that!\n\n[CM1_2B:COUNT1]\nAwright girl, it's your loss mate init!\n\n[CM1_2C:COUNT1]\nAwright me ol'china, how's it hangin'?\n\n[CM1_2D:COUNT1]\nWhat do you know about counterfeiting?\n\n[CM1_2E:COUNT1]\nOh I'm fine Paul, how 'bout you?\n\n[CM1_2F:COUNT1]\nCome 'ere!\n\n[CM1_2G:COUNT1]\nAwright! Awright! Awright!! You're obviously a busy man.\n\n[CM1_2H:COUNT1]\nAll I know about dodgy readys is the Triads supply the plates.\n\n[CM1_2I:COUNT1]\nThey've got a shipping company down the docks,\n\n[CM1_2J:COUNT1]\nthe boss man would know when the plates are coming in next!\n\n[CM1_2K:COUNT1]\nThanks Paul.\n\n[CM1_2L:COUNT1]\nWhat's the matter with you, you maniac!\n\n[CM1_2M:COUNT1]\nGive me another drink, lively!\n\n[CM1_3:COUNT1]\n~g~You've been spotted!\n\n[CM1_5:COUNT1]\n~g~Go and meet Kent Paul at the Malibu Club!\n\n[CNT1_1:COUNT1]\nWho are you? Oooof! Aaiieee! Not the face! Not the face!\n\n[CM1_1:COUNT1]\n~g~Go to the Chartered Libertine Lines boat at the docks.\n\n[CM1_2:COUNT1]\n~g~The Shipping Officer will have the information that is required.\n\n[CNT1_2:COUNT1]\nOk, I talk! I talk!\n\n[CM1_6:COUNT1]\n~g~Get the information back to the Print Works!\n\n{=================================== MISSION TABLE COUNT2 ===================================}\n\n[CNT2_B1:COUNT2]\nAlright, the courier's moving the plates from the docks today.\n\n[CNT2_B2:COUNT2]\nI'm gonna go intercept them, grab the plates, lose any heat, and make my way back here.\n\n[CNT2_B3:COUNT2]\nNow. Depending how well this goes,\n\n[CNT2_B4:COUNT2]\nwe may have five minutes to print the money before the counterfeit syndicate finds us, or we may have all year.\n\n[CNT2_B5:COUNT2]\nEither way, I want green rolling off the presses five minutes after I get back. Got it?\n\n[CNT2_B6:COUNT2]\nDon't you worry Tommy. We'll be ready.\n\n[CNT2_B7:COUNT2]\nMe an'the boys will be around in the neighborhood case you need any heat taken care of.\n\n[CNT2_B8:COUNT2]\nAll right, everybody cool? All right. I'll catch you later...\n\n[CNT2_01:COUNT2]\n~g~The counterfeit plates ~y~courier~g~ is arriving at the ~r~docks~g~ in a helicopter any second now.\n\n[CNT2_02:COUNT2]\n~r~The plates courier has fled in the helicopter.\n\n[CNT2_03:COUNT2]\n~r~The courier has arrived at his destination safely, you're too late!\n\n[CNT2_04:COUNT2]\n~r~You destroyed the plates in the explosion!\n\n[CNT2_05:COUNT2]\n~g~You have the counterfeit plates. Take them to the print works.\n\n[CNT2_06:COUNT2]\n~g~The courier has died and dropped the plates, get to them before anyone else.\n\n[CNT2_07:COUNT2]\n~g~One of the guards has picked up the plates, don't let 'em get away.\n\n[CNT2_08:COUNT2]\n~g~The ~r~courier~g~ with the plates has arrived at the docks.\n\n[CNT2_4:COUNT2]\nPrivate business. You're not welcome!\n\n[CNT2_09:COUNT2]\nPRINT WORKS ASSET COMPLETED\n\n[CNT2_10:COUNT2]\n~g~The print works will now generate revenue up to a maximum of $~1~. Make sure you collect it regularly.\n\n[CNT2_11:COUNT2]\n~r~The plates are at the bottom of the sea!\n\n{=================================== MISSION TABLE CUBAN1 ===================================}\n\n[CUB1_A:CUBAN1]\nSi, men?\n\n[CUB1_B:CUBAN1]\nHey, easy Papi, this man's for me. You, you the boy?\n\n[CUB1_C:CUBAN1]\nOh yeh. You the boy. I think so, you know?\n\n[CUB1_D:CUBAN1]\nNo. I don't think I do.\n\n[CUB1_E:CUBAN1]\nOh yeah? You come here, tough guy.\n\n[CUB1_F:CUBAN1]\nYou think you can take me on?\n\n[CUB1_G:CUBAN1]\nYou think you can play stupid with me?\n\n[CUB1_H:CUBAN1]\nNo, I think you're playing plenty stupid enough for both of us.\n\n[CUB1_I:CUBAN1]\nHey, he call you dumb, son.\n\n[CUB1_J:CUBAN1]\nAnd I call him a little girl, Papi.\n\n[CUB1_K:CUBAN1]\nLook at him, all dressed up like that.\n\n[CUB1_L:CUBAN1]\nWhat is this, ladies night?\n\n[CUB1_M:CUBAN1]\nYou some kind of tough guy, you dress like a woman?\n\n[CUB1_N:CUBAN1]\nYou got on panties like a woman too, huh?\n\n[CUB1_O:CUBAN1]\nWhat you got against women? You prefer men, big boy?\n\n[CUB1_P:CUBAN1]\nI like women! I like all women! I love my mother, chico!\n\n[CUB1_Q:CUBAN1]\nAlright, alright, I'll take your word for it. Relax.\n\n[CUB1_R:CUBAN1]\nCan you drive, amigo?\n\n[CUB1_S:CUBAN1]\nYeah... like a woman.\n\n[CUB1_T:CUBAN1]\nVery funny. I like you, big boy. Maybe you can help.\n\n[CUB1_U:CUBAN1]\nMaybe you can prove you a man. Huh?\n\n[CUB1_V:CUBAN1]\nTake out the boat.\n\n[CUB1_W:CUBAN1]\nShow me you got some big cojones,\n\n[CUB1_X:CUBAN1]\nand not some little bitty chiquita ones.\n\n[CUB1_02:CUBAN1]\nOk man, treat her like a woman.\n\n[CUB1_03:CUBAN1]\nNot bad, you're a real man.\n\n[CUB1_04:CUBAN1]\nYou got real big cojones, amigo.\n\n[CUB1_05:CUBAN1]\nAmigo, you a man, man.\n\n[CUB1_06:CUBAN1]\nCall yourself a man, man?\n\n[CUB1_07:CUBAN1]\nYou a little scaredy kitten, baby boy, go cry to your mommy!\n\n[CUB1_09:CUBAN1]\nMan, you the man, man. I like you, man. I like you a lot.\n\n[CUB1_10:CUBAN1]\nAny time, man. 'cause you got cojones. And all my friends have big cojones.\n\n[CUB1_11:CUBAN1]\n~r~You Killed Rico!\n\n[CUB1_12:CUBAN1]\nGo through the first checkpoint to begin the test.\n\n[CUB1_14:CUBAN1]\nGet back in the boat!\n\n[CUB1_15:CUBAN1]\n~r~You are too slow, man.\n\n[CUB1_01:CUBAN1]\nHey, I'm Rico. You the man with the big cojones?\n\n[CUB1_13:CUBAN1]\n~g~You have three minutes to get round the course.\n\n[CUB1_08:CUBAN1]\nYou a big waste of space. Walk like a man, talk like a man, but you drive like an idiot.\n\n{=================================== MISSION TABLE CUBAN2 ===================================}\n\n[CUB2_A:CUBAN2]\nUn cafecito, por favor, Alberto..\n\n[CUB2_N:CUBAN2]\nNo problema, Tommy.\n\n[CUB2_B:CUBAN2]\nPapi! Una grande problema!\n\n[CUB2_O:CUBAN2]\nUmberto my son, what happened?\n\n[CUB2_C:CUBAN2]\nThe Haitians! I hate these Haitians!\n\n[CUB2_D:CUBAN2]\nThey mess with me for the last time!\n\n[CUB2_E:CUBAN2]\nThese Hai - these Haitians! We take 'em out!\n\n[CUB2_F:CUBAN2]\nOnly we need some backup.\n\n[CUB2_H:CUBAN2]\nAmigo, you drive good!\n\n[CUB2_I:CUBAN2]\nFor a woman. Right?\n\n[CUB2_J:CUBAN2]\nThis is no time for joking!\n\n[CUB2_K:CUBAN2]\nCome on, drive for me again!\n\n[CUB2_L:CUBAN2]\nTake my boys over there, and then we'll take these Haitians down!\n\n[CUB2_01:CUBAN2]\nNot enough room, man, you need a bigger car.\n\n[CUB2_02:CUBAN2]\nWe need reinforcements from the cafe!\n\n[CUB2_03:CUBAN2]\n~g~Get a car and pick up the Cubans from outside Robina's Cafe.\n\n[CUB2_04:CUBAN2]\n~g~Go and drop the Cubans off at the fight.\n\n[CUB2_05:CUBAN2]\nTake out that cowardly sniper!\n\n[CUB2_07:CUBAN2]\nThey fight like girls! Take cover!\n\n[CUB2_09:CUBAN2]\nSniper on the roof!\n\n[CUB2_11:CUBAN2]\n~r~You fool, we needed that car.\n\n[CUB2_12:CUBAN2]\nHey amigo! Good to see you could make it!\n\n[CUB2_13:CUBAN2]\nStinking nest of Haitians, we gonna kill 'em all!\n\n[CUB2_14:CUBAN2]\nCHAAAAAARGE!\n\n[CUB2_15:CUBAN2]\nNow, my brothers, CHAAARRRGGEE!!\n\n[CUB2_16:CUBAN2]\nTommy, we have proved our manful bravery!\n\n[CUB2_17:CUBAN2]\nLet us steal the van full of drugs and make good our escape!\n\n[CUB2_18:CUBAN2]\n~g~Get a car and pick up the Cubans\n\n[CUB2_19:CUBAN2]\nWe gonna fight like men!\n\n[CUB2_21:CUBAN2]\nFight like men with huge cojones!\n\n[CUB2_22:CUBAN2]\n~g~ Finish off the rest of the Haitians so the Cubans can move forward.\n\n[CUB2_23:CUBAN2]\n~g~ Little Haiti will be swarming with Haitians trying to even the score with the Cubans. Watch your back.\n\n[CUB2_24:CUBAN2]\n~g~Return to Robina's Cafe with the Van and park it round the back.\n\n[CUB2_25:CUBAN2]\nKILL ALL THE HAITIANS!!\n\n[CUB2_G:CUBAN2]\nI lost a few hermanos already out there.\n\n[CUB2_M:CUBAN2]\nThey mess with me, they mess with the biggest boy in town!\n\n{=================================== MISSION TABLE CUBAN3 ===================================}\n\n[CUB3_B:CUBAN3]\nPoppa, don't serve this snake in the straw.\n\n[CUB3_C:CUBAN3]\nYou're two-faced, Tommy!\n\n[CUB3_E:CUBAN3]\nThe Haitians, man. They're laughing at me!\n\n[CUB3_G:CUBAN3]\nThey're laughing at me, Tommy. At me!\n\n[CUB3_I:CUBAN3]\nNobody does whatever they like, Umberto, they do what you let them do.\n\n[CUB3_J:CUBAN3]\nWhat?\n\n[CUB3_K:CUBAN3]\nYou want somebody taken care of?\n\n[CUB3_L:CUBAN3]\nI can handle it, but it's gonna cost you.\n\n[CUB3_M:CUBAN3]\nI know we're brothers and all, but this is business.\n\n[CUB3_N:CUBAN3]\nTommy. You a real man. Businessman, a gentleman.\n\n[CUB3_O:CUBAN3]\nThese Haitians. They have a load of product coming in off shore, really good stuff.\n\n[CUB3_P:CUBAN3]\nWe take it, and we finish them.\n\n[CUB3_Q:CUBAN3]\nYou take it, and I look after you. Like my brother. Like my son.\n\n[CUB3_R:CUBAN3]\nI think I prefer the cash to being bounced on your knee, amigo.\n\n[CUB3_01:CUBAN3]\nHey Rico. Nice boat, you ready?\n\n[CUB3_03:CUBAN3]\n~g~Collect all the briefcases filled with the drugs and cash.\n\n[CUB3_04:CUBAN3]\n~g~Get the drugs and cash back to Umberto.\n\n[CUB3_05:CUBAN3]\nSi Tommy. Now you be a good shot today,\n\n[CUB3_06:CUBAN3]\nMy boat, she no good full of holes, ok?\n\n[CUB3_07:CUBAN3]\n~g~ Go meet Rico. He'll drive you to the meet location.\n\n[CUB3_02:CUBAN3]\n~g~KILL ALL THE HAITIANS ON THE BOATS!!\n\n[CUB3_08:CUBAN3]\nUh oh.. Pack of Cubans. We under attack!\n\n[CUB3_A:CUBAN3]\nAlberto. Una cafe, senor.\n\n[CUB3_D:CUBAN3]\nYou're either two-faced, or you're a wimp, baby boy!\n\n[CUB3_F:CUBAN3]\nEasy, easy. What's your problem?\n\n[CUB3_H:CUBAN3]\nUmberto Robina! They're doing whatever they like!\n\n{=================================== MISSION TABLE CUBAN4 ===================================}\n\n[CUB4_A:CUBAN4]\nHey, ladies. You know what I'm gonna do?\n\n[CUB4_B:CUBAN4]\nI'm gonna kill me a Haitian. And then?\n\n[CUB4_C:CUBAN4]\nAnd then I'm going to make love like a man.\n\n[CUB4_D:CUBAN4]\nYou know that, chica? Something like this.\n\n[CUB4_E:CUBAN4]\nLoser!\n\n[CUB4_F:CUBAN4]\nPrick.\n\n[CUB4_G:CUBAN4]\nHey, baby, I wouldn't touch you with a ten foot pole!\n\n[CUB4_H:CUBAN4]\nUmberto Robina, he likes the ladies! Not some goat in a skirt!\n\n[CUB4_I:CUBAN4]\nTommy!! Tommy, I love you, I love you! Let's go!\n\n[CUB4_J:CUBAN4]\nGo where? Can't I get a cup of coffee first?\n\n[CUB4_K:CUBAN4]\nNo time for coffee! Besides, I just had one.\n\n[CUB4_L:CUBAN4]\nWe gonna take out the Haitians.\n\n[CUB4_M:CUBAN4]\nTommy, how do you take out a snake?\n\n[CUB4_N:CUBAN4]\nYou bite him in the ass! Hahaha!\n\n[CUB4_O:CUBAN4]\nWhatever you say, Umberto.\n\n[CUB4_P:CUBAN4]\nTommy, you go and get us a little Haitian car.\n\n[CUB4_Q:CUBAN4]\nWhen you get it, come back and pick up my boy.\n\n[CUB4_R:CUBAN4]\nPepe, and take him out to the Haitians.\n\n[CUB4_S:CUBAN4]\nThen, you go around to the Haitians processing plant, and you use their solvent as an explosive.\n\n[CUB4_T:CUBAN4]\nBoom! Bye bye!\n\n[CUB4_U:CUBAN4]\nUmberto, what about you?\n\n[CUB4_V:CUBAN4]\nUhh... I'm going to stay behind, and watch over the cafe with Poppa.\n\n[CUB4_W:CUBAN4]\nHe not feeling so good. You know?\n\n[CUB4_02:CUBAN4]\n~g~The bombs will be set with a 45 second timer.\n\n[CUB4_04:CUBAN4]\n~r~You've alerted the base, there is no way we will get in now!\n\n[CUB4_07:CUBAN4]\nOy - the solvent is round the back, amigo.\n\n[CUB4_08:CUBAN4]\nHola, amigos.\n\n[CUB4_09:CUBAN4]\nBueno. Haitian Putas. Muerte.\n\n[CUB4_10:CUBAN4]\nVamos.\n\n[CUB4_11:CUBAN4]\nVamos indeed.\n\n[CUB4_12:CUBAN4]\nHey, we need a Haitian gang car!\n\n[CUB4_13:CUBAN4]\nOye, let's go find our muchachos!\n\n[CUB4_14:CUBAN4]\nFollow my compadres.\n\n[CUB4_15:CUBAN4]\nOk, in you go...\n\n[CUB4_16:CUBAN4]\nI'm going to plant the bomb, cover me!\n\n[CUB4_17:CUBAN4]\nRUN!!\n\n[CUB4_18:CUBAN4]\nMan, this a nice part of town...\n\n[CUB4_19:CUBAN4]\nThis place is a dump, man.\n\n[CUB4_20:CUBAN4]\nI had a beautiful woman... lived around this neighborhood.\n\n[CUB4_21:CUBAN4]\nYou know, they do nice pizzas here.\n\n[CUB4_22:CUBAN4]\nWhoah, man. You drive like a crazy bitch!\n\n[CUB4_23:CUBAN4]\nYou lost, man?\n\n[CUB4_24:CUBAN4]\nYou've left Pepe behind, go and get him.\n\n[CUB4_03:CUBAN4]\n~g~Stay in the car until safely parked inside the compound.\n\n[CUB4_26:CUBAN4]\n~g~Take Pepe, head North into Little Haiti and steal a Voodoo car.\n\n[CUB4_27:CUBAN4]\n~g~Go and meet up with Rico and the other Cubans.\n\n[CUB4_28:CUBAN4]\n~g~Join the other Cubans at the Haitian Drugs Factory.\n\n[CUB4_29:CUBAN4]\n~g~Walk into each of the markers to plant a bomb at that location.\n\n[CUB4_30:CUBAN4]\n~g~After all three bombs are planted, get clear of the factory before it blows.\n\n[CUB4_31:CUBAN4]\n~g~Get clear of the factory!!\n\n[CUB4_32:CUBAN4]\n~g~Park the car at the blip and get out.\n\n[CUB4_06:CUBAN4]\n~r~You did not get far enough away from the base and we had to abort the explosion!\n\n{=================================== MISSION TABLE FINALE ===================================}\n\n[FIN1_01:FINALE]\nWhat's going on?\n\n[FIN1_02:FINALE]\nTommy! Oh good, good. Listen, listen. Uh, listen,\n\n[FIN1_03:FINALE]\nI like fish. I love fish.\n\n[FIN1_04:FINALE]\nI love them as pets in bowls, or as food on a plate,\n\n[FIN1_05:FINALE]\nbut as much as I love em, I don't want to sleep with them.\n\n[FIN1_06:FINALE]\nOkay, but right now your Italian brothers are coming from up there to fit me with some cement shoes, and I...\n\n[FIN1_07:FINALE]\nShut up Ken. Sit down.\n\n[FIN1_08:FINALE]\nLance, what the hell's going on?\n\n[FIN1_09:FINALE]\nIt's your friends up north Tommy. They ain't too happy you capped their man.\n\n[FIN1_10:FINALE]\nThey're coming down to see the business today.\n\n[FIN1_11:FINALE]\nThey took longer than I thought...\n\n[FIN1_12:FINALE]\nGuys, we gotta make this final we gotta leave no doubt that this is my operation. Mine!\n\n[FIN1_13:FINALE]\nKen, you get the first run of counterfeit cash and put three mil in briefcases.\n\n[FIN1_14:FINALE]\nLance, you get the guys together...\n\n[FIN2_01:FINALE]\nTommy!\n\n[FIN2_02:FINALE]\nWhat? No big hugs for your old buddy?\n\n[FIN2_03:FINALE]\nI've had fifteen years out of the loop,\n\n[FIN2_04:FINALE]\nI'm a bit rusty on family etiquette.\n\n[FIN2_05:FINALE]\nAlways angry, eh Tommy.\n\n[FIN2_06:FINALE]\nDidn't I say your temper would get you into trouble, huh?\n\n[FIN2_07:FINALE]\nThere's three mil in the cases...\n\n[FIN2_08:FINALE]\nHow many was it? Ten? No, eleven men.\n\n[FIN2_09:FINALE]\nThat's how you get to be called the Harwood Butcher! Heh-heh-heh!\n\n[FIN2_10:FINALE]\nYou sent me to kill one man, ONE MAN. They knew I was coming Sonny...\n\n[FIN2_11:FINALE]\nTommy, Tommy, watch your tone.\n\n[FIN2_12:FINALE]\nAnyone would think you blame me for that unfortunate set of circumstances.\n\n[FIN2_13:FINALE]\nJust take the money...\n\n[FIN2_14:FINALE]\nGet the damn cash.\n\n[FIN2_15:FINALE]\nYou know, Tommy? I did what I could for you, I pulled strings, called in favors.\n\n[FIN2_16:FINALE]\nI was your friend, Tommy. I hoped you'd see sense, see what's good for business.\n\n[FIN2_17:FINALE]\nI trusted you, Tommy, and you disappointed me.\n\n[FIN2_18:FINALE]\nBut at least someone in your chicken shit organization knows how to do business,\n\n[FIN2_19:FINALE]\nIsn't that right, Lance?\n\n[FIN2_20:FINALE]\nI'm sorry Tommy. This is Vice City. This is business.\n\n[FIN2_21:FINALE]\nYou sold us out...\n\n[FIN2_22:FINALE]\nNo. I sold YOU out, Tommy, I sold YOU out.\n\n[FIN2_23:FINALE]\nThe real cash is upstairs in the safe.\n\n[FIN2_24:FINALE]\nTommy, what was the big plan?\n\n[FIN2_25:FINALE]\nYou think I'd just take the fake cash?\n\n[FIN2_26:FINALE]\nSave face and run away with my tail between my legs?!\n\n[FIN2_27:FINALE]\nNo.\n\n[FIN2_28:FINALE]\nI just wanted to piss you off before I kill you.\n\n[FIN3_01:FINALE]\nTommy?\n\n[FIN3_02:FINALE]\nOh my god, Tommy! What happened?\n\n[FIN3_03:FINALE]\nWhat does it look like?\n\n[FIN3_04:FINALE]\nIt looks like you ruined your suit!\n\n[FIN3_05:FINALE]\nand Tommy, that was a beautiful suit! Tommy, what on earth happened?\n\n[FIN3_06:FINALE]\nI had a disagreement with a business associate, you know how it is.\n\n[FIN3_07:FINALE]\nTommy, I have a disagreement, I send them an angry letter.\n\n[FIN3_08:FINALE]\nMaybe I pee in their mailbox. I don't start World War III.\n\n[FIN3_09:FINALE]\nYou know, maybe you should speak to my shrink...\n\n[FIN3_10:FINALE]\nThat stupid prick, Lance...\n\n[FIN3_11:FINALE]\nTommy. I never liked that guy, okay?\n\n[FIN3_12:FINALE]\nHe's neurotic, he's insecure, he's self-centered - the guy's an asshole!\n\n[FIN3_13:FINALE]\nI'm glad you took him out!\n\n[FIN3_14:FINALE]\nI don't think we're gonna be getting any more heat from up north either...\n\n[FIN3_15:FINALE]\n...'cause there ain't no 'up north', anymore.\n\n[FIN3_16:FINALE]\nIt's all down south now.\n\n[FIN3_17:FINALE]\nWait, does that mean what I think it means..? Tommy, baby!\n\n[FIN3_18:FINALE]\nWhat do you think it means?\n\n[FIN3_19:FINALE]\nThat we're in charge... I mean, that you're in charge. Oh, Tommy!\n\n[FIN3_20:FINALE]\nYou know, Ken. I think this could be the beginning of a beautiful business relationship....\n\n[FIN3_21:FINALE]\nAfter all, you're a conniving, backstabbing, two-bit thief\n\n[FIN3_22:FINALE]\nand I'm a convicted psychotic killer and drug dealer.\n\n[FIN3_23:FINALE]\nI know. Ain't it just beautiful?\n\n[FIN_B1:FINALE]\n~g~Go and kill ~y~Lance Vance~g~ the backstabber.\n\n[FIN_B2:FINALE]\n~g~Kill ~p~Sonny~g~ and finish this once and for all.\n\n[FIN_B3:FINALE]\n~g~The Mafia are trying to steal your money. Defend the safe.\n\n[FIN_B4:FINALE]\n~g~You are close to death, get some ~w~health~g~ from downstairs.\n\n[FIN_B5:FINALE]\n~g~The Mafia is stealing your money, defend the ~c~safe\n\n[FIN_B7:FINALE]\n~r~The mafia has stolen all your money.\n\n[DEFSAFE:FINALE]\n~g~Get back to the safe and defend it.\n\n{=================================== MISSION TABLE FIRETRK ===================================}\n\n[F_PASS1:FIRETRK]\nFire extinguished!\n\n[F_FAIL2:FIRETRK]\n~r~You're too late!\n\n[F_CANC:FIRETRK]\n~r~Fire Fighter mission cancelled!\n\n[F_EXTIN:FIRETRK]\nFIRES:\n\n[F_START:FIRETRK]\n~g~Burning vehicle reported in the ~a~ area. Go and extinguish the fire.\n\n[SIREN_1:FIRETRK]\nTo turn on this vehicle's sirens tap the ~h~~k~~VEHICLE_HORN~ ~w~button.\n\n[SIREN_2:FIRETRK]\nTo turn on this vehicle's sirens tap the ~h~~k~~VEHICLE_HORN~ ~w~button.\n\n[FIREPRO:FIRETRK]\nFire Truck Mission level 12 complete. You are now completely fireproof!!\n\n[F_FAIL1:FIRETRK]\nFire Fighter mission ended.\n\n[F_STAR1:FIRETRK]\n~g~Burning vehicles reported in the ~a~ area. Go and extinguish the fire.\n\n[SPRAY_4:FIRETRK] { reVC update }\nUse the ~h~~k~~VEHICLE_FIREWEAPON~ ~w~button to fire the water cannon. Aim using ~h~~k~~VEHICLE_TURRETLEFT~~w~ and ~h~~k~~VEHICLE_TURRETRIGHT~~w~.\n\n[SPRAY_1:FIRETRK] { reVC update }\nUse the ~h~~k~~VEHICLE_FIREWEAPON~ ~w~button to fire the water cannon. Aim using ~h~~k~~VEHICLE_TURRETLEFT~~w~ and ~h~~k~~VEHICLE_TURRETRIGHT~~w~.\n\n{=================================== MISSION TABLE GENERA1 ===================================}\n\n[GEN1_A:GENERA1]\nMr. Vercetti!\n\n[GEN1_B:GENERA1]\nColonel.\n\n[GEN1_D:GENERA1]\nNo - thanks.\n\n[GEN1_E:GENERA1]\nI'm ashamed to admit that one of the causes of our mutual problem appears to have been the loose tongue of a man I used to trust.\n\n[GEN1_F:GENERA1]\nI've been carrying Gonzalez for years, but now his incompetence reaches new heights!\n\n[GEN1_G:GENERA1]\nIt is only right that you kill Gonzalez...\n\n[GEN1_H:GENERA1]\nDid he do it? It's the money that's important to me.\n\n[GEN1_J:GENERA1]\nHe will be at his Penthouse, half drunk probably. Use this...\n\n[GEN1_06:GENERA1]\nEh! He's got a blade!\n\n[GEN1_07:GENERA1]\nGo away from me, you cheap bastard!\n\n[GEN1_08:GENERA1]\nOh sweet Jesus, I've wasted my life and my looks!\n\n[GEN1_10:GENERA1]\nI'm going to shut that big mouth of yours!\n\n[GEN1_11:GENERA1]\nStop running you fat slimeball!\n\n[GEN1_12:GENERA1]\nStand still and I'll make it quick!\n\n[GEN1_13:GENERA1]\nQuit your squealing, no one cares, fatso!\n\n[GEN1_C:GENERA1]\nThank you for coming. Please sit. Lobster?\n\n[GEN1_05:GENERA1]\n~g~Go and kill Gonzalez!\n\n[GEN1_09:GENERA1]\nI pay you double, Tommy, DOUBLE!\n\n[GEN1_18:GENERA1]\n~r~Gonzalez has made it safely to the Police Station!\n\n[GEN1_19:GENERA1]\n~g~The Vice City Police are on to you!\n\n[GEN1_20:GENERA1]\n~g~Get into a vehicle.\n\n[GEN1_21:GENERA1]\n~g~Get to the~h~ Pay 'N' Spray~g~ in~h~ Vice Point~g~.\n\n[GEN1_22:GENERA1]\nDrive your vehicle into the spray shop to lose your ~h~wanted level, ~h~repair and ~h~respray your vehicle. Cost - ~h~$100. This time it's free.\n\n[GEN1_01:GENERA1]\nWhen jogging, press and hold the~h~ ~k~~PED_FIREWEAPON~ ~w~button to prepare a melee attack.\n\n[GEN1_02:GENERA1]\nWhen jogging, press and hold the~h~ ~k~~PED_FIREWEAPON~ ~w~button to prepare a melee attack.\n\n[GEN1_03:GENERA1]\nWhen jogging, press and hold the~h~ ~k~~PED_FIREWEAPON~ ~w~button to prepare a melee attack.\n\n[GEN1_14:GENERA1]\nRelease the~h~ ~k~~PED_FIREWEAPON~ ~w~button to make the attack.\n\n[GEN1_15:GENERA1]\nRelease the~h~ ~k~~PED_FIREWEAPON~ ~w~button to make the attack.\n\n[GEN1_16:GENERA1]\nRelease the~h~ ~k~~PED_FIREWEAPON~ ~w~button to make the attack.\n\n[GEN1_I:GENERA1]\nFor this kindness I'll reward you, and then we will find your money together.\n\n[GEN1_23:GENERA1]\n~g~Go back through the doors to return to the ground floor.\n\n{=================================== MISSION TABLE GENERA2 ===================================}\n\n[COL2_B:GENERA2]\nThis looks delicious, huh? Tapir snout?\n\n[COL2_C:GENERA2]\nUhhh... no, no. No, thanks.\n\n[COL2_D:GENERA2]\nTommy, you are like a pampas breeze that has freed me from the stench of corruption,\n\n[COL2_E:GENERA2]\nalthough, I must appear to mourn his passing and carry on with business as usual.\n\n[COL2_F:GENERA2]\nThis isn't getting me any closer to my money...\n\n[COL2_G:GENERA2]\nTommy, my friend, you are not in Liberty now. Here we do things differently.\n\n[COL2_H:GENERA2]\nI will continue with my enquiries but in the meantime I have a valuable deal to close.\n\n[COL2_I:GENERA2]\nA favor for a friend, Cortez?\n\n[COL2_J:GENERA2]\nYou're a good friend, Tommy. I knew you would not let me down.\n\n[COL2_K:GENERA2]\nI need you to meet a courier who has obtained some valuable technology for me...\n\n[COL2_1:GENERA2]\nZe rain, she is tres wet zis time of the year...\n\n[COL2_2:GENERA2]\nWhat?\n\n[COL2_3:GENERA2]\nAh, comment?\n\n[COL2_4:GENERA2]\nLook, Cortez sent me. Just give me the damn chips.\n\n[COL2_5:GENERA2]\nOh...d'accord.\n\n[COL2_B1:GENERA2]\n~g~Meet the courier at the mall.\n\n[COL2_B2:GENERA2]\n~g~The courier is fleeing with the guidance chips! Don't let him get away!\n\n[COL2_B3:GENERA2]\n~g~Take the guidance chips back to the Colonel.\n\n[COL2_F1:GENERA2]\n~r~You killed the contact!\n\n[COL2_F2:GENERA2]\n~g~The courier is dead. Grab the guidance chips.\n\n[COL2_6A:GENERA2]\nFreeze, imperialist American pig! Zat iz propertay of ze government Francais. 'And eet over!\n\n[BLIPHLP:GENERA2]\nThe blip on the radar is a triangle pointing up, this shows that the target is higher than the player.\n\n[COL2_F3:GENERA2]\n~r~The guidance chips are at the bottom of the sea.\n\n[COL2_F4:GENERA2]\n~r~The courier has escaped! You failed to get the guidance chips.\n\n[COL2_A:GENERA2]\nTommy! Come, join me.\n\n{=================================== MISSION TABLE GENERA3 ===================================}\n\n[GEN3_A:GENERA3]\nThomas, I appreciate your coming.\n\n[GEN3_B:GENERA3]\nForgive me for getting straight to business.\n\n[GEN3_C:GENERA3]\nDiaz has asked me to oversee a minor business transaction.\n\n[GEN3_D:GENERA3]\nLet's hope it goes better than last time, huh?\n\n[GEN3_E:GENERA3]\nWhich is why I thought of you, my friend.\n\n[GEN3_F:GENERA3]\nI've dropped some protection at the multistory carpark.\n\n[GEN3_G:GENERA3]\nPick it up - then go and watch over Diaz's men at the drop off.\n\n[GEN3_H:GENERA3]\nGracias, amigo.\n\n[GEN3_1:GENERA3]\nHogging all the action, I see...\n\n[GEN3_2:GENERA3]\nLook, you wanna do something other than just shadowing me everywhere? Why don't you come along and show me if you're any use.\n\n[GEN3_3:GENERA3]\nI might just do that. The name's Lance, by the way.\n\n[GEN3_5:GENERA3]\nYou must be Cortez's new gun.\n\n[GEN3_6:GENERA3]\nUntil more gainful opportunities arise.\n\n[GEN3_7:GENERA3]\nThey'll be here any minute - we both better get a good vantage point...\n\n[GEN3_8:GENERA3]\nOK! I'll take the balcony, you get the roof across the yard.\n\n[GEN3_9:GENERA3]\nI live! Dickheads! And it's all down to you! What is your name?\n\n[GEN3_10:GENERA3]\nTommy.\n\n[GEN3_11:GENERA3]\nI see you soon, amigo, I think!\n\n[GEN3_12:GENERA3]\nShit. Where's that guy Lance?\n\n[GEN3_14:GENERA3]\nTommy! I need some help here!\n\n[GEN3_15:GENERA3]\nDon't worry, I got you covered!\n\n[GEN3_16:GENERA3]\nDiaz's men are getting cut down!\n\n[GEN3_19:GENERA3]\n~g~Haitians! They're busting the deal! Protect Diaz!\n\n[GEN3_20:GENERA3]\n~g~The Colonel has arranged some firepower for you at the multistory carpark.\n\n[GEN3_22:GENERA3]\nDiaz's Health:\n\n[GEN3_23:GENERA3]\n~g~You've left Lance behind! Go and get him!\n\n[GEN3_25:GENERA3]\n~r~Lance died!\n\n[GEN3_28:GENERA3]\n~g~Take the briefcase back to Diaz.\n\n[GEN3_29:GENERA3]\n~g~Collect the briefcase and take it back to Diaz.\n\n[GEN3_30:GENERA3]\n~r~He got away with the money! Diaz will have your balls for this!\n\n[GEN3_33:GENERA3]\n~r~Check your fire!! You're supposed to be watching over Diaz and his men, not shooting them!\n\n[GEN3_34:GENERA3]\n~r~There ain't gonna be a deal if you shoot the Cubans!\n\n[GEN3_35:GENERA3]\n~g~He's stolen Diaz's money!\n\n[GEN3_36:GENERA3]\n~g~Grab the bike, chase him down and get Diaz's money back!\n\n[GEN3_37:GENERA3]\n~g~Here come the Cubans. Watch over the deal making sure Diaz and Lance are safe.\n\n[GEN3_38:GENERA3]\n~r~Diaz died! You failed to protect him!\n\n[GEN3_39:GENERA3]\n~g~Get to your vantage point up the stairs.\n\n[GEN3_44:GENERA3]\n~g~Go with Lance to the drop off and watch over Diaz.\n\n[GEN3_45:GENERA3]\nThey'll be here any minute, we both better get a good vantage point.\n\n[GEN3_40:GENERA3] { reVC update }\nTo ~h~shoot straight ahead ~w~on a ~h~motorbike ~w~press the ~h~~k~~VEHICLE_FIREWEAPON~ ~w~button.\n\n[GEN3_41:GENERA3] { reVC update }\nTo ~h~shoot straight ahead ~w~on a ~h~motorbike ~w~press the ~h~~k~~VEHICLE_FIREWEAPON~ ~w~button.\n\n[GEN3_46:GENERA3]\nSheeit!\n\n[GEN3_47:GENERA3]\nTommy!\n\n[GEN3_48:GENERA3]\nDamn!\n\n[GEN3_49:GENERA3]\nlance's health:\n\n[GEN3_50:GENERA3]\n~r~You lost Diaz's money! Next time try not to reduce the money to ashes!\n\n[GEN3_51:GENERA3]\nMore damned Haitians in a shitty van!\n\n[GEN3_54:GENERA3]\nDon't just stand there, you pricks, chase that Haitian dickhead down!\n\n[GEN3_55:GENERA3]\nTommy! I'll stay here and watch over Diaz!\n\n[GEN3_18:GENERA3]\n~g~Here come the Cubans, keep close to Diaz. Watch over the deal making Diaz and Lance are safe.\n\n[GEN3_56:GENERA3]\n~r~Diaz was ambushed and died! Next time keep him in your sights!\n\n[GEN3_57:GENERA3]\nThe Kruger is an assault rifle, which allows you to manually aim in 1st person.\n\n[GEN3_58:GENERA3]\nPress and hold the~h~ ~k~~PED_LOCK_TARGET~~w~ button to ~h~aim~w~ with an assault rifle.\n\n[GEN3_59:GENERA3]\nPress and hold the~h~ ~k~~PED_LOCK_TARGET~~w~ button to ~h~aim~w~ with an assault rifle.\n\n[GEN3_60:GENERA3]\nPress the ~h~~k~~PED_FIREWEAPON~~w~ button to ~h~fire~w~ an assault rifle.\n\n[GEN3_61:GENERA3]\nPress the ~h~~k~~PED_FIREWEAPON~~w~ button to ~h~fire~w~ an assault rifle.\n\n[GEN3_62:GENERA3]\nPress the ~h~~k~~PED_FIREWEAPON~~w~ button to ~h~fire~w~ an assault rifle.\n\n[GEN3_63:GENERA3]\nAs well as performing drive-by's,~h~ motorbikes ~w~allow you to ~h~shoot forwards~w~.\n\n[GEN3_64:GENERA3] { reVC update }\nTo shoot forwards while on a bike press the ~h~~k~~VEHICLE_FIREWEAPON~~w~ button.\n\n[GEN3_65:GENERA3] { reVC update }\nTo shoot forwards while on a bike press the ~h~~k~~VEHICLE_FIREWEAPON~~w~ button.\n\n[GEN3_66:GENERA3] { reVC update }\nTo shoot forwards while on a bike press the ~h~~k~~VEHICLE_FIREWEAPON~~w~ button.\n\n[GEN3_67:GENERA3]\nYou must have a sub machine gun to shoot forwards on a motorbike.\n\n[GEN3_53:GENERA3]\nMY MONEY!\n\n[GEN3_52:GENERA3]\nThese Haitians think they can take RICARDO DIAZ!?!\n\n{=================================== MISSION TABLE GENERA4 ===================================}\n\n[DETON:GENERA4]\nDETONATION:\n\n[COL4_3:GENERA4]\nCONVOY HALT!\n\n[COL4_6:GENERA4]\nWE'RE TAKING ENEMY FIRE!\n\n[COL4_7:GENERA4]\nCivilian, move away from the tank!\n\n[COL4_8:GENERA4]\nI SAID, move away, IMMEDIATELY!\n\n[COL4_9:GENERA4]\nDEFENSIVE POSITIONS!\n\n[COL4_11:GENERA4]\nGet that civilian out of our way soldier! - Sir, Yes Sir!\n\n[COL4_12:GENERA4]\nCivilian in the TANK! STOP HIM!\n\n[COL4_13:GENERA4]\nThis is a military convoy, do not obstruct our route.\n\n[COL4_14:GENERA4]\nDrop him soldier.\n\n[COL4_15:GENERA4]\nGet that civilian vehicle out of our way! - Sir! Moving vehicle Sir!\n\n[COL4_17:GENERA4]\nOk, PLATOON MOVE IT OUT!\n\n[COL4_18:GENERA4]\nSomeone's on the tank Sir!\n\n[COL4_19:GENERA4]\nGo get some doughnuts, soldier! - Sir, Yes Sir!\n\n[COL4_20:GENERA4]\nTarget acquired, Sir\n\n[COL4_21:GENERA4]\nSNIPER!\n\n[COL4_22:GENERA4]\nI'm getting out of here.\n\n[COL4_23:GENERA4]\nObjective completed! Platoon dismissed! - Lets go eat some doughnuts.\n\n[COL4_24:GENERA4]\nSecurity protocol Delta India Echo triggered! Vehicle self destruct initiated!\n\n[COL4_26:GENERA4]\nPrepare to die Communist scum!\n\n[COL4_B2:GENERA4]\n~r~The tank arrived at its destination safely!\n\n[COL4_B5:GENERA4]\n~r~The tank has been destroyed!\n\n[COL4_01:GENERA4]\nDiaz was pleased, and would like to meet you again.\n\n[COL4_02:GENERA4]\nIs that a good thing?\n\n[COL4_03:GENERA4]\nOf course! Although I'm starting to think that Diaz was responsible for our unfortunate loss...\n\n[COL4_04:GENERA4]\nWhat makes you say that?\n\n[COL4_05:GENERA4]\nOne does not wave accusations at a man like Diaz - I'm merely thinking out loud...\n\n[COL4_06:GENERA4]\nNo matter. I have a proposal that you could profit from...\n\n[COL4_07:GENERA4]\nI don't have time to run more errands, Cortez.\n\n[COL4_08:GENERA4]\nI would have thought a man with such dangerous debts would be hungry for opportunities. Please, Tommy, at least hear me out.\n\n[COL4_09:GENERA4]\nGo on...\n\n[COL410:GENERA4]\nI have a buyer for a piece of military hardware that is being taken through town. Pick it up for me...\n\n[COL411:GENERA4]\nand once you get it, I want you to call me immediately, then...\n\n[COL4_B4:GENERA4]\n~g~The tank is locked. Find a way to lure out the occupants.\n\n[COL4_1:GENERA4]\nWhat's up with the Gunner? - Don't know Sir!\n\n[COL4_4:GENERA4]\nGet topside soldier. - Sir, Yes Sir!\n\n[COL4_B1:GENERA4]\n~g~Go and acquire the piece of military hardware that is being taken through town.\n\n[COL4_B3:GENERA4]\n~g~Drop the tank off in the Colonels lockup before it self destructs.\n\n[COL4_B6:GENERA4]\n~g~Find a way to steal the tank!\n\n[COL4_B7:GENERA4]\n~g~Drive the tank into the garage.\n\n[COL4_B8:GENERA4]\n~g~Get out of the tank and walk out of the garage.\n\n{=================================== MISSION TABLE GENERA5 ===================================}\n\n[COL5A_1:GENERA5]\nCircumstances force a hasty departure, amigo.\n\n[COL5A_2:GENERA5]\nWhat's the problem?\n\n[COL5A_3:GENERA5]\nEhh, the French want their missile technology back and after that last incident,\n\n[COL5A_4:GENERA5]\nI feel it is time to find safer harbors.\n\n[COL5A_5:GENERA5]\nWouldn't it be safer to fly?\n\n[COL5A_6:GENERA5]\nI'd be dead before I reached check-in. Besides, I need to get my merchandise out of the country.\n\n[COL5A_7:GENERA5]\nNeed another gun?\n\n[COL5A_8:GENERA5]\nYou, my friend, are worth ten guns...\n\n[COL5B_1:GENERA5]\nThomas, you have protected and served me well.\n\n[COL5B_2:GENERA5]\nBut now you must leave us before we reach the open seas.\n\n[COL5B_4:GENERA5]\nThank you, Colonel.\n\n[COL5B_5:GENERA5]\nOne more request. While I'm away, could you keep an eye on Mercedes for me?\n\n[COL5B_6:GENERA5]\nI think she could look after herself, but sure, I'll keep an eye out.\n\n[COL5B_7:GENERA5]\nGracias, amigo. Hasta luego.\n\n[COL5B_8:GENERA5]\nAdios, amigo.\n\n[COL5_7:GENERA5]\nStop shooting at me!\n\n[COL5_9:GENERA5]\nTommy, stop them shooting at me!\n\n[COL5_10:GENERA5]\nI have diplomatic immunity!\n\n[COL5_11:GENERA5]\nDon't shoot, I am a Colonel!\n\n[COL5_12:GENERA5]\nThomas, kill them, my country will love you.\n\n[COL5_13:GENERA5]\nTommy, we are being overrun by the French!\n\n[COL5_14:GENERA5]\nTommy, everywhere I look, there are French men, I hate it!\n\n[COL5_15:GENERA5]\nTommy, how are you?\n\n[COL5_16:GENERA5]\nThis is for Piaf and Gainesbourg and your stupid french bread!\n\n[COL5_1:GENERA5]\nPort side! Port side!\n\n[COL5_2:GENERA5]\nThey're attacking from starboard!\n\n[COL5_3:GENERA5]\nThe bridge up ahead!\n\n[COL5_4:GENERA5]\nThey've got a helicopter!\n\n[COL5_B1:GENERA5]\n~g~Defend the Colonel and his yacht at all costs.\n\n[COL5_B2:GENERA5]\n~g~Get up front and clear the route for the Colonel's yacht.\n\n[COL5_B3:GENERA5]\n~r~The Colonel is dead!\n\n[COL5_B4:GENERA5]\n~g~Shoot the attacking helicopter out of the sky.\n\n[COL5B_3:GENERA5]\nI will lower my personal launch. Keep it, my friend, a token of my gratitude.\n\n[COL5_B5:GENERA5]\n~g~Shoot down the helicopters, do not endanger the yacht.\n\n[COL5_B6:GENERA5]\n~g~You have run out of ammo, get more from the stairs on the top deck.\n\n[COL5_B7:GENERA5]\n~g~You are running low on health, get more from the stairs on the top deck.\n\n{=================================== MISSION TABLE HAIT1 ===================================}\n\n[HAM1_A:HAIT1]\nHello? Hello?\n\n[HAM1_C:HAIT1]\nYou must be the big bad man me grandaddy been chattin' 'bout.\n\n[HAM1_D:HAIT1]\nTells me tings about you, you know, when he visits,\n\n[HAM1_E:HAIT1]\nand about the others who wait for you.\n\n[HAM1_F:HAIT1]\nNow, we all dead for long time, but you,\n\n[HAM1_G:HAIT1]\nI wouldn't want to be in your shoes, ha ha ha ha ha!\n\n[HAM1_H:HAIT1]\nI got a message to come here.\n\n[HAM1_I:HAIT1]\nCan you hear dem?\n\n[HAM1_J:HAIT1]\nDem callin' your name, boy, must want you pretty bad, don't ya tink?\n\n[HAM1_K:HAIT1]\nNow you do old Auntie Poulet a turn, huh, maybe she help you.\n\n[HAM1_L:HAIT1]\nMaybe she can give you a little juju after all of dis.\n\n[HAM1_M:HAIT1]\nGive you some magic to give the law man the stink eye, hmmmmm?\n\n[HAM1_N:HAIT1]\nLook, this is all very, um... give me what?\n\n[HAM1_O:HAIT1]\nI,I, I think I've got the wrong address...\n\n[HAM1_P:HAIT1]\nDo me these tings, Tommy......\n\n[HAM1_Q:HAIT1]\nThe Cubans, nasty proud foofoos, mmm,\n\n[HAM1_R:HAIT1]\nbeen making my lovely Haitian boys shake de heads.\n\n[HAM1_S:HAIT1]\nNow they told the policeman where me been stashing my powders.\n\n[HAM1_T:HAIT1]\nDey tink it drugs, them stupid.\n\n[HAM1_U:HAIT1]\nNow be a good boy Tommy and go and get the powders for Auntie Poulet.\n\n[HAM1_V:HAIT1]\nYeah, yeah, sure, sure.\n\n[HAM1_1:HAIT1]\n~g~The cops are closing in on our stashes. BE quick, and beat dem to it!\n\n[HAM1_2:HAIT1]\n~r~The cops got to the stash first!\n\n[HAM1_3:HAIT1]\n~g~Get this stuff back to the hideout!\n\n[HAM1_4:HAIT1]\n~g~Good! Now get the next one!\n\n[HAM1_6:HAIT1]\n~r~The Stash was destroyed, you idiot!\n\n[HAM1_7:HAIT1]\n~g~The cops have got our stash! Retrieve it before they get away!\n\n[HAM1_8:HAIT1]\n~g~The cops are on the way to pick up the stash, get a move on!\n\n[HAT_1A:HAIT1]\n~g~Don't move a muscle, chump!\n\n[HAM1_B:HAIT1]\nCome in, my dear, and rest your soul.\n\n{=================================== MISSION TABLE HAIT2 ===================================}\n\n[HAT2_B1:HAIT2]\n~g~Get to the van that contains the flying bombs.\n\n[HAT2_B2:HAIT2]\nKill the Cubans...\n\n[HAT2_B4:HAIT2]\n...and destroy their boats!\n\n[HAT2_B5:HAIT2]\n~g~The Cubans are making a run for it. Don't let them get away!\n\n[HAT2_B6:HAIT2]\n~r~The RC plane is getting too far out of range!\n\n[HAT2_B7:HAIT2]\n~g~One of the Cubans in escaping in a car. Don't leave any witnesses!\n\n[HAT2_B8:HAIT2]\n~r~You have no RC planes left!\n\n[HAT2_B9:HAIT2]\nRC Planes:\n\n[HAT2_1:HAIT2]\nOh, sorry, I - I must have the wrong address...\n\n[HAT2_2:HAIT2]\nWell, you might as well come in and rest your soles and have some tea.\n\n[HAT2_3:HAIT2]\nDo you have something there for me, Tommy?\n\n[HAT2_4:HAIT2]\nYeah...\n\n[HAT2_5:HAIT2]\nThis place feels familiar to me, uh - it's - a smell from childhood - a deja vu...\n\n[HAT2_6:HAIT2]\nNow Tommy, I'm going to whisper a lickle errand for you. Hear me well, aye?\n\n[HAT2_7:HAIT2]\nYou look like someone I, I...\n\n[HAT2_8:HAIT2]\nThe Cubans have fast boats they use to cross the seas with drugs.\n\n[HAT2_9:HAIT2]\nIt is their livelihood.\n\n[HAT2_10:HAIT2]\nMe nephew bin making lickle flying bombs to take dem out.\n\n[HAT2_11:HAIT2]\nBlow de boats to coffin wood.\n\n[HAT2_12:HAIT2]\nThanks for the tea.\n\n[HAT2_B3:HAIT2] { reVC update }\nPress the ~h~~k~~VEHICLE_FIREWEAPON~ ~w~button to drop a bomb. Press the ~h~~k~~VEHICLE_ENTER_EXIT~ ~w~button to cancel.\n\n{=================================== MISSION TABLE HAIT3 ===================================}\n\n[HAM3_A:HAIT3]\nHello? Hello - uh..I'm looking for somebody around here...\n\n[HAM3_B:HAIT3]\nYou looking hungry, Tommy.\n\n[HAM3_C:HAIT3]\nDo I know you?\n\n[HAM3_D:HAIT3]\nHush now.\n\n[HAM3_E:HAIT3]\nOne more ting an I can let you go, Tommy.\n\n[HAM3_F:HAIT3]\nMy boys gone war wit dem Cuban boys.\n\n[HAM3_G:HAIT3]\nBut no guns.\n\n[HAM3_H:HAIT3]\nHmm, but de Cubans have a surprise comin'.\n\n[HAM3_I:HAIT3]\nWhile they fight in de streets, you take this rifle and kill dem in de hubbub.\n\n[HAM3_J:HAIT3]\nNo one sees you, no one hear you.\n\n[HAM3_K:HAIT3]\nNow, Tommy, you do this for me, and you no longer tied to my apron strings.\n\n[HAM3_1:HAIT3]\n~g~We must win this battle. If all the Haitians die we lose.\n\n[HAM3_3:HAIT3]\n~g~I expect the Cubans to cheat so be on your guard.\n\n[HAM3_4:HAIT3]\n~r~You have been spotted! The mission is a failure!\n\n[HAM3_5:HAIT3]\n~g~You must kill the Cubans from a distance. You must not be seen.\n\n[HAM3_8:HAIT3]\n~g~Haitians are dying! Improve your aim.\n\n[HAM3_7:HAIT3]\n~g~Look Out! The Cubans have brought reinforcements. Kill them all!!\n\n[HAM3_2:HAIT3]\n~r~The Haitians have died!\n\n[HAM3_L:HAIT3]\nKay auntie..\n\n{=================================== MISSION TABLE HOTEL ===================================}\n\n[INTB_A:HOTEL]\nTommy! Tommy, it's been too long.\n\n[INTB_B:HOTEL]\nHello Sonny.\n\n[INTB_C:HOTEL]\nI know, I know. You're just overwhelmed with emotion.\n\n[INTB_D:HOTEL]\nFifteen years - seems like only yesterday.\n\n[INTB_E:HOTEL]\nI guess that's a perspective thing.\n\n[INTB_F:HOTEL]\nHey, doing time for the family is no piece of cake,\n\n[INTB_G:HOTEL]\nbut the family looks after its own, ok?\n\n[INTB_H:HOTEL]\nSo, how'd the deal go down - you sitting on some white gold?\n\n[INTB_I:HOTEL]\nLook Sonny, we were set up. The deal was an ambush. Harry and Lee are dead.\n\n[INTB_J:HOTEL]\nYou better be kidding me Tommy. Tell me you still got the money.\n\n[INTB_K:HOTEL]\n...no Sonny...I don't have the money.\n\n[INTB_L:HOTEL]\nThat was my money, Tommy, MY MONEY!\n\n[INTB_M:HOTEL]\nYou better not be screwing me Tommy because you know I'm not a man to be screwed with!\n\n[INTB_N:HOTEL]\nWait Sonny.\n\n[INTB_O:HOTEL]\nYou have my personal assurance that I'm going to get your money back and the drugs.\n\n[INTB_P:HOTEL]\nAnd I'm gonna mail you the dicks of those responsible.\n\n[INTB_Q:HOTEL]\nHey, I already know that. You're not a fool Tommy, but I warn you, neither am I.\n\n[INTB_R:HOTEL]\nIf it was anybody else you'd be DEAD already.\n\n[INTB_S:HOTEL]\nBut because it's you, because we got history, I'm gonna let you handle this.\n\n[INTB_T:HOTEL]\nLook, Sonny, you got my word.\n\n[INTB_U:HOTEL]\nI'll be in touch.\n\n{=================================== MISSION TABLE ICECRE1 ===================================}\n\n[ICC1_1:ICECRE1]\n~g~Use your Ice Cream van distribute drugs around Vice City.\n\n[ICC1_3:ICECRE1]\n~g~You receive money for each transaction you make, but the more transactions you make the more police attention you get.\n\n[ICC1_4:ICECRE1]\n~g~There aren't any customers in this area try another one.\n\n[ICC1_5:ICECRE1]\nDeals done:\n\n[ICC1_6:ICECRE1]\n~g~Use the Mr. Whoopee van to distribute Cherry Poppers product around Vice City.\n\n[ICC1_7:ICECRE1]\n~g~You receive money for each transaction you make, but the more transactions you make the more police attention you get.\n\n[ICC1_9:ICECRE1]\n~g~Local gangs will not appreciate you doing business on their turf so expect hostility if you do so.\n\n[ICC1_10:ICECRE1]\n~g~You made ~1~ deals!\n\n[ICC1_11:ICECRE1]\n~g~You made ~1~ deal!\n\n[ICC1_12:ICECRE1]\nPROPERTY ACQUIRED!\n\n[ICC1_13:ICECRE1]\n~r~You didn't make any deals!\n\n[ICC1_14:ICECRE1]\nICECREAM ASSET COMPLETED\n\n[ICC1_15:ICECRE1]\n~g~The icecream factory will now generate revenue up to a maximum of $~1~. Make sure you collect it regularly.\n\n[ICC1_2:ICECRE1]\n~g~Park your van and press the ~h~~k~~VEHICLE_HORN~~w~ to play your ice cream jingle to notify customers that your ready for business.\n\n[ICC1_16:ICECRE1]\n~g~Use your Mr. Whoopee van to distribute Cherry Poppers product around Vice City.\n\n[ICC1_8:ICECRE1]\n~g~To make a transaction, ~h~park your van ~g~and press the ~h~~k~~VEHICLE_HORN~ ~g~button to play the ice cream jingle to attract customers.\n\n[ICE_AT1:ICECRE1]\nICECREAM FACTORY ASSET COMPLETED\n\n[ICE_AT2:ICECRE1]\n~g~The Cherry Popper factory will now generate revenue up to a maximum of $~1~. Make sure you collect it regularly.\n\n[ICC1_17:ICECRE1]\nDistribution mission over\n\n[ICC1_18:ICECRE1]\nTotal ice cream sales: $~1~\n\n[ICC1_19:ICECRE1]\nTotal deals done: ~1~\n\n{=================================== MISSION TABLE ICECUT ===================================}\n\n[ICC1_A:ICECUT]\nWho are you?\n\n[ICC1_B:ICECUT]\nYour new owner.\n\n[ICC1_C:ICECUT]\nWere you now, or at any time, a child?\n\n[ICC1_D:ICECUT]\nWhat are you talking about?\n\n[ICC1_E:ICECUT]\nWere you a child?\n\n[ICC1_F:ICECUT]\nYes! Calm down! What's wrong with you?\n\n[ICC1_G:ICECUT]\nI knew it. A child.\n\n[ICC1_H:ICECUT]\nA dirty, stinking, sniveling, snotting, vile, puking, crying little baby!\n\n[ICC1_K:ICECUT]\nOw! Calm down.\n\n[ICC1_L:ICECUT]\nI HATE babies, and I hate children.\n\n[ICC1_N:ICECUT]\nEnough already!\n\n[ICC1_P:ICECUT]\nYou make soft ice cream, okay? It's purely for kids.\n\n[ICC1_Q:ICECUT]\nWhat kind of psycho are you?\n\n[ICC1_R:ICECUT]\nJust so I understand this, why make children happy if you hate them?\n\n[ICC1_S:ICECUT]\nOh, you stupid, sniveling, snotty-\n\n[ICC1_T:ICECUT]\nShut up!\n\n[ICC1_U:ICECUT]\n- Brat!\n\n[ICC1_V:ICECUT]\nThe ice cream is a front.\n\n[ICC1_W:ICECUT]\nWe distribute other, non-dairy products.\n\n[ICC1_X:ICECUT]\nAnd if I see a kid, I put him to good use.\n\n[ICC1_Y:ICECUT]\nDon't I, kiddies? Yes - yes, I do. Mummy doesn't love you.\n\n[ICC1_Z:ICECUT]\nShe HATES you!\n\n[ICC1_ZA:ICECUT]\nPROPERTY ACQUIRED!\n\n[ICC1_M:ICECUT]\nThey're dirty, sniveling, snotting, vile, puking little..\n\n[ICC1_I:ICECUT]\nA baby.. an awful, horrible, disgusting little boo hoo.\n\n[ICC1_J:ICECUT]\nMommy doesn't love you. You little shit!\n\n{=================================== MISSION TABLE INTRO ===================================}\n\n[INT1_A:INTRO]\nTommy Vercetti...Huh! shit.\n\n[INT1_B:INTRO]\nDidn't think they'd ever let him out.\n\n[INT1_C:INTRO]\nHe kept his head down, helps people forget.\n\n[INT1_D:INTRO]\nPeople will remember soon enough.\n\n[INT1_E:INTRO]\nWhen they see him walking down the streets of their neighborhoods.\n\n[INT1_F:INTRO]\nIt will be bad for business.\n\n[INT1_G:INTRO]\nWell, what are we gonna do, Sonny?\n\n[INT1_H:INTRO]\nWe treat him like an old friend and keep him busy out of town. OK?\n\n[INT1_I:INTRO]\nWe been talking about expanding down South, right?\n\n[INT1_J:INTRO]\nVice City is twenty-four carat gold these days.\n\n[INT1_K:INTRO]\nThe Colombians, the Mexicans, hell,\n\n[INT1_L:INTRO]\neven those Cuban refugees are cutting themselves a piece of some nice action.\n\n[INT1_M:INTRO]\nBut it's all drugs, Sonny,\n\n[INT1_N:INTRO]\nNone of the families will touch that shit!\n\n[INT1_O:INTRO]\nTimes are changing.\n\n[INT1_P:INTRO]\nThe families can't keep their backs turned while our enemies reap the rewards.\n\n[INT1_Q:INTRO]\nSo, we send someone down to do the dirty work for us...\n\n[INT1_R:INTRO]\nand cut ourselves a nice quiet slice. OK?\n\n[INT1_S:INTRO]\nWho's our contact down there?\n\n[INT1_T:INTRO]\nKen Rosenberg, schmuck of a lawyer.\n\n[INT1_U:INTRO]\nHow's he gonna hold Vercetti's leash?\n\n[INT1_V:INTRO]\nWe don't need him to.\n\n[INT1_W:INTRO]\nWe just set him loose in Vice City,\n\n[INT1_X:INTRO]\nwe give him a little cash to get started. OK?\n\n[INT1_Y:INTRO]\nGive it a few months.\n\n[INT1_Z:INTRO]\nThen we go down,\n\n[INT1_A1:INTRO]\npay him a little visit, right?\n\n[INT1_A2:INTRO]\nsee how he's doing.\n\n[INT2_A:INTRO]\nHey, hey, guys! It's, uh, Ken Rosenberg here! Hey! Heh, heh, hey, great, hey!\n\n[INT2_B:INTRO]\nWell, uh, I'm gonna drive you guys to the meet, okay?\n\n[INT2_C:INTRO]\nNow, I've talked to the suppliers and they are very, huh-ha,\n\n[INT2_D:INTRO]\nkeen to start a business relationship, so, uh,\n\n[INT2_E:INTRO]\nif all goes well, we should, uh,\n\n[INT2_F:INTRO]\nbe doing very nicely for ourselves, which is, y'know...\n\n[INT2_G:INTRO]\ngood..\n\n[INT2_H:INTRO]\nOkay, so. They're brothers, okay.\n\n[INT2_I:INTRO]\nOne operates the uh, the business,\n\n[INT2_J:INTRO]\nand the other one does the flying.\n\n[INT2_K:INTRO]\nNow they operate out of Mexico,\n\n[INT2_M:INTRO]\nThey own a farm in Panama.\n\n[INT2_N:INTRO]\nOkay, all right, listen -\n\n[INT2_O:INTRO]\nyou guys, when we get there should I stay in the car,\n\n[INT2_P:INTRO]\nor do you guys want me to come in with you guys?\n\n[INT2_Q:INTRO]\nNo. Stay in the car.\n\n[INT2_R:INTRO]\nYou know what, I thought about it,\n\n[INT2_S:INTRO]\nI'm gonna watch the car.\n\n[INT3_A:INTRO]\nOk, that's them in the chopper.\n\n[INT3_B:INTRO]\nAll right, here's the deal.\n\n[INT3_C:INTRO]\nThey want a straight exchange on open ground.\n\n[INT3_D:INTRO]\nAll right? Ok. Stay tight, let's go.\n\n[INT3_E:INTRO]\nAll right. Take it easy, now.\n\n[INT3_F:INTRO]\nI'm right here. The cars running, baby!\n\n[INT3_G:INTRO]\nGot it?\n\n[INT3_H:INTRO]\n100% pure grade-A Colombian, my friend.\n\n[INT3_I:INTRO]\nThe greens?\n\n[INT3_J:INTRO]\nTens and twenties...used.\n\n[INT3_L:INTRO]\nGo on, get out of here! Drive!\n\n[INT4_A:INTRO]\nScrewed! We're screwed!\n\n[INT4_B:INTRO]\nThis is soo typical,\n\n[INT4_C:INTRO]\nI poke my head out of the gutter for one freakin' second,\n\n[INT4_D:INTRO]\nand fate shovels shit in my face!\n\n[INT4_E:INTRO]\nWell, screw you!\n\n[INT4_F:INTRO]\nShut your face and quit complaining! You're alive, aren't ya'?\n\n[INT4_G:INTRO]\nDrop me right up here.\n\n[INT4_H:INTRO]\nGo dump the car, then go get some sleep.\n\n[INT4_I:INTRO]\nI'll drop by your office tomorrow and we can start sorting this mess out.\n\n[INT4_J:INTRO]\nOK, that's a good idea, I'll get some sleep.\n\n[INT4_K:INTRO]\nWhat are you gonna do?\n\n[INT4_L:INTRO]\nMake my way back to my hotel,\n\n[INT4_M:INTRO]\nclear my head, and figure this crap out.\n\n[INT4_N:INTRO]\nOK.\n\n[INTRO1:INTRO]\nI poke my head out of the gutter for one freakin' second and fate shovels shit in my face!\n\n[INTRO2:INTRO]\nGo get some sleep.\n\n[INTRO3:INTRO]\nWhat are you gonna do?\n\n[INTRO4:INTRO]\nI'll drop by your office tomorrow and we can start sorting this mess out.\n\n[INT3_K:INTRO]\nI think we have a deal, my friend. HA HA!\n\n[INT3_M:INTRO]\nLet me see it.\n\n[INT2_L:INTRO]\nno, no, no, wait...\n\n[INT3_N:INTRO]\nOh Shit!\n\n{=================================== MISSION TABLE KENT1 ===================================}\n\n[KPM1_A:KENT1]\nAwright mush, I'm gonna save your Vera, mate.\n\n[KPM1_B:KENT1]\nWhat the hell are you talking about?\n\n[KPM1_C:KENT1]\nYou know that wanker Diaz, the Bugle Master.\n\n[KPM1_D:KENT1]\nHe's got your boy, Lance. Word is your mate tried to jump him...\n\n[KPM1_E:KENT1]\ndidn't jump high enough if you know what I mean.\n\n[KPM1_F:KENT1]\nWhere did he take him? In plain English?\n\n[KPM1_G:KENT1]\nKeep your barnet on! They got him across town at the junkyard.\n\n[KPM1_H:KENT1]\nBloody hell....you nutter!\n\n[KPM1_2:KENT1]\n~r~You were supposed to get Lance out alive!\n\n[KPM1_3:KENT1]\nLANCE'S HEALTH:\n\n[RESC_1:KENT1]\nYou ok to use a gun?\n\n[RESC_2:KENT1]\nSure...I guess...nice to see you, too.\n\n[RESC_3:KENT1]\nLet's get out of here.\n\n[RESC_4:KENT1]\nThere goes my careful planning blown to shit, thanks to you. You screwed up real good, Lance!\n\n[RESC_5:KENT1]\nHe killed my brother. What do you expect me to do, mow his lawns?\n\n[RESC_6:KENT1]\nWe're gonna have to take out that prick Diaz before he takes us out.\n\n[RESC_7:KENT1]\nGet patched up and meet me on the bridge to Star Island, ok?\n\n[RESC_8:KENT1]\nOk, I got you.\n\n[KPM1_1:KENT1]\n~g~Lance is being held at the junk yard, Go and rescue him!\n\n[KPM1_4:KENT1]\n~g~Get Lance to the hospital!\n\n[M_PASSN:KENT1]\nMISSION PASSED!\n\n[KPM1_5:KENT1]\n~g~Diaz's guys are after you! Get Lance to the hospital.\n\n{=================================== MISSION TABLE KICKSTT ===================================}\n\n[KICK1_2:KICKSTT]\n~r~You did not get back to the bike quickly enough!\n\n[KICK1_7:KICKSTT]\n~r~You have wrecked the bike!\n\n[KICK1_8:KICKSTT]\n~g~Get on the bike!\n\n[KICK1_T:KICKSTT]\nTIME TAKEN:\n\n[KICKTM:KICKSTT]\n~b~EVENT TIME: ~1~:~1~\n\n[KICKTM2:KICKSTT]\n~b~EVENT TIME: ~1~:0~1~\n\n[GETBIKE:KICKSTT]\n~g~You have ~1~ seconds to return to a dirtbike before the mission ends.\n\n[KICK1_1:KICKSTT]\n~g~Complete the course as quickly as possible.\n\n[KICK1_6:KICKSTT]\n~g~Well done!\n\n[KICK_10:KICKSTT]\n~g~Use the Sanchez to complete the course by passing through all of the checkpoints.\n\n[KICK_12:KICKSTT]\n~r~You bottled it!\n\n[KICK_13:KICKSTT]\n~r~You have taken too long!\n\n[KICK_11:KICKSTT]\n~g~To leave the mission stand in the ~q~pink marker~g~ on foot.\n\n{=================================== MISSION TABLE LAWYER1 ===================================}\n\n[LAW1_A:LAWYER1]\nGo get some sleep, he says -\n\n[LAW1_B:LAWYER1]\n- I have been sitting in this chair all night with the lights off drinking coffee!\n\n[LAW1_C:LAWYER1]\nThis is a disaster. We are so screwed, man!\n\n[LAW1_D:LAWYER1]\nThese gorillas, listen to me, are gonna come down here and rip my head off. It's ridiculous!\n\n[LAW1_E:LAWYER1]\nI did NOT go to law school for this! Ok, now what the hell are we gonna do?\n\n[LAW1_F:LAWYER1]\nShut up, sit down, relax. I'll tell you what we're gonna do.\n\n[LAW1_G:LAWYER1]\nYou're gonna find out who took our cocaine - and then, I'm gonna kill them.\n\n[LAW1_H:LAWYER1]\nThat's a good idea. That's a GREAT idea. Let me think, let me think, let me think.\n\n[LAW1_I:LAWYER1]\n- OH! There's this retired Colonel, Colonel Juan Garcia Cortez.\n\n[LAW1_J:LAWYER1]\nHe's the one that helped me set up this deal\n\n[LAW1_K:LAWYER1]\nwell away from Vice City's established thugs. Ok?\n\n[LAW1_L:LAWYER1]\nNow, listen. He's holding his party out in the bay on his expensive yacht\n\n[LAW1_M:LAWYER1]\nand all of Vice City's big players are gonna be there. OK?\n\n[LAW1_N:LAWYER1]\nI have an invite, of course I have an invite,\n\n[LAW1_O:LAWYER1]\nbut there's no way that I'm going out there, sticking my head out the door - no way! Not gonna happen.\n\n[LAW1_P:LAWYER1]\nI told you, shut up! I'll go myself...\n\n[LAW1_Q:LAWYER1]\nHo - whoa, whoa! Hey, I like 1978 too, but, y'know, this isn't gonna be a beer and strippers do.\n\n[LAW1_R:LAWYER1]\nI mean, no offense, but I think that you might turn heads on the runway for the wrong reasons.\n\n[LAW1_S:LAWYER1]\nWhat's wrong with the way I'm dressed?\n\n[LAW1_T:LAWYER1]\nOk, look, here. Stop by Rafael's, tell him I sent 'ya. He'll make you look respectable.\n\n[LAW1_U:LAWYER1]\nOK, go, c'mon...\n\n[LAWP_1:LAWYER1]\nBuenas noches.\n\n[LAWP_2:LAWYER1]\nI understand you are here on the behalf of Mr. Rosenberg,\n\n[LAWP_3:LAWYER1]\nI hope any recent problems have not affected his health, or uh,\n\n[LAWP_4:LAWYER1]\nmental well being, Mr...uh?\n\n[LAWP_5:LAWYER1]\nVercetti. He's just got a touch of...agoraphobia.\n\n[LAWP_6:LAWYER1]\nExcellent, excellent. And you?\n\n[LAWP_7:LAWYER1]\nI just want my merchandise.\n\n[LAWP_8:LAWYER1]\nAh. It's an unfortunate set of circumstances for all involved.\n\n[LAWP_9:LAWYER1]\nOf course I have initiated my own lines of inquiry,\n\n[LAWP_10:LAWYER1]\nbut such a delicate matter will take time.\n\n[LAWP_11:LAWYER1]\nPerhaps we will talk later.\n\n[LAWP_12:LAWYER1]\nMeanwhile, let me introduce you to my daughter,\n\n[LAWP_13:LAWYER1]\nMercedes!\n\n[LAWP_14:LAWYER1]\nCaramia, could you look after our guest while I attend to my necessary obligations?\n\n[LAWP_15:LAWYER1]\nOf course, daddy.\n\n[LAWP_16:LAWYER1]\nPlease excuse me.\n\n[LAWP_17:LAWYER1]\nMercedes!?\n\n[LAWP_18:LAWYER1]\nYou try living with it.\n\n[LAWP_19:LAWYER1]\nAnyway, let me point out some of our more distinguished guests...\n\n[LAWP_20:LAWYER1]\nThat's our congressman Alex Shrub with rising silicone star Candy Suxxx...\n\n[LAWP_21:LAWYER1]\nAnd have you met my lovely wife Laura? No?\n\n[LAWP_22:LAWYER1]\nWell, unfortunately she's in Alabama. This is Candy.\n\n[LAWP_23:LAWYER1]\nAnd over there we have the Vice City Mambas' star tight end, BJ -\n\n[LAWP_24:LAWYER1]\nalways the charmer.\n\n[LAWP_25:LAWYER1]\nI blocked down on him and then I put him in a wheelchair!\n\n[LAWP_26:LAWYER1]\nHaha, that is good!\n\n[LAWP_27:LAWYER1]\nWell now, I'm looking at some prime real estate property.\n\n[LAWP_28:LAWYER1]\nAnd that poolside amphibian is Jezz Torrent,\n\n[LAWP_29:LAWYER1]\nlead singer with Love Fist.\n\n[LAWP_30:LAWYER1]\nCan I tell yous - do you know how they play ping-pong in Thailand?\n\n[LAWP_31:LAWYER1]\nLet me tell you's,\n\n[LAWP_32:LAWYER1]\nit does not involve a paddle, if you know what I mean!\n\n[LAWP_33:LAWYER1]\nImpotent.\n\n[LAWP_34:LAWYER1]\nAnd the chatty trio.\n\n[LAWP_35:LAWYER1]\nThat sleeping sweat gland is Papa's right hand gimp, Gonzalez\n\n[LAWP_36:LAWYER1]\nand the other two are Pastor Richards\n\n[LAWP_37:LAWYER1]\nand pseudo intellectual film director, Steve Scott.\n\n[LAWP_38:LAWYER1]\n...passion with the nympho invaders,\n\n[LAWP_39:LAWYER1]\nwhen the giant shark comes in and\n\n[LAWP_40:LAWYER1]\njust bites their dicks off!\n\n[LAWP_41:LAWYER1]\nHa now, you never saw anything like that before, have you?\n\n[LAWP_42:LAWYER1]\nColonel!\n\n[LAWP_43:LAWYER1]\nyour parties as ever are a triumph, hahahaha!\n\n[LAWP_44:LAWYER1]\nI can only apologize for my late arrival.\n\n[LAWP_45:LAWYER1]\nAh, de nada amigo. How do we find you?\n\n[LAWP_46:LAWYER1]\nOur business is very trying - barbarians at the gates.\n\n[LAWP_47:LAWYER1]\nA time for rewarding one's friends and liquidating one's enemies, amigo.\n\n[LAWP_48:LAWYER1]\nWho's the loudmouth?\n\n[LAWP_49:LAWYER1]\nRicardo Diaz. He's Mr. Coke.\n\n[LAWP_50:LAWYER1]\nMercedes!\n\n[LAWP_51:LAWYER1]\nOh, I was just taking my friend back into town.\n\n[LAWP_52:LAWYER1]\nAnother time, Ricardo!\n\n[LAWP_53:LAWYER1]\nLet's get out of here.\n\n[LAWP_54:LAWYER1]\nActually, take me to the Pole Position club.\n\n[LAW1_2:LAWYER1]\n~g~Get to the Colonel's boat.\n\n[LAW1_4:LAWYER1]\n~r~You killed the Colonel's daughter!\n\n[LAW1_5:LAWYER1]\nWill you be working for my father?\n\n[LAW1_6:LAWYER1]\nMaybe.\n\n[LAW1_7:LAWYER1]\nDo you mind me resting my hand in your lap?\n\n[LAW1_8:LAWYER1]\nMaybe...\n\n[LAW1_9:LAWYER1]\nIt's so difficult having a rich and powerful father. Vamos.\n\n[LAW1_10:LAWYER1]\nSee you around, handsome!\n\n[LAW1_11:LAWYER1]\nI'm sure you will.\n\n[LAW1_12:LAWYER1]\nHmmmm...nice bike.\n\n[LAW1_13:LAWYER1]\nNo! My Bike!\n\n[LAW1_3:LAWYER1]\n~g~Take the Colonel's daughter to the Pole Position club.\n\n[HELP20:LAWYER1]\nFollow the ~h~T-shirt~w~ blip on the radar to find Rafael's.\n\n[LAW1_14:LAWYER1]\nWow, I like, really dig your motorcycle.\n\n[LAW1_15:LAWYER1]\nYeah babe, just picked it up from Howlin' Pete's\n\n{=================================== MISSION TABLE LAWYER2 ===================================}\n\n[LAW2_A:LAWYER2]\nAh! Well, I hope you're having a good time. Because I'm going out of my mind with worry here. What did you find out?\n\n[LAW2_B:LAWYER2]\nThat there are more criminals in this town than in prison. We need a lead from the streets...\n\n[LAW2_C:LAWYER2]\nOk, let me think, let me think, let me think -\n\n[LAW2_D:LAWYER2]\n- AH! I've got it!\n\n[LAW2_E:LAWYER2]\nOk, There's this limey, some music industry slimeball,\n\n[LAW2_F:LAWYER2]\ngoes by the name of Kent Paul.\n\n[LAW2_G:LAWYER2]\nAnyway, he's got his nose so far up most of Vice City's ass\n\n[LAW2_I:LAWYER2]\nit's this guy, all right? He's always at The Malibu.\n\n[LAW2_J:LAWYER2]\nI'll go pay him a visit.\n\n[LAW2B_A:LAWYER2]\nWhere'd you pop up from?\n\n[LAW2B_B:LAWYER2]\nI've been looking for a bird like you for ages, mate...\n\n[LAW2B_C:LAWYER2]\nKent Paul, mate. Yeah, I'm the guvnor 'round here.\n\n[LAW2B_D:LAWYER2]\nI'm looking for some English guy...\n\n[LAW2B_E:LAWYER2]\nI sort things out, you know what I mean?\n\n[LAW2B_F:LAWYER2]\nI'll treat you. Whatever you want, I'll get you, girl.\n\n[LAW2B_G:LAWYER2]\nDon't you worry about a thing, mate.\n\n[LAW2B_H:LAWYER2]\nGet lost, honey.\n\n[LAW2B_I:LAWYER2]\nOi oi oi oi oi!\n\n[LAW2B_J:LAWYER2]\nYou Kent Paul? I'm a friend of Rosenberg's...\n\n[LAW2B_K:LAWYER2]\nRosenberg...Rosenberg...Oh, that bonkers ambulance chaser!\n\n[LAW2B_L:LAWYER2]\nThat guy could defend an innocent man all the way to death row!\n\n[LAW2B_M:LAWYER2]\nGive us another drink, bruv.\n\n[LAW2B_N:LAWYER2]\nEverybody's a comedian.\n\n[LAW2B_O:LAWYER2]\nListen to me, I'm missing twenty keys and a lot of cash...\n\n[LAW2B_P:LAWYER2]\nDrugs, mate? It's a mug's game.\n\n[LAW2B_Q:LAWYER2]\nWhat do you know about it?\n\n[LAW2B_R:LAWYER2]\nOi oi! What I was coming to was,\n\n[LAW2B_S:LAWYER2]\nthere's some chef-cum-trumpetshifter who deals out kitchen of a hotel on Ocean Drive.\n\n[LAW2B_T:LAWYER2]\nHe's been looking real pleased with himself lately. You could go and check him out...?!\n\n[LAW2B_U:LAWYER2]\nI will - and I'll be seeing you around.\n\n[LAW2B_V:LAWYER2]\nYeah, that's right. Go on - walk away, you mug. I'll knock you spark out!\n\n[LAW2B_W:LAWYER2]\nGive me a drink - and where's that slut!\n\n[LAW2C_A:LAWYER2]\nOh, way to go, tough guy. Beat him to a pulp. That should make him real chatty.\n\n[LAW2C_B:LAWYER2]\nYou want some, too?\n\n[LAW2C_C:LAWYER2]\nHey, chill. I want what you want, brother.\n\n[LAW2C_D:LAWYER2]\nOh, yeah? And what's that?\n\n[LAW2C_E:LAWYER2]\nYour green - and my dead brother's white lady. Unfortunately, you just silenced our lead.\n\n[LAW2C_F:LAWYER2]\nAccidents happen. Get lost.\n\n[LAW2C_G:LAWYER2]\nHey, hey, whoa. No need to go all 'Lone Ranger' on my ass.\n\n[LAW2C_H:LAWYER2]\nThe way I see it - we two hombres in a strange town. We need to watch each other's back.\n\n[LAW2C_I:LAWYER2]\nMy back's just fine, brother...\n\n[LAW2C_J:LAWYER2]\nYou sure about that? Here, take this.\n\n[LAW2C_K:LAWYER2]\nFollow me!\n\n[LAW2_1:LAWYER2]\nHey, whatchoo lookin' at?\n\n[LAW2_2:LAWYER2]\nYou better start talking..\n\n[LAW2_3:LAWYER2]\nHey, make me, you prick!\n\n[LAW2_4:LAWYER2]\nThis way!\n\n[LAW2_5:LAWYER2]\nI'm going to go see what I can dig up. I'll be watching you, Tommy.\n\n[LAW2_6:LAWYER2]\n~g~Go to the Malibu Club and find Kent Paul.\n\n[LAW2_7:LAWYER2]\n~g~Go and find the chef on Ocean Drive.\n\n[LAW2_10:LAWYER2]\n~g~Drive back to the hotel.\n\n[LAW2_11:LAWYER2]\n~g~Pick up his cell phone.\n\n[LAW2_12:LAWYER2]\nCell phone acquired! You can now receive phone calls.\n\n[LAW2_13:LAWYER2]\n~g~You've left Lance behind! Go and get him!\n\n[LAW2_14:LAWYER2]\nWe gotta get the hell outta here!\n\n[GUN_2A:LAWYER2]\nHold the ~h~~k~~PED_LOCK_TARGET~ ~w~button to ~h~auto-target~w~, press the ~h~~k~~PED_FIREWEAPON~ ~w~button to ~h~fire!\n\n[GUN_2C:LAWYER2]\nHold the ~h~~k~~PED_LOCK_TARGET~ ~w~button to ~h~auto-target~w~, press the ~h~~k~~PED_FIREWEAPON~ ~w~button to ~h~fire!\n\n[GUN_2D:LAWYER2]\nHold the ~h~~k~~PED_LOCK_TARGET~ ~w~button to ~h~auto-target~w~, press the ~h~~k~~PED_FIREWEAPON~ ~w~button to ~h~fire!\n\n[HELP17:LAWYER2]\nPress the ~h~~k~~PED_FIREWEAPON~ ~w~button to attack the chef.\n\n[HELP18:LAWYER2]\nPress the~h~ ~k~~PED_FIREWEAPON~ ~w~button to attack the chef.\n\n[LAW3_11:LAWYER2]\nStand in the ~q~pink marker~w~ to view the weapons on offer.\n\n[LAW3_12:LAWYER2]\nYou can select weapons by pressing ~h~left~w~ or ~h~right~w~ on the ~h~directional button.\n\n[LAW3_13:LAWYER2]\nIf you have enough cash you can buy weapons by pressing the ~h~~k~~PED_SPRINT~ ~w~button.\n\n[LAW3_14:LAWYER2]\nYou can exit the shop by pressing the ~h~~k~~VEHICLE_ENTER_EXIT~ ~w~button.\n\n[LAW3_15:LAWYER2]\nFollow the ~h~Gun blip~w~ on the radar to find ~h~Ammu-Nation.\n\n[LAW2_15:LAWYER2]\n~g~Go to Ammu-Nation.\n\n[LAW2_H:LAWYER2]\nthat if anybody knows the whereabouts of 20 k's of coke,\n\n[LAW2_K:LAWYER2]\nTake it easy now.\n\n[LAW2_16:LAWYER2]\nOne thing you gotta realize about this town. You gotta pack some heat.\n\n[LAW2_17:LAWYER2]\nC'mon, the local gun shop's a couple of blocks away.\n\n[LAW2_18:LAWYER2]\nTommy, every man needs a little R&R once in a while.\n\n[LAW2_19:LAWYER2]\nThis here's the Pole Position Strip Club. You might want to drop in some time.\n\n{=================================== MISSION TABLE LAWYER3 ===================================}\n\n[LAW3_A:LAWYER3]\nAaah! Oh, for god's sake, it's you! Oh, Jeez - I'm gonna need new pants!\n\n[LAW3_B:LAWYER3]\nHey, those psychos from up north - they've been on the horn, and they're coming down here soon.\n\n[LAW3_C:LAWYER3]\nNow where is the goddamn money?!\n\n[LAW3_D:LAWYER3]\nRelax, relax. We're not at that part yet.\n\n[LAW3_E:LAWYER3]\nOhhh... I thought that you were taking care of this, I really did!\n\n[LAW3_F:LAWYER3]\nAnd now those guidos say we gotta do them a favor.\n\n[LAW3_G:LAWYER3]\nYou mean I gotta do 'em a favor.\n\n[LAW3_H:LAWYER3]\nOh, of course that's what I mean. Do I look like I can intimidate a jury?\n\n[LAW3_I:LAWYER3]\nI couldn't intimidate a child - and believe me, I've tried.\n\n[LAW3_J:LAWYER3]\nNow, look. It's either that, or Forelli's cousin, Giorgio, gets five years for fraud.\n\n[LAW3_K:LAWYER3]\nYou gotta take these guys OUT!\n\n[LAW3_L:LAWYER3]\nI understand. Help the jury change their minds. Don't worry about it.\n\n[LAW3_M:LAWYER3]\nNo no no no no - NO! I tried that. The jury case didn't go so well,\n\n[LAW3_N:LAWYER3]\nso MAKE them change their minds.\n\n[LAW3_1:LAWYER3]\nGiorgio sends his regards.\n\n[LAW3_2:LAWYER3]\nRemember, guilty is a dirty word.\n\n[LAW3_3:LAWYER3]\nInnocent until I say otherwise.\n\n[LAW3_4:LAWYER3]\nYou know he's not guilty.\n\n[LAW3_5:LAWYER3]\nYou remember Giorgio? You remember he's innocent.\n\n[LAW3_6:LAWYER3]\nNot guilty, understand? Good.\n\n[LAW3_8:LAWYER3]\n~r~You killed a Juror!\n\n[LAW3_9:LAWYER3]\n~g~Smash up the Juror's car to get him out!\n\n[HELP40:LAWYER3]\nYou can smash cars up by using the hammer or a similar weapon.\n\n[HELP41:LAWYER3]\nor you can ram them with a vehicle\n\n[LAW3_20:LAWYER3]\n~g~Smash up the Juror's car!\n\n[LAW3_21:LAWYER3]\nI can't believe this is happening!\n\n[LAW3_22:LAWYER3]\nUnbelievable!\n\n[LAW3_23:LAWYER3]\nOk! Ok, man! I get the message!\n\n[LAW3_24:LAWYER3]\n~g~That hammer would be useful.\n\n[LAW3_7:LAWYER3]\n~g~Go and intimidate the two jurors, but DON'T kill them!\n\n[HELP23:LAWYER3]\nYou can follow the ~h~hammer blip~w~ on the radar if you want to buy melee weapons from the hardware store.\n\n[LAW3_16:LAWYER3]\nDumb Florida Moron.\n\n[LAW3_17:LAWYER3]\nGet out of the way!\n\n{=================================== MISSION TABLE LAWYER4 ===================================}\n\n[LAW4_A:LAWYER4]\nAvery, it goes without saying... Tommy! Tommy! Any progress? No, no, no - tell me later, tell me later.\n\n[LAW4_B:LAWYER4]\nTommy, this is Avery Carrington - I believe you met at the party?\n\n[LAW4_C:LAWYER4]\nNot in person.\n\n[LAW4_D:LAWYER4]\nHowdy.\n\n[LAW4_E:LAWYER4]\nAvery here has a proposition.\n\n[LAW4_F:LAWYER4]\nHaven't we got other things on our mind?\n\n[LAW4_G:LAWYER4]\nI'm trying to keep the wolves from the door, so could you please cut me some slack?\n\n[LAW4_H:LAWYER4]\nI'm stretched like a wire and even if I'm dead by the end of the week, I'd like to think that I didn't die poor.\n\n[LAW4_I:LAWYER4]\nNow just calm down, both of you.\n\n[LAW4_J:LAWYER4]\nSon, you help me and any greaseballs giving you a hard time, I'll see to it they take a long dirt nap.\n\n[LAW4_K:LAWYER4]\nOk. What could I do for ya'?\n\n[LAW4_L:LAWYER4]\nThis delivery company's got its depot on some prime land. They won't sell.\n\n[LAW4_M:LAWYER4]\nThey're hanging on like a big old prairie rat, so we gotta go in there and smoke that vermin out.\n\n[LAW4_N:LAWYER4]\nHead on down there and stir up a hornet's nest\n\n[LAW4_O:LAWYER4]\n- the security will have their hands full and then you can sneak in and put 'em out of business.\n\n[LAW4_P:LAWYER4]\nAnd you could drop by Rafael's for a change of clothes. You might be there a while, but yeah, go for it.\n\n[LAW4_Q:LAWYER4]\nShould be a riot.\n\n[LAW4_R:LAWYER4]\nIf the balls drop like they should, stop by my office sometime...\n\n[LAW4_1:LAWYER4]\nPlease disperse. The management will discuss any grievances in the appropriate manner!\n\n[LAW4_2:LAWYER4]\nPlease disperse. Go back to your homes!\n\n[LAW4_3:LAWYER4]\nPlease disperse! This is inappropriate!\n\n[LAW4_4:LAWYER4]\nPlease disperse. You will all end up on the streets.\n\n[LAW4_5:LAWYER4]\nSticks out, boys! Let's crack some commie skulls!\n\n[LAW4_13:LAWYER4]\n~g~Start fighting with at least 4 workers to get a riot started.\n\n[LAW4_14:LAWYER4]\n~g~Destroy the vans in the compound!\n\n[HELP38:LAWYER4]\nIf you take out someone who's holding a weapon, they will drop it.\n\n[HELP39:LAWYER4]\nYou can target and shoot explosive barrels but keep your distance.\n\n{=================================== MISSION TABLE MIAMI_1 ===================================}\n\n[T4X4_1A:MIAMI_1]\n~g~You have ~1~ seconds to collect ~y~24~g~ checkpoints. ~g~You may collect them in ~y~ANY ORDER.\n\n[T4X4_1B:MIAMI_1]\n~y~PASS THROUGH~g~ the first checkpoint to start the ~r~TIMER.\n\n[T4X4_1C:MIAMI_1]\n~1~ of 24!\n\n[GETBIK1:MIAMI_1]\nYou have ~1~ seconds to get on a PCJ 600!\n\n[GETBIK3:MIAMI_1]\n~r~You need a PCJ 600 to attempt this mission!\n\n{=================================== MISSION TABLE MM ===================================}\n\n[BLOD_04:MM]\nCAR HEALTH:\n\n[BLOD_05:MM]\n~g~TARGET TIME: ~1~ Minute\n\n[BLOD_06:MM]\n~g~TARGET TIME: ~1~ Minutes\n\n[BLOD_07:MM]\nNEW Best Time: ~1~ Seconds\n\n[BLOD_08:MM]\nCars Destroyed: ~1~\n\n[BLOD_09:MM]\n$~1~\n\n[BLOD_10:MM]\nWINNER!!\n\n[BLOD_01:MM]\nDrive through the checkpoints to increase your overall time.\n\n[BLOD_02:MM]\nYou will fail if your overall time reaches zero.\n\n[BLOD_03:MM]\nGet your overall time above the Target Time to win!\n\n{=================================== MISSION TABLE OVALRIG ===================================}\n\n[HOTR_01:OVALRIG]\n~g~The Race lasts for 12 laps. Only 1st, 2nd and 3rd places qualify for winnings.\n\n[HOTR_02:OVALRIG]\n~g~If your car is destroyed you will be disqualified.\n\n[HOTR_03:OVALRIG]\n~g~When your car is damaged you can get it repaired at the pitstop.\n\n[HOTR_04:OVALRIG]\n~g~This is the way to leave the stadium.\n\n[HOTR_05:OVALRIG]\nCar Health:\n\n[HOTR_06:OVALRIG]\nLaps:\n\n[HOTR_07:OVALRIG]\nNew best time: ~1~:0~1~\n\n[HOTR_08:OVALRIG]\nTime: ~1~:~1~\n\n[HOTR_10:OVALRIG]\nRace Time:\n\n[HOTR_09:OVALRIG]\nPosition:\n\n[HOTR_12:OVALRIG]\n~r~Your car has been destroyed!\n\n[HOTR_13:OVALRIG]\n~r~You didn't win the race!\n\n[HOTR_14:OVALRIG]\n~r~You have been disqualified!\n\n[HOTR_15:OVALRIG]\nTime: ~1~:~1~\n\n[HOTR_16:OVALRIG]\nTime: ~1~:0~1~\n\n[HOTR_17:OVALRIG]\nBest Time: ~1~:~1~\n\n[HOTR_18:OVALRIG]\nBest Time: ~1~:0~1~\n\n[HOTR_19:OVALRIG]\nBest Time: NA\n\n[HOTR_20:OVALRIG]\nNew Best Time: ~1~:~1~\n\n[HOTR_21:OVALRIG]\nNew Best Time: ~1~:0~1~\n\n[HOTR_22:OVALRIG]\nBest Result: NA\n\n[HOTR_23:OVALRIG]\nBest Result: 1st\n\n[HOTR_24:OVALRIG]\nBest Result: 2nd\n\n[HOTR_25:OVALRIG]\nBest Result: 3rd\n\n[HOTR_26:OVALRIG]\nBest Result: ~1~th\n\n[HOTR_27:OVALRIG]\nBest Lap Time: ~1~.~1~ seconds\n\n[HOTR_28:OVALRIG]\nBest Lap Time: ~1~.0~1~ seconds\n\n[HOTR_29:OVALRIG]\n$~1~\n\n[HOTR_30:OVALRIG]\n1ST PLACE\n\n[HOTR_31:OVALRIG]\n2ND PLACE\n\n[HOTR_32:OVALRIG]\n3RD PLACE\n\n[HOTR_33:OVALRIG]\nBest Lap Time: NA\n\n[HOTR_11:OVALRIG]\nNew best lap time: ~1~.~1~ seconds\n\n[HOTR_34:OVALRIG]\nNew best lap time: ~1~.0~1~ seconds\n\n{=================================== MISSION TABLE PHIL1 ===================================}\n\n[PHIL1_A:PHIL1]\nPhil?\n\n[PHIL1_B:PHIL1]\nRUN!\n\n[PHIL1_C:PHIL1]\nRun\n\n[PHIL1_E:PHIL1]\nShit Phil, you drink that stuff?\n\n[PHIL1_F:PHIL1]\nHell, you don't have to drink it\n\n[PHIL1_G:PHIL1]\n- just a good whiff will set you off. Hoowwee!\n\n[PHIL1_H:PHIL1]\nListen Phil, you said you could fix me up with some firepower...\n\n[PHIL1_I:PHIL1]\nSure thing.\n\n[PHIL1_J:PHIL1]\nThere's some Mexican gun-runner been doing me for business of late.\n\n[PHIL1_K:PHIL1]\nHe does his weekly run about now.\n\n[PHIL1_L:PHIL1]\nRam his hardware off the back of his trucks before he goes to ground.\n\n[PHIL1_M:PHIL1]\nAnd you'd be doing me a favor while you're at it.\n\n[PHIL1_N:PHIL1]\nThen finish him off.\n\n[PHI1_01:PHIL1]\n~g~Go and knock the arms off the back of the dealers' trucks.\n\n[PHI1_02:PHIL1]\n~g~The arms dealer dropped his load. Smash the crate and pick up the weapon.\n\n[PHI1_03:PHIL1]\n~g~Looks like they have called for back up.\n\n[PHI1_04:PHIL1]\n~g~Now go and finish off the remaining arms dealers.\n\n[PHI1_HP:PHIL1]\nWhen using Detonator Grenades, throw a grenade then trigger the explosion at any time.\n\n[PHIL1_O:PHIL1]\nHoooooweeeeee!\n\n[PHIL1_D:PHIL1]\nNever get a naked flame too close to one of Phil Cassidy's Boomshine stills!\n\n{=================================== MISSION TABLE PHIL2 ===================================}\n\n[PHIL2_A:PHIL2]\nHey Phil, how's it goin?\n\n[PHIL2_B:PHIL2]\nHeeyyyy, Tommy. Howyadoin'? Ish been too long...\n\n[PHIL2_C:PHIL2]\nI swear you should lay off that boomshine, man -\n\n[PHIL2_D:PHIL2]\nsmells like paint stripper. Making my eyes burn...\n\n[PHIL2_E:PHIL2]\nShshs shhh youshelf Tommy,\n\n[PHIL2_F:PHIL2]\nand come over here because there's someshin' I wanna show you.. someshin.\n\n[PHIL2_G:PHIL2]\nWoof! God! Should I be able to smell that from way over here? I'm feeling woozy.\n\n[PHIL2_H:PHIL2]\nDon'tchaworry about the shmell Tommy, you jush wash thish.\n\n[PHIL2_I:PHIL2]\nShittycheapbatteriesh or shumin'. There'sh shum more on the bench.\n\n[PHIL2_J:PHIL2]\nTA-DAAA!\n\n[PHIL2_K:PHIL2]\nAww Damn!\n\n[PHI2_01:PHIL2]\n~g~Quick, get Phil to the hospital.\n\n[PHI2_03:PHIL2]\n~r~Phil Cassidy is dead!!! Now who's gonna supply arms in Vice City?\n\n[PHI2_05:PHIL2]\nNot the hospital, man! Too many cops and Viet Cong!\n\n[PHI2_06:PHIL2]\nThere's an ex-army surgeon owes me a few favors and a lawnmower.\n\n[PHI2_07:PHIL2]\nHe's got a place down Little Havana - ooo look, a giant fish.\n\n[PHI2_08:PHIL2]\nWatch out! Charlie in the tree line!\n\n[PHI2_09:PHIL2]\nIs it me or are the roads made of jelly?\n\n[PHI2_10:PHIL2]\nBroken Spoon to Mother Hen, you copy?\n\n[PHI2_11:PHIL2]\nSpooney Wooney Woo Woo Woooo!\n\n[PHI2_12:PHIL2]\nHe's come for me boy!\n\n[PHI2_13:PHIL2]\nBlack feathered wings beating all around...\n\n[PHI2_14:PHIL2]\nIt's beautiful, man ... it's beautiful ... but so cold ...\n\n[PHI2_15:PHIL2]\n10-4 we've got a drunk driver.\n\n[PHI2_04:PHIL2]\nPHIL'S HEALTH:\n\n[PHI_AS1:PHIL2]\nPHILS PLACE ASSET COMPLETED\n\n[PHI_AS2:PHIL2]\n~g~New Weapons available to purchase from Phils Place.\n\n{=================================== MISSION TABLE PIZZA ===================================}\n\n[PIZ1_01:PIZZA]\n~g~Go deliver these pizzas, you must throw the pizza to the customers. Do a drive-by to throw the pizzas.\n\n[PIZ1_02:PIZZA]\n~g~You have thrown all your pizzas, go back and get some more.\n\n[PIZ1_05:PIZZA]\n~g~You have five minutes to deliver the orders before the customers phone another pizza shop.\n\n[PIZ1_07:PIZZA]\n~r~You killed the customer! You're fired.\n\n[PIZ1_08:PIZZA]\n~r~You are out of time. You're fired.\n\n[PIZ1_09:PIZZA]\n~r~You destroyed our bike! You're fired.\n\n[PIZ1_11:PIZZA]\nHey! Get back on the bike!\n\n[PIZ1_12:PIZZA]\nPizzas left:\n\n[PIZ1_06:PIZZA]\nPress the~h~ ~k~~TOGGLE_SUBMISSIONS~~w~ when on the bike to cancel the mission.\n\n[PIZ1_13:PIZZA]\nGet these delivered nice and hot.\n\n[PIZ1_14:PIZZA]\nPal, pizza's for you.\n\n[PIZ1_15:PIZZA]\nHey, come on Mister, deliver these quick.\n\n[PIZ1_16:PIZZA]\nWhat are you waiting around for Mister? You got pizza to deliver.\n\n[PIZ1_17:PIZZA]\nI know you didn't want to be a pizza boy, well I don't give a damn.\n\n[PIZ1_18:PIZZA]\nDeliver these.\n\n[PIZ1_19:PIZZA]\nThese need delivering.\n\n[PIZ1_20:PIZZA]\nCome on Mister, deliver these things or you're sacked.\n\n[PIZ1_21:PIZZA]\nWe got people waiting pal.\n\n[PIZ1_22:PIZZA]\nWhat are you waiting around for? These need delivering!\n\n[PIZ1_23:PIZZA]\nDeliver the damn food Mister.\n\n[PIZ1_24:PIZZA]\nThese need delivering pal.\n\n[PIZ1_25:PIZZA]\nMan, can you take these?\n\n[PIZ1_26:PIZZA]\nMister, deliver these pronto, avamos amigo.\n\n[PIZ1_27:PIZZA]\nCome on, we're in a rush, deliver these.\n\n[PIZ1_28:PIZZA]\nYou again? well deliver these quick pal.\n\n[PIZ1_29:PIZZA]\nNo wasting time this time pal.\n\n[PIZ1_30:PIZZA]\nCome on you lazy bastard, deliver this crap on time.\n\n[PIZ1_31:PIZZA]\nYou'll never get a promotion unless you move faster this time.\n\n[PIZ1_32:PIZZA]\n~r~Pizza's too hot to handle?\n\n[PIZ1_33:PIZZA]\n~g~Return to the restaurant for more orders.\n\n[PIZ1_34:PIZZA]\n~g~Pizza delivered, here's your cash.\n\n[PIZ_WON:PIZZA]\nPizza Mission Complete. Your max Health increased to 150.\n\n{=================================== MISSION TABLE PORN1 ===================================}\n\n[POR1_A:PORN1]\nAction.\n\n[POR1_B:PORN1]\nWhoa! Now that's big.\n\n[POR1_C:PORN1]\n12 inches. That is regulation baby.\n\n[POR1_D:PORN1]\nCUT!! Who IS this idiot? You! YOU! Why are you in my space? WHY?\n\n[POR1_E:PORN1]\nWhat is all this crap?\n\n[POR1_F:PORN1]\nAliens? Fishing poles?\n\n[POR1_G:PORN1]\nWho's ever seen a shark that big?\n\n[POR1_H:PORN1]\nAll this stuff's gotta go.\n\n[POR1_I:PORN1]\nWhy'd you get in this business, ya prick?\n\n[POR1_J:PORN1]\nHuh?\n\n[POR1_K:PORN1]\nFor the pussy, that's why! What is this??\n\n[POR1_L:PORN1]\nThis is my art - SECURITY!\n\n[POR1_M:PORN1]\nLook, you pompous asshole, I own you now. I own all of this.\n\n[POR1_N:PORN1]\nWe're gonna turn this place around...\n\n[POR1_O:PORN1]\nI'm gonna make you rich.\n\n[POR1_P:PORN1]\nUh. You're - You - you're Tommy Vercetti? But I thought that you were...\n\n[POR1_Q:PORN1]\nThat's right.\n\n[POR1_R:PORN1]\nWe're gonna be making some changes around here and start making some real money.\n\n[POR1_S:PORN1]\nActually, have you ever thought about, umm...\n\n[POR1_T:PORN1]\nBut first we're going to need some good-looking broads.\n\n[POR1_U:PORN1]\nYeh, girls are fine but you... whew!\n\n[POR1_02:PORN1]\n~g~ Go and take out Candy's pimp, then return and pick up Candy.\n\n[POR1_04:PORN1]\nYo, Candy. I'm looking for movie talent - you interested?\n\n[POR1_05:PORN1]\nSure! But, you'd have to talk to my agent...\n\n[POR1_06:PORN1]\nThe HELL are you doin'?\n\n[POR1_07:PORN1]\nYou should have stayed at home today!\n\n[POR1_7B:PORN1]\nCan you believe this asshole?\n\n[POR1_08:PORN1]\nHey Mercedes!\n\n[POR1_09:PORN1]\nHey Tommy! You wanna party?\n\n[POR1_10:PORN1]\nNot now sweets. You interested in doing some movies?\n\n[POR1_11:PORN1]\nOf course. As long as it's cheap and sleazy.\n\n[POR1_13:PORN1]\n~g~Take the girls back to the Studio to meet Steve.\n\n[POR1_17:PORN1]\nWhoa, cool shark!\n\n[POR1_18:PORN1]\n~r~Mercedes is dead!\n\n[POR1_20:PORN1]\nTommy where are you going? Get back here!\n\n[POR1_21:PORN1]\nWhere are you going?\n\n[POR1_22:PORN1]\nTommy, when are we going to spend some time alone together?\n\n[POR1_01:PORN1]\n~g~Candy Suxxx would be perfect for a starring role!\n\n[POR1_12:PORN1]\n~g~Take Candy with you to meet up with Mercedes.\n\n[POR1_16:PORN1]\nMaybe later, babe...\n\n[POR1_24:PORN1]\n~g~Go back and collect Candy.\n\n[POR1_25:PORN1]\n~g~You have left Candy behind, go and get her.\n\n[POR1_23:PORN1]\n~g~Candy will be taking care of business ~h~Downtown~g~.\n\n[POR1_26:PORN1]\n~g~Here's Candy, looks like she has been with Congressman Shrub again.\n\n[POR1_15:PORN1]\nTommy, you coming in for a warm-up?\n\n[POR1_14:PORN1]\nHeh heh - you're hired!\n\n[POR1_27:PORN1]\nCome on, let's go.\n\n[POR1_28:PORN1]\nTommy be careful! My implants aren't insured yet!\n\n[POR1_29:PORN1]\nYou call that driving?\n\n[POR1_30:PORN1]\nI can't do porno after this!\n\n[POR1_31:PORN1]\nWhat? Are you trying to kill me? I thought I was the star!\n\n{=================================== MISSION TABLE PORN2 ===================================}\n\n[POR2_A:PORN2]\nHow's filming going, Steve?\n\n[POR2_B:PORN2]\nWell, Candy is a natural and that new girl - she's insatiable!\n\n[POR2_C:PORN2]\nShe went through half the cast and crew before I even took a light reading.\n\n[POR2_D:PORN2]\nAnyway, hey, tomorrow we're going on location to shoot the boat scenes -\n\n[POR2_E:PORN2]\nBoat scenes?! What boat scenes?\n\n[POR2_F:PORN2]\nThe fishermen are in the throes of passion when this giant shark comes in -\n\n[POR2_G:PORN2]\nWhat'd I say about the giant shark?\n\n[POR2_H:PORN2]\nI said, 'NO GIANT SHARK', alright?\n\n[POR2_I:PORN2]\nJust keep the cameras pointed at the poontang!\n\n[POR2_J:PORN2]\nOk ok, hey Tommy, a guy's gotta try, right?\n\n[POR2_K:PORN2]\nGet those flyers printed up?\n\n[POR2_L:PORN2]\nYeah, but nobody's gonna let us distribute those things, I mean\n\n[POR2_M:PORN2]\nThey're just too, uh, they're unimaginative.\n\n[POR2_N:PORN2]\nYou don't worry about that.\n\n[POR2_O:PORN2]\nI've got my own ideas for distribution.\n\n[POR2_P:PORN2]\nO.K. Hey, Candy, uh - in my trailer.\n\n[POR2_01:PORN2]\n~g~There is a seaplane that was used as a prop in some old indie film round the back of the studios.\n\n[POR2_02:PORN2]\n~g~Pick one of the checkpoints to start dropping the flyers from.\n\n[POR2_03:PORN2]\n~g~Drop the flyers all the way to the end checkpoint.\n\n[POR2_04:PORN2]\n~r~LOW FUEL!!!\n\n[POR2_05:PORN2]\n~g~Use it to distribute the flyers around town.\n\n[DILDO:PORN2]\nSkimmer Fuel:\n\n[POR2_Q:PORN2]\nOh, boy.\n\n[PORN2_9:PORN2]\n~g~You have ~1~ seconds to return to a Skimmer before the mission ends.\n\n{=================================== MISSION TABLE PORN3 ===================================}\n\n[POR3_A:PORN3]\nOk, what's the problem now?\n\n[POR3_B:PORN3]\nSSShhhh!\n\n[POR3_C:PORN3]\nWell, after his close encounter with the nympho-invaders,\n\n[POR3_D:PORN3]\nour hero finds himself unable to think of anything but this huge phallic mountain -\n\n[POR3_E:PORN3]\nand that's when I want to do the scene with the vat of mashed potatoes, but then we, uh -\n\n[POR3_F:PORN3]\nI don't give a crap about that!\n\n[POR3_G:PORN3]\nJ - Just keep going, keep going!\n\n[POR3_H:PORN3]\nHey Tommy...\n\n[POR3_I:PORN3]\nYou mentioned something about some legal problem on the phone?\n\n[POR3_J:PORN3]\nCongressman Alex Shrub has jumped on the pre-election bandwagon, he's going after the puritan vote.\n\n[POR3_K:PORN3]\nRumors are he's gonna support measures to restrict, shall we say,\n\n[POR3_L:PORN3]\nthe more fleshy aspects of this nation's great entertainment industry.\n\n[POR3_M:PORN3]\nGreat.\n\n[POR3_N:PORN3]\nCandy! You know Shrub,\n\n[POR3_O:PORN3]\nyou guys get up to anything kinky?\n\n[POR3_P:PORN3]\nOh yeah, oh yeah, oh yeah! Yes yes yes YES OOOoooh!\n\n[POR3_Q:PORN3]\nPlease - tell me you got that.\n\n[POR3_R:PORN3]\nWas that part of the, uh... or was she talking to..?\n\n[POR3_S:PORN3]\nHey, I can never tell. Anyway...\n\n[POR3_T:PORN3]\nYou're probably best following her after the shoot,\n\n[POR3_U:PORN3]\nsee if she'll lead you to their new love nest.\n\n[POR3_V:PORN3]\nYou got a camera?\n\n[POR3_X:PORN3]\nYeah. Get him a camera.\n\n[POR3_02:PORN3]\n~r~You've killed the Congressman! There's no way you can blackmail him now.\n\n[POR3_03:PORN3]\n~r~You've alerted the Congressman's protection, they will get him out of there immediately.\n\n[POR3_04:PORN3]\nUh, Candy, could you call me Martha?\n\n[POR3_05:PORN3]\nOh Alex - I mean Martha. Whatever you say...\n\n[POR3_06:PORN3]\nMartha, someone's watching.. how kinky.\n\n[POR3_07:PORN3]\nYou! Give me that camera!\n\n[POR3_01:PORN3]\n~g~Follow Candy's ~h~Stretch~g~.\n\n[POR3_15:PORN3]\n~r~You trashed Candy's Stretch!\n\n[POR3_17:PORN3]\n~g~Get back to the Porn Studios with the film.\n\n[POR3_19:PORN3]\n~r~You ran out of film!\n\n[POR3_21:PORN3]\n~g~You lost Candy's Stretch!\n\n[POR3_22:PORN3]\n~g~The WK Chariot Hotel across from his balcony should provide an ideal photo-grabbing location.\n\n[POR3_23:PORN3]\n~g~There is a side door that will allow you access to the hotel.\n\n[POR3_08:PORN3]\nPress and hold the~h~ ~k~~PED_LOCK_TARGET~ ~w~button to ~h~target~w~ with the camera.\n\n[POR3_09:PORN3]\nPress and hold the~h~ ~k~~PED_LOCK_TARGET~ ~w~button to ~h~target ~w~with the camera.\n\n[POR3_10:PORN3]\nPress the~h~ ~k~~PED_SNIPER_ZOOM_IN~ ~w~button to ~h~zoom in ~w~with the camera and the~h~ ~k~~PED_SNIPER_ZOOM_OUT~ ~w~button to ~h~zoom out ~w~again.\n\n[POR3_11:PORN3]\nPress the~h~ ~k~~PED_SNIPER_ZOOM_IN~ ~w~button to ~h~zoom in ~w~with the camera and the~h~ ~k~~PED_SNIPER_ZOOM_OUT~ ~w~button to ~h~zoom out ~w~again.\n\n[POR3_12:PORN3]\nPress the~h~ ~k~~PED_FIREWEAPON~ ~w~button to take a picture.\n\n[POR3_13:PORN3]\nPress the~h~ ~k~~PED_FIREWEAPON~ ~w~button to take a picture.\n\n[POR3_14:PORN3]\nPress the~h~ ~k~~PED_FIREWEAPON~ ~w~button to take a picture.\n\n[POR3_20:PORN3]\n~g~If you need transport, use the ~h~Sparrow~g~ round the back.\n\n[POR3_16:PORN3]\n~g~You need three good blackmail photographs of Alex Shrub with Candy.\n\n[POR3_24:PORN3]\nPHOTOS TAKEN:\n\n{=================================== MISSION TABLE PORN4 ===================================}\n\n[POR4_A:PORN4]\nI'm sorry, but I just can't swallow this right now.\n\n[POR4_B:PORN4]\nOh COME ON darling!\n\n[POR4_C:PORN4]\nHe's hung like a sperm whale for pity's sake,\n\n[POR4_D:PORN4]\nhow can you not feel the part?!\n\n[POR4_E:PORN4]\nBut Stevie...\n\n[POR4_F:PORN4]\nHow's my star director?\n\n[POR4_G:PORN4]\nOh, man. The struggle between the artistic integrity and\n\n[POR4_H:PORN4]\nthe humping, pumping action continues unabated.\n\n[POR4_I:PORN4]\nAnd before you ask, yes, all four videos will be released by their...\n\n[POR4_J:PORN4]\nHoney, can you PLEASE keep the anaconda in the shot,\n\n[POR4_K:PORN4]\nhe costs more per hour than you do!\n\n[POR4_L:PORN4]\nOh, sorry Steve.\n\n[POR4_M:PORN4]\nI was thinking, we need some kind of big stunt to really promote the launch.\n\n[POR4_N:PORN4]\nSomething that will make a real impact on the City - you got any ideas?\n\n[POR4_O:PORN4]\nWell, in the old days they used to have gala events,\n\n[POR4_P:PORN4]\nstars, limos, the night sky crisscrossed with searchlights...\n\n[POR4_Q:PORN4]\nSearchlights! I've got an idea...\n\n[POR4_R:PORN4]\n...yeah, yeah, yeah. The little sequined numbers, and the limos, oh, premieres\n\n[POR4_S:PORN4]\nOh, yes ma'am, of course ma'am,\n\n[POR4_T:PORN4]\nand the press, and the barrage of lights...\n\n[POR4_01:PORN4]\n~g~Go ~y~Downtown~g~ and adjust the spotlight on top of the building.\n\n[POR4_02:PORN4]\n~g~A fast bike will be needed to jump from roof to roof. The Security Guard usually drives a ~y~PCJ 600~g~ to work...\n\n[POR4_03:PORN4]\n~g~You will need to get onto the roofs of the buildings. There should be a lift into one of the upper offices...\n\n[POR4_06:PORN4]\n~g~Return to the lower office if you need access to the rooftops again.\n\n[POR4_07:PORN4]\n~g~You will need a bike so you can jump from building to building.\n\n[POR4_08:PORN4]\n~g~Smash through the window to start the course. You have until 07:00 before it gets too light to get up there unseen.\n\n[POR4_09:PORN4]\n~g~The pickups will show you which building to jump to next.\n\n[POR4_10:PORN4]\n~r~It's too light to get up there unseen.\n\n[POR4_11:PORN4]\n~g~Return to the ladder if you need access to the rooftops again.\n\n[POR4_05:PORN4]\n~g~These stairs will lead round to a lower office.\n\n[POR_AS1:PORN4]\nFILM STUDIO ASSET COMPLETED\n\n[POR_AS2:PORN4]\n~g~Inter Global Films will now generate revenue up to a maximum of $~1~. Make sure you collect it regularly.\n\n{=================================== MISSION TABLE PROT1 ===================================}\n\n[PRO1_B:PROT1]\nI can't stand this look. Tommy, whadaya say? Whadaya say we put a bar in...\n\n[PRO1_D:PROT1]\nListen to me,\n\n[PRO1_E:PROT1]\nThe time to take over this town is now. It's all out there waiting for us.\n\n[PRO1_F:PROT1]\nWe need to start seizing territory,\n\n[PRO1_G:PROT1]\nlet Vice City know we're the new players in town, know what I'm saying?\n\n[PRO1_I:PROT1]\nWhat you need is a legitimate front Tommy, real estate. It's never done me no harm.\n\n[PRO1_J:PROT1]\nWe need to start using some muscle or we can kiss all that hard work goodbye.\n\n[PRO1_K:PROT1]\nLocal businesses know Diaz is dead, and they're refusing to pay protection!\n\n[PRO1_L:PROT1]\nOoh! We could try bribery...\n\n[PRO1_M:PROT1]\nBribery? Screw bribery! I'll show you how to make 'em scared!\n\n[PRO1_01:PROT1]\n~g~Do a hit and run on the shop fronts and the owners will be begging for protection.\n\n[PRO1_03:PROT1]\n~r~This was supposed to be a hit and run, not a 'hit and have coffee'.\n\n[PRO1_04:PROT1]\nMy livelihood, destroyed!\n\n[PRO1_05:PROT1]\nRuined...RUINED!!\n\n[PRO1_06:PROT1]\nI pay through the ass for protection!\n\n[PRO1_07:PROT1]\nMy beautiful window display!\n\n[PRO1_08:PROT1]\nMy store. My wonderful store.\n\n[PRO1_09:PROT1]\nVercetti. Remember the name.\n\n[PRO1_10:PROT1]\nI run this town now. ME!\n\n[BUYP1:PROT1]\nYou can now buy property in certain areas of the map.\n\n[BUYP2:PROT1]\nIf you see a green house pickup, you can buy that property.\n\n[PRO1_N:PROT1]\nI'll be back here in five minutes...\n\n[PRO1_11:PROT1]\n~g~Get to ~y~The North Point Mall~g~ in ~y~Vice Point~g~.\n\n[PRO1_12:PROT1]\n~g~Smash the panes of glass in each shop front and the owners will be begging for new protection.\n\n[PRO1_A:PROT1]\nOh, we gotta redecorate this place. We gotta make it look older.\n\n[PRO1_C:PROT1]\nYou're my lawyer, Rosenberg, not my interior decorator. Got it?\n\n[BUYP3:PROT1]\nStand inside the pickup, then press the ~h~~k~~PED_ANSWER_PHONE~~w~ button to purchase that property.\n\n[PRO1_13:PROT1]\n~g~You have five minutes to smash them all.\n\n{=================================== MISSION TABLE PROT2 ===================================}\n\n[PRO2_A:PROT2]\nWhat's the problem?\n\n[PRO2_B:PROT2]\nSome bar is refusing to pay.\n\n[PRO2_C:PROT2]\nThey reckon they're protected by a local gang of thugs.\n\n[PRO2_D:PROT2]\nBut don't worry Tommy, I can handle it.\n\n[PRO2_E:PROT2]\nYou call this handling it?\n\n[PRO2_F:PROT2]\nYou two, off your asses...\n\n[PRO2_G:PROT2]\nLet's go.\n\n[PRO2_10:PROT2]\n~g~Two more have made a run for it. Track them down and finish this.\n\n[PRO2_11:PROT2]\nGet in the car, useless.\n\n[PRO2_02:PROT2]\nYour protection needs a little more protection.\n\n[PRO2_03:PROT2]\nAw hell, not again! I don't need this crap!\n\n[PRO2_04:PROT2]\nThese idiots operate out of DBP Security around the block.\n\n[PRO2_05:PROT2]\nYou guys just sort it out amongst yourselves.\n\n[PRO2_06:PROT2]\nI'll be seeing you later.\n\n[PRO2_07:PROT2]\nYeah, yeah, whatever.\n\n[PRO2_09:PROT2]\n~g~Go and speak to the Front Page Bar Owner.\n\n[PRO2_01:PROT2]\n~g~Take out the guards protecting the Front Page Bar and find out who supplied them.\n\n[PRO2_08:PROT2]\n~g~DBP Security will know you are on your way, go and get them before they clear out.\n\n{=================================== MISSION TABLE PROT3 ===================================}\n\n[PRO3_A:PROT3]\nYou moron! What were you thinking?!\n\n[PRO3_B:PROT3]\nDo you realize what this means?!\n\n[PRO3_C:PROT3]\nWe could all be sunk!\n\n[PRO3_D:PROT3]\nThe timer must have got screwed.\n\n[PRO3_E:PROT3]\nThat place was wired to go up like a firework factory.\n\n[PRO3_F:PROT3]\nThen somebody tipped off the cops...\n\n[PRO3_G:PROT3]\nWhat's the problem, fellas?\n\n[PRO3_H:PROT3]\nMike was supposed to torch some place in the mall,\n\n[PRO3_I:PROT3]\nbut he screwed the fuses and now the cops are crawling all over it.\n\n[PRO3_J:PROT3]\nWe gotta get our stuff and get out of here!\n\n[PRO3_K:PROT3]\nRelax, both of you, let me think for a second!\n\n[PRO3_L:PROT3]\nTommy Vercetti just doesn't cut and run.\n\n[PRO3_M:PROT3]\nThe cops are gonna be going over that building with a fine toothed comb, right?\n\n[PRO3_N:PROT3]\nBut that takes time.\n\n[PRO3_O:PROT3]\nWe gotta go in and torch that place ourselves.\n\n[PRO3_P:PROT3]\nYeah, but...\n\n[PRO3_Q:PROT3]\nNo one but a cop could get within a mile of that place!\n\n[PRO3_R:PROT3]\nSo we go as cops.\n\n[PRO3_S:PROT3]\nWe gotta get uniforms - and we're gonna need a squad car.\n\n[PRO3_T:PROT3]\nAll thanks to you Mike.\n\n[PRO3_U:PROT3]\nI'm sorry.\n\n[PRO3_V:PROT3]\nI got it.\n\n[PRO3_W:PROT3]\nWhat we got to do is lure the cops in with the finger,\n\n[PRO3_X:PROT3]\nput them in a lock-up\n\n[PRO3_Y:PROT3]\nand jump 'em.\n\n[PRO3_Z:PROT3]\nGood plan. Let's go!\n\n[PRO3_A1:PROT3]\nAlright.\n\n[PRO3_01:PROT3]\nOk Lance, let's get the cops' attention!\n\n[PRO3_02:PROT3]\n~g~ Take a cop car and go and plant the bomb at the Tarbrush Coffee Shop in the Mall.\n\n[PRO3_03:PROT3]\n~g~ You've left Lance behind, go and get him.\n\n[PRO3_04:PROT3]\n~g~ Let's go.\n\n[PRO3_05:PROT3]\n~r~You killed Lance!\n\n[PRO3_07:PROT3]\n~g~ You have blown your cover. Hurry up and plant the bomb!\n\n[PRO3_09:PROT3]\nTie 'em up and gag 'em!\n\n[PRO3_10:PROT3]\nOoo. Fits perfectly!\n\n[PRO3_11:PROT3]\nBit tight around the crotch though...\n\n[PRO3_12:PROT3]\nOh yeah yeah, mine too. Mine too.\n\n[PRO3_13:PROT3]\nEasy brother! No cop drives this bad!\n\n[PRO3_14:PROT3]\nRemember - smile at the other cops\n\n[PRO3_15:PROT3]\nHey there officer. Nice badge, nice badge.\n\n[PRO3_16:PROT3]\nReal smooth, Lance.\n\n[PRO3_17:PROT3]\nOk, timers are set, 5 seconds and ticking.\n\n[PRO3_18:PROT3]\n5 seconds?!! We got to get the hell out of here!\n\n[PRO3_19:PROT3]\nNow that got them really irritated.\n\n[PRO3_20:PROT3]\n~g~ Get two cops to follow you into the garage.\n\n[PRO3_21:PROT3]\n~g~Get a wanted level so the cops will follow you into the lock-up.\n\n[PRO3_22:PROT3]\n~g~The lock-up door is blocked! You need to clear the door so it can close.\n\n[PRO3_23:PROT3]\n~g~Walk into the marker to plant the bomb.\n\n[PRO3_24:PROT3]\n~g~Get clear of the Cafe!\n\n[PRO_AS1:PROT3]\nPROTECTION RING ASSET COMPLETED\n\n[PRO_AS2:PROT3]\n~g~Vercetti Estate will now generate revenue up to a maximum of $~1~. Make sure you collect it regularly.\n\n[PRO3_08:PROT3]\n~g~ Get back to ~h~Vercetti Estate~g~ on ~h~Starfish Island~g~.\n\n{=================================== MISSION TABLE RACES ===================================}\n\n[RACES_2:RACES]\n~g~You need a vehicle to race, this is not a foot race!\n\n[RACES_3:RACES]\n3..2..1.. GO GO GO!\n\n[RACES_8:RACES]\n~r~You didn't win the race!\n\n[RACES00:RACES]\nRace ~1~:\n\n[RACES01:RACES]\nTerminal Velocity\n\n[RACES02:RACES]\nOcean Drive\n\n[RACES03:RACES]\nBorder Run\n\n[RACES04:RACES]\nCapital Cruise\n\n[RACES05:RACES]\nTour!\n\n[RACES06:RACES]\nV.C. Endurance\n\n[RACES07:RACES]\nEntrance Fee: $~1~\n\n[RACES08:RACES]\nBest Time: ~1~:~1~\n\n[RACES09:RACES]\nBest Result: 1st\n\n[RACES10:RACES]\nBest Result: 2nd\n\n[RACES11:RACES]\nBest Result: 3rd\n\n[RACES12:RACES]\nBest Result: 4th\n\n[RACES13:RACES]\nTrack Length: ~1~.~1~ km\n\n[RACES15:RACES]\nBest Time: NA\n\n[RACES16:RACES]\nBest Result: NA\n\n[RACES19:RACES]\nYou cannot afford to enter this race.\n\n[RACES22:RACES]\nBest Time: ~1~:0~1~\n\n[RACES23:RACES]\nTrack Length: ~1~.~1~ miles\n\n[RACES_1:RACES]\n~g~Get a fast vehicle and get to the starting grid.\n\n[RACEHLP:RACES]\n~w~Press the~h~ ~k~~PED_SPRINT~ ~w~button to start the selected race. Press the~h~ ~k~~VEHICLE_ENTER_EXIT~ ~w~button to exit.\n\n{=================================== MISSION TABLE RCHELI1 ===================================}\n\n[WRECKED:RCHELI1]\n~r~The vehicle is wrecked!\n\n[RCH1_4:RCHELI1]\nCheckpoints:\n\n[RCH1_7:RCHELI1]\n~g~There are 20 checkpoints in total.\n\n[RCH1_12:RCHELI1]\n~g~The RC helicopter is getting too far out of range!\n\n[RCH1_13:RCHELI1]\n~r~The RC helicopter went out of range!\n\n[RCH1_8:RCHELI1] { reVC update }\n~g~If you wish to quit this mission press the ~h~~k~~VEHICLE_FIREWEAPON~ ~g~button to detonate your RC Helicopter.\n\n{=================================== MISSION TABLE RCPLNE1 ===================================}\n\n[RCPL1_4:RCPLNE1]\n~g~Compete in a CHECKPOINT RACE with 3 other RC Plane's\n\n[RCPL1_5:RCPLNE1]\n~g~Fly through the checkpoints scattered throughout Vice City.\n\n[RCPL1_6:RCPLNE1] { reVC update }\n~g~If you wish to quit this mission press the ~h~~k~~VEHICLE_FIREWEAPON~ ~g~button to detonate your RC Plane.\n\n[RCPL1_8:RCPLNE1]\n~g~Your RC Plane is going out of range!\n\n[RCPL1_9:RCPLNE1]\n~r~Your RC Plane went out of range!\n\n{=================================== MISSION TABLE RCRACE1 ===================================}\n\n[RCRC1_1:RCRACE1]\n~g~Compete in a CHECKPOINT RACE with 3 other RC Bandits over 2 LAPS\n\n[RCRC1_3:RCRACE1]\n~g~Final lap!\n\n[RCR1_4:RCRACE1]\nlaps left:\n\n[RCR1_1:RCRACE1]\n~g~Compete in a checkpoint race with 3 other RC Cars.\n\n[RCR1_2:RCRACE1]\n~g~Be the first to complete two laps of the track to win!\n\n[RCR1_6:RCRACE1]\n~g~Your RC Car is going out of range!\n\n[RCR1_7:RCRACE1]\n~r~Your RC Car went out of range!\n\n{=================================== MISSION TABLE ROCK1 ===================================}\n\n[RBM1_A:ROCK1]\nAllllllllRrrighttt!\n\n[RBM1_B:ROCK1]\nYessss! Brilliant, bloody brilliant!\n\n[RBM1_D:ROCK1]\nHey, you ever met Love Fist before?\n\n[RBM1_E:ROCK1]\nNo, I haven't but I've always loved your music.\n\n[RBM1_F:ROCK1]\nLet me introduce you to the band.\n\n[RBM1_G:ROCK1]\nThis is Percy, Dick, and Willy's in the kaze, and that was Jezz in the booth earlier,\n\n[RBM1_H:ROCK1]\nand guys, I want you to meet a good friend of mine.\n\n[RBM1_I:ROCK1]\nThis is Tommy. We go way back.\n\n[RBM1_J:ROCK1]\nAll right, pal.\n\n[RBM1_K:ROCK1]\nAnd eh, what was your name again?\n\n[RBM1_L:ROCK1]\nLeave it out, Jezz you, remember -\n\n[RBM1_M:ROCK1]\ndon't be playing them games with me, mate,\n\n[RBM1_N:ROCK1]\nI'm too crafty for that, sunshine!\n\n[RBM1_O:ROCK1]\nYou see, the thing is, Tom, the boys need some help.\n\n[RBM1_P:ROCK1]\nThey ain't too connected here, they don't have the old 'how's your father?'\n\n[RBM1_Q:ROCK1]\nWe need some drugs, pal!\n\n[RBM1_R:ROCK1]\nGonna get on the old Love Fist fury, you know?!\n\n[RBM1_S:ROCK1]\nWell, this is Vice City, man. What's the problem?\n\n[RBM1_U:ROCK1]\nLove Juice, man!\n\n[RBM1_V:ROCK1]\nLove Juice?\n\n[RBM1_W:ROCK1]\nAye, two parts boomshine, 1 part trumpet, 5 fizz bombs and a liter of petrol.\n\n[RBM1_X:ROCK1]\nCan you help us out, pal?\n\n[RBM1_Y:ROCK1]\nAw, it would really mean a lot to the boys.\n\n[RBM1_Z:ROCK1]\nYou can do that for the boys, right?\n\n[RBM1_7:ROCK1]\n~r~You did not get the Love Juice in time!\n\n[RBM1_8:ROCK1]\n~r~Mercedes is dead!\n\n[RBM1_10:ROCK1]\n~r~You idiot! You have destroyed the merchandise!\n\n[RBM1_13:ROCK1]\n~g~Get the 'Love Juice' and Mercedes to the band before they are needed on stage.\n\n[RBM1_15:ROCK1]\n~r~You have lost the dealer, our cash and the drugs!\n\n[RBM1_17:ROCK1]\n~g~Kill the dealer and get the drugs!\n\n[MOB_07A:ROCK1]\nHey mate, the guys could do with some company, if you know what I mean...\n\n[MOB_07B:ROCK1]\nI know just the girl.\n\n[ROK1_5:ROCK1]\nHey, Mercedes!\n\n[ROK1_6:ROCK1]\nHiya, Tommy. And how are you?\n\n[ROK1_7:ROCK1]\nJust fine. Listen, you fancy having Love Fist?\n\n[ROK1_8:ROCK1]\nOk, but just as a favor I expect returned..\n\n[RBM1_14:ROCK1]\n~g~You need a car or a motorcycle!\n\n[RBM1_1:ROCK1]\n~g~Go and collect Mercedes from her apartment.\n\n[RBM1_12:ROCK1]\n~g~Go and collect the 'Love Juice' ingredients from the dealer.\n\n[ROK1_2:ROCK1]\nNO LONGER NEEDED\n\n[ROK1_3:ROCK1]\nNO LONGER NEEDED\n\n[MERC_39:ROCK1]\nI'll see you later, big boy.\n\n[RBM1_C:ROCK1]\nHey, Tommy! Glad you could make it.\n\n[RBM1_9:ROCK1]\n~g~Go and collect some love juice from the dealer for Love Fist!\n\n[ROK1_1A:ROCK1]\nLooking for something special? I got what you need!\n\n[ROK1_9:ROCK1]\nThanks for the money, sucker!\n\n[RBM1_T:ROCK1]\nWe need Love Juice, man, you know?\n\n{=================================== MISSION TABLE ROCK2 ===================================}\n\n[RBM2_A:ROCK2]\nTommy, man. Am I glad to see you!\n\n[RBM2_B:ROCK2]\nWhat's going on?\n\n[RBM2_C:ROCK2]\nBad vibes, Tommy....\n\n[RBM2_E:ROCK2]\nThere's this cat, we hardly know him, but he knows us.\n\n[RBM2_F:ROCK2]\nLike this cat. Knows all about us.\n\n[RBM2_G:ROCK2]\nKnows that Willy likes his ladies' underwear, eh!\n\n[RBM2_H:ROCK2]\nOr that Percy likes Duran Duran!\n\n[RBM2_K:ROCK2]\nYeah, the love rocket thing, right. But listen, this cat...\n\n[RBM2_L:ROCK2]\nyeh, yeh, the guy, he wants Love Fist dead.\n\n[RBM2_M:ROCK2]\nDead Tommy.\n\n[RBM2_N:ROCK2]\nLove Fist gone. You know what they say, the good die young.\n\n[RBM2_O:ROCK2]\nbut Tommy, you gotta save Love Fist!\n\n[RBM2_P:ROCK2]\nWe got a signing in two hours and I think...\n\n[RBM2_Q:ROCK2]\nAnd the boys think the stalker's gonna try some monkey business there.\n\n[RBM2_1:ROCK2]\n~g~Drive the limo to the signing event and try to draw the psycho out.\n\n[RBM2_2:ROCK2]\n~r~You've wrecked the band's car!\n\n[RBM2_3:ROCK2]\n~g~Get to the signing!\n\n[RBM2_4:ROCK2]\n~g~Get the Psycho! Don't let him escape!\n\n[RBM2_5:ROCK2]\n~r~You lost him, you idiot!\n\n[RBM2_7:ROCK2]\n~r~The fans have been attacked, the psycho won't show!\n\n[RBM2_8:ROCK2]\n~r~The security guards have been attacked, the psycho won't show!\n\n[PSYCH_1:ROCK2]\nI'll see Love Fist burn!\n\n[PSYCH_2:ROCK2]\nLove Fist ruined my life!\n\n[RBM2_I:ROCK2]\nShut up ye fool. Just 'cause Jezz bangs sheep.\n\n[RBM2_R:ROCK2]\nOi shut it!\n\n[RBM2_D:ROCK2]\nAye, I'm not joking, it's heavy stuff man, heavy you know?\n\n[RBM2_J:ROCK2]\nIt's a love rocket thing, you know?\n\n{=================================== MISSION TABLE ROCK3 ===================================}\n\n[RBM3_A:ROCK3]\nTommy! Tommy! Tommy, man, that psycho's back!\n\n[RBM3_B:ROCK3]\nWhat's going on?\n\n[RBM3_C:ROCK3]\nThat psycho won't leave Love Fist alone!\n\n[RBM3_D:ROCK3]\nYou didnae kill him man. And now he's back.\n\n[RBM3_E:ROCK3]\nYeah, yeah, yeah, and the thing is...\n\n[RBM3_F:ROCK3]\nThe thing is, we need someone to drive the limo we can trust,\n\n[RBM3_G:ROCK3]\ncause that nutter keeps making threats!\n\n[RBM3_I:ROCK3]\nWe're all bricking ourselves, man.\n\n[RBM3_J:ROCK3]\nOkay guys, calm down, I'll handle this.\n\n[RBM3_K:ROCK3]\nNormally I wouldn't busy myself with driving around a bunch of drunken Scottish bisexuals,\n\n[RBM3_L:ROCK3]\nbut, in your case I'll make an exception.\n\n[RBM3_4:ROCK3]\n~r~You've killed Love Fist!\n\n[RBM3_6:ROCK3]\nDETONATION:\n\n[RBM3_1:ROCK3]\n~g~Drive Love Fist to the venue.\n\n[RBM3_2:ROCK3]\nWhile the bomb is armed if you try to leave the car it will explode...\n\n[RBM3_3:ROCK3]\nIf the detonation bar completely fills the bomb will explode.\n\n[RBM3_8:ROCK3]\nThe faster you drive the lower the detonation bar will go.\n\n[RBM3_7:ROCK3]\n~g~BOMB DEFUSED!\n\n[ROK3_62:ROCK3]\nso we thought we'd show you our Temple of Rock -\n\n[ROK3_63:ROCK3]\nGet a feel for that Love Fist fury!\n\n[ROK3_64:ROCK3]\nListen to yourself, man. It's papier-mache and gaffa tape.\n\n[ROK3_65:ROCK3]\nHey, to the kids, it's a temple and we are the priests!\n\n[ROK3_66:ROCK3]\nAye, well, if the kids like their priests half cut and tone deaf,\n\n[ROK3_67:ROCK3]\nwho am I to argue?\n\n[ROK3_68:ROCK3]\nOh geez, the tape's getting chewed again.\n\n[ROK3_69:ROCK3]\nAt this rate, we'll never get to play live.\n\n[ROK3_70:ROCK3]\nOohh shite! My bowels...\n\n[ROK3_73:ROCK3]\nJezz is running the tape,\n\n[RBM3_9:ROCK3]\nIf you are stopped or drive slowly the detonation bar will increase.\n\n[RBM3_H:ROCK3]\nI'm shitin' masel' man. I need ma ma!\n\n[ROK3_71:ROCK3]\nWe gotta get on with it - thanks again Tommy, Know what I am saying, nice one, bye!\n\n[ROK3_1:ROCK3]\nAt last man, time for a well earned drink. The venue's just a hundred yards down the road.\n\n[ROK3_2:ROCK3]\nBetter make it a large one then. Hey Tommy, change the tunes, man.\n\n[ROK3_3:ROCK3]\nI get confused if my head ain't banging. Ah look, what's this? Hey Tommy, stick this tape on.\n\n[ROK3_4:ROCK3]\nLove Fist. Your time polluting the airwaves is over. I gave you the chance to be friends.\n\n[ROK3_5:ROCK3]\nNow, I'm giving you the chance to die. Try to slow down and your limousine will explode, along with your BIG, HAIRY ARSES!\n\n[ROK3_6:ROCK3]\nTommy pal, you gotta save the band! I'm getting bored of this. Just keep the pedal to the metal!!\n\n[ROK3_7:ROCK3]\nWe gotta find the bomb! Can't we just drive around all day? Aye, we've got plenty to drink..\n\n[ROK3_8:ROCK3]\nWon't the bomb not be in the engine? We'll have to stop to get it. We're all going to die! I'm gonna get drunk!\n\n[ROK3_9:ROCK3]\nHey, there's a queue here pal! The answer ain't in the drinks cabinet! Get out of my way!\n\n[ROK3_10:ROCK3]\nHey, the vodka bottle's got wires coming out of it! That's not vodka, that's BOOMSHINE!\n\n[ROK3_11:ROCK3]\nWAAAAAAGGGHHHH!!!! And it's wired to blow!! WAAAAAAAAAAAAGGGHHHHHHHH!!!!\n\n[ROK3_12:ROCK3]\nThey always said the drink would kill me. I've seen this on the telly. you gotta pull out one of the wires. Which wire? I don't know, man.\n\n[ROK3_13:ROCK3]\nI don't have a clue. Willy, say something. I'm gonna play bass in hell.\n\n[ROK3_14:ROCK3]\nTommy man, keep driving fast, pal. Somebody do something. Aye, clever!\n\n[ROK3_15:ROCK3]\n'Somebody do something', what kind of crap is that, I've seen braver girls. Okay tough guy, you do something.\n\n[ROK3_16:ROCK3]\nLook, man, I play a musical instrument I don't have a clue about bomb disposal. Willy could just suck the boomshine out with a straw.\n\n[ROK3_17:ROCK3]\nAye, I've heard that your good at that kind of thing. Hey, I was off my tits that night, as well you know!\n\n[ROK3_18:ROCK3]\nJust pass Willy a straw! A straw?!?! This is the Love Fist Tour Bus!\n\n[ROK3_19:ROCK3]\nWhere am I gonna get a straw from, know wot I mean? Which wire, Tommy? The green one. There isn't a green one.\n\n[ROK3_20:ROCK3]\nOr is this one green? Any of these wires look green to you?\n\n[ROK3_21:ROCK3]\nOh no! Death's on the cards! Everything looks green! I should have dumped you lot when I had the chance man.\n\n[ROK3_22:ROCK3]\nGlory seeker. Capitalist. I've been carrying you for years. Shut up. You're a muppit.\n\n[ROK3_23:ROCK3]\nA big screaming girl. Yeah. Shut up and pull a wire. Which wire? This one..\n\n[ROK3_24:ROCK3]\nNO! Man, we're okay. We ain't been blown up, pal.\n\n[ROK3_25:ROCK3]\nTommy, man, nice one. Rock and roll, man. Ain't we got a gig to go to?\n\n[ROK3_26:ROCK3]\nA racket to make? Groupies to abuse? LOVE FIST!\n\n[ROK3_27:ROCK3]\nHave you finished with that bottle?\n\n{=================================== MISSION TABLE SERG1 ===================================}\n\n[TEX1_A:SERG1]\nCome in and park yourself on the hide, son.\n\n[TEX1_B:SERG1]\nHell, my daddy used to say, never look a gift horse in the mouth, and by golly, he never did.\n\n[TEX1_C:SERG1]\nWould you like a drop of the old Kentucky?\n\n[TEX1_D:SERG1]\nNo thanks.\n\n[TEX1_E:SERG1]\nA clean thinker! I like that.\n\n[TEX1_F:SERG1]\nNow, the property business isn't all about high-falootin' paper pushing.\n\n[TEX1_G:SERG1]\nIt's about dirt! And the will to claim that dirt! You with me, son?\n\n[TEX1_H:SERG1]\nOh yeah.\n\n[TEX1_K:SERG1]\nPersuasion's my forte.\n\n[TEX1_L:SERG1]\nYeh, he'll be down at the country club, down on the golf course.\n\n[TEX1_M:SERG1]\nThey don't allow guns, so his bodyguards won't be packing lawgivers.\n\n[TEX1_N:SERG1]\nGo beat eight tons of crap out of him.\n\n[TEX1_O:SERG1]\nHere now - I got you a membership, and boy you're going to need more appropriate clothing.\n\n[TEX1_2:SERG1]\n~g~Now head to the Leaf Links Golf Club.\n\n[TEX1_3:SERG1]\nWho's this guy? Boys, deal with him.\n\n[TEX1_6:SERG1]\nNice ass baby!\n\n[TEX1_7:SERG1]\nIs this me?\n\n[TEX1_I:SERG1]\nWell, I need some tenacious bastard to let go of some dirt,\n\n[TEX1_J:SERG1]\nand you look to me like the kind of guy to persuade him.\n\n[TEX1_0:SERG1]\n~g~The target is at the driving range enjoying a game of golf. Make sure it's his last.\n\n[TEX1_8:SERG1]\nEach time you enter a caddy you automatically receive a golf club, providing your melee weapon slot is empty.\n\n[TEX1_9:SERG1]\nGet him!\n\n[TEX1_10:SERG1]\nKill that Psycho!\n\n[TEX1_1:SERG1]\n~g~Go and pick up some golfing clothes from Jocksports.\n\n{=================================== MISSION TABLE SERG2 ===================================}\n\n[TEX_2A:SERG2]\n~g~Excellent! They've spotted you!\n\n[TEX_2B:SERG2]\n~r~Fool! People have to WITNESS a Cuban doing the hit!\n\n[TEX_2C:SERG2]\n~g~Go get yourself some Cuban gang colors in Little Havana!\n\n[TEX_2D:SERG2]\n~g~Take out the Haitian Gang Lord at Romero's Funeral Parlor!\n\n[TEX2_A:SERG2]\nTommy, this is Donald Love. Donald, this here is Tommy Vercetti,\n\n[TEX2_B:SERG2]\nthe latest gunslinger to come to these parts.\n\n[TEX2_C:SERG2]\nYeh...uh...\n\n[TEX2_D:SERG2]\nDonald, you just shut up and listen, and you might learn something.\n\n[TEX2_E:SERG2]\nNow, nothing brings down real estate prices quicker than a good old-fashioned gang war -\n\n[TEX2_F:SERG2]\n'cept maybe a disaster, like a biblical plague or something,\n\n[TEX2_G:SERG2]\nbut, that may be going too far in this case.\n\n[TEX2_H:SERG2]\nYou getting this down, you four-eyed prick?\n\n[TEX2_I:SERG2]\nNow recently a Haitian gang lord died. Apparently the Cubans did it, nobody's certain.\n\n[TEX2_J:SERG2]\nBut let's make them certain! You disguise yourself as a Cuban hombre,\n\n[TEX2_K:SERG2]\nand head on down to crash that funeral. Mix it up, and then high tail it.\n\n[TEX2_L:SERG2]\nYou getting this down, Donald?\n\n[TEX2_M:SERG2]\nWell, that ought to put the coyote in the chicken coop, huh?\n\n[TEX2_N:SERG2]\nAnd then we'll just sit back, and watch the prices tumble.\n\n[TEXEXIT:SERG2]\n~g~Now get out of Little Haiti!\n\n{=================================== MISSION TABLE SERG3 ===================================}\n\n[TEX3_A:SERG3]\nNow look here, son. I got a problem and I reckon you could help me with it.\n\n[TEX3_B:SERG3]\nI'm no builder.\n\n[TEX3_C:SERG3]\nNo, I was thinking more of your demolition skills.\n\n[TEX3_D:SERG3]\nNow this here, this is the development as planned and this,\n\n[TEX3_E:SERG3]\nthis is the property that we're looking at.\n\n[TEX3_F:SERG3]\nYou're trying to say this new office block is kind of in the way.\n\n[TEX3_G:SERG3]\nYou catch on quick.\n\n[TEX3_H:SERG3]\nNow I'm going to head out of town for a while\n\n[TEX3_I:SERG3]\nand if that office development were to face sudden and insurmountable structural problems, then I..\n\n[TEX3_J:SERG3]\nAs a civil minded individual you'd feel obliged to step in and\n\n[TEX3_K:SERG3]\nsave the rejuvenation of an important area of the city?\n\n[TEX3_L:SERG3]\nWhere can I get more guys like you?\n\n[TEX3_1:SERG3]\n~g~Use the RC helicopter to transport bombs to four demolition points on the building site.\n\n[TEX3_2:SERG3]\n~g~You must place one bomb at each target. You can place bombs in any order.\n\n[TEX3_3:SERG3]\n~g~Maneuver the RC helicopter next to a bomb to pick it up. it can carry one bomb at a time..\n\n[TEX3_5:SERG3]\n~g~If you place a bomb unsuccessfully you can pick it up and try again.\n\n[TEX3_7:SERG3]\n~g~You must then place the remaining bombs in 7 minutes!\n\n[TEX3_8:SERG3]\n~g~You missed the target! Pick up a bomb and try again!\n\n[TEX3_10:SERG3]\n~g~Drop the bomb at a target.\n\n[TEX3_11:SERG3]\ntargets left:\n\n[TEX3_17:SERG3]\n~r~You ran out of time!\n\n[TEX3_18:SERG3]\n~r~Your RC Helicopter has been destroyed!\n\n[TEX3_19:SERG3]\n~r~You dropped your bomb in the water! That ain't no way to fish!\n\n[TEX3_20:SERG3]\n~r~The RC Helicopter is nearly out of range!\n\n[TEX3_21:SERG3]\n~r~The RC Helicopter went out of range!\n\n[TEX3_24:SERG3]\nPress the ~h~~k~~VEHICLE_LOOKLEFT~ ~w~button to rotate the helicopter counter-clockwise.\n\n[TEX3_25:SERG3]\nPress the ~h~~k~~VEHICLE_LOOKRIGHT~ ~w~button to rotate the helicopter clockwise.\n\n[TEX3_27:SERG3]\n~g~A central stairway allows access to all the floors in the building.\n\n[TEX3_31:SERG3]\n~r~You destroyed the TOPFUN van that contained the bombs and RC helicopter!\n\n[TEX3_32:SERG3]\nYou can ~h~look behind~w~ by simultaneously pressing the ~h~~k~~VEHICLE_LOOKLEFT~~w~ and the ~h~~k~~VEHICLE_LOOKRIGHT~~w~ buttons.\n\n[TEX3_4:SERG3] { reVC update }\n~g~To drop a bomb press the~h~ ~k~~VEHICLE_FIREWEAPON~ ~g~button.\n\n[TEX3_29:SERG3] { reVC update }\nTo drop a bomb press the~h~ ~k~~VEHICLE_FIREWEAPON~ ~w~button.\n\n[TEX3_26:SERG3]\nPressing the ~h~~k~~VEHICLE_BRAKE~ ~w~button ~w~decreases the rotor speed, causing the helicopter to~h~ descend.\n\n[TEX3_22:SERG3]\nPressing the ~h~~k~~VEHICLE_ACCELERATE~ ~w~button increases the rotor speed, causing the helicopter to ~h~ascend.\n\n[TEX3_16:SERG3]\n~g~Get to the ~w~TOPFUN ~g~van near the building site to be demolished.\n\n[TEX3_33:SERG3]\nOnce you pick up a bomb the radar will show you the position of the target relative to the RC helicopter.\n\n[TEX3_34:SERG3]\nAn ~h~upwards pointing triangular blip ~w~indicates the target is ~h~above ~w~the RC helicopter.\n\n[TEX3_35:SERG3]\nA ~h~downward pointing triangular blip ~w~indicates the target is ~h~below ~w~the RC helicopter.\n\n[TEX3_36:SERG3]\nA ~h~square blip ~w~indicates the target is on the ~h~same level ~w~as the RC helicopter\n\n[TEX3_6:SERG3]\n~g~Once you have picked up a bomb for the first time, the detonation timer will start.\n\n[TEX3_28:SERG3]\nTo ~h~pick up a bomb~w~, simply maneuver the RC helicopter next to it. The RC Helicopter can carry one bomb at a time.\n\n[TEX3_30:SERG3]\n~g~To pick up a bomb, simply maneuver the RC helicopter next to it. The RC Helicopter can carry one bomb at a time.\n\n[TEX3_12:SERG3]\n~g~Bomb planted! Only 3 more targets to go! Go back and get another bomb.\n\n[TEX3_13:SERG3]\n~g~Bomb planted! Only 2 more targets to go! Go back and get another bomb.\n\n[TEX3_14:SERG3]\n~g~Bomb planted! Only 1 more target to go! Go back and get another bomb.\n\n[TEX3_15:SERG3]\n~r~Detonation timer initiated! ~g~You must plant the ~w~4 bombs ~g~in the remaining time!\n\n[TEX3_37:SERG3]\nPushing ~h~back on the analog stick ~w~decreases the rotor speed, causing the helicopter to~h~ descend.\n\n[TEX3_38:SERG3] { reVC update }\n{ Pressing the ~h~~k~~VEHICLE_ACCELERATE~ ~w~button increases the rotor speed, causing the helicopter to ~h~ascend. }\nPushing ~h~forward on the analog stick ~w~increases the rotor speed, causing the helicopter to ~h~ascend.\n\n[TEX3_39:SERG3]\n~g~To drop a bomb press the ~h~~k~~VEHICLE_HANDBRAKE~ ~g~button.\n\n[TEX3_40:SERG3]\nTo drop a bomb press the ~h~~k~~VEHICLE_HANDBRAKE~ ~w~button.\n\n[TEX3_23:SERG3]\nPress the ~h~~k~~VEHICLE_TURRETUP~~w~ and ~h~~k~~VEHICLE_TURRETDOWN~~w~ buttons to tilt the helicopter in the direction you wish to maneuver it.\n\n{=================================== MISSION TABLE TAXI1 ===================================}\n\n[FARES:TAXI1]\nFARES:\n\n[TAXI1:TAXI1]\n~g~Look for a fare.\n\n[TSCORE2:TAXI1]\n$~1~\n\n[IN_ROW:TAXI1]\n~1~ IN A ROW bonus! $~1~\n\n[TAXI3:TAXI1]\n~r~Your passenger fled in terror!\n\n[TAXI7:TAXI1]\n~r~Your car is trashed, get it repaired.\n\n[TAXI4:TAXI1]\nFare complete!\n\n[TAXI5:TAXI1]\nSPEED BONUS!!\n\n[TAXI6:TAXI1]\nTaxi mission over\n\n[TAXIH1:TAXI1]\nStop near a highlighted pedestrian to pick them up then drive them to their destination before the time runs out.\n\n[FARE1:TAXI1]\n~g~Destination ~w~'The Pole Position Club' ~g~in Ocean Beach.\n\n[FARE3:TAXI1]\n~g~Destination ~w~'The Marina' ~g~in Ocean Beach.\n\n[FARE4:TAXI1]\n~g~Destination ~w~'Ammu-Nation' ~g~in Ocean Beach.\n\n[FARE5:TAXI1]\n~g~Destination ~w~'The Hardware store' ~g~in Washington Beach.\n\n[FARE6:TAXI1]\n~g~Destination ~w~'The North Point Mall' ~g~in Vice Point.\n\n[MFARE1:TAXI1]\n~g~Destination ~w~'Ammu-Nation' ~g~in Downtown.\n\n[MFARE2:TAXI1]\n~g~Destination ~w~'the Terminal' ~g~at Escobar International Airport.\n\n[WFARE3:TAXI1]\n~g~Destination ~w~'Sunshine Autos' ~g~in Little Havana.\n\n[WFARE4:TAXI1]\n~g~Destination ~w~'Kaufman Cabs' ~g~in Little Haiti.\n\n[WFARE5:TAXI1]\n~g~Destination ~w~'The Hardware store' ~g~in Little Havana.\n\n[WFARE6:TAXI1]\n~g~Destination ~w~'Howlin Petes Bike Emporium' ~g~in Downtown.\n\n[FARE7:TAXI1]\n~g~Destination ~w~'The Jewelers' ~g~in Vice Point.\n\n[FARE8:TAXI1]\n~g~Destination ~w~'The Beach' ~g~in Ocean Beach.\n\n[FARE9:TAXI1]\n~g~Destination ~w~'The Beach' ~g~in Washington Beach.\n\n[FARE10:TAXI1]\n~g~Destination ~w~'The Beach' ~g~in Vice Point.\n\n[FARE11:TAXI1]\n~g~Destination ~w~'Hospital' ~g~in Ocean Beach.\n\n[FARE12:TAXI1]\n~g~Destination ~w~'Hospital' ~g~in Vice Point.\n\n[FARE13:TAXI1]\n~g~Destination ~w~'Police Station' ~g~in Washington Beach.\n\n[FARE14:TAXI1]\n~g~Destination ~w~'Police Station' ~g~in Vice Point.\n\n[FARE15:TAXI1]\n~g~Destination ~w~'Pizza Restaurant' ~g~in Vice Point.\n\n[WFARE7:TAXI1]\n~g~Destination ~w~'Police Station' ~g~in Little Havana.\n\n[WFARE8:TAXI1]\n~g~Destination ~w~'Police Station' ~g~in Downtown.\n\n[WFARE9:TAXI1]\n~g~Destination ~w~'Hospital' ~g~in Downtown.\n\n[WFARE10:TAXI1]\n~g~Destination ~w~'Hospital' ~g~in Little Havana.\n\n[WFARE11:TAXI1]\n~g~Destination ~w~'The Stadium' ~g~in Downtown.\n\n[WFARE12:TAXI1]\n~g~Destination ~w~'Pizza Restaurant' ~g~in Little Haiti.\n\n[WFARE13:TAXI1]\n~g~Destination ~w~'Pizza Restaurant' ~g~in Downtown.\n\n[WFARE14:TAXI1]\n~g~Destination ~w~'Docks' ~g~in Viceport.\n\n[WFARE15:TAXI1]\n~g~Destination ~w~'Chemist' ~g~in Little Haiti.\n\n[FARE2:TAXI1]\n~g~Destination ~w~'The Malibu club' ~g~in Vice Point.\n\n{=================================== MISSION TABLE TAXICUT ===================================}\n\n[TAXC_A:TAXICUT]\nGuess you're the new owner.\n\n[TAXC_B:TAXICUT]\nWhat are you, mob? Cartel? You don't look Mexican...\n\n[TAXC_C:TAXICUT]\nAnyhoo, I guess you better get on with the 'things are gonna change around here' crap,\n\n[TAXC_D:TAXICUT]\nmaybe threaten one of the drivers -\n\n[TAXC_E:TAXICUT]\ngo steady on Ted over there, he's just had his hernia fixed.\n\n[TAXC_F:TAXICUT]\nWell, yeah. Things are going to change around here, lady.\n\n[TAXC_G:TAXICUT]\nOh crap, sonny. Might as well leave this to me -\n\n[TAXC_H:TAXICUT]\nI've been doing this for years.\n\n[TAXC_I:TAXICUT]\nNow hear this.\n\n[TAXC_J:TAXICUT]\nWe are now under new management and things are going to change around here again.\n\n[TAXC_K:TAXICUT]\nOur new management, the\n\n[TAXC_L:TAXICUT]\n- Which gang are you?\n\n[TAXC_M:TAXICUT]\nWell, I'm not part of any gang actually.\n\n[TAXC_N:TAXICUT]\nWhat's your goddamned name, kid?\n\n[TAXC_O:TAXICUT]\nVercetti, Tommy Vercetti.\n\n[TAXC_P:TAXICUT]\nOur new management, the Vercetti Gang,\n\n[TAXC_Q:TAXICUT]\nis gonna make sure we get no trouble.\n\n[TAXC_R:TAXICUT]\nCapiche? Out!\n\n[TAXC_S:TAXICUT]\nDid you like the 'capiche'? I liked the 'capiche'.\n\n[TAXC_T:TAXICUT]\nSo this is how it's worked in the past,\n\n[TAXC_U:TAXICUT]\nWe run the firm as usual.\n\n[TAXC_V:TAXICUT]\nIf we get any trouble from rival firms, you beat the crap out of them.\n\n[TAXC_W:TAXICUT]\nThen they beat the crap out of us,\n\n[TAXC_X:TAXICUT]\nthen you beat the crap out of them,\n\n[TAXC_Y:TAXICUT]\netcetera, etcetera. You got it?\n\n[TAXC_Z:TAXICUT]\nUh, yeah, I guess...\n\n[TAXC_A1:TAXICUT]\nJust grab a taxi from the garage if you feel like jumping in.\n\n{=================================== MISSION TABLE TAXIWA1 ===================================}\n\n[OUTTIME:TAXIWA1]\n~r~Too slow, man, too slow!\n\n[TAX1_1:TAXIWA1]\nOk, we got a high class fare needs picking up from Starfish island - any takers?\n\n[TAX1_2:TAXIWA1]\nTommy here, I'll take it!\n\n[TAX1_3:TAXIWA1]\nThis is my fare, back off asshole!\n\n[TAX1_4:TAXIWA1]\nCome on come on, Get in, quick!\n\n[TAX1_5:TAXIWA1]\nOk, ok! Just don't hurt me!\n\n[TAXW1_1:TAXIWA1]\n~g~Pick up the V.I.P. on Starfish Island.\n\n[TAXW1_2:TAXIWA1]\n~g~Get the V.I.P back! Take the other car out!\n\n[TAXW1_3:TAXIWA1]\n~r~The V.I.P. is dead!\n\n[TAXW1_4:TAXIWA1]\n~r~The V.I.P. has been dropped off!\n\n[TAXW1_6:TAXIWA1]\n~g~Take the V.I.P. to the airport!\n\n{=================================== MISSION TABLE TAXIWA2 ===================================}\n\n[TAX2_1:TAXIWA2]\nCalling all cars, we're losing fares all over town. What's with you guys?\n\n[TAX2_2:TAXIWA2]\nVC Cabs keep beating us to it. They've just got too many cars - we can't compete!\n\n[TAX2_3:TAXIWA2]\nMr. Vercetti, if you're out there listening in, you gotta put some VC Cabs out of action before we go bust!\n\n[TAXW2_1:TAXIWA2]\n~g~Destroy 3 of the rival taxis!\n\n{=================================== MISSION TABLE TAXIWA3 ===================================}\n\n[TAX3_1:TAXIWA3]\nCar 13, We got a Miss Cortez, asked for you especially.\n\n[TAX3_2:TAXIWA3]\nOk, I got it. Car 13 out!\n\n[TAX3_3:TAXIWA3]\nHmmmm, no sign of Mercedes...\n\n[TAXW3_3:TAXIWA3]\n~g~Take out the leader cab!\n\n[TAXW3_2:TAXIWA3]\n~g~Stay alive until the timer runs out.\n\n[TAX_AS1:TAXIWA3]\nTAXI FIRM ASSET COMPLETED\n\n[TAX_AS2:TAXIWA3]\n~g~Kaufman Cabs will now generate revenue up to a maximum of $~1~. Make sure you collect it regularly.\n\n[TAX3_4:TAXIWA3]\nIt's time for Kaufman Cab's guardian angel to eat some fender!\n\n[TAX3_5:TAXIWA3]\nHey boy I'm gonna tan your hide!\n\n{ reVC updates }\n{ new languages }\n[FEL_JAP]\nJAPANESE\n\n[FEL_POL]\nPOLISH\n\n[FEL_RUS]\nRUSSIAN\n\n{ new display menus }\n[FET_GFX]\nGRAPHICS SETUP\n\n[FED_MIP]\nMIP MAPPING\n\n[FED_AAS]\nANTI ALIASING\n\n[FED_FIL]\nTEXTURE FILTERING\n\n[FED_BIL]\nBILINEAR\n\n[FED_TRL]\nTRILINEAR\n\n[FED_WND]\nWINDOWED\n\n[FED_FLS]\nFULLSCREEN\n\n[FEM_CSB]\nCUTSCENE BORDERS\n\n[FEM_SCF]\nSCREEN FORMAT\n\n[FEM_ISL]\nMAP MEMORY USAGE\n\n[FEM_LOW]\nLOW\n\n[FEM_MED]\nMEDIUM\n\n[FEM_HIG]\nHIGH\n\n[FEM_2PR]\nPS2 ALPHA TEST\n\n[FEC_FRC]\nFREE CAM\n\n{ Linux joy detection }\n[FEC_JOD]\nDETECT JOYSTICK\n\n[FEC_JPR]\nPress any key on the joystick of your choice that you want to use on the game, and it will be selected.\n\n[FEC_JDE]\nDetected joystick\n\n{ mission restart }\n[FET_RMS]\nREPLAY MISSION\n\n[FESZ_RM]\nRETRY?\n\n[FED_VPL]\nVEHICLE PIPELINE\n\n[FED_PRM]\nPED RIM LIGHT\n\n[FED_RGL]\nROAD GLOSS\n\n[FED_CLF]\nCOLOUR FILTER\n\n[FED_WLM]\nWORLD LIGHTMAPS\n\n[FED_MBL]\nMOTION BLUR\n\n[FEM_SIM]\nSIMPLE\n\n[FEM_NRM]\nNORMAL\n\n[FEM_MOB]\nMOBILE\n\n[FED_MFX]\nMATFX\n\n[FED_NEO]\nNEO\n\n[FEM_PS2]\nPS2\n\n[FEM_XBX]\nXBOX\n\n[FEC_IVP]\nINVERT PAD VERTICALLY\n\n[FEM_NON]\nNONE\n\n[FEC_DS2]\nDUALSHOCK 2\n\n[FEC_DS3]\nDUALSHOCK 3\n\n[FEC_DS4]\nDUALSHOCK 4\n\n[FEC_360]\nXBOX 360 CONTROLLER\n\n[FEC_ONE]\nXBOX ONE CONTROLLER\n\n[FEC_TYP]\nGAMEPAD TYPE\n\n[FET_AGS]\nGAMEPAD SETTINGS\n\n[FEM_AUT] { aspect ratio related }\nAUTO\n\n{ end of file }\n[DUMMY]\nTHIS LABEL NEEDS TO BE HERE !!!\nAS THE LAST LABEL DOES NOT GET COMPILED"
  },
  {
    "path": "utils/gxt/build.bat",
    "content": "gxt -g VC -i \"american.txt\" -o \"../../gamefiles/TEXT/american.gxt\"\ngxt -g VC -i \"french.txt\" -o \"../../gamefiles/TEXT/french.gxt\"\ngxt -g VC -i \"german.txt\" -o \"../../gamefiles/TEXT/german.gxt\"\ngxt -g VC -i \"italian.txt\" -o \"../../gamefiles/TEXT/italian.gxt\"\ngxt -g VC -i \"spanish.txt\" -o \"../../gamefiles/TEXT/spanish.gxt\""
  },
  {
    "path": "utils/gxt/french.txt",
    "content": "﻿{\n    New strings are at the bottom of file.\n    Do not change the order of strings.\n    You can fix the typos of existing translation but please refrain from\n    unnecessary edits like rephasing because you think it suits better for your taste.\n}\n\n[RAMPAGE]\nRODEO!\n\n[RAMP_F]\nECHEC DU RODEO!\n\n[RAMP_P]\nRODEO REUSSI!\n\n[RAMP_A]\nTOUS LES RODEOS REUSSIS!\n\n[PAGE_01]\nTue ~1~ membres de gang en 2 minutes!\n\n[PAGE_02]\nDétruis ~1~ véhicules en 2 minutes!\n\n[PAGE_03]\nRoule à côte des membres de gang et tue-en ~1~ en 2 minutes!\n\n[PAGE_04]\nEcrase ~1~ membres de gang en 2 minutes!\n\n[PAGE_05]\nEclate la tête de ~1~ membres de gang en 2 minutes!\n\n[FEC_ABR]\nAccélérer, freiner ou marche arrière\n\n[CLOHELP]\nVêtements changés!\n\n[FE_MLG]\nLEGENDE DE LA CARTE\n\n[FED_RDR]\nRADAR\n\n[FED_HUD]\nL'INTERFACE\n\n[FED_RDL]\nGRAND\n\n[FED_RDB]\nBIPS UNIQUEMENT\n\n[FED_HUF]\nFONDU\n\n[FEI_BTU]\n; = -\n\n[FEI_SCR]\nFait défiler\n\n[FEST_HV]\nMissions d'Autodéfense, niveau maximum\n\n[LG_01]\nPosition du joueur\n\n[LG_02]\nAvery Carrington\n\n[LG_03]\nMotards\n\n[LG_04]\nColonel Cortez\n\n[LG_05]\nRicardo Diaz\n\n[LG_06]\nKent Paul\n\n[LG_07]\nAvocat\n\n[LG_08]\nPhil Cassidy\n\n[LG_09]\nChantier naval\n\n[LG_10]\nClub Malibu\n\n[LG_11]\nCubains\n\n[LG_12]\nStudio de Cinéma\n\n[LG_13]\nAmmu-Nation\n\n[LG_14]\nHaïtiens\n\n[LG_15]\nQuincaillerie\n\n[LG_16]\nPlanque\n\n[LG_17]\nCrèmes glacées\n\n[LG_18]\nTaxi Kaufman\n\n[LG_19]\nLove Fist\n\n[LG_20]\nImprimerie\n\n[LG_21]\nPropriété\n\n[LG_22]\nPay 'n' Spray\n\n[LG_23]\nBoutique de fringues\n\n[LG_24]\nManoir de Tommy\n\n[LG_25]\nTéléphone\n\n[LG_26]\nStation de radio Wildstyle\n\n[LG_27]\nStation de radio Flash FM\n\n[LG_28]\nStation de radio KChat\n\n[LG_29]\nStation de radio Fever 105\n\n[LG_30]\nStation de radio VRock\n\n[LG_31]\nStation de radio VCPR\n\n[LG_32]\nStation de radio Espantoso\n\n[LG_33]\nStation de radio Emotion 98.3\n\n[LG_34]\nStation de radio Onde 103\n\n[LG_35]\nDestination\n\n[LG_36]\nSun Yard\n\n[LG_37]\nBoîte de striptease\n\n[MAP_YAH]\nVOUS ETES ICI\n\n[MAP_LEG]\nLégende\n\n[SENTXS]\nSentinelle XS\n\n[VCNMAV]\nVCN Maverick\n\n[TAXSHRT]\n~g~Au lieu de conduire, tu peux te servir de ce taxi Kaufman pour te déplacer. Cela te coûtera $9.\n\n[BRIBE1]\nTu viens de récupérer un pot-de-vin de la police. Cela réduira ton indice de recherche d'une étoile.\n\n[SUNSHIN]\nSunshine Autos\n\n[KAUFCAB]\nTaxis Kaufman\n\n[BOATYAR]\nLe chantier naval\n\n[WANT_L]\nTu as perdu ton indice de recherche. Ne commets pas de délit tant que les étoiles brillent ou tu seras de nouveau très recherché.\n\n[HOTRNG]\nHOTRING\n\n[BLODRNG]\nBLOODRING\n\n[DIRTRNG]\nDIRTRING\n\n[IN_VEH]\n~g~Eh! Remonte dans ta caisse!\n\n[HEY]\n~g~Te la joue pas perso, reste avec tes potes!\n\n[HELP3]\nT'es vite crevé, ton sprint ne dure donc pas longtemps.\n\n[HELP4_D]\nPousse le ~h~joystick analogique droit ~w~ vers le haut pour ~h~accélérer.\n\n[HELP5_D]\nTire le ~h~joystick analogique droit~w~ vers toi pour ~h~freiner~w~ ou pour ~h~reculer~w~ si le véhicule est à l'arrêt.\n\n[HELP7_A]\nMaintiens la ~h~ ~k~~PED_LOCK_TARGET~ ~w~ enfoncée pour ~h~viser~w~ avec le fusil à lunette.\n\n[HELP7_D]\nMaintiens la ~h~ ~k~~PED_LOCK_TARGET~ ~w~ enfoncée pour ~h~viser~w~ avec le fusil à lunette.\n\n[HELP10]\nCe badge t'indique que t'es recherché par la police.\n\n[HELP11]\nPlus t'as de badges, plus ton indice de recherche est important.\n\n[HELP13]\nTu as parfois intérêt à emprunter des chemins non indiqués sur le radar.\n\n[TIMER]\nCette mission est en temps limité. Tu dois donc la réussir avant que le compteur n'atteigne zéro.\n\n[HORN]\n~g~Klaxonne!\n\n[NOMONEY]\n~g~T'as pas assez de cash!\n\n[REWARD]\nRECOMPENSE $~1~\n\n[M_FAIL]\nECHEC DE LA MISSION!\n\n[M_PASS]\nMISSION ACCOMPLIE! $~1~\n\n[DEAD]\nT'ES MORT!\n\n[BUSTED]\nCHOPE!\n\n[WEATHE1]\nTEMPS ENSOLEILLE\n\n[WEATHE2]\nTEMPS TRES ENSOLEILLE\n\n[WEATHE3]\nTEMPS NUAGEUX\n\n[WEATHE4]\nTEMPS PLUVIEUX\n\n[WEATHE5]\nTEMPS BRUMEUX\n\n[WEATHE6]\nTEMPS NORMAL\n\n[NUMBER]\n~1~\n\n[LOADCAR]\nCHARGEMENT DU VEHICULE... (APPUIE SUR F1 POUR ANNULER)\n\n[CARSOFF]\nTrafic désactivé.\n\n[CARS_ON]\nTrafic activé.\n\n[TEXTXYZ]\nEcriture des coordonnées sur le fichier...\n\n[CHEATON]\nMode triche activé\n\n[CHEATOF]\nMode triche désactivé\n\n[IMPORT1]\nVa dehors et attends ton véhicule.\n\n[PAGEB11]\nLance-flammes livré à la planque\n\n[WANT_A]\nTu ne seras arrêté que si tu as un ~h~indice de recherche.\n\n[WANT_B]\nLa rangée d'étoiles dans le coin supérieur droit de l'écran symbolise ton ~h~indice de recherche~w~.\n\n[WANT_C]\nTon ~h~indice de recherche~w~ est désormais de un...\n\n[WANT_D]\ndeux...\n\n[WANT_E]\ntrois...\n\n[WANT_F]\nPlus ton ~h~indice de recherche~w~ augmente, plus les forces de l'ordre t'en veulent.\n\n[WANT_G]\nQuand tu es ~h~'chopé'~w~, tu es amené au poste de police le plus proche.\n\n[WANT_H]\nLes flics se laisseront corrompre contre toutes tes armes et une partie de ton cash.\n\n[WANT_I]\nToutes les missions en cours échoueront.\n\n[WANT_J]\nPlus tu joueras, plus tu trouveras de moyens de diminuer ton indice de recherche.\n\n[WANT_K]\nEn voiture, les ~h~ATELIERS DE PEINTURE~w~ te permettront d'effacer ton indice de recherche.\n\n[HEAL_B]\nQuand tu es ~h~'H.S'~w~, t'es amené à l'hôpital le plus proche.\n\n[HEAL_C]\nOn te confisque alors toute ton artillerie et les docteurs prennent ton argent pour te remettre en forme.\n\n[HEAL_E]\nEn jouant, tu trouveras d'autres moyens de te soigner ou de te protéger.\n\n[SAVE1]\nEntre dans la corona pour ~h~sauvegarder la partie~w~. Tu ne peux pas sauvegarder en cours de mission.\n\n[SAVE2]\nTout véhicule laissé dans ce garage sera enregistré lors de la sauvegarde.\n\n[AMMU]\nVa chez Ammu-Nation pour acheter une arme.\n\n[R_TIME]\nTEMPS DE COURSE :\n\n[PROP_1]\nTu n'as pas assez de cash pour acheter cette propriété\n\n[PROP_2]\nTu ne peux pas acheter une propriété en cours de mission\n\n[IND_ZON]\nVice City Beach\n\n[COM_ZON]\nPartie centrale de Vice City\n\n[BEACH1]\nOcean Beach\n\n[BEACH2]\nWashington Beach\n\n[BEACH3]\nVice Point\n\n[GOLFC]\nLeaf Links\n\n[STARI]\nStarfish Island\n\n[DOCKS]\nPort de Vice\n\n[HAVANA]\nLittle Havana\n\n[HAITI]\nLittle Haiti\n\n[PORNI]\nPrawn Island\n\n[DTOWN]\nCentre\n\n[VICE_C]\nVice City\n\n[A_PORT]\nAéroport Escobar\n\n[JUNKY]\nDécharge\n\n[PISTOL]\nPistolet\n\n[PYTHON]\n.357\n\n[UZI]\nUz-1\n\n[TEC9]\nTec 9\n\n[M4]\nM4\n\n[INGRAM]\nMac\n\n[MP5]\nMP\n\n[RUGER]\nKruger\n\n[SNIPE]\nFusil à lunette\n\n[GRENADE]\nGrenades\n\n[SHOTGN1]\nFusil à pompe\n\n[SHOTGN2]\nS.P.A.S. 12\n\n[SHOTGN3]\nFusil à pompe Stubby\n\n[ARMOUR]\nGilet pare-balles\n\n[LASER]\n.308 Lunette\n\n[BASEBAT]\nBatte de baseball\n\n[HAMMER]\nMarteau\n\n[SCREWD]\nTournevis\n\n[CLEVER]\nCouperet\n\n[MACHETE]\nMachette\n\n[KNIFE]\nCouteau\n\n[KATANA]\nKatana\n\n[CHAINSA]\nTronçonneuse\n\n[G_COST]\n$~1~\n\n[CAR_1]\nAmbulance\n\n[MALIBU]\nMalibu Club\n\n[MANSION]\nLa résidence de Diaz\n\n[TMANS]\nChez Tommy\n\n[STRIP]\n'Pole Position Club'\n\n[MALL1]\nCentre commercial de North Point\n\n[BANKINT]\nEl Banco Corrupto Grande\n\n[RANGE]\nChamp de tir\n\n[POL_HQ]\nQG de Vice City Police\n\n[INT_B]\nUn vieil ami\n\n[INTB_1]\n~g~Va au bureau de l'avocat.\n\n[LAW_1]\nLa Fête\n\n[LAW_2]\nBaston de Rue\n\n[LAW_3]\nJury sous pression\n\n[LAW_4]\nEmeute\n\n[COL_1]\nSalaud de traître\n\n[COL_2]\nFusillade\n\n[COL_3]\nAnges gardiens\n\n[COL_4]\nChef, oui, chef !\n\n[COL_5]\nSur le Pont\n\n[COK_1]\nCourse poursuite\n\n[COK_2]\nPhnom Penh '86\n\n[COK_3]\nSpeedboat\n\n[COK_4]\nOffre & demande\n\n[KENT_1]\nCouloir de la mort\n\n[ASS_1]\nLiquidation\n\n[BUD_1]\nEXTORSION\n\n[BUD_2]\nRixe de Bar\n\n[BUD_3]\nCopLand\n\n[CAP_1]\nL'encaisseur\n\n[FIN_1]\nAmis proches\n\n[BANK_1]\nSans Issue\n\n[BANK_2]\nLe Flingueur\n\n[BANK_3]\nLe Chauffeur\n\n[BANK_4]\nHold-up\n\n[CNT_1]\nLa Mèche est vendue\n\n[CNT_2]\nHalte au Messager\n\n[PORN_1]\nBout d'essai\n\n[PORN_2]\nDodo Vibro\n\n[PORN_3]\nMartha\n\n[PORN_4]\nProjecteur-G\n\n[TAX_1]\nTaxis Kaufman\n\n[TAXI_1]\nV.I.P.\n\n[TAXI_2]\nConcurrence Amicale\n\n[TAXI_3]\nCabmaggedon\n\n[ICE_1]\nDistribution\n\n[TEX_1]\nQuatre fers\n\n[TEX_2]\nFunérailles\n\n[TEX_3]\nDemolition Man\n\n[PHIL_1]\nTrafiquant d'armes\n\n[PHIL_2]\nBoomshine Saigon\n\n[BIKE_1]\nAlliage d'Acier\n\n[BIKE_2]\nColère\n\n[BIKE_3]\nBécane\n\n[ROCK_1]\nLove Juice\n\n[ROCK_2]\nPsychopathe\n\n[ROCK_3]\nPromo\n\n[ROCK_4]\nLes Love Fist!\n\n[HAT_1]\nJuju\n\n[HAT_2]\nBombes!\n\n[HAT_3]\nRaclée\n\n[CUB_1]\nCascades aquatiques\n\n[CUB_2]\nChair à Canon\n\n[CUB_3]\nBataille Navale\n\n[CUB_4]\nVaudou\n\n[JOB_1]\nAccident de la route\n\n[JOB_2]\nBute la femme!\n\n[JOB_3]\nAutocide\n\n[JOB_4]\nEnregistrement\n\n[JOB_5]\nDétails\n\n[ANSWER]\nAppuie sur la ~h~~k~~PED_ANSWER_PHONE~~w~ pour répondre au téléphone.\n\n[MOB_01A]\nComment ça va, mon pote? C'est Paul! J'ai peut-être quelque chose d'intéressant pour toi, mais faut que je te parle en personne.\n\n[MOB_01B]\nJe suis en train de me la couler douce au Malibu.\n\n[MOB_01C]\nTu me devras un ou deux petits services en échange, mon mignon. A tout à l'heure...\n\n[MOB_02A]\nSniiiiiiiiiiiif! Hé, salut, Tommy! Tommy?\n\n[MOB_02B]\nOn a un problème à l'imprimerie. Tu ferais mieux d'aller y jeter un coup d'oeil.\n\n[MOB_02C]\nQuelque chose a merdé. C'est le bordel. Faut que j'te laisse.\n\n[MOB_03A]\nMr Vercetti? J'ai ici un document signé qui établit formellement\n\n[MOB_03B]\nque vous avez racheté toutes les dettes de BJ's Auto.\n\n[MOB_03C]\nLa disparition soudaine de BJ ne me laisse pas d'autre choix\n\n[MOB_03D]\nque de vous tenir pour responsable du passif de cette société.\n\n[MOB_03E]\nJusqu'à ce que ce compte soit complètement soldé\n\n[MOB_03F]\nvous devriez considérer les rues de Vice City comme très dangereuses.\n\n[MOB_04A]\nComment va, vieille branche?\n\n[MOB_04B]\nEcoute, Tommy, j'avais oublié de te dire qu'on va avoir besoin de balaises en plus pour le concert.\n\n[MOB_04C]\nY'a un gang de motards dirigé par Mitch Baker, ça nous ferai une super publicité. Vraiment Rock'n'roll, Baby.\n\n[MOB_04D]\nRègle ça pour moi et je te laisserai accéder aux coulisses du concert, d'accord?\n\n[MOB_05A]\nBien joué, Tommy, j'suis content d'avoir récupéré ma bécane.\n\n[MOB_05B]\nDis à Mr Kent Paul que la sécurité sera assurée pour le concert.\n\n[MOB_05C]\nTu as ma parole.\n\n[MOB_05D]\nBon, maintenant, évite de t'attirer des emmerdes.\n\n[MOB_06A]\nTommy! Ceux d'en bas, ils parlent de toi, mon petit...\n\n[MOB_06B]\nJe me disais que tu te laisserais peut-être tenter par un doux foyer et par une soupe au gombo de tata Poulet? Mmm?\n\n[MOB_06C]\nFais un saut par ma cuisine un de ces jours, hein, Tommy?\n\n[MOB_08A]\nSalut, Tommy, je me disais que t'aurais peut-être besoin d'un conseil en affaires...\n\n[MOB_08B]\nDès que tu as une opération en route, il faut que tu passes prendre le fric de la semaine.\n\n[MOB_08C]\nSi tu laisses les mecs penser que ce sont eux qui dirigent l'affaire, ils essayent de ronger tes bénefs! Ok?\n\n[MOB_08D]\nCa va, Ken, je connais le business...\n\n[MOB_08E]\nOk, ok, je sais que tu sais. Je sais. C'était...\n\n[MOB_08F]\nC'était juste pour te dire que je sais que tu sais que je sais...\n\n[MOB_08G]\nOuvre simplement l'oeil!\n\n[MOB_08H]\nT'inquiète, Ken, t'inquiète...\n\n[MOB_09A]\nSalut, Léo! J'ai du boulot pour toi!\n\n[MOB_09B]\nC'est pas Léo.\n\n[MOB_09C]\nSi Léo apprend que t'as son téléphone, il va te buter aussi sec!\n\n[MOB_09D]\nPeut-être que Léo est mort. Peut-être même que c'est moi qui l'ai buté et que j'ai hérité de son téléphone. T'avais pas pensé à ça hein, connard?\n\n[MOB_09E]\nT'as buté Léo? Alors, c'est que t'en as dans le froc! Tu veux bosser pour moi?\n\n[MOB_09F]\nPasse au café de mon père dans Little Havana et on pourra causer entre hommes.\n\n[MOB_10A]\nTommy! Ecoute, j'ai un service à te demander!\n\n[MOB_10B]\nSteve! Comment ça marche, le cinoche?\n\n[MOB_10C]\nCa va, ça va. Mais on a besoin d'une scène de poursuite en bagnole et on a pas le budget pour ça.\n\n[MOB_10D]\nJ'ai laissé des bagnoles dans les environs. Tu sauras quoi faire.\n\n[MOB_10E]\nOK, Steve, je vais voir ce que je peux faire. A plus tard.\n\n[MOB_11A]\nSalut petit, je me suis dit que j'allais te passer un coup de fil pour te donner un bon conseil.\n\n[MOB_11B]\nSalut Avery, qu'est-ce que tu voulais me dire?\n\n[MOB_11C]\nLes perspectives ne manquent pas dans cette ville, si tu possèdes le bon business... Tu vois ce que je veux dire?\n\n[MOB_11D]\nJe pense que oui...\n\n[MOB_11E]\nJe te conseille d'ouvrir l'oeil, et le bon, si tu veux dégotter un bon business. A plus tard.\n\n[MOB_11F]\nCiao, Avery.\n\n[MOB12_A]\nTommy! C'est Avery! Ecoute, je suis débordé de boulot pour le moment,\n\n[MOB12_B]\net j'ai un de mes réprésentants qui a besoin d'être chaperonné jusqu'aux Gator Keys.\n\n[MOB12_C]\nJe suis sur l'achat d'un terrain là-bas, alors j'envoie un mec graisser quelques pattes.\n\n[MOB12_D]\nJ'ai besoin que tu t'assures qu'il arrive bien là-bas. OK?\n\n[MOB12_E]\nOK, pas de problème, Avery! Mais où c'est que je le trouve, ce mec?\n\n[MOB12_F]\nIl boucle une affaire au chantier. Je lui ai dit que tu le prendrais là-bas.\n\n[MOB12_G]\nOk, Avery. J'y vais. A plus tard.\n\n[MOB13_A]\nVercetti? VERCETTI! Putain, mec, faut que tu me files un coup de main!\n\n[MOB13_B]\nMr Moffat? Comment va la famille?\n\n[MOB13_C]\nMerde, mais quel con! Tu m'entends?\n\n[MOB13_D]\nCa m'a fait plaisir d'avoir des nouvelles...\n\n[MOB13_E]\nAttends! Attends! Vercetti, euh... Tommy. Je peux t'appeler Tommy?\n\n[MOB13_F]\nOn est tous les deux dans les affaires, pas vrai? Et tu sais renifler les bonnes, hein?\n\n[MOB13_G]\nJ'ai pas le temps de causer, viens-en au fait!\n\n[MOB13_H]\nDu FRIC! Voilà le putain de fait!\n\n[MOB13_I]\nJe me suis encore tiré de taule, mais ça prend jamais longtemps avant qu'ils me retombent dessus. Pour eux, c'est qu'un putain de jeu!\n\n[MOB13_J]\nJe t'appelle d'une cabine quelque part dans le trou du cul du monde!\n\n[MOB13_K]\nSors-moi de là avant qu'ils me chopent encore et... et... ah... meeeerde...\n\n[MOB13_L]\nEh bien, c'est que je suis très occupé pour les prochaines-\n\n[MOB13_M]\nNon! Me laisse pas dans cette merde! T'as pas de coeur ou quoi? Putain, j'devrais pas avoir à m'abaisser comme ça!\n\n[MOB13_N]\nJe suis à genoux, Tommy! Et c'est les rotules dans la poussière que je te supplie...\n\n[MOB13_O]\nJ'imagine que je pourrais passer dans le coin et voir si je te trouve...\n\n[MOB13_P]\nOh, merde, les voilà! Putain, magne-toi, Tommy! Vite!\n\n[MOB_14A]\nSalut, Tommy, on va bien s'entendre, toi et moi.\n\n[MOB_14B]\nUne tendre amie est venu me sussurrer dans l'oreille que la division SWAT de Vice City a un coffre dans une grosse banque,\n\n[MOB_14C]\net ils y gardent les pots-de-vin de toutes ces dernières années.\n\n[MOB_14D]\nC'est une sorte de caisse de retraite pour vieux garçons.\n\n[MOB_14E]\nEvidemment, si cette info pouvait t'aider à ramasser un peu de ce pognon,\n\n[MOB_14F]\nj'imagine que tu te sentirais obligé de m'en refiler un peu, pas vrai, Tommy?\n\n[MOB_14G]\nJe vais garder ça à l'esprit, merci, Kent.\n\n[MOB_14H]\nJe m'appelle Paul, abruti! Et je suis du Kent, près de Londres.\n\n[MOB_14I]\nPour ce que j'en ai à foutre de la campagne anglaise, depuis l'école...\n\n[MOB15_A]\nTommy, mon vieux, c'est Paul, du Kent.\n\n[MOB15_B]\nIl y a une ou deux authentiques dames qui ont ton nom plein la bouche, au Malibu.\n\n[MOB15_C]\nDe quoi tu parles?!\n\n[MOB15_D]\nDe gonzesses, de poulettes, de filles, quoi! Et bien élevées, pas le genre à causer pognon.\n\n[MOB15_E]\nFaut que tu viennes voir ça.\n\n[MOB16_A]\nTommy, c'est Paulo, que pasa amigo?\n\n[MOB16_B]\nQu'est-ce que tu m'veux, Paul? J'ai pas besoin de fausses fringues de marque.\n\n[MOB16_C]\nTrès drôle, mon vieux, mais je fais pas dans la fringue de tapette, moi.\n\n[MOB16_D]\nBon, je t'appelle parce que j'me demande si je ne pourrais pas avoir un rôle dans un de tes films.\n\n[MOB16_E]\nJ'ai fait pas mal de pornos en Angleterre, mon vieux.\n\n[MOB16_F]\nAu plumard, je suis une mitrailleuse lourde.\n\n[MOB16_G]\nMerci de me proposer tes services, Paul, j'y réfléchirai.\n\n[MOB16_H]\nSérieusement, pense à moi, après tout ce que j'ai fait pour toi...\n\n[MOB16_I]\nJustement, j'essaie de l'oublier.\n\n[MOB17_A]\nTommy Vercetti, comment ça va, big boss?\n\n[MOB17_B]\nJ'ai entendu tous ces trucs sur toi. Un flambeur en ville maintenant...\n\n[MOB17_C]\nPaul, t'es bourré.\n\n[MOB17_D]\nNaan! Pauvre abruti! J'suis pas saoul!\n\n[MOB17_E]\nJ'ai juste pris un ou deux verres et quelques tournées, et ça fait deux jours que j'ai pas fermé l'oeil!\n\n[MOB17_F]\nDe toute façon, ne me traite pas comme ça.\n\n[MOB17_G]\nJe suis pas une poire. Qui c'est qui t'a lancé dans cette ville? Hein, qui? Moi!\n\n[MOB17_H]\nAh ouais?\n\n[MOB17_I]\nOuais!\n\n[MOB17_J]\nPaul, t'énerve pas. J'étais occupé, sois pas stupide.\n\n[MOB17_K]\nJe suis pas stupide, connard! Ils me l'ont dit en maison de redressement!\n\n[MOB17_L]\nSi tu cherches les emmerdes, mon pote, tu vas les trouver!\n\n[MOB17_M]\nTommy, s'il te plaît! T'étais mon grand espoir! Te fous pas de moi!\n\n[MOB17_N]\nPaul, va roupiller un bon coup, sérieusement.\n\n[MOB18_A]\nTommy, c'est Paulo, comment ça va, mon pote, je me suis dit que j'allais te passer un petit coup de fil.\n\n[MOB18_B]\nAh, mon pote, tu croiras jamais l'incroyable petit lot que je viens de lever...\n\n[MOB18_C]\nElle se promenait juste en bas dans Little Havana, mon pote.\n\n[MOB18_D]\nElle m'a dit qu'elle s'appelait Mercedes ou un truc comme ça. Ah, mon pote, faut que t'ailles voir cette fille!\n\n[MOB18_E]\nElle ferait bander un eunuque! Elle m'a dit que j'étais le meilleur coup de sa vie et tout et tout!\n\n[MOB18_F]\nVas-y, trouve-la. A plus tard.\n\n[MOB19_A]\nTommy V, c'est KP! Kent Paul. Le bruit court que des mecs veulent te faire la peau.\n\n[MOB19_B]\nOuvre l'oeil, mon pote. Et oublie pas... Je t'ai rien dit.\n\n[MOB_20A]\nSalut, Tommy, c'est Paul. Je viens juste d'entendre dire que t'avais été un vilain garçon.\n\n[MOB_20B]\nIl y a quelqu'un qui s'est vexé de te voir jouer les caïds et ça lui a donné de mauvaises idées...\n\n[MOB_20C]\nBon, dis à personne que je t'ai rencardé. Les grandes gueules finissent toujours par l'avoir dans l'os.\n\n[MOB_20D]\nEnfin, j'ai entendu dire que ta tête a été mise à prix et que quelqu'un va essayer de t'avoir,\n\n[MOB_20E]\nalors fais gaffe, et m'oublie pas, mon pote.\n\n[MOB71_A]\nTommy, Thomas, c'est Cortez. Que pasa?\n\n[MOB71_B]\nLes affaires tournent... Et toi, comment ça va?\n\n[MOB71_C]\nTommy, ici, c'est toujours la guerre. Excusez la mauvaise ligne, mais on vient juste d'avoir un nouveau coup d'état manqué.\n\n[MOB71_D]\nLe peuple est la plus exigeante des maîtresses.\n\n[MOB71_E]\nSi je compte bien, y'a eu trois révolutions et quatre coups d'état depuis que je suis rentré de Vice City.\n\n[MOB71_F]\nHeureusement, à chaque fois, j'ai pris du galon.\n\n[MOB71_G]\nJe voulais vous demander quelque chose à propos de Mercedes...\n\n[MOB71_H]\nOuais? Quoi?\n\n[MOB71_I]\nVoilà, Tommy, Tommy, j'ai entendu toutes ces histoires et je sais pas quoi penser...\n\n[MOB71_J]\nPeut-être que tout le monde essaye de m'humilier...\n\n[MOB71_K]\nPeut-être qu'elle se croit tout permis, mais dites-moi juste la vérité, Tommy, c'est vrai?\n\n[MOB71_L]\nMais dites-moi juste la vérité, Tommy, c'est vrai?\n\n[MOB71_M]\nQu'est-ce qui est vrai?\n\n[MOB71_N]\nCes bruits qui courent... Elle va vraiment devenir avocate?\n\n[MOB71_O]\nAh, Tommy, c'est une véritable honte! Nous, les Cortez, sommes une honorable famille et nous ne tolèrerons jamais qu'une de nos filles devienne avocate.\n\n[MOB71_P]\nJe vous en prie, dites-moi que ce n'est pas vrai, je ne crois pas que je pourrais le supporter.\n\n[MOB71_Q]\nColonel, je peux vous assurer que Mercedes ne deviendra jamais avocate. Ne vous inquiètez pas.\n\n[MOB71_R]\nMerci, Tommy, cette honte me serait insupportable. C'est une femme, pas un parasite, vous comprenez.\n\n[MOB71_S]\nJe le sais, colonel.\n\n[MOB71_T]\nBon, vous allez devoir m'excuser, Tommy, mais le nouveau ministre de l'intérieur vient d'arriver...\n\n[MOB71_U]\nIl y a de nombreuses années, j'ai tué son père au cours d'une tentative de coup d'état ratée et je dois me montrer poli. Adios, amigo.\n\n[MOB22_A]\nTommy, vous vous révèlez très utile, amigo.\n\n[MOB22_B]\nMerci, Cortez. Et mon affaire?\n\n[MOB22_C]\nTommy, je travaille inlassablement en ce sens pour aller au fond des choses et de la vérité dans cette terrible histoire.\n\n[MOB22_D]\nVous avez ma parole, mais en attendant,\n\n[MOB22_E]\nacceptez, je vous en prie, les sincères remerciements de mon peuple pour vos actions bénéfiques.\n\n[MOB_25A]\nTommy, c'est Cortez. Les Français me font beaucoup d'ennuis...\n\n[MOB_25B]\nLes sales hypocrites! Ils passent des siècles à piller les pays pauvres et ils osent me traiter de voleur!\n\n[MOB_25C]\nJe vais avoir besoin de votre aide aussi vite que possible.\n\n[MOB_25D]\nVite, Tommy, j'ai vraiment besoin de vous. Je hais ces maudits Français!\n\n[MOB_26A]\nAllo, Tommy?\n\n[MOB_26B]\nOuais?\n\n[MOB_26C]\nC'est moi, Baker. Je voulais juste te dire que j'ai beaucoup apprécié le spectacle.\n\n[MOB_26D]\nMoi et mes gars, on veut te remercier, et te rappeler\n\n[MOB_26E]\nque tu as tout notre respect. Bon, salut. Et continue comme ça, mon pote.\n\n[MOB_29A]\nAllo? Vous êtes bien M. Tommy Vercetti?\n\n[MOB_29B]\nOuais.\n\n[MOB_29C]\nBien. J'ai entendu dire que vous êtes l'homme à appeler quand on est victime d'une invasion de vermine.\n\n[MOB_29D]\nCa se peut...\n\n[MOB_29E]\nEh bien, là je suis vraiment envahi par la vermine. Les haïtiens sont partout...\n\n[MOB_29F]\nJe m'appelle Umberto Robina et je vous propose une rencontre au Café Robina aussitôt que vous pourrez.\n\n[MOB_29G]\nMoi j'vous le dis, ces maudits haïtiens sont allés trop loin, cette fois...\n\n[MOB_29H]\nTest\n\n[MOB_30A]\nTommy, c'est Umberto Robina.\n\n[MOB_30B]\nQuoi de neuf au café?\n\n[MOB_30C]\nOh, merveilleux, Tommy, vraiment incroyable! Ici, plus de mauviettes, Tommy. Juste de vrais hommes et des belles filles!\n\n[MOB_30D]\nJe voulais te dire que moi et papa, maintenant, on te considère comme cubain.\n\n[MOB_30E]\nT'as fait tes preuves, mon frère et t'en as une sacrée paire dans l'pantalon!\n\n[MOB_30F]\nEuh, merci, Umberto. Personne ne m'a dit ça depuis que je suis sorti de taule. Bon, salut.\n\n[MOB_33A]\nTommy, c'est Phil! Bon, arrête tes conneries et écoute-moi, tu veux?\n\n[MOB_33B]\nBon. J'ai du whisky extra fort, presque fermenté, et je me demandais si tu voulais pas venir boire un coup...\n\n[MOB_33C]\nSans déconner, Tommy, si t'as besoin d'un verre ou de décoller de la peinture, t'es le bienvenu, ce truc fera de toi un homme!\n\n[MOB_33D]\nCa me fait cet effet, même si je vois plus rien d'un oeil. Je t'attends, t'entends?\n\n[MOB_34A]\nTommy, ça m'a fait vraiment plaisir de bosser avec toi. Je m'étais pas autant marré depuis la guerre du Vietnam, mon pote.\n\n[MOB_34B]\nBon, si t'as besoin de quelque chose, tu m'appelles, t'entends?\n\n[MOB_34C]\nJe n'oublie jamais ceux avec qui j'ai servi\n\n[MOB_34D]\net je suis sûr que je peux t'aider, t'entends?\n\n[MOB_35A]\nTommy, la blessure cicatrise bien. Le truc drôle, c'est que\n\n[MOB_35B]\nj'ai combattu dans six batailles et que je m'en suis toujours sorti sans une égratignure, et voilà!\n\n[MOB_35C]\n'Phil, le manchot d'un bras.' Enfin, j'ai encore une large selection d'armes de poing alors je serai jamais 'Phil, le désarmé', t'entends?\n\n[MOB_35D]\nAller, mon pote, laisse tomber les conneries sentimentales et va te boire un verre, t'entends?\n\n[MOB_36A]\nTommy, c'est Phil. Je voulais te remercier pour le coup de main, mon pote.\n\n[MOB_36B]\nSalopard de Charlie, toujours à tendre des embuscades ici ou là,\n\n[MOB_36C]\nmais la blessure cicatrise bien, et ça veut aussi dire que j'aurai plus à truander le gouvernement pour le contrôle d'invalidité. Merci, mon pote.\n\n[MOB_40A]\nSalut, Tommy, c'est Sonny. Alors ce bronzage?\n\n[MOB_40B]\nJ'suis pas bronzé.\n\n[MOB_40C]\nOuais et t'as pas non plus mon pognon, alors je m'interrogeais...\n\n[MOB_40D]\nJe me disais : 'Qu'est-ce qu'il fout?' Alors, je te le demande, Tommy, qu'est-ce que tu fous?\n\n[MOB_40E]\nJe cherche le pognon, Sonny, t'inquéte pas!\n\n[MOB_40F]\nJe m'inquiéte, Tommy, c'est mon genre,\n\n[MOB_40G]\nparce que j'ai ce problème récurrent dans la vie de tomber sur des gens indignes de confiance...\n\n[MOB_40H]\nNe sois pas indigne de ma confiance, Tommy, s'il te plaît...\n\n[MOB_40I]\nRends-nous à tous deux ce service. J'attends de tes nouvelles...\n\n[MOB_41A]\nTommy, tu te souviens de moi?\n\n[MOB_41B]\nSalut, Sonny.\n\n[MOB_41C]\nOuais, exactement, Sonny, on est de vieux amis,\n\n[MOB_41D]\nmais tu ne m'écris jamais, tu ne m'appelles jamais. Tu ne veux plus qu'on soit amis?\n\n[MOB_41E]\nJ'ai été très occupé à régler des trucs ici et là. Tu ne m'aides pas beaucoup, ici.\n\n[MOB_41F]\nOh, c'est ma faute? Bon, j'ai entendu que tu étais très occupé, d'accord,\n\n[MOB_41G]\noccupé à liquider des barons de la drogue, occupé à prendre le pouvoir.\n\n[MOB_41H]\nAlors je te préviens simplement de ne pas m'oublier, Tommy, parce que moi, je ne t'oublie pas...\n\n[MOB_42A]\nTommy.\n\n[MOB_42B]\nSonny.\n\n[MOB_42C]\nFaut croire que t'es à moitié sourd, alors je vais me répéter :\n\n[MOB_42D]\nTommy, où est ce putain de pognon? Où est cette putain de marchandise? Et où est ma putain de part sur ta nouvelle affaire?\n\n[MOB_42E]\nTu te fous vraiment d'ma gueule, Tommy, et ça me fait pas rire!\n\n[MOB_43A]\nTommy! Tommy! J'ai eu Sonny au téléphone. Tu m'écoutes?\n\n[MOB_43B]\nJe ne sais pas pour toi, mais il y a un mec qui menace de buter toute ma famille,\n\n[MOB_43C]\net ça me fout vraiment les jetons. Qu'est-ce que tu comptes faire?\n\n[MOB_43D]\nReste calme, Ken, tout va bien se passer.\n\n[MOB_43E]\nJe suis calme! Calme comme un homme qui craint pour sa propre vie!\n\n[MOB_43F]\nKen, j'ai d'autres choses en tête pour l'instant,\n\n[MOB_43G]\non s'occupera de Forelli quand l'heure sera venue.\n\n[MOB_43H]\nJe suis calme. J'ai pas l'air calme? J'sais pas, c'est ma voix qui a changé à cause de la mort qui me pend au nez!\n\n[MOB45_A]\nTommy, faut qu'on cause sérieusement.\n\n[MOB45_B]\nC'est quoi le problème, Lance?\n\n[MOB45_C]\nC'est toi le problème, mon pote, j'ai l'impression que tu m'files pas une part équitable...\n\n[MOB45_D]\nMais le pire, c'est que tu m'as foutu la honte devant les mecs. Je supporte pas ça.\n\n[MOB45_E]\nLance, c'est pas ça du tout. T'as fait des bourdes, c'est tout.\n\n[MOB45_F]\nTommy, je suis pas ton petit messager et encore moins ton garçon de courses.\n\n[MOB45_G]\nLance, déconne pas et on aura pas d'emmerdes! Et si c'est moi qui déconne, tu peux me rentrer dedans quand tu veux.\n\n[MOB45_H]\nTommy, j'ai tout fait pour toi et tu me traites comme un con. Fais pas ça.\n\n[MOB45_I]\nLance, je ne vais pas t'arnaquer ou te planter un couteau dans le dos, ok?\n\n[MOB45_J]\nT'énerve pas. C'est déjà assez dur comme ça, sans que tu perdes les pédales.\n\n[MOB45_K]\nFais-moi confiance. Tu m'entends? Tu m'entends?\n\n[MOB45_L]\nJe t'entends, Tommy, mais je peux pas supporter ça plus longtemps.\n\n[MOB45_M]\nLance, arrête de déconner. Maintenant, je te préviens.\n\n[MOB45_N]\nTu m'entends? Relax! Prends quelques jours de repos et on en reparle, ok?\n\n[MOB46_A]\nTommy, c'est Lance.\n\n[MOB46_B]\nOuais?\n\n[MOB46_C]\nMême pas un 'ça fait plaisir d'avoir des tes nouvelles'? Allez, mec, sois sympa!\n\n[MOB46_D]\nJe suis occupé. Qu'est-ce que tu veux?\n\n[MOB46_E]\nRien. C'était juste pour te dire... Tu sais, Tommy, on peut faire ce truc.\n\n[MOB46_F]\nToi et moi, sans problème. Tu vois ce que je veux dire?\n\n[MOB46_G]\nVa bien falloir qu'on le fasse, parce que sinon, on est morts, Lance.\n\n[MOB46_H]\nOn peut plus reculer, maintenant, mais merci de ton appel. On se reparle plus tard.\n\n[MOB_47A]\nTommy, c'est Lance, on a de gros problèmes. Amène-toi ici en vitesse.\n\n[MOB52_A]\nSalut, Léo, je crois qu'on a un acheteur pour la marchandise de Diaz.\n\n[MOB52_B]\nIl faut que tu l'appelles, mec, pour organiser le deal, tu comprends?\n\n[MOB52_C]\nT'es où, là?\n\n[MOB52_D]\nT'es sûr que ça va, Léo? T'as une voix bizarre...\n\n[MOB52_E]\nDis-moi juste où t'es.\n\n[MOB52_F]\nQui c'est qui cause? Je veux parler à Léo!\n\n[MOB52_G]\nLéo est parti pour un moment, je le remplace.\n\n[MOB52_H]\nVa te faire foutre, connard!\n\n[MOB54_A]\nSalut, Tommy!\n\n[MOB54_B]\nSalut, Mercedes, quoi de neuf?\n\n[MOB54_C]\nJ'ai un nouvel appartement dans Vice Point.\n\n[MOB54_D]\nJ'ai pensé que tu voudrais peut-être passer un de ces quatre...\n\n[MOB54_E]\nJ'adorerai. A plus tard.\n\n[MOB55_A]\nTommy, c'est moi.\n\n[MOB55_B]\nSalut, Mercedes.\n\n[MOB55_C]\nTommy, je m'ennuie tellement! Quand est-ce qu'on va s'amuser?\n\n[MOB55_D]\nComment ça?\n\n[MOB55_E]\nBon, je sais que t'es très occupé à te battre, à tuer des gens ou à les corrompre,\n\n[MOB55_F]\nmais moi, j'ai envie de m'amuser un peu! Alors, ne m'oublie pas, Tommy!\n\n[MOB56_A]\nTommy, j'ai entendu dire que tu avais tué Ricardo Diaz!\n\n[MOB56_B]\nUn feu accidentel s'est déclenché dans sa résidence...\n\n[MOB56_C]\nJe pense qu'il a cramé dans sa chemise en acrylique.\n\n[MOB56_D]\nTommy, je suis si fière de toi! Je savais que tu étais un vrai macho!\n\n[MOB56_E]\nAh, mon dur de dur, je suis si fière d'être ton amie!\n\n[MOB56_F]\nJe sais que tu vas être très occupé à essayer de t'emparer de cette ville,\n\n[MOB56_G]\nmais ne m'oublie pas, d'accord?\n\n[MOB57_A]\nC'est Mercedes. Je ne t'aime plus, Tommy!\n\n[MOB57_B]\nC'est fini! C'est vrai! Parce que tu n'es plus gentil avec moi!\n\n[MOB57_C]\nTu ne me traites plus comme une dame! Tu m'ignores et je te déteste!\n\n[MOB57_D]\nJe veux que tu viennes me voir tout de suite! \"\n\n[MOB58_A]\nTommy.\n\n[MOB58_B]\nSalut, Mercedes.\n\n[MOB58_C]\nBonjour monsieur le vrai dur! Je suis très en colère contre toi, Tommy!\n\n[MOB58_D]\nNe m'oblige plus jamais à supporter Jezz Torrent!\n\n[MOB58_E]\nIl est pathétique! En plein milieu il a commencé à pleurer à cause de son toutou\n\n[MOB58_F]\nqui est mort quand il avait 7 ans et parce que sa mère ne l'a jamais aimé...\n\n[MOB58_G]\nEn plus, Tommy, il porte une perruque et un soutien-gorge dans l'intimité!\n\n[MOB58_H]\nJe t'en veux vraiment!\n\n[MOB59_A]\nOoh Tommy, c'est Mercedes.\n\n[MOB59_B]\nJe voulais juste te dire que je m'étais éclatée sur le tournage!\n\n[MOB59_C]\nSi tu as quelque chose d'autre de ce genre, pense à moi!\n\n[MOB59_D]\nJe suis sincère! J'ai toujours voulu être actrice!\n\n[MOB59_E]\nJe crois que j'ai beaucoup appris sur l'art dramatique!\n\n[MOB59_F]\nC'est tellement révélateur! Merci beaucoup! On se voit très bientôt, adios!\n\n[MOB_99]\nRends-toi à la cabine indiquée.\n\n[MOB_98]\nRends-toi à la cabine indiquée.\n\n[MOB_97]\nRends-toi à la cabine indiquée.\n\n[MOB_96]\nRends-toi à la cabine indiquée.\n\n[MOB_95]\nRends-toi à la cabine indiquée.\n\n[A_TIME]\n+~1~ secondes\n\n[F_RANGE]\nLa radio du camion de pompiers ne capte plus rien. Rapproche-toi d'une caserne!\n\n[DODO_FT]\nTu as 'volé' pendant ~1~ secondes!\n\n[GA_8]\nUtilise le détonateur pour armer la bombe.\n\n[GA_10]\nBravo. Voilà tes ~1~$.\n\n[GA_11]\nOn en a déjà des comme ça. Ca nous sert à rien!\n\n[GA_12]\nBombe armée\n\n[GA_13]\nComme un pro! Finis la liste et t'auras un bonus!\n\n[GA_14]\nToutes les voitures! PARFAIT! Tiens, voilà un petit quelque chose!\n\n[GA_15]\nJ'espère que t'aimes la nouvelle couleur.\n\n[GA_16]\nLa peinture est en option!\n\n[GA_19]\nCe modèle ne nous intéresse pas!\n\n[GA_20]\nOn en a trop des comme ça! Désolé, mec.\n\n[CHASE]\nAttention maximale des médias\n\n[CHASE1]\nIgnoré\n\n[CHASE2]\nEnnuyeux\n\n[CHASE3]\nPlus ou moins intéressant\n\n[CHASE4]\nJournal local page 7\n\n[CHASE5]\nJournal local La une\n\n[CHASE6]\nVice Courier Rubrique 1\n\n[CHASE7]\nVice Courier La une\n\n[CHASE8]\nTélé locale 3h du mat'\n\n[CHASE9]\nTélé locale Infos\n\n[CHASE10]\nTélé locale Direct\n\n[CHASE11]\nUFA Today page 12\n\n[CHASE12]\nUFA Today page 4\n\n[CHASE13]\nPhoto dans UFA Today\n\n[CHASE14]\nTélé nationale 4h du mat'\n\n[CHASE15]\nTélé nationale Infos\n\n[CHASE16]\nTélé nationale Direct\n\n[CHASE17]\nInfos internationales\n\n[CHASE18]\nCrise nationale\n\n[CHASE19]\nCrise internationale\n\n[CHASE20]\nEvénement mondial\n\n[CHASE21]\nTruc de légendes\n\n[CR_1]\nLa grue ne peut pas soulever ce véhicule.\n\n[PU_MONY]\nT'as pas assez de liquide.\n\n[CO_ALL]\nTu les as toutes eues. Tiens, voilà pour toi...\n\n[FEM_ON]\nActivé\n\n[FEM_OFF]\nDésactivé\n\n[FEM_YES]\nOui\n\n[FEM_NO]\nNon\n\n[FEM_RET]\nRéessayer\n\n[FEC_NA]\nNA\n\n[FEC_CWL]\nFaire défiler les armes vers la gauche\n\n[FEC_CWR]\nFaire défiler les armes vers la droite\n\n[FEC_LOF]\nRegarder devant\n\n[FEC_TAR]\nViser\n\n[FEC_MOV]\nDéplacement\n\n[FEC_CAM]\nModes caméra\n\n[FEC_PAU]\nPause\n\n[FEC_ENV]\nMonter dans un véhicule\n\n[FEC_JUM]\nSauter\n\n[FEC_ATT]\nAttaquer ou tirer\n\n[FEC_RUN]\nCourir\n\n[FEC_FPC]\nVue subjective\n\n[FEC_LL]\nRergarder à gauche\n\n[FEC_LB]\nRegarder derrière\n\n[FEC_LR]\nRegarder à droite\n\n[FEC_HOR]\nKlaxon\n\n[FEC_VES]\nCommandes du véhicule\n\n[FEC_BRA]\nFreiner ou marche arrière\n\n[FEC_HAB]\nFrein à main\n\n[FEC_CAW]\nArme du véhicule\n\n[FEC_ACC]\nAccélérateur\n\n[FEC_CCF]\nConfiguration :\n\n[FEC_CF1]\nConfig. 1\n\n[FEC_CF2]\nConfig. 2\n\n[FEC_CF3]\nConfig. 3\n\n[FEC_CF4]\nConfig. 4\n\n[FEC_CDP]\nAffichage manette :\n\n[FEC_ONF]\nà pied\n\n[FEC_INC]\nEn voiture\n\n[FEC_VIB]\nVibrations :\n\n[FEL_ENG]\nAnglais\n\n[FEL_FRE]\nFrançais\n\n[FEL_GER]\nAllemand\n\n[FEL_ITA]\nItalien\n\n[FEL_SPA]\nEspagnol\n\n[FED_DBG]\nMenu Debug\n\n[FED_RID]\nRecharger IDE\n\n[FED_RIP]\nRecharger IPL\n\n[FED_PAH]\nAnalyser Saut\n\n[FED_DFL]\nCTheScripts::DbgFlag\n\n[FED_DLS]\nLumière blanche de debug allumée\n\n[FED_SPR]\nAffiche les groupes de pietons\n\n[FED_SCR]\nAffiche les groupes en voiture\n\n[FED_SCZ]\nAffiche les zones de massacre\n\n[FED_DSR]\nDebug les demandes de répartition par niveaux\n\n[FED_SCP]\ngb Indique les polys de collision\n\n[PL_STAT]\nStats du joueur\n\n[PE_WAST]\nPersonnes tuées par toi\n\n[PE_WSOT]\nPersonnes tuées par d'autres\n\n[TM_BUST]\nNb de fois capturé\n\n[GNG_WST]\nGangsters tués\n\n[DED_CRI]\nCriminels tués\n\n[PER_COM]\nPourcentage accompli\n\n[KGS_EXP]\nKilos d'explosifs utilisés\n\n[ACCURA]\nPrécision\n\n[ST_WEAP]\nBudget arsenal\n\n[ST_PROP]\nBudget propriété\n\n[ST_AUTO]\nBudget réparation et peinture voiture\n\n[ST_PHOT]\nPhotos prises\n\n[ST_LOAN]\nVisites des usuriers\n\n[ST_STOR]\nMagasins liquidés\n\n[ST_MOVI]\nCascades de films\n\n[ST_PIZZ]\nPizza livrées\n\n[ST_GARB]\nCollectes de détritus effectuées\n\n[ST_ICEC]\nCrèmes glacées vendues\n\n[TOP_SHO]\nMeilleur score au champ de tir\n\n[SHO_RAN]\nPosition au champ de tir\n\n[SEAGULL]\nMouettes descendues\n\n[PROPOWN]\nPropriété possédée\n\n[ST_TIME]\nTemps de jeu\n\n[ST_FTIM]\nHeures de vol\n\n[ST_PRAN]\nClassement pilote\n\n[ST_RAN0]\nApprenti\n\n[ST_RAN1]\nNavigateur\n\n[ST_RAN2]\nCopilote\n\n[ST_RAN3]\nJunior\n\n[ST_RAN4]\nCompétent\n\n[ST_RAN5]\nSenior\n\n[ST_RAN6]\nAs\n\n[ST_RAN7]\nBaron rouge\n\n[ST_DRWN]\nPoissons nourris\n\n[ST_FASH]\nBudget fringues\n\n[ST_DAMA]\nPropriété détruite\n\n[TM_DED]\nVisites à l'hôpital\n\n[DAYSPS]\nJours passés dans le jeu\n\n[NUMSHV]\nVisites dans l'entrepôt\n\n[MXCARD]\nDist. max. de saut de Cascade dangereuse (ft)\n\n[MXCARJ]\nHauteur max. de saut de Cascade dangereuse(ft)\n\n[MXCARDM]\nDist. max. de saut de Cascade dangereuse (m)\n\n[MXCARJM]\nHauteur max. de saut de Cascade dangereuse (m)\n\n[MXFLIP]\nSaltos max. de saut de Cascade dangereuse\n\n[MXJUMP]\nRotation max. de saut de Cascade dangereuse\n\n[BUL_FIR]\nBalles tirées\n\n[BUL_HIT]\nBalles ayant atteint la cible\n\n[SPRAYIN]\nPeintures\n\n[BSTSTU]\nMeilleure cacade jusqu'à maintenant\n\n[INSTUN]\nCascade dangereuse\n\n[PRINST]\nCascade dangereuse parfaite\n\n[DBINST]\nDouble cascade dangereuse\n\n[DBPINS]\nDouble cascade dangereuse parfaite\n\n[TRINST]\nTriple cascade dangereuse\n\n[PRTRST]\nTriple cascade dangereuse parfaite\n\n[QUINST]\nQuadruple cascade dangereuse\n\n[PQUINS]\nQuadruple cascade dangereuse parfaite\n\n[NOSTUC]\nAucune cascade dangereuse réalisée\n\n[NOUNIF]\nSauts uniques accomplis\n\n[NMISON]\nTentatives de mission\n\n[PASDRO]\nPassagers perdus\n\n[MONTAX]\nTotal des courses en taxi\n\n[DAYPLC]\nDépenses quotidiennes de police\n\n[CRIMRA]\nTaux de criminalité :\n\n[STPR_1]\nLe Malibu\n\n[STPR_2]\nImprimerie\n\n[STPR_3]\nStudio de cinéma\n\n[STPR_4]\nUsine de crème glacée\n\n[STPR_5]\nConcession automobile\n\n[STPR_6]\nCompagnie de taxis\n\n[STPR_7]\nChantier naval\n\n[SET1EN]\nConfig. 1. Activée\n\n[GMSAVE]\nSauvegarder partie\n\n[FEDS_TB]\nRetour\n\n[FEST_OO]\nsur\n\n[FEC_TUC]\nCommandes tourelle\n\n[FEC_RS3]\nFaire défiler les stations de radio (touche L3)\n\n[FEC_HO3]\nKlaxonner (touche L3)\n\n[C_FAIL]\nMission d'autodéfense terminée!\n\n[C_ESCP]\n~r~Le suspect s'est échappé!\n\n[C_VIGIL]\nBONUS AUTODEFENSE!\n\n[HEAL_A]\nTon niveau de ~h~santé~w~ s'affiche en orange en haut à droite de l'écran.\n\n[WRONGCD]\nDisque invalide. Insère le bon disque.\n\n[NOCD]\nLe compartiment à disque est vide. Insère un disque.\n\n[OPENCD]\nLe compartiment à disque est ouvert. Referme-le.\n\n[CDERROR]\nErreur au cours de la lecture du DVD de Grand Theft Auto: Vice City\n\n[RESTART]\nDémarrage d'une nouvelle partie\n\n[GA_3]\nPlus de cadeaux. 100$ pour repeindre!\n\n[GA_1]\nOula! Je ne touche à rien d'aussi chaud, moi!\n\n[GA_1A]\nReviens quand tu seras moins occupé...\n\n[HELP9_C]\nAppuie sur la~h~ ~k~~PED_FIREWEAPON~ ~w~pour ~h~tirer~w~ avec le fusil à lunette.\n\n[TAXI2]\n~r~Tu n'as plus le temps!\n\n[PAGEB13]\nSanté livrée à la planque\n\n[PAGEB14]\nAdrénaline livrée à la planque\n\n[FESZ_CA]\nAnnuler\n\n[FES_NGA]\nNouvelle partie\n\n[FES_CAN]\nAnnuler\n\n[FESZ_QL]\nToutes les étapes non sauvegardées de cette partie seront perdues. Charger la partie?\n\n[FESZ_QD]\nEffacer cette sauvegarde?\n\n[FESZ_QO]\nEcraser cette sauvegarde?\n\n[FESZ_QR]\nVeux-tu vraiment commencer une autre partie? Toutes les données depuis la dernière partie sauvegardée seront perdues. Continuer?\n\n[T4X4_1]\n'Terrain de jeu PCJ'\n\n[BMX_1]\n'Sélection par la boue'\n\n[BMX_2]\n'Piste d'essai'\n\n[BMXFAIL]\n~r~Tu n'as pas réussi à établir un nouveau record!\n\n[T4X4_3]\n'DANS LA POCHE!'\n\n[MM_1]\n'Cônes en folie'\n\n[T4X4_F]\n~r~Tu t'es barré! Trop dur pour toi?\n\n[LANDSTK]\nLandstalker\n\n[IDAHO]\nIdaho\n\n[STINGER]\nStinger\n\n[LINERUN]\nLinerunner\n\n[PEREN]\nPerennial\n\n[SENTINL]\nSentinelle\n\n[RIO]\nRio\n\n[PATRIOT]\nPatriote\n\n[FIRETRK]\nCamion de pompier\n\n[TRASHM]\nTrashmaster\n\n[STRETCH]\nStretch\n\n[MANANA]\nManana\n\n[INFERNS]\nInfernus\n\n[VOODOO]\nVoodoo\n\n[PONY]\nPony\n\n[MULE]\nMule\n\n[CHEETAH]\nCheetah\n\n[AMBULAN]\nAmbulance\n\n[FBICAR]\nFBI Washington\n\n[MOONBM]\nMoonbeam\n\n[ESPERAN]\nEsperanto\n\n[TAXI]\nTaxi\n\n[WASHING]\nWashington\n\n[BOBCAT]\nBobcat\n\n[WHOOPEE]\nMr Whoopee\n\n[BFINJC]\nBF Injection\n\n[HUNTER]\nHunter\n\n[POLICAR]\nPolice\n\n[ENFORCR]\nEnforcer\n\n[SECURI]\nSecuricar\n\n[BANSHEE]\nBanshee\n\n[PREDATR]\nPredator\n\n[BUS]\nBus\n\n[RHINO]\nRhino\n\n[BARRCKS]\nBarracks OL\n\n[CUBAN]\nCuban Hermes\n\n[HELI]\nHélicoptère\n\n[DODO]\nDodo\n\n[COACH]\nCoach\n\n[CABBIE]\nCabbie\n\n[STALION]\nStallion\n\n[RUMPO]\nRumpo\n\n[RCBANDT]\nRC Bandit\n\n[ROMERO]\nCorbillard de Romero\n\n[PACKER]\nPacker\n\n[ADMIRAL]\nAmiral\n\n[SQUALO]\nSqualo\n\n[SEASPAR]\nSea Sparrow\n\n[PIZZABO]\nPizza Boy\n\n[GANGBUR]\nGang Burrito\n\n[TROPIC]\nTropic\n\n[SPEEDER]\nSpeeder\n\n[REEFER]\nReefer\n\n[FLATBED]\nFlatbed\n\n[YANKEE]\nYankee\n\n[CADDY]\nCaddy\n\n[ZEBRA]\nTaxi Zebra\n\n[TOPFUN]\nTop Fun\n\n[SKIMMER]\nSkimmer\n\n[PCJ600]\nPCJ 600\n\n[PHOENIX]\nPhoenix\n\n[FAGGIO]\nFaggio\n\n[FREEWAY]\nFreeway\n\n[RCBARON]\nRC Baron\n\n[RCRAIDE]\nRC Raider\n\n[GLENDAL]\nGlendale\n\n[OCEANIC]\nOceanic\n\n[SANCHEZ]\nSanchez\n\n[SPARROW]\nSparrow\n\n[LOVEFIS]\nLove Fist\n\n[COASTG]\nGarde-côte\n\n[DINGHY]\nDinghy\n\n[HERMES]\nHermes\n\n[SABRE]\nSabre\n\n[SABRETU]\nSabre Turbo\n\n[WALTON]\nWalton\n\n[REGINA]\nRegina\n\n[COMET]\nComet\n\n[DELUXO]\nDeluxo\n\n[BURRITO]\nBurrito\n\n[SPAND]\nSpandex Express\n\n[MARQUIS]\nMarquis\n\n[BAGGAGE]\nBagagiste\n\n[KAUFMAN]\nTaxi Kaufman\n\n[COASTMA]\nGarde-côte Maverick\n\n[MAVERIC]\nMaverick\n\n[RANCHER]\nRancher\n\n[FBIRANC]\nFBI Rancher\n\n[VIRGO]\nVirgo\n\n[GREENWO]\nGreenwood\n\n[HOTRING]\nHotring Racer\n\n[BLISTAC]\nBlista Compact\n\n[FEST_DF]\nDist. parcourue à pied (miles)\n\n[FEST_DC]\nDist. parcourue en voiture (miles)\n\n[FESTDFM]\nDistance parcourue à pied (m)\n\n[FESTDCM]\nDistance parcourue en voiture (m)\n\n[TOT_DIS]\nDistance totale parcourue (miles)\n\n[TOTDISM]\nDistance totale parcourue (m)\n\n[DISTHEL]\nDist. parcourue en hélicoptère (miles)\n\n[DISTHEM]\nDist. parcourue en hélicoptère (m)\n\n[DISTBOA]\nDist. parcourue en bateau (miles)\n\n[DISTBOM]\nDist. parcourue en bateau (m)\n\n[FEST_LS]\nPersonnes secourues en ambulance\n\n[FEST_CC]\nCriminels tués lors de la mission d'autodéfense\n\n[FEST_FE]\nNombre total de feux éteints\n\n[FEST_RP]\nRodéos réussis\n\n[FEST_MP]\nMissions réussies\n\n[FEST_BB]\nLes fous du volant :\n\n[FEST_H0]\nNombre maximum de points de passage\n\n[FEST_GC]\nNombre total de voitures de gang :\n\n[FEST_H1]\nDestruction de diablo\n\n[FEST_H2]\nMassacre de la Mafia\n\n[FEST_H3]\nLe désastre du casino\n\n[FEST_H4]\nLe destructeur de Rumpo\n\n[USJ]\nBONUS POUR CASCADE UNIQUE!\n\n[RATNG1]\nCitoyen honnête\n\n[RATNG2]\nQuidam\n\n[RATNG3]\nEboueur\n\n[RATNG4]\nVoleur à l'étalage\n\n[RATNG5]\nVandale\n\n[RATNG6]\nEscroc\n\n[RATNG7]\nPickpocket\n\n[RATNG8]\nCleptomane\n\n[RATNG9]\nMouchard\n\n[RATNG10]\nRat\n\n[RATNG11]\nSangsue\n\n[RATNG12]\nLe roi de l'arnaque\n\n[RATNG13]\nAigrefin\n\n[RATNG14]\nGrippe-sou\n\n[RATNG15]\nCrapule\n\n[RATNG16]\nRascal\n\n[RATNG17]\nRacaille\n\n[RATNG18]\nGarnement\n\n[RATNG19]\nVaurien\n\n[RATNG20]\nHors-la-loi\n\n[RATNG21]\nVoyou\n\n[RATNG22]\nLâche\n\n[RATNG23]\nIdiot SA\n\n[RATNG24]\nIdiot\n\n[RATNG25]\nRécidiviste\n\n[RATNG26]\nAncien taulard\n\n[RATNG27]\nCriminel\n\n[RATNG28]\nClochard\n\n[RATNG29]\nSage\n\n[RATNG30]\nPilote\n\n[RATNG31]\nGros bras\n\n[RATNG32]\nTueur à gages\n\n[RATNG33]\nChasseur de tête\n\n[RATNG34]\nForce de l'ordre\n\n[RATNG35]\nRonin\n\n[RATNG36]\nMagouilleur\n\n[RATNG37]\nTueur\n\n[RATNG38]\nAssocié\n\n[RATNG39]\nBoucher\n\n[RATNG40]\nNettoyeur\n\n[RATNG41]\nAssassin\n\n[RATNG42]\nConseiller\n\n[RATNG43]\nAutodidacte\n\n[RATNG44]\nBras droit\n\n[RATNG45]\nExécutant\n\n[RATNG46]\nLieutenant\n\n[RATNG47]\nSous-chef\n\n[RATNG48]\nCapo\n\n[RATNG49]\nPatron\n\n[RATNG50]\nNoops\n\n[RATNG51]\nDon\n\n[RATNG52]\nRoi de la putain de ville\n\n[PAGE_00]\n.\n\n[WELCOME]\nBIENVENUE A\n\n[TSCORE]\nREVENUS : ~1~$\n\n[PBOAT_2] { reVC update }\nAppuie sur la ~h~~k~~VEHICLE_FIREWEAPON~~w~ pour tirer avec les canons du bateau.\n\n[HJSTAT]\nDistance : ~1~.~1~ m Hauteur : ~1~.~1~ m Saltos : ~1~ Rotation : ~1~_\n\n[HJSTATW]\nDistance : ~1~.~1~ m Hauteur : ~1~.~1~ m Saltos : ~1~ Rotation : ~1~_ Et quelle belle réception!\n\n[ATUTOR]\nAppuie sur la ~h~~k~~TOGGLE_SUBMISSIONS~~w~ pour activer ou désactiver les missions ambulance.\n\n[FEST_HA]\nMission ambulance, niveau maximum\n\n[C_KILLS]\nCRIMINELS TUES : ~1~\n\n[HJSTATF]\nDistance : ~1~ ft Hauteur : ~1~ ft Saltos : ~1~ Rotation : ~1~_\n\n[HJSTAWF]\nDistance : ~1~ ft Hauteur : ~1~ ft Saltos : ~1~ Rotation : ~1~_ Et quelle belle réception!\n\n[CRED001]\nROCKSTAR NORTH\n\n[CRD001A]\nDIRECTEUR DU STUDIO\n\n[CRD001B]\nANDREW SEMPLE\n\n[CRED002]\nPRODUCTEUR\n\n[CRD002A]\nDIRECTEUR DU DEVELOPPEMENT\n\n[CRED003]\nLESLIE BENZIES\n\n[CRED004]\nCONCEPTEUR GRAPHIQUE\n\n[CRED005]\nAARON GARBUT\n\n[CRED006]\nDIRECTEURS TECHNIQUES\n\n[CRED007]\nOBBE VERMEIJ\n\n[CRED008]\nADAM FOWLER\n\n[CRED010]\nANDREW DUTHIE\n\n[CRED011]\nCRAIG FILSHIE\n\n[CRED012]\nWILLIAM MILLS\n\n[CRED013]\nCHRIS ROTHWELL\n\n[CRD013A]\nIMRAN SARWAR\n\n[CRD013B]\nJAMES WORRALL\n\n[CRD013C]\nJOHN HAIME\n\n[CRED014]\nECRIT PAR\n\n[CRED015]\nJAMES WORRALL\n\n[CRED016]\nPAUL KUROWSKI\n\n[CRED017]\nDAN HOUSER\n\n[CRED018]\nCONCEPTEUR PRINCIPAL DES PERSONNAGES\n\n[CRD018A]\nCONCEPTEUR DES PERSONNAGES\n\n[CRED019]\nIAN MCQUE\n\n[CRD019A]\nTOKS SOLARIN\n\n[CRD019B]\nALAN DAVIDSON\n\n[CRED020]\nANIMATEUR PRINCIPAL\n\n[CRED021]\nALEX HORTON\n\n[CRD022A]\nANIMATEURS\n\n[CRED022]\nLEE MONTGOMERY\n\n[CRD022B]\nDUNCAN SHIELDS\n\n[CRD022C]\nGUS BRAID\n\n[CRED023]\nCONCEPTEURS DES VEHICULES\n\n[CRD023A]\nJOLYON ORME\n\n[CRD023B]\nALAN DUNCAN\n\n[CRD024A]\nCONCEPTEUR PRINCIPAL DES VEHICULES\n\n[CRED024]\nPAUL KUROWSKI\n\n[CRED025]\nCONCEPTEURS DE CARTE\n\n[CRED026]\nADAM COCHRANE\n\n[CRED027]\nNIK TAYLOR\n\n[CRED028]\nGARY MCADAM\n\n[CRED029]\nKEIRAN BAILLIE\n\n[CRED030]\nALISDAIR WOOD\n\n[CRED031]\nANDREW SOOSAY\n\n[CRD031A]\nSTEVEN MULHOLLAND\n\n[CRD031B]\nWAYLAND STANDING\n\n[CRD031C]\nCAMPBELL J. DICK\n\n[CRD031D]\nCONCEPTEUR GRAPHIQUE\n\n[CRD031E]\nSTUART PETRI\n\n[CRED032]\nPROGRAMMEUR PRINCIPAL\n\n[CRD032A]\nPROGRAMMEURS\n\n[CRED033]\nALEXANDER ROGER\n\n[CRED034]\nGRAEME WILLIAMSON\n\n[CRED035]\nBARANE CHAN\n\n[CRED036]\nDEREK PAYNE\n\n[CRED037]\nGORDON YEOMAN\n\n[CRD037A]\nALAN CAMPBELL\n\n[CRD037B]\nMARK HANLON\n\n[CRD037C]\nANDRZEJ MADAJCZYK\n\n[CRED038]\nPRODUCTEUR MUSIQUE PRINCIPAL\n\n[CRED039]\nCRAIG CONNER\n\n[CRED040]\nSTUART ROSS\n\n[CRED041]\nINGENIEUR AUDIO PRINCIPAL\n\n[CRED042]\nALLAN WALKER\n\n[CRD041A]\nINGENIEUR DU SON\n\n[CRD041B]\nAUDIO\n\n[CRD042A]\nWILL MORTON\n\n[CRED043]\nPROGRAMMEUR AUDIO\n\n[CRED044]\nRAYMOND USHER\n\n[CRED045]\nRESPONSABLE DES TESTS\n\n[CRED046]\nCRAIG ARBUTHNOTT\n\n[CRED047]\nRESPONSABLE CQ\n\n[CRED048]\nNEIL CORBETT\n\n[CRED049]\nKEVIN WONG\n\n[CRED050]\nCQ\n\n[CRED051]\nDAVID BEDDOES\n\n[CRED052]\nDAVID WATSON\n\n[CRED053]\nBARRY CLARK\n\n[CRED054]\nROSS SPARROW\n\n[CRED055]\nJAMES ALLAN\n\n[CRED056]\nNEIL MEIKLE\n\n[CRD056A]\nGEORGE WILLIAMSON\n\n[CRD056B]\nMATT JONES\n\n[CRD056C]\nROB HARBOUR\n\n[CRD056D]\nTOM WHITTAKER\n\n[CRED057]\nASSISTANCE TECHNIQUE PRINCIPALE\n\n[CRED058]\nLORRAINE ROY\n\n[CRD057A]\nASSISTANCE TECHNIQUE\n\n[CRED059]\nCHRISTINE CHALMERS\n\n[CRD060A]\nSERVICES GENERAUX\n\n[CRD060B]\nKIM GURNEY\n\n[CRD060C]\nCASSIE OLIVER\n\n[CRED060]\nROCKSTAR NEW YORK\n\n[CRED061]\nPRODUCTEUR EXECUTIF\n\n[CRED062]\nSAM HOUSER\n\n[CRED063]\nPRODUCTEUR\n\n[CRED064]\nDAN HOUSER\n\n[CRED065]\nVICE-PRESIDENT DU DEVELOPPEMENT\n\n[CRED066]\nJAMIE KING\n\n[CRED067]\nRESPONSABLE TECHNOLOGIE\n\n[CRED068]\nGARY J. FOREMAN\n\n[CRED069]\nPRODUCTEUR ASSOCIE\n\n[CRED070]\nJEREMY POPE\n\n[CRD071A]\nRESPONSABLE CONTROLE QUALITE\n\n[CRD072A]\nJEFF ROSA\n\n[CRED071]\nRESPONSABLE MUSIQUE\n\n[CRED072]\nTERRY DONOVAN\n\n[CRED073]\nEQUIPE DE PRODUCTION\n\n[CRED074]\nTERRY DONOVAN\n\n[CRED075]\nJENNIFER KOLBE\n\n[CRED076]\nJENEFER GROSS\n\n[CRED077]\nLAURA PATERSON\n\n[CRED078]\nJEFF CASTANEDA\n\n[CRED079]\nJERONIMO BARRERA\n\n[CRED080]\nCARLY SLATER\n\n[CRED081]\nJUNG KWAK\n\n[CRED082]\nBRIAN WOOD\n\n[CRED083]\nRENAUD SEBANNE\n\n[CRED084]\nRICHARD KRUGER\n\n[CRD084A]\nDANIEL EINZIG\n\n[CRD084B]\nJACEN BURROWS\n\n[CRD084C]\nLINN PR\n\n[CRD084D]\nCOUVERTURE\n\n[CRD084E]\nSTEPHEN BLISS\n\n[CRED085]\nKENT PAUL'S 80 NOSTALGIA ZONE\n\n[CRED086]\nECRIT PAR DAN HOUSER\n\n[CRD086A]\nPRODUIT PAR ADAM TEDMAN\n\n[CRED087]\nWWW.KENTPAUL.COM ET WWW.VICECITY.COM\n\n[CRED088]\nCREES PAR\n\n[CRD088A]\nADAM TEDMAN\n\n[CRD088B]\nDAVID YU\n\n[CRD088C]\nJERRY LUNA\n\n[CRD088D]\nSTUART PETRI\n\n[CRD088E]\nMICHAEL CARNEVALE\n\n[CRD088F]\nGREG LAU\n\n[CRD088G]\nFUTABA HAYASHI\n\n[CRED089]\nRESPONSABLE CQ\n\n[CRED090]\nCRAIG ARBUTHNOTT\n\n[CRED091]\nANALYSTE PRINCIPAL\n\n[CRED092]\nADAM DAVIDSON\n\n[CRD092A]\nJOE HOWELL\n\n[CRD092B]\nMARC FERNANDEZ\n\n[CRED093]\nANALYSTE DE JEU\n\n[CRED094]\nRICHARD HUIE\n\n[CRED095]\nEQUIPE DE TEST CHEZ ROCKSTAR\n\n[CRED096]\nLANCE WILLIAMS\n\n[CRED097]\nJOE GREENE\n\n[CRED098]\nBRIAN PLANER\n\n[CRD098A]\nELIZABETH SATTERWHITE\n\n[CRD098B]\nJAMEEL VEGA\n\n[CRD098C]\nMIKE HONG\n\n[CRED099]\nLEE CUMMINGS\n\n[CRED100]\nHISTOIRE\n\n[CRED101]\nJAMES WORRALL\n\n[CRED102]\nDAN HOUSER\n\n[CRED103]\nADAM TEDMAN\n\n[CRED104]\nPAUL YEATES\n\n[CRED105]\nJENEFER GROSS\n\n[CRED106]\nLAURA PATERSON\n\n[CRED107]\nCINEMATIQUES\n\n[CRED108]\nECRITES PAR DAN HOUSER ET JAMES WORRALL\n\n[CRED109]\nDIRECTION DE L'AUDIO PAR DAN HOUSER ET NAVID KHONSARI\n\n[CRED110]\nPRODUCTION DE JAMIE KING\n\n[CRD110A]\nCASTING : JAMIE KING, SEAN MACALUSO\n\n[CRED111]\nDISTRIBUTION\n\n[CRD111A]\nPERSONNAGES SECONDAIRES\n\n[CRED112]\nTOMMY VERCETTI : RAY LIOTTA\n\n[CRED113]\nKEN ROSENBERG : WILLIAN FICHTNER\n\n[CRED114]\nSONNY FORELLI : TOM SIZEMORE\n\n[CRED115]\nSTEVE SCOTT : DENNIS HOPPER\n\n[CRED116]\nAVERY CARRINGTON : BURT REYNOLDS\n\n[CRED117]\nRICARDO DIAZ : LUIS GUZMAN\n\n[CRED118]\nLANCE VANCE : PHILIP MICHAEL THOMAS\n\n[CRED119]\nCOLONEL JUAN CORTEZ : ROBERT DAVI\n\n[CRED120]\nUMBERTO ROBINA : DANNY TREJO\n\n[CRED121]\nPHIL CASSIDY : GARY BUSEY\n\n[CRED122]\nMITCH BAKER : LEE MAJORS\n\n[CRED123]\nMERCEDES CORTEZ : FAIRUZA BALK\n\n[CRED124]\nKENT PAUL : DANNY DYER\n\n[CRED125]\nJEZZ TORRENT : KEVIN MCKIDD\n\n[CRED126]\nREGULATRICE TAXI : DEBORAH HARRY\n\n[CRED127]\nCANDY SUXX : JENNA JAMESON\n\n[CRED128]\nBJ SMITH : LAWRENCE TAYLOR\n\n[CRED129]\nTATA POULET : YOUREE CLEOMILI HARRIS\n\n[CRED130]\nFOURNISSEUR : ARMANDO RIESCO\n\n[CRED131]\nCOUGAR : BLAYNE PERRY\n\n[CRED132]\nHILARY : CHARLES TUCKER\n\n[CRED133]\nALEX SHRUB, REPRESENTANT DU CONGRES : CHRIS LUCAS\n\n[CRED134]\nLE VIEUX KELLY : GEORGE DICENZO\n\n[CRD134A]\nCAM JONES : GREG SIMS\n\n[CRD134B]\nPSYCHOPATHE : HUNTER PLATIN\n\n[CRD134C]\nMAUDE, LA VENDEUSE DE GLACES : JANE GENNARO\n\n[CRD134D]\nJETHRO : JOHN ZURHELLEN\n\n[CRD134E]\nGONZALES : JORGE PUPO\n\n[CRD134F]\nDWAYNE : NAVID KHONSARI\n\n[CRD134G]\nDICK : PETER MCKAY\n\n[CRD134H]\nMIKE, L'ACTEUR DE PORNO : ROBERT CIHRA\n\n[CRD134I]\nPERCY : RUSSELL FOREMAN\n\n[CRED135]\nCAPTURE DE MOUVEMENTS\n\n[CRED136]\nANIME PAR\n\n[CRD136A]\nDIRECTION TECHNIQUE PAR ALEX HORTON\n\n[CRED137]\nDIRIGE PAR\n\n[CRD137A]\nDIRIGE PAR NAVID KHONSARI\n\n[CRED138]\nPRODUIT PAR\n\n[CRD138A]\nPRODUIT PAR JAMIE KING\n\n[CRD138B]\nRENAUD SEBBANE\n\n[CRED139]\nENREGISTRE AUX PERSPECTIVE STUDIOS, BROOKLYN\n\n[CRED140]\nACTEURS POUR LA CAPTURE DE MOUVEMENTS\n\n[CRD140A]\nBLAYNE PERRY\n\n[CRD140B]\nJONATHON SALE\n\n[CRD140C]\nCHARLES TUCKER\n\n[CRD140D]\nEDDIE MARRERO\n\n[CRD140E]\nWILLIAM MCCALL\n\n[CRD140F]\nJORGE PUPO\n\n[CRD140G]\nROBERT JACKSON\n\n[CRD140H]\nTARA RADCLIFFE\n\n[CRD140I]\nJENIFER GAMBETESE\n\n[CRD140J]\nKRIS ACHEVARRIA\n\n[CRD140K]\nALI ORDOUBADI\n\n[CRD140L]\nKAHLEEM POOLE\n\n[CRED141]\nDIALOGUES DES PIETONS\n\n[CRD141A]\nECRIT PAR DAN HOUSER, MARC FERNANDEZ, GILLIAN TELLING ET NAVID KHONSARI\n\n[CRD141B]\nAVEC L'AIDE DE JEREMY POPE, LANCE WILLIAMS ET JENNY JEMISON\n\n[CRED142]\nECRITS PAR\n\n[CRD142A]\nDAN HOUSER ET JAMES WORRALL\n\n[CRED143]\nDIRIGE PAR DAN HOUSER, CRAIG CONNER, MARC FERNANDEZ ET ALLAN WALKER\n\n[CRED144]\nPRODUITS PAR RENAUD SEBANNE\n\n[CRED145]\nPIETONS\n\n[CRED146]\nADAM DAVIDSON, ADAM WATKINS, ALEJANDRO K. BROWN, ALEX ANTHONY SIOUKAS, ALEX GARCIA,\n\n[CRED147]\nALICE SALTZMAN, ALISON CIHRA, AMY SALIMA, AMY SALZMAN, ANDREA VIDELA, ANTHONY ATTI,\n\n[CRED148]\nANTHONY RIVERA, BIJAN SHAMS, BLAYNE PERRY, BRETT BISOGNO, BREYE MATA, BRIAN PANEN,\n\n[CRED149]\nBROCK VODER, CAREY BERTINI, CHARISSE LAMBERT, CHRIS DIFAT, CHRIS REISENBERGER,\n\n[CRED150]\nCHRISTOPHER BRODAY, CHRISTOPHER CARRO, CYNTHIA GREENE, DAMARIES LOPEZ, DAN LEE,\n\n[CRED151]\nDAN SCHNEIDER, DAN TOYAMA, DAVID DEAN CHALTFIELD, JR., DAVID HARRISON, DAVID WILEY,\n\n[CRED152]\nDEBORAH COLLINS, DEBRANDA CHANEY-GILES, DEMETRA KOUKOULAS, DENISE ROSADO,\n\n[CRED153]\nDEVIN BENNETT, DEVIN WINTERBOTTOM, DORIS WOO, DOUGLAS HARRISON, DUNCAN COUTTS,\n\n[CRED154]\nDUPE AJAYI, EDWIN AVELLANEDA, ELIZABETH HOWELL, ELIZABETH SATTERWHITE, ERIC NAGLE,\n\n[CRED155]\nESTEBAN KARPLUS, F. FONT, FUTABA HAYASHI, GENE HILGREEN, GERALD COSGROVE,\n\n[CRED156]\nGERARD LUNA, GILLIAN TELLING, GREGG CARLUCCI, GREGORY CLERVOIX, GREGORY SCHWEIZER,\n\n[CRED157]\nHADLEY TOMICKI, J. ROSSETT, JAMEEL VEGA, JASON JONES, JEFF ROSA, JENNIFER JEMISON,\n\n[CRED158]\nJEREMY TAGGERT, JESSICA RIDER, JOSEPH GREENE,JOSEPH HOWELL, KATE DUKICH,\n\n[CRED159]\nKEL O'NEILL, KEVIN HOPKINS, LADAWN JAMES, LANCE WILLIAMS, LAURA BUBBLES,\n\n[CRED160]\nLAURA PATTERSON, LEE CUMMINGS, LETICIA L. YOUNG, LINDSAY KENNEDY, LISA ORITZ,\n\n[CRED161]\nLORNA JORDAN, LUCIO AMADIO, MARCO FERNANDEZ, MARIKO TANAKA, MARLON MATTHEWS,\n\n[CRED162]\nMARY TELLING, MASAYOSHI MITSUYAMA, MATTHEW CHUNG, MAX ALLSTADT, MAX BOGDANOV,\n\n[CRED163]\nMELISSA ALVAREZ, MICHAEL MAY, MICHAEL ROTHSTEIN, MIGUEL VIDAL, MIKE FEDERLINE,\n\n[CRED164]\nNATALIE DESCALZO, N'GAI MEMBERS, NICOLAS MALLO, NOELLE SADLER, NORBERT MORIVAN,\n\n[CRED165]\nOSWALD GREENE, JR., PETER MCKAY, PETER APPEL, PRESTON SAVARESE, RAFAEL GONZALES,\n\n[CRED166]\nRANDY JOHNSON, REY CONCEPCION, RICHARD KROGER, ROB TIBBS, ROBERT JACKSON,\n\n[CRED167]\nROBERT SCHULER, ROSS A. MCINTYRE, RUSSELL FOREMAN, RUTH NUNEZ, SALVADORE SUAZO,\n\n[CRED168]\nSAM WHITE, SANTOS GONZALES, SCOTT SMITH, SEYMOUR FRAILMAN, SPELMAN BRAUMAN,\n\n[CRED169]\nSTEPHANIE TELLING, STEVE KNEZEVICH, STEVE ROBERT, SUMIKO YASUDA, SUSAN LEWIS,\n\n[CRED170]\nSYLVIA COLACIOS, TOMOKO MIYAZAKI, TRON, VERDEL HALE, YVES MONDESIR, ZENO LEINFELDER,\n\n[CRED171]\nDAVID BEDDOES, CHRISTINE CHALMERS, BARRY CLARK, NEIL CORBETT, KIM GURNEY, NEIL MEIKLE,\n\n[CRED172]\nCASSIE OLIVER, LORRAINE ROY, DAVID WATSON, KEVIN WONG, WILL MORTON\n\n[CRED175]\nADAM DAVIDSON\n\n[CRED176]\nLANCE WILLIAMS\n\n[CRED177]\nNEIL MCCAFFREY\n\n[CRED178]\nLAURA PATERSON\n\n[CRED179]\nREY CONCEPCION\n\n[CRED180]\nCHARLES HEROLD\n\n[CRED181]\nANDREW GREENWALD\n\n[CRED182]\nJAMES MIELKE\n\n[CRED183]\nPETER SUCIU\n\n[CRED184]\nALEX ODULIO\n\n[CRED185]\nDON NKRUMAH\n\n[CRED186]\nKENDALL PITTMAN\n\n[CRED187]\nSAL SUAZO\n\n[CRED188]\nEREK MATEO\n\n[CRED189]\nCHRIS DIFATE\n\n[CRED190]\nLEILA MILTON\n\n[CRED191]\nDARREN ZOLTOWSKI\n\n[CRED192]\nVIRGINIA SMITH\n\n[CRED193]\nKEVIN CASSIN\n\n[CRED194]\nJASON SHIGEMORI\n\n[CRED195]\nKELLY KINSELLA\n\n[CRED196]\nMOLLIE STICKNEY\n\n[CRED197]\nSTANTON SARJEANT\n\n[CRED198]\nLAURA WALSH\n\n[CRED199]\nMARK GARONE\n\n[CRED200]\nJOANNA SLY\n\n[CRED201]\nELIZABETH HOWELL\n\n[CRED202]\nANA HERCULES\n\n[CRED203]\nSHIRLEY IRICK\n\n[CRED204]\nKASHONA FIELDS\n\n[CRED205]\nJOEL M. LILJE\n\n[CRED206]\nJOHN DIBENEDETTO\n\n[CRED207]\nNANCY GILES\n\n[CRED208]\nRYAN CROY\n\n[CRED209]\nJENNIFER KOLBE\n\n[CRED210]\nLIAM BURKE\n\n[CRED211]\nSIGRID PREISSL\n\n[CRED212]\nANITA FITZSIMONS\n\n[CRED213]\nPHILIPPA RASELLI\n\n[CRED214]\nWIL QUESNEL\n\n[CRED215]\nFALKO BURKERT\n\n[CRED216]\nSARA SEWELL\n\n[CRED217]\nSTATIONS DE RADIO ET MUSIQUE\n\n[CRED218]\nCONSULTANT EN MUSIQUE\n\n[CRD218A]\nHEINZ HENN\n\n[CRD218B]\nSTUART ROSS\n\n[CRED219]\nCOORDINATEUR DE LA BANDE-SON\n\n[CRED220]\nTERRY DONOVAN\n\n[CRED221]\nPRODUCTEUR CHEZ ROCKSTAR GAMES\n\n[CRED222]\nDAN HOUSER ET LAZLOW\n\n[CRED223]\nPRODUCTEUR CHEZ ROCKSTAR NORTH\n\n[CRED224]\nCRAIG CONNER\n\n[CRED225]\nALLAN WALKER\n\n[CRED226]\nLAZLOW\n\n[CRED227]\nDJ BANTER ET IMAGING\n\n[CRED228]\nECRIT PAR DAN HOUSER ET LAZLOW\n\n[CRED229]\nFLASH FM\n\n[CRD229A]\nTONI-MARIA CHAMBERS\n\n[CRD229B]\nVOIX ET PRODUCTION : JEFF BERLIN\n\n[CRED230]\nREMERCIEMENTS SPECIAUX A\n\n[CRED231]\nTOMMY MOTTOLA,\n\n[CRED232]\nMICHELLE ANTHONY,\n\n[CRED233]\nSTEVE BARNETT,\n\n[CRED234]\nCHUCK FLECKENSTEIN,\n\n[CRED235]\nRITA LIBERATOR\n\n[CRED236]\nMARTIN ET CLAIRE LOGAN\n\n[CRED237]\nSANDRA HUTTON\n\n[CRED238]\nCHRISTINE DAVIDSON\n\n[CRED239]\nALAN, RED ET BIGFOOT\n\n[CRED240]\nLE T\n\n[CRED241]\nCOLIN DONALD\n\n[CRED242]\nKERRY STALLWOOD\n\n[CRED243]\nALAN MCGREGOR\n\n[CRED244]\nCHRIS MORTON\n\n[CRED245]\nEMIL BUSSE\n\n[CRED246]\nEMILY BAILLIE\n\n[CRED247]\nKEVIN ARCHIBALD\n\n[CRED248]\nMORAG KERR\n\n[CRED249]\nCATH WALKER\n\n[CRED250]\nISO BAR\n\n[CRED251]\nWATERLINE\n\n[CRED252]\nNEWS CAFE\n\n[CRD251A]\nTHE POND\n\n[CRD252A]\nPIVO\n\n[CRED253]\nBUDGET VIDEO RENTALS\n\n[CRED254]\nLORNA'S SCOOTER\n\n[CRED255]\nGARETH MURFIN\n\n[CRED256]\nGRAPHISMES ADDITIONNELS\n\n[CRED257]\nTONY PORTER\n\n[CRED258]\nCRAIG MOORE\n\n[CRED259]\nANIMATION SYNCHRO LABIALE DES CINEMATIQUES\n\n[CRED260]\nCOSGROVE HALL FILMS\n\n[CRED261]\nPRODUCTEUR : OWEN BALLHATCHET\n\n[CRED262]\nANIMATEUR SENIOR : JON TURNER\n\n[CRED263]\nANIMATEURS : RICHARD DRUMM\n\n[CRED264]\nDAVE BROWN\n\n[CRED265]\nMAIR THOMAS\n\n[CRED266]\nPRASHANT PATEL\n\n[CRED267]\nCONSULTANT TECHNOLOGIE AUDIO\n\n[CRED268]\nRIK EDE POUR GAMESOUND LTD.\n\n[CRED269]\nASSISTANCE INTEGRATION DTS\n\n[CRED270]\nTED LAVERTY POUR DTS\n\n[CRED271]\nCHRIS GREER POUR DTS\n\n[CRED272]\nJASON PAGE POUR SCEE\n\n[CRED273]\nRECHERCHE ET ANALYSE\n\n[CRED274]\nVROCK\n\n[CRED275]\nDJ : LAZLOW\n\n[CRED276]\nVOIX : JOE KELLY\n\n[CRED277]\nPRODUCTION : JONATHAN HANST\n\n[CRED278]\nONDE 103\n\n[CRED279]\nDJ : ADAM FIRST-JAMIE CANFIELD\n\n[CRED280]\nVOIX : JEN SWEENLEY\n\n[CRED281]\nPRODUCTION : JONATHAN HANST\n\n[CRED282]\nFEVER 105\n\n[CRED283]\nDJ : OLIVER 'LADYKILLER' BISCUIT-JULIUS DYSON\n\n[CRED284]\nVOIX D'HOMME : ED McMANN\n\n[CRED285]\nVOIX DE FEMME : SHWNEE SMITH\n\n[CRED286]\nPRODUCTION : LISTEN KISTEN\n\n[CRED287]\nEMOTION 98.3\n\n[CRED288]\nDJ : FERNANDO- FRANK CHAVEZ\n\n[CRED289]\nVOIX : JEN SWEENLEY\n\n[CRED290]\nPRODUCTION : JONATHAN HANST\n\n[CRED291]\nRADIO ESPANTOSO\n\n[CRED292]\nDJ : PEPE-TONY CHILRODES\n\n[CRED293]\nWILDSTYLE\n\n[CRED294]\nDJ : MISTER MAGIC\n\n[CRED295]\nVOIX : FRANK SILVESTRO\n\n[CRED296]\nPRODUCTION : LAZLOW\n\n[CRED297]\nKCHAT\n\n[CRED298]\nECRIT PAR DAN HOUSER ET LAZLOW\n\n[CRED299]\nPRODUIT ET EDITE PAR LAZLOW\n\n[CRED300]\nDJ AMY SHECKENHAUSEN : LEYNA WEBER\n\n[CRED301]\nJEZ TORRENT : KEVIN MCKIDD\n\n[CRED302]\nMANDY : COLLEEN CORBETT\n\n[CRED303]\nMICHELLE CARAPADIS : MARY BIRDSONG\n\n[CRED304]\nMR.ZOO : CARL DOWLING\n\n[CRED305]\nGETHSEMANEE : LYNN LIPTON\n\n[CRED306]\nCLAUDE MAGINOT : JOHN MAUCERI\n\n[CRED307]\nBJ SMITH : LAWRENCE TAYLOR\n\n[CRED308]\nTHOR : FRANK FAVA\n\n[CRED309]\nINTERLOCUTEURS\n\n[CRED310]\nCOUZIN ED, JOSH CLARK, JASON BUHRMESTER, JUAN ALLER, WAYNE OLIVER, SUSAN LEWIS, GILLIAN TELLING, TOM MURRAY, MIKE FERRANTE SR., EMMANUEL GOLDSTEIN, DAN HOUSER, NICK MANDELOS, GERRY COSGROVE, MIKE PALERMO, PORKCHOP, KEITH BROADAS\n\n[CRED311]\nLEWIS, GILLIAN TELLING, TOM MURRAY, MIKE FERRANTE SR., EMMANUEL GOLDSTEIN,\n\n[CRED312]\nDAN HOUSER, NICK MANDELOS, GERRY COSGROVE, MIKE PALERMO, PORKCHOP,\n\n[CRED313]\nKEITH BROADAS\n\n[CRED314]\nVCPR\n\n[CRED315]\nECRIT PAR DAN HOUSER ET LAZLOW\n\n[CRED316]\nPRODUIT PAR LAZLOW\n\n[CRED317]\nMAURICE CHAVEZ : PHILLIP ANTHONY RODRIGUEZ\n\n[CRED318]\nJONATHAN FREELOADER : PATRICK OLSEN\n\n[CRED319]\nMICHELLE MONTANIUS : KELLY GUEST\n\n[CRED320]\nALEX SHRUB : CHRIS LUCAS\n\n[CRED321]\nCALLUM CRAYSHAW : SEAN MODICA\n\n[CRED322]\nJOHN F. HICKORY : LJ GANSEN\n\n[CRED323]\nLE PASTEUR RICHARDS : DAVID GREEN\n\n[CRED324]\nJAN BROWN : MAUREEN SILLIMAN\n\n[CRED325]\nBARRY STARK : RENAUD SEBBANE\n\n[CRED326]\nJENNY LOUISE CRAB : MARY BIRDSONG\n\n[CRED327]\nKONSTANTINOS SMITH : KONSTANTINOS.COM\n\n[CRED328]\nJEREMY ROBARD : PETER SILVESTRO\n\n[CRED329]\nPUBLICITES RADIO\n\n[CRED330]\nECRITES PAR DAN HOUSER ET LAZLOW\n\n[CRED331]\nPRODUITES PAR LAZLOW\n\n[CRED332]\nJINGLES SUPPLEMENTAIRES PRODUITS PAR CRAIG CONNER\n\n[CRED333]\nVOIX DES PUBLICITES :\n\n[CRED334]\nADAM DAVIDSON, ALEX ANTHONY, ALICE SALTZMAN, AMY SALZMAN, KATE DUKICH,\n\n[CRED335]\nARAN RONICLE, BARB JONES, BEN KRECH, BRIAN THOMAS, BROCK YODER, CHRIS\n\n[CRED336]\nFERRANTE, CRAIG CONNER, DAVE RYAN, DAVID GREEN, DORIS WOO, DOUGLAS\n\n[CRED337]\nHARRISON, ED MCMANN, FRANK CHAVEZ, FRANK FAVA, GENE HILGREEN, GREG\n\n[CRED338]\nSCHWEIZER, HUNTER PLATIN, JAMES FERRANTE, JEFF BERLIN, JEFF ROSA, JOE KELLY,\n\n[CRED339]\nJOHN MAUCERI, JOSH CLARK, JULIE WEMYSS, KEVIN STRALEY, KIM GURNEY, LANCE\n\n[CRED340]\nWILLIAMS, LAURA PATERSON, LAZLOW, LISA ORTIZ, LORNA JORDAN, LUCIEN JONES,\n\n[CRED341]\nMAUREEN SILLIMAN, MIKE FERRANTE JR., PETE GUSTIN, PETER SILVESTRO, RAFF\n\n[CRED342]\nCROLLA, RANDY JOHNSON, RICHARD KRUGER, RON REEVE, SHELLEY MILLER, SKY, TJ ALLARD\n\n[CRD344A]\nENREGISTREMENTS AUX DIGITAL ARTS STUDIOS,\n\n[CRED344]\nNYC, TRACK 9 STUDIOS, NYC,\n\n[CRED345]\nWEDDINGTON MULTIMEDIA, LOS ANGELES,\n\n[CRD345A]\nSYNC SOUND, NYC ET RADIO LAZLOW, LONG ISLAND.\n\n[CRED346]\nMERCI A AXEL ERICSON ET WON LEE DE DIGITAL ARTS, PAUL VASQUEZ DETRACK 9 STUDIOS, JOHN BOWEN ET JOHN HASSLER DE SYNC SOUND.\n\n[CRED347]\nMARK LLOYD\n\n[CRED348]\nTIM BATES\n\n[CRED349]\nKIT BROWN\n\n[CRED350]\nANDY MASON\n\n[CRED351]\nPHIL DEANE\n\n[CRED352]\nPHIL ALEXANDER\n\n[CRED353]\nMATT HEWITT\n\n[CRED354]\nDENBY GRACE\n\n[CRED355]\nANTOINE CABROL\n\n[CRED356]\nJONATHAN STONES\n\n[CRED357]\nMIKE BLACKBURN\n\n[CRED358]\nTIM MCGAFF\n\n[CINCAM]\nCaméra cinématique\n\n[RC4]\n'RODEO DE RUMPO'\n\n[LEGAL]\n~g~Elimine toute menace criminelle!\n\n[GA_2]\nNouveau moteur et nouvelle peinture. Les flics ne te reconnaîtront plus!\n\n[HELP15]\nSi tu es à pied, appuie sur la ~h~~k~~PED_LOOKBEHIND~~w~ pour ~h~regarder derrière~w~. Utilise le ~h~joystick analogique droit~w~ pour ~h~regarder autour~w~ de toi.\n\n[FEC_LB4]\nRegarder derrière (touche R3)\n\n[PERPIC]\nPaquets cachés trouvés\n\n[CO_ONE]\nPaquet caché ~1~ sur ~1~\n\n[GA_21]\nImpossible de garer plus de véhicules dans ce garage.\n\n[CHEAT1]\nCodes activés\n\n[CHEAT2]\nCode d'arme\n\n[CHEAT3]\nCode de santé\n\n[CHEAT4]\nCode d'armure\n\n[CHEAT5]\nCode d'indice de recherche\n\n[CHEAT6]\nCode d'argent\n\n[CHEAT7]\nCode de météo\n\n[USJ_ALL]\nTOUTES LES CASCADES ONT ETE ACCOMPLIES!\n\n[JAN]\nJan\n\n[FEB]\nFév\n\n[MAR]\nMar\n\n[APR]\nAvr\n\n[MAY]\nMai\n\n[JUN]\nJun\n\n[JUL]\nJui\n\n[AUG]\nAoû\n\n[SEP]\nSept\n\n[OCT]\nOct\n\n[NOV]\nNov\n\n[DEC]\nDéc\n\n[DEFDT]\n--:---:---- --:--:--\n\n[BONUS]\n~g~BONUS $~1~\n\n[HORN1]\nAppuie sur la ~h~~k~~VEHICLE_HORN~ ~w~pour ~h~klaxonner.\n\n[HORN2]\nAppuie sur la ~h~~k~~VEHICLE_HORN~ ~w~pour ~h~klaxonner.\n\n[HORN3]\nAppuie sur la ~h~~k~~VEHICLE_HORN~ ~w~pour ~h~klaxonner.\n\n[FEC_EXV]\nMonter et descendre d'un véhicule\n\n[TAXI_M]\n'CHAUFFEUR DE TAXI'\n\n[COP_M]\n'AUTODEFENSE'\n\n[FIRE_M]\n'POMPIER'\n\n[AMBUL_M]\n'AMBULANCE'\n\n[HJ_IS]\nBONUS DE CASCADE DANGEREUSE : $~1~\n\n[HJ_PIS]\nBONUS DE CASCADE DANGEREUSE PARFAITE : $~1~\n\n[HJ_DIS]\nBONUS DE DOUBLE CASCADE DANGEREUSE : $~1~\n\n[HJ_PDIS]\nBONUS DE DOUBLE CASCADE DANGEREUSE PARFAITE : $~1~\n\n[HJ_TIS]\nBONUS DE TRIPLE CASCADE DANGEREUSE : $~1~\n\n[HJ_PTIS]\nBONUS DE TRIPLE CASCADE DANGEREUSE PARFAITE : $~1~\n\n[HJ_QIS]\nBONUS DE QUADRUPLE CASCADE DANGEREUSE : $~1~\n\n[HJ_PQIS]\nBONUS DE QUADRUPLE CASCADE DANGEREUSE PARFAITE : $~1~\n\n[FESZ_LS]\nChargement effectué.\n\n[HELI_1A]\nTeste tes capacités avec le Sparrow et vois en combien de temps tu peux réussir le parcours.\n\n[HELI_1B]\nParcours réussi!\n\n[HELIODD]\nPetits boulots en hélico\n\n[INT2_M]\nIls sont proprios d'une ferme au Panama!\n\n[INT2_N]\nOk, écoutez un peu...\n\n[INT2_O]\nLes gars, quand on sera là-bas, est-ce que je dois rester dans la bagnole,\n\n[INT2_P]\noù bien est-ce que vous voulez absolument que je vienne avec vous?\n\n[INT2_Q]\nNon, Reste dans la bagnole.\n\n[INT2_R]\nVous savez quoi, j'ai réfléchi à la question,\n\n[INT2_S]\nJe vais surveiller la bagnole.\n\n[INT4_A]\nOn est baisés! Baisés!\n\n[INT4_B]\nPutain, c'est vraiment le coup classique!\n\n[INT4_C]\nJe sors la tête d'un caniveau pour une seconde de défonce,\n\n[INT4_D]\net le destin me chie de la merde plein la gueule!\n\n[INT4_E]\nAllez vous faire mettre!\n\n[INT4_F]\nFerme-la et arrêter de gueuler! T'es encore vivant, pas vrai?\n\n[INT4_G]\nLaisse-moi là.\n\n[INT4_H]\nDébarrasse-toi de la caisse et va roupiller un bon coup.\n\n[INT4_I]\nJe passerai à ton bureau demain et on essayera de trouver une solution à ce merdier.\n\n[INT4_J]\nOuais, bonne idée, je vais aller roupiller.\n\n[INT4_K]\nQu'est-ce que tu vas faire?\n\n[INT4_L]\nRentrer à mon hôtel.\n\n[INT4_M]\nEt penser à autre chose que ces conneries.\n\n[INT4_N]\nOk.\n\n[LAW]\nMISSIONS AVOCAT\n\n[LAW1_1]\n~g~Va te procurer de nouvelles fringues à la boutique de Rafael.\n\n[LAW4_6]\nBrûlez la direction!\n\n[LAW4_7]\nTuez les patrons!\n\n[LAW4_8]\nAllez! Battez-vous! Allez!\n\n[LAW4_9]\nPlus de vacances! Moins de travail!\n\n[LAW4_11]\nAllez! Battez-vous! Allez!\n\n[LAW4_12]\nViva la revolucion!\n\n[GENERAL]\nMISSIONS DU COLONEL\n\n[GEN3_4]\nTommy Vercetti. Allons-y...\n\n[GEN3_13]\nC'est quoi ton problème, mec? Monte sur le toit de l'autre côté de la cour avant qu'ils rappliquent!\n\n[GEN3_17]\nMeeeerde! T'essayes de m'buter ou quoi?\n\n[GEN3_21]\n~g~Il a le pognon de Diaz! Attrape-le et récupère le fric!\n\n[GEN3_24]\n~r~Diaz est mort! Tu devais le protéger!\n\n[GEN3_26]\n~r~T'as flingué Diaz!\n\n[GEN3_27]\n~r~T'as descendu les gardes du corps de Diaz!\n\n[GEN3_31]\n~g~Va au rencart et veille sur Diaz.\n\n[GEN3_32]\n~g~Va te mettre en position sur le toit du bâtiment en face de Lance.\n\n[COKE]\nMISSIONS BARON DE LA COKE\n\n[COK1_3]\nJ'espère que tu vas te casser la gueule!\n\n[COK1_6]\nJ'en ai marre de ces merdeux.\n\n[COK2_7]\nTu vois ces marqueurs? Essaye de flinguer les lumières!\n\n[COK2_10]\nEn tout cas, tu tires mieux que tu causes.\n\n[COK2_11]\nMerci. T'as un certain charme aussi.\n\n[COK2_12]\nJe sais, Tommy.\n\n[COK2_18]\nT'aimes bien Kenny Loggins?\n\n[COK2_19]\nTu parles, j'adore ce disque ouais!\n\n[COK2_26]\n~r~T'as buté Lance!\n\n[COK3_1]\nTire pas, mec!\n\n[COK3_2]\nQu'est-ce que c'est que ça?\n\n[COK3_3]\nIl embarque le bateau! Merde!\n\n[COK3_4]\nA l'aide! Il y a un mec qui nous fauche le bateau!\n\n[COK4_W]\nBon! C'est le dernier.\n\n[COK4_X]\nJe vais mettre le moteur en route.\n\n[COK4_Y]\nJe crois qu'on a de la visite...\n\n[COK4_2]\nOuais.\n\n[COK4_6]\nTu sais où on va?\n\n[COK4_7]\nOn est paumés?\n\n[COK4_8]\nOn a de la concurrence!\n\n[COK4_9]\nBousille-les!\n\n[COK4_9A]\nL'heure de la danse de Lance Vance a sonné!\n\n[COK4_10]\nRéduits en miettes! Bons à nourrir la poiscaille!\n\n[COK4_11]\nOn a réussi! Les autres bateaux ne sont pas de taille.\n\n[COK4_17]\nIls sont prêts à tout!\n\n[COK4_18]\nJ'ai les pieds mouillés! On prend la flotte!\n\n[COK4_21]\nPont droit devant!\n\n[COK4_22]\nEcope, on va chavirer!\n\n[COK4_23]\nJoli coup.\n\n[COK4_29]\n~r~T'as buté Lance!\n\n[ASS1_6]\nContinue, Tommy, ça va aller!\n\n[ASS1_7]\nPrenez ça, enculés d'assassins!\n\n[ASS1_8]\nJe suis coincé!\n\n[ASS1_9]\nJe te couvre, Tommy!\n\n[ASS1_10]\nHé, c'est chouette toutes ces plantes...\n\n[ASS1_11]\nHé, Tommy, je peux avoir une chambre avec vue sur la baie?\n\n[ASS1_12]\nIl y a vraiment de superbes plafonds, ici...\n\n[ASS1_3]\nLance! Couvre-moi!\n\n[ASS1_5]\nLance!\n\n[ASS1_15]\n~g~Attaque la résidence et tue Diaz!\n\n[ASS1_17]\n~g~Il existe de nombreux accès à la résidence.\n\n[TAXWAR]\nMISSIONS GUERRE DES TAXIS\n\n[NOTAXI]\n~g~T'as besoin d'un taxi Kaufman pour activer cette mission.\n\n[TAXW1_5]\n~g~Faut que tu sois dans un taxi Kaufman!\n\n[TAX2_4]\nVas-y, Tommy.\n\n[TAX2_5]\nMassacre-lui la tête.\n\n[TAX2_6]\nIl a même pas son permis.\n\n[TAX2_7]\nPutain de limousines!\n\n[TAXW3_1]\n~g~Va prendre Mercedes.\n\n[RACE1]\n~g~3..2..1.. PARTEZ!\n\n[RACE2]\n~g~3\n\n[RACE3]\n~g~2\n\n[RACE4]\n~g~1\n\n[RACE5]\n~g~PARTEZ!\n\n[FIRST]\n~b~1er\n\n[SECOND]\n~b~2e\n\n[THIRD]\n~b~3e\n\n[FOURTH]\n~b~4e\n\n[RACETM]\n~b~TEMPS DE COURSE : ~1~:~1~\n\n[RACETM2]\n~b~TEMPS DE COURSE : ~1~:0~1~\n\n[RACEFA]\n~r~Tu n'as pas gagné la course!\n\n[TEX1_5]\n~r~Il s'est tiré!\n\n[SEG3_1]\nTEMPS:\n\n[SEG3_2]\n~g~Va à la camionnette qui contient le bombardier télécommandé et les bombes à retardement.\n\n[SEG3_3]\n~g~Utilise le bombardier télécommandé pour transporter 4 bombes vers 4 zones cibles sur le chantier.\n\n[SERG3_5]\n~g~Tu ne peux transporter qu'une bombe à la fois et tu ne peux récupérer une bombe déjà larguée avec succès.\n\n[SEG3_7]\n~g~Une fois que tu as largué la première bombe sur une zone cible, le compte à rebours s'enclenche. Tu dois larguer toutes les bombes avant la fin de celui-ci.\n\n[SEG3_8]\n~g~Les 4 bombes doivent être larguées sur les 4 zones cibles pour réussir la mission et détruire le bâtiment.\n\n[SEG3_9]\n~g~Tu as touché la cible! Plus que 3!\n\n[SEG3_10]\n~g~Tu as touché la cible! Plus que 2!\n\n[SEG3_11]\n~g~Tu as touché la cible! Plus qu'une!\n\n[SEG3_12]\n~r~Tu as raté la cible! Va récupérer une bombe!\n\n[SEG3_13]\n~g~Largue la bombe sur une zone cible.\n\n[SEG3_14]\n~r~Le temps est écoulé et tu n'as pu détruire le bâtiment.\n\n[SEG3_15]\n~r~Ton bombardier télécommandé a été détruit! Comment tu vas transporter les bombes, maintenant?\n\n[AVERY]\nMISSIONS AVERY\n\n[ASM]\nMISSIONS ASSASSIN\n\n[ASM_1]\nMISSION ASSASSIN 1\n\n[ASM1_1]\n~g~Ton aide dans l'éradication de ces indésirables fut une excellente affaire. J'ai un autre travail pour toi. Regarde sous le téléphone.\n\n[ASM1_2]\n~g~Rends-toi à la cabine en dehors du centre commercial à Washington.\n\n[ASM1_3]\n~g~Carl Pearson, livreur de pizzas. Il ne doit pas terminer sa tournée.\n\n[ASM1_4]\n~g~Tue le livreur de pizzas avant qu'il le livre toutes ses pizzas.\n\n[ASM_2]\nMISSION ASSASSIN 2\n\n[ASM_3]\nMISSION ASSASSIN 3\n\n[ASM3_A]\nMarcus Hammond, Franco Carter, Dick Tanner, Nick Kong et Stuntman Driver appartiennent tous au syndicat européen qui s'apprête à faire un hold-up.\n\n[ASM3_B]\nIls sont tous en position. Il faut qu'ils soient tous morts avant le commencement. Tu as 9 minutes. J'ai laissé quelques flingues à proximité qui devraient t'être utiles.\n\n[ASM3_1]\n~g~Va récupérer l'arme que M. Black a laissé pour toi.\n\n[ASM3_2]\n~g~Ne t'approche pas trop près de la cible ou tu risques d'être repéré.\n\n[ASM3_3]\n~g~Pour un travail propre et rapide, installe-toi près de leurs positions dans des emplacements d'où tu pourras facilement les liquider, sans être repéré.\n\n[ASM3_4]\n~g~Il t'a vu! Vaudrait mieux le buter en vitesse, maintenant!\n\n[ASM3_5]\n~g~Marcus Hammond est en position près des panneaux publicitaires dans Washington.\n\n[ASM3_6]\n~g~Franco Carter est en position à côté de DBP Security non loin d'Ocean Drive.\n\n[ASM3_7]\n~g~Dick Tanner est en position à côté de la bijouterie dans Vice Point.\n\n[ASM3_8]\n~g~Nick Kong est en position près de Washington Beach.\n\n[ASM3_9]\n~g~Stuntman Driver est en position à Washington.\n\n[ASM3_10]\n~r~Tu n'as pas réussi à tous les descendre.\n\n[ASM_4]\nMISSION ASSASSIN 4\n\n[ASM4_1]\n~g~Va récupérer le fusil laissé à ton intention dans le feuillage à l'extérieur du terminal de l'aéroport.\n\n[ASM4_2]\n~g~Ne rate pas la cible où tu alerteras ses gardes du corps et garde tes distances pour qu'il ne te repère pas.\n\n[ASM4_3]\n~g~Observe la femme sur le balcon au-dessus des comptoirs d'enregistrements du terminal. NE LA TUE PAS.\n\n[ASM4_4]\n~g~Tue l'homme à qui elle donnera la serviette, mais seulement quand il l'aura récupérée. Prends ensuite la serviette et amène-la à Ammu-Nation dans le centre.\n\n[ASM4_5]\n~g~Récupère la serviette!\n\n[ASM4_6]\n~g~Amène la serviette à Ammu-Nation dans le centre!\n\n[ASM4_7]\n~r~Imbécile! Tu as tué la femme!\n\n[ASM4_8]\n~r~La cible t'a entendu tirer! Le deal est annulé!\n\n[ASM4_9]\n~r~La cible a embarqué à bord de son avion!\n\n[ASM4_10]\n~r~On dirait que tu n'es pas le seul à t'intéresser à cette serviette! Amène-la en vitesse à Ammu-Nation!\n\n[ASM4_11]\n~r~La cible t'a repéré! Le deal est annulé!\n\n[ASM4_13]\n~g~Il t'a repéré et essaye de s'enfuir! Rattrape-le et récupère la serviette!\n\n[ASM4_14]\n~g~La barre de distance dans le coin supérieur droit de l'écran te signale ta proximité avec la cible. Ne la laisse pas devenir pleine ou il te repèrera.\n\n[ASM_5]\nMISSION ASSASSIN 5\n\n[KICK]\nDEMARRAGE AU PIED\n\n[KICK1_3]\n~g~Nombre de fautes de pied : ~1~\n\n[KICK1_4]\n~g~Pénalité de temps : ~1~ secondes\n\n[BANK]\nMISSIONS BRAQUAGE\n\n[BANK1]\nMISSION BRAQUAGE 1\n\n[BANK2]\nMISSION BRAQUAGE 2\n\n[BJM2_3]\nTAUX DE REUSSITE : ~1~%\n\n[BJM2_15]\nSCORE :\n\n[BJM2_18]\nSCORE A BATTRE :\n\n[BJM2_19]\n~g~Touche autant de cibles que possible dans le temps imparti!\n\n[BJM2_21]\n~g~Touche autant de cibles que possible jusqu'à épuisement de tes munitions.\n\n[BANK3]\nMISSION BRAQUAGE 3\n\n[BJM3_1]\n~g~Trouve une bagnole qui a des chevaux et rends-toi sur la grille de départ.\n\n[BNK4_2A]\nLes gars au garage ont fait du super boulot sur ce bébé.\n\n[BNK4_3G]\nOh, merde, maintenant, on a les flics au cul!\n\n[BNK4_3H]\nEt on n'est même pas encore sur place...\n\n[BNK4_3K]\nVa d'abord falloir semer les flics...\n\n[BNK4_3L]\nMerde, Tommy, t'essayes de tous nous tuer?\n\n[BNK4_3N]\nTout ce que j'aime part en fumée!\n\n[BNK422A]\nCam, combien de temps?\n\n[BK4_23A]\nDonne-moi 3 minutes!\n\n[BNK4_26]\nBordel de merde! Les voilà!\n\n[BNK4_32]\nSers-toi des explosifs pour ouvrir les coffres!\n\n[BNK4_43]\nJe nous couvre, FONCE!\n\n[BNK4_51]\nJe te trouve très bien comme ça.\n\n[KENT]\nMISSIONS KENT PAUL\n\n[KENT1]\nMISSION KENT PAUL 1\n\n[COUNT]\nMISSIONS CONTREFACON\n\n[COUNT1]\nMISSION CONTREFACON 1\n\n[COUNT2]\nMISSION CONTREFACON 2\n\n[BIKE]\nMISSIONS BIKERS\n\n[BIKE1]\nMISSION BIKERS 1\n\n[BIKE2]\nMISSION BIKERS 2\n\n[BIKE3]\nMISSION BIKERS 3\n\n[GOAWAY1]\nReviens quand tu auras fini les missions du gang haïtien.\n\n[HAIT]\nMISSIONS GANG HAITIEN\n\n[HAIT1]\nMISSION GANG HAITIEN 1\n\n[HAIT2]\nMISSION GANG HAITIEN 2\n\n[HAIT3]\nMISSION GANG HAITIEN 3\n\n[HAM3_6]\n~g~Utilise le fusil à lunette que je t'ai donné pour les tuer!\n\n[ROCK]\nMISSIONS GROUPE DE ROCK\n\n[ROK1_4]\n~g~Ok, je crois que c'est ce que vous vouliez...\n\n[ROK1_1E]\n~g~Ca te coûtera plus que ce que tu as!\n\n[ROK1_1F]\n~g~Reviens quand tu auras le pognon!\n\n[RBM2_6]\n~g~Waou! C'est un mec! Arrête-le!\n\n[ROCK3]\nMISSION GROUPE DE ROCK 3\n\n[ROK3_6D]\n~r~en même temps que vos sales grosses têtes chevelues!\n\n[ROK3_40]\nPrès de la glacière?\n\n[RBM3_5]\n~g~Emmène les Love Fist au concert.\n\n[CUBANM]\nMISSIONS GANG CUBAIN\n\n[CUBAN1]\nMISSION GANG CUBAIN 1\n\n[CUBAN2]\nMISSION GANG CUBAIN 2\n\n[CUB2_10]\n~r~T'es supposé tuer des Haïtiens, pas des Cubains!\n\n[CUBAN3]\nMISSION GANG CUBAIN 3\n\n[CUBAN4]\nMISSION GANG CUBAIN 40\n\n[CUB4_25]\nOk, allons-y!\n\n[PROT]\nMISSIONS DE PROTECTION\n\n[PRO1_H]\nArrêtez de vous exciter, tous les deux. Je commence à peine à voir comment les choses marchent ici.\n\n[PRO1_02]\n~g~Sors du centre commercial.\n\n[PRO3_06]\n~g~Sème les flics.\n\n[PORN]\nMISSIONS PORNO\n\n[PORN1]\nMISSION PORNO 1\n\n[POR1_03]\n~r~Candy est morte!\n\n[PORN2]\nMISSION PORNO 2\n\n[PORN3]\nMISSION PORNO 3\n\n[POR3_18]\nT'as été repéré!\n\n[PORN4]\nMISSION PORNO 4\n\n[POR4_04]\n~g~Les bureaux se trouvent de l'autre côté de cette porte.\n\n[PHIL]\nMISSIONS PHIL\n\n[PHIL1]\nMISSION PHIL 1\n\n[PHI1_06]\nQu'est-ce que tu fous à conduire comme ça?\n\n[PHI1_07]\nHé!\n\n[PHIL2]\nMISSION PHIL 2\n\n[PIZ1_A]\nMISSION LIVREUR DE PIZZA\n\n[PIZ1_03]\n~g~Retourne à la pizzeria pour d'autres commandes.\n\n[PIZ1_04]\n~g~Voilà tes nouvelles commandes.\n\n[PIZ1_10]\nAppuie sur la ~h~ touche R3 ~w~ pour annuler les missions pizzas.\n\n[CNTBUY1]\nImprimerie achetée : $~1~\n\n[CARBUY]\nConcession achetée : $~1~\n\n[PORNBUY]\nStudio de cinéma acheté: $~1~\n\n[ICEBUY]\nUsine de crème glacée achetée: $~1~\n\n[TAXIBUY]\nCompagnie de taxis achetée: $~1~\n\n[BANKBUY]\nClub Malibu acheté : $~1~\n\n[BOATBUY]\nChantier naval acheté: $~1~\n\n[PRNT_NO]\nTu ne peux pas acheter l'imprimerie pour l'instant, reviens plus tard.\n\n[CAR_NO]\nTu ne peux pas acheter la concession automobile pour l'instant, reviens plus tard.\n\n[PORN_NO]\nTu ne peux pas acheter le studio de cinéma pour l'instant, reviens plus tard.\n\n[ICE_NO]\nTu ne peux pas acheter l'usine de crème glacée pour l'instant, reviens plus tard.\n\n[TAXI_NO]\nTu ne peux pas acheter la compagnie de taxis pour l'instant, reviens plus tard.\n\n[BANK_NO]\nTu ne peux pas acheter le club Malibu pour l'instant, reviens plus tard.\n\n[BOAT_NO]\nTu ne peux pas acheter le chantier naval pour l'instant, reviens plus tard.\n\n[PRNT_R3]\nAppuie sur la touche R3 pour acheter l'imprimerie au prix de $~1~\n\n[CAR_R3]\nAppuie sur la touche R3 pour acheter la concession automobile au prix de $~1~\n\n[PORN_R3]\nAppuie sur la touche R3 pour acheter le studio de cinéma au prix de $~1~\n\n[ICE_R3]\nAppuie sur la touche R3 pour acheter l'usine de crème glacée au prix de $~1~\n\n[TAXI_R3]\nAppuie sur la touche R3 pour acheter la compagnie de taxis au prix de $~1~\n\n[BANK_R3]\nAppuie sur la touche R3 pour acheter le club Malibu au prix de $~1~\n\n[BOAT_R3]\nAppuie sur la touche R3 pour acheter le chantier naval au prix de $~1~\n\n[COL2_6]\nArrête espèce de porc impérialiste d'Américain!\n\n[COL2_6B]\nCeci est la propriété du gouvernement français!\n\n[COL2_6C]\nEt c'est terminé.\n\n[COL3_A]\nThomas, merci d'être venu.\n\n[COL3_B]\nDésolé d'aller droit au but...\n\n[COL3_C]\nDiaz m'a demandé de superviser une petite transaction financière.\n\n[COL3_D]\nEspérons que ça se passera mieux que la dernière fois.\n\n[COL3_E]\nC'est la raison pour laquelle j'ai pensé à vous, mon ami.\n\n[COL3_F]\nJ'ai laissé un revolver au parking à niveaux.\n\n[COL3_G]\nRécupèrez-le et allez surveiller les mecs de Diaz au dépôt.\n\n[COL4_2]\nJe sais pas, chef!\n\n[COL4_5]\nChef, oui, chef!\n\n[COL4_10]\nAllons manger quelques beignets.\n\n[COL4_16]\nChef, on déplace le véhicule, chef!\n\n[COL4_25]\nAutodestruction du véhicule initialisée!\n\n[COL5_6]\nMercedes, cette fille aura ma peau.\n\n[COL5_8]\nMaudit cafard!\n\n[COL5_5]\nCrevez, porcs de Français!\n\n[CNT2_1]\nTuez-le!\n\n[CNT2_2]\nRécupérez les plaques!\n\n[CNT2_3]\nProtégez le coursier!\n\n[FINKILL]\nOk, les mecs, butez-le!\n\n[FIN_6]\nSonny est en haut avec le coffre et MON argent...\n\n[FIN_10]\nSonny? SONNY! Je viens te chercher!\n\n[RACES_4]\n3\n\n[RACES_5]\n2\n\n[RACES_6]\n1\n\n[RACES_7]\nPARTEZ!\n\n[RACES_9]\nTemps : ~1~:~1~\n\n[RACES]\nTEMPS :\n\n[RACES17]\nNv temps record : ~1~:~1~\n\n[RACES20]\nNv temps record : ~1~:0~1~\n\n[RACES21]\nTemps : ~1~:0~1~\n\n[RCH1_1]\n~g~Utilise l'hélicoptère radiocommandé, le RC Raider, pour PASSER les points de passage.\n\n[RCH1_2]\n~g~Les POINTS DE PASSAGE sont disséminés dans l'aéroport.\n\n[RCH1_3]\n~g~Tu as ~c~8 minutes~g~ pour passer les ~c~20!\n\n[RCH1_5]\nTemps\n\n[RCRC1_1]\n~g~Fais une COURSE DE POINTS DE PASSAGE contre deux autres RC Bandits sur 2 TOURS\n\n[RCRC1_2]\n~g~Va sur la grille de départ!\n\n[RCRC1_3]\n~g~Dernier tour!\n\n[RCRC1_4]\n~g~3\n\n[RCRC1_5]\n~g~2\n\n[RCRC1_6]\n~g~1\n\n[RCRC1_7]\n~g~PARTEZ!\n\n[RCRC1_8]\n~g~Temps de course : ~1~ secondes\n\n[RCPL1_1]\n~g~Fais une COURSE DE POINTS DE PASSAGE contre 3 autres RC Baron\n\n[RCPL1_2]\n~g~Tu dois passer par le ~o~CENTRE CORONA ~g~pour valider un point de passage.\n\n[RCPL1_3]\n~g~Va sur la grille de départ maintenant!\n\n[FEA_2SP]\n2 haut-parleurs\n\n[FEA_4SP]\nPlus de 2 haut-parleurs\n\n[FEA_EAR]\nCasque\n\n[FEA_NAH]\nPAS DE MATERIEL AUDIO\n\n[FET_APP]\nAPPLIQUER\n\n[FES_SKN]\nNOM DU SKIN\n\n[FES_DAT]\nDATE\n\n[FES_SET]\nUtiliser Skin\n\n[FET_DEF]\nPar défaut\n\n[FESZ_QZ]\nVeux-tu vraiment sauvegarder cette partie?\n\n[FES_SCG]\nSauvegarder la partie en cours?\n\n[FES_LCG]\nCharger la partie et continuer à jouer?\n\n[FEC_FIR]\nTirer\n\n[FEC_NWE]\nArme suivante\n\n[FEC_PWE]\nArme précédente\n\n[FEC_FOR]\nAvant\n\n[FEC_BAC]\nArrière\n\n[FEC_LEF]\nGauche\n\n[FEC_RIG]\nDroite\n\n[FEC_ZIN]\nZoom avant\n\n[FEC_ZOT]\nZoom arrière\n\n[FEC_EEX]\nEntrer+sortir\n\n[FEC_RAD]\nRadio\n\n[FEC_SUB]\nSous-mission\n\n[FEC_CMR]\nChanger caméra\n\n[FEC_JMP]\nSauter\n\n[FEC_SPN]\nCourir\n\n[FEC_HND]\nFrein à main\n\n[FEC_LOL]\nRegarder à gauche\n\n[FEC_LOR]\nRegarder à droite\n\n[FEC_NTR]\nCible suivante\n\n[FEC_PTT]\nCible précédente\n\n[FEC_LBA]\nRegarder derrière\n\n[FEC_CEN]\nCentrer caméra\n\n[FET_CCN]\nClassique\n\n[FET_SCN]\nStandard\n\n[FET_CFT]\nA PIED\n\n[FET_CCR]\nEN VOITURE\n\n[FET_CAC]\nACTION\n\n[FEC_IBT]\n-\n\n[FEC_MXO]\nMXB1\n\n[FEC_MXT]\nMXB2\n\n[FEC_UNB]\nNON LIE\n\n[FEC_TFL]\nRegard gauche+tourelle G\n\n[FEC_TFR]\nRegarde droite+tourelle D\n\n[FEC_MWF]\nVOLANT MS HAUT\n\n[FEC_MWB]\nVOLANT MX BAS\n\n[FEC_ORR]\nou\n\n[FEC_NUS]\nNON UTILISE\n\n[FEC_LUD]\nRegarder en haut\n\n[FEC_LDU]\nRegarder en bas\n\n[FEC_CMP]\nCOMBO : REGARDER G+D\n\n[LAW_1A]\nlaw_1a\n\n[LAW_1B]\nlaw_1b\n\n[LAW_2A]\nlaw_2a\n\n[LAW_2B]\nlaw_2b\n\n[FEH_STA]\nSTATS\n\n[FEH_LOA]\nCHARGER\n\n[FEH_CON]\nCOMMANDES\n\n[FEH_AUD]\nAUDIO\n\n[FEH_DIS]\nAFFICHAGE\n\n[FEH_LAN]\nLANGUE\n\n[FEH_SGA]\nLANCER NOUVELLE PARTIE\n\n[FEO_CON]\nConfiguration manette\n\n[FEO_AUD]\nConfiguration audio\n\n[FEO_DIS]\nConfiguration affichage\n\n[FEO_LAN]\nChoix langue\n\n[FEO_PLA]\nConfiguration joueur\n\n[FEA_OUT]\nSortie\n\n[FEA_ST]\nStéréo\n\n[FEA_DTS]\nDTS\n\n[FEA_RSS]\nStation de radio\n\n[FEA_NON]\nRADIO ETEINTE\n\n[FEA_FM0]\nWILDSTYLE\n\n[FEA_FM1]\nFLASH FM\n\n[FEA_FM2]\nKCHAT\n\n[FEA_FM3]\nFEVER 105\n\n[FEA_FM4]\nVROCK\n\n[FEA_FM5]\nVCPR\n\n[FEA_FM7]\nEMOTION 98.3\n\n[FEA_FM8]\nONDE 103\n\n[FED_BRI]\nLuminosité\n\n[FED_TRA]\nRémanences :\n\n[FED_SUB]\nSous-titres\n\n[FED_WIS]\nEcran large\n\n[FED_POS]\nPosition écran\n\n[FEP_RES]\nReprendre\n\n[FEP_STG]\nCommencer partie\n\n[FEP_STA]\nStats\n\n[FEP_BRI]\nBriefings\n\n[FEP_OPT]\nOptions\n\n[FEP_QUI]\nQuitter partie\n\n[FES_LOA]\nCharger partie\n\n[FES_DEL]\nEffacer partie\n\n[FEC_CSU]\nConfiguration manette\n\n[FEC_RED]\nRéassigner commandes\n\n[FEC_MOU]\nParamètres souris\n\n[DISTGOL]\nDist. parcourue en voiturette (miles)\n\n[DISTGOM]\nDistance parcourue en voiturette (m)\n\n[ST_FAVR]\nStation de radio préférée\n\n[ST_WSTR]\nStation de radio la moins écoutée\n\n[ST_FAVV]\nVéhicule préféré\n\n[ST_STAR]\nTotal d'étoiles de recherche obtenues\n\n[ST_HEAD]\nNombre de tirs à la tête\n\n[ST_GANG]\nGang le moins apprécié\n\n[ST_STGN]\nTotal d'étoiles de recherche évitées\n\n[TYREPOP]\nPneus crevés avec des balles\n\n[TYRESLA]\nPneus lacérés avec une lame\n\n[ST_BRK]\nNombre de victimes dans le Bloodring\n\n[ST_LTBR]\nPlus longue durée dans le Bloodring (sec)\n\n[ST_GNG1]\nCubains\n\n[ST_GNG2]\nHaïtiens\n\n[ST_GNG3]\nFaux voyous\n\n[ST_GNG4]\nGang de Diaz\n\n[ST_GNG5]\nAgents de sécurité\n\n[ST_GNG6]\nGang de motards\n\n[ST_GNG7]\nGang de Vercetti\n\n[ST_GNG8]\nGolfeurs\n\n[FEA_FM6]\nESPANTOSO\n\n[ST_ASSI]\nContrats exécutés\n\n[DISTBIK]\nDist. parcourue à moto (miles)\n\n[DISTBIM]\nDist. parcourue à moto (m)\n\n[HOTEL]\nHôtel Ocean View\n\n[ICC1_1]\n~g~Utilise ta camionnette de crème glacée pour distribuer de la drogue à Vice City.\n\n[ICC1_2]\n~g~Gare ta camionnette et appuie sur ~h~~k~~VEHICLE_HORN~~w~ pour jouer le jingle et signaler à tes clients que tu es prêt.\n\n[ICC1_3]\n~g~Tu reçois de l'argent pour chaque transaction faite, mais plus tu fais d'affaires, plus tu attires l'attention de la police.\n\n[KICK1_9]\nPOINTS DE PASSAGE RESTANTS :\n\n[FIN_B6]\nTu n'as pas assez d'argent pour commencer cette mission.\n\n[TEX3_3]\n~g~Pour ramasser une bombe, manoeuvre l'hélico au-dessus d'elle. La bombe est alors automatiquement fixée sous la carlingue.\n\n[TEX3_9]\n~g~Ramasse une bombe en manoeuvrant l'hélico à côté d'elle.\n\n[HELP22]\nVa vers la position du bip de la maison verte sur le radar.\n\n[FES_FMS]\nFormatage terminé. Sélectionne OK pour continuer.\n\n[FES_SSC]\nSauvegarde terminée. Sélectionne OK pour continuer.\n\n[FES_DSC]\nSuppression terminée. Sélectionne OK pour continuer.\n\n[FESZ_QC]\nEcraser ce fichier de sauvegarde corrompu?\n\n[FES_CHE]\nAttention! Un ou plusieurs codes ont été activés, ce qui peut affecter votre fichier de sauvegarde. Sauvegarde déconseillée.\n\n[FET_SG]\nSAUVEGARDER\n\n[FEH_BRI]\nBRIEFING\n\n[FEH_MAP]\nCARTE\n\n[FEM_OK]\nOK\n\n[FEC_CRO]\nS'accroupir\n\n[FEC_CR3]\nS'accroupir (touche L3)\n\n[FEC_SMT]\nSous-mission\n\n[FEC_SM3]\nSous-mission (touche R3)\n\n[FEC_RSC]\nStations de radio\n\n[ST_PR01]\nPilote\n\n[ST_PR02]\nSoldat armée de l'air\n\n[ST_PR03]\nOfficier pilote\n\n[ST_PR04]\nCaporal\n\n[ST_PR05]\nLieutenant\n\n[ST_PR06]\nSergent\n\n[ST_PR07]\nCapitaine\n\n[ST_PR08]\nBiggs\n\n[ST_PR09]\nWedge\n\n[ST_PR10]\nBaron rouge\n\n[ST_PR11]\nGoose\n\n[ST_PR12]\nViper\n\n[ST_PR13]\nJester\n\n[ST_PR14]\nChappy\n\n[ST_PR15]\nIceman\n\n[ST_PR16]\nMaverick\n\n[ST_PR17]\nNoops\n\n[ST_PR18]\nMaréchal de l'air\n\n[ST_PR19]\nAs\n\n[FET_LG]\nCharger partie\n\n[CAR_EXP]\nVéhicules routiers détruits\n\n[BOA_EXP]\nBateaux détruits\n\n[HEL_DST]\nAvions et hélicoptères détruits\n\n[STFT_01]\nMeilleur temps sur 'Alliage d'Acier'\n\n[STFT_02]\nMeilleur temps sur 'Le chauffeur'\n\n[STFT_03]\nMeilleur temps sur Dirt Ring\n\n[STFT_04]\nMeilleur temps course avion télécommandé\n\n[STFT_05]\nMeilleur temps course voiture télécommandée\n\n[STFT_06]\nMeilleur temps hélico télécommandé\n\n[STFT_07]\nMeilleur temps sur 'Terminal Velocity'\n\n[STFT_08]\nMeilleur temps sur 'Ocean Drive'\n\n[STFT_09]\nMeilleur temps sur 'Border Run'\n\n[STFT_10]\nMeilleur temps sur 'Capital Cruise'\n\n[STFT_11]\nMeilleur temps sur 'Virée!'\n\n[STFT_12]\nMeilleur temps sur 'Endurance V.C.'\n\n[STHC_01]\nMeilleur score sur Le Flingueur.\n\n[STHC_02]\nMeilleur pourcentage de tir au but sur le Flingueur.\n\n[STHC_03]\nNombre de deals de drogue\n\n[HELP24]\nTu peux maintenant bosser pour le colonel.\n\n[HELP25]\nTu peux maintenant bosser pour Avery Carrington\n\n[HELP29]\nTu peux te rendre au magasin de fringues quand tu n'es pas en mission.\n\n[HELP30]\nQuand tu achètes de nouvelles fringues, ton indice de recherche retombe à zéro.\n\n[BJM2_22]\n~r~Tu as quitté le stand de tir!\n\n[BJM2_23]\n~g~Si tu quittes le stand de tir pendant la compétition, la mission est un échec.\n\n[ASM4_24]\nDistance :\n\n[RBM1_6]\n~g~Ramène Mercedes et le Love Juice au groupe, au studio d'enregistrement.\n\n[RBM1_3]\nPLUS NECESSAIRE\n\n[HAM1_5]\nPLUS NECESSAIRE\n\n[RBM1_11]\nPLUS NECESSAIRE\n\n[HELP31]\nPour réaliser un arrosage latéral, regarde d'abord à droite ou à gauche en utilisant ~k~~VEHICLE_LOOKLEFT~ ou ~k~~VEHICLE_LOOKRIGHT~.\n\n[HELP34]\nTu dois être armé d'une mitraillette pour réaliser un arrosage latéral.\n\n[STRIP_1]\n~r~T'as pas assez de pognon, pauvre fauché!\n\n[EXIT_1]\nAppuie sur ~k~~PED_SPRINT~ pour sortir.\n\n[ASM1_A]\nM. Teal, votre aide dans l'éradication de ces indésirables fut une excellente affaire. J'ai un autre travail plus en finesse pour vous.\n\n[ASM1_B]\nRegardez sous le téléphone.\n\n[ASM1_C]\nJ'ai un autre travail plus en finesse pour vous.\n\n[SCARF]\nAppartement 3c\n\n[LAW4_10]\nLes patrons sont tous des salauds!\n\n[GEN1_04]\n~g~Passe la porte pour accéder au toit de Gonzalez.\n\n[GEN1_17]\n~g~Gonzalez se fait la malle! Suis-le et finis-en avec lui!\n\n[RCH1_9]\n~b~TEMPS TOTAL : ~1~:~1~\n\n[RCH1_10]\n~b~TEMPS TOTAL : ~1~:0~1~\n\n[WHEEL01]\nDOUBLE BONUS DEUX ROUES : $ ~1~ Distance : ~1~.~1~m Temps : ~1~ secondes\n\n[WHEEL02]\nDOUBLE BONUS DEUX ROUES : $ ~1~ Distance : ~1~ feet Temps : ~1~ secondes\n\n[WHEEL03]\nBONUS DEUX ROUES : $ ~1~ Temps : ~1~ secondes\n\n[WHEEL04]\nBONUS DEUX ROUES : $ ~1~ Distance : ~1~.~1~m\n\n[WHEEL05]\nBONUS DEUX ROUES : $ ~1~ Distance : ~1~ pieds\n\n[WHEEL06]\nBONUS ROUE ARRIERE : $ ~1~ Distance : ~1~.~1~m Temps : ~1~ secondes\n\n[WHEEL07]\nBONUS ROUE ARRIERE : $ ~1~ Distance : ~1~ feet Temps : ~1~ secondes\n\n[WHEEL08]\nBONUS ROUE ARRIERE : $ ~1~ Temps : ~1~ secondes\n\n[WHEEL09]\nBONUS ROUE ARRIERE : $ ~1~ Distance : ~1~.~1~m\n\n[WHEEL10]\nBONUS ROUE ARRIERE : $ ~1~ Distance : ~1~ pieds\n\n[WHEEL11]\nBONUS ROUE AVANT : $ ~1~ Distance : ~1~.~1~m Temps : ~1~ secondes\n\n[WHEEL12]\nBONUS ROUE AVANT : $ ~1~ Distance : ~1~ pieds Temps : ~1~ secondes\n\n[WHEEL13]\nBONUS ROUE AVANT: $ ~1~ Temps : ~1~ secondes\n\n[WHEEL14]\nBONUS ROUE AVANT : $ ~1~ Distance : ~1~.~1~m\n\n[WHEEL15]\nBONUS ROUE AVANT : $ ~1~ Distance : ~1~ pieds\n\n[ROK3_72]\nLove Fist!\n\n[POR1_19]\nHé!\n\n[DESPERA]\nDesperado\n\n[MOB_99A]\nRends-toi à la cabine près du centre commercial à Washington.\n\n[MOB_98A]\nRends-toi à la cabine dans Vice Point.\n\n[MOB_96A]\nRends-toi à la cabine du terminal de l'aéroport.\n\n[MOB_95A]\nRends-toi à la cabine dans Little Havana.\n\n[BNK1_1]\nJe peux vous aider, monsieur?\n\n[BNK1_2]\nIl y a un imposteur!\n\n[BNK1_3]\nIl a pêté les plombs!\n\n[BNK1_4]\nBon sang, t'es qui, toi?\n\n[BNK1_5]\nOù es ton badge?\n\n[BNK1_6]\nLes voilà! Descendez-les!\n\n[MOB_24A]\nBonjour, c'est M. Vercetti?\n\n[MOB_24B]\nOui.\n\n[MOB_24C]\nici Cortez. Vous étiez à ma fête.\n\n[MOB_24D]\nOui, je me souviens.\n\n[MOB_24E]\nM. Vercetti, c'est un regrettable incident, ce qui s'est produit avec votre affaire.\n\n[MOB_24F]\nJe sais.\n\n[MOB_24G]\nJe veux que vous sachiez que mes hommes et moi, faisons le maximum pour tirer ça au clair.\n\n[MOB_24H]\nSi vous souhaitez me parler en privé, vous me trouverez sur le bateau. Au revoir, senor.\n\n[BNK2_2]\nVISEZ 3-2-1 FEU!\n\n[BNK2_3]\nZONE DEGAGEE!\n\n[BNK2_6]\nCe mec est cinglé!\n\n[ANGEL]\nAngel\n\n[CUBJET]\nJetmax cubain\n\n[SANDKIN]\nSandking\n\n[POLMAV]\nMaverick Police\n\n[BOXVILL]\nBoxville\n\n[BENSON]\nBenson\n\n[HOTRINA]\nHotring Racer\n\n[HOTRINB]\nHotring Racer\n\n[BLOODRA]\nBloodring Banger\n\n[BLOODRB]\nBloodring Banger\n\n[MAFIACR]\nMafia Cruiser\n\n[COP_M2]\n'VICE SQUAD'\n\n[COP_M3]\n'BROWN THUNDER'\n\n[BJM2_20]\n~g~Quand tu n'as plus de ~w~temps ~g~ou de ~w~munitions ~g~, la manche est terminée!\n\n[BNK3_2]\nPas question que je conduise pour toi! J'en parlerai pendant la réunion de groupe!\n\n[FEM_SL1]\nPas de sauvegarde 1\n\n[FEM_SL2]\nPas de sauvegarde 2\n\n[FEM_SL3]\nPas de sauvegarde 3\n\n[FEM_SL4]\nPas de sauvegarde 4\n\n[FEM_SL5]\nPas de sauvegarde 5\n\n[FEM_SL6]\nPas de sauvegarde 6\n\n[FEM_SL7]\nPas de sauvegarde 7\n\n[FEM_SL8]\nPas de sauvegarde 8\n\n[FEA_CHA]\nPassage en mode STEREO. Patiente un instant...\n\n[FEA_CHD]\nAttention! Tu es en train de passer du mode STEREO au mode DTS. Patiente un instant...\n\n[FEI_SEL]\nSélectionner\n\n[FEI_BAC]\nRetour\n\n[FEI_RES]\nReprendre\n\n[FEI_NAV]\nExplorer\n\n[FEI_BTX]\nTouche / -\n\n[FEI_BTT]\nTouche \" -\n\n[FEI_STA]\nTouche START -\n\n[FEI_BTD]\n; = > < -\n\n[FEI_STO]\nArrêter\n\n[MOB_68A]\nTommy, mon fiston, j'ai une surprise pour toi!\n\n[MOB_68B]\nJe suis au studio d'enregistrement avec quelques artistes réputés.\n\n[MOB_68C]\nPourquoi tu ne viendrais pas faire un tour?\n\n[MOB_68D]\nC'est une bonne idée, non? Allez, à plus tard. C'est plutôt normal, non? Allez, à plus tard.\n\n[OUTFT1]\nStreetwear\n\n[OUTFT2]\nSoirée\n\n[OUTFT3]\nBleu de travail\n\n[OUTFT4]\nCountry club\n\n[OUTFT5]\nCubano\n\n[OUTFT6]\nFlic\n\n[OUTFT7]\nBraqueur\n\n[OUTFT8]\nDécontracté\n\n[OUTFT9]\nM. Vercetti\n\n[OUTFT10]\nSurvêtement\n\n[OUTFT13]\nMC Tommy\n\n[HOTR_07]\nNouveau record : ~1~:0~1~\n\n[HOTR_08]\nTemps : ~1~:~1~\n\n[GEN3_45]\nIls seront là d'une minute à l'autre. On ferait mieux de se trouver une bonne planque...\n\n[CAR_AS1]\nCONCESSION AUTOMOBILE ACQUISE\n\n[CAR_AS2]\n~g~Sunshine Autos génère dorénavant un revenu de $~1~ maximum. Pense à récupérer le fric régulièrement.\n\n[BUYSAVE]\n~g~Puisque tu n'es pas en mission, tu peux sauvegarder ta partie gratuitement.\n\n[BUYGARG]\n~g~Tu peux aussi garer des véhicules dans ce garage.\n\n[STRPBUY]\nClub Pole Position acquis : $~1~\n\n[STRP_R3]\nPour acheter le club Pole Position pour $~1~, appuie sur la touche R3.\n\n[NBMN_R3]\nPour acheter Elswanko Casa pour $~1~, appuie sur la touche R3.\n\n[GA_4]\nLes bombes pour voiture coûtent $1000 pièce.\n\n[GA_5]\nTa caisse est déjà équipée d'une bombe.\n\n[GA_6] { reVC update }\nGare-toi, amorce-la en appuyant sur la ~h~~k~~VEHICLE_FIREWEAPON~~w~ et BARRE-TOI vite!\n\n[GA_7] { reVC update }\nAmorce la bombe en appuyant sur la ~h~~k~~VEHICLE_FIREWEAPON~~w~. Elle explosera au démarrage.\n\n[GA_6B] { reVC update }\nGare-toi, amorce-la en appuyant sur la ~h~~k~~VEHICLE_FIREWEAPON~~w~ et BARRE-TOI vite!\n\n[GA_7B] { reVC update }\nAmorce la bombe en appuyant sur la ~h~~k~~VEHICLE_FIREWEAPON~~w~. Elle explosera au démarrage.\n\n[MOB_70A]\nTommy, c'est moi, le colonel Cortez. Ecoutez senor, je parie qu'avec vous, tout est possible.\n\n[MOB_70B]\nJe serai sur le bateau.\n\n[PICK1]\nGilet pare-balles livré dans l'hôtel Ocean View!\n\n[PICK2]\n.357 livré à la planque!\n\n[PICK3]\nTronçonneuse livrée à la planque!\n\n[PICK4]\nLance-flammes livré à la planque!\n\n[PICK5]\n.308 Lunette livré à la planque!\n\n[PICK6]\nMitrailleuse livrée à la planque!\n\n[PICK7]\nLance-roquettes livré à la planque!\n\n[PICK8]\nSea Sparrow désormais disponible dans la résidence!\n\n[PICK9]\nChar désormais disponible dans la caserne de l'armée!\n\n[PICK10]\nHunter désormais disponible dans la caserne de l'armée!\n\n[HELP41]\ntu peux aussi les défoncer avec un véhicule\n\n[ICC1_6]\n~g~Utilise le Mr. Whopee pour distribuer des produits Cherry Poppers dans Vice City.\n\n[ICC1_12]\nPROPRIETE ACQUISE!\n\n[CLOTH1]\nTenue de soirée livrée chez Rafael sur Ocean Beach.\n\n[CLOTH2]\nTenue streetwear livrée aux planques.\n\n[CLOTH3]\nBleu de travail livré chez Tooled Up dans le centre commercial de North Point.\n\n[CLOTH4]\nTenue pour le Country Club livrée au Leaf Links Golf Club.\n\n[CLOTH5]\nTenue Cubano livrée chez Little Havana Streetwear dans Little Havana.\n\n[CLOTH6]\nUniforme de flic livré au poste de police de Washington Beach.\n\n[CLOTH7]\nTenue décontractée livrée chez Gash dans le centre commercial de North Point.\n\n[CLOTH8]\nTenue de M. Vercetti livrée chez Collar & Cuffs sur Ocean Beach.\n\n[CLOTH9]\nSurvêtement livré chez Jocksport dans le centre.\n\n[CLOTH10]\nTenue de braqueur livrée au Malibu de Vice Point.\n\n[RBM1_9]\n~g~Va chez le dealer et rapporte du Love Juice pour les Love Fist!\n\n[MOB_62A]\nTommy, c'est Ricardo Diaz, je voulais te remercier de m'avoir sauvé.\n\n[MOB_62B]\nJ'ai demandé à ce con de Cortez. Il a dit que tu feras l'affaire, mon ami. Viens me voir à l'occasion.\n\n[MOB_62C]\nC'est d'un mec comme toi dont j'ai besoin. J'ai plus que des têtes de bites,\n\n[MOB_62D]\ndes têtes de bite partout! Tu vas gagner plein de pognon.\n\n[GOAWAY2]\n~g~Reviens quand tu auras terminé les missions Bikers.\n\n[COL2_9]\nImbécile de Ricain! Ils vous ont suivi jusqu'ici!\n\n[LOADCOL]\nChargement...\n\n[STFT_17]\nMeilleur temps sur Terrain de jeu PCJ\n\n[STFT_18]\nMeilleur temps sur 'Sélection par la boue'\n\n[STFT_19]\nMeilleur temps sur Piste d'essai\n\n[NEW_REC]\nNouveau record! ~1~ minutes et ~1~ secondes.\n\n[BMX_HOW]\n~g~Fais deux tours de circuit, ~y~en passant par ~g~les ~y~POINTS DE PASSAGE~g~!\n\n[BMXREW1]\n~g~Chaque fois que tu inscris un nouveau record pour les deux tours,\n\n[BMXREW2]\n~g~une meilleure ~y~RECOMPENSE ~g~t'est offerte!\n\n[BMXRAIN]\n~g~On dirait qu'il pleut...\n\n[ITBEG]\nAU DEBUT...\n\n[NBMNBUY]\nEl Swanko Casa acheté : $ ~1~\n\n[LNKVBUY]\nAppartement de Links View acheté : $ ~1~\n\n[HYCOBUY]\nHyman Condo acheté : $ ~1~\n\n[BUYGARS]\n~g~Tu peux également stocker des véhicules dans ces garages.\n\n[OCHEBUY]\nAppartement d'Ocean Heights acheté : $ ~1~\n\n[WASHBUY]\n1102 Washington Street acheté : $ ~1~\n\n[VCPTBUY]\n3321 Vice Point acheté : $ ~1~\n\n[SKUMBUY]\nSkumole Terrace achetée : $~1~\n\n[HELP6_C]\nAppuie sur la ~h~~k~~VEHICLE_HANDBRAKE~~w~ pour actionner le frein à main.\n\n[HELP2_A]\nAppuie sur la ~h~~k~~PED_SPRINT~~w~ lorsque tu cours pour ~h~sprinter.\n\n[HELP4_A]\nAppuie sur la ~h~~k~~VEHICLE_ACCELERATE~~w~ pour accélérer.\n\n[HELP5_A]\nAppuie sur la ~h~~k~~VEHICLE_BRAKE~~w~ pour freiner ou faire marche arrière si le véhicule est à l'arrêt.\n\n[HELP8_A]\nAppuie sur la ~h~~k~~PED_SNIPER_ZOOM_IN~~w~ pour faire un zoom avant avec le fusil et sur la ~x~touche /~w~ pour faire un zoom arrière.\n\n[PBOAT_1] { reVC update }\nAppuie sur la~h~ ~k~~VEHICLE_FIREWEAPON~~w~ pour tirer avec les canons du bateau.\n\n[SEG3_4] { reVC update }\n~g~Tu peux ramasser des bombes en pilotant ton avion radiocommandé à côté. Appuie sur la ~h~~k~~VEHICLE_FIREWEAPON~ ~g~touche.\n\n[RCR1_3] { reVC update }\n~g~Si tu veux quitter cette mission, appuie sur la ~h~~k~~VEHICLE_FIREWEAPON~~g~ pour faire exploser ta voiture radiocommandée.\n\n[HELP32] { reVC update }\nAppuie ensuite sur la ~h~~k~~VEHICLE_FIREWEAPON~~w~ pour tirer.\n\n[HELP33] { reVC update }\nAppuie ensuite sur la ~h~~k~~VEHICLE_FIREWEAPON~~w~ pour tirer.\n\n[TTUTOR]\nAppuie sur la ~h~~k~~TOGGLE_SUBMISSIONS~~w~ pour activer ou désactiver les missions Taxi.\n\n[TTUTOR2]\nAppuie sur la ~h~~k~~TOGGLE_SUBMISSIONS~~w~ pour activer ou désactiver les missions Taxi.\n\n[FTUTOR]\nAppuie sur la ~h~~k~~TOGGLE_SUBMISSIONS~~w~ pour activer ou désactiver les missions Camion de pompiers.\n\n[FTUTOR2]\nAppuie sur la ~h~~k~~TOGGLE_SUBMISSIONS~~w~ pour activer ou désactiver les missions Camion de pompiers.\n\n[CTUTOR]\nAppuie sur la ~h~~k~~TOGGLE_SUBMISSIONS~~w~ pour activer ou désactiver les missions Auto-défense.\n\n[CTUTOR2]\nAppuie sur la ~h~~k~~TOGGLE_SUBMISSIONS~~w~ pour activer ou désactiver les missions Auto-défense.\n\n[HELP8_B]\nAppuie sur la~h~ ~k~~PED_SNIPER_ZOOM_IN~ ~w~pour faire un ~h~zoom avant~w~ avec le fusil et sur la ~h~~k~~PED_SNIPER_ZOOM_OUT~~w~ pour faire un ~h~zoom arrière~w~.\n\n[ATUTOR3]\nAppuie sur la ~h~~k~~TOGGLE_SUBMISSIONS~~w~ pour activer ou désactiver les missions Ambulance.\n\n[GUN_H1]\n~w~Appuie sur la~h~ ~k~~PED_SPRINT~~w~ pour acheter. ~w~Appuie sur la~h~ ~k~~VEHICLE_ENTER_EXIT~~w~ pour quitter.\n\n[PU_CF3] { reVC update }\nAppuie sur la ~h~~k~~PED_ANSWER_PHONE~~w~ pour remplacer l'arme actuelle dans cet emplacement.\n\n[PU_CF4] { reVC update }\nAppuie sur la ~h~~k~~PED_ANSWER_PHONE~~w~ pour remplacer l'arme actuelle dans cet emplacement.\n\n[HELP9_B]\nAppuie sur la~h~ ~k~~PED_FIREWEAPON~ ~w~pour ~h~tirer~w~ avec le fusil à lunette.\n\n[HELP37]\nSi tu ne veux pas monter dans un véhicule quand tu braques le conducteur, appuie sur la ~h~~k~~PED_SPRINT~.\n\n[HELP6_A]\nAppuie sur la ~h~~k~~VEHICLE_HANDBRAKE~ ~w~ pour actionner le frein à main.\n\n[HELP6_D]\nAppuie sur la ~h~~k~~VEHICLE_HANDBRAKE~ ~w~ pour actionner le frein à main.\n\n[HELP26]\nAppuie sur la ~h~~k~~VEHICLE_ENTER_EXIT~ ~w~ pour monter ou sortir d'un véhicule.\n\n[HELP27]\nAppuie sur ~h~~k~~VEHICLE_TURRETUP~~w~ ou ~h~~k~~VEHICLE_TURRETDOWN~~w~ pour déplacer ton poids sur une moto.\n\n[HELP28]\nAppuie sur ~h~~k~~VEHICLE_TURRETUP~~w~ ou ~h~~k~~VEHICLE_TURRETDOWN~~w~ pour déplacer ton poids sur une moto.\n\n[HELP35]\nAppuie sur ~h~~k~~GO_LEFT~~w~ ou ~h~~k~~GO_RIGHT~~w~ pour diriger le véhicule.\n\n[HELP36]\nAppuie sur ~h~~k~~GO_LEFT~~w~ ou ~h~~k~~GO_RIGHT~~w~ pour diriger le véhicule.\n\n[HELP42]\nSuis le ~q~point rose~w~ pour trouver l'hôtel.\n\n[HELP19]\nMarche sur le ~q~marqueur rose~w~ pour continuer.\n\n[HELP1]\nArrête-toi au centre du ~q~marqueur rose.\n\n[HELP12]\nMarche au centre du ~q~marqueur rose~w~ pour lancer une mission.\n\n[SEG3_6]\n~g~Pour toucher ta cible, tu dois larguer la bombe sur la zone indiquée par le ~q~marqueur rose~w~. Tu peux larguer les bombes dans n'importe quel ordre.\n\n[S_PROMP]\nLorsque tu n'es pas en mission, tu peux sauvegarder la partie en ramassant la ~h~cassette.\n\n[HELP16]\nFranchis la porte d'entrée de l'hôtel ~h~Ocean View~w~ pour y pénétrer.\n\n[HELP43]\n~g~Rends-toi à l'hôtel ~h~Ocean View~g~ sur Ocean Drive.\n\n[HELI_F1]\n~r~Mission Point de passage hélico annulée!\n\n[AMMUHLP]\nSi tu as besoin d'armes, va chez ~h~Ammu-Nation~w~. Suis le ~h~point pistolet~w~ sur le radar.\n\n[HELI_1]\nPoint de passage hélico du Centre\n\n[HELI_2]\nPoint de passage hélico d'Ocean Beach\n\n[HELI_3]\nPoint de passage hélico de Vice Point\n\n[HELI_4]\nPoint de passage hélico de Little Haiti\n\n[FST_MFR]\nStation de radio préférée\n\n[FST_LFR]\nStation de radio la moins écoutée\n\n[FEI_HOL]\nMaintenir\n\n[FEI_ZOO]\nZoom\n\n[FEI_BTR]\n> < -\n\n[FEI_NA]\nAucun\n\n[MESA]\nGrande table\n\n[STRP_NO]\nTu ne peux pas acheter la boîte de striptease maintenant. Reviens plus tard.\n\n[CHSE]\nPOURSUITE\n\n[NBMN_L]\nAppuie sur la ~h~~k~~PED_ANSWER_PHONE~ ~w~pour acheter El Swanko Casa pour $~1~.\n\n[NBMN_T]\nAppuie sur la ~h~~k~~PED_ANSWER_PHONE~ ~w~pour acheter El Swanko Casa pour $~1~.\n\n[NBMN_C]\nAppuie sur la ~h~~k~~PED_ANSWER_PHONE~ ~w~pour acheter El Swanko Casa pour $~1~.\n\n[LNKV_L]\nAppuie sur la ~h~~k~~PED_ANSWER_PHONE~ ~w~pour acheter l'appartement de Links View pour $~1~.\n\n[LNKV_T]\nAppuie sur la ~h~~k~~PED_ANSWER_PHONE~ ~w~pour acheter l'appartement de Links View pour $~1~.\n\n[LNKV_C]\nAppuie sur la ~h~~k~~PED_ANSWER_PHONE~ ~w~pour acheter l'appartement de Links View pour $~1~.\n\n[HYCO_L]\nAppuie sur la ~h~~k~~PED_ANSWER_PHONE~ ~w~pour acheter Hyman Condo pour $~1~.\n\n[HYCO_T]\nAppuie sur la ~h~~k~~PED_ANSWER_PHONE~ ~w~pour acheter Hyman Condo pour $~1~.\n\n[HYCO_C]\nAppuie sur la ~h~~k~~PED_ANSWER_PHONE~ ~w~pour acheter Hyman Condo pour $~1~.\n\n[OCHE_L]\nAppuie sur la ~h~~k~~PED_ANSWER_PHONE~ ~w~pour acheter l'appartement d'Ocean Heights pour $~1~.\n\n[OCHE_T]\nAppuie sur la ~h~~k~~PED_ANSWER_PHONE~ ~w~pour acheter l'appartement d'Ocean Heights pour $~1~.\n\n[OCHE_C]\nAppuie sur la ~h~~k~~PED_ANSWER_PHONE~ ~w~pour acheter l'appartement d'Ocean Heights pour $~1~.\n\n[WASH_L]\nAppuie sur la ~h~~k~~PED_ANSWER_PHONE~ ~w~pour acheter le 1102 Washington Street pour $~1~.\n\n[WASH_T]\nAppuie sur la ~h~~k~~PED_ANSWER_PHONE~ ~w~pour acheter le 1102 Washington Street pour $~1~.\n\n[WASH_C]\nAppuie sur la ~h~~k~~PED_ANSWER_PHONE~ ~w~pour acheter le 1102 Washington Street pour $~1~.\n\n[VCPT_L]\nAppuie sur la ~h~~k~~PED_ANSWER_PHONE~ ~w~pour acheter le 3321 Vice Point pour $~1~.\n\n[VCPT_T]\nAppuie sur la ~h~~k~~PED_ANSWER_PHONE~ ~w~pour acheter le 3321 Vice Point pour $~1~.\n\n[VCPT_C]\nAppuie sur la ~h~~k~~PED_ANSWER_PHONE~ ~w~pour acheter le 3321 Vice Point pour $~1~.\n\n[SKUM_L]\nAppuie sur la ~h~~k~~PED_ANSWER_PHONE~~w~ pour acheter la Skumole Terrace pour $~1~.\n\n[SKUM_T]\nAppuie sur la ~h~~k~~PED_ANSWER_PHONE~~w~ pour acheter la Skumole Terrace pour $~1~.\n\n[SKUM_C]\nAppuie sur la ~h~~k~~PED_ANSWER_PHONE~~w~ pour acheter la Skumole Terrace pour $~1~.\n\n[PRNT_L]\nAppuie sur la ~h~~k~~PED_ANSWER_PHONE~ ~w~pour acheter l'imprimerie pour $~1~.\n\n[PRNT_T]\nAppuie sur la ~h~~k~~PED_ANSWER_PHONE~ ~w~pour acheter l'imprimerie pour $~1~.\n\n[PRNT_C]\nAppuie sur la ~h~~k~~PED_ANSWER_PHONE~ ~w~pour acheter l'imprimerie pour $~1~.\n\n[CAR_L]\nAppuie sur la ~h~~k~~PED_ANSWER_PHONE~ ~w~pour acheter la concession automobile pour $~1~.\n\n[CAR_T]\nAppuie sur la ~h~~k~~PED_ANSWER_PHONE~ ~w~pour acheter la concession automobile pour $~1~.\n\n[CAR_C]\nAppuie sur la ~h~~k~~PED_ANSWER_PHONE~ ~w~pour acheter la concession automobile pour $~1~.\n\n[PORN_L]\nAppuie sur la ~h~~k~~PED_ANSWER_PHONE~ ~w~pour acheter le studio de cinéma pour $~1~.\n\n[PORN_T]\nAppuie sur la ~h~~k~~PED_ANSWER_PHONE~ ~w~pour acheter le studio de cinéma pour $~1~.\n\n[PORN_C]\nAppuie sur la ~h~~k~~PED_ANSWER_PHONE~ ~w~pour acheter le studio de cinéma pour $~1~.\n\n[ICE_L]\nAppuie sur la ~h~~k~~PED_ANSWER_PHONE~ ~w~pour acheter l'usine de crème glacée pour $~1~.\n\n[ICE_T]\nAppuie sur la ~h~~k~~PED_ANSWER_PHONE~ ~w~pour acheter l'usine de crème glacée pour $~1~.\n\n[ICE_C]\nAppuie sur la ~h~~k~~PED_ANSWER_PHONE~ ~w~pour acheter l'usine de crème glacée pour $~1~.\n\n[TAXI_L]\nAppuie sur la ~h~~k~~PED_ANSWER_PHONE~ ~w~pour acheter la compagnie de taxis pour $~1~.\n\n[TAXI_T]\nAppuie sur la ~h~~k~~PED_ANSWER_PHONE~ ~w~pour acheter la compagnie de taxis pour $~1~.\n\n[TAXI_C]\nAppuie sur la ~h~~k~~PED_ANSWER_PHONE~ ~w~pour acheter la compagnie de taxis pour $~1~.\n\n[BANK_L]\nAppuie sur la ~h~~k~~PED_ANSWER_PHONE~ ~w~pour acheter le Malibu pour $~1~.\n\n[BANK_T]\nAppuie sur la ~h~~k~~PED_ANSWER_PHONE~ ~w~pour acheter le Malibu pour $~1~.\n\n[BANK_C]\nAppuie sur la ~h~~k~~PED_ANSWER_PHONE~ ~w~pour acheter le Malibu pour $~1~.\n\n[BOAT_L]\nAppuie sur la ~h~~k~~PED_ANSWER_PHONE~ ~w~pour acheter le chantier naval pour $~1~.\n\n[BOAT_T]\nAppuie sur la ~h~~k~~PED_ANSWER_PHONE~ ~w~pour acheter le chantier naval pour $~1~.\n\n[BOAT_C]\nAppuie sur la ~h~~k~~PED_ANSWER_PHONE~ ~w~pour acheter le chantier naval pour $~1~.\n\n[STRP_L]\nAppuie sur la ~h~~k~~PED_ANSWER_PHONE~ ~w~pour acheter le Pole Position Club pour $~1~.\n\n[STRP_T]\nAppuie sur la ~h~~k~~PED_ANSWER_PHONE~ ~w~pour acheter le Pole Position Club pour $~1~.\n\n[STRP_C]\nAppuie sur la ~h~~k~~PED_ANSWER_PHONE~ ~w~pour acheter le Pole Position Club pour $~1~.\n\n[STOCK]\n~r~stock écoulé\n\n[HELP14]\nPour trouver le cabinet d'avocats, suis le ~h~point L~w~ sur le radar.\n\n[BOAT_AS]\n~g~Le chantier naval génère dorénavant un revenu de $~1~ maximum. Pense à récupérer le fric régulièrement.\n\n[BOAT_A2]\nCHANTIER NAVAL OK\n\n[BOAT_N]\nCheckpoint Charlie\n\n[BOAT_P]\n~g~Récupère les paquets avant la fin du temps imparti.\n\n[FEI_R1B]\nTouches R1\\R2 -\n\n[HELP9_A]\nAppuie sur la touche ~h~~k~~PED_FIREWEAPON~ ~w~pour tirer avec le fusil à lunette.\n\n[HELP21]\nAppuie sur la touche ~h~~k~~VEHICLE_ENTER_EXIT~ ~w~pour monter dans un véhicule ou en sortir.\n\n[CREAM]\nDistribution\n\n[UMBERTO]\nCafé Robina\n\n[PU_CF1]\nAppuie sur la touche ~h~~k~~PED_ANSWER_PHONE~ ~w~pour ramasser cette arme. Elle remplacera toute autre arme du même type que tu possèdes.\n\n[FED_RDM]\nCARTE ET POINTS\n\n[FEC_ILU]\nVue inversée à la 1ere personne :\n\n[NITRO]\nTous les taxis disposent d'un saut turbo! Appuie simplement sur la touche klaxonner.\n\n[RATNG53]\nFaux cul\n\n[RATNG54]\nFaiseur d'emmerdes\n\n[RATNG55]\nMalhonnête\n\n[RATNG56]\nTricheur\n\n[RATNG57]\nMythomane\n\n[STHC_04]\nMeilleur score au beach ball de Keepie-Uppy\n\n[STHC_05]\nMeilleur résultat au Hotring\n\n[STFT_13]\nMeilleur tps point de passage hélico du centre\n\n[STFT_14]\nMeilleur tps point de passage hélico d'Ocean Beach\n\n[STFT_15]\nMeilleur tps point de passage hélico de Vice Point\n\n[STFT_16]\nMeilleur tps point de passage hélico de Little Haiti\n\n[STFT_21]\nMeilleur temps au Hotring\n\n[STFT_22]\nMeilleur temps au tour au Hotring\n\n[STFT_20]\nMeilleur temps au 'Cone Crazy'\n\n[HELP44]\nArrête-toi sur le ~q~marqueur rose.\n\n[HELP45]\nAppuie sur la ~h~~k~~PED_DUCK~~w~ pour t'accroupir. Ceci augmente la précision des flingues que tu portes.\n\n[RCR1_5]\nCourse de Bandit RC\n\n[RCPL1_7]\nCourse de Baron RC\n\n[RCH1_11]\nCourse de Raider RC\n\n[FEA_CTD]\nAttention! Un équipement matériel compatible DTS est requis pour cette fonction. Continuer?\n\n[FEM_STE]\nSTEREO\n\n[FEM_UDY]\nDTS\n\n[GREET]\nBien le bonjour de...\n\n[LANCE_1]\nHé, mec, conduis un peu mieux!\n\n[LANCE_2]\nHé, fais gaffe à ce que tu fais!\n\n[LANCE_3]\nHé, tu vas où, là?\n\n[LANCE_4]\nOn fait quoi maintenant?\n\n[LAW4_15]\nPlus de fric!\n\n[MERC_5]\nBelle voiture, M. Vercetti.\n\n[MERC_26]\nPLUS VITE, PLUS VITE, PLUS VITE!\n\n[MERC_27]\nAttention, Tommy, je me suis fait refaire le nez le mois dernier.\n\n[MERC_28]\nTommy, conduis prudemment!\n\n[MERC_29]\nTommy, va moins vite!\n\n[MERC_30]\nTommy, tu veux bien tuer quelqu'un d'autre que moi?\n\n[MERC_31]\nTommy, chéri, ne me tue pas!\n\n[MERC_32]\nTommy, ça me très plaisir que t'aies volé cette caisse!\n\n[MERC_40]\nJ'ai vraiment passé un bon moment.\n\n[MERC_43]\nAdios, mon chou.\n\n[MERC_44]\nContinue la muscu, d'accord?\n\n[MERC_45]\nCiao, mon beau.\n\n[COL5_17]\nOh mon dieu, ils ont un hélicoptère!\n\n[COL5_18]\nAbattez l'hélico!\n\n[COL5_19]\nTommy, débarrasse-nous de cet hélico!\n\n[COL5_20]\nIl revient! Détruisez cet hélico!\n\n[COL5_21]\nVisez la taille de cet hélico!\n\n[COL5_22]\nLe revoilà!\n\n[FEA_DSM]\nAttention! Cette sauvegarde est paramétrée pour un son DTS. Du matériel compatible DTS doit être connecté. Choisir entre une sortie audio STEREO ou DTS.\n\n[STFT_23]\nMeilleur temps à Checkpoint Charlie\n\n[HELP50]\nAppuie sur la touche ~h~~k~~PED_ANSWER_PHONE~~w~ pour placer la caméra derrière toi.\n\n[HELP51]\nAppuie sur la touche ~h~~k~~PED_ANSWER_PHONE~~w~ pour placer la caméra derrière toi.\n\n[HELP52]\nAppuie sur la touche ~h~~k~~PED_ANSWER_PHONE~~w~ pour placer la caméra derrière toi.\n\n[HELP53]\nAppuie sur la touche ~h~~k~~PED_CYCLE_WEAPON_LEFT~~w~ ou sur la touche ~h~~k~~PED_CYCLE_WEAPON_RIGHT~~w~ pour faire défiler tes armes disponibles.\n\n[HELP46]\nIl existe huit différents types d'armes.\n\n[HELP47]\nTu peux porter une arme de chaque type à la fois, un type de pistolet, un type de fusil à pompe, etc.\n\n[HELP54]\n~w~Prix : $~1~ ~r~L'achat de cette arme remplacera celle que tu possèdes déjà.\n\n[HELP2A2]\nAppuie sur la touche ~h~~k~~PED_SPRINT~~w~ quand tu cours, pour ~h~sprinter.\n\n[HLPSN_A]\nGrâce au fusil à lunette, tu peux zoomer de loin sur une cible et la viser avec précision.\n\n[HLPSN_B]\nAppuie sur la touche~h~ ~k~~PED_LOCK_TARGET~ ~w~et maintiens-la enfoncée pour ~h~viser~w~ avec le fusil à lunette.\n\n[HLPSN_C]\nAppuie sur la touche~h~ ~k~~PED_LOCK_TARGET~ ~w~et maintiens-la enfoncée pour ~h~viser~w~ avec le fusil à lunette.\n\n[HLPSN_D]\nAppuie sur la touche ~h~~k~~PED_SNIPER_ZOOM_IN~~w~ pour ~h~faire un zoom avant ~w~avec le fusil à lunette et sur la touche~h~ ~k~~PED_SNIPER_ZOOM_OUT~ ~w~pour ~h~faire un zoom arrière~w~.\n\n[HLPSN_E]\nAppuie sur la touche ~h~~k~~PED_FIREWEAPON~~w~ ~w~pour ~h~tirer~w~ avec le fusil à lunette.\n\n[HLPSN_F]\nAppuie sur la touche ~h~~k~~PED_FIREWEAPON~~w~ ~w~pour ~h~tirer~w~ avec le fusil à lunette.\n\n[HLPSN_G]\nAppuie sur la touche ~h~~k~~PED_FIREWEAPON~~w~ ~w~pour ~h~tirer~w~ avec le fusil à lunette.\n\n[PLANE_H]\nUtilise la touche ~h~~k~~VEHICLE_ACCELERATE~~w~ pour accélérer. Gauche et droite pour tourner.\n\n[PLANE_4] { reVC update }\n{Utilise la touche ~h~~k~~VEHICLE_ACCELERATE~~w~ pour accélérer. Gauche et droite pour tourner.}\nUtilise le joystick analogique droit pour accélérer, appuie vers le bas sur le joystick analogique gauche pour monter et vers le haut pour descendre. Gauche et droite pour tourner.\n\n[HELP55]\nAppuie sur la touche ~h~~k~~PED_FIREWEAPON~~w~ pour attaquer le chef.\n\n[STPR_8]\nPole Position Club\n\n[STPR_9]\n3321 Vice Point\n\n[STPR_10]\nAppartement de Links View\n\n[STPR_11]\nEl Swanko Casa\n\n[STPR_12]\n1102 Washington Street\n\n[STPR_13]\nAppartement d'Ocean Heights\n\n[STPR_14]\nSkumole Shack\n\n[STPR_15]\nHyman Condo\n\n[RCCANX]\n~r~Avion RC annulé.\n\n[CLT_HL2]\nLorsque tu ramasses des fringues, une ou deux étoiles d'indice de recherche sont enlevées.\n\n[CRED009]\nCONCEPTION DES MISSIONS\n\n[CRED359]\nLEE JOHNSON\n\n[CRED360]\nHENDRIK LESSER\n\n[CRED361]\nPASQUALE STACCHIOTTI\n\n[CRED362]\nENRIQUE FERNANDEZ\n\n[CRED363]\nPAUL BYERS\n\n[CRED364]\nMIKE EMENY\n\n[CRED365]\nROB DUNKIN\n\n[CRED366]\nCHARLIE KINLOCH\n\n[CRED367]\nKEVIN HOBSON\n\n[CRED368]\nJIM CREE\n\n[MOB_66A]\nTommy, Tommy, Tommy, pourquoi t'es revenu ici?\n\n[MOB_66B]\nOn t'a déjà dit qu'on voulait plus te revoir.\n\n[MOB_67A]\nTommy, je crois que tu devrais rester à l'écart, tu saisis?\n\n[MOB_67B]\nLes petits gars Haïtiens t'aiment pas beaucoup.\n\n[MOB_18A]\nTommy, c'est Paulo. Tu vas bien? Bon, mec, il faut que je te parle.\n\n[MOB_18B]\nAh, mon pote, tu croiras jamais l'incroyable petit lot que je viens de lever...\n\n[MOB_18C]\nElle se promenait juste en bas dans Little Havana, mon pote.\n\n[MOB_18D]\nElle m'a dit qu'elle s'appelait Mercedes ou un truc comme ça.\n\n[MOB_18E]\nAh, mon pote, faut que t'ailles voir cette fille!\n\n[MOB_18F]\nElle ferait bander un eunuque! Elle m'a dit que j'étais le meilleur coup de sa vie et tout et tout!\n\n[MOB_18G]\nVas-y, trouve-la. A plus tard!\n\n[MOB_72A]\nTommy, c'est moi, Lance. Ferme-la, Tommy, parce que j'ai pas le temps de discuter!\n\n[MOB_72B]\nJ'me tape de ce que t'as à me dire. Pourquoi ça m'intéresserait? T'en as rien à foutre de moi, non?\n\n[MOB_72C]\nIl faut que tu sois plus sympa avec moi. Donne-moi une belle part. Tu vois...\n\n[MOB_72D]\nTommy... Ecoute, mec, je suis désolé. C'est que...\n\n[MOB_72E]\nLes gens arrêtent pas de me materner, de me traiter comme un gamin.\n\n[MOB_72F]\nMon frère pourrait me faire ça, mais pas toi. S'il te plaît.\n\n[MOB_72G]\nFaut que j'y aille.\n\n[MOB_63A]\nTommy, c'est Earnest. Earnest Kelly.\n\n[MOB_63B]\nCa va?\n\n[MOB_63C]\nBien. Il va me falloir une canne pour marcher, mais je devrais revenir rapidement dans les affaires.\n\n[MOB_63D]\nBien.\n\n[MOB_63E]\nJ'ai appris au sujet de Lance. Quel enculé, hein?\n\n[MOB_63F]\nOuais.\n\n[MOB_63G]\nNe jamais faire confiance à un mec qui se trimballe en pyjama. C'est ce que je dis toujours. J'espère bien qu'il en a bavé, ce con.\n\n[MOB_63H]\nJe crois que oui. Je pensais pas qu'il était comme ça...\n\n[MOB_63I]\nTommy, t'as beau être cinglé, t'es vraiment naïf. Il va falloir que je t'apprenne deux ou trois trucs sur la vie, dès que je serai remis sur pied.\n\n[MOB_63J]\nPrends ton temps, Earnest et surtout, prends soin de toi.\n\n[MOB_16A]\nTommy, c'est Paulo. Que pasa amigo?\n\n[MOB_16B]\nQu'est-ce tu m'veux, Paul? J'veux pas de fringues de contrefaçon.\n\n[MOB_16C]\nTrès drôle, mon pote, mais tu sais que je fais pas dans la merde. Non, j'appelle juste pour savoir si t'aurais pas un rôle pour moi dans un de tes films.\n\n[MOB_16D]\nJ'ai fait pas mal de X en Angleterre, mec. J'en ai plus que toi dans l'pantalon.\n\n[MOB_16E]\nPaul, merci pour la proposition, je vais y réfléchir.\n\n[MOB_16F]\nSérieux, pense à moi, après tout ce que j'ai fait pour toi.\n\n[MOB_16G]\nC'est ce que j'essaie d'oublier, justement...\n\n[MOB_17A]\nTommy Vercetti, comment vas-tu? J'ai entendu tous ces trucs sur toi. Un flambeur en ville maintenant...\n\n[MOB_17B]\nPaul, t'es bourré?\n\n[MOB_17C]\nNon, pauv' con, je suis pas bourré! J'ai juste pris deux ou trois verres et quelques tournées, et ça fait deux jours que j'ai pas fermé l'oeil!\n\n[MOB_17D]\nDe toute façon, me traite pas comme ça. Je suis pas une poire. Qui c'est qui t'a lancé dans cette ville? Hein, qui? Moi!\n\n[MOB_17F]\nAh ouais?\n\n[MOB_17G]\nMe traite pas comme ça? Qui c'est qui t'a présenté à des gens? Je t'ai montré tous les trucs, je me suis fait chier pour toi et voilà comment tu m'remercies.\n\n[MOB_17H]\nTu m'ignores. Tu me laisses de côté après tout ce que j'ai fait pour toi! Qui tu crois que je suis? Une merde ou je sais pas quoi?\n\n[MOB_17I]\nPaul, calme-toi. J'ai été occupé, ne sois pas stupide.\n\n[MOB_17J]\nJe suis pas stupide, connard! Ils me l'ont dit en maison de redressement! Si tu cherches les emmerdes, mon pote, tu vas les trouver!\n\n[MOB_17K]\nTommy, s'il te plaît! T'étais mon grand espoir! Te fous pas de moi!\n\n[MOB_17L]\nPaul, va roupiller un bon coup, sérieusement.\n\n[MOB_73A]\nTommy, c'est Steve.\n\n[MOB_73B]\nSalut, Steve.\n\n[MOB_73C]\nSalut le génie. T'es merveilleux! Je suis une merveille! Ils nous adorent. On réécrit le livre des records, mon pote!\n\n[MOB_73D]\nJe parle de putain de récompenses. Enfin je peux envoyer mon père à l'hospice et lui dire de fermer sa gueule.\n\n[MOB_73E]\nEuh... C'est cool, Steve.\n\n[MOB_73F]\nCool? C'est génial, mec. GENIAL quoi! Il n'a jamais voulu croire en moi, mais regarde ce qu'on a réussi à faire.\n\n[MOB_73G]\nJe suis le plus grand réalisateur de films de cul faits maison de la planète, mon pote. Je voulais juste te dire que je suis heureux de t'avoir rencontré.\n\n[MOB_73H]\nMerci, Steve.\n\n[MOB_73I]\nJe t'aime, bébé. Et reste comme tu es, d'accord?\n\n[MOB_73J]\nD'accord. Salut, Steve.\n\n[BOLLOX]\nAppuie sur la touche ~o~R1 ~w~pour larguer une bombe. Appuie sur la touche ~t~\" ~w~pour annuler.\n\n[BRID_OP]\nAvis de tempête terminé : tous les ponts sont maintenant accessibles.\n\n[BRID_CL]\nAvis de tempête : tous les ponts sont fermés.\n\n[LG_38]\nCible\n\n[ASSET_C]\nPole Position, OK\n\n[ASSET_D]\n~g~Le club Pole Position va maintenant créer un revenu d'un maximum de $~1~ par jour. Venez retirer votre argent régulièrement.\n\n[ST_WHEE]\nTemps maximum sur roue arrière (secs)\n\n[ST_STOP]\nTemps maximum sur roue avant (secs)\n\n[ST_2WHE]\nTemps maximum sur deux roues (secs)\n\n[ST_WHED]\nDistance maximum sur roue arrière (m)\n\n[ST_STOD]\nDistance maximum sur roue avant (m)\n\n[ST_2WHD]\nDistance maximum sur deux roues (m)\n\n[OUTFT11]\nSurvêtement\n\n[OUTFT12]\nFrankie\n\n[RELOAD]\n~g~Tu as gagné la possibilité de recharger ton arme rapidement\n\n[APACHE]\nHunter livré à l'héliport d'Ocean Beach\n\n[CRED369]\nJOHN MCCARDLE\n\n[CRED370]\nDAVID MURDOCH\n\n[CRED371]\nCHRIS BROWN\n\n[CRED372]\nPAUL GREEN\n\n[CRED373]\nKYLE MILNE\n\n[CUNTY]\nNouveaux vêtements livrés au Domaine Vercetti\n\n[GOODBOY]\n$50 pour bonne conduite\n\n[NEWCONT]\nNouveau ~h~point de contact ~w~créé à la marina d'Ocean Beach\n\n[FIRELVL]\nMission Camion de pompiers niveau ~1~\n\n[HELP56]\nAppuie sur la touche ~h~~k~~CAMERA_CHANGE_VIEW_ALL_SITUATIONS~~w~ pour changer le mode de la caméra.\n\n[HELP57]\nAppuie sur la touche ~h~~k~~CAMERA_CHANGE_VIEW_ALL_SITUATIONS~~w~ pour changer le mode de la caméra.\n\n[HELP58]\nTout en visant, appuie sur la touche ~h~~k~~PED_CYCLE_TARGET_LEFT~~w~ ou ~h~~k~~PED_CYCLE_TARGET_RIGHT~~w~ pour faire défiler les cibles.\n\n[HELP59]\nTout en visant, appuie sur la touche ~h~~k~~PED_CYCLE_TARGET_LEFT~~w~ ou ~h~~k~~PED_CYCLE_TARGET_RIGHT~~w~ pour faire défiler les cibles.\n\n[HELP60]\nSi tu appuies sur la touche ~h~~k~~PED_SPRINT~ ~w~quand tu essaies de piquer une caisse, tu ne peux pas monter dedans.\n\n[HELP61]\nTu as désormais des munitions illimitées et tous tes véhicules sont deux fois plus résistants.\n\n[CRED374]\nKEVIN YUN\n\n[CRED375]\nERICK COBBS\n\n[CRED376]\nRANDY BLAKE\n\n[CRED377]\nBRANDON LIM\n\n[CRED378]\nBRANDON FENOL\n\n[CRED379]\nMICHAEL MANOLE\n\n[CRED380]\nALETHEIA SIMONSON\n\n[CRED381]\nJOHN JANSEN\n\n[FEC_LB1]\nRegarder\n\n[FEC_LB2]\nderrière\n\n[FEC_LB3]\nRegarder derrière\n\n[FEC_R3]\n(touche R3)\n\n[FEC_PED]\nCommandes à pied\n\n[FEC_VEH]\nCommandes des véhicules\n\n[FEC_FPR]\nCommandes en vue subjective\n\n[FEC_CMM]\nCommandes principales\n\n[FEC_PWL]\nAller à gauche\n\n[FEC_PWR]\nAller à droite\n\n[FEC_PWF]\nAvancer\n\n[FEC_PWT]\nAvancer vers caméra\n\n[FEC_PLB]\nVue arrière\n\n[FEC_PFR]\nTirer\n\n[FEC_CLE]\nDéfilement Gauche des armes\n\n[FEC_CRI]\nDéfilement Droite des armes\n\n[FEC_LKT]\nVerrouiller cible\n\n[FEC_PJP]\nSaut à pied\n\n[FEC_PSP]\nSprint à pied\n\n[FEC_PSH]\nTir à pied\n\n[FEC_TLF]\nCible suivante Gauche\n\n[FEC_TRG]\nCible suivante Droite\n\n[FEC_CCM]\nCentrer caméra derrière joueur\n\n[FEC_SZI]\nFusil à lunette zoom avant\n\n[FEC_SZO]\nFusil à lunette zoom arrière\n\n[FEC_LKL]\nRegarder à gauche en vue subjective\n\n[FEC_LRT]\nRegarder à droite en vue subjective\n\n[FEC_LUP]\nRegarder en haut en vue subjective\n\n[FEC_LDN]\nRegarder en bas en vue subjective\n\n[FEC_LBH]\nRegarder derrière le véhicule\n\n[FEC_LLF]\nRegarder à gauche du véhicule\n\n[FEC_LRG]\nRegarder à droite du véhicule\n\n[FEC_HRN]\nKlaxon\n\n[FEC_HBR]\nFrein à main\n\n[FEC_ACL]\nAccélérer\n\n[FEC_BRK]\nFreiner\n\n[FEC_TSM]\nActiver/Désactiver sous-missions\n\n[FEC_CRD]\nChanger la station de radio\n\n[FEC_ENT]\nEntrer/Sortir d'un véhicule\n\n[FEC_WPN]\nTirer\n\n[FEC_PAS]\nPause\n\n[FEC_FPO]\nChanger d'arme en vue subjective\n\n[FEC_SMS]\nAfficher/Masquer curseur\n\n[FEC_CMS]\nChanger de mode de caméra\n\n[FEC_TSS]\nFaire une capture d'écran\n\n[FEC_DBG]\nMenu Debug\n\n[FEC_TGD]\nAlterner manette jeu/debug\n\n[FEC_TDO]\nDésactiver caméra debug\n\n[FEC_IVH]\nInverser souris horizontale\n\n[FEC_MSL]\nBGS\n\n[FEC_MSM]\nBMS\n\n[FEC_MSR]\nBDS\n\n[FEC_QUE]\n???\n\n[FEC_TWO]\nDeux touches clavier au maximum\n\n[FEC_UMS]\nBoutons souris uniquement\n\n[FEC_OMS]\nUn bouton souris au maximum\n\n[FEC_UJS]\nUn bouton joystick au maximum\n\n[FEC_OJS]\nUn bouton joystick maximum par action\n\n[FEC_PTL]\nUtiliser verrouillage de cible avec commande de tir gauche\n\n[FEC_PTR]\nUtiliser verrouillage de cible avec commande de tir droite\n\n[FEC_LBC]\nUtiliser regarder gauche avec regarder droite\n\n[FEC_JBO]\nJOY ~1~\n\n[FEC_WAR]\nAvertissement\n\n[FEC_OKK]\nO.K.\n\n[FEC_DLF]\nErreur lors de suppression\n\n[FEC_SVU]\nErreur lors de la sauvegarde\n\n[FEC_LUN]\nErreur lors du chargement. Fichier corrompu, veuillez le supprimer.\n\n[FEC_PAD]\nManette\n\n[FEC_JOY]\nJoystick\n\n[FES_CSA]\nSélectionnez une apparence dans la liste suivante :\n\n[FET_HRD]\nPARAMETRES PAR DEFAUT RETABLIS\n\n[FET_MST]\nDIRECTION CONTROLEE PAR LA SOURIS\n\n[FEC_STR]\nETOILE PAV.NUM.\n\n[FET_MIG]\nGAUCHE, DROITE, MOLETTE SOURIS POUR REGLER\n\n[FET_CIG]\nRETOUR ARRIERE POUR EFFACER - BGS, RETOUR POUR CHANGER\n\n[FET_DSN]\nSkin joueur par defaut.bmp\n\n[FET_RSO]\nPARAMETRE D'ORIGINE RETABLI\n\n[FET_RSC]\nMATERIEL INDISPONIBLE - PARAMETRE D'ORIGINE RETABLI\n\n[FEA_3DH]\nCONFIG. CARTE-SON\n\n[FEA_SPK]\nCONFIG. HAUT-PARLEURS\n\n[FEM_LOD]\nDISTANCE MODELES\n\n[FEM_VSC]\nSYNCHRO VIDEO\n\n[FEM_FRM]\nRESTRICTION VIDEO\n\n[FEM_MM]\nMENU PRINCIPAL\n\n[FED_RES]\nRESOLUTION ECRAN\n\n[FET_CTL]\nCONFIG. PERIPHERIQUE\n\n[FET_OPT]\nOPTIONS\n\n[FEC_MSH]\nSENSIBILITE SOURIS\n\n[FEC_IVV]\nINVERSER SOURIS VERTIC.\n\n[FET_MTI]\nCONFIG. SOURIS\n\n[FEC_FNC]\nF~1~\n\n[FEC_IRT]\nINSER\n\n[FEC_DLL]\nSUPPR\n\n[FEC_HME]\nORIG\n\n[FEC_END]\nFIN\n\n[FEC_PGU]\nPAGE HAUT\n\n[FEC_PGD]\nPAGE BAS\n\n[FEC_UPA]\nHAUT\n\n[FEC_DWA]\nBAS\n\n[FEC_LFA]\nGAUCHE\n\n[FEC_RFA]\nDROITE\n\n[FEC_NUM]\nPAV.NUM\n\n[FEC_NMN]\nPAV.NUM~1~\n\n[FEC_FWS]\nPAV.NUM /\n\n[FEC_PLS]\nPAV.NUM +\n\n[FEC_MIN]\nPAV.NUM -\n\n[FEC_DOT]\nPAV.NUM .\n\n[FEC_NLK]\nVERR NUM\n\n[FEC_ETR]\nENTR\n\n[FEC_SLK]\nARRET DEFIL\n\n[FEC_PSB]\nPAUSE\n\n[FEC_BSP]\nRET. ARR.\n\n[FEC_TAB]\nTAB\n\n[FEC_CLK]\nVERR MAJ\n\n[FEC_RTN]\nRETOUR\n\n[FEC_LSF]\nMAJ. G\n\n[FEC_RSF]\nMAJ. D\n\n[FEC_LCT]\nCTRL G\n\n[FEC_RCT]\nCTRL D\n\n[FEC_LAL]\nALT G\n\n[FEC_RAL]\nALT D\n\n[FEC_LWD]\nWIN G\n\n[FEC_RWD]\nWIN D\n\n[FEC_WRC]\nCLIC WIN\n\n[FEC_SPC]\nESP\n\n[WIN_TTL]\nGrand Theft Auto VC\n\n[WIN_95]\nGrand Theft Auto VC n'est pas compatible WINDOWS 95\n\n[WIN_DX]\nGrand Theft Auto VC requiert la version 8.1 de DirectX minimum.\n\n[FET_EIG]\nIMPOSSIBLE DE PARAMETRER UNE TOUCHE POUR CETTE ACTION\n\n[FET_DAM]\nMODELAGE ACCOUST. DYNAMIQUE\n\n[FEQ_SRE]\nEtes-vous sûr de vouloir quitter ? Votre progression depuis la dernière sauvegarde sera perdue. Continuer ?\n\n[FEQ_SRW]\nEtes-vous sûr de vouloir quitter la partie ?\n\n[FET_QG]\nQUITTER PARTIE\n\n[FEN_STA]\nCOMMENCER PARTIE\n\n[FET_PAU]\nMENU PAUSE\n\n[REPLAY]\nRALENTI\n\n[FET_PS]\nCONFIG. JOUEURS\n\n[FEC_ANS]\nAction\n\n[CVT_MSG]\nConversion des textures vers un format optimal pour votre carte graphique\n\n[FEC_SFT]\nMAJ\n\n[FEH_VMP]\nVOIR CARTE\n\n[FES_DEE]\nEchec de la suppression ! Recommencer.\n\n[FES_CMP]\nEchec de la sauvegarde ! Recommencer.\n\n[FESZ_WR]\nSauvegarde en cours. Un instant...\n\n[FELD_WR]\nChargement en cours. Un instant...\n\n[FEDL_WR]\nSuppression en cours. Un instant...\n\n[PCRESRT]\nLancement d'une nouvelle partie. Un instant...\n\n[FET_STI]\nCommandes standard\n\n[FET_CTI]\nCommandes classiques\n\n[FEH_NA]\nOPTION NON DISPONIBLE\n\n[FEH_MPH]\nSOURIS, CURSEURS POUR SE DEPLACER - PAGE HAUT, PAGE BAS, MOLETTE POUR ZOOMER, L - LEGENDE\n\n[FEA_MP3]\nLECTEUR MP3\n\n[NO_PCCD]\nInsérer le disque de GTA Vice City ou appuyer sur ECHAP pour annuler\n\n[FEH_SSA]\nCURSEURS POUR SE DEPLACER - S POUR SAUVEGARDER LE FICHIER\n\n[FES_CMI]\nDERNIERE MISSION REUSSIE\n\n[FET_STS]\nSTATS SAUVEGARDEES DANS 'STATS.HTML' + 'STATS.TXT'\n\n[WIN_VDM]\nGrand Theft Auto VC ne dispose pas de suffisamment de mémoire graphique.\n\n[FEC_ERI]\nErreur ! Une ou plusieurs actions ne sont pas assignées à une touche ou à un bouton. Vérifier que toutes les actions sont bien assignées.\n\n[FEC_TFU]\nTourelle + Orienter haut\n\n[FEC_TFD]\nTourelle + Orienter bas\n\n[FET_RIG]\nCHOISIR UNE AUTRE COMMANDE POUR CETTE ACTION\n\n[FEA_NM3]\nAUCUN FICHIER MP3 TROUVE\n\n[FEA_MPB]\nVOLUME MP3 A FOND\n\n[FEA_MUS]\nVOLUME MUSIQUE\n\n[FEA_SFX]\nVOLUME EFFETS SONORES\n\n[CVT_ERR]\nEspace disque épuisé. Libérez de la mémoire sur votre disque dur pour continuer. Appuyez sur ECHAP pour annuler.\n\n[FEA_ADP]\nAUTODETECT MATERIEL\n\n{=================================== MISSION TABLE AMBULAE ===================================}\n\n[ATUTOR2:AMBULAE]\n~g~Conduis les patients à l'hôpital. DOUCEMENT. Chaque secousse réduit leurs chances de survie.\n\n[A_FULL:AMBULAE]\n~r~Ambulance pleine!\n\n[A_FAIL2:AMBULAE]\n~r~Ton manque de rapidité a été fatal pour le patient!\n\n[A_FAIL3:AMBULAE]\n~r~Le patient est mort!!\n\n[A_PASS:AMBULAE]\nSauvé!\n\n[A_COMP2:AMBULAE]\nTu ne seras plus jamais essoufflé!\n\n[A_COMP1:AMBULAE]\nMissions Ambulance réussies : $~1~\n\n[A_CANC:AMBULAE]\n~r~Mission ambulance annulée!\n\n[A_COMP3:AMBULAE]\nMissions ambulance accomplies! Maintenant, tu peux sprinter indéfiniment!\n\n[ALEVEL:AMBULAE]\nMission ambulance, niveau ~1~\n\n[A_FAIL1:AMBULAE]\nMission ambulance achevée.\n\n[A_SAVES:AMBULAE]\nPERSONNES SAUVEES : ~1~\n\n{=================================== MISSION TABLE ASSIN1 ===================================}\n\n[ASM1_5:ASSIN1]\n~r~Il a livré toutes ses pizzas!\n\n[ASM1_6:ASSIN1]\nLivraisons restantes :\n\n[ASM1_7:ASSIN1]\n~g~Carl Pearson, livreur de pizzas. Tue-le avant qu'il ne termine ses livraisons.\n\n[ASM1_D:ASSIN1]\nTon aide dans l'éradication de ces indésirables fut une excellente affaire.\n\n{=================================== MISSION TABLE ASSIN2 ===================================}\n\n[ASM2_1:ASSIN2]\n~g~Mme Dawson va bientôt quitter la bijouterie à Vice Point. Tue-la. Il faut que ça ressemble à un accident de voiture.\n\n[ASM2_3:ASSIN2]\n~g~Ca va sauter, écarte toi!\n\n[ASM2_4:ASSIN2]\n~r~T'as bousillé sa bagnole alors qu'elle était même pas dedans. Elle est pas près de l'utiliser, maintenant!\n\n[ASM2_5:ASSIN2]\n~r~Elle s'est enfuie!\n\n[ASM2_6:ASSIN2]\n~r~Tu étais trop près de l'accident!\n\n[ASM2_7:ASSIN2]\n~g~N'utilise pas d'armes! Il faut que ça ressemble à un accident! Sors-la plutôt de la route!\n\n[ASM2_8:ASSIN2]\n~g~La mort de madame Dawson doit avoir l'air d'un accident. N'utilise pas d'armes.\n\n[ASM2_9:ASSIN2]\n~g~Il te faut une voiture pour ce boulot!\n\n[ASM2_10:ASSIN2]\n~g~Quand sa bagnole prendra feu, éloigne-toi le plus possible du lieu de l'accident.\n\n[ASM2_11:ASSIN2]\nA l'aide!\n\n[ASM2_12:ASSIN2]\nQue quelqu'un m'aide!\n\n[ASM2_13:ASSIN2]\nOh non!\n\n[ASM2_A:ASSIN2]\nMes félicitations pour ce travail bien fait, Mr. Teal. Mon client était ravi.\n\n[ASM2_2:ASSIN2]\nSanté :\n\n{=================================== MISSION TABLE ASSIN3 ===================================}\n\n[ASM3_11:ASSIN3]\nTEMPS :\n\n[ASM3_C:ASSIN3]\nUn gang européen prépare un braquage de banque à Vice City. Mes employeurs préfèreraient que cela n'arrive pas.\n\n[ASM3_D:ASSIN3]\nChaque membre du gang dispose d'une couverture à Vice City. Certains ont des petits boulots, d'autres jouent les touristes.\n\n[ASM3_E:ASSIN3]\nChaque cible et leur position probable sont indiqués sous le téléphone.\n\n[ASM3_14:ASSIN3]\n~g~Dick Tanner est à côté de DBP Security sur Ocean Drive.\n\n[ASM3_15:ASSIN3]\n~g~Marcus Hammond et Franco Carter sont près de la bijouterie de Vice Point.\n\n[ASM3_16:ASSIN3]\n~g~Nick Kong est à côté de Washington Beach.\n\n[ASM3_18:ASSIN3]\n~g~Ne t'approche pas trop près de la cible où elle risque de te repérer et d'essayer de se faire la malle!\n\n[ASM3_19:ASSIN3]\n~g~Il t'a repéré! Bute-le!\n\n[ASM3_20:ASSIN3]\n~g~Ils t'ont repéré! Tue-les vite tous les deux!\n\n[ASM3_21:ASSIN3]\n~r~Tu n'as pas tué tous les membres du gang à temps!\n\n[ASM3_22:ASSIN3]\n~g~Ne t'approche pas trop des cibles ou elles risquent de te repérer et d'essayer de filer.\n\n[ASM3_12:ASSIN3]\n~g~Des armes ont été laissées à ta disposition dans le coin si tu en as besoin. Tu as ~h~9 MINUTES ~g~pour tuer tous les membres du gang.\n\n[ASM3_13:ASSIN3]\n~g~Mike Griffin travaille sur un panneau publicitaire à Washington.\n\n[ASM3_17:ASSIN3]\n~g~Charlie Dilson est à moto sur Washington.\n\n{=================================== MISSION TABLE ASSIN4 ===================================}\n\n[ASM4_12:ASSIN4]\nDistance :\n\n[ASM4_15:ASSIN4]\n~g~Prends le fusil à lunette sur ta droite.\n\n[ASM4_16:ASSIN4]\n~g~Observe la femme au balcon. Elle va descendre l'escalator et demander l'heure à quelqu'un.\n\n[ASM4_17:ASSIN4]\n~g~Lorsque la conversation est terminée, liquide son interlocuteur sans faire de mal à la femme.\n\n[ASM4_18:ASSIN4]\n~g~Une fois la cible éliminée, récupère la serviette et amène-la à Ammu-Nation dans le centre.\n\n[ASM4_19:ASSIN4]\n~g~Reste à distance de la cible. Sa proximité t'est indiquée par la barre de distance située dans le coin supérieur droit de l'écran.\n\n[ASM4_20:ASSIN4]\n~g~Ne la laisse pas devenir pleine ou tu seras repéré.\n\n[ASM4_21:ASSIN4]\n~g~Récupère la serviette!\n\n[ASM4_22:ASSIN4]\n~g~Ramène la serviette à Ammu-Nation dans le centre.\n\n[ASM4_23:ASSIN4]\n~g~Il t'a repéré et s'enfuit. Rattrape-le et récupère la serviette!\n\n[ASM4_25:ASSIN4]\n~r~T'as buté la femme, imbécile!\n\n[ASM4_26:ASSIN4]\n~r~La cible a embarqué pour son vol!\n\n[ASM4_27:ASSIN4]\n~r~La cible t'a repéré! Tu devais garder tes distances!\n\n[ASM4_28:ASSIN4]\n~r~La cible t'a repéré! Elle t'a entendu tirer!\n\n[ASM4_29:ASSIN4]\n~r~Ne le tue qu'après qu'il ait parlé à la femme!\n\n[ASM4_A:ASSIN4]\nL'heure est venue de s'occuper d'un gros poisson, M. Teal. Il y a un fusil dans le feuillage à votre droite.\n\n[ASM4_B:ASSIN4]\nSurveillez la femme sur le balcon situé au-dessus des guichets d'enregistrement. Elle va avancer à travers la foule et demander l'heure à quelqu'un.\n\n[ASM4_C:ASSIN4]\nVous devez tuer son interlocuteur, récupérer la mallette et l'apporter à l'emplacement indiqué sous le téléphone.\n\n{=================================== MISSION TABLE ASSIN5 ===================================}\n\n[ASM5_A:ASSIN5]\nUn deal important se déroule sur le toit de l'usine de crème glacée Cherry Popper.\n\n[ASM5_B:ASSIN5]\nDescendez toutes les personnes impliquées, embarquez la marchandise et amènez-la à la piste pour hélicos de l'aéroport.\n\n[ASM5_C:ASSIN5]\nIl y a une porte sur votre gauche qui mène à l'arrière de l'usine.\n\n[ASM5_1:ASSIN5]\n~g~Entre dans l'enceinte située derrière l'usine de crème glacée Cherry Popper et va jusqu'au toit où se fait le deal.\n\n[ASM5_2:ASSIN5]\n~g~Récupère la marchandise et amène-la à la piste pour hélicos de l'aéroport.\n\n[ASM5_3:ASSIN5]\n~g~Emmène la marchandise à la piste pour hélicos de l'aéroport!\n\n{=================================== MISSION TABLE BANKJ1 ===================================}\n\n[WANTED1:BANKJ1]\n~g~Largue les flics et perds ton indice de recherche!\n\n[BJM1_A:BANKJ1]\nTommy! Hé, regarde-ça, c'est génial! J'ai fait installer un minibar!\n\n[BJM1_B:BANKJ1]\nY'a déjà un vrai bar en bas, Ken.\n\n[BJM1_C:BANKJ1]\nOuais, je sais, et alors? Bon, j'ai le tableau noir que tu m'as demandé.\n\n[BJM1_D:BANKJ1]\nAh, c'est là qu'on voit l'intérêt de ton école de droit : t'as appris à suivre les instructions.\n\n[BJM1_E:BANKJ1]\nBon, il me faut un mec sûr.\n\n[BJM1_F:BANKJ1]\nEuh, d'accord, laisse-moi réfléchir... Sûr... sûr... sûr... Je sais! Je connais un mec qui te plaira!\n\n[BJM1_G:BANKJ1]\nAaah, non, merde, ce con est au trou.\n\n[BJM1_H:BANKJ1]\nComment ça au trou?\n\n[BJM1_I:BANKJ1]\nDans un poste de police. Il attend son transfert.\n\n[BJM1_J:BANKJ1]\nJe crois qu'il va être remis en liberté sur parole...\n\n[BJM1_1:BANKJ1]\n~g~Sors Cam Jones de chez les flics!\n\n[BJM1_3:BANKJ1]\n~g~Tu trouveras quelque chose d'utile dans la salle des casiers.\n\n[BJM1_21:BANKJ1]\n~g~La carte d'accès aux cellules se trouve à l'étage.\n\n[BNK1_7:BANKJ1]\nCam Jones?\n\n[BNK1_8:BANKJ1]\nJe viens t'aider à mettre les bouts!\n\n[BNK1_10:BANKJ1]\nOuais, c'est moi...\n\n[BNK1_11:BANKJ1]\nCa me va!\n\n[BNK1_13:BANKJ1]\nJ'ai un boulot à faire et t'es mon perceur de coffre.\n\n[BNK1_14:BANKJ1]\nMarre de perdre mon temps dans une cellule.\n\n[BJM1_22:BANKJ1]\n~g~Ramène Cam chez lui!\n\n[BJM1_23:BANKJ1]\n~g~Tu dois d'abord trouver la carte d'accès!\n\n[BNK1_12:BANKJ1]\nSème les flics et ramène-moi chez moi!\n\n[BJM1_20:BANKJ1]\nJette ton flingue ou tu vas en subir les conséquences!\n\n[BJM1_5:BANKJ1]\nAccès réservé au personnel autorisé!\n\n[BJM1_2:BANKJ1]\n~r~T'étais supposé faire sortir Cam, pas le faire tuer!\n\n[BJM1_4:BANKJ1]\nIl est armé! Descendez-le!\n\n{=================================== MISSION TABLE BANKJ2 ===================================}\n\n[BJM2_A:BANKJ2]\nIl nous faut un braqueur. T'en connais un?\n\n[BJM2_B:BANKJ2]\nHé, Tommy, Tommy, ce truc ça permet d'rester dans l'coup, mec!\n\n[BJM2_C:BANKJ2]\nWoooOOOooo!\n\n[BJM2_D:BANKJ2]\nJ'pourrais être ton braqueur! Haut les mains! Haut les mains!\n\n[BJM2_E:BANKJ2]\nT'es pas un braqueur, t'es un idiot.\n\n[BJM2_F:BANKJ2]\nVa boire un verre et ferme-la.\n\n[BJM2_G:BANKJ2]\nHé, tire-toi de mon chemin! Ye ye ye ow ow!\n\n[BJM2_H:BANKJ2]\nCam, qu'est-ce que t'en penses?\n\n[BJM2_I:BANKJ2]\nBen, le meilleur tireur de cette ville, c'est un mec qui s'appelle Cassidy.\n\n[BJM2_J:BANKJ2]\nAh ouais?\n\n[BJM2_K:BANKJ2]\nOuais. Un militaire ou en tout cas c'est ce qu'il croit.\n\n[BJM2_L:BANKJ2]\nJe doute qu'il ait jamais été dans l'armée, mais il sait sûrement où dégotter des flingues.\n\n[BJM2_M:BANKJ2]\nIl devrait être au champ de tir.\n\n[BJM2_2A:BANKJ2]\nC'est toi, Phil Cassidy?\n\n[BJM2_2B:BANKJ2]\nPourquoi?\n\n[BJM2_2C:BANKJ2]\nJe cherche un mec qui sache se servir d'un flingue. D'après ce que je vois, j'suis pas convaincu...\n\n[BJM2_2D:BANKJ2]\nMon pote, je peux dégomme une mouche sur ta tête à 25 mètres!\n\n[BJM2_2E:BANKJ2]\nVraiment?\n\n[BJM2_2F:BANKJ2]\nOuais. J'ai appris ça à l'armée.\n\n[BJM2_2G:BANKJ2]\nIls s'amusent souvent à descendre des mouches à l'armée? Heureusement que je paye pas d'impôts!\n\n[BJM2_2H:BANKJ2]\nTu t'crois marrant peut-être, minus?\n\n[BJM2_2I:BANKJ2]\nHa ha ha ha ha!\n\n[BJM2_2J:BANKJ2]\nTirons quelques coups.\n\n[BJM2_1:BANKJ2]\n~g~Va à Ammu-Nation dans le centre et parle à Phil Cassidy.\n\n[BJM2_4:BANKJ2]\nSCORE MANCHE 1 : ~1~\n\n[BJM2_6:BANKJ2]\nSCORE MANCHE 2 : ~1~\n\n[BJM2_7:BANKJ2]\nSCORE TOTAL : ~1~\n\n[BJM2_9:BANKJ2]\n~g~Va au point de départ de la deuxième manche.\n\n[BJM2_11:BANKJ2]\n~r~Phil est mort!\n\n[BJM2_12:BANKJ2]\n~r~Un des tireurs est mort!\n\n[BJM2_14:BANKJ2]\n~g~Continue jusqu'au prochain secteur!\n\n[BJM2_17:BANKJ2]\n~g~Va parler à Phil.\n\n[BJM2_24:BANKJ2]\n~g~La cible la plus proche rapporte un point.\n\n[BJM2_25:BANKJ2]\n~g~La cible intermédiaire rapporte deux points.\n\n[BJM2_27:BANKJ2]\n~g~Toutes les cibles de cette manche rapportent un point.\n\n[BNK2_4:BANKJ2]\nWaou!\n\n[BNK2_5:BANKJ2]\nIl raterait une vache dans un couloir!\n\n[BNK2_7:BANKJ2]\nBon, tu veux bien me rendre un service et m'assister sur un boulot?\n\n[BNK2_8:BANKJ2]\nMon gars, vu comment tu tires, si tu me demandes en mariage, j'accepte.\n\n[BNK2_9A:BANKJ2]\nMon gars, tu ferais mieux de remballer ton baratin et tes grands projets. T'es trop mauvais tireur.\n\n[BNK2_9B:BANKJ2]\nT'es trop mauvais tireur.\n\n[BJM2_28:BANKJ2]\nSCORE MANCHE TROIS : ~1~\n\n[BJM2_26:BANKJ2]\n~g~La cible éloignée rapporte trois points.\n\n[BNK2_1:BANKJ2]\nBALLES REELLES\n\n[RANGE_1:BANKJ2]\nSCORE POUR LE TIR : ~1~\n\n[BJM2_2:BANKJ2]\n~g~Pour quitter la manche, appuie sur la ~h~~k~~PED_JUMPING~.\n\n[BJM2_N:BANKJ2]\nDu calme...\n\n{=================================== MISSION TABLE BANKJ3 ===================================}\n\n[BJM3_A:BANKJ3]\nLes choses commencent à se mettre tranquillement en place, ici.\n\n[BJM3_B:BANKJ3]\nC'est quoi le plan, Tommy? Que pasa, amigo?\n\n[BJM3_C:BANKJ3]\nLe plan, c'est que toi, tu restes ici à glander. Bon, on a besoin d'un chauffeur.\n\n[BJM3_D:BANKJ3]\nTommy, je m'en charge! Je peux conduire.\n\n[BJM3_E:BANKJ3]\nC'est Hilary que tu veux, mec! Pas un stupide vantard d'école de droit.\n\n[BJM3_F:BANKJ3]\nHilary, c'est le meilleur. T'as jamais vu quelqu'un conduire aussi vite. Je vais l'appeler.\n\n[BJM3_G:BANKJ3]\nSalut, Hil, c'est Phil. Comment ça va? Non, attends, on causera plus tard, j'ai besoin que tu me rendes un service.\n\n[BJM3_H:BANKJ3]\nJ'ai avec moi un mec du nord. Non, je crois pas qu'il était dans l'armée, mais il a besoin d'un conducteur.\n\n[BJM3_I:BANKJ3]\nPour un peu d'adrénaline. Ok, compris.\n\n[BJM3_J:BANKJ3]\nQu'est-ce qu'il a dit?\n\n[BJM3_K:BANKJ3]\nBon, il marche, pas de problème. En fait, y'a juste un détail, tu vois, il pose toujours une condition.\n\n[BJM3_L:BANKJ3]\nIl refuse de bosser pour quelqu'un qui ne peut pas le battre. Un truc à cause de sa mère.\n\n[BJM3_M:BANKJ3]\nQuoi qu'il en soit, il veut t'affronter d'abord et il a dit qu'il te retrouvait dehors...\n\n[BJM3_2A:BANKJ3]\nC'est toi Tommy? Evidemment que c'est toi Tommy, enfin, je veux dire,\n\n[BJM3_2B:BANKJ3]\npourquoi est-ce que quelqu'un d'autre parlerait avec moi?\n\n[BJM3_2C:BANKJ3]\nBon. Ecoute-moi.\n\n[BJM3_2D:BANKJ3]\nJe conduis pour toi que SI, et seulement SI, tu peux conduire convenablement.\n\n[BJM3_2E:BANKJ3]\nAbandonne et je ne te pardonnerai jamais.\n\n[BJM3_2:BANKJ3]\n~r~Hilary est mort!\n\n[BJM3_4:BANKJ3]\n~g~T'as besoin d'une voiture!\n\n[BNK3_1:BANKJ3]\nOk, je piloterai pour toi, mais s'il te plaît, traite-moi mal.\n\n[BNK3_3A:BANKJ3]\nCourse de rue illégale dans Vice Point!\n\n[BNK3_3B:BANKJ3]\nAppel à tous les officiers.\n\n[BNK3_3C:BANKJ3]\nLes courses de rue sont formellement interdites!\n\n{=================================== MISSION TABLE BANKJ4 ===================================}\n\n[BNK4_A:BANKJ4]\n~w~Comme vous pouvez voir, les mecs, ça va être le fric le plus facile qu'on se soit jamais fait!\n\n[BNK4_B:BANKJ4]\n~w~Tommy, sérieusement, va falloir que tu considères la question judiciaire.\n\n[BNK4_C:BANKJ4]\n~w~Merde! Qu'est-ce que tu fumes, mon pote? J'appelle pas ça un plan!\n\n[BNK4_D:BANKJ4]\n~w~Bon, de toute manière, on a pas besoin de plan!\n\n[BNK4_E:BANKJ4]\n~w~Prenez le communisme, ça c'était un plan! Et regarde où en est la Russie, maintenant!\n\n[BNK4_F:BANKJ4]\n~w~Du calme, Ok? Avec une équipe comme ça, il n'y aura pas le moindre problème!\n\n[BNK4_G:BANKJ4]\n~w~On amène Cam au coffre. Phil, toi et moi, on s'occupe de la sécurité et Hilary conduit la bagnole.\n\n[BNK4_H:BANKJ4]\n~w~Hum, euh, t'oublies pas quelqu'un? Quelqu'un qui t'aurait aidé depuis le début dans cette ville? Quelqu'un...\n\n[BNK4_I:BANKJ4]\n~w~Ken... Ken, c'est vrai. Bon, Ken va s'occuper de blanchir le pognon et de garder les boissons au frais!\n\n[BNK4_J:BANKJ4]\n~w~Je comprends pas ce que je suis supposé faire ici.\n\n[BNK4_K:BANKJ4]\n~w~Ecoute, c'est dans la poche. T'as jamais vu de film?\n\n[BNK4_L:BANKJ4]\n~w~On entre dans la banque, on sort nos flingues et on ressort plein aux as!\n\n[P_DEAD:BANKJ4]\n~r~Phil est mort!\n\n[C_DEAD:BANKJ4]\n~r~Cam est mort!\n\n[H_DEAD:BANKJ4]\n~r~Hilary est mort!\n\n[P_HIND:BANKJ4]\n~r~T'as perdu Phil!\n\n[C_HIND:BANKJ4]\n~r~T'as oublié Cam!\n\n[H_HIND:BANKJ4]\n~r~Hilary est resté derrière!\n\n[GETCAR:BANKJ4]\n~g~Monte dans la bagnole pour terminer le boulot!\n\n[TRASHED:BANKJ4]\n~r~T'as détruit la bagnole pour s'enfuir!\n\n[BNK4_1:BANKJ4]\nJe vais conduire.\n\n[BNK4_2:BANKJ4]\nSuper. Un passager. Attends que j'en parle à la réunion!\n\n[BNK4_3A:BANKJ4]\nHé, fais gaffe à la caisse, Tommy!\n\n[BNK4_3B:BANKJ4]\nTommy, Hilary prend trop de place!\n\n[BNK4_3C:BANKJ4]\nC'est pas vrai!\n\n[BNK4_3D:BANKJ4]\nToi aussi!\n\n[BNK4_3E:BANKJ4]\nHé, fermez-la tous les deux ou vous rentrez à pied!\n\n[BNK4_3F:BANKJ4]\nOuais, Hilary.\n\n[BNK4_3I:BANKJ4]\nPutain, Phil! Arrête d'agiter ce truc devant moi!\n\n[BNK4_3J:BANKJ4]\nOuais, tu vas éborgner quelqu'un!\n\n[BNK4_3M:BANKJ4]\nMon bébé! Elle est foutue!\n\n[BNK4_3O:BANKJ4]\nTu t'accroches à l'illusion de la permanence!\n\n[BNK4_3P:BANKJ4]\nQuoi?!\n\n[BNK4_3Q:BANKJ4]\nTu crois que toutes les choses dureront!\n\n[BNK4_3R:BANKJ4]\nLa jeunesse, les amours, les pizzas...\n\n[BNK4_3S:BANKJ4]\nTout prend fin un jour, et tu dois l'accepter.\n\n[BNK4_3T:BANKJ4]\nOuais, t'as raison, merci, Cam.\n\n[BNK4_3U:BANKJ4]\nDe rien.\n\n[BNK4_3V:BANKJ4]\nHé, Tommy, pourquoi on s'arrête?\n\n[BNK4_4A:BANKJ4]\n~w~Hilary, continue à tourner autour du quartier.\n\n[BNK4_5:BANKJ4]\n~w~Ok, Tommy, ok.\n\n[BNK4_6:BANKJ4]\n~w~C'EST UN HOLD-UP!\n\n[BNK4_7:BANKJ4]\n~w~PERSONNE NE BOUGE!\n\n[BNK4_8:BANKJ4]\n~w~TOUT LE MONDE CONTRE LE MUR!\n\n[BNK4_9:BANKJ4]\nPhil! Monte la garde!\n\n[BNK4_10:BANKJ4]\nBien compris!\n\n[BNK4_11:BANKJ4]\nAmène-toi, Cam, la salle des coffres est en haut...\n\n[BK4_12A:BANKJ4]\nMerde! C'est un Flange 9000!\n\n[BK4_12B:BANKJ4]\nCa peut prendre des heures à ouvrir,\n\n[BK4_12C:BANKJ4]\nou cinq minutes si tu peux trouver le directeur...\n\n[BNK4_13:BANKJ4]\nJe vais aller voir où il se planque.\n\n[BK4_14A:BANKJ4]\nCa roule, Phil?\n\n[BNK4_15:BANKJ4]\nPas de problème. Tout le monde se tient relax.\n\n[BNK4_16:BANKJ4]\nToi! Tu viens avec moi!\n\n[BNK4_17:BANKJ4]\nD'accord! D'accord! Ne tirez pas!\n\n[BNK4_18:BANKJ4]\nJ'AI DIT PERSONNE NE BOUGE!\n\n[BK4_19A:BANKJ4]\nC'est réglé sur une serrure à horloge,\n\n[BK4_19B:BANKJ4]\nVous feriez aussi bien d'abandonner tout de suite!\n\n[BK4_20A:BANKJ4]\nPutain, je peux court-circuiter l'horloge,\n\n[BK4_20B:BANKJ4]\non a juste besoin de ton code secret et c'est bingo!\n\n[BNK4_21:BANKJ4]\nReste ici. T'essayes quoi que ce soit et t'es mort! Pigé?\n\n[BK4_24A:BANKJ4]\nJe vais voir Phil, je reviens tout de suite.\n\n[BK4_24B:BANKJ4]\nJe t'avais dit de pas toucher à cette alarme!\n\n[BNK4_25:BANKJ4]\nLe commando du SWAT sera là d'une minute à l'autre!\n\n[BNK4_27:BANKJ4]\nJ'aurais besoin d'un coup de main, Tommy!\n\n[BNK4_28:BANKJ4]\nIci le SWAT de Vice City! Vous êtes complètement encerclés!\n\n[BNK4_29:BANKJ4]\nEncerclés? HA HA HA HAAAAAaaa!\n\n[BNK4_30:BANKJ4]\nIls racontent que des conneries, ces ripoux!\n\n[BK4_31A:BANKJ4]\nTommy! La salle des coffres est ouverte!\n\n[BK4_34A:BANKJ4]\nOk, on a la caisse de retraite du SWAT! Tirons-nous de là!\n\n[BK4_34B:BANKJ4]\nBon, vous l'aurez cherché! C'était votre dernière chance!\n\n[BK4_35A:BANKJ4]\nIls lancent l'assaut!\n\n[BK4_35B:BANKJ4]\nPlanquez-vous!\n\n[BNK4_36:BANKJ4]\nOù est Cam?\n\n[BNK4_37:BANKJ4]\nDu passé...\n\n[BNK4_38:BANKJ4]\nC'était le dernier! On dégage! Allez!\n\n[BNK_39:BANKJ4]\nMerde! Où est Hilary?\n\n[BK4_40A:BANKJ4]\nIl me payera ça!\n\n[BNK4_42:BANKJ4]\nHé! Les mecs! Montez! Je vous couvre!\n\n[BNK4_44:BANKJ4]\nOn a réussi! On est riches! RICHES!\n\n[BNK4_45:BANKJ4]\nDommage que Cam y soit resté, c'était un mec réglo!\n\n[BNK4_46:BANKJ4]\nOuais. Enfin... On hérite de sa part!\n\n[BNK4_47:BANKJ4]\nTu l'as dit! Ouais!\n\n[BNK4_48:BANKJ4]\nTommy, que dirais-tu d'un massage?\n\n[BNK4_49:BANKJ4]\nSalut, Mercedes! Ouais, pourquoi pas, je me sens un peu tendu...\n\n[BNK450A:BANKJ4]\nQu'est-ce que je te disais, Tommy? Hein, quoi? Le SWAT a du souci à se faire quand Kent Paul est en ville.\n\n[BNK450B:BANKJ4]\nAllez, allonge une plus grosse part, mon pote, j'ai besoin de nouvelles fringues!\n\n[BNK4_94:BANKJ4]\n~w~Ok, les mecs. Tout roule comme prévu.\n\n[BM_DEAD:BANKJ4]\n~r~T'avais besoin du directeur vivant!\n\n[ASSET_A:BANKJ4]\nBRAQUAGE DE BANQUE OK!\n\n[ASSET_B:BANKJ4]\n~g~Le Malibu Club génère dorénavant un revenu de $~1~ maximum. Pense à récupérer le fric régulièrement.\n\n[IDIOT:BANKJ4]\n~r~T'as raison, trimballe-toi déguisé en malade pour attirer l'attention! Espèce d'abruti!\n\n{=================================== MISSION TABLE BARON1 ===================================}\n\n[COK1_A:BARON1]\nAllez, sale carne, allez! Allez! Putain...\n\n[COK1_B:BARON1]\nConnard de cheval! Je te ferai décapiter!\n\n[COK1_C:BARON1]\nC'est qui ce con?\n\n[COK1_D:BARON1]\nTommy Vercetti, vous vous souvenez de moi?\n\n[COK1_E:BARON1]\nExcuse-moi, mais j'suis un peu enervé. Fais jamais confiance à une saloperie de canasson!\n\n[COK1_F:BARON1]\nTu fais du bon boulot. Maintenant, tu travailles pour moi.\n\n[COK1_H:BARON1]\nComme je disais, amigo, tu bosses pour moi. Maintenant, la ferme! Un salopard m'a trahi!\n\n[COK1_I:BARON1]\nIl croit que je sais pas combien de pognon je devrais gagner... Mais me faucher 3%, c'est pareil que d'me faucher 100%!\n\n[COK1_J:BARON1]\nPersonne ne me fait ça! PERSONNE!\n\n[COK1_K:BARON1]\nTu vas le suivre depuis son appart' pour voir où il va! On le descendra plus tard.\n\n[COK1_1:BARON1]\nOh merde!\n\n[COK1_2:BARON1]\nUn peu trop lent, papi!\n\n[COK1_4:BARON1]\nPauv' mec.\n\n[COK1_5:BARON1]\nTu ferais mieux de continuer à courir, connard!\n\n[COK1_8:BARON1]\n~g~Vite! Grimpe dans une caisse et suis-le!\n\n[COK1_9:BARON1]\n~r~Tu es supposé le suivre, pas le buter!\n\n[COK1_10:BARON1]\n~r~Va à la maison des voleurs et trouve où il planque le fric!\n\n[COK1_11:BARON1]\n~g~Regarde par cette fenêtre.\n\n[COK1_7:BARON1]\n~g~Il s'est échappé vers le toit. Suis-le mais ne le tue pas!\n\n[COK1_G:BARON1]\nJe travaille pour du fric.\n\n{=================================== MISSION TABLE BARON2 ===================================}\n\n[COK2_V:BARON2]\nIl commence à me faire confiance...\n\n[COK2_A:BARON2]\nQui c'est qui m'a foutu un con pareil!\n\n[COK2_B:BARON2]\nCON! CON! CON! CON!\n\n[COK2_C:BARON2]\nTommy -\n\n[COK2_D:BARON2]\nQuoi, Ricardo?\n\n[COK2_E:BARON2]\nCes merdeux, faut toujours qu'ils essayent de m'baiser...\n\n[COK2_F:BARON2]\nC'est le problème avec ce genre de biz...\n\n[COK2_G:BARON2]\nQu'est-ce que tu fous toi?\n\n[COK2_H:BARON2]\nCes connards m'ont vraiment manqué de respect.\n\n[COK2_I:BARON2]\nBientôt, le premier connard venu va penser qu'il peut vendre de la dope à Vice City.\n\n[COK2_J:BARON2]\nEt ensuite, ça sera quoi? Ces pourris de la Mafia, hein?\n\n[COK2_K:BARON2]\nLe Q.G. de ce gang est une vrai forteresse au rez-de-chaussée,\n\n[COK2_L:BARON2]\nalors Quentin ici... Quentin! QUENTIN!\n\n[COK2_M:BARON2]\nIl va te faire survoler la zone!\n\n[COK2_N:BARON2]\nLiquide-les!\n\n[COK2_O:BARON2]\nQu'est-ce que tu fous toi?\n\n[COK2_P:BARON2]\nQu'est-ce que tu fous ici?\n\n[COK2_Q:BARON2]\nHé, je me suis un peu renseigné et c'est sûr\n\n[COK2_R:BARON2]\nque c'est Diaz qui a bousillé le deal et refroidi mon frère!\n\n[COK2_S:BARON2]\nEt il va t'buter toi aussi!\n\n[COK2_T:BARON2]\nJe peux me faire Diaz!\n\n[COK2_U:BARON2]\nNon, écoute-moi! JE m'occupe de Diaz!\n\n[COK2_1:BARON2]\nIl y a un truc que j'pige pas, pourquoi 'Quentin'?\n\n[COK2_2:BARON2]\nJe sais pas, ça sonne bien... Quentin Vance...\n\n[COK2_3:BARON2]\nVance? Tu t'appelles Lance Vance?\n\n[COK2_4:BARON2]\nCa va, hein! J'en ai déjà eu pour mon compte à l'école!\n\n[COK2_5:BARON2]\nT'as déjà tiré depuis un hélico?\n\n[COK2_8:BARON2]\nOn va où, au fait?\n\n[COK2_9:BARON2]\nPrawn Island.\n\n[COK2_13:BARON2]\nLance Vance. Mon pauv' vieux...\n\n[COK2_14:BARON2]\nOk, on y est presque.\n\n[COK2_15:BARON2]\nOn va faire un ou deux passages,\n\n[COK2_16:BARON2]\nAlors, descends autant de tireurs que tu peux.\n\n[COK2_17:BARON2]\nEt puis je te dépose et tu te débrouilles tout seul.\n\n[COK2_20:BARON2]\nMerde, c'est la guerre en bas! Descends ces tireurs!\n\n[COK2_21:BARON2]\nOn s'fait canarder, mec!\n\n[COK2_22:BARON2]\nCa coûte un max de réparer c'coucou, alors bute-les!\n\n[COK2_23:BARON2]\nBon, t'es tout seul à partir de là. Bonne chance, mon frère!\n\n[COK2_24:BARON2]\nEtat hélico :\n\n[COK2_25:BARON2]\n~g~Va récupérer le pognon sur le toit.\n\n[COK2_27:BARON2]\nT'es sur MES plates-bandes, connard!\n\n[COK2_28:BARON2]\nTa fin est proche!\n\n[COK2_6:BARON2]\nNon. Je vais m'entraîner un peu en chemin.\n\n[OPEN_B:BARON2]\nLes barrières sur les routes pour le centre ville ont été retirées.\n\n{=================================== MISSION TABLE BARON3 ===================================}\n\n[COK3_A:BARON3]\nTu fais moins le fier maintenant, hein!\n\n[COK3_B:BARON3]\nAhahahaha, ahahahaha!\n\n[COK3_C:BARON3]\nHo! Fais gaffe où tu braques ce truc!\n\n[COK3_D:BARON3]\nPlus de merde de pigeon sur ma bagnole, hein, Tommy!\n\n[COK3_E:BARON3]\nFaut croire que non...\n\n[COK3_F:BARON3]\nT'as sacrément raison. Bon, écoute,\n\n[COK3_G:BARON3]\ntu sais qui possède le bateau le plus rapide de la côte est?\n\n[COK3_H:BARON3]\nJe suis pas bien sûr.\n\n[COK3_I:BARON3]\nMOI! Et je voudrais pas que ça change...\n\n[COK3_J:BARON3]\nTous les contrebandiers d'ici à Caracas ne rêvent que d'un seul truc, un bateau plus rapide que le mien.\n\n[COK3_K:BARON3]\nEt la rumeur prétend que le chantier naval Hull-o-caust vient juste d'en finir un\n\n[COK3_L:BARON3]\npour le compte de je ne sais quel connard du Costa Rica.\n\n[COK3_M:BARON3]\nAlors, Tommy... JE VEUX CE BATEAU!\n\n[COK3_N:BARON3]\nJe crois que tes pigeons sont de retour...\n\n[COK3_O:BARON3]\nAh! Je croyais que je t'avais eu! D'où tu sors?\n\n[COK3_P:BARON3]\nPigeons d'mes deux! Boum! Aaaaah!\n\n[COK3_5:BARON3]\n~g~Trouve l'interrupteur pour abaisser le bateau.\n\n[COK3_6:BARON3]\n~g~Amène le bateau à la résidence.\n\n[COK3_7:BARON3]\n~r~T'as détruit le bateau!\n\n[COK3_8:BARON3]\n~g~Va au chantier naval des docks et fauche le bateau le plus rapide.\n\n[COK3_9:BARON3]\n~g~Monte dans le bateau.\n\n{=================================== MISSION TABLE BARON4 ===================================}\n\n[COK4_A:BARON4]\nEjection! Connerie d'engin!\n\n[COK4_B:BARON4]\nPourquoi tu m'fais ça?\n\n[COK4_C:BARON4]\nPour qui tu t'prends, putain de magnéto! Grrr!\n\n[COK4_D:BARON4]\nENCULE!\n\n[COK4_E:BARON4]\nSi il m'bouffe ma cassette préférée d'El burro, il est fini!\n\n[COK4_F:BARON4]\nQu'est-ce que je peux faire d'autre?\n\n[COK4_G:BARON4]\nIl doit pas être branché, c'est tout...\n\n[COK4_H:BARON4]\nHein?\n\n[COK4_I:BARON4]\nMerde! Tant pis, j'peux m'en acheter cent si ça me chante.\n\n[COK4_J:BARON4]\nBon, Tommy,\n\n[COK4_K:BARON4]\ntous les mois, il y a un indépendant qui met le cap sur Vice City pour y amarrer son yatch.\n\n[COK4_L:BARON4]\nIl vend sa cargaison au premier bateau.\n\n[COK4_M:BARON4]\nJe veux que tu prennes le speedboat,\n\n[COK4_N:BARON4]\nque tu largues tous les autres connards intéressés\n\n[COK4_O:BARON4]\net que tu ramènes la cargaison ici. Ok?\n\n[COK4_P:BARON4]\nLaisse-moi deviner. T'as pensé que je pourrais avoir besoin d'un ange-gardien.\n\n[COK4_Q:BARON4]\nJe dis juste que t'as intérêt à me laisser entrer, mon pote.\n\n[COK4_R:BARON4]\nTu peux m'sortir tout un tas de conneries sur le dur solitaire,\n\n[COK4_S:BARON4]\nmais je sais qu'un de ces quatre, j'vais t'sauver la mise.\n\n[COK4_T:BARON4]\net qu'après tu voudras me rouler une pelle!\n\n[COK4_U:BARON4]\nTaré, va!\n\n[COK4_V:BARON4]\nHahahaha\n\n[COK4_1:BARON4]\nTommy, on sait que c'est Diaz qui a fait foirer notre deal...\n\n[COK4_3:BARON4]\nAlors pourquoi on bosse pour sa gueule?\n\n[COK4_4:BARON4]\nPlus on en apprend maintenant, plus on en saura quand on s'emparera de cette ville!\n\n[COK4_5:BARON4]\nJ'aime bien ton style, mon pote. Vraiment culotté.\n\n[COK4_12:BARON4]\nFais gaffe, ils arrivent de partout!\n\n[COK4_13:BARON4]\nOn les a eu! Fonce chez Diaz aussi vite que tu peux!\n\n[COK4_14:BARON4]\nTu veux ta part de plancton?\n\n[COK4_15:BARON4]\nSalue la poiscaille de ma part!\n\n[COK4_16:BARON4]\nMange! Mange!\n\n[COK4_19:BARON4]\nEncore des emmerdes droit devant!\n\n[COK4_20:BARON4]\nIl y a des porte-flingues sur cette jetée!\n\n[COK4_24:BARON4]\nJoli coup, mon pote. T'es vraiment un cinglé de première!\n\n[COK4_25:BARON4]\nAh... Merci.\n\n[COK4_26:BARON4]\nA la prochaine, Tommy.\n\n[COK4_27:BARON4]\nOkay, M. Lance Vance Danse.\n\n[COK4_28:BARON4]\n~g~Atteins le yatch avant les autres bateaux!\n\n[COK4_31:BARON4]\n~g~Va jusqu'au bateau le plus rapide de la jetée!\n\n[COK4_32:BARON4]\n~r~Trop lent!\n\n[COK4_33:BARON4]\n~r~T'as détruit le bateau!\n\n[COK4_34:BARON4]\n~g~Bousille ces bateaux!\n\n[COK4_35:BARON4]\nEtat du bateau :\n\n{=================================== MISSION TABLE BARON5 ===================================}\n\n[PROP_A:BARON5]\nPROPRIETE ACHETEE!\n\n[COK4_30:BARON5]\n~r~Lance est mort!\n\n[ASS1_A:BARON5]\nJ'ai récupéré des flingues. Ils sont dans l'coffre.\n\n[ASS1_B:BARON5]\nMerde alors! Où c'est que t'as dégoté tout ça?\n\n[ASS1_C:BARON5]\nJe l'gardais au frais pour une grande occasion...\n\n[ASS1_D:BARON5]\nCa te botte?\n\n[ASS1_E:BARON5]\nTu parles que ça m'botte.\n\n[ASS1_F:BARON5]\nEspèce de connard...\n\n[ASS1_G:BARON5]\nMa belle maison...\n\n[ASS1_H:BARON5]\nRegarde ce que t'en as fait!\n\n[ASS1_I:BARON5]\nCa c'est pour mon frère!\n\n[ASS1_J:BARON5]\nJe te faisais confiance, Tommy...\n\n[ASS1_K:BARON5]\nJe t'aurais aidé à devenir...\n\n[ASS1_L:BARON5]\nBonne nuit, Diaz.\n\n[ASS1_1:BARON5]\nCet endroit va bientôt grouiller de salopards... Fais gaffe.\n\n[ASS1_2:BARON5]\nT'en fais pas, Tommy, je te couvre.\n\n[ASS1_4:BARON5]\nDiaz doit être à l'intérieur!\n\n[ASS1_13:BARON5]\nDIAZ! Je suis venu reprendre ton affaire!\n\n[ASS1_14:BARON5]\nTOMMY! Tu me trahis... Idiot! Je vais te buter tout de suite!\n\n[ASS1_16:BARON5]\n~g~Tue Diaz!\n\n[BUD1:BARON5]\nLance\n\n[ASS1_18:BARON5]\n~g~La porte est verrouillée. Trouve un autre chemin.\n\n[ASS1_19:BARON5]\nPar ici!\n\n[ASS1_20:BARON5]\nTommy, mon problème c'est Quentin, pas toi, mec!\n\n{=================================== MISSION TABLE BIKE1 ===================================}\n\n[BM1_A:BIKE1]\nOù est Baker?\n\n[BM1_B:BIKE1]\nJe cherche Big Mitch Baker...\n\n[BM1_C:BIKE1]\nQui le cherche?\n\n[BM1_D:BIKE1]\nTommy Vercetti.\n\n[BM1_E:BIKE1]\nVercetti...\n\n[BM1_F:BIKE1]\nT'as pas l'air d'un flic, ce qui te donne droit à une minute...\n\n[BM1_G:BIKE1]\nT'as intérêt à faire court!\n\n[BM1_H:BIKE1]\nKent Paul dit que ça pourrait t'intéresser de te charger de la sécurité pour un boulot qu'il prépare.\n\n[BM1_I:BIKE1]\nKent Paul? Ah! Pas étonnant qu'il t'ai envoyé.\n\n[BM1_J:BIKE1]\nLa dernière fois qu'il est passé ici, il en est ressorti par la fenêtre avec rien d'autre que son costume d'anglais.\n\n[BM1_K:BIKE1]\nBon, t'es intéressé ou pas?\n\n[BM1_L:BIKE1]\nOn ne rend des services qu'à ceux qui font partie de la bande.\n\n[BM1_M:BIKE1]\nComment je me joins à vous?\n\n[BM1_N:BIKE1]\nOn est pas un club de loisirs, mon pote! Tu peux conduire une bécane?\n\n[BM1_O:BIKE1]\nTu peux t'asseoir sur un tabouret de bar et boire?\n\n[BM1_P:BIKE1]\nCougar, Zeppelin, allez voir comment elle se débrouille sur une bécane...\n\n[BM1_2:BIKE1]\n~g~Il te faut une Freeway ou une Angel pour participer!\n\n[BM1_3:BIKE1]\n~r~Les concurrents ont été attaqués!\n\n[BIKE1_1:BIKE1]\nBon, chouettes fringues. Voyons ce que tu peux faire.\n\n[BM1_1:BIKE1]\n~g~Enfourche une Freeway ou une Angel et va sur la grille de départ.\n\n{=================================== MISSION TABLE BIKE2 ===================================}\n\n[BM2_4:BIKE2]\n~r~Tu n'as pas rempli le chaosmètre à temps!\n\n[BM2_1:BIKE2]\nCHAOSMETRE :\n\n[BM2_A:BIKE2]\nHa ha ha, je t'ai encore eu!\n\n[BM2_B:BIKE2]\nHé, Vercetti.\n\n[BM2_C:BIKE2]\nCougar dit que tu te débrouilles plutôt bien sur une bécane.\n\n[BM2_D:BIKE2]\nOuais, mais combien d'épreuves il va encore falloir que je me tape?\n\n[BM2_E:BIKE2]\nJe suis très occupé, mon pote.\n\n[BM2_F:BIKE2]\nSi c'est une baston qui peut régler la question, alors amène-toi!\n\n[BM2_G:BIKE2]\nDevenir l'un d'entre nous, c'est pas qu'une question de baston. C'est appartenir à une famille.\n\n[BM2_H:BIKE2]\nOuais, j'ai déjà appartenu à une famille avant et ça n'a pas bien collé.\n\n[BM2_I:BIKE2]\nPeut-être, mais notre famille veille sur les siens.\n\n[BM2_J:BIKE2]\nOn demande à personne de faire le sale boulot pour l'abandonner au trou pendant quinze ans...\n\n[BM2_K:BIKE2]\nEt ouais, je me suis renseigné.\n\n[BM2_L:BIKE2]\nCe que tu vois, c'est la plus grande famille d'inadaptés, de parias et d'ordures qui existe.\n\n[BM2_M:BIKE2]\nCertains ont même été trahis par leur propre pays!\n\n[BM2_N:BIKE2]\nOn m'a foutu en taule pendant la guerre du Vietnam! Saloperie...\n\n[BM2_O:BIKE2]\nVoilà pourquoi je vais te demander d'aller foutre le bordel.\n\n[BM2_P:BIKE2]\nCe pays de merde a vraiment besoin d'un coup de pied au cul et c'est nous qui allons le lui donner!\n\n[BM2_Q:BIKE2]\nAlors sors de là, attrape une bécane et montre à cette ville à quel point t'es énervé!\n\n[BM2_R:BIKE2]\nD'accord.\n\n[BM2_2:BIKE2]\n~g~Tu dois remplir le chaosmètre dans le temps imparti pour nous prouver que t'es un dur de dur!\n\n[BM2_3:BIKE2]\n~g~Ce bruit veut dire qu'une partie du chaosmètre est remplie, continue comme ça.\n\n{=================================== MISSION TABLE BIKE3 ===================================}\n\n[BM3_A:BIKE3]\nSalut, Mitch.\n\n[BM3_B:BIKE3]\nHé! Mais c'est ce gros méchant de Vercetti!\n\n[BM3_C:BIKE3]\nMaintenant, je veux voir à quel point tu peux te battre pour ton secteur.\n\n[BM3_D:BIKE3]\nUn gang local a commis l'erreur de me faucher ma bécane...\n\n[BM3_E:BIKE3]\nProbablement un truc de machos ou quelque chose de ce genre.\n\n[BM3_F:BIKE3]\nMoi et mes gars, on pourrait aller leur donner la leçon qu'ils méritent...\n\n[BM3_G:BIKE3]\nEnfin...\n\n[BM3_H:BIKE3]\nJe me suis dit que ça serait une excellente initiation pour toi.\n\n[BM3_I:BIKE3]\nTu me ramènes ma bécane et tu pourras dire à Paul qu'on assurera la sécurité.\n\n[BM3_2:BIKE3]\n~r~Tu étais supposé ramener la bécane, pas la bousiller!\n\n[BM3_3:BIKE3]\n~g~Ramène la bécane au bar!\n\n[BM3_4:BIKE3]\n~g~Monte sur la bécane!\n\n[INTRUDE:BIKE3]\n~g~T'as été repéré!\n\n[BM3_6:BIKE3]\n~g~Ils se planquent derrière Ammu-Nation dans le centre.\n\n[BM3_7:BIKE3]\n~g~T'auras besoin d'une bécane rapide pour accéder au toit.\n\n[BM3_8:BIKE3]\n~g~Sers-toi de la bécane pour sauter de ces marches jusqu'à l'autre côté de la route.\n\n[BM3_1:BIKE3]\n~g~Un gang local a volé l'Angel de Mitch Baker. Récupère-la!\n\n[BM3_9:BIKE3]\n~g~Récupère l'Angel de Mitch Baker et dégage de là!\n\n{=================================== MISSION TABLE BMX_1 ===================================}\n\n[BMX_REC:BMX_1]\n~g~Nouveau record établi : ~1~!\n\n[GETBIK2:BMX_1]\nTu as ~1~ secondes pour enfourcher une bécane!\n\n{=================================== MISSION TABLE BOATBUY ===================================}\n\n[DRUG_1:BOATBUY]\nBonjour? Y'a quelqu'un? Y'A QUELQU'UN???\n\n[DRUG_2:BOATBUY]\nFerme-la. Il y a un mec, ici.\n\n[DRUG_3:BOATBUY]\nHé, mon pote! T'es le nouveau proprio?\n\n[DRUG_4:BOATBUY]\nOuais. Lequel de ces bateaux est le plus rapide?\n\n[DRUG_5:BOATBUY]\nIl est déjà à l'eau, mon pote,\n\n[DRUG_6:BOATBUY]\nje me suis dit que tu voudrais peut-être l'essayer.\n\n[DRUG_7:BOATBUY]\nMon pote, il est déjà équipé d'un moteur de 300 chevaux...\n\n[DRUG_8:BOATBUY]\n...et avec la coque en fibre de verre, il touche même pas l'eau!\n\n[DRUG_9:BOATBUY]\nIl monte à 60 noeuds en quatre secondes, mon pote...\n\n[DRUG_10:BOATBUY]\nEt il peut embarquer vingt écopes de la meilleure jamaïquaine dans la coque.\n\n[DRUG_11:BOATBUY]\nAlors vas-y, mon pote, il t'attend pour décoler!\n\n[DRUG_12:BOATBUY]\nOuais, hé, mon pote, t'as du feu?\n\n[DRUG_13:BOATBUY]\nMec?\n\n{=================================== MISSION TABLE CAP_1 ===================================}\n\n[CAP1_B1:CAP_1]\n~g~La mafia taxe tes commerces. Trouve-les et bute-les.\n\n[CAP1_B2:CAP_1]\n~g~La mafia taxe le chantier naval!\n\n[CAP1_B3:CAP_1]\n~g~La mafia taxe l'usine de crème glacée!\n\n[CAP1_B4:CAP_1]\n~g~La mafia taxe la concession automobile!\n\n[CAP1_B5:CAP_1]\n~g~La mafia taxe la compagnie de taxis!\n\n[CAP_01:CAP_1]\nOk, où est l'urgence?\n\n[CAP_02:CAP_1]\nQUI?\n\n[CAP_03:CAP_1]\nTommy... Des truands de la mafia... Ils ont dit qu'ils venaient prendre leur part...\n\n[CAP_04:CAP_1]\n... Ils ont dit que c'était le pognon de Mr Forello... J'me sens mal...\n\n[CAP_05:CAP_1]\nForelli? SONNY Forelli?\n\n[CAP_06:CAP_1]\nOuais, c'est ça... je crois... Ils ont beaucoup insisté...\n\n[CAP_07:CAP_1]\nT'inquiète pas, je suis pas en colère contre toi.\n\n[CAP_08:CAP_1]\nEmmène-le à l'hosto.\n\n[CAP_09:CAP_1]\nTommy... Taille un nouveau trou du cul à ce salopard de ma part...\n\n[CAP_10:CAP_1]\nJe vais lui en rajouter deux!\n\n[CAP1_2:CAP_1]\nTu connais la règle, Vercetti!\n\n[CAP1_3:CAP_1]\nAvec les compliments de M. Forelli!\n\n[CAP1_4:CAP_1]\nC'est le boucher d'Harwood!\n\n[CAP1_5:CAP_1]\nTu diras à Sonny... de dégager!\n\n[CAP1_6:CAP_1]\nVice City est à moi, désormais, pas à lui!\n\n[CAP1_7:CAP_1]\nTu crois que tu peux m'avoir, Vercetti?\n\n[CAP1_8:CAP_1]\nOn va continuer à s'amener jusqu'à ce que tu sois raide mort, Vercetti!\n\n[CAP1_9:CAP_1]\nT'as pas une chance, connard psychotique!\n\n[CAP1_10:CAP_1]\nJe vais te descendre, Vercetti!\n\n[CAP1_11:CAP_1]\nT'as toujours été un con!\n\n[CAP1_12:CAP_1]\nTu vas crever, Vercetti!\n\n[CAP1_B6:CAP_1]\n~g~Tu as trouvé l'encaisseur. Tue-le.\n\n[CAP1_B7:CAP_1]\n~g~Tu as perdu l'encaisseur.\n\n[CAP1_B8:CAP_1]\n~r~L'encaisseur a taxé toutes tes affaires.\n\n[CAP1_B9:CAP_1]\n~g~La mafia a taxé le Malibu!\n\n[CAP1_B0:CAP_1]\n~g~La mafia a taxé le studio de cinéma!\n\n[CAP1_C2:CAP_1]\n~g~La mafia est arrivée au chantier naval!\n\n[CAP1_C3:CAP_1]\n~g~La mafia est arrivée à l'usine de crème glacée!\n\n[CAP1_C4:CAP_1]\n~g~La mafia est arrivée à la concession automobile!\n\n[CAP1_C5:CAP_1]\n~g~La mafia est arrivée à la compagnie de taxis!\n\n[CAP1_C9:CAP_1]\n~g~La mafia est arrivée au Malibu!\n\n[CAP1_C0:CAP_1]\n~g~La mafia est arrivée au studio de cinéma!\n\n[CAP1_D2:CAP_1]\n~g~La mafia quitte le chantier naval!\n\n[CAP1_D3:CAP_1]\n~g~La mafia quitte l'usine de crème glacée!\n\n[CAP1_D4:CAP_1]\n~g~La mafia quitte la concession automobile!\n\n[CAP1_D5:CAP_1]\n~g~La mafia quitte la compagnie de taxis!\n\n[CAP1_D9:CAP_1]\n~g~La mafia quitte le Malibu!\n\n[CAP1_D0:CAP_1]\n~g~La mafia quitte le studio de cinéma!\n\n[CAP1B10:CAP_1]\nTu t'es occupé des taxeurs. Y'en a d'autres qui arrivent.\n\n{=================================== MISSION TABLE CARBUY ===================================}\n\n[CAR1_1:CARBUY]\nB.J. Smith. Et vous devez être Mr Vercetti.\n\n[CAR1_2:CARBUY]\nVous voulez visiter?\n\n[CAR1_3:CARBUY]\nPourquoi pas?\n\n[CAR1_4:CARBUY]\nVous savez, je suis bien triste de vendre l'affaire...\n\n[CAR1_5:CARBUY]\nC'était mon premier investissement de professionnel.\n\n[CAR1_6:CARBUY]\nMais l'heure est venue pour moi de continuer ma route.\n\n[CAR1_7:CARBUY]\nVous quittez la ville?\n\n[CAR1_8:CARBUY]\nPas trop pressé, j'espère?\n\n[CAR1_9:CARBUY]\nNon, je sors juste de ma retraite et je prépare mon retour dans les affaires.\n\n[CAR1_10:CARBUY]\nCette affaire était pas trop solide,\n\n[CAR1_11:CARBUY]\nmais mon personnel a pris sur lui de faire un peu plus\n\n[CAR1_12:CARBUY]\ncréatif en ce qui concerne les méthodes pour devenir rentable.\n\n[CAR1_13:CARBUY]\nEvidemment, je pourrais démanteler l'affaire avant de la refiler.\n\n[CAR1_14:CARBUY]\nMerde, je pourrais y foutre le feu si ça me chantait.\n\n[CAR1_15:CARBUY]\nC'est un terrain de premier ordre.\n\n[CAR1_16:CARBUY]\nOh, je ne m'en ferais pas pour ça.\n\n[CAR1_17:CARBUY]\nCet endroit me semble idéal.\n\n[CAR1_18:CARBUY]\nOuais, il l'est, alors, marché conclu?\n\n{=================================== MISSION TABLE CARPAR1 ===================================}\n\n[MM_1_A:CARPAR1]\n~g~Récupère ~y~5 points de passage~r~ SANS ~g~renverser de ~r~CONES! ~g~Tu peux les récupérer dans ~y~N'IMPORTE QUEL ORDRE.\n\n[CONE_1:CARPAR1]\n~r~Tu as renversé un cône!\n\n[MM_1_C:CARPAR1]\n~y~FRANCHIS~g~ un point de passage pour enclencher le compteur. ~g~Chaque point de passage te crédite ~y~~1~ SECONDES~g~.\n\n{=================================== MISSION TABLE COPCAR ===================================}\n\n[CLEVEL:COPCAR]\nMissions d'autodéfense niveau ~1~\n\n[C_COMP1:COPCAR]\nNiveau 12 de mission Auto-défense réussi : votre max de gilet pare-balles passe à 150.\n\n[KILLS:COPCAR]\nVICTIMES :\n\n[C_BREIF:COPCAR]\n~g~Suspect aperçu pour la dernière fois dans le secteur ~a~.\n\n[C_PASS:COPCAR]\nMENACE ENRAYEE : $~1~\n\n[COPCART:COPCAR]\n~g~Tu as ~1~ secondes pour retourner à une voiture de police avant que la mission ne s'achève.\n\n[C_CANC:COPCAR]\n~r~Mission d'autodéfense annulée!\n\n[C_TIME:COPCAR]\n~r~Ta carrière de flic est terminée!\n\n{=================================== MISSION TABLE COUNT1 ===================================}\n\n[CM1_A:COUNT1]\nVercetti? Hé, vous avez acheté la vieille imprimerie?\n\n[CM1_B:COUNT1]\nOuais, mon vieux a travaillé sur ces machines.\n\n[CM1_C:COUNT1]\nJ'aurais voulu marcher sur ses traces, mais... J'ai suivi une autre voie.\n\n[CM1_D:COUNT1]\nVous avez l'intention de vendre les vieilles machines, et de tout casser?\n\n[CM1_E:COUNT1]\nJe m'disais qu'on pourrait peut-être imprimer quelque chose, un journal ou un magazine...\n\n[CM1_F:COUNT1]\nArrête tes conneries, fiston! J'ai toujours rêvé d'imprimer mon propre pognon! C'est pas très compliqué!\n\n[CM1_G:COUNT1]\nTu sais, j'ai fait ça sur une petite échelle pendant des années.\n\n[CM1_H:COUNT1]\nAh ouais?\n\n[CM1_I:COUNT1]\nOuais. Mais il nous faut des plaques de bonne qualité.\n\n[CM1_J:COUNT1]\nEvidemment! Il y a un syndicat de contrefaçon qui opère déjà en Floride!\n\n[CM1_K:COUNT1]\nUn syndicat?\n\n[CM1_L:COUNT1]\nOuais. C'est le bruit qui court en tout cas.\n\n[CM1_M:COUNT1]\nJe connais un mec qui en saura sûrement plus...\n\n[CM1_N:COUNT1]\nOn avait l'habitude de passer nos soirées ensemble, à nettoyer les rouleaux...\n\n[CM1_2A:COUNT1]\nMate-moi ce cul!\n\n[CM1_2B:COUNT1]\nOk, ma belle, c'est l'heure de l'initiation!\n\n[CM1_2C:COUNT1]\nSalut, vieille branche, comment ça va?\n\n[CM1_2D:COUNT1]\nQue sais-tu à propos de la contrefaçon?\n\n[CM1_2E:COUNT1]\nOh, je vais bien, Paul, et toi?\n\n[CM1_2F:COUNT1]\nViens ici!\n\n[CM1_2G:COUNT1]\nBon! Bon! Bon! Tu es visiblement un homme très occupé!\n\n[CM1_2H:COUNT1]\nTout ce que je sais, c'est que les Triades fournissent les plaques.\n\n[CM1_2I:COUNT1]\nElles ont une compagnie de navigation sur les quais\n\n[CM1_2J:COUNT1]\net le patron devrait savoir quand les plaques arrivent!\n\n[CM1_2K:COUNT1]\nMerci, Paul.\n\n[CM1_2L:COUNT1]\nC'est quoi ton problème, pauvre maniaque!\n\n[CM1_2M:COUNT1]\nUn autre verre, en vitesse!\n\n[CM1_3:COUNT1]\n~g~T'as été repéré!\n\n[CM1_5:COUNT1]\n~g~Va retrouver Kent Paul au Malibu!\n\n[CNT1_1:COUNT1]\nT'es qui toi? Aïe! Pas le visage! Pas le visage!\n\n[CM1_1:COUNT1]\n~g~Va au bateau de la Chartered Libertine Lines sur les docks.\n\n[CM1_2:COUNT1]\n~g~L'officier de navigation détient l'information dont tu as besoin.\n\n[CNT1_2:COUNT1]\nOk, je parle! Je parle!\n\n[CM1_6:COUNT1]\n~g~Ramène l'info à l'imprimerie!\n\n{=================================== MISSION TABLE COUNT2 ===================================}\n\n[CNT2_B1:COUNT2]\nBon, le coursier déplace les plaques des docks aujourd'hui.\n\n[CNT2_B2:COUNT2]\nFaut l'intercepter et récupérer ces plaques, semer les flics éventuels et revenir ici.\n\n[CNT2_B3:COUNT2]\nEn fonction de comment ça marche,\n\n[CNT2_B4:COUNT2]\non aura entre cinq minutes et toute l'année pour imprimer le pognon avant que le syndicat de contrefaçon rapplique.\n\n[CNT2_B5:COUNT2]\nQuoi qu'il en soit, je veux voir les premiers billets sortir de la presse cinq minutes après mon retour! C'est compris?\n\n[CNT2_B6:COUNT2]\nT'inquiète pas, Tommy, on sera prêts.\n\n[CNT2_B7:COUNT2]\nLes gars et moi, on sera dans le coin au cas où t'aurais besoin de renforts.\n\n[CNT2_B8:COUNT2]\nBon, tout le monde a compris? Parfait. A plus tard.\n\n[CNT2_01:COUNT2]\n~g~Le ~r~coursier~g~ qui porte les plaques va bientôt arriver aux ~y~docks~g~ en hélico.\n\n[CNT2_02:COUNT2]\n~r~Le coursier s'est enfui en hélico!\n\n[CNT2_03:COUNT2]\n~r~Le coursier est parvenu à destination sain et sauf, c'est trop tard!\n\n[CNT2_04:COUNT2]\n~r~Tu as détruit les plaques dans l'explosion!\n\n[CNT2_05:COUNT2]\n~g~Tu as les plaques. Emmène-les à l'imprimerie!\n\n[CNT2_06:COUNT2]\n~g~Le coursier est mort et il a jeté les plaques. Récupère-les en premier.\n\n[CNT2_07:COUNT2]\n~g~Un des gardes a ramassé les plaques, ne le laisse pas s'enfuir!\n\n[CNT2_08:COUNT2]\n~g~Le ~r~coursier~g~ avec les plaques est arrivé aux docks.\n\n[CNT2_4:COUNT2]\nAffaire privée! Dégagez!\n\n[CNT2_09:COUNT2]\nIMPRIMERIE ACQUISE\n\n[CNT2_10:COUNT2]\n~g~L'imprimerie va maintenant générer un revenu maximum de $~1~. Veille à relever régulièrement les compteurs.\n\n[CNT2_11:COUNT2]\n~r~Les plaques sont au fond de la mer!\n\n{=================================== MISSION TABLE CUBAN1 ===================================}\n\n[CUB1_A:CUBAN1]\nSi, mec?\n\n[CUB1_B:CUBAN1]\nHé, du calme, papa, ce mec est là pour moi. Hé, c'est toi le mec?\n\n[CUB1_C:CUBAN1]\nOh ouais. C'est toi le mec. Je crois bien, tu sais.\n\n[CUB1_D:CUBAN1]\nNon, je crois pas.\n\n[CUB1_E:CUBAN1]\nAh ouais? Amène-toi, gros dur!\n\n[CUB1_F:CUBAN1]\nTu crois que tu peux jouer avec moi?\n\n[CUB1_G:CUBAN1]\nTu penses que tu peux jouer au con avec moi?\n\n[CUB1_H:CUBAN1]\nNon, je pense que tu joues assez le con pour nous deux.\n\n[CUB1_I:CUBAN1]\nHé, il t'a traité de con, fiston.\n\n[CUB1_J:CUBAN1]\nEt moi, je le traite de fillette, papa.\n\n[CUB1_K:CUBAN1]\nRegarde-le, tout habillé comme ça.\n\n[CUB1_L:CUBAN1]\nC'est la soirée des pouffiasses, ce soir?\n\n[CUB1_M:CUBAN1]\nToi qu'est plutôt balaise, pourquoi tu te fringues en nana?\n\n[CUB1_N:CUBAN1]\nEt t'as une petite culotte comme les gonzesses?\n\n[CUB1_O:CUBAN1]\nQu'est-ce que t'as contre les femmes? Tu préfères les mecs, mon gros?\n\n[CUB1_P:CUBAN1]\nJ'aime les femmes! J'aime toutes les femmes! J'aime ma maman, Chico!\n\n[CUB1_Q:CUBAN1]\nOk, ok, j'te crois sur parole.\n\n[CUB1_R:CUBAN1]\nTu sais conduire, amigo?\n\n[CUB1_S:CUBAN1]\nOuais... Comme une gonzesse.\n\n[CUB1_T:CUBAN1]\nTrès drôle... Tu me plais, ma grosse, peut-être que tu peux aider.\n\n[CUB1_U:CUBAN1]\nTu peux peut-être nous montrer que t'es un vrai mec?\n\n[CUB1_V:CUBAN1]\nSors le bateau.\n\n[CUB1_W:CUBAN1]\nProuve-moi que t'as des couilles énormes\n\n[CUB1_X:CUBAN1]\net pas une paire de pois chiches!\n\n[CUB1_02:CUBAN1]\nOk, mec, traite-la comme une gonzesse.\n\n[CUB1_03:CUBAN1]\nPas mal, t'es un vrai macho.\n\n[CUB1_04:CUBAN1]\nMerde, t'en a vraiment dans le pantalon, amigo.\n\n[CUB1_05:CUBAN1]\nAmigo, t'es un vrai mec, mec.\n\n[CUB1_06:CUBAN1]\nTu te prends pour un homme, mec?\n\n[CUB1_07:CUBAN1]\nT'es qu'une petite poule mouillée, petit, c'est ta mère qui te manque?\n\n[CUB1_08:CUBAN1]\nTu gâches tout! Tu marches comme un mec, tu causes comme un mec, mais tu conduis comme une gonzesse!\n\n[CUB1_09:CUBAN1]\nMec, t'es un vrai mec de chez mec, mec! Putain, je t'adore, mec!\n\n[CUB1_10:CUBAN1]\nC'est quand tu veux, mec. T'as des couilles de taureau et tous mes potes ont des couilles énormes!\n\n[CUB1_11:CUBAN1]\n~r~T'as tué Rico!\n\n[CUB1_12:CUBAN1]\nVa jusqu'au premier point de contrôle pour commencer le test.\n\n[CUB1_14:CUBAN1]\nRetourne dans le bateau!\n\n[CUB1_15:CUBAN1]\n~r~T'es trop lent, mec!\n\n[CUB1_01:CUBAN1]\nSalut, moi c'est Rico. C'est toi qu'a des couilles de taureau?\n\n[CUB1_13:CUBAN1]\n~g~Tu as trois minutes pour terminer le parcours.\n\n{=================================== MISSION TABLE CUBAN2 ===================================}\n\n[CUB2_25:CUBAN2]\nBUTE TOUS LES HAITIENS!\n\n[CUB2_A:CUBAN2]\nUn cafecito, por favor, Alberto...\n\n[CUB2_N:CUBAN2]\nTout de suite, Tommy.\n\n[CUB2_B:CUBAN2]\nPoppa! Un gran problema!\n\n[CUB2_O:CUBAN2]\nUmberto, mon fils, que s'est-il passé?\n\n[CUB2_C:CUBAN2]\nLes Haïtiens! Je hais les Haïtiens!\n\n[CUB2_D:CUBAN2]\nC'est la dernière fois qu'ils me font chier!\n\n[CUB2_E:CUBAN2]\nCes Haïtiens... On va les liquider!\n\n[CUB2_F:CUBAN2]\nOn a juste besoin de renforts...\n\n[CUB2_G:CUBAN2]\nJ'ai déjà perdu pas mal de frères là-bas.\n\n[CUB2_H:CUBAN2]\nAmigo, tu conduis pas mal!\n\n[CUB2_I:CUBAN2]\nPour une gonzesse... Pas vrai?\n\n[CUB2_J:CUBAN2]\nC'est pas l'heure des vannes!\n\n[CUB2_K:CUBAN2]\nAllez, conduis encore pour moi!\n\n[CUB2_L:CUBAN2]\nRécupère mes gars là-bas et puis on s'occupe de ces Haïtiens!\n\n[CUB2_M:CUBAN2]\nIls m'ont cherché et ils sont tombés sur le mec le plus balaise de la ville!\n\n[CUB2_01:CUBAN2]\nC'est trop petit, mec, il te faut une plus grosse bagnole.\n\n[CUB2_02:CUBAN2]\nOn a besoin de renforts du café!\n\n[CUB2_03:CUBAN2]\n~g~Prend une bagnole et va ramasser les Cubains à l'extérieur du café de Robina.\n\n[CUB2_04:CUBAN2]\n~g~Amène les Cubains à l'endroit de la bagarre.\n\n[CUB2_05:CUBAN2]\nLiquide ce lâche de tireur embusqué!\n\n[CUB2_07:CUBAN2]\nIls se battent comme des filles! A couvert!\n\n[CUB2_09:CUBAN2]\nUn sniper sur le toit!\n\n[CUB2_11:CUBAN2]\n~r~Imbécile, on avait besoin de cette bagnole!\n\n[CUB2_12:CUBAN2]\nHé, amigo! Content de te voir que t'as réussi!\n\n[CUB2_13:CUBAN2]\nPutains de Haïtiens, on va tous les descendre!\n\n[CUB2_14:CUBAN2]\nCHAAAAAARGEZ!\n\n[CUB2_15:CUBAN2]\nMaintenant, mes frères! Chaaaargez!\n\n[CUB2_16:CUBAN2]\nTommy, on a fait la preuve de notre courage!\n\n[CUB2_17:CUBAN2]\nPiquons cette camionnette bourrée de drogue et tirons-nous!\n\n[CUB2_18:CUBAN2]\n~g~Trouve une bagnole et va chercher les Cubains.\n\n[CUB2_19:CUBAN2]\nOn va se battre comme des hommes!\n\n[CUB2_21:CUBAN2]\nBattez-vous avec vos couilles!\n\n[CUB2_22:CUBAN2]\n~g~Elimine les derniers Haïtiens pour que les Cubains puissent avancer.\n\n[CUB2_23:CUBAN2]\n~g~Little Haiti va grouiller de Haïtiens voulant régler leurs comptes avec les Cubains. Fais gaffe à tes couilles.\n\n[CUB2_24:CUBAN2]\n~g~Retourne au café de Robina avec la camionnette et gare-la derrière.\n\n{=================================== MISSION TABLE CUBAN3 ===================================}\n\n[CUB3_A:CUBAN3]\nAlberto. Un café, senor.\n\n[CUB3_B:CUBAN3]\nPapa, ne sers pas ce morbac...\n\n[CUB3_C:CUBAN3]\nT'es un hypocrite, Tommy!\n\n[CUB3_D:CUBAN3]\nT'es soit un hypocrite, soit une gonzesse!\n\n[CUB3_E:CUBAN3]\nLes Haïtiens, mec! Ils se foutent de ma gueule!\n\n[CUB3_F:CUBAN3]\nDu calme. C'est quoi ton problème?\n\n[CUB3_G:CUBAN3]\nIls se foutent ma gueule, Tommy, de ma gueule!\n\n[CUB3_H:CUBAN3]\nUmberto Robina! Ils font comme ça leur chante!\n\n[CUB3_I:CUBAN3]\nPersonne fait ce qu'il veut, Umberto, ils font ce que tu les laisses faire.\n\n[CUB3_J:CUBAN3]\nQuoi?\n\n[CUB3_K:CUBAN3]\nTu veux que quelqu'un s'en occupe?\n\n[CUB3_L:CUBAN3]\nJe peux m'en charger, mais ça va te coûter cher!\n\n[CUB3_M:CUBAN3]\nJe sais qu'on est frères et tout et tout, mais ça, c'est les affaires...\n\n[CUB3_N:CUBAN3]\nTommy, t'es un vrai mec! Un businessman! Un gentleman!\n\n[CUB3_O:CUBAN3]\nCes Haïtiens. Ils ont de la marchandise de première qualité qui arrive par la mer.\n\n[CUB3_P:CUBAN3]\nOn la prend et on en finit avec eux.\n\n[CUB3_Q:CUBAN3]\nTu t'en charges et je veillerai sur toi. Comme mon frère. Comme mon fils.\n\n[CUB3_R:CUBAN3]\nJ'préfère que tu me files du pognon, plutôt que de me faire sauter sur tes genoux, amigo...\n\n[CUB3_01:CUBAN3]\nSalut, Rico. Chouette bateau. T'es prêt?\n\n[CUB3_03:CUBAN3]\n~g~Récupère toutes les serviettes pleines de drogue et de cash.\n\n[CUB3_04:CUBAN3]\n~g~Ramène la drogue et le cash à Umberto.\n\n[CUB3_05:CUBAN3]\nSi, Tommy, faut que tu tires bien, aujourd'hui.\n\n[CUB3_06:CUBAN3]\nMon bateau, je voudrais pas qu'il se retrouve plein de trous, ok?\n\n[CUB3_07:CUBAN3]\n~g~Va retrouver Rico. Il te conduira au rendez-vous.\n\n[CUB3_02:CUBAN3]\n~g~TUE TOUS LES HAITIENS EN BATEAU!\n\n[CUB3_08:CUBAN3]\nOh oh... Les Cubains. On nous attaque!\n\n{=================================== MISSION TABLE CUBAN4 ===================================}\n\n[CUB4_A:CUBAN4]\nSalut, les filles, vous savez ce que je vais faire?\n\n[CUB4_B:CUBAN4]\nJe vais aller me descendre un Haïtien. Et après, vous savez quoi?\n\n[CUB4_C:CUBAN4]\nAprès, je vais me vider les couilles comme un homme!\n\n[CUB4_D:CUBAN4]\nT'as déjà vu ça chica? Un peu comme ça...\n\n[CUB4_E:CUBAN4]\nPauv' mec!\n\n[CUB4_F:CUBAN4]\nConnard!\n\n[CUB4_G:CUBAN4]\nHé, ma poule, je te toucherai même pas avec une perche!\n\n[CUB4_H:CUBAN4]\nUmberto Robina, il aime les femmes! Pas les vieilles dindes en jupe!\n\n[CUB4_I:CUBAN4]\nTommy! Tommy, je t'aime, je t'aime! Allons-y!\n\n[CUB4_J:CUBAN4]\nOù ça? Je peux pas avoir un café d'abord?\n\n[CUB4_K:CUBAN4]\nPas le temps pour un café! D'ailleurs, je viens d'en prendre un!\n\n[CUB4_L:CUBAN4]\nFaut qu'on liquide les Haïtiens!\n\n[CUB4_M:CUBAN4]\nTommy, tu sais comment on tue un serpent?\n\n[CUB4_N:CUBAN4]\nTu le mords au cul! Ahahaha!\n\n[CUB4_O:CUBAN4]\nSi tu le dis, Umberto.\n\n[CUB4_P:CUBAN4]\nTommy, va nous trouver une petite bagnole haïtienne!\n\n[CUB4_Q:CUBAN4]\nDès que tu l'as, reviens récupérer mon petit\n\n[CUB4_R:CUBAN4]\nPepe et emmène-le chez les Haïtiens.\n\n[CUB4_S:CUBAN4]\nEnsuite, tu vas au centre de retraitement des Haïtiens et tu te sers de leurs solvants comme explosif.\n\n[CUB4_T:CUBAN4]\nBoom! Et bye bye!\n\n[CUB4_U:CUBAN4]\nEt toi, Umberto?\n\n[CUB4_V:CUBAN4]\nOh, je reste en arrière, je surveille le café avec papa.\n\n[CUB4_W:CUBAN4]\nIl ne se sent pas très bien, tu sais.\n\n[CUB4_02:CUBAN4]\n~g~Les bombes ont un retardateur de 45 secondes.\n\n[CUB4_04:CUBAN4]\n~r~Tu as mis leur base en alerte! Plus question d'entrer, maintenant!\n\n[CUB4_07:CUBAN4]\nLes solvants sont à l'arrière, amigo.\n\n[CUB4_08:CUBAN4]\nHola, amigos.\n\n[CUB4_09:CUBAN4]\nBueno. Putains d'Haïtiens. Muerte.\n\n[CUB4_10:CUBAN4]\nVamos.\n\n[CUB4_11:CUBAN4]\nSi, vamos.\n\n[CUB4_12:CUBAN4]\nHé, on a besoin d'une bagnole haïtienne!\n\n[CUB4_13:CUBAN4]\nBueno, allons trouver ces muchachos!\n\n[CUB4_14:CUBAN4]\nSuis mes amigos.\n\n[CUB4_15:CUBAN4]\nOk, tu entres...\n\n[CUB4_16:CUBAN4]\nJe vais poser la bombe, couvrez-moi!\n\n[CUB4_17:CUBAN4]\nCOURS!\n\n[CUB4_18:CUBAN4]\nMec, c'est un quartier cool...\n\n[CUB4_19:CUBAN4]\nCet endroit est une décharge, mec.\n\n[CUB4_20:CUBAN4]\nJ'avais une belle copine... Elle vivait dans le coin.\n\n[CUB4_21:CUBAN4]\nTu sais, ils font de super pizzas, ici!\n\n[CUB4_22:CUBAN4]\nHé, mec, tu conduis comme une putain de gonzesse!\n\n[CUB4_23:CUBAN4]\nT'es perdu, mec?\n\n[CUB4_24:CUBAN4]\nT'as laissé Pepe derrière, va le récupérer!\n\n[CUB4_03:CUBAN4]\n~g~Ne sors pas de la bagnole avant qu'elle soit garée en sécurité dans l'enceinte.\n\n[CUB4_26:CUBAN4]\n~g~Emmène Pepe, file au nord dans Little Haïti et fauche une bagnole Vaudou.\n\n[CUB4_27:CUBAN4]\n~g~Va retrouver Rico et les autres Cubains.\n\n[CUB4_28:CUBAN4]\n~g~Va rejoindre les Cubains dans l'usine de dope haïtienne.\n\n[CUB4_29:CUBAN4]\n~g~Marche sur chacun des marqueurs pour y poser une bombe.\n\n[CUB4_30:CUBAN4]\n~g~Une fois les trois bombes posées, sors de l'usine avant qu'elle n'explose.\n\n[CUB4_31:CUBAN4]\n~g~Sors de l'usine!\n\n[CUB4_32:CUBAN4]\n~g~Gare la bagnole à l'endroit du bip et descends.\n\n[CUB4_06:CUBAN4]\n~r~Tu ne t'es pas assez éloigné de la base et on a dû annuler l'explosion!\n\n{=================================== MISSION TABLE FINALE ===================================}\n\n[FIN_1A:FINALE]\nAmène-toi, putain de salopard de traître!\n\n[FIN_1B:FINALE]\nTu vas crever, Judas de mes deux!\n\n[FIN_1C:FINALE]\nC'est la dernière danse de Lance Vance!\n\n[FIN_2B:FINALE]\nAh ouais, c'est ce que tu crois?\n\n[FIN_2C:FINALE]\nJ'ai dit que je l'avais assez entendu celle-là à l'école!\n\n[FIN_3:FINALE]\nPlus personne pour couvrir ton cul, hein, Tommy?\n\n[FIN_4:FINALE]\nT'es plus que du passé, Tommy, du passé!\n\n[FIN_5:FINALE]\nT'as choisi le mauvais camp, Lance...\n\n[FIN_11A:FINALE]\nTu m'as volé quinze ans de ma vie, Sonny...\n\n[FIN_11B:FINALE]\nEt je viens te présenter l'addition!\n\n[FIN_12A:FINALE]\nT'as encore rien compris!\n\n[FIN_12B:FINALE]\nTu m'appartiens, Tommy...\n\n[FIN_12C:FINALE]\nC'est moi qui devait les faire ces quinze années!\n\n[FIN_13:FINALE]\nAttrapez-le, les mecs, il a jamais rien pigé.\n\n[FIN1_01:FINALE]\nQu'est-ce qui se passe?\n\n[FIN1_02:FINALE]\nTommy! Ah, bien, bien. Ecoute, écoute... Euh, écoute.\n\n[FIN1_03:FINALE]\nJ'aime bien les poissons. Ouais, j'adore le poisson!\n\n[FIN1_04:FINALE]\nJe l'aime à toutes les sauces, dans le bocal ou dans l'assiette,\n\n[FIN1_05:FINALE]\nmais c'est pas parce que je l'aime que je veux dormir avec!\n\n[FIN1_06:FINALE]\nEt maintenant, il y a tes cousins ritals qui s'amènent pour me coller les pieds dans le béton, et je...\n\n[FIN1_07:FINALE]\nLa ferme, Ken. Assis.\n\n[FIN1_08:FINALE]\nLance, bordel, qu'est-ce qui se passe?\n\n[FIN1_09:FINALE]\nC'est tes amis du nord, Tommy... Ils ont pas aimé ce que t'as fait à leur mec.\n\n[FIN1_10:FINALE]\nIls s'amènent aujourd'hui pour régler cette affaire.\n\n[FIN1_11:FINALE]\nIls ont mis plus de temps que je pensais...\n\n[FIN1_12:FINALE]\nLes mecs, faut en finir et faire comprendre à tout le monde que désormais, c'est mon business! LE MIEN!\n\n[FIN1_13:FINALE]\nKen, prend la première production de faux dollars et mets-en pour vingt millions dans des porte-documents.\n\n[FIN1_14:FINALE]\nLance, tu rassembles tout le monde...\n\n[FIN2_01:FINALE]\nTommy!\n\n[FIN2_02:FINALE]\nQuoi? T'embrasses pas ton vieux pote?\n\n[FIN2_03:FINALE]\nCa fait quinze piges que je suis hors-circuit\n\n[FIN2_04:FINALE]\net je suis un peu rouillé question étiquette.\n\n[FIN2_05:FINALE]\nToujours la haine, hein, Tommy!\n\n[FIN2_06:FINALE]\nJe te l'avais pas dit que ton sale caractère te causerait des emmerdes?\n\n[FIN2_07:FINALE]\nIl y a vingt millions là-dedans...\n\n[FIN2_08:FINALE]\nCombien ils étaient déjà? Dix, non onze...\n\n[FIN2_09:FINALE]\nC'est pour ça qu'on t'a surnommé le boucher d'Hartwood! Hé hé hé!\n\n[FIN2_10:FINALE]\nTu m'avais envoyé buter un mec, un seul mec. Mais ils savaient que je venais, Sonny...\n\n[FIN2_11:FINALE]\nFais gaffe à ce que tu dis...\n\n[FIN2_12:FINALE]\nQuelqu'un pourrait penser que tu veux me coller sur le dos un malheureux concours de circonstances...\n\n[FIN2_13:FINALE]\nPrends simplement ce pognon...\n\n[FIN2_14:FINALE]\nPrendre le putain de fric?\n\n[FIN2_15:FINALE]\nTu sais, Tommy, j'ai fait ce que je pouvais pour toi, j'ai tiré des ficelles et demandé des services.\n\n[FIN2_16:FINALE]\nJ'étais ton pote, Tommy. J'espérais que tu entendrais raison et comprendrais ce qui est bon pour les affaires.\n\n[FIN2_17:FINALE]\nJe t'ai fait confiance, Tommy et je suis déçu...\n\n[FIN2_18:FINALE]\nMais il y a au moins un mec dans ton organisation de merde qui s'y connaît en business,\n\n[FIN2_19:FINALE]\nPas vrai, Lance?\n\n[FIN2_20:FINALE]\nDésolé, Tommy, On est à Vice City. C'est les affaires...\n\n[FIN2_21:FINALE]\nTu nous as vendus...\n\n[FIN2_22:FINALE]\nNon, juste toi, Tommy, juste TOI.\n\n[FIN2_23:FINALE]\nLe vrai pognon est en haut dans le coffre!\n\n[FIN2_24:FINALE]\nAlors, Tommy, c'était quoi le grand plan?\n\n[FIN2_25:FINALE]\nTu croyais que j'allais simplement prendre les faux biftons?\n\n[FIN2_26:FINALE]\nSauver la face et m'enfuir la queue entre les jambes?\n\n[FIN2_27:FINALE]\nNon.\n\n[FIN2_28:FINALE]\nJe voulais juste te faire chier avant de te buter.\n\n[FIN3_01:FINALE]\nTommy?\n\n[FIN3_02:FINALE]\nOh, mon Dieu, Tommy! Qu'est-ce qui s'est passé?\n\n[FIN3_03:FINALE]\nA ton avis?\n\n[FIN3_04:FINALE]\nOn dirait que t'as niqué ton costard!\n\n[FIN3_05:FINALE]\nSans compter qu'il était chouette, Tommy! Mais qu'est-ce qui s'est passé?\n\n[FIN3_06:FINALE]\nJ'ai eu un désaccord avec un partenaire commercial, tu sais comment c'est.\n\n[FIN3_07:FINALE]\nTommy, moi, quand j'ai un désaccord avec un partenaire commercial, je lui envoie une lettre enflammée...\n\n[FIN3_08:FINALE]\nA la rigueur, je pisse dans sa boite aux lettres... Mais je commence pas la troisième guerre mondiale!\n\n[FIN3_09:FINALE]\nTu sais, tu devrais peut-être voir mon psy...\n\n[FIN3_10:FINALE]\nCe sale con de Lance...\n\n[FIN3_11:FINALE]\nTommy. J'ai jamais pu blairer ce mec, tu sais?\n\n[FIN3_12:FINALE]\nC'est un névrosé dangereux et égocentrique. Un vrai salopard!\n\n[FIN3_13:FINALE]\nJe suis bien content que tu l'aies liquidé!\n\n[FIN3_14:FINALE]\nJe crois pas qu'on doive s'attendre à plus d'emmerdes en provenance du nord...\n\n[FIN3_15:FINALE]\n... Parce qu'il y a plus de nord...\n\n[FIN3_16:FINALE]\nMaintenant, il n'y a plus que le sud...\n\n[FIN3_17:FINALE]\nAttends, est-ce que ça veut dire ce que je crois que ça veut dire, Tommy?\n\n[FIN3_18:FINALE]\nQu'est-ce que tu crois que ça veut dire?\n\n[FIN3_19:FINALE]\nQu'on est au commandement... Enfin, que tu es au commandement. Oh, Tommy...\n\n[FIN3_20:FINALE]\nTu sais, Ken, c'est peut-être le début d'une grande amitié en affaires...\n\n[FIN3_21:FINALE]\nAprès tout, t'es un voleur minable un peu magouilleur sur les bords...\n\n[FIN3_22:FINALE]\nEt moi je suis un tueur psychotique doublé d'un dealer...\n\n[FIN3_23:FINALE]\nOuais. Si c'est pas grandiose!\n\n[FIN_B1:FINALE]\n~g~Va tuer ~y~Vance~g~ le traître.\n\n[FIN_B2:FINALE]\n~g~Trouve ~p~Sonni~g~ et règle-lui son compte pour de bon.\n\n[FIN_B3:FINALE]\n~g~La mafia essaye de voler ton pognon. Défends le coffre.\n\n[FIN_B4:FINALE]\n~g~Tu es presque mort. Va chercher ~w~de quoi te soigner~g~ en bas.\n\n[FIN_B5:FINALE]\n~g~La mafia te vole ton pognon. Défends le ~c~coffre.\n\n[FIN_B7:FINALE]\n~r~La mafia t'a volé tout ton pognon.\n\n[DEFSAFE:FINALE]\n~g~Retourne au coffre et protège-le.\n\n{=================================== MISSION TABLE FIRETRK ===================================}\n\n[F_PASS1:FIRETRK]\nFeu éteint!\n\n[F_FAIL2:FIRETRK]\n~r~T'arrives trop tard!\n\n[F_CANC:FIRETRK]\n~r~Mission pompier annulée!\n\n[F_EXTIN:FIRETRK]\nINCENDIES :\n\n[F_START:FIRETRK]\n~g~Véhicule en feu repéré dans le secteur ~a~. Va éteindre le feu.\n\n[SIREN_1:FIRETRK]\nPour déclencher la sirène de ce véhicule, appuie brièvement sur la ~h~~k~~VEHICLE_HORN~~w~.\n\n[SIREN_2:FIRETRK]\nPour déclencher la sirène de ce véhicule, appuie brièvement sur la ~h~~k~~VEHICLE_HORN~~w~.\n\n[FIREPRO:FIRETRK]\nMission Camion de pompiers niveau 12 réussie. T'es complètement ignifugé maintenant!\n\n[F_FAIL1:FIRETRK]\nMission Camion de pompiers achevée.\n\n[F_STAR1:FIRETRK]\n~g~Véhicules en flammes dans la zone ~a~. Va éteindre l'incendie.\n\n[SPRAY_4:FIRETRK] { reVC update }\nUtilise la touche ~h~~k~~VEHICLE_FIREWEAPON~ ~w~pour tirer avec le canon à eau et le ~h~~k~~VEHICLE_TURRETLEFT~~w~ et ~h~~k~~VEHICLE_TURRETRIGHT~~w~ pour viser.\n\n[SPRAY_1:FIRETRK] { reVC update }\nUtilise la touche ~h~~k~~VEHICLE_FIREWEAPON~ ~w~pour tirer avec le canon à eau et le ~h~~k~~VEHICLE_TURRETLEFT~~w~ et ~h~~k~~VEHICLE_TURRETRIGHT~~w~ pour viser.\n\n{=================================== MISSION TABLE GENERA1 ===================================}\n\n[GEN1_A:GENERA1]\nMr. Vercetti!\n\n[GEN1_B:GENERA1]\nColonel.\n\n[GEN1_D:GENERA1]\nNon merci.\n\n[GEN1_E:GENERA1]\nCa me gêne beaucoup d'admettre que la cause d'un de nos problèmes communs semble être un homme en qui j'avais confiance.\n\n[GEN1_F:GENERA1]\nJ'ai supporté Gonzalez pendant des années, mais son incompétence a atteint de nouveaux sommets.\n\n[GEN1_G:GENERA1]\nVous avez le droit de tuer Gonzalez...\n\n[GEN1_H:GENERA1]\nC'est lui qui m'a entubé? La seule chose qui m'intéresse, c'est le pognon!\n\n[GEN1_I:GENERA1]\nJe vous récompenserai pour ce service et nous chercherons ensuite votre argent ensemble.\n\n[GEN1_J:GENERA1]\nIl sera dans son appartement, probablement à moitié saoul. Servez-vous de ça...\n\n[GEN1_06:GENERA1]\nHé! Il a une tronçonneuse!\n\n[GEN1_07:GENERA1]\nT'approche pas de moi, connard!\n\n[GEN1_08:GENERA1]\nOh, mon Dieu, j'ai gâché ma vie et j'suis devenu un laidron!\n\n[GEN1_10:GENERA1]\nJe vais t'faire fermer ta grande gueule une bonne fois pour toutes.\n\n[GEN1_11:GENERA1]\nEssaye pas de t'enfuir, bâtard!\n\n[GEN1_12:GENERA1]\nLaisse-toi faire et ça sera rapide!\n\n[GEN1_13:GENERA1]\nArrête de gueuler, ça intéresse personne!\n\n[GEN1_C:GENERA1]\nMerci d'être venu. Asseyez-vous. Du homard?\n\n[GEN1_05:GENERA1]\n~g~Va tuer Gonzales!\n\n[GEN1_09:GENERA1]\nJe t'offre le double, Tommy, LE DOUBLE!\n\n[GEN1_18:GENERA1]\n~r~Gonzalez a réussi à atteindre le poste de police vivant!\n\n[GEN1_19:GENERA1]\n~g~Les flics de Vice City te cherchent!\n\n[GEN1_20:GENERA1]\n~g~Monte dans une bagnole.\n\n[GEN1_21:GENERA1]\n~g~Va au~h~ Pay 'N' Spray~g~ à~h~ Vice Point~g~.\n\n[GEN1_22:GENERA1]\n~g~Conduis ton véhicule à l'intérieur de l'atelier de peinture pour perdre ton ~h~indice de recherche~g~, ~h~réparer ~g~et ~h~repeindre ~g~ton véhicule. Coût : ~h~$100~g~. Cette coup-ci, c'est gratuit.\n\n[GEN1_01:GENERA1]\nQuand tu cours, maintiens la~h~ ~k~~PED_FIREWEAPON~~w~ enfoncée pour préparer une attaque au corps à corps.\n\n[GEN1_02:GENERA1]\nQuand tu cours, maintiens la~h~ ~k~~PED_FIREWEAPON~~w~ enfoncée pour préparer une attaque au corps à corps.\n\n[GEN1_03:GENERA1]\nQuand tu cours, maintiens la~h~ ~k~~PED_FIREWEAPON~~w~ enfoncée pour préparer une attaque au corps à corps.\n\n[GEN1_14:GENERA1]\nRelâche la~h~ ~k~~PED_FIREWEAPON~~w~ pour attaquer.\n\n[GEN1_15:GENERA1]\nRelâche la~h~ ~k~~PED_FIREWEAPON~~w~ pour attaquer.\n\n[GEN1_16:GENERA1]\nRelâche la~h~ ~k~~PED_FIREWEAPON~~w~ pour attaquer.\n\n[GEN1_23:GENERA1]\n~g~Franchis à nouveau les portes pour revenir au rez-de-chaussée.\n\n{=================================== MISSION TABLE GENERA2 ===================================}\n\n[COL2_A:GENERA2]\nTommy! Venez donc vous joindre à moi!\n\n[COL2_B:GENERA2]\nCa a l'air bon, hein! Un peu de museau de tapir?\n\n[COL2_C:GENERA2]\nEuh... Non. Non, merci.\n\n[COL2_D:GENERA2]\nTommy, vous êtes comme le vent de la pampa qui m'a purifié de la puanteur de la corruption.\n\n[COL2_E:GENERA2]\nJe dois cependant montrer que je pleure sa mort et continuer les affaires comme d'habitude.\n\n[COL2_F:GENERA2]\nCa me rapproche pas beaucoup de mon pognon...\n\n[COL2_G:GENERA2]\nTommy, mon cher, vous n'êtes pas à Liberty. Ici, ça se passe autrement.\n\n[COL2_H:GENERA2]\nJe vais continuer mon enquête, mais en attendant, j'ai une bonne affaire à conclure.\n\n[COL2_I:GENERA2]\nUn service à rendre à un ami, Cortez.\n\n[COL2_J:GENERA2]\nVous êtes un ami, Tommy. Je savais que vous ne me laisseriez pas tomber.\n\n[COL2_K:GENERA2]\nIl faut que vous rencontriez un coursier qui m'a obtenu une technologie intéressante...\n\n[COL2_1:GENERA2]\nAh, la pluie est très dense en cette saison...\n\n[COL2_2:GENERA2]\nQuoi?\n\n[COL2_3:GENERA2]\nAh, comment?\n\n[COL2_4:GENERA2]\nEcoute, Cortez m'envoie. File-moi ces putain de processeurs.\n\n[COL2_5:GENERA2]\nOh... D'accord.\n\n[COL2_B1:GENERA2]\n~g~Retrouve le coursier au centre commercial.\n\n[COL2_B2:GENERA2]\n~g~Le coursier se barre avec les processeurs de guidage. Ne le laisse pas filer!\n\n[COL2_B3:GENERA2]\n~g~Ramène les processeurs de guidage au Colonel.\n\n[COL2_F1:GENERA2]\n~r~T'as buté le contact!\n\n[COL2_F2:GENERA2]\n~r~Le coursier est mort. Récupère les processeurs.\n\n[COL2_6A:GENERA2]\nArrête, espèce de porc impérialiste d'américain! Ceci est la propriété du gouvernement français! Rendez-le!\n\n[BLIPHLP:GENERA2]\nLe bip sur le radar est un triangle pointant vers le haut, ce qui signifie que la cible est plus élevée que toi.\n\n[COL2_F3:GENERA2]\n~r~Les processeurs de guidage sont au fond de la mer.\n\n[COL2_F4:GENERA2]\n~r~Le coursier s'est fait la malle! Tu n'as pas récupéré les processeurs de guidage!\n\n{=================================== MISSION TABLE GENERA3 ===================================}\n\n[GEN3_49:GENERA3]\nSanté de Lance:\n\n[GEN3_A:GENERA3]\nMerci d'être venu, Thomas.\n\n[GEN3_B:GENERA3]\nPardonnez-moi d'en venir directement au fait...\n\n[GEN3_C:GENERA3]\nDiaz m'a demandé de superviser une petite transaction...\n\n[GEN3_D:GENERA3]\nEspérons que ça se passera mieux que l'autre fois, n'est-ce pas?\n\n[GEN3_E:GENERA3]\nC'est pour ça que j'ai pensé à vous, amigo.\n\n[GEN3_F:GENERA3]\nJ'ai déposé une arme dans le parking à niveaux.\n\n[GEN3_G:GENERA3]\nRécupèrez-le et allez surveiller les hommes de Diaz au rendez-vous.\n\n[GEN3_H:GENERA3]\nGracias, amigo...\n\n[GEN3_1:GENERA3]\nOn s'accapare toute l'action, à ce que je vois...\n\n[GEN3_2:GENERA3]\nEcoute, tu veux pas faire autre chose que de me suivre partout comme mon ombre? Pourquoi tu ne viens pas pour me montrer à quoi t'es bon?\n\n[GEN3_3:GENERA3]\nPourquoi pas... Au fait, moi c'est Lance.\n\n[GEN3_5:GENERA3]\nTu dois être le nouveau porte-flingues de Cortez.\n\n[GEN3_6:GENERA3]\nJusqu'à ce que de meilleures opportunités se présentent...\n\n[GEN3_7:GENERA3]\nIls seront là d'une minute à l'autre. On ferait mieux de se trouver une bonne planque...\n\n[GEN3_8:GENERA3]\nOK! Je vais sur le balcon et toi tu t'mets sur le toit de l'autre côté de la cour.\n\n[GEN3_9:GENERA3]\nJ'suis vivant! Têtes de noeuds! Et ça c'est grâce à toi! C'est quoi ton nom?\n\n[GEN3_10:GENERA3]\nTommy.\n\n[GEN3_11:GENERA3]\nOn se reverra bientôt, je pense!\n\n[GEN3_12:GENERA3]\nBon, où est passé Lance? Merde...\n\n[GEN3_14:GENERA3]\nTommy! J'ai besoin d'un coup de main!\n\n[GEN3_15:GENERA3]\nT'en fais pas, je te couvre!\n\n[GEN3_16:GENERA3]\nLes hommes de Diaz se font massacrer!\n\n[GEN3_19:GENERA3]\n~g~Les haïtiens! Ils veulent foutre le deal en l'air! Protège Diaz!\n\n[GEN3_20:GENERA3]\n~g~Va au parking à niveaux où tu peux récupérer le flingue que le Colonel a laissé pour toi.\n\n[GEN3_22:GENERA3]\nSanté de Diaz :\n\n[GEN3_23:GENERA3]\n~g~T'as laissé Lance derrière! Va le chercher!\n\n[GEN3_25:GENERA3]\n~r~Lance est mort!\n\n[GEN3_28:GENERA3]\n~g~Ramène la serviette à Diaz.\n\n[GEN3_29:GENERA3]\n~g~Récupère la serviette et ramène-la à Diaz.\n\n[GEN3_30:GENERA3]\n~r~Il s'est barré avec le pognon! Diaz va te couper les couilles!\n\n[GEN3_33:GENERA3]\n~r~Tu es supposé surveiller Diaz et ses hommes, pas les flinguer!\n\n[GEN3_34:GENERA3]\n~r~Ils ne vont pas pouvoir faire affaire si tu descends les cubains!\n\n[GEN3_35:GENERA3]\n~g~Il a volé le pognon de Diaz!\n\n[GEN3_36:GENERA3]\n~g~Saute sur la moto, rattrape-le et récupère le pognon de Diaz!\n\n[GEN3_37:GENERA3]\n~g~Voilà les Cubains. Surveille le deal en veillant à la sécurité de Diaz et de Lance.\n\n[GEN3_38:GENERA3]\n~r~Diaz est mort! Tu devais le protéger!\n\n[GEN3_39:GENERA3]\n~g~Prends position en haut des escaliers.\n\n[GEN3_44:GENERA3]\n~g~Va avec Lance au rendez-vous et protège Diaz.\n\n[GEN3_40:GENERA3] { reVC update }\nPour ~h~tirer droit devant ~w~lorsque tu es en ~h~moto~w~, appuie sur la ~h~~k~~VEHICLE_FIREWEAPON~.\n\n[GEN3_41:GENERA3] { reVC update }\nPour ~h~tirer droit devant ~w~lorsque tu es en ~h~moto~w~, appuie sur la ~h~~k~~VEHICLE_FIREWEAPON~.\n\n[GEN3_46:GENERA3]\nChiiiier!\n\n[GEN3_47:GENERA3]\nTommy!\n\n[GEN3_48:GENERA3]\nMerde!\n\n[GEN3_50:GENERA3]\n~r~Tu as paumé le fric de Diaz! La prochaine fois, essaie de ne pas cramer le blé!\n\n[GEN3_51:GENERA3]\nEncore des Haïtiens dans un camion merdique!\n\n[GEN3_54:GENERA3]\ns Restez pas plantés là, bande d'abrutis! Butez-moi ce Haïtien de merde!\n\n[GEN3_55:GENERA3]\nTommy! Je reste là et je m'occupe de Diaz!\n\n[GEN3_18:GENERA3]\n~g~Voilà les Cubains. Reste près de Diaz. Surveille les opérations tout en t'assurant que Diaz et Lance sont en sécurité.\n\n[GEN3_56:GENERA3]\n~r~Diaz a été pris dans une embuscade et s'est fait tuer! La prochaine fois, ne le quitte pas des yeux!\n\n[GEN3_57:GENERA3]\nLe Kruger est un fusil d'assaut permettant de viser manuellement à la 1ere personne.\n\n[GEN3_58:GENERA3]\nAppuie sur la touche~h~ R1~w~ et maintiens-la enfoncée pour ~h~viser~w~ avec un fusil d'assaut.\n\n[GEN3_59:GENERA3]\nAppuie sur la touche~h~ L1~w~ et maintiens-la enfoncée pour ~h~viser~w~ avec un fusil d'assaut.\n\n[GEN3_60:GENERA3]\nAppuie sur la touche ~h~~k~~PED_FIREWEAPON~~w~ pour ~h~tirer~w~ avec un fusil d'assaut.\n\n[GEN3_61:GENERA3]\nAppuie sur la touche ~h~~k~~PED_FIREWEAPON~~w~ pour ~h~tirer~w~ avec un fusil d'assaut.\n\n[GEN3_62:GENERA3]\nAppuie sur la touche ~h~~k~~PED_FIREWEAPON~~w~ pour ~h~tirer~w~ avec un fusil d'assaut.\n\n[GEN3_63:GENERA3]\nTu peux fusiller des types de côté sur une ~h~ moto ~w~, mais également ~h~tirer droit devant~w~.\n\n[GEN3_64:GENERA3] { reVC update }\nAppuie sur la touche ~h~~k~~VEHICLE_FIREWEAPON~~w~ pour tirer droit devant toi sur une moto.\n\n[GEN3_65:GENERA3] { reVC update }\nAppuie sur la touche ~h~~k~~VEHICLE_FIREWEAPON~~w~ pour tirer droit devant toi sur une moto.\n\n[GEN3_66:GENERA3] { reVC update }\nAppuie sur la touche ~h~~k~~VEHICLE_FIREWEAPON~~w~ pour tirer droit devant toi sur une moto.\n\n[GEN3_67:GENERA3]\nIl te faut une mitrailleuse pour tirer droit devant toi sur une moto.\n\n[GEN3_53:GENERA3]\nMon argent!\n\n[GEN3_52:GENERA3]\nCes Haitiens pensent qu'ils peuvent se payer Ricardo Diaz!\n\n{=================================== MISSION TABLE GENERA4 ===================================}\n\n[DETON:GENERA4]\nDETONATION :\n\n[COL4_3:GENERA4]\nCONVOI, HALTE!\n\n[COL4_6:GENERA4]\nON EST SOUS LE FEU ENNEMI!\n\n[COL4_7:GENERA4]\nCivil, éloigne-toi du char!\n\n[COL4_8:GENERA4]\nJ'ai dit, dégage! IMMEDIATEMENT!\n\n[COL4_9:GENERA4]\nPOSITIONS DEFENSIVES!\n\n[COL4_11:GENERA4]\nDégagez ce civil de notre chemin, soldat! -Chef, oui, chef!\n\n[COL4_12:GENERA4]\nUn civil dans le char! ARRETEZ-LE!\n\n[COL4_13:GENERA4]\nCeci est un convoi militaire, ne bloquez pas la route!\n\n[COL4_14:GENERA4]\nDescendez-le, soldat.\n\n[COL4_15:GENERA4]\nDégagez ce véhicule civil de la route! -Chef, on déplace le véhicule, chef!\n\n[COL4_17:GENERA4]\nOk, peloton, on dégage!\n\n[COL4_18:GENERA4]\nY'a quelqu'un dans le char, chef!\n\n[COL4_19:GENERA4]\nTrouvez-moi quelques beignets, soldat! -Chef, oui, chef!\n\n[COL4_20:GENERA4]\nCible verrouillée, chef!\n\n[COL4_21:GENERA4]\nTIREUR D'ELITE!\n\n[COL4_22:GENERA4]\nJe me tire d'ici.\n\n[COL4_23:GENERA4]\nObjectif atteint! Peloton, rompez! -Allons manger quelques beignets!\n\n[COL4_24:GENERA4]\nProtocole de sécurité Delta India Echo déclenché! Autodestruction du véhicule initialisée!\n\n[COL4_26:GENERA4]\nPrépare-toi à crever, ordure communiste!\n\n[COL4_B2:GENERA4]\n~r~Le char est parvenu sans problème à destination!\n\n[COL4_B5:GENERA4]\n~r~Le char est détruit!\n\n[COL4_01:GENERA4]\nDiaz était très content et il veut vous voir.\n\n[COL4_02:GENERA4]\nEt c'est une bonne chose?\n\n[COL4_03:GENERA4]\nEvidemment! Même si je commence à penser que Diaz est responsable de notre malheureuse perte...\n\n[COL4_04:GENERA4]\nQu'est-ce qui vous fait dire ça?\n\n[COL4_05:GENERA4]\nOn n'accuse pas comme ça un homme comme Diaz... Je ne faisais que penser à haute voix...\n\n[COL4_06:GENERA4]\nQuoi qu'il en soit, j'ai une proposition qui devrait vous intéresser...\n\n[COL4_07:GENERA4]\nJe n'ai plus le temps de faire des commissions, Cortez.\n\n[COL4_08:GENERA4]\nJ'aurais pensé qu'un homme avec des dettes aussi délicates serait ouvert à toute opportunité. Mais écoutez quand même, Tommy.\n\n[COL4_09:GENERA4]\nAllez-y...\n\n[COL410:GENERA4]\nJ'ai un acheteur pour une pièce d'artillerie qui est emmenée à travers la ville. Récupèrez-la pour moi.\n\n[COL411:GENERA4]\nEt une fois que vous l'aurez, je veux que vous m'appeliez de suite, et...\n\n[COL4_B4:GENERA4]\n~g~Le char est verrouillé. Trouve le moyen d'en faire sortir les occupants.\n\n[COL4_1:GENERA4]\nQu'est-ce qui se passe avec l'artilleur? - Aucune idée, chef!\n\n[COL4_4:GENERA4]\nMontez voir, soldat! - Chef, oui, chef!\n\n[COL4_B1:GENERA4]\n~g~Va faucher la pièce d'artillerie escortée à travers la ville.\n\n[COL4_B3:GENERA4]\n~g~Amène le char dans le garage du colonel avant qu'il ne s'autodétruise.\n\n[COL4_B6:GENERA4]\n~g~Trouve un moyen de piquer le char!\n\n[COL4_B7:GENERA4]\n~g~Conduis le char dans le garage.\n\n[COL4_B8:GENERA4]\n~g~Sors du char et du garage.\n\n{=================================== MISSION TABLE GENERA5 ===================================}\n\n[COL5A_1:GENERA5]\nLes circonstances me forcent à un départ en hâte, amigo.\n\n[COL5A_2:GENERA5]\nQuel est le problème?\n\n[COL5A_3:GENERA5]\nLes français veulent récupérer leur technologie de missile et après le dernier incident,\n\n[COL5A_4:GENERA5]\nje crois que l'heure est venue de me mettre à l'abri.\n\n[COL5A_5:GENERA5]\nCa serait pas plus sûr de partir en avion ?\n\n[COL5A_6:GENERA5]\nJe serais mort avant d'avoir atteint l'enregistrement. D'ailleurs, il faut que je fasse sortir la marchandise du pays.\n\n[COL5A_7:GENERA5]\nBesoin d'un autre flingue?\n\n[COL5A_8:GENERA5]\nVous, amigo, vous en valez dix... hahahaha.\n\n[COL5B_1:GENERA5]\nTommy, vous m'avez bien protégé et servi.\n\n[COL5B_2:GENERA5]\nMais maintenant, vous devez nous laisser avant qu'on arrive en pleine mer.\n\n[COL5B_4:GENERA5]\nMerci, Colonel.\n\n[COL5B_5:GENERA5]\nUne dernière chose, pendant que je suis parti, pouvez-vous surveiller Mercedes pour moi?\n\n[COL5B_6:GENERA5]\nJe crois qu'elle peut se surveiller tout seule, mais soyez tranquille, je garderai l'oeil ouvert.\n\n[COL5B_7:GENERA5]\nMerci, mon ami. Jusqu'à mon retour.\n\n[COL5B_8:GENERA5]\nAdios, amigo.\n\n[COL5_7:GENERA5]\nArrêtez de me tirer dessus!\n\n[COL5_9:GENERA5]\nTommy, empêchez-les de me tirer dessus!\n\n[COL5_10:GENERA5]\nJ'ai l'immunité diplomatique!\n\n[COL5_11:GENERA5]\nNe tirez pas, je suis un Colonel!\n\n[COL5_12:GENERA5]\nTommy, descendez-les, mon pays vous en sera reconnaissant.\n\n[COL5_13:GENERA5]\nTommy, on est submergés par les Français!\n\n[COL5_14:GENERA5]\nTommy, il y a des Français partout! Je déteste ça!\n\n[COL5_15:GENERA5]\nTommy, comment ça va?\n\n[COL5_16:GENERA5]\nCa, c'est pour Piaf et Gainsbourg et votre saloperie de pain français!\n\n[COL5_1:GENERA5]\nA bâbord! A bâbord!\n\n[COL5_2:GENERA5]\nIls attaquent à tribord!\n\n[COL5_3:GENERA5]\nLe pont devant!\n\n[COL5_4:GENERA5]\nIls ont un hélico!\n\n[COL5_B1:GENERA5]\n~g~Protège le colonel et son yacht à tout prix.\n\n[COL5_B2:GENERA5]\n~g~Passe devant et dégage la route pour le yacht du colonel.\n\n[COL5_B3:GENERA5]\n~r~Le colonel est mort!\n\n[COL5_B4:GENERA5]\n~g~Abats l'hélicoptère vous tire dessus.\n\n[COL5B_3:GENERA5]\nJe vous laisse ma vedette personnelle. Gardez-la en témoignage de ma gratitude!\n\n[COL5_B5:GENERA5]\n~g~Descends les hélicos et protège bien le yacht.\n\n[COL5_B6:GENERA5]\n~g~Tu n'as plus de munitions, va en chercher d'autres dans les escaliers du pont supérieur.\n\n[COL5_B7:GENERA5]\n~g~Ta santé diminue. Régénère-la dans les escaliers du pont supérieur.\n\n{=================================== MISSION TABLE HAIT1 ===================================}\n\n[HAM1_A:HAIT1]\nBonjour? Y'a quelqu'un?\n\n[HAM1_B:HAIT1]\nEntre, mon petit, et repose ton esprit.\n\n[HAM1_C:HAIT1]\nTu dois être le grand méchant homme dont m'a parlé mon grand-père.\n\n[HAM1_D:HAIT1]\nIl me dit des choses sur toi, tu sais, quand il me rend visite\n\n[HAM1_E:HAIT1]\net aussi des choses sur les autres qui t'attendent.\n\n[HAM1_F:HAIT1]\nBon, nous sommes tous morts depuis longtemps, mais toi,\n\n[HAM1_G:HAIT1]\nje ne voudrais pas être à ta place, hé hé hé!\n\n[HAM1_H:HAIT1]\nJ'ai reçu un message. De venir ici.\n\n[HAM1_I:HAIT1]\nTu les entends?\n\n[HAM1_J:HAIT1]\nIls crient ton nom, mon garçon, ils doivent vraiment te vouloir, tu ne crois pas?\n\n[HAM1_K:HAIT1]\nMaintenant, si tu rends service à tata Poulet, peut-être qu'elle peut t'aider.\n\n[HAM1_L:HAIT1]\nPeut-être qu'elle peut te donner un petit grigri après tout ça.\n\n[HAM1_M:HAIT1]\nTe donner de la magie pour donner le mauvais oeil au policier, mmmm?\n\n[HAM1_N:HAIT1]\nEcoute, tout ça est très, hum... me donner quoi?\n\n[HAM1_O:HAIT1]\nJe... Je crois que je me suis planté d'adresse...\n\n[HAM1_P:HAIT1]\nFais-ça pour moi, Tommy...\n\n[HAM1_Q:HAIT1]\nLes Cubains, ces vilains coqs arrogants, hum,\n\n[HAM1_R:HAIT1]\nont fait des ennuis à mes adorables garçons haïtiens.\n\n[HAM1_S:HAIT1]\nEt maintenant, ils ont dit au policier où je cachais mes poudres!\n\n[HAM1_T:HAIT1]\nIls pensent que c'est des drogues, les idiots!\n\n[HAM1_U:HAIT1]\nAlors, sois un gentil garçon, Tommy, et va chercher les poudres de tata Poulet.\n\n[HAM1_V:HAIT1]\nOui, d'accord, d'accord.\n\n[HAM1_1:HAIT1]\n~g~Les policiers se rapprochent des poudres! Va les récupérer avant eux!\n\n[HAM1_2:HAIT1]\n~r~Les policiers ont trouvé la cachette les premiers!\n\n[HAM1_3:HAIT1]\n~g~Ramène tout ça à la planque!\n\n[HAM1_4:HAIT1]\n~g~Bien! Maintenant, la suivante!\n\n[HAM1_6:HAIT1]\n~r~La cachette a été détruite, imbécile!\n\n[HAM1_7:HAIT1]\n~g~Les policiers ont les poudres! Récupère-les avant qu'ils filent!\n\n[HAM1_8:HAIT1]\n~g~Les flics sont en route pour récupérer les poudres, magne-toi!\n\n[HAT_1A:HAIT1]\n~g~Bouge pas d'un poil, connard!\n\n{=================================== MISSION TABLE HAIT2 ===================================}\n\n[HAT2_B1:HAIT2]\n~g~Va à la camionnette contenant les bombes volantes.\n\n[HAT2_B2:HAIT2]\nTue les Cubains...\n\n[HAT2_B4:HAIT2]\n... Et détruis leurs bateaux!\n\n[HAT2_B5:HAIT2]\n~g~Les Cubains essayent de s'enfuir! Ne les laisse pas faire!\n\n[HAT2_B6:HAIT2]\n~r~L'avion télécommandé est hors de portée!\n\n[HAT2_B7:HAIT2]\n~g~Un des Cubains s'échappe en voiture. Ne laisse aucun témoin!\n\n[HAT2_B8:HAIT2]\n~r~Tu n'as plus d'avions télécommandés!\n\n[HAT2_B9:HAIT2]\nAvions télécommandés :\n\n[HAT2_1:HAIT2]\nOh, désolé, j'ai dû me tromper d'adresse...\n\n[HAT2_2:HAIT2]\nEh bien, entre donc te détendre en buvant un peu de thé.\n\n[HAT2_3:HAIT2]\nTu as quelque chose pour moi, Tommy?\n\n[HAT2_4:HAIT2]\nOuais...\n\n[HAT2_5:HAIT2]\nCet endroit me semble familier. Un vague souvenir d'enfance, un air de déjà vu...\n\n[HAT2_6:HAIT2]\nTommy, je voudrais te demander de faire une petite commission pour moi...\n\n[HAT2_7:HAIT2]\nTu me rappelles quelqu'un que...\n\n[HAT2_8:HAIT2]\nLes Cubains ont des bateaux très rapides qui leur servent à traverser les mers avec de la drogue.\n\n[HAT2_9:HAIT2]\nC'est leur gagne-pain.\n\n[HAT2_10:HAIT2]\nMon neveu a fabriqué quelques bombes volantes pour nous en débarrasser.\n\n[HAT2_11:HAIT2]\nTransforme leurs bateaux en allumettes!\n\n[HAT2_12:HAIT2]\nBon, merci pour le thé.\n\n[HAT2_B3:HAIT2] { reVC update }\nAppuie sur la touche ~h~~k~~VEHICLE_FIREWEAPON~~w~ pour larguer une bombe ou sur ~h~~k~~VEHICLE_ENTER_EXIT~~w~ pour annuler.\n\n{=================================== MISSION TABLE HAIT3 ===================================}\n\n[HAM3_A:HAIT3]\nSalut, euh, je... Je cherche quelqu'un dans le coin...\n\n[HAM3_B:HAIT3]\nTu as l'air d'avoir faim, Tommy.\n\n[HAM3_C:HAIT3]\nOn se connait?\n\n[HAM3_D:HAIT3]\nChut!\n\n[HAM3_E:HAIT3]\nEncore une chose et je te laisse partir, Tommy.\n\n[HAM3_F:HAIT3]\nMes garçons sont en guerre contre les Cubains.\n\n[HAM3_G:HAIT3]\nMais pas de revolvers.\n\n[HAM3_H:HAIT3]\nHum, mais les Cubains ont une suprise qui les attend!\n\n[HAM3_I:HAIT3]\nPendant qu'ils se battent dans les rues, prends ce fusil et tue-les dans la confusion!\n\n[HAM3_J:HAIT3]\nPersonne ne te verra, personne ne t'entendra!\n\n[HAM3_K:HAIT3]\nSi tu fais ça pour tata Poulet, Tommy, tu ne seras plus lié aux cordons de mon tablier!\n\n[HAM3_1:HAIT3]\n~g~On doit gagner cette bataille! Si tous les Haïtiens meurent, c'est foutu!\n\n[HAM3_3:HAIT3]\n~g~Les Cubains risquent de tricher, alors fais attention.\n\n[HAM3_4:HAIT3]\n~r~Tu as été repéré! C'est foutu!\n\n[HAM3_5:HAIT3]\n~g~Tu dois tuer les cubains de loin. Ne te fais pas voir.\n\n[HAM3_8:HAIT3]\n~g~Les Haïtiens se font descendre! Vise mieux!\n\n[HAM3_7:HAIT3]\n~g~Fais gaffe! Les Cubains ont amené des renforts. Liquide-les tous!\n\n[HAM3_2:HAIT3]\n~r~Les Haïtiens sont morts!\n\n[HAM3_L:HAIT3]\nTata...\n\n{=================================== MISSION TABLE HOTEL ===================================}\n\n[INTB_A:HOTEL]\nTommy! Ca fait une paye!\n\n[INTB_B:HOTEL]\nSalut Sonny...\n\n[INTB_C:HOTEL]\nJe sais, je sais, t'es submergé par l'émotion, hein?\n\n[INTB_D:HOTEL]\nQuinze piges et c'est comme si c'était hier!\n\n[INTB_E:HOTEL]\nC'est une façon de voir les choses...\n\n[INTB_F:HOTEL]\nHé, bosser pour la famille, tu sais, c'est pas de la tarte,\n\n[INTB_G:HOTEL]\nmais la famille veille toujours sur les siens, tu comprends?\n\n[INTB_H:HOTEL]\nBon, raconte un peu comment l'affaire s'est passée? Ca y est, t'es blindé?\n\n[INTB_I:HOTEL]\nEcoute, Sonny, on s'est fait piéger. C'était une embuscade. Et ils ont buté Harry et Lee.\n\n[INTB_J:HOTEL]\nJ'espère pour toi que tu rigoles, Tommy... Et t'as plutôt intérêt à toujours avoir le fric...\n\n[INTB_K:HOTEL]\n... Non... Sonny... J'ai plus le fric...\n\n[INTB_L:HOTEL]\nC'était mon fric, Tommy! MON FRIC!!!\n\n[INTB_M:HOTEL]\nVaudrait mieux pas que t'essayes de me baiser Tommy, parce que je suis pas le genre à aimer ça...\n\n[INTB_N:HOTEL]\nAttend Sonny...\n\n[INTB_O:HOTEL]\nJe te donne ma parole d'honneur que je vais récupérer ton fric et la dope.\n\n[INTB_P:HOTEL]\nEt en prime, je t'enverrai les couilles de ceux qui ont fait ça!\n\n[INTB_Q:HOTEL]\nCa, je le sais déjà... Tommy, t'es pas con, mais je te préviens, moi non plus...\n\n[INTB_R:HOTEL]\nEt si c'était pas toi, tu serais déjà mort...\n\n[INTB_S:HOTEL]\nMais j'ai un faible pour toi et en souvenir du passé, je vais te laisser t'en charger.\n\n[INTB_T:HOTEL]\nT'en fais pas, Sonny, t'as ma parole!\n\n[INTB_U:HOTEL]\nJe te tiens au courant, ciao.\n\n{=================================== MISSION TABLE ICECRE1 ===================================}\n\n[ICC1_4:ICECRE1]\n~g~Il n'y a aucun client dans ce secteur. Essaye ailleurs.\n\n[ICC1_5:ICECRE1]\nDeals effectués :\n\n[ICC1_7:ICECRE1]\n~g~Tu reçois de l'argent pour chaque transaction faite, mais plus tu fais d'affaires, plus tu attires l'attention de la police.\n\n[ICC1_8:ICECRE1]\n~g~Pour effectuer une transaction, ~h~gare ta camionnette ~g~et appuie sur la ~h~~k~~VEHICLE_HORN~ ~g~pour jouer le jingle et attirer les clients.\n\n[ICC1_9:ICECRE1]\n~g~Les gangs locaux n'apprécient pas qu'on fasse des affaires sur leur territoire. Attends-toi à des représailles.\n\n[ICC1_10:ICECRE1]\n~g~Tu as fait ~1~ deals!\n\n[ICC1_11:ICECRE1]\n~g~Tu as fait ~1~ deals!\n\n[ICC1_13:ICECRE1]\n~r~T'as fait aucun deal!\n\n[ICC1_14:ICECRE1]\nUSINE DE CREME GLACEE OK\n\n[ICC1_15:ICECRE1]\n~g~L'usine de crème glacée génère dorénavant un revenu de $~1~ maximum. Pense à récupérer le fric régulièrement.\n\n[ICC1_16:ICECRE1]\n~g~Utilise la camionnette de Mr Whoopee pour distribuer les produits Cherry Poppers dans Vice City.\n\n[ICE_AT1:ICECRE1]\nUSINE DE CREME GLACEE OK\n\n[ICE_AT2:ICECRE1]\n~g~L'usine Cherry Popper génère dorénavant un revenu de $~1~ maximum. Pense à récupérer le fric régulièrement.\n\n[ICC1_17:ICECRE1]\nMission Distribution terminée\n\n[ICC1_18:ICECRE1]\nTotal des ventes de glaces : $~1~\n\n[ICC1_19:ICECRE1]\nTotal de deals réalisés : ~1~\n\n{=================================== MISSION TABLE ICECUT ===================================}\n\n[ICC1_A:ICECUT]\nT'es qui toi?\n\n[ICC1_B:ICECUT]\nLe nouveau proprio.\n\n[ICC1_C:ICECUT]\nEst-ce que t'as déjà été enfant?\n\n[ICC1_D:ICECUT]\nMais de quoi tu parles?\n\n[ICC1_E:ICECUT]\nAs-tu été un gosse?\n\n[ICC1_F:ICECUT]\nOuais! Vas-y, c'est quoi ton problème?\n\n[ICC1_G:ICECUT]\nJe le savais. Un chiard.\n\n[ICC1_H:ICECUT]\nUn putain de gosse pourri gâté, un chialeur, un emmerdeur, un bébé à sa maman!\n\n[ICC1_I:ICECUT]\nUn bébé... Un horrible et dégoûtant petit morveux. Ouin ouin.\n\n[ICC1_J:ICECUT]\nTa maman t'aime pas. Petite merde!\n\n[ICC1_K:ICECUT]\nHé! Calme-toi.\n\n[ICC1_L:ICECUT]\nJe HAIS les mouflets et les mômes.\n\n[ICC1_M:ICECUT]\nCe sont des putains de pourris gâtés, de chialeurs, d'emmerdeurs...\n\n[ICC1_N:ICECUT]\nCa suffit maintenant!\n\n[ICC1_O:ICECUT]\nC'est quoi ton problème?\n\n[ICC1_P:ICECUT]\nTu confectionnes des glaces, non? C'est un truc pour les gosses.\n\n[ICC1_Q:ICECUT]\nT'es quoi comme genre de cinglé, toi?\n\n[ICC1_R:ICECUT]\nQue je comprenne... A quoi ça sert de rendre les gosses heureux si tu les déteste?\n\n[ICC1_S:ICECUT]\nEspèce d'abruti, petit curieux, fouinard-\n\n[ICC1_T:ICECUT]\nLa ferme!\n\n[ICC1_U:ICECUT]\n-de merde!\n\n[ICC1_V:ICECUT]\nLes glaces c'est une couverture.\n\n[ICC1_W:ICECUT]\nOn fait aussi dans autre chose que les produits laitiers.\n\n[ICC1_X:ICECUT]\nEt si je vois un gosse, j'en fait mon affaire.\n\n[ICC1_Y:ICECUT]\nN'est-ce pas, gamin? Ouais, c'est bien ça. Ta maman t'aime pas.\n\n[ICC1_Z:ICECUT]\nElle te DETESTE!\n\n[ICC1_ZA:ICECUT]\nPROPRIETE ACQUISE!\n\n{=================================== MISSION TABLE INTRO ===================================}\n\n[INT1_A:INTRO]\nTommy Vercetti... Oh, merde!\n\n[INT1_B:INTRO]\nJ'pensais pas qu'ils le laisseraient sortir un jour...\n\n[INT1_C:INTRO]\nIl a gardé un profil bas, pour se faire oublier...\n\n[INT1_D:INTRO]\nMais les gens vont vite retrouver la mémoire\n\n[INT1_E:INTRO]\nquand ils vont le voir débouler dans les rues du voisinage.\n\n[INT1_F:INTRO]\nEt ça va pas être bon pour les affaires...\n\n[INT1_G:INTRO]\nEt alors, qu'est-ce qu'on va faire, Sonny?\n\n[INT1_H:INTRO]\nOn le traite comme un vieil ami et on lui trouve de quoi s'occuper en-dehors de la ville. OK?\n\n[INT1_I:INTRO]\nOn parlait justement de s'étendre vers le sud... Pas vrai?\n\n[INT1_J:INTRO]\nVice City, c'est du 24 carats, maintenant.\n\n[INT1_K:INTRO]\nLes colombiens, les mexicains... Putain,\n\n[INT1_L:INTRO]\nmême les réfugiés cubains se taillent une belle part du gâteau!\n\n[INT1_M:INTRO]\nMais ils font tous dans la dope, Sonny!\n\n[INT1_N:INTRO]\nAucune famille ne touche à cette merde!\n\n[INT1_O:INTRO]\nLes temps changent...\n\n[INT1_P:INTRO]\nLes familles ne peuvent pas rester les bras croisés pendant que nos adversaires ramassent le jackpot.\n\n[INT1_Q:INTRO]\nAlors, on envoie un mec là-bas faire le sale boulot\n\n[INT1_R:INTRO]\net pour nous en tailler une bonne part. OK?\n\n[INT1_S:INTRO]\nC'est qui, notre contact là-bas?\n\n[INT1_T:INTRO]\nKen Rosenberg, le con d'avocat...\n\n[INT1_U:INTRO]\nEt comment il va faire pour tenir Vercetti en laisse?\n\n[INT1_V:INTRO]\nIl aura pas besoin de faire ça.\n\n[INT1_W:INTRO]\nOn le lâche juste dans Vice City\n\n[INT1_X:INTRO]\net on lui refile un peu de cash pour commencer. OK?\n\n[INT1_Y:INTRO]\nDonne-lui quelques mois...\n\n[INT1_Z:INTRO]\nEt puis, on descendra\n\n[INT1_A1:INTRO]\nlui rendre une petite visite, tu saisis?\n\n[INT1_A2:INTRO]\nHistoire de voir comment il se débrouille...\n\n[INT2_A:INTRO]\nHey, salut les gars, c'est moi, Ken Rosenberg! Hé ! Super!\n\n[INT2_B:INTRO]\nBon, euh, je vais vous conduire au rendez-vous, ok?\n\n[INT2_C:INTRO]\nJ'ai parlé avec les fournisseurs, ils sont très, hé hé,\n\n[INT2_D:INTRO]\ntrès impatients de commencer cette affaire, et... euh,\n\n[INT2_E:INTRO]\nsi tout se passe sans accroc, on devrait... euh,\n\n[INT2_F:INTRO]\ns'en mettre plein les poches, ce qui est vraiment, vous savez...\n\n[INT2_G:INTRO]\nune bonne chose...\n\n[INT2_H:INTRO]\nOk. Bon, ils sont frères, ok.\n\n[INT2_I:INTRO]\nIl y en a un qui fait marcher... euh, l'affaire\n\n[INT2_J:INTRO]\net l'autre qui s'occupe du transport en hélicoptère.\n\n[INT2_K:INTRO]\nMaintenant, ils opèrent du Mexique,\n\n[INT3_A:INTRO]\nOk, c'est eux, dans l'hélico.\n\n[INT3_B:INTRO]\nBon, voilà le deal.\n\n[INT3_C:INTRO]\nIls veulent un échange en terrain découvert.\n\n[INT3_D:INTRO]\nOK? Bon, allons-y et restez groupés.\n\n[INT3_E:INTRO]\nBon, personne s'énerve, maintenant.\n\n[INT3_F:INTRO]\nJe suis ici! Le moteur tourne!\n\n[INT3_G:INTRO]\nTu l'as?\n\n[INT3_H:INTRO]\nDe la colombienne 100% pure, la meilleure qualité, amigo.\n\n[INT3_I:INTRO]\nLes billets?\n\n[INT3_J:INTRO]\nDes 10 et des 20... usagés.\n\n[INT3_L:INTRO]\nAllez! Sors-nous de là! Roule!\n\n[INTRO1:INTRO]\nJe sors la tête d'un caniveau pour une seconde de défonce, et le destin me chie de la merde plein la gueule!\n\n[INTRO2:INTRO]\nVa roupiller.\n\n[INTRO3:INTRO]\nQu'est-ce que tu vas faire?\n\n[INTRO4:INTRO]\nJe passerai à ton bureau demain et on essayera de trouver une solution à ce merdier.\n\n[INT3_K:INTRO]\nJe crois que nous allons faire affaire, amigo, hé hé hé!\n\n[INT3_M:INTRO]\nLaisse-moi voir.\n\n[INT2_L:INTRO]\nnon, non, non, attends...\n\n{=================================== MISSION TABLE KENT1 ===================================}\n\n[KPM1_A:KENT1]\nD'accord, mon vieux, je vais sauver ton petit ami.\n\n[KPM1_B:KENT1]\nDe quoi tu m'causes?\n\n[KPM1_C:KENT1]\nTu connais ce branleur, Diaz, la grande gueule...\n\n[KPM1_D:KENT1]\nIl a ton pote, Lance. Il paraît que celui-ci a essayé de lui sauter sur le poil.\n\n[KPM1_E:KENT1]\nMais il a pas sauté assez haut, si tu vois ce que je veux dire...\n\n[KPM1_F:KENT1]\nOù il l'a emmené? Et tourne pas autour du pot!\n\n[KPM1_G:KENT1]\nT'énerve pas! Ils l'ont emmené de l'autre côté de la ville, à la décharge.\n\n[KPM1_H:KENT1]\nPutain... Pauvre cinglé...\n\n[KPM1_2:KENT1]\n~r~Tu étais supposé sortir Lance vivant de ce guêpier!\n\n[KPM1_3:KENT1]\nSANTE DE LANCE :\n\n[RESC_1:KENT1]\nTu peux te servir d'un flingue?\n\n[RESC_2:KENT1]\nOuais... je pense... Content de te voir moi aussi.\n\n[RESC_3:KENT1]\nSortons de là!\n\n[RESC_4:KENT1]\nCa fout tous mes plans en l'air, tes conneries. Cette fois-ci, t'as vraiment merdé pour de bon, Lance!\n\n[RESC_5:KENT1]\nIl a descendu mon frère! Tu croyais que j'allais faire quoi? Lui tondre sa pelouse?\n\n[RESC_6:KENT1]\nVa falloir qu'on liquide ce connard de Diaz avant qu'il en fasse autant avec nous.\n\n[RESC_7:KENT1]\nVa récupérer et retrouve-moi sur le pont de Star Island. Ok?\n\n[RESC_8:KENT1]\nOK.\n\n[KPM1_1:KENT1]\n~g~Lance est retenu prisonnier dans la décharge. Va le sauver!\n\n[KPM1_4:KENT1]\n~g~Amène Lance à l'hosto!\n\n[M_PASSN:KENT1]\nMISSION TERMINEE!\n\n[KPM1_5:KENT1]\n~g~Les mecs de Diaz sont après toi, amène Lance à l'hosto.\n\n{=================================== MISSION TABLE KICKSTT ===================================}\n\n[KICK1_2:KICKSTT]\n~r~Tu n'as pas récupéré la moto assez vite!\n\n[KICK1_7:KICKSTT]\n~r~Tu as niqué la moto!\n\n[KICK1_8:KICKSTT]\n~g~Monte sur la moto!\n\n[KICK1_T:KICKSTT]\nTEMPS PRIS :\n\n[KICKTM:KICKSTT]\n~b~TEMPS DE L'EPREUVE : ~1~:~1~\n\n[KICKTM2:KICKSTT]\n~b~TEMPS DE L'EPREUVE : ~1~:0~1~\n\n[GETBIKE:KICKSTT]\n~g~Il te reste ~1~ secondes pour retourner à une moto avant la fin de la mission.\n\n[KICK1_1:KICKSTT]\n~g~Termine le parcours aussi vite que possible.\n\n[KICK1_6:KICKSTT]\n~g~Bien joué!\n\n[KICK_10:KICKSTT]\n~g~Utilise la Sanchez pour terminer le parcours sans oublier aucun point de passage.\n\n[KICK_12:KICKSTT]\n~r~Tu t'es dégonflé!\n\n[KICK_13:KICKSTT]\n~r~T'as mis trop de temps!\n\n[KICK_11:KICKSTT]\n~g~Pour quitter la mission, marche sur le ~q~marqueur rose~g~.\n\n{=================================== MISSION TABLE LAWYER1 ===================================}\n\n[LAW1_A:LAWYER1]\nVa roupiller, qu'il m'a dit -\n\n[LAW1_B:LAWYER1]\n- et je suis resté toute la nuit le cul vissé sur cette chaise dans le noir à boire du café!\n\n[LAW1_C:LAWYER1]\nC'est la merde. On est baisés jusqu'à l'os, mon pote!\n\n[LAW1_D:LAWYER1]\nEcoute-moi, ces balaises, ils vont débarquer ici pour m'arracher la tête! C'est pas possible!\n\n[LAW1_E:LAWYER1]\nJ'me suis pas tapé l'école de droit pour ça! Putain, qu'est-ce qu'on va faire maintenant?\n\n[LAW1_F:LAWYER1]\nFerme-la, pose ton cul et détends-toi. Je vais te dire ce qu'on va faire.\n\n[LAW1_G:LAWYER1]\nFaut que tu trouves les types qui nous ont fauché la coke et après je les descends.\n\n[LAW1_H:LAWYER1]\nBonne idée. Excellente idée. Laisse-moi réfléchir, laisse-moi réfléchir.\n\n[LAW1_I:LAWYER1]\nJe sais! Il y a ce Colonel à la retraite, le Colonel Juan Garcia Cortez.\n\n[LAW1_J:LAWYER1]\nC'est lui qui m'a aidé à organiser l'affaire\n\n[LAW1_K:LAWYER1]\nen-dehors des truands établis de Vice City. Ok?\n\n[LAW1_L:LAWYER1]\nMaintenant, écoute. Il organise une fiesta dans la baie, sur son yatch du luxe\n\n[LAW1_M:LAWYER1]\net tous les gros pontes de Vice City seront là!\n\n[LAW1_N:LAWYER1]\nJ'ai une invitation, bien sûr que j'ai une invitation,\n\n[LAW1_O:LAWYER1]\nmais il est pas question que je sorte d'ici. Non, pas question!\n\n[LAW1_P:LAWYER1]\nFerme-la, je t'ai dit! Je vais y aller moi-même...\n\n[LAW1_Q:LAWYER1]\nAttends deux secondes! Tu sais, moi aussi, j'aime bien 1978, mais là, c'est pas une soirée bière et striptease...\n\n[LAW1_R:LAWYER1]\nJe veux dire, sans vouloir t'offenser, hein, tu risque de te faire refouler à l'entrée, quoi...\n\n[LAW1_S:LAWYER1]\nY'a un problème avec mes fringues?\n\n[LAW1_T:LAWYER1]\nBon, écoute. Fais un saut chez Rafael, dis-lui que tu viens de ma part et il te relookera.\n\n[LAW1_U:LAWYER1]\nOk, allez, vas-y...\n\n[LAWP_1:LAWYER1]\nBuenas noches.\n\n[LAWP_2:LAWYER1]\nSi je comprends bien, c'est M. Rosenberg qui vous envoie.\n\n[LAWP_3:LAWYER1]\nJ'espère que de récents problèmes n'ont pas affecté sa santé, ou ... hum...\n\n[LAWP_4:LAWYER1]\nson équilibre mental, M....?\n\n[LAWP_5:LAWYER1]\nVercetti. Il fait simplement un peu... d'agoraphobie.\n\n[LAWP_6:LAWYER1]\nExcellent, excellent. Et vous?\n\n[LAWP_7:LAWYER1]\nJe veux juste ma marchandise.\n\n[LAWP_8:LAWYER1]\nAh. C'est un malheureux concours de circonstances pour toutes les personnes impliquées...\n\n[LAWP_9:LAWYER1]\nBien entendu, j'ai de mon côté ordonné une enquête...\n\n[LAWP_10:LAWYER1]\nMais c'est un problème délicat qui nécessite du temps...\n\n[LAWP_11:LAWYER1]\nPeut-être en reparlerons-nous plus tard, voulez-vous?\n\n[LAWP_12:LAWYER1]\nEn attendant, laissez-moi vous présenter ma fille...\n\n[LAWP_13:LAWYER1]\nMercedes!\n\n[LAWP_14:LAWYER1]\nCaramia, pourrais-tu t'occuper de notre invité pendant que je m'occupe des autres convives?\n\n[LAWP_15:LAWYER1]\nD'accord, papa.\n\n[LAWP_16:LAWYER1]\nVeuillez m'excuser...\n\n[LAWP_17:LAWYER1]\nMercedes?\n\n[LAWP_18:LAWYER1]\nEt il faut vivre avec ça...\n\n[LAWP_19:LAWYER1]\nQuoi qu'il en soit, laissez-moi vous montrer quelques uns de nos distingués invités...\n\n[LAWP_20:LAWYER1]\nCelui-ci est le membre du congrès Alex Shrub accompagné par la star montante siliconée Candy Suxxx...\n\n[LAWP_21:LAWYER1]\nEt connaissez-vous ma charmante femme Laura? Non?\n\n[LAWP_22:LAWYER1]\nEh bien, malheureusement, elle est en Alabama, voici Candy.\n\n[LAWP_23:LAWYER1]\nEt là-bas, nous avons l'ailier vedette des Mambas de Vice City, BJ.\n\n[LAWP_24:LAWYER1]\ntoujours aussi charmeur\n\n[LAWP_25:LAWYER1]\nMais je l'ai plaqué et mis dans une chaise roulante!\n\n[LAWP_26:LAWYER1]\nHa ha! Excellent!\n\n[LAWP_27:LAWYER1]\nEn ce moment, je cherche une nouvelle propriété de luxe.\n\n[LAWP_28:LAWYER1]\nEt ce molusque c'est Jezz Torrent,\n\n[LAWP_29:LAWYER1]\nLe chanteur principal des Love Fist.\n\n[LAWP_30:LAWYER1]\nSavez-vous... comment ils jouent au ping-pong, en Thaïlande?\n\n[LAWP_31:LAWYER1]\nJe vais vous le dire...\n\n[LAWP_32:LAWYER1]\nIls n'utilisent pas de raquettes, si vous voyez ce que je veux dire!\n\n[LAWP_33:LAWYER1]\nL'impotent.\n\n[LAWP_34:LAWYER1]\nEt le trio bavard.\n\n[LAWP_35:LAWYER1]\nCette outre à sueur ronflante est le bras droit handicapé de papa, Gonzales.\n\n[LAWP_36:LAWYER1]\nLes deux autres sont le Pasteur Richards\n\n[LAWP_37:LAWYER1]\net un réalisateur pseudo intellectuel nommé Steve Scott.\n\n[LAWP_38:LAWYER1]\n...passion avec les envahisseuses nymphomanes,\n\n[LAWP_39:LAWYER1]\nLe requin géant s'amène et\n\n[LAWP_40:LAWYER1]\nil leur bouffe simplement les couilles!\n\n[LAWP_41:LAWYER1]\nAh, c'est là. Vous n'avez jamais vu un truc pareil avant, hein?\n\n[LAWP_42:LAWYER1]\nColonel!\n\n[LAWP_43:LAWYER1]\nVos fêtes sont toujours aussi réussies, hahahahha!\n\n[LAWP_44:LAWYER1]\nJe ne puis que m'excuser de mon arrivée tardive.\n\n[LAWP_45:LAWYER1]\nAh, de nada amigo. Comment allez-vous?\n\n[LAWP_46:LAWYER1]\nNos affaires sont très difficile - Les barbares sont aux portes de la ville.\n\n[LAWP_47:LAWYER1]\nL'heure est venue de récompenser les amis et de liquider les ennemis, amigo.\n\n[LAWP_48:LAWYER1]\nC'est qui, la grande gueule?\n\n[LAWP_49:LAWYER1]\nRicardo Diaz, c'est Mr.Coke.\n\n[LAWP_50:LAWYER1]\nMercedes!\n\n[LAWP_51:LAWYER1]\nOh, je raccompagnais justement mon ami en ville.\n\n[LAWP_52:LAWYER1]\nUne autre fois, Ricardo!\n\n[LAWP_53:LAWYER1]\nPartons d'ici!\n\n[LAWP_54:LAWYER1]\nEn fait, emmenez-moi plutôt au Pole Position club.\n\n[LAW1_2:LAWYER1]\n~g~Va au yatch du Colonel.\n\n[LAW1_4:LAWYER1]\n~r~Tu as tué la fille du Colonel!\n\n[LAW1_5:LAWYER1]\nVous allez travailler pour mon père?\n\n[LAW1_6:LAWYER1]\nPeut-être.\n\n[LAW1_7:LAWYER1]\nCa vous ennuie si je pose ma main sur votre genou?\n\n[LAW1_8:LAWYER1]\nPeut-être...\n\n[LAW1_9:LAWYER1]\nC'est trop dur d'avoir un père riche et puissant! Vamos!\n\n[LAW1_10:LAWYER1]\nA plus tard, mon mignon!\n\n[LAW1_11:LAWYER1]\nSans aucun doute.\n\n[LAW1_12:LAWYER1]\nMmmm... Chouette bécane.\n\n[LAW1_13:LAWYER1]\nNon! Ma moto!\n\n[LAW1_3:LAWYER1]\n~g~Emmène la fille du Colonel au Pole Position Club.\n\n[HELP20:LAWYER1]\nSuis le ~h~point T-shirt~w~ sur le radar pour trouver Rafael.\n\n[LAW1_14:LAWYER1]\nMmmm, j'aime beaucoup ta grosse moto.\n\n[LAW1_15:LAWYER1]\nOuais, bébé, je viens de piquer ça à ce con\n\n{=================================== MISSION TABLE LAWYER2 ===================================}\n\n[LAW2_A:LAWYER2]\nAh! Eh bien, j'espère que tu t'es bien amusé! Parce que moi, je suis mort d'inquiétude! Qu'est-ce que t'as trouvé?\n\n[LAW2_B:LAWYER2]\nQu'y'a plus de criminels dans cette ville qu'en taule. Faut qu'on trouve une piste dans la rue.\n\n[LAW2_C:LAWYER2]\nAttends, laisse-moi réfléchir, voyons...\n\n[LAW2_D:LAWYER2]\nAh! J'ai trouvé!\n\n[LAW2_E:LAWYER2]\nBon, il y a bien cet anglais, une espèce de déchet du biz de la musique,\n\n[LAW2_F:LAWYER2]\nil est connu sous le nom de Kent Paul.\n\n[LAW2_G:LAWYER2]\nQuoi qu'il en soit, il a le nez plongé dans la merde de Vice City depuis un moment\n\n[LAW2_H:LAWYER2]\net ça, si quelqu'un sait où sont les 20 kilos de coke,\n\n[LAW2_I:LAWYER2]\nc'est bien lui, ok? Il est toujours fourré au Malibu...\n\n[LAW2_J:LAWYER2]\nJe vais aller lui rendre une petite visite...\n\n[LAW2B_A:LAWYER2]\nD'où tu sors, toi?\n\n[LAW2B_B:LAWYER2]\nJe cherche un oiseau dans ton genre depuis une éternité...\n\n[LAW2B_C:LAWYER2]\nKent Paul, mon pote. Ouais, dans le coin, c'est moi le patron.\n\n[LAW2B_D:LAWYER2]\nJe cherche un Anglais...\n\n[LAW2B_E:LAWYER2]\nJe résouds les problèmes, si tu vois ce que je veux dire?\n\n[LAW2B_F:LAWYER2]\nJe vais m'occuper de toi. Quoi que tu demandes, tu l'auras...\n\n[LAW2B_G:LAWYER2]\nNe t'inquiéte absolument de rien.\n\n[LAW2B_H:LAWYER2]\nDégage, chérie!\n\n[LAW2B_I:LAWYER2]\nHé hé hé hé hé!\n\n[LAW2B_J:LAWYER2]\nC'est toi, Kent Paul? Je suis un pote de Rosenberg...\n\n[LAW2B_K:LAWYER2]\nRosenberg...Rosenberg... Ah, ce cinglé qui poursuit les ambulances!\n\n[LAW2B_L:LAWYER2]\nCe mec peut défendre un innocent jusqu'au couloir de la mort!\n\n[LAW2B_M:LAWYER2]\nDonne-nous un autre verre!\n\n[LAW2B_N:LAWYER2]\nOn est tous des comédiens.\n\n[LAW2B_O:LAWYER2]\nEcoute-moi, il me manque vingt kilos et un gros tas de pognon...\n\n[LAW2B_P:LAWYER2]\nUne affaire de drogue? C'est toujours des pièges à con...\n\n[LAW2B_Q:LAWYER2]\nQu'est-ce que tu sais à ce propos?\n\n[LAW2B_R:LAWYER2]\nHé! Hé! Là où je voulais en venir,\n\n[LAW2B_S:LAWYER2]\nc'est à un cuisinier-trompettiste qui deale à l'extérieur de la cuisine d'un hôtel sur Ocean Drive.\n\n[LAW2B_T:LAWYER2]\nIl avait l'air très content de lui, ces derniers temps. Tu pourrais peut-être aller voir ça de plus près...\n\n[LAW2B_U:LAWYER2]\nBon, je vais y aller. A plus tard.\n\n[LAW2B_V:LAWYER2]\nOuais, c'est ça. Allez, dégage, imbécile ou je te botte le cul!\n\n[LAW2B_W:LAWYER2]\nDonne-moi à boire et putain, où est cette salope?\n\n[LAW2C_A:LAWYER2]\nOuais, c'est bien, massacre-le, ça devrait le rendre plus bavard.\n\n[LAW2C_B:LAWYER2]\nT'en veux aussi?\n\n[LAW2C_C:LAWYER2]\nHé, relax, je veux la même chose que toi, mon frère.\n\n[LAW2C_D:LAWYER2]\nAh ouais? Et c'est quoi?\n\n[LAW2C_E:LAWYER2]\nTon fric et la blanche de mon regretté frère. Malheureusement, tu viens de refroidir notre piste.\n\n[LAW2C_F:LAWYER2]\nC'était un accident. Dégage.\n\n[LAW2C_G:LAWYER2]\nHé, hé! Pas la peine de jouer les justiciers solitaires avec moi!\n\n[LAW2C_H:LAWYER2]\nVoilà comment je vois les choses... On est deux mecs dans une ville étrange. Et on a besoin de veiller l'un sur l'autre.\n\n[LAW2C_I:LAWYER2]\nJ'ai pas besoin de toi, mon frère...\n\n[LAW2C_J:LAWYER2]\nT'en es sûr? Tiens, attrape!\n\n[LAW2C_K:LAWYER2]\nSuis-moi!\n\n[LAW2_1:LAWYER2]\nQu'est-ce que tu regardes?\n\n[LAW2_2:LAWYER2]\nTu ferais mieux de commencer à causer...\n\n[LAW2_3:LAWYER2]\nSuce-moi, connard!\n\n[LAW2_4:LAWYER2]\nPar là!\n\n[LAW2_5:LAWYER2]\nJe vais voir ce que je peux trouver. Je garde un oeil sur toi, Tommy.\n\n[LAW2_6:LAWYER2]\n~g~Va au Malibu Club et trouve Kent Paul.\n\n[LAW2_7:LAWYER2]\n~g~Trouve le cuisinier sur Ocean Drive.\n\n[LAW2_10:LAWYER2]\n~g~Retourne à l'hôtel.\n\n[LAW2_11:LAWYER2]\n~g~Ramasse son portable!\n\n[LAW2_12:LAWYER2]\nPortable acquis! Tu peux maintenant recevoir des coups de fil.\n\n[LAW2_13:LAWYER2]\n~g~Tu as laissé Lance derrière! Va le chercher!\n\n[LAW2_14:LAWYER2]\nOn doit foutre le camp d'ici!\n\n[GUN_2A:LAWYER2]\nMaintiens la ~h~~k~~PED_LOCK_TARGET~ ~w~enfoncée pour ~h~viser automatiquement~w~. Appuie sur la~h~ ~k~~PED_FIREWEAPON~~w~ pour ~h~tirer!\n\n[GUN_2C:LAWYER2]\nMaintiens la ~h~~k~~PED_LOCK_TARGET~ ~w~enfoncée pour ~h~viser automatiquement~w~. Appuie sur la~h~ ~k~~PED_FIREWEAPON~~w~ pour ~h~tirer!\n\n[GUN_2D:LAWYER2]\nMaintiens la ~h~~k~~PED_LOCK_TARGET~ ~w~enfoncée pour ~h~viser automatiquement~w~. Appuie sur la~h~ ~k~~PED_FIREWEAPON~~w~ pour ~h~tirer!\n\n[HELP17:LAWYER2]\nAppuie sur la~h~ ~k~~PED_FIREWEAPON~ ~w~pour attaquer le chef.\n\n[HELP18:LAWYER2]\nAppuie sur la~h~ ~k~~PED_FIREWEAPON~~w~ pour attaquer le chef.\n\n[LAW3_11:LAWYER2]\nPlace-toi sur le ~q~marqueur rose~w~ pour consulter les armes en vente.\n\n[LAW3_12:LAWYER2]\nTu peux sélectionner des armes en appuyant sur ~h~gauche~w~ ou ~h~droite~w~ de la ~h~touche directionnelle.\n\n[LAW3_13:LAWYER2]\nSi tu as assez de blé, tu peux acheter des armes en appuyant sur la ~h~~k~~PED_SPRINT~.\n\n[LAW3_14:LAWYER2]\nTu peux sortir du magasin en appuyant sur la ~h~~k~~VEHICLE_ENTER_EXIT~.\n\n[LAW3_15:LAWYER2]\nSuis le ~h~point pistolet~w~ sur le radar pour trouver ~h~Ammu-Nation\n\n[LAW2_15:LAWYER2]\n~g~Va chez Ammu-Nation.\n\n[LAW2_K:LAWYER2]\ncalme-toi, maintenant.\n\n[LAW2_16:LAWYER2]\nIl faut que tu comprennes un truc sur cette ville. Tu dois toujours avoir un flingue sur toi.\n\n[LAW2_17:LAWYER2]\nAllez, l'armurerie du coin n'est qu'à quelques pas d'ici.\n\n[LAW2_18:LAWYER2]\nTommy, tout le monde a besoin de se la couler douce de temps en temps.\n\n[LAW2_19:LAWYER2]\nVoici le Pole Position Strip Club. Tu pourrais y passer de temps en temps.\n\n{=================================== MISSION TABLE LAWYER3 ===================================}\n\n[LAW3_A:LAWYER3]\nAaaaaah! Oh, nom de Dieu, c'est toi! Merde, je vais avoir besoin d'un nouveau pantalon!\n\n[LAW3_B:LAWYER3]\nPutain, ces psychopathes du nord ont téléphoné pour dire qu'ils rappliquaient bientôt...\n\n[LAW3_C:LAWYER3]\nAlors, où est ce sacré pognon?\n\n[LAW3_D:LAWYER3]\nRelax, relax, on n'en est pas encore là.\n\n[LAW3_E:LAWYER3]\nJe croyais vraiment que tu t'en occupais...\n\n[LAW3_F:LAWYER3]\nEt maintenant, ces mecs disent qu'il faut qu'on leur rende un service...\n\n[LAW3_G:LAWYER3]\nTu veux dire que JE dois leur rendre un service...\n\n[LAW3_H:LAWYER3]\nOuais, évidemment! Est-ce que j'ai l'air de pouvoir impressionner un jury?\n\n[LAW3_I:LAWYER3]\nJe ne pourrais même pas faire peur à un gosse et crois-moi, j'ai essayé!\n\n[LAW3_J:LAWYER3]\nMaintenant, écoute, c'est ça ou le cousin de Forelli, Georgio, se prend cinq ans pour escroquerie.\n\n[LAW3_K:LAWYER3]\nFaut que tu t'occupes de ces mecs!\n\n[LAW3_L:LAWYER3]\nJe comprends. Demander au jury de changer d'opinion. T'en fais pas.\n\n[LAW3_M:LAWYER3]\nNon non non non! Ca, j'ai déjà essayé! Et l'affaire ne s'est pas arrangée!\n\n[LAW3_N:LAWYER3]\nTu dois les OBLIGER à changer d'opinion!\n\n[LAW3_1:LAWYER3]\nAvec les compliments de Georgio...\n\n[LAW3_2:LAWYER3]\nN'oublie pas que le mot 'coupable' est proscrit!\n\n[LAW3_3:LAWYER3]\nIl est innocent, jusqu'à ce que je dise le contraire.\n\n[LAW3_4:LAWYER3]\nTu sais qu'il n'est pas coupable...\n\n[LAW3_5:LAWYER3]\nTu te souviens de Georgio? Et donc qu'il est innocent?\n\n[LAW3_6:LAWYER3]\nNon coupable. C'est compris... bien.\n\n[LAW3_8:LAWYER3]\n~r~Tu as tué un juré!\n\n[LAW3_9:LAWYER3]\n~g~Bousille la voiture du juré pour le faire sortir!\n\n[HELP40:LAWYER3]\nTu peux bousiller les voitures avec le marteau ou un outil similaire.\n\n[LAW3_10:LAWYER3]\n~g~Tu peux aller à la ~h~quincaillerie~g~ pour acheter une arme de corps à corps.\n\n[LAW3_20:LAWYER3]\n~g~Bousille la voiture du juré!\n\n[LAW3_21:LAWYER3]\nJe n'arrive pas à le croire!\n\n[LAW3_22:LAWYER3]\nIncroyable!\n\n[LAW3_23:LAWYER3]\nOk! C'est bon, j'ai compris!\n\n[LAW3_24:LAWYER3]\n~g~Ce marteau pourrait être utile.\n\n[LAW3_7:LAWYER3]\n~g~Va intimider les deux jurés, mais NE LES TUE PAS!\n\n[HELP23:LAWYER3]\nTu peux suivre le ~h~marteau~w~ sur le radar si tu veux acheter des armes de corps à corps dans la quincaillerie.\n\n[LAW3_16:LAWYER3]\nde Pete de Floride.\n\n[LAW3_17:LAWYER3]\nCasse-toi de là!\n\n{=================================== MISSION TABLE LAWYER4 ===================================}\n\n[LAW4_A:LAWYER4]\nAvery, cela va sans dire... Ah, Tommy! Des nouvelles? Non, non, tu m'en parleras plus tard. Plus tard.\n\n[LAW4_B:LAWYER4]\nTommy, voici Avery Carrington. Je crois que vous vous êtes rencontrés à la fête?\n\n[LAW4_C:LAWYER4]\nPas directement.\n\n[LAW4_D:LAWYER4]\nSalut.\n\n[LAW4_E:LAWYER4]\nAvery a une proposition à nous faire.\n\n[LAW4_F:LAWYER4]\nOn a pas déjà du pain sur la planche?\n\n[LAW4_G:LAWYER4]\nJ'essaye de maintenir les loups au loin, alors lâche-moi un peu la grappe!\n\n[LAW4_H:LAWYER4]\nJe suis tendu comme un cable et même si je dois crever avant la fin de la semaine, j'ai pas envie de mourir pauvre!\n\n[LAW4_I:LAWYER4]\nBon, vous énervez pas, tous les deux.\n\n[LAW4_J:LAWYER4]\nEcoute, petit, tu me files un coup de main et le moindre latino qui te fait chier, je m'occupe de lui.\n\n[LAW4_K:LAWYER4]\nOk, qu'est-ce que je peux faire pour toi?\n\n[LAW4_L:LAWYER4]\nCette société de livraison a son dépôt sur un terrain très intéressant. Et ils ne veulent pas vendre.\n\n[LAW4_M:LAWYER4]\nIls s'accrochent à leur terrain comme des rats entêtés, alors va falloir exploser cette vermine.\n\n[LAW4_N:LAWYER4]\nVa là-bas et mets le feu aux poudres.\n\n[LAW4_O:LAWYER4]\nLa sécurité sera débordée et tu pourras te glisser dedans et en finir avec eux...\n\n[LAW4_P:LAWYER4]\nTu peux aussi passer chez Rafael pour changer de fringues. T'en as sans doute pour un moment, mais bon, fonce!\n\n[LAW4_Q:LAWYER4]\nCa va être une vraie émeute.\n\n[LAW4_R:LAWYER4]\nSi tout se passe comme sur des roulettes, passe me voir au bureau...\n\n[LAW4_1:LAWYER4]\nDispersez-vous! La direction n'écoutera vos revendications que dans les conditions appropriées!\n\n[LAW4_2:LAWYER4]\nDispersez-vous! Retournez chez vous!\n\n[LAW4_3:LAWYER4]\nDispersez-vous! C'est inapproprié!\n\n[LAW4_4:LAWYER4]\nDispersez-vous ou vous finirez tous à la rue!\n\n[LAW4_5:LAWYER4]\nSortez vos bâtons, les mecs, on va briser quelques crânes de cocos!\n\n[LAW4_13:LAWYER4]\n~g~Commence à te battre avec au moins 4 ouvriers pour déclencher une émeute.\n\n[LAW4_14:LAWYER4]\n~g~Détruis les camionnettes du complexe!\n\n[HELP38:LAWYER4]\nSi tu butes quelqu'un qui porte une arme, il la lâche.\n\n[HELP39:LAWYER4]\nTu peux tirer sur les barils d'explosifs, mais garde tes distances.\n\n{=================================== MISSION TABLE MIAMI_1 ===================================}\n\n[T4X4_1A:MIAMI_1]\n~g~Tu as ~1~ secondes pour récupérer ~y~24~g~ points de passage. ~g~Fais-le dans ~y~N'IMPORTE QUEL ORDRE.\n\n[T4X4_1B:MIAMI_1]\n~y~Passe A TRAVERS~g~ le premier point de passage pour déclencher le ~r~CHRONOMETRE.\n\n[T4X4_1C:MIAMI_1]\n~1~ sur 24!\n\n[GETBIK1:MIAMI_1]\nTu as ~1~ secondes pour enfourcher une PCJ 600!\n\n[GETBIK3:MIAMI_1]\n~r~Tu as besoin d'une PCJ 600 pour cette mission!\n\n{=================================== MISSION TABLE MM ===================================}\n\n[BLOD_04:MM]\nETAT DE LA VOITURE :\n\n[BLOD_05:MM]\n~g~TEMPS VISE : ~1~ minute\n\n[BLOD_06:MM]\n~g~TEMPS VISE : ~1~ minutes\n\n[BLOD_07:MM]\nNV meilleur tps : ~1~ secondes\n\n[BLOD_08:MM]\nVoitures détruites : ~1~\n\n[BLOD_09:MM]\n$~1~\n\n[BLOD_10:MM]\nVAINQUEUR!\n\n[BLOD_01:MM]\nFranchis les points de passage pour augmenter ton temps général.\n\n[BLOD_02:MM]\nTu as perdu si ton temps général est à zéro.\n\n[BLOD_03:MM]\nIl faut que ton temps général soit supérieur au temps visé pour gagner!\n\n{=================================== MISSION TABLE OVALRIG ===================================}\n\n[HOTR_01:OVALRIG]\n~g~La course dure 12 tours. Seuls les trois premiers arrivés reçoivent une récompense.\n\n[HOTR_02:OVALRIG]\n~g~Tu es disqualifié si ta bagnole est détruite.\n\n[HOTR_03:OVALRIG]\n~g~Si ta bagnole est bousillée, tu peux la faire réparer aux stands.\n\n[HOTR_04:OVALRIG]\n~g~C'est par là pour sortir du stade.\n\n[HOTR_05:OVALRIG]\nEtat de la voiture :\n\n[HOTR_06:OVALRIG]\nTours :\n\n[HOTR_10:OVALRIG]\nTemps de course :\n\n[HOTR_09:OVALRIG]\nPosition :\n\n[HOTR_12:OVALRIG]\n~r~Ta caisse est bousillée!\n\n[HOTR_13:OVALRIG]\n~r~Tu n'as pas gagné la course!\n\n[HOTR_14:OVALRIG]\n~r~Tu as été disqualifié!\n\n[HOTR_15:OVALRIG]\nTemps : ~1~:~1~\n\n[HOTR_16:OVALRIG]\nTemps : ~1~:0~1~\n\n[HOTR_17:OVALRIG]\nMeilleur temps : ~1~:~1~\n\n[HOTR_18:OVALRIG]\nMeilleur temps : ~1~:0~1~\n\n[HOTR_19:OVALRIG]\nMeilleur temps : aucun\n\n[HOTR_20:OVALRIG]\nNv meilleur tps : ~1~:~1~\n\n[HOTR_21:OVALRIG]\nNv meilleur tps : ~1~:0~1~\n\n[HOTR_22:OVALRIG]\nMeilleur résultat : aucun\n\n[HOTR_23:OVALRIG]\nMeilleur résultat : 1er\n\n[HOTR_24:OVALRIG]\nMeilleur résultat : 2e\n\n[HOTR_25:OVALRIG]\nMeilleur résultat : 3e\n\n[HOTR_26:OVALRIG]\nMeilleur résultat : ~1~e\n\n[HOTR_27:OVALRIG]\nMeilleur tps au tr : ~1~.~1~ secondes\n\n[HOTR_28:OVALRIG]\nMeilleur tps au tr : ~1~.0~1~ secondes\n\n[HOTR_29:OVALRIG]\n$~1~\n\n[HOTR_30:OVALRIG]\n1ERE PLACE\n\n[HOTR_31:OVALRIG]\n2E PLACE\n\n[HOTR_32:OVALRIG]\n3E PLACE\n\n[HOTR_33:OVALRIG]\nMeilleur tps au tr : aucun\n\n[HOTR_11:OVALRIG]\nNv meilleur tps au tr : ~1~.~1~ secondes\n\n[HOTR_34:OVALRIG]\nNv meilleur tps au tr : ~1~.0~1~ secondes\n\n{=================================== MISSION TABLE PHIL1 ===================================}\n\n[PHI1_HP:PHIL1]\nTu peux lancer une grenade à détonateur quelque part puis l'y faire exploser au moment souhaité.\n\n[PHIL1_A:PHIL1]\nPhil?\n\n[PHIL1_B:PHIL1]\nCOURS!\n\n[PHIL1_C:PHIL1]\nCours.\n\n[PHIL1_E:PHIL1]\nMerde, Phil, tu bois cette saloperie?\n\n[PHIL1_F:PHIL1]\nPutain, t'as pas besoin de la boire!\n\n[PHIL1_G:PHIL1]\nTu la renifles juste un bon coup et t'exploses direct!\n\n[PHIL1_H:PHIL1]\nEcoute, Phil, t'avais dit que tu pourrais t'occuper de ma puissance de feu...\n\n[PHIL1_I:PHIL1]\nPas de problème.\n\n[PHIL1_J:PHIL1]\nIl y a ce mexicain qui trafique des armes, il a pas été réglo avec moi.\n\n[PHIL1_K:PHIL1]\nIl fait sa tournée hebdomadaire, maintenant.\n\n[PHIL1_L:PHIL1]\nDéfonce l'arrière de son camion et sers-toi avant qu'il réagisse.\n\n[PHIL1_M:PHIL1]\nEt rends-moi un service au passage tant que tu y es.\n\n[PHIL1_N:PHIL1]\nEnsuite, règle-lui son compte...\n\n[PHI1_01:PHIL1]\n~g~Va piquer les armes à l'arrière du camion du trafiquant.\n\n[PHI1_02:PHIL1]\n~g~Le trafiquant a largué son chargement. Brise la caisse et ramasse l'artillerie.\n\n[PHI1_03:PHIL1]\n~g~On dirait qu'ils ont demandé des renforts...\n\n[PHI1_04:PHIL1]\n~g~Va maintenant finir les trafiquants d'armes survivants.\n\n[PHIL1_O:PHIL1]\nYeeeeeeehhaaaaa!\n\n[PHIL1_D:PHIL1]\nN'approche jamais une allumette enflammée du boomshine de Phil Cassidy!\n\n{=================================== MISSION TABLE PHIL2 ===================================}\n\n[PHIL2_A:PHIL2]\nSalut, Phil, ça roule?\n\n[PHIL2_B:PHIL2]\nSaluut Tommyyyy! Comment ça va? Ca fait tellement longtemps...\n\n[PHIL2_C:PHIL2]\nJe te jure que tu devrais arrêter le boomshine...\n\n[PHIL2_D:PHIL2]\nCa sent comme du décapant à peinture, j'ai les yeux qui brûlent...\n\n[PHIL2_E:PHIL2]\nFerme-la, Tommy\n\n[PHIL2_F:PHIL2]\net amène-toi par là. Y'a quelque chose que je veux te montrer... Quelque chose...\n\n[PHIL2_G:PHIL2]\nWaou! Putain! C'est normal que je sente l'odeur d'ici? Je me sens tout drôle...\n\n[PHIL2_H:PHIL2]\nT'inquiète pas de l'odeur, Tommy, regarde juste ça.\n\n[PHIL2_I:PHIL2]\nPutain de saloperies de piles bon marché! Il y en a d'autres sur le banc.\n\n[PHIL2_J:PHIL2]\nTA-DAAA!\n\n[PHIL2_K:PHIL2]\nOh merde!\n\n[PHI2_01:PHIL2]\n~g~Vite, emmène Phil à l'hosto!\n\n[PHI2_03:PHIL2]\n~r~Phil Cassidy est mort! Maintenant, qui va nous filer des flingues à Liberty?\n\n[PHI2_05:PHIL2]\nPas à l'hosto, mec, c'est plein de flics et de vietcongs!\n\n[PHI2_06:PHIL2]\nIl y a un ancien chirurgien de l'armée qui me doit quelques services et une tondeuse...\n\n[PHI2_07:PHIL2]\nIl crêche à Little Havana, oh! Regarde! Un poisson géant!\n\n[PHI2_08:PHIL2]\nFais gaffe! Charlie sur la ligne des arbres!\n\n[PHI2_09:PHIL2]\nC'est moi qui hallucine ou la route est vraiment toute molle?\n\n[PHI2_10:PHIL2]\nCuillère Brisée à Mère Poule, tu me reçois?\n\n[PHI2_11:PHIL2]\nSpooney Wooney Woo Woo Woooo!\n\n[PHI2_12:PHIL2]\nLa mort m'appelle, mon garçon!\n\n[PHI2_13:PHIL2]\nDes ailes noires qui battent tout autour...\n\n[PHI2_14:PHIL2]\nC'est magnifique, mec, magnifique... Mais tellement froid...\n\n[PHI2_15:PHIL2]\n10-4 On a un conducteur en état d'ivresse.\n\n[PHI2_04:PHIL2]\nSANTE DE PHIL :\n\n[PHI_AS1:PHIL2]\nCHEZ PHILS PLACE OK\n\n[PHI_AS2:PHIL2]\n~g~De nouvelles armes sont en vente chez Phils Place.\n\n{=================================== MISSION TABLE PIZZA ===================================}\n\n[PIZ1_01:PIZZA]\n~g~Va livrer ces pizzas. Tu dois les balancer aux clients. Roule à côté d'eux pour lancer les pizzas.\n\n[PIZ1_02:PIZZA]\n~g~T'as balancé toutes tes pizzas, retourne en chercher d'autres.\n\n[PIZ1_05:PIZZA]\n~g~Tu as 5 minutes pour livrer les commandes avant que que les clients n'appelent une autre pizzeria.\n\n[PIZ1_07:PIZZA]\n~r~T'as tué le client! T'es viré!\n\n[PIZ1_08:PIZZA]\n~r~T'es à la bourre! T'es viré!\n\n[PIZ1_09:PIZZA]\n~r~T'as bousillé notre bécane! T'es viré!\n\n[PIZ1_11:PIZZA]\nHé! Retourne sur ta bécane!\n\n[PIZ1_12:PIZZA]\nPizzas restantes :\n\n[PIZ1_06:PIZZA]\nAppuie sur la~h~ ~k~~TOGGLE_SUBMISSIONS~~w~ quand tu es sur la moto pour annuler la mission.\n\n[PIZ1_13:PIZZA]\nEffectue ces livraisons en vitesse.\n\n[PIZ1_14:PIZZA]\nMon pote, un pizza pour toi!\n\n[PIZ1_15:PIZZA]\nAllez, mon vieux, livre ça en vitesse.\n\n[PIZ1_16:PIZZA]\nQu'est-ce que t'attends, mon vieux? T'as des pizzas à livrer!\n\n[PIZ1_17:PIZZA]\nJe sais que tu voulais pas faire ce boulot, mais je m'en tape!\n\n[PIZ1_18:PIZZA]\nVa livrer ça.\n\n[PIZ1_19:PIZZA]\nOn a besoin de livrer ça.\n\n[PIZ1_20:PIZZA]\nAllez, mon vieux, livre ça ou t'es viré!\n\n[PIZ1_21:PIZZA]\nIl y a des gens qui attendent, mon vieux.\n\n[PIZ1_22:PIZZA]\nMais qu'est-ce que t'attends? Faut livrer ça!\n\n[PIZ1_23:PIZZA]\nVa livrer cette saloperie de bouffe!\n\n[PIZ1_24:PIZZA]\nLes clients ont les crocs, mon vieux!\n\n[PIZ1_25:PIZZA]\nTu peux prendre ça, mon vieux?\n\n[PIZ1_26:PIZZA]\nTiens, va livrer ça en vitesse, amigo.\n\n[PIZ1_27:PIZZA]\nMagne-toi, on est débordés. Va livrer ça!\n\n[PIZ1_28:PIZZA]\nEncore toi? Qu'est-ce que t'attends? Va livrer ça!\n\n[PIZ1_29:PIZZA]\nPerds pas de temps, cette fois-ci.\n\n[PIZ1_30:PIZZA]\nEspèce de bon à rien! Va livrer ça en vitesse!\n\n[PIZ1_31:PIZZA]\nT'auras jamais de promotion si tu traînes encore ce coup-ci.\n\n[PIZ1_32:PIZZA]\n~r~La pizza est trop chaude ou quoi?\n\n[PIZ1_33:PIZZA]\n~g~Retourne au restaurant pour d'autres commandes.\n\n[PIZ1_34:PIZZA]\n~g~Pizza livrée. Voilà ton fric.\n\n[PIZ_WON:PIZZA]\nMission Pizza terminée. votre max de Santé passe à 150.\n\n{=================================== MISSION TABLE PORN1 ===================================}\n\n[POR1_A:PORN1]\nAction\n\n[POR1_B:PORN1]\nOoooh! C'est un sacré morceau!\n\n[POR1_C:PORN1]\n30 centimètres, c'est la taille réglementaire, bébé.\n\n[POR1_D:PORN1]\nCOUPEZ! Qui c'est cet abruti? Toi! Toi! T'es dans le champ? POURQUOI?\n\n[POR1_E:PORN1]\nQu'est-ce que c'est que ces conneries?\n\n[POR1_F:PORN1]\nDes aliens? Des cannes à pêche?\n\n[POR1_G:PORN1]\nJ'ai jamais vu un requin aussi gros...\n\n[POR1_H:PORN1]\nFaut que tout ça dégage!\n\n[POR1_I:PORN1]\nPourquoi t'es dans le métier, connard?\n\n[POR1_J:PORN1]\nHein?\n\n[POR1_K:PORN1]\nBen, pour les chattes, évidemment! Alors, qu'est-ce que c'est que ça?\n\n[POR1_L:PORN1]\nCeci est mon art - SECURITE!\n\n[POR1_M:PORN1]\nEcoute-moi, trou du cul arrogant, tu m'appartiens maintenant. Tout m'appartient ici.\n\n[POR1_N:PORN1]\nOn va révolutionner cet endroit...\n\n[POR1_O:PORN1]\nJe vais faire ta fortune...\n\n[POR1_P:PORN1]\nOh. Tu es... Tu... es Tommy Vercetti? Mais je croyais que tu étais...\n\n[POR1_Q:PORN1]\nExactement...\n\n[POR1_R:PORN1]\nVa y avoir quelques changements dans le coin et on va commencer à se faire des ronds.\n\n[POR1_S:PORN1]\nAu fait, as-tu jamais pensé à...\n\n[POR1_T:PORN1]\nMais d'abord, on va avoir besoin de quelques putes bien foutues...\n\n[POR1_U:PORN1]\nOuais, les filles c'est bien mais toi... waou!\n\n[POR1_02:PORN1]\n~g~Bute le mac de Candy, puis retourne la récupérer.\n\n[POR1_04:PORN1]\nSalut, Candy. Je cherche des actrices, ça te branche?\n\n[POR1_05:PORN1]\nEt comment! Mais faut causer à mon agent...\n\n[POR1_06:PORN1]\nPutain qu'est-ce que tu fous?\n\n[POR1_07:PORN1]\nTu aurais mieux fait de rester à la maison, aujourd'hui!\n\n[POR1_7B:PORN1]\nJ'arrive pas à croire ce trou du cul!\n\n[POR1_08:PORN1]\nSalut, Mercedes!\n\n[POR1_09:PORN1]\nSalut, Tommy! Tu viens faire la fête?\n\n[POR1_10:PORN1]\nNon, pas maintenant, chérie. Ca te dirait de faire du cinéma?\n\n[POR1_11:PORN1]\nEvidemment! Mais seulement si c'est sordide et bon marché!\n\n[POR1_13:PORN1]\n~g~Emmène les filles au studio y retrouver Steve.\n\n[POR1_14:PORN1]\nT'es engagé!\n\n[POR1_15:PORN1]\nHé tommy, tu viens pour un bout d'essai?\n\n[POR1_17:PORN1]\nWaou! Sympa le requin!\n\n[POR1_18:PORN1]\n~r~Mercedes est morte!\n\n[POR1_20:PORN1]\nTommy! Où tu vas? Reviens ici!\n\n[POR1_21:PORN1]\nOù tu vas?\n\n[POR1_22:PORN1]\nTommy, quand c'est qu'on va pouvoir être un peu seuls ensemble?\n\n[POR1_01:PORN1]\n~g~Candy Suxxx serait parfaite pour un premier rôle!\n\n[POR1_12:PORN1]\n~g~Emmène Candy avec toi pour rencontrer Mercedes.\n\n[POR1_16:PORN1]\nPlus tard, peut-être, mon chou...\n\n[POR1_24:PORN1]\n~g~Retourne chercher Candy.\n\n[POR1_25:PORN1]\n~g~Tu as laissé Candy. Retourne la chercher!\n\n[POR1_23:PORN1]\n~g~Candy va s'occuper de l'affaire dans le ~h~Centre~g~.\n\n[POR1_26:PORN1]\n~g~Voilà Candy. On dirait qu'elle a encore eu rendez-vous avec le représentant du Congrès, Alex Shrub.\n\n[POR1_27:PORN1]\nAllez, partons d'ici!\n\n[POR1_28:PORN1]\nTommy, sois prudent! Mes implants ne sont pas encore assurés!\n\n[POR1_29:PORN1]\nTu appelles ça conduire?\n\n[POR1_30:PORN1]\nJe pourrais plus faire du porno après ça!\n\n[POR1_31:PORN1]\nQuoi? T'essaies de me tuer ou quoi? Je croyais que c'était moi, la star!\n\n{=================================== MISSION TABLE PORN2 ===================================}\n\n[POR2_A:PORN2]\nComment ça se passe, Steve?\n\n[POR2_B:PORN2]\nEh ben, Candy est faite pour le rôle et la nouvelle fille est infatigable!\n\n[POR2_C:PORN2]\nElle s'est tapé la moitié du casting et des techniciens avant même que j'ai fini de régler les éclairages!\n\n[POR2_D:PORN2]\nEnfin, demain, on va en extérieurs pour tourner les scènes du bateau...\n\n[POR2_E:PORN2]\nLes scènes du bateau? Quelles scènes du bateau?\n\n[POR2_F:PORN2]\nLes pêcheurs sont dans les filets de la passion quand ce requin géant arrive...\n\n[POR2_G:PORN2]\nQu'est-ce que j'avais dit à propos du requin géant?\n\n[POR2_H:PORN2]\nJ'avais dit : PAS DE REQUIN GEANT! Ok?\n\n[POR2_I:PORN2]\nLaisse simplement les caméras braquées sur le pieu!\n\n[POR2_J:PORN2]\nOk ok, Tommy, j'avais bien le droit d'essayer...\n\n[POR2_K:PORN2]\nLes prospectus sont imprimés?\n\n[POR2_L:PORN2]\nOuais, mais personne va nous laisser distribuer ces trucs, je veux dire...\n\n[POR2_M:PORN2]\nIls sont un peu trop, hum, enfin, ils manquent un peu de poésie...\n\n[POR2_N:PORN2]\nT'en fais pas pour ça!\n\n[POR2_O:PORN2]\nJ'ai mes propres plans pour la distribution...\n\n[POR2_P:PORN2]\nOK. Hé, Candy, amène-toi dans ma caravane!\n\n[POR2_01:PORN2]\n~g~Il y a un hydravion à l'arrière des studios qui servait pour la propagande des vieux films.\n\n[POR2_02:PORN2]\n~g~Atteins l'un des points de contrôle pour commencer à larguer les prospectus.\n\n[POR2_03:PORN2]\n~g~Largue les prospectus tout le long du chemin jusqu'au dernier point de contrôle.\n\n[POR2_04:PORN2]\n~r~NIVEAU DE CARBURANT BAS!\n\n[POR2_05:PORN2]\nUtilise-le pour distribuer les prospectus dans la ville.\n\n[DILDO:PORN2]\nKérosène :\n\n[POR2_Q:PORN2]\nOh, merde!\n\n[PORN2_9:PORN2]\n~g~Il te reste ~1~ secondes pour retourner à une Skimmer avant la fin de la mission.\n\n{=================================== MISSION TABLE PORN3 ===================================}\n\n[POR3_A:PORN3]\nBon, c'est quoi le problème, maintenant?\n\n[POR3_B:PORN3]\nChuuuut!\n\n[POR3_C:PORN3]\nEh bien, après l'intime rencontre avec les envahisseuses nymphomanes,\n\n[POR3_D:PORN3]\nnotre jeune héros se retrouve incapable de penser à autre chose que cette énorme montagne phallique\n\n[POR3_E:PORN3]\net c'est là qu'on veut placer la scène avec la cuve de purée de patates, mais alors on...\n\n[POR3_F:PORN3]\nCes conneries m'intéressent pas!\n\n[POR3_G:PORN3]\nContinuez simplement le boulot, continuez...\n\n[POR3_H:PORN3]\nHé, Tommy...\n\n[POR3_I:PORN3]\nT'as évoqué un problème légal au téléphone...\n\n[POR3_J:PORN3]\nAh ouais! Le représentant du Congrès Alex Shrub a pris le train électoral en marche à la pêche des votes puritains...\n\n[POR3_K:PORN3]\nLa rumeur laisse entendre qu'il soutient des mesures de restriction contre...\n\n[POR3_L:PORN3]\nDisons... les formes les plus charnelles de la grande industrie cinématographique de ce pays.\n\n[POR3_M:PORN3]\nSuper.\n\n[POR3_N:PORN3]\nCandy! Tu connais Shrub.\n\n[POR3_O:PORN3]\nVous faites des trucs bizarres tous les deux?\n\n[POR3_P:PORN3]\nOh oui! Oui! Oh oui! Oui oui oui ouuuuuuuuuuuuuuuuuui!\n\n[POR3_Q:PORN3]\nDis-moi que t'as eu ça...\n\n[POR3_R:PORN3]\nEst-ce que ça faisait partie du... euh... Ou bien elle parlait à...\n\n[POR3_S:PORN3]\nImpossible à dire... Dans tous les cas...\n\n[POR3_T:PORN3]\nTu ferais mieux de la suivre après le tournage\n\n[POR3_U:PORN3]\net voir si elle te mènera pas à leur nouveau nid d'amour.\n\n[POR3_V:PORN3]\nT'as un appareil photo?\n\n[POR3_X:PORN3]\nHé, file-lui un appareil photo!\n\n[POR3_02:PORN3]\n~r~Tu as tué le représentant du Congrès! T'auras du mal à le faire chanter, maintenant!\n\n[POR3_03:PORN3]\n~r~Tu as alerté la sécurité du représentant du Congrès, ils vont le faire sortir tout de suite.\n\n[POR3_04:PORN3]\nCandy, tu peux m'appeler Martha?\n\n[POR3_05:PORN3]\nOh Alex, enfin, je veux dire Martha. Comme tu veux...\n\n[POR3_06:PORN3]\nMartha, il y a quelqu'un qui regarde... C'est pervers...\n\n[POR3_07:PORN3]\nVous là-bas, donnez-moi cet appareil photo!\n\n[POR3_01:PORN3]\n~g~Suis la ~h~Stretch~g~ de Candy.\n\n[POR3_15:PORN3]\n~r~T'as bousillé la Stretch de Candy!\n\n[POR3_17:PORN3]\n~g~Retourne aux Porn Studios avec la pellicule.\n\n[POR3_19:PORN3]\n~r~T'es à court de pellicule!\n\n[POR3_21:PORN3]\n~g~T'as perdu la Stretch de Candy!\n\n[POR3_22:PORN3]\n~g~Le WK Chariot Hotel de l'autre côté de ce balcon devrait être idéal, comme point de vue.\n\n[POR3_23:PORN3]\n~g~Il y a une porte latérale qui te permettra d'accéder à l'hôtel.\n\n[POR3_08:PORN3]\nAppuie sur la~h~ ~k~~PED_LOCK_TARGET~ ~w~et maintiens-la enfoncée pour ~h~cadrer~w~ la photo.\n\n[POR3_09:PORN3]\nAppuie sur la~h~ ~k~~PED_LOCK_TARGET~ ~w~et maintiens-la enfoncée pour ~h~cadrer~w~ la photo.\n\n[POR3_10:PORN3]\nAppuie sur la~h~ ~k~~PED_SNIPER_ZOOM_IN~ ~w~pour faire un ~h~zoom avant~w~ et sur la~h~ ~k~~PED_SNIPER_ZOOM_OUT~ ~w~pour faire un ~h~zoom arrière~w~.\n\n[POR3_11:PORN3]\nAppuie sur la~h~ ~k~~PED_SNIPER_ZOOM_IN~ ~w~pour faire un ~h~zoom avant~w~ et sur la~h~ ~k~~PED_SNIPER_ZOOM_OUT~ ~w~pour faire un ~h~zoom arrière~w~.\n\n[POR3_12:PORN3]\nAppuie sur la~h~ ~k~~PED_FIREWEAPON~ ~w~pour prendre une photo.\n\n[POR3_13:PORN3]\nAppuie sur la~h~ ~k~~PED_FIREWEAPON~ ~w~pour prendre une photo.\n\n[POR3_14:PORN3]\nAppuie sur la~h~ ~k~~PED_FIREWEAPON~ ~w~pour prendre une photo.\n\n[POR3_20:PORN3]\n~g~Si tu as besoin de te déplacer, utilise la ~h~Sparrow~g~ garée derrière.\n\n[POR3_16:PORN3]\n~g~Il te faut trois bons clichés d'Alex Shrub avec Candy pour le faire chanter.\n\n[POR3_24:PORN3]\nPHOTOS PRISES :\n\n{=================================== MISSION TABLE PORN4 ===================================}\n\n[POR4_A:PORN4]\nJe suis désolée, mais je ne peux pas avaler maintenant!\n\n[POR4_B:PORN4]\nOh, ALLEZ! Chérie!\n\n[POR4_C:PORN4]\nIl décharge comme une baleine, par pitié\n\n[POR4_D:PORN4]\ncomment tu fais pour ne pas saisir le rôle?\n\n[POR4_E:PORN4]\nMais Stevie...\n\n[POR4_F:PORN4]\nComment va mon réalisateur vedette?\n\n[POR4_G:PORN4]\nAh, mon pote, la lutte incessante entre l'intégrité artistique et\n\n[POR4_H:PORN4]\nl'éjaculation sous toutes ses formes est loin d'être terminée.\n\n[POR4_I:PORN4]\nEt avant que tu me poses la question, je t'informe que les quatre vidéos sortiront dans les...\n\n[POR4_J:PORN4]\nChérie, veux-tu garder l'anaconda dans le champ, S'IL TE PLAIT.\n\n[POR4_K:PORN4]\nIl prend plus de l'heure que toi!\n\n[POR4_L:PORN4]\nOh, pardon, Steve...\n\n[POR4_M:PORN4]\nJe me disais, faudrait monter un gros coup de pub pour la promo du film.\n\n[POR4_N:PORN4]\nUn truc qui aurait vraiment de l'impact sur la ville... T'as pas une idée?\n\n[POR4_O:PORN4]\nEh ben, autrefois, on faisait des galas,\n\n[POR4_P:PORN4]\navec des vedettes, des limousines, la nuit éclairée par les projos...\n\n[POR4_Q:PORN4]\nDes projecteurs? J'ai une idée!\n\n[POR4_R:PORN4]\n...Ouais, ouais, ouais! Le petit numéro de paillettes, les limousines, ah, les premières!\n\n[POR4_S:PORN4]\nOh oui, chère madaaaame, bien sûr, chère madaaaame...\n\n[POR4_T:PORN4]\net la presse, et le barrage de lumières...\n\n[POR4_01:PORN4]\n~g~Va dans le ~y~Centre~g~ et ajuste le projecteur sur le toit du bâtiment.\n\n[POR4_02:PORN4]\n~g~Une bécane rapide est nécessaire pour sauter de toit en toit. L'agent de sécurité a l'habitude de venir en ~y~PCJ 600~g~ au boulot...\n\n[POR4_03:PORN4]\n~g~Faut que tu montes sur les toits. Il devrait y avoir un ascenceur dans l'un des immeubles de bureaux.\n\n[POR4_06:PORN4]\n~g~Retourne à l'immeuble de bureaux du bas si tu as besoin d'accéder à nouveau au toit.\n\n[POR4_07:PORN4]\n~g~Tu as besoin d'une bécane pour sauter de bâtiment en bâtiment!\n\n[POR4_08:PORN4]\n~g~Fonce à travers la fenêtre pour commencer. Tu as jusqu'à 07:00 avant que la lumière du jour ne risque de te faire découvrir.\n\n[POR4_09:PORN4]\n~g~Les marqueurs t'indiquent sur quel bâtiment sauter ensuite.\n\n[POR4_10:PORN4]\n~r~Il fait maintenant trop clair pour monter sans te faire voir.\n\n[POR4_11:PORN4]\nRetourne à l'escalier si tu as à nouveau besoin d'accéder au toit.\n\n[POR4_05:PORN4]\n~g~Ces escaliers mènent à un bureau.\n\n[POR_AS1:PORN4]\nSTUDIO DE CINEMA OK\n\n[POR_AS2:PORN4]\n~g~Inter Global Films génère dorénavant un revenu de $~1~ maximum. Pense à récupérer le fric régulièrement.\n\n{=================================== MISSION TABLE PROT1 ===================================}\n\n[PRO1_B:PROT1]\nJe supporte pas ce style. Tommy, qu'est-ce que t'en penses? Qu'est-ce que tu dirais qu'on mette un bar dans...\n\n[PRO1_D:PROT1]\nEcoutez-moi...\n\n[PRO1_E:PROT1]\nL'heure est venue de mettre la main sur cette ville! Le monde n'attend plus que nous!\n\n[PRO1_F:PROT1]\nFaut qu'on commence à s'emparer de territoires!\n\n[PRO1_G:PROT1]\nFaut qu'on fasse comprendre à tout Vice City qu'on est les nouveaux maîtres du jeu! Tu vois ce que je veux dire?\n\n[PRO1_I:PROT1]\nCe qu'il te faut, c'est une façade légale, Tommy! Une affaire officielle! Ca m'a jamais rapporté d'emmerdes!\n\n[PRO1_J:PROT1]\nFaut qu'on commence à utiliser des balaises ou autant faire une croix sur tout le boulot qu'on s'est tapé jusque là.\n\n[PRO1_K:PROT1]\nLes commerces locaux savent que Diaz est mort et ils refusent de payer pour leur protection!\n\n[PRO1_L:PROT1]\nAh. On pourrait essayer la corruption...\n\n[PRO1_M:PROT1]\nLa corruption! Mon cul, la corruption! Je vais vous montrer comment on leur fait peur!\n\n[PRO1_01:PROT1]\n~g~Défoule-toi sur les devantures des magasins et les proprios supplieront pour être protégés.\n\n[PRO1_03:PROT1]\n~r~C'était supposé être un raid éclair, pas une pause café.\n\n[PRO1_04:PROT1]\nMon gagne-pain est détruit!\n\n[PRO1_05:PROT1]\nTout est en ruines!\n\n[PRO1_06:PROT1]\nJe paye le prix fort pour ma protection!\n\n[PRO1_07:PROT1]\nMa belle vitrine!\n\n[PRO1_08:PROT1]\nMon magasin! Mon beau magasin!\n\n[PRO1_09:PROT1]\nVercetti. Souvenez-vous de mon nom...\n\n[PRO1_10:PROT1]\nJe règne désormais sur cette ville. MOI!\n\n[BUYP1:PROT1]\nTu peux désormais acheter des propriétés dans certaines zones de la carte.\n\n[BUYP2:PROT1]\nSi tu vois un marqueur vert sur une propriété, c'est que tu peux l'acheter.\n\n[PRO1_N:PROT1]\nJe reviens dans cinq minutes...\n\n[PRO1_11:PROT1]\n~g~Va au ~y~Centre commercial de North Point~g~ dans ~y~Vice Point~g~.\n\n[PRO1_12:PROT1]\n~g~Brise les vitrines de chaque magasin et les proprios supplieront pour une nouvelle protection.\n\n[PRO1_A:PROT1]\nAh, faut qu'on redécore cet endroit, faut qu'on lui donne un air plus vieux.\n\n[PRO1_C:PROT1]\nT'es mon avocat, Rosenberg. Pas mon décorateur. Compris?\n\n[BUYP3:PROT1]\nTiens-toi sur le marqueur, puis appuie sur la touche ~h~~k~~PED_ANSWER_PHONE~~w~ pour acheter cette propriété.\n\n[PRO1_13:PROT1]\n~g~Tu as cinq minutes pour tous les avoir.\n\n{=================================== MISSION TABLE PROT2 ===================================}\n\n[PRO2_A:PROT2]\nC'est quoi l'problème?\n\n[PRO2_B:PROT2]\nUn bar refuse de payer.\n\n[PRO2_C:PROT2]\nLe boss considère qu'il est sous la protection d'un gang de voyous du coin...\n\n[PRO2_D:PROT2]\nMais t'en fais pas, Tommy, je peux m'en occuper.\n\n[PRO2_E:PROT2]\nC'est ça que t'appelles t'en occuper?\n\n[PRO2_F:PROT2]\nVous deux, levez vos culs de là...\n\n[PRO2_G:PROT2]\nAllons-y.\n\n[PRO2_01:PROT2]\n~g~Liquide les gardes qui protègent le Front Page Bar et trouve qui les a approvisionnés.\n\n[PRO2_10:PROT2]\n~g~Il y en a deux de plus qui se sont fait la malle. Finis-en avec eux.\n\n[PRO2_11:PROT2]\nMontez dans la caisse, bons à rien.\n\n[PRO2_02:PROT2]\nTa protection a besoin d'être légèrement renforcée.\n\n[PRO2_03:PROT2]\nAh, non, pas encore! J'en ai marre!\n\n[PRO2_04:PROT2]\nCes imbéciles opèrent dans le quartier à partir de DBP Security.\n\n[PRO2_05:PROT2]\nRéglez la question entre vous, les mecs.\n\n[PRO2_06:PROT2]\nBon, à plus tard.\n\n[PRO2_07:PROT2]\nOuais, ouais, c'est ça.\n\n[PRO2_08:PROT2]\n~g~Les abrutis du DBP Security sauront que t'y vas, alors fonce et chope-les avant qu'ils décampent!\n\n[PRO2_09:PROT2]\n~g~Va parler au proprio du Front Page Bar.\n\n{=================================== MISSION TABLE PROT3 ===================================}\n\n[PRO3_A:PROT3]\nPauvre crétin! A quoi tu pensais?\n\n[PRO3_B:PROT3]\nTu réalise ce qui aurait pu arriver?\n\n[PRO3_C:PROT3]\nOn a failli tous se faire avoir!\n\n[PRO3_D:PROT3]\nLe retardateur a dû déconner...\n\n[PRO3_E:PROT3]\nCet endroit était prêt à sauter comme une usine de feux d'artifice.\n\n[PRO3_F:PROT3]\nEt pis quelqu'un a rencardé les flics...\n\n[PRO3_G:PROT3]\nC'est quoi le problème, les mecs?\n\n[PRO3_H:PROT3]\nMike devait foutre le feu quelque part dans le centre commercial,\n\n[PRO3_I:PROT3]\nmais il a foiré son coup et maintenant, les flics grouillent, là-bas.\n\n[PRO3_J:PROT3]\nFaut qu'on récupère notre bordel et qu'on s'tire de là!\n\n[PRO3_K:PROT3]\nDu calme, vous deux, laissez-moi réfléchir une seconde!\n\n[PRO3_L:PROT3]\nTommy Vercetti a pas l'habitude de mettre les bouts comme ça...\n\n[PRO3_M:PROT3]\nLes flics vont passer ce bâtiment au peigne fin, pas vrai?\n\n[PRO3_N:PROT3]\nMais ça prend du temps...\n\n[PRO3_O:PROT3]\nOn va entrer et foutre le feu nous-mêmes!\n\n[PRO3_P:PROT3]\nOuais, mais...\n\n[PRO3_Q:PROT3]\nIl y a que les flics qui peuvent approcher à moins d'un kilomètre de là-bas!\n\n[PRO3_R:PROT3]\nAlors, on ira en tant que flics!\n\n[PRO3_S:PROT3]\nOn va se dégotter des uniformes et il nous faut aussi une bagnole de patrouille.\n\n[PRO3_T:PROT3]\nTout ça à cause de toi, Mike.\n\n[PRO3_U:PROT3]\nJe suis désolé.\n\n[PRO3_V:PROT3]\nJ'ai trouvé!\n\n[PRO3_W:PROT3]\nTout ce qu'on a à faire, c'est appâter les flics avec un doigt levé,\n\n[PRO3_X:PROT3]\nde les prendre au piège\n\n[PRO3_Y:PROT3]\net de leur sauter dessus!\n\n[PRO3_Z:PROT3]\nSuper plan! En route!\n\n[PRO3_A1:PROT3]\nOK.\n\n[PRO3_01:PROT3]\nOk Lance, attirons l'attention des flics!\n\n[PRO3_02:PROT3]\n~g~Prends la bagnole des flics et va poser la bombe au Tarbrush Coffee Shop dans le centre commercial.\n\n[PRO3_03:PROT3]\n~g~T'as laissé Lance derrière, va le récupérer!\n\n[PRO3_04:PROT3]\n~g~Allons-y!\n\n[PRO3_05:PROT3]\n~r~T'as buté Lance!\n\n[PRO3_07:PROT3]\n~g~Tu as grillé ta couverture! Magne-toi de poser la bombe!\n\n[PRO3_09:PROT3]\nLigotons et bâillonnons-les!\n\n[PRO3_10:PROT3]\nAaah! Il me va parfaitement!\n\n[PRO3_11:PROT3]\nMais quand même un peu serré au niveau des couilles...\n\n[PRO3_12:PROT3]\nAh ouais? Le mien aussi, c'est pareil!\n\n[PRO3_13:PROT3]\nDu calme, mon pote! Les flics conduisent pas aussi mal!\n\n[PRO3_14:PROT3]\nOublie pas... Faut sourire aux autres flics...\n\n[PRO3_15:PROT3]\nSalut officier. Bel insigne, bel insigne...\n\n[PRO3_16:PROT3]\nTout doux, Lance.\n\n[PRO3_17:PROT3]\nOk, les retardateurs sont programmés, 5 secondes et ça saute!\n\n[PRO3_18:PROT3]\n5 secondes? Putain faut dégager d'ici en vitesse!\n\n[PRO3_19:PROT3]\nMaintenant, ils vont vraiment être fâchés...\n\n[PRO3_20:PROT3]\n~g~Fais-toi suivre par deux flics dans le garage.\n\n[PRO3_21:PROT3]\n~g~Tu dois avoir un indice de recherche pour que les flics te suivent dans le piège.\n\n[PRO3_22:PROT3]\n~g~La porte est bloquée! Dégage le passage pour qu'elle puisse être refermée.\n\n[PRO3_23:PROT3]\n~g~Marche sur le marqueur pour poser la bombe.\n\n[PRO3_24:PROT3]\n~g~Tire-toi du café!\n\n[PRO_AS1:PROT3]\nPROTECTION OK\n\n[PRO_AS2:PROT3]\n~g~Vercetti Estate génère désormais un revenu de $~1~ maximum. Pense à récupérer le fric régulièrement.\n\n[PRO3_08:PROT3]\n~g~ Retourne à ~h~Vercetti Estate~g~ sur ~h~Starfish Island~g~.\n\n{=================================== MISSION TABLE RACES ===================================}\n\n[RACES_2:RACES]\n~g~Il te faut un véhicule, c'est pas une course à pied!\n\n[RACES_3:RACES]\n3... 2... 1... PARTEZ!\n\n[RACES_8:RACES]\n~r~Tu n'as pas gagné la course!\n\n[RACES00:RACES]\nCourse ~1~ :\n\n[RACES01:RACES]\nTerminal Velocity\n\n[RACES02:RACES]\nOcean Drive\n\n[RACES03:RACES]\nBorder Run\n\n[RACES04:RACES]\nCapital Cruise\n\n[RACES05:RACES]\nVirée!\n\n[RACES06:RACES]\nEndurance V.C.\n\n[RACES07:RACES]\nParticipation : ~1~$\n\n[RACES08:RACES]\nMeilleur temps : ~1~:~1~\n\n[RACES09:RACES]\nMeilleure perf : 1er\n\n[RACES10:RACES]\nMeilleure perf : 2e\n\n[RACES11:RACES]\nMeilleure perf : 3e\n\n[RACES12:RACES]\nMeilleure perf : 4e\n\n[RACES13:RACES]\nLongueur circuit : ~1~.~1~ km\n\n[RACES15:RACES]\nMeilleur temps : NA\n\n[RACES16:RACES]\nMeilleure perf : NA\n\n[RACES18:RACES]\nTU AS GAGNE : $~1~\n\n[RACES19:RACES]\nTu n'as pas assez de moyens pour participer.\n\n[RACES22:RACES]\nMeilleur temps : ~1~:0~1~\n\n[RACES23:RACES]\nLongueur circuit : ~1~.~1~ miles\n\n[RACES_1:RACES]\n~g~Trouve un bolide et rends-toi sur la grille de départ.\n\n[RACEHLP:RACES]\n~w~Appuie sur la~h~ ~k~~PED_SPRINT~~w~ pour commencer la course choisie. Appuie sur la~h~ ~k~~VEHICLE_ENTER_EXIT~~w~ pour quitter.\n\n{=================================== MISSION TABLE RCHELI1 ===================================}\n\n[WRECKED:RCHELI1]\nTon véhicule est mort!\n\n[RCH1_4:RCHELI1]\nPoints de passage restants :\n\n[RCH1_6:RCHELI1]\n~g~Utilise l'hélico télécommandé pour passer les points de passage à travers l'aéroport.\n\n[RCH1_7:RCHELI1]\n~g~Il y a 20 points de passage en tout.\n\n[RCH1_12:RCHELI1]\n~g~L'hélicoptère télécommandé est presque hors de portée!\n\n[RCH1_13:RCHELI1]\n~r~L'hélicoptère radiocommandé est hors de portée!\n\n[RCH1_8:RCHELI1] { reVC update }\n~g~Si tu veux quitter cette mission, appuie sur la ~h~~k~~VEHICLE_FIREWEAPON~~g~ pour faire exploser ton hélicoptère radiocommandé.\n\n{=================================== MISSION TABLE RCPLNE1 ===================================}\n\n[RCPL1_4:RCPLNE1]\n~g~Fais une COURSE DE POINTS DE PASSAGE avec 3 autres avions télécommandés.\n\n[RCPL1_5:RCPLNE1]\n~g~Passe par les points de passage dispersés dans Vice City.\n\n[RCPL1_6:RCPLNE1] { reVC update }\n~g~Si tu veux quitter cette mission, appuie sur la ~h~~k~~VEHICLE_FIREWEAPON~~g~ pour faire exploser ton avion radiocommandé.\n\n[RCPL1_8:RCPLNE1]\n~g~Ton avion RC va sortir du périmètre!\n\n[RCPL1_9:RCPLNE1]\n~r~Ton avion RC est sorti du périmètre!\n\n{=================================== MISSION TABLE RCRACE1 ===================================}\n\n[RCR1_4:RCRACE1]\nTours restants :\n\n[RCR1_1:RCRACE1]\n~g~Fais une course de points de passage contre 3 autres voitures RC.\n\n[RCR1_2:RCRACE1]\n~g~Sois le premier à boucler 2 tours de circuit pour gagner!\n\n[RCR1_6:RCRACE1]\n~g~Ta voiture RC va sortir du périmètre!\n\n[RCR1_7:RCRACE1]\n~r~Ta voiture RC est sortie du périmètre!\n\n{=================================== MISSION TABLE ROCK1 ===================================}\n\n[RBM1_A:ROCK1]\nOkaaaaaaaaaay!\n\n[RBM1_B:ROCK1]\nGrandiose! Vraiment génial!\n\n[RBM1_D:ROCK1]\nHé, t'as déjà rencontré les Love Fist?\n\n[RBM1_E:ROCK1]\nNon, mais j'adore votre musique!\n\n[RBM1_F:ROCK1]\nLaisse-moi te présenter au groupe.\n\n[RBM1_G:ROCK1]\nVoici P, Percy, Dick et Willy est aux chiottes et Jezz était dans la cabine tout à l'heure...\n\n[RBM1_H:ROCK1]\nLes mecs, je veux vous présenter un bon ami à moi.\n\n[RBM1_I:ROCK1]\nVoici Tommy. Ca fait un bail qu'on se connait.\n\n[RBM1_J:ROCK1]\nOk, mon pote.\n\n[RBM1_K:ROCK1]\nAh, euh... C'est quoi déjà, ton nom?\n\n[RBM1_L:ROCK1]\nArrête-ça Jezz tu t'en souviens,\n\n[RBM1_M:ROCK1]\net essaye pas de jouer au plus malin avec moi,\n\n[RBM1_N:ROCK1]\nje suis trop intelligent, mon mignon!\n\n[RBM1_O:ROCK1]\nTu vois, le problème, Tom, c'est que ces garçons ont besoin d'aide.\n\n[RBM1_P:ROCK1]\nIls n'ont pas beaucoup de contacts ici et ils savent pas à qui s'adresser.\n\n[RBM1_Q:ROCK1]\nOn a besoin de drogue, mon pote!\n\n[RBM1_R:ROCK1]\nFaut qu'on réveille la vieille fureur de Love Fist, tu vois?\n\n[RBM1_S:ROCK1]\nEt bien, ici, c'est Vice City, quel est le problème?\n\n[RBM1_U:ROCK1]\nDu Love Juice, mec!\n\n[RBM1_V:ROCK1]\nDu Love Juice?\n\n[RBM1_W:ROCK1]\nOuais, deux doses de boomshine, une dose de trompette, 5 bombes fizz et un litre d'essence.\n\n[RBM1_X:ROCK1]\nTu peux nous aider, mon pote?\n\n[RBM1_Y:ROCK1]\nAh, ça rendrait tellement service aux garçons!\n\n[RBM1_Z:ROCK1]\nTu peux faire ça pour les garçons, pas vrai?\n\n[RBM1_8:ROCK1]\n~r~Mercedes est morte!\n\n[RBM1_10:ROCK1]\n~r~Imbécile! Tu as détruit la marchandise!\n\n[RBM1_13:ROCK1]\n~g~Amène le Love Juice et Mercedes au groupe avant qu'ils n'entrent sur scène.\n\n[RBM1_15:ROCK1]\n~r~Tu as perdu le dealer, notre cash et la drogue!\n\n[RBM1_17:ROCK1]\n~g~Tue le dealer et prends la drogue!\n\n[MOB_07A:ROCK1]\nSalut, mon vieux, les gars auraient besoin d'un peu de compagnie, si tu vois ce que je veux dire...\n\n[MOB_07B:ROCK1]\nJe connais justement la fille qu'il faut.\n\n[ROK1_5:ROCK1]\nSalut Mercedes!\n\n[ROK1_6:ROCK1]\nSalut, Tommy. Comment vas-tu?\n\n[ROK1_7:ROCK1]\nCa roule. Ecoute, les Love Fist, ça te branche?\n\n[ROK1_8:ROCK1]\nOk, mais c'est un service qu'il faudra me retourner...\n\n[RBM1_14:ROCK1]\n~g~T'as besoin d'une bagnole ou d'une bécane!\n\n[RBM1_1:ROCK1]\n~g~Va prendre Mercedes à son appartement.\n\n[RBM1_12:ROCK1]\n~g~Va récupérer les ingrédients du Love Juice chez le dealer.\n\n[ROK1_2:ROCK1]\nPLUS NECESSAIRE\n\n[ROK1_3:ROCK1]\nPLUS NECESSAIRE\n\n[MERC_39:ROCK1]\nA plus tard, champion.\n\n[RBM1_C:ROCK1]\nHé, Tommy! Content que t'aies réussi!\n\n[ROK1_1A:ROCK1]\nTu cherches quelque chose de spécial? J'ai ce qu'il te faut!\n\n[ROK1_9:ROCK1]\nMerci pour le pognon, suce boules!\n\n[RBM1_T:ROCK1]\nOn a besoin de Love Juice, mec, tu vois?\n\n{=================================== MISSION TABLE ROCK2 ===================================}\n\n[RBM2_A:ROCK2]\nTommy, mon pote, je suis content de te voir!\n\n[RBM2_B:ROCK2]\nQu'est-ce qui se passe?\n\n[RBM2_C:ROCK2]\nDes mauvaises vibrations, Tommy...\n\n[RBM2_E:ROCK2]\nIl y a ce chat, on le connaît pas, mais lui il nous connaît.\n\n[RBM2_F:ROCK2]\nC'est comme ce chat. Il nous connaît tous.\n\n[RBM2_G:ROCK2]\nIl sait que Willy a un faible pour les culottes de ses femmes, hé hé!\n\n[RBM2_H:ROCK2]\nOu que Percy aime bien Duran Duran!\n\n[RBM2_K:ROCK2]\nOuais, le truc de la fusée d'amour, c'est vrai. Mais écoute, ce chat...\n\n[RBM2_L:ROCK2]\nouais, ouais, ce gars, il veut voir les Love Fist morts!\n\n[RBM2_M:ROCK2]\nMorts, Tommy.\n\n[RBM2_N:ROCK2]\nLes Love Fist disparus. Tu sais ce qu'on dit, les meilleurs meurent jeunes...\n\n[RBM2_O:ROCK2]\nTommy, faut que tu sauves les Love Fist!\n\n[RBM2_P:ROCK2]\nOn a une séance d'autographes dans deux heures et je pense que...\n\n[RBM2_Q:ROCK2]\nEt les garçons pensent que le mec va essayer quelque chose de très vilain là-bas.\n\n[RBM2_1:ROCK2]\n~g~Conduis la limousine à la séance d'autographes et essaye de démasquer le psychopathe .\n\n[RBM2_2:ROCK2]\n~r~T'as bousillé la bagnole du groupe!\n\n[RBM2_3:ROCK2]\n~g~Va à la séance d'autographes!\n\n[RBM2_4:ROCK2]\n~g~Attrape le psychopathe! Ne le laisse pas s'échapper!\n\n[RBM2_5:ROCK2]\n~r~Tu l'as perdu, imbécile!\n\n[RBM2_7:ROCK2]\n~r~Les fans ont été attaqués, le psychopathe ne se montrera pas!\n\n[RBM2_8:ROCK2]\n~r~Les agents de sécurité ont été attaqués, le psychopathe ne se montrera pas!\n\n[PSYCH_1:ROCK2]\nJe veux voir les Love Fist morts!\n\n[PSYCH_2:ROCK2]\nLes Love Fist ont gâché ma vie!\n\n[RBM2_I:ROCK2]\nFerme-la un peu. C'est pas parce que Jezz encule les moutons...\n\n[RBM2_R:ROCK2]\nOh, ferme-la!\n\n[RBM2_D:ROCK2]\nJe plaisante pas. C'est pas des conneries, mec, tu piges?\n\n[RBM2_J:ROCK2]\nC'est le truc de la fusée d'amour, tu sais?\n\n{=================================== MISSION TABLE ROCK3 ===================================}\n\n[RBM3_A:ROCK3]\nTommy! Le psychopathe est de retour!\n\n[RBM3_B:ROCK3]\nQu'est-ce qui se passe?\n\n[RBM3_C:ROCK3]\nCe psychopathe ne laissera jamais les Love Fist tranquilles!\n\n[RBM3_D:ROCK3]\nTu l'as pas tué, mon pote et il est revenu.\n\n[RBM3_E:ROCK3]\nOuais, ouais et le truc c'est que...\n\n[RBM3_F:ROCK3]\nLe truc, c'est qu'on a besoin de quelqu'un de confiance pour conduire la limousine,\n\n[RBM3_G:ROCK3]\nparce que ce timbré continue à nous menacer!\n\n[RBM3_I:ROCK3]\nOn chie tous dans nos frocs, mec.\n\n[RBM3_J:ROCK3]\nOk, les gars, du calme, je vais m'en occuper...\n\n[RBM3_K:ROCK3]\nNormalement, j'ai mieux à foutre que de faire le taxi pour une bande d'Ecossais bisexuels bourrés,\n\n[RBM3_L:ROCK3]\nmais dans votre cas, je vais faire une exception.\n\n[ROK3_03:ROCK3]\nAutant pas faire dans la demi-mesure, alors.\n\n[ROK3_04:ROCK3]\nHé, Tommy, change la musique!\n\n[ROK3_08:ROCK3]\nCa commence à me faire chier, cette histoire.\n\n[ROK3_09:ROCK3]\nGarde juste le pied au plancher!\n\n[ROK3_61:ROCK3]\nFaut qu'on trouve la bombe!\n\n[ROK3_28:ROCK3]\nJe vais bientôt jouer de la basse en enfer...\n\n[ROK3_30:ROCK3]\nQue quelqu'un fasse quelque chose!\n\n[ROK3_32:ROCK3]\nOk, toi monsieur le dur à cuire, fais quelque chose!\n\n[ROK3_34:ROCK3]\nWilly pourrait juste sucer le boomshine à la paille.\n\n[ROK3_37:ROCK3]\nPassez une paille à Willy!\n\n[ROK3_41:ROCK3]\nQuel fil, Tommy?\n\n[ROK3_42:ROCK3]\nLe vert.\n\n[ROK3_43:ROCK3]\nY'en a pas de vert. Ou alors celui-la est vert?\n\n[ROK3_44:ROCK3]\nEst-ce qu'un de ces fils te semble vert?\n\n[ROK3_49:ROCK3]\nCa fait des années que je te supporte!\n\n[ROK3_51:ROCK3]\nUne grosse poufiasse hurlante...\n\n[ROK3_52:ROCK3]\nOuais!\n\n[ROK3_53:ROCK3]\nFerme-la et arrache un fil!\n\n[ROK3_54:ROCK3]\nLequel?\n\n[ROK3_55:ROCK3]\nCelui-là...\n\n[ROK3_56:ROCK3]\nNon!\n\n[ROK3_57:ROCK3]\nHé, on est ok, on a pas sauté, les potes! Tommy, mon pote bravo. Et Rock and Roll!\n\n[ROK3_58:ROCK3]\nOn a pas un concert où aller? Un racket à faire? Des fans à insulter?\n\n[ROK3_59:ROCK3]\nLOVE FIST!\n\n[ROK3_60:ROCK3]\nT'as fini avec cette bouteille?\n\n[RBM3_4:ROCK3]\n~r~Tu as tué les Love Fist!\n\n[RBM3_6:ROCK3]\nDETONATION :\n\n[RBM3_1:ROCK3]\n~g~Conduis les Love Fist jusqu'au concert.\n\n[RBM3_2:ROCK3]\nSi tu essayes de quitter la voiture tant que la bombe est armée, elle explosera.\n\n[RBM3_3:ROCK3]\nSi la jauge de détonation devient pleine, la bombe explose.\n\n[RBM3_8:ROCK3]\nPlus tu conduis vite, plus la jauge de détonation diminue.\n\n[RBM3_7:ROCK3]\n~g~BOMBE DESAMORCEE!\n\n[ROK3_6A:ROCK3]\n~g~Love Fist. Vous avez fini de polluer les ondes!\n\n[ROK3_6B:ROCK3]\n~g~Je vous ai donné l'occasion de devenir mes amis. Je vais maintenant vous offrir celle de mourir!\n\n[ROK3_62:ROCK3]\nalors on a pensé te montrer notre Temple du rock-\n\n[ROK3_63:ROCK3]\nQue tu te fasses une idée de la fureur des Love Fist!\n\n[ROK3_64:ROCK3]\nEcoute-toi toi même, mon pote. C'est de la daube!\n\n[ROK3_65:ROCK3]\nHé, à tous les gosses, c'est un temple et nous sommes les prêtres!\n\n[ROK3_66:ROCK3]\nOuais, eh ben, si les gosses aiment leurs prêtres à moitié saouls et complètement sourds,\n\n[ROK3_67:ROCK3]\nc'est leur problème.\n\n[ROK3_68:ROCK3]\nAh, merde, la bande de la cassette est encore bouffée.\n\n[ROK3_69:ROCK3]\nSi ça continue, faudra jouer en live.\n\n[ROK3_70:ROCK3]\nOoooh merde! Mes intestins...\n\n[ROK3_74:ROCK3]\nAh, tiens, qu'est-ce que c'est que ça? Tommy, mets cette cassette.\n\n[ROK3_01:ROCK3]\nMon pote, c'est enfin l'heure d'un verre bien mérité.\n\n[ROK3_02:ROCK3]\nLa salle de concert est à une centaine de mètres plus loin.\n\n[ROK3_05:ROCK3]\nJe me sens bizarre quand ma tête ne tambourine pas.\n\n[ROK3_07:ROCK3]\nTommy, faut que tu sauves le groupe!\n\n[ROK3_29:ROCK3]\nTommy, continue de foncer, mec!\n\n[ROK3_31:ROCK3]\nQue quelqu'un fasse quelque chose... C'est quoi ces conneries? J'ai déjà vu des minettes plus courageuses.\n\n[ROK3_33:ROCK3]\nEcoute, mec. Moi, je joue d'un instrument, j'y connais rien aux bombes.\n\n[ROK3_35:ROCK3]\nOuais, j'ai entendu dire que t'étais doué pour ce genre de trucs!\n\n[ROK3_38:ROCK3]\nUne paille? Hé, ici, c'est le bus de tournée des Love Fist!\n\n[ROK3_39:ROCK3]\nOù c'est que tu veux que je trouve une paille?\n\n[ROK3_46:ROCK3]\nJ'aurais dû te larguer quand j'en avais l'occasion.\n\n[ROK3_47:ROCK3]\nCapitaliste!\n\n[ROK3_48:ROCK3]\nArriviste!\n\n[ROK3_73:ROCK3]\nJezz écoute la cassette,\n\n[RBM3_9:ROCK3]\nSi tu t'arrêtes ou conduis trop lentement, la jauge de détonation augmente.\n\n[ROK3_50:ROCK3]\nFerme-la, pauvre abruti!\n\n[ROK3_36:ROCK3]\nHé, j'étais raide défoncé cette nuit-là, et tu le sais bien!\n\n[RBM3_H:ROCK3]\nJe chie dans mon froc, mec. Je veux ma maman!\n\n[ROK3_45:ROCK3]\nOh, je vois la mort dans les cartes! Tout est vert!\n\n[ROK3_6C:ROCK3]\n~g~Si tu ralentis, la limousine explosera et les GROS TOCARDS CHEVELUS avec!\n\n[ROK3_71:ROCK3]\nOn doit continuer. Merci encore, Tommy! T'as assuré, mec! A plus!\n\n[ROK3_1:ROCK3]\nEnfin, mec, voici l'heure d'un verre bien mérité. La salle est juste à quelques mètres d'ici.\n\n[ROK3_2:ROCK3]\nTu m'en sers un grand alors. Hé, Tommy, change de musique, mec.\n\n[ROK3_3:ROCK3]\nJe pète les plombs si je secoue pas la tête. Hé, regarde, c'est quoi ça? Tommy, mets cette cassette.\n\n[ROK3_4:ROCK3]\nLove Fist. Vous avez fini de polluer les ondes. Je vous ai donné une chance de devenir mes amis.\n\n[ROK3_5:ROCK3]\nMaintenant vous allez mourir. Essayez de freiner et c'est la fin! Paf, plus de limousine et plus de GROS NASES CHEVELUS non plus.\n\n[ROK3_6:ROCK3]\nTommy, mec, tu dois sauver le groupe! J'en ai marre de ces conneries. Enlève pas ton pied de la pédale, mec!\n\n[ROK3_7:ROCK3]\nOn doit trouver la bombe! On peut pas continuer à rouler toute la journée? Ouais, quoi, on a plein de trucs à boire...\n\n[ROK3_8:ROCK3]\nLa bombe, elle serait pas dans le moteur? Va falloir qu'on s'arrête pour la désamorcer! Merde, mec, on va tous crever! J'vais m'bourrer la gueule!\n\n[ROK3_9:ROCK3]\nHé, on est dans la mouise, mon pote! Tu trouveras pas ta réponse dans la boisson! Tire-toi de là!\n\n[ROK3_10:ROCK3]\nHé, y'a des fils qui sortent de la bouteille de vodka! C'est pas de la vodka, c'est du BOOMSHINE!\n\n[ROK3_11:ROCK3]\nAAAAAHHHHHH! Elle va exploser! AAAAAAAAAAAHHHHH!!!!!!!!!!\n\n[ROK3_12:ROCK3]\nOn m'avait prévenu que l'alcool me perdrait. J'ai déjà vu ça à la télé. Il suffit de tirer un de ces fils, mais lequel? J'en sais foutre rien, mec!\n\n[ROK3_13:ROCK3]\nPutain, j'en sais rien! Willy, dis quelque chose. J'vais jouer de la basse en enfer.\n\n[ROK3_14:ROCK3]\nTommy, mec, continue de rouler à fond la caisse. Que quelqu'un fasse quelque chose! Ouais, c'est ça.\n\n[ROK3_15:ROCK3]\n'Que quelqu'un fasse quelque chose'. Putain, c'est quoi ces conneries. J'ai connu des tantes plus braves. Vas-y le gros dur, fais quelque chose!\n\n[ROK3_16:ROCK3]\nEcoute, mec, je suis musicien moi, j'sais pas comment ça fonctionne les bombes. Willy a qu'à sucer le boomshine à la paille.\n\n[ROK3_17:ROCK3]\nOuais, on m'a dit que ça, tu savais faire. J'étais tout émoustillé ce soir-là, comme tu le sais!\n\n[ROK3_18:ROCK3]\nT'as qu'à filer une paille à Willy! Une paille? C'est le bus de tournée des Love Fist!\n\n[ROK3_19:ROCK3]\nOù est-ce que je vais bien pouvoir trouver une paille? Quel fil, Tommy? Le vert. Y'en a pas de vert.\n\n[ROK3_20:ROCK3]\nOù peut-être qu'il est vert celui-là? T'en vois un vert, toi?\n\n[ROK3_21:ROCK3]\nOh non! On va crever! Je vois la vie en vert! J'aurais dû me débarrasser de toi qu'en j'en avais l'occasion.\n\n[ROK3_22:ROCK3]\nChasse la gloire! Capitaliste! Ca fait des années que je te soutiens. Ferme-là, tafiole!\n\n[ROK3_23:ROCK3]\nUne grosse chialeuse, ouais, ferme-là et tire le putain de fil! Lequel? Celui-là...\n\n[ROK3_24:ROCK3]\nNON! On est pas morts. On a pas sauté, mec!\n\n[ROK3_25:ROCK3]\nTommy, bien joué, mec. Rock and roll, mon pote! On a pas un concert à donner, nous?\n\n[ROK3_26:ROCK3]\nAmasser du blé? Abuser des minettes? LOVE FIST!\n\n[ROK3_27:ROCK3]\nT'as fini avec cette bouteille?\n\n{=================================== MISSION TABLE SERG1 ===================================}\n\n[TEX1_A:SERG1]\nEntre et pose ton cul sur une des banquettes.\n\n[TEX1_B:SERG1]\nPutain, mon père avait l'habitude de dire qu'à cheval donné, on ne regarde pas les dents et il l'a jamais fait!\n\n[TEX1_C:SERG1]\nTu veux une larme de bon vieux whisky?\n\n[TEX1_D:SERG1]\nNon merci.\n\n[TEX1_E:SERG1]\nUn mec qui aime avoir les idées claires, c'est bien.\n\n[TEX1_F:SERG1]\nEn ce moment, mes affaires tournent pas comme elles le devraient...\n\n[TEX1_G:SERG1]\nC'est la merde! Et je veux nettoyer une partie de cette merde! T'es avec moi?\n\n[TEX1_H:SERG1]\nEuh, ouais.\n\n[TEX1_I:SERG1]\nEn fait, j'ai besoin d'un mec obstiné pour me débarrasser d'une merde.\n\n[TEX1_J:SERG1]\nT'as l'air du genre persuasif.\n\n[TEX1_K:SERG1]\nLa persuasion c'est ma spécialité.\n\n[TEX1_L:SERG1]\nBon, ce mec sera au country club du golf.\n\n[TEX1_M:SERG1]\nIls autorisent pas les flingues, alors ses gardes du corps en auront pas.\n\n[TEX1_N:SERG1]\nVa me massacrer ce salopard.\n\n[TEX1_O:SERG1]\nTiens, voilà ta carte de membre, mais va falloir te trouver des fringues plus appropriées.\n\n[TEX1_2:SERG1]\n~g~Maintenant, direction le Leaf Links Golf Club.\n\n[TEX1_0:SERG1]\n~g~La cible est à ta portée, en train de jouer au golf. Fais en sorte que ce soit sa dernière partie!\n\n[TEX1_3:SERG1]\nC'est qui ce mec? Occupez-vous de lui!\n\n[TEX1_6:SERG1]\nQuel beau cul!\n\n[TEX1_7:SERG1]\nC'est moi, ça?\n\n[TEX1_8:SERG1]\nChaque fois que tu ouvres ton caddie, tu reçois automatiquement un club de golf si ton emplacement d'arme de corps à corps est vide.\n\n[TEX1_9:SERG1]\nAttrapez-le!\n\n[TEX1_10:SERG1]\nTuez-moi ce dingue!\n\n[TEX1_1:SERG1]\n~g~Va chercher des fringues de golfeur chez Jocksport's.\n\n{=================================== MISSION TABLE SERG2 ===================================}\n\n[TEXEXIT:SERG2]\n~g~Maintenant, casse-toi de Little Haiti!\n\n[TEX_2A:SERG2]\n~g~Parfait! Ils t'ont repéré!\n\n[TEX_2B:SERG2]\n~r~Imbécile! Les gens doivent VOIR un cubain faire le coup!\n\n[TEX_2C:SERG2]\n~g~Va te trouver des fringues de cubain dans Little Havana!\n\n[TEX_2D:SERG2]\n~g~Maintenant, liquide le chef de gang haïtien au salon funéraire Romero!\n\n[TEX2_A:SERG2]\nTommy, voici Donald Love. Donald, Tommy Vercetti,\n\n[TEX2_B:SERG2]\nla dernière crapule à débarquer ici.\n\n[TEX2_C:SERG2]\nOuais... Euh...\n\n[TEX2_D:SERG2]\nDonald, ferme-la et écoute, t'apprendras peut-être quelque chose.\n\n[TEX2_E:SERG2]\nBon. Il y a rien de mieux qu'une bonne guerre des gangs pour faire baisser les prix de l'immobilier.\n\n[TEX2_F:SERG2]\nA part une catastrophe, peut-être, comme une peste biblique ou un truc dans le genre.\n\n[TEX2_G:SERG2]\nMais ça serait aller un peu trop loin, dans le cas présent.\n\n[TEX2_H:SERG2]\nTu piges, tête de gland?\n\n[TEX2_I:SERG2]\nUn chef du gang haïtien est mort y'a pas longtemps. C'est apparemment un coup des Cubains, mais personne en est sûr.\n\n[TEX2_J:SERG2]\nAlors on va arranger ça! Tu te déguises en Cubain\n\n[TEX2_K:SERG2]\net tu fonces foutre le bordel aux funérailles. Tu leur balances la sauce et tu dégages vite fait.\n\n[TEX2_L:SERG2]\nT'as compris, Donald?\n\n[TEX2_M:SERG2]\nC'est comme faire entrer le renard dans le poulailler, hein?\n\n[TEX2_N:SERG2]\nEt puis on attend tranquillement que les prix s'écroulent.\n\n{=================================== MISSION TABLE SERG3 ===================================}\n\n[TEX3_A:SERG3]\nRegarde un peu, mon pote. J'ai un problème et je compte sur ton aide.\n\n[TEX3_B:SERG3]\nJe suis pas constructeur.\n\n[TEX3_C:SERG3]\nBen, je pensais surtout à tes talents de démolisseur.\n\n[TEX3_D:SERG3]\nBon, là, c'est le développement prévu, et ça,\n\n[TEX3_E:SERG3]\nc'est la propriété sur laquelle on a des vues.\n\n[TEX3_F:SERG3]\nT'essayes de me dire que ce nouveau bloc de bureaux est comme qui dirait sur le chemin.\n\n[TEX3_G:SERG3]\nT'as tout compris.\n\n[TEX3_H:SERG3]\nBon, je vais aller faire un tour en ville pendant un moment\n\n[TEX3_I:SERG3]\net si la construction de ces bureaux devait faire face à de subits et insurmontables problèmes structurels, alors je...\n\n[TEX3_J:SERG3]\nEn tant qu'honnête citoyen, vous vous sentiriez obligé d'intervenir\n\n[TEX3_K:SERG3]\npour la réhabilitation d'un important secteur de la ville?\n\n[TEX3_L:SERG3]\nOù on peut en trouver d'autres, des mecs dans ton genre?\n\n[TEX3_1:SERG3]\n~g~Utilise l'hélico télécommandé pour transporter des bombes sur les quatre cibles du bâtiment que tu dois détruire.\n\n[TEX3_2:SERG3]\n~g~Tu dois larguer une bombe sur chaque cible, et ce, dans n'importe quel ordre.\n\n[TEX3_5:SERG3]\n~g~Si tu largues une bombe sans succès, tu peux la récupérer pour un nouvel essai.\n\n[TEX3_7:SERG3]\n~g~Tu a alors 7 minutes pour larguer toutes les autres bombes!\n\n[TEX3_8:SERG3]\n~g~Tu as raté la cible! Récupère la bombe et réessaye!\n\n[TEX3_10:SERG3]\n~g~Largue la bombe sur la cible.\n\n[TEX3_11:SERG3]\nCibles restantes:\n\n[TEX3_17:SERG3]\n~r~Tu as dépassé le temps imparti et le bâtiment n'est pas détruit.\n\n[TEX3_18:SERG3]\n~r~Ton hélico télécommandé a été détruit! Comment vas-tu faire pour transporter les bombes, maintenant?\n\n[TEX3_19:SERG3]\n~r~Tu as largué ta bombe dans l'eau! Tu as besoin des 4 bombes pour détruire le bâtiment!\n\n[TEX3_20:SERG3]\n~g~Ton hélico télécommandé est presque hors de portée! Retourne au bâtiment et termine le travail!\n\n[TEX3_21:SERG3]\n~r~Ton hélico télécommandé est hors de portée!\n\n[TEX3_24:SERG3]\nAppuie sur ~h~~k~~VEHICLE_LOOKLEFT~ ~w~pour faire pivoter l'hélico dans le sens inverse des aiguilles d'une montre.\n\n[TEX3_25:SERG3]\nAppuie sur ~h~~k~~VEHICLE_LOOKLEFT~ ~w~pour faire pivoter l'hélico dans le sens des aiguilles d'une montre.\n\n[TEX3_27:SERG3]\n~g~L'escalier central mène à tous les étages du bâtiment.\n\n[TEX3_31:SERG3]\n~r~Tu as détruit la camionnette qui contenait l'hélico télécommandé et les bombes!\n\n[TEX3_32:SERG3]\nTu peux ~h~regarder derrière~w~ toi en ~h~appuyant simultanément sur ~k~~VEHICLE_LOOKLEFT~ et ~k~~VEHICLE_LOOKRIGHT~~w~.\n\n[TEX3_4:SERG3] { reVC update }\n~g~Pour larguer une bombe, appuie sur la~h~ ~k~~VEHICLE_FIREWEAPON~~w~.\n\n[TEX3_29:SERG3] { reVC update }\nPour larguer une bombe, appuie sur la~h~ ~k~~VEHICLE_FIREWEAPON~.\n\n[TEX3_26:SERG3]\nAppuie sur la ~h~~k~~VEHICLE_BRAKE~ ~w~pour réduire la vitesse du rotor et ainsi faire~h~ descendre l'hélicoptère.\n\n[TEX3_22:SERG3]\nAppuie sur la ~h~~k~~VEHICLE_ACCELERATE~ ~w~pour augmenter la vitesse du rotor et ainsi faire~h~ monter l'hélicoptère.\n\n[TEX3_16:SERG3]\n~g~Va jusqu'au camion ~w~TOPFUN ~g~ près du bâtiment à démolir.\n\n[TEX3_33:SERG3]\nUne fois que tu as ramassé une bombe, le radar t'indique la position de la cible par rapport à l'hélico.\n\n[TEX3_34:SERG3]\nLe ~h~point triangulaire vers le haut ~w~indique que la cible se trouve ~h~au-dessus ~w~de l'hélicoptère radiocommandé.\n\n[TEX3_35:SERG3]\nLe ~h~point triangulaire vers le bas ~w~indique que la cible se trouve ~h~en dessous ~w~de l'hélicoptère radiocommandé.\n\n[TEX3_36:SERG3]\nLe ~h~point carré ~w~indique que la cible se trouve ~h~au même niveau ~w~que l'hélicoptère radiocommandé.\n\n[TEX3_6:SERG3]\n~g~Une fois que tu as ramassé une bombe pour la première fois, le compte à rebours s'enclenche.\n\n[TEX3_28:SERG3]\nPour ~h~ramasser une bombe~w~, manoeuvre l'hélico radiocommandé à côté. Il ne peut transporter qu'une seule bombe à la fois.\n\n[TEX3_30:SERG3]\n~g~Pour ramasser une bombe, manoeuvre l'hélico radiocommandé à côté. Il ne peut transporter qu'une seule bombe à la fois.\n\n[TEX3_12:SERG3]\n~g~Bombe posée! Plus que 3 cibles! Va chercher une autre bombe!\n\n[TEX3_13:SERG3]\n~g~Bombe posée! Plus que 2 cibles! Va chercher une autre bombe!\n\n[TEX3_14:SERG3]\n~g~Bombe posée! Plus qu'une cible! Va chercher une autre bombe!\n\n[TEX3_15:SERG3]\n~r~Compte à rebours enclenché! ~g~Tu dois poser les ~w~4 bombes ~g~avant la fin du temps imparti!\n\n[TEX3_37:SERG3]\nPousse le ~h~joystick analogique droit vers le haut ~w~pour vitesse la vitesse du rotor et ainsi faire ~h~ monter l'hélicoptère.\n\n[TEX3_38:SERG3] { reVC update }\n{Pousse le ~h~~k~~VEHICLE_ACCELERATE~ ~w~pour augmenter la réduire du rotor et ainsi faire ~h~ descendre l'hélicoptère.}\nPousse le ~h~joystick analogique droit vers la bas ~w~pour augmenter la réduire du rotor et ainsi faire ~h~ descendre l'hélicoptère.\n\n[TEX3_39:SERG3]\n~g~Appuie sur la touche ~h~~k~~VEHICLE_HANDBRAKE~ ~g~pour larguer une bombe.\n\n[TEX3_40:SERG3]\nAppuie sur la touche ~h~~k~~VEHICLE_HANDBRAKE~ ~w~pour larguer une bombe.\n\n[TEX3_23:SERG3]\nAppuyer sur les touches ~h~~k~~VEHICLE_TURRETUP~~w~ et ~h~~k~~VEHICLE_TURRETDOWN~~w~ pour orienter l'hélicoptère dans la direction souhaitée.\n\n{=================================== MISSION TABLE TAXI1 ===================================}\n\n[FARES:TAXI1]\nCLIENTS:\n\n[TAXI1:TAXI1]\nCherche une course.\n\n[TSCORE2:TAXI1]\n~1~$\n\n[IN_ROW:TAXI1]\n~1~ DE SUITE! Bonus : ~1~$\n\n[TAXI3:TAXI1]\n~r~Ton client est parti terrorisé!\n\n[TAXI7:TAXI1]\n~r~Ta voiture est endommagée. Fais-la réparer.\n\n[TAXI4:TAXI1]\nLa course est finie!\n\n[TAXI5:TAXI1]\nBONUS DE VITESSE!\n\n[TAXI6:TAXI1]\nLa mission taxi est finie\n\n[TAXIH1:TAXI1]\nArrête-toi près d'un piéton mis en évidence pour qu'il monte, puis conduis-le à destination avant la fin du temps imparti.\n\n[FARE1:TAXI1]\n~g~Destination ~w~'le Pole Position Club' ~g~à Ocean Beach.\n\n[FARE3:TAXI1]\n~g~Destination ~w~'le Marina' ~g~à Ocean Beach.\n\n[FARE4:TAXI1]\n~g~Destination ~w~'Ammu-Nation' ~g~à Ocean Beach.\n\n[FARE5:TAXI1]\n~g~Destination ~w~'la quincaillerie' ~g~à Washington Beach.\n\n[FARE6:TAXI1]\n~g~Destination ~w~'le centre commercial de North Point' ~g~à Vice Point.\n\n[MFARE1:TAXI1]\n~g~Destination ~w~'Ammu-Nation' ~g~dans le Centre.\n\n[MFARE2:TAXI1]\n~g~Destination ~w~'le Terminal' ~g~à l'aéroport International Escobar.\n\n[WFARE3:TAXI1]\n~g~Destination ~w~'Sunshine Autos' ~g~dans Little Havana.\n\n[WFARE4:TAXI1]\n~g~Destination ~w~'les taxis Kaufman' ~g~dans Little Haiti.\n\n[WFARE5:TAXI1]\n~g~Destination ~w~'la quincaillerie' ~g~dans Little Havana.\n\n[WFARE6:TAXI1]\n~g~Destination ~w~'Howlin Petes Bike Emporium' ~g~dans le Centre.\n\n[FARE7:TAXI1]\n~g~Destination ~w~'Les bijoutiers' ~g~à Vice Point.\n\n[FARE8:TAXI1]\n~g~Destination ~w~'la plage' ~g~à Ocean Beach.\n\n[FARE9:TAXI1]\n~g~Destination ~w~'la plage' ~g~à Washington Beach.\n\n[FARE10:TAXI1]\n~g~Destination ~w~'la plage' ~g~à Vice Point.\n\n[FARE11:TAXI1]\n~g~Destination ~w~'l'hôpital' ~g~à Ocean Beach.\n\n[FARE12:TAXI1]\n~g~Destination ~w~'l'hôpital' ~g~à Vice Point.\n\n[FARE13:TAXI1]\n~g~Destination ~w~'le commissariat de police' ~g~à Washington Beach.\n\n[FARE14:TAXI1]\n~g~Destination ~w~'le commissariat de police' ~g~à Vice Point.\n\n[FARE15:TAXI1]\n~g~Destination ~w~'le restaurant de pizza' ~g~à Vice Point.\n\n[WFARE7:TAXI1]\n~g~Destination ~w~'le commissariat de police' ~g~à Little Havana.\n\n[WFARE8:TAXI1]\n~g~Destination ~w~'le commissariat de police' ~g~à Downtown.\n\n[WFARE9:TAXI1]\n~g~Destination ~w~'l'hôpital' ~g~à Downtown.\n\n[WFARE10:TAXI1]\n~g~Destination ~w~'l'hôpital' ~g~à Little Havana.\n\n[WFARE11:TAXI1]\n~g~Destination ~w~'le stade' ~g~à Downtown.\n\n[WFARE12:TAXI1]\n~g~Destination ~w~'le restaurant de pizza' ~g~à Little Haiti.\n\n[WFARE13:TAXI1]\n~g~Destination ~w~'le restaurant de pizza' ~g~à Downtown.\n\n[WFARE14:TAXI1]\n~g~Destination ~w~'les docks' ~g~à Viceport.\n\n[WFARE15:TAXI1]\n~g~Destination ~w~'la pharmacie' ~g~à Little Haiti.\n\n[FARE2:TAXI1]\n~g~Destination ~w~'le Malibu club' ~g~à Vice Point.\n\n{=================================== MISSION TABLE TAXICUT ===================================}\n\n[TAXC_A:TAXICUT]\nJ'imagine que t'es le nouveau proprio.\n\n[TAXC_B:TAXICUT]\nD'où tu sors? La Mafia? Le Cartel? T'as pas l'air mexicain...\n\n[TAXC_C:TAXICUT]\nQuoi qu'il en soit, tu ferais mieux de continuer avec le barratin comme quoi les choses vont changer,\n\n[TAXC_D:TAXICUT]\npeut-être même menacer des conducteurs...\n\n[TAXC_E:TAXICUT]\nVas-y mollo avec Ted là-bas, on vient juste de lui soigner son hernie.\n\n[TAXC_F:TAXICUT]\nEh bien, ouais. Les choses vont changer dans le coin, madame.\n\n[TAXC_G:TAXICUT]\nArrête tes conneries, petit. Vaut mieux que tu me laisses faire.\n\n[TAXC_H:TAXICUT]\nCa fait des années que je suis dans ce genre de biz.\n\n[TAXC_I:TAXICUT]\nEcoutez tous.\n\n[TAXC_J:TAXICUT]\nOn a une nouvelle direction et les choses vont encore changer dans le coin.\n\n[TAXC_K:TAXICUT]\nNotre nouvelle direction, la...\n\n[TAXC_L:TAXICUT]\nTu fais partie de quel gang?\n\n[TAXC_M:TAXICUT]\nEn fait, je fais pas partie d'un gang...\n\n[TAXC_N:TAXICUT]\nC'est quoi ton foutu nom, petit?\n\n[TAXC_O:TAXICUT]\nVercetti, Tommy Vercetti.\n\n[TAXC_P:TAXICUT]\nNotre nouvelle direction, le gang Vercetti,\n\n[TAXC_Q:TAXICUT]\nva veiller à nous éviter les emmerdes.\n\n[TAXC_R:TAXICUT]\nCapiche? Terminé!\n\n[TAXC_S:TAXICUT]\nQu'est-ce que t'as pensé du 'capiche'? Moi, j'ai bien aimé le 'capiche'.\n\n[TAXC_T:TAXICUT]\nBon, alors c'est comme ça que ça marchait avant\n\n[TAXC_U:TAXICUT]\net on va continuer à faire tourner l'entreprise comme ça.\n\n[TAXC_V:TAXICUT]\nSi on a des ennuis avec une compagnie concurrente, tu leur flanques une dérouillée.\n\n[TAXC_W:TAXICUT]\nPuis ils nous flanquent une dérouillée.\n\n[TAXC_X:TAXICUT]\npuis tu leur flanques une dérouillée,\n\n[TAXC_Y:TAXICUT]\net cetera et cetera. T'as pigé?\n\n[TAXC_Z:TAXICUT]\nEuh, ouais, je crois...\n\n[TAXC_A1:TAXICUT]\nPrends simplement un taxi au garage si tu te sens de bosser.\n\n{=================================== MISSION TABLE TAXIWA1 ===================================}\n\n[OUTTIME:TAXIWA1]\n~r~T'es trop lent, mec, trop lent!\n\n[TAX1_1:TAXIWA1]\nOk, on a un client rupin qui a besoin d'être ramassé à Starfish island, ça intéresse quelqu'un?\n\n[TAX1_2:TAXIWA1]\nIci, Tommy, je prends!\n\n[TAX1_3:TAXIWA1]\nC'est mon client, dégage!\n\n[TAX1_4:TAXIWA1]\nAllez, vite, monte!\n\n[TAX1_5:TAXIWA1]\nOk, ok, mais ne me faites pas de mal!\n\n[TAXW1_1:TAXIWA1]\n~g~Va prendre le V.I.P. sur Starfish Island.\n\n[TAXW1_2:TAXIWA1]\n~g~Ramène le V.I.P.! Bousille l'autre bagnole!\n\n[TAXW1_3:TAXIWA1]\n~r~Le V.I.P. est mort!\n\n[TAXW1_4:TAXIWA1]\n~r~Le V.I.P. a été déposé!\n\n[TAXW1_6:TAXIWA1]\n~g~Emmène le V.I.P. à l'aéroport!\n\n{=================================== MISSION TABLE TAXIWA2 ===================================}\n\n[TAX2_1:TAXIWA2]\nAppel à toutes les voitures, on perd des clients dans toute la ville! Qu'est-ce que vous foutez, les gars?\n\n[TAX2_2:TAXIWA2]\nLes taxis VC nous les prennent! Ils ont trop de voitures, on peut pas rivaliser!\n\n[TAX2_3:TAXIWA2]\nVercetti, si t'es en ville en train d'écouter, va falloir mettre quelques taxis VC hors circuit ou c'est la faillite!\n\n[TAXW2_1:TAXIWA2]\n~g~Détruis 3 taxis concurrents!\n\n{=================================== MISSION TABLE TAXIWA3 ===================================}\n\n[TAX3_1:TAXIWA3]\nVoiture 13, on a une demoiselle Cortez à prendre dans le centre, elle vous a spécialement demandé.\n\n[TAX3_2:TAXIWA3]\nOk, je prends. Voiture 13 en course!\n\n[TAX3_3:TAXIWA3]\nHmmmm, aucun signe de Mercedes...\n\n[TAXW3_3:TAXIWA3]\n~g~Bousille le taxi leader!\n\n[TAXW3_2:TAXIWA3]\n~g~Reste vivant jusqu'à la fin du temps imparti.\n\n[TAX_AS1:TAXIWA3]\nCOMPAGNIE DE TAXIS ACQUISE\n\n[TAX_AS2:TAXIWA3]\n~G~Les taxis Kaufman génère dorénavant un revenu de $~1~ maximum. Pense à récupérer le fric régulièrement.\n\n[TAX3_4:TAXIWA3]\nL'heure est venue pour l'ange gardien des taxis Kaufman de froisser de la tôle!\n\n[TAX3_5:TAXIWA3]\nHé mec, j'vais te bousiller ta caisse!\n\n{ reVC updates }\n{ new languages }\n[FEL_JAP]\nJAPONAIS\n\n[FEL_POL]\nPOLONAIS\n\n[FEL_RUS]\nRUSSE\n\n{ new display menus }\n[FET_GFX]\nGRAPHICS SETUP\n\n[FED_MIP]\nMIP MAPPING\n\n[FED_AAS]\nANTI ALIASING\n\n[FED_FIL]\nTEXTURE FILTERING\n\n[FED_BIL]\nBILINEAR\n\n[FED_TRL]\nTRILINEAR\n\n[FED_WND]\nWINDOWED\n\n[FED_FLS]\nFULLSCREEN\n\n[FEM_CSB]\nCUTSCENE BORDERS\n\n[FEM_SCF]\nSCREEN FORMAT\n\n[FEM_ISL]\nMAP MEMORY USAGE\n\n[FEM_LOW]\nLOW\n\n[FEM_MED]\nMEDIUM\n\n[FEM_HIG]\nHIGH\n\n[FEM_2PR]\nPS2 ALPHA TEST\n\n[FEC_FRC]\nFREE CAM\n\n{ Linux joy detection }\n[FEC_JOD]\nDETECT JOYSTICK\n\n[FEC_JPR]\nPress any key on the joystick of your choice that you want to use on the game, and it will be selected.\n\n[FEC_JDE]\nDetected joystick\n\n{ mission restart }\n[FET_RMS]\nREJOUER MISSION\n\n[FESZ_RM]\nREJOUER?\n\n[FED_VPL]\nVEHICLE PIPELINE\n\n[FED_PRM]\nPED RIM LIGHT\n\n[FED_RGL]\nROAD GLOSS\n\n[FED_CLF]\nCOLOUR FILTER\n\n[FED_WLM]\nWORLD LIGHTMAPS\n\n[FED_MBL]\nMOTION BLUR\n\n[FEM_SIM]\nSIMPLE\n\n[FEM_NRM]\nNORMAL\n\n[FEM_MOB]\nMOBILE\n\n[FED_MFX]\nMATFX\n\n[FED_NEO]\nNEO\n\n[FEM_PS2]\nPS2\n\n[FEM_XBX]\nXBOX\n\n[FEC_IVP]\nINVERT PAD VERTICALLY\n\n[FEM_NON]\nNONE\n\n[FEC_DS2]\nDUALSHOCK 2\n\n[FEC_DS3]\nDUALSHOCK 3\n\n[FEC_DS4]\nDUALSHOCK 4\n\n[FEC_360]\nXBOX 360 CONTROLLER\n\n[FEC_ONE]\nXBOX ONE CONTROLLER\n\n[FEC_TYP]\nGAMEPAD TYPE\n\n[FET_AGS]\nGAMEPAD SETTINGS\n\n[FEM_AUT] { aspect ratio related }\nAUTO\n\n[DUMMY]\nTHIS LABEL NEEDS TO BE HERE !!!\nAS THE LAST LABEL DOES NOT GET COMPILED"
  },
  {
    "path": "utils/gxt/german.txt",
    "content": "﻿{\n    New strings are at the bottom of file.\n    Do not change the order of strings.\n    You can fix the typos of existing translation but please refrain from\n    unnecessary edits like rephasing because you think it suits better for your taste.\n}\n\n[RAMPAGE]\nAMOKLAUF!!\n\n[RAMP_F]\nAMOKLAUF FEHLGESCHLAGEN!!\n\n[RAMP_P]\nAMOKLAUF BESTANDEN!!\n\n[RAMP_A]\nALLE AMOKLÃUFE BESTANDEN!!\n\n[PAGE_01]\nDein Job: ~1~ Gang-Mitglieder in 2 Minuten!\n\n[PAGE_02]\nZerstöre ~1~ Fahrzeuge in 2 Minuten!\n\n[PAGE_03]\nErledige ~1~ Gang-Mitglieder in 2 Minuten im Vorbeifahren!\n\n[PAGE_04]\nÜberfahre ~1~ Gang-Mitglieder in 2 Minuten!\n\n[PAGE_05]\nDein Job: ~1~ Gang-Mitglieder in 2 Minuten!\n\n[SENTXS]\nSentinel XS\n\n[MAP_LEG]\nLegende\n\n[VCNMAV]\nVCN Maverick\n\n[LG_01]\nPosition des Spielers\n\n[LG_02]\nAvery Carrington\n\n[LG_03]\nBiker-Kontaktpunkt\n\n[LG_04]\nColonel Cortez\n\n[LG_05]\nRicardo Diaz\n\n[LG_06]\nKent Paul\n\n[LG_07]\nRechtsanwalt\n\n[LG_08]\nPhil Cassidy\n\n[LG_09]\nBootswerft\n\n[LG_10]\nMalibu Club\n\n[LG_11]\nKubaner\n\n[LG_12]\nFilmstudio\n\n[LG_13]\nAmmuNation\n\n[LG_14]\nHaitianer\n\n[LG_15]\nEisenwarenladen\n\n[LG_16]\nVersteck\n\n[LG_17]\nEiscreme\n\n[LG_18]\nKaufman-Taxis\n\n[LG_19]\nLove Fist\n\n[LG_20]\nDruckerei\n\n[LG_21]\nImmobilie\n\n[LG_22]\nPay 'n' Spray\n\n[LG_23]\nBekleidungsgeschãft\n\n[LG_24]\nTommys Villa\n\n[LG_25]\nTelefon\n\n[LG_26]\nRadiosender Wildstyle\n\n[LG_27]\nRadiosender Flash FM\n\n[LG_28]\nRadiosender KChat\n\n[LG_29]\nRadiosender Fever 105\n\n[LG_30]\nRadiosender VRock\n\n[LG_31]\nPolizeifunk-Zentrale\n\n[LG_32]\nRadiosender Espantoso\n\n[LG_33]\nRadiosender Emotion 98.3\n\n[LG_34]\nRadiosender Wave 103\n\n[LG_36]\nSun Yard\n\n[LG_37]\nStripper-Bar\n\n[MAP_YAH]\nDU BIST HIER\n\n[TAXSHRT]\n~g~Du kannst dieses Kaufman-Taxi nehmen, statt selbst Auto zu fahren. Das kostet dich $9.\n\n[MOB_09D]\nVielleicht hab ich Leo ja erledigt und mir sein Handy genommen. Hast du schon mal daran gedacht, du Penner?\n\n[FE_MLG]\nKARTENLEGENDE\n\n[FED_RDR]\nRADAR-MODUS\n\n[FED_HUD]\nHUD-MODUS\n\n[FED_RDL]\nGROSS\n\n[FED_RDB]\nNUR SYMBOLE\n\n[FED_HUF]\nINFOS EIN- & AUSBLENDEN\n\n[FEST_HV]\nHöchstes Bürgerwehr-Missions-Level\n\n[BRIBE1]\nDu hast soeben Polizei-Bestechungsgeld aufgenommen, dein Fahndungslevel verringert sich damit um einen Stern.\n\n[CLOHELP]\nSaubere Klamotten!!\n\n[SUNSHIN]\nSunshine Autos\n\n[CHERRYP]\nCherry Popper Eiscreme\n\n[KAUFCAB]\nKaufman-Taxis\n\n[BOATYAR]\nDie Bootswerft\n\n[WANT_L]\nDein Fahndungslevel ist bis auf weiteres aufgehoben. Solltest du ein Verbrechen begehen, wãhrend die Sterne blinken, wird dein volles Fahndungslevel wieder aktiv.\n\n[PICK1]\nKugelsichere Weste im Ocean View Hotel angeliefert!\n\n[HOTRNG]\nHOTRING\n\n[BLODRNG]\nCHAOS-DERBY\n\n[DIRTRNG]\nDIRTRING\n\n[FEC_ABR]\nBeschleunigen, Bremsen oder Zurücksetzen\n\n[FEI_BTU]\n; = -\n\n[FEI_SCR]\nScrollen\n\n[SKUMBUY]\nSkumole Shack gekauft: $ ~1~\n\n[SKUM_L]\nDrücke die ~h~L1-Taste~w~, um Skumole Shack zu kaufen. Preis: $~1~\n\n[SKUM_T]\nDrücke die ~t~\"-Taste~w~, um Skumole Shack zu kaufen. Preis: $~1~\n\n[SKUM_C]\nDrücke die ~o~|-Taste~w~, um Skumole Shack zu kaufen. Preis: $~1~\n\n[LG_35]\nZiel\n\n[IN_VEH]\n~g~Hey! Zurück ins Auto!!\n\n[HEY]\n~g~Keine Alleingãnge. Halt die Gang beisammen!\n\n[HELP3]\nDu kannst nur kurze Zeit sprinten, ohne müde zu werden.\n\n[HELP4_D]\nDrücke den~h~ rechten Analog-Stick nach oben, um zu ~h~beschleunigen.\n\n[HELP5_D]\nZieh den ~h~rechten Analog-Stick~w~ zurück, um zu ~h~bremsen~w~, oder um ~h~zurückzusetzen~w~, wenn das Fahrzeug steht.\n\n[HELP7_A]\nHalte die~h~ ~k~~PED_LOCK_TARGET~ ~w~gedrückt, um mit dem Prãzisionsgewehr zu zielen.\n\n[HELP7_D]\nHalte die~h~ ~k~~PED_LOCK_TARGET~ ~w~gedrückt, um mit dem Prãzisionsgewehr zu zielen.\n\n[HELP10]\nDieser Stern zeigt an, dass du von der Polizei gesucht wirst.\n\n[HELP11]\nJe mehr Sterne, desto dringender wirst du gesucht.\n\n[HELP13]\nManchmal musst du vielleicht Wege finden, die das Radar nicht zeigt.\n\n[TIMER]\nDiese Mission hat ein Zeitlimit. Du musst sie beendet haben, bevor die Zeit um ist.\n\n[HORN]\n~g~Drück auf die Hupe.\n\n[NOMONEY]\n~g~Du brauchst mehr Cash!\n\n[REWARD]\nBELOHNUNG $~1~\n\n[M_FAIL]\nMISSION FEHLGESCHLAGEN!\n\n[M_PASS]\nMISSION ERFÜLLT! $~1~\n\n[DEAD]\nAUSSER GEFECHT!\n\n[BUSTED]\nVERHAFTET!\n\n[WEATHE1]\nWETTER AUF SONNIG UMSTELLEN\n\n[WEATHE2]\nWETTER AUF SEHR SONNIG UMSTELLEN\n\n[WEATHE3]\nWETTER AUF BEWÖLKT UMSTELLEN\n\n[WEATHE4]\nWETTER AUF REGNERISCH UMSTELLEN\n\n[WEATHE5]\nWETTER AUF NEBLIG UMSTELLEN\n\n[WEATHE6]\nWETTER NORMAL\n\n[NUMBER]\n~1~\n\n[LOADCAR]\nLADE FAHRZEUG... (ABBRECHEN MIT L1)\n\n[CARSOFF]\nDeaktivierte Fahrzeuge.\n\n[CARS_ON]\nAktivierte Fahrzeuge.\n\n[TEXTXYZ]\nSchreibe Koordinaten in Datei...\n\n[CHEATON]\nCheat Modus AN\n\n[CHEATOF]\nCheat Modus AUS\n\n[IMPORT1]\nGeh nach draußen und warte auf dein Fahrzeug.\n\n[PAGEB11]\nFlammenwerfer in Versteck angeliefert.\n\n[WANT_A]\nVerhaftet wirst du nur, wenn die Polizei nach dir ~h~fahndet.\n\n[WANT_B]\nDein ~h~Fahndungslevel~w~ wird durch die Reihe von Sternen oben rechts auf dem Bildschirm dargestellt.\n\n[WANT_C]\nDu hast jetzt einen ~h~Fahndungslevel~w~ von eins...\n\n[WANT_D]\nzwei...\n\n[WANT_E]\ndrei...\n\n[WANT_F]\nSteigt dein ~h~Fahndungslevel~w~, wirst du von besser ausgebildeten Polizisten gejagt.\n\n[WANT_G]\nWirst du ~h~verhaftet~w~, wirst du zum nãchsten Polizeirevier gebracht.\n\n[WANT_H]\nDie Cops werden dir alle Waffen abnehmen und kassieren ein wenig Bestechungsgeld von dir.\n\n[WANT_I]\nWenn dir das auf einer Mission passiert, ist die Mission fehlgeschlagen.\n\n[WANT_J]\nIm Verlauf des Spiels wirst du Möglichkeiten entdecken, deinen Fahndungslevel zu reduzieren.\n\n[WANT_K]\nWenn du in einem Wagen sitzt, werden ~h~LACKIEREREIEN~w~ den Fahndungslevel ~h~annullieren.\n\n[HEAL_B]\nWenn du ~h~'außer Gefecht'~w~ bist, wirst du zur nãchsten Klinik gebracht.\n\n[HEAL_C]\nDu verlierst alle Waffen, und die Ãrzte knöpfen dir ein wenig Cash für die Behandlung ab.\n\n[HEAL_E]\nJe lãnger du spielst, desto mehr Wege wirst du finden, dich selbst zu verarzten oder zu schützen.\n\n[SAVE1]\nStell dich in die Markierung. So kannst du dein ~h~Spiel speichern~w~. Wãhrend einer Mission kannst du nicht speichern.\n\n[SAVE2]\nJedes Fahrzeug, das in dieser Garage abgestellt wird, wird für dich aufbewahrt, wenn das Spiel gespeichert wird.\n\n[AMMU]\nBetritt den Ammu-Nation, um eine Waffe zu kaufen.\n\n[R_TIME]\nZEIT:\n\n[PROP_1]\nDu hast nicht genug Cash für dieses Objekt.\n\n[PROP_2]\nWãhrend einer Mission kannst du keine Objekte kaufen.\n\n[IND_ZON]\nVice City Beach\n\n[COM_ZON]\nVice City Mainland\n\n[BEACH1]\nOcean Beach\n\n[BEACH2]\nWashington Beach\n\n[BEACH3]\nVice Point\n\n[GOLFC]\nLeaf Links Golfclub\n\n[STARI]\nStarfish Island\n\n[DOCKS]\nViceport\n\n[HAVANA]\nLittle Havana\n\n[HAITI]\nLittle Haiti\n\n[PORNI]\nPrawn Island\n\n[DTOWN]\nDowntown\n\n[VICE_C]\nVice City\n\n[A_PORT]\nEscobar Inter. Airport\n\n[JUNKY]\nSchrottplatz\n\n[PISTOL]\nPistole\n\n[PYTHON]\n.357\n\n[UZI]\nUz-1\n\n[TEC9]\nTec 9\n\n[M4]\nM4\n\n[INGRAM]\nMac\n\n[MP5]\nMP\n\n[RUGER]\nKruger\n\n[SNIPE]\nPrãzisionsgewehr\n\n[GRENADE]\nGranaten\n\n[SHOTGN1]\nSchrotflinte\n\n[SHOTGN2]\nS.P.A.S. 12\n\n[SHOTGN3]\nAbgesãgte Schrotflinte\n\n[ARMOUR]\nKugelsichere Weste\n\n[LASER]\n.308 Prãzisionsgewehr\n\n[BASEBAT]\nBaseballschlãger\n\n[HAMMER]\nHammer\n\n[SCREWD]\nSchraubenzieher\n\n[CLEVER]\nFleischerbeil\n\n[MACHETE]\nMachete\n\n[KNIFE]\nMesser\n\n[KATANA]\nKatana\n\n[CHAINSA]\nKettensãge\n\n[G_COST]\n$~1~\n\n[CAR_1]\nKrankenwagen\n\n[MALIBU]\nMalibu Club\n\n[MANSION]\nDiaz' Haus\n\n[TMANS]\nVercetti Estate\n\n[STRIP]\nPole Position Club\n\n[MALL1]\nNorth Point Einkaufszentrum\n\n[BANKINT]\nEl Banco Corrupto Grande\n\n[RANGE]\nSchießstand\n\n[POL_HQ]\nVice City Polizeihauptquartier\n\n[INT_B]\nEin alter Freund\n\n[INTB_1]\n~g~Begib dich in die Anwaltskanzlei.\n\n[LAW_1]\nDie Party\n\n[LAW_2]\nDunkle Gassen\n\n[LAW_3]\nDie Geschworenen\n\n[LAW_4]\nAufruhr\n\n[COL_1]\nDer Verrãter\n\n[COL_2]\nKugelhagel im Einkaufszentrum\n\n[COL_3]\nDie Schutzengel\n\n[COL_4]\nZu Befehl, Sir!\n\n[COL_5]\nAlle Mann an Deck!\n\n[COK_1]\nDie Jagd\n\n[COK_2]\nPhnom Penh '86\n\n[COK_3]\nDas schnellste Boot\n\n[COK_4]\nAngebot & Nachfrage\n\n[KENT_1]\nDie Befreiungsaktion\n\n[ASS_1]\nPizza Mortale\n\n[BUD_1]\nFette Beute\n\n[BUD_2]\nZoff in der Bar\n\n[BUD_3]\nCop-Land\n\n[CAP_1]\nDer Eintreiber\n\n[FIN_1]\nFreunde und andere Feinde\n\n[BANK_1]\nKein Entkommen?\n\n[BANK_2]\nDer Scharfschütze\n\n[BANK_3]\nDer Fahrer\n\n[BANK_4]\nDer Coup\n\n[CNT_1]\nDer Singvogel\n\n[CNT_2]\nDer Kurier\n\n[PORN_1]\nAlle meine Pferdchen\n\n[PORN_2]\nDer Dildo-Jet\n\n[PORN_3]\nEin Mann namens Martha\n\n[PORN_4]\nHeiße Lightshow\n\n[TAX_1]\nKaufman-Taxis\n\n[TAXI_1]\nV.I.P\n\n[TAXI_2]\nKonkurrentenjagd\n\n[TAXI_3]\nDas Taxi-Inferno\n\n[ICE_1]\nEiscreme und andere Leckereien\n\n[TEX_1]\nSchlagende Argumente\n\n[TEX_2]\nDas Begrãbnis\n\n[TEX_3]\nSchutt und Asche\n\n[PHIL_1]\nDer Waffenschieber\n\n[PHIL_2]\nTNT-Whiskey\n\n[BIKE_1]\nWheels of Steel\n\n[BIKE_2]\nChaos-City\n\n[BIKE_3]\nBig Bakers Bike\n\n[ROCK_1]\nLove Juice\n\n[ROCK_2]\nDer Psychokiller\n\n[ROCK_3]\nDie PR-Tour\n\n[ROCK_4]\nLove Fist!\n\n[HAT_1]\nMysteriöses Pulver\n\n[HAT_2]\nFliegende Bomben\n\n[HAT_3]\nSchmutzige Methoden\n\n[CUB_1]\nStunt-Boot-Action\n\n[CUB_2]\nKanonenfutter\n\n[CUB_3]\nDie Seeschlacht\n\n[CUB_4]\nTrojanisches Voodoo\n\n[JOB_1]\nDer Pizza-Lieferant\n\n[JOB_2]\nEin bedauerlicher Unfall\n\n[JOB_3]\nDie rasende Schrottfabrik\n\n[JOB_4]\nTrouble am Check-In\n\n[JOB_5]\nGefeuert!\n\n[ANSWER]\nDrücke die ~h~~k~~PED_ANSWER_PHONE~~w~, um den Anruf auf deinem Handy entgegenzunehmen.\n\n[MOB_01A]\nHey, mein Alter! Paul hier. Ich hãtte da vielleicht was für dich, aber das müssen wir unter vier Augen besprechen.\n\n[MOB_01B]\nIch bin im Malibu und lass es mir gutgehen.\n\n[MOB_01C]\nIch denke, ich hab einen gut bei dir, wenn du das hörst, Kumpel. Bis gleich.\n\n[MOB_02A]\nHey! Hallo, Tommy? Tommy!\n\n[MOB_02B]\nIn der Druckerei ist irgendwas im Busch. Fahr mal rüber und kümmere dich darum.\n\n[MOB_02C]\nEs scheint ziemlichen Ãrger zu geben. Ich muss Schluss machen.\n\n[MOB_03A]\nMr. Vercetti? Ich habe hier einen unterschriebenen Wisch,\n\n[MOB_03B]\nder besagt, dass Sie alle Schulden von 'BJ's Autos' übernehmen.\n\n[MOB_03C]\nNach BJ's plötzlichem Verschwinden hab ich keine andere Wahl,\n\n[MOB_03D]\nals Sie für seine Verbindlichkeiten zur Rechenschaft zu ziehen.\n\n[MOB_03E]\nBis Sie die volle Summe beglichen haben,\n\n[MOB_03F]\nsollte Ihnen klar sein, dass Vice City ein heißes Pflaster für Sie ist.\n\n[MOB_04A]\nWie geht's, mein Alter?\n\n[MOB_04B]\nIch hab vergessen, dir zu sagen, dass wir für das Konzert noch ein paar Ordner brauchen.\n\n[MOB_04C]\nDa gibt's so 'ne Biker-Gang, die wãr super für die Publicity.\n\n[MOB_04D]\nWenn du mir das arrangierst, besorg ich dir 'n VIP-Pass für den Abend. Ok?\n\n[MOB_05A]\nGut gemacht, Tommy. Schön, den Ofen wiederzuhaben.\n\n[MOB_05B]\nSag Mr. Kent Paul, dass er seine Ordner für das Konzert kriegt.\n\n[MOB_05C]\nDu hast mein Wort darauf.\n\n[MOB_05D]\nHalt die Ohren steif.\n\n[MOB_06A]\nTommy, man hört so allerlei über dich, mein Junge.\n\n[MOB_06B]\nWenn du willst, kocht Tante Poulet dir ein leckeres Süppchen, dann kannst du mal abschalten, hm?\n\n[MOB_06C]\nKomm doch die Tage mal bei mir vorbei, ok, Tommy?\n\n[MOB_08A]\nTommy, ich dachte mir, du könntest meinen Rat als Geschãftsmann brauchen.\n\n[MOB_08B]\nWenn du ein Unternehmen am Laufen hast, musst du einmal pro Woche die Einnahmen kassieren gehen.\n\n[MOB_08C]\nSonst werden deine Leute übermütig und versuchen, in die eigene Tasche zu wirtschaften. Ok?\n\n[MOB_08D]\nHey, ich weiß selbst, wie man so was macht, Ken, ok?\n\n[MOB_08E]\nOk, ok. Ich weiß ja, dass du Bescheid weißt.\n\n[MOB_08F]\nIch meinte ja nur, damit du weißt, dass ich im Zweifelsfall auch Bescheid weiß.\n\n[MOB_08G]\nNur für alle Fãlle, mein Alter!\n\n[MOB_08H]\nWenn du meinst, Ken...\n\n[MOB_09A]\nHey, Leo! Ich hab Arbeit für dich!\n\n[MOB_09B]\nHier ist nicht Leo.\n\n[MOB_09C]\nHey, wenn Leo erfãhrt, dass du mit seinem Handy telefonierst, bist du fãllig.\n\n[MOB_09E]\nDu hast Leo erledigt? Du musst Mumm haben - willst du für mich arbeiten?\n\n[MOB_09F]\nKomm ins Café von meinem Vater in Little Havana, dann können wir reden.\n\n[MOB_10A]\nTommy! Du musst mir einen Gefallen tun.\n\n[MOB_10B]\nSteve! Was machen die Dreharbeiten?\n\n[MOB_10C]\nGut. Ich- ãh, WIR brauchen noch eine Autoverfolgungsjagd, aber unser Budget ist knapp.\n\n[MOB_10D]\nIch hab in der Stadt verteilt ein paar Karren stehen. Du weißt, was zu tun ist.\n\n[MOB_10E]\nOk, Steve, ich halt die Augen offen. Bis dann.\n\n[MOB_11A]\nHallo, Söhnchen. Ich wollte dir kurz 'nen kleinen Tipp geben.\n\n[MOB_11B]\nHi, Avery. Worum geht's denn?\n\n[MOB_11C]\nMan kann in dieser Stadt viel Geld machen, wenn man die richtigen Immobilien hat. Klingelt's?\n\n[MOB_11D]\nIch denke schon.\n\n[MOB_11E]\nAlso, halt die Augen offen, dann könnte sich dir die ideale Gelegenheit bieten. Bis bald.\n\n[MOB_11F]\nCiao, Avery.\n\n[MOB12_A]\nHey, Tommy. Avery hier. Hör mal, ich hab gerade alle Hãnde voll zu tun,\n\n[MOB12_B]\nund ein Bevollmãchtigter von mir müsste zu den Gator Keys eskortiert werden.\n\n[MOB12_C]\nIch will da ein Stück Land kaufen und schick ihn hin, um den Deal abzuschließen.\n\n[MOB12_D]\nKönntest du dafür sorgen, dass er gut dort ankommt?\n\n[MOB12_E]\nMach ich doch glatt, Avery. Wo soll ich ihn abholen?\n\n[MOB12_F]\nEr hat gerade noch an der Baustelle zu tun. Hol ihn doch am besten dort ab.\n\n[MOB12_G]\nKein Problem. Bis dann, Avery.\n\n[MOB13_A]\nVercetti? VERCETTI!! Verdammt, Mann, Sie müssen mir helfen!\n\n[MOB13_B]\nMr. Moffat? Wie geht's der Familie?\n\n[MOB13_C]\nZur Hölle mit Ihnen, hören Sie!\n\n[MOB13_D]\nTja, war nett, mit Ihnen zu plaudern...\n\n[MOB13_E]\nWARTEN SIE! Vercetti - Tommy, kann ich Tommy zu Ihnen sagen?\n\n[MOB13_F]\nWir sind beide Geschãftsleute. Sie erkennen doch ein gutes Geschãft sofort, oder?\n\n[MOB13_G]\nIch hab keine Zeit für Palaver. Kommen Sie zum Punkt.\n\n[MOB13_H]\nGELD. Geld ist der Punkt, verdammt!\n\n[MOB13_I]\nIch bin den Kerlen nochmal entwischt, aber sie sitzen mir im Nacken. Die machen sich einen Spaß daraus!\n\n[MOB13_J]\nIch bin in einer Telefonzelle, irgendwo in diesem verdammten Loch.\n\n[MOB13_K]\nHolen Sie mich hier raus, bevor sie mich schnappen und-... oh Gott...\n\n[MOB13_L]\nIch bin leider ausgebucht bis-...\n\n[MOB13_M]\nNein! Verarschen Sie mich nicht, haben Sie Erbarmen! Kein Mensch hat das verdient!\n\n[MOB13_N]\nIch flehe Sie an, Tommy, auf den Knien flehe ich Sie an! Bitte...\n\n[MOB13_O]\nNaja, ich könnte 'nen kurzen Abstecher machen. Vielleicht finde ich Sie...\n\n[MOB13_P]\nOh Gott, sie kommen! Um Himmels Willen, beeilen Sie sich!\n\n[MOB_14A]\nHey, Tommy, hör zu, das wird dir gefallen.\n\n[MOB_14B]\nEin Vögelchen hat mir gesteckt, dass das Vice City-Spezialkommando in einem renommierten Finanzinstitut ein Schließfach hat.\n\n[MOB_14C]\nDa sind die Schmiergelder drin, die sie über die Jahre kassiert haben.\n\n[MOB_14D]\nSo 'ne Art Altersversorgung für die ganze Mannschaft.\n\n[MOB_14E]\nSollte dir diese Info je helfen, dir was von dem Kuchen anzueignen,\n\n[MOB_14F]\nwürdest du dich sicher verpflichtet fühlen, mir 'n Stück davon abzugeben?\n\n[MOB_14G]\nIch werd dich nicht vergessen. Danke, Kent.\n\n[MOB_14H]\n'Paul'heiße ich, Scherzkeks. Ich KOMME aus Kent, Nãhe London.\n\n[MOB_14I]\nMein geographisches Wissen über England ist eben nicht mehr, was es war.\n\n[MOB15_A]\nTommy, Alter. Hier ist Paul aus Kent.\n\n[MOB15_B]\nUnten im Malibu, da sind ein paar Keulen, die haben ein Auge auf dich geworfen.\n\n[MOB15_C]\nIch verstehe nur Bahnhof.\n\n[MOB15_D]\nHasen. Miezen. Na, Puppen, eben. Coole Babes, keine Professionellen, oder so.\n\n[MOB15_E]\nDu solltest mal kommen und sie dir ansehen.\n\n[MOB16_A]\nTommy, hier Paul. Wie geht's, mein Freund?\n\n[MOB16_B]\nWas willst du, Paul? Ich brauch keine getürkten Designer-Klamotten.\n\n[MOB16_C]\nSehr witzig. Du weißt, dass ich mit getürkter Ware nichts am Hut habe.\n\n[MOB16_D]\nWollte nur hören, ob ich nicht 'ne Rolle in einem von deinen Filmen kriegen könnte.\n\n[MOB16_E]\nIn England habe ich viel einschlãgiges Zeug gedreht.\n\n[MOB16_F]\nIch hab mehr zu bieten als du, mein Alter.\n\n[MOB16_G]\nPaul, danke für das Angebot. Ich komm auf dich zurück.\n\n[MOB16_H]\nLass mich nicht hãngen. Denk dran, was ich alles für dich getan habe.\n\n[MOB16_I]\nDas versuch ich ja grade zu vergessen.\n\n[MOB17_A]\nTommy Vercetti. Wie geht's, großer Meister?\n\n[MOB17_B]\nMan hört so einiges über dich. Bist jetzt 'ne große Nummer in der Stadt, hã?\n\n[MOB17_C]\nPaul, du bist betrunken.\n\n[MOB17_D]\nNein, du Trottel, ich bin nicht betrunken.\n\n[MOB17_E]\nHab mir nur ein paar Ladungen Stoff gegeben, war seit ein paar Tagen nicht im Bett.\n\n[MOB17_F]\nUnd du brauchst mich nicht dumm anzureden.\n\n[MOB17_G]\nIch bin nicht irgendwer. Wer hat dir denn in dieser Stadt den Weg geebnet? Ich!\n\n[MOB17_H]\nTatsãchlich?\n\n[MOB17_I]\nTatsãchlich!\n\n[MOB17_J]\nPaul, reg dich ab. Ich hatte viel zu tun. Sei kein Idiot.\n\n[MOB17_K]\nIch bin kein Idiot. Das haben sie schon im Jugendknast gesagt.\n\n[MOB17_L]\nWenn du Ãrger haben willst, Freundchen, den kannst du haben!\n\n[MOB17_M]\nTommy, bitte! Du warst meine große Hoffnung. Bitte, mach dich nicht lustig über mich!\n\n[MOB17_N]\nPaul, schlaf mal 'ne Runde. Im Ernst.\n\n[MOB18_A]\nTommy, hier Paul. Wie geht's, Alter? Hey, ich dachte mir, das musst du hören...\n\n[MOB18_B]\nEcht der Hammer. Du glaubst nicht, was mir für 'ne Puppe über den Weg gelaufen ist.\n\n[MOB18_C]\n'ne Bordsteinschwalbe, oder sowas. Unten in Little Havana.\n\n[MOB18_D]\nSagt, sie heißt Mercedes oder so ãhnlich. Wahnsinn, Alter. Die Puppe musst du dir geben.\n\n[MOB18_E]\nDa würde 'nen Toter Hormonkoller kriegen. Sie sagt, ich wãr der beste, den sie je hatte.\n\n[MOB18_F]\nHalt die Augen nach ihr offen. Bis dann.\n\n[MOB19_A]\nTommy, hier KP - Kent Paul. Ich hab lãuten hören, dass jemand dich leimen will.\n\n[MOB19_B]\nAlso, sei wachsam, mein Freund. Und kein Sterbenswörtchen, dass du das von mir weißt.\n\n[MOB_20A]\nHallo, Tommy. Hier Paul. Ich höre, dass du ein paar Leuten auf den Schlips getreten bist.\n\n[MOB_20B]\nIrgendjemand sieht es anscheinend nicht gern, dass du auf einmal den großen Zampano spielst.\n\n[MOB_20C]\nAlso, sag nicht, ich hãtte dich nicht gewarnt. Es rãcht sich, wenn man's übertreibt.\n\n[MOB_20D]\nJedenfalls ist angeblich ein Kopfgeld auf dich ausgesetzt und es ist schon jemand hinter dir her.\n\n[MOB_20E]\nAlso pass auf dich auf. Und vergiss mich nicht ganz.\n\n[MOB71_A]\nTommy, Thomas, hier Cortez. Wie geht's?\n\n[MOB71_B]\nEs bleibt spannend. Und selbst?\n\n[MOB71_C]\nEin ewiger Kampf, Tommy. Entschuldigen Sie die schlechte Verbindung, wir hatten wieder einen Putschversuch.\n\n[MOB71_D]\nEs gibt keine anspruchsvollere Geliebte als das Volk.\n\n[MOB71_E]\nSeit ich aus Vice City zurück bin, gab's drei Revolutionen und vier Staatsstreiche.\n\n[MOB71_F]\nZum Glück bin ich jedesmal befördert worden.\n\n[MOB71_G]\nIch wollte Sie wegen Mercedes etwas fragen.\n\n[MOB71_H]\nOK. Was ist mit ihr?\n\n[MOB71_I]\nIch hör Geschichten über sie und weiß nicht, was ich davon halten soll.\n\n[MOB71_J]\nVielleicht wollen mich alle demütigen.\n\n[MOB71_K]\nVielleicht wird sie übermütig, seit ich weg musste, sagen Sie mir nur eins, Tommy. Ist das wahr?.\n\n[MOB71_L]\nsagen Sie mir nur eins, Tommy. Ist das wahr?\n\n[MOB71_M]\nIst was wahr?\n\n[MOB71_N]\nDie Geschichten, die ich höre? Will sie wirklich Anwãltin werden?\n\n[MOB71_O]\nWelche Schande, Tommy. Wir Cortez sind eine stolze Familie und würden nie einer Tochter erlauben, Anwãltin zu werden.\n\n[MOB71_P]\nSagen Sie mir, dass es nicht wahr ist. Das ertrage ich nicht.\n\n[MOB71_Q]\nColonel, ich versichere Ihnen, dass Mercedes niemals Anwãltin wird. Keine Angst.\n\n[MOB71_R]\nDanke, Tommy - das wãre zu viel der Schande. Sie ist eine Dame, keine Schmarotzerin.\n\n[MOB71_S]\nIch weiß, Colonel\n\n[MOB71_T]\nTommy, Sie müssen jetzt entschuldigen, gerade kommt der neue Innenminister.\n\n[MOB71_U]\nIch hab seinen Vater vor Jahren bei einem Putschversuch erledigt. Ich muss mich gut mit ihm stellen. Wiederhören.\n\n[MOB22_A]\nTommy, Sie erweisen sich als sehr nützlich, mein Freund.\n\n[MOB22_B]\nDanke, Cortez. Was ist mit meinem Deal?\n\n[MOB22_C]\nTommy, ich mühe mich ohne Unterlass, um diesem Sumpf von elenden Lügen und Intrigen auf den Grund zu gehen.\n\n[MOB22_D]\nSie haben mein Wort darauf. Einstweilen möchte ich\n\n[MOB22_E]\nIhnen den Dank meines Volkes aussprechen, für das Sie so viel getan haben.\n\n[MOB_25A]\nTommy, hier Cortez. Die Franzosen machen mir Ãrger. Und wie.\n\n[MOB_25B]\nVerdammte Heuchler! Jahrhundertelang beuten sie arme Lãnder aus und mich schimpfen sie einen Dieb!\n\n[MOB_25C]\nIch brauche dingend Ihre Hilfe.\n\n[MOB_25D]\nBeeilen Sie sich. Ich brauche Sie. Ich hasse die Franzosen.\n\n[MOB_26A]\nHallo, Tommy?\n\n[MOB_26B]\nJa?\n\n[MOB_26C]\nBaker hier. Wollte dir nur sagen, der Gig hat Spaß gemacht.\n\n[MOB_26D]\nDanke, auch im Namen der Gang. Eins sollst du wissen:\n\n[MOB_26E]\nDu hast unsern Respekt. Halt die Nase im Wind, Junge.\n\n[MOB_29A]\nHallo? Spreche ich mit Mr. Tommy Vercetti?\n\n[MOB_29B]\nJa.\n\n[MOB_29C]\nIch hab mir sagen lassen, du wãrst der richtige Mann, wenn man Kroppzeug am Hals hat.\n\n[MOB_29D]\nVielleicht...\n\n[MOB_29E]\nTja, ich hab 'ne regelrechte Plage am Hals. Haitianer, überall.\n\n[MOB_29F]\nMein Name ist Umberto Robina und es wãr mir recht, wenn du baldmöglichst ins Café Robina kãmst.\n\n[MOB_29G]\nDiesmal haben's die Haitianer nãmlich zu weit getrieben.\n\n[MOB_29H]\nTest\n\n[MOB_30A]\nTommy, hier Umberto Robina.\n\n[MOB_30B]\nWie lãuft das Café?\n\n[MOB_30C]\nOh, bestens. Sagenhaft, Tommy, sagenhaft. Keine Memmen, Tommy, nur echte Mãnner. Und wunderschöne Frauen!\n\n[MOB_30D]\nIch wollte nur sagen, für mich und Paps bist du jetzt einer von uns. Ein Kubaner.\n\n[MOB_30E]\nDu bist ein ganzer Kerl. Du hast Mumm in den Knochen.\n\n[MOB_30F]\nDanke, Umberto. Seit ich aus dem Knast raus bin, hat das keiner zu mir gesagt. Bis dann.\n\n[MOB_33A]\nTommy, Phil hier. Spar dir die sentimentalen Worte, hör mir einfach zu, ok?\n\n[MOB_33B]\nAlso, ich brau hier 'nen extra starken TNT-Whiskey und ich wollte fragen, ob du mal 'nen Schluck probieren willst.\n\n[MOB_33C]\nIm Ernst, Tommy, wenn du 'nen Drink willst, oder 'ne Wand abbeizen musst - das Zeug macht einen Mann aus dir.\n\n[MOB_33D]\nBei mir hat's jedenfalls gewirkt, auch wenn ich jetzt auf einem Auge nichts mehr sehe. Ich warte auf dich.\n\n[MOB_34A]\nTommy, war ein Vergnügen, mit dir zu arbeiten. So einen Spaß hatte ich seit Vietnam nicht mehr.\n\n[MOB_34B]\nAlso, falls du je irgendwas brauchst, ruf mich an, ok?\n\n[MOB_34C]\nIch vergesse keinen, mit dem ich in der Schlacht war.\n\n[MOB_34D]\nUnd ich kann dir bestimmt irgendwann helfen, ok?\n\n[MOB_35A]\nTommy, die Wunde verheilt gut. Ist nur komisch:\n\n[MOB_35B]\nda hab ich auf 6 Schlachtfeldern gekãmpft und nie 'n Kratzer abgekriegt und dann das!\n\n[MOB_35C]\nJetzt bin ich der einarmige Phil. Hab aber 'n gutes Arsenal an Handfeuerwaffen, also bin ich auch mit Arm ab nicht arm dran.\n\n[MOB_35D]\nAlso hör auf mit der sentimentalen Scheiße und hol dir 'nen Drink, ok!\n\n[MOB_36A]\nTommy, hier Phil. Wollte mich bedanken, dass du mich da rausgehauen hast.\n\n[MOB_36B]\nVerdammte Vietnamesen. Wo du hinschaust ein Hinterhalt.\n\n[MOB_36C]\nDie Wunde heilt gut. Und jetzt kassiere ich meine Versehrtenrente endlich völlig zurecht. Danke, Kumpel.\n\n[MOB_40A]\nHey, Tommy, hier Sonny. Was macht die Sonnenbrãune?\n\n[MOB_40B]\nIch hab keine Sonnenbrãune.\n\n[MOB_40C]\nNaja, mein Geld hast du jedenfalls auch nicht. Daher frag ich mich,\n\n[MOB_40D]\nwas treibst du eigentlich die ganze Zeit, Tommy? Sag doch mal?\n\n[MOB_40E]\nIch bin auf der Suche nach deinem Geld, Sonny. Keine Sorge.\n\n[MOB_40F]\nIch mach mir aber Sorgen, Tommy, ich kann nicht anders.\n\n[MOB_40G]\nIch hab nãmlich anscheinend mit zu viel unzuverlãssigen Menschen zu tun.\n\n[MOB_40H]\nSei du bitte kein unzuverlãssiger Mensch, Tommy.\n\n[MOB_40I]\nTu dir und mir einen Gefallen. Ich freu mich, von dir zu hören.\n\n[MOB_41A]\nTommy, kennst du mich noch?\n\n[MOB_41B]\nHey, Sonny.\n\n[MOB_41C]\nJa genau, Sonny. Wir sind doch alte Freunde,\n\n[MOB_41D]\naber du schreibst nie, rufst nie an. Willst du denn nicht mehr mein Freund sein?\n\n[MOB_41E]\nIch hab alle Hãnde voll zu tun, die Sache zu regeln. Und du bist auch keine große Hilfe.\n\n[MOB_41F]\nAch, ich bin also schuld? Ja, ich hab gehört, dass du zu tun hast...\n\n[MOB_41G]\nMusst Drogenbarone erledigen, ihre Geschãfte übernehmen.\n\n[MOB_41H]\nVergiss mich nicht, Tommy. Ich verspreche dir nãmlich, dass ich dich nicht vergesse...\n\n[MOB_42A]\nTommy.\n\n[MOB_42B]\nSonny.\n\n[MOB_42C]\nAnscheinend hörst du neuerdings schlecht, deshalb frag ich dich jetzt nochmal:\n\n[MOB_42D]\nTommy, wo ist die verdammte Kohle? Wo ist der verdammte Stoff und wo ist mein Anteil an deinem neuen Geschãft?\n\n[MOB_42E]\nDu hãltst mich zum Narren, Tommy, ich find's bloß nicht zum Lachen.\n\n[MOB_43A]\nTommy, Tommy, Tommy, Sonny hat gerade angerufen, dãmmert dir was?\n\n[MOB_43B]\nIch weiß nicht, wie das mit dir ist, aber wenn mir jemand droht, dass er meine Familie umbringt,\n\n[MOB_43C]\ndann macht mir das eine Scheißangst. Was gedenkst du zu unternehmen?\n\n[MOB_43D]\nNur die Ruhe, Ken, alles wird cool.\n\n[MOB_43E]\nIch BIN ruhig. So ruhig wie man sein kann, wenn man um sein Leben fürchtet!\n\n[MOB_43F]\nKen, ich muss mich gerade auf was anderes konzentrieren.\n\n[MOB_43G]\nWir kümmern uns zu gegebener Zeit um Forelli.\n\n[MOB_43H]\nIch bin ruhig. Hör ich mich nicht ruhig an? Muss die Todesangst sein, die auf die Stimme schlãgt.\n\n[MOB45_A]\nTommy, wir müssen miteinander reden.\n\n[MOB45_B]\nWo liegt das Problem, Lance?\n\n[MOB45_C]\nBei dir, mein Freund: Ich finde, du gibst mir keinen fairen Anteil.\n\n[MOB45_D]\nNoch dazu hast du mich vor den Jungs blamiert. Das kann ich nicht auf mir sitzen lassen.\n\n[MOB45_E]\nLance, das siehst du falsch. Du hast Fehler gemacht.\n\n[MOB45_F]\nTommy, ich bin nicht dein Laufbursche. Nicht dein Lakai.\n\n[MOB45_G]\nLance, alles ist ok, solange du keinen Mist baust. Und sollte ICH Mist bauen, steh ich dafür gerade.\n\n[MOB45_H]\nTommy, ich hab alles für dich getan und du trittst mich mit Füßen. Mach das doch nicht.\n\n[MOB45_I]\nLance, ich betrüg dich nicht und falle dir nicht in den Rücken, ok?\n\n[MOB45_J]\nReiß dich zusammen. Es ist schwer genug, ohne dass du mir die Ohren vollheulst.\n\n[MOB45_K]\nVertrau mir, hörst du. Hörst du?\n\n[MOB45_L]\nJa, Tommy, aber ich halt das nicht mehr lange aus.\n\n[MOB45_M]\nLance, komm mir bloß nicht so, ich warne dich.\n\n[MOB45_N]\nReg dich ab, mach ein paar Tage frei, dann unterhalten wir uns, ok?\n\n[MOB46_A]\nTommy - Lance.\n\n[MOB46_B]\nJa?\n\n[MOB46_C]\nKein 'Schön, dass du anrufst, Lance!' Kein freundliches Wort? Was soll das?\n\n[MOB46_D]\nIch habe gerade zu tun, Lance. Was willst du?\n\n[MOB46_E]\nNichts. Ich wollte dir nur sagen, wir kriegen das hin.\n\n[MOB46_F]\nDu und ich, ohne Probleme. Du verstehst mich?\n\n[MOB46_G]\nWir müssen es hinkriegen. Sonst sind wir erledigt, Lance.\n\n[MOB46_H]\nWir stecken schon viel zu tief drin. Aber danke für den Anruf. Du hörst von mir.\n\n[MOB_47A]\nTommy - Lance. Wir stecken in der Patsche. Du musst sofort kommen.\n\n[MOB52_A]\nHey, Leo, ich glaube, wir haben einen Kãufer für Diaz' Ware.\n\n[MOB52_B]\nDu musst ihn anrufen und den Deal in die Wege leiten, ok?\n\n[MOB52_C]\nWo bist du gerade?\n\n[MOB52_D]\nIst irgendwas, Leo? Du hörst dich so komisch an.\n\n[MOB52_E]\nSag mir, wo du bist.\n\n[MOB52_F]\nVerdammt, wer ist da dran? Gib mir Leo!\n\n[MOB52_G]\nLeo ist 'ne Weile verreist, ich vertrete ihn.\n\n[MOB52_H]\nZum Teufel mit dir!\n\n[MOB54_A]\nHi, Tommy!\n\n[MOB54_B]\nHi, Mercedes. Wie geht's?\n\n[MOB54_C]\nIch hab 'ne neue Wohnung in Vice Point.\n\n[MOB54_D]\nVielleicht kommst du mich ja mal besuchen.\n\n[MOB54_E]\nKlar, gern. Also, bis spãter.\n\n[MOB55_A]\nTommy, ich bin's.\n\n[MOB55_B]\nHi, Mercedes.\n\n[MOB55_C]\nTommy, mir ist so langweilig. Wann hast du denn mal Zeit für mich?\n\n[MOB55_D]\nWas soll denn das heißen?\n\n[MOB55_E]\nIch weiß, du hast so viel zu tun, musst Leute beseitigen und bestechen.\n\n[MOB55_F]\nAber ich will mal wieder Spaß haben. Also vergiss mich nicht, hörst du?\n\n[MOB56_A]\nTommy, es heißt, du hast Ricardo Diaz erledigt.\n\n[MOB56_B]\nIn seinem Haus ist ein Feuer ausgebrochen.\n\n[MOB56_C]\nIch glaube, er hatte ein Acrylhemd an und ist verbrannt.\n\n[MOB56_D]\nTommy, ich bin so stolz auf dich. Ich wusste, du bist ein echter Mann.\n\n[MOB56_E]\nUnd er war ein Mistkerl. Ich bin so stolz, dass du mein Freund bist.\n\n[MOB56_F]\nIch weiß, du hast zu tun, du musst schließlich die Stadt erobern.\n\n[MOB56_G]\nAber vergiss mich nicht, hörst du?\n\n[MOB57_A]\nIch bin's, Mercedes. Ich liebe dich nicht mehr, Tommy.\n\n[MOB57_B]\nWirklich nicht mehr. Du bist nicht mehr nett zu Mercedes.\n\n[MOB57_C]\nDu behandelst mich nicht mehr wie eine Dame. Du ignorierst mich und ich hasse dich.\n\n[MOB57_D]\nIch bestehe darauf, dass du sofort zu mir kommst!\n\n[MOB58_A]\nTommy.\n\n[MOB58_B]\nHey, Mercedes.\n\n[MOB58_C]\nSelber hey, du toller Hecht. Ich bin sauer auf dich, Tommy.\n\n[MOB58_D]\nSchick mich nie mehr zu diesem Jezz Torrent.\n\n[MOB58_E]\nSo ein Jammerlappen. Mittendrin fãngt er an zu weinen wegen seinem Hündchen,\n\n[MOB58_F]\ndas gestorben ist, als er 7 war, und dass seine Mama ihn nie lieb hatte.\n\n[MOB58_G]\nUnd Tommy - privat lãuft er in Perücke und BH rum.\n\n[MOB58_H]\nIch bin nicht gut auf dich zu sprechen!\n\n[MOB59_A]\nOh, Tommy. Ich bin's, Mercedes.\n\n[MOB59_B]\nIch wollte dir nur sagen, es ist ganz toll beim Film.\n\n[MOB59_C]\nWenn du nochmal etwas für mich hast, sag Bescheid.\n\n[MOB59_D]\nWirklich. Ich wollte immer Schauspielerin werden.\n\n[MOB59_E]\nIch denke, ich lerne viel über die Dramaturgie.\n\n[MOB59_F]\nEs ist so lehrreich! Vielen, vielen Dank. Bis bald. Adios.\n\n[MOB_99]\nGeh zu der Telefonzelle vor Ort.\n\n[MOB_98]\nGeh zu der Telefonzelle vor Ort.\n\n[MOB_97]\nGeh zu der Telefonzelle vor Ort.\n\n[MOB_96]\nGeh zu der Telefonzelle vor Ort.\n\n[MOB_95]\nGeh zu der Telefonzelle vor Ort.\n\n[A_TIME]\n+~1~ Sekunden\n\n[F_RANGE]\n~g~Du bist außer Reichweite des Feuerwehrfunks. Fahr nãher an eine Feuerwache heran!\n\n[DODO_FT]\nDu bist ~1~ Sekunden geflogen!\n\n[GA_8]\nBenutze den Zünder, um die Bombe hochgehen zu lassen.\n\n[GA_10]\nHübsche Karre. Hier sind deine $~1~.\n\n[GA_11]\nSo eine Karre haben wir schon. Die können wir nicht gebrauchen.\n\n[GA_12]\nBombe ist scharf.\n\n[GA_13]\nAuf dich ist Verlass. Wenn du alle, die auf der Liste stehen, abgeliefert hast, kriegst du einen Bonus.\n\n[GA_14]\nDu hast alle georderten Karren geliefert. Sehr gut. Hier, für dich.\n\n[GA_15]\nHoffentlich gefãllt dir die neue Farbe.\n\n[GA_16]\nDas Umspritzen ist gratis.\n\n[GA_19]\nAn dem Modell haben wir kein Interesse.\n\n[GA_20]\nVon der Sorte haben wir schon mehr als genug. Sorry, da kommen wir nicht ins Geschãft.\n\n[CHASE]\nGrößtes Medieninteresse bisher\n\n[CHASE1]\nNull\n\n[CHASE2]\nMinimal\n\n[CHASE3]\nVages Interesse\n\n[CHASE4]\nLokalblatt Seite 7\n\n[CHASE5]\nLokalblatt Titelseite\n\n[CHASE6]\nVice Courier einspaltig\n\n[CHASE7]\nVice Courier Titelseite\n\n[CHASE8]\nLokalsender 3-Uhr-Nachrichten\n\n[CHASE9]\nLokalsender 20-Uhr-Nachrichten\n\n[CHASE10]\nLokalsender Live-Berichterstattung\n\n[CHASE11]\nUFA Today Seite 12\n\n[CHASE12]\nUFA Today Seite 4\n\n[CHASE13]\nFoto in UFA Today\n\n[CHASE14]\nLandesweites TV 4-Uhr-News\n\n[CHASE15]\nLandesweites TV 20-Uhr-News\n\n[CHASE16]\nLandesweite Live-Berichterstattung\n\n[CHASE17]\nInternationale Berichterstattung\n\n[CHASE18]\nNationale Krise\n\n[CHASE19]\nInternationale Krise\n\n[CHASE20]\nWeltereignis\n\n[CHASE21]\nStoff aus dem Legenden sind\n\n[CR_1]\nKran kann dieses Fahrzeug nicht anheben.\n\n[PU_MONY]\nDu hast nicht genug Geld.\n\n[CO_ALL]\nDu hast sie alle geliefert. Hier, für dich.\n\n[FEM_ON]\nAN\n\n[FEM_OFF]\nAUS\n\n[FEM_YES]\nJa\n\n[FEM_NO]\nNein\n\n[FEM_RET]\nWiederholen\n\n[FEC_NA]\nNicht verfügbar\n\n[FEC_CWL]\nEine Waffe nach links\n\n[FEC_CWR]\nEine Waffe nach rechts\n\n[FEC_LOF]\nNach vorne sehen\n\n[FEC_TAR]\nZielen\n\n[FEC_MOV]\nBewegung\n\n[FEC_CAM]\nBlickwinkel\n\n[FEC_PAU]\nPause\n\n[FEC_ENV]\nIn Fahrzeug einsteigen\n\n[FEC_JUM]\nSpringen\n\n[FEC_ATT]\nAngreifen oder Waffe abfeuern\n\n[FEC_RUN]\nRennen\n\n[FEC_FPC]\nSubjektive Kamera\n\n[FEC_LL]\nNach links sehen\n\n[FEC_LB]\nNach hinten sehen\n\n[FEC_LR]\nNach rechts sehen\n\n[FEC_HOR]\nHupe\n\n[FEC_VES]\nFahrzeugsteuerung\n\n[FEC_BRA]\nBremsen oder rückwãrts fahren\n\n[FEC_HAB]\nHandbremse\n\n[FEC_CAW]\nFahrzeugwaffe\n\n[FEC_ACC]\nBeschleunigen\n\n[FEC_CCF]\nKonfiguration :\n\n[FEC_CF1]\nKonfig. 1\n\n[FEC_CF2]\nKonfig. 2\n\n[FEC_CF3]\nKonfig. 3\n\n[FEC_CF4]\nKonfig. 4\n\n[FEC_CDP]\nController-Anzeige :\n\n[FEC_ONF]\nZu Fuß\n\n[FEC_INC]\nIm Auto\n\n[FEC_VIB]\nVibration :\n\n[FEL_ENG]\nEnglisch\n\n[FEL_FRE]\nFranzösisch\n\n[FEL_GER]\nDeutsch\n\n[FEL_ITA]\nItalienisch\n\n[FEL_SPA]\nSpanisch\n\n[FED_DBG]\nMenu Debug\n\n[FED_RID]\nReload IDE\n\n[FED_RIP]\nReload IPL\n\n[FED_PAH]\nParse Heap\n\n[FED_DFL]\nCTheScripts::DbgFlag\n\n[FED_DLS]\nBig White Debug Light Switched\n\n[FED_SPR]\nShow Ped Road Groups\n\n[FED_SCR]\nShow Car Road Grups\n\n[FED_SCZ]\nShow Cull Zones\n\n[FED_DSR]\nDebug Streaming Requests\n\n[FED_SCP]\ngbShowCollisionPolys\n\n[PL_STAT]\nSpielerstatistiken\n\n[PE_WAST]\nVon dir abservierte Personen\n\n[PE_WSOT]\nVon anderen abservierte Personen\n\n[TM_BUST]\nZahl deiner Verhaftungen\n\n[GNG_WST]\nGang-Mitglieder\n\n[DED_CRI]\nKriminelle\n\n[PER_COM]\nAbsolviert (in Prozent)\n\n[KGS_EXP]\nSprengstoffverbrauch in kg\n\n[ACCURA]\nTreffsicherheit\n\n[ST_WEAP]\nWaffen-Budget\n\n[ST_PROP]\nBudget für Objekte\n\n[ST_AUTO]\nBudget für Autoreparaturen und Lackierung\n\n[ST_PHOT]\nVon dir gemachte Fotos\n\n[ST_LOAN]\nBesuche von Kredithaien\n\n[ST_STOR]\nGeknackte Lãden\n\n[ST_MOVI]\nFilm-Stunts\n\n[ST_PIZZ]\nGelieferte Pizzas\n\n[ST_GARB]\nGetãtigte Müllfuhren\n\n[ST_ICEC]\nVerkaufte Eiscreme\n\n[TOP_SHO]\nBeste Schießstand-Punktzahl\n\n[SHO_RAN]\nSchießstand-Rangliste\n\n[SEAGULL]\nAbgeschossene Möwen\n\n[PROPOWN]\nObjekte in deinem Besitz\n\n[ST_TIME]\nGespielte Zeit\n\n[ST_FTIM]\nFlugstunden\n\n[ST_PRAN]\nPiloten-Rating\n\n[ST_RAN0]\nAnfãnger\n\n[ST_RAN1]\nNavigator\n\n[ST_RAN2]\nCo-Pilot\n\n[ST_RAN3]\nHalb-Profi\n\n[ST_RAN4]\nKönner\n\n[ST_RAN5]\nProfi\n\n[ST_RAN6]\nAss\n\n[ST_RAN7]\nRoter Baron\n\n[ST_DRWN]\nGefütterte Fische\n\n[ST_FASH]\nKleidungsbudget\n\n[ST_DAMA]\nZerstörte Objekte\n\n[TM_DED]\nKrankenhausbesuche\n\n[DAYSPS]\nIm Spiel verstrichene Tage\n\n[NUMSHV]\nBesuche in Versteck\n\n[MXCARD]\nWeitester IRRSINNS-Sprung (in Fuß)\n\n[MXCARJ]\nHöchster IRRSINNS-Sprung (in Fuß)\n\n[MXCARDM]\nWeitester IRRSINNS-Sprung (m)\n\n[MXCARJM]\nHöchster IRRSINNS-Sprung (m)\n\n[MXFLIP]\nMax. Anzahl Salti\n\n[MXJUMP]\nMax. Drehungen im Sprung\n\n[BUL_FIR]\nVerschossene Kugeln\n\n[BUL_HIT]\nKugeln, die trafen\n\n[SPRAYIN]\nAnzahl Lackierungen\n\n[BSTSTU]\nBester IRRSINNS-Stunt bisher\n\n[INSTUN]\nIrrsinns-Stunt\n\n[PRINST]\nSuper Irrsinns-Stunt\n\n[DBINST]\nDoppelter Irrsinns-Stunt\n\n[DBPINS]\nSuper-Doppel-Irrsinns-Stunt\n\n[TRINST]\nDreifacher Irrsinns-Stunt\n\n[PRTRST]\nSuper-Dreifach-Irrsinns-Stunt\n\n[QUINST]\nVierfacher Irrsinns-Stunt\n\n[PQUINS]\nSuper-Vierfach-Irrsinns-Stunt\n\n[NOSTUC]\nBisher keine Irrsinns-Stunts geschafft\n\n[NOUNIF]\nMonster-Stunts geschafft\n\n[NMISON]\nBegonnene Missionen\n\n[PASDRO]\nAns Ziel beförderte Fahrgãste\n\n[MONTAX]\nMit Taxi verdientes Geld\n\n[DAYPLC]\nTagesetat für Polizei\n\n[CRIMRA]\nRang:\n\n[STPR_1]\nMalibu Club\n\n[STPR_2]\nDruckerei\n\n[STPR_3]\nFilmstudio\n\n[STPR_4]\nEiscremefabrik\n\n[STPR_5]\nAutohaus\n\n[STPR_6]\nTaxiunternehmen\n\n[STPR_7]\nBootswerft\n\n[SET1EN]\nKonfig. 1 aktiviert\n\n[GMSAVE]\nSpiel speichern\n\n[FEDS_TB]\nZurück\n\n[FEST_OO]\nvon\n\n[FEC_TUC]\nGeschützsteuerung\n\n[FEC_RS3]\nRadiosender auswãhlen (L3-Taste)\n\n[FEC_HO3]\nHupe (L3-Taste)\n\n[C_FAIL]\nBürgerwehr-Mission beendet!\n\n[C_ESCP]\n~r~Der Verdãchtige ist entwischt!\n\n[C_VIGIL]\nBÜRGERWEHR BONUS!!\n\n[HEAL_A]\nDein ~h~Gesundheitszustand~w~ wird rechts oben auf dem Bildschirm in Orange angezeigt.\n\n[WRONGCD]\nFalsche DVD. Bitte legen Sie die richtige DVD ein.\n\n[NOCD]\nDie DVD-Lade ist leer. Bitte DVD einlegen.\n\n[OPENCD]\nDie DVD-Lade ist offen. Bitte schließen.\n\n[CDERROR]\nFehler beim Lesen der 'Grand Theft Auto: Vice City' DVD.\n\n[RESTART]\nNeues Spiel wird gestartet\n\n[GA_3]\nKeine Gratisjobs mehr. Umspritzen kostet $100!\n\n[GA_1]\nHey, so was heißes rühre ich nicht an!\n\n[GA_1A]\nKomm wieder, wenn du nicht so viel zu tun hast...\n\n[HELP9_C]\nDrücke die~h~ ~k~~PED_FIREWEAPON~~w~, um das Prãzisionsgewehr ~h~abzufeuern~w~.\n\n[TAXI2]\n~r~Die Zeit ist um!\n\n[PAGEB13]\nGesundheits-Powerups in Versteck angeliefert.\n\n[PAGEB14]\nAdrenalin in Versteck vorrãtig.\n\n[FESZ_CA]\nAbbrechen\n\n[FES_NGA]\nNeues Spiel\n\n[FES_CAN]\nAbbrechen\n\n[FESZ_QL]\nAlle nicht gespeicherten Daten des aktuellen Spiels werden verloren gehen. Ladevorgang fortsetzen?\n\n[FESZ_QD]\nDieses gespeicherte Spiel wirklich löschen?\n\n[FESZ_QO]\nDieses gespeicherte Spiel wirklich überschreiben?\n\n[FESZ_QR]\nWirklich ein neues Spiel beginnen? Alle Daten seit dem letzten Speichern werden verloren gehen. Weiter?\n\n[T4X4_1]\n'PCJ Rallye'\n\n[BMX_1]\n'Krasses Gelãnde'\n\n[BMX_2]\n'Teststrecke'\n\n[BMXFAIL]\n~r~Du hast es nicht geschafft, einen neuen Rekord aufzustellen!\n\n[BMX_REC]\n~g~Neuer Rekord:~1~ !!\n\n[T4X4_3]\n'CHECKPOINT FIEBER'\n\n[MM_1]\n'PYLONEN-RALLYE'\n\n[T4X4_F]\n~r~Du hast gekniffen! Schon überfordert?\n\n[LANDSTK]\nLandstalker\n\n[IDAHO]\nIdaho\n\n[STINGER]\nStinger\n\n[LINERUN]\nLinerunner\n\n[PEREN]\nPerennial\n\n[SENTINL]\nSentinel\n\n[RIO]\nRio\n\n[PATRIOT]\nPatriot\n\n[FIRETRK]\nFeuerwehrwagen\n\n[TRASHM]\nTrashmaster\n\n[STRETCH]\nStretch Limo\n\n[MANANA]\nManana\n\n[INFERNS]\nInfernus\n\n[VOODOO]\nVoodoo\n\n[PONY]\nPony\n\n[MULE]\nMule\n\n[CHEETAH]\nCheetah\n\n[AMBULAN]\nKrankenwagen\n\n[FBICAR]\nFBI Washington\n\n[MOONBM]\nMoonbeam\n\n[ESPERAN]\nEsperanto\n\n[TAXI]\nTaxi\n\n[WASHING]\nWashington\n\n[BOBCAT]\nBobcat\n\n[WHOOPEE]\nMr Whoopee\n\n[BFINJC]\nBF Injection\n\n[HUNTER]\nHunter\n\n[POLICAR]\nPolizei\n\n[ENFORCR]\nEnforcer\n\n[SECURI]\nSecuricar\n\n[BANSHEE]\nBanshee\n\n[PREDATR]\nPredator\n\n[BUS]\nBus\n\n[RHINO]\nRhino\n\n[BARRCKS]\nBarracks OL\n\n[CUBAN]\nKubanischer Hermes\n\n[HELI]\nHelikopter\n\n[DODO]\nDodo\n\n[COACH]\nCoach\n\n[CABBIE]\nCabbie\n\n[STALION]\nStallion\n\n[RUMPO]\nRumpo\n\n[RCBANDT]\nRC Bandit\n\n[ROMERO]\nRomeros Leichenwagen\n\n[PACKER]\nPacker\n\n[ADMIRAL]\nAdmiral\n\n[SQUALO]\nSqualo\n\n[SEASPAR]\nSea Sparrow\n\n[PIZZABO]\nPizza Boy\n\n[GANGBUR]\nGang Burrito\n\n[TROPIC]\nTropic\n\n[SPEEDER]\nSpeeder\n\n[REEFER]\nReefer\n\n[FLATBED]\nFlatbed\n\n[YANKEE]\nYankee\n\n[CADDY]\nCaddy\n\n[ZEBRA]\nZebra Cab\n\n[TOPFUN]\nTop Fun\n\n[SKIMMER]\nSkimmer\n\n[PCJ600]\nPCJ 600\n\n[PHOENIX]\nPhoenix\n\n[FAGGIO]\nFaggio\n\n[FREEWAY]\nFreeway\n\n[RCBARON]\nRC Baron\n\n[RCRAIDE]\nRC Raider\n\n[GLENDAL]\nGlendale\n\n[OCEANIC]\nOceanic\n\n[SANCHEZ]\nSanchez\n\n[SPARROW]\nSparrow\n\n[LOVEFIS]\nLove Fist\n\n[COASTG]\nKüstenwache\n\n[DINGHY]\nDinghy\n\n[HERMES]\nHermes\n\n[SABRE]\nSabre\n\n[SABRETU]\nSabre Turbo\n\n[WALTON]\nWalton\n\n[REGINA]\nRegina\n\n[COMET]\nComet\n\n[DELUXO]\nDeluxo\n\n[BURRITO]\nBurrito\n\n[SPAND]\nSpandex Express\n\n[MARQUIS]\nMarquis\n\n[BAGGAGE]\nBaggage Handler\n\n[KAUFMAN]\nKaufman-Taxi\n\n[COASTMA]\nKüstenwachen-Maverick\n\n[MAVERIC]\nMaverick\n\n[RANCHER]\nRancher\n\n[FBIRANC]\nFBI Rancher\n\n[VIRGO]\nVirgo\n\n[GREENWO]\nGreenwood\n\n[HOTRING]\nHotring Racer\n\n[BLISTAC]\nBlista Compact\n\n[FEST_DF]\nZu Fuß zurückgel. Strecke (Meilen)\n\n[FEST_DC]\nMit Auto gefahrene Strecke (Meilen)\n\n[FESTDFM]\nZu Fuß zurückgelegte Strecke (Meter)\n\n[FESTDCM]\nMit Auto gefahrene Strecke (Meter)\n\n[TOT_DIS]\nInsgesamt zurückgel. Strecke (Meilen)\n\n[TOTDISM]\nInsgesamt zurückgel. Strecke (Meter)\n\n[DISTHEL]\nMit Helikopter geflogene Strecke (Meilen)\n\n[DISTHEM]\nMit Helikopter geflogene Strecke (Meter)\n\n[DISTBOA]\nMit Boot zurückgel. Strecke (Meilen)\n\n[DISTBOM]\nMit Boot zurückgel. Strecke (Meter)\n\n[FEST_LS]\nMit Krankenwagen gerettete Menschen\n\n[FEST_CC]\nKriminelle bei Bürgerwehr-Mission\n\n[FEST_FE]\nGelöschte Feuer gesamt\n\n[FEST_RP]\nBestandene Amokfahrten\n\n[FEST_MP]\nErledigte Missionen\n\n[FEST_BB]\nSchnelle Autos, Schnelles Geld:\n\n[FEST_H0]\nMeiste Checkpoints\n\n[FEST_GC]\nGeschrottete Gang-Autos:\n\n[FEST_H1]\nIm Dschungel der Diablos\n\n[FEST_H2]\nMafia-Massaker\n\n[FEST_H3]\nDer Casino-Coup\n\n[FEST_H4]\nRock'n'Roll mit Rumpo\n\n[USJ]\nMONSTER-STUNT-BONUS!\n\n[RATNG1]\nUnbescholtener Bürger\n\n[RATNG2]\nDurchschnittstyp\n\n[RATNG3]\nFalschparker\n\n[RATNG4]\nLadendieb\n\n[RATNG5]\nRowdy\n\n[RATNG6]\nLaufbursche\n\n[RATNG7]\nTaschendieb\n\n[RATNG8]\nKleptomane\n\n[RATNG9]\nInformant\n\n[RATNG10]\nSpitzel\n\n[RATNG11]\nVerrãter\n\n[RATNG12]\nHochstapler\n\n[RATNG13]\nBetrüger\n\n[RATNG14]\nSchieber\n\n[RATNG15]\nFalschspieler\n\n[RATNG16]\nSchlãger\n\n[RATNG17]\nStraßengauner\n\n[RATNG18]\nGauner\n\n[RATNG19]\nHalunke\n\n[RATNG20]\nOutlaw\n\n[RATNG21]\nSchurke\n\n[RATNG22]\nKurier\n\n[RATNG23]\nGangster\n\n[RATNG24]\nObergangster\n\n[RATNG25]\nGalgenvogel\n\n[RATNG26]\nEx-Knacki\n\n[RATNG27]\nSchwerer Junge\n\n[RATNG28]\nProfi\n\n[RATNG29]\nDrahtzieher\n\n[RATNG30]\nFahrer\n\n[RATNG31]\nSoldat\n\n[RATNG32]\nGorilla\n\n[RATNG33]\nKopfgeldjãger\n\n[RATNG34]\nMann fürs Grobe\n\n[RATNG35]\nRonin\n\n[RATNG36]\nAbrãumer\n\n[RATNG37]\nHit-Man\n\n[RATNG38]\nPartner\n\n[RATNG39]\nButcher\n\n[RATNG40]\nTroubleshooter\n\n[RATNG41]\nAttentãter\n\n[RATNG42]\nAdjutant\n\n[RATNG43]\nGemachter Mann\n\n[RATNG44]\nRechte Hand\n\n[RATNG45]\nVollstrecker\n\n[RATNG46]\nLeutnant\n\n[RATNG47]\nVize-Boss\n\n[RATNG48]\nCapo\n\n[RATNG49]\nBoss\n\n[RATNG50]\nOberboss\n\n[RATNG51]\nDon\n\n[RATNG52]\nKing of the City\n\n[PAGE_00]\n..\n\n[WELCOME]\nWILLKOMMEN IN\n\n[TSCORE]\nEINKÜNFTE: $~1~\n\n[PBOAT_2] { reVC update }\nDrücke die ~h~~k~~VEHICLE_FIREWEAPON~~w~, um die Bordkanonen abzufeuern.\n\n[HJSTAT]\nDistanz: ~1~.~1~m Höhe: ~1~.~1~m Saltos: ~1~ Drehungen: ~1~_\n\n[HJSTATW]\nDistanz: ~1~.~1~m Höhe: ~1~.~1~m Saltos: ~1~ Drehungen: ~1~_ Und was für eine Landung!\n\n[ATUTOR]\nDrücke die ~h~~k~~TOGGLE_SUBMISSIONS~~w~, um Krankenwagen-Missionen an- oder abzuschalten.\n\n[FEST_HA]\nHöchster Krankenwagen-Missions-Level\n\n[C_KILLS]\nKRIMINELLE: ~1~\n\n[HJSTATF]\nDistanz: ~1~Fuß Höhe: ~1~Fuß Saltos: ~1~ Drehungen: ~1~_\n\n[HJSTAWF]\nDistanz: ~1~Fuß Höhe: ~1~Fuß Saltos: ~1~ Drehungen: ~1~_ Und was für eine Landung!\n\n[CRED001]\nROCKSTAR NORTH\n\n[CRD001A]\nSTUDIO DIRECTOR\n\n[CRD001B]\nANDREW SEMPLE\n\n[CRED002]\nPRODUCER\n\n[CRD002A]\nDEVELOPMENT DIRECTOR\n\n[CRED003]\nLESLIE BENZIES\n\n[CRED004]\nART DIRECTOR\n\n[CRED005]\nAARON GARBUT\n\n[CRED006]\nTECHNICAL DIRECTORS\n\n[CRED007]\nOBBE VERMEIJ\n\n[CRED008]\nADAM FOWLER\n\n[CRED010]\nANDREW DUTHIE\n\n[CRED011]\nCRAIG FILSHIE\n\n[CRED012]\nWILLIAM MILLS\n\n[CRED013]\nCHRIS ROTHWELL\n\n[CRD013A]\nIMRAN SARWAR\n\n[CRD013B]\nJAMES WORRALL\n\n[CRD013C]\nJOHN HAIME\n\n[CRED014]\nWRITTEN BY\n\n[CRED015]\nJAMES WORRALL\n\n[CRED016]\nPAUL KUROWSKI\n\n[CRED017]\nDAN HOUSER\n\n[CRED018]\nLEAD CHARACTER DESIGNER\n\n[CRD018A]\nCHARACTER DESIGNER\n\n[CRED019]\nIAN MCQUE\n\n[CRD019A]\nTOKS SOLARIN\n\n[CRD019B]\nALAN DAVIDSON\n\n[CRED020]\nLEAD ANIMATOR\n\n[CRED021]\nALEX HORTON\n\n[CRD022A]\nANIMATORS\n\n[CRED022]\nLEE MONTGOMERY\n\n[CRD022B]\nDUNCAN SHIELDS\n\n[CRD022C]\nGUS BRAID\n\n[CRED023]\nVEHICLE DESIGNERS\n\n[CRD023A]\nJOLYON ORME\n\n[CRD023B]\nALAN DUNCAN\n\n[CRD024A]\nLEAD VEHICLE DESIGNER\n\n[CRED024]\nPAUL KUROWSKI\n\n[CRED025]\nMAP DESIGNERS\n\n[CRED026]\nADAM COCHRANE\n\n[CRED027]\nNIK TAYLOR\n\n[CRED028]\nGARY MCADAM\n\n[CRED029]\nKEIRAN BAILLIE\n\n[CRED030]\nALISDAIR WOOD\n\n[CRED031]\nANDREW SOOSAY\n\n[CRD031A]\nSTEVEN MULHOLLAND\n\n[CRD031B]\nWAYLAND STANDING\n\n[CRD031C]\nCAMPBELL J. DICK\n\n[CRD031D]\nGRAPHIC DESIGNER\n\n[CRD031E]\nSTUART PETRI\n\n[CRED032]\nLEAD PROGRAMMER\n\n[CRD032A]\nPROGRAMMERS\n\n[CRED033]\nALEXANDER ROGER\n\n[CRED034]\nGRAEME WILLIAMSON\n\n[CRED035]\nBARANE CHAN\n\n[CRED036]\nDEREK PAYNE\n\n[CRED037]\nGORDON YEOMAN\n\n[CRD037A]\nALAN CAMPBELL\n\n[CRD037B]\nMARK HANLON\n\n[CRD037C]\nANDRZEJ MADAJCZYK\n\n[CRED038]\nLEAD MUSIC PRODUCER\n\n[CRED039]\nCRAIG CONNER\n\n[CRED040]\nSTUART ROSS\n\n[CRED041]\nLEAD AUDIO ENGINEER\n\n[CRED042]\nALLAN WALKER\n\n[CRD041A]\nAUDIO ENGINEER\n\n[CRD041B]\nAUDIO\n\n[CRD042A]\nWILL MORTON\n\n[CRED043]\nAUDIO PROGRAMMER\n\n[CRED044]\nRAYMOND USHER\n\n[CRED045]\nTEST MANAGER\n\n[CRED046]\nCRAIG ARBUTHNOTT\n\n[CRED047]\nLEAD QA\n\n[CRED048]\nNEIL CORBETT\n\n[CRED049]\nKEVIN WONG\n\n[CRED050]\nQA\n\n[CRED051]\nDAVID BEDDOES\n\n[CRED052]\nDAVID WATSON\n\n[CRED053]\nBARRY CLARK\n\n[CRED054]\nROSS SPARROW\n\n[CRED055]\nJAMES ALLAN\n\n[CRED056]\nNEIL MEIKLE\n\n[CRD056A]\nGEORGE WILLIAMSON\n\n[CRD056B]\nMATT JONES\n\n[CRD056C]\nROB HARBOUR\n\n[CRD056D]\nTOM WHITTAKER\n\n[CRED057]\nLEAD TECHNICAL SUPPORT\n\n[CRED058]\nLORRAINE ROY\n\n[CRD057A]\nTECHNICAL SUPPORT\n\n[CRED059]\nCHRISTINE CHALMERS\n\n[CRD060A]\nOFFICE SUPPORT\n\n[CRD060B]\nKIM GURNEY\n\n[CRD060C]\nCASSIE OLIVER\n\n[CRED060]\nROCKSTAR NEW YORK\n\n[CRED061]\nEXECUTIVE PRODUCER\n\n[CRED062]\nSAM HOUSER\n\n[CRED063]\nPRODUCER\n\n[CRED064]\nDAN HOUSER\n\n[CRED065]\nVP OF DEVELOPMENT\n\n[CRED066]\nJAMIE KING\n\n[CRED067]\nCHIEF TECHNOLOGY OFFICER\n\n[CRED068]\nGARY J. FOREMAN\n\n[CRED069]\nASSOCIATE PRODUCER\n\n[CRED070]\nJEREMY POPE\n\n[CRD071A]\nDIRECTOR OF QUALITY ASSURANCE\n\n[CRD072A]\nJEFF ROSA\n\n[CRED071]\nMUSIC SUPERVISOR\n\n[CRED072]\nTERRY DONOVAN\n\n[CRED073]\nPRODUCTION TEAM\n\n[CRED074]\nTERRY DONOVAN\n\n[CRED075]\nJENNIFER KOLBE\n\n[CRED076]\nJENEFER GROSS\n\n[CRED077]\nLAURA PATERSON\n\n[CRED078]\nJEFF CASTANEDA\n\n[CRED079]\nJERONIMO BARRERA\n\n[CRED080]\nCARLY SLATER\n\n[CRED081]\nJUNG KWAK\n\n[CRED082]\nBRIAN WOOD\n\n[CRED083]\nRENAUD SEBANNE\n\n[CRED084]\nRICHARD KRUGER\n\n[CRD084A]\nDANIEL EINZIG\n\n[CRD084B]\nJACEN BURROWS\n\n[CRD084C]\nLINN PR\n\n[CRD084D]\nCOVER ART\n\n[CRD084E]\nSTEPHEN BLISS\n\n[CRED085]\nKENT PAUL'S 80 NOSTALGIA ZONE\n\n[CRED086]\nWRITTEN BY DAN HOUSER\n\n[CRD086A]\nPRODUCED BY ADAM TEDMAN\n\n[CRED087]\nWWW.KENTPAUL.COM AND WWW.VICECITY.COM\n\n[CRED088]\nCREATED BY\n\n[CRD088A]\nADAM TEDMAN\n\n[CRD088B]\nDAVID YU\n\n[CRD088C]\nJERRY LUNA\n\n[CRD088D]\nSTUART PETRI\n\n[CRD088E]\nMICHAEL CARNEVALE\n\n[CRD088F]\nGREG LAU\n\n[CRD088G]\nFUTABA HAYASHI\n\n[CRED089]\nQA MANAGER\n\n[CRED090]\nCRAIG ARBUTHNOTT\n\n[CRED091]\nLEAD ANALYST\n\n[CRED092]\nADAM DAVIDSON\n\n[CRD092A]\nJOE HOWELL\n\n[CRD092B]\nMARC FERNANDEZ\n\n[CRED093]\nGAME ANALYST\n\n[CRED094]\nRICHARD HUIE\n\n[CRED095]\nROCKSTAR TEST TEAM\n\n[CRED096]\nLANCE WILLIAMS\n\n[CRED097]\nJOE GREENE\n\n[CRED098]\nBRIAN PLANER\n\n[CRD098A]\nELIZABETH SATTERWHITE\n\n[CRD098B]\nJAMEEL VEGA\n\n[CRD098C]\nMIKE HONG\n\n[CRED099]\nLEE CUMMINGS\n\n[CRED100]\nSTORY\n\n[CRED101]\nJAMES WORRALL\n\n[CRED102]\nDAN HOUSER\n\n[CRED103]\nADAM TEDMAN\n\n[CRED104]\nPAUL YEATES\n\n[CRED105]\nJENEFER GROSS\n\n[CRED106]\nLAURA PATERSON\n\n[CRED107]\nCUT SCENES\n\n[CRED108]\nWRITTEN BY DAN HOUSER AND JAMES WORRALL\n\n[CRED109]\nAUDIO DIRECTED BY DAN HOUSER AND NAVID KHONSARI\n\n[CRED110]\nPRODUCED BY JAMIE KING\n\n[CRD110A]\nTALENT PROCUREMENT: JAMIE KING, SEAN MACALUSO\n\n[CRED111]\nCAST\n\n[CRD111A]\nSUPPORTING CHARACTERS\n\n[CRED112]\nTOMMY VERCETTI - RAY LIOTTA\n\n[CRED113]\nKEN ROSENBERG - WILLIAN FICHTNER\n\n[CRED114]\nSONNY FORELLI - TOM SIZEMORE\n\n[CRED115]\nSTEVE SCOTT - DENNIS HOPPER\n\n[CRED116]\nAVERY CARRINGTON - BURT REYNOLDS\n\n[CRED117]\nRICARDO DIAZ - LUIS GUZMAN\n\n[CRED118]\nLANCE VANCE - PHILIP MICHAEL THOMAS\n\n[CRED119]\nCOLONEL JUAN CORTEZ - ROBERT DAVI\n\n[CRED120]\nUMBERTO ROBINA - DANNY TREJO\n\n[CRED121]\nPHIL CASSIDY - GARY BUSEY\n\n[CRED122]\nMITCH BAKER - LEE MAJORS\n\n[CRED123]\nMERCEDES CORTEZ - FAIRUZA BALK\n\n[CRED124]\nKENT PAUL - DANNY DYER\n\n[CRED125]\nJEZZ TORRENT - KEVIN MCKIDD\n\n[CRED126]\nTAXI CONTROLLER - DEBORAH HARRY\n\n[CRED127]\nCANDY SUXX - JENNA JAMESON\n\n[CRED128]\nBJ SMITH - LAWRENCE TAYLOR\n\n[CRED129]\nAUNTIE POULET - YOUREE CLEOMILI HARRIS\n\n[CRED130]\nSUPPLIER - ARMANDO RIESCO\n\n[CRED131]\nCOUGAR - BLAYNE PERRY\n\n[CRED132]\nHILARY - CHARLES TUCKER\n\n[CRED133]\nCONGRESSMAN ALEX SHRUB - CHRIS LUCAS\n\n[CRED134]\nOLD MAN KELLY - GEORGE DICENZO\n\n[CRD134A]\nCAM JONES - GREG SIMS\n\n[CRD134B]\nPSYCHO - HUNTER PLATIN\n\n[CRD134C]\nMAUDE THE ICE CREAM LADY - JANE GENNARO\n\n[CRD134D]\nJETHRO - JOHN ZURHELLEN\n\n[CRD134E]\nGONZALES - JORGE PUPO\n\n[CRD134F]\nDWAYNE - NAVID KHONSARI\n\n[CRD134G]\nDICK - PETER MCKAY\n\n[CRD134H]\nMIKE THE GOON & PORN GUY - ROBERT CIHRA\n\n[CRD134I]\nPERCY - RUSSELL FOREMAN\n\n[CRED135]\nMOTION CAPTURE\n\n[CRED136]\nANIMATED BY\n\n[CRD136A]\nTECHNICAL DIRECTION BY ALEX HORTON\n\n[CRED137]\nDIRECTED BY\n\n[CRD137A]\nDIRECTED BY NAVID KHONSARI\n\n[CRED138]\nPRODUCED BY\n\n[CRD138A]\nPRODUCED BY JAMIE KING\n\n[CRD138B]\nRENAUD SEBBANE\n\n[CRED139]\nRECORDED AT PERSPECTIVE STUDIOS, BROOKLYN\n\n[CRED140]\nMOTION CAPTURE ACTORS\n\n[CRD140A]\nBLAYNE PERRY\n\n[CRD140B]\nJONATHON SALE\n\n[CRD140C]\nCHARLES TUCKER\n\n[CRD140D]\nEDDIE MARRERO\n\n[CRD140E]\nWILLIAM MCCALL\n\n[CRD140F]\nJORGE PUPO\n\n[CRD140G]\nROBERT JACKSON\n\n[CRD140H]\nTARA RADCLIFFE\n\n[CRD140I]\nJENIFER GAMBETESE\n\n[CRD140J]\nKRIS ACHEVARRIA\n\n[CRD140K]\nALI ORDOUBADI\n\n[CRD140L]\nKAHLEEM POOLE\n\n[CRED141]\nPEDESTRIAN DIALOGUE\n\n[CRD141A]\nWRITTEN BY DAN HOUSER, MARC FERNANDEZ, GILLIAN TELLING AND NAVID KHONSARI\n\n[CRD141B]\nWITH HELP FROM JEREMY POPE, LANCE WILLIAMS, AND JENNY JEMISON\n\n[CRED142]\nWRITTEN BY\n\n[CRD142A]\nDAN HOUSER AND JAMES WORRALL\n\n[CRED143]\nDIRECTED BY DAN HOUSER, CRAIG CONNER, MARC FERNANDEZ, AND ALLAN WALKER\n\n[CRED144]\nPRODUCED BY RENAUD SEBANNE\n\n[CRED145]\nPEDESTRIANS\n\n[CRED146]\nADAM DAVIDSON, ADAM WATKINS, ALEJANDRO K. BROWN, ALEX ANTHONY SIOUKAS, ALEX GARCIA,\n\n[CRED147]\nALICE SALTZMAN, ALISON CIHRA, AMY SALIMA, AMY SALZMAN, ANDREA VIDELA, ANTHONY ATTI,\n\n[CRED148]\nANTHONY RIVERA, BIJAN SHAMS, BLAYNE PERRY, BRETT BISOGNO, BREYE MATA, BRIAN PANEN,\n\n[CRED149]\nBROCK VODER, CAREY BERTINI, CHARISSE LAMBERT, CHRIS DIFAT, CHRIS REISENBERGER,\n\n[CRED150]\nCHRISTOPHER BRODAY, CHRISTOPHER CARRO, CYNTHIA GREENE, DAMARIES LOPEZ, DAN LEE,\n\n[CRED151]\nDAN SCHNEIDER, DAN TOYAMA, DAVID DEAN CHALTFIELD, JR., DAVID HARRISON, DAVID WILEY,\n\n[CRED152]\nDEBORAH COLLINS, DEBRANDA CHANEY-GILES, DEMETRA KOUKOULAS, DENISE ROSADO,\n\n[CRED153]\nDEVIN BENNETT, DEVIN WINTERBOTTOM, DORIS WOO, DOUGLAS HARRISON, DUNCAN COUTTS,\n\n[CRED154]\nDUPE AJAYI, EDWIN AVELLANEDA, ELIZABETH HOWELL, ELIZABETH SATTERWHITE, ERIC NAGLE,\n\n[CRED155]\nESTEBAN KARPLUS, F. FONT, FUTABA HAYASHI, GENE HILGREEN, GERALD COSGROVE,\n\n[CRED156]\nGERARD LUNA, GILLIAN TELLING, GREGG CARLUCCI, GREGORY CLERVOIX, GREGORY SCHWEIZER,\n\n[CRED157]\nHADLEY TOMICKI, J. ROSSETT, JAMEEL VEGA, JASON JONES, JEFF ROSA, JENNIFER JEMISON,\n\n[CRED158]\nJEREMY TAGGERT, JESSICA RIDER, JOSEPH GREENE,JOSEPH HOWELL, KATE DUKICH,\n\n[CRED159]\nKEL O'NEILL, KEVIN HOPKINS, LADAWN JAMES, LANCE WILLIAMS, LAURA BUBBLES,\n\n[CRED160]\nLAURA PATTERSON, LEE CUMMINGS, LETICIA L. YOUNG, LINDSAY KENNEDY, LISA ORITZ,\n\n[CRED161]\nLORNA JORDAN, LUCIO AMADIO, MARCO FERNANDEZ, MARIKO TANAKA, MARLON MATTHEWS,\n\n[CRED162]\nMARY TELLING, MASAYOSHI MITSUYAMA, MATTHEW CHUNG, MAX ALLSTADT, MAX BOGDANOV,\n\n[CRED163]\nMELISSA ALVAREZ, MICHAEL MAY, MICHAEL ROTHSTEIN, MIGUEL VIDAL, MIKE FEDERLINE,\n\n[CRED164]\nNATALIE DESCALZO, N'GAI MEMBERS, NICOLAS MALLO, NOELLE SADLER, NORBERT MORIVAN,\n\n[CRED165]\nOSWALD GREENE, JR., PETER MCKAY, PETER APPEL, PRESTON SAVARESE, RAFAEL GONZALES,\n\n[CRED166]\nRANDY JOHNSON, REY CONCEPCION, RICHARD KROGER, ROB TIBBS, ROBERT JACKSON,\n\n[CRED167]\nROBERT SCHULER, ROSS A. MCINTYRE, RUSSELL FOREMAN, RUTH NUNEZ, SALVADORE SUAZO,\n\n[CRED168]\nSAM WHITE, SANTOS GONZALES, SCOTT SMITH, SEYMOUR FRAILMAN, SPELMAN BRAUMAN,\n\n[CRED169]\nSTEPHANIE TELLING, STEVE KNEZEVICH, STEVE ROBERT, SUMIKO YASUDA, SUSAN LEWIS,\n\n[CRED170]\nSYLVIA COLACIOS, TOMOKO MIYAZAKI, TRON, VERDEL HALE, YVES MONDESIR, ZENO LEINFELDER,\n\n[CRED171]\nDAVID BEDDOES, CHRISTINE CHALMERS, BARRY CLARK, NEIL CORBETT, KIM GURNEY, NEIL MEIKLE,\n\n[CRED172]\nCASSIE OLIVER, LORRAINE ROY, DAVID WATSON, KEVIN WONG, WILL MORTON\n\n[CRED175]\nADAM DAVIDSON\n\n[CRED176]\nLANCE WILLIAMS\n\n[CRED177]\nNEIL MCCAFFREY\n\n[CRED178]\nLAURA PATERSON\n\n[CRED179]\nREY CONCEPCION\n\n[CRED180]\nCHARLES HEROLD\n\n[CRED181]\nANDREW GREENWALD\n\n[CRED182]\nJAMES MIELKE\n\n[CRED183]\nPETER SUCIU\n\n[CRED184]\nALEX ODULIO\n\n[CRED185]\nDON NKRUMAH\n\n[CRED186]\nKENDALL PITTMAN\n\n[CRED187]\nSAL SUAZO\n\n[CRED188]\nEREK MATEO\n\n[CRED189]\nCHRIS DIFATE\n\n[CRED190]\nLEILA MILTON\n\n[CRED191]\nDARREN ZOLTOWSKI\n\n[CRED192]\nVIRGINIA SMITH\n\n[CRED193]\nKEVIN CASSIN\n\n[CRED194]\nJASON SHIGEMORI\n\n[CRED195]\nKELLY KINSELLA\n\n[CRED196]\nMOLLIE STICKNEY\n\n[CRED197]\nSTANTON SARJEANT\n\n[CRED198]\nLAURA WALSH\n\n[CRED199]\nMARK GARONE\n\n[CRED200]\nJOANNA SLY\n\n[CRED201]\nELIZABETH HOWELL\n\n[CRED202]\nANA HERCULES\n\n[CRED203]\nSHIRLEY IRICK\n\n[CRED204]\nKASHONA FIELDS\n\n[CRED205]\nJOEL M. LILJE\n\n[CRED206]\nJOHN DIBENEDETTO\n\n[CRED207]\nNANCY GILES\n\n[CRED208]\nRYAN CROY\n\n[CRED209]\nJENNIFER KOLBE\n\n[CRED210]\nLIAM BURKE\n\n[CRED211]\nSIGRID PREISSL\n\n[CRED212]\nANITA FITZSIMONS\n\n[CRED213]\nPHILIPPA RASELLI\n\n[CRED214]\nWIL QUESNEL\n\n[CRED215]\nFALKO BURKERT\n\n[CRED216]\nSARA SEWELL\n\n[CRED217]\nRADIO STATIONS AND MUSIC\n\n[CRED218]\nMUSIC CONSULTANCY\n\n[CRD218A]\nHEINZ HENN\n\n[CRD218B]\nSTUART ROSS\n\n[CRED219]\nSOUNDTRACK CO-ORDINATOR\n\n[CRED220]\nTERRY DONOVAN\n\n[CRED221]\nPRODUCER FOR ROCKSTAR GAMES\n\n[CRED222]\nDAN HOUSER AND LAZLOW\n\n[CRED223]\nPRODUCER FOR ROCKSTAR NORTH\n\n[CRED224]\nCRAIG CONNER\n\n[CRED225]\nALLAN WALKER\n\n[CRED226]\nLAZLOW\n\n[CRED227]\nDJ BANTER AND IMAGING\n\n[CRED228]\nWRITTEN BY DAN HOUSER AND LAZLOW\n\n[CRED229]\nFLASH FM\n\n[CRD229A]\nTONI-MARIA CHAMBERS\n\n[CRD229B]\nIMAGING VOICE AND PRODUCTION-JEFF BERLIN\n\n[CRED230]\nSPECIAL THANKS TO\n\n[CRED231]\nTOMMY MOTTOLA,\n\n[CRED232]\nMICHELLE ANTHONY,\n\n[CRED233]\nSTEVE BARNETT,\n\n[CRED234]\nCHUCK FLECKENSTEIN,\n\n[CRED235]\nRITA LIBERATOR\n\n[CRED236]\nMARTIN & CLAIRE LOGAN\n\n[CRED237]\nSANDRA HUTTON\n\n[CRED238]\nCHRISTINE DAVIDSON\n\n[CRED239]\nALAN, RED & BIGFOOT\n\n[CRED240]\nLE T\n\n[CRED241]\nCOLIN DONALD\n\n[CRED242]\nKERRY STALLWOOD\n\n[CRED243]\nALAN MCGREGOR\n\n[CRED244]\nCHRIS MORTON\n\n[CRED245]\nEMIL BUSSE\n\n[CRED246]\nEMILY BAILLIE\n\n[CRED247]\nKEVIN ARCHIBALD\n\n[CRED248]\nMORAG KERR\n\n[CRED249]\nCATH WALKER\n\n[CRED250]\nISO BAR\n\n[CRED251]\nWATERLINE\n\n[CRED252]\nNEWS CAFE\n\n[CRD251A]\nTHE POND\n\n[CRD252A]\nPIVO\n\n[CRED253]\nBUDGET VIDEO RENTALS\n\n[CRED254]\nLORNA'S SCOOTER\n\n[CRED255]\nGARETH MURFIN\n\n[CRED256]\nADDITIONAL ART\n\n[CRED257]\nTONY PORTER\n\n[CRED258]\nCRAIG MOORE\n\n[CRED259]\nCUT SCENE LIP-SYNC ANIMATION\n\n[CRED260]\nCOSGROVE HALL FILMS\n\n[CRED261]\nPRODUCER - OWEN BALLHATCHET\n\n[CRED262]\nSENIOR ANIMATOR - JON TURNER\n\n[CRED263]\nANIMATORS - RICHARD DRUMM\n\n[CRED264]\nDAVE BROWN\n\n[CRED265]\nMAIR THOMAS\n\n[CRED266]\nPRASHANT PATEL\n\n[CRED267]\nAUDIO TECHNOLOGY CONSULTANT\n\n[CRED268]\nRIK EDE FOR GAMESOUND LTD.\n\n[CRED269]\nDTS INTEGRATION SUPPORT\n\n[CRED270]\nTED LAVERTY FOR DTS\n\n[CRED271]\nCHRIS GREER FOR DTS\n\n[CRED272]\nJASON PAGE FOR SCEE\n\n[CRED273]\nRESEARCH AND ANALYSIS\n\n[CRED274]\nVROCK\n\n[CRED275]\nDJ: LAZLOW AS HIMSELF\n\n[CRED276]\nIMAGING VOICE-JOE KELLY\n\n[CRED277]\nIMAGING PRODUCTION-JONATHAN HANST\n\n[CRED278]\nWAVE 103\n\n[CRED279]\nDJ: ADAM FIRST-JAMIE CANFIELD\n\n[CRED280]\nIMAGING VOICE-JEN SWEENEY\n\n[CRED281]\nIMAGING PRODUCTION-JONATHAN HANST\n\n[CRED282]\nFEVER 105\n\n[CRED283]\nDJ: OLIVER 'LADYKILLER' BISCUIT-JULIUS DYSON\n\n[CRED284]\nIMAGING VOICE MALE-ED MCMANN\n\n[CRED285]\nIMAGING VOICE FEMALE-SHAWNEE SMITH\n\n[CRED286]\nIMAGING PRODUCTION- LISTEN KITCHEN\n\n[CRED287]\nEMOTION 98.3\n\n[CRED288]\nDJ: FERNANDO- FRANK CHAVEZ\n\n[CRED289]\nIMAGING VOICE-JEN SWEENEY\n\n[CRED290]\nIMAGING PRODUCTION-JONATHAN HANST\n\n[CRED291]\nRADIO ESPANTOSO\n\n[CRED292]\nDJ: PEPE-TONY CHILRODES\n\n[CRED293]\nWILDSTYLE\n\n[CRED294]\nDJ: MISTER MAGIC AS HIMSELF\n\n[CRED295]\nIMAGING VOICE-FRANK SILVESTRO\n\n[CRED296]\nIMAGING PRODUCTION-LAZLOW\n\n[CRED297]\nKCHAT\n\n[CRED298]\nWRITTEN BY DAN HOUSER AND LAZLOW\n\n[CRED299]\nPRODUCED AND EDITED BY LAZLOW\n\n[CRED300]\nDJ AMY SHECKENHAUSEN -LEYNA WEBER\n\n[CRED301]\nJEZ TORRENT-KEVIN MCKIDD\n\n[CRED302]\nMANDY -COLLEEN CORBETT\n\n[CRED303]\nMICHELLE CARAPADIS-MARY BIRDSONG\n\n[CRED304]\nMR.ZOO-CARL DOWLING\n\n[CRED305]\nGETHSEMANEE-LYNN LIPTON\n\n[CRED306]\nCLAUDE MAGINOT-JOHN MAUCERI\n\n[CRED307]\nBJ SMITH-LAWRENCE TAYLOR\n\n[CRED308]\nTHOR-FRANK FAVA\n\n[CRED309]\nRADIO CALLERS\n\n[CRED310]\nCOUZIN ED, JOSH CLARK, JASON BUHRMESTER, JUAN ALLER, WAYNE OLIVER, SUSAN LEWIS, GILLIAN TELLING, TOM MURRAY, MIKE FERRANTE SR., EMMANUEL GOLDSTEIN, DAN HOUSER, NICK MANDELOS, GERRY COSGROVE, MIKE PALERMO, PORKCHOP, KEITH BROADAS\n\n[CRED311]\nLEWIS, GILLIAN TELLING, TOM MURRAY, MIKE FERRANTE SR., EMMANUEL GOLDSTEIN,\n\n[CRED312]\nDAN HOUSER, NICK MANDELOS, GERRY COSGROVE, MIKE PALERMO, PORKCHOP,\n\n[CRED313]\nKEITH BROADAS\n\n[CRED314]\nVCPR\n\n[CRED315]\nWRITTEN BY DAN HOUSER AND LAZLOW\n\n[CRED316]\nPRODUCED BY LAZLOW\n\n[CRED317]\nMAURICE CHAVEZ-PHILLIP ANTHONY RODRIGUEZ\n\n[CRED318]\nJONATHAN FREELOADER- PATRICK OLSEN\n\n[CRED319]\nMICHELLE MONTANIUS-KELLY GUEST\n\n[CRED320]\nREP. ALEX SHRUB- CHRIS LUCAS\n\n[CRED321]\nCALLUM CRAYSHAW- SEAN MODICA\n\n[CRED322]\nJOHN F. HICKORY- LJ GANSEN\n\n[CRED323]\nPASTOR RICHARDS- DAVID GREEN\n\n[CRED324]\nJAN BROWN- MAUREEN SILLIMAN\n\n[CRED325]\nBARRY STARK- RENAUD SEBBANE\n\n[CRED326]\nJENNY LOUISE CRAB- MARY BIRDSONG\n\n[CRED327]\nKONSTANTINOS SMITH- KONSTANTINOS.COM\n\n[CRED328]\nJEREMY ROBARD-PETER SILVESTRO\n\n[CRED329]\nRADIO COMMERCIALS\n\n[CRED330]\nWRITTEN BY DAN HOUSER AND LAZLOW\n\n[CRED331]\nPRODUCED BY LAZLOW\n\n[CRED332]\nADDITIONAL JINGLES PRODUCED BY CRAIG CONNER\n\n[CRED333]\nCOMMERCIAL VOICES:\n\n[CRED334]\nADAM DAVIDSON, ALEX ANTHONY, ALICE SALTZMAN, AMY SALZMAN, KATE DUKICH,\n\n[CRED335]\nARAN RONICLE, BARB JONES, BEN KRECH, BRIAN THOMAS, BROCK YODER, CHRIS\n\n[CRED336]\nFERRANTE, CRAIG CONNER, DAVE RYAN, DAVID GREEN, DORIS WOO, DOUGLAS\n\n[CRED337]\nHARRISON, ED MCMANN, FRANK CHAVEZ, FRANK FAVA, GENE HILGREEN, GREG\n\n[CRED338]\nSCHWEIZER, HUNTER PLATIN, JAMES FERRANTE, JEFF BERLIN, JEFF ROSA, JOE KELLY,\n\n[CRED339]\nJOHN MAUCERI, JOSH CLARK, JULIE WEMYSS, KEVIN STRALEY, KIM GURNEY, LANCE\n\n[CRED340]\nWILLIAMS, LAURA PATERSON, LAZLOW, LISA ORTIZ, LORNA JORDAN, LUCIEN JONES,\n\n[CRED341]\nMAUREEN SILLIMAN, MIKE FERRANTE JR., PETE GUSTIN, PETER SILVESTRO, RAFF\n\n[CRED342]\nCROLLA, RANDY JOHNSON, RICHARD KRUGER, RON REEVE, SHELLEY MILLER, SKY, TJ ALLARD\n\n[CRD344A]\nAUDIO RECORDED AT DIGITAL ARTS STUDIOS,\n\n[CRED344]\nNYC, TRACK 9 STUDIOS, NYC,\n\n[CRED345]\nWEDDINGTON MULTIMEDIA, LOS ANGELES,\n\n[CRD345A]\nSYNC SOUND, NYC AND RADIO LAZLOW, LONG ISLAND.\n\n[CRED346]\nTHANKS TO AXEL ERICSON AND WON LEE AT DIGITAL ARTS, PAUL VASQUEZ AT TRACK 9 STUDIOS, JOHN BOWEN AND JOHN HASSLER AT SYNC SOUND\n\n[CRED347]\nMARK LLOYD\n\n[CRED348]\nTIM BATES\n\n[CRED349]\nKIT BROWN\n\n[CRED350]\nANDY MASON\n\n[CRED351]\nPHIL DEANE\n\n[CRED352]\nPHIL ALEXANDER\n\n[CRED353]\nMATT HEWITT\n\n[CRED354]\nDENBY GRACE\n\n[CRED355]\nANTOINE CABROL\n\n[CRED356]\nJONATHAN STONES\n\n[CRED357]\nMIKE BLACKBURN\n\n[CRED358]\nTIM MCGAFF\n\n[CINCAM]\nCinematic-Kamera\n\n[RC4]\n'ROCK'N ROLL MIT RUMPO'\n\n[LEGAL]\n~g~Schalte die kriminelle Bedrohung aus!\n\n[GA_2]\nNeuer Motor und neue Lackierung. Die Cops werden dich nicht identifizieren!\n\n[HELP15]\nWenn zu Fuß unterwegs, drücke die ~h~~k~~PED_LOOKBEHIND~~w~, um ~h~nach hinten zu sehen~w~. Benutze den ~h~rechten Analog-Stick~w~, um dich ~h~umzusehen~w~.\n\n[FEC_LB4]\nNach hinten sehen (R3-Taste)\n\n[PERPIC]\nVersteckte Pãckchen gefunden\n\n[CO_ONE]\nVerstecktes Pãckchen ~1~ von ~1~\n\n[GA_21]\nIn dieser Garage bringst du keine Autos mehr unter.\n\n[CHEAT1]\nCheat aktiviert\n\n[CHEAT2]\nWaffen-Cheat\n\n[CHEAT3]\nHealth-Cheat\n\n[CHEAT4]\nPanzerungs-Cheat\n\n[CHEAT5]\nFahndungslevel-Cheat\n\n[CHEAT6]\nGeld-Cheat\n\n[CHEAT7]\nWetter-Cheat\n\n[USJ_ALL]\nALLE MONSTER-STUNTS ABSOLVIERT!\n\n[JAN]\nJan\n\n[FEB]\nFeb\n\n[MAR]\nMãr\n\n[APR]\nApr\n\n[MAY]\nMai\n\n[JUN]\nJun\n\n[JUL]\nJul\n\n[AUG]\nAug\n\n[SEP]\nSept\n\n[OCT]\nOkt\n\n[NOV]\nNov\n\n[DEC]\nDez\n\n[DEFDT]\n--:---:---- --:--:--\n\n[BONUS]\n~g~BONUS $~1~\n\n[HORN1]\nDrück die ~h~~k~~VEHICLE_HORN~~w~, um zu ~h~hupen.\n\n[HORN2]\nDrück die ~h~~k~~VEHICLE_HORN~~w~, um zu ~h~hupen.\n\n[HORN3]\nDrück die ~h~~k~~VEHICLE_HORN~~w~, um zu ~h~hupen.\n\n[FEC_EXV]\nIn Fahrzeug ein- und aussteigen.\n\n[TAXI_M]\n'TAXIFAHRER'\n\n[COP_M]\n'BÜRGERWEHR'\n\n[FIRE_M]\n'FEUERWEHRMANN'\n\n[AMBUL_M]\n'SANITÃTER'\n\n[HJ_IS]\nIRRSINNS-STUNT-BONUS: $~1~\n\n[HJ_PIS]\nSUPER IRRSINNS-STUNT-BONUS: $~1~\n\n[HJ_DIS]\nDOPPELTER IRRSINNS-STUNT-BONUS: $~1~\n\n[HJ_PDIS]\nSUPER-DOPPEL-IRRSINNS-STUNT-BONUS: $~1~\n\n[HJ_TIS]\nDREIFACHER IRRSINNS-STUNT-BONUS: $~1~\n\n[HJ_PTIS]\nSUPER-DREIFACH-IRRSINNS-STUNT-BONUS: $~1~\n\n[HJ_QIS]\nVIERFACHER IRRSINNS-STUNT-BONUS: $~1~\n\n[HJ_PQIS]\nSUPER-VIERFACH-IRRSINNS-STUNT-BONUS: $~1~\n\n[FESZ_LS]\nLadevorgang beendet.\n\n[HELI_1A]\nTeste dein Können mit dem 'Sparrow'. Probiere, wie schnell du den Kurs abfliegen kannst.\n\n[HELI_1B]\nKurs absolviert!\n\n[HELIODD]\nHelikopter-Jobs\n\n[LAW]\nDIE ANWALTSMISSIONEN\n\n[LAW1_1]\n~g~Besorge dir neue Sachen in Rafaels Shop.\n\n[LAW4_6]\nNieder mit der Geschãftsleitung!\n\n[LAW4_7]\nTod den Bossen!\n\n[LAW4_8]\nKampf, Kampf, Kampf, Kampf!\n\n[LAW4_9]\nMehr Urlaub, weniger Arbeit!\n\n[LAW4_11]\nKampf, Kampf, Kampf, Kampf!\n\n[LAW4_12]\nEs lebe die Revolution!\n\n[GENERAL]\nDIE COLONEL-MISSIONEN\n\n[GEN3_4]\nTommy Vercetti. Los, komm...\n\n[GEN3_13]\nWas ist los, Mann?! Steig auf das Dach gegenüber im Hof bevor sie kommen!\n\n[GEN3_17]\nMist! Willst du mich umbringen?!\n\n[GEN3_21]\n~g~Er hat Diaz' Geld! Stelle ihn und hole es zurück!\n\n[GEN3_24]\n~r~Diaz hat's erwischt! Du hast versagt!\n\n[GEN3_26]\n~r~Du hast Diaz erwischt!\n\n[GEN3_27]\n~r~Du hast Diaz' Bodyguards erwischt!\n\n[GEN3_31]\n~g~Begib dich zum Übergabeort und pass auf Diaz auf.\n\n[GEN3_32]\n~g~Begib dich zu deinem Beobachtungsposten auf dem Dach des Gebãudes gegenüber von Lance.\n\n[COKE]\nDIE KOKS-BARON-MISSIONEN\n\n[COK1_3]\nIch hoffe, du brichst dir das Genick!\n\n[COK1_6]\nIch hab diese Idioten satt!\n\n[COK2_7]\nSiehst du diese Bojen? Versuch, die Lichter auszuschießen.\n\n[COK2_10]\nEines ist sicher: Du schießt besser als du laberst.\n\n[COK2_11]\nDanke. Du bist ein echter Charmeur.\n\n[COK2_12]\nIch weiß, Tommy.\n\n[COK2_18]\nStehst du auf Kenny Loggins?\n\n[COK2_19]\nMann, ich liebe diese Scheibe.\n\n[COK2_26]\n~r~Du hast Lance erwischt!\n\n[COK3_1]\nNicht schießen, Mann!\n\n[COK3_2]\nWas ist in dem Zeug drin?\n\n[COK3_3]\nEr klaut das Boot. Mist!\n\n[COK3_4]\nHilfe! Irgendein Irrer stiehlt das Boot, Mann!\n\n[COK4_W]\nUff! Das ist der letzte.\n\n[COK4_X]\nIch lass die Mühle an.\n\n[COK4_Y]\nIch glaube, wir haben ein paar neue Freunde.\n\n[COK4_2]\nJa.\n\n[COK4_6]\nWeißt du, wo's lang geht?\n\n[COK4_7]\nHaben wir uns verfahren?\n\n[COK4_8]\nWir haben Konkurrenz bekommen!\n\n[COK4_9]\nKnöpf sie dir vor!\n\n[COK4_9A]\nZeit für den Lance Vance Dance!\n\n[COK4_10]\nDie sind Kleinholz! Und Fischfutter.\n\n[COK4_11]\nGeschafft! Die anderen Schiffchen taugen nicht viel.\n\n[COK4_17]\nDie wollen's wissen!\n\n[COK4_18]\nIch hab nasse Füße! WIR KRIEGEN WASSER INS BOOT!\n\n[COK4_21]\nAchtung, Brücke!\n\n[COK4_22]\nRaus! Das Ding geht hoch!\n\n[COK4_23]\nGut geschossen.\n\n[COK4_29]\n~r~Du hast Lance erwischt!\n\n[ASS1_6]\nGeh nur, Tommy, ich komm schon zurecht!\n\n[ASS1_7]\nDas ist für euch, ihr verdammten Mörder!!\n\n[ASS1_8]\nIch komm hier nicht weg!\n\n[ASS1_9]\nIch bin da, Tommy!\n\n[ASS1_10]\nHey, das ist aber ein herzallerliebstes Beet.\n\n[ASS1_11]\nHey Tommy, krieg ich ein Zimmer mit Blick auf die Bucht?\n\n[ASS1_12]\nSchön hohe Decken hat's hier...\n\n[ASS1_3]\nLance! Ich brauche Deckung!\n\n[ASS1_4]\nDiaz muss drinnen sein!\n\n[ASS1_5]\nLance!\n\n[ASS1_15]\n~g~Stürme die Villa und erledige Diaz!\n\n[ASS1_17]\n~g~Es führen mehrere Wege in die Villa.\n\n[TAXWAR]\nTAXI-KRIEG-MISSIONEN\n\n[NOTAXI]\n~g~Du brauchst ein Kaufman-Taxi, um diese Mission zu aktivieren.\n\n[TAXW1_5]\n~g~Du musst in einem Kaufman-Taxi sitzen!\n\n[TAX2_4]\nAuf geht's, Tommy.\n\n[TAX2_5]\nPolier ihm die Visage.\n\n[TAX2_6]\nDer hat nicht mal eine Lizenz.\n\n[TAX2_7]\nVerdammte Limo-Services.\n\n[TAXW3_1]\n~g~Hole Mercedes ab.\n\n[RACE1]\n~g~3...2...1...LOS, LOS, LOS!\n\n[RACE2]\n~g~3\n\n[RACE3]\n~g~2\n\n[RACE4]\n~g~1\n\n[RACE5]\n~g~LOS!\n\n[FIRST]\n~b~1.\n\n[SECOND]\n~b~2.\n\n[THIRD]\n~b~3.\n\n[FOURTH]\n~b~4.\n\n[RACETM]\n~b~ZEIT: ~1~:~1~\n\n[RACETM2]\n~b~ZEIT: ~1~:0~1~\n\n[RACEFA]\n~r~Du hast das Rennen verloren!\n\n[TEX1_5]\n~r~Er ist entkommen!\n\n[SEG3_1]\nZEIT:\n\n[SEG3_2]\n~g~Begib dich zu dem Transporter mit dem RC Raider und den Zeitzünder-Bomben.\n\n[SEG3_3]\n~g~Du musst den RC Raider benutzen, um 4 Bomben zu 4 Zielzonen auf dem Grundstück zu bringen.\n\n[SERG3_5]\n~g~Du kannst immer nur 1 Bombe transportieren und kannst erfolgreich platzierten Bomben nicht wieder aufnehmen.\n\n[SEG3_7]\n~g~Sobald du die ERSTE Bombe platziert hast, lãuft der Timer des Zeitzünders an. Du musst dann alle Bomben innerhalb dieses Zeitraums platzieren.\n\n[SEG3_8]\n~g~Alle 4 Bomben müssen in den 4 Zielzonen platziert werden, um die Mission zu erfüllen und das Gebãude zu demolieren.\n\n[SEG3_9]\n~g~Zielzone getroffen! Noch 3 Bomben.\n\n[SEG3_10]\n~g~Zielzone getroffen! Noch 2 Bomben.\n\n[SEG3_11]\n~g~Zielzone getroffen! Noch 1 Bombe.\n\n[SEG3_12]\n~r~Ziel verfehlt. Hol dir eine Bombe!\n\n[SEG3_13]\n~g~Wirf die Bombe in einer Zielzone ab.\n\n[SEG3_14]\n~r~Die Zeit ist um. Demolierung des Gebãudes fehlgeschlagen.\n\n[SEG3_15]\n~r~Dein RC Raider ist zerstört. Wie willst du jetzt die Bomben transportieren?\n\n[AVERY]\nAVERY-MISSIONEN\n\n[ASM]\nATTENTÃTERMISSIONEN\n\n[ASM_1]\nATTENTÃTERMISSION 1\n\n[ASM1_1]\n~g~Mr. Teal, Ihre Hilfe bei der Beseitigung der Landeier war ãußerst wertvoll. Ich habe noch mehr Arbeit, die eine eher 'zupackende' Art verlangt. Ihr nãchster Job klebt unter dem Telefon.\n\n[ASM1_2]\n~g~Begib zu dich dem Fernsprecher vor dem Einkaufszentrum in Washington.\n\n[ASM1_3]\n~g~Carl Pearson, Pizza-Lieferant. Er darf seine Lieferungen nicht durchführen.\n\n[ASM1_4]\n~g~Schalte den Pizza-Lieferanten aus, bevor er seine Lieferungen abschließt.\n\n[ASM_2]\nATTENTÃTERMISSION 2\n\n[ASM_3]\nATTENTÃTERMISSION 3\n\n[ASM3_A]\nMarcus Hammond, Franco Carter, Dick Tanner, Nick Kong und Stuntman Driver gehören zu einem europãischen Syndikat und planen einen Überfall.\n\n[ASM3_B]\nSie sind alle bereits in Position. Schalten Sie sie aus, bevor es losgeht. Sie haben 9 Minuten. Ich habe in der Nãhe Waffen deponiert, die Sie brauchen werden.\n\n[ASM3_1]\n~g~Hol dir die Waffe, die Mr. Black für dich deponiert hat.\n\n[ASM3_2]\n~g~Geh nicht zu dicht an die Zielperson heran, sonst bemerkt sie dich.\n\n[ASM3_3]\n~g~Es geht schneller, wenn du dir eine günstige Position nahe ihrem Standort suchst und zuschlãgst, ohne gesehen zu werden.\n\n[ASM3_4]\n~g~Er hat dich gesehen. Du musst ihn irgendwie ausschalten!\n\n[ASM3_5]\n~g~Marcus Hammond befindet sich bei den Werbetafeln in Washington Beach.\n\n[ASM3_6]\n~g~Franco Carter befindet sich bei DBP Security nahe dem Ocean Drive.\n\n[ASM3_7]\n~g~Dick Tanner ist in der Nãhe des Juweliers in Vice Point.\n\n[ASM3_8]\n~g~Nick Kong befindet sich nãhe Washington Beach.\n\n[ASM3_9]\n~g~Stuntman Driver ist in Washington.\n\n[ASM3_10]\nDu hast nicht alle ausgeschaltet.\n\n[ASM_4]\nATTENTÃTERMISSION 4\n\n[ASM4_1]\n~g~Hol dir das Gewehr, das im Laub vor dem Flughafen-Terminal für dich deponiert wurde.\n\n[ASM4_2]\n~g~Verfehle dein Ziel nicht, du alarmierst sonst die Leibwãchter. Und bleib auf Distanz, damit er dich nicht bemerkt.\n\n[ASM4_3]\n~g~Beobachte die Frau über den Check-in-Schaltern im Terminal. TU IHR NICHTS.\n\n[ASM4_4]\n~g~Erledige den Mann, dem sie den Aktenkoffer gibt, aber erst, NACHDEM ER IHN GENOMMEN HAT. Hole den Koffer und bringe ihn ins Ammu-Nation Downtown.\n\n[ASM4_5]\nHol dir den Aktenkoffer.\n\n[ASM4_6]\n~g~Bring den Aktenkoffer ins Ammu-Nation Downtown.\n\n[ASM4_7]\n~r~Du hast die Frau erwischt, du Idiot!\n\n[ASM4_8]\n~r~Die Zielperson hat gehört, wie du geschossen hast. Der Deal ist geplatzt!\n\n[ASM4_9]\n~r~Die Zielperson hat das Flugzeug bestiegen!\n\n[ASM4_11]\n~r~Die Zielperson hat dich gesehen! Der Deal ist geplatzt!\n\n[ASM4_13]\n~g~Er hat dich bemerkt und flieht. Schalte ihn aus und hol dir den Aktenkoffer!\n\n[ASM4_14]\n~g~Der Distanz-Balken am oberen rechten Bildschirmrand zeigt dir, wie nahe du der Zielperson bist. Lass ihn nicht voll werden, sonst sieht sie dich.\n\n[ASM_5]\nATTENTÃTERMISSION 5\n\n[KICK]\nKICKSTART\n\n[KICK1_3]\n~g~Anzahl, wie oft der Fuß abgesetzt wurde: ~1~\n\n[KICK1_4]\n~g~Zeitstrafe: ~1~ Sekunden\n\n[BANK]\nBANK-MISSIONEN\n\n[BANK1]\nBANK-MISSION 1\n\n[BANK2]\nBANK-MISSION 2\n\n[BJM2_21]\n~g~Triff so viele Ziele als möglich, solange deine Munition reicht.\n\n[BANK3]\nBANK-MISSION 3\n\n[BJM3_1]\n~g~Besorg dir ein schnelles Auto und fahre an den Start.\n\n[BNK4_2A]\nDie Mechaniker haben das Baby super hergerichtet.\n\n[BNK4_3G]\nOh, Mist, jetzt haben wir die Cops am Hals!\n\n[BNK4_3H]\nUnd wir sind noch nicht mal da.\n\n[BNK4_3K]\nAlso, erst mal müssen wir die Cops abschütteln...\n\n[BNK4_3L]\nGroßer Gott, Tommy, willst du uns alle umbringen?!\n\n[BNK4_3N]\nAlles, was ich gern habe, geht kaputt!\n\n[BNK4_26]\nVerdammt! Da sind sie schon!\n\n[BNK4_32]\nSpreng die Schließfãcher mit Sprengstoff auf.\n\n[BNK4_36]\nWo ist Cam?\n\n[BNK4_37]\nIn der Hölle.\n\n[BNK4_38]\nDas ist der letzte! LOS! LOS! LOS!\n\n[BNK_39]\nShit! Wo bleibt Hilary?\n\n[BK4_40A]\nIch werd was für seine Verlustãngste tun!\n\n[BNK4_42]\nHey, Jungs! Los, rein! Ich geb euch Deckung!\n\n[BNK4_43]\nIch hab alles im Griff! FAHR!\n\n[BNK4_44]\nGeschafft! Wir sind reich! REICH!\n\n[BNK4_45]\nEin Jammer, dass Cam es nicht gepackt hat. Er war 'n guter Kerl.\n\n[BNK4_46]\nJa. Andererseits, so bleibt mehr für uns!\n\n[BNK4_47]\nSehr richtig! YEEEEHAAAH!\n\n[BNK4_48]\nTommy, eine Massage gefãllig?\n\n[BNK4_49]\nHi, Mercedes. Ja, ich bin ein bisschen verspannt...\n\n[BNK450A]\nWas hab ich gesagt, Tommy? Korrupte Bullen müssen sich vorsehen, wenn Kent Paul in der Stadt ist.\n\n[BNK450B]\nKomm, gib mir 'nen größeren Batzen ab. Na komm. Ich brauch neue Klamotten.\n\n[BNK4_51]\nIch finde, du siehst ok aus.\n\n[KENT]\nKENT PAUL-MISSIONEN\n\n[KENT1]\nKENT PAUL-MISSION 1\n\n[COUNT]\nFÃLSCHER-MISSIONEN\n\n[COUNT1]\nFÃLSCHER-MISSION 1\n\n[COUNT2]\nFÃLSCHER-MISSION 2\n\n[BIKE]\nDIE BIKER GANG-MISSIONEN\n\n[BIKE1]\nBIKER-MISSION 1\n\n[BIKE2]\nBIKER-MISSION 2\n\n[BIKE3]\nBIKER-MISSION 3\n\n[GOAWAY1]\nKomm wieder, wenn du die Haiti-Gang-Missionen abgeschlossen hast.\n\n[HAIT]\nDIE HAITI-GANG-MISSIONEN\n\n[HAIT1]\nHAITI-MISSION 1\n\n[HAIT2]\nHAITI-MISSION 2\n\n[HAIT3]\nHAITI-MISSION 3\n\n[HAM3_6]\n~g~Verwende das Prãzisionsgewehr, das ich für dich besorgt habe.\n\n[ROCK]\nDIE ROCKBAND-GANG-MISSIONEN\n\n[ROK1_4]\n~g~Ok, ich glaube, das ist es, was du suchst...\n\n[ROK1_1E]\n~g~Das kostet mehr als du hast!\n\n[ROK1_1F]\n~g~Komm wieder, wenn du die Kohle hast.\n\n[RBM2_6]\n~g~Wow! Die ist 'n Kerl! Halt ihn auf!\n\n[ROCK3]\nROCKBAND-MISSION 3\n\n[ROK3_6D]\n~r~und IHR UND EUER KOPFPUTZ mit dazu!\n\n[ROK3_40]\nNeben dem Kühler für die Babynahrung?\n\n[RBM3_5]\n~g~Bring Love Fist zu ihrem Auftritt.\n\n[CUBANM]\nDIE KUBA-GANG-MISSIONEN\n\n[CUBAN1]\nKUBA-MISSION 1\n\n[CUBAN2]\nKUBA-MISSION 2\n\n[CUB2_10]\n~r~Du sollst Haitianer ausschalten, keine Kubaner!\n\n[CUBAN3]\nKUBA-MISSION 3\n\n[CUBAN4]\nKUBA-MISSION 4\n\n[CUB4_04]\n~r~Du hast die Basis alarmiert. Jetzt kommen wir niemals rein!\n\n[CUB4_05]\n~r~Du solltest doch im Auto bleiben. Jetzt lassen sie uns niemals rein.\n\n[CUB4_25]\nOkay, los geht's.\n\n[PROT]\nSCHUTZGELD-MISSIONEN\n\n[PRO1_02]\n~g~Verlasse das Einkaufszentrum.\n\n[PRO3_06]\n~g~Hãng die Cops ab.\n\n[PORN]\nPORNO-MISSIONEN\n\n[PORN1]\nPORNO-MISSION 1\n\n[POR1_03]\n~r~Candy ist erledigt!\n\n[PORN2]\nPORNO-MISSION 2\n\n[PORN3]\nPORNO-MISSION 3\n\n[POR3_18]\nMan hat dich bemerkt!\n\n[PORN4]\nPORNO-MISSON 4\n\n[POR4_04]\n~g~Die Büros liegen auf der anderen Seite dieses Tors.\n\n[PHIL]\nPHIL-MISSIONEN\n\n[PHIL1]\nPHIL-MISSION 1\n\n[PHIL2]\nPHIL-MISSION 2\n\n[PIZ1_A]\nPIZZABOTEN-MISSION\n\n[PIZ1_03]\n~g~Fahr zurück zum Pizza-Service für weitere Bestellungen.\n\n[PIZ1_04]\n~g~Hier sind die neuen Bestellungen.\n\n[PIZ1_10]\nDrücke die ~h~R3-Taste~w~, um die Pizza-Missionen abzubrechen.\n\n[CNTBUY1]\nDruckerei gekauft: $ ~1~\n\n[CARBUY]\nAutohaus gekauft: $ ~1~\n\n[PORNBUY]\nFilmstudio gekauft: $ ~1~\n\n[ICEBUY]\nEiscremefabrik gekauft: $ ~1~\n\n[TAXIBUY]\nTaxiunternehmen gekauft: $ ~1~\n\n[BANKBUY]\nMalibu Club gekauft: $ ~1~\n\n[BOATBUY]\nBootswerft gekauft: $ ~1~\n\n[PRNT_NO]\nZurzeit kannst du die Druckerei nicht kaufen. Komm spãter wieder.\n\n[CAR_NO]\nZurzeit kannst du das Autohaus nicht kaufen. Komm spãter wieder.\n\n[PORN_NO]\nZurzeit kannst du das Filmstudio nicht kaufen. Komm spãter wieder.\n\n[ICE_NO]\nZurzeit kannst du die Eiscremefabrik nicht kaufen. Komm spãter wieder.\n\n[TAXI_NO]\nZurzeit kannst du das Taxiunternehmen nicht kaufen. Komm spãter wieder.\n\n[BANK_NO]\nZurzeit kannst du den Malibu Club nicht kaufen. Komm spãter wieder.\n\n[BOAT_NO]\nZurzeit kannst du die Bootswerft nicht kaufen. Komm spãter wieder.\n\n[PRNT_R3]\nDrücke R3, um die Druckerei zu kaufen. Preis: $~1~\n\n[CAR_R3]\nDrücke R3, um das Autohaus zu kaufen. Preis: $~1~\n\n[PORN_R3]\nDrücke R3, um das Filmstudio zu kaufen. Preis: $~1~\n\n[ICE_R3]\nDrücke R3, um die Eiscremefabrik zu kaufen. Preis: $~1~\n\n[TAXI_R3]\nDrücke R3, um das Taxiunternehmen zu kaufen. Preis: $~1~\n\n[BANK_R3]\nDrücke R3, um den Malibu Club zu kaufen. Preis: $~1~\n\n[BOAT_R3]\nDrücke R3, um die Bootswerft zu kaufen. Preis: $~1~\n\n[COL2_6]\nKeine Bewegung, amerikanisches Imperialistenschwein!\n\n[COL2_6B]\nDas ist Eigentum des französischen Staates.\n\n[COL2_6C]\nHer damit!\n\n[COL3_A]\nThomas, schön, dass Sie da sind.\n\n[COL3_B]\nVerzeihen Sie, dass ich direkt zum Geschãftlichen komme.\n\n[COL3_C]\nDiaz bat mich, eine kleine Transaktion für ihn zu überwachen.\n\n[COL3_D]\nHoffentlich lãuft es diesmal besser als zuletzt.\n\n[COL3_E]\nDeshalb wende ich mich ja an Sie, mein Freund.\n\n[COL3_F]\nIch habe im Parkhaus ein wenig Artillerie deponiert.\n\n[COL3_G]\nHolen Sie sich die und beschützen Sie Diaz' Mãnner bei der Übergabe.\n\n[COL4_2]\nIch weiß nicht, Sir!\n\n[COL4_5]\nSir, zu Befehl, Sir!\n\n[COL4_10]\nGehen wir ein paar Donuts essen.\n\n[COL4_16]\nFahrzeug wird weggeschafft, Sir!\n\n[COL4_25]\nSelbstzerstörung des Fahrzeugs eingeleitet!\n\n[COL5_6]\nMercedes - dieses Kind bringt mich noch ins Grab.\n\n[COL5_8]\nVerdammte Bande!\n\n[COL5_5]\nNehmt das, Franzosenschweine!\n\n[CNT2_1]\nMacht ihn fertig!\n\n[CNT2_2]\nHol die Platten!\n\n[CNT2_3]\nBeschütze den Kurier!\n\n[FINKILL]\nOk, Jungs, macht ihn fertig!\n\n[FIN_1A]\nKomm her, du hinterhãltiger Dreckskerl!\n\n[FIN_1B]\nJetzt bist du fãllig, du mieser Verrãter!\n\n[FIN_1C]\nDas wird dein letzter 'Dance', Lance Vance!\n\n[FIN_2B]\nAch, wirklich?\n\n[FIN_2C]\nDer dumme Spruch war schon im Kindergarten alt!\n\n[FIN_3]\nKeiner da, um dich rauszuhauen, diesmal, hã, Tommy?\n\n[FIN_4]\nDu bist am Ende, Tommy.\n\n[FIN_5]\nDu hast dich auf die falsche Seite geschlagen, Lance...\n\n[FIN_6]\nSonny ist oben am Safe mit MEINEM Geld...\n\n[FIN_10]\nSonny? SONNY! Jetzt bist du fãllig!\n\n[FIN_11A]\nDu hast mir 15 Jahre gestohlen, Sonny.\n\n[FIN_11B]\nUnd das wirst du mir jetzt büßen!\n\n[FIN_12A]\nDu kapierst es immer noch nicht, oder?\n\n[FIN_12B]\nDein Arsch gehört mir, Tommy.\n\n[FIN_12C]\nDiese 15 Jahre hast du anstelle von mir abgesessen!\n\n[FIN_13]\nSchnappt ihn euch. Er hat nie was begriffen.\n\n[RACES_4]\n3\n\n[RACES_5]\n2\n\n[RACES_6]\n1\n\n[RACES_7]\nLOS!\n\n[RACES_9]\nZeit: ~1~:~1~\n\n[RACES]\nZEIT:\n\n[RACES17]\nNeue Bestzeit: ~1~:~1~\n\n[RACES18]\nPREISGELD: $~1~\n\n[RACES20]\nNeue Bestzeit: ~1~:0~1~\n\n[RACES21]\nZeit: ~1~:0~1~\n\n[RCH1_1]\n~g~Benutze den ferngesteuerten Helikopter, den RC Raider, um die Checkpoints zu PASSIEREN.\n\n[RCH1_2]\n~g~Die CHECKPOINTS sind überall auf dem Flughafen verteilt.\n\n[RCH1_3]\n~g~Du hast ~c~8 MINUTEN~g~, um alle ~c~20 zu passieren!\n\n[RCH1_5]\nZeit\n\n[RCRC1_2]\n~g~Begib dich zur Startlinie!\n\n[RCRC1_4]\n~g~3\n\n[RCRC1_5]\n~g~2\n\n[RCRC1_6]\n~g~1\n\n[RCRC1_7]\n~g~LOS!\n\n[RCRC1_8]\n~g~Absolvierte Zeit: ~1~ Sekunden\n\n[RCPL1_1]\n~g~Liefere dir mit 3 anderen RC Barons ein CHECKPOINT-RENNEN.\n\n[RCPL1_2]\n~g~Du musst durch die ~o~MITTLERE MARKIERUNG ~g~hindurch, um einen Checkpoint zu passieren.\n\n[RCPL1_3]\n~g~Begib dich zur Startlinie!\n\n[ICC1_O]\nWas ist denn in Sie gefahren?\n\n[FEA_2SP]\n2 Boxen\n\n[FEA_4SP]\nMehr als 2 Boxen\n\n[FEA_EAR]\nKopfhörer\n\n[FEA_NAH]\nKEINE AUDIO HARDWARE\n\n[FET_APP]\nÜBERNEHMEN\n\n[FES_SKN]\nSKIN-NAME\n\n[FES_DAT]\nDATUM\n\n[FES_SET]\nSkin verwenden\n\n[FET_DEF]\nStandard wiederherst.\n\n[FESZ_QZ]\nDieses Spiel wirklich speichern?\n\n[FES_SCG]\nLaufendes Spiel speichern?\n\n[FES_LCG]\nSpiel laden und weiterspielen?\n\n[FEC_FIR]\nFeuern\n\n[FEC_NWE]\nNãchste Waffe\n\n[FEC_PWE]\nVorherige Waffe\n\n[FEC_FOR]\nVorwãrts\n\n[FEC_BAC]\nRückwãrts\n\n[FEC_LEF]\nLinks\n\n[FEC_RIG]\nRechts\n\n[FEC_ZIN]\nHeranzoomen\n\n[FEC_ZOT]\nHinauszoomen\n\n[FEC_EEX]\nEin-/Aussteigen\n\n[FEC_RAD]\nRadio\n\n[FEC_SUB]\nSpezialmission\n\n[FEC_CMR]\nBlickwinkel ãndern\n\n[FEC_JMP]\nSpringen\n\n[FEC_SPN]\nSprinten\n\n[FEC_HND]\nHandbremse\n\n[FEC_LOL]\nNach links sehen\n\n[FEC_LOR]\nNach rechts sehen\n\n[FEC_NTR]\nNãchstes Ziel\n\n[FEC_PTT]\nVorheriges Ziel\n\n[FEC_LBA]\nNach hinten sehen\n\n[FEC_CEN]\nKamera zentrieren\n\n[FET_CCN]\nClassic\n\n[FET_SCN]\nStandard\n\n[FET_CFT]\nZU FUSS\n\n[FET_CCR]\nIN FAHRZEUG\n\n[FET_CAC]\nAKTION\n\n[FEC_IBT]\n-\n\n[FEC_MXO]\nMXB1\n\n[FEC_MXT]\nMXB2\n\n[FEC_UNB]\nNICHT BEL.\n\n[FEC_TFL]\nLinks sehen + Geschütz L\n\n[FEC_TFR]\nRechts sehen + Geschütz R\n\n[FEC_MWF]\nMAUSRAD AUFW.\n\n[FEC_MWB]\nMAUSRAD ABW.\n\n[FEC_ORR]\noder\n\n[FEC_NUS]\nNICHT VERWENDET\n\n[FEC_LUD]\nAufw. sehen\n\n[FEC_LDU]\nAbw. sehen\n\n[FEC_CMP]\nCOMBO: L+R SEHEN\n\n[LAW_1A]\nlaw_1a\n\n[LAW_1B]\nlaw_1b\n\n[LAW_2A]\nlaw_2a\n\n[LAW_2B]\nlaw_2b\n\n[FEH_STA]\nSTATISTIKEN\n\n[FEH_LOA]\nLADEN\n\n[FEH_CON]\nSTEUERUNG\n\n[FEH_AUD]\nAUDIO\n\n[FEH_DIS]\nANZEIGE\n\n[FEH_LAN]\nSPRACHE\n\n[FEH_SGA]\nNEUES SPIEL STARTEN\n\n[FEO_CON]\nController-Setup\n\n[FEO_AUD]\nAudio-Setup\n\n[FEO_DIS]\nAnzeigen-Setup\n\n[FEO_LAN]\nSprachen-Setup\n\n[FEO_PLA]\nSpieler-Setup\n\n[FEA_OUT]\nAusgabe\n\n[FEA_ST]\nStereo\n\n[FEA_DTS]\nDTS\n\n[FEA_RSS]\nRadiosender\n\n[FEA_NON]\nRADIO AUS\n\n[FEA_FM0]\nWILDSTYLE\n\n[FEA_FM1]\nFLASH FM\n\n[FEA_FM2]\nKCHAT\n\n[FEA_FM3]\nFEVER 105\n\n[FEA_FM4]\nVROCK\n\n[FEA_FM5]\nVCPR\n\n[FEA_FM7]\nEMOTION 98.3\n\n[FEA_FM8]\nWAVE 103\n\n[FED_BRI]\nHelligkeit\n\n[FED_TRA]\nUnschãrfe-FX\n\n[FED_SUB]\nUntertitel\n\n[FED_WIS]\nBreitbild\n\n[FED_POS]\nAnzeige-Position\n\n[FEP_RES]\nFortsetzen\n\n[FEP_STG]\nSpiel starten\n\n[FEP_STA]\nStatistiken\n\n[FEP_BRI]\nMissionsinfos\n\n[FEP_OPT]\nOptionen\n\n[FEP_QUI]\nSpiel beenden\n\n[FES_LOA]\nSpiel laden\n\n[FES_DEL]\nSpiel löschen\n\n[FEC_CSU]\nController-Setup\n\n[FEC_RED]\nSteuerung ãndern\n\n[FEC_MOU]\nMaus-Einstellg.\n\n[DISTGOL]\nMit Golfwagen zurückgel. Entfernung (Meilen)\n\n[DISTGOM]\nMit Golfwagen zurückgel. Entfernung (Meter)\n\n[ST_FAVR]\nLieblings-Radiosender\n\n[ST_WSTR]\nUnbeliebtester Radiosender\n\n[ST_FAVV]\nLieblingsfahrzeug\n\n[ST_STAR]\nAnzahl angehãufter Fahndungssterne\n\n[ST_HEAD]\nAnzahl Köpfe\n\n[ST_GANG]\nUnbeliebteste Gang\n\n[ST_STGN]\nAnzahl losgewordener Fahndungssterne\n\n[TYREPOP]\nZerschossene Reifen\n\n[TYRESLA]\nAufgeschlitzte Reifen\n\n[ST_BRK]\nErledigte Gegner im Chaos-Derby\n\n[ST_LTBR]\nLãngste Zeit im Chaos-Derby (Sekunden)\n\n[ST_GNG1]\nKubaner\n\n[ST_GNG2]\nHaitianer\n\n[ST_GNG3]\nMöchtegern-Gangster\n\n[ST_GNG4]\nDiaz' Gang\n\n[ST_GNG5]\nSicherheitsbeamte\n\n[ST_GNG6]\nBiker-Gang\n\n[ST_GNG7]\nVercetti-Gang\n\n[ST_GNG8]\nGolfer\n\n[FEA_FM6]\nESPANTOSO\n\n[ST_ASSI]\nAusgeführte Attentãtermissionen\n\n[DISTBIK]\nMit Motorrad zurückgel. Strecke (Meilen)\n\n[DISTBIM]\nMit Motorrad zurückgel. Strecke (Meter)\n\n[HOTEL]\nOcean View Hotel\n\n[KICK1_9]\nVERBLEIBENDE CHECKPOINTS:\n\n[FIN_B6]\nDu hast nicht genug Geld, um diese Mission zu beginnen.\n\n[TEX3_9]\n~g~Steuere den Helikopter über eine Bombe, um sie aufzunehmen.\n\n[HELP22]\nBegib dich zu dem grünen Haus-Symbol auf dem Radar.\n\n[FES_SSC]\nDaten wurden gespeichert. Weiter mit OK.\n\n[FES_DSC]\nDaten wurden gelöscht. Weiter mit OK.\n\n[FESZ_QC]\nDieses beschãdigte Spiel überschreiben?\n\n[FES_CHE]\nAchtung! Ein oder mehrere Cheats sind aktiviert, dies kann sich auf die Speicherung auswirken. Es wird empfohlen, dieses Spiel nicht zu speichern.\n\n[FET_SG]\nSPIEL SPEICHERN\n\n[FEH_BRI]\nMISSIONSINFO\n\n[FEH_MAP]\nKARTE\n\n[FEM_OK]\nOK\n\n[FEC_CRO]\nDucken\n\n[FEC_CR3]\nDucken (L3-Taste)\n\n[FEC_SMT]\nSpezialmission\n\n[FEC_SM3]\nSpezialmission (R3-Taste)\n\n[FEC_RSC]\nRadiosender\n\n[ST_PR01]\nFlieger\n\n[ST_PR02]\nLuftwaffensoldat\n\n[ST_PR03]\nGefreiter\n\n[ST_PR04]\nUnteroffizier\n\n[ST_PR05]\nLeutnant\n\n[ST_PR06]\nStabsunteroffizier\n\n[ST_PR07]\nHauptmann\n\n[ST_PR08]\nKönner\n\n[ST_PR09]\nProfi\n\n[ST_PR10]\nRoter Baron\n\n[ST_PR11]\nWildgans\n\n[ST_PR12]\nViper\n\n[ST_PR13]\nFalke\n\n[ST_PR14]\nAdler\n\n[ST_PR15]\nBlitz\n\n[ST_PR16]\nTornado\n\n[ST_PR17]\nTaifun\n\n[ST_PR18]\nLuftwaffengeneral\n\n[ST_PR19]\nAss\n\n[FET_LG]\nSPIEL LADEN\n\n[CAR_EXP]\nStraßenfahrzeuge zerstört\n\n[BOA_EXP]\nBoote zerstört\n\n[HEL_DST]\nFlugzeuge & Helikopter zerstört\n\n[STFT_01]\nSchnellste Zeit bei 'Wheels of Steels'\n\n[STFT_02]\nSchnellste Zeit bei 'Der Fahrer'\n\n[STFT_03]\nSchnellste Zeit auf Gelãndemotorradstrecke\n\n[STFT_04]\nSchnellste Zeit bei Modellflugzeug-Rennen\n\n[STFT_05]\nSchnellste Zeit mit den ferngesteuerten Autos\n\n[STFT_06]\nSchnellste Zeit bei Helikopter-Rennen\n\n[STFT_07]\nSchnellste Zeit bei 'Todeskaracho'\n\n[STFT_08]\nSchnellste Zeit bei 'Ocean Drive'\n\n[STFT_09]\nSchnellste Zeit bei 'Küsten-Rallye'\n\n[STFT_10]\nSchnellste Zeit bei 'Capital Cruise'\n\n[STFT_11]\nSchnellste Zeit bei 'Tour!'\n\n[STFT_12]\nSchnellste Zeit bei 'V.C. Endurance'\n\n[STHC_01]\nHigh-Score bei Schießstand-Mission\n\n[STHC_02]\nBeste Trefferquote am Schießstand (in Prozent)\n\n[STHC_03]\nAnzahl getãtigter Drogendeals\n\n[HELP24]\nDu kannst jetzt Auftrãge vom Colonel annehmen.\n\n[HELP25]\nDu kannst jetzt Auftrãge von Avery Carrington annehmen.\n\n[HELP29]\nAußerhalb eine Mision kannst du zu dem Bekleidungsgeschãft gehen.\n\n[HELP30]\nWenn du neue Klamotten kaufst, reduziert sich dein Fahndungslevel auf null.\n\n[ASM4_24]\nEntfernung:\n\n[RBM1_6]\n~g~Bring Mercedes und den 'Love Juice' zu der Band ins Aufnahmestudio.\n\n[RBM1_3]\nNICHT MEHR BENÖTIGT\n\n[HAM1_5]\nNICHT MEHR BENÖTIGT\n\n[RBM1_11]\nNICHT MEHR BENÖTIGT\n\n[HELP31]\nUm aus dem fahrenden Fahrzeug zu schießen, sieh zuerst mit ~k~~VEHICLE_LOOKLEFT~ oder ~k~~VEHICLE_LOOKRIGHT~ nach links oder rechts.\n\n[HELP34]\nDu brauchst eine Maschinenpistole für einen 'Drive-By'.\n\n[STRIP_1]\n~r~Nicht genug Cash, du windiger Geizhals!\n\n[EXIT_1]\n~k~~PED_SPRINT~ zum Beenden.\n\n[ASM1_B]\nIhr nãchster Auftrag klebt unter dem Telefon.\n\n[ASM1_C]\nIch habe noch mehr Arbeit, die eine eher 'zupackende' Art verlangt.\n\n[SCARF]\nApartment 3c\n\n[LAW4_10]\nReiche Manager sind Schweine!\n\n[RCH1_6]\n~g~Benutze den ferngesteuerten Helikopter, um Checkpoints überall auf dem Flughafen abzufliegen.\n\n[RCH1_9]\n~b~GESAMTZEIT: ~1~:~1~\n\n[RCH1_10]\n~b~GESAMTZEIT: ~1~:0~1~\n\n[WHEEL01]\nZWEIRAD DOPPELBONUS: $ ~1~ Distanz: ~1~.~1~m Zeit: ~1~ Sekunden\n\n[WHEEL02]\nZWEIRAD DOPPELBONUS: $ ~1~ Distanz: ~1~ Fuß Zeit: ~1~ Sekunden\n\n[WHEEL03]\nZWEIRAD BONUS: $ ~1~ Zeit: ~1~ Sekunden\n\n[WHEEL04]\nZWEIRAD BONUS: $ ~1~ Distanz: ~1~.~1~m\n\n[WHEEL05]\nZWEIRAD BONUS: $ ~1~ Distanz: ~1~ Fuß\n\n[WHEEL06]\nWHEELIE BONUS: $ ~1~ Distanz: ~1~.~1~m Zeit: ~1~ Sekunden\n\n[WHEEL07]\nWHEELIE BONUS: $ ~1~ Distanz: ~1~ Fuß Time: ~1~ Sekunden\n\n[WHEEL08]\nWHEELIE BONUS: $ ~1~ Zeit: ~1~ Sekunden\n\n[WHEEL09]\nWHEELIE BONUS: $ ~1~ Distanz: ~1~.~1~m\n\n[WHEEL10]\nWHEELIE BONUS: $ ~1~ Distanz: ~1~.~1~ Fuß\n\n[WHEEL11]\nVOLLBREMSUNGSBONUS: $ ~1~ Distanz: ~1~.~1~m Zeit: ~1~ Sekunden\n\n[WHEEL12]\nVOLLBREMSUNGSBONUS: $ ~1~ Distanz: ~1~ Fuß Zeit: ~1~ Sekunden\n\n[WHEEL13]\nVOLLBREMSUNGSBONUS: $ ~1~ Zeit: ~1~ Sekunden\n\n[WHEEL14]\nVOLLBREMSUNGSBONUS: $ ~1~ Distanz: ~1~.~1~m\n\n[WHEEL15]\nVOLLBREMSUNGSBONUS: $ ~1~ Distanz: ~1~ Fuß\n\n[ROK3_72]\nLove Fist!\n\n[ROK3_74]\nAh, seht mal, was ist das? Hey, Tommy, leg mal dieses Band ein.\n\n[POR1_19]\nHey!\n\n[DESPERA]\nDesperado\n\n[MOB_99A]\nBegib dich zu dem Fernsprecher neben dem Einkaufszentrum in Washington Beach.\n\n[MOB_98A]\nBegib dich zu dem Fernsprecher in Vice Point.\n\n[MOB_96A]\nBegib dich zu dem Fernsprecher beim Flughafen-Terminal.\n\n[MOB_95A]\nBegib dich zu dem Fernsprecher in Little Havana.\n\n[BNK1_1]\nKann ich Ihnen helfen, Sir?\n\n[BNK1_2]\nDer Typ ist verkleidet!\n\n[BNK1_3]\nEr ist verrückt geworden!\n\n[BNK1_4]\nWer zum Teufel sind Sie?\n\n[BNK1_5]\nWo ist Ihre Dienstmarke?\n\n[BNK1_6]\nDa sind sie! Feuer frei!\n\n[MOB_24A]\nHallo, spricht da Mr. Vercetti?\n\n[MOB_24B]\nJa.\n\n[MOB_24C]\nHier Cortez. Sie waren bei meiner Party.\n\n[MOB_24D]\nJa. Ich erinnere mich.\n\n[MOB_24E]\nMr. Vercetti, es war höchst unglücklich, was da bei der Abwicklung Ihres Geschãfts vorgefallen ist.\n\n[MOB_24F]\nIch weiß.\n\n[MOB_24G]\nSie sollen wissen, dass ich und meine Leute alles tun, um der Sache auf den Grund zu gehen.\n\n[MOB_24H]\nFalls Sie mit mir persönlich sprechen wollen, finden Sie mich auf dem Schiff. Guten Tag, Senor.\n\n[BNK2_6]\nDer Typ ist geisteskrank!\n\n[ANGEL]\nAngel\n\n[CUBJET]\nKubanischer Jetmax\n\n[SANDKIN]\nSandking\n\n[POLMAV]\nPolizei-Maverick\n\n[BOXVILL]\nBoxville\n\n[BENSON]\nBenson\n\n[HOTRINA]\nHotring Racer\n\n[HOTRINB]\nHotring Racer\n\n[BLOODRA]\nChaos-Derby Banger\n\n[BLOODRB]\nChaos-Derby Banger\n\n[MAFIACR]\nMafia Cruiser\n\n[COP_M2]\n'EINSATZ IN VICE CITY'\n\n[COP_M3]\n'DONNER ÜBER VICE CITY'\n\n[BNK3_2]\nIch fahre nicht für dich, niemals. Das erzãhle ich in der Therapie.\n\n[FEM_SL1]\nDatei 1 nicht vorhanden\n\n[FEM_SL2]\nDatei 2 nicht vorhanden\n\n[FEM_SL3]\nDatei 3 nicht vorhanden\n\n[FEM_SL4]\nDatei 4 nicht vorhanden\n\n[FEM_SL5]\nDatei 5 nicht vorhanden\n\n[FEM_SL6]\nDatei 6 nicht vorhanden\n\n[FEM_SL7]\nDatei 7 nicht vorhanden\n\n[FEM_SL8]\nDatei 8 nicht vorhanden\n\n[FEA_CHA]\nTonausgabe wird auf STEREO umgeschaltet. Bitte warten...\n\n[FEA_CHD]\nAchtung! Sie schalten die Tonausgabe von STEREO auf DTS um. Bitte warten...\n\n[FEI_SEL]\nAuswahl\n\n[FEI_BAC]\nZurück\n\n[FEI_RES]\nWeiter\n\n[FEI_NAV]\nNavigieren\n\n[FEI_BTX]\n/-Taste -\n\n[FEI_BTT]\n\"-Taste -\n\n[FEI_STA]\nSTART-Taste -\n\n[FEI_BTD]\n; = > < -\n\n[FEI_STO]\nStop\n\n[MOB_68A]\nTommy, Alter, ich hab eine Überraschung für dich.\n\n[MOB_68B]\nIch bin im Aufnahmestudio mit ein paar super Musikern.\n\n[MOB_68C]\nWarum kommst du nicht kurz vorbei?\n\n[MOB_68D]\nKannst dir denken, dass es sich lohnt, oder? Bis dann.\n\n[OUTFT1]\nStraße\n\n[OUTFT2]\nAbendgarderobe\n\n[OUTFT3]\nOverall\n\n[OUTFT4]\nCountry Club\n\n[OUTFT5]\nHavana\n\n[OUTFT6]\nCop\n\n[OUTFT7]\nBankrãuber\n\n[OUTFT8]\nFreizeit\n\n[OUTFT9]\nMr. Vercetti\n\n[OUTFT10]\nTrainingsanzug\n\n[OUTFT13]\nMC Tommy\n\n[CAR_AS1]\nAUTOHAUS ERWORBEN\n\n[CAR_AS2]\n~g~Sunshine Autos generiert nun bis zu $~1~ Einkünfte. Hol dir das Geld regelmãßig ab.\n\n[BUYSAVE]\n~g~Außerhalb einer Mission kannst du dein Spiel hier umsonst speichern.\n\n[BUYGARG]\n~g~Du kannst in dieser Garage auch Autos abstellen.\n\n[STRPBUY]\nPole Position Club gekauft: $ ~1~\n\n[STRP_R3]\nDrücke R3, um den Pole Position Club zu kaufen. Preis: $~1~\n\n[NBMN_R3]\nDrücke R3, um Elswanko Casa zu kaufen. Preis: $~1~\n\n[GA_4]\nAutobomben kosten $1000 pro Stück.\n\n[GA_5]\nIn deinem Wagen ist schon eine Autobombe.\n\n[GA_6] { reVC update }\nPark die Karre, mach sie durch Drücken der ~h~~k~~VEHICLE_FIREWEAPON~~w~ scharf und dann HAU AB!\n\n[GA_7] { reVC update }\nMach die Bombe mit der ~h~~k~~VEHICLE_FIREWEAPON~~w~ scharf. Dann geht sie hoch, wenn der Wagen angelassen wird.\n\n[GA_6B] { reVC update }\nPark die Karre, mach sie durch Drücken der ~h~~k~~VEHICLE_FIREWEAPON~~w~ scharf und dann HAU AB!\n\n[GA_7B] { reVC update }\nMach die Bombe mit der ~h~~k~~VEHICLE_FIREWEAPON~~w~ scharf. Dann geht sie hoch, wenn der Wagen angelassen wird.\n\n[MOB_70A]\nTommy, ich bin's, Colonel Cortez. Hören Sie, Sie sind doch ein Mann, der Dinge zu erledigen weiß.\n\n[MOB_70B]\nSie finden mich auf dem Boot.\n\n[PICK2]\n.357 in Verstecken angeliefert!\n\n[PICK3]\nKettensãgen in Verstecken angeliefert!\n\n[PICK4]\nFlammenwerfer in Verstecken angeliefert!\n\n[PICK5]\n.308 Prãzisionsgewehr in Verstecken angeliefert!\n\n[PICK6]\nMini-Kanonen in Verstecken angeliefert!\n\n[PICK7]\nRaketenwerfer in Verstecken angeliefert!\n\n[PICK8]\nSea Sparrow jetzt bei Vercetti Estate verfügbar!\n\n[PICK9]\nPanzer jetzt in Army-Kaserne verfügbar!\n\n[PICK10]\nHunter jetzt in Army-Kaserne verfügbar!\n\n[CLOTH1]\nAbendgarderobe bei Rafaels in Ocean Beach erhãltlich.\n\n[CLOTH2]\nStraßenkleidung in Verstecken angeliefert.\n\n[CLOTH3]\nOverall bei 'Tooled Up' im North Point Einkaufszentrum erhãltlich.\n\n[CLOTH4]\nCountry Club-Bekleidung beim Golf Club in Leaf Links erhãltlich.\n\n[CLOTH5]\nHavana-Outfit bei 'Little Havana Streetwear' in Little Havana erhãltlich.\n\n[CLOTH6]\nPolizeiuniform bei Polizeistation in Washington Beach erhãltlich.\n\n[CLOTH7]\nFreizeitbekleidung bei 'Gash' im North Point Einkaufszentrum erhãltlich.\n\n[CLOTH8]\nMr. Vercetti-Outfit bei 'Collar & Cuffs'in Ocean Beach erhãltlich.\n\n[CLOTH9]\nTrainingsanzug bei 'Jocksport' in Downtown erhãltlich.\n\n[CLOTH10]\nBankrãuber-Outfit beim Malibu Club in Vice Point erhãltlich.\n\n[MOB_62A]\nTommy, hier Ricardo Diaz. Ich wollte dir danken, dass du mich gerettet hast.\n\n[MOB_62B]\nIch hab den Trottel von Cortez gefragt. Er meint, du wãrst ein Mann für alle Fãlle. Komm doch mal bei mir vorbei.\n\n[MOB_62C]\nIch brauche einen Kerl wie dich. Ich hab nãmlich nur Schwachköpfe.\n\n[MOB_62D]\nNur lauter Schwachköpfe. Ich mache dich schwer reich.\n\n[GOAWAY2]\nKomm wieder, wenn du die Biker Gang-Missionen abgeschlossen hast.\n\n[COL2_9]\nDu amerikanischer Idiot! Sie sind dir hierher gefolgt!\n\n[LOADCOL]\nLade...\n\n[STFT_17]\nSchnellste Zeit bei 'PCJ Rallye'\n\n[STFT_18]\nSchnellste Zeit bei 'Krasses Gelãnde'\n\n[STFT_19]\nSchnellste Zeit bei 'Teststrecke'\n\n[NEW_REC]\nNeuer Rekord!! ~1~ Minuten und ~1~ Sekunden.\n\n[BMX_HOW]\n~g~Fahr zwei Runden auf der Gelãndemotorradstrecke. ~y~Passiere dabei ~g~die ~y~CHECKPOINTS~g~!\n\n[BMXREW1]\n~g~Jedes Mal wenn du deine bisherige Bestzeit für die zwei Runden verbesserst,\n\n[BMXREW2]\n~g~bekommst du eine noch höhere ~y~BELOHNUNG~g~!\n\n[BMXRAIN]\n~g~Sieht nach Regen aus...\n\n[ITBEG]\nAm Anfang...\n\n[NBMNBUY]\nEl Swanko Casa gekauft: $ ~1~\n\n[LNKVBUY]\nLinks View Apartment gekauft: $ ~1~\n\n[HYCOBUY]\nHyman Condo gekauft: $ ~1~\n\n[BUYGARS]\n~g~Du kannst in diesen Garagen auch Autos abstellen.\n\n[OCHEBUY]\nOcean Heights Apartment gekauft: $ ~1~\n\n[WASHBUY]\n1102 Washington Street gekauft: $ ~1~\n\n[VCPTBUY]\n3321 Vice Point gekauft: $ ~1~\n\n[HELP6_C]\nDrücke die ~h~~k~~VEHICLE_HANDBRAKE~~w~, um die Handbremse anzuziehen.\n\n[HELP2_A]\nDrücke die ~h~~k~~PED_SPRINT~~w~, um zu ~h~sprinten.\n\n[HELP4_A]\nDrücke die ~h~~k~~VEHICLE_ACCELERATE~~w~, um zu beschleunigen.\n\n[HELP5_A]\nDrücke die ~h~~k~~VEHICLE_BRAKE~~w~, um zu bremsen, oder um zurückzusetzen, wenn das Fahrzeug steht.\n\n[HELP8_A]\nDrücke die ~h~~k~~PED_SNIPER_ZOOM_IN~~w~, um an das Ziel heranzuzoomen und die ~x~/-Taste~w~,um herauszuzoomen.\n\n[PBOAT_1] { reVC update }\nDrücke die~h~ ~k~~VEHICLE_FIREWEAPON~~w~, um die Bordkanonen abzufeuern.\n\n[SEG3_4] { reVC update }\n~g~Um Bomben aufzunehmen, steuere den RC Raider einfach nahe an sie heran. Um eine abzuwerfen, drücke die ~h~~k~~VEHICLE_FIREWEAPON~~g~-Taste.\n\n[RCR1_3] { reVC update }\n~g~Wenn du diese Mission abbrechen willst, drücke die ~h~~k~~VEHICLE_FIREWEAPON~~g~, um dein Auto zu sprengen.\n\n[HELP32] { reVC update }\nDann feuere mit der ~h~~k~~VEHICLE_FIREWEAPON~.\n\n[HELP33] { reVC update }\nDann feuere mit der ~h~~k~~VEHICLE_FIREWEAPON~.\n\n[TTUTOR]\nDrücke die ~h~~k~~TOGGLE_SUBMISSIONS~~w~, um Taxi-Missionen an- oder abzuschalten.\n\n[TTUTOR2]\nDrücke die ~h~~k~~TOGGLE_SUBMISSIONS~~w~, um Taxi-Missionen an- oder abzuschalten.\n\n[FTUTOR]\nDrücke die ~h~~k~~TOGGLE_SUBMISSIONS~~w~, um Feuerwehrwagen-Missionen an- oder abzuschalten.\n\n[FTUTOR2]\nDrücke die ~h~~k~~TOGGLE_SUBMISSIONS~~w~, um Feuerwehrwagen-Missionen an- oder abzuschalten.\n\n[CTUTOR]\nDrücke die ~h~~k~~TOGGLE_SUBMISSIONS~~w~, um Bürgerwehr-Missionen zu aktivieren oder zu deaktivieren.\n\n[CTUTOR2]\nDrücke die ~h~~k~~TOGGLE_SUBMISSIONS~~w~, um Bürgerwehr-Missionen zu aktivieren oder zu deaktivieren.\n\n[HELP8_B]\nDrücke die~h~ ~k~~PED_SNIPER_ZOOM_IN~~w~, um ~h~an das Ziel heranzuzoomen ~w~und die~h~ ~k~~PED_SNIPER_ZOOM_OUT~~w~, um ~h~herauszuzoomen~w~.\n\n[ATUTOR3]\nDrücke die ~h~~k~~TOGGLE_SUBMISSIONS~~w~, um Krankenwagen-Missionen an- oder abzuschalten.\n\n[GUN_H1]\n~w~Drück die~h~ ~k~~PED_SPRINT~~w~, um zu kaufen. ~w~Drück die~h~ ~k~~VEHICLE_ENTER_EXIT~~w~, um zu gehen.\n\n[PU_CF3] { reVC update }\nDrück die ~h~~k~~PED_ANSWER_PHONE~~w~, um die augenblickliche Waffe in diesem Slot auszutauschen.\n\n[PU_CF4] { reVC update }\nDrück die ~h~~k~~PED_ANSWER_PHONE~~w~, um die augenblickliche Waffe in diesem Slot auszutauschen.\n\n[HELP9_B]\nDrücke die~h~ ~k~~PED_FIREWEAPON~~w~, um das Prãzisionsgewehr ~h~abzufeuern~w~.\n\n[HELP37]\nWenn du doch nicht in ein Auto einsteigen willst, das du im Begriff bist, zu klauen, drück die ~h~~k~~PED_SPRINT~.\n\n[HELP6_A]\nDrücke die ~h~~k~~VEHICLE_HANDBRAKE~~w~, um die Handbremse anzuziehen.\n\n[HELP6_D]\nDrücke die ~h~~k~~VEHICLE_HANDBRAKE~~w~, um die Handbremse anzuziehen.\n\n[HELP26]\nDrücke die ~h~~k~~VEHICLE_ENTER_EXIT~~w~, um in ein Fahrzeug ein- oder auszusteigen.\n\n[HELP27]\nDrücke ~h~~k~~VEHICLE_TURRETUP~~w~ oder ~h~~k~~VEHICLE_TURRETDOWN~~w~ um dein Gewicht auf einem Motorrad zu verlagern.\n\n[HELP28]\nDrücke ~h~~k~~VEHICLE_TURRETUP~~w~ oder ~h~~k~~VEHICLE_TURRETDOWN~~w~ um dein Gewicht auf einem Motorrad zu verlagern.\n\n[HELP35]\nBenutze die ~h~~k~~GO_LEFT~~w~ oder ~h~~k~~GO_RIGHT~~w~ um das Fahrzeug zu steuern.\n\n[HELP36]\nBenutze die ~h~~k~~GO_LEFT~~w~ oder ~h~~k~~GO_RIGHT~~w~ um das Fahrzeug zu steuern.\n\n[HELP42]\nFolge dem ~q~rosa Symbol~w~, um zum Hotel zu kommen.\n\n[HELP19]\nStell dich in die ~q~rosa Markierung~w~, um weiterzumachen.\n\n[HELP1]\nHalte in der Mitte der ~q~rosa Markierung.\n\n[HELP12]\nGeh ins Zentrum der ~q~rosa Markierung~w~, um eine Mission zu starten.\n\n[SEG3_6]\n~g~Um eine Zielzone zu treffen, musst du die Bombe innerhalb der ~q~rosa Markierung~g~ abwerfen. Die Reihenfolge spielt dabei keine Rolle.\n\n[S_PROMP]\nAußerhalb einer Mission kannst du dein Spiel speichern, indem du das ~h~Cassetten-Symbol aufnimmst.\n\n[HELP16]\nGeh durch die Eingangstür, um das ~h~Ocean View Hotel~w~ zu betreten.\n\n[HELP43]\n~g~Begib dich zum ~h~Ocean View Hotel~g~ am Ocean Drive.\n\n[HELI_F1]\n~r~Heli-Ceckpoint-Mission abgebrochen!\n\n[AMMUHLP]\nWenn du Waffen brauchst, geh zu ~h~AmmuNation~w~. Das ~h~Pistolensymbol~w~ auf dem Radar zeigt dir den Weg.\n\n[HELI_1]\nDowntown Heli-Checkpoint\n\n[HELI_2]\nOcean Beach Heli-Checkpoint\n\n[HELI_3]\nVice Point Heli-Checkpoint\n\n[HELI_4]\nLittle Haiti Heli-Checkpoint\n\n[FST_MFR]\nLieblings-Radiosender\n\n[FST_LFR]\nUnbeliebtester Radiosender\n\n[FEI_HOL]\nHalten\n\n[FEI_ZOO]\nZoom\n\n[FEI_BTR]\n> < -\n\n[FEI_NA]\nNicht verfügbar\n\n[MESA]\nMesa Grande\n\n[STRP_NO]\nZurzeit kannst du die Stripper-Bar nicht kaufen. Komm spãter wieder.\n\n[CHSE]\nVERFOLGUNGSJAGD\n\n[NBMN_L]\nDrücke die ~h~~k~~PED_ANSWER_PHONE~~w~, um El Swanko Casa zu kaufen. Preis: $~1~\n\n[NBMN_T]\nDrücke die ~h~~k~~PED_ANSWER_PHONE~~w~, um El Swanko Casa zu kaufen. Preis: $~1~\n\n[NBMN_C]\nDrücke die ~h~~k~~PED_ANSWER_PHONE~~w~, um El Swanko Casa zu kaufen. Preis: $~1~\n\n[LNKV_L]\nDrücke die ~h~~k~~PED_ANSWER_PHONE~~w~, um das Links View Apartment zu kaufen. Preis: $~1~\n\n[LNKV_T]\nDrücke die ~h~~k~~PED_ANSWER_PHONE~~w~, um das Links View Apartment zu kaufen. Preis: $~1~\n\n[LNKV_C]\nDrücke die ~h~~k~~PED_ANSWER_PHONE~~w~, um das Links View Apartment zu kaufen. Preis: $~1~\n\n[HYCO_L]\nDrücke die ~h~~k~~PED_ANSWER_PHONE~~w~, um das Hyman Condo zu kaufen. Preis: $~1~\n\n[HYCO_T]\nDrücke die ~h~~k~~PED_ANSWER_PHONE~~w~, um das Hyman Condo zu kaufen. Preis: $~1~\n\n[HYCO_C]\nDrücke die ~h~~k~~PED_ANSWER_PHONE~~w~, um das Hyman Condo zu kaufen. Preis: $~1~\n\n[OCHE_L]\nDrücke die ~h~~k~~PED_ANSWER_PHONE~~w~, um das Ocean Heights Apartment zu kaufen. Preis: $~1~\n\n[OCHE_T]\nDrücke die ~h~~k~~PED_ANSWER_PHONE~~w~, um das Ocean Heights Apartment zu kaufen. Preis: $~1~\n\n[OCHE_C]\nDrücke die ~h~~k~~PED_ANSWER_PHONE~~w~, um das Ocean Heights Apartment zu kaufen. Preis: $~1~\n\n[WASH_L]\nDrücke die ~h~~k~~PED_ANSWER_PHONE~~w~, um 1102 Washington Street zu kaufen. Preis: $~1~\n\n[WASH_T]\nDrücke die ~h~~k~~PED_ANSWER_PHONE~~w~, um 1102 Washington Street zu kaufen. Preis: $~1~\n\n[WASH_C]\nDrücke die ~h~~k~~PED_ANSWER_PHONE~~w~, um 1102 Washington Street zu kaufen. Preis: $~1~\n\n[VCPT_L]\nDrücke die ~h~~k~~PED_ANSWER_PHONE~~w~, um 3321 Vice Point zu kaufen. Preis: $~1~\n\n[VCPT_T]\nDrücke die ~h~~k~~PED_ANSWER_PHONE~~w~, um 3321 Vice Point zu kaufen. Preis: $~1~\n\n[VCPT_C]\nDrücke die ~h~~k~~PED_ANSWER_PHONE~~w~, um 3321 Vice Point zu kaufen. Preis: $~1~\n\n[PRNT_L]\nDrücke die ~h~~k~~PED_ANSWER_PHONE~~w~, um die Druckerei zu kaufen. Preis: $~1~\n\n[PRNT_T]\nDrücke die ~h~~k~~PED_ANSWER_PHONE~~w~, um die Druckerei zu kaufen. Preis: $~1~\n\n[PRNT_C]\nDrücke die ~h~~k~~PED_ANSWER_PHONE~~w~, um die Druckerei zu kaufen. Preis: $~1~\n\n[CAR_L]\nDrücke die ~h~~k~~PED_ANSWER_PHONE~~w~, um das Autohaus zu kaufen. Preis: $~1~\n\n[CAR_T]\nDrücke die ~h~~k~~PED_ANSWER_PHONE~~w~, um das Autohaus zu kaufen. Preis: $~1~\n\n[CAR_C]\nDrücke die ~h~~k~~PED_ANSWER_PHONE~~w~, um das Autohaus zu kaufen. Preis: $~1~\n\n[PORN_L]\nDrücke die ~h~~k~~PED_ANSWER_PHONE~~w~, um das Filmstudio zu kaufen. Preis: $~1~\n\n[PORN_T]\nDrücke die ~h~~k~~PED_ANSWER_PHONE~~w~, um das Filmstudio zu kaufen. Preis: $~1~\n\n[PORN_C]\nDrücke die ~h~~k~~PED_ANSWER_PHONE~~w~, um das Filmstudio zu kaufen. Preis: $~1~\n\n[ICE_L]\nDrücke die ~h~~k~~PED_ANSWER_PHONE~~w~, um die Eiscremefabrik zu kaufen. Preis: $~1~\n\n[ICE_T]\nDrücke die ~h~~k~~PED_ANSWER_PHONE~~w~, um die Eiscremefabrik zu kaufen. Preis: $~1~\n\n[ICE_C]\nDrücke die ~h~~k~~PED_ANSWER_PHONE~~w~, um die Eiscremefabrik zu kaufen. Preis: $~1~\n\n[TAXI_L]\nDrücke die ~h~~k~~PED_ANSWER_PHONE~~w~, um das Taxiunternehmen zu kaufen. Preis: $~1~\n\n[TAXI_T]\nDrücke die ~h~~k~~PED_ANSWER_PHONE~~w~, um das Taxiunternehmen zu kaufen. Preis: $~1~\n\n[TAXI_C]\nDrücke die ~h~~k~~PED_ANSWER_PHONE~~w~, um das Taxiunternehmen zu kaufen. Preis: $~1~\n\n[BANK_L]\nDrücke die ~h~~k~~PED_ANSWER_PHONE~~w~, um den Malibu Club zu kaufen. Preis: $~1~\n\n[BANK_T]\nDrücke die ~h~~k~~PED_ANSWER_PHONE~~w~, um den Malibu Club zu kaufen. Preis: $~1~\n\n[BANK_C]\nDrücke die ~h~~k~~PED_ANSWER_PHONE~~w~, um den Malibu Club zu kaufen. Preis: $~1~\n\n[BOAT_L]\nDrücke die ~h~~k~~PED_ANSWER_PHONE~~w~, um die Bootswerft zu kaufen. Preis: $~1~\n\n[BOAT_T]\nDrücke die ~h~~k~~PED_ANSWER_PHONE~~w~, um die Bootswerft zu kaufen. Preis: $~1~\n\n[BOAT_C]\nDrücke die ~h~~k~~PED_ANSWER_PHONE~~w~, um die Bootswerft zu kaufen. Preis: $~1~\n\n[STRP_L]\nDrücke die ~h~~k~~PED_ANSWER_PHONE~~w~, um den Pole Position Club zu kaufen. Preis: $~1~\n\n[STRP_T]\nDrücke die ~h~~k~~PED_ANSWER_PHONE~~w~, um den Pole Position Club zu kaufen. Preis: $~1~\n\n[STRP_C]\nDrücke die ~h~~k~~PED_ANSWER_PHONE~~w~, um den Pole Position Club zu kaufen. Preis: $~1~\n\n[STOCK]\n~r~nicht vorrãtig\n\n[HELP14]\nUm das Büro des Anwalts zu finden, folge dem ~h~'L'~w~ auf dem Radar.\n\n[BOAT_AS]\n~g~Die Bootswerft generiert nun bis zu $~1~ Einkünfte. Hol dir das Geld regelmãßig ab.\n\n[BOAT_A2]\nBOOTSWERFT-MISSIONEN ERFÜLLT\n\n[BOAT_N]\nCheckpoint Charlie\n\n[BOAT_P]\n~g~Sammle die Pãckchen ein, ehe die Zeit um ist.\n\n[FEI_R1B]\nR1- \\ R2-Taste -\n\n[HELP9_A]\nDrücke die ~h~~k~~PED_FIREWEAPON~~w~-Taste, um das Prãzisionsgewehr abzufeuern.\n\n[HELP21]\nDrücke die ~h~~k~~VEHICLE_ENTER_EXIT~~w~-Taste, um in ein Fahrzeug ein- oder auszusteigen.\n\n[CREAM]\nStoff-Auslieferung\n\n[UMBERTO]\nCafé Robina\n\n[PU_CF1]\nDrück die ~h~~k~~PED_ANSWER_PHONE~~w~-Taste, um diese Waffe aufzunehmen. Falls du schon eine Waffe von diesem Typ hast, wird sie durch die neue ersetzt.\n\n[FED_RDM]\nKARTE & SYMBOLE\n\n[FEC_ILU]\nKamera invertieren :\n\n[NITRO]\nAlle Taxis haben jetzt einen Jumper-Turbo! Du musst nur die Taste für die Hupe drücken.\n\n[RATNG53]\nWindei\n\n[RATNG54]\nNiete\n\n[RATNG55]\nHacker\n\n[RATNG56]\nMogelpaket\n\n[RATNG57]\nTotaler Lügner\n\n[STHC_04]\nHigh-Score beim Fußball-Hochhalten\n\n[STHC_05]\nBestes Hotring-Resultat\n\n[STFT_13]\nSchnellste Zeit bei Downtown Heli-Checkpoint\n\n[STFT_14]\nSchnellste Zeit Ocean Beach Heli-Checkpoint\n\n[STFT_15]\nSchnellste Zeit bei Vice Point Heli-Checkpoint\n\n[STFT_16]\nSchnellste Zeit bei Little Haiti Heli-Checkpoint\n\n[STFT_21]\nSchnellste Zeit bei Hotring\n\n[STFT_22]\nSchnellste Rundenzeit bei Hotring\n\n[STFT_20]\nSchnellste Zeit bei 'Pylonen-Rallye'\n\n[HELP44]\nHalte in der ~q~rosa Markierung.\n\n[HELP45]\nDrücke die ~h~~k~~PED_DUCK~~w~ um dich zu ducken. Dadurch erhöht sich die Treffsicherheit der Waffen, die du hãltst.\n\n[RCR1_5]\nRC Bandit-Rennen\n\n[RCPL1_7]\nRC Baron-Rennen\n\n[RCH1_11]\nRC Raider Checkpoint-Jagd\n\n[FEA_CTD]\nAchtung! Für diesen Modus muss DTS-kompatible Hardware angeschlosen sein. Fortfahren?\n\n[FEM_STE]\nAUF STEREO EINSTELLEN\n\n[FEM_UDY]\nAUF DTS EINSTELLEN\n\n[GREET]\nGrüße aus...\n\n[LANCE_1]\nHey, Mann, fahr vorsichtiger!\n\n[LANCE_2]\nHey, pass doch auf, was du machst!\n\n[LANCE_3]\nHey, wo fahren wir jetzt hin?\n\n[LANCE_4]\nWas machen wir jetzt?\n\n[LAW4_15]\nMehr Geld!\n\n[MERC_5]\nSchönes Auto, Mr. Vercetti.\n\n[MERC_26]\nSCHNELLER, SCHNELLER, SCHNELLER!\n\n[MERC_27]\nVorsichtig, Tommy, ich hab mir erst letzten Monat die Nase korrigieren lassen.\n\n[MERC_28]\nTommy, fahr vorsichtig.\n\n[MERC_29]\nTommy, fahr langsamer.\n\n[MERC_30]\nTommy, bring jemand anders um, aber bitte nicht mich.\n\n[MERC_31]\nTommy, Baby, bring mich nicht um!\n\n[MERC_32]\nTommy, ich bin froh, dass du dieses Auto gestohlen hast!\n\n[MERC_40]\nIch hatte so viel Spaß.\n\n[MERC_43]\nAdios, mein Engel.\n\n[MERC_44]\nUnd mach schön weiter Bodybuilding, hörst du?\n\n[MERC_45]\nCiao, mein Hübscher.\n\n[COL5_17]\nOh, Gott, sie haben einen Helikopter!\n\n[COL5_18]\nSchießt den Helikopter ab!\n\n[COL5_19]\nTommy, schießen Sie den Helikopter ab!\n\n[COL5_20]\nDa kommt er wieder! Schießt den Helikopter ab!\n\n[COL5_21]\nSieh dir diesen riesigen Helikopter an!\n\n[COL5_22]\nDa kommt er wieder!\n\n[FEA_DSM]\nAchtung! Dieses Spiel ist auf DTS-Tonausgabe eingestellt. Dazu muss DTS-kompatible Hardware angeschlossen sein. Bitte wãhlen Sie, ob Sie mit DTS oder STEREO-Tonausgabe fortfahren wollen.\n\n[STFT_23]\nSchnellste Zeit bei Checkpoint Carlie\n\n[HELP50]\nDrücke die ~h~~k~~PED_ANSWER_PHONE~~w~-Taste, um die Spielerfigur von hinten zu sehen.\n\n[HELP51]\nDrücke die ~h~~k~~PED_ANSWER_PHONE~~w~-Taste, um die Spielerfigur von hinten zu sehen.\n\n[HELP52]\nDrücke die ~h~~k~~PED_ANSWER_PHONE~~w~-Taste, um die Spielerfigur von hinten zu sehen.\n\n[HELP53]\nBenutze die ~h~~k~~PED_CYCLE_WEAPON_LEFT~~w~-Taste und die ~h~~k~~PED_CYCLE_WEAPON_RIGHT~~w~-Taste, um zwischen deinen Waffen zu wechseln.\n\n[HELP46]\nEs gibt acht verschiedene Waffentypen.\n\n[HELP47]\nDu kannst von jedem Waffentyp immer nur eine bei dir tragen - also einen Typ Pistole, einen Typ Schrotflinte, usw.\n\n[HELP54]\n~w~Preis: $~1~ ~r~Deine augenblickliche Waffe wird ersetzt, wenn du diese kaufst.\n\n[HELP2A2]\nDrücke die ~h~~k~~PED_SPRINT~~w~-Taste, um zu ~h~sprinten.\n\n[HLPSN_A]\nDas Prãzisionsgewehr ermöglicht dir, an dein Ziel heranzuzoomen und auf größere Distanz mit hoher Genauigkeit zu schießen.\n\n[HLPSN_B]\nHalte die~h~ ~k~~PED_LOCK_TARGET~~w~-Taste gedrückt, um mit dem Prãzisionsgewehr zu ~h~zielen~w~.\n\n[HLPSN_C]\nHalte die~h~ ~k~~PED_LOCK_TARGET~~w~-Taste gedrückt, um mit dem Prãzisionsgewehr zu ~h~zielen~w~.\n\n[HLPSN_D]\nDrücke die ~h~~k~~PED_SNIPER_ZOOM_IN~~w~-Taste, um ~h~an das Ziel heranzuzoomen ~w~und die~h~ ~k~~PED_SNIPER_ZOOM_OUT~~w~,um ~h~herauszuzoomen~w~.\n\n[HLPSN_E]\nDrücke die ~h~~k~~PED_FIREWEAPON~~w~-Taste, um das Prãzisionsgewehr ~h~abzufeuern~w~.\n\n[HLPSN_F]\nDrücke die ~h~~k~~PED_FIREWEAPON~~w~-Taste, um das Prãzisionsgewehr ~h~abzufeuern~w~.\n\n[HLPSN_G]\nDrücke die ~h~~k~~PED_FIREWEAPON~~w~-Taste, um das Prãzisionsgewehr ~h~abzufeuern~w~.\n\n[PLANE_H]\nBenutze die ~h~~k~~VEHICLE_ACCELERATE~~w~-Taste, um zu beschleunigen. Links bzw. Rechts für Richtungswechsel.\n\n[PLANE_4] { reVC update }\n{Benutze die ~h~~k~~VEHICLE_ACCELERATE~~w~-Taste, um zu beschleunigen. Links bzw. Rechts für Richtungswechsel.}\nBenutze den rechten Analog-Stick, um zu beschleunigen. Ziehe den linken Analog-Stick, um zu steigen oder drücke ihn nach vorn, um zu sinken. Links bzw. Rechts für Richtungswechsel.\n\n[HELP55]\nDrücke die ~h~~k~~PED_FIREWEAPON~~w~-Taste, um den Küchenchef anzugreifen.\n\n[STPR_8]\nPole Position Club\n\n[STPR_9]\n3321 Vice Point\n\n[STPR_10]\nLinks View Apartment\n\n[STPR_11]\nEl Swanko Casa\n\n[STPR_12]\n1102 Washington Street\n\n[STPR_13]\nOcean Heights Apartment\n\n[STPR_14]\nSkumole Shack\n\n[STPR_15]\nHyman Condo\n\n[RCCANX]\n~r~Flugzeug-Mission abgebrochen.\n\n[CLT_HL2]\nWenn du neue Kleider aufnimmst, werden dadurch Fahndungslevel von einem bis zwei Sternen annulliert.\n\n[CRED009]\nMISSION DESIGN\n\n[CRED359]\nLEE JOHNSON\n\n[CRED360]\nHENDRIK LESSER\n\n[CRED361]\nPASQUALE STACCHIOTTI\n\n[CRED362]\nENRIQUE FERNANDEZ\n\n[CRED363]\nPAUL BYERS\n\n[CRED364]\nMIKE EMENY\n\n[CRED365]\nROB DUNKIN\n\n[CRED366]\nCHARLIE KINLOCH\n\n[CRED367]\nKEVIN HOBSON\n\n[CRED368]\nJIM CREE\n\n[MOB_66A]\nTommy, Tommy, Tommy, wieso bist du wieder zurückgekommen?\n\n[MOB_66B]\nIch hab dir doch gesagt, wir wollen dich hier nicht mehr sehen.\n\n[MOB_67A]\nTommy, ich glaube, du solltest dich hier nicht mehr blicken lassen, hörst du?\n\n[MOB_67B]\nDie Haitianer sind nicht sehr gut auf dich zu sprechen.\n\n[MOB_18A]\nTommy, hier Paul. Wie geht's, Alter? Hey, ich dachte mir, das musst du hören...\n\n[MOB_18B]\nEcht der Hammer. Du glaubst nicht, was mir für 'ne Puppe über den Weg gelaufen ist.\n\n[MOB_18C]\n'ne Bordsteinschwalbe, oder sowas. Unten in Little Havana.\n\n[MOB_18D]\nSagt, sie heißt Mercedes oder so ãhnlich.\n\n[MOB_18E]\nWahnsinn, Alter. Die Puppe musst du dir geben.\n\n[MOB_18F]\nDa würde 'nen Toter Hormonkoller kriegen. Sie sagt, ich wãr der beste, den sie je hatte.\n\n[MOB_18G]\nHalt die Augen nach ihr offen. Bis dann.\n\n[MOB_72A]\nTommy, ich bin's, Lance. Du hãltst jetzt mal den Rand, Tommy, ich hab nãmlich keine Zeit für Geschwãtz.\n\n[MOB_72B]\nInteressiert mich auch nicht, was du zu sagen hast. Warum auch? Ich bin dir doch sowieso scheißegal, stimmt's?\n\n[MOB_72C]\nDu solltest dich mehr um mich kümmern. Mir einen fairen Anteil geben. Weißt du...\n\n[MOB_72D]\nTommy... hör mal, Mann, es tut mir leid. Nur...\n\n[MOB_72E]\nich werd schon mein Leben lang immer nur von oben herab behandelt, wie ein kleines Kind.\n\n[MOB_72F]\nMein Bruder hat das auch immer gemacht. Bitte, mein Alter, mach du das nicht.\n\n[MOB_72G]\nIch muss auflegen.\n\n[MOB_63A]\nTommy, hier Earnest. Earnest Kelly.\n\n[MOB_63B]\nWie geht's?\n\n[MOB_63C]\nGanz gut. Werd zum Laufen 'nen Stock brauchen, müsste aber bald wieder arbeiten können.\n\n[MOB_63D]\nGut.\n\n[MOB_63E]\nIch hab das mit Lance gehört. Was für ein Schwein, hã?\n\n[MOB_63F]\nJa.\n\n[MOB_63G]\nTrau nie einem Mann, der im Pyjama auf der Straße herumlãuft. Gut, dass du ihn erledigt hast. Ich hoffe, es war nicht kurz und schmerzlos.\n\n[MOB_63H]\nEher nicht. Ich hãtte nur nicht gedacht, dass er so einer ist...\n\n[MOB_63I]\nTommy, für einen wildgewordenen Irren bist du ziemlich naiv. Ich bin bald wieder an der Arbeit, dann bring ich dir mal ein paar Sachen übers Leben bei, ok?\n\n[MOB_63J]\nLass dir Zeit, Earnest. Pass auf dich auf.\n\n[MOB_16A]\nTommy, hier Paul. Wie geht's, mein Freund?\n\n[MOB_16B]\nWas willst du, Paul? Ich brauch keine getürkten Designer-Klamotten.\n\n[MOB_16C]\nSehr witzig. Du weißt, dass ich mit getürkter Ware nichts am Hut habe. Wollte nur hören, ob ich nicht 'ne Rolle in einem von deinen Filmen kriegen könnte.\n\n[MOB_16D]\nIn England habe ich damals viel einschlãgiges Zeug gedreht. Ich hab mehr zu bieten als du, mein Alter.\n\n[MOB_16E]\nPaul, danke für das Angebot. Ich komm auf dich zurück.\n\n[MOB_16F]\nLass mich nicht hãngen. Denk dran, was ich alles für dich getan habe.\n\n[MOB_16G]\nDas versuch ich ja grade zu vergessen.\n\n[MOB_17A]\nTommy Vercetti. Wie geht's, großer Meister? Man hört so einiges über dich. Bist jetzt 'ne große Nummer in der Stadt, hã?\n\n[MOB_17B]\nPaul, du bist betrunken.\n\n[MOB_17C]\nNein, du Trottel, ich bin nicht betrunken. Hab mir nur ein paar Ladungen Stoff gegeben, war seit ein paar Tagen nicht im Bett.\n\n[MOB_17D]\nUnd du brauchst mich nicht dumm anzureden. Ich bin nicht irgendwer. Wer hat dir denn in dieser Stadt den Weg geebnet? Ich!\n\n[MOB_17F]\nTatsãchlich?\n\n[MOB_17G]\nKomm mir nicht so! Ich hab dich mit den ganzen Leuten bekanntgemacht. Hab dir gezeigt, wie der Hase lãuft, hab alles mögliche für dich getan, und so dankst du es mir?!\n\n[MOB_17H]\nDu ignorierst mich. Du gibst mir keine Chance, mitzumischen, nach allem, was ich für dich getan habe! Hãltst du mich für einen Schwachkopf?\n\n[MOB_17I]\nPaul, reg dich ab. Ich hatte viel zu tun. Sei kein Idiot.\n\n[MOB_17J]\nIch bin kein Idiot. Das haben sie schon im Jugendknast gesagt. Wenn du Ãrger haben willst, Freundchen, den kannst du haben!\n\n[MOB_17K]\nTommy, bitte! Du warst meine große Hoffnung. Bitte, mach dich nicht lustig über mich!\n\n[MOB_17L]\nPaul, schlaf mal 'ne Runde. Im Ernst.\n\n[MOB_73A]\nTommy, hier Steve.\n\n[MOB_73B]\nHey, Steve.\n\n[MOB_73C]\nHey, aber wie! Du bist ein Genie! Ich bin ein Genie! Sie lieben uns alle. Wir brechen alle Rekorde, mein Alter.\n\n[MOB_73D]\nUns winken ganz große Filmpreise. Jetzt kann ich endlich meinen alten Herrn ins Heim stecken und ihm sagen, er soll die Klappe halten.\n\n[MOB_73E]\nÃh, das ist cool, Steve.\n\n[MOB_73F]\nCool? Mann, das ist heiß! Heiß! H.E.I.ß! Er hat nie an mich geglaubt. Hat immer gedacht, ich wãre kein Künstler, und jetzt hab ich's geschafft!\n\n[MOB_73G]\nIch bin der größte Porno-Regisseur aller Zeiten, mein Freund. Wollte dir nur sagen, es ist mir eine Freude, dich kennengelernt zu haben.\n\n[MOB_73H]\nDanke, Steve.\n\n[MOB_73I]\nIch liebe dich, Baby. Bleib bloß genau so wie du bist, ok?\n\n[MOB_73J]\nWerd's mir merken. Ciao, Steve.\n\n[BOLLOX]\nDrücke die ~o~R1~w~-Taste, um eine Bombe abzuwerfen. Drücke die ~t~\"~w~-Taste zum Abbrechen.\n\n[BRID_OP]\nSturmwarnung vorüber. Alle Brücken zum Festland sind wieder geöffnet.\n\n[BRID_CL]\nSturmwarnung: Alle Brücken zum Festland sind gesperrt.\n\n[LG_38]\nZiel\n\n[ASSET_C]\nPOLE POSITION ERWORBEN!\n\n[ASSET_D]\n~g~Der Pole Position Club sorgt nun für ein Einkommen von bis zu $~1~ pro Tag. Hol dir dein Geld regelmãssig!\n\n[ST_WHEE]\nLãngste 'Wheelie' Zeit (sekunden)\n\n[ST_STOP]\nLãngste 'Stoppie' Zeit (sekunden)\n\n[ST_2WHE]\nLãngste 2 Rad Zeit (sekunden)\n\n[ST_WHED]\nLãngste 'Wheelie' Distanz (m)\n\n[ST_STOD]\nLãngste 'Stoppie' Distanz (m)\n\n[ST_2WHD]\nLãngste 2 Rad Distanz (m)\n\n[OUTFT11]\nTrainer\n\n[OUTFT12]\nFrankie\n\n[RELOAD]\n~g~Du hast die schnell Nachladefãhigkeit gewonnen!\n\n[APACHE]\nHunter zur Heli Landeplattform am Ocean Beach geliefert.\n\n[CRED369]\nJOHN MCCARDLE\n\n[CRED370]\nDAVID MURDOCH\n\n[CRED371]\nCHRIS BROWN\n\n[CRED372]\nPAUL GREEN\n\n[CRED373]\nKYLE MILNE\n\n[CUNTY]\nNeue Kleider wurden zum Vercetti Estate geliefert!\n\n[GOODBOY]\n$50 'Guter Bürger' Bonus!\n\n[NEWCONT]\nNeuer Kontaktpunkt am Jachthafen am Ocean Beach!!\n\n[FIRELVL]\nFeuerwehr-Mission Level ~1~\n\n[HELP56]\nDrücke die ~h~~k~~CAMERA_CHANGE_VIEW_ALL_SITUATIONS~~w~-Taste, um den Blickwinkel zu ãndern.\n\n[HELP57]\nDrücke die ~h~~k~~CAMERA_CHANGE_VIEW_ALL_SITUATIONS~~w~-Taste, um den Blickwinkel zu ãndern.\n\n[HELP58]\nBeim Zielen kann durch Drücken der ~h~~k~~PED_CYCLE_TARGET_LEFT~~w~-Taste zwischen Zielen hin- und her gewechselt werden.\n\n[HELP59]\nBeim Zielen kann durch Drücken der ~h~~k~~PED_CYCLE_TARGET_LEFT~~w~-Taste zwischen Zielen hin- und her gewechselt werden.\n\n[HELP60]\nWenn du wãhrend eines Autodiebstahls die ~h~~k~~PED_SPRINT~ ~w~-Taste drückst, steigst du nicht in das Fahrzeug ein.\n\n[HELP61]\nDu hast jetzt unbegrenzt Munition und doppelte Health für alle Fahrzeuge.\n\n[CRED374]\nKEVIN YUN\n\n[CRED375]\nERICK COBBS\n\n[CRED376]\nRANDY BLAKE\n\n[CRED377]\nBRANDON LIM\n\n[CRED378]\nBRANDON FENOL\n\n[CRED379]\nMICHAEL MANOLE\n\n[CRED380]\nALETHEIA SIMONSON\n\n[CRED381]\nJOHN JANSEN\n\n[FEC_LB1]\nSchau\n\n[FEC_LB2]\nnach hinten\n\n[FEC_LB3]\nNach hinten schauen\n\n[FEC_R3]\n(R3-Taste)\n\n[FEC_PED]\nSteuerung zu Fuß\n\n[FEC_VEH]\nSteuerung in Fahrzeug\n\n[FEC_FPR]\nSteuerung für First-Person\n\n[FEC_CMM]\nAllgemeine Steuerung\n\n[FEC_PWL]\nNach links\n\n[FEC_PWR]\nNach rechts\n\n[FEC_PWF]\nVorwãrts gehen\n\n[FEC_PWT]\nAuf Kamera zugehen\n\n[FEC_PLB]\nNach hinten schauen\n\n[FEC_PFR]\nWaffe abfeuern\n\n[FEC_CLE]\nEine Waffe nach links\n\n[FEC_CRI]\nEine Waffe nach rechts\n\n[FEC_LKT]\nZiel fixieren\n\n[FEC_PJP]\nFußgãnger springen\n\n[FEC_PSP]\nFußgãnger sprinten\n\n[FEC_PSH]\nFußgãnger schießen\n\n[FEC_TLF]\nEin Ziel nach links\n\n[FEC_TRG]\nEin Ziel nach rechts\n\n[FEC_CCM]\nKamera hinter Spieler zentrieren\n\n[FEC_SZI]\nMit Prãzisionsgewehr heranzoomen\n\n[FEC_SZO]\nMit Prãzisionsgewehr herauszoomen\n\n[FEC_LKL]\nFirst-Person nach links schauen\n\n[FEC_LRT]\nFirst-Person nach rechts schauen\n\n[FEC_LUP]\nFirst-Person nach oben schauen\n\n[FEC_LDN]\nFirst-Person nach unten schauen\n\n[FEC_LBH]\nAus Fahrzeug nach hinten schauen\n\n[FEC_LLF]\nAus Fahrzeug nach links schauen\n\n[FEC_LRG]\nAus Fahrzeug nach rechts schauen\n\n[FEC_HRN]\nHupe\n\n[FEC_HBR]\nHandbremse\n\n[FEC_ACL]\nGas geben\n\n[FEC_BRK]\nBremsen\n\n[FEC_TSM]\nSpezialmissionen An/Aus\n\n[FEC_CRD]\nRadiosender wechseln\n\n[FEC_ENT]\nIn Fahrzeug Ein-/Aussteigen\n\n[FEC_WPN]\nWaffe abfeuern\n\n[FEC_PAS]\nPause\n\n[FEC_FPO]\nFirst Person Weapons Toggle.\n\n[FEC_SMS]\nMauszeiger An/Aus\n\n[FEC_CMS]\nBlickwinkel wechseln.\n\n[FEC_TSS]\nScreen Shot\n\n[FEC_DBG]\nDebug-Menü\n\n[FEC_TGD]\nMit Pad zwischen Spiel- u. Debug-Modus wechseln\n\n[FEC_TDO]\nDebug-Kamera Aus\n\n[FEC_IVH]\nMaus horizontal invertieren\n\n[FEC_MSL]\nMAUSTASTE L\n\n[FEC_MSM]\nMAUSTASTE M\n\n[FEC_MSR]\nMAUSTASTE R\n\n[FEC_QUE]\n???\n\n[FEC_TWO]\nNur zwei Tastaturtasten erlaubt\n\n[FEC_OMS]\nNur eine Maustaste erlaubt\n\n[FEC_OJS]\nNur ein Joystick-Button pro Aktion erlaubt\n\n[FEC_PTL]\n\"Ziel fixieren\" u. \"Waffenauswahl links\" gleichzeitig drücken.\n\n[FEC_PTR]\n\"Ziel fixieren\" u. \"Waffenauswahl rechts\" gleichzeitig drücken.\n\n[FEC_LBC]\n\"Nach links schauen\" u. \"Nach rechts schauen\" gleichzeitig drücken.\n\n[FEC_JBO]\nJOY ~1~\n\n[FEC_WAR]\nAchtung!\n\n[FEC_OKK]\nOK\n\n[FEC_DLF]\nLöschen fehlgeschlagen.\n\n[FEC_SVU]\nSpeichern fehlgeschlagen.\n\n[FEC_LUN]\nLaden fehlgeschlagen. Datei beschãdigt. Bitte löschen.\n\n[FEC_PAD]\nGamepad\n\n[FEC_JOY]\nJoystick\n\n[FES_CSA]\nWãhlen Sie eine Skin aus der Liste aus:\n\n[FET_HRD]\nSTANDARDEINSTLLG. WIEDERHERGESTELLT\n\n[FET_MST]\nMAUSSTEUERUNG\n\n[FEC_STR]\nNUM STERN\n\n[FET_MIG]\nLINKS,RECHTS,MAUSRAD ZUR EINSTLLG.\n\n[FET_CIG]\nRÜCKT. ZUM LÖSCHEN - LMT,RETURN ZUM ÃNDERN\n\n[FET_DSN]\nStandard-Player Skin.bmp\n\n[FET_RSO]\nORIGINAL-EINSTELLG. WIEDERHERGESTELLT\n\n[FET_RSC]\nHARDWARE NICHT VERFÜGBAR - ORIGINAL-EINSTELLG. WIEDERHERGESTELLT\n\n[FEA_3DH]\nAUDIO HARDWARE\n\n[FEA_SPK]\nBOXEN KONFIGURATION\n\n[FEM_LOD]\nDISTANZ-DARSTELLG.\n\n[FEM_VSC]\nFRAME SYNC\n\n[FEM_FRM]\nFRAME LIMITER\n\n[FEM_MM]\nHAUPTMENÜ\n\n[FED_RES]\nBILDSCHIRMAUFLSG.\n\n[FET_CTL]\nCONTROLLER-SETUP\n\n[FET_OPT]\nOPTIONEN\n\n[FEC_MSH]\nMAUSEMPFINDLICHKEIT\n\n[FEC_IVV]\nMAUS VERTIKAL INVERTIEREN\n\n[FET_MTI]\nMAUS STEURUNGSKONFIG.\n\n[FEC_FNC]\nF~1~\n\n[FEC_IRT]\nEINFG\n\n[FEC_DLL]\nENTF\n\n[FEC_HME]\nPOS1\n\n[FEC_END]\nENDE\n\n[FEC_PGU]\nBILD AUF\n\n[FEC_PGD]\nBILD AB\n\n[FEC_UPA]\nAUF\n\n[FEC_DWA]\nAB\n\n[FEC_LFA]\nLINKS\n\n[FEC_RFA]\nRECHTS\n\n[FEC_NUM]\nNUM\n\n[FEC_NMN]\nNUM~1~\n\n[FEC_FWS]\nNUM /\n\n[FEC_PLS]\nNUM +\n\n[FEC_MIN]\nNUM -\n\n[FEC_DOT]\nNUM ,\n\n[FEC_NLK]\nNUMLOCK\n\n[FEC_ETR]\nENT\n\n[FEC_SLK]\nROLLEN\n\n[FEC_PSB]\nUNTBR\n\n[FEC_BSP]\nRÜCKT.\n\n[FEC_TAB]\nTAB\n\n[FEC_CLK]\nCAPSLOCK\n\n[FEC_RTN]\nRET\n\n[FEC_LSF]\nLUMSCHALT\n\n[FEC_RSF]\nRUMSCHALT\n\n[FEC_LCT]\nLSTRG\n\n[FEC_RCT]\nRSTRG\n\n[FEC_LAL]\nLALT\n\n[FEC_RAL]\nRALT\n\n[FEC_LWD]\nLWIN\n\n[FEC_RWD]\nRWIN\n\n[FEC_WRC]\nWINKLICK\n\n[FEC_SPC]\nLEERT.\n\n[WIN_TTL]\nGTA VC\n\n[WIN_95]\nGTA VC lãuft nicht unter Windows 95\n\n[WIN_DX]\nGTA VC benötigt mind. DirectX Version 8.1\n\n[FET_EIG]\nKANN DIESER AKTION KEINE STEUERUNG ZUWEISEN\n\n[FET_DAM]\nDYNAMISCHE AKUSTIK\n\n[FEQ_SRE]\nWirklich beenden? Alle Daten seit dem letzten Speichern werden verlorengehen. Weiter?\n\n[FEQ_SRW]\nSpiel wirklich beenden?\n\n[FET_QG]\nSPIEL BEENDEN\n\n[FEN_STA]\nSPIEL STARTEN\n\n[REPLAY]\nWIEDERHOLUNG\n\n[FET_PAU]\nPAUSENMENÜ\n\n[FEC_ANS]\nAktion\n\n[CVT_MSG]\nTexturen werden in optimales Format für Ihre Grafikkarte konvertiert\n\n[FEC_SFT]\nUMSCHALT\n\n[CVT_ERR]\nKein Platz mehr auf der Festplatte. Bitte schaffen Sie Speicherplatz, bevor Sie fortfahren. ESC zum Abbrechen.\n\n[FEH_VMP]\nKARTE ANSEHEN\n\n[FES_DEE]\nLöschen fehlgeschlagen! Bitte noch einmal versuchen.\n\n[FES_CMP]\nSpeichern fehlgeschlagen! Bitte noch einmal versuchen.\n\n[FESZ_WR]\nSpiel wird gespeichert. Bitte warten...\n\n[FELD_WR]\nSpiel wird geladen. Bitte warten...\n\n[FEDL_WR]\nGespeichertes Spiel wird gelöscht. Bitte warten...\n\n[PCRESRT]\nNeues Spiel wird gestartet. Bitte warten...\n\n[FET_STI]\nStandard-Steuerung\n\n[FET_CTI]\nClassic-Steuerung\n\n[FET_PS]\nSPIELER-SKIN SETUP\n\n[FEH_NA]\nOPTION NICHT VERFÜGBAR\n\n[FEH_MPH]\nMAUS, CURSOR ZUM BEWEGEN - BILD AUFW., BILD ABW., MAUSRAD ZUM ZOOMEN, L - LEGENDE\n\n[FEA_MP3]\nMP3 PLAYER\n\n[NO_PCCD]\nBitte legen Sie die GTA Vice City Disk ein, oder drücken Sie ESC zum Abbrechen\n\n[FEH_SSA]\nCURSOR ZUM BEWEGEN - S UM ZU SPEICHERN\n\n[FES_CMI]\nLETZTE ERFÜLLTE MISSION\n\n[FET_STS]\nSTATISTIKEN GESPEICHERT IN 'STATS.HTML' + 'STATS.TXT'\n\n[WIN_VDM]\nNicht genug verfügbarer Grafikspeicher für GTA Vice City vorhanden\n\n[FEC_ERI]\nFehler! Eine oder mehrere Aktionen haben keine Tastenbelegungen. Bitte alle Aktionen belegen.\n\n[FEC_TFU]\nGeschütz + nach hinten neigen\n\n[FEC_TFD]\nGeschütz + nach vorne neigen\n\n[FET_RIG]\nWÃHLEN SIE EINE NEUE TASTENBELEGUNG FÜR DIESE AKTION\n\n[FEA_NM3]\nKEINE MP3-DATEIEN GEFUNDEN\n\n[FEA_MPB]\nMP3 LAUTSTÃRKE-BOOST\n\n[FEA_MUS]\nLAUTSTÃRKE MUSIK\n\n[FEA_SFX]\nLAUTSTÃRKE SFX\n\n[FEA_ADP]\nAUTOMATISCHE HARDWARE ERKENNUNG\n\n{=================================== MISSION TABLE AMBULAE ===================================}\n\n[A_COMP1:AMBULAE]\nKrankenwagen-Missionen abgeschlossen: $ ~1~\n\n[ATUTOR2:AMBULAE]\n~g~Fahre die Patienten VORSICHTIG in die Klinik. Jede Erschütterung verringert ihre Überlebenschancen.\n\n[A_FULL:AMBULAE]\n~r~Krankenwagen voll!!\n\n[A_FAIL2:AMBULAE]\n~r~Deine Bummelei war tödlich für den Patienten!\n\n[A_FAIL3:AMBULAE]\n~r~Der Patient ist tot!!\n\n[A_PASS:AMBULAE]\nGerettet!\n\n[A_COMP2:AMBULAE]\nDu ermüdest nie!\n\n[A_CANC:AMBULAE]\n~r~Krankenwagen-Mission abgebrochen!\n\n[A_COMP3:AMBULAE]\nKrankenwagen-Missionen abgeschlossen! Du wirst beim Rennen nie ermüden!\n\n[ALEVEL:AMBULAE]\nKrankenwagen-Mission Level ~1~\n\n[A_FAIL1:AMBULAE]\nKrankenwagen-Mission beendet.\n\n[A_SAVES:AMBULAE]\nGERETTETE MENSCHEN: ~1~\n\n{=================================== MISSION TABLE ASSIN1 ===================================}\n\n[ASM1_5:ASSIN1]\n~r~Er hat seine Lieferungen abgeschlossen!\n\n[ASM1_6:ASSIN1]\nWeitere Lieferungen:\n\n[ASM1_7:ASSIN1]\n~g~Carl Pearson, Pizza-Lieferant. Schalte ihn aus, bevor er seine Lieferungen abschließt.\n\n[ASM1_A:ASSIN1]\nMr. Teal, Ihre Hilfe bei der Beseitigung der Landeier war ãußerst wertvoll. Ich habe noch mehr Arbeit, die eine eher 'zupackende' Art verlangt.\n\n[ASM1_D:ASSIN1]\nMr. Teal, Ihre Hilfe bei der Beseitigung der Landeier war ãußerst wertvoll.\n\n{=================================== MISSION TABLE ASSIN2 ===================================}\n\n[ASM2_1:ASSIN2]\n~g~Mrs. Dawson verlãsst bald den Juwelier in Vice Point. Schalte sie aus. Es muss wie ein Autounfall aussehen.\n\n[ASM2_3:ASSIN2]\n~g~Das Fahrzeug wird explodieren! Hau ab!\n\n[ASM2_4:ASSIN2]\n~r~Du hast ihr Auto beschãdigt, obwohl sie nicht drin saß! Jetzt wird sie nicht einsteigen!\n\n[ASM2_5:ASSIN2]\n~r~Sie ist entwischt!\n\n[ASM2_6:ASSIN2]\n~r~Du warst zu nah am Unfallort!\n\n[ASM2_7:ASSIN2]\n~g~Keine Waffen! Es soll wie ein Unfall aussehen! Drãnge sie stattdessen von der Fahrbahn!\n\n[ASM2_8:ASSIN2]\n~g~Das ganze muss wie ein Unfall aussehen. Benutze keine Waffen.\n\n[ASM2_9:ASSIN2]\nDu brauchst einen fahrbaren Untersatz für diesen Job.\n\n[ASM2_10:ASSIN2]\n~g~Wenn ihr Auto in Flammen aufgeht, entferne dich so weit wie möglich von der Unfallstelle.\n\n[ASM2_11:ASSIN2]\nHilfe!\n\n[ASM2_12:ASSIN2]\nHilf mir doch jemand!\n\n[ASM2_13:ASSIN2]\nOh Gott!\n\n[ASM2_A:ASSIN2]\nMein Kompliment für die gute Arbeit, Mr. Teal. Mein Kunde war sehr zufrieden.\n\n[ASM2_2:ASSIN2]\nHealth:\n\n{=================================== MISSION TABLE ASSIN3 ===================================}\n\n[ASM3_11:ASSIN3]\nZEIT:\n\n[ASM3_C:ASSIN3]\nEine europãische Gang plant einen Überfall auf eine Bank in Vice City. Meinen Arbeitgebern wãre sehr daran gelegen, dass das nicht passiert.\n\n[ASM3_D:ASSIN3]\nAlle Mitglieder der Gang haben eine Tarnung, solange sie sich hier in Vice City aufhalten. Manche haben Jobs, andere geben sich als Touristen aus.\n\n[ASM3_E:ASSIN3]\nInfos über alle Zielpersonen und ihre wahrscheinlichen Aufenthaltsorte kleben unter dem Telefon.\n\n[ASM3_14:ASSIN3]\n~g~Dick Tanner hãlt sich bei DBP Security am Ocean Drive auf.\n\n[ASM3_15:ASSIN3]\n~g~Marc Hammond und Franco Carter halten sich in der Nãhe des Juwelierladens in Vice Point auf.\n\n[ASM3_16:ASSIN3]\n~g~Nick Kong hãlt sich in der Nãhe von Washington Beach auf.\n\n[ASM3_18:ASSIN3]\n~g~Geh nicht zu nahe an deine Zielperson heran, sonst entdeckt sie dich und du musst hinter ihr herjagen.\n\n[ASM3_19:ASSIN3]\n~g~Er hat dich gesehen! Schalte ihn aus!\n\n[ASM3_20:ASSIN3]\n~g~Sie haben dich gesehen! Schalte alle beide aus!\n\n[ASM3_21:ASSIN3]\n~r~Du hast nicht alle Mitglieder der Gang rechtzeitig erledigt!\n\n[ASM3_22:ASSIN3]\n~g~Geh nicht zu nahe an deine Zielpersonen heran, sonst entdecken sie dich und versuchen zu fliehen.\n\n[ASM3_12:ASSIN3]\n~g~In der Nãhe sind einige Waffen für dich deponiert worden, falls du sie brauchen solltest. Du hast ~h~9 MINUTEN~g~, um alle Gang-Mitglieder auszuschalten.\n\n[ASM3_13:ASSIN3]\n~g~Mike Griffin arbeitet an einer Plakatwand in Washington.\n\n[ASM3_17:ASSIN3]\n~g~Charlie Dilson fãhrt mit dem Motorrad in Washington herum.\n\n{=================================== MISSION TABLE ASSIN4 ===================================}\n\n[ASM4_10:ASSIN4]\n~g~Du warst anscheinend nicht der einzige, der hinter dem Aktenkoffer her war. Bring ihn schnell ins Ammu-Nation!\n\n[ASM4_12:ASSIN4]\nDistanz:\n\n[ASM4_15:ASSIN4]\n~g~Nimm das Prãzisionsgewehr zu deiner Rechten.\n\n[ASM4_16:ASSIN4]\n~g~Behalte die Frau auf der Empore im Auge. Sie wird die Rolltreppe hinuntergehen und die Zielperson nach der Uhrzeit fragen.\n\n[ASM4_17:ASSIN4]\n~g~Schalte die Zielperson aus, NACHDEM die Frau mit ihr gesprochen hat. Aber erledige nicht die Frau.\n\n[ASM4_18:ASSIN4]\n~g~Wenn die Zielperson ausgeschaltet ist, nimm ihren Aktenkoffer und bringe ihn zum Ammu-Nation in Downtown.\n\n[ASM4_19:ASSIN4]\n~g~Halte Abstand von der Zielperson. Die Entfernungs-Anzeige rechts oben am Bildschirm zeigt an, wie nahe du an der Zielperson bist.\n\n[ASM4_20:ASSIN4]\n~g~Lass den Anzeigebalken nicht an den Anschlag geraten, sonst sieht dich die Zielperson.\n\n[ASM4_21:ASSIN4]\n~g~Schnapp dir den Aktenkoffer!\n\n[ASM4_22:ASSIN4]\n~g~Bring den Aktenkoffer zum Ammu-Nation in Downtown.\n\n[ASM4_23:ASSIN4]\n~g~Er hat dich entdeckt und versucht zu fliehen. Erledige ihn und schnapp dir den Aktenkoffer!\n\n[ASM4_25:ASSIN4]\n~r~Du hast die Frau ausgeschaltet, du Idiot!\n\n[ASM4_26:ASSIN4]\n~r~Die Zielperson hat das Flugzeug bestiegen!\n\n[ASM4_27:ASSIN4]\n~r~Die Zielperson hat dich gesehen! Du hãttest Abstand halten sollen!\n\n[ASM4_28:ASSIN4]\n~r~Die Zielperson hat dich gesehen! Er hat gehört, wie du geschossen hast!\n\n[ASM4_29:ASSIN4]\n~r~Schalte ihn erst aus, wenn er mit der Frau gesprochen hat!\n\n[ASM4_A:ASSIN4]\nEs wird Zeit für dickere Brocken, Mr. Teal. Unter dem Busch zu Ihrer Rechten ist ein Gewehr.\n\n[ASM4_B:ASSIN4]\nBehalten Sie die Frau auf der Empore über dem Check-In im Auge. Sie wird durch die Menge gehen und jemanden nach der Uhrzeit fragen.\n\n[ASM4_C:ASSIN4]\nSie müssen die betreffende Person ausschalten, ihren Aktenkoffer nehmen und ihn zu der Adresse, die unter dem Telefon klebt, bringen.\n\n{=================================== MISSION TABLE ASSIN5 ===================================}\n\n[ASM5_A:ASSIN5]\nAuf dem Dach der Cherry Popper-Eiscremefabrik findet eine Übergabe von wertvoller Ware statt.\n\n[ASM5_B:ASSIN5]\nErledigen Sie alle Beteiligten, klauen Sie die Ware und bringen Sie sie zum Heliport am Flughafen.\n\n[ASM5_C:ASSIN5]\nLinks von Ihnen ist ein Tor, das zur Rückseite der Fabrik führt.\n\n[ASM5_1:ASSIN5]\n~g~Geh auf das Gelãnde hinter der Cherry Popper-Eiscremefabrik und dann auf das Dach, wo der Deal abgewickelt wird.\n\n[ASM5_2:ASSIN5]\n~g~Schnapp dir die Ware und bring sie zum Heliport am Flughafen.\n\n[ASM5_3:ASSIN5]\n~g~Bring die Ware zum Heliport am Flughafen!\n\n{=================================== MISSION TABLE BANKJ1 ===================================}\n\n[WANTED1:BANKJ1]\n~g~Schüttle die Cops ab. Verringere deinen Fahndungslevel.\n\n[BJM1_A:BANKJ1]\nTommy! Hey, Tommy, sieh mal, das ist super! Ich hab eine Minibar einbauen lassen!\n\n[BJM1_B:BANKJ1]\nWir haben unten eine ausgewachsene Bar, Ken.\n\n[BJM1_C:BANKJ1]\nJa, ja, wie auch immer. Tja, ich hab die Tafel besorgt, die du haben wolltest.\n\n[BJM1_D:BANKJ1]\nAh, das ist der Lohn des Jurastudiums: Die Fãhigkeit, Anweisungen auszuführen.\n\n[BJM1_E:BANKJ1]\nAlso, ich brauche einen Safeknacker.\n\n[BJM1_F:BANKJ1]\nOh, ok, mal nachdenken...Safeknacker, Safeknacker...Ich hab's! Du wirst begeistert sein!\n\n[BJM1_G:BANKJ1]\nAah, nicht dieser Schwachkopf. Der sitzt doch.\n\n[BJM1_H:BANKJ1]\nWo sitzt er denn?\n\n[BJM1_I:BANKJ1]\nIn einer Zelle in einem Polizeirevier. Er wartet auf seine Verlegung.\n\n[BJM1_J:BANKJ1]\nIch glaube fast, er kommt auf Bewãhrung raus...\n\n[BJM1_1:BANKJ1]\n~g~Befreie Cam Jones aus der Haft!\n\n[BJM1_3:BANKJ1]\n~g~In der Umkleide des Reviers findest du etwas Nützliches.\n\n[BJM1_21:BANKJ1]\n~g~Die Key Card zu den Zellen findet sich im Obergeschoss des Reviers.\n\n[BNK1_7:BANKJ1]\nCam Jones?\n\n[BNK1_8:BANKJ1]\nIch hol dich hier raus.\n\n[BNK1_10:BANKJ1]\nJa, der bin ich...\n\n[BNK1_11:BANKJ1]\nGanz wie du meinst!\n\n[BNK1_13:BANKJ1]\nIch ziehe einen Job durch, und du bist mein Safeknacker.\n\n[BNK1_14:BANKJ1]\nBesser als in 'ner Zelle zu verrotten!\n\n[BJM1_22:BANKJ1]\n~g~Bring Cam nach Hause!\n\n[BJM1_23:BANKJ1]\n~g~Du brauchst zunãchst die Magnetkarte für die Tür!\n\n[BNK1_12:BANKJ1]\nHãng die Bullen ab und bring mich nach Hause!\n\n[BJM1_20:BANKJ1]\nDie Waffe weg oder es passiert was!\n\n[BJM1_5:BANKJ1]\nZutritt ab hier nur für befugtes Personal.\n\n[BJM1_2:BANKJ1]\n~r~Du solltest Cam die Freiheit bringen, nicht den Tod!\n\n[BJM1_4:BANKJ1]\nEr ist bewaffnet! Erledigt ihn!\n\n{=================================== MISSION TABLE BANKJ2 ===================================}\n\n[BJM2_A:BANKJ2]\nWir brauchen einen Überfall-Experten. Kennt ihr einen?\n\n[BJM2_B:BANKJ2]\nHey, Tommy, Tommy, Tommy, das Zeug bringt dich nach vorn, Mann.\n\n[BJM2_C:BANKJ2]\nWoooOOOooo!\n\n[BJM2_D:BANKJ2]\nIch könnte dein Experte sein! Überfall! Überfall!\n\n[BJM2_E:BANKJ2]\nDu bist kein Experte, du bist ein Idiot.\n\n[BJM2_F:BANKJ2]\nMach dir 'nen Drink und halt die Klappe.\n\n[BJM2_G:BANKJ2]\nHey, aus dem Weg!\n\n[BJM2_H:BANKJ2]\nCam, was meinst du?\n\n[BJM2_I:BANKJ2]\nTja, der beste Schütze in der Stadt ist ein Kerl namens Cassidy.\n\n[BJM2_J:BANKJ2]\nAch ja?\n\n[BJM2_K:BANKJ2]\nJa. Soldat, oder wenigstens hãlt er sich dafür.\n\n[BJM2_L:BANKJ2]\nIch bezweifle, dass er je bei der Army war, aber er kann mit der Knarre umgehen.\n\n[BJM2_M:BANKJ2]\nWahrscheinlich ist er in der Schießanlage.\n\n[BJM2_2A:BANKJ2]\nBist du Phil Cassidy?\n\n[BJM2_2B:BANKJ2]\nWieso?\n\n[BJM2_2C:BANKJ2]\nIch suche einen, der mit der Kanone umgehen kann. Was ich hier so sehe, überzeugt mich nicht.\n\n[BJM2_2D:BANKJ2]\nJungchen, ich schieße dir auf 25 Meter eine Fliege vom Kopf.\n\n[BJM2_2E:BANKJ2]\nAch wirklich?\n\n[BJM2_2F:BANKJ2]\nJa. Hab ich bei der Army gelernt.\n\n[BJM2_2G:BANKJ2]\nIst Fliegen-Schießen so beliebt in der Army? Gut, dass ich keine Steuern zahle.\n\n[BJM2_2H:BANKJ2]\nSollte das witzig sein, Jungchen?\n\n[BJM2_2I:BANKJ2]\nHa ha ha ha ha!\n\n[BJM2_2J:BANKJ2]\nLass uns schießen.\n\n[BJM2_1:BANKJ2]\n~g~Begib dich nach Downtown ins Ammu-Nation und sprich mit Phil Cassidy.\n\n[BJM2_3:BANKJ2]\nTREFFERQUOTE: ~1~%\n\n[BJM2_4:BANKJ2]\nPUNKTE RUNDE EINS: ~1~\n\n[BJM2_6:BANKJ2]\nPUNKTE RUNDE ZWEI: ~1~\n\n[BJM2_7:BANKJ2]\nGESAMTPUNKTZAHL FÜR DAS SCHIESSEN: ~1~\n\n[BJM2_9:BANKJ2]\n~g~Begib dich zum Startpunkt für Runde Zwei.\n\n[BJM2_11:BANKJ2]\n~r~Phil ist erledigt!\n\n[BJM2_12:BANKJ2]\n~r~Einer der Schützen ist erledigt!\n\n[BJM2_14:BANKJ2]\n~g~Begib dich zum nãchsten Areal!\n\n[BJM2_15:BANKJ2]\nPUNKTE:\n\n[BJM2_17:BANKJ2]\n~g~Sprich mit Phil.\n\n[BJM2_18:BANKJ2]\nZU SCHLAGEN:\n\n[BJM2_19:BANKJ2]\n~g~Triff innerhalb des Zeitlimits so viele Ziele wie du kannst!\n\n[BJM2_22:BANKJ2]\n~r~Du hast den Schießstand verlassen!\n\n[BJM2_23:BANKJ2]\n~g~Wenn du den Schießstand wãhrend des Wettbewerbs verlãsst, ist die Mission gescheitert.\n\n[BJM2_24:BANKJ2]\n~g~Das nahegelegenste Ziel bringt 1 Punkt.\n\n[BJM2_25:BANKJ2]\n~g~Das mittlere Ziel bringt 2 Punkte.\n\n[BJM2_27:BANKJ2]\n~g~Alle Ziele dieser Runde bringen 1 Punkt.\n\n[BNK2_2:BANKJ2]\nZIELEN 3-2-1 FEUER!\n\n[BNK2_3:BANKJ2]\nAREAL KLAR!\n\n[BNK2_4:BANKJ2]\nHuuuiii!\n\n[BNK2_5:BANKJ2]\nDer trãfe nicht mal ein Scheunentor.\n\n[BNK2_7:BANKJ2]\nAlso, was ist jetzt, hilfst du mir bei dem Job?\n\n[BNK2_8:BANKJ2]\nJungchen, so wie du schießt, würde ich dich sogar heiraten.\n\n[BNK2_9A:BANKJ2]\nJunge, deine Sprüche und deine Hirngespinste kannst du dir sonst wohin stecken. Du bist ein lausiger Schütze.\n\n[BNK2_9B:BANKJ2]\nDu bist ein lausiger Schütze.\n\n[BJM2_28:BANKJ2]\nPUNKTE RUNDE DREI: ~1~\n\n[BJM2_20:BANKJ2]\n~g~Geht dir die ~w~Zeit ~g~oder die ~w~Munition ~g~aus, ist die Runde beendet!\n\n[BJM2_26:BANKJ2]\n~g~Das am weitesten entfernte Ziel bringt 3 Punkte.\n\n[BNK2_1:BANKJ2]\nSCHARFE MUNITION\n\n[RANGE_1:BANKJ2]\nPUNKTZAHL SCHIESS-RUNDE:~1~\n\n[BJM2_2:BANKJ2]\n~g~Um die Runde zu beenden, drücke die ~h~~k~~PED_JUMPING~.\n\n[BJM2_N:BANKJ2]\nNur die Ruhe.\n\n{=================================== MISSION TABLE BANKJ3 ===================================}\n\n[BJM3_A:BANKJ3]\nLangsam fügt sich alles sehr schön zusammen hier.\n\n[BJM3_B:BANKJ3]\nWas ist der Plan, Tommy? Was geht ab, Amigo?\n\n[BJM3_C:BANKJ3]\nDer Plan ist, dass du dich wie ein Vollidiot benimmst. Wir brauchen einen Fahrer.\n\n[BJM3_D:BANKJ3]\nTommy, ich mach's. Ich kann fahren.\n\n[BJM3_E:BANKJ3]\nNimm Hilary, Boss, nicht diesen Labersack von einem Rechtverdreher.\n\n[BJM3_F:BANKJ3]\nHilary ist der beste. So schnell wie den hast noch keinen fahren sehen. Ich rufe ihn mal an.\n\n[BJM3_G:BANKJ3]\nHey, Hil, hier Phil. Wie lãuft's? Nein, sag nichts. Dazu haben wir spãter Zeit. Tust du mir einen Gefallen?\n\n[BJM3_H:BANKJ3]\nIch hab hier einen Typ aus dem Norden. Nein, ich glaub, er war nicht beim Militãr. Aber er braucht einen Fahrer.\n\n[BJM3_I:BANKJ3]\nFür einen Job. Ok, verstehe.\n\n[BJM3_J:BANKJ3]\nWas hat er gesagt?\n\n[BJM3_K:BANKJ3]\nEr macht's. Kein Problem. Na ja, ein kleines vielleicht: Er leidet unter Verlustãngsten.\n\n[BJM3_L:BANKJ3]\nEr arbeitet anscheinend nicht für Leute, die ihn nicht schlagen können. Hat was mit seiner Mutter zu tun.\n\n[BJM3_M:BANKJ3]\nJedenfalls will er erst ein Rennen gegen dich fahren. Er wartet draußen auf dich.\n\n[BJM3_2A:BANKJ3]\nBist du Tommy? Klar bist du Tommy, ich meine,\n\n[BJM3_2B:BANKJ3]\nwieso sollte sonst einer mit mir reden wollen?\n\n[BJM3_2C:BANKJ3]\nOk. Das ganze lãuft so ab:\n\n[BJM3_2D:BANKJ3]\nIch fahre für dich, WENN und NUR WENN du selbst anstãndig fãhrst.\n\n[BJM3_2E:BANKJ3]\nVerlierst du mich, verzeihe ich dir das nie.\n\n[BJM3_2:BANKJ3]\nHilary ist erledigt!\n\n[BJM3_4:BANKJ3]\n~g~Du brauchst ein Auto, um mitzumachen.\n\n[BNK3_1:BANKJ3]\nOk, ich fahre für dich. Aber bitte, behandle mich schlecht.\n\n[BNK3_3A:BANKJ3]\nIllegales Straßenrennen bei Vice Point.\n\n[BNK3_3B:BANKJ3]\nAn alle Einsatzkrãfte.\n\n[BNK3_3C:BANKJ3]\nStraßenrennen sind verboten und illegal!\n\n{=================================== MISSION TABLE BANKJ4 ===================================}\n\n[BNK4_A:BANKJ4]\n~w~Ihr seht Gentlemen, das wird leicht verdientes Geld für uns.\n\n[BNK4_B:BANKJ4]\n~w~Ernsthaft, Tommy, du solltest dir überlegen, Anwalt zu werden.\n\n[BNK4_C:BANKJ4]\n~w~Was zum Geier rauchst du eigentlich, Mann? Das ist kein simpler Plan.\n\n[BNK4_D:BANKJ4]\n~w~Ach, wer braucht schon simple Plãne?\n\n[BNK4_E:BANKJ4]\n~w~Der Kommunismus, das war ein simpler Plan. Hat Russland aber nicht viel genützt, hah?\n\n[BNK4_F:BANKJ4]\n~w~Ganz ruhig. Mit einem Team wie diesem ist das alles kein Problem.\n\n[BNK4_G:BANKJ4]\n~w~Cam übernimmt den Safe. Phil? Wir beide kümmern uns um die Sicherheit, und Hilary fãhrt den Fluchtwagen.\n\n[BNK4_H:BANKJ4]\n~w~Ãh, hast du nicht jemanden vergessen? Jemanden, der dir unzãhlige Male geholfen hat in dieser Stadt? Jemanden...?\n\n[BNK4_I:BANKJ4]\n~w~Ken...Ken, richtig. Ken wãscht das Geld für uns und stellt schon mal die Drinks kalt.\n\n[BNK4_J:BANKJ4]\n~w~Ich verstehe nicht, was ich hier soll.\n\n[BNK4_K:BANKJ4]\n~w~Ist doch ganz einfach. Warst du noch nie im Kino?\n\n[BNK4_L:BANKJ4]\n~w~Wir latschen in die Bank rein, fuchteln mit den Knarren rum und gehen stinkreich wieder raus.\n\n[P_DEAD:BANKJ4]\n~r~Phil ist erledigt!!\n\n[C_DEAD:BANKJ4]\n~r~Cam ist erledigt!!\n\n[H_DEAD:BANKJ4]\n~r~Hilary ist erledigt!!\n\n[P_HIND:BANKJ4]\n~r~Du hast Phil verloren!\n\n[C_HIND:BANKJ4]\n~r~Cam wurde abgehãngt!\n\n[H_HIND:BANKJ4]\n~r~Hilary wurde im Stich gelassen!\n\n[GETCAR:BANKJ4]\nSteig in den Fluchtwagen und führe den Plan aus!\n\n[TRASHED:BANKJ4]\n~r~DU HAST DEN FLUCHTWAGEN GESCHROTTET!!\n\n[BNK4_1:BANKJ4]\nIch fahre.\n\n[BNK4_2:BANKJ4]\nNa prima. Beifahrer. Wenn ich das in der Therapie erzãhle.\n\n[BNK4_3A:BANKJ4]\nHey, pass auf, wo du hinfãhrst, Tommy!\n\n[BNK4_3B:BANKJ4]\nTommy, Hilary macht sich so breit!\n\n[BNK4_3C:BANKJ4]\nStimmt gar nicht!\n\n[BNK4_3D:BANKJ4]\nDoch!\n\n[BNK4_3E:BANKJ4]\nHey, Klappe, ihr zwei, oder ihr könnt zu Fuß gehen.\n\n[BNK4_3F:BANKJ4]\nJa, Hilary.\n\n[BNK4_3I:BANKJ4]\nHerrgott, Phil, hör auf, mit diesem Ding rumzufuchteln!\n\n[BNK4_3J:BANKJ4]\nJa, am Ende geht das noch ins Auge!\n\n[BNK4_3M:BANKJ4]\nMein Baby! Alles Schrott!\n\n[BNK4_3O:BANKJ4]\nDu hãngst zu sehr an der Illusion der Ewigkeit.\n\n[BNK4_3P:BANKJ4]\nWas?\n\n[BNK4_3Q:BANKJ4]\nDu denkst, alles bleibt ewig.\n\n[BNK4_3R:BANKJ4]\nJugend, geliebte Menschen, Pizza,\n\n[BNK4_3S:BANKJ4]\nAlles geht mal vorbei, und das musst du akzeptieren.\n\n[BNK4_3T:BANKJ4]\nHey, du hast recht. Danke, Cam.\n\n[BNK4_3U:BANKJ4]\nNichts zu danken.\n\n[BNK4_3V:BANKJ4]\nHey, Tommy, wieso halten wir?\n\n[BNK4_4A:BANKJ4]\n~w~Hilary, fahr ein bisschen um den Block.\n\n[BNK4_5:BANKJ4]\n~w~Ok, Tommy, ok.\n\n[BNK4_6:BANKJ4]\n~w~DIES IST EIN ÜBERFALL!\n\n[BNK4_7:BANKJ4]\n~w~KEINER BEWEGT SICH!\n\n[BNK4_8:BANKJ4]\n~w~ALLE AN DIE WAND!\n\n[BNK4_9:BANKJ4]\nPhil, halt die Stellung!\n\n[BNK4_10:BANKJ4]\nVerstanden!\n\n[BNK4_11:BANKJ4]\nLos Cam, der Tresor ist oben...\n\n[BK4_12A:BANKJ4]\nVerdammt, das ist ein Flange 9000!\n\n[BK4_12B:BANKJ4]\nKönnte Stunden dauern, den zu knacken.\n\n[BK4_12C:BANKJ4]\nOder 5 Minuten, wenn du den Manager findest.\n\n[BNK4_13:BANKJ4]\nIch seh nach, wo er sich verkrochen hat.\n\n[BK4_14A:BANKJ4]\nPhil, alles im grünen Bereich?\n\n[BNK4_15:BANKJ4]\nKlar. Im dunkelgrünen Bereich.\n\n[BNK4_16:BANKJ4]\nDu da! Mitkommen!\n\n[BNK4_17:BANKJ4]\nOk! Ok! Nicht schießen!\n\n[BNK4_18:BANKJ4]\nICH SAGTE, KEINER RÜHRT SICH!\n\n[BK4_19A:BANKJ4]\nDer Safe hat eine Zeitsperre,\n\n[BK4_19B:BANKJ4]\nihr könnt ebenso gut gleich aufgeben!\n\n[BK4_20A:BANKJ4]\nAch, die Zeitsperre kann ich umgehen.\n\n[BK4_20B:BANKJ4]\nDann brauchen wir nur noch deinen Code und alles ist in Butter!\n\n[BNK4_21:BANKJ4]\nBleib hier. Wenn du Zicken machst, bist du Fischfutter, klar?\n\n[BNK422A:BANKJ4]\nCam, wie lange noch?\n\n[BK4_23A:BANKJ4]\nGib mir noch 3 Minuten!\n\n[BK4_24A:BANKJ4]\nIch seh mal nach Phil. Bin gleich wieder da.\n\n[BK4_24B:BANKJ4]\nIch hab gesagt, Finger weg vom Alarm!\n\n[BNK4_25:BANKJ4]\nDas Spezialkommando muss gleich hier sein!\n\n[BNK4_27:BANKJ4]\nIch könnte ein bisschen Hilfe brauchen, Tommy!\n\n[BNK4_28:BANKJ4]\nVice City Spezialkommando! Sie sind umzingelt!\n\n[BNK4_29:BANKJ4]\nUmzingelt? HA HA HA HAAAAAaaa!\n\n[BNK4_30:BANKJ4]\nDie scheißen sich ein, die korrupten Schweine!\n\n[BK4_31A:BANKJ4]\nTommy, der Tresor ist offen!\n\n[BK4_34A:BANKJ4]\nOk, wir haben die Pensionskasse der Bullen. Los, raus hier!\n\n[BK4_34B:BANKJ4]\nOk, ihr habt es so gewollt. Ihr hattet eure letzte Chance!\n\n[BK4_35A:BANKJ4]\nDie stürmen den Laden!\n\n[BK4_35B:BANKJ4]\nIn Deckung!\n\n[BNK4_94:BANKJ4]\n~w~Ok, Jungs. Jeder hãlt sich an den Plan .\n\n[BM_DEAD:BANKJ4]\n~r~Du brauchst den Bank Manager lebend!!\n\n[ASSET_A:BANKJ4]\nBANK-MISSIONEN ERFÜLLT!\n\n[ASSET_B:BANKJ4]\n~g~Der Malibu Club generiert nun bis zu $~1~ Einkünfte. Hol dir das Geld regelmãßig ab.\n\n[IDIOT:BANKJ4]\n~r~Na super - angezogen wie ein Irrer durch die Gegend laufen und Aufmerksamkeit erregen, IDIOT!\n\n{=================================== MISSION TABLE BARON1 ===================================}\n\n[COK1_A:BARON1]\nKomm schon, Brauner, komm!\n\n[COK1_B:BARON1]\nDãmlicher Klepper! Dich mach ich einen Kopf kürzer!\n\n[COK1_C:BARON1]\nWer ist der Blödmann?\n\n[COK1_D:BARON1]\nTommy Vercetti, Sie erinnern sich.\n\n[COK1_E:BARON1]\nTschuldigung, ich bin etwas nervös. Vertrau niemals einem verdammten Pferd!\n\n[COK1_F:BARON1]\nDu machst deine Sache gut. Du arbeitest jetzt für mich.\n\n[COK1_H:BARON1]\nWie gesagt, Amigo, du arbeitest für mich. Basta. So ein Mistkerl hat mich betrogen.\n\n[COK1_I:BARON1]\nEr denkt, ich weiß nicht, wie viel Geld mir zusteht. Aber 3% zu klauen ist genauso schlimm wie 100% zu klauen.\n\n[COK1_J:BARON1]\nNiemand haut mich übers Ohr. NIEMAND!!\n\n[COK1_K:BARON1]\nFolge ihm von seiner Wohnung aus und sieh nach, wo er hin will. Spãter erledigen wir ihn.\n\n[COK1_1:BARON1]\nOh, Shit!\n\n[COK1_2:BARON1]\nZu langsam, Opa!\n\n[COK1_4:BARON1]\nVersager.\n\n[COK1_5:BARON1]\nIch würde einen Zahn zulegen, du Mistsack!\n\n[COK1_8:BARON1]\n~g~Schnell! Schnapp dir einen Untersatz und folge ihm!\n\n[COK1_9:BARON1]\n~r~Du sollst ihn verfolgen, nicht umlegen!\n\n[COK1_10:BARON1]\n~r~Begib dich zum Haus des Diebes und such das Geldversteck.\n\n[COK1_11:BARON1]\n~g~Schau durch sein Fenster.\n\n[COK1_7:BARON1]\n~g~Er ist aufs Dach geflohen. Bleib ihm auf den Fersen, aber erledige ihn nicht.\n\n[COK1_G:BARON1]\nIch arbeite gegen Geld.\n\n{=================================== MISSION TABLE BARON2 ===================================}\n\n[COK2_A:BARON2]\nWas bist du eigentlich für ein inkompetenter Narr?\n\n[COK2_B:BARON2]\nNARR! NARR! NARR! NARR!\n\n[COK2_C:BARON2]\nTommy-\n\n[COK2_D:BARON2]\nWas, Ricardo?\n\n[COK2_E:BARON2]\nDiese Idioten - dauernd wollen sie einen reinlegen.\n\n[COK2_F:BARON2]\nDas ist der Fehler an dieser Branche.\n\n[COK2_G:BARON2]\nWas soll denn das? Aaaaah!\n\n[COK2_H:BARON2]\nDiese Mistkerle haben mich bitter enttãuscht.\n\n[COK2_I:BARON2]\nBald denkt jeder Depp, er kann in Vice City Koks verkaufen.\n\n[COK2_J:BARON2]\nWas kommt als nãchstes, hah? Die verstunkene Mafia?!\n\n[COK2_K:BARON2]\nDiese Bandengegend ist eine Festung ohne Mauern.\n\n[COK2_L:BARON2]\nAlso: Quentin hier - Quentin! QUENTIN!\n\n[COK2_M:BARON2]\nEr fliegt dich über das Areal.\n\n[COK2_N:BARON2]\nHeb ihr Nest aus!\n\n[COK2_O:BARON2]\nWas soll denn das?\n\n[COK2_P:BARON2]\nWas willst du hier?\n\n[COK2_Q:BARON2]\nHey, ich hab mich umgehört, und es ist klar,\n\n[COK2_R:BARON2]\ndass Diaz in den Deal reingeplatzt ist und meinen Bruder erledigt hat.\n\n[COK2_S:BARON2]\nUnd dich erledigt er auch!\n\n[COK2_T:BARON2]\nMit Diaz nehm ich's auf!\n\n[COK2_U:BARON2]\nNein, hör zu! Ich übernehme Diaz -\n\n[COK2_V:BARON2]\ner beginnt mir zu vertrauen.\n\n[COK2_1:BARON2]\nEines versteh ich nicht: Was soll das mit 'Quentin'!?\n\n[COK2_2:BARON2]\nWeiß nicht. Hat mir immer gefallen...Quentin Vance...\n\n[COK2_3:BARON2]\nVance? Du heißt wirklich Lance Vance?!\n\n[COK2_4:BARON2]\nHey! Das hab ich schon in der Schule oft genug gehört!\n\n[COK2_5:BARON2]\nHast du so was schon mal aus einem Helikopter abgefeuert?\n\n[COK2_8:BARON2]\nWo fliegen wir denn hier?\n\n[COK2_9:BARON2]\nPrawn Island.\n\n[COK2_13:BARON2]\n'Lance Vance'. Du armer Teufel.\n\n[COK2_14:BARON2]\nOk, wir sind gleich da.\n\n[COK2_15:BARON2]\nWir fliegen ein paar Mal drüber weg.\n\n[COK2_16:BARON2]\nSchalte so viele Kerle aus wie du kannst.\n\n[COK2_17:BARON2]\nDann setze ich dich ab, und du bist auf dich allein gestellt.\n\n[COK2_20:BARON2]\nShit! Das ist ja wie im Krieg hier! Schalt welche von den Schützen aus!\n\n[COK2_21:BARON2]\nWir werden getroffen, Mann!\n\n[COK2_22:BARON2]\nReparaturen an dem Kübel hier kosten! Schalt sie aus!\n\n[COK2_23:BARON2]\nOk, von jetzt an bist du auf dich alleine gestellt. Viel Glück!\n\n[COK2_24:BARON2]\nZustand Helikopter:\n\n[COK2_25:BARON2]\n~g~Hol das Geld auf dem Dach.\n\n[COK2_27:BARON2]\nDu bist auf MEINEM Gebiet, Mistkerl!\n\n[COK2_28:BARON2]\nDich mach ich fertig!\n\n[COK2_6:BARON2]\nNein. Aber ich kann ja unterwegs ein bisschen üben.\n\n[OPEN_B:BARON2]\nDie Straßensperren zum Festland sind aufgehoben worden.\n\n{=================================== MISSION TABLE BARON3 ===================================}\n\n[COK3_A:BARON3]\nDas gefãllt euch nicht, was?!\n\n[COK3_B:BARON3]\nAhahahahaa, Ahahahahaa.\n\n[COK3_C:BARON3]\nVorsicht! Passen Sie auf, wo Sie damit hin zielen!\n\n[COK3_D:BARON3]\nKein Taubendreck mehr auf MEINEM Dach, was Tommy?\n\n[COK3_E:BARON3]\nSieht nicht so aus.\n\n[COK3_F:BARON3]\nDas kannst du laut sagen. Also, hör zu:\n\n[COK3_G:BARON3]\nWeißt du, wem das schnellste Boot an der Ostküste gehört?\n\n[COK3_H:BARON3]\nNicht wirklich.\n\n[COK3_I:BARON3]\nMIR. Und das soll auch so bleiben.\n\n[COK3_J:BARON3]\nJeder Schmuggler von hier bis Caracas hat EINEN Traum: ein schnelleres Boot.\n\n[COK3_K:BARON3]\nEs heißt, die Hull Werft hat gerade so ein Boot fertiggestellt,\n\n[COK3_L:BARON3]\nfür irgendeinen costaricanischen Idioten.\n\n[COK3_M:BARON3]\nUnd, Tommy...ICH WILL DIESES BOOT!!!\n\n[COK3_N:BARON3]\nIch glaube, die Tauben sind wieder da.\n\n[COK3_O:BARON3]\nAh! Ich dachte, ich hab euch erwischt. Wo kommst du denn her?\n\n[COK3_P:BARON3]\nTauben! Boom! Aaaaah!\n\n[COK3_5:BARON3]\n~g~Suche den Schalter, um das Boot abzusenken.\n\n[COK3_6:BARON3]\n~g~Bringe das Boot zur Villa.\n\n[COK3_7:BARON3]\n~r~Du hast das Boot zerstört!\n\n[COK3_8:BARON3]\n~g~Begib dich zur Bootswerft an den Docks und klau das schnellste Boot.\n\n[COK3_9:BARON3]\n~g~Jetzt steig in das Boot.\n\n{=================================== MISSION TABLE BARON4 ===================================}\n\n[COK4_A:BARON4]\nEject! PLASTIKMÜLL!\n\n[COK4_B:BARON4]\nWie kannst du mir das antun?\n\n[COK4_C:BARON4]\nWas bildest du dir ein, du mieses Stück Plastikdreck! Aaargh!\n\n[COK4_D:BARON4]\nVERDAMMT!\n\n[COK4_E:BARON4]\nWenn das Ding meinen Lieblings-El-Burro-Film frisst, ist Sense!\n\n[COK4_F:BARON4]\nWas kann ich noch tun?\n\n[COK4_G:BARON4]\nIst wahrscheinlich nicht eingesteckt.\n\n[COK4_H:BARON4]\nWas?\n\n[COK4_I:BARON4]\nVerdammt. Egal, ich kann mir noch 100 davon kaufen.\n\n[COK4_J:BARON4]\nAlso, Tommy,\n\n[COK4_K:BARON4]\njeden Monat legt ein 'Freiberufler' mit seiner Jacht in Vice City an.\n\n[COK4_L:BARON4]\nEr verkauft seine Fracht an das erstbeste Schiff.\n\n[COK4_M:BARON4]\nDu schnappst dir das Rennboot,\n\n[COK4_N:BARON4]\nund bist vor allen anderen Pennern bei ihm.\n\n[COK4_O:BARON4]\nDann bringst du die Fracht hierher, ok?\n\n[COK4_P:BARON4]\nLass mich raten. Du dachtest, ich brauche einen Schutzengel.\n\n[COK4_Q:BARON4]\nIch denke nur, du solltest mich mitnehmen, Mann.\n\n[COK4_R:BARON4]\nDu kannst lange den einsamen Macho-Helden markieren,\n\n[COK4_S:BARON4]\naber eines Tages werde ich dir den Hintern retten\n\n[COK4_T:BARON4]\nund du wirst mich wahrscheinlich dafür küssen wollen.\n\n[COK4_U:BARON4]\nSpinner.\n\n[COK4_V:BARON4]\nHahahaha!\n\n[COK4_1:BARON4]\nTommy, wir wissen, es war Diaz, der unseren Deal platzen ließ.\n\n[COK4_3:BARON4]\nWieso spielen wir dann die Laufburschen für ihn?\n\n[COK4_4:BARON4]\nJe mehr wir jetzt lernen, desto weniger müssen wir lernen, wenn wir diese Stadt übernehmen!\n\n[COK4_5:BARON4]\nDein Stil gefãllt mir. Echt erfrischend.\n\n[COK4_12:BARON4]\nPass auf, die kommen von überall\n\n[COK4_13:BARON4]\nErwischt! Fahr zu Diaz so schnell du kannst!\n\n[COK4_14:BARON4]\nWillst du was abhaben?\n\n[COK4_15:BARON4]\nSchönen Gruß an die Fische!\n\n[COK4_16:BARON4]\nNimm das! Und das!\n\n[COK4_19:BARON4]\nGleich kommt's noch dicker!\n\n[COK4_20:BARON4]\nDa sind Schützen auf dem Pier!\n\n[COK4_24:BARON4]\nGut geschossen, mein Freund. Du bist ein erstklassiger Psycho.\n\n[COK4_25:BARON4]\nDanke sehr.\n\n[COK4_26:BARON4]\nWir sehen uns, Tommy.\n\n[COK4_27:BARON4]\nOk, Mr. Lance Vance Dance.\n\n[COK4_28:BARON4]\n~g~Sei vor den anderen Booten bei der Jacht!\n\n[COK4_31:BARON4]\n~g~Begib dich zum schnellsten Boot auf dem Pier!\n\n[COK4_32:BARON4]\n~r~Zu langsam!\n\n[COK4_33:BARON4]\n~r~Du hast das Boot zerstört!\n\n[COK4_34:BARON4]\n~g~Zieh diese Boote aus dem Verkehr!\n\n[COK4_35:BARON4]\nZustand Boot:\n\n{=================================== MISSION TABLE BARON5 ===================================}\n\n[PROP_A:BARON5]\nOBJEKT ERWORBEN!\n\n[COK4_30:BARON5]\n~r~Lance ist erledigt!\n\n[ASS1_A:BARON5]\nIm Kofferraum sind ein paar Kanonen.\n\n[ASS1_B:BARON5]\nWahnsinn! Wo hast du denn die alle her?\n\n[ASS1_C:BARON5]\nHab ich für schlechte Zeiten zurückgelegt.\n\n[ASS1_D:BARON5]\nZufrieden?\n\n[ASS1_E:BARON5]\nJa. Und wie!\n\n[ASS1_F:BARON5]\nIhr dãmlichen Idioten!\n\n[ASS1_G:BARON5]\nMein schönes Haus\n\n[ASS1_H:BARON5]\nSeht euch an, was ihr angestellt habt!\n\n[ASS1_I:BARON5]\nDas ist für meinen Bruder!\n\n[ASS1_J:BARON5]\nIch habe dir vertraut, Tommy.\n\n[ASS1_K:BARON5]\nIch hãtte was aus dir gemacht...\n\n[ASS1_L:BARON5]\nGute Nacht, Mr. Diaz.\n\n[ASS1_1:BARON5]\nBald wimmelt's hier von Arschlöchern. Sei vorsichtig.\n\n[ASS1_2:BARON5]\nKeine Panik, Tommy, ich geb dir Deckung.\n\n[ASS1_13:BARON5]\nDIAZ?! Ich bin hier, um deinen Laden zu übernehmen!\n\n[ASS1_14:BARON5]\nTOMMY! Du Verrãter...Du Idiot! Dich mache ich fix und fertig...\n\n[ASS1_16:BARON5]\n~g~Erledige Diaz!\n\n[BUD1:BARON5]\nLance\n\n[ASS1_18:BARON5]\n~g~Die Tür ist verschlossen. Versuche es auf einem anderen Weg.\n\n[ASS1_19:BARON5]\nDa lang!\n\n[ASS1_20:BARON5]\nTommy, ich hab ein Problem mit Quentin, nicht mit dir, Mann!\n\n{=================================== MISSION TABLE BIKE1 ===================================}\n\n[BM1_A:BIKE1]\nWo ist Baker?\n\n[BM1_B:BIKE1]\nIch suche Big Mitch Baker...\n\n[BM1_C:BIKE1]\nWer sucht ihn?\n\n[BM1_D:BIKE1]\nTommy Vercetti.\n\n[BM1_E:BIKE1]\nVercetti.\n\n[BM1_F:BIKE1]\nDu siehst nicht wie ein Bulle aus, das heißt, du hast 1 Minute.\n\n[BM1_G:BIKE1]\nAlso drück auf die Tube.\n\n[BM1_H:BIKE1]\nKent Paul sagt, ihr wãrt interessiert, die Security für einen Gig zu übernehmen, den er plant.\n\n[BM1_I:BIKE1]\nKent Paul? Pfff! Kein Wunder, dass er dich schickt.\n\n[BM1_J:BIKE1]\nAls er das letzte Mal hier war, ist er durch Fenster wieder gegangen - und zwar splitternackt.\n\n[BM1_K:BIKE1]\nSeid ihr nun interessiert oder nicht?\n\n[BM1_L:BIKE1]\nGefãlligkeiten gibt's nur für Mitglieder.\n\n[BM1_M:BIKE1]\nWie kann ich beitreten?\n\n[BM1_N:BIKE1]\nWir sind hier kein Golfklub, Kleiner. Kannst du 'n Bike fahren?\n\n[BM1_O:BIKE1]\nKannst du auf 'm Barhocker sitzen und saufen?\n\n[BM1_P:BIKE1]\nCougar, Zeppelin, checkt mal ab, wie diese Sissy hier fãhrt.\n\n[BM1_2:BIKE1]\n~g~Du brauchst eine Freeway oder eine Angel, um mitzumachen!\n\n[BM1_3:BIKE1]\n~r~Die Fahrer wurden angegriffen!\n\n[BIKE1_1:BIKE1]\nOk, Schickimickibürschchen, dann zeig mal, was du drauf hast.\n\n[BM1_1:BIKE1]\n~g~Schnapp dir eine Freeway oder eine Angel und geh in Startposition.\n\n{=================================== MISSION TABLE BIKE2 ===================================}\n\n[BM2_2:BIKE2]\n~g~Du musst den Chaosmesser in der vorgegebenen Zeit vollmachen, um uns zu zeigen, aus welchen Holz du bist!\n\n[BM2_4:BIKE2]\n~r~Du hast den Chaosmesser nicht rechtzeitig vollgemacht!\n\n[BM2_1:BIKE2]\nCHAOSMESSER:\n\n[BM2_A:BIKE2]\nHa, ha, ha, hab dich wieder erwischt.\n\n[BM2_B:BIKE2]\nHey, Vercetti.\n\n[BM2_C:BIKE2]\nCougar meint, du fãhrst ziemlich gut.\n\n[BM2_D:BIKE2]\nJa, wie lange soll ich noch hier rumgurken?\n\n[BM2_E:BIKE2]\nIch bin ein sehr beschãftigter Mann.\n\n[BM2_F:BIKE2]\nWenn ich mich kloppen soll, damit das klar geht, dann los.\n\n[BM2_G:BIKE2]\nEs geht bei uns nicht nur ums dreinschlagen. Man muss zur Familie gehören.\n\n[BM2_H:BIKE2]\nJa, ich hab schon mal zu einer Familie gehört. Hat nicht funktioniert.\n\n[BM2_I:BIKE2]\nKlar. Aber unsere Familie kümmert sich um ihre Leute.\n\n[BM2_J:BIKE2]\nWir verlangen nicht, dass einer die Drecksarbeit macht und danach 15 Jahre einsitzt.\n\n[BM2_K:BIKE2]\nJa, ganz recht. Ich hab meine Hausaufgaben gemacht.\n\n[BM2_L:BIKE2]\nDas hier ist die größte Familie von Außenseitern, Outlaws und Unruhestiftern.\n\n[BM2_M:BIKE2]\nEin paar von uns wurden sogar von ihrem eigenen Land verraten.\n\n[BM2_N:BIKE2]\nWãhrend des Vietnamkriegs war ich eingelocht. Miese Sache.\n\n[BM2_O:BIKE2]\nDrum sollst du denen ja zeigen, was Sache ist.\n\n[BM2_P:BIKE2]\nDieses ganze verdammte Land braucht einen Arschtritt, und wir geben ihm diesen Tritt.\n\n[BM2_Q:BIKE2]\nAlso los, schnapp dir ein Bike und zeig der Stadt, wie sauer du bist.\n\n[BM2_R:BIKE2]\nAlles klar.\n\n[BM2_3:BIKE2]\n~g~Dieser Ton zeigt an, dass du einen Teil gefüllt hast. Mach ihn immer voller.\n\n{=================================== MISSION TABLE BIKE3 ===================================}\n\n[BM3_A:BIKE3]\nHi, Mitch.\n\n[BM3_B:BIKE3]\nAh, sieh an, 'Outlaw' Vercetti.\n\n[BM3_C:BIKE3]\nJetzt will ich sehen, wie du für deine Kumpels kãmpfst.\n\n[BM3_D:BIKE3]\nEine Straßengang von hier hat den Fehler gemacht, meinen Hobel zu klauen.\n\n[BM3_E:BIKE3]\nWollten wahrscheinlich zeigen, was für coole Machos sie sind.\n\n[BM3_F:BIKE3]\nIch und die Jungs wollten ihnen eigentlich ein bisschen Respekt einblãuen.\n\n[BM3_G:BIKE3]\nAber-\n\n[BM3_H:BIKE3]\n-dann dachte ich mir, das wãre doch ein guter Test für dich.\n\n[BM3_I:BIKE3]\nBring mir meine Maschine zurück und Paul kriegt seine Security.\n\n[BM3_2:BIKE3]\n~r~Du solltest die Maschine zurückbringen, nicht schrotten!\n\n[BM3_3:BIKE3]\n~g~Bring die Maschine zur Bar!\n\n[BM3_4:BIKE3]\n~g~Setz dich auf die Maschine!\n\n[INTRUDE:BIKE3]\n~g~Man hat dich bemerkt!\n\n[BM3_6:BIKE3]\n~g~Sie sind Downtown hinter dem Ammu-Nation.\n\n[BM3_7:BIKE3]\n~g~Du brauchst eine schnelle Maschine, um auf das Dach zu gelangen.\n\n[BM3_8:BIKE3]\n~g~Spring mit dem Bike von diesen Stufen auf das Dach auf der anderen Seite der Straße.\n\n[BM3_1:BIKE3]\n~g~Eine Gang hat Mitch Bakers Maschine geklaut. Beschaff sie ihm wieder!\n\n[BM3_9:BIKE3]\n~g~Schnapp dir Mitchs Maschine und mach dich aus dem Staub!\n\n{=================================== MISSION TABLE BMX_1 ===================================}\n\n[GETBIK2:BMX_1]\nDu hast ~1~ Sekunden, um auf ein Gelãndemotorrad zu steigen!\n\n{=================================== MISSION TABLE BOATBUY ===================================}\n\n[DRUG_1:BOATBUY]\nHallo? Hal-lo?! Hallo?\n\n[DRUG_13:BOATBUY]\nMeister?\n\n[DRUG_2:BOATBUY]\nMach aus. Da kommt einer.\n\n[DRUG_3:BOATBUY]\nTag, Herr Anzugmensch. Sie müssen der neue Eigentümer sein.\n\n[DRUG_4:BOATBUY]\nJa. Welches von den Booten ist das schnellste?\n\n[DRUG_5:BOATBUY]\nDas ist schon im Wasser, Meister.\n\n[DRUG_6:BOATBUY]\nDachte mir, dass Sie es mal testen wollen.\n\n[DRUG_7:BOATBUY]\nDas Ding hat jetzt schon 300 PS unter der Haube, Meister.\n\n[DRUG_8:BOATBUY]\nUnd mit dem Fiberglas-Rumpf - das Ding pfeift nur so durch die Wellen!\n\n[DRUG_9:BOATBUY]\nIn vier Sekunden von null auf sechzig Meilen, Meister.\n\n[DRUG_10:BOATBUY]\nUnd im Rumpf kriegen Sie so 20 Ladungen vom besten jamaikanischen Gras unter.\n\n[DRUG_11:BOATBUY]\nNur zu, Chef, machen Sie 'ne Spritztour!\n\n[DRUG_12:BOATBUY]\nHey Anzugmensch, haben Sie mal Feuer?\n\n{=================================== MISSION TABLE CAP_1 ===================================}\n\n[CAP1_B1:CAP_1]\n~g~Die Mafia verlangt Schutzgeld von dir. Stöbere sie auf und erledige sie.\n\n[CAP1_B2:CAP_1]\n~g~Die Mafia verlangt von dir Schutzgeld für die Bootswerft!\n\n[CAP1_B3:CAP_1]\n~g~Die Mafia verlangt von dir Schutzgeld für die Eiscremefabrik!\n\n[CAP1_B4:CAP_1]\n~g~Die Mafia verlangt von dir Schutzgeld für das Autohaus!\n\n[CAP1_B5:CAP_1]\n~g~Die Mafia verlangt von dir Schutzgeld für das Taxiunternehmen!\n\n[CAP_01:CAP_1]\nOk, wo brennt's denn?\n\n[CAP_02:CAP_1]\nWer war das?\n\n[CAP_03:CAP_1]\nTommy... ein paar Mafia-Typen... sie wollen wiederkommen, ihren Anteil abkassieren.\n\n[CAP_04:CAP_1]\nEin gewisser Mr. Forello hãtte dir Geld gegeben. Mir geht's schlecht.\n\n[CAP_05:CAP_1]\nForelli? SONNY Forelli?\n\n[CAP_06:CAP_1]\nJa, so heißt er, glaube ich... ich konnte nichts gegen sie ausrichten.\n\n[CAP_07:CAP_1]\nKeine Angst, mein Freund, ich mach dir keine Vorwürfe.\n\n[CAP_08:CAP_1]\nBringt ihn ins Krankenhaus.\n\n[CAP_09:CAP_1]\nTommy... mach den Kerl 'nen Kopf kürzer für mich...\n\n[CAP_10:CAP_1]\nIch mach ihn zwei Köpfe kürzer...\n\n[CAP1_2:CAP_1]\nDu kennst die Regeln, Vercetti!\n\n[CAP1_3:CAP_1]\nMr. Forelli bestellt schöne Grüße!\n\n[CAP1_4:CAP_1]\nDas ist der Harwood Butcher!\n\n[CAP1_5:CAP_1]\nSag Sonny, er soll mir vom Leib bleiben!\n\n[CAP1_6:CAP_1]\nVice City gehört nicht mehr ihm, sondern MIR!\n\n[CAP1_7:CAP_1]\nDu glaubst, du kannst mich vom Thron stürzen, Vercetti?\n\n[CAP1_8:CAP_1]\nWir jagen dich bis ans Ende deiner Tage, Vercetti.\n\n[CAP1_9:CAP_1]\nDu hast keine Chance, du irrer Idiot!\n\n[CAP1_10:CAP_1]\nIch mach dich fertig, Vercetti.\n\n[CAP1_11:CAP_1]\nDu warst schon immer ein Schwachkopf.\n\n[CAP1_12:CAP_1]\nDu wirst dran glauben, Vercetti.\n\n[CAP1_B6:CAP_1]\n~g~Du hast den Eintreiber gefunden, erledige ihn.\n\n[CAP1_B7:CAP_1]\n~g~Du hast den Eintreiber verloren.\n\n[CAP1_B8:CAP_1]\n~r~Der Eintreiber verlangt für all deine Geschãfte Schutzgeld.\n\n[CAP1_B9:CAP_1]\n~g~Die Mafia verlangt Schutzgeld für das Malibu!\n\n[CAP1_B0:CAP_1]\n~g~Die Mafia verlangt Schutzgeld für das Filmstudio!\n\n[CAP1_C2:CAP_1]\n~g~Die Mafia ist bei der Bootswerft angekommen!\n\n[CAP1_C3:CAP_1]\n~g~Die Mafia ist bei der Eiscremefabrik angekommen!\n\n[CAP1_C4:CAP_1]\n~g~Die Mafia ist bei dem Autohaus angekommen!\n\n[CAP1_C5:CAP_1]\n~g~Die Mafia ist bei dem Taxiunternehmen angekommen!\n\n[CAP1_C9:CAP_1]\n~g~Die Mafia ist im Malibu Club angekommen!\n\n[CAP1_C0:CAP_1]\n~g~Die Mafia ist im Filmstudio angekommen!\n\n[CAP1_D2:CAP_1]\n~g~Die Mafia verlãsst die Bootswerft!\n\n[CAP1_D3:CAP_1]\n~g~Die Mafia verlãsst die Eiscremefabrik!\n\n[CAP1_D4:CAP_1]\n~g~Die Mafia verlãsst das Autohaus!\n\n[CAP1_D5:CAP_1]\n~g~Die Mafia verlãsst das Taxiunternehmen!\n\n[CAP1_D9:CAP_1]\n~g~Die Mafia verlãsst den Malibu Club!\n\n[CAP1_D0:CAP_1]\n~g~Die Mafia verlãsst das Filmstudio!\n\n[CAP1B10:CAP_1]\nDu hast die Eintreiber erledigt. Es kommen weitere.\n\n{=================================== MISSION TABLE CARBUY ===================================}\n\n[CAR1_1:CARBUY]\nB.J. Smith. Und Sie müssen Mr. Vercetti sein.\n\n[CAR1_2:CARBUY]\nSoll ich Sie herumführen?\n\n[CAR1_3:CARBUY]\nWarum nicht?\n\n[CAR1_4:CARBUY]\nTja, ich verkaufe das Autohaus ja eigentlich nur ungern.\n\n[CAR1_5:CARBUY]\nWar meine erste Investition, nachdem ich Football-Profi wurde.\n\n[CAR1_6:CARBUY]\nAber es wird Zeit für eine Luftverãnderung.\n\n[CAR1_7:CARBUY]\nSie verlassen die Stadt?\n\n[CAR1_8:CARBUY]\nNicht in allzu großer Eile, hoffe ich doch?\n\n[CAR1_9:CARBUY]\nNein, ich bereite mich nur auf mein Comeback als Football-Profi vor. Ich hatte schon aufgehört.\n\n[CAR1_10:CARBUY]\nDas Geschãft lief nicht allzu gut.\n\n[CAR1_11:CARBUY]\nDa haben sich meine Angestellten was einfallen lassen,\n\n[CAR1_12:CARBUY]\num ein bisschen was 'nebenbei' zu erwirtschaften.\n\n[CAR1_13:CARBUY]\nIch könnte den Laden auch dichtmachen, bevor ich ihn Ihnen verkaufe.\n\n[CAR1_14:CARBUY]\nIch könnte die Bude bei Bedarf sogar abfackeln.\n\n[CAR1_15:CARBUY]\nDas ist erstklassiger Baugrund hier.\n\n[CAR1_16:CARBUY]\nMachen Sie sich mal keine Gedanken.\n\n[CAR1_17:CARBUY]\nDer Laden ist genau das, was ich brauche.\n\n[CAR1_18:CARBUY]\nJa. Dann kommen wir also ins Geschãft?\n\n{=================================== MISSION TABLE CARPAR1 ===================================}\n\n[MM_1_A:CARPAR1]\n~g~Passiere ~y~5 checkpoints~r~ OHNE irgendwelche ~r~Hütchen ~g~umzufahren! ~g~Die ~y~REIHENFOLGE IST BELIEBIG.\n\n[CONE_1:CARPAR1]\n~r~Du hast ein Hütchen umgefahren!!\n\n[MM_1_C:CARPAR1]\n~y~PASSIERE~g~ einen Checkpoint, dann lãuft die Zeit. ~g~Jeder Checkpoint bringt dir ~y~~1~ SEKUNDEN~g~.\n\n{=================================== MISSION TABLE COPCAR ===================================}\n\n[C_COMP1:COPCAR]\nBürgerwehr-Mission Level 12 beendet: Deine max. Panzerung erhöht sich auf 150\n\n[CLEVEL:COPCAR]\nBürgerwehr-Mission Level ~1~\n\n[C_PASS:COPCAR]\nBEDROHUNG AUSGERÃUMT: $ ~1~\n\n[KILLS:COPCAR]\nHITS:\n\n[C_BREIF:COPCAR]\n~g~Verdãchtiger wurde zuletzt in der Gegend von ~a~ gesichtet.\n\n[COPCART:COPCAR]\n~g~Du hast ~1~ Sekunden, um zu einem Polizeifahrzeug zurückzukehren, bevor die Mission endet.\n\n[C_CANC:COPCAR]\n~r~Bürgerwehr-Mission abgebrochen!\n\n[C_TIME:COPCAR]\n~r~Deine Zeit als Gesetzeshüter ist vorbei!\n\n{=================================== MISSION TABLE COUNT1 ===================================}\n\n[CM1_A:COUNT1]\nMr.Vercetti? Hey. Sie haben die alte Druckerei gekauft?\n\n[CM1_B:COUNT1]\nJa, mein Vater hat an diesen Dingern gearbeitet.\n\n[CM1_C:COUNT1]\nIch sollte in seine Fußstapfen treten, aber...es ist anders gekommen.\n\n[CM1_D:COUNT1]\nWollen Sie die alten Maschinen verkaufen, das Werk abreißen?\n\n[CM1_E:COUNT1]\nIch denke nach, ob wir was drucken sollten. Eine Zeitung, ein Magazin...\n\n[CM1_F:COUNT1]\nAch, Blödsinn, absoluter Blödsinn. Ich drucke lieber Geld. Ist gar nicht so schwer.\n\n[CM1_G:COUNT1]\nIn kleinerem Umfang mache ich das schon seit Jahren.\n\n[CM1_H:COUNT1]\nTatsãchlich?\n\n[CM1_I:COUNT1]\nKlar. Aber wir brãuchten gute Platten.\n\n[CM1_J:COUNT1]\nNatürlich! In Florida gibt es schon ein Geldfãlscher-Syndikat.\n\n[CM1_K:COUNT1]\nEin Syndikat?\n\n[CM1_L:COUNT1]\nJa. Hab aber nur gerüchteweise davon gehört.\n\n[CM1_M:COUNT1]\nIch kenne einen, der kennt sich mit Gerüchten aus...\n\n[CM1_N:COUNT1]\nHab immer die Abende mit ihm verbracht, die Walzen reinigen.\n\n[CM1_2A:COUNT1]\nSieh dir diesen Hintern an!\n\n[CM1_2B:COUNT1]\nTja, Kleine, du weißt nicht, was dir entgeht!\n\n[CM1_2C:COUNT1]\nNa, alter Freund, wie lãuft's so?\n\n[CM1_2D:COUNT1]\nWas weißt du über Geldfãlscherei?\n\n[CM1_2E:COUNT1]\n'Oh, alles bestens, Paul, und bei dir?'\n\n[CM1_2F:COUNT1]\nKomm her!\n\n[CM1_2G:COUNT1]\nIst ja gut, ist ja gut. Anscheinend bist du schwer beschãftigt.\n\n[CM1_2H:COUNT1]\nÜber Falschgeld weiß ich nur, dass die Triaden die Platten liefern.\n\n[CM1_2I:COUNT1]\nDie haben eine Reederei unten bei den Docks.\n\n[CM1_2J:COUNT1]\nDer Boss weiß, wann die nãchsten Platten reinkommen.\n\n[CM1_2K:COUNT1]\nDanke, Paul.\n\n[CM1_2L:COUNT1]\nWas ist bloß los mit dir, du Wahnsinniger!\n\n[CM1_2M:COUNT1]\nGib mir noch einen Drink, hopp!\n\n[CM1_3:COUNT1]\n~g~Man hat dich bemerkt!\n\n[CM1_5:COUNT1]\n~g~Begib dich zu Kent Paul in den Malibu Club!\n\n[CNT1_1:COUNT1]\nWer sind Sie? Uff! Aiiee! Nicht ins Gesicht! Nicht ins Gesicht!\n\n[CM1_1:COUNT1]\n~g~Begib dich zum Schiff der Chartered Libertine Lines bei den Docks.\n\n[CM1_2:COUNT1]\n~g~Der Reedereichef verfügt über die benötigten Informationen.\n\n[CNT1_2:COUNT1]\nOk, ich rede ja! Ich rede!\n\n[CM1_6:COUNT1]\n~g~Begib dich mit den Informationen zurück in die Druckerei!\n\n{=================================== MISSION TABLE COUNT2 ===================================}\n\n[CNT2_B1:COUNT2]\nOk, der Kurier holt die Druckplatten heute vom Hafen ab.\n\n[CNT2_B2:COUNT2]\nIch fange ihn ab, schnapp mir die Platten, hãng die Cops ab und komm wieder hierher.\n\n[CNT2_B3:COUNT2]\nAlso, je nachdem wie es lãuft, haben wir\n\n[CNT2_B4:COUNT2]\nentweder 5 Minuten zum Gelddrucken, bis das Fãlschersyndikat uns findet, oder wir haben alle Zeit der Welt.\n\n[CNT2_B5:COUNT2]\nJedenfalls will ich 5 Minuten nachdem ich hier bin, Scheinchen aus der Presse kommen sehen!\n\n[CNT2_B6:COUNT2]\nKeine Sorge, Tommy. Wir sind bereit.\n\n[CNT2_B7:COUNT2]\nIch und die Jungs bleiben in der Nãhe, falls die Cops dir in die Quere kommen.\n\n[CNT2_B8:COUNT2]\nOk. Jeder weiß, was er zu tun hat? Gut. Bis spãter.\n\n[CNT2_01:COUNT2]\n~g~Der ~r~Kurier~g~ mit den Druckplatten kommt jeden Moment in einem Helikopter an den ~y~Docks~g~ an.\n\n[CNT2_02:COUNT2]\n~r~Der Kurier mit den Platten ist im Helikopter geflohen.\n\n[CNT2_03:COUNT2]\n~r~Der Kurier ist an seinem Ziel angekommen. Du kommst zu spãt!\n\n[CNT2_04:COUNT2]\n~r~Du hast die Platten in der Explosion zerstört!\n\n[CNT2_05:COUNT2]\n~g~Du hast die Druckplatten. Bring sie in die Druckerei.\n\n[CNT2_06:COUNT2]\n~g~Der Kurier ist hinüber. Hol dir die Platten, ehe dir jemand zuvorkommt.\n\n[CNT2_07:COUNT2]\n~g~Eine der Wachen hat die Platten genommen. Lass ihn nicht entkommen!\n\n[CNT2_08:COUNT2]\n~g~Der ~r~Kurier~g~ mit den Platten ist an den Docks eingetroffen.\n\n[CNT2_4:COUNT2]\nPrivatangelegenheit. Du hast hier nichts verloren!\n\n[CNT2_09:COUNT2]\nDRUCKEREI ERWORBEN\n\n[CNT2_10:COUNT2]\n~g~Die Druckerei generiert nun bis zu $~1~ Einkünfte. Hol dir das Geld regelmãßig ab.\n\n[CNT2_11:COUNT2]\n~r~Die Platten liegen auf dem Meeresgrund!\n\n{=================================== MISSION TABLE CUBAN1 ===================================}\n\n[CUB1_A:CUBAN1]\nWas ist, Mann?\n\n[CUB1_B:CUBAN1]\nHey, langsam, Paps, der ist für mich. Bist du der Bursche?\n\n[CUB1_C:CUBAN1]\nOh ja, du bist der Bursche. Glaub schon.\n\n[CUB1_D:CUBAN1]\nNein, glaub ich nicht.\n\n[CUB1_E:CUBAN1]\nAch ja? Komm her du Großmaul.\n\n[CUB1_F:CUBAN1]\nMeinst du, du kannst es mit mir aufnehmen?\n\n[CUB1_G:CUBAN1]\nMeinst du, du kannst mich für blöd verkaufen?\n\n[CUB1_H:CUBAN1]\nNein, ich glaube, deine Blödheit reicht für uns beide.\n\n[CUB1_I:CUBAN1]\nHey, er sagt, du bist dumm, mein Sohn.\n\n[CUB1_J:CUBAN1]\nUnd ich sage, er ist ein kleines Mãdchen, Paps.\n\n[CUB1_K:CUBAN1]\nSieh dir doch an, wie er angezogen ist.\n\n[CUB1_L:CUBAN1]\nWas ist los? Ist heute Weiberabend?\n\n[CUB1_M:CUBAN1]\nDu willst ein harter Kerl sein und ziehst dich an wie ein Weib?\n\n[CUB1_N:CUBAN1]\nHast du auch ein Höschen an, oder was?\n\n[CUB1_O:CUBAN1]\nWas hast du gegen Frauen? Ziehst du Mãnner vor?\n\n[CUB1_P:CUBAN1]\nIch liebe Frauen! Ich liebe alle Frauen! Ich liebe meine Mutter, Chico.\n\n[CUB1_Q:CUBAN1]\nOk, ok, ich glaub's dir ja.\n\n[CUB1_R:CUBAN1]\nKannst du fahren, Amigo?\n\n[CUB1_S:CUBAN1]\nJa...wie eine Frau.\n\n[CUB1_T:CUBAN1]\nSehr witzig. Du gefãllst mir, Großer. Vielleicht kannst du mir helfen.\n\n[CUB1_U:CUBAN1]\nVielleicht kannst du beweisen, dass du ein Mann bist. Hah?\n\n[CUB1_V:CUBAN1]\nSchnapp dir das Boot.\n\n[CUB1_W:CUBAN1]\nZeig mir, dass du ein ganzer Kerl bist,\n\n[CUB1_X:CUBAN1]\nund kein kleines Mãdchen.\n\n[CUB1_02:CUBAN1]\nOk Mann, behandle es wie eine Frau.\n\n[CUB1_03:CUBAN1]\nNicht schlecht, du bist ein echter Mann.\n\n[CUB1_04:CUBAN1]\nMann, du bist ein ganzer Kerl, Amigo.\n\n[CUB1_05:CUBAN1]\nAmigo, du bist ein Mann, Mann.\n\n[CUB1_06:CUBAN1]\nDu willst ein Mann sein, Mann?\n\n[CUB1_07:CUBAN1]\nDu bist ein feiges Würstchen, Kleiner, heul dich bei Mammi aus.\n\n[CUB1_08:CUBAN1]\nDu bist zu nichts zu gebrauchen. Macht einen auf harter Mann, aber fãhrt wie ein Idiot.\n\n[CUB1_09:CUBAN1]\nMann, du bist der Hammer, Mann. Du gefãllst mir. Du gefãllst mir sehr.\n\n[CUB1_10:CUBAN1]\nDu bist gut, Mann. Weil du ein ganzer Kerl bist. Alle meine Freunde sind ganze Kerle.\n\n[CUB1_11:CUBAN1]\nDu hast Rico erledigt!\n\n[CUB1_12:CUBAN1]\nFahre durch den ersten Checkpoint, um den Test zu beginnen.\n\n[CUB1_14:CUBAN1]\nSteig wieder ins Boot!\n\n[CUB1_15:CUBAN1]\nDu bist zu langsam, Mann.\n\n[CUB1_01:CUBAN1]\nHi, ich bin Rico. Bist du der 'ganze Kerl'?\n\n[CUB1_13:CUBAN1]\n~g~Du hast drei Minuten, um den Rundkurs zu schaffen.\n\n{=================================== MISSION TABLE CUBAN2 ===================================}\n\n[CUB2_25:CUBAN2]\nERLEDIGE ALLE HAITIANER!!\n\n[CUB2_M:CUBAN2]\nWer sich mit mir anlegt, hat sich den stãrksten der Stadt rausgesucht!\n\n[CUB2_A:CUBAN2]\nEine Kaffee, bitte, Alberto.\n\n[CUB2_N:CUBAN2]\nKein Problem, Tommy.\n\n[CUB2_B:CUBAN2]\nPaps! Es gibt ein Riesenproblem!\n\n[CUB2_O:CUBAN2]\nUmberto, mein Sohn, was ist passiert?\n\n[CUB2_C:CUBAN2]\nDie Haitianer! Ich hasse die Haitianer!\n\n[CUB2_D:CUBAN2]\nDie haben mir das letzte Mal ans Bein gepinkelt!\n\n[CUB2_E:CUBAN2]\nDiese Haitianer. Wir machen sie fertig!\n\n[CUB2_F:CUBAN2]\nAber dazu brauchen wir Hilfe.\n\n[CUB2_G:CUBAN2]\nIch hab dabei schon ein paar Brüder verloren.\n\n[CUB2_H:CUBAN2]\nAmigo, du fãhrst gut!\n\n[CUB2_I:CUBAN2]\nFür eine Frau, was?\n\n[CUB2_J:CUBAN2]\nJetzt ist nicht die Zeit für Witze!\n\n[CUB2_K:CUBAN2]\nKomm, fahr noch mal für mich!\n\n[CUB2_L:CUBAN2]\nBring meine Jungs da rüber, und dann erledigen wir diese Haitianer!\n\n[CUB2_01:CUBAN2]\nDa ist nicht genug Platz, Mann, du brauchst ein größeres Auto.\n\n[CUB2_02:CUBAN2]\nWir brauchen Verstãrkung aus dem Café!\n\n[CUB2_03:CUBAN2]\n~g~Besorg dir ein Auto und hole die Kubaner vor Robinas Café ab.\n\n[CUB2_04:CUBAN2]\n~g~Setze die Kubaner am Kampfort ab.\n\n[CUB2_05:CUBAN2]\nSchalte den feigen Heckenschützen aus!\n\n[CUB2_07:CUBAN2]\nDie kãmpfen wie Weiber! In Deckung!\n\n[CUB2_09:CUBAN2]\nHeckenschütze auf dem Dach!\n\n[CUB2_11:CUBAN2]\n~r~Du Idiot! Das Auto hãtten wir gebraucht!\n\n[CUB2_12:CUBAN2]\nHey, Amigo! Schön zu sehen, dass du's geschafft hast!\n\n[CUB2_13:CUBAN2]\nStinkendes Haitianer-Nest. Das werden wir komplett ausheben!\n\n[CUB2_14:CUBAN2]\nANGRIFF!\n\n[CUB2_15:CUBAN2]\nLos, meine Brüder, ANGRIFF!!\n\n[CUB2_16:CUBAN2]\nTommy, wir haben unseren mannhaften Mut bewiesen!\n\n[CUB2_17:CUBAN2]\nLass uns diesen Wagen voller Stoff nehmen und abhauen!\n\n[CUB2_18:CUBAN2]\n~g~Besorge dir ein Auto und hole die Kubaner ab.\n\n[CUB2_19:CUBAN2]\nWir werden kãmpfen wie Mãnner!\n\n[CUB2_21:CUBAN2]\nKãmpfen wie ganze Kerle!\n\n[CUB2_22:CUBAN2]\n~g~Schalte die restlichen Haitianer aus, damit die Kubaner vorrücken können.\n\n[CUB2_23:CUBAN2]\n~g~In Little Haiti wird es von Haitianern wimmeln, die sich an den Kubanern rãchen wollen. Sei vorsichtig.\n\n[CUB2_24:CUBAN2]\n~g~Kehre mit dem Van zu Robinas Café zurück und parke hinter dem Haus.\n\n{=================================== MISSION TABLE CUBAN3 ===================================}\n\n[CUB3_A:CUBAN3]\nAlberto? Einen Kaffee, Senor?\n\n[CUB3_B:CUBAN3]\nPaps, gib dieser falschen Schlange nichts.\n\n[CUB3_C:CUBAN3]\nDu hast zwei Gesichter, Tommy!\n\n[CUB3_D:CUBAN3]\nDu hast entweder zwei Gesichter oder du bist ein Feigling, Kleiner!\n\n[CUB3_E:CUBAN3]\nDie Haitianer, Mann, die lachen mich aus.\n\n[CUB3_F:CUBAN3]\nRuhig, ruhig. Was gibt es für Probleme?\n\n[CUB3_G:CUBAN3]\nSie lachen mich aus, Tommy. Mich!\n\n[CUB3_H:CUBAN3]\nUmberto Robina. Die tun, was sie wollen!\n\n[CUB3_I:CUBAN3]\nDie tun nicht, was sie wollen, Umberto. Sie tun, was du sie tun lãsst.\n\n[CUB3_J:CUBAN3]\nWas?\n\n[CUB3_K:CUBAN3]\nSoll jemand aus dem Weg gerãumt werden?\n\n[CUB3_L:CUBAN3]\nIch kann das machen, aber es kostet.\n\n[CUB3_M:CUBAN3]\nIch weiß, wir sind Brüder und alles, aber hier geht's um ein Geschãft.\n\n[CUB3_N:CUBAN3]\nTommy. Du bist ein echter Mann. Ein Geschãftsmann, ein Gentleman.\n\n[CUB3_O:CUBAN3]\nDie Haitianer, sie erwarten eine Schiffladung Stoff, richtig gutes Zeug.\n\n[CUB3_P:CUBAN3]\nWir schnappen es uns und erledigen sie.\n\n[CUB3_Q:CUBAN3]\nDu schnappst es dir, ich passe auf dich auf. Wie auf einen Bruder, einen Sohn.\n\n[CUB3_R:CUBAN3]\nIch glaube, Cash ist mir lieber als auf deinen Knien zu reiten, Amigo.\n\n[CUB3_01:CUBAN3]\nHey, Rico. Nettes Boot. Bist du bereit?\n\n[CUB3_03:CUBAN3]\n~g~Sammle alle Aktenkoffer mit Stoff und Geld ein.\n\n[CUB3_04:CUBAN3]\n~g~Bringe die Drogen und das Geld zu Umberto.\n\n[CUB3_05:CUBAN3]\nJa, Tommy. Also, sei ein guter Kapitãn heute.\n\n[CUB3_06:CUBAN3]\nMein Boot nützt mir nichts, wenn es durchlöchert ist, ok?\n\n[CUB3_07:CUBAN3]\n~g~Begib dich zu Rico. Er fãhrt dich zum Treffpunkt.\n\n[CUB3_02:CUBAN3]\n~g~ERLEDIGE ALLE HAITIANER AUF DEN BOOTEN!!\n\n[CUB3_08:CUBAN3]\nOh-oh... eine Bande Kubaner. Wir werden angegriffen!\n\n{=================================== MISSION TABLE CUBAN4 ===================================}\n\n[CUB4_A:CUBAN4]\nHey, Ladies. Wisst ihr, was ich mache?\n\n[CUB4_B:CUBAN4]\nIch erledige einen Haitianer. Und dann?\n\n[CUB4_C:CUBAN4]\nDann mache ich Liebe wie ein Mann.\n\n[CUB4_D:CUBAN4]\nWeißt du, Kleine? So in der Art.\n\n[CUB4_E:CUBAN4]\nPenner!\n\n[CUB4_F:CUBAN4]\nVollidiot.\n\n[CUB4_G:CUBAN4]\nHey, Baby, dich würde ich nicht mit 'ner Kneifzange anfassen!\n\n[CUB4_H:CUBAN4]\nUmberto Robina mag Frauen, keine Ziege mit Rock!\n\n[CUB4_I:CUBAN4]\nTommy!! Tommy, ich liebe dich, ich liebe dich! Lass uns gehen!\n\n[CUB4_J:CUBAN4]\nWohin denn? Kann ich nicht noch einen Kaffee trinken?\n\n[CUB4_K:CUBAN4]\nKeine Zeit! Außerdem habe ich erst einen getrunken.\n\n[CUB4_L:CUBAN4]\nWir nehmen uns die Haitianer vor.\n\n[CUB4_M:CUBAN4]\nTommy, wie erledigt man eine Schlange?\n\n[CUB4_N:CUBAN4]\nMan beißt sie in den Hintern! Hahaha!\n\n[CUB4_O:CUBAN4]\nWenn du es sagst, Umberto.\n\n[CUB4_P:CUBAN4]\nTommy, geh und besorge uns ein kleines haitianisches Auto.\n\n[CUB4_Q:CUBAN4]\nWenn du es hast, komm zurück und hol meinen Jungen ab\n\n[CUB4_R:CUBAN4]\nPepe, und fahre ihn zu den Haitianern.\n\n[CUB4_S:CUBAN4]\nDann begibst du dich zur Laboranlage der Haitianer und verwendest ihr Lösungsmittel als Sprengstoff.\n\n[CUB4_T:CUBAN4]\nBumm! Bye bye!\n\n[CUB4_U:CUBAN4]\nUmberto, was ist mit dir?\n\n[CUB4_V:CUBAN4]\nOh, ich halte mich raus und passe mit Paps auf das Café auf.\n\n[CUB4_W:CUBAN4]\nEr fühlt sich nicht besonders, weißt du.\n\n[CUB4_02:CUBAN4]\n~g~Die Bomben werden per Zeitzünder auf 45 sek. gestellt sein.\n\n[CUB4_07:CUBAN4]\nZum Lösungsmittel geht's hintenrum, Amigo.\n\n[CUB4_08:CUBAN4]\nHola, Amigos.\n\n[CUB4_09:CUBAN4]\nBueno. Haitian Putas. Muerte.\n\n[CUB4_10:CUBAN4]\nVamos.\n\n[CUB4_11:CUBAN4]\nGenau, vamos.\n\n[CUB4_12:CUBAN4]\nHey, wir brauchen ein haitianisches Gang-Auto!\n\n[CUB4_13:CUBAN4]\nOye, suchen wir unsere Muchachos!\n\n[CUB4_14:CUBAN4]\nFolge meinen Compadres.\n\n[CUB4_15:CUBAN4]\nOk, nur immer rein...\n\n[CUB4_16:CUBAN4]\nIch lege die Bombe. Gib mir Deckung.\n\n[CUB4_17:CUBAN4]\nRENN!\n\n[CUB4_18:CUBAN4]\nMann, das ist ein schönes Viertel hier...\n\n[CUB4_19:CUBAN4]\nDas ist doch eine Müllhalde, Mann.\n\n[CUB4_20:CUBAN4]\nIch kannte mal eine schöne Frau, die hat hier gewohnt.\n\n[CUB4_21:CUBAN4]\nDie machen gute Pizza hier.\n\n[CUB4_22:CUBAN4]\nHey, Mann! Du fãhrst wie ein Verrückter!\n\n[CUB4_23:CUBAN4]\nHast du dich verfahren, Mann?\n\n[CUB4_24:CUBAN4]\nDu hast Pepe vergessen, hole ihn.\n\n[CUB4_03:CUBAN4]\n~g~Bleib im Wagen, bis er sicher auf dem Gelãnde geparkt ist.\n\n[CUB4_26:CUBAN4]\n~g~Nimm dir Pepe, fahr Richtung Norden nach Little Haiti und klaue einen Voodoo.\n\n[CUB4_27:CUBAN4]\n~g~Triff dich mit Rico und den anderen Kubanern.\n\n[CUB4_28:CUBAN4]\n~g~Triff dich mit den anderen Kubanern bei der haitianischen Drogenfabrik.\n\n[CUB4_29:CUBAN4]\n~g~Gehe in jede der Markierungen, um an dieser Stelle eine Bombe zu legen.\n\n[CUB4_30:CUBAN4]\n~g~Wenn alle drei Bomben gelegt sind, entferne dich von der Fabrik bevor sie hochgeht.\n\n[CUB4_31:CUBAN4]\n~g~Mach, dass du von der Fabrik wegkommst!!\n\n[CUB4_32:CUBAN4]\n~g~Park den Wagen an der im Radar markierten Stelle und steig aus.\n\n[CUB4_06:CUBAN4]\n~r~Du bist nicht weit genug von der Basis weggekommen, wir mussten die Detonation abbrechen!\n\n{=================================== MISSION TABLE FINALE ===================================}\n\n[FIN1_01:FINALE]\nWas ist los?\n\n[FIN1_02:FINALE]\nTommy! Ah, gut, gut. Hör zu. Hör zu...\n\n[FIN1_03:FINALE]\nIch mag Fische. Ich liebe Fische.\n\n[FIN1_04:FINALE]\nIch liebe sie als Haustiere oder auch lecker zubereitet.\n\n[FIN1_05:FINALE]\nAber ich liebe sie nicht so sehr, dass ich als Fischfutter im Hafen enden will.\n\n[FIN1_06:FINALE]\nUnd jetzt kommen auf einmal deine italienischen Brüder an und wollen mir Zementschuhe verpassen. Und ich...\n\n[FIN1_07:FINALE]\nHalt den Mund, Ken. Setz dich.\n\n[FIN1_08:FINALE]\nLance, was lãuft hier, verdammt?\n\n[FIN1_09:FINALE]\nDeine Freunde aus dem Norden, Tommy. Die sind nicht sehr froh, dass du ihren Mann erledigt hast.\n\n[FIN1_10:FINALE]\nSie kommen heute, um nach dem Rechten zu sehen.\n\n[FIN1_11:FINALE]\nSie haben lãnger gebraucht, als ich dachte...\n\n[FIN1_12:FINALE]\nJungs, wir müssen denen ein für alle Mal klar machen, dass das mein Laden ist. MEINER!\n\n[FIN1_13:FINALE]\nKen, hol die erste Ladung von dem Falschgeld und pack 20 Mios in Aktenkoffer.\n\n[FIN1_14:FINALE]\nLance, du trommelst die anderen Jungs zusammen...\n\n[FIN2_01:FINALE]\nTommy!\n\n[FIN2_02:FINALE]\nWas ist? Keine Umarmung für deinen alten Freund?\n\n[FIN2_03:FINALE]\nIch war 15 Jahre weg vom Fenster,\n\n[FIN2_04:FINALE]\nbin nicht mehr auf dem Laufenden, was Manieren angeht.\n\n[FIN2_05:FINALE]\nImmer Wut im Bauch, hã, Tommy?\n\n[FIN2_06:FINALE]\nIch sag's ja, dein Temperament wird dir nochmal schlecht bekommen.\n\n[FIN2_07:FINALE]\nIn den Koffern sind 20 Millionen...\n\n[FIN2_08:FINALE]\nWie viele waren es denn? Zehn? Nein, elf Mãnner.\n\n[FIN2_09:FINALE]\nSo kommt man zu dem Spitznamen 'Harwood-Butcher'! Hehehe!\n\n[FIN2_10:FINALE]\nIch sollte EINEN Mann für dich erledigen! Die wussten, dass ich komme, Sonny...\n\n[FIN2_11:FINALE]\nWie redest du denn mit mir?\n\n[FIN2_12:FINALE]\nWie kommst du darauf, mich für diesen unglücklichen Zufall verantwortlich zu machen?\n\n[FIN2_13:FINALE]\nNimm einfach das Geld...\n\n[FIN2_14:FINALE]\nHolt das Geld!\n\n[FIN2_15:FINALE]\nWeißt du, Tommy, ich hab für dich getan, was nur ging. Himmel und Hölle in Bewegung gesetzt.\n\n[FIN2_16:FINALE]\nIch war dein Freund. Ich dachte, du nimmst Vernunft an. Kapierst, was gut fürs Geschãft ist.\n\n[FIN2_17:FINALE]\nIch hab dir vertraut, Tommy, und du hast mich enttãuscht.\n\n[FIN2_18:FINALE]\nAber wenigstens einer in deiner mickrigen Organisation weiß, wie man Geschãfte macht.\n\n[FIN2_19:FINALE]\nStimmt's, Lance?\n\n[FIN2_20:FINALE]\nSorry, Tommy. So lãuft's in Vice City. So lãuft das Geschãft.\n\n[FIN2_21:FINALE]\nDu hast uns verraten...\n\n[FIN2_22:FINALE]\nNein, ich hab DICH verraten, Tommy, nur DICH.\n\n[FIN2_23:FINALE]\nDie echten Piepen sind oben im Safe.\n\n[FIN2_24:FINALE]\nTommy, wie hast du dir das denn vorgestellt?\n\n[FIN2_25:FINALE]\nDachtest du, ich lass mich mit Blüten abspeisen?\n\n[FIN2_26:FINALE]\nDass ich den Schwanz einziehe und abhaue, um nicht das Gesicht zu verlieren?\n\n[FIN2_27:FINALE]\nNein.\n\n[FIN2_28:FINALE]\nIch wollte dich nur noch ein bisschen ãrgern, bevor ich dich fertig mache.\n\n[FIN3_01:FINALE]\nTommy?\n\n[FIN3_02:FINALE]\nOh Gott, Tommy! Was ist passiert?\n\n[FIN3_03:FINALE]\nWonach sieht's denn aus?\n\n[FIN3_04:FINALE]\nSieht aus, als wãr dein Anzug ruiniert!\n\n[FIN3_05:FINALE]\nUnd das war ein wunderbarer Anzug! Tommy, Herrgott, was ist passiert?\n\n[FIN3_06:FINALE]\nKleine Meinungsverschiedenheit mit einem Geschãftsfreund. Wie das so ist.\n\n[FIN3_07:FINALE]\nWenn ich eine Meinungsverschiedenheit mit einem Geschãftsfreund habe, schick ich ihm einen bösen Brief.\n\n[FIN3_08:FINALE]\nOder ich pinkle ihm in den Briefkasten, aber ich fang nicht den 3. Weltkrieg an.\n\n[FIN3_09:FINALE]\nVielleicht solltest du mal zu meinem Therapeuten gehen...\n\n[FIN3_10:FINALE]\nDieser Dreckskerl von Lance...\n\n[FIN3_11:FINALE]\nTommy, ich konnte den Kerl ja nie leiden.\n\n[FIN3_12:FINALE]\nEr ist neurotisch, unsicher, selbstsüchtig - Er ist ein Arschloch!\n\n[FIN3_13:FINALE]\nGut, dass du ihn fertig gemacht hast!\n\n[FIN3_14:FINALE]\nIch glaub auch nicht, dass wir nochmal Ãrger mit denen aus dem Norden kriegen...\n\n[FIN3_15:FINALE]\nDie aus dem Norden gibt's nãmlich nicht mehr.\n\n[FIN3_16:FINALE]\nGibt nur noch die im Süden.\n\n[FIN3_17:FINALE]\nMoment, verstehe ich dich richtig, Tommy, Heißt das...?\n\n[FIN3_18:FINALE]\nNa, was meinst du, was das heißt?\n\n[FIN3_19:FINALE]\nDass wir jetzt die Herren im Haus sind... ich meine, dass DU der Herr im Haus bist. Oh, Tommy...\n\n[FIN3_20:FINALE]\nWeißt du, Ken, das könnte der Beginn einer wunderbaren Geschãftsbeziehung sein...\n\n[FIN3_21:FINALE]\nSchließlich bist du ein hinterlistiger, mieser kleiner Dieb...\n\n[FIN3_22:FINALE]\nund ich bin ein verurteilter Psychopath und Dealer.\n\n[FIN3_23:FINALE]\nIch weiß. Ist das nicht wunderbar?\n\n[FIN_B1:FINALE]\n~g~Erledige den Verrãter ~y~Vance~g~.\n\n[FIN_B2:FINALE]\n~g~Erledige ~p~Sonny~g~, um die Sache ein für alle Mal zuende zu bringen.\n\n[FIN_B3:FINALE]\n~g~Die Mafia will dein Geld stehlen. Verteidige den Safe.\n\n[FIN_B4:FINALE]\n~g~Du hãltst nicht mehr lange durch. Hol dir unten ein wenig ~w~Energie~g~.\n\n[FIN_B5:FINALE]\n~g~Die Mafia stiehlt dein Geld. Verteidige den ~c~Safe.\n\n[FIN_B7:FINALE]\n~r~Die Mafia hat dein gesamtes Geld gestohlen.\n\n[DEFSAFE:FINALE]\n~g~Geh zurück zum Safe und verteidige ihn.\n\n{=================================== MISSION TABLE FIRETRK ===================================}\n\n[F_PASS1:FIRETRK]\nFeuer gelöscht!\n\n[F_FAIL2:FIRETRK]\n~r~Du kommst zu spãt!\n\n[F_CANC:FIRETRK]\n~r~Feuerwehr-Mission abgebrochen!\n\n[F_EXTIN:FIRETRK]\nFEUER:\n\n[F_START:FIRETRK]\n~g~Brennendes Fahrzeug in der Gegend von ~a~ gemeldet. Lösche den Brand.\n\n[SIREN_1:FIRETRK]\nUm die Sirenen dieses Fahrzeugs einzuschalten, drücke die ~h~~k~~VEHICLE_HORN~~w~.\n\n[SIREN_2:FIRETRK]\nUm die Sirenen dieses Fahrzeugs einzuschalten, drücke die ~h~~k~~VEHICLE_HORN~~w~.\n\n[FIREPRO:FIRETRK]\nFeuerwehr-Mission Level 12 abgeschlossen: Du bist jetzt absolut feuerfest!!\n\n[F_FAIL1:FIRETRK]\nFeuerwehr-Mission beendet.\n\n[F_STAR1:FIRETRK]\n~g~Brennende Fahrzeuge in der Gegend von ~a~ gemeldet. Lösche den Brand.\n\n[SPRAY_4:FIRETRK] { reVC update }\nBenutze die ~h~~k~~VEHICLE_FIREWEAPON~~w~-Taste, um die Wasserkanone abzufeuern und den ~h~~k~~VEHICLE_TURRETLEFT~~w~ und ~h~~k~~VEHICLE_TURRETRIGHT~~w~, um mit der Wasserkanone zu zielen.\n\n[SPRAY_1:FIRETRK] { reVC update }\nBenutze die ~h~~k~~VEHICLE_FIREWEAPON~~w~-Taste, um die Wasserkanone abzufeuern und den ~h~~k~~VEHICLE_TURRETLEFT~~w~ und ~h~~k~~VEHICLE_TURRETRIGHT~~w~, um mit der Wasserkanone zu zielen.\n\n{=================================== MISSION TABLE GENERA1 ===================================}\n\n[GEN1_I:GENERA1]\nFür diesen kleinen Gefallen werde ich Sie belohnen. Danach suchen wir Ihr Geld gemeinsam.\n\n[GEN1_A:GENERA1]\nMr. Vercetti!\n\n[GEN1_B:GENERA1]\nColonel.\n\n[GEN1_D:GENERA1]\nNein danke.\n\n[GEN1_E:GENERA1]\nEs ist mir peinlich, aber es scheint, unser Problem ist zum Teil auf das lose Mundwerk einer mir vertrauten Person zurückzuführen.\n\n[GEN1_F:GENERA1]\nSeit Jahren schleppe ich Gonzalez mit, aber nun erreicht seine Unfãhigkeit einen neuen Höhepunkt.\n\n[GEN1_G:GENERA1]\nEs ist nur gerecht, wenn Sie Gonzalez erledigen.\n\n[GEN1_H:GENERA1]\nWar er es? Mir geht es in erster Linie um das Geld.\n\n[GEN1_J:GENERA1]\nEr ist in seinem Penthouse, vermutlich halb betrunken. Nehmen Sie das hier.\n\n[GEN1_06:GENERA1]\nEr hat eine Kettensãge!!\n\n[GEN1_07:GENERA1]\nBleib mir vom Leib, du elender Mistkerl!\n\n[GEN1_08:GENERA1]\nGütiger Himmel, mein Leben ist ruiniert, und mein Aussehen dazu!\n\n[GEN1_10:GENERA1]\nIch werd dir dein Mundwerk stopfen!\n\n[GEN1_11:GENERA1]\nBleib stehen, du Fettsack!\n\n[GEN1_12:GENERA1]\nBleib stehen, und es geht ganz schnell!\n\n[GEN1_13:GENERA1]\nHör auf zu jammern, das interessiert keinen, Fettsack!\n\n[GEN1_C:GENERA1]\nDanke für Ihr Kommen. Setzen Sie sich. Hummer?\n\n[GEN1_04:GENERA1]\n~g~Benutze den Eingang, um Zugang zu Gonzalez' Dachwohnung zu erhalten.\n\n[GEN1_05:GENERA1]\n~g~Erledige Gonzalez!\n\n[GEN1_09:GENERA1]\nIch zahle dir das Doppelte, Tommy, das DOPPELTE!\n\n[GEN1_17:GENERA1]\n~g~Gonzalez versucht zu fliehen! Folge ihm durch die Türen und erledige ihn.\n\n[GEN1_18:GENERA1]\n~r~Gonzalez hat das Polizeirevier sicher erreicht!\n\n[GEN1_19:GENERA1]\n~g~Die Polizei von Vice City ist hinter dir her!\n\n[GEN1_20:GENERA1]\n~g~Steig in ein Fahrzeug.\n\n[GEN1_21:GENERA1]\n~g~Begib dich zur~h~ Pay 'N' Spray-Lackiererei~g~ in~h~ Vice Point~g~.\n\n[GEN1_22:GENERA1]\n~g~Bring dein Fahrzeug in die Lackiererei, um deinen ~h~Fahndungslevel~g~ loszuwerden und das Fahrzeug zu ~h~reparieren ~g~und ~h~umzuspritzen~g~. Kosten - ~h~$100~g~. Diesmal gratis.\n\n[GEN1_01:GENERA1]\nUm im Laufen eine Nahkampfattacke vorzubereiten, die~o~ |-Taste~w~ gedrückt halten.\n\n[GEN1_02:GENERA1]\nUm im Laufen eine Nahkampfattacke vorzubereiten, die~x~ /-Taste~w~ gedrückt halten.\n\n[GEN1_03:GENERA1]\nUm im Laufen eine Nahkampfattacke vorzubereiten, die~h~ R1-Taste~w~ gedrückt halten.\n\n[GEN1_14:GENERA1]\nLass die~h~ ~k~~PED_FIREWEAPON~~w~ los, um die Attacke auszuführen.\n\n[GEN1_15:GENERA1]\nLasse die~h~ ~k~~PED_FIREWEAPON~~w~ los, um die Attacke auszuführen.\n\n[GEN1_16:GENERA1]\nLasse die~h~ ~k~~PED_FIREWEAPON~~w~ los, um die Attacke auszuführen.\n\n[GEN1_23:GENERA1]\n~g~Geh durch die Türen zurück ins Erdgeschoss.\n\n{=================================== MISSION TABLE GENERA2 ===================================}\n\n[COL2_A:GENERA2]\nTommy! Setzen Sie sich zu mir.\n\n[COL2_B:GENERA2]\nSieht das nicht köstlich aus? Tapirschnauze?\n\n[COL2_C:GENERA2]\nÃh... Nein. Nein, danke.\n\n[COL2_D:GENERA2]\nTommy, Sie sind wie eine Pampas-Brise, die mich vom Gestank der Korruption befreit hat.\n\n[COL2_E:GENERA2]\nNatürlich muss ich so tun, als trauere ich um ihn und muss wie immer meine Arbeit machen.\n\n[COL2_F:GENERA2]\nDas bringt mich meinem Geld nicht nãher...\n\n[COL2_G:GENERA2]\nTommy, mein Freund, Sie sind hier nicht in Liberty. Hier regeln wir Dinge anders.\n\n[COL2_H:GENERA2]\nIch werde weiter nachforschen, zunãchst hãtte ich aber ein lukratives Geschãft abzuschließen.\n\n[COL2_I:GENERA2]\nFreunden tu ich gern einen Gefallen, Cortez...\n\n[COL2_J:GENERA2]\nSie sind ein guter Freund, Tommy. Ich wusste, ich kann auf Sie zãhlen.\n\n[COL2_K:GENERA2]\nSie müssen sich mit einem Kurier treffen, der wertvolle 'Technologie' für mich beschafft hat.\n\n[COL2_1:GENERA2]\nDie Regen ist sich sehr nass um diese Jahreszeit...\n\n[COL2_2:GENERA2]\nWas?\n\n[COL2_3:GENERA2]\nÃh, comment?\n\n[COL2_4:GENERA2]\nHören Sie, Cortez schickt mich. Geben Sie mir die verdammten Mikrochips.\n\n[COL2_5:GENERA2]\nOh... ok.\n\n[COL2_B1:GENERA2]\n~g~Triff dich mit dem Kurier im Einkaufszentrum.\n\n[COL2_B2:GENERA2]\n~g~Der Kurier flieht mit den Lenkwaffen-Chips. Lass ihn nicht entkommen!\n\n[COL2_B3:GENERA2]\n~g~Bring die Lenkwaffen-Chips zum Colonel.\n\n[COL2_F1:GENERA2]\n~r~Du hast die Kontaktperson erledigt!\n\n[COL2_F2:GENERA2]\n~r~Der Kurier ist hinüber. Schnapp dir die Lenkwaffen-Chips.\n\n[COL2_6A:GENERA2]\nKeine Bewegung, amerikanisches Imperialistenschwein! Das ist Eigentum des französischen Staates. Her damit!\n\n[BLIPHLP:GENERA2]\nDas Radar zeigt ein nach oben zeigendes Dreieck, das bedeutet, dass das Ziel sich in größerer Höhe befindet als der Spieler.\n\n[COL2_F3:GENERA2]\n~r~Die Lenkwaffen-Chips liegen auf dem Meeresgrund.\n\n[COL2_F4:GENERA2]\n~r~Der Kurier ist entkommen! Du hast dir die Chips durch die Lappen gehen lassen.\n\n{=================================== MISSION TABLE GENERA3 ===================================}\n\n[GEN3_49:GENERA3]\nLance' Gesundheitszustand:\n\n[GEN3_A:GENERA3]\nThomas, danke, dass Sie kommen.\n\n[GEN3_B:GENERA3]\nVerzeihen Sie, wenn ich gleich zur Sache komme.\n\n[GEN3_C:GENERA3]\nDiaz bat mich, eine kleinere geschãftliche Transaktion zu überwachen.\n\n[GEN3_D:GENERA3]\nWird hoffentlich besser laufen als die letzte, hah?\n\n[GEN3_E:GENERA3]\nDarum habe ich an Sie gedacht, mein Freund.\n\n[GEN3_F:GENERA3]\nIch habe etwas zu Ihrem Schutz beim Parkhaus deponiert.\n\n[GEN3_G:GENERA3]\nHolen Sie es ab. Und dann bewachen Sie Diaz' Mãnner bei dem Deal.\n\n[GEN3_H:GENERA3]\nDanke, Amigo.\n\n[GEN3_1:GENERA3]\nReißt sich alles selbst unter den Nagel, wie ich sehe.\n\n[GEN3_2:GENERA3]\nSag mal, ist das alles, was du kannst, mir dauernd nachzuschnüffeln? Komm mit und zeig mir, dass du was drauf hast.\n\n[GEN3_3:GENERA3]\nKönnte ich machen. Ich heiße übrigens Lance.\n\n[GEN3_5:GENERA3]\nDu musst Cortez' neuer Mann sein.\n\n[GEN3_6:GENERA3]\nBis ich was besseres finde...\n\n[GEN3_7:GENERA3]\nSie müssen bald hier sein. Wir sollten uns gute Beobachtungsposten suchen.\n\n[GEN3_8:GENERA3]\nOk! Ich nehm den Balkon, du kletterst auf das Dach drüben im Hof.\n\n[GEN3_9:GENERA3]\nIch lebe! Idioten! Und das nur wegen dir! Wie heißt du?\n\n[GEN3_10:GENERA3]\nTommy.\n\n[GEN3_11:GENERA3]\nWir sehen uns bald wieder, glaube ich!\n\n[GEN3_12:GENERA3]\nWo steckt denn Lance? Shit...\n\n[GEN3_14:GENERA3]\nTommy! Ich brauch Hilfe!\n\n[GEN3_15:GENERA3]\nKeine Sorge, ich hab alles im Griff!\n\n[GEN3_16:GENERA3]\nDiaz' Mãnner werden umgemãht!\n\n[GEN3_19:GENERA3]\n~g~Haitianer! Sie greifen an! Beschütze Diaz!\n\n[GEN3_20:GENERA3]\n~g~Begib dich zum Parkhaus. Hol dir die Waffe, die der Colonel dort für dich deponiert hat.\n\n[GEN3_22:GENERA3]\nDiaz' Gesundheitszustand:\n\n[GEN3_23:GENERA3]\n~g~Du hast Lance vergessen. Hole ihn!\n\n[GEN3_25:GENERA3]\n~r~Lance hat's erwischt!\n\n[GEN3_28:GENERA3]\n~g~Bring den Aktenkoffer zu Diaz zurück.\n\n[GEN3_29:GENERA3]\n~g~Hol dir den Aktenkoffer und bringe ihn zu Diaz zurück.\n\n[GEN3_30:GENERA3]\n~r~Er ist mit dem Geld entwischt! Dafür macht Diaz dich kalt!\n\n[GEN3_33:GENERA3]\n~r~Du sollst Diaz und seine Mãnner bewachen, nicht beschießen!\n\n[GEN3_34:GENERA3]\n~r~Es gibt keinen Deal, wenn du die Kubaner erledigst!\n\n[GEN3_35:GENERA3]\n~g~Er hat Diaz' Geld gestohlen!\n\n[GEN3_36:GENERA3]\n~g~Schnapp dir das Motorrad, stelle ihn und hol Diaz' Geld zurück!\n\n[GEN3_37:GENERA3]\n~g~. Die Kubaner kommen. Überwache den Deal. Pass auf Diaz und Lance auf.\n\n[GEN3_38:GENERA3]\n~r~Diaz hat's erwischt! Du hast versagt!\n\n[GEN3_39:GENERA3]\n~g~Begib dich zu deinem Beobachtungsposten die Treppe hoch.\n\n[GEN3_44:GENERA3]\n~g~Begib dich mit Lance zum Übergabeort und pass auf Diaz auf.\n\n[GEN3_45:GENERA3]\nSie müssen bald hier sein. Wir sollten uns gute Beobachtungsposten suchen.\n\n[GEN3_40:GENERA3] { reVC update }\nUm auf einem ~h~Motorrad ~w~sitzend ~h~geradeaus zu feuern~w~, drücke die ~h~~k~~VEHICLE_FIREWEAPON~.\n\n[GEN3_41:GENERA3] { reVC update }\nUm auf einem ~h~Motorrad ~w~sitzend ~h~geradeaus zu feuern~w~, drücke die ~h~~k~~VEHICLE_FIREWEAPON~.\n\n[GEN3_46:GENERA3]\nScheiße!\n\n[GEN3_47:GENERA3]\nTommy!\n\n[GEN3_48:GENERA3]\nVerdammt!\n\n[GEN3_50:GENERA3]\n~r~Du hast Diaz' Geld verloren! Versuch das nãchste Mal, das Geld nicht zu vernichten!\n\n[GEN3_51:GENERA3]\nNoch mehr verdammte Haitianer in einem beschissenen Van!\n\n[GEN3_54:GENERA3]\nSteht nicht rum, ihr Idioten! Schnappt euch diesen haitianischen Mistkerl!\n\n[GEN3_55:GENERA3]\nTommy! Ich bleibe hier und passe auf Diaz auf!\n\n[GEN3_18:GENERA3]\n~g~Die Kubaner kommen. Bleib in Diaz' Nãhe. Überwache den Deal. Pass auf Diaz und Lance auf.\n\n[GEN3_56:GENERA3]\n~r~Diaz ist hinüber, er ist in einen Hinterhalt geraten. Pass das nãchste Mal auf ihn auf!\n\n[GEN3_57:GENERA3]\nDie Kruger ist ein Sturmgewehr, das einem erlaubt, in der subjektiven Kamera-Einstellung manuell zu zielen.\n\n[GEN3_58:GENERA3]\nHalte die~h~ R1~w~-Taste gedrückt, um mit dem Sturmgewehr zu ~h~zielen~w~.\n\n[GEN3_59:GENERA3]\nHalte die~h~ L1~w~-Taste gedrückt, um mit dem Sturmgewehr zu ~h~zielen~w~.\n\n[GEN3_60:GENERA3]\nDrücke die ~h~~k~~PED_FIREWEAPON~~w~-Taste, um das Sturmgewehr ~h~abzufeuern~w~.\n\n[GEN3_61:GENERA3]\nDrücke die ~h~~k~~PED_FIREWEAPON~~w~-Taste, um das Sturmgewehr ~h~abzufeuern~w~.\n\n[GEN3_62:GENERA3]\nDrücke die ~h~~k~~PED_FIREWEAPON~~w~-Taste, um das Sturmgewehr ~h~abzufeuern~w~.\n\n[GEN3_63:GENERA3]\nAuf~h~ Motorrãdern ~w~kann man nicht nur im Vorbeifahren seitlich auf Ziele schießen, man kann auch ~h~geradeaus feuern~w~.\n\n[GEN3_64:GENERA3] { reVC update }\nUm auf einem Motorrad sitzend geradeaus zu feuern, drücke die ~h~~k~~VEHICLE_FIREWEAPON~~w~-Taste.\n\n[GEN3_65:GENERA3] { reVC update }\nUm auf einem Motorrad sitzend geradeaus zu feuern, drücke die ~h~~k~~VEHICLE_FIREWEAPON~~w~-Taste.\n\n[GEN3_66:GENERA3] { reVC update }\nUm auf einem Motorrad sitzend geradeaus zu feuern, drücke die ~h~~k~~VEHICLE_FIREWEAPON~~w~-Taste.\n\n[GEN3_67:GENERA3]\nDu brauchst eine Maschinenpistole, um auf einem Motorrad sitzend geradeaus zu feuern.\n\n[GEN3_53:GENERA3]\nMEIN GELD!\n\n[GEN3_52:GENERA3]\nDiese Haitianer denken sie könnten RICARDO DIAZ stürzen!?!\n\n{=================================== MISSION TABLE GENERA4 ===================================}\n\n[DETON:GENERA4]\nDETONATION:\n\n[COL4_3:GENERA4]\nKONVOI HALT!\n\n[COL4_6:GENERA4]\nWIR STEHEN UNTER FEINDLICHEM BESCHUSS!\n\n[COL4_7:GENERA4]\nWeg da von dem Panzer, Zivilist!\n\n[COL4_8:GENERA4]\nICH SAGTE, WEG DA! SOFORT!\n\n[COL4_9:GENERA4]\nAUF GEFECHTSPOSITIONEN!\n\n[COL4_11:GENERA4]\nSchaffen Sie den Zivilisten aus dem Weg, Soldat! - Sir, zu Befehl, Sir!\n\n[COL4_12:GENERA4]\nZivilist im PANZER! HALTET IHN AUF!\n\n[COL4_13:GENERA4]\nDies ist ein Militãrkonvoi, machen Sie den Weg frei!\n\n[COL4_14:GENERA4]\nErledigen sie ihn, Soldat.\n\n[COL4_15:GENERA4]\nSchaffen Sie das Zivilfahrzeug aus dem Weg! -Fahrzeug wird weggeschafft, Sir!\n\n[COL4_17:GENERA4]\nOK, EINHEIT WEITER!\n\n[COL4_18:GENERA4]\nDa ist jemand auf dem Panzer, Sir!\n\n[COL4_19:GENERA4]\nGehen Sie ein paar Donuts holen, Soldat! - Zu Befehl, Sir!\n\n[COL4_20:GENERA4]\nZiel erfasst, Sir.\n\n[COL4_21:GENERA4]\nHECKENSCHÜTZE!\n\n[COL4_22:GENERA4]\nIch seh zu, dass ich hier wegkomme!\n\n[COL4_23:GENERA4]\nEinsatz durchgeführt! Einheit, wegtreten! - Gehen wir ein paar Donuts essen.\n\n[COL4_24:GENERA4]\nSicherheitsmechanismus Delta India Echo aktiviert. Selbstzerstörung des Fahrzeugs eingeleitet!\n\n[COL4_26:GENERA4]\nMach dein Testament, dreckiger Kommunist!\n\n[COL4_B2:GENERA4]\n~r~Der Panzer ist wohlbehalten an seinem Ziel angekommen!\n\n[COL4_B5:GENERA4]\n~r~Der Panzer ist zerstört worden!\n\n[COL4_01:GENERA4]\nDiaz war sehr angetan und würde Sie gerne wiedersehen.\n\n[COL4_02:GENERA4]\nIst das eine gute Nachricht?\n\n[COL4_03:GENERA4]\nAber sicher! Obwohl mich der Verdacht beschleicht, dass Diaz für unsere Verluste verantwortlich war...\n\n[COL4_04:GENERA4]\nWie kommen Sie darauf?\n\n[COL4_05:GENERA4]\nMan erhebt keine Anschuldigungen gegen einen Mann wie Diaz. Ich habe nur laut nachgedacht.\n\n[COL4_06:GENERA4]\nEgal. Ich habe einen Vorschlag, der lukrativ für Sie sein könnte...\n\n[COL4_07:GENERA4]\nIch habe keine Zeit für weitere Auftrãge, Cortez.\n\n[COL4_08:GENERA4]\nEin Mann mit solch bedrohlichen Schulden sollte doch um jede Verdienstmöglichkeit dankbar sein. Hören Sie mich wenigstens an.\n\n[COL4_09:GENERA4]\nNa gut...\n\n[COL410:GENERA4]\nIch habe einen Kãufer für ein 'Militãrgerãt', das durch die Stadt transportiert wird. Beschaffen Sie es!\n\n[COL411:GENERA4]\nWenn Sie es haben, rufen Sie mich unverzüglich an...\n\n[COL4_B4:GENERA4]\n~g~Der Panzer ist abgeschlossen. Lass dir etwas einfallen, um die Besatzung herauszulocken.\n\n[COL4_1:GENERA4]\nWas ist mit dem Kanonier? - Weiß nicht, Sir!\n\n[COL4_4:GENERA4]\nLos, sehen Sie nach, Soldat! - Zu Befehl, Sir!\n\n[COL4_B1:GENERA4]\n~g~Besorge das militãrische Fahrzeug, das durch die Stadt gefahren wird.\n\n[COL4_B3:GENERA4]\n~g~Liefere den Panzer in der Garage des Colonels ab, bevor er sich selbst zerstört.\n\n[COL4_B6:GENERA4]\n~g~Finde einen Weg, den Panzer zu klauen!\n\n[COL4_B7:GENERA4]\n~g~Fahr den Panzer in die Garage.\n\n[COL4_B8:GENERA4]\n~g~Steig aus dem Panzer und verlasse die Garage.\n\n{=================================== MISSION TABLE GENERA5 ===================================}\n\n[COL5A_1:GENERA5]\nDie Lage erfordert ein eiliges Verschwinden, Amigo.\n\n[COL5A_2:GENERA5]\nWas gibt's für ein Problem?\n\n[COL5A_3:GENERA5]\nDie Franzosen wollen ihre Lenkwaffen-Chips wieder und nach dem letzten Zwischenfall\n\n[COL5A_4:GENERA5]\nzieht es mich in sicherere Gefilde.\n\n[COL5A_5:GENERA5]\nWãre es nicht sicherer zu fliegen?\n\n[COL5A_6:GENERA5]\nIch wãre erledigt, bevor ich eingecheckt hãtte. Außerdem muss ich Ware außer Landes schaffen.\n\n[COL5A_7:GENERA5]\nBrauchen Sie noch einen Bodyguard?\n\n[COL5A_8:GENERA5]\nSie, mein Freund, sind zehn Bodyguards wert. Hahaha.\n\n[COL5B_1:GENERA5]\nThomas, Sie haben mich beschützt und mir treu gedient.\n\n[COL5B_2:GENERA5]\nAber jetzt müssen Sie uns verlassen, ehe wir das offene Meer erreichen.\n\n[COL5B_4:GENERA5]\nDanke, Colonel.\n\n[COL5B_5:GENERA5]\nEine Bitte noch. Könnten Sie ein Auge auf Mercedes haben, solange ich weg bin?\n\n[COL5B_6:GENERA5]\nIch glaub zwar, sie kann auf sich selbst aufpassen, aber klar.\n\n[COL5B_7:GENERA5]\nDanke, mein Freund. Bis zu meiner Rückkehr.\n\n[COL5B_8:GENERA5]\nAdios, Amigo.\n\n[COL5_7:GENERA5]\nHören Sie auf, auf mich zu schießen!\n\n[COL5_9:GENERA5]\nTommy, die sollen aufhören, auf mich zu schießen!\n\n[COL5_10:GENERA5]\nIch genieße diplomatische Immunitãt.\n\n[COL5_11:GENERA5]\nNicht schießen, ich bin ein Colonel!\n\n[COL5_12:GENERA5]\nThomas, machen Sie sie fertig. Mein Land wird es Ihnen danken.\n\n[COL5_13:GENERA5]\nTommy, wir werden von den Franzosen überrannt!\n\n[COL5_14:GENERA5]\nTommy, wo ich hinsehe, überall Franzosen! Wie ich es hasse!\n\n[COL5_15:GENERA5]\nTommy, alles in Ordnung?\n\n[COL5_16:GENERA5]\nDas ist für Piaf und Gainesbourg und für euer dãmliches französisches Weißbrot!\n\n[COL5_1:GENERA5]\nBackbord! Backbord!\n\n[COL5_2:GENERA5]\nSie greifen von Steuerbord an!\n\n[COL5_3:GENERA5]\nDie Brücke da vorn!\n\n[COL5_4:GENERA5]\nSie haben einen Helikopter!\n\n[COL5_B1:GENERA5]\n~g~Beschütze den Colonel und seine Jacht um jeden Preis.\n\n[COL5_B2:GENERA5]\n~g~Geh nach vorn und rãume der Jacht des Colonels den Weg frei.\n\n[COL5_B3:GENERA5]\n~r~Der Colonel ist hinüber!\n\n[COL5_B4:GENERA5]\n~g~Schieße den angreifenden Helikopter vom Himmel.\n\n[COL5B_3:GENERA5]\nIch werde meine Privatbarkasse zu Wasser lassen. Sie gehört Ihnen, als Ausdruck meiner Dankbarkeit.\n\n[COL5_B5:GENERA5]\n~g~Schieß die Helikopter ab, gefãhrde nicht die Jacht.\n\n[COL5_B6:GENERA5]\n~g~Du hast keine Munition mehr. Hol dir an der Treppe des Oberdecks Nachschub.\n\n[COL5_B7:GENERA5]\n~g~Du hast nur noch wenig Energie. Hol dir an der Treppe des Oberdecks Nachschub.\n\n{=================================== MISSION TABLE HAIT1 ===================================}\n\n[HAM1_A:HAIT1]\nHallo? Hallo?\n\n[HAM1_B:HAIT1]\nKomm rein, mein Lieber, und ruh dich aus.\n\n[HAM1_C:HAIT1]\nDu musst der große böse Mann sein, von dem mein Großvater erzãhlt hat.\n\n[HAM1_D:HAIT1]\nEr erzãhlte immer von dir, wenn er zu Besuch kam,\n\n[HAM1_E:HAIT1]\nund von den anderen, die auf dich warten.\n\n[HAM1_F:HAIT1]\nTja, wir müssen alle mal sterben, aber du...\n\n[HAM1_G:HAIT1]\n....in deiner Haut möchte ich dann nicht stecken. Hehehe!\n\n[HAM1_H:HAIT1]\nEs hieß, ich soll hierher kommen.\n\n[HAM1_I:HAIT1]\nKannst du sie hören?\n\n[HAM1_J:HAIT1]\nSie rufen deinen Namen, Junge. Die müssen ziemlich scharf auf dich sein, was?\n\n[HAM1_K:HAIT1]\nAber wenn du der alten Tante Poulet hilfst, hilft sie dir vielleicht auch.\n\n[HAM1_L:HAIT1]\nVielleicht kann sie dir danach einen kleinen Talisman schenken.\n\n[HAM1_M:HAIT1]\nEin bisschen Magie, die den Mãnnern des Gesetzes schlechte Augen macht, hmm?\n\n[HAM1_N:HAIT1]\nHören Sie, das ist alles sehr, ãh... Sie geben mir was?\n\n[HAM1_O:HAIT1]\nIch...ich...ich glaube, ich bin hier falsch.\n\n[HAM1_P:HAIT1]\nErweise mir ein paar Gefãlligkeiten, Tommy...\n\n[HAM1_Q:HAIT1]\nDie Kubaner, miese, hochnãsige Narren, hmmm,\n\n[HAM1_R:HAIT1]\nhaben meine lieben Haiti-Boys sehr geãrgert.\n\n[HAM1_S:HAIT1]\nJetzt haben sie den Polizisten erzãhlt, wo ich meine Pülverchen versteckt habe.\n\n[HAM1_T:HAIT1]\nSie denken, das sind Drogen, diese Dummköpfe.\n\n[HAM1_U:HAIT1]\nSei ein braver Bub, Tommy, und hole Tante Poulet die Pülverchen.\n\n[HAM1_V:HAIT1]\nJa, ja. Sicher, sicher.\n\n[HAM1_1:HAIT1]\n~g~Die Cops nãhern sich dem Zeug. Hol es, bevor sie dort sind.\n\n[HAM1_2:HAIT1]\n~r~Die Cops waren schneller bei dem Zeug!\n\n[HAM1_3:HAIT1]\n~g~Bring das Zeug zum Unterschlupf!\n\n[HAM1_4:HAIT1]\n~g~Gut. Jetzt das nãchste!\n\n[HAM1_6:HAIT1]\n~r~Das Zeug wurde vernichtet, du Idiot!\n\n[HAM1_7:HAIT1]\n~g~Die Cops haben das Zeug! Hol es dir wieder, bevor sie weg sind!\n\n[HAM1_8:HAIT1]\n~g~Die Cops sind unterwegs, um das Zeug abzuholen. Beeil dich!\n\n[HAT_1A:HAIT1]\n~g~Keine Bewegung, Freundchen!\n\n{=================================== MISSION TABLE HAIT2 ===================================}\n\n[HAT2_B1:HAIT2]\n~g~Begib dich zu dem Wagen, in dem die fliegenden Bomben sind.\n\n[HAT2_B2:HAIT2]\nSchalte die Kubaner aus...\n\n[HAT2_B4:HAIT2]\n.... und zerstöre ihre Boote!\n\n[HAT2_B5:HAIT2]\n~g~Die Kubaner hauen ab. Lass sie nicht entkommen!\n\n[HAT2_B6:HAIT2]\n~r~Das ferngesteuerte Flugzeug ist außer Reichweite!\n\n[HAT2_B7:HAIT2]\n~g~Einer der Kubaner flieht in einem Auto. Lass ihn nicht entkommen!\n\n[HAT2_B8:HAIT2]\n~r~Du hast keine ferngesteuerten Flugzeuge mehr!\n\n[HAT2_B9:HAIT2]\nFerngesteuerte Flugzeuge:\n\n[HAT2_1:HAIT2]\nOh. Entschuldigung, ich muss die falsche Adresse haben...\n\n[HAT2_2:HAIT2]\nDu kannst gern reinkommen und dich bei einer Tasse Tee ausruhen.\n\n[HAT2_3:HAIT2]\nHast du etwas für mich, Tommy?\n\n[HAT2_4:HAIT2]\nJa...\n\n[HAT2_5:HAIT2]\nDas kommt mir so bekannt vor hier. Ein Geruch aus meiner Kindheit - das muss ein Déjà-vu sein...\n\n[HAT2_6:HAIT2]\nTommy, du kannst was für mich tun, ich werd's dir erklãren. Hör gut zu, ja?\n\n[HAT2_7:HAIT2]\nSie sehen aus wie jemand, den...\n\n[HAT2_8:HAIT2]\nDie Kubaner haben schnelle Boote, mit denen transportieren sie Drogen übers Meer.\n\n[HAT2_9:HAIT2]\nDavon leben sie.\n\n[HAT2_10:HAIT2]\nMein Neffe hat kleine fliegende Bomben gebaut, um ihnen das Handwerk zu legen.\n\n[HAT2_11:HAIT2]\nLass ihre Boote in die Luft fliegen.\n\n[HAT2_12:HAIT2]\nTja, danke für den Tee.\n\n[HAT2_B3:HAIT2] { reVC update }\nUm eine Bombe abzuwerfen, drück die ~h~~k~~VEHICLE_FIREWEAPON~~w~-Taste. ~h~~k~~VEHICLE_ENTER_EXIT~~w~-Taste zum Beenden.\n\n{=================================== MISSION TABLE HAIT3 ===================================}\n\n[HAM3_A:HAIT3]\nHallo, hallo, ich, ãh, ich suche hier jemanden...\n\n[HAM3_B:HAIT3]\nDu siehst hungrig aus, Tommy.\n\n[HAM3_C:HAIT3]\nKenne ich Sie?\n\n[HAM3_D:HAIT3]\nSei jetzt still.\n\n[HAM3_E:HAIT3]\nEine Gefãlligkeit noch, dann lasse ich dich gehen, Tommy.\n\n[HAM3_F:HAIT3]\nMeine Jungs haben die Kubaner zum Kampf gefordert.\n\n[HAM3_G:HAIT3]\nAber ohne Kanonen.\n\n[HAM3_H:HAIT3]\nHmm, aber die Kubaner werden ihr blaues Wunder erleben.\n\n[HAM3_I:HAIT3]\nWenn sie in den Straßen kãmpfen, nimmst du dieses Gewehr und rãumst auf.\n\n[HAM3_J:HAIT3]\nKeiner sieht dich, keiner hört dich.\n\n[HAM3_K:HAIT3]\nWenn du das für mich tust, Tommy, dann kommst frei aus meinen Schürzenbãndern.\n\n[HAM3_1:HAIT3]\n~g~Wir müssen gewinnen. Werden alle Haitianer erledigt, haben wir verloren.\n\n[HAM3_3:HAIT3]\n~g~Vermutlich werden die Kubaner schummeln. Sei auf der Hut!\n\n[HAM3_4:HAIT3]\n~r~Du wurdest entdeckt! Die Mission ist fehlgeschlagen!\n\n[HAM3_5:HAIT3]\n~g~Du musst die Kubaner aus der Distanz erwischen. Man darf dich nicht sehen.\n\n[HAM3_8:HAIT3]\n~g~Es gibt Verluste unter den Haitianern! Du musst besser zielen!\n\n[HAM3_7:HAIT3]\n~g~Vorsicht! Die Kubaner haben Verstãrkung mitgebracht. Schalte sie alle aus!!\n\n[HAM3_2:HAIT3]\n~r~Die Haitianer sind weg vom Fenster!\n\n[HAM3_L:HAIT3]\nOkay, Tantchen...\n\n{=================================== MISSION TABLE HOTEL ===================================}\n\n[INTB_A:HOTEL]\nTommy! Tommy, wir haben uns lange nicht gesehen.\n\n[INTB_B:HOTEL]\nHallo, Sonny.\n\n[INTB_C:HOTEL]\nIch weiß, ich weiß. Dir kommen vor Rührung die Trãnen.\n\n[INTB_D:HOTEL]\n15 Jahre ist es her - dabei kommt's mir vor, als wãr's gestern gewesen.\n\n[INTB_E:HOTEL]\nDU hast leicht reden.\n\n[INTB_F:HOTEL]\nHey, für die Familie in den Knast zu gehen, ist kein Zuckerschlecken,\n\n[INTB_G:HOTEL]\naber die Familie zeigt sich für sowas erkenntlich, ok?\n\n[INTB_H:HOTEL]\nAlso, wie ist der Deal gelaufen - hast du Schnee an der Hand?\n\n[INTB_I:HOTEL]\nSonny, wir sind reingelegt worden. Der Deal war eine Falle. Harry und Lee sind tot.\n\n[INTB_J:HOTEL]\nDas ist nicht dein Ernst, Tommy. Du hast doch hoffentlich noch das Geld.\n\n[INTB_K:HOTEL]\nNein, Sonny... Ich hab das Geld nicht mehr.\n\n[INTB_L:HOTEL]\nDas war mein Geld, Tommy. MEIN GELD!\n\n[INTB_M:HOTEL]\nVersuch bloß nicht, mich reinzulegen, Tommy. Mich legt man nicht rein, das weißt du!\n\n[INTB_N:HOTEL]\nWarte, Sonny.\n\n[INTB_O:HOTEL]\nDu hast mein Wort darauf, dass ich dir dein Geld wiederbeschaffe. Und die Drogen.\n\n[INTB_P:HOTEL]\nUnd ich liefere dir die Kerle, die dahinterstecken.\n\n[INTB_Q:HOTEL]\nDas weiß ich doch. Du bist kein Idiot, Tommy, aber ich warne dich - ich bin auch keiner.\n\n[INTB_R:HOTEL]\nWenn du's nicht wãrst - ein anderer wãr lãngst fãllig!\n\n[INTB_S:HOTEL]\nAber uns beide verbindet eine alte Freundschaft. Ich lasse dich das regeln.\n\n[INTB_T:HOTEL]\nSonny, du hast mein Ehrenwort.\n\n[INTB_U:HOTEL]\nDu hörst von mir.\n\n{=================================== MISSION TABLE ICECRE1 ===================================}\n\n[ICC1_1:ICECRE1]\n~g~Benutze deinen Eis-Wagen, um in Vice City Drogen zu verkaufen.\n\n[ICC1_2:ICECRE1]\n~g~Parke den Eis-Wagen und drücke ~h~~k~~VEHICLE_HORN~~w~, um den Eiscreme-Jingle abzuspielen, damit deine Kunden wissen, dass du Ware zu verkaufen hast.\n\n[ICC1_3:ICECRE1]\n~g~Für jede Transaktion bekommst du Geld. Aber je mehr Transaktionen du tãtigst, desto stãrker wird die Polizei auf dich aufmerksam.\n\n[ICC1_4:ICECRE1]\n~g~In dieser Gegend sind keine Kunden. Versuche es woanders.\n\n[ICC1_5:ICECRE1]\nGetãtigte Deals:\n\n[ICC1_6:ICECRE1]\n~g~Nimm den Mr. Whopee, um in Vice City Cherry Popper-Produkte zu vertreiben.\n\n[ICC1_7:ICECRE1]\n~g~Für jede Transaktion bekommst du Geld. Aber je mehr Transaktionen du tãtigst, desto stãrker wird die Polizei auf dich aufmerksam.\n\n[ICC1_8:ICECRE1]\n~g~Um eine Transaktion zu tãtigen, ~h~parke deinen Wagen ~g~und drücke die ~h~~k~~VEHICLE_HORN~~g~, um den Eiscreme-Jingle abzuspielen, damit deine Kunden wissen, dass du Ware zu verkaufen hast.\n\n[ICC1_9:ICECRE1]\n~g~Andere Gangs werden es nicht gern sehen, dass du in ihrem Revier Geschãfte machst, du musst also mit Feindseligkeiten rechnen.\n\n[ICC1_10:ICECRE1]\n~g~Du hast ~1~ Deals getãtigt!\n\n[ICC1_11:ICECRE1]\n~g~Du hast ~1~ Deal getãtigt.\n\n[ICC1_12:ICECRE1]\nOBJEKT ERWORBEN!\n\n[ICC1_13:ICECRE1]\n~r~Du hast keine Deals getãtigt!\n\n[ICC1_14:ICECRE1]\nEISCREME-MISSIONEN ERFÜLLT\n\n[ICC1_15:ICECRE1]\n~g~Die Eiscremefabrik generiert nun bis zu $~1~ Einkünfte. Hol dir das Geld regelmãßig ab.\n\n[ICC1_16:ICECRE1]\n~g~Nimm den Mr. Whoopee, um in Vice City Cherry Popper-Produkte zu vertreiben.\n\n[ICE_AT1:ICECRE1]\nEISCREMEFABRIK-MISSIONEN ERFÜLLT\n\n[ICE_AT2:ICECRE1]\n~g~Die Cherry Popper-Fabrik generiert nun bis zu $~1~ Einkünfte. Hol dir das Geld regelmãßig ab.\n\n[ICC1_17:ICECRE1]\nStoff-Auslieferungs-Mission beendet\n\n[ICC1_18:ICECRE1]\nEiscremeverkauf insgesamt: $~1~\n\n[ICC1_19:ICECRE1]\nInsgesamt getãtigte Deals: ~1~\n\n{=================================== MISSION TABLE ICECUT ===================================}\n\n[ICC1_M:ICECUT]\nSie sind schmutzige, verrotzte, verlauste, eklige, sabbernde kleine...\n\n[ICC1_I:ICECUT]\nEin Baby... ein widerwãrtiges, grãßliches, ekelhaftes kleines Gör!\n\n[ICC1_J:ICECUT]\nMammi liebt dich nicht. Du kleines Stück Scheiße!\n\n[ICC1_A:ICECUT]\nWer sind Sie?\n\n[ICC1_B:ICECUT]\nDer neue Inhaber dieses Ladens.\n\n[ICC1_C:ICECUT]\nSind Sie, oder waren Sie je ein Kind?\n\n[ICC1_D:ICECUT]\nWas soll denn das heißen?\n\n[ICC1_E:ICECUT]\nWaren Sie je ein Kind?\n\n[ICC1_F:ICECUT]\nJa! Immer mit der Ruhe! Was ist denn mit Ihnen los?\n\n[ICC1_G:ICECUT]\nIch wusste es. Ein Kind.\n\n[ICC1_H:ICECUT]\nEin schmutziges, stinkendes, verrotztes, verlaustes, nölendes kleines Baby!\n\n[ICC1_K:ICECUT]\nAu! Beruhigen Sie sich doch!\n\n[ICC1_L:ICECUT]\nIch HASSE Babies. Und ich hasse Kinder.\n\n[ICC1_N:ICECUT]\nEs reicht jetzt!\n\n[ICC1_P:ICECUT]\nSie stellen doch Softeis her, oder? Das essen doch nur Kinder.\n\n[ICC1_Q:ICECUT]\nSind Sie komplett irre?\n\n[ICC1_R:ICECUT]\nErklãren Sie mir das mal - warum Kinder glücklich machen, wenn Sie sie hassen?\n\n[ICC1_S:ICECUT]\nOh, du dãmliches, verrotztes, verlaustes-\n\n[ICC1_T:ICECUT]\nSchluss jetzt!\n\n[ICC1_U:ICECUT]\n- Gör!\n\n[ICC1_V:ICECUT]\nDas Eis ist nur Tarnung!\n\n[ICC1_W:ICECUT]\nWir vertreiben auch andere Waren. Nicht-Milchprodukte.\n\n[ICC1_X:ICECUT]\nUnd wenn ich ein Kind sehe, dann weiß ich, was ich mit ihm anfange.\n\n[ICC1_Y:ICECUT]\nNicht wahr, Kinderchen? Ja, ja. Mammi hat euch gar nicht lieb.\n\n[ICC1_Z:ICECUT]\nSie HASST euch!\n\n[ICC1_ZA:ICECUT]\nOBJEKT ERWORBEN!\n\n{=================================== MISSION TABLE INTRO ===================================}\n\n[INT1_A:INTRO]\nTommy Vercetti...Hah! Shit.\n\n[INT1_B:INTRO]\nHãtte nicht gedacht, dass der noch mal rauskommt.\n\n[INT1_C:INTRO]\nEr hat den Kopf eingezogen. War fast vergessen.\n\n[INT1_D:INTRO]\nAber bald wird man sich an ihn erinnern.\n\n[INT1_E:INTRO]\nWenn man ihn wieder durch ihre Viertel tigern sieht.\n\n[INT1_F:INTRO]\nWird schlecht fürs Geschãft sein.\n\n[INT1_G:INTRO]\nTja, was sollen wir machen, Sonny?\n\n[INT1_H:INTRO]\nWir machen auf alte Kumpels und schicken ihn woanders hin. Ok?\n\n[INT1_I:INTRO]\nWir wollten doch sowieso nach Süden expandieren, oder?\n\n[INT1_J:INTRO]\nIn Vice City liegt zurzeit das Geld auf der Straße.\n\n[INT1_K:INTRO]\nDie Kolumbianer, die Mexikaner,\n\n[INT1_L:INTRO]\nja, sogar die kubanischen Flüchtlinge machen alle glãnzende Geschãfte.\n\n[INT1_M:INTRO]\nAber das geht nur mit Drogen, Sonny.\n\n[INT1_N:INTRO]\nAber keine der Familien rührt dieses Zeug an!\n\n[INT1_O:INTRO]\nDie Zeiten ãndern sich.\n\n[INT1_P:INTRO]\nDie Familien können nicht wegsehen, wãhrend unsere Feinde groß abkassieren.\n\n[INT1_Q:INTRO]\nAlso schicken wir jemanden für die Drecksarbeit da runter\n\n[INT1_R:INTRO]\nund schneiden uns 'ne hübsche Scheibe ab. Ok?\n\n[INT1_S:INTRO]\nWer ist unser Kontaktmann da unten?\n\n[INT1_T:INTRO]\nKen Rosenberg, ein Idiot von einem Anwalt.\n\n[INT1_U:INTRO]\nWie soll der Vercetti im Zaum halten?\n\n[INT1_V:INTRO]\nMuss er gar nicht.\n\n[INT1_W:INTRO]\nWir lassen ihn einfach auf Vice City los.\n\n[INT1_X:INTRO]\nWir geben ihm ein bisschen Startgeld, ok?\n\n[INT1_Y:INTRO]\nWir warten ein paar Monate.\n\n[INT1_Z:INTRO]\nDann fahren wir hin\n\n[INT1_A1:INTRO]\nund schauen mal bei ihm rein, klar?\n\n[INT1_A2:INTRO]\nMal sehen, wie er sich macht.\n\n[INT2_A:INTRO]\nHey, hey, Jungs! Ich bin, ãh, Ken Rosenberg. Ha, ha, sehr gut, hey!\n\n[INT2_B:INTRO]\nTja, ãh, ich soll euch zu dem Trefffen fahren, okay?\n\n[INT2_C:INTRO]\nIch hab mit den Lieferanten geredet, und die würden,\n\n[INT2_D:INTRO]\nliebend gern mit uns ins Geschãft kommen. Und, ãh,\n\n[INT2_E:INTRO]\nwenn alles gut geht, dann dürfte da\n\n[INT2_F:INTRO]\nein Haufen Kohle für uns drin sein. Und das ist doch, na ja...\n\n[INT2_G:INTRO]\ngut...\n\n[INT2_H:INTRO]\nOkay. Es sind zwei Brüder, ok?\n\n[INT2_I:INTRO]\nDer eine schmeißt, ãh, den Laden,\n\n[INT2_J:INTRO]\nder andere macht die Flüge.\n\n[INT2_K:INTRO]\nDie arbeiten von Mexiko aus,\n\n[INT2_M:INTRO]\nSie haben eine Farm in Panama.\n\n[INT2_N:INTRO]\nOkay, passt auf, Jungs,\n\n[INT2_O:INTRO]\nwenn wir dort ankommen, sollte ich im Auto bleiben,\n\n[INT2_P:INTRO]\noder soll ich mit reinkommen?\n\n[INT2_Q:INTRO]\nNein. Bleib im Wagen.\n\n[INT2_R:INTRO]\nWisst ihr was, ich hab's mir überlegt.\n\n[INT2_S:INTRO]\nIch pass auf den Wagen auf.\n\n[INT3_A:INTRO]\nOk, das sind sie, da im Helikopter.\n\n[INT3_B:INTRO]\nOk, das ganze lãuft so ab:\n\n[INT3_C:INTRO]\nDie wollen eine saubere Übergabe auf offenem Gelãnde.\n\n[INT3_D:INTRO]\nAlles klar? Ok, dann wollen wir mal.\n\n[INT3_E:INTRO]\nOk, ganz ruhig jetzt.\n\n[INT3_F:INTRO]\nIch bin hier. Der Wagen lãuft, Baby!\n\n[INT3_G:INTRO]\nHast du's?\n\n[INT3_H:INTRO]\n100% astreines kolumbianisches Koks, mein Freund.\n\n[INT3_I:INTRO]\nDie Kohle?\n\n[INT3_J:INTRO]\nZehner und Zwanziger. Gebrauchte Scheine.\n\n[INT3_L:INTRO]\nLos, los, weg hier! Fahr los!\n\n[INT4_A:INTRO]\nGearscht. Wir sind voll gearscht!\n\n[INT4_B:INTRO]\nDas ist wieder typisch.\n\n[INT4_C:INTRO]\nDa passe ich eine einziges Mal nicht auf,\n\n[INT4_D:INTRO]\nund prompt kriege ich eins reingewürgt.\n\n[INT4_E:INTRO]\nHier!\n\n[INT4_F:INTRO]\nHör endlich auf zu jammern. Du lebst schließlich noch, oder?\n\n[INT4_G:INTRO]\nLass mich hier raus.\n\n[INT4_H:INTRO]\nSchaff das Auto weg und leg dich schlafen.\n\n[INT4_I:INTRO]\nIch komme morgen zu dir ins Büro, dann sehen wir weiter.\n\n[INT4_J:INTRO]\nOk, gute Idee. Ich leg mich erstmal hin.\n\n[INT4_K:INTRO]\nWas hast du vor?\n\n[INT4_L:INTRO]\nIch geh zurück in mein Hotel.\n\n[INT4_M:INTRO]\nIch muss nachdenken, was schiefgelaufen ist.\n\n[INT4_N:INTRO]\nOk.\n\n[INTRO1:INTRO]\nDa passe ich ein einziges Mal nicht auf, und prompt kriege ich eins reingewürgt.\n\n[INTRO2:INTRO]\nLeg dich schlafen.\n\n[INTRO3:INTRO]\nWas hast du vor?\n\n[INTRO4:INTRO]\nIch komme morgen zu dir ins Büro, dann sehen wir weiter.\n\n[INT3_K:INTRO]\nTja, der Deal kann steigen, mein Freund.\n\n[INT3_M:INTRO]\nZeig her.\n\n[INT2_L:INTRO]\nNein, nein, nein, wartet...\n\n{=================================== MISSION TABLE KENT1 ===================================}\n\n[KPM1_A:KENT1]\nOk, du Knallkopf, ich werde deine Haut retten.\n\n[KPM1_B:KENT1]\nWas sagst du?\n\n[KPM1_C:KENT1]\nDu kennst doch Diaz, den Idioten, den Koks-König?\n\n[KPM1_D:KENT1]\nEr hat deinen Freund Lance. Es heißt, dein Kumpel wollte ihm an den Kragen.\n\n[KPM1_E:KENT1]\nHat ihn aber fast den eigenen gekostet hat, falls du weißt, was ich meine.\n\n[KPM1_F:KENT1]\nWo hat er ihn hingebracht? Im Klartext!\n\n[KPM1_G:KENT1]\nMach dich mal locker! Sie haben ihn beim Schrottplatz erwischt.\n\n[KPM1_H:KENT1]\nVerdammt noch mal. Psycho.\n\n[KPM1_2:KENT1]\n~r~Du solltest Lance lebend da rausholen!\n\n[KPM1_3:KENT1]\nLance' Gesundheitszustand:\n\n[RESC_1:KENT1]\nKannst du eine Waffe halten?\n\n[RESC_2:KENT1]\nKlar, glaub schon. Freut mich, dich zu sehen.\n\n[RESC_3:KENT1]\nLos, wir verschwinden von hier.\n\n[RESC_4:KENT1]\nDank dir ist mein ganzer schöner Plan im Eimer. Das hast du sauber vermasselt, Lance.\n\n[RESC_5:KENT1]\nEr hat meinen Bruder auf dem Gewissen. Soll ich ihm den Rasen mãhen?\n\n[RESC_6:KENT1]\nWir müssen diesen Diaz erledigen bevor er uns erledigt.\n\n[RESC_7:KENT1]\nLass dich zusammenflicken, dann treffen wir uns auf der Brücke nach Star Island, ok?\n\n[RESC_8:KENT1]\nOk, alles klar.\n\n[KPM1_1:KENT1]\n~g~Lance wird auf dem Schrottplatz gefangengehalten. Rette ihn!\n\n[KPM1_4:KENT1]\n~g~Bring Lance ins Krankenhaus!\n\n[M_PASSN:KENT1]\nMISSION ERFÜLLT!\n\n[KPM1_5:KENT1]\n~g~Diaz' Leute sind hinter euch her. Bring Lance ins Krankenhaus.\n\n{=================================== MISSION TABLE KICKSTT ===================================}\n\n[KICK1_2:KICKSTT]\n~r~Du warst nicht schnell genug bei der Maschine!\n\n[KICK1_7:KICKSTT]\n~r~Du hast die Maschine geschrottet!\n\n[KICK1_8:KICKSTT]\n~g~Setz dich auf das Motorrad!\n\n[KICK1_T:KICKSTT]\nBENÖTIGTE ZEIT:\n\n[KICKTM:KICKSTT]\n~b~ZEIT: ~1~:~1~\n\n[KICKTM2:KICKSTT]\n~b~ZEIT: ~1~:0~1~\n\n[GETBIKE:KICKSTT]\n~g~Du hast ~1~ Sekunden, um zu einer Gelãndemaschine zurückzukehren, bevor die Mission endet.\n\n[KICK1_1:KICKSTT]\n~g~Absolviere den Kurs so schnell wie möglich.\n\n[KICK1_6:KICKSTT]\n~g~Gut gemacht!\n\n[KICK_10:KICKSTT]\n~G~Nimm den Sanchez und absolviere den Kurs, indem du alle Checkpoints passierst.\n\n[KICK_12:KICKSTT]\n~r~Du hast es vermasselt!\n\n[KICK_13:KICKSTT]\n~r~Du hast zu lange gebraucht!\n\n[KICK_11:KICKSTT]\n~g~Um die Mission zu beenden, stell dich zu Fuß in die ~q~rosa Markierung~g~.\n\n{=================================== MISSION TABLE LAWYER1 ===================================}\n\n[LAW1_A:LAWYER1]\nLeg dich schlafen, sagt er -\n\n[LAW1_B:LAWYER1]\n- Ich sitz die ganze Nacht im Dunklen hier rum und trink Kaffee!\n\n[LAW1_C:LAWYER1]\nDas ist eine Katastrophe. Wir sind so gearscht, Mann!\n\n[LAW1_D:LAWYER1]\nDiese Gorillas, die kommen hier runter und reißen mir den Kopf ab. Es ist beinahe zum lachen!\n\n[LAW1_E:LAWYER1]\nDafür habe ich NICHT Jura studiert. Ok, was sollen wir jetzt machen?\n\n[LAW1_F:LAWYER1]\nSei still, setz dich hin und bleib ruhig. Ich sag dir, was wir machen.\n\n[LAW1_G:LAWYER1]\nDu findest raus, wer das Koks geklaut hat - und ich nehm ihn mir vor.\n\n[LAW1_H:LAWYER1]\nGute Idee. SEHR gute Idee. Lass mich nachdenken, lass mich nachdenken.\n\n[LAW1_I:LAWYER1]\nOH! Da gibt es diesen Colonel a.D., Colonel Juan Garcia Cortez.\n\n[LAW1_J:LAWYER1]\nDer half mir, diesen Deal einzufãdeln,\n\n[LAW1_K:LAWYER1]\nund zwar ohne Vice Citys Gangster-Establishment. Ok?\n\n[LAW1_L:LAWYER1]\nPass auf, der gibt eine Party in der Bucht, auf seiner Luxusjacht\n\n[LAW1_M:LAWYER1]\nda kommt alles, was in Vice City Rang und Namen hat.\n\n[LAW1_N:LAWYER1]\nIch hab natürlich eine Einladung, versteht sich,\n\n[LAW1_O:LAWYER1]\naber mich kriegen keine zehn Pferde hier raus. Auf keinen Fall!\n\n[LAW1_P:LAWYER1]\nHalt die Klappe! Ich geh selbst hin...\n\n[LAW1_Q:LAWYER1]\nMoment! Hey, ich steh ja auch auf den 78er Look , aber das wird dort kein nostalgisches Saufgelage.\n\n[LAW1_R:LAWYER1]\nIch meine, nichts gegen dich, aber mit den Klamotten wirst du dort ziemlich blöd angeschaut.\n\n[LAW1_S:LAWYER1]\nWieso? Was ist mit meinen Sachen?\n\n[LAW1_T:LAWYER1]\nPass auf. Fahr zu Rafael. Sag ihm, ich schicke dich, und er soll dich ordentlich einkleiden.\n\n[LAW1_U:LAWYER1]\nOk, Los jetzt. Mach hinne...\n\n[LAWP_1:LAWYER1]\nGuten Abend.\n\n[LAWP_2:LAWYER1]\nIch höre, Sie sind anstelle von Mr. Rosenberg hier.\n\n[LAWP_3:LAWYER1]\nIch hoffe, gewisse Vorfãlle haben seiner Gesundheit nicht geschadet,\n\n[LAWP_4:LAWYER1]\noder seiner Psyche, Mr...ãh?\n\n[LAWP_5:LAWYER1]\nVercetti. Er leidet ein wenig an...Platzangst.\n\n[LAWP_6:LAWYER1]\nAusgezeichnet, ausgezeichnet. Und Sie?\n\n[LAWP_7:LAWYER1]\nIch will nur meine Ware.\n\n[LAWP_8:LAWYER1]\nAh. Eine missliche Lage für alle Beteiligten.\n\n[LAWP_9:LAWYER1]\nNatürlich stelle ich selbst Nachforschungen an, aber\n\n[LAWP_10:LAWYER1]\nbei solch heiklen Sachen dauert das ein wenig.\n\n[LAWP_11:LAWYER1]\nWir sprechen uns vielleicht spãter. Hm?\n\n[LAWP_12:LAWYER1]\nInzwischen möchte ich Ihnen meine Tochter vorstellen,\n\n[LAWP_13:LAWYER1]\nMercedes!\n\n[LAWP_14:LAWYER1]\nKönntest du dich um unseren Gast kümmern, wãhrend ich mich um andere Dinge\n\n[LAWP_15:LAWYER1]\nNatürlich, Daddy.\n\n[LAWP_16:LAWYER1]\nEntschuldigen Sie mich, bitte.\n\n[LAWP_17:LAWYER1]\nMercedes!?\n\n[LAWP_18:LAWYER1]\nLeb du mal mit so 'nem Namen.\n\n[LAWP_19:LAWYER1]\nNa gut, ich zeig dir mal einige unserer bekannteren Gãste...\n\n[LAWP_20:LAWYER1]\nDas ist unser Abgeordneter Alex Shrub mit dem aufgehenden Sternchen Candy Suxx..\n\n[LAWP_21:LAWYER1]\nUnd kennen Sie schon meine reizende Frau Laura? Nein?\n\n[LAWP_22:LAWYER1]\nNun, leider ist sie in Alabama. Das hier ist Candy.\n\n[LAWP_23:LAWYER1]\nUnd hier haben wir den Star-Verteidiger der Vice City Mambas, BJ.\n\n[LAWP_24:LAWYER1]\nImmer charmant.\n\n[LAWP_25:LAWYER1]\nIch hab ihn voll geblockt. Der sitzt heute im Rollstuhl!\n\n[LAWP_26:LAWYER1]\nHaha, das ist gut!\n\n[LAWP_27:LAWYER1]\nTja, ich bin an einem super Grundstück dran.\n\n[LAWP_28:LAWYER1]\nUnd der Schleimbold dort ist Jezz Torrent,\n\n[LAWP_29:LAWYER1]\nDer Sãnger von 'Love Fist'.\n\n[LAWP_30:LAWYER1]\nWisst ihr, wie sie in Thailand Pingpong spielen?\n\n[LAWP_31:LAWYER1]\nIch verrat's euch,\n\n[LAWP_32:LAWYER1]\nman spielt ohne Schlãger, wenn ihr wisst, was ich meine!\n\n[LAWP_33:LAWYER1]\nImpotent.\n\n[LAWP_34:LAWYER1]\nUnd das schwatzhafte Trio.\n\n[LAWP_35:LAWYER1]\nDiese schlafende Schweißfabrik ist Papas Obersklave, Gonzalez.\n\n[LAWP_36:LAWYER1]\nund die anderen beiden sind Pastor Richards\n\n[LAWP_37:LAWYER1]\nund der pseudo-intellektuelle Regisseur Steve Scott.\n\n[LAWP_38:LAWYER1]\n....leidenschaftlich mit den nymphomanischen Aliens\n\n[LAWP_39:LAWYER1]\nDa kommt der riesige Hai und\n\n[LAWP_40:LAWYER1]\nbeißt ihnen ihr Ding ab!\n\n[LAWP_41:LAWYER1]\nHa! So was hat doch die Welt noch nicht gesehen, oder?\n\n[LAWP_42:LAWYER1]\nColonel!\n\n[LAWP_43:LAWYER1]\nIhre Party ist wie immer fantastisch, hahahaha!\n\n[LAWP_44:LAWYER1]\nIch entschuldige mich für die Verspãtung.\n\n[LAWP_45:LAWYER1]\nAh, nicht doch, Amigo. Wie geht es ihnen?\n\n[LAWP_46:LAWYER1]\nUnsere Geschãfte laufen schwierig - die Barbaren stehen vor den Toren.\n\n[LAWP_47:LAWYER1]\nEine Zeit, Freunde zu belohnen und Feinde auszuschalten, Amigo.\n\n[LAWP_48:LAWYER1]\nWer ist das Großmaul?\n\n[LAWP_49:LAWYER1]\nRicardo Diaz. Er ist Mr. Koks.\n\n[LAWP_50:LAWYER1]\nMercedes!\n\n[LAWP_51:LAWYER1]\nOh, ich will gerade meinen Freund in die Stadt bringen.\n\n[LAWP_52:LAWYER1]\nEin andermal, Ricardo!\n\n[LAWP_53:LAWYER1]\nLass uns verschwinden.\n\n[LAWP_54:LAWYER1]\nFahr mich zum Pole Position Club.\n\n[LAW1_2:LAWYER1]\n~g~Begib dich zur Jacht des Colonels.\n\n[LAW1_4:LAWYER1]\n~r~Du hast die Tochter des Colonels erledigt!\n\n[LAW1_5:LAWYER1]\nWirst du für meinen Vater arbeiten?\n\n[LAW1_6:LAWYER1]\nVielleicht.\n\n[LAW1_7:LAWYER1]\nDarf ich meine Hand in deinen Schoß legen?\n\n[LAW1_8:LAWYER1]\nVielleicht...\n\n[LAW1_9:LAWYER1]\nEs ist schwer, einen so reichen, mãchtigen Vater zu haben. Los.\n\n[LAW1_10:LAWYER1]\nWir sehen uns, mein Hübscher!\n\n[LAW1_11:LAWYER1]\nGanz bestimmt.\n\n[LAW1_12:LAWYER1]\nHmm, netter Ofen.\n\n[LAW1_13:LAWYER1]\nNein! Mein Motorrad!\n\n[LAW1_3:LAWYER1]\n~g~Bring die Tochter des Colonels zum Pole Position Club.\n\n[HELP20:LAWYER1]\nFolge dem ~h~T-shirt-Symbol~w~ auf dem Radar, um Rafael's zu finden.\n\n[LAW1_14:LAWYER1]\nWow, das ist ja wirklich ein tolles Motorrad.\n\n[LAW1_15:LAWYER1]\nJa, Baby, hab ich mir gerade bei Howlin' Pete's besorgt.\n\n{=================================== MISSION TABLE LAWYER2 ===================================}\n\n[LAW2_A:LAWYER2]\nAh! Tja, ich hoffe, du amüsierst dich gut, wãhrend ich hier vor Angst halb umkomme. Was hast du rausgefunden?\n\n[LAW2_B:LAWYER2]\nDass es in dieser Stadt mehr Gangster gibt als im Knast. Wir brauchen einen Tipp von der Straße...\n\n[LAW2_C:LAWYER2]\nOk, lass mich nachdenken, lass mich nachdenken -\n\n[LAW2_D:LAWYER2]\n- AH! Ich hab's!\n\n[LAW2_E:LAWYER2]\nOk, es gibt da so 'n Englãnder, so 'n Idiot aus der Musikbranche.\n\n[LAW2_F:LAWYER2]\nEr nennt sich Kent Paul.\n\n[LAW2_G:LAWYER2]\nUnd der ist in all den Kreisen von Vice City richtig dick drin.\n\n[LAW2_H:LAWYER2]\nWenn einer weiß, wo 20 Kilo Koks abgeblieben sind,\n\n[LAW2_I:LAWYER2]\ndann dieser Typ. Er ist immer im Malibu.\n\n[LAW2_J:LAWYER2]\nIch seh ihn mir mal an.\n\n[LAW2B_A:LAWYER2]\nWo kommst du denn her?\n\n[LAW2B_B:LAWYER2]\nNach einer wie dir suche ich schon seit Ewigkeiten.\n\n[LAW2B_C:LAWYER2]\nKent Paul. Ja, ich bin hier die Nummer Eins.\n\n[LAW2B_D:LAWYER2]\nIch suche einen Englãnder...\n\n[LAW2B_E:LAWYER2]\nIch ziehe hier die Strippen, verstehst du?\n\n[LAW2B_F:LAWYER2]\nIch lade dich ein. Ich kann dir alles besorgen, Süße.\n\n[LAW2B_G:LAWYER2]\nMach dir keine Gedanken.\n\n[LAW2B_H:LAWYER2]\nVerzieh dich, Schãtzchen.\n\n[LAW2B_I:LAWYER2]\nOi oi oi oi!\n\n[LAW2B_J:LAWYER2]\nBist du Kent Paul? Ich bin ein Freund von Rosenberg...\n\n[LAW2B_K:LAWYER2]\nRosenberg...Rosenberg... Ach, dieser abgedrehte Winkeladvokat!\n\n[LAW2B_L:LAWYER2]\nDer bringt noch den Unschuldigsten auf den elektrischen Stuhl!\n\n[LAW2B_M:LAWYER2]\nMach uns noch 'nen Drink, mein Freund.\n\n[LAW2B_N:LAWYER2]\nBist ein echter Komiker.\n\n[LAW2B_O:LAWYER2]\nHör zu, ich vermisse 20 Kilo und einen Haufen Geld...\n\n[LAW2B_P:LAWYER2]\nDrogen? Das ist doch Schwachsinn.\n\n[LAW2B_Q:LAWYER2]\nWas weißt du darüber?\n\n[LAW2B_R:LAWYER2]\nOi, oi! Gerade wollte ich's sagen...\n\n[LAW2B_S:LAWYER2]\nEs gibt da einen Koch, der verdealt Koks in der Küche eines Hotels am Ocean Drive.\n\n[LAW2B_T:LAWYER2]\nMacht einen ziemlich zufriedenen Eindruck in letzter Zeit. Solltest du mal auschecken.\n\n[LAW2B_U:LAWYER2]\nMach ich. Und wir sehen uns.\n\n[LAW2B_V:LAWYER2]\nJa, ja. Nur zu. Hau bloß ab, du Stinktier. Dir polier ich noch die Visage!\n\n[LAW2B_W:LAWYER2]\nGib mir 'nen Drink. Und wo ist die Puppe?\n\n[LAW2C_A:LAWYER2]\nOh, sehr gut, Rambo, schlag ihn ruhig zu Brei. Dann redet er ganz bestimmt.\n\n[LAW2C_B:LAWYER2]\nWillst du auch ein paar?\n\n[LAW2C_C:LAWYER2]\nHey, ruhig. Ich will das gleiche wie du, Bruder.\n\n[LAW2C_D:LAWYER2]\nAch ja? Und das wãre?\n\n[LAW2C_E:LAWYER2]\nDeine Kohle und den Stoff meines toten Bruders. Aber du hast gerade unsere Spur erledigt.\n\n[LAW2C_F:LAWYER2]\nDumm gelaufen. Verzieh dich.\n\n[LAW2C_G:LAWYER2]\nHey, hey! Kein Grund, hier den dicken Mann zu spielen.\n\n[LAW2C_H:LAWYER2]\nSieh mal: Wir sind zwei Hombres in 'ner fremden Stadt. Wir sollten uns gegenseitig helfen.\n\n[LAW2C_I:LAWYER2]\nIch helf mir selbst, Bruder.\n\n[LAW2C_J:LAWYER2]\nBist du dir sicher? Hier nimm das.\n\n[LAW2C_K:LAWYER2]\nKomm mit!\n\n[LAW2_1:LAWYER2]\nWas glotzt du denn so?\n\n[LAW2_2:LAWYER2]\nRede endlich...\n\n[LAW2_3:LAWYER2]\nZwing mich doch dazu, du Pfeife!\n\n[LAW2_4:LAWYER2]\nMir nach!\n\n[LAW2_5:LAWYER2]\nIch seh zu, was ich rausfinde. Ich behalte dich im Auge, Tommy.\n\n[LAW2_6:LAWYER2]\n~g~Begib dich zum Malibu Club und suche Kent Paul.\n\n[LAW2_7:LAWYER2]\n~g~Suche den Küchenchef auf dem Ocean Drive.\n\n[LAW2_10:LAWYER2]\n~g~Fahre zurück zum Hotel.\n\n[LAW2_11:LAWYER2]\n~g~Nimm sein Handy.\n\n[LAW2_12:LAWYER2]\nDu hast jetzt ein Handy und kannst Telefongesprãche entgegennehmen!\n\n[LAW2_13:LAWYER2]\n~g~Du hast Lance zurückgelassen! Geh ihn holen!\n\n[LAW2_14:LAWYER2]\nVerdammt, nichts wie weg hier!\n\n[GUN_2A:LAWYER2]\nHalte die ~h~~k~~PED_LOCK_TARGET~ ~w~gedrückt, um ~h~automatisch zu zielen~w~. Drücke die ~h~~k~~PED_FIREWEAPON~~w~, um zu ~h~feuern!\n\n[GUN_2C:LAWYER2]\nHalte die ~h~~k~~PED_LOCK_TARGET~ ~w~gedrückt, um ~h~automatisch zu zielen~w~. Drücke die ~h~~k~~PED_FIREWEAPON~~w~, um zu ~h~feuern!\n\n[GUN_2D:LAWYER2]\nHalte die ~h~~k~~PED_LOCK_TARGET~ ~w~gedrückt, um ~h~automatisch zu zielen~w~. Drücke die ~h~~k~~PED_FIREWEAPON~~w~, um zu ~h~feuern!\n\n[HELP17:LAWYER2]\nDrücke die ~h~~k~~PED_FIREWEAPON~~w~, um den Küchenchef anzugreifen.\n\n[HELP18:LAWYER2]\nDrücke die~h~ ~k~~PED_FIREWEAPON~~w~, um den Küchenchef anzugreifen.\n\n[LAW3_11:LAWYER2]\nStell dich in die ~q~rosa Markierung~w~, um zu sehen, was im Angebot ist.\n\n[LAW3_12:LAWYER2]\nDu kannst Waffen auswãhlen, indem du die ~h~linke~w~ oder ~h~rechte~w~ ~h~Richtungstaste drückst.\n\n[LAW3_13:LAWYER2]\nWenn du genug Geld hast, kannst du Waffen durch Drücken der ~h~~k~~PED_SPRINT~~w~ kaufen.\n\n[LAW3_14:LAWYER2]\nUm zu gehen, drücke die ~h~~k~~VEHICLE_ENTER_EXIT~\n\n[LAW3_15:LAWYER2]\nFolge dem ~h~Pistolensymbol~w~ auf dem Radar, so kommst du zu AmmuNation.\n\n[LAW2_15:LAWYER2]\n~g~Begib dich zu AmmuNation.\n\n[LAW2_K:LAWYER2]\nNur die Ruhe.\n\n[LAW2_16:LAWYER2]\nEins musst du wissen: In dieser Stadt darfst du nie unbewaffnet sein.\n\n[LAW2_17:LAWYER2]\nKomm, der nãchste Waffenladen ist ein paar Blocks von hier.\n\n[LAW2_18:LAWYER2]\nTommy, jeder Mann braucht ab und zu mal ein bisschen Entspannung.\n\n[LAW2_19:LAWYER2]\nDas ist die Pole Position Stripper-Bar. Solltest du bei Gelegenheit mal reinschauen.\n\n{=================================== MISSION TABLE LAWYER3 ===================================}\n\n[_A:LAWYER3]\nArrgh! Ach, du lieber Gott! Du! Meine Güte, ich brauch 'ne neue Hose!\n\n[LAW3_B:LAWYER3]\nHey, diese Psychos aus dem Norden haben angerufen. Sie kommen bald hier runter.\n\n[LAW3_C:LAWYER3]\nAlso, wo ist das verdammte Geld?\n\n[LAW3_D:LAWYER3]\nGanz ruhig. Soweit sind wir noch nicht.\n\n[LAW3_E:LAWYER3]\nIch hab wirklich gedacht, du erledigst das.\n\n[LAW3_F:LAWYER3]\nUnd jetzt sagen diese Gauner, wir sollen ihnen einen Gefallen tun.\n\n[LAW3_G:LAWYER3]\nDu meinst, ICH soll ihnen einen Gefallen tun.\n\n[LAW3_H:LAWYER3]\nDu sagst es. Sehe ich aus, als könnte ich Geschworene einschüchtern?\n\n[LAW3_I:LAWYER3]\nIch kann nicht mal ein Kind einschüchtern. Ich hab's versucht.\n\n[LAW3_J:LAWYER3]\nHör zu, wenn du kneifst, kriegt Forellis Cousin Georgio 5 Jahre wegen Betrugs.\n\n[LAW3_K:LAWYER3]\nDu musst diese Typen ausschalten.\n\n[LAW3_L:LAWYER3]\nVerstehe. Den Geschworenen helfen 'umzudenken'. Kein Problem.\n\n[LAW3_M:LAWYER3]\nNein, nein, nein! Das hab ich schon versucht. Das ist nicht gelaufen,\n\n[LAW3_N:LAWYER3]\nZWING sie dazu, umzudenken.\n\n[LAW3_1:LAWYER3]\nGeorgio lãsst grüßen.\n\n[LAW3_2:LAWYER3]\nDenk dran, 'Schuldig' ist ein hãssliches Wort.\n\n[LAW3_3:LAWYER3]\n'Unschuldig', bis ich was anderes sage.\n\n[LAW3_4:LAWYER3]\nEr ist nicht schuldig.\n\n[LAW3_5:LAWYER3]\nDu kennst Georgio? Merk dir: Er ist nicht schuldig.\n\n[LAW3_6:LAWYER3]\nNicht schuldig. Verstanden...gut.\n\n[LAW3_8:LAWYER3]\n~r~Du hast einen Geschworenen erledigt!\n\n[LAW3_9:LAWYER3]\n~g~Schrotte das Auto des Geschworenen, damit er aussteigt!\n\n[HELP40:LAWYER3]\nDu kannst Autos mit dem Hammer oder einer ãhnlichen Waffe zertrümmern.\n\n[HELP41:LAWYER3]\nOder du kannst sie mit einem Fahrzeug rammen.\n\n[LAW3_10:LAWYER3]\n~g~Eine Nahkampfwaffe kannst du im ~h~Eisenwarenladen~g~ kaufen.\n\n[LAW3_20:LAWYER3]\n~g~Schrotte das Auto des Geschworenen!\n\n[LAW3_21:LAWYER3]\nDas kann doch wohl nicht wahr sein!\n\n[LAW3_22:LAWYER3]\nUnglaublich!\n\n[LAW3_23:LAWYER3]\nOk! Ok! Ich hab kapiert!\n\n[LAW3_24:LAWYER3]\n~g~Dieser Hammer wãre nützlich.\n\n[LAW3_7:LAWYER3]\n~g~Schüchtere die 2 Geschworenen ein, aber erledige sie NICHT!\n\n[HELP23:LAWYER3]\nFolge dem ~h~Hammer-Symbol~w~ auf dem Radar, wenn du beim Eisenwarenladen Nahkampfwaffen kaufen willst.\n\n[LAW3_16:LAWYER3]\nDãmlicher Florida-Idiot!\n\n[LAW3_17:LAWYER3]\nAus dem Weg!\n\n{=================================== MISSION TABLE LAWYER4 ===================================}\n\n[LAW4_A:LAWYER4]\nAvery, es versteht sich von selbst... Tommy! Tommy! Fortschritte gemacht? Nein, erzãhl's mir spãter.\n\n[LAW4_B:LAWYER4]\nTommy, das ist Avery Carrington. Kennt ihr euch nicht von der Party?\n\n[LAW4_C:LAWYER4]\nNicht persönlich.\n\n[LAW4_D:LAWYER4]\nTagchen.\n\n[LAW4_E:LAWYER4]\nAvery hat einen Vorschlag für uns.\n\n[LAW4_F:LAWYER4]\nHaben wir nicht was besseres zu tun?\n\n[LAW4_G:LAWYER4]\nIch versuch hier, unseren Hals zu retten. Also würdest du mich bitte ausreden lassen?\n\n[LAW4_H:LAWYER4]\nIch hab Angst. Aber wenn ich schon Ende der Woche sterbe, möchte ich wenigstens nicht arm sterben.\n\n[LAW4_I:LAWYER4]\nJetzt beruhigt euch, ihr beiden.\n\n[LAW4_J:LAWYER4]\nJunge, wenn du mir hilfst, sorge ich dafür, dass jeder, der dir Ãrger macht, unter die Erde kommt.\n\n[LAW4_K:LAWYER4]\nOk, was kann ich für Sie tun?\n\n[LAW4_L:LAWYER4]\nEine Spedition hat ihr Lager auf einem Top-Grundstück - und will nicht verkaufen.\n\n[LAW4_M:LAWYER4]\nDie sitzen da drauf wie die Ratten in ihren Löchern. Also müssen wir dieses Ungeziefer ausrãuchern.\n\n[LAW4_N:LAWYER4]\nFahr hin und stich ein wenig ins Wespennest.\n\n[LAW4_O:LAWYER4]\nDas wird die Security beschãftigen. Dann schleichst du dich rein und machst den Laden platt.\n\n[LAW4_P:LAWYER4]\nUnd du könntest dich bei Rafael's neu einkleiden. Kann 'ne Weile dauern, aber mach das ruhig mal.\n\n[LAW4_Q:LAWYER4]\nDas gibt ein Fest.\n\n[LAW4_R:LAWYER4]\nWenn alles lãuft wie geplant, komm mal zu mir ins Büro...\n\n[LAW4_1:LAWYER4]\nBitte, geht auseinander! Die Geschãftsleitung wird sich aller Probleme annehmen!\n\n[LAW4_2:LAWYER4]\nBitte, geht auseinander! Geht wieder nach Hause!\n\n[LAW4_3:LAWYER4]\nBitte, geht auseinander! Das ist nicht akzeptabel!\n\n[LAW4_4:LAWYER4]\nBitte, geht auseinander! Ihr landet alle auf der Straße!\n\n[LAW4_5:LAWYER4]\nDie Knüppel raus, Jungs! Diesen Kommis zeigten wir's!\n\n[LAW4_13:LAWYER4]\nFange mit mind. 4 Arbeitern Streit an, um einen Aufruhr zu starten.\n\n[LAW4_14:LAWYER4]\n~g~Zerstöre die Transporter auf dem Gelãnde!\n\n[HELP38:LAWYER4]\nWenn du jemanden ausschaltest, der eine Waffe trãgt, lãsst er sie fallen.\n\n[HELP39:LAWYER4]\nDu kannst explosive Fãsser anvisieren und abschießen, aber bleib auf Distanz.\n\n{=================================== MISSION TABLE MIAMI_1 ===================================}\n\n[T4X4_1A:MIAMI_1]\n~g~Du hast ~1~ Sekunden, um ~y~24~g~ Checkpoints abzufahren. ~g~Die ~y~REIHENFOLGE IST BELIEBIG.\n\n[T4X4_1B:MIAMI_1]\n~y~PASSIERE~g~ den ersten Checkpoint, dann lãuft die ~r~STOPPUHR.\n\n[T4X4_1C:MIAMI_1]\n~1~ von 24!\n\n[GETBIK1:MIAMI_1]\nDu hast ~1~ Sekunden, um auf eine PCJ 600 zu steigen!\n\n[GETBIK3:MIAMI_1]\n~r~Du brauchst eine PCJ 600, um diese Mission durchzuführen!\n\n{=================================== MISSION TABLE MM ===================================}\n\n[BLOD_04:MM]\nZUSTAND AUTO:\n\n[BLOD_05:MM]\n~g~ZIELZEIT: ~1~ Minute\n\n[BLOD_06:MM]\n~g~ZIELZEIT: ~1~ Minuten\n\n[BLOD_07:MM]\nNEUE Bestzeit: ~1~ Sekunden\n\n[BLOD_08:MM]\nZerstörte Autos: ~1~\n\n[BLOD_09:MM]\n$~1~\n\n[BLOD_10:MM]\nSIEGER!!\n\n[BLOD_01:MM]\nFahr durch die Checkpoints, um deine Gesamtzeit zu verlãngern.\n\n[BLOD_02:MM]\nWenn die Gesamtzeit abgelaufen ist, hast du versagt.\n\n[BLOD_03:MM]\nUm zu gewinnen, muss deine Gesamtzeit die Zielzeit überschreiten!\n\n{=================================== MISSION TABLE OVALRIG ===================================}\n\n[HOTR_01:OVALRIG]\n~g~Das Rennen geht über 12 Runden. Nur die ersten drei Plãtze qualifizeren für einen Gewinn.\n\n[HOTR_02:OVALRIG]\n~g~Wird dein Auto zerstört, wirst du disqualifiziert.\n\n[HOTR_03:OVALRIG]\n~g~Wird dein Auto beschãdigt, kannst du es an der Box reparieren lassen.\n\n[HOTR_04:OVALRIG]\n~g~Da geht es aus dem Stadion raus.\n\n[HOTR_05:OVALRIG]\nZustand Auto:\n\n[HOTR_06:OVALRIG]\nRunden:\n\n[HOTR_07:OVALRIG]\nNeue Bestzeit: ~1~:0~1~\n\n[HOTR_08:OVALRIG]\nZeit: ~1~:~1~\n\n[HOTR_10:OVALRIG]\nAbsolvierte Zeit:\n\n[HOTR_09:OVALRIG]\nPosition:\n\n[HOTR_12:OVALRIG]\n~r~Dein Fahrzeug ist zerstört worden!\n\n[HOTR_13:OVALRIG]\n~r~Du hast das Rennen nicht gewonnen!\n\n[HOTR_14:OVALRIG]\n~r~Du bist disqualifiziert worden!\n\n[HOTR_15:OVALRIG]\nZeit: ~1~:~1~\n\n[HOTR_16:OVALRIG]\nZeit: ~1~:0~1~\n\n[HOTR_17:OVALRIG]\nBestzeit: ~1~:~1~\n\n[HOTR_18:OVALRIG]\nBestzeit: ~1~:0~1~\n\n[HOTR_19:OVALRIG]\nBestzeit: Nicht verfügbar\n\n[HOTR_20:OVALRIG]\nNeue Bestzeit: ~1~:~1~\n\n[HOTR_21:OVALRIG]\nNeue Bestzeit: ~1~:0~1~\n\n[HOTR_22:OVALRIG]\nBeste Platzierung: Nicht verfügbar\n\n[HOTR_23:OVALRIG]\nBeste Platzierung: 1.\n\n[HOTR_24:OVALRIG]\nBeste Platzierung: 2.\n\n[HOTR_25:OVALRIG]\nBeste Platzierung: 3.\n\n[HOTR_26:OVALRIG]\nBeste Platzierung: ~1~.\n\n[HOTR_27:OVALRIG]\nBeste Rundenzeit: ~1~.~1~ Sekunden\n\n[HOTR_28:OVALRIG]\nBeste Rundenzeit: ~1~.0~1~ Sekunden\n\n[HOTR_29:OVALRIG]\n$~1~\n\n[HOTR_30:OVALRIG]\n1. PLATZ\n\n[HOTR_31:OVALRIG]\n2. PLATZ\n\n[HOTR_32:OVALRIG]\n3. PLATZ\n\n[HOTR_33:OVALRIG]\nBeste Rundenzeit: Nicht verfügbar\n\n[HOTR_11:OVALRIG]\nNeue beste Rundenzeit: ~1~.~1~ Sekunden\n\n[HOTR_34:OVALRIG]\nNeue beste Rundenzeit: ~1~.0~1~ Sekunden\n\n{=================================== MISSION TABLE PHIL1 ===================================}\n\n[PHI1_HP:PHIL1]\nWenn du Granaten mit Fernzünder benutzt, wirf die Granate, dann löse die Explosion zu einem beliebigen Zeitpunkt aus.\n\n[PHIL1_A:PHIL1]\nPhil?\n\n[PHIL1_B:PHIL1]\nSCHNELL WEG!\n\n[PHIL1_C:PHIL1]\nSchnell weg!\n\n[PHIL1_E:PHIL1]\nScheiße, Phil, das Zeug trinkst du?\n\n[PHIL1_F:PHIL1]\nHey, du musst es nicht trinken.\n\n[PHIL1_G:PHIL1]\nDas haut schon rein, wenn du nur dran riechst.\n\n[PHIL1_H:PHIL1]\nHör mal, Phil, du sagtest, du könntest mir Artillerie besorgen...\n\n[PHIL1_I:PHIL1]\nKlar.\n\n[PHIL1_J:PHIL1]\nIn letzter Zeit macht mir ein mexikanischer Waffenschieber Konkurrenz.\n\n[PHIL1_K:PHIL1]\nDer müsste jetzt gerade auf seiner wöchentlichen Runde sein.\n\n[PHIL1_L:PHIL1]\nRamm mit deiner Karre die Ware von seinem Wagen runter, bevor er wieder abtaucht.\n\n[PHIL1_M:PHIL1]\nTust mir einen großen Gefallen damit.\n\n[PHIL1_N:PHIL1]\nUnd dann mach ihn fertig.\n\n[PHI1_01:PHIL1]\n~g~Ramme die Waffen von der Ladeflãche des Waffenschiebers.\n\n[PHI1_02:PHIL1]\n~g~Der Waffenhãndler hat die Ladung verloren. Schlag die Kiste kaputt und nimm die Waffe.\n\n[PHI1_03:PHIL1]\n~g~Sie haben anscheinend Verstãrkung gerufen.\n\n[PHI1_04:PHIL1]\n~g~Jetzt erledige die restlichen Waffenschieber.\n\n[PHI1_06:PHIL1]\nPass doch auf, wo du hinfãhrst!\n\n[PHI1_07:PHIL1]\nHey!\n\n[PHIL1_O:PHIL1]\nHuuuuhuuu!\n\n[PHIL1_D:PHIL1]\nKomm nie mit 'ner offenen Flamme in die Nãhe von Phil Cassidys TNT-Whiskey!\n\n{=================================== MISSION TABLE PHIL2 ===================================}\n\n[PHIL2_A:PHIL2]\nHey, Phil, wie geht's?\n\n[PHIL2_B:PHIL2]\nHey, Tommy. Alles klar? Lange nicht gesehen...\n\n[PHIL2_C:PHIL2]\nDu solltest wirklich die Finger von dem TNT-Whiskey lassen.\n\n[PHIL2_D:PHIL2]\nDas Zeug riecht ja wie Terpentin. Mir brennen schon die Augen.\n\n[PHIL2_E:PHIL2]\nLass stecken, Tommy.\n\n[PHIL2_F:PHIL2]\nKomm hier rüber, ich will dir nãmlich was zeigen.\n\n[PHIL2_G:PHIL2]\nWahnsinn! Das rieche ich ja schon von hier. Mir ist schon ganz schwindlig.\n\n[PHIL2_H:PHIL2]\nKümmer dich nicht um den Geruch. Tommy, sieh dir das an.\n\n[PHIL2_I:PHIL2]\nBillige Schrottbatterien. Da auf der Bank sind noch welche.\n\n[PHIL2_J:PHIL2]\nTata!\n\n[PHIL2_K:PHIL2]\nOh, verflucht!\n\n[PHI2_01:PHIL2]\n~g~Schnell, bring Phil ins Krankenhaus.\n\n[PHI2_03:PHIL2]\n~r~Phil Cassidy ist tot!!! Wer soll Liberty nun mit Waffen versorgen?\n\n[PHI2_05:PHIL2]\nNicht ins Krankenhaus, Mann! Zu viele Cops und Vietcong!\n\n[PHI2_06:PHIL2]\nIch kenn 'nen Ex-Army-Arzt, der schuldet mir einen Gefallen und 'nen Rasenmãher.\n\n[PHI2_07:PHIL2]\nEr hat 'ne Praxis unten in Little Havana. Uh, guck mal, ein Riesenfisch.\n\n[PHI2_08:PHIL2]\nAchtung! Da in den Bãumen - Vietcong!\n\n[PHI2_09:PHIL2]\nSpinn ich, oder ist die Straße aus Gummi?\n\n[PHI2_10:PHIL2]\nBroken Spoon an Mother Hen, bitte kommen!\n\n[PHI2_11:PHIL2]\nSpooney Wooney Woo Woo Woooo!\n\n[PHI2_12:PHIL2]\nEr kommt mich holen, Jungchen!\n\n[PHI2_13:PHIL2]\nSchwarze Schwingen breiten sich über mir aus...\n\n[PHI2_14:PHIL2]\nEs ist wunderschön, Mann. Wunderschön... mir ist nur so kalt...\n\n[PHI2_15:PHIL2]\nRoger! Wir haben einen betrunkenen Fahrer.\n\n[PHI2_04:PHIL2]\nPhils Gesundheitszustand:\n\n[PHI_AS1:PHIL2]\nPHIL-MISSIONEN ERFÜLLT\n\n[PHI_AS2:PHIL2]\n~g~Bei Phil gibt es neue Waffen zu kaufen.\n\n{=================================== MISSION TABLE PIZZA ===================================}\n\n[PIZ1_01:PIZZA]\n~g~Liefere diese Pizzas aus. Du musst den Kunden die Pizzas zuwerfen, wãhrend du an ihnen vorbeifãhrst.\n\n[PIZ1_02:PIZZA]\n~g~Du hast alle Pizzas zugestellt. Fahr zurück und hole noch mehr.\n\n[PIZ1_05:PIZZA]\n~g~Du hast 5 Minuten, um die Pizzas zu liefern, sonst rufen die Kunden einen anderen Pizza-Service an.\n\n[PIZ1_07:PIZZA]\n~r~Du hast den Kunden erledigt! Du bist gefeuert.\n\n[PIZ1_08:PIZZA]\n~r~Die Zeit ist um. Du bist gefeuert.\n\n[PIZ1_09:PIZZA]\n~r~Du hast dein Motorrad geschrottet! Du bist gefeuert.\n\n[PIZ1_11:PIZZA]\nHey! Steig wieder aufs Motorrad!\n\n[PIZ1_12:PIZZA]\nVerbleibende Pizzas:\n\n[PIZ1_06:PIZZA]\nDrücke die ~h~ R3-Taste~w~, wenn du auf einem Bike sitzt und die Mission abbrechen willst.\n\n[PIZ1_13:PIZZA]\nLiefere sie schön heiß ab.\n\n[PIZ1_14:PIZZA]\nKumpel, Pizzas für dich.\n\n[PIZ1_15:PIZZA]\nHey, na los, Mister, liefere sie schnell aus.\n\n[PIZ1_16:PIZZA]\nWorauf wartest du, Mister? Du sollst Pizzas liefern.\n\n[PIZ1_17:PIZZA]\nIch weiß, du wolltest kein Pizza-Lieferant sein. Na ja, mir egal.\n\n[PIZ1_18:PIZZA]\nLiefere die aus.\n\n[PIZ1_19:PIZZA]\nDie müssen ausgeliefert werden.\n\n[PIZ1_20:PIZZA]\nNa los, Mister, liefere die Dinger aus, oder du fliegst.\n\n[PIZ1_21:PIZZA]\nDie Leute warten, Kumpel.\n\n[PIZ1_22:PIZZA]\nWartest du auf bessere Zeiten? Die müssen ausgeliefert werden!\n\n[PIZ1_23:PIZZA]\nLiefer den verdammten Fraß aus, Mister.\n\n[PIZ1_24:PIZZA]\nDie müssen ausgeliefert werden, Kumpel.\n\n[PIZ1_25:PIZZA]\nMann, kannst du die übernehmen?\n\n[PIZ1_26:PIZZA]\nMister, liefere die Dinger schnell ab, hopp, Amigo.\n\n[PIZ1_27:PIZZA]\nKomm schon, wir sind unter Druck, liefere die Dinger aus.\n\n[PIZ1_28:PIZZA]\nDu schon wieder? Liefere die hier schnell aus, Kumpel.\n\n[PIZ1_29:PIZZA]\nKeine Trödelei diesmal, Kumpel.\n\n[PIZ1_30:PIZZA]\nNa los, du fauler Hund, liefere den Fraß rechtzeitig aus.\n\n[PIZ1_31:PIZZA]\nDu wirst nie befördert, wenn du diesmal nicht schneller machst.\n\n[PIZ1_32:PIZZA]\n~r~Ist dir die Pizza zu heiß?\n\n[PIZ1_33:PIZZA]\n~g~Kehre zum Restaurant zurück, um weitere Auftrãge zu bekommen.\n\n[PIZ1_34:PIZZA]\n~g~Pizza geliefert, hier ist dein Geld.\n\n[PIZ_WON:PIZZA]\nPizza-Mission abgeschlossen. Deine max. Gesundheit erhöht sich auf 150\n\n{=================================== MISSION TABLE PORN1 ===================================}\n\n[POR1_15:PORN1]\nHey, Tommy, kommst du auf eine Aufwãrmrunde mit rein!?\n\n[POR1_14:PORN1]\nDu bist engagiert!\n\n[POR1_A:PORN1]\nAction!\n\n[POR1_B:PORN1]\nWow! Der ist aber groß!\n\n[POR1_C:PORN1]\n30cm, das ist Vorschrift, Baby.\n\n[POR1_D:PORN1]\nSCHNITT! Wer ist dieser Idiot? Du da! Was machst du in meinem Studio? Was willst du?\n\n[POR1_E:PORN1]\nWas soll das alles hier?\n\n[POR1_F:PORN1]\nAliens? Angelruten?\n\n[POR1_G:PORN1]\nWer hat jemals einen so großen Hai gesehen?\n\n[POR1_H:PORN1]\nDas muss alles raus hier.\n\n[POR1_I:PORN1]\nWieso bist du in diese Branche gegangen, du Idiot?\n\n[POR1_J:PORN1]\nHah?\n\n[POR1_K:PORN1]\nWegen der Pussys, deswegen. Was ist das??\n\n[POR1_L:PORN1]\nDas ist meine Kunst- SICHERHEITSDIENST!\n\n[POR1_M:PORN1]\nHör zu, du aufgeblasener Penner, du gehörst jetzt mir. Mir gehört das alles hier.\n\n[POR1_N:PORN1]\nWir krempeln den Laden hier um.\n\n[POR1_O:PORN1]\nIch mache dich reich.\n\n[POR1_P:PORN1]\nÃh, du...du bist Tommy Vercetti? Aber ich dachte, du wãrst...\n\n[POR1_Q:PORN1]\nGanz recht.\n\n[POR1_R:PORN1]\nWir ãndern hier ein paar Dinge und dann machen wir richtig Kohle.\n\n[POR1_S:PORN1]\nHast du dir schon mal überlegt...\n\n[POR1_T:PORN1]\nAber zuerst brauchen wir mal ein paar hübsche Mãdels hier.\n\n[POR1_U:PORN1]\nJa, Girls sind ok, aber du...wow!\n\n[POR1_02:PORN1]\n~g~Schalte Candys Agent aus, dann komm wieder und hole Candy.\n\n[POR1_04:PORN1]\nHey, Candy. Ich suche Filmtalente. Interessiert?\n\n[POR1_05:PORN1]\nKlar! Aber da musst du mit meinem Agenten reden.\n\n[POR1_06:PORN1]\nWas zum Teufel soll das?\n\n[POR1_07:PORN1]\nDu hãttest heute zu Hause bleiben sollen!\n\n[POR1_7B:PORN1]\nWas sagt man zu so 'nem Arschloch?\n\n[POR1_08:PORN1]\nHey, Mercedes!\n\n[POR1_09:PORN1]\nHi, Tommy. Na, ein bisschen feiern?\n\n[POR1_10:PORN1]\nJetzt nicht, Süße. Bist du an Filmaufnahmen interessiert?\n\n[POR1_11:PORN1]\nKlar. Wenn's schön billig und dreckig ist.\n\n[POR1_13:PORN1]\n~g~Bring die Girls ins Studio zu Steve.\n\n[POR1_17:PORN1]\nWow, cooler Hai!\n\n[POR1_18:PORN1]\n~r~Mercedes ist erledigt!\n\n[POR1_20:PORN1]\nTommy, wo willst du hin? Komm zurück!\n\n[POR1_21:PORN1]\nWo willst du hin?\n\n[POR1_22:PORN1]\nTommy, wann sehen wir uns mal ganz allein, nur du und ich?\n\n[POR1_01:PORN1]\n~g~Candy Suxxx wãre perfekt für die Hauptrolle!\n\n[POR1_12:PORN1]\n~g~Nimm Candy mit zu deinem Treffen mit Mercedes.\n\n[POR1_16:PORN1]\nVielleicht spãter, Schãtzchen...\n\n[POR1_24:PORN1]\n~g~Geh zurück und hole Candy.\n\n[POR1_25:PORN1]\n~g~Du hast Candy vergessen. Geh sie holen.\n\n[POR1_23:PORN1]\n~g~Candy wird sich um das Geschãft in ~h~Downtown~g~ kümmern.\n\n[POR1_26:PORN1]\n~g~Da ist Candy. Sie scheint wieder mit dem Kongressabgeordneten Shrub zusammen gewesen zu sein.\n\n[POR1_27:PORN1]\nLos, gehen wir.\n\n[POR1_28:PORN1]\nTommy, sei vorsichtig! Meine Implantate sind noch nicht versichert!\n\n[POR1_29:PORN1]\nDas nennst du fahren?\n\n[POR1_30:PORN1]\nDanach kann ich keinen Porno mehr machen!\n\n[POR1_31:PORN1]\nWas ist los? Willst du mich umbringen? Ich dachte, ich wãre der Star!\n\n{=================================== MISSION TABLE PORN2 ===================================}\n\n[POR2_A:PORN2]\nWas macht die Filmerei, Steve?\n\n[POR2_B:PORN2]\nTja, Candy ist ein Naturtalent, und die Neue ist unersãttlich!\n\n[POR2_C:PORN2]\nDie hatte schon vor der ersten Probe das halbe Team durch.\n\n[POR2_D:PORN2]\nJedenfalls, morgen haben wir einen Außendreh. Wir schießen ein paar Boot-Szenen.\n\n[POR2_E:PORN2]\nBoot-Szenen? Was für Boot-Szenen?\n\n[POR2_F:PORN2]\nDie Fischer zappeln im Netz der Leidenschaft, als ein riesiger Hai daherkommt -\n\n[POR2_G:PORN2]\nWas habe ich über den Riesenhai gesagt?\n\n[POR2_H:PORN2]\nIch sagte, 'KEIN RIESENHAI', ok?\n\n[POR2_I:PORN2]\nHalt die Kameras auf die Mãdels gerichtet!\n\n[POR2_J:PORN2]\nOk, ok. Hey, Tommy, probieren kann ich's ja mal, oder?\n\n[POR2_K:PORN2]\nHabt ihr die Flyer drucken lassen?\n\n[POR2_L:PORN2]\nJa, aber man wird uns die Dinger nicht verteilen lassen. Ich meine,\n\n[POR2_M:PORN2]\ndie sind einfach zu, ãh, zu deutlich.\n\n[POR2_N:PORN2]\nMach dir darüber keine Gedanken.\n\n[POR2_O:PORN2]\nIch hab da so meine Ideen, wie wir die verteilen.\n\n[POR2_P:PORN2]\nOk. Hey, Candy, ãh, in meinen Wohnwagen.\n\n[POR2_01:PORN2]\n~g~Hinter den Studios steht ein altes Wasserflugzeug, das mal als Requisite für einen Indy-Film diente.\n\n[POR2_02:PORN2]\n~g~Suche dir einen Checkpoint aus, um mit dem Abwurf der Flyer zu beginnen.\n\n[POR2_03:PORN2]\n~g~Wirf die Flyer überall bis zum End-Checkpoint ab.\n\n[POR2_04:PORN2]\n~r~TREIBSTOFFMANGEL!!!\n\n[POR2_05:PORN2]\nBenutze es, um die Flyer in der Stadt zu verteilen.\n\n[DILDO:PORN2]\nSkimmer-Tankinhalt:\n\n[POR2_Q:PORN2]\nOh, Mann.\n\n[PORN2_9:PORN2]\n~g~Du hast ~1~ Sekunden, um zu einer Skimmer zurückzukehren, bevor die Mission endet.\n\n{=================================== MISSION TABLE PORN3 ===================================}\n\n[POR3_A:PORN3]\nOk, was ist jetzt wieder?\n\n[POR3_B:PORN3]\nSchsch!\n\n[POR3_C:PORN3]\nNun, nach seiner Begegnung mit den Nympho-Aliens\n\n[POR3_D:PORN3]\nkann unser Held an nichts anderes denken, als an einen riesigen Phallusberg-\n\n[POR3_E:PORN3]\nund da wollen wir die Szene mit dem Bottich voll Kartoffelpüree drehen, aber dann...\n\n[POR3_F:PORN3]\nDas interessiert mich nicht die Bohne.\n\n[POR3_G:PORN3]\nD-Dreh einfach weiter. Weiter, weiter.\n\n[POR3_H:PORN3]\nHey, Tommy...\n\n[POR3_I:PORN3]\nDu hast am Telefon was von rechtlichen Problemen gesagt?\n\n[POR3_J:PORN3]\nAch ja! Der Kongressabgeordnete Alex Shrub ist auf Wahlkampftour und buhlt um Stimmen bei den Puritanern.\n\n[POR3_K:PORN3]\nEs heißt, er unterstützt ein Verbot der, sagen wir mal, eher\n\n[POR3_L:PORN3]\nfleischlichen Bereiche der großartigen Unterhaltungsindustrie unseres Landes.\n\n[POR3_M:PORN3]\nGroßartig.\n\n[POR3_N:PORN3]\nCandy! Du kennst doch Shrub.\n\n[POR3_O:PORN3]\nMacht ihr auch ausgefallene Sachen?\n\n[POR3_P:PORN3]\nOh ja, oh ja, oh ja! Ja, ja, ja, JA, Oooooooh!\n\n[POR3_Q:PORN3]\nBitte sag, dass du das hast.\n\n[POR3_R:PORN3]\nGehörte das zum, ãh... oder war das die Antwort für...\n\n[POR3_S:PORN3]\nHey, ich kann das nie unterscheiden. Jedenfalls...\n\n[POR3_T:PORN3]\nDas beste wird sein, du folgst ihr nach dem Dreh.\n\n[POR3_U:PORN3]\nMal sehen, ob sie dich zu ihrem neuen Liebesnest führt.\n\n[POR3_V:PORN3]\nHast du eine Kamera?\n\n[POR3_X:PORN3]\nJa. Gebt ihm eine Kamera.\n\n[POR3_02:PORN3]\n~r~Du hast den Abgeordneten erledigt! Jetzt kannst du ihn nicht mehr erpressen.\n\n[POR3_03:PORN3]\n~r~Du hast die Bodyguards des Abgeordneten aufgescheucht. Sie werden ihn sofort wegbringen.\n\n[POR3_04:PORN3]\nCandy, könntest du mich Martha nennen?\n\n[POR3_05:PORN3]\nOh, Alex - ich meine Martha - ich tu alles, was du willst.\n\n[POR3_06:PORN3]\nMartha, jemand sieht uns zu. Wie erregend.\n\n[POR3_07:PORN3]\nSie da! Geben Sie mir die Kamera.\n\n[POR3_01:PORN3]\n~g~Folge Candys ~h~Stretch-Limo~g~.\n\n[POR3_15:PORN3]\n~r~Du hast Candys Stretch-Limo geschrottet!\n\n[POR3_17:PORN3]\n~g~Begib dich mit dem Film zurück ins Pornostudio.\n\n[POR3_19:PORN3]\n~r~Der Film ist alle!\n\n[POR3_21:PORN3]\n~g~Du hast Candys Stretch-Limo verloren!\n\n[POR3_22:PORN3]\n~g~Das WK Chariot Hotel gegenüber seines Balkons dürfte eine ideale Position zum Fotografieren bieten.\n\n[POR3_23:PORN3]\n~g~Es gibt eine Seitentür, durch die du in das Hotel kommst.\n\n[POR3_08:PORN3]\nHalte die~h~ ~k~~PED_LOCK_TARGET~ ~w~gedrückt, um mit der Kamera zu ~h~zielen~w~.\n\n[POR3_09:PORN3]\nHalte die~h~ ~k~~PED_LOCK_TARGET~ ~w~gedrückt, um mit der Kamera zu ~h~zielen~w~.\n\n[POR3_10:PORN3]\nDrücke die~h~ ~k~~PED_SNIPER_ZOOM_IN~~w~, um ~h~heranzuzoomen ~w~und die~h~ ~k~~PED_SNIPER_ZOOM_OUT~~w~, um wieder ~h~wegzuzoomen~w~.\n\n[POR3_11:PORN3]\nDrücke die~h~ ~k~~PED_SNIPER_ZOOM_IN~~w~, um ~h~heranzuzoomen ~w~und die~h~ ~k~~PED_SNIPER_ZOOM_OUT~~w~, um wieder ~h~wegzuzoomen~w~.\n\n[POR3_12:PORN3]\nDrücke die~h~ ~k~~PED_FIREWEAPON~~w~, um ein Bild zu machen.\n\n[POR3_13:PORN3]\nDrücke die~h~ ~k~~PED_FIREWEAPON~~w~, um ein Bild zu machen.\n\n[POR3_14:PORN3]\nDrücke die~h~ ~k~~PED_FIREWEAPON~~w~, um ein Bild zu machen.\n\n[POR3_20:PORN3]\n~g~Wenn du ein Transportmittel brauchst, nimm den ~h~Sparrow~g~ hinter dem Haus.\n\n[POR3_16:PORN3]\n~g~Du brauchst drei gute kompromittierende Fotos von Alex Shrub mit Candy.\n\n[POR3_24:PORN3]\nGESCHOSSENE FOTOS:\n\n{=================================== MISSION TABLE PORN4 ===================================}\n\n[POR4_A:PORN4]\nTut mir leid, ich kann das jetzt nicht schlucken.\n\n[POR4_B:PORN4]\nAch KOMM, Darling!\n\n[POR4_C:PORN4]\nDer ist ausgestattet wie ein Pottwal, Herrgott noch mal,\n\n[POR4_D:PORN4]\nwie kannst du dich da nicht einfühlen?!\n\n[POR4_E:PORN4]\nAber Stevie...\n\n[POR4_F:PORN4]\nWie geht's meinem Starregisseur?\n\n[POR4_G:PORN4]\nOh Mann. Der Kampf zwischen künstlerischer Ambition und\n\n[POR4_H:PORN4]\ndiesem Rumgenudle tobt unvermindert.\n\n[POR4_I:PORN4]\nUnd bevor du fragst: Ja, alle vier Videos werden veröffentlicht, wenn...\n\n[POR4_J:PORN4]\nSchãtzchen, kannst du BITTE die Anaconda im Bild halten,\n\n[POR4_K:PORN4]\ndie kostet pro Stunde mehr als du!\n\n[POR4_L:PORN4]\nOh, sorry, Steve.\n\n[POR4_M:PORN4]\nIch hab mir gedacht, als Werbung für den Start brauchen wir einen richtigen Knaller.\n\n[POR4_N:PORN4]\nIrgendwas, was so richtig Furore macht in der Stadt. Hast du eine Idee?\n\n[POR4_O:PORN4]\nNa ja, früher gab's da immer Galas,\n\n[POR4_P:PORN4]\nStars, Limos, riesige Suchscheinwerfer am Nachthimmel...\n\n[POR4_Q:PORN4]\nSuchscheinwerfer? Ich hab eine Idee...\n\n[POR4_R:PORN4]\n....ja, ja, ja. Die heißen Mãdels mit ihren Paillettenkleidern und die Limos, oh, Premieren.\n\n[POR4_S:PORN4]\nO ja, Ma'am, natürlich, Ma'am,\n\n[POR4_T:PORN4]\nUnd die Presse und die Lichter-Flut...\n\n[POR4_01:PORN4]\n~g~Begib dich nach ~y~Downtown~g~und richte den Scheinwerfer auf dem Gebãude aus.\n\n[POR4_02:PORN4]\n~g~Du brauchst ein schnelles Bike, um von Dach zu Dach zu springen. Der Wachmann fãhrt immer mit einer ~y~PCJ 600~g~zur Arbeit...\n\n[POR4_03:PORN4]\n~g~Du wirst auf die Gebãudedãcher müssen. In eines der oberen Büros sollte ein Lift führen...\n\n[POR4_06:PORN4]\n~g~Kehre in das tiefer gelegene Büro zurück, wenn du noch mal auf die Dãcher musst.\n\n[POR4_07:PORN4]\n~g~Du brauchst ein Motorrad, um von Gebãude zu Gebãude zu springen.\n\n[POR4_08:PORN4]\n~g~Brich durch das Fenster, um zu starten. Du hast bis 07:00 Zeit. Dann wird es zu hell, um ungesehen hinaufzukommen.\n\n[POR4_09:PORN4]\n~g~Die Pfeile zeigen dir, zu welchem Gebãude du als nãchstes springen musst.\n\n[POR4_10:PORN4]\n~r~Es ist zu hell, um ungesehen dort hinaufzukommen.\n\n[POR4_11:PORN4]\nKehre zur Leiter zurück, wenn du noch mal auf die Dãcher musst.\n\n[POR4_05:PORN4]\n~g~Diese Treppe führt zu einem tiefer gelegenen Büro.\n\n[POR_AS1:PORN4]\nFILMSTUDIO-MISSIONEN ERFÜLLT\n\n[POR_AS2:PORN4]\n~g~Inter Global Films generiert nun bis zu $~1~ Einkünfte. Hol dir das Geld regelmãßig ab.\n\n{=================================== MISSION TABLE PROT1 ===================================}\n\n[PRO1_A:PROT1]\nOh, wir müssen diesen Laden umbauen. Das muss ãlter aussehen.\n\n[PRO1_B:PROT1]\nIch kann diesen Look nicht ab, Tommy. Was meinst du, sollen wir eine Bar einbauen..?\n\n[PRO1_D:PROT1]\nHört mal.\n\n[PRO1_E:PROT1]\nDie Zeit ist gekommen, die Stadt zu übernehmen. Sie wartet nur auf uns.\n\n[PRO1_F:PROT1]\nWir müssen langsam Gebiete einnehmen.\n\n[PRO1_G:PROT1]\nVice City soll merken, dass wir die neuen Bosse sind, versteht ihr?\n\n[PRO1_H:PROT1]\nJetzt beruhigt euch mal kurz. Allmãhlich kapiere ich schon, wie das ganze hier lãuft.\n\n[PRO1_I:PROT1]\nWas du brauchst, ist eine legale Fassade, Tommy, Immobilien. Hat mir nicht geschadet.\n\n[PRO1_J:PROT1]\nWir müssen die Muskeln spielen lassen, sonst war die ganze harte Arbeit umsonst.\n\n[PRO1_K:PROT1]\nDie Geschãftsleute hier wissen, dass Diaz weg ist und weigern sich, Schutzgeld zu zahlen.\n\n[PRO1_L:PROT1]\nOh, wir könnten es mit Schmiergeld versuchen...\n\n[PRO1_M:PROT1]\nSchmiergeld? Blödsinn! Ich zeig euch, wie man denen Angst macht.\n\n[PRO1_01:PROT1]\n~g~Demoliere die Schaufenster der Lãden und die Inhaber werden darum betteln, zahlen zu dürfen.\n\n[PRO1_03:PROT1]\n~r~Du sollst abhauen, nicht Kaffee trinken gehen.\n\n[PRO1_04:PROT1]\nMein Lebenswerk! Zerstört!\n\n[PRO1_05:PROT1]\nIch bin ruiniert...RUINIERT!!\n\n[PRO1_06:PROT1]\nIch zahle einen Haufen Schutzgeld!\n\n[PRO1_07:PROT1]\nMein schönes Schaufenster!\n\n[PRO1_08:PROT1]\nMein Laden! Mein schöner Laden!\n\n[PRO1_09:PROT1]\nVercetti. Merkt euch den Namen.\n\n[PRO1_10:PROT1]\nIch bin jetzt der Boss in der Stadt. ICH!\n\n[BUYP1:PROT1]\nDu kannst jetzt in bestimmten Gegenden auf der Karte Objekte kaufen.\n\n[BUYP2:PROT1]\nWenn du ein Gebãude mit grüner Markierung siehst, kannst du dieses kaufen.\n\n[PRO1_N:PROT1]\nIch bin in fünf Minuten zurück...\n\n[PRO1_11:PROT1]\n~g~Begib dich zum ~y~North Point Einkaufszentrum~g~ in ~y~Vice Point~g~.\n\n[PRO1_12:PROT1]\n~g~Zerbrich die Schaufenster eines jeden Ladens, und die Inhaber werden um neuen Schutz betteln.\n\n[PRO1_C:PROT1]\nDu bist mein Anwalt, nicht mein Innenarchitekt. Klar?\n\n[BUYP3:PROT1]\nStell dich in die Markierung und drücke die ~h~~k~~PED_ANSWER_PHONE~~w~-Taste, um das Objekt zu kaufen.\n\n[PRO1_13:PROT1]\n~g~Du hast fünf Minuten, um alle zu demolieren.\n\n{=================================== MISSION TABLE PROT2 ===================================}\n\n[PRO2_01:PROT2]\n~g~Schalte die Wachen aus, die die Front Page Bar beschützen und finde raus, wer hinter ihnen steckt.\n\n[PRO2_08:PROT2]\n~g~Die DBP Security wird wissen, dass du kommst. Schnapp sie dir, ehe sie abhauen.\n\n[PRO2_A:PROT2]\nWas gibt's für Probleme?\n\n[PRO2_B:PROT2]\nEine Bar weigert sich zu zahlen.\n\n[PRO2_C:PROT2]\nDie glauben, die werden von so einer Schlãgerbande beschützt.\n\n[PRO2_D:PROT2]\nAber keine Sorge, Tommy, ich regle das.\n\n[PRO2_E:PROT2]\nDas nennst du regeln?\n\n[PRO2_F:PROT2]\nIhr zwei. Hebt mal den Hintern...\n\n[PRO2_G:PROT2]\nLos.\n\n[PRO2_10:PROT2]\nZwei sind abgehauen. Finde sie und bring die Sache zuende.\n\n[PRO2_11:PROT2]\nSteig in den Wagen, Nichtsnutz.\n\n[PRO2_02:PROT2]\nDein Schutz braucht ein bisschen mehr Schutz.\n\n[PRO2_03:PROT2]\nAch, verdammt! Nicht schon wieder! Das brauche ich wirklich nicht!\n\n[PRO2_04:PROT2]\nDiese Idioten arbeiten eigentlich für die DBP Security gleich um die Ecke.\n\n[PRO2_05:PROT2]\nMacht ihr das mal unter euch aus.\n\n[PRO2_06:PROT2]\nWir sehen uns.\n\n[PRO2_07:PROT2]\nJa, ja. Wenn's sein muss.\n\n[PRO2_09:PROT2]\n~g~Begib dich zur Front Page Bar und sprich mit dem Besitzer.\n\n{=================================== MISSION TABLE PROT3 ===================================}\n\n[PRO3_A:PROT3]\nDu Trottel! Was hast du dir dabei gedacht?!\n\n[PRO3_B:PROT3]\nIst dir klar, was das bedeutet?!\n\n[PRO3_C:PROT3]\nDas könnte das Ende für uns alle sein!\n\n[PRO3_D:PROT3]\nDer Zeitzünder muss hin gewesen sein.\n\n[PRO3_E:PROT3]\nDer Laden war mit Sprengstoff vollgepackt wie eine Feuerwerkfabrik.\n\n[PRO3_F:PROT3]\nDann hat jemand den Cops einen Tipp gegeben...\n\n[PRO3_G:PROT3]\nWas gibt's für Probleme, Jungs?\n\n[PRO3_H:PROT3]\nMike sollte einen Laden im Einkaufszentrum abfackeln,\n\n[PRO3_I:PROT3]\naber er hat's vermasselt und jetzt wimmelt es dort von Bullen.\n\n[PRO3_J:PROT3]\nWir müssen unser Zeug holen und verschwinden!\n\n[PRO3_K:PROT3]\nLangsam, ihr beiden, lasst mich kurz nachdenken!\n\n[PRO3_L:PROT3]\nTommy Vercetti lãuft nicht einfach weg.\n\n[PRO3_M:PROT3]\nDie Cops werden das Gebãude sorgfãltig durchkãmmen, oder?\n\n[PRO3_N:PROT3]\nAber das dauert.\n\n[PRO3_O:PROT3]\nWir müssen den Laden selbst abfackeln.\n\n[PRO3_P:PROT3]\nJa, aber...\n\n[PRO3_Q:PROT3]\nNur ein Cop kommt auch nur in die Nãhe von dem Laden!\n\n[PRO3_R:PROT3]\nDann gehen wir eben als Cops.\n\n[PRO3_S:PROT3]\nWir brauchen Uniformen und einen Streifenwagen.\n\n[PRO3_T:PROT3]\nUnd das alles nur wegen dir, Mike.\n\n[PRO3_U:PROT3]\nTut mir leid.\n\n[PRO3_V:PROT3]\nIch hab's.\n\n[PRO3_W:PROT3]\nWir müssen die Cops hereinlocken,\n\n[PRO3_X:PROT3]\ndann sperren wir sie ein\n\n[PRO3_Y:PROT3]\nund überwãltigen sie.\n\n[PRO3_Z:PROT3]\nGuter Plan. Los geht's!\n\n[PRO3_A1:PROT3]\nOk.\n\n[PRO3_01:PROT3]\nOk, Lance, machen wir die Cops auf uns aufmerksam!\n\n[PRO3_02:PROT3]\n~g~ Nimm den Streifenwagen und lege die Bombe im Tarbrush Coffee Shop im Einkaufszentrum.\n\n[PRO3_03:PROT3]\n~g~Du hast Lance vergessen. Hole ihn.\n\n[PRO3_04:PROT3]\n~g~ Los geht's.\n\n[PRO3_05:PROT3]\n~r~Du hast Lance erledigt!\n\n[PRO3_07:PROT3]\n~g~Die Tarnung ist aufgeflogen. Beeilung, platziere die Bombe!\n\n[PRO3_09:PROT3]\nFessle und kneble sie!\n\n[PRO3_10:PROT3]\nUuh! Passt perfekt!\n\n[PRO3_11:PROT3]\nBisschen eng im Schritt vielleicht...\n\n[PRO3_12:PROT3]\nOh ja, ja. Meine auch, meine auch.\n\n[PRO3_13:PROT3]\nVorsicht, Bruder! Kein Cop fãhrt so schlecht!\n\n[PRO3_14:PROT3]\nDenk dran, lãchle die anderen Cops an.\n\n[PRO3_15:PROT3]\nHallo, Officer. Hübsche Marke, hübsche Marke.\n\n[PRO3_16:PROT3]\nGanz toll, Lance.\n\n[PRO3_17:PROT3]\nOk, die Zünder sind auf 5 Sekunden gestellt.\n\n[PRO3_18:PROT3]\n5 Sekunden?!! Nichts wie raus hier!\n\n[PRO3_19:PROT3]\nJetzt sind sie so richtig stocksauer.\n\n[PRO3_20:PROT3]\n~g~Bring 2 Cops dazu, dir in die Garage zu folgen.\n\n[PRO3_21:PROT3]\n~g~Beschaff dir einen Fahndungslevel, damit dir die Cops in die Garage folgen.\n\n[PRO3_22:PROT3]\n~g~Das Garagentor ist blockiert! Du musst es freirãumen, damit es schließen kann.\n\n[PRO3_23:PROT3]\n~g~Stell dich in die Markierung, um die Bombe zu platzieren.\n\n[PRO3_24:PROT3]\n~g~Verschwinde aus der Nãhe des Cafés!\n\n[PRO_AS1:PROT3]\nSCHUTZGELD-MISSIONEN ERFÜLLT\n\n[PRO_AS2:PROT3]\n~g~Das Vercetti Estate generiert nun bis zu $~1~ Einkünfte. Hol dir das Geld regelmãßig ab.\n\n[PRO3_08:PROT3]\n~g~Du musst zurück zu ~h~Vercetti Estate~g~ auf ~h~Starfish Island~g~.\n\n{=================================== MISSION TABLE RACES ===================================}\n\n[RACES_2:RACES]\n~g~Du brauchst ein Fahrzeug! Das ist kein Wettlaufen!\n\n[RACES_3:RACES]\n3..2..1.. LOS, LOS, LOS!\n\n[RACES_8:RACES]\n~r~Du hast das Rennen nicht gewonnen!\n\n[RACES00:RACES]\nRennen ~1~:\n\n[RACES01:RACES]\nTodeskaracho\n\n[RACES02:RACES]\nOcean Drive\n\n[RACES03:RACES]\nKüsten-Rallye\n\n[RACES04:RACES]\nCapital Cruise\n\n[RACES05:RACES]\nTour!\n\n[RACES06:RACES]\nV.C. Endurance\n\n[RACES07:RACES]\nStartgebühr: $~1~\n\n[RACES08:RACES]\nBestzeit: ~1~:~1~\n\n[RACES09:RACES]\nBeste Platzierung: 1.\n\n[RACES10:RACES]\nBeste Platzierung: 2.\n\n[RACES11:RACES]\nBeste Platzierung: 3.\n\n[RACES12:RACES]\nBeste Platzierung: 4.\n\n[RACES13:RACES]\nStreckenlãnge: ~1~.~1~ km\n\n[RACES15:RACES]\nBestzeit: Nicht verfügbar\n\n[RACES16:RACES]\nBeste Platzierung: Nicht verfügbar\n\n[RACES19:RACES]\nDu hast nicht genug Geld, um an diesem Rennen teilzunehmen.\n\n[RACES22:RACES]\nBestzeit: ~1~:0~1~\n\n[RACES23:RACES]\nStreckenlãnge: ~1~.~1~ Meilen\n\n[RACES_1:RACES]\n~g~Schnapp dir ein schnelles Fahrzeug und begib dich zur Startlinie.\n\n[RACEHLP:RACES]\n~w~Drücke die~h~ ~k~~PED_SPRINT~~w~, um das ausgewãhlte Rennen zu starten. Drücke die~h~ ~k~~VEHICLE_ENTER_EXIT~~w~, um abzubrechen.\n\n{=================================== MISSION TABLE RCHELI1 ===================================}\n\n[WRECKED:RCHELI1]\n~r~Das Fahrzeug ist Schrott!\n\n[RCH1_4:RCHELI1]\nVerbleibende Checkpoints:\n\n[RCH1_7:RCHELI1]\n~g~Es gibt insgesamt 20 Checkpoints.\n\n[RCH1_12:RCHELI1]\n~g~Der ferngesteuerte Helikopter gerãt außer Reichweite!\n\n[RCH1_13:RCHELI1]\n~r~Der ferngesteuerte Helikopter ist außer Reichweite!\n\n[RCH1_8:RCHELI1] { reVC update }\n~g~Wenn du diese Mission abbrechen willst, drücke die ~h~~k~~VEHICLE_FIREWEAPON~~g~, um deinen Heli zu sprengen.\n\n{=================================== MISSION TABLE RCPLNE1 ===================================}\n\n[RCPL1_4:RCPLNE1]\n~g~Miss dich mit 3 anderen ferngesteuerten Maschinen in einem CHECKPOINT RENNEN\n\n[RCPL1_5:RCPLNE1]\n~g~Flieg durch die Checkpoints, die über Vice City verteilt sind.\n\n[RCPL1_6:RCPLNE1] { reVC update }\n~g~Wenn du diese Mission abbrechen willst, drücke die ~h~~k~~VEHICLE_FIREWEAPON~~g~, um dein Flugzeug zu sprengen.\n\n[RCPL1_8:RCPLNE1]\n~g~Dein ferngesteuertes Flugzeug gerãt außer Reichweite!\n\n[RCPL1_9:RCPLNE1]\n~r~Dein ferngesteuertes Flugzeug ist außer Reichweite!\n\n{=================================== MISSION TABLE RCRACE1 ===================================}\n\n[RCRC1_1:RCRACE1]\n~g~Liefere dir mit 3 anderen RC Bandits ein CHECKPOINT-RENNEN über 2 RUNDEN.\n\n[RCRC1_3:RCRACE1]\n~g~Letzte Runde!\n\n[RCR1_4:RCRACE1]\nVerbleibende Runden:\n\n[RCR1_1:RCRACE1]\n~g~Tritt in einem Checkpoint-Rennen gegen 3 andere ferngesteuerte Autos an.\n\n[RCR1_2:RCRACE1]\n~g~Du musst als erster 2 volle Runden auf dem Kurs fahren!\n\n[RCR1_6:RCRACE1]\n~g~Dein ferngesteuertes Auto gerãt außer Reichweite!\n\n[RCR1_7:RCRACE1]\n~r~Dein ferngesteuertes Auto ist außer Reichweite!\n\n{=================================== MISSION TABLE ROCK1 ===================================}\n\n[RBM1_A:ROCK1]\nAllllllllRrrighttt!\n\n[RBM1_B:ROCK1]\nFantastisch, einfach fantastisch!\n\n[RBM1_D:ROCK1]\nHey, kennst du die Jungs von Love Fist?\n\n[RBM1_E:ROCK1]\nNein, aber ihre Musik habe ich immer geliebt.\n\n[RBM1_F:ROCK1]\nIch stelle dir die Band vor.\n\n[RBM1_G:ROCK1]\nDas ist P, Percy, Dick, und Willy ist auf dem Klo. Und das vorher in der Kabine war Jezz.\n\n[RBM1_H:ROCK1]\nJungs, ich möchte euch einen guten Freund vorstellen.\n\n[RBM1_I:ROCK1]\nDas ist Tommy. Wir kennen uns schon ewig.\n\n[RBM1_J:ROCK1]\nAlles paletti, Mann.\n\n[RBM1_K:ROCK1]\nUnd, ãh, wie war dein Name noch mal?\n\n[RBM1_L:ROCK1]\nLass das, Jezz. Merk dir eines,\n\n[RBM1_M:ROCK1]\nmit mir kannst du diese Spielchen nicht machen.\n\n[RBM1_N:ROCK1]\nIch bin dir einfach über, Sonnenscheinchen.\n\n[RBM1_O:ROCK1]\nDie Sache ist die, Tom, die Jungs brauchen Hilfe.\n\n[RBM1_P:ROCK1]\nDie haben hier keine Connections, kein Vitamin B.\n\n[RBM1_Q:ROCK1]\nWir brauchen Stoff, Alter.\n\n[RBM1_R:ROCK1]\nDamit wir den alten Love Fist Spirit finden, verstehst du?!\n\n[RBM1_S:ROCK1]\nWir sind hier in Vice City, Mann. Wo liegt das Problem?\n\n[RBM1_U:ROCK1]\nLove Juice, Mann!\n\n[RBM1_V:ROCK1]\nLove Juice?\n\n[RBM1_W:ROCK1]\nGenau. 2 Teile TNT-Whiskey, 1 Teil Koks, 5 Pãckchen Brause und 1 Liter Sprit.\n\n[RBM1_X:ROCK1]\nKannst du uns weiterhelfen, Alter?\n\n[RBM1_Y:ROCK1]\nEs würde den Jungs wirklich viel bedeuten.\n\n[RBM1_Z:ROCK1]\nDu kannst den Jungs doch helfen, oder?\n\n[RBM1_7:ROCK1]\n~r~Du hast den Love Juice nicht rechtzeitig besorgt!\n\n[RBM1_8:ROCK1]\n~r~Mercedes ist erledigt!\n\n[RBM1_10:ROCK1]\n~r~Du Idiot! Du hast die Ware vernichtet!\n\n[RBM1_13:ROCK1]\n~g~Bring den Love Juice und Mercedes zu der Band bevor sie auf die Bühne muss.\n\n[RBM1_15:ROCK1]\n~r~Du hast den Dealer verloren, unser Geld und den Stoff!\n\n[RBM1_17:ROCK1]\n~g~Knöpf dir den Dealer vor und hol dir den Stoff!\n\n[MOB_07A:ROCK1]\nHey, die Jungs könnten ein bisschen Gesellschaft vertragen, falls du weißt, was ich meine...\n\n[MOB_07B:ROCK1]\nDa kenne ich genau die richtige.\n\n[ROK1_5:ROCK1]\nHey, Mercedes!\n\n[ROK1_6:ROCK1]\nHi, Tommy. Na, wie lãuft's so?\n\n[ROK1_7:ROCK1]\nAlles bestens. Hör mal, willst du die Jungs von Love Fist verführen?\n\n[ROK1_8:ROCK1]\nOk, aber dafür bist du mir einen Gefallen schuldig.\n\n[RBM1_14:ROCK1]\n~g~Du brauchst ein Auto oder Motorrad!\n\n[RBM1_1:ROCK1]\n~g~Hol Mercedes in ihrer Wohnung ab.\n\n[RBM1_12:ROCK1]\n~g~Besorg die Zutaten für den 'Love Juice' von dem Dealer.\n\n[ROK1_2:ROCK1]\nNICHT MEHR BENÖTIGT\n\n[ROK1_3:ROCK1]\nNICHT MEHR BENÖTIGT\n\n[MERC_39:ROCK1]\nWir sehen uns spãter, Big Boy.\n\n[RBM1_C:ROCK1]\nHey, Tommy! Schön, dass du kommen konntest.\n\n[RBM1_9:ROCK1]\n~g~Besorg von dem Dealer Love Juice für Love Fist!\n\n[ROK1_1A:ROCK1]\nSuchst du was Bestimmtes? Ich habe genau, was du brauchst!\n\n[ROK1_9:ROCK1]\nDanke für die Kohle, du Trottel!\n\n[RBM1_T:ROCK1]\nWir brauchen Love Juice, Mann, klar?\n\n{=================================== MISSION TABLE ROCK2 ===================================}\n\n[RBM2_A:ROCK2]\nTommy, Mann, bin ich froh, dich zu sehen!\n\n[RBM2_B:ROCK2]\nWas ist los?\n\n[RBM2_C:ROCK2]\nSchlechte Vibes, Tommy...\n\n[RBM2_E:ROCK2]\nDa ist so 'n Typ, wir kennen ihn kaum, aber er kennt uns.\n\n[RBM2_F:ROCK2]\nSo wie er da. Weiß alles über uns.\n\n[RBM2_G:ROCK2]\nWeiß, dass Willy auf Damenunterwãsche steht, eh!\n\n[RBM2_H:ROCK2]\nOder dass Percy auf Duran Duran steht!\n\n[RBM2_K:ROCK2]\nJa, die Liebesrakete, schon gut. Aber hör zu, dieser Typ...\n\n[RBM2_L:ROCK2]\nja, ja, der Typ will Love Fist ausknipsen.\n\n[RBM2_M:ROCK2]\nAusknipsen, Tommy.\n\n[RBM2_N:ROCK2]\nLove Fist soll verschwinden. Wie es immer heißt: Die Besten sterben jung.\n\n[RBM2_O:ROCK2]\nAber Tommy, du musst Love Fist retten!\n\n[RBM2_P:ROCK2]\nWir geben in zwei Stunden eine Autogrammstunde, und ich glaube...\n\n[RBM2_Q:ROCK2]\nUnd die Jungs glauben, dass der Kerl dort irgendwas plant.\n\n[RBM2_1:ROCK2]\n~g~Fahre die Limo zum Ort der Autogrammstunde und versuche, den Irren zu finden.\n\n[RBM2_2:ROCK2]\n~r~Du hast den Wagen der Band geschrottet!\n\n[RBM2_3:ROCK2]\n~g~Geh zu der Autogrammstunde!\n\n[RBM2_4:ROCK2]\n~g~Erledige den Irren. Lass ihn nicht entkommen!\n\n[RBM2_5:ROCK2]\n~r~Du hast ihn verloren, du Idiot!\n\n[RBM2_7:ROCK2]\n~r~Die Fans wurden angegriffen. Der Irre wird nicht auftauchen!\n\n[RBM2_8:ROCK2]\n~r~Die Security-Leute wurden angegriffen. Der Irre wird nicht auftauchen!\n\n[PSYCH_1:ROCK2]\nLove Fist wird in der Hölle braten!\n\n[PSYCH_2:ROCK2]\nLove Fist hat mein Leben zerstört!\n\n[RBM2_I:ROCK2]\nHalt's Maul, du Irrer! Nur weil Jezz auf Schafe steht.\n\n[RBM2_R:ROCK2]\nHey, Schnauze!\n\n[RBM2_D:ROCK2]\nDas ist kein Spaß, das ist 'ne brutale Geschichte, brutal, ok?\n\n[RBM2_J:ROCK2]\nIch sage nur, die Liebesrakete, ok?\n\n{=================================== MISSION TABLE ROCK3 ===================================}\n\n[RBM3_A:ROCK3]\nTommy! Tommy! Tommy, Mann, der Irre ist wieder da!\n\n[RBM3_B:ROCK3]\nWas ist denn los?\n\n[RBM3_C:ROCK3]\nDieser Irre lãsst Love Fist nicht in Ruhe!\n\n[RBM3_D:ROCK3]\nDu hast ihn nicht erwischt, Mann. Und jetzt ist er wieder da.\n\n[RBM3_E:ROCK3]\nJa, ja, ja, und es ist nãmlich so...\n\n[RBM3_F:ROCK3]\nwir brauchen für die Limo einen Fahrer, dem wir vertrauen können,\n\n[RBM3_G:ROCK3]\nweil der Irre uns stãndig bedroht!\n\n[RBM3_I:ROCK3]\nWir scheißen uns alle in die Hosen, Mann.\n\n[RBM3_J:ROCK3]\nOk, Jungs, nur die Ruhe. Ich mach das schon.\n\n[RBM3_K:ROCK3]\nNormalerweise würde ich keine besoffenen, schottischen Tucken durch die Gegend kutschieren,\n\n[RBM3_L:ROCK3]\naber für euch mache ich eine Ausnahme.\n\n[ROK3_03:ROCK3]\nDann mach mir einen großen.\n\n[ROK3_04:ROCK3]\nHey, Tommy, nun mach mal halblang, Mann.\n\n[ROK3_08:ROCK3]\nLangsam wird's langweilig.\n\n[ROK3_09:ROCK3]\nHalt bloß das Pedal durchgedrückt!!\n\n[ROK3_61:ROCK3]\nWir müssen die Bombe finden!\n\n[ROK3_28:ROCK3]\nIch werd Bass in der Hölle spielen.\n\n[ROK3_30:ROCK3]\nTu doch einer was!\n\n[ROK3_32:ROCK3]\nOk, Obermacho, dann tu du doch was!\n\n[ROK3_34:ROCK3]\nWilly könnte den TNT-Whiskey mit einem Strohhalm raussaugen.\n\n[ROK3_37:ROCK3]\nGebt Willy einen Strohhalm!\n\n[ROK3_41:ROCK3]\nWelchen Draht, Tommy?\n\n[ROK3_42:ROCK3]\nDen grünen.\n\n[ROK3_43:ROCK3]\nDa ist kein grüner. Oder ist der hier grün?\n\n[ROK3_44:ROCK3]\nSieht für dich einer von den Drãhten grün aus?\n\n[ROK3_49:ROCK3]\nIch hab euch doch jahrelang nur mitgeschleppt.\n\n[ROK3_51:ROCK3]\nEin großes keifendes Weib.\n\n[ROK3_52:ROCK3]\nJa.\n\n[ROK3_53:ROCK3]\nKlappe jetzt und zieht einen Draht raus.\n\n[ROK3_54:ROCK3]\nWelchen?\n\n[ROK3_55:ROCK3]\nDen da...\n\n[ROK3_56:ROCK3]\nNEIN!\n\n[ROK3_57:ROCK3]\nMann, alles ok. Wir sind nicht hochgegangen, Alter. Tommy, Mann, gut gemacht. Rock 'n' Roll, Mann.\n\n[ROK3_58:ROCK3]\nMüssen wir nicht zu einem Gig? Krach machen? Groupies abgreifen?\n\n[ROK3_59:ROCK3]\nLOVE FIST!\n\n[ROK3_60:ROCK3]\nBist du fertig mit der Pulle?\n\n[RBM3_4:ROCK3]\n~r~Love Fist ist Geschichte!\n\n[RBM3_6:ROCK3]\nDETONATION:\n\n[RBM3_1:ROCK3]\n~g~Chauffiere Love Fist zu ihrem Auftritt.\n\n[RBM3_2:ROCK3]\nFalls du versuchst, aus dem Auto auszusteigen, wenn die Bombe scharfgemacht ist, wird sie explodieren...\n\n[RBM3_3:ROCK3]\nIst der Detonations-Balken am Anschlag, explodiert die Bombe.\n\n[RBM3_8:ROCK3]\nJe schneller du fãhrst, desto niedriger der Detonations-Balken.\n\n[RBM3_7:ROCK3]\n~g~BOMBE ENTSCHÃRFT!\n\n[ROK3_6A:ROCK3]\n~g~Love Fist. Ihr habt den Ãther lange genug verschmutzt!\n\n[ROK3_6B:ROCK3]\n~g~Ich wollte euer Freund sein. Jetzt will ich, dass ihr untergeht.\n\n[ROK3_62:ROCK3]\nWir dachten, wir zeigen dir mal unseren Rocktempel...\n\n[ROK3_63:ROCK3]\nKannst dir die Power von Love Fist reinziehen!\n\n[ROK3_64:ROCK3]\nHör sich das einer an, Mann. Das ist Pappmaché und Klebeband.\n\n[ROK3_65:ROCK3]\nHey, für die Kids ist es ein Tempel, und wir sind die Priester!\n\n[ROK3_66:ROCK3]\nTja, wenn die Kids es toll finden, dass ihre Priester dicht und unmusikalisch sind,\n\n[ROK3_67:ROCK3]\nwas soll man da sagen?\n\n[ROK3_68:ROCK3]\nOh, Mist, das Ding frisst schon wieder das Band.\n\n[ROK3_69:ROCK3]\nWenn das so ist, müssen wir live spielen.\n\n[ROK3_70:ROCK3]\nOoooh Shit! Mein Darm...\n\n[ROK3_01:ROCK3]\nEndlich, Mann, Zeit für einen wohlverdienten Drink.\n\n[ROK3_02:ROCK3]\nDie Halle ist nur 100 Meter die Straße runter.\n\n[ROK3_05:ROCK3]\nIch werd irre, wenn ich keinen Sprit kriege.\n\n[ROK3_07:ROCK3]\nTommy, mein Freund, wir müssen die Band retten!\n\n[ROK3_29:ROCK3]\nTommy, bleib auf dem Gas, Alter.\n\n[ROK3_31:ROCK3]\nGanz toll. 'Tu doch einer was.' Was ist denn das für eine Ansage? Da kenn ich mutigere Mãdels.\n\n[ROK3_33:ROCK3]\nAlter, ich bin Musiker. Vom Bomben-Entschãrfen hab ich keinen blassen Dunst.\n\n[ROK3_35:ROCK3]\nEben, so was liegt dir doch, was ich so höre.\n\n[ROK3_38:ROCK3]\nEinen Strohhalm?! Dies ist der Tour-Bus von Love Fist!\n\n[ROK3_39:ROCK3]\nWo zum Geier sollte hier ein Strohhalm sein?\n\n[ROK3_46:ROCK3]\nIch hãtte euch alle rausschmeißen sollen, als es noch ging, Mann.\n\n[ROK3_47:ROCK3]\nKapitalist.\n\n[ROK3_48:ROCK3]\nKameradenschwein.\n\n[ROK3_73:ROCK3]\nJezz spielt das Band ab,\n\n[RBM3_9:ROCK3]\nWenn du angehalten wirst oder langsam fãhrst, wãchst der Detonations-Balken.\n\n[ROK3_50:ROCK3]\nHalt die Klappe. Du bist ein Idiot.\n\n[ROK3_36:ROCK3]\nHey, ich war an dem Abend vielleicht komplett zugedröhnt!\n\n[RBM3_H:ROCK3]\nIch scheiß mir in die Hose, Mann. Ich will zu meiner Mama!\n\n[ROK3_45:ROCK3]\nOh nein. Im Angesicht des Todes sieht alles grün aus.\n\n[ROK3_6C:ROCK3]\n~g~Wenn ihr langsamer werdet, geht eure Limo hoch, IHR UND EURE HAARIGEN ÃRSCHE mit dazu!\n\n[ROK3_71:ROCK3]\nWir müssen uns ranhalten. Danke nochmal, Tommy, du hast es echt drauf. Ciao.\n\n[ROK3_1:ROCK3]\nEndlich, Mann, Zeit für einen wohlverdienten Drink. Die Halle ist nur 100 Meter die Straße runter.\n\n[ROK3_2:ROCK3]\nMach mir mal einen großen. Hey, Tommy, leg mal 'nen anderen Sound auf, Mann.\n\n[ROK3_3:ROCK3]\nIch werd wirr im Kopf, wenn nichts zum Headbangen lãuft. Hey, Tommy, leg mal dieses Band ein.\n\n[ROK3_4:ROCK3]\nLove Fist. Ihr habt den Ãther lange genug verschmutzt! Ich wollte euer Freund sein.\n\n[ROK3_5:ROCK3]\nJetzt will ich, dass ihr untergeht. Wenn ihr langsamer werdet, geht eure Limo hoch, IHR UND EURE HAARIGEN ÃRSCHE mit dazu!\n\n[ROK3_6:ROCK3]\nTommy, mein Freund, du musst die Band retten! Langsam wird's langweilig. Halt bloß das Pedal durchgedrückt!!\n\n[ROK3_7:ROCK3]\nWir müssen die Bombe finden! Können wir nicht einfach den ganzen Tag rumfahren? Wir haben jedenfalls jede Menge zu saufen.\n\n[ROK3_8:ROCK3]\nKönnte die Bombe nicht unter der Motorhaube sein? Da kommen wir nie ran, ohne anzuhalten! Wir werden alle sterben! Ich besauf mich!\n\n[ROK3_9:ROCK3]\nHey, hier gibt's eine Warteschlange, Alter! Die Lösung liegt nicht in der Minibar! Weg da!\n\n[ROK3_10:ROCK3]\nHey, aus der Wodkapulle kommen Drãhte raus! Das ist kein Wodka, das ist TNT-WHISKEY!\n\n[ROK3_11:ROCK3]\nWAAAAAAGGGHHHH!!!! Das Ding ist scharfgemacht!! WAAAAAAAAAAGGGHHHHHH!!!!\n\n[ROK3_12:ROCK3]\nMan hat mir immer gesagt, der Alk wird mich killen... Das kenn ich aus dem Fernsehen. Du musst einen der Drãhte rausziehen. Welchen Draht? Weiß ich doch nicht, Mann.\n\n[ROK3_13:ROCK3]\nKeinen Schimmer. Willy, sag doch mal was. Ich werd Bass in der Hölle spielen.\n\n[ROK3_14:ROCK3]\nTommy, bleib auf dem Gas, Mann. Tu doch einer was! Ganz toll...\n\n[ROK3_15:ROCK3]\n'Tu doch einer was.' Was ist denn das für eine Ansage? Da kenn ich mutigere Mãdchen. Ok, Obermacho, dann tu du doch was!\n\n[ROK3_16:ROCK3]\nAlter, ich bin Musiker. Mit Bomben kenne ich mich nicht aus. Willy könnte den TNT-Whiskey mit einem Strohhalm raussaugen.\n\n[ROK3_17:ROCK3]\nEben, so was liegt dir doch, was ich so höre. Hey, ich war total blau an dem Abend, das wisst ihr ganz genau!\n\n[ROK3_18:ROCK3]\nGebt Willy einen Strohhalm! Einen Strohhalm?! Wi sind im Band-Auto von Love Fist!\n\n[ROK3_19:ROCK3]\nWo zum Geier sollte hier ein Strohhalm sein? Welchen Draht, Tommy? Den grünen. Da ist kein grüner.\n\n[ROK3_20:ROCK3]\nOder ist der hier grün? Sieht für dich einer von den Drãhten grün aus?\n\n[ROK3_21:ROCK3]\nOh nein. Im Angesicht des Todes sieht alles grün aus. Ich hãtte euch alle rausschmeißen sollen, als es noch ging, Mann.\n\n[ROK3_22:ROCK3]\nKameradenschwein. Kapitalist. Ich hab euch doch jahrelang nur mitgeschleppt. Halt die Klappe. Du bist ein Idiot.\n\n[ROK3_23:ROCK3]\nEin großes keifendes Weib. Ja. Klappe jetzt und zieht einen Draht raus. Welchen? Den da...\n\n[ROK3_24:ROCK3]\nNEIN! Mann, alles ok. Wir sind nicht hochgegangen, Alter.\n\n[ROK3_25:ROCK3]\nTommy, Mann, gut gemacht. Rock 'n' Roll, Mann. Müssen wir nicht zu einem Gig?\n\n[ROK3_26:ROCK3]\nKrach machen? Groupies abgreifen? LOVE FIST!\n\n[ROK3_27:ROCK3]\nBist du fertig mit der Pulle?\n\n{=================================== MISSION TABLE SERG1 ===================================}\n\n[TEX1_0:SERG1]\n~g~Die Zielperson ist auf der Driving Range. Sorg dafür, dass er seinen letzten Golfball geschlagen hat!\n\n[TEX1_A:SERG1]\nKomm rein und setz dich auf deinen Hintern, Junge.\n\n[TEX1_B:SERG1]\nMein Daddy hat immer gesagt, einem geschenkten Gaul schaut man nicht ins Maul. Hat's auch nie getan.\n\n[TEX1_C:SERG1]\nEin Glãschen alter Kentucky gefãllig?\n\n[TEX1_D:SERG1]\nNein danke.\n\n[TEX1_E:SERG1]\nEin nüchterner Denker, das gefãllt mir.\n\n[TEX1_F:SERG1]\nIm Immobiliengeschãft geht's nicht um hochtrabende Vertrãge.\n\n[TEX1_G:SERG1]\nEs geht um Land. Und darum, dieses Land zu kriegen. Kannst du mir folgen?\n\n[TEX1_H:SERG1]\nOh, ja.\n\n[TEX1_I:SERG1]\nIch will, dass so ein sturer Hund sein Land hergibt.\n\n[TEX1_J:SERG1]\nMir scheint, du könntest ihn dazu überreden.\n\n[TEX1_K:SERG1]\nIch bin der reinste Überredungskünstler.\n\n[TEX1_L:SERG1]\nJa. Er wird im Country Club sein, auf dem Golfplatz.\n\n[TEX1_M:SERG1]\nKnarren sind dort verboten. Seine Bodyguards werden also unbewaffnet sein.\n\n[TEX1_N:SERG1]\nDu sollst ihn so richtig gründlich vermöbeln.\n\n[TEX1_O:SERG1]\nHier, ich hab dir einen Mitgliedsausweis besorgt. Aber du brauchst passendere Kleidung.\n\n[TEX1_2:SERG1]\n~g~Begib dich jetzt zum Leaf Links Golf Club.\n\n[TEX1_3:SERG1]\nWer ist der Kerl? Jungs, nehmt ihn euch vor.\n\n[TEX1_6:SERG1]\nHübscher Hintern, Baby!\n\n[TEX1_7:SERG1]\nBin ich das?\n\n[TEX1_8:SERG1]\nJedesmal wenn du in einen Golfwagen steigst, erhãltst du automatisch einen Golfschlãger, vorausgesetzt, du hast nicht schon eine Nahkampfwaffe.\n\n[TEX1_9:SERG1]\nSchnapp ihn dir!\n\n[TEX1_10:SERG1]\nMach den Irren fertig!\n\n[TEX1_1:SERG1]\n~g~Besorg dir bei Jocksport Golferklamotten.\n\n{=================================== MISSION TABLE SERG2 ===================================}\n\n[TEXEXIT:SERG2]\n~g~Jetzt verschwinde aus Little Haiti!\n\n[TEX_2A:SERG2]\n~g~Großartig! Sie haben dich bemerkt!\n\n[TEX_2B:SERG2]\n~r~Narr! Die Leute müssen SEHEN, dass der Tãter ein Kubaner ist!\n\n[TEX_2C:SERG2]\n~g~Besorge dir bei Rafael's Kleidung in den Farben der kubanischen Gang.\n\n[TEX_2D:SERG2]\n~g~Nimm dir jetzt den Boss der Haitianer in Romeros Beerdigungsinstitut vor.\n\n[TEX2_A:SERG2]\nTommy, das ist Donald Love. Donald, das ist Tommy Vercetti,\n\n[TEX2_B:SERG2]\nder neueste Draufgãnger hier in der Stadt.\n\n[TEX2_C:SERG2]\nJa...ãh...\n\n[TEX2_D:SERG2]\nDonald, sei still und hör zu. Vielleicht kannst du was lernen.\n\n[TEX2_E:SERG2]\nAlso. Nichts lãsst Immobilienpreise schneller abstürzen als ein guter alter Bandenkrieg.\n\n[TEX2_F:SERG2]\nAußer vielleicht eine Katastrophe, eine biblische Plage oder so,\n\n[TEX2_G:SERG2]\naber das ginge hier wohl zu weit.\n\n[TEX2_H:SERG2]\nKannst du mir folgen, Brillenschlange?\n\n[TEX2_I:SERG2]\nJüngst starb ein haitianischer Gang-Boss. Man tippt, es waren die Kubaner, aber keiner weiß es.\n\n[TEX2_J:SERG2]\nAber wir wollen sicher gehen. Du verkleidest dich als kubanischer Hombre\n\n[TEX2_K:SERG2]\nund machst Krawall bei der Beerdigung. Misch sie auf und dann verzieh dich.\n\n[TEX2_L:SERG2]\nKannst du mir folgen, Donald?\n\n[TEX2_M:SERG2]\nDas dürfte das Fass zum Überlaufen bringen, was?\n\n[TEX2_N:SERG2]\nUnd wir lehnen uns zurück und sehen zu, wie die Preise purzeln.\n\n{=================================== MISSION TABLE SERG3 ===================================}\n\n[TEX3_A:SERG3]\nPass auf, Junge. Ich habe ein Problem und denke, du könntest mir weiterhelfen.\n\n[TEX3_B:SERG3]\nIch bin kein Bauunternehmer.\n\n[TEX3_C:SERG3]\nNein, ich dachte mehr an deine Talente als Abrissunternehmer.\n\n[TEX3_D:SERG3]\nDas hier zeigt, was wir geplant haben. Und so-\n\n[TEX3_E:SERG3]\n-so sieht der betreffende Grund heute aus.\n\n[TEX3_F:SERG3]\nSie wollen sagen, das neue Bürohaus da ist Ihnen im Weg.\n\n[TEX3_G:SERG3]\nGut mitgedacht.\n\n[TEX3_H:SERG3]\nAlso, ich verdrücke mich eine Weile aus der Stadt,\n\n[TEX3_I:SERG3]\nund wenn dieses Bürogebãude urplötzlich irreparable Schãden aufweist, dann...\n\n[TEX3_J:SERG3]\n....fühlen Sie sich als guter Mensch verpflichtet, einzuspringen und\n\n[TEX3_K:SERG3]\n-für die Neugestaltung eines wichtigen Gebiets der Stadt zu sorgen?\n\n[TEX3_L:SERG3]\nWo finde ich mehr Mãnner wie dich?\n\n[TEX3_1:SERG3]\n~g~Benutze den ferngesteuerten Helikopter, um Bomben zu 4 Zielen an dem zur Sprengung vorgesehenen Gebãude zu transportieren.\n\n[TEX3_2:SERG3]\n~g~Du musst an jedem Ziel eine Bombe abwerfen. Die Reihenfolge ist beliebig.\n\n[TEX3_3:SERG3]\n~g~Steuere den Helikopter direkt über eine Bombe, um sie aufzunehmen. Die Bombe heftet sich dann automatisch an den Helikopter.\n\n[TEX3_5:SERG3]\n~g~Wenn eine Bombe ihr Ziel verfehlt, kannst du sie erneut aufnehmen und es nochmal versuchen.\n\n[TEX3_7:SERG3]\n~g~Dann hast du noch 7 Minuten, um die restlichen Bomben im Ziel zu platzieren.\n\n[TEX3_8:SERG3]\n~g~Du hast das Ziel verfehlt! Nimm die Bombe wieder auf und versuche es nochmal!\n\n[TEX3_10:SERG3]\n~g~Wirf die Bombe über einem der Ziele ab.\n\n[TEX3_11:SERG3]\nVerbleibende Ziele:\n\n[TEX3_17:SERG3]\n~r~Die Zeit ist um. Du hast es nicht geschafft, das Gebãude zu sprengen.\n\n[TEX3_18:SERG3]\n~r~Dein Helikopter wurde zerstört! Wie willst du jetzt die Bomben transportieren?\n\n[TEX3_19:SERG3]\n~r~Deine Bombe ist im Wasser gelandet! Du brauchst ALLE 4 Bomben, um die Sprengung vorzunehmen.\n\n[TEX3_20:SERG3]\n~g~Dein Helikopter ist fast außer Reichweite. Du musst zurück zur Baustelle, um deine Arbeit zuende zu bringen!\n\n[TEX3_21:SERG3]\n~r~Dein Helikopter befindet sich außer Reichweite!\n\n[TEX3_24:SERG3]\nDrücke ~h~~k~~VEHICLE_LOOKLEFT~~w~, um den Helikopter gegen den Uhrzeigersinn zu drehen.\n\n[TEX3_25:SERG3]\nDrücke ~h~~k~~VEHICLE_LOOKLEFT~~w~, um den Helikopter im Uhrzeigersinn zu drehen.\n\n[TEX3_27:SERG3]\n~g~Über eine Haupttreppe hat man Zugang zu allen Stockwerken des Gebãudes.\n\n[TEX3_31:SERG3]\n~r~Du hast den Wagen mit den Bomben und dem ferngesteuerten Helikopter zerstört!\n\n[TEX3_32:SERG3]\nDu kannst ~h~nach hinten sehen~w~, indem du ~h~gleichzeitig ~k~~VEHICLE_LOOKLEFT~ und ~k~~VEHICLE_LOOKRIGHT~ drückst~w~.\n\n[TEX3_4:SERG3] { reVC update }\n~g~Um eine Bombe abzuwerfen, drücke die~h~ ~k~~VEHICLE_FIREWEAPON~~w~.\n\n[TEX3_29:SERG3] { reVC update }\nUm eine Bombe abzuwerfen, drücke die~h~ ~k~~VEHICLE_FIREWEAPON~.\n\n[TEX3_26:SERG3]\nDrücke die ~h~~k~~VEHICLE_BRAKE~~w~, um die Rotorgeschwindigkeit zu verringern, der Helikopter ~h~verliert dann an Höhe.\n\n[TEX3_22:SERG3]\nDrücke die ~h~~k~~VEHICLE_ACCELERATE~~w~, um die Rotorgeschwindigkeit zu erhöhen, der Helikopter ~h~gewinnt dann an Höhe.\n\n[TEX3_16:SERG3]\n~g~Begib dich zu dem ~w~TOPFUN~g~-Wagen nahe dem zum Abriss vorgesehenen Gebãude.\n\n[TEX3_33:SERG3]\nWenn du eine Bombe aufgenommen hast, zeigt dir das Radar die Position des Ziels in Relation zu dem ferngesteuerten Helikopter.\n\n[TEX3_34:SERG3]\nEin ~h~nach oben zeigendes Dreieck ~w~bedeutet, dass das Ziel sich in ~h~größerer Höhe ~w~befindet als der Helikopter.\n\n[TEX3_35:SERG3]\nEin ~h~nach unten zeigendes Dreieck ~w~bedeutet, dass das Ziel sich in ~h~geringerer Höhe ~w~befindet als der Helikopter.\n\n[TEX3_36:SERG3]\nEin ~h~Viereck ~w~ bedeutet, dass das Ziel sich auf ~h~der gleichen Höhe ~w~befindet wie der Helikopter.\n\n[TEX3_6:SERG3]\n~g~Wenn du die erste Bombe aufgenommen hast, wird der Zeitzünder aktiviert.\n\n[TEX3_28:SERG3]\nUm ~h~eine Bombe aufzunehmen~w~, steuere den Helikopter direkt über sie. Der Helikopter kann immer nur eine Bombe tragen.\n\n[TEX3_30:SERG3]\n~g~Um eine Bombe aufzunehmen, steuere den Helikopter direkt über sie. Der Helikopter kann immer nur eine Bombe tragen.\n\n[TEX3_12:SERG3]\n~g~Bombe platziert! Es bleiben nur noch 3 Ziele! Hol die nãchste Bombe.\n\n[TEX3_13:SERG3]\n~g~Bombe platziert! Es bleiben nur noch 2 Ziele! Hol die nãchste Bombe.\n\n[TEX3_14:SERG3]\n~g~Bombe platziert! Es bleibt nur noch 1 Ziel! Hol die nãchste Bombe.\n\n[TEX3_15:SERG3]\n~r~Zeitzünder aktiviert! ~g~ Du musst die ~w~4 Bomben ~g~in der verbleibenden Zeit platzieren.\n\n[TEX3_37:SERG3]\nZieh den ~h~ Rechten Analog-Stick zurück~w~, um die Rotorgeschwindigkeit zu erhöhen, der Helikopter ~h~ gewinnt dann an Höhe.\n\n[TEX3_38:SERG3] { reVC update }\n{Drück den ~h~ ~k~~VEHICLE_ACCELERATE~~w~, um die Rotorgeschwindigkeit zu verringern, der Helikopter ~h~ verliert dann an Höhe.}\nDrück den ~h~ Rechten Analog-Stick nach vorn~w~, um die Rotorgeschwindigkeit zu verringern, der Helikopter ~h~ verliert dann an Höhe.\n\n[TEX3_39:SERG3]\nUm eine Bombe abzuwerfen, drücke die ~h~~k~~VEHICLE_HANDBRAKE~~g~-Taste.\n\n[TEX3_40:SERG3]\nUm eine Bombe abzuwerfen, drücke die ~h~~k~~VEHICLE_HANDBRAKE~~w~-Taste.\n\n[TEX3_23:SERG3]\nMit ~h~~k~~VEHICLE_TURRETUP~~w~ und ~h~~k~~VEHICLE_TURRETDOWN~~w~ neigst du den Helikopter in die Richtung, in die du ihn steuern willst.\n\n{=================================== MISSION TABLE TAXI1 ===================================}\n\n[FARES:TAXI1]\nFAHRTEN:\n\n[TAXI1:TAXI1]\n~g~Besorg dir einen Fahrgast.\n\n[TSCORE2:TAXI1]\n$~1~\n\n[IN_ROW:TAXI1]\n~1~ SERIEN-Bonus! $~1~\n\n[TAXI3:TAXI1]\n~r~Dein Fahrgast ist entsetzt geflohen!\n\n[TAXI7:TAXI1]\n~r~Dein Wagen ist Schrott. Repariere ihn.\n\n[TAXI4:TAXI1]\nFahrt abgeschlossen!\n\n[TAXI5:TAXI1]\nSPEED BONUS!!\n\n[TAXI6:TAXI1]\nTaxi-Mission beendet\n\n[TAXIH1:TAXI1]\nHalte neben einem markierten Fußgãnger, um ihn einsteigen zu lassen, dann bringe ihn rechtzeitig an sein Fahrtziel.\n\n[FARE1:TAXI1]\n~g~Fahrtziel ~w~'Pole Position Club' ~g~in Ocean Beach.\n\n[FARE3:TAXI1]\n~g~Fahrtziel ~w~'Marina' ~g~in Ocean Beach.\n\n[FARE4:TAXI1]\n~g~Fahrtziel ~w~'Ammu-Nation' ~g~in Ocean Beach.\n\n[FARE5:TAXI1]\n~g~Fahrtziel ~w~'Eisenwarenladen' ~g~in Washington Beach.\n\n[FARE6:TAXI1]\n~g~Fahrtziel ~w~'North Point Einkaufszentrum' ~g~in Vice Point.\n\n[MFARE1:TAXI1]\n~g~Fahrtziel ~w~'Ammu-Nation' ~g~in Downtown.\n\n[MFARE2:TAXI1]\n~g~Fahrtziel ~w~'Terminal' ~g~im Escobar International Airport.\n\n[WFARE3:TAXI1]\n~g~Fahrtziel ~w~'Sunshine Autos' ~g~in Little Havana.\n\n[WFARE4:TAXI1]\n~g~Fahrtziel ~w~'Kaufman-Taxis' ~g~in Little Haiti.\n\n[WFARE5:TAXI1]\n~g~Fahrtziel ~w~'Eisenwarenladen' ~g~in Little Havana.\n\n[WFARE6:TAXI1]\n~g~Fahrtziel ~w~'Howlin Petes Bike Emporium' ~g~in Downtown.\n\n[FARE7:TAXI1]\n~g~Fahrtziel ~w~'die Juweliere' ~g~in Vice Point.\n\n[FARE8:TAXI1]\n~g~Fahrtziel ~w~'der Strand' ~g~in Ocean Beach.\n\n[FARE9:TAXI1]\n~g~Fahrtziel ~w~'der Strand' ~g~in Washington Beach.\n\n[FARE10:TAXI1]\n~g~Fahrtziel ~w~'der Strand' ~g~in Vice Point.\n\n[FARE11:TAXI1]\n~g~Fahrtziel ~w~'das Krankenhaus' ~g~in Ocean Beach.\n\n[FARE12:TAXI1]\n~g~Fahrtziel ~w~'das Krankenhaus' ~g~in Vice Point.\n\n[FARE13:TAXI1]\n~g~Fahrtziel ~w~'die Polizeistation' ~g~in Washington Beach.\n\n[FARE14:TAXI1]\n~g~Fahrtziel ~w~'die Polizeistation' ~g~in Vice Point.\n\n[FARE15:TAXI1]\n~g~Fahrtziel ~w~'die Pizzagaststãtte' ~g~in Vice Point.\n\n[WFARE7:TAXI1]\n~g~Fahrtziel ~w~'die Polizeistation' ~g~in Little Havana.\n\n[WFARE8:TAXI1]\n~g~Fahrtziel ~w~'die Polizeistation' ~g~in Downtown.\n\n[WFARE9:TAXI1]\n~g~Fahrtziel ~w~'das Krankenhaus' ~g~in Downtown.\n\n[WFARE10:TAXI1]\n~g~Fahrtziel ~w~'das Krankenhaus' ~g~in Little Havana.\n\n[WFARE11:TAXI1]\n~g~Fahrtziel ~w~'der Stadium' ~g~in Downtown.\n\n[WFARE12:TAXI1]\n~g~Fahrtziel ~w~'die Pizzagaststãtte' ~g~in Little Haiti.\n\n[WFARE13:TAXI1]\n~g~Fahrtziel ~w~'die Pizzagaststãtte' ~g~in Downtown.\n\n[WFARE14:TAXI1]\n~g~Fahrtziel ~w~'die Docks' ~g~in Viceport.\n\n[WFARE15:TAXI1]\n~g~Fahrtziel ~w~'die Apotheke' ~g~in Little Haiti.\n\n[FARE2:TAXI1]\n~g~Fahrtziel ~w~'Malibu Club' ~g~in Vice Point.\n\n{=================================== MISSION TABLE TAXICUT ===================================}\n\n[TAXC_A:TAXICUT]\nSchãtze, sie sind der neue Besitzer.\n\n[TAXC_B:TAXICUT]\nSind Sie 'n Mafioso? Oder vom Kartell? Sehen nicht aus wie ein Mexikaner.\n\n[TAXC_C:TAXICUT]\nEgal. Halten Sie schon endlich Ihre Predigt von wegen 'Jetzt wird alles anders',\n\n[TAXC_D:TAXICUT]\nbedrohen Sie ein paar von den Fahrern-\n\n[TAXC_E:TAXICUT]\naber nicht Ted, der ist gerade an der Leiste operiert.\n\n[TAXC_F:TAXICUT]\nTja, also, hier wird sich einiges ãndern, Lady.\n\n[TAXC_G:TAXICUT]\nAber nicht doch, Jungchen. Überlassen Sie das lieber mir -\n\n[TAXC_H:TAXICUT]\nIch mach das schon seit Jahren.\n\n[TAXC_I:TAXICUT]\nAlles mal herhören.\n\n[TAXC_J:TAXICUT]\nWir haben eine neue Geschãftsleitung, und es wird sich wieder mal einiges ãndern hier.\n\n[TAXC_K:TAXICUT]\nUnsere neue Geschãftsleitung, die-\n\n[TAXC_L:TAXICUT]\nVon welcher Gang sind Sie?\n\n[TAXC_M:TAXICUT]\nIch gehöre keiner Gang an.\n\n[TAXC_N:TAXICUT]\nUnd wie heißen Sie, junger Mann?\n\n[TAXC_O:TAXICUT]\nVercetti, Tommy Vercetti.\n\n[TAXC_P:TAXICUT]\nUnsere neue Geschãftsleitung, die Vercetti Gang,\n\n[TAXC_Q:TAXICUT]\nwird dafür sorgen, dass wir keinen Ãrger kriegen.\n\n[TAXC_R:TAXICUT]\nCapiche? Ende!\n\n[TAXC_S:TAXICUT]\nWie fanden Sie das 'Capiche'? Ich fand's gut.\n\n[TAXC_T:TAXICUT]\nAlso, so ist das immer gelaufen:\n\n[TAXC_U:TAXICUT]\nWir führen die Firma weiter wie gewohnt.\n\n[TAXC_V:TAXICUT]\nWenn die Konkurrenz Ãrger macht, gebt ihr ihnen eines auf die Mütze.\n\n[TAXC_W:TAXICUT]\nDann geben die uns eines auf die Mütze.\n\n[TAXC_X:TAXICUT]\nDann geben sie denen eines auf die Mütze.\n\n[TAXC_Y:TAXICUT]\nUnd so weiter, und so fort. Kapiert?\n\n[TAXC_Z:TAXICUT]\nÃh, ja, ich glaub schon.\n\n[TAXC_A1:TAXICUT]\nSchnappen Sie sich ein Taxi aus der Garage, wenn Sie Lust haben.\n\n{=================================== MISSION TABLE TAXIWA1 ===================================}\n\n[OUTTIME:TAXIWA1]\n~r~Zu langsam, Mann, zu langsam!\n\n[TAX1_1:TAXIWA1]\nOk, eine V.I.P. müsste von Starfish Island abgeholt werden. Jemand interessiert?\n\n[TAX1_2:TAXIWA1]\nTommy hier. Ich übernehme das.\n\n[TAX1_3:TAXIWA1]\nDas ist meine Fuhre. Hau ab!\n\n[TAX1_4:TAXIWA1]\nLos, los, steigen Sie ein. Schnell!\n\n[TAX1_5:TAXIWA1]\nOk, ok! Aber tun Sie mir nichts!\n\n[TAXW1_1:TAXIWA1]\n~g~Hol die V.I.P. auf Starfish Island ab.\n\n[TAXW1_2:TAXIWA1]\n~g~Hol die V.I.P. zurück! Schalte den anderen Wagen aus!\n\n[TAXW1_3:TAXIWA1]\n~r~Die V.I.P. ist Geschichte!\n\n[TAXW1_4:TAXIWA1]\n~r~Die V.I.P. wurde abgesetzt!\n\n[TAXW1_6:TAXIWA1]\n~g~Bring die V.I.P zum Flughafen!\n\n{=================================== MISSION TABLE TAXIWA2 ===================================}\n\n[TAX2_1:TAXIWA2]\nAn alle Wagen. Wir kriegen nirgends Fahrgãste. Was ist los mit euch?\n\n[TAX2_2:TAXIWA2]\nVC-Taxi ist dauernd schneller als wir. Die haben einfach zu viele Autos. Keine Chance.\n\n[TAX2_3:TAXIWA2]\nMr. Vercetti, wenn Sie zufãllig mithören: Sie müssen ein paar VC-Taxis ausschalten, sonst sind wir pleite!\n\n[TAXW2_1:TAXIWA2]\n~g~Schalte 3 Taxis der Konkurrenz aus!\n\n{=================================== MISSION TABLE TAXIWA3 ===================================}\n\n[TAX3_1:TAXIWA3]\nWagen 13, eine Miss Cortez möchte von Ihnen ganz persönlich in Downtown abgeholt werden.\n\n[TAX3_2:TAXIWA3]\nOk, verstanden. Wagen 13 Ende.\n\n[TAX3_3:TAXIWA3]\nHmmm, keine Spur von Mercedes...\n\n[TAXW3_3:TAXIWA3]\n~g~Schalte das Taxi des Anführers aus!\n\n[TAXW3_2:TAXIWA3]\n~g~Halte durch, bis die Zeit abgelaufen ist.\n\n[TAX_AS1:TAXIWA3]\nTAXIUNTERNEHMEN ERWORBEN\n\n[TAX_AS2:TAXIWA3]\n~g~Kaufman-Taxis generiert nun bis zu $~1~ Einkünfte. Hol dir das Geld regelmãßig ab.\n\n[TAX3_4:TAXIWA3]\nWird Zeit, dass der Schutzengel von Kaufman-Taxis eine vor den Latz kriegt!\n\n[TAX3_5:TAXIWA3]\nHey, Freundchen, dir zieh ich das Fell über die Ohren!\n\n{ reVC updates }\n{ new languages }\n[FEL_JAP]\nJAPANISCH\n\n[FEL_POL]\nPOLNISCH\n\n[FEL_RUS]\nRUSSISCH\n\n{ new display menus }\n[FET_GFX]\nGRAPHICS SETUP\n\n[FED_MIP]\nMIP MAPPING\n\n[FED_AAS]\nANTI ALIASING\n\n[FED_FIL]\nTEXTURE FILTERING\n\n[FED_BIL]\nBILINEAR\n\n[FED_TRL]\nTRILINEAR\n\n[FED_WND]\nWINDOWED\n\n[FED_FLS]\nFULLSCREEN\n\n[FEM_CSB]\nCUTSCENE BORDERS\n\n[FEM_SCF]\nSCREEN FORMAT\n\n[FEM_ISL]\nMAP MEMORY USAGE\n\n[FEM_LOW]\nLOW\n\n[FEM_MED]\nMEDIUM\n\n[FEM_HIG]\nHIGH\n\n[FEM_2PR]\nPS2 ALPHA TEST\n\n[FEC_FRC]\nFREE CAM\n\n{ Linux joy detection }\n[FEC_JOD]\nDETECT JOYSTICK\n\n[FEC_JPR]\nPress any key on the joystick of your choice that you want to use on the game, and it will be selected.\n\n[FEC_JDE]\nDetected joystick\n\n{ mission restart }\n[FET_RMS]\nMISSION WIEDERHOLEN\n\n[FESZ_RM]\nWIEDERHOLEN?\n\n[FED_VPL]\nVEHICLE PIPELINE\n\n[FED_PRM]\nPED RIM LIGHT\n\n[FED_RGL]\nROAD GLOSS\n\n[FED_CLF]\nCOLOUR FILTER\n\n[FED_WLM]\nWORLD LIGHTMAPS\n\n[FED_MBL]\nMOTION BLUR\n\n[FEM_SIM]\nSIMPLE\n\n[FEM_NRM]\nNORMAL\n\n[FEM_MOB]\nMOBILE\n\n[FED_MFX]\nMATFX\n\n[FED_NEO]\nNEO\n\n[FEM_PS2]\nPS2\n\n[FEM_XBX]\nXBOX\n\n[FEC_IVP]\nINVERT PAD VERTICALLY\n\n[FEM_NON]\nNONE\n\n[FEC_DS2]\nDUALSHOCK 2\n\n[FEC_DS3]\nDUALSHOCK 3\n\n[FEC_DS4]\nDUALSHOCK 4\n\n[FEC_360]\nXBOX 360 CONTROLLER\n\n[FEC_ONE]\nXBOX ONE CONTROLLER\n\n[FEC_TYP]\nGAMEPAD TYPE\n\n[FET_AGS]\nGAMEPAD SETTINGS\n\n[FEM_AUT] { aspect ratio related }\nAUTO\n\n[DUMMY]\nTHIS LABEL NEEDS TO BE HERE !!!\nAS THE LAST LABEL DOES NOT GET COMPILED"
  },
  {
    "path": "utils/gxt/italian.txt",
    "content": "﻿{\n    New strings are at the bottom of file.\n    Do not change the order of strings.\n    You can fix the typos of existing translation but please refrain from\n    unnecessary edits like rephasing because you think it suits better for your taste.\n}\n\n[IN_VEH]\n~g~Ehi! Torna nel veicolo!\n\n[HEY]\n~g~Non procedere da solo, stai insieme ai tuoi compagni!\n\n[HELP3]\nRicorda che puoi eseguire uno scatto solo per brevi tratti.\n\n[HELP4_D]\nSposta la ~h~levetta analogica destra~w~ verso l'alto per ~h~accelerare~w~.\n\n[HELP5_D]\nSposta la ~h~levetta analogica destra~w~ verso il basso per ~h~frenare~w~ o, se il veicolo è fermo, per inserire la ~h~retromarcia~w~.\n\n[HELP7_A]\nTieni premuto il ~h~~k~~PED_LOCK_TARGET~~w~ per ~h~mirare~w~ con il fucile di precisione.\n\n[HELP7_D]\nTieni premuto il ~h~~k~~PED_LOCK_TARGET~~w~ per ~h~mirare~w~ con il fucile di precisione.\n\n[HELP10]\nQuesta stella indica il tuo livello di sospetto.\n\n[HELP11]\nPiù stelle hai, maggiore è il tuo livello di sospetto.\n\n[HELP13]\nIn alcuni casi potresti dover utilizzare passaggi non segnati sul radar.\n\n[TIMER]\nQuesta è una missione a tempo: devi portarla a termine prima che il contatore raggiunga lo zero.\n\n[HORN]\n~g~Suona il clacson.\n\n[NOMONEY]\n~g~Ti servono più soldi!\n\n[REWARD]\nRICOMPENSA ~1~$\n\n[M_FAIL]\nMISSIONE FALLITA!\n\n[M_PASS]\nMISSIONE COMPLETATA! ~1~$\n\n[DEAD]\nMASSACRATO!\n\n[BUSTED]\nBECCATO!\n\n[WEATHE1]\nFORZA TEMPO SOLEGGIATO\n\n[WEATHE2]\nFORZA TEMPO MOLTO SOLEGGIATO\n\n[WEATHE3]\nFORZA TEMPO NUVOLOSO\n\n[WEATHE4]\nFORZA TEMPO PIOVOSO\n\n[WEATHE5]\nFORZA TEMPO NEBBIOSO\n\n[WEATHE6]\nTEMPO NORMALE\n\n[NUMBER]\n~1~\n\n[LOADCAR]\nCARICAMENTO VEICOLO... (PREMI L1 PER ANNULLARE)\n\n[CARSOFF]\nVeicoli disabilitati.\n\n[CARS_ON]\nVeicoli abilitati.\n\n[TEXTXYZ]\nScrittura coordinate sul file...\n\n[CHEATON]\nModalità trucchi attivata\n\n[CHEATOF]\nModalità trucchi disattivata\n\n[IMPORT1]\nEsci fuori e aspetta il tuo veicolo.\n\n[PAGEB11]\nLanciafiamme depositato nel nascondiglio\n\n[WANT_A]\nVerrai arrestato solo se hai un ~h~livello di sospetto~w~.\n\n[WANT_B]\nIl tuo ~h~livello di sospetto~w~ è rappresentato da una riga di stelle nell'angolo superiore destro dello schermo.\n\n[WANT_C]\nAdesso hai un ~h~livello di sospetto~w~ pari a uno...\n\n[WANT_D]\ndue...\n\n[WANT_E]\ntre...\n\n[WANT_F]\nMan mano che il tuo ~h~livello di sospetto~w~ aumenta, attirerai l'attenzione di forze dell'ordine sempre più potenti.\n\n[WANT_G]\nSe vieni ~h~'beccato'~w~, verrai portato alla più vicina stazione di polizia.\n\n[WANT_H]\nI poliziotti prenderanno tutte le tue armi e parte dei tuoi risparmi come bustarella.\n\n[WANT_I]\nQualsiasi missione stavi affrontando verrà considerata come fallita.\n\n[WANT_J]\nScoprirai alcuni modi per ridurre il tuo livello di sospetto procedendo nel gioco.\n\n[WANT_K]\nSe sei in un veicolo, i ~h~carozzieri~w~ potranno ~h~azzerare il tuo livello di sospetto~w~.\n\n[HEAL_B]\nQuando sei ~h~'massacrato'~w~, verrai trasportato al più vicino ospedale.\n\n[HEAL_C]\nPerderai tutte le tue armi e i dottori prenderanno parte dei tuoi risparmi per rimetterti in sesto.\n\n[HEAL_E]\nScoprirai alcuni modi per curarti o per proteggerti dagli attacchi procedendo nel gioco.\n\n[SAVE1]\nPassa attraverso la corona per ~h~salvare la partita~w~. Non puoi salvare durante una missione.\n\n[SAVE2]\nQualsiasi veicolo parcheggiato nel garage verrà salvato insieme alla partita.\n\n[AMMU]\nEntra in Ammu-Nation per comprare un'arma.\n\n[R_TIME]\nTEMPO DI GARA:\n\n[PROP_1]\nNon hai abbastanza soldi per comprare questa proprietà.\n\n[PROP_2]\nNon puoi comprare una proprietà mentre sei in missione.\n\n[IND_ZON]\nVice City Beach\n\n[COM_ZON]\nVice City Mainland\n\n[BEACH1]\nOcean Beach\n\n[BEACH2]\nWashington Beach\n\n[BEACH3]\nVice Point\n\n[GOLFC]\nLeaf Links\n\n[STARI]\nStarfish Island\n\n[DOCKS]\nPorto\n\n[HAVANA]\nLittle Havana\n\n[HAITI]\nLittle Haiti\n\n[PORNI]\nPrawn Island\n\n[DTOWN]\nDowntown\n\n[VICE_C]\nVice City\n\n[A_PORT]\nEscobar International\n\n[JUNKY]\nDiscarica\n\n[PISTOL]\nPistola\n\n[PYTHON]\n.357\n\n[UZI]\nUz-1\n\n[TEC9]\nTec 9\n\n[M4]\nM4\n\n[INGRAM]\nMac\n\n[MP5]\nMP\n\n[RUGER]\nKruger\n\n[SNIPE]\nFucile di precisione\n\n[GRENADE]\nGranate\n\n[SHOTGN1]\nFucile a pompa\n\n[SHOTGN2]\nS.P.A.S. 12\n\n[SHOTGN3]\nFucile a canne mozze\n\n[ARMOUR]\nGiubbotto antiproiettile\n\n[LASER]\n.308 Fucile di precisione\n\n[BASEBAT]\nMazza da baseball\n\n[HAMMER]\nMartello\n\n[SCREWD]\nCacciavite\n\n[CLEVER]\nMannaia\n\n[MACHETE]\nMacete\n\n[KNIFE]\nColtello\n\n[KATANA]\nKatana\n\n[CHAINSA]\nMotosega\n\n[G_COST]\n~1~$\n\n[CAR_1]\nAmbulanza\n\n[MALIBU]\nIl club Malibu\n\n[MANSION]\nVilla di Diaz\n\n[TMANS]\nChez Tommy\n\n[STRIP]\nIl club Pole Position\n\n[MALL1]\nNorth Point Mall\n\n[BANKINT]\nEl Banco Corrupto Grande\n\n[RANGE]\nPoligono di tiro\n\n[POL_HQ]\nPolizia di VC\n\n[INT_B]\nUn vecchio amico\n\n[INTB_1]\n~g~Vai all'ufficio degli avvocati.\n\n[LAW_1]\nIl party\n\n[LAW_2]\nRissa nel vicolo\n\n[LAW_3]\nFuria sulla giuria\n\n[LAW_4]\nSommossa\n\n[COL_1]\nFottuto traditore\n\n[COL_2]\nSparatoria al Mall\n\n[COL_3]\nAngeli custodi\n\n[COL_4]\nSissignore, signore!\n\n[COL_5]\nTutti sul ponte!\n\n[COK_1]\nL'inseguimento\n\n[COK_2]\nPhnom Penh '86\n\n[COK_3]\nLa barca più veloce\n\n[COK_4]\nDomanda e offerta\n\n[KENT_1]\nIl braccio della morte\n\n[ASS_1]\nEliminazione\n\n[BUD_1]\nEstorsione\n\n[BUD_2]\nRissa al bar\n\n[BUD_3]\nCop Land\n\n[CAP_1]\nFuori l'esattore\n\n[FIN_1]\nTieniti stretto gli amici...\n\n[BANK_1]\nSenza via di fuga?\n\n[BANK_2]\nIl tiratore\n\n[BANK_3]\nL'autista\n\n[BANK_4]\nLa rapina\n\n[CNT_1]\nSfornare verdoni\n\n[CNT_2]\nColpire il corriere\n\n[PORN_1]\nGiro di reclutamento\n\n[PORN_2]\nIl dodo del dildo\n\n[PORN_3]\nLa foto di Martha\n\n[PORN_4]\nRiflettori sul punto G\n\n[TAX_1]\nTaxi di Kaufman\n\n[TAXI_1]\nVIP\n\n[TAXI_2]\nRivalità amichevole\n\n[TAXI_3]\nCabmaggedon\n\n[ICE_1]\nDistribuzione\n\n[TEX_1]\nFerro quattro\n\n[TEX_2]\nDue in un colpo\n\n[TEX_3]\nIl demolitore\n\n[PHIL_1]\nCorriere delle armi\n\n[PHIL_2]\nBroda e Saigon\n\n[BIKE_1]\nDue ruote d'acciaio\n\n[BIKE_2]\nBollire la pentola\n\n[BIKE_3]\nValla a prendere!\n\n[ROCK_1]\nIl succo dell'amore\n\n[ROCK_2]\nKiller psicotico\n\n[ROCK_3]\nGiro pubblicitario\n\n[ROCK_4]\nLove Fist!\n\n[HAT_1]\nLe polveri della zia\n\n[HAT_2]\nBombardamento!\n\n[HAT_3]\nTutto di nascosto\n\n[CUB_1]\nGara sull'acqua\n\n[CUB_2]\nCarne da cannone\n\n[CUB_3]\nBattaglia navale\n\n[CUB_4]\nVoodoo a doppio taglio\n\n[JOB_1]\nMorte per strada\n\n[JOB_2]\nElimina la moglie\n\n[JOB_3]\nIncidente...\n\n[JOB_4]\nL'ultima partenza\n\n[JOB_5]\nRisoluzione\n\n[ANSWER]\nPremi il ~h~~k~~PED_ANSWER_PHONE~~w~ per rispondere al cellulare.\n\n[MOB_01A]\nCiao vecchio mio! Sono Paul. Potrei avere delle informazioni per te, ma ti voglio parlare in privato.\n\n[MOB_01B]\nMi sto godendo un aperitivo al Malibu.\n\n[MOB_01C]\nCredo che mi dovrai un favore o due dopo questo, carino. Ci vediamo dopo.\n\n[MOB_02A]\nSsssnniiiiffffff! Ehi! Tommy? Ciao, Tommy!\n\n[MOB_02B]\nCi sono dei problemi alla stamperia. Faresti meglio ad andare a controllare.\n\n[MOB_02C]\nUn qualche tipo di casino. C'è qualcosa che non va. Devo andare.\n\n[MOB_03A]\nMr. Vercetti? Ho qui davanti a me un pezzo di carta che afferma\n\n[MOB_03B]\nche lei si è preso carico dei debiti di BJ's Auto.\n\n[MOB_03C]\nCon l'improvvisa scomparsa di BJ, non ho altra scelta\n\n[MOB_03D]\nche ritenerla responsabile delle sue debolezze finanziarie.\n\n[MOB_03E]\nFinché questo debito non sarà ripagato,\n\n[MOB_03F]\ndovrà considerare le strade di Vice City non molto amichevoli.\n\n[MOB_04A]\nCome butta, amico?\n\n[MOB_04B]\nAscolta Tommy, mi sono dimenticato di dirti che avremo bisogno di qualche gorilla extra per il concerto.\n\n[MOB_04C]\nC'è una banda di motociclisti e sarebbero una perfetta pubblicità.\n\n[MOB_04D]\nOccupatene tu e ti farò accedere al back stage dello spettacolo, OK?\n\n[MOB_05A]\nEhi, sono Mitch! Ottimo lavoro, Tommy: è bello riavere indietro la mia vecchia bambina.\n\n[MOB_05B]\nDì a Mr. Kent Paul che avrà la sorveglianza per lo spettacolo.\n\n[MOB_05C]\nHai la mia parola.\n\n[MOB_05D]\nAdesso tieniti fuori dai guai.\n\n[MOB_06A]\nTommy, si è parlato molto di te, ragazzo.\n\n[MOB_06B]\nPensavo ti servisse un po' di calore, per cui la zia Poulet ti ha preparato una bella zuppa, hmmm?\n\n[MOB_06C]\nPassa a trovarmi in cucina ogni tanto, OK Tommy?\n\n[MOB_08A]\nEhi, Tommy, ho pensato che ti potessero servire dei consigli.\n\n[MOB_08B]\nQuando hai un'operazione in corso, dovrai passare a ritirare i soldi della settimana.\n\n[MOB_08C]\nLascia pensare ai ragazzi che abbiano il controllo del posto e loro cercheranno di ridurne i profitti, OK?\n\n[MOB_08D]\nEhi Ken, so come far funzionare le cose, OK.\n\n[MOB_08E]\nOK, OK! Lo so che lo sai. Lo so. Stavo solo...\n\n[MOB_08F]\nTi stavo solo ricordando che lo so, cioè che tu sai che io so.\n\n[MOB_08G]\nSolo per ricordartelo!\n\n[MOB_08H]\nSì Ken, va bene...\n\n[MOB_09A]\nEhi Leo! Ho del lavoro per te!\n\n[MOB_09B]\nNon sono Leo!\n\n[MOB_09C]\nEhi, se Leo scopre che hai il suo telefono, ti farà a pezzi!\n\n[MOB_09D]\nForse Leo è già morto. Forse ho ucciso Leo e ho preso il suo telefono: non ci hai pensato, idiota?\n\n[MOB_09E]\nHai ucciso Leo? Devi avere due grandi cojones. Vuoi lavorare per me?\n\n[MOB_09F]\nPassa dal bar di mio padre a Little Havana e ne possiamo parlare.\n\n[MOB_10A]\nTommy! Senti, devo chiederti un favore.\n\n[MOB_10B]\nSteve! Come va il film?\n\n[MOB_10C]\nBene, bene. Senti ho, ehm, abbiamo bisogno di una scena di inseguimento, ma siamo a corto di denaro.\n\n[MOB_10D]\nHo lasciato qualche macchina in città. Sono certo che sai cosa fare.\n\n[MOB_10E]\nOK Steve, terrò un occhio aperto. Ci vediamo!\n\n[MOB_11A]\nCiao figliolo, t'ho chiamato per darti un consiglio.\n\n[MOB_11B]\nCiao Avery. Come butta?\n\n[MOB_11C]\nCi sono un sacco di opportunità in questa città se possiedi le proprietà giuste, mi segui?\n\n[MOB_11D]\nTutto chiaro...\n\n[MOB_11E]\nVolevo dirti di tenere gli occhi aperti: potresti trovare l'occasione giusta per far soldi. Ci becchiamo!\n\n[MOB_11F]\nCiao, Avery.\n\n[MOB12_A]\nEhi Tommy! Sono Avery! Ascolta: sono piuttosto incasinato al momento\n\n[MOB12_B]\ne un mio rappresentante ha bisogno di un accompagnatore fino a Gator Keys.\n\n[MOB12_C]\nSto cercando di acquistare del terreno da quelle parti, per cui mando qualcuno in avanscoperta.\n\n[MOB12_D]\nMi faresti un favore? Potresti controllare che arrivi a destinazione tutto intero?\n\n[MOB12_E]\nCerto, nessun problema Avery. Dove vuoi che lo passi a prendere?\n\n[MOB12_F]\nSta finendo un lavoro presso il cantiere. Gli ho detto che saresti passato lì.\n\n[MOB12_G]\nNessun problema. Ci vediamo, Avery.\n\n[MOB13_A]\nVercetti? VERCETTI!!! Maledizione, mi devi aiutare!\n\n[MOB13_B]\nMr. Moffat? Come sta la famiglia?\n\n[MOB13_C]\nBrutto maledetto, BASTARDO! Mi hai sentito?\n\n[MOB13_D]\nBeh, è stato un piacere chiacchierare...\n\n[MOB13_E]\nASPETTA! Aspetta Vercetti... Tommy, posso chiamarti Tommy?\n\n[MOB13_F]\nSiamo entrambi professionisti, vero? Sono certo che sai riconoscere un affare, vero?\n\n[MOB13_G]\nNon ho tempo da perdere, arriva al punto.\n\n[MOB13_H]\nSOLDI. I soldi sono il punto!\n\n[MOB13_I]\nSono fuggito nuovamente da quei maledetti, ma non ci metteranno molto a trovarmi... Pensano si tratti di uno stupido gioco!\n\n[MOB13_J]\nSono a un telefono pubblico da qualche parte in questo posto di merda.\n\n[MOB13_K]\nAiutami a scappare prima che mi prendano e... e... oddio...\n\n[MOB13_L]\nBeh, sono impegnato per i prossimi...\n\n[MOB13_M]\nNo! Non fare lo stronzo con me, abbi cuore! Nessuno dovrebbe fare una... una cosa simile!\n\n[MOB13_N]\nSono in ginocchio, Tommy: nella polvere a chiederti pietà...\n\n[MOB13_O]\nBeh, forse potrei passare da quelle parti, vediamo se riesco a trovarti...\n\n[MOB13_P]\nOddio, stanno arrivando! Ti supplico, muoviti, muoviti!\n\n[MOB_14A]\nEhi, ciao Tommy: vedrai che mi adorerai!\n\n[MOB_14B]\nUn piccolo uccellino mi ha detto che la divisione SWAT di Vice City ha un deposito presso un'importante banca,\n\n[MOB_14C]\ndove tengono tutte le bustarelle intascate nel corso degli anni,\n\n[MOB_14D]\nun po' come una pensione per gli anni a venire.\n\n[MOB_14E]\nLogicamente, se questa informazione dovesse aiutarti a ottenere i soldi,\n\n[MOB_14F]\nimmagino che ti sentiresti obbligato a passarmene una parte...\n\n[MOB_14G]\nMe lo ricorderò, grazie Kent.\n\n[MOB_14H]\nSono Paul. Vengo dal Kent, vicino a Londra, cretino.\n\n[MOB_14I]\nLe mie conoscenze di geografia non sono mai state un gran che.\n\n[MOB15_A]\nTommy, amico, sono Paul, dal Kent,\n\n[MOB15_B]\nun paio di squinzie hanno il tuo nome scritto dappertutto giù al Malibu.\n\n[MOB15_C]\nDi cosa stai parlando?\n\n[MOB15_D]\nSquinzie. Passere. Chiaro no? Strafighe. E anche ben messe, non credo fossero mignotte...\n\n[MOB15_E]\nDovresti venire a dare un'occhiata.\n\n[MOB16_A]\nTommy, sono Paulo, que pasa amigo?\n\n[MOB16_B]\nChe cosa vuoi Paul: non sono interessato a vestiti di marca taroccati.\n\n[MOB16_C]\nMolto divertente, amico, ma lo sai che non tratto merce di seconda classe.\n\n[MOB16_D]\nNah, ti ho chiamato per sapere se potevo avere una parte nei tuoi film,\n\n[MOB16_E]\nquando ero in Inghilterra ho fatto un sacco di cose, sai?\n\n[MOB16_F]\nHo attributi più forniti di te, amico.\n\n[MOB16_G]\nPaul, grazie per l'offerta, lo terrò presente.\n\n[MOB16_H]\nDavvero, non scordarti di me dopo tutto quello che ho fatto per te.\n\n[MOB16_I]\nÈ proprio ciò che sto cercando di dimenticare...\n\n[MOB17_A]\nTommy Vercetti: come va, Mr. Pezzo Grosso?\n\n[MOB17_B]\nHo saputo le tue novità: un vero giocatore in città, eh...\n\n[MOB17_C]\nPaul, sei ubriaco.\n\n[MOB17_D]\nNo, idiota. Non sono ubriaco.\n\n[MOB17_E]\nSolo un paio di bicchierini e qualche pillola: non dormo da un paio di giorni, sai...\n\n[MOB17_F]\nComunque, niente prediche.\n\n[MOB17_G]\nNon sono uno stupido. Chi ti ha portato in questa città? Chi? Io, ecco chi.\n\n[MOB17_H]\nDavvero?\n\n[MOB17_I]\nDavvero!\n\n[MOB17_J]\nPaul, sta' buono. Sono stato occupato, non fare l'idiota.\n\n[MOB17_K]\nNon sono un idiota, chiaro? Questo è ciò che hanno detto in riformatorio.\n\n[MOB17_L]\nStai forse cercando guai, amico? Beh, stai per trovarli!\n\n[MOB17_M]\nTommy, amico. Per favore. Sei la mia più grande speranza! Per favore, non ridere di me.\n\n[MOB17_N]\nPaul, cerca di dormire, davvero.\n\n[MOB18_A]\nTommy, sono Paulo, come butta? Bene amico, comunque, volevo farti una chiamata.\n\n[MOB18_B]\nOssignore, amico, non crederai mai che razza di strafiga ho appena incontrato.\n\n[MOB18_C]\nNon so esattamente chi fosse, ma passeggiava per Little Havana.\n\n[MOB18_D]\nHa detto che si chiamava Mercedes o qualcosa del genere. Oddio, dovresti proprio vedere questa gnocca.\n\n[MOB18_E]\nRiuscirebbe a succhiare via la mina da una matita. Mi ha detto che ero il migliore che avesse mai avuto e via dicendo.\n\n[MOB18_F]\nDovresti farci un giro. Ci vediamo!\n\n[MOB19_A]\nTommy V, sono KP. Kent Paul. Gira voce che ti vogliano fare a pezzi.\n\n[MOB19_B]\nTieni gli occhi bene aperti, amico e ricorda: io non ti ho detto niente al riguardo.\n\n[MOB_20A]\nEhi Tommy, sono Paul. Ho appena sentito che sei stato un ragazzaccio cattivo.\n\n[MOB_20B]\nQualcuno si è offeso per il tuo comportamento da grand'uomo, e adesso è davvero arrabbiato.\n\n[MOB_20C]\nBeh, non dire che non ti ho avvertito: vantarsi è un gioco pericoloso, amico.\n\n[MOB_20D]\nComunque, ho anche sentito che c'è una taglia sulla tua testa e che qualcuno ti ha già preso di mira,\n\n[MOB_20E]\nper cui guardati la schiena e ricordati di me, amico.\n\n[MOB71_A]\nTommy, Tommy, sono Cortez. Que pasa?\n\n[MOB71_B]\nLa situazione è interessante. A lei come va?\n\n[MOB71_C]\nTommy, qui è sempre una battaglia. Scusami per la battuta scontata, ma abbiamo sventato un altro golpe.\n\n[MOB71_D]\nLa gente non smette mai di pretendere di più.\n\n[MOB71_E]\nDa quando sono tornato da Vice City, abbiamo avuto tre rivoluzioni e quattro golpe falliti.\n\n[MOB71_F]\nFortunatamente, sono stato promosso ogni volta.\n\n[MOB71_G]\nTi volevo chiedere di Mercedes.\n\n[MOB71_H]\nSì? Cosa vuole sapere?\n\n[MOB71_I]\nOh Tommy, ho sentito tutte queste storie e non so cosa pensare.\n\n[MOB71_J]\nForse tutti si divertono a umiliarmi.\n\n[MOB71_K]\nForse pensa di poter fare ciò che vuole ma dimmi, Tommy: è tutto vero?\n\n[MOB71_L]\nma dimmi, Tommy: è tutto vero?\n\n[MOB71_M]\nChe cosa?\n\n[MOB71_N]\nLe storie che ho sentito: sta pensando davvero di diventare avvocato?\n\n[MOB71_O]\nOh Tommy, che vergogna. Noi Cortez siamo una famiglia all'antica e non permetteremo mai che una di noi diventasse avvocato.\n\n[MOB71_P]\nTi prego, dimmi che non è vero. Non credo resisterei al colpo.\n\n[MOB71_Q]\nColonnello, le assicuro che Mercedes non diventerà mai un avvocato. Non si preoccupi.\n\n[MOB71_R]\nGrazie Tommy, la vergogna sarebbe schiacciante. Lei è una vera dama, non una parassita, capisci?\n\n[MOB71_S]\nCapisco, Colonnello.\n\n[MOB71_T]\nComunque, Tommy, devi scusarmi: è appena arrivato il nuovo ministro degli interni.\n\n[MOB71_U]\nQualche anno fa, ho ucciso suo padre in un golpe fallito, per cui devo essere gentile. Buona giornata, amico.\n\n[MOB22_A]\nTommy, ti stai rivelando molto utile, amico.\n\n[MOB22_B]\nGrazie, Cortez. Cosa mi dice del nostro accordo?\n\n[MOB22_C]\nTommy, sto lavorando senza sosta nel tentativo di raggiungere il fondo di questa fossa piena di bugie e inganni,\n\n[MOB22_D]\nhai la mia parola al riguardo, ma nel frattempo,\n\n[MOB22_E]\nti prego di accettare i più sinceri ringraziamenti da parte della gente per cui stai lavorando.\n\n[MOB_25A]\nTommy, sono Cortez. I Francesi mi stanno causando tutti i problemi possibili.\n\n[MOB_25B]\nMaledetti ipocriti. Hanno passato secoli a derubare la povera gente e adesso osano chiamare me ladro!\n\n[MOB_25C]\nAvrò bisogno del tuo aiuto il prima possibile.\n\n[MOB_25D]\nSbrigati, Tommy: ho bisogno di te. Odio questi dannati Francesi.\n\n[MOB_26A]\nEhi, Tommy?\n\n[MOB_26B]\nSì?\n\n[MOB_26C]\nSono Baker. Volevo dirti che ho davvero apprezzato lo show.\n\n[MOB_26D]\nIo e i ragazzi vogliamo ringraziarti e ricordarti\n\n[MOB_26E]\nche hai tutto il nostro rispetto. Buona giornata, continua così.\n\n[MOB_29A]\nSalve, parlo con Mr. Tommy Vercetti?\n\n[MOB_29B]\nSì.\n\n[MOB_29C]\nBeh, ho sentito dire che sei tu l'uomo da chiamare in caso di infestazione da parassiti.\n\n[MOB_29D]\nForse...\n\n[MOB_29E]\nBeh, ho in corso un'infestazione davvero pesante: Haitiani da tutte le parti.\n\n[MOB_29F]\nMi chiamo Umberto Robina e vorrei incontrarmi con te al Cafe Robina il prima possibile,\n\n[MOB_29G]\nperché questa volta i fottuti Haitiani sono andati troppo oltre.\n\n[MOB_29H]\nTest\n\n[MOB_30A]\nTommy, sono Umberto Robina.\n\n[MOB_30B]\nCome va al caffè?\n\n[MOB_30C]\nOh, meraviglioso. Incredibile, Tommy, incredibile. Niente perdenti, Tommy, solo veri uomini, sai no, e donne stupende.\n\n[MOB_30D]\nComunque, volevo dirti che per tutti noi adesso sei un vero Cubano.\n\n[MOB_30E]\nHai provato di essere all'altezza. Hai provato di avere due grandi cojones.\n\n[MOB_30F]\nErr... grazie, Umberto. Nessuno mi ha detto una cosa simile da quando ho lasciato la galera. Ci becchiamo in giro.\n\n[MOB_33A]\nTommy, sono Phil: smettila di perdere tempo con le vaccate e ascoltami, intesi?\n\n[MOB_33B]\nBene. Ho un bel po' di broda bella forte quasi a perfetta fermentazione e mi chiedevo se ne volevi assaggiare un po'.\n\n[MOB_33C]\nTi assicuro, Tommy, che se ami bere, o se devi rimuovere della vernice, questa è la roba che fa per te.\n\n[MOB_33D]\nPer me è stata una bomba, anche se non ci vedo più bene da un occhio. Ti aspetto, ciao.\n\n[MOB_34A]\nTommy, mi è davvero piaciuto lavorare con te. Non mi divertivo così dalle scorrerie in Vietnam, amico.\n\n[MOB_34B]\nSe mai ti servisse qualcosa, chiamami, capito?\n\n[MOB_34C]\nRicordo sempre quelli coi quali ho prestato servizio,\n\n[MOB_34D]\ne sono sicuro di poterti dare una mano, chiaro?\n\n[MOB_35A]\nTommy, la ferita si sta rimarginando bene. È divertente:\n\n[MOB_35B]\nho combattuti in sei campi di battaglia e sono sempre uscito senza un graffio... e adesso questo!\n\n[MOB_35C]\nPhil senza un braccio. Comunque, ho una abbondante selezione di armi a una mano, per cui almeno non sarò disarmato!\n\n[MOB_35D]\nComunque, figliolo, lasciamo stare le stronzate sentimentali e vedi di scolarti qualcosa da parte mia!\n\n[MOB_36A]\nTommy, sono Phil. Ti volevo ringraziare di essere stato sul campo, figliolo.\n\n[MOB_36B]\nMaledetti Viet, non perdono occasione per farti un attentato...\n\n[MOB_36C]\nComunque, la ferita sta guarendo: adesso non mi sentirò più in colpa quando riceverò il mio consueto assegno per disabili. Grazie, amico.\n\n[MOB_40A]\nEhi, Tommy, sono Sonny. Come va l'abbronzatura?\n\n[MOB_40B]\nNon ho preso il sole.\n\n[MOB_40C]\nBeh, non hai preso neanche i miei soldi, per cui mi chiedevo:\n\n[MOB_40D]\nche cosa stai combinando? Dimmi un po', Tommy, che cosa fai?\n\n[MOB_40E]\nSto cercando i soldi, Sonny, non ti preoccupare.\n\n[MOB_40F]\nInvece mi preoccupo, Tommy, è il mio stile,\n\n[MOB_40G]\npoiché ho sempre dei problemi con gente che non ama rispettare i patti.\n\n[MOB_40H]\nNon diventare inaffidabile, Tommy, fallo per me...\n\n[MOB_40I]\nFai un favore a entrambi. Non vedo l'ora di ricevere buone nuove.\n\n[MOB_41A]\nTommy, ti ricordi di me?\n\n[MOB_41B]\nEhi, Sonny.\n\n[MOB_41C]\nSì, sono proprio io, Sonny. Siamo vecchi amici,\n\n[MOB_41D]\ne tu non mi scrivi mai, non mi chiami mai. Non vuoi più essere mio amico?\n\n[MOB_41E]\nSono stato occupato a mettere le cose a posto. Non mi hai dato un gran che di aiuto da queste parti.\n\n[MOB_41F]\nAh, è questa la mia colpa? Beh, ho sentito che sei stato molto occupato.\n\n[MOB_41G]\nOccupato a uccidere i baroni della droga. Occupato a prendere il potere.\n\n[MOB_41H]\nNon dimenticarti di noi, Tommy, poiché, te lo assicuro, io non mi sono dimenticato di te.\n\n[MOB_42A]\nTommy.\n\n[MOB_42B]\nSonny.\n\n[MOB_42C]\nHai di sicuro dei problemi di udito, per cui proverò ancora...\n\n[MOB_42D]\nTommy, dove sono i maledetti soldi, dov'è la maledetta roba e dov'è la mia parte dei tuoi ultimi guadagni?\n\n[MOB_42E]\nTommy, mi stai facendo fare la figura dell'idiota, e io non sto ridendo.\n\n[MOB_43A]\nTommy, Tommy, Tommy, avevo Sonny al telefono... OK, sei con me?\n\n[MOB_43B]\nNon so te, ma so che qualcuno sta minacciando di morte la mia famiglia,\n\n[MOB_43C]\nil che mi sta davvero facendo cagare sotto. Che cosa intendi fare?\n\n[MOB_43D]\nStai calmo, Ken, andrà tutto bene.\n\n[MOB_43E]\nIo SONO calmo, calmo quanto un uomo in pericolo di vita!\n\n[MOB_43F]\nKen, ora come ora ho altre cose per la testa,\n\n[MOB_43G]\nci occuperemo di Forelli al momento giusto.\n\n[MOB_43H]\nIo sono calmo. Non ti sembro calmo? Forse è la morte incombente che mi sta facendo tremare la voce.\n\n[MOB45_A]\nTommy, dobbiamo parlare di un po' di cose.\n\n[MOB45_B]\nC'è qualche problema, Lance?\n\n[MOB45_C]\nSi tratta di te, amico, non mi sembra di ricevere la fetta che merito.\n\n[MOB45_D]\nE inoltre, mi hai imbarazzato davanti ai ragazzi. Non lo posso permettere.\n\n[MOB45_E]\nLance, non è andata così. Hai commesso degli errori.\n\n[MOB45_F]\nTommy, non sono il tuo fattorino. Non sono un tuo scagnozzo.\n\n[MOB45_G]\nLance, non fare casini e non avremo alcun problema. Se faccio un errore, me la puoi far pagare in qualsiasi momento.\n\n[MOB45_H]\nTommy, ho fatto tutto per te e mi tratti come un idiota. Non farlo.\n\n[MOB45_I]\nLance, non ti causerò problemi e non ti pugnalerò alle spalle, promesso.\n\n[MOB45_J]\nRilassati. La cosa è già abbastanza difficile senza che tu ti metta a fare il tenero con me.\n\n[MOB45_K]\nFidati: mi hai sentito, mi hai sentito?\n\n[MOB45_L]\nTi ho sentito, ma Tommy, non sopporterò ancora per lungo.\n\n[MOB45_M]\nLance, non fare così: adesso sono io ad avvertirti.\n\n[MOB45_N]\nMi hai sentito? Rilassati, prenditi qualche giorno e poi ne riparliamo, OK?\n\n[MOB46_A]\nTommy, sono Lance.\n\n[MOB46_B]\nSì?\n\n[MOB46_C]\nSono felice di sentirti Lance. Forza, stai tranquillo, stai tranquillo.\n\n[MOB46_D]\nSono nel mezzo di un problema: ho bisogno di te.\n\n[MOB46_E]\nNiente, giusto per dire. Tommy, ce ne possiamo occupare.\n\n[MOB46_F]\nIo e te, nessun problema. Capisci ciò che intendo?\n\n[MOB46_G]\nDobbiamo proprio farlo, se no siamo entrambi morti, Lance.\n\n[MOB46_H]\nSiamo andati troppo oltre, ma grazie della chiamata. Ci sentiamo più tardi.\n\n[MOB_47A]\nTommy, sono Lance. Abbiamo un problema serio. Vieni qui in fretta.\n\n[MOB52_A]\nEhi, Leo, sembra ci sia un compratore per la roba di Diaz.\n\n[MOB52_B]\nDevi fargli uno squillo, ragazzo, e preparare l'accordo, chiaro?\n\n[MOB52_C]\nDove ti trovi adesso?\n\n[MOB52_D]\nStai bene Leo? Mi sembri un po' strano...\n\n[MOB52_E]\nDimmi dove ti trovi.\n\n[MOB52_F]\nChi diavolo sei? Passami subito Leo!\n\n[MOB52_G]\nLeo se ne è andato per un po' e adesso sono io in carica.\n\n[MOB52_H]\nFottiti, stronzo!\n\n[MOB54_A]\nCiao Tommy!\n\n[MOB54_B]\nCiao Mercedes, come butta?\n\n[MOB54_C]\nHo un nuovo appartamento in Vice Point...\n\n[MOB54_D]\nmagari un giorno di questi potresti farci un salto.\n\n[MOB54_E]\nMi piacerebbe, ci sentiamo.\n\n[MOB55_A]\nTommy, sono io.\n\n[MOB55_B]\nCiao Mercedes.\n\n[MOB55_C]\nTommy, sono così annoiata: perché non ci divertiamo un po' insieme?\n\n[MOB55_D]\nCosa intendi dire?\n\n[MOB55_E]\nBeh, lo so che sei occupato a combattere, uccidere e corrompere gente,\n\n[MOB55_F]\nma io ho voglia di divertirmi un po'. Non ti scordare di me, capito?\n\n[MOB56_A]\nTommy, ho sentito che hai ucciso Ricardo Diaz.\n\n[MOB56_B]\nC'è stato uno sfortunato incendio nella sua villa.\n\n[MOB56_C]\nCredo sia morto bruciato nella sua camicia in acrilico.\n\n[MOB56_D]\nTommy, sono così fiera di te. Lo sapevo che eri un vero uomo.\n\n[MOB56_E]\nEra un inutile idiota senza testa: mi rendi orgogliosa di essere tua amica.\n\n[MOB56_F]\nNo, lo so che sei impegnato a prendere il possesso di questa città,\n\n[MOB56_G]\nma non dimenticarti di me, capito?\n\n[MOB57_A]\nSono Mercedes. Non ti amo più, Tommy.\n\n[MOB57_B]\nProprio no, onestamente. Tu non sei più gentile con la tua Mercedes.\n\n[MOB57_C]\nNon mi tratti più come una signora: mi ignori e io ti odio.\n\n[MOB57_D]\nInsisto che tu venga a trovarmi immediatamente!\n\n[MOB58_A]\nTommy.\n\n[MOB58_B]\nEhi Mercedes.\n\n[MOB58_C]\nEhi sì, Mr. Tipo Duro. Sono davvero arrabbiata con te, Tommy.\n\n[MOB58_D]\nNon farmi più passare le serate con Jezz Torrent.\n\n[MOB58_E]\nÈ davvero patetico. A metà delle scale ha iniziato a piagnucolare per il suo cane\n\n[MOB58_F]\nche è morto quando aveva sette anni e a ripetere che la mamma non lo ha mai amato.\n\n[MOB58_G]\nE Tommy, indossa una parrucca e un reggiseno quando è in intimità.\n\n[MOB58_H]\nNon sono molto felice di te!\n\n[MOB59_A]\nOoh Tommy, sono Mercedes.\n\n[MOB59_B]\nVolevo solo dirti che mi sono divertita così tanto sul set del film.\n\n[MOB59_C]\nSe hai qualcos'altro del genere, fammelo sapere.\n\n[MOB59_D]\nLo penso davvero. Ho sempre desiderato fare l'attrice.\n\n[MOB59_E]\nCredo di aver imparato molto sull'approccio drammatico.\n\n[MOB59_F]\nÈ così illuminante! Grazie, grazie! Spero di vederti presto! Adios.\n\n[MOB_99]\nRaggiungi il telefono pubblico.\n\n[MOB_98]\nRaggiungi il telefono pubblico.\n\n[MOB_97]\nRaggiungi il telefono pubblico.\n\n[MOB_96]\nRaggiungi il telefono pubblico.\n\n[MOB_95]\nRaggiungi il telefono pubblico.\n\n[A_TIME]\n+~1~ secondi\n\n[F_RANGE]\n~g~Sei fuori dal raggio d'azione della radio. Avvicinati alla stazione dei pompieri!\n\n[DODO_FT]\nHai volato per ~1~ secondi!\n\n[GA_8]\nUsa il detonatore per attivare la bomba.\n\n[GA_10]\nNon male. Eccoti ~1~$\n\n[GA_11]\nNe abbiamo già una. A noi non serve!\n\n[GA_12]\nBomba innescata\n\n[GA_13]\nUn furto da manuale. Completa la lista e ci sarà un bonus per te.\n\n[GA_14]\nHai portato tutte le macchine. BENE! Eccoti un bonus...\n\n[GA_15]\nSpero che ti piaccia il nuovo colore.\n\n[GA_16]\nLa riverniciatura è gratuita.\n\n[GA_19]\nNon siamo interessati a questo modello.\n\n[GA_20]\nDi questo modello ne abbiamo in abbondanza. Mi dispiace, non siamo interessati.\n\n[CHASE]\nMassima attenzione dei media\n\n[CHASE1]\nIgnoto\n\n[CHASE2]\nNoioso\n\n[CHASE3]\nAppena interessante\n\n[CHASE4]\nGiornale locale, pagina 7\n\n[CHASE5]\nGiornale locale, prima pagina\n\n[CHASE6]\nVice Courier, 1 colonna\n\n[CHASE7]\nVice Courier, prima pagina\n\n[CHASE8]\nTV locale, 3 AM\n\n[CHASE9]\nTV locale, news\n\n[CHASE10]\nTV locale, servizio in diretta\n\n[CHASE11]\nUFA Today, pagina 12\n\n[CHASE12]\nUFA Today, pagina 4\n\n[CHASE13]\nFoto in UFA Today\n\n[CHASE14]\nTV nazionale, 4 AM\n\n[CHASE15]\nTV nazionale, news\n\n[CHASE16]\nTV nazionale, servizio in diretta\n\n[CHASE17]\nAvvenimento internazionale\n\n[CHASE18]\nCrisi nazionale\n\n[CHASE19]\nCrisi internazionale\n\n[CHASE20]\nEvento mondiale\n\n[CHASE21]\nRoba da leggenda\n\n[CR_1]\nLa gru non può alzare questo veicolo.\n\n[PU_MONY]\nNon hai abbastanza soldi.\n\n[CO_ALL]\nLi hai presi tutti. Eccoti un piccolo extra...\n\n[FEM_ON]\nON\n\n[FEM_OFF]\nOFF\n\n[FEM_YES]\nSì\n\n[FEM_NO]\nNo\n\n[FEM_RET]\nRiprova\n\n[FEC_NA]\nND\n\n[FEC_CWL]\nScorri armi a sinistra\n\n[FEC_CWR]\nScorri armi a destra\n\n[FEC_LOF]\nGuarda avanti\n\n[FEC_TAR]\nBersaglio\n\n[FEC_MOV]\nMovimento\n\n[FEC_CAM]\nModalità visuale\n\n[FEC_PAU]\nPausa\n\n[FEC_ENV]\nSali sul veicolo\n\n[FEC_JUM]\nSalta\n\n[FEC_ATT]\nAttacca o fuoco con arma\n\n[FEC_RUN]\nCorri\n\n[FEC_FPC]\nVisuale in prima persona\n\n[FEC_LL]\nGuarda a sinistra\n\n[FEC_LB]\nGuarda indietro\n\n[FEC_LR]\nGuarda a destra\n\n[FEC_HOR]\nClacson\n\n[FEC_VES]\nComandi veicolo\n\n[FEC_BRA]\nFreno o retromarcia\n\n[FEC_HAB]\nFreno a mano\n\n[FEC_CAW]\nArma vettura\n\n[FEC_ACC]\nAccelera\n\n[FEC_CCF]\nConfigurazione :\n\n[FEC_CF1]\nConfig 1\n\n[FEC_CF2]\nConfig 2\n\n[FEC_CF3]\nConfig 3\n\n[FEC_CF4]\nConfig 4\n\n[FEC_CDP]\nSchermata controller :\n\n[FEC_ONF]\nA piedi\n\n[FEC_INC]\nIn macchina\n\n[FEC_VIB]\nVibrazione :\n\n[FEL_ENG]\nInglese\n\n[FEL_FRE]\nFrancese\n\n[FEL_GER]\nTedesco\n\n[FEL_ITA]\nItaliano\n\n[FEL_SPA]\nSpagnolo\n\n[FED_DBG]\nMenu Debug\n\n[FED_RID]\nReload IDE\n\n[FED_RIP]\nReload IPL\n\n[FED_PAH]\nParse Heap\n\n[FED_DFL]\nCTheScripts::DbgFlag\n\n[FED_DLS]\nBig White Debug Light Switched\n\n[FED_SPR]\nShow Ped Road Groups\n\n[FED_SCR]\nShow Car Road Grups\n\n[FED_SCZ]\nShow Cull Zones\n\n[FED_DSR]\nDebug Streaming Requests\n\n[FED_SCP]\ngbShowCollisionPolys\n\n[PL_STAT]\nStatistiche giocatore\n\n[PE_WAST]\nPersone massacrate\n\n[PE_WSOT]\nPersone massacrate da altri\n\n[TM_BUST]\nArresti subiti\n\n[GNG_WST]\nMembri delle gang massacrati\n\n[DED_CRI]\nCriminali massacrati\n\n[PER_COM]\nPercentuale completata\n\n[KGS_EXP]\nKg di esplosivo utilizzati\n\n[ACCURA]\nPrecisione\n\n[ST_WEAP]\nBudget armi\n\n[ST_PROP]\nBudget proprietà\n\n[ST_AUTO]\nBudget riparazioni e colorazione auto\n\n[ST_PHOT]\nFotografie scattate\n\n[ST_LOAN]\nVisite degli usurai\n\n[ST_STOR]\nEdifici razziati\n\n[ST_MOVI]\nStunt nei film\n\n[ST_PIZZ]\nPizze consegnate\n\n[ST_GARB]\nSpazzatura raccolta\n\n[ST_ICEC]\nGelati venduti\n\n[TOP_SHO]\nMiglior punteggio al poligono\n\n[SHO_RAN]\nGraduatoria al poligono\n\n[SEAGULL]\nGabbiani abbattuti\n\n[PROPOWN]\nProprietà posseduti\n\n[ST_TIME]\nTempo di gioco\n\n[ST_FTIM]\nOre di volo\n\n[ST_PRAN]\nGraduatoria pilota\n\n[ST_RAN0]\nApprendista\n\n[ST_RAN1]\nNavigatore\n\n[ST_RAN2]\nCopilota\n\n[ST_RAN3]\nPratico\n\n[ST_RAN4]\nCompetente\n\n[ST_RAN5]\nAnziano\n\n[ST_RAN6]\nAsso\n\n[ST_RAN7]\nBarone Rosso\n\n[ST_DRWN]\nPesci sfamati\n\n[ST_FASH]\nBudget abbigliamento\n\n[ST_DAMA]\nProprietà distrutte\n\n[TM_DED]\nVisite all'ospedale\n\n[DAYSPS]\nGiorni trascorsi nel gioco\n\n[NUMSHV]\nVisite al rifugio\n\n[MXCARD]\nDistanza max salto FOLLE (ft)\n\n[MXCARJ]\nAltezza max salto FOLLE (ft)\n\n[MXCARDM]\nDistanza max salto FOLLE (m)\n\n[MXCARJM]\nAltezza max salto FOLLE (m)\n\n[MXFLIP]\nNumero max ribaltamenti FOLLI\n\n[MXJUMP]\nNumero max rotazioni FOLLI\n\n[BUL_FIR]\nColpi sparati\n\n[BUL_HIT]\nColpi a segno\n\n[SPRAYIN]\nRiverniciature\n\n[BSTSTU]\nMigliore acrobazia FOLLE\n\n[INSTUN]\nAcrobazia folle\n\n[PRINST]\nAcrobazia folle perfetta\n\n[DBINST]\nDoppia acrobazia folle\n\n[DBPINS]\nDoppia acrobazia folle perfetta\n\n[TRINST]\nTripla acrobazia folle\n\n[PRTRST]\nTripla acrobazia folle perfetta\n\n[QUINST]\nQuadrupla acrobazia folle\n\n[PQUINS]\nQuadrupla acrobazia folle perfetta\n\n[NOSTUC]\nNessuna acrobazia FOLLE effettuata\n\n[NOUNIF]\nAcrobazie uniche completate\n\n[NMISON]\nMissioni provate\n\n[PASDRO]\nPasseggeri scaricati\n\n[MONTAX]\nSoldi guadagnati in taxi\n\n[DAYPLC]\nSpesa giornaliera polizia\n\n[CRIMRA]\nLivello criminalità:\n\n[STPR_1]\nMalibu\n\n[STPR_2]\nTipografia\n\n[STPR_3]\nStudio cinematografico\n\n[STPR_4]\nFabbrica di gelato\n\n[STPR_5]\nLavaggio auto\n\n[STPR_6]\nCompagnia di taxi\n\n[STPR_7]\nCantiere navale\n\n[SET1EN]\nConfig. 1. Abilitata.\n\n[GMSAVE]\nSalva partita\n\n[FEDS_TB]\nIndietro\n\n[FEST_OO]\nsu\n\n[FEC_TUC]\nComandi torretta\n\n[FEC_RS3]\nStazioni radio (tasto L3)\n\n[FEC_HO3]\nClacson (tasto L3)\n\n[C_FAIL]\nMissione Vigilante terminata!\n\n[C_ESCP]\n~r~Il sospettato è fuggito!\n\n[C_VIGIL]\nBONUS VIGILANTE!\n\n[HEAL_A]\nLa tua ~h~salute~w~ è indicata in color arancione in alto a destra sullo schermo.\n\n[WRONGCD]\nDisco errato. Inserisci il disco corretto.\n\n[NOCD]\nIl cassetto del disco è vuoto. Inserisci il disco.\n\n[OPENCD]\nIl cassetto del disco è aperto: è necessario chiuderlo.\n\n[CDERROR]\nErrore di lettura dal DVD Grand Theft Auto: Vice City.\n\n[RESTART]\nAvvio di una nuova partita\n\n[GA_3]\nNiente più sconti. $100 per la riverniciatura!\n\n[GA_1]\nWow! Non tocco niente di COSÌ caldo!\n\n[GA_1A]\nTorna quando non sarai così occupato...\n\n[HELP9_C]\nPremi il ~h~~k~~PED_FIREWEAPON~~w~ per ~h~sparare~w~ col fucile di precisione.\n\n[TAXI2]\n~r~Tempo scaduto!\n\n[PAGEB13]\nSalute consegnata al nascondiglio\n\n[PAGEB14]\nAdrenalina consegnata al nascondiglio\n\n[FESZ_CA]\nAnnulla\n\n[FES_NGA]\nNuova partita\n\n[FES_CAN]\nAnnulla\n\n[FESZ_QL]\nTutti i progressi della partita attuale non ancora salvati andranno perduti. Vuoi procedere con il caricamento?\n\n[FESZ_QD]\nVuoi eliminare questa partita salvata?\n\n[FESZ_QO]\nVuoi procedere con la sovrascrittura di questa partita salvata?\n\n[FESZ_QR]\nSei sicuro di voler iniziare una nuova partita? Tutti i progressi fatti fino all'ultimo salvataggio andranno perduti. Vuoi procedere?\n\n[T4X4_1]\n'Parco divertimenti PCJ'\n\n[BMX_1]\n'Prova del fango'\n\n[BMX_2]\n'Tracciato di prova'\n\n[BMXFAIL]\n~r~Non sei riuscito a stabilire un nuovo record!\n\n[T4X4_3]\n'TENUTA!'\n\n[MM_1]\n'FOLLIA CONICA'\n\n[T4X4_F]\n~r~Ti sei ritirato! Troppo difficile per te?\n\n[LANDSTK]\nLandstalker\n\n[IDAHO]\nIdaho\n\n[STINGER]\nStinger\n\n[LINERUN]\nLinerunner\n\n[PEREN]\nFamiliare\n\n[SENTINL]\nSentinel\n\n[RIO]\nRio\n\n[PATRIOT]\nPatriot\n\n[FIRETRK]\nCamion dei pompieri\n\n[TRASHM]\nNettezza urbana\n\n[STRETCH]\nStretch\n\n[MANANA]\nManana\n\n[INFERNS]\nInfernus\n\n[VOODOO]\nVoodoo\n\n[PONY]\nPony\n\n[MULE]\nMule\n\n[CHEETAH]\nCheetah\n\n[AMBULAN]\nAmbulanza\n\n[FBICAR]\nFBI Washington\n\n[MOONBM]\nMoonbeam\n\n[ESPERAN]\nEsperanto\n\n[TAXI]\nTaxi\n\n[WASHING]\nWashington\n\n[BOBCAT]\nBobcat\n\n[WHOOPEE]\nMr Whoopee\n\n[BFINJC]\nBF a iniezione\n\n[HUNTER]\nHunter\n\n[POLICAR]\nPolizia\n\n[ENFORCR]\nVolante\n\n[SECURI]\nSecuricar\n\n[BANSHEE]\nBanshee\n\n[PREDATR]\nPredator\n\n[BUS]\nAutobus\n\n[RHINO]\nRhino\n\n[BARRCKS]\nCaserma OL\n\n[CUBAN]\nCuban Hermes\n\n[HELI]\nElicottero\n\n[DODO]\nDodo\n\n[COACH]\nPullman\n\n[CABBIE]\nVecchio taxi\n\n[STALION]\nStallion\n\n[RUMPO]\nRumpo\n\n[RCBANDT]\nBandit radiocomandato\n\n[ROMERO]\nCarro funebre di Romero\n\n[PACKER]\nPacker\n\n[ADMIRAL]\nAdmiral\n\n[SQUALO]\nSqualo\n\n[SEASPAR]\nSea Sparrow\n\n[PIZZABO]\nPizza Boy\n\n[GANGBUR]\nGang Burrito\n\n[TROPIC]\nTropic\n\n[SPEEDER]\nSpeeder\n\n[REEFER]\nReefer\n\n[FLATBED]\nFlatbed\n\n[YANKEE]\nYankee\n\n[CADDY]\nCaddy\n\n[ZEBRA]\nTaxi Zebra\n\n[TOPFUN]\nTop Fun\n\n[SKIMMER]\nSkimmer\n\n[PCJ600]\nPCJ 600\n\n[PHOENIX]\nPhoenix\n\n[FAGGIO]\nFaggio\n\n[FREEWAY]\nFreeway\n\n[RCBARON]\nBaron radiocomandato\n\n[RCRAIDE]\nRaider radiocomandato\n\n[GLENDAL]\nGlendale\n\n[OCEANIC]\nOceanic\n\n[SANCHEZ]\nSanchez\n\n[SPARROW]\nSparrow\n\n[LOVEFIS]\nLove Fist\n\n[COASTG]\nCoast Guard\n\n[DINGHY]\nDinghy\n\n[HERMES]\nHermes\n\n[SABRE]\nSabre\n\n[SABRETU]\nSabre Turbo\n\n[WALTON]\nWalton\n\n[REGINA]\nRegina\n\n[COMET]\nComet\n\n[DELUXO]\nDeluxo\n\n[BURRITO]\nBurrito\n\n[SPAND]\nSpandex Express\n\n[MARQUIS]\nMarquis\n\n[BAGGAGE]\nBaggage Handler\n\n[KAUFMAN]\nTaxi Kaufman\n\n[COASTMA]\nCoastguard Maverick\n\n[MAVERIC]\nMaverick\n\n[RANCHER]\nRancher\n\n[FBIRANC]\nFBI Rancher\n\n[VIRGO]\nVirgo\n\n[GREENWO]\nGreenwood\n\n[HOTRING]\nHotring Racer\n\n[BLISTAC]\nBlista Compact\n\n[FEST_DF]\nDistanza a piedi (miglia)\n\n[FEST_DC]\nDistanza in auto (miglia)\n\n[FESTDFM]\nDistanza a piedi (metri)\n\n[FESTDCM]\nDistanza in auto (metri)\n\n[TOT_DIS]\nDistanza totale (miglia)\n\n[TOTDISM]\nDistanza totale (metri)\n\n[DISTHEL]\nDistanza in elicottero (miglia)\n\n[DISTHEM]\nDistanza in elicottero (metri)\n\n[DISTBOA]\nDistanza in barca (miglia)\n\n[DISTBOM]\nDistanza in barca (metri)\n\n[FEST_LS]\nPersone salvate in ambulanza\n\n[FEST_CC]\nCriminali uccisi in missioni Vigilante\n\n[FEST_FE]\nIncendi estinti\n\n[FEST_RP]\nViolenze eseguite\n\n[FEST_MP]\nMissioni completate\n\n[FEST_BB]\nBling-bling Scramble:\n\n[FEST_H0]\nMaggior numero di punti di controllo\n\n[FEST_GC]\nAuto delle gang distrutte:\n\n[FEST_H1]\nDistruzione Diablo\n\n[FEST_H2]\nMassacro Mafioso\n\n[FEST_H3]\nCalamità al Casinò\n\n[FEST_H4]\nDemolizioni Rumpo\n\n[USJ]\nBONUS ACROBAZIA UNICA!\n\n[RATNG1]\nCittadino onesto\n\n[RATNG2]\nSconosciuto\n\n[RATNG3]\nPezzente\n\n[RATNG4]\nFurfantello\n\n[RATNG5]\nVandalo\n\n[RATNG6]\nFattorino\n\n[RATNG7]\nBorsaiolo\n\n[RATNG8]\nCleptomane\n\n[RATNG9]\nTeppista\n\n[RATNG10]\nLadruncolo\n\n[RATNG11]\nSanguisuga\n\n[RATNG12]\nTruffatore\n\n[RATNG13]\nFarabutto\n\n[RATNG14]\nInformatore\n\n[RATNG15]\nImbroglione\n\n[RATNG16]\nBullo\n\n[RATNG17]\nCanaglia\n\n[RATNG18]\nScapestrato\n\n[RATNG19]\nRuffiano\n\n[RATNG20]\nFuorilegge\n\n[RATNG21]\nDelinquente\n\n[RATNG22]\nLadro\n\n[RATNG23]\nScagnozzo\n\n[RATNG24]\nTirapiedi\n\n[RATNG25]\nAvanzo di galera\n\n[RATNG26]\nEx galeotto\n\n[RATNG27]\nCriminale\n\n[RATNG28]\nPicchiatore\n\n[RATNG29]\nSaggio\n\n[RATNG30]\nAutista\n\n[RATNG31]\nGuardia del corpo\n\n[RATNG32]\nAttaccabrighe\n\n[RATNG33]\nCacciatore di taglie\n\n[RATNG34]\nVigilante\n\n[RATNG35]\nRonin\n\n[RATNG36]\nRiparatore\n\n[RATNG37]\nSicario\n\n[RATNG38]\nSocio\n\n[RATNG39]\nMacellaio\n\n[RATNG40]\nPulitore\n\n[RATNG41]\nAssassino\n\n[RATNG42]\nConsigliere\n\n[RATNG43]\nConsulente\n\n[RATNG44]\nBraccio destro\n\n[RATNG45]\nEsecutore\n\n[RATNG46]\nTenente\n\n[RATNG47]\nAiutante del boss\n\n[RATNG48]\nCapo\n\n[RATNG49]\nBoss\n\n[RATNG50]\nIntoccabile\n\n[RATNG51]\nDon\n\n[RATNG52]\nRe della fottuta città\n\n[PAGE_00]\n.\n\n[WELCOME]\nBENVENUTO A\n\n[TSCORE]\nGUADAGNI: ~1~$\n\n[PBOAT_2] { reVC update }\nPremi il ~h~~k~~VEHICLE_FIREWEAPON~~w~ per sparare con i cannoni della barca.\n\n[HJSTAT]\nDistanza: ~1~.~1~m Altezza: ~1~.~1~m Ribaltamenti: ~1~ Rotazioni: ~1~_\n\n[HJSTATW]\nDistanza: ~1~.~1~m Altezza: ~1~.~1~m Ribaltamenti: ~1~ Rotazioni: ~1~_ E che grande atterraggio!\n\n[ATUTOR]\nPremi il ~h~~k~~TOGGLE_SUBMISSIONS~~w~ per attivare o disattivare le missioni Infermiere.\n\n[FEST_HA]\nLivello massimo della missione Infermiere\n\n[C_KILLS]\nCRIMINALI UCCISI: ~1~\n\n[HJSTATF]\nDistanza: ~1~ piedi Altezza: ~1~ piedi Ribaltamenti: ~1~ Rotazioni: ~1~_\n\n[HJSTAWF]\nDistanza: ~1~ piedi Altezza: ~1~ piedi Ribaltamenti: ~1~ Rotazioni: ~1~_ E che grande atterraggio!\n\n[CRED001]\nROCKSTAR NORTH\n\n[CRD001A]\nDIRETTORE DELLO STUDIO\n\n[CRD001B]\nANDREW SEMPLE\n\n[CRED002]\nPRODUTTORE\n\n[CRD002A]\nDIRETTORE DI SVILUPPO\n\n[CRED003]\nLESLIE BENZIES\n\n[CRED004]\nDIRETTORE ARTISTICO\n\n[CRED005]\nAARON GARBUT\n\n[CRED006]\nDIRETTORI TECNICI\n\n[CRED007]\nOBBE VERMEIJ\n\n[CRED008]\nADAM FOWLER\n\n[CRED010]\nANDREW DUTHIE\n\n[CRED011]\nCRAIG FILSHIE\n\n[CRED012]\nWILLIAM MILLS\n\n[CRED013]\nCHRIS ROTHWELL\n\n[CRD013A]\nIMRAN SARWAR\n\n[CRD013B]\nJAMES WORRALL\n\n[CRD013C]\nJOHN HAIME\n\n[CRED014]\nSCRITTO DA\n\n[CRED015]\nJAMES WORRALL\n\n[CRED016]\nPAUL KUROWSKI\n\n[CRED017]\nDAN HOUSER\n\n[CRED018]\nPROGETTAZIONE PERSONAGGI PRINCIPALI\n\n[CRD018A]\nPROGETTAZIONE PERSONAGGI\n\n[CRED019]\nIAN MCQUE\n\n[CRD019A]\nTOKS SOLARIN\n\n[CRD019B]\nALAN DAVIDSON\n\n[CRED020]\nANIMATORE CAPO\n\n[CRED021]\nALEX HORTON\n\n[CRD022A]\nANIMATORI\n\n[CRED022]\nLEE MONTGOMERY\n\n[CRD022B]\nDUNCAN SHIELDS\n\n[CRD022C]\nGUS BRAID\n\n[CRED023]\nPROGETTAZIONE VEICOLI\n\n[CRD023A]\nJOLYON ORME\n\n[CRD023B]\nALAN DUNCAN\n\n[CRD024A]\nCAPO PROGETTAZIONE VEICOLI\n\n[CRED024]\nPAUL KUROWSKI\n\n[CRED025]\nPROGETTAZIONE MAPPA\n\n[CRED026]\nADAM COCHRANE\n\n[CRED027]\nNIK TAYLOR\n\n[CRED028]\nGARY MCADAM\n\n[CRED029]\nKEIRAN BAILLIE\n\n[CRED030]\nALISDAIR WOOD\n\n[CRED031]\nANDREW SOOSAY\n\n[CRD031A]\nSTEVEN MULHOLLAND\n\n[CRD031B]\nWAYLAND STANDING\n\n[CRD031C]\nCAMPBELL J. DICK\n\n[CRD031D]\nPROGETTAZIONE GRAFICA\n\n[CRD031E]\nSTUART PETRI\n\n[CRED032]\nPROGRAMMATORE CAPO\n\n[CRD032A]\nPROGRAMMATORI\n\n[CRED033]\nALEXANDER ROGER\n\n[CRED034]\nGRAEME WILLIAMSON\n\n[CRED035]\nBARANE CHAN\n\n[CRED036]\nDEREK PAYNE\n\n[CRED037]\nGORDON YEOMAN\n\n[CRD037A]\nALAN CAMPBELL\n\n[CRD037B]\nMARK HANLON\n\n[CRD037C]\nANDRZEJ MADAJCZYK\n\n[CRED038]\nCAPO PRODUZIONE MUSICA\n\n[CRED039]\nCRAIG CONNER\n\n[CRED040]\nSTUART ROSS\n\n[CRED041]\nCAPO INGEGNERE AUDIO\n\n[CRED042]\nALLAN WALKER\n\n[CRD041A]\nINGEGNERE AUDIO\n\n[CRD041B]\nAUDIO\n\n[CRD042A]\nWILL MORTON\n\n[CRED043]\nPROGRAMMATORE AUDIO\n\n[CRED044]\nRAYMOND USHER\n\n[CRED045]\nRESPONSABILE TESTING\n\n[CRED046]\nCRAIG ARBUTHNOTT\n\n[CRED047]\nCAPO CQ\n\n[CRED048]\nNEIL CORBETT\n\n[CRED049]\nKEVIN WONG\n\n[CRED050]\nCQ\n\n[CRED051]\nDAVID BEDDOES\n\n[CRED052]\nDAVID WATSON\n\n[CRED053]\nBARRY CLARK\n\n[CRED054]\nROSS SPARROW\n\n[CRED055]\nJAMES ALLAN\n\n[CRED056]\nNEIL MEIKLE\n\n[CRD056A]\nGEORGE WILLIAMSON\n\n[CRD056B]\nMATT JONES\n\n[CRD056C]\nROB HARBOUR\n\n[CRD056D]\nTOM WHITTAKER\n\n[CRED057]\nCAPO SUPPORTO TECNICO\n\n[CRED058]\nLORRAINE ROY\n\n[CRD057A]\nSUPPORTO TECNICO\n\n[CRED059]\nCHRISTINE CHALMERS\n\n[CRD060A]\nSUPPORTO UFFICIO\n\n[CRD060B]\nKIM GURNEY\n\n[CRD060C]\nCASSIE OLIVER\n\n[CRED060]\nROCKSTAR NEW YORK\n\n[CRED061]\nPRODUTTORE ESECUTIVO\n\n[CRED062]\nSAM HOUSER\n\n[CRED063]\nPRODUTTORE\n\n[CRED064]\nDAN HOUSER\n\n[CRED065]\nVP DI SVILUPPO\n\n[CRED066]\nJAMIE KING\n\n[CRED067]\nCAPO RESPONSABILE TECNOLOGICO\n\n[CRED068]\nGARY J. FOREMAN\n\n[CRED069]\nPRODUTTORE ASSOCIATO\n\n[CRED070]\nJEREMY POPE\n\n[CRD071A]\nDIRETTORE DEL CQ\n\n[CRD072A]\nJEFF ROSA\n\n[CRED071]\nSUPERVISORE MUSICA\n\n[CRED072]\nTERRY DONOVAN\n\n[CRED073]\nSQUADRA DI PRODUZIONE\n\n[CRED074]\nTERRY DONOVAN\n\n[CRED075]\nJENNIFER KOLBE\n\n[CRED076]\nJENEFER GROSS\n\n[CRED077]\nLAURA PATERSON\n\n[CRED078]\nJEFF CASTANEDA\n\n[CRED079]\nJERONIMO BARRERA\n\n[CRED080]\nCARLY SLATER\n\n[CRED081]\nJUNG KWAK\n\n[CRED082]\nBRIAN WOOD\n\n[CRED083]\nRENAUD SEBANNE\n\n[CRED084]\nRICHARD KRUGER\n\n[CRD084A]\nDANIEL EINZIG\n\n[CRD084B]\nJACEN BURROWS\n\n[CRD084C]\nLINN PR\n\n[CRD084D]\nGRAFICA DI COPERTINA\n\n[CRD084E]\nSTEPHEN BLISS\n\n[CRED085]\nKENT PAUL'S 80 NOSTALGIA ZONE\n\n[CRED086]\nCOMPOSTA DA DAN HOUSER\n\n[CRD086A]\nPRODOTTA DA ADAM TEDMAN\n\n[CRED087]\nWWW.KENTPAUL.COM E WWW.VICECITY.COM\n\n[CRED088]\nCREATO DA\n\n[CRD088A]\nADAM TEDMAN\n\n[CRD088B]\nDAVID YU\n\n[CRD088C]\nJERRY LUNA\n\n[CRD088D]\nSTUART PETRI\n\n[CRD088E]\nMICHAEL CARNEVALE\n\n[CRD088F]\nGREG LAU\n\n[CRD088G]\nFUTABA HAYASHI\n\n[CRED089]\nRESPONSABILE CQ\n\n[CRED090]\nCRAIG ARBUTHNOTT\n\n[CRED091]\nCAPO ANALISTA\n\n[CRED092]\nADAM DAVIDSON\n\n[CRD092A]\nJOE HOWELL\n\n[CRD092B]\nMARC FERNANDEZ\n\n[CRED093]\nANALISTA DI GIOCO\n\n[CRED094]\nRICHARD HUIE\n\n[CRED095]\nSQUADRA TESTING ROCKSTAR\n\n[CRED096]\nLANCE WILLIAMS\n\n[CRED097]\nJOE GREENE\n\n[CRED098]\nBRIAN PLANER\n\n[CRD098A]\nELIZABETH SATTERWHITE\n\n[CRD098B]\nJAMEEL VEGA\n\n[CRD098C]\nMIKE HONG\n\n[CRED099]\nLEE CUMMINGS\n\n[CRED100]\nSCENEGGIATURA\n\n[CRED101]\nJAMES WORRALL\n\n[CRED102]\nDAN HOUSER\n\n[CRED103]\nADAM TEDMAN\n\n[CRED104]\nPAUL YEATES\n\n[CRED105]\nJENEFER GROSS\n\n[CRED106]\nLAURA PATERSON\n\n[CRED107]\nSEQUENZE ANIMATE\n\n[CRED108]\nSCRITTE DA DAN HOUSER E JAMES WORRALL\n\n[CRED109]\nDIREZIONE AUDIO DI DAN HOUSER E NAVID KHONSARI\n\n[CRED110]\nPRODOTTE DA JAMIE KING\n\n[CRD110A]\nRICERCA TALENTI: JAMIE KING, SEAN MACALUSO\n\n[CRED111]\nCAST\n\n[CRD111A]\nPERSONAGGI PRINCIPALI\n\n[CRED112]\nTOMMY VERCETTI - RAY LIOTTA\n\n[CRED113]\nKEN ROSENBERG - WILLIAN FICHTNER\n\n[CRED114]\nSONNY FORELLI - TOM SIZEMORE\n\n[CRED115]\nSTEVE SCOTT - DENNIS HOPPER\n\n[CRED116]\nAVERY CARRINGTON - BURT REYNOLDS\n\n[CRED117]\nRICARDO DIAZ - LUIS GUZMAN\n\n[CRED118]\nLANCE VANCE - PHILIP MICHAEL THOMAS\n\n[CRED119]\nCOLONNELLO JUAN CORTEZ - ROBERT DAVI\n\n[CRED120]\nUMBERTO ROBINA - DANNY TREJO\n\n[CRED121]\nPHIL CASSIDY - GARY BUSEY\n\n[CRED122]\nMITCH BAKER - LEE MAJORS\n\n[CRED123]\nMERCEDES CORTEZ - FAIRUZA BALK\n\n[CRED124]\nKENT PAUL - DANNY DYER\n\n[CRED125]\nJEZZ TORRENT - KEVIN MCKIDD\n\n[CRED126]\nCENTRALINISTA TAXI - DEBORAH HARRY\n\n[CRED127]\nCANDY SUXX - JENNA JAMESON\n\n[CRED128]\nBJ SMITH - LAWRENCE TAYLOR\n\n[CRED129]\nAUNTIE POULET - YOUREE CLEOMILI HARRIS\n\n[CRED130]\nSPACCIATORE - ARMANDO RIESCO\n\n[CRED131]\nCOUGAR - BLAYNE PERRY\n\n[CRED132]\nHILARY - CHARLES TUCKER\n\n[CRED133]\nDEPUTATO ALEX SHRUB - CHRIS LUCAS\n\n[CRED134]\nVECCHIO KELLY - GEORGE DICENZO\n\n[CRD134A]\nCAM JONES - GREG SIMS\n\n[CRD134B]\nPSICOPATICO - HUNTER PLATIN\n\n[CRD134C]\nMAUDE, LA SIGNORA DEI GELATI - JANE GENNARO\n\n[CRD134D]\nJETHRO - JOHN ZURHELLEN\n\n[CRD134E]\nGONZALES - JORGE PUPO\n\n[CRD134F]\nDWAYNE - NAVID KHONSARI\n\n[CRD134G]\nDICK - PETER MCKAY\n\n[CRD134H]\nMIKE & PORNOSTAR - ROBERT CIHRA\n\n[CRD134I]\nPERCY - RUSSELL FOREMAN\n\n[CRED135]\nMOTION CAPTURE\n\n[CRED136]\nANIMATO DA\n\n[CRD136A]\nDIREZIONE TECNICA DI ALEX HORTON\n\n[CRED137]\nDIRETTO DA\n\n[CRD137A]\nDIRETTO DA NAVID KHONSARI\n\n[CRED138]\nPRODOTTO DA\n\n[CRD138A]\nPRODOTTO DA JAMIE KING\n\n[CRD138B]\nRENAUD SEBBANE\n\n[CRED139]\nREGISTRATO PRESSO PERSPECTIVE STUDIOS, BROOKLYN\n\n[CRED140]\nATTORI MOTION CAPTURE\n\n[CRD140A]\nBLAYNE PERRY\n\n[CRD140B]\nJONATHON SALE\n\n[CRD140C]\nCHARLES TUCKER\n\n[CRD140D]\nEDDIE MARRERO\n\n[CRD140E]\nWILLIAM MCCALL\n\n[CRD140F]\nJORGE PUPO\n\n[CRD140G]\nROBERT JACKSON\n\n[CRD140H]\nTARA RADCLIFFE\n\n[CRD140I]\nJENIFER GAMBETESE\n\n[CRD140J]\nKRIS ACHEVARRIA\n\n[CRD140K]\nALI ORDOUBADI\n\n[CRD140L]\nKAHLEEM POOLE\n\n[CRED141]\nDIALOGHI PEDONI\n\n[CRD141A]\nSCRITTI DA DAN HOUSER, MARC FERNANDEZ, GILLIAN TELLING E NAVID KHONSARI\n\n[CRD141B]\nCON L'AIUTO DI JEREMY POPE, LANCE WILLIAMS E JENNY JEMISON\n\n[CRED142]\nSCRITTI DA\n\n[CRD142A]\nDAN HOUSER E JAMES WORRALL\n\n[CRED143]\nDIRETTI DA DAN HOUSER, CRAIG CONNER, MARC FERNANDEZ E ALLAN WALKER\n\n[CRED144]\nPRODOTTI DA RENAUD SEBANNE\n\n[CRED145]\nPEDONI\n\n[CRED146]\nADAM DAVIDSON, ADAM WATKINS, ALEJANDRO K. BROWN, ALEX ANTHONY SIOUKAS, ALEX GARCIA,\n\n[CRED147]\nALICE SALTZMAN, ALISON CIHRA, AMY SALIMA, AMY SALZMAN, ANDREA VIDELA, ANTHONY ATTI,\n\n[CRED148]\nANTHONY RIVERA, BIJAN SHAMS, BLAYNE PERRY, BRETT BISOGNO, BREYE MATA, BRIAN PANEN,\n\n[CRED149]\nBROCK VODER, CAREY BERTINI, CHARISSE LAMBERT, CHRIS DIFAT, CHRIS REISENBERGER,\n\n[CRED150]\nCHRISTOPHER BRODAY, CHRISTOPHER CARRO, CYNTHIA GREENE, DAMARIES LOPEZ, DAN LEE,\n\n[CRED151]\nDAN SCHNEIDER, DAN TOYAMA, DAVID DEAN CHALTFIELD, JR., DAVID HARRISON, DAVID WILEY,\n\n[CRED152]\nDEBORAH COLLINS, DEBRANDA CHANEY-GILES, DEMETRA KOUKOULAS, DENISE ROSADO,\n\n[CRED153]\nDEVIN BENNETT, DEVIN WINTERBOTTOM, DORIS WOO, DOUGLAS HARRISON, DUNCAN COUTTS,\n\n[CRED154]\nDUPE AJAYI, EDWIN AVELLANEDA, ELIZABETH HOWELL, ELIZABETH SATTERWHITE, ERIC NAGLE,\n\n[CRED155]\nESTEBAN KARPLUS, F. FONT, FUTABA HAYASHI, GENE HILGREEN, GERALD COSGROVE,\n\n[CRED156]\nGERARD LUNA, GILLIAN TELLING, GREGG CARLUCCI, GREGORY CLERVOIX, GREGORY SCHWEIZER,\n\n[CRED157]\nHADLEY TOMICKI, J. ROSSETT, JAMEEL VEGA, JASON JONES, JEFF ROSA, JENNIFER JEMISON,\n\n[CRED158]\nJEREMY TAGGERT, JESSICA RIDER, JOSEPH GREENE,JOSEPH HOWELL, KATE DUKICH,\n\n[CRED159]\nKEL O'NEILL, KEVIN HOPKINS, LADAWN JAMES, LANCE WILLIAMS, LAURA BUBBLES,\n\n[CRED160]\nLAURA PATTERSON, LEE CUMMINGS, LETICIA L. YOUNG, LINDSAY KENNEDY, LISA ORITZ,\n\n[CRED161]\nLORNA JORDAN, LUCIO AMADIO, MARCO FERNANDEZ, MARIKO TANAKA, MARLON MATTHEWS,\n\n[CRED162]\nMARY TELLING, MASAYOSHI MITSUYAMA, MATTHEW CHUNG, MAX ALLSTADT, MAX BOGDANOV,\n\n[CRED163]\nMELISSA ALVAREZ, MICHAEL MAY, MICHAEL ROTHSTEIN, MIGUEL VIDAL, MIKE FEDERLINE,\n\n[CRED164]\nNATALIE DESCALZO, N'GAI MEMBERS, NICOLAS MALLO, NOELLE SADLER, NORBERT MORIVAN,\n\n[CRED165]\nOSWALD GREENE, JR., PETER MCKAY, PETER APPEL, PRESTON SAVARESE, RAFAEL GONZALES,\n\n[CRED166]\nRANDY JOHNSON, REY CONCEPCION, RICHARD KROGER, ROB TIBBS, ROBERT JACKSON,\n\n[CRED167]\nROBERT SCHULER, ROSS A. MCINTYRE, RUSSELL FOREMAN, RUTH NUNEZ, SALVADORE SUAZO,\n\n[CRED168]\nSAM WHITE, SANTOS GONZALES, SCOTT SMITH, SEYMOUR FRAILMAN, SPELMAN BRAUMAN,\n\n[CRED169]\nSTEPHANIE TELLING, STEVE KNEZEVICH, STEVE ROBERT, SUMIKO YASUDA, SUSAN LEWIS,\n\n[CRED170]\nSYLVIA COLACIOS, TOMOKO MIYAZAKI, TRON, VERDEL HALE, YVES MONDESIR, ZENO LEINFELDER,\n\n[CRED171]\nDAVID BEDDOES, CHRISTINE CHALMERS, BARRY CLARK, NEIL CORBETT, KIM GURNEY, NEIL MEIKLE,\n\n[CRED172]\nCASSIE OLIVER, LORRAINE ROY, DAVID WATSON, KEVIN WONG, WILL MORTON\n\n[CRED175]\nADAM DAVIDSON\n\n[CRED176]\nLANCE WILLIAMS\n\n[CRED177]\nNEIL MCCAFFREY\n\n[CRED178]\nLAURA PATERSON\n\n[CRED179]\nREY CONCEPCION\n\n[CRED180]\nCHARLES HEROLD\n\n[CRED181]\nANDREW GREENWALD\n\n[CRED182]\nJAMES MIELKE\n\n[CRED183]\nPETER SUCIU\n\n[CRED184]\nALEX ODULIO\n\n[CRED185]\nDON NKRUMAH\n\n[CRED186]\nKENDALL PITTMAN\n\n[CRED187]\nSAL SUAZO\n\n[CRED188]\nEREK MATEO\n\n[CRED189]\nCHRIS DIFATE\n\n[CRED190]\nLEILA MILTON\n\n[CRED191]\nDARREN ZOLTOWSKI\n\n[CRED192]\nVIRGINIA SMITH\n\n[CRED193]\nKEVIN CASSIN\n\n[CRED194]\nJASON SHIGEMORI\n\n[CRED195]\nKELLY KINSELLA\n\n[CRED196]\nMOLLIE STICKNEY\n\n[CRED197]\nSTANTON SARJEANT\n\n[CRED198]\nLAURA WALSH\n\n[CRED199]\nMARK GARONE\n\n[CRED200]\nJOANNA SLY\n\n[CRED201]\nELIZABETH HOWELL\n\n[CRED202]\nANA HERCULES\n\n[CRED203]\nSHIRLEY IRICK\n\n[CRED204]\nKASHONA FIELDS\n\n[CRED205]\nJOEL M. LILJE\n\n[CRED206]\nJOHN DIBENEDETTO\n\n[CRED207]\nNANCY GILES\n\n[CRED208]\nRYAN CROY\n\n[CRED209]\nJENNIFER KOLBE\n\n[CRED210]\nLIAM BURKE\n\n[CRED211]\nSIGRID PREISSL\n\n[CRED212]\nANITA FITZSIMONS\n\n[CRED213]\nPHILIPPA RASELLI\n\n[CRED214]\nWIL QUESNEL\n\n[CRED215]\nFALKO BURKERT\n\n[CRED216]\nSARA SEWELL\n\n[CRED217]\nSTAZIONI RADIO E MUSICA\n\n[CRED218]\nCONSULENZA MUSICALE\n\n[CRD218A]\nHEINZ HENN\n\n[CRD218B]\nSTUART ROSS\n\n[CRED219]\nCOORDINATORE TRACCE AUDIO\n\n[CRED220]\nTERRY DONOVAN\n\n[CRED221]\nPRODUTTORI ROCKSTAR GAMES\n\n[CRED222]\nDAN HOUSER E LAZLOW\n\n[CRED223]\nPRODUTTORE ROCKSTAR NORTH\n\n[CRED224]\nCRAIG CONNER\n\n[CRED225]\nALLAN WALKER\n\n[CRED226]\nLAZLOW\n\n[CRED227]\nDJ BANTER E IMAGING\n\n[CRED228]\nSCRITTO DA DAN HOUSER E LAZLOW\n\n[CRED229]\nFLASH FM\n\n[CRD229A]\nTONI-MARIA CHAMBERS\n\n[CRD229B]\nVOCE E PRODUZIONE IMAGING - JEFF BERLIN\n\n[CRED230]\nUN RINGRAZIAMENTO SPECIALE A\n\n[CRED231]\nTOMMY MOTTOLA,\n\n[CRED232]\nMICHELLE ANTHONY,\n\n[CRED233]\nSTEVE BARNETT,\n\n[CRED234]\nCHUCK FLECKENSTEIN,\n\n[CRED235]\nRITA LIBERATOR\n\n[CRED236]\nMARTIN & CLAIRE LOGAN\n\n[CRED237]\nSANDRA HUTTON\n\n[CRED238]\nCHRISTINE DAVIDSON\n\n[CRED239]\nALAN, RED & BIGFOOT\n\n[CRED240]\nLE T\n\n[CRED241]\nCOLIN DONALD\n\n[CRED242]\nKERRY STALLWOOD\n\n[CRED243]\nALAN MCGREGOR\n\n[CRED244]\nCHRIS MORTON\n\n[CRED245]\nEMIL BUSSE\n\n[CRED246]\nEMILY BAILLIE\n\n[CRED247]\nKEVIN ARCHIBALD\n\n[CRED248]\nMORAG KERR\n\n[CRED249]\nCATH WALKER\n\n[CRED250]\nISO BAR\n\n[CRED251]\nWATERLINE\n\n[CRED252]\nNEWS CAFE\n\n[CRD251A]\nTHE POND\n\n[CRD252A]\nPIVO\n\n[CRED253]\nBUDGET VIDEO RENTALS\n\n[CRED254]\nLORNA'S SCOOTER\n\n[CRED255]\nGARETH MURFIN\n\n[CRED256]\nGRAFICA ADDIZIONALE\n\n[CRED257]\nTONY PORTER\n\n[CRED258]\nCRAIG MOORE\n\n[CRED259]\nSINCRONIZZAZIONE LABIALE SEQUENZE\n\n[CRED260]\nCOSGROVE HALL FILMS\n\n[CRED261]\nPRODUTTORE - OWEN BALLHATCHET\n\n[CRED262]\nANIMATORE SENIOR- JON TURNER\n\n[CRED263]\nANIMATORI - RICHARD DRUMM\n\n[CRED264]\nDAVE BROWN\n\n[CRED265]\nMAIR THOMAS\n\n[CRED266]\nPRASHANT PATEL\n\n[CRED267]\nCONSULENTE TECNOLOGICO AUDIO\n\n[CRED268]\nRIK EDE DI GAMESOUND LTD.\n\n[CRED269]\nSUPPORTO INTEGRAZIONE DTS\n\n[CRED270]\nTED LAVERTY DI DTS\n\n[CRED271]\nCHRIS GREER DI DTS\n\n[CRED272]\nJASON PAGE DI DTS\n\n[CRED273]\nRICERCA E ANALISI\n\n[CRED274]\nVROCK\n\n[CRED275]\nDJ: LAZLOW COME SE STESSO\n\n[CRED276]\nVOCE IMAGING - JOE KELLY\n\n[CRED277]\nPRODUZIONE IMAGING - JONATHAN HANST\n\n[CRED278]\nWAVE 103\n\n[CRED279]\nDJ: ADAM FIRST - JAMIE CANFIELD\n\n[CRED280]\nVOCE IMAGING - JEN SWEENEY\n\n[CRED281]\nPRODUZIONE IMAGING - JONATHAN HANST\n\n[CRED282]\nFEVER 105\n\n[CRED283]\nDJ: OLIVER 'LADYKILLER' BISCUIT - JULIUS DYSON\n\n[CRED284]\nVOCE IMAGING MASCHILE - ED MCMANN\n\n[CRED285]\nVOCE IMAGING FEMMINILE - SHAWNEE SMITH\n\n[CRED286]\nPRODUZIONE IMAGING - LISTEN KITCHEN\n\n[CRED287]\nEMOTION 98.3\n\n[CRED288]\nDJ: FERNANDO - FRANK CHAVEZ\n\n[CRED289]\nVOCE IMAGING - JEN SWEENEY\n\n[CRED290]\nPRODUZIONE IMAGING - JONATHAN HANST\n\n[CRED291]\nRADIO ESPANTOSO\n\n[CRED292]\nDJ: PEPE - TONY CHILRODES\n\n[CRED293]\nWILDSTYLE\n\n[CRED294]\nDJ: MISTER MAGIC COME SE STESSO\n\n[CRED295]\nVOCE IMAGING - FRANK SILVESTRO\n\n[CRED296]\nPRODUZIONE IMAGING - LAZLOW\n\n[CRED297]\nKCHAT\n\n[CRED298]\nSCRITTA DA DAN HOUSER E LAZLOW\n\n[CRED299]\nPRODOTTA E MIXATA DA LAZLOW\n\n[CRED300]\nDJ AMY SHECKENHAUSEN - LEYNA WEBER\n\n[CRED301]\nJEZ TORRENT - KEVIN MCKIDD\n\n[CRED302]\nMANDY - COLLEEN CORBETT\n\n[CRED303]\nMICHELLE CARAPADIS - MARY BIRDSONG\n\n[CRED304]\nMR.ZOO - CARL DOWLING\n\n[CRED305]\nGETHSEMANEE - LYNN LIPTON\n\n[CRED306]\nCLAUDE MAGINOT - JOHN MAUCERI\n\n[CRED307]\nBJ SMITH - LAWRENCE TAYLOR\n\n[CRED308]\nTHOR - FRANK FAVA\n\n[CRED309]\nVOCI PUBBLICITÀ\n\n[CRED310]\nCOUZIN ED, JOSH CLARK, JASON BUHRMESTER, JUAN ALLER, WAYNE OLIVER, SUSAN LEWIS, GILLIAN TELLING, TOM MURRAY, MIKE FERRANTE SR., EMMANUEL GOLDSTEIN, DAN HOUSER, NICK MANDELOS, GERRY COSGROVE, MIKE PALERMO, PORKCHOP, KEITH BROADAS\n\n[CRED311]\nLEWIS, GILLIAN TELLING, TOM MURRAY, MIKE FERRANTE SR., EMMANUEL GOLDSTEIN,\n\n[CRED312]\nDAN HOUSER, NICK MANDELOS, GERRY COSGROVE, MIKE PALERMO, PORKCHOP,\n\n[CRED313]\nKEITH BROADAS\n\n[CRED314]\nVCPR\n\n[CRED315]\nSCRITTO DA DAN HOUSER E LAZLOW\n\n[CRED316]\nPRODOTTO DA LAZLOW\n\n[CRED317]\nMAURICE CHAVEZ - PHILLIP ANTHONY RODRIGUEZ\n\n[CRED318]\nJONATHAN FREELOADER - PATRICK OLSEN\n\n[CRED319]\nMICHELLE MONTANIUS - KELLY GUEST\n\n[CRED320]\nDEP. ALEX SHRUB - CHRIS LUCAS\n\n[CRED321]\nCALLUM CRAYSHAW - SEAN MODICA\n\n[CRED322]\nJOHN F. HICKORY - LJ GANSEN\n\n[CRED323]\nPASTOR RICHARDS - DAVID GREEN\n\n[CRED324]\nJAN BROWN - MAUREEN SILLIMAN\n\n[CRED325]\nBARRY STARK - RENAUD SEBBANE\n\n[CRED326]\nJENNY LOUISE CRAB - MARY BIRDSONG\n\n[CRED327]\nKONSTANTINOS SMITH - KONSTANTINOS.COM\n\n[CRED328]\nJEREMY ROBARD - PETER SILVESTRO\n\n[CRED329]\nPUBBLICITÀ RADIO\n\n[CRED330]\nSCRITTE DA DAN HOUSER E LAZLOW\n\n[CRED331]\nPRODOTTE DA LAZLOW\n\n[CRED332]\nJINGLE AGGIUNTIVI PRODOTTI DA CRAIG CONNER\n\n[CRED333]\nVOCI PUBBLICITÀ\n\n[CRED334]\nADAM DAVIDSON, ALEX ANTHONY, ALICE SALTZMAN, AMY SALZMAN, KATE DUKICH,\n\n[CRED335]\nARAN RONICLE, BARB JONES, BEN KRECH, BRIAN THOMAS, BROCK YODER, CHRIS\n\n[CRED336]\nFERRANTE, CRAIG CONNER, DAVE RYAN, DAVID GREEN, DORIS WOO, DOUGLAS\n\n[CRED337]\nHARRISON, ED MCMANN, FRANK CHAVEZ, FRANK FAVA, GENE HILGREEN, GREG\n\n[CRED338]\nSCHWEIZER, HUNTER PLATIN, JAMES FERRANTE, JEFF BERLIN, JEFF ROSA, JOE KELLY,\n\n[CRED339]\nJOHN MAUCERI, JOSH CLARK, JULIE WEMYSS, KEVIN STRALEY, KIM GURNEY, LANCE\n\n[CRED340]\nWILLIAMS, LAURA PATERSON, LAZLOW, LISA ORTIZ, LORNA JORDAN, LUCIEN JONES,\n\n[CRED341]\nMAUREEN SILLIMAN, MIKE FERRANTE JR., PETE GUSTIN, PETER SILVESTRO, RAFF\n\n[CRED342]\nCROLLA, RANDY JOHNSON, RICHARD KRUGER, RON REEVE, SHELLEY MILLER, SKY, TJ ALLARD\n\n[CRD344A]\nAUDIO REGISTRATO PRESSO DIGITAL ARTS STUDIOS,\n\n[CRED344]\nNYC, TRACK 9 STUDIOS, NYC,\n\n[CRED345]\nWEDDINGTON MULTIMEDIA, LOS ANGELES,\n\n[CRD345A]\nSYNC SOUND, NYC E RADIO LAZLOW, LONG ISLAND.\n\n[CRED346]\nUN RINGRAZIAMENTO A AXEL ERICSON E WON LEE DI DIGITAL ARTS, PAUL VASQUEZ DI TRACK 9 STUDIOS, JOHN BOWEN E JOHN HASSLER DI SYNC SOUND\n\n[CRED347]\nMARK LLOYD\n\n[CRED348]\nTIM BATES\n\n[CRED349]\nKIT BROWN\n\n[CRED350]\nANDY MASON\n\n[CRED351]\nPHIL DEANE\n\n[CRED352]\nPHIL ALEXANDER\n\n[CRED353]\nMATT HEWITT\n\n[CRED354]\nDENBY GRACE\n\n[CRED355]\nANTOINE CABROL\n\n[CRED356]\nJONOTHAN STONES\n\n[CRED357]\nMIKE BLACKBURN\n\n[CRED358]\nTIM MCGAFF\n\n[CINCAM]\nCamera mobile\n\n[RC4]\n'LA FURIA DI RUMPO'\n\n[LEGAL]\n~g~Elimina la minaccia criminale!\n\n[GA_2]\nMotore nuovo e carrozzeria riverniciata. Gli sbirri non ti riconosceranno!\n\n[HELP15]\nQuando sei a piedi, premi il ~h~~k~~PED_LOOKBEHIND~~w~ per ~h~guardare indietro~w~. Usa la ~h~levetta analogica destra~w~ per ~h~guardarti attorno~w~.\n\n[FEC_LB4]\nGuarda indietro (tasto R3)\n\n[PERPIC]\nPacchetti speciali recuperati\n\n[CO_ONE]\nPacchetto speciale ~1~ su ~1~\n\n[GA_21]\nNon puoi parcheggiare altri veicoli in questo garage.\n\n[CHEAT1]\nTrucco attivato\n\n[CHEAT2]\nTrucco armi\n\n[CHEAT3]\nTrucco salute\n\n[CHEAT4]\nTrucco armatura\n\n[CHEAT5]\nTrucco livello di sospetto\n\n[CHEAT6]\nTrucco soldi\n\n[CHEAT7]\nTrucco tempo atmosferico\n\n[USJ_ALL]\nTUTTE LE ACROBAZIE UNICHE COMPLETATE\n\n[JAN]\nGen\n\n[FEB]\nFeb\n\n[MAR]\nMar\n\n[APR]\nApr\n\n[MAY]\nMag\n\n[JUN]\nGiu\n\n[JUL]\nLug\n\n[AUG]\nAgo\n\n[SEP]\nSet\n\n[OCT]\nOtt\n\n[NOV]\nNov\n\n[DEC]\nDic\n\n[DEFDT]\n--:---:---- --:--:--\n\n[BONUS]\n~g~BONUS ~1~$\n\n[HORN1]\nPremi il ~h~~k~~VEHICLE_HORN~~w~ per attivare il ~h~clacson~w~.\n\n[HORN2]\nPremi il ~h~~k~~VEHICLE_HORN~~w~ per attivare il ~h~clacson~w~.\n\n[HORN3]\nPremi il ~h~~k~~VEHICLE_HORN~~w~ per attivare il ~h~clacson~w~.\n\n[FEC_EXV]\nEsci dal veicolo\n\n[TAXI_M]\n'TAXI DRIVER'\n\n[COP_M]\n'VIGILANTE'\n\n[FIRE_M]\n'POMPIERE'\n\n[AMBUL_M]\n'INFERMIERE'\n\n[HJ_IS]\nBONUS ACROBAZIA FOLLE: ~1~$\n\n[HJ_PIS]\nBONUS ACROBAZIA FOLLE PERFETTA: ~1~$\n\n[HJ_DIS]\nBONUS DOPPIA ACROBAZIA FOLLE: ~1~$\n\n[HJ_PDIS]\nBONUS DOPPIA ACROBAZIA FOLLE PERFETTA: ~1~$\n\n[HJ_TIS]\nBONUS TRIPLA ACROBAZIA FOLLE: ~1~$\n\n[HJ_PTIS]\nBONUS TRIPLA ACROBAZIA FOLLE PERFETTA: ~1~$\n\n[HJ_QIS]\nBONUS QUADRUPLA ACROBAZIA FOLLE: ~1~$\n\n[HJ_PQIS]\nBONUS QUADRUPLA ACROBAZIA FOLLE PERFETTA: ~1~$\n\n[FESZ_LS]\nCaricamento completato.\n\n[HELI_1A]\nProva le tue abilità con lo Sparrow: scopri quanto velocemente riesci a completare il percorso.\n\n[HELI_1B]\nPercorso completato!\n\n[HELIODD]\nStrani incarichi con l'elicottero\n\n[INT2_M]\nHanno una fattoria in Panama.\n\n[INT2_N]\nOK, va bene, ascoltate:\n\n[INT2_O]\nquando arriviamo volete che resti in macchina\n\n[INT2_P]\no preferite che venga con voi altri?\n\n[INT2_Q]\nNo, resta in macchina.\n\n[INT2_R]\nLo sapete, ci ho pensato su.\n\n[INT2_S]\nPenso proprio che resterò in macchina.\n\n[INT4_A]\nFottuti! Siamo fottuti!\n\n[INT4_B]\nÈ sempre la stessa storia,\n\n[INT4_C]\nmetto fuori la testa per un maledetto secondo,\n\n[INT4_D]\ne il fato mi tira palate di merda in faccia!\n\n[INT4_E]\nBene, vaffanculo!\n\n[INT4_F]\nSmettila di fare casino e di lamentarti. Siamo vivi, non è vero?\n\n[INT4_G]\nFammi scendere qua.\n\n[INT4_H]\nFai scomparire la macchina e fatti una bella dormita.\n\n[INT4_I]\nPasserò domani a trovarti in ufficio e troveremo un modo per risolvere questo casino.\n\n[INT4_J]\nOK, mi sembra un'ottima idea, andrò a dormire.\n\n[INT4_K]\nChe cosa intendi fare?\n\n[INT4_L]\nTornare nella mia stanza,\n\n[INT4_M]\nschiarirmi le idee e risolvere questo casino.\n\n[INT4_N]\nOK.\n\n[LAW]\nMISSIONI DELL'AVVOCATO\n\n[LAW1_1]\n~g~Vai a prendere degli abiti nuovi dal negozio di vestiti Rafael's.\n\n[LAW4_6]\nBrucia l'amministrazione!\n\n[LAW4_7]\nUccidi i responsabili!\n\n[LAW4_8]\nCombattere, combattere, combattere, combattere,.\n\n[LAW4_9]\nPiù ferie, meno lavoro!\n\n[LAW4_11]\nCombattere, combattere, combattere, combattere,.\n\n[LAW4_12]\nViva la rivoluzione.\n\n[GENERAL]\nMISSIONI DEL COLONNELLO\n\n[GEN3_4]\nTommy Vercetti. Andiamo...\n\n[GEN3_13]\nChe cosa diavolo ti prende? Vai sul tetto dall'altra parte del cortile prima che arrivino!\n\n[GEN3_17]\nMeeerda! Stai cercando di ammazzarmi?\n\n[GEN3_21]\n~g~Ha preso i soldi di Diaz! Inseguilo e riprendili!\n\n[GEN3_24]\n~r~Diaz è morto! Non sei riuscito a proteggerlo!\n\n[GEN3_26]\n~r~Hai ucciso Diaz!\n\n[GEN3_27]\n~r~Hai ucciso una guardia di Diaz!\n\n[GEN3_31]\n~g~Vai all'appuntamento e proteggi Diaz.\n\n[GEN3_32]\n~g~Raggiungi il tetto nell'edificio di fronte a Lance e appostati.\n\n[COKE]\nMISSIONI DEL BARONE DELLA COCA\n\n[COK1_3]\nSpero tu cada e ti rompa l'osso del collo!\n\n[COK1_6]\nSono stanco di tutto questo.\n\n[COK2_7]\nVedi quei segnali, ragazzo? Cerca di colpire le luci!\n\n[COK2_10]\nDi certo sei più bravo a sparare che a parlare.\n\n[COK2_11]\nGrazie. Anche tu hai una bella parlantina.\n\n[COK2_12]\nLo so, Tommy.\n\n[COK2_18]\nTi diverti con Kenny Loggins.\n\n[COK2_19]\nCielo, adoro questo album!\n\n[COK2_26]\n~r~Hai ucciso Lance!\n\n[COK3_1]\nNon sparare, amico!\n\n[COK3_2]\nChe cosa sta succedendo?\n\n[COK3_3]\nSta prendendo la barca. Farabutto!\n\n[COK3_4]\nAiuto! Un idiota sta rubando la barca!\n\n[COK4_W]\nUugghh! Questo è l'ultimo.\n\n[COK4_X]\nVado ad accendere...\n\n[COK4_Y]\nA quanto sembra abbiamo dei nuovi amici.\n\n[COK4_2]\nSì.\n\n[COK4_6]\nSai dove stiamo andando?\n\n[COK4_7]\nCi siamo persi?\n\n[COK4_8]\nAbbiamo un po' di competizione!\n\n[COK4_9]\nFalli fuori!\n\n[COK4_9A]\nÈ giunta l'ora di un po' di Lance Vance Dance!\n\n[COK4_10]\nSono pronti per il macero! E per sfamare i pesci.\n\n[COK4_11]\nCe l'abbiamo fatta! Le altre imbarcazioni non sono della nostra classe.\n\n[COK4_17]\nStanno iniziando a pregare!\n\n[COK4_18]\nI miei piedi sono bagnati! STIAMO IMBARCANDO ACQUA!\n\n[COK4_21]\nPonte in arrivo!\n\n[COK4_22]\nLanciati, sta per esplodere!\n\n[COK4_23]\nBel colpo!\n\n[COK4_29]\n~r~Hai ucciso Lance!\n\n[ASS1_6]\nVai Tommy, andrà tutto bene!\n\n[ASS1_7]\nBeccatevi questo, maledetti assassini!\n\n[ASS1_8]\nSono bloccato!\n\n[ASS1_9]\nTi copro io Tommy!\n\n[ASS1_10]\nEhi, questo sì che è un bel confine alberato.\n\n[ASS1_11]\nEhi Tommy, posso avere la stanza con la vista sulla baia?\n\n[ASS1_12]\nChe bel soffitto alto che c'è qui...\n\n[ASS1_3]\nLance! Ho bisogno di copertura!\n\n[ASS1_5]\nLance!\n\n[ASS1_15]\n~g~Distruggi la dimora e uccidi Diaz!\n\n[ASS1_17]\n~g~Sono disponibili più strade all'interno della villa.\n\n[TAXWAR]\nMISSIONI GUERRA DEI TAXI\n\n[NOTAXI]\n~g~Hai bisogno di un taxi Kaufman per attivare questa missione.\n\n[TAXW1_5]\n~g~Devi avere un taxi Kaufman!\n\n[TAX2_4]\nForza, Tommy.\n\n[TAX2_5]\nRiempilo di botte!\n\n[TAX2_6]\nNon ha neppure il permesso.\n\n[TAX2_7]\nMaledetti servizi di limousine.\n\n[TAXW3_1]\n~g~Vai a prendere Mercedes.\n\n[RACE1]\n~g~3..2..1.. VIA VIA VIA!\n\n[RACE2]\n~g~3\n\n[RACE3]\n~g~2\n\n[RACE4]\n~g~1\n\n[RACE5]\n~g~VIA!\n\n[FIRST]\n~b~PRIMO\n\n[SECOND]\n~b~SECONDO\n\n[THIRD]\n~b~TERZO\n\n[FOURTH]\n~b~QUARTO\n\n[RACETM]\n~b~TEMPO DI GARA: ~1~:~1~\n\n[RACETM2]\n~b~TEMPO DI GARA: ~1~:0~1~\n\n[RACEFA]\n~r~Non sei riuscito a vincere la gara!\n\n[TEX1_5]\n~r~È riuscito a fuggire!\n\n[SEG3_1]\nTEMPO:\n\n[SEG3_2]\n~g~Raggiungi il van che contiene il Raider radiocomandato e le bombe a tempo.\n\n[SEG3_3]\n~g~Devi utilizzare il RAIDER RADIOCOMANDATO per trasportare le 4 bombe nelle 4 aree bersaglio all'interno del cantiere.\n\n[SERG3_5]\n~g~Puoi trasportare solo una bomba alla volta e non puoi raccogliere dell'esplosivo correttamente posizionato.\n\n[SEG3_7]\n~g~Una volta posizionata la PRIMA bomba con successo su di un bersaglio, partirà il conto alla rovescia, dovrai piazzare tutti gli esplosivi entro il tempo limite.\n\n[SEG3_8]\n~g~Le 4 bombe devono essere tutte posizionate su ognuno dei bersagli per passare la missione e demolire l'edificio.\n\n[SEG3_9]\n~g~Bomba piazzata! Ancora 3.\n\n[SEG3_10]\n~g~Bomba piazzata! Ancora 2.\n\n[SEG3_11]\n~g~Bomba piazzata! Ne manca una sola.\n\n[SEG3_12]\n~g~Bomba NON piazzata! Recupera l'esplosivo!\n\n[SEG3_13]\n~g~Piazza la bomba nella zona bersaglio.\n\n[SEG3_14]\n~r~Tempo esaurito: hai fallito nel demolire l'edificio.\n\n[SEG3_15]\n~r~Il Raider radiocomandato è stato distrutto! Come farai adesso a trasportare le bombe?\n\n[AVERY]\nMISSIONI DI AVERY\n\n[ASM]\nMISSIONI DA SICARIO\n\n[ASM_1]\nMISSIONE DA SICARIO 1\n\n[ASM1_1]\n~g~Mr. Teal, il tuo aiuto nello sradicare gli stranieri è stato inestimabile per il nostro lavoro. Ho un altro lavoro con un contatto più 'diretto'. I dettagli sono stati attaccati sotto al telefono.\n\n[ASM1_2]\n~g~Raggiungi il telefono pubblico presso il Mall in Washington Beach.\n\n[ASM1_3]\n~g~Carl Pearson, fattorino di una pizzeria. Non deve completare le sue consegne.\n\n[ASM1_4]\n~g~Uccidi il fattorino prima che possa completare le sue consegne.\n\n[ASM_2]\nMISSIONE DA SICARIO 2\n\n[ASM_3]\nMISSIONE DA SICARIO 3\n\n[ASM3_A]\nMarcus Hammond, Franco Carter, Dick Tanner, Nick Kong e Stuntman Driver fanno tutti parte di un'associazione europea che si sta preparando a commettere una rapina.\n\n[ASM3_B]\nSi trovano tutti nella loro posizione pronti all'azione. Voglio che vengano tutti eliminati prima che inizi il colpo. Ho disposto delle utili armi nei paraggi.\n\n[ASM3_1]\n~g~Recupera le armi che Mr. Black ha lasciato per te.\n\n[ASM3_2]\n~g~Non avvicinarti troppo, se no il bersaglio potrebbe vederti.\n\n[ASM3_3]\n~g~Per un'eliminazione più rapida, colpisci da una locazione vicino alle loro postazioni ed evita di farti vedere.\n\n[ASM3_4]\n~g~Ti ha visto! Fallo fuori il prima possibile!\n\n[ASM3_5]\n~g~Marcus Hammond si trova presso dei cartelli pubblicitari in Washington.\n\n[ASM3_6]\n~g~Franco Carter si trova presso la DBP Security vicino a Ocean Drive.\n\n[ASM3_7]\n~g~Dick Tanner si trova presso la gioielleria in Vice Point.\n\n[ASM3_8]\n~g~Nick Kong si trova presso Washington Beach.\n\n[ASM3_9]\n~g~Stuntman Driver si trova presso Washington Beach.\n\n[ASM3_10]\n~r~Non sei riuscito a eliminarli tutti quanti.\n\n[ASM_4]\nMISSIONE DA SICARIO 4\n\n[ASM4_1]\n~g~Recupera il fucile che ti abbiamo lasciato tra le foglie presso il terminal dell'aeroporto.\n\n[ASM4_2]\n~g~Non mancare il bersaglio o allarmerai le sue guardie del corpo: ricorda di tenere una certa distanza per evitare di essere visto.\n\n[ASM4_3]\n~g~Osserva la donna sul balcone sopra ai banconi del check-in dentro il terminal. NON UCCIDERLA.\n\n[ASM4_4]\n~g~Elimina l'uomo a cui passa la valigetta ma solo DOPO CHE L'AVRÀ RACCOLTA. Poi recupera la valigetta e portala ad Ammu-Nation in Downtown.\n\n[ASM4_5]\n~g~Recupera la valigetta!\n\n[ASM4_6]\n~g~Porta la valigetta ad Ammu-Nation in Downtown\n\n[ASM4_7]\n~r~Hai ucciso la donna, idiota!\n\n[ASM4_8]\n~r~Il bersaglio ha sentito il colpo d'arma da fuoco! L'accordo è saltato!\n\n[ASM4_9]\n~r~Il bersaglio è salito a bordo del volo!\n\n[ASM4_10]\n~g~Sembra tu non sia l'unico interessato alla valigetta! Portala in fretta ad Ammu-Nation!\n\n[ASM4_11]\n~r~Il bersaglio ti ha visto! L'accordo è saltato!\n\n[ASM4_13]\n~g~Ti ha visto e sta scappando! Uccidilo e recupera la valigetta!\n\n[ASM4_14]\n~g~L'indicatore della distanza nella parte superiore destra dello schermo ti tiene informato sulla distanza dal bersaglio. Se si riempirà, verrai avvistato.\n\n[ASM_5]\nMISSIONE DA SICARIO 5\n\n[KICK]\nKICKSTART\n\n[KICK1_3]\n~g~Numero di volte che hai appoggiato i piedi: ~1~\n\n[KICK1_4]\n~g~Penalità: ~1~ secondi\n\n[BANK]\nMISSIONI RAPINA\n\n[BANK1]\nMISSIONE RAPINA 1\n\n[BANK2]\nMISSIONE RAPINA 2\n\n[BJM2_3]\nPERCENTUALE DI CENTRI: ~1~%\n\n[BJM2_15]\nPUNTEGGIO:\n\n[BJM2_18]\nPUNTEGGIO DA BATTERE:\n\n[BJM2_19]\n~g~Colpisci il maggior numero di bersagli entro il tempo limite!\n\n[BJM2_21]\n~g~Colpisci il maggior numero di bersagli finché hai ancora colpi.\n\n[BANK3]\nMISSIONE RAPINA 3\n\n[BJM3_1]\n~g~Trova una macchina da corsa e posizionati sulla griglia di partenza.\n\n[BNK4_2A]\nI ragazzi dell'officina hanno fatto un ottimo lavoro su questa piccola.\n\n[BNK4_3G]\nOmmerda, abbiamo la polizia alle calcagna!\n\n[BNK4_3H]\n...e non siamo ancora neanche arrivati.\n\n[BNK4_3K]\nDobbiamo seminare prima la polizia...\n\n[BNK4_3L]\nCristo Tommy, stai cercando di farci fuori?\n\n[BNK4_3N]\nTutto ciò che amo finisce a pezzi!\n\n[BNK422A]\nCam, quanto tempo?\n\n[BK4_23A]\nMi bastano 3 minuti!\n\n[BNK4_26]\nMaledizione! Ecco che arrivano!\n\n[BNK4_32]\nUsa l'esplosivo per aprire le cassette di sicurezza!\n\n[BNK4_43]\nVi copro io il culo, PARTI!\n\n[BNK4_51]\nA me sembri a posto.\n\n[KENT]\nMISSIONI DI KENT PAUL\n\n[KENT1]\nMISSIONE DI KENT PAUL 1\n\n[COUNT]\nMISSIONI DI FALSIFICAZIONE\n\n[COUNT1]\nMISSIONE DI FALSIFICAZIONE 1\n\n[COUNT2]\nMISSIONE DI FALSIFICAZIONE 2\n\n[BIKE]\nMISSIONI DEI MOTOCICLISTI\n\n[BIKE1]\nMISSIONE DEI MOTOCICLISTI 1\n\n[BIKE2]\nMISSIONE DEI MOTOCICLISTI 2\n\n[BIKE3]\nMISSIONE DEI MOTOCICLISTI 3\n\n[GOAWAY1]\nRitorna quando avrai completato le missioni per la gang di Haiti.\n\n[HAIT]\nMISSIONI DEGLI HAITIANI\n\n[HAIT1]\nMISSIONE DEGLI HAITIANI 1\n\n[HAIT2]\nMISSIONE DEGLI HAITIANI 2\n\n[HAIT3]\nMISSIONE DEGLI HAITIANI 3\n\n[HAM3_6]\n~g~Utilizza il fucile di precisione che ti ho lasciato per completare la missione.\n\n[ROCK]\nMISSIONI DELLA BAND\n\n[ROK1_4]\n~g~OK, credo tu stessi cercando questo...\n\n[ROK1_1E]\n~g~Ti costerà di più di quanto hai!\n\n[ROK1_1F]\n~g~Ritorna quando avrai i soldi.\n\n[RBM2_6]\n~g~Wow! È un uomo, bloccalo!\n\n[ROCK3]\nMISSIONE DELLA BAND 3\n\n[ROK3_6D]\n~r~insieme alle vostre GROSSE TESTE DA CAPELLONI!\n\n[ROK3_40]\nVicino al fottuto minibar?\n\n[RBM3_5]\n~g~Porta i Love Fist allo spettacolo.\n\n[CUBANM]\nMISSIONI DEI CUBANI\n\n[CUBAN1]\nMISSIONE DEI CUBANI 1\n\n[CUBAN2]\nMISSIONE DEI CUBANI 2\n\n[CUB2_10]\n~r~Dovresti uccidere gli Haitiani, non i Cubani.\n\n[CUBAN3]\nMISSIONE DEI CUBANI 3\n\n[CUBAN4]\nMISSIONE DEI CUBANI 4\n\n[CUB4_05]\n~r~Ti avevo detto di restare in macchina! Adesso non riusciremo mai a entrare!\n\n[CUB4_25]\nOK, andiamo.\n\n[PROT]\nMISSIONI DI PROTEZIONE\n\n[PRO1_H]\nPerché non ti calmi per un secondo, sto finalmente cominciando a capire come funzionano le cose da queste parti.\n\n[PRO1_02]\n~g~Esci dal Mall.\n\n[PRO3_06]\n~g~Fai perdere le tracce.\n\n[PORN]\nMISSIONI PORNOGRAFIA\n\n[PORN1]\nMISSIONE PORNOGRAFIA 1\n\n[POR1_03]\n~r~Candy è morta!\n\n[PORN2]\nMISSIONE PORNOGRAFIA 2\n\n[PORN3]\nMISSIONE PORNOGRAFIA 3\n\n[POR3_18]\nSei stato visto!\n\n[PORN4]\nMISSIONE PORNOGRAFIA 4\n\n[POR4_04]\n~g~Gli uffici sono dall'altra parte di questo cancello.\n\n[PHIL]\nMISSIONI DI PHIL\n\n[PHIL1]\nMISSIONE DI PHIL 1\n\n[PHI1_06]\nMa che combini, come diavolo guidi?\n\n[PHI1_07]\nEhi!\n\n[PHIL2]\nMISSIONE DI PHIL 2\n\n[PIZ1_A]\nMISSIONE RECAPITO PIZZE\n\n[PIZ1_03]\n~g~Ritorna alla pizzeria e prendi le nuove ordinazioni.\n\n[PIZ1_04]\n~g~Ecco le nuove ordinazioni.\n\n[PIZ1_10]\nPremi il ~h~tasto R3~w~ per annullare la missione.\n\n[CNTBUY1]\nTipografia acquistata: ~1~$\n\n[CARBUY]\nConcessionario acquistato: ~1~$\n\n[PORNBUY]\nStudio cinematografico acquistato: ~1~$\n\n[ICEBUY]\nFabbrica di gelato acquistata: ~1~$\n\n[TAXIBUY]\nCompagnia di taxi acquistata: ~1~$\n\n[BANKBUY]\nMalibu acquistato: ~1~$\n\n[BOATBUY]\nCantiere navale acquistato: ~1~$\n\n[PRNT_NO]\nNon puoi ancora comprare la tipografia, prova più tardi.\n\n[CAR_NO]\nNon puoi ancora comprare il concessionario, prova più tardi.\n\n[PORN_NO]\nNon puoi ancora comprare lo studio cinematografico, prova più tardi.\n\n[ICE_NO]\nNon puoi ancora comprare la fabbrica di gelato, prova più tardi.\n\n[TAXI_NO]\nNon puoi ancora comprare la compagnia di taxi, prova più tardi.\n\n[BANK_NO]\nNon puoi ancora comprare il Malibu, prova più tardi.\n\n[BOAT_NO]\nNon puoi ancora comprare il cantiere navale, prova più tardi.\n\n[PRNT_R3]\nPremi il tasto R3 per acquistare la tipografia per ~1~$\n\n[CAR_R3]\nPremi il tasto R3 per acquistare il concessionario per ~1~$\n\n[PORN_R3]\nPremi il tasto R3 per acquistare lo studio cinematografico per ~1~$\n\n[ICE_R3]\nPremi il tasto R3 per acquistare la fabbrica di gelato per ~1~$\n\n[TAXI_R3]\nPremi il tasto R3 per acquistare la compagnia di taxi per ~1~$\n\n[BANK_R3]\nPremi il tasto R3 per acquistare il Malibu per ~1~$\n\n[BOAT_R3]\nPremi il tasto R3 per acquistare il cantiere navale per ~1~$\n\n[COL2_6]\nFermo, brutto maiale imperialista americano!\n\n[COL2_6B]\nQuesta è proprietà del governo francese.\n\n[COL2_6C]\nÈ finita!\n\n[COL3_A]\nThomas, grazie per essere venuto.\n\n[COL3_B]\nScusami se giungo subito al punto.\n\n[COL3_C]\nDiaz mi ha chiesto di sovrintendere una piccola transizione di lavoro.\n\n[COL3_D]\nSperiamo vada meglio dell'ultima...\n\n[COL3_E]\nEd è per questo che ho pensato a te, amico.\n\n[COL3_F]\nHo lasciato un po' di supporto al parcheggio multipiano.\n\n[COL3_G]\nRaccogli il materiale, poi raggiungi e sorveglia gli uomini di Diaz all'incontro.\n\n[COL4_2]\nNon so signore!\n\n[COL4_5]\nSignorsì, signore!\n\n[COL4_10]\nAndiamo a prendere delle ciambelle.\n\n[COL4_16]\nSignore! Sposto il veicolo, signore!\n\n[COL4_25]\nAutodistruzione del veicolo attivata!\n\n[COL5_6]\nMercedes, quella ragazza sarà la mia rovina.\n\n[COL5_8]\nMaledetti scarafaggi!\n\n[COL5_5]\nMorite, maiali Francesi!\n\n[CNT2_1]\nUccidetelo\n\n[CNT2_2]\nRecuperate le matrici!\n\n[CNT2_3]\nProteggete il corriere.\n\n[FINKILL]\nOK ragazzi, uccidetelo!\n\n[FIN_6]\nSonny è interessato alla mia cassaforte e ai miei soldi...\n\n[FIN_10]\nSonny? SONNY! Sto venendo a prenderti!\n\n[RACES_4]\n3\n\n[RACES_5]\n2\n\n[RACES_6]\n1\n\n[RACES_7]\nVIA!\n\n[RACES_9]\nTempo: ~1~:~1~\n\n[RACES]\nTEMPO:\n\n[RACES17]\nNuovo miglior tempo: ~1~:~1~\n\n[RACES20]\nNuovo miglior tempo: ~1~:0~1~\n\n[RACES21]\nTempo: ~1~:0~1~\n\n[RCH1_1]\n~g~Usa l'elicottero radiocomandato, il Raider, per PASSARE ATTRAVERSO i punti di controllo.\n\n[RCH1_2]\n~g~I punti di controllo sono sparsi per tutto l'aeroporto.\n\n[RCH1_3]\n~g~Hai ~c~8 MINUTI~g~ per attraversarli tutti e ~c~20~g~!\n\n[RCH1_5]\nTempo\n\n[RCRC1_1]\n~g~Sfida nella GARA A TAPPE altri 3 Bandit radiocomandati su 2 GIRI.\n\n[RCRC1_2]\n~g~Raggiungi subito la griglia di partenza!\n\n[RCRC1_3]\n~g~Giro finale!\n\n[RCRC1_4]\n~g~3\n\n[RCRC1_5]\n~g~2\n\n[RCRC1_6]\n~g~1\n\n[RCRC1_7]\n~g~VIA!\n\n[RCRC1_8]\n~g~Tempo di gara: ~1~ secondi\n\n[RCPL1_1]\n~g~Sfida nella GARA A TAPPE altri 3 Baron radiocomandati.\n\n[RCPL1_2]\n~g~Devi attraversare la ~o~CORONA CENTRALE~g~ per passare con successo un punto di controllo.\n\n[RCPL1_3]\n~g~Raggiungi subito la griglia di partenza!\n\n[FEA_2SP]\n2 altoparlanti\n\n[FEA_4SP]\nPiù di 2 altoparlanti\n\n[FEA_EAR]\nCuffie\n\n[FEA_NAH]\nNESSUNA PERIFERICA AUDIO\n\n[FET_APP]\nAPPLICA\n\n[FES_SKN]\nNOME SKIN\n\n[FES_DAT]\nDATA\n\n[FES_SET]\nUsa skin\n\n[FET_DEF]\nRipristina predefiniti\n\n[FESZ_QZ]\nSei sicuro di voler salvare la partita?\n\n[FES_SCG]\nSalvare la partita?\n\n[FES_LCG]\nVuoi caricare e continuare la partita?\n\n[FEC_FIR]\nFuoco\n\n[FEC_NWE]\nArma successiva\n\n[FEC_PWE]\nArma precedente\n\n[FEC_FOR]\nAvanti\n\n[FEC_BAC]\nIndietro\n\n[FEC_LEF]\nSinistra\n\n[FEC_RIG]\nDestra\n\n[FEC_ZIN]\nIngrandisci\n\n[FEC_ZOT]\nRiduci\n\n[FEC_EEX]\nEntra o esci\n\n[FEC_RAD]\nRadio\n\n[FEC_SUB]\nSottomissione\n\n[FEC_CMR]\nCambia visuale\n\n[FEC_JMP]\nSalto\n\n[FEC_SPN]\nScatto\n\n[FEC_HND]\nFreno a mano\n\n[FEC_LOL]\nSguardo a sinistra\n\n[FEC_LOR]\nSguardo a destra\n\n[FEC_NTR]\nBersaglio successivo\n\n[FEC_PTT]\nBersaglio precedente\n\n[FEC_LBA]\nSguardo indietro\n\n[FEC_CEN]\nCentra visuale\n\n[FET_CCN]\nClassico\n\n[FET_SCN]\nPredefinito\n\n[FET_CFT]\nA PIEDI\n\n[FET_CCR]\nIN MACCHINA\n\n[FET_CAC]\nAZIONE\n\n[FEC_IBT]\n-\n\n[FEC_MXO]\nMXB1\n\n[FEC_MXT]\nMXB2\n\n[FEC_UNB]\nNON ASSEGNATO\n\n[FEC_TFL]\nSguardo+Torretta a SX\n\n[FEC_TFR]\nSguardo+Torretta a DX\n\n[FEC_MWF]\nVOLANTE SU\n\n[FEC_MWB]\nVOLANTE GIÙ\n\n[FEC_ORR]\no\n\n[FEC_NUS]\nNON USATO\n\n[FEC_LUD]\nSguardo su\n\n[FEC_LDU]\nSguardo giù\n\n[FEC_CMP]\nCOMBO: SGUARDO SX+DX\n\n[LAW_1A]\nlaw_1a\n\n[LAW_1B]\nlaw_1b\n\n[LAW_2A]\nlaw_2a\n\n[LAW_2B]\nlaw_2b\n\n[FEH_STA]\nSTATISTICHE\n\n[FEH_LOA]\nCARICA\n\n[FEH_CON]\nCOMANDI\n\n[FEH_AUD]\nAUDIO\n\n[FEH_DIS]\nVIDEO\n\n[FEH_LAN]\nLINGUA\n\n[FEH_SGA]\nNUOVA PARTITA\n\n[FEO_CON]\nImpostazioni controller\n\n[FEO_AUD]\nImpostazioni audio\n\n[FEO_DIS]\nImpostazioni video\n\n[FEO_LAN]\nImpostazioni lingua\n\n[FEO_PLA]\nImpostazioni giocatore\n\n[FEA_OUT]\nUscita\n\n[FEA_ST]\nStereo\n\n[FEA_DTS]\nDTS\n\n[FEA_RSS]\nStazione radio\n\n[FEA_NON]\nNO RADIO\n\n[FEA_FM0]\nWILDSTYLE\n\n[FEA_FM1]\nFLASH FM\n\n[FEA_FM2]\nKCHAT\n\n[FEA_FM3]\nFEVER 105\n\n[FEA_FM4]\nVROCK\n\n[FEA_FM5]\nVCPR\n\n[FEA_FM7]\nEMOTION 98.3\n\n[FEA_FM8]\nWAVE 103\n\n[FED_BRI]\nLuminosità\n\n[FED_TRA]\nTracce :\n\n[FED_SUB]\nSottotitoli\n\n[FED_WIS]\nPanoramico\n\n[FED_POS]\nPosizione schermo\n\n[FEP_RES]\nRiprendi\n\n[FEP_STG]\nAvvia partita\n\n[FEP_STA]\nStatistiche\n\n[FEP_BRI]\nBriefing\n\n[FEP_OPT]\nOpzioni\n\n[FEP_QUI]\nEsci\n\n[FES_LOA]\nCarica partita\n\n[FES_DEL]\nElimina partita\n\n[FEC_CSU]\nImpostazioni controller\n\n[FEC_RED]\nRidefinisci comandi\n\n[FEC_MOU]\nImpostazioni mouse\n\n[DISTGOL]\nDistanza percorsa su cart da golf (miglia)\n\n[DISTGOM]\nDistanza percorsa su cart da golf (metri)\n\n[ST_FAVR]\nStazione radio preferita\n\n[ST_WSTR]\nStazione radio meno amata\n\n[ST_FAVV]\nVeicolo preferito\n\n[ST_STAR]\nTotale stelle di sospetto\n\n[ST_HEAD]\nColpi alla testa\n\n[ST_GANG]\nGang meno amata\n\n[ST_STGN]\nTotale stelle di sospetto evase\n\n[TYREPOP]\nPneumatici esplosi con proiettili\n\n[TYRESLA]\nPneumatici tagliati con una lama\n\n[ST_BRK]\nNumero di uccisioni nel Bloodring\n\n[ST_LTBR]\nPermanenza massima nel Bloodring (sec)\n\n[ST_GNG1]\nCubani\n\n[ST_GNG2]\nHaitiani\n\n[ST_GNG3]\nTeppistelli\n\n[ST_GNG4]\nGang di Diaz\n\n[ST_GNG5]\nSorveglianza\n\n[ST_GNG6]\nGang di motociclisti\n\n[ST_GNG7]\nGang di Vercetti\n\n[ST_GNG8]\nGiocatori di golf\n\n[FEA_FM6]\nESPANTOSO\n\n[ST_ASSI]\nContratti da sicario completati\n\n[DISTBIK]\nDistanza percorsa in moto (miglia)\n\n[DISTBIM]\nDistanza percorsa in moto (metri)\n\n[HOTEL]\nHotel Ocean View\n\n[ICC1_1]\n~g~Utilizza il camioncino dei gelati per distribuire droga in Vice City.\n\n[ICC1_2]\n~g~Parcheggia il camioncino e premi ~h~~k~~VEHICLE_HORN~~w~ per attivare il campanello e attrarre i clienti.\n\n[ICC1_3]\n~g~Riceverai soldi per ogni transizione, ma più ne esegui, maggiori saranno le probabilità di attirare l'attenzione della polizia.\n\n[KICK1_9]\nPUNTI DI CONTROLLO RIMANENTI:\n\n[FIN_B6]\nNon hai abbastanza soldi per avviare questa missione.\n\n[TEX3_3]\n~g~Per raccogliere una bomba, avvicinati con l'elicottero: la bomba verrà automaticamente raccolta.\n\n[TEX3_9]\n~g~Raccogli una bomba avvicinandole l'elicottero.\n\n[HELP22]\nRaggiungi la casa verde sul radar.\n\n[FES_FMS]\nFormattazione completata. Seleziona OK per continuare.\n\n[FES_SSC]\nSalvataggio completato. Seleziona OK per continuare.\n\n[FES_DSC]\nEliminazione completata. Seleziona OK per continuare.\n\n[FESZ_QC]\nVuoi sovrascrivere il salvataggio corrotto?\n\n[FES_CHE]\nAttenzione! Uno o più trucchi sono stati attivati: ciò influenzerà il salvataggio. Si consiglia di non salvare questa partita.\n\n[FET_SG]\nSALVA PARTITA\n\n[FEH_BRI]\nBRIEFING\n\n[FEH_MAP]\nMAPPA\n\n[FEM_OK]\nOK\n\n[FEC_CRO]\nAbbassarsi\n\n[FEC_CR3]\nAbbassarsi (tasto L3)\n\n[FEC_SMT]\nSottomissione\n\n[FEC_SM3]\nSottomissione (tasto R3)\n\n[FEC_RSC]\nStazioni radio\n\n[ST_PR01]\nApprendista\n\n[ST_PR02]\nAviere\n\n[ST_PR03]\nUfficiale\n\n[ST_PR04]\nCaporale\n\n[ST_PR05]\nTenente\n\n[ST_PR06]\nSergente\n\n[ST_PR07]\nCapitano\n\n[ST_PR08]\nBiggs\n\n[ST_PR09]\nWedge\n\n[ST_PR10]\nBarone rosso\n\n[ST_PR11]\nGoose\n\n[ST_PR12]\nViper\n\n[ST_PR13]\nJester\n\n[ST_PR14]\nChappy\n\n[ST_PR15]\nIceman\n\n[ST_PR16]\nMaverick\n\n[ST_PR17]\nNoops\n\n[ST_PR18]\nMaresciallo\n\n[ST_PR19]\nAsso\n\n[FET_LG]\nCARICA PARTITA\n\n[CAR_EXP]\nVeicoli distrutti\n\n[BOA_EXP]\nImbarcazioni distrutte\n\n[HEL_DST]\nVelivoli distrutti\n\n[STFT_01]\nTempo migliore in 'Due ruote d'acciaio'\n\n[STFT_02]\nTempo migliore in 'L'autista'\n\n[STFT_03]\nTempo migliore nella prova del fango\n\n[STFT_04]\nTempo migliore con gli aerei radiocomandati\n\n[STFT_05]\nTempo migliore con le macchine radiocomandate\n\n[STFT_06]\nTempo migliore di raccolta con l'elicottero\n\n[STFT_07]\nTempo migliore in 'Terminal Velocity'\n\n[STFT_08]\nTempo migliore in 'Ocean Drive'\n\n[STFT_09]\nTempo migliore in 'Border Run'\n\n[STFT_10]\nTempo migliore in 'Capital Cruise'\n\n[STFT_11]\nTempo migliore in 'Tour!'\n\n[STFT_12]\nTempo migliore in 'V.C. Endurance'\n\n[STHC_01]\nPunteggio migliore al poligono\n\n[STHC_02]\nMiglior percentuale di colpi al poligono\n\n[STHC_03]\nNumero di traffici di droga\n\n[HELP24]\nAdesso puoi accettare le missioni del Colonnello.\n\n[HELP25]\nAdesso puoi accettare le missioni di Avery Carrington.\n\n[HELP29]\nPuoi far visita al negozio di abbigliamento quando non sei in missione.\n\n[HELP30]\nQuando compri nuovi abiti, il tuo livello di sospetto scenderà a zero.\n\n[BJM2_22]\n~r~Sei uscito dal poligono di tiro!\n\n[BJM2_23]\n~g~Se esci dal poligono di tiro durante la competizione, fallirai la missione.\n\n[ASM4_24]\nDistanza:\n\n[RBM1_6]\n~g~Porta Mercedes e la 'Love Juice' al gruppo nello studio di registrazione.\n\n[RBM1_3]\nNON NECESSARIO\n\n[HAM1_5]\nNON NECESSARIO\n\n[RBM1_11]\nNON NECESSARIO\n\n[HELP31]\nPer eseguire un assalto in macchina, guarda a destra o a sinistra premendo il tasto L2 o il tasto R2.\n\n[HELP34]\nHai bisogno di una mitragliatrice per eseguire un assalto in macchina.\n\n[STRIP_1]\n~r~Soldi insufficienti, brutto idiota.\n\n[EXIT_1]\nPremi ~k~~PED_SPRINT~ per uscire.\n\n[ASM1_A]\nMr. Teal, il tuo aiuto nello sradicare gli stranieri è stato inestimabile per il nostro lavoro. Ho un altro compito con un contatto più 'diretto'.\n\n[ASM1_B]\nI dettagli per il prossimo colpo sono stati attaccati sotto al telefono.\n\n[ASM1_C]\nHo un altro compito con un contatto più 'diretto'.\n\n[SCARF]\nAppartamento 3c\n\n[LAW4_10]\nLa ricca amministrazione ci ha rotto!\n\n[GEN1_04]\n~g~Attraversa la porta per accedere alla piattaforma sul tetto di Gonzalez.\n\n[GEN1_17]\n~g~Gonzalez sta fuggendo! Seguilo attraverso le porte e finiscilo!\n\n[RCH1_9]\n~b~TEMPO TOTALE: ~1~:~1~\n\n[RCH1_10]\n~b~TEMPO TOTALE: ~1~:0~1~\n\n[WHEEL01]\nBONUS DOPPIO SU DUE RUOTE: ~1~$ Distanza: ~1~.~1~ m Tempo: ~1~ secondi\n\n[WHEEL02]\nBONUS DOPPIO SU DUE RUOTE: ~1~$ Distanza: ~1~ piedi Tempo: ~1~ secondi\n\n[WHEEL03]\nBONUS SU DUE RUOTE: ~1~$ Tempo: ~1~ secondi\n\n[WHEEL04]\nBONUS SU DUE RUOTE: ~1~$ Distanza: ~1~.~1~ m\n\n[WHEEL05]\nBONUS SU DUE RUOTE: ~1~$ Distanza: ~1~ piedi\n\n[WHEEL06]\nBONUS IMPENNATA: ~1~$ Distanza: ~1~.~1~ m Tempo: ~1~ secondi\n\n[WHEEL07]\nBONUS IMPENNATA: ~1~$ Distanza: ~1~ piedi Tempo: ~1~ secondi\n\n[WHEEL08]\nBONUS IMPENNATA: ~1~$ Tempo: ~1~ secondi\n\n[WHEEL09]\nBONUS IMPENNATA: ~1~$ Distanza: ~1~.~1~ m\n\n[WHEEL10]\nBONUS IMPENNATA: ~1~$ Distanza: ~1~ piedi\n\n[WHEEL11]\nBONUS FRENATA IN PUNTA: ~1~$ Distanza: ~1~.~1~ m Tempo: ~1~ secondi\n\n[WHEEL12]\nBONUS FRENATA IN PUNTA: ~1~$ Distanza: ~1~ piedi Tempo: ~1~ secondi\n\n[WHEEL13]\nBONUS FRENATA IN PUNTA: ~1~$ Tempo: ~1~ secondi\n\n[WHEEL14]\nBONUS FRENATA IN PUNTA: ~1~$ Distanza: ~1~.~1~ m\n\n[WHEEL15]\nBONUS FRENATA IN PUNTA: ~1~$ Distanza: ~1~ piedi\n\n[ROK3_72]\nLove Fist!\n\n[POR1_19]\nEhi!\n\n[DESPERA]\nDesperado\n\n[MOB_99A]\nRaggiungi il telefono pubblico vicino al Mall in Washington.\n\n[MOB_98A]\nRaggiungi il telefono pubblico in Vice Point.\n\n[MOB_96A]\nRaggiungi il telefono pubblico al terminal dell'aeroporto.\n\n[MOB_95A]\nRaggiungi il telefono pubblico in Little Havana.\n\n[BNK1_1]\nLa posso aiutare, signore?\n\n[BNK1_2]\nUn impostore!\n\n[BNK1_3]\nÈ impazzito!\n\n[BNK1_4]\nMa chi diavolo sei?\n\n[BNK1_5]\nDov'è il tuo distintivo?\n\n[BNK1_6]\nEccoli là! Sparate per uccidere!\n\n[MOB_24A]\nSalve: Mr Vercetti?\n\n[MOB_24B]\nSì.\n\n[MOB_24C]\nSono Cortez. Eri invitato al mio party.\n\n[MOB_24D]\nSì, ricordo.\n\n[MOB_24E]\nMr. Vercetti, è stato davvero uno sfortunato incidente quello avvenuto al tuo accordo.\n\n[MOB_24F]\nLo so.\n\n[MOB_24G]\nSappi che io e la mia gente stiamo facendo il massimo per scoprire cosa è successo.\n\n[MOB_24H]\nSe vuoi parlarne in prima persona, mi troverai sulla mia barca. Buona giornata, senor.\n\n[BNK2_2]\nMIRARE 3-2-1 FUOCO!\n\n[BNK2_3]\nAREA RIPULITA!\n\n[BNK2_6]\nQuesto tipo è pazzo!\n\n[ANGEL]\nAngel\n\n[CUBJET]\nJetmax Cubano\n\n[SANDKIN]\nSandking\n\n[POLMAV]\nMaverick della polizia\n\n[BOXVILL]\nBoxville\n\n[BENSON]\nBenson\n\n[HOTRINA]\nHotring Racer\n\n[HOTRINB]\nHotring Racer\n\n[BLOODRA]\nBloodring Banger\n\n[BLOODRB]\nBloodring Banger\n\n[MAFIACR]\nCruiser della Mafia\n\n[COP_M2]\n'VICE SQUAD'\n\n[COP_M3]\n'BROWN THUNDER'\n\n[BJM2_20]\n~g~Quando finisci il ~w~tempo~g~ o i ~w~colpi~g~, il turno è finito!\n\n[BNK3_2]\nNon intendo guidare per te, per niente, e lo dirò ai miei compagni di terapia.\n\n[FEM_SL1]\nSalvataggio 1 non trovato\n\n[FEM_SL2]\nSalvataggio 2 non trovato\n\n[FEM_SL3]\nSalvataggio 3 non trovato\n\n[FEM_SL4]\nSalvataggio 4 non trovato\n\n[FEM_SL5]\nSalvataggio 5 non trovato\n\n[FEM_SL6]\nSalvataggio 6 non trovato\n\n[FEM_SL7]\nSalvataggio 7 non trovato\n\n[FEM_SL8]\nSalvataggio 8 non trovato\n\n[FEA_CHA]\nModifica uscita audio in STEREO. Attendere...\n\n[FEA_CHD]\nAttenzione! Modifica uscita audio da STEREO a DTS. Attendere...\n\n[FEI_SEL]\nSeleziona\n\n[FEI_BAC]\nIndietro\n\n[FEI_RES]\nRiprendi\n\n[FEI_NAV]\nNaviga\n\n[FEI_BTX]\nTasto / -\n\n[FEI_BTT]\nTasto \" -\n\n[FEI_STA]\nTasto START -\n\n[FEI_BTD]\n; = > < -\n\n[FEI_STO]\nStop\n\n[MOB_68A]\nEhi Tommy, ho una sorpresa per te.\n\n[MOB_68B]\nSono allo studio cinematografico con dei grandi artisti.\n\n[MOB_68C]\nPerché non vieni a farci visita?\n\n[MOB_68D]\nLo sai che è una buona idea, vero? Ci vediamo.\n\n[OUTFT1]\nDa strada\n\n[OUTFT2]\nEleganti\n\n[OUTFT3]\nTuta\n\n[OUTFT4]\nSportivo\n\n[OUTFT5]\nHavana\n\n[OUTFT6]\nDa poliziotto\n\n[OUTFT7]\nDa rapina\n\n[OUTFT8]\nCasual\n\n[OUTFT9]\nMr. Vercetti\n\n[OUTFT10]\nDa corsa\n\n[OUTFT13]\nMC Tommy\n\n[HOTR_07]\nNuovo miglior tempo: ~1~:0~1~\n\n[HOTR_08]\nTempo: ~1~:~1~\n\n[GEN3_45]\nArriveranno fra pochi minuti: troviamo un buon punto dove appostarci...\n\n[CAR_AS1]\nBENI CONCESSIONARIA ACQUISITI\n\n[CAR_AS2]\n~g~La concessionaria d'ora in poi genererà introiti per un massimo di ~1~$. Ricordati di recuperarli regolarmente.\n\n[BUYSAVE]\n~g~Se non sei in missione, potrai ora salvare la partita da qui gratuitamente.\n\n[BUYGARG]\n~g~Potrai anche depositare i mezzi in questo garage.\n\n[STRPBUY]\nClub Pole Position acquistato: ~1~$\n\n[STRP_R3]\nPremi il tasto R3 per acquistare il club Pole Position per ~1~$\n\n[NBMN_R3]\nPremi il tasto R3 per acquistare Elswanko Casa per ~1~$\n\n[GA_4]\nLe bombe per le macchine costano 1000$\n\n[GA_5]\nLa tua macchina ha già una bomba installata.\n\n[GA_6] { reVC update }\nParcheggiala, attivala premendo il ~h~~k~~VEHICLE_FIREWEAPON~~w~ e DATTELA A GAMBE!\n\n[GA_7] { reVC update }\nArma la bomba con il ~h~~k~~VEHICLE_FIREWEAPON~~w~: esploderà non appena qualcuno cercherà di avviarla.\n\n[GA_6B] { reVC update }\nParcheggiala, attivala premendo il ~h~~k~~VEHICLE_FIREWEAPON~~w~ e DATTELA A GAMBE!\n\n[GA_7B] { reVC update }\nArma la bomba con il ~h~~k~~VEHICLE_FIREWEAPON~~w~: esploderà non appena qualcuno cercherà di avviarla.\n\n[MOB_70A]\nTommy, sono io, il Colonnello Cortez. Ascolta senor, credo tu sia una persona capace di risolvere i problemi.\n\n[MOB_70B]\nMi troverai sulla mia barca.\n\n[PICK1]\nGiubbotto antiproiettile consegnato all'hotel Ocean View!\n\n[PICK2]\n.357 consegnato al nascondiglio!\n\n[PICK3]\nMotosega consegnata al nascondiglio!\n\n[PICK4]\nLanciafiamme consegnato al nascondiglio!\n\n[PICK5]\n.308 Fucile di precisione consegnato al nascondiglio!\n\n[PICK6]\nMitragliatore consegnato al nascondiglio!\n\n[PICK7]\nLanciamissili consegnato al nascondiglio!\n\n[PICK8]\nSea Sparrow adesso disponibile alla villa!\n\n[PICK9]\nCarro armato adesso disponibile alle caserme!\n\n[PICK10]\nHunter adesso disponibile alle caserme!\n\n[HELP41]\no puoi speronarli con il tuo mezzo\n\n[ICC1_6]\n~g~Utilizza il Mr. Whopee per distribuire i prodotti Cherry Poppers per Vice City.\n\n[ICC1_12]\nPROPRIETÀ ACQUISTATA!\n\n[CLOTH1]\nAbiti eleganti consegnati a Rafaels in Ocean Beach.\n\n[CLOTH2]\nAbiti da strada consegnati al nascondiglio.\n\n[CLOTH3]\nTuta consegnata a Tooled Up nel Mall North Point.\n\n[CLOTH4]\nAbiti sportivi consegnati al club di Golf in Leafs Links.\n\n[CLOTH5]\nAbiti havana consegnati a Little Havana Streetwear in Little Havana.\n\n[CLOTH6]\nAbiti da poliziotto consegnati alla stazione di polizia in Washington Beach.\n\n[CLOTH7]\nAbiti casual consegnati a Gash nel Mall North Point.\n\n[CLOTH8]\nAbiti Mr. Vercetti consegnati a Collar & Cuffs in Ocean Beach.\n\n[CLOTH9]\nAbiti da corsa consegnati a Jocksport in Downtown.\n\n[CLOTH10]\nAbiti da rapina consegnati al club Malibu in Vice Point.\n\n[RBM1_9]\n~g~Recupera della Love Juice dallo spacciatore per i Love Fist!\n\n[MOB_62A]\nTommy, sono Ricardo Diaz. Ti volevo ringraziare per l'aiuto ai miei uomini.\n\n[MOB_62B]\nHo chiesto a quel coglione di Cortez e mi ha detto che il vero affare sei tu. Amico, vienimi a trovare.\n\n[MOB_62C]\nHo bisogno di un tipo come te. Sono circondato da coglioni,\n\n[MOB_62D]\ncoglioni dappertutto, davvero. Ti farò diventare ricco.\n\n[GOAWAY2]\n~g~Ritorna quando avrai completato le missioni dei motociclisti.\n\n[COL2_9]\nIdiota di un americano! Ti sei fatto seguire!\n\n[LOADCOL]\nCaricamento...\n\n[STFT_17]\nTempo migliore in 'Parco divertimenti PCJ'\n\n[STFT_18]\nTempo migliore in 'Prova del fango'\n\n[STFT_19]\nTempo migliore in 'Tracciato di prova'\n\n[NEW_REC]\nNuovo record!!! ~1~ minuti e ~1~ secondi.\n\n[BMX_HOW]\n~g~Fai due giri sul tracciato sterrato, ~y~passando attraverso~g~ i ~y~PUNTI DI CONTROLLO~g~!\n\n[BMXREW1]\n~g~Ogni volta che batti il tuo record precedente per i due giri,\n\n[BMXREW2]\n~g~otterrai una ~y~RICOMPENSA~g~ più cospicua!\n\n[BMXRAIN]\n~g~È come se piovesse...\n\n[ITBEG]\nAll'inizio...\n\n[NBMNBUY]\nEl Swanko Casa acquistata: ~1~$\n\n[LNKVBUY]\nAppartamento Links View acquistato: ~1~$\n\n[HYCOBUY]\nCondominio Hyman acquistato: ~1~$\n\n[BUYGARS]\n~g~Puoi parcheggiare altri veicoli in questi garage.\n\n[OCHEBUY]\nAppartamento Ocean Heights acquistato: ~1~$\n\n[WASHBUY]\n1102 Washington Street acquistata: ~1~$\n\n[VCPTBUY]\n3321 Vice Point acquistata: ~1~$\n\n[SKUMBUY]\nSkumole Shack acquistato: ~1~$\n\n[HELP6_C]\nPremi il ~h~~k~~VEHICLE_HANDBRAKE~~w~ per tirare il freno a mano.\n\n[HELP2_A]\nPremi il ~h~~k~~PED_SPRINT~~w~ mentre corri per effettuare uno ~h~scatto~w~.\n\n[HELP4_A]\nPremi il ~h~~k~~VEHICLE_ACCELERATE~~w~ per ~h~accelerare~w~.\n\n[HELP5_A]\nPremi il ~h~~k~~VEHICLE_BRAKE~~w~ per frenare o, se il veicolo è fermo, per inserire la retromarcia.\n\n[HELP8_A]\nPremi il ~h~~k~~PED_SNIPER_ZOOM_IN~~w~ per zoomare col fucile e il ~x~tasto /~w~ per allargare il campo.\n\n[PBOAT_1] { reVC update }\nPremi il ~h~~k~~VEHICLE_FIREWEAPON~~w~ per sparare con i cannoni della barca.\n\n[SEG3_4] { reVC update }\n~g~Puoi raccogliere una bomba avvicinando il Raider telecomandato. Per posizionare la bomba, premi il ~h~~k~~VEHICLE_FIREWEAPON~.\n\n[RCR1_3] { reVC update }\n~g~Se desideri interrompere la missione, premi il ~h~~k~~VEHICLE_FIREWEAPON~~g~ per far esplodere la macchina.\n\n[HELP32] { reVC update }\nPoi spara con il ~h~~k~~VEHICLE_FIREWEAPON~~w~.\n\n[HELP33] { reVC update }\nPoi spara con il ~h~~k~~VEHICLE_FIREWEAPON~~w~.\n\n[TTUTOR]\nPremi il ~h~~k~~TOGGLE_SUBMISSIONS~~w~ per attivare o disattivare le missioni Taxi.\n\n[TTUTOR2]\nPremi il ~h~~k~~TOGGLE_SUBMISSIONS~~w~ per attivare o disattivare le missioni Taxi.\n\n[FTUTOR]\nPremi il ~h~~k~~TOGGLE_SUBMISSIONS~~w~ per attivare o disattivare le missioni Camion dei pompieri.\n\n[FTUTOR2]\nPremi il ~h~~k~~TOGGLE_SUBMISSIONS~~w~ per attivare o disattivare le missioni Camion dei pompieri.\n\n[CTUTOR]\nPremi il ~h~~k~~TOGGLE_SUBMISSIONS~~w~ per attivare o disattivare le missioni Vigilante.\n\n[CTUTOR2]\nPremi il ~h~~k~~TOGGLE_SUBMISSIONS~~w~ per attivare o disattivare le missioni Vigilante.\n\n[HELP8_B]\nPremi il ~h~~k~~PED_SNIPER_ZOOM_IN~~w~ per ~h~zoomare~w~ col fucile e il ~h~~k~~PED_SNIPER_ZOOM_OUT~~w~ per ~h~allargare~w~ il campo.\n\n[ATUTOR3]\nPremi il ~h~~k~~TOGGLE_SUBMISSIONS~~w~ per attivare o disattivare le missioni Infermiere.\n\n[GUN_H1]\n~w~Premi il ~h~~k~~PED_SPRINT~~w~ per comprare. ~w~Premi il ~h~~k~~VEHICLE_ENTER_EXIT~~w~ per uscire.\n\n[PU_CF3] { reVC update }\nPremi il ~h~~k~~PED_ANSWER_PHONE~~w~ per sostituire l'arma attuale con quella presente in questo slot.\n\n[PU_CF4] { reVC update }\nPremi il ~h~~k~~PED_ANSWER_PHONE~~w~ per sostituire l'arma attuale con quella presente in questo slot.\n\n[HELP9_B]\nPremi il ~h~~k~~PED_FIREWEAPON~~w~ per sparare con il fucile di precisione.\n\n[HELP37]\nSe non vuoi entrare in un veicolo mentre stai assalendo un guidatore, premi il ~h~~k~~PED_SPRINT~~w~.\n\n[HELP6_A]\nPremi il ~h~~k~~VEHICLE_HANDBRAKE~~w~ per tirare il freno a mano.\n\n[HELP6_D]\nPremi il ~h~~k~~VEHICLE_HANDBRAKE~~w~ per tirare il freno a mano.\n\n[HELP26]\nPremi il ~h~~k~~VEHICLE_ENTER_EXIT~~w~ per entrare o uscire da un veicolo.\n\n[HELP27]\nPremi il ~h~~k~~VEHICLE_TURRETUP~~w~ o ~h~~k~~VEHICLE_TURRETDOWN~~w~ per spostare il peso sulla moto.\n\n[HELP28]\nPremi il ~h~~k~~VEHICLE_TURRETUP~~w~ o ~h~~k~~VEHICLE_TURRETDOWN~~w~ per spostare il peso sulla moto.\n\n[HELP35]\nPremi il ~h~~k~~GO_LEFT~~w~ o la ~h~~k~~GO_RIGHT~~w~ per sterzare.\n\n[HELP36]\nPremi il ~h~~k~~GO_LEFT~~w~ o la ~h~~k~~GO_RIGHT~~w~ per sterzare.\n\n[HELP42]\nSegui il ~q~segnalino rosa~w~ per trovare l'hotel.\n\n[HELP19]\nCammina sul ~q~segnalino rosa~w~ per continuare.\n\n[HELP1]\nFermati al centro del ~q~segnalino rosa~w~.\n\n[HELP12]\nCammina nel centro del ~q~segnalino rosa~w~ per attivare una missione.\n\n[SEG3_6]\n~g~Per colpire con successo un bersaglio, devi sganciare la bomba nell'area con un ~q~segnalino rosa~g~. Puoi posizionare le bombe in un ordine qualsiasi.\n\n[S_PROMP]\nQuando non sei in missione, puoi salvare la partita raccogliendo il bonus ~h~audiocassetta~w~.\n\n[HELP16]\nPassa attraverso la porta principale dell'hotel ~h~Ocean View~w~ per entrare nell'edificio.\n\n[HELP43]\n~g~Raggiungi l'hotel ~h~Ocean View~g~ in Ocean Drive.\n\n[HELI_F1]\n~r~Gara a tappe con l'elicottero annullata!\n\n[AMMUHLP]\nSe hai bisogno di armi, fai un salto ad ~h~Ammu-Nation~w~. Segui il ~h~segnale a forma di pistola~w~ sul radar.\n\n[HELI_1]\nTappa elicottero Downtown\n\n[HELI_2]\nTappa elicottero Ocean Beach\n\n[HELI_3]\nTappa elicottero Vice Point\n\n[HELI_4]\nTappa elicottero Little Haiti\n\n[FST_MFR]\nStazione radio preferita\n\n[FST_LFR]\nStazione radio meno amata\n\n[FEI_HOL]\nTrattieni\n\n[FEI_ZOO]\nZoom\n\n[FEI_BTR]\n> < -\n\n[FEI_NA]\nN\\D\n\n[MESA]\nMesa Grande\n\n[STRP_NO]\nNon puoi ancora comprare il club a luci rosse, prova più tardi.\n\n[CHSE]\nINSEGUI\n\n[NBMN_L]\nPremi il ~h~~k~~PED_ANSWER_PHONE~~w~ per acquistare El Swanko Casa per ~1~$\n\n[NBMN_T]\nPremi il ~h~~k~~PED_ANSWER_PHONE~~w~ per acquistare El Swanko Casa per ~1~$\n\n[NBMN_C]\nPremi il ~h~~k~~PED_ANSWER_PHONE~~w~ per acquistare El Swanko Casa per ~1~$\n\n[LNKV_L]\nPremi il ~h~~k~~PED_ANSWER_PHONE~~w~ per acquistare l'appartamento Links View per ~1~$\n\n[LNKV_T]\nPremi il ~h~~k~~PED_ANSWER_PHONE~~w~ per acquistare l'appartamento Links View per ~1~$\n\n[LNKV_C]\nPremi il ~h~~k~~PED_ANSWER_PHONE~~w~ per acquistare l'appartamento Links View per ~1~$\n\n[HYCO_L]\nPremi il ~h~~k~~PED_ANSWER_PHONE~~w~ per acquistare il condominio Hyman per ~1~$\n\n[HYCO_T]\nPremi il ~h~~k~~PED_ANSWER_PHONE~~w~ per acquistare il condominio Hyman per ~1~$\n\n[HYCO_C]\nPremi il ~h~~k~~PED_ANSWER_PHONE~~w~ per acquistare il condominio Hyman per ~1~$\n\n[OCHE_L]\nPremi il ~h~~k~~PED_ANSWER_PHONE~~w~ per acquistare l'appartamento Ocean Heights per ~1~$\n\n[OCHE_T]\nPremi il ~h~~k~~PED_ANSWER_PHONE~~w~ per acquistare l'appartamento Ocean Heights per ~1~$\n\n[OCHE_C]\nPremi il ~h~~k~~PED_ANSWER_PHONE~~w~ per acquistare l'appartamento Ocean Heights per ~1~$\n\n[WASH_L]\nPremi il ~h~~k~~PED_ANSWER_PHONE~~w~ per acquistare 1102 Washington Street per ~1~$\n\n[WASH_T]\nPremi il ~h~~k~~PED_ANSWER_PHONE~~w~ per acquistare 1102 Washington Street per ~1~$\n\n[WASH_C]\nPremi il ~h~~k~~PED_ANSWER_PHONE~~w~ per acquistare 1102 Washington Street per ~1~$\n\n[VCPT_L]\nPremi il ~h~~k~~PED_ANSWER_PHONE~~w~ per acquistare 3321 Vice Point per ~1~$\n\n[VCPT_T]\nPremi il ~h~~k~~PED_ANSWER_PHONE~~w~ per acquistare 3321 Vice Point per ~1~$\n\n[VCPT_C]\nPremi il ~h~~k~~PED_ANSWER_PHONE~~w~ per acquistare 3321 Vice Point per ~1~$\n\n[SKUM_L]\nPremi il ~h~~k~~PED_ANSWER_PHONE~~w~ per acquistare lo Skumole Shack per ~1~$\n\n[SKUM_T]\nPremi il ~h~~k~~PED_ANSWER_PHONE~~w~ per acquistare lo Skumole Shack per ~1~$\n\n[SKUM_C]\nPremi il ~h~~k~~PED_ANSWER_PHONE~~w~ per acquistare lo Skumole Shack per ~1~$\n\n[PRNT_L]\nPremi il ~h~~k~~PED_ANSWER_PHONE~~w~ per acquistare la tipografia per ~1~$\n\n[PRNT_T]\nPremi il ~h~~k~~PED_ANSWER_PHONE~~w~ per acquistare la tipografia per ~1~$\n\n[PRNT_C]\nPremi il ~h~~k~~PED_ANSWER_PHONE~~w~ per acquistare la tipografia per ~1~$\n\n[CAR_L]\nPremi il ~h~~k~~PED_ANSWER_PHONE~~w~ per acquistare il concessionario per ~1~$\n\n[CAR_T]\nPremi il ~h~~k~~PED_ANSWER_PHONE~~w~ per acquistare il concessionario per ~1~$\n\n[CAR_C]\nPremi il ~h~~k~~PED_ANSWER_PHONE~~w~ per acquistare il concessionario per ~1~$\n\n[PORN_L]\nPremi il ~h~~k~~PED_ANSWER_PHONE~~w~ per acquistare lo studio cinematografico per ~1~$\n\n[PORN_T]\nPremi il ~h~~k~~PED_ANSWER_PHONE~~w~ per acquistare lo studio cinematografico per ~1~$\n\n[PORN_C]\nPremi il ~h~~k~~PED_ANSWER_PHONE~~w~ per acquistare lo studio cinematografico per ~1~$\n\n[ICE_L]\nPremi il ~h~~k~~PED_ANSWER_PHONE~~w~ per acquistare la fabbrica di gelato per ~1~$\n\n[ICE_T]\nPremi il ~h~~k~~PED_ANSWER_PHONE~~w~ per acquistare la fabbrica di gelato per ~1~$\n\n[ICE_C]\nPremi il ~h~~k~~PED_ANSWER_PHONE~~w~ per acquistare la fabbrica di gelato per ~1~$\n\n[TAXI_L]\nPremi il ~h~~k~~PED_ANSWER_PHONE~~w~ per acquistare la compagnia di taxi per ~1~$\n\n[TAXI_T]\nPremi il ~h~~k~~PED_ANSWER_PHONE~~w~ per acquistare la compagnia di taxi per ~1~$\n\n[TAXI_C]\nPremi il ~h~~k~~PED_ANSWER_PHONE~~w~ per acquistare la compagnia di taxi per ~1~$\n\n[BANK_L]\nPremi il ~h~~k~~PED_ANSWER_PHONE~~w~ per acquistare il Malibu per ~1~$\n\n[BANK_T]\nPremi il ~h~~k~~PED_ANSWER_PHONE~~w~ per acquistare il Malibu per ~1~$\n\n[BANK_C]\nPremi il ~h~~k~~PED_ANSWER_PHONE~~w~ per acquistare il Malibu per ~1~$\n\n[BOAT_L]\nPremi il ~h~~k~~PED_ANSWER_PHONE~~w~ per acquistare il cantiere navale per ~1~$\n\n[BOAT_T]\nPremi il ~h~~k~~PED_ANSWER_PHONE~~w~ per acquistare il cantiere navale per ~1~$\n\n[BOAT_C]\nPremi il ~h~~k~~PED_ANSWER_PHONE~~w~ per acquistare il cantiere navale per ~1~$\n\n[STRP_L]\nPremi il ~h~~k~~PED_ANSWER_PHONE~~w~ per acquistare il club Pole Position per ~1~$\n\n[STRP_T]\nPremi il ~h~~k~~PED_ANSWER_PHONE~~w~ per acquistare il club Pole Position per ~1~$\n\n[STRP_C]\nPremi il ~h~~k~~PED_ANSWER_PHONE~~w~ per acquistare il club Pole Position per ~1~$\n\n[STOCK]\n~r~scorte esaurite\n\n[HELP14]\nPer trovare l'ufficio dell'avvocato, segui la ~h~L~w~ sul radar.\n\n[RAMPAGE]\nVIOLENZA!\n\n[RAMP_F]\nVIOLENZA FALLITA!\n\n[RAMP_P]\nVIOLENZA COMPIUTA!\n\n[RAMP_A]\nTUTTE LE VIOLENZE COMPIUTE!\n\n[PAGE_01]\nUccidi ~1~ membri della gang in 2 minuti!\n\n[PAGE_02]\nDistruggi ~1~ veicoli in 2 minuti!\n\n[PAGE_03]\nUccidi sparando in corsa ~1~ membri della gang in 2 minuti!\n\n[PAGE_04]\nTravolgi ~1~ membri della gang in 2 minuti!\n\n[PAGE_05]\nFai saltare la testa a ~1~ membri della gang in 2 minuti!\n\n[SENTXS]\nSentinel XS\n\n[MAP_LEG]\nLegenda\n\n[VCNMAV]\nVCN Maverick\n\n[LG_01]\nPosizione giocatore\n\n[LG_02]\nAvery Carrington\n\n[LG_03]\nContatto motociclisti\n\n[LG_04]\nColonnello Cortez\n\n[LG_05]\nRicardo Diaz\n\n[LG_06]\nKent Paul\n\n[LG_07]\nAvvocato\n\n[LG_08]\nPhil Cassidy\n\n[LG_09]\nCantiere navale\n\n[LG_10]\nClub Malibu\n\n[LG_11]\nCubani\n\n[LG_12]\nStudio cinematografico\n\n[LG_13]\nAmmuNation\n\n[LG_14]\nHaitiani\n\n[LG_15]\nFerramenta\n\n[LG_16]\nNascondiglio\n\n[LG_17]\nFabbrica di gelato\n\n[LG_18]\nTaxi Kaufman\n\n[LG_19]\nLove Fist\n\n[LG_20]\nTipografia\n\n[LG_21]\nProprietà\n\n[LG_22]\nPay 'n' Spray\n\n[LG_23]\nNegozio di vestiario\n\n[LG_24]\nDimora di Tommy\n\n[LG_25]\nTelefono\n\n[LG_26]\nStazione radio Wildstyle\n\n[LG_27]\nStazione radio Flash FM\n\n[LG_28]\nStazione radio KChat\n\n[LG_29]\nStazione radio Fever 105\n\n[LG_30]\nStazione radio VROck\n\n[LG_31]\nStazione radio VCPR\n\n[LG_32]\nStazione radio Espantoso\n\n[LG_33]\nStazione radio Emotion 98.3\n\n[LG_34]\nStazione radio Wave 103\n\n[LG_36]\nSun Yard\n\n[LG_37]\nClub a luci rosse\n\n[MAP_YAH]\nTU SEI QUI\n\n[TAXSHRT]\n~g~Puoi utilizzare questo taxi Kaufman per arrivare a destinazione invece di guidare. Ti costerà 9$.\n\n[FE_MLG]\nLEGENDA MAPPA\n\n[FED_RDR]\nRADAR\n\n[FED_HUD]\nINTERFACCIA\n\n[FED_RDL]\nGRANDE\n\n[FED_RDB]\nSOLO SEGNALI\n\n[FED_HUF]\nDISSOLVENZA\n\n[FEST_HV]\nMassimo livello missione Vigilante\n\n[BRIBE1]\nHai appena raccolto una bustarella della polizia: il tuo livello di sospetto è sceso di una stella.\n\n[CLOHELP]\nAbiti puliti!\n\n[SUNSHIN]\nSunshine Autos\n\n[CHERRYP]\nGelateria Cherry Popper\n\n[KAUFCAB]\nTaxi Kaufman\n\n[BOATYAR]\nCantiere navale\n\n[WANT_L]\nIl tuo livello di sospetto è sospeso: se commetterai un crimine mentre le stelle lampeggiano, il tuo livello di sospetto verrà ripristinato.\n\n[HOTRNG]\nHOTRING\n\n[BLODRNG]\nBLOODRING\n\n[DIRTRNG]\nDIRTRING\n\n[FEC_ABR]\nAccelera, frena o inverti marcia\n\n[FEI_BTU]\n; = -\n\n[FEI_SCR]\nScorri\n\n[LG_35]\nDestinazione\n\n[BOAT_AS]\n~g~Il cantiere navale d'ora in poi genererà introiti per un massimo di ~1~$. Ricordati di recuperarli regolarmente.\n\n[BOAT_A2]\nCANTIERE NAVALE COMPLETATO\n\n[BOAT_N]\nTappa Charlie\n\n[BOAT_P]\n~g~Raccogli i pacchi prima dello scadere del tempo.\n\n[FEI_R1B]\nTasto R1 \\ R2 -\n\n[HELP9_A]\nPremi il tasto ~h~~k~~PED_FIREWEAPON~~w~ per sparare con il fucile di precisione.\n\n[HELP21]\nPremi il tasto ~h~~k~~VEHICLE_ENTER_EXIT~~w~ per entrare o uscire da un veicolo.\n\n[CREAM]\nDistribuzione\n\n[UMBERTO]\nCafe Robina\n\n[PU_CF1]\nPremi il tasto ~h~~k~~PED_ANSWER_PHONE~~w~ per raccogliere quest'arma e sostituirla con qualsiasi altra dello stesso tipo in tuo possesso.\n\n[FED_RDM]\nMAPPA E INDICATORI\n\n[FEC_ILU]\nSguardo invertito in prima persona :\n\n[NITRO]\nTutti i taxi adesso hanno il super salto! Premi il pulsante del clacson.\n\n[RATNG53]\nInaffidabile\n\n[RATNG54]\nImbarazzante\n\n[RATNG55]\nHacker\n\n[RATNG56]\nBaro\n\n[RATNG57]\nBugiardo assoluto\n\n[STHC_04]\nMiglior punteggio con la palla sulla spiaggia\n\n[STHC_05]\nMiglior risultato Hotring\n\n[STFT_13]\nTempo migliore corsa in elicottero a Downtown\n\n[STFT_14]\nTempo migliore corsa in elicottero a Ocean Beach\n\n[STFT_15]\nTempo migliore corsa in elicottero a Vice Point\n\n[STFT_16]\nTempo migliore corsa in elicottero a Little Haiti\n\n[STFT_21]\nTempo migliore nell'Hotring\n\n[STFT_22]\nGiro migliore nell'Hotring\n\n[STFT_20]\nTempo migliore in 'Cone Crazy'\n\n[HELP44]\nFermati nel ~q~ segnalino rosa.\n\n[HELP45]\nPremi il ~h~~k~~PED_DUCK~~w~ per abbassarti. In questo modo migliorerai la precisione con le armi da fuoco.\n\n[RCR1_5]\nCorsa Bandit radiocomandati\n\n[RCPL1_7]\nCorsa Baron radiocomandati\n\n[RCH1_11]\nRaccolta Raider radiocomandato\n\n[FEA_CTD]\nAttenzione! Questa caratteristica richiede delle periferiche compatibili DTS. Vuoi procedere?\n\n[FEM_STE]\nUSA STEREO\n\n[FEM_UDY]\nUSA DTS\n\n[GREET]\nSaluti da...\n\n[LANCE_1]\nEhi bello, guida con più prudenza!\n\n[LANCE_2]\nEhi, guarda cosa hai combinato!\n\n[LANCE_3]\nEhi, ma dove stai andando adesso?\n\n[LANCE_4]\nCosa diavolo stai facendo?\n\n[LAW4_15]\nPiù soldi!\n\n[MERC_5]\nBella machina, Mr. Vercetti.\n\n[MERC_26]\nPIÙ VELOCE, PIÙ VELOCE, PIÙ VELOCE!\n\n[MERC_27]\nAttento Tommy, mi hanno rifatto il naso il mese scorso.\n\n[MERC_28]\nTommy, guida con attenzione.\n\n[MERC_29]\nTommy, vai più piano!\n\n[MERC_30]\nTommy per favore, fai fuori qualcun altro!\n\n[MERC_31]\nTommy, baby, non farmi fuori!\n\n[MERC_32]\nTommy, sono felice che hai rubato questa macchina!\n\n[MERC_40]\nMi sono davvero divertita.\n\n[MERC_43]\nAdios, angioletto.\n\n[MERC_44]\nContinua a lavorarci, capito?\n\n[MERC_45]\nCiao, bellezza.\n\n[COL5_17]\nOddio, hanno un elicottero!\n\n[COL5_18]\nAbbatti l'elicottero!\n\n[COL5_19]\nTommy, abbatti quell'elicottero!\n\n[COL5_20]\nSta tornando! Distruggi l'elicottero!\n\n[COL5_21]\nMa guarda quanto è grosso!\n\n[COL5_22]\nSta tornando di nuovo!\n\n[FEA_DSM]\nAttenzione! Questo salvataggio utilizza il DTS e richiede periferiche compatibili. Scegli se vuoi procedere utilizzando l'uscita DTS o quella STEREO.\n\n[STFT_23]\nTempo migliore per la tappa Charlie\n\n[HELP50]\nPremi il tasto ~h~~k~~PED_ANSWER_PHONE~~w~ per posizionare la visuale da dietro.\n\n[HELP51]\nPremi il tasto ~h~~k~~PED_ANSWER_PHONE~~w ~ per posizionare la visuale da dietro.\n\n[HELP52]\nPremi il tasto ~h~~k~~PED_ANSWER_PHONE~~w ~ per posizionare la visuale da dietro.\n\n[HELP53]\nPremi il tasto ~h~~k~~PED_CYCLE_WEAPON_LEFT~~w~ o il tasto ~h~~k~~PED_CYCLE_WEAPON_RIGHT~~w~ per passare in rassegna le armi disponibili.\n\n[HELP46]\nSono disponibili otto diversi tipi di arma.\n\n[HELP47]\nPuoi trasportare una sola arma per tipo alla volta: un tipo di pistola, un tipo di fucile a pompa...\n\n[HELP54]\n~w~Costo: ~1~$ ~r~Comprando quest'arma sostituirai quella in uso.\n\n[HELP2A2]\nPremi il tasto ~h~~k~~PED_SPRINT~~w~ mentre corri per effettuare uno ~h~scatto~w~.\n\n[HLPSN_A]\nIl fucile di precisione ti permette di ingrandire l'immagine e colpire i bersagli con precisione dalla distanza.\n\n[HLPSN_B]\nTieni premuto il tasto ~h~~k~~PED_LOCK_TARGET~~w~ per ~h~mirare~w~ col fucile di precisione.\n\n[HLPSN_C]\nTieni premuto il tasto ~h~L1~w~ per ~h~mirare~w~ col fucile di precisione.\n\n[HLPSN_D]\nPremi il tasto ~h~~k~~PED_SNIPER_ZOOM_IN~~w~ per ~h~zoomare~w~ col fucile e il tasto ~h~~k~~PED_SNIPER_ZOOM_OUT~~w~ per ~h~allargare il campo~w~.\n\n[HLPSN_E]\nPremi il tasto ~h~~k~~PED_FIREWEAPON~~w~ per ~h~sparare~w~ col fucile di precisione.\n\n[HLPSN_F]\nPremi il tasto ~h~~k~~PED_FIREWEAPON~~w~ per ~h~sparare~w~ col fucile di precisione.\n\n[HLPSN_G]\nPremi il tasto ~h~~k~~PED_FIREWEAPON~~w~ per ~h~sparare~w~ col fucile di precisione.\n\n[PLANE_H]\nUsa il tasto ~h~~k~~VEHICLE_ACCELERATE~~w~ per accelerare e a sinistra e a destra per curvare.\n\n[PLANE_4] { reVC update }\n{Usa il tasto ~h~~k~~VEHICLE_ACCELERATE~~w~ per accelerare e a sinistra e a destra per curvare.}\nUsa la levetta analogica destra per accelerare, premi la levetta analogica sinistra in basso per salire, in alto per scendere e a sinistra e a destra per curvare.\n\n[HELP55]\nPremi il tasto ~h~~k~~PED_FIREWEAPON~~w~ per attaccare lo chef.\n\n[STPR_8]\nClub Pole Position\n\n[STPR_9]\n3321 Vice Point\n\n[STPR_10]\nAppartamento Links View\n\n[STPR_11]\nEl Swanko Casa\n\n[STPR_12]\n1102 Washington Street\n\n[STPR_13]\nAppartamento Ocean Heights\n\n[STPR_14]\nSkumole Shack\n\n[STPR_15]\nCondominio Hyman\n\n[RCCANX]\n~r~Aereo radiocomandato annullato.\n\n[CLT_HL2]\nQuando viene raccolto un bonus vestiti, vengono rimosse una o due stelle del livello di sospetto.\n\n[CRED009]\nPROGETTAZIONE MISSIONI\n\n[CRED359]\nLEE JOHNSON\n\n[CRED360]\nHENDRIK LESSER\n\n[CRED361]\nPASQUALE STACCHIOTTI\n\n[CRED362]\nENRIQUE FERNANDEZ\n\n[CRED363]\nPAUL BYERS\n\n[CRED364]\nMIKE EMENY\n\n[CRED365]\nROB DUNKIN\n\n[CRED366]\nCHARLIE KINLOCH\n\n[CRED367]\nKEVIN HOBSON\n\n[CRED368]\nJIM CREE\n\n[MOB_66A]\nTommy, Tommy, Tommy, perché sei tornato qua?\n\n[MOB_66B]\nTe l'avevo detto che non vi volevamo più vedere.\n\n[MOB_67A]\nTommy, credo che dovresti andartene, capito?\n\n[MOB_67B]\nI ragazzi Haitiani non sono molto felici di te.\n\n[MOB_18A]\nTommy, sono Paulo, come stai? Bene amico, ascolta: volevo farti una chiamata.\n\n[MOB_18B]\nOssignore, amico, non crederai mai che razza di strafiga ho appena incontrato.\n\n[MOB_18C]\nUna prostituta forse, passeggiava per Little Havana.\n\n[MOB_18D]\nHa detto che si chiamava Mercedes o qualcosa del genere.\n\n[MOB_18E]\nOddio, dovresti proprio vedere questa gnocca.\n\n[MOB_18F]\nRiuscirebbe a succhiare via la mina da una matita. Mi detto che ero il migliore che avesse mai avuto e via dicendo.\n\n[MOB_18G]\nDovresti farci un giro. Ci vediamo!\n\n[MOB_72A]\nTommy, sono io, Lance. Tieni la bocca chiusa Tommy, perché non ho tempo da perdere.\n\n[MOB_72B]\nNon mi importa cos'hai da dire. Perché dovrei? Non te ne frega niente di me, non è vero?\n\n[MOB_72C]\nDovresti fare più attenzione a me. Dovresti darmi la fetta che merito. Lo sai...\n\n[MOB_72D]\nTommy... senti amico, mi dispiace. È solo che...\n\n[MOB_72E]\nLa gente mi ha sempre trattato con accondiscenda, come se fossi un bambino.\n\n[MOB_72F]\nMio fratello lo farebbe. Per favore, amico, tu non farlo.\n\n[MOB_72G]\nDevo andare.\n\n[MOB_63A]\nTommy, sono Earnest. Earnest Kelly.\n\n[MOB_63B]\nCome stai?\n\n[MOB_63C]\nNon male. Avrò bisogno di un bastone per camminare, ma dovrei tornare al lavoro ben presto.\n\n[MOB_63D]\nBene.\n\n[MOB_63E]\nHo sentito di Lance. Che brutto storno, eh?\n\n[MOB_63F]\nSì.\n\n[MOB_63G]\nMai fidarsi di qualcuno che cammina per strada in pigiama. Ecco cosa dico. Sono felice che l'hai fatto fuori. Spero che sia stato doloroso per lui.\n\n[MOB_63H]\nCredo di sì. Non credevo fosse quel genere di persona...\n\n[MOB_63I]\nTommy, per essere un pazzo violento, sei piuttosto ingenuo. Tornerò presto al lavoro e ti insegnerò un paio di cose sulla vita. Ci sentiamo.\n\n[MOB_63J]\nFai con calma, Earnest. Abbi cura di te.\n\n[MOB_16A]\nTommy, sono Paulo, que pasa amigo?\n\n[MOB_16B]\nChe cosa vuoi Paul: non sono interessato a vestiti di marca taroccati.\n\n[MOB_16C]\nMolto divertente, amico, ma lo sai che non tratto merce di seconda classe. Nah, ti ho chiamato per sapere se potevo avere una parte nei tuoi film.\n\n[MOB_16D]\nQuando ero in Inghilterra ho fatto un sacco di cose, sai? Ho attributi più forniti di te, amico.\n\n[MOB_16E]\nPaul, grazie per l'offerta, lo terrò presente.\n\n[MOB_16F]\nDavvero, non scordarti di me dopo tutto quello che ho fatto per te.\n\n[MOB_16G]\nÈ proprio ciò che sto cercando di dimenticare...\n\n[MOB_17A]\nTommy Vercetti: come va, Mr. Pezzo Grosso? Ho saputo le tue novità: un vero giocatore in città, eh...\n\n[MOB_17B]\nPaul, sei ubriaco.\n\n[MOB_17C]\nNo, idiota. Non sono ubriaco. Solo un paio di bicchierini e qualche pillola: non dormo da un paio di giorni, sai...\n\n[MOB_17D]\nComunque, niente prediche. Non sono uno stupido. Chi ti ha portato in questa città? Chi? Io, ecco chi.\n\n[MOB_17F]\nDavvero?\n\n[MOB_17G]\nNiente prediche, smettila! Ti ho fatto conoscere la gente giusta, ti ho mostrato che corde tirare. Ho fatto molto per te e questo è il modo con cui mi ringrazi.\n\n[MOB_17H]\nMi ignori. Non mi aiuti a entrare dopo tutto ciò che ho fatto per te! Cosa credi che sia? Un idiota?\n\n[MOB_17I]\nPaul, sta' buono. Sono stato occupato, non fare l'idiota.\n\n[MOB_17J]\nNon sono un idiota, chiaro? Questo è ciò che hanno detto in riformatorio. Stai forse cercando guai, amico? Beh, stai per trovarli!\n\n[MOB_17K]\nTommy, amico. Per favore. Sei la mia più grande speranza! Per favore, non ridere di me.\n\n[MOB_17L]\nPaul, cerca di dormire, davvero.\n\n[MOB_73A]\nTommy, sono Steve.\n\n[MOB_73B]\nEhi Steve.\n\n[MOB_73C]\nEhi, ciao genio. Sei uno spettacolo! Anch'io sono uno spettacolo! Ci adorano. Stiamo battendo tutti i record, amico.\n\n[MOB_73D]\nStiamo ottenendo dei grandi riconoscimenti. Finalmente posso comprare una casa al mio vecchio così se ne starà zitto.\n\n[MOB_73E]\nEeer, mi sembra perfetto, Steve.\n\n[MOB_73F]\nPerfetto? È meraviglioso! Meraviglioso, MERAVIGLIOSO! Non ha mai creduto in me. Non pensava fossi un artista, ma adesso ce l'ho fatta.\n\n[MOB_73G]\nSono il miglior direttore sadomaso di tutti i tempi, amico. Volevo solo dirti che è stato un piacere averti incontrato.\n\n[MOB_73H]\nGrazie Steve.\n\n[MOB_73I]\nTi voglio bene, amico. Non cambiare, capito?\n\n[MOB_73J]\nCapito. Ci sentiamo Steve.\n\n[BOLLOX]\nPremi il tasto ~o~R1~w~ per sganciare una bomba. Premi il tasto ~t~\"~w~ per annullare.\n\n[BRID_OP]\nPericolo uragano terminato: tutti i ponti per la terra ferma sono nuovamente aperti.\n\n[BRID_CL]\nPericolo uragano: tutti i ponti per la terra ferma sono chiusi.\n\n[LG_38]\nBersaglio\n\n[ASSET_C]\nPOLE POSITION COMPLETATA!\n\n[ASSET_D]\n~g~ Il Club Pole Position generera' un reddito fino ad un massimo di $~1~ al giorno. Ritira il denaro regolarmente!\n\n[ST_WHEE]\nImpennata più lunga (sec)\n\n[ST_STOP]\nFrenata in punta più lunga (sec)\n\n[ST_2WHE]\nPermanenza su 2 ruote più lunga (sec)\n\n[ST_WHED]\nDistanza piu' lunga in impennata (m)\n\n[ST_STOD]\nDistanza piu' lunga in frenata (m)\n\n[ST_2WHD]\nDistanza piu' lunga su 2 ruote (m)\n\n[OUTFT11]\nTuta da ginnastica\n\n[OUTFT12]\nFrankie\n\n[RELOAD]\n~g~Hai vinto l'abilita' di ricarica veloce!\n\n[APACHE]\nHunter consegnato all'eliporto di Ocean Beach\n\n[CRED369]\nJOHN MCCARDLE\n\n[CRED370]\nDAVID MURDOCH\n\n[CRED371]\nCHRIS BROWN\n\n[CRED372]\nPAUL GREEN\n\n[CRED373]\nKYLE MILNE\n\n[CUNTY]\nNuovi vestiti consegnati alla Proprieta' di Vercetti!\n\n[GOODBOY]\n$50 Come Bonus Buon Cittadino!\n\n[NEWCONT]\nNuovo ~h~Punto di Contatto~w~ disponibile alla Marina di Ocean Beach!!\n\n[FIRELVL]\nMissione Camion dei pompieri livello ~1~\n\n[HELP56]\nPremi il tasto ~h~~k~~CAMERA_CHANGE_VIEW_ALL_SITUATIONS~~w~ per cambiare la modalità di visuale.\n\n[HELP57]\nPremi il tasto ~h~~k~~CAMERA_CHANGE_VIEW_ALL_SITUATIONS~~w~ per cambiare la modalità di visuale.\n\n[HELP58]\nMentre prendi la mira, premi il ~h~~k~~PED_CYCLE_TARGET_LEFT~~w~, ~h~~k~~PED_CYCLE_TARGET_RIGHT~~w~ per cambiare bersaglio.\n\n[HELP59]\nMentre prendi la mira, premi il ~h~~k~~PED_CYCLE_TARGET_LEFT~~w~, ~h~~k~~PED_CYCLE_TARGET_RIGHT~~w~ per cambiare bersaglio.\n\n[HELP60]\nSe premi il tasto ~h~~k~~PED_SPRINT~~w~ mentre assalti una macchina, non entrerai nel veicolo.\n\n[HELP61]\nAdesso hai colpi infiniti e il doppio dell'energia su tutti i veicoli.\n\n[CRED374]\nKEVIN YUN\n\n[CRED375]\nERICK COBBS\n\n[CRED376]\nRANDY BLAKE\n\n[CRED377]\nBRANDON LIM\n\n[CRED378]\nBRANDON FENOL\n\n[CRED379]\nMICHAEL MANOLE\n\n[CRED380]\nALETHEIA SIMONSON\n\n[CRED381]\nJOHN JANSEN\n\n[FEC_LB1]\nGuarda\n\n[FEC_LB2]\nindietro\n\n[FEC_LB3]\nGuarda indietro\n\n[FEC_R3]\n(tasto R3)\n\n[FEC_PED]\nComandi a piedi\n\n[FEC_VEH]\nComandi in un veicolo\n\n[FEC_FPR]\nComandi in prima persona\n\n[FEC_CMM]\nComandi comuni\n\n[FEC_PWL]\nCammina a sinistra\n\n[FEC_PWR]\nCammina a destra\n\n[FEC_PWF]\nCammina in avanti\n\n[FEC_PWT]\nCammina verso la telecamera\n\n[FEC_PLB]\nGuardati indietro\n\n[FEC_PFR]\nSpara con l'arma\n\n[FEC_CLE]\nArma precedente\n\n[FEC_CRI]\nArma successiva\n\n[FEC_LKT]\nAggancia bersaglio\n\n[FEC_PJP]\nSalto Ped\n\n[FEC_PSP]\nScatto Ped\n\n[FEC_PSH]\nSparo Ped\n\n[FEC_TLF]\nBersaglio successivo a sinistra\n\n[FEC_TRG]\nBersaglio successivo a destra\n\n[FEC_CCM]\nCentra visuale dietro al giocatore\n\n[FEC_SZI]\nIngrandimento fucile di precisione\n\n[FEC_SZO]\nRiduzione fucile di precisione\n\n[FEC_LKL]\nSguardo a sinistra\n\n[FEC_LRT]\nSguardo a destra\n\n[FEC_LUP]\nSguardo verso l'alto\n\n[FEC_LDN]\nSguardo verso il basso\n\n[FEC_LBH]\nGuarda dietro al veicolo\n\n[FEC_LLF]\nGuarda a sinistra del veicolo\n\n[FEC_LRG]\nGuarda a destra del veicolo\n\n[FEC_HRN]\nClacson\n\n[FEC_HBR]\nFreno a mano\n\n[FEC_ACL]\nAcceleratore\n\n[FEC_BRK]\nFreno\n\n[FEC_TSM]\nAttiva/Disattiva sottomissioni\n\n[FEC_CRD]\nCambia stazione radio\n\n[FEC_ENT]\nEntra/Esci da un veicolo\n\n[FEC_WPN]\nSpara con l'arma\n\n[FEC_PAS]\nPausa\n\n[FEC_FPO]\nAttiva/Disattiva visuale di puntamento\n\n[FEC_SMS]\nMostra/Nascondi puntatore del mouse\n\n[FEC_CMS]\nCambia la modalità di visuale in qualsiasi situazione\n\n[FEC_TSS]\nSalva un'immagine di gioco\n\n[FEC_DBG]\nMenu debug\n\n[FEC_TGD]\nPad game/Debug\n\n[FEC_TDO]\nDisabilita visuale debug\n\n[FEC_IVH]\nInverti mouse orizzontalmente\n\n[FEC_MSL]\nPULSANTE SX\n\n[FEC_MSM]\nPULSANTE CEN\n\n[FEC_MSR]\nPULSANTE DX\n\n[FEC_QUE]\n???\n\n[FEC_TWO]\nUn massimo di due tasti per comando.\n\n[FEC_UMS]\nUn pulsante del mouse può essere assegnato a un solo comando!\n\n[FEC_OMS]\nSolo un pulsante del mouse.\n\n[FEC_UJS]\nUn pulsante del joystick può essere usato per un solo comando!\n\n[FEC_OJS]\nSolo un pulsante del joystick.\n\n[FEC_PTL]\nUsa Aggancia bersaglio con Arma precedente\n\n[FEC_PTR]\nUsa Aggancia bersaglio con Arma successiva\n\n[FEC_LBC]\nUsa Guarda a sinistra con Guarda a destra\n\n[FEC_JBO]\nJOY ~1~\n\n[FEC_WAR]\nAttenzione\n\n[FEC_OKK]\nOK\n\n[FEC_DLF]\nEliminazione fallita.\n\n[FEC_SVU]\nSalvataggio fallito.\n\n[FEC_LUN]\nCaricamento fallito. File corrotto: è necessario eliminarlo.\n\n[FEC_PAD]\nGamepad\n\n[FEC_JOY]\nJoystick\n\n[FES_CSA]\nSeleziona una skin dalla seguente lista:\n\n[FET_HRD]\nIMPOSTAZIONI PREDEFINITE RIPRISTINATE\n\n[FET_MST]\nSTERZO VIA MOUSE\n\n[FEC_STR]\nNUM ASTERISCO\n\n[FET_MIG]\nSINISTRA, DESTRA, ROTELLA PER MODIFICARE\n\n[FET_CIG]\nINDIETRO PER AZZERARE - PULSANTE SX, INVIO PER MODIFICARE\n\n[FET_DSN]\nSkin predefinita.bmp\n\n[FET_RSO]\nRIPRISTINATE IMPOSTAZIONI ORIGINALI\n\n[FET_RSC]\nHARDWARE NON DISPONIBILE - RIPRISTINATE IMPOSTAZIONI ORIGINALI\n\n[FEA_3DH]\nHARDWARE AUDIO\n\n[FEA_SPK]\nCONFIGURAZIONE ALTOPARLANTI\n\n[FEM_LOD]\nDISTANZA VISUALE\n\n[FEM_VSC]\nSINCRONIA FRAME\n\n[FEM_FRM]\nLIMITATORE FRAME\n\n[FEM_MM]\nMENU PRINCIPALE\n\n[FED_RES]\nRISOLUZIONE\n\n[FET_CTL]\nIMPOSTAZIONI DEI COMANDI\n\n[FET_OPT]\nOPZIONI\n\n[FEC_MSH]\nSENSIBILITÀ MOUSE\n\n[FEC_IVV]\nINVERTI MOUSE VERTICALMENTE\n\n[FET_MTI]\nCONFIGURAZIONE COL MOUSE\n\n[FEC_FNC]\nF~1~\n\n[FEC_IRT]\nINS\n\n[FEC_DLL]\nCANC\n\n[FEC_HME]\nHOME\n\n[FEC_END]\nFINE\n\n[FEC_PGU]\nPAG SU\n\n[FEC_PGD]\nPAG GIÙ\n\n[FEC_UPA]\nSU\n\n[FEC_DWA]\nGIÙ\n\n[FEC_LFA]\nSINISTRA\n\n[FEC_RFA]\nDESTRA\n\n[FEC_NUM]\nNUM\n\n[FEC_NMN]\nNUM~1~\n\n[FEC_FWS]\nNUM /\n\n[FEC_PLS]\nNUM +\n\n[FEC_MIN]\nNUM -\n\n[FEC_DOT]\nNUM .\n\n[FEC_NLK]\nBLOC NUM\n\n[FEC_ETR]\nINVIO\n\n[FEC_SLK]\nBLOC SCORR\n\n[FEC_PSB]\nPAUSA\n\n[FEC_BSP]\nINDIETRO\n\n[FEC_TAB]\nTAB\n\n[FEC_CLK]\nBLOC MAIUSC\n\n[FEC_RTN]\nRET\n\n[FEC_LSF]\nMAIUSC SX\n\n[FEC_RSF]\nMAIUSC DX\n\n[FEC_LCT]\nCTRL SX\n\n[FEC_RCT]\nCTRL DX\n\n[FEC_LAL]\nALT SX\n\n[FEC_RAL]\nALT DX\n\n[FEC_LWD]\nWIN SX\n\n[FEC_RWD]\nWIN DX\n\n[FEC_WRC]\nCLIC WIN\n\n[FEC_SPC]\nBARRA\n\n[WIN_TTL]\nGrand Theft Auto VC\n\n[WIN_95]\nGrand Theft Auto VC non è supportato da Windows 95\n\n[WIN_DX]\nGrand Theft Auto VC richiede DirectX versione 8.1 o superiore\n\n[FET_EIG]\nIMPOSSIBILE ASSEGNARE UN COMANDO A QUESTA AZIONE\n\n[FET_DAM]\nMODELLAZIONE ACUSTICA DINAMICA\n\n[FEQ_SRE]\nSei sicuro di voler uscire? Tutti i progressi dall'ultimo salvataggio verranno persi. Vuoi procedere?\n\n[FEQ_SRW]\nSei sicuro di voler uscire dal gioco?\n\n[FET_QG]\nESCI DAL GIOCO\n\n[FEN_STA]\nAVVIA LA PARTITA\n\n[FET_PAU]\nMENU PAUSA\n\n[REPLAY]\nREPLAY\n\n[FEC_ANS]\nAzione\n\n[CVT_MSG]\nConversione texture per prestazioni ottimali con la tua scheda video\n\n[FEC_SFT]\nMAIUSC\n\n[FEH_VMP]\nVEDI MAPPA\n\n[FES_DEE]\nEliminazione fallita! Prova nuovamente.\n\n[FES_CMP]\nSalvataggio fallito! Prova nuovamente.\n\n[FESZ_WR]\nSalvataggio partita. Un momento...\n\n[FELD_WR]\nCaricamento partita. Un momento...\n\n[FEDL_WR]\nEliminazione salvataggio. Un momento...\n\n[PCRESRT]\nAvvio nuova partita. Un momento...\n\n[FET_STI]\nConfigurazione standard\n\n[FET_CTI]\nConfigurazione classica\n\n[FET_PS]\nIMPOSTAZIONE SKIN GIOCATORE\n\n[FEH_NA]\nOPZIONE NON DISPONIBILE\n\n[FEH_MPH]\nMOUSE, FRECCE PER MUOVERSI - PAGSU, PAGGIÙ, ROTELLINA PER LO ZOOM, L - LEGENDA\n\n[FEA_MP3]\nRIPRODUTTORE MP3\n\n[NO_PCCD]\nInserisci il CD di GTA Vice City o premi Esc per annullare\n\n[FEH_SSA]\nFRECCE PER MUOVERSI - S PER SALVARE\n\n[FES_CMI]\nULTIMA MISSIONE COMPLETATA\n\n[FET_STS]\nSTATISTICHE SALVATE NEL FILE 'STATS.HTML' + 'STATS.TXT'\n\n[WIN_VDM]\nMemoria video insufficiente per eseguire Grand Theft Auto VC\n\n[FEC_ERI]\nErrore! Uno o più azioni non sono assegnate a nessun tasto o pulsante. Assicurati che a tutte le azioni corrisponda un comando.\n\n[FEC_TFU]\nTorretta + Inclina in su\n\n[FEC_TFD]\nTorretta + Inclina in giù\n\n[FET_RIG]\nSELEZIONA IL NUOVO COMANDO PER QUESTA AZIONE\n\n[FEA_NM3]\nNESSUN FILE MP3 TROVATO\n\n[FEA_MPB]\nINCREMENTO VOLUME MP3\n\n[FEA_MUS]\nVOLUME MUSICA\n\n[FEA_SFX]\nVOLUME EFFETTI\n\n[CVT_ERR]\nSpazio su disco esaurito; è necessario liberare dello spazio prima di poter procedere. Premi ESC per annullare.\n\n[FEA_ADP]\nRILEVAMENTO AUTOMATICO\n\n{=================================== MISSION TABLE AMBULAE ===================================}\n\n[ATUTOR2:AMBULAE]\n~g~Conduci i pazienti all'ospedale guidando CON PRUDENZA! Qualsiasi scossone può ucciderli.\n\n[A_FULL:AMBULAE]\n~r~Ambulanza piena!\n\n[A_FAIL2:AMBULAE]\n~r~La tua scarsa sollecitudine è stata fatale al paziente!\n\n[A_FAIL3:AMBULAE]\n~r~Il paziente è morto!\n\n[A_PASS:AMBULAE]\nSalvato!\n\n[A_COMP2:AMBULAE]\nNon ti stancherai mai!\n\n[A_COMP1:AMBULAE]\nMissioni Infermiere completate: ~1~$\n\n[A_CANC:AMBULAE]\n~r~Missione Infermiere annullata!\n\n[A_COMP3:AMBULAE]\nMissione Infermiere completata! Non ti stancherai mentre corri!\n\n[ALEVEL:AMBULAE]\nMissione Infermiere livello ~1~\n\n[A_FAIL1:AMBULAE]\nMissione Infermiere terminata.\n\n[A_SAVES:AMBULAE]\nPERSONE SALVATE: ~1~\n\n{=================================== MISSION TABLE ASSIN1 ===================================}\n\n[ASM1_5:ASSIN1]\n~r~Ha completato le sue consegne!\n\n[ASM1_6:ASSIN1]\nConsegne rimanenti:\n\n[ASM1_7:ASSIN1]\n~g~Carl Pearson, fattorino di una pizzeria. Uccidilo prima che completi le sue consegne.\n\n[ASM1_D:ASSIN1]\nMr. Teal, il tuo aiuto nello sradicare gli stranieri è stato inestimabile per il nostro lavoro.\n\n{=================================== MISSION TABLE ASSIN2 ===================================}\n\n[ASM2_1:ASSIN2]\n~g~Mrs. Dawson lascerà presto la gioielleria in Vice Point. Devi ucciderla. Deve sembrare un incidente d'auto.\n\n[ASM2_3:ASSIN2]\n~g~Sta per esplodere! Allontanati!\n\n[ASM2_4:ASSIN2]\n~r~Hai danneggiato la sua auto, ma lei non è sopra! Adesso non ci entrerà di sicuro!\n\n[ASM2_5:ASSIN2]\n~r~È riuscita a scappare!\n\n[ASM2_6:ASSIN2]\n~r~Sei stato visto troppo vicino alla scena dell'incidente!\n\n[ASM2_7:ASSIN2]\n~g~Non utilizzare armi! Deve sembrare un incidente! Spingila fuori strada!\n\n[ASM2_8:ASSIN2]\n~g~La morte di Mrs. Dawson deve sembrare un incidente. Non utilizzare armi.\n\n[ASM2_9:ASSIN2]\n~g~Avrai bisogno di una vettura per questo lavoro!\n\n[ASM2_10:ASSIN2]\n~g~Quando la sua macchina prende fuoco, allontanati il più possibile dal luogo dell'incidente.\n\n[ASM2_11:ASSIN2]\nAiuto!\n\n[ASM2_12:ASSIN2]\nQualcuno mi aiuti!\n\n[ASM2_13:ASSIN2]\nOddio!\n\n[ASM2_A:ASSIN2]\nComplimenti per l'ottimo lavoro, Mr. Teal. Il mio cliente è molto soddisfatto.\n\n[ASM2_2:ASSIN2]\nSalute:\n\n{=================================== MISSION TABLE ASSIN3 ===================================}\n\n[ASM3_11:ASSIN3]\nTEMPO:\n\n[ASM3_C:ASSIN3]\nUna gang europea ha pianificato un furto in banca a Vice City. I miei clienti preferirebbero che il colpo non vada a segno.\n\n[ASM3_D:ASSIN3]\nOgni membro della gang ha un nascondiglio nella città: alcuni hanno dei lavori di copertura, altri sono in vacanza.\n\n[ASM3_E:ASSIN3]\nDettagli e posizione più probabile di ogni bersaglio sono riportati nel nastro sotto al telefono.\n\n[ASM3_14:ASSIN3]\n~g~Dick Tanner si trova presso la DBP Security in Ocean Drive.\n\n[ASM3_15:ASSIN3]\n~g~Marcus Hammond e Franco Carter si trovano presso la gioielleria in Vice Point.\n\n[ASM3_16:ASSIN3]\n~g~Nick Kong si trova presso Washington Beach.\n\n[ASM3_18:ASSIN3]\n~g~Non avvicinarti troppo, se no il bersaglio potrebbe vederti e sarai costretto a inseguirlo!\n\n[ASM3_19:ASSIN3]\n~g~Ti ha visto! Fallo fuori!\n\n[ASM3_20:ASSIN3]\n~g~Ti hanno visto! Falli fuori entrambi!\n\n[ASM3_21:ASSIN3]\n~r~Non hai ucciso tutti i membri della gang in tempo!\n\n[ASM3_22:ASSIN3]\n~g~Non avvicinarti troppo, se no i bersagli potrebbero vederti e cercare di scappare!\n\n[ASM3_12:ASSIN3]\n~g~Un assortimento di armi è stato lasciato per te nel caso di bisogno. Hai ~h~9 MINUTI~g~ per uccidere tutti i membri della gang.\n\n[ASM3_13:ASSIN3]\n~g~Mike Griffin lavora su un cartello pubblicitario in Washington.\n\n[ASM3_17:ASSIN3]\n~g~Charlie Dilson è in macchina in Washington.\n\n{=================================== MISSION TABLE ASSIN4 ===================================}\n\n[ASM4_12:ASSIN4]\nDistanza:\n\n[ASM4_15:ASSIN4]\n~g~Recupera il fucile di precisione alla tua destra.\n\n[ASM4_16:ASSIN4]\n~g~Osserva la donna sul balcone: scenderà per le scale e chiederà l'ora a un uomo.\n\n[ASM4_17:ASSIN4]\n~g~Solo quando la conversazione avrà termine, dovrai uccidere l'uomo con cui ha parlato ma NON la donna.\n\n[ASM4_18:ASSIN4]\n~g~Una volta eliminato il bersaglio, recupera la sua valigetta e portala ad Ammu-Nation in Downtown.\n\n[ASM4_19:ASSIN4]\n~g~Tieni la distanza dal bersaglio: la barra nella parte superiore destra dello schermo indica quanto gli sei vicino.\n\n[ASM4_20:ASSIN4]\n~g~Se si riempirà, verrai avvistato.\n\n[ASM4_21:ASSIN4]\n~g~Recupera la valigetta!\n\n[ASM4_22:ASSIN4]\n~g~Porta la valigetta ad Ammu-Nation in Downtown.\n\n[ASM4_23:ASSIN4]\n~g~Ti ha visto e sta fuggendo! Uccidilo e recupera la valigetta!\n\n[ASM4_25:ASSIN4]\n~r~Hai ucciso la donna, idiota!\n\n[ASM4_26:ASSIN4]\n~r~Il bersaglio è salito a bordo del volo!\n\n[ASM4_27:ASSIN4]\n~r~Il bersaglio ti ha visto! Avresti dovuto tenerti a distanza!\n\n[ASM4_28:ASSIN4]\n~r~Il bersaglio ti ha visto! Ti ha sentito sparare!\n\n[ASM4_29:ASSIN4]\n~r~Dovevi ucciderlo solo dopo che aveva parlato con la donna!\n\n[ASM4_A:ASSIN4]\nÈ giunta l'ora di occuparsi di pesci più grossi, Mr Teal. Troverai un fucile tra le foglie alla tua destra.\n\n[ASM4_B:ASSIN4]\nOsserva la donna sul balcone sopra i banchi dei check-in: scenderà per le scale e chiederà l'ora a un uomo.\n\n[ASM4_C:ASSIN4]\nDovrai uccidere questa persona, recuperare la sua valigetta e portarla nella locazione riportata sotto al telefono.\n\n{=================================== MISSION TABLE ASSIN5 ===================================}\n\n[ASM5_A:ASSIN5]\nC'è uno scambio di beni sopra il tetto della fabbrica di gelato Cherry Popper.\n\n[ASM5_B:ASSIN5]\nUccidi tutti gli elementi coinvolti, recupera la merce e portala all'eliporto presso l'aeroporto.\n\n[ASM5_C:ASSIN5]\nAlla tua sinistra troverai un cancello che porta al retro della fabbrica.\n\n[ASM5_1:ASSIN5]\n~g~Entra nel cortile dietro alla fabbrica di gelato Cherry Popper e apriti la strada fino al luogo dello scambio.\n\n[ASM5_2:ASSIN5]\n~g~Recupera la merce e portala all'eliporto presso l'aeroporto.\n\n[ASM5_3:ASSIN5]\n~g~Porta la merce all'eliporto presso l'aeroporto!\n\n{=================================== MISSION TABLE BANKJ1 ===================================}\n\n[WANTED1:BANKJ1]\n~g~Semina i poliziotti per perdere il tuo livello di sospetto.\n\n[BJM1_A:BANKJ1]\nTommy! Ehi Tommy, guarda qua, è grandioso! Ho fatto installare un minibar!\n\n[BJM1_B:BANKJ1]\nAbbiamo un intero bar al piano di sotto, Ken.\n\n[BJM1_C:BANKJ1]\nSì, sì, certo. Beh, ho portato quella lavagna che mi avevi richiesto.\n\n[BJM1_D:BANKJ1]\nAh, questi sono i benefici della scuola dell'obbligo: l'abilità di seguire le istruzioni.\n\n[BJM1_E:BANKJ1]\nAdesso mi serve uno scassinatore.\n\n[BJM1_F:BANKJ1]\nOh, va bene, beh, fammi pensare... scassinatore, scassinatore, scassinatore... Trovato! Questo tipo ti farà impazzire!\n\n[BJM1_G:BANKJ1]\nAhh, nah, quello schmuck. È dentro.\n\n[BJM1_H:BANKJ1]\nDentro dove?\n\n[BJM1_I:BANKJ1]\nIn una cella nel quartier generale della polizia in attesa di trasferimento.\n\n[BJM1_J:BANKJ1]\nCredo stia per essere rilasciato sulla parola...\n\n[BJM1_1:BANKJ1]\n~g~Fai fuggire Cam Jones dalla custodia della polizia!\n\n[BJM1_3:BANKJ1]\n~g~Troverai ciò che ti serve nello spogliatoio della stazione.\n\n[BJM1_21:BANKJ1]\n~g~La tessera per le celle si trova nel piano superiore della stazione.\n\n[BNK1_7:BANKJ1]\nCam Jones?\n\n[BNK1_8:BANKJ1]\nTi sto facendo scappare!\n\n[BNK1_10:BANKJ1]\nSì, sono io...\n\n[BNK1_11:BANKJ1]\nCome vuoi!\n\n[BNK1_13:BANKJ1]\nDevo fare un lavoro e tu sarai il mio scassinatore.\n\n[BNK1_14:BANKJ1]\nSempre meglio che restare col culo in galera!\n\n[BJM1_22:BANKJ1]\n~g~Riporta Cam a casa sua!\n\n[BJM1_23:BANKJ1]\n~g~Prima devi recuperare la tessera!\n\n[BNK1_12:BANKJ1]\nFai perdere le tracce e riportami a casa!\n\n[BJM1_20:BANKJ1]\nMetti via l'arma o ne pagherai le conseguenze!\n\n[BJM1_5:BANKJ1]\nSolo personale autorizzato oltre a questo punto!\n\n[BJM1_2:BANKJ1]\n~r~Dovevi far fuggire Cam, non farlo morire!\n\n[BJM1_4:BANKJ1]\nÈ armato! Uccidetelo!\n\n{=================================== MISSION TABLE BANKJ2 ===================================}\n\n[BJM2_A:BANKJ2]\nAbbiamo bisogno di un tiratore. Ne conosci uno?\n\n[BJM2_B:BANKJ2]\nEhi Tommy, Tommy, Tommy, questa roba ti tiene in forma, amico.\n\n[BJM2_C:BANKJ2]\nWoooOOOooo!\n\n[BJM2_D:BANKJ2]\nPotrei essere io il tuo tiratore! Spara! Spara!\n\n[BJM2_E:BANKJ2]\nNon sei un tiratore, sei un idiota.\n\n[BJM2_F:BANKJ2]\nFatti un drink e sta zitto.\n\n[BJM2_G:BANKJ2]\nEhi, via dai miei piedi! Ye ye ye ow ow.\n\n[BJM2_H:BANKJ2]\nCam, cosa mi dici?\n\n[BJM2_I:BANKJ2]\nBeh, il miglior tiratore in città è un tipo chiamato Cassidy.\n\n[BJM2_J:BANKJ2]\nDavvero?\n\n[BJM2_K:BANKJ2]\nSì. Un militare, o per lo meno crede di esserlo.\n\n[BJM2_L:BANKJ2]\nNon credo sia mai stato nell'esercito, ma sicuramente sa come tenere in mano un'arma.\n\n[BJM2_M:BANKJ2]\nLo troverai di sicuro al poligono di tiro.\n\n[BJM2_2A:BANKJ2]\nSei Phil Cassidy?\n\n[BJM2_2B:BANKJ2]\nPerché?\n\n[BJM2_2C:BANKJ2]\nSto cercando un uomo che sappia come sparare. Da quello che vedo, non sono molto convinto...\n\n[BJM2_2D:BANKJ2]\nFigliolo, potrei colpire una mosca sulla tua testa a 30 metri di distanza.\n\n[BJM2_2E:BANKJ2]\nDavvero?\n\n[BJM2_2F:BANKJ2]\nCerto. Ho fatto pratica nell'esercito.\n\n[BJM2_2G:BANKJ2]\nLo sparo alla mosca è così popolare nell'esercito? Per fortuna non pago le tasse.\n\n[BJM2_2H:BANKJ2]\nStai cercando di fare lo spiritoso?\n\n[BJM2_2I:BANKJ2]\nAh ah ah ah ah!\n\n[BJM2_2J:BANKJ2]\nSpariamo.\n\n[BJM2_1:BANKJ2]\n~g~Raggiungi Ammu-Nation in Downtown e parla con Phil Cassidy.\n\n[BJM2_4:BANKJ2]\nPUNTEGGIO PRIMO TURNO: ~1~\n\n[BJM2_6:BANKJ2]\nPUNTEGGIO SECONDO TURNO: ~1~\n\n[BJM2_7:BANKJ2]\nPUNTEGGIO TOTALE: ~1~\n\n[BJM2_9:BANKJ2]\n~G~Raggiungi il punto di partenza del secondo turno.\n\n[BJM2_11:BANKJ2]\n~r~Phil è morto!\n\n[BJM2_12:BANKJ2]\n~r~Uno dei tiratori è morto!\n\n[BJM2_14:BANKJ2]\n~g~Raggiungi la prossima area!\n\n[BJM2_17:BANKJ2]\n~g~Vai a parlare con Phil.\n\n[BJM2_24:BANKJ2]\n~g~Il bersaglio più vicino vale un punto.\n\n[BJM2_25:BANKJ2]\n~g~Il bersaglio centrale vale due punti.\n\n[BJM2_27:BANKJ2]\n~g~In questo turno, tutti i bersagli valgono un punto.\n\n[BNK2_4:BANKJ2]\nHoooeee!\n\n[BNK2_5:BANKJ2]\nNon riusciresti a colpire neanche un elefante!\n\n[BNK2_7:BANKJ2]\nFammi un favore, aiutami a mettere a segno un colpo.\n\n[BNK2_8:BANKJ2]\nFigliolo, da come hai sparato, se mi chiedessi di sposarti direi di sì.\n\n[BNK2_9A:BANKJ2]\nFigliolo, ficcati la tua parlata e le tue grandi idee là dove non batte il sole. Non sai sparare per niente.\n\n[BNK2_9B:BANKJ2]\nNon sai sparare per niente.\n\n[BJM2_28:BANKJ2]\nPUNTEGGIO TERZO TURNO: ~1~\n\n[BJM2_26:BANKJ2]\n~g~Il bersaglio più lontano vale tre punti.\n\n[BNK2_1:BANKJ2]\nMUNIZIONI VERE\n\n[RANGE_1:BANKJ2]\nPUNTEGGIO PER COLPO: ~1~\n\n[BJM2_2:BANKJ2]\n~g~Per interrompere il turno, premi il ~h~~k~~PED_JUMPING~~g~.\n\n[BJM2_N:BANKJ2]\nRilassati.\n\n{=================================== MISSION TABLE BANKJ3 ===================================}\n\n[BJM3_A:BANKJ3]\nLe cose stanno iniziando a prendere forma.\n\n[BJM3_B:BANKJ3]\nQual è il piano Tommy? Que pasa, amigo?\n\n[BJM3_C:BANKJ3]\nLa tua parte consiste nel continuare a fare l'idiota. Comunque, adesso abbiamo bisogno di un pilota.\n\n[BJM3_D:BANKJ3]\nTommy, lo farò io. Io so guidare bene.\n\n[BJM3_E:BANKJ3]\nTi serve Hilary, capo. Di certo non un sapientone avvocato del cazzo.\n\n[BJM3_F:BANKJ3]\nHilary è la persona giusta. Non troverai nessuno capace di guidare così veloce. Gli posso fare una chiamata.\n\n[BJM3_G:BANKJ3]\nEhi Hil, sono Phil. Come butta? No, lascia stare, ne parliamo un'altra volta. Mi faresti un favore?\n\n[BJM3_H:BANKJ3]\nHo qui un tipo del nord... No, no, non credo abbia fatto il servizio militare, ma ha bisogno di un guidatore.\n\n[BJM3_I:BANKJ3]\nPer un po' di azione. OK, capisco.\n\n[BJM3_J:BANKJ3]\nChe cosa ha detto?\n\n[BJM3_K:BANKJ3]\nBeh, ci sta, nessun problema. Beh, un piccolo problema c'è: ha subito uno shock da abbandono.\n\n[BJM3_L:BANKJ3]\nSembra non voglia lavorare con nessuno che non sia capace di batterlo. Qualcosa che ha a che fare con la sua vecchia.\n\n[BJM3_M:BANKJ3]\nComunque, vuole prima sfidarti in una corsa, ha detto che ci aspettava fuori...\n\n[BJM3_2A:BANKJ3]\nSei Tommy? Beh, certo che sei Tommy, cioè...\n\n[BJM3_2B:BANKJ3]\nPer quale altro motivo qualcuno vorrebbe parlare con me?\n\n[BJM3_2C:BANKJ3]\nOK, vedila in questo modo...\n\n[BJM3_2D:BANKJ3]\nIo guiderò SE, e solo SE, tu sai guidare come si deve.\n\n[BJM3_2E:BANKJ3]\nLasciami solo... e non te lo perdonerò mai.\n\n[BJM3_2:BANKJ3]\n~r~Hilary è morto!\n\n[BJM3_4:BANKJ3]\n~g~Hai bisogno di una vettura per partecipare!\n\n[BNK3_1:BANKJ3]\nOK. Guiderò per te, ma per favore trattami male!\n\n[BNK3_3A:BANKJ3]\nCorsa illegale in corso presso Vice Point.\n\n[BNK3_3B:BANKJ3]\nA tutte le pattuglie.\n\n[BNK3_3C:BANKJ3]\nQueste corse sono illegali e vietate!\n\n{=================================== MISSION TABLE BANKJ4 ===================================}\n\n[BNK4_A:BANKJ4]\n~w~Come potete vedere, signori, questi saranno i soldi più facili della storia.\n\n[BNK4_B:BANKJ4]\n~w~Tommy, seriamente, dovresti pensare di fare l'avvocato.\n\n[BNK4_C:BANKJ4]\n~w~Ma che cosa ti fumi, amico? Non è per niente un piano semplice!\n\n[BNK4_D:BANKJ4]\n~w~Beh, chi ha bisogno di un piano semplice?\n\n[BNK4_E:BANKJ4]\n~w~Prendi il comunismo, beh, quello era un piano semplice. Non ha fatto così bene alla Russia, no?\n\n[BNK4_F:BANKJ4]\n~w~Rilassatevi, OK? Con una squadra come la nostra, non ci saranno problemi.\n\n[BNK4_G:BANKJ4]\n~w~Abbiamo Cam per la cassaforte. Phil? Noi ci occuperemo della sorveglianza, mentre Hilary guiderà l'auto per la fuga.\n\n[BNK4_H:BANKJ4]\n~w~Uh, eh eh, non ti stai dimenticando qualcuno? Qualcuno che ti ha costantemente aiutato in questa città? Qualcuno...?\n\n[BNK4_I:BANKJ4]\n~w~Ken... Ken, ma certo. Il nostro Ken si occuperà di lavare il denaro sporco e di tenere le birre al fresco.\n\n[BNK4_J:BANKJ4]\n~w~Non ho ancora capito cosa ci sto a fare io qua.\n\n[BNK4_K:BANKJ4]\n~w~Beh, è semplice: non hai mai visto un film d'azione?\n\n[BNK4_L:BANKJ4]\n~w~Entriamo nella banca, sventoliamo in giro l'arma e usciamo molto ricchi.\n\n[P_DEAD:BANKJ4]\n~r~Phil è morto!\n\n[C_DEAD:BANKJ4]\n~r~Cam è morto!\n\n[H_DEAD:BANKJ4]\n~r~Hilary è morto!\n\n[P_HIND:BANKJ4]\n~r~Hai perso Phil!\n\n[C_HIND:BANKJ4]\n~r~Cam è restato indietro!\n\n[H_HIND:BANKJ4]\n~r~Hai abbandonato Hilary!\n\n[GETCAR:BANKJ4]\n~g~Entra nell'auto e preparati alla rapina!\n\n[TRASHED:BANKJ4]\n~r~HAI DISTRUTTO L'AUTO PER LA FUGA!!!\n\n[BNK4_1:BANKJ4]\nGuido io.\n\n[BNK4_2:BANKJ4]\nOttimo. Un passeggero. Aspetta che lo dica al resto del gruppo.\n\n[BNK4_3A:BANKJ4]\nEhi, fai attenzione alla macchina, Tommy!\n\n[BNK4_3B:BANKJ4]\nTommy, Hilary occupa troppo spazio!\n\n[BNK4_3C:BANKJ4]\nNon è vero!\n\n[BNK4_3D:BANKJ4]\nInvece sì!\n\n[BNK4_3E:BANKJ4]\nEhi, state entrambi zitti o ve ne andate a piedi.\n\n[BNK4_3F:BANKJ4]\nSì Hilary.\n\n[BNK4_3I:BANKJ4]\nPerdio, Phil, smettila di sventolare quell'affare in giro!\n\n[BNK4_3J:BANKJ4]\nSì, finirai col cavare un occhio a qualcuno!\n\n[BNK4_3M:BANKJ4]\nLa mia bambina! È a pezzi!\n\n[BNK4_3O:BANKJ4]\nSei accecato dall'illusione di permanenza.\n\n[BNK4_3P:BANKJ4]\nCosa?\n\n[BNK4_3Q:BANKJ4]\nPensi che tutto duri per sempre.\n\n[BNK4_3R:BANKJ4]\nLa giovinezza, le persone care, la pizza...\n\n[BNK4_3S:BANKJ4]\nMa tutto passa e finisce e tu lo devi accettare.\n\n[BNK4_3T:BANKJ4]\nEhi, hai ragione. Grazie Cam.\n\n[BNK4_3U:BANKJ4]\nÈ un piacere.\n\n[BNK4_3V:BANKJ4]\nEhi Tommy, perché ci siamo fermati?\n\n[BNK4_4A:BANKJ4]\n~w~Hilary, continua a guidare attorno al quartiere.\n\n[BNK4_5:BANKJ4]\n~w~OK Tommy, OK.\n\n[BNK4_6:BANKJ4]\n~w~QUESTA È UNA RAPINA!\n\n[BNK4_7:BANKJ4]\n~w~NESSUNO SI MUOVA!\n\n[BNK4_8:BANKJ4]\n~w~TUTTI CONTRO QUEL MURO!\n\n[BNK4_9:BANKJ4]\nPhil, mantieni il controllo!\n\n[BNK4_10:BANKJ4]\nRicevuto capo!\n\n[BNK4_11:BANKJ4]\nVieni Cam, la cassaforte è di sopra...\n\n[BK4_12A:BANKJ4]\nMaledizione! È una Flange 9000!\n\n[BK4_12B:BANKJ4]\nPotrei impiegare ore ad aprirla,\n\n[BK4_12C:BANKJ4]\no cinque minuti se trovi l'amministratore.\n\n[BNK4_13:BANKJ4]\nVado a scoprire dove si è rintanato.\n\n[BK4_14A:BANKJ4]\nPhil, va tutto bene?\n\n[BNK4_15:BANKJ4]\nCerto. Tutto liscio come l'olio.\n\n[BNK4_16:BANKJ4]\nTu, tu vieni con me!\n\n[BNK4_17:BANKJ4]\nOK, OK! Ti prego, non sparare!\n\n[BNK4_18:BANKJ4]\nHO DETTO NESSUNO SI MUOVA!\n\n[BK4_19A:BANKJ4]\nL'apertura è temporizzata,\n\n[BK4_19B:BANKJ4]\npotete anche rinunciarci!\n\n[BK4_20A:BANKJ4]\nDiamine, posso aggirare l'apertura a tempo,\n\n[BK4_20B:BANKJ4]\nma poi avremo bisogno del tuo codice per spalancarla!\n\n[BNK4_21:BANKJ4]\nSta qua. Se fai uno scherzo diventi cibo per pesci. Chiaro?\n\n[BK4_24A:BANKJ4]\nVado a controllare Phil, torno subito.\n\n[BK4_24B:BANKJ4]\nTe l'avevo detto di non toccare l'allarme!\n\n[BNK4_25:BANKJ4]\nLa squadra SWAT sarà qui fra pochi minuti!\n\n[BNK4_27:BANKJ4]\nUn po' di aiuto non farebbe male, Tommy.\n\n[BNK4_28:BANKJ4]\nSWAT di Vice City! Siete completamente circondati!\n\n[BNK4_29:BANKJ4]\nCircondati? AH AH AH Aaaaaaaaaah!\n\n[BNK4_30:BANKJ4]\nSi stanno cagando addosso, corrotti bastardi!\n\n[BK4_31A:BANKJ4]\nTommy! La cassaforte è aperta!\n\n[BK4_34A:BANKJ4]\nOK, abbiamo i fondi pensione della SWAT. Andiamocene da qui!\n\n[BK4_34B:BANKJ4]\nOK, l'avete voluto voi! Il tempo è scaduto!\n\n[BK4_35A:BANKJ4]\nStanno assalendo l'edificio!\n\n[BK4_35B:BANKJ4]\nAl riparo!\n\n[BNK4_36:BANKJ4]\nDov'è Cam?\n\n[BNK4_37:BANKJ4]\nNon ce l'ha fatta...\n\n[BNK4_38:BANKJ4]\nQuesto è l'ultimo. VIA! VIA! VIA!\n\n[BNK_39:BANKJ4]\nMerda! Dov'è Hilary?\n\n[BK4_40A:BANKJ4]\nGliela do io l'illusione di permanenza!\n\n[BNK4_42:BANKJ4]\nEhi, ragazzi! Entrate, vi copro io!\n\n[BNK4_44:BANKJ4]\nCe l'abbiamo fatta! Siamo ricchi, RICCHI!\n\n[BNK4_45:BANKJ4]\nPeccato che Cam non ce l'ha fatta, era un bravo ragazzo!\n\n[BNK4_46:BANKJ4]\nSì, comunque... ora ce n'è più per noi!\n\n[BNK4_47:BANKJ4]\nMaledettamente vero! YEEEEHAAAH!\n\n[BNK4_48:BANKJ4]\nTommy, vuoi un massaggio?\n\n[BNK4_49:BANKJ4]\nCiao Mercedes! Sì, effettivamente sono un po' teso...\n\n[BNK450A:BANKJ4]\nSai cosa ti dico Tommy? Sai cosa ti dico? I membri corrotti della SWAT faranno meglio a fare attenzione finché Kent Paul è in città.\n\n[BNK450B:BANKJ4]\nEddai, dammene una fetta più grande! Amico, dai! Mi devo comprare dei vestiti nuovi!\n\n[BNK4_94:BANKJ4]\n~w~OK, ragazzi. Procediamo come pianificato.\n\n[BM_DEAD:BANKJ4]\n~r~Hai bisogno dell'amministratore vivo!\n\n[ASSET_A:BANKJ4]\nRAPINA ALLA BANCA COMPLETATA!\n\n[ASSET_B:BANKJ4]\n~g~Il Malibu d'ora in poi genererà introiti per un massimo di ~1~$. Ricordati di recuperarli regolarmente.\n\n[IDIOT:BANKJ4]\n~r~Vai in giro vestito come un pazzo e attiri l'attenzione! Sei un IDIOTA!\n\n{=================================== MISSION TABLE BARON1 ===================================}\n\n[COK1_A:BARON1]\nForza, dai, forza! Yeh yeh aaaah...\n\n[COK1_B:BARON1]\nStupido cavallo! Ti taglierò la testa!\n\n[COK1_C:BARON1]\nChi è questo stronzo?\n\n[COK1_D:BARON1]\nTommy Vercetti, ti ricorderai di me.\n\n[COK1_E:BARON1]\nScusami, sono un po' ansioso. Mai fidarsi di un fottuto cavallo!\n\n[COK1_F:BARON1]\nHai fatto un bel lavoro: adesso lavori per me.\n\n[COK1_H:BARON1]\nCome ti ho detto, amigo, lavori per me. Adesso sta zitto. Un qualche giuda mi ha tradito.\n\n[COK1_I:BARON1]\nPensava non sapessi quanti soldi stessi facendo, ma rubarmi il 3% è come rubarmi il 100%.\n\n[COK1_J:BARON1]\nNessuno fa questo a me. NESSUNO!!!\n\n[COK1_K:BARON1]\nSeguilo nel suo appartamento e scopri dove va! Successivamente, lo elimineremo noi.\n\n[COK1_1:BARON1]\nOmmerda!\n\n[COK1_2:BARON1]\nTroppo lento, nonnino!\n\n[COK1_4:BARON1]\nPerdente.\n\n[COK1_5:BARON1]\nTi conviene continuare a correre, stronzo!\n\n[COK1_8:BARON1]\n~g~Svelto! Recupera un mezzo e inseguilo!\n\n[COK1_9:BARON1]\n~r~Dovevi inseguirlo, non ucciderlo!\n\n[COK1_10:BARON1]\n~r~Entra nella casa del ladro e scopri dove ha nascosto il denaro.\n\n[COK1_11:BARON1]\n~g~Dai un'occhiata da questa finestra.\n\n[COK1_7:BARON1]\n~g~È scappato sul tetto: stagli dietro ma non ucciderlo!\n\n[COK1_G:BARON1]\nLavoro per soldi.\n\n{=================================== MISSION TABLE BARON2 ===================================}\n\n[COK2_A:BARON2]\nMa che fottuti incompetenti non siete?\n\n[COK2_B:BARON2]\nIDIOTI! IDIOTI! IDIOTI! IDIOTI!\n\n[COK2_C:BARON2]\nTommy,\n\n[COK2_D:BARON2]\nquesti idioti... cercano sempre di fregarti.\n\n[COK2_E:BARON2]\nÈ questo il problema in questo business.\n\n[COK2_F:BARON2]\nChe cosa credi di fare? Aaaaah!\n\n[COK2_G:BARON2]\nQuesti stronzi hanno fallito miseramente.\n\n[COK2_H:BARON2]\nBen presto anche i papà e le mamme penseranno di poter spacciare coca in Vice City.\n\n[COK2_I:BARON2]\nChi sarà il prossimo adesso? La fottuta mafia?\n\n[COK2_J:BARON2]\nLa base della loro banda è una fortezza al piano terra,\n\n[COK2_K:BARON2]\nper cui Quentin... Quentin! QUENTIN!\n\n[COK2_L:BARON2]\nLui ti porterà in volo sull'area!\n\n[COK2_M:BARON2]\nSradicateli!\n\n[COK2_N:BARON2]\nChe cosa credi di fare?\n\n[COK2_O:BARON2]\nChe cosa fai qua?\n\n[COK2_P:BARON2]\nEhi, ho chiesto in giro ed è ovvio\n\n[COK2_Q:BARON2]\nche Diaz ha fatto saltare l'accordo e ha freddato mio fratello.\n\n[COK2_R:BARON2]\nE ucciderà anche te!\n\n[COK2_S:BARON2]\nIo posso far fuori Diaz!\n\n[COK2_T:BARON2]\nNo, ascoltami! Io mi occuperò di Diaz:\n\n[COK2_U:BARON2]\nsta cominciando a fidarsi di me.\n\n[COK2_1:BARON2]\nHo una domanda, però: perché 'Quentin'?\n\n[COK2_2:BARON2]\nNon lo so, mi è sempre piaciuto... Quentin Vance...\n\n[COK2_3:BARON2]\nVance? Tu sei Lance Vance?\n\n[COK2_4:BARON2]\nEhi, ne ho avuto abbastanza a scuola!\n\n[COK2_5:BARON2]\nHai mai provato a sparare con quelli da un elicottero?\n\n[COK2_8:BARON2]\nDove ci stiamo dirigendo?\n\n[COK2_9:BARON2]\nPrawn Island.\n\n[COK2_13:BARON2]\nLance Vance. Brutto bastardo.\n\n[COK2_14:BARON2]\nOK, siamo quasi arrivati.\n\n[COK2_15:BARON2]\nFaremo un paio di passaggi.\n\n[COK2_16:BARON2]\nCerca di colpire il maggior numero di nemici possibile.\n\n[COK2_17:BARON2]\nPoi ti scarico e dovrai cavartela da solo.\n\n[COK2_20:BARON2]\nMerda! Siamo in una zona di guerra! Abbatti un po' di gente!\n\n[COK2_21:BARON2]\nStiamo sotto tiro, amico!\n\n[COK2_22:BARON2]\nQuesto affare è maledettamente costoso da riparare! Falli fuori!\n\n[COK2_23:BARON2]\nOK, adesso dovrai cavartela da solo... Buona fortuna, fratello!\n\n[COK2_24:BARON2]\nCondizioni elicottero:\n\n[COK2_25:BARON2]\n~g~Recupera i soldi sul tetto.\n\n[COK2_27:BARON2]\nSei nel MIO territorio, stronzo!\n\n[COK2_28:BARON2]\nStai per affondare!\n\n[COK2_6:BARON2]\nNo. Farò un po' di pratica lungo la strada.\n\n[OPEN_B:BARON2]\nIl blocco stradale per la terraferma è stato rimosso.\n\n[COK2_V:BARON2]\nsta cominciando a fidarsi di me.\n\n{=================================== MISSION TABLE BARON3 ===================================}\n\n[COK3_A:BARON3]\nScommetto che adesso non vi divertite più!\n\n[COK3_B:BARON3]\nAh ah ah ah!\n\n[COK3_C:BARON3]\nWoh! Fai attenzione a dove punti quel coso.\n\n[COK3_D:BARON3]\nBasta con merda di piccione sulla MIA macchina, vero Tommy?\n\n[COK3_E:BARON3]\nDirei di sì.\n\n[COK3_F:BARON3]\nHai proprio ragione. Adesso ascolta:\n\n[COK3_G:BARON3]\nsai chi possiede la barca più veloce della costa est?\n\n[COK3_H:BARON3]\nNon così su due piedi.\n\n[COK3_I:BARON3]\nIO. E voglio che la situazione non cambi.\n\n[COK3_J:BARON3]\nOgni contrabbandiere da qui a Caracas ha un solo sogno: un'imbarcazione più veloce.\n\n[COK3_K:BARON3]\nSi mormora che il cantiere Hull-o-Caust ha appena finito di costruirne una\n\n[COK3_L:BARON3]\nper una testa di cazzo del Costa Rica.\n\n[COK3_M:BARON3]\nE Tommy... IO VOGLIO QUELLA BARCA!!!\n\n[COK3_N:BARON3]\nCredo che siano tornati i tuoi piccioni.\n\n[COK3_O:BARON3]\nAh! Pensavo di averti preso. Da dove salti fuori?\n\n[COK3_P:BARON3]\nPiccioni! Boom! Ah ah ah!\n\n[COK3_5:BARON3]\n~g~Trova l'interruttore per abbassare l'imbarcazione.\n\n[COK3_6:BARON3]\n~g~Porta la barca alla villa di Diaz.\n\n[COK3_7:BARON3]\n~r~Hai distrutto la barca!\n\n[COK3_8:BARON3]\n~g~Raggiungi il cantiere al porto e ruba la barca più veloce.\n\n[COK3_9:BARON3]\n~g~Adesso entra nella barca.\n\n{=================================== MISSION TABLE BARON4 ===================================}\n\n[COK4_A:BARON4]\nSputa fuori! CATORCIO DI PLASTICA!\n\n[COK4_B:BARON4]\nCome osi farmi questo?\n\n[COK4_C:BARON4]\nChi credi di essere, brutto pezzo di merdosa plastica! Aaarrgh!\n\n[COK4_D:BARON4]\nVAFFANCULO!\n\n[COK4_E:BARON4]\nSe hai distrutto il mio film favorito di El Burro ti spacco!\n\n[COK4_F:BARON4]\nChe altro posso fare?\n\n[COK4_G:BARON4]\nForse non è collegato...\n\n[COK4_H:BARON4]\nCosa?\n\n[COK4_I:BARON4]\nMerda... non importa, ne posso comprare a centinaia.\n\n[COK4_J:BARON4]\nAdesso Tommy,\n\n[COK4_K:BARON4]\nogni mese un freelance naviga fino a Vice City e ormeggia il suo yacht.\n\n[COK4_L:BARON4]\nVende il suo carico alla prima imbarcazione.\n\n[COK4_M:BARON4]\nVoglio che tu prenda la barca più veloce,\n\n[COK4_N:BARON4]\nbatta tutti gli altri stronzi\n\n[COK4_O:BARON4]\ne riporti qui il carico, OK?\n\n[COK4_P:BARON4]\nFammi indovinare, pensavi mi avrebbe fatto comodo un angelo custode?\n\n[COK4_Q:BARON4]\nVorrei solo che mi lasciassi venire, amico mio.\n\n[COK4_R:BARON4]\nPuoi continuare con queste stronzate alla rambo,\n\n[COK4_S:BARON4]\nma sono sicuro che un giorno o l'altro ti salverò il culo.\n\n[COK4_T:BARON4]\ne allora vorrai baciarmi!\n\n[COK4_U:BARON4]\nSei pazzo.\n\n[COK4_V:BARON4]\nAh ah ah!\n\n[COK4_1:BARON4]\nAllora Tommy, sappiamo che è stato Diaz a far saltare il nostro affare...\n\n[COK4_3:BARON4]\nAllora per quale motivo continuiamo a lavorare per lui?\n\n[COK4_4:BARON4]\nPiù cose scopriamo adesso, meno dovremo imparare quando ci impossesseremo di questa città!\n\n[COK4_5:BARON4]\nMi piace il tuo stile, amico. Molto fico.\n\n[COK4_12:BARON4]\nAttento, stanno arrivando da tutte le parti!\n\n[COK4_13:BARON4]\nPreso! Torniamo da Diaz il più velocemente possibile!\n\n[COK4_14:BARON4]\nNe vuoi un po'?\n\n[COK4_15:BARON4]\nSalutami i pesci!\n\n[COK4_16:BARON4]\nPrendi questo! E questo!\n\n[COK4_19:BARON4]\nAltri guai in arrivo!\n\n[COK4_20:BARON4]\nCi stanno sparando da quel molo!\n\n[COK4_24:BARON4]\nBel colpo, amico. Sei un vero pazzo di prima classe.\n\n[COK4_25:BARON4]\nBeh, grazie.\n\n[COK4_26:BARON4]\nCi vediamo, Tommy.\n\n[COK4_27:BARON4]\nOK, Mr. Lance Vance Dance.\n\n[COK4_28:BARON4]\n~g~Raggiungi lo yacht prima delle altre imbarcazioni!\n\n[COK4_31:BARON4]\n~g~Raggiungi la barca più veloce attraccata al molo!\n\n[COK4_32:BARON4]\n~r~Troppo lento!\n\n[COK4_33:BARON4]\n~r~Hai distrutto la barca!\n\n[COK4_34:BARON4]\n~g~Affonda quelle imbarcazioni!\n\n[COK4_35:BARON4]\nCondizioni barca:\n\n{=================================== MISSION TABLE BARON5 ===================================}\n\n[PROP_A:BARON5]\nPROPRIETÀ ACQUISITA!\n\n[COK4_30:BARON5]\n~r~Lance è morto!\n\n[ASS1_A:BARON5]\nHo messo un po' di cannoni nel bagagliaio.\n\n[ASS1_B:BARON5]\nAccidenti! Dove hai trovato tutta questa roba?\n\n[ASS1_C:BARON5]\nLa tenevo da parte per una giornata di pioggia.\n\n[ASS1_D:BARON5]\nTi piace?\n\n[ASS1_E:BARON5]\nSì, mi piace.\n\n[ASS1_F:BARON5]\nBrutto idiota...\n\n[ASS1_G:BARON5]\nLa mia bellissima casa...\n\n[ASS1_H:BARON5]\nGuarda cosa hai combinato!\n\n[ASS1_I:BARON5]\nQuesto è per mio fratello!\n\n[ASS1_J:BARON5]\nMi fidavo di te, Tommy!\n\n[ASS1_K:BARON5]\nTi avrei fatto diventare...\n\n[ASS1_L:BARON5]\nBuona notte, Mr. Diaz.\n\n[ASS1_1:BARON5]\nQuesto posto sarà zeppo di stronzi... fai attenzione...\n\n[ASS1_2:BARON5]\nNon preoccuparti, Tommy, ti copro io.\n\n[ASS1_4:BARON5]\nDiaz deve essere qui dentro!\n\n[ASS1_13:BARON5]\nDIAZ? Sono venuto a prendermi il tuo business!\n\n[ASS1_14:BARON5]\nTOMMY! Mi hai tradito... Idiota! Ti ucciderò fra un attimo!\n\n[ASS1_16:BARON5]\n~g~Uccidi Diaz!\n\n[BUD1:BARON5]\nLance\n\n[ASS1_18:BARON5]\n~g~La porta è chiusa: trova un percorso alternativo.\n\n[ASS1_19:BARON5]\nDi qua!\n\n[ASS1_20:BARON5]\nTommy, ho un problema con Quentin, non con te!\n\n{=================================== MISSION TABLE BIKE1 ===================================}\n\n[BM1_A:BIKE1]\nDov'è Baker?\n\n[BM1_B:BIKE1]\nSto cercando Big Mitch Baker...\n\n[BM1_C:BIKE1]\nChi lo cerca?\n\n[BM1_D:BIKE1]\nTommy Vercetti.\n\n[BM1_E:BIKE1]\nVercetti.\n\n[BM1_F:BIKE1]\nNon mi sembri della polizia, il che ti ha fatto guadagnare un minuto.\n\n[BM1_G:BIKE1]\nTi conviene parlare in fretta.\n\n[BM1_H:BIKE1]\nKent Paul mi ha detto che saresti stato interessato a occuparti della sorveglianza di uno spettacolo che sta allestendo.\n\n[BM1_I:BIKE1]\nKent Paul? Sheesh! Non mi stupisce abbia mandato te.\n\n[BM1_J:BIKE1]\nL'ultima volta che è stato qui è uscito dalla finestra con il vestitino che gli hanno dato alla nascita.\n\n[BM1_K:BIKE1]\nSei interessato o no?\n\n[BM1_L:BIKE1]\nFacciamo solo favori tra compagni.\n\n[BM1_M:BIKE1]\nCome faccio a diventarlo?\n\n[BM1_N:BIKE1]\nNon è uno circolo sportivo, amico. Sai guidare una moto?\n\n[BM1_O:BIKE1]\nSai sederti su uno sgabello e bere birra?\n\n[BM1_P:BIKE1]\nCougar, Zeppelin, scoprite se questa ragazzina sa portare una moto...\n\n[BM1_2:BIKE1]\n~g~Hai bisogno di una Freeway o di un'Angel per gareggiare!\n\n[BM1_3:BIKE1]\n~r~I partecipanti sono stati attaccati!\n\n[BIKE1_1:BIKE1]\nBene, bei vestiti. Vediamo cosa sai fare.\n\n[BM1_1:BIKE1]\n~g~Recupera una Freeway o un'Angel e posizionati sulla griglia di partenza.\n\n{=================================== MISSION TABLE BIKE2 ===================================}\n\n[BM2_1:BIKE2]\nCAOS:\n\n[BM2_A:BIKE2]\nAh ah ah, ti ho preso di nuovo!\n\n[BM2_B:BIKE2]\nEhi, Vercetti.\n\n[BM2_C:BIKE2]\nCougar ha detto che sai portare la moto come si deve.\n\n[BM2_D:BIKE2]\nGià, quanti altri giretti devo ancora fare?\n\n[BM2_E:BIKE2]\nSono un uomo molto impegnato.\n\n[BM2_F:BIKE2]\nSe serve una bella scazzottata per mettere le cose a posto, dillo chiaramente.\n\n[BM2_G:BIKE2]\nEssere uno di noi non significa solo azzuffarsi. Si tratta di far parte di una famiglia.\n\n[BM2_H:BIKE2]\nSì, sono già stato parte di una famiglia. Non ha funzionato.\n\n[BM2_I:BIKE2]\nSì, certo, ma questa famiglia si occupa dei suoi membri.\n\n[BM2_J:BIKE2]\nNon chiediamo a uno di fare il lavoro sporco per poi lasciarlo marcire quindici anni ai lavori forzati.\n\n[BM2_K:BIKE2]\nSì, esatto. Ho fatto la mia parte.\n\n[BM2_L:BIKE2]\nQuesta è la più grande famiglia di disadattati, reietti e derelitti.\n\n[BM2_M:BIKE2]\nMerda, alcuni di noi sono stati persino traditi dalla propria nazione.\n\n[BM2_N:BIKE2]\nSono stato imprigionato durante il Vietnam. Brutta storia.\n\n[BM2_O:BIKE2]\nEd è per questo che ti chiedo di far bollire la pentola.\n\n[BM2_P:BIKE2]\nQuesta fottuta nazione ha bisogno di un bel calcio nel culo, e saremo noi a darglielo.\n\n[BM2_Q:BIKE2]\nPer cui esci, prendi una moto e mostra a questa città quanto siamo arrabbiati!\n\n[BM2_R:BIKE2]\nVa bene.\n\n[BM2_2:BIKE2]\n~g~Devi riempire l'indicatore del caos entro il tempo stabilito per mostrare quanto sei arrabbiato!\n\n[BM2_3:BIKE2]\n~g~Questo suono indica che hai riempito parte dell'indicatore, continua così.\n\n[BM2_4:BIKE2]\n~r~Non sei riuscito a riempire l'indicatore del caos in tempo!\n\n{=================================== MISSION TABLE BIKE3 ===================================}\n\n[BM3_A:BIKE3]\nEhi, ciao Mitch.\n\n[BM3_B:BIKE3]\nAccidenti Vercetti, hai davvero le palle.\n\n[BM3_C:BIKE3]\nAdesso voglio vedere se sei pronto a combattere per la tua famiglia.\n\n[BM3_D:BIKE3]\nUna gang locale ha fatto l'errore di rubare il mio mezzo...\n\n[BM3_E:BIKE3]\nprobabilmente come prova di coraggio o qualcosa del genere.\n\n[BM3_F:BIKE3]\nIo e i miei uomini stavamo per andare a dar loro una lezione sul rispetto.\n\n[BM3_G:BIKE3]\nComunque,\n\n[BM3_H:BIKE3]\nho pensato che sarebbe stata un'ottima occasione per la tua iniziazione.\n\n[BM3_I:BIKE3]\nRiportami indietro la mia moto e potrai dire a Paul che avrà la sua sorveglianza.\n\n[BM3_2:BIKE3]\n~r~Dovevi riportare indietro la moto, non distruggerla!\n\n[BM3_3:BIKE3]\n~g~Riporta la moto al bar!\n\n[BM3_4:BIKE3]\n~g~Sali sulla moto!\n\n[INTRUDE:BIKE3]\n~g~Ti hanno visto!\n\n[BM3_6:BIKE3]\n~g~Si sono rintanati dietro Ammu-Nation in Downtown.\n\n[BM3_7:BIKE3]\n~g~Avrai bisogno di una moto più veloce per accedere al tetto.\n\n[BM3_8:BIKE3]\n~g~Usa la moto per saltare da queste scale fino al tetto nella parte più lontana della strada.\n\n[BM3_1:BIKE3]\n~g~Una gang locale ha rubato la Angel di Mitch Baker: riportala indietro!\n\n[BM3_9:BIKE3]\n~g~Recupera l'Angel di Mitch Baker e vattene!\n\n{=================================== MISSION TABLE BMX_1 ===================================}\n\n[BMX_REC:BMX_1]\n~g~Nuovo record stabilito: ~1~!!\n\n[GETBIK2:BMX_1]\nHai ~1~ secondi per salire su una Dirt Bike!\n\n{=================================== MISSION TABLE BOATBUY ===================================}\n\n[DRUG_1:BOATBUY]\nSalve? Saaalve? Salve?\n\n[DRUG_2:BOATBUY]\nTranquillo amico, sono qua.\n\n[DRUG_3:BOATBUY]\nEhi, damerino! Dimmi, sei il nuovo proprietario?\n\n[DRUG_4:BOATBUY]\nSì. Qual è la barca più veloce?\n\n[DRUG_5:BOATBUY]\nÈ già in acqua, amico,\n\n[DRUG_6:BOATBUY]\npensavo che la volessi provare.\n\n[DRUG_7:BOATBUY]\nAmico, ha già sopra un bel motore da 300 cavalli...\n\n[DRUG_8:BOATBUY]\n...e la struttura in vetroresina: vola davvero sull'acqua!\n\n[DRUG_9:BOATBUY]\nPuò andare da zero a sessanta in quattro secondi spaccati...\n\n[DRUG_10:BOATBUY]\ne può tenere venti pacchi della migliore erba giamaicana nella stiva!\n\n[DRUG_11:BOATBUY]\nDacci dentro, amico, è pronta a volare!\n\n[DRUG_12:BOATBUY]\nYo yo, uh, ehi amico, hai da accendere?\n\n[DRUG_13:BOATBUY]\nAmico?\n\n{=================================== MISSION TABLE CAP_1 ===================================}\n\n[CAP1_B1:CAP_1]\n~g~La Mafia sta tassando il tuo business. Trovali e falli fuori.\n\n[CAP1_B2:CAP_1]\n~g~La Mafia ha tassato il tuo cantiere navale!\n\n[CAP1_B3:CAP_1]\n~g~La Mafia ha tassato la tua fabbrica di gelato!\n\n[CAP1_B4:CAP_1]\n~g~La Mafia ha tassato la concessionaria!\n\n[CAP1_B5:CAP_1]\n~g~La Mafia ha tassato la tua compagnia di taxi!\n\n[CAP_01:CAP_1]\nOK, qual è l'emergenza?\n\n[CAP_02:CAP_1]\nCHI?\n\n[CAP_03:CAP_1]\nTommy... dei maledetti mafiosi... dicevano di essere venuti a prendere la loro fetta...\n\n[CAP_04:CAP_1]\n...dicevano che erano soldi di Mr. Forello... mi sento di merda.\n\n[CAP_05:CAP_1]\nForelli? SONNY Forelli?\n\n[CAP_06:CAP_1]\nSì, quel nome... credo... hanno davvero insistito...\n\n[CAP_07:CAP_1]\nNon preoccuparti amico, non sono arrabbiato con te.\n\n[CAP_08:CAP_1]\nPortalo all'ospedale.\n\n[CAP_09:CAP_1]\nTommy... fai a quel tipo un nuovo buco da cui cagare...\n\n[CAP_10:CAP_1]\nHo intenzione di fargliene due.\n\n[CAP1_2:CAP_1]\nConosci le regole, Vercetti!\n\n[CAP1_3:CAP_1]\nMr. Forelli manda i suoi saluti!\n\n[CAP1_4:CAP_1]\nÈ il macellaio di Harwood!\n\n[CAP1_5:CAP_1]\nDì a Sonny di stare alla larga!\n\n[CAP1_6:CAP_1]\nVice City è MIA adesso, NON sua.\n\n[CAP1_7:CAP_1]\nPensi di potermi tagliar fuori, Vercetti?\n\n[CAP1_8:CAP_1]\nTi inseguiremo fino a farti fuori, Vercetti.\n\n[CAP1_9:CAP_1]\nNon hai nessuna possibilità, brutto cazzone psicopatico.\n\n[CAP1_10:CAP_1]\nTi ucciderò, Vercetti.\n\n[CAP1_11:CAP_1]\nSei sempre stato uno stronzo.\n\n[CAP1_12:CAP_1]\nTi ammazzo, Vercetti.\n\n[CAP1_B6:CAP_1]\n~g~Hai trovato l'esattore: uccidilo!\n\n[CAP1_B7:CAP_1]\n~g~Hai perso l'esattore.\n\n[CAP1_B8:CAP_1]\n~r~L'esattore ha tassato tutte le tue proprietà.\n\n[CAP1_B9:CAP_1]\n~g~La Mafia ha tassato il Malibu!\n\n[CAP1_B0:CAP_1]\n~g~La Mafia ha tassato lo studio cinematografico!\n\n[CAP1_C2:CAP_1]\n~g~La Mafia è arrivata al cantiere navale!\n\n[CAP1_C3:CAP_1]\n~g~La Mafia è arrivata alla fabbrica di gelato!\n\n[CAP1_C4:CAP_1]\n~g~La Mafia è arrivata al concessionario!\n\n[CAP1_C5:CAP_1]\n~g~La Mafia è arrivata alla compagnia di taxi!\n\n[CAP1_C9:CAP_1]\n~g~La Mafia è arrivata al Malibu!\n\n[CAP1_C0:CAP_1]\n~g~La Mafia è arrivata allo studio cinematografico!\n\n[CAP1_D2:CAP_1]\n~g~La Mafia sta abbandonando il cantiere navale!\n\n[CAP1_D3:CAP_1]\n~g~La Mafia sta abbandonando la fabbrica di gelato!\n\n[CAP1_D4:CAP_1]\n~g~La Mafia sta abbandonando il concessionario!\n\n[CAP1_D5:CAP_1]\n~g~La Mafia sta abbandonando la compagnia di taxi!\n\n[CAP1_D9:CAP_1]\n~g~La Mafia sta abbandonando il Malibu!\n\n[CAP1_D0:CAP_1]\n~g~La Mafia sta abbandonando lo studio cinematografico!\n\n[CAP1B10:CAP_1]\nHai beccato gli esattori. Altri stanno arrivando.\n\n{=================================== MISSION TABLE CARBUY ===================================}\n\n[CAR1_1:CARBUY]\nB.J. Smith. E tu devi essere Mr. Vercetti.\n\n[CAR1_2:CARBUY]\nTi andrebbe un giro?\n\n[CAR1_3:CARBUY]\nPerché no.\n\n[CAR1_4:CARBUY]\nBene, mi dispiace un po' vendere il concessionario.\n\n[CAR1_5:CARBUY]\nÈ stato il mio primo investimento da quando mi sono messo in proprio.\n\n[CAR1_6:CARBUY]\nMa adesso è giunta l'ora di andare avanti.\n\n[CAR1_7:CARBUY]\nLasci la città?\n\n[CAR1_8:CARBUY]\nNon troppo in fretta, spero?\n\n[CAR1_9:CARBUY]\nNo. Sto per prepararmi al pensionamento e ai miei futuri investimenti.\n\n[CAR1_10:CARBUY]\nIl mercato non tirava molto,\n\n[CAR1_11:CARBUY]\ne la mia squadra si è preoccupata personalmente di diventare\n\n[CAR1_12:CARBUY]\npiù creativa nella produzione di contanti.\n\n[CAR1_13:CARBUY]\nLogicamente, potrei smantellare l'organizzazione prima di vendere.\n\n[CAR1_14:CARBUY]\nDiamine, potrei radere al suolo tutto quanto se volessi.\n\n[CAR1_15:CARBUY]\nQuest'area è in pieno sviluppo.\n\n[CAR1_16:CARBUY]\nOh, non mi preoccuperei di ciò.\n\n[CAR1_17:CARBUY]\nIl posto mi sembra perfetto.\n\n[CAR1_18:CARBUY]\nSì, lo è, allora siamo d'accordo?\n\n{=================================== MISSION TABLE CARPAR1 ===================================}\n\n[MM_1_A:CARPAR1]\n~g~Attraversa ~y~5 punti di controllo ~r~SENZA~g~ abbattere i ~r~CONI~g~! ~g~Puoi attraversarli in ~y~QUALSIASI ORDINE~g~.\n\n[CONE_1:CARPAR1]\n~r~Hai abbattuto un cono!\n\n[MM_1_C:CARPAR1]\n~y~ATTRAVERSA~g~ un punto di controllo per attivare il TIMER. ~g~Ogni punto di controllo ti fornirà ~y~~1~ SECONDI~g~ extra.\n\n{=================================== MISSION TABLE COPCAR ===================================}\n\n[KILLS:COPCAR]\nUCCISIONI:\n\n[C_BREIF:COPCAR]\n~g~Sospettato visto in prossimità dell'area ~a~.\n\n[C_PASS:COPCAR]\nMINACCIA ELIMINATA: ~1~$\n\n[COPCART:COPCAR]\n~g~Hai ~1~ secondi per tornare a un veicolo della polizia prima che la missione abbia termine.\n\n[C_CANC:COPCAR]\n~r~Missione Vigilante annullata!\n\n[C_TIME:COPCAR]\n~r~È scaduto il tuo tempo come tutore della legge!\n\n[C_COMP1:COPCAR]\nMissione Vigilante livello 12 completata: valore massimo dell'armatura aumentato a 150.\n\n[CLEVEL:COPCAR]\nMissione Vigilante livello ~1~\n\n{=================================== MISSION TABLE COUNT1 ===================================}\n\n[CM1_A:COUNT1]\nMr. Vercetti? Ehi, hai comprato la vecchia tipografia?\n\n[CM1_B:COUNT1]\nSì, il mio vecchio un tempo lavorava nel campo.\n\n[CM1_C:COUNT1]\nAvrei voluto seguire le sue orme, ma... ho deciso di vivere diversamente.\n\n[CM1_D:COUNT1]\nStai progettando di vendere il vecchio macchinario smontandolo in pezzi?\n\n[CM1_E:COUNT1]\nHo pensato che potremmo stampare ancora qualcosa... un giornale, una rivista...\n\n[CM1_F:COUNT1]\nChe merda, figliolo, roba di bassa qualità. Ho sempre sognato stampare soldi. Non è poi così difficile.\n\n[CM1_G:COUNT1]\nSai, l'ho fatto su scala ridotta per anni.\n\n[CM1_H:COUNT1]\nDavvero?\n\n[CM1_I:COUNT1]\nCerto. Ma prima abbiamo bisogno di matrici di buona qualità.\n\n[CM1_J:COUNT1]\nMa certo! C'è già un'organizzazione di falsificatori in azione in Florida.\n\n[CM1_K:COUNT1]\nUn'organizzazione?\n\n[CM1_L:COUNT1]\nSì. Beh, ho sentito solo delle voci.\n\n[CM1_M:COUNT1]\nConosco un tipo che si intende di voci...\n\n[CM1_N:COUNT1]\nUn tempo passavo le serate con lui, mentre pulivo i rulli...\n\n[CM1_2A:COUNT1]\nAccidenti che culo incredibile!\n\n[CM1_2B:COUNT1]\nVa bene, bellezza, sei tu che ci perdi!\n\n[CM1_2C:COUNT1]\nEhi, ciao amico, come butta?\n\n[CM1_2D:COUNT1]\nChe cosa sai della falsificazione?\n\n[CM1_2E:COUNT1]\nOh, sto bene Paul, e a te?\n\n[CM1_2F:COUNT1]\nVieni qua.\n\n[CM1_2G:COUNT1]\nVa bene! Va bene! Va bene! Sei ovviamente un tipo impegnato.\n\n[CM1_2H:COUNT1]\nTutto ciò che so sul campo è che la Triade fornisce le matrici.\n\n[CM1_2I:COUNT1]\nHanno una società di spedizioni nel porto,\n\n[CM1_2J:COUNT1]\nil capo di certo saprà quando passeranno nuovamente delle matrici!\n\n[CM1_2K:COUNT1]\nGrazie Paul.\n\n[CM1_2L:COUNT1]\nQual è il tuo problema, sei un maniaco!\n\n[CM1_2M:COUNT1]\nDammi un altro drink, in fretta!\n\n[CM1_3:COUNT1]\n~g~Ti hanno visto!\n\n[CM1_5:COUNT1]\n~g~Incontrati con Kent Paul al Malibu Club!\n\n[CNT1_1:COUNT1]\nChi sei? Oooof! Aaiieee! Non il viso! Non il viso!\n\n[CM1_1:COUNT1]\n~g~Vai alla compagnia marittima Chartered Libertine nel porto.\n\n[CM1_2:COUNT1]\n~g~L'ufficiale delle spedizioni è in possesso delle informazioni che ti servono.\n\n[CNT1_2:COUNT1]\nOK, parlerò, parlerò!\n\n[CM1_6:COUNT1]\n~g~Ritorna con le informazioni alla tipografia!\n\n{=================================== MISSION TABLE COUNT2 ===================================}\n\n[CNT2_B1:COUNT2]\nBene, il corriere porterà le matrici al porto oggi stesso.\n\n[CNT2_B2:COUNT2]\nHo intenzione di intercettare il corriere, recuperare le matrici, far perdere le tracce e tornare qua.\n\n[CNT2_B3:COUNT2]\nBene. A seconda di quanto bene vadano le cose,\n\n[CNT2_B4:COUNT2]\npotremmo avere cinque minuti per stampare soldi prima che l'associazione dei falsificatori ci trovi, o potremmo avere tutto l'anno.\n\n[CNT2_B5:COUNT2]\nIn ogni caso, voglio veder bigliettoni verdi uscire cinque minuti dopo che sarò tornato. Tutto chiaro?\n\n[CNT2_B6:COUNT2]\nNon preoccuparti, Tommy. Saremo pronti.\n\n[CNT2_B7:COUNT2]\nIo e i ragazzi saremo in giro per il quartiere se mai dovessi avere bisogno di una mano con gli inseguitori.\n\n[CNT2_B8:COUNT2]\nOttimo: siete tutti pronti? Perfetto. Ci vediamo più tardi...\n\n[CNT2_01:COUNT2]\n~g~Il ~r~corriere~g~ con le matrici arriverà fra pochi attimi al ~y~porto~g~ in elicottero.\n\n[CNT2_02:COUNT2]\n~r~Il corriere è scappato con l'elicottero.\n\n[CNT2_03:COUNT2]\n~r~Il corriere è arrivato a destinazione sano e salvo. Sei in ritardo!\n\n[CNT2_04:COUNT2]\n~r~Hai distrutto le matrici nell'esplosione!\n\n[CNT2_05:COUNT2]\n~g~Hai preso le matrici. Riportale alla tipografia.\n\n[CNT2_06:COUNT2]\n~g~Il corriere è morto e ha lasciato cadere le matrici: raccoglile prima che lo faccia qualcun altro.\n\n[CNT2_07:COUNT2]\n~g~Una delle guardie ha raccolto le matrici: non lasciarlo scappare!\n\n[CNT2_08:COUNT2]\n~g~Il ~r~corriere~g~ con le matrici è arrivato al porto.\n\n[CNT2_4:COUNT2]\nFaccende private, non sei il ben venuto.\n\n[CNT2_09:COUNT2]\nBENI TIPOGRAFIA ACQUISITI\n\n[CNT2_10:COUNT2]\n~g~La tipografia d'ora in poi genererà introiti per un massimo di ~1~$. Ricordati di recuperarli regolarmente.\n\n[CNT2_11:COUNT2]\n~r~Le matrici adesso sono in fondo all'oceano!\n\n{=================================== MISSION TABLE CUBAN1 ===================================}\n\n[CUB1_A:CUBAN1]\nSì amico?\n\n[CUB1_B:CUBAN1]\nEhi, tranquillo papà, è venuto per me. Sei tu l'uomo?\n\n[CUB1_C:CUBAN1]\nOh sì, sei tu l'uomo. Credo per lo meno, vero?\n\n[CUB1_D:CUBAN1]\nNo, non credo.\n\n[CUB1_E:CUBAN1]\nAh sì? Vieni qua, osso duro.\n\n[CUB1_F:CUBAN1]\nPensi di potermi prendere in giro?\n\n[CUB1_G:CUBAN1]\nCredi di poter fare lo stupido con me?\n\n[CUB1_H:CUBAN1]\nNo, credo tu stia facendo abbastanza lo stupido per entrambi.\n\n[CUB1_I:CUBAN1]\nEhi figliolo, ha detto che sei stupido.\n\n[CUB1_J:CUBAN1]\nE io lo chiamo femminuccia, papà.\n\n[CUB1_K:CUBAN1]\nGuarda un po' come va in giro vestito.\n\n[CUB1_L:CUBAN1]\nChe cos'è questa? L'ultima moda femminile per la notte?\n\n[CUB1_M:CUBAN1]\nPerché un osso duro come te si veste da donnina?\n\n[CUB1_N:CUBAN1]\nHai le mutandine come le signorine, eh?\n\n[CUB1_O:CUBAN1]\nCos'hai contro le donne? Preferisci gli uomini, amico?\n\n[CUB1_P:CUBAN1]\nMi piacciono le donne! Tutte le donne! Adoro mia madre, chico.\n\n[CUB1_Q:CUBAN1]\nVa bene, va bene, ti credo sulla parola.\n\n[CUB1_R:CUBAN1]\nSai guidare, amigo?\n\n[CUB1_S:CUBAN1]\nCerto... come una donna.\n\n[CUB1_T:CUBAN1]\nMolto divertente. Mi piaci, ragazzo. Forse ci puoi aiutare.\n\n[CUB1_U:CUBAN1]\nPotresti provare di essere un uomo. Huh?\n\n[CUB1_V:CUBAN1]\nPorta fuori la barca.\n\n[CUB1_W:CUBAN1]\nMostra di avere due grossi cojones,\n\n[CUB1_X:CUBAN1]\ne non piccoli minuscoli chiquita.\n\n[CUB1_02:CUBAN1]\nOK amico, trattala come una vera signora.\n\n[CUB1_03:CUBAN1]\nNon male, sei un vero uomo.\n\n[CUB1_04:CUBAN1]\nAccidenti, hai davvero due grossi cojones, amigo.\n\n[CUB1_05:CUBAN1]\nAmigo, sei un vero uomo.\n\n[CUB1_06:CUBAN1]\nE tu ti reputi un uomo?\n\n[CUB1_07:CUBAN1]\nSei un piccolo gattino impaurito, bamboccio: vai a piangere dalla mamma!\n\n[CUB1_08:CUBAN1]\nSei un grande spreco di spazio. Cammini come un uomo, parli come un uomo, ma guidi come un idiota.\n\n[CUB1_09:CUBAN1]\nAmico, sei tu l'uomo. Mi piaci, amico. Mi piaci molto.\n\n[CUB1_10:CUBAN1]\nA qualsiasi ora, amico, perché tu hai i cojones e tutti i miei amici hanno grandi cajones.\n\n[CUB1_11:CUBAN1]\n~r~Hai ucciso Rico!\n\n[CUB1_12:CUBAN1]\nPassa per il primo punto di controllo per cominciare il test.\n\n[CUB1_14:CUBAN1]\nTorna alla barca!\n\n[CUB1_15:CUBAN1]\n~r~Sei troppo lento, amico.\n\n[CUB1_01:CUBAN1]\nEhi, sono Rico. Sei tu l'uomo con i grandi cojones?\n\n[CUB1_13:CUBAN1]\n~g~Hai tre minuti per completare il percorso.\n\n{=================================== MISSION TABLE CUBAN2 ===================================}\n\n[CUB2_A:CUBAN2]\nUn cafecito, por favor, Alberto...\n\n[CUB2_N:CUBAN2]\nNessun problema, Tommy.\n\n[CUB2_B:CUBAN2]\nPapà! Un gran problema!\n\n[CUB2_O:CUBAN2]\nUmberto, figlio mio, cosa succede?\n\n[CUB2_C:CUBAN2]\nGli Haitiani! Odio quei maledetti Haitiani!\n\n[CUB2_D:CUBAN2]\nHanno osato crearmi problemi per l'ultima vota!\n\n[CUB2_E:CUBAN2]\nQuesti Haitiani. Facciamoli fuori!\n\n[CUB2_F:CUBAN2]\nAvremo bisogno di supporto.\n\n[CUB2_G:CUBAN2]\nHo già perso degli hermanos là fuori.\n\n[CUB2_H:CUBAN2]\nAmigo, tu guidi bene!\n\n[CUB2_I:CUBAN2]\nPer una donna, giusto?\n\n[CUB2_J:CUBAN2]\nNon è il momento degli scherzi!\n\n[CUB2_K:CUBAN2]\nForza, guida nuovamente per me!\n\n[CUB2_L:CUBAN2]\nPorta i miei ragazzi in posizione e faremo fuori quegli Haitiani!\n\n[CUB2_M:CUBAN2]\nSi sono messi contro me, hanno scherzato con il pezzo grosso della città!\n\n[CUB2_01:CUBAN2]\nTroppo piccola, amico, devi prendere una macchina più grande.\n\n[CUB2_02:CUBAN2]\nAbbiamo bisogno di rinforzi dal café!\n\n[CUB2_03:CUBAN2]\n~g~Prendi una macchina e recupera i Cubani di fronte al café Robina.\n\n[CUB2_04:CUBAN2]\n~g~Scarica i Cubani sul luogo dello scontro.\n\n[CUB2_05:CUBAN2]\nFai fuori quel codardo di un cecchino!\n\n[CUB2_07:CUBAN2]\nCombattono come donnicciole! Mettetevi al riparo!\n\n[CUB2_09:CUBAN2]\nCecchino sul tetto!\n\n[CUB2_11:CUBAN2]\n~r~Idiota, avevamo bisogno della macchina.\n\n[CUB2_12:CUBAN2]\nEhi amigo! Sono felice che ce l'hai fatta.\n\n[CUB2_13:CUBAN2]\nCovo puzzolente di Haitiani, li uccideremo tutti!\n\n[CUB2_14:CUBAN2]\nCAAARICAAAA!\n\n[CUB2_15:CUBAN2]\nAdesso, fratelli, CAAARICAAAA!\n\n[CUB2_16:CUBAN2]\nTommy, abbiamo provato il nostro coraggio!\n\n[CUB2_17:CUBAN2]\nRubiamo quel van pieno di droga e scappiamo in fretta!\n\n[CUB2_18:CUBAN2]\n~g~Recupera una macchina per caricare i Cubani.\n\n[CUB2_19:CUBAN2]\nCombatteremo come uomini!\n\n[CUB2_21:CUBAN2]\nCombattiamo come uomini con grandi cojones!\n\n[CUB2_22:CUBAN2]\n~g~Elimina il resto degli Haitiani così i Cubani potranno avanzare.\n\n[CUB2_23:CUBAN2]\n~g~Little Haiti sarà piena di Haitiani desiderosi di pareggiare il conto con i Cubani. Guardati la schiena.\n\n[CUB2_24:CUBAN2]\n~g~Torna al Café Robina con il van e parcheggialo sul retro.\n\n[CUB2_25:CUBAN2]\nUCCIDI TUTTI GLI HAITIANI!!!\n\n{=================================== MISSION TABLE CUBAN3 ===================================}\n\n[CUB3_A:CUBAN3]\nAlberto. Un caffè, senor.\n\n[CUB3_B:CUBAN3]\nPapà, non servire questo serpente nascosto nella paglia.\n\n[CUB3_C:CUBAN3]\nSei un doppiogiochista, Tommy!\n\n[CUB3_D:CUBAN3]\nO fai il doppio gioco o sei un perdente, ragazzo!\n\n[CUB3_E:CUBAN3]\nGli Haitiani! Merda, stanno ridendo di me.\n\n[CUB3_F:CUBAN3]\nEhi. Calmati. Qual è il tuo problema?\n\n[CUB3_G:CUBAN3]\nRidono di me, Tommy! Di me!\n\n[CUB3_H:CUBAN3]\nUmberto Robina! Fanno tutto ciò che vogliono!\n\n[CUB3_I:CUBAN3]\nNessuno fa ciò che vuole, Umberto, fanno ciò che tu permetti loro di fare.\n\n[CUB3_J:CUBAN3]\nCosa?\n\n[CUB3_K:CUBAN3]\nVuoi che mi occupi di qualcuno?\n\n[CUB3_L:CUBAN3]\nPosso pensarci io, ma ti costerà.\n\n[CUB3_M:CUBAN3]\nLo so che siamo come fratelli, ma stiamo parlando di affari.\n\n[CUB3_N:CUBAN3]\nTommy, sei un vero uomo. Un vero businessman, un gentleman.\n\n[CUB3_O:CUBAN3]\nQuesti Haitiani. Hanno un carico di merce in arrivo via mare, roba di prima qualità.\n\n[CUB3_P:CUBAN3]\nLa prendiamo e li facciamo fuori.\n\n[CUB3_Q:CUBAN3]\nTu la prendi, io ti copro. Come mio fratello, come mio figlio.\n\n[CUB3_R:CUBAN3]\nPreferisco i soldi che saltellare sulle tue gambe, amigo.\n\n[CUB3_01:CUBAN3]\nEhi Rico, bella barca. Sei pronto?\n\n[CUB3_03:CUBAN3]\n~g~Raccogli tutte le valigette piene di soldi e droga.\n\n[CUB3_04:CUBAN3]\n~g~Riporta la droga e i soldi a Umberto.\n\n[CUB3_05:CUBAN3]\nSì Tommy. Vedi di sparare come si deve oggi,\n\n[CUB3_06:CUBAN3]\nnon voglio riempire la mia barca di buchi, OK?\n\n[CUB3_07:CUBAN3]\n~g~Incontrati con Rico, lui ti porterà fino alla locazione dell'incontro.\n\n[CUB3_02:CUBAN3]\n~g~UCCIDI TUTTI GLI HAITIANI SULLE BARCHE!!!\n\n[CUB3_08:CUBAN3]\nUh oh... un gruppo di Cubani. Siamo sotto attacco!\n\n{=================================== MISSION TABLE CUBAN4 ===================================}\n\n[CUB4_A:CUBAN4]\nEhi signorine, sapete che cosa voglio fare?\n\n[CUB4_B:CUBAN4]\nVoglio far fuori un Haitiano. E poi?\n\n[CUB4_C:CUBAN4]\nPoi voglio fare l'amore come un vero uomo.\n\n[CUB4_D:CUBAN4]\nCapito chica? Proprio così.\n\n[CUB4_E:CUBAN4]\nFallito!\n\n[CUB4_F:CUBAN4]\nCafone.\n\n[CUB4_G:CUBAN4]\nEhi bella, non ti toccherei neanche con un bastone da lontano!\n\n[CUB4_H:CUBAN4]\nUmberto Robina, a lui piacciono le vere donne! Non delle capre in minigonna!\n\n[CUB4_I:CUBAN4]\nTommy! Tommy, ti voglio bene, davvero! Andiamo!\n\n[CUB4_J:CUBAN4]\nDove? Non posso prendere prima una tazza di caffè?\n\n[CUB4_K:CUBAN4]\nNon c'è tempo per il caffè! Inoltre, io l'ho già preso.\n\n[CUB4_L:CUBAN4]\nDobbiamo far fuori gli Haitiani.\n\n[CUB4_M:CUBAN4]\nTommy, come fai a uccidere un serpente?\n\n[CUB4_N:CUBAN4]\nLo mordi sul culo! Ah ah ah!\n\n[CUB4_O:CUBAN4]\nSe lo dici te, Umberto.\n\n[CUB4_P:CUBAN4]\nTommy, recupera una piccola auto Haitiana.\n\n[CUB4_Q:CUBAN4]\nQuando ce l'hai, torna qui e carica il mio ragazzo,\n\n[CUB4_R:CUBAN4]\nPepe, e portalo fino agli Haitiani.\n\n[CUB4_S:CUBAN4]\nPoi aggiri l'impianto di lavorazione degli Haitiani e utilizzi il solvente come esplosivo.\n\n[CUB4_T:CUBAN4]\nBoom! Bye bye!\n\n[CUB4_U:CUBAN4]\nUmberto, e tu?\n\n[CUB4_V:CUBAN4]\nOh, io resto nelle retrovie e controllo il café con papà.\n\n[CUB4_W:CUBAN4]\nNon si sente molto bene, sai?\n\n[CUB4_02:CUBAN4]\n~g~Le bombe verranno piazzate con un timer di 45 secondi.\n\n[CUB4_04:CUBAN4]\n~r~Hai allarmato la base, adesso non riusciremo mai a entrare!\n\n[CUB4_07:CUBAN4]\nIl solvente è sul retro, amigo.\n\n[CUB4_08:CUBAN4]\nHola, Amigos.\n\n[CUB4_09:CUBAN4]\nBueno. Haitiane Putas. Muerte.\n\n[CUB4_10:CUBAN4]\nVamos.\n\n[CUB4_11:CUBAN4]\nVamos davvero.\n\n[CUB4_12:CUBAN4]\nEhi, abbiamo bisogno di un'auto degli Haitiani!\n\n[CUB4_13:CUBAN4]\nOye, andiamo a trovare i nostri muchachos!\n\n[CUB4_14:CUBAN4]\nSeguimi, compadres.\n\n[CUB4_15:CUBAN4]\nOK, vai dentro...\n\n[CUB4_16:CUBAN4]\nIo posizionerò le bombe, coprimi!\n\n[CUB4_17:CUBAN4]\nCORRI!\n\n[CUB4_18:CUBAN4]\nAmico, questa sì che è una bella parte della città...\n\n[CUB4_19:CUBAN4]\nQuesto luogo è una fogna.\n\n[CUB4_20:CUBAN4]\nAvevo una bella donna... viveva da queste parti.\n\n[CUB4_21:CUBAN4]\nLo sai, fanno delle buone pizze da queste parti.\n\n[CUB4_22:CUBAN4]\nWhoa, amico. Guidi come un cavallo impazzito!\n\n[CUB4_23:CUBAN4]\nTi sei perso, amico?\n\n[CUB4_24:CUBAN4]\nHai lasciato indietro Pepe, vai a riprenderlo!\n\n[CUB4_03:CUBAN4]\n~g~Resta in macchina fino a quando questa non sarà parcheggiata all'interno.\n\n[CUB4_26:CUBAN4]\n~g~Prendi Pepe, dirigiti a nord verso Little Haiti e ruba una macchina Voodoo.\n\n[CUB4_27:CUBAN4]\n~g~Raggiungi Rico e gli altri Cubani.\n\n[CUB4_28:CUBAN4]\n~g~Unisciti agli altri Cubani presso la fabbrica di droga Haitiana.\n\n[CUB4_29:CUBAN4]\n~g~Cammina su ogni segnalino per posizionare una bomba.\n\n[CUB4_30:CUBAN4]\n~g~Dopo aver posizionato tutte e tre le bombe, scappa dalla fabbrica prima che esploda.\n\n[CUB4_31:CUBAN4]\n~g~Scappa dalla fabbrica!!!\n\n[CUB4_32:CUBAN4]\n~g~Parcheggia l'auto nel punto segnalato ed esci.\n\n[CUB4_06:CUBAN4]\n~r~Non ti sei allontanato a sufficienza dalla base e abbiamo dovuto interrompere l'esplosione!\n\n{=================================== MISSION TABLE FINALE ===================================}\n\n[FIN_1A:FINALE]\nVieni qui brutto doppiogiochista di merda!\n\n[FIN_1B:FINALE]\nTi faccio a pezzi, traditore del cazzo!\n\n[FIN_1C:FINALE]\nQuesto è l'ultimo ballo per Lance Vance!\n\n[FIN_2B:FINALE]\nOh, ma davvero!\n\n[FIN_2C:FINALE]\nTe l'avevo detto che ne avevo avuto abbastanza a scuola!\n\n[FIN_3:FINALE]\nAdesso chi ti coprirà il culo, eh Tommy?\n\n[FIN_4:FINALE]\nSei storia, Tommy, storia!\n\n[FIN_5:FINALE]\nHai scelto il lato sbagliato, Lance...\n\n[FIN_11A:FINALE]\nSonny, mi hai rubato quindici anni di vita...\n\n[FIN_11B:FINALE]\nE adesso te la farò pagare!\n\n[FIN_12A:FINALE]\nNon hai ancora capito, vero?\n\n[FIN_12B:FINALE]\nIo ti POSSIEDO, Tommy.\n\n[FIN_12C:FINALE]\nQuei quindici anni erano miei!\n\n[FIN_13:FINALE]\nPrendetelo ragazzi, non ha mai capito niente.\n\n[FIN1_01:FINALE]\nCosa sta succedendo?\n\n[FIN1_02:FINALE]\nTommy! Oh bene, bene. Ascolta, ascolta. Uh, ascolta.\n\n[FIN1_03:FINALE]\nA me piacciono i pesci. Adoro i pesci.\n\n[FIN1_04:FINALE]\nMi piacciono quando nuotano in una boccia o come cibo in un piatto,\n\n[FIN1_05:FINALE]\nma per quanto li ami, non voglio dormire in loro compagnia.\n\n[FIN1_06:FINALE]\nVa bene, ma adesso i tuoi fratelli italiani stanno venendo per mettermi ai piedi delle belle scarpe in cemento e io...\n\n[FIN1_07:FINALE]\nSta zitto Ken. Siediti.\n\n[FIN1_08:FINALE]\nLance, di che diavolo stai parlando?\n\n[FIN1_09:FINALE]\nSono i tuoi amici del nord, Tommy. Non sono felici di cosa hai fatto al loro uomo.\n\n[FIN1_10:FINALE]\nOggi verranno giù per questioni di lavoro.\n\n[FIN1_11:FINALE]\nCi hanno messo di più di quanto credessi...\n\n[FIN1_12:FINALE]\nRagazzi, dobbiamo essere molto chiari. Non voglio che ci siano dubbi sul fatto che questa è la mia operazione. MIA!\n\n[FIN1_13:FINALE]\nKen, recupera la prima partita di soldi falsi e metti venti milioni in delle valigette.\n\n[FIN1_14:FINALE]\nLance, raduna i ragazzi...\n\n[FIN2_01:FINALE]\nTommy!\n\n[FIN2_02:FINALE]\nCosa? Niente abbraccio per un vecchio amico?\n\n[FIN2_03:FINALE]\nSono stato per quindici anni fuori dal giro,\n\n[FIN2_04:FINALE]\nsono un po' arrugginito in fatto di etichetta familiare.\n\n[FIN2_05:FINALE]\nSempre arrabbiato, vero Tommy?\n\n[FIN2_06:FINALE]\nNon ti avevo detto che il tuo carattere ti avrebbe messo nei guai, eh?\n\n[FIN2_07:FINALE]\nCi sono venti milioni in quelle valigette...\n\n[FIN2_08:FINALE]\nQuanti hai detto? Dieci? No, undici uomini.\n\n[FIN2_09:FINALE]\nÈ così che sei diventato il macellaio di Harwood! Eh eh eh!\n\n[FIN2_10:FINALE]\nMi hai inviato per uccidere un uomo, UN UOMO. Sapevano che stavo arrivando Sonny...\n\n[FIN2_11:FINALE]\nModera il tono.\n\n[FIN2_12:FINALE]\nQualcuno potrebbe pensare che stai incolpando me per le sfortunate circostanze.\n\n[FIN2_13:FINALE]\nPrendi i fottuti soldi...\n\n[FIN2_14:FINALE]\nPrendi i fottuti soldi?\n\n[FIN2_15:FINALE]\nLo sai, Tommy? Ho fatto quello che ho potuto per te. Ho tirato i fili, ho chiesto favori.\n\n[FIN2_16:FINALE]\nEro tuo amico, Tommy. Pensavo che avresti avuto buon senso, che avresti capito cosa è bene per il business.\n\n[FIN2_17:FINALE]\nMi fidavo di te, Tommy. E tu mi hai deluso.\n\n[FIN2_18:FINALE]\nMa alla fine qualcuno nella tua organizzazione del cazzo ha capito come si fa il business.\n\n[FIN2_19:FINALE]\nNon è vero, Lance?\n\n[FIN2_20:FINALE]\nMi dispiace Tommy. Questa è Vice City. Questo è il suo business.\n\n[FIN2_21:FINALE]\nCi hai venduto...\n\n[FIN2_22:FINALE]\nNo. Ho venduto TE, Tommy, ho venduto TE.\n\n[FIN2_23:FINALE]\nI soldi veri sono di sopra nella cassaforte.\n\n[FIN2_24:FINALE]\nAllora Tommy, questo era il grande piano?\n\n[FIN2_25:FINALE]\nPensavi davvero che avrei preso i soldi finti?\n\n[FIN2_26:FINALE]\nSalva la faccia e scappa con la coda tra le gambe!\n\n[FIN2_27:FINALE]\nNo.\n\n[FIN2_28:FINALE]\nVolevo solo farti incazzare prima di ucciderti.\n\n[FIN3_01:FINALE]\nTommy?\n\n[FIN3_02:FINALE]\nOh mio Dio, Tommy! Che cosa è successo?\n\n[FIN3_03:FINALE]\nChe cosa ti sembra sia successo?\n\n[FIN3_04:FINALE]\nMi sembra ti si sia rovinato l'abito!\n\n[FIN3_05:FINALE]\nAccidenti, Tommy, era così bello! Tommy, che diavolo è successo?\n\n[FIN3_06:FINALE]\nHo avuto una divergenza di vedute con un socio in affari, sai come vanno queste cose.\n\n[FIN3_07:FINALE]\nTommy, se io ho una divergenza con un socio, gli mando una lettera di insulti.\n\n[FIN3_08:FINALE]\nForse gli piscio nella casella della posta. Ma non do il via alla terza guerra mondiale!\n\n[FIN3_09:FINALE]\nLo sai, forse dovresti parlare con il mio strizzacervelli...\n\n[FIN3_10:FINALE]\nQuello stupido idiota, Lance...\n\n[FIN3_11:FINALE]\nTommy, non mi è mai piaciuto quel tipo, OK?\n\n[FIN3_12:FINALE]\nÈ nevrotico, insicuro, egocentrico... quel tipo è un vero stronzo!\n\n[FIN3_13:FINALE]\nSono felice che l'hai fatto fuori!\n\n[FIN3_14:FINALE]\nNon penso che riceveremo ulteriori problemi dal nord...\n\n[FIN3_15:FINALE]\n...fondamentalmente perché non c'è più un 'nord'.\n\n[FIN3_16:FINALE]\nAdesso è tutto a sud.\n\n[FIN3_17:FINALE]\nAspetta, vuoi forse dire ciò che penso io, caro il mio Tommy?\n\n[FIN3_18:FINALE]\nCosa credi che significhi?\n\n[FIN3_19:FINALE]\nChe siamo in carica... cioè, che sei in carica! Oh Tommy...\n\n[FIN3_20:FINALE]\nLo sai, Ken, questo potrebbe essere l'inizio di uno splendido rapporto lavorativo...\n\n[FIN3_21:FINALE]\nDopo tutto, tu sei un convincente, diffamante, fottuto ladro.\n\n[FIN3_22:FINALE]\ne io sono uno psicopatico assassino convinto e uno spacciatore.\n\n[FIN3_23:FINALE]\nLo so, non è meraviglioso?\n\n[FIN_B1:FINALE]\n~g~Uccidi ~y~Vance~g~, il fottuto traditore.\n\n[FIN_B2:FINALE]\n~g~Trova ~p~Sonny~g~ e metti la parola fine a questa storia.\n\n[FIN_B3:FINALE]\n~g~La Mafia sta cercando di rubare i tuoi soldi. Difendi la cassaforte.\n\n[FIN_B4:FINALE]\n~g~Sei prossimo alla morte: recupera della ~w~salute~g~ dal basso.\n\n[FIN_B5:FINALE]\n~g~La Mafia sta rubando i tuoi soldi. Difendi la ~c~cassaforte~g~.\n\n[FIN_B7:FINALE]\n~r~La Mafia ha rubato i tuoi soldi!\n\n[DEFSAFE:FINALE]\n~g~Ritorna alla cassaforte e difendila.\n\n{=================================== MISSION TABLE FIRETRK ===================================}\n\n[F_PASS1:FIRETRK]\nIncendio spento!\n\n[F_FAIL2:FIRETRK]\n~r~Sei arrivato tardi!\n\n[F_CANC:FIRETRK]\n~r~Missione Pompieri annullata!\n\n[F_EXTIN:FIRETRK]\nINCENDI:\n\n[F_START:FIRETRK]\n~g~Veicolo in fiamme avvistato in ~a~. Vai a spegnere il fuoco.\n\n[SIREN_1:FIRETRK]\nPer attivare la sirena di questo veicolo premi il ~h~~k~~VEHICLE_HORN~~w~.\n\n[SIREN_2:FIRETRK]\nPer attivare la sirena di questo veicolo premi il ~h~~k~~VEHICLE_HORN~~w~.\n\n[FIREPRO:FIRETRK]\nMissione Camion dei pompieri livello 12 completata: adesso sei permanentemente ignifugo!!!\n\n[F_FAIL1:FIRETRK]\nMissione Camion dei pompieri terminata.\n\n[F_STAR1:FIRETRK]\n~g~Veicoli in fiamme presso l'area ~a~. Vai a spegnere l'incendio.\n\n[SPRAY_4:FIRETRK] { reVC update }\nPremi il tasto ~h~~k~~VEHICLE_FIREWEAPON~~w~ per sparare con il cannone ad acqua e la ~h~~k~~VEHICLE_TURRETLEFT~~w~ e ~h~~k~~VEHICLE_TURRETRIGHT~~w~ per mirare.\n\n[SPRAY_1:FIRETRK] { reVC update }\nPremi il tasto ~h~~k~~VEHICLE_FIREWEAPON~~w~ per sparare con il cannone ad acqua e la ~h~~k~~VEHICLE_TURRETLEFT~~w~ e ~h~~k~~VEHICLE_TURRETRIGHT~~w~ per mirare.\n\n{=================================== MISSION TABLE GENERA1 ===================================}\n\n[GEN1_A:GENERA1]\nMr. Vercetti!\n\n[GEN1_B:GENERA1]\nColonnello.\n\n[GEN1_D:GENERA1]\nNo, grazie.\n\n[GEN1_E:GENERA1]\nMi vergogno ad ammettere che una delle cause dei nostri problemi comuni sembra sia stata la linguaccia di una persona di cui credevo di potermi fidare.\n\n[GEN1_F:GENERA1]\nMi sono tenuto Gonzalez per anni, ma ora la sua incompetenza ha raggiunto il fondo.\n\n[GEN1_G:GENERA1]\nSarebbe solo un bene se eliminassi Gonzalez...\n\n[GEN1_H:GENERA1]\nÈ stato lui? A me importa solo dei miei soldi.\n\n[GEN1_I:GENERA1]\nQuesta gentilezza verrà ricompensata dopo troveremo insieme i tuoi soldi.\n\n[GEN1_J:GENERA1]\nLo troverai nella sua Penthouse, probabilmente mezzo ubriaco. Usa questo...\n\n[GEN1_06:GENERA1]\nEeek! Ha una motosega!\n\n[GEN1_07:GENERA1]\nStammi lontano, brutto bastardo!\n\n[GEN1_08:GENERA1]\nOddio santo, ho distrutto la mia vita e il mio look!\n\n[GEN1_10:GENERA1]\nHo deciso di chiudere quella tua maledetta boccaccia!\n\n[GEN1_11:GENERA1]\nSmettila di correre, brutto grassone!\n\n[GEN1_12:GENERA1]\nStai fermo, così la facciamo finita!\n\n[GEN1_13:GENERA1]\nSmettila di strillare, non gliene frega a nessuno, grassone!\n\n[GEN1_C:GENERA1]\nGrazie per essere venuto. Siediti. Vuoi dell'aragosta?\n\n[GEN1_05:GENERA1]\n~g~Uccidi Gonzalez!\n\n[GEN1_09:GENERA1]\nTi pagherò doppio, Tommy, DOPPIO!\n\n[GEN1_18:GENERA1]\n~r~Gonzalez ha raggiunto sano e salvo la stazione di polizia!\n\n[GEN1_19:GENERA1]\n~g~La polizia di Vice City ti sta inseguendo!\n\n[GEN1_20:GENERA1]\n~g~Prendi un veicolo.\n\n[GEN1_21:GENERA1]\n~g~Raggiungi il ~h~Pay 'N' Spray~g~ in ~h~Vice Point~g~.\n\n[GEN1_22:GENERA1]\n~g~Guida il tuo veicolo attraverso il carrozziere per perdere il ~h~livello di sospetto~g~, ~h~riparare~g~ e ~h~ricolorare~g~ il mezzo. Costo: ~h~100$~g~. Questa volta è gratis.\n\n[GEN1_01:GENERA1]\nQuando corri, tieni premuto il ~o~tasto |~w~ per preparare un attacco corpo a corpo.\n\n[GEN1_02:GENERA1]\nQuando corri, tieni premuto il ~x~tasto /~w~ per preparare un attacco corpo a corpo.\n\n[GEN1_03:GENERA1]\nQuando corri, tieni premuto il ~h~tasto R1~w~ per preparare un attacco corpo a corpo.\n\n[GEN1_14:GENERA1]\nRilascia il ~h~~k~~PED_FIREWEAPON~~w~ per eseguire l'attacco.\n\n[GEN1_15:GENERA1]\nRilascia il ~h~~k~~PED_FIREWEAPON~~w~ per eseguire l'attacco.\n\n[GEN1_16:GENERA1]\nRilascia il ~h~~k~~PED_FIREWEAPON~~w~ per eseguire l'attacco.\n\n[GEN1_23:GENERA1]\n~g~Passa per le porte per tornare al piano terra.\n\n{=================================== MISSION TABLE GENERA2 ===================================}\n\n[COL2_A:GENERA2]\nTommy! Vieni qui da me.\n\n[COL2_B:GENERA2]\nNon ti sembra delizioso, vero? Lingua di Tapia?\n\n[COL2_C:GENERA2]\nEerr... No, no grazie.\n\n[COL2_D:GENERA2]\nTommy, sei come un vento fresco della pampa che mi libera dall'olezzo della corruzione,\n\n[COL2_E:GENERA2]\nbenché mi addolori la recente dipartita, devo continuare come sempre con il mio lavoro.\n\n[COL2_F:GENERA2]\nNon mi sembra ci stiamo avvicinando ai miei soldi...\n\n[COL2_G:GENERA2]\nTommy, amico mio, non sei più a Liberty. Qui le cose vanno in modo diverso.\n\n[COL2_H:GENERA2]\nContinuerò le mie ricerche, ma nel frattempo ho un interessante accordo da proporti.\n\n[COL2_I:GENERA2]\nUn favore per un amico, Cortez.\n\n[COL2_J:GENERA2]\nSei un vero amico, Tommy, Ero certo che non mi avresti deluso.\n\n[COL2_K:GENERA2]\nHo bisogno che tu incontri un corriere che mi ha recuperato una tecnologia di cui ho bisogno...\n\n[COL2_1:GENERA2]\nLa pioggia, è così très umido in questo periodo dell'anno...\n\n[COL2_2:GENERA2]\nCosa?\n\n[COL2_3:GENERA2]\nAh, comment?\n\n[COL2_4:GENERA2]\nAscolta, mi manda Cortez. Dammi quei maledetti chip.\n\n[COL2_5:GENERA2]\nOh... d'accord.\n\n[COL2_B1:GENERA2]\n~g~Incontra il corriere al Mall.\n\n[COL2_B2:GENERA2]\n~g~Il correre sta scappando con i chip: non farlo scappare!\n\n[COL2_B3:GENERA2]\n~g~Porta i chip al Colonnello.\n\n[COL2_F1:GENERA2]\n~r~Hai ucciso il contatto!\n\n[COL2_F2:GENERA2]\n~r~Il corriere è morto. Raccogli i chip.\n\n[COL2_6A:GENERA2]\nFermo, brutto maiale imperialista americano! Questa è proprietà del governo francese. Passamela!\n\n[BLIPHLP:GENERA2]\nSe il segnale sul radar è un triangolo verso l'alto, significa che il bersaglio è in posizione più elevata rispetto al giocatore.\n\n[COL2_F3:GENERA2]\n~r~I chip adesso riposano in fondo all'oceano.\n\n[COL2_F4:GENERA2]\n~r~Il corriere è scappato! Non sei riuscito a recuperare i chip.\n\n{=================================== MISSION TABLE GENERA3 ===================================}\n\n[GEN3_A:GENERA3]\nThomas, grazie per essere venuto.\n\n[GEN3_B:GENERA3]\nPerdonami se giungo subito al punto.\n\n[GEN3_C:GENERA3]\nDiaz mi ha chiesto di sovrintendere una piccola transizione di lavoro.\n\n[GEN3_D:GENERA3]\nSperiamo vada meglio dell'ultima...\n\n[GEN3_E:GENERA3]\nEd è per questo che ho pensato a te, amico.\n\n[GEN3_F:GENERA3]\nHo lasciato un po' di supporto al parcheggio multipiano.\n\n[GEN3_G:GENERA3]\nRaccogli il materiale, poi raggiungi e sorveglia gli uomini di Diaz all'incontro.\n\n[GEN3_H:GENERA3]\nGracias, amigo.\n\n[GEN3_1:GENERA3]\nAmi l'azione, vedo...\n\n[GEN3_2:GENERA3]\nSenti, ti capita mai di fare qualcos'altro che non sia seguirmi dappertutto? Perché non vieni con me e mi dimostri di servire a qualcosa?\n\n[GEN3_3:GENERA3]\nPotrei anche farlo. A proposito, mi chiamo Lance.\n\n[GEN3_5:GENERA3]\nDevi essere il nuovo uomo di Cortez.\n\n[GEN3_6:GENERA3]\nFino a quando non mi capiteranno opportunità più lucrose.\n\n[GEN3_7:GENERA3]\nArriveranno fra pochi minuti: meglio trovare un buon punto dove appostarsi...\n\n[GEN3_8:GENERA3]\nOK! Io prendo il balcone, tu prendi il tetto dall'altra parte del cortile.\n\n[GEN3_9:GENERA3]\nSono vivo, brutti stronzi! E tutto grazie a te! Come ti chiami?\n\n[GEN3_10:GENERA3]\nTommy.\n\n[GEN3_11:GENERA3]\nCi incontreremo di nuovo, credo!\n\n[GEN3_12:GENERA3]\nDove diavolo è andato Lance? Merda...\n\n[GEN3_14:GENERA3]\nTommy! Ho bisogno di aiuto!\n\n[GEN3_15:GENERA3]\nNon preoccuparti, ti copro io!\n\n[GEN3_16:GENERA3]\nGli uomini di Diaz si stanno facendo massacrare!\n\n[GEN3_19:GENERA3]\n~g~Haitiani! Stanno mandando a monte l'affare! Proteggi Diaz!\n\n[GEN3_20:GENERA3]\n~g~Entra nel parcheggio multipiano e recupera ciò che il Colonnello ha lasciato per te.\n\n[GEN3_22:GENERA3]\nSalute di Diaz:\n\n[GEN3_23:GENERA3]\n~g~Hai lasciato Lance indietro! Vallo a prendere!\n\n[GEN3_25:GENERA3]\n~r~Lance è morto!\n\n[GEN3_28:GENERA3]\n~g~Riporta la valigetta a Diaz.\n\n[GEN3_29:GENERA3]\n~g~Raccogli la valigetta e riportala a Diaz.\n\n[GEN3_30:GENERA3]\n~r~È scappato con i soldi! Diaz ti strapperà le palle per questo!\n\n[GEN3_33:GENERA3]\n~r~Dovresti proteggere Diaz e i suoi uomini, non sparargli addosso!\n\n[GEN3_34:GENERA3]\n~r~Non ci sarà nessun accordo se spari ai Cubani!\n\n[GEN3_35:GENERA3]\n~g~Ha rubato i soldi di Diaz!\n\n[GEN3_36:GENERA3]\n~g~Prendi la moto, inseguilo e recupera i soldi di Diaz!\n\n[GEN3_37:GENERA3]\n~g~Stanno arrivando i Cubani. Assicurati che niente vada storto e proteggi Diaz e Lance.\n\n[GEN3_38:GENERA3]\n~r~Diaz è morto! Non sei riuscito a proteggerlo!\n\n[GEN3_39:GENERA3]\n~g~Raggiungi la tua postazione sopra alle scale.\n\n[GEN3_44:GENERA3]\n~g~Vai con Lance all'appuntamento e proteggi Diaz.\n\n[GEN3_40:GENERA3] { reVC update }\nPer ~h~sparare davanti~w~ su una ~h~moto~w~ premi il ~h~~k~~VEHICLE_FIREWEAPON~~w~.\n\n[GEN3_41:GENERA3] { reVC update }\nPer ~h~sparare davanti~w~ su una ~h~moto~w~ premi il ~h~~k~~VEHICLE_FIREWEAPON~~w~.\n\n[GEN3_46:GENERA3]\nMeerda!\n\n[GEN3_47:GENERA3]\nTommy!\n\n[GEN3_48:GENERA3]\nMaledizione!\n\n[GEN3_49:GENERA3]\nSALUTE DI LANCE:\n\n[GEN3_50:GENERA3]\n~r~Hai distrutto i soldi di Diaz! La prossima volta cerca di non ridurre le banconote in cenere!\n\n[GEN3_51:GENERA3]\nAltri fottuti Haitiani in un merdoso van!\n\n[GEN3_54:GENERA3]\nNon restare lì impalato, idiota, insegui quello stronzo di un Haitiano!\n\n[GEN3_55:GENERA3]\nTommy! Io resto qua a proteggere Diaz!\n\n[GEN3_18:GENERA3]\n~g~Stanno arrivando i Cubani, resta vicino a Diaz. Assicurati che niente vada storto e proteggi Diaz e Lance.\n\n[GEN3_56:GENERA3]\n~r~Diaz è stato assalito e ucciso! La prossima volta, cerca di proteggerlo!\n\n[GEN3_57:GENERA3]\nIl Kruger è un fucile d'assalto che permette di mirare in prima persona.\n\n[GEN3_58:GENERA3]\nTieni premuto il tasto ~h~R1~w~ per ~h~mirare~w~ con il fucile d'assalto.\n\n[GEN3_59:GENERA3]\nTieni premuto il tasto ~h~L1~w~ per ~h~mirare~w~ col fucile d'assalto.\n\n[GEN3_60:GENERA3]\nPremi il tasto ~h~~k~~PED_FIREWEAPON~~w~ per ~h~sparare~w~ col fucile d'assalto.\n\n[GEN3_61:GENERA3]\nPremi il tasto ~h~~k~~PED_FIREWEAPON~~w~ per ~h~sparare~w~ col fucile d'assalto.\n\n[GEN3_62:GENERA3]\nPremi il tasto ~h~~k~~PED_FIREWEAPON~~w~ per ~h~sparare~w~ col fucile d'assalto.\n\n[GEN3_63:GENERA3]\nOltre a permetterti di sparare in corsa, con le ~h~moto~w~ puoi anche ~h~sparare in avanti~w~.\n\n[GEN3_64:GENERA3] { reVC update }\nPer sparare in avanti quando sei su una moto, premi il tasto ~h~~k~~VEHICLE_FIREWEAPON~~w~.\n\n[GEN3_65:GENERA3] { reVC update }\nPer sparare in avanti quando sei su una moto, premi il tasto ~h~~k~~VEHICLE_FIREWEAPON~~w~.\n\n[GEN3_66:GENERA3] { reVC update }\nPer sparare in avanti quando sei su una moto, premi il tasto ~h~~k~~VEHICLE_FIREWEAPON~~w~.\n\n[GEN3_67:GENERA3]\nHai bisogno di una mitragliatrice per poter sparare in avanti.\n\n[GEN3_53:GENERA3]\nI MIEI SOLDI!\n\n[GEN3_52:GENERA3]\nQuesti Haitiani pensano che possono farsi RICARDO DIAZ!?!\n\n{=================================== MISSION TABLE GENERA4 ===================================}\n\n[DETON:GENERA4]\nDETONAZIONE:\n\n[COL4_3:GENERA4]\nCONVOGLIO ALT!\n\n[COL4_6:GENERA4]\nSIAMO SOTTO FUOCO NEMICO!\n\n[COL4_7:GENERA4]\nCivile, si allontani dal carro armato!\n\n[COL4_8:GENERA4]\nHO DETTO, si allontani, IMMEDIATAMENTE!\n\n[COL4_9:GENERA4]\nPOSIZIONI DIFENSIVE!\n\n[COL4_11:GENERA4]\nPorta via quel civile, soldato! - Signorsì, signore!\n\n[COL4_12:GENERA4]\nCivile nel CARRO ARMATO! FERMATELO!\n\n[COL4_13:GENERA4]\nQuesto è un convoglio militare, non ostacoli il passaggio.\n\n[COL4_14:GENERA4]\nFallo fuori, soldato.\n\n[COL4_15:GENERA4]\nSpostate quel veicolo civile via dalla strada! -Signore! Sposto il veicolo, signore!\n\n[COL4_17:GENERA4]\nOK, PLOTONE, IN MARCIA!\n\n[COL4_18:GENERA4]\nQualcuno è entrato nel carro armato, signore!\n\n[COL4_19:GENERA4]\nVai a prendere delle ciambelle, soldato! - Signorsì, signore!\n\n[COL4_20:GENERA4]\nBersaglio acquisito, signore!\n\n[COL4_21:GENERA4]\nCECCHINO!\n\n[COL4_22:GENERA4]\nIo me la squaglio.\n\n[COL4_23:GENERA4]\nObiettivo completato! Plotone riposo! -Andiamo a mangiarci qualche ciambella.\n\n[COL4_24:GENERA4]\nProtocollo di sicurezza Delta India Echo attivato! Autodistruzione del veicolo attivata!\n\n[COL4_26:GENERA4]\nPreparati a morire, maledetto comunista!\n\n[COL4_B2:GENERA4]\n~r~Il carro armato è arrivato con successo a destinazione!\n\n[COL4_B5:GENERA4]\n~r~Il carro armato è stato distrutto!\n\n[COL4_01:GENERA4]\nDiaz era soddisfatto e vorrebbe incontrarti nuovamente.\n\n[COL4_02:GENERA4]\nÈ un buon segno?\n\n[COL4_03:GENERA4]\nMa certo! Benché credo che Diaz sia il responsabile della nostra sfortunata perdita...\n\n[COL4_04:GENERA4]\nChe cosa glielo fa pensare?\n\n[COL4_05:GENERA4]\nNessuno accusa direttamente un uomo come Diaz... sto solo pensando a voce altra...\n\n[COL4_06:GENERA4]\nNon importa. Ho una proposta che potrebbe interessarti...\n\n[COL4_07:GENERA4]\nNon ho più tempo per i suoi lavori, Cortez.\n\n[COL4_08:GENERA4]\nPensavo che un uomo con dei debiti così pericolosi fosse desideroso di opportunità. Per favore, Tommy, almeno ascoltami.\n\n[COL4_09:GENERA4]\nMi dica...\n\n[COL410:GENERA4]\nHo un acquirente per un mezzo militare che sta attraversando la città. Recuperalo per me...\n\n[COL411:GENERA4]\ne, quando lo avrai, vorrei che mi chiamassi immediatamente. Poi...\n\n[COL4_B4:GENERA4]\n~g~Il carro armato è chiuso. Trova un modo per far uscire gli occupanti.\n\n[COL4_1:GENERA4]\nChe cos'ha il mitragliatore? -Non so signore!\n\n[COL4_4:GENERA4]\n-Vai di sopra, soldato. -Signorsì, signore!\n\n[COL4_B1:GENERA4]\n~g~Impadronisciti del mezzo militare che sta attraversando la città.\n\n[COL4_B3:GENERA4]\n~g~Porta il carro armato al garage del Colonnello prima che si autodistrugga.\n\n[COL4_B6:GENERA4]\n~g~Trova un modo per rubare il carro armato!\n\n[COL4_B7:GENERA4]\n~g~Porta il carro armato dentro al garage.\n\n[COL4_B8:GENERA4]\n~g~Esci dal carro armato e abbandona il garage.\n\n{=================================== MISSION TABLE GENERA5 ===================================}\n\n[COL5A_1:GENERA5]\nLe circostanze richiedono una rapida partenza, amigo.\n\n[COL5A_2:GENERA5]\nQual è il problema?\n\n[COL5A_3:GENERA5]\nUh, i Francesi rivogliono la loro tecnologia missilistica indietro dopo quell'incidente...\n\n[COL5A_4:GENERA5]\nSento che è giunta l'ora di partire per porti più sicuri.\n\n[COL5A_5:GENERA5]\nNon sarebbe meglio via aria?\n\n[COL5A_6:GENERA5]\nSarei morto ancor prima di raggiungere il check-in. Inoltre, devo portare la mia merce fuori dal paese.\n\n[COL5A_7:GENERA5]\nServe un'altra pistola?\n\n[COL5A_8:GENERA5]\nTu, amico, vali come dieci pistole... ah ah ah!\n\n[COL5B_1:GENERA5]\nThomas, mi hai protetto e servito bene.\n\n[COL5B_2:GENERA5]\nMa adesso devi abbandonarci prima che raggiungiamo il mare aperto.\n\n[COL5B_4:GENERA5]\nGrazie mille, Colonnello.\n\n[COL5B_5:GENERA5]\nUn'ultima richiesta, mentre sono via: terresti un occhio su Mercedes per me?\n\n[COL5B_6:GENERA5]\nCredo sappia badare a sé stessa, ma certo, la terrò sott'occhio.\n\n[COL5B_7:GENERA5]\nGrazie mille, amico. A presto!\n\n[COL5B_8:GENERA5]\nAdios, amigo.\n\n[COL5_7:GENERA5]\nSmettila di spararmi!\n\n[COL5_9:GENERA5]\nTommy, falli smettere di sparare!\n\n[COL5_10:GENERA5]\nHo l'immunità diplomatica!\n\n[COL5_11:GENERA5]\nNon sparare, sono il Colonnello!\n\n[COL5_12:GENERA5]\nThomas, uccidili: la mia nazione ti sarà riconoscente.\n\n[COL5_13:GENERA5]\nTommy, siamo assaliti dai Francesi!\n\n[COL5_14:GENERA5]\nTommy, dovunque guardo vedo dei Francesi. Io li odio!\n\n[COL5_15:GENERA5]\nTommy, come stai?\n\n[COL5_16:GENERA5]\nQuesto è per la Piaf e Gainesbourg e per le vostre stupide baguette!\n\n[COL5_1:GENERA5]\nA babordo! A babordo!\n\n[COL5_2:GENERA5]\nCi attaccano da tribordo!\n\n[COL5_3:GENERA5]\nIl ponte qui davanti!\n\n[COL5_4:GENERA5]\nHanno un elicottero!\n\n[COL5_B1:GENERA5]\n~g~Difendi a tutti i costi il Colonnello e il suo yacht.\n\n[COL5_B2:GENERA5]\n~g~Vai a prua e libera la strada per il passaggio dello yacht del Colonnello.\n\n[COL5_B3:GENERA5]\n~r~Il Colonnello è morto!\n\n[COL5_B4:GENERA5]\n~g~Abbatti l'elicottero!\n\n[COL5B_3:GENERA5]\nFarò calare la mia lancia personale. Tienila, amico, un pegno della mia gratitudine.\n\n[COL5_B5:GENERA5]\n~g~Abbatti gli elicotteri e proteggi lo yacht.\n\n[COL5_B6:GENERA5]\n~g~Hai finito i colpi: recuperane altri dalle scale al ponte superiore.\n\n[COL5_B7:GENERA5]\n~g~Sei a corto di salute: recuperane altra dalle scale al ponte superiore\n\n{=================================== MISSION TABLE HAIT1 ===================================}\n\n[HAM1_A:HAIT1]\nPermesso?\n\n[HAM1_B:HAIT1]\nEntra pure, caro, e riposa l'anima.\n\n[HAM1_C:HAIT1]\nDevi essere il grande uomo cattivo di cui parlava mio nonno.\n\n[HAM1_D:HAIT1]\nMi ha raccontato di te, sai, quando mi fa visita,\n\n[HAM1_E:HAIT1]\ne degli altri che ti aspettano.\n\n[HAM1_F:HAIT1]\nAdesso, siamo tutti morti da tempo, ma tu sai,\n\n[HAM1_G:HAIT1]\nnon vorrei essere nei tuoi panni, eh eh eh!\n\n[HAM1_H:HAIT1]\nHo ricevuto un messaggio. Sono venuto.\n\n[HAM1_I:HAIT1]\nLi puoi sentire?\n\n[HAM1_J:HAIT1]\nStanno chiamando il tuo nome, devono proprio volerti, non credi?\n\n[HAM1_K:HAIT1]\nMagari adesso dai una mano alla zia Poulet, uh, e forse lei ti aiuta.\n\n[HAM1_L:HAIT1]\nForse potrà darti un piccolo juju dopo tutto questo.\n\n[HAM1_M:HAIT1]\nUn po' di magia per dare all'uomo di legge il malocchio, hmmm?\n\n[HAM1_N:HAIT1]\nAscolta, tutto questo è, uhm... darmi cosa?\n\n[HAM1_O:HAIT1]\nCredo, credo proprio di aver sbagliato indirizzo...\n\n[HAM1_P:HAIT1]\nFai per me questo favore, Tommy...\n\n[HAM1_Q:HAIT1]\nI Cubani, foofoo molto orgogliosi, hmmm,\n\n[HAM1_R:HAIT1]\nhanno dato molti grattacapi ai miei ragazzi Haitiani.\n\n[HAM1_S:HAIT1]\nAdesso hanno detto alla polizia dove nascondo le mie polveri.\n\n[HAM1_T:HAIT1]\nPensano sia droga, gli stupidi.\n\n[HAM1_U:HAIT1]\nAdesso fai il bravo, Tommy, e vai a prendere le polveri per la zia Poulet.\n\n[HAM1_V:HAIT1]\nSì, sì, certo, vado.\n\n[HAM1_1:HAIT1]\n~g~I poliziotti si stanno avvicinando alle nostre riserve. Fermali prima che ci riescano.\n\n[HAM1_2:HAIT1]\n~r~I poliziotti sono arrivati per primi alla riserva!\n\n[HAM1_3:HAIT1]\n~g~Riporta questa roba al nascondiglio!\n\n[HAM1_4:HAIT1]\n~g~Ottimo! Adesso pensa al prossimo!\n\n[HAM1_6:HAIT1]\n~r~La riserva è stata distrutta, idiota!\n\n[HAM1_7:HAIT1]\n~g~La polizia ha preso la nostra riserva! Recuperala prima che se ne vada!\n\n[HAM1_8:HAIT1]\n~g~I poliziotti sono vicini alla riserva: datti una mossa!\n\n[HAT_1A:HAIT1]\n~g~Non muoverti, allocco!\n\n{=================================== MISSION TABLE HAIT2 ===================================}\n\n[HAT2_B1:HAIT2]\n~g~Raggiungi il van che contiene le bombe volanti.\n\n[HAT2_B2:HAIT2]\nUccidi i Cubani...\n\n[HAT2_B4:HAIT2]\n...e distruggi le loro imbarcazioni!\n\n[HAT2_B5:HAIT2]\n~g~I Cubani stanno fuggendo: non lasciarli scappare!\n\n[HAT2_B6:HAIT2]\n~r~L'aereo radiocomandato si sta allontanando dal raggio d'azione!\n\n[HAT2_B7:HAIT2]\n~g~Uno dei Cubani sta fuggendo in macchina. Non lasciare nessun testimone!\n\n[HAT2_B8:HAIT2]\n~g~Non hai più aerei radiocomandati!\n\n[HAT2_B9:HAIT2]\nAerei radiocomandati:\n\n[HAT2_1:HAIT2]\nOh. Scusa, devo aver sbagliato indirizzo...\n\n[HAT2_2:HAIT2]\nPuoi entrare comunque a riposare i piedi e a bere un po' di tè.\n\n[HAT2_3:HAIT2]\nHai qualcosa per me, Tommy?\n\n[HAT2_4:HAIT2]\nSì...\n\n[HAT2_5:HAIT2]\nQuesto posto mi sembra familiare. Un odore della mia gioventù... un deja vu...\n\n[HAT2_6:HAIT2]\nAdesso Tommy, ti sussurrerò una piccola commissione che devi farmi. Ascoltami attentamente, va bene?\n\n[HAT2_7:HAIT2]\nMi ricordi qualcuno che...\n\n[HAT2_8:HAIT2]\nI Cubani hanno imbarcazioni molto veloci che utilizzano per trasportare la droga via mare.\n\n[HAT2_9:HAIT2]\nÈ il loro modo di vivere.\n\n[HAT2_10:HAIT2]\nMio nipote ha costruito delle simpatiche bombe per farli fuori.\n\n[HAT2_11:HAIT2]\nFai esplodere le barche e inchioda le loro bare.\n\n[HAT2_12:HAIT2]\nBeh, grazie per il tè.\n\n[HAT2_B3:HAIT2] { reVC update }\nPremi il ~h~~k~~VEHICLE_FIREWEAPON~~w~ per sganciare una bomba. Premi il ~h~~k~~VEHICLE_ENTER_EXIT~ \"~w~ per annullare.\n\n{=================================== MISSION TABLE HAIT3 ===================================}\n\n[HAM3_A:HAIT3]\nSalve, salve, io, uh... Stavo cercando qualcuno...\n\n[HAM3_B:HAIT3]\nMi sembri affamato, Tommy.\n\n[HAM3_C:HAIT3]\nCi conosciamo?\n\n[HAM3_D:HAIT3]\nZitto ora.\n\n[HAM3_E:HAIT3]\nUn'ultima cosa e potrai andare, Tommy.\n\n[HAM3_F:HAIT3]\nI miei ragazzi sono in guerra con i Cubani.\n\n[HAM3_G:HAIT3]\nMa niente pistole.\n\n[HAM3_H:HAIT3]\nHmmm, ma i Cubani hanno una sorpresa in serbo.\n\n[HAM3_I:HAIT3]\nMentre combattono per la strada, tu prendi questo fucile e li elimini durante la confusione.\n\n[HAM3_J:HAIT3]\nNessuno ti vede, nessuno ti sente.\n\n[HAM3_K:HAIT3]\nAdesso, Tommy, fai questo per me e non sarai più aggrappato al mio grembiule.\n\n[HAM3_1:HAIT3]\n~g~Dobbiamo vincere questa battaglia. Se tutti gli Haitiani muoiono, sarà la fine.\n\n[HAM3_3:HAIT3]\n~g~Sospetto che i Cubani bareranno, per cui stai in guardia.\n\n[HAM3_4:HAIT3]\n~r~Ti hanno visto! La missione è fallita!\n\n[HAM3_5:HAIT3]\n~g~Devi eliminare i Cubani da lontano. Non devono vederti.\n\n[HAM3_8:HAIT3]\n~g~Gli Haitiani stanno morendo! Migliora la tua mira!\n\n[HAM3_7:HAIT3]\n~g~Attento! I Cubani hanno chiamato rinforzi. Uccidili tutti quanti!\n\n[HAM3_2:HAIT3]\n~r~Gli Haitiani sono morti!\n\n[HAM3_L:HAIT3]\nSssì zia...\n\n{=================================== MISSION TABLE HOTEL ===================================}\n\n[INTB_A:HOTEL]\nTommy! Tommy, quanto tempo è passato!\n\n[INTB_B:HOTEL]\nCiao Sonny.\n\n[INTB_C:HOTEL]\nLo so, lo so, sei sopraffatto dall'emozione.\n\n[INTB_D:HOTEL]\nQuindici anni... sembra come se fosse ieri.\n\n[INTB_E:HOTEL]\nCredo dipenda dal punto di vista.\n\n[INTB_F:HOTEL]\nEhi, stare dentro per la famiglia non è una passeggiata,\n\n[INTB_G:HOTEL]\nma la famiglia si preoccupa dei suoi, OK?\n\n[INTB_H:HOTEL]\nAllora, raccontami come è andata... Eri in ballo con l'oro bianco?\n\n[INTB_I:HOTEL]\nAscolta Sonny, ci avevano incastrato. L'incontro era un'imboscata. Harry e Lee sono morti.\n\n[INTB_J:HOTEL]\nBasta con queste storie, Tommy. Hai ancora i soldi, vero?\n\n[INTB_K:HOTEL]\n...no Sonny... non ho i soldi.\n\n[INTB_L:HOTEL]\nQuelli erano i miei soldi, Tommy, I MIEI SOLDI!\n\n[INTB_M:HOTEL]\nNon cercare di fottermi, Tommy, perché sai che non sono una persona a cui piace essere presa per il culo!\n\n[INTB_N:HOTEL]\nAspetta Sonny.\n\n[INTB_O:HOTEL]\nHai la mia parola che recupererò i tuoi soldi e la droga.\n\n[INTB_P:HOTEL]\nE ti farò avere per posta l'uccello dei responsabili.\n\n[INTB_Q:HOTEL]\nEhi, ne sono certo. Non sei uno stupido, Tommy, ma ti avverto: non lo sono neanch'io.\n\n[INTB_R:HOTEL]\nSe fosse stato qualcun altro, adesso sarebbe già MORTO.\n\n[INTB_S:HOTEL]\nMa visto che sei tu, che ci conosciamo da tempo, ti permetterò di gestire la situazione.\n\n[INTB_T:HOTEL]\nEhi, Sonny, hai la mia parola.\n\n[INTB_U:HOTEL]\nMi farò vivo.\n\n{=================================== MISSION TABLE ICECRE1 ===================================}\n\n[ICC1_4:ICECRE1]\n~g~Non ci sono clienti in quest'area, prova in un'altra.\n\n[ICC1_5:ICECRE1]\nTransazioni effettuate:\n\n[ICC1_7:ICECRE1]\n~g~Riceverai soldi per ogni transazione, ma più ne esegui, maggiori saranno le probabilità di attirare l'attenzione della polizia.\n\n[ICC1_8:ICECRE1]\n~g~Per eseguire una transazione, ~h~parcheggia il camioncino~g~ e premi il ~h~~k~~VEHICLE_HORN~~g~ per suonare il campanello e attrarre i clienti.\n\n[ICC1_9:ICECRE1]\n~g~Le gang locali non apprezzeranno il tuo lavoro nel loro territorio, per cui aspettati azioni ostili.\n\n[ICC1_10:ICECRE1]\n~g~Hai portato a termine ~1~ transazioni!\n\n[ICC1_11:ICECRE1]\n~g~Hai portato a termine ~1~ transazione!\n\n[ICC1_13:ICECRE1]\n~r~Non hai portato a termine nessuna transazione.\n\n[ICC1_14:ICECRE1]\nBENI FABBRICA DI GELATO ACQUISITI\n\n[ICC1_15:ICECRE1]\n~g~La fabbrica di gelato d'ora in poi genererà introiti per un massimo di ~1~$. Ricordati di recuperarli regolarmente.\n\n[ICC1_16:ICECRE1]\n~g~Utilizza il Mr. Whoopee per distribuire i prodotti Cherry Poppers per Vice City.\n\n[ICE_AT1:ICECRE1]\nFABBRICA DI GELATO COMPLETATA\n\n[ICE_AT2:ICECRE1]\n~g~La fabbrica Cherry Popper d'ora in poi genererà introiti per un massimo di ~1~$. Ricordati di recuperarli regolarmente.\n\n[ICC1_17:ICECRE1]\nMissione di distribuzione terminata.\n\n[ICC1_18:ICECRE1]\nVendita totale gelati: ~1~$\n\n[ICC1_19:ICECRE1]\nTransizioni totali eseguite: ~1~\n\n{=================================== MISSION TABLE ICECUT ===================================}\n\n[ICC1_A:ICECUT]\nChi sei?\n\n[ICC1_B:ICECUT]\nIl nuovo proprietario.\n\n[ICC1_C:ICECUT]\nSei per caso, o lo sei mai stato, un bambino?\n\n[ICC1_D:ICECUT]\nMa di cosa stai parlando?\n\n[ICC1_E:ICECUT]\nSei stato un bambino?\n\n[ICC1_F:ICECUT]\nCerto! Calmati! Che ti prende?\n\n[ICC1_G:ICECUT]\nLo sapevo. Un bambino.\n\n[ICC1_H:ICECUT]\nUno sporco, puzzolente, moccioso, lamentoso, vile, vomitevole, piagnucoloso piccolo bambino!\n\n[ICC1_I:ICECUT]\nUn bambino... un mostruoso, orribile disgustoso piccolo bambino. Boo hoo.\n\n[ICC1_J:ICECUT]\nLa mamma non ti ama, brutto piccolo avanzo!\n\n[ICC1_K:ICECUT]\nOw! Accidenti, calmati!\n\n[ICC1_L:ICECUT]\nIo ODIO i bambini, odio i poppanti.\n\n[ICC1_M:ICECUT]\nSono sporchi, puzzolenti, mocciosi, vomitevoli piccoli...\n\n[ICC1_N:ICECUT]\nNe ho avuto abbastanza!\n\n[ICC1_O:ICECUT]\nMa che diavolo hai?\n\n[ICC1_P:ICECUT]\nTu fai gelati, vero? Sono solo per bambini.\n\n[ICC1_Q:ICECUT]\nMa che psicopatica sei?\n\n[ICC1_R:ICECUT]\nÈ così mi sono chiesta: perché fare felici i bambini se li odio?\n\n[ICC1_S:ICECUT]\nOh, stupidi, schifosi, mocciosi...\n\n[ICC1_T:ICECUT]\nSta zitta!\n\n[ICC1_U:ICECUT]\n...Monellaccio!\n\n[ICC1_V:ICECUT]\nLa gelateria è solo una facciata.\n\n[ICC1_W:ICECUT]\nNoi distribuiamo altro, prodotti non caseari.\n\n[ICC1_X:ICECUT]\nE se vedo un bambino, non perdo occasione.\n\n[ICC1_Y:ICECUT]\nNon è vero, bambini? Sì, sì, lo faccio. La mamma non vi ama.\n\n[ICC1_Z:ICECUT]\nLei vi ODIA!\n\n[ICC1_ZA:ICECUT]\nPROPRIETÀ ACQUISTATA!\n\n{=================================== MISSION TABLE INTRO ===================================}\n\n[INT1_A:INTRO]\nTommy Vercetti... Ommerda!\n\n[INT1_B:INTRO]\nPensavo non lo avrebbero mai rilasciato.\n\n[INT1_C:INTRO]\nHa tenuto la testa bassa... molta gente ha dimenticato.\n\n[INT1_D:INTRO]\nMa molti ricorderanno ben presto...\n\n[INT1_E:INTRO]\nQuando lo vedranno camminare per le strade del loro vicinato.\n\n[INT1_F:INTRO]\nNon sarà una cosa positiva per il business.\n\n[INT1_G:INTRO]\nBeh, che cosa facciamo, Sonny?\n\n[INT1_H:INTRO]\nLo trattiamo come un amico e lo teniamo impegnato fuori città, OK?\n\n[INT1_I:INTRO]\nParlavamo di espanderci verso sud, vero?\n\n[INT1_J:INTRO]\nVice City è oro puro in questi giorni.\n\n[INT1_K:INTRO]\nI Colombiani, i Messicani, che diamine,\n\n[INT1_L:INTRO]\nanche i rifugiati Cubani si sono ritagliati una bella fetta della torta.\n\n[INT1_M:INTRO]\nMa si tratta di droga, Sonny,\n\n[INT1_N:INTRO]\nnessuno delle famiglie toccherà quella merda!\n\n[INT1_O:INTRO]\nI tempi cambiano.\n\n[INT1_P:INTRO]\nLe famiglie non possono girare le spalle mentre i nostri nemici si godono il raccolto.\n\n[INT1_Q:INTRO]\nPer cui mandiamo qualcuno a fare il lavoro sporco\n\n[INT1_R:INTRO]\ne a prendere una bella fetta per noi, OK?\n\n[INT1_S:INTRO]\nChi è il nostro contatto laggiù?\n\n[INT1_T:INTRO]\nKen Rosenberg, uno schmuck di un avvocato.\n\n[INT1_U:INTRO]\nCome farà a tenere al guinzaglio Vercetti?\n\n[INT1_V:INTRO]\nNon dovrà farlo.\n\n[INT1_W:INTRO]\nMandiamolo alla ribalta a Vice City\n\n[INT1_X:INTRO]\ncon un po' di denaro per cominciare, OK?\n\n[INT1_Y:INTRO]\nLasciamogli qualche mese.\n\n[INT1_Z:INTRO]\nPoi andiamo giù,\n\n[INT1_A1:INTRO]\ngli facciamo visita, giusto?\n\n[INT1_A2:INTRO]\nE vediamo come se la sta cavando...\n\n[INT2_A:INTRO]\nEhi, ehi, amici! Sono, uh, Ken Rosenberg! Eh, eh, ottimo, ehi!\n\n[INT2_B:INTRO]\nBene, uh, vi accompagno in auto all'appuntamento, OK?\n\n[INT2_C:INTRO]\nHo parlato con i fornitori e loro sono molto, ehm,\n\n[INT2_D:INTRO]\ndesiderosi di avviare una relazione commerciale, per cui, uh,\n\n[INT2_E:INTRO]\nse tutto dovesse andare come deve, noi, dovremmo, uh,\n\n[INT2_F:INTRO]\nottenere dei buoni risultati economici, il che, cioè...\n\n[INT2_G:INTRO]\nè bene...\n\n[INT2_H:INTRO]\nOK allora. Sono fratelli, OK.\n\n[INT2_I:INTRO]\nUno si occupa del, uh, business,\n\n[INT2_J:INTRO]\nmentre l'altro si occupa dei voli.\n\n[INT2_K:INTRO]\nAdesso operano dal Messico,\n\n[INT3_A:INTRO]\nOK, sono loro sull'elicottero.\n\n[INT3_B:INTRO]\nBene, questo è l'accordo.\n\n[INT3_C:INTRO]\nVogliono uno scambio diretto in campo aperto.\n\n[INT3_D:INTRO]\nVa bene? OK, nervi saldi, andiamo.\n\n[INT3_E:INTRO]\nVedi di star calmo.\n\n[INT3_F:INTRO]\nResto qui con l'auto pronta a partire!\n\n[INT3_G:INTRO]\nChiaro?\n\n[INT3_H:INTRO]\nColombiana 100% pura di prima classe, amici miei.\n\n[INT3_I:INTRO]\nI verdoni?\n\n[INT3_J:INTRO]\nDa dieci e da venti... usati.\n\n[INT3_L:INTRO]\nForza, vieni qua! Muoviti!\n\n[INTRO1:INTRO]\nmetto fuori la testa per un maledetto secondo, e il fato mi tira palate di merda in faccia!\n\n[INTRO2:INTRO]\nVai a riposarti.\n\n[INTRO3:INTRO]\nChe cosa intendi fare?\n\n[INTRO4:INTRO]\nPasserò domani a trovarti in ufficio e troveremo un modo per risolvere questo casino.\n\n[INT3_K:INTRO]\nSiamo d'accordo allora, amico. AH AH!\n\n[INT3_M:INTRO]\nFammi dare un'occhiata.\n\n[INT2_L:INTRO]\nno, no, no, aspetta...\n\n{=================================== MISSION TABLE KENT1 ===================================}\n\n[KPM1_A:KENT1]\nEhi bello, ho delle informazioni sul tuo amico.\n\n[KPM1_B:KENT1]\nMa di cosa stai parlando?\n\n[KPM1_C:KENT1]\nConosci quel fallito di Diaz, il signore degli spacciatori?\n\n[KPM1_D:KENT1]\nHa preso il tuo amico, Lance. Sembra che abbia cercato di scavalcarlo...\n\n[KPM1_E:KENT1]\nma non ha saltato abbastanza in alto, se capisci cosa intendo.\n\n[KPM1_F:KENT1]\nDove lo hanno portato? Senza giri di parole!\n\n[KPM1_G:KENT1]\nStai calmo! Lo hanno trasportato attraverso la città fino alla discarica.\n\n[KPM1_H:KENT1]\nMaledizione... Brutto idiota.\n\n[KPM1_2:KENT1]\n~r~Dovevi portare Lance fuori vivo da lì!\n\n[KPM1_3:KENT1]\nSALUTE DI LANCE:\n\n[RESC_1:KENT1]\nCe la fai a usare un'arma?\n\n[RESC_2:KENT1]\nCerto... credo... È bello rivederti!\n\n[RESC_3:KENT1]\nAndiamocene da qua.\n\n[RESC_4:KENT1]\nBene, con questo hai mandato a puttane tutti i miei bei piani. L'hai proprio fatta grossa, Lance.\n\n[RESC_5:KENT1]\nHa ucciso mio fratello. Che cosa ti aspettavi facessi, che gli tagliassi il prato?\n\n[RESC_6:KENT1]\nDobbiamo far fuori quello stronzo di Diaz prima che sia lui a farlo.\n\n[RESC_7:KENT1]\nPreparati e incontriamoci al ponte di Star Island, OK?\n\n[RESC_8:KENT1]\nOK, ricevuto.\n\n[KPM1_1:KENT1]\n~g~Lance viene tenuto nella discarica: vai a salvarlo!\n\n[KPM1_4:KENT1]\n~g~Porta Lance all'ospedale!\n\n[M_PASSN:KENT1]\nMISSIONE COMPLETATA!\n\n[KPM1_5:KENT1]\n~g~Gli uomini di Diaz ti stanno dietro: porta Lance all'ospedale.\n\n{=================================== MISSION TABLE KICKSTT ===================================}\n\n[KICK1_2:KICKSTT]\n~r~Non sei tornato abbastanza velocemente alla tua moto!\n\n[KICK1_7:KICKSTT]\n~r~Hai distrutto la moto!\n\n[KICK1_8:KICKSTT]\n~g~Ritorna sulla moto!\n\n[KICK1_T:KICKSTT]\nTEMPO IMPIEGATO:\n\n[KICKTM:KICKSTT]\n~b~DURATA EVENTO: ~1~:~1~\n\n[KICKTM2:KICKSTT]\n~b~DURATA EVENTO: ~1~:0~1~\n\n[GETBIKE:KICKSTT]\n~g~Hai ~1~ secondi per tornare sulla tua moto prima che la missione abbia termine.\n\n[KICK1_1:KICKSTT]\n~g~Completa il tracciato il più velocemente possibile.\n\n[KICK1_6:KICKSTT]\n~g~Complimenti!\n\n[KICK_10:KICKSTT]\n~g~Usa il Sanchez per completare il percorso passando per tutti i punti di controllo.\n\n[KICK_12:KICKSTT]\n~g~Ti sei bloccato!\n\n[KICK_13:KICKSTT]\n~g~Ci hai messo troppo tempo!\n\n[KICK_11:KICKSTT]\n~g~Per abbandonare la missione, posizionati a piedi sul ~q~segnalino rosa~g~.\n\n{=================================== MISSION TABLE LAWYER1 ===================================}\n\n[LAW1_A:LAWYER1]\nVai a riposarti un po', ha detto...\n\n[LAW1_B:LAWYER1]\n...ho passato tutta la sera su questa seggiola a bere caffè con la luce spenta.\n\n[LAW1_C:LAWYER1]\nÈ un disastro. Siamo veramente fottuti, amico!\n\n[LAW1_D:LAWYER1]\nQuei gorilla, non sto scherzando, verranno qui da me e mi staccheranno la testa. È ridicolo!\n\n[LAW1_E:LAWYER1]\nNON mi sono laureato in giurisprudenza per questo! Bene, dimmi un po': che cosa hai intenzione di fare?\n\n[LAW1_F:LAWYER1]\nSta zitto, siediti e rilassati. Ti dirò che cosa faremo.\n\n[LAW1_G:LAWYER1]\nTu dovrai scoprire chi ha preso la nostra cocaina... e io li farò fuori.\n\n[LAW1_H:LAWYER1]\nÈ una buona idea. Anzi, è un'OTTIMA idea. Fammici pensare, fammici pensare, fammici pensare.\n\n[LAW1_I:LAWYER1]\nAh! C'è quel Colonnello in pensione, il Colonnello Juan Garcia Cortez.\n\n[LAW1_J:LAWYER1]\nÈ stato lui che mi ha aiutato a preparare il piano\n\n[LAW1_K:LAWYER1]\nben lontano dai criminali di Vice City. OK?\n\n[LAW1_L:LAWYER1]\nAdesso ascolta: sta organizzando un party nella baia sul suo costoso yacht\n\n[LAW1_M:LAWYER1]\ne tutte le personalità di spicco di Vice City saranno presenti.\n\n[LAW1_N:LAWYER1]\nIo ho un invito, chiaramente ne ho uno...\n\n[LAW1_O:LAWYER1]\nma non ho la minima intenzione di mettere la testa fuori dalla porta, per nessun motivo!\n\n[LAW1_P:LAWYER1]\nTe l'ho detto, sta zitto! Ci andrò io...\n\n[LAW1_Q:LAWYER1]\nWhoa, whoa, whoa! Ehi, anche a me piace lo stile del 78, ma, lo sai, non si tratta di una festa con birra e spogliarelliste.\n\n[LAW1_R:LAWYER1]\nIntendo dire, senza offesa, che molta gente potrebbe girarsi a guardarti per la ragione sbagliata...\n\n[LAW1_S:LAWYER1]\nVuoi dire che c'è qualcosa che non va in come mi vesto?\n\n[LAW1_T:LAWYER1]\nOK, ascolta. Fermati da Rafael's, digli che ti mando io e lui si occuperà di renderti presentabile.\n\n[LAW1_U:LAWYER1]\nOK, forza, andiamo...\n\n[LAWP_1:LAWYER1]\nBuenas noches.\n\n[LAWP_2:LAWYER1]\nDa quanto ho capito, è qui per conto di Mr. Rosenberg.\n\n[LAWP_3:LAWYER1]\nSpero che gli avvenimenti recenti non abbiano avuto effetti sulla sua salute o, uh,\n\n[LAWP_4:LAWYER1]\nsulla sua sanità mentale, Mr...?\n\n[LAWP_5:LAWYER1]\nVercetti. Ha solo avuto un attacco di... agorafobia.\n\n[LAWP_6:LAWYER1]\nEccellente, eccellente. E lei?\n\n[LAWP_7:LAWYER1]\nVoglio solo la mia merce.\n\n[LAWP_8:LAWYER1]\nAh. Si è trattato di sfortunate circostanze per tutte le persone coinvolte.\n\n[LAWP_9:LAWYER1]\nChiaramente, ho dato il via a delle ricerche personali\n\n[LAWP_10:LAWYER1]\nma una situazione così delicata richiede tempo.\n\n[LAWP_11:LAWYER1]\nMagari ne parleremo più tardi, va bene?\n\n[LAWP_12:LAWYER1]\nNel frattempo, le presento mia figlia,\n\n[LAWP_13:LAWYER1]\nMercedes!\n\n[LAWP_14:LAWYER1]\nCara mia, perché non ti prendi cura del nostro ospite mentre io mi occupo delle mie cose?\n\n[LAWP_15:LAWYER1]\nCertamente, papà.\n\n[LAWP_16:LAWYER1]\nMi scusi.\n\n[LAWP_17:LAWYER1]\nMercedes?\n\n[LAWP_18:LAWYER1]\nNon è facile portare questo nome.\n\n[LAWP_19:LAWYER1]\nComunque, lasci che le presenti alcuni dei nostri distinti ospiti...\n\n[LAWP_20:LAWYER1]\nLui è Alex Shrub, il nostro deputato, con Candy Suxxx, la famosa star siliconata...\n\n[LAWP_21:LAWYER1]\nAvete conosciuto la mia dolce moglie, Laura?\n\n[LAWP_22:LAWYER1]\nVeramente questa è Candy, mia moglie si trova in Alabama ora.\n\n[LAWP_23:LAWYER1]\nE da quella parte abbiamo la stella dei Vice City Mambas, BJ.\n\n[LAWP_24:LAWYER1]\nun vero ammaliatore\n\n[LAWP_25:LAWYER1]\nL'ho placcato, davvero, e l'ho fatto finire su una sedia a rotelle!\n\n[LAWP_26:LAWYER1]\nAh, ah, questa è buona!\n\n[LAWP_27:LAWYER1]\nBeh, adesso sto cercando di acquistare dei terreni di qualità.\n\n[LAWP_28:LAWYER1]\nE quella specie di anfibio da piscina è Jezz Torrent,\n\n[LAWP_29:LAWYER1]\nvoce solista dei Love Fist.\n\n[LAWP_30:LAWYER1]\nVe lo posso dire... sapete come giocano a ping-pong in Tailandia?\n\n[LAWP_31:LAWYER1]\nDa non crederci...\n\n[LAWP_32:LAWYER1]\ndi certo, non richiede l'uso della racchetta, se capite cosa intendo!\n\n[LAWP_33:LAWYER1]\nImpotente.\n\n[LAWP_34:LAWYER1]\nE il loquace trio.\n\n[LAWP_35:LAWYER1]\nQuella pustola sudata e addormentata è il braccio destro di papà, Gonzalez,\n\n[LAWP_36:LAWYER1]\nmentre gli altri due sono il pastore Richards\n\n[LAWP_37:LAWYER1]\ne il regista pseudo-intellettuale, Steve Scott.\n\n[LAWP_38:LAWYER1]\n...pare che abbiano una passione per le ninfomani...\n\n[LAWP_39:LAWYER1]\n...quando lo squalo gigante arriva e\n\n[LAWP_40:LAWYER1]\nstrappa a morsi i loro uccelli!\n\n[LAWP_41:LAWYER1]\nAh! Non si è mai visto qualcosa del genere prima, vero?\n\n[LAWP_42:LAWYER1]\nColonnello!\n\n[LAWP_43:LAWYER1]\nI suoi party sono sempre un successo! Ah ah ah!\n\n[LAWP_44:LAWYER1]\nPosso solo chiedere scusa per il mio ritardo.\n\n[LAWP_45:LAWYER1]\nAh, de nada amigo. E come vanno gli affari?\n\n[LAWP_46:LAWYER1]\nSai, sono molto difficili...i nemici sono sempre alle costole.\n\n[LAWP_47:LAWYER1]\nIl tempo di ricompensare gli amici e liquidare i nemici, amigo.\n\n[LAWP_48:LAWYER1]\nChi è il chiacchierone?\n\n[LAWP_49:LAWYER1]\nRicardo Diaz. È Mr. Coca.\n\n[LAWP_50:LAWYER1]\nMercedes!\n\n[LAWP_51:LAWYER1]\nOh, stavo giusto riaccompagnando i miei amici in città.\n\n[LAWP_52:LAWYER1]\nUn'altra volta, Ricardo!\n\n[LAWP_53:LAWYER1]\nAndiamocene.\n\n[LAWP_54:LAWYER1]\nAnzi, portatemi al club Pole Position.\n\n[LAW1_2:LAWYER1]\n~g~Raggiungi lo yacht del Colonnello.\n\n[LAW1_4:LAWYER1]\n~r~Hai ucciso la figlia del Colonnello!\n\n[LAW1_5:LAWYER1]\nLavorerai per mio padre?\n\n[LAW1_6:LAWYER1]\nForse.\n\n[LAW1_7:LAWYER1]\nTi dispiace se appoggio la mano tra le tue gambe?\n\n[LAW1_8:LAWYER1]\nForse...\n\n[LAW1_9:LAWYER1]\nÈ così difficile avere un padre ricco e potente. Vamos.\n\n[LAW1_10:LAWYER1]\nCi vediamo in giro, stallone!\n\n[LAW1_11:LAWYER1]\nSono sicuro di sì.\n\n[LAW1_12:LAWYER1]\nHmmm... bella moto.\n\n[LAW1_13:LAWYER1]\nNo! La mia moto!\n\n[LAW1_3:LAWYER1]\n~g~Porta la figlia del Colonnello al club Pole Position.\n\n[HELP20:LAWYER1]\nSegui il ~h~segnale a forma di maglietta~w~ per trovare Rafael's.\n\n[LAW1_14:LAWYER1]\nAccidenti, mi piace: la tua moto va alla grande.\n\n[LAW1_15:LAWYER1]\nEh sì, l'ho appena presa da Howlin' Pete's.\n\n{=================================== MISSION TABLE LAWYER2 ===================================}\n\n[LAW2_A:LAWYER2]\nAh! Beh, spero tu ti sia divertito. Io stavo quasi per impazzire dalla preoccupazione. Che cos'hai scoperto?\n\n[LAW2_B:LAWYER2]\nChe ci sono più criminali a piede libero in città che nella prigione. Abbiamo bisogno di qualcuno di strada...\n\n[LAW2_C:LAWYER2]\nOK, fammici pensare, fammici pensare, fammici pensare...\n\n[LAW2_D:LAWYER2]\nAh! Trovato!\n\n[LAW2_E:LAWYER2]\nOK, c'è questo inglese, un tizio legato al campo della musica,\n\n[LAW2_F:LAWYER2]\nmi sembra si chiami Kent Paul.\n\n[LAW2_G:LAWYER2]\nComunque, ha ficcato il naso nelle chiappe di metà della gente di Vice City\n\n[LAW2_H:LAWYER2]\nper cui, se qualcuno sa dove sono questi 20 chili di coca,\n\n[LAW2_I:LAWYER2]\nè sicuramente lui, chiaro? È sempre al Malibu.\n\n[LAW2_J:LAWYER2]\nAndrò a trovarlo.\n\n[LAW2B_A:LAWYER2]\nEhi, da dove sbuchi?\n\n[LAW2B_B:LAWYER2]\nHo cercato per anni un fiorellino come te, bellezza...\n\n[LAW2B_C:LAWYER2]\nKent Paul, tesoro. Sì, sono il capo da queste parti.\n\n[LAW2B_D:LAWYER2]\nSto cercando un tipo inglese...\n\n[LAW2B_E:LAWYER2]\nRisolvo i problemi, capisci cosa intendo?\n\n[LAW2B_F:LAWYER2]\nTi tratterò bene: qualsiasi cosa tu voglia, te la farò avere, cara.\n\n[LAW2B_G:LAWYER2]\nNon preoccuparti di niente, bellezza.\n\n[LAW2B_H:LAWYER2]\nVattene, tesoro.\n\n[LAW2B_I:LAWYER2]\nOi oi oi oi oi!\n\n[LAW2B_J:LAWYER2]\nSei Kent Paul? Sono un amico di Rosenberg...\n\n[LAW2B_K:LAWYER2]\nRosenberg... Rosenberg... Oh, l'avvocato matto!\n\n[LAW2B_L:LAWYER2]\nQuel tipo potrebbe difendere un innocente fino alla sedia elettrica!\n\n[LAW2B_M:LAWYER2]\nDacci un altro drink, amico.\n\n[LAW2B_N:LAWYER2]\nUn altro comico.\n\n[LAW2B_O:LAWYER2]\nAscoltami: mi hanno soffiato venti chili e un sacco di contanti...\n\n[LAW2B_P:LAWYER2]\nDroga amico? È roba da delinquenti.\n\n[LAW2B_Q:LAWYER2]\nChe cosa ne sai?\n\n[LAW2B_R:LAWYER2]\nOi oi! Ciò che volevo dire è\n\n[LAW2B_S:LAWYER2]\nche c'è uno chef che spaccia sottobanco nella cucina di un hotel su Ocean Drive.\n\n[LAW2B_T:LAWYER2]\nRecentemente, mi è sembrato molto felice di come gli buttava... Potresti passare a trovarlo e investigare...\n\n[LAW2B_U:LAWYER2]\nLo farò... ci becchiamo in giro.\n\n[LAW2B_V:LAWYER2]\nBeh, sì certo! Vai, vai pure idiota. Ci penserò io a tenerti a bada!\n\n[LAW2B_W:LAWYER2]\nDammi un bicchiere... e dov'è finita quella sgualdrina?\n\n[LAW2C_A:LAWYER2]\nOh, ottimo lavoro, sei proprio un duro. Riducilo in poltiglia, questo sicuramente lo aiuterà a diventare più loquace!\n\n[LAW2C_B:LAWYER2]\nNe vuoi anche tu?\n\n[LAW2C_C:LAWYER2]\nEhi, calma. Quel che va bene a te, va bene a me, amico.\n\n[LAW2C_D:LAWYER2]\nAh sì? E di cosa si tratta?\n\n[LAW2C_E:LAWYER2]\nI verdoni... e l'amica bianca del mio povero fratello. Sfortunatamente, hai appena fatto fuori il nostro contatto.\n\n[LAW2C_F:LAWYER2]\nGli incidenti capitano. Scompari.\n\n[LAW2C_G:LAWYER2]\nEhi, ehi, whoa. Non c'è bisogno di recitare la parte del 'Giustiziere solitario'.\n\n[LAW2C_H:LAWYER2]\nIo la vedo così: siamo due hombres in una strana città. Dobbiamo guardarci a vicenda le spalle.\n\n[LAW2C_I:LAWYER2]\nLe mie spalle stanno benissimo, fratello...\n\n[LAW2C_J:LAWYER2]\nNe sei sicuro? Ehi, prendi questa.\n\n[LAW2C_K:LAWYER2]\nSeguimi!\n\n[LAW2_1:LAWYER2]\nChe cos'hai da guardare?\n\n[LAW2_2:LAWYER2]\nTi conviene iniziare a parlare...\n\n[LAW2_3:LAWYER2]\nMaledetto stronzo!\n\n[LAW2_4:LAWYER2]\nDa questa parte!\n\n[LAW2_5:LAWYER2]\nVediamo cosa riesco a scoprire. Ci vediamo, Tommy.\n\n[LAW2_6:LAWYER2]\n~g~Vai al Malibu e trova Kent Paul.\n\n[LAW2_7:LAWYER2]\n~g~Trova lo chef in Ocean Drive.\n\n[LAW2_10:LAWYER2]\n~g~Torna in macchina all'hotel.\n\n[LAW2_11:LAWYER2]\n~g~Raccogli il suo cellulare.\n\n[LAW2_12:LAWYER2]\nCellulare acquisito! Adesso potrai ricevere telefonate!\n\n[LAW2_13:LAWYER2]\n~g~Hai lasciato Lance indietro! Vallo a prendere!\n\n[LAW2_14:LAWYER2]\nAndiamocene da qui!\n\n[GUN_2A:LAWYER2]\nTieni premuto il ~h~~k~~PED_LOCK_TARGET~~w~ per la ~h~mira automatica~w~ e premi il ~h~~k~~PED_FIREWEAPON~~w~ per ~h~sparare~w~!\n\n[GUN_2C:LAWYER2]\nTieni premuto il ~h~~k~~PED_LOCK_TARGET~~w~ per la ~h~mira automatica~w~ e premi il ~h~~k~~PED_FIREWEAPON~~w~ per ~h~sparare~w~!\n\n[GUN_2D:LAWYER2]\nTieni premuto il ~h~~k~~PED_LOCK_TARGET~~w~ per la ~h~mira automatica~w~ e premi il ~h~~k~~PED_FIREWEAPON~~w~ per ~h~sparare~w~!\n\n[HELP17:LAWYER2]\nPremi il ~h~~k~~PED_FIREWEAPON~~w~ per attaccare lo chef.\n\n[HELP18:LAWYER2]\nPremi il ~h~~k~~PED_FIREWEAPON~~w~ per attaccare lo chef.\n\n[LAW3_11:LAWYER2]\nPosizionati sul ~q~segnalino rosa~w~ per vedere le armi in offerta.\n\n[LAW3_12:LAWYER2]\nPuoi selezionare l'arma premendo il ~h~tasto direzionale~w~ a ~h~sinistra~w~ o a ~h~destra~w~.\n\n[LAW3_13:LAWYER2]\nSe hai denaro a sufficienza puoi comprare armi premendo il ~h~~k~~PED_SPRINT~~w~.\n\n[LAW3_14:LAWYER2]\nPuoi uscire da un negozio premendo il ~h~~k~~VEHICLE_ENTER_EXIT~~w~.\n\n[LAW3_15:LAWYER2]\nSegui il ~h~segnale a forma di pistola~w~ per trovare ~h~Ammu-Nation~w~.\n\n[LAW2_15:LAWYER2]\n~g~Raggiungi Ammu-Nation.\n\n[LAW2_K:LAWYER2]\nVedi di star calmo.\n\n[LAW2_16:LAWYER2]\nDevi sapere qualcosa su questa città: hai bisogno di potenza di fuoco.\n\n[LAW2_17:LAWYER2]\nForza, l'armaiolo locale è solo a qualche isolato di distanza.\n\n[LAW2_18:LAWYER2]\nTommy, tutti quanti hanno bisogno di un po' di relax ogni tanto.\n\n[LAW2_19:LAWYER2]\nEcco il club a luci rosse Pole Position. Facci un salto ogni tanto.\n\n{=================================== MISSION TABLE LAWYER3 ===================================}\n\n[LAW3_A:LAWYER3]\nAarrgh! Maledizione, sei tu! Oddio, avrò bisogno di un nuovo paio di pantaloni!\n\n[LAW3_B:LAWYER3]\nEhi, quei psicopatici del nord hanno drizzato le orecchie e verranno a visitarci molto presto.\n\n[LAW3_C:LAWYER3]\nDove diavolo sono i fottuti soldi?\n\n[LAW3_D:LAWYER3]\nRilassati, rilassati. Non siamo ancora arrivati a questa parte.\n\n[LAW3_E:LAWYER3]\nPensavo ti stessi prendendo cura di questo aspetto, davvero.\n\n[LAW3_F:LAWYER3]\nE adesso quei delinquenti si aspettano addirittura da noi un favore.\n\n[LAW3_G:LAWYER3]\nVuoi dire che io devo far loro un favore.\n\n[LAW3_H:LAWYER3]\nOh, beh, certo, proprio così. Credi davvero che potrei intimidire una giuria?\n\n[LAW3_I:LAWYER3]\nNon riuscirei a intimidire neppure un bambino... e credimi, ci ho provato.\n\n[LAW3_J:LAWYER3]\nAdesso o ci riusciamo, oppure il cugino di Forelli, Giorgio, si becca cinque anni per frode.\n\n[LAW3_K:LAWYER3]\nDevi CONVINCERE questi tipi!\n\n[LAW3_L:LAWYER3]\nCapisco. Devo aiutare la giuria a cambiare idea. Non preoccuparti...\n\n[LAW3_M:LAWYER3]\nNo no no no NO! Ci ho provato. Le cose con la giuria non sono andate per il meglio,\n\n[LAW3_N:LAWYER3]\nper cui ASSICURATI che cambino davvero idea.\n\n[LAW3_1:LAWYER3]\nGiorgio ti manda i suoi saluti.\n\n[LAW3_2:LAWYER3]\nRicorda: colpevole è una parolaccia.\n\n[LAW3_3:LAWYER3]\nInnocente fino a prova contraria... ecco cosa dire.\n\n[LAW3_4:LAWYER3]\nLo sai che non è colpevole.\n\n[LAW3_5:LAWYER3]\nTi ricordi di Giorgio? Ricordati che è innocente.\n\n[LAW3_6:LAWYER3]\nNon colpevole... Capito? Bene.\n\n[LAW3_8:LAWYER3]\n~r~Hai ucciso un giurato!\n\n[LAW3_9:LAWYER3]\n~g~Distruggi l'auto del giurato per farlo uscire!\n\n[HELP40:LAWYER3]\nPuoi distruggere le macchine utilizzando un martello o un'arma simile.\n\n[LAW3_10:LAWYER3]\n~g~Visita il ~h~ferramenta~g~ per comprare un'arma corpo a corpo.\n\n[LAW3_20:LAWYER3]\n~g~Distruggi la macchina del giurato!\n\n[LAW3_21:LAWYER3]\nNon posso credere che sta succedendo!\n\n[LAW3_22:LAWYER3]\nIncredibile!\n\n[LAW3_23:LAWYER3]\nOK! OK! Ho compreso il messaggio!\n\n[LAW3_24:LAWYER3]\n~g~Quel martello potrebbe tornare utile.\n\n[LAW3_7:LAWYER3]\n~g~Minaccia i due giurati, ma NON ucciderli!\n\n[HELP23:LAWYER3]\nSegui il ~h~segnale a forma di martello~w~ se vuoi comprare delle armi corpo a copro dal ferramenta.\n\n[LAW3_16:LAWYER3]\nStupidi idioti del Florida.\n\n[LAW3_17:LAWYER3]\nVia dai piedi.\n\n{=================================== MISSION TABLE LAWYER4 ===================================}\n\n[LAW4_A:LAWYER4]\nAvery, è chiaro che... Tommy! Tommy! Qualche progresso? No no no, parliamone dopo, mi racconti dopo.\n\n[LAW4_B:LAWYER4]\nTommy, ti presento Avery Carrington: credo tu lo abbia incontrato al party.\n\n[LAW4_C:LAWYER4]\nNon di persona.\n\n[LAW4_D:LAWYER4]\nPiacere.\n\n[LAW4_E:LAWYER4]\nAvery ha una proposta da farci.\n\n[LAW4_F:LAWYER4]\nNon ti sembra che abbiamo già altro da fare?\n\n[LAW4_G:LAWYER4]\nSto cercando di tenere lontani i lupi dalla porta, per cui apprezzerei un po' di collaborazione.\n\n[LAW4_H:LAWYER4]\nSono tirato come un filo e, anche se dovessi morire alla fine della settimana, desidererei non farlo da povero!\n\n[LAW4_I:LAWYER4]\nAdesso calmatevi, tutti e due.\n\n[LAW4_J:LAWYER4]\nFigliolo, dammi una mano e vedrò di mettere a nanna sottoterra qualsiasi stronzo vi stia dando problemi.\n\n[LAW4_K:LAWYER4]\nOK, cosa posso fare?\n\n[LAW4_L:LAWYER4]\nQuesta società di consegne ha un deposito su un terreno di prima qualità. Non vogliono vendere.\n\n[LAW4_M:LAWYER4]\nSi sono rintanati come dei ratti di prateria, per cui vorrei andassi a trovarli e li facessi uscire con un po' di fumo.\n\n[LAW4_N:LAWYER4]\nRaggiungi il posto e fai scoppiare un vespaio:\n\n[LAW4_O:LAWYER4]\nmentre la sorveglianza sarà impegnata, entra dentro e mettili fuori gioco.\n\n[LAW4_P:LAWYER4]\nPassa pure da Rafael's per un cambio d'abito: ci potresti mettere un po', ma va bene lo stesso.\n\n[LAW4_Q:LAWYER4]\nPotrebbe funzionare una sommossa.\n\n[LAW4_R:LAWYER4]\nSe le cose vanno come devono, passa a trovarmi nel mio ufficio...\n\n[LAW4_1:LAWYER4]\nDisperdetevi! L'amministrazione discuterà qualsiasi rimostranza in modo appropriato!\n\n[LAW4_2:LAWYER4]\nDisperdetevi! Tornate a casa!\n\n[LAW4_3:LAWYER4]\nDisperdetevi! Questo comportamento è inaccettabile!\n\n[LAW4_4:LAWYER4]\nDisperdetevi! Rischiate di finire tutti per strada!\n\n[LAW4_5:LAWYER4]\nForza, ragazzi! Spacchiamo il cranio a qualche rosso!\n\n[LAW4_13:LAWYER4]\n~g~Comincia a combattere con almeno 4 lavoratori per avviare la sommossa.\n\n[LAW4_14:LAWYER4]\n~g~Distruggi i van nell'autorimessa!\n\n[HELP38:LAWYER4]\nSe uccidi qualcuno con un'arma, la lascerà cadere.\n\n[HELP39:LAWYER4]\nPuoi far esplodere i barili di esplosivo, ma tieni la distanza!\n\n{=================================== MISSION TABLE MIAMI_1 ===================================}\n\n[T4X4_1A:MIAMI_1]\n~g~Hai ~1~ secondi per attraversare ~y~24~g~ punti di controllo. ~g~Puoi attraversarli in ~y~QUALSIASI ORDINE~g~.\n\n[T4X4_1B:MIAMI_1]\n~y~ATTRAVERSA~g~ il primo punto di controllo per attivare il ~r~TIMER~g~.\n\n[T4X4_1C:MIAMI_1]\n~1~ su 24!\n\n[GETBIK1:MIAMI_1]\nHai ~1~ secondi per salire su una PCJ 600!\n\n[GETBIK3:MIAMI_1]\n~r~Hai bisogno di una PCJ 600 per affrontare questa missione!\n\n{=================================== MISSION TABLE MM ===================================}\n\n[BLOD_04:MM]\nCONDIZIONI MACCHINA:\n\n[BLOD_05:MM]\n~g~TEMPO BERSAGLIO: ~1~ minuto\n\n[BLOD_06:MM]\n~g~TEMPO BERSAGLIO: ~1~ minuti\n\n[BLOD_07:MM]\nNUOVO miglior tempo: ~1~ secondi\n\n[BLOD_08:MM]\nVeicoli distrutti: ~1~\n\n[BLOD_09:MM]\n~1~$\n\n[BLOD_10:MM]\nVINCITORE!!!\n\n[BLOD_01:MM]\nGuida attraverso i punti di controllo per aumentare il tuo tempo globale.\n\n[BLOD_02:MM]\nFallirai se il tempo globale scadrà a zero.\n\n[BLOD_03:MM]\nPorta il tuo tempo globale sopra a quello bersaglio per vincere!\n\n{=================================== MISSION TABLE OVALRIG ===================================}\n\n[HOTR_01:OVALRIG]\n~g~La gara dura 12 giri: solo il primo, il secondo e il terzo si qualificheranno come vincitori.\n\n[HOTR_02:OVALRIG]\n~g~Se il tuo mezzo viene distrutto, sarai squalificato.\n\n[HOTR_03:OVALRIG]\n~g~Se danneggi il mezzo, potrai ripararlo ai box.\n\n[HOTR_04:OVALRIG]\n~g~Da qui potrai uscire dallo stadio.\n\n[HOTR_05:OVALRIG]\nCondizioni macchina:\n\n[HOTR_06:OVALRIG]\nGiri:\n\n[HOTR_10:OVALRIG]\nTempo di gara:\n\n[HOTR_09:OVALRIG]\nPosizione:\n\n[HOTR_12:OVALRIG]\n~r~La tua macchina è stata distrutta!\n\n[HOTR_13:OVALRIG]\n~r~Non hai vinto la gara!\n\n[HOTR_14:OVALRIG]\n~r~Sei stato squalificato!\n\n[HOTR_15:OVALRIG]\nTempo: ~1~:~1~\n\n[HOTR_16:OVALRIG]\nTempo: ~1~:0~1~\n\n[HOTR_17:OVALRIG]\nTempo migliore: ~1~:~1~\n\n[HOTR_18:OVALRIG]\nTempo migliore: ~1~:0~1~\n\n[HOTR_19:OVALRIG]\nTempo migliore: NA\n\n[HOTR_20:OVALRIG]\nNuovo tempo migliore: ~1~:~1~\n\n[HOTR_21:OVALRIG]\nNuovo tempo migliore: ~1~:0~1~\n\n[HOTR_22:OVALRIG]\nMiglior risultato: NA\n\n[HOTR_23:OVALRIG]\nMiglior risultato: PRIMO\n\n[HOTR_24:OVALRIG]\nMiglior risultato: SECONDO\n\n[HOTR_25:OVALRIG]\nMiglior risultato: TERZO\n\n[HOTR_26:OVALRIG]\nMiglior risultato: ~1~\n\n[HOTR_27:OVALRIG]\nMiglior giro: ~1~.~1~ secondi\n\n[HOTR_28:OVALRIG]\nMiglior giro: ~1~.0~1~ secondi\n\n[HOTR_29:OVALRIG]\n~1~$\n\n[HOTR_30:OVALRIG]\nPRIMA POSIZIONE\n\n[HOTR_31:OVALRIG]\nSECONDA POSIZIONE\n\n[HOTR_32:OVALRIG]\nTERZA POSIZIONE\n\n[HOTR_33:OVALRIG]\nMiglior giro: NA\n\n[HOTR_11:OVALRIG]\nNuovo giro migliore: ~1~.~1~ secondi\n\n[HOTR_34:OVALRIG]\nNuovo giro migliore: ~1~.0~1~ secondi\n\n{=================================== MISSION TABLE PHIL1 ===================================}\n\n[PHIL1_A:PHIL1]\nPhil?\n\n[PHIL1_B:PHIL1]\nCORRI!\n\n[PHIL1_C:PHIL1]\nCorri!\n\n[PHIL1_E:PHIL1]\nMerda Phil, tu bevi quella schifezza?\n\n[PHIL1_F:PHIL1]\nAccidenti, non la devi mica bere...\n\n[PHIL1_G:PHIL1]\nbasta una sniffata per sballare.\n\n[PHIL1_H:PHIL1]\nAscoltami Phil, mi hai detto che potevi fornirmi delle armi...\n\n[PHIL1_I:PHIL1]\nStanne certo!\n\n[PHIL1_J:PHIL1]\nC'è un trafficante d'armi Messicano con cui ho fatto un po' di affari.\n\n[PHIL1_K:PHIL1]\nFa la sua consegna settimanale più o meno adesso.\n\n[PHIL1_L:PHIL1]\nSperona il suo camion e fai cadere le armi prima che scappi.\n\n[PHIL1_M:PHIL1]\nE già che ci sei, fammi un favore:\n\n[PHIL1_N:PHIL1]\nfallo fuori.\n\n[PHI1_01:PHIL1]\n~g~Fai cadere le armi dal camion del trafficante.\n\n[PHI1_02:PHIL1]\n~g~Il trafficante ha lasciato cadere il carico. Distruggi le casse e recupera le armi.\n\n[PHI1_03:PHIL1]\n~g~Sembra abbiano chiesto rinforzi.\n\n[PHI1_04:PHIL1]\n~g~Adesso finisci i trafficanti ancora vivi.\n\n[PHI1_HP:PHIL1]\nQuando utilizzi una granata a tempo, lanciala e poi falla esplodere in un secondo momento.\n\n[PHIL1_O:PHIL1]\nHoooooweeeeee!\n\n[PHIL1_D:PHIL1]\nNona avvicinare mai una fiamma alla broda di Phil Cassidy!\n\n{=================================== MISSION TABLE PHIL2 ===================================}\n\n[PHIL2_A:PHIL2]\nEhi Phil, come butta?\n\n[PHIL2_B:PHIL2]\nEeeeehi Tommy, Come va? E passcato moolto tempo...\n\n[PHIL2_C:PHIL2]\nDevi davvero smetterla con quella broda,\n\n[PHIL2_D:PHIL2]\naccidenti, puzza di solvente. Mi fa bruciare gli occhi...\n\n[PHIL2_E:PHIL2]\nShshs shhh silenzio Tommy,\n\n[PHIL2_F:PHIL2]\ne vieni qua che ho qualcoscia da farti vedere... qualcoscia...\n\n[PHIL2_G:PHIL2]\nWoof! Oddio! Riuscirei a sniffarlo da qui in fondo! Mi gira già la testa!\n\n[PHIL2_H:PHIL2]\nNon preoccuparti per l'odore, Tommy, guarda quescto...\n\n[PHIL2_I:PHIL2]\nLa fottuta batteria o qualcosc'altro... Scen'è un altra sulla mensola...\n\n[PHIL2_J:PHIL2]\nTA-DAAA!\n\n[PHIL2_K:PHIL2]\nOmmerda!\n\n[PHI2_01:PHIL2]\n~g~Forza, porta Phil all'ospedale.\n\n[PHI2_03:PHIL2]\n~r~Phil Cassidy è morto!!! Adesso chi ti rifornirà di armi?\n\n[PHI2_05:PHIL2]\nNon all'ospedale, amico! Troppi poliziotti e Viet Cong!\n\n[PHI2_06:PHIL2]\nC'è un vecchio ex-medico militare che mi deve qualche favore e una falciatrice.\n\n[PHI2_07:PHIL2]\nSi trova lungo Little Havana, oooh guarda, un pesce gigante.\n\n[PHI2_08:PHIL2]\nAttento! Nemico tra gli alberi!\n\n[PHI2_09:PHIL2]\nMi sbaglio o le strade sono di gelatina?\n\n[PHI2_10:PHIL2]\nCucchiaio Storto a Mamma Gallina, mi ricevi?\n\n[PHI2_11:PHIL2]\nCucchiaione-ione Woo Woo Woooo!\n\n[PHI2_12:PHIL2]\nSta venendo per me, amico!\n\n[PHI2_13:PHIL2]\nPiume nere che svolazzano dappertutto...\n\n[PHI2_14:PHIL2]\nÈ così bello, amico... così bello... ma così freddo...\n\n[PHI2_15:PHIL2]\n10-4, abbiamo un guidatore ubriaco.\n\n[PHI2_04:PHIL2]\nSALUTE DI PHIL:\n\n[PHI_AS1:PHIL2]\nPHILS PLACE COMPLETATO\n\n[PHI_AS2:PHIL2]\n~g~Nuove armi disponibili presso Phils Place.\n\n{=================================== MISSION TABLE PIZZA ===================================}\n\n[PIZ1_01:PIZZA]\n~g~Vai a consegnare queste pizze: devi lanciarle ai clienti. Fai un giro e tira le pizze.\n\n[PIZ1_02:PIZZA]\n~g~Hai lanciato tutte le pizze, torna indietro e prendine altre.\n\n[PIZ1_05:PIZZA]\n~g~Hai cinque minuti per consegnare le pizze prima che i clienti chiamino un altro negozio di consegne.\n\n[PIZ1_07:PIZZA]\n~r~Hai ucciso un cliente! Sei licenziato!\n\n[PIZ1_08:PIZZA]\n~r~Tempo scaduto. Sei licenziato!\n\n[PIZ1_09:PIZZA]\n~r~Hai distrutto il nostro mezzo! Sei licenziato!\n\n[PIZ1_11:PIZZA]\nEhi! Rimettiti in sella!\n\n[PIZ1_12:PIZZA]\nPizze mancanti:\n\n[PIZ1_06:PIZZA]\nPremi il ~h~~k~~TOGGLE_SUBMISSIONS~~w~ mentre sei in moto per interrompere la missione.\n\n[PIZ1_13:PIZZA]\nConsegnale belle calde e fragranti.\n\n[PIZ1_14:PIZZA]\nAmico, eccoti le pizze.\n\n[PIZ1_15:PIZZA]\nEhi, amico, consegnale in fretta.\n\n[PIZ1_16:PIZZA]\nChe cosa stai aspettando, amico? Hai delle pizze da consegnare!\n\n[PIZ1_17:PIZZA]\nSo che non volevi fare il fattorino delle pizze, ma non me ne frega niente.\n\n[PIZ1_18:PIZZA]\nConsegna queste.\n\n[PIZ1_19:PIZZA]\nDevi consegnare queste.\n\n[PIZ1_20:PIZZA]\nForza, ragazzo, consegna queste o sei licenziato.\n\n[PIZ1_21:PIZZA]\nC'è gente in attesa, amico.\n\n[PIZ1_22:PIZZA]\nChe cosa stai aspettando? Devono essere consegnate!\n\n[PIZ1_23:PIZZA]\nConsegna queste maledette pizze.\n\n[PIZ1_24:PIZZA]\nForza, consegnale calde.\n\n[PIZ1_25:PIZZA]\nEhi, ti occuperesti di queste?\n\n[PIZ1_26:PIZZA]\nEhi, consegna subito queste: forza amico.\n\n[PIZ1_27:PIZZA]\nForza, siamo di fretta: consegnale subito.\n\n[PIZ1_28:PIZZA]\nAncora tu? Bene, consegnale in fretta, amico.\n\n[PIZ1_29:PIZZA]\nNon c'è tempo da perdere, consegnale tutte.\n\n[PIZ1_30:PIZZA]\nMuoviti, brutto pelandrone, consegna questa roba in tempo.\n\n[PIZ1_31:PIZZA]\nNon otterrai una promozione se non ti muoverai più in fretta.\n\n[PIZ1_32:PIZZA]\n~r~La pizza è troppo calda per te?\n\n[PIZ1_33:PIZZA]\n~g~Torna alla pizzeria per altre ordinazioni.\n\n[PIZ1_34:PIZZA]\n~g~Pizze consegnate, ecco i soldi.\n\n[PIZ_WON:PIZZA]\nMissione Pizza completata. Valore massimo dell'salute aumentato a 150.\n\n{=================================== MISSION TABLE PORN1 ===================================}\n\n[POR1_A:PORN1]\nAzione!\n\n[POR1_B:PORN1]\nWhoa! Questo sì che è un bel...\n\n[POR1_C:PORN1]\n30 centimetri, è questa la norma, baby.\n\n[POR1_D:PORN1]\nTAGLIA! Chi è quell'idiota? Tu! TU! Che cosa stai facendo sul mio set? PERCHÉ?\n\n[POR1_E:PORN1]\nCosa sono tute queste stronzate?\n\n[POR1_F:PORN1]\nAlieni? Canne da pesca?\n\n[POR1_G:PORN1]\nChi ha mai visto uno squalo così grande?\n\n[POR1_H:PORN1]\nTutta questa roba deve andarsene.\n\n[POR1_I:PORN1]\nPerché sei venuto a rompere, idiota?\n\n[POR1_J:PORN1]\nEh?\n\n[POR1_K:PORN1]\nPer la passera, ecco perché! Che cos'è questo?\n\n[POR1_L:PORN1]\nQuesta è la mia arte. SORVEGLIANZA!\n\n[POR1_M:PORN1]\nAscolta, lurido fighettino, ti ho comprato. Ho comprato tutto questo.\n\n[POR1_N:PORN1]\nE ho intenzione di cambiare le cose da queste parti...\n\n[POR1_O:PORN1]\nTi farò ricco.\n\n[POR1_P:PORN1]\nUh. Tu sei... tu... tu sei Tommy Vercetti? Pensavo che tu fossi...\n\n[POR1_Q:PORN1]\nEsatto.\n\n[POR1_R:PORN1]\nFaremo numerosi cambiamenti da queste parte e inizieremo a fare soldi veri.\n\n[POR1_S:PORN1]\nEffettivamente, hai mai pensato che...\n\n[POR1_T:PORN1]\nMa prima dobbiamo trovare delle tope che meritino.\n\n[POR1_U:PORN1]\nSì. Le ragazze sono carine, ma sai... Wow!\n\n[POR1_02:PORN1]\n~g~Metti fuori gioco il pappone di Candy e poi passa a prenderla.\n\n[POR1_04:PORN1]\nYo, Candy. Sto cercando delle attrici talentuose: sei interessata?\n\n[POR1_05:PORN1]\nCerto! Ma prima dovrai parlare con il mio agente...\n\n[POR1_06:PORN1]\nChe DIAVOLO stai facendo?\n\n[POR1_07:PORN1]\nAvresti fatto meglio a stare a casa oggi!\n\n[POR1_7B:PORN1]\nMa hai visto questo stronzo?\n\n[POR1_08:PORN1]\nEhi Mercedes!\n\n[POR1_09:PORN1]\nEhi Tommy, vuoi divertirti?\n\n[POR1_10:PORN1]\nNon adesso, tesoro. Sei interessata a fare dei film?\n\n[POR1_11:PORN1]\nCerto, sempre che possano premiare il mio talento.\n\n[POR1_13:PORN1]\n~g~Porta le ragazze allo studio e presentale a Steve.\n\n[POR1_14:PORN1]\nSei assunta!\n\n[POR1_15:PORN1]\nEhi Tommy, vieni anche tu per un riscaldamento?\n\n[POR1_17:PORN1]\nWhoa, che bello squalo!\n\n[POR1_18:PORN1]\n~r~Mercedes è morta!\n\n[POR1_20:PORN1]\nTommy, dove stai andando? Torna qui!\n\n[POR1_21:PORN1]\nDove stai andando?\n\n[POR1_22:PORN1]\nTommy, quando passeremo un po' di tempo io e te da soli?\n\n[POR1_01:PORN1]\n~g~Candy Suxxx sarebbe perfetta per il ruolo da protagonista!\n\n[POR1_12:PORN1]\n~g~Porta Candy con te all'appuntamento con Mercedes.\n\n[POR1_16:PORN1]\nMagari più tardi...\n\n[POR1_24:PORN1]\n~g~Torna indietro e prendi Candy.\n\n[POR1_25:PORN1]\n~g~Hai lasciato Candy indietro, torna a prenderla.\n\n[POR1_23:PORN1]\n~g~Candy starà lavorando in ~h~Downtown~g~.\n\n[POR1_26:PORN1]\n~g~Ecco Candy, sembra sia stata ancora con il deputato Shrub.\n\n[POR1_27:PORN1]\nForza, andiamo.\n\n[POR1_28:PORN1]\nTommy, fai attenzione! Il mio seno siliconato non è ancora assicurato!\n\n[POR1_29:PORN1]\nÈ questo il modo di guidare?\n\n[POR1_30:PORN1]\nNon posso recitare dopo tutto questo!\n\n[POR1_31:PORN1]\nCosa? Stai cercando di uccidermi? Credevo di essere una star!\n\n{=================================== MISSION TABLE PORN2 ===================================}\n\n[POR2_A:PORN2]\nCome stanno andando le riprese, Steve?\n\n[POR2_B:PORN2]\nBeh, Candy è un talento naturale e l'altra ragazza... è insaziabile!\n\n[POR2_C:PORN2]\nSi è passata metà del cast e dello staff prima ancora che iniziassi a fare i controlli delle luci.\n\n[POR2_D:PORN2]\nComunque, eh, domani andiamo fuori a registrare le scene sulla barca...\n\n[POR2_E:PORN2]\nScene sulla barca? Quali scene sulla barca?\n\n[POR2_F:PORN2]\nI pescatori sono presi dalla passione quando lo squalo gigante arriva e...\n\n[POR2_G:PORN2]\nChe cosa ho detto sullo squalo gigante?\n\n[POR2_H:PORN2]\nHo detto: 'NIENTE SQUALO GIGANTE', tutto chiaro?\n\n[POR2_I:PORN2]\nLascia semplicemente le telecamere puntate sull'azione!\n\n[POR2_J:PORN2]\nOK, OK. Ehi Tommy, ci devo pure provare, no?\n\n[POR2_K:PORN2]\nHai fatto stampare quei volantini?\n\n[POR2_L:PORN2]\nSì, ma nessuno ci farà distribuire quella roba, cioè...\n\n[POR2_M:PORN2]\nLasciano semplicemente troppo, uh... poco all'immaginazione.\n\n[POR2_N:PORN2]\nNon preoccuparti per quello.\n\n[POR2_O:PORN2]\nHo le mie idee sulla distribuzione.\n\n[POR2_P:PORN2]\nOK. Ehi Candy, uh, nella mia roulotte.\n\n[POR2_01:PORN2]\n~g~C'è un idrovolante che è stato utilizzato nelle scene di alcuni vecchi film di Indy nel retro degli studi.\n\n[POR2_02:PORN2]\n~g~Passa sopra uno dei punti di controllo per cominciare a distribuire volantini.\n\n[POR2_03:PORN2]\n~g~Lancia i volantini fino alla fine del punto di controllo.\n\n[POR2_04:PORN2]\n~r~CARBURANTE AL MINIMO!!!\n\n[POR2_05:PORN2]\nUsalo per distribuire i volantini per la città.\n\n[DILDO:PORN2]\nCarburante:\n\n[POR2_Q:PORN2]\nAccidenti.\n\n[PORN2_9:PORN2]\n~g~Hai ~1~ secondi per tornare sulla tua Skimmer prima che la missione abbia termine.\n\n{=================================== MISSION TABLE PORN3 ===================================}\n\n[POR3_A:PORN3]\nOK, qual è il problema adesso?\n\n[POR3_B:PORN3]\nSSShhhh!\n\n[POR3_C:PORN3]\nBeh, dopo il suo incontro ravvicinato con le ninfo-invasori,\n\n[POR3_D:PORN3]\nil nostro eroe non riesce a pensare ad altro che a questa immensa montagna fallica...\n\n[POR3_E:PORN3]\ned è qui che vogliamo girare la scena con la tinozza piena di puré, ma poi noi...\n\n[POR3_F:PORN3]\nNon me ne può fregar di meno,\n\n[POR3_G:PORN3]\nBasta che continui, continui, continui.\n\n[POR3_H:PORN3]\nEhi Tommy...\n\n[POR3_I:PORN3]\nmi hai accennato qualcosa al telefono riguardo dei problemi legali...\n\n[POR3_J:PORN3]\nAh sì! Il deputato Alex Shrub, lanciato verso la cattura di nuovi elettori, ha deciso di conquistare i puritani.\n\n[POR3_K:PORN3]\nSi mormora che voglia supportare delle misure per limitare, diciamo,\n\n[POR3_L:PORN3]\nl'aspetto più carnale della grande industria nazionale dell'intrattenimento.\n\n[POR3_M:PORN3]\nOttimo.\n\n[POR3_N:PORN3]\nCandy! Conosci Shrub,\n\n[POR3_O:PORN3]\nvoi ragazzi vi siete lanciati in qualcosa di perverso?\n\n[POR3_P:PORN3]\nOh sì, oh sì, oh sì! Sì sì sì SÌ OOOoooh!\n\n[POR3_Q:PORN3]\nTi prego, dimmi che lo hai ripreso.\n\n[POR3_R:PORN3]\nFaceva parte del... uh... o stava parlando con...\n\n[POR3_S:PORN3]\nEhi, non saprei dire. Comunque...\n\n[POR3_T:PORN3]\nTi consiglio vivamente di seguirla dopo le riprese,\n\n[POR3_U:PORN3]\nvedi se va dritta al suo nuovo nido d'amore.\n\n[POR3_V:PORN3]\nHai una macchina fotografica?\n\n[POR3_X:PORN3]\nCerto, dategliene una.\n\n[POR3_02:PORN3]\n~r~Hai ucciso il deputato! Adesso come farai a ricattarlo?\n\n[POR3_03:PORN3]\n~r~Hai allarmato la sorveglianza del deputato: lo porteranno immediatamente via.\n\n[POR3_04:PORN3]\nCandy, mi chiameresti Martha?\n\n[POR3_05:PORN3]\nOh Alex, cioè Martha. Tutto ciò che vuoi!\n\n[POR3_06:PORN3]\nMartha, qualcuno ci sta osservando... che cosa perversa.\n\n[POR3_07:PORN3]\nEhi tu. Dammi quella macchina fotografica!\n\n[POR3_01:PORN3]\n~g~Segui la ~h~limousine~g~ di Candy.\n\n[POR3_15:PORN3]\n~r~Hai distrutto la limousine di Candy!\n\n[POR3_17:PORN3]\n~g~Torna allo studio con il rullino.\n\n[POR3_19:PORN3]\n~r~Hai finito il rullino!\n\n[POR3_21:PORN3]\n~g~Hai perso la limousine di Candy!\n\n[POR3_22:PORN3]\n~g~L'hotel WR Chariot di fronte al balcone dovrebbe essere un luogo ideale per scattare le foto.\n\n[POR3_23:PORN3]\n~g~C'è un ingresso laterale che ti permetterà di entrare nell'hotel.\n\n[POR3_08:PORN3]\nTieni premuto il ~h~~k~~PED_LOCK_TARGET~~w~ per ~h~mirare~w~ con la macchina fotografica.\n\n[POR3_09:PORN3]\nTieni premuto il ~h~~k~~PED_LOCK_TARGET~~w~ per ~h~mirare~w~ con la macchina fotografica.\n\n[POR3_10:PORN3]\nPremi il ~h~~k~~PED_SNIPER_ZOOM_IN~~w~ per ~h~zoomare~w~ con la macchina fotografica e il ~h~~k~~PED_SNIPER_ZOOM_OUT~~w~ per ~h~allargare il campo~w~.\n\n[POR3_11:PORN3]\nPremi il ~h~~k~~PED_SNIPER_ZOOM_IN~~w~ per ~h~zoomare~w~ con la macchina fotografica e il ~h~~k~~PED_SNIPER_ZOOM_OUT~~w~ per ~h~allargare il campo~w~.\n\n[POR3_12:PORN3]\nPremi il ~h~~k~~PED_FIREWEAPON~~w~ per scattare una foto.\n\n[POR3_13:PORN3]\nPremi il ~h~~k~~PED_FIREWEAPON~~w~ per scattare una foto.\n\n[POR3_14:PORN3]\nPremi il ~h~~k~~PED_FIREWEAPON~~w~ per scattare una foto.\n\n[POR3_20:PORN3]\n~g~Se hai bisogno di un mezzo, usa lo ~h~Sparrow~g~ sul retro.\n\n[POR3_16:PORN3]\n~g~Hai bisogno di tre foto di qualità di Alex Shrub con Candy.\n\n[POR3_24:PORN3]\nFOTO SCATTATE:\n\n{=================================== MISSION TABLE PORN4 ===================================}\n\n[POR4_A:PORN4]\nMi dispiace, ma adesso proprio non riesco ad ingoiarlo.\n\n[POR4_B:PORN4]\nOh EDDAI tesoro!\n\n[POR4_C:PORN4]\nÈ inalberato come un capodoglio, accidenti,\n\n[POR4_D:PORN4]\ncome fai a non farti coinvolgere dalla parte?\n\n[POR4_E:PORN4]\nMa Stevie...\n\n[POR4_F:PORN4]\nCome sta andando il mio regista?\n\n[POR4_G:PORN4]\nOh, accidenti. Lo scontro tra l'integrità artistica e\n\n[POR4_H:PORN4]\ni sobbalzi e le pompanti azioni continua senza sosta.\n\n[POR4_I:PORN4]\nE, prima che tu me lo chieda, sì, tutti e quattro i film saranno pronti per...\n\n[POR4_J:PORN4]\nDolcezza, potresti PER FAVORE tenere l'anaconda nell'inquadratura,\n\n[POR4_K:PORN4]\nmi costa più lei all'ora di te!\n\n[POR4_L:PORN4]\nOh, scusa Steve.\n\n[POR4_M:PORN4]\nPensavo, abbiamo bisogno di qualche grossa acrobazia per promuovere il lancio.\n\n[POR4_N:PORN4]\nQualcosa che farà davvero impatto sulla città... ti viene in mente niente?\n\n[POR4_O:PORN4]\nBeh, nei vecchio tempi si facevano le feste di gala,\n\n[POR4_P:PORN4]\nattori, limousine, il cielo notturno illuminato dai riflettori...\n\n[POR4_Q:PORN4]\nRiflettori? Mi è venuta un'idea...\n\n[POR4_R:PORN4]\n...sì, sì, sì. I vestiti pieni di lustrini, e le limousine, oh, le prime visioni...\n\n[POR4_S:PORN4]\nOh, sì signora, certo signora,\n\n[POR4_T:PORN4]\ne la stampa, e gli sbarramenti di luci...\n\n[POR4_01:PORN4]\n~g~Raggiungi ~y~Downtown~g~ e posiziona i riflettori sopra l'edificio.\n\n[POR4_02:PORN4]\n~g~Avrai bisogno di una moto veloce per saltare da un tetto all'altro. La guardia della sorveglianza possiede una ~y~PCJ 600~g~...\n\n[POR4_03:PORN4]\n~g~Devi raggiungere i tetti degli edifici. Ci dovrebbe essere un ascensore in uno degli uffici ai piani superiori...\n\n[POR4_06:PORN4]\n~g~Torna all'ufficio ai piani inferiori se vuoi accedere nuovamente ai tetti.\n\n[POR4_07:PORN4]\n~g~Avrai bisogno di una moto per saltare da un edificio all'altro.\n\n[POR4_08:PORN4]\n~g~Lanciati attraverso la finestra per avviare il percorso. Avrai tempo fino alle 07:00 prima che diventi troppo luminoso per muoverti non visto.\n\n[POR4_09:PORN4]\n~g~I bonus ti mostreranno il successivo edificio su cui saltare.\n\n[POR4_10:PORN4]\n~r~È troppo tardi per arrivare in cima non visto.\n\n[POR4_11:PORN4]\nRitorna alla scala se vuoi accedere nuovamente ai tetti.\n\n[POR4_05:PORN4]\n~g~Queste scale portano a un ufficio ai piani inferiori.\n\n[POR_AS1:PORN4]\nSTUDIO CINEMATOGRAFICO COMPLETATO\n\n[POR_AS2:PORN4]\n~g~L'Inter Global Films d'ora in poi genererà introiti per un massimo di ~1~$. Ricordati di recuperarli regolarmente.\n\n{=================================== MISSION TABLE PROT1 ===================================}\n\n[PRO1_B:PROT1]\nNon sopporto più questo aspetto. Tommy, che ne dici? E se mettessimo un bar...\n\n[PRO1_D:PROT1]\nAscoltami,\n\n[PRO1_E:PROT1]\nè giunta l'ora di prendere in mano questa città. È tutto pronto per questo.\n\n[PRO1_F:PROT1]\nDobbiamo cominciare a impadronirci del territorio\n\n[PRO1_G:PROT1]\ne far sapere a Vice City che ci sono nuovi giocatori in città, mi segui?\n\n[PRO1_I:PROT1]\nTommy, ciò di cui hai bisogno è una facciata legale, delle proprietà. A me ha sempre fatto comodo.\n\n[PRO1_J:PROT1]\nDobbiamo iniziare a mostrare i denti o tutto questo lavoro sarà stato vano.\n\n[PRO1_K:PROT1]\nI gruppi locali sanno che Diaz è morto e si rifiutano di pagare per la protezione!\n\n[PRO1_L:PROT1]\nPotremmo provare con la corruzione...\n\n[PRO1_M:PROT1]\nCorruzione? A fanculo la corruzione! Ti mostrerò io come si fa a spaventarli.\n\n[PRO1_01:PROT1]\n~g~Assali i negozi e fuggi: i proprietari chiederanno la tua protezione.\n\n[PRO1_03:PROT1]\n~r~Si trattava di un assali e fuggi, non di un assali e bevi un caffè.\n\n[PRO1_04:PROT1]\nTutti i miei beni, distrutti!\n\n[PRO1_05:PROT1]\nRovinato... ROVINATO!\n\n[PRO1_06:PROT1]\nMaledizione, devo pagare la protezione!\n\n[PRO1_07:PROT1]\nLa mia meravigliosa vetrina!\n\n[PRO1_08:PROT1]\nIl mio negozio, il mio bellissimo negozio.\n\n[PRO1_09:PROT1]\nVercetti, ricorda questo nome.\n\n[PRO1_10:PROT1]\nAdesso gestisco io questa città. IO!\n\n[BUYP1:PROT1]\nNon puoi comprare proprietà in certe aree della mappa.\n\n[BUYP2:PROT1]\nSe vedi un'icona a forma di casa verde, puoi comprare quella proprietà.\n\n[PRO1_N:PROT1]\nSarò di ritorno fra cinque minuti...\n\n[PRO1_11:PROT1]\n~g~Raggiungi il ~y~Mall North Point~g~ in ~y~Vice Point~g~.\n\n[PRO1_12:PROT1]\n~g~Distruggi le vetrine di tutti i negozi e i proprietari saranno pronti a chiederti protezione.\n\n[PRO1_A:PROT1]\nOh, dobbiamo ridecorare questo posto, deve sembrare più vecchio.\n\n[PRO1_C:PROT1]\nSei il mio avvocato, Rosenberg, non il mio arredatore. Chiaro?\n\n[BUYP3:PROT1]\nPosizionati all'interno del simbolo e premi il tasto ~h~~k~~PED_ANSWER_PHONE~~w~ per acquistare la proprietà.\n\n[PRO1_13:PROT1]\n~g~Hai cinque minuti per distruggerli tutti.\n\n{=================================== MISSION TABLE PROT2 ===================================}\n\n[PRO2_A:PROT2]\nQual è il problema?\n\n[PRO2_B:PROT2]\nAlcuni bar si rifiutano di pagare.\n\n[PRO2_C:PROT2]\nDicono di essere protetti da una gang locale di malviventi.\n\n[PRO2_D:PROT2]\nMa non preoccuparti, Tommy, me ne occupo io.\n\n[PRO2_E:PROT2]\nE tu te ne occupi in questo modo?\n\n[PRO2_F:PROT2]\nVoi due, alzate il culo...\n\n[PRO2_G:PROT2]\nAndiamo.\n\n[PRO2_01:PROT2]\n~g~Fai fuori le guardie che sorvegliano il Front Page Bar e scopri chi le ha rifornite.\n\n[PRO2_10:PROT2]\n~g~Altri due sono riusciti a scappare. Rintracciali e finisci questa storia.\n\n[PRO2_11:PROT2]\nEntra in macchina, idiota.\n\n[PRO2_02:PROT2]\nLa tua protezione ha bisogno di più protezione.\n\n[PRO2_03:PROT2]\nMaledizione, non ancora! Non ne voglio sapere!\n\n[PRO2_04:PROT2]\nQuesti idioti operano per la DBP Security, con sede dietro all'isolato.\n\n[PRO2_05:PROT2]\nVedete di risolverla per i fatti vostri.\n\n[PRO2_06:PROT2]\nCi si vede più tardi.\n\n[PRO2_07:PROT2]\nSì, sì, certo.\n\n[PRO2_08:PROT2]\n~g~La DBP Security presto scoprirà le tue intenzioni: attacca prima che si ritiri.\n\n[PRO2_09:PROT2]\n~g~Vai a parlare con il proprietario del Front Page.\n\n{=================================== MISSION TABLE PROT3 ===================================}\n\n[PRO3_A:PROT3]\nCretino! Ma a cosa pensavi?\n\n[PRO3_B:PROT3]\nTi rendi conto che cosa hai combinato?\n\n[PRO3_C:PROT3]\nPotremmo essere tutti rovinati!\n\n[PRO3_D:PROT3]\nIl timer deve essersi inceppato.\n\n[PRO3_E:PROT3]\nQuel posto era stato minato per saltare come una fabbrica di fuochi d'artificio.\n\n[PRO3_F:PROT3]\nMa qualcuno ha informato i poliziotti...\n\n[PRO3_G:PROT3]\nQual è il problema, ragazzi?\n\n[PRO3_H:PROT3]\nMike doveva dar fuoco a un locale del Mall,\n\n[PRO3_I:PROT3]\nma ha fatto casino con i fusibili e adesso la polizia sta indagando.\n\n[PRO3_J:PROT3]\nDobbiamo preparare la nostra roba e andarcene da qui!\n\n[PRO3_K:PROT3]\nRilassatevi, tutti e due: fatemi pensare per un attimo!\n\n[PRO3_L:PROT3]\nTommy Vercetti non scappa con la coda fra le gambe.\n\n[PRO3_M:PROT3]\nI poliziotti passeranno al setaccio l'intero edificio, giusto?\n\n[PRO3_N:PROT3]\nMa tutto ciò richiede tempo.\n\n[PRO3_O:PROT3]\nDobbiamo entrare e dar fuoco noi stessi al locale.\n\n[PRO3_P:PROT3]\nSì, ma...\n\n[PRO3_Q:PROT3]\nSolo un poliziotto potrebbe avvicinarsi a meno di un chilometro dal luogo!\n\n[PRO3_R:PROT3]\nAllora andiamo come poliziotti.\n\n[PRO3_S:PROT3]\nRecupereremo delle uniformi... e avremo bisogno di una volante.\n\n[PRO3_T:PROT3]\nTutto questo grazie a te, Mike.\n\n[PRO3_U:PROT3]\nMi dispiace.\n\n[PRO3_V:PROT3]\nHo capito.\n\n[PRO3_W:PROT3]\nQuello che dobbiamo fare è attirare i poliziotti con un gestaccio,\n\n[PRO3_X:PROT3]\nMetterli con le spalle al muro\n\n[PRO3_Y:PROT3]\ne sopraffarli.\n\n[PRO3_Z:PROT3]\nOttimo piano, andiamo!\n\n[PRO3_A1:PROT3]\nBene.\n\n[PRO3_01:PROT3]\nOK Lance, attira l'attenzione dei poliziotti!\n\n[PRO3_02:PROT3]\n~g~Prendi la macchina della polizia e vai a posizionare la bomba nel Tarbrush Café dentro al Mall.\n\n[PRO3_03:PROT3]\n~g~Hai lasciato Lance indietro, torna a prenderlo.\n\n[PRO3_04:PROT3]\n~g~Andiamo.\n\n[PRO3_05:PROT3]\n~r~Hai ucciso Lance!\n\n[PRO3_07:PROT3]\n~g~È saltata la vostra copertura. Muoviti a piazzare la bomba!\n\n[PRO3_09:PROT3]\nLegali e imbavagliali!\n\n[PRO3_10:PROT3]\nOooh. Mi calza a pennello!\n\n[PRO3_11:PROT3]\nUn po' stretto sul pacco...\n\n[PRO3_12:PROT3]\nOh sì, hai ragione, anche a me!\n\n[PRO3_13:PROT3]\nTranquillo fratello: nessun poliziotto guida così male!\n\n[PRO3_14:PROT3]\nRicorda: sorridi agli altri poliziotti!\n\n[PRO3_15:PROT3]\nEhi agente, bel distintivo, bel distintivo.\n\n[PRO3_16:PROT3]\nUn po' più sciolto, Lance.\n\n[PRO3_17:PROT3]\nOK, i timer sono pronti, 5 secondi alla scadenza.\n\n[PRO3_18:PROT3]\n5 secondi? Dobbiamo scappare di corsa da qua!\n\n[PRO3_19:PROT3]\nQuesto deve davvero averli irritati.\n\n[PRO3_20:PROT3]\n~g~Fatevi inseguire dai due poliziotti nel garage.\n\n[PRO3_21:PROT3]\n~g~Ottieni un livello di sospetto così i poliziotti ti inseguiranno fino al garage.\n\n[PRO3_22:PROT3]\n~g~La porta del garage è bloccata! Liberala così potrai chiuderla.\n\n[PRO3_23:PROT3]\n~g~Cammina sul segnalino per piazzare la bomba.\n\n[PRO3_24:PROT3]\n~g~Allontanati dal Café!\n\n[PRO_AS1:PROT3]\nCIRCOLO DI PROTEZIONE COMPLETATO\n\n[PRO_AS2:PROT3]\n~g~La proprietà di Vercetti d'ora in poi genererà introiti per un massimo di ~1~$. Ricordati di recuperarli regolarmente.\n\n[PRO3_08:PROT3]\n~g~Torna alla ~h~proprietà di Vercetti~g~ su ~h~Starfish Island~g~.\n\n{=================================== MISSION TABLE RACES ===================================}\n\n[RACES_2:RACES]\n~g~Hai bisogno di un veicolo per partecipare, non è mica una maratona!\n\n[RACES_3:RACES]\n3..2..1.. VIA VIA VIA!\n\n[RACES_8:RACES]\n~r~Non hai vinto la corsa!\n\n[RACES00:RACES]\nCorsa ~1~:\n\n[RACES01:RACES]\nTerminal Velocity\n\n[RACES02:RACES]\nOcean Drive\n\n[RACES03:RACES]\nBorder Run\n\n[RACES04:RACES]\nCapital Cruise\n\n[RACES05:RACES]\nTour!\n\n[RACES06:RACES]\nV.C. Endurance\n\n[RACES07:RACES]\nCosto d'ingresso: ~1~$\n\n[RACES08:RACES]\nTempo migliore: ~1~:~1~\n\n[RACES09:RACES]\nMiglior risultato: PRIMO\n\n[RACES10:RACES]\nMiglior risultato: SECONDO\n\n[RACES11:RACES]\nMiglior risultato: TERZO\n\n[RACES12:RACES]\nMiglior risultato: QUARTO\n\n[RACES13:RACES]\nLunghezza tracciato: ~1~.~1~ km\n\n[RACES15:RACES]\nMiglior tempo: ND\n\n[RACES16:RACES]\nMiglior risultato: ND\n\n[RACES18:RACES]\nHAI VINTO: ~1~$\n\n[RACES19:RACES]\nNon puoi permetterti di partecipare a questa gara.\n\n[RACES22:RACES]\nTempo migliore: ~1~:0~1~\n\n[RACES23:RACES]\nLunghezza tracciato: ~1~.~1~ miglia\n\n[RACES_1:RACES]\n~g~Recupera un veicolo veloce e raggiungi la griglia di partenza.\n\n[RACEHLP:RACES]\n~w~Premi il ~h~~k~~PED_SPRINT~~w~ per avviare la corsa selezionata. ~w~Premi il ~h~~k~~VEHICLE_ENTER_EXIT~~w~ per uscire.\n\n{=================================== MISSION TABLE RCHELI1 ===================================}\n\n[WRECKED:RCHELI1]\n~r~Il veicolo è a pezzi!\n\n[RCH1_4:RCHELI1]\nPunti di controllo rimanenti:\n\n[RCH1_6:RCHELI1]\n~g~Usa l'elicottero radiocomandato per attraversare i punti di controllo nella zona dell'aeroporto.\n\n[RCH1_7:RCHELI1]\n~g~In totale ci sono 20 punti di controllo.\n\n[RCH1_12:RCHELI1]\n~r~L'elicottero radiocomandato si sta allontanando dal raggio d'azione!\n\n[RCH1_13:RCHELI1]\n~r~L'elicottero radiocomandato è fuori portata!\n\n[RCH1_8:RCHELI1] { reVC update }\n~g~Se desideri interrompere la missione, premi il ~h~~k~~VEHICLE_FIREWEAPON~~g~ per far esplodere l'elicottero.\n\n{=================================== MISSION TABLE RCPLNE1 ===================================}\n\n[RCPL1_4:RCPLNE1]\n~g~Sfida nella GARA A TAPPE altri 3 aerei radiocomandati.\n\n[RCPL1_5:RCPLNE1]\n~g~Vola attraverso i punti di controllo in Vice City.\n\n[RCPL1_6:RCPLNE1] { reVC update }\n~g~Se desideri interrompere la missione, premi il ~h~~k~~VEHICLE_FIREWEAPON~~g~ per far esplodere l'aereo.\n\n[RCPL1_8:RCPLNE1]\n~g~L'aereo radiocomandato è quasi fuori portata!\n\n[RCPL1_9:RCPLNE1]\n~r~L'aereo radiocomandato è fuori portata!\n\n{=================================== MISSION TABLE RCRACE1 ===================================}\n\n[RCR1_4:RCRACE1]\nGiri rimanenti:\n\n[RCR1_1:RCRACE1]\n~g~Sfida in una gara a tappe altre 3 macchine radiocomandate.\n\n[RCR1_2:RCRACE1]\n~g~Per vincere, completa per primo due giri del tracciato!\n\n[RCR1_6:RCRACE1]\n~g~La macchina radiocomandata è quasi fuori portata!\n\n[RCR1_7:RCRACE1]\n~r~La macchina radiocomandata è fuori portata!\n\n{=================================== MISSION TABLE ROCK1 ===================================}\n\n[RBM1_A:ROCK1]\nAllllllllRrrighttt!\n\n[RBM1_B:ROCK1]\nBrillante, davvero brillante!\n\n[RBM1_D:ROCK1]\nEhi, hai già incontrato i Love Fist?\n\n[RBM1_E:ROCK1]\nNo, non ancora, ma mi piace molto la vostra musica.\n\n[RBM1_F:ROCK1]\nLascia che ti presenti la band.\n\n[RBM1_G:ROCK1]\nQuesto è P, Percy, Dick. Willy è nel cesso! Jezz è invece il tipo che hai visto prima nella cabina di registrazione.\n\n[RBM1_H:ROCK1]\nRagazzi, vorrei presentarvi un mio carissimo amico.\n\n[RBM1_I:ROCK1]\nSi chiama Tommy. Ci conosciamo da tempo.\n\n[RBM1_J:ROCK1]\nCiao amico.\n\n[RBM1_K:ROCK1]\nE, ehm, qual era il tuo nome?\n\n[RBM1_L:ROCK1]\nEddai Jezz che lo sai,\n\n[RBM1_M:ROCK1]\nnon fare questi scherzetti con me, amico,\n\n[RBM1_N:ROCK1]\nsono troppo furbo per cascarci, tesoro!\n\n[RBM1_O:ROCK1]\nVedi, la situazione Tom è che i ragazzi hanno bisogno di aiuto.\n\n[RBM1_P:ROCK1]\nNon hanno i contatti giusti da questa parte, del tipo 'come sta tuo padre'.\n\n[RBM1_Q:ROCK1]\nAbbiamo bisogno di droga, amico!\n\n[RBM1_R:ROCK1]\nDobbiamo fare un po' di casino alla Love Fist, capito?\n\n[RBM1_S:ROCK1]\nBeh, questa è Vice City. Qual è il problema?\n\n[RBM1_U:ROCK1]\nLove Juice, sì!\n\n[RBM1_V:ROCK1]\nLove Juice?\n\n[RBM1_W:ROCK1]\nSì, due parti di broda, una parte di polvere, cinque bombe effervescenti e un litro di petrolio.\n\n[RBM1_X:ROCK1]\nCi puoi aiutare, amico?\n\n[RBM1_Y:ROCK1]\nBeh, significherebbe molto per i ragazzi.\n\n[RBM1_Z:ROCK1]\nLo farai per loro, vero?\n\n[RBM1_7:ROCK1]\n~r~Non hai portato la Love Juice in tempo!\n\n[RBM1_8:ROCK1]\n~r~Mercedes è morta!\n\n[RBM1_10:ROCK1]\n~r~Idiota! Hai distrutto la merce!\n\n[RBM1_13:ROCK1]\n~g~Porta la 'Love Juice' e Mercedes alla band prima che salgano sul palco.\n\n[RBM1_15:ROCK1]\n~r~Hai perso lo spacciatore, i soldi e la droga!\n\n[RBM1_17:ROCK1]\n~g~Uccidi lo spacciatore e recupera la droga!\n\n[MOB_07A:ROCK1]\nEhi amico, ai ragazzi non dispiacerebbe un po' di compagnia, se capisci cosa intendo...\n\n[MOB_07B:ROCK1]\nConosco la ragazza giusta.\n\n[ROK1_5:ROCK1]\nEhi Mercedes!\n\n[ROK1_6:ROCK1]\nCiao Tommy, come stai?\n\n[ROK1_7:ROCK1]\nNon male. Senti, ti piacerebbe intrattenere i Love Fist?\n\n[ROK1_8:ROCK1]\nOK, ma per questo favore voglio una ricompensa...\n\n[RBM1_14:ROCK1]\n~g~Hai bisogno di una macchina o di una moto!\n\n[RBM1_1:ROCK1]\n~g~Vai a prendere Mercedes al suo appartamento.\n\n[RBM1_12:ROCK1]\n~g~Raccogli gli ingredienti per la 'Love Juice' dallo spacciatore.\n\n[ROK1_2:ROCK1]\nNON NECESSARIO\n\n[ROK1_3:ROCK1]\nNON NECESSARIO\n\n[MERC_39:ROCK1]\nCi vediamo più tardi, tesoro.\n\n[RBM1_C:ROCK1]\nEhi, Tommy! Sono felice che ce tu l'abbia fatta.\n\n[ROK1_1A:ROCK1]\nStai cercando qualcosa di speciale? Ho proprio ciò che ti serve!\n\n[ROK1_9:ROCK1]\nGrazie per i soldi, idiota!\n\n[RBM1_T:ROCK1]\nAbbiamo bisogno di Love Juice, hai presente?\n\n{=================================== MISSION TABLE ROCK2 ===================================}\n\n[RBM2_A:ROCK2]\nTommy, amico, sono felice di vederti!\n\n[RBM2_B:ROCK2]\nCosa succede?\n\n[RBM2_C:ROCK2]\nBrutte vibrazioni, Tommy...\n\n[RBM2_E:ROCK2]\nC'è questo tipo, lo conosciamo appena, ma lui la sa lunga su di noi.\n\n[RBM2_F:ROCK2]\nCome questo tipo. Sa tutto su di noi.\n\n[RBM2_G:ROCK2]\nSa che Willy ama la biancheria intima femminile, eh!\n\n[RBM2_H:ROCK2]\nO che a Percy piacciono i Duran Duran!\n\n[RBM2_K:ROCK2]\nSì, come nella storia dei missili, esatto. Ma ascolta, questo bastardo...\n\n[RBM2_L:ROCK2]\ncioè, sì, questo tipo, vuole vedere i Love Fist morti.\n\n[RBM2_M:ROCK2]\nMorti, Tommy.\n\n[RBM2_N:ROCK2]\nLove Fist morti. Lo sai come si dice, i buoni muoiono giovani.\n\n[RBM2_O:ROCK2]\nMa Tommy, devi salvare i Love Fist!\n\n[RBM2_P:ROCK2]\nAbbiamo un concerto fra due ore e credo...\n\n[RBM2_Q:ROCK2]\nI ragazzi credono che il maniaco stia architettando qualcosa di losco.\n\n[RBM2_1:ROCK2]\n~g~Guida la limousine al concerto e cerca di attirare allo scoperto lo psicopatico.\n\n[RBM2_2:ROCK2]\n~r~Hai distrutto l'auto della band!\n\n[RBM2_3:ROCK2]\n~g~Vai al concerto!\n\n[RBM2_4:ROCK2]\n~g~Becca lo psicopatico! Non farlo scappare!\n\n[RBM2_5:ROCK2]\n~r~Lo hai perso, idiota!\n\n[RBM2_7:ROCK2]\n~r~I fan sono stati attaccati: lo psicopatico non si farà vivo!\n\n[RBM2_8:ROCK2]\n~r~Le guardie della sorveglianza sono state attaccate: lo psicopatico non si farà vivo!\n\n[PSYCH_1:ROCK2]\nVedrò i Love Fist bruciare!\n\n[PSYCH_2:ROCK2]\nI Love Fist hanno rovinato la mia vita!\n\n[RBM2_I:ROCK2]\nSta zitto, idiota. Solo perché a Jezz piacciono le pecore.\n\n[RBM2_R:ROCK2]\nMa sta' zitto!\n\n[RBM2_D:ROCK2]\nCerto, niente scherzi, è roba forte, davvero forte sai?\n\n[RBM2_J:ROCK2]\nÈ una questione di passione, sai?\n\n{=================================== MISSION TABLE ROCK3 ===================================}\n\n[RBM3_A:ROCK3]\nTommy! Tommy! Tommy amico, lo psicopatico è tornato!\n\n[RBM3_B:ROCK3]\nChe succede?\n\n[RBM3_C:ROCK3]\nQuello psicopatico non vuole lasciar stare i Love Fist!\n\n[RBM3_D:ROCK3]\nNon lo hai ucciso, amico. E adesso è tornato.\n\n[RBM3_E:ROCK3]\nSì, sì, sì e il problema è che...\n\n[RBM3_F:ROCK3]\nIl problema è che abbiamo bisogno di qualcuno di cui ci fidiamo per guidare la limousine,\n\n[RBM3_G:ROCK3]\npoiché il pazzo continua a minacciarci!\n\n[RBM3_I:ROCK3]\nStiamo letteralmente cadendo a pezzi.\n\n[RBM3_J:ROCK3]\nOK ragazzi, calmatevi. Me ne occuperò io.\n\n[RBM3_K:ROCK3]\nGeneralmente non perdo tempo a portare in giro un gruppo di ubriaconi scozzesi bisessuali,\n\n[RBM3_L:ROCK3]\nma, nel vostro caso, farò un'eccezione.\n\n[ROK3_03:ROCK3]\nConviene fare un giro più lungo.\n\n[ROK3_04:ROCK3]\nEhi Tommy, cambia la stazione.\n\n[ROK3_08:ROCK3]\nMi sto annoiando di tutto questo.\n\n[ROK3_09:ROCK3]\nTieni premuto il maledetto pedale!\n\n[ROK3_61:ROCK3]\nDobbiamo trovare la bomba!\n\n[ROK3_28:ROCK3]\nSuonerò il basso all'inferno.\n\n[ROK3_30:ROCK3]\nQualcuno faccia qualcosa.\n\n[ROK3_32:ROCK3]\nOK, osso duro, fai qualcosa tu allora.\n\n[ROK3_34:ROCK3]\nWilly, potresti succhiare la broda con una cannuccia.\n\n[ROK3_37:ROCK3]\nPassa una cannuccia a Willy!\n\n[ROK3_41:ROCK3]\nQuale filo, Tommy?\n\n[ROK3_42:ROCK3]\nQuello verde.\n\n[ROK3_43:ROCK3]\nNon c'è un filo verde! Questo forse è verde...\n\n[ROK3_44:ROCK3]\nQualcuno di questi fili ti sembra verde?\n\n[ROK3_49:ROCK3]\nTi ho tenuto con me per anni.\n\n[ROK3_51:ROCK3]\nUna ragazzina isterica.\n\n[ROK3_52:ROCK3]\nSì.\n\n[ROK3_53:ROCK3]\nTaci e taglia un filo.\n\n[ROK3_54:ROCK3]\nQuale filo?\n\n[ROK3_55:ROCK3]\nQuesto qua...\n\n[ROK3_56:ROCK3]\nNO!\n\n[ROK3_57:ROCK3]\nOddio, siamo vivi. Non siamo esplosi, amico. Tommy, bel lavoro. Rock and roll, ragazzi.\n\n[ROK3_58:ROCK3]\nNon abbiamo uno spettacolo a cui andare? Del casino da fare? Fans di cui abusare?\n\n[ROK3_59:ROCK3]\nLOVE FIST!\n\n[ROK3_60:ROCK3]\nHai finito con quella bottiglia?\n\n[RBM3_4:ROCK3]\n~r~Hai ucciso i Love Fist!\n\n[RBM3_6:ROCK3]\nDETONAZIONE:\n\n[RBM3_1:ROCK3]\n~g~Trasporta i Love Fist al concerto.\n\n[RBM3_2:ROCK3]\nMentre la bomba è innescata, esploderà se cercherai di lasciare la macchina...\n\n[RBM3_3:ROCK3]\nSe la barra di detonazione si riempie completamente, la bomba esploderà.\n\n[RBM3_8:ROCK3]\nPiù velocemente guidi, più lentamente si riempirà.\n\n[RBM3_7:ROCK3]\n~g~BOMBA DISINNESCATA!\n\n[ROK3_6A:ROCK3]\n~g~Love Fist. Avete finito di inquinare l'etere.\n\n[ROK3_6B:ROCK3]\n~g~Vi ho dato la possibilità di essere amici. Adesso vi darò la possibilità di morire.\n\n[ROK3_62:ROCK3]\nPer cui abbiamo pensato di mostrarti il nostro Tempio del Rock.\n\n[ROK3_63:ROCK3]\nPer percepire il furore alla Love Fist!\n\n[ROK3_64:ROCK3]\nAscolta come parli, amico. Si tratta di carta pesta e adesivo.\n\n[ROK3_65:ROCK3]\nEhi, ragazzi, questo è il tempio e noi siamo i sacerdoti.\n\n[ROK3_66:ROCK3]\nBeh, se i ragazzi amano i loro sacerdoti a pezzi e mezzi sordi,\n\n[ROK3_67:ROCK3]\nchi sono per discutere?\n\n[ROK3_68:ROCK3]\nOddio, si è rovinato nuovamente il nastro.\n\n[ROK3_69:ROCK3]\nSe andiamo avanti così, dovremo suonare dal vivo.\n\n[ROK3_70:ROCK3]\nOooh merda! La pancia...\n\n[ROK3_74:ROCK3]\nAh guarda: che cos'è? Ehi Tommy, metti su questo nastro.\n\n[ROK3_01:ROCK3]\nFinalmente, amico: è l'ora di un bel drink.\n\n[ROK3_02:ROCK3]\nIl concerto è a cento metri lungo la strada.\n\n[ROK3_05:ROCK3]\nMi rimbambisco se non agito la testa.\n\n[ROK3_07:ROCK3]\nTommy, amico, devi salvare la band!\n\n[ROK3_29:ROCK3]\nTommy, continua a guidare senza rallentare!\n\n[ROK3_31:ROCK3]\nBella: 'Qualcuno faccia qualcosa'. Ma che idiozia è questa? Ho conosciuto froci più coraggiosi.\n\n[ROK3_33:ROCK3]\nAscolta, sono un musicista. Non ho la minima idea di come disarmare una bomba.\n\n[ROK3_35:ROCK3]\nSì, mi è giunta voce che sei bravo in queste cose.\n\n[ROK3_38:ROCK3]\nUna cannuccia? Questo è il furgone da tour dei Love Fist!\n\n[ROK3_39:ROCK3]\nDove diavolo la trovo una cannuccia, amico?\n\n[ROK3_46:ROCK3]\nAvrei dovuto scaricarti quando ne ho avuto la possibilità.\n\n[ROK3_47:ROCK3]\nCapitalista.\n\n[ROK3_48:ROCK3]\nSchiavo dalla gloria.\n\n[ROK3_73:ROCK3]\nJezz sta riproducendo il nastro.\n\n[RBM3_9:ROCK3]\nSe ti fermi o guidi lentamente, la barra di detonazione aumenterà.\n\n[ROK3_50:ROCK3]\nSta zitto. Sei un idiota.\n\n[ROK3_36:ROCK3]\nEhi, ero completamente fuori di testa quella notte, e voi lo sapete!\n\n[RBM3_H:ROCK3]\nMi sto cagando addosso, amico. Voglio la mamma!\n\n[ROK3_45:ROCK3]\nLa fine imminente mi fa vedere tutto verde.\n\n[ROK3_6C:ROCK3]\n~g~Rallenta e la limousine esploderà, insieme ai vostri GROSSI CULI PELOSI!\n\n[ROK3_71:ROCK3]\nDobbiamo andare avanti con quello che abbiamo. Grazie ancora Tommy. Cioè, sai cosa intendo, ciao!\n\n[ROK3_1:ROCK3]\nAlla fine è giunta l'ora di un meritato bicchierino. Lo spettacolo si tiene a circa cento metri lungo la strada.\n\n[ROK3_2:ROCK3]\nConviene fare un giro più lungo. Ehi Tommy, cambia la stazione.\n\n[ROK3_3:ROCK3]\nSì Tommy, mi rimbambisco se non agito la testa. Ehi guarda, cos'è questo? Ehi Tommy, metti su questa cassetta.\n\n[ROK3_4:ROCK3]\nLove Fist. Avete finito di inquinare l'etere. Vi ho dato la possibilità di essere amici.\n\n[ROK3_5:ROCK3]\nAdesso vi darò la possibilità di morire. Se rallentate, la vostra limousine esploderà, insieme ai vostri GROSSI CULI PELOSI!\n\n[ROK3_6:ROCK3]\nTommy, devi salvare la band! Mi sto annoiando di tutto questo. Tieni premuto il maledetto pedale!\n\n[ROK3_7:ROCK3]\nDobbiamo trovare la bomba! Perché? Non possiamo guidare tutto il giorno? È vero, c'è un sacco di roba da bere...\n\n[ROK3_8:ROCK3]\nLa bomba non sarà nel motore? Dovremmo fermarci per prenderla! Moriremo tutti quanti! Credo che mi ubriacherò!\n\n[ROK3_9:ROCK3]\nEhi, c'è una coda da rispettare, amico! La risposta non è nel minibar! Spostati!\n\n[ROK3_10:ROCK3]\nEhi, dalla bottiglia di vodka escono un sacco di fili! Non è vodka, quella è BRODA!\n\n[ROK3_11:ROCK3]\nWAAAAAAGGGHHHH!!! Ed è predisposta per esplodere! WAAAAAAAAAAAAGGGHHHHHHHH!!!\n\n[ROK3_12:ROCK3]\nLo dicevano che l'alcol mi avrebbe fatto fuori... L'ho visto in televisione, devi tagliare uno dei fili. Quale? Non lo so, amico.\n\n[ROK3_13:ROCK3]\nNon ne ho idea. Willy, dimmi qualcosa. Suonerò il basso all'inferno.\n\n[ROK3_14:ROCK3]\nTommy, continua a guidare senza rallentare! Qualcuno faccia qualcosa. Bella!\n\n[ROK3_15:ROCK3]\n'Qualcuno faccia qualcosa'. Ma che idiozia è questa? Ho conosciuto froci più coraggiosi. OK, osso duro, fai qualcosa tu allora.\n\n[ROK3_16:ROCK3]\nAscolta, io sono un musicista. Non ho la minima idea di come disarmare una bomba. Willy, potresti succhiare la broda con una cannuccia.\n\n[ROK3_17:ROCK3]\nSì, mi è giunta voce che sei bravo in queste cose. Ehi, ero completamente fuori di testa quella notte, e voi lo sapete!\n\n[ROK3_18:ROCK3]\nPassa una cannuccia a Willy! Una cannuccia? Questo è il furgone da tour di Love Fist!\n\n[ROK3_19:ROCK3]\nDove diavolo la trovo una cannuccia, non so se mi spiego? Quale filo, Tommy? Quello verde. Non c'è un filo verde!\n\n[ROK3_20:ROCK3]\nQuesto forse è verde... Qualcuno di questi fili ti sembra verde?\n\n[ROK3_21:ROCK3]\nIh no! La fine imminente mi fa vedere tutto verde! Avrei dovuto scaricarti quando ne ho avuto la possibilità.\n\n[ROK3_22:ROCK3]\nAccecato dalla gloria. Capitalista. Ti ho tenuto con me per anni. Sta zitto. Sei un idiota.\n\n[ROK3_23:ROCK3]\nUna ragazzina isterica. Sì. Taci e taglia un filo. Quale filo? Questo qua...\n\n[ROK3_24:ROCK3]\nNO! Oddio, siamo vivi. Non siamo esplosi, amico.\n\n[ROK3_25:ROCK3]\nTommy, bel lavoro. Rock and roll, ragazzi. Non abbiamo uno spettacolo a cui andare?\n\n[ROK3_26:ROCK3]\nDel casino da fare? Fans di cui abusare? LOVE FIST!\n\n[ROK3_27:ROCK3]\nHai finito con quella bottiglia?\n\n{=================================== MISSION TABLE SERG1 ===================================}\n\n[TEX1_A:SERG1]\nVieni a metterti qui vicino a me, figliolo.\n\n[TEX1_B:SERG1]\nDiamine, mio padre diceva sempre 'A caval donato non si guarda in bocca' ed effettivamente non lo ha mai fatto.\n\n[TEX1_C:SERG1]\nVuoi un goccio di sano Kentucky?\n\n[TEX1_D:SERG1]\nNo, grazie.\n\n[TEX1_E:SERG1]\nSei uno dalla testa lucida, mi piace.\n\n[TEX1_F:SERG1]\nOra, il business dei terreni non ha niente a che fare con quello che dicono i giornali.\n\n[TEX1_G:SERG1]\nSi tratta solo di polvere! E la volontà di possederla! Mi segui, figliolo?\n\n[TEX1_H:SERG1]\nSì, certo.\n\n[TEX1_J:SERG1]\nTu mi sembri la persona giusta per convincerlo.\n\n[TEX1_K:SERG1]\nLa persuasione è il mio forte.\n\n[TEX1_L:SERG1]\nBene. Lo troverai al circolo sportivo, presso il campo da golf.\n\n[TEX1_M:SERG1]\nNon permettono di entrare con le armi, per cui le sue guardie del corpo non saranno armate.\n\n[TEX1_N:SERG1]\nVai e riempilo di santissime mazzate.\n\n[TEX1_O:SERG1]\nPrendi, ti ho iscritto al club, inoltre, credo proprio avrai bisogno di abiti più adeguati.\n\n[TEX1_2:SERG1]\n~g~Raggiungi il club di golf Leaf Links.\n\n[TEX1_0:SERG1]\n~g~Il bersaglio si sta allenando a golf: assicurati che sia la sua ultima partita.\n\n[TEX1_3:SERG1]\nChi è questo tipo? Ragazzi, occupatevene voi.\n\n[TEX1_6:SERG1]\nBel culo bimba!\n\n[TEX1_7:SERG1]\nMa sono io?\n\n[TEX1_I:SERG1]\nBene, c'è un tenace bastardo che non si decide a vendere.\n\n[TEX1_8:SERG1]\nOgni volta che entri su un cart da golf, ottieni automaticamente una mazza da golf, sempre se lo spazio per l'arma corpo a corpo è disponibile.\n\n[TEX1_9:SERG1]\nPrendilo!\n\n[TEX1_10:SERG1]\nUccidi lo psicopatico!\n\n[TEX1_1:SERG1]\n~g~Recupera degli abiti da golf presso Jocksport's.\n\n{=================================== MISSION TABLE SERG2 ===================================}\n\n[TEX_2A:SERG2]\n~g~Eccellente! Ti hanno visto!\n\n[TEX_2B:SERG2]\n~r~Pazzo! La gente deve essere TESTIMONE di un attacco da parte di un Cubano!\n\n[TEX_2C:SERG2]\n~g~Vai a recuperare dei vestiti con i colori della gang dei Cubani da Rafael's!\n\n[TEX_2D:SERG2]\n~g~Adesso metti fuori gioco il capo della gang degli Haitiani presso l'impresa di pompe funebri Romero's.\n\n[TEX2_A:SERG2]\nTommy, questo è Donald Love. Donald, questo è Tommy Vercetti,\n\n[TEX2_B:SERG2]\nl'ultimo cowboy arrivato da queste parti.\n\n[TEX2_C:SERG2]\nYeh... uh...\n\n[TEX2_D:SERG2]\nDonald, sta zitto e ascoltami, potresti imparare qualcosa.\n\n[TEX2_E:SERG2]\nAdesso, niente fa calare i prezzi dei terreni come una bella guerra tra gang rivali.\n\n[TEX2_F:SERG2]\nEccetto, forse, un disastro, come una piaga biblica o qualcosa del genere.\n\n[TEX2_G:SERG2]\nMa per il caso in questione mi sembra un po' troppo.\n\n[TEX2_H:SERG2]\nCapisci, brutto idiota quattr'occhi?\n\n[TEX2_I:SERG2]\nRecentemente è morto un capo gang degli Haitiani e, a quanto sembra, sono stati i Cubani.\n\n[TEX2_J:SERG2]\nTogliamo loro qualsiasi dubbio, allora! Vestiti da ombre Cubano\n\n[TEX2_K:SERG2]\ne vai a disturbare il funerale. Fai un bel casino e dattela a gambe.\n\n[TEX2_L:SERG2]\nHai capito, Donald?\n\n[TEX2_M:SERG2]\nQuesto dovrebbe mettere il coyote nel pollaio, vero?\n\n[TEX2_N:SERG2]\nDopodiché dovremo solo attendere e veder crollare i prezzi.\n\n[TEXEXIT:SERG2]\n~g~Vattene da Little Haiti!\n\n{=================================== MISSION TABLE SERG3 ===================================}\n\n[TEX3_A:SERG3]\nGuarda qua, figliolo. Ho un problema e sono certo tu possa darmi una mano.\n\n[TEX3_B:SERG3]\nNon sono un geometra.\n\n[TEX3_C:SERG3]\nNo, mi riferivo principalmente alle tue doti di demolitore.\n\n[TEX3_D:SERG3]\nEcco la faccenda: questo è il progetto approvato, e questo,\n\n[TEX3_E:SERG3]\nquesto è il terreno che stiamo seguendo.\n\n[TEX3_F:SERG3]\nStai cercando di dirmi che questo nuovo isolato di uffici è nel posto sbagliato.\n\n[TEX3_G:SERG3]\nCapisci al volo.\n\n[TEX3_H:SERG3]\nAdesso devo allontanarmi per un po' dalla città...\n\n[TEX3_I:SERG3]\n...e se la costruzione di quegli uffici dovesse subire un improvviso e insormontabile problema strutturale, beh, allora...\n\n[TEX3_J:SERG3]\ncome ogni civile e ragionevole individuo, ti sentiresti obbligato a intervenire\n\n[TEX3_K:SERG3]\nper favorire il ringiovanimento di un'area così importante della città?\n\n[TEX3_L:SERG3]\nDove posso ordinare altra gente come te?\n\n[TEX3_1:SERG3]\n~g~Utilizza l'elicottero radiocomandato per trasportare le bombe nelle quattro aree bersaglio dell'edificio.\n\n[TEX3_2:SERG3]\n~g~Devi posizionare una bomba su ogni bersaglio. Puoi piazzare l'esplosivo in qualsiasi ordine.\n\n[TEX3_5:SERG3]\n~g~Se fai cadere una bomba senza successo, potrai raccoglierla nuovamente e riprovare.\n\n[TEX3_7:SERG3]\n~g~Dovrai piazzare tutti gli esplosivi rimanenti in 7 minuti!\n\n[TEX3_8:SERG3]\n~g~Hai mancato il bersaglio! Raccogli la bomba e riprova!\n\n[TEX3_10:SERG3]\n~g~Fai cadere la bomba sul bersaglio.\n\n[TEX3_11:SERG3]\nBersagli rimanenti:\n\n[TEX3_17:SERG3]\n~r~Il tempo è scaduto: non sei riuscito a demolire l'edificio!\n\n[TEX3_18:SERG3]\n~r~L'elicottero radiocomandato è stato distrutto! Come farai adesso a trasportare le bombe?\n\n[TEX3_19:SERG3]\n~r~Hai fatto cadere la bomba in acqua! Hai bisogno di tutte le 4 bombe per demolire il cantiere!\n\n[TEX3_20:SERG3]\n~g~L'elicottero radiocomandato è quasi fuori portata. Torna indietro al cantiere e completa il lavoro!\n\n[TEX3_21:SERG3]\n~r~L'elicottero radiocomandato è fuori portata!\n\n[TEX3_24:SERG3]\nPremi il ~h~~k~~VEHICLE_LOOKLEFT~~w~ per ruotare l'elicottero in senso antiorario.\n\n[TEX3_25:SERG3]\nPremi il ~h~~k~~VEHICLE_LOOKLEFT~~w~ per ruotare l'elicottero in senso orario.\n\n[TEX3_27:SERG3]\n~g~Le scale centrali ti permetteranno di accedere a tutti i piani dell'edificio.\n\n[TEX3_31:SERG3]\n~r~Hai distrutto il van contenente le bombe e l'elicottero radiocomandato!\n\n[TEX3_32:SERG3]\nPuoi ~h~guardare indietro~w~ premendo ~h~simultaneamente ~k~~VEHICLE_LOOKLEFT~ e ~k~~VEHICLE_LOOKRIGHT~~w~.\n\n[TEX3_4:SERG3] { reVC update }\n~g~Per sganciare una bomba, premi il ~h~~k~~VEHICLE_FIREWEAPON~~g~.\n\n[TEX3_29:SERG3] { reVC update }\nPer sganciare una bomba, premi il ~h~~k~~VEHICLE_FIREWEAPON~~w~.\n\n[TEX3_26:SERG3]\nPremi il ~h~~k~~VEHICLE_BRAKE~~w~ per ridurre la velocità del rotore dell'elicottero in modo da farlo abbassare.\n\n[TEX3_22:SERG3]\nPremi il ~h~~k~~VEHICLE_ACCELERATE~~w~ per aumentare la velocità del rotore dell'elicottero in modo da ~h~farlo alzare.\n\n[TEX3_16:SERG3]\n~g~Raggiungi il van ~w~TOPFUN~g~ presso il cantiere edile da demolire.\n\n[TEX3_33:SERG3]\nUna volta raccolta una bomba, il radar mostrerà la pozione del bersaglio rispetto all'elicottero radiocomandato.\n\n[TEX3_34:SERG3]\nUn ~h~triangolo verso l'alto~w~ indica che il bersaglio si trova ~h~più in alto~w~ dell'elicottero.\n\n[TEX3_35:SERG3]\nUn ~h~triangolo verso il basso~w~ indica che il bersaglio si trova ~h~più in basso~w~ dell'elicottero.\n\n[TEX3_36:SERG3]\nUn ~h~quadrato~w~ indica che il bersaglio si trova alla ~h~stessa altezza~w~ dell'elicottero.\n\n[TEX3_6:SERG3]\n~g~Una volta raccolta la prima bomba, comincerà il conto alla rovescia.\n\n[TEX3_28:SERG3]\nPer ~h~raccogliere una bomba~w~, avvicinaci l'elicottero radiocomandato. L'elicottero può trasportare una sola bomba alla volta.\n\n[TEX3_30:SERG3]\nPer raccogliere una bomba, avvicinaci l'elicottero radiocomandato. L'elicottero può trasportare una sola bomba alla volta.\n\n[TEX3_12:SERG3]\n~g~Bomba posizionata! Ancora 3 bersagli! Torna indietro e recupera un'altra bomba.\n\n[TEX3_13:SERG3]\n~g~Bomba posizionata! Ancora 2 bersagli! Torna indietro e recupera un'altra bomba.\n\n[TEX3_14:SERG3]\n~g~Bomba posizionata! Ancora 1 bersaglio! Torna indietro e recupera un'altra bomba.\n\n[TEX3_15:SERG3]\n~r~Conto alla rovescia avviato! ~g~Devi posizionare le ~w~4 bombe~g~ in tempo!\n\n[TEX3_37:SERG3]\nSposta ~h~in basso la levetta analogica destra~w~ per aumentare la velocità del rotore e ~h~far salire~w~ l'elicottero.\n\n[TEX3_38:SERG3] { reVC update }\n{Sposta ~h~~k~~VEHICLE_ACCELERATE~~w~ per ridurre la velocità del rotore e ~h~far scendere~w~ l'elicottero.}\nSposta ~h~in alto la levetta analogica destra~w~ per ridurre la velocità del rotore e ~h~far scendere~w~ l'elicottero.\n\n[TEX3_39:SERG3]\n~g~Per sganciare una bomba, premi il tasto ~h~~k~~VEHICLE_HANDBRAKE~~g~.\n\n[TEX3_40:SERG3]\nPer sganciare una bomba, premi il tasto ~h~~k~~VEHICLE_HANDBRAKE~~w~.\n\n[TEX3_23:SERG3]\nPremi i tasti ~h~~k~~VEHICLE_TURRETUP~~w~ e ~h~~k~~VEHICLE_TURRETDOWN~~w~ per inclinare l'elicottero nella direzione desiderata.\n\n{=================================== MISSION TABLE TAXI1 ===================================}\n\n[FARES:TAXI1]\nCLIENTI:\n\n[TAXI1:TAXI1]\n~g~Trova un passeggero.\n\n[TSCORE2:TAXI1]\n~1~$\n\n[IN_ROW:TAXI1]\nBonus ~1~ DI SEGUITO! ~1~$\n\n[TAXI3:TAXI1]\n~r~Il passeggero è fuggito terrorizzato!\n\n[TAXI7:TAXI1]\n~r~La tua auto è distrutta, falla riparare.\n\n[TAXI4:TAXI1]\nCorsa completata!\n\n[TAXI5:TAXI1]\nBONUS VELOCITÀ!\n\n[TAXI6:TAXI1]\nMissione taxi terminata\n\n[TAXIH1:TAXI1]\nFermati vicino a un pedone evidenziato per farlo salire a bordo e portarlo a destinazione prima che scada il tempo.\n\n[FARE1:TAXI1]\n~g~Destinazione: ~w~'Club Pole Position'~g~ in Ocean Beach.\n\n[FARE3:TAXI1]\n~g~Destinazione: ~w~'Marina'~g~ in Ocean Beach.\n\n[FARE4:TAXI1]\n~g~Destinazione: ~w~'Ammu-Nation'~g~ in Ocean Beach.\n\n[FARE5:TAXI1]\n~g~Destinazione: ~w~'Hardware store'~g~ in Washington Beach.\n\n[FARE6:TAXI1]\n~g~Destinazione: ~w~'Mall North Point'~g~ in Vice Point.\n\n[MFARE1:TAXI1]\n~g~Destinazione: ~w~'Ammu-Nation'~g~ in Downtown.\n\n[MFARE2:TAXI1]\n~g~Destinazione: ~w~'il terminal'~g~ all'aeroporto internazionale Escobar.\n\n[WFARE3:TAXI1]\n~g~Destinazione: ~w~'Sunshine Autos'~g~ in Little Havana.\n\n[WFARE4:TAXI1]\n~g~Destinazione: ~w~'Taxi Kaufman'~g~ in Little Haiti.\n\n[WFARE5:TAXI1]\n~g~Destinazione: ~w~'Hardware store'~g~ in Little Havana.\n\n[WFARE6:TAXI1]\n~g~Destinazione: ~w~'Howlin Petes Bike'~g~ in Downtown.\n\n[FARE7:TAXI1]\n~g~Destinazione: ~w~'il negozio dei gioiellieri'~g~ in Vice Point.\n\n[FARE8:TAXI1]\n~g~Destinazione: ~w~'la spiaggia'~g~ in Ocean Beach.\n\n[FARE9:TAXI1]\n~g~Destinazione: ~w~'la spiaggia'~g~ in Washington Beach.\n\n[FARE10:TAXI1]\n~g~Destinazione: ~w~'la spiaggia'~g~ in Vice Point.\n\n[FARE11:TAXI1]\n~g~Destinazione: ~w~'l'ospedale'~g~ in Ocean Beach.\n\n[FARE12:TAXI1]\n~g~Destinazione: ~w~'l'ospedale'~g~ in Vice Point.\n\n[FARE13:TAXI1]\n~g~Destinazione: ~w~'la stazione di polizia'~g~ in Washington Beach.\n\n[FARE14:TAXI1]\n~g~Destinazione: ~w~'la stazione di polizia'~g~ in Vice Point.\n\n[FARE15:TAXI1]\n~g~Destinazione: ~w~'il ristorante della pizza'~g~ in Vice Point.\n\n[WFARE7:TAXI1]\n~g~Destinazione: ~w~'la stazione di polizia'~g~ in Little Havana.\n\n[WFARE8:TAXI1]\n~g~Destinazione: ~w~'la stazione di polizia'~g~ in Downtown.\n\n[WFARE9:TAXI1]\n~g~Destinazione: ~w~'l'ospedale'~g~ in Downtown.\n\n[WFARE10:TAXI1]\n~g~Destinazione: ~w~'l'ospedale'~g~ in Little Havana.\n\n[WFARE11:TAXI1]\n~g~Destinazione: ~w~'lo stadio'~g~ in Downtown.\n\n[WFARE12:TAXI1]\n~g~Destinazione: ~w~'il ristorante della pizza'~g~ in Little Haiti.\n\n[WFARE13:TAXI1]\n~g~Destinazione: ~w~'il ristorante della pizza'~g~ in Downtown.\n\n[WFARE14:TAXI1]\n~g~Destinazione: ~w~'i bacini'~g~ in Viceport.\n\n[WFARE15:TAXI1]\n~g~Destinazione: ~w~'la farmacia'~g~ in Little Haiti.\n\n[FARE2:TAXI1]\n~g~Destinazione: ~w~'Club Malibu'~g~ in Vice Point.\n\n{=================================== MISSION TABLE TAXICUT ===================================}\n\n[TAXC_A:TAXICUT]\nImmagino tu sia il nuovo proprietario.\n\n[TAXC_B:TAXICUT]\nDi chi fai parte? Mafia? Cartello? Non sembri Messicano...\n\n[TAXC_C:TAXICUT]\nComunque, immagino ora comincerai con la vecchia frase 'le cose stanno per cambiare da queste parti',\n\n[TAXC_D:TAXICUT]\nmagari minaccerai uno degli autisti...\n\n[TAXC_E:TAXICUT]\nvacci piano con quello là, Ted, ha appena avuto un'ernia al disco.\n\n[TAXC_F:TAXICUT]\nBeh, sì. Le cose stanno per cambiare da queste parti, signora.\n\n[TAXC_G:TAXICUT]\nChe felicità, figliolo. Me ne occupo io...\n\n[TAXC_H:TAXICUT]\nOrmai lo faccio da anni.\n\n[TAXC_I:TAXICUT]\nAttenzione a tutti:\n\n[TAXC_J:TAXICUT]\nè cambiata la gestione e le cose stanno nuovamente per cambiare da queste parti.\n\n[TAXC_K:TAXICUT]\nIl nostro nuovo direttore, della...\n\n[TAXC_L:TAXICUT]\nDi quale gang fai parte?\n\n[TAXC_M:TAXICUT]\nBeh, non faccio parte di nessuna gang.\n\n[TAXC_N:TAXICUT]\nAllora qual è il tuo maledetto nome, ragazzo?\n\n[TAXC_O:TAXICUT]\nVercetti, Tommy Vercetti.\n\n[TAXC_P:TAXICUT]\nIn nostro nuovo direttore, della Vercetti Gang,\n\n[TAXC_Q:TAXICUT]\nsi assicurerà che non ci succedano incidenti.\n\n[TAXC_R:TAXICUT]\nCapisce? Fine!\n\n[TAXC_S:TAXICUT]\nTi è piaciuto il 'Capisce'? A me è piaciuto il 'Capisce'.\n\n[TAXC_T:TAXICUT]\nAllora è così che ha funzionato nel passato:\n\n[TAXC_U:TAXICUT]\nnoi portiamo avanti l'azienda come sempre.\n\n[TAXC_V:TAXICUT]\nSe abbiamo problemi con la concorrenza, tu ti occupi di riempirli di botte.\n\n[TAXC_W:TAXICUT]\nPoi loro ci riempiono di botte,\n\n[TAXC_X:TAXICUT]\npoi tu riempi loro di botte nuovamente,\n\n[TAXC_Y:TAXICUT]\neccetera, eccetera. Tutto chiaro?\n\n[TAXC_Z:TAXICUT]\nUh, sì, almeno credo...\n\n[TAXC_A1:TAXICUT]\nPrendi un taxi dal garage se ti senti di lanciarti subito nella mischia.\n\n{=================================== MISSION TABLE TAXIWA1 ===================================}\n\n[OUTTIME:TAXIWA1]\n~r~Troppo lento, troppo lento!\n\n[TAX1_1:TAXIWA1]\nOK, abbiamo un cliente danaroso che richiede un taxi da Starfish Island: qualche volontario?\n\n[TAX1_2:TAXIWA1]\nQui Tommy, lo prendo io!\n\n[TAX1_3:TAXIWA1]\nQuesto cliente è mio, indietro!\n\n[TAX1_4:TAXIWA1]\nForza, forza, entra in fretta!\n\n[TAX1_5:TAXIWA1]\nOK, OK! Ti prego, non farmi male!\n\n[TAXW1_1:TAXIWA1]\n~g~Passa a prendere il VIP su Starfish Island.\n\n[TAXW1_2:TAXIWA1]\n~g~Porta indietro il VIP! Metti fuori gioco l'altra macchina!\n\n[TAXW1_3:TAXIWA1]\n~r~Il VIP è morto!\n\n[TAXW1_4:TAXIWA1]\n~r~Il VIP è arrivato a destinazione!\n\n[TAXW1_6:TAXIWA1]\n~g~Porta il VIP all'aeroporto!\n\n{=================================== MISSION TABLE TAXIWA2 ===================================}\n\n[TAX2_1:TAXIWA2]\nChiamata a tutti i veicoli: stiamo perdendo clienti in tutta la città. Che cosa sta succedendo?\n\n[TAX2_2:TAXIWA2]\nI taxi VC continuano a batterci sul tempo. Sono in troppi, non possiamo competere!\n\n[TAX2_3:TAXIWA2]\nMr. Vercetti, se sei in ascolto, devi mettere fuori gioco un po' dei taxi VC, se no falliamo!\n\n[TAXW2_1:TAXIWA2]\n~g~Distruggi 3 taxi rivali!\n\n{=================================== MISSION TABLE TAXIWA3 ===================================}\n\n[TAX3_1:TAXIWA3]\nTaxi 13, la signorina Cortez ha bisogno di essere prelevata da Down Town e ha richiesto esplicitamente di te.\n\n[TAX3_2:TAXIWA3]\nOK, ricevuto. Taxi 13 chiudo.\n\n[TAX3_3:TAXIWA3]\nHmmm, nessun segno di Mercedes...\n\n[TAXW3_3:TAXIWA3]\n~g~Metti fuori combattimento il capo dei taxisti!\n\n[TAXW3_2:TAXIWA3]\n~g~Resta vivo fino allo scadere del tempo.\n\n[TAX_AS1:TAXIWA3]\nBENI COMPAGNIA DEI TAXI ACQUISITI\n\n[TAX_AS2:TAXIWA3]\nLa compagnia dei taxi d'ora in poi genererà introiti per un massimo di ~1~$. Ricordati di recuperarli regolarmente.\n\n[TAX3_4:TAXIWA3]\nÈ giunta l'ora che l'angelo custode dei Taxi Kaufman entri in azione!\n\n[TAX3_5:TAXIWA3]\nEhi ragazzo, ti abbronzo il fondoschiena!\n\n{ re3 updates }\n{ new languages }\n[FEL_JAP]\nGIAPPONESE\n\n[FEL_POL]\nPOLACCO\n\n[FEL_RUS]\nRUSSO\n\n{ new display menus }\n[FET_GFX]\nGRAPHICS SETUP\n\n[FED_MIP]\nMIP MAPPING\n\n[FED_AAS]\nANTI ALIASING\n\n[FED_FIL]\nTEXTURE FILTERING\n\n[FED_BIL]\nBILINEAR\n\n[FED_TRL]\nTRILINEAR\n\n[FED_WND]\nWINDOWED\n\n[FED_FLS]\nFULLSCREEN\n\n[FEM_CSB]\nCUTSCENE BORDERS\n\n[FEM_SCF]\nSCREEN FORMAT\n\n[FEM_ISL]\nMAP MEMORY USAGE\n\n[FEM_LOW]\nLOW\n\n[FEM_MED]\nMEDIUM\n\n[FEM_HIG]\nHIGH\n\n[FEM_2PR]\nPS2 ALPHA TEST\n\n[FEC_FRC]\nFREE CAM\n\n{ Linux joy detection }\n[FEC_JOD]\nDETECT JOYSTICK\n\n[FEC_JPR]\nPress any key on the joystick of your choice that you want to use on the game, and it will be selected.\n\n[FEC_JDE]\nDetected joystick\n\n{ mission restart }\n[FET_RMS]\nRIGIOCA MISSIONE\n\n[FESZ_RM]\nRIGIOCA?\n\n[FED_VPL]\nVEHICLE PIPELINE\n\n[FED_PRM]\nPED RIM LIGHT\n\n[FED_RGL]\nROAD GLOSS\n\n[FED_CLF]\nCOLOUR FILTER\n\n[FED_WLM]\nWORLD LIGHTMAPS\n\n[FED_MBL]\nMOTION BLUR\n\n[FEM_SIM]\nSIMPLE\n\n[FEM_NRM]\nNORMAL\n\n[FEM_MOB]\nMOBILE\n\n[FED_MFX]\nMATFX\n\n[FED_NEO]\nNEO\n\n[FEM_PS2]\nPS2\n\n[FEM_XBX]\nXBOX\n\n[FEC_IVP]\nINVERT PAD VERTICALLY\n\n[FEM_NON]\nNONE\n\n[FEC_DS2]\nDUALSHOCK 2\n\n[FEC_DS3]\nDUALSHOCK 3\n\n[FEC_DS4]\nDUALSHOCK 4\n\n[FEC_360]\nXBOX 360 CONTROLLER\n\n[FEC_ONE]\nXBOX ONE CONTROLLER\n\n[FEC_TYP]\nGAMEPAD TYPE\n\n[FET_AGS]\nGAMEPAD SETTINGS\n\n[FEM_AUT] { aspect ratio related }\nAUTO\n\n[DUMMY]\nTHIS LABEL NEEDS TO BE HERE !!!\nAS THE LAST LABEL DOES NOT GET COMPILED"
  },
  {
    "path": "utils/gxt/spanish.txt",
    "content": "﻿{\n    New strings are at the bottom of file.\n    Do not change the order of strings.\n    You can fix the typos of existing translation but please refrain from\n    unnecessary edits like rephasing because you think it suits better for your taste.\n\n    SPANISH NOTE:\n    This is European Spanish, do not mix it with Latin American Spanish.\n    If you want the Latin American Spanish translation you'd have to create\n    a separate txt for it.\n}\n\n{ Grand Theft Auto Vice City Spanish (Spain) Translation }\n{ Contains some of the official fixes made by Rockstar for the iOS port }\n{ Additional translation rewrites, corrections and fixes by IlDucci }\n[IN_VEH]\n~g~¡Eh! ¡Vuelve al vehículo!\n\n[HEY]\n~g~¡No vayas solo, mantén tu grupo unido!\n\n[HELP3]\nSolo puedes esprintar durante cortos periodos de tiempo, antes de cansarte.\n\n[HELP4_D]\nMueve el ~h~joystick analógico derecho~w~ hacia arriba para ~h~acelerar.\n\n[HELP5_D]\nTira del ~h~joystick analógico derecho~w~ hacia atrás para ~h~frenar~w~, o para ~h~dar marcha atrás~w~ si el vehículo se ha detenido.\n\n[HELP7_A]\nPulsa y mantén pulsado el ~h~~k~~PED_LOCK_TARGET~ ~w~para ~h~apuntar~w~ con el rifle de francotirador.\n\n[HELP7_D]\nPulsa y mantén pulsado el ~h~~k~~PED_LOCK_TARGET~ ~w~para ~h~apuntar~w~ con el rifle de francotirador.\n\n[HELP10]\nEsta insignia indica que tienes un nivel de se busca por la policía.\n\n[HELP11]\nCuantas más insignias tengas, mayor es tu nivel de se busca.\n\n[HELP13]\nAlgunas veces puedes necesitar ir por caminos que el radar no detecta.\n\n[TIMER]\nÉsta es una misión cronometrada, debes completarla antes de que el cronómetro llegue a cero.\n\n[HORN]\n~g~Toca la bocina.\n\n[NOMONEY]\n~g~¡Necesitas más dinero!\n\n[REWARD]\nRECOMPENSA ~1~ $\n\n[M_FAIL]\n¡MISIÓN FALLIDA!\n\n[M_PASS]\n¡MISIÓN SUPERADA! ~1~ $\n\n[DEAD]\n¡ELIMINADO!\n\n[BUSTED]\n¡ARRESTADO!\n\n[WEATHE1]\nFORZAR TIEMPO SOLEADO\n\n[WEATHE2]\nFORZAR TIEMPO EXTREMADAMENTE SOLEADO\n\n[WEATHE3]\nFORZAR TIEMPO NUBLADO\n\n[WEATHE4]\nFORZAR TIEMPO LLUVIOSO\n\n[WEATHE5]\nFORZAR TIEMPO CON NIEBLA\n\n[WEATHE6]\nTIEMPO NORMAL\n\n[NUMBER]\n~1~\n\n[LOADCAR]\nCARGANDO VEHÍCULO... (PULSA L1 PARA CANCELAR)\n\n[CARSOFF]\nCoches desactivados.\n\n[CARS_ON]\nCoches activados.\n\n[TEXTXYZ]\nEscribiendo coordenadas en el archivo...\n\n[CHEATON]\nModo trucos ACTIVADO\n\n[CHEATOF]\nModo trucos DESACTIVADO\n\n[IMPORT1]\nVe fuera y espera tu vehículo.\n\n[PAGEB11]\nEntregado lanzallamas en el escondite\n\n[WANT_A]\nSólo serás arrestado si tienes un ~h~nivel de se busca.\n\n[WANT_B]\nTu ~h~nivel de se busca~w~ viene representado por la fila de estrellas en la parte superior derecha de la pantalla.\n\n[WANT_C]\nAhora tienes un ~h~nivel de se busca~w~ de una...\n\n[WANT_D]\ndos...\n\n[WANT_E]\ntres...\n\n[WANT_F]\nA medida que tu ~h~nivel de se busca~w~ aumente, atraerás a representantes más poderosos de las fuerzas policiales.\n\n[WANT_G]\nCuando te hayan ~h~''arrestado''~w~ serás conducido a la comisaría más cercana.\n\n[WANT_H]\nLos polis te quitarán todas las armas y parte de tu dinero como soborno.\n\n[WANT_I]\nCualquier misión en la que estuvieses habrá fracasado.\n\n[WANT_J]\nEncontrarás modos de reducir tu nivel de se busca cuanto más juegues.\n\n[WANT_K]\nSi estás en un coche, el ~h~TALLER DE PINTURA~w~ limpiará ~h~tu nivel de búsqueda.\n\n[HEAL_B]\nCuando seas ~h~''eliminado''~w~ serás conducido al hospital más cercano.\n\n[HEAL_C]\nPerderás tus armas y los médicos te quitarán algo de dinero por recomponerte.\n\n[HEAL_E]\nEncontrarás modos de curarte o de protegerte cuanto más juegues al juego.\n\n[BRIBE1]\nAcabas de recoger un soborno de la policía, esto disminuirá en una estrella tu nivel de se busca.\n\n[SAVE1]\nEntra al corona para ~h~guardar la partida~w~. No puedes guardar durante una misión.\n\n[SAVE2]\nCualquier vehículo que quede en este garaje será almacenado cuando se guarde la partida.\n\n[AMMU]\nVe dentro de Ammu-Nation para comprar un arma.\n\n[R_TIME]\nTIEMPO DE CARRERA:\n\n[PROP_1]\nNo tienes suficiente dinero para adquirir esta propiedad\n\n[PROP_2]\nNo puedes comprar propiedades mientras estás en una misión.\n\n[IND_ZON]\nVice City Beach\n\n[COM_ZON]\nPenínsula de Vice City\n\n[BEACH1]\nOcean Beach\n\n[BEACH2]\nWashington Beach\n\n[BEACH3]\nVice Point\n\n[GOLFC]\nLeaf Links\n\n[STARI]\nStarfish Island\n\n[DOCKS]\nViceport\n\n[HAVANA]\nLittle Havana\n\n[HAITI]\nLittle Haiti\n\n[PORNI]\nPrawn Island\n\n[DTOWN]\nCentro de la ciudad\n\n[VICE_C]\nVice City\n\n[A_PORT]\nEscobar International\n\n[JUNKY]\nVertedero\n\n[PISTOL]\nPistola\n\n[PYTHON]\n.357\n\n[UZI]\nUz-1\n\n[TEC9]\nTec 9\n\n[M4]\nM4\n\n[INGRAM]\nMac\n\n[MP5]\nMP\n\n[RUGER]\nKruger\n\n[SNIPE]\nRifle de francotirador\n\n[GRENADE]\nGranadas\n\n[SHOTGN1]\nEscopeta\n\n[SHOTGN2]\nS.P.A.S. 12\n\n[SHOTGN3]\nEscopeta de cañones recortados\n\n[ARMOUR]\nChaleco antibalas\n\n[LASER]\n.308 Rifle de francotirador\n\n[BASEBAT]\nBate de béisbol\n\n[HAMMER]\nMartillo\n\n[SCREWD]\nDestornillador\n\n[CLEVER]\nCuchillo de carnicero\n\n[MACHETE]\nMachete\n\n[KNIFE]\nCuchillo\n\n[KATANA]\nKatana\n\n[CHAINSA]\nSierra eléctrica\n\n[G_COST]\n~1~ $\n\n[CAR_1]\nAmbulancia\n\n[MALIBU]\nEl Club Malibú\n\n[MANSION]\nMansión de Díaz\n\n[TMANS]\nFinca de Vercetti\n\n[STRIP]\nEl Club Pole Position\n\n[MALL1]\nCentro comercial North Point\n\n[BANKINT]\nEl Banco Corrupto Grande\n\n[RANGE]\nCampo de tiro con rifle\n\n[POL_HQ]\nCuartel general de VCPD\n\n[INT_B]\nUn viejo amigo\n\n[INTB_1]\n~g~Ve a la oficina del Abogado.\n\n[LAW_1]\nLa fiesta\n\n[LAW_2]\nPelea en el callejón trasero\n\n[LAW_3]\nFuria en el jurado\n\n[LAW_4]\nDisturbios\n\n[COL_1]\nCerdo traidor\n\n[COL_2]\nTiros en el centro comercial\n\n[COL_3]\nÁngeles guardianes\n\n[COL_4]\n¡Señor, sí, señor!\n\n[COL_5]\n¡Todos con las manos arriba!\n\n[COK_1]\nLa caza\n\n[COK_2]\nPhnom Penh '86\n\n[COK_3]\nEl barco más rápido\n\n[COK_4]\nOferta y demanda\n\n[KENT_1]\nEl corredor de la muerte\n\n[ASS_1]\nBorrar\n\n[BUD_1]\nExtorsión\n\n[BUD_2]\nPelea en el bar\n\n[BUD_3]\nTierra de polis\n\n[CAP_1]\nLiquida al cobrador\n\n[FIN_1]\nMantén cerca a tus amigos...\n\n[BANK_1]\n¿Sin escapatoria?\n\n[BANK_2]\nEl tirador\n\n[BANK_3]\nEl conductor\n\n[BANK_4]\nEl atraco\n\n[CNT_1]\nDescubriendo el pastel\n\n[CNT_2]\nAtaca al mensajero\n\n[PORN_1]\nCampaña de reclutamiento\n\n[PORN_2]\nConsolador Dodo\n\n[PORN_3]\nLa foto policial de Marta\n\n[PORN_4]\nPunto G\n\n[TAX_1]\nTaxis Kaufman\n\n[TAXI_1]\nV.I.P.\n\n[TAXI_2]\nRivalidad amistosa\n\n[TAXI_3]\nTaxigedón\n\n[ICE_1]\nDistribución\n\n[TEX_1]\nHierro número cuatro\n\n[TEX_2]\nDos leves impactos\n\n[TEX_3]\nDemoledor\n\n[PHIL_1]\nTraficante de armas\n\n[PHIL_2]\nBoomshine Saigon\n\n[BIKE_1]\nMoto con llantas de aleación\n\n[BIKE_2]\nIncitando al macho\n\n[BIKE_3]\nMoto robada\n\n[ROCK_1]\nLove Juice\n\n[ROCK_2]\nAsesino psicópata\n\n[ROCK_3]\nGira publicitaria\n\n[ROCK_4]\n¡Love Fist!\n\n[HAT_1]\nPoción mágica\n\n[HAT_2]\n¡Bombas fuera!\n\n[HAT_3]\nJuego sucio\n\n[CUB_1]\nEl desafío del barco trucado\n\n[CUB_2]\nCarne de cañón\n\n[CUB_3]\nEncuentro naval\n\n[CUB_4]\nVudú troyano\n\n[JOB_1]\nMuerte en la carretera\n\n[JOB_2]\nElimina a la esposa\n\n[JOB_3]\nAutocidio\n\n[JOB_4]\nComprobar el registro\n\n[JOB_5]\nCabos sueltos\n\n[ANSWER]\nPulsa ~h~~k~~PED_ANSWER_PHONE~~w~ para responder a una llamada a tu teléfono móvil.\n\n[MOB_01A]\n¡Estás bien figura! Soy Paul. Puede que tenga algún resultado para ti, pero necesito hablar contigo cara a cara.\n\n[MOB_01B]\nEstoy de relax en el Malibu.\n\n[MOB_01C]\nCreo que después de esto me vas a deber un favor o dos, guapo. Hasta luego.\n\n[MOB_02A]\nSsssnniiiiffffff... ¡Eh! Hola, ¿Tommy? ¡Tommy!\n\n[MOB_02B]\nTenemos un problema en la imprenta. Mejor que vayas y lo compruebes.\n\n[MOB_02C]\nAlgún tipo de lío. Las cosas andan revueltas. Tengo que irme.\n\n[MOB_03A]\n¿Sr. Vercetti? Tengo un trozo de mierda firmada que dice\n\n[MOB_03B]\nque usted ha asumido todas las deudas de BJ's Auto.\n\n[MOB_03C]\nCon la repentina desaparición de BJ no tengo más remedio\n\n[MOB_03D]\nque hacerle responsable de su inestabilidad financiera\n\n[MOB_03E]\nHasta que esta cuenta quede completamente saldada\n\n[MOB_03F]\ndebería considerar que las calles de Vice City son poco seguras.\n\n[MOB_04A]\n¿Cómo estás, tío? Soy Paulo.\n\n[MOB_04B]\nMira, Tommy, me olvidé de mencionar que vamos a necesitar más seguridad para el concierto.\n\n[MOB_04C]\nHay una banda de moteros liderada por Mitch Baker que serían la publicidad ideal.\n\n[MOB_04D]\nSolucióname esto y te conseguiré un pase para la actuación, ¿vale?\n\n[MOB_05A]\nSoy Mitch. Hiciste un buen trabajo, Tommy. Es bueno volver a tener a mi pequeña en casa.\n\n[MOB_05B]\nDile al Sr. Kent Paul que dispondrá de seguridad para la actuación.\n\n[MOB_05C]\nTiene mi palabra de ello.\n\n[MOB_05D]\nIntenta no meterte en problemas.\n\n[MOB_06A]\nTommy, esos de abajo han estado rajando sobre ti, chico.\n\n[MOB_06B]\nPensé que podrías necesitar consuelo casero así que la tía Poulet te preparará una sopa, ¿hmmm?\n\n[MOB_06C]\nPásate por mi cocina alguna vez, ¿de acuerdo Tommy?\n\n[MOB_08A]\nEh Tommy, pensé que podrías necesitar algún asesoramiento financiero.\n\n[MOB_08B]\nUna vez que tengas la operación en marcha, tendrás que pasarte a recoger la recaudación de la semana.\n\n[MOB_08C]\nDeja que esos tipos crean que son los amos del lugar e intentarán cepillarse los beneficios... ¿vale?\n\n[MOB_08D]\nEh, sé como llevar el negocio, Ken.\n\n[MOB_08E]\nVale, vale. Lo sé, ya sabes. Lo sé. Estaba,\n\n[MOB_08F]\nSólo estaba, ya sabes, diciéndote que sé, que tú sabes que yo lo sé.\n\n[MOB_08G]\n¡Solo manteniéndolo a punto, nene!\n\n[MOB_08H]\nLo que sea, Ken, lo que sea...\n\n[MOB_09A]\n¡Eh, Leo! ¡Tengo trabajo para ti!\n\n[MOB_09B]\nNo soy Leo.\n\n[MOB_09C]\n¡Eh, como Leo sepa que tienes su teléfono, te va a liquidar!\n\n[MOB_09D]\nQuizás Leo ya esté muerto. Quizás yo le maté y cogí su teléfono, ¿te has parado a pensar eso, gilipollas?\n\n[MOB_09E]\n¿Mataste a Leo? Debes tener unas pelotas muy grandes... ¿quieres trabajar para mí?\n\n[MOB_09F]\nPásate por el café de mi padre en Little Havana y podremos hablar de tú a tú.\n\n[MOB_10A]\n¡Tommy! Mira, tengo que pedirte un favor.\n\n[MOB_10B]\n¡Steve! ¿Cómo van con el rodaje?\n\n[MOB_10C]\nBien, bien. Yo, je, NOSOTROS necesitamos una escena con una persecución de coches, pero nuestro presupuesto no da para más.\n\n[MOB_10D]\nMe han dejado un coche en la ciudad. Tú sabrás qué hacer.\n\n[MOB_10E]\nDe acuerdo, Steve, estaré al tanto. Te veo luego.\n\n[MOB_11A]\n¿Qué hay, hijo? Pensé sólo en llamarte para darte algún consejo.\n\n[MOB_11B]\nHola, Avery. ¿Qué te preocupa?\n\n[MOB_11C]\nHay muchas oportunidades en esta ciudad si dispones de las propiedades adecuadas, ¿entiendes lo que quiero decir?\n\n[MOB_11D]\nCreo que sí...\n\n[MOB_11E]\nLo que digo es que mantengas los ojos abiertos y podrás encontrar la oportunidad de negocio perfecta. Te veré luego.\n\n[MOB_11F]\nNos vemos, Avery.\n\n[MOB12_A]\n¡Eh, Tommy, soy Avery! Ahora escucha, estoy muy liado en este momento\n\n[MOB12_B]\ny uno de mis representantes necesita carabina para ir a Gator Keys.\n\n[MOB12_C]\nEstoy detrás de unas tierras por allí, así que voy a enviar alguien a que ablande el trato.\n\n[MOB12_D]\nPodrías hacerme un favor y asegurarte de que llega allí, ¿entendido?\n\n[MOB12_E]\nSí, eso está hecho, Avery. ¿Dónde te gustaría que le recogiese?\n\n[MOB12_F]\nEstá terminando algunos negocios en la obra. Le dije que le recogerías allí.\n\n[MOB12_G]\nNingún problema. Nos vemos, Avery.\n\n[MOB13_A]\n¿Vercetti? ¡VERCETTI! ¡Maldito seas, tío, tienes que ayudarme!\n\n[MOB13_B]\n¿Sr. Moffat? ¿Cómo le va la vida en familia?\n\n[MOB13_C]\nMaldito seas, DEMONIOS, ¿me oyes?\n\n[MOB13_D]\nBueno, fue agradable charlar...\n\n[MOB13_E]\n¡ESPERA! Espera, Vercetti Tommy, ¿Puedo llamarte Tommy?\n\n[MOB13_F]\nLos dos somos hombres de negocios, ¿verdad? Reconoces un buen negocio cuando lo ves.\n\n[MOB13_G]\nNo tengo tiempo para charlar, vaya al grano.\n\n[MOB13_H]\nDINERO. El dinero es el maldito asunto.\n\n[MOB13_I]\nMe escapado de la trena otra vez, pero nunca tardan mucho en encontrarme... ¡creen que es un maldito juego!\n\n[MOB13_J]\nEstoy en un teléfono público en alguna parte de este agujero de mierda olvidado de la mano de Dios.\n\n[MOB13_K]\nSácame de aquí antes de que me lleven de vuelta y... oh... Dios...\n\n[MOB13_L]\nBueno, estoy ocupado durante las próximas...\n\n[MOB13_M]\n¡No! ¡No me jodas, ten piedad! Ningún hombre debería tener que hacer esas, esas cosas.\n\n[MOB13_N]\nEstoy de rodillas, Tommy, en el fango, rogándote, por favor...\n\n[MOB13_O]\nSupongo que podría desviarme hacia allí, veré si puedo localizarte...\n\n[MOB13_P]\nOh, Dios, ya vienen. Por el amor de Dios, date prisa, ¡date prisa!\n\n[MOB_14A]\nHola, Tommy, me vas a adorar, amigo.\n\n[MOB_14B]\nUn pajarito me ha dicho que la división SWAT de Vice City tiene un depósito en una entidad bancaria ciertamente grande,\n\n[MOB_14C]\ndonde guardan todos los sobornos que han recibido durante estos años,\n\n[MOB_14D]\n¡como una especie de fondo de retiro para los veteranos!\n\n[MOB_14E]\nPor supuesto, si esta información te ayudase a adquirir parte de ese dinero,\n\n[MOB_14F]\n¿Supongo que te sentirías obligado a mandarme algo?\n\n[MOB_14G]\nLo tendré en mente, gracias Kent.\n\n[MOB_14H]\nEs Paul. Soy de Kent, cerca de Londres, idiota.\n\n[MOB_14I]\nMi conocimiento de la geografía provincial inglesa ya no es lo que era.\n\n[MOB15_A]\nTommy, colega, soy Paul, de Kent,\n\n[MOB15_B]\nun par de titis han escrito tu nombre por todas partes, en el Malibú.\n\n[MOB15_C]\n¿De qué estás hablando?\n\n[MOB15_D]\nTías. Palomitas. Ya sabes. Chicas. De las buenas, no creas que son furcias ni nada por el estilo.\n\n[MOB15_E]\nTienes que venir a echarles un vistazo.\n\n[MOB16_A]\nTommy, aquí Paulo, ¿qué pasa amigo?\n\n[MOB16_B]\n¿Qué quieres Paul? No quiero ropa de imitación.\n\n[MOB16_C]\nMuy divertido, colega, pero yo no toco la ropa falsificada.\n\n[MOB16_D]\nNada, sólo llamaba para ver si consigo un papel en una de tus películas,\n\n[MOB16_E]\nen Inglaterra hice un montón de porno, colega.\n\n[MOB16_F]\nGuardo más fuego que tu, hijo mío.\n\n[MOB16_G]\nPaul, gracias por la oferta, lo tendré en mente.\n\n[MOB16_H]\nEn serio, no te olvides de mí, después de todo lo que he hecho por ti.\n\n[MOB16_I]\nEso es lo que estoy intentando olvidar.\n\n[MOB19_A]\nTommy V, aquí KP. Kent Paul. En las calles se dice que hay gente que te quiere despellejar.\n\n[MOB19_B]\nMantén los ojos abiertos. Y recuerda, yo no te he dicho nada de esto.\n\n[MOB_20A]\nDe acuerdo, Tommy, soy Paul. Me ha dicho un pajarito que has sido un chico muy malo.\n\n[MOB_20B]\nA alguien le ha ofendido que de repente estés actuando como si fueses el mandamás, dándote aires de grandeza.\n\n[MOB_20C]\nBueno, no digas que nunca te advertí. Presumir es un juego de tontos, hijo.\n\n[MOB_20D]\nEn cualquier caso, oí que se ha puesto un precio a tu cabeza y que alguien te la va a partir,\n\n[MOB_20E]\nasí que ten cuidado, y acuérdate de mí, colega.\n\n[MOB21_A]\nTommy, Thomas, soy Cortez. ¿Qué pasa?\n\n[MOB21_B]\nLas cosas van bien. ¿Cómo estás?\n\n[MOB21_G]\nDe todos modos, Tommy, quisiera preguntarte algo sobre Mercedes.\n\n[MOB21_H]\n¿Sí? ¿Qué pasa con ella?\n\n[MOB21_I]\nOh Tommy, Tommy, oigo todas esas historias y no sé qué pensar.\n\n[MOB21_K]\nQuizás ella piense que puede hacer lo que quiera ahora que pero dime, Tommy, ¿es verdad?\n\n[MOB21_M]\n¿El qué es verdad?\n\n[MOB21_N]\nLas historias que he oído. ¿De verdad va a ser abogada?\n\n[MOB21_O]\nOh Tommy, la vergüenza. Los Cortez somos una familia orgullosa\n\n[MOB21_P]\ny nunca permitiríamos que una hija nuestra se convirtiese en abogada. Por favor, dime que no es así. No creo que pudiese soportarlo.\n\n[MOB21_Q]\nCoronel, puedo asegurarle que Mercedes nunca será abogada. No tema.\n\n[MOB21_R]\nGracias, Tommy, gracias. La vergüenza sería insoportable.\n\n[MOB21_S]\nLo sé, coronel.\n\n[MOB21_T]\nBueno, Tommy, debes perdonarme, ha llegado el nuevo ministro de interior.\n\n[MOB21_U]\nHace muchos años, yo maté a su padre en un golpe fallido así que debo ser cortés. Buenos días, amigo.\n\n[MOB21_C]\nTommy, aquí siempre es una lucha. Siento el ruido, acabamos de tener otro golpe fallido.\n\n[MOB21_D]\nLa gente es la señora más exigente de todas.\n\n[MOB21_E]\nDesde que he vuelto de Vice City y hasta ahora, hemos tenido tres revoluciones y cuatro golpes.\n\n[MOB21_F]\nAfortunadamente, me han ascendido cada vez.\n\n[MOB21_J]\nQuizás todo el mundo me está humillando.\n\n[MOB21_L]\npero dime, Tommy, ¿es verdad?\n\n[MOB22_A]\nTommy, estás demostrando ser muy útil, amigo mío.\n\n[MOB22_B]\nGracias, Cortez. ¿Qué hay de mi asunto?\n\n[MOB22_C]\nTommy, estoy trabajando infatigablemente en tu nombre para conseguir llegar al fondo de esta zanja de apestosas mentiras y engaños,\n\n[MOB22_D]\ntienes mi palabra al respecto, pero mientras tanto,\n\n[MOB22_E]\npor favor, acepta el estimable agradecimiento de mi gente por tu trabajo para nosotros.\n\n[MOB_25A]\nTommy, soy Cortez. Los franceses me están causando todo tipo de problemas.\n\n[MOB_25B]\nMalditos hipócritas. ¡Se pasan cien años robando a países pobres y me llaman ladrón a mí!\n\n[MOB_25C]\nVoy a necesitar tu ayuda tan pronto como sea posible.\n\n[MOB_25D]\nPor favor, Tommy, date prisa, te necesito, ¿de acuerdo? Odio a esos malditos franceses.\n\n[MOB_26A]\nHola, ¿Tommy?\n\n[MOB_26B]\n¿Sí?\n\n[MOB_26C]\nSoy Baker. Sólo quería decirte que verdaderamente disfruté con el espectáculo.\n\n[MOB_26D]\nLos chicos y yo queremos darte las gracias, y recordarte,\n\n[MOB_26E]\nque te tienes nuestro respeto. Buenos días. Sigue cabalgando duro, chico.\n\n[MOB_29A]\nHola, ¿hablo con el Sr. Tommy Vercetti?\n\n[MOB_29B]\nSí.\n\n[MOB_29C]\nBueno, he oído por radio macuto que usted es el hombre que hay que buscar cuando alguien tiene una plaga de bichos.\n\n[MOB_29D]\nPuede...\n\n[MOB_29E]\nBueno, yo tengo una plaga de bichos de verdad. Haitianos, por todas partes.\n\n[MOB_29F]\nMi nombre es Umberto Robina y quiero que nos reunamos en el Café Robina lo antes posible,\n\n[MOB_29G]\nporque, como le digo, estos malditos haitianos se han pasado de la raya esta vez.\n\n[MOB_29H]\nPrueba\n\n[MOB_30A]\nTommy, soy Umberto Robina.\n\n[MOB_30B]\n¿Cómo está el café?\n\n[MOB_30C]\nOh, maravilloso. Increíble. Tommy, increíble. Sin blandengues, Tommy, sólo hombres de verdad, ya sabes, ¡y las mujeres hermosas!\n\n[MOB_30D]\nDe todos modos, quería decirte que para papá y para mí, para nosotros, ahora eres un cubano.\n\n[MOB_30E]\nHas demostrado que tienes unas pelotas de cojones, tío.\n\n[MOB_30F]\nGracias, Umberto. Nadie me había dicho eso desde que salí de la cárcel. Nos vemos.\n\n[MOB_33A]\nTommy, soy Phil, olvida toda esa mierda del pasado y escúchame, ¿me oyes?\n\n[MOB_33B]\nBien. Tengo un pelotazo extra a punto de fermentar y me preguntaba si te apetecería probarlo.\n\n[MOB_33C]\nEn serio, Tommy, si quieres una copa, o si necesitas ponerte a tono, este material hará de ti un hombre.\n\n[MOB_33D]\nA mí me pasó aunque todavía no puedo ver por un ojo. Te estaré esperando, lo que oyes.\n\n[MOB_34A]\nTommy, de verdad que he disfrutado trabajando contigo. No me había divertido tanto desde la loma en Vietnam, colega.\n\n[MOB_34B]\nDe todas formas, si necesitas algo, llámame, ¿me oyes?\n\n[MOB_34C]\nSiempre me acuerdo de aquellos con los que he servido,\n\n[MOB_34D]\ny estoy seguro de que puedo ayudarte, ¿me oyes?\n\n[MOB_35A]\nTommy, la herida está cicatrizando bien. Lo gracioso es\n\n[MOB_35B]\nque he luchado en 6 zonas de combate y siempre he salido sin un rasguño, ¡y ahora esto!\n\n[MOB_35C]\nPhil el manco. Aún así, tengo una buena selección armas de fuego para mancos, así que nunca seré Phil el desarmado, lo que oyes.\n\n[MOB_35D]\nVenga, hijo, corta con esa mierda sentimental y pídete una copa, ¡me oyes!\n\n[MOB_36A]\nTommy, soy Phil, quiero darte las gracias por ayudarme allí, hijo,\n\n[MOB_36B]\nmaldito Charlie, siempre te tenderá una emboscada de un modo o de otro.\n\n[MOB_36C]\nBueno, la herida está cicatrizando bien, y eso quiere decir que voy a dejar de estafar al gobierno con mi cheque de incapacidad. Gracias, colega.\n\n[MOB_40A]\nEh, Tommy, soy Sonny. ¿Qué tal el bronceado?\n\n[MOB_40B]\nNo tengo bronceado.\n\n[MOB_40C]\nBueno, tampoco tienes mi dinero, así que me estoy preguntando,\n\n[MOB_40D]\n¿qué estás haciendo? Así que, dime Tommy ¿qué estás haciendo?\n\n[MOB_40E]\nEstoy buscando el dinero, Sonny. No te preocupes.\n\n[MOB_40F]\nMe estoy preocupando, Tommy, ese es mi estilo,\n\n[MOB_40G]\nporque parece que en mi vida tengo este problema con gente que no es de confianza.\n\n[MOB_40H]\nNo seas una persona poco fiable, Tommy, por favor.\n\n[MOB_40I]\nHaznos un favor. Tengo muchas ganas de tener noticias tuyas.\n\n[MOB_41A]\nTommy, ¿te acuerdas de mí?\n\n[MOB_41B]\nHola, Sonny.\n\n[MOB_41C]\nSí, está bien, Sonny. Somos viejos amigos,\n\n[MOB_41D]\ny nunca me escribes, nunca llamas. ¿No quieres que sigamos siendo amigos?\n\n[MOB_41E]\nHe estado muy ocupado intentando arreglar las cosas. No me diste mucho apoyo.\n\n[MOB_41F]\nOh, y es culpa mía, ¿verdad? Bueno, he oído que has estado muy ocupado.\n\n[MOB_41G]\nOcupado matando a capos. Ocupado tomando el poder.\n\n[MOB_41H]\nNo te olvides de nosotros, Tommy, porque puedo asegurarte que yo no me he olvidado de ti.\n\n[MOB_42A]\nTommy.\n\n[MOB_42B]\nSonny.\n\n[MOB_42C]\nObviamente tienes un problema a la hora de escuchar a los demás, de modo que lo intentaré de nuevo.\n\n[MOB_42D]\nTommy, ¿dónde está el maldito dinero, dónde está el maldito material y dónde está mi parte de tus nuevos golpes?\n\n[MOB_42E]\nMe estás haciendo quedar como un idiota, Tommy, y no me hace gracia.\n\n[MOB_43A]\nTommy, Tommy, Tommy, tenía a Sonny al teléfono, de acuerdo, ¿me sigues?\n\n[MOB_43B]\nNo sé tú, pero hay algo sobre un hombre que amenaza con asesinar a mi familia\n\n[MOB_43C]\nque realmente me pone enfermo. ¿Qué vas a hacer?\n\n[MOB_43D]\nTen calma, Ken, todo irá bien.\n\n[MOB_43E]\n¡ESTOY calmado, todo lo calmado que puede estar un hombre cuando teme por su vida!\n\n[MOB_43F]\nKen, ahora mismo tengo otras cosas en la cabeza,\n\n[MOB_43G]\nnos ocuparemos de Forelli cuando llegue el momento.\n\n[MOB_43H]\nEstoy calmado. ¿No te lo parece? Debe ser la muerte inminente la que le hace esto a mi voz.\n\n[MOB45_A]\nTommy, tenemos cosas de las que hablar.\n\n[MOB45_B]\n¿Cuál es el problema, Lance?\n\n[MOB45_C]\nEres tú, amigo, creo que no me estás dando una tajada justa.\n\n[MOB45_D]\nY lo que es más, me estás avergonzando delante de los chicos. No puedo permitirlo.\n\n[MOB45_E]\nLance, las cosas no son así. Has estado cometiendo errores.\n\n[MOB45_F]\nTommy, no soy tu chico de los recados. No soy tu emisario.\n\n[MOB45_G]\nLance, no la cagues, y no tendremos ningún problema. Si la cago yo, entonces podrás venir a reprochármelo en cualquier momento.\n\n[MOB45_H]\nTommy, he hecho de todo por ti, pero me tratas como si fuese estúpido. No hagas eso.\n\n[MOB45_I]\nLance no te voy a timar ni a apuñalarte por la espalda, de acuerdo.\n\n[MOB45_J]\nTómatelo con calma. Esto ya es lo suficientemente duro sin que te me pongas sentimental.\n\n[MOB45_K]\nConfía en mí. ¿Me oyes, me oyes?\n\n[MOB45_L]\nTe oigo, pero Tommy, no puedo aguantar esto por más tiempo.\n\n[MOB45_M]\nLance, no seas así. Ahora te estoy dando un aviso.\n\n[MOB45_N]\n¿Me oyes? Relájate, tómate unos días libres, y luego hablaremos, ¿vale?\n\n[MOB46_A]\n¡Eh, Tommy! Soy Lance.\n\n[MOB46_B]\n¿Sí?\n\n[MOB46_C]\nMe alegro tanto de tener noticias tuyas, Lance. Venga, tío, enróllate, enróllate.\n\n[MOB46_D]\nEstoy ocupado. ¿Qué quieres?\n\n[MOB46_E]\nNada. Solo llamo para decirte, ya sabes. Mira Tommy, podemos hacer esto.\n\n[MOB46_F]\nTú y yo, sin ningún problema. ¿Sabes lo que quiero decir?\n\n[MOB46_G]\nVamos a tener que hacerlo, porque de otro modo, estaremos muertos, Lance.\n\n[MOB46_H]\nYa hemos ido demasiado lejos. Pero gracias por llamar. Hablaré contigo más tarde.\n\n[MOB_47A]\nTommy, Lance, tenemos problemas serios. Ven aquí. Enseguida.\n\n[MOB52_A]\nEh, Leo, creo que tengo un comprador para la mercancía de Díaz.\n\n[MOB52_B]\nTienes que llamarle, tío, montar el trato, ¿sabes?\n\n[MOB52_C]\n¿Dónde estás?\n\n[MOB52_D]\n¿Estás bien, Leo? Te noto un tanto diferente.\n\n[MOB52_E]\nSimplemente dime dónde estás.\n\n[MOB52_F]\n¿Quién demonios eres? ¡Que se ponga Leo!\n\n[MOB52_G]\nLeo se ha ido de viaje unos días, me dejó al cargo de todo.\n\n[MOB52_H]\n¡Que te jodan, tío!\n\n[MOB54_A]\n¡Hola, Tommy!\n\n[MOB54_B]\nHola, Mercedes, ¿cómo te va?\n\n[MOB54_C]\nTengo un apartamento nuevo en Vice Point,\n\n[MOB54_D]\npensé que quizás querrías pasarte en algún momento.\n\n[MOB54_E]\nMe encantaría. Te veo luego.\n\n[MOB55_A]\nTommy, soy yo.\n\n[MOB55_B]\nHola, Mercedes.\n\n[MOB55_C]\nTommy, estoy tan aburrida, ¿cuándo vamos a divertirnos un poco?\n\n[MOB55_D]\n¿Qué quieres decir?\n\n[MOB55_E]\nBueno, sé que estás ocupado luchando y matando y sobornando a gente,\n\n[MOB55_F]\npero yo sólo quiero divertirme un poco. Así que no te olvides de mí, ¿me oyes?\n\n[MOB56_A]\nTommy, oí que te cargaste a Ricardo Díaz.\n\n[MOB56_B]\nHubo un desafortunado tiroteo en su mansión.\n\n[MOB56_C]\nCreo que se quemó hasta morir en su camisa acrílica.\n\n[MOB56_D]\nTommy, estoy tan orgullosa de ti. Sabía que eras un hombre de verdad.\n\n[MOB56_E]\nEra un marrano en pantalones, me haces sentir muy orgullosa de ser tu amiga.\n\n[MOB56_F]\nNo, sé que vas a estar ocupado intentando tomar las riendas de esta ciudad,\n\n[MOB56_G]\npero no te olvides de mí, ¿me oyes?\n\n[MOB57_A]\nSoy Mercedes. Ya no te amo, Tommy.\n\n[MOB57_B]\nYa no lo hago. De verdad. Porque ya no eres amable con Mercedes.\n\n[MOB57_C]\nYa no la tratas como una dama. Me ignoras y te odio.\n\n[MOB57_D]\n¡Insisto en que vengas a verme enseguida!\n\n[MOB58_A]\nTommy.\n\n[MOB58_B]\nHola, Mercedes.\n\n[MOB58_C]\nHola, tipo duro. Estoy muy enfadada contigo, Tommy.\n\n[MOB58_D]\nNo me hagas ir nunca más por ahí con Jezz Torrent otra vez.\n\n[MOB58_E]\nEs patético. A mitad de camino, empieza a llorar por su perrito\n\n[MOB58_F]\nque murió cuando él tenía siete años y que si su madre nunca le había querido.\n\n[MOB58_G]\nY Tommy. En privado lleva peluca y sostén.\n\n[MOB58_H]\n¡No estoy muy contenta contigo!\n\n[MOB59_A]\nOoh Tommy, soy Mercedes.\n\n[MOB59_B]\nSólo quería decirte que me divertí mucho en el plató de rodaje.\n\n[MOB59_C]\nCualquier otra cosa que tengas así, me lo dices.\n\n[MOB59_D]\nLo digo de verdad. Siempre quise ser actriz.\n\n[MOB59_E]\nCreo que aprendí mucho sobre el proceso dramático.\n\n[MOB59_F]\n¡Es tan instructivo! Gracias. Gracias. Hasta muy, muy pronto. Adiós.\n\n[MOB_99]\nVe al teléfono público del lugar.\n\n[MOB_98]\nVe al teléfono público del lugar.\n\n[MOB_97]\nVe al teléfono público del lugar.\n\n[MOB_96]\nVe al teléfono público del lugar.\n\n[MOB_95]\nVe al teléfono público del lugar.\n\n[A_TIME]\n+~1~ segundos\n\n[DODO_FT]\n¡Volaste durante ~1~ segundos!\n\n[GA_8]\nUtiliza el detonador para activar la bomba.\n\n[GA_10]\nMuy bien. Aquí están tus ~1~ $.\n\n[GA_11]\nYa tenemos ese coche. ¡No nos sirve!\n\n[GA_12]\nBomba activada.\n\n[GA_13]\nEntregado como un profesional. Completa la lista y habrá una bonificación para ti.\n\n[GA_14]\nTodos los coches. ¡ESTUPENDO! Aquí tienes una cosilla.\n\n[GA_15]\nEspero que te guste el nuevo color.\n\n[GA_16]\nVolver a pintarlo es gratis.\n\n[GA_19]\nNo estamos interesados en este modelo.\n\n[GA_20]\nTenemos más de eso de los que podemos colocar. Lo siento, tío, no hay trato.\n\n[CHASE]\nAtención de la prensa\n\n[CHASE1]\nIgnorado\n\n[CHASE2]\nAburrido\n\n[CHASE3]\nAlgo interesante\n\n[CHASE4]\nPágina 7 del periódico local\n\n[CHASE5]\nPortada del periódico local\n\n[CHASE6]\nPágina 2 del Vice Courier\n\n[CHASE7]\nPortada del Vice Courier\n\n[CHASE8]\nTV Local a las 3 de la mañana\n\n[CHASE9]\nNoticias locales en TV\n\n[CHASE10]\nCobertura en directo de la TV Local\n\n[CHASE11]\nPágina 12 del UFA Today\n\n[CHASE12]\nPágina 4 del UFA Today\n\n[CHASE13]\nImagen en UFA Today\n\n[CHASE14]\nTV Nacional a las 4 de la mañana\n\n[CHASE15]\nNoticias de la TV Nacional\n\n[CHASE16]\nCobertura en directo de la TV Nacional\n\n[CHASE17]\nNoticias internacionales\n\n[CHASE18]\nCrisis nacional\n\n[CHASE19]\nCrisis internacional\n\n[CHASE20]\nAcontecimiento mundial\n\n[CHASE21]\nLeyenda\n\n[CR_1]\nLa grúa no puede levantar este vehículo\n\n[PU_MONY]\nNo tienes suficiente dinero.\n\n[CO_ALL]\nLos tienes todos. Aquí tienes una cosilla...\n\n[FEM_ON]\nSÍ\n\n[FEM_OFF]\nNO\n\n[FEM_YES]\nSí\n\n[FEM_NO]\nNo\n\n[FEM_RET]\nREINTENTAR\n\n[FEC_NA]\nNO DISPONIBLE\n\n[FEC_CWL]\nEscoger arma hacia la izquierda\n\n[FEC_CWR]\nEscoger arma hacia la derecha\n\n[FEC_LOF]\nMirar hacia adelante\n\n[FEC_TAR]\nObjetivo\n\n[FEC_MOV]\nMovimiento\n\n[FEC_CAM]\nModos de cámara\n\n[FEC_PAU]\nPausa\n\n[FEC_ENV]\nEntrar en el vehículo\n\n[FEC_JUM]\nSaltar\n\n[FEC_ATT]\nAtacar o disparar arma\n\n[FEC_RUN]\nCorrer\n\n[FEC_FPC]\nCámara en primera persona\n\n[FEC_LL]\nMirar a la izquierda\n\n[FEC_LB]\nRetrovisor\n\n[FEC_LR]\nMirar a la derecha\n\n[FEC_ABR]\nAcelerar, frenar o dar marcha atrás\n\n[FEC_HOR]\nBocina\n\n[FEC_VES]\nControl del vehículo\n\n[FEC_BRA]\nFreno o marcha atrás\n\n[FEC_HAB]\nFreno de mano\n\n[FEC_CAW]\nArma del vehículo\n\n[FEC_ACC]\nAcelerar\n\n[FEC_CCF]\nConfiguración:\n\n[FEC_CF1]\nConfiguración 1\n\n[FEC_CF2]\nConfiguración 2\n\n[FEC_CF3]\nConfiguración 3\n\n[FEC_CF4]\nConfiguración 4\n\n[FEC_CDP]\nPantalla del mando\n\n[FEC_ONF]\nA pie\n\n[FEC_INC]\nEn coche\n\n[FEC_VIB]\nVibración :\n\n[FEL_ENG]\nInglés\n\n[FEL_FRE]\nFrancés\n\n[FEL_GER]\nAlemán\n\n[FEL_ITA]\nItaliano\n\n[FEL_SPA]\nEspañol\n\n[FED_DBG]\nMenú de soluciones técnicas\n\n[FED_RID]\nRecargar IDE\n\n[FED_RIP]\nRecargar IPL\n\n[FED_PAH]\nParse Heap\n\n[FED_DFL]\nCLos guiones::DbgBandera\n\n[FED_DLS]\nGran luz blanca de solución técnica encendida\n\n[FED_SPR]\nMostrar grupos de aceras\n\n[FED_SCR]\nMostrar grupos de carreteras\n\n[FED_SCZ]\nMostrar zonas de desechos\n\n[FED_DSR]\nSolicitud de solución técnica del streaming\n\n[FED_SCP]\ngbMostrarcolisiónPolys\n\n[PL_STAT]\nEstadísticas del jugador\n\n[PE_WAST]\nGente que te has cargado\n\n[PE_WSOT]\nGente eliminada por otros\n\n[TM_BUST]\nVeces detenido\n\n[GNG_WST]\nMiembros de la banda liquidados\n\n[DED_CRI]\nCriminales liquidados\n\n[PER_COM]\nPorcentaje completado\n\n[KGS_EXP]\nKilogramos de explosivos empleados\n\n[ACCURA]\nPrecisión\n\n[ST_WEAP]\nPresupuesto armamentístico\n\n[ST_PROP]\nPresupuesto de propiedades\n\n[ST_AUTO]\nPresupuesto para reparación de coches y pintura\n\n[ST_PHOT]\nFotografías tomadas\n\n[ST_LOAN]\nVisitas de usureros prestamistas\n\n[ST_STOR]\nAlmacenes desvalijados\n\n[ST_MOVI]\nEscenas de especialista\n\n[ST_PIZZ]\nPizzas entregadas\n\n[ST_GARB]\nRecogidas de basura efectuadas\n\n[ST_ICEC]\n''Helado'' vendido\n\n[TOP_SHO]\nPuntuación máxima en el campo de tiro\n\n[SHO_RAN]\nClasificación del campo de tiro\n\n[SEAGULL]\nGaviotas disparadas\n\n[PROPOWN]\nPropiedad en posesión\n\n[ST_TIME]\nTiempo de juego\n\n[ST_FTIM]\nHoras de vuelo\n\n[ST_PRAN]\nClasificación de los pilotos\n\n[ST_RAN0]\nAprendiz\n\n[ST_RAN1]\nNavegante\n\n[ST_RAN2]\nCopiloto\n\n[ST_RAN3]\nJunior\n\n[ST_RAN4]\nCompetente\n\n[ST_RAN5]\nSenior\n\n[ST_RAN6]\nAs\n\n[ST_RAN7]\nBarón rojo\n\n[ST_DRWN]\nPeces alimentados\n\n[ST_FASH]\nPresupuesto para moda\n\n[ST_DAMA]\nCoste de propiedades destruidas\n\n[TM_DED]\nVisitas al hospital\n\n[DAYSPS]\nDías transcurridos en el juego\n\n[NUMSHV]\nVisitas a pisos francos\n\n[MXCARD]\nMax. Distancia de salto LOCO (pies)\n\n[MXCARJ]\nMax. Altura de salto LOCO (pies)\n\n[MXCARDM]\nMáxima distancia de salto LOCO (m)\n\n[MXCARJM]\nMáxima altura de salto LOCO (m)\n\n[MXFLIP]\nMáximas vueltas de salto LOCO\n\n[MXJUMP]\nMáxima rotación de salto LOCO\n\n[BUL_FIR]\nBalas disparadas\n\n[BUL_HIT]\nAciertos\n\n[SPRAYIN]\nPintura\n\n[BSTSTU]\nMejor maniobra LOCA hasta ahora\n\n[INSTUN]\nManiobra loca\n\n[PRINST]\nManiobra loca perfecta\n\n[DBINST]\nManiobra loca doble\n\n[DBPINS]\nManiobra loca doble perfecta\n\n[TRINST]\nManiobra loca triple\n\n[PRTRST]\nManiobra loca triple perfecta\n\n[QUINST]\nManiobra loca cuádruple\n\n[PQUINS]\nManiobra loca cuádruple perfecta\n\n[NOSTUC]\nNo se ha completado ninguna\n\n[NOUNIF]\nSaltos únicos completados\n\n[NMISON]\nIntentos de misión\n\n[PASDRO]\nPasajeros en destino\n\n[MONTAX]\nDinero conseguido con el taxi\n\n[DAYPLC]\nGastos diarios provocados a la policía\n\n[CRIMRA]\nTasa criminal:\n\n[STPR_1]\nEl Malibú\n\n[STPR_2]\nImprenta\n\n[STPR_3]\nEstudio de cine\n\n[STPR_4]\nFábrica de helados\n\n[STPR_5]\nSalón de coches\n\n[STPR_6]\nCompañía de taxis\n\n[STPR_7]\nAstillero\n\n[SET1EN]\nConfiguración 1. Activada\n\n[GMSAVE]\nGuardar partida\n\n[FEDS_TB]\nVolver\n\n[FEST_OO]\nde\n\n[FEC_TUC]\nControl de la torreta\n\n[FEC_RS3]\nCambiar emisora de radio (Botón L3)\n\n[FEC_HO3]\nBocina (Botón L3)\n\n[C_FAIL]\n¡Misión de justiciero terminada!\n\n[C_ESCP]\n~r~¡El sospechoso ha escapado!\n\n[C_VIGIL]\n¡BONIFICACIÓN DE JUSTICIERO!\n\n[HEAL_A]\nTu ~h~salud~w~ aparece en naranja en la parte superior derecha de la pantalla.\n\n[WRONGCD]\nDisco incorrecto. Introduce el disco correcto.\n\n[NOCD]\nLa bandeja del disco está vacía. Por favor, inserta el disco.\n\n[OPENCD]\nLa bandeja del disco está abierta. Por favor, cierra la bandeja de disco.\n\n[CDERROR]\nError al leer el DVD de Grand Theft Auto: Vice City\n\n[RESTART]\nIniciando nueva partida\n\n[GA_3]\nNo hay más regalitos. ¡100 $ para volver a pintar!\n\n[GA_1]\n¡Hala! ¡Demasiado peligroso para mi gusto!\n\n[GA_1A]\nVuelve cuando no estés tan ocupado...\n\n[HELP9_C]\nPulsa ~h~~k~~k~~PED_FIREWEAPON~~w~para ~h~disparar~w~ el fusil de francotirador.\n\n[TAXI2]\n~r~¡Te has quedado sin tiempo!\n\n[PAGEB13]\nSalud entregada en el escondite\n\n[PAGEB14]\nAdrenalina entregada en el escondite\n\n[FESZ_CA]\nCancelar\n\n[FES_NGA]\nNueva partida\n\n[FES_CAN]\nCancelar\n\n[FESZ_QL]\nTodo el progreso no guardado de tu partida actual se perderá. ¿Continuar cargando?\n\n[FESZ_QD]\n¿Proceder a borrar esta partida guardada?\n\n[FESZ_QO]\n¿Proceder para sobrescribir esta partida guardada?\n\n[FESZ_QR]\n¿Seguro que quieres empezar una nueva partida? Todo el progreso desde la última partida guardada se perderá. ¿Continuar?\n\n[T4X4_1]\nPrueba de PCJ\n\n[BMX_1]\nTrial de tierra\n\n[BMX_2]\nPista de pruebas\n\n[BMXFAIL]\n~r~¡No has conseguido un nuevo récord!\n\n[BMX_REC]\n~g~¡Nuevo récord establecido: ~1~!\n\n[T4X4_3]\n¡AGARRADO!\n\n[MM_1]\nCONOCIRCUITO\n\n[T4X4_F]\n~r~¡Te rajaste! ¿Demasiado duro para ti?\n\n[LANDSTK]\nLandstalker\n\n[IDAHO]\nIdaho\n\n[STINGER]\nStinger\n\n[LINERUN]\nLinerunner\n\n[PEREN]\nPerennial\n\n[SENTINL]\nSentinel\n\n[RIO]\nRío\n\n[PATRIOT]\nPatriot\n\n[FIRETRK]\nCamión de bomberos\n\n[TRASHM]\nTrashmaster\n\n[STRETCH]\nLimusina\n\n[MANANA]\nMañana\n\n[INFERNS]\nInfernus\n\n[VOODOO]\nVoodoo\n\n[PONY]\nPony\n\n[MULE]\nMule\n\n[CHEETAH]\nCheetah\n\n[AMBULAN]\nAmbulancia\n\n[FBICAR]\nFBI Washington\n\n[MOONBM]\nMoonbeam\n\n[ESPERAN]\nEsperanto\n\n[TAXI]\nTaxi\n\n[WASHING]\nWashington\n\n[BOBCAT]\nBobcat\n\n[WHOOPEE]\nMr Whoopee\n\n[BFINJC]\nBF Injection\n\n[HUNTER]\nHunter\n\n[POLICAR]\nPolicía\n\n[ENFORCR]\nEnforcer\n\n[SECURI]\nSecuricar\n\n[BANSHEE]\nBanshee\n\n[PREDATR]\nPredator\n\n[BUS]\nAutobús\n\n[RHINO]\nRhino\n\n[BARRCKS]\nBarracks OL\n\n[CUBAN]\nCuban Hermes\n\n[HELI]\nHelicóptero\n\n[DODO]\nDodo\n\n[COACH]\nAutocar\n\n[CABBIE]\nTaxi clásico\n\n[STALION]\nStallion\n\n[RUMPO]\nRumpo\n\n[RCBANDT]\nBandit RC\n\n[ROMERO]\nRomero's Hearse\n\n[PACKER]\nPacker\n\n[ADMIRAL]\nAdmiral\n\n[SQUALO]\nSqualo\n\n[SEASPAR]\nSea Sparrow\n\n[PIZZABO]\nPizza Boy\n\n[GANGBUR]\nGang Burrito\n\n[TROPIC]\nTropic\n\n[SPEEDER]\nSpeeder\n\n[REEFER]\nReefer\n\n[FLATBED]\nFlatbed\n\n[YANKEE]\nYankee\n\n[CADDY]\nCaddy\n\n[ZEBRA]\nTaxi cebra\n\n[TOPFUN]\nTop Fun\n\n[SKIMMER]\nSkimmer\n\n[PCJ600]\nPCJ 600\n\n[PHOENIX]\nPhoenix\n\n[FAGGIO]\nFaggio\n\n[FREEWAY]\nFreeway\n\n[RCBARON]\nBarón RC\n\n[RCRAIDE]\nRaider RC\n\n[GLENDAL]\nGlendale\n\n[OCEANIC]\nOceanic\n\n[SANCHEZ]\nSanchez\n\n[SPARROW]\nSparrow\n\n[LOVEFIS]\nLove Fist\n\n[COASTG]\nGuardacostas\n\n[DINGHY]\nDinghy\n\n[HERMES]\nHermes\n\n[SABRE]\nSabre\n\n[SABRETU]\nSabre Turbo\n\n[WALTON]\nWalton\n\n[REGINA]\nRegina\n\n[COMET]\nComet\n\n[DELUXO]\nDeluxo\n\n[BURRITO]\nBurrito\n\n[SPAND]\nSpand Express\n\n[MARQUIS]\nMarquis\n\n[BAGGAGE]\nMozo de equipaje\n\n[KAUFMAN]\nTaxi Kaufman\n\n[COASTMA]\nGuardacostas Maverick\n\n[MAVERIC]\nMaverick\n\n[RANCHER]\nRancher\n\n[FBIRANC]\nFBI Rancher\n\n[VIRGO]\nVirgo\n\n[GREENWO]\nGreenwood\n\n[HOTRING]\nHotring Racer\n\n[BLISTAC]\nBlista Compact\n\n[FEST_DF]\nDist. recorrida a pie (millas)\n\n[FEST_DC]\nDist. recorrida en coche (millas)\n\n[FESTDFM]\nDistancia recorrida a pie (m)\n\n[FESTDCM]\nDistancia recorrida en coche (m)\n\n[TOT_DIS]\nDistancia total recorrida (millas)\n\n[TOTDISM]\nDistancia total recorrida (m)\n\n[DISTHEL]\nDist. recorrida en helicóptero (millas)\n\n[DISTHEM]\nDistancia recorrida en helicóptero (m)\n\n[DISTBOA]\nDist. recorrida en barco (millas)\n\n[DISTBOM]\nDistancia recorrida en barco (m)\n\n[FEST_LS]\nGente salvada en una ambulancia\n\n[FEST_CC]\nCriminales asesinados en misión Vigilante\n\n[FEST_FE]\nTotal de fuegos extinguidos\n\n[FEST_RP]\nMasacres superadas\n\n[FEST_MP]\nMisiones superadas\n\n[FEST_BB]\nBling-bling Scramble:\n\n[FEST_H0]\nMayoría de puntos de control\n\n[FEST_GC]\nTotal de coches de bandas:\n\n[FEST_H1]\nDestrucción del diablo\n\n[FEST_H2]\nMasacre de la mafia\n\n[FEST_H3]\nCasino Calamity\n\n[FEST_H4]\nRumpo Wrecker\n\n[USJ]\n¡BONIFICACIÓN POR MANIOBRA ÚNICA!\n\n[USJ_DUN]\nMANIOBRA YA COMPLETADA\n\n[RATNG1]\nCiudadano honrado\n\n[RATNG2]\nNadie en especial\n\n[RATNG3]\nBasurero\n\n[RATNG4]\nCleptómano\n\n[RATNG5]\nVándalo\n\n[RATNG6]\nChico de los recados\n\n[RATNG7]\nCarterista\n\n[RATNG8]\nCleptómano\n\n[RATNG9]\nChivato\n\n[RATNG10]\nRata\n\n[RATNG11]\nLince\n\n[RATNG12]\nEstafador\n\n[RATNG13]\nTimador\n\n[RATNG14]\nCorredor de apuestas\n\n[RATNG15]\nBuscavidas\n\n[RATNG16]\nMatón\n\n[RATNG17]\nChusma\n\n[RATNG18]\nBribón\n\n[RATNG19]\nRufián\n\n[RATNG20]\nProscrito\n\n[RATNG21]\nMalhechor\n\n[RATNG22]\nAsesino\n\n[RATNG23]\nSuper matón\n\n[RATNG24]\nMatón\n\n[RATNG25]\nPresidiario\n\n[RATNG26]\nExconvicto\n\n[RATNG27]\nCriminal\n\n[RATNG28]\nSaqueador\n\n[RATNG29]\nMafioso\n\n[RATNG30]\nConductor\n\n[RATNG31]\nGorila\n\n[RATNG32]\nAsesino profesional\n\n[RATNG33]\nAsuntos internos\n\n[RATNG34]\nAgente\n\n[RATNG35]\nRonin\n\n[RATNG36]\nManitas\n\n[RATNG37]\nAsesino a sueldo\n\n[RATNG38]\nAsociado\n\n[RATNG39]\nCarnicero\n\n[RATNG40]\nEncargado de la limpieza\n\n[RATNG41]\nAsesino\n\n[RATNG42]\nConsigliere\n\n[RATNG43]\nMaleante\n\n[RATNG44]\nMano derecha\n\n[RATNG45]\nEjecutor\n\n[RATNG46]\nTeniente\n\n[RATNG47]\nSubjefe\n\n[RATNG48]\nCapo\n\n[RATNG49]\nJefe\n\n[RATNG50]\nNegado\n\n[RATNG51]\nDon\n\n[RATNG52]\nRey de la Jodida Ciudad\n\n[PAGE_00]\n.\n\n[WELCOME]\nBIENVENIDO A\n\n[TSCORE]\nGANANCIAS: ~1~ $\n\n[PBOAT_2] { reVC update }\nPulsa ~h~~k~~VEHICLE_FIREWEAPON~~w~ para disparar los cañones del barco.\n\n[HJSTAT]\nDistancia: ~1~.~1~m Altura: ~1~.~1~m Vueltas: ~1~ Rotación: ~1~_\n\n[HJSTATW]\nDistancia: ~1~.~1~m Altura: ~1~.~1~m Vueltas: ~1~ Rotación: ~1~_ ¡qué gran aterrizaje!\n\n[ATUTOR]\nPulsa ~h~~k~~TOGGLE_SUBMISSIONS~~w~ para activar o desactivar las misiones de ATS.\n\n[FEST_HA]\nNivel más alto de misión de ATS\n\n[C_KILLS]\nCRIMINALES ASESINADOS: ~1~\n\n[HJSTATF]\nDistancia: ~1~ pies Altura: ~1~ pies Vueltas: ~1~ Rotación: ~1~_\n\n[HJSTAWF]\nDistancia: ~1~ pies Altura: ~1~ pies Vueltas: ~1~ Rotación: ~1~_, ¡y qué gran aterrizaje!\n\n[CRED001]\nROCKSTAR NORTH\n\n[CRD001A]\nDIRECTOR DEL ESTUDIO\n\n[CRD001B]\nANDREW SEMPLE\n\n[CRED002]\nPRODUCTOR\n\n[CRD002A]\nDIRECTOR DE DESARROLLO\n\n[CRED003]\nLESLIE BENZIES\n\n[CRED004]\nDIRECTOR DE ARTE\n\n[CRED005]\nAARON GARBUT\n\n[CRED006]\nDIRECTORES TÉCNICOS\n\n[CRED007]\nOBBE VERMEIJ\n\n[CRED008]\nADAM FOWLER\n\n[CRED010]\nANDREW DUTHIE\n\n[CRED011]\nCRAIG FILSHIE\n\n[CRED012]\nWILLIAM MILLS\n\n[CRED013]\nCHRIS ROTHWELL\n\n[CRD013A]\nIMRAN SARWAR\n\n[CRD013B]\nJAMES WORRALL\n\n[CRD013C]\nJOHN HAIME\n\n[CRED014]\nESCRITO POR\n\n[CRED015]\nJAMES WORRALL\n\n[CRED016]\nPAUL KUROWSKI\n\n[CRED017]\nDAN HOUSER\n\n[CRED018]\nDISEÑO DEL PERSONAJE PRINCIPAL\n\n[CRD018A]\nDISEÑO DE PERSONAJES\n\n[CRED019]\nIAN MCQUE\n\n[CRD019A]\nTOKS SOLARIN\n\n[CRD019B]\nALAN DAVIDSON\n\n[CRED020]\nANIMACIÓN PRINCIPAL\n\n[CRED021]\nALEX HORTON\n\n[CRD022A]\nANIMACIÓN\n\n[CRED022]\nLEE MONTGOMERY\n\n[CRD022B]\nDUNCAN SHIELDS\n\n[CRD022C]\nGUS BRAID\n\n[CRED023]\nDISEÑO DE VEHÍCULOS\n\n[CRD023A]\nJOLYON ORME\n\n[CRD023B]\nALAN DUNCAN\n\n[CRD024A]\nDISEÑO DEL VEHÍCULO PRINCIPAL\n\n[CRED024]\nPAUL KUROWSKI\n\n[CRED025]\nDISEÑO DE MAPAS\n\n[CRED026]\nADAM COCHRANE\n\n[CRED027]\nNIK TAYLOR\n\n[CRED028]\nGARY MCADAM\n\n[CRED029]\nKEIRAN BAILLIE\n\n[CRED030]\nALISDAIR WOOD\n\n[CRED031]\nANDREW SOOSAY\n\n[CRD031A]\nSTEVEN MULHOLLAND\n\n[CRD031B]\nWAYLAND STANDING\n\n[CRD031C]\nCAMPBELL J. DICK\n\n[CRD031D]\nDISEÑO GRÁFICO\n\n[CRD031E]\nSTUART PETRI\n\n[CRED032]\nPROGRAMADOR JEFE\n\n[CRD032A]\nPROGRAMADORES\n\n[CRED033]\nALEXANDER ROGER\n\n[CRED034]\nGRAEME WILLIAMSON\n\n[CRED035]\nBARANE CHAN\n\n[CRED036]\nDEREK PAYNE\n\n[CRED037]\nGORDON YEOMAN\n\n[CRD037A]\nALAN CAMPBELL\n\n[CRD037B]\nMARK HANLON\n\n[CRD037C]\nANDRZEJ MADAJCZYK\n\n[CRED038]\nPRODUCTOR JEFE MUSICAL\n\n[CRED039]\nCRAIG CONNER\n\n[CRED040]\nSTUART ROSS\n\n[CRED041]\nINGENIERO JEFE DE AUDIO\n\n[CRED042]\nALLAN WALKER\n\n[CRD041A]\nINGENIERO DE AUDIO\n\n[CRD041B]\nAUDIO\n\n[CRD042A]\nWILL MORTON\n\n[CRED043]\nPROGRAMADOR DE AUDIO\n\n[CRED044]\nRAYMOND USHER\n\n[CRED045]\nJEFE DE PRUEBAS\n\n[CRED046]\nCRAIG ARBUTHNOTT\n\n[CRED047]\nCONTROL DE CALIDAD PRINCIPAL\n\n[CRED048]\nNEIL CORBETT\n\n[CRED049]\nKEVIN WONG\n\n[CRED050]\nCONTROL DE CALIDAD\n\n[CRED051]\nDAVID BEDDOES\n\n[CRED052]\nDAVID WATSON\n\n[CRED053]\nBARRY CLARK\n\n[CRED054]\nROSS SPARROW\n\n[CRED055]\nJAMES ALLAN\n\n[CRED056]\nNEIL MEIKLE\n\n[CRD056A]\nGEORGE WILLIAMSON\n\n[CRD056B]\nMATT JONES\n\n[CRD056C]\nROB HARBOUR\n\n[CRD056D]\nTOM WHITTAKER\n\n[CRED057]\nSOPORTE TÉCNICO PRINCIPAL\n\n[CRED058]\nLORRAINE ROY\n\n[CRD057A]\nSOPORTE TÉCNICO\n\n[CRED059]\nCHRISTINE CHALMERS\n\n[CRD060A]\nSOPORTE DE OFICINA\n\n[CRD060B]\nKIM GURNEY\n\n[CRD060C]\nCASSIE OLIVER\n\n[CRED060]\nROCKSTAR NUEVA YORK\n\n[CRED061]\nGABINETE DE APOYO\n\n[CRED062]\nSAM HOUSER\n\n[CRED063]\nPRODUCTOR\n\n[CRED064]\nDAN HOUSER\n\n[CRED065]\nVICEPRESIDENTE DE DESARROLLO\n\n[CRED066]\nJAMIE KING\n\n[CRED067]\nOFICIAL JEFE DE TECNOLOGÍA\n\n[CRED068]\nGARY J. FOREMAN\n\n[CRED069]\nPRODUCTOR ASOCIADO\n\n[CRED070]\nJEREMY POPE\n\n[CRD071A]\nDIRECTOR DE CONTROL DE CALIDAD\n\n[CRD072A]\nJEFF ROSA\n\n[CRED071]\nSUPERVISOR MUSICAL\n\n[CRED072]\nTERRY DONOVAN\n\n[CRED073]\nEQUIPO DE PRODUCCIÓN\n\n[CRED074]\nTERRY DONOVAN\n\n[CRED075]\nJENNIFER KOLBE\n\n[CRED076]\nJENEFER GROSS\n\n[CRED077]\nLAURA PATERSON\n\n[CRED078]\nJEFF CASTANEDA\n\n[CRED079]\nJERONIMO BARRERA\n\n[CRED080]\nCARLY SLATER\n\n[CRED081]\nJUNG KWAK\n\n[CRED082]\nBRIAN WOOD\n\n[CRED083]\nRENAUD SEBANNE\n\n[CRED084]\nRICHARD KRUGER\n\n[CRD084A]\nDANIEL EINZIG\n\n[CRD084B]\nJACEN BURROWS\n\n[CRD084C]\nLINN PR\n\n[CRD084D]\nDISEÑO DE PORTADA\n\n[CRD084E]\nSTEPHEN BLISS\n\n[CRED085]\nKENT PAUL'S 80 NOSTALGIA ZONE\n\n[CRED086]\nESCRITO POR DAN HOUSER\n\n[CRD086A]\nPRODUCIDO POR ADAM TEDMAN\n\n[CRED087]\nWWW.KENTPAUL.COM AND WWW.VICECITY.COM\n\n[CRED088]\nCREADO POR\n\n[CRD088A]\nADAM TEDMAN\n\n[CRD088B]\nDAVID YU\n\n[CRD088C]\nJERRY LUNA\n\n[CRD088D]\nSTUART PETRI\n\n[CRD088E]\nMICHAEL CARNEVALE\n\n[CRD088F]\nGREG LAU\n\n[CRD088G]\nFUTABA HAYASHI\n\n[CRED089]\nJEFE DE CONTROL DE CALIDAD\n\n[CRED090]\nCRAIG ARBUTHNOTT\n\n[CRED091]\nANALISTA JEFE\n\n[CRED092]\nADAM DAVIDSON\n\n[CRD092A]\nJOE HOWELL\n\n[CRD092B]\nMARC FERNANDEZ\n\n[CRED093]\nANALISTA DEL JUEGO\n\n[CRED094]\nRICHARD HUIE\n\n[CRED095]\nEQUIPO DE PRUEBAS DE ROCKSTAR\n\n[CRED096]\nLANCE WILLIAMS\n\n[CRED097]\nJOE GREENE\n\n[CRED098]\nBRIAN PLANER\n\n[CRD098A]\nELIZABETH SATTERWHITE\n\n[CRD098B]\nJAMEEL VEGA\n\n[CRD098C]\nMIKE HONG\n\n[CRED099]\nLEE CUMMINGS\n\n[CRED100]\nHISTORIA\n\n[CRED101]\nJAMES WORRALL\n\n[CRED102]\nDAN HOUSER\n\n[CRED103]\nADAM TEDMAN\n\n[CRED104]\nPAUL YEATES\n\n[CRED105]\nJENEFER GROSS\n\n[CRED106]\nLAURA PATERSON\n\n[CRED107]\nSECUENCIAS\n\n[CRED108]\nESCRITAS POR DAN HOUSER Y JAMES WORRALL\n\n[CRED109]\nDIRECCIÓN DE AUDIO DE DAN HOUSER Y NAVID KHONSARI\n\n[CRED110]\nPRODUCIDAS POR JAMIE KING\n\n[CRD110A]\nSELECCIÓN DE ACTORES: JAMIE KING, SEAN MACALUSO\n\n[CRED111]\nREPARTO\n\n[CRD111A]\nPERSONAJES DE REPARTO\n\n[CRED112]\nTOMMY VERCETTI - RAY LIOTTA\n\n[CRED113]\nKEN ROSENBERG - WILLIAN FICHTNER\n\n[CRED114]\nSONNY FORELLI - TOM SIZEMORE\n\n[CRED115]\nSTEVE SCOTT - DENNIS HOPPER\n\n[CRED116]\nAVERY CARRINGTON - BURT REYNOLDS\n\n[CRED117]\nRICARDO DÍAZ - LUIS GUZMÁN\n\n[CRED118]\nLANCE VANCE - PHILIP MICHAEL THOMAS\n\n[CRED119]\nCORONEL JUAN CORTEZ - ROBERT DAVI\n\n[CRED120]\nUMBERTO ROBINA - DANNY TREJO\n\n[CRED121]\nPHIL CASSIDY - GARY BUSEY\n\n[CRED122]\nMITCH BAKER - LEE MAJORS\n\n[CRED123]\nMERCEDES CORTEZ - FAIRUZA BALK\n\n[CRED124]\nKENT PAUL - DANNY DYER\n\n[CRED125]\nJEZZ TORRENT - KEVIN MCKIDD\n\n[CRED126]\nSUPERVISOR TAXIS - DEBORAH HARRY\n\n[CRED127]\nCANDY SUXX - JENNA JAMESON\n\n[CRED128]\nBJ SMITH - LAWRENCE TAYLOR\n\n[CRED129]\nTÍA POULET - YOUREE CLEOMILI HARRIS\n\n[CRED130]\nPROVEEDOR - ARMANDO RIESCO\n\n[CRED131]\nCOUGAR - BLAYNE PERRY\n\n[CRED132]\nHILARY - CHARLES TUCKER\n\n[CRED133]\nCONGRESISTA ALEX SHRUB - CHRIS LUCAS\n\n[CRED134]\nVIEJO KELLY - GEORGE DICENZO\n\n[CRD134A]\nCAM JONES - GREG SIMS\n\n[CRD134B]\nPSICÓPATA - HUNTER PLATIN\n\n[CRD134C]\nMAUDE LA VENDEDORA DE HELADOS - JANE GENNARO\n\n[CRD134D]\nJETHRO - JOHN ZURHELLEN\n\n[CRD134E]\nGONZÁLEZ - JORGE PUPO\n\n[CRD134F]\nDWAYNE - NAVID KHONSARI\n\n[CRD134G]\nDICK - PETER MCKAY\n\n[CRD134H]\nMIKE EL MATÓN & CHICO PORNO - ROBERT CIHRA\n\n[CRD134I]\nPERCY - RUSSELL FOREMAN\n\n[CRED135]\nCAPTURA DE MOVIMIENTOS\n\n[CRED136]\nANIMACIÓN DE\n\n[CRD136A]\nDIRECCIÓN TÉCNICA DE ALEX HORTON\n\n[CRED137]\nDIRIGIDO POR\n\n[CRD137A]\nDIRIGIDO POR NAVID KHONSARI\n\n[CRED138]\nPRODUCIDO POR\n\n[CRD138A]\nPRODUCIDO POR JAMIE KING\n\n[CRD138B]\nRENAUD SEBBANE\n\n[CRED139]\nGRABADO EN PERSPECTIVE STUDIOS, BROOKLYN\n\n[CRED140]\nACTORES DE CAPTURA DE MOVIMIENTOS\n\n[CRD140A]\nBLAYNE PERRY\n\n[CRD140B]\nJONATHON SALE\n\n[CRD140C]\nCHARLES TUCKER\n\n[CRD140D]\nEDDIE MARRERO\n\n[CRD140E]\nWILLIAM MCCALL\n\n[CRD140F]\nJORGE PUPO\n\n[CRD140G]\nROBERT JACKSON\n\n[CRD140H]\nTARA RADCLIFFE\n\n[CRD140I]\nJENIFER GAMBETESE\n\n[CRD140J]\nKRIS ACHEVARRIA\n\n[CRD140K]\nALI ORDOUBADI\n\n[CRD140L]\nKAHLEEM POOLE\n\n[CRED141]\nDIÁLOGOS DE LOS PEATONES\n\n[CRD141A]\nESCRITOS POR DAN HOUSER, MARC FERNÁNDEZ, GILLIAN TELLING Y NAVID KHONSARI\n\n[CRD141B]\nCON LA AYUDA DE JEREMY POPE, LANCE WILLIAMS, Y JENNY JEMISON\n\n[CRED142]\nESCRITO POR\n\n[CRD142A]\nDAN HOUSER Y JAMES WORRALL\n\n[CRED143]\nDIRIGIDO POR DAN HOUSER, CRAIG CONNER, MARC FERNÁNDEZ, Y ALLAN WALKER\n\n[CRED144]\nPRODUCIDO POR RENAUD SEBANNE\n\n[CRED145]\nPEATONES\n\n[CRED146]\nADAM DAVIDSON, ADAM WATKINS, ALEJANDRO K. BROWN, ALEX ANTHONY SIOUKAS, ALEX GARCÍA,\n\n[CRED147]\nALICE SALTZMAN, ALISON CIHRA, AMY SALIMA, AMY SALZMAN, ANDREA VIDELA, ANTHONY ATTI,\n\n[CRED148]\nANTHONY RIVERA, BIJAN SHAMS, BLAYNE PERRY, BRETT BISOGNO, BREYE MATA, BRIAN PANEN,\n\n[CRED149]\nBROCK VODER, CAREY BERTINI, CHARISSE LAMBERT, CHRIS DIFAT, CHRIS REISENBERGER,\n\n[CRED150]\nCHRISTOPHER BRODAY, CHRISTOPHER CARRO, CYNTHIA GREENE, DAMARIES LÓPEZ, DAN LEE,\n\n[CRED151]\nDAN SCHNEIDER, DAN TOYAMA, DAVID DEAN CHALTFIELD, JR., DAVID HARRISON, DAVID WILEY,\n\n[CRED152]\nDEBORAH COLLINS, DEBRANDA CHANEY-GILES, DEMETRA KOUKOULAS, DENISE ROSADO,\n\n[CRED153]\nDEVIN BENNETT, DEVIN WINTERBOTTOM, DORIS WOO, DOUGLAS HARRISON, DUNCAN COUTTS,\n\n[CRED154]\nDUPE AJAYI, EDWIN AVELLANEDA, ELIZABETH HOWELL, ELIZABETH SATTERWHITE, ERIC NAGLE,\n\n[CRED155]\nESTEBAN KARPLUS, F. FONT, FUTABA HAYASHI, GENE HILGREEN, GERALD COSGROVE,\n\n[CRED156]\nGERARD LUNA, GILLIAN TELLING, GREGG CARLUCCI, GREGORY CLERVOIX, GREGORY SCHWEIZER,\n\n[CRED157]\nHADLEY TOMICKI, J. ROSSETT, JAMEEL VEGA, JASON JONES, JEFF ROSA, JENNIFER JEMISON,\n\n[CRED158]\nJEREMY TAGGERT, JESSICA RIDER, JOSEPH GREENE,JOSEPH HOWELL, KATE DUKICH,\n\n[CRED159]\nKEL O'NEILL, KEVIN HOPKINS, LADAWN JAMES, LANCE WILLIAMS, LAURA BUBBLES,\n\n[CRED160]\nLAURA PATTERSON, LEE CUMMINGS, LETICIA L. YOUNG, LINDSAY KENNEDY, LISA ORITZ,\n\n[CRED161]\nLORNA JORDAN, LUCIO AMADIO, MARCO FERNÁNDEZ, MARIKO TANAKA, MARLON MATTHEWS,\n\n[CRED162]\nMARY TELLING, MASAYOSHI MITSUYAMA, MATTHEW CHUNG, MAX ALLSTADT, MAX BOGDANOV,\n\n[CRED163]\nMELISSA ÁLVAREZ, MICHAEL MAY, MICHAEL ROTHSTEIN, MIGUEL VIDAL, MIKE FEDERLINE,\n\n[CRED164]\nNATALIE DESCALZO, N'GAI MEMBERS, NICOLAS MALLO, NOELLE SADLER, NORBERT MORIVAN,\n\n[CRED165]\nOSWALD GREENE, JR., PETER MCKAY, PETER APPEL, PRESTON SAVARESE, RAFAEL GONZÁLEZ,\n\n[CRED166]\nRANDY JOHNSON, REY CONCEPCIÓN, RICHARD KROGER, ROB TIBBS, ROBERT JACKSON,\n\n[CRED167]\nROBERT SCHULER, ROSS A. MCINTYRE, RUSSELL FOREMAN, RUTH NÚÑEZ, SALVADORE SUAZO,\n\n[CRED168]\nSAM WHITE, SANTOS GONZÁLEZ, SCOTT SMITH, SEYMOUR FRAILMAN, SPELMAN BRAUMAN,\n\n[CRED169]\nSTEPHANIE TELLING, STEVE KNEZEVICH, STEVE ROBERT, SUMIKO YASUDA, SUSAN LEWIS,\n\n[CRED170]\nSYLVIA COLACIOS, TOMOKO MIYAZAKI, TRON, VERDEL HALE, YVES MONDESIR, ZENO LEINFELDER,\n\n[CRED171]\nDAVID BEDDOES, CHRISTINE CHALMERS, BARRY CLARK, NEIL CORBETT, KIM GURNEY, NEIL MEIKLE,\n\n[CRED172]\nCASSIE OLIVER, LORRAINE ROY, DAVID WATSON, KEVIN WONG, WILL MORTON\n\n[CRED175]\nADAM DAVIDSON\n\n[CRED176]\nLANCE WILLIAMS\n\n[CRED177]\nNEIL MCCAFFREY\n\n[CRED178]\nLAURA PATERSON\n\n[CRED179]\nREY CONCEPCIÓN\n\n[CRED180]\nCHARLES HEROLD\n\n[CRED181]\nANDREW GREENWALD\n\n[CRED182]\nJAMES MIELKE\n\n[CRED183]\nPETER SUCIU\n\n[CRED184]\nALEX ODULIO\n\n[CRED185]\nDON NKRUMAH\n\n[CRED186]\nKENDALL PITTMAN\n\n[CRED187]\nSAL SUAZO\n\n[CRED188]\nEREK MATEO\n\n[CRED189]\nCHRIS DIFATE\n\n[CRED190]\nLEILA MILTON\n\n[CRED191]\nDARREN ZOLTOWSKI\n\n[CRED192]\nVIRGINIA SMITH\n\n[CRED193]\nKEVIN CASSIN\n\n[CRED194]\nJASON SHIGEMORI\n\n[CRED195]\nKELLY KINSELLA\n\n[CRED196]\nMOLLIE STICKNEY\n\n[CRED197]\nSTANTON SARJEANT\n\n[CRED198]\nLAURA WALSH\n\n[CRED199]\nMARK GARONE\n\n[CRED200]\nJOANNA SLY\n\n[CRED201]\nELIZABETH HOWELL\n\n[CRED202]\nANA HÉRCULES\n\n[CRED203]\nSHIRLEY IRICK\n\n[CRED204]\nKASHONA FIELDS\n\n[CRED205]\nJOEL M. LILJE\n\n[CRED206]\nJOHN DIBENEDETTO\n\n[CRED207]\nNANCY GILES\n\n[CRED208]\nRYAN CROY\n\n[CRED209]\nJENNIFER KOLBE\n\n[CRED210]\nLIAM BURKE\n\n[CRED211]\nSIGRID PREISSL\n\n[CRED212]\nANITA FITZSIMONS\n\n[CRED213]\nPHILIPPA RASELLI\n\n[CRED214]\nWIL QUESNEL\n\n[CRED215]\nFALKO BURKERT\n\n[CRED216]\nSARA SEWELL\n\n[CRED217]\nEMISORAS DE RADIO Y MÚSICA\n\n[CRED218]\nASESOR MUSICAL\n\n[CRD218A]\nHEINZ HENN\n\n[CRD218B]\nSTUART ROSS\n\n[CRED219]\nCOORDINADOR DE LA BANDA SONORA\n\n[CRED220]\nTERRY DONOVAN\n\n[CRED221]\nPRODUCTOR DE ROCKSTAR GAMES\n\n[CRED222]\nDAN HOUSER Y LAZLOW\n\n[CRED223]\nPRODUCTOR DE ROCKSTAR NORTH\n\n[CRED224]\nCRAIG CONNER\n\n[CRED225]\nALLAN WALKER\n\n[CRED226]\nLAZLOW\n\n[CRED227]\nDJ BANTER E IMÁGENES\n\n[CRED228]\nESCRITO POR DAN HOUSER Y LAZLOW\n\n[CRED229]\nFLASH FM\n\n[CRD229A]\nTONI-MARIA CHAMBERS\n\n[CRD229B]\nVOCES FICTICIAS Y PRODUCCIÓN-JEFF BERLIN\n\n[CRED230]\nGRACIAS ESPECIALES A\n\n[CRED231]\nTOMMY MOTTOLA,\n\n[CRED232]\nMICHELLE ANTHONY,\n\n[CRED233]\nSTEVE BARNETT,\n\n[CRED234]\nCHUCK FLECKENSTEIN,\n\n[CRED235]\nRITA LIBERATOR\n\n[CRED236]\nMARTIN & CLAIRE LOGAN\n\n[CRED237]\nSANDRA HUTTON\n\n[CRED238]\nCHRISTINE DAVIDSON\n\n[CRED239]\nALAN, RED & BIGFOOT\n\n[CRED240]\nLE T\n\n[CRED241]\nCOLIN DONALD\n\n[CRED242]\nKERRY STALLWOOD\n\n[CRED243]\nALAN MCGREGOR\n\n[CRED244]\nCHRIS MORTON\n\n[CRED245]\nEMIL BUSSE\n\n[CRED246]\nEMILY BAILLIE\n\n[CRED247]\nKEVIN ARCHIBALD\n\n[CRED248]\nMORAG KERR\n\n[CRED249]\nCATH WALKER\n\n[CRED250]\nISO BAR\n\n[CRED251]\nWATERLINE\n\n[CRED252]\nNEWS CAFE\n\n[CRD251A]\nTHE POND\n\n[CRD252A]\nPIVO\n\n[CRED253]\nBUDGET VIDEO RENTALS\n\n[CRED254]\nLORNA'S SCOOTER\n\n[CRED255]\nGARETH MURFIN\n\n[CRED256]\nARTE ADICIONAL\n\n[CRED257]\nTONY PORTER\n\n[CRED258]\nCRAIG MOORE\n\n[CRED259]\nANIMACIÓN DE SINCRONIZACIÓN LABIAL DE LAS SECUENCIAS\n\n[CRED260]\nCOSGROVE HALL FILMS\n\n[CRED261]\nPRODUCTOR - OWEN BALLHATCHET\n\n[CRED262]\nANIMADOR SENIOR - JON TURNER\n\n[CRED263]\nANIMADORES - RICHARD DRUMM\n\n[CRED264]\nDAVE BROWN\n\n[CRED265]\nMAIR THOMAS\n\n[CRED266]\nPRASHANT PATEL\n\n[CRED267]\nASESOR TECNOLOGÍA DE AUDIO\n\n[CRED268]\nRIK EDE PARA GAMESOUND LTD.\n\n[CRED269]\nSOPORTE DTS INTEGRATION\n\n[CRED270]\nTED LAVERTY DE DTS\n\n[CRED271]\nCHRIS GREER DE DTS\n\n[CRED272]\nJASON PAGE DE SCEE\n\n[CRED273]\nINVESTIGACIÓN Y ANÁLISIS\n\n[CRED274]\nVROCK\n\n[CRED275]\nDJ: LAZLOW COMO ÉL MISMO\n\n[CRED276]\nVOZ-JOE KELLY\n\n[CRED277]\nPRODUCCIÓN-JONATHAN HANST\n\n[CRED278]\nWAVE 103\n\n[CRED279]\nDJ: ADAM FIRST-JAMIE CANFIELD\n\n[CRED280]\nVOZ-JEN SWEENEY\n\n[CRED281]\nPRODUCCIÓN-JONATHAN HANST\n\n[CRED282]\nFEVER 105\n\n[CRED283]\nDJ: OLIVER 'LADYKILLER' BISCUIT-JULIUS DYSON\n\n[CRED284]\nVOZ MASCULINA-ED MCMANN\n\n[CRED285]\nVOZ FEMENINA-SHAWNEE SMITH\n\n[CRED286]\nPRODUCCIÓN- LISTEN KITCHEN\n\n[CRED287]\nEMOTION 98.3\n\n[CRED288]\nDJ: FERNANDO- FRANK CHAVEZ\n\n[CRED289]\nVOZ-JEN SWEENEY\n\n[CRED290]\nPRODUCCIÓN-JONATHAN HANST\n\n[CRED291]\nRADIO ESPANTOSO\n\n[CRED292]\nDJ: PEPE-TONY CHILRODES\n\n[CRED293]\nWILDSTYLE\n\n[CRED294]\nDJ: MISTER MAGIC AS HIMSELF\n\n[CRED295]\nVOZ-FRANK SILVESTRO\n\n[CRED296]\nPRODUCCIÓN-LAZLOW\n\n[CRED297]\nKCHAT\n\n[CRED298]\nESCRITO POR DAN HOUSER Y LAZLOW\n\n[CRED299]\nPRODUCIDO Y EDITADO POR LAZLOW\n\n[CRED300]\nDJ AMY SHECKENHAUSEN -LEYNA WEBER\n\n[CRED301]\nJEZ TORRENT-KEVIN MCKIDD\n\n[CRED302]\nMANDY -COLLEEN CORBETT\n\n[CRED303]\nMICHELLE CARAPADIS-MARY BIRDSONG\n\n[CRED304]\nMR.ZOO-CARL DOWLING\n\n[CRED305]\nGETHSEMANEE-LYNN LIPTON\n\n[CRED306]\nCLAUDE MAGINOT-JOHN MAUCERI\n\n[CRED307]\nBJ SMITH-LAWRENCE TAYLOR\n\n[CRED308]\nTHOR-FRANK FAVA\n\n[CRED309]\nPERSONAS LLAMANDO A LA RADIO\n\n[CRED310]\nCOUZIN ED, JOSH CLARK, JASON BUHRMESTER, JUAN ALLER, WAYNE OLIVER, SUSAN LEWIS, GILLIAN TELLING, TOM MURRAY, MIKE FERRANTE SR., EMMANUEL GOLDSTEIN, DAN HOUSER, NICK MANDELOS, GERRY COSGROVE, MIKE PALERMO, PORKCHOP, KEITH BROADAS\n\n[CRED311]\nLEWIS, GILLIAN TELLING, TOM MURRAY, MIKE FERRANTE SR., EMMANUEL GOLDSTEIN,\n\n[CRED312]\nDAN HOUSER, NICK MANDELOS, GERRY COSGROVE, MIKE PALERMO, PORKCHOP,\n\n[CRED313]\nKEITH BROADAS\n\n[CRED314]\nVCPR\n\n[CRED315]\nESCRITO POR DAN HOUSER Y LAZLOW\n\n[CRED316]\nPRODUCIDO POR LAZLOW\n\n[CRED317]\nMAURICE CHAVEZ-PHILLIP ANTHONY RODRIGUEZ\n\n[CRED318]\nJONATHAN FREELOADER- PATRICK OLSEN\n\n[CRED319]\nMICHELLE MONTANIUS-KELLY GUEST\n\n[CRED320]\nREP. ALEX SHRUB- CHRIS LUCAS\n\n[CRED321]\nCALLUM CRAYSHAW- SEAN MODICA\n\n[CRED322]\nJOHN F. HICKORY- LJ GANSEN\n\n[CRED323]\nPASTOR RICHARDS- DAVID GREEN\n\n[CRED324]\nJAN BROWN- MAUREEN SILLIMAN\n\n[CRED325]\nBARRY STARK- RENAUD SEBBANE\n\n[CRED326]\nJENNY LOUISE CRAB- MARY BIRDSONG\n\n[CRED327]\nKONSTANTINOS SMITH- KONSTANTINOS.COM\n\n[CRED328]\nJEREMY ROBARD-PETER SILVESTRO\n\n[CRED329]\nANUNCIOS DE RADIO\n\n[CRED330]\nESCRITOS POR DAN HOUSER Y LAZLOW\n\n[CRED331]\nPRODUCIDOS POR LAZLOW\n\n[CRED332]\nJINGLES ADICIONALES PRODUCIDOS POR CRAIG CONNER\n\n[CRED333]\nVOCES EN LOS ANUNCIOS:\n\n[CRED334]\nADAM DAVIDSON, ALEX ANTHONY, ALICE SALTZMAN, AMY SALZMAN, KATE DUKICH,\n\n[CRED335]\nARAN RONICLE, BARB JONES, BEN KRECH, BRIAN THOMAS, BROCK YODER, CHRIS\n\n[CRED336]\nFERRANTE, CRAIG CONNER, DAVE RYAN, DAVID GREEN, DORIS WOO, DOUGLAS\n\n[CRED337]\nHARRISON, ED MCMANN, FRANK CHÁVEZ, FRANK FAVA, GENE HILGREEN, GREG\n\n[CRED338]\nSCHWEIZER, HUNTER PLATIN, JAMES FERRANTE, JEFF BERLIN, JEFF ROSA, JOE KELLY,\n\n[CRED339]\nJOHN MAUCERI, JOSH CLARK, JULIE WEMYSS, KEVIN STRALEY, KIM GURNEY, LANCE\n\n[CRED340]\nWILLIAMS, LAURA PATERSON, LAZLOW, LISA ORTIZ, LORNA JORDAN, LUCIEN JONES,\n\n[CRED341]\nMAUREEN SILLIMAN, MIKE FERRANTE JR., PETE GUSTIN, PETER SILVESTRO, RAFF\n\n[CRED342]\nCROLLA, RANDY JOHNSON, RICHARD KRUGER, RON REEVE, SHELLEY MILLER, SKY, TJ ALLARD\n\n[CRD344A]\nAUDIO GRABADO EN DIGITAL ARTS STUDIOS,\n\n[CRED344]\nNYC, TRACK 9 STUDIOS, NYC,\n\n[CRED345]\nWEDDINGTON MULTIMEDIA, LOS ANGELES,\n\n[CRD345A]\nSYNC SOUND, NYC Y RADIO LAZLOW, LONG ISLAND.\n\n[CRED346]\nGRACIAS A AXEL ERICSON Y WON LEE EN DIGITAL ARTS, PAUL VÁSQUEZ EN TRACK 9 STUDIOS, JOHN BOWEN Y JOHN HASSLER EN SYNC SOUND\n\n[CRED347]\nMARK LLOYD\n\n[CRED348]\nTIM BATES\n\n[CRED349]\nKIT BROWN\n\n[CRED350]\nANDY MASON\n\n[CRED351]\nPHIL DEANE\n\n[CRED352]\nPHIL ALEXANDER\n\n[CRED353]\nMATT HEWITT\n\n[CRED354]\nDENBY GRACE\n\n[CRED355]\nANTOINE CABROL\n\n[CRED356]\nJONOTHAN STONES\n\n[CRED357]\nMIKE BLACKBURN\n\n[CRED358]\nTIM MCGAFF\n\n[CINCAM]\nCámara cinemática\n\n[RC4]\nMASACRES RUMPO\n\n[LEGAL]\n~g~¡Elimina la amenaza criminal!\n\n[GA_2]\nNuevo motor y trabajo de pintura. ¡Los policías no te reconocerán!\n\n[HELP15]\nCuando vayas a pie, pulsa ~h~~k~~PED_LOOKBEHIND~~w~ para ~h~mirar detrás~w~. Utiliza el ~h~joystick analógico derecho~w~ para ~h~mirar a tu alrededor~w~.\n\n[FEC_LB4]\nMirar detrás (botón R3)\n\n[PERPIC]\nObjetos ocultos encontrados\n\n[CO_ONE]\nObjeto oculto ~1~ de ~1~\n\n[GA_21]\nNo puedes almacenar más coches en este garaje.\n\n[CHEAT1]\nTruco activado\n\n[CHEAT2]\nTruco de arma\n\n[CHEAT3]\nTruco de salud\n\n[CHEAT4]\nTruco de blindaje\n\n[CHEAT5]\nTruco de nivel de se busca\n\n[CHEAT6]\nTruco de dinero\n\n[CHEAT7]\nTruco de tiempo\n\n[USJ_ALL]\n¡TODAS LAS MANIOBRAS ÚNICAS COMPLETADAS!\n\n[JAN]\nEne\n\n[FEB]\nFeb\n\n[MAR]\nMar\n\n[APR]\nAbr\n\n[MAY]\nMay\n\n[JUN]\nJun\n\n[JUL]\nJul\n\n[AUG]\nAgo\n\n[SEP]\nSep\n\n[OCT]\nOct\n\n[NOV]\nNov\n\n[DEC]\nDic\n\n[DEFDT]\n--:---:---- --:--:--\n\n[BONUS]\n~g~BONIFICACIÓN ~1~ $\n\n[HORN1]\nPulsa ~h~~k~~VEHICLE_HORN~~w~para tocar el ~h~claxon.\n\n[HORN2]\nPulsa ~h~~k~~VEHICLE_HORN~~w~para tocar el ~h~claxon.\n\n[HORN3]\nPulsa ~h~~k~~VEHICLE_HORN~~w~para tocar el ~h~claxon.\n\n[FEC_EXV]\nEntrar y salir de vehículo\n\n[TAXI_M]\n'TAXISTA'\n\n[COP_M]\n'JUSTICIERO'\n\n[FIRE_M]\n'BOMBERO'\n\n[AMBUL_M]\n'ATS'\n\n[HJ_IS]\nBONIFICACIÓN POR ACROBACIA: ~1~ $\n\n[HJ_PIS]\nBONIFICACIÓN POR ACROBACIA PERFECTA: ~1~ $\n\n[HJ_DIS]\nBONIFICACIÓN POR ACROBACIA DOBLE: ~1~ $\n\n[HJ_PDIS]\nBONIFICACIÓN POR ACROBACIA DOBLE PERFECTA: ~1~ $\n\n[HJ_TIS]\nBONIFICACIÓN POR ACROBACIA TRIPLE: ~1~ $\n\n[HJ_PTIS]\nBONIFICACIÓN POR ACROBACIA TRIPLE PERFECTA: ~1~ $\n\n[HJ_QIS]\nBONIFICACIÓN POR ACROBACIA CUÁDRUPLE: ~1~ $\n\n[HJ_PQIS]\nBONIFICACIÓN POR ACROBACIA CUÁDRUPLE PERFECTA: ~1~ $\n\n[FESZ_LS]\nCarga completada con éxito.\n\n[HELI_1A]\nPrueba tus habilidades con el Sparrow, comprueba lo rápido que puedes completar el circuito.\n\n[HELI_1B]\n¡Circuito completado! ~1~ $\n\n[HELIODD]\nTrabajos esporádicos del helicóptero\n\n[LAW]\nLAS MISIONES DEL ABOGADO\n\n[LAW1_1]\n~g~Consigue unos trapos nuevos en la tienda de ropa de Rafael.\n\n[LAW4_6]\n¡Quemad la dirección!\n\n[LAW4_7]\n¡Matad a los jefes!\n\n[LAW4_8]\nLuchad, luchad, luchad, luchad.\n\n[LAW4_9]\n¡Más vacaciones, menos trabajo!\n\n[LAW4_11]\n¡Luchad! ¡Luchad! ¡Luchad! ¡Luchad!\n\n[LAW4_12]\n¡Viva la revolución!\n\n[GENERAL]\nLAS MISIONES DEL CORONEL\n\n[GEN3_4]\nTommy Vercetti. Vamos...\n\n[GEN3_13]\n¿Cuál es tu problema, tío? ¡Sube al tejado al otro lado del patio antes de que aparezcan!\n\n[GEN3_17]\n¡Mierda! ¿Intentas matarme?\n\n[GEN3_21]\n~g~¡Tiene el dinero de Díaz! ¡Ve tras él y recupéralo!\n\n[GEN3_24]\n~r~¡Díaz murió! ¡Has fracasado al protegerle!\n\n[GEN3_26]\n~r~¡Le pegaste un tiro a Díaz!\n\n[GEN3_27]\n~r~¡Disparaste a los guardaespaldas de Díaz!\n\n[GEN3_31]\n~g~Ahora ve al punto de entrega y cuida de Díaz.\n\n[GEN3_32]\n~g~Ve a tu posición elevada en el tejado del edificio opuesto a donde está Lance.\n\n[COKE]\nLAS MISIONES DEL BARÓN DE LA NIEVE\n\n[COK1_3]\n¡Espero que te caigas y te rompas el cuello!\n\n[COK1_6]\nEstoy cansado de estos mamones.\n\n[COK2_7]\n¿Veis esos marcadores chicos? ¡Probad a dar a las luces!\n\n[COK2_10]\nDesde luego eres mejor disparando que charlando.\n\n[COK2_11]\nGracias. Eres un verdadero encanto.\n\n[COK2_12]\nLo sé, Tommy.\n\n[COK2_18]\n¿Te gusta Kenny Loggins?\n\n[COK2_19]\nDios, ¡me encanta este disco!\n\n[COK2_26]\n~r~¡Mataste a Lance!\n\n[COK3_1]\n¡No dispares tío!\n\n[COK3_2]\n¿Qué hay ahí?\n\n[COK3_3]\nSe está llevando el barco. Gorrón.\n\n[COK3_4]\n¡Ayuda! ¡Un tipo me está robando el barco, tío!\n\n[COK4_W]\n¡Uugghh! Ése era el último.\n\n[COK4_X]\nVoy a arrancarlo\n\n[COK4_Y]\nCreo que tenemos algunos amigos nuevos.\n\n[COK4_2]\nSí.\n\n[COK4_6]\n¿A dónde crees que vamos?\n\n[COK4_7]\n¿Nos hemos perdido?\n\n[COK4_8]\n¡Tenemos competencia!\n\n[COK4_9]\n¡Elimínales!\n\n[COK4_9A]\n¡Es hora del baile de Lance Vance!\n\n[COK4_10]\n¡Ya son astillas! Y comida para los peces.\n\n[COK4_11]\n¡Lo conseguimos! Esos otros barcos no son de la clase VIP.\n\n[COK4_17]\n¡Se están desesperando!\n\n[COK4_18]\n¡Mis malditos pies están mojados! ¡NOS ESTÁ ENTRANDO AGUA!\n\n[COK4_21]\n¡Subiendo el puente!\n\n[COK4_22]\n¡Salta, está apunto de estallar!\n\n[COK4_23]\nBuen disparo.\n\n[COK4_29]\n~r~¡Mataste a Lance!\n\n[ASS1_6]\n¡Adelante Tommy, yo estaré bien!\n\n[ASS1_7]\n¡Comeos esto, asesinos hijos de puta!\n\n[ASS1_8]\n¡Me han dado!\n\n[ASS1_9]\n¡Te tengo cubierto, Tommy!\n\n[ASS1_10]\nEh, este seto es precioso.\n\n[ASS1_11]\nTommy, ¿puedo tener una habitación con vistas a la bahía?\n\n[ASS1_12]\nUnos techos altos muy bonitos...\n\n[ASS1_3]\n¡Lance! ¡Necesito que me cubras!\n\n[ASS1_4]\n¡Díaz debe de estar dentro!\n\n[ASS1_5]\n¡Lance!\n\n[TAXWAR]\nMISIONES DE LA GUERRA DE TAXIS\n\n[NOTAXI]\n~g~Necesitas un Taxi Kaufman para activar esta misión.\n\n[TAXW1_5]\n~g~¡Necesitas estar en un taxi Kaufman!\n\n[TAX2_4]\nAdelante, Tommy.\n\n[TAX2_5]\nDale una buena paliza.\n\n[TAX2_6]\nNi siquiera tiene licencia.\n\n[TAX2_7]\nMalditos servicios de limusina.\n\n[TAXW3_1]\n~g~Ve y recoge a Mercedes.\n\n[RACE1]\n~g~3..2..1.. ¡VAMOS VAMOS VAMOS!\n\n[RACE2]\n~g~3\n\n[RACE3]\n~g~2\n\n[RACE4]\n~g~1\n\n[RACE5]\n~g~¡ADELANTE!\n\n[FIRST]\n~b~1\n\n[SECOND]\n~b~2\n\n[THIRD]\n~b~3\n\n[FOURTH]\n~b~4\n\n[RACETM]\n~b~TIEMPO DE CARRERA: ~1~:~1~\n\n[RACETM2]\n~b~TIEMPO DE CARRERA: ~1~:0~1~\n\n[RACEFA]\n~r~¡Has fracasado en ganar la carrera!\n\n[HOTRNG]\nHOTRING\n\n[BLODRNG]\nBLOODRING\n\n[DIRTRNG]\nDIRTRING\n\n[TEX1_5]\n~r~¡Se escapó!\n\n[SEG3_1]\nTIEMPO:\n\n[SEG3_2]\n~g~Ve a la camioneta que contiene el Helicótero RC y las bombas por control remoto con temporizador.\n\n[SEG3_3]\n~g~Debes emplear el Helicótero RC para transportar 4 bombas hasta 4 objetivos en lugar del edificio.\n\n[SERG3_5]\n~g~Sólo puedes llevar una bomba en cada ocasión y no puedes recoger bombas colocadas con éxito.\n\n[SEG3_7]\n~g~Una vez que hayas soltado con éxito la PRIMERA bomba sobre una zona del objetivo, el cronómetro de detonación se pondrá en marcha; de modo que tendrás que soltar todas las bombas dentro de este período de tiempo.\n\n[SEG3_8]\n~g~Las 4 bombas deben estar colocadas en las 4 zonas objetivo para superar la misión y demoler el edificio.\n\n[SEG3_9]\n~g~¡Alcanzaste el objetivo! Quedan 3.\n\n[SEG3_10]\n~g~¡Alcanzaste el objetivo! Quedan 2.\n\n[SEG3_11]\n~g~¡Alcanzaste el objetivo! ¡Sólo queda 1!\n\n[SEG3_12]\n~r~¡Fallaste el blanco! ¡Ve a por una bomba!\n\n[SEG3_13]\n~g~Deja caer la bomba en una zona del objetivo.\n\n[SEG3_14]\n~r~Te quedaste sin tiempo y fracasaste en demoler el edificio.\n\n[SEG3_15]\n~r~¡Tu Helicótero RC ha sido destruido! ¿Cómo vas a transportar las bombas ahora?\n\n[AVERY]\nMISIONES DE AVERY\n\n[ASM]\nMISIONES DE ASESINO\n\n[ASM_1]\nMISIÓN DE ASESINO 1\n\n[ASM1_1]\n~g~Sr. Teal, su ayuda en la eliminación de los forasteros fue inestimablemente buena para el negocio. Tengo más trabajo para usted y más próximo a la ''intervención''. Encontrará su siguiente trabajo pegado con cinta adhesiva bajo el teléfono.\n\n[ASM1_2]\n~g~Ve a la cabina telefónica que hay frente al centro comercial de Washington.\n\n[ASM1_3]\n~g~Carl Pearson, un repartidor de pizza. No debe finalizar sus entregas.\n\n[ASM1_4]\n~g~Elimina al repartidor de pizza antes de que complete sus entregas.\n\n[ASM_2]\nMISIÓN DE ASESINO 2\n\n[ASM_3]\nMISIÓN DE ASESINO 3\n\n[ASM3_1]\n~g~Ve a coger el arma que el Sr. Black ha dejado para ti.\n\n[ASM3_2]\n~g~No te acerques demasiado al objetivo o podría verte.\n\n[ASM3_3]\n~g~Para un trabajo más rápido, colócate en lugares cercanos a su ubicación y evita ser visto. Esto te proporcionará una buena posición para eliminarles.\n\n[ASM3_4]\n~g~¡Te ha visto! ¡Mejor elimínale de cualquier modo que puedas!\n\n[ASM3_5]\n~g~Marcus Hammond está situado cerca de los anuncios de Washington.\n\n[ASM3_6]\n~g~Franco Carter está situado en el DBP de Seguridad, cerca de Ocean Drive.\n\n[ASM3_7]\n~g~Dick Tanner está cerca de la joyería de Vice Point.\n\n[ASM3_8]\n~g~Nick Kong está colocado cerca de Washington Beach.\n\n[ASM3_9]\n~g~El conductor está situado en Washington.\n\n[ASM3_10]\n~r~Fallaste en matarles a todos.\n\n[ASM_4]\nMISIÓN DE ASESINO 4\n\n[ASM4_1]\n~g~Ve a por el rifle que te han dejado entre el follaje que hay en las cercanías de la terminal del aeropuerto.\n\n[ASM4_2]\n~g~No falles tu blanco o podrías alertar a sus guardaespaldas, y recuerda mantener las distancias para que no te detecte.\n\n[ASM4_3]\n~g~Vigila a la mujer de la galería que hay sobre los mostradores de facturación, dentro de la terminal del aeropuerto. PERO NO LA MATES.\n\n[ASM4_4]\n~g~Mata al hombre al que ella dé el maletín, pero sólo DESPUÉS DE QUE ÉSTE LO RECOJA. Entonces recupera el maletín y llévalo a Ammu-Nation en el centro de la ciudad.\n\n[ASM4_5]\n~g~¡Consigue el maletín!\n\n[ASM4_6]\n~g~Lleva al maletín a Ammu-Nation en el centro de la ciudad.\n\n[ASM4_7]\n~r~¡Estúpido, has matado a la mujer!\n\n[ASM4_8]\n~r~¡El blanco te oyó disparar el arma! ¡El trato queda anulado!\n\n[ASM4_9]\n~r~¡El blanco ha embarcado en su vuelo!\n\n[ASM4_11]\n~r~¡El blanco te ha visto! ¡El trato queda anulado!\n\n[ASM4_13]\n~g~Te ha visto y está huyendo, ¡atrápale y consigue el maletín!\n\n[ASM4_14]\n~g~La barra de distancia en la parte superior derecha de la pantalla te proporciona una indicación de lo cerca que estás de tu blanco. No permitas que se llene o éste te verá.\n\n[ASM_5]\nMISIÓN DE ASESINO 5\n\n[KICK]\nARRANQUE\n\n[KICK1_3]\n~g~Número de veces que pusiste el pie: ~1~\n\n[KICK1_4]\n~g~Tiempo de penalización: ~1~ segundos\n\n[BANK]\nMISIONES DEL ATRACO AL BANCO\n\n[BANK1]\nMISIÓN DE ATRACO AL BANCO 1\n\n[BANK2]\nMISIÓN DE ATRACO AL BANCO 2\n\n[BJM2_21]\n~g~Acierta a tantos blancos como puedas mientras te quede munición.\n\n[BANK3]\nMISIÓN DE ATRACO AL BANCO 3\n\n[BJM3_1]\n~g~Consigue un coche rápido y ve a la parrilla de salida.\n\n[BNK4_2A]\nLos chicos hicieron un trabajo genial con este pequeño.\n\n[BNK4_3G]\n¡Oh, mierda, ahora los polis andan tras nosotros!\n\n[BNK4_3H]\nY ni siquiera hemos llegado.\n\n[BNK4_3K]\nPrimero tendremos que despistar a los polis...\n\n[BNK4_3L]\nJoder, Tommy, ¿intentas matarnos a todos?\n\n[BNK4_3N]\n¡Todo lo que me importa acaba destrozado!\n\n[BNK4_26]\n¡Maldición! ¡Aquí vienen!\n\n[BNK4_32]\n¡Usa los explosivos para abrir las cajas de depósito!\n\n[BNK4_36]\n¿Dónde está Cam?\n\n[BNK4_37]\nEs historia...\n\n[BNK4_38]\nÉse era el último. ¡Vamos! ¡Vamos! ¡Vamos!\n\n[BNK_39]\n¡Mierda! ¿Dónde está Hilary?\n\n[BK4_40A]\n¡Ya le daré yo miedo al abandono!\n\n[BNK4_42]\n¡Eh, tíos! ¡Subid! ¡Yo os cubro!\n\n[BNK4_43]\n¡Ya cubro yo nuestros culos, tú conduce!\n\n[BNK4_44]\n¡Lo conseguimos! ¡Somos ricos! ¡Ricos!\n\n[BNK4_45]\nEs una pena que Cam no lo consiguiese, ¡era un buen tipo!\n\n[BNK4_46]\nSí. Pero aún así... ¡más tajada para nosotros!\n\n[BNK4_47]\n¡Claro que sí! ¡Sí!\n\n[BNK4_48]\nTommy, ¿te gustaría un masaje?\n\n[BNK4_49]\n¡Hola, Mercedes! Sí, estoy un poco tenso...\n\n[BNK450A]\n¿Qué te dije, Tommy? ¿Qué te dije? Maldito SWAT, será mejor que tengas cuidado cuando Kent Paul esté en la ciudad.\n\n[BNK450B]\nVamos, dame una tajada más grande, colega, venga. Tengo que comprarme ropa nueva.\n\n[BNK4_51]\nYo creo que tienes buen aspecto.\n\n[KENT]\nMISIONES DE KENT PAUL\n\n[KENT1]\nMISIÓN DE KENT PAUL 1\n\n[COUNT]\nMISIONES DE FALSIFICACIÓN\n\n[COUNT1]\nMISIÓN DE FALSIFICACIÓN 1\n\n[COUNT2]\nMISIÓN DE FALSIFICACIÓN 2\n\n[BIKE]\nLAS MISIONES DE LA PANDILLA DE MOTEROS\n\n[BIKE1]\nMISIÓN DE MOTORISTA 1\n\n[BIKE2]\nMISIÓN DE MOTORISTA 2\n\n[BIKE3]\nMISIÓN DE MOTORISTA 3\n\n[GOAWAY1]\nVuelve cuando hayas terminado con las misiones de la banda haitiana.\n\n[HAIT]\nLAS MISIONES DE LA BANDA HAITIANA\n\n[HAIT1]\nMISIÓN HAITIANA 1\n\n[HAIT2]\nMISIÓN HAITIANA 2\n\n[HAIT3]\nMISIÓN HAITIANA 3\n\n[HAM3_6]\n~g~Utiliza el rifle de francotirador que te he dejado para cumplir tu tarea.\n\n[ROCK]\nLAS MISIONES DE LA BANDA DE ROCK\n\n[ROK1_4]\n~g~De acuerdo, creo que esto es lo que andabais buscando...\n\n[ROK1_1E]\n~g~¡Costará más de lo que tienes!\n\n[ROK1_1F]\n~g~Vuelve cuando tengas el dinero.\n\n[RBM2_6]\n~g~¡Guau! ¡Ella es un tío, detenle!\n\n[ROCK3]\nMISIONES DE LA BANDA DE ROCK 3\n\n[RBM3_5]\n~g~Lleva a los Love Fist al escenario.\n\n[CUBANM]\nLAS MISIONES DE LA BANDA CUBANA\n\n[CUBAN1]\nMISIÓN CUBANA 1\n\n[CUBAN2]\nMISIÓN CUBANA 2\n\n[CUB2_10]\n~r~¡Se supone que debes matar a haitianos, no a cubanos!\n\n[CUBAN3]\nMISIÓN CUBANA 3\n\n[CUBAN4]\nMISIÓN CUBANA 4\n\n[PROT]\nMISIONES DE PROTECCIÓN\n\n[PORN]\nMISIONES PORNO\n\n[PORN1]\nMISIÓN PORNO 1\n\n[POR1_03]\n~r~¡Candy está muerta!\n\n[PORN2]\nMISIÓN PORNO 2\n\n[PORN3]\nMISIÓN PORNO 3\n\n[PORN4]\nMISIÓN PORNO 4\n\n[PHIL]\nMISIONES DE PHIL\n\n[PHIL1]\nMISIÓN DE PHIL 1\n\n[PHIL2]\nMISIÓN DE PHIL 2\n\n[PIZ1_A]\nMISIÓN DEL REPARTIDOR DE PIZZAS\n\n[CNTBUY1]\nCompra de la imprenta: ~1~ $\n\n[CARBUY]\nCompra del salón de coches: ~1~ $\n\n[PORNBUY]\nCompra del estudio cinematográfico: ~1~ $\n\n[ICEBUY]\nCompra de la fábrica de helados: ~1~ $\n\n[TAXIBUY]\nCompra de la empresa de taxis: ~1~ $\n\n[BANKBUY]\nCompra del Malibú: ~1~ $\n\n[BOATBUY]\nCompra del astillero: ~1~ $\n\n[PRNT_NO]\nNo puedes comprar la imprenta en este momento, vuelve más tarde.\n\n[CAR_NO]\nNo puedes comprar el salón de coches en este momento, vuelve más tarde.\n\n[PORN_NO]\nNo puedes comprar el estudio cinematográfico en este momento, vuelve más tarde.\n\n[ICE_NO]\nNo puedes comprar la fábrica de helados en este momento, vuelve más tarde.\n\n[TAXI_NO]\nNo puedes comprar la compañía de taxis en este momento, vuelve más tarde.\n\n[BANK_NO]\nNo puedes comprar el Malibú en este momento, vuelve más tarde.\n\n[BOAT_NO]\nNo puedes comprar el astillero en este momento, vuelve más tarde.\n\n[COL2_6]\n¡Alto, cerdo imperialista americano!\n\n[COL2_6B]\nEso es propiedad del gobierno francés.\n\n[COL2_6C]\n¡y se acabó!\n\n[COL3_A]\nThomas, aprecio que vinieses.\n\n[COL3_B]\nPerdóname por ir directamente al asunto.\n\n[COL3_C]\nDiaz me ha pedido que supervise una transacción de un negocio menor.\n\n[COL3_D]\nEsperemos que vaya mejor que la última vez.\n\n[COL3_E]\nPor eso es por lo que pensé en ti, amigo mío.\n\n[COL3_F]\nHe dejado algo de protección en el aparcamiento.\n\n[COL3_G]\nRecógele y luego id a ver a los hombres de Diaz en el punto de entrega.\n\n[COL4_2]\n¡No lo sé, señor!\n\n[COL4_5]\n¡Señor, sí, señor!\n\n[COL4_10]\nVamos a comer unos donuts.\n\n[COL4_16]\n¡Señor! ¡Moviendo el vehículo, señor!\n\n[COL4_25]\n¡Iniciada autodestrucción del vehículo!\n\n[COL5_6]\nMercedes, esa chica me matará.\n\n[COL5_8]\n¡Maldita cucaracha!\n\n[COL5_5]\n¡Morid, cerdos franceses!\n\n[CNT2_1]\nMatadle.\n\n[CNT2_2]\n¡Conseguid las planchas!\n\n[CNT2_3]\n¡Proteged al mensajero!\n\n[FINKILL]\n¡De acuerdo, chicos, matadle!\n\n[FIN_1A]\n¡Ven aquí, traidor, pedazo de mierda!\n\n[FIN_1B]\n¡Vas a caer, mamón traicionero!\n\n[FIN_1C]\n¡Éste es el último baile para Lance Vance!\n\n[FIN_2B]\n¡Oh, eso crees tú!\n\n[FIN_2C]\n¡Ya tuve suficiente de eso en la escuela!\n\n[FIN_3]\nAhora no hay nadie para cubrirte el trasero, ¿eh, Tommy?\n\n[FIN_4]\nEres historia, Tommy, historia.\n\n[FIN_5]\nEscogiste el lado equivocado, Lance...\n\n[FIN_6]\nSonny está arriba con la caja fuerte y mi dinero...\n\n[FIN_10]\n¿Sonny? ¡Sonny! ¡Voy por ti!\n\n[FIN_11A]\nMe arrebataste quince años, Sonny...\n\n[FIN_11B]\n¡Y ahora voy a hacértelo pagar!\n\n[FIN_12A]\nTodavía no lo captas, ¿verdad?\n\n[FIN_12B]\nEres de mi propiedad, Tommy.\n\n[FIN_12C]\n¡Esos quince años eran míos para gastarlos!\n\n[FIN_13]\nAtrapadle chicos, nunca comprendió nada.\n\n[RACES_4]\n3\n\n[RACES_5]\n2\n\n[RACES_6]\n1\n\n[RACES_7]\n¡ADELANTE!\n\n[RACES_9]\nTiempo: ~1~:~1~\n\n[RACES]\nTIEMPO:\n\n[RACES17]\nNuevo mejor tiempo: ~1~:~1~\n\n[RACES18]\nHAS GANADO: ~1~ $\n\n[RACES20]\nNuevo mejor tiempo: ~1~:0~1~\n\n[RACES21]\nTiempo: ~1~:0~1~\n\n\n[RCH1_2]\n~g~Los CONTROLES están esparcidos a lo largo del aeropuerto.\n\n[RCH1_5]\nTiempo:\n\n[RCRC1_2]\n~g~¡Ve a la parrilla de salida!\n\n[RCRC1_4]\n~g~3\n\n[RCRC1_5]\n~g~2\n\n[RCRC1_6]\n~g~1\n\n[RCRC1_7]\n~g~¡ADELANTE!\n\n[RCRC1_8]\n~g~Tiempo de carrera: ~1~ segundos\n\n[RCPL1_1]\n~g~Compite en una CARRERA DE PUNTOS DE CONTROL con otros tres Barón RC.\n\n[RCPL1_2]\n~g~Debes atravesar la ~o~CORONA DEL CENTRO ~g~para pasar con éxito un punto de control.\n\n[RCPL1_3]\n~g~¡Ve ahora a la parrilla de salida!\n\n[ICC1_O]\n¿Qué pasa contigo?\n\n[FEA_2SP]\n2 altavoces\n\n[FEA_4SP]\nMás de 2 altavoces\n\n[FEA_EAR]\nAuriculares\n\n[FEA_NAH]\nNO HAY HARDWARE DE AUDIO\n\n[FET_APP]\nAPLICAR\n\n[FES_SKN]\nNOMBRE DE APARIENCIA\n\n[FES_DAT]\nFECHA\n\n[FES_SET]\nUtilizar apariencia\n\n[FET_DEF]\nRestaurar valores por defecto\n\n[FESZ_QZ]\n¿Seguro de que quieres guardar esta partida?\n\n[FES_SCG]\n¿Guardar la partida actual?\n\n[FES_LCG]\n¿Cargar la partida y continuar jugando?\n\n[FEC_FIR]\nDisparar\n\n[FEC_NWE]\nSiguiente arma\n\n[FEC_PWE]\nArma anterior\n\n[FEC_FOR]\nAvanzar\n\n[FEC_BAC]\nRetroceder\n\n[FEC_LEF]\nIzquierda\n\n[FEC_RIG]\nDerecha\n\n[FEC_ZIN]\nAcercar zoom\n\n[FEC_ZOT]\nAlejar zoom\n\n[FEC_EEX]\nEntrar y salir\n\n[FEC_RAD]\nRadio\n\n[FEC_SUB]\nMisión secundaria\n\n[FEC_CMR]\nCambiar cámara\n\n[FEC_JMP]\nSaltar\n\n[FEC_SPN]\nEsprintar\n\n[FEC_HND]\nFreno de mano\n\n[FEC_LOL]\nMirar hacia la izquierda\n\n[FEC_LOR]\nMirar hacia la derecha\n\n[FEC_NTR]\nSiguiente objetivo\n\n[FEC_PTT]\nObjetivo anterior\n\n[FEC_LBA]\nMirar detrás\n\n[FEC_CEN]\nCentrar cámara\n\n[FET_CFT]\nA PIE\n\n[FET_CCR]\nEN COCHE\n\n[FET_CAC]\nACCIÓN\n\n[FEC_IBT]\n-\n\n[FEC_MXO]\nMXB1\n\n[FEC_MXT]\nMXB2\n\n[FEC_UNB]\nILIMITADO\n\n[FEC_TFL]\nMirar a izquierd+Torreta L\n\n[FEC_TFR]\nMirar a derecha+Torreta R\n\n[FEC_MWF]\nRUEDA DEL RATÓN ARRIBA\n\n[FEC_MWB]\nRUEDA DEL RATÓN ABAJO\n\n[FEC_ORR]\no\n\n[FEC_NUS]\nNO UTILIZADO\n\n[FEC_LUD]\nMirar arriba\n\n[FEC_LDU]\nMirar abajo\n\n[FEC_CMP]\nCOMBO: MIRAR I+d\n\n[LAW_1A]\nlaw_1a\n\n[LAW_1B]\nlaw_1b\n\n[LAW_2A]\nlaw_2a\n\n[LAW_2B]\nlaw_2b\n\n[FEH_STA]\nESTADÍSTICAS\n\n[FEH_LOA]\nCARGAR\n\n[FEH_CON]\nCONTROLES\n\n[FEH_AUD]\nSONIDO\n\n[FEH_DIS]\nPANTALLA\n\n[FEH_LAN]\nIDIOMA\n\n[FEH_SGA]\nINICIAR NUEVA PARTIDA\n\n[FEO_CON]\nConfiguración del mando\n\n[FEO_AUD]\nConfiguración de sonido\n\n[FEO_DIS]\nConfiguración de pantalla\n\n[FEO_LAN]\nConfiguración de idioma\n\n[FEO_PLA]\nConfiguración del jugador\n\n[FET_PS]\nCONFIGURACIÓN DE APARIENCIA\n\n[FEA_OUT]\nSalida\n\n[FEA_ST]\nEstéreo\n\n[FEA_DTS]\nDTS\n\n[FEA_RSS]\nEmisora de radio\n\n[FEA_NON]\nRADIO APAGADA\n\n[FEA_FM0]\nWILDSTYLE\n\n[FEA_FM1]\nFLASH FM\n\n[FEA_FM2]\nKCHAT\n\n[FEA_FM3]\nFEVER 105\n\n[FEA_FM4]\nVROCK\n\n[FEA_FM5]\nVCPR\n\n[FEA_FM7]\nEMOTION 98.3\n\n[FEA_FM8]\nWAVE 103\n\n[FED_BRI]\nBrillo\n\n[FED_TRA]\nEstelas\n\n[FED_SUB]\nSubtítulos\n\n[FED_WIS]\nFormato 16:9\n\n[FED_POS]\nPosición de la pantalla\n\n[FED_RDR]\nRADAR\n\n[FED_HUD]\nMODO HUD\n\n[FED_RDB]\nSOLO ICONOS\n\n[FE_MLG]\nLEYENDA DEL MAPA\n\n[FEI_SCR]\nDesplazarse\n\n[FEP_RES]\nContinuar\n\n[FEP_STG]\nIniciar partida\n\n[FEP_STA]\nEstadísticas\n\n[FEP_BRI]\nResumen\n\n[FEP_OPT]\nOpciones\n\n[FEP_QUI]\nSalir del juego\n\n[FES_LOA]\nCargar partida\n\n[FES_DEL]\nBorrar partida\n\n[FEC_CSU]\nConfiguración del controlador\n\n[FEC_RED]\nRedefinir controles\n\n[FEC_MOU]\nConfiguración del ratón\n\n[DISTGOL]\nDistancia recorrida en carro de golf (millas)\n\n[DISTGOM]\nDistancia recorrida en carro de golf (m)\n\n[ST_FAVR]\nEstación de radio favorita\n\n[ST_WSTR]\nestación de radio que menos te gusta\n\n[ST_FAVV]\nVehículo favorito\n\n[ST_STAR]\nNúmero total de estrellas se busca conseguidas\n\n[ST_HEAD]\nNúmero de disparos a la cabeza\n\n[ST_GANG]\nBanda que menos te gusta\n\n[ST_STGN]\nNúmero total de estrellas se busca evadidas\n\n[TYREPOP]\nNeumáticos reventados por disparos\n\n[TYRESLA]\nNeumáticos rajados con una navaja\n\n[ST_BRK]\nNúmero de muertes en el anillo sangriento\n\n[ST_LTBR]\nMayor tiempo en el anillo sangriento (segs.)\n\n[ST_GNG1]\nCubanos\n\n[ST_GNG2]\nHaitianos\n\n[ST_GNG3]\nAspirantes callejeros\n\n[ST_GNG4]\nPandilleros de Díaz\n\n[ST_GNG5]\nGuardias de seguridad\n\n[ST_GNG6]\nBanda de motoristas\n\n[ST_GNG7]\nBanda de Vercetti\n\n[ST_GNG8]\nGolfistas\n\n[FEA_FM6]\nESPANTOSO\n\n[ST_ASSI]\nContratos de asesinato completados\n\n[DISTBIK]\nDist. Recorrida en moto (millas)\n\n[DISTBIM]\nDistancia recorrida en moto (m)\n\n[HOTEL]\nOcean View\n\n[KICK1_9]\nPUNTOS DE CONTROL:\n\n[FIN_B6]\nNo tienes suficiente dinero para empezar esta misión.\n\n[TEX3_9]\n~g~Recoge una bomba pasando con el helicóptero RC cerca de ella.\n\n[HELP22]\nVe a la señal de la casa verde que hay en el radar.\n\n[FES_FMS]\nÉxito al formatear. Selecciona Aceptar para continuar.\n\n[FES_SSC]\nÉxito al guardar. Selecciona Aceptar para continuar.\n\n[FES_DSC]\nÉxito al borrar. Selecciona Aceptar para continuar.\n\n[FESZ_QC]\n¿Deseas sobreescribir esta partida guardada dañada?\n\n[FES_CHE]\n¡Atención! Se han activado uno o más trucos, esto puede afectar a tus partidas guardadas. Te recomendamos no guardar esta partida.\n\n[FET_SG]\nGUARDAR PARTIDA\n\n[FEH_BRI]\nINFORME\n\n[FEH_MAP]\nMAPA\n\n[FEM_OK]\nAceptar\n\n[FEC_CRO]\nAgacharse\n\n[FEC_CR3]\nAgacharse (Botón L3)\n\n[FEC_SMT]\nSub-misión\n\n[FEC_SM3]\nSub-misión (Botón R3)\n\n[FEC_RSC]\nEmisoras de radio\n\n[ST_PR01]\nAviador\n\n[ST_PR02]\nPiloto del ejército\n\n[ST_PR03]\nOficial piloto\n\n[ST_PR04]\nCabo\n\n[ST_PR05]\nTeniente\n\n[ST_PR06]\nSargento\n\n[ST_PR07]\nCapitán\n\n[ST_PR08]\nBiggs\n\n[ST_PR09]\nWedge\n\n[ST_PR10]\nBarón Rojo\n\n[ST_PR11]\nGanso\n\n[ST_PR12]\nVíbora\n\n[ST_PR13]\nJester\n\n[ST_PR14]\nChappy\n\n[ST_PR15]\nIceman\n\n[ST_PR16]\nMaverick\n\n[ST_PR17]\nNegado\n\n[ST_PR18]\nGeneral de la Armada aérea\n\n[ST_PR19]\nAs\n\n[FET_LG]\nCARGAR JUEGO\n\n[CAR_EXP]\nVehículos destruidos\n\n[BOA_EXP]\nBarcos destruidos\n\n[HEL_DST]\nAviones y helicópteros destruidos\n\n[STFT_01]\nTiempo más rápido de ''Moto con llantas de aleación''\n\n[STFT_02]\nTiempo más rápido de ''El conductor''\n\n[STFT_03]\nTiempo más rápido en el Circuito de Tierra\n\n[STFT_04]\nTiempo más rápido en la Carrera de Aviones RC\n\n[STFT_05]\nTiempo más rápido en la Carrera de Coches RC\n\n[STFT_06]\nTiempo más rápido Control del Helicóptero RC\n\n[STFT_07]\nTiempo más rápido en ''Velocidad terminal''\n\n[STFT_08]\nTiempo más rápido en ''Ocean Drive''\n\n[STFT_09]\nTiempo más rápido en ''Carrera por el borde''\n\n[STFT_10]\nTiempo más rápido en ''Capital Cruise''\n\n[STFT_11]\nTiempo más rápido en ''¡Tour!''\n\n[STFT_12]\nTiempo más rápido en ''Aguante en V.C.''\n\n[STHC_01]\nPuntuación más alta en el campo de tiro\n\n[STHC_02]\nMejor porcentaje de impactos en el campo de tiro\n\n[STHC_03]\nVentas de droga realizadas\n\n[HELP24]\nAhora puedes aceptar trabajos del Coronel.\n\n[HELP25]\nAhora puedes aceptar trabajos de Avery Carrington.\n\n[HELP29]\nPuedes visitar la tienda de ropa cuando no estés en una misión.\n\n[HELP30]\nCuando compres ropa nueva, tu nivel de se busca se establecerá en cero.\n\n[ASM4_24]\ndistancia:\n\n[RBM1_6]\n~g~Lleva a Mercedes y el ''love juice'' a la banda en el estudio de grabación.\n\n[HELP31]\nPara hacer una pasada, mira primero a izquierda o derecha con ~k~~VEHICLE_LOOKLEFT~ o ~k~~VEHICLE_LOOKRIGHT~.\n\n[HELP34]\nPara realizar una pasada deberás tener un subfusil.\n\n[STRIP_1]\n~r~No tienes dinero suficiente, tacaño miserable.\n\n[EXIT_1]\nPulsa ~k~~PED_SPRINT~ para salir.\n\n[ASM1_B]\nEncontrará su siguiente trabajo pegado con cinta adhesiva bajo el teléfono.\n\n[ASM1_C]\nTengo más trabajo para usted que requerirá tomar ''el volante'' de la situación.\n\n[SCARF]\nApartamento 3c\n\n[LAW4_10]\n¡Mamones de directores!\n\n[RCH1_6]\n~g~Utiliza el helicóptero RC para pasar por los puntos de control dispersados por el aeropuerto.\n\n[RCH1_9]\n~b~TIEMPO TOTAL: ~1~:~1~\n\n[RCH1_10]\n~b~TIEMPO TOTAL: ~1~:0~1~\n\n[WHEEL01]\nDOBLE BONIFICACIÓN EN DOS RUEDAS: ~1~ $ Distancia: ~1~,~1~m Tiempo: ~1~ segundos\n\n[WHEEL02]\nDOBLE BONIFICACIÓN EN DOS RUEDAS: ~1~ $ Distancia: ~1~ pies Tiempo: ~1~ segundos\n\n[WHEEL03]\nBONIFICACIÓN EN DOS RUEDAS: ~1~ $ Tiempo: ~1~ segundos\n\n[WHEEL04]\nBONIFICACIÓN EN DOS RUEDAS: ~1~ $ Distancia: ~1~,~1~m\n\n[WHEEL05]\nBONIFICACIÓN EN DOS RUEDAS: ~1~ $ Distancia: ~1~ pies\n\n[WHEEL06]\nBONIFICACIÓN EN CABALLITO: ~1~ $ Distancia: ~1~,~1~m Tiempo: ~1~ segundos\n\n[WHEEL07]\nBONIFICACIÓN EN CABALLITO: ~1~ $ Distancia: ~1~ pies Tiempo: ~1~ segundos\n\n[WHEEL08]\nBONIFICACIÓN EN CABALLITO: ~1~ $ Tiempo: ~1~ segundos\n\n[WHEEL09]\nBONIFICACIÓN EN CABALLITO: ~1~ $ Distancia: ~1~,~1~m\n\n[WHEEL10]\nBONIFICACIÓN EN CABALLITO: ~1~ $ Distancia: ~1~ pies\n\n[WHEEL11]\nBONIFICACIÓN EN PARADA MÁS LARGA: ~1~ $ Distancia: ~1~,~1~m Tiempo: ~1~ segundos\n\n[WHEEL12]\nBONIFICACIÓN EN PARADA MÁS LARGA: ~1~ $ Distancia: ~1~ pies Tiempo: ~1~ segundos\n\n[WHEEL13]\nBONIFICACIÓN EN PARADA MÁS LARGA: ~1~ $ Tiempo: ~1~ segundos\n\n[WHEEL14]\nBONIFICACIÓN EN PARADA MÁS LARGA: ~1~ $ Distancia: ~1~,~1~m\n\n[WHEEL15]\nBONIFICACIÓN EN PARADA MÁS LARGA: ~1~ $ Distancia: ~1~ pies\n\n[ROK3_72]\n¡Love Fist!\n\n[POR1_19]\n¡Eh!\n\n[DESPERA]\nDesesperado\n\n[MOB_99A]\nVe hasta el teléfono público junto al centro comercial en Washington.\n\n[MOB_98A]\nVe hasta el teléfono público en Vice Point.\n\n[MOB_96A]\nVe hasta el teléfono público en la terminal del aeropuerto.\n\n[MOB_95A]\nVe hasta el teléfono público en Little Havana.\n\n[BNK1_1]\n¿Le puedo ayudar, señor?\n\n[BNK1_2]\n¡Hay un impostor!\n\n[BNK1_3]\n¡Se ha vuelto loco!\n\n[BNK1_4]\n¿Quién demonios eres?\n\n[BNK1_5]\n¿Dónde está tu placa?\n\n[BNK1_6]\n¡Ahí están! ¡Dispara a matar!\n\n[MOB_24A]\nHola, ¿Sr. Vercetti?\n\n[MOB_24B]\nSí.\n\n[MOB_24C]\nSoy Cortez. Usted estuvo en mi fiesta.\n\n[MOB_24D]\nSí, lo recuerdo.\n\n[MOB_24E]\nSr. Vercetti, ha sido un desgraciado incidente lo que ocurrió con su operación de negocios.\n\n[MOB_24F]\nLo sé.\n\n[MOB_24G]\nQuiero que sepa que tanto yo como mi gente estamos haciendo todo lo que podemos para llegar al fondo de este tema.\n\n[MOB_24H]\nSi desea hablar conmigo de manera más privada, me podrá encontrar en el barco. Buenos días, señor.\n\n[BNK2_6]\n¡Este tío está chalado!\n\n[ANGEL]\nÁngel\n\n[CUBJET]\nJetmax Cubano\n\n[SANDKIN]\nSandking\n\n[POLMAV]\nMaverick de la policía\n\n[BOXVILL]\nBoxville\n\n[BENSON]\nBenson\n\n[HOTRINA]\nCorredor de Hotring\n\n[HOTRINB]\nCorredor de Hotring\n\n[BLOODRA]\nCoche de Bloodring\n\n[BLOODRB]\nCoche de Bloodring\n\n[MAFIACR]\nYate de la Mafia\n\n[COP_M2]\nANTI VICIO\n\n[COP_M3]\nTRUENO MARRÓN\n\n[BNK3_2]\nNo voy a conducir por ti, ni soñando, voy a compartir esto con el grupo.\n\n[FEM_SL1]\nNo hay archivo 1 guardado\n\n[FEM_SL2]\nNo hay archivo 2 guardado\n\n[FEM_SL3]\nNo hay archivo 3 guardado\n\n[FEM_SL4]\nNo hay archivo 4 guardado\n\n[FEM_SL5]\nNo hay archivo 5 guardado\n\n[FEM_SL6]\nNo hay archivo 6 guardado\n\n[FEM_SL7]\nNo hay archivo 7 guardado\n\n[FEM_SL8]\nNo hay archivo 8 guardado\n\n[FEA_CHA]\nCambiando la salida de audio a ESTÉREO. Espera...\n\n[FEA_CHD]\n¡Aviso! Estás cambiando la salida de ESTÉREO a DTS. Espera...\n\n[FEI_SEL]\nSelec.\n\n[FEI_BAC]\nAtrás\n\n[FEI_RES]\nReanudar\n\n[FEI_NAV]\nNavegar\n\n[FEI_BTX]\nbotón / -\n\n[FEI_BTT]\nbotón \" -\n\n[FEI_STA]\nBotón START -\n\n[FEI_BTD]\n; = > < -\n\n[FEI_STO]\nParar\n\n[MOB_68A]\nTommy, tío, tengo una sorpresa para ti.\n\n[MOB_68B]\nMe encuentro en el estudio de grabación con unos artistas importantes.\n\n[MOB_68C]\n¿Por qué no te vienes por aquí?\n\n[MOB_68D]\nSabes que esto tiene sentido, ¿a que sí? Hasta dentro de un rato.\n\n[OUTFT1]\nCalle\n\n[OUTFT2]\nEtiqueta\n\n[OUTFT3]\nMono de trabajo\n\n[OUTFT4]\nClub de campo\n\n[OUTFT5]\nHabana\n\n[OUTFT6]\nPolicía\n\n[OUTFT7]\nAtraco al banco\n\n[OUTFT8]\nInformal\n\n[OUTFT9]\nSr. Vercetti\n\n[OUTFT10]\nChándal\n\n[OUTFT13]\nMC Tommy\n\n[CAR_AS1]\nCONCESIONARIO DE COCHES CONSOLIDADO\n\n[CAR_AS2]\n~g~El Concesionario de coches Sunshine generará ahora unos ingresos de hasta ~1~ $ máximo. Asegúrate de recaudarlos regularmente.\n\n[BUYSAVE]\n~g~A partir de ahora, podrás guardar tu partida aquí cuando no estés en una misión.\n\n[BUYGARG]\n~g~También puedes almacenar vehículos en este garaje.\n\n[STRPBUY]\nAdquirido el club Pole Position: ~1~ $\n\n[GA_4]\nLas bombas de coche son 500 $ cada una.\n\n[GA_5]\nTu coche ya está equipado con una bomba.\n\n[GA_6] { reVC update }\n¡Apárcalo, actívala pulsando ~h~~k~~VEHICLE_FIREWEAPON~~w~ y SAL PITANDO!\n\n[GA_7] { reVC update }\n¡Ármalo pulsando ~h~~k~~VEHICLE_FIREWEAPON~~w~. La bomba explotará cuando se arranque el motor.\n\n[GA_6B] { reVC update }\n¡Apárcalo, actívala pulsando ~h~~k~~VEHICLE_FIREWEAPON~~w~ y SAL PITANDO!\n\n[GA_7B] { reVC update }\n¡Ármalo pulsando ~h~~k~~VEHICLE_FIREWEAPON~~w~. La bomba explotará cuando se arranque el motor.\n\n[MOB_70A]\nTommy, soy yo, el coronel Cortez. Mira, me parece que eres la clase de hombre que lleva a cabo los trabajos. Así que ayúdame, por favor.\n\n[MOB_70B]\nMe podrás encontrar en el barco.\n\n[PICK1]\n¡El chaleco antibalas ha sido entregado en el hotel Ocean View!\n\n[PICK2]\n¡La .357 ha sido entregada en el hotel Ocean View!\n\n[PICK3]\n¡La sierra mecánica ha sido entregada en el hotel Ocean View!\n\n[PICK4]\n¡El lanzallamas ha sido entregado en el hotel Ocean View!\n\n[PICK5]\n¡El rifle de francotirador .308 ha sido entregado en el hotel Ocean View!\n\n[PICK6]\n¡La Ametralladora Pesada ha sido entregada en el hotel Ocean View!\n\n[PICK7]\n¡El lanzacohetes ha sido entregado en el hotel Ocean View!\n\n[PICK8]\n¡El Sea Sparrow está ahora disponible en la mansión de Starfish Island!\n\n[PICK9]\n¡El tanque está ahora disponible en los cuarteles del ejército!\n\n[PICK10]\n¡El Hunter está ahora disponible en los cuarteles del ejército!\n\n[CLOTH1]\nEl traje de etiqueta ha sido entregado en Rafaels en Ocean Beach.\n\n[CLOTH2]\nEl traje de calle ha sido entregado en los pisos francos.\n\n[CLOTH3]\nEl mono de trabajo ha sido entregado en Tooled Up en el centro comercial de North Point.\n\n[CLOTH4]\nEl traje del club de campo ha sido entregado en el club de golf de Leaf Links.\n\n[CLOTH5]\nEl traje Havana ha sido entregado en la tienda de ropa de Little Havana.\n\n[CLOTH6]\nEl traje de policía ha sido entregado en la jefatura de policía de Washington Beach.\n\n[CLOTH7]\nEl traje informal ha sido entregado en Gash del centro comercial de North Point.\n\n[CLOTH8]\nEl traje del Sr. Vercetti ha sido entregado en Collar & Cuffs de Ocean Beach.\n\n[CLOTH9]\nEl chándal ha sido entregado en Jocksport del centro de la ciudad.\n\n[CLOTH10]\nEl traje para el atraco al banco ha sido entregado en el Club Malibu de Vice Point.\n\n[MOB_62A]\nTommy, soy Ricardo Díaz, quiero darte las gracias por cuidar de mí, tío.\n\n[MOB_62B]\nHe preguntado al gilipollas de Cortez, y me ha dicho que eres bueno, amigo, ¿por qué no vienes a verme?\n\n[MOB_62C]\nNecesito un tío como tú. Todos los que tengo son gilipollas perdidos,\n\n[MOB_62D]\ngilipollas por todas partes, tío. Yo te puedo hacer muy rico.\n\n[GOAWAY2]\n~g~Regresa cuando hayas terminado las misiones de la banda de moteros.\n\n[COL2_9]\n¡Estúpido americano! ¡Te han seguido hasta aquí!\n\n[LOADCOL]\nCargando...\n\n[STFT_17]\nTiempo más rápido en la ''Prueba PCJ''\n\n[STFT_18]\nTiempo más rápido en el ''Trial de tierra''\n\n[STFT_19]\nTiempo más rápido en la ''Pista de Pruebas''\n\n[NEW_REC]\n¡Nuevo récord establecido! ~w~~1~ minutos ~g~y ~w~~1~ segundos.\n\n[BMX_HOW]\n~g~¡Da dos vueltas a la pista de tierra, ~y~pasando por ~g~los ~y~PUNTOS DE CONTROL ~g~por el camino!\n\n[BMXREW1]\n~g~¡Cada vez que batas tu récord anterior de las dos vueltas\n\n[BMXREW2]\n~g~conseguirás una ~y~RECOMPENSA ~g~mejor!\n\n[BMXRAIN]\n~g~Parece lluvia...\n\n[ITBEG]\nAl principio...\n\n[NBMNBUY]\nCasa Swanko adquirida: ~1~ $\n\n[LNKVBUY]\nApartamento en Links View adquirido: ~1~ $\n\n[HYCOBUY]\nPiso de Hyman adquirido: ~1~ $\n\n[BUYGARS]\n~g~Puedes guardar vehículos en estos garajes.\n\n[OCHEBUY]\nApartamento de Ocean Heights adquirido: ~1~ $\n\n[WASHBUY]\n1102 de la calle Washington adquirido: ~1~ $\n\n[VCPTBUY]\n3321 de Vice Point adquirido: ~1~ $\n\n[SKUMBUY]\nChabola Skumole adquirida: ~1~ $\n\n[HELP6_C]\nPulsa ~h~~k~~VEHICLE_HANDBRAKE~~w~ para usar el freno de mano del vehículo.\n\n[HELP2_A]\nPulsa ~h~~k~~PED_SPRINT~~w~~w~ cuando estés corriendo para ~h~esprintar.\n\n[HELP4_A]\nPulsa ~h~~k~~VEHICLE_ACCELERATE~~w~ para acelerar.\n\n[HELP5_A]\nPulsa ~h~~k~~VEHICLE_BRAKE~~w~ para frenar o para dar marcha atrás si el vehículo se ha detenido.\n\n[HELP8_A]\nPulsa ~h~~k~~PED_SNIPER_ZOOM_IN~~w~ para hacer zoom con el rifle y ~h~~k~~PED_SNIPER_ZOOM_OUT~~w~ para alejar la vista.\n\n[PBOAT_1] { reVC update }\nPulsa ~h~ ~k~~VEHICLE_FIREWEAPON~~w~ para disparar los cañones del barco.\n\n[SEG3_4] { reVC update }\n~g~Puedes recoger bombas simplemente pilotando tu Helicóptero RC cerca de cada una de ellas, para soltar una bomba pulsa ~h~~k~~VEHICLE_FIREWEAPON~~g~.\n\n[RCR1_3] { reVC update }\n~g~Si quieres abandonar esta misión, pulsa ~h~~k~~VEHICLE_FIREWEAPON~~g~ para detonar tu coche RC.\n\n[HELP32] { reVC update }\nA continuación dispara pulsando ~h~~k~~VEHICLE_FIREWEAPON~.\n\n[HELP33] { reVC update }\nA continuación dispara pulsando ~h~~k~~VEHICLE_FIREWEAPON~.\n\n[TTUTOR]\nPulsa ~h~~k~~TOGGLE_SUBMISSIONS~~w~ para comenzar o cancelar las misiones de taxista.\n\n[TTUTOR2]\nPulsa ~h~~k~~TOGGLE_SUBMISSIONS~~w~ para comenzar o cancelar las misiones de taxista.\n\n[FTUTOR]\nPulsa ~h~~k~~TOGGLE_SUBMISSIONS~~w~ para comenzar o cancelar las misiones del camión de bomberos.\n\n[FTUTOR2]\nPulsa ~h~~k~~TOGGLE_SUBMISSIONS~~w~ para comenzar o cancelar las misiones del camión de bomberos.\n\n[CTUTOR]\nPulsa ~h~~k~~TOGGLE_SUBMISSIONS~~w~ para comenzar o cancelar las misiones de justiciero.\n\n[CTUTOR2]\nPulsa ~h~~k~~TOGGLE_SUBMISSIONS~~w~ para comenzar o cancelar las misiones de justiciero.\n\n[HELP8_B]\nPulsa ~h~~k~~PED_SNIPER_ZOOM_IN~ ~w~para ~h~acercar la vista ~w~con el rifle y ~h~~k~~PED_SNIPER_ZOOM_OUT~ ~w~para ~h~alejar la vista ~w~otra vez.\n\n[ATUTOR3]\nPulsa ~h~~k~~TOGGLE_SUBMISSIONS~~w~ para comenzar o cancelar las misiones de ATS.\n\n[GUN_H1]\n~w~Pulsa ~h~~k~~PED_SPRINT~~w~ para comprar. ~w~Pulsa ~h~~k~~VEHICLE_ENTER_EXIT~~w~ para salir.\n\n[PU_CF3] { reVC update }\nPulsa ~h~~k~~PED_ANSWER_PHONE~~w~ para reemplazar tu arma actual en esta ranura.\n\n[PU_CF4] { reVC update }\nPulsa ~h~~k~~PED_ANSWER_PHONE~~w~ para reemplazar tu arma actual en esta ranura.\n\n[HELP9_B]\nPulsa ~h~~k~~PED_FIREWEAPON~ ~w~para ~h~disparar~w~ el rifle de francotirador.\n\n[HELP37]\nSi no quieres subir al coche mientras se lo estás robando a alguien, pulsa ~h~~k~~PED_SPRINT~.\n\n[HELP6_A]\nPulsa ~h~~k~~VEHICLE_HANDBRAKE~~w~ para usar el freno de mano del vehículo.\n\n[HELP6_D]\nPulsa ~h~~k~~VEHICLE_HANDBRAKE~~w~ para usar el freno de mano del vehículo.\n\n[HELP26]\nPulsa ~h~~k~~VEHICLE_ENTER_EXIT~~w~ para subir o bajar de un vehículo.\n\n[HELP27]\nPulsa ~h~~k~~VEHICLE_TURRETUP~~w~ o ~h~~k~~VEHICLE_TURRETDOWN~~w~ para equilibrar tu peso en la moto.\n\n[HELP28]\nPulsa ~h~~k~~VEHICLE_TURRETUP~~w~ o ~h~~k~~VEHICLE_TURRETDOWN~~w~ para equilibrar tu peso en la moto.\n\n[HELP35]\nPulsa ~h~~k~~GO_LEFT~~w~ o ~h~~k~~GO_RIGHT~~w~ para conducir el vehículo.\n\n[HELP36]\nPulsa ~h~~k~~GO_LEFT~~w~ o ~h~~k~~GO_RIGHT~~w~ para conducir el vehículo.\n\n[HELP42]\nVe al ~q~icono rosa~w~ para encontrar el hotel.\n\n[HELP19]\nCamina hasta el ~q~marcador rosa~w~ para continuar.\n\n[HELP1]\nPárate en el centro del ~q~marcador rosa.\n\n[HELP12]\nCamina hasta el centro del ~q~marcador rosa~w~ para activar una misión.\n\n[SEG3_6]\n~g~Para acertar en una zona objetivo con éxito, deberás soltar una bomba en la zona representada por el ~q~marcador rosa~w~. Puedes soltar las bombas en cualquier orden.\n\n[S_PROMP]\nCuando no estés en una misión podrás guardar tu progreso recogiendo las ~h~cintas de cassette~w~.\n\n[HELP16]\nCruza la puerta principal del hotel ~h~Ocean View~w~ para entrar en el edificio.\n\n[HELP43]\n~g~Ve al hotel ~h~Ocean View~g~ en Ocean Drive.\n\n[HELI_F1]\n~r~¡Misión de puntos de control cancelada!\n\n[AMMUHLP]\nSi necesitas armas pásate por ~h~Ammu-Nation~w~. Está indicado en el radar como una ~h~pistola~w~ azul.\n\n[HELI_1]\nControl del Helicóptero de Centro de la ciudad\n\n[HELI_2]\nControl del Helicóptero de Ocean Beach\n\n[HELI_3]\nControl del Helicóptero de Vice Point\n\n[HELI_4]\nControl del Helicóptero de Little Haiti\n\n[FST_MFR]\nEmisora de radio preferida\n\n[FST_LFR]\nEmisora de radio menos escuchada\n\n[FEI_HOL]\nMantener\n\n[FEI_ZOO]\nZoom\n\n[FEI_BTR]\n> < -\n\n[FEI_NA]\nN\\A\n\n[MESA]\nMesa Grande\n\n[STRP_NO]\nNo puedes comprar el club de striptease en este momento, vuelve luego.\n\n[CHSE]\nPERSECUCIÓN\n\n[NBMN_L]\nPulsa ~h~~k~~PED_ANSWER_PHONE~~w~ para comprar la casa Swanko por ~1~ $.\n\n[NBMN_T]\nPulsa ~h~~k~~PED_ANSWER_PHONE~~w~ para comprar la casa Swanko por ~1~ $.\n\n[NBMN_C]\nPulsa ~h~~k~~PED_ANSWER_PHONE~~w~ para comprar la casa Swanko por ~1~ $.\n\n[LNKV_L]\nPulsa ~h~~k~~PED_ANSWER_PHONE~~w~ para comprar el apartamento de Links View por ~1~ $.\n\n[LNKV_T]\nPulsa ~h~~k~~PED_ANSWER_PHONE~~w~ para comprar el apartamento de Linsk View por ~1~ $.\n\n[LNKV_C]\nPulsa ~h~~k~~PED_ANSWER_PHONE~~w~ para comprar el apartamento de Links View por ~1~ $.\n\n[HYCO_L]\nPulsa ~h~~k~~PED_ANSWER_PHONE~~w~ para comprar el piso de Hyman por ~1~ $.\n\n[HYCO_T]\nPulsa ~h~~k~~PED_ANSWER_PHONE~~w~ para comprar el piso de Hyman por ~1~ $.\n\n[HYCO_C]\nPulsa ~h~~k~~PED_ANSWER_PHONE~~w~ para comprar el piso de Hyman por ~1~ $.\n\n[OCHE_L]\nPulsa ~h~~k~~PED_ANSWER_PHONE~~w~ para comprar el apartamento de Ocean Heights por ~1~ $.\n\n[OCHE_T]\nPulsa ~h~~k~~PED_ANSWER_PHONE~~w~ para comprar el apartamento de Ocean Heights por ~1~ $.\n\n[OCHE_C]\nPulsa ~h~~k~~PED_ANSWER_PHONE~~w~ para comprar el apartamento de Ocean Heights por ~1~ $.\n\n[WASH_L]\nPulsa ~h~~k~~PED_ANSWER_PHONE~~w~ para comprar el 1102 de la calle Washington por ~1~ $.\n\n[WASH_T]\nPulsa ~h~~k~~PED_ANSWER_PHONE~~w~ para comprar el 1102 de la calle Washington por ~1~ $.\n\n[WASH_C]\nPulsa ~h~~k~~PED_ANSWER_PHONE~~w~ para comprar el 1102 de la calle Washington por ~1~ $.\n\n[VCPT_L]\nPulsa ~h~~k~~PED_ANSWER_PHONE~~w~ para comprar el 3321 de Vice Point por ~1~ $.\n\n[VCPT_T]\nPulsa ~h~~k~~PED_ANSWER_PHONE~~w~ para comprar el 3321 de Vice Point por ~1~ $.\n\n[VCPT_C]\nPulsa ~h~~k~~PED_ANSWER_PHONE~~w~ para comprar el 3321 de Vice Point por ~1~ $.\n\n[SKUM_L]\nPulsa ~h~~k~~PED_ANSWER_PHONE~~w~ para comprar la chabola Skumole por ~1~ $.\n\n[SKUM_T]\nPulsa ~h~~k~~PED_ANSWER_PHONE~~w~para comprar la chabola Skumole por ~1~ $.\n\n[SKUM_C]\nPulsa ~h~~k~~PED_ANSWER_PHONE~ ~w~ para comprar la chabola Skumole por ~1~ $.\n\n[PRNT_L]\nPulsa ~h~~k~~PED_ANSWER_PHONE~~w~ para comprar la imprenta por ~1~ $.\n\n[PRNT_T]\nPulsa ~h~~k~~PED_ANSWER_PHONE~~w~ para comprar la imprenta por ~1~ $.\n\n[PRNT_C]\nPulsa ~h~~k~~PED_ANSWER_PHONE~~w~ para comprar la imprenta por ~1~ $.\n\n[CAR_L]\nPulsa ~h~~k~~PED_ANSWER_PHONE~~w~ para comprar el concesionario de coches por ~1~ $.\n\n[CAR_T]\nPulsa ~h~~k~~PED_ANSWER_PHONE~~w~ para comprar el concesionario de coches por ~1~ $.\n\n[CAR_C]\nPulsa ~h~~k~~PED_ANSWER_PHONE~~w~ para comprar el concesionario de coches por ~1~ $.\n\n[PORN_L]\nPulsa ~h~~k~~PED_ANSWER_PHONE~~w~ para comprar los estudios de cine por ~1~ $.\n\n[PORN_T]\nPulsa ~h~~k~~PED_ANSWER_PHONE~~w~ para comprar los estudios de cine por ~1~ $.\n\n[PORN_C]\nPulsa ~h~~k~~PED_ANSWER_PHONE~~w~ para comprar los estudios de cine por ~1~ $.\n\n[ICE_L]\nPulsa ~h~~k~~PED_ANSWER_PHONE~~w~ para comprar la fábrica de helados por ~1~ $.\n\n[ICE_T]\nPulsa ~h~~k~~PED_ANSWER_PHONE~~w~ para comprar la fábrica de helados por ~1~ $.\n\n[ICE_C]\nPulsa ~h~~k~~PED_ANSWER_PHONE~~w~ para comprar la fábrica de helados por ~1~ $.\n\n[TAXI_L]\nPulsa ~h~~k~~PED_ANSWER_PHONE~~w~ para comprar la compañía de taxis por ~1~ $.\n\n[TAXI_T]\nPulsa ~h~~k~~PED_ANSWER_PHONE~~w~ para comprar la compañía de taxis por ~1~ $.\n\n[TAXI_C]\nPulsa ~h~~k~~PED_ANSWER_PHONE~~w~ para comprar la compañía de taxis por ~1~ $.\n\n[BANK_L]\nPulsa ~h~~k~~PED_ANSWER_PHONE~~w~ para comprar el Malibú por ~1~ $.\n\n[BANK_T]\nPulsa ~h~~k~~PED_ANSWER_PHONE~~w~ para comprar el Malibú por ~1~ $.\n\n[BANK_C]\nPulsa ~h~~k~~PED_ANSWER_PHONE~~w~ para comprar el Malibú por ~1~ $.\n\n[BOAT_L]\nPulsa ~h~~k~~PED_ANSWER_PHONE~~w~ para comprar el astillero por ~1~ $.\n\n[BOAT_T]\nPulsa ~h~~k~~PED_ANSWER_PHONE~~w~ para comprar el astillero por ~1~ $.\n\n[BOAT_C]\nPulsa ~h~~k~~PED_ANSWER_PHONE~~w~ para comprar el astillero por ~1~ $.\n\n[STRP_L]\nPulsa ~h~~k~~PED_ANSWER_PHONE~~w~ para comprar el club Pole Position por ~1~ $.\n\n[STRP_T]\nPulsa ~h~~k~~PED_ANSWER_PHONE~~w~ para comprar el club Pole Position por ~1~ $.\n\n[STRP_C]\nPulsa ~h~~k~~PED_ANSWER_PHONE~~w~ para comprar el club Pole Position por ~1~ $.\n\n[STOCK]\n~r~Agotado\n\n[HELP14]\nPara encontrar el bufete del abogado, ve hacia la ~h~señal de la L~w~ que hay en el radar.\n\n[RAMPAGE]\n¡MASACRE!\n\n[RAMP_F]\n¡MASACRE FALLIDA!\n\n[RAMP_P]\n¡MASACRE COMPLETADA!\n\n[RAMP_A]\n¡TODAS LAS MASACRES COMPLETADAS!\n\n[PAGE_01]\n¡Liquida a ~1~ criminales en 2 minutos!\n\n[PAGE_02]\n¡Destruye ~1~ vehículos en 2 minutos!\n\n[PAGE_03]\n¡Pasa en el coche y cárgate a ~1~ criminales en 2 minutos!\n\n[PAGE_04]\n¡Atropella y mata a ~1~ criminales en 2 minutos!\n\n[PAGE_05]\n¡Abate a tiros a ~1~ criminales en 2 minutos!\n\n[SENTXS]\nSentinel XS\n\n[MAP_LEG]\nLeyenda\n\n[VCNMAV]\nVCN Maverick\n\n[LG_01]\nPosición del jugador\n\n[LG_02]\nAvery Carrington\n\n[LG_03]\nContacto del motero\n\n[LG_04]\nCoronel Cortez\n\n[LG_05]\nRicardo Díaz\n\n[LG_06]\nKent Paul\n\n[LG_07]\nAbogado\n\n[LG_08]\nPhil Cassidy\n\n[LG_09]\nAstillero\n\n[LG_10]\nClub Malibú\n\n[LG_11]\nCubanos\n\n[LG_12]\nEstudio Cinematográfico\n\n[LG_13]\nAmmu-Nation\n\n[LG_14]\nHaitianos\n\n[LG_15]\nFerretería\n\n[LG_16]\nPiso franco\n\n[LG_17]\nHelado\n\n[LG_18]\nTaxis Kaufman\n\n[LG_19]\nLove Fist\n\n[LG_20]\nImprenta\n\n[LG_21]\nPropiedad\n\n[LG_22]\nTaller de Pintura\n\n[LG_23]\nTienda de ropa\n\n[LG_24]\nMansión de Tommy\n\n[LG_25]\nTeléfono\n\n[LG_26]\nEmisora de radio Wildstyle\n\n[LG_27]\nEmisora de radio Flash FM\n\n[LG_28]\nEmisora de radio Kchat\n\n[LG_29]\nEmisora de radio Fever 105\n\n[LG_30]\nEmisora de radio VRock\n\n[LG_31]\nEmisora de radio VCPR\n\n[LG_32]\nEmisora de radio Espantoso\n\n[LG_33]\nEmisora de radio Emotion 98.3\n\n[LG_34]\nEmisora de radio Wave 103\n\n[LG_35]\nDestino\n\n[LG_36]\nSolarium\n\n[LG_37]\nClub de Striptease\n\n[LG_38]\nObjetivo\n\n[MAP_YAH]\nESTÁS AQUÍ\n\n[TAXSHRT]\n~g~Puedes coger este taxi Kaufman para ir a tu destino sin conducir. Te costará 9 $.\n\n[FEST_HV]\nNivel más alto de misión de justiciero\n\n[CLOHELP]\n¡Ropa limpia!\n\n[SUNSHIN]\nCoches Sunshine\n\n[CHERRYP]\nHelados Cherry Popper\n\n[KAUFCAB]\nTaxis Kaufman\n\n[BOATYAR]\nEl Astillero\n\n[WANT_L]\nHas perdido tu nivel de se busca, si cometes un crimen mientras las estrellas parpadean, tu nivel total de se busca se restablecerá.\n\n[FEI_BTU]\n; = -\n\n[BOAT_AS]\n~g~El astillero generará ahora unos ingresos hasta un máximo de ~1~ $. Asegúrate de recaudarlos de manera regular.\n\n[BOAT_A2]\nASTILLERO COMPLETADO\n\n[BOAT_N]\nPunto de control Charlie\n\n[BOAT_P]\n~g~Recoge los paquetes antes de que se acabe el tiempo.\n\n[FEI_R1B]\nBotón R1 \\ R2 -\n\n[HELP9_A]\nPulsa ~h~~k~~PED_FIREWEAPON~ ~w~para disparar el rifle de francotirador.\n\n[HELP21]\nPulsa ~h~~k~~VEHICLE_ENTER_EXIT~ ~w~para subir o bajar de un vehículo.\n\n[CREAM]\nDistribución\n\n[UMBERTO]\nCafé Robina\n\n[PU_CF1]\nPulsa ~h~~k~~PED_ANSWER_PHONE~ ~w~para recoger esta arma. Reemplazará cualquier arma del mismo tipo que tengas.\n\n[FED_RDM]\nMAPA E ICONOS\n\n[FEC_ILU]\nInvertir vista en primera persona\n\n[NITRO]\n¡Ahora todos los taxis disponen de un impulsor de salto! Simplemente toca el claxon.\n\n[RATNG53]\nInformal\n\n[RATNG54]\nVergüenza\n\n[RATNG55]\nHacker\n\n[RATNG56]\nLiante\n\n[RATNG57]\nMentiroso compulsivo\n\n[STHC_04]\nPuntuación más alta por mantener la pelota en el aire en la playa\n\n[STHC_05]\nMejor resultado de Hotring\n\n[STFT_13]\nMejor tiempo en el Control del Helicóptero del centro\n\n[STFT_14]\nMejor tiempo en el Control del Helicóptero de Ocean Beach\n\n[STFT_15]\nMejor tiempo en el Control del Helicóptero de Vice Point\n\n[STFT_16]\nMejor tiempo en el Control del Helicóptero de Little Haití\n\n[STFT_21]\nTiempo más rápido en Hotring\n\n[STFT_22]\nVuelta más rápida en Hotring\n\n[STFT_20]\nTiempo más rápido en el ''Conocircuito''\n\n[HELP44]\nDetente en el ~q~marcador rosa.\n\n[HELP45]\nPulsa ~h~~k~~PED_DUCK~~w~ para agacharte. Esto aumentará tu puntería con las armas que llevas.\n\n[RCR1_5]\nCarrera Bandit RC\n\n[RCPL1_7]\nCarrera Barón RC\n\n[RCH1_11]\nRecogidas del Raider RC\n\n[FEA_CTD]\n¡Aviso! Esta característica requiere que el dispositivo compatible DTS esté conectado. ¿Continuar?\n\n[FEM_STE]\nUTILIZAR ESTÉREO\n\n[GREET]\nSaludos desde...\n\n[LANCE_1]\n¡Venga, tío, conduce con más cuidado!\n\n[LANCE_2]\n¡Eh, mira lo que haces!\n\n[LANCE_3]\n¿Eh, dónde vamos ahora?\n\n[LANCE_4]\n¿Qué estamos haciendo ahora?\n\n[LAW4_15]\n¡Más dinero!\n\n[MERC_5]\nBonito coche, Mr. Vercetti.\n\n[MERC_26]\n¡DEPRISA, DEPRISA, DEPRISA!\n\n[MERC_27]\nCon cuidado Tommy, me arreglaron la nariz el mes pasado.\n\n[MERC_28]\nConduce con cuidado Tommy.\n\n[MERC_29]\nVe más despacio Tommy.\n\n[MERC_30]\nTommy, si no te importa mata a quien quieras menos a mí.\n\n[MERC_31]\n¡Tommy, cielo, no me mates!\n\n[MERC_32]\n¡Tommy, me alegro que robaras este coche!\n\n[MERC_40]\nMe he divertido tanto.\n\n[MERC_43]\nAdiós, mi ángel.\n\n[MERC_44]\nAhora sigue machacándote, me oyes.\n\n[MERC_45]\nCiao, guapetón.\n\n[COL5_17]\n¡Oh, Dios mío, tienen un helicóptero!\n\n[COL5_18]\n¡Dispara al helicóptero!\n\n[COL5_19]\nTommy, ¡hazte con ese helicóptero!\n\n[COL5_20]\n¡Ahí viene otra vez! ¡Derriba a ese helicóptero!\n\n[COL5_21]\n¡Mira el tamaño de ese helicóptero!\n\n[COL5_22]\n¡Ahí viene de nuevo!\n\n[FEA_DSM]\n¡Aviso! Esta partida guardada está configurada para utilizar DTS. Esto requiere que el dispositivo compatible DTS esté conectado. Por favor selecciona si quieres continuar usando el sistema DTS o ESTÉREO.\n\n[STFT_23]\nTiempo más rápido en Punto de control Charlie\n\n[HELP50]\nPulsa ~h~~k~~PED_ANSWER_PHONE~~w~ para colocar la cámara detrás de ti.\n\n[HELP51]\nPulsa ~h~~k~~PED_ANSWER_PHONE~~w~ para colocar la cámara detrás de ti.\n\n[HELP52]\nPulsa ~h~~k~~PED_ANSWER_PHONE~~w~ para colocar la cámara detrás de ti.\n\n[HELP53]\nPulsa ~h~~k~~PED_CYCLE_WEAPON_LEFT~~w~ o ~h~~k~~PED_CYCLE_WEAPON_RIGHT~~w~ para elegir entre todas tus armas disponibles.\n\n[HELP46]\nHay ocho categorías de armas diferentes.\n\n[HELP47]\nPuedes llevar una arma de cada categoría al mismo tiempo: un tipo de pistola, un tipo de rifle.\n\n[HELP54]\n~w~Cuesta: ~1~ $. ~r~Si compras esta arma reemplazarás la actual.\n\n[HELP2A2]\nPulsa ~h~~k~~PED_SPRINT~~w~ cuando corras para ~h~esprintar.\n\n[HLPSN_A]\nEl rifle de francotirador te permite hacer zoom de acercamiento y disparar con más precisión a objetivos a una cierta distancia.\n\n[HLPSN_B]\nMantén pulsado ~h~~k~~PED_LOCK_TARGET~ ~w~para ~h~apuntar~w~ con el rifle de francotirador.\n\n[HLPSN_C]\nMantén pulsado ~h~~k~~PED_LOCK_TARGET~ ~w~para ~h~apuntar~w~ con el rifle de francotirador.\n\n[HLPSN_D]\nPulsa ~h~~k~~PED_SNIPER_ZOOM_IN~~w~ para ~h~acercar la vista ~w~con el rifle y ~h~~k~~PED_SNIPER_ZOOM_OUT~ ~w~para ~h~alejarla~w~.\n\n[HLPSN_E]\nPulsa ~h~~k~~PED_FIREWEAPON~~w~ para ~h~disparar~w~ el rifle de francotirador.\n\n[HLPSN_F]\nPulsa ~h~~k~~PED_FIREWEAPON~~w~ para ~h~disparar~w~ el rifle de francotirador.\n\n[HLPSN_G]\nPulsa ~h~~k~~PED_FIREWEAPON~~w~ para ~h~disparar~w~ el rifle de francotirador.\n\n[PLANE_H]\nMueve ~h~~k~~VEHICLE_ACCELERATE~~w~ hacia delante para acelerar y a izquierda o derecha para girar.\n\n[PLANE_4] { reVC update }\n{Mueve ~h~~k~~VEHICLE_ACCELERATE~~w~ hacia delante para acelerar y a izquierda o derecha para girar.}\nUtiliza el joystick analógico derecho para acelerar, tira hacia atrás el joystick analógico izquierdo para ascender, empújalo hacia adelante para descender. Para girar muévelo a izquierda o derecha.\n\n[HELP55]\nPulsa ~h~~k~~PED_FIREWEAPON~~w~ para atacar al chef.\n\n[STPR_8]\nClub Pole Position\n\n[STPR_9]\n3321 de Vice Point\n\n[STPR_10]\nApartamento de Links View\n\n[STPR_11]\nCasa Swanko\n\n[STPR_12]\n1102 de Washington Street\n\n[STPR_13]\nApartamento de Ocean Heights\n\n[STPR_14]\nChabola Skumole\n\n[STPR_15]\nPiso de Hyman\n\n[RCCANX]\n~r~Misión de avión RC cancelada.\n\n[CLT_HL2]\nCuando recojas ropa, te librarás de una o dos estrellas del nivel de se busca.\n\n[CRED009]\nDISEÑO DE MISIONES\n\n[CRED359]\nLEE JOHNSON\n\n[CRED360]\nHENDRIK LESSER\n\n[CRED361]\nPASQUALE STACCHIOTTI\n\n[CRED362]\nENRIQUE FERNÁNDEZ\n\n[CRED363]\nPAUL BYERS\n\n[CRED364]\nMIKE EMENY\n\n[CRED365]\nROB DUNKIN\n\n[CRED366]\nCHARLIE KINLOCH\n\n[CRED367]\nKEVIN HOBSON\n\n[CRED368]\nJIM CREE\n\n[MOB_66A]\nTommy, Tommy, ¿para qué has vuelto?\n\n[MOB_66B]\nYa te he dicho que no queremos verte más.\n\n[MOB_67A]\nTommy, creo que no deberías acercarte, ¿me oyes?\n\n[MOB_67B]\nLos chicos haitianos no están muy contentos contigo.\n\n[MOB_18A]\nTommy, soy Paulo, ¿cómo estás? Vale hombre, bueno pensé que tenía que mandarte una nota.\n\n[MOB_18B]\nOh Dios misericordioso, hijo mío, no te vas a creer la categoría de la furcia que acabo de conocer.\n\n[MOB_18C]\nProstituta callejera o algo parecido, cerca de Little Havana, tío.\n\n[MOB_18D]\nMe dijo que se llamaba Mercedes o algo así.\n\n[MOB_18E]\nOh Dios, tío, tienes que probar a esa palomita.\n\n[MOB_18F]\nSabe como ponerte a tono. Dijo que yo era el mejor tío con el que había estado en toda su vida.\n\n[MOB_18G]\nEstate al tanto por si la ves. Hasta luego.\n\n[MOB_72A]\nTommy, soy yo, Lance. Mantén la boca cerrada Tommy porque no tengo ganas de hablar.\n\n[MOB_72B]\nNo estoy interesado en lo que tengas que decir. ¿Por qué debería estarlo? ¿Te preocupas tú por mí?\n\n[MOB_72C]\nTienes que cuidarme un poco mejor. Darme una buena tajada, ya sabes...\n\n[MOB_72D]\nTommy... oh, mira, tío, Lo siento. Es solo que...\n\n[MOB_72E]\nLa gente me ha estado sobreprotegiendo toda mi vida, tratándome como a un niño.\n\n[MOB_72F]\nMi hermano haría eso. Por favor, tío, no lo hagas.\n\n[MOB_72G]\nTengo que irme.\n\n[MOB_63A]\nTommy, soy Earnest. Earnest Kelly.\n\n[MOB_63B]\n¿Cómo estás?\n\n[MOB_63C]\nEstoy bien. Necesitaré un bastón para andar pero muy pronto volveré al trabajo.\n\n[MOB_63D]\nBien.\n\n[MOB_63E]\nMe enteré de lo de Lance. Vaya cabroncete, ¿eh?\n\n[MOB_63F]\nSí.\n\n[MOB_63G]\nNo te fíes nunca de un hombre que va por la calle en pijama. Y es lo que digo yo. Menos mal que lo mataste. Espero que el mamón sufriera.\n\n[MOB_63H]\nCreo que sí. Lo que pasa es que yo no creí que...\n\n[MOB_63I]\nTommy, para ser un chalado furioso, eres bastante ingenuo. Cuando vuelva a trabajar pronto te enseñaré un par de cosas sobre la vida, me oyes.\n\n[MOB_63J]\nTómate tu tiempo, Earnest. Cuídate.\n\n[MOB_16A]\nTommy, soy Paulo, ¿qué pasa amigo?\n\n[MOB_16B]\nQué quieres Paul. No necesito ropa de marca de imitación.\n\n[MOB_16C]\nMuy gracioso, tío, pero sabes que no toco nada de mercancía ilegal. No, sólo llamaba para ver si puedo conseguir un papel en una de tus películas.\n\n[MOB_16D]\nAllí en Inglaterra hice un montón de porno, colega. Soy bastante más ardiente que tú, pequeño.\n\n[MOB_16E]\nPaul, gracias por la oferta, lo tendré en cuenta.\n\n[MOB_16F]\nEn serio, después de todo lo que he hecho por ti, no te olvides de mí.\n\n[MOB_16G]\nEso es lo que intento olvidar.\n\n[MOB_17A]\nTommy Vercetti, ¿Qué tal te va Sr. Influyente? He oído un montón de cosas sobre ti, así que ahora eres el que manda en la ciudad, eh...\n\n[MOB_17B]\nPaul, estás borracho.\n\n[MOB_17C]\nNo, imbécil, no estoy borracho. Sólo he tomado un par de copas y alguna que otra invitación, no me he acostado en los dos últimos días, sabes.\n\n[MOB_17D]\nEn cualquier caso, no me vengas con esto. No soy tonto. ¿Quién te estableció en esta ciudad? ¿Quién? Yo. Que te enteres.\n\n[MOB_17F]\n¿De verdad?\n\n[MOB_17G]\nNo me vengas con esto. Yo te presenté a la gente. Te enseñé cómo hacer bien los trabajos, hice muchas cosas por ti, y así es como me lo pagas.\n\n[MOB_17H]\nMe ignoras. Ni siguieras me das acceso a nada, después de todo lo que hice por ti. ¿Quién te crees que soy? ¿Un retrasado mental o algo así?\n\n[MOB_17I]\nPaul, tranquilízate. He estado muy ocupado, no te comportes como un idiota..\n\n[MOB_17J]\nNo soy un idiota, colega. Eso es lo que decían en el reformatorio. ¿Estás buscando bronca? ¡Porque la vas a tener!\n\n[MOB_17K]\nTommy, colega. Por favor. ¡Tú eras mi gran esperanza! Por favor, ¡no te rías de mí!\n\n[MOB_17L]\nPaul, vete a dormir un poco, de verdad.\n\n[MOB_73A]\nTommy, soy Steve.\n\n[MOB_73B]\nEh, Steve.\n\n[MOB_73C]\n¡Eres un portento! ¡Soy un portento! La gente está loca por nosotros. Vamos a entrar en la historia, amigo.\n\n[MOB_73D]\nSe trata de los premios más importantes. Podré llevar a mi padre a una residencia y no tener que escucharle nunca más.\n\n[MOB_73E]\nEso está bien, Steve.\n\n[MOB_73F]\nMejor que bien tío. Mejor, mucho mejor. Nunca creyó en mí. Nunca creyó que pudiera ser un artista y ahora lo he conseguido.\n\n[MOB_73G]\nSoy el mejor director de cine porno de todos los tiempos, amigo. Solo quería decirte que ha sido un placer conocerte.\n\n[MOB_73H]\nGracias Steve.\n\n[MOB_73I]\nTe quiero tío, No cambies, me oyes.\n\n[MOB_73J]\nTe oigo. Adiós Steve.\n\n[BOLLOX]\nPulsa ~h~~k~~VEHICLE_HANDBRAKE~ ~w~para soltar una bomba. Pulsa ~h~~k~~VEHICLE_ENTER_EXIT~ ~w~para cancelar.\n\n[BRID_OP]\nEl temporal ha pasado, todos los puentes hacia la península están ahora abiertos.\n\n[BRID_CL]\nAlerta de temporal: Cerrados todos los puentes hacia la península.\n\n[ASSET_C]\n¡CLUB POLE POSITION CONSOLIDADO!\n\n[ASSET_D]\nEl club Pole Position generará ahora unos ingresos máximos de hasta ~1~ $ al día. ¡Asegúrate de recaudarlos regularmente!\n\n[ST_WHEE]\nMayor tiempo en caballito (seg)\n\n[ST_STOP]\nMayor tiempo en parada (seg)\n\n[ST_2WHE]\nMayor tiempo en dos ruedas (seg)\n\n[ST_WHED]\nMayor distancia en caballito (m)\n\n[ST_STOD]\nMayor distancia en parada (m)\n\n[ST_2WHD]\nMayor distancia en dos ruedas (m)\n\n[OUTFT11]\nChándal\n\n[OUTFT12]\nFrankie\n\n[RELOAD]\n~g~¡Has conseguido la habilidad de recargar rápidamente!\n\n[APACHE]\nHunter entregado en el helipuerto de Ocean Beach.\n\n[CRED369]\nJOHN MCCARDLE\n\n[CRED370]\nDAVID MURDOCH\n\n[CRED371]\nCHRIS BROWN\n\n[CRED372]\nPAUL GREEN\n\n[CRED373]\nKYLE MILNE\n\n[CRED374]\nKEVIN YUN\n\n[CRED375]\nERICK COBBS\n\n[CRED376]\nRANDY BLAKE\n\n[CRED377]\nBRANDON LIM\n\n[CRED378]\nBRANDON FENOL\n\n[CRED379]\nMICHAEL MANOLE\n\n[CRED380]\nALETHEIA SIMONSON\n\n[CRED381]\nJOHN JANSEN\n\n[CUNTY]\n¡Ropa nueva entregada en la finca de Vercetti!\n\n[GOODBOY]\n¡Prima de 50 $ por comportamiento ejemplar!\n\n[NEWCONT]\n¡Nuevo ~h~punto de contacto ~w~disponible en el puerto deportivo en Ocean Beach!\n\n[FIRELVL]\nMisión de camión de bomberos nivel ~1~\n\n\n[HELP56]\nPulsa ~h~~k~~CAMERA_CHANGE_VIEW_ALL_SITUATIONS~~w~ para ajustar la cámara.\n\n[HELP57]\nPulsa ~h~~k~~CAMERA_CHANGE_VIEW_ALL_SITUATIONS~~w~ para ajustar la cámara.\n\n[HELP58]\nMientras estás apuntando, puedes pulsar ~h~~k~~PED_CYCLE_TARGET_LEFT~~w~ o ~h~~k~~PED_CYCLE_TARGET_RIGHT~~w~para cambiar de objetivo.\n\n[HELP59]\nMientras estás apuntando, puedes pulsar ~h~~k~~PED_CYCLE_TARGET_LEFT~~w~ o ~h~~k~~PED_CYCLE_TARGET_RIGHT~~w~para cambiar de objetivo.\n\n[HELP60]\nSi pulsas ~h~~k~~PED_SPRINT~ ~w~ mientras estás robando un coche, no te subirás en él.\n\n[HELP61]\nAhora dispones de munición ilimitada y el doble de robustez en todos los vehículos.\n\n[FEC_LB1]\nMirar\n\n[FEC_LB2]\ndetrás\n\n[FEC_LB3]\nMirar detrás\n\n[FEC_R3]\n(botón R3)\n\n[FEC_PED]\nControles a pie\n\n[FEC_VEH]\nControles en vehículo\n\n[FEC_FPR]\nControles en primera persona\n\n[FEC_CMM]\nControles comunes\n\n[FEC_PWL]\nIr a la izquierda\n\n[FEC_PWR]\nIr a la derecha\n\n[FEC_PWF]\nAndar hacia delante\n\n[FEC_PWT]\nAndar hacia la cámara\n\n[FEC_PLB]\nMirar hacia atrás.\n\n[FEC_PFR]\nDisparar arma\n\n[FEC_CLE]\nCambiar Arma a la Izq.\n\n[FEC_CRI]\nCambiar Arma a la Dcha.\n\n[FEC_LKT]\nBloquear objetivo\n\n[FEC_PJP]\nSalto Peatón\n\n[FEC_PSP]\nSprint Peatón\n\n[FEC_PSH]\nDisparar Peatón\n\n[FEC_TLF]\nSiguiente objetivo a la izq.\n\n[FEC_TRG]\nSiguiente objetivo a la dcha.\n\n[FEC_CCM]\nCentrar cámara detrás del jugador\n\n[FEC_SZI]\nAcercar vista rifle francotirador\n\n[FEC_SZO]\nAlejar vista rifle francotirador\n\n[FEC_LKL]\nMirar izq. en primera persona\n\n[FEC_LRT]\nMirar dcha. en primera persona\n\n[FEC_LUP]\nMirar arr. en primera persona\n\n[FEC_LDN]\nMirar abj. en primera persona\n\n[FEC_LBH]\nMirar hacia atrás en vehículo\n\n[FEC_LLF]\nMirar a la izq. en vehículo\n\n[FEC_LRG]\nMirar a la dch. en vehículo\n\n[FEC_HRN]\nClaxon\n\n[FEC_HBR]\nFreno de mano del vehículo\n\n[FEC_ACL]\nAcelerar vehículo\n\n[FEC_BRK]\nFrenar vehículo\n\n[FEC_TSM]\nMisiones secundarias\n\n[FEC_CRD]\nCambiar emisora de radio\n\n[FEC_ENT]\nEntrar/salir de vehículo\n\n[FEC_WPN]\nDisparar arma\n\n[FEC_PAS]\nPausa\n\n[FEC_FPO]\nCambiar armas primera persona\n\n[FEC_SMS]\nMostrar puntero del ratón\n\n[FEC_CMS]\nCambiar modo cámara en todas situaciones.\n\n[FEC_TSS]\nCapturar pantalla\n\n[FEC_DBG]\nDEBUG MENU\n\n[FEC_TGD]\nCambiar mando de juego/depuración\n\n[FEC_TDO]\nCambiar cámara depuración No\n\n[FEC_IVH]\nInvertir horizontalidad ratón\n\n[FEC_MSL]\nBIR\n\n[FEC_MSM]\nBCR\n\n[FEC_MSR]\nBDR\n\n[FEC_QUE]\n???\n\n[FEC_TWO]\nPermitidas sólo dos teclas del teclado.\n\n[FEC_UMS]\nPor favor sólo teclas de ratón.\n\n[FEC_OMS]\nPermitida sólo una tecla del ratón.\n\n[FEC_UJS]\nPor favor sólo botones de joystick.\n\n[FEC_OJS]\nPermitido sólo un botón de joystick por acción.\n\n[FEC_PTL]\nUsar Bloquear objetivo al cambiar arma a izq.\n\n[FEC_PTR]\nUsar Bloquear objetivo al cambiar arma a dcha.\n\n[FEC_LBC]\nUsar Mirar a izq. con Mirar a la dcha.\n\n[FEC_JBO]\nJOY ~1~\n\n[FEC_WAR]\nAviso\n\n[FEC_OKK]\nAceptar\n\n[FEC_DLF]\nError al borrar.\n\n[FEC_SVU]\nError al guardar.\n\n[FEC_LUN]\nError al cargar. Archivo dañado, por favor bórralo.\n\n[FEC_PAD]\nGamepad\n\n[FEC_JOY]\nJoystick\n\n[FES_CSA]\nSeleccionar aspecto de la lista inferior:\n\n[FET_HRD]\nAJUSTES POR DEFECTO RESTAURADOS\n\n[FET_MST]\nCONDUCCIÓN CONTROLADA POR EL RATÓN\n\n[FEC_STR]\nNUM. INICIO\n\n[FET_MIG]\nIZQUIERDA, DERECHA, RUEDA DEL RATÓN PARA AJUSTAR\n\n[FET_CIG]\nRETROCESO PARA QUITAR - BIR, VOLVER A CAMBIAR\n\n[FET_DSN]\nApariencia predeterminada del jugador.bmp\n\n[FET_RSO]\nRESTAURADO AJUSTE ORIGINAL\n\n[FET_RSC]\nHARDAWARE NO DISPONIBLE. RESTAURADO AJUSTE ORIGINAL\n\n[FEA_3DH]\nHARDWARE DE SONIDO\n\n[FEA_SPK]\nAJUSTE DE ALTAVOCES\n\n[FEM_LOD]\nDIST. DE REPRESENTACIÓN\n\n[FEM_VSC]\nSINCRONÍA DE IMAGEN\n\n[FEM_FRM]\nLIMITADOR DE CUADROS\n\n[FEM_MM]\nMENÚ PRINCIPAL\n\n[FED_RES]\nRESOLUCIÓN DE PANTALLA\n\n[FET_CTL]\nCONFIGURAR MANDO\n\n[FET_OPT]\nOPCIONES\n\n[FEC_MSH]\nSENSIBILIDAD DEL RATÓN\n\n[FEC_IVV]\nINVERTIR VERTICALIDAD RATÓN\n\n[FEC_FNC]\nF~1~\n\n[FEC_IRT]\nINSERT\n\n[FEC_DLL]\nSUPR\n\n[FEC_HME]\nINICIO\n\n[FEC_END]\nFIN\n\n[FEC_PGU]\nRE PÁG\n\n[FEC_PGD]\nAV PÁG\n\n[FEC_UPA]\nARRIBA\n\n[FEC_DWA]\nABAJO\n\n[FEC_LFA]\nIZDA\n\n[FEC_RFA]\nDCHA\n\n[FEC_NUM]\nNUM.\n\n[FEC_NMN]\nNUM. ~1~\n\n[FEC_FWS]\nNUM. /\n\n[FEC_PLS]\nNUM. +\n\n[FEC_MIN]\nNUM. -\n\n[FEC_DOT]\nNUM. .\n\n[FEC_NLK]\nBLOQ NUM\n\n[FEC_ETR]\nINTRO\n\n[FEC_SLK]\nBLOQ DESPL\n\n[FEC_PSB]\nPAUSA INTER\n\n[FEC_BSP]\nRETROCESO\n\n[FEC_TAB]\nTAB\n\n[FEC_CLK]\nBLOQ MAYÚS\n\n[FEC_RTN]\nINTRO\n\n[FEC_LSF]\nMAYÚS IZQ\n\n[FEC_RSF]\nMAYÚS DCH\n\n[FEC_LCT]\nCTRL I\n\n[FEC_RCT]\nCTRL D\n\n[FEC_LAL]\nALT I\n\n[FEC_RAL]\nALT D\n\n[FEC_LWD]\nWIN I\n\n[FEC_RWD]\nWIN D\n\n[FEC_WRC]\nAPMENÚ\n\n[FEC_SPC]\nESPACIO\n\n[WIN_TTL]\nGrand Theft Auto VC\n\n[WIN_95]\nGrand Theft Auto VC no se puede ejecutar bajo W95\n\n[WIN_DX]\nGrand Theft Auto VC necesita al menos la versión 8.1 de DirectX\n\n[FET_EIG]\nNO SE PUEDE DEFINIR UN CONTROL PARA ESTA ACCIÓN\n\n[FET_DAM]\nMODELADO ACÚSTICO DINÁMICO\n\n[FEQ_SRE]\n¿Seguro que quieres salir? Se perderán todos los progresos desde la última partida guardada. ¿Quieres proceder?\n\n[FEQ_SRW]\n¿Seguro que quieres salir del juego?\n\n[FET_QG]\nSALIR DEL JUEGO\n\n[FEN_STA]\nINICIAR JUEGO\n\n[FET_PAU]\nMENÚ PAUSA\n\n[REPLAY]\nVOLVER A JUGAR\n\n[FEC_ANS]\nAcción\n\n[CVT_MSG]\nConvertir texturas a un formato óptimo para tu tarjeta de vídeo\n\n[FEC_SFT]\nMAYÚS\n\n[FEH_VMP]\nVER MAPA\n\n[FES_DEE]\n¡Error al eliminar! Por favor, inténtalo de nuevo.\n\n[FES_CMP]\n¡Error al guardar! Por favor, inténtalo de nuevo.\n\n[FESZ_WR]\nGuardando partida actual. Por favor, espera...\n\n[FELD_WR]\nCargando el juego. Por favor, espera...\n\n[FEDL_WR]\nEliminando partida guardada. Por favor, espera...\n\n[PCRESRT]\nIniciando nueva partida. Por favor, espera...\n\n[FET_STI]\nControles estándar\n\n[FET_CTI]\nControles clásicos\n\n[FEH_NA]\nOPCIÓN NO DISPONIBLE\n\n[FEH_MPH]\nRATÓN, CURSORES PARA MOVERSE - RE. PAG, AV. PAG, RUEDA RATÓN PARA ZOOM, L - LEYENDA\n\n[FEA_MP3]\nREPRODUCTOR MP3\n\n[NO_PCCD]\nPor favor, introduce tu CD de GTA Vice City o pulsa ESC para cancelar\n\n[FEH_SSA]\nCURSORES PARA MOVERSE - S PARA GUARDAR EN UN ARCHIVO\n\n[FES_CMI]\nÚLTIMA MISIÓN SUPERADA\n\n[FET_STS]\nESTADÍSTICAS GUARDADAS EN 'STATS.HTML' + 'STATS.TXT'\n\n[WIN_VDM]\nGrand Theft Auto VC no pudo encontrar suficiente memoria de vídeo disponible\n\n[FEC_ERI]\n¡Error! Una o más acciones de control no están vinculadas a ninguna tecla o botón. Comprueba que todas las acciones de control estén definidas.\n\n[FEC_TFU]\nTorreta + Inclinar arriba\n\n[FEC_TFD]\nTorreta + Inclinar abajo\n\n[FET_RIG]\nELIGE UN NUEVO CONTROL PARA ESTA ACCIÓN\n\n[FEA_NM3]\nNO SE ENCONTRARON ARCHIVOS MP3\n\n[FEA_MPB]\nSUBIR VOLUMEN DE MP3\n\n[FEA_MUS]\nVOLUMEN DE MÚSICA\n\n[FEA_SFX]\nVOLUMEN DE EFECTOS\n\n[CVT_ERR]\nTe has quedado sin espacio en el disco duro. Por favor, antes de seguir consigue algo de espacio en tu disco duro. Pulsa ESC para cancelar.\n\n[FEA_ADP]\nDETECTAR EL HARDWARE AUTOMÁTICAMENTE\n\n{=================================== MISSION TABLE AMBULAE ===================================}\n\n[ATUTOR2:AMBULAE]\n~g~Lleva a los pacientes al hospital CON CUIDADO. Cada bache reduce sus posibilidades de supervivencia.\n\n[A_FULL:AMBULAE]\n~r~¡Ambulancia llena!\n\n[A_FAIL2:AMBULAE]\n~r~¡Tu falta de urgencia ha sido mortal para el paciente!\n\n[A_FAIL3:AMBULAE]\n~r~¡El paciente está muerto!\n\n[A_PASS:AMBULAE]\n¡Rescatado!\n\n[A_COMP2:AMBULAE]\n¡Nunca te cansarás!\n\n[A_CANC:AMBULAE]\n~r~¡Misión de ATS cancelada!\n\n[A_COMP3:AMBULAE]\n¡Misiones de ATS completadas! ¡Nunca te cansarás cuando estés corriendo!\n\n[ALEVEL:AMBULAE]\nMisión de ATS nivel ~1~\n\n[A_FAIL1:AMBULAE]\nMisión de ATS terminada.\n\n[A_SAVES:AMBULAE]\nPERSONAS SALVADAS: ~1~\n\n[A_COMP1:AMBULAE]\nMisiones de ATS completas: ~1~ $\n\n{=================================== MISSION TABLE ASSIN1 ===================================}\n\n[ASM1_5:ASSIN1]\n~r~¡Completó sus entregas!\n\n[ASM1_6:ASSIN1]\nEntregas restantes:\n\n[ASM1_7:ASSIN1]\n~g~Carl Pearson, repartidor de pizza. Mátale antes que finalice el reparto.\n\n[ASM1_A:ASSIN1]\nSr. Teal, su ayuda en erradicar a esos forasteros fue inestimable para el negocio. Tengo más trabajo para usted y más cercano a la ''intervención''.\n\n[ASM1_D:ASSIN1]\nSr. Teal, su ayuda en erradicar a esos forasteros fue inestimable para el negocio.\n\n{=================================== MISSION TABLE ASSIN2 ===================================}\n\n[ASM2_1:ASSIN2]\n~g~La Sra. Dawson dejará pronto la joyería de Vice Point. Mátala. Debe parecer un accidente de coche.\n\n[ASM2_3:ASSIN2]\n~g~¡Va a estallar! ¡Largo de aquí!\n\n[ASM2_4:ASSIN2]\n~r~Dañaste su coche ¡y ni siquiera está en él! ¡Ahora no se subirá ahí!\n\n[ASM2_5:ASSIN2]\n~r~¡Se escapó!\n\n[ASM2_6:ASSIN2]\n~r~¡Estabas demasiado cerca de la escena del ''accidente''!\n\n[ASM2_7:ASSIN2]\n~g~¡No utilices armas! ¡Se supone que debe parecer un accidente! ¡En vez de eso, sácala de la carretera!\n\n[ASM2_8:ASSIN2]\n~g~Debes hacer que la muerte de la Sra. Dawson parezca un accidente. No utilices ningún arma.\n\n[ASM2_9:ASSIN2]\n~g~¡Necesitas un coche para este trabajo!\n\n[ASM2_10:ASSIN2]\n~g~Cuando el coche explote en llamas vete lo más lejos posible de la escena del accidente.\n\n[ASM2_11:ASSIN2]\n¡Ayúdame!\n\n[ASM2_12:ASSIN2]\n¡Que alguien me ayude!\n\n[ASM2_13:ASSIN2]\n¡oh, Dios mío!\n\n[ASM2_A:ASSIN2]\nFelicidades por un trabajo bien hecho, Sr. Teal. Mi cliente está muy satisfecho.\n\n[ASM2_2:ASSIN2]\nsalud:\n\n{=================================== MISSION TABLE ASSIN3 ===================================}\n\n[ASM3_11:ASSIN3]\nTIEMPO:\n\n[ASM3_C:ASSIN3]\nUna banda europea planea atracar un banco en Vice City. A mis jefes les gustaría que esto no sucediese.\n\n[ASM3_D:ASSIN3]\nCada miembro de la banda tiene una tapadera mientras está aquí en Vice City. Algunos tienen trabajos sin importancia y otros están de vacaciones.\n\n[ASM3_E:ASSIN3]\nCada objetivo y sus posibles paraderos están pegados con cinta adhesiva bajo el teléfono.\n\n[ASM3_14:ASSIN3]\n~g~Dick Tanner está ubicado junto al DBP de Seguridad en Ocean Drive.\n\n[ASM3_15:ASSIN3]\n~g~Marcus Hammond y Franco Carter están ubicados junto a la joyería en Vice Point.\n\n[ASM3_16:ASSIN3]\n~g~Nick Kong está en su barco cerca de Washington Beach.\n\n[ASM3_18:ASSIN3]\n~g~¡No te acerque demasiado al objetivo o te descubrirá y tendrás que perseguirle hasta atraparle!\n\n[ASM3_19:ASSIN3]\n~g~¡Te ha visto! ¡Acaba con él!\n\n[ASM3_20:ASSIN3]\n~g~¡Te han visto! ¡Asegúrate de acabar con los dos!\n\n[ASM3_21:ASSIN3]\n~r~¡No mataste a todos los miembros de la banda a tiempo!\n\n[ASM3_22:ASSIN3]\n~g~¡No te acerques demasiado a los objetivos o te descubrirán e intentarán escapar.\n\n[ASM3_12:ASSIN3]\n~g~Se ha dejado cerca una selección de armas en caso de necesidad. Dispones de ~h~9 MINUTOS ~g~para matar a todos los miembros de la banda.\n\n[ASM3_13:ASSIN3]\n~g~Mike Griffin está trabajando en una valla de publicidad en Washington.\n\n[ASM3_17:ASSIN3]\n~g~Charlie Dilson está dando una vuelta en su moto en Washington.\n\n{=================================== MISSION TABLE ASSIN4 ===================================}\n\n[ASM4_10:ASSIN4]\n~g~¡Parece que no eres el único que persigue el maletín! ¡Llévalo deprisa a Ammu- Nation!\n\n[ASM4_12:ASSIN4]\nDistancia:\n\n[ASM4_15:ASSIN4]\n~g~Busca el rifle de francotirador hacia tu derecha.\n\n[ASM4_16:ASSIN4]\n~g~Observa a la mujer de la galería, bajará por las escaleras mecánicas y preguntará a alguien la hora.\n\n[ASM4_17:ASSIN4]\n~g~Solamente cuando la conversación haya concluido, mata a la persona con la que habló, pero no la mates a ella.\n\n[ASM4_18:ASSIN4]\n~g~Cuando el objetivo haya muerto, recupera el maletín y llévalo a Ammu-Nation, en el centro.\n\n[ASM4_19:ASSIN4]\n~g~Mantén tu distancia del objetivo, la barra de distancia de la parte superior de la pantalla te indica lo cerca que estás del objetivo.\n\n[ASM4_20:ASSIN4]\n~g~No dejes que se llene o te verá.\n\n[ASM4_21:ASSIN4]\n~g~¡Recoge el maletín!\n\n[ASM4_22:ASSIN4]\n~g~Lleva el maletín a Ammu-Nation, en el centro.\n\n[ASM4_23:ASSIN4]\n~g~¡Te ha visto y se escapa, atrápale y consigue el maletín!\n\n[ASM4_25:ASSIN4]\n~r~¡Has matado a la mujer, idiota!\n\n[ASM4_26:ASSIN4]\n~r~¡El objetivo ha subido a su avión!\n\n[ASM4_27:ASSIN4]\n~r~¡El objetivo te ha visto! ¡Deberías mantener tu distancia!\n\n[ASM4_28:ASSIN4]\n~r~¡El objetivo te ha visto! ¡Te ha escuchado disparar el arma!\n\n[ASM4_29:ASSIN4]\n~r~¡Mátale sólo después que haya hablado con la mujer!\n\n[ASM4_A:ASSIN4]\nEs hora de ir a por el pez gordo, Sr. Teal. Hay un rifle a su derecha, tras la maceta.\n\n[ASM4_B:ASSIN4]\nObserve a la mujer que está en la galería por encima de los mostradores de facturación. Caminará por entre la gente y le preguntará a alguien la hora.\n\n[ASM4_C:ASSIN4]\nDebe matar a esa persona, recoger el maletín y llevarlo al lugar adherido con cinta bajo el teléfono.\n\n{=================================== MISSION TABLE ASSIN5 ===================================}\n\n[ASM5_A:ASSIN5]\nUn valioso canje va a tener lugar en el tejado de la compañía de helados Cherry Popper.\n\n[ASM5_B:ASSIN5]\nLiquide a todos los implicados, robe el maletín y llévelo al helipuerto del aeropuerto.\n\n[ASM5_C:ASSIN5]\nHay una puerta a su izquierda que conduce a la parte trasera de la fábrica.\n\n[ASM5_1:ASSIN5]\n~g~Entra al complejo por detrás de la compañía de helados Cherry Popper y dirígete al tejado donde va a tener lugar el trato.\n\n[ASM5_2:ASSIN5]\n~g~Consigue el maletín y llévalo al helipuerto del aeropuerto.\n\n[ASM5_3:ASSIN5]\n~g~¡Lleva el maletín al helipuerto del aeropuerto!\n\n{=================================== MISSION TABLE BANKJ1 ===================================}\n\n[WANTED1:BANKJ1]\n~g~¡Quítate de encima a los polis y pierde tu nivel de se busca!\n\n[BJM1_A:BANKJ1]\n¡Tommy! ¡Eh, Tommy, mira esto, es genial! ¡He hecho que nos instalen un minibar!\n\n[BJM1_B:BANKJ1]\nTenemos todo un bar abajo, Ken.\n\n[BJM1_C:BANKJ1]\nSí, sí, vale. Bueno, tengo la pizarra que pediste.\n\n[BJM1_D:BANKJ1]\nEso es lo bueno de estudiar derecho: te enseñan a seguir las instrucciones.\n\n[BJM1_E:BANKJ1]\nNecesito un hombre para la caja fuerte.\n\n[BJM1_F:BANKJ1]\nDe acuerdo, bueno, déjame pensar... caja fuerte, caja fuerte, caja fuerte, caja fuerte... ¡Lo tengo! ¡Este tipo te va a encantar!\n\n[BJM1_G:BANKJ1]\nAh, ese idiota no. Está encerrado.\n\n[BJM1_H:BANKJ1]\n¿Encerrado dónde?\n\n[BJM1_I:BANKJ1]\nEn la celda de una comisaría esperando el traslado.\n\n[BJM1_J:BANKJ1]\nCreo que está a punto de conseguir la libertad condicional...\n\n[BJM1_1:BANKJ1]\n~g~¡Libera a Cam Jones de la comisaría de policía!\n\n[BJM1_3:BANKJ1]\n~g~Encontrarás algo útil en el vestuario de la comisaría.\n\n[BJM1_21:BANKJ1]\n~g~Puedes encontrar la llave de las celdas en el piso de arriba de la comisaría.\n\n[BNK1_7:BANKJ1]\n¿Cam Jones?\n\n[BNK1_8:BANKJ1]\n¡Te voy a sacar de aquí!\n\n[BNK1_10:BANKJ1]\nSí, soy yo...\n\n[BNK1_11:BANKJ1]\n¡Lo que tú digas!\n\n[BNK1_13:BANKJ1]\nVoy a hacer un trabajo y tu serás mi revienta cajas fuertes.\n\n[BNK1_14:BANKJ1]\n¡Eso es mejor que pudrirse en una celda!\n\n[BJM1_22:BANKJ1]\n~g~¡Lleva a Cam de vuelta a su casa!\n\n[BJM1_23:BANKJ1]\n~g~¡Necesitas coger la tarjeta llave primero!\n\n[BNK1_12:BANKJ1]\n¡Piérdeles el rastro y llévame a mi casa!\n\n[BJM1_20:BANKJ1]\n¡Guarda el arma o te enfréntate a las consecuencias!\n\n[BJM1_5:BANKJ1]\n¡Sólo personal autorizado más allá de este punto!\n\n[BJM1_2:BANKJ1]\n~r~¡Se supone que tenías que sacar a rastras a Cam, no matarle!\n\n[BJM1_4:BANKJ1]\n¡Está armado! ¡Mátale!\n\n{=================================== MISSION TABLE BANKJ2 ===================================}\n\n[BJM2_A:BANKJ2]\nNecesitamos a un atracador. ¿Conoces a alguno?\n\n[BJM2_B:BANKJ2]\nEh, Tommy, Tommy, Tommy, esta mierda te pone a tono, tío.\n\n[BJM2_C:BANKJ2]\n¡Guauuuuu!\n\n[BJM2_D:BANKJ2]\n¡Yo podría ser tu atracador! ¡Manos arriba! ¡Manos arriba!\n\n[BJM2_E:BANKJ2]\nTú no eres un atracador, tú eres un idiota.\n\n[BJM2_F:BANKJ2]\nAhora ponte una copa y cállate.\n\n[BJM2_G:BANKJ2]\nEh. ¡Quítate de mi camino! Sí, sí, sí, eh, eh.\n\n[BJM2_H:BANKJ2]\n¿Cam, tú qué opinas?\n\n[BJM2_I:BANKJ2]\nBueno, el mejor tirador de esta ciudad es un tipo llamado Cassidy.\n\n[BJM2_J:BANKJ2]\n¿Seguro?\n\n[BJM2_K:BANKJ2]\nSí. Un militar, o al menos él piensa que lo es.\n\n[BJM2_L:BANKJ2]\nDudo que estuviese alguna vez en el ejército, pero desde luego sabe manejar las armas.\n\n[BJM2_M:BANKJ2]\nEstará en el campo de tiro.\n\n[BJM2_2A:BANKJ2]\n¿Tú eres Phil Cassidy?\n\n[BJM2_2B:BANKJ2]\n¿Por qué?\n\n[BJM2_2C:BANKJ2]\nEstoy buscando a un hombre que sepa manejar un arma. Pero ahora que te veo, no estoy muy convencido.\n\n[BJM2_2D:BANKJ2]\nHijo, podría quitarte una mosca de la cabeza de un solo disparo a 100 metros.\n\n[BJM2_2E:BANKJ2]\nOh, ¿de verdad?\n\n[BJM2_2F:BANKJ2]\nSí. Aprendí en el ejército.\n\n[BJM2_2G:BANKJ2]\n¿Se suele disparar a las moscas en el ejército? Me alegra no pagar impuestos.\n\n[BJM2_2H:BANKJ2]\n¿Intentas ser gracioso?\n\n[BJM2_2I:BANKJ2]\n~n~\n\n[BJM2_2J:BANKJ2]\nVamos a disparar.\n\n[BJM2_1:BANKJ2]\n~g~Ve a Ammu-Nation en el centro de la ciudad y habla con Phil Cassidy.\n\n[BJM2_3:BANKJ2]\nTASA DE IMPACTOS: ~1~%\n\n[BJM2_4:BANKJ2]\nPUNTUACIÓN PRIMERA FASE: ~1~\n\n[BJM2_6:BANKJ2]\nPUNTUACIÓN SEGUNDA FASE: ~1~\n\n[BJM2_7:BANKJ2]\nPUNTUACIÓN TOTAL DE DISPARO: ~1~\n\n[BJM2_9:BANKJ2]\n~g~Ve al punto de inicio de la segunda fase.\n\n[BJM2_11:BANKJ2]\n~r~¡Phil está muerto!\n\n[BJM2_12:BANKJ2]\n~r~¡Uno de los tiradores está muerto!\n\n[BJM2_14:BANKJ2]\n~g~¡Pasa a la siguiente fase!\n\n[BJM2_15:BANKJ2]\nPUNTUACIÓN:\n\n[BJM2_17:BANKJ2]\n~g~Ve y habla con Phil.\n\n[BJM2_18:BANKJ2]\nPUNTUACIÓN A SUPERAR:\n\n[BJM2_19:BANKJ2]\n~g~¡Acierta a tantos blancos como puedas dentro del límite de tiempo!\n\n[BJM2_22:BANKJ2]\n~r~¡Has abandonado el campo de tiro!\n\n[BJM2_23:BANKJ2]\n~g~Si abandonas el campo de tiro durante la competición, fracasarás en la misión.\n\n[BJM2_24:BANKJ2]\n~g~El objetivo más cercano vale un punto.\n\n[BJM2_25:BANKJ2]\n~g~El objetivo del medio vale dos puntos.\n\n[BJM2_27:BANKJ2]\n~g~Todos los objetivos de esta ronda valen un punto.\n\n[BNK2_2:BANKJ2]\nAPUNTA, 3, 2, 1... ¡FUEGO!\n\n[BNK2_3:BANKJ2]\n¡ZONA DESPEJADA!\n\n[BNK2_4:BANKJ2]\n¡Yupiiiiiii!\n\n[BNK2_5:BANKJ2]\n¡No podrías darle ni a un elefante a 2 metros!\n\n[BNK2_7:BANKJ2]\nEntonces, ¿quieres hacerme un favor y ayudarme a preparar un atraco?\n\n[BNK2_8:BANKJ2]\nHijo, disparando de ese modo, si me pidieras que sea tu mujer, te diría que sí.\n\n[BNK2_9A:BANKJ2]\nHijo, mejor será que te vayas y te metas tus ideas y palabrería donde te quepan. Eres una mierda disparando.\n\n[BNK2_9B:BANKJ2]\nEres una mierda disparando.\n\n[BJM2_28:BANKJ2]\nPUNTUACIÓN RONDA TRES: ~1~\n\n[BJM2_20:BANKJ2]\n~g~¡La ronda se acabará cuando te quedes sin ~w~tiempo ~g~o ~w~munición~g~!\n\n[BJM2_26:BANKJ2]\n~g~El objetivo más lejano vale tres puntos.\n\n[BNK2_1:BANKJ2]\nMUNICIÓN CARGADA\n\n[RANGE_1:BANKJ2]\nPUNTUACIÓN POR DISPARO: ~1~\n\n[BJM2_2:BANKJ2]\n~g~Para abandonar la ronda, pulsa ~h~~k~~PED_JUMPING~.\n\n[BJM2_N:BANKJ2]\nTranqui.\n\n{=================================== MISSION TABLE BANKJ3 ===================================}\n\n[BJM3_A:BANKJ3]\nLas cosas empiezan a ir bien.\n\n[BJM3_B:BANKJ3]\n¿Cuál es el plan, Tommy? ¿Qué pasa, amigo?\n\n[BJM3_C:BANKJ3]\nEl plan es que tú sigas haciendo el imbécil. En fin, necesitamos a un conductor.\n\n[BJM3_D:BANKJ3]\nTommy, yo lo haré. Sé conducir.\n\n[BJM3_E:BANKJ3]\nNecesitamos a Hilary, señor, no a un picapleitos charlatán.\n\n[BJM3_F:BANKJ3]\nHilary es nuestra mejor opción. Seguro que no has visto nunca conducir a nadie tan rápido. Voy a darle un toque.\n\n[BJM3_G:BANKJ3]\nEh, Hil, soy Phil. ¿Cómo te va? No, no hables. Recordaremos los viejos tiempos más tarde. ¿Quieres hacerme un favor?\n\n[BJM3_H:BANKJ3]\nTengo a un tipo del norte... No, no, no creo que sirviese en el ejército, pero quiere un conductor.\n\n[BJM3_I:BANKJ3]\nPor un poco de acción. De acuerdo, comprendo.\n\n[BJM3_J:BANKJ3]\n¿Qué dijo?\n\n[BJM3_K:BANKJ3]\nBueno, lo hará, no hay problema. Bueno, podría haber un pequeño problema... Verás, tiene miedo al abandono.\n\n[BJM3_L:BANKJ3]\nY parece que no trabajará para nadie que no pueda derrotarle. Tiene algo que ver con su madre o algo así.\n\n[BJM3_M:BANKJ3]\nDe todas formas primero quiere echarte una carrera, dice que se encontrará contigo fuera...\n\n[BJM3_2A:BANKJ3]\n¿Eres Tommy? Por supuesto que eres Tommy, quiero decir,\n\n[BJM3_2B:BANKJ3]\n¿quién más querría hablar conmigo?\n\n[BJM3_2C:BANKJ3]\nVale. Esto es lo que hay.\n\n[BJM3_2D:BANKJ3]\nConduciré para ti solamente si me demuestras que conduces bien.\n\n[BJM3_2E:BANKJ3]\nDéjame tirado, y nunca te perdonaré.\n\n[BJM3_2:BANKJ3]\n~r~¡Hilary está muerto!\n\n[BJM3_4:BANKJ3]\n~g~¡Necesitas un coche para participar!\n\n[BNK3_1:BANKJ3]\nVale. Te llevaré pero por favor, machácame un poco.\n\n[BNK3_3A:BANKJ3]\nCarrera callejera ilegal en progreso en Vice Point.\n\n[BNK3_3B:BANKJ3]\nLlamando a todos los agentes.\n\n[BNK3_3C:BANKJ3]\nCorredores callejeros, ¡esto es ilegal y no está permitido!\n\n{=================================== MISSION TABLE BANKJ4 ===================================}\n\n[BNK4_A:BANKJ4]\n~w~Como podéis ver, caballeros, éste va a ser el dinero más fácil que hayamos ganado jamás.\n\n[BNK4_B:BANKJ4]\n~w~Tommy, de verdad, tienes que plantearte seriamente el meterte en la abogacía.\n\n[BNK4_C:BANKJ4]\n~w~Pero, ¿qué coño te estás fumando, tío? ¡Este no es un plan sencillo!\n\n[BNK4_D:BANKJ4]\n~w~Bueno, de todas formas, ¿quién necesita un plan sencillo?\n\n[BNK4_E:BANKJ4]\n~w~Mira el comunismo, bien, pues ese era un plan sencillo. Y jodió bien a Rusia ¿no?\n\n[BNK4_F:BANKJ4]\n~w~Cálmate, ¿vale? Con un equipo como éste, no va a haber problemas.\n\n[BNK4_G:BANKJ4]\n~w~Tenemos a Cam en la caja fuerte. ¿Phil? Tú y yo nos encargaremos de la seguridad y Hilary conducirá el coche de huída.\n\n[BNK4_H:BANKJ4]\n~w~Uh, je, je, ¿no te olvidas de alguien? ¿Alguien que te ayudó siempre en esta ciudad? ¿Alguien...?\n\n[BNK4_I:BANKJ4]\n~w~Ken... Ken, es cierto. Aquí Ken, él nos lavará el dinero y mantendrá las bebidas frías.\n\n[BNK4_J:BANKJ4]\n~w~No comprendo qué se supone que debo hacer aquí.\n\n[BNK4_K:BANKJ4]\n~w~Mira, es sencillo. ¿No has visto nunca una película?\n\n[BNK4_L:BANKJ4]\n~w~Entramos en el banco, enseñamos las armas y nos marchamos siendo hombres muy ricos.\n\n[P_DEAD:BANKJ4]\n~r~¡Phil está muerto!\n\n[C_DEAD:BANKJ4]\n~r~¡Cam está muerto!\n\n[H_DEAD:BANKJ4]\n~r~¡Hilary está muerto!\n\n[P_HIND:BANKJ4]\n~r~¡Has perdido a Phil!\n\n[C_HIND:BANKJ4]\n~r~¡Cam se ha quedado atrás!\n\n[H_HIND:BANKJ4]\n~r~¡Hilary ha sido abandonado!\n\n[GETCAR:BANKJ4]\n~g~¡Sube en el coche de escapada para hacer el trabajito del banco!\n\n[TRASHED:BANKJ4]\n~r~¡DESTROZASTE EL COCHE DE FUGA!\n\n[BNK4_1:BANKJ4]\nYo conduciré.\n\n[BNK4_2:BANKJ4]\nGenial. Un pasajero. Espera a que les hable de esto al grupo.\n\n[BNK4_3A:BANKJ4]\n¡Eh, cuidado con las ruedas, Tommy!\n\n[BNK4_3B:BANKJ4]\n¡Tommy, Hilary está ocupando mucho espacio!\n\n[BNK4_3C:BANKJ4]\n¡No es verdad!\n\n[BNK4_3D:BANKJ4]\n¡Sí!\n\n[BNK4_3E:BANKJ4]\nEh, callaos los dos o iréis andando.\n\n[BNK4_3F:BANKJ4]\nSí, Hilary.\n\n[BNK4_3I:BANKJ4]\nPor el amor de Dios, Phil, deja de agitar esa cosa.\n\n[BNK4_3J:BANKJ4]\n¡Sí, le sacarás un ojo a alguien!\n\n[BNK4_3M:BANKJ4]\n¡Mi pequeña! ¡Está hecha un desastre!\n\n[BNK4_3O:BANKJ4]\nTe aferras a la ilusión de una permanencia perpetua...\n\n[BNK4_3P:BANKJ4]\n¿Qué?\n\n[BNK4_3Q:BANKJ4]\nCrees que todas las cosas durarán.\n\n[BNK4_3R:BANKJ4]\nLa juventud, los seres queridos, la pizza...\n\n[BNK4_3S:BANKJ4]\nTodo pasará o terminará y debes aceptar eso.\n\n[BNK4_3T:BANKJ4]\nSí, tienes razón. Gracias, Cam.\n\n[BNK4_3U:BANKJ4]\nNo hay de que.\n\n[BNK4_3V:BANKJ4]\nEh, Tommy, ¿por qué nos hemos detenido?\n\n[BNK4_4A:BANKJ4]\n~w~Hilary, sigue conduciendo en torno a la manzana.\n\n[BNK4_5:BANKJ4]\n~w~De acuerdo, Tommy, de acuerdo.\n\n[BNK4_6:BANKJ4]\n~w~¡ESTO ES UN ATRACO!\n\n[BNK4_7:BANKJ4]\n~w~¡QUE NADIE SE MUEVA!\n\n[BNK4_8:BANKJ4]\n~w~¡TODO EL MUNDO CONTRA ESA PARED!\n\n[BNK4_9:BANKJ4]\n¡Phil, quédate vigilando!\n\n[BNK4_10:BANKJ4]\n¡No problemo!\n\n[BNK4_11:BANKJ4]\nVamos, Cam, la cámara acorazada está arriba...\n\n[BK4_12A:BANKJ4]\n¡Maldición! ¡Es una Flange 9000!\n\n[BK4_12B:BANKJ4]\nPodría tardar horas en abrirla,\n\n[BK4_12C:BANKJ4]\no cinco minutos si encuentras al director.\n\n[BNK4_13:BANKJ4]\nIré a averiguar en qué agujero se ha metido.\n\n[BK4_14A:BANKJ4]\nPhil, ¿van bien las cosas?\n\n[BNK4_15:BANKJ4]\nSí. Todo está muy tranquilo.\n\n[BNK4_16:BANKJ4]\n¡Tú, ven conmigo!\n\n[BNK4_17:BANKJ4]\n¡De acuerdo! ¡De acuerdo! ¡Por favor, no dispare!\n\n[BNK4_18:BANKJ4]\n¡DIJE QUE NO SE MOVIESE NADIE!\n\n[BK4_19A:BANKJ4]\nTiene un cierre temporizado.\n\n[BK4_19B:BANKJ4]\n¡Podríais rendiros ahora mismo!\n\n[BK4_20A:BANKJ4]\nDiablos, puedo hacer un puente en el cierre temporizado,\n\n[BK4_20B:BANKJ4]\n¡Así que solo necesitaremos tu código de acceso y ya está!\n\n[BNK4_21:BANKJ4]\nQuédate aquí. Intenta algo y serás comida para los peces. ¿Lo captas?\n\n[BNK422A:BANKJ4]\nCam, ¿cuánto tiempo?\n\n[BK4_23A:BANKJ4]\n¡Dame cinco minutos!\n\n[BK4_24A:BANKJ4]\nVoy a comprobar qué tal va Phil, volveré.\n\n[BK4_24B:BANKJ4]\n¡Te dije que no tocases esa alarma!\n\n[BNK4_25:BANKJ4]\n¡Los de operaciones especiales estarán aquí en cualquier momento!\n\n[BNK4_27:BANKJ4]\n¡Me vendría bien un poco de ayuda aquí, Tommy!\n\n[BNK4_28:BANKJ4]\n¡SWAT de Vice City! ¡Estáis rodeados!\n\n[BNK4_29:BANKJ4]\n¿Rodeados?\n\n[BNK4_30:BANKJ4]\nLa están cagando, ¡bastardos corruptos!\n\n[BK4_31A:BANKJ4]\n¡Tommy! ¡La cámara acorazada está abierta!\n\n[BK4_34A:BANKJ4]\nDe acuerdo, tenemos el fondo de pensiones de los SWAT. ¡Salgamos de aquí!\n\n[BK4_34B:BANKJ4]\n¡De acuerdo, vosotros lo habéis pedido! ¡Habéis tenido vuestra última oportunidad!\n\n[BK4_35A:BANKJ4]\n¡Van a arrasar el lugar!\n\n[BK4_35B:BANKJ4]\n¡A cubierto!\n\n[BNK4_94:BANKJ4]\n~w~De acuerdo chicos. Ha sido tan fácil como lo habíamos planeado.\n\n[BM_DEAD:BANKJ4]\n~r~¡Necesitas al director del banco vivo!\n\n[ASSET_A:BANKJ4]\n¡ATRACO AL BANCO COMPLETADO!\n\n[ASSET_B:BANKJ4]\n~g~El Club Malibú generará ahora unos ingresos máximos de hasta ~1~ $ al día. ¡Asegúrate de recaudarlos regularmente!\n\n[IDIOT:BANKJ4]\n~r~ Eso es, ve por ahí vestido como un chiflado y llamando la atención, ¡IDIOTA!\n\n{=================================== MISSION TABLE BARON1 ===================================}\n\n[COK1_A:BARON1]\nVamos nena, vamos, sí, ¡sí!\n\n[COK1_B:BARON1]\n¡Estúpido caballo! ¡Te cortaré la cabeza!\n\n[COK1_C:BARON1]\n¿Quién es este gilipollas?\n\n[COK1_D:BARON1]\nTommy Vercetti, ¿me recuerdas?\n\n[COK1_E:BARON1]\nPerdóname, estoy un poco alterado. ¡Nunca te fíes de un maldito caballo!\n\n[COK1_F:BARON1]\nHiciste un buen trabajo... ahora trabajas para mí.\n\n[COK1_H:BARON1]\nComo dije amigo, trabajas para mí. Ahora, cállate. Algún Judas me ha traicionado.\n\n[COK1_I:BARON1]\nÉl cree que no sé cuando dinero debería sacar con esto, pero robar un 3% es tan malo como robar el 100%.\n\n[COK1_J:BARON1]\nNadie me hace esto a mí. ¡NADIE!\n\n[COK1_K:BARON1]\n¡Le sigues desde su apartamento y ves a dónde va! Más tarde, le mataremos.\n\n[COK1_1:BARON1]\n¡Mierda!\n\n[COK1_2:BARON1]\n¡Demasiado lento, abuelo!\n\n[COK1_4:BARON1]\nPerdedor.\n\n[COK1_5:BARON1]\n¡Mejor sigue corriendo, gilipollas!\n\n[COK1_8:BARON1]\n~g~¡Rápido! ¡Consigue un vehículo y síguele!\n\n[COK1_9:BARON1]\n~r~¡Se supone que debes seguirle, no matarle!\n\n[COK1_10:BARON1]\n~r~Ve a la casa del ladrón y descubre dónde esconde el dinero.\n\n[COK1_11:BARON1]\n~g~Echa un vistazo por su ventana.\n\n[COK1_7:BARON1]\n~g~¡Se ha escapado por el tejado, ve tras él pero no le mates!\n\n[COK1_G:BARON1]\nTrabajo por dinero.\n\n{=================================== MISSION TABLE BARON2 ===================================}\n\n[COK2_A:BARON2]\n¿Qué clase de tonto incompetente eres?\n\n[COK2_B:BARON2]\n¡TONTO! ¡TONTO! ¡TONTO! ¡TONTO!\n\n[COK2_C:BARON2]\nTommy...\n\n[COK2_D:BARON2]\n¿Qué pasa, Ricardo?\n\n[COK2_E:BARON2]\nEstos idiotas... Siempre intentan joderle a uno.\n\n[COK2_F:BARON2]\nEse es el problema de este negocio.\n\n[COK2_G:BARON2]\n¿Qué crees que estás haciendo?\n\n[COK2_H:BARON2]\nEstos mamones me han fallado miserablemente.\n\n[COK2_I:BARON2]\nPronto cualquier madre o padre creerán que pueden vender farlopa en Vice City.\n\n[COK2_J:BARON2]\n¿Y ahora qué, eh? ¿La apestosa Mafia?\n\n[COK2_K:BARON2]\nEse antro de mafiosos es una fortaleza inexpugnable desde el suelo,\n\n[COK2_L:BARON2]\nasí que Quentin... ¡Quentin! ¡QUENTIN!\n\n[COK2_M:BARON2]\n¡Volará sobre la zona!\n\n[COK2_N:BARON2]\n¡Hacedles desaparecer!\n\n[COK2_O:BARON2]\n¿Qué crees que estás haciendo?\n\n[COK2_P:BARON2]\n¿Qué haces aquí?\n\n[COK2_Q:BARON2]\nHe estado haciendo preguntas por ahí, y es obvio\n\n[COK2_R:BARON2]\nque Diaz se saltó el trato y se cargó a mi hermano.\n\n[COK2_S:BARON2]\n¡Y te matará a ti también!\n\n[COK2_T:BARON2]\n¡Puedo encargarme de Diaz!\n\n[COK2_U:BARON2]\nNo. ¡Escúchame! Yo me encargaré de Diaz...\n\n[COK2_V:BARON2]\nEstá empezando a confiar en mí.\n\n[COK2_1:BARON2]\nHay una cosa que me mosquea... ¿por qué Quentin?\n\n[COK2_2:BARON2]\nNo sé, siempre me ha gustado... Quentin Vance...\n\n[COK2_3:BARON2]\n¿Vance? ¿Tu nombre es Lance Vance?\n\n[COK2_4:BARON2]\n¡Eh! ¡Ya tuve bastante con eso en la escuela!\n\n[COK2_5:BARON2]\n¿Alguna vez has disparado uno de esos desde un helicóptero?\n\n[COK2_8:BARON2]\nEn fin, ¿a dónde nos dirigimos?\n\n[COK2_9:BARON2]\nA Prawn Island.\n\n[COK2_13:BARON2]\nLance Vance. Pobre desgraciado.\n\n[COK2_14:BARON2]\nBien, casi hemos llegado.\n\n[COK2_15:BARON2]\nDaremos un par de pasadas.\n\n[COK2_16:BARON2]\nAsí que elimina a tantos como puedas.\n\n[COK2_17:BARON2]\nDespués te dejaré abajo y te las arreglarás solo.\n\n[COK2_20:BARON2]\n¡Mierda! ¡Ésto es una zona de guerra! ¡Elimina a algunos de esos pistoleros!\n\n[COK2_21:BARON2]\n¡Nos están alcanzando, tío!\n\n[COK2_22:BARON2]\n¡Arreglar esta cosa no sale barato! ¡Elimínalos!\n\n[COK2_23:BARON2]\nVale, de ahora en adelante es cosa tuya... ¡Buena suerte, hermano!\n\n[COK2_24:BARON2]\nHelicóptero:\n\n[COK2_25:BARON2]\n~g~Ve y recoge el dinero del tejado.\n\n[COK2_27:BARON2]\n¡Estás en mi territorio, gilipollas!\n\n[COK2_28:BARON2]\n¡Vas a desaparecer!\n\n[COK2_6:BARON2]\nNo. Practicaré un poco por el camino.\n\n[OPEN_B:BARON2]\nLos controles policiales con dirección a la península han sido levantados\n\n{=================================== MISSION TABLE BARON3 ===================================}\n\n[COK3_A:BARON3]\nAhora ya no os sentís tan complacidas, ¿eh?\n\n[COK3_B:BARON3]\n~n~\n\n[COK3_C:BARON3]\n¡Guau! Mira hacia donde mueves esa cosa.\n\n[COK3_D:BARON3]\nYa no habrá más mierda de paloma en mi coche, ¿eh, Tommy?\n\n[COK3_E:BARON3]\nSupongo que no.\n\n[COK3_F:BARON3]\nTienes toda la razón. Ahora escucha,\n\n[COK3_G:BARON3]\n¿sabes quién posee el barco más rápido de la costa este?\n\n[COK3_H:BARON3]\nNi idea.\n\n[COK3_I:BARON3]\nYo. Y quiero que siga siendo así.\n\n[COK3_J:BARON3]\nCada traficante de aquí a Caracas tiene un sueño, un barco más rápido.\n\n[COK3_K:BARON3]\nSe rumorea que el astillero acaba de terminar un barco así\n\n[COK3_L:BARON3]\npara algún mamón costarricense.\n\n[COK3_M:BARON3]\nY Tommy... ¡QUIERO ESE BARCO!\n\n[COK3_N:BARON3]\nCreo que han vuelto tus palomas.\n\n[COK3_O:BARON3]\n¡Ah! Pensé que te tenía. ¿De dónde has salido?\n\n[COK3_P:BARON3]\n¡Palomas! ¡Boom! ¡Aaaaah!\n\n[COK3_5:BARON3]\n~g~Localiza el interruptor para bajar el barco.\n\n[COK3_6:BARON3]\n~g~Lleva el barco a la mansión.\n\n[COK3_7:BARON3]\n~r~¡Destruiste el barco!\n\n[COK3_8:BARON3]\n~g~Ve al astillero, en los muelles y roba el barco más rápido.\n\n[COK3_9:BARON3]\n~g~Ahora sube al barco.\n\n{=================================== MISSION TABLE BARON4 ===================================}\n\n[COK4_A:BARON4]\n¡Expúlsala! ¡MIERDA DE PLÁSTICO!\n\n[COK4_B:BARON4]\n¿Por qué me haces esto?\n\n[COK4_C:BARON4]\n¿Quién te crees que eres, maldita mierda de plástico?\n\n[COK4_D:BARON4]\n¡QUE TE JODAN!\n\n[COK4_E:BARON4]\nSe traga mi película favorita de El burro, ¡se muere!\n\n[COK4_F:BARON4]\n¿Qué más podría haber hecho?\n\n[COK4_G:BARON4]\nProbablemente no estaba enchufado.\n\n[COK4_H:BARON4]\n¿Qué?\n\n[COK4_I:BARON4]\nMaldición... No importa, puedo comprar cien más.\n\n[COK4_J:BARON4]\nAhora, Tommy,\n\n[COK4_K:BARON4]\ncada mes un camello autónomo navega hasta Vice City y amarra su yate.\n\n[COK4_L:BARON4]\nVende su partida al primer barco.\n\n[COK4_M:BARON4]\nQuiero que cojas la lancha motora\n\n[COK4_N:BARON4]\ny que elimines a todos los otros cabrones,\n\n[COK4_O:BARON4]\nluego me traes aquí el alijo, ¿entendido?\n\n[COK4_P:BARON4]\nDéjame adivinar, pensaste que me podía venir bien un ángel guardián.\n\n[COK4_Q:BARON4]\nSolo digo que tienes que dejarme participar, tío.\n\n[COK4_R:BARON4]\nAhora ya puedes contarme toda esa basura del 'chico duro solitario',\n\n[COK4_S:BARON4]\npero sé que un día te voy a salvar el culo\n\n[COK4_T:BARON4]\n¡y probablemente querrás darme un beso!\n\n[COK4_U:BARON4]\nColgado.\n\n[COK4_V:BARON4]\n~n~\n\n[COK4_1:BARON4]\nAsí que Tommy, sabemos que fue Díaz quien jodió nuestro trato...\n\n[COK4_3:BARON4]\nAsí que, ¿por qué coño vamos por ahí haciéndole recados?\n\n[COK4_4:BARON4]\nCuanto más aprendamos ahora, ¡menos tendremos que aprender cuando tomemos el control de esta ciudad!\n\n[COK4_5:BARON4]\nMe encanta tu estilo, tío. Muy fresco.\n\n[COK4_12:BARON4]\n¡Cuidado, vienen de todas partes!\n\n[COK4_13:BARON4]\nYa está. ¡Dirígete hacia Díaz tan rápido como puedas!\n\n[COK4_14:BARON4]\n¿Queréis un poco de esto?\n\n[COK4_15:BARON4]\n¡A dormir con los peces!\n\n[COK4_16:BARON4]\n¡Comed! ¡COMED!\n\n[COK4_19:BARON4]\n¡Más problemas ahí adelante!\n\n[COK4_20:BARON4]\n¡Hay más pistoleros en el malecón!\n\n[COK4_24:BARON4]\nBuen disparo, amigo mío. Eres un verdadero y auténtico lunático de categoría A.\n\n[COK4_25:BARON4]\nBueno, gracias.\n\n[COK4_26:BARON4]\nNos vemos, Tommy.\n\n[COK4_27:BARON4]\nVale, Sr. Lance Vance.\n\n[COK4_28:BARON4]\n~g~¡Ve hasta el yate antes de que lleguen los otros barcos!\n\n[COK4_31:BARON4]\n~g~¡Ve al barco más rápido del embarcadero!\n\n[COK4_32:BARON4]\n~r~¡Demasiado lento!\n\n[COK4_33:BARON4]\n~r~¡Has destruido el barco!\n\n[COK4_34:BARON4]\n~g~¡Hunde esos barcos!\n\n[COK4_35:BARON4]\nEstado del barco:\n\n{=================================== MISSION TABLE BARON5 ===================================}\n\n[PROP_A:BARON5]\n¡PROPIEDAD ADQUIRIDA!\n\n[COK4_30:BARON5]\n~r~¡Lance está muerto!\n\n[ASS1_A:BARON5]\nHe conseguido unos juguetes nuevos. Están en el maletero.\n\n[ASS1_B:BARON5]\n¡Mierda! ¿Dónde conseguiste todo este material?\n\n[ASS1_C:BARON5]\nLo he estado guardando para un momento como éste.\n\n[ASS1_D:BARON5]\n¿Te gusta?\n\n[ASS1_E:BARON5]\nSí, me gusta.\n\n[ASS1_F:BARON5]\nEstúpidos mamones...\n\n[ASS1_G:BARON5]\nMi hermosa casa.\n\n[ASS1_H:BARON5]\n¡Mirad lo que le habéis hecho!\n\n[ASS1_I:BARON5]\n¡Esto es por mi hermano!\n\n[ASS1_J:BARON5]\nConfiaba en ti, Tommy.\n\n[ASS1_K:BARON5]\nTe hubiese convertido en...\n\n[ASS1_L:BARON5]\nDiga buenas noches, Sr. Díaz.\n\n[ASS1_1:BARON5]\nEste lugar va a estar hasta arriba de capullos... ten cuidado...\n\n[ASS1_2:BARON5]\nNo te preocupes Tommy, te cubro.\n\n[ASS1_13:BARON5]\n¡DÍAZ! ¡He venido a encargarme de tu negocio!\n\n[ASS1_14:BARON5]\n¡TOMMY! Me has traicionado... ¡Imbécil! Voy a acabar contigo muy pronto...\n\n[ASS1_15:BARON5]\n~g~¡Arrasa esa mansión y mata a Diaz!\n\n[ASS1_16:BARON5]\n~g~¡Mata a Diaz!\n\n[ASS1_17:BARON5]\n~g~Hay múltiples caminos para entrar en la mansión.\n\n[BUD1:BARON5]\nLance\n\n[ASS1_18:BARON5]\n~g~La puerta está cerrada con llave, intenta otra ruta.\n\n[ASS1_19:BARON5]\n¡Por aquí!\n\n[ASS1_20:BARON5]\n¡Tommy, mi problema es con Quentin, no contigo, tío!\n\n{=================================== MISSION TABLE BIKE1 ===================================}\n\n[BM1_A:BIKE1]\n¿Dónde está Baker?\n\n[BM1_B:BIKE1]\nEstoy buscando al gran Mitch Baker...\n\n[BM1_C:BIKE1]\n¿Quién le busca?\n\n[BM1_D:BIKE1]\nTommy Vercetti.\n\n[BM1_E:BIKE1]\nVercetti.\n\n[BM1_F:BIKE1]\nNo pareces policía, así que eso te concede un minuto.\n\n[BM1_G:BIKE1]\nHabla rápido.\n\n[BM1_H:BIKE1]\nKent Paul dijo que podrías estar interesado en llevar la seguridad de una gira que él ha organizado.\n\n[BM1_I:BIKE1]\n¿Kent Paul? No me extraña que te enviase en su lugar.\n\n[BM1_J:BIKE1]\nLa última vez que estuvo aquí, se marchó por la ventana sin nada, tal cual le trajo su madre al mundo.\n\n[BM1_K:BIKE1]\n¿Estás interesado o no?\n\n[BM1_L:BIKE1]\nSólo hacemos favores a los nuestros.\n\n[BM1_M:BIKE1]\n¿Cómo puedo unirme a vosotros?\n\n[BM1_N:BIKE1]\nEste no es un club de campo, chico. ¿Sabes montar en moto?\n\n[BM1_O:BIKE1]\n¿Sabes sentarte en un taburete y beber?\n\n[BM1_P:BIKE1]\nCougar, Zeppelin, id a ver cómo se le da la moto a esta nenaza...\n\n[BM1_2:BIKE1]\n~g~¡Necesitas una Freeway o una Ángel para competir!\n\n[BM1_3:BIKE1]\n~r~¡Los corredores han sido atacados!\n\n[BIKE1_1:BIKE1]\nBien, modelitos caros. Veamos qué puedes hacer.\n\n[BM1_1:BIKE1]\n~g~Consigue una Freeway o una Ángel y ve a la parrilla de salida.\n\n{=================================== MISSION TABLE BIKE2 ===================================}\n\n[BM2_1:BIKE2]\nCAOSMETRO:\n\n[BM2_A:BIKE2]\nTe he vuelto a ganar.\n\n[BM2_B:BIKE2]\nEh, Vercetti.\n\n[BM2_C:BIKE2]\nCougar dice que sabes manejar muy bien una moto.\n\n[BM2_D:BIKE2]\nSí, ¿cuántos recados más voy a tener que hacer?\n\n[BM2_E:BIKE2]\nSoy un hombre muy ocupado.\n\n[BM2_F:BIKE2]\nSi es un combate lo que va arreglarlo todo, entonces adelante.\n\n[BM2_G:BIKE2]\nSer uno de nosotros no va solo de fanfarronear. Va de ser parte de una familia.\n\n[BM2_H:BIKE2]\nSí, he sido parte de una familia antes. No funcionó.\n\n[BM2_I:BIKE2]\nSí, seguro, pero esta familia cuida de los suyos.\n\n[BM2_J:BIKE2]\nNo le pedimos a un hombre que haga el trabajo sucio y luego le dejamos pasar quince años de sequía.\n\n[BM2_K:BIKE2]\nSí, es verdad. He hecho mis deberes.\n\n[BM2_L:BIKE2]\nÉsta de aquí es la familia más grande de inadaptados, rebeldes y tipos duros.\n\n[BM2_M:BIKE2]\nDiablos, algunos de nosotros incluso hemos sido traicionados por nuestro propio país.\n\n[BM2_N:BIKE2]\nEstuve preso durante Vietnam. Un tema desagradable.\n\n[BM2_O:BIKE2]\nPor eso es por lo que voy a pedirte que vayas a armar jaleo.\n\n[BM2_P:BIKE2]\nEste maldito país necesita una patada en el culo, y nosotros se la vamos a dar.\n\n[BM2_Q:BIKE2]\n¡Así que sal de ahí, pilla una moto, demuestra a esta ciudad lo cabreado que estás!\n\n[BM2_R:BIKE2]\nDe acuerdo.\n\n[BM2_2:BIKE2]\n~g~¡Debes llenar el Caosmetro en el tiempo determinado para demostrarnos lo duro que eres!\n\n[BM2_3:BIKE2]\n~g~Este sonido indica que has llenado una parte del contador, continúa así.\n\n[BM2_4:BIKE2]\n~r~¡Has fracasado en llenar el Caosmetro a tiempo!\n\n{=================================== MISSION TABLE BIKE3 ===================================}\n\n[BM3_A:BIKE3]\nHola, Mitch.\n\n[BM3_B:BIKE3]\nBueno, si es el ''tipo duro'' Vercetti.\n\n[BM3_C:BIKE3]\nAhora quiero ver lo bien que sabes luchar por tu territorio.\n\n[BM3_D:BIKE3]\nUna banda callejera local cometió el error de robar mi moto,\n\n[BM3_E:BIKE3]\nprobablemente para hacerse los machos o algo así.\n\n[BM3_F:BIKE3]\nLos chicos y yo iríamos a darles una lección sobre el respeto a las propiedades ajenas y todo eso.\n\n[BM3_G:BIKE3]\nEn fin...\n\n[BM3_H:BIKE3]\nEntonces empecé a pensar que esto sería una buena iniciación para ti.\n\n[BM3_I:BIKE3]\nDevuélveme mi moto y puedes decirle a Paul que tiene su seguridad.\n\n[BM3_2:BIKE3]\n~r~¡Se suponía que debías traer de vuelta la moto, no destruirla!\n\n[BM3_3:BIKE3]\n~g~¡Lleva la moto de vuelta al bar!\n\n[BM3_4:BIKE3]\n~g~¡Sube a la moto!\n\n[INTRUDE:BIKE3]\n~g~¡Te han visto!\n\n[BM3_6:BIKE3]\n~g~Están refugiados detrás de Ammu-Nation en la zona del centro.\n\n[BM3_7:BIKE3]\n~g~Necesitarás una moto rápida para conseguir acceder al tejado.\n\n[BM3_8:BIKE3]\n~g~Utiliza la moto para saltar desde esas escaleras hasta el tejado que hay en el extremo opuesto de la carretera.\n\n[BM3_1:BIKE3]\n~g~Una banda local ha robado la Ángel de Mitch Baker. ¡Recupérala!\n\n[BM3_9:BIKE3]\n~g~¡Recupera la Ángel de Mitch y sal de ahí!\n\n{=================================== MISSION TABLE BMX_1 ===================================}\n\n[GETBIK2:BMX_1]\n¡Tienes ~1~ segundos para subirte a una moto de motocross!\n\n{=================================== MISSION TABLE BOATBUY ===================================}\n\n[DRUG_1:BOATBUY]\n¿Hola?\n\n[DRUG_2:BOATBUY]\nApágalo. Hay un tipo ahí afuera.\n\n[DRUG_3:BOATBUY]\n¡Eh, el tipo del traje! Supongo que eres el nuevo propietario.\n\n[DRUG_4:BOATBUY]\nSí. ¿Cuál de los barcos es el más rápido?\n\n[DRUG_5:BOATBUY]\nYa está en el agua, tío,\n\n[DRUG_6:BOATBUY]\nPensé que querrías probarlo.\n\n[DRUG_7:BOATBUY]\nTío, funciona con un motor de 300 caballos...\n\n[DRUG_8:BOATBUY]\ny el casco es de fibra de vidrio, ¡sale disparado por las olas!\n\n[DRUG_9:BOATBUY]\nPuede ponerse de cero a noventa tan sólo en cuatro segundos, tío...\n\n[DRUG_10:BOATBUY]\n¡y puede llevar como veinte contenedores de la mejor hierba jamaicana justo en el casco!\n\n[DRUG_11:BOATBUY]\nAsí que adelante, tío, ¡está preparada para volar!\n\n[DRUG_12:BOATBUY]\nTipo trajeado, ¿tienes fuego?\n\n[DRUG_13:BOATBUY]\n¿Colega?\n\n{=================================== MISSION TABLE CAP_1 ===================================}\n\n[CAP1_B1:CAP_1]\n~g~La mafia está imponiendo impuestos a tus negocios. Encuéntrales y mátales.\n\n[CAP1_B2:CAP_1]\n~g~¡La mafia ha saqueado el astillero!\n\n[CAP1_B3:CAP_1]\n~g~¡La mafia ha saqueado la fábrica de helados!\n\n[CAP1_B4:CAP_1]\n~g~¡La mafia ha saqueado el salón de autos!\n\n[CAP1_B5:CAP_1]\n~g~¡La mafia ha saqueado la compañía de taxis!\n\n[CAP_01:CAP_1]\n¿Cuál es la emergencia?\n\n[CAP_02:CAP_1]\n¿QUIÉN?\n\n[CAP_03:CAP_1]\nTommy... unos matones mafiosos... dijeron que vendrían a recoger su parte...\n\n[CAP_04:CAP_1]\nDijeron que era dinero del Sr. Forello... me siento una basura.\n\n[CAP_05:CAP_1]\n¿Forelli? ¿SONNY Forelli?\n\n[CAP_06:CAP_1]\nSí, ése es el tipo... creo... insistieron mucho...\n\n[CAP_07:CAP_1]\nNo te preocupes, abuelo, no estoy enfadado contigo.\n\n[CAP_08:CAP_1]\nLlevadle al hospital.\n\n[CAP_09:CAP_1]\nTommy... rájale un nuevo culo a ese tipo por mí...\n\n[CAP_10:CAP_1]\nVoy a rajarle en dos.\n\n[CAP1_2:CAP_1]\n¡Conoces las reglas, Vercetti!\n\n[CAP1_3:CAP_1]\n¡El Sr. Forelli envía sus saludos!\n\n[CAP1_4:CAP_1]\n¡Es el carnicero de Harwood!\n\n[CAP1_5:CAP_1]\nDecidle a Sonny... ¡Que permanezca alejado!\n\n[CAP1_6:CAP_1]\nVice City ahora es MÍA, NO suya.\n\n[CAP1_7:CAP_1]\n¿Crees que puedes eliminarme, Vercetti?\n\n[CAP1_8:CAP_1]\nSeguiremos yendo tras de ti hasta que mueras, Vercetti.\n\n[CAP1_9:CAP_1]\nNo tienes ni una oportunidad, mamón psicótico.\n\n[CAP1_10:CAP_1]\nTe mataré, Vercetti.\n\n[CAP1_11:CAP_1]\nSiempre fuiste un gilipollas.\n\n[CAP1_12:CAP_1]\nVas a morir, Vercetti.\n\n[CAP1_B6:CAP_1]\n~g~Has encontrado al cobrador, remátale.\n\n[CAP1_B7:CAP_1]\n~g~Has perdido al cobrador.\n\n[CAP1_B8:CAP_1]\n~r~El cobrador ha saqueado todos tus negocios.\n\n[CAP1_B9:CAP_1]\n~g~¡La mafia ha saqueado a El Malibu!\n\n[CAP1_B0:CAP_1]\n~g~¡La mafia ha saqueado al estudio cinematográfico!\n\n[CAP1_C2:CAP_1]\n~g~¡La mafia ha llegado al astillero!\n\n[CAP1_C3:CAP_1]\n~g~¡La mafia ha llegado a la fábrica de helados!\n\n[CAP1_C4:CAP_1]\n~g~¡La mafia ha llegado al concesionario de coches!\n\n[CAP1_C5:CAP_1]\n~g~¡La mafia ha llegado a la compañía de taxis!\n\n[CAP1_C9:CAP_1]\n~g~¡La mafia ha llegado al Malibú!\n\n[CAP1_C0:CAP_1]\n~g~¡La mafia ha llegado al estudio cinematográfico!\n\n[CAP1_D2:CAP_1]\n~g~¡La mafia abandona el astillero!\n\n[CAP1_D3:CAP_1]\n~g~La mafia abandona la fábrica de helados!\n\n[CAP1_D4:CAP_1]\n~g~¡La mafia abandona el concesionario de coches!\n\n[CAP1_D5:CAP_1]\n~g~¡La mafia abandona la compañía de taxis!\n\n[CAP1_D9:CAP_1]\n~g~¡La mafia abandona el Malibú!\n\n[CAP1_D0:CAP_1]\n~g~¡La mafia abandona el estudio cinematográfico!\n\n[CAP1B10:CAP_1]\nHas puesto límite a los recaudadores. Vienen más de camino.\n\n{=================================== MISSION TABLE CARBUY ===================================}\n\n[CAR1_1:CARBUY]\nB.J. Smith. Y usted debe ser el Sr. Vercetti.\n\n[CAR1_2:CARBUY]\n¿Le gustaría dar una vuelta?\n\n[CAR1_3:CARBUY]\nPodría ser.\n\n[CAR1_4:CARBUY]\nEstoy muy triste por vender el negocio.\n\n[CAR1_5:CARBUY]\nEsta fue mi primera inversión después de convertirme en profesional.\n\n[CAR1_6:CARBUY]\nPero es hora de que me mude.\n\n[CAR1_7:CARBUY]\n¿Deja la ciudad?\n\n[CAR1_8:CARBUY]\nNo demasiado deprisa, espero.\n\n[CAR1_9:CARBUY]\nNo. Me estoy retirando pero simplemente para preparar mi regreso.\n\n[CAR1_10:CARBUY]\nEl negocio no era demasiado fuerte,\n\n[CAR1_11:CARBUY]\ny mi equipo quizás se puso demasiado\n\n[CAR1_12:CARBUY]\ncreativo con la generación de la riqueza.\n\n[CAR1_13:CARBUY]\nObviamente, habría podido desmantelar el negocio antes de cederlo.\n\n[CAR1_14:CARBUY]\nDiablos, podría haber quemado el sitio si hubiese querido.\n\n[CAR1_15:CARBUY]\nEsta es tierra para una urbanización de primera.\n\n[CAR1_16:CARBUY]\nOh, yo no me preocuparía por nada de eso.\n\n[CAR1_17:CARBUY]\nEste lugar parece perfecto.\n\n[CAR1_18:CARBUY]\nSí, así es, ¿así que entiendo que tenemos un trato?\n\n{=================================== MISSION TABLE CARPAR1 ===================================}\n\n[MM_1_A:CARPAR1]\n~g~Atraviesa ~y~5 puntos de control ~r~¡SIN ~g~aplastar ningún ~r~CONO! ~g~Puedes atravesarlos en ~y~CUALQUIER ORDEN.\n\n[CONE_1:CARPAR1]\n~r~¡Aplastaste un cono!\n\n[MM_1_C:CARPAR1]\n~y~PASA POR~g~ un punto de control para activar el temporizador. ~g~Cada punto de control te dará ~y~~1~ SEGUNDOS~g~.\n\n{=================================== MISSION TABLE COPCAR ===================================}\n\n[KILLS:COPCAR]\nMUERTES:\n\n[C_BREIF:COPCAR]\n~g~Sospechoso visto por última vez en la zona de ~a~.\n\n[C_PASS:COPCAR]\nAMENAZA ELIMINADA: ~1~ $\n\n[COPCART:COPCAR]\n~g~Tienes ~1~ segundos para volver al vehículo de policía antes de que termine la misión.\n\n[C_CANC:COPCAR]\n~r~¡Misión de justiciero cancelada!\n\n[C_TIME:COPCAR]\n~r~¡Tu tiempo como representante de la ley se ha terminado!\n\n[C_COMP1:COPCAR]\nHas completado el nivel 12 de la misión de justiciero: tu armadura personal máxima ha aumentado a 150.\n\n[CLEVEL:COPCAR]\nMisión de justiciero nivel ~1~\n\n{=================================== MISSION TABLE COUNT1 ===================================}\n\n[CM1_A:COUNT1]\n¿Sr. Vercetti? ¿Comprando la vieja imprenta?\n\n[CM1_B:COUNT1]\nSí, mi viejo solía trabajar con ellas.\n\n[CM1_C:COUNT1]\nIba a seguirle en el negocio, pero... viví una vida diferente.\n\n[CM1_D:COUNT1]\n¿Planea vender la vieja maquinaria o destruirla?\n\n[CM1_E:COUNT1]\nEstoy pensando que podíamos imprimir algo, un periódico, una revista...\n\n[CM1_F:COUNT1]\nOh, mierda, hijo, todo eso es mierda de baja calidad. Siempre me ha apetecido imprimir dinero. No es tan difícil.\n\n[CM1_G:COUNT1]\nYa sabes, llevo haciéndolo a pequeña escala durante años.\n\n[CM1_H:COUNT1]\n¿De verdad?\n\n[CM1_I:COUNT1]\nClaro. Pero necesitamos unas planchas de buena calidad.\n\n[CM1_J:COUNT1]\n¡Por supuesto! Hay un sindicato de la falsificación que opera ya en Florida.\n\n[CM1_K:COUNT1]\n¿Un sindicato?\n\n[CM1_L:COUNT1]\nSí. He escuchado algunos rumores.\n\n[CM1_M:COUNT1]\nConozco a un tipo que es bueno con los rumores...\n\n[CM1_N:COUNT1]\nSolía pasar las tardes con él, limpiando los rodillos...\n\n[CM1_2A:COUNT1]\n¡Menudo trasero!\n\n[CM1_2B:COUNT1]\n¡Vale chica, tú te lo pierdes!\n\n[CM1_2C:COUNT1]\nBuenas, figura, ¿cómo va todo?\n\n[CM1_2D:COUNT1]\n¿Qué sabes sobre falsificación?\n\n[CM1_2E:COUNT1]\nEstoy bien, Paul, ¿qué tal tú?\n\n[CM1_2F:COUNT1]\n¡Ven aquí!\n\n[CM1_2G:COUNT1]\n¡Vale! ¡Vale! Obviamente eres un hombre ocupado.\n\n[CM1_2H:COUNT1]\nTodo lo que sé sobre los asuntos turbios es que las tríadas suministran las planchas.\n\n[CM1_2I:COUNT1]\nTienen una compañía de envíos en los muelles,\n\n[CM1_2J:COUNT1]\n¡el jefe sabrá cuándo vienen las próximas planchas!\n\n[CM1_2K:COUNT1]\nGracias, Paul.\n\n[CM1_2L:COUNT1]\n¡Cuál es tu problema, lunático!\n\n[CM1_2M:COUNT1]\n¡Ponme otra copa, pronto!\n\n[CM1_3:COUNT1]\n~g~¡Te han visto!\n\n[CM1_5:COUNT1]\n~g~¡Ve a encontrarte con Kent Paul en el Club Malibú!\n\n[CNT1_1:COUNT1]\n¿Quién eres tú? ¡En la cara no! ¡En la cara no!\n\n[CM1_1:COUNT1]\n~g~Ve al barco de la línea charter Libertine en el muelle.\n\n[CM1_2:COUNT1]\n~g~El encargado de los envíos tendrá toda la información necesaria.\n\n[CNT1_2:COUNT1]\nVale, ¡hablaré! ¡hablaré!\n\n[CM1_6:COUNT1]\n~g~¡Lleva toda la información de vuelta a la imprenta!\n\n{=================================== MISSION TABLE COUNT2 ===================================}\n\n[CNT2_B1:COUNT2]\nDe acuerdo, hoy el mensajero moverá las planchas de los muelles.\n\n[CNT2_B2:COUNT2]\nVoy a interceptarles, coger las planchas, deshacerme de las pruebas, y volver aquí.\n\n[CNT2_B3:COUNT2]\nDependiendo de lo bien que vaya esto,\n\n[CNT2_B4:COUNT2]\npodemos tener cinco minutos para imprimir el dinero antes de que el sindicato de falsificación nos encuentre, o puede que tengamos todo el año.\n\n[CNT2_B5:COUNT2]\nDe cualquier modo, quiero que los verdes salgan de las prensas cinco minutos después de que vuelva. ¿Entendido?\n\n[CNT2_B6:COUNT2]\nNo te preocupes, Tommy. Estaremos preparados.\n\n[CNT2_B7:COUNT2]\nLos otros chicos y yo estaremos por aquí en el vecindario, en caso de que necesites que nos ocupemos de cualquier problema.\n\n[CNT2_B8:COUNT2]\nDe acuerdo, ¿todo el mundo está tranquilo? De acuerdo. Os veré luego...\n\n[CNT2_01:COUNT2]\n~g~El ~r~mensajero~g~ con las planchas de falsificación llegará en cualquier momento a los ~y~muelles~g~ en un helicóptero.\n\n[CNT2_02:COUNT2]\n~r~El mensajero de las planchas ha huido en el helicóptero.\n\n[CNT2_03:COUNT2]\n~r~¡El mensajero ha llegado a su destino sano y salvo, llegas demasiado tarde!\n\n[CNT2_04:COUNT2]\n~r~¡Has destruido las planchas en la explosión!\n\n[CNT2_05:COUNT2]\n~g~Tienes las planchas de falsificación. Llévalas a la imprenta.\n\n[CNT2_06:COUNT2]\n~g~El mensajero ha muerto y ha dejado caer las planchas, recógelas antes de que lo haga otro.\n\n[CNT2_07:COUNT2]\n~g~Una de las guardias ha recogido las planchas, no la dejes escapar.\n\n[CNT2_08:COUNT2]\n~g~El ~r~mensajero~g~ ha llegado a los muelles con las planchas.\n\n[CNT2_4:COUNT2]\nNegocio privado. ¡No eres bienvenido!\n\n[CNT2_09:COUNT2]\nIMPRENTA CONSOLIDADA\n\n[CNT2_10:COUNT2]\n~g~La imprenta generará ahora unos ingresos hasta un máximo de ~1~ $. Asegúrate que lo recaudas de manera regular.\n\n[CNT2_11:COUNT2]\n~r~¡Las planchas están en el fondo del mar!\n\n{=================================== MISSION TABLE CUBAN1 ===================================}\n\n[CUB1_A:CUBAN1]\n¿Sí, tío?\n\n[CUB1_B:CUBAN1]\nEh, tranquilo papito, este hombre es para mí. Tú, ¿tú eres el chico?\n\n[CUB1_C:CUBAN1]\nOh, sí. Tú eres el chico. Eso creo, ¿sabes?\n\n[CUB1_D:CUBAN1]\nNo. No creo que lo sepa.\n\n[CUB1_E:CUBAN1]\n¿Oh, sí? Ven aquí, tipo duro.\n\n[CUB1_F:CUBAN1]\n¿Crees que puedes desafiarme?\n\n[CUB1_G:CUBAN1]\n¿Crees que puedes jugar a ese estúpido juego conmigo?\n\n[CUB1_H:CUBAN1]\nNo, creo que ya lo estás haciendo tú lo suficientemente estúpido por los dos.\n\n[CUB1_I:CUBAN1]\nEh, te llamó tonto, hijo.\n\n[CUB1_J:CUBAN1]\nY yo le llamé niñita, papá.\n\n[CUB1_K:CUBAN1]\nMírale, vestido así.\n\n[CUB1_L:CUBAN1]\n¿Qué es esto, un traje de noche?\n\n[CUB1_M:CUBAN1]\n¿Eres alguna clase de tipo duro y vistes como una mujer?\n\n[CUB1_N:CUBAN1]\nTambién llevas pantis como una mujer, ¿eh?\n\n[CUB1_O:CUBAN1]\n¿Qué tienes contra las mujeres? ¿Prefieres a los hombres, grandullón?\n\n[CUB1_P:CUBAN1]\n¡Me gustan las mujeres! ¡Me gustan las mujeres! ¡Amo a mi madre, chico!\n\n[CUB1_Q:CUBAN1]\nDe acuerdo, de acuerdo. Aceptaré tu palabra.\n\n[CUB1_R:CUBAN1]\n¿Sabes conducir, amigo?\n\n[CUB1_S:CUBAN1]\nSí... como una mujer.\n\n[CUB1_T:CUBAN1]\nMuy gracioso. Me gustas, grandullón. Quizás puedas ayudarme.\n\n[CUB1_U:CUBAN1]\nQuizás puedas demostrar que eres un hombre. ¿Eh?\n\n[CUB1_V:CUBAN1]\nSaca el barco.\n\n[CUB1_W:CUBAN1]\nDemuéstrame que tienes un par de cojones,\n\n[CUB1_X:CUBAN1]\ny no unos chiquitos de ratón.\n\n[CUB1_02:CUBAN1]\nDe acuerdo, tío, trátalo como a una mujer.\n\n[CUB1_03:CUBAN1]\nNo está mal, un hombre de verdad.\n\n[CUB1_04:CUBAN1]\nTío, tienes unas pelotas bien grandes, amigo.\n\n[CUB1_05:CUBAN1]\nAmigo, eres un tío.\n\n[CUB1_06:CUBAN1]\n¿Puedes decir que eres un machote, tío?\n\n[CUB1_07:CUBAN1]\nEres un ratón asustado, niñito, vete a llorar con tu mamá.\n\n[CUB1_08:CUBAN1]\nEres una bazofia. Andas como un tío, hablas con un tío, pero conduces como un idiota.\n\n[CUB1_09:CUBAN1]\nBrother, eres un macho. Me gustas, tío. Me gustas un montón.\n\n[CUB1_10:CUBAN1]\nEn cualquier momento, tío. Porque tienes un par. Y todos mis amigos tienen un buen par de cojones.\n\n[CUB1_11:CUBAN1]\n~r~¡Mataste a Rico!\n\n[CUB1_12:CUBAN1]\nAtraviesa el primer punto de control para comenzar la prueba.\n\n[CUB1_14:CUBAN1]\n¡Vuelve al bote!\n\n[CUB1_15:CUBAN1]\n~r~Brother, eres demasiado lento.\n\n[CUB1_01:CUBAN1]\nEh, soy Rico. ¿Eres tú el tío de las pelotas grandes?\n\n[CUB1_13:CUBAN1]\n~g~Tienes tres minutos para recorrer el circuito.\n\n{=================================== MISSION TABLE CUBAN2 ===================================}\n\n[CUB2_A:CUBAN2]\nUn cafetito, por favor, Alberto...\n\n[CUB2_N:CUBAN2]\nSin problema, Tommy.\n\n[CUB2_B:CUBAN2]\n¡Papá! ¡Un gran problema!\n\n[CUB2_O:CUBAN2]\nUmberto, mi hijo, ¿qué ocurre?\n\n[CUB2_C:CUBAN2]\n¡Los haitianos! ¡Odio a estos haitianos!\n\n[CUB2_D:CUBAN2]\n¡Me han molestado por última vez!\n\n[CUB2_E:CUBAN2]\n¡Nos desharemos de ellos!\n\n[CUB2_F:CUBAN2]\nSólo necesitamos un poco de apoyo.\n\n[CUB2_G:CUBAN2]\nYa he perdido algunos hermanos ahí fuera.\n\n[CUB2_H:CUBAN2]\n¡Amigo, tú conduces bien!\n\n[CUB2_I:CUBAN2]\nPara ser una mujer. ¿No?\n\n[CUB2_J:CUBAN2]\n¡Éste no es momento de bromear!\n\n[CUB2_K:CUBAN2]\n¡Vamos, maneja de nuevo para mí!\n\n[CUB2_L:CUBAN2]\n¡Lleva a mis chicos allí y eliminaremos a esos haitianos!\n\n[CUB2_M:CUBAN2]\n¡Se meten conmigo y se meten con el chico grande de la ciudad!\n\n[CUB2_01:CUBAN2]\nNo hay suficiente espacio, brother, necesitas un coche más grande.\n\n[CUB2_02:CUBAN2]\n¡Necesitamos refuerzos del café!\n\n[CUB2_03:CUBAN2]\n~g~Consigue un coche y recoge a los cubanos frente al Café Robina.\n\n[CUB2_04:CUBAN2]\n~g~Ve y deja a los cubanos en la zona de combate.\n\n[CUB2_05:CUBAN2]\n¡Elimina a ese francotirador cobarde!\n\n[CUB2_07:CUBAN2]\n¡Luchan como nenas! ¡Ponte a cubierto!\n\n[CUB2_09:CUBAN2]\n¡Francotirador en el tejado!\n\n[CUB2_11:CUBAN2]\n~r~Estúpido, necesitábamos ese coche.\n\n[CUB2_12:CUBAN2]\n¡Eh, amigo! ¡Me alegro de que hayas podido venir!\n\n[CUB2_13:CUBAN2]\n¡Apestoso nido de haitianos, vamos a matarlos a todos!\n\n[CUB2_14:CUBAN2]\n¡A LA CARGA!\n\n[CUB2_15:CUBAN2]\n¡Ahora, hermanos, A LA CAAARGA!\n\n[CUB2_16:CUBAN2]\n¡Tommy, hemos demostrado nuestro valor y nuestra hombría!\n\n[CUB2_17:CUBAN2]\n¡Vamos a robar esa furgoneta llena de farlopa y pegarnos el piro!\n\n[CUB2_18:CUBAN2]\n~g~Consigue un coche y recoge a los cubanos.\n\n[CUB2_19:CUBAN2]\n¡Vamos a combatir como machos!\n\n[CUB2_21:CUBAN2]\n¡Luchad como machos con un par de cojones!\n\n[CUB2_22:CUBAN2]\n~g~Termina con el resto de los haitianos para que los cubanos puedan avanzar.\n\n[CUB2_23:CUBAN2]\n~g~Little Haiti estará atestado de haitianos intentando desquitarse con los cubanos. ¡Ten cuidado!\n\n[CUB2_24:CUBAN2]\n~g~Vuelve al Café Robina en la furgoneta y aparca en la parte trasera.\n\n[CUB2_25:CUBAN2]\n¡MATA A TODOS LOS HAITIANOS!\n\n{=================================== MISSION TABLE CUBAN3 ===================================}\n\n[CUB3_A:CUBAN3]\nAlberto. Un cafetito, señor.\n\n[CUB3_B:CUBAN3]\nPapaíto, no sirvas a esta sabandija.\n\n[CUB3_C:CUBAN3]\n¡Tienes dos caras, Tommy!\n\n[CUB3_D:CUBAN3]\n¡Tú, guapito de cara, o eres un falso o eres un calzonazos!\n\n[CUB3_E:CUBAN3]\n¡Los haitianos! Tío, se están riendo de mí.\n\n[CUB3_F:CUBAN3]\nVale, vale. ¿Qué problema tienes?\n\n[CUB3_G:CUBAN3]\nSe están riendo de mí, Tommy. ¡De mí!\n\n[CUB3_H:CUBAN3]\n¡Umberto Robina! ¡Están haciendo lo que quieren!\n\n[CUB3_I:CUBAN3]\nNadie hace lo que quiere, Umberto, hacen lo que les dejes hacer.\n\n[CUB3_J:CUBAN3]\n¿Qué?\n\n[CUB3_K:CUBAN3]\n¿Quieres que alguien se ocupe del asunto?\n\n[CUB3_L:CUBAN3]\nPuedo manejarlo, pero va a costarte.\n\n[CUB3_M:CUBAN3]\nSé que somos hermanos y todo eso, pero esto es un negocio.\n\n[CUB3_N:CUBAN3]\nTommy. Eres un verdadero macho. Un tío de negocios, un caballero.\n\n[CUB3_O:CUBAN3]\nEstos haitianos. Tienen un alijo de producto que va a venir desde alta mar, un material de primera.\n\n[CUB3_P:CUBAN3]\nLo agarraremos y acabaremos con ellos.\n\n[CUB3_Q:CUBAN3]\nTú lo agarrarás y yo cuidaré de ti. Como a un hermano. Como a un hijo.\n\n[CUB3_R:CUBAN3]\nCreo que prefiero el dinero a que me mezas en tus rodillas, amigo.\n\n[CUB3_01:CUBAN3]\nEh, Rico. Bonito barco, ¿estás preparado?\n\n[CUB3_03:CUBAN3]\n~g~Recoge todos los maletines llenos de nieve y dinero.\n\n[CUB3_04:CUBAN3]\n~g~Lleva la nieve y la pasta de vuelta a Umberto.\n\n[CUB3_05:CUBAN3]\nSí, Tommy. Tienes que apuntar bien.\n\n[CUB3_06:CUBAN3]\nMi barco, no me sirve lleno de agujeros, ¿eh?\n\n[CUB3_07:CUBAN3]\n~g~Ve y reúnete con Rico. Te llevará al punto de encuentro.\n\n\n[CUB3_02:CUBAN3]\n~g~¡MATA A TODOS LOS HAITIANOS DEL BARCO!\n[CUB3_08:CUBAN3]\nOh, oh... Una banda de cubanos. ¡Nos atacan!\n\n{=================================== MISSION TABLE CUBAN4 ===================================}\n\n[CUB4_A:CUBAN4]\nEy, señoritas. ¿Sabéis qué voy a hacer?\n\n[CUB4_B:CUBAN4]\nPrimero voy a matar un haitiano. ¿Y después?\n\n[CUB4_C:CUBAN4]\nVoy a hacer el amor como un hombre.\n\n[CUB4_D:CUBAN4]\n¿Sabes chica? Algo así.\n\n[CUB4_E:CUBAN4]\n¡Perdedor!\n\n[CUB4_F:CUBAN4]\nMamón.\n\n[CUB4_G:CUBAN4]\n¡Ey, nena, no te tocaría ni con una pértiga de tres metros!\n\n[CUB4_H:CUBAN4]\n¡A Umberto Robina le gustan las damas! ¡No una cabra con faldas!\n\n[CUB4_I:CUBAN4]\n¡Tommy! ¡Tommy, te quiero, te quiero! ¡Vámonos!\n\n[CUB4_J:CUBAN4]\n¿Irnos a donde? ¿No me puedo tomar primero una taza de café?\n\n[CUB4_K:CUBAN4]\n¡No hay tiempo para café! Además, acabo de tomarme uno.\n\n[CUB4_L:CUBAN4]\nVamos a eliminar a los haitianos.\n\n[CUB4_M:CUBAN4]\nTommy, ¿qué tiene un elefante dentro de la trompa?\n\n[CUB4_N:CUBAN4]\n¡Dos metros de mocos! ¡Ja, ja, ja!\n\n[CUB4_O:CUBAN4]\nLo que tú digas, Umberto.\n\n[CUB4_P:CUBAN4]\nTommy, ve y consíguenos un cochecito haitiano.\n\n[CUB4_Q:CUBAN4]\nCuando lo tengas, regresa y recoge a mi chico\n\n[CUB4_R:CUBAN4]\nPepe, y llévale a donde los haitianos.\n\n[CUB4_S:CUBAN4]\nLuego te vas hasta la planta de procesamiento de los haitianos y utilizas su disolvente como explosivo.\n\n[CUB4_T:CUBAN4]\n¡Boom! Y ¡Bye bye!\n\n[CUB4_U:CUBAN4]\nUmberto, ¿qué hay de ti?\n\n[CUB4_V:CUBAN4]\nOh, voy a quedarme atrás, a vigilar el café con papá.\n\n[CUB4_W:CUBAN4]\nNo se siente muy bien, ¿sabes?\n\n[CUB4_02:CUBAN4]\n~g~Las bombas se colocarán con un temporizador de 45 segundos.\n\n[CUB4_04:CUBAN4]\n~r~¡Alertaste a la base, ahora no habrá modo de entrar!\n\n[CUB4_07:CUBAN4]\nEl disolvente está a la vuelta, amigo.\n\n[CUB4_08:CUBAN4]\nHola, amigos.\n\n[CUB4_09:CUBAN4]\nBueno. Haitianos putas. Muerte.\n\n[CUB4_10:CUBAN4]\nVamos.\n\n[CUB4_11:CUBAN4]\nSí, vamos.\n\n[CUB4_12:CUBAN4]\n¡Ey, necesitamos un coche de la banda haitiana!\n\n[CUB4_13:CUBAN4]\n¡Oye, vamos a encontrar a nuestros muchachos!\n\n[CUB4_14:CUBAN4]\nSigue a mis compadres.\n\n[CUB4_15:CUBAN4]\nDe acuerdo, allá vas...\n\n[CUB4_16:CUBAN4]\n¡Voy a colocar la bomba, cubridme!\n\n[CUB4_17:CUBAN4]\n¡CORRED!\n\n[CUB4_18:CUBAN4]\nTío, esta es una parte bonita de la ciudad...\n\n[CUB4_19:CUBAN4]\nCompadre, este lugar es un vertedero.\n\n[CUB4_20:CUBAN4]\nYo tenía una hermosa mujer... vivía por este barrio.\n\n[CUB4_21:CUBAN4]\nSabes, allí hacen unas buenas pizzas.\n\n[CUB4_22:CUBAN4]\n¡Tío! ¡Conduces como un loco!\n\n[CUB4_23:CUBAN4]\n¿Te has perdido tío?\n\n[CUB4_24:CUBAN4]\nDejaste atrás a Pepe, ve a por él.\n\n[CUB4_03:CUBAN4]\n~g~Permanece en el coche hasta que puedas aparcar sin percances dentro del recinto.\n\n[CUB4_26:CUBAN4]\n~g~Recoge a Pepe, dirígete al norte a Little Haiti y roba un coche Voodoo.\n\n[CUB4_27:CUBAN4]\n~g~Ve y reúnete con Rico y los otros cubanos.\n\n[CUB4_28:CUBAN4]\n~g~Reúnete con los otros cubanos en el laboratorio de sustancias químicas haitiano.\n\n[CUB4_29:CUBAN4]\n~g~Camina hacia cada uno de los marcadores para colocar la bomba en ese lugar.\n\n[CUB4_30:CUBAN4]\n~g~Después de colocar las tres bombas, aléjate de la fábrica antes que salte por los aires.\n\n[CUB4_31:CUBAN4]\n~g~¡Aléjate de la fábrica!\n\n[CUB4_32:CUBAN4]\n~g~Aparca el coche en el marcador y bájate de él.\n\n[CUB4_06:CUBAN4]\n~r~No te alejaste lo suficiente de la base, ¡y hemos tenido que abortar la explosión!\n\n{=================================== MISSION TABLE FINALE ===================================}\n\n[FIN1_01:FINALE]\n¿Qué está pasando?\n\n[FIN1_02:FINALE]\n¡Tommy! Oh, bien, bien. Escucha, escucha. Uh, escucha,\n\n[FIN1_03:FINALE]\nme gusta el pescado. Me encanta el pescado.\n\n[FIN1_04:FINALE]\nMe encantan como mascotas en peceras, o como comida en un plato,\n\n[FIN1_05:FINALE]\npero aunque los adoro, no quiero dormir con ellos.\n\n[FIN1_06:FINALE]\nDe acuerdo, pero ahora mismo, tus hermanos italianos van a salir de ahí para ponerme esos zapatos de cemento y yo...\n\n[FIN1_07:FINALE]\nCállate, Ken. Siéntate.\n\n[FIN1_08:FINALE]\nLance, ¿qué demonios ocurre?\n\n[FIN1_09:FINALE]\nEs tu amigo del norte, Tommy. No está muy contento de que matases a su hombre.\n\n[FIN1_10:FINALE]\nVienen hoy para ver el negocio.\n\n[FIN1_11:FINALE]\nTardaron más de lo que pensaba...\n\n[FIN1_12:FINALE]\nChicos, tenemos que acabar con esto y no dejar duda de que ésta es mi operación. ¡Mía!\n\n[FIN1_13:FINALE]\nKen, pon tres millones de la primera tanda de dinero falsificado en maletines.\n\n[FIN1_14:FINALE]\nLance, reúne a los muchachos...\n\n[FIN2_01:FINALE]\n¡Tommy!\n\n[FIN2_02:FINALE]\n¿Qué? ¿No hay un gran abrazo para tu viejo colega?\n\n[FIN2_03:FINALE]\nHe pasado quince años fuera del negocio,\n\n[FIN2_04:FINALE]\nestoy un poco oxidado respecto a las costumbres de la familia.\n\n[FIN2_05:FINALE]\nSiempre enfadado, ¿eh? Tommy.\n\n[FIN2_06:FINALE]\nNo te dije que tu temperamento te metería en problemas, ¿eh?\n\n[FIN2_07:FINALE]\nHay tres millones en los maletines...\n\n[FIN2_08:FINALE]\n¿Cuántos fueron? ¿Diez? No, once hombres.\n\n[FIN2_09:FINALE]\n¡Así es como llegaron a llamarte el Carnicero de Harwood! ¡Je je je!\n\n[FIN2_10:FINALE]\nMe enviaste a matar a un hombre, UN HOMBRE. Sabían que iba para allá.\n\n[FIN2_11:FINALE]\nVigila tu tono.\n\n[FIN2_12:FINALE]\nCualquiera pensaría que me echas la culpa por ese desafortunado conjunto de circunstancias.\n\n[FIN2_13:FINALE]\nSimplemente coge el dinero...\n\n[FIN2_14:FINALE]\n¿Que coja el maldito dinero?\n\n[FIN2_15:FINALE]\n¿Sabes, Tommy? Hice lo que pude por ti, tiré de algunos hilos, pedí favores.\n\n[FIN2_16:FINALE]\nYo era tu amigo, Tommy. Esperaba que entraras en razón, ver qué es bueno para el negocio.\n\n[FIN2_17:FINALE]\nConfié en ti, Tommy, y me decepcionaste.\n\n[FIN2_18:FINALE]\nPero al menos alguno de tu organización de mierda sabe hacer negocios,\n\n[FIN2_19:FINALE]\n¿No es verdad, Lance?\n\n[FIN2_20:FINALE]\nLo siento, Tommy. Esto es Vice City. Son negocios.\n\n[FIN2_21:FINALE]\nNos vendiste.\n\n[FIN2_22:FINALE]\nNo. Te vendí a TI, Tommy, te vendí a TI.\n\n[FIN2_23:FINALE]\nEl dinero de verdad está arriba, en la caja fuerte.\n\n[FIN2_24:FINALE]\nAsí que Tommy, ¿cuál es el gran plan?\n\n[FIN2_25:FINALE]\n¿Creías que solo me llevaría el dinero falso?\n\n[FIN2_26:FINALE]\n¿Salvar el culo y huir con el rabo entre las piernas?\n\n[FIN2_27:FINALE]\nNo.\n\n[FIN2_28:FINALE]\nSolo quería joderte antes de matarte.\n\n[FIN3_01:FINALE]\n¿Tommy?\n\n[FIN3_02:FINALE]\nOh, Dios mío, ¡Tommy! ¿Qué ha sucedido?\n\n[FIN3_03:FINALE]\n¿A ti qué te parece?\n\n[FIN3_04:FINALE]\n¡Parece que te han arruinado el traje!\n\n[FIN3_05:FINALE]\n¡Y Tommy, era un traje muy bonito! Tommy, ¿qué diablos ha ocurrido?\n\n[FIN3_06:FINALE]\nTuve un desacuerdo con un socio del negocio, ya sabes cómo son estas cosas.\n\n[FIN3_07:FINALE]\nTommy, cuando tengo un desacuerdo con un socio, le envío una carta muy enfadado.\n\n[FIN3_08:FINALE]\nQuizás me mee en su buzón. No empiezo la tercera guerra mundial.\n\n[FIN3_09:FINALE]\n¿Sabes? Quizás deberías hablar con mi psiquiatra...\n\n[FIN3_10:FINALE]\nÉse estúpido mamón, Lance...\n\n[FIN3_11:FINALE]\nTommy. A mí nunca me gustó ese tipo, ¿de acuerdo?\n\n[FIN3_12:FINALE]\nEra neurótico, era inseguro, era egocéntrico... ¡ese tipo era un gilipollas!\n\n[FIN3_13:FINALE]\n¡Me alegro de que lo eliminases!\n\n[FIN3_14:FINALE]\nNo creo que vayamos a tener más líos desde la parte norte...\n\n[FIN3_15:FINALE]\nporque ya no hay 'parte norte'.\n\n[FIN3_16:FINALE]\nAhora es todo sur.\n\n[FIN3_17:FINALE]\nEspera, eso quiere decir lo que creo que quiere decir, Tommy, ¿nene?\n\n[FIN3_18:FINALE]\n¿Qué crees que significa?\n\n[FIN3_19:FINALE]\nQue estamos al mando... Quiero decir, que tú estás al mando. Oh, Tommy...\n\n[FIN3_20:FINALE]\n¿Sabes, Ken? Este podría ser el comienzo de una hermosa relación comercial...\n\n[FIN3_21:FINALE]\nDespués de todo, eres un cómplice, traicionero, ladrón de tres al cuarto\n\n[FIN3_22:FINALE]\ny yo soy un asesino psicópata convicto y además paso farlopa.\n\n[FIN3_23:FINALE]\nLo sé. ¿No es sencillamente hermoso?\n\n[FIN_B1:FINALE]\n~g~Ve y liquida al traidor de ~y~Lance Vance~g~.\n\n[FIN_B2:FINALE]\n~g~Liquida a ~p~Sonny~g~ y acaba con esto de una vez por todas.\n\n[FIN_B3:FINALE]\n~g~La mafia está intentando robarte el dinero. Protege la caja fuerte.\n\n[FIN_B4:FINALE]\n~g~Estás casi muerto, consigue ~w~salud~g~ en el piso de abajo.\n\n[FIN_B5:FINALE]\n~g~La mafia está robándote el dinero, protege la ~c~caja fuerte~g~.\n\n[FIN_B7:FINALE]\n~r~La mafia te ha robado todo el dinero.\n\n[DEFSAFE:FINALE]\n~g~Regresa a la caja fuerte y protégela.\n\n{=================================== MISSION TABLE FIRETRK ===================================}\n\n[F_PASS1:FIRETRK]\n¡Fuego extinguido!\n\n[F_FAIL2:FIRETRK]\n~r~¡Llegas demasiado tarde!\n\n[F_CANC:FIRETRK]\n~r~¡Misión de bombero cancelada!\n\n[F_EXTIN:FIRETRK]\nFUEGOS:\n\n[F_START:FIRETRK]\n~g~Se ha informado de un vehículo ardiendo en la zona de ~a~. Ve y extingue el fuego.\n\n[SIREN_1:FIRETRK]\nPara activar la sirena de este vehículo, pulsa ~h~~k~~VEHICLE_HORN~~w~.\n\n[SIREN_2:FIRETRK]\nPara activar la sirena de este vehículo, pulsa ~h~~k~~VEHICLE_HORN~~w~.\n\n[FIREPRO:FIRETRK]\nNivel 12 de la misión del camión de bomberos completado. ¡Ahora eres completamente ignífugo!\n\n[F_FAIL1:FIRETRK]\nMisión de bombero terminada.\n\n[F_STAR1:FIRETRK]\n~g~Se ha informado de que hay vehículos ardiendo en la ~a~ zona. Ve y apaga el fuego.\n\n[SPRAY_4:FIRETRK] { reVC update }\nPulsa ~h~~k~~VEHICLE_FIREWEAPON~ ~w~para disparar el cañón de agua y ~h~~k~~VEHICLE_TURRETLEFT~~w~ o ~h~~k~~VEHICLE_TURRETRIGHT~~w~ para apuntar con él.\n\n[SPRAY_1:FIRETRK] { reVC update }\nPulsa ~h~~k~~VEHICLE_FIREWEAPON~ ~w~para disparar el cañón de agua y ~h~~k~~VEHICLE_TURRETLEFT~~w~ o ~h~~k~~VEHICLE_TURRETRIGHT~~w~ para apuntar con él.\n\n{=================================== MISSION TABLE GENERA1 ===================================}\n\n[GEN1_A:GENERA1]\n¡Sr. Vercetti!\n\n[GEN1_B:GENERA1]\nCoronel.\n\n[GEN1_D:GENERA1]\nNo, gracias.\n\n[GEN1_E:GENERA1]\nMe avergüenza admitir que una de las causas de nuestro mutuo problema parece ser la lengua larga de un hombre en el que solía confiar.\n\n[GEN1_F:GENERA1]\nHe tenido conmigo a González durante años, pero ahora su incompetencia alcanza nuevas cotas.\n\n[GEN1_G:GENERA1]\nLo correcto es que mates a González...\n\n[GEN1_H:GENERA1]\n¿Lo hizo él? El dinero es lo único importante para mí.\n\n[GEN1_I:GENERA1]\nPor tu gentileza te compensaré y después buscaremos juntos tu dinero.\n\n[GEN1_J:GENERA1]\nEstará en su ático, probablemente medio borracho. Utiliza esto...\n\n[GEN1_K:GENERA1]\nUtiliza esto...\n\n[GEN1_06:GENERA1]\n¡Eh! ¡Tiene una sierra!\n\n[GEN1_07:GENERA1]\n¡Mantente alejado de mí, cabrón miserable!\n\n[GEN1_08:GENERA1]\n¡Maldición, he desperdiciado mi vida y mi belleza!\n\n[GEN1_10:GENERA1]\n¡Te voy a cerrar esa bocaza tuya!\n\n[GEN1_11:GENERA1]\n¡Deja de correr gorda bola de sebo!\n\n[GEN1_12:GENERA1]\n¡Estate quieto y haré que sea rápido!\n\n[GEN1_13:GENERA1]\nDeja de chillar, a nadie le importa, ¡gordo!\n\n[GEN1_C:GENERA1]\nGracias por venir. Por favor siéntese. ¿Langosta?\n\n[GEN1_05:GENERA1]\n~g~¡Ve y liquida a González!\n\n[GEN1_09:GENERA1]\nTe pagaré el doble, Tommy, ¡EL DOBLE!\n\n[GEN1_18:GENERA1]\n~r~¡González ha conseguido llegar a la Jefatura de Policía!\n\n[GEN1_19:GENERA1]\n~g~¡La policía de Vice City viene a por ti!\n\n[GEN1_20:GENERA1]\n~g~Sube a un vehículo.\n\n[GEN1_21:GENERA1]\n~g~Ve al~h~ taller de pintura~g~ de~h~ Vice Point~g~.\n\n[GEN1_22:GENERA1]\n~g~Conduce tu vehículo hasta el interior del ~h~taller de pintura~w~ para perder tu ~h~nivel de se busca~w~, reparar y volver a pintar tu vehículo. El precio es ~h~100 $~g~. Esta vez es gratis.\n\n[GEN1_01:GENERA1]\nCuando estés corriendo, mantén pulsado ~h~~k~~PED_FIREWEAPON~~w~ para preparar un ataque cuerpo a cuerpo.\n\n[GEN1_02:GENERA1]\nCuando estés corriendo, mantén pulsado ~h~~k~~PED_FIREWEAPON~~w~ para preparar un ataque cuerpo a cuerpo.\n\n[GEN1_03:GENERA1]\nCuando estés corriendo, mantén pulsado ~h~~k~~PED_FIREWEAPON~~w~ para preparar un ataque cuerpo a cuerpo.\n\n[GEN1_14:GENERA1]\nSuelta ~h~~k~~PED_FIREWEAPON~~w~ para atacar.\n\n[GEN1_15:GENERA1]\nSuelta ~h~~k~~PED_FIREWEAPON~~w~ para atacar.\n\n[GEN1_16:GENERA1]\nSuelta ~h~~k~~PED_FIREWEAPON~~w~ para atacar.\n\n[GEN1_23:GENERA1]\n~g~Vuelve pasando por las puertas para regresar a la planta baja.\n\n{=================================== MISSION TABLE GENERA2 ===================================}\n\n[COL2_A:GENERA2]\n¡Tommy! Ven, acércate.\n\n[COL2_B:GENERA2]\nQué buena pinta, ¿eh? ¿Hocico de tapir?\n\n[COL2_C:GENERA2]\nNo. No, gracias.\n\n[COL2_D:GENERA2]\nTommy, eres como una brisa de la pampa que me ha liberado de la peste de la corrupción,\n\n[COL2_E:GENERA2]\naunque, parece que debo llorar su paso y seguir con el negocio como siempre.\n\n[COL2_F:GENERA2]\nEsto no me está acercando mucho a mi dinero...\n\n[COL2_G:GENERA2]\nTommy, amigo mío, ahora no estás en Liberty. Aquí hacemos las cosas de un modo diferente.\n\n[COL2_H:GENERA2]\nContinuaré con mis investigaciones pero mientras tanto tengo un valioso trato que cerrar.\n\n[COL2_I:GENERA2]\nUn favor para un amigo, Cortez.\n\n[COL2_J:GENERA2]\nEres un buen amigo, Tommy. Sabía que no me decepcionarías.\n\n[COL2_K:GENERA2]\nNecesito que te encuentres con un mensajero que ha conseguido una tecnología valiosa para mí...\n\n[COL2_1:GENERA2]\nLa lluvia, está muy húmeda esta época del año...\n\n[COL2_2:GENERA2]\n¿Qué?\n\n[COL2_3:GENERA2]\nAh, comment?\n\n[COL2_4:GENERA2]\nMira, me envía Cortez. Tan sólo dame los malditos chips.\n\n[COL2_5:GENERA2]\nOh... d'accord.\n\n[COL2_B1:GENERA2]\n~g~Encuéntrate con el mensajero en el centro comercial.\n\n[COL2_B2:GENERA2]\n~g~El mensajero está huyendo con los chips guía, ¡no le dejes escapar!\n\n[COL2_B3:GENERA2]\n~g~Recupera los chips guía y llévaselos de vuelta al Coronel.\n\n[COL2_F1:GENERA2]\n~r~¡Mataste al contacto!\n\n[COL2_F2:GENERA2]\n~r~El mensajero está muerto. Coge los chips guía.\n\n[COL2_6A:GENERA2]\n¡Alto, cerdo imperialista americano! Eso es propiedad del gobierno francés. ¡Y se acabó!\n\n[BLIPHLP:GENERA2]\nCuando el icono en el radar es un triángulo apuntando hacia arriba, indica que el objetivo está por encima del jugador.\n\n[COL2_F3:GENERA2]\n~r~Los chips de orientación están en el fondo del mar.\n\n[COL2_F4:GENERA2]\n~r~¡El mensajero ha escapado! Has fracasado en conseguir los chips de orientación.\n\n{=================================== MISSION TABLE GENERA3 ===================================}\n\n[GEN3_A:GENERA3]\nThomas, agradezco que hayas venido.\n\n[GEN3_B:GENERA3]\nPerdóname por ir directamente a los negocios.\n\n[GEN3_C:GENERA3]\nDíaz me ha pedido que supervise una transacción comercial poco importante.\n\n[GEN3_D:GENERA3]\nEsperemos que vaya mejor que la última vez, ¿eh?\n\n[GEN3_E:GENERA3]\nPor eso es por lo que pensé en ti, amigo mío.\n\n[GEN3_F:GENERA3]\nHe dejado protección en un aparcamiento de varias plantas.\n\n[GEN3_G:GENERA3]\nRecógela... luego ve a vigilar a los hombres de Díaz en el punto de entrega.\n\n[GEN3_H:GENERA3]\nGracias, amigo.\n\n[GEN3_1:GENERA3]\nMonopolizando toda la acción, ya veo...\n\n[GEN3_2:GENERA3]\nMira, ¿quieres dejar de seguirme a todas partes? ¿Por qué no vienes y me demuestras que vales para algo?\n\n[GEN3_3:GENERA3]\nPodría hacerlo. Mi nombre es Lance, por cierto.\n\n[GEN3_5:GENERA3]\nTú debes de ser el nuevo matón de Cortez.\n\n[GEN3_6:GENERA3]\nHasta que surjan oportunidades mejor pagadas.\n\n[GEN3_7:GENERA3]\nEstarán aquí en cualquier momento. Será mejor que consigamos una posición ventajosa...\n\n[GEN3_8:GENERA3]\n¡De acuerdo! Yo iré al balcón, tú sube a ese tejado al otro lado del patio.\n\n[GEN3_9:GENERA3]\n¡Estoy vivo! ¡Mamones! ¡Y todo gracias a ti! ¿Cómo te llamas?\n\n[GEN3_10:GENERA3]\nTommy.\n\n[GEN3_11:GENERA3]\nNos veremos pronto, ¡creo!\n\n[GEN3_12:GENERA3]\nMierda. ¿Dónde está Lance?\n\n[GEN3_14:GENERA3]\n¡Tommy! ¡Necesito ayuda aquí!\n\n[GEN3_15:GENERA3]\n¡No te preocupes, te tengo cubierto!\n\n[GEN3_16:GENERA3]\n¡Los hombres de Díaz están siendo eliminados!\n\n[GEN3_19:GENERA3]\n~g~¡Haitianos! ¡Están saboteando el trato! ¡Protege a Díaz!\n\n[GEN3_20:GENERA3]\n~g~Ve al aparcamiento donde podrás recoger el arma que te dejó el Coronel.\n\n[GEN3_22:GENERA3]\nSalud de Díaz:\n\n[GEN3_23:GENERA3]\n~g~¡Has dejado a Lance atrás! ¡Ve a por él!\n\n[GEN3_25:GENERA3]\n~r~¡Lance murió!\n\n[GEN3_28:GENERA3]\n~g~Devuélvele el maletín a Díaz.\n\n[GEN3_29:GENERA3]\n~g~Recoge el maletín y llévaselo a Díaz.\n\n[GEN3_30:GENERA3]\n~r~¡Se escapó con el dinero! ¡Díaz te arrancará las pelotas por ésto!\n\n[GEN3_33:GENERA3]\n~r~¡Mira adónde disparas! Se supone que tienes que proteger a Díaz y a sus hombres, ¡no dispararles!\n\n[GEN3_34:GENERA3]\n~r~¡No va a haber ningún trato si disparas a los cubanos!\n\n[GEN3_35:GENERA3]\n~g~¡Ha robado el dinero de Díaz!\n\n[GEN3_36:GENERA3]\n~g~¡Pilla una moto, persíguele y recupera el dinero de Díaz!\n\n[GEN3_37:GENERA3]\n~g~Aquí vienen los cubanos. Vigila el trato y asegúrate que Díaz y Lance están a salvo.\n\n[GEN3_38:GENERA3]\n~r~¡Díaz ha muerto! ¡Has fallado en protegerle!\n\n[GEN3_39:GENERA3]\n~g~Ve a tu posición estratégica en el piso de arriba.\n\n[GEN3_44:GENERA3]\n~g~Ve con Lance al punto de entrega y vigila a Díaz.\n\n[GEN3_45:GENERA3]\nEstarán aquí en cualquier minuto, mejor será que vayamos tomando posiciones estratégicas.\n\n[GEN3_40:GENERA3] { reVC update }\nPara ~h~disparar hacia el frente ~w~sobre una ~h~moto ~w~pulsa ~h~~k~~VEHICLE_FIREWEAPON~~w~.\n\n[GEN3_41:GENERA3] { reVC update }\nPara ~h~disparar hacia el frente ~w~sobre una ~h~moto ~w~pulsa ~h~~k~~VEHICLE_FIREWEAPON~~w~.\n\n[GEN3_46:GENERA3]\n¡Mierda!\n\n[GEN3_47:GENERA3]\n¡Tommy!\n\n[GEN3_48:GENERA3]\n¡Maldición!\n\n[GEN3_49:GENERA3]\nSalud de Lance:\n\n[GEN3_50:GENERA3]\n~r~¡Has perdido el dinero de Díaz! ¡La próxima vez intenta no convertir mi dinero en cenizas!\n\n[GEN3_51:GENERA3]\n¡Más condenados haitianos en una furgoneta apestosa!\n\n[GEN3_54:GENERA3]\n¡No os quedéis ahí, panda de gilipollas, perseguid a ese haitiano cabrón!\n\n[GEN3_55:GENERA3]\n¡Tommy! ¡Yo me quedo aquí a proteger a Díaz!\n\n[GEN3_18:GENERA3]\n~g~Aquí llegan los cubanos, mantente cerca de Díaz. Asegúrate de que la negociación entre Díaz y Lance sea segura.\n\n[GEN3_56:GENERA3]\n~r~¡Díaz ha caído en una emboscada y ha muerto! ¡La próxima vez no le pierdas de vista!\n\n[GEN3_57:GENERA3]\nEl Kruger es un rifle de asalto que te permite apuntar en primera persona manualmente.\n\n[GEN3_58:GENERA3]\nMantén pulsado ~h~~k~~PED_LOCK_TARGET~~w~ para ~h~apuntar~w~ con un rifle de asalto.\n\n[GEN3_59:GENERA3]\nMantén pulsado ~h~~k~~PED_LOCK_TARGET~~w~ para ~h~apuntar~w~ con un rifle de asalto.\n\n[GEN3_60:GENERA3]\nPulsa ~h~~k~~PED_FIREWEAPON~~w~ para ~h~disparar~w~ un rifle de asalto.\n\n[GEN3_61:GENERA3]\nPulsa ~h~~k~~PED_FIREWEAPON~~w~ para ~h~disparar~w~ un rifle de asalto.\n\n[GEN3_62:GENERA3]\nPulsa ~h~~k~~PED_FIREWEAPON~~w~ para ~h~disparar~w~ un rifle de asalto.\n\n[GEN3_63:GENERA3]\nAdemás de realizar maniobras de acercamiento,~h~ las motos ~w~te permiten ~h~disparar hacia adelante~w~.\n\n[GEN3_64:GENERA3] { reVC update }\nPara ~h~disparar hacia el frente ~w~sobre una ~h~moto ~w~pulsa ~h~~k~~VEHICLE_FIREWEAPON~~w~.\n\n[GEN3_65:GENERA3] { reVC update }\nPara ~h~disparar hacia el frente ~w~sobre una ~h~moto ~w~pulsa ~h~~k~~VEHICLE_FIREWEAPON~~w~.\n\n[GEN3_66:GENERA3] { reVC update }\nPara ~h~disparar hacia el frente ~w~sobre una ~h~moto ~w~pulsa ~h~~k~~VEHICLE_FIREWEAPON~~w~.\n\n[GEN3_67:GENERA3]\nPara disparar hacia el frente en una moto deberás tener un subfusil.\n\n[GEN3_53:GENERA3]\n¡Mi dinero!\n\n[GEN3_52:GENERA3]\n¿Esos haitianos creen que pueden enfrentarse a RICARDO DÍAZ?\n\n{=================================== MISSION TABLE GENERA4 ===================================}\n\n[DETON:GENERA4]\nDETONACIÓN:\n\n[COL4_3:GENERA4]\n¡CONVOY, ALTO!\n\n[COL4_6:GENERA4]\n¡NOS ESTÁN DISPARANDO!\n\n[COL4_7:GENERA4]\n¡Civil, aléjese del tanque!\n\n[COL4_8:GENERA4]\n¡DIJE, alejaos, INMEDIATAMENTE!\n\n[COL4_9:GENERA4]\n¡POSICIONES DEFENSIVAS!\n\n[COL4_11:GENERA4]\n- ¡Quite a esos civiles fuera de mi camino, soldado! - ¡Señor, sí, señor!\n\n[COL4_12:GENERA4]\n¡Civil en el TANQUE! ¡DETENEDLE!\n\n[COL4_13:GENERA4]\nEste es un convoy militar, no obstruyan nuestra ruta.\n\n[COL4_14:GENERA4]\nTírelo, soldado.\n\n[COL4_15:GENERA4]\n- ¡Mueva ese vehículo civil fuera de nuestro camino! - ¡Señor! ¡Moviendo el vehículo, señor!\n\n[COL4_17:GENERA4]\n¡Bien, PELOTÓN, MUÉVANSE!\n\n[COL4_18:GENERA4]\n¡Hay alguien en el tanque, señor!\n\n[COL4_19:GENERA4]\n- ¡Vaya a conseguir unos donuts, soldado! - ¡Señor, sí, señor!\n\n[COL4_20:GENERA4]\nBlanco localizado, señor.\n\n[COL4_21:GENERA4]\n¡FRANCOTIRADOR!\n\n[COL4_22:GENERA4]\nMe voy de aquí.\n\n[COL4_23:GENERA4]\n- ¡Objetivo completado! ¡Pelotón, rompan filas! - Vamos a comer unos cuantos donuts.\n\n[COL4_24:GENERA4]\n¡Activado protocolo de seguridad Delta India Eco! ¡Iniciada autodestrucción del vehículo!\n\n[COL4_26:GENERA4]\n¡Prepárate para morir, basura comunista!\n\n[COL4_B2:GENERA4]\n~r~El tanque llegó a su destino a salvo!\n\n[COL4_B5:GENERA4]\n~r~¡El tanque ha sido destruido!\n\n[COL4_01:GENERA4]\nDíaz estaba complacido, y le gustaría verte de nuevo.\n\n[COL4_02:GENERA4]\n¿Es eso algo bueno?\n\n[COL4_03:GENERA4]\n¡Por supuesto! Aunque estoy empezando a pensar que Díaz fue el responsable de nuestra desafortunada pérdida...\n\n[COL4_04:GENERA4]\n¿Qué te hace decir eso?\n\n[COL4_05:GENERA4]\nUno no esgrime acusaciones contra un hombre como Díaz... Solo estoy pensando en voz alta...\n\n[COL4_06:GENERA4]\nNo importa. Tengo una propuesta de la que te podrías beneficiar...\n\n[COL4_07:GENERA4]\nNo tengo tiempo para hacer más recados, Cortez.\n\n[COL4_08:GENERA4]\nYo habría pensado que un hombre con unas deudas tan grandes estaría ansioso por encontrar oportunidades. Por favor, Tommy, al menos escúchame.\n\n[COL4_09:GENERA4]\nAdelante...\n\n[COL410:GENERA4]\nTengo un comprador para una pieza de equipo militar que está siendo transportada a través de la ciudad. Recógela para mí...\n\n[COL411:GENERA4]\ny una vez que la tengas, quiero que me llames inmediatamente, entonces...\n\n[COL4_B4:GENERA4]\n~g~El tanque está bloqueado. Busca un modo de engañar a los ocupantes.\n\n[COL4_1:GENERA4]\n- ¿Que qué pasa con el artillero? - ¡No lo sé, señor!\n\n[COL4_4:GENERA4]\n- Ve arriba soldado. - ¡Sí, señor!\n\n[COL4_B1:GENERA4]\n~g~Ve y adquiere el vehículo militar que se está paseando por la ciudad.\n\n[COL4_B3:GENERA4]\n~g~Deja el tanque en el escondite del Coronel antes que se autodestruya.\n\n[COL4_B6:GENERA4]\n~g~¡Encuentra el modo de robar el tanque!\n\n[COL4_B7:GENERA4]\n~g~Conduce el tanque al garaje.\n\n[COL4_B8:GENERA4]\n~g~Bájate del tanque y sal del garaje.\n\n{=================================== MISSION TABLE GENERA5 ===================================}\n\n[COL5A_1:GENERA5]\nLas circunstancias fuerzan una apresurada partida, amigo.\n\n[COL5A_2:GENERA5]\n¿Cuál es el problema?\n\n[COL5A_3:GENERA5]\nLos franceses quieren recuperar la tecnología de sus misiles y después del último incidente,\n\n[COL5A_4:GENERA5]\nsiento que es momento de encontrar puertos más seguros.\n\n[COL5A_5:GENERA5]\n¿No sería más seguro volar?\n\n[COL5A_6:GENERA5]\nEstaría muerto antes de alcanzar el mostrador de facturación de equipajes. Además, necesito sacar del país mi mercancía.\n\n[COL5A_7:GENERA5]\n¿Necesitas otro guardaespaldas?\n\n[COL5A_8:GENERA5]\nTú, amigo mío, vales por diez guardaespaldas...\n\n[COL5B_1:GENERA5]\nThomas, me has protegido y servido bien.\n\n[COL5B_2:GENERA5]\nPero ahora debes dejarnos antes de que lleguemos a mar abierto.\n\n[COL5B_4:GENERA5]\nGracias, Coronel.\n\n[COL5B_5:GENERA5]\nUna petición más, mientras estoy fuera, ¿podrías vigilar a Mercedes por mí?\n\n[COL5B_6:GENERA5]\nCreo que ella puede cuidarse por sí misma, pero seguro, la vigilaré.\n\n[COL5B_7:GENERA5]\nGracias, amigo mío. Hasta luego.\n\n[COL5B_8:GENERA5]\nAdiós, amigo.\n\n[COL5_7:GENERA5]\n¡Deja de dispararme!\n\n[COL5_9:GENERA5]\n¡Tommy, haz que dejen de dispararme!\n\n[COL5_10:GENERA5]\n¡Tengo inmunidad diplomática!\n\n[COL5_11:GENERA5]\n¡No disparen, soy un Coronel!\n\n[COL5_12:GENERA5]\nThomas, mátales, mi país te adorará.\n\n[COL5_13:GENERA5]\n¡Tommy, los franceses nos superan!\n\n[COL5_14:GENERA5]\nTommy, mire a donde mire, hay franceses, ¡lo odio!\n\n[COL5_15:GENERA5]\nTommy, ¿cómo estás?\n\n[COL5_16:GENERA5]\n¡Ésto es por Piaf y Gainesbourg y por vuestro estúpido pan francés!\n\n[COL5_1:GENERA5]\n¡A babor! ¡A babor!\n\n[COL5_2:GENERA5]\n¡Están atacando desde estribor!\n\n[COL5_3:GENERA5]\n¡El puente está ahí delante!\n\n[COL5_4:GENERA5]\n¡Tienen un helicóptero!\n\n[COL5_B1:GENERA5]\n~g~Protege al Coronel y su yate a toda costa.\n\n[COL5_B2:GENERA5]\n~g~Ponte delante y despeja la ruta del yate del Coronel.\n\n[COL5_B3:GENERA5]\n~r~¡El Coronel está muerto!\n\n[COL5_B4:GENERA5]\n~g~Destruye el helicóptero de ataque.\n\n[COL5B_3:GENERA5]\nBajaré mi lancha personal. Quédatela, amigo, en señal de mi agradecimiento.\n\n[COL5_B5:GENERA5]\n~g~Dispara para abatir los helicópteros, no pongas en peligro el yate.\n\n[COL5_B6:GENERA5]\n~g~Te has quedado sin munición, consigue más de las escaleras en la cubierta superior.\n\n[COL5_B7:GENERA5]\n~g~Te estás quedando sin salud, consigue más de las escaleras en la cubierta superior.\n\n{=================================== MISSION TABLE HAIT1 ===================================}\n\n[HAM1_A:HAIT1]\n¿Hola? ¿Hola?\n\n[HAM1_B:HAIT1]\nEntra, cielo, y descansa los pies.\n\n[HAM1_C:HAIT1]\nTú debes de ser el gran hombre malo sobre el que ha estado hablando mi abuelo.\n\n[HAM1_D:HAIT1]\nMe cuenta cosas sobre ti, ya sabes, cuando me visita,\n\n[HAM1_E:HAIT1]\ny sobre los otros que te esperan.\n\n[HAM1_F:HAIT1]\nBien, todos llevamos muertos mucho tiempo, pero tú...\n\n[HAM1_G:HAIT1]\nNo me gustaría estar en tu pellejo.\n\n[HAM1_H:HAIT1]\nRecibí un mensaje. Para que viniese aquí.\n\n[HAM1_I:HAIT1]\n¿Puedes oírles?\n\n[HAM1_J:HAIT1]\nEstán diciendo tu nombre, deben quererte mucho, ¿no crees?\n\n[HAM1_K:HAIT1]\nAhora ayudarás a la tía Poulet y quizás ella te ayude.\n\n[HAM1_L:HAIT1]\nQuizás ella pueda darte un pequeño talismán después de todo esto.\n\n[HAM1_M:HAIT1]\n¿Darte algo de magia para echar el mal de ojo a la policía?\n\n[HAM1_N:HAIT1]\nMira, esto es todo muy... ¿darme qué?\n\n[HAM1_O:HAIT1]\nYo, yo, creo que recibí la dirección equivocada...\n\n[HAM1_P:HAIT1]\nHaz esto por mí, Tommy...\n\n[HAM1_Q:HAIT1]\nLos cubanos, tontos orgullosos y desagradables,\n\n[HAM1_R:HAIT1]\nhan estado causando problemas a mis encantadores chicos haitianos.\n\n[HAM1_S:HAIT1]\nAhora le han dicho a la policía donde he estado almacenando mis polvos.\n\n[HAM1_T:HAIT1]\nEllos piensan que es farlopa, pardillos.\n\n[HAM1_U:HAIT1]\nAhora sé un buen chico, Tommy, y ve a conseguir los polvos para la tía Poulet.\n\n[HAM1_V:HAIT1]\nSí, sí, seguro, seguro.\n\n[HAM1_1:HAIT1]\n~g~Los polis se están acercando a nuestros escondites. Ve y consíguelos antes que ellos lo hagan.\n\n[HAM1_2:HAIT1]\n~r~¡Los polis llegaron primero al escondite!\n\n[HAM1_3:HAIT1]\n~g~¡Lleva este material de vuelta al escondite!\n\n[HAM1_4:HAIT1]\n~g~¡Bien! ¡Ahora el siguiente!\n\n[HAM1_6:HAIT1]\n~r~¡Ese almacén está destruido, idiota!\n\n[HAM1_7:HAIT1]\n~g~¡Los polis han conseguido nuestro alijo! ¡Recupéralo antes de que se marchen!\n\n[HAM1_8:HAIT1]\n~g~Los polis están de camino para recoger el alijo, ¡date prisa!\n\n[HAT_1A:HAIT1]\n~g~¡No muevas ni un solo dedo!\n\n{=================================== MISSION TABLE HAIT2 ===================================}\n\n[HAT2_B1:HAIT2]\n~g~Ve hasta la camioneta que contiene las bombas aéreas.\n\n[HAT2_B2:HAIT2]\nMata a los cubanos...\n\n[HAT2_B4:HAIT2]\n¡Y destruye sus barcos!\n\n[HAT2_B5:HAIT2]\n~g~Los cubanos están huyendo. ¡No les dejes escapar!\n\n[HAT2_B6:HAIT2]\n~r~¡El avión RC está yendo demasiado lejos del alcance!\n\n[HAT2_B7:HAIT2]\n~g~Uno de los cubanos está escapando en un coche. ¡No dejes ningún testigo!\n\n[HAT2_B8:HAIT2]\n~r~¡No te quedan aviones RC!\n\n[HAT2_B9:HAIT2]\nAviones RC:\n\n[HAT2_1:HAIT2]\nOh. Lo siento, debo tener la dirección equivocada...\n\n[HAT2_2:HAIT2]\nBueno, también podrías entrar y descansar los pies y tomarte una taza de té.\n\n[HAT2_3:HAIT2]\n¿Tienes algo ahí para mí?\n\n[HAT2_4:HAIT2]\nSí...\n\n[HAT2_5:HAIT2]\nEste lugar me parece familiar. Un olor de la niñez... un deja vu...\n\n[HAT2_6:HAIT2]\nBien, Tommy, te voy a susurrar un pequeño recado para que lo hagas. Escúchame bien, ¿vale?\n\n[HAT2_7:HAIT2]\nTe pareces a alguien que yo...\n\n[HAT2_8:HAIT2]\nLos cubanos tienen barcos rápidos que usan para cruzar el charco cargados de polvo.\n\n[HAT2_9:HAIT2]\nEs su sustento.\n\n[HAT2_10:HAIT2]\nMi sobrino ha estado preparando pequeñas bombas aéreas para eliminarles.\n\n[HAT2_11:HAIT2]\nVuela los barcos y conviértelos en madera de ataúd.\n\n[HAT2_12:HAIT2]\nMuchas gracias por el té.\n\n[HAT2_B3:HAIT2] { reVC update }\nPulsa ~h~~k~~VEHICLE_FIREWEAPON~~w~ para soltar una bomba. Pulsa ~h~~k~~VEHICLE_ENTER_EXIT~~w~ para cancelar.\n\n{=================================== MISSION TABLE HAIT3 ===================================}\n\n[HAM3_A:HAIT3]\n¿Hola? Hola, eh... Estaba buscando a alguien por aquí...\n\n[HAM3_B:HAIT3]\nPareces hambriento, Tommy,\n\n[HAM3_C:HAIT3]\n¿Te conozco?\n\n[HAM3_D:HAIT3]\nSilencio.\n\n[HAM3_E:HAIT3]\nUna cosa más y te podré dejar marchar, Tommy.\n\n[HAM3_F:HAIT3]\nMis chicos están en guerra con los cubanos.\n\n[HAM3_G:HAIT3]\nPero sin armas.\n\n[HAM3_H:HAIT3]\nPero los cubanos tienen una sorpresa por llegar.\n\n[HAM3_I:HAIT3]\nMientras combaten en las calles, tú tomarás este rifle y los matarás en medio del alboroto.\n\n[HAM3_J:HAIT3]\nNadie te verá, nadie te oirá.\n\n[HAM3_K:HAIT3]\nTommy, si haces esto por mí, ya no estarás atado a los lazos de mi delantal.\n\n[HAM3_1:HAIT3]\n~g~Debemos ganar esta batalla. Si todos los haitianos mueren, perdemos nosotros.\n\n[HAM3_3:HAIT3]\n~g~Espero que los cubanos hagan trampas así que permanece alerta.\n\n[HAM3_4:HAIT3]\n~r~¡Te han visto! ¡La misión ha fracasado!\n\n[HAM3_5:HAIT3]\n~g~Debes matar a los cubanos desde lejos. No deben verte.\n\n[HAM3_8:HAIT3]\n~g~¡Los haitianos están muriendo! Mejora tu puntería.\n\n[HAM3_7:HAIT3]\n~g~¡Cuidado! Los cubanos han traído refuerzos. ¡¡Acaba con todos ellos!!\n\n[HAM3_2:HAIT3]\n~r~¡Los haitianos han muerto!\n\n[HAM3_L:HAIT3]\nVale, tía...\n\n{=================================== MISSION TABLE HOTEL ===================================}\n\n[INTB_A:HOTEL]\n¡Tommy! Tommy, ha pasado tanto tiempo.\n\n[INTB_B:HOTEL]\nHola, Sonny.\n\n[INTB_C:HOTEL]\nLo sé, lo sé. Te abruma la emoción.\n\n[INTB_D:HOTEL]\nQuince años... si parece que fue ayer.\n\n[INTB_E:HOTEL]\nSupongo que es cuestión de perspectiva.\n\n[INTB_F:HOTEL]\nEh, estar en el talego por la familia no es agradable,\n\n[INTB_G:HOTEL]\naunque la familia cuida de los suyos, ¿no es verdad?\n\n[INTB_H:HOTEL]\nY bien, cómo fue el negocio... ¿estás sentado en una pila de oro blanco?\n\n[INTB_I:HOTEL]\nMira, Sonny, nos tendieron una trampa. El negocio fue una emboscada. Harry y Lee están muertos.\n\n[INTB_J:HOTEL]\nMe estás tomando el pelo, ¿no? Tommy. Dime que aún tienes el dinero.\n\n[INTB_K:HOTEL]\nNo Sonny... no tengo el dinero.\n\n[INTB_L:HOTEL]\nÉse era mi dinero, Tommy, ¡mi dinero!\n\n[INTB_M:HOTEL]\n¡Espero que no me andes jodiendo, Tommy, porque sabes que soy un hombre con el que no se puede jugar!\n\n[INTB_N:HOTEL]\nEspera Sonny.\n\n[INTB_O:HOTEL]\nTienes mi garantía personal de que voy a conseguir recuperar el dinero y el alijo.\n\n[INTB_P:HOTEL]\nY te voy a enviar por correo las pelotas de los responsables.\n\n[INTB_Q:HOTEL]\nEh, ya lo sé. No eres tonto, Tommy, pero te prevengo, yo tampoco lo soy.\n\n[INTB_R:HOTEL]\nSi se tratase de cualquier otro, ya estarías MUERTO.\n\n[INTB_S:HOTEL]\nPero como se trata de ti, como hemos hecho historia, voy a dejar que te ocupes de esto.\n\n[INTB_T:HOTEL]\nMira, Sonny, tienes mi palabra.\n\n[INTB_U:HOTEL]\nEstaremos en contacto.\n\n{=================================== MISSION TABLE ICECRE1 ===================================}\n\n[ICC1_1:ICECRE1]\n~g~Utiliza la furgoneta de los helados para distribuir perica en Vice City.\n\n[ICC1_3:ICECRE1]\n~g~Recibirás dinero por cada venta que hagas, pero cuantas más transacciones hagas más atraerás la atención de la policía.\n\n[ICC1_4:ICECRE1]\n~g~No hay ningún cliente en esta zona, inténtalo en otra.\n\n[ICC1_5:ICECRE1]\nNegocios hechos:\n\n[ICC1_6:ICECRE1]\n~g~Utiliza la furgoneta Mr. Whoopee para distribuir los productos Cherry Popper por Vice City.\n\n[ICC1_7:ICECRE1]\n~g~Por cada transacción que hagas recibirás dinero, aunque cuantas más operaciones lleves a cabo más atención provocarás de la policía.\n\n[ICC1_8:ICECRE1]\n~g~Para llevar a cabo el negocio ~h~aparca la furgoneta, ~g~y pulsa el ~h~~k~~VEHICLE_HORN~ ~g~para que suene la música que llamará la atención de la gente.\n\n[ICC1_9:ICECRE1]\n~g~A las bandas locales no les gustará que hagas negocios en su territorio así que si haces esto, prepárate para hostilidades.\n\n[ICC1_10:ICECRE1]\n~g~Has hecho ~1~ tratos!\n\n[ICC1_11:ICECRE1]\n~g~Has hecho ~1~ trato!\n\n[ICC1_12:ICECRE1]\n¡PROPIEDAD ADQUIRIDA!\n\n[ICC1_13:ICECRE1]\n~r~¡No conseguiste ningún trato!\n\n[ICC1_14:ICECRE1]\nFÁBRICA DE HELADOS CONSOLIDADA\n\n[ICC1_15:ICECRE1]\n~g~La fábrica de helados generará ahora unos ingresos máximos de hasta ~1~ $. Asegúrate de recaudarlos regularmente.\n\n[ICC1_2:ICECRE1]\n~g~Aparca la furgoneta y pulsa ~h~~k~~VEHICLE_HORN~~w~ para que suene la música indicando a los clientes que estás listo para hacer empezar.\n\n[ICC1_16:ICECRE1]\n~g~Utiliza la furgoneta Mr. Whoopee para distribuir los productos Cherry Popper por Vice City.\n\n[ICE_AT1:ICECRE1]\nFÁBRICA DE HELADOS CONSOLIDADA\n\n[ICE_AT2:ICECRE1]\n~g~La fábrica Cherry Popper generará ahora unos ingresos hasta un máximo de ~1~ $. Asegúrate de recaudarlos de manera regular.\n\n[ICC1_17:ICECRE1]\nMisión de Distribución finalizada\n\n[ICC1_18:ICECRE1]\nVenta total de helados: ~1~ $\n\n[ICC1_19:ICECRE1]\nTotal de negocios hechos: ~1~\n\n{=================================== MISSION TABLE ICECUT ===================================}\n\n[ICC1_A:ICECUT]\n¿Quién eres tú?\n\n[ICC1_B:ICECUT]\nEl nuevo propietario.\n\n[ICC1_C:ICECUT]\n¿Fuiste ahora o en cualquier momento un niño?\n\n[ICC1_D:ICECUT]\n¿De qué estás hablando?\n\n[ICC1_E:ICECUT]\n¿Fuiste niño?\n\n[ICC1_F:ICECUT]\n¡Sí! ¡Calma! ¿Qué pasa contigo?\n\n[ICC1_G:ICECUT]\nLo sabía. Un niño.\n\n[ICC1_H:ICECUT]\n¡Un maldito, apestoso, lloriqueante, mocoso, vil, vomitivo y pequeño bebé chillón!\n\n[ICC1_I:ICECUT]\nBebés... Criaturas repugnantes, horribles y espantosas.\n\n[ICC1_J:ICECUT]\nMami no te quiere. ¡mierdecilla!\n\n[ICC1_K:ICECUT]\nCálmate.\n\n[ICC1_L:ICECUT]\nODIO los bebés, odio los niños.\n\n[ICC1_M:ICECUT]\nSon unos pequeños guarros, llorones, mocosos, perversos y vomitivos...\n\n[ICC1_N:ICECUT]\n¡Ya es suficiente!\n\n[ICC1_O:ICECUT]\n¿Qué pasa contigo?\n\n[ICC1_P:ICECUT]\n¿Fabricas helado, de acuerdo? Es básicamente para los niños.\n\n[ICC1_Q:ICECUT]\n¿Qué clase de psicópata eres tú?\n\n[ICC1_R:ICECUT]\nSolo para que lo entienda, ¿para qué hacer felices a los niños si los odias?\n\n[ICC1_S:ICECUT]\nOh, estúpido, apestoso, lloriqueante...\n\n[ICC1_T:ICECUT]\n¡Cállate!\n\n[ICC1_U:ICECUT]\n¡Mocoso!\n\n[ICC1_V:ICECUT]\nEl helado es una tapadera.\n\n[ICC1_W:ICECUT]\nDistribuimos otros productos no lácteos.\n\n[ICC1_X:ICECUT]\nY si veo un niño, le saco provecho.\n\n[ICC1_Y:ICECUT]\n¿Verdad, niños? Sí, sí, lo hago. Mamá no os quiere.\n\n[ICC1_Z:ICECUT]\n¡Os ODIA!\n\n[ICC1_ZA:ICECUT]\n¡PROPIEDAD ADQUIRIDA!\n\n{=================================== MISSION TABLE INTRO ===================================}\n\n[INT1_A:INTRO]\nTommy Vercetti... Mierda.\n\n[INT1_B:INTRO]\nNo pensé que le fueran a soltar nunca.\n\n[INT1_C:INTRO]\nMantuvo la cabeza gacha, ayuda a la gente a olvidar.\n\n[INT1_D:INTRO]\nLa gente lo recordará antes de lo que crees.\n\n[INT1_E:INTRO]\nCuando le vean paseando por las calles de su barrio.\n\n[INT1_F:INTRO]\nSerá malo para el negocio.\n\n[INT1_G:INTRO]\nBien, ¿qué vamos a hacer, Sonny?\n\n[INT1_H:INTRO]\nLe tratamos como a un viejo amigo y le tenemos ocupado fuera de la ciudad. ¿De acuerdo?\n\n[INT1_I:INTRO]\nHemos estado hablando de expandirnos hacia el sur. ¿Verdad?\n\n[INT1_J:INTRO]\nHoy en día Vice City es oro de veinticuatro quilates.\n\n[INT1_K:INTRO]\nLos colombianos, los mejicanos, demonios,\n\n[INT1_L:INTRO]\nincluso esos refugiados cubanos se están repartiendo un buen pedazo de la acción.\n\n[INT1_M:INTRO]\nPero todo es por la nieve, Sonny.\n\n[INT1_N:INTRO]\n¡Ninguna de las familias tocará esa mierda!\n\n[INT1_O:INTRO]\nLos tiempos cambian.\n\n[INT1_P:INTRO]\nLas familias no pueden seguir dando la espalda mientras nuestros enemigos recogen las recompensas.\n\n[INT1_Q:INTRO]\nAsí que enviaremos a alguien para que nos hagan el trabajo sucio\n\n[INT1_R:INTRO]\ny tranquilamente nos llevaremos un buen cacho. ¿Vale?\n\n[INT1_S:INTRO]\n¿Quién es nuestro contacto allí?\n\n[INT1_T:INTRO]\nKen Rosenberg, un estúpido abogado.\n\n[INT1_U:INTRO]\n¿Cómo va a atar corto a Vercetti?\n\n[INT1_V:INTRO]\nNo necesitamos que lo haga.\n\n[INT1_W:INTRO]\nSimplemente le soltaremos en Vice City\n\n[INT1_X:INTRO]\ny le daremos un poco de dinero para que empiece. ¿De acuerdo?\n\n[INT1_Y:INTRO]\nLe damos unos cuantos meses.\n\n[INT1_Z:INTRO]\nLuego vamos,\n\n[INT1_A1:INTRO]\ny le hacemos una pequeña visita, ¿de acuerdo?\n\n[INT1_A2:INTRO]\nPara ver cómo le va.\n\n[INT2_A:INTRO]\n¡Eh, eh, tíos! ¡Aquí, eh, Ken Rosenberg! ¡Je, je, genial!\n\n[INT2_B:INTRO]\nBueno, voy a llevaros a la reunión, ¿vale?\n\n[INT2_C:INTRO]\nHe hablado con los proveedores, y ellos están muy...\n\n[INT2_D:INTRO]\ninteresados en empezar una relación de negocios, así que...\n\n[INT2_E:INTRO]\nsi todo esto va bien, deberíamos...\n\n[INT2_F:INTRO]\nempezar a obtener beneficios, lo cual es, ya sabes...\n\n[INT2_G:INTRO]\nBueno.\n\n[INT2_H:INTRO]\nEntonces. Son hermanos, ¿vale?\n\n[INT2_I:INTRO]\nUno dirige el negocio,\n\n[INT2_J:INTRO]\ny el otro se encarga de los vuelos.\n\n[INT2_K:INTRO]\nAhora operan fuera de Méjico\n\n[INT3_A:INTRO]\nBien, son los del helicóptero.\n\n[INT3_B:INTRO]\nDe acuerdo, este es el trato.\n\n[INT3_C:INTRO]\nQuieren un intercambio directo en campo abierto.\n\n[INT3_D:INTRO]\n¿De acuerdo? De acuerdo, permanece firme, vamos.\n\n[INT3_E:INTRO]\nDe acuerdo, ahora con cuidado.\n\n[INT3_F:INTRO]\nEstoy aquí. ¡El coche está en marcha, nena!\n\n[INT3_G:INTRO]\n¿Lo tienes?\n\n[INT3_H:INTRO]\nColombiana, 100% con un grado de pureza A, amigo.\n\n[INT3_I:INTRO]\n¿Los verdes?\n\n[INT3_J:INTRO]\nDe diez y de veinte... usados.\n\n[INT3_L:INTRO]\n¡Vamos, fuera de aquí! ¡Arranca!\n\n[INT4_A:INTRO]\n¡Jodidos! ¡Estamos jodidos!\n\n[INT4_B:INTRO]\nMuy típico,\n\n[INT4_C:INTRO]\nsaco la cabeza del agujero un jodido segundo,\n\n[INT4_D:INTRO]\n¡Y el destino me echa la mierda a la cara!\n\n[INT4_E:INTRO]\nBueno, ¡jódete!\n\n[INT4_F:INTRO]\nCierra el pico y deja de quejarte. Estás vivo, ¿no?\n\n[INT4_G:INTRO]\nDéjame justo aquí.\n\n[INT4_H:INTRO]\nVe y abandona el coche y luego vete a dormir un poco.\n\n[INT4_I:INTRO]\nMañana me pasaré por tu oficina y podemos empezar a solucionar esto.\n\n[INT4_J:INTRO]\nDe acuerdo, es una buena idea, iré a dormir un poco.\n\n[INT4_K:INTRO]\n¿Qué vas a hacer tú.\n\n[INT4_L:INTRO]\nMe las arreglaré para volver a mi hotel.\n\n[INT4_M:INTRO]\nA despejar la mente y a pensar sobre esta mierda.\n\n[INT4_N:INTRO]\nVale.\n\n[INTRO1:INTRO]\nSaco la cabeza del agujero un jodido segundo y el destino, ¡me echa la mierda en la cara!\n\n[INTRO2:INTRO]\nVete a dormir un poco.\n\n[INTRO3:INTRO]\n¿Qué es lo que vas a hacer?\n\n[INTRO4:INTRO]\nMañana me pasaré por tu oficina y empezaremos a solucionar todo este desorden.\n\n[INT3_K:INTRO]\nCreo que hemos llegado a un acuerdo, amigo mío.\n\n[INT3_M:INTRO]\nDéjame ver.\n\n[INT2_L:INTRO]\nno, no, no, espera...\n\n[INT3_N:INTRO]\n¡Mierda!\n\n{=================================== MISSION TABLE KENT1 ===================================}\n\n[KPM1_A:KENT1]\nA ver tío, te voy a salvar el culo, colega.\n\n[KPM1_B:KENT1]\n¿De qué coño me estás hablando?\n\n[KPM1_C:KENT1]\nConoces a ese bastardo de Díaz, Don Farlopa.\n\n[KPM1_D:KENT1]\nTiene a tu colega, Lance. Dicen que tu amigo intentó atacarle por sorpresa...\n\n[KPM1_E:KENT1]\npero no fue lo suficientemente sorprendente, si entiendes lo que te quiero decir.\n\n[KPM1_F:KENT1]\n¿A dónde le llevó?\n\n[KPM1_G:KENT1]\n¡Tranquilo! Le hicieron cruzar la ciudad hasta el desguace.\n\n[KPM1_H:KENT1]\nMaldita sea... ¡Chalado!\n\n[KPM1_2:KENT1]\n~r~¡Se suponía que debías sacar con vida a Lance!\n\n[KPM1_3:KENT1]\nSALUD DE LANCE:\n\n[RESC_1:KENT1]\n¿Crees que puedes usar un arma?\n\n[RESC_2:KENT1]\nSí... supongo... yo también me alegro de verte.\n\n[RESC_3:KENT1]\nSalgamos de aquí.\n\n[RESC_4:KENT1]\nAhí va todo mi cuidadoso plan, directo a la mierda, gracias a ti. La jodiste bien.\n\n[RESC_5:KENT1]\nMató a mi hermano. ¿Qué esperabas que hiciese, cortarle el césped?\n\n[RESC_6:KENT1]\nVamos a tener que eliminar a ese mamón de Díaz antes de que él nos elimine a nosotros.\n\n[RESC_7:KENT1]\nHaz que te curen y encuéntrate conmigo en el puente que va a Star Island, ¿de acuerdo?\n\n[RESC_8:KENT1]\nDe acuerdo, entendido.\n\n[KPM1_1:KENT1]\n~g~¡Lance está siendo retenido en el desguace, ve y libérale!\n\n[KPM1_4:KENT1]\n~g~¡Lleva a Lance al hospital!\n\n[M_PASSN:KENT1]\n¡MISIÓN SUPERADA!\n\n[KPM1_5:KENT1]\n~g~¡Los hombres de Díaz te están buscando! Lleva a Lance al hospital.\n\n{=================================== MISSION TABLE KICKSTT ===================================}\n\n[KICK1_2:KICKSTT]\n~r~¡No volviste a la moto lo suficientemente rápido!\n\n[KICK1_7:KICKSTT]\n~r~¡Has destrozado la moto!\n\n[KICK1_8:KICKSTT]\n~g~¡Sube a la moto!\n\n[KICK1_T:KICKSTT]\nTIEMPO EMPLEADO:\n\n[KICKTM:KICKSTT]\n~b~TIEMPO DE PRUEBA: ~1~:~1~\n\n[KICKTM2:KICKSTT]\n~b~TIEMPO DE PRUEBA: ~1~:0~1~\n\n[GETBIKE:KICKSTT]\n~g~Tienes ~1~ segundos para volver a subir a una moto antes de que termine la misión.\n\n[KICK1_1:KICKSTT]\n~g~Completa el circuito lo más rápidamente posible.\n\n[KICK1_6:KICKSTT]\n~g~¡Bien hecho!\n\n[KICK_10:KICKSTT]\n~g~Utiliza la Sanchez para completar el circuito pasando por todos los puntos de control.\n\n[KICK_12:KICKSTT]\n~r~¡La has cagado!\n\n[KICK_13:KICKSTT]\n~r~¡Has tardado mucho tiempo!\n\n[KICK_11:KICKSTT]\n~g~Para abandonar la misión, sitúate en el ~q~marcador rosa~g~.\n\n{=================================== MISSION TABLE LAWYER1 ===================================}\n\n[LAW1_A:LAWYER1]\nVe a dormir un poco, dice...\n\n[LAW1_B:LAWYER1]\n¡Llevo sentado en esta silla toda la noche con las luces apagadas y bebiendo café!\n\n[LAW1_C:LAWYER1]\nEsto es un desastre. ¡Estamos muy jodidos, tío!\n\n[LAW1_D:LAWYER1]\nEstos gorilas, escúchame, van a venir aquí a arrancarme la cabeza. ¡Es ridículo!\n\n[LAW1_E:LAWYER1]\n¡NO fui a la universidad para ésto! De acuerdo, ¿ahora qué coño vamos a hacer?\n\n[LAW1_F:LAWYER1]\nCállate, siéntate y relájate. Te diré lo que vamos a hacer.\n\n[LAW1_G:LAWYER1]\nVas a descubrir quién se llevó nuestra nieve... y después voy a cargármelos.\n\n[LAW1_H:LAWYER1]\nEs una buena idea. Es una idea GENIAL. Déjame pensar, déjame pensar, déjame pensar.\n\n[LAW1_I:LAWYER1]\n¡Oh! Está este Coronel retirado, el coronel Juan García Cortez.\n\n[LAW1_J:LAWYER1]\nÉl es el que me ayudó a montar esta operación\n\n[LAW1_K:LAWYER1]\nbien lejos de los matones establecidos de Vice City. ¿Entendido?\n\n[LAW1_L:LAWYER1]\nBien, escucha. Está dando una fiesta en su lujoso yate en la bahía\n\n[LAW1_M:LAWYER1]\ny todos los hombres más importantes de Vice City van a estar allí.\n\n[LAW1_N:LAWYER1]\nTengo invitación, por supuesto que tengo invitación,\n\n[LAW1_O:LAWYER1]\npero no sueñes que vaya a asomar la cabeza por esa puerta... ¡ni lo sueñes!\n\n[LAW1_P:LAWYER1]\n¡Te lo dije, cállate! Iré yo mismo...\n\n[LAW1_Q:LAWYER1]\nA mí también me gusta el estilo de 1978, pero esto no va a ser una fiesta con cerveza y tías en pelotas.\n\n[LAW1_R:LAWYER1]\nQuiero decir, sin ánimo de ofender, creo que podrías hacer que la gente se volviese a mirar por razones equivocadas.\n\n[LAW1_S:LAWYER1]\n¿Qué hay de malo con cómo voy vestido?\n\n[LAW1_T:LAWYER1]\nVale, mira, ten. Pásate por donde Rafael, dile que te envío yo, hará que parezcas respetable.\n\n[LAW1_U:LAWYER1]\nBien, ve, vamos...\n\n[LAWP_1:LAWYER1]\nBuenas noches.\n\n[LAWP_2:LAWYER1]\nTengo entendido que viene de parte del Sr. Rosenberg,\n\n[LAWP_3:LAWYER1]\nEspero que ningún problema reciente le haya afectado a su salud física, o uh,\n\n[LAWP_4:LAWYER1]\no mental, Sr... ¿eh?\n\n[LAWP_5:LAWYER1]\nVercetti. Tan sólo tiene un poco de... agorafobia.\n\n[LAWP_6:LAWYER1]\nExcelente, excelente. ¿Y usted?\n\n[LAWP_7:LAWYER1]\nYo solo quiero mi farlopa.\n\n[LAWP_8:LAWYER1]\nAh. Ha sido un desgraciado cúmulo de circunstancias para todos los interesados.\n\n[LAWP_9:LAWYER1]\nPor supuesto, he iniciado mis propias pesquisas\n\n[LAWP_10:LAWYER1]\npero un asunto tan delicado llevará tiempo.\n\n[LAWP_11:LAWYER1]\nQuizás hablemos más tarde. ¿Eh?\n\n[LAWP_12:LAWYER1]\nMientras tanto, permítame presentarle a mi hija.\n\n[LAWP_13:LAWYER1]\n¡Mercedes!\n\n[LAWP_14:LAWYER1]\nCara mía, ¿podrías acompañar a nuestro invitado mientras atiendo a mis obligaciones?\n\n[LAWP_15:LAWYER1]\nPor supuesto, papá.\n\n[LAWP_16:LAWYER1]\nPor favor, discúlpeme.\n\n[LAWP_17:LAWYER1]\n¿Mercedes?\n\n[LAWP_18:LAWYER1]\nIntenta acostumbrarte.\n\n[LAWP_19:LAWYER1]\nEn fin, déjame presentarte a algunos de nuestros invitados más distinguidos...\n\n[LAWP_20:LAWYER1]\nEse es nuestro congresista Alex Shrub con la sonriente estrella de la silicona Candy Suxxx...\n\n[LAWP_21:LAWYER1]\n¿Conoces a mi encantadora esposa, Laura? ¿No?\n\n[LAWP_22:LAWYER1]\nBueno, desafortunadamente ella está en Alabama. Te presento a Candy.\n\n[LAWP_23:LAWYER1]\nY por ahí tenemos a la estirada estrella de las Mambas de Vice City, BJ.\n\n[LAWP_24:LAWYER1]\nSiempre tan encantador.\n\n[LAWP_25:LAWYER1]\nLe paré en seco, lo hice, ¡y le dejé en una silla de ruedas!\n\n[LAWP_26:LAWYER1]\n¡Ja, ja, ésa es buena!\n\n[LAWP_27:LAWYER1]\nBien, ahora estoy mirando una verdadera propiedad de primera.\n\n[LAWP_28:LAWYER1]\nY ese anfibio al lado de la piscina es Jezz Torrent,\n\n[LAWP_29:LAWYER1]\ncantante principal de Love Fist.\n\n[LAWP_30:LAWYER1]\n¿Sabéis cómo juegan al ping-pong en Tailandia?\n\n[LAWP_31:LAWYER1]\nDejad que os lo cuente,\n\n[LAWP_32:LAWYER1]\n¡no hace falta una pala precisamente! ¿entendéis lo que quiero decir?\n\n[LAWP_33:LAWYER1]\nImpotente.\n\n[LAWP_34:LAWYER1]\nY el trío charlatán.\n\n[LAWP_35:LAWYER1]\nEsa glándula sudorípara durmiente es la mano derecha de papá, González\n\n[LAWP_36:LAWYER1]\ny los otros dos son el pastor Richards\n\n[LAWP_37:LAWYER1]\ny el director de cine seudointelectual, Steve Scott.\n\n[LAWP_38:LAWYER1]\nPasión con las invasoras ninfómanas,\n\n[LAWP_39:LAWYER1]\nentonces aparece el tiburón gigante y...\n\n[LAWP_40:LAWYER1]\n¡Les arranca las pollas de un mordisco!\n\n[LAWP_41:LAWYER1]\nJa, bien. Nunca has visto nada igual, ¿Verdad?\n\n[LAWP_42:LAWYER1]\n¡Coronel!\n\n[LAWP_43:LAWYER1]\n¡Sus fiestas tienen siempre un gran éxito!\n\n[LAWP_44:LAWYER1]\nSólo puedo pedir disculpas por mi tardía llegada.\n\n[LAWP_45:LAWYER1]\nAh, de nada amigo. ¿Cómo nos encontramos?\n\n[LAWP_46:LAWYER1]\nNuestro negocio es muy estresante, siempre intentan desbancarnos.\n\n[LAWP_47:LAWYER1]\nHay un momento para recompensar a los amigos de uno y para liquidar a los enemigos, amigo.\n\n[LAWP_48:LAWYER1]\n¿Quién es el bocazas?\n\n[LAWP_49:LAWYER1]\nRicardo Díaz, alias Don Farlopa.\n\n[LAWP_50:LAWYER1]\n¡Mercedes!\n\n[LAWP_51:LAWYER1]\nOh, estaba a punto de llevar a mi amigo de vuelta a la ciudad.\n\n[LAWP_52:LAWYER1]\n¡En otro momento, Ricardo!\n\n[LAWP_53:LAWYER1]\nSalgamos de aquí.\n\n[LAWP_54:LAWYER1]\nMejor llévame al club Pole Position.\n\n[LAW1_2:LAWYER1]\n~g~Ve al barco del Coronel.\n\n[LAW1_4:LAWYER1]\n~r~¡Mataste a la hija del Coronel!\n\n[LAW1_5:LAWYER1]\n¿Trabajarás para mi padre?\n\n[LAW1_6:LAWYER1]\nQuizás.\n\n[LAW1_7:LAWYER1]\n¿Te importa que pose mi mano en tu regazo?\n\n[LAW1_8:LAWYER1]\nQuizás...\n\n[LAW1_9:LAWYER1]\nEs tan difícil tener un padre rico y poderoso. Vamos.\n\n[LAW1_10:LAWYER1]\n¡Nos vemos, guapo!\n\n[LAW1_11:LAWYER1]\nEstoy seguro.\n\n[LAW1_12:LAWYER1]\nBonita moto.\n\n[LAW1_13:LAWYER1]\n¡No! ¡Mi moto!\n\n[LAW1_3:LAWYER1]\n~g~Lleva a la hija del Coronel al club Pole Position.\n\n[HELP20:LAWYER1]\nVe al icono de la ~h~camiseta~w~ que hay en el radar para encontrar la tienda de Rafael.\n\n[LAW1_14:LAWYER1]\n¡Guau!, Me encantaría probar tu moto.\n\n[LAW1_15:LAWYER1]\nSí pequeño, pues recógela de Howlin' Pete's\n\n{=================================== MISSION TABLE LAWYER2 ===================================}\n\n[LAW2_A:LAWYER2]\n¡Ah! Espero que te lo estés pasando bien. Porque yo me estoy volviendo loco de preocupación. ¿Qué has descubierto?\n\n[LAW2_B:LAWYER2]\nQue hay más criminales en esta ciudad que en la cárcel. Necesitamos un confidente de las calles...\n\n[LAW2_C:LAWYER2]\nVale, déjame pensar, déjame pensar, déjame pensar...\n\n[LAW2_D:LAWYER2]\n¡AH! ¡Lo tengo!\n\n[LAW2_E:LAWYER2]\nEstá este inglés, un baboso de la industria musical,\n\n[LAW2_F:LAWYER2]\nse hace llamar Kent Paul.\n\n[LAW2_G:LAWYER2]\nBueno, tiene la cabeza tan metida en la mayoría de los culos de Vice City\n\n[LAW2_H:LAWYER2]\nque si alguien sabe el paradero de 20 kilos de farlopa,\n\n[LAW2_I:LAWYER2]\nes este tío, ¿de acuerdo? Siempre está en el Malibú.\n\n[LAW2_J:LAWYER2]\nLe haré una visita.\n\n[LAW2B_A:LAWYER2]\n¿De dónde saliste?\n\n[LAW2B_B:LAWYER2]\nHe estado buscando una chica como tú durante siglos, tía...\n\n[LAW2B_C:LAWYER2]\nKent Paul, tía. Por aquí soy el que manda.\n\n[LAW2B_D:LAWYER2]\nEstoy buscando a un tipo inglés...\n\n[LAW2B_E:LAWYER2]\nMuevo hilos, ¿entiendes lo que quiero decir?\n\n[LAW2B_F:LAWYER2]\nTe invitaré. Lo que quieras, te lo conseguiré, chica.\n\n[LAW2B_G:LAWYER2]\nNo te preocupes por nada, tía.\n\n[LAW2B_H:LAWYER2]\nPiérdete, guapa.\n\n[LAW2B_I:LAWYER2]\n¡Eh, eh, eh, eh, eh!\n\n[LAW2B_J:LAWYER2]\n¿Eres Kent Paul? Soy amigo de Rosenberg...\n\n[LAW2B_K:LAWYER2]\nRosenberg... Rosenberg... ¡Oh, ese chalado abogado de pacotilla!\n\n[LAW2B_L:LAWYER2]\n¡Ese tipo podría defender a un inocente y mandarle directamente al corredor de la muerte!\n\n[LAW2B_M:LAWYER2]\nPonnos otra copa, hermano.\n\n[LAW2B_N:LAWYER2]\nTodo el mundo es cómico.\n\n[LAW2B_O:LAWYER2]\nEscúchame, he perdido veinte kilos y un montón de pasta...\n\n[LAW2B_P:LAWYER2]\n¿Drogas, tío? Es un juego de tontos.\n\n[LAW2B_Q:LAWYER2]\n¿Qué sabes al respecto?\n\n[LAW2B_R:LAWYER2]\n¡Eh, eh! A lo que iba es que,\n\n[LAW2B_S:LAWYER2]\nhay un chef-camello que tiene su negocio en la cocina de un hotel en Ocean Drive.\n\n[LAW2B_T:LAWYER2]\nÚltimamente parece muy satisfecho de sí mismo. ¿Podrías ir y tantearle?\n\n[LAW2B_U:LAWYER2]\nLo haré... y ya nos veremos.\n\n[LAW2B_V:LAWYER2]\nSí, está bien. Venga... vete, idiota. ¡Te voy a quitar las luces de un puñetazo!\n\n[LAW2B_W:LAWYER2]\nPonme una copa... ¡y dónde está esa zorra!\n\n[LAW2C_A:LAWYER2]\nOh, así se hace, tipo duro. Machácale. Eso debería hacerle muy parlanchín.\n\n[LAW2C_B:LAWYER2]\n¿Tú también quieres un poco?\n\n[LAW2C_C:LAWYER2]\nEh, relájate. Quiero lo que tú quieres, hermano.\n\n[LAW2C_D:LAWYER2]\n¿Oh, sí? ¿Y qué es eso?\n\n[LAW2C_E:LAWYER2]\nTu dinero... y la nieve de mi hermano muerto. Desgraciadamente, hiciste callar a nuestro contacto.\n\n[LAW2C_F:LAWYER2]\nLos accidentes ocurren. Piérdete.\n\n[LAW2C_G:LAWYER2]\nEh, eh, guau. No hay necesidad de hacerte el llanero solitario conmigo.\n\n[LAW2C_H:LAWYER2]\nTal y como yo lo veo... somos dos hombres en una ciudad extraña. Necesitamos cubrirnos las espaldas mutuamente.\n\n[LAW2C_I:LAWYER2]\nMi espalda está bien, hermano...\n\n[LAW2C_J:LAWYER2]\n¿Estás seguro de eso? Ten, toma esto...\n\n[LAW2C_K:LAWYER2]\n¡Sígueme!\n\n[LAW2_1:LAWYER2]\n¿Qué estás mirando?\n\n[LAW2_2:LAWYER2]\nMejor empieza a hablar...\n\n[LAW2_3:LAWYER2]\n¡Oblígame, mamón!\n\n[LAW2_4:LAWYER2]\n¡Por aquí!\n\n[LAW2_5:LAWYER2]\nVoy a ver qué puedo averiguar. Te estaré vigilando, Tommy.\n\n[LAW2_6:LAWYER2]\n~g~Ve al club Malibú y busca a Kent Paul.\n\n[LAW2_7:LAWYER2]\n~g~Ve y busca al chef en Ocean Drive.\n\n[LAW2_10:LAWYER2]\n~g~Regresa al hotel.\n\n[LAW2_11:LAWYER2]\n~g~Recoge su teléfono móvil.\n\n[LAW2_12:LAWYER2]\n¡Adquirido un teléfono móvil! Ahora puedes recibir llamadas telefónicas.\n\n[LAW2_13:LAWYER2]\n~g~¡Has dejado a Lance atrás! ¡Ve y tráele!\n\n[LAW2_14:LAWYER2]\n¡Tenemos que salir pitando de aquí!\n\n[GUN_2A:LAWYER2]\n¡Mantén ~h~~k~~PED_LOCK_TARGET~ ~w~para ~h~apuntar automáticamente~w~ y pulsa ~h~~k~~PED_FIREWEAPON~ ~w~para ~h~disparar!\n\n[GUN_2C:LAWYER2]\n¡Mantén ~h~~k~~PED_LOCK_TARGET~ ~w~para ~h~apuntar automáticamente~w~ y pulsa ~h~~k~~PED_FIREWEAPON~ ~w~para ~h~disparar!\n\n[GUN_2D:LAWYER2]\n¡Mantén ~h~~k~~PED_LOCK_TARGET~ ~w~para ~h~apuntar automáticamente~w~ y pulsa ~h~~k~~PED_FIREWEAPON~ ~w~para ~h~disparar!\n\n[HELP17:LAWYER2]\nPulsa ~h~~k~~PED_FIREWEAPON~~w~ para atacar al chef.\n\n[HELP18:LAWYER2]\nPulsa ~h~~k~~PED_FIREWEAPON~~w~ para atacar al chef.\n\n[LAW3_11:LAWYER2]\nSitúate en el ~q~marcador rosa~w~ para ver las armas disponibles.\n\n[LAW3_12:LAWYER2]\nPuedes seleccionar armas pulsando ~h~izquierda~w~ o ~h~derecha~w~ en los ~h~botones de dirección~w~.\n\n[LAW3_13:LAWYER2]\nSi dispones de suficiente dinero, puedes comprar armas pulsando ~h~~k~~PED_SPRINT~~w~.\n\n[LAW3_14:LAWYER2]\nPuedes salir de la tienda pulsando ~h~~k~~VEHICLE_ENTER_EXIT~~w~.\n\n[LAW3_15:LAWYER2]\nVe al ~h~icono de la pistola~w~ que hay en el radar para encontrar el ~h~Ammu-Nation~w~.\n\n[LAW2_15:LAWYER2]\n~g~Ve a Ammu-Nation.\n\n[LAW2_K:LAWYER2]\nTómatelo con calma.\n\n[LAW2_16:LAWYER2]\nTienes que entender una cosa sobre esta ciudad. Tienes que saber protegerte.\n\n[LAW2_17:LAWYER2]\nVenga, la tienda de armas local está a un par de manzanas de aquí.\n\n[LAW2_18:LAWYER2]\nTommy, cada hombre necesita un poco de rock de vez en cuando.\n\n[LAW2_19:LAWYER2]\nEste de aquí es el club de striptease Pole Position. Quizás quieras entrar alguna vez.\n\n{=================================== MISSION TABLE LAWYER3 ===================================}\n\n[LAW3_A:LAWYER3]\n¡Aagh! ¡Oh, por el amor de Dios, eres tú! Oh, Jesús, ¡voy a necesitar pantalones nuevos!\n\n[LAW3_B:LAWYER3]\nEh, esos psicópatas del norte han estado entrometiéndose y pronto vendrán aquí.\n\n[LAW3_C:LAWYER3]\nBien, ¿dónde está el maldito dinero?\n\n[LAW3_D:LAWYER3]\nRelájate, relájate. Aún no hemos llegado a esa parte.\n\n[LAW3_E:LAWYER3]\nPensé que te estabas ocupando de esto, de verdad que sí.\n\n[LAW3_F:LAWYER3]\nY ahora esos tipos dicen que les tenemos que hacer un favor.\n\n[LAW3_G:LAWYER3]\nQuieres decir que yo tengo que hacerles un favor.\n\n[LAW3_H:LAWYER3]\nOh, por supuesto, eso es lo que quiero decir. ¿Doy yo la impresión de poder intimidar a un jurado?\n\n[LAW3_I:LAWYER3]\nNo podría intimidar a un niño y créeme, lo he intentado.\n\n[LAW3_J:LAWYER3]\nAhora mira, es eso, o al primo de Forelli, Giorgio, le caerán cinco años por fraude.\n\n[LAW3_K:LAWYER3]\n¡Tienes que encargarte de esos tipos!\n\n[LAW3_L:LAWYER3]\nComprendo. Ayuda al jurado a que cambie de idea. No te preocupes por ello.\n\n[LAW3_M:LAWYER3]\n¡No no no no... NO! Ya intenté eso. El caso del jurado no fue tan bien,\n\n[LAW3_N:LAWYER3]\nasí que HAZ que cambien de idea.\n\n[LAW3_1:LAWYER3]\nGiorgio envía sus saludos.\n\n[LAW3_2:LAWYER3]\nRecuerda, ''culpable'' es una palabra fea.\n\n[LAW3_3:LAWYER3]\nInocente hasta que yo diga lo contrario.\n\n[LAW3_4:LAWYER3]\nSabes que no es culpable.\n\n[LAW3_5:LAWYER3]\n¿Recuerdas a Giorgio? Recuerda que es inocente.\n\n[LAW3_6:LAWYER3]\nNo culpable. ¿Comprendido? Bien.\n\n[LAW3_8:LAWYER3]\n~r~¡Mataste a un miembro del jurado!\n\n[LAW3_9:LAWYER3]\n~g~¡Destroza el coche del miembro del jurado para sacarle de ahí!\n\n[HELP40:LAWYER3]\nPuedes destrozar coches usando el martillo o un arma similar.\n\n[HELP41:LAWYER3]\no puedes aplastarlas con un vehículo\n\n[LAW3_20:LAWYER3]\n~g~¡Destroza el coche del miembro del jurado!\n\n[LAW3_21:LAWYER3]\n¡No puedo creer lo que está pasando!\n\n[LAW3_22:LAWYER3]\n¡Increíble!\n\n[LAW3_23:LAWYER3]\n¡Ya! ¡Ya! ¡Entendido!\n\n[LAW3_24:LAWYER3]\n~g~Ese martillo será útil.\n\n[LAW3_7:LAWYER3]\n~g~¡Ve y coacciona a los dos miembros del jurado pero NO los mates!\n\n[HELP23:LAWYER3]\nPuedes ir al ~h~icono del martillo~w~ que hay en el radar si quieres comprar armas blancas en la ferretería.\n\n[LAW3_16:LAWYER3]\nEstúpido cretino de Florida.\n\n[LAW3_17:LAWYER3]\n¡Quítate de en medio!\n\n{=================================== MISSION TABLE LAWYER4 ===================================}\n\n[LAW4_A:LAWYER4]\nAvery, ni que decir tiene... ¡Tommy! ¡Tommy! ¿Algún progreso? No, no, no... cuéntamelo luego, cuéntamelo luego.\n\n[LAW4_B:LAWYER4]\nTommy, éste es Avery Carrington... ¿Creo que os conocisteis en la fiesta?\n\n[LAW4_C:LAWYER4]\nNo en persona.\n\n[LAW4_D:LAWYER4]\n¿Qué tal?\n\n[LAW4_E:LAWYER4]\nAvery tiene una proposición.\n\n[LAW4_F:LAWYER4]\n¿No tenemos otras cosas en mente?\n\n[LAW4_G:LAWYER4]\nEstoy intentando mantener todo bajo control así que, ¿podrías darme un respiro?\n\n[LAW4_H:LAWYER4]\nEstoy tenso como un alambre e incluso si estoy muerto al final de la semana, me gustaría pensar que no moriré pobre.\n\n[LAW4_I:LAWYER4]\nBien, calmaos, los dos.\n\n[LAW4_J:LAWYER4]\nHijo, si me ayudas, me encargaré de que cualquier capullo que te esté molestando se eche una buena siesta.\n\n[LAW4_K:LAWYER4]\nDe acuerdo, ¿qué puedo hacer por ti?\n\n[LAW4_L:LAWYER4]\nEsta compañía de reparto tiene el almacén en unos terrenos de primera. No venderán.\n\n[LAW4_M:LAWYER4]\nEstán aguantando como una vieja rata de la pradera, así que tenemos que ir allí y ahumar a esas alimañas para hacerlas salir.\n\n[LAW4_N:LAWYER4]\nVe allí y alborota el avispero.\n\n[LAW4_O:LAWYER4]\nLos de seguridad tendrán las manos ocupadas y entonces podrás colarte y dejarles fuera de combate.\n\n[LAW4_P:LAWYER4]\nY podrías pasarte por Rafael para cambiarte de ropa. Podrías estar allí un rato, pero sí, ve.\n\n[LAW4_Q:LAWYER4]\nDebería ser un motín.\n\n[LAW4_R:LAWYER4]\nSi las cosas salen como deberían, pásate alguna vez por mi oficina...\n\n[LAW4_1:LAWYER4]\nPor favor, dispérsense. ¡La dirección discutirá cualquier queja de la forma apropiada!\n\n[LAW4_2:LAWYER4]\nPor favor, dispérsense. ¡Vuelvan a sus casas!\n\n[LAW4_3:LAWYER4]\n¡Por favor, dispérsense! ¡Esto no es apropiado!\n\n[LAW4_4:LAWYER4]\nPor favor, dispérsense. Todos acabaréis en la calle.\n\n[LAW4_5:LAWYER4]\n¡Desenfundad, chicos! ¡Vamos a romper unos cuantos cráneos comunistas!\n\n[LAW4_13:LAWYER4]\n~g~Empieza a luchar con al menos 4 trabajadores para iniciar una revuelta.\n\n[LAW4_14:LAWYER4]\n~g~¡Destruye las furgonetas del complejo!\n\n[HELP38:LAWYER4]\nSi matas a alguien que lleva un arma, la dejará caer.\n\n[HELP39:LAWYER4]\nPuedes disparar a los barriles explosivos, pero mantén la distancia.\n\n{=================================== MISSION TABLE MIAMI_1 ===================================}\n\n[T4X4_1A:MIAMI_1]\n~g~Tienes ~1~ segundos para pasar por ~y~24~g~ puntos de control. ~g~Puedes atravesarlos en ~y~CUALQUIER ORDEN.\n\n[T4X4_1B:MIAMI_1]\n~y~ATRAVIESA~g~ el primer punto de control para poner en marcha el ~r~CRONÓMETRO.\n\n[T4X4_1C:MIAMI_1]\n¡~1~ de 24!\n\n[GETBIK1:MIAMI_1]\n¡Tienes ~1~ segundos para subirte en una PCJ 600!\n\n[GETBIK3:MIAMI_1]\n~r~Necesitas una PCJ 600 para realizar esta misión!\n\n{=================================== MISSION TABLE MM ===================================}\n\n[BLOD_04:MM]\nESTADO DEL COCHE:\n\n[BLOD_05:MM]\n~g~TIEMPO OBJETIVO: ~1~ Minuto\n\n[BLOD_06:MM]\n~g~TIEMPO OBJETIVO: ~1~ Minutos\n\n[BLOD_07:MM]\nNUEVO Mejor Tiempo: ~1~ Segundos\n\n[BLOD_08:MM]\nCoches destrozados: ~1~\n\n[BLOD_09:MM]\n~1~ $\n\n[BLOD_10:MM]\n¡GANADOR!\n\n[BLOD_01:MM]\nPasa por todos los puntos de control para aumentar tu tiempo total.\n\n[BLOD_02:MM]\nFracasarás si tu tiempo total llega a cero.\n\n[BLOD_03:MM]\n¡Consigue que tu tiempo total sean superior al objetivo a superar!\n\n{=================================== MISSION TABLE OVALRIG ===================================}\n\n[HOTR_01:OVALRIG]\n~g~La carrera dura 12 vueltas. Solamente los puestos 1, 2 y 3 obtienen premios en metálico.\n\n[HOTR_02:OVALRIG]\n~g~Si destrozas tu coche serás descalificado.\n\n[HOTR_03:OVALRIG]\n~g~Cuando tu coche sufra daños podrás repararlo en boxes.\n\n[HOTR_04:OVALRIG]\n~g~Este es el camino para salir del estadio.\n\n[HOTR_05:OVALRIG]\nEstado del coche:\n\n[HOTR_06:OVALRIG]\nVueltas:\n\n[HOTR_07:OVALRIG]\nNuevo mejor tiempo: ~1~:0~1~\n\n[HOTR_08:OVALRIG]\nTiempo: ~1~:~1~\n\n[HOTR_10:OVALRIG]\nTiempo de carrera:\n\n[HOTR_09:OVALRIG]\nPosición:\n\n[HOTR_12:OVALRIG]\n~r~¡Tu coche está destrozado!\n\n[HOTR_13:OVALRIG]\n~r~¡No ganaste la carrera!\n\n[HOTR_14:OVALRIG]\n~r~¡Has sido descalificado!\n\n[HOTR_15:OVALRIG]\nTiempo: ~1~:~1~\n\n[HOTR_16:OVALRIG]\nTiempo: ~1~:0~1~\n\n[HOTR_17:OVALRIG]\nMejor Tiempo: ~1~:~1~\n\n[HOTR_18:OVALRIG]\nMejor Tiempo: ~1~:0~1~\n\n[HOTR_19:OVALRIG]\nMejor Tiempo: NA\n\n[HOTR_20:OVALRIG]\nNuevo Mejor Tiempo: ~1~:~1~\n\n[HOTR_21:OVALRIG]\nNuevo Mejor Tiempo: ~1~:0~1~\n\n[HOTR_22:OVALRIG]\nMejor Resultado: NA\n\n[HOTR_23:OVALRIG]\nMejor resultado: 1\n\n[HOTR_24:OVALRIG]\nMejor resultado: 2\n\n[HOTR_25:OVALRIG]\nMejor resultado: 3\n\n[HOTR_26:OVALRIG]\nMejor resultado: ~1~\n\n[HOTR_27:OVALRIG]\nMejor Tiempo de Vuelta: ~1~.~1~ segundos\n\n[HOTR_28:OVALRIG]\nMejor Tiempo de Vuelta: ~1~.0~1~ segundos\n\n[HOTR_29:OVALRIG]\n~1~ $\n\n[HOTR_30:OVALRIG]\nPUESTO: 1\n\n[HOTR_31:OVALRIG]\nPUESTO: 2\n\n[HOTR_32:OVALRIG]\nPUESTO: 3\n\n[HOTR_33:OVALRIG]\nMejor tiempo de vuelta: ninguno\n\n[HOTR_11:OVALRIG]\nNuevo mejor tiempo de vuelta: ~1~,~1~ segundos\n\n[HOTR_34:OVALRIG]\nNuevo mejor tiempo de vuelta: ~1~,0~1~ segundos\n\n{=================================== MISSION TABLE PHIL1 ===================================}\n\n[PHIL1_A:PHIL1]\n¿Phil?\n\n[PHIL1_B:PHIL1]\n¡CORRE!\n\n[PHIL1_C:PHIL1]\n¡Corre!\n\n[PHIL1_E:PHIL1]\nMierda Phil, ¿te bebes ese mejunje?\n\n[PHIL1_F:PHIL1]\nDiablos, no tienes que bebértelo...\n\n[PHIL1_G:PHIL1]\nsolo tienes que olerlo para colocarte.\n\n[PHIL1_H:PHIL1]\nEscucha, Phil, dijiste que podrías proporcionarme algo de potencia de fuego...\n\n[PHIL1_I:PHIL1]\nPor supuesto.\n\n[PHIL1_J:PHIL1]\nHay un traficante de armas mejicano que me ha estado pisando el negocio últimamente.\n\n[PHIL1_K:PHIL1]\nSuele realizar su ronda semanal a esta hora.\n\n[PHIL1_L:PHIL1]\nHaz caer la mercancía de la parte de atrás de sus camiones antes de que acabe fuera de nuestro alcance.\n\n[PHIL1_M:PHIL1]\nY mientras estás en ello me estarás haciendo un favor.\n\n[PHIL1_N:PHIL1]\nLuego acaba con él.\n\n[PHI1_01:PHIL1]\n~g~Ve y pilla las armas de la parte trasera de los camiones del traficante.\n\n[PHI1_02:PHIL1]\n~g~El traficante de armas ha perdido la carga. Destroza la caja y recoge el arma.\n\n[PHI1_03:PHIL1]\n~g~Parece que han llamado pidiendo refuerzos.\n\n[PHI1_04:PHIL1]\n~g~Ahora ve y acaba con el resto de los traficantes.\n\n[PHI1_HP:PHIL1]\nCuando utilices Detonador de Granadas, lanza una granada y después provoca la explosión en cualquier momento.\n\n[PHIL1_O:PHIL1]\n¡Jooooodeeeeer!\n\n[PHIL1_D:PHIL1]\n¡Nunca acerques una llama a uno de los alambiques de boomshine de Phil Cassidy!\n\n{=================================== MISSION TABLE PHIL2 ===================================}\n\n[PHIL2_A:PHIL2]\nHola, Phil, ¿cómo te va?\n\n[PHIL2_B:PHIL2]\nEhhh, Tommy. ¿Cómo estás? Hace tanto tiempo...\n\n[PHIL2_C:PHIL2]\nTe juro que deberías dejar ese mejunje, tío.\n\n[PHIL2_D:PHIL2]\nHuele como decapante de pintura. Hace que me ardan los ojos...\n\n[PHIL2_E:PHIL2]\nShhh, shhh, tú mismo, Tommy,\n\n[PHIL2_F:PHIL2]\ny ven aquí porque hay algo que quiero enseñarte... algo.\n\n[PHIL2_G:PHIL2]\n¡Dios! ¿Debería poder oler eso desde aquí? Me estoy mareando.\n\n[PHIL2_H:PHIL2]\nNo te preocupes por el olor, Tommy, mira esto.\n\n[PHIL2_I:PHIL2]\nLas malditas pilas baratas o algo así. Hay más en el banco.\n\n[PHIL2_J:PHIL2]\n¡TA-DAAA!\n\n[PHIL2_K:PHIL2]\n¡Maldición!\n\n[PHI2_01:PHIL2]\n~g~Rápido, lleva a Phil al hospital.\n\n[PHI2_03:PHIL2]\n~r~¡Phil Cassidy está muerto! ¿Ahora quién va a suministrar armas en Vice City?\n\n[PHI2_05:PHIL2]\n¡Al hospital no, tío! ¡Demasiados polis y vietcongs!\n\n[PHI2_06:PHIL2]\nHay un excirujano del ejército que me debe unos cuantos favores... y un cortador de césped.\n\n[PHI2_07:PHIL2]\nTiene un lugar llamado Little Havana, oh mira, un pez gigante.\n\n[PHI2_08:PHIL2]\n¡Cuidado! ¡Charlies en la línea de los árboles!\n\n[PHI2_09:PHIL2]\n¿Soy yo o las carreteras están hechas de gelatina?\n\n[PHI2_10:PHIL2]\nCuchara rota a madre gallina, ¿me recibes?\n\n[PHI2_11:PHIL2]\n¡Cucharita, rita, rit, rit!\n\n[PHI2_12:PHIL2]\n¡Viene a por mí, chico!\n\n[PHI2_13:PHIL2]\nHay alas de plumas negras aleteando por todas partes...\n\n[PHI2_14:PHIL2]\nEs hermoso, tío... es hermoso... pero hace tanto frío...\n\n[PHI2_15:PHIL2]\n10-4 tenemos un conductor borracho.\n\n[PHI2_04:PHIL2]\nSALUD DE PHIL:\n\n[PHI_AS1:PHIL2]\nLOCAL DE PHIL CONSOLIDADO\n\n[PHI_AS2:PHIL2]\n~g~Nuevas armas disponibles para comprar en el Local de Phil.\n\n{=================================== MISSION TABLE PIZZA ===================================}\n\n[PIZ1_01:PIZZA]\n~g~Ve a entregar estas pizzas, debes lanzar la pizza a los clientes. Pasa cerca para lanzar las pizzas.\n\n[PIZ1_02:PIZZA]\n~g~Has lanzado todas tus pizzas, vuelve y recoge algunas más.\n\n[PIZ1_05:PIZZA]\n~g~Tienes cinco minutos para entregar los pedidos antes de que los clientes telefoneen a otra pizzería.\n\n[PIZ1_07:PIZZA]\n~r~¡Mataste al cliente! Estás despedido.\n\n[PIZ1_08:PIZZA]\n~r~Te has quedado sin tiempo. Estás despedido.\n\n[PIZ1_09:PIZZA]\n~r~¡Destruiste nuestra moto! Estás despedido.\n\n[PIZ1_11:PIZZA]\n¡Eh! ¡Vuelve a subir a la moto!\n\n[PIZ1_12:PIZZA]\nPizzas restantes:\n\n[PIZ1_06:PIZZA]\nPulsa ~h~~k~~TOGGLE_SUBMISSIONS~~w~ cuando estés en la moto para cancelar la misión.\n\n[PIZ1_13:PIZZA]\nReparte éstas bien calentitas.\n\n[PIZ1_14:PIZZA]\nAmigo, te toca repartir éstas.\n\n[PIZ1_15:PIZZA]\nA ver, tío, repártelas rápido.\n\n[PIZ1_16:PIZZA]\n¿Qué estás esperando, tío? Tienes pizzas que repartir.\n\n[PIZ1_17:PIZZA]\nYa sé que no querías ser el chico de las pizzas, vale me importa un cuerno.\n\n[PIZ1_18:PIZZA]\nReparte éstas.\n\n[PIZ1_19:PIZZA]\nHay que repartir éstas.\n\n[PIZ1_20:PIZZA]\nVenga hombre, reparte estas cosas o estás despedido.\n\n[PIZ1_21:PIZZA]\nTenemos gente esperando amigo.\n\n[PIZ1_22:PIZZA]\n¿Qué estás esperando? ¡Hay que repartir esto!\n\n[PIZ1_23:PIZZA]\nHaz el reparto de la maldita comida hombre.\n\n[PIZ1_24:PIZZA]\nHay que repartir éstas, amigo.\n\n[PIZ1_25:PIZZA]\nTío, ¿te puedes llevar éstas?\n\n[PIZ1_26:PIZZA]\nOye, haz el reparto pronto, vamos amigo.\n\n[PIZ1_27:PIZZA]\nVenga, tenemos prisa, haz ya el reparto.\n\n[PIZ1_28:PIZZA]\n¿Otra vez tú? Bueno, reparte éstas deprisa, amigo.\n\n[PIZ1_29:PIZZA]\nNo pierdas el tiempo amigo.\n\n[PIZ1_30:PIZZA]\nVenga ya vago hijo de puta, reparte esta mierda de una vez.\n\n[PIZ1_31:PIZZA]\nNo tendrás nunca un ascenso a menos que te muevas más rápido esta vez.\n\n[PIZ1_32:PIZZA]\n~r~¿La pizza es demasiado caliente para encargarte de ella?\n\n[PIZ1_33:PIZZA]\n~g~Vuelve al restaurante a por más pedidos.\n\n[PIZ1_34:PIZZA]\n~g~Pizza repartida, aquí está tu dinero.\n\n[PIZ_WON:PIZZA]\nMisión de Pizza Completada. Tu salud Personal máxima ha aumentado a 150.\n\n{=================================== MISSION TABLE PORN1 ===================================}\n\n[POR1_A:PORN1]\nAcción.\n\n[POR1_B:PORN1]\n¡Guau! Eso sí que es grande.\n\n[POR1_C:PORN1]\n30 cm, eso es para pensárselo, nene.\n\n[POR1_D:PORN1]\n¡CORTEN! ¿Quién es este idiota? ¡Tú! ¡Tú! ¿Por qué estás en el set? ¿POR QUÉ?\n\n[POR1_E:PORN1]\n¿De qué va toda esta basura?\n\n[POR1_F:PORN1]\n¿Alienígenas? ¿Cañas de pescar?\n\n[POR1_G:PORN1]\n¿Quién ha visto alguna vez a un tiburón tan grande?\n\n[POR1_H:PORN1]\nHay que desechar todo este material.\n\n[POR1_I:PORN1]\n¿Por qué te metiste en este negocio, mamón?\n\n[POR1_J:PORN1]\n¿Eh?\n\n[POR1_K:PORN1]\n¡Por los chochos, evidentemente! ¿Qué es esto?\n\n[POR1_L:PORN1]\nÉste es mi arte. ¡SEGURIDAD!\n\n[POR1_M:PORN1]\nMira, pomposo gilipollas, ahora eres de mi propiedad. Yo poseo todo esto.\n\n[POR1_N:PORN1]\nVamos a cambiar este lugar...\n\n[POR1_O:PORN1]\nVoy a hacerte rico.\n\n[POR1_P:PORN1]\nUsted es... Usted... ¿Usted es Tommy Vercetti? Pero yo creí que usted era...\n\n[POR1_Q:PORN1]\nEso es.\n\n[POR1_R:PORN1]\nVamos a hacer algunos cambios por aquí y vamos a empezar a hacer dinero de verdad.\n\n[POR1_S:PORN1]\nEn realidad, alguna vez has pensado en...\n\n[POR1_T:PORN1]\nPero primero, vamos a necesitar unas chicas guapas de verdad...\n\n[POR1_U:PORN1]\nSí, las chicas están bien, pero tú... ¡guau!\n\n[POR1_02:PORN1]\n~g~ Ve y elimina al chulo de Candy, luego vuelve y recoge a Candy.\n\n[POR1_04:PORN1]\nCandy. Estoy buscando una estrella de cine. ¿Estás interesada?\n\n[POR1_05:PORN1]\n¡Claro! Pero tendrás que hablar con mi agente...\n\n[POR1_06:PORN1]\n¿Qué DEMONIOS estás haciendo?\n\n[POR1_07:PORN1]\n¡Hoy deberías haberte quedado en casa!\n\n[POR1_7B:PORN1]\n¿Puedes creer a este gilipollas?\n\n[POR1_08:PORN1]\n¡Eh, Mercedes!\n\n[POR1_09:PORN1]\n¡Eh, Tommy! ¿Quieres ir de fiesta?\n\n[POR1_10:PORN1]\nAhora no, preciosa. ¿Te interesa hacer algunas películas?\n\n[POR1_11:PORN1]\nPor supuesto. Mientras que sea una peli barata y cutre.\n\n[POR1_13:PORN1]\n~g~Lleva a las chicas de vuelta al Estudio para que conozcan a Steve.\n\n[POR1_14:PORN1]\n¡Contratada!\n\n[POR1_15:PORN1]\nEh Tommy, ¿¡qué, vienes a entrar en calor!?\n\n[POR1_17:PORN1]\n¡Guau, un tiburón genial!\n\n[POR1_18:PORN1]\n~r~¡Mercedes está muerta!\n\n[POR1_20:PORN1]\nTommy, ¿a dónde vas? ¡Vuelve aquí!\n\n[POR1_21:PORN1]\n¿A dónde vas?\n\n[POR1_22:PORN1]\nTommy, ¿cuando vamos a pasar algún tiempo a solas?\n\n[POR1_01:PORN1]\n~g~¡Candy Suxxx sería perfecta para el papel principal!\n\n[POR1_12:PORN1]\n~g~Ve con Candy a encontrarte con Mercedes.\n\n[POR1_16:PORN1]\nQuizás después, nena...\n\n[POR1_24:PORN1]\n~g~Vuelve y recoge a Candy.\n\n[POR1_25:PORN1]\n~g~Te has dejado atrás a Candy, ve y tráela.\n\n[POR1_23:PORN1]\n~g~Candy estará ocupándose de unos asuntos en el ~h~centro de la ciudad~g~.\n\n[POR1_26:PORN1]\n~g~Aquí está Candy, parece que ha estado otra vez con el congresista Shrub.\n\n[POR1_27:PORN1]\nVenga, vamos.\n\n[POR1_28:PORN1]\n¡Tommy ten cuidado! ¡Aún no he asegurado mis implantes!\n\n[POR1_29:PORN1]\n¿Y a esto le llamas conducir?\n\n[POR1_30:PORN1]\n¡No podré hacer ningún numerito porno después de esto!\n\n[POR1_31:PORN1]\n¿Qué? ¿Me estás intentando matar? ¡Creía que era la estrella era yo!\n\n{=================================== MISSION TABLE PORN2 ===================================}\n\n[POR2_A:PORN2]\n¿Cómo va el rodaje, Steve?\n\n[POR2_B:PORN2]\nBien, Candy es una fuera de serie y esa chica nueva ¡es insaciable!\n\n[POR2_C:PORN2]\nSe repasó a la mitad del reparto antes de que pudiese medir la luz.\n\n[POR2_D:PORN2]\nDe todas formas, eh, mañana vamos a exteriores a rodar las escenas del barco...\n\n[POR2_E:PORN2]\n¿Escenas del barco, qué escenas del barco?\n\n[POR2_F:PORN2]\nLos pescadores son presa de la pasión cuando aparece el tiburón gigante...\n\n[POR2_G:PORN2]\n¿Qué te dije del tiburón gigante?\n\n[POR2_H:PORN2]\nDije, ''SIN TIBURÓN GIGANTE'', ¿de acuerdo?\n\n[POR2_I:PORN2]\n¡Tú solo tienes que mantener las cámaras apuntando a los conejos!\n\n[POR2_J:PORN2]\nDe acuerdo, de acuerdo, eh Tommy, uno tiene que intentarlo, ¿de acuerdo?\n\n[POR2_K:PORN2]\n¿Has hecho que impriman esos folletos?\n\n[POR2_L:PORN2]\nSí, pero nadie va a distribuir esas cosas, quiero decir que...\n\n[POR2_M:PORN2]\nson demasiado... poco imaginativos.\n\n[POR2_N:PORN2]\nNo te preocupes por eso.\n\n[POR2_O:PORN2]\nTengo mis propias ideas para la distribución.\n\n[POR2_P:PORN2]\nVale. Candy, ven a mi caravana.\n\n[POR2_01:PORN2]\n~g~Hay un hidroavión que se utilizó como atrezzo en una antigua película independiente a la vuelta de los estudios.\n\n[POR2_02:PORN2]\n~g~Escoge uno de los puntos de control para empezar a dejar caer los folletos.\n\n[POR2_03:PORN2]\n~g~Deja caer los folletos por todo el camino hasta el último punto de control.\n\n[POR2_04:PORN2]\n~r~¡COMBUSTIBLE BAJO!\n\n[POR2_05:PORN2]\nUtilízalo para distribuir los folletos por toda la ciudad.\n\n[DILDO:PORN2]\nCombustible del Skimmer:\n\n[POR2_Q:PORN2]\n¡Jo!, tío.\n\n[PORN2_9:PORN2]\n~g~Tienes ~1~ segundos para volver a subir a una Skimmer antes de que termine la misión.\n\n{=================================== MISSION TABLE PORN3 ===================================}\n\n[POR3_A:PORN3]\nVale, ¿cuál es el problema ahora?\n\n[POR3_B:PORN3]\n¡SSShhhh!\n\n[POR3_C:PORN3]\nBien, después de este encuentro cercano con las invasoras ninfómanas\n\n[POR3_D:PORN3]\nnuestro héroe se encuentra incapaz de pensar en nada excepto en esta enorme montaña fálica...\n\n[POR3_E:PORN3]\ny es entonces cuando queremos hacer la escena con la tina de puré de patatas, pero entonces...\n\n[POR3_F:PORN3]\n¡Me importa una mierda!\n\n[POR3_G:PORN3]\n¡Sigue, sigue!\n\n[POR3_H:PORN3]\nEh Tommy...\n\n[POR3_I:PORN3]\n¿Mencionaste algo sobre un problema legal al teléfono?\n\n[POR3_J:PORN3]\n¡Vaya que sí! El congresista Alex Shrub se ha subido al tren preelectoral y va tras el voto puritano.\n\n[POR3_K:PORN3]\nHay rumores de que va a apoyar medidas restrictivas, digamos,\n\n[POR3_L:PORN3]\npara el aspecto más lujurioso de la gran industria del entretenimiento de esta nación.\n\n[POR3_M:PORN3]\nGenial.\n\n[POR3_N:PORN3]\n¡Candy! Tú conoces a Shrub,\n\n[POR3_O:PORN3]\n¿llegasteis a algo pervertido?\n\n[POR3_P:PORN3]\n¡Oh sí, oh sí, oh sí! ¡Sí sí sí SÍ! ¡OOOoooh!\n\n[POR3_Q:PORN3]\nPor favor dime que filmaste eso.\n\n[POR3_R:PORN3]\n¿Eso era parte del eh... o estaba hablando conmigo...?\n\n[POR3_S:PORN3]\nEh, uno nunca podría decirlo... De todas formas...\n\n[POR3_T:PORN3]\nProbablemente sea mejor que la sigas después del rodaje,\n\n[POR3_U:PORN3]\npara ver si te lleva a su nuevo nido de amor.\n\n[POR3_V:PORN3]\n¿Tienes una cámara?\n\n[POR3_X:PORN3]\nVale, conseguidle una cámara.\n\n[POR3_02:PORN3]\n~r~¡Has asesinado al Congresista! Ahora no habrá modo de que puedas chantajearle.\n\n[POR3_03:PORN3]\n~r~Has alertado a la protección del Congresista, le sacarán de aquí inmediatamente.\n\n[POR3_04:PORN3]\nCandy, ¿podrías llamarme Marta?\n\n[POR3_05:PORN3]\nOh Alex, quiero decir Marta. Lo que tú digas.\n\n[POR3_06:PORN3]\nMarta, alguien está mirando... qué pervertido.\n\n[POR3_07:PORN3]\nTú, el de ahí. Dame esa cámara.\n\n[POR3_01:PORN3]\n~g~Sigue la ~h~limusina~g~ de Candy.\n\n[POR3_15:PORN3]\n~r~¡Has destruido la limusina de Candy!\n\n[POR3_17:PORN3]\n~g~Regresa a la compañía de pornografía con las fotos.\n\n[POR3_19:PORN3]\n~r~¡Te has quedado sin película!\n\n[POR3_21:PORN3]\n~g~¡Has perdido la limusina de Candy!\n\n[POR3_22:PORN3]\n~g~El Hotel WK Chariot frente a este balcón debería proporcionar el lugar ideal para la sesión fotográfica.\n\n[POR3_23:PORN3]\n~g~Hay una puerta lateral que te permitirá acceder al hotel.\n\n[POR3_08:PORN3]\nMantén pulsado ~h~~k~~PED_LOCK_TARGET~ ~w~para~h~ enfocar~w~ con la cámara.\n\n[POR3_09:PORN3]\nMantén pulsado ~h~~k~~PED_LOCK_TARGET~ ~w~para~h~ enfocar~w~ con la cámara.\n\n[POR3_10:PORN3]\nPulsa ~h~~k~~PED_SNIPER_ZOOM_IN~ ~w~para ~h~acercar el zoom ~w~con la cámara y ~h~~k~~PED_SNIPER_ZOOM_OUT~ ~w~para ~h~alejarlo ~w~de nuevo.\n\n[POR3_11:PORN3]\nPulsa ~h~~k~~PED_SNIPER_ZOOM_IN~ ~w~para ~h~acercar el zoom ~w~con la cámara y ~h~~k~~PED_SNIPER_ZOOM_OUT~ ~w~para ~h~alejarlo ~w~de nuevo.\n\n[POR3_12:PORN3]\nPulsa ~h~~k~~PED_FIREWEAPON~ ~w~para sacar una foto.\n\n[POR3_13:PORN3]\nPulsa ~h~~k~~PED_FIREWEAPON~ ~w~para sacar una foto.\n\n[POR3_14:PORN3]\nPulsa ~h~~k~~PED_FIREWEAPON~ ~w~para sacar una foto.\n\n[POR3_20:PORN3]\n~g~Si necesitas transporte, utiliza el ~h~Sparrow~g~ que está en la parte de atrás.\n\n[POR3_16:PORN3]\n~g~Necesitas tres buenas fotos de Alex Shrub con Candy para chantajearle.\n\n[POR3_24:PORN3]\nFOTOS HECHAS:\n\n{=================================== MISSION TABLE PORN4 ===================================}\n\n[POR4_A:PORN4]\nLo siento, pero no puedo tragarme eso ahora.\n\n[POR4_B:PORN4]\n¡Oh, VENGA, cariño!\n\n[POR4_C:PORN4]\nLa tiene como un cachalote, por el amor de Dios,\n\n[POR4_D:PORN4]\n¿cómo es que no puedes sentir el papel?\n\n[POR4_E:PORN4]\nPero Stevie...\n\n[POR4_F:PORN4]\n¿Cómo está mi director estrella?\n\n[POR4_G:PORN4]\nOh, tío. La lucha entre la integridad artística y\n\n[POR4_H:PORN4]\nla acción cargante y bombeante continúa sin perder intensidad.\n\n[POR4_I:PORN4]\nY antes de que puedas preguntarlo, sí, los cuatro vídeos serán lanzados en sus...\n\n[POR4_J:PORN4]\nCariño, podrías POR FAVOR mantener la anaconda dentro del plano,\n\n[POR4_K:PORN4]\n¡cuesta por hora más de lo que cuestas tú!\n\n[POR4_L:PORN4]\nOh, lo siento, Steve.\n\n[POR4_M:PORN4]\nEstaba pensando, necesitamos algún tipo de gran truco publicitario para promover de verdad el lanzamiento.\n\n[POR4_N:PORN4]\nAlgo que tenga un verdadero impacto en la ciudad, ¿tienes alguna idea?\n\n[POR4_O:PORN4]\nBueno, en los viejos tiempos solían organizar fiestas,\n\n[POR4_P:PORN4]\nestrellas, limusinas, el cielo nocturno con los focos entrecruzados...\n\n[POR4_Q:PORN4]\n¿Focos? Tengo una idea...\n\n[POR4_R:PORN4]\n...sí, sí, sí. Los numeritos de lentejuelas, y las limusinas, oh, premieres.\n\n[POR4_S:PORN4]\nOh, sí, madam, por supuesto madam,\n\n[POR4_T:PORN4]\ny la prensa, y el bombardeo de luces...\n\n[POR4_01:PORN4]\n~g~Ve al ~y~centro~g~ y ajusta los focos sobre lo alto del edificio.\n\n[POR4_02:PORN4]\n~g~Necesitarás una moto rápida para saltar de un tejado a otro. El guardia de seguridad normalmente lleva una ~y~PCJ 600~g~ para ir a trabajar...\n\n[POR4_03:PORN4]\n~g~Necesitarás subir a los tejados de los edificios. Debería de haber un ascensor que lleve a una de las oficinas superiores...\n\n[POR4_06:PORN4]\n~g~Vuelve a la oficina inferior si de nuevo necesitas acceso a los tejados.\n\n[POR4_07:PORN4]\n~g~Necesitarás una moto para poder saltar de un edificio a otro.\n\n[POR4_08:PORN4]\n~g~Atraviesa la ventana para empezar el recorrido. Tienes hasta las 07:00 antes de que haya demasiada luz como para subir allí sin ser visto.\n\n[POR4_09:PORN4]\n~g~Los marcadores rosas te mostrarán a qué edificio saltar después.\n\n[POR4_10:PORN4]\n~r~Hay demasiada luz como para subir ahí sin ser visto.\n\n[POR4_11:PORN4]\n~g~Vuelve a la escalera si necesitas acceder de nuevo a los tejados.\n\n[POR4_05:PORN4]\n~g~Estas escaleras llevan a una oficina en el piso inferior.\n\n[POR_AS1:PORN4]\nESTUDIO CINEMATOGRÁFICO CONSOLIDADO\n\n[POR_AS2:PORN4]\n~g~Inter Global Films generará ahora unos ingresos máximos de hasta ~1~ $. Asegúrate que lo recaudas de forma regular.\n\n{=================================== MISSION TABLE PROT1 ===================================}\n\n[PRO1_B:PROT1]\nNo puedo soportar este look. Tommy, ¿Tú que dices? ¿Qué te parece si ponemos un bar en...\n\n[PRO1_D:PROT1]\nEscúchame,\n\n[PRO1_E:PROT1]\nEs hora de tomar esta ciudad. Está ahí, esperándonos.\n\n[PRO1_F:PROT1]\nNecesitamos empezar a ampliar nuestro territorio,\n\n[PRO1_G:PROT1]\nvamos a dejar que Vice City sepa que somos los nuevos tíos importantes de la ciudad, ¿sabes a lo que me refiero?\n\n[PRO1_I:PROT1]\nLo que necesitas es un frente legítimo, Tommy, una verdadera propiedad. A mí nunca me ha hecho daño.\n\n[PRO1_J:PROT1]\nNecesitamos empezar a utilizar la fuerza o podemos despedirnos de todo el trabajo duro que hemos hecho.\n\n[PRO1_K:PROT1]\n¡Los negociantes locales saben que Díaz está muerto, y se niegan a pagar la protección!\n\n[PRO1_L:PROT1]\nOh. Podríamos intentar el soborno...\n\n[PRO1_M:PROT1]\n¿Soborno? ¡Que le jodan al soborno! Te mostraré cómo hacer que se asusten.\n\n[PRO1_01:PROT1]\n~g~Ve a atracar los escaparates de las tiendas y tendrás a los propietarios suplicando protección.\n\n[PRO1_03:PROT1]\n~r~Se suponía que deberías atacar y salir corriendo, no atacar y tomarte un café.\n\n[PRO1_04:PROT1]\n¡Mi sustento, destruido!\n\n[PRO1_05:PROT1]\n¡Arruinado... ESTOY ARRUINADO!\n\n[PRO1_06:PROT1]\n¡Pagaré lo que sea por protección!\n\n[PRO1_07:PROT1]\n¡Mi hermoso escaparate destruido!\n\n[PRO1_08:PROT1]\nMi tienda. Mi maravillosa tienda.\n\n[PRO1_09:PROT1]\nVercetti. Recuerda el nombre.\n\n[PRO1_10:PROT1]\nAhora dirijo esta ciudad. ¡YO!\n\n[BUYP1:PROT1]\nAhora puedes comprar propiedades en ciertas zonas de la ciudad.\n\n[BUYP2:PROT1]\nSi ves un indicador con una casa verde, puedes comprar esa propiedad.\n\n[PRO1_N:PROT1]\nVolveré aquí en cinco minutos...\n\n[PRO1_11:PROT1]\n~g~Ve al ~y~Centro Comercial North Point~g~ en ~y~Vice Point~g~.\n\n[PRO1_12:PROT1]\n~g~Destroza los escaparates de todas las tiendas y los propietarios te suplicarán para obtener nueva protección.\n\n[PRO1_A:PROT1]\nOh, tenemos que volver a pintar este sitio. Tenemos que hacer que parezca más viejo.\n\n[PRO1_C:PROT1]\nRosenberg, eres mi abogado, no mi diseñador de interiores, ¿lo entiendes?\n\n[BUYP3:PROT1]\nSitúate en el marcador, a continuación pulsa ~h~~k~~PED_ANSWER_PHONE~~w~ para comprar la propiedad.\n\n[PRO1_13:PROT1]\n~g~Dispones de cinco minutos para machacarlos a todos.\n\n{=================================== MISSION TABLE PROT2 ===================================}\n\n[PRO2_A:PROT2]\n¿Cuál es el problema?\n\n[PRO2_B:PROT2]\nUn bar se niega a pagar.\n\n[PRO2_C:PROT2]\nCreen que están protegidos por una banda de matones locales.\n\n[PRO2_D:PROT2]\nPero no te preocupes, Tommy, yo me encargo.\n\n[PRO2_E:PROT2]\n¿Llamas a esto encargarte?\n\n[PRO2_F:PROT2]\nVosotros dos, en pie...\n\n[PRO2_G:PROT2]\nVamos.\n\n[PRO2_01:PROT2]\n~g~Elimina a los guardias que vigilan el Bar Front Page y descubre quién los ha puesto ahí.\n\n[PRO2_10:PROT2]\n~g~Dos más han huido. Sígueles la pista y acaba con ellos.\n\n[PRO2_11:PROT2]\nSube al coche, inútil.\n\n[PRO2_02:PROT2]\nTu seguridad necesita un poco más de seguridad.\n\n[PRO2_03:PROT2]\n¡Ahh! demonios, ¡otra vez no! ¡no necesito esta basura!\n\n[PRO2_04:PROT2]\nEstos idiotas pertenecen al DBP de Seguridad que hay a la vuelta de la esquina.\n\n[PRO2_05:PROT2]\n¡Eh tíos! Arregladlo entre vosotros.\n\n[PRO2_06:PROT2]\nNos vemos en un rato.\n\n[PRO2_07:PROT2]\nSí, vale, lo que tú digas.\n\n[PRO2_08:PROT2]\n~g~El DBP de Seguridad sabrá que estás de camino, ve y atrápalos antes que escapen.\n\n[PRO2_09:PROT2]\n~g~Ve y habla con el dueño del bar Front Page.\n\n{=================================== MISSION TABLE PROT3 ===================================}\n\n[PRO3_A:PROT3]\n¡Idiota! ¿En qué estabas pensando?\n\n[PRO3_B:PROT3]\n¿Te das cuenta de lo que significa ésto?\n\n[PRO3_C:PROT3]\n¡Podríamos estar todos hundidos!\n\n[PRO3_D:PROT3]\nEl temporizador debe haberse jodido.\n\n[PRO3_E:PROT3]\nEse lugar estaba preparado para estallar como una fábrica de fuegos artificiales.\n\n[PRO3_F:PROT3]\nEntonces alguien avisó a la poli...\n\n[PRO3_G:PROT3]\n¿Cuál es el problema, colegas?\n\n[PRO3_H:PROT3]\nSe suponía que Mike iba a quemar algún sitio en el centro comercial,\n\n[PRO3_I:PROT3]\npero la cagó con los fusibles y ahora eso está plagado de polis.\n\n[PRO3_J:PROT3]\n¡Tenemos que conseguir nuestras cosas y salir de aquí!\n\n[PRO3_K:PROT3]\n¡Relajaos los dos, dejadme pensar un segundo!\n\n[PRO3_L:PROT3]\nTommy Vercetti no corta por lo sano y huye.\n\n[PRO3_M:PROT3]\nLos polis van a repasar ese edificio con un buen cepillo de dientes, ¿verdad?\n\n[PRO3_N:PROT3]\nPero eso lleva tiempo.\n\n[PRO3_O:PROT3]\nTenemos que ir y quemar nosotros mismos ese sitio.\n\n[PRO3_P:PROT3]\nSí, pero...\n\n[PRO3_Q:PROT3]\n¡Nadie excepto un poli podría acercarse a una milla de ese lugar!\n\n[PRO3_R:PROT3]\nAsí que iremos como polis.\n\n[PRO3_S:PROT3]\nTenemos que conseguir uniformes, y vamos a necesitar un coche patrulla.\n\n[PRO3_T:PROT3]\nTodo gracias a ti, Mike.\n\n[PRO3_U:PROT3]\nLo siento.\n\n[PRO3_V:PROT3]\nLo capto.\n\n[PRO3_W:PROT3]\nLo que tenemos que hacer es atraer a los polis enseñándoles el dedo,\n\n[PRO3_X:PROT3]\nencerrarles\n\n[PRO3_Y:PROT3]\ny asaltarles.\n\n[PRO3_Z:PROT3]\nBuen plan. ¡Vamos!\n\n[PRO3_A1:PROT3]\nDe acuerdo.\n\n[PRO3_01:PROT3]\nDe acuerdo, Lance, ¡vamos a por los polis!\n\n[PRO3_02:PROT3]\n~g~ Roba el coche de policía y coloca la bomba en el Café Tarbrush del centro comercial.\n\n[PRO3_03:PROT3]\n~g~ Has dejado atrás a Lance, vuelve y recógele.\n\n[PRO3_04:PROT3]\n~g~ Vamos.\n\n[PRO3_05:PROT3]\n~r~¡Has matado a Lance!\n\n[PRO3_07:PROT3]\n~g~ Te has descubierto. ¡Date prisa y coloca la bomba!\n\n[PRO3_08:PROT3]\n~g~Vuelve a la ~h~finca de Vercetti~g~ en ~h~Starfish Island~g~.\n\n[PRO3_09:PROT3]\n¡Átales y amordázales!\n\n[PRO3_10:PROT3]\n¡Me queda como un guante!\n\n[PRO3_11:PROT3]\nUn poco ajustado en la entrepierna...\n\n[PRO3_12:PROT3]\nOh, sí, sí, el mío también. El mío también.\n\n[PRO3_13:PROT3]\n¡Relájate, hermano! ¡Ningún poli conduce tan mal!\n\n[PRO3_14:PROT3]\nRecuerda, sonríe a los otros polis.\n\n[PRO3_15:PROT3]\nHola, agente. Bonita placa, bonita placa.\n\n[PRO3_16:PROT3]\nMuy desenvuelto, Lance.\n\n[PRO3_17:PROT3]\nDe acuerdo, los temporizadores están colocados, 5 segundos.\n\n[PRO3_18:PROT3]\n¿5 segundos? ¡Tenemos que salir de aquí pitando!\n\n[PRO3_19:PROT3]\nAhora que los hemos enfadado de verdad.\n\n[PRO3_20:PROT3]\n~g~ Haz que dos polis te sigan hasta el garaje.\n\n[PRO3_21:PROT3]\n~g~Consigue un nivel de se busca suficiente para que los polis te sigan hasta el garaje.\n\n[PRO3_22:PROT3]\n~g~¡La puerta del garaje está bloqueada! El acceso tiene que estar despejado para que se pueda cerrar.\n\n[PRO3_23:PROT3]\n~g~Camina hacia el marcador para colocar la bomba.\n\n[PRO3_24:PROT3]\n~g~¡Aléjate del Café!\n\n[PRO_AS1:PROT3]\nANILLO DE PROTECCIÓN COMPLETADO\n\n[PRO_AS2:PROT3]\n~g~La finca de Vercetti generará ahora unos ingresos máximos de hasta ~1~ $. Asegúrate de recaudarlo regularmente.\n\n{=================================== MISSION TABLE RACES ===================================}\n\n[RACES_2:RACES]\n~g~¡Necesitas un vehículo para correr, esto no es una carrera a pie!\n\n[RACES_3:RACES]\n3... 2... 1... ¡ADELANTE! ¡ADELANTE! ¡ADELANTE!\n\n[RACES_8:RACES]\n~r~¡No has ganado la carrera!\n\n[RACES00:RACES]\nCarrera ~1~:\n\n[RACES01:RACES]\nVelocidad terminal\n\n[RACES02:RACES]\nOcean Drive\n\n[RACES03:RACES]\nCarrera por el borde\n\n[RACES04:RACES]\nCapital Cruise\n\n[RACES05:RACES]\n¡Tour!\n\n[RACES06:RACES]\nAguante en V.C.\n\n[RACES07:RACES]\nPrecio de entrada: ~1~ $\n\n[RACES08:RACES]\nMejor tiempo: ~1~:~1~\n\n[RACES09:RACES]\nMejor resultado: 1\n\n[RACES10:RACES]\nMejor resultado: 2\n\n[RACES11:RACES]\nMejor resultado: 3\n\n[RACES12:RACES]\nMejor resultado: 4\n\n[RACES13:RACES]\nLongitud de pista: ~1~.~1~ km\n\n[RACES15:RACES]\nMejor tiempo: NA\n\n[RACES16:RACES]\nMejor resultado: NA\n\n[RACES19:RACES]\nNo puedes permitirte entrar en esta carrera.\n\n[RACES22:RACES]\nMejor tiempo: ~1~:0~1~\n\n[RACES23:RACES]\nLongitud de la pista: ~1~.~1~ millas\n\n[RACES_1:RACES]\n~g~Consigue un vehículo rápido y ve a la parrilla de salida.\n\n[RACEHLP:RACES]\n~w~Pulsa ~h~~k~~PED_SPRINT~~w~ para empezar la carrera seleccionada. Pulsa ~h~~k~~VEHICLE_ENTER_EXIT~~w~ para salir.\n\n{=================================== MISSION TABLE RCHELI1 ===================================}\n\n[WRECKED:RCHELI1]\n~r~¡El vehículo está destrozado!\n\n[RCH1_4:RCHELI1]\nPuntos de control:\n\n[RCH1_7:RCHELI1]\n~g~Hay 20 puntos de control en total.\n\n[RCH1_12:RCHELI1]\n~g~¡El helicóptero RC está saliendo fuera de su alcance de control!\n\n[RCH1_13:RCHELI1]\n~r~¡El helicóptero RC se ha salido de su radio de alcance!\n\n[RCH1_8:RCHELI1] { reVC update }\n~g~Si deseas abandonar esta misión, pulsa ~h~~k~~VEHICLE_FIREWEAPON~~g~ para detonar tu helicóptero RC.\n\n{=================================== MISSION TABLE RCPLNE1 ===================================}\n\n[RCPL1_4:RCPLNE1]\n~g~Compite en una CARRERA DE PUNTOS DE CONTROL contra otros tres aviones RC.\n\n[RCPL1_5:RCPLNE1]\n~g~Vuela a través de los puntos de control dispersados por Vice City.\n\n[RCPL1_6:RCPLNE1] { reVC update }\n~g~Si deseas abandonar esta misión, pulsa ~h~~k~~VEHICLE_FIREWEAPON~~g~ para detonar tu avión RC.\n\n[RCPL1_8:RCPLNE1]\n~g~¡Tu avión RC está saliendo fuera del alcance!\n\n[RCPL1_9:RCPLNE1]\n~r~¡Tu avión RC se salió del alcance!\n\n{=================================== MISSION TABLE RCRACE1 ===================================}\n\n[RCRC1_1:RCRACE1]\n~g~Compite en una CARRERA DE PUNTOS DE CONTROL contra 3 Barón RC durante dos vueltas.\n\n[RCRC1_3:RCRACE1]\n~g~¡Vuelta final!\n\n[RCR1_4:RCRACE1]\nvueltas restantes:\n\n[RCR1_1:RCRACE1]\n~g~Compite en una carrera de puntos de control contra otros tres coches RC.\n\n[RCR1_2:RCRACE1]\n~g~¡Consigue ser el primero en completar las dos vueltas del circuito para ganar!\n\n[RCR1_6:RCRACE1]\n~g~¡Tu coche RC se está saliendo fuera del alcance!\n\n[RCR1_7:RCRACE1]\n~r~¡Tu coche RC se salió del alcance!\n\n{=================================== MISSION TABLE ROCK1 ===================================}\n\n[RBM1_A:ROCK1]\n~n~\n\n[RBM1_B:ROCK1]\n¡Brillante, jodidamente brillante!\n\n[RBM1_D:ROCK1]\n¿Eh, habías conocido antes a los Love Fist?\n\n[RBM1_E:ROCK1]\nNo, pero siempre me encantó vuestra música.\n\n[RBM1_F:ROCK1]\nDéjame presentarte a la banda.\n\n[RBM1_G:ROCK1]\nEstos son P, Percy, Dick, y Willy está en el kaze, y ese de antes de la cabina era Jezz,\n\n[RBM1_H:ROCK1]\ny tíos, quiero que conozcáis a un buen amigo mío.\n\n[RBM1_I:ROCK1]\nEste es Tommy. Nos conocemos desde hace mucho.\n\n[RBM1_J:ROCK1]\nDe acuerdo, colega.\n\n[RBM1_K:ROCK1]\nY, eh, ¿cuál era tu nombre?\n\n[RBM1_L:ROCK1]\nDéjalo, Jezz, lo recuerdas,\n\n[RBM1_M:ROCK1]\nno juegues a eso conmigo, colega,\n\n[RBM1_N:ROCK1]\n¡soy demasiado astuto para eso, encanto!\n\n[RBM1_O:ROCK1]\nVerás, Tom, la cosa es que los chicos necesitan algo de ayuda.\n\n[RBM1_P:ROCK1]\nNo tienen muchos contactos en la zona, gente a la que preguntarle ''¿vienes mucho por aquí?'' y todo eso.\n\n[RBM1_Q:ROCK1]\n¡Necesitamos unos tiritos, colega!\n\n[RBM1_R:ROCK1]\n¿Vamos a pillar la vieja furia Love Fist, sabes?\n\n[RBM1_S:ROCK1]\nBueno, esto es Vice City, tío. ¿Cuál es el problema?\n\n[RBM1_U:ROCK1]\n¡Love juice, tío!\n\n[RBM1_V:ROCK1]\n¿Love juice?\n\n[RBM1_W:ROCK1]\nSí, dos partes de boomshine, una parte de farlopa, cinco caramelos con picapica y un litro de gasolina.\n\n[RBM1_X:ROCK1]\n¿Puedes ayudarnos, colega?\n\n[RBM1_Y:ROCK1]\nDe verdad significaría mucho para los chicos.\n\n[RBM1_Z:ROCK1]\nPuedes hacer eso por los muchachos, ¿verdad?\n\n[RBM1_7:ROCK1]\n~r~¡No conseguiste a tiempo el ''love juice''!\n\n[RBM1_8:ROCK1]\n~r~¡Mercedes está muerta!\n\n[RBM1_10:ROCK1]\n~r~¡Idiota! ¡Has destruido el material!\n\n[RBM1_13:ROCK1]\n~g~Lleva el ''love juice'' y a Mercedes a la banda antes de que sean requeridos en el escenario.\n\n[RBM1_15:ROCK1]\n~r~¡Has perdido al camello, nuestra pasta y la nieve!\n\n[RBM1_17:ROCK1]\n~g~¡Mata al camello y consigue los ingredientes!\n\n[MOB_07A:ROCK1]\nEh colega, a los chicos les vendría bien algo de compañía, si entiendes lo que quiero decir...\n\n[MOB_07B:ROCK1]\nConozco a la chica apropiada.\n\n[ROK1_5:ROCK1]\n¡Hola, Mercedes!\n\n[ROK1_6:ROCK1]\nHola, Tommy. ¿Cómo estás?\n\n[ROK1_7:ROCK1]\nBien. Escucha, ¿te apetece acostarte con los Love Fist?\n\n[ROK1_8:ROCK1]\nDe acuerdo, pero sólo como un favor que espero que me sea devuelto...\n\n[RBM1_14:ROCK1]\n~g~¡Necesitas un coche o una moto!\n\n[RBM1_1:ROCK1]\n~g~Ve y recoge a Mercedes en su apartamento.\n\n[RBM1_12:ROCK1]\n~g~Ve y reúnete con el camello para conseguir los ingredientes del ''love juice''.\n\n[ROK1_2:ROCK1]\nYA NO ES NECESARIO\n\n[ROK1_3:ROCK1]\nYA NO ES NECESARIO\n\n[MERC_39:ROCK1]\nHasta luego grandullón.\n\n[RBM1_C:ROCK1]\n¡Eh, Tommy! Me alegro que pudieras venir.\n\n[RBM1_9:ROCK1]\n~g~¡Ve y reúnete con el camello de los Love Fist para conseguir algo de ''love juice''!\n\n[ROK1_1A:ROCK1]\n¿Buscas algo especial? ¡Yo tengo lo que necesitas!\n\n[ROK1_9:ROCK1]\n¡Gracias por el dinero, mamón!\n\n[RBM1_T:ROCK1]\nNecesitamos ''love juice'', tío, ¿sabes?\n\n{=================================== MISSION TABLE ROCK2 ===================================}\n\n[RBM2_A:ROCK2]\nTommy, tío. ¡Me alegro de verte!\n\n[RBM2_B:ROCK2]\n¿Qué sucede?\n\n[RBM2_C:ROCK2]\nMalas vibraciones, Tommy...\n\n[RBM2_E:ROCK2]\nHay un tipo, apenas le conocemos, pero él nos conoce a nosotros.\n\n[RBM2_F:ROCK2]\nComo este tipo, que lo sabe todo de nosotros.\n\n[RBM2_G:ROCK2]\nSabe que a Willy le gusta ponerse ropa interior de mujeres.\n\n[RBM2_H:ROCK2]\n¡O que a Percy le gusta Duran Duran!\n\n[RBM2_K:ROCK2]\nSí, bien, tu cohete del amor. Pero escucha, este tipo...\n\n[RBM2_L:ROCK2]\nEl tipo, quiere ver a los Love Fist muertos.\n\n[RBM2_M:ROCK2]\nMuertos, Tommy.\n\n[RBM2_N:ROCK2]\nEl final Love Fist. Ya sabes lo que dicen, los buenos mueren jóvenes.\n\n[RBM2_O:ROCK2]\n¡Pero Tommy, tienes que salvar a los Love Fist!\n\n[RBM2_P:ROCK2]\nTenemos que firmar en dos horas y creo...\n\n[RBM2_Q:ROCK2]\nLos chicos creen que el sospechoso va a intentar hacer algún recibimiento infame.\n\n[RBM2_1:ROCK2]\n~g~Conduce la limusina a la firma de autógrafos e intenta encontrar al psicópata.\n\n[RBM2_2:ROCK2]\n~r~¡Destrozaste el coche de la banda!\n\n[RBM2_3:ROCK2]\n~g~¡Ve a la firma de autógrafos!\n\n[RBM2_4:ROCK2]\n~g~¡Atrapa al psicópata! ¡No le dejes escapar!\n\n[RBM2_5:ROCK2]\n~r~¡Lo perdiste, idiota!\n\n[RBM2_7:ROCK2]\n~r~¡Los fans han sido atacados, el psicópata no aparecerá!\n\n[RBM2_8:ROCK2]\n~r~¡Los guardas de seguridad han sido atacados, el psicópata no aparecerá!\n\n[PSYCH_1:ROCK2]\n¡Me encantaría ver arder a los Love Fist!\n\n[PSYCH_2:ROCK2]\n¡Los Love Fist arruinaron mi vida!\n\n[RBM2_I:ROCK2]\nCállate, idiota. Sólo porque Jezz se folla ovejas.\n\n[RBM2_R:ROCK2]\n¡Eh, cierra la boca!\n\n[RBM2_D:ROCK2]\nSí, no estoy de broma, es un tema muy gordo tío, muy gordo, ¿sabes?\n\n[RBM2_J:ROCK2]\nEs lo que atrae a mi cohete del amor, ¿entiendes?\n\n{=================================== MISSION TABLE ROCK3 ===================================}\n\n[RBM3_A:ROCK3]\n¡Tommy! ¡Tommy! ¡Tommy, tío, ese psicópata ha vuelto!\n\n[RBM3_B:ROCK3]\n¿Qué está pasando?\n\n[RBM3_C:ROCK3]\n¡Ese psicópata no dejará en paz a los Love Fist!\n\n[RBM3_D:ROCK3]\nNo le mataste, tío. Y ahora ha vuelto.\n\n[RBM3_E:ROCK3]\nSí, sí, sí, y la cuestión es...\n\n[RBM3_F:ROCK3]\nLa cuestión es que necesitamos alguien en quien poder confiar para que conduzca la limo,\n\n[RBM3_G:ROCK3]\n¡porque ese chiflado sigue con las amenazas!\n\n[RBM3_I:ROCK3]\nAquí estamos todos acojonados, tío.\n\n[RBM3_J:ROCK3]\nDe acuerdo tíos, calmaos, yo me encargaré de esto.\n\n[RBM3_K:ROCK3]\nNormalmente, no me ocuparía de ir por ahí haciendo de chófer para una panda de bisexuales escoceses bebidos,\n\n[RBM3_L:ROCK3]\npero, en vuestro caso, haré una excepción.\n\n[RBM3_4:ROCK3]\n~r~¡Has matado a los Love Fist!\n\n[RBM3_6:ROCK3]\nDETONACIÓN:\n\n[RBM3_1:ROCK3]\n~g~Conduce a los Love Fist al local del concierto.\n\n[RBM3_2:ROCK3]\nSi intentas abandonar el coche mientras la bomba está armada explotará...\n\n[RBM3_3:ROCK3]\nSi la barra de detonación se llena completamente la bomba explotará.\n\n[RBM3_8:ROCK3]\nCuanto más rápido conduzcas más despacio se moverá la barra de detonación.\n\n[RBM3_7:ROCK3]\n~g~¡BOMBA DESACTIVADA!\n\n[ROK3_62:ROCK3]\ny pensamos que podríamos enseñarte nuestro Templo del Rock.\n\n[ROK3_63:ROCK3]\n¡Para que te vayas acostumbrando a la furia de Love Fist!\n\n[ROK3_64:ROCK3]\nEscúchate a ti mismo, tío. Es papel maché y cinta aislante.\n\n[ROK3_65:ROCK3]\nEh, para los chavales, ¡esto es un templo y nosotros somos los sacerdotes!\n\n[ROK3_66:ROCK3]\nSi, vale, si a los chavales les gustan los sacerdotes colgados y sin oído musical,\n\n[ROK3_67:ROCK3]\n¿quién soy yo para discutirlo?\n\n[ROK3_68:ROCK3]\nVaya por Dios, se está comiendo la cinta otra vez.\n\n[ROK3_69:ROCK3]\nCon este ritmo tendremos que tocar en directo.\n\n[ROK3_70:ROCK3]\nOohh ¡mierda! Mis tripas...\n\n[ROK3_73:ROCK3]\nJezz está escuchando la cinta,\n\n[RBM3_9:ROCK3]\nSi te paran o reduces la velocidad la barra de detonación aumentará.\n\n[RBM3_H:ROCK3]\n¡Me estoy cagando de miedo tío. Necesito a mi, mamá!\n\n[ROK3_71:ROCK3]\nTenemos que seguir con esto. Gracias de nuevo Tommy, ya sabes lo que quiero decir, apúntate una, ¡adiós!\n\n[ROK3_1:ROCK3]\nAl fin tío, hora de un merecido trago. La sala de conciertos está solo a unos cientos de metros calle abajo.\n\n[ROK3_2:ROCK3]\nMejor ponme uno doble. Eh Tommy, cambia los temas, tío.\n\n[ROK3_3:ROCK3]\nMe siento perdido si la cabeza no me estalla. Ah, mira, ¿Qué es esto? Eh Tommy, pon esta cinta.\n\n[ROK3_4:ROCK3]\nLove Fist. Vuestro tiempo contaminando las ondas se ha terminado. Os di la oportunidad de ser amigos.\n\n[ROK3_5:ROCK3]\nAhora os doy la oportunidad de morir. ¡Intentad aminorar la marcha y vuestra limusina explotará junto con vuestros GRANDES Y PELUDOS CULOS!\n\n[ROK3_6:ROCK3]\nTommy amigo, ¡tienes que salvar a la banda! Yo me estoy cansando de esto. ¡Mantén pisado el acelerador!\n\n[ROK3_7:ROCK3]\n¡Tenemos que encontrar la bomba! ¿Podremos conducir por ahí todo el día? Sí, tenemos suficiente bebida..\n\n[ROK3_8:ROCK3]\n¿La bomba no estará en el motor? Tendremos que parar y cogerla. ¡Vamos a morir todos! ¡Me voy a emborrachar!\n\n[ROK3_9:ROCK3]\nEh, ¡amigo, aquí hay cola! ¡La respuesta no está en el mueble bar! ¡Sal de mi camino!\n\n[ROK3_10:ROCK3]\nEh, ¡a la botella de vodka le salen unos cables! ¡Eso no es vodka!, ¡Eso es una BOMBA!\n\n[ROK3_11:ROCK3]\n¡Y está preparada para explotar!\n\n[ROK3_12:ROCK3]\nSiempre me dijeron que la bebida acabaría conmigo. He visto esto en la tele. Tienes que tirar de uno de los cables. ¿De qué cable? Pues no sé tío.\n\n[ROK3_13:ROCK3]\nNo tengo ni idea. Willy, di algo. Voy a tocar el bajo en el otro mundo.\n\n[ROK3_14:ROCK3]\nTommy tío, sigue conduciendo deprisa, amigo. Que alguien haga algo. Si, ¡qué listo!\n\n[ROK3_15:ROCK3]\n''Que alguien haga algo'', qué mierda es esa, he visto a niñas con más valor. Tipo duro, haz tú algo.\n\n[ROK3_16:ROCK3]\nMira tío, yo toco un instrumento y no tengo ni idea de desactivar bombas. Willy podrías beberte el líquido de la bomba con una pajita.\n\n[ROK3_17:ROCK3]\nSí, he oído que eres bueno en ese tipo de cosas. ¡Eh, aquella noche estaba muy colgado, como bien sabes!\n\n[ROK3_18:ROCK3]\n¡Anda pásale una pajita a Willy! ¿Una pajita? ¡Este es el autobús de la gira de los Love Fist!\n\n[ROK3_19:ROCK3]\n¿De dónde voy a sacar yo una pajita? ¿me entiendes? ¿Qué cable Tommy? El verde. No hay ninguno verde.\n\n[ROK3_20:ROCK3]\n¿O es que este es verde? ¿Te parece verde alguno de estos cables?\n\n[ROK3_21:ROCK3]\n¡Oh no! ¡La muerte está en las cartas! ¡Todo parece verde! Tenía que haberos dejado tirados cuando tuve la oportunidad.\n\n[ROK3_22:ROCK3]\nBuscador de gloria. Capitalista. He estado tirando de ti durante años. Cállate. Eres un espantajo.\n\n[ROK3_23:ROCK3]\nUna nena grande y chillona. Sí. Cállate y tira del cable. ¿Qué cable? Este...\n\n[ROK3_24:ROCK3]\n¡NO, tío! estamos bien. ¡No hemos saltado por los aires, amigo.\n\n[ROK3_25:ROCK3]\nTommy, tío, chachi. Rock and roll, tío. ¿No tenemos que actuar?\n\n[ROK3_26:ROCK3]\n¿Meter bulla? ¿Abusar de las fans? ¡LOVE FIST!\n\n[ROK3_27:ROCK3]\n¿Has terminado con esa botella?\n\n{=================================== MISSION TABLE SERG1 ===================================}\n\n[TEX1_A:SERG1]\nEntra y disfruta de los asientos de cuero, hijo.\n\n[TEX1_B:SERG1]\nDemonios, mi padre solía decir, a caballo regalado no le mires el diente, y por Dios que nunca lo hizo.\n\n[TEX1_C:SERG1]\n¿Te gustaría un trago del viejo Kentucky?\n\n[TEX1_D:SERG1]\nNo gracias.\n\n[TEX1_E:SERG1]\nAlguien con la mente despejada, me gusta eso.\n\n[TEX1_F:SERG1]\nEl negocio de la propiedad no se trata solo de papeleo pretencioso.\n\n[TEX1_G:SERG1]\n¡Se trata de tierra! ¡Y el derecho a reclamarla! ¿Me sigues, hijo?\n\n[TEX1_H:SERG1]\nSí.\n\n[TEX1_J:SERG1]\nY yo creo que eres la clase de tío para persuadirle.\n\n[TEX1_K:SERG1]\nLa persuasión es mi fuerte.\n\n[TEX1_L:SERG1]\nSí, estará en el club de campo, en el campo de golf.\n\n[TEX1_M:SERG1]\nAllí no permiten armas, así que sus guardaespaldas no llevarán protección.\n\n[TEX1_N:SERG1]\nVe y dale una paliza inolvidable.\n\n[TEX1_O:SERG1]\nBien, toma... te he conseguido un carné de socio, y chico, vas a necesitar un tipo de ropa más apropiada.\n\n[TEX1_2:SERG1]\n~g~Ahora ve al Club de golf Leaf Links.\n\n[TEX1_0:SERG1]\n~g~El objetivo está en el campo de prácticas disfrutando de una partida de golf. ¡Asegúrate de que sea la última!\n\n[TEX1_3:SERG1]\n¿Quién es este tipo? Chicos, ocuparos de él.\n\n[TEX1_6:SERG1]\n¡Bonito culo nena!\n\n[TEX1_7:SERG1]\n¿Este soy yo?\n\n[TEX1_I:SERG1]\nBueno, necesito algún cabrón obstinado que suelte algo de mierda.\n\n[TEX1_8:SERG1]\nCada vez que subas a un Caddy recibirás automáticamente un palo de golf, siempre que la ranura de armas blancas esté vacía.\n\n[TEX1_9:SERG1]\n¡Atrapadle!\n\n[TEX1_10:SERG1]\n¡Mata a ese psicópata!\n\n[TEX1_1:SERG1]\n~g~Ve y consigue ropa de golf en Jocksports.\n\n{=================================== MISSION TABLE SERG2 ===================================}\n\n[TEX_2A:SERG2]\n~g~¡Excelente! ¡Te han visto!\n\n[TEX_2B:SERG2]\n~r~¡Idiota! ¡La gente debe PRESENCIAR a un cubano haciendo el trabajito!\n\n[TEX_2C:SERG2]\n~g~¡Ve y consígue algo con los colores de la banda cubana en Little Havana!\n\n[TEX_2D:SERG2]\n~g~¡Ahora elimina al capo de la banda haitiana en la Funeraria de Romero!\n\n[TEX2_A:SERG2]\nTommy, este es Donald Love. Donald, te presento a Tommy Vercetti,\n\n[TEX2_B:SERG2]\nel último tirador más rápido en llegar a estos lares.\n\n[TEX2_C:SERG2]\nSi... eh...\n\n[TEX2_D:SERG2]\nDonald, ahora cállate y escucha, puede que aprendas algo.\n\n[TEX2_E:SERG2]\nVeamos. Nada hace que los precios de las propiedades bajen más rápido que una guerra entre bandas al viejo estilo.\n\n[TEX2_F:SERG2]\nExcepto un desastre quizás, como la peste de la que habla la biblia o algo así,\n\n[TEX2_G:SERG2]\naunque puede que en este caso vayamos demasiado lejos.\n\n[TEX2_H:SERG2]\n¿Te estás enterando, capullo cuatro ojos?\n\n[TEX2_I:SERG2]\nHace poco murió un capo de una banda haitiana. Al parecer lo hicieron los cubanos, nadie lo sabe.\n\n[TEX2_J:SERG2]\n¡Pero se lo haremos saber! Disfrázate de cubano\n\n[TEX2_K:SERG2]\ny ve a reventar el funeral. Crea confusión y después le sigues bien de cerca.\n\n[TEX2_L:SERG2]\n¿Te estás enterando, Donald?\n\n[TEX2_M:SERG2]\nEso debería meter al zorro en el gallinero. ¿Eh?\n\n[TEX2_N:SERG2]\ny ahora sólo tenemos que sentarnos a esperar y ver cómo caen los precios.\n\n[TEXEXIT:SERG2]\n~g~¡Lárgate de Little Haiti ahora!\n\n{=================================== MISSION TABLE SERG3 ===================================}\n\n[TEX3_A:SERG3]\nBien, mira, hijo. Tengo un problema y creo que podrías ayudarme con él.\n\n[TEX3_B:SERG3]\nNo soy constructor.\n\n[TEX3_C:SERG3]\nNo, estaba pensando más bien en tus habilidades para la demolición.\n\n[TEX3_D:SERG3]\nBien, esto de aquí es el centro empresarial tal y como se ha planeado, y éste\n\n[TEX3_E:SERG3]\nes el solar que estamos buscando.\n\n[TEX3_F:SERG3]\nIntentas decir que este nuevo bloque de oficinas está en medio.\n\n[TEX3_G:SERG3]\nLo captas rápido.\n\n[TEX3_H:SERG3]\nBien, voy a irme de esta ciudad durante un tiempo\n\n[TEX3_I:SERG3]\ny si ese centro de oficinas se enfrentase a problemas estructurales repentinos e insalvables, entonces yo...\n\n[TEX3_J:SERG3]\n¿Como buen ciudadano se sentirá obligado a intervenir y\n\n[TEX3_K:SERG3]\nsalvar la remodelación de una zona tan importante de la ciudad?\n\n[TEX3_L:SERG3]\n¿Dónde puedo conseguir más tipos como tú?\n\n[TEX3_1:SERG3]\n~g~Utiliza el helicóptero RC para transportar las bombas a los cuatro objetivos del edificio que debes demoler.\n\n[TEX3_2:SERG3]\n~g~Debes colocar una bomba en cada objetivo. Puedes colocarlas en cualquier orden.\n\n[TEX3_3:SERG3]\n~g~Para recoger una bomba, dirige el helicóptero RC hasta a ella. Solo puedes llevar las bombas de una en una.\n\n[TEX3_4:SERG3] { reVC update }\n~g~Para soltar una bomba pulsa ~h~~k~~VEHICLE_FIREWEAPON~~g~.\n\n[TEX3_5:SERG3]\n~g~Si fallas al colocar una bomba podrás recogerla e intentarlo de nuevo.\n\n[TEX3_6:SERG3]\n~g~Cuando hayas recogido una bomba por primera vez, el temporizador de detonación se pondrá en marcha.\n\n[TEX3_7:SERG3]\n~g~¡A continuación deberás conseguir colocar el resto de las bombas en 7 minutos!\n\n[TEX3_8:SERG3]\n~g~¡Has fallado en el objetivo! ¡Recoge la bomba e inténtalo de nuevo!\n\n[TEX3_10:SERG3]\n~g~Suelta la bomba en el objetivo.\n\n[TEX3_11:SERG3]\nobjetivos restantes:\n\n[TEX3_17:SERG3]\n~r~¡Te has quedado sin tiempo!\n\n[TEX3_18:SERG3]\n~r~¡Tu helicóptero RC ha sido destruido!\n\n[TEX3_19:SERG3]\n~r~¡Has lanzado la bomba en el agua! ¡Esa no es manera de pescar!\n\n[TEX3_20:SERG3]\n~g~¡Tu Helicóptero RC está casi fuera del alcance del control remoto!\n\n[TEX3_21:SERG3]\n~r~¡Tu Helicóptero RC está fuera del alcance del control remoto!\n\n[TEX3_24:SERG3]\nPulsa ~h~~k~~VEHICLE_LOOKLEFT~ ~w~para girar el helicóptero en sentido contrario a las agujas del reloj.\n\n[TEX3_25:SERG3]\nPulsa ~h~~k~~VEHICLE_LOOKLEFT~ ~w~para girar el helicóptero en sentido de las agujas del reloj.\n\n[TEX3_27:SERG3]\n~g~Una escalera central permite el acceso a todas las plantas del edificio.\n\n[TEX3_31:SERG3]\n~r~¡Has destruido la furgoneta de TOPFUN que tenía las bombas y el helicóptero RC!\n\n[TEX3_32:SERG3]\nPuedes ~h~mirar atrás~w~ si ~h~pulsas simultáneamente ~k~~VEHICLE_LOOKLEFT~ y ~k~~VEHICLE_LOOKRIGHT~~w~.\n\n[TEX3_29:SERG3] { reVC update }\n~g~Para soltar una bomba pulsa ~h~~k~~VEHICLE_FIREWEAPON~~g~.\n\n[TEX3_26:SERG3]\nPulsa ~h~~k~~VEHICLE_BRAKE~~w~ para disminuir la velocidad del rotor y ~h~descender~w~.\n\n[TEX3_22:SERG3]\nPulsa ~h~~k~~VEHICLE_ACCELERATE~~w~ para aumentar la velocidad del rotor y así ~h~ascender~w~.\n\n[TEX3_16:SERG3]\n~g~Ve a la furgoneta ~w~TOPFUN ~g~cercana al solar de construcción que se va a demoler.\n\n[TEX3_33:SERG3]\nUna vez que recojas una bomba el radar te mostrará la posición del objetivo con relación al helicóptero RC.\n\n[TEX3_34:SERG3]\nUn ~h~icono triangular apuntando hacia arriba ~w~indica que el objetivo está ~h~por encima ~w~del helicóptero RC.\n\n[TEX3_35:SERG3]\nUn ~h~icono triangular apuntando hacia abajo ~w~indica que el objetivo está ~h~por debajo ~w~del helicóptero RC.\n\n[TEX3_36:SERG3]\nUn ~h~icono cuadrado ~w~indica que el objetivo está al ~h~mismo nivel ~w~que el helicóptero RC.\n\n[TEX3_28:SERG3]\nPara ~h~recoger una bomba~w~, simplemente dirige el helicóptero RC hasta ella. El helicóptero RC sólo puede transportar una bomba.\n\n[TEX3_30:SERG3]\n~g~Para recoger una bomba, simplemente dirige el helicóptero RC hasta ella. El helicóptero RC sólo puede transportar una bomba.\n\n[TEX3_12:SERG3]\n~g~¡Bomba colocada! ¡Quedan 3 objetivos más! Vuelve a por otra bomba.\n\n[TEX3_13:SERG3]\n~g~¡Bomba colocada! ¡Quedan 2 objetivos más! Vuelve a por otra bomba.\n\n[TEX3_14:SERG3]\n~g~¡Bomba colocada! ¡Queda 1 objetivo más! Vuelve a por otra bomba.\n\n[TEX3_15:SERG3]\n~r~¡El temporizador de detonación se ha puesto en marcha! ~g~Debes colocar las ~w~4 bombas ~g~en el tiempo restante!\n\n[TEX3_37:SERG3]\nSi empujas ~h~el joystick analógico derecho hacia atrás~w~, aumentarás la velocidad del rotor y así ~h~ascenderá~w~.\n\n[TEX3_38:SERG3] { reVC update }\n{Pulsa ~h~~k~~VEHICLE_ACCELERATE~~w~ para aumentar la velocidad del rotor y así ~h~ascender~w~.}\nSi empujas ~h~el joystick analógico derecho hacia adelante ~w~la velocidad del rotor aumenta, haciendo que el helicóptero ~h~descienda.\n\n[TEX3_39:SERG3]\n~g~Para soltar una bomba pulsa ~h~~k~~VEHICLE_HANDBRAKE~~w~.\n\n[TEX3_40:SERG3]\n~g~Para soltar una bomba pulsa ~h~~k~~VEHICLE_HANDBRAKE~~w~.\n\n[TEX3_23:SERG3]\nPulsa ~h~~k~~VEHICLE_TURRETUP~~w~ y ~h~~k~~VEHICLE_TURRETDOWN~~w~ para inclinar el helicóptero en la dirección deseada.\n\n{=================================== MISSION TABLE TAXI1 ===================================}\n\n[FARES:TAXI1]\nCARRERAS:\n\n[TAXI1:TAXI1]\n~g~Busca un cliente.\n\n[TSCORE2:TAXI1]\n~1~ $\n\n[IN_ROW:TAXI1]\n~1~ ¡Racha de clientes! ~1~ $\n\n[TAXI3:TAXI1]\n~r~¡Tu pasajero huye aterrorizado!\n\n[TAXI7:TAXI1]\n~r~Tu coche está destrozado, haz que lo reparen.\n\n[TAXI4:TAXI1]\n¡Viaje completado!\n\n[TAXI5:TAXI1]\n¡VIAJE RÁPIDO!\n\n[TAXI6:TAXI1]\nMisión de taxista cancelada\n\n[TAXIH1:TAXI1]\nDetente cerca de un peatón que esté resaltado para recogerle y llevarle a su destino antes de que se agote el tiempo.\n\n[FARE1:TAXI1]\n~g~Destino ~w~''el club Pole Position'' ~g~en Ocean Beach.\n\n[FARE3:TAXI1]\n~g~Destino ~w~''el club náutico'' ~g~en Ocean Beach.\n\n[FARE4:TAXI1]\n~g~Destino ~w~''Ammu-Nation'' ~g~en Ocean Beach.\n\n[FARE5:TAXI1]\n~g~Destino ~w~''la ferretería'' ~g~en Washington Beach.\n\n[FARE6:TAXI1]\n~g~Destino ~w~''el centro comercial North Point'' ~g~en Vice Point.\n\n[MFARE1:TAXI1]\n~g~Destino ~w~''Ammu-Nation'' ~g~en el centro.\n\n[MFARE2:TAXI1]\n~g~Destino ~w~''la terminal'' ~g~en el aeropuerto Escobar International.\n\n[WFARE3:TAXI1]\n~g~Destino ~w~''Coches Sunshine'' ~g~en Little Havana.\n\n[WFARE4:TAXI1]\n~g~Destino ~w~''Taxis Kaufman'' ~g~en Little Haiti.\n\n[WFARE5:TAXI1]\n~g~Destino ~w~''la ferretería'' ~g~en Little Havana.\n\n[WFARE6:TAXI1]\n~g~Destino ~w~''Emporio Howlin Petes Bike'' ~g~en el centro.\n\n[FARE7:TAXI1]\n~g~Destino ~w~''la joyería'' ~g~en Vice Point.\n\n[FARE8:TAXI1]\n~g~Destino ~w~''la playa'' ~g~en Ocean Beach.\n\n[FARE9:TAXI1]\n~g~Destino ~w~''la playa'' ~g~en Washington Beach.\n\n[FARE10:TAXI1]\n~g~Destino ~w~''la playa'' ~g~en Vice Point.\n\n[FARE11:TAXI1]\n~g~Destino ~w~''el hospital'' ~g~en Ocean Beach.\n\n[FARE12:TAXI1]\n~g~Destino ~w~''el hospital'' ~g~en Vice Point.\n\n[FARE13:TAXI1]\n~g~Destino ~w~''la comisaría de policía'' ~g~en Washington Beach.\n\n[FARE14:TAXI1]\n~g~Destino ~w~''la comisaría de policía'' ~g~en Vice Point.\n\n[FARE15:TAXI1]\n~g~Destino ~w~''la pizzería'' ~g~en Vice Point.\n\n[WFARE7:TAXI1]\n~g~Destino ~w~''la comisaría de policía'' ~g~en Little Havana.\n\n[WFARE8:TAXI1]\n~g~Destino ~w~''la comisaría de policía'' ~g~en el centro de la ciudad.\n\n[WFARE9:TAXI1]\n~g~Destino ~w~''el hospital'' ~g~en el centro de la ciudad.\n\n[WFARE10:TAXI1]\n~g~Destino ~w~''el hospital'' ~g~en Little Havana.\n\n[WFARE11:TAXI1]\n~g~Destino ~w~''el estadio'' ~g~en el centro de la ciudad.\n\n[WFARE12:TAXI1]\n~g~Destino ~w~''la pizzería'' ~g~en Little Haiti.\n\n[WFARE13:TAXI1]\n~g~Destino ~w~''la pizzería'' ~g~en el centro de la ciudad.\n\n[WFARE14:TAXI1]\n~g~Destino ~w~''los muelles'' ~g~en Viceport.\n\n[WFARE15:TAXI1]\n~g~Destino ~w~''la farmacia'' ~g~en Little Haiti.\n\n[FARE2:TAXI1]\n~g~Destino ~w~''el club Malibú'' ~g~en Vice Point.\n\n{=================================== MISSION TABLE TAXICUT ===================================}\n\n[TAXC_A:TAXICUT]\nSupongo que eres el nuevo propietario.\n\n[TAXC_B:TAXICUT]\n¿Qué eres, mafioso? ¿Del cártel? No pareces mejicano...\n\n[TAXC_C:TAXICUT]\nEn fin, será mejor que sueltes el rollo de ''las cosas van a cambiar por aquí'',\n\n[TAXC_D:TAXICUT]\nquizás amenazar a alguno de los conductores...\n\n[TAXC_E:TAXICUT]\nve con calma con Ted, el de ahí, acaban de curarle la hernia.\n\n[TAXC_F:TAXICUT]\nBueno, sí. Las cosas van a cambiar por aquí, señora.\n\n[TAXC_G:TAXICUT]\nOh, mierda, hijo. Anda dejarme esto a mí...\n\n[TAXC_H:TAXICUT]\nLlevo haciéndolo años.\n\n[TAXC_I:TAXICUT]\nAhora oíd esto.\n\n[TAXC_J:TAXICUT]\nAhora tenemos una nueva dirección y las cosas van a cambiar por aquí.\n\n[TAXC_K:TAXICUT]\nNuestra nueva dirección, los...\n\n[TAXC_L:TAXICUT]\n¿De qué banda eres?\n\n[TAXC_M:TAXICUT]\nBueno, en realidad no formo parte de ninguna banda.\n\n[TAXC_N:TAXICUT]\n¿Cómo coño te llamas, muchacho?\n\n[TAXC_O:TAXICUT]\nVercetti, Tommy Vercetti.\n\n[TAXC_P:TAXICUT]\nNuestra nueva administración, la banda de Vercetti,\n\n[TAXC_Q:TAXICUT]\nse va a encargar de que no tengamos problemas.\n\n[TAXC_R:TAXICUT]\n¿Capiche? ¡Corto!\n\n[TAXC_S:TAXICUT]\n¿Te gustó el ''capiche''? A mí me gustó el ''capiche''.\n\n[TAXC_T:TAXICUT]\nAsí que así es como funcionaban las cosas en el pasado,\n\n[TAXC_U:TAXICUT]\nDirigimos la compañía como siempre.\n\n[TAXC_V:TAXICUT]\nSi tenemos algún problema con las compañías rivales, tú les das una somanta de palos.\n\n[TAXC_W:TAXICUT]\nLuego ellos nos la dan a nosotros,\n\n[TAXC_X:TAXICUT]\ny después, se la vuelves a dar a ellos,\n\n[TAXC_Y:TAXICUT]\netcétera, etcétera. ¿Lo captas?\n\n[TAXC_Z:TAXICUT]\nSí, supongo...\n\n[TAXC_A1:TAXICUT]\nSimplemente toma un taxi del garaje si tienes ganas de subir a bordo.\n\n{=================================== MISSION TABLE TAXIWA1 ===================================}\n\n[OUTTIME:TAXIWA1]\n~r~¡Demasiado lento, tío, demasiado lento!\n\n[TAX1_1:TAXIWA1]\nTenemos un cliente importante que necesita que lo recojan en Starfish Island. ¿Alguien me recibe?\n\n[TAX1_2:TAXIWA1]\n¡Aquí Tommy, yo lo recogeré!\n\n[TAX1_3:TAXIWA1]\n¡Este es mi cliente, lárgate, gilipollas!\n\n[TAX1_4:TAXIWA1]\nVenga, venga, entre, ¡rápido!\n\n[TAX1_5:TAXIWA1]\n¡Vale, vale! ¡No me haga daño!\n\n[TAXW1_1:TAXIWA1]\n~g~Recoge al V.I.P. en Starfish Island.\n\n[TAXW1_2:TAXIWA1]\n~g~¡Recupera al V.I.P! ¡Destroza el otro coche!\n\n[TAXW1_3:TAXIWA1]\n~r~¡El V.I.P. está muerto!\n\n[TAXW1_4:TAXIWA1]\n~r~¡El V.I.P. se ha apeado!\n\n[TAXW1_6:TAXIWA1]\n~g~¡Lleva al V.I.P. al aeropuerto!\n\n{=================================== MISSION TABLE TAXIWA2 ===================================}\n\n[TAX2_1:TAXIWA2]\nLlamando a todos los taxis, estamos perdiendo clientes por toda la ciudad. ¿Qué os pasa, tíos?\n\n[TAX2_2:TAXIWA2]\nTaxis VC sigue llevándonos la delantera. ¡Tienen tantos coches que no podemos competir!\n\n[TAX2_3:TAXIWA2]\nSr. Vercetti, si está ahí escuchando, ¡tiene que poner fuera de circulación unos cuantos Taxis VC antes de que nos hundan!\n\n[TAXW2_1:TAXIWA2]\n~g~¡Destruye 3 de los taxis rivales!\n\n{=================================== MISSION TABLE TAXIWA3 ===================================}\n\n[TAX3_1:TAXIWA3]\nCoche 13, tengo a una tal Señorita Cortez, preguntó especialmente por usted.\n\n[TAX3_2:TAXIWA3]\nVale, entendido. ¡Coche 13 en ruta!\n\n[TAX3_3:TAXIWA3]\nNo hay rastro de Mercedes...\n\n[TAXW3_3:TAXIWA3]\n~g~Destrulle al taxi principal!\n\n[TAXW3_2:TAXIWA3]\n~g~Permanece con vida hasta que se agote el temporizador.\n\n[TAX_AS1:TAXIWA3]\nCOMPAÑÍA DE TAXIS CONSOLIDADA\n\n[TAX_AS2:TAXIWA3]\n~g~Los taxis Kaufman generarán ahora unos ingresos de hasta ~1~ $ máximo. Asegúrate de recaudarlos regularmente.\n\n[TAX3_4:TAXIWA3]\n¡Es hora que el ángel guardián de Taxis Kaufman coma algo del parachoques!\n\n[TAX3_5:TAXIWA3]\n¡Eh chico te voy a zurrar la badana!\n\n{ reVC updates }\n{ new languages }\n[FEL_JAP]\nJAPONÉS\n\n[FEL_POL]\nPOLACO\n\n[FEL_RUS]\nRUSO\n\n{ new display menus }\n[FET_GFX]\nCONFIGURACIÓN DE GRÁFICOS\n\n[FED_MIP]\nMIPMAPPING\n\n[FED_AAS]\nSUAVIZADO DE BORDES\n\n[FED_FIL]\nFILTRO DE TEXTURAS\n\n[FED_BIL]\nBILINEAL\n\n[FED_TRL]\nTRILINEAL\n\n[FED_WND]\nVENTANA\n\n[FED_FLS]\nPANTALLA COMPLETA\n\n[FEM_CSB]\nBORDES EN CINEMÁTICAS\n\n[FEM_SCF]\nFORMATO DE IMAGEN\n\n[FEM_ISL]\nUSO DE MEMORIA\n\n[FEM_LOW]\nBAJO\n\n[FEM_MED]\nMEDIO\n\n[FEM_HIG]\nALTO\n\n[FEM_2PR]\nALPHA TEST TIPO PS2\n\n[FEC_FRC]\nCÁMARA LIBRE\n\n{ Linux joy detection }\n[FEC_JOD]\nDETECTAR JOYSTICK\n\n[FEC_JPR]\nPulsa cualquier botón del joystick que quieras usar con el juego para seleccionarlo.\n\n[FEC_JDE]\nJoystick detectado\n\n{ mission restart }\n[FET_RMS]\nREPETIR MISIÓN\n\n[FESZ_RM]\n¿REINTENTAR?\n\n[FED_VPL]\nFLUJO DE VEHÍCULOS\n\n[FED_PRM]\nLUCES EN PEATONES\n\n[FED_RGL]\nBRILLO DE CARRETERAS\n\n[FED_CLF]\nFILTRO DE COLOR\n\n[FED_WLM]\nMAPAS DE LUZ DEL MUNDO\n\n[FED_MBL]\nDESENFOQ. MOVIMIENTO\n\n[FEM_SIM]\nSIMPLE\n\n[FEM_NRM]\nNORMAL\n\n[FEM_MOB]\nMÓVIL\n\n[FED_MFX]\nMATFX\n\n[FED_NEO]\nNEO\n\n[FEM_PS2]\nPS2\n\n[FEM_XBX]\nXBOX\n\n[FEC_IVP]\nINVERTIR VERTICALIDAD MANDO\n\n[FEM_NON]\nNADA\n\n[FEC_DS2]\nDUALSHOCK 2\n\n[FEC_DS3]\nDUALSHOCK 3\n\n[FEC_DS4]\nDUALSHOCK 4\n\n[FEC_360]\nMANDO DE XBOX 360\n\n[FEC_ONE]\nMANDO DE XBOX ONE\n\n[FEC_TYP]\nTIPO DE MANDO\n\n[FET_AGS]\nAJUSTES DE MANDO\n\n[FEM_AUT] { aspect ratio related }\nAUTO\n\n{ end of file }\n[DUMMY]\nTHIS LABEL NEEDS TO BE HERE !!!\nAS THE LAST LABEL DOES NOT GET COMPILED"
  },
  {
    "path": "vendor/libsndfile/ChangeLog",
    "content": "2013-04-05  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * Makefile.am\n    Make sure checkprograms are built as part of 'make test-tarball'.\n    Closes: https://github.com/erikd/libsndfile/issues/37\n\n2013-03-29  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/dft_cmp.c\n    Fix a buffer overflow detected using GCC 4.8's -fsantiize=address runtime\n    error checking functionality. This was a buffer overflow in libsndfile's\n    test suite, not in the actual library code.\n\n2013-03-09  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * M4/gcc_version.m4\n    Fix to work with OpenBSD's sed.\n\n2013-03-07  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/ALAC/alac_encoder.c\n    Patch from Michael Pruett (author of libaudiofile) to add correct byte\n    swapping for the mChannelLayoutTag field.\n\n2013-03-02  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * doc/bugs.html\n    Bugs should bt reported on the github issue tracker.\n\n2013-02-22  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.ac\n    Improve sanitization of FLAC_CFLAGS value.\n\n2013-02-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/Makefile.am\n    Call python interpreter instead of using '#!' in script. Thanks to Jan\n    Stary for reporting this.\n\n    * doc/index.html doc/FAQ.html\n    Make internal links relative. Patch from Jan Stary.\n\n2013-02-13  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/test_endswap.def src/test_endswap.tpl\n    Add tests for psf_put_be32() and psf_put_be64().\n\n    * src/sfendian.h src/test_endswap.(def|tpl)\n    Add functions psf_get_be(16|32|64) with tests.\n    These are needed for platforms where un-aligned accesses cause bus faults.\n\n    * src/ALAC/ag_enc.c src/ALAC/alac_decoder.c\n    Replace all un-aligned accesses with safe alternatives.\n    Closes: https://github.com/erikd/libsndfile/issues/19\n\n2013-02-12  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sfendian.h\n    Add big endian versions of H2BE_16 and H2BE_32.\n\n2013-02-11  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/ALAC/\n    Replace Apple endswap routines with ones from libsndfile.\n\n    * merge from libsndfile-cart repo\n    Add ability to set and get a cart chunk with WAV and RF64.\n    Orignal patch by Chris Roberts <c.roberts@csrfm.com> required a number of\n    tweaks.\n\n2013-02-10  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/common.h\n    Bump SF_HEADER_LEN from 8192 to 12292, the value it was in the 1.0.25\n    release.\n\n2013-02-09  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/alac.c\n    Fix segfault when encoding 8 channel files.\n    Closes: https://github.com/erikd/libsndfile/issues/30\n\n2013-02-07  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/ALAC/EndianPortable.c\n    Fall back to compiler's __BYTE_ORDER__ for endian-ness detection.\n\n2013-02-06  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.ac src/common.h src/ima_adpcm.c src/ms_adpcm.c src/paf.c\n    Drop tests for and #ifdef hackery for C99 struct flexible array feature.\n    libsndfile assumes the compiler supports most of the ISO C99 standard.\n\n    * src/alac.c\n    Fix valgrind invalid realloc. Reported by nu774.\n    Closes: https://github.com/erikd/libsndfile/issues/31\n\n2013-02-05  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/alac.c\n    The 'pakt' chunk header should now be written correctly.\n    Closes: https://github.com/erikd/libsndfile/issues/24\n\n    * configure.ac Makefile.am\n    Use PKG_INSTALLDIR when it exists. Suggestion from Christoph Thompson.\n    Closes: https://github.com/erikd/libsndfile/pull/28\n\n2013-02-03  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/common.h src/caf.c\n    Read the ALAC 'pakt' header and stash the values.\n\n    * src/sfendian.h\n    Add functions psf_put_be64() and psf_put_be32().\n\n    * src/alac.c\n    Start work on filling on the 'pakt' chunk header.\n\n2013-02-02  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * doc/FAQ.html\n    Add missing opening <P> tag.\n\n    * src/alac.c\n    Increase ALAC_BYTE_BUFFER_SIZE to 82000.\n\n2013-01-27  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * doc/FAQ.html\n    Improve question #8.\n\n2013-01-02  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/ogg_opus.c\n    Add skeleton implementation so someone else can run with it.\n\n2012-12-12  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/common.h src/dwd.c src/rx2.c src/txw.c\n    Fix for compiling when configured with --enable-experimental. Thanks to\n    Eric Wong for reporting this.\n\n2012-12-01  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.ac programs/sndfile-play.c\n    OS X 10.8 uses a different audio API to previous versions.\n    Fix compile failure on by disabling sndfile-play on this version.\n    Someone needs to supply code for the new API.\n\n2012-11-30  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * Octave/Makefile.am Octave/octave_test.sh\n    Fix 'make distcheck'.\n\n2012-10-13  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * M4/octave.m4\n    Relax constraints on Octave version.\n\n2012-10-11  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/utils.tpl\n    Improve compare_*_or_die() functions.\n\n    * src/command.c\n    Fix bug reported by Keiler Florian. When reading short or int data from a\n    file containing float data, and setting SFC_SET_SCALE_FLOAT_INT_READ to\n    SF_TRUE would fail 3, 5, 7 and other channels counts. Problem was that\n    psf_calc_signal_max() was not calculating the signal max correctly.\n    Calculation of the signal max was failing because it was trying to read\n    a sample count that was not an integer multiple of the channel count.\n\n    * tests/channel_test.c tests/Makefile.am tests/test_wrapper.sh.in\n    Add test for the above.\n\n2012-09-25  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.hh\n    Added a constructor to allow the use of SF_VIRTUAL_IO. Patch from\n    DannyDaemonic : https://github.com/erikd/libsndfile/pull/20\n\n2012-08-23  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * doc/octave.html\n    Fix link to octave.sourceforge.net. Thanks to IOhannes m zmoelnig.\n\n    * src/mat5.c\n    Allow reading of mat5 files without a specified sample rate (default to\n    44.1kHz). Thanks to IOhannes m zmoelnig.\n\n2012-08-19  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/paf.c\n    Error out if channel count is zero. Bug report from William ELla via\n    launchpad:\n    https://bugs.launchpad.net/ubuntu/+source/libsndfile/+bug/1036831\n\n2012-08-04  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.ac programs/sndfile-play.c\n    Patch from Ricci Adams to use OSX's AudioQueues on OSX 10.7 and greater.\n\n2012-07-09  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * programs/common.c\n    Accept \"ogg\" as a file extention for Ogg/Vorbis files.\n\n2012-06-22  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/flac.c\n    Make sure any previously allocated FLAC stream encoder and stream decoder\n    objects are deleted before a new one is allocated.\n\n2012-06-20  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/utils.tpl\n    Rename gen_lowpass_noise_float() to gen_lowpass_signal_float() and add a\n    sine wave component so that different FLAC compression levels can be\n    tested.\n\n    * src/sndfile.h.in doc/command.html\n    Add SFC_SET_COMPRESSION_LEVEL and document it.\n\n    * src/sndfile.c\n    Catch SFC_SET_VBR_ENCODING_QUALITY command and implement it as the inverse\n    of SFC_SET_COMPRESSION_LEVEL.\n\n    * src/ogg_vorbis.c src/flac.c\n    Implement SFC_SET_COMPRESSION_LEVEL command.\n\n    * tests/test_wrapper.sh.in tests/compression_size_test.c\n    Use the compression_size_test on FLAC as well.\n\n2012-06-19  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/\n    Rename vorbis_test.c -> compression_size_test.c so it can be extended to\n    test FLAC as well.\n\n2012-06-18  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/broadcast.c\n    Fix a bug where a file with a 'bext' chunk with a zero length coding\n    history field would get corrupted when the file was closed.\n    Reported by Paul Davis of the Ardour project.\n\n    * src/test_broadcast_var.c\n    Add a test for the above.\n\n2012-05-19  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.c\n    sf_format_check: For SF_FORMAT_AIFF, reject endian-ness setttings for\n    non-PCM formats.\n\n2012-04-12  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/aiff.c\n    Fix regression in handling of odd length SSND chunks.\n    Thanks Olivier Tristan for the example file.\n\n    * src/aiff.c src/wav.c\n    Exit parser loop when marker == 0.\n\n2012-04-04  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * doc/FAQ.html\n    Fix text. Thanks to Richard Collins.\n\n2012-03-24  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/caf.c\n    Exit parse loop if the marker is zero. Pass jump offsets as size_t instead\n    of int.\n\n2012-03-20  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/alac.c\n    Fix segfault when decoding CAF/ALAC file with more than 4 channels.\n    Fixes github issue #8 reported by Charles Van Winkle.\n\n2012-03-20  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/common.h\n    Change 'typedef SF_CHUNK_ITERATOR { ... } SF_CHUNK_ITERATOR' into 'struct\n    SF_CHUNK_ITERATOR { ... }' to prevent older compilers from complaining of\n    re-typedef-ing of SF_CHUNK_ITERATOR.\n\n    * configure.ac\n    Fix if test for empty $prefix.\n\n2012-03-18  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/*.c tests/chunk_test.c\n    Reworking of custom chunk handling code.\n    - Memory for the iterator is now attached to the SF_PRIVATE struct and\n      freed one sf_close().\n    - Rename sf_create_chunk_iterator() ->  sf_get_chunk_iterator().\n    - Each SNDFILE handle never has more than one SF_CHUNK_ITERATOR handle.\n\n    * tests/string_test.c\n    Fix un-initialised char buffer.\n\n2012-03-17  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/*.c tests/chunk_test.c\n    Add improved handling of custom chunk getting and settings. Set of patches\n    from IOhannes m zmoelnig submitted via github pull request #6.\n\n    * src/alac.c\n    Fix calculated frame count for files with zero block length.\n\n2012-03-13  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/avr.c\n    Remove double assignment to psf->endian. Thanks Kao Dome.\n\n    * src/gsm610.c\n    Fix clearing of buffers. Thanks Kao Dome.\n\n    * src/paf.c\n    Remove duplicate code. Thanks Kao Dome.\n\n    * src/test_strncpy_crlf.c\n    Fix minor error in test. Thanks Kao Dome.\n\n    * src/common.h src/*.c\n    Fix a bunch of valgrind errors.\n\n2012-03-13  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.c\n    Fix typo in error string 'Uknown' -> 'Unknown'.\n\n    * tests/fix_this.c\n    Fix potential int overflow.\n\n2012-03-10  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/alac.c\n    Fix decoding of last block so that the decode length is not a multiple of\n    the block length. Fixes github issue #4 reported by Charles Van Winkle.\n\n    * src/sfconfig.h src/sfendian.h\n    Fix for MinGW cross compiling. Use '#if (defined __*66__)' instead of\n    '#if __*86__' because the MinGW header use '#ifdef __x86_64__'.\n\n2012-03-10  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/ALAC/ src/alac.c\n    Unify the interface between libsndfile and Apple ALAC codec. Regardless of\n    file bit width samples are now passed between the two as int32_t that are\n    justified towards the most significant bit. Without this modification, 16\n    conversion functions would have been needed between the libsndfile (short,\n    int, float, double) types and the ALAC types (16, 20, 24 and 32 bit). With\n    this mod, only 4 are needed.\n\n    * tests/floating_point_test.tpl tests/write_read_test.(def|tpl)\n    Add tests for 20 and 24 bit ALAC/CAF files.\n\n    * src/command.c\n    Add ALAC/CAF to the SFC_GET_FORMAT_* commands. Fixes github issue #5.\n\n    * configure.ac\n    Only use automake AM_SLIENT_RULES where supported. Thanks Dave Yeo.\n\n    * tests/pipe_test.tpl\n    Disable tests on OS/2. Thanks Dave Yeo.\n\n2012-03-09  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.ac src/sfconfig.h src/sfendian.h\n    For GCC, use inline assembler for endian swapping. This should work with\n    older versions of GCC like the one currently used in OS/2.\n\n2012-03-06  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/alac.c\n    Make sure temp file gets opened in binary mode.\n\n    * src/alac.c src/common.c src/common.h\n    Fix function alac_write16_d().\n\n    * tests/floating_point_test.tpl\n    Add tests for 16 bit ALAC/CAF.\n\n    * src/alac.c src/common.c src/common.h\n    Add support for 32 bit ALAC/CAF files.\n\n    * tests/floating_point_test.tpl tests/write_read_test.tpl\n    Add tests for 32 bit ALAC/CAF files.\n\n2012-03-05  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/\n    Refactor chunk storage so it work on big as well as little endian CPUs.\n\n    * tests/chunk_test.c\n    Clean up error messages.\n\n    * src/sfendian.h src/*.c\n    Rename endian swapping macros and add ENDSWAP_64 and BE2H_64.\n\n    * configure.ac\n    Detect presence of <x86intrin.h> header file.\n\n    * src/sfendian.h\n    Use <x86intrin.h> intrinsics (ie for MinGW) when <byteswap.h> is not\n    present.\n    Make ENDSWAP_64() work with i686-w64-mingw32 compiler.\n\n    * src/ALAC/EndianPortable.c\n    Add support for __powerpc__.\n\n    * src/sfconfig.h\n    Make sure HAVE_X86INTRIN_H is either 1 or 0.\n\n2012-03-03  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/ALAC/*\n    Big dump of code for Apple's ALAC file format. The copyyright to this code\n    is owned by Apple who have released it under an Apache style license. A few\n    small modifications were made to allow this to be integrated into libsndfile\n    but unfortunately the history of those changes were lost because they were\n    developed in a Bzr tree and during that time libsndfile moved to Git.\n\n    * src/alac.c src/caf.c src/common.[ch] src/Makefile.am src/sndfile.h.in\n        src/sndfile.c\n    Hook new ALAC codec in.\n\n    * programs/sndfile-convert.c\n    Add support for alac codec.\n\n    * tests/write_read_test.tpl\n    Expand tests to cover ALAC.\n\n2012-03-02  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/aiff.c src/wav.c\n    Fix a couple of regressions from version 1.0.25.\n\n2012-03-01  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/strings.c\n    Minor refactoring. Make sure that the memory allocation size if always > 0\n    to avoid undefined behaviour.\n\n2012-02-29  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/chunk.c\n    Fix buffer overrun introduced in recently added chunk logging. This chunk\n    logging has not yet made it to a libsndfile release version. Thanks to\n    Olivier Tristan for providing an example file.\n\n    * src/wav.c\n    Fix handling of odd sized chunks which was causing the parser to lose some\n    chunks. Thanks to Olivier Tristan for providing an example file.\n\n2012-02-26  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/util.tpl\n    Used gnu_printf format checking with mingw-w64 compiler.\n\n    * tests/header_test.tpl\n    Printf format fixes.\n\n2012-02-25  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * M4/extra_pkg.m4\n    Update PKG_CHECK_MOD_VERSION macro to add an AC_TRY_LINK step. This fix\n    allows the configure process to catch attempts to link incompatible\n    libraries. For example, linking 32 bit version of eg libFLAC to a 64 bit\n    version of libsndfile will now fail. Similarly, when cross compiling\n    libsndfile from Linux to Windows linking the Linux versions of a library\n    to the Windows version of libsndfile will now also fail.\n\n    * src/sndfile.h.in src/sndfile.c src/common.h src/create_symbols_file.py\n    Add API function sf_current_byterate().\n\n    * src/dwvw.c src/flac.c src/ogg_vorbis.c src/sds.c\n    Add codec specific handlers for current byterate.\n\n    * tests/floating_point_test.tpl\n    Add initial test for sf_current_byterate().\n\n2012-02-24  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/common.[ch]\n    Add function psf_decode_frame_count().\n\n    * src/dwvw.c\n    Fix a termnation bug that caused the decoder to go into an infinite loop.\n\n2012-02-24  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/wav.c\n    Fix a regression in the WAV header parser. Thanks to Olivier Tristan for\n    bug report and the example file.\n\n2012-02-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.c\n    Return error when SF_BROADCAST_INFO struct has bad coding_history_size.\n    Thanks to Alex Weiss for the report.\n\n2012-02-20  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/au.c src/flac.c src/g72x.c src/ogg_vorbis.c src/wav_w64.c\n    Don't fake psf->bytewidth values.\n\n2012-02-19  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/string_test.c\n    Fix valgrind warnings.\n\n    * src/common.h src/sndfile.c src/strings.c\n    Make string storage dynamically allocated.\n\n    * src/sndfile.c\n    Add extra validation for custom chunk handling.\n\n2012-02-18  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/wav.c\n    Improve handlling unknown chunk types. Thanks to Olivier Tristan for sending\n    example files.\n\n    * src/utils.tpl\n    Add GCC specific testing for format string parameters for exit_if_true().\n\n    * tests/*.c tests/*.tpl\n    Fix all printf format warnings.\n\n    * programs/sndfile-play.c\n    Remove un-needed OSX include <Carbon.h>. Thanks jamesfmilne for github\n    issue #3.\n\n    * tests/chunk_test.c\n    Extend custom chunk test.\n\n2012-02-12  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/wav.c\n    Jump over some more chunk types while parsing.\n\n2012-02-04  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/common.h src/strings.c\n    Change way strings are stored in SF_PRIVATE in preparation for dynamically\n    allocating the storage.\n\n2012-02-02  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/common.h src*.c\n    Improve encapsulation of string data in SF_PRIVATE.\n\n2012-02-01  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/common.h src*.c\n    Remove the buffer union from SF_PRIVATE. Most uses of this have been\n    replaced with a BUF_UNION that is allocated on the stack.\n\n2012-01-31  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/common.h src*.c\n    Rename logbuffer field of SF_PRIVATE to parselog and reduce its size.\n    Put the parselog buffer and the index inside a struct within SF_PRIVATE.\n\n2012-01-26  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.ac\n    Fix typo, FLAC_CLFAGS -> FLAC_CFLAGS. Thanks to Jeremy Friesner.\n\n2012-01-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.c src/ogg.c\n    Fix misleading error message when trying to create an SF_FORMAT_OGG file\n    with anything other than SF_FORMAT_FILE. Thanks to Charles Van Winkle for\n    the bug report. Github issue #1.\n\n2012-01-20  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.c src/wav.c\n    Allow files opened in RDWR mode with string data in the tailer to be\n    extended. Thanks to Bodo for the patch.\n\n    * tests/string_test.c\n    Add tests for the above changes (patch from Bodo).\n\n2012-01-09  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/aiff.c\n    Refactor reading of chunk size and use of psf_store_read_chunk().\n\n    * src/(caf|wav).c\n    Correct storing of chunk offset.\n\n2012-01-05  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/aiff.c src/wav.c src/common.h\n    Refactor common code into src/common.h.\n\n    * src/caf.c\n    Make custom chunks work for CAF files.\n\n    * tests/chunk_test.c tests/test_wrapper.sh.in\n    Test CAF files with custom chunks.\n\n    * src/sndfile.c\n    Prevent psf->codec_close() being called more than once.\n\n2012-01-04  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * programs/sndfile-cmp.c\n    Catch the case where the second file has more frames than the first.\n\n2012-01-02  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/create_symbols_file.py\n    Add sf_set_chunk/sf_get_chunk_size/sf_get_chunk_data.\n\n2011-12-31  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/chunk_test.c tests/Makefile.am\n    New test for custom chunks.\n\n    * src/aiff.c src/chunk.c src/common.h src/sndfile.c\n    Make custom chunks work on AIFF files.\n\n    * src/wav.c\n    Make custom chunks work on WAV files (includes refactoring).\n\n2011-11-12  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.h.in src/common.h src/sndfile.c\n    Start working on setting/getting chunks.\n\n2011-11-24  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/binheader_writef_check.py src/create_symbols_file.py\n    Make it work for Python 2 and 3. Thanks Michael.\n\n2011-11-19  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * libsndfile.spec.in\n    Change field name 'URL' to 'Url'.\n\n    * src/sndfile.h.in\n    Add SF_SEEK_SET/CUR/END.\n\n2011-11-05  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/id3.c\n    Fix a stack overflow that can occur when parsing a file with multiple\n    ID3 headers which would cause libsndfile to go into an infinite recursion\n    until it blew the stack. Thanks to Anders Svensson for supplying an example\n    file.\n\n2011-10-30  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/double64.c src/float32.c src/common.h\n    Make (float32|double_64)_(be|le)_read() functions const correct.\n\n2011-10-28  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sfendian.h\n    Minor tweaking of types. Cast to ptr to correct final type rather void*.\n\n    * programs/sndfile-play.c tests/utils.tpl\n    Fix compiler warnings with latest MinGW cross compiler.\n\n2011-10-13  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/file_io.c\n    Use the non-deprecated resource fork name on OSX. Thanks to Olivier Tristan.\n\n2011-10-12  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/wav.c\n    Jump over the 'olym' chunks when parsing.\n\n2011-10-06  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/write_read_test.tpl\n    Remove windows only truncate() implementation.\n\n2011-09-04  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sd2.c src/sndfile.c\n    Make sure 23 bit PCM SD2 files are readable/writeable.\n\n    * tests/write_read_test.tpl\n    Add tests for 32 bit PCM SD2 files.\n\n2011-08-23  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.ac\n    Use AC_SYS_LARGEFILE instead of AC_SYS_EXTRA_LARGEFILE as suggested by\n    Jan Willies.\n\n2011-08-07  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.ac Makefile.am\n    Move ACLOCAL_AMFLAGS setup to Makefile.am.\n\n2011-07-15  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * doc/command.html\n    Merge two separate blocks of SFC_SET_VBR_ENCODING_QUALITY documentation.\n\n    * src/paf.c\n    Replace ppaf24->samplesperblock with a compile time constant.\n\n2011-07-13  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/ogg_vorbis.c\n    Fix return value of SFC_SET_VBR_ENCODING_QUALITY command.\n\n    * doc/command.html\n    Document SFC_SET_VBR_ENCODING_QUALITY, SFC_GET/SET_LOOP_INFO and\n    SFC_GET_INSTRUMENT.\n\n    * NEWS README configure.ac doc/*.html\n    Updates for 1.0.25.\n\n2011-07-07  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sfconfig.h\n    Add handling for HAVE_SYS_WAIT_H.\n\n    * Makefile.am src/Makefile.am tests/Makefile.am\n    Add 'checkprograms' target.\n\n2011-07-05  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/common.h src/sndfile.c\n    Purge SF_ASSERT macro. Use standard C assert instead.\n\n    * src/paf.c src/common.h src/sndfile.c\n    Fix for Secunia Advisory SA45125, heap overflow (heap gets overwritten with\n    byte value of 0) due to integer overflow if PAF file handler.\n\n    * src/ima_adpcm.c src/ms_adpcm.c src/paf.c\n    Use calloc instead of malloc followed by memset.\n\n    * tests/utils.tpl\n    Clean up use of memset.\n\n2011-07-05  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/ogg.c\n    Fix log message.\n\n    * tests/format_check_test.c\n    Fix compiler warnings.\n\n2011-07-04  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.c\n    Fix error message for erro code SFE_ZERO_MINOR_FORMAT.\n\n    * tests/format_check_test.c\n    Add a test to for SF_FINFO format field validation.\n\n    * src/ogg.c src/ogg_vorbis.c src/ogg.h src/ogg_pcm.c src/ogg_speex.c\n        src/common.h src/Makefile.am\n    Move vorbis specific code to ogg_vorbis.c, add new files for handling PCM\n    and Speex codecs in an Ogg container. The later two are only enabled with\n    ENABLE_EXPERIMENTAL_CODE config variable.\n\n2011-06-28  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/strings.c\n    Clean up and refactor storage of SF_STR_SOFTWARE.\n\n2011-06-23  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.h.in doc/api.html\n    Fix definition of SF_STR_LAST and update SF_STR_* related docs. Thanks to\n    Tim van der Molen for the patch.\n\n2011-06-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * programs/sndfile-interleave.c\n    Fix handling of argc. Thanks to Marius Hennecke.\n\n    * src/wav_w64.c\n    Accept broken WAV files with blockalign == 0. Thanks to Olivier Tristan for\n    providing example files.\n\n    * src/wav.c\n    Jump over 'FLLR' chunks.\n\n2011-06-14  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.h.in\n    Fix -Wundef warning due to ENABLE_SNDFILE_WINDOWS_PROTOTYPES.\n\n    * configure.ac\n    Add -Wundef to CFLAGS.\n\n    * src/ogg.c\n    Fix -Wunder warning.\n\n2011-05-18  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.ac\n    Use int64_t instead of off_t when they are the same size.\n\n    * src/Makefile.am tests/Makefile.am\n    Use check_PROGRAMS instead of noinst_PROGRAMS where appropriate.\n\n2011-05-08  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/wav.c\n    Don't allow unknown and/or un-editable chunks to prevent the file from being\n    opened in SFM_RDWR mode.\n\n2011-04-25  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/format_check_test.c\n    Fix segfault in test program.\n\n2011-04-25  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/format_check_test.c\n    New test program to check to make sure that sf_open() and sf_check_format()\n    agree as to what is a valid program.\n\n    * tests/Makefile.am tests/test_wrapper.sh.in\n    Hook into build and test runner.\n\n    * src/sndfile.c\n    Fix some sf_format_check() problems. Thanks to Charles Van Winkle for the\n    notification.\n\n2011-04-06  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/caf.c\n    Add validation to size of 'data' chunk and fix size of written 'data'\n    chunk. Thanks to Michael Pruett for reporting this.\n\n2011-03-28  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/* tests/* programs/*\n    Fix a bunch of compiler warnings with gcc-4.6.\n\n2011-03-25  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/util.tpl\n    Add NOT macro to util.h.\n\n    * src/strings.c\n    Fix handling of SF_STR_SOFTWARE that resulted in a segfault due to calling\n    strlen() on an unterminated string. Thanks to Francois Thibaud for reporting\n    this problem.\n\n    * tests/string_test.c\n    Add test for SF_STR_SOFTWARE segfault bug.\n\n    * configure.ac\n    Sanitize FLAC_CFLAGS value supplied by pkg-config which returns a value of\n    '-I${includedir}/FLAC'. However FLAC also provides an include file\n    <assert.h> which clashes with the Standard C header of the same name. The\n    solution is strip the 'FLAC' part off the end and include all FLAC headers\n    as <FLAC/header.h>.\n\n    * configure.ac src/Makefile.am\n    Use non-recursive make in src/ directory.\n\n2011-03-23  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * NEWS README docs/*.html\n    Updates for 1.0.24 release.\n\n2011-03-22  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.ac\n    Fix up usage of sed (should not assume GNU sed).\n\n    * M4/add_(c|cxx)flags.m4\n    Test flags in isolation.\n\n    * tests/cpp_test.cc\n    Fix a broken test (test segfaults). Report by Dave Flogeras.\n\n2011-03-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * programs/common.[ch]\n    Add function program_name() which returns the program name minus the path\n    from argv [0].\n\n    * programs/*.c programs/Makefile.am\n    Use program_name() where appropriate. Fix build.\n\n2011-03-20  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/wav.c\n    For u-law and A-law files, write an 18 byte 'fmt ' chunk instead of a 16\n    byte one. Win98 accepts files with a 16 but not 18 byte 'fmt' chunk. Later\n    version accept 18 byte but not 16 byte.\n\n2011-03-15  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * doc/FAQ.html\n    Add examples for question 12.\n\n    * doc/libsndfile.css.in\n    Add tweaks for h4 element.\n\n    * doc/api.html\n    Add documentation for virtual I/O functionality. Thanks to Uli Franke.\n\n    * tests/util.tpl\n    Add static inline functions sf_info_clear() and sf_info_setup().\n\n    * tests/(alaw|dwvw|ulaw)_test.c\n    Use functions sf_info_clear() and sf_info_setup().\n\n2011-03-08  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.ac\n    Fail more gracefully if pkg-config is missing. Suggestion from Brian\n    Willoughby.\n\n2011-02-27  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/common.c\n    Use size_t instead of int for size params with varargs.\n\n2011-02-09  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * doc/index.html\n    Update supported platforms with more Debian platforms and Android.\n\n2011-01-27  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.hh\n    Add an LPCWSTR version of the SndfileHandle constructor to the SndfileHandle\n    class definition. Thanks to Eric Eizenman for pointing out this was missing.\n\n    * tests/cpp_test.cc\n    Add test for LPCWSTR version of the SndfileHandle constructor.\n\n2011-01-19  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * programs/sndfile-play.c\n    Remove cruft.\n\n2010-12-01  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.hh\n    Add methods rawHandle() and takeOwnership(). Thanks to Tim Blechmann for\n    the patch.\n\n    * tests/cpp_test.cc\n    Add tests for above two methods. Also supplied by Tim Blechmann.\n\n2010-11-11  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * doc/api.html\n    Add mention of use of sf_strerror() when sf_open() fails.\n\n2010-11-01  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.ac\n    Make TYPEOF_SF_COUNT_T int64_t where possible. This may fix problems where\n    people are compiling on a 64 bit system with the GCC -m32 flag.\n\n    * src/sndfile.h.in\n    Fix comments on sf_count_t.\n\n2010-10-26  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/aiff.c\n    Handle non-zero offset field in SSND chunk. Thanks to Michael Chinen.\n\n2010-10-20  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.ac\n    Sed fix for FreeBSD. Thanks Tony Theodore.\n\n2010-10-14  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * shave.in M4/shave.m4\n    Fix shave invocation of windres compiler. Thanks Damien Lespiau (upstream\n    shave author).\n\n    * configure.ac M4/shave.m4 shave-libtool.in shave.in\n    Switch from shave to automake-1.11's AM_SILENT_RULES.\n\n2010-10-13  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * shave-libtool.in shave.in\n    Sync to upstream version.\n\n    * src/rf64.c\n    More work to make the parser more robust and accepting of mal-formed files.\n\n2010-10-12  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/common.h\n    Add functions psf_strlcpy() and psf_strlcat().\n\n    * src/broadcast.c src/sndfile.c src/strings.c src/test_main.c\n        src/test_main.h src/test_strncpy_crlf.c\n    Use functions psf_strlcpy() and psf_strlcat() as appropriate.\n\n    * tests/string_test.c\n    Add tests for SF_STR_GENRE and SF_STR_TRACKNUMBER.\n\n    * src/rf64.c\n    Fix size of 'ds64' chunk when writing RF64.\n\n2010-10-10  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * programs/*.c\n    Add the libsndfile version to the usage message of all programs.\n\n2010-10-10  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.ac src/version-metadata.rc.in src/Makefile.am\n    Add version string resources to the windows DLL.\n\n    * doc/api.html\n    Update to add missing SF_FORMAT_* values. Closed Debian bug #545257.\n\n    * NEWS README configure.ac doc/*.html\n    Updates for 1.0.23 release.\n\n2010-10-09  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/pedantic-header-test.sh.in\n    Handle unusual values of CC environment variable.\n\n    * src/rf64.c\n    Minor tweaks and additional sanity checking.\n\n    * src/Makefile.am src/binheader_writef_check.py\n    Use python 2.6.\n\n2010-10-08  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.hh\n    Add a missing 'inline' before a constructor defintion.\n\n2010-10-06  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/common.h\n    Add macro NOT.\n\n    * src/rf64.c\n    Minor tweaks.\n\n    * Makefile.am */Makefile.am\n    Add *~ to CLEANFILES.\n\n2010-10-05  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.c\n    Fix a typo in the error string for SFE_OPEN_PIPE_RDWR. Thanks to Charles\n    Van Winkle for the report.\n\n2010-10-04  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/flac.c src/ogg.c src/sndfile.h.in src/strings.c src/wav.c\n    Add ability to read/write tracknumber and genre to flac/ogg/wav files.\n    Thanks to Matti Nykyri for the patch.\n\n    * src/common.h src/broadcast.c src/strings.c\n    Add function psf_safe_strncpy() and use where appropriate.\n\n2010-10-04  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * NEWS README configure.ac doc/*.html\n    Updates for 1.0.22 release.\n\n2010-10-03  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/common.h src/broadcast.c src/rf64.c src/sndfile.c src/wav.c\n    Rewrite of SF_BROADCAST_INFO handling.\n\n    * src/test_broadcast_var.c tests/command_test.c\n    Tweak SF_BROADCAST_INFO tests.\n\n    * src/test_broadcast_var.c\n    Fix OSX stack check error.\n\n2010-09-30  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sds.c\n    Set sustain_loop_end to 0 as suggested by Brian Lewis.\n\n2010-09-29  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sds.c\n    Make sure the correct frame count gets written into the header.\n\n    * tests/write_read_test.tpl\n    Don't allow SDS files to have a long frame count.\n\n2010-09-17  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sds.c\n    Apply a pair of patches from Brian Lewis to fix the packet number location\n    and the checksum.\n\n2010-09-10  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    *  src/aiff.c src/file_io.c src/ogg.c src/rf64.c src/sndfile.c\n        src/strings.c src/test_audio_detect.c src/test_strncpy_crlf.c\n        src/wav.c tests/pcm_test.tpl\n   Fix a bunch of minor issues found using static analysis.\n\n2010-08-23  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/test_broadcast_var.c\n    New file containing tests for broadcast_set_var().\n\n    * src/Makefile.am src/test_main.[ch]\n    Hook test_broadcast_var.c into tests.\n\n2010-08-22  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/broadcast.c src/common.(c|h)\n    Move function strncpy_crlf() to src/common.c so the function can be tested\n    in isolation.\n\n    * src/test_strncpy_crlf.c\n    New file.\n\n    * src/Makefile.am src/test_main.[ch]\n    Hook test_strncpy_crlf.c into tests.\n\n2010-08-18  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/common.h\n    Move code around to make comments make sense.\n\n    * src/broadcast.c\n    Add debugging code that is disabled by default.\n\n2010-08-02  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/flac.c\n    When the file meta data says the file has zero frames set psf->sf.frames\n    to SF_COUNT_MAX. Fixes Debian bug #590752.\n\n    * programs/sndfile-info.c\n    Print 'unknown' if frame count == SF_COUNT_MAX.\n\n2010-06-27  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.c\n    Only support writing mono SVX files. Multichannel SVX files are not\n    interleaved and there is no support infrastructure to cache and write\n    multiple channels to create a non-interleaved file.\n\n    * src/file_io.c\n    Don't call close() on a file descriptor of -1. Thanks to Jeremy Friesner\n    for the bug report.\n\n2010-06-09  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/common.h\n    Add macro SF_ASSERT.\n\n    * src/sndfile.c\n    Use SF_ASSERT to ensure sizeof (sf_count_t) == 8.\n\n    * src/svx.c\n    Add support for reading and writing stereo SVX files.\n\n2010-05-07  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.ac\n    When compiling with x86_64-w64-mingw32-gcc link with -static-libgcc flags.\n\n    * programs/common.c programs/sndfile-metadata-set.c\n    Update metadata after the audio data is copied. Other minor fixes. Patch\n    from Marius Hennecke.\n\n2010-05-04  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/nist.c\n    Fix a regression reported by Hugh Secker-Walker.\n\n    * src/api.html\n    Add comment about sf_open_fd() not working on Windows if the application\n    and the libsndfile DLL are linked to different versions of the Microsoft\n    C runtime DLL.\n\n2010-04-23  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/pedantic-header-test.sh.in\n    Fix 'make distcheck'.\n\n2010-04-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/pedantic-header-test.sh.in\n    New file to test whether sndfile.h can be compiled with gcc's -pedantic\n    flag.\n\n    * configure.ac tests/test_wrapper.sh.in\n    Hook pedantic-header-test into test suite.\n\n    * src/sndfile.h.in\n    Fix -pedantic warning.\n\n2010-04-19  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * programs/sndfile-salvage.c programs/Makefile.am\n    New program to salvage the audio data from WAV/WAVEX/AIFF files which are\n    greater than 4Gig in size.\n\n2010-04-09  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * programs/sndfile-convert.c\n    Fix valgrind warning.\n\n2010-04-06  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * programs/sndfile-cmp.c\n    When files differ in the PCM data, also print the difference offset.\n    Minor cleanup.\n\n2010-03-19  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/aiff.c\n    Don't use the 'twos' marker for 24 and 32 bit PCM, use 'in24' and 'in32'\n    instead. Thanks to Paul Davis (Ardour) for this suggestion.\n\n2010-02-28  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.ac\n    Clean up configure report.\n\n    * tests/utils.tpl\n    Add functions test_read_raw_or_die and test_write_raw_or_die.\n\n    * tests/rdwr_test.(def|tpl) tests/Makefile.am\n    Add new test program and hook into build.\n\n    * src/sndfile.c\n    Fix minor issues with sf_read/write_raw(). Bug reported by Milan Křápek.\n\n    * tests/test_wrapper.sh.in\n    Add rdwr_test to the test wrapper script.\n\n2010-02-22  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.ac\n    Remove -fpascal-strings from OSX's OS_SPECIFIC_CFLAGS.\n\n    * programs/common.[ch] programs/sndfile-metadata-set.c\n    Apply a patch from Robin Gareus allowing the setting of the time reference\n    field of the BEXT chunk.\n\n2010-02-06  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/ima_adpcm.c\n    Add a fix from Jonatan Liljedahl to handle predictor overflow when decoding\n    IMA4.\n\n2010-01-26  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.hh\n    Add a constructor which takes an existing file descriptor and then calls\n    sf_open_fd(). Patch from Sakari Bergen.\n\n2010-01-10  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * programs/sndfile-deinterleave.c programs/sndfile-interleave.c\n    Improve usage messages.\n\n2010-01-09  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/id3.c src/Makefile.am\n    Add new file src/id3.c and hook into build.\n\n    * src/sndfile.c src/common.h\n    Detect and skip and ID3 header at the start of the file.\n\n2010-01-07  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * programs/common.c\n    Fix update_strings() copyright, comment, album and license are correctly\n    written. Thanks to Todd Allen for reporting this.\n\n    * man/Makefile.am\n    Change GNU makeism to something more widely supported. Thanks to Christian\n    Weisgerber for reporting this.\n\n    * configure.ac programs/Makefile.am programs/sndfile-play.c\n    Apply patch from Christian Weisgerber and Jacob Meuserto add support for\n    OpenBSD's sndio.\n\n2010-01-05  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * doc/api.html\n    Discourage the use of sf_read/write_raw().\n\n2009-12-28  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.ac\n    Test for Unix pipe() and waitpid() functions.\n\n    * src/sfconfig.h tests/pipe_test.tpl\n    Disable pipe_test if pipe() and waitpid() aren't available.\n\n2009-12-16  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.ac src/Makefile.am src/create_symbols_file.py\n        src/make-static-lib-hidden-privates.sh\n    Change name of generated file src/Symbols.linux to Symbols.gnu-binutils and\n    and use the same symbols file for other systems which use GNU binutils like\n    Debian's kfreebsd.\n\n    * M4/shave.m4 shave.in\n    Update shave files from upstream.\n\n2009-12-15  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * man/sndfile-metadata-get.1\n    Fix typo.\n\n    * man/sndfile-interleave.1 man/Makefile.am\n    New man page.\n\n2009-12-13  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/ogg.c\n    When decoding to short or int, clip the decoded signal to [-1.0, 1.0] if\n    its too hot. Thanks to Dmitry Baikov for suggesting this.\n\n    * NEWS README doc/*.html\n    Updates for 1.0.21.\n\n2009-12-09  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * programs/sndfile-jackplay.c man/sndfile-jackplay.1\n    Remove these which will now be in found in the sndfile-tools package.\n\n    * programs/Makefile.am man/Makefile.am\n    Remove build rules for sndfile-jackplay.\n\n    * configure.ac\n    Remove detection of JACK Audio Connect Kit.\n\n    * programs/sndfile-concat.c man/sndfile-concat.1\n    Add new program with man page.\n\n    * man/Makefile.am programs/Makefile.am\n    Hook sndfile-concat into build system.\n\n2009-12-08  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/error_test.c\n    Don't terminate when sf_close() returns zero in error_close_test().\n    It seems that Windows 7 behaves differently from earlier versions of\n    Windows.\n\n2009-12-03  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.ac M4/*.m4\n    Rename all custom macros from AC_* to MN_*.\n\n    * programs/sndfile-interleave.c\n    Make it actually work.\n\n2009-12-02  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * doc/*.html configure.ac\n    Corrections and clarifications courtesy of Robin Forder.\n\n    * programs/sndfile-convert.c programs/common.[ch]\n    Move some code from convert to common for reuse.\n\n    * programs/sndfile-interleave.c programs/sndfile-interleave.c\n    Add new programs sndfile-interleave and sndfile-deinterleave.\n\n    * programs/Makefile.am\n    Hook new programs into build.\n\n2009-12-01  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/create_symbols_file.py tests/stdio_test.c tests/win32_test.c\n    Minor OS/2 tweaks as suggested by David Yeo.\n\n    * tests/multi_file_test.c\n    Fix file creation flags on windows. Thanks to Bruce Sharpe.\n\n    * src/sf_unistd.h\n    Set all group and other file create permssions to zero.\n\n    * tests/win32_test.c\n    Add a new test.\n\n2009-11-30  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * doc/print.css doc/*.html\n    Add a print stylesheet and update all HTML documents to reference it.\n    Thanks to Aditya Bhargava for suggesting this.\n\n    * doc/index.html\n    Minor corrections.\n\n2009-11-29  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * sndfile.pc.in\n    Add a Libs.private entry to assist with static linking.\n\n2009-11-28  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/make-static-lib-hidden-privates.sh src/Makefile.am\n    Add a script to hide all non-public symbols in the libsndfile.a static\n    library.\n\n2009-11-22  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/locale_test.c\n    Correct usage of ENABLE_SNDFILE_WINDOWS_PROTOTYPES.\n\n2009-11-20  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/windows.c\n    Correct usage of ENABLE_SNDFILE_WINDOWS_PROTOTYPES.\n\n2009-11-16  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * programs/sndfile-convert.c\n    Allow the program to read from stdin by specifying '-' on the command line\n    as the input file.\n\n    * src/sndfile.h.in\n    Hash define ENABLE_SNDFILE_WINDOWS_PROTOTYPES to 1 for greater safety.\n\n    * tests/virtual_io_test.c\n    Add a PAF/PCM_24 test and verify the file length is not negative\n    immediately after openning the file for write.\n\n2009-10-18  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/wav.c\n    When writing loop lengths, adjust the end position by one to make up for\n    Microsoft's screwed up spec. Thanks to Olivier Tristan for the patch.\n\n2009-10-14  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/flac.c\n    Apply patch from Uli Franke allowing FLAC files to be encoded at any sample\n    rate.\n\n2009-10-09  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/nist.c\n    Fix parsing of odd ulaw encoded file provided by Jan Silovsky.\n\n    * configure.ac\n    Insist on libvorbis >= 1.2.3. Earlier verions have bugs that cause the\n    libsndfile test suite to fail on MIPS, PowerPC and others.\n    See: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=549899\n\n2009-10-06  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * man/sndfile-convert.1\n    Fix warning from Debian's lintian checks.\n\n    * man/sndfile-cmp.1 man/sndfile-jackplay.1 man/sndfile-metadata-get.1\n        man/Makefile.am\n    Add three new minimal manpages and hook into build.\n\n2009-10-05  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/test_wrapper.sh.in\n    Don't run cpp_test on x86_64-w64-mingw32.\n\n2009-09-28  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/utils.tpl\n    On windows, make sure the open() function doesn't get called with a third\n    parameter of 0 which fails for no good reason. Also make sure this third\n    parameter doesn't get called with S_IRGRP when compiling for windows because\n    Wine complains.\n\n    * src/sndfile.hh\n    Add a SndfileHandle constructor for windows that takes a 'const wchar_t *'\n    string.\n\n    * doc/FAQ.html\n    Add Q/A : I'm cross compiling libsndfile for another platform. How can I\n    run the test suite?\n\n    * src/create_symbols_file.py src/Makefile.am\n    Add Symbols.static target, a list of symbols, one per line.\n\n2009-09-27  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/test_wrapper.sh.in\n    Update to allow all tests to be gathered up into a testsuite tarball and\n    then be run using this script.\n\n    * build-test-tarball.mk.in\n    Add a Make script to build a tarball of all the test binaries and the test\n    wrapper script. This is useful for cross compiling; you can build the\n    binaries, build test test tarball and transfer the test tarball to the\n    target machine for testing.\n\n2009-09-26  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/common.h src/*.c\n    Modify SF_FILE struct to allow it to carry either 8-bit or 16-bit strings\n    for the file path, directory and name. Fixes for this change throughout.\n\n    * src/windows.c src/Makefile.am\n    New file defining new windows only public function sf_wchar_open() which\n    takes a 'const wchar_t *' string (LPCWSTR) for the file name parameter.\n\n    * src/sndfile.h.in\n    Add SF_CHANNEL_MAP_ABISONIC_* entries.\n    Add windows only defintion for sf_wchar_open().\n\n    * src/create_symbols_file.py\n    Add sf_wchar_open() to the list of public symbols (windows only).\n\n    * tests/locale_test.c\n    Add a wchar_test() to test sf_wchar_open().\n\n2009-09-25  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/common.h src/*.c\n    Split file stuff into PSF_FILE struct within the SF_PRIVATE struct.\n\n2009-09-23  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/aiff.c src/voc.c\n    When a byte is needed, use unsigned char.\n\n    * src/ima_oki_adpcm.c src/broadcast.c src/test_ima_oki_adpcm.c\n    Include sfconfig.h to prevent compile errors with MinGW compilers.\n\n    * configure.ac\n    Remove AM_CONFIG_HEADER due to warnings from autoconf 2.64.\n\n    * tests/locale_test.c\n    Update to work with xx_XX.UTF-8 style locales. Refactoring.\n\n2009-09-22  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.ac\n    Set __USE_MINGW_ANSI_STDIO to 1 when compiling using MinGW compilers.\n    Remove unneeded AC_SUBST.\n    Report Host CPU/OS/vendor.\n\n2009-09-19  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.c\n    Fix error message string.\n\n    * src/flac.c\n    Add 88200 to the list of supported sample rates.\n\n    * src/ogg.c\n    Fix compiler warning when using gcc-4.5.0.\n\n    * programs/sndfile-info.c tests/utils.tpl\n    Remove WIN32 snprintf #define.\n\n    * src/ima_adpcm.c\n    Fix minor bug in aiff_ima_encode_block. Thanks to Denis Fileev for finding\n    this.\n\n2009-09-16  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/caf.c\n    Use the correct C99 format specifier for int64_t.\n\n    * M4/endian.m4\n    Fix detection of CPU endian-ness when cross compiling. Thanks to Pierre\n    Ossman for the bug report.\n\n    * src/caf.c src/sndfile.c\n    Fix reading and writing of PEAK chunks in CAF files.\n\n    * tests/peak_chunk_test.c tests/test_wrapper.sh.in\n    Run peak_chunk_test on CAF files.\n\n2009-09-15  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/aiff.c src/wav.c\n    Use the correct C99 format specifier for int64_t.\n\n2009-08-30  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/rf64.c src/sndfile.c src/wav.c src/wav_w64.h\n    Apply a patch (massaged slightly) from Uli Franke adding handling of the\n    BEXT chunk in RF64 files.\n\n    * tests/command_test.c\n    Update channel_map_test() function so WAV test passes.\n\n    * src/rf64.c\n    Add channel mapping and ambisonic support.\n\n    * src/sndfile.h\n    Add comments showing correspondance between libsndfile channel map\n    defintiions and those used by Apple and MS.\n\n    Add handling of reading/writing channel map info.\n\n    * tests/command_test.c tests/test_wrapper.sh.in\n    Update channel map tests.\n\n2009-07-29  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/common.h\n    Add function psf_isprint() a replacement for the standard C isprint()\n    function which ignores any locale settings and treats all input as ASCII.\n\n    * src/(aiff|common|rf64|sd2|strings|svx|wav).c\n    Use psf_isprint() instead of isprint().\n\n2009-07-13  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/command.c\n    Add string descriptions for SF_FORMAT_RF64 and SF_FORMAT_MPC2K.\n\n2009-06-30  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * programs/sndfile-play.c\n    Allow use of Open Sound System audio output under FreeBSD.\n\n2009-06-24  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.ac\n    Add patch from Conrad Parker to add --disable-jack.\n\n2009-05-28  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/alaw.c src/float32.c src/htk.c src/pcm.c src/sds.c src/ulaw.c\n    Fix bugs where invalid files can cause a divide by zero error (SIGFPE).\n    Thanks to Sami Liedes for reporting this a Debian bug #530831.\n\n2009-05-26  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/chanmap.[ch]\n    New files for channel map decoding/encoding.\n\n2009-05-25  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.ac src/sndfile.h.in\n    Fix MSVC definition of sf_count_t.\n\n2009-05-24  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/wav_w64.[ch]\n    Add wavex_channelmask to WAV_PRIVATE struct and add a function to convert\n    an array of SF_CHANNEL_MASK_* values into a bit mask for use in WAV files.\n\n    * src/wav.c\n    Add ability to write the channel mask.\n\n2009-05-23  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * programs/sndfile-info.c\n    Add -c command line option to dump the channel map information.\n\n    * src/wav_w64.c\n    Don't bail from parser if channel map bitmask is faulty.\n\n    * src/common.h src/sndfile.c\n    Remove error code SFE_W64_BAD_CHANNEL_MAP which is not needed any more.\n\n    * src/sndfile.c\n    On SFC_SET_CHANNEL_MAP_INFO pass the channel map command down to container's\n    command handler.\n\n2009-05-22  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.h.in src/common.h src/sndfile.c src/wav_w64.c\n    Apply a patch from Lennart Poettering (PulseAudio) to allow reading of\n    channel data in WAV and W64 files.\n    Add a test for the above.\n\n2009-05-20  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/FAQ.html\n    Update the section about pre-compiled binaries for Win64.\n\n2009-05-14  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/common.h src/test_conversions.c\n    Be more careful when including <stdint.h> so compiling on pre-C99 platforms\n    (hello Slowlaris) might actually work.\n\n    * NEWS README doc/*.html\n    Updates for 1.0.20.\n\n2009-04-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/voc.c\n    Fix a bug whereby opening a specially crafted VOC file could result in a\n    heap overflow. Thanks to Tobias Klein (http://www.trapkit.de) for reporting\n    this issue.\n\n    * src/aiff.c\n    Fix potential (heap) buffer overflow when parsing 'MARK' chunk.\n\n2009-04-12  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/stdin_test.c\n    Check psf->error after opening file.\n\n    * src/file_io.c\n    Fix obscure seeking bug reported by Hugh Secker-Walker.\n\n    * tests/utils.tpl\n    Add check of sf_error to test_open_file_or_die().\n\n    * src/sndfile.c\n    Clear error if opening resource fork fails.\n\n2009-04-11  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/alaw_test.c tests/locale_test.c tests/ulaw_test.c\n    Cleanup output.\n\n2009-03-25  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/float32.c\n    Fix f2s_clip_array.\n\n2009-03-24  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/float32.c\n    In host_read_f2s call convert instead of f2s_array.\n\n    * src/ima_adpcm.c\n    Remove dead code.\n\n    * src/test_ima_oki_adpcm.c examples/generate.c tests/dither_test.c\n        tests/dwvw_test.c tests/fix_this.c tests/generate.c\n        tests/multi_file_test.c\n    Minor fixes.\n\n2009-03-23  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * M4/shave.m4 shave.in\n    Pulled update from upstream.\n\n2009-03-19  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * doc/api.html\n    Add pointers to example programs in source code tarball.\n\n2009-03-17  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/common.h\n    Define SF_PLATFORM_S64 for non-gcc compilers with 'long long' type.\n\n    * configure.ac\n    Add documentation for --disable-external-libs and improve error handling\n    for that option.\n\n    * src/sndfile.c src/sndfile.h.in src/create_symbols_file.py\n    Add public function sf_version_string.\n\n    * tests/sfversion.c\n    Test function sf_version_string.\n\n    * M4/shave.m4 shave-libtool.in shave.in\n    Add new files from 'git clone git://git.lespiau.name/shave'.\n\n    * configure.ac\n    Enable shave.\n\n    * src/Makefile.am src/binheader_writef_check.py Octave/*\n    Shave related tweaks.\n\n2009-03-15  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/common.h src/caf.c src/sndfile.c\n    Add SF_MAX_CHANNELS (set to 256) and use it.\n\n    * src/sndfile.h.in\n    Check for either _MSCVER or _MSC_VER being defined.\n\n2009-03-04  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/vorbis_test.c\n    Relax test slighly to allow test to pass on more CPUs etc.\n\n2009-03-03  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.ac\n    Detect vorbis_version_string() correctly.\n\n2009-03-02  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * doc/index.html\n    Add a 'See Also' section with a link to sndfile-tools.\n\n    * NEWS README doc/*.html\n    Updates for 1.0.19 release.\n\n    * configure.ac\n    Fix --enable-external-libs logic.\n\n2009-03-01  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/aiff.c\n    Fix resource leak and potential read beyond end of buffer.\n\n    * src/nist.c\n    Fix reading of header value sample_n_bytes.\n\n    * src/sd2.c src/wav.c\n    Fix potential read beyond end of buffer.\n\n    * src/sndfile.c src/svx.c\n    Check return values of file_io functions.\n\n    * tests/win32_test.c\n    Fix resource leak.\n\n    * configure.ac\n    Detect the presence/absence of vorbis_version_string() in libvorbis.\n\n    * src/ogg.c\n    Only call vorbis_version_string() from libvorbis if present.\n\n2009-02-24  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/win32_test.c\n    Don't use sprintf, even on windows.\n\n    * src/aiff.c src/rf64.c src/wav.c\n    Eliminate dead code, more validation of data read from file.\n\n2009-02-22  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/ima_adpcm.c\n    Clamp values to a valid range before indexing ima_step_size array.\n\n    * src/GSM610/*.c tests/*c programs/*.c src/audio_detect.c\n    Don't include un-needed headers.\n\n    * programs/sndfile-info.c\n    Remove dead code.\n\n    * tests/test_wrapper.sh.in\n    Add 'set -e' so the script exits on error.\n\n    * src/test_ima_oki_adpcm.c\n    Fix read beyond end of array.\n\n    * tests/win32_test.c\n    Add missing close on file descriptor.\n\n    * src/nist.c programs/sndfile-metadata-set.c\n    Fix 'unused variable' warnings.\n\n    * src/aiff.c\n    Fix potential memory leak in handling of 'MARK' chunk.\n    Remove un-needed test (unsigned > 0).\n\n    * src/sd2.c\n    Improve handling of heap allocated buffer.\n\n    * src/sndfile.c\n    Remove un-needed test (always true).\n\n    * src/wav.c src/rf64.c\n    Ifdef out dead code that will be resurected some time in the future.\n\n    * src/wav.c src/w64.c src/xi.c\n    Handle error return values from psf_ftell.\n\n    * src/wav_w64.c\n    Fix handling and error checking of MSADPCM coefficient arrays.\n\n    * regtest/*.c\n    Bunch of fixes.\n\n    * src/test_file_io.c\n    Use snprintf instead of strncpy in test program.\n\n2009-02-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sd2.c\n    Validate data before using.\n\n    * src/caf.c\n    Validate channels per frame value before using, fixing a possible integer\n    overflow bug, leading to a possible heap overflow. Found by Alin Rad Pop of\n    Secunia Research (CVE-2009-0186).\n\n2009-02-20  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * Octave/octave_test.sh\n    Unset TERM environment variable and export LD_LIBRARY_PATH.\n\n2009-02-16  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/file_io.c\n    In windows code, cast LPVOID to 'char*' in printf.\n\n2009-02-15  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * M4/octave.m4\n    Clear the TERM environment before evaluating anything in Octave. This works\n    around problems that might occur if a users TERM settings are incorrect.\n    Thanks to Rob Til Freedmen for helping to debug this.\n\n    * src/wav.c\n    Handle four zero bytes as a marker within a LIST or INFO chunk.\n    Thanks to Rogério Brito for supplying an example file.\n\n2009-02-14  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/common.h src/*.c\n    Use C99 snprintf everywhere.\n\n2009-02-11  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/test_wrapper.sh.in\n    New file to act as the template for the test wrapper script.\n\n    * configure.ac\n    Generate tests/test_wrapper.sh from the template.\n\n    * tests/Makefile.am\n    Replace all tests with a single invocation of the test wrapper script.\n\n2009-02-09  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/ogg.c\n    Record vorbis library version string.\n\n    * configure.ac\n    Require libvorbis >= 1.2.2.\n\n    * M4/endian.m4\n    Fix bracketing of function for autoconf 2.63. Thanks to Richard Ash.\n\n    * M4/octave.m4 M4/mkoctfile_version.m4\n    Clean up AC_WITH_ARG usage using AC_HELP_STRING.\n\n2009-02-08  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * Octave/Makefile.am\n    Use $(top_buildir) instead of $(builddir) which may not be defined.\n\n    * M4/octave.m4\n    Improve logic and status reporting.\n\n2009-02-07  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.ac  AUTHORS NEWS README doc/*.html\n    Final tweaks for 1.0.18 release.\n\n2009-02-03  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * programs/sndfile-convert.c\n    Add 'htk' to the list of convert formats.\n\n    * programs/sndfile-info.c\n    Simplify get_signal_max using SFC_CALC_SIGNAL_MAX command.\n    Increase size of files for which signal max will be calculated.\n\n2009-01-14  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * doc/index.html\n    Fix links for SoX and WavPlay. Thanks to Daniel Griscom.\n\n2009-01-11  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * programs/sndfile-metadata-get.c\n    Make valgrind clean.\n    Clean up temp string array usage.\n    Error out if trying to update coding history in RDWR mode.\n\n2009-01-10  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * doc/index.html\n    Fix links to versions of the LGPL.\n\n2008-12-14  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/string_test.c\n    Add test for RDWR mode where the file ends up shorter than when it was\n    opened.\n\n    * src/wav.c\n    Truncate the file on close for RDWR mode where the file ends up shorter\n    than when it was opened.\n\n2008-11-30  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * M4/add_cflags.m4\n    Fix problem with quoting of '#include'.\n\n    * M4/add_cxxflags.m4 configure.ac\n    Add new file M4/add_cxxflags.m4 and use it in configure.ac.\n\n2008-11-19  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * programs/sndfile-info.c\n    Apply patch from Conrad Parker to calculate and display total duration when\n    more than one file is dumped.\n\n2008-11-10  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.ac src/Makefile.am\n    Tweaks to generation of Symbols files.\n\n    * tests/win32_ordinal_test.c\n    Update tests for above changes.\n\n2008-11-06  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * programs/common.c\n    When merging broadcast info, make sure to clear the destination field\n    before copying in the new data.\n\n    * programs/test-sndfile-metadata-set.py\n    Add test for the above.\n\n    * src/broadcast.c\n    Fix checking of required coding_history_size.\n\n2008-10-28  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/command_test.c\n    Add test to detect if coding history is truncated.\n\n    * src/broadcast.c\n    Fix truncation of coding history.\n\n2008-10-27  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/command_test.c\n    Add broadcast_coding_history_size test.\n\n    * programs/*.[ch]\n    Use SF_BROADCAST_INFO_VAR to manipulate larger 'bext' chunks.\n\n    * src/rf64.c\n    Add code to prevent infinite loop on malformed file.\n\n    * src/common.h src/sndfile.c src/w64.c src/wav_w64.c\n    Rationalize and improve error handling when parsing 'fmt ' chunk.\n\n    * M4/octave.m4\n    Simplify and remove cruft.\n    Check for correct Octave version.\n\n    * Octave/*\n    Reduce 3 C++ files to one, fix build for octave 3.0, fix build.\n\n    * Octave/sndfile.cc Octave/PKG_ADD\n    Add Octave function sfversion which returns the libsndfile version that the\n    module is linked against.\n\n    * Octave/Makefile.am\n    Bunch of build and 'make distcheck' fixes.\n\n2008-10-26  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * programs/common.c\n    Return 1 if SFC_SET_BROADCAST_INFO fails.\n\n    * programs/test-sndfile-metadata-set.py\n    Update for new programs directory, exit on any error.\n\n    * tests/error_test.c\n    Fix failure behaviour in error_number_test.\n\n    * src/common.h src/sndfile.c\n    Add error number SFE_BAD_BROADCAST_INFO_SIZE.\n\n    * src/*\n    Reimplement handling of broadcast extentioon chunk in WAV/WAVEX files.\n\n    * src/broadcast.c\n    Fix generation of added coding history.\n\n2008-10-25  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * programs/sndfile-metadata-get.c programs/sndfile-info.c\n    Exit with non-zero on errors.\n\n2008-10-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * examples/sndfile-to-text.c examples/Makefile.am\n    Add a new example program and hook it into the build.\n\n    * examples/ programs/\n    Add a new directory programs and move sndfile-info, sndfile-play and other\n    real programs to the new directory, leaving example programs where they\n    were.\n\n2008-10-20  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/Makefile.am\n    Automake 1.10 MinGW cross compiling fixes.\n\n2008-10-19  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * examples/sndfile-play.c\n    Remove call to deprecated function snd_pcm_sw_params_get_xfer_align.\n    Fix gcc-4.3 compiler warnings.\n\n    * tests/command_test.c\n    Fix a valgrind warning.\n\n    * tests/error_test.c tests/multi_file_test.c tests/peak_chunk_test.c\n        tests/pipe_test.tpl tests/stdio_test.c tests/win32_test.c\n    Fix gcc-4.3 compiler warnings.\n\n2008-10-17  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/broadcast.c\n    Fix termination of desitination string in strncpy_crlf.\n    When copying BROADCAST_INFO chunk, make sure destination gets correct line\n    endings.\n\n    * examples/common.c\n    Fix copying of BROADCAST_INFO coding_history field.\n\n2008-10-13  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/command_test.c\n    Add test function instrument_rw_test, but don't hook it into the testing\n    yet.\n\n    * src/common.h src/command.c src/sndfile.c src/flac.c\n    Error code rationalization.\n\n    * src/common.h src/sndfile.c\n    Set psf->error to SFE_CMD_HAS_DATA when adding metadata via sf_command()\n    fails due to psf->have_written being true.\n\n    * doc/command.html\n    Document the SFC_GET/SET_BROADCAST_INFO comamnds.\n\n2008-10-10  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/command_test.c\n    Improve error reporting when '\\0' is found in coding history.\n    Fix false failure.\n\n2008-10-09  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/broadcast.c\n    Convert all coding history line endings to \\r\\n.\n\n    * tests/command_test.c\n    Add test to make sure all line endings are converted to \\r\\n.\n\n2008-10-08  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/broadcast.c\n    Changed the order of coding history fields.\n\n    * tests/command_test.c\n    Update bextch test to cope with previous change.\n\n    * examples/common.c\n    Add extra length check when copying broadcast info data.\n\n2008-10-05  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/utils.tpl tests/pcm_test.tpl\n    Update check_file_hash_or_die to use 64 bit hash.\n\n    * tests/checksum_test.c tests/Makefile.am\n    Add new checksum_test specifically for lossy compression of headerless\n    files.\n\n2008-10-04  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/gsm610.c\n    Seek to psf->dataoffset before decoding first block.\n\n    * src/sndfile.c\n    Fix detection of mpc2k files on big endian systems.\n\n2008-10-03  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/broadcast.c\n    Use '\\r\\n' newlines in Coding History as required by spec.\n\n2008-10-02  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/test_conversions.c\n    Use int64_t instead of 'long long'.\n\n2008-10-01  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * examples/sndfile-metadata-set.c\n    Remove --bext-coding-history-append command line option because it didn't\n    really make sense.\n\n    * examples/sndfile-metadata-(get|set).c\n    Add usage messages.\n\n    * examples/test-sndfile-metadata-set.py\n    Start work on test coding history.\n\n2008-09-30  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * README doc/win32.html\n    Bring these up to date.\n\n    * src/aiff.c\n    Fix parsing of REX files.\n\n2008-09-29  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/file_io.c\n    Use intptr_t instead of long for return value of _get_osfhandle.\n\n    * src/test_conversions.c src/test_endswap.tpl\n    Fix printing of int64_t values.\n\n    * examples/sndfile-play.c\n    Fix win64 issues.\n\n    * tests/win32_ordinal_test.c\n    Fix calling of GetProcAddress with ordinal under win64.\n\n    * tests/utils.tpl\n    Fix win64 issues.\n\n2008-09-25  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * examples/*\n    Rename copy_data.[ch] to common.[ch]. Fix build.\n    Move code from sndfile-metadata-set.c to common.c.\n\n    * examples/Makefile.am tests/Makefile.am regtest/Makefile.am\n    Clean paths.\n\n2008-09-19  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * doc/tutorial.html doc/Makefile.am\n    Add file doc/tutorial.html and hook into build/dist system.\n\n2008-09-14  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * examples/sndfile-metadata-set.c\n    Clean up handling of bext command line params.\n\n2008-09-13  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/w64.c\n    Add handling/skipping of a couple of new chunk types.\n\n2008-09-09  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.ac\n    Add -funsigned-char to CFLAGS if the compiler supports it.\n\n    * examples/sndfile-metadata-(get|set).c\n    Add handling for more metadata types.\n\n2008-09-04  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/common.h\n    Add macros SF_CONTAINER, SF_CODEC and SF_ENDIAN useful for splitting format\n    field of SF_INFO into component parts.\n\n    * src/*.c\n    Use new macros everywhere it is appropriate.\n\n2008-09-02  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * examples/sndfile-bwf-set.c\n    Massive reworking.\n\n2008-08-24  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * examples/sndfile-bwf-set.c\n    Add --info-auto-create-date command line option.\n\n    * examples/sndfile-metadata-set.c examples/sndfile-metadata-get.c\n        examples/Makefile.am examples/test-sndfile-bwf-set.py\n    Rename sndfile-bwf-(set|get).c to sndfile-metadata-(set|get).c.\n    Change command line args.\n\n2008-08-23  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/wav.c\n    Allow 'PAD ' chunk to be modified in RDWR mode.\n\n    * src/sndfile.h.in src/sndfile.c\n    Add handling (incomplete) for SFC_SET_ADD_HEADER_PAD_CHUNK.\n\n    * tests/Makefile.am tests/write_read_test.tpl tests/header_test.tpl\n        tests/misc_test.c\n    Add tests for RF64.\n\n    * src/rf64.c\n    Fixes to make sure all tests pass.\n\n    * tests/Makefile.am tests/string_test.c\n    Add string tests (not yet passing).\n\n2008-08-22  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/rf64.c\n    First pass at writing RF64 now working.\n\n2008-08-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * examples/sndfile-convert.c\n    Add SF_FORMAT_RF64 to format_map.\n\n    * src/common.h src/sndfile.c\n    More RF64 support code.\n\n    * examples/sndfile-bwf-set.c\n    Fix the month number in autogenerated date string and use hypen in date\n    instead of slash.\n\n    * examples/test-sndfile-bwf-set.py\n    Update tests.\n\n    * examples/sndfile-info.c\n    When called with -i or -b option, operate on all files on command line, not\n    just the first.\n\n2008-08-19  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/rf64.c\n    New file to handle RF64 (WAV like format supportting > 4Gig files).\n\n    * src/sndfile.h.in src/common.h src/sndfile.c src/Makefile.am\n    Hook the above into build so hacking can begin.\n\n    * src/pcm.c\n    Improve log message when pcm_init fails.\n\n    * src/sndfile-info.c\n    Only calculate and print 'Signal Max' if file is less than 10 megabytes in\n    length.\n\n2008-08-18  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/string_test.c\n    Polish string_multi_set_test.\n\n    * src/wav.c\n    In RDWR mode, pad the header if necessary (ie LIST chunk has moved or\n    length has changed).\n    Minor fixes in wav_write_strings.\n    Write PAD chunk with default endian-ness, not a specific endian-ness.\n\n    * examples/test-sndfile-bwf-set.py\n    Add Python script to test sndfile-bwf-set/get.\n\n    * examples/sndfile-bwf-set.c\n    Clean up and fixes.\n\n    * src/wav.c\n    Merge function wavex_write_header into wav_write_header, deleting about 70\n    lines of code.\n\n    * src/common.h\n    Double value of SF_MAX_STRINGS.\n\n    * tests/string_test.c\n    Add string tests for WAVEX and RIFX files.\n\n    * tests/command_test.c\n    Add broadcast test for WAVEX files.\n\n2008-08-17  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/string_test.c\n    Add a new string_rdwr_test (currently failing for WAV).\n    Add a new string_multi_set_test (currently failing).\n\n    * tests/command_test.c\n    Add new broadcast_rdwr_test (currently failing).\n\n    * src/wav.c\n    Fix to WAV parser to allow 'bext' chunk to be updated in place.\n    In wav_write_tailer, seek to psf->dataend if its greater than zero.\n\n    * src/sndfile.c\n    Make sure psf->have_written gets set correctly in mode SFM_RDWR.\n\n    * configure.ac\n    Test for <sys/time.h> and gettimeofday.\n\n    * src/common.c\n    Use gettimeofday() to initialize psf_rand_int32.\n\n    * src/common.h src/sndfile.c\n    Add unique_id field to SF_PRIVATE struct.\n\n    * src/common.h src/sndfile.c src/wav.c src/wav_w64.[ch]\n    Move wavex_ambisonic field from SF_PRIVATE struct to WAV_PRIVATE struct.\n\n    * src/common.h src/strings.c\n    Add function psf_location_string_count.\n\n2008-08-16  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.ac\n    Test for localtime and localtime_r.\n\n    * examples/sndfile-convert.c\n    In function copy_metadata(), copy broadcast info if present.\n\n    * examples/copy_data.[ch] examples/Makefile.am\n    Break some functionality out of sndfile-convert.c so it can be used in\n    examples/sndfile-bwf-set.c.\n\n    * tests/utils.tpl\n    Add new function create_short_sndfile().\n\n    * examples/sndfile-bwf-set.c examples/sndfile-bwf-get.c\n        examples/Makefile.am\n    Add new files and hook into build.\n\n2008-08-11  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.h.in\n    Fix comments. Patch from Mark Glines.\n\n2008-07-30  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/misc_test.c\n    Use zero_data_test on Ogg/Vorbis files.\n\n    * src/ogg.c\n    Fix segfault when closing an Ogg/Vorbis file that has been opened for write\n    but had no actual data written to it. Bug reported by Chinoy Gupta.\n\n    * tests/Makefile.am\n    Make sure to run mist_test on Ogg/Vorbis files.\n\n2008-07-19  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * regtest/Makefile.am\n    Use SQLITE3_CFLAGS to locate sqlite headers.\n\n2008-07-10  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * doc/index.html doc/FAQ.html\n    Add notes about which versions of windows libsndfile works on.\n\n2008-07-03  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/misc_test.c\n    Add a test for correct handling of Ambisonic files. Thanks to Fons\n    Adriaensen for the test.\n\n    * src/wav.c src/wav_w64.c\n    Fix handling of Ambisonic files. Thanks to Fons Adriaensen for the patch.\n\n2008-06-29  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.ac\n    Fix detection/enabling of external libs.\n\n    * M4/extra_pkg.m4 M4/Makefile.am\n    Add m4 macro PKG_CHECK_MOD_VERSION which is a hacked version\n    PKG_CHECK_MODULES. The new macro prints the version number of the package\n    it is searching for.\n\n2008-06-14  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/aiff.c\n    Apply a fix from Axel Röbel where if the second loop in the instrument\n    chunk is none, the loop mode is written into the first loop.\n\n2008-05-31  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/test_float.c src/test_main.(c|h) src/Makefile.am\n    Add new file to test functions float32_(le|be)_(read|write) and\n    double64_(le|be)_(read|write). Hook into build and testsuite.\n\n    * src/double64.c src/float32.c\n    Fix bugs in functions found by test added above. Thanks to Nicolas Castagne\n    for reporting this bug.\n\n    * src/sndfile.h.in\n    Change time_reference_(low|high) entries of SF_BROADCAST_INFO struct to\n    unsigned.\n\n    * examples/sndfile-info.c\n    Print out the BEXT time reference in a sensible format.\n\n2008-05-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/*.c\n    Fuzz fixes.\n\n    * src/ogg.c\n    Add call to ogg_stream_clear to fix valgrind warning.\n\n    * src/aiff.c\n    Fix x86_64 compile issue.\n\n    * configure.ac src/Makefile.am src/flac.c src/ogg.c\n    Link to external versions of FLAC, Ogg and Vorbis.\n\n    * tests/lossy_comp_test.c tests/ogg_test.c tests/string_test.c\n        tests/vorbis_test.c tests/write_read_test.tpl\n    Fix tests when configured with --disable-external-libs.\n\n    * tests/external_libs_test.c tests/Makefile.am\n    Add new test and hook into build and test suite.\n\n    * src/command.c\n    Use HAVE_EXTERNAL_LIBS to ensure that the SFC_GET_FORMAT_* commands return\n    the right data when external libs are disabled.\n\n2008-05-11  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/write_read_test.tpl\n    Add a test for extending a file during write by seeking past the current\n    end of file.\n\n    * src/sndfile.c\n    Allow seeking past end of file during write.\n\n2008-05-10  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * doc/api.html doc/command.html\n    Move all information about the sf_command function to command.html and add\n    a link from documentation of the sf_read/write_raw function to the\n    SFC_RAW_NEEDS_ENDSWAP command.\n\n    * doc/index.html doc/FAQ.html doc/libsndfile.css\n    Minor documentation tweaks.\n\n2008-05-09  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.ac\n    Add AM_PROG_CC_C_O.\n\n2008-04-27  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/error_test.c\n    Add a test to make sure if file opened with sf_open_fd, and then the file\n    descriptor is closed, then sf_close will return an error code. Thanks to\n    Dave Flogeras for the bug report.\n\n    * src/sndfile.c\n    Make sf_close return an error is the file descriptor is already closed.\n\n2008-04-19  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.ac\n    Set object format to aout for OS/2. Thanks to David Yeo.\n\n    * src/mpc2k.c src/sndfile.c src/sndfile.h.in src/common.h src/Makefile.am\n    Add ability to read MPC 2000 file.\n\n    * tests/write_read_test.tpl tests/misc_test.c tests/header_test.tpl\n        tests/Makefile.am\n    Add tests for MPC 2000 file format.\n\n    * examples/sndfile-convert.c\n    Allow conversion to MPC 2000 file format.\n\n2008-04-17  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/VORBIS/lib/codebook.c\n    Sync from upstream SVN.\n\n    * autogen.sh configure.ac\n    Minor tweaks.\n\n2008-04-13  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/ogg.c\n    Add a patch that fixes finding the length in samples of an Ogg/Vorbis file.\n    The patch as supplied segfaulted and required many hours of debugging.\n\n    * src/OGG/bitwise.c\n    Sync from upstream SVN.\n\n2008-04-09  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/aiff.c\n    Fix up handling of 'APPL' chunk. Thanks to Axel Röbel for bringing up\n    this issue.\n\n2008-04-06  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/*.c\n    Add calls to sf_close() where needed.\n\n    * tests/utils.tpl tests/multi_file_test.c\n    Always pass 0 as the third argument to open when OS_IS_WIN32.\n\n2008-04-03  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/test_*\n    Add files test_main.[ch].\n    Collapse all tests into a single executable.\n\n2008-03-30  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/FLAC\n    Sync to upstream CVS.\n\n2008-03-25  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/common.h\n    Make SF_MIN and SF_MAX macros MinGW friendly.\n\n    * examples/sndfile-(info|play).c\n    Use Sleep function from <windows.h> instead of _sleep.\n\n    * tests/locale_test.c\n    Disable some tests when OS_IS_WIN32.\n\n    * src/FLAC/src/share/replaygain_anal/replaygain_analysis.c\n        src/FLAC/src/share/utf8/utf8.c\n    MinGW fixes.\n\n2008-03-11  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * doc/FAQ.html\n    Tweaks to pcm16 <-> float conversion answer.\n\n2008-02-10  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/OGG\n    Sync to SVN upstream.\n\n    * Makefile.am\n    Add 'DISTCHECK_CONFIGURE_FLAGS = --enable-gcc-werror'.\n\n2008-02-05  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * examples/sndfile-jackplay.c\n    Minor tweaks to warning message printed when compiled without libjack.\n\n2008-01-27  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/peak_chunk_test.c\n    Improve read_write_peak_test to find more errors. Inspired by example\n    provided by Nicolas Castagne.\n\n    * src/aiff.c\n    Another SFM_RDWR fix shown up by above test.\n\n2008-01-24  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/aiff.c\n    Fix reading of COMM encoding string.\n\n    * src/chunk.c src/common.h src/Makefile.am\n    New file for storing and retrieving info about header chunks. Hook into\n    build.\n\n    * src/aiff.c\n    Use new chunk logging to fix problem with AIFF in RDWR mode.\n\n2008-01-22  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/command.c\n    Add WVE to the list of major formats.\n\n    * tests/aiff_rw_test.c\n    Fix error reporting.\n\n2008-01-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/common.[ch]\n    Add internal functions str_of_major_format, str_of_minor_format,\n    str_of_open_mode and str_of_endianness.\n\n    * tests/write_read_test.tpl\n    Fix reporting of errors in new_rdwr_XXXX_test.\n\n2008-01-20  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * examples/sndfile-play.c\n    Apply patch from Yair K. to fix compiles with OSS v4.\n\n    * src/common.h src/float32.c src/double64.c\n    Rename psf->float_enswap to psf->data_endswap.\n\n    * src/sndfile.h.in src/sndfile.c src/pcm.c\n    Add command SFC_RAW_NEEDS_ENDSWAP.\n\n    * tests/command.c\n    Add test for SFC_RAW_NEEDS_ENDSWAP.\n\n    * doc/command.html\n    Document SFC_RAW_NEEDS_ENDSWAP.\n\n    * tests/peak_chunk_test.c\n    Add test function read_write_peak_test. Thanks to Nicolas Castagne for the\n    bug report.\n\n2008-01-09  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * examples/sndfile-cmp.c\n    Add new example program contributed by Conrad Parker.\n\n    * examples/Makefile.am\n    Hook into build.\n\n    * doc/development.html\n    Change use or reconfigure.mk to autogen.sh.\n\n2008-01-08  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/win32_test.c\n    Add another win32 test.\n\n    * tests/util.tpl\n    Add function file_length_fd which wraps fstat.\n\n    * tests/Makefile.am\n    Run the multi_file_test on AU files.\n\n    * tests/multi_file_test.c\n    Use function file_length_fd() instead of file_length() to overcome stupid\n    win32 bug. Fscking hell Microsoft sucks so much.\n\n2008-01-05  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sd2.c\n    Fix a rsrc parsing bug. Example file supplied by Uli Franke.\n\n2007-12-28  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * doc/index.html\n    Allow use of either LGPL v2.1 or LGPL v3.\n\n    * tests/header_test.tpl\n    Add header_shrink_test from Axel Röbel.\n\n    * src/wav.c\n    Add fix from Axel Röbel for writing files with float data but no peak\n    chunk (ie peak chunk gets removed after the file is opened).\n\n    * src/aiff.c tests/header_test.tpl\n    Apply similar fix to above for AIFF files.\n\n    * src/wav.c tests/header_test.tpl\n    Apply similar fix to above for WAVEX files.\n\n    * src/command.c\n    Add Ogg/Vorbis to 'get format' commands.\n\n2007-12-16  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/ogg.c\n    Fix seeking on multichannel Ogg Vorbis files. Reported by Bodo.\n    Set the default encoding quality to 0.4 instead of 4.0 (Bodo again).\n\n    * tests/ogg_test.c\n    Add stereo seek tests.\n\n2007-12-14  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/ogg_test.c\n    Add a test (currently failing) for stereo seeking on Ogg Vorbis files. Test\n    case supplied by Bodo.\n\n    * tests/utils.(def|tpl)\n    Add compare_XXX_or_die functions.\n\n2007-12-05  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/aiff.c\n    Fix a bug where ignoring ssnd_fmt.offset and ssnd_fmt.blocksize caused\n    misaligned reading of 24 bit data. Thanks to Uli Franke for reporting this.\n\n2007-12-03  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/vox_adpcm.c src/ima_oki_adpcm.[ch] src/Makefile.am\n    Merge in code from the vox-patch branch. Thanks to Robs for the patch\n    which fixes a long standing bug in the VOX codec.\n\n2007-12-01  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * examples/sndfile-convert.c\n    Fix handling of -override-sample-rate=X option.\n\n2007-11-25  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/ogg.c src/VORBIS\n    Merge in Ogg Vorbis support from John ffitch of the Csound project.\n\n2007-11-24  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.c\n    Recognise files with 'vox6' extension as 6kHz OKI VOX ADPCM files. Also\n    recognise 'vox8' as and 'vox' as 8kHz files.\n\n    * configure.ac\n    Detect libjack (JACK Audio Connect Kit).\n\n    * examples/sndfile-jackplay.c examples/Makefile.am\n    Add new example program to play sound files using the JACK audio server.\n    Thanks to Jonatan Liljedahl for allowing this to be included.\n\n2007-11-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * doc/index.html\n    Update support table with SD2 and FLAC.\n\n2007-11-17  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.c\n    Fix calculation of internal value psf->read_current when attempting to read\n    past end of audio data.\n    Remove redundant code.\n\n    * tests/lossy_comp_test.c\n    Add read_raw_test to check that raw reads do not go past the end of the\n    audio data section.\n    Clean up error output messages.\n\n    * src/sndfile.c\n    Add code to prevent sf_read_raw from reading past the end of the audio data.\n\n    * tests/Makefile.am\n    Add the wav_pcm lossy_comp_test.\n\n2007-11-16  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.ac src/Makefile.am src/create_symbols_file.py\n    More OS/2 fixes from David Yeo.\n\n2007-11-12  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/file_io.c tests/utils.tpl tests/benchmark.tpl\n    Improve handling of requirements for O_BINARY as suggested by Ed Schouten.\n\n2007-11-11  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/common.h\n    Fix symbol class when SF_MIN is nested inside SF_MAX or vice versa.\n\n    * src/create_symbols_file.py\n    Add support for OS/2 contributed by David Yeo.\n\n2007-11-05  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * M4/gcc_version.m4\n    Add macro AC_GCC_VERSION to detect GCC_MAJOR_VERSION and GCC_MINOR_VERSION.\n\n    * configure.ac\n    Use AC_GCC_VERSION to work around gcc-4.2 inline warning stupidity.\n    See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=33995\n    Use -fgnu-inline to prevent stupid warnings.\n\n2007-11-03  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/util.tpl\n    Increase the printing width for print_test_name().\n\n    * tests/command_test.c tests/Makefile.am\n    Add tests for correct updating of broadcast WAV coding history.\n\n    * examples/sndfilehandle.cc examples/Makefile.am\n    Add example program using the C++ SndfileHandle class.\n\n2007-10-29  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/common.h src/sndfile.c\n    Add error codes SFE_ZERO_MAJOR_FORMAT and SFE_ZERO_MINOR_FORMAT.\n\n2007-10-26  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sd2.c\n    Identify sample-rate/sample-size/channels by resource id.\n\n2007-10-25  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/broadcast.c src/common.h src/sndfile.c\n    Improvements to handling of broadcast info in WAV files. Thanks to Frederic\n    Cornu and other for their input.\n\n2007-10-24  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/FLAC/include/share/alloc.h\n    Mingw fix for SIZE_T_MAX from Uli Franke.\n\n2007-10-23  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/open_fail_test.c tests/error_test.c tests/Makefile.am\n    Move tests from open_fail_test.c to error_test.c and remove the former.\n\n2007-10-22  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/scale_clip_test.(def|tpl)\n    Add tests for SFC_SET_INT_FLOAT_WRITE command.\n\n    * doc/command.html\n    Add docs for SFC_SET_INT_FLOAT_WRITE command.\n\n    * examples/sndfile-play.c tests/dft_cmp.c\n    Fix gcc-4.2 warning messages.\n\n2007-10-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.h.in src/sndfile.c\n    Add command SFC_GET_CURRENT_SF_INFO.\n\n    * src/sndfile.h.in src/sndfile.c src/create_symbols_file.py\n    Remove function sf_get_info (only ever in pre-release code).\n\n    * tests/command_test.c\n    Add test for SFC_GET_CURRENT_SF_INFO.\n\n2007-10-15  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/wav.c\n    Add parsing of 'exif' chunks. Originally coded by Trent Apted.\n\n    * configure.ac\n    Put config stuff in Cfg directory.\n    Remove check for inttypes.h.\n\n2007-10-10  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/w64.c\n    Fix writing of 'riff' chunk length and check for correct value in parser.\n\n2007-09-20  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * doc/index.html\n    Link to MP3 FAQ entry.\n\n2007-09-18  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/flac.c\n    Move the blocksize check to an earlier stage of flac_buffer_copy.\n\n2007-09-12  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/FLAC\n    Huge merge from FLAC upstream.\n\n2007-09-10  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * examples/*.c\n    Change license to all example programs to BSD.\n\n2007-09-08  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/FLAC/include/FLAC/metadata.h\n    Include <sys/types.h> to prevent compile error on OSX.\n\n    * Octave/octave_test.sh\n    Disable test on OSX. Can't get it to work.\n\n    * src/flac.c\n    Check the blocksize returned from the FLAC decoder to prevent buffer\n    overruns. Reported by Jeremy Friesner. Thanks.\n\n2007-09-07  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * Makefile.am M4/octave.m4\n    Fix build when Octave headers are not present.\n\n2007-08-27  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * doc/development.html\n    Add note about bzr repository directory looking empty.\n\n2007-08-26  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.ac Octave/* M4/octave_*\n    Bunch of changes to add ability to build GNU Octave modules to read/write\n    sound files using libsndfile from Octave.\n\n2007-08-23  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * acinclude.m4 configure.ac ...\n    Get rid of acinclude.m4 and replace it with an M4 directory.\n\n2007-08-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.h.in\n    Remove crufty Metrowerks compiler support. Allow header file to be compiled\n    on windows with both GCC and microsoft compiler.\n\n2007-08-19  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/dft_cmp.[ch] tests/floating_point_test.tpl\n    Clean up floating point tests.\n\n2007-08-14  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/aiff.c\n    Fix segfault when COMM chunk length is byte swapped.\n\n2007-08-09  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/common.h src/mat4.c src/mat5.c src/sndfile.c\n    Add a generic SFE_CHANNEL_COUNT_ZERO error, remove format specific errors.\n\n    * src/au.c\n    Fix crash on AU files with zero channel count. Reported by Ben Alison.\n\n2007-08-08  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/voc.c\n    Fix bug in handling file supplied by Matt Olenik.\n\n2007-07-31  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/OGG\n    Merge from OGG upstream sources.\n\n2007-07-25  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/FLAC\n    Merge from FLAC upstream sources.\n\n2007-07-15  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/flac.c\n    Fix memory leak; set copy parameter to FALSE in call to\n    FLAC__metadata_object_vorbiscomment_append_comment.\n\n    * src/common.[ch]\n    Add function psf_rand_int32().\n\n2007-07-14  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/FLAC\n    Merge from FLAC upstream sources.\n\n    * src/strings.c tests/string_test.c tests/Makefile.am\n    Make sure string tests for SF_STR_LICENSE actually works.\n\n2007-07-13  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/string_test.c\n    Add ability to test strings stored in metadata secion of FLAC files.\n\n    * src/string.c\n    Fix logic for testing if audio data has been written and string is added.\n    Make sure SF_STR_ALBUM actually works.\n\n    * src/flac.c\n    Finalize reading/writing string metadata. Tests pass.\n\n    * src/sndfile.h.in tests/string_test.c src/flac.c\n    Add string type SF_STR_LICENSE, update test and use for FLAC files.\n\n    * src/sndfile.h.in\n    Add definition for SFC_SET_SCALE_FLOAT_INT_WRITE command.\n\n    * src/common.h src/double64.c src/float32.c src/sndfile.c\n    Add support for SFC_SET_SCALE_FLOAT_INT_WRITE (still needs testing).\n\n2007-07-12  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/flac.c\n    Apply patch from Ed Schouten to read artist and title metadata from FLAC\n    files.\n    Improve reporting of FLAC metadata.\n\n    * src/sndfile.h.in tests/string_test.c src/flac.c\n    Add string type SF_STR_ALBUM, update test and use for FLAC files.\n\n2007-06-28  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/FLAC/*\n    Merge from upstream CVS.\n\n2007-06-16  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/FLAC/*\n    Update from upstream CVS.\n\n2007-06-14  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/cpp_test.cc\n    Add extra tests for when the SndfileHandle constructor fails.\n\n    * src/sndfile.hh\n    Make sure failure to open the file in the constructor does not allow later\n    calls to other methods to fail.\n\n2007-06-10  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/util.tpl\n    Add function write_mono_file.\n\n    * tests/generate.[ch] tests/Makefile.am\n    Add files generate.[ch] and hook into build.\n\n    * tests/write_read_test.tpl\n    Add multi_seek_test.\n\n    * src/flac.c\n    Fix buffer overflow bug. Test provided by Jeremy Friesner and fix provided\n    by David Viens.\n\n2007-06-07  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * doc/FAQ.html\n    Minor update.\n\n    * configure.ac src/FLAC/src/libFLAC/ia32/Makefile.am src/Makefile.am\n    Apply patch from Trent Apted make it compile on Intel MacOSX. Thanks Trent.\n\n2007-05-28  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/wav.c\n    Fix writing of MSGUID subtypes. Thanks to Bruce Sharpe.\n\n2007-05-22  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/wav.c\n    Fix array indexing bug raised by Bruce Sharpe.\n\n2007-05-12  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/FLAC/src/share/getopt/getopt.c\n    Fix Mac OSX / PowerPC compile warnings.\n\n    * configure.ac\n    Make sure WORDS_BIGENDIAN gets correctly defined for FLAC code.\n\n2007-05-04  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * doc/FAQ.html\n    Add Q/A about MP3 support.\n\n2007-05-03  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * doc/new_file_type.HOWTO\n    Minor updates.\n\n2007-05-02  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/wve.c\n    Fix a couple bad parameters with psf_log_printf.\n\n    * src/pcm.c\n    Improve error reporting.\n\n    * src/common.h src/common.c\n    Constify psf_hexdump.\n\n2007-04-30  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/FLAC\n    Ditch and re-import required FLAC code.\n\n    * configure.ac\n    Force FLAC__HAS_OGG variable to 1.\n\n    * src/FLAC/src/libFLAC/stream_encoder.c\n    Fix compiler warnings.\n\n2007-04-23  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.ac tests/win32_ordinal_test.c\n    Detect if win32 DLL is beging generated and only run win32_ordinal_test if\n    true.\n\n    * src/G72x/Makefile.am src/Makefile.am\n    Use $(EXEEXT) where possible.\n\n2007-04-18  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/wve.c src/common.h src/sndfile.c\n    Complete definition of SfE_WVE_NO_WVE error message.\n\n    * src/wve.c\n    Fix error in files generated on big endian systems. Robustify parsing.\n\n2007-04-16  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/double64.c\n    Fix clipping of double to short conversions on 64 bit systems.\n\n    * src/flac.c regtest/database.c tests/cpp_test.cc\n    Fix compile warnings for 64 bit systems.\n\n2007-04-15  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/wav.c src/wav_w64.c\n    Use audio detect function when 'fmt ' chunk data is suspicious.\n\n    * configure.ac\n    Add ugly hack to remove -Werror from some Makefiles.\n\n2007-04-14  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/GSM610/long_term.c src/macbinary3.c tests/cpp_test.cc\n    Add patch from André Pang to clean up compiles on OSX.\n\n    * src/wve.c src/common.h src/sndfile.c src/sndfile.h.in\n        examples/sndfile-convert.c\n    Merge changes from Reuben Thomas to improve WVE support.\n\n    * tests/lossy_comp_test.c tests/Makefile.am\n    Add tests for WVE files.\n\n2007-04-11  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.hh\n    Add a static SndfileHandle::formatCheck method as suggested by Jorge\n    Jiménez.\n\n2007-04-09  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.c\n    Fixed a bug in sf_error() where the function itself was being compared\n    against zero. Add a check for a NULL return from peak_info_calloc. Fix a\n    possible NULL dereference.\n\n2007-04-07  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/flac.c\n    Turn off seekable flag when writing, return SFE_BAD_RDWR_FORMAT when\n    opening file for RDWR.\n\n    * src/sndfile.c\n    Improve error message for SFE_BAD_RDWR_FORMAT.\n\n    * src/mat4.c\n    Fix array indexing issue. Thanks to Ben Allison (Nullsoft) for alerting me.\n\n2007-03-05  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * doc/FAQ.html\n    Add Q/A 19 on project files.\n\n2007-03-01  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.c\n    Guard agains MacOSX universal binary compiles.\n\n    * doc/FAQ.html\n    Add Q/A 18 and clean up Q3.\n\n2007-02-22  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/aiff.c\n    Add support for 'in24' files.\n\n2007-02-13  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/wav.c src/wav_w64.c src/wav_w64.h\n    Start work towards detecting ausio codec type from the actual audio data.\n\n    * src/audio_detect.c src/test_audio_detect.c\n    Add new file and its unit test.\n\n2007-02-07  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * examples/cooledit-fixer.c examples/Makefile.am\n    Remove old broken example program.\n\n2007-02-06  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.c src/sndfile.h.in src/create_symbols_file.py\n    Add function sf_get_info.\n\n2007-01-25  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * examples/sndfile-play.c\n    For ALSA, use the 'default' device instead of 'plughw:0'.\n\n2007-01-22  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.c\n    Allow writing of WAV/WAVEX 'BEXT' chunks in SFM_RDWR mode.\n\n2007-01-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * doc/development.html doc/embedded_files.html man/sndfile-play.1\n    Minor documentation fixes. Thanks Reuben Thomas.\n\n2006-12-16  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * examples/sndfile-convert.c\n    Add -override-sample-rate command line option.\n\n2006-11-19  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/misc_test.c\n    Force errno to zero at start of some tests.\n\n    * src/sndfile.c\n    Minor clean up of error handling.\n\n    * configure.ac\n    Remove an assembler test which was failing on OSX.\n\n2006-11-15  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/common.h\n    Fix the definition of SF_PLATFORM_S64 for MinGW.\n\n    * src/FLAC/Makefile.am src/FLAC/share/grabbag/Makefile.am\n    Fix path problems for MinGW.\n\n2006-11-13  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sfendian.h\n    Add include guard.\n\n    * src/Makefile.am src/flac.c\n    Clean up include paths.\n\n    * src/test_conversions.c\n    New file to test psf_binheader_readf/writef functions.\n\n    * src/Makefile.am src/test_file_io.c src/test_log_printf.c src/common.c\n    Clean up unit testing.\n\n    * src/common.c\n    Fix a bug reading/writing 64 bit header fields. Thanks to Jonathan Woithe\n    for reporting this.\n\n    * src/test_conversions.c\n    Complete unit test for above fix.\n\n2006-11-11  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.c\n    More refactoring to clean up psf_open_file() and vairous sf_open()\n    functions.\n\n2006-11-09  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/wav.c\n    Apply a patch from Jonathan Woithe to allow opening of (malformed) WAV\n    files of over 4 gigabytes.\n\n2006-11-05  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.c\n    Refactor function psf_open_file() to provide a single return point.\n\n    * tests/misc_test.c\n    Fix permission_test to ensure that read only file can be created.\n\n2006-11-03  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/common.h\n    Add SF_PLATFORM_S64 macro as a platform independant way of doing signed 64\n    bit integers.\n\n    * src/aiff.c src/svx.c src/wav.c\n    Add warning in log if files are larger than 4 gigabytes in size.\n\n2006-11-01  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/FLAC src/OGG confgure.ac src/Makefile.am\n    Pull in all required FLAC and OGG code so external libraries are not\n    needed. This makes compiling on stupid fscking Windoze easier.\n\n2006-10-27  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sd2.c\n    Add workaround for switched sample rate and sample size.\n\n    * src/wav.c\n    Add workaround for excessively long coding history in the 'bext' chunk.\n\n2006-10-23  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.h.in src/sndfile.c src/wav.c doc/command.html\n    Use SF_AMBISONIC_* instead of SF_TRUE/SF_FALSE.\n\n2006-10-22  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.h.in src/wav.c src/wav_w64.c src/common.h doc/command.html\n    Apply a patch from Fons Adriaensen to allow writing on WAVEX Ambisonic\n    files. Still needs a little tweaking before its ready for release.\n\n    * src/*.c\n    Use the UNUSED macro to prevent compiler warnings.\n\n2006-10-19  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/aiff.c\n    Fix a bug in parsing AIFF files with a slightly unusual 'basc' chunk. Thanks\n    to David Viens for providing two example files.\n\n    * src/common.(c|h) src/aiff.c\n    Add a function psf_sanitize_string and use it in aiff.c.\n\n2006-10-18  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/wav_w64.c\n    Apply a patch from Fons Adriaensen which fixes a minor WAVEX GUID issue.\n\n2006-10-17  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/Makefile.am\n    Fix problem related to recent test coverage changes.\n\n2006-10-15  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.ac tests/Makefile.am\n    Add --enable-test-coverage configure option.\n\n2006-10-05  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.hh\n    Add an std::string SndfileHandle constructor.\n\n    * tests/scale_clip_test.tpl\n    Fix the 'make distcheck' target.\n\n2006-10-03  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/double64.c src/float32.c\n    Add optional clipping on float file data to int read data conversions.\n\n    * tests/tests/scale_clip_test.(def|tpl)\n    Add test for above new code.\n\n2006-09-06  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/aiff_rw_test.c\n    Add 'MARK' chunks to make sure they are parsed correctly.\n\n2006-09-05  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/aiff.c\n    Fix parsing of MARK chunks. Many thanks to Sciss for generating files to\n    help debug the problem.\n\n2006-09-02  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/common.h\n    Make the SF_MIN and SF_MAX macros at least partially type safe.\n\n    * tests/lossy_comp_test.c\n    Fix overflow problems when ensuring that signalis not zero.\n\n2006-08-31  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.ac docs/*.html\n    Changes for release 1.0.17.\n\n2006-08-08  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/flac.c\n    Remove inline from functions called by pointer. Thanks to Sampo Savolainen\n    for notifying me of this.\n\n2006-07-31  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.hh\n    Add writeSync method.\n    Add copy constructor and assignment operator (thanks Daniel Schmitt).\n    Add methods readRaw and writeRaw.\n    Make read/write/readf/writef simple overlaods instead of templates (thanks\n    to Trent Apted for suggesting this).\n\n    * tests/cpp_test.cc\n    Cleanup. Add tests.\n\n2006-07-30  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.hh\n    Templatize the read/write/readf/writef methods as suggested by Lars Luthman.\n    Prevent the potential leak of SNDFILE* pointers in the openRead/openWrite/\n    openReadWrite methods.\n    Add const to SF_INFO pointer in Sndfile constructor.\n    Make the destrictor call the close() method.\n\n    * tests/cpp_test.cc\n    Add more tests.\n\n2006-07-29  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/cpp_test.cc\n    Remove the generated file so \"make distcheck\" passes.\n\n    * src/Makefile.am\n    Add sndfile.hh to distributed header files.\n\n    * src/sndfile.hh\n    Change the license for the C++ wrapper to modified BSD.\n\n2006-07-28  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.hh\n    Complete it.\n\n    * tests/cpp_test.cc\n    Add more tests.\n\n2006-07-27  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/utils.tpl\n    Add extern C to generated header file.\n\n    * src/sndfile.hh\n    Work towards completing this.\n\n    * tests/cpp_test.cc tests/Makefile.am\n    Add a C++ test and hook into build.\n\n    * configure.ac\n    Add appropriate CXXFLAGS.\n\n2006-07-26  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.ac\n    Test if compiler supports -Wpointer-arith.\n\n    * src/common.c\n    Fix a warning resulting from -Wpointer-arith.\n\n2006-07-15  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * examples/sndfile-play.c\n    Explicitly set endian-ness as well as setting 16 bit output.\n\n    * examples/sndfile-info.c\n    Make sure to parse info if file fails to open.\n\n    * src/sndfile.c\n    Handle parse error a little better.\n\n    * src/wav_w64.[ch]\n    Minor clean up, add detection of IPP ITU G723.1.\n\n2006-06-23  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.c\n    Make sure psf->dataoffset gets reset to zero when openning headersless\n    files based on the file name extension.\n\n2006-06-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/(command|lossy_comp|pcm|scale_clip)_test.c tests/fix_this.c\n        tests/write_read_test.(tpl|def)\n    Fix gcc-4.1 compiler warnings about \"dereferencing type-punned pointer will\n    break strict-aliasing rules\".\n\n    * examples/cooledit-fixer.c\n    More fixes like above.\n\n2006-06-20  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/file_io.c\n    Fix a windows bug where the syserr string of SF_PRIVATE was not being set\n    correctly.\n\n    * src/sndfile.c\n    Fixed a logic bug in sf_seek(). Thanks to Paul Davis for finding this.\n\n2006-06-04  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.ac\n    Fixed detection of S_IRGRP.\n\n2006-05-30  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * sndfile-convert.c\n    Add conversion SF_INSTRUMENT data when present.\n\n2006-05-22  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * doc/development.html\n    Removed references to tla on windows.\n\n    * src/common.h src/sndfile.c\n    Add separate void pointers for file containter and file codec data to\n    SF_PRIVATE struct. Still need to move all existing fdata pointers.\n\n    * tests/write_read_test.tpl\n    Change the order of some tests.\n\n    * src/aiff.c\n    When writing 'AIFC' files, make sure get an 'FVER' gets added.\n\n    * src/common.h src/(dwvw|flac|g72x|gsm610|ima_adpcm|ms_adpcm|paf|sds).c\n        src/(sndfile|voc|vox_adpcm|xi).c\n    Remove fdata field from SF_PRIVATE struct and replace it with codec_data.\n\n2006-05-10  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * Win32/testprog.c Win32/Makefile.am\n    Add a minimal win32 test program.\n\n    * Win32/README-precompiled-dll.txt Mingw-make-dist.sh\n    Update readme and Mingw build script.\n\n2006-05-09  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.ac acinclude.m4\n    Minor fixes for Solaris.\n\n2006-05-05  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/test_endswap.(def|tpl)\n    Fix printf formatting for int64_t on 64 bit machines.\n\n2006-05-04  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/binhead_check.py\n    New file to check for bad parameters passed to psf_binheader_writef().\n\n    * src/Makefile.am\n    Hook into test suite.\n\n    * src/voc.c src/caf.c src/wav.c src/mat5.c src/mat4.c\n    Fix bugs found by new test program.\n\n    * src/double64.c\n    Clean up double64_get_capability().\n\n2006-05-03  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/wav_w64.c\n    Fix a bug on x86_64 where an int was being passed via stdargs and being\n    read using size_t which is 64 bits. Thenks to John ffitch for giving me a\n    login on his box.\n\n2006-05-02  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/caf.c src/double64.c examples/sndfile-info.c tests/virtual_io_test.c\n            tests/utils.tpl\n    Fix a couple of signed/unsigned problems.\n\n2006-05-01  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/command_test.c\n    Add channel map tests.\n\n    * src/common.h src/sndfile.c\n    Add a pointer to the SF_PRIVATE struct and make sure it gets freed in\n    sf_close().\n\n2006-04-30  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.ac doc/(command|index|api).html NEWS README\n    Updates for 1.0.16 release.\n\n    * src/sndfile.h.in\n    Define enums for channel mapping.\n\n    * examples/sndfile-info.c\n    Clean up usage of SF_INFO struct.\n\n2006-04-29  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/util.tpl\n    Add function testing function exit_if_true().\n\n    * tests/floating_point_test.tpl\n    Fix a problem where the test program was not exiting when the test failed.\n\n2006-04-15  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.h.in src/sndfile.c src/common.h src/command.c\n    Implement new commands SFC_GET_SIGNAL_MAX and SFC_GET_MAX_ALL_CHANNELS.\n\n    * doc/commands.html\n    Document new commands. Other minor updates.\n\n    * tests/peak_chunk_test.c\n    Update tests for new commands.\n\n2006-04-02  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/peak_chunk_test.c\n    Add test for RIFX and WAVEX files.\n    Try and confuse the PEAK chunk writing by enabling and disabling it.\n\n    * src/sndfile.c\n    Fix a bug where enabling and disabling PEAK chunk was screwing up.\n\n2006-03-31  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.h.in\n    Add the block of 190 reserved bytes into this struct to allow for\n    future expansion.\n\n    * src/wav.c src/sndfile.c src/broadcast.c\n    Significant cleanup of broadcast wave stuff.\n\n    * examples/sndfile-info.c\n    Fix print message.\n\n    * tests/command_test.c tests/Makefile.am\n    Complete bext tests, hook test in test suite.\n\n2006-03-30  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.h.in\n    Make coding_history field of SF_BROADCAST_INFO struct a char array instead\n    of a char pointer.\n\n    * src/sndfile.c src/common.h src/wav.c\n    Clean up knock on effects of above chnage.\n\n    * examples/sndfile-info.c\n    Add -b command line option to usage message.\n    Clean up output of broadcast wave info.\n\n    * src/wav.c\n    Ignore and skip the 'levl' chunk.\n\n2006-03-26  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.ac\n    Fix handling of --enable and --disable configure args. Thanks to Diego\n    'Flameeyes' Pettenò who sent the patch.\n\n2006-03-22  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * doc/win32.html\n    Make it really clear that although the MSVC++ cannot compile libsndfile,\n    the precompiled DLL can be used in C++ programs compiled with MSVC++.\n\n2006-03-18  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/aiff.c\n    Fix bug in writing of INST chunk in AIFF files.\n    Fix potential bug in writing MARK chunks.\n\n    * src/sndfile.c\n    Make sure the instrument chunk can only be written at the start of the file.\n\n    * tests/command_test.c\n    Add check of log buffer.\n\n    * tests/utils.tpl\n    Add usage of space character to psf_binheader_writef.\n\n2006-03-17  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/Makefile.am tests/Makefile.am\n    Remove --source-time argument from autogen command lines.\n\n    * src/broadcast.c\n    New file for EBU Broadcast chunk in WAV files.\n\n    * src/sndfile.c src/sndfile.h.in src/wav.c src/common.h\n    Add patch from Paul Davis implementing read/write of the BEXT chunk.\n\n2006-03-16  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * Win32/README-precompiled-dll.txt\n    New file descibing how to use the precompiled DLL.\n\n    * Win32/Makefile.am\n    Add Win32/README-precompiled-dll.txt to EXTRA_DIST files.\n\n    * configure.ac\n    Bump version to 1.0.15.\n\n2006-03-11  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/wav.c\n    On read, only add the endian flag if the file is big endian.\n\n    * src/ms_adpcm.c\n    Fixed writing of APDCM coeffs in RIFX files.\n\n    * tests/write_read_test.tpl tests/lossy_comp_test.c\n    Add tests for RIFX files.\n\n2006-03-10  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * Mingw-make-dist.sh\n    Bunch of improvements.\n\n    * doc/win32.html\n    Update MinGW program versions.\n\n2006-03-09  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/create_symbols_file.py\n    Fix the library name in created win32 DEF file. Add correct DLL name for\n    Cygwin DLL.\n\n    * Win32/Makefile.am tests/Makefile.am\n    Remove redundant files, add win32_ordinal_test to test suite.\n\n    * tests/win32_ordinal_test.c\n    Update to do test in cygsndfile-1.dll as well.\n\n    * doc/win32.html\n    Fix typo, mention that -mno-cygwin with the Cygwin compiler does not work.\n\n    * src/wav.c src/wav_w64.c src/sndfile.c src/sndfile.h.in\n    Apply large patch from Jesse Chappell which adds support for RIFX files.\n\n2006-03-08  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * Makefile.am\n    Add Mingw-make-dist.sh to the extra dist files.\n\n    * configure.ac\n    Fix setting SHLIB_VERSION_ARG for MinGW.\n\n    * tests/win32_ordinal_test.c\n    New test program to test that the win32 DLL ordinals agree with the DEF\n    file.\n\n2006-03-04  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/common.h\n    Add a static inline function to convert an int to a size_t. This will be\n    a compile to nothing on 32 bit CPUs and a sign extension on 64 bit CPUs.\n\n    * src/aiff.c src/avr.c src/common.c src/xi.c src/gsm610.c\n    Fix an ia64 problem where a varargs function was being passed an int in\n    some places and a size_t in other places.\n\n    * src/sd2.c\n    Add a workaround for situations where OSX seems to add an extra 0x52 bytes\n    to the start of the resource fork.\n\n2006-02-19  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * Mingw-make-dist.sh\n    Add a shell script to build the windows binary/source ZIP file.\n\n    * doc/index.html\n    Add download link for windows binary/source ZIP file. Add links for GPG\n    signatures.\n\n    * doc/win32.html\n    Remove info about building using microsoft compiler.\n\n    * configure.ac\n    Bump version to 1.0.14.\n\n2006-02-11  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sd2.c\n    Improve logging of errors in resource fork parser.\n\n2006-01-31  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * Win32/Makefile.msvc\n    Replace au_g72x.* with g72x.*. Thanks to ussell Borogove.\n\n2006-01-29  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/common.c\n    Make sure return values are initialised header buffer is full.\n\n    * src/wav.c\n    Add workarounds for messed up WAV files.\n\n2006-01-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * Win32/config.h\n    Undef HAVE_INTTYPES_H for win32.\n\n    * tests/command_test.c\n    Don't exit on error in instrument test for XI files.\n\n    * configure.ac\n    Bump version to 1.0.13.\n\n    * doc/*.html NEWS README\n    Update version numbers.\n\n2006-01-19  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/xi.c\n    Start work on add read/write of instrument chunks.\n\n    * src/command_test.c\n    Add tests for XI instrument chunk.\n\n    * tests/largefile_test.c tests/Makefile.am\n    Add new test and hook it into the build system. This test will not be run\n    automatically because it requires 3 Gig of disk space and takes 3 minutes\n    to run.\n\n2006-01-10  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * examples/sndfile-play.c\n    Fix calculation of samples remaining in win32 code. Thanks Axel Röbel.\n\n    * src/common.h\n    Make sure length of header buffer can hold header plus strings. Thanks Axel\n    Röbel.\n\n2006-01-09  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.h.in src/aiff.c src/wav.c\n    Apply a patch from John ffitch (Csound project).\n    Add detune field to SF_INSTRUMENT struct.\n    Add reading/writing instrument chunks to WAV files.\n\n    * tests/command_test.c\n    Update SF_INSTRUMENT tests.\n\n    * tests/Makefile.am\n    Hook instrument tests into test suite.\n\n2006-01-05  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.ac\n    Check for <inttypes.h> because some broken systems (like Solaris) don't have\n    <stdint.h> which is the 1999 ISO C standard file containing int64_t.\n\n    * src/sfendian.h src/common.h\n    Use <inttypes.h> if <stdint.h> is not available.\n\n2005-12-30  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/peak_chunk_test.c\n    Extend and clean up tests.\n\n    * src/sndfile.c\n    Fix a bug that prevented the turning off of PEAK chunks.\n\n2005-12-29  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/error_test.c\n    Make the test distclean correct.\n\n    * src/file_io.c\n    Fix an SD2 MacOSX bug (reported by vince schwarzinger).\n\n2005-12-28  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/aiff.c tests/command_test.c\n    Apply a big patch from John ffitch (Csound project) to add reading and\n    writing of instrument chunks to AIFF files. Also update the test.\n\n2005-12-10  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/aiff_rw_test.c tests/virtual_io_test.c tests/utils.tpl\n    Move test function dump_data_to_file() to utils.tpl.\n\n    * tests/error_test.c tests/Makefile.am\n    Updates, including a new test to test that sf_error() returns a valid error\n    number.\n\n2005-12-07  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * examples/list_formats.c\n    Make sure the SF_INFO struct is memset to all zero before being used.\n    Thanks to Stephen F. Booth.\n\n    * src/sndfile.c\n    Make the return value of sf_error() match the API documentation.\n\n2005-11-19  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * examples/sndfile-convert.c\n    Allow conversion to raw gsm610.\n\n    * src/common.h src/sndfile.c src/au.c\n    Remove au_nh_open() and all references to it (wasn't working anyway).\n\n    * tests/headerless_test.c\n    Add new test for file extension based detection.\n\n    * src/sndfile.c\n    Rejig file extension based file type detection.\n\n2005-11-16  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.c\n    Add \"gsm\" as a recognised file extension when no magic number can be found.\n\n    * tests/lossy_comp_test.c tests/Makefile.am\n    Test headerless GSM610.\n\n2005-11-13  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * doc/api.html\n    Fix a minor typo and a minor error. Thanks Christoph Kobe and John Pavel.\n\n2005-10-30  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/wav_w64.c\n    Add more reporting of 'fmt ' chunk for G721 encoded files.\n\n    * src/wav.c\n    Gernerate a more correct 20 byte 'fmt ' chunk rather than a 16 byte one.\n\n2005-10-29  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/G72x/g72x.[ch]\n    Minor cleanup of interface.\n\n2005-10-28  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/ogg.c\n    Removed the horribly broken and non-functional OGG implementation when\n    --enable-experimental was enabled. When OGG does finally work it will be\n    merged.\n\n    * src/caf.c\n    Fix a memory leak.\n\n2005-10-27  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/g72x.c src/G72x/*.(c|h) src/common.h src/sndfile.c src/wav.c src/au.c\n    Add support for G721 encoded WAV files.\n\n    * doc/index.html\n    Update support matrix.\n\n    * tests/lossy_comp_test.c\n    For file formats that support it, add string data after the audio data and\n    make sure it isn't treated as audio data on read.\n\n    * src/gsm610.c\n    Add code to ensure that the container close function (ie for WAV files) gets\n    called after the codec's close function. This allows GSM610 encoded WAV files\n    to have string data following the audio data.\n    Add an AIFF specific check on psf->datalength.\n\n    * src/wav.c\n    Simplify wav_close function.\n\n    * src/aiff.c\n    Make sure the tailer data gets written at an even file offset. Pad if\n    necessary.\n\n    * src/common.h\n    Replace the close function pointer in SF_PRIVATE with separate functions\n    codec_close and container_close. The former is always called first.\n\n    *  src/*.c\n    Fix knock on effects of above.\n\n2005-10-26  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * examples/sndfile-info.c\n    Complete dumping SF_INSTRUMENT data.\n\n    * src/dwvw.c src/ima_adpcm.c src/gsm610.c src/ms_adpcm.c\n    Add extra checks in *_init function.\n\n    * tests/lossy_comp_test.c\n    Add a string comment to the end of the files to make sure that the decoder\n    doesn't decode beyond the end of the audio data section.\n\n2005-10-25  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * examples/sndfile-info.c\n    Minor code cleanup.\n    Start work on dumping SF_INSTRUMENT data.\n\n2005-10-23  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.h.in src/common.h src/common.c\n    Update definition of SF_INSTRUMENT struct and create a function to allocate\n    and initialize the struct (input from David Viens).\n    Clean up definition of SF_INSTRUMENT struct.\n\n    * src/wav.c src/wav_w64.c\n    Add support for Ambisoncs B WAVEX files (David Viens).\n\n    * src/aiff.c src/wav.c src/wav_w64.c\n    Start work on reading/writing the SF_INSTRUMENT data.\n\n    * src/sndfile.c\n    Add code to get and set SF_INSTRUMENT data.\n\n    * tests/command_test.* tests/Makefile.am\n    Add test for set and getof SF_INSTRUMENT data.\n    The file command_test.c is no longer autogen generated.\n\n2005-10-15  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/gsm610.c\n    Minor cleanup.\n\n2005-10-14  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/lossy_comp_test.c\n    Minor cleanup.\n\n2005-10-13  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/*.c\n    Ensure sfconfig.h is included before any other header file.\n\n    * src/file_io.c\n    Add comments documenting the three sections of the file.\n\n    * src/gsm610.c\n    Make sure SF_FORMAT_WAVEX are handled correctly.\n\n2005-10-07  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.ac\n    Add options to allow disabling of FLAC and ALSA. Suggested by Ben Greear.\n\n2005-09-30  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/locale_test.c\n    Modify the way the unicode strings were encoded so that older compilers\n    do not complain. Thanks Axel Röbel.\n\n    * configure.ac\n    Bump the version to 1.0.12 for release.\n\n    * NEWS README Win32/config.h doc/(FAQ|index.html|command|api).html\n    Update version numbers.\n\n2005-09-26  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/flac.c\n    Fix valgrind error and minor cleanup.\n\n2005-09-25  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/(au|paf|aiff|w64|wav|svx).c\n    Make sure structs are initialised.\n\n2005-09-24  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.ac\n    Make -Wdeclaration-after-statement work with --enable-gcc-werror configure\n    option.\n    Add -std=gnu99 (C99 plus posix style stuff like gmtime_r) to CFLAGS if the\n    compiler supports it.\n\n2005-09-23  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.ac acinclude.m4\n    Add -Wdeclaration-after-statement to CFLAGS if the compilers supports it.\n\n2005-09-22  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/util.(tpl|def)\n    Make the test_write_*_or_die() functions const safe.\n\n2005-09-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/nist.c\n    Make sure the data offset is read from the file header. Thanks to\n    David A. van Leeuwen for a patch.\n\n2005-09-20  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.ac src/sfconfig.h\n    Check for <locale.h> and the function setlocale().\n    Set config variables to zero if not found.\n\n    * tests/locale_test.c tests/Makefile.am\n    Add new test program and hook into build/test system.\n\n2005-09-18  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/common.h src/file_io.c\n    On windows, use windows specific types for file handles.\n    Add functions psf_init_files() and psf_use_rsrc().\n\n    * src/sd2.c\n    Make resource fork handling independant of file desciptor/handles.\n\n    * src/sndfile.c src/test_file_io.c\n    Fix knock on effects.\n\n2005-09-06  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/float_cast.h\n    The lrint and lrintf implementations in Cygwin are both buggy and slow.\n    Add replacements which were pulled from the Public Domain MinGW math.h\n    header file.\n\n2005-09-05  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/(lossy_comp_test|virtual_io_test).c\n    More Valgrind fixups.\n\n    * configure.ac\n    Simplify and correct configuring for Cygwin.\n\n    * Win32/config.h Win32/sndfile.h Win32/Makefile.msvc\n    Update build for MSVC.\n\n2005-09-04  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/lossy_comp_test.c\n    Make sure to close SNDFILE when exiting test when file format is not seekable.\n\n    * tests/(aiff_rw_test|virtual_io_test).c\n    Do a few valgrind fix ups.\n\n2005-09-03  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/float32.c src/double64.c\n    Replace floating point equality comparisons with greater/less comparisons.\n    Found by John Pavel using the Intel compiler.\n\n    * src/sfconfig.h\n    New file to clean up issues surrounding autoconf generated preprocessor\n    symbols.\n\n    * src/*.(c|h) tests/*.(c|tpl) examples/*.c\n    Fixed a bunch of other stuff found by John Pavel using the Intel compiler.\n\n    * src/file_io.c\n    Remove Mac OS9 Metrowerks compiler specific hacks.\n\n2005-08-31  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/w64.c\n    Cast integer literal to sf_count_t in call to psf_binheader_writef() to\n    prevent Valgrind error.\n\n2005-08-30  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * doc/command.html\n    Improve documentation of SF_GET_FORMAT_SUBTYPE.\n\n2005-08-26  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * examples/sndfile-convert.c\n    Allow files to be converted to SD2 format.\n\n    * src/sd2.c\n    Fix a bug in reading and writing of SD2 files on little endian CPUs.\n    Thanks to Matthew Willis for finding this.\n\n2005-08-25  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * doc/api.html\n    Update Note2 to point to SFC_SET_SCALE_FLOAT_INT_READ.\n\n2005-08-16  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.ac\n    Use $host_os instead of $target_os (thanks to Mo De Jong).\n\n2005-08-15  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/Makefile.am\n    Apply a patch from Mo DeJong to allow building outside of the source dir.\n\n    * src/file_io.c\n    Fix psf_fsync() for win32.\n\n    * src/wav.c src/wav_w64.(c|h)\n    Move some code from wav.c to wav_w64.c to improve the log output of files of\n    type WAVE_FORMAT_EXTENSIBLE.\n\n2005-08-10  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/create_symbols_file.py\n    Make sure sf_write_fsync is an exported symbol.\n\n    * examples/sndfile-convert.c\n    Add support for writing VOX adpcm files.\n\n2005-07-31  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * doc/api.html\n    Document the new function sf_write_sync().\n\n    * doc/FAQ.html\n    Do you plan to support XYZ codec.\n\n2005-07-28  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.h.in src/sndfile.c\n    Add function sf_write_sync() to the API.\n\n    * src/common.h src/file_io.c\n    Low level implementation (win32 not done yet).\n\n    * tests/write_read_test.tpl\n    Use the new function in the tests.\n\n2005-07-24  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/common.h src/double64.c src/float32.c src/sndfile.c\n    Change the way PEAK chunk info is stored. Peaks now stored as an sf_count_t\n    for position and a double as the value.\n\n    * src/aiff.c src/caf.c src/wav.c\n    Fix knock on effects of above changes.\n\n    * src/caf.c\n    Implement 'peak' chunk for file wuth data in SF_FORMAT_FLOAT or\n    SF_FORMAT_DOUBLE format.\n\n2005-07-23  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/nist.c\n    Fix a bug where a variable was being used without being initialized.\n\n    * src/flac.c\n    Add extra debug in sf_flac_meta_callback.\n    Make a bunch of private functions static.\n\n    * src/aiff.c src/wav.c\n    Fix allocation for PEAK_CHUNK (bug found using valgrind).\n\n2005-07-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/common.h\n    Move the peak_loc field of SF_PRIVATE to the PEAK_CHUNK struct.\n    Remove had_peak field of SF_PRIVATE, use pchunk != NULL instead.\n    Rename PEAK_CHUNK and PEAK_POS to PEAK_CHUNK_32 and PEAK_POS_32.\n\n    * src/aiff.c src/caf.c src/wav.c src/float32.c src/double64.c\n    Fix knock on effects from above.\n\n2005-07-19  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/wav.c\n    Prevent files with unknown chunks from being opened read/write.\n\n2005-07-14  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/flac.c\n    Do not use psf->end_of_file because it never gets set to anything.\n\n    * src/common.h\n    Remove unused SF_PRIVATE field end_of_file.\n\n2005-07-12  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/common.c\n    Change the 'S' format specifier of psf_binheader_writef() to write AIFF\n    style strings (no terminating character).\n\n    * src/aiff.c\n    Move to new (correct) AIFF string style. Thanks to Axel Röbel for being\n    so persistent on this issue.\n\n2005-07-11  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.c\n    Allow SFE_UNSUPPORTED_FORMAT as an error from sf_open().\n\n    * doc/api.html doc/command.html\n    Documentation updates (thanks to Kyroz for promoting these updates).\n\n    * src/mat5.c\n    Modify the way the header is written.\n\n2005-07-10  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/caf.c\n    Add a 'free' chunk to the written file so that the audio data starts at\n    an offset of 0x1000.\n\n    * src/sndfile.c\n    Allow SFE_UNSUPPORTED_FORMAT as an error from sf_open().\n\n2005-07-09  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/caf.c src/sndfile.c\n    Add support for signed 8 bit integers.\n\n    * tests/write_read_test.tpl\n    Add test for signed 8 bit integers in CAF files.\n\n    * doc/index.html\n    Update matrix for signed 8 bit integers in CAF files.\n\n2005-07-08  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.c\n    Update sf_check_format() to support CAF.\n\n    * examples/sndfile-convert.c\n    Add support for \".caf\" file extension.\n\n    * doc/index.html\n    Add Apple CAF to the support matrix.\n\n    * src/caf.c\n    Add file write support.\n\n    * src/common.c\n    Fix printing of Frames.\n\n    * tests/Makefile.am tests/write_read_test.tpl tests/lossy_comp_test.c\n        tests/header_test.tpl misc_test.c\n    Add tests for CAF files.\n\n2005-07-07  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * doc/FAQ.html\n    Fix Q/A about reading/writing memory buffers.\n\n    * src/caf.c\n    Bunch of work to support reading of CAF files.\n\n2005-07-04  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/(aiff|ima_adpcm|mat4|mat5|ms_adpcm).c examples/sndfile-play.c\n    Fix sign conversion errors reported by gcc-4.0.\n\n    * src/caf.c\n    New file for Apple's Core Audio File format.\n\n    * src/sndfile.c src/common.h src/sndfile.h.in src/Makefile.am\n    Hook new file into build system.\n\n2005-06-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src_wav_w64.c\n    Fix handling of stupidly large 'fmt ' chunks. Thanks to Vadim Berezniker\n    for supplying an example file.\n\n    * src/common.h src/sndfile.c\n    Remove redundant error code SFE_WAV_FMT_TOO_BIG.\n\n2005-06-20  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.h.in src/common.h src/sndfile.c\n    Add public error value SF_ERR_MALFORMED_FILE.\n\n    * src/sndfile.c\n    When parsing a file header fails and we don't have a system error, then set\n    the error number to SF_ERR_MALFORMED_FILE (suggested by Kyroz).\n\n    * configure.ac\n    Allow sqlite support to be disabled in configure script.\n\n    * regtest/database.c regtest/sndfile-regtest.c\n    Fix compiling when sqlite is missing.\n\n2005-06-11  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/file_io.c\n    Fix psf_is_pipe() and return value of psf_fread() when using virtual i/o.\n\n    * src/sndfile.c\n    Fix VALIDATE_AND_ASSIGN_PSF macro for virtual i/o.\n\n    * tests/virtual_io_test.c\n    Fill in skeleton test program.\n\n    * tests/Makefile.am\n    Move virtual i/o tests to end of tests with stdio/pipe tests.\n\n    * src/(sndfile.h.in|file_io.c|common.h|sndfile.c) tests/virtual_io_test.c\n    Rename some of the virtual i/o functions and data types.\n\n2005-06-10  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.c\n    Fix the return values of sf_commands : SFC_SET_NORM_DOUBLE,\n    SFC_SET_NORM_FLOAT, SFC_GET_LIB_VERSION and SFC_GET_LOG_INFO. Thanks to\n    Kyroz for pointing out these errors.\n\n    * doc/command.html\n    Correct documented return values for SFC_SET_NORM_DOUBLE and\n    SFC_SET_NORM_FLOAT. Thanks to Kyroz again.\n\n2005-05-17  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * regtest/*\n    Add new files for sndfile-regtest program.\n\n    * configure.ac Makefile.am\n    Hook regetest into build.\n\n    * src/wav.c src/common.c\n    Fix a regression where long ICMT chunks were causing the WAV parser\n    to exit.\n\n2005-05-15  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * libsndfile.spec.in\n    Add html docs to the files section as suggested by Karsten Jeppesen.\n\n    * src/aiff.c\n    Fix parsing of odd length ANNO chunks.\n\n2005-05-13  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/common.h\n    Change the include guard to prevent clashes with other code.\n\n2005-05-12  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * examples/sndfile-play.c\n    Improve error handling in code for playback under Linux/ALSA.\n\n2005-05-10  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/ircam.c\n    Fix writing of IRCAM files on big endian systems (thanks to Axel Röbel).\n\n    * src/wav.c\n    Add workaround for files created by the Peak audio editor on Mac which can\n    produce files with very short LIST chunks (thanks to Jonathan Segel who\n    supplied the file).\n\n2005-04-30  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/aiff.c\n    Apply a patch From David Viens to make the parsing of basc chunks more\n    robust.\n\n    * src/wav.c\n    Another patch from David Viens to write correct wavex channel masks for\n    the most common channel configurations.\n\n2005-04-08  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/command.c\n    Only allow FLAC in the format arrays if FLAC is enabled. Thanks to\n    Leigh Smith.\n\n2005-03-09  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/common.h\n    Add a directory field for storing the file directory to the SF_PRIVATE\n    struct.\n\n    * src/sndfile.c\n    Grab the directory name when copying the file path.\n\n    * src/file_io.c\n    Cleanup psf_open_rsrc() and also check for resource fork in\n    .AppleDouble/filename.\n\n2005-03-01  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/svx.c\n    Fix a bug in the printing of the channel count. Bug reported by Michael\n    Schwendt. Thanks.\n\n2005-01-26  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/paf.c\n    Fix a seek bug for 24 bit PAF files.\n\n    * tests/write_read_test.tpl\n    Update write_read_test to trigger the previously hidden PAF seek bug.\n\n2005-01-25  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/aiff.c src/w64.c src/wav.c\n    Do not return a header parse error when the log buffer overflows.\n    Continuing parsing works even on files where the log buffer does overflow.\n    This avoids a bug on some weirdo WAV (and other) files.\n\n    * src/common.h src/sndfile.c\n    Remove SFE_LOG_OVERRIN error and its associated error message.\n\n    * src/file_io.c\n    Fix a rsrc fork problem on MacOSX.\n\n2004-12-31  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile-play.c\n    In the ALSA output code, added call to snd_pcm_drain() just before\n    snd_pcm_close() as suggested by Thomas Kaeding.\n    In the OSS output code, added two ioctls (SNDCTL_DSP_POST and\n    SNDCTL_DSP_SYNC) just before the close of the audio device.\n\n    * tests/virtual_io_test.c tests/Makefile.am\n    Add a new test program (currently empty) and add it to the build.\n\n2004-12-29  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.h.in src/sndfile.h src/common.h src/file_io.c\n      src/create_symbols_file.py\n    Apply patch from Steve Baker which is the beginnings of a virtual\n    I/O interface.\n\n2004-12-23  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/*.c src/sndfile.h.in\n    Const-ify the write path throughout the library.\n\n2004-12-14  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * doc/development.html\n    Minor improvements.\n\n2004-11-29  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * doc/bugs.html\n    Minor improvements.\n\n2004-11-18  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/aiff.c\n    Add workaround for Logic Platinum AIFF files with broken COMT chunks.\n\n2004-11-16  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * doc/FAQ.html\n    Remove some ambiguities in the SD2 FAQ answer.\n\n2004-11-15  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * Win32/sndfile.h Win32/config.h MacOS9/sndfile.h MacOS9/config.h\n    Updates from autoconfig versions.\n\n2004-11-13  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/aiff.c\n    Fix parsing of COMT chunks. Store SF_STR_COMMENT data in ANNO chunks\n    instead of COMT chunk.\n\n2004-11-07  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/file_io.c src/common.h\n    Change the ptr argument to psf_write() from \"void*\" to a \"const void*\".\n    Thanks to Tobias Gehrig for suggesting this.\n\n2004-10-31  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/file_io.c src/common.h\n    Add functions psf_close_rsrc() and read length of resourse fork into\n    rsrclength field of SF_PRIVATE.\n\n    * src/sd2.c\n    Make sure resource fork gets closed.\n\n    * tests/util.tpl\n    Add functions to check for file descriptor leakage.\n\n    * src/write_read_test.tpl\n    Use the file descriptor leak checks.\n\n    * src/sndfile.h.in\n    Add SFC_GET_LOOP_INFO and SF_LOOP_INFO struct.\n\n    * src/common.h\n    Add SF_LOOP_INFO pointer to SF_PRIVATE.\n\n    * src/wav.c src/aiff.c\n    Improve and add parsing of 'ACID' and 'basc' chunks, filling in\n    SF_LOOP_INFO data in SF_PRIVATE.\n\n2004-10-30  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sd2.c\n    Further cleanup: remove printfs, change snprintf to LSF_SNPRINTF.\n\n    * Win32/config.h Win32/sndfile.h\n    Updates.\n\n    * tests/util.tpl\n    Add win32 macro for snprintf.\n\n2004-10-29  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sfendian.h\n    Add macros : H2BE_SHORT, H2BE_INT, H2LE_SHORT and H2LE_INT.\n\n    * src/sd2.c\n    Use macros to make sure writing SD2 files on little endian machines works\n    correctly.\n\n    * tests/util.tpl\n    Add a delete_file() function which also deletes the resource fork of SD2\n    files.\n\n    * tests/write_read_test.tpl\n    Use delete_file() so that \"make distcheck\" works.\n\n2004-10-28  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.c src/file_io.c\n    Move resource filename construction and testing to psf_open_rsrc().\n\n    * src/common.h src/sndfile.c\n    Add error SFE_SD2_FD_DISALLOWED.\n\n    * tests/util.tpl tests/*.(c|tpl)\n    Add and allow_fd parameter to test_open_file_or_die() so that use of\n    sf_open_fd() can be avoided when opening SD2 files.\n\n2004-10-27  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/wav.c\n    Update ACID chunk parsing.\n\n    * src/sd2.c\n    More fixes for files with large resource forks.\n\n2004-10-23  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/common.h src/sndfile.c\n    Add error numbers and messages for sd2 files.\n\n    * src/sd2.c\n    Reading of sd2 (resource fork version) now seems to be working.\n\n2004-10-17  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/file_io.h\n    Update file_io.c to include win32 psf_rsrc_open().\n\n    * tests/floating_point_test.tpl\n    Remove use of __func__ in test programs (MSVC++ doesn't grok this).\n\n    * Win32/(config|sndfile).h MacOS9/(config|sndfile).h\n    Updates.\n\n2004-10-13  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sfendian.h\n    Fix endswap_int64_t_(array|copy).\n\n    * src/test_endswap.(tpl|def)\n    Add tests for above and inprove all tests.\n\n2004-10-12  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sfendian.h\n    Improve type safety, add endswap_double_array().\n\n    * src/double64.c\n    Use endswap_double_array() instead of endswap_long_array().\n\n    * src/test_endswap.(tpl|def) src/Makefile.am\n    Add preliminary endswap tests and hook into build system.\n\n2004-10-06  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/configure.ac src/makefile.am\n    Finally fix the bulding of DLLs on Win32/MinGW.\n\n    * tests/makefile.am\n    Fix running of tests on Win32/MinGW.\n\n2004-10-01  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.h.in src/sndfile.c tests/floating_point_test.tpl\n    Rename SFC_SET_FLOAT_INT_MULTIPLIER to SFC_SET_SCALE_FLOAT_INT_READ.\n\n    * doc/command.html\n    Document SFC_SET_SCALE_FLOAT_INT_READ.\n\n2004-09-30  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/floating_point_test.(tpl|def)\n    Derived from floating_point_test.c.\n    Add (float|double)_(short|int)_test functions.\n\n    * tests/util.(tpl|def)\n    Make separate float and double versions of gen_windowed_sine().\n\n    * tests/write_read_test.tpl\n    Fix after changes to gen_windowed_sine().\n\n    * src/(float32|double64).c\n    Implement SFC_SET_FLOAT_INT_MULTIPPLIER.\n\n2004-09-29  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * acinclude.m4\n    Fix warnings from automake 1.8 and later.\n\n    * examples/sndfile-info.c\n    Add a \"fflush (stdout)\" after printing Win32 message.\n\n2004-09-28  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * Win32/Makefile.mingw.in\n    Add a \"make install\" target.\n\n2004-09-24  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.h.in src/common.h src/sndfile.c src/command.c\n    Start work on adding command SFC_SET_FLOAT_INT_MULTIPLIER.\n\n2004-09-22  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * examples/sndfile-convert.c\n    Fix a bug converting stereo integer PCM files to float.\n\n2004-09-22  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * examples/sndfile-play.c\n    Appy patch from Conrad Parker to make Mac OSX error messages more\n    consistent and informative.\n\n    * doc/api.html\n    Fix a HTML HREF which was wrong.\n\n    * doc/win32.html\n    Add information about when nmake fails.\n\n2004-09-05  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * examples/sndfile-play.c\n    Another patch from Denis Cote to prevent race conditions.\n\n2004-09-02  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/common.h src/ms_adpcm.c src/ima_adpcm.c\n    Fix alternative to ISO standard flexible struct array feature for broken\n    compilers.\n\n2004-08-31  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/common.h src/string.c src/sndfile.c\n    Make sf_set_string() return an error if trying to set a string when in\n    read mode.\n\n2004-08-29  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/common.h\n    Change the unnamed union into a named union so gcc-2.95 will compile it.\n\n    * src/*.c\n    Fixes to allow for the above change.\n\n2004-08-20  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * examples/sndfile-play.c\n    Fixes for Win32. Thanks to Denis Cote.\n\n    * Win32/Win32/Makefile.(msvc|mingw.in)\n    Fix build system after removal of sfendian.h.\n    Build sndfile-convert.\n\n    * src/Makefile.am\n    Remove sfendian.c from dependancies.\n\n2004-08-10  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.h.in\n    Fix typo in comments (thanks Tommi Sakari Uimonen).\n\n2004-07-31  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/(a|u)law_test.c\n    Minor cleanup.\n\n2004-07-29  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/(pcm|float|double64|ulaw|alaw|xi).c\n    Optimise read/write loops by removing a redundant variable.\n\n2004-07-24  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/file_io.c\n    Remove call to fsync() in psf_close().\n\n2004-07-19  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/pcm.c\n    Inline x2y_array() functions where possible.\n\n    * configure.ac\n    Detect presence of type int64_t.\n\n    * src/sfendian.c src/sfendian.h\n    Move functions in the first file to the sfendian.h as static inline\n    functions.\n    Improve endswap_long_*() where possible.\n\n2004-07-17  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/pcm.c\n    When converting from unsigned char to float or double, subtract 128 before\n    converting to float/double rather than after to save a floating point\n    operation as suggested by Stefan Briesenick.\n\n    * src/(pcm|sfendian|alaw|ulaw|double64|float32).c\n    Optimize inner loops by changing the loop counting slightly as suggested\n    by Stefan Briesenick.\n\n    * configure.ac\n    Detect presence of <byteswap.h>.\n\n    * src/sfendian.h\n    Use <byteswap.h> if present as suggested by Stefan Briesenick.\n\n    * src/pcm.c\n    Update bytewapping.\n\n2004-07-02  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/common.h src/*.c\n    Change the psf->buffer field of SF_PRIVATE into a more type safe union with\n    double, float, int etc elements.\n\n2004-06-28  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * examples/sndfile-play.c\n    Merge slightly modifed patch from Stanko Juzbasic which allows playback of\n    mono files on MacOSX.\n\n2004-06-25  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * examples/sndfile-convert.c\n    Move copy_metadata() after the second sf_open().\n\n2004-06-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * examples/sndfile-convert.c\n    Fix a bug which caused the program to go into an infinite loop if the source\n    file has no meta-data. Thanks to Ron Parker for reporting this.\n\n    * src/sndfile.h.in\n    Add SF_STR_FIRST and SF_STR_LAST to allow enumeration of string types.\n\n    * Win32/sndfile.h MacOS9/sndfile.h\n    Update these as per the above file.\n\n2004-06-17  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.ac src/common.h src/ogg.c src/sndfile.c src/sndfile.h.in\n      src/Makefile.am\n    Apply large patch from Conrad Parker implementing Ogg Vorbis, Ogg Speex and\n    Annodex support via liboggz and libfishsound. Thanks Conrad.\n\n2004-06-15  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/avr.c src/ircam.c src/nist.c src/paf.c src/xi.c\n    Add cast to size_t for some parameters passed to psf_binheader_writef. This\n    is Debian bug number 253490. Thanks to Anand Kumria and Andreas Jochens.\n\n    * src/w64.c\n    Found and fixed a bug resulting from use of size_t when writing W64 'fmt '\n    chunk.\n\n2004-06-14  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.ac\n    Bump version to 1.0.10 ready for release.\n\n    * Makefile.am\n    Remove redundant files (check_libsndfile.py libsndfile_version_convert.py)\n    from distribution tarball.\n\n    * tests/header_test.tpl\n    Fix uninitialised variable.\n\n    * src/GSM610/short_term.c\n    Fix compiler warning on MSVC++.\n\n2004-05-23  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/wav.c\n    Improve record keeping of chunks seen and return an error if a file with\n    unusual chunks is opened in mode SFM_RDWR.\n\n    * src/mmreg.h\n    This file not needed so remove it.\n\n2004-05-22  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/header_test.tpl\n    Add extra_header_test().\n\n    * src/common.h src/sndfile.c\n    Add SFE_RDWR_BAD_HEADER error number and string.\n\n2004-05-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/utils.tpl tests/*.c tests/*.tpl\n    Add a line number argument to check_log_buffer_or_die() and update all\n    files that use that function.\n\n    * tests/header_test.tpl\n    Modify/update tests for files opened SFM_RDWR and SFC_UPDATE_HEADER_AUTO.\n\n    * src/aiff.c src/wav.c\n    Fix another bug in AIFF and WAV files opened in SFM_RDWR and using\n    SFC_UPDATE_HEADER_AUTO.\n\n    * src/test_file_io.c\n    Add a test for psf_ftruncate() function.\n\n2004-05-19  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.c\n    Fix another  weird corner case bug found by Martin Rumori. Thanks.\n\n    * tests/header_test.(tpl|def)\n    Two new files to test for the absence of the above bug and include tests\n    moved from tests/misc_test.c.\n\n    * tests/Makefile.am\n    Hook new tests into build/test system.\n\n    * tests/misc_test.c\n    Remove update_header_test() which has been moved to the new files above.\n\n2004-05-16  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/aiff.c\n    Fixed a bug reported by Martin Rumori on the LAD list. If a file created\n    with a format of SF_FORMAT_FLOAT and then closed before any data is written\n    to it, the header can get screwed up (PEAK chunk gets overwritten).\n\n    * tests/write_read_test.tpl\n    Add a test (empty_file_test) for the above bug.\n\n2004-05-13  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * Win32/Makefile.mingw.in\n    Added a Makefile for MinGW (needs to be processed by configure).\n\n    * src/mmsystem.h src/mmreg.h\n    Add files from the Wine project (under the LGPL) to allow build of\n    sndfile-play.exe under MinGW.\n\n2004-05-12  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/GSM610/gsm610_priv.h\n    Replace ugly macros with inline functions.\n\n    * src/GSM610/*.c\n    Remove temporary variables used by macros and other minor fixes required by\n    above change.\n\n2004-05-10  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/pipe_test.tpl tests/stdio_test.c Win32/Makefile.msvc\n    Make sure these programs compile (even though they do nothing) on Win32\n    and add them to the \"make check\" target.\n\n    * src/sfendian.h\n    Fix warning on Sparc CPU and code cleanup.\n\n2004-05-09  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/file_io.c\n    Fix warning messages when compiling under MinGW.\n\n2004-05-01  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.ac\n    Set HAVE_FLEXIBLE_ARRAY in src/config.h depending on whether the compiler\n    accepts the flexible array struct member as per 1999 ISO C standard.\n\n    * src/common.h src/ima_adpcm.c src/paf.c src/ms_adpcm.c\n    Added ugly #if HAVE_FLEXIBLE_ARRAY and provided a non-standards compliant\n    hack for non 1999 ISO C compliant compilers.\n\n2004-04-26  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/strings.c\n    If adding an SF_STR_SOFTWARE string, only append libsndfile-X.Y.Z if the\n    string does not already have libsndfile in the string. Thanks to Conrad\n    Parker.\n\n    * tests/string_test.c\n    Add test to verify the above.\n\n    * examples/sndfile-convert.c\n    Add ability to transcode meta data as well (Conrad Parker).\n\n2004-04-25  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * doc/command.html\n    Fix minor error. Thanks to Simon Burton.\n\n    * doc/win32.html\n    Started adding instructions for compiling libsndfile under MinGW.\n\n    * configure.ac\n    Add --enable-bow-docs to enable black text on a white background HTML docs.\n\n    * doc/libsndfile.css.in\n    This is now a template file for configure which sets the foreground and\n    background colours.\n\n2004-04-20  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.ac\n    Do some MinGW fixes.\n\n    * configure.ac doc/Makefile.am\n    Install HTML docs when doing make install.\n\n2004-04-19  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * examples/sndfile-info.c\n    Print out the dB level with the signal max.\n\n2004-04-15  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/file_io.c\n    Define S_ISSOCK in src/file_io.c if required.\n\n2004-04-03  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.ac\n    Improve printout configuration summary (as suggested by Axel Röbel).\n\n    * doc/index.html\n    Add link to pre-release location.\n\n    * src/sndfile.h.in\n    Remove comma after last element of enum.\n\n    * src/float32.c src/double64.c\n    Fix read/write of float/double encoded raw files to/from pipes.\n\n    * tests/pipe_test.c tests/pipe_test.tpl tests/pipe_test.def\n    Turn pipe_test.c into an autogenerated file and add tests for reading/\n    writing floats and doubles.\n\n    * tests/Makefile.am\n    Hook tests/pipe_test.* into build system.\n\n2004-04-02  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.ac acinclude.m4\n    Rename AC_C_STRUCT_HACK macro to AC_C99_FLEXIBLE_ARRAY.\n\n2004-03-31  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/misc_test.c\n    Perform update_header_test in RDWR mode as well.\n\n    * src/aiff.c\n    Fix problems when updating header in RDWR mode.\n\n2004-03-30  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/wav.c src/w64.c src/wav_w64.c\n    Integrate code supplied by David Viens for supporting microsoft's\n    WAVEFORMATEXTENSIBLE stuff. Thanks David for supplying this.\n\n    * configure.ac doc/*.html\n    Bump version to 1.0.9.\n\n2004-03-28  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/command.c src/sndfile.c src/sndfile.h.in src/wav.c\n    Started work on supporting microsoft's WAVEFORMATEXTENSIBLE gunk.\n\n2004-03-26  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/avr.c\n    New file to handle Audio Visual Resaerch files.\n\n    * src/sndfile.h.in src/common.h src/sndfile.c src/command.c\n    Hook AVR into everything else.\n\n    * tests/Makefile.am tests/write_read_test.tpl tests/misc_test.c\n    Add testing for AVR files.\n\n2004-03-22  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/file_io.c\n    Fix psf_set_file() for win32. Thanks to Vincent Trussart (Plogue Art et\n    Technologie) for coming up with the solution.\n\n2004-03-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/write_read_test.tpl\n    Fixed a bug that was causing valgrind to report a memory leak. The bug was\n    in the test code itself, not the library.\n\n2004-03-20  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * examples/generate.cs\n    An example showing how to use libsndfile from C#. Thanks to James Robson\n    for providing this.\n\n2004-03-19  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/common.c\n    Fix problems with WAV files containing large chunks after the 'data'\n    chunk. Thanks to Koen Tanghe for providing a sample file.\n\n2004-03-17  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.ac\n    Detect presense of ALSA (Advanced Linux Sound Architecture).\n\n    * examples/sndfile-play.c\n    Add ALSA output support.\n\n    * examples/Makefile.am\n    Add ALSA_LIBS to link line of sndfile-play.c.\n\n2004-03-15  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * acinclude.m4\n    Add new macro (AC_C_STRUCT_HACK) to detect whether the C compiler allows\n    the use of the what is known as the struct hack introduced by the 1999 ISO\n    C Standard.\n\n    * configure.ac\n    The last release would not compile with gcc-2.95 due to the use of features\n    (ie struct hack) introduced by the 1999 ISO C Standard.\n    Add check to make sure compiler handles this and bomb out if it doesn't.\n\n2004-03-14  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/write_read_test.tpl\n    Fix compiler warning on Win32.\n\n    * src/file_io.c\n    Fix use of an un-initialised variable in Win32 stuff.\n\n    * Win32/config.h examples/sndfile-play.c\n    Win32 fixes.\n\n2004-03-10  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.ac\n    Fix bug which occurres when configuring for MinGW.\n    If compiler is gcc and cross compiling use -nostdinc.\n\n2004-03-09  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/common.h src/aiff.c src/wav.c src/float32.c src/double64.c\n      src/sndfile.c\n    Fix a bug with PEAK chunk handling for files with more than 16 channels.\n    Thanks to Remy Bruno for finding this.\n\n2004-03-08  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/common.c\n    Fix a bug which was preventing WAV files being openned correctly if the\n    file had a very large header. Thanks to Eldad Zack for finding this.\n\n2004-03-04  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.ac src/file_io.c\n    Fix cross-compiling from Linux to Win32 using the MinGW tools.\n\n2004-03-01  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/create_symbols_file.sh\n    Christian Weisgerber pointed out that the shell script did not run on a\n    real Bourne shell although it did run under Bash in Bourne shell mode.\n\n    * src/create_symbols_file.py\n    Rewrite of above in Python. Also add support for writing Win32 .def files.\n    The Python script generates Symbols.linux, Symbols.darwin and\n    libsndfile.def (Win32 version). These files get shipped with the tarball\n    so there should not be necessary to run the Python script when building\n    the code from the tarball.\n\n    * configure.ac src/Makefile.am Win32/Makefile.am\n    Hook new Python script into the build system.\n\n2004-02-25  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/configure.ac\n    Add --enable-gcc-werror option and move GCC specific stuff down.\n\n2004-02-24  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * acinclude.m4 configure.ac\n    Fix clip mode detection (tested in one of HP's testdrive Itanium II boxes).\n\n    * src/file_io.c\n    Added check for sizeof (off_t) != sizeof (sf_count_t) to prevent recurrence\n    of missing large file support on Linux and Solaris.\n\n2004-02-19  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * examples/sndfile-play.c\n    Fix a MacOSX specific bug which was caused by a space being inserted in\n    the middle of a file name.\n\n    * configure.ac src/Makefile.am examples/Makefile.am\n    Fix a couple of MacOSX build issues.\n\n2004-02-17  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * doc/command.html\n    Document SFC_SET_CLIPPING and SFC_GET_CLIPPING.\n\n2004-02-14  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * doc/*.html\n    Applied patch from Frank Neumann (author of lakai) which fixes many minor\n    typos in documentation. Thanks Frank.\n\n2004-02-13  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * ChangeLog\n    Changed my email address throughout source and docs.\n\n2004-02-08  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/file_io.c\n    Make sure config.h is included before stdio.h to make sure large file\n    support is enabled on Linux (and Solaris).\n\n    * tests/misc_test.c\n    Disable update_header test on Win32. This should work but doesn't and\n    I'm not sure why.\n\n    * Make.bat Win32/Makefile.msvc\n    Updates.\n\n2004-01-07  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/common.h\n    Changed logindex, headindex and headend files of SF_PRIVATE from unsigned\n    int to int to prevent weird arithmetic bugs.\n\n    * src/common.c src/aiff.c src/wav.c src/w64.c\n    Fixed compiler warnings resulting from above change.\n\n2004-01-06  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/common.c\n    Fixed a bug in header reader for some files with data after the sample data.\n\n2003-12-29  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/lossy_comp_test.c tests/Makefile.am\n    Add tests for AIFF/IMA files.\n\n2003-12-26  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/macbinary3.c src/macos.c\n    Two new files required for handling SD2 files.\n\n    * src/common.h\n    Add prototypes for functions in above two files.\n\n    * src/Makefile.am\n    Hook new files into build system.\n\n2003-12-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.ac\n    Add checks for mmap() and getpagesize() which might be used at some time\n    for faster file reads.\n    Add detection of MacOSX.\n\n2003-12-13  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * doc/FAQ.html\n    Minor mods to pkg-config section.\n\n2003-12-12  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/create_symbols_file.sh\n    Andre Pang (also known as Ozone) pointed out that on MacOSX, all non\n    static symbols are exported causing troubles when trying to link\n    libsndfile with another library which has any of the same symbols.\n    He fixed this by supplying the MacOSX linker with a file containing\n    all the public symbols so that only they would be exported and then\n    supplied a patch for libsndfile.\n    This wasn't quite ideal, because I would have to maintain two (3 if\n    you include Win32) separate files containing the exported symbols.\n    A better solution was to create this script which can generate a\n    Symbols file for Linux, MacoSX and any other OS that supports\n    minimising the number of exported symbols.\n\n    * configure.ac src/Makefile.am\n    Hook the new script into the build process.\n\n2003-12-10  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * doc/index.html\n    Added comments about Steve Dekorte's SoundConverter scam.\n\n2003-12-07  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/file_io.c\n    Axel Röbel pointed out that on Mac OSX a pipe is not considered a fifo\n    (S_ISFIFO (st.st_mode) is false) but a socket (S_ISSOCK (st.st_mode) is\n    true). The test has therefore been changed to is S_ISREG and anything\n    which which does not return true for S_ISREG is considered a pipe.\n\n2003-11-25  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/misc_test.c\n    Fix update_header_test to pass SDS.\n\n    * src/sds.c\n    More minor fixes.\n\n    * tests/floating_point_test.c\n    Add test for SDS files.\n\n    * src/command.c\n    Add SDS to major_formats array.\n\n2003-11-24  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/write_read_test.tpl tests/misc_test.c\n    Add tests for SDS files.\n\n    * src/sds.c\n    Fix a bug in header update code.\n\n2003-11-23  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sds.c\n    Get file write working.\n\n    * src/paf.c\n    Fix a potential bug in paf24_seek().\n\n2003-11-04  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * doc/FAQ.html\n    Add Q/A about u-law encoded WAV files.\n\n    * Win32/*.h\n    Updated so it compiles on Win32.\n\n2003-11-03  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * examples/sndfile-convert.c\n    Add -alaw and -ulaw command line arguments.\n\n    * configure.ac\n    Add library versioning comments.\n    Add arguments to AC_INIT.\n\n2003-10-28  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/file_io.c\n    Ross Bencina has contributed code to replace all of the (mostly broken)\n    Win32 POSIX emulation calls with calls the native Win32 file I/O API.\n    This code still needs testing but is likely to be a huge improvemnt\n    of support for Win32. Thanks Ross.\n\n2003-10-27  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/dwvw.c\n    Removed filedes field from the DWVW_PRIVATE struct.\n\n    * src/file_io.c\n    Change psf_fopen() so it returns psf->error instead of the file descriptor.\n    Add new functions psf_set_stdio() and psf_set_file().\n\n    * src/sndfile.c\n    Change these to work with changed psf_fopen() return value.\n    Remove all uses of psf->filedes from sndfile, making it easier to slot native\n    Win32 API file handling functions.\n\n    * src/test_file_io.c\n    Minor changes to make it compile with new file_io.c stuff.\n\n2003-10-26  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/gsm610.h\n    Rename a variable from true to true_flag. As Ross Bencina points out,\n    true is defined in the C99 header <stdbool.h>.\n\n    * src/file_io.c\n    If fstat() fails, return SF_TRUE instead of -1 (Ross Bencina).\n\n2003-10-09  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/common.h\n    Increase the size of SF_BUFFER_LEN and SF_HEADER_LEN.\n\n    * src/sndfile.c\n    Fix sf_read/write_raw which were dividing by psf->bytwidth and\n    psf->blockwidth which can both be zero.\n\n    * examples/sndfile-info.c\n    Increase size of BUFFER_LEN.\n\n2003-09-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.ac\n    Add checks for <sys/wait.h> and ssize_t.\n    Other Win32/MinGW checks.\n\n    * src/aiff.c src/au_g72x.c src/file_io.c src/gsm610.c src/interleave.c\n      src/paf.c src/sds.c src/svx.c src/voc.c src/w64.c src/wav.c src/xi.c\n    Fix compiler warnings.\n\n2003-09-20  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/scale_clip_test.tpl\n    Add definition of M_PI if needed.\n\n2003-09-19  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.ac\n    Detect if S_IRGRP is declared in <unistd.h>.\n\n    * src/file_io.c tests/*.tpl tests/*.c\n    More fixes for Win32/MSVC++ and MinGW. MinGW does have <unistd.h> but that\n    file doesn't declare S_IRGRP.\n\n2003-10-18  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/config.h.in\n    Add comment stating that the sf_count_t typedef is determined when\n    libsndfile is being compiled.\n\n    * tests/utils.tpl\n    Modified so that utils.c gets one copy of the GPL and not two.\n\n\n2003-09-17  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * Win32/unistd.h src/sf_unistd.h\n    Move first file to the second. This will help for Win32/MSVC++ and MinGW.\n\n    * Win32/Makefile.am src/Makefile.am\n    Changed in line with above.\n\n    * Win32/Makefile.msvc\n    Removed \"/I Win32\" which is no longer required.\n\n    * src/file_io.c src/test_file_io.c tests/*.tpl tests/*.c\n    If HAVE_UNISTD_H include <unistd.h> else include <sf_unistd.h>. This should\n    work for Win32, MinGW and other fakes Unix-like OSes.\n\n    * src/*.c\n    Removed #include <unistd.h> from files which didn't need it.\n\n2003-09-16  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * libsndfile.spec.in\n    Apply fix from Andrew Schultz.\n\n2003-09-07  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/vox_adpcm.c\n    Only set psf->sf.samplerate if the existing value is invalid.\n\n2003-09-06  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * examples/sndfile-play.c\n    Started adding support for ALSA output.\n\n2003-09-04  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.h.in\n    Removed <stdlib.h> from sndfile.h.\n\n    * src/*.c examples/*.c tests/*.c tests/*.tpl\n    Added <stdlib.h> where needed.\n\n2003-09-02  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/common.h\n    Added ARRAY_LEN, SF_MAX and SF_MIN macros.\n\n2003-08-19  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * doc/index.html\n    Remove statements about alternative licensing arrangements.\n\n2003-08-17  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * MacOS MacOS9 Makefile.am configure.ac\n    Change directory name from MacOS to MacOS9\n\n    * MacOS9/MacOS9-readme.txt\n    Change name to make it really obvious, add text to top of file to make it\n    still more obvious again.\n\n2003-08-16  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/test_log_printf.c\n    Add tests for %u conversions.\n\n    * src/common.c\n    Fix psf_log_printf() %u conversions.\n\n2003-08-15  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/aiff.c\n    Fixed a bug where opening a file with a non-trival header in SFM_RDWR mode\n    would over-write part of the header. Thanks to Axel Röbel for pointing\n    this out. Axel also provided a patch to fix this but I came up with a\n    neater and more general solution.\n    Return error when openning an AIFF file with data after the SSND chunk\n    (Thanks Axel Röbel).\n\n    * tests/aiff_rw_test.c\n    Improvements to test program which will later allow it to be generalised to\n    test WAV, SVX and others as required.\n\n2003-08-14  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/pipe_test.c\n    Add useek_pipe_rw_test() submitted by Russell Francis.\n\n    * src/sndfile.c\n    In sf_open_fd(), check if input file descriptor is a pipe.\n\n    * src/sndfile.[ch]\n    Fix typo in variable name do_not_close_descriptor.\n\n2003-08-13  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/test_log_printf.c\n    Improve the tests for %d and %s conversions.\n\n    * src/common.c\n    Fixed a few problems in psf_log_printf() found using new tests.\n\n2003-08-06  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.ac\n    Add -Wwrite-strings warning to CFLAGS if the compiler is GCC. Thanks to\n    Peter Miller (Aegis author) for suggesting this and supplying a patch.\n\n    * src/*.c examples/*.c tests/*.c\n    Fix all compiler warnings arising from the above.\n\n2003-08-02  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/aiff_rw_test.c tests/Makefile.am\n    New test program to check for errors re-writing the headers of AIFC files\n    opened in mode SFM_RDWR.\n\n2003-07-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * examples/sndfile-play.c\n    Applied a patch from Tero Pelander to allow this program to run on systems\n    using devfs which used /dev/sound/dsp instead of /dev/dsp.\n\n2003-07-11  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * doc/new_file_type.HOWTO\n    Updated document. Still incomplete.\n\n2003-06-29  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.c\n    Fix VALIDATE_SNDFILE_AND_ASSIGN_PSF which was returning an error rather\n    than saving it and returning zero.\n\n2003-06-25  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/file_io.c\n    Two fixes for Mac OS9.\n    Fix all casts from sf_count_t to ssize_t (not size_t).\n\n2003-06-22  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/wav.c\n    Fix for reading files with RIFF length of 8 and data length of 0.\n\n2003-06-14  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/*.c tests/*.c tests/*.tpl\n    Added comments to mark code for removal when make Lite version of\n    libsndfile.\n\n2003-06-09  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * examples/sndfile-convert.c\n    Add extra error checking for unrecognised arguments.\n\n2003-06-08  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/ima_adpcm.c\n    Started adding code to write IMA ADPCM encoded AIFF files.\n\n    * src/test_log_printf.c src/Makefile.am\n    New file to test psf_log_printf() function and add hooks into build system.\n\n    * src/common.c\n    Move psf_log_printf() function to top of the file and only compile the rest\n    of the file if if PSF_LOG_PRINTF_ONLY is not defined.\n\n2003-06-03  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * Win32/config.h Win32/sndfile.h\n    Updated with new config variables.\n\n    * Win32/unistd.h src/file_io.c\n    Added implementation of S_ISFIFO macro which Win32 seems to lack and is\n    used in src/file_io.c.\n\n    * tests/utils.tpl\n    Added #include <unitstd.h> to pull in Win32/unistd.h so it compiles for\n    Win32.\n\n    * src/Makefile.msvc\n    Added src\\test_file_io.exe build target and run this as the very first\n    test.\n\n    * tests/win32_test.c\n    Add support for testing Cygwin32.\n\n    * configure.ac\n    Detect POSIX fsync() and fdatasync() functions.\n\n    * src/file_io.c\n    If compiling for Cygwin, call fsync() before calling fstat() to retrieve\n    file length.\n\n    * tests/pcm_test.tpl\n    Add a test for lrintf() function. This was required to detect a really\n    broken lrint() and lrintf() on Cygwin.\n\n    * tests/misc_test.c\n    Don't run permission test when compiling under Cygwin.\n\n    * src/float_cast.h\n    Fix fallback macro for lrint() and lrintf() to cast to long instead of int\n    to match official function prototypes.\n\n2003-06-02  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * examples/sndfile-convert.c\n    Modifications to improve accuracy of conversions; use double data for\n    floating point and int for everything else.\n\n    * src/ima_apdcm.c\n    Completed work on decoding IMA ADPCM encoded AIFF files. Still need to\n    get encoding working.\n\n2003-05-28  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/aiff.c src/ima_adpcm.c\n    Start working on getting IMA ADPCM encoded AIFF files working.\n\n2003-05-27  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.ac\n    Fixed the touch command for when the autogen program is not found (Matt\n    Flax).\n\n    * src/ulaw.c src/alaw.c\n    Made these pipe-able.\n\n2003-05-24  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/paf.c src/ircam.c\n    Fixed writing to pipe.\n\n    * src/wav.c src/aiff.c src/nist.c src/mat*.c src/svx.c src/w64.c\n    Return SFE_NO_PIPE_WRITE if an attempt is made to write to a pipe.\n\n2003-05-23  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * examples/sndfile-info.c\n    Modified to detect unknown file lengths.\n\n    * src/mat4.c\n    Fix reading from a pipe.\n\n2003-05-22  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/pipe_test.c\n    Add more file types to tests.\n\n    * src/mat4.c\n    Removed explicit setting of psf->sf.seekable to SF_TRUE.\n\n    * tests/utils.tpl\n    Add macro for generating and check data in the stdio and pipe tests.\n\n    * tests/stdout_test.c tests/stdin_test.c\n    Use the above macro to generate known data on output and check data on\n    input.\n\n    * src/voc.c src/htk.c common.h sndfile.c\n    Disallow reading/writing VOC and HTK files from/to pipes be returning new\n    error values.\n\n    * src/w64.c\n    Fixes to allow reading from a pipe.\n\n2003-05-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.ac src/sndfile.h.in\n    When the configure script determines the sizeof (sf_count_t), also set the\n    value of SF_COUNT_MAX in sndfile.h.\n\n    * configure.ac\n    Remove -pedantic flag from default GCC compiler flags.\n\n    * tests/pipe_test.c\n    Add a pipe_read_test() before doing pipe_write_test().\n\n    * tests/scale_clip_test.c\n    Add test to make sure non-normalized values also clip in the right way.\n\n2003-05-18  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.ac\n    Add test to detect processor clipping capabilities.\n\n    * tests/stdin_test.c tests/stdout_test.c\n    Fix a pair of compiler warnings.\n\n    * src/common.h\n    Add new pipeoffset field to SF_PRIVATE. This will contain the current file\n    offset when operating on a pipe.\n\n    * src/common.c\n    Removed direct calls to psf_fread()/psf_fseek()/psf_fgets() etc from\n    psf_binheader_readf and redirect them to new buffered versions\n    header_read(), header_seek() and header_gets().\n    Add \"G\" format specifier to emulate fgets() functionality with buffering.\n    This will allow reading some file types from pipes.\n\n    * src/file_io.c\n    When the file descriptor is a pipe, manintain psf->pipeoffset.\n\n    * src/pvf.c\n    Change use of psf_fgets() to psf_binheader_readf() as required but changes to header re\n\n    * src/au.c\n    Fix reading from a pipe.\n\n2003-05-17  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/pcm.c\n    Add clipping versions of the f2XXX_array() functions to allow option of\n    clipping data that would otherwise overflow.\n\n    * tests/scale_clip_test.tpl tests/scale_clip_test.def\n    New files test that clipping option does actually work.\n\n2003-05-14  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * doc/index.html\n    Fixed a typo (\"OS(\" instead of \"OS9\").\n\n2003-05-13  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/open_fail_test.c\n    Include <string.h> to prevent warning message of missing declaration of\n    memset().\n\n2003-05-12  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/common.h\n    Add new \"add_clipping\" field to SF_PRIVATE.\n\n    * src/sndfile.h.in src/sndfile.c\n    Add command SFC_SET_CLIPPING which sets/resets add_clipping field.\n\n2003-05-11  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * doc/api.html\n    Add docs for sf_set_string() and sf_get_string().\n\n    * src/common.h src/sndfile.c\n    Add new SFE_STR_BAD_STRING error.\n\n    * tests/stdin_test.c tests/stdout_test.c\n    Removed all non-error print statements.\n\n    * tests/stdio_test.c tests/pipe_test.c tests/Makefile.am\n    Add print statements removed from two files above.\n\n2003-05-10  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * libsndfile.spec.in\n    Fixed a coulpe of minor errors discovered by someone calling themselves\n    Agent Smith.\n\n    * src/common.c src/common.h src/file_io.h\n    Added is_pipe field to SF_PRIVATE and declaration of psf_is_pipe()\n    function. (Axel Röbel)\n\n    * src/sndfile.c\n    Fixed determination of whether the file is a pipe. (Axel Röbel)\n\n    * src/paf.c\n    Force paf24 to start with undefined mode. (Axel Röbel)\n\n    * tests/pipe_test.c\n    Mods to make this test work and actually do the test on RAW files. (Axel\n    Röbel).\n\n2003-05-05  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.c\n    Fixed a potential bug where psf->sf.seekable was being set to FALSE when\n    operating on stdin or stdout but then the default initialiser was reseting\n    it to TRUE. Thanks to Axel Röbel.\n\n    * src/aiff.c\n    Fixed a bug in the header parser where it was not handling an odd length\n    COMM chunk correctly. Thanks to Axel Röbel.\n\n    * src/test_file_io.c\n    Add more tests.\n\n    * tests/win32_test.c\n    New file for showing the bugs in the Win32 implementation of the POSIX API.\n    It also runs on Linux for sanity checking.\n\n    * tests/Makefile.am Win32/Makefile.msvc\n    Hook the new test program into the build system.\n\n2003-05-04  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/test_file_io.c\n    New test program to test operation of functions defined in file_io.c. This\n    should make supporting win32 significantly easier.\n\n    * src/Makefile.am\n    Hook new test program into the build system.\n\n    * src/file_io.c\n    Add compile/run time check that sizeof statbuf.st_size and sf_count_t are\n    the same.\n\n    * src/common.h src/sndfile.c\n    Added new error code and error message for new check.\n\n    * tests/benchmark.tpl\n    Fix to use frames instead of samples in SF_INFO.\n\n2003-05-03  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/file_io.c\n    More stuffing about working around PLAIN OLD-FASHIONED **BUGS** in Win32.\n\n    * examples/sndfile-info.c\n    Applied patch from Conrad Parker to add \"--help\" and \"-h\" options as\n    well as an improved usage message.\n\n2003-05-02  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/au.c\n    Added embedded file support.\n\n    * tests/multi_file_test.c\n    Added tests for embedded AU files.\n    Added verbose testing mode.\n\n    * src/common.h src/sndfile.c\n    Added an embedded AU specific error code and message.\n\n    * src/wav.c\n    Added patch from Conrad Parker which filled in a little more information\n    about ACIDized WAV files.\n\n2003-04-30  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/file_io.c\n    Fixed Win32 version of psf_fseek() which was calling psf_get_filelen()\n    which was in turn calling psf_fseek() which in the end blew the stack.\n    Now of course this would have been easy to find on Linux, but this blow\n    up was happening in kernel32.dll and the fscking MSVC++ debugger couldn't\n    figure out what call caused this (it couldn't even tell me the stack had\n    overflowed) and was absolutley useless for this debugging exercise.\n    On top of that, the reason I got into this mess was that windoze doesn't\n    have a working fstat() function which can return file lengths > 2 Gig. It\n    HAS a fscking _fstati64() but the file length value is only updated AFTER\n    the bloody file is closed. That makes it completely useless.\n    How the hell do people stand working on this crap excuse of an OS?\n\n2003-04-29  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * Win32/unistd.h src/file_io.c\n    Moved definitions of S_IGRP etc from file_io.c to unistd.h so that these\n    can be used in the test programs.\n\n    * Win32/libsndfile.def\n    Added sf_open_fd.\n\n    * Win32/sndfile.h\n    Updated to match src/sndfile.h.in.\n\n    * Win32/Makefile.msvc\n    Added dither.c and htk.c to libsndfile.dll target.\n\n2003-04-28  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/file_io.c\n    First attempt at getting the Win32 versions of the these functions working.\n    They still need to be tested.\n\n2003-04-27  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/strings.c\n    Found and fixed a bug which was causing psf_store_string() to fail on\n    Motorola 68k processors. Many thanks to Joshua Haberman (Debian maintainer\n    of libsndfile) for compiling and running debug code to help me debug the\n    problem.\n\n2003-04-26  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.c src/file_io.c src/wav.c src/aiff.c\n    Much hacking to get reading and writing of embedded files working (ie sound\n    files at a non-zero files offset).\n\n    * doc/embedded_files.html\n    First pass atempt at documenting reading/writing embedded files.\n\n2003-04-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * doc/FAQ.html\n    Updated answer to \"Why doesn't libsndfile do interleaving/de-interleaving?\"\n\n2003-04-19  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/wav.c src/aiff.c\n    Fix retrieving and storing of string data from files. Need to be careful\n    about using psf->buffer for strings.\n\n2003-04-18  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/file_io.c\n    Fix psf_fseek() for seeks withing embedded files.\n\n2003-04-15  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.h.in\n    Changed the definition of SNDFILE slightly to produce warnings when it isn't\n    used correctly. This should have zero affect in code which uses the SNDFILE\n    type correctly.\n\n    * src/sndfile.c\n    Fixed a few compiler warnings cause by the changes to the SNDFILE type.\n\n2003-04-12  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * doc/FAQ.html\n    Added question and answer to the question \"How about adding the ability\n    to write/read sound files to/from memory buffers?\".\n\n2003-04-08  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/write_read_test.tpl\n    Removed un-needed enums declaring TRUE and FALSE and replaced usage of\n    these with SF_TRUE and SF_FALSE.\n\n    * tests/multi_file_test.c\n    New test program to test sf_open_fd() on files containing data other than\n    a single sound file.\n\n2003-04-06  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/file_io.c\n    When creating files, set the readable by others flag. This still allows\n    further restrictions to be enforced by use of the user's umask. Fix\n    suggested by Eric Lyon.\n\n2003-04-05  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.h.in src/sndfile.c\n    Changed sf_open_fd(). Dropped offset parameter and added a close_desc\n    parameter. If close desc is TRUE, the file descritpor passed into the\n    library will be closed when sf_close() is called.\n\n    * tests/utils.tpl\n    Modified call to sf_open_fd() to set close_desc parameter to SF_TRUE.\n\n2003-04-04  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/write_read_test.tpl\n    Add a string (using sf_set_string() function) before and after data section\n    of all files. This will make sure that if string data can be added, it\n    doesn't overwrite real audio data.\n\n2003-04-02  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.c\n    Started work on supporting a non-zero offset parameter for sf_open_fd ().\n\n    * src/<file header parsers>.c\n    Removed many uses of psf_fseek (SEEK_END) which to allow for future use of\n    sf_open_fd() with non-zero offset.\n    Associated refactoring.\n\n    * src/aiff.c\n    Implemented functionality required to get sf_get_string() and\n    sf_set_string() working for AIFF files.\n\n2003-04-01  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/utils.tpl\n    Modified test_open_file_or_die() to alternately use sf_open() and\n    sf_open_fd().\n\n    * src/svx.c\n    Fixed a bug which occurred when openning an existing file for read/write\n    using sf_open_fd(). In this case, the existing NAME chunk needs to be\n    read into psf->filename.\n    Fixed printing of sf_count_t types to logbuffer.\n\n2003-03-31  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.h.in\n    Added prototype for new function sf_open_fd().\n\n    * src/sndfile.c\n    Moved most of the code in sf_open() to a new function psf_open_file().\n    Created new function sf_open_fd() which also uses psf_open_file() but\n    does not currently support the offset parameter.\n\n    * doc/api.html\n    Document sf_open_fd().\n\n2003-03-09  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.c\n    Fixed a memory leak reported by Evgeny Karpov. Memory leak only occurred\n    when an attempt was made to read and the open() call fails.\n\n2003-03-08  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/open_fail_test.c\n    New test program to check for memory leaks when sf_open fails on a valid\n    file. Currently this must be run manually under valgrid.\n\n    * tests/Makefile.am\n    Hook new test program into build.\n\n2003-03-03  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * Octave/sndfile_save.m Octave/sndfile_play.m\n    Added a -mat-binary option to the octave save command to force the output\n    to binary mode even if the user has set ascii data as the default. Found\n    by Christopher Moore.\n\n2003-02-27  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * doc/dither.html\n    New file which will document the interface which allows the addition of\n    audio dither when sample word sizes are being reduced.\n\n    * src/dither.c\n    More work.\n\n2003-02-26  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/misc_test.c\n    In update_header_test(), make HTK files a special case.\n\n    * doc/index.html\n    Added HTK to the feature matrix.\n\n2003-02-25  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/htk.c\n    New file for reading/writing HMM Tool Kit files.\n\n    * src/sndfile.h.in src/sndfile.c src/command.c src/Makefile.am\n    Hook in htk.c\n\n    * tests/write_read_test.tpl tests/misc_test.c tests/Makefile.am\n    Add tests for HTK files.\n\n2003-02-22  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/wav.c\n    Fixed a bug where the LIST chunk length was being written incorrectly.\n\n    * tests/string_test.c\n    Added call to check_log_buffer().\n    Minor cleanups.\n\n2003-02-10  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/wav_w64.h\n    Applied patch from Antoine Mathys to add extra WAV format definitions and\n    a G72x_ADPCM_WAV_FMT struct definition.\n\n    * src/wav_w64.c\n    Applied patch from Antoine Mathys which converts wav_w64_format_str() from\n    one huge inefficient switch statement to a binary search.\n\n    * tests/string_test.c\n    Dump log buffer if tests fail.\n\n2003-02-07  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/string_test.c\n    David Viens supplied some modifications to this file which showed up a bug\n    when using sf_set_string() and the sf_writef_float() functions.\n\n    * src/sndfile.c\n    Fixed the above bug.\n\n2003-02-06  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * doc/FAQ.html\n    Added Q and A on how to detect libsndfile in configure.in (at the suggestion\n    of Davy Durham).\n\n2003-02-05  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.h.in\n    Add enums and typedefs for dither.\n    Deprecate SFC_SET_ADD_DITHER_ON_WRITE and SFC_SET_ADD_DITHER_ON_READ, to be\n    replaced with SFC_SET_DITHER_ON_WRITE and SFC_SET_DITHER_ON_READ which will\n    allow different dither algorithms to be enabled.\n    Added SFC_GET_DITHER_INFO_COUNT and SFC_GET_DITHER_INFO.\n\n    * src/sndfile.h.in src/Version_script.in Win32/libsndfile.def.\n    Added public sf_dither_*() functions.\n\n    * src/sndfile.c\n    Implement commands above.\n\n    * src/dither.c\n    More work. Framework and external hooks into dither algorithms complete.\n\n2003-02-03  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * doc/version-1.html libsndfile_version_convert.py\n    Remove redundant files.\n\n    * doc/index.html doc/api.html\n    Remove links to version-1.html.\n\n    * src/dither.c\n    New file to allow the addition of audio dither on input and output.\n\n    * src/common.h\n    Add prototype for dither_init() function.\n\n    * Makefile.am doc/Makefile.am\n    Changes for added and removed files.\n\n2003-02-02  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * Win32/Makefile.msvc\n    Changes to force example binaries to be placed in the top level directory\n    instead of the examples/ directory.\n    Add src/strings.c and src/xi.c to the build.\n    Add string_test to build and to tests on WAV files.\n\n    * doc/index.html\n    Added XI to support matrix.\n\n2003-01-27  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.h.in\n    Added prototypes for sf_get_string() and sf_set_string() and SF_STR_*\n    enum values.\n\n    * src/sndfile.c\n    Added public interface to sf_get_string() and sf_set_string().\n\n    * src/wav.c\n    Added code for setting and getting strings in WAV files.\n\n    * tests/string_test.c\n    New test program for sf_get_string() and sf_set_string() functionality.\n\n    * tests/Makefile.am\n    Hook new test program into build and test framework.\n\n2003-01-26  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/common.h\n    Added fields to SF_PRIVATE for string data needed to implement\n    sf_get_string() and sf_set_string().\n\n    * src/strings.c\n    New file for storing and retrieving strings to/from files.\n\n    * src/Makefile.am\n    Added strings.c to build.\n\n2003-01-25  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/xi.c\n    Read seems to be working so looking at write.\n\n    * src/sndfile.h.in\n    Added SF_FORMAT_XI, SF_FORMAT_DPCM_8 and SF_FORMAT_DPCM_16 enum values.\n\n    * tests/floating_point_test.c tests/lossy_comp_test.c tests/Makefile.am\n    Added test for 8 and 16 bit XI format files.\n\n2003-01-24  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * doc/index.html\n    Added a non-lawyer readable summary of the licensing provisions as\n    suggested by Steve Dekorte.\n\n2003-01-23  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/wav.c\n    Fixed a compiler warning found by Alexander Lerch.\n\n2003-01-18  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.ac\n    Fixed the multiple linking of libm.\n\n2003-01-17  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * Win32/Makefile.mcvs\n    Added comments on the correct way to set up the MSVCDir environment\n    variable.\n\n    * doc/win32.html\n    Add on how to set up the MSVCDir environment variable.\n\n2003-01-15  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * examples/sndfile-play.c examples/sndfile-info.c\n    When run on Win32 without any command line parameters print a message and\n    then sleep for 5 seconds. This means the when somebody double clicks on\n    these programs in explorer the user will actually see the message.\n\n2003-01-14  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/misc_test.c\n    Bypass permission test if running as root because root is allowed to open\n    a readonly file for write.\n\n2003-01-08  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * Win32/Makefile.msvc\n    Added pvf.c and xi.c source files to project.\n\n    * src/sndfile.h\n    Updated for PVF files.\n\n2003-01-07  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.c\n    Modified validate_sfinfo() to force samplerate, channels and sections\n    to be >= 1.\n    In format_from_extension() replaced calls to does_extension_match()\n    with strcmp().\n\n    * src/xi.c\n    More work.\n\n2003-01-06  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * doc/Makefile.am\n    Added octave.html which had been left out. Found by Jan Weil.\n\n2003-01-05  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/pvf.c src/common.h src/sndfile.c\n    Fixed error handling for PVF files.\n\n    * src/xi.c\n    New file for handling Fasttracker 2 Extended Instrument files. Not working\n    yet and included when configured with --enable-experimental.\n\n    * src/sndfile.c src/common.h\n    Hooked in new file xi.c.\n\n2002-12-30  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/rx2.c\n    Added a patch from Marek Peteraj which sheds a little more light on the\n    slices within an RX2 file. Still need to find out data encoding.\n\n2002-12-20  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/wav.c\n    Started work on decoding 'acid' and 'strc' chunks.\n\n2002-12-14  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/peak_check_test.c\n    Minor cleanup.\n\n2002-12-12  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/write_read_test.tpl\n    Added check to make sure no error was generated when an attempt was made to\n    read past the end of the file.\n\n2002-12-11  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * doc/lists.html\n    Added \"mailto\" links for all three lists.\n\n    * src/pvf.c\n    New file for Portable Voice Format files.\n\n    * src/sndfile.h.in src/sndfile.c src/common.h src/command.c src/Makefile.am\n    Added hooks for SF_FORMAT_PVF format files.\n\n    * tests/write_read_test.tpl tests/std*.c\n    Add tests for SF_FORMAT_PVF.\n\n    * doc/index.html\n    Add PVF to the compatibility matrix.\n\n    * src/pcm.c src/alaw.c src/ulaw.c src/float32.c src/double64.c\n    Previously, attempts to read beyond the end of a file would set psf->error\n    to SFE_SHORT_ERROR. This behaviour diverged from the behaviour of the POSIX\n    read() call but has now been fixed.\n    Attempts to read beyond the end of the file will return a short read count\n    but will not longer set any error.\n\n2002-12-09  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.c\n    Add more sanity checking when opening a RAW file for read. When format is\n    not RAW, zero out all members of the SF_INFO struct.\n\n    * tests/raw_test.c\n    Add bad_raw_test() to check for above problem.\n\n    * tests/stdin_test.c examples/sndfile-info.c\n    Set the format field of the SF_INFO struct to zero before calling\n    sf_open().\n\n    * doc/api.html\n    Add information about the need to set the format field of the SF_INFO struct\n    to zero when opening non-RAW files for read.\n\n    * configure.ac\n    Removed use of conversion script on Solaris. Not all Solaris versions\n    support it.\n\n    * doc/lists.html\n    New file containg details of the mailing lists.\n\n    * doc/index.html\n    Add a link to the above new file.\n\n2002-12-04  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/dft_cmp.c\n    Fixed a SIGFPE on Alpha caused by a log10 (0.0). Thanks to Joshua Haberman\n    for providing the gdb traceback.\n\n2002-11-28  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/wav.c\n    Added more capabilities to 'smpl' chunk parser.\n\n    * src/sndfile.c\n    Fixed some (not all) possible problems found with Flawfinder.\n\n2002-11-24  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.c\n    Fixed a bug in sf_seek(). This bug could only occur when an attempt was\n    made to read beyond the end and then sf_seek() was called with a whence\n    parameter of SEEK_CUR.\n\n    * src/file_io.c\n    Win32's _fstati64() does not work, it returns BS. Re-implemented\n    psf_get_filelen() in terms of psf_fseek().\n\n    * tests/write_read_test.tpl\n    Add a test to detect above bug.\n\n    * src/float_cast.h\n    Modification to prevent compiler warnings on Mac OS X.\n\n    * src/file_io.c\n    Fixes for windows (what a f**ked OS).\n\n2002-11-08  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.ac\n    Disable use of native lrint()/lrintf() on Mac OSX. These functions exist on\n    Mac OSX 10.2 but not on 10.1. Forcing the use of the versions in\n    src/float_cast.h means that a library compiled on 10.2 will still work on\n    10.1.\n\n2002-11-06  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.in configure.ac\n    Renamed configure.in to configure.ac as expected by later versions of\n    autoconf.\n    Slight hacking of configure.ac to work with version 2.54 of autoconf.\n    Changed to using -dumpversion instead of --version for determining GCC\n    version numer as suggested by Anand Kumria.\n\n    * src/G72x/Makefile.am\n    Slight hacking required for operation with automake 1.6.3.\n\n2002-11-05  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/common.c\n    In psf_binheader_readf() changed type parameter type \"b\" type from size_t\n    to int to prevent errors on IA64 CPU where sizeof (size_t) != sizeof (int).\n    Thanks to Enrique Robledo Arnuncio for debugging this.\n\n2002-11-04  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * test/command_test.tpl\n    Changed test value so test would pass on Solaris.\n\n    * src/Version_script.in\n    Modified version numbering so that later versions of 1.0.X can replace\n    earlier versions without recompilation.\n\n    * src/vox_adpcm.c\n    Fixed bug causing short reads.\n\n2002-11-03  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * test/floating_point_test.c\n    Code cleanup using functions from util.c.\n    Add test for IEEE replacement floats and doubles.\n\n2002-11-01  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/wav.c\n    Fixed a possible divide by zero error when read the 'smpl' chunk. Thanks to\n    Serg Repalov for the example file.\n\n    * tests/pcm_test.tpl\n    Used sf_command (SFC_TEST_IEEE_FLOAT_REPLACE) to test IEEE replacement code.\n    Clean up pcm_double_test().\n\n    * src/float32.c src/double64.c\n    Force use of IEEE replacement code using psf->ieee_replace is TRUE,\n    Print message to log_buffer as well.\n    Rename all broken_read_* and broken_write* functions to replace_read_* and\n    replace_write_*.\n\n    * tests/util.tpl\n    Added string_in_log_buffer().\n\n    * tests/pcm_test.tpl\n    Use string_in_log_buffer() to ensure that IEEE replacement code has been\n    used.\n\n    * configure.in\n    Removed --enable-force-broken-float option. IEEE replacement code is now\n    always tested.\n\n2002-10-31  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/double64.c\n    Implement code for read/writing IEEE doubles on platforms where the native\n    double format is not IEEE.\n\n    * src/float32.c src/common.h\n    Remove float32_read() and float32_write(). Replace with float32_le_read(),\n    float32_be_read(), float32_le_write() and float32_be_write() to match stuff\n    in src/double64.c.\n\n    * src/common.c\n    Fix all usage of float32_write().\n\n    * src/sndfile.h.in\n    Added SFC_TEST_IEEE_FLOAT_REPLACE command (testing only).\n\n    * src/common.h\n    Added SF_PRIVATE field ieee_replace.\n\n    * src/sndfile.c\n    In sf_command() set/reset psf->ieee_replace.\n\n2002-10-26  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/pcm_test.tpl\n    Fixed a problem when testing with --enable-force-broken-float. The test was\n    generating a value of negative zero and the broken float code is not able\n    to write negative zero. Removing the negative zero fixed the test.\n\n2002-10-25  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/file_io.c\n    Added fix for Cygwin (suggested by Maros Michalik).\n\n2002-10-23  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/file_io.c\n    Improved error detection and handling.\n\n    * src/file_io.c src/common.h\n    Removed functions psf_ferror() and psf_clearerr() which were redundant\n    after above improvements.\n\n    * src/aiff.c src/svx.c src/w64.c src/wav.c\n    Removed all use of psf_ferror() and psf_clearerr().\n\n    * src/sndfile.c\n    Removed #include of <stdio.h>, <unistd.h>, <fcntl.h> and <math.h> which\n    are no longer needed.\n\n    * tests/misc_test.c\n    Added test to make sure the correct error message is returned with an\n    existing read-only file is openned for write.\n\n2002-10-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * doc/index.html doc/api.html\n    Updated for OKI Dialogic ADPCM files.\n\n    * src/command.c\n    Added VOX ADPCM to sub_fomats.\n\n2002-10-20  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/vox_adpcm.c src/Makefile.am\n    New file for handling OKI Dialogic ADPCM files.\n\n    * src/sndfile.h\n    Add new subtype SF_FORMAT_VOX_ADPCM.\n\n    * src/sndfile.c\n    Renamed function is_au_snd_file () to format_from_extenstion () and expanded\n    its functionality to detect headerless VOX files.\n\n    * src/raw.c\n    Added hooks for SF_FORMAT_VOX_ADPCM.\n\n    * examples/sndfile-info.c\n    Print out file duration (suggested by Conrad Parker).\n\n    * libsndfile.spec.in\n    Force installation of sndfile.pc file (found by John Thompson).\n\n    * tests/Makefile.am tests/lossy_comp_test.c tests/floating_point_test.c\n    Add tests for SF_FORMAT_VOX_ADPCM.\n\n2002-10-18  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/misc_test.c\n    Add test which attempts to write to /dev/full (on Linux anyway) to check\n    for correct handling of writing to a full filesystem.\n\n    * src/sndfile.c\n    Return correct error message if the header cannot be written because the\n    filesystem is full.\n\n    * tests/util.tpl\n    Corrected printing of file mode in error reporting.\n\n    * src/mat5.c\n    Fixed a bug where a MAT5 file written by libsndfile could not be opened by\n    Octave 2.1.36.\n\n2002-10-13  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/common.h src/file_io.c\n    All low level file I/O have been modified to be better able to report\n    system errors resulting from calling system level open/read/write etc.\n\n    * src/*.c\n    Updated for compatibility with above changes.\n\n    * examples/cooledit-fixer.c\n    New example program which fixes badly broken file created by Syntrillium's\n    Cooledit which are marked as containing PCM samples but actually contain\n    floating point data.\n\n    * examples/Makefile.am\n    Hooked cooledit-fixer into the build system.\n\n2002-10-10  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * doc/command.html\n    Document SFC_GET_FORMAT_INFO.\n\n2002-10-09  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * examples/wav32_aiff24.c examples/sndfile2oct.c examples/sfhexdump.c\n        examples/sfdump.c\n    Removed these files because they weren't interesting.\n\n    * examples/sfconvert.c examples/sndfile-convert.c\n    Renamed the first to the latter.\n\n    * examples/Makefile.am\n    Added sndfile-convert to the bin_PROGRAMS, so it is installed when the lib\n    is installed.\n    Removed old programs wav32_aiff24 and sndfile2oct.\n\n    * man/sndfile-convert.1\n    New man page.\n\n    * examples/sndfile-convert.c\n    Added some gloss now that sndfile-convert.c is an installed program.\n\n    * src/sndfile.h.in src/sndfile.c src/common.h src/command.h\n    Added command SFC_GET_FORMAT_INFO.\n\n    * tests/command_test.c\n    Added tests form SFC_GET_FORMAT_INFO.\n\n2002-10-08  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.c\n    In sf_format_check() return error if samplerate < 0.\n\n2002-10-07  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/aiff.c\n    Fixed bug in handling of COMM chunks with a 4 byte encoding byte but no\n    encoding string.\n\n2002-10-06  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.c\n    Fixed repeated word in an error message.\n\n2002-10-05  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * doc/index.html\n    Improved advertising in Features section.\n\n2002-10-04  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/wav.c\n    Added decoding of 'labl' chunks within 'LIST' chunks.\n\n    * src/common.h\n    Added (experimental only) SF_FORMAT_OGG and SF_FORMAT_VORBIS and definition\n    of ogg_open(). This is nowhere near working yet.\n\n    * src/sndfile.c\n    Added detection of 'OggS' file marker and added call to ogg_open() to\n    switch statement.\n\n    * src/ogg.c\n    New file. Very early start of Ogg Vorbis support.\n\n    * src/wav.c\n    Added handling of brain-damaged and broken Cooledit \"32 bit 24.0 float\n    type 1\" files. These files are marked as being 24 bit WAVE_FORMAT_PCM with\n    a block alignment of 4 times the numbers of channels but are in fact 32 bit\n    floating point.\n\n2002-10-02  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.in\n    Modified option --enable-experimental to set ENABLE_EXPERIMENTAL_CODE in\n    config.h to either 0 or 1.\n\n    * src/sndfile.c\n    Modify sf_command (SFC_GET_LIB_VERSION) to append \"-exp\" to the version\n    string if experimental code has been enabled.\n\n2002-10-01  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/Makefile.am\n    Added -lm to libsndfile_la_LIBADD. This means that -lm is not longer needed\n    in the link line when linking something to libsndfile.\n\n    * tests/Makefile.am examples/Makefile.am\n    Removed -lm from all link lines.\n\n    * sndfile.pc.in\n    Removed -lm from Libs line.\n\n2002-09-24  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/file_io.c\n    Removed all perror() calls.\n\n    * src/nist.c\n    Removed calls to exit() function.\n    Added check to detect NIST files dammaged from Unix CR -> Win32 CRLF\n    conversion process.\n\n2002-09-24  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.h.in src/sndfile.c\n    New function sf_strerror() which will eventually replace functions\n    sf_perror() and sf_error_str().\n    Function sf_error_number() has also been changed, but this was documented\n    as being for testing only.\n\n    * doc/api.html\n    Documented above changes.\n\n    * tests/*.c examples/*.c\n    Changed to new error functions.\n\n2002-09-22  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.in\n    Detect GCC version, and print a warning message about writeable strings\n    it GCC major version number is less than 3.\n\n2002-09-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.h.in doc/api.html\n    Documentation fixes.\n\n2002-09-19  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/Version_script.in src/Makefile.am configure.in\n    Use the version script to prevent the exporting of all non public symbols.\n    This currently only works with Linux. Will test on Solaris as well.\n\n    * src/float_cast.h\n    Added #ifndef to prevent the #warning directives killing the SGI MIPSpro\n    compiler.\n\n    * src/au_g72x.c src/double64.c src/float32.c src/gsm610.c src/ima_adpcm.c\n        src/ms_adpcm.c\n    Fix benign compiler warnings arising from previously added compiler\n    flags.\n\n2002-09-18  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.c\n    Fixed a bug in sf_error_str() where errnum was used as the index instead\n    of k. Found by Tim Hockin.\n\n    * examples/sndfile-play.c\n    Fixed a compiler warning resulting from a variable shadowing a previously\n    defined local.\n\n2002-09-17  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.h.in src/sndfile.c\n    Added command SFC_SET_RAW_START_OFFSET.\n\n    * doc/command.html\n    Document SFC_SET_RAW_START_OFFSET.\n\n    * tests/raw_test.c tests/Makefile.am\n    Add new file for testing SF_FORMAT_RAW specific functionality.\n\n    * tests/dwvw_test.c\n    Updates.\n\n2002-09-16  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/wav.c\n    Modified reading of 'smpl' chunk to take account of the sampler data field.\n\n    * tests/utils.tpl tests/utils.h\n    Added function print_test_name().\n\n    * tests/misc_test.c tests/write_read_test.tpl tests/lossy_comp_test.c\n        tests/pcm_test.tpl tests/command_test.tpl tests/floating_point_test.c\n    Convert to use function print_test_name().\n\n2002-09-15  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * doc/octave.html\n    Added a link to some other Octave scripts for reading and writing sound\n    files.\n\n    * src/paf.c\n    Change type of dummy data field to int. This should fix a benign compiler\n    warning on some CPUs.\n    Removed superfluous casts resulting from the above change.\n\n    * src/rx2.c\n    More hacking.\n\n2002-09-14  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/mat5.c src/common.c\n    Changed usage of snprintf() to LSF_SNPRINTF().\n\n    * Win32/Makefile.msvc\n    Updated to include new files and add new tests.\n\n    * Win32/config.h Win32/sndfile.h\n    Updated.\n\n    * doc/api.html\n    Added note about the possibility of \"missing\" features actually being\n    implemented as an sf_command().\n\n2002-09-13  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/misc_test.c\n    Added previously missing update_header_test and zero_data_tests for PAF,\n    MAT4 and MAT5 formats.\n\n    * src/paf.c src/mat4.c src/mat5.c\n    Fixed bugs uncovered by new tests above.\n\n    * src/mat5.c\n    Generalised parsing of name fields of MAT5 files.\n\n    * src/mat5.c src/sndfile.c\n    Added support for unsigned 8 bit PCM MAT5 files.\n\n    * tests/write_read_test.tpl\n    Added test for unsigned 8 bit PCM MAT5 files.\n\n    * doc/index.html\n    Added unsigned 8 bit PCM MAT5 to capabilities matrix.\n\n2002-09-12  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * test/update_header_test.c tests/misc_test.c\n    Renamed update_header_test.c to misc_test.c.\n    Added zero_data_test() to check for case where file is opened for write and\n    closed immediately. The resulting file can be left in a state where\n    libsndfile cannot open it. Problem reported by Werner Schweer, the author\n    of Muse.\n\n    * src/aiff.c\n    Removed superfluous cast.\n\n    * src/wav.c src/svx.c\n    Fixed case of file generated with no data.\n    Removed superfluous cast.\n\n    * src/sndfile.c\n    Fixed error on IA64 platform caused by incorrect termination of\n    SndfileErrors struct array. This problem was found in the Debian buildd\n    logs (http://buildd.debian.org/).\n\n    * configure.in\n    Added Octave directory.\n\n    * Octave/Makefile.ma\n    New Makfile.am for Octave directory.\n\n    * Octave/sndfile_load.m Octave/sndfile_save.m Octave/sndfile_play.m\n    New files for working with Octave.\n\n    * doc/octave.html\n    Document explaining the use of the above three Octave scripts.\n\n2002-09-10  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.c\n    Fixed bug in RDWR mode.\n\n2002-09-09  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/common.c\n    Fixed psf_get_date_str() for systems which don't have gmtime_r() or\n    gmtime().\n\n    * src/file_io.c\n    Added #include <io.h> for Win32. Reported by Koen Tanghe.\n\n2002-09-08  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/common.c\n    Added 'S' format specifier for psf_binheader_writef() which writes a C\n    string, including single null terminator to the header.\n    Added 'j' format specifier to allow jumping forwards or backwards in the\n    header.\n    Added function psf_get_date_str().\n\n    * src/mat5.c\n    Complete read and write support.\n\n    * doc/index.html\n    Added entries for MAT4 and MAT5 in capabilities matrix.\n\n2002-09-06  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/mat4.c\n    Completed read and write support.\n\n    * src/common.h src/sndfile.c\n    Added MAT4 and MAT5 specific error messages.\n\n    * tests/write_read_test.tpl tests/Makefile.am\n    Added tests for MAT4 and MAT5 files.\n\n    * tests/stdio_test.c tests/stdout_test.c tests/stdin_test.c\n    Added tests for MAT4 and MAT5 files.\n\n2002-09-05  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/command.c\n    Added elements for SF_FORMAT_MAT4 and SF_FORMAT_MAT5 to major_formats\n    array.\n\n    * examples/sfconvert.c\n    Added mat4 and mat5 output targets.\n\n2002-09-04  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.c\n    Added check to prevent errors openning read only formats for read/write.\n\n    * src/interleave.c\n    New file for interleaving non-interleaved data. Non-interleaved data is\n    only supported on read.\n\n    * src/Makefile.am\n    Added src/interleave.c to build.\n\n2002-09-03  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/double64.c src/common.h\n    Added double64_be_read(), double64_le_read(), double64_be_write() and\n    double64_le_write() which replace double64_read() and double64_write().\n\n    * src/common.c\n    Cleanup of psf_binheader_readf() and add ability to read big and little\n    endian doubles (required by mat4.c and mat5.c).\n    Add ability for psf_binheader_writef() to write doubles to sound file\n    headers.\n\n2002-09-01  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/mat5.c\n    New file for reading Matlab (tm) version 5 data files. This is also the\n    native binary file format for version 2.1.X of GNU Octave which will be\n    used for testing.\n    Not complete yet.\n\n    * src/mat4.c\n    New file for reading Matlab (tm) version 4.2 data files. This is also the\n    native binary file format for version 2.0.X of GNU Octave which will be\n    used for testing.\n    Not complete yet.\n\n    * src/sndfile.h.in src/sndfile.c src/common.h src/command.c src/Makefile.am\n    Mods to add Matlab files.\n\n    * src/common.[ch]\n    Added readf_endian field to SF_PRIVATE struct allowing endianness to\n    remembered across calls to sf_binheader_readf().\n    Fixed bug in width_specifier behaviour for printing hex values.\n\n2002-08-31  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/file_io.c\n    Check return value of close() call in psf_fclose().\n\n2002-08-24  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/ms_adpcm.c\n    Commented out some code where 0x10000 was being subtracted from a short\n    and the result assigned to a short again. Andrew Zaja found this.\n\n2002-08-23  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * doc/command.html\n    Fixed typo found by Tommi Ilmonen.\n\n    * src/ima_adpcm.c\n    Changed type of diff from short to int to prevent errors which can occur\n    during very rare circumstances. Thanks to FUWAFUWA.\n\n2002-08-16  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/floating_point_test.c\n    Disable testing on machines without lrintf().\n\n    * Win32/Makefile.msvc\n    Added dwd.c and wve.c to build.\n\n    * configure.in\n    Bumped version to 1.0.0.\n\n2002-08-15  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/file_io.c\n    Add a #include for Mac OS 9. Thanks to Stephane Letz.\n\n    * src/wav.c\n    Changed an snprintf to LSF_SNPRINTF.\n\n    * doc/Makefile.am\n    Added version-1.html.\n\n2002-08-14  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.in\n    Bumped version to 1.0.rc6.\n\n    * src/*.c\n    Modified scaling of normalised floats and doubles to integers. Until now\n    this has been done by multiplying by 0x8000 for short output, 0x80000000\n    for 32 bit ints and so on. Unfortunately this can cause an overflow and\n    wrap around in the target value. All thes values have therefore been\n    reduced to 0x7FFF, 0x7FFFFFFF and so on. The conversion from ints to\n    normalised floats and doubles remains unchanged. This does mean that for\n    repeated conversions normalised float -> pcm16 -> normalised float would\n    result in a decrease in amplitude of 0x7FFF/0x8000 on every round trip.\n    This is undesirable but less undesireable than the wrap around I am trying\n    to avoid.\n\n    * tests/floating_point_test.c\n    Removed file hash checking because new float scaling procedure introduced\n    above prevented the ability to crate a has on both x86 and PowerPC systems.\n\n2002-08-13  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/txw.c\n    Completed reading of TXW files. Seek doesn't work yet.\n\n    * src/file_io.c\n    Added a MacOS 9 replacement for ftruncate().\n\n    * MacOS/sndfile.h\n    Added MacOS 9 header file. This should be copied into src/ to compile\n    libsndfile for MacOS9.\n\n2002-08-12  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.c\n    Fixed commands SF_SET_NORM_DOUBLE and SFC_SET_NORM_FLOAT to return their\n    values after being set. Reported by Jussi Laako.\n\n    * configure.in\n    If autogen is not found, touch all .c and .h files in tests/.\n\n    * src/common.c\n    Added format width specifier to psf_log_printf() for %u, %d, %D and %X.\n\n    * src/dwd.c\n    Completed implementation of read only access to these files.\n\n    * src/common.h src/*.c src/pcm.c\n    Removed redundant field chars from SF_PRIVATE struct and modified\n    pcm_init() to do without it.\n\n2002-08-11  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/wve.c\n    New file implementing read of Psion Alaw files. This will be a read only\n    format. Implementation complete.\n\n    * src/dwd/c\n    Started implementation of DiamondWare Digitized files. Also read only, not\n    complete.\n\n    * src/wav.c\n    Add parsing of 'smpl' chunk.\n\n    * src/paf.c\n    Fixed reading on un-normalized doubles and floats from 24 bit PAF files.\n    This brings it into line with the reading of 8 bit files into\n    un-normalized doubles which returns values in the range [-128, 127].\n\n    * src/common.c\n    Modified psf_log_printf() to accept the %% conversion specifier to allow\n    printing of a single '%'.\n\n    * src/sds.c\n    Read only of 16 bit samples is working. Need to build a test harness for\n    this and other read only formats.\n\n2002-08-10  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.in\n    Added --enable-experimental configure option.\n    Removed pkg-config message at the end of the configure process.\n\n    * src/sds.c src/txw.c src/rx2.c src/sd2.c\n    Moved all the code in these files inside #if ENABLE_EXPERIMENTAL_CODE\n    blocks and added new *_open() function for the case where experimental is\n    not enabled. These new functions just return SFE_UNIMPLMENTED.\n\n    * Win32/sndfile.h src/sndfile.h.in src/common.h\n    Removed un-necessary #pragma pack commands.\n\n    * src/file_io.c\n    Implemented psf_ftruncate() and much other hacking for Win32.\n\n    * Win32/Makefile.msvc\n    Updated.\n\n    * doc/win32.html\n    Updated to include the copying of the sndfile.h file from the Win32/\n    directory to the src/ directory.\n\n    * Make.bat\n    Batch file to make compiling on Wi32 a little easier. Implements \"make\" and\n    \"make check\".\n\n2002-08-09  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/file_io.c\n    Add place holder for ftruncate() on Win32 which doesn't have ftruncate().\n    This will need to be fixed later.\n\n    * src/sndfile.h.in\n    New file (copy of sndfile.h) with sets up @TYPEOF_SF_COUNT_T@ which will be\n    replaced by the correct type during configure.\n\n    * configure.in\n    Modified to find a good type for TYPEOF_SF_COUNT_T.\n\n    * src/aiff.c\n    Fixed a bug when reading malformed headers.\n\n    * src/common.c\n    Set read values to zero before performing read.\n\n2002-08-08  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * doc/command.html\n    Fixed some HTML tags which were not allowing jumps to links within the\n    page.\n\n    * src/sds.c\n    Massive hacking on this.\n\n    * src/wav.c\n    Added recognition of 'clm ' tag.\n\n2002-08-07  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * doc/index.html\n    Added beginning of a capabilities list beyond simple file formats which\n    can be read/written.\n\n    * src/aiff.c\n    Added parsing of INST and MARK chunks of AIFF files. At the moment this\n    data is simply recorded in the log buffer. Later it will be possible to\n    read this data from an application using sf_command().\n\n    * src/wav.c\n    Added parsing of 'cue ' chunk which contains loop information in WAV files.\n\n    * exampes/sndfile-info.c\n    Changed reporting of Samples to Frames.\n\n    * src/wav.c src/w64.c src/aiff.c src/wav_w64.h\n    Moved from a samples to a frames nomenclature to avoid confusion.\n\n    * doc/FAQ.html\n    What's the best format for storing temporary files?\n\n    * src/sds.c\n    New file for reading/writing Midi Sample Dump Standard files.\n\n    * src/Makefile.am src/sndfile.c src/common.[ch]\n    Added hooks for sds.c.\n\n    * examples/sndfile-info.c\n    Changed from using sf_perror() to using sf_error_str().\n\n2002-08-06  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * doc/api.html\n    Added explanation of mode parameter for sf_open().\n    Added explanation of usage of SFM_* values in sf_seek().\n\n    * src/sndfile.[ch] src/command.c src/file_io.c src/common.h\n    Implemented SFC_FILE_TRUNCATE to allow a file to be truncated. File\n    truncation was suggested by James McCartney.\n\n    * src/command.html\n    Documented SFC_FILE_TRUNCATE.\n\n    * tests/command_test.c\n    Add tests for SFC_FILE_TRUNCATE.\n\n    * src/sndfile.c\n    Added a thrid parameter to the VALIDATE_SNDFILE_AND_ASSIGN_PSF macro to\n    make resetting the error number optional. All uses of the macro other than\n    in error reporting functions were changed to reset the error number.\n\n    * src/pcm.c\n    Fixed a bug were sf_read_* was logging an SFE_SHORT_READ even when no error\n    occurred.\n\n    * tests/write_read_test.tpl\n    Added tests of internal error state.\n\n2002-08-05  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/GSM610/private.h src/GSM610/*.c src/GSM610/Makefile.am\n    Renamed private.h to gsm610_priv.h to prevent clash with other headers\n    named private.h in other directories. (Probably only a problem on MacOS 9).\n\n    * src/G72x/private.h src/G72x/*.c src/G72x/Makefile.am\n    Renamed private.h to g72x_priv.h to prevent clash with other headers\n    named private.h in other directories. (Probably only a problem on MacOS 9).\n\n    * MacOS/config.h\n    Changed values of HAVE_LRINT and HAVE_LRINTF to force use of code in\n    float_cash.h.\n\n    * src/sndfile.h\n    Changes the name of samples field of the SF_INFO to frames. The old name\n    had caused too much confusion and it simply had to be changed. There will\n    be at least one more pre-release.\n\n2002-08-04  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * doc/index.html\n    Updated formats matrix to include RAW (header-less) GSM 6.10.\n    Fix specificaltion of table and spelling mistakes.\n\n    * src/sndfile.c src/command.c\n    Fixed bug in SFC_CALC_MAX_SIGNAL family and psf_calc_signal_max ().\n\n    * tests/command.c\n    Removed cruft.\n    Added test for SFC_CALC_MAX_SIGNAL and SFC_CALC_NORM_MAX_SIGNAL.\n\n    * configure.in\n    Update version to 1.0.0rc5.\n\n    * sfendian.h\n    Removed inclusion of un-necessary header.\n\n2002-08-03  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/aiff.c\n    Minor fixes of info written to log buffer.\n\n    * src/float_cast.h\n    Add definition of HAVE_LRINT_REPLACEMENT.\n\n    * tests/floating_point_test.c\n    Fix file hash check on systems without lrint/lrintf.\n\n    * tests/dft_cmp.c\n    Limit SNR to less than -500.0dB.\n\n    * examples/sndfile2oct.c\n    Fixed compiler warnings.\n\n    * doc/api.html\n    Fixed error where last parameter of sf_error_str() was sf_count_t instead\n    of size_t.\n\n2002-08-02  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * doc/FAQ.html\n    Why doesn't libsndfile do interleaving/de-interleaving.\n\n    * tests/pcm_test.tpl\n    On Win32 do not perform hash check on files containing doubles.\n\n2002-08-01  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/common.h\n    Defined SF_COUNT_MAX_POSITIVE() macro, a portable way of setting variables\n    of type sf_count_t to their maximum positive value.\n\n    * src/dwvw.c src/w64.c\n    Used SF_COUNT_MAX_POSITIVE().\n\n2002-07-31  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/paf.c\n    Fixed bug in reading/writing of 24 bit PCM PAF files on big endian systems.\n\n    * tests/floating_point_tests.c\n    Fixed hash values for 24 bit PCM PAF files.\n    Disabled file has check if lrintf() function is not available and added\n    warning.\n    Decreased level of signal from a peak of 1.0 to a value of 0.95 to prevent\n    problems on platforms without lrintf() ie Solaris.\n\n2002-07-30  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/wav.c\n    Fixed a problem with two different kinds of mal-formed WAV file header. The\n    first had the 'fact' chunk before the 'fmt ' chunk, the other had an\n    incomplete 'INFO' chunk at the end of the file.\n\n    * src/w64.c\n    Added fix to allow differentiation between W64 files and ACID files.\n\n    * src/au_g72x.c src/common.h src/sndfile.c\n    Added error for G72x encoded files with more than one channel.\n\n    * tests/pcm_test.tpl tests/utils.tpl\n    Moved function check_file_hash_or_die() to utils.tpl. Function was then\n    modified to calculate the has of the whole file.\n\n    * src/wav.c\n    Fixed problem writing the 'fact' chunk on big endian systems.\n\n    * tests/sfconvert.c\n    Fixed bug where .paf files were being written as Sphere NIST.\n\n2002-07-29  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/voc.c\n    Fix for reading headers generated using SFC_UPDATE_HEADER_NOW.\n\n    * doc/command.html\n    Add docs for SFC_UPDATE_HEADER_NOW and SFC_SET_UPDATE_HEADER_AUTO.\n\n2002-07-28  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * man/sndfile-info.1 man/sndfile-play.1\n    Added manpages supplied by Joshua Haberman the Debian maintainer for\n    libsndfile. Additional tweaks by me.\n\n    * configure.in man/Makefile.am\n    Hooked manpages into autoconf/automake system.\n\n    * src/sndfile.c\n    Added hooks for SFC_SET_UPDATE_HEADER_AUTO.\n\n    * tests/update_header_test.c\n    Improved rigor of testing.\n\n    * src/*.c\n    Fixed problem with *_write_header() functions.\n\n2002-07-27  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * doc/*.html\n    Updates to documentation to fix problems found by wdg-html-validator.\n\n    * src/common.h src/command.c\n    Added normalize parameter to calls to psf_calc_signal_max() and\n    psf_calc_max_all_channels().\n\n    * src/sndfile.c\n    Added handling for commands SFC_CALC_NORM_SIGNAL_MAX and\n    SFC_CALC_NORM_MAX_ALL_CHANNELS.\n\n    * doc/command.html\n    Added entry for SFC_CALC_NORM_SIGNAL_MAX and SFC_CALC_NORM_MAX_ALL_CHANNELS.\n\n2002-07-26  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * examples/sndfile-play.c Win32/Makefile.msvc\n    Get sndfile-play program working on Win32. The Win32 PCM sample I/O API\n    sucks. The sndfile-play program now works on Linux, MacOSX, Solaris and\n    Win32.\n\n2002-07-25  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * doc/FAQ.html\n    New file for frequently asked questsions.\n\n2002-07-22  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * doc/api.html\n    Documentation fixes.\n\n    * src/au.[ch] src/au_g72x.c src/G72x/g72x.h\n    Add support of 40kbps G723 ADPCM encoding.\n\n    * tests/lossy_comp_test.c tests/floating_point_test.c\n    Add tests for 40kbps G723 ADPCM encoding.\n\n    * doc/index.html\n    Update support matrix.\n\n2002-07-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * doc/command.html\n    Documented SFC_GET_SIMPLE_FORMAT_COUNT, SFC_GET_SIMPLE_FORMAT,\n    SFC_GET_FORMAT_* and SFC_SET_ADD_PEAK_CHUNK.\n\n    * src/sndfile.c src/pcm.c\n    Add ability to turn on and off the addition of a PEAK chunk for floating\n    point WAV and AIFF files.\n\n    * src/sndfile.[ch] src/common.h src/command.c\n    Added sf_command SFC_CALC_MAX_ALL_CHANNELS. Implemented by Maurizio Umberto\n    Puxeddu.\n\n    * doc/command.html\n    Docs for SFC_CALC_MAX_ALL_CHANNELS (assisted by Maurizio Umberto Puxeddu).\n\n2002-07-18  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.c src/gsm610.c\n    Finalised support for GSM 6.10 AIFF files and added support for GSM 6.10\n    encoded RAW (header-less) files.\n\n    * src/wav.c\n    Add support for IBM_FORMAT_MULAW and IBM_FORMAT_ALAW encodings.\n\n    * src/api.html\n    Fixed more documentation bugs.\n\n2002-07-17  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.h src/common.h\n    Moved some yet-to-be-implelmented values for SF_FORMAT_* from the public\n    header file sndfile.h to the private header file common.h to avoid\n    confusion about the actual capabilities of libsndfile.\n\n2002-07-16  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/aiff.c src/wav.c\n    Fixed file parsing for WAV and AIFF files containing non-audio data after\n    the data chunk.\n\n    * src/aiff.c src/sndfile.c\n    Add support for GSM 6.10 encoded AIFF files.\n\n    * tests/lossy_comp_test.c tests/Makefile.am\n    Add tests for GSM 6.10 encoded AIFF files.\n\n    * src/*.c\n    Fix compiler warnings.\n\n2002-07-15  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/command_test.c\n    For SFC_SET_NORM_* tests, change the file format from SF_FORMAT_WAV to\n    SF_FORMAT_RAW.\n\n    * src/sndfile.c\n    Added sf_command(SFC_TEST_ADD_TRAILING_DATA) to allow testing of reading\n    from AIFF and WAV files with non-audio data after the audio chunk.\n\n    * src/common.h\n    Add test commands SFC_TEST_WAV_ADD_INFO_CHUNK and\n    SFC_TEST_AIFF_ADD_INST_CHUNK. When these commands are working, they will be\n    moved to src/sndfile.h\n\n    * src/aiff.c src/wav.c\n    Begin implementation of XXXX_command() hook for sf_command().\n\n    * tests/write_read_test.tpl\n    Added sf_command (SFC_TEST_ADD_TRAILING_DATA) to ensure above new code was\n    working.\n\n2002-07-13  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/update_header_test.c\n    Allow read sample count == write sample count - 1 to fix problems with VOC\n    files.\n\n    * tests/write_read_test.tpl tests/pcm_test.tpl\n    Fixed some problems in the test suite discovered by using Valgrind.\n\n2002-07-12  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/utils.[ch] tests/*.c\n    Renamed check_log_buffer() to check_log_buffer_or_die().\n\n    * src/sndfile.c\n    SFC_UPDATE_HEADER_NOW and SFC_SETUPDATE_HEADER_AUTO almost finished. Works\n    for all file formats other than VOC.\n\n2002-07-11  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.[ch] src/common.h\n    Started adding functionality to allow the file header to be updated before\n    the file is closed on files open for SFM_WRITE. This was requested by\n    Maurizio Umberto Puxeddu who is using libsndfile for file I/O in iCSound.\n\n    * tests/update_header_test.c\n    New test program to test that the above functionality is working correctly.\n\n    * tests/peak_chunk_test.c tests/floating_point_test.c\n    Cleanups.\n\n2002-07-10  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sfendian.[ch]\n    Changed length count parameters for all endswap_XXX() functions from\n    sf_count_t (which can be 64 bit even on 32 bit architectures) to int. These\n    functions are only called frin inside the library, are always called with\n    integer parameters and doing the actual calculation on 64 bit values is\n    slow in comparision to doing it on ints.\n\n    * examples/sndfile-play.c\n    More playback hacking for Win32.\n\n2002-07-09  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/common.c\n    In psf_log_printf(), changed %D format conversion specifier to %M (marker) and\n    added %D specifier for printing the sf_count_t type.\n\n    * src/*.c\n    Changed all usage of psf_log_printf() with %D format conversion specifiers\n    to use %M conversion instead.\n\n    * tests/pcm_test.tpl tests/pcm_test.def\n    New files to autogen pcm_test.c.\n\n    * src/pcm.c\n    Fixed bug in scaling floats and doubles to 24 bit PCM and vice versa.\n\n2002-07-08  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.in\n    Fix setup of $ac_cv_sys_largefile_CFLAGS so that sndfile.pc gets valid\n    values for CFLAGS.\n\n    * examples/sndfile-play.c\n    Start adding playback support for Win32.\n\n2002-07-07  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/*.c\n    Worked to removed compiler warnings.\n    Extensive refactoring.\n\n    * src/common.[ch]\n    Added function psf_memset() which works like the standard C function memset\n    but takes and sf_count_t as the length parameter.\n\n    * src/sndfile.c\n    Replaced calls to memset(0 with calls to psf_memset() as required.\n\n2002-07-06  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.c\n    Added \"libsndfile : \" to the start of all error messages. This was suggested\n    by Conrad Parker author of Sweep ( http://sweep.sourceforge.net/ ).\n\n    * src/sfendian.[ch]\n    Added endswap_XXXX_copy() functions.\n\n    * src/pcm.c src/float32.c src/double64.c\n    Use endswap_XXXX_copy() functions and removed dead code.\n    Cleanups and optimisations.\n\n2002-07-05  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.c src/sndfile.h\n    Gave values to all the SFC_* enum values to allow better control of the\n    interface as commands are added and removed.\n    Added new command SFC_SET_ADD_PEAK_CHUNK.\n\n    * src/wav.c src/aiff.c\n    Modified wav_write_header and aiff_write_header to make addition of a PEAK\n    chunk optional, even on floating point files.\n\n    * tests/benchmark.tpl\n    Added call to sf_command(SFC_SET_ADD_PEAK_CHUNK) to turn off addition of a\n    PEAK chunk for the benchmark where we are trying to miximize speed.\n\n    * src.pcm.c\n    Changed tribyte typedef to something more sensible.\n    Further conversion speed ups.\n\n2002-07-03  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/command.c\n    In major_formats rename \"Sphere NIST\" to \"NIST Sphere\".\n\n    * src/common.c src/sfendian.c\n    Moved all endswap_XXX_array() functions to sfendian.c. These functions will\n    be tweaked to provide maximum performance. Since maximum performance on one\n    platform does not guarantee maximum performance on another, a small set of\n    functions will be written and the optimal one chosen at compile time.\n\n    * src/common.h src/sfendian.h\n    Declarations of all endswap_XXX_array() functions moved to sfendian.h.\n\n    * src/Makefile.am\n    Add sfendian.c to build targets.\n\n2002-07-01  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/pcm.c src/sfendian.h\n    Re-coded PCM encoders and decoders to match or better the speed of\n    libsndfile version 0.0.28.\n\n2002-06-30  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/wav.c\n    Add checking for WAVPACK data in standard PCM WAV file. Return error if\n    found. This WAVPACK is *WAY* broken. It uses the same PCM WAV file header\n    and then stores non-PCM data.\n\n    * tests/benchmark.tpl\n    Added more tests.\n\n2002-06-29  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/benchmark.tpl\n    Added conditional definition of M_PI.\n    For Win32, set WRITE_PERMS to 0777.\n\n    * Win32/Makefile.msvc\n    Added target to make generate program on Win32.\n\n    * src/samplitude.c\n    Removed handler for Samplitude RAP file format. This file type seems rarer\n    than hens teeth and is completely undocumented.\n\n    * src/common.h src/sndfile.c src/Makefile.am Win32/Makefile.msvc\n    Removed references to sampltiude RAP format.\n\n    * tests/benchmark.tpl\n    Benchmark program now prints the libsndfile version number when run. This\n    program was also backported to version 0 to compare results. Version\n    1.0.0rc2 is faster than version 0.0.28 on most conversions but slower on\n    some. The slow ones need to be fixed before final release.\n\n2002-06-28  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/benchmark.def tests/benchmark.tpl\n    New files which generate tests/benchmark.c using Autogen. Added int ->\n    SF_FORMAT_PCM_24 test.\n\n    * tests/benchmark.c\n    Now and Autogen output file.\n\n    * tests/Makefile.am\n    Updated for above changes.\n\n2002-06-27  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/benchmark.c\n    Basic benchmark program complete. Need to convert it to Autogen.\n\n    * Win32/Makefile.msvc\n    Added benchmark.exe target.\n\n2002-06-26  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * examples/generate.c\n    New program to generate a number of different output file formats from a\n    single input file. This allows testing of the created files.\n\n    * tests/benchmark.c\n    New test program to benchmark libsndfile. Nowhere near complete yet.\n\n    * examples/Makefile.am tests/Makefile.am\n    New make rules for the two new programs.\n\n2002-06-25  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * Win32/libsndfile.def\n    Removed definition for sf_signal_max().\n\n    * src/sndfile.c\n    Removed cruft.\n\n    * doc/index.html\n    A number of documentation bugs were fixed. Thanks to Anand Kumria.\n\n    * doc/version-1.html\n    Minor doc updates.\n\n    * configure.in\n    Bumped version to 1.0.0rc2.\n\n    * src/sf_command.h src/Makefile.am\n    Removed the header file as it was no longer being used. Thanks to Anand\n    Kunria for spotting this.\n\n    * doc/index.html\n    A number of documentation bugs were fixed. Thanks to Anand Kumria.\n\n2002-06-24  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/common.h\n    Test for Win32 before testing SIZEOF_OFF_T so that it works correctly\n    on Win32..\n\n    * src/file_io.c\n    Win32 fixes to ensure O_BINARY is used for file open.\n\n    * doc/win32.html\n    New file documenting the building libsndfile on Win32.\n\n    * doc/*.html\n    Updating of documentation.\n\n2002-06-23  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/pcm_test.c\n    Minor changes to allow easier determination of test file name.\n\n    * src/sndfile.[ch]\n    Removed function sf_signal_max().\n\n    * examples/sndfile-play.c\n    Changed call to sf_signal_max() to a call to sf_command().\n\n2002-06-22  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/format.c src/command.c\n    Renamed format.c to command.c which will now include code for sf_command()\n    calls to perform operations other than format commands.\n\n    * src/sndfile.c src/sndfile.h\n    Removed function sf_get_signal_max() which is replaced by commands passed\n    to sf_command().\n\n    * src/command.c\n    Implement commands SFC_CALC_SIGNAL_MAX.\n\n    * doc/command.html\n    Documented SFC_CALC_SIGNAL_MAX.\n\n2002-06-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * examples/sndfile-play.c\n    Mods to make sndfile-play work on Solaris. The program sndfile-play now\n    runs on Linux, MaxOSX and Solaris. Win32 to come.\n\n    * src/format.c\n    Added SF_FORMAT_DWVW_* to subtype_formats array.\n\n    * src/nist.c\n    Added support for 8 bit NIST Sphere files. Example file supplied by Anand\n    Kumria.\n\n2002-06-20  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * examples/sndfile-info.c\n    Tidy up of output format.\n\n    * examnples/sndfile-play.c\n    Mods to make sndfile-play work on MacOSX using Apple's CoreAudio API.\n\n    * configure.in\n    Add new variables OS_SPECIFIC_INCLUDES and OS_SPECIFIC_LINKS which were\n    required to supply extra include paths and link parameters to get\n    sndfile-play working on MacOSX.\n\n    * examples/Makefile.am\n    Use OS_SPOECIFIC_INCLUDES and OS_SPECIFIC_LINKS to build commands for\n    sndfile-play.\n\n2002-06-19  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/nist.c\n    Added ability to read/write new NIST Sphere file types (A-law, u-law).\n    Header parser was re-written from scratch. Example files supplied by Anand\n    Kumria.\n\n    * src/sndfile.c\n    Support for A-law and u-law NIST files.\n\n    * tests/Makefile.am tests/lossy_comp_test.c\n    Tests for A-law and u-law NIST files.\n\n2002-06-18  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/utils.c\n    Fixed an error in error string.\n\n2002-06-17  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * acinclude.m4\n    Removed exit command to allow cross-compiling.\n\n    * Win32/unistd.h src/file_io.c\n    Moved contents of first file into the second file (enclosed in #ifdef).\n    Win32/unistd.h is now an empty file but still must be there for libsndfile\n    to compile on Win32.\n\n    * src/sd2.c, src/sndfile.c:\n    Fixes for Sound Designer II files on big endian systems.\n\n2002-06-16  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.in\n    Modified to work around problems with crappy MacOSX version of sed.\n    Added sanity check for proper values for CFLAGS.\n\n2002-06-14  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.c\n    Code clean up in sf_open ().\n\n    * Win32/Makefile.msvc\n    Michael Fink's contributed MSVC++ makefile was hacked to bits and put back\n    together in a new improved form.\n\n    * src/file_io.c\n    Fixes for Win32; _lseeki64() returns an invalid argument for calls like\n    _lseeki64(fd, 0, SEEK_CUR) so need to use _telli64 (fd) instead.\n\n    * src/common.h src/sndfile.c src/wav.c src/aiff.c\n    Added SFE_LOG_OVERRUN error.\n    Added termination for potential infinite loop when parsing file headers.\n\n    * src/wav.c src/w64.c\n    Fixed bug casuing incorrect header generation when opening file read/write.\n\n2002-06-12  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * doc/api.html\n    Improved the documentation to make it clearer that the file read method\n    and the underlying file format are completely disconnected. Suggested\n    by Josh Green.\n\n    * doc/command.html\n    Started correcting docs to take into account changes made to the\n    operations of the sf_command () function. Not complete yet.\n\n    * src/sndfile.c\n    Reverted some changes which had broken the partially working SDII header\n    parsing. Now have access to an iBook with OS X so reading and writing SDII\n    files on all platforms should be a reality in the near future. On Mac this\n    will involve reading the resource fork via the standard MacOS API. To move\n    a file from Mac to another OS, the resource and data forks will need to be\n    combined before transfer. The combined file will be read on both Mac and\n    other OSes like any other file.\n\n2002-06-08  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * ltmain.sh\n    Applied a patch from http://fink.sourceforge.net/doc/porting/libtool.php\n    which allows libsndfile to compile on MacOSX 10.1. This patch should not\n    interfere with compiling on other OSes.\n\n    * src/GSM610/private.h\n    Changes to fix compile problems on MacOSX (see src/GSM610/ChangeLog).\n\n    * src/float_cast.h\n    Added MacOSX replacements for lrint() and lrintf().\n\n2002-06-05  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.c\n    Replaced the code to print the filename to the log buffer when a file is\n    opened. This code seems to have been left out during the merge of\n    sf_open_read() and sf_open_write() to make a single  functions sf_open().\n\n2002-06-01  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/wav.c\n    Fixed a bug where the WAV header parser was going into an infinite loop\n    on a badly formed LIST chunk. File supplied by David Viens.\n\n2002-05-25  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.in\n    Added a message at the end of the configuration process to warn about the\n    need for the use of pkg-config when linking programs against version 1 of\n    libsndfile.\n\n    * doc/pkg-config.html\n    New documentation file containing details of how to use pkg-config to\n    retrieve settings for CFLAGS and library locations for linking files\n    against version 1 of libsndfile.\n\n2002-05-17  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/wav.c\n    Fixed minor bug in handling of so-called ACIDized WAV files.\n\n2002-05-16  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * Win32/libsndfile.def Win32/Makefile.msvc\n    Two new files contributed by Michael Fink (from the winLAME project)\n    which allows libsndfile to be built on windows in a MSDOS box by doing\n    \"nmake -f Makefile.msvc\". Way cool!\n\n2002-05-15  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.in\n    MacOSX is SSSOOOOOOO screwed up!!! I can't believe how hard it is to\n    generate a tarball which will configure and compile on that platform.\n    Joined the libtool mailing list to try and get some answers.\n\n2002-05-13  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.in\n    Changed to autoconf version 2.50. MacOSX uses autoconf version 2.53 which\n    is incompatible with with version 2.13 which had been using until now.\n    The AC_SYS_LARGE_FILE macro distributed withe autoconf 2.50 is missing a\n    few features so AC_SYS_EXTRA_LARGE file was defined to replace it.\n\n    * configure.in\n    Changed to automake version 1.5 to try and make a tarball which will\n    work on MacOSX.\n\n2002-05-12  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/wav_gsm610.c\n    Changed name to gsm610.c. Added reading/writing of headerless files.\n\n    * src/sndfile.c src/raw.c\n    Added ability to read/write headerless (SF_FORMAT_RAW) GSM 6.10 files.\n\n2002-05-11  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/lossy_comp_test.c\n    Clean up in preparation for Autogen-ing this file.\n\n    * src/GSM610/*.[ch]\n    Code cleanup and prepartion forgetting file seek working. Details in\n    src/GSM610/ChangeLog.\n\n    * sndfile.pc.in\n    Testing complete. Is sndfile.m4 still needed?\n\n2002-05-09  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/write_read_test.tpl tests/rdwr_test.tpl\n    Merged tests from these two programs into write_read_test.tpl and deleted\n    rdwr_test.tpl.\n\n2002-05-08  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/w64.c src/svx.c src/paf.c\n    Fixed bugs in read/write mode.\n\n2002-05-07  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * examples/Makefile.am\n    Renamed sfplay.c to sndfile-play.c and sndfile_info.c to sndfile-info.c for\n    consistency when these programs become part of the Debian package\n    sndfile-programs.\n\n    * sndfile.pc.in\n    New file to replace sndfile-config.in. Libsndfile now uses the pkg-config\n    model for providing installation parameters to dependant programs.\n\n    * src/sndfile.c\n    Cleanup of code in sf_open().\n\n2002-05-06  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/utils.tpl tests/write_read_test.tpl\n    More conversion to Autogen fixes and enchancements.\n\n    * src/*.c\n    Read/write mode is now working for 16, 24 and 32 bit PCM as well as 32\n    bit float and 64 bit double data. More tests still required.\n\n    * src/Makefile.am\n    Added DISTCLEANFILES target to remove config.status and config.last.\n\n    * Win32/Makefile.am MacOS/Makefile.am\n    Added DISTCLEANFILES target to remove Makefile.\n\n2002-05-05  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/*.[ch] tests/rdwr_test.c\n    More verifying workings of read/write mode. Fixing bugs found.\n\n    * tests/utils.[ch]\n    Made these files Autogen generated files.\n\n    * tests/util.tpl tests/util.def\n    New Autogen files to generate utils.[ch]. Moved some generic test functions\n    into this file. Autogen is such a great tool!\n\n2002-05-03  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/pcm.c src/float_cast.h Win32/config.h\n    Fixed a couple of Win32 specific bugs pointed out by Michael Fink\n    (maintainer of WinLAME) and David Viens.\n\n    * tests/check_log_buffer.[ch] tests/utils.[ch]\n    Moved check_log_buffer() to utils.[ch] and deleted old file.\n\n2002-05-02  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/common.[ch] src/sndfile.c\n    New function psf_default_seek() which will be the default seek function\n    for things like PCM and floating point data. This default is set for\n    both read and write in sf_open() but can be over-ridden by any codec\n    during it's initialisation.\n\n2002-05-01  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/au.c\n    AU files use a data size value of -1 to mean unknown. Fixed au_open_read()\n    to allow opening files like this.\n\n    * tests/rdwr_test .c\n    Added more tests.\n\n    * src/sndfile.c\n    Fixed bugs in read/write mode found due to improvements in the test\n    program.\n\n2002-04-30  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/rdwr_test .c\n    New file for testing read/write mode.\n\n2002-04-29  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * m4/*\n    Removed all m4 macros from this directory as they get concatenated to form\n    the file aclocal.m4 anyway.\n\n    * sndfile.m4\n    Moved this from the m4 directory to the root directory asn this is part of\n    the distribution and is installed during \"make install\".\n\n2002-04-29  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/float32.c\n    Removed logging of peaks for all file formats other than AIFF and WAV.\n\n    * tests/write_read_test.tpl tests/write_read_test.def\n    New files which autogen uses to generate write_read_test.c. Doing it this\n    way makes write_read_test.c far easier to maintain. Other test programs\n    will be converted to autogen in the near future.\n\n    * src/*.c\n    Fixed a few bugs found when testing on Sparc (bug endian) Solaris.\n\n2002-04-28  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * doc/*.html\n    Fixed documention versioning.\n\n    * configure.in\n    Fixed a bug in the routines which search for Large File Support on systems\n    which have large file support by defualt.\n\n2002-04-27  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/*.[ch]\n    Found and fixed an issue which can cause a bug in other software (I was\n    porting Conrad Parker's Sweep program from version 0 of the library to\n    version 1). When opening a file for write, the libsndfile code would\n    set the sfinfo.samples field to a maximum value.\n\n    * tests/write_read_test.c\n    Added tests to detect the above problem.\n\n2002-04-25  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/*.[ch]\n    Finished base implementation of read/write mode. Much more testing still\n    needed.\n\n    * m4/largefile.m4\n    Macro for detecting Large File Standard capabilities. This macro was ripped\n    out of the aclocal.m4 file of GNU tar-1.13.\n\n    * configure.in\n    Added detection of large file support. Files larger than 2 Gigabytes should\n    now be supported on 64 bit platforms and many 32 bit platforms including\n    Linux (2.4 kernel, glibc-2.2), *BSD, MacOS, Win32.\n\n    * libsndfile_convert_version.py\n    A Python script which attempts to autoconvert code written to use version 0\n    to version 1.\n\n2002-04-24  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/*.[ch]\n    Finished base implementation of read/write mode. Much more testing still\n    needed.\n\n    * tests/write_read_test.c\n    Preliminary tests for read/write mode added. More needed.\n\n2002-04-20  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.[ch]\n    Removed sf_open_read() and sf_open_write() functions,replacting them with\n    sf_open() which takes an extra mode parameter (SF_OPEN_READ, SF_OPEN_WRITE,\n    or SF_OPEN_RDWR). This new function sf_open can now be modified to allow\n    opening a file formodification (RDWR).\n\n2002-04-19  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/*.c\n    Completed merging of separate xxx_open_read() and xxx_open_write()\n    functions. All tests pass.\n\n2002-04-18  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/au.c\n    Massive refactoring required to merge au_open_read() with au_open_write()\n    to create au_open().\n\n2002-04-17  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/*.c\n    Started changes required to allow a sound file to be opened in read/write\n    mode, with separate file pointers for read and write. This involves merging\n    of encoder/decoder functions like pcm_read_init() and pcm_write_init()\n    int a new function pcm_init() as well as doing something similar for all\n    the file type specific functions ie aiff_open_read() and aiff_open_write()\n    were merged to make the function aiff_open().\n\n2002-04-15  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/file_io.c\n    New file containing psf_fopen(), psf_fread(), psf_fwrite(), psf_fseek() and\n    psf_ftell() functions. These function will replace use of fopen/fread/fwrite\n    etc and allow access to files larger than 2 gigabytes on a number of 32 bit\n    OSes (Linux on x86, 32 bit Solaris user space apps, Win32 and MacOS).\n\n    * src/*.c\n    Replaced all instances of fopen with psf_open, fread with psd_read, fwrite\n    with psf_write and so on.\n\n2002-03-11  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/dwvw.c\n    Finally fixed all known problems with 12, 16 and 24 bit DWVW encoding.\n\n    * tests/floating_point_test.c\n    Added tests for 12, 16 and 24 bit DWVW encoding.\n\n2002-03-03  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * m4/endian.m4\n    Defines a new m4 macro AC_C_FIND_ENDIAN, for determining the endian-ness of\n    the target CPU. It first checks for the definition of BYTE_ORDER in\n    <endian.h>, then in <sys/types.h> and <sys/param.h>. If none of these work\n    and the C compiler is not a cross compiler it compiles and runs a program\n    to test for endian-ness. If the compiler is a cross compiler it makes a\n    guess based on $target_cpu.\n\n    * configure.in\n    Modified to use AC_C_FIND_ENDIAN.\n\n    * src/sfendian.h\n    Simplified.\n\n2002-02-23  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/floating_point_test.c\n    Tests completely rewritten using the dft_cmp function. Now able to\n    calculate a quick guesstimate of the Signal to Noise Ratio of the encoder.\n\n2002-02-15  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/dft_cmp.[ch]\n    New files containing functions for comparing pre and post lossily\n    compressed data using a quickly hacked DFT.\n\n    * tests/utils.[ch]\n    New files containing functions for saving pre and post encoded data in a\n    file readable by the GNU Octave package.\n\n2002-02-13  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * m4/lrint.m4 m4/lrintf.m4\n    Fixed m4 macros to define HAVE_LRINT and HAVE_LRINTF even when the test\n    is cached.\n\n2002-02-12  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/floating_point_test.c\n    Fixed improper use of strncat ().\n\n2002-02-11  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/headerless_test.c\n    New test program to test the ability to open and read a known file type as a\n    RAW header-less file.\n\n2002-02-07  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/losy_comp_test.c\n    Added a test to ensure that the data read from a file is not all zeros.\n\n    * examples/sfconvert.c\n    Added \"-gsm610\" encoding types.\n\n2002-01-29  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * examples/sfconvert.c\n    Added \"-dwvw12\", \"-dwvw16\" and \"-dwvw24\" encoding types.\n\n    * tests/dwvw_test.c\n    New file for testing DWVW encoder/decoder.\n\n2002-01-28  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/dwvw.c\n    Implemented writing of DWVW. 12 bit seems to work, 16 and 24 bit still broken.\n\n    * src/aiff.c\n    Improved reporting of encoding types.\n\n    * src/voc.c\n    Clean up.\n\n2002-01-27  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/dwvw.c\n    New file implementing lossless Delta Word Variable Width (DWVW) encoding.\n    Reading 12 bit DWVW is now working.\n\n    * src/aiff.c common.h sndfile.c\n    Added hooks for DWVW encoded AIFF and RAW files.\n\n2002-01-15  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/w64.c\n    Robustify header parsing.\n\n    * src/wav_w64.h\n    Header file wav.h was renamed to wav_w64.h to signify sharing of\n    definitions across the two file types.\n\n    * src/wav.c src/w64.c src/wav_w64.c\n    Refactoring.\n    Modified and moved functions with a high degree of similarity between\n    wav.c and w64.c to wav_w64.c.\n\n2002-01-14  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/w64.c\n    Completed work on getting read and write working.\n\n    * examples/sfplay.c\n    Added code to scale floating point data so it plays at a reasonable volume.\n\n    * tests/Makefile.am tests/write_read_test.c\n    Added tests for W64 files.\n\n2002-01-13  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/*.c\n    Modded all code in file header writing routines to use\n    psf_new_binheader_writef().\n    Removed psf_binheader_writef() from src/common.c.\n    Globally replaced psf_new_binheader_writef with psf_binheader_writef.\n\n2002-01-12  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/*.c\n    Modded all code in file parsing routines to use psf_new_binheader_readf().\n    Removed psf_binheader_readf() from src/common.c.\n    Globally replaced psf_new_binheader_readf with psf_binheader_readf.\n\n    * src/common.[ch]\n    Added new function psf_new_binheader_writef () which will soon replace\n    psf_binheader_writef (). The new function has basically the same function\n    as the original but has a more flexible and capable interface. It also\n    allows the writing of 64 bit integer values for files contains 64 bit file\n    offsets.\n\n2002-01-11  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/formats.c src/sndfile.c src/sndfile.h\n    Added code allowing full enumeration of supported file formats via the\n    sf_command () interface.\n    This feature will allow applications to avoid needing recompilation when\n    support for new file formats are added to libsndfile.\n\n    * tests/command_test.c\n    Added test code for the above feature.\n\n    * examples/list_formats.c\n    New file. An example of the use of the supported file enumeration\n    interface. This program lists all the major formats and for each major\n    format the supported subformats.\n\n2002-01-10  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/*.[ch] tests/*.c\n    Changed command parameter of sf_command () function from a test string to\n    an int. The valid values for the command parameter begin with SFC_ and are\n    listed in src/sndfile.h.\n\n2001-12-20  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/formats.c src/sndfile.c\n    Added an way of enumerating a set of common file formats using the\n    sf_command () interface. This interface was suggested by Dominic Mazzoni,\n    one of the main authors of Audacity (http://audacity.sourceforge.net/).\n\n2001-12-26  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.c\n    Added checking of filename parameter in sf_open_read (). Previousy, if a\n    NULL pointer was passed the library would segfault.\n\n2001-12-18  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/common.c src/common.h\n    Changed the len parameter of the endswap_*_array () functions from type\n    int to type long.\n\n    * src/pcm.c\n    Fixed a problem which\n\n2001-12-15  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.c\n    Added conditional #include <sys/types.h> for EMX/gcc on OS/2. Thanks to\n    Paul Hartman for pointing this out.\n\n    * tests/lossy_comp_test.c tests/floating_point_test.c\n    Added definitions for M_PI for when it isn't defined in <math.h>.\n\n2001-11-30  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/ircam.c\n    Re-implemented the header reader. Old version was making incorrect\n    assumptions about the endian-ness of the file from the magic number at the\n    start of the file. The new code looks at the integer which holds the\n    number of channels and determines the endian-ness from that.\n\n2001-11-30  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/aiff.c\n    Added support for other AIFC types ('raw ', 'in32', '23ni').\n    Further work on IMA ADPCM encoding.\n\n2001-11-29  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/ima_adpcm.c\n    Renamed from wav_ima_adpcm.c. This file will soon handle IMA ADPCM\n    encodings for both WAV and AIFF files.\n\n    * src/aiff.c\n    Started adding IMA ADPCM support.\n\n2001-11-28  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/double.c\n    New file for handling double precision floating point (SF_FORMAT_DOUBLE)\n    data.\n\n    * src/wav.c src/aiff.c src/au.c src/raw.c\n    Added support for SF_FORMAT_DOUBLE data.\n\n    * src/common.[ch]\n    Addition of endswap_long_array () for endian swapping 64 bit integers. This\n    function will work correctly on processors with 32 bit and 64 bit longs.\n    Optimised endswap_short_array () and endswap_int_array ().\n\n    * tests/pcm_test.c\n    Added and extra check. After the first file of each type is written to disk\n    a checksum is performed of the first 64 bytes and checked against a pre-\n    calculated value. This will work whatever the endian-ness of the host\n    machine.\n\n2001-11-27  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/aiff.c\n    Added handling of u-law, A-law encoded AIFF files. Thanks to Tom Erbe for\n    supplying example files.\n\n    * tests/lossy_comp_test.c\n    Added tests for above.\n\n    * src/common.h src/*.c\n    Removed function typedefs from common.h and function pointer casting in all\n    the other files. This allows the compiler to perform proper type checking.\n    Hopefully this will prevernt problems like the sf_seek bug for OpenBSD,\n    BeOS etc.\n\n    * src/common.[ch]\n    Added new function psf_new_binheader_readf () which will eventually replace\n    psf_binheader_readf (). The new function has basically the same function as\n    the original but has a more flexible and capable interface. It also allows\n    the reading of 64 bit integer values for files contains 64 bit file\n    offsets.\n\n2001-11-26  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/voc.c\n    Completed implementation of VOC file handling. Can now handle 8 and 16 bit\n    PCM, u-law and A-law files with one or two channels.\n\n    * src/write_read_test.c tests/lossy_comp_test.c\n    Added tests for VOC files.\n\n2001-11-22  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/float_cast.h\n    Added inline asm version of lrint/lrintf for MacOS. Solution provided by\n    Stephane Letz.\n\n    * src/voc.c\n    More work on this braindamaged format. The VOC files produced by SoX also\n    have a number of inconsistencies.\n\n2001-11-19  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/paf.c\n    Added support for 8 bit PCM PAF files.\n\n    * tests/write_read_test.c\n    Added tests for 8 bit PAF files.\n\n2001-11-18  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/pcm_test.c\n    New test program to test for correct scaling of integer values between\n    different sized integer containers (ie short -> int).\n    The new specs for libsndfile state that when the source and destination\n    containers are of a different size, the most significant bit of the source\n    value becomes the most significant bit of the destination container.\n\n    * src/pcm.c src/paf.c\n    Modified to pass the above test program.\n\n    * tests/write_read_test.c tests/lossy_comp_test.c\n    Modified to work with the new scaling rules.\n\n2001-11-17  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/raw.c tests/write_read_test.c tests/write_read_test.c\n    Added ability to do raw reads/writes of float, u-law and A-law files.\n\n    * src/*.[ch] examples/*.[ch] tests/*.[ch]\n    Removed dependance on pcmbitwidth field of SF_INFO struct and moved to new\n    SF_FORMAT_* types and use of SF_ENDIAN_BIG/LITTLE/CPU.\n\n2001-11-12  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/*.[ch]\n    Started implmentation of major changes documented in doc/version1.html.\n\n    Removed all usage of off_t which is not part of the ISO C standard. All\n    places which were using it are now using type long which is the type of\n    the offset parameter for the fseek function.\n    This should fix problems on BeOS, MacOS and *BSD like systems which were\n    failing \"make check\" because sizeof (long) != sizeof (off_t).\n\n--------------------------------------------------------------------------------\nThis is the boundary between version 1 of the library above and version 0 below.\n--------------------------------------------------------------------------------\n\n2001-11-11  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * examples/sfplay_beos.cpp\n    Added BeOS version of sfplay.c. This needs to be compiled using a C++\n    compiler so is therefore not built by default. Thanks to Marcus Overhagen\n    for providing this.\n\n2001-11-10  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * examples/sfplay.c\n    New example file showing how libsndfile can be used to read and play a\n    sound file.\n    At the moment on Linux is supported. Others will follow in the near future.\n\n2001-11-09  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/pcm.c\n    Fixed problem with normalisation code where a value of 1.0 could map to\n    a value greater than MAX_SHORT or MAX_INT. Thanks to Roger Dannenberg for\n    pointing this out.\n\n2001-11-08  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/pcm.c\n    Fixed scaling issue when reading/writing 8 bit files using\n    sf_read/sf_write_short ().\n    On read, values are scaled so that the most significant bit in the char\n    ends up in the most significant bit of the short. On write, values are\n    scaled so that most significant bit in the short ends up as the most\n    significant bit in the char.\n\n2001-11-07  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/au.c src/sndfile.c\n    Added support for 32 bit float data in big and little endian AU files.\n\n    * tests/write_read_test.c\n    Added tests for 32 bit float data in AU files.\n\n2001-11-06  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/lossy_comp_test.c\n    Finalised testing of stereo files where possible.\n\n2001-11-05  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/wav_ms_adpcm.c\n    Fixed bug in writing stereo MS ADPCM WAV files. Thanks to Xu Xin for\n    pointing out this problem.\n\n2001-10-24  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/wav_ms_adpcm.c\n    Modified function srate2blocksize () to handle 44k1Hz stereo files.\n\n2001-10-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/w64.c\n    Added support for Sonic Foundry 64 bit WAV format. As Linux (my main\n    development platform) does not yet support 64 bit file offsets by default,\n    current handling of this file format treats everything as 32 bit and fails\n    openning the file, if it finds anything that goes beyond 32 bit values.\n\n    * src/sndfile.[hc] src/common.h src/Makefile.am\n    Added hooks for W64 support.\n\n2001-10-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.in\n    Added more warnings options to CFLAGS when the gcc compiler is detected.\n\n    * src/*.[ch] tests/*.c examples/*.c\n    Started fixing the warning messages due to the new CFLASG.\n\n    * src/voc.c\n    More work on VOC file read/writing.\n\n    * src/paf.c\n    Found that PAF files were not checking the normalisation flag when reading\n    or writing floats and doubles. Fixed it.\n\n    * tests/floating_point_test.c\n    Added specific test for the above problem.\n\n    * src/float_cast.h src/pcm.c\n    Added a section for Win32 to define lrint () and lrintf () in the header\n    and implement it in the pcm.c\n\n2001-10-20  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * sndfile-config.in m4/sndfile.m4\n    These files were donated by Conrad Parker who also provided instructions\n    on how to install them using autoconf/automake.\n\n    * src/float_cast.h\n    Fiddled around with this file some more. On Linux and other gcc supported\n    OSes use the C99 functions lrintf() and lrint() for casting from floating\n    point to int without incurring the huge perfromance penalty (particularly\n    on the i386 family) caused by the regular C cast from float to int.\n    These new C99 functions replace the FLOAT_TO_* and DOUBLE_TO_* macros which\n    I had been playing with.\n\n    * configure.in m4/lrint.m4 m4/lrintf.m4\n    Add detection of these functions.\n\n2001-10-17  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/voc.c\n    Completed code for reading VOC files containing a single audio data\n    segment.\n    Started implementing code to handle files with multiple VOC_SOUND_DATA\n    segments but couldn't be bothered finishing it. Multiple segment files can\n    have different sample rates for different sections and other nasties like\n    silence and repeat segments.\n\n2001-10-16  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/common.h src/*.c\n    Removed SF_PRIVATE struct field fdata and replaced it with extra_data.\n\n    * src/voc.c\n    Further development of the read part of this woefult file format.\n\n2001-10-04  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/float_cast.h\n    Implemented gcc and i386 floating point to int cast macros. Standard cast\n    will be used when not on gcc for i385.\n\n    * src/pcm.c\n    Modified all uses of FLOAT/DOUBLE_TO_INT and FLOAT/DOUBLE_TO_SHORT casts to\n    comply with macros in float_cast.h.\n\n2001-10-04  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/voc.c\n    Changed the TYPE_xxx enum names to VOC_TYPE_xxx to prevent name clashes\n    on MacOS with CodeWarrior 6.0.\n\n    * MacOS/MacOS-readme.txt\n    Updated the compile instructions. Probably still need work as I don't have\n    access to a Mac.\n\n2001-10-01  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/wav.c src/aiff.c common.c\n    Changed all references to snprintf to LSF_SNPRINTF and all vsnprintf to\n    LSF_VSNPRINTF. LSF_VSNPRINTF and LSF_VSNPRINTF are defined in common.h.\n\n    * src/common.h\n    Added checking of HAVE_SNPRINTF and HAVE_VSNPRINTF and defining\n    LSF_VSNPRINTF and LSF_VSNPRINTF to appropriate values.\n\n    * src/missing.c\n    New file containing a minimal implementation of snprintf and vsnprintf\n    functions named missing_snprintf and missing_vsnprintf respectively. These\n    are only compliled into the binary if snprintf and/or vsnprintf are not\n    available.\n\n2001-09-29  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/ircam.c\n    New file to handle Berkeley/IRCAM/CARL files.\n\n    * src/sndfile.c src/common.h\n    Modified for IRCAM handling.\n\n    * tests/*.c\n    Added tests for IRCAM files.\n\n2001-09-27  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/wav.c\n    Apparently microsoft windows (tm) doesn't like ulaw and Alaw WAV files with\n    20 byte format chunks (contrary to ms's own documentation). Fixed the WAV\n    header writing code to generate smaller ms compliant ulaw and Alaw WAV\n    files.\n\n2001-09-17  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/stdio_test.sh tests/stdio_test.c\n    Shell script was rewritten as a C program due to incompatibilities of the\n    sh shell on Linux and Solaris.\n\n2001-09-16  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/stdio_test.sh tests/stdout_test.c tests/stdin_test.c\n    New test programs to verify the correct operation of reading from stdin and\n    writing to stdout.\n\n    * src/sndfile.c wav.c au.c nist.c paf.c\n    Fixed a bugs uncovered by the new test programs above.\n\n2001-09-15  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.c wav.c\n    Fixed a bug preventing reading a file from stdin. Found by T. Narita.\n\n2001-09-12  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/common.h\n    Fixed a problem on OpenBSD 2.9 which was causing sf_seek() to fail on IMA\n    WAV files. Root cause was the declaration of the func_seek typedef not\n    matching the functions it was actually being used to point to. In OpenBSD\n    sizeof (off_t) != sizeof (int). Thanks to Heikki Korpela for allowing me\n    to log into his OpenBSD machine to debug this problem.\n\n2001-09-03  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.c\n    Implemented sf_command (\"norm float\").\n\n    * src/*.c\n    Implemented handling of sf_command (\"set-norm-float\"). Float normalization\n    can now be turned on and off.\n\n    * tests/double_test.c\n    Renamed to floating_point_test.c. Modified to include tests for all scaled\n    reads and writes of floats and doubles.\n\n    * src/au_g72x.c\n    Fixed bug in normalization code found with improved floating_point_test\n    program.\n\n    * src/wav.c\n    Added code for parsing 'INFO' and 'LIST' chunks. Will be used for extract\n    text annotations from WAV files.\n\n    * src/aiff.c\n    Added code for parsing '(c) ' and 'ANNO' chunks. Will be used for extract\n    text annotations from WAV files.\n\n2001-09-02  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * examples/sf_info.c example/Makefile.am\n    Renamed to sndfile_info.c. The program sndfile_info will now be installed\n    when the library is installed.\n\n    * src/float_cast.h\n    New file defining floating point to short and int casts. These casts will\n    eventually replace all flot and double casts to short and int. See comments\n    at the top of the file for the reasoning.\n\n    * src/*.c\n    Changed all default float and double casts to short or int with macros\n    defined in floatcast.h. At the moment these casts do nothing. They will be\n    replaced with faster float to int cast operations in the near future.\n\n2001-08-31  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/command_test.c\n    New file for testing sf_command () functionality.\n\n    * src/sndfile.c\n    Revisiting of error return values of some functions.\n    Started implementing sf_command () a new function will allow on-the-fly\n    modification of library behaviour, or instance, sample value scaling.\n\n    * src/common.h\n    Added hook for format specific sf_command () calls to SNDFILE struct.\n\n    * doc/api.html\n    Updated and errors corrected.\n\n    * doc/command.html\n    New documentation file explaining new sf_command () function.\n\n2001-08-11  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.c\n    Fixed error return values from sf_read*() and sf_write*(). There were\n    numerous instances of -1 being returned through size_t. These now all set\n    error int the SF_PRIVATE struct and return 0. Thanks to David Viens for\n    spotting this.\n\n2001-08-01  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/common.c\n    Fixed use of va_arg() calls that were causing warning messages with the\n    latest version of gcc (thanks Maurizio Umberto Puxeddu).\n\n2001-07-25  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/*.c src/sfendian.h\n    Moved definition of MAKE_MARKER macro to sfendian.h\n\n2001-07-23  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.c\n    Modified sf_get_lib_version () so that version string will be visible using\n    the Unix strings command.\n\n    * examples/Makefile.am examples/sfinfo.c\n    Renamed sfinfo program and source code to sf_info. This prevents a name\n    clash with the program included with libaudiofile.\n\n2001-07-22  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/read_seek_test.c tests/lossy_comp_test.c\n    Added tests for sf_read_float () and sf_readf_float ().\n\n    * src/voc.c\n    New files for handling Creative Voice files (not complete).\n\n    * src/samplitude.c\n    New files for handling Samplitude files (not complete).\n\n2001-07-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/aiff.c src/au.c src/paf.c src/svx.c src/wav.c\n    Converted these files to using psf_binheader_readf() function. Will soon be\n    ready to attempt to make reading writing from pipes work reliably.\n\n    * src/*.[ch]\n    Added code for sf_read_float () and sf_readf_float () methods of accessing\n    file data.\n\n2001-07-20  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/paf.c src/wav_gsm610.c\n    Removed two printf()s which had escaped notice for some time (thanks\n    Sigbjørn Skjæret).\n\n2001-07-19  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/wav_gsm610.c\n    Fixed a bug which prevented GSM 6.10 encoded WAV files generated by\n    libsndfile from being played in Windoze (thanks klay).\n\n2001-07-18  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/common.[ch]\n    Implemented psf_binheader_readf() which will do for file header reading what\n    psf_binheader_writef() did for writing headers. Will eventually allow\n    libsndfile to read and write from pipes, including named pipes.\n\n2001-07-16  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * MacOS/config.h Win32/config.h\n    Attempted to bring these two files uptodate with src/config.h. As I don't\n    have access to either of these systems support for them may be completely\n    broken.\n\n2001-06-18  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/float32.c\n    Fixed bug for big endian processors that can't read 32 bit IEEE floats. Now\n    tested on Intel x86 and UltraSparc processors.\n\n2001-06-13  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/aiff.c\n    Modified to allow REX files (from Propellorhead's Recycle and Reason\n    programs) to be read.\n    REX files are basically an AIFF file with slightly unusual sequence of\n    chunks (AIFF files are supposed to allow any sequence) and some extra\n    application specific information.\n    Not yet able to write a REX file as the details of the application specific\n    data is unknown.\n\n2001-06-12  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/wav.c\n    Fixed endian bug when reading PEAK chunk on big endian machines.\n\n    * src/common.c\n    Fixed endian bug when reading PEAK chunk on big endian machines with\n    --enable-force-broken-float configure option.\n    Fix psf_binheader_writef for (FORCE_BROKEN_FLOAT ||______)\n\n2001-06-07  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.in src/config.h.in\n    Removed old CAN_READ_WRITE_x86_IEEE configure variable now that float\n    capabilities are detected at run time.\n    Added FORCE_BROKEN_FLOAT to allow testing of broken float code on machines\n    where the processor can in fact handle floats correctly.\n\n    * src/float32.c\n    Rejigged code reading and writing of floats on broken processors.\n\n    * m4/\n    Removed this directory and all its files as they are no longer needed.\n\n2001-06-05  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/peak_chunk_test.c\n    New test to validate reading and writing of peak chunk.\n\n    * examples/sfconvert\n    Added -float32 option.\n\n    * src/*.c\n    Changed all error return values to negative values (ie the negative of what\n    they were).\n\n    * src/sndfile.c tests/error_test.c\n    Modified to take account of the previous change.\n\n2001-06-04  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/float32.c\n    File renamed from wav_float.c and renamed function to something more\n    general.\n    Added runtime detection of floating point capabilities.\n    Added recording of peaks during write for generation of PEAK chunk.\n\n    * src/wav.c src/aiff.c\n    Added handing for PEAK chunk for floating point files. PEAK is read when the\n    file headers are read and generated when the file is closed. Logic is in\n    place for adding PEAK chunk to end of file when writing to a pipe (reading\n    and writing from/to pipe to be implemented soon).\n\n    * src/sndfile.c\n    Modified sf_signal_max () to use PEAK values if present.\n\n2001-06-03  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/*.c\n    Added pcm_read_init () and pcm_write_init () to src/pcm.c and removed all\n    other calls to functions in this file from the filetype specific files.\n\n    * src/*.c\n    Added alaw_read_init (), alaw_write_int (), ulaw_read_init () and\n    ulaw_write_init () and removed all other calls to functions in alaw.c and\n    ulaw.c from the filetype specific files.\n\n    * tests/write_read_test.c\n    Added tests to validate sf_seek () on all file types.\n\n    * src/raw.c\n    Implemented raw_seek () function to fix a bug where\n    sf_seek (file, 0, SEEK_SET) on a RAW file failed.\n\n    * src/paf.c\n    Fixed a bug in paf24_seek () found due to added seeks tests in\n    tests/write_read_test.c\n\n2001-06-01  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/read_seek_test.c\n    Fixed a couple of broken binary files.\n\n    * src/aiff.c src/wav.c\n    Added handling of PEAK chunks on file read.\n\n2001-05-31  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * check_libsndfile.py\n    New file for the regression testing of libsndfile.\n    check_libsndfile.py is a Python script which reads in a file containing\n    filenames of audio files. Each file is checked by running the examples/sfinfo\n    program on them and checking for error or warning messages in the libsndfile\n    log buffer.\n\n    * check_libsndfile.list\n    This is an example list of audio files for use with check_libsndfile.py\n\n    * tests/lossy_comp_test.c\n    Changed the defined value of M_PI for math header files which don't have it.\n    This fixed validation test failures on MetroWerks compilers. Thanks to Lord\n    Praetor Satanus of Acheron for bringing this to my attention.\n\n2001-05-30  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/common.[ch]\n    Removed psf_header_setf () which was no longer required after refactoring\n    and simplification of header writing.\n    Added 'z' format specifier to psf_binheader_writef () for zero filling header\n    with N bytes. Used by paf.c and nist.c\n\n    * tests/check_log_buffer.c\n    New file implementing check_log_buffer () which reads the log buffer of a\n    SNDFILE* object and searches for error and warning messages. Calls exit ()\n    if any are found.\n\n    * tests/*.c\n    Added calls to check_log_buffer () after each call to sf_open_XXX ().\n\n2001-05-29  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/wav.c src/wav_ms_adpcm.c src/wav_gsm610.c\n    Major rehack of header writing using psf_binheader_writef ().\n\n2001-05-28  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/wav.c src/wav_ima_adpcm.c\n    Major rehack of header writing using psf_binheader_writef ().\n\n2001-05-27  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/wav.c\n    Changed return type of get_encoding_str () to prevent compiler warnings on\n    Mac OSX.\n\n    * src/aiff.c src/au.c\n    Major rehack of header writing using psf_binheader_writef ().\n\n2001-05-25  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/common.h src/common.c\n    Added comments.\n    Name of log buffer changed from strbuffer to logbuffer.\n    Name of log buffer index variable changed from strindex to logindex.\n\n    * src/*.[ch]\n    Changed name of internal logging function from psf_sprintf () to\n    psf_log_printf ().\n    Changed name of internal header generation functions from\n    psf_[ab]h_printf () to psf_asciiheader_printf () and\n    psf_binheader_writef ().\n    Changed name of internal header manipulation function psf_hsetf () to\n    psf_header_setf ().\n\n2001-05-24  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/nist.c\n    Fixed reading and writing of sample_byte_format header. \"01\" means little\n    endian and \"10\" means big endian regardless of bit width.\n\n    * configure.in\n    Detect Mac OSX and disable -Wall and -pedantic gcc options. Mac OSX is\n    way screwed up and spews out buckets of warning messages from the system\n    headers.\n    Added --disable-gcc-opt configure option (sets gcc optimisation to -O0 ) for\n    easier debugging.\n    Made decision to harmonise source code version number and .so library\n    version number. Future releases will stick to this rule.\n\n    * doc/new_file_type.HOWTO\n    New file to document the addition of new file types to libsndfile.\n\n2001-05-23  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/nist.c\n    New file for reading/writing Sphere NIST audio file format.\n    Originally requested by Elis Pomales in 1999.\n    Retrieved from unstable (and untouched for 18 months) branch of libsndfile.\n    Some vital information gleaned from the source code to Bill Schottstaedt's\n    sndlib library : ftp://ccrma-ftp.stanford.edu/pub/Lisp/sndlib.tar.gz\n    Currently reading and writing 16, 24 and 32 bit, big-endian and little\n    endian, stereo and mono files.\n\n    * src/common.h src/common.c\n    Added psf_ah_printf () function to help construction of ASCII headers (ie NIST).\n\n    * configure.in\n    Added test for vsnprintf () required by psf_ah_printf ().\n\n    * tests/write_read_test.c\n    Added tests for supported NIST files.\n\n2001-05-22  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/write_read_test.c\n    Added tests for little endian AIFC files.\n\n    * src/aiff.c\n    Minor re-working of aiff_open_write ().\n    Added write support for little endian PCM encoded AIFC files.\n\n2001-05-13  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/aiff.c\n    Minor re-working of aiff_open_read ().\n    Added read support for little endian PCM encoded AIFC files from the Mac\n    OSX CD ripper program. Guillaume Lessard provided a couple of sample files\n    and a working patch.\n    The patch was not used as is but gave a good guide as to what to do.\n\n2001-05-11  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.h\n    Fixed comments about endian-ness of WAV and AIFF files. Guillaume Lessard\n    pointed out the error.\n\n2001-04-23  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * examples/make_sine.c\n    Re-write of this example using sample rate and required frequency in Hz.\n\n2001-02-11  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.c\n    Fixed bug that prevented known file types from being read as RAW PCM data.\n\n2000-12-16  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/aiff.c\n    Added handing of COMT chunk.\n\n2000-11-16  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * examples/sfconvert.c\n    Fixed bug in normalisatio code. Pointed out by Johnny Wu.\n\n2000-11-08  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * Win32/config.h\n    Fixed the incorrect setting of HAVE_ENDIAN_H parameter. Win32 only issue.\n\n2000-10-27  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/Makefile.am\n    Added -lm for write_read_test_LDADD.\n\n2000-10-16  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.c src/au.c\n    Fixed bug which prevented writing of G723 24kbps AU files.\n\n    * tests/lossy_comp_test.c\n    Corrrection to options for G723 tests.\n\n    * configure.in\n    Added --disable-gcc-pipe option for DJGPP compiler (gcc on MS-DOS) which\n    doesn't allow gcc -pipe option.\n\n2000-09-03  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/ulaw.c src/alaw.c src/wav_imaadpcm.c src/msadpcm.c src/wav_gsm610.c\n    Fixed normailsation bugs shown up by new double_test program.\n\n2000-08-31  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/pcm.c\n    Fixed bug in normalisation code (spotted by Steve Lhomme).\n\n    * tests/double_test.c\n    New file to test scaled and unscaled sf_read_double() and sf_write_double()\n    functions.\n\n2000-08-28  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * COPYING\n    Changed to the LGPL COPYING file (spotted by H. S. Teoh).\n\n2000-08-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.h\n    Removed prototype of unimplemented function sf_get_info(). Added prototype\n    for sf_error_number() Thanks to Sigbjørn Skjæret for spotting these.\n\n2000-08-18  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/newpcm.h\n    New file to contain a complete rewrite of the PCM data handling.\n\n2000-08-15  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.c\n    Fixed a leak of FILE* pointers in sf_open_write(). Thanks to Sigbjørn\n    Skjæret for spotting this one.\n\n2000-08-13  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/au_g72x.c src/G72x/g72x.c\n    Added G723 encoded AU file support.\n\n    * tests/lossy_comp_test.c\n    Added tests for G721 and G723 encoded AU files.\n\n2000-08-06  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * all files\n    Changed the license to LGPL. Albert Faber who had copyright on\n    Win32/unistd.h gave his permission to change the license on that file. All\n    other files were either copyright erikd AT mega-nerd DOT com or copyright\n    under a GPL/LGPL compatible license.\n\n2000-08-06  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/lossy_comp_test.c\n    Fixed incorrect error message.\n\n    * src/au_g72x.c src/G72x/*\n    G721 encoded AU files now working.\n\n    * Win32/README-Win32.txt\n    Replaced this file with a new one which gives a full explanation\n    of how to build libsndfile under Win32. Thanks to Mike Ricos.\n\n2000-08-05  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/*.[ch]\n    Removed double leading underscores from the start of all variable and\n    function names. Identifiers with a leading underscores are reserved\n    for use by the compiler.\n\n    * src/au_g72x.c src/G72x/*\n    Continued work on G721 encoded AU files.\n\n2000-07-12  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/G72x/*\n    New files for reading/writing G721 and G723 ADPCM audio. These files\n    are from a Sun Microsystems reference implementation released under a\n    free software licence.\n    Extensive changes to this code to make it fit in with libsndfile.\n    See the ChangeLog in this directory for details.\n\n    * src/au_g72x.c\n    New file for G721 encoded AU files.\n\n2000-07-08  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * libsndfile.spec.in\n    Added a spec file for making RPMs. Thanks to Josh Green for supplying this.\n\n2000-06-28  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.c src/sndfile.h\n    Add checking for and handling of header-less u-law encoded AU/SND files.\n    Any file with a \".au\" or \".snd\" file extension and without the normal\n    AU file header is treated as an 8kHz, u-law encoded file.\n\n    * src/au.h\n    New function for opening a headerless u-law encoded file for read.\n\n2000-06-04  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/paf.c\n    Add checking for files shorter than minimal PAF file header length.\n\n2000-06-02  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/write_read_test.c\n    Added extra sf_perror() calls when sf_write_XXXX fails.\n\n2000-05-29  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/common.c\n    Modified usage of va_arg() macro to work correctly on PowerPC\n    Linux. Thanks to Kyle Wheeler for giving me ssh access to his\n    machine while I was trying to track this down.\n\n    * configure.in src/*.[ch]\n    Sorted out some endian-ness issues brought up by PowerPC Linux.\n\n    * tests/read_seek_test.c\n    Added extra debugging for when tests fail.\n\n2000-05-18  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/wav.c\n    Fixed bug in GSM 6.10 handling for big-endian machines. Thanks\n    to Sigbjørn Skjæret for reporting this.\n\n2000-04-25  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.c src/wav.c src/wav_gsm610.c\n    Finallised writing of GSM 6.10 WAV files.\n\n    * tests/lossy_comp_test.c\n    Wrote new test code for GSM 6.10 files.\n\n    * examples/sfinfo.c\n    Fixed incorrect format in printf() statement.\n\n2000-04-06  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.h.in\n    Fixed comments about sf_perror () and sf_error_str ().\n\n2000-03-14  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.in\n    Fixed --enable-justsrc option.\n\n2000-03-07  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * wav.c\n    Fixed checking of bytespersec field of header. Still some weirdness\n    with some files.\n\n2000-03-05  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/lossy_comp_test.c\n    Added option to test PCM WAV files (sanity check).\n    Fixed bug in sf_seek() tests.\n\n2000-02-29  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.c src/wav.c\n    Minor changes to allow writing of GSM 6.10 WAV files.\n\n2000-02-28  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.in Makefile.am src/Makefile.am\n    Finally got around to figuring out how to build a single library from\n    multiple source directories.\n    Reading GSM 6.10 files now seems to work.\n\n2000-01-03  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/wav.c\n    Added more error reporting in read_fmt_chunk().\n\n1999-12-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * examples/sfinfo.c\n    Modified program to accept multiple filenames from the command line.\n\n1999-11-27  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/wav_ima_adpcm.c\n    Moved code around in preparation to adding ability to read/write IMA ADPCM\n    encoded AIFF files.\n\n1999-11-16  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/common.c\n    Fixed put_int() and put_short() macros used by _psf_hprintf() which were\n    causing seg. faults on Sparc Solaris.\n\n1999-11-15  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/common.c\n    Added string.h to includes. Thanks to Sigbjxrn Skjfret.\n\n    * src/svx.c\n    Fixed __svx_close() function to ensure FORM and BODY chunks are correctly\n    set.\n\n1999-10-01  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/au.c\n    Fixed handling of incorrect size field in AU header on read. Thanks to\n    Christoph Lauer for finding this problem.\n\n1999-09-28  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/aiff.c\n    Fixed a bug with incorrect SSND chunk length being written. This also lead\n    to finding an minor error in AIFF header parsing. Thanks to Dan Timis for\n    pointing this out.\n\n1999-09-24  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/paf.c\n    Fixed a bug with reading and writing 24 bit stereo PAF files. This problem\n    came to light when implementing tests for the new functions which operate\n    in terms of frames rather than items.\n\n1999-09-23  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.c\n    Modified file type detection to use first 12 bytes of file rather than\n    file name extension. Required this because NIST files use the same\n    filename extension as Microsoft WAV files.\n\n    * src/sndfile.c src/sndfile.h\n    Added short, int and double read/write functions which work in frames\n    rather than items. This was originally suggested by Maurizio Umberto\n    Puxeddu.\n\n1999-09-22  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/svx.c\n    Finished off implementation of write using __psf_hprintf().\n\n1999-09-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/common.h\n    Added a buffer to SF_PRIVATE for writing the header. This is required\n    to make generating headers for IFF/SVX files easier as well as making\n    it easier to do re-write the headers which will be required when\n    sf_rewrite_header() is implemented.\n\n    * src/common.c\n    Implemented __psf_hprintf() function. This is an internal function\n    which is documented briefly just above the code.\n\n1999-09-05  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.c\n    Fixed a bug in sf_write_raw() where it was returning incorrect values\n    (thanks to Richard Dobson for finding this one). Must put in a test\n    routine for sf_read_raw and sf_write_raw.\n\n    * src/aiff.c\n    Fixed default FORMsize in __aiff_open_write ().\n\n    * src/sndfile.c\n    Added copy of filename to internal data structure. IFF/SVX files\n    contain a NAME header chunk. Both sf_open_read() and sf_open_write()\n    copy the file name (less the leading path information) to the\n    filename field.\n\n    * src/svx.c\n    Started implementing writing of files.\n\n1999-08-04  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/svx.c\n    New file for reading/writing 8SVX and 16SVX files.\n\n    * src/sndfile.[ch] src/common.h\n    Changes for SVX files.\n\n    * src/aiff.c\n    Fixed header parsing when unknown chunk is found.\n\n1999-08-01  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/paf.c\n    New file for reading/writing Ensoniq PARIS audio file format.\n\n    * src/sndfile.[ch] src/common.h\n    Changes for PAF files.\n\n    * src/sndfile.[ch]\n    Added stuff for sf_get_lib_version() function.\n\n\n1999-07-31  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.h MacOS/config.h\n    Fixed minor MacOS configuration issues.\n\n1999-07-30  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * MacOS/\n    Added a new directory for the MacOS config.h file and the\n    readme file.\n\n    * src/aiff.c\n    Fixed calculation of datalength when reading SSND chunk. Thanks to\n    Sigbjørn Skjæret for pointing out this error.\n\n1999-07-29  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.c src/sndfile.h src/raw.c\n    Further fixing of #includes for MacOS.\n\n1999-07-25  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/wav.c src/aiff.c\n    Added call to ferror () in main header parsing loop of __XXX_open_read\n    functions. This should fix problems on platforms (MacOS, AmigaOS) where\n    fseek()ing or fread()ing beyond the end of the file puts the FILE*\n    stream in an error state until clearerr() is called.\n\n    * tests/write_read_test.c\n    Added tests for RAW header-less PCM files.\n\n    * src/common.h\n    Moved definition of struct tribyte to pcm.c which is the only place\n    which needs it.\n\n    * src/pcm.c\n    Modified all code which assumed sizeof (struct tribyte) == 3. This code\n    did not work on MacOS. Thanks to Ben \"Jacobs\" for pointing this out.\n\n    * src/au.c\n    Removed <sys/stat.h> from list of #includes (not being used).\n\n    * src/sndfile.c\n    Added MacOS specific #ifdef to replace <sys/stat.h>.\n\n    * src/sndfile.h\n    Added MacOS specific #ifdef to replace <sys/stat.h>.\n\n    * src/sndfile.h\n    Added MacOS specific typedef for off_t.\n\n    * MacOS-readme.txt\n    New file with instructions for building libsndfile under MacOS. Thanks\n    to Ben \"Jacobs\" for supplying these instructions.\n\n1999-07-24  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.in\n    Removed sndfile.h from generated file list as there were no longer\n    any autoconf substitutions being made.\n\n    * src/raw.c\n    New file for handling raw header-less PCM files. In order to open these\n    for read, the user must specify format, pcmbitwidth and channels in the\n    SF_INFO struct when calling sf_open_read ().\n\n    * src/sndfile.c\n    Added support for raw header-less PCM files.\n\n1999-07-22  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * examples/sfinfo.c\n    Removed options so the sfinfo program always prints out all the information.\n\n1999-07-19  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/alaw.c\n    New file for A-law encoding (similar to u-law).\n\n    * tests/alaw_test.c\n    New test program to test the A-law encode/decode lookup tables.\n\n    * tests/lossy_comp_test.c\n    Added tests for a-law encoded WAV, AU and AULE files.\n\n1999-07-18  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.c src/au.c\n    Removed second \"#include <unistd.h>\". Thanks to Ben \"Jacobs\" for pointing\n    this out.\n\n1999-07-18  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/ulaw_test.c\n    New test program to test the u-law encode/decode lookup tables.\n\n1999-07-16  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.h\n    Made corrections to comments on the return values from sf_seek ().\n\n    * src/sndfile.c\n    Fixed boundary condition checking bug and accounting bug in sf_read_raw ().\n\n1999-07-15  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/au.c src/ulaw.c\n    Finished implementation of u-law encoded AU files.\n\n    * src/wav.c\n    Implemented reading and writing of u-law encoded WAV files.\n\n    * tests/\n    Changed name of adpcm_test.c to lossy_comp_test.c. This test program\n    will now be used to test Ulaw and Alaw encoding as well as APDCM.\n    Added tests for Ulaw encoded WAV files.\n\n1999-07-14  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/adpcm_test.c\n    Initialised amp variable in gen_signal() to remove compiler warning.\n\n1999-07-12  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/aiff.c\n    In __aiff_open_read () prevented fseek()ing beyond end of file which\n    was causing trouble on MacOS with the MetroWerks compiler. Thanks to\n    Ben \"Jacobs\" for pointing this out.\n\n    *src/wav.c\n    Fixed as above in __wav_open_read ().\n\n1999-07-01    Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/wav_ms_adpcm.c\n    Implemented MS ADPCM encoding. Code cleanup of decoder.\n\n    * tests/adpcm_test.c\n    Added tests for MS ADPCM WAV files.\n\n    * src/wav_ima_adpcm.c\n    Fixed incorrect parameter in call to srate2blocksize () from\n    __ima_writer_init ().\n\n1999-06-23  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/read_seek_test.c\n    Added test for 8 bit AIFF files.\n\n1999-06-18  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/write_read_test.c\n    Removed test for IMA ADPCM WAV files which is now done in adpcm_test.c\n\n    * configure.in\n    Added -Wconversion to CFLAGS.\n\n    * src/*.c tests/*.c examples/*.c\n    Fixed all warnings resulting from use of -Wconversion.\n\n1999-06-17  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/wav.c\n    Added fact chunk handling on read and write for all non WAVE_FORMAT_PCM\n    WAV files.\n\n    * src/wav_ima.c\n    Changed block alignment to be dependant on sample rate. This should make\n    WAV files created with libsndfile compatible with the MS Windows media\n    players.\n\n    * tests/adpcm_test.c\n    Reimplemented adpcm_test_short and implemented adpcm_test_int and\n    adpcm_test_double.\n    Now have full testing of IMA ADPCM WAV file read, write and seek.\n\n1999-06-15  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/wav_float.c\n    Fixed function prototype for x86f2d_array () which was causing ocassional\n    seg. faults on Sparc Solaris machines.\n\n1999-06-14  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/aiff.c\n    Fixed bug in __aiff_close where the length fields in the header were\n    not being correctly calculated before writing.\n\n    * tests/write_read_test.c\n    Modified to detect the above bug in WAV, AIFF and AU files.\n\n1999-06-12    Erik de Castro Lopo     <erikd AT mega-nerd DOT com>\n\n    * Win32/*\n    Added a contribution from Albert Faber to allow libsndfile to compile\n    under Win32 systems. libsndfile will now be used as part of LAME the\n    the MPEG 1 Layer 3 encoder (http://internet.roadrunner.com/~mt/mp3/).\n\n1999-06-11    Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.in\n    Changed to reflect previous changes.\n\n    * src/wav_ima_adpcm.c\n    Fixed incorrect calculation of bytespersec header field (IMA ADPCM only).\n\n    Fixed bug when writing from int or double data to IMA ADPCM file. Will need\n    to write test code for this.\n\n    Fixed bug in __ima_write () whereby the length of the current block was\n    calculated incorrectly. Thanks to Jongcheon Park for pointing this out.\n\n1999-03-27  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/*.c\n    Changed all read/write/lseek function calls to fread/fwrite/\n    fseek/ftell and added error checking of return values from\n    fread and fwrite in critical areas of the code.\n\n    * src/au.c\n    Fixed incorrect datasize element in AU header on write.\n\n    * tests/error_test.c\n    Add new test to check all error values have an associated error\n    string. This will avoid embarrassing real world core dumps.\n\n1999-03-23  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/wav.c src/aiff.c\n    Added handling for unknown chunk markers in the file.\n\n1999-03-22  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.c\n    Filled in missing error strings in SndfileErrors array. Missing entries\n    can cause core dumps when calling sf_error-str (). Thanks to Sam\n    <mrsam at-sign geocities.com> for finding this problem.\n\n1999-03-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/wav_ima_adpcm.c\n    Work on wav_ms_adpcm.c uncovered a bug in __ima_read () when reading\n    stereo files. Caused by not adjusting offset into buffer of decoded\n    samples for 2 channels. A similar bug existed in __ima_write ().\n    Need a test for stereo ADPCM files.\n\n    * src/wav_ms_adpcm.c\n    Decoder working correctly.\n\n1999-03-18  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * configure.in Makefile.am\n    Added --enable-justsrc configuration variable sent by Sam\n    <mrsam at-sign geocities.com>.\n\n    * src/wav_ima_adpcm.c\n    Fixed bug when reading beyond end of data section due to not\n    checking pima->blockcount.\n    This uncovered __ima_seek () bug due to pima->blockcount being set\n    before calling __ima_init_block ().\n\n1999-03-17  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/wav.c\n    Started implementing MS ADPCM decoder.\n    If file is WAVE_FORMAT_ADPCM and length of data chunk is odd, this\n    encoder seems to add an extra byte. Why not just give an even data\n    length?\n\n1999-03-16  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/wav.c\n    Split code out of wav.c to create wav_float.c and wav_ima_adpcm.c.\n    This will make it easier to add and debug other kinds of WAV files\n    in future.\n\n1999-03-14  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/\n    Added adpcm_test.c which implements test functions for\n    IMA ADPCM reading/writing/seeking etc.\n\n    * src/wav.c\n    Fixed many bugs in IMA ADPCM encoder and decoder.\n\n1999-03-11  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/wav.c\n    Finished implementing IMA ADPCM encoder and decoder (what a bitch!).\n\n1999-03-03  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/wav.c\n    Started implementing IMA ADPCM decoder.\n\n1999-03-02  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/sndfile.c\n    Fixed bug where the sf_read_XXX functions were returning a\n    incorrect read count when reading past end of file.\n    Fixed bug in sf_seek () when seeking backwards from end of file.\n\n    * tests/read_seek_test.c\n    Added multiple read test to short_test(), int_test () and\n    double_test ().\n    Added extra chunk to all test WAV files to test that reading\n    stops at end of 'data' chunk.\n\n1999-02-21  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/write_read_test.c\n    Added tests for little DEC endian AU files.\n\n    * src/au.c\n    Add handling for DEC format little endian AU files.\n\n1999-02-20  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/aiff.c src/au.c src/wav.c\n    Add __psf_sprintf calls during header parsing.\n\n    * src/sndfile.c src/common.c\n    Implement sf_header_info (sndfile.c) function and __psf_sprintf (common.c).\n\n    * tests/write_read_test.c\n    Added tests for 8 bit PCM files (WAV, AIFF and AU).\n\n    * src/au.c src/aiff.c\n    Add handling of 8 bit PCM data format.\n\n    * src/aiff.c\n    On write, set blocksize in SSND chunk to zero like everybody else.\n\n1999-02-16  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/pcm.c:\n    Fixed bug in let2s_array (cptr was not being initialised).\n\n    * src/sndfile.c:\n    Fixed bug in sf_read_raw and sf_write_raw. sf_seek should\n    now work when using these functions.\n\n1999-02-15  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * tests/write_read_test.c:\n    Force test_buffer array to be double aligned. Sparc Solaris\n    requires this.\n\n1999-02-14  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/pcm.c:\n    Fixed a bug which was causing errors in the reading\n    and writing of 24 bit PCM files.\n\n    * doc/api.html\n    Finished of preliminary documentaion.\n\n1999-02-13  Erik de Castro Lopo  <erikd AT mega-nerd DOT com>\n\n    * src/aiff.c:\n    Changed reading of 'COMM' chunk to avoid reading an int\n    which overlaps an int (4 byte) boundary.\n"
  },
  {
    "path": "vendor/libsndfile/NEWS",
    "content": "Version 1.0.28 (2017-04-02)\n  * Fix buffer overruns in FLAC and ID3 handling code.\n  * Move to variable length header storage.\n  * Fix detection of Large File Support for 32 bit systems.\n  * Remove large stack allocations in ALAC handling code.\n  * Remove all use of Variable Length Arrays.\n  * Minor bug fixes and improvements.\n\nVersion 1.0.27 (2016-06-19)\n  * Fix an SF_INFO seekable flag regression introduced in 1.0.26.\n  * Fix potential infinite loops on malformed input files.\n  * Add string metadata read/write for CAF and RF64.\n  * Add handling of CUE chunks.\n  * Fix endian-ness issues in PAF files.\n  * Minor bug fixes and improvements.\n\nVersion 1.0.26 (2015-11-22)\n  * Fix for CVE-2014-9496, SD2 buffer read overflow.\n  * Fix for CVE-2014-9756, file_io.c divide by zero.\n  * Fix for CVE-2015-7805, AIFF heap write overflow.\n  * Add support for ALAC encoder in a CAF container.\n  * Add support for Cart chunks in WAV files.\n  * Minor bug fixes and improvements.\n\nVersion 1.0.25 (2011-07-13)\n  * Fix for Secunia Advisory SA45125, heap overflow in PAF file handler.\n  * Accept broken WAV files with blockalign == 0.\n  * Minor bug fixes and improvements.\n\nVersion 1.0.24 (2011-03-23)\n  * WAV files now have an 18 byte u-law and A-law fmt chunk.\n  * Document virtual I/O functionality.\n  * Two new methods rawHandle() and takeOwnership() in sndfile.hh.\n  * AIFF fix for non-zero offset value in SSND chunk.\n  * Minor bug fixes and improvements.\n\nVersion 1.0.23 (2010-10-10)\n  * Add version metadata to Windows DLL.\n  * Add a missing 'inline' to sndfile.hh.\n  * Update docs.\n  * Minor bug fixes and improvements.\n\nVersion 1.0.22 (2010-10-04)\n  * Couple of fixes for SDS file writer.\n  * Fixes arising from static analysis.\n  * Handle FLAC files with ID3 meta data at start of file.\n  * Handle FLAC files which report zero length.\n  * Other minor bug fixes and improvements.\n\nVersion 1.0.21 (2009-12-13)\n  * Add a couple of new binary programs to programs/ dir.\n  * Remove sndfile-jackplay (now in sndfile-tools package).\n  * Add windows only function sf_wchar_open().\n  * Bunch of minor bug fixes.\n\nVersion 1.0.20 (2009-05-14)\n  * Fix potential heap overflow in VOC file parser (Tobias Klein, http://www.trapkit.de/).\n\nVersion 1.0.19 (2009-03-02)\n  * Fix for CVE-2009-0186 (Alin Rad Pop, Secunia Research).\n  * Huge number of minor bug fixes as a result of static analysis.\n\nVersion 1.0.18 (2009-02-07)\n  * Add Ogg/Vorbis support (thanks to John ffitch).\n  * Remove captive FLAC library.\n  * Many new features and bug fixes.\n  * Generate Win32 and Win64 pre-compiled binaries.\n\nVersion 1.0.17 (2006-08-31)\n  * Add sndfile.hh C++ wrapper.\n  * Update Win32 MinGW build instructions.\n  * Minor bug fixes and cleanups.\n\nVersion 1.0.16 (2006-04-30)\n  * Add support for Broadcast (BEXT) chunks in WAV files.\n  * Implement new commands SFC_GET_SIGNAL_MAX and SFC_GET_MAX_ALL_CHANNELS.\n  * Add support for RIFX (big endian WAV variant).\n  * Fix configure script bugs.\n  * Fix bug in INST and MARK chunk writing for AIFF files.\n\nVersion 1.0.15 (2006-03-16)\n  * Fix some ia64 issues.\n  * Fix precompiled DLL.\n  * Minor bug fixes.\n\nVersion 1.0.14 (2006-02-19)\n  * Really fix MinGW compile problems.\n  * Minor bug fixes.\n\nVersion 1.0.13 (2006-01-21)\n  * Fix for MinGW compiler problems.\n  * Allow readin/write of instrument chunks from WAV and AIFF files.\n  * Compile problem fix for Solaris compiler.\n  * Minor cleanups and bug fixes.\n\nVersion 1.0.12 (2005-09-30)\n  * Add support for FLAC and Apple's Core Audio Format (CAF).\n  * Add virtual I/O interface (still needs docs).\n  * Cygwin and other Win32 fixes.\n  * Minor bug fixes and cleanups.\n\nVersion 1.0.11 (2004-11-15)\n  * Add support for SD2 files.\n  * Add read support for loop info in WAV and AIFF files.\n  * Add more tests.\n  * Improve type safety.\n  * Minor optimisations and bug fixes.\n\nVersion 1.0.10 (2004-06-15)\n  * Fix AIFF read/write mode bugs.\n  * Add support for compiling Win32 DLLS using MinGW.\n  * Fix problems resulting in failed compiles with gcc-2.95.\n  * Improve test suite.\n  * Minor bug fixes.\n\nVersion 1.0.9 (2004-03-30)\n  * Add handling of AVR (Audio Visual Research) files.\n  * Improve handling of WAVEFORMATEXTENSIBLE WAV files.\n  * Fix for using pipes on Win32.\n\nVersion 1.0.8 (2004-03-14)\n  * Correct peak chunk handing for files with > 16 tracks.\n  * Fix for WAV files with huge number of CUE chunks.\n\nVersion 1.0.7 (2004-02-25)\n  * Fix clip mode detection on ia64, MIPS and other CPUs.\n  * Fix two MacOSX build problems.\n\nVersion 1.0.6 (2004-02-08)\n  * Added support for native Win32 file access API (Ross Bencina).\n  * New mode to add clippling then a converting from float/double to integer\n    would otherwise wrap around.\n  * Fixed a bug in reading/writing files > 2Gig on Linux, Solaris and others.\n  * Many minor bug fixes.\n  * Other random fixes for Win32.\n\nVersion 1.0.5 (2003-05-03)\n  * Added support for HTK files.\n  * Added new function sf_open_fd() to allow for secure opening of temporary\n    files as well as reading/writing sound files embedded within larger\n    container files.\n  * Added string support for AIFF files.\n  * Minor bug fixes and code cleanups.\n\nVersion 1.0.4 (2003-02-02)\n  * Added suport of PVF and XI files.\n  * Added functionality for setting and retreiving strings from sound files.\n  * Minor code cleanups and bug fixes.\n\nVersion 1.0.3 (2002-12-09)\n  * Minor bug fixes.\n\nVersion 1.0.2 (2002-11-24)\n  * Added support for VOX ADPCM.\n  * Improved error reporting.\n  * Added version scripting on Linux and Solaris.\n  * Minor bug fixes.\n\nVersion 1.0.1 (2002-09-14)\n  * Added MAT and MAT5 file formats.\n  * Minor bug fixes.\n\nVersion 1.0.0 (2002-08-16)\n  * Final release for 1.0.0.\n\nVersion 1.0.0rc6 (2002-08-14)\n  * Release candidate 6 for the 1.0.0 series.\n  * MacOS9 fixes.\n\nVersion 1.0.0rc5 (2002-08-10)\n  * Release candidate 5 for the 1.0.0 series.\n  * Changed the definition of sf_count_t which was causing problems when\n    libsndfile was compiled with other libraries (ie WxWindows).\n  * Minor bug fixes.\n  * Documentation cleanup.\n\nVersion 1.0.0rc4 (2002-08-03)\n  * Release candidate 4 for the 1.0.0 series.\n  * Minor bug fixes.\n  * Fix broken Win32 \"make check\".\n\nVersion 1.0.0rc3 (2002-08-02)\n  * Release candidate 3 for the 1.0.0 series.\n  * Fix bug where libsndfile was reading beyond the end of the data chunk.\n  * Added on-the-fly header updates on write.\n  * Fix a couple of documentation issues.\n\nVersion 1.0.0rc2 (2002-06-24)\n  * Release candidate 2 for the 1.0.0 series.\n  * Fix compile problem for Win32.\n\nVersion 1.0.0rc1 (2002-06-24)\n  * Release candidate 1 for the 1.0.0 series.\n\nVersion 0.0.28 (2002-04-27)\n  * Last offical release of 0.0.X series of the library.\n\nVersion 0.0.8 (1999-02-16)\n  * First offical release.\n"
  },
  {
    "path": "vendor/libsndfile/include/sndfile.h",
    "content": "/*\n** Copyright (C) 1999-2016 Erik de Castro Lopo <erikd@mega-nerd.com>\n**\n** This program is free software; you can redistribute it and/or modify\n** it under the terms of the GNU Lesser General Public License as published by\n** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.\n**\n** You should have received a copy of the GNU Lesser General Public License\n** along with this program; if not, write to the Free Software\n** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n*/\n\n/*\n** sndfile.h -- system-wide definitions\n**\n** API documentation is in the doc/ directory of the source code tarball\n** and at http://www.mega-nerd.com/libsndfile/api.html.\n*/\n\n#ifndef SNDFILE_H\n#define SNDFILE_H\n\n/* This is the version 1.0.X header file. */\n#define\tSNDFILE_1\n\n#include <stdio.h>\n#include <stdint.h>\n#include <sys/types.h>\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\t/* __cplusplus */\n\n/* The following file types can be read and written.\n** A file type would consist of a major type (ie SF_FORMAT_WAV) bitwise\n** ORed with a minor type (ie SF_FORMAT_PCM). SF_FORMAT_TYPEMASK and\n** SF_FORMAT_SUBMASK can be used to separate the major and minor file\n** types.\n*/\n\nenum\n{\t/* Major formats. */\n\tSF_FORMAT_WAV\t\t\t= 0x010000,\t\t/* Microsoft WAV format (little endian default). */\n\tSF_FORMAT_AIFF\t\t\t= 0x020000,\t\t/* Apple/SGI AIFF format (big endian). */\n\tSF_FORMAT_AU\t\t\t= 0x030000,\t\t/* Sun/NeXT AU format (big endian). */\n\tSF_FORMAT_RAW\t\t\t= 0x040000,\t\t/* RAW PCM data. */\n\tSF_FORMAT_PAF\t\t\t= 0x050000,\t\t/* Ensoniq PARIS file format. */\n\tSF_FORMAT_SVX\t\t\t= 0x060000,\t\t/* Amiga IFF / SVX8 / SV16 format. */\n\tSF_FORMAT_NIST\t\t\t= 0x070000,\t\t/* Sphere NIST format. */\n\tSF_FORMAT_VOC\t\t\t= 0x080000,\t\t/* VOC files. */\n\tSF_FORMAT_IRCAM\t\t\t= 0x0A0000,\t\t/* Berkeley/IRCAM/CARL */\n\tSF_FORMAT_W64\t\t\t= 0x0B0000,\t\t/* Sonic Foundry's 64 bit RIFF/WAV */\n\tSF_FORMAT_MAT4\t\t\t= 0x0C0000,\t\t/* Matlab (tm) V4.2 / GNU Octave 2.0 */\n\tSF_FORMAT_MAT5\t\t\t= 0x0D0000,\t\t/* Matlab (tm) V5.0 / GNU Octave 2.1 */\n\tSF_FORMAT_PVF\t\t\t= 0x0E0000,\t\t/* Portable Voice Format */\n\tSF_FORMAT_XI\t\t\t= 0x0F0000,\t\t/* Fasttracker 2 Extended Instrument */\n\tSF_FORMAT_HTK\t\t\t= 0x100000,\t\t/* HMM Tool Kit format */\n\tSF_FORMAT_SDS\t\t\t= 0x110000,\t\t/* Midi Sample Dump Standard */\n\tSF_FORMAT_AVR\t\t\t= 0x120000,\t\t/* Audio Visual Research */\n\tSF_FORMAT_WAVEX\t\t\t= 0x130000,\t\t/* MS WAVE with WAVEFORMATEX */\n\tSF_FORMAT_SD2\t\t\t= 0x160000,\t\t/* Sound Designer 2 */\n\tSF_FORMAT_FLAC\t\t\t= 0x170000,\t\t/* FLAC lossless file format */\n\tSF_FORMAT_CAF\t\t\t= 0x180000,\t\t/* Core Audio File format */\n\tSF_FORMAT_WVE\t\t\t= 0x190000,\t\t/* Psion WVE format */\n\tSF_FORMAT_OGG\t\t\t= 0x200000,\t\t/* Xiph OGG container */\n\tSF_FORMAT_MPC2K\t\t\t= 0x210000,\t\t/* Akai MPC 2000 sampler */\n\tSF_FORMAT_RF64\t\t\t= 0x220000,\t\t/* RF64 WAV file */\n\n\t/* Subtypes from here on. */\n\n\tSF_FORMAT_PCM_S8\t\t= 0x0001,\t\t/* Signed 8 bit data */\n\tSF_FORMAT_PCM_16\t\t= 0x0002,\t\t/* Signed 16 bit data */\n\tSF_FORMAT_PCM_24\t\t= 0x0003,\t\t/* Signed 24 bit data */\n\tSF_FORMAT_PCM_32\t\t= 0x0004,\t\t/* Signed 32 bit data */\n\n\tSF_FORMAT_PCM_U8\t\t= 0x0005,\t\t/* Unsigned 8 bit data (WAV and RAW only) */\n\n\tSF_FORMAT_FLOAT\t\t\t= 0x0006,\t\t/* 32 bit float data */\n\tSF_FORMAT_DOUBLE\t\t= 0x0007,\t\t/* 64 bit float data */\n\n\tSF_FORMAT_ULAW\t\t\t= 0x0010,\t\t/* U-Law encoded. */\n\tSF_FORMAT_ALAW\t\t\t= 0x0011,\t\t/* A-Law encoded. */\n\tSF_FORMAT_IMA_ADPCM\t\t= 0x0012,\t\t/* IMA ADPCM. */\n\tSF_FORMAT_MS_ADPCM\t\t= 0x0013,\t\t/* Microsoft ADPCM. */\n\n\tSF_FORMAT_GSM610\t\t= 0x0020,\t\t/* GSM 6.10 encoding. */\n\tSF_FORMAT_VOX_ADPCM\t\t= 0x0021,\t\t/* OKI / Dialogix ADPCM */\n\n\tSF_FORMAT_G721_32\t\t= 0x0030,\t\t/* 32kbs G721 ADPCM encoding. */\n\tSF_FORMAT_G723_24\t\t= 0x0031,\t\t/* 24kbs G723 ADPCM encoding. */\n\tSF_FORMAT_G723_40\t\t= 0x0032,\t\t/* 40kbs G723 ADPCM encoding. */\n\n\tSF_FORMAT_DWVW_12\t\t= 0x0040, \t\t/* 12 bit Delta Width Variable Word encoding. */\n\tSF_FORMAT_DWVW_16\t\t= 0x0041, \t\t/* 16 bit Delta Width Variable Word encoding. */\n\tSF_FORMAT_DWVW_24\t\t= 0x0042, \t\t/* 24 bit Delta Width Variable Word encoding. */\n\tSF_FORMAT_DWVW_N\t\t= 0x0043, \t\t/* N bit Delta Width Variable Word encoding. */\n\n\tSF_FORMAT_DPCM_8\t\t= 0x0050,\t\t/* 8 bit differential PCM (XI only) */\n\tSF_FORMAT_DPCM_16\t\t= 0x0051,\t\t/* 16 bit differential PCM (XI only) */\n\n\tSF_FORMAT_VORBIS\t\t= 0x0060,\t\t/* Xiph Vorbis encoding. */\n\n\tSF_FORMAT_ALAC_16\t\t= 0x0070,\t\t/* Apple Lossless Audio Codec (16 bit). */\n\tSF_FORMAT_ALAC_20\t\t= 0x0071,\t\t/* Apple Lossless Audio Codec (20 bit). */\n\tSF_FORMAT_ALAC_24\t\t= 0x0072,\t\t/* Apple Lossless Audio Codec (24 bit). */\n\tSF_FORMAT_ALAC_32\t\t= 0x0073,\t\t/* Apple Lossless Audio Codec (32 bit). */\n\n\t/* Endian-ness options. */\n\n\tSF_ENDIAN_FILE\t\t\t= 0x00000000,\t/* Default file endian-ness. */\n\tSF_ENDIAN_LITTLE\t\t= 0x10000000,\t/* Force little endian-ness. */\n\tSF_ENDIAN_BIG\t\t\t= 0x20000000,\t/* Force big endian-ness. */\n\tSF_ENDIAN_CPU\t\t\t= 0x30000000,\t/* Force CPU endian-ness. */\n\n\tSF_FORMAT_SUBMASK\t\t= 0x0000FFFF,\n\tSF_FORMAT_TYPEMASK\t\t= 0x0FFF0000,\n\tSF_FORMAT_ENDMASK\t\t= 0x30000000\n} ;\n\n/*\n** The following are the valid command numbers for the sf_command()\n** interface.  The use of these commands is documented in the file\n** command.html in the doc directory of the source code distribution.\n*/\n\nenum\n{\tSFC_GET_LIB_VERSION\t\t\t\t= 0x1000,\n\tSFC_GET_LOG_INFO\t\t\t\t= 0x1001,\n\tSFC_GET_CURRENT_SF_INFO\t\t\t= 0x1002,\n\n\n\tSFC_GET_NORM_DOUBLE\t\t\t\t= 0x1010,\n\tSFC_GET_NORM_FLOAT\t\t\t\t= 0x1011,\n\tSFC_SET_NORM_DOUBLE\t\t\t\t= 0x1012,\n\tSFC_SET_NORM_FLOAT\t\t\t\t= 0x1013,\n\tSFC_SET_SCALE_FLOAT_INT_READ\t= 0x1014,\n\tSFC_SET_SCALE_INT_FLOAT_WRITE\t= 0x1015,\n\n\tSFC_GET_SIMPLE_FORMAT_COUNT\t\t= 0x1020,\n\tSFC_GET_SIMPLE_FORMAT\t\t\t= 0x1021,\n\n\tSFC_GET_FORMAT_INFO\t\t\t\t= 0x1028,\n\n\tSFC_GET_FORMAT_MAJOR_COUNT\t\t= 0x1030,\n\tSFC_GET_FORMAT_MAJOR\t\t\t= 0x1031,\n\tSFC_GET_FORMAT_SUBTYPE_COUNT\t= 0x1032,\n\tSFC_GET_FORMAT_SUBTYPE\t\t\t= 0x1033,\n\n\tSFC_CALC_SIGNAL_MAX\t\t\t\t= 0x1040,\n\tSFC_CALC_NORM_SIGNAL_MAX\t\t= 0x1041,\n\tSFC_CALC_MAX_ALL_CHANNELS\t\t= 0x1042,\n\tSFC_CALC_NORM_MAX_ALL_CHANNELS\t= 0x1043,\n\tSFC_GET_SIGNAL_MAX\t\t\t\t= 0x1044,\n\tSFC_GET_MAX_ALL_CHANNELS\t\t= 0x1045,\n\n\tSFC_SET_ADD_PEAK_CHUNK\t\t\t= 0x1050,\n\tSFC_SET_ADD_HEADER_PAD_CHUNK\t= 0x1051,\n\n\tSFC_UPDATE_HEADER_NOW\t\t\t= 0x1060,\n\tSFC_SET_UPDATE_HEADER_AUTO\t\t= 0x1061,\n\n\tSFC_FILE_TRUNCATE\t\t\t\t= 0x1080,\n\n\tSFC_SET_RAW_START_OFFSET\t\t= 0x1090,\n\n\tSFC_SET_DITHER_ON_WRITE\t\t\t= 0x10A0,\n\tSFC_SET_DITHER_ON_READ\t\t\t= 0x10A1,\n\n\tSFC_GET_DITHER_INFO_COUNT\t\t= 0x10A2,\n\tSFC_GET_DITHER_INFO\t\t\t\t= 0x10A3,\n\n\tSFC_GET_EMBED_FILE_INFO\t\t\t= 0x10B0,\n\n\tSFC_SET_CLIPPING\t\t\t\t= 0x10C0,\n\tSFC_GET_CLIPPING\t\t\t\t= 0x10C1,\n\n\tSFC_GET_CUE_COUNT\t\t\t\t= 0x10CD,\n\tSFC_GET_CUE\t\t\t\t\t\t= 0x10CE,\n\tSFC_SET_CUE\t\t\t\t\t\t= 0x10CF,\n\n\tSFC_GET_INSTRUMENT\t\t\t\t= 0x10D0,\n\tSFC_SET_INSTRUMENT\t\t\t\t= 0x10D1,\n\n\tSFC_GET_LOOP_INFO\t\t\t\t= 0x10E0,\n\n\tSFC_GET_BROADCAST_INFO\t\t\t= 0x10F0,\n\tSFC_SET_BROADCAST_INFO\t\t\t= 0x10F1,\n\n\tSFC_GET_CHANNEL_MAP_INFO\t\t= 0x1100,\n\tSFC_SET_CHANNEL_MAP_INFO\t\t= 0x1101,\n\n\tSFC_RAW_DATA_NEEDS_ENDSWAP\t\t= 0x1110,\n\n\t/* Support for Wavex Ambisonics Format */\n\tSFC_WAVEX_SET_AMBISONIC\t\t\t= 0x1200,\n\tSFC_WAVEX_GET_AMBISONIC\t\t\t= 0x1201,\n\n\t/*\n\t** RF64 files can be set so that on-close, writable files that have less\n\t** than 4GB of data in them are converted to RIFF/WAV, as per EBU\n\t** recommendations.\n\t*/\n\tSFC_RF64_AUTO_DOWNGRADE\t\t\t= 0x1210,\n\n\tSFC_SET_VBR_ENCODING_QUALITY\t= 0x1300,\n\tSFC_SET_COMPRESSION_LEVEL\t\t= 0x1301,\n\n\t/* Cart Chunk support */\n\tSFC_SET_CART_INFO\t\t\t\t= 0x1400,\n\tSFC_GET_CART_INFO\t\t\t\t= 0x1401,\n\n\t/* Following commands for testing only. */\n\tSFC_TEST_IEEE_FLOAT_REPLACE\t\t= 0x6001,\n\n\t/*\n\t** SFC_SET_ADD_* values are deprecated and will disappear at some\n\t** time in the future. They are guaranteed to be here up to and\n\t** including version 1.0.8 to avoid breakage of existing software.\n\t** They currently do nothing and will continue to do nothing.\n\t*/\n\tSFC_SET_ADD_DITHER_ON_WRITE\t\t= 0x1070,\n\tSFC_SET_ADD_DITHER_ON_READ\t\t= 0x1071\n} ;\n\n\n/*\n** String types that can be set and read from files. Not all file types\n** support this and even the file types which support one, may not support\n** all string types.\n*/\n\nenum\n{\tSF_STR_TITLE\t\t\t\t\t= 0x01,\n\tSF_STR_COPYRIGHT\t\t\t\t= 0x02,\n\tSF_STR_SOFTWARE\t\t\t\t\t= 0x03,\n\tSF_STR_ARTIST\t\t\t\t\t= 0x04,\n\tSF_STR_COMMENT\t\t\t\t\t= 0x05,\n\tSF_STR_DATE\t\t\t\t\t\t= 0x06,\n\tSF_STR_ALBUM\t\t\t\t\t= 0x07,\n\tSF_STR_LICENSE\t\t\t\t\t= 0x08,\n\tSF_STR_TRACKNUMBER\t\t\t\t= 0x09,\n\tSF_STR_GENRE\t\t\t\t\t= 0x10\n} ;\n\n/*\n** Use the following as the start and end index when doing metadata\n** transcoding.\n*/\n\n#define\tSF_STR_FIRST\tSF_STR_TITLE\n#define\tSF_STR_LAST\t\tSF_STR_GENRE\n\nenum\n{\t/* True and false */\n\tSF_FALSE\t= 0,\n\tSF_TRUE\t\t= 1,\n\n\t/* Modes for opening files. */\n\tSFM_READ\t= 0x10,\n\tSFM_WRITE\t= 0x20,\n\tSFM_RDWR\t= 0x30,\n\n\tSF_AMBISONIC_NONE\t\t= 0x40,\n\tSF_AMBISONIC_B_FORMAT\t= 0x41\n} ;\n\n/* Public error values. These are guaranteed to remain unchanged for the duration\n** of the library major version number.\n** There are also a large number of private error numbers which are internal to\n** the library which can change at any time.\n*/\n\nenum\n{\tSF_ERR_NO_ERROR\t\t\t\t= 0,\n\tSF_ERR_UNRECOGNISED_FORMAT\t= 1,\n\tSF_ERR_SYSTEM\t\t\t\t= 2,\n\tSF_ERR_MALFORMED_FILE\t\t= 3,\n\tSF_ERR_UNSUPPORTED_ENCODING\t= 4\n} ;\n\n\n/* Channel map values (used with SFC_SET/GET_CHANNEL_MAP).\n*/\n\nenum\n{\tSF_CHANNEL_MAP_INVALID = 0,\n\tSF_CHANNEL_MAP_MONO = 1,\n\tSF_CHANNEL_MAP_LEFT,\t\t\t\t\t/* Apple calls this 'Left' */\n\tSF_CHANNEL_MAP_RIGHT,\t\t\t\t\t/* Apple calls this 'Right' */\n\tSF_CHANNEL_MAP_CENTER,\t\t\t\t\t/* Apple calls this 'Center' */\n\tSF_CHANNEL_MAP_FRONT_LEFT,\n\tSF_CHANNEL_MAP_FRONT_RIGHT,\n\tSF_CHANNEL_MAP_FRONT_CENTER,\n\tSF_CHANNEL_MAP_REAR_CENTER,\t\t\t\t/* Apple calls this 'Center Surround', Msft calls this 'Back Center' */\n\tSF_CHANNEL_MAP_REAR_LEFT,\t\t\t\t/* Apple calls this 'Left Surround', Msft calls this 'Back Left' */\n\tSF_CHANNEL_MAP_REAR_RIGHT,\t\t\t\t/* Apple calls this 'Right Surround', Msft calls this 'Back Right' */\n\tSF_CHANNEL_MAP_LFE,\t\t\t\t\t\t/* Apple calls this 'LFEScreen', Msft calls this 'Low Frequency'  */\n\tSF_CHANNEL_MAP_FRONT_LEFT_OF_CENTER,\t/* Apple calls this 'Left Center' */\n\tSF_CHANNEL_MAP_FRONT_RIGHT_OF_CENTER,\t/* Apple calls this 'Right Center */\n\tSF_CHANNEL_MAP_SIDE_LEFT,\t\t\t\t/* Apple calls this 'Left Surround Direct' */\n\tSF_CHANNEL_MAP_SIDE_RIGHT,\t\t\t\t/* Apple calls this 'Right Surround Direct' */\n\tSF_CHANNEL_MAP_TOP_CENTER,\t\t\t\t/* Apple calls this 'Top Center Surround' */\n\tSF_CHANNEL_MAP_TOP_FRONT_LEFT,\t\t\t/* Apple calls this 'Vertical Height Left' */\n\tSF_CHANNEL_MAP_TOP_FRONT_RIGHT,\t\t\t/* Apple calls this 'Vertical Height Right' */\n\tSF_CHANNEL_MAP_TOP_FRONT_CENTER,\t\t/* Apple calls this 'Vertical Height Center' */\n\tSF_CHANNEL_MAP_TOP_REAR_LEFT,\t\t\t/* Apple and MS call this 'Top Back Left' */\n\tSF_CHANNEL_MAP_TOP_REAR_RIGHT,\t\t\t/* Apple and MS call this 'Top Back Right' */\n\tSF_CHANNEL_MAP_TOP_REAR_CENTER,\t\t\t/* Apple and MS call this 'Top Back Center' */\n\n\tSF_CHANNEL_MAP_AMBISONIC_B_W,\n\tSF_CHANNEL_MAP_AMBISONIC_B_X,\n\tSF_CHANNEL_MAP_AMBISONIC_B_Y,\n\tSF_CHANNEL_MAP_AMBISONIC_B_Z,\n\n\tSF_CHANNEL_MAP_MAX\n} ;\n\n\n/* A SNDFILE* pointer can be passed around much like stdio.h's FILE* pointer. */\n\ntypedef\tstruct SNDFILE_tag\tSNDFILE ;\n\n/* The following typedef is system specific and is defined when libsndfile is\n** compiled. sf_count_t will be a 64 bit value when the underlying OS allows\n** 64 bit file offsets.\n** On windows, we need to allow the same header file to be compiler by both GCC\n** and the Microsoft compiler.\n*/\n\n#if (defined (_MSCVER) || defined (_MSC_VER) && (_MSC_VER < 1310))\ntypedef __int64\t\tsf_count_t ;\n#define SF_COUNT_MAX\t\t0x7fffffffffffffffi64\n#else\ntypedef __int64\tsf_count_t ;\n#define SF_COUNT_MAX\t\t0x7FFFFFFFFFFFFFFFLL\n#endif\n\n\n/* A pointer to a SF_INFO structure is passed to sf_open () and filled in.\n** On write, the SF_INFO structure is filled in by the user and passed into\n** sf_open ().\n*/\n\nstruct SF_INFO\n{\tsf_count_t\tframes ;\t\t/* Used to be called samples.  Changed to avoid confusion. */\n\tint\t\t\tsamplerate ;\n\tint\t\t\tchannels ;\n\tint\t\t\tformat ;\n\tint\t\t\tsections ;\n\tint\t\t\tseekable ;\n} ;\n\ntypedef\tstruct SF_INFO SF_INFO ;\n\n/* The SF_FORMAT_INFO struct is used to retrieve information about the sound\n** file formats libsndfile supports using the sf_command () interface.\n**\n** Using this interface will allow applications to support new file formats\n** and encoding types when libsndfile is upgraded, without requiring\n** re-compilation of the application.\n**\n** Please consult the libsndfile documentation (particularly the information\n** on the sf_command () interface) for examples of its use.\n*/\n\ntypedef struct\n{\tint\t\t\tformat ;\n\tconst char\t*name ;\n\tconst char\t*extension ;\n} SF_FORMAT_INFO ;\n\n/*\n** Enums and typedefs for adding dither on read and write.\n** See the html documentation for sf_command(), SFC_SET_DITHER_ON_WRITE\n** and SFC_SET_DITHER_ON_READ.\n*/\n\nenum\n{\tSFD_DEFAULT_LEVEL\t= 0,\n\tSFD_CUSTOM_LEVEL\t= 0x40000000,\n\n\tSFD_NO_DITHER\t\t= 500,\n\tSFD_WHITE\t\t\t= 501,\n\tSFD_TRIANGULAR_PDF\t= 502\n} ;\n\ntypedef struct\n{\tint\t\t\ttype ;\n\tdouble\t\tlevel ;\n\tconst char\t*name ;\n} SF_DITHER_INFO ;\n\n/* Struct used to retrieve information about a file embedded within a\n** larger file. See SFC_GET_EMBED_FILE_INFO.\n*/\n\ntypedef struct\n{\tsf_count_t\toffset ;\n\tsf_count_t\tlength ;\n} SF_EMBED_FILE_INFO ;\n\n/*\n**\tStruct used to retrieve cue marker information from a file\n*/\n\ntypedef struct\n{\tint32_t \tindx ;\n\tuint32_t \tposition ;\n\tint32_t \tfcc_chunk ;\n\tint32_t \tchunk_start ;\n\tint32_t\t\tblock_start ;\n\tuint32_t \tsample_offset ;\n\tchar name [256] ;\n} SF_CUE_POINT ;\n\n#define\tSF_CUES_VAR(count) \\\n\tstruct \\\n\t{\tuint32_t cue_count ; \\\n\t\tSF_CUE_POINT cue_points [count] ; \\\n\t}\n\ntypedef SF_CUES_VAR (100) SF_CUES ;\n\n/*\n**\tStructs used to retrieve music sample information from a file.\n*/\n\nenum\n{\t/*\n\t**\tThe loop mode field in SF_INSTRUMENT will be one of the following.\n\t*/\n\tSF_LOOP_NONE = 800,\n\tSF_LOOP_FORWARD,\n\tSF_LOOP_BACKWARD,\n\tSF_LOOP_ALTERNATING\n} ;\n\ntypedef struct\n{\tint gain ;\n\tchar basenote, detune ;\n\tchar velocity_lo, velocity_hi ;\n\tchar key_lo, key_hi ;\n\tint loop_count ;\n\n\tstruct\n\t{\tint mode ;\n\t\tuint32_t start ;\n\t\tuint32_t end ;\n\t\tuint32_t count ;\n\t} loops [16] ; /* make variable in a sensible way */\n} SF_INSTRUMENT ;\n\n\n\n/* Struct used to retrieve loop information from a file.*/\ntypedef struct\n{\n\tshort\ttime_sig_num ;\t/* any positive integer    > 0  */\n\tshort\ttime_sig_den ;\t/* any positive power of 2 > 0  */\n\tint\t\tloop_mode ;\t\t/* see SF_LOOP enum             */\n\n\tint\t\tnum_beats ;\t\t/* this is NOT the amount of quarter notes !!!*/\n\t\t\t\t\t\t\t/* a full bar of 4/4 is 4 beats */\n\t\t\t\t\t\t\t/* a full bar of 7/8 is 7 beats */\n\n\tfloat\tbpm ;\t\t\t/* suggestion, as it can be calculated using other fields:*/\n\t\t\t\t\t\t\t/* file's length, file's sampleRate and our time_sig_den*/\n\t\t\t\t\t\t\t/* -> bpms are always the amount of _quarter notes_ per minute */\n\n\tint\troot_key ;\t\t\t/* MIDI note, or -1 for None */\n\tint future [6] ;\n} SF_LOOP_INFO ;\n\n\n/*\tStruct used to retrieve broadcast (EBU) information from a file.\n**\tStrongly (!) based on EBU \"bext\" chunk format used in Broadcast WAVE.\n*/\n#define\tSF_BROADCAST_INFO_VAR(coding_hist_size) \\\n\t\t\tstruct \\\n\t\t\t{\tchar\t\tdescription [256] ; \\\n\t\t\t\tchar\t\toriginator [32] ; \\\n\t\t\t\tchar\t\toriginator_reference [32] ; \\\n\t\t\t\tchar\t\torigination_date [10] ; \\\n\t\t\t\tchar\t\torigination_time [8] ; \\\n\t\t\t\tuint32_t\ttime_reference_low ; \\\n\t\t\t\tuint32_t\ttime_reference_high ; \\\n\t\t\t\tshort\t\tversion ; \\\n\t\t\t\tchar\t\tumid [64] ; \\\n\t\t\t\tchar\t\treserved [190] ; \\\n\t\t\t\tuint32_t\tcoding_history_size ; \\\n\t\t\t\tchar\t\tcoding_history [coding_hist_size] ; \\\n\t\t\t}\n\n/* SF_BROADCAST_INFO is the above struct with coding_history field of 256 bytes. */\ntypedef SF_BROADCAST_INFO_VAR (256) SF_BROADCAST_INFO ;\n\nstruct SF_CART_TIMER\n{\tchar\tusage [4] ;\n\tint32_t\tvalue ;\n} ;\n\ntypedef struct SF_CART_TIMER SF_CART_TIMER ;\n\n#define\tSF_CART_INFO_VAR(p_tag_text_size) \\\n\t\t\tstruct \\\n\t\t\t{\tchar\t\tversion [4] ; \\\n\t\t\t\tchar\t\ttitle [64] ; \\\n\t\t\t\tchar\t\tartist [64] ; \\\n\t\t\t\tchar\t\tcut_id [64] ; \\\n\t\t\t\tchar\t\tclient_id [64] ; \\\n\t\t\t\tchar\t\tcategory [64] ; \\\n\t\t\t\tchar\t\tclassification [64] ; \\\n\t\t\t\tchar\t\tout_cue [64] ; \\\n\t\t\t\tchar\t\tstart_date [10] ; \\\n\t\t\t\tchar\t\tstart_time [8] ; \\\n\t\t\t\tchar\t\tend_date [10] ; \\\n\t\t\t\tchar\t\tend_time [8] ; \\\n\t\t\t\tchar\t\tproducer_app_id [64] ; \\\n\t\t\t\tchar\t\tproducer_app_version [64] ; \\\n\t\t\t\tchar\t\tuser_def [64] ; \\\n\t\t\t\tint32_t\t\tlevel_reference ; \\\n\t\t\t\tSF_CART_TIMER\tpost_timers [8] ; \\\n\t\t\t\tchar\t\treserved [276] ; \\\n\t\t\t\tchar\t\turl [1024] ; \\\n\t\t\t\tuint32_t\ttag_text_size ; \\\n\t\t\t\tchar\t\ttag_text [p_tag_text_size] ; \\\n\t\t\t}\n\ntypedef SF_CART_INFO_VAR (256) SF_CART_INFO ;\n\n/*\tVirtual I/O functionality. */\n\ntypedef sf_count_t\t\t(*sf_vio_get_filelen)\t(void *user_data) ;\ntypedef sf_count_t\t\t(*sf_vio_seek)\t\t(sf_count_t offset, int whence, void *user_data) ;\ntypedef sf_count_t\t\t(*sf_vio_read)\t\t(void *ptr, sf_count_t count, void *user_data) ;\ntypedef sf_count_t\t\t(*sf_vio_write)\t\t(const void *ptr, sf_count_t count, void *user_data) ;\ntypedef sf_count_t\t\t(*sf_vio_tell)\t\t(void *user_data) ;\n\nstruct SF_VIRTUAL_IO\n{\tsf_vio_get_filelen\tget_filelen ;\n\tsf_vio_seek\t\t\tseek ;\n\tsf_vio_read\t\t\tread ;\n\tsf_vio_write\t\twrite ;\n\tsf_vio_tell\t\t\ttell ;\n} ;\n\ntypedef\tstruct SF_VIRTUAL_IO SF_VIRTUAL_IO ;\n\n\n/* Open the specified file for read, write or both. On error, this will\n** return a NULL pointer. To find the error number, pass a NULL SNDFILE\n** to sf_strerror ().\n** All calls to sf_open() should be matched with a call to sf_close().\n*/\n\nSNDFILE* \tsf_open\t\t(const char *path, int mode, SF_INFO *sfinfo) ;\n\n\n/* Use the existing file descriptor to create a SNDFILE object. If close_desc\n** is TRUE, the file descriptor will be closed when sf_close() is called. If\n** it is FALSE, the descriptor will not be closed.\n** When passed a descriptor like this, the library will assume that the start\n** of file header is at the current file offset. This allows sound files within\n** larger container files to be read and/or written.\n** On error, this will return a NULL pointer. To find the error number, pass a\n** NULL SNDFILE to sf_strerror ().\n** All calls to sf_open_fd() should be matched with a call to sf_close().\n\n*/\n\nSNDFILE* \tsf_open_fd\t(int fd, int mode, SF_INFO *sfinfo, int close_desc) ;\n\nSNDFILE* \tsf_open_virtual\t(SF_VIRTUAL_IO *sfvirtual, int mode, SF_INFO *sfinfo, void *user_data) ;\n\n\n/* sf_error () returns a error number which can be translated to a text\n** string using sf_error_number().\n*/\n\nint\t\tsf_error\t\t(SNDFILE *sndfile) ;\n\n\n/* sf_strerror () returns to the caller a pointer to the current error message for\n** the given SNDFILE.\n*/\n\nconst char* sf_strerror (SNDFILE *sndfile) ;\n\n\n/* sf_error_number () allows the retrieval of the error string for each internal\n** error number.\n**\n*/\n\nconst char*\tsf_error_number\t(int errnum) ;\n\n\n/* The following two error functions are deprecated but they will remain in the\n** library for the foreseeable future. The function sf_strerror() should be used\n** in their place.\n*/\n\nint\t\tsf_perror\t\t(SNDFILE *sndfile) ;\nint\t\tsf_error_str\t(SNDFILE *sndfile, char* str, size_t len) ;\n\n\n/* Return TRUE if fields of the SF_INFO struct are a valid combination of values. */\n\nint\t\tsf_command\t(SNDFILE *sndfile, int command, void *data, int datasize) ;\n\n\n/* Return TRUE if fields of the SF_INFO struct are a valid combination of values. */\n\nint\t\tsf_format_check\t(const SF_INFO *info) ;\n\n\n/* Seek within the waveform data chunk of the SNDFILE. sf_seek () uses\n** the same values for whence (SEEK_SET, SEEK_CUR and SEEK_END) as\n** stdio.h function fseek ().\n** An offset of zero with whence set to SEEK_SET will position the\n** read / write pointer to the first data sample.\n** On success sf_seek returns the current position in (multi-channel)\n** samples from the start of the file.\n** Please see the libsndfile documentation for moving the read pointer\n** separately from the write pointer on files open in mode SFM_RDWR.\n** On error all of these functions return -1.\n*/\n\nenum\n{\tSF_SEEK_SET = SEEK_SET,\n\tSF_SEEK_CUR = SEEK_CUR,\n\tSF_SEEK_END = SEEK_END\n} ;\n\nsf_count_t\tsf_seek \t\t(SNDFILE *sndfile, sf_count_t frames, int whence) ;\n\n\n/* Functions for retrieving and setting string data within sound files.\n** Not all file types support this features; AIFF and WAV do. For both\n** functions, the str_type parameter must be one of the SF_STR_* values\n** defined above.\n** On error, sf_set_string() returns non-zero while sf_get_string()\n** returns NULL.\n*/\n\nint sf_set_string (SNDFILE *sndfile, int str_type, const char* str) ;\n\nconst char* sf_get_string (SNDFILE *sndfile, int str_type) ;\n\n\n/* Return the library version string. */\n\nconst char * sf_version_string (void) ;\n\n/* Return the current byterate at this point in the file. The byte rate in this\n** case is the number of bytes per second of audio data. For instance, for a\n** stereo, 18 bit PCM encoded file with an 16kHz sample rate, the byte rate\n** would be 2 (stereo) * 2 (two bytes per sample) * 16000 => 64000 bytes/sec.\n** For some file formats the returned value will be accurate and exact, for some\n** it will be a close approximation, for some it will be the average bitrate for\n** the whole file and for some it will be a time varying value that was accurate\n** when the file was most recently read or written.\n** To get the bitrate, multiple this value by 8.\n** Returns -1 for unknown.\n*/\nint sf_current_byterate (SNDFILE *sndfile) ;\n\n/* Functions for reading/writing the waveform data of a sound file.\n*/\n\nsf_count_t\tsf_read_raw\t\t(SNDFILE *sndfile, void *ptr, sf_count_t bytes) ;\nsf_count_t\tsf_write_raw \t(SNDFILE *sndfile, const void *ptr, sf_count_t bytes) ;\n\n\n/* Functions for reading and writing the data chunk in terms of frames.\n** The number of items actually read/written = frames * number of channels.\n**     sf_xxxx_raw\t\tread/writes the raw data bytes from/to the file\n**     sf_xxxx_short\tpasses data in the native short format\n**     sf_xxxx_int\t\tpasses data in the native int format\n**     sf_xxxx_float\tpasses data in the native float format\n**     sf_xxxx_double\tpasses data in the native double format\n** All of these read/write function return number of frames read/written.\n*/\n\nsf_count_t\tsf_readf_short\t(SNDFILE *sndfile, short *ptr, sf_count_t frames) ;\nsf_count_t\tsf_writef_short\t(SNDFILE *sndfile, const short *ptr, sf_count_t frames) ;\n\nsf_count_t\tsf_readf_int\t(SNDFILE *sndfile, int *ptr, sf_count_t frames) ;\nsf_count_t\tsf_writef_int \t(SNDFILE *sndfile, const int *ptr, sf_count_t frames) ;\n\nsf_count_t\tsf_readf_float\t(SNDFILE *sndfile, float *ptr, sf_count_t frames) ;\nsf_count_t\tsf_writef_float\t(SNDFILE *sndfile, const float *ptr, sf_count_t frames) ;\n\nsf_count_t\tsf_readf_double\t\t(SNDFILE *sndfile, double *ptr, sf_count_t frames) ;\nsf_count_t\tsf_writef_double\t(SNDFILE *sndfile, const double *ptr, sf_count_t frames) ;\n\n\n/* Functions for reading and writing the data chunk in terms of items.\n** Otherwise similar to above.\n** All of these read/write function return number of items read/written.\n*/\n\nsf_count_t\tsf_read_short\t(SNDFILE *sndfile, short *ptr, sf_count_t items) ;\nsf_count_t\tsf_write_short\t(SNDFILE *sndfile, const short *ptr, sf_count_t items) ;\n\nsf_count_t\tsf_read_int\t\t(SNDFILE *sndfile, int *ptr, sf_count_t items) ;\nsf_count_t\tsf_write_int \t(SNDFILE *sndfile, const int *ptr, sf_count_t items) ;\n\nsf_count_t\tsf_read_float\t(SNDFILE *sndfile, float *ptr, sf_count_t items) ;\nsf_count_t\tsf_write_float\t(SNDFILE *sndfile, const float *ptr, sf_count_t items) ;\n\nsf_count_t\tsf_read_double\t(SNDFILE *sndfile, double *ptr, sf_count_t items) ;\nsf_count_t\tsf_write_double\t(SNDFILE *sndfile, const double *ptr, sf_count_t items) ;\n\n\n/* Close the SNDFILE and clean up all memory allocations associated with this\n** file.\n** Returns 0 on success, or an error number.\n*/\n\nint\t\tsf_close\t\t(SNDFILE *sndfile) ;\n\n\n/* If the file is opened SFM_WRITE or SFM_RDWR, call fsync() on the file\n** to force the writing of data to disk. If the file is opened SFM_READ\n** no action is taken.\n*/\n\nvoid\tsf_write_sync\t(SNDFILE *sndfile) ;\n\n\n\n/* The function sf_wchar_open() is Windows Only!\n** Open a file passing in a Windows Unicode filename. Otherwise, this is\n** the same as sf_open().\n**\n** In order for this to work, you need to do the following:\n**\n**\t\t#include <windows.h>\n**\t\t#define ENABLE_SNDFILE_WINDOWS_PROTOTYPES 1\n**\t\t#including <sndfile.h>\n*/\n\n#if (defined (ENABLE_SNDFILE_WINDOWS_PROTOTYPES) && ENABLE_SNDFILE_WINDOWS_PROTOTYPES)\nSNDFILE* sf_wchar_open (LPCWSTR wpath, int mode, SF_INFO *sfinfo) ;\n#endif\n\n\n\n\n/* Getting and setting of chunks from within a sound file.\n**\n** These functions allow the getting and setting of chunks within a sound file\n** (for those formats which allow it).\n**\n** These functions fail safely. Specifically, they will not allow you to overwrite\n** existing chunks or add extra versions of format specific reserved chunks but\n** should allow you to retrieve any and all chunks (may not be implemented for\n** all chunks or all file formats).\n*/\n\nstruct SF_CHUNK_INFO\n{\tchar\t\tid [64] ;\t/* The chunk identifier. */\n\tunsigned\tid_size ;\t/* The size of the chunk identifier. */\n\tunsigned\tdatalen ;\t/* The size of that data. */\n\tvoid\t\t*data ;\t\t/* Pointer to the data. */\n} ;\n\ntypedef struct SF_CHUNK_INFO SF_CHUNK_INFO ;\n\n/* Set the specified chunk info (must be done before any audio data is written\n** to the file). This will fail for format specific reserved chunks.\n** The chunk_info->data pointer must be valid until the file is closed.\n** Returns SF_ERR_NO_ERROR on success or non-zero on failure.\n*/\nint sf_set_chunk (SNDFILE * sndfile, const SF_CHUNK_INFO * chunk_info) ;\n\n/*\n** An opaque structure to an iterator over the all chunks of a given id\n*/\ntypedef\tstruct SF_CHUNK_ITERATOR SF_CHUNK_ITERATOR ;\n\n/* Get an iterator for all chunks matching chunk_info.\n** The iterator will point to the first chunk matching chunk_info.\n** Chunks are matching, if (chunk_info->id) matches the first\n**     (chunk_info->id_size) bytes of a chunk found in the SNDFILE* handle.\n** If chunk_info is NULL, an iterator to all chunks in the SNDFILE* handle\n**     is returned.\n** The values of chunk_info->datalen and chunk_info->data are ignored.\n** If no matching chunks are found in the sndfile, NULL is returned.\n** The returned iterator will stay valid until one of the following occurs:\n**     a) The sndfile is closed.\n**     b) A new chunk is added using sf_set_chunk().\n**     c) Another chunk iterator function is called on the same SNDFILE* handle\n**        that causes the iterator to be modified.\n** The memory for the iterator belongs to the SNDFILE* handle and is freed when\n** sf_close() is called.\n*/\nSF_CHUNK_ITERATOR *\nsf_get_chunk_iterator (SNDFILE * sndfile, const SF_CHUNK_INFO * chunk_info) ;\n\n/* Iterate through chunks by incrementing the iterator.\n** Increments the iterator and returns a handle to the new one.\n** After this call, iterator will no longer be valid, and you must use the\n**      newly returned handle from now on.\n** The returned handle can be used to access the next chunk matching\n**      the criteria as defined in sf_get_chunk_iterator().\n** If iterator points to the last chunk, this will free all resources\n**      associated with iterator and return NULL.\n** The returned iterator will stay valid until sf_get_chunk_iterator_next\n**      is called again, the sndfile is closed or a new chunk us added.\n*/\nSF_CHUNK_ITERATOR *\nsf_next_chunk_iterator (SF_CHUNK_ITERATOR * iterator) ;\n\n\n/* Get the size of the specified chunk.\n** If the specified chunk exists, the size will be returned in the\n**      datalen field of the SF_CHUNK_INFO struct.\n**      Additionally, the id of the chunk will be copied to the id\n**      field of the SF_CHUNK_INFO struct and it's id_size field will\n**      be updated accordingly.\n** If the chunk doesn't exist chunk_info->datalen will be zero, and the\n**      id and id_size fields will be undefined.\n** The function will return SF_ERR_NO_ERROR on success or non-zero on\n** failure.\n*/\nint\nsf_get_chunk_size (const SF_CHUNK_ITERATOR * it, SF_CHUNK_INFO * chunk_info) ;\n\n/* Get the specified chunk data.\n** If the specified chunk exists, up to chunk_info->datalen bytes of\n**      the chunk data will be copied into the chunk_info->data buffer\n**      (allocated by the caller) and the chunk_info->datalen field\n**      updated to reflect the size of the data. The id and id_size\n**      field will be updated according to the retrieved chunk\n** If the chunk doesn't exist chunk_info->datalen will be zero, and the\n**      id and id_size fields will be undefined.\n** The function will return SF_ERR_NO_ERROR on success or non-zero on\n** failure.\n*/\nint\nsf_get_chunk_data (const SF_CHUNK_ITERATOR * it, SF_CHUNK_INFO * chunk_info) ;\n\n\n#ifdef __cplusplus\n}\t\t/* extern \"C\" */\n#endif\t/* __cplusplus */\n\n#endif\t/* SNDFILE_H */\n\n"
  },
  {
    "path": "vendor/libsndfile/include/sndfile.hh",
    "content": "/*\n** Copyright (C) 2005-2012 Erik de Castro Lopo <erikd@mega-nerd.com>\n**\n** All rights reserved.\n**\n** Redistribution and use in source and binary forms, with or without\n** modification, are permitted provided that the following conditions are\n** met:\n**\n**     * Redistributions of source code must retain the above copyright\n**       notice, this list of conditions and the following disclaimer.\n**     * Redistributions in binary form must reproduce the above copyright\n**       notice, this list of conditions and the following disclaimer in\n**       the documentation and/or other materials provided with the\n**       distribution.\n**     * Neither the author nor the names of any contributors may be used\n**       to endorse or promote products derived from this software without\n**       specific prior written permission.\n**\n** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n** \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED\n** TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n** EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;\n** OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\n** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR\n** OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF\n** ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n/*\n** The above modified BSD style license (GPL and LGPL compatible) applies to\n** this file. It does not apply to libsndfile itself which is released under\n** the GNU LGPL or the libsndfile test suite which is released under the GNU\n** GPL.\n** This means that this header file can be used under this modified BSD style\n** license, but the LGPL still holds for the libsndfile library itself.\n*/\n\n/*\n** sndfile.hh -- A lightweight C++ wrapper for the libsndfile API.\n**\n** All the methods are inlines and all functionality is contained in this\n** file. There is no separate implementation file.\n**\n** API documentation is in the doc/ directory of the source code tarball\n** and at http://www.mega-nerd.com/libsndfile/api.html.\n*/\n\n#ifndef SNDFILE_HH\n#define SNDFILE_HH\n\n#include <sndfile.h>\n\n#include <string>\n#include <new> // for std::nothrow\n\nclass SndfileHandle\n{\tprivate :\n\t\tstruct SNDFILE_ref\n\t\t{\tSNDFILE_ref (void) ;\n\t\t\t~SNDFILE_ref (void) ;\n\n\t\t\tSNDFILE *sf ;\n\t\t\tSF_INFO sfinfo ;\n\t\t\tint ref ;\n\t\t\t} ;\n\n\t\tSNDFILE_ref *p ;\n\n\tpublic :\n\t\t\t/* Default constructor */\n\t\t\tSndfileHandle (void) : p (NULL) {} ;\n\t\t\tSndfileHandle (const char *path, int mode = SFM_READ,\n\t\t\t\t\t\t\tint format = 0, int channels = 0, int samplerate = 0) ;\n\t\t\tSndfileHandle (std::string const & path, int mode = SFM_READ,\n\t\t\t\t\t\t\tint format = 0, int channels = 0, int samplerate = 0) ;\n\t\t\tSndfileHandle (int fd, bool close_desc, int mode = SFM_READ,\n\t\t\t\t\t\t\tint format = 0, int channels = 0, int samplerate = 0) ;\n\t\t\tSndfileHandle (SF_VIRTUAL_IO &sfvirtual, void *user_data, int mode = SFM_READ,\n\t\t\t\t\t\t\tint format = 0, int channels = 0, int samplerate = 0) ;\n\n#ifdef ENABLE_SNDFILE_WINDOWS_PROTOTYPES\n\t\t\tSndfileHandle (LPCWSTR wpath, int mode = SFM_READ,\n\t\t\t\t\t\t\tint format = 0, int channels = 0, int samplerate = 0) ;\n#endif\n\n\t\t\t~SndfileHandle (void) ;\n\n\t\t\tSndfileHandle (const SndfileHandle &orig) ;\n\t\t\tSndfileHandle & operator = (const SndfileHandle &rhs) ;\n\n\t\t/* Mainly for debugging/testing. */\n\t\tint refCount (void) const { return (p == NULL) ? 0 : p->ref ; }\n\n\t\toperator bool () const { return (p != NULL) ; }\n\n\t\tbool operator == (const SndfileHandle &rhs) const { return (p == rhs.p) ; }\n\n\t\tsf_count_t\tframes (void) const\t\t{ return p ? p->sfinfo.frames : 0 ; }\n\t\tint\t\t\tformat (void) const\t\t{ return p ? p->sfinfo.format : 0 ; }\n\t\tint\t\t\tchannels (void) const\t{ return p ? p->sfinfo.channels : 0 ; }\n\t\tint\t\t\tsamplerate (void) const { return p ? p->sfinfo.samplerate : 0 ; }\n\n\t\tint error (void) const ;\n\t\tconst char * strError (void) const ;\n\n\t\tint command (int cmd, void *data, int datasize) ;\n\n\t\tsf_count_t\tseek (sf_count_t frames, int whence) ;\n\n\t\tvoid writeSync (void) ;\n\n\t\tint setString (int str_type, const char* str) ;\n\n\t\tconst char* getString (int str_type) const ;\n\n\t\tstatic int formatCheck (int format, int channels, int samplerate) ;\n\n\t\tsf_count_t read (short *ptr, sf_count_t items) ;\n\t\tsf_count_t read (int *ptr, sf_count_t items) ;\n\t\tsf_count_t read (float *ptr, sf_count_t items) ;\n\t\tsf_count_t read (double *ptr, sf_count_t items) ;\n\n\t\tsf_count_t write (const short *ptr, sf_count_t items) ;\n\t\tsf_count_t write (const int *ptr, sf_count_t items) ;\n\t\tsf_count_t write (const float *ptr, sf_count_t items) ;\n\t\tsf_count_t write (const double *ptr, sf_count_t items) ;\n\n\t\tsf_count_t readf (short *ptr, sf_count_t frames) ;\n\t\tsf_count_t readf (int *ptr, sf_count_t frames) ;\n\t\tsf_count_t readf (float *ptr, sf_count_t frames) ;\n\t\tsf_count_t readf (double *ptr, sf_count_t frames) ;\n\n\t\tsf_count_t writef (const short *ptr, sf_count_t frames) ;\n\t\tsf_count_t writef (const int *ptr, sf_count_t frames) ;\n\t\tsf_count_t writef (const float *ptr, sf_count_t frames) ;\n\t\tsf_count_t writef (const double *ptr, sf_count_t frames) ;\n\n\t\tsf_count_t\treadRaw\t\t(void *ptr, sf_count_t bytes) ;\n\t\tsf_count_t\twriteRaw\t(const void *ptr, sf_count_t bytes) ;\n\n\t\t/**< Raw access to the handle. SndfileHandle keeps ownership. */\n\t\tSNDFILE * rawHandle (void) ;\n\n\t\t/**< Take ownership of handle, if reference count is 1. */\n\t\tSNDFILE * takeOwnership (void) ;\n} ;\n\n/*==============================================================================\n**\tNothing but implementation below.\n*/\n\ninline\nSndfileHandle::SNDFILE_ref::SNDFILE_ref (void)\n: sf (NULL), sfinfo (), ref (1)\n{}\n\ninline\nSndfileHandle::SNDFILE_ref::~SNDFILE_ref (void)\n{\tif (sf != NULL) sf_close (sf) ; }\n\ninline\nSndfileHandle::SndfileHandle (const char *path, int mode, int fmt, int chans, int srate)\n: p (NULL)\n{\n\tp = new (std::nothrow) SNDFILE_ref () ;\n\n\tif (p != NULL)\n\t{\tp->ref = 1 ;\n\n\t\tp->sfinfo.frames = 0 ;\n\t\tp->sfinfo.channels = chans ;\n\t\tp->sfinfo.format = fmt ;\n\t\tp->sfinfo.samplerate = srate ;\n\t\tp->sfinfo.sections = 0 ;\n\t\tp->sfinfo.seekable = 0 ;\n\n\t\tp->sf = sf_open (path, mode, &p->sfinfo) ;\n\t\t} ;\n\n\treturn ;\n} /* SndfileHandle const char * constructor */\n\ninline\nSndfileHandle::SndfileHandle (std::string const & path, int mode, int fmt, int chans, int srate)\n: p (NULL)\n{\n\tp = new (std::nothrow) SNDFILE_ref () ;\n\n\tif (p != NULL)\n\t{\tp->ref = 1 ;\n\n\t\tp->sfinfo.frames = 0 ;\n\t\tp->sfinfo.channels = chans ;\n\t\tp->sfinfo.format = fmt ;\n\t\tp->sfinfo.samplerate = srate ;\n\t\tp->sfinfo.sections = 0 ;\n\t\tp->sfinfo.seekable = 0 ;\n\n\t\tp->sf = sf_open (path.c_str (), mode, &p->sfinfo) ;\n\t\t} ;\n\n\treturn ;\n} /* SndfileHandle std::string constructor */\n\ninline\nSndfileHandle::SndfileHandle (int fd, bool close_desc, int mode, int fmt, int chans, int srate)\n: p (NULL)\n{\n\tif (fd < 0)\n\t\treturn ;\n\n\tp = new (std::nothrow) SNDFILE_ref () ;\n\n\tif (p != NULL)\n\t{\tp->ref = 1 ;\n\n\t\tp->sfinfo.frames = 0 ;\n\t\tp->sfinfo.channels = chans ;\n\t\tp->sfinfo.format = fmt ;\n\t\tp->sfinfo.samplerate = srate ;\n\t\tp->sfinfo.sections = 0 ;\n\t\tp->sfinfo.seekable = 0 ;\n\n\t\tp->sf = sf_open_fd (fd, mode, &p->sfinfo, close_desc) ;\n\t\t} ;\n\n\treturn ;\n} /* SndfileHandle fd constructor */\n\ninline\nSndfileHandle::SndfileHandle (SF_VIRTUAL_IO &sfvirtual, void *user_data, int mode, int fmt, int chans, int srate)\n: p (NULL)\n{\n\tp = new (std::nothrow) SNDFILE_ref () ;\n\n\tif (p != NULL)\n\t{\tp->ref = 1 ;\n\n\t\tp->sfinfo.frames = 0 ;\n\t\tp->sfinfo.channels = chans ;\n\t\tp->sfinfo.format = fmt ;\n\t\tp->sfinfo.samplerate = srate ;\n\t\tp->sfinfo.sections = 0 ;\n\t\tp->sfinfo.seekable = 0 ;\n\n\t\tp->sf = sf_open_virtual (&sfvirtual, mode, &p->sfinfo, user_data) ;\n\t\t} ;\n\n\treturn ;\n} /* SndfileHandle std::string constructor */\n\ninline\nSndfileHandle::~SndfileHandle (void)\n{\tif (p != NULL && --p->ref == 0)\n\t\tdelete p ;\n} /* SndfileHandle destructor */\n\n\ninline\nSndfileHandle::SndfileHandle (const SndfileHandle &orig)\n: p (orig.p)\n{\tif (p != NULL)\n\t\t++p->ref ;\n} /* SndfileHandle copy constructor */\n\ninline SndfileHandle &\nSndfileHandle::operator = (const SndfileHandle &rhs)\n{\n\tif (&rhs == this)\n\t\treturn *this ;\n\tif (p != NULL && --p->ref == 0)\n\t\tdelete p ;\n\n\tp = rhs.p ;\n\tif (p != NULL)\n\t\t++p->ref ;\n\n\treturn *this ;\n} /* SndfileHandle assignment operator */\n\ninline int\nSndfileHandle::error (void) const\n{\treturn sf_error (p->sf) ; }\n\ninline const char *\nSndfileHandle::strError (void) const\n{\treturn sf_strerror (p->sf) ; }\n\ninline int\nSndfileHandle::command (int cmd, void *data, int datasize)\n{\treturn sf_command (p->sf, cmd, data, datasize) ; }\n\ninline sf_count_t\nSndfileHandle::seek (sf_count_t frame_count, int whence)\n{\treturn sf_seek (p->sf, frame_count, whence) ; }\n\ninline void\nSndfileHandle::writeSync (void)\n{\tsf_write_sync (p->sf) ; }\n\ninline int\nSndfileHandle::setString (int str_type, const char* str)\n{\treturn sf_set_string (p->sf, str_type, str) ; }\n\ninline const char*\nSndfileHandle::getString (int str_type) const\n{\treturn sf_get_string (p->sf, str_type) ; }\n\ninline int\nSndfileHandle::formatCheck (int fmt, int chans, int srate)\n{\n\tSF_INFO sfinfo ;\n\n\tsfinfo.frames = 0 ;\n\tsfinfo.channels = chans ;\n\tsfinfo.format = fmt ;\n\tsfinfo.samplerate = srate ;\n\tsfinfo.sections = 0 ;\n\tsfinfo.seekable = 0 ;\n\n\treturn sf_format_check (&sfinfo) ;\n}\n\n/*---------------------------------------------------------------------*/\n\ninline sf_count_t\nSndfileHandle::read (short *ptr, sf_count_t items)\n{\treturn sf_read_short (p->sf, ptr, items) ; }\n\ninline sf_count_t\nSndfileHandle::read (int *ptr, sf_count_t items)\n{\treturn sf_read_int (p->sf, ptr, items) ; }\n\ninline sf_count_t\nSndfileHandle::read (float *ptr, sf_count_t items)\n{\treturn sf_read_float (p->sf, ptr, items) ; }\n\ninline sf_count_t\nSndfileHandle::read (double *ptr, sf_count_t items)\n{\treturn sf_read_double (p->sf, ptr, items) ; }\n\ninline sf_count_t\nSndfileHandle::write (const short *ptr, sf_count_t items)\n{\treturn sf_write_short (p->sf, ptr, items) ; }\n\ninline sf_count_t\nSndfileHandle::write (const int *ptr, sf_count_t items)\n{\treturn sf_write_int (p->sf, ptr, items) ; }\n\ninline sf_count_t\nSndfileHandle::write (const float *ptr, sf_count_t items)\n{\treturn sf_write_float (p->sf, ptr, items) ; }\n\ninline sf_count_t\nSndfileHandle::write (const double *ptr, sf_count_t items)\n{\treturn sf_write_double (p->sf, ptr, items) ; }\n\ninline sf_count_t\nSndfileHandle::readf (short *ptr, sf_count_t frame_count)\n{\treturn sf_readf_short (p->sf, ptr, frame_count) ; }\n\ninline sf_count_t\nSndfileHandle::readf (int *ptr, sf_count_t frame_count)\n{\treturn sf_readf_int (p->sf, ptr, frame_count) ; }\n\ninline sf_count_t\nSndfileHandle::readf (float *ptr, sf_count_t frame_count)\n{\treturn sf_readf_float (p->sf, ptr, frame_count) ; }\n\ninline sf_count_t\nSndfileHandle::readf (double *ptr, sf_count_t frame_count)\n{\treturn sf_readf_double (p->sf, ptr, frame_count) ; }\n\ninline sf_count_t\nSndfileHandle::writef (const short *ptr, sf_count_t frame_count)\n{\treturn sf_writef_short (p->sf, ptr, frame_count) ; }\n\ninline sf_count_t\nSndfileHandle::writef (const int *ptr, sf_count_t frame_count)\n{\treturn sf_writef_int (p->sf, ptr, frame_count) ; }\n\ninline sf_count_t\nSndfileHandle::writef (const float *ptr, sf_count_t frame_count)\n{\treturn sf_writef_float (p->sf, ptr, frame_count) ; }\n\ninline sf_count_t\nSndfileHandle::writef (const double *ptr, sf_count_t frame_count)\n{\treturn sf_writef_double (p->sf, ptr, frame_count) ; }\n\ninline sf_count_t\nSndfileHandle::readRaw (void *ptr, sf_count_t bytes)\n{\treturn sf_read_raw (p->sf, ptr, bytes) ; }\n\ninline sf_count_t\nSndfileHandle::writeRaw (const void *ptr, sf_count_t bytes)\n{\treturn sf_write_raw (p->sf, ptr, bytes) ; }\n\ninline SNDFILE *\nSndfileHandle::rawHandle (void)\n{\treturn (p ? p->sf : NULL) ; }\n\ninline SNDFILE *\nSndfileHandle::takeOwnership (void)\n{\n\tif (p == NULL || (p->ref != 1))\n\t\treturn NULL ;\n\n\tSNDFILE * sf = p->sf ;\n\tp->sf = NULL ;\n\tdelete p ;\n\tp = NULL ;\n\treturn sf ;\n}\n\n#ifdef ENABLE_SNDFILE_WINDOWS_PROTOTYPES\n\ninline\nSndfileHandle::SndfileHandle (LPCWSTR wpath, int mode, int fmt, int chans, int srate)\n: p (NULL)\n{\n\tp = new (std::nothrow) SNDFILE_ref () ;\n\n\tif (p != NULL)\n\t{\tp->ref = 1 ;\n\n\t\tp->sfinfo.frames = 0 ;\n\t\tp->sfinfo.channels = chans ;\n\t\tp->sfinfo.format = fmt ;\n\t\tp->sfinfo.samplerate = srate ;\n\t\tp->sfinfo.sections = 0 ;\n\t\tp->sfinfo.seekable = 0 ;\n\n\t\tp->sf = sf_wchar_open (wpath, mode, &p->sfinfo) ;\n\t\t} ;\n\n\treturn ;\n} /* SndfileHandle const wchar_t * constructor */\n\n#endif\n\n#endif\t/* SNDFILE_HH */\n\n"
  },
  {
    "path": "vendor/libsndfile/lib/Win32/libsndfile-1.def",
    "content": "; Auto-generated by create_symbols_file.py\n\nLIBRARY libsndfile-1.dll\nEXPORTS\n\nsf_command           @1\nsf_open              @2\nsf_close             @3\nsf_seek              @4\nsf_error             @7\nsf_perror            @8\nsf_error_str         @9\nsf_error_number      @10\nsf_format_check      @11\nsf_read_raw          @16\nsf_readf_short       @17\nsf_readf_int         @18\nsf_readf_float       @19\nsf_readf_double      @20\nsf_read_short        @21\nsf_read_int          @22\nsf_read_float        @23\nsf_read_double       @24\nsf_write_raw         @32\nsf_writef_short      @33\nsf_writef_int        @34\nsf_writef_float      @35\nsf_writef_double     @36\nsf_write_short       @37\nsf_write_int         @38\nsf_write_float       @39\nsf_write_double      @40\nsf_strerror          @50\nsf_get_string        @60\nsf_set_string        @61\nsf_version_string    @68\nsf_open_fd           @70\nsf_wchar_open        @71\nsf_open_virtual      @80\nsf_write_sync        @90\nsf_set_chunk         @100\nsf_get_chunk_size    @101\nsf_get_chunk_data    @102\nsf_get_chunk_iterator @103\nsf_next_chunk_iterator @104\nsf_current_byterate  @110\n\n"
  },
  {
    "path": "vendor/libsndfile/lib/Win32/pkgconfig/sndfile.pc",
    "content": "prefix=c:/devel/target/libsndfile\nexec_prefix=${prefix}\nlibdir=${exec_prefix}/lib\nincludedir=${prefix}/include\n\nName: sndfile\nDescription: A library for reading and writing audio files\nRequires: \nVersion: 1.0.28\nLibs: -L${libdir} -lsndfile\nLibs.private: Ext/libflac.la Ext/libvorbis.la Ext/libogg.la\nCflags: -I${includedir} \n"
  },
  {
    "path": "vendor/libsndfile/lib/Win64/libsndfile-1.def",
    "content": "; Auto-generated by create_symbols_file.py\n\nLIBRARY libsndfile-1.dll\nEXPORTS\n\nsf_command           @1\nsf_open              @2\nsf_close             @3\nsf_seek              @4\nsf_error             @7\nsf_perror            @8\nsf_error_str         @9\nsf_error_number      @10\nsf_format_check      @11\nsf_read_raw          @16\nsf_readf_short       @17\nsf_readf_int         @18\nsf_readf_float       @19\nsf_readf_double      @20\nsf_read_short        @21\nsf_read_int          @22\nsf_read_float        @23\nsf_read_double       @24\nsf_write_raw         @32\nsf_writef_short      @33\nsf_writef_int        @34\nsf_writef_float      @35\nsf_writef_double     @36\nsf_write_short       @37\nsf_write_int         @38\nsf_write_float       @39\nsf_write_double      @40\nsf_strerror          @50\nsf_get_string        @60\nsf_set_string        @61\nsf_version_string    @68\nsf_open_fd           @70\nsf_wchar_open        @71\nsf_open_virtual      @80\nsf_write_sync        @90\nsf_set_chunk         @100\nsf_get_chunk_size    @101\nsf_get_chunk_data    @102\nsf_get_chunk_iterator @103\nsf_next_chunk_iterator @104\nsf_current_byterate  @110\n\n"
  },
  {
    "path": "vendor/libsndfile/lib/Win64/pkgconfig/sndfile.pc",
    "content": "prefix=c:/devel/target/libsndfile\nexec_prefix=${prefix}\nlibdir=${exec_prefix}/lib\nincludedir=${prefix}/include\n\nName: sndfile\nDescription: A library for reading and writing audio files\nRequires: \nVersion: 1.0.28\nLibs: -L${libdir} -lsndfile\nLibs.private: Ext/libflac.la Ext/libvorbis.la Ext/libogg.la\nCflags: -I${includedir} \n"
  },
  {
    "path": "vendor/milessdk/include/mss.h",
    "content": "#pragma once\n\n// fake mss.h header for use with re3, to make using mss32.dll possible\n// gta3 uses miles 6.1a\n// check https://github.com/withmorten/re3mss for more info\n\n#include <stdint.h>\n\ntypedef char C8;\ntypedef uint8_t U8;\ntypedef int8_t S8;\ntypedef int16_t S16;\ntypedef uint16_t U16;\ntypedef int32_t S32;\ntypedef uint32_t U32;\ntypedef float F32;\ntypedef double F64;\n\ntypedef void *HSTREAM;\ntypedef U32 HPROVIDER;\ntypedef void *H3DPOBJECT;\ntypedef H3DPOBJECT H3DSAMPLE;\ntypedef void *HSAMPLE;\ntypedef void *HDIGDRIVER;\n\ntypedef U32 HPROENUM;\n#define HPROENUM_FIRST 0\n\ntypedef S32 M3DRESULT;\n\n#define M3D_NOERR 0\n\nenum { ENVIRONMENT_CAVE = 8 };\n\n#define AIL_3D_2_SPEAKER 0\n#define AIL_3D_HEADPHONE 1\n#define AIL_3D_4_SPEAKER 3\n\n#define DIG_MIXER_CHANNELS 1\n\n#define DIG_F_MONO_16 1\n#define DIG_PCM_SIGN 1\n\n#define SMP_PLAYING 4\n\ntypedef struct _AILSOUNDINFO\n{\n\tS32 format;\n\tvoid const *data_ptr;\n\tU32 data_len;\n\tU32 rate;\n\tS32 bits;\n\tS32 channels;\n\tU32 samples;\n\tU32 block_size;\n\tvoid const *initial_ptr;\n} AILSOUNDINFO;\n\ntypedef U32 (WINAPI *AIL_file_open_callback)(char const * Filename, U32 * FileHandle);\n\ntypedef void (WINAPI *AIL_file_close_callback)(U32 FileHandle);\n\n#define AIL_FILE_SEEK_BEGIN 0\n#define AIL_FILE_SEEK_CURRENT 1\n#define AIL_FILE_SEEK_END 2\n\ntypedef S32(WINAPI *AIL_file_seek_callback)(U32 FileHandle, S32 Offset, U32 Type);\n\ntypedef U32(WINAPI *AIL_file_read_callback)(U32 FileHandle, void* Buffer, U32 Bytes);\n\n#ifdef RE3MSS_EXPORTS\n#define RE3MSS_EXPORT __declspec(dllexport)\n#else\n#define RE3MSS_EXPORT __declspec(dllimport)\n#endif\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nRE3MSS_EXPORT S32 WINAPI AIL_enumerate_3D_providers(HPROENUM *next, HPROVIDER *dest, C8 **name);\nRE3MSS_EXPORT void WINAPI AIL_release_3D_sample_handle(H3DSAMPLE S);\nRE3MSS_EXPORT void WINAPI AIL_close_3D_provider(HPROVIDER lib);\nRE3MSS_EXPORT void WINAPI AIL_set_3D_provider_preference(HPROVIDER lib, C8 const *name, void const *val);\nRE3MSS_EXPORT M3DRESULT WINAPI AIL_open_3D_provider(HPROVIDER lib);\nRE3MSS_EXPORT C8 *WINAPI AIL_last_error(void);\nRE3MSS_EXPORT S32 WINAPI AIL_3D_room_type(HPROVIDER lib);\nRE3MSS_EXPORT void WINAPI AIL_set_3D_room_type(HPROVIDER lib, S32 room_type);\nRE3MSS_EXPORT void WINAPI AIL_3D_provider_attribute(HPROVIDER lib, C8 const *name, void *val);\nRE3MSS_EXPORT H3DSAMPLE WINAPI AIL_allocate_3D_sample_handle(HPROVIDER lib);\nRE3MSS_EXPORT void WINAPI AIL_set_3D_sample_effects_level(H3DSAMPLE S, F32 effects_level);\nRE3MSS_EXPORT void WINAPI AIL_set_3D_speaker_type(HPROVIDER lib, S32 speaker_type);\nRE3MSS_EXPORT HSTREAM WINAPI AIL_open_stream(HDIGDRIVER dig, C8 const *filename, S32 stream_mem);\nRE3MSS_EXPORT void WINAPI AIL_stream_ms_position(HSTREAM S, S32 *total_milliseconds, S32 *current_milliseconds);\nRE3MSS_EXPORT void WINAPI AIL_close_stream(HSTREAM stream);\nRE3MSS_EXPORT S32 WINAPI AIL_digital_handle_release(HDIGDRIVER drvr);\nRE3MSS_EXPORT S32 WINAPI AIL_digital_handle_reacquire(HDIGDRIVER drvr);\nRE3MSS_EXPORT C8 *WINAPI AIL_set_redist_directory(C8 const *dir);\nRE3MSS_EXPORT S32 WINAPI AIL_startup(void);\nRE3MSS_EXPORT S32 WINAPI AIL_set_preference(U32 number, S32 value);\nRE3MSS_EXPORT HDIGDRIVER WINAPI AIL_open_digital_driver(U32 frequency, S32 bits, S32 channel, U32 flags);\nRE3MSS_EXPORT void *WINAPI AIL_mem_alloc_lock(U32 size);\nRE3MSS_EXPORT HSAMPLE WINAPI AIL_allocate_sample_handle(HDIGDRIVER dig);\nRE3MSS_EXPORT void WINAPI AIL_init_sample(HSAMPLE S);\nRE3MSS_EXPORT void WINAPI AIL_set_sample_type(HSAMPLE S, S32 format, U32 flags);\nRE3MSS_EXPORT void WINAPI AIL_pause_stream(HSTREAM stream, S32 onoff);\nRE3MSS_EXPORT void WINAPI AIL_release_sample_handle(HSAMPLE S);\nRE3MSS_EXPORT void WINAPI AIL_mem_free_lock(void *ptr);\nRE3MSS_EXPORT void WINAPI AIL_close_digital_driver(HDIGDRIVER dig);\nRE3MSS_EXPORT void WINAPI AIL_shutdown(void);\nRE3MSS_EXPORT void WINAPI AIL_set_3D_sample_volume(H3DSAMPLE S, S32 volume);\nRE3MSS_EXPORT void WINAPI AIL_set_sample_volume(HSAMPLE S, S32 volume);\nRE3MSS_EXPORT void WINAPI AIL_set_sample_address(HSAMPLE S, void const *start, U32 len);\nRE3MSS_EXPORT S32 WINAPI AIL_set_3D_sample_info(H3DSAMPLE S, AILSOUNDINFO const *info);\nRE3MSS_EXPORT void WINAPI AIL_set_3D_position(H3DPOBJECT obj, F32 X, F32 Y, F32 Z);\nRE3MSS_EXPORT void WINAPI AIL_set_3D_sample_distances(H3DSAMPLE S, F32 max_dist, F32 min_dist);\nRE3MSS_EXPORT void WINAPI AIL_set_sample_pan(HSAMPLE S, S32 pan);\nRE3MSS_EXPORT void WINAPI AIL_set_sample_playback_rate(HSAMPLE S, S32 playback_rate);\nRE3MSS_EXPORT void WINAPI AIL_set_3D_sample_playback_rate(H3DSAMPLE S, S32 playback_rate);\nRE3MSS_EXPORT void WINAPI AIL_set_sample_loop_block(HSAMPLE S, S32 loop_start_offset, S32 loop_end_offset);\nRE3MSS_EXPORT void WINAPI AIL_set_3D_sample_loop_block(H3DSAMPLE S, S32 loop_start_offset, S32 loop_end_offset);\nRE3MSS_EXPORT void WINAPI AIL_set_sample_loop_count(HSAMPLE S, S32 loop_count);\nRE3MSS_EXPORT void WINAPI AIL_set_3D_sample_loop_count(H3DSAMPLE S, S32 loops);\nRE3MSS_EXPORT U32 WINAPI AIL_sample_status(HSAMPLE S);\nRE3MSS_EXPORT U32 WINAPI AIL_3D_sample_status(H3DSAMPLE S);\nRE3MSS_EXPORT void WINAPI AIL_start_sample(HSAMPLE S);\nRE3MSS_EXPORT void WINAPI AIL_start_3D_sample(H3DSAMPLE S);\nRE3MSS_EXPORT void WINAPI AIL_end_sample(HSAMPLE S);\nRE3MSS_EXPORT void WINAPI AIL_end_3D_sample(H3DSAMPLE S);\nRE3MSS_EXPORT void WINAPI AIL_set_stream_loop_count(HSTREAM stream, S32 count);\nRE3MSS_EXPORT S32 WINAPI AIL_service_stream(HSTREAM stream, S32 fillup);\nRE3MSS_EXPORT void WINAPI AIL_start_stream(HSTREAM stream);\nRE3MSS_EXPORT void WINAPI AIL_set_stream_ms_position(HSTREAM S, S32 milliseconds);\nRE3MSS_EXPORT void WINAPI AIL_set_stream_volume(HSTREAM stream, S32 volume);\nRE3MSS_EXPORT void WINAPI AIL_set_stream_pan(HSTREAM stream, S32 pan);\nRE3MSS_EXPORT S32 WINAPI AIL_stream_status(HSTREAM stream);\nRE3MSS_EXPORT void WINAPI AIL_set_file_callbacks(AIL_file_open_callback opencb, AIL_file_close_callback closecb, AIL_file_seek_callback seekcb, AIL_file_read_callback readcb);\n\n#ifdef __cplusplus\n}\n#endif\n"
  },
  {
    "path": "vendor/mpg123/include/fmt123.h",
    "content": "/*\n\tlibmpg123: MPEG Audio Decoder library\n\n\tseparate header just for audio format definitions not tied to\n\tlibrary code\n\n\tcopyright 1995-2020 by the mpg123 project\n\tfree software under the terms of the LGPL 2.1\n\tsee COPYING and AUTHORS files in distribution or http://mpg123.org\n*/\n\n#ifndef MPG123_ENC_H\n#define MPG123_ENC_H\n\n/** \\file fmt123.h Audio format definitions. */\n\n/** \\defgroup mpg123_enc mpg123 PCM sample encodings\n *  These are definitions for audio formats used by libmpg123 and\n *  libout123.\n *\n * @{\n */\n\n/** An enum over all sample types possibly known to mpg123.\n *  The values are designed as bit flags to allow bitmasking for encoding\n *  families.\n *  This is also why the enum is not used as type for actual encoding variables,\n *  plain integers (at least 16 bit, 15 bit being used) cover the possible\n *  combinations of these flags.\n *\n *  Note that (your build of) libmpg123 does not necessarily support all these.\n *  Usually, you can expect the 8bit encodings and signed 16 bit.\n *  Also 32bit float will be usual beginning with mpg123-1.7.0 .\n *  What you should bear in mind is that (SSE, etc) optimized routines may be\n *  absent for some formats. We do have SSE for 16, 32 bit and float, though.\n *  24 bit integer is done via postprocessing of 32 bit output -- just cutting\n *  the last byte, no rounding, even. If you want better, do it yourself.\n *\n *  All formats are in native byte order. If you need different endinaness, you\n *  can simply postprocess the output buffers (libmpg123 wouldn't do anything\n * else). The macro MPG123_SAMPLESIZE() can be helpful there.\n */\nenum mpg123_enc_enum\n{\n/* 0000 0000 0000 1111 Some 8 bit  integer encoding. */\n\tMPG123_ENC_8      = 0x00f\n/* 0000 0000 0100 0000 Some 16 bit integer encoding. */\n,\tMPG123_ENC_16     = 0x040\n/* 0100 0000 0000 0000 Some 24 bit integer encoding. */\n,\tMPG123_ENC_24     = 0x4000 \n/* 0000 0001 0000 0000 Some 32 bit integer encoding. */\n,\tMPG123_ENC_32     = 0x100  \n/* 0000 0000 1000 0000 Some signed integer encoding. */\n,\tMPG123_ENC_SIGNED = 0x080  \n/* 0000 1110 0000 0000 Some float encoding. */\n,\tMPG123_ENC_FLOAT  = 0xe00  \n/* 0000 0000 1101 0000 signed 16 bit */\n,\tMPG123_ENC_SIGNED_16   = (MPG123_ENC_16|MPG123_ENC_SIGNED|0x10)\n/* 0000 0000 0110 0000 unsigned 16 bit */\n,\tMPG123_ENC_UNSIGNED_16 = (MPG123_ENC_16|0x20)\n/* 0000 0000 0000 0001 unsigned 8 bit */\n,\tMPG123_ENC_UNSIGNED_8  = 0x01\n/* 0000 0000 1000 0010 signed 8 bit */\n,\tMPG123_ENC_SIGNED_8    = (MPG123_ENC_SIGNED|0x02)\n/* 0000 0000 0000 0100 ulaw 8 bit */\n,\tMPG123_ENC_ULAW_8      = 0x04\n/* 0000 0000 0000 1000 alaw 8 bit */\n,\tMPG123_ENC_ALAW_8      = 0x08\n/* 0001 0001 1000 0000 signed 32 bit */\n,\tMPG123_ENC_SIGNED_32   = MPG123_ENC_32|MPG123_ENC_SIGNED|0x1000\n/* 0010 0001 0000 0000 unsigned 32 bit */\n,\tMPG123_ENC_UNSIGNED_32 = MPG123_ENC_32|0x2000\n/* 0101 0000 1000 0000 signed 24 bit */\n,\tMPG123_ENC_SIGNED_24   = MPG123_ENC_24|MPG123_ENC_SIGNED|0x1000\n/* 0110 0000 0000 0000 unsigned 24 bit */\n,\tMPG123_ENC_UNSIGNED_24 = MPG123_ENC_24|0x2000\n/* 0000 0010 0000 0000 32bit float */\n,\tMPG123_ENC_FLOAT_32    = 0x200\n/* 0000 0100 0000 0000 64bit float */\n,\tMPG123_ENC_FLOAT_64    = 0x400\n/* Any possibly known encoding from the list above. */\n,\tMPG123_ENC_ANY = ( MPG123_ENC_SIGNED_16  | MPG123_ENC_UNSIGNED_16\n\t                 | MPG123_ENC_UNSIGNED_8 | MPG123_ENC_SIGNED_8\n\t                 | MPG123_ENC_ULAW_8     | MPG123_ENC_ALAW_8\n\t                 | MPG123_ENC_SIGNED_32  | MPG123_ENC_UNSIGNED_32\n\t                 | MPG123_ENC_SIGNED_24  | MPG123_ENC_UNSIGNED_24\n\t                 | MPG123_ENC_FLOAT_32   | MPG123_ENC_FLOAT_64    )\n};\n\n/** Get size of one PCM sample with given encoding.\n *  This is included both in libmpg123 and libout123. Both offer\n *  an API function to provide the macro results from library\n *  compile-time, not that of you application. This most likely\n *  does not matter as I do not expect any fresh PCM sample\n *  encoding to appear. But who knows? Perhaps the encoding type\n *  will be abused for funny things in future, not even plain PCM.\n *  And, by the way: Thomas really likes the ?: operator.\n * \\param enc the encoding (mpg123_enc_enum value)\n * \\return size of one sample in bytes\n */\n#define MPG123_SAMPLESIZE(enc) ( \\\n\t(enc) < 1 \\\n\t?\t0 \\\n\t:\t( (enc) & MPG123_ENC_8 \\\n\t\t?\t1 \\\n\t\t:\t( (enc) & MPG123_ENC_16 \\\n\t\t\t?\t2 \\\n\t\t\t:\t( (enc) & MPG123_ENC_24 \\\n\t\t\t\t?\t3 \\\n\t\t\t\t:\t( (  (enc) & MPG123_ENC_32 \\\n\t\t\t\t\t  || (enc) == MPG123_ENC_FLOAT_32 ) \\\n\t\t\t\t\t?\t4 \\\n\t\t\t\t\t:\t( (enc) == MPG123_ENC_FLOAT_64 \\\n\t\t\t\t\t\t?\t8 \\\n\t\t\t\t\t\t:\t0 \\\n)\t)\t)\t)\t)\t)\n\n/** Representation of zero in differing encodings.\n *  This exists to define proper silence in various encodings without\n *  having to link to libsyn123 to do actual conversions at runtime.\n *  You have to handle big/little endian order yourself, though.\n *  This takes the shortcut that any signed encoding has a zero with\n *  all-zero bits. Unsigned linear encodings just have the highest bit set\n *  (2^(n-1) for n bits), while the nonlinear 8-bit ones are special.\n *  \\param enc the encoding (mpg123_enc_enum value)\n *  \\param siz bytes per sample (return value of MPG123_SAMPLESIZE(enc))\n *  \\param off byte (octet) offset counted from LSB\n *  \\return unsigned byte value for the designated octet\n */\n#define MPG123_ZEROSAMPLE(enc, siz, off) ( \\\n\t(enc) == MPG123_ENC_ULAW_8 \\\n\t?\t(off == 0 ? 0xff : 0x00) \\\n\t:\t( (enc) == MPG123_ENC_ALAW_8 \\\n\t\t?\t(off == 0 ? 0xd5 : 0x00) \\\n\t\t:\t( (((enc) & (MPG123_ENC_SIGNED|MPG123_ENC_FLOAT)) || (siz) != ((off)+1)) \\\n\t\t\t?\t0x00 \\\n\t\t\t:\t0x80 \\\n\t)\t)\t)\n\n/** Structure defining an audio format.\n *  Providing the members as individual function arguments to define a certain\n *  output format is easy enough. This struct makes is more comfortable to deal\n *  with a list of formats.\n *  Negative values for the members might be used to communicate use of default\n *  values.\n */\nstruct mpg123_fmt\n{\n\tlong rate;    /**< sampling rate in Hz  */\n\tint channels; /**< channel count */\n\t/** encoding code, can be single value or bitwise or of members of\n\t *  mpg123_enc_enum */\n\tint encoding;\n};\n\n/* @} */\n\n#endif\n\n"
  },
  {
    "path": "vendor/mpg123/include/mpg123.h",
    "content": "/*\n\tlibmpg123: MPEG Audio Decoder library (version 1.26.3)\n\n\tcopyright 1995-2015 by the mpg123 project\n\tfree software under the terms of the LGPL 2.1\n\tsee COPYING and AUTHORS files in distribution or http://mpg123.org\n*/\n\n#ifndef MPG123_LIB_H\n#define MPG123_LIB_H\n\n#include <fmt123.h>\n\n/** \\file mpg123.h The header file for the libmpg123 MPEG Audio decoder */\n\n/** A macro to check at compile time which set of API functions to expect.\n * This should be incremented at least each time a new symbol is added\n * to the header.\n */\n#define MPG123_API_VERSION 45\n\n#ifndef MPG123_EXPORT\n/** Defines needed for MS Visual Studio(tm) DLL builds.\n * Every public function must be prefixed with MPG123_EXPORT. When building \n * the DLL ensure to define BUILD_MPG123_DLL. This makes the function accessible\n * for clients and includes it in the import library which is created together\n * with the DLL. When consuming the DLL ensure to define LINK_MPG123_DLL which\n * imports the functions from the DLL. \n */\n#ifdef BUILD_MPG123_DLL\n/* The dll exports. */\n#define MPG123_EXPORT __declspec(dllexport)\n#else\n#ifdef LINK_MPG123_DLL\n/* The exe imports. */\n#define MPG123_EXPORT __declspec(dllimport)\n#else\n/* Nothing on normal/UNIX builds */\n#define MPG123_EXPORT\n#endif\n#endif\n#endif\n\n/* This is for Visual Studio, so this header works as distributed in the binary downloads */\n#if defined(_MSC_VER) && !defined(MPG123_DEF_SSIZE_T)\n#define MPG123_DEF_SSIZE_T\n#include <stddef.h>\ntypedef ptrdiff_t ssize_t;\n#endif\n\n#ifndef MPG123_NO_CONFIGURE /* Enable use of this file without configure. */\n#include <stdlib.h>\n#include <sys/types.h>\n\n/* Simplified large file handling.\n\tI used to have a check here that prevents building for a library with conflicting large file setup\n\t(application that uses 32 bit offsets with library that uses 64 bits).\n\tWhile that was perfectly fine in an environment where there is one incarnation of the library,\n\tit hurt GNU/Linux and Solaris systems with multilib where the distribution fails to provide the\n\tcorrect header matching the 32 bit library (where large files need explicit support) or\n\tthe 64 bit library (where there is no distinction).\n\n\tNew approach: When the app defines _FILE_OFFSET_BITS, it wants non-default large file support,\n\tand thus functions with added suffix (mpg123_open_64).\n\tAny mismatch will be caught at link time because of the _FILE_OFFSET_BITS setting used when\n\tbuilding libmpg123. Plus, there's dual mode large file support in mpg123 since 1.12 now.\n\tLink failure is not the expected outcome of any half-sane usage anymore.\n\n\tMore complication: What about client code defining _LARGEFILE64_SOURCE? It might want direct access to the _64 functions, along with the ones without suffix. Well, that's possible now via defining MPG123_NO_LARGENAME and MPG123_LARGESUFFIX, respectively, for disabling or enforcing the suffix names.\n*/\n\n/*\n\tNow, the renaming of large file aware functions.\n\tBy default, it appends underscore _FILE_OFFSET_BITS (so, mpg123_seek_64 for mpg123_seek), if _FILE_OFFSET_BITS is defined. You can force a different suffix via MPG123_LARGESUFFIX (that must include the underscore), or you can just disable the whole mess by defining MPG123_NO_LARGENAME.\n*/\n#if (!defined MPG123_NO_LARGENAME) && ((defined _FILE_OFFSET_BITS) || (defined MPG123_LARGESUFFIX))\n\n/* Need some trickery to concatenate the value(s) of the given macro(s). */\n#define MPG123_MACROCAT_REALLY(a, b) a ## b\n#define MPG123_MACROCAT(a, b) MPG123_MACROCAT_REALLY(a, b)\n#ifndef MPG123_LARGESUFFIX\n#define MPG123_LARGESUFFIX MPG123_MACROCAT(_, _FILE_OFFSET_BITS)\n#endif\n#define MPG123_LARGENAME(func) MPG123_MACROCAT(func, MPG123_LARGESUFFIX)\n\n#define mpg123_open_fixed   MPG123_LARGENAME(mpg123_open_fixed)\n#define mpg123_open         MPG123_LARGENAME(mpg123_open)\n#define mpg123_open_fd      MPG123_LARGENAME(mpg123_open_fd)\n#define mpg123_open_handle  MPG123_LARGENAME(mpg123_open_handle)\n#define mpg123_framebyframe_decode MPG123_LARGENAME(mpg123_framebyframe_decode)\n#define mpg123_decode_frame MPG123_LARGENAME(mpg123_decode_frame)\n#define mpg123_tell         MPG123_LARGENAME(mpg123_tell)\n#define mpg123_tellframe    MPG123_LARGENAME(mpg123_tellframe)\n#define mpg123_tell_stream  MPG123_LARGENAME(mpg123_tell_stream)\n#define mpg123_seek         MPG123_LARGENAME(mpg123_seek)\n#define mpg123_feedseek     MPG123_LARGENAME(mpg123_feedseek)\n#define mpg123_seek_frame   MPG123_LARGENAME(mpg123_seek_frame)\n#define mpg123_timeframe    MPG123_LARGENAME(mpg123_timeframe)\n#define mpg123_index        MPG123_LARGENAME(mpg123_index)\n#define mpg123_set_index    MPG123_LARGENAME(mpg123_set_index)\n#define mpg123_position     MPG123_LARGENAME(mpg123_position)\n#define mpg123_length       MPG123_LARGENAME(mpg123_length)\n#define mpg123_framelength  MPG123_LARGENAME(mpg123_framelength)\n#define mpg123_set_filesize MPG123_LARGENAME(mpg123_set_filesize)\n#define mpg123_replace_reader MPG123_LARGENAME(mpg123_replace_reader)\n#define mpg123_replace_reader_handle MPG123_LARGENAME(mpg123_replace_reader_handle)\n#define mpg123_framepos MPG123_LARGENAME(mpg123_framepos)\n\n#endif /* largefile hackery */\n\n#endif /* MPG123_NO_CONFIGURE */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/** \\defgroup mpg123_init mpg123 library and handle setup\n *\n * Functions to initialise and shutdown the mpg123 library and handles.\n * The parameters of handles have workable defaults, you only have to tune them when you want to tune something;-)\n * Tip: Use a RVA setting...\n *\n * @{\n */\n\n/** Opaque structure for the libmpg123 decoder handle. */\nstruct mpg123_handle_struct;\n\n/** Opaque structure for the libmpg123 decoder handle.\n *  Most functions take a pointer to a mpg123_handle as first argument and operate on its data in an object-oriented manner.\n */\ntypedef struct mpg123_handle_struct mpg123_handle;\n\n/** Function to initialise the mpg123 library. \n * This should be called once in a non-parallel context. It is not explicitly\n * thread-safe, but repeated/concurrent calls still _should_ be safe as static\n * tables are filled with the same values anyway.\n *\n *\t\\return MPG123_OK if successful, otherwise an error number.\n */\nMPG123_EXPORT int mpg123_init(void);\n\n/** Superfluous Function to close down the mpg123 library.\n * This was created with the thought that there sometime will be cleanup code\n * to be run after library use. This never materialized. You can forget about\n * this function and it is only here for old programs that do call it.\n */\nMPG123_EXPORT void mpg123_exit(void);\n\n/** Create a handle with optional choice of decoder (named by a string, see mpg123_decoders() or mpg123_supported_decoders()).\n *  and optional retrieval of an error code to feed to mpg123_plain_strerror().\n *  Optional means: Any of or both the parameters may be NULL.\n *\n *  \\param decoder optional choice of decoder variant (NULL for default)\n *  \\param error optional address to store error codes\n *  \\return Non-NULL pointer to fresh handle when successful.\n */\nMPG123_EXPORT mpg123_handle *mpg123_new(const char* decoder, int *error);\n\n/** Delete handle, mh is either a valid mpg123 handle or NULL.\n *  \\param mh handle\n */\nMPG123_EXPORT void mpg123_delete(mpg123_handle *mh);\n\n/** Free plain memory allocated within libmpg123.\n *  This is for library users that are not sure to use the same underlying\n *  memory allocator as libmpg123. It is just a wrapper over free() in\n *  the underlying C library.\n */\nMPG123_EXPORT void mpg123_free(void *ptr);\n\n/** Enumeration of the parameters types that it is possible to set/get. */\nenum mpg123_parms\n{\n\tMPG123_VERBOSE = 0,        /**< set verbosity value for enabling messages to stderr, >= 0 makes sense (integer) */\n\tMPG123_FLAGS,          /**< set all flags, p.ex val = MPG123_GAPLESS|MPG123_MONO_MIX (integer) */\n\tMPG123_ADD_FLAGS,      /**< add some flags (integer) */\n\tMPG123_FORCE_RATE,     /**< when value > 0, force output rate to that value (integer) */\n\tMPG123_DOWN_SAMPLE,    /**< 0=native rate, 1=half rate, 2=quarter rate (integer) */\n\tMPG123_RVA,            /**< one of the RVA choices above (integer) */\n\tMPG123_DOWNSPEED,      /**< play a frame N times (integer) */\n\tMPG123_UPSPEED,        /**< play every Nth frame (integer) */\n\tMPG123_START_FRAME,    /**< start with this frame (skip frames before that, integer) */ \n\tMPG123_DECODE_FRAMES,  /**< decode only this number of frames (integer) */\n\tMPG123_ICY_INTERVAL,   /**< Stream contains ICY metadata with this interval (integer).\n\t                            Make sure to set this _before_ opening a stream.*/\n\tMPG123_OUTSCALE,       /**< the scale for output samples (amplitude - integer or float according to mpg123 output format, normally integer) */\n\tMPG123_TIMEOUT,        /**< timeout for reading from a stream (not supported on win32, integer) */\n\tMPG123_REMOVE_FLAGS,   /**< remove some flags (inverse of MPG123_ADD_FLAGS, integer) */\n\tMPG123_RESYNC_LIMIT,   /**< Try resync on frame parsing for that many bytes or until end of stream (<0 ... integer). This can enlarge the limit for skipping junk on beginning, too (but not reduce it).  */\n\tMPG123_INDEX_SIZE      /**< Set the frame index size (if supported). Values <0 mean that the index is allowed to grow dynamically in these steps (in positive direction, of course) -- Use this when you really want a full index with every individual frame. */\n\t,MPG123_PREFRAMES /**< Decode/ignore that many frames in advance for layer 3. This is needed to fill bit reservoir after seeking, for example (but also at least one frame in advance is needed to have all \"normal\" data for layer 3). Give a positive integer value, please.*/\n\t,MPG123_FEEDPOOL  /**< For feeder mode, keep that many buffers in a pool to avoid frequent malloc/free. The pool is allocated on mpg123_open_feed(). If you change this parameter afterwards, you can trigger growth and shrinkage during decoding. The default value could change any time. If you care about this, then set it. (integer) */\n\t,MPG123_FEEDBUFFER /**< Minimal size of one internal feeder buffer, again, the default value is subject to change. (integer) */\n\t,MPG123_FREEFORMAT_SIZE /**< Tell the parser a free-format frame size to\n\t * avoid read-ahead to get it. A value of -1 (default) means that the parser\n\t * will determine it. The parameter value is applied during decoder setup\n\t * for a freshly opened stream only.\n\t */\n};\n\n/** Flag bits for MPG123_FLAGS, use the usual binary or to combine. */\nenum mpg123_param_flags\n{\n\t MPG123_FORCE_MONO   = 0x7  /**<     0111 Force some mono mode: This is a test bitmask for seeing if any mono forcing is active. */\n\t,MPG123_MONO_LEFT    = 0x1  /**<     0001 Force playback of left channel only.  */\n\t,MPG123_MONO_RIGHT   = 0x2  /**<     0010 Force playback of right channel only. */\n\t,MPG123_MONO_MIX     = 0x4  /**<     0100 Force playback of mixed mono.         */\n\t,MPG123_FORCE_STEREO = 0x8  /**<     1000 Force stereo output.                  */\n\t,MPG123_FORCE_8BIT   = 0x10 /**< 00010000 Force 8bit formats.                   */\n\t,MPG123_QUIET        = 0x20 /**< 00100000 Suppress any printouts (overrules verbose).                    */\n\t,MPG123_GAPLESS      = 0x40 /**< 01000000 Enable gapless decoding (default on if libmpg123 has support). */\n\t,MPG123_NO_RESYNC    = 0x80 /**< 10000000 Disable resync stream after error.                             */\n\t,MPG123_SEEKBUFFER   = 0x100 /**< 000100000000 Enable small buffer on non-seekable streams to allow some peek-ahead (for better MPEG sync). */\n\t,MPG123_FUZZY        = 0x200 /**< 001000000000 Enable fuzzy seeks (guessing byte offsets or using approximate seek points from Xing TOC) */\n\t,MPG123_FORCE_FLOAT  = 0x400 /**< 010000000000 Force floating point output (32 or 64 bits depends on mpg123 internal precision). */\n\t,MPG123_PLAIN_ID3TEXT = 0x800 /**< 100000000000 Do not translate ID3 text data to UTF-8. ID3 strings will contain the raw text data, with the first byte containing the ID3 encoding code. */\n\t,MPG123_IGNORE_STREAMLENGTH = 0x1000 /**< 1000000000000 Ignore any stream length information contained in the stream, which can be contained in a 'TLEN' frame of an ID3v2 tag or a Xing tag */\n\t,MPG123_SKIP_ID3V2 = 0x2000 /**< 10 0000 0000 0000 Do not parse ID3v2 tags, just skip them. */\n\t,MPG123_IGNORE_INFOFRAME = 0x4000 /**< 100 0000 0000 0000 Do not parse the LAME/Xing info frame, treat it as normal MPEG data. */\n\t,MPG123_AUTO_RESAMPLE = 0x8000 /**< 1000 0000 0000 0000 Allow automatic internal resampling of any kind (default on if supported). Especially when going lowlevel with replacing output buffer, you might want to unset this flag. Setting MPG123_DOWNSAMPLE or MPG123_FORCE_RATE will override this. */\n\t,MPG123_PICTURE = 0x10000 /**< 17th bit: Enable storage of pictures from tags (ID3v2 APIC). */\n\t,MPG123_NO_PEEK_END    = 0x20000 /**< 18th bit: Do not seek to the end of\n\t *  the stream in order to probe\n\t *  the stream length and search for the id3v1 field. This also means\n\t *  the file size is unknown unless set using mpg123_set_filesize() and\n\t *  the stream is assumed as non-seekable unless overridden.\n\t */\n\t,MPG123_FORCE_SEEKABLE = 0x40000 /**< 19th bit: Force the stream to be seekable. */\n\t,MPG123_STORE_RAW_ID3  = 0x80000 /**< store raw ID3 data (even if skipping) */\n\t,MPG123_FORCE_ENDIAN   = 0x100000 /**< Enforce endianess of output samples.\n\t *  This is not reflected in the format codes. If this flag is set along with\n\t *  MPG123_BIG_ENDIAN, MPG123_ENC_SIGNED16 means s16be, without\n\t *  MPG123_BIG_ENDIAN, it means s16le. Normal operation without\n\t *  MPG123_FORCE_ENDIAN produces output in native byte order.\n\t */\n\t,MPG123_BIG_ENDIAN     = 0x200000 /**< Choose big endian instead of little. */\n\t,MPG123_NO_READAHEAD   = 0x400000 /**< Disable read-ahead in parser. If\n\t * you know you provide full frames to the feeder API, this enables\n\t * decoder output from the first one on, instead of having to wait for\n\t * the next frame to confirm that the stream is healthy. It also disables\n\t * free format support unless you provide a frame size using\n\t * MPG123_FREEFORMAT_SIZE.\n\t */\n\t,MPG123_FLOAT_FALLBACK = 0x800000 /**< Consider floating point output encoding only after\n\t * trying other (possibly downsampled) rates and encodings first. This is to\n\t * support efficient playback where floating point output is only configured for\n\t * an external resampler, bypassing that resampler when the desired rate can\n\t * be produced directly. This is enabled by default to be closer to older versions\n\t * of libmpg123 which did not enable float automatically at all. If disabled,\n\t * float is considered after the 16 bit default and higher-bit integer encodings\n\t * for any rate. */\n\t,MPG123_NO_FRANKENSTEIN = 0x1000000 /**< Disable support for Frankenstein streams\n\t * (different MPEG streams stiched together). Do not accept serious change of MPEG\n\t * header inside a single stream. With this flag, the audio output format cannot\n\t * change during decoding unless you open a new stream. This also stops decoding\n\t * after an announced end of stream (Info header contained a number of frames\n\t * and this number has been reached). This makes your MP3 files behave more like\n\t * ordinary media files with defined structure, rather than stream dumps with\n\t * some sugar. */\n};\n\n/** choices for MPG123_RVA */\nenum mpg123_param_rva\n{\n\t MPG123_RVA_OFF   = 0 /**< RVA disabled (default).   */\n\t,MPG123_RVA_MIX   = 1 /**< Use mix/track/radio gain. */\n\t,MPG123_RVA_ALBUM = 2 /**< Use album/audiophile gain */\n\t,MPG123_RVA_MAX   = MPG123_RVA_ALBUM /**< The maximum RVA code, may increase in future. */\n};\n\n/** Set a specific parameter, for a specific mpg123_handle, using a parameter \n *  type key chosen from the mpg123_parms enumeration, to the specified value.\n *  \\param mh handle\n *  \\param type parameter choice\n *  \\param value integer value\n *  \\param fvalue floating point value\n *  \\return MPG123_OK on success\n */\nMPG123_EXPORT int mpg123_param( mpg123_handle *mh\n,\tenum mpg123_parms type, long value, double fvalue );\n\n/** Get a specific parameter, for a specific mpg123_handle. \n *  See the mpg123_parms enumeration for a list of available parameters.\n *  \\param mh handle\n *  \\param type parameter choice\n *  \\param value integer value return address\n *  \\param fvalue floating point value return address\n *  \\return MPG123_OK on success\n */\nMPG123_EXPORT int mpg123_getparam( mpg123_handle *mh\n,\tenum mpg123_parms type, long *value, double *fvalue );\n\n/** Feature set available for query with mpg123_feature. */\nenum mpg123_feature_set\n{\n\t MPG123_FEATURE_ABI_UTF8OPEN = 0     /**< mpg123 expects path names to be given in UTF-8 encoding instead of plain native. */\n\t,MPG123_FEATURE_OUTPUT_8BIT          /**< 8bit output   */\n\t,MPG123_FEATURE_OUTPUT_16BIT         /**< 16bit output  */\n\t,MPG123_FEATURE_OUTPUT_32BIT         /**< 32bit output  */\n\t,MPG123_FEATURE_INDEX                /**< support for building a frame index for accurate seeking */\n\t,MPG123_FEATURE_PARSE_ID3V2          /**< id3v2 parsing */\n\t,MPG123_FEATURE_DECODE_LAYER1        /**< mpeg layer-1 decoder enabled */\n\t,MPG123_FEATURE_DECODE_LAYER2        /**< mpeg layer-2 decoder enabled */\n\t,MPG123_FEATURE_DECODE_LAYER3        /**< mpeg layer-3 decoder enabled */\n\t,MPG123_FEATURE_DECODE_ACCURATE      /**< accurate decoder rounding    */\n\t,MPG123_FEATURE_DECODE_DOWNSAMPLE    /**< downsample (sample omit)     */\n\t,MPG123_FEATURE_DECODE_NTOM          /**< flexible rate decoding       */\n\t,MPG123_FEATURE_PARSE_ICY            /**< ICY support                  */\n\t,MPG123_FEATURE_TIMEOUT_READ         /**< Reader with timeout (network). */\n\t,MPG123_FEATURE_EQUALIZER            /**< tunable equalizer */\n\t,MPG123_FEATURE_MOREINFO             /**< more info extraction (for frame analyzer) */\n\t,MPG123_FEATURE_OUTPUT_FLOAT32      /**< 32 bit float output */\n\t,MPG123_FEATURE_OUTPUT_FLOAT64      /**< 64 bit float output (usually never) */\n};\n\n/** Query libmpg123 features.\n *  \\param key feature selection\n *  \\return 1 for success, 0 for unimplemented functions\n */\nMPG123_EXPORT int mpg123_feature(const enum mpg123_feature_set key);\n\n/** Query libmpg123 features with better ABI compatibility\n *\n *  This is the same as mpg123_feature(), but this time not using\n *  the enum as argument. Compilers don't have to agree on the size of\n *  enums and hence they are not safe in public API.\n *\n *  \\param key feature selection\n *  \\return 1 for success, 0 for unimplemented functions\n */\nMPG123_EXPORT int mpg123_feature2(int key);\n\n/* @} */\n\n\n/** \\defgroup mpg123_error mpg123 error handling\n *\n * Functions to get text version of the error numbers and an enumeration\n * of the error codes returned by libmpg123.\n *\n * Most functions operating on a mpg123_handle simply return MPG123_OK (0)\n * on success and MPG123_ERR (-1) on failure, setting the internal error\n * variable of the handle to the specific error code. If there was not a valid\n * (non-NULL) handle provided to a function operating on one, MPG123_BAD_HANDLE\n * may be returned if this can not be confused with a valid positive return\n * value.\n * Meaning: A function expected to return positive integers on success will\n * always indicate error or a special condition by returning a negative one.\n *\n * Decoding/seek functions may also return message codes MPG123_DONE,\n * MPG123_NEW_FORMAT and MPG123_NEED_MORE (all negative, see below on how to\n * react). Note that calls to those can be nested, so generally watch out\n * for these codes after initial handle setup.\n * Especially any function that needs information about the current stream\n * to work will try to at least parse the beginning if that did not happen\n * yet.\n *\n * On a function that is supposed to return MPG123_OK on success and\n * MPG123_ERR on failure, make sure you check for != MPG123_OK, not\n * == MPG123_ERR, as the error code could get more specific in future,\n * or there is just a special message from a decoding routine as indicated\n * above.\n *\n * @{\n */\n\n/** Enumeration of the message and error codes and returned by libmpg123 functions. */\nenum mpg123_errors\n{\n\tMPG123_DONE=-12,\t/**< Message: Track ended. Stop decoding. */\n\tMPG123_NEW_FORMAT=-11,\t/**< Message: Output format will be different on next call. Note that some libmpg123 versions between 1.4.3 and 1.8.0 insist on you calling mpg123_getformat() after getting this message code. Newer verisons behave like advertised: You have the chance to call mpg123_getformat(), but you can also just continue decoding and get your data. */\n\tMPG123_NEED_MORE=-10,\t/**< Message: For feed reader: \"Feed me more!\" (call mpg123_feed() or mpg123_decode() with some new input data). */\n\tMPG123_ERR=-1,\t\t\t/**< Generic Error */\n\tMPG123_OK=0, \t\t\t/**< Success */\n\tMPG123_BAD_OUTFORMAT, \t/**< Unable to set up output format! */\n\tMPG123_BAD_CHANNEL,\t\t/**< Invalid channel number specified. */\n\tMPG123_BAD_RATE,\t\t/**< Invalid sample rate specified.  */\n\tMPG123_ERR_16TO8TABLE,\t/**< Unable to allocate memory for 16 to 8 converter table! */\n\tMPG123_BAD_PARAM,\t\t/**< Bad parameter id! */\n\tMPG123_BAD_BUFFER,\t\t/**< Bad buffer given -- invalid pointer or too small size. */\n\tMPG123_OUT_OF_MEM,\t\t/**< Out of memory -- some malloc() failed. */\n\tMPG123_NOT_INITIALIZED,\t/**< You didn't initialize the library! */\n\tMPG123_BAD_DECODER,\t\t/**< Invalid decoder choice. */\n\tMPG123_BAD_HANDLE,\t\t/**< Invalid mpg123 handle. */\n\tMPG123_NO_BUFFERS,\t\t/**< Unable to initialize frame buffers (out of memory?). */\n\tMPG123_BAD_RVA,\t\t\t/**< Invalid RVA mode. */\n\tMPG123_NO_GAPLESS,\t\t/**< This build doesn't support gapless decoding. */\n\tMPG123_NO_SPACE,\t\t/**< Not enough buffer space. */\n\tMPG123_BAD_TYPES,\t\t/**< Incompatible numeric data types. */\n\tMPG123_BAD_BAND,\t\t/**< Bad equalizer band. */\n\tMPG123_ERR_NULL,\t\t/**< Null pointer given where valid storage address needed. */\n\tMPG123_ERR_READER,\t\t/**< Error reading the stream. */\n\tMPG123_NO_SEEK_FROM_END,/**< Cannot seek from end (end is not known). */\n\tMPG123_BAD_WHENCE,\t\t/**< Invalid 'whence' for seek function.*/\n\tMPG123_NO_TIMEOUT,\t\t/**< Build does not support stream timeouts. */\n\tMPG123_BAD_FILE,\t\t/**< File access error. */\n\tMPG123_NO_SEEK,\t\t\t/**< Seek not supported by stream. */\n\tMPG123_NO_READER,\t\t/**< No stream opened. */\n\tMPG123_BAD_PARS,\t\t/**< Bad parameter handle. */\n\tMPG123_BAD_INDEX_PAR,\t/**< Bad parameters to mpg123_index() and mpg123_set_index() */\n\tMPG123_OUT_OF_SYNC,\t/**< Lost track in bytestream and did not try to resync. */\n\tMPG123_RESYNC_FAIL,\t/**< Resync failed to find valid MPEG data. */\n\tMPG123_NO_8BIT,\t/**< No 8bit encoding possible. */\n\tMPG123_BAD_ALIGN,\t/**< Stack aligmnent error */\n\tMPG123_NULL_BUFFER,\t/**< NULL input buffer with non-zero size... */\n\tMPG123_NO_RELSEEK,\t/**< Relative seek not possible (screwed up file offset) */\n\tMPG123_NULL_POINTER, /**< You gave a null pointer somewhere where you shouldn't have. */\n\tMPG123_BAD_KEY,\t/**< Bad key value given. */\n\tMPG123_NO_INDEX,\t/**< No frame index in this build. */\n\tMPG123_INDEX_FAIL,\t/**< Something with frame index went wrong. */\n\tMPG123_BAD_DECODER_SETUP,\t/**< Something prevents a proper decoder setup */\n\tMPG123_MISSING_FEATURE  /**< This feature has not been built into libmpg123. */\n\t,MPG123_BAD_VALUE /**< A bad value has been given, somewhere. */\n\t,MPG123_LSEEK_FAILED /**< Low-level seek failed. */\n\t,MPG123_BAD_CUSTOM_IO /**< Custom I/O not prepared. */\n\t,MPG123_LFS_OVERFLOW /**< Offset value overflow during translation of large file API calls -- your client program cannot handle that large file. */\n\t,MPG123_INT_OVERFLOW /**< Some integer overflow. */\n};\n\n/** Look up error strings given integer code.\n *  \\param errcode integer error code\n *  \\return string describing what that error error code means\n */\nMPG123_EXPORT const char* mpg123_plain_strerror(int errcode);\n\n/** Give string describing what error has occured in the context of handle mh.\n *  When a function operating on an mpg123 handle returns MPG123_ERR, you should check for the actual reason via\n *  char *errmsg = mpg123_strerror(mh)\n *  This function will catch mh == NULL and return the message for MPG123_BAD_HANDLE.\n *  \\param mh handle\n *  \\return error message\n */\nMPG123_EXPORT const char* mpg123_strerror(mpg123_handle *mh);\n\n/** Return the plain errcode intead of a string.\n *  \\param mh handle\n *  \\return error code recorded in handle or MPG123_BAD_HANDLE\n */\nMPG123_EXPORT int mpg123_errcode(mpg123_handle *mh);\n\n/*@}*/\n\n\n/** \\defgroup mpg123_decoder mpg123 decoder selection\n *\n * Functions to list and select the available decoders.\n * Perhaps the most prominent feature of mpg123: You have several (optimized) decoders to choose from (on x86 and PPC (MacOS) systems, that is).\n *\n * @{\n */\n\n/** Get available decoder list.\n *  \\return NULL-terminated array of generally available decoder names (plain 8bit ASCII)\n */\nMPG123_EXPORT const char **mpg123_decoders(void);\n\n/** Get supported decoder list.\n *  \\return NULL-terminated array of the decoders supported by the CPU (plain 8bit ASCII)\n */\nMPG123_EXPORT const char **mpg123_supported_decoders(void);\n\n/** Set the active decoder.\n *  \\param mh handle\n *  \\param decoder_name name of decoder\n *  \\return MPG123_OK on success\n */\nMPG123_EXPORT int mpg123_decoder(mpg123_handle *mh, const char* decoder_name);\n\n/** Get the currently active decoder name.\n *  The active decoder engine can vary depening on output constraints,\n *  mostly non-resampling, integer output is accelerated via 3DNow & Co. but for\n *  other modes a fallback engine kicks in.\n *  Note that this can return a decoder that is only active in the hidden and not\n *  available as decoder choice from the outside.\n *  \\param mh handle\n *  \\return The decoder name or NULL on error.\n */\nMPG123_EXPORT const char* mpg123_current_decoder(mpg123_handle *mh);\n\n/*@}*/\n\n\n/** \\defgroup mpg123_output mpg123 output audio format \n *\n * Functions to get and select the format of the decoded audio.\n *\n * Before you dive in, please be warned that you might get confused by this.\n * This seems to happen a lot, therefore I am trying to explain in advance.\n * If you do feel confused and just want to decode your normal MPEG audio files that\n * don't alter properties in the middle, just use mpg123_open_fixed() with a fixed encoding\n * and channel count and forget about a matrix of audio formats. If you want to get funky,\n * read ahead ...\n *\n * The mpg123 library decides what output format to use when encountering the first frame in a stream, or actually any frame that is still valid but differs from the frames before in the prompted output format. At such a deciding point, an internal table of allowed encodings, sampling rates and channel setups is consulted. According to this table, an output format is chosen and the decoding engine set up accordingly (including optimized routines for different output formats). This might seem unusual but it just follows from the non-existence of \"MPEG audio files\" with defined overall properties. There are streams, streams are concatenations of (semi) independent frames. We store streams on disk and call them \"MPEG audio files\", but that does not change their nature as the decoder is concerned (the LAME/Xing header for gapless decoding makes things interesting again).\n *\n * To get to the point: What you do with mpg123_format() and friends is to fill the internal table of allowed formats before it is used. That includes removing support for some formats or adding your forced sample rate (see MPG123_FORCE_RATE) that will be used with the crude internal resampler. Also keep in mind that the sample encoding is just a question of choice -- the MPEG frames do only indicate their native sampling rate and channel count. If you want to decode to integer or float samples, 8 or 16 bit ... that is your decision. In a \"clean\" world, libmpg123 would always decode to 32 bit float and let you handle any sample conversion. But there are optimized routines that work faster by directly decoding to the desired encoding / accuracy. We prefer efficiency over conceptual tidyness.\n *\n * People often start out thinking that mpg123_format() should change the actual decoding format on the fly. That is wrong. It only has effect on the next natural change of output format, when libmpg123 will consult its format table again. To make life easier, you might want to call mpg123_format_none() before any thing else and then just allow one desired encoding and a limited set of sample rates / channel choices that you actually intend to deal with. You can force libmpg123 to decode everything to 44100 KHz, stereo, 16 bit integer ... it will duplicate mono channels and even do resampling if needed (unless that feature is disabled in the build, same with some encodings). But I have to stress that the resampling of libmpg123 is very crude and doesn't even contain any kind of \"proper\" interpolation.\n *\n * In any case, watch out for MPG123_NEW_FORMAT as return message from decoding routines and call mpg123_getformat() to get the currently active output format.\n *\n * @{\n */\n\n/** They can be combined into one number (3) to indicate mono and stereo... */\nenum mpg123_channelcount\n{\n\t MPG123_MONO   = 1 /**< mono */\n\t,MPG123_STEREO = 2 /**< stereo */\n};\n\n/** An array of supported standard sample rates\n *  These are possible native sample rates of MPEG audio files.\n *  You can still force mpg123 to resample to a different one, but by\n *  default you will only get audio in one of these samplings.\n *  This list is in ascending order.\n *  \\param list Store a pointer to the sample rates array there.\n *  \\param number Store the number of sample rates there. */\nMPG123_EXPORT void mpg123_rates(const long **list, size_t *number);\n\n/** An array of supported audio encodings.\n *  An audio encoding is one of the fully qualified members of mpg123_enc_enum (MPG123_ENC_SIGNED_16, not MPG123_SIGNED).\n *  \\param list Store a pointer to the encodings array there.\n *  \\param number Store the number of encodings there. */\nMPG123_EXPORT void mpg123_encodings(const int **list, size_t *number);\n\n/** Return the size (in bytes) of one mono sample of the named encoding.\n * \\param encoding The encoding value to analyze.\n * \\return positive size of encoding in bytes, 0 on invalid encoding. */\nMPG123_EXPORT int mpg123_encsize(int encoding);\n\n/** Configure a mpg123 handle to accept no output format at all, \n *  use before specifying supported formats with mpg123_format\n *  \\param mh handle\n *  \\return MPG123_OK on success\n */\nMPG123_EXPORT int mpg123_format_none(mpg123_handle *mh);\n\n/** Configure mpg123 handle to accept all formats \n *  (also any custom rate you may set) -- this is default.\n *  \\param mh handle\n *  \\return MPG123_OK on success\n */\nMPG123_EXPORT int mpg123_format_all(mpg123_handle *mh);\n\n/** Set the audio format support of a mpg123_handle in detail:\n *  \\param mh handle\n *  \\param rate The sample rate value (in Hertz).\n *  \\param channels A combination of MPG123_STEREO and MPG123_MONO.\n *  \\param encodings A combination of accepted encodings for rate and channels, p.ex MPG123_ENC_SIGNED16 | MPG123_ENC_ULAW_8 (or 0 for no support). Please note that some encodings may not be supported in the library build and thus will be ignored here.\n *  \\return MPG123_OK on success, MPG123_ERR if there was an error. */\nMPG123_EXPORT int mpg123_format( mpg123_handle *mh\n,\tlong rate, int channels, int encodings );\n\n/** Set the audio format support of a mpg123_handle in detail:\n *  \\param mh handle\n *  \\param rate The sample rate value (in Hertz). Special value 0 means\n *     all rates (the reason for this variant of mpg123_format()).\n *  \\param channels A combination of MPG123_STEREO and MPG123_MONO.\n *  \\param encodings A combination of accepted encodings for rate and channels,\n *     p.ex MPG123_ENC_SIGNED16 | MPG123_ENC_ULAW_8 (or 0 for no support).\n *     Please note that some encodings may not be supported in the library build\n *     and thus will be ignored here.\n *  \\return MPG123_OK on success, MPG123_ERR if there was an error. */\nMPG123_EXPORT int mpg123_format2( mpg123_handle *mh\n,\tlong rate, int channels, int encodings );\n\n/** Check to see if a specific format at a specific rate is supported \n *  by mpg123_handle.\n *  \\param mh handle\n *  \\param rate sampling rate\n *  \\param encoding encoding\n *  \\return 0 for no support (that includes invalid parameters), MPG123_STEREO, \n *          MPG123_MONO or MPG123_STEREO|MPG123_MONO. */\nMPG123_EXPORT int mpg123_format_support( mpg123_handle *mh\n,\tlong rate, int encoding );\n\n/** Get the current output format written to the addresses given.\n *  If the stream is freshly loaded, this will try to parse enough\n *  of it to give you the format to come. This clears the flag that\n *  would otherwise make the first decoding call return\n *  MPG123_NEW_FORMAT.\n *  \\param mh handle\n *  \\param rate sampling rate return address\n *  \\param channels channel count return address\n *  \\param encoding encoding return address\n *  \\return MPG123_OK on success\n */\nMPG123_EXPORT int mpg123_getformat( mpg123_handle *mh\n,\tlong *rate, int *channels, int *encoding );\n\n/** Get the current output format written to the addresses given.\n *  This differs from plain mpg123_getformat() in that you can choose\n *  _not_ to clear the flag that would trigger the next decoding call\n *  to return MPG123_NEW_FORMAT in case of a new format arriving.\n *  \\param mh handle\n *  \\param rate sampling rate return address\n *  \\param channels channel count return address\n *  \\param encoding encoding return address\n *  \\param clear_flag if true, clear internal format flag\n *  \\return MPG123_OK on success\n */\nMPG123_EXPORT int mpg123_getformat2( mpg123_handle *mh\n,\tlong *rate, int *channels, int *encoding, int clear_flag );\n\n/*@}*/\n\n\n/** \\defgroup mpg123_input mpg123 file input and decoding\n *\n * Functions for input bitstream and decoding operations.\n * Decoding/seek functions may also return message codes MPG123_DONE, MPG123_NEW_FORMAT and MPG123_NEED_MORE (please read up on these on how to react!).\n * @{\n */\n\n/** Open a simple MPEG file with fixed properties.\n *\n *  This function shall simplify the common use case of a plain MPEG\n *  file on disk that you want to decode, with one fixed sample\n *  rate and channel count, and usually a length defined by a Lame/Info/Xing\n *  tag. It will:\n *\n *  - set the MPG123_NO_FRANKENSTEIN flag\n *  - set up format support according to given parameters,\n *  - open the file,\n *  - query audio format,\n *  - fix the audio format support table to ensure the format stays the same,\n *  - call mpg123_scan() if there is no header frame to tell the track length.\n *\n *  From that on, you can call mpg123_getformat() for querying the sample\n *  rate (and channel count in case you allowed both) and mpg123_length()\n *  to get a pretty safe number for the duration.\n *  Only the sample rate is left open as that indeed is a fixed property of\n *  MPEG files. You could set MPG123_FORCE_RATE beforehand, but that may trigger\n *  low-quality resampling in the decoder, only do so if in dire need.\n *  The library will convert mono files to stereo for you, and vice versa.\n *  If any constraint cannot be satisified (most likely because of a non-default\n *  build of libmpg123), you get MPG123_ERR returned and can query the detailed\n *  cause from the handle. Only on MPG123_OK there will an open file that you\n *  then close using mpg123_close(), or implicitly on mpg123_delete() or the next\n *  call to open another file.\n *\n *  So, for your usual CD rip collection, you could use\n *\n *    mpg123_open_fixed(mh, path, MPG123_STEREO, MPG123_ENC_SIGNED_16)\n *\n *  and be happy calling mpg123_getformat() to verify 44100 Hz rate, then just\n *  playing away with mpg123_read(). The occasional mono file, or MP2 file,\n *  will also be decoded without you really noticing. Just the speed could be\n *  wrong if you do not care about sample rate at all.\n *  \\param mh handle\n *  \\param path filesystem path\n *  \\param channels allowed channel count, either 1 (MPG123_MONO) or\n *    2 (MPG123_STEREO), or bitwise or of them, but then you're halfway back to\n *    calling mpg123_format() again;-)\n *  \\param encoding a definite encoding from enum mpg123_enc_enum\n *    or a bitmask like for mpg123_format(), defeating the purpose somewhat\n */\nMPG123_EXPORT int mpg123_open_fixed(mpg123_handle *mh, const char *path\n,\tint channels, int encoding);\n\n/** Open and prepare to decode the specified file by filesystem path.\n *  This does not open HTTP urls; libmpg123 contains no networking code.\n *  If you want to decode internet streams, use mpg123_open_fd() or mpg123_open_feed().\n *  \\param mh handle\n *  \\param path filesystem path\n *  \\return MPG123_OK on success\n */\nMPG123_EXPORT int mpg123_open(mpg123_handle *mh, const char *path);\n\n/** Use an already opened file descriptor as the bitstream input\n *  mpg123_close() will _not_ close the file descriptor.\n *  \\param mh handle\n *  \\param fd file descriptor\n *  \\return MPG123_OK on success\n */\nMPG123_EXPORT int mpg123_open_fd(mpg123_handle *mh, int fd);\n\n/** Use an opaque handle as bitstream input. This works only with the\n *  replaced I/O from mpg123_replace_reader_handle()!\n *  mpg123_close() will call the cleanup callback for your handle (if you gave one).\n *  \\param mh handle\n *  \\param iohandle your handle\n *  \\return MPG123_OK on success\n */\nMPG123_EXPORT int mpg123_open_handle(mpg123_handle *mh, void *iohandle);\n\n/** Open a new bitstream and prepare for direct feeding\n *  This works together with mpg123_decode(); you are responsible for reading and feeding the input bitstream.\n *  Also, you are expected to handle ICY metadata extraction yourself. This\n *  input method does not handle MPG123_ICY_INTERVAL. It does parse ID3 frames, though.\n *  \\param mh handle\n *  \\return MPG123_OK on success\n */\nMPG123_EXPORT int mpg123_open_feed(mpg123_handle *mh);\n\n/** Closes the source, if libmpg123 opened it.\n *  \\param mh handle\n *  \\return MPG123_OK on success\n */\nMPG123_EXPORT int mpg123_close(mpg123_handle *mh);\n\n/** Read from stream and decode up to outmemsize bytes.\n *\n *  Note: The type of outmemory changed to a void pointer in mpg123 1.26.0\n *  (API version 45).\n *\n *  \\param mh handle\n *  \\param outmemory address of output buffer to write to\n *  \\param outmemsize maximum number of bytes to write\n *  \\param done address to store the number of actually decoded bytes to\n *  \\return MPG123_OK or error/message code\n */\nMPG123_EXPORT int mpg123_read(mpg123_handle *mh\n,\tvoid *outmemory, size_t outmemsize, size_t *done );\n\n/** Feed data for a stream that has been opened with mpg123_open_feed().\n *  It's give and take: You provide the bytestream, mpg123 gives you the decoded samples.\n *  \\param mh handle\n *  \\param in input buffer\n *  \\param size number of input bytes\n *  \\return MPG123_OK or error/message code.\n */\nMPG123_EXPORT int mpg123_feed( mpg123_handle *mh\n,\tconst unsigned char *in, size_t size );\n\n/** Decode MPEG Audio from inmemory to outmemory. \n *  This is very close to a drop-in replacement for old mpglib.\n *  When you give zero-sized output buffer the input will be parsed until \n *  decoded data is available. This enables you to get MPG123_NEW_FORMAT (and query it) \n *  without taking decoded data.\n *  Think of this function being the union of mpg123_read() and mpg123_feed() (which it actually is, sort of;-).\n *  You can actually always decide if you want those specialized functions in separate steps or one call this one here.\n *\n *  Note: The type of outmemory changed to a void pointer in mpg123 1.26.0\n *  (API version 45).\n *\n *  \\param mh handle\n *  \\param inmemory input buffer\n *  \\param inmemsize number of input bytes\n *  \\param outmemory output buffer\n *  \\param outmemsize maximum number of output bytes\n *  \\param done address to store the number of actually decoded bytes to\n *  \\return error/message code (watch out especially for MPG123_NEED_MORE)\n */\nMPG123_EXPORT int mpg123_decode( mpg123_handle *mh\n,\tconst unsigned char *inmemory, size_t inmemsize\n,\tvoid *outmemory, size_t outmemsize, size_t *done );\n\n/** Decode next MPEG frame to internal buffer\n *  or read a frame and return after setting a new format.\n *  \\param mh handle\n *  \\param num current frame offset gets stored there\n *  \\param audio This pointer is set to the internal buffer to read the decoded audio from.\n *  \\param bytes number of output bytes ready in the buffer\n *  \\return MPG123_OK or error/message code\n */\nMPG123_EXPORT int mpg123_decode_frame( mpg123_handle *mh\n,\toff_t *num, unsigned char **audio, size_t *bytes );\n\n/** Decode current MPEG frame to internal buffer.\n * Warning: This is experimental API that might change in future releases!\n * Please watch mpg123 development closely when using it.\n *  \\param mh handle\n *  \\param num last frame offset gets stored there\n *  \\param audio this pointer is set to the internal buffer to read the decoded audio from.\n *  \\param bytes number of output bytes ready in the buffer\n *  \\return MPG123_OK or error/message code\n */\nMPG123_EXPORT int mpg123_framebyframe_decode( mpg123_handle *mh\n,\toff_t *num, unsigned char **audio, size_t *bytes );\n\n/** Find, read and parse the next mp3 frame\n * Warning: This is experimental API that might change in future releases!\n * Please watch mpg123 development closely when using it.\n *  \\param mh handle\n *  \\return MPG123_OK or error/message code\n */\nMPG123_EXPORT int mpg123_framebyframe_next(mpg123_handle *mh);\n\n/** Get access to the raw input data for the last parsed frame.\n * This gives you a direct look (and write access) to the frame body data.\n * Together with the raw header, you can reconstruct the whole raw MPEG stream without junk and meta data, or play games by actually modifying the frame body data before decoding this frame (mpg123_framebyframe_decode()).\n * A more sane use would be to use this for CRC checking (see mpg123_info() and MPG123_CRC), the first two bytes of the body make up the CRC16 checksum, if present.\n * You can provide NULL for a parameter pointer when you are not interested in the value.\n *\n * \\param mh handle\n * \\param header the 4-byte MPEG header\n * \\param bodydata pointer to the frame body stored in the handle (without the header)\n * \\param bodybytes size of frame body in bytes (without the header)\n * \\return MPG123_OK if there was a yet un-decoded frame to get the\n *    data from, MPG123_BAD_HANDLE or MPG123_ERR otherwise (without further\n *    explanation, the error state of the mpg123_handle is not modified by\n *    this function).\n */\nMPG123_EXPORT int mpg123_framedata( mpg123_handle *mh\n,\tunsigned long *header, unsigned char **bodydata, size_t *bodybytes );\n\n/** Get the input position (byte offset in stream) of the last parsed frame.\n *  This can be used for external seek index building, for example.\n *  It just returns the internally stored offset, regardless of validity --\n *  you ensure that a valid frame has been parsed before!\n * \\param mh handle\n * \\return byte offset in stream\n */\nMPG123_EXPORT off_t mpg123_framepos(mpg123_handle *mh);\n\n/*@}*/\n\n\n/** \\defgroup mpg123_seek mpg123 position and seeking\n *\n * Functions querying and manipulating position in the decoded audio bitstream.\n * The position is measured in decoded audio samples, or MPEG frame offset for the specific functions.\n * If gapless code is in effect, the positions are adjusted to compensate the skipped padding/delay - meaning, you should not care about that at all and just use the position defined for the samples you get out of the decoder;-)\n * The general usage is modelled after stdlib's ftell() and fseek().\n * Especially, the whence parameter for the seek functions has the same meaning as the one for fseek() and needs the same constants from stdlib.h: \n * - SEEK_SET: set position to (or near to) specified offset\n * - SEEK_CUR: change position by offset from now\n * - SEEK_END: set position to offset from end\n *\n * Note that sample-accurate seek only works when gapless support has been enabled at compile time; seek is frame-accurate otherwise.\n * Also, really sample-accurate seeking (meaning that you get the identical sample value after seeking compared to plain decoding up to the position) is only guaranteed when you do not mess with the position code by using MPG123_UPSPEED, MPG123_DOWNSPEED or MPG123_START_FRAME. The first two mainly should cause trouble with NtoM resampling, but in any case with these options in effect, you have to keep in mind that the sample offset is not the same as counting the samples you get from decoding since mpg123 counts the skipped samples, too (or the samples played twice only once)!\n * Short: When you care about the sample position, don't mess with those parameters;-)\n * Also, seeking is not guaranteed to work for all streams (underlying stream may not support it).\n * And yet another caveat: If the stream is concatenated out of differing pieces (Frankenstein stream), seeking may suffer, too.\n *\n * @{\n */\n\n/** Returns the current position in samples.\n *  On the next successful read, you'd get that sample.\n *  \\param mh handle\n *  \\return sample offset or MPG123_ERR (null handle)\n */\nMPG123_EXPORT off_t mpg123_tell(mpg123_handle *mh);\n\n/** Returns the frame number that the next read will give you data from.\n *  \\param mh handle\n *  \\return frame offset or MPG123_ERR (null handle)\n */\nMPG123_EXPORT off_t mpg123_tellframe(mpg123_handle *mh);\n\n/** Returns the current byte offset in the input stream.\n *  \\param mh handle\n *  \\return byte offset or MPG123_ERR (null handle)\n */\nMPG123_EXPORT off_t mpg123_tell_stream(mpg123_handle *mh);\n\n/** Seek to a desired sample offset.\n *  Usage is modelled afer the standard lseek().\n * \\param mh handle\n * \\param sampleoff offset in PCM samples\n * \\param whence one of SEEK_SET, SEEK_CUR or SEEK_END\n * \\return The resulting offset >= 0 or error/message code\n */\nMPG123_EXPORT off_t mpg123_seek( mpg123_handle *mh\n,\toff_t sampleoff, int whence );\n\n/** Seek to a desired sample offset in data feeding mode. \n *  This just prepares things to be right only if you ensure that the next chunk of input data will be from input_offset byte position.\n *  \\param mh handle\n *  \\param sampleoff offset in PCM samples\n *  \\param whence one of SEEK_SET, SEEK_CUR or SEEK_END\n *  \\param input_offset The position it expects to be at the \n *                      next time data is fed to mpg123_decode().\n *  \\return The resulting offset >= 0 or error/message code */\nMPG123_EXPORT off_t mpg123_feedseek( mpg123_handle *mh\n,\toff_t sampleoff, int whence, off_t *input_offset );\n\n/** Seek to a desired MPEG frame offset.\n *  Usage is modelled afer the standard lseek().\n * \\param mh handle\n * \\param frameoff offset in MPEG frames\n * \\param whence one of SEEK_SET, SEEK_CUR or SEEK_END\n * \\return The resulting offset >= 0 or error/message code */\nMPG123_EXPORT off_t mpg123_seek_frame( mpg123_handle *mh\n,\toff_t frameoff, int whence );\n\n/** Return a MPEG frame offset corresponding to an offset in seconds.\n *  This assumes that the samples per frame do not change in the file/stream, which is a good assumption for any sane file/stream only.\n *  \\return frame offset >= 0 or error/message code */\nMPG123_EXPORT off_t mpg123_timeframe(mpg123_handle *mh, double sec);\n\n/** Give access to the frame index table that is managed for seeking.\n *  You are asked not to modify the values... Use mpg123_set_index to set the\n *  seek index\n *  \\param mh handle\n *  \\param offsets pointer to the index array\n *  \\param step one index byte offset advances this many MPEG frames\n *  \\param fill number of recorded index offsets; size of the array\n *  \\return MPG123_OK on success\n */\nMPG123_EXPORT int mpg123_index( mpg123_handle *mh\n,\toff_t **offsets, off_t *step, size_t *fill );\n\n/** Set the frame index table\n *  Setting offsets to NULL and fill > 0 will allocate fill entries. Setting offsets\n *  to NULL and fill to 0 will clear the index and free the allocated memory used by the index.\n *  \\param mh handle\n *  \\param offsets pointer to the index array\n *  \\param step    one index byte offset advances this many MPEG frames\n *  \\param fill    number of recorded index offsets; size of the array\n *  \\return MPG123_OK on success\n */\nMPG123_EXPORT int mpg123_set_index( mpg123_handle *mh\n,\toff_t *offsets, off_t step, size_t fill );\n\n/** An old crutch to keep old mpg123 binaries happy.\n *  WARNING: This function is there only to avoid runtime linking errors with\n *  standalone mpg123 before version 1.23.0 (if you strangely update the\n *  library but not the end-user program) and actually is broken\n *  for various cases (p.ex. 24 bit output). Do never use. It might eventually\n *  be purged from the library.\n */\nMPG123_EXPORT int mpg123_position( mpg123_handle *mh, off_t frame_offset, off_t buffered_bytes, off_t *current_frame, off_t *frames_left, double *current_seconds, double *seconds_left);\n\n/*@}*/\n\n\n/** \\defgroup mpg123_voleq mpg123 volume and equalizer\n *\n * @{\n */\n\n/** another channel enumeration, for left/right choice */\nenum mpg123_channels\n{\n\t MPG123_LEFT=0x1\t/**< The Left Channel. */\n\t,MPG123_RIGHT=0x2\t/**< The Right Channel. */\n\t,MPG123_LR=0x3\t/**< Both left and right channel; same as MPG123_LEFT|MPG123_RIGHT */\n};\n\n/** Set the 32 Band Audio Equalizer settings.\n *  \\param mh handle\n *  \\param channel Can be MPG123_LEFT, MPG123_RIGHT or MPG123_LEFT|MPG123_RIGHT for both.\n *  \\param band The equaliser band to change (from 0 to 31)\n *  \\param val The (linear) adjustment factor.\n *  \\return MPG123_OK on success\n */\nMPG123_EXPORT int mpg123_eq( mpg123_handle *mh\n,\tenum mpg123_channels channel, int band, double val );\n\n/** Get the 32 Band Audio Equalizer settings.\n *  \\param mh handle\n *  \\param channel Can be MPG123_LEFT, MPG123_RIGHT or MPG123_LEFT|MPG123_RIGHT for (arithmetic mean of) both.\n *  \\param band The equaliser band to change (from 0 to 31)\n *  \\return The (linear) adjustment factor (zero for pad parameters) */\nMPG123_EXPORT double mpg123_geteq(mpg123_handle *mh\n                                 , enum mpg123_channels channel, int band);\n\n/** Reset the 32 Band Audio Equalizer settings to flat\n *  \\param mh handle\n *  \\return MPG123_OK on success\n */\nMPG123_EXPORT int mpg123_reset_eq(mpg123_handle *mh);\n\n/** Set the absolute output volume including the RVA setting, \n *  vol<0 just applies (a possibly changed) RVA setting.\n *  \\param mh handle\n *  \\param vol volume value (linear factor)\n *  \\return MPG123_OK on success\n */\nMPG123_EXPORT int mpg123_volume(mpg123_handle *mh, double vol);\n\n/** Adjust output volume including the RVA setting by chosen amount\n *  \\param mh handle\n *  \\param change volume value (linear factor increment)\n *  \\return MPG123_OK on success\n */\nMPG123_EXPORT int mpg123_volume_change(mpg123_handle *mh, double change);\n\n/** Return current volume setting, the actual value due to RVA, and the RVA \n *  adjustment itself. It's all as double float value to abstract the sample \n *  format. The volume values are linear factors / amplitudes (not percent) \n *  and the RVA value is in decibels.\n *  \\param mh handle\n *  \\param base return address for base volume (linear factor)\n *  \\param really return address for actual volume (linear factor)\n *  \\param rva_db return address for RVA value (decibels)\n *  \\return MPG123_OK on success\n */\nMPG123_EXPORT int mpg123_getvolume(mpg123_handle *mh, double *base, double *really, double *rva_db);\n\n/* TODO: Set some preamp in addition / to replace internal RVA handling? */\n\n/*@}*/\n\n\n/** \\defgroup mpg123_status mpg123 status and information\n *\n * @{\n */\n\n/** Enumeration of the mode types of Variable Bitrate */\nenum mpg123_vbr {\n\tMPG123_CBR=0,\t/**< Constant Bitrate Mode (default) */\n\tMPG123_VBR,\t\t/**< Variable Bitrate Mode */\n\tMPG123_ABR\t\t/**< Average Bitrate Mode */\n};\n\n/** Enumeration of the MPEG Versions */\nenum mpg123_version {\n\tMPG123_1_0=0,\t/**< MPEG Version 1.0 */\n\tMPG123_2_0,\t\t/**< MPEG Version 2.0 */\n\tMPG123_2_5\t\t/**< MPEG Version 2.5 */\n};\n\n\n/** Enumeration of the MPEG Audio mode.\n *  Only the mono mode has 1 channel, the others have 2 channels. */\nenum mpg123_mode {\n\tMPG123_M_STEREO=0,\t/**< Standard Stereo. */\n\tMPG123_M_JOINT,\t\t/**< Joint Stereo. */\n\tMPG123_M_DUAL,\t\t/**< Dual Channel. */\n\tMPG123_M_MONO\t\t/**< Single Channel. */\n};\n\n\n/** Enumeration of the MPEG Audio flag bits */\nenum mpg123_flags {\n\tMPG123_CRC=0x1,\t\t\t/**< The bitstream is error protected using 16-bit CRC. */\n\tMPG123_COPYRIGHT=0x2,\t/**< The bitstream is copyrighted. */\n\tMPG123_PRIVATE=0x4,\t\t/**< The private bit has been set. */\n\tMPG123_ORIGINAL=0x8\t/**< The bitstream is an original, not a copy. */\n};\n\n/** Data structure for storing information about a frame of MPEG Audio */\nstruct mpg123_frameinfo\n{\n\tenum mpg123_version version;\t/**< The MPEG version (1.0/2.0/2.5). */\n\tint layer;\t\t\t\t\t\t/**< The MPEG Audio Layer (MP1/MP2/MP3). */\n\tlong rate; \t\t\t\t\t\t/**< The sampling rate in Hz. */\n\tenum mpg123_mode mode;\t\t\t/**< The audio mode (Mono, Stereo, Joint-stero, Dual Channel). */\n\tint mode_ext;\t\t\t\t\t/**< The mode extension bit flag. */\n\tint framesize;\t\t\t\t\t/**< The size of the frame (in bytes, including header). */\n\tenum mpg123_flags flags;\t\t/**< MPEG Audio flag bits. Just now I realize that it should be declared as int, not enum. It's a bitwise combination of the enum values. */\n\tint emphasis;\t\t\t\t\t/**< The emphasis type. */\n\tint bitrate;\t\t\t\t\t/**< Bitrate of the frame (kbps). */\n\tint abr_rate;\t\t\t\t\t/**< The target average bitrate. */\n\tenum mpg123_vbr vbr;\t\t\t/**< The VBR mode. */\n};\n\n/** Data structure for even more detailed information out of the decoder,\n  * for MPEG layer III only.\n  * This was added to support the frame analyzer by the Lame project and\n  * just follows what was used there before. You know what the fields mean\n  * if you want use this structure. */\nstruct mpg123_moreinfo\n{\n\tdouble xr[2][2][576];\n\tdouble sfb[2][2][22];  /* [2][2][SBMAX_l] */\n\tdouble sfb_s[2][2][3*13]; /* [2][2][3*SBMAX_s] */\n\tint qss[2][2];\n\tint big_values[2][2];\n\tint sub_gain[2][2][3];\n\tint scalefac_scale[2][2];\n\tint preflag[2][2];\n\tint blocktype[2][2];\n\tint mixed[2][2];\n\tint mainbits[2][2];\n\tint sfbits[2][2];\n\tint scfsi[2];\n\tint maindata;\n\tint padding;\n};\n\n/** Get frame information about the MPEG audio bitstream and store it in a mpg123_frameinfo structure.\n *  \\param mh handle\n *  \\param mi address of existing frameinfo structure to write to\n *  \\return MPG123_OK on success\n */\nMPG123_EXPORT int mpg123_info(mpg123_handle *mh, struct mpg123_frameinfo *mi);\n\n/** Trigger collection of additional decoder information while decoding.\n *  \\param mh handle\n *  \\param mi pointer to data storage (NULL to disable collection)\n *  \\return MPG123_OK if the collection was enabled/disabled as desired, MPG123_ERR\n *    otherwise (e.g. if the feature is disabled)\n */\nMPG123_EXPORT int mpg123_set_moreinfo( mpg123_handle *mh\n,\tstruct mpg123_moreinfo *mi );\n\n/** Get the safe output buffer size for all cases\n *  (when you want to replace the internal buffer)\n *  \\return safe buffer size\n */\nMPG123_EXPORT size_t mpg123_safe_buffer(void);\n\n/** Make a full parsing scan of each frame in the file. ID3 tags are found. An\n *  accurate length value is stored. Seek index will be filled. A seek back to\n *  current position is performed. At all, this function refuses work when\n *  stream is not seekable.\n *  \\param mh handle\n *  \\return MPG123_OK on success\n */\nMPG123_EXPORT int mpg123_scan(mpg123_handle *mh);\n\n/** Return, if possible, the full (expected) length of current track in\n *  MPEG frames.\n * \\param mh handle\n * \\return length >= 0 or MPG123_ERR if there is no length guess possible.\n */\nMPG123_EXPORT off_t mpg123_framelength(mpg123_handle *mh);\n\n/** Return, if possible, the full (expected) length of current\n *  track in samples (PCM frames).\n *\n *  This relies either on an Info frame at the beginning or a previous\n *  call to mpg123_scan() to get the real number of MPEG frames in a\n *  file. It will guess based on file size if neither Info frame nor\n *  scan data are present. In any case, there is no guarantee that the\n *  decoder will not give you more data, for example in case the open\n *  file gets appended to during decoding.\n * \\param mh handle\n * \\return length >= 0 or MPG123_ERR if there is no length guess possible.\n */\nMPG123_EXPORT off_t mpg123_length(mpg123_handle *mh);\n\n/** Override the value for file size in bytes.\n *  Useful for getting sensible track length values in feed mode or for HTTP streams.\n *  \\param mh handle\n *  \\param size file size in bytes\n *  \\return MPG123_OK on success\n */\nMPG123_EXPORT int mpg123_set_filesize(mpg123_handle *mh, off_t size);\n\n/** Get MPEG frame duration in seconds.\n *  \\param mh handle\n *  \\return frame duration in seconds, <0 on error\n */\nMPG123_EXPORT double mpg123_tpf(mpg123_handle *mh);\n\n/** Get MPEG frame duration in samples.\n *  \\param mh handle\n *  \\return samples per frame for the most recently parsed frame; <0 on errors\n */\nMPG123_EXPORT int mpg123_spf(mpg123_handle *mh);\n\n/** Get and reset the clip count.\n *  \\param mh handle\n *  \\return count of clipped samples\n */\nMPG123_EXPORT long mpg123_clip(mpg123_handle *mh);\n\n\n/** The key values for state information from mpg123_getstate(). */\nenum mpg123_state\n{\n\t MPG123_ACCURATE = 1 /**< Query if positons are currently accurate (integer value, 0 if false, 1 if true). */\n\t,MPG123_BUFFERFILL   /**< Get fill of internal (feed) input buffer as integer byte count returned as long and as double. An error is returned on integer overflow while converting to (signed) long, but the returned floating point value shold still be fine. */\n\t,MPG123_FRANKENSTEIN /**< Stream consists of carelessly stitched together files. Seeking may yield unexpected results (also with MPG123_ACCURATE, it may be confused). */\n\t,MPG123_FRESH_DECODER /**< Decoder structure has been updated, possibly indicating changed stream (integer value, 0 if false, 1 if true). Flag is cleared after retrieval. */\n\t,MPG123_ENC_DELAY /** Encoder delay read from Info tag (layer III, -1 if unknown). */\n\t,MPG123_ENC_PADDING /** Encoder padding read from Info tag (layer III, -1 if unknown). */\n\t,MPG123_DEC_DELAY /** Decoder delay (for layer III only, -1 otherwise). */\n};\n\n/** Get various current decoder/stream state information.\n *  \\param mh handle\n *  \\param key the key to identify the information to give.\n *  \\param val the address to return (long) integer values to\n *  \\param fval the address to return floating point values to\n *  \\return MPG123_OK on success\n */\nMPG123_EXPORT int mpg123_getstate( mpg123_handle *mh\n,\tenum mpg123_state key, long *val, double *fval );\n\n/*@}*/\n\n\n/** \\defgroup mpg123_metadata mpg123 metadata handling\n *\n * Functions to retrieve the metadata from MPEG Audio files and streams.\n * Also includes string handling functions.\n *\n * @{\n */\n\n/** Data structure for storing strings in a safer way than a standard C-String.\n *  Can also hold a number of null-terminated strings. */\ntypedef struct \n{\n\tchar* p;     /**< pointer to the string data */\n\tsize_t size; /**< raw number of bytes allocated */\n\tsize_t fill; /**< number of used bytes (including closing zero byte) */\n} mpg123_string;\n\n/** Allocate and intialize a new string.\n *  \\param val optional initial string value (can be NULL)\n */\nMPG123_EXPORT mpg123_string* mpg123_new_string(const char* val);\n\n/** Free memory of contents and the string structure itself.\n *  \\param sb string handle\n */\nMPG123_EXPORT void mpg123_delete_string(mpg123_string* sb);\n\n/** Initialize an existing mpg123_string structure to {NULL, 0, 0}.\n *  If you hand in a NULL pointer here, your program should crash. The other\n *  string functions are more forgiving, but this one here is too basic.\n *  \\param sb string handle (address of existing structure on your side)\n */\nMPG123_EXPORT void mpg123_init_string(mpg123_string* sb);\n\n/** Free-up memory of the contents of an mpg123_string (not the struct itself).\n *  This also calls mpg123_init_string() and hence is safe to be called\n *  repeatedly.\n *  \\param sb string handle\n */\nMPG123_EXPORT void mpg123_free_string(mpg123_string* sb);\n\n/** Change the size of a mpg123_string\n *  \\param sb string handle\n *  \\param news new size in bytes\n *  \\return 0 on error, 1 on success\n */\nMPG123_EXPORT int mpg123_resize_string(mpg123_string* sb, size_t news);\n\n/** Increase size of a mpg123_string if necessary (it may stay larger).\n *  Note that the functions for adding and setting in current libmpg123\n *  use this instead of mpg123_resize_string().\n *  That way, you can preallocate memory and safely work afterwards with\n *  pieces.\n *  \\param sb string handle\n *  \\param news new minimum size\n *  \\return 0 on error, 1 on success\n */\nMPG123_EXPORT int mpg123_grow_string(mpg123_string* sb, size_t news);\n\n/** Copy the contents of one mpg123_string string to another.\n *  Yes the order of arguments is reversed compated to memcpy().\n *  \\param from string handle\n *  \\param to string handle\n *  \\return 0 on error, 1 on success\n */\nMPG123_EXPORT int mpg123_copy_string(mpg123_string* from, mpg123_string* to);\n\n/** Move the contents of one mpg123_string string to another.\n *  This frees any memory associated with the target and moves over the\n *  pointers from the source, leaving the source without content after\n *  that. The only possible error is that you hand in NULL pointers.\n *  If you handed in a valid source, its contents will be gone, even if\n *  there was no target to move to. If you hand in a valid target, its\n *  original contents will also always be gone, to be replaced with the\n *  source's contents if there was some.\n *  \\param from source string handle\n *  \\param to   target string handle\n *  \\return 0 on error, 1 on success\n */\nMPG123_EXPORT int mpg123_move_string(mpg123_string* from, mpg123_string* to);\n\n/** Append a C-String to an mpg123_string\n *  \\param sb string handle\n *  \\param stuff to append\n *  \\return 0 on error, 1 on success\n */\nMPG123_EXPORT int mpg123_add_string(mpg123_string* sb, const char* stuff);\n\n/** Append a C-substring to an mpg123 string\n *  \\param sb string handle\n *  \\param stuff content to copy\n *  \\param from offset to copy from\n *  \\param count number of characters to copy (a null-byte is always appended)\n *  \\return 0 on error, 1 on success\n */\nMPG123_EXPORT int mpg123_add_substring( mpg123_string *sb\n,\tconst char *stuff, size_t from, size_t count );\n\n/** Set the content of a mpg123_string to a C-string\n *  \\param sb string handle\n *  \\param stuff content to copy\n *  \\return 0 on error, 1 on success\n */\nMPG123_EXPORT int mpg123_set_string(mpg123_string* sb, const char* stuff);\n\n/** Set the content of a mpg123_string to a C-substring\n *  \\param sb string handle\n *  \\param stuff the future content\n *  \\param from offset to copy from\n *  \\param count number of characters to copy (a null-byte is always appended)\n *  \\return 0 on error, 1 on success\n */\nMPG123_EXPORT int mpg123_set_substring( mpg123_string *sb\n,\tconst char *stuff, size_t from, size_t count );\n\n/** Count characters in a mpg123 string (non-null bytes or Unicode points).\n *  This function is of limited use, as it does just count code points\n *  encoded in an UTF-8 string, only loosely related to the count of visible\n *  characters. Get your full Unicode handling support elsewhere.\n *  \\param sb string handle\n *  \\param utf8 a flag to tell if the string is in utf8 encoding\n *  \\return character count\n*/\nMPG123_EXPORT size_t mpg123_strlen(mpg123_string *sb, int utf8);\n\n/** Remove trailing \\\\r and \\\\n, if present.\n *  \\param sb string handle\n *  \\return 0 on error, 1 on success\n */\nMPG123_EXPORT int mpg123_chomp_string(mpg123_string *sb);\n\n/** Determine if two strings contain the same data.\n *  This only returns 1 if both given handles are non-NULL and\n *  if they are filled with the same bytes.\n *  \\param a first string handle\n *  \\param b second string handle\n *  \\return 0 for different strings, 1 for identical\n */\nMPG123_EXPORT int mpg123_same_string(mpg123_string *a, mpg123_string *b);\n\n/** The mpg123 text encodings. This contains encodings we encounter in ID3 tags or ICY meta info. */\nenum mpg123_text_encoding\n{\n\t mpg123_text_unknown  = 0 /**< Unkown encoding... mpg123_id3_encoding can return that on invalid codes. */\n\t,mpg123_text_utf8     = 1 /**< UTF-8 */\n\t,mpg123_text_latin1   = 2 /**< ISO-8859-1. Note that sometimes latin1 in ID3 is abused for totally different encodings. */\n\t,mpg123_text_icy      = 3 /**< ICY metadata encoding, usually CP-1252 but we take it as UTF-8 if it qualifies as such. */\n\t,mpg123_text_cp1252   = 4 /**< Really CP-1252 without any guessing. */\n\t,mpg123_text_utf16    = 5 /**< Some UTF-16 encoding. The last of a set of leading BOMs (byte order mark) rules.\n\t                           *   When there is no BOM, big endian ordering is used. Note that UCS-2 qualifies as UTF-8 when\n\t                           *   you don't mess with the reserved code points. If you want to decode little endian data\n\t                           *   without BOM you need to prepend 0xff 0xfe yourself. */\n\t,mpg123_text_utf16bom = 6 /**< Just an alias for UTF-16, ID3v2 has this as distinct code. */\n\t,mpg123_text_utf16be  = 7 /**< Another alias for UTF16 from ID3v2. Note, that, because of the mess that is reality,\n\t                           *   BOMs are used if encountered. There really is not much distinction between the UTF16 types for mpg123\n\t                           *   One exception: Since this is seen in ID3v2 tags, leading null bytes are skipped for all other UTF16\n\t                           *   types (we expect a BOM before real data there), not so for utf16be!*/\n\t,mpg123_text_max      = 7 /**< Placeholder for the maximum encoding value. */\n};\n\n/** The encoding byte values from ID3v2. */\nenum mpg123_id3_enc\n{\n\t mpg123_id3_latin1   = 0 /**< Note: This sometimes can mean anything in practice... */\n\t,mpg123_id3_utf16bom = 1 /**< UTF16, UCS-2 ... it's all the same for practical purposes. */\n\t,mpg123_id3_utf16be  = 2 /**< Big-endian UTF-16, BOM see note for mpg123_text_utf16be. */\n\t,mpg123_id3_utf8     = 3 /**< Our lovely overly ASCII-compatible 8 byte encoding for the world. */\n\t,mpg123_id3_enc_max  = 3 /**< Placeholder to check valid range of encoding byte. */\n};\n\n/** Convert ID3 encoding byte to mpg123 encoding index.\n *  \\param id3_enc_byte the ID3 encoding code\n *  \\return the mpg123 encoding index\n */\n\nMPG123_EXPORT enum mpg123_text_encoding mpg123_enc_from_id3(unsigned char id3_enc_byte);\n\n/** Store text data in string, after converting to UTF-8 from indicated encoding\n *  A prominent error can be that you provided an unknown encoding value, or this build of libmpg123 lacks support for certain encodings (ID3 or ICY stuff missing).\n *  Also, you might want to take a bit of care with preparing the data; for example, strip leading zeroes (I have seen that).\n *  \\param sb  target string\n *  \\param enc mpg123 text encoding value\n *  \\param source source buffer with plain unsigned bytes (you might need to cast from signed char)\n *  \\param source_size number of bytes in the source buffer\n *  \\return 0 on error, 1 on success (on error, mpg123_free_string is called on sb)\n */\nMPG123_EXPORT int mpg123_store_utf8(mpg123_string *sb, enum mpg123_text_encoding enc, const unsigned char *source, size_t source_size);\n\n/** Sub data structure for ID3v2, for storing various text fields (including comments).\n *  This is for ID3v2 COMM, TXXX and all the other text fields.\n *  Only COMM, TXXX and USLT may have a description, only COMM and USLT\n *  have a language.\n *  You should consult the ID3v2 specification for the use of the various text fields\n * (\"frames\" in ID3v2 documentation, I use \"fields\" here to separate from MPEG frames). */\ntypedef struct\n{\n\tchar lang[3]; /**< Three-letter language code (not terminated). */\n\tchar id[4];   /**< The ID3v2 text field id, like TALB, TPE2, ... (4 characters, no string termination). */\n\tmpg123_string description; /**< Empty for the generic comment... */\n\tmpg123_string text;        /**< ... */\n} mpg123_text;\n\n/** The picture type values from ID3v2. */\nenum mpg123_id3_pic_type\n{\n\t mpg123_id3_pic_other          =  0 /**< see ID3v2 docs */\n\t,mpg123_id3_pic_icon           =  1 /**< see ID3v2 docs */\n\t,mpg123_id3_pic_other_icon     =  2 /**< see ID3v2 docs */\n\t,mpg123_id3_pic_front_cover    =  3 /**< see ID3v2 docs */\n\t,mpg123_id3_pic_back_cover     =  4 /**< see ID3v2 docs */\n\t,mpg123_id3_pic_leaflet        =  5 /**< see ID3v2 docs */\n\t,mpg123_id3_pic_media          =  6 /**< see ID3v2 docs */\n\t,mpg123_id3_pic_lead           =  7 /**< see ID3v2 docs */\n\t,mpg123_id3_pic_artist         =  8 /**< see ID3v2 docs */\n\t,mpg123_id3_pic_conductor      =  9 /**< see ID3v2 docs */\n\t,mpg123_id3_pic_orchestra      = 10 /**< see ID3v2 docs */\n\t,mpg123_id3_pic_composer       = 11 /**< see ID3v2 docs */\n\t,mpg123_id3_pic_lyricist       = 12 /**< see ID3v2 docs */\n\t,mpg123_id3_pic_location       = 13 /**< see ID3v2 docs */\n\t,mpg123_id3_pic_recording      = 14 /**< see ID3v2 docs */\n\t,mpg123_id3_pic_performance    = 15 /**< see ID3v2 docs */\n\t,mpg123_id3_pic_video          = 16 /**< see ID3v2 docs */\n\t,mpg123_id3_pic_fish           = 17 /**< see ID3v2 docs */\n\t,mpg123_id3_pic_illustration   = 18 /**< see ID3v2 docs */\n\t,mpg123_id3_pic_artist_logo    = 19 /**< see ID3v2 docs */\n\t,mpg123_id3_pic_publisher_logo = 20 /**< see ID3v2 docs */\n};\n\n/** Sub data structure for ID3v2, for storing picture data including comment.\n *  This is for the ID3v2 APIC field. You should consult the ID3v2 specification\n *  for the use of the APIC field (\"frames\" in ID3v2 documentation, I use \"fields\"\n *  here to separate from MPEG frames). */\ntypedef struct\n{\n\tchar type;                 /**< mpg123_id3_pic_type value */\n\tmpg123_string description; /**< description string */\n\tmpg123_string mime_type;   /**< MIME type */\n\tsize_t size;               /**< size in bytes */\n\tunsigned char* data;       /**< pointer to the image data */\n} mpg123_picture;\n\n/** Data structure for storing IDV3v2 tags.\n *  This structure is not a direct binary mapping with the file contents.\n *  The ID3v2 text frames are allowed to contain multiple strings.\n *  So check for null bytes until you reach the mpg123_string fill.\n *  All text is encoded in UTF-8. */\ntypedef struct\n{\n\tunsigned char version; /**< 3 or 4 for ID3v2.3 or ID3v2.4. */\n\tmpg123_string *title;   /**< Title string (pointer into text_list). */\n\tmpg123_string *artist;  /**< Artist string (pointer into text_list). */\n\tmpg123_string *album;   /**< Album string (pointer into text_list). */\n\tmpg123_string *year;    /**< The year as a string (pointer into text_list). */\n\tmpg123_string *genre;   /**< Genre String (pointer into text_list). The genre string(s) may very well need postprocessing, esp. for ID3v2.3. */\n\tmpg123_string *comment; /**< Pointer to last encountered comment text with empty description. */\n\t/* Encountered ID3v2 fields are appended to these lists.\n\t   There can be multiple occurences, the pointers above always point to the last encountered data. */\n\tmpg123_text    *comment_list; /**< Array of comments. */\n\tsize_t          comments;     /**< Number of comments. */\n\tmpg123_text    *text;         /**< Array of ID3v2 text fields (including USLT) */\n\tsize_t          texts;        /**< Numer of text fields. */\n\tmpg123_text    *extra;        /**< The array of extra (TXXX) fields. */\n\tsize_t          extras;       /**< Number of extra text (TXXX) fields. */\n\tmpg123_picture  *picture;     /**< Array of ID3v2 pictures fields (APIC).\n\t\tOnly populated if MPG123_PICTURE flag is set! */\n\tsize_t           pictures;    /**< Number of picture (APIC) fields. */\n} mpg123_id3v2;\n\n/** Data structure for ID3v1 tags (the last 128 bytes of a file).\n *  Don't take anything for granted (like string termination)!\n *  Also note the change ID3v1.1 did: comment[28] = 0; comment[29] = track_number\n *  It is your task to support ID3v1 only or ID3v1.1 ...*/\ntypedef struct\n{\n\tchar tag[3];         /**< Always the string \"TAG\", the classic intro. */\n\tchar title[30];      /**< Title string.  */\n\tchar artist[30];     /**< Artist string. */\n\tchar album[30];      /**< Album string. */\n\tchar year[4];        /**< Year string. */\n\tchar comment[30];    /**< Comment string. */\n\tunsigned char genre; /**< Genre index. */\n} mpg123_id3v1;\n\n#define MPG123_ID3     0x3 /**< 0011 There is some ID3 info. Also matches 0010 or NEW_ID3. */\n#define MPG123_NEW_ID3 0x1 /**< 0001 There is ID3 info that changed since last call to mpg123_id3. */\n#define MPG123_ICY     0xc /**< 1100 There is some ICY info. Also matches 0100 or NEW_ICY.*/\n#define MPG123_NEW_ICY 0x4 /**< 0100 There is ICY info that changed since last call to mpg123_icy. */\n\n/** Query if there is (new) meta info, be it ID3 or ICY (or something new in future).\n *  \\param mh handle\n *  \\return combination of flags, 0 on error (same as \"nothing new\")\n */\nMPG123_EXPORT int mpg123_meta_check(mpg123_handle *mh);\n\n/** Clean up meta data storage (ID3v2 and ICY), freeing memory.\n *  \\param mh handle\n */\nMPG123_EXPORT void mpg123_meta_free(mpg123_handle *mh);\n\n/** Point v1 and v2 to existing data structures wich may change on any next read/decode function call.\n *  v1 and/or v2 can be set to NULL when there is no corresponding data.\n *  \\return MPG123_OK on success\n */\nMPG123_EXPORT int mpg123_id3( mpg123_handle *mh\n,\tmpg123_id3v1 **v1, mpg123_id3v2 **v2 );\n\n/** Return pointers to and size of stored raw ID3 data if storage has\n *  been configured with MPG123_RAW_ID3 and stream parsing passed the\n *  metadata already. Null value with zero size is a possibility!\n *  The storage can change at any next API call.\n *  \\param v1 address to store pointer to v1 tag\n *  \\param v1_size size of v1 data in bytes\n *  \\param v2 address to store pointer to v2 tag\n *  \\param v2_size size of v2 data in bytes\n *  \\return MPG123_OK or MPG123_ERR. Only on MPG123_OK the output\n *          values are set.\n */\nMPG123_EXPORT int mpg123_id3_raw( mpg123_handle *mh\n,\tunsigned char **v1, size_t *v1_size\n,\tunsigned char **v2, size_t *v2_size );\n\n/** Point icy_meta to existing data structure wich may change on any next read/decode function call.\n *  \\param mh handle\n *  \\param icy_meta return address for ICY meta string (set to NULL if nothing there)\n *  \\return MPG123_OK on success\n */\nMPG123_EXPORT int mpg123_icy(mpg123_handle *mh, char **icy_meta);\n\n/** Decode from windows-1252 (the encoding ICY metainfo used) to UTF-8.\n *  Note that this is very similar to mpg123_store_utf8(&sb, mpg123_text_icy, icy_text, strlen(icy_text+1)) .\n *  \\param icy_text The input data in ICY encoding\n *  \\return pointer to newly allocated buffer with UTF-8 data (You free() it!) */\nMPG123_EXPORT char* mpg123_icy2utf8(const char* icy_text);\n\n\n/* @} */\n\n\n/** \\defgroup mpg123_advpar mpg123 advanced parameter API\n *\n *  Direct access to a parameter set without full handle around it.\n *\tPossible uses:\n *    - Influence behaviour of library _during_ initialization of handle (MPG123_VERBOSE).\n *    - Use one set of parameters for multiple handles.\n *\n *\tThe functions for handling mpg123_pars (mpg123_par() and mpg123_fmt() \n *  family) directly return a fully qualified mpg123 error code, the ones \n *  operating on full handles normally MPG123_OK or MPG123_ERR, storing the \n *  specific error code itseld inside the handle. \n *\n * @{\n */\n\n/** Opaque structure for the libmpg123 decoder parameters. */\nstruct mpg123_pars_struct;\n\n/** Opaque structure for the libmpg123 decoder parameters. */\ntypedef struct mpg123_pars_struct   mpg123_pars;\n\n/** Create a handle with preset parameters.\n *  \\param mp parameter handle\n *  \\param decoder decoder choice\n *  \\param error error code return address\n *  \\return mpg123 handle\n */\nMPG123_EXPORT mpg123_handle *mpg123_parnew( mpg123_pars *mp\n,\tconst char* decoder, int *error );\n\n/** Allocate memory for and return a pointer to a new mpg123_pars\n *  \\param error error code return address\n *  \\return new parameter handle\n */\nMPG123_EXPORT mpg123_pars *mpg123_new_pars(int *error);\n\n/** Delete and free up memory used by a mpg123_pars data structure\n *  \\param mp parameter handle\n */\nMPG123_EXPORT void mpg123_delete_pars(mpg123_pars* mp);\n\n/** Configure mpg123 parameters to accept no output format at all, \n *  use before specifying supported formats with mpg123_format\n *  \\param mp parameter handle\n *  \\return MPG123_OK on success\n */\nMPG123_EXPORT int mpg123_fmt_none(mpg123_pars *mp);\n\n/** Configure mpg123 parameters to accept all formats \n *  (also any custom rate you may set) -- this is default. \n *  \\param mp parameter handle\n *  \\return MPG123_OK on success\n */\nMPG123_EXPORT int mpg123_fmt_all(mpg123_pars *mp);\n\n/** Set the audio format support of a mpg123_pars in detail:\n * \\param mp parameter handle\n * \\param rate The sample rate value (in Hertz).\n * \\param channels A combination of MPG123_STEREO and MPG123_MONO.\n * \\param encodings A combination of accepted encodings for rate and channels,\n *                  p.ex MPG123_ENC_SIGNED16|MPG123_ENC_ULAW_8 (or 0 for no\n *                  support).\n * \\return MPG123_OK on success\n*/\nMPG123_EXPORT int mpg123_fmt(mpg123_pars *mp\n,\tlong rate, int channels, int encodings);\n\n/** Set the audio format support of a mpg123_pars in detail:\n * \\param mp parameter handle\n * \\param rate The sample rate value (in Hertz). Special value 0 means\n *             all rates (reason for this variant of mpg123_fmt).\n * \\param channels A combination of MPG123_STEREO and MPG123_MONO.\n * \\param encodings A combination of accepted encodings for rate and channels,\n *                  p.ex MPG123_ENC_SIGNED16|MPG123_ENC_ULAW_8 (or 0 for no\n *                  support).\n * \\return MPG123_OK on success\n*/\nMPG123_EXPORT int mpg123_fmt2(mpg123_pars *mp\n,\tlong rate, int channels, int encodings);\n\n/** Check to see if a specific format at a specific rate is supported\n *  by mpg123_pars.\n *  \\param mp parameter handle\n *  \\param rate sampling rate\n *  \\param encoding encoding\n *  \\return 0 for no support (that includes invalid parameters), MPG123_STEREO, \n *          MPG123_MONO or MPG123_STEREO|MPG123_MONO. */\nMPG123_EXPORT int mpg123_fmt_support(mpg123_pars *mp, long rate, int encoding);\n\n/** Set a specific parameter, for a specific mpg123_pars, using a parameter \n *  type key chosen from the mpg123_parms enumeration, to the specified value.\n *  \\param mp parameter handle\n *  \\param type parameter choice\n *  \\param value integer value\n *  \\param fvalue floating point value\n *  \\return MPG123_OK on success\n */\nMPG123_EXPORT int mpg123_par( mpg123_pars *mp\n,\tenum mpg123_parms type, long value, double fvalue );\n\n/** Get a specific parameter, for a specific mpg123_pars. \n *  See the mpg123_parms enumeration for a list of available parameters.\n *  \\param mp parameter handle\n *  \\param type parameter choice\n *  \\param value integer value return address\n *  \\param fvalue floating point value return address\n *  \\return MPG123_OK on success\n */\nMPG123_EXPORT int mpg123_getpar( mpg123_pars *mp\n,\tenum mpg123_parms type, long *value, double *fvalue);\n\n/* @} */\n\n\n/** \\defgroup mpg123_lowio mpg123 low level I/O\n  * You may want to do tricky stuff with I/O that does not work with mpg123's default file access or you want to make it decode into your own pocket...\n  *\n  * @{ */\n\n/** Replace default internal buffer with user-supplied buffer.\n  * Instead of working on it's own private buffer, mpg123 will directly use the one you provide for storing decoded audio.\n  * Note that the required buffer size could be bigger than expected from output\n  * encoding if libmpg123 has to convert from primary decoder output (p.ex. 32 bit\n  * storage for 24 bit output).\n  *\n  *  Note: The type of data changed to a void pointer in mpg123 1.26.0\n  *  (API version 45).\n  *\n  * \\param mh handle\n  * \\param data pointer to user buffer\n  * \\param size of buffer in bytes\n  * \\return MPG123_OK on success\n  */\nMPG123_EXPORT int mpg123_replace_buffer(mpg123_handle *mh\n,\tvoid *data, size_t size);\n\n/** The max size of one frame's decoded output with current settings.\n *  Use that to determine an appropriate minimum buffer size for decoding one frame.\n *  \\param mh handle\n *  \\return maximum decoded data size in bytes\n */\nMPG123_EXPORT size_t mpg123_outblock(mpg123_handle *mh);\n\n/** Replace low-level stream access functions; read and lseek as known in POSIX.\n *  You can use this to make any fancy file opening/closing yourself, \n *  using mpg123_open_fd() to set the file descriptor for your read/lseek\n *  (doesn't need to be a \"real\" file descriptor...).\n *  Setting a function to NULL means that the default internal read is \n *  used (active from next mpg123_open call on).\n *  Note: As it would be troublesome to mess with this while having a file open,\n *  this implies mpg123_close().\n * \\param mh handle\n * \\param r_read callback for reading (behaviour like POSIX read)\n * \\param r_lseek callback for seeking (like POSIX lseek)\n * \\return MPG123_OK on success\n */\nMPG123_EXPORT int mpg123_replace_reader( mpg123_handle *mh\n,\tssize_t (*r_read) (int, void *, size_t)\n,\toff_t (*r_lseek)(int, off_t, int)\n);\n\n/** Replace I/O functions with your own ones operating on some kind of\n *  handle instead of integer descriptors.\n *  The handle is a void pointer, so you can pass any data you want...\n *  mpg123_open_handle() is the call you make to use the I/O defined here.\n *  There is no fallback to internal read/seek here.\n *  Note: As it would be troublesome to mess with this while having a file open,\n *  this mpg123_close() is implied here.\n *  \\param mh handle\n *  \\param r_read callback for reading (behaviour like POSIX read)\n *  \\param r_lseek callback for seeking (like POSIX lseek)\n *  \\param cleanup A callback to clean up an I/O handle on mpg123_close,\n *         can be NULL for none (you take care of cleaning your handles).\n * \\return MPG123_OK on success\n */\nMPG123_EXPORT int mpg123_replace_reader_handle( mpg123_handle *mh\n,\tssize_t (*r_read) (void *, void *, size_t)\n,\toff_t (*r_lseek)(void *, off_t, int)\n,\tvoid (*cleanup)(void*) );\n\n/* @} */\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "vendor/openal-soft/COPYING",
    "content": "                  GNU LIBRARY GENERAL PUBLIC LICENSE\n                       Version 2, June 1991\n\n Copyright (C) 1991 Free Software Foundation, Inc.\n 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n[This is the first released version of the library GPL.  It is\n numbered 2 because it goes with version 2 of the ordinary GPL.]\n\n                            Preamble\n\n  The licenses for most software are designed to take away your\nfreedom to share and change it.  By contrast, the GNU General Public\nLicenses are intended to guarantee your freedom to share and change\nfree software--to make sure the software is free for all its users.\n\n  This license, the Library General Public License, applies to some\nspecially designated Free Software Foundation software, and to any\nother libraries whose authors decide to use it.  You can use it for\nyour libraries, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthis service if you wish), that you receive source code or can get it\nif you want it, that you can change the software or use pieces of it\nin new free programs; and that you know you can do these things.\n\n  To protect your rights, we need to make restrictions that forbid\nanyone to deny you these rights or to ask you to surrender the rights.\nThese restrictions translate to certain responsibilities for you if\nyou distribute copies of the library, or if you modify it.\n\n  For example, if you distribute copies of the library, whether gratis\nor for a fee, you must give the recipients all the rights that we gave\nyou.  You must make sure that they, too, receive or can get the source\ncode.  If you link a program with the library, you must provide\ncomplete object files to the recipients so that they can relink them\nwith the library, after making changes to the library and recompiling\nit.  And you must show them these terms so they know their rights.\n\n  Our method of protecting your rights has two steps: (1) copyright\nthe library, and (2) offer you this license which gives you legal\npermission to copy, distribute and/or modify the library.\n\n  Also, for each distributor's protection, we want to make certain\nthat everyone understands that there is no warranty for this free\nlibrary.  If the library is modified by someone else and passed on, we\nwant its recipients to know that what they have is not the original\nversion, so that any problems introduced by others will not reflect on\nthe original authors' reputations.\n\n  Finally, any free program is threatened constantly by software\npatents.  We wish to avoid the danger that companies distributing free\nsoftware will individually obtain patent licenses, thus in effect\ntransforming the program into proprietary software.  To prevent this,\nwe have made it clear that any patent must be licensed for everyone's\nfree use or not licensed at all.\n\n  Most GNU software, including some libraries, is covered by the ordinary\nGNU General Public License, which was designed for utility programs.  This\nlicense, the GNU Library General Public License, applies to certain\ndesignated libraries.  This license is quite different from the ordinary\none; be sure to read it in full, and don't assume that anything in it is\nthe same as in the ordinary license.\n\n  The reason we have a separate public license for some libraries is that\nthey blur the distinction we usually make between modifying or adding to a\nprogram and simply using it.  Linking a program with a library, without\nchanging the library, is in some sense simply using the library, and is\nanalogous to running a utility program or application program.  However, in\na textual and legal sense, the linked executable is a combined work, a\nderivative of the original library, and the ordinary General Public License\ntreats it as such.\n\n  Because of this blurred distinction, using the ordinary General\nPublic License for libraries did not effectively promote software\nsharing, because most developers did not use the libraries.  We\nconcluded that weaker conditions might promote sharing better.\n\n  However, unrestricted linking of non-free programs would deprive the\nusers of those programs of all benefit from the free status of the\nlibraries themselves.  This Library General Public License is intended to\npermit developers of non-free programs to use free libraries, while\npreserving your freedom as a user of such programs to change the free\nlibraries that are incorporated in them.  (We have not seen how to achieve\nthis as regards changes in header files, but we have achieved it as regards\nchanges in the actual functions of the Library.)  The hope is that this\nwill lead to faster development of free libraries.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.  Pay close attention to the difference between a\n\"work based on the library\" and a \"work that uses the library\".  The\nformer contains code derived from the library, while the latter only\nworks together with the library.\n\n  Note that it is possible for a library to be covered by the ordinary\nGeneral Public License rather than by this special one.\n\n                  GNU LIBRARY GENERAL PUBLIC LICENSE\n   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION\n\n  0. This License Agreement applies to any software library which\ncontains a notice placed by the copyright holder or other authorized\nparty saying it may be distributed under the terms of this Library\nGeneral Public License (also called \"this License\").  Each licensee is\naddressed as \"you\".\n\n  A \"library\" means a collection of software functions and/or data\nprepared so as to be conveniently linked with application programs\n(which use some of those functions and data) to form executables.\n\n  The \"Library\", below, refers to any such software library or work\nwhich has been distributed under these terms.  A \"work based on the\nLibrary\" means either the Library or any derivative work under\ncopyright law: that is to say, a work containing the Library or a\nportion of it, either verbatim or with modifications and/or translated\nstraightforwardly into another language.  (Hereinafter, translation is\nincluded without limitation in the term \"modification\".)\n\n  \"Source code\" for a work means the preferred form of the work for\nmaking modifications to it.  For a library, complete source code means\nall the source code for all modules it contains, plus any associated\ninterface definition files, plus the scripts used to control compilation\nand installation of the library.\n\n  Activities other than copying, distribution and modification are not\ncovered by this License; they are outside its scope.  The act of\nrunning a program using the Library is not restricted, and output from\nsuch a program is covered only if its contents constitute a work based\non the Library (independent of the use of the Library in a tool for\nwriting it).  Whether that is true depends on what the Library does\nand what the program that uses the Library does.\n  \n  1. You may copy and distribute verbatim copies of the Library's\ncomplete source code as you receive it, in any medium, provided that\nyou conspicuously and appropriately publish on each copy an\nappropriate copyright notice and disclaimer of warranty; keep intact\nall the notices that refer to this License and to the absence of any\nwarranty; and distribute a copy of this License along with the\nLibrary.\n\n  You may charge a fee for the physical act of transferring a copy,\nand you may at your option offer warranty protection in exchange for a\nfee.\n\n  2. You may modify your copy or copies of the Library or any portion\nof it, thus forming a work based on the Library, and copy and\ndistribute such modifications or work under the terms of Section 1\nabove, provided that you also meet all of these conditions:\n\n    a) The modified work must itself be a software library.\n\n    b) You must cause the files modified to carry prominent notices\n    stating that you changed the files and the date of any change.\n\n    c) You must cause the whole of the work to be licensed at no\n    charge to all third parties under the terms of this License.\n\n    d) If a facility in the modified Library refers to a function or a\n    table of data to be supplied by an application program that uses\n    the facility, other than as an argument passed when the facility\n    is invoked, then you must make a good faith effort to ensure that,\n    in the event an application does not supply such function or\n    table, the facility still operates, and performs whatever part of\n    its purpose remains meaningful.\n\n    (For example, a function in a library to compute square roots has\n    a purpose that is entirely well-defined independent of the\n    application.  Therefore, Subsection 2d requires that any\n    application-supplied function or table used by this function must\n    be optional: if the application does not supply it, the square\n    root function must still compute square roots.)\n\nThese requirements apply to the modified work as a whole.  If\nidentifiable sections of that work are not derived from the Library,\nand can be reasonably considered independent and separate works in\nthemselves, then this License, and its terms, do not apply to those\nsections when you distribute them as separate works.  But when you\ndistribute the same sections as part of a whole which is a work based\non the Library, the distribution of the whole must be on the terms of\nthis License, whose permissions for other licensees extend to the\nentire whole, and thus to each and every part regardless of who wrote\nit.\n\nThus, it is not the intent of this section to claim rights or contest\nyour rights to work written entirely by you; rather, the intent is to\nexercise the right to control the distribution of derivative or\ncollective works based on the Library.\n\nIn addition, mere aggregation of another work not based on the Library\nwith the Library (or with a work based on the Library) on a volume of\na storage or distribution medium does not bring the other work under\nthe scope of this License.\n\n  3. You may opt to apply the terms of the ordinary GNU General Public\nLicense instead of this License to a given copy of the Library.  To do\nthis, you must alter all the notices that refer to this License, so\nthat they refer to the ordinary GNU General Public License, version 2,\ninstead of to this License.  (If a newer version than version 2 of the\nordinary GNU General Public License has appeared, then you can specify\nthat version instead if you wish.)  Do not make any other change in\nthese notices.\n\n  Once this change is made in a given copy, it is irreversible for\nthat copy, so the ordinary GNU General Public License applies to all\nsubsequent copies and derivative works made from that copy.\n\n  This option is useful when you wish to copy part of the code of\nthe Library into a program that is not a library.\n\n  4. You may copy and distribute the Library (or a portion or\nderivative of it, under Section 2) in object code or executable form\nunder the terms of Sections 1 and 2 above provided that you accompany\nit with the complete corresponding machine-readable source code, which\nmust be distributed under the terms of Sections 1 and 2 above on a\nmedium customarily used for software interchange.\n\n  If distribution of object code is made by offering access to copy\nfrom a designated place, then offering equivalent access to copy the\nsource code from the same place satisfies the requirement to\ndistribute the source code, even though third parties are not\ncompelled to copy the source along with the object code.\n\n  5. A program that contains no derivative of any portion of the\nLibrary, but is designed to work with the Library by being compiled or\nlinked with it, is called a \"work that uses the Library\".  Such a\nwork, in isolation, is not a derivative work of the Library, and\ntherefore falls outside the scope of this License.\n\n  However, linking a \"work that uses the Library\" with the Library\ncreates an executable that is a derivative of the Library (because it\ncontains portions of the Library), rather than a \"work that uses the\nlibrary\".  The executable is therefore covered by this License.\nSection 6 states terms for distribution of such executables.\n\n  When a \"work that uses the Library\" uses material from a header file\nthat is part of the Library, the object code for the work may be a\nderivative work of the Library even though the source code is not.\nWhether this is true is especially significant if the work can be\nlinked without the Library, or if the work is itself a library.  The\nthreshold for this to be true is not precisely defined by law.\n\n  If such an object file uses only numerical parameters, data\nstructure layouts and accessors, and small macros and small inline\nfunctions (ten lines or less in length), then the use of the object\nfile is unrestricted, regardless of whether it is legally a derivative\nwork.  (Executables containing this object code plus portions of the\nLibrary will still fall under Section 6.)\n\n  Otherwise, if the work is a derivative of the Library, you may\ndistribute the object code for the work under the terms of Section 6.\nAny executables containing that work also fall under Section 6,\nwhether or not they are linked directly with the Library itself.\n\n  6. As an exception to the Sections above, you may also compile or\nlink a \"work that uses the Library\" with the Library to produce a\nwork containing portions of the Library, and distribute that work\nunder terms of your choice, provided that the terms permit\nmodification of the work for the customer's own use and reverse\nengineering for debugging such modifications.\n\n  You must give prominent notice with each copy of the work that the\nLibrary is used in it and that the Library and its use are covered by\nthis License.  You must supply a copy of this License.  If the work\nduring execution displays copyright notices, you must include the\ncopyright notice for the Library among them, as well as a reference\ndirecting the user to the copy of this License.  Also, you must do one\nof these things:\n\n    a) Accompany the work with the complete corresponding\n    machine-readable source code for the Library including whatever\n    changes were used in the work (which must be distributed under\n    Sections 1 and 2 above); and, if the work is an executable linked\n    with the Library, with the complete machine-readable \"work that\n    uses the Library\", as object code and/or source code, so that the\n    user can modify the Library and then relink to produce a modified\n    executable containing the modified Library.  (It is understood\n    that the user who changes the contents of definitions files in the\n    Library will not necessarily be able to recompile the application\n    to use the modified definitions.)\n\n    b) Accompany the work with a written offer, valid for at\n    least three years, to give the same user the materials\n    specified in Subsection 6a, above, for a charge no more\n    than the cost of performing this distribution.\n\n    c) If distribution of the work is made by offering access to copy\n    from a designated place, offer equivalent access to copy the above\n    specified materials from the same place.\n\n    d) Verify that the user has already received a copy of these\n    materials or that you have already sent this user a copy.\n\n  For an executable, the required form of the \"work that uses the\nLibrary\" must include any data and utility programs needed for\nreproducing the executable from it.  However, as a special exception,\nthe source code distributed need not include anything that is normally\ndistributed (in either source or binary form) with the major\ncomponents (compiler, kernel, and so on) of the operating system on\nwhich the executable runs, unless that component itself accompanies\nthe executable.\n\n  It may happen that this requirement contradicts the license\nrestrictions of other proprietary libraries that do not normally\naccompany the operating system.  Such a contradiction means you cannot\nuse both them and the Library together in an executable that you\ndistribute.\n\n  7. You may place library facilities that are a work based on the\nLibrary side-by-side in a single library together with other library\nfacilities not covered by this License, and distribute such a combined\nlibrary, provided that the separate distribution of the work based on\nthe Library and of the other library facilities is otherwise\npermitted, and provided that you do these two things:\n\n    a) Accompany the combined library with a copy of the same work\n    based on the Library, uncombined with any other library\n    facilities.  This must be distributed under the terms of the\n    Sections above.\n\n    b) Give prominent notice with the combined library of the fact\n    that part of it is a work based on the Library, and explaining\n    where to find the accompanying uncombined form of the same work.\n\n  8. You may not copy, modify, sublicense, link with, or distribute\nthe Library except as expressly provided under this License.  Any\nattempt otherwise to copy, modify, sublicense, link with, or\ndistribute the Library is void, and will automatically terminate your\nrights under this License.  However, parties who have received copies,\nor rights, from you under this License will not have their licenses\nterminated so long as such parties remain in full compliance.\n\n  9. You are not required to accept this License, since you have not\nsigned it.  However, nothing else grants you permission to modify or\ndistribute the Library or its derivative works.  These actions are\nprohibited by law if you do not accept this License.  Therefore, by\nmodifying or distributing the Library (or any work based on the\nLibrary), you indicate your acceptance of this License to do so, and\nall its terms and conditions for copying, distributing or modifying\nthe Library or works based on it.\n\n  10. Each time you redistribute the Library (or any work based on the\nLibrary), the recipient automatically receives a license from the\noriginal licensor to copy, distribute, link with or modify the Library\nsubject to these terms and conditions.  You may not impose any further\nrestrictions on the recipients' exercise of the rights granted herein.\nYou are not responsible for enforcing compliance by third parties to\nthis License.\n\n  11. If, as a consequence of a court judgment or allegation of patent\ninfringement or for any other reason (not limited to patent issues),\nconditions 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\ndistribute so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you\nmay not distribute the Library at all.  For example, if a patent\nlicense would not permit royalty-free redistribution of the Library by\nall those who receive copies directly or indirectly through you, then\nthe only way you could satisfy both it and this License would be to\nrefrain entirely from distribution of the Library.\n\nIf any portion of this section is held invalid or unenforceable under any\nparticular circumstance, the balance of the section is intended to apply,\nand the section as a whole is intended to apply in other circumstances.\n\nIt is not the purpose of this section to induce you to infringe any\npatents or other property right claims or to contest validity of any\nsuch claims; this section has the sole purpose of protecting the\nintegrity of the free software distribution system which is\nimplemented by public license practices.  Many people have made\ngenerous contributions to the wide range of software distributed\nthrough that system in reliance on consistent application of that\nsystem; it is up to the author/donor to decide if he or she is willing\nto distribute software through any other system and a licensee cannot\nimpose that choice.\n\nThis section is intended to make thoroughly clear what is believed to\nbe a consequence of the rest of this License.\n\n  12. If the distribution and/or use of the Library is restricted in\ncertain countries either by patents or by copyrighted interfaces, the\noriginal copyright holder who places the Library under this License may add\nan explicit geographical distribution limitation excluding those countries,\nso that distribution is permitted only in or among countries not thus\nexcluded.  In such case, this License incorporates the limitation as if\nwritten in the body of this License.\n\n  13. The Free Software Foundation may publish revised and/or new\nversions of the Library General Public License from time to time.\nSuch new versions will be similar in spirit to the present version,\nbut may differ in detail to address new problems or concerns.\n\nEach version is given a distinguishing version number.  If the Library\nspecifies a version number of this License which applies to it and\n\"any later version\", you have the option of following the terms and\nconditions either of that version or of any later version published by\nthe Free Software Foundation.  If the Library does not specify a\nlicense version number, you may choose any version ever published by\nthe Free Software Foundation.\n\n  14. If you wish to incorporate parts of the Library into other free\nprograms whose distribution conditions are incompatible with these,\nwrite to the author to ask for permission.  For software which is\ncopyrighted by the Free Software Foundation, write to the Free\nSoftware Foundation; we sometimes make exceptions for this.  Our\ndecision will be guided by the two goals of preserving the free status\nof all derivatives of our free software and of promoting the sharing\nand reuse of software generally.\n\n                            NO WARRANTY\n\n  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO\nWARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.\nEXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR\nOTHER PARTIES PROVIDE THE LIBRARY \"AS IS\" WITHOUT WARRANTY OF ANY\nKIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE\nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE\nLIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME\nTHE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN\nWRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY\nAND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU\nFOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR\nCONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE\nLIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING\nRENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A\nFAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF\nSUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH\nDAMAGES.\n\n                     END OF TERMS AND CONDITIONS\n"
  },
  {
    "path": "vendor/openal-soft/include/AL/al.h",
    "content": "#ifndef AL_AL_H\n#define AL_AL_H\n\n#if defined(__cplusplus)\nextern \"C\" {\n#endif\n\n#ifndef AL_API\n #if defined(AL_LIBTYPE_STATIC)\n  #define AL_API\n #elif defined(_WIN32)\n  #define AL_API __declspec(dllimport)\n #else\n  #define AL_API extern\n #endif\n#endif\n\n#if defined(_WIN32)\n #define AL_APIENTRY __cdecl\n#else\n #define AL_APIENTRY\n#endif\n\n\n/* Deprecated macros. */\n#define OPENAL\n#define ALAPI                                    AL_API\n#define ALAPIENTRY                               AL_APIENTRY\n#define AL_INVALID                               (-1)\n#define AL_ILLEGAL_ENUM                          AL_INVALID_ENUM\n#define AL_ILLEGAL_COMMAND                       AL_INVALID_OPERATION\n\n/* Supported AL versions. */\n#define AL_VERSION_1_0\n#define AL_VERSION_1_1\n\n/** 8-bit boolean */\ntypedef char ALboolean;\n\n/** character */\ntypedef char ALchar;\n\n/** signed 8-bit 2's complement integer */\ntypedef signed char ALbyte;\n\n/** unsigned 8-bit integer */\ntypedef unsigned char ALubyte;\n\n/** signed 16-bit 2's complement integer */\ntypedef short ALshort;\n\n/** unsigned 16-bit integer */\ntypedef unsigned short ALushort;\n\n/** signed 32-bit 2's complement integer */\ntypedef int ALint;\n\n/** unsigned 32-bit integer */\ntypedef unsigned int ALuint;\n\n/** non-negative 32-bit binary integer size */\ntypedef int ALsizei;\n\n/** enumerated 32-bit value */\ntypedef int ALenum;\n\n/** 32-bit IEEE754 floating-point */\ntypedef float ALfloat;\n\n/** 64-bit IEEE754 floating-point */\ntypedef double ALdouble;\n\n/** void type (for opaque pointers only) */\ntypedef void ALvoid;\n\n\n/* Enumerant values begin at column 50. No tabs. */\n\n/** \"no distance model\" or \"no buffer\" */\n#define AL_NONE                                  0\n\n/** Boolean False. */\n#define AL_FALSE                                 0\n\n/** Boolean True. */\n#define AL_TRUE                                  1\n\n\n/**\n * Relative source.\n * Type:    ALboolean\n * Range:   [AL_TRUE, AL_FALSE]\n * Default: AL_FALSE\n *\n * Specifies if the Source has relative coordinates.\n */\n#define AL_SOURCE_RELATIVE                       0x202\n\n\n/**\n * Inner cone angle, in degrees.\n * Type:    ALint, ALfloat\n * Range:   [0 - 360]\n * Default: 360\n *\n * The angle covered by the inner cone, where the source will not attenuate.\n */\n#define AL_CONE_INNER_ANGLE                      0x1001\n\n/**\n * Outer cone angle, in degrees.\n * Range:   [0 - 360]\n * Default: 360\n *\n * The angle covered by the outer cone, where the source will be fully\n * attenuated.\n */\n#define AL_CONE_OUTER_ANGLE                      0x1002\n\n/**\n * Source pitch.\n * Type:    ALfloat\n * Range:   [0.5 - 2.0]\n * Default: 1.0\n *\n * A multiplier for the frequency (sample rate) of the source's buffer.\n */\n#define AL_PITCH                                 0x1003\n\n/**\n * Source or listener position.\n * Type:    ALfloat[3], ALint[3]\n * Default: {0, 0, 0}\n *\n * The source or listener location in three dimensional space.\n *\n * OpenAL, like OpenGL, uses a right handed coordinate system, where in a\n * frontal default view X (thumb) points right, Y points up (index finger), and\n * Z points towards the viewer/camera (middle finger).\n *\n * To switch from a left handed coordinate system, flip the sign on the Z\n * coordinate.\n */\n#define AL_POSITION                              0x1004\n\n/**\n * Source direction.\n * Type:    ALfloat[3], ALint[3]\n * Default: {0, 0, 0}\n *\n * Specifies the current direction in local space.\n * A zero-length vector specifies an omni-directional source (cone is ignored).\n */\n#define AL_DIRECTION                             0x1005\n\n/**\n * Source or listener velocity.\n * Type:    ALfloat[3], ALint[3]\n * Default: {0, 0, 0}\n *\n * Specifies the current velocity in local space.\n */\n#define AL_VELOCITY                              0x1006\n\n/**\n * Source looping.\n * Type:    ALboolean\n * Range:   [AL_TRUE, AL_FALSE]\n * Default: AL_FALSE\n *\n * Specifies whether source is looping.\n */\n#define AL_LOOPING                               0x1007\n\n/**\n * Source buffer.\n * Type:  ALuint\n * Range: any valid Buffer.\n *\n * Specifies the buffer to provide sound samples.\n */\n#define AL_BUFFER                                0x1009\n\n/**\n * Source or listener gain.\n * Type:  ALfloat\n * Range: [0.0 - ]\n *\n * A value of 1.0 means unattenuated. Each division by 2 equals an attenuation\n * of about -6dB. Each multiplicaton by 2 equals an amplification of about\n * +6dB.\n *\n * A value of 0.0 is meaningless with respect to a logarithmic scale; it is\n * silent.\n */\n#define AL_GAIN                                  0x100A\n\n/**\n * Minimum source gain.\n * Type:  ALfloat\n * Range: [0.0 - 1.0]\n *\n * The minimum gain allowed for a source, after distance and cone attenation is\n * applied (if applicable).\n */\n#define AL_MIN_GAIN                              0x100D\n\n/**\n * Maximum source gain.\n * Type:  ALfloat\n * Range: [0.0 - 1.0]\n *\n * The maximum gain allowed for a source, after distance and cone attenation is\n * applied (if applicable).\n */\n#define AL_MAX_GAIN                              0x100E\n\n/**\n * Listener orientation.\n * Type: ALfloat[6]\n * Default: {0.0, 0.0, -1.0, 0.0, 1.0, 0.0}\n *\n * Effectively two three dimensional vectors. The first vector is the front (or\n * \"at\") and the second is the top (or \"up\").\n *\n * Both vectors are in local space.\n */\n#define AL_ORIENTATION                           0x100F\n\n/**\n * Source state (query only).\n * Type:  ALint\n * Range: [AL_INITIAL, AL_PLAYING, AL_PAUSED, AL_STOPPED]\n */\n#define AL_SOURCE_STATE                          0x1010\n\n/* Source state values. */\n#define AL_INITIAL                               0x1011\n#define AL_PLAYING                               0x1012\n#define AL_PAUSED                                0x1013\n#define AL_STOPPED                               0x1014\n\n/**\n * Source Buffer Queue size (query only).\n * Type: ALint\n *\n * The number of buffers queued using alSourceQueueBuffers, minus the buffers\n * removed with alSourceUnqueueBuffers.\n */\n#define AL_BUFFERS_QUEUED                        0x1015\n\n/**\n * Source Buffer Queue processed count (query only).\n * Type: ALint\n *\n * The number of queued buffers that have been fully processed, and can be\n * removed with alSourceUnqueueBuffers.\n *\n * Looping sources will never fully process buffers because they will be set to\n * play again for when the source loops.\n */\n#define AL_BUFFERS_PROCESSED                     0x1016\n\n/**\n * Source reference distance.\n * Type:    ALfloat\n * Range:   [0.0 - ]\n * Default: 1.0\n *\n * The distance in units that no attenuation occurs.\n *\n * At 0.0, no distance attenuation ever occurs on non-linear attenuation models.\n */\n#define AL_REFERENCE_DISTANCE                    0x1020\n\n/**\n * Source rolloff factor.\n * Type:    ALfloat\n * Range:   [0.0 - ]\n * Default: 1.0\n *\n * Multiplier to exaggerate or diminish distance attenuation.\n *\n * At 0.0, no distance attenuation ever occurs.\n */\n#define AL_ROLLOFF_FACTOR                        0x1021\n\n/**\n * Outer cone gain.\n * Type:    ALfloat\n * Range:   [0.0 - 1.0]\n * Default: 0.0\n *\n * The gain attenuation applied when the listener is outside of the source's\n * outer cone.\n */\n#define AL_CONE_OUTER_GAIN                       0x1022\n\n/**\n * Source maximum distance.\n * Type:    ALfloat\n * Range:   [0.0 - ]\n * Default: FLT_MAX\n *\n * The distance above which the source is not attenuated any further with a\n * clamped distance model, or where attenuation reaches 0.0 gain for linear\n * distance models with a default rolloff factor.\n */\n#define AL_MAX_DISTANCE                          0x1023\n\n/** Source buffer position, in seconds */\n#define AL_SEC_OFFSET                            0x1024\n/** Source buffer position, in sample frames */\n#define AL_SAMPLE_OFFSET                         0x1025\n/** Source buffer position, in bytes */\n#define AL_BYTE_OFFSET                           0x1026\n\n/**\n * Source type (query only).\n * Type:  ALint\n * Range: [AL_STATIC, AL_STREAMING, AL_UNDETERMINED]\n *\n * A Source is Static if a Buffer has been attached using AL_BUFFER.\n *\n * A Source is Streaming if one or more Buffers have been attached using\n * alSourceQueueBuffers.\n *\n * A Source is Undetermined when it has the NULL buffer attached using\n * AL_BUFFER.\n */\n#define AL_SOURCE_TYPE                           0x1027\n\n/* Source type values. */\n#define AL_STATIC                                0x1028\n#define AL_STREAMING                             0x1029\n#define AL_UNDETERMINED                          0x1030\n\n/** Unsigned 8-bit mono buffer format. */\n#define AL_FORMAT_MONO8                          0x1100\n/** Signed 16-bit mono buffer format. */\n#define AL_FORMAT_MONO16                         0x1101\n/** Unsigned 8-bit stereo buffer format. */\n#define AL_FORMAT_STEREO8                        0x1102\n/** Signed 16-bit stereo buffer format. */\n#define AL_FORMAT_STEREO16                       0x1103\n\n/** Buffer frequency (query only). */\n#define AL_FREQUENCY                             0x2001\n/** Buffer bits per sample (query only). */\n#define AL_BITS                                  0x2002\n/** Buffer channel count (query only). */\n#define AL_CHANNELS                              0x2003\n/** Buffer data size (query only). */\n#define AL_SIZE                                  0x2004\n\n/* Buffer state. Not for public use. */\n#define AL_UNUSED                                0x2010\n#define AL_PENDING                               0x2011\n#define AL_PROCESSED                             0x2012\n\n\n/** No error. */\n#define AL_NO_ERROR                              0\n\n/** Invalid name paramater passed to AL call. */\n#define AL_INVALID_NAME                          0xA001\n\n/** Invalid enum parameter passed to AL call. */\n#define AL_INVALID_ENUM                          0xA002\n\n/** Invalid value parameter passed to AL call. */\n#define AL_INVALID_VALUE                         0xA003\n\n/** Illegal AL call. */\n#define AL_INVALID_OPERATION                     0xA004\n\n/** Not enough memory. */\n#define AL_OUT_OF_MEMORY                         0xA005\n\n\n/** Context string: Vendor ID. */\n#define AL_VENDOR                                0xB001\n/** Context string: Version. */\n#define AL_VERSION                               0xB002\n/** Context string: Renderer ID. */\n#define AL_RENDERER                              0xB003\n/** Context string: Space-separated extension list. */\n#define AL_EXTENSIONS                            0xB004\n\n\n/**\n * Doppler scale.\n * Type:    ALfloat\n * Range:   [0.0 - ]\n * Default: 1.0\n *\n * Scale for source and listener velocities.\n */\n#define AL_DOPPLER_FACTOR                        0xC000\nAL_API void AL_APIENTRY alDopplerFactor(ALfloat value);\n\n/**\n * Doppler velocity (deprecated).\n *\n * A multiplier applied to the Speed of Sound.\n */\n#define AL_DOPPLER_VELOCITY                      0xC001\nAL_API void AL_APIENTRY alDopplerVelocity(ALfloat value);\n\n/**\n * Speed of Sound, in units per second.\n * Type:    ALfloat\n * Range:   [0.0001 - ]\n * Default: 343.3\n *\n * The speed at which sound waves are assumed to travel, when calculating the\n * doppler effect.\n */\n#define AL_SPEED_OF_SOUND                        0xC003\nAL_API void AL_APIENTRY alSpeedOfSound(ALfloat value);\n\n/**\n * Distance attenuation model.\n * Type:    ALint\n * Range:   [AL_NONE, AL_INVERSE_DISTANCE, AL_INVERSE_DISTANCE_CLAMPED,\n *           AL_LINEAR_DISTANCE, AL_LINEAR_DISTANCE_CLAMPED,\n *           AL_EXPONENT_DISTANCE, AL_EXPONENT_DISTANCE_CLAMPED]\n * Default: AL_INVERSE_DISTANCE_CLAMPED\n *\n * The model by which sources attenuate with distance.\n *\n * None     - No distance attenuation.\n * Inverse  - Doubling the distance halves the source gain.\n * Linear   - Linear gain scaling between the reference and max distances.\n * Exponent - Exponential gain dropoff.\n *\n * Clamped variations work like the non-clamped counterparts, except the\n * distance calculated is clamped between the reference and max distances.\n */\n#define AL_DISTANCE_MODEL                        0xD000\nAL_API void AL_APIENTRY alDistanceModel(ALenum distanceModel);\n\n/* Distance model values. */\n#define AL_INVERSE_DISTANCE                      0xD001\n#define AL_INVERSE_DISTANCE_CLAMPED              0xD002\n#define AL_LINEAR_DISTANCE                       0xD003\n#define AL_LINEAR_DISTANCE_CLAMPED               0xD004\n#define AL_EXPONENT_DISTANCE                     0xD005\n#define AL_EXPONENT_DISTANCE_CLAMPED             0xD006\n\n/* Renderer State management. */\nAL_API void AL_APIENTRY alEnable(ALenum capability);\nAL_API void AL_APIENTRY alDisable(ALenum capability);\nAL_API ALboolean AL_APIENTRY alIsEnabled(ALenum capability);\n\n/* State retrieval. */\nAL_API const ALchar* AL_APIENTRY alGetString(ALenum param);\nAL_API void AL_APIENTRY alGetBooleanv(ALenum param, ALboolean *values);\nAL_API void AL_APIENTRY alGetIntegerv(ALenum param, ALint *values);\nAL_API void AL_APIENTRY alGetFloatv(ALenum param, ALfloat *values);\nAL_API void AL_APIENTRY alGetDoublev(ALenum param, ALdouble *values);\nAL_API ALboolean AL_APIENTRY alGetBoolean(ALenum param);\nAL_API ALint AL_APIENTRY alGetInteger(ALenum param);\nAL_API ALfloat AL_APIENTRY alGetFloat(ALenum param);\nAL_API ALdouble AL_APIENTRY alGetDouble(ALenum param);\n\n/* Error retrieval. */\n\n/** Obtain the first error generated in the AL context since the last check. */\nAL_API ALenum AL_APIENTRY alGetError(void);\n\n/** Query for the presence of an extension on the AL context. */\nAL_API ALboolean AL_APIENTRY alIsExtensionPresent(const ALchar *extname);\n/**\n * Retrieve the address of a function. The returned function may be context-\n * specific.\n */\nAL_API void* AL_APIENTRY alGetProcAddress(const ALchar *fname);\n/**\n * Retrieve the value of an enum. The returned value may be context-specific.\n */\nAL_API ALenum AL_APIENTRY alGetEnumValue(const ALchar *ename);\n\n\n/* Set Listener parameters */\nAL_API void AL_APIENTRY alListenerf(ALenum param, ALfloat value);\nAL_API void AL_APIENTRY alListener3f(ALenum param, ALfloat value1, ALfloat value2, ALfloat value3);\nAL_API void AL_APIENTRY alListenerfv(ALenum param, const ALfloat *values);\nAL_API void AL_APIENTRY alListeneri(ALenum param, ALint value);\nAL_API void AL_APIENTRY alListener3i(ALenum param, ALint value1, ALint value2, ALint value3);\nAL_API void AL_APIENTRY alListeneriv(ALenum param, const ALint *values);\n\n/* Get Listener parameters */\nAL_API void AL_APIENTRY alGetListenerf(ALenum param, ALfloat *value);\nAL_API void AL_APIENTRY alGetListener3f(ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3);\nAL_API void AL_APIENTRY alGetListenerfv(ALenum param, ALfloat *values);\nAL_API void AL_APIENTRY alGetListeneri(ALenum param, ALint *value);\nAL_API void AL_APIENTRY alGetListener3i(ALenum param, ALint *value1, ALint *value2, ALint *value3);\nAL_API void AL_APIENTRY alGetListeneriv(ALenum param, ALint *values);\n\n\n/** Create Source objects. */\nAL_API void AL_APIENTRY alGenSources(ALsizei n, ALuint *sources);\n/** Delete Source objects. */\nAL_API void AL_APIENTRY alDeleteSources(ALsizei n, const ALuint *sources);\n/** Verify a handle is a valid Source. */\nAL_API ALboolean AL_APIENTRY alIsSource(ALuint source);\n\n/* Set Source parameters. */\nAL_API void AL_APIENTRY alSourcef(ALuint source, ALenum param, ALfloat value);\nAL_API void AL_APIENTRY alSource3f(ALuint source, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3);\nAL_API void AL_APIENTRY alSourcefv(ALuint source, ALenum param, const ALfloat *values);\nAL_API void AL_APIENTRY alSourcei(ALuint source, ALenum param, ALint value);\nAL_API void AL_APIENTRY alSource3i(ALuint source, ALenum param, ALint value1, ALint value2, ALint value3);\nAL_API void AL_APIENTRY alSourceiv(ALuint source, ALenum param, const ALint *values);\n\n/* Get Source parameters. */\nAL_API void AL_APIENTRY alGetSourcef(ALuint source, ALenum param, ALfloat *value);\nAL_API void AL_APIENTRY alGetSource3f(ALuint source, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3);\nAL_API void AL_APIENTRY alGetSourcefv(ALuint source, ALenum param, ALfloat *values);\nAL_API void AL_APIENTRY alGetSourcei(ALuint source,  ALenum param, ALint *value);\nAL_API void AL_APIENTRY alGetSource3i(ALuint source, ALenum param, ALint *value1, ALint *value2, ALint *value3);\nAL_API void AL_APIENTRY alGetSourceiv(ALuint source,  ALenum param, ALint *values);\n\n\n/** Play, replay, or resume (if paused) a list of Sources */\nAL_API void AL_APIENTRY alSourcePlayv(ALsizei n, const ALuint *sources);\n/** Stop a list of Sources */\nAL_API void AL_APIENTRY alSourceStopv(ALsizei n, const ALuint *sources);\n/** Rewind a list of Sources */\nAL_API void AL_APIENTRY alSourceRewindv(ALsizei n, const ALuint *sources);\n/** Pause a list of Sources */\nAL_API void AL_APIENTRY alSourcePausev(ALsizei n, const ALuint *sources);\n\n/** Play, replay, or resume a Source */\nAL_API void AL_APIENTRY alSourcePlay(ALuint source);\n/** Stop a Source */\nAL_API void AL_APIENTRY alSourceStop(ALuint source);\n/** Rewind a Source (set playback postiton to beginning) */\nAL_API void AL_APIENTRY alSourceRewind(ALuint source);\n/** Pause a Source */\nAL_API void AL_APIENTRY alSourcePause(ALuint source);\n\n/** Queue buffers onto a source */\nAL_API void AL_APIENTRY alSourceQueueBuffers(ALuint source, ALsizei nb, const ALuint *buffers);\n/** Unqueue processed buffers from a source */\nAL_API void AL_APIENTRY alSourceUnqueueBuffers(ALuint source, ALsizei nb, ALuint *buffers);\n\n\n/** Create Buffer objects */\nAL_API void AL_APIENTRY alGenBuffers(ALsizei n, ALuint *buffers);\n/** Delete Buffer objects */\nAL_API void AL_APIENTRY alDeleteBuffers(ALsizei n, const ALuint *buffers);\n/** Verify a handle is a valid Buffer */\nAL_API ALboolean AL_APIENTRY alIsBuffer(ALuint buffer);\n\n/** Specifies the data to be copied into a buffer */\nAL_API void AL_APIENTRY alBufferData(ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei freq);\n\n/* Set Buffer parameters, */\nAL_API void AL_APIENTRY alBufferf(ALuint buffer, ALenum param, ALfloat value);\nAL_API void AL_APIENTRY alBuffer3f(ALuint buffer, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3);\nAL_API void AL_APIENTRY alBufferfv(ALuint buffer, ALenum param, const ALfloat *values);\nAL_API void AL_APIENTRY alBufferi(ALuint buffer, ALenum param, ALint value);\nAL_API void AL_APIENTRY alBuffer3i(ALuint buffer, ALenum param, ALint value1, ALint value2, ALint value3);\nAL_API void AL_APIENTRY alBufferiv(ALuint buffer, ALenum param, const ALint *values);\n\n/* Get Buffer parameters. */\nAL_API void AL_APIENTRY alGetBufferf(ALuint buffer, ALenum param, ALfloat *value);\nAL_API void AL_APIENTRY alGetBuffer3f(ALuint buffer, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3);\nAL_API void AL_APIENTRY alGetBufferfv(ALuint buffer, ALenum param, ALfloat *values);\nAL_API void AL_APIENTRY alGetBufferi(ALuint buffer, ALenum param, ALint *value);\nAL_API void AL_APIENTRY alGetBuffer3i(ALuint buffer, ALenum param, ALint *value1, ALint *value2, ALint *value3);\nAL_API void AL_APIENTRY alGetBufferiv(ALuint buffer, ALenum param, ALint *values);\n\n/* Pointer-to-function type, useful for dynamically getting AL entry points. */\ntypedef void          (AL_APIENTRY *LPALENABLE)(ALenum capability);\ntypedef void          (AL_APIENTRY *LPALDISABLE)(ALenum capability);\ntypedef ALboolean     (AL_APIENTRY *LPALISENABLED)(ALenum capability);\ntypedef const ALchar* (AL_APIENTRY *LPALGETSTRING)(ALenum param);\ntypedef void          (AL_APIENTRY *LPALGETBOOLEANV)(ALenum param, ALboolean *values);\ntypedef void          (AL_APIENTRY *LPALGETINTEGERV)(ALenum param, ALint *values);\ntypedef void          (AL_APIENTRY *LPALGETFLOATV)(ALenum param, ALfloat *values);\ntypedef void          (AL_APIENTRY *LPALGETDOUBLEV)(ALenum param, ALdouble *values);\ntypedef ALboolean     (AL_APIENTRY *LPALGETBOOLEAN)(ALenum param);\ntypedef ALint         (AL_APIENTRY *LPALGETINTEGER)(ALenum param);\ntypedef ALfloat       (AL_APIENTRY *LPALGETFLOAT)(ALenum param);\ntypedef ALdouble      (AL_APIENTRY *LPALGETDOUBLE)(ALenum param);\ntypedef ALenum        (AL_APIENTRY *LPALGETERROR)(void);\ntypedef ALboolean     (AL_APIENTRY *LPALISEXTENSIONPRESENT)(const ALchar *extname);\ntypedef void*         (AL_APIENTRY *LPALGETPROCADDRESS)(const ALchar *fname);\ntypedef ALenum        (AL_APIENTRY *LPALGETENUMVALUE)(const ALchar *ename);\ntypedef void          (AL_APIENTRY *LPALLISTENERF)(ALenum param, ALfloat value);\ntypedef void          (AL_APIENTRY *LPALLISTENER3F)(ALenum param, ALfloat value1, ALfloat value2, ALfloat value3);\ntypedef void          (AL_APIENTRY *LPALLISTENERFV)(ALenum param, const ALfloat *values);\ntypedef void          (AL_APIENTRY *LPALLISTENERI)(ALenum param, ALint value);\ntypedef void          (AL_APIENTRY *LPALLISTENER3I)(ALenum param, ALint value1, ALint value2, ALint value3);\ntypedef void          (AL_APIENTRY *LPALLISTENERIV)(ALenum param, const ALint *values);\ntypedef void          (AL_APIENTRY *LPALGETLISTENERF)(ALenum param, ALfloat *value);\ntypedef void          (AL_APIENTRY *LPALGETLISTENER3F)(ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3);\ntypedef void          (AL_APIENTRY *LPALGETLISTENERFV)(ALenum param, ALfloat *values);\ntypedef void          (AL_APIENTRY *LPALGETLISTENERI)(ALenum param, ALint *value);\ntypedef void          (AL_APIENTRY *LPALGETLISTENER3I)(ALenum param, ALint *value1, ALint *value2, ALint *value3);\ntypedef void          (AL_APIENTRY *LPALGETLISTENERIV)(ALenum param, ALint *values);\ntypedef void          (AL_APIENTRY *LPALGENSOURCES)(ALsizei n, ALuint *sources);\ntypedef void          (AL_APIENTRY *LPALDELETESOURCES)(ALsizei n, const ALuint *sources);\ntypedef ALboolean     (AL_APIENTRY *LPALISSOURCE)(ALuint source);\ntypedef void          (AL_APIENTRY *LPALSOURCEF)(ALuint source, ALenum param, ALfloat value);\ntypedef void          (AL_APIENTRY *LPALSOURCE3F)(ALuint source, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3);\ntypedef void          (AL_APIENTRY *LPALSOURCEFV)(ALuint source, ALenum param, const ALfloat *values);\ntypedef void          (AL_APIENTRY *LPALSOURCEI)(ALuint source, ALenum param, ALint value);\ntypedef void          (AL_APIENTRY *LPALSOURCE3I)(ALuint source, ALenum param, ALint value1, ALint value2, ALint value3);\ntypedef void          (AL_APIENTRY *LPALSOURCEIV)(ALuint source, ALenum param, const ALint *values);\ntypedef void          (AL_APIENTRY *LPALGETSOURCEF)(ALuint source, ALenum param, ALfloat *value);\ntypedef void          (AL_APIENTRY *LPALGETSOURCE3F)(ALuint source, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3);\ntypedef void          (AL_APIENTRY *LPALGETSOURCEFV)(ALuint source, ALenum param, ALfloat *values);\ntypedef void          (AL_APIENTRY *LPALGETSOURCEI)(ALuint source, ALenum param, ALint *value);\ntypedef void          (AL_APIENTRY *LPALGETSOURCE3I)(ALuint source, ALenum param, ALint *value1, ALint *value2, ALint *value3);\ntypedef void          (AL_APIENTRY *LPALGETSOURCEIV)(ALuint source, ALenum param, ALint *values);\ntypedef void          (AL_APIENTRY *LPALSOURCEPLAYV)(ALsizei n, const ALuint *sources);\ntypedef void          (AL_APIENTRY *LPALSOURCESTOPV)(ALsizei n, const ALuint *sources);\ntypedef void          (AL_APIENTRY *LPALSOURCEREWINDV)(ALsizei n, const ALuint *sources);\ntypedef void          (AL_APIENTRY *LPALSOURCEPAUSEV)(ALsizei n, const ALuint *sources);\ntypedef void          (AL_APIENTRY *LPALSOURCEPLAY)(ALuint source);\ntypedef void          (AL_APIENTRY *LPALSOURCESTOP)(ALuint source);\ntypedef void          (AL_APIENTRY *LPALSOURCEREWIND)(ALuint source);\ntypedef void          (AL_APIENTRY *LPALSOURCEPAUSE)(ALuint source);\ntypedef void          (AL_APIENTRY *LPALSOURCEQUEUEBUFFERS)(ALuint source, ALsizei nb, const ALuint *buffers);\ntypedef void          (AL_APIENTRY *LPALSOURCEUNQUEUEBUFFERS)(ALuint source, ALsizei nb, ALuint *buffers);\ntypedef void          (AL_APIENTRY *LPALGENBUFFERS)(ALsizei n, ALuint *buffers);\ntypedef void          (AL_APIENTRY *LPALDELETEBUFFERS)(ALsizei n, const ALuint *buffers);\ntypedef ALboolean     (AL_APIENTRY *LPALISBUFFER)(ALuint buffer);\ntypedef void          (AL_APIENTRY *LPALBUFFERDATA)(ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei freq);\ntypedef void          (AL_APIENTRY *LPALBUFFERF)(ALuint buffer, ALenum param, ALfloat value);\ntypedef void          (AL_APIENTRY *LPALBUFFER3F)(ALuint buffer, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3);\ntypedef void          (AL_APIENTRY *LPALBUFFERFV)(ALuint buffer, ALenum param, const ALfloat *values);\ntypedef void          (AL_APIENTRY *LPALBUFFERI)(ALuint buffer, ALenum param, ALint value);\ntypedef void          (AL_APIENTRY *LPALBUFFER3I)(ALuint buffer, ALenum param, ALint value1, ALint value2, ALint value3);\ntypedef void          (AL_APIENTRY *LPALBUFFERIV)(ALuint buffer, ALenum param, const ALint *values);\ntypedef void          (AL_APIENTRY *LPALGETBUFFERF)(ALuint buffer, ALenum param, ALfloat *value);\ntypedef void          (AL_APIENTRY *LPALGETBUFFER3F)(ALuint buffer, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3);\ntypedef void          (AL_APIENTRY *LPALGETBUFFERFV)(ALuint buffer, ALenum param, ALfloat *values);\ntypedef void          (AL_APIENTRY *LPALGETBUFFERI)(ALuint buffer, ALenum param, ALint *value);\ntypedef void          (AL_APIENTRY *LPALGETBUFFER3I)(ALuint buffer, ALenum param, ALint *value1, ALint *value2, ALint *value3);\ntypedef void          (AL_APIENTRY *LPALGETBUFFERIV)(ALuint buffer, ALenum param, ALint *values);\ntypedef void          (AL_APIENTRY *LPALDOPPLERFACTOR)(ALfloat value);\ntypedef void          (AL_APIENTRY *LPALDOPPLERVELOCITY)(ALfloat value);\ntypedef void          (AL_APIENTRY *LPALSPEEDOFSOUND)(ALfloat value);\ntypedef void          (AL_APIENTRY *LPALDISTANCEMODEL)(ALenum distanceModel);\n\n#if defined(__cplusplus)\n}  /* extern \"C\" */\n#endif\n\n#endif /* AL_AL_H */\n"
  },
  {
    "path": "vendor/openal-soft/include/AL/alc.h",
    "content": "#ifndef AL_ALC_H\n#define AL_ALC_H\n\n#if defined(__cplusplus)\nextern \"C\" {\n#endif\n\n#ifndef ALC_API\n #if defined(AL_LIBTYPE_STATIC)\n  #define ALC_API\n #elif defined(_WIN32)\n  #define ALC_API __declspec(dllimport)\n #else\n  #define ALC_API extern\n #endif\n#endif\n\n#if defined(_WIN32)\n #define ALC_APIENTRY __cdecl\n#else\n #define ALC_APIENTRY\n#endif\n\n\n/* Deprecated macros. */\n#define ALCAPI                                   ALC_API\n#define ALCAPIENTRY                              ALC_APIENTRY\n#define ALC_INVALID                              0\n\n/** Supported ALC version? */\n#define ALC_VERSION_0_1                          1\n\n/** Opaque device handle */\ntypedef struct ALCdevice ALCdevice;\n/** Opaque context handle */\ntypedef struct ALCcontext ALCcontext;\n\n/** 8-bit boolean */\ntypedef char ALCboolean;\n\n/** character */\ntypedef char ALCchar;\n\n/** signed 8-bit 2's complement integer */\ntypedef signed char ALCbyte;\n\n/** unsigned 8-bit integer */\ntypedef unsigned char ALCubyte;\n\n/** signed 16-bit 2's complement integer */\ntypedef short ALCshort;\n\n/** unsigned 16-bit integer */\ntypedef unsigned short ALCushort;\n\n/** signed 32-bit 2's complement integer */\ntypedef int ALCint;\n\n/** unsigned 32-bit integer */\ntypedef unsigned int ALCuint;\n\n/** non-negative 32-bit binary integer size */\ntypedef int ALCsizei;\n\n/** enumerated 32-bit value */\ntypedef int ALCenum;\n\n/** 32-bit IEEE754 floating-point */\ntypedef float ALCfloat;\n\n/** 64-bit IEEE754 floating-point */\ntypedef double ALCdouble;\n\n/** void type (for opaque pointers only) */\ntypedef void ALCvoid;\n\n\n/* Enumerant values begin at column 50. No tabs. */\n\n/** Boolean False. */\n#define ALC_FALSE                                0\n\n/** Boolean True. */\n#define ALC_TRUE                                 1\n\n/** Context attribute: <int> Hz. */\n#define ALC_FREQUENCY                            0x1007\n\n/** Context attribute: <int> Hz. */\n#define ALC_REFRESH                              0x1008\n\n/** Context attribute: AL_TRUE or AL_FALSE synchronous context? */\n#define ALC_SYNC                                 0x1009\n\n/** Context attribute: <int> requested Mono (3D) Sources. */\n#define ALC_MONO_SOURCES                         0x1010\n\n/** Context attribute: <int> requested Stereo Sources. */\n#define ALC_STEREO_SOURCES                       0x1011\n\n/** No error. */\n#define ALC_NO_ERROR                             0\n\n/** Invalid device handle. */\n#define ALC_INVALID_DEVICE                       0xA001\n\n/** Invalid context handle. */\n#define ALC_INVALID_CONTEXT                      0xA002\n\n/** Invalid enum parameter passed to an ALC call. */\n#define ALC_INVALID_ENUM                         0xA003\n\n/** Invalid value parameter passed to an ALC call. */\n#define ALC_INVALID_VALUE                        0xA004\n\n/** Out of memory. */\n#define ALC_OUT_OF_MEMORY                        0xA005\n\n\n/** Runtime ALC major version. */\n#define ALC_MAJOR_VERSION                        0x1000\n/** Runtime ALC minor version. */\n#define ALC_MINOR_VERSION                        0x1001\n\n/** Context attribute list size. */\n#define ALC_ATTRIBUTES_SIZE                      0x1002\n/** Context attribute list properties. */\n#define ALC_ALL_ATTRIBUTES                       0x1003\n\n/** String for the default device specifier. */\n#define ALC_DEFAULT_DEVICE_SPECIFIER             0x1004\n/**\n * String for the given device's specifier.\n *\n * If device handle is NULL, it is instead a null-char separated list of\n * strings of known device specifiers (list ends with an empty string).\n */\n#define ALC_DEVICE_SPECIFIER                     0x1005\n/** String for space-separated list of ALC extensions. */\n#define ALC_EXTENSIONS                           0x1006\n\n\n/** Capture extension */\n#define ALC_EXT_CAPTURE 1\n/**\n * String for the given capture device's specifier.\n *\n * If device handle is NULL, it is instead a null-char separated list of\n * strings of known capture device specifiers (list ends with an empty string).\n */\n#define ALC_CAPTURE_DEVICE_SPECIFIER             0x310\n/** String for the default capture device specifier. */\n#define ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER     0x311\n/** Number of sample frames available for capture. */\n#define ALC_CAPTURE_SAMPLES                      0x312\n\n\n/** Enumerate All extension */\n#define ALC_ENUMERATE_ALL_EXT 1\n/** String for the default extended device specifier. */\n#define ALC_DEFAULT_ALL_DEVICES_SPECIFIER        0x1012\n/**\n * String for the given extended device's specifier.\n *\n * If device handle is NULL, it is instead a null-char separated list of\n * strings of known extended device specifiers (list ends with an empty string).\n */\n#define ALC_ALL_DEVICES_SPECIFIER                0x1013\n\n\n/* Context management. */\n\n/** Create and attach a context to the given device. */\nALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrlist);\n/**\n * Makes the given context the active process-wide context. Passing NULL clears\n * the active context.\n */\nALC_API ALCboolean  ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context);\n/** Resumes processing updates for the given context. */\nALC_API void        ALC_APIENTRY alcProcessContext(ALCcontext *context);\n/** Suspends updates for the given context. */\nALC_API void        ALC_APIENTRY alcSuspendContext(ALCcontext *context);\n/** Remove a context from its device and destroys it. */\nALC_API void        ALC_APIENTRY alcDestroyContext(ALCcontext *context);\n/** Returns the currently active context. */\nALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void);\n/** Returns the device that a particular context is attached to. */\nALC_API ALCdevice*  ALC_APIENTRY alcGetContextsDevice(ALCcontext *context);\n\n/* Device management. */\n\n/** Opens the named playback device. */\nALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *devicename);\n/** Closes the given playback device. */\nALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *device);\n\n/* Error support. */\n\n/** Obtain the most recent Device error. */\nALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device);\n\n/* Extension support. */\n\n/**\n * Query for the presence of an extension on the device. Pass a NULL device to\n * query a device-inspecific extension.\n */\nALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extname);\n/**\n * Retrieve the address of a function. Given a non-NULL device, the returned\n * function may be device-specific.\n */\nALC_API ALCvoid*   ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcname);\n/**\n * Retrieve the value of an enum. Given a non-NULL device, the returned value\n * may be device-specific.\n */\nALC_API ALCenum    ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumname);\n\n/* Query functions. */\n\n/** Returns information about the device, and error strings. */\nALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *device, ALCenum param);\n/** Returns information about the device and the version of OpenAL. */\nALC_API void           ALC_APIENTRY alcGetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values);\n\n/* Capture functions. */\n\n/**\n * Opens the named capture device with the given frequency, format, and buffer\n * size.\n */\nALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *devicename, ALCuint frequency, ALCenum format, ALCsizei buffersize);\n/** Closes the given capture device. */\nALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *device);\n/** Starts capturing samples into the device buffer.  */\nALC_API void       ALC_APIENTRY alcCaptureStart(ALCdevice *device);\n/** Stops capturing samples. Samples in the device buffer remain available. */\nALC_API void       ALC_APIENTRY alcCaptureStop(ALCdevice *device);\n/** Reads samples from the device buffer. */\nALC_API void       ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples);\n\n/* Pointer-to-function type, useful for dynamically getting ALC entry points. */\ntypedef ALCcontext*    (ALC_APIENTRY *LPALCCREATECONTEXT)(ALCdevice *device, const ALCint *attrlist);\ntypedef ALCboolean     (ALC_APIENTRY *LPALCMAKECONTEXTCURRENT)(ALCcontext *context);\ntypedef void           (ALC_APIENTRY *LPALCPROCESSCONTEXT)(ALCcontext *context);\ntypedef void           (ALC_APIENTRY *LPALCSUSPENDCONTEXT)(ALCcontext *context);\ntypedef void           (ALC_APIENTRY *LPALCDESTROYCONTEXT)(ALCcontext *context);\ntypedef ALCcontext*    (ALC_APIENTRY *LPALCGETCURRENTCONTEXT)(void);\ntypedef ALCdevice*     (ALC_APIENTRY *LPALCGETCONTEXTSDEVICE)(ALCcontext *context);\ntypedef ALCdevice*     (ALC_APIENTRY *LPALCOPENDEVICE)(const ALCchar *devicename);\ntypedef ALCboolean     (ALC_APIENTRY *LPALCCLOSEDEVICE)(ALCdevice *device);\ntypedef ALCenum        (ALC_APIENTRY *LPALCGETERROR)(ALCdevice *device);\ntypedef ALCboolean     (ALC_APIENTRY *LPALCISEXTENSIONPRESENT)(ALCdevice *device, const ALCchar *extname);\ntypedef ALCvoid*       (ALC_APIENTRY *LPALCGETPROCADDRESS)(ALCdevice *device, const ALCchar *funcname);\ntypedef ALCenum        (ALC_APIENTRY *LPALCGETENUMVALUE)(ALCdevice *device, const ALCchar *enumname);\ntypedef const ALCchar* (ALC_APIENTRY *LPALCGETSTRING)(ALCdevice *device, ALCenum param);\ntypedef void           (ALC_APIENTRY *LPALCGETINTEGERV)(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values);\ntypedef ALCdevice*     (ALC_APIENTRY *LPALCCAPTUREOPENDEVICE)(const ALCchar *devicename, ALCuint frequency, ALCenum format, ALCsizei buffersize);\ntypedef ALCboolean     (ALC_APIENTRY *LPALCCAPTURECLOSEDEVICE)(ALCdevice *device);\ntypedef void           (ALC_APIENTRY *LPALCCAPTURESTART)(ALCdevice *device);\ntypedef void           (ALC_APIENTRY *LPALCCAPTURESTOP)(ALCdevice *device);\ntypedef void           (ALC_APIENTRY *LPALCCAPTURESAMPLES)(ALCdevice *device, ALCvoid *buffer, ALCsizei samples);\n\n#if defined(__cplusplus)\n}\n#endif\n\n#endif /* AL_ALC_H */\n"
  },
  {
    "path": "vendor/openal-soft/include/AL/alext.h",
    "content": "/**\n * OpenAL cross platform audio library\n * Copyright (C) 2008 by authors.\n * This library is free software; you can redistribute it and/or\n *  modify it under the terms of the GNU Library General Public\n *  License as published by the Free Software Foundation; either\n *  version 2 of the License, or (at your option) any later version.\n *\n * This library is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n *  Library General Public License for more details.\n *\n * You should have received a copy of the GNU Library General Public\n *  License along with this library; if not, write to the\n *  Free Software Foundation, Inc.,\n *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n * Or go to http://www.gnu.org/copyleft/lgpl.html\n */\n\n#ifndef AL_ALEXT_H\n#define AL_ALEXT_H\n\n#include <stddef.h>\n/* Define int64_t and uint64_t types */\n#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L\n#include <inttypes.h>\n#elif defined(__cplusplus) && __cplusplus >= 201103L\n#include <cinttypes>\n#elif defined(_WIN32) && defined(__GNUC__)\n#include <stdint.h>\n#elif defined(_WIN32)\ntypedef __int64 int64_t;\ntypedef unsigned __int64 uint64_t;\n#else\n/* Fallback if nothing above works */\n#include <inttypes.h>\n#endif\n\n#include \"alc.h\"\n#include \"al.h\"\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#ifndef AL_LOKI_IMA_ADPCM_format\n#define AL_LOKI_IMA_ADPCM_format 1\n#define AL_FORMAT_IMA_ADPCM_MONO16_EXT           0x10000\n#define AL_FORMAT_IMA_ADPCM_STEREO16_EXT         0x10001\n#endif\n\n#ifndef AL_LOKI_WAVE_format\n#define AL_LOKI_WAVE_format 1\n#define AL_FORMAT_WAVE_EXT                       0x10002\n#endif\n\n#ifndef AL_EXT_vorbis\n#define AL_EXT_vorbis 1\n#define AL_FORMAT_VORBIS_EXT                     0x10003\n#endif\n\n#ifndef AL_LOKI_quadriphonic\n#define AL_LOKI_quadriphonic 1\n#define AL_FORMAT_QUAD8_LOKI                     0x10004\n#define AL_FORMAT_QUAD16_LOKI                    0x10005\n#endif\n\n#ifndef AL_EXT_float32\n#define AL_EXT_float32 1\n#define AL_FORMAT_MONO_FLOAT32                   0x10010\n#define AL_FORMAT_STEREO_FLOAT32                 0x10011\n#endif\n\n#ifndef AL_EXT_double\n#define AL_EXT_double 1\n#define AL_FORMAT_MONO_DOUBLE_EXT                0x10012\n#define AL_FORMAT_STEREO_DOUBLE_EXT              0x10013\n#endif\n\n#ifndef AL_EXT_MULAW\n#define AL_EXT_MULAW 1\n#define AL_FORMAT_MONO_MULAW_EXT                 0x10014\n#define AL_FORMAT_STEREO_MULAW_EXT               0x10015\n#endif\n\n#ifndef AL_EXT_ALAW\n#define AL_EXT_ALAW 1\n#define AL_FORMAT_MONO_ALAW_EXT                  0x10016\n#define AL_FORMAT_STEREO_ALAW_EXT                0x10017\n#endif\n\n#ifndef ALC_LOKI_audio_channel\n#define ALC_LOKI_audio_channel 1\n#define ALC_CHAN_MAIN_LOKI                       0x500001\n#define ALC_CHAN_PCM_LOKI                        0x500002\n#define ALC_CHAN_CD_LOKI                         0x500003\n#endif\n\n#ifndef AL_EXT_MCFORMATS\n#define AL_EXT_MCFORMATS 1\n/* Provides support for surround sound buffer formats with 8, 16, and 32-bit\n * samples.\n *\n * QUAD8: Unsigned 8-bit, Quadraphonic (Front Left, Front Right, Rear Left,\n *        Rear Right).\n * QUAD16: Signed 16-bit, Quadraphonic.\n * QUAD32: 32-bit float, Quadraphonic.\n * REAR8: Unsigned 8-bit, Rear Stereo (Rear Left, Rear Right).\n * REAR16: Signed 16-bit, Rear Stereo.\n * REAR32: 32-bit float, Rear Stereo.\n * 51CHN8: Unsigned 8-bit, 5.1 Surround (Front Left, Front Right, Front Center,\n *         LFE, Side Left, Side Right). Note that some audio systems may label\n *         5.1's Side channels as Rear or Surround; they are equivalent for the\n *         purposes of this extension.\n * 51CHN16: Signed 16-bit, 5.1 Surround.\n * 51CHN32: 32-bit float, 5.1 Surround.\n * 61CHN8: Unsigned 8-bit, 6.1 Surround (Front Left, Front Right, Front Center,\n *         LFE, Rear Center, Side Left, Side Right).\n * 61CHN16: Signed 16-bit, 6.1 Surround.\n * 61CHN32: 32-bit float, 6.1 Surround.\n * 71CHN8: Unsigned 8-bit, 7.1 Surround (Front Left, Front Right, Front Center,\n *         LFE, Rear Left, Rear Right, Side Left, Side Right).\n * 71CHN16: Signed 16-bit, 7.1 Surround.\n * 71CHN32: 32-bit float, 7.1 Surround.\n */\n#define AL_FORMAT_QUAD8                          0x1204\n#define AL_FORMAT_QUAD16                         0x1205\n#define AL_FORMAT_QUAD32                         0x1206\n#define AL_FORMAT_REAR8                          0x1207\n#define AL_FORMAT_REAR16                         0x1208\n#define AL_FORMAT_REAR32                         0x1209\n#define AL_FORMAT_51CHN8                         0x120A\n#define AL_FORMAT_51CHN16                        0x120B\n#define AL_FORMAT_51CHN32                        0x120C\n#define AL_FORMAT_61CHN8                         0x120D\n#define AL_FORMAT_61CHN16                        0x120E\n#define AL_FORMAT_61CHN32                        0x120F\n#define AL_FORMAT_71CHN8                         0x1210\n#define AL_FORMAT_71CHN16                        0x1211\n#define AL_FORMAT_71CHN32                        0x1212\n#endif\n\n#ifndef AL_EXT_MULAW_MCFORMATS\n#define AL_EXT_MULAW_MCFORMATS 1\n#define AL_FORMAT_MONO_MULAW                     0x10014\n#define AL_FORMAT_STEREO_MULAW                   0x10015\n#define AL_FORMAT_QUAD_MULAW                     0x10021\n#define AL_FORMAT_REAR_MULAW                     0x10022\n#define AL_FORMAT_51CHN_MULAW                    0x10023\n#define AL_FORMAT_61CHN_MULAW                    0x10024\n#define AL_FORMAT_71CHN_MULAW                    0x10025\n#endif\n\n#ifndef AL_EXT_IMA4\n#define AL_EXT_IMA4 1\n#define AL_FORMAT_MONO_IMA4                      0x1300\n#define AL_FORMAT_STEREO_IMA4                    0x1301\n#endif\n\n#ifndef AL_EXT_STATIC_BUFFER\n#define AL_EXT_STATIC_BUFFER 1\ntypedef void (AL_APIENTRY*PFNALBUFFERDATASTATICPROC)(const ALint,ALenum,ALvoid*,ALsizei,ALsizei);\n#ifdef AL_ALEXT_PROTOTYPES\nAL_API void AL_APIENTRY alBufferDataStatic(const ALint buffer, ALenum format, ALvoid *data, ALsizei len, ALsizei freq);\n#endif\n#endif\n\n#ifndef ALC_EXT_EFX\n#define ALC_EXT_EFX 1\n#include \"efx.h\"\n#endif\n\n#ifndef ALC_EXT_disconnect\n#define ALC_EXT_disconnect 1\n#define ALC_CONNECTED                            0x313\n#endif\n\n#ifndef ALC_EXT_thread_local_context\n#define ALC_EXT_thread_local_context 1\ntypedef ALCboolean  (ALC_APIENTRY*PFNALCSETTHREADCONTEXTPROC)(ALCcontext *context);\ntypedef ALCcontext* (ALC_APIENTRY*PFNALCGETTHREADCONTEXTPROC)(void);\n#ifdef AL_ALEXT_PROTOTYPES\nALC_API ALCboolean  ALC_APIENTRY alcSetThreadContext(ALCcontext *context);\nALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void);\n#endif\n#endif\n\n#ifndef AL_EXT_source_distance_model\n#define AL_EXT_source_distance_model 1\n#define AL_SOURCE_DISTANCE_MODEL                 0x200\n#endif\n\n#ifndef AL_SOFT_buffer_sub_data\n#define AL_SOFT_buffer_sub_data 1\n#define AL_BYTE_RW_OFFSETS_SOFT                  0x1031\n#define AL_SAMPLE_RW_OFFSETS_SOFT                0x1032\ntypedef void (AL_APIENTRY*PFNALBUFFERSUBDATASOFTPROC)(ALuint,ALenum,const ALvoid*,ALsizei,ALsizei);\n#ifdef AL_ALEXT_PROTOTYPES\nAL_API void AL_APIENTRY alBufferSubDataSOFT(ALuint buffer,ALenum format,const ALvoid *data,ALsizei offset,ALsizei length);\n#endif\n#endif\n\n#ifndef AL_SOFT_loop_points\n#define AL_SOFT_loop_points 1\n#define AL_LOOP_POINTS_SOFT                      0x2015\n#endif\n\n#ifndef AL_EXT_FOLDBACK\n#define AL_EXT_FOLDBACK 1\n#define AL_EXT_FOLDBACK_NAME                     \"AL_EXT_FOLDBACK\"\n#define AL_FOLDBACK_EVENT_BLOCK                  0x4112\n#define AL_FOLDBACK_EVENT_START                  0x4111\n#define AL_FOLDBACK_EVENT_STOP                   0x4113\n#define AL_FOLDBACK_MODE_MONO                    0x4101\n#define AL_FOLDBACK_MODE_STEREO                  0x4102\ntypedef void (AL_APIENTRY*LPALFOLDBACKCALLBACK)(ALenum,ALsizei);\ntypedef void (AL_APIENTRY*LPALREQUESTFOLDBACKSTART)(ALenum,ALsizei,ALsizei,ALfloat*,LPALFOLDBACKCALLBACK);\ntypedef void (AL_APIENTRY*LPALREQUESTFOLDBACKSTOP)(void);\n#ifdef AL_ALEXT_PROTOTYPES\nAL_API void AL_APIENTRY alRequestFoldbackStart(ALenum mode,ALsizei count,ALsizei length,ALfloat *mem,LPALFOLDBACKCALLBACK callback);\nAL_API void AL_APIENTRY alRequestFoldbackStop(void);\n#endif\n#endif\n\n#ifndef ALC_EXT_DEDICATED\n#define ALC_EXT_DEDICATED 1\n#define AL_DEDICATED_GAIN                        0x0001\n#define AL_EFFECT_DEDICATED_DIALOGUE             0x9001\n#define AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT 0x9000\n#endif\n\n#ifndef AL_SOFT_buffer_samples\n#define AL_SOFT_buffer_samples 1\n/* Channel configurations */\n#define AL_MONO_SOFT                             0x1500\n#define AL_STEREO_SOFT                           0x1501\n#define AL_REAR_SOFT                             0x1502\n#define AL_QUAD_SOFT                             0x1503\n#define AL_5POINT1_SOFT                          0x1504\n#define AL_6POINT1_SOFT                          0x1505\n#define AL_7POINT1_SOFT                          0x1506\n\n/* Sample types */\n#define AL_BYTE_SOFT                             0x1400\n#define AL_UNSIGNED_BYTE_SOFT                    0x1401\n#define AL_SHORT_SOFT                            0x1402\n#define AL_UNSIGNED_SHORT_SOFT                   0x1403\n#define AL_INT_SOFT                              0x1404\n#define AL_UNSIGNED_INT_SOFT                     0x1405\n#define AL_FLOAT_SOFT                            0x1406\n#define AL_DOUBLE_SOFT                           0x1407\n#define AL_BYTE3_SOFT                            0x1408\n#define AL_UNSIGNED_BYTE3_SOFT                   0x1409\n\n/* Storage formats */\n#define AL_MONO8_SOFT                            0x1100\n#define AL_MONO16_SOFT                           0x1101\n#define AL_MONO32F_SOFT                          0x10010\n#define AL_STEREO8_SOFT                          0x1102\n#define AL_STEREO16_SOFT                         0x1103\n#define AL_STEREO32F_SOFT                        0x10011\n#define AL_QUAD8_SOFT                            0x1204\n#define AL_QUAD16_SOFT                           0x1205\n#define AL_QUAD32F_SOFT                          0x1206\n#define AL_REAR8_SOFT                            0x1207\n#define AL_REAR16_SOFT                           0x1208\n#define AL_REAR32F_SOFT                          0x1209\n#define AL_5POINT1_8_SOFT                        0x120A\n#define AL_5POINT1_16_SOFT                       0x120B\n#define AL_5POINT1_32F_SOFT                      0x120C\n#define AL_6POINT1_8_SOFT                        0x120D\n#define AL_6POINT1_16_SOFT                       0x120E\n#define AL_6POINT1_32F_SOFT                      0x120F\n#define AL_7POINT1_8_SOFT                        0x1210\n#define AL_7POINT1_16_SOFT                       0x1211\n#define AL_7POINT1_32F_SOFT                      0x1212\n\n/* Buffer attributes */\n#define AL_INTERNAL_FORMAT_SOFT                  0x2008\n#define AL_BYTE_LENGTH_SOFT                      0x2009\n#define AL_SAMPLE_LENGTH_SOFT                    0x200A\n#define AL_SEC_LENGTH_SOFT                       0x200B\n\ntypedef void (AL_APIENTRY*LPALBUFFERSAMPLESSOFT)(ALuint,ALuint,ALenum,ALsizei,ALenum,ALenum,const ALvoid*);\ntypedef void (AL_APIENTRY*LPALBUFFERSUBSAMPLESSOFT)(ALuint,ALsizei,ALsizei,ALenum,ALenum,const ALvoid*);\ntypedef void (AL_APIENTRY*LPALGETBUFFERSAMPLESSOFT)(ALuint,ALsizei,ALsizei,ALenum,ALenum,ALvoid*);\ntypedef ALboolean (AL_APIENTRY*LPALISBUFFERFORMATSUPPORTEDSOFT)(ALenum);\n#ifdef AL_ALEXT_PROTOTYPES\nAL_API void AL_APIENTRY alBufferSamplesSOFT(ALuint buffer, ALuint samplerate, ALenum internalformat, ALsizei samples, ALenum channels, ALenum type, const ALvoid *data);\nAL_API void AL_APIENTRY alBufferSubSamplesSOFT(ALuint buffer, ALsizei offset, ALsizei samples, ALenum channels, ALenum type, const ALvoid *data);\nAL_API void AL_APIENTRY alGetBufferSamplesSOFT(ALuint buffer, ALsizei offset, ALsizei samples, ALenum channels, ALenum type, ALvoid *data);\nAL_API ALboolean AL_APIENTRY alIsBufferFormatSupportedSOFT(ALenum format);\n#endif\n#endif\n\n#ifndef AL_SOFT_direct_channels\n#define AL_SOFT_direct_channels 1\n#define AL_DIRECT_CHANNELS_SOFT                  0x1033\n#endif\n\n#ifndef ALC_SOFT_loopback\n#define ALC_SOFT_loopback 1\n#define ALC_FORMAT_CHANNELS_SOFT                 0x1990\n#define ALC_FORMAT_TYPE_SOFT                     0x1991\n\n/* Sample types */\n#define ALC_BYTE_SOFT                            0x1400\n#define ALC_UNSIGNED_BYTE_SOFT                   0x1401\n#define ALC_SHORT_SOFT                           0x1402\n#define ALC_UNSIGNED_SHORT_SOFT                  0x1403\n#define ALC_INT_SOFT                             0x1404\n#define ALC_UNSIGNED_INT_SOFT                    0x1405\n#define ALC_FLOAT_SOFT                           0x1406\n\n/* Channel configurations */\n#define ALC_MONO_SOFT                            0x1500\n#define ALC_STEREO_SOFT                          0x1501\n#define ALC_QUAD_SOFT                            0x1503\n#define ALC_5POINT1_SOFT                         0x1504\n#define ALC_6POINT1_SOFT                         0x1505\n#define ALC_7POINT1_SOFT                         0x1506\n\ntypedef ALCdevice* (ALC_APIENTRY*LPALCLOOPBACKOPENDEVICESOFT)(const ALCchar*);\ntypedef ALCboolean (ALC_APIENTRY*LPALCISRENDERFORMATSUPPORTEDSOFT)(ALCdevice*,ALCsizei,ALCenum,ALCenum);\ntypedef void (ALC_APIENTRY*LPALCRENDERSAMPLESSOFT)(ALCdevice*,ALCvoid*,ALCsizei);\n#ifdef AL_ALEXT_PROTOTYPES\nALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceName);\nALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type);\nALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples);\n#endif\n#endif\n\n#ifndef AL_EXT_STEREO_ANGLES\n#define AL_EXT_STEREO_ANGLES 1\n#define AL_STEREO_ANGLES                         0x1030\n#endif\n\n#ifndef AL_EXT_SOURCE_RADIUS\n#define AL_EXT_SOURCE_RADIUS 1\n#define AL_SOURCE_RADIUS                         0x1031\n#endif\n\n#ifndef AL_SOFT_source_latency\n#define AL_SOFT_source_latency 1\n#define AL_SAMPLE_OFFSET_LATENCY_SOFT            0x1200\n#define AL_SEC_OFFSET_LATENCY_SOFT               0x1201\ntypedef int64_t ALint64SOFT;\ntypedef uint64_t ALuint64SOFT;\ntypedef void (AL_APIENTRY*LPALSOURCEDSOFT)(ALuint,ALenum,ALdouble);\ntypedef void (AL_APIENTRY*LPALSOURCE3DSOFT)(ALuint,ALenum,ALdouble,ALdouble,ALdouble);\ntypedef void (AL_APIENTRY*LPALSOURCEDVSOFT)(ALuint,ALenum,const ALdouble*);\ntypedef void (AL_APIENTRY*LPALGETSOURCEDSOFT)(ALuint,ALenum,ALdouble*);\ntypedef void (AL_APIENTRY*LPALGETSOURCE3DSOFT)(ALuint,ALenum,ALdouble*,ALdouble*,ALdouble*);\ntypedef void (AL_APIENTRY*LPALGETSOURCEDVSOFT)(ALuint,ALenum,ALdouble*);\ntypedef void (AL_APIENTRY*LPALSOURCEI64SOFT)(ALuint,ALenum,ALint64SOFT);\ntypedef void (AL_APIENTRY*LPALSOURCE3I64SOFT)(ALuint,ALenum,ALint64SOFT,ALint64SOFT,ALint64SOFT);\ntypedef void (AL_APIENTRY*LPALSOURCEI64VSOFT)(ALuint,ALenum,const ALint64SOFT*);\ntypedef void (AL_APIENTRY*LPALGETSOURCEI64SOFT)(ALuint,ALenum,ALint64SOFT*);\ntypedef void (AL_APIENTRY*LPALGETSOURCE3I64SOFT)(ALuint,ALenum,ALint64SOFT*,ALint64SOFT*,ALint64SOFT*);\ntypedef void (AL_APIENTRY*LPALGETSOURCEI64VSOFT)(ALuint,ALenum,ALint64SOFT*);\n#ifdef AL_ALEXT_PROTOTYPES\nAL_API void AL_APIENTRY alSourcedSOFT(ALuint source, ALenum param, ALdouble value);\nAL_API void AL_APIENTRY alSource3dSOFT(ALuint source, ALenum param, ALdouble value1, ALdouble value2, ALdouble value3);\nAL_API void AL_APIENTRY alSourcedvSOFT(ALuint source, ALenum param, const ALdouble *values);\nAL_API void AL_APIENTRY alGetSourcedSOFT(ALuint source, ALenum param, ALdouble *value);\nAL_API void AL_APIENTRY alGetSource3dSOFT(ALuint source, ALenum param, ALdouble *value1, ALdouble *value2, ALdouble *value3);\nAL_API void AL_APIENTRY alGetSourcedvSOFT(ALuint source, ALenum param, ALdouble *values);\nAL_API void AL_APIENTRY alSourcei64SOFT(ALuint source, ALenum param, ALint64SOFT value);\nAL_API void AL_APIENTRY alSource3i64SOFT(ALuint source, ALenum param, ALint64SOFT value1, ALint64SOFT value2, ALint64SOFT value3);\nAL_API void AL_APIENTRY alSourcei64vSOFT(ALuint source, ALenum param, const ALint64SOFT *values);\nAL_API void AL_APIENTRY alGetSourcei64SOFT(ALuint source, ALenum param, ALint64SOFT *value);\nAL_API void AL_APIENTRY alGetSource3i64SOFT(ALuint source, ALenum param, ALint64SOFT *value1, ALint64SOFT *value2, ALint64SOFT *value3);\nAL_API void AL_APIENTRY alGetSourcei64vSOFT(ALuint source, ALenum param, ALint64SOFT *values);\n#endif\n#endif\n\n#ifndef ALC_EXT_DEFAULT_FILTER_ORDER\n#define ALC_EXT_DEFAULT_FILTER_ORDER 1\n#define ALC_DEFAULT_FILTER_ORDER                 0x1100\n#endif\n\n#ifndef AL_SOFT_deferred_updates\n#define AL_SOFT_deferred_updates 1\n#define AL_DEFERRED_UPDATES_SOFT                 0xC002\ntypedef void (AL_APIENTRY*LPALDEFERUPDATESSOFT)(void);\ntypedef void (AL_APIENTRY*LPALPROCESSUPDATESSOFT)(void);\n#ifdef AL_ALEXT_PROTOTYPES\nAL_API void AL_APIENTRY alDeferUpdatesSOFT(void);\nAL_API void AL_APIENTRY alProcessUpdatesSOFT(void);\n#endif\n#endif\n\n#ifndef AL_SOFT_block_alignment\n#define AL_SOFT_block_alignment 1\n#define AL_UNPACK_BLOCK_ALIGNMENT_SOFT           0x200C\n#define AL_PACK_BLOCK_ALIGNMENT_SOFT             0x200D\n#endif\n\n#ifndef AL_SOFT_MSADPCM\n#define AL_SOFT_MSADPCM 1\n#define AL_FORMAT_MONO_MSADPCM_SOFT              0x1302\n#define AL_FORMAT_STEREO_MSADPCM_SOFT            0x1303\n#endif\n\n#ifndef AL_SOFT_source_length\n#define AL_SOFT_source_length 1\n/*#define AL_BYTE_LENGTH_SOFT                      0x2009*/\n/*#define AL_SAMPLE_LENGTH_SOFT                    0x200A*/\n/*#define AL_SEC_LENGTH_SOFT                       0x200B*/\n#endif\n\n#ifndef ALC_SOFT_pause_device\n#define ALC_SOFT_pause_device 1\ntypedef void (ALC_APIENTRY*LPALCDEVICEPAUSESOFT)(ALCdevice *device);\ntypedef void (ALC_APIENTRY*LPALCDEVICERESUMESOFT)(ALCdevice *device);\n#ifdef AL_ALEXT_PROTOTYPES\nALC_API void ALC_APIENTRY alcDevicePauseSOFT(ALCdevice *device);\nALC_API void ALC_APIENTRY alcDeviceResumeSOFT(ALCdevice *device);\n#endif\n#endif\n\n#ifndef AL_EXT_BFORMAT\n#define AL_EXT_BFORMAT 1\n/* Provides support for B-Format ambisonic buffers (first-order, FuMa scaling\n * and layout).\n *\n * BFORMAT2D_8: Unsigned 8-bit, 3-channel non-periphonic (WXY).\n * BFORMAT2D_16: Signed 16-bit, 3-channel non-periphonic (WXY).\n * BFORMAT2D_FLOAT32: 32-bit float, 3-channel non-periphonic (WXY).\n * BFORMAT3D_8: Unsigned 8-bit, 4-channel periphonic (WXYZ).\n * BFORMAT3D_16: Signed 16-bit, 4-channel periphonic (WXYZ).\n * BFORMAT3D_FLOAT32: 32-bit float, 4-channel periphonic (WXYZ).\n */\n#define AL_FORMAT_BFORMAT2D_8                    0x20021\n#define AL_FORMAT_BFORMAT2D_16                   0x20022\n#define AL_FORMAT_BFORMAT2D_FLOAT32              0x20023\n#define AL_FORMAT_BFORMAT3D_8                    0x20031\n#define AL_FORMAT_BFORMAT3D_16                   0x20032\n#define AL_FORMAT_BFORMAT3D_FLOAT32              0x20033\n#endif\n\n#ifndef AL_EXT_MULAW_BFORMAT\n#define AL_EXT_MULAW_BFORMAT 1\n#define AL_FORMAT_BFORMAT2D_MULAW                0x10031\n#define AL_FORMAT_BFORMAT3D_MULAW                0x10032\n#endif\n\n#ifndef ALC_SOFT_HRTF\n#define ALC_SOFT_HRTF 1\n#define ALC_HRTF_SOFT                            0x1992\n#define ALC_DONT_CARE_SOFT                       0x0002\n#define ALC_HRTF_STATUS_SOFT                     0x1993\n#define ALC_HRTF_DISABLED_SOFT                   0x0000\n#define ALC_HRTF_ENABLED_SOFT                    0x0001\n#define ALC_HRTF_DENIED_SOFT                     0x0002\n#define ALC_HRTF_REQUIRED_SOFT                   0x0003\n#define ALC_HRTF_HEADPHONES_DETECTED_SOFT        0x0004\n#define ALC_HRTF_UNSUPPORTED_FORMAT_SOFT         0x0005\n#define ALC_NUM_HRTF_SPECIFIERS_SOFT             0x1994\n#define ALC_HRTF_SPECIFIER_SOFT                  0x1995\n#define ALC_HRTF_ID_SOFT                         0x1996\ntypedef const ALCchar* (ALC_APIENTRY*LPALCGETSTRINGISOFT)(ALCdevice *device, ALCenum paramName, ALCsizei index);\ntypedef ALCboolean (ALC_APIENTRY*LPALCRESETDEVICESOFT)(ALCdevice *device, const ALCint *attribs);\n#ifdef AL_ALEXT_PROTOTYPES\nALC_API const ALCchar* ALC_APIENTRY alcGetStringiSOFT(ALCdevice *device, ALCenum paramName, ALCsizei index);\nALC_API ALCboolean ALC_APIENTRY alcResetDeviceSOFT(ALCdevice *device, const ALCint *attribs);\n#endif\n#endif\n\n#ifndef AL_SOFT_gain_clamp_ex\n#define AL_SOFT_gain_clamp_ex 1\n#define AL_GAIN_LIMIT_SOFT                       0x200E\n#endif\n\n#ifndef AL_SOFT_source_resampler\n#define AL_SOFT_source_resampler\n#define AL_NUM_RESAMPLERS_SOFT                   0x1210\n#define AL_DEFAULT_RESAMPLER_SOFT                0x1211\n#define AL_SOURCE_RESAMPLER_SOFT                 0x1212\n#define AL_RESAMPLER_NAME_SOFT                   0x1213\ntypedef const ALchar* (AL_APIENTRY*LPALGETSTRINGISOFT)(ALenum pname, ALsizei index);\n#ifdef AL_ALEXT_PROTOTYPES\nAL_API const ALchar* AL_APIENTRY alGetStringiSOFT(ALenum pname, ALsizei index);\n#endif\n#endif\n\n#ifndef AL_SOFT_source_spatialize\n#define AL_SOFT_source_spatialize\n#define AL_SOURCE_SPATIALIZE_SOFT                0x1214\n#define AL_AUTO_SOFT                             0x0002\n#endif\n\n#ifndef ALC_SOFT_output_limiter\n#define ALC_SOFT_output_limiter\n#define ALC_OUTPUT_LIMITER_SOFT                  0x199A\n#endif\n\n#ifndef ALC_SOFT_device_clock\n#define ALC_SOFT_device_clock 1\ntypedef int64_t ALCint64SOFT;\ntypedef uint64_t ALCuint64SOFT;\n#define ALC_DEVICE_CLOCK_SOFT                    0x1600\n#define ALC_DEVICE_LATENCY_SOFT                  0x1601\n#define ALC_DEVICE_CLOCK_LATENCY_SOFT            0x1602\n#define AL_SAMPLE_OFFSET_CLOCK_SOFT              0x1202\n#define AL_SEC_OFFSET_CLOCK_SOFT                 0x1203\ntypedef void (ALC_APIENTRY*LPALCGETINTEGER64VSOFT)(ALCdevice *device, ALCenum pname, ALsizei size, ALCint64SOFT *values);\n#ifdef AL_ALEXT_PROTOTYPES\nALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, ALsizei size, ALCint64SOFT *values);\n#endif\n#endif\n\n#ifndef AL_SOFT_direct_channels_remix\n#define AL_SOFT_direct_channels_remix 1\n#define AL_DROP_UNMATCHED_SOFT                   0x0001\n#define AL_REMIX_UNMATCHED_SOFT                  0x0002\n#endif\n\n#ifndef AL_SOFT_bformat_ex\n#define AL_SOFT_bformat_ex 1\n#define AL_AMBISONIC_LAYOUT_SOFT                 0x1997\n#define AL_AMBISONIC_SCALING_SOFT                0x1998\n\n/* Ambisonic layouts */\n#define AL_FUMA_SOFT                             0x0000\n#define AL_ACN_SOFT                              0x0001\n\n/* Ambisonic scalings (normalization) */\n/*#define AL_FUMA_SOFT*/\n#define AL_SN3D_SOFT                             0x0001\n#define AL_N3D_SOFT                              0x0002\n#endif\n\n#ifndef ALC_SOFT_loopback_bformat\n#define ALC_SOFT_loopback_bformat 1\n#define ALC_AMBISONIC_LAYOUT_SOFT                0x1997\n#define ALC_AMBISONIC_SCALING_SOFT               0x1998\n#define ALC_AMBISONIC_ORDER_SOFT                 0x1999\n#define ALC_MAX_AMBISONIC_ORDER_SOFT             0x199B\n\n#define ALC_BFORMAT3D_SOFT                       0x1507\n\n/* Ambisonic layouts */\n#define ALC_FUMA_SOFT                            0x0000\n#define ALC_ACN_SOFT                             0x0001\n\n/* Ambisonic scalings (normalization) */\n/*#define ALC_FUMA_SOFT*/\n#define ALC_SN3D_SOFT                            0x0001\n#define ALC_N3D_SOFT                             0x0002\n#endif\n\n#ifndef AL_SOFT_effect_target\n#define AL_SOFT_effect_target\n#define AL_EFFECTSLOT_TARGET_SOFT                0x199C\n#endif\n\n#ifndef AL_SOFT_events\n#define AL_SOFT_events 1\n#define AL_EVENT_CALLBACK_FUNCTION_SOFT          0x19A2\n#define AL_EVENT_CALLBACK_USER_PARAM_SOFT        0x19A3\n#define AL_EVENT_TYPE_BUFFER_COMPLETED_SOFT      0x19A4\n#define AL_EVENT_TYPE_SOURCE_STATE_CHANGED_SOFT  0x19A5\n#define AL_EVENT_TYPE_DISCONNECTED_SOFT          0x19A6\ntypedef void (AL_APIENTRY*ALEVENTPROCSOFT)(ALenum eventType, ALuint object, ALuint param,\n                                           ALsizei length, const ALchar *message,\n                                           void *userParam);\ntypedef void (AL_APIENTRY*LPALEVENTCONTROLSOFT)(ALsizei count, const ALenum *types, ALboolean enable);\ntypedef void (AL_APIENTRY*LPALEVENTCALLBACKSOFT)(ALEVENTPROCSOFT callback, void *userParam);\ntypedef void* (AL_APIENTRY*LPALGETPOINTERSOFT)(ALenum pname);\ntypedef void (AL_APIENTRY*LPALGETPOINTERVSOFT)(ALenum pname, void **values);\n#ifdef AL_ALEXT_PROTOTYPES\nAL_API void AL_APIENTRY alEventControlSOFT(ALsizei count, const ALenum *types, ALboolean enable);\nAL_API void AL_APIENTRY alEventCallbackSOFT(ALEVENTPROCSOFT callback, void *userParam);\nAL_API void* AL_APIENTRY alGetPointerSOFT(ALenum pname);\nAL_API void AL_APIENTRY alGetPointervSOFT(ALenum pname, void **values);\n#endif\n#endif\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "vendor/openal-soft/include/AL/efx-creative.h",
    "content": "/* The tokens that would be defined here are already defined in efx.h. This\n * empty file is here to provide compatibility with Windows-based projects\n * that would include it. */\n"
  },
  {
    "path": "vendor/openal-soft/include/AL/efx-presets.h",
    "content": "/* Reverb presets for EFX */\n\n#ifndef EFX_PRESETS_H\n#define EFX_PRESETS_H\n\n#ifndef EFXEAXREVERBPROPERTIES_DEFINED\n#define EFXEAXREVERBPROPERTIES_DEFINED\ntypedef struct {\n    float flDensity;\n    float flDiffusion;\n    float flGain;\n    float flGainHF;\n    float flGainLF;\n    float flDecayTime;\n    float flDecayHFRatio;\n    float flDecayLFRatio;\n    float flReflectionsGain;\n    float flReflectionsDelay;\n    float flReflectionsPan[3];\n    float flLateReverbGain;\n    float flLateReverbDelay;\n    float flLateReverbPan[3];\n    float flEchoTime;\n    float flEchoDepth;\n    float flModulationTime;\n    float flModulationDepth;\n    float flAirAbsorptionGainHF;\n    float flHFReference;\n    float flLFReference;\n    float flRoomRolloffFactor;\n    int   iDecayHFLimit;\n} EFXEAXREVERBPROPERTIES, *LPEFXEAXREVERBPROPERTIES;\n#endif\n\n/* Default Presets */\n\n#define EFX_REVERB_PRESET_GENERIC \\\n    { 1.0000f, 1.0000f, 0.3162f, 0.8913f, 1.0000f, 1.4900f, 0.8300f, 1.0000f, 0.0500f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 1.2589f, 0.0110f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }\n\n#define EFX_REVERB_PRESET_PADDEDCELL \\\n    { 0.1715f, 1.0000f, 0.3162f, 0.0010f, 1.0000f, 0.1700f, 0.1000f, 1.0000f, 0.2500f, 0.0010f, { 0.0000f, 0.0000f, 0.0000f }, 1.2691f, 0.0020f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }\n\n#define EFX_REVERB_PRESET_ROOM \\\n    { 0.4287f, 1.0000f, 0.3162f, 0.5929f, 1.0000f, 0.4000f, 0.8300f, 1.0000f, 0.1503f, 0.0020f, { 0.0000f, 0.0000f, 0.0000f }, 1.0629f, 0.0030f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }\n\n#define EFX_REVERB_PRESET_BATHROOM \\\n    { 0.1715f, 1.0000f, 0.3162f, 0.2512f, 1.0000f, 1.4900f, 0.5400f, 1.0000f, 0.6531f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 3.2734f, 0.0110f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }\n\n#define EFX_REVERB_PRESET_LIVINGROOM \\\n    { 0.9766f, 1.0000f, 0.3162f, 0.0010f, 1.0000f, 0.5000f, 0.1000f, 1.0000f, 0.2051f, 0.0030f, { 0.0000f, 0.0000f, 0.0000f }, 0.2805f, 0.0040f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }\n\n#define EFX_REVERB_PRESET_STONEROOM \\\n    { 1.0000f, 1.0000f, 0.3162f, 0.7079f, 1.0000f, 2.3100f, 0.6400f, 1.0000f, 0.4411f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 1.1003f, 0.0170f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }\n\n#define EFX_REVERB_PRESET_AUDITORIUM \\\n    { 1.0000f, 1.0000f, 0.3162f, 0.5781f, 1.0000f, 4.3200f, 0.5900f, 1.0000f, 0.4032f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 0.7170f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }\n\n#define EFX_REVERB_PRESET_CONCERTHALL \\\n    { 1.0000f, 1.0000f, 0.3162f, 0.5623f, 1.0000f, 3.9200f, 0.7000f, 1.0000f, 0.2427f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 0.9977f, 0.0290f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }\n\n#define EFX_REVERB_PRESET_CAVE \\\n    { 1.0000f, 1.0000f, 0.3162f, 1.0000f, 1.0000f, 2.9100f, 1.3000f, 1.0000f, 0.5000f, 0.0150f, { 0.0000f, 0.0000f, 0.0000f }, 0.7063f, 0.0220f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 }\n\n#define EFX_REVERB_PRESET_ARENA \\\n    { 1.0000f, 1.0000f, 0.3162f, 0.4477f, 1.0000f, 7.2400f, 0.3300f, 1.0000f, 0.2612f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 1.0186f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }\n\n#define EFX_REVERB_PRESET_HANGAR \\\n    { 1.0000f, 1.0000f, 0.3162f, 0.3162f, 1.0000f, 10.0500f, 0.2300f, 1.0000f, 0.5000f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 1.2560f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }\n\n#define EFX_REVERB_PRESET_CARPETEDHALLWAY \\\n    { 0.4287f, 1.0000f, 0.3162f, 0.0100f, 1.0000f, 0.3000f, 0.1000f, 1.0000f, 0.1215f, 0.0020f, { 0.0000f, 0.0000f, 0.0000f }, 0.1531f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }\n\n#define EFX_REVERB_PRESET_HALLWAY \\\n    { 0.3645f, 1.0000f, 0.3162f, 0.7079f, 1.0000f, 1.4900f, 0.5900f, 1.0000f, 0.2458f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 1.6615f, 0.0110f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }\n\n#define EFX_REVERB_PRESET_STONECORRIDOR \\\n    { 1.0000f, 1.0000f, 0.3162f, 0.7612f, 1.0000f, 2.7000f, 0.7900f, 1.0000f, 0.2472f, 0.0130f, { 0.0000f, 0.0000f, 0.0000f }, 1.5758f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }\n\n#define EFX_REVERB_PRESET_ALLEY \\\n    { 1.0000f, 0.3000f, 0.3162f, 0.7328f, 1.0000f, 1.4900f, 0.8600f, 1.0000f, 0.2500f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 0.9954f, 0.0110f, { 0.0000f, 0.0000f, 0.0000f }, 0.1250f, 0.9500f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }\n\n#define EFX_REVERB_PRESET_FOREST \\\n    { 1.0000f, 0.3000f, 0.3162f, 0.0224f, 1.0000f, 1.4900f, 0.5400f, 1.0000f, 0.0525f, 0.1620f, { 0.0000f, 0.0000f, 0.0000f }, 0.7682f, 0.0880f, { 0.0000f, 0.0000f, 0.0000f }, 0.1250f, 1.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }\n\n#define EFX_REVERB_PRESET_CITY \\\n    { 1.0000f, 0.5000f, 0.3162f, 0.3981f, 1.0000f, 1.4900f, 0.6700f, 1.0000f, 0.0730f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 0.1427f, 0.0110f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }\n\n#define EFX_REVERB_PRESET_MOUNTAINS \\\n    { 1.0000f, 0.2700f, 0.3162f, 0.0562f, 1.0000f, 1.4900f, 0.2100f, 1.0000f, 0.0407f, 0.3000f, { 0.0000f, 0.0000f, 0.0000f }, 0.1919f, 0.1000f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 1.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 }\n\n#define EFX_REVERB_PRESET_QUARRY \\\n    { 1.0000f, 1.0000f, 0.3162f, 0.3162f, 1.0000f, 1.4900f, 0.8300f, 1.0000f, 0.0000f, 0.0610f, { 0.0000f, 0.0000f, 0.0000f }, 1.7783f, 0.0250f, { 0.0000f, 0.0000f, 0.0000f }, 0.1250f, 0.7000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }\n\n#define EFX_REVERB_PRESET_PLAIN \\\n    { 1.0000f, 0.2100f, 0.3162f, 0.1000f, 1.0000f, 1.4900f, 0.5000f, 1.0000f, 0.0585f, 0.1790f, { 0.0000f, 0.0000f, 0.0000f }, 0.1089f, 0.1000f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 1.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }\n\n#define EFX_REVERB_PRESET_PARKINGLOT \\\n    { 1.0000f, 1.0000f, 0.3162f, 1.0000f, 1.0000f, 1.6500f, 1.5000f, 1.0000f, 0.2082f, 0.0080f, { 0.0000f, 0.0000f, 0.0000f }, 0.2652f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 }\n\n#define EFX_REVERB_PRESET_SEWERPIPE \\\n    { 0.3071f, 0.8000f, 0.3162f, 0.3162f, 1.0000f, 2.8100f, 0.1400f, 1.0000f, 1.6387f, 0.0140f, { 0.0000f, 0.0000f, 0.0000f }, 3.2471f, 0.0210f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }\n\n#define EFX_REVERB_PRESET_UNDERWATER \\\n    { 0.3645f, 1.0000f, 0.3162f, 0.0100f, 1.0000f, 1.4900f, 0.1000f, 1.0000f, 0.5963f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 7.0795f, 0.0110f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 1.1800f, 0.3480f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }\n\n#define EFX_REVERB_PRESET_DRUGGED \\\n    { 0.4287f, 0.5000f, 0.3162f, 1.0000f, 1.0000f, 8.3900f, 1.3900f, 1.0000f, 0.8760f, 0.0020f, { 0.0000f, 0.0000f, 0.0000f }, 3.1081f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 1.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 }\n\n#define EFX_REVERB_PRESET_DIZZY \\\n    { 0.3645f, 0.6000f, 0.3162f, 0.6310f, 1.0000f, 17.2300f, 0.5600f, 1.0000f, 0.1392f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 0.4937f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 1.0000f, 0.8100f, 0.3100f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 }\n\n#define EFX_REVERB_PRESET_PSYCHOTIC \\\n    { 0.0625f, 0.5000f, 0.3162f, 0.8404f, 1.0000f, 7.5600f, 0.9100f, 1.0000f, 0.4864f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 2.4378f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 4.0000f, 1.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 }\n\n/* Castle Presets */\n\n#define EFX_REVERB_PRESET_CASTLE_SMALLROOM \\\n    { 1.0000f, 0.8900f, 0.3162f, 0.3981f, 0.1000f, 1.2200f, 0.8300f, 0.3100f, 0.8913f, 0.0220f, { 0.0000f, 0.0000f, 0.0000f }, 1.9953f, 0.0110f, { 0.0000f, 0.0000f, 0.0000f }, 0.1380f, 0.0800f, 0.2500f, 0.0000f, 0.9943f, 5168.6001f, 139.5000f, 0.0000f, 0x1 }\n\n#define EFX_REVERB_PRESET_CASTLE_SHORTPASSAGE \\\n    { 1.0000f, 0.8900f, 0.3162f, 0.3162f, 0.1000f, 2.3200f, 0.8300f, 0.3100f, 0.8913f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 1.2589f, 0.0230f, { 0.0000f, 0.0000f, 0.0000f }, 0.1380f, 0.0800f, 0.2500f, 0.0000f, 0.9943f, 5168.6001f, 139.5000f, 0.0000f, 0x1 }\n\n#define EFX_REVERB_PRESET_CASTLE_MEDIUMROOM \\\n    { 1.0000f, 0.9300f, 0.3162f, 0.2818f, 0.1000f, 2.0400f, 0.8300f, 0.4600f, 0.6310f, 0.0220f, { 0.0000f, 0.0000f, 0.0000f }, 1.5849f, 0.0110f, { 0.0000f, 0.0000f, 0.0000f }, 0.1550f, 0.0300f, 0.2500f, 0.0000f, 0.9943f, 5168.6001f, 139.5000f, 0.0000f, 0x1 }\n\n#define EFX_REVERB_PRESET_CASTLE_LARGEROOM \\\n    { 1.0000f, 0.8200f, 0.3162f, 0.2818f, 0.1259f, 2.5300f, 0.8300f, 0.5000f, 0.4467f, 0.0340f, { 0.0000f, 0.0000f, 0.0000f }, 1.2589f, 0.0160f, { 0.0000f, 0.0000f, 0.0000f }, 0.1850f, 0.0700f, 0.2500f, 0.0000f, 0.9943f, 5168.6001f, 139.5000f, 0.0000f, 0x1 }\n\n#define EFX_REVERB_PRESET_CASTLE_LONGPASSAGE \\\n    { 1.0000f, 0.8900f, 0.3162f, 0.3981f, 0.1000f, 3.4200f, 0.8300f, 0.3100f, 0.8913f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 1.4125f, 0.0230f, { 0.0000f, 0.0000f, 0.0000f }, 0.1380f, 0.0800f, 0.2500f, 0.0000f, 0.9943f, 5168.6001f, 139.5000f, 0.0000f, 0x1 }\n\n#define EFX_REVERB_PRESET_CASTLE_HALL \\\n    { 1.0000f, 0.8100f, 0.3162f, 0.2818f, 0.1778f, 3.1400f, 0.7900f, 0.6200f, 0.1778f, 0.0560f, { 0.0000f, 0.0000f, 0.0000f }, 1.1220f, 0.0240f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5168.6001f, 139.5000f, 0.0000f, 0x1 }\n\n#define EFX_REVERB_PRESET_CASTLE_CUPBOARD \\\n    { 1.0000f, 0.8900f, 0.3162f, 0.2818f, 0.1000f, 0.6700f, 0.8700f, 0.3100f, 1.4125f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 3.5481f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 0.1380f, 0.0800f, 0.2500f, 0.0000f, 0.9943f, 5168.6001f, 139.5000f, 0.0000f, 0x1 }\n\n#define EFX_REVERB_PRESET_CASTLE_COURTYARD \\\n    { 1.0000f, 0.4200f, 0.3162f, 0.4467f, 0.1995f, 2.1300f, 0.6100f, 0.2300f, 0.2239f, 0.1600f, { 0.0000f, 0.0000f, 0.0000f }, 0.7079f, 0.0360f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.3700f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 }\n\n#define EFX_REVERB_PRESET_CASTLE_ALCOVE \\\n    { 1.0000f, 0.8900f, 0.3162f, 0.5012f, 0.1000f, 1.6400f, 0.8700f, 0.3100f, 1.0000f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 1.4125f, 0.0340f, { 0.0000f, 0.0000f, 0.0000f }, 0.1380f, 0.0800f, 0.2500f, 0.0000f, 0.9943f, 5168.6001f, 139.5000f, 0.0000f, 0x1 }\n\n/* Factory Presets */\n\n#define EFX_REVERB_PRESET_FACTORY_SMALLROOM \\\n    { 0.3645f, 0.8200f, 0.3162f, 0.7943f, 0.5012f, 1.7200f, 0.6500f, 1.3100f, 0.7079f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 1.7783f, 0.0240f, { 0.0000f, 0.0000f, 0.0000f }, 0.1190f, 0.0700f, 0.2500f, 0.0000f, 0.9943f, 3762.6001f, 362.5000f, 0.0000f, 0x1 }\n\n#define EFX_REVERB_PRESET_FACTORY_SHORTPASSAGE \\\n    { 0.3645f, 0.6400f, 0.2512f, 0.7943f, 0.5012f, 2.5300f, 0.6500f, 1.3100f, 1.0000f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 1.2589f, 0.0380f, { 0.0000f, 0.0000f, 0.0000f }, 0.1350f, 0.2300f, 0.2500f, 0.0000f, 0.9943f, 3762.6001f, 362.5000f, 0.0000f, 0x1 }\n\n#define EFX_REVERB_PRESET_FACTORY_MEDIUMROOM \\\n    { 0.4287f, 0.8200f, 0.2512f, 0.7943f, 0.5012f, 2.7600f, 0.6500f, 1.3100f, 0.2818f, 0.0220f, { 0.0000f, 0.0000f, 0.0000f }, 1.4125f, 0.0230f, { 0.0000f, 0.0000f, 0.0000f }, 0.1740f, 0.0700f, 0.2500f, 0.0000f, 0.9943f, 3762.6001f, 362.5000f, 0.0000f, 0x1 }\n\n#define EFX_REVERB_PRESET_FACTORY_LARGEROOM \\\n    { 0.4287f, 0.7500f, 0.2512f, 0.7079f, 0.6310f, 4.2400f, 0.5100f, 1.3100f, 0.1778f, 0.0390f, { 0.0000f, 0.0000f, 0.0000f }, 1.1220f, 0.0230f, { 0.0000f, 0.0000f, 0.0000f }, 0.2310f, 0.0700f, 0.2500f, 0.0000f, 0.9943f, 3762.6001f, 362.5000f, 0.0000f, 0x1 }\n\n#define EFX_REVERB_PRESET_FACTORY_LONGPASSAGE \\\n    { 0.3645f, 0.6400f, 0.2512f, 0.7943f, 0.5012f, 4.0600f, 0.6500f, 1.3100f, 1.0000f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 1.2589f, 0.0370f, { 0.0000f, 0.0000f, 0.0000f }, 0.1350f, 0.2300f, 0.2500f, 0.0000f, 0.9943f, 3762.6001f, 362.5000f, 0.0000f, 0x1 }\n\n#define EFX_REVERB_PRESET_FACTORY_HALL \\\n    { 0.4287f, 0.7500f, 0.3162f, 0.7079f, 0.6310f, 7.4300f, 0.5100f, 1.3100f, 0.0631f, 0.0730f, { 0.0000f, 0.0000f, 0.0000f }, 0.8913f, 0.0270f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0700f, 0.2500f, 0.0000f, 0.9943f, 3762.6001f, 362.5000f, 0.0000f, 0x1 }\n\n#define EFX_REVERB_PRESET_FACTORY_CUPBOARD \\\n    { 0.3071f, 0.6300f, 0.2512f, 0.7943f, 0.5012f, 0.4900f, 0.6500f, 1.3100f, 1.2589f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 1.9953f, 0.0320f, { 0.0000f, 0.0000f, 0.0000f }, 0.1070f, 0.0700f, 0.2500f, 0.0000f, 0.9943f, 3762.6001f, 362.5000f, 0.0000f, 0x1 }\n\n#define EFX_REVERB_PRESET_FACTORY_COURTYARD \\\n    { 0.3071f, 0.5700f, 0.3162f, 0.3162f, 0.6310f, 2.3200f, 0.2900f, 0.5600f, 0.2239f, 0.1400f, { 0.0000f, 0.0000f, 0.0000f }, 0.3981f, 0.0390f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.2900f, 0.2500f, 0.0000f, 0.9943f, 3762.6001f, 362.5000f, 0.0000f, 0x1 }\n\n#define EFX_REVERB_PRESET_FACTORY_ALCOVE \\\n    { 0.3645f, 0.5900f, 0.2512f, 0.7943f, 0.5012f, 3.1400f, 0.6500f, 1.3100f, 1.4125f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 1.0000f, 0.0380f, { 0.0000f, 0.0000f, 0.0000f }, 0.1140f, 0.1000f, 0.2500f, 0.0000f, 0.9943f, 3762.6001f, 362.5000f, 0.0000f, 0x1 }\n\n/* Ice Palace Presets */\n\n#define EFX_REVERB_PRESET_ICEPALACE_SMALLROOM \\\n    { 1.0000f, 0.8400f, 0.3162f, 0.5623f, 0.2818f, 1.5100f, 1.5300f, 0.2700f, 0.8913f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 1.4125f, 0.0110f, { 0.0000f, 0.0000f, 0.0000f }, 0.1640f, 0.1400f, 0.2500f, 0.0000f, 0.9943f, 12428.5000f, 99.6000f, 0.0000f, 0x1 }\n\n#define EFX_REVERB_PRESET_ICEPALACE_SHORTPASSAGE \\\n    { 1.0000f, 0.7500f, 0.3162f, 0.5623f, 0.2818f, 1.7900f, 1.4600f, 0.2800f, 0.5012f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 1.1220f, 0.0190f, { 0.0000f, 0.0000f, 0.0000f }, 0.1770f, 0.0900f, 0.2500f, 0.0000f, 0.9943f, 12428.5000f, 99.6000f, 0.0000f, 0x1 }\n\n#define EFX_REVERB_PRESET_ICEPALACE_MEDIUMROOM \\\n    { 1.0000f, 0.8700f, 0.3162f, 0.5623f, 0.4467f, 2.2200f, 1.5300f, 0.3200f, 0.3981f, 0.0390f, { 0.0000f, 0.0000f, 0.0000f }, 1.1220f, 0.0270f, { 0.0000f, 0.0000f, 0.0000f }, 0.1860f, 0.1200f, 0.2500f, 0.0000f, 0.9943f, 12428.5000f, 99.6000f, 0.0000f, 0x1 }\n\n#define EFX_REVERB_PRESET_ICEPALACE_LARGEROOM \\\n    { 1.0000f, 0.8100f, 0.3162f, 0.5623f, 0.4467f, 3.1400f, 1.5300f, 0.3200f, 0.2512f, 0.0390f, { 0.0000f, 0.0000f, 0.0000f }, 1.0000f, 0.0270f, { 0.0000f, 0.0000f, 0.0000f }, 0.2140f, 0.1100f, 0.2500f, 0.0000f, 0.9943f, 12428.5000f, 99.6000f, 0.0000f, 0x1 }\n\n#define EFX_REVERB_PRESET_ICEPALACE_LONGPASSAGE \\\n    { 1.0000f, 0.7700f, 0.3162f, 0.5623f, 0.3981f, 3.0100f, 1.4600f, 0.2800f, 0.7943f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 1.2589f, 0.0250f, { 0.0000f, 0.0000f, 0.0000f }, 0.1860f, 0.0400f, 0.2500f, 0.0000f, 0.9943f, 12428.5000f, 99.6000f, 0.0000f, 0x1 }\n\n#define EFX_REVERB_PRESET_ICEPALACE_HALL \\\n    { 1.0000f, 0.7600f, 0.3162f, 0.4467f, 0.5623f, 5.4900f, 1.5300f, 0.3800f, 0.1122f, 0.0540f, { 0.0000f, 0.0000f, 0.0000f }, 0.6310f, 0.0520f, { 0.0000f, 0.0000f, 0.0000f }, 0.2260f, 0.1100f, 0.2500f, 0.0000f, 0.9943f, 12428.5000f, 99.6000f, 0.0000f, 0x1 }\n\n#define EFX_REVERB_PRESET_ICEPALACE_CUPBOARD \\\n    { 1.0000f, 0.8300f, 0.3162f, 0.5012f, 0.2239f, 0.7600f, 1.5300f, 0.2600f, 1.1220f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 1.9953f, 0.0160f, { 0.0000f, 0.0000f, 0.0000f }, 0.1430f, 0.0800f, 0.2500f, 0.0000f, 0.9943f, 12428.5000f, 99.6000f, 0.0000f, 0x1 }\n\n#define EFX_REVERB_PRESET_ICEPALACE_COURTYARD \\\n    { 1.0000f, 0.5900f, 0.3162f, 0.2818f, 0.3162f, 2.0400f, 1.2000f, 0.3800f, 0.3162f, 0.1730f, { 0.0000f, 0.0000f, 0.0000f }, 0.3162f, 0.0430f, { 0.0000f, 0.0000f, 0.0000f }, 0.2350f, 0.4800f, 0.2500f, 0.0000f, 0.9943f, 12428.5000f, 99.6000f, 0.0000f, 0x1 }\n\n#define EFX_REVERB_PRESET_ICEPALACE_ALCOVE \\\n    { 1.0000f, 0.8400f, 0.3162f, 0.5623f, 0.2818f, 2.7600f, 1.4600f, 0.2800f, 1.1220f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 0.8913f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.1610f, 0.0900f, 0.2500f, 0.0000f, 0.9943f, 12428.5000f, 99.6000f, 0.0000f, 0x1 }\n\n/* Space Station Presets */\n\n#define EFX_REVERB_PRESET_SPACESTATION_SMALLROOM \\\n    { 0.2109f, 0.7000f, 0.3162f, 0.7079f, 0.8913f, 1.7200f, 0.8200f, 0.5500f, 0.7943f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 1.4125f, 0.0130f, { 0.0000f, 0.0000f, 0.0000f }, 0.1880f, 0.2600f, 0.2500f, 0.0000f, 0.9943f, 3316.1001f, 458.2000f, 0.0000f, 0x1 }\n\n#define EFX_REVERB_PRESET_SPACESTATION_SHORTPASSAGE \\\n    { 0.2109f, 0.8700f, 0.3162f, 0.6310f, 0.8913f, 3.5700f, 0.5000f, 0.5500f, 1.0000f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 1.1220f, 0.0160f, { 0.0000f, 0.0000f, 0.0000f }, 0.1720f, 0.2000f, 0.2500f, 0.0000f, 0.9943f, 3316.1001f, 458.2000f, 0.0000f, 0x1 }\n\n#define EFX_REVERB_PRESET_SPACESTATION_MEDIUMROOM \\\n    { 0.2109f, 0.7500f, 0.3162f, 0.6310f, 0.8913f, 3.0100f, 0.5000f, 0.5500f, 0.3981f, 0.0340f, { 0.0000f, 0.0000f, 0.0000f }, 1.1220f, 0.0350f, { 0.0000f, 0.0000f, 0.0000f }, 0.2090f, 0.3100f, 0.2500f, 0.0000f, 0.9943f, 3316.1001f, 458.2000f, 0.0000f, 0x1 }\n\n#define EFX_REVERB_PRESET_SPACESTATION_LARGEROOM \\\n    { 0.3645f, 0.8100f, 0.3162f, 0.6310f, 0.8913f, 3.8900f, 0.3800f, 0.6100f, 0.3162f, 0.0560f, { 0.0000f, 0.0000f, 0.0000f }, 0.8913f, 0.0350f, { 0.0000f, 0.0000f, 0.0000f }, 0.2330f, 0.2800f, 0.2500f, 0.0000f, 0.9943f, 3316.1001f, 458.2000f, 0.0000f, 0x1 }\n\n#define EFX_REVERB_PRESET_SPACESTATION_LONGPASSAGE \\\n    { 0.4287f, 0.8200f, 0.3162f, 0.6310f, 0.8913f, 4.6200f, 0.6200f, 0.5500f, 1.0000f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 1.2589f, 0.0310f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.2300f, 0.2500f, 0.0000f, 0.9943f, 3316.1001f, 458.2000f, 0.0000f, 0x1 }\n\n#define EFX_REVERB_PRESET_SPACESTATION_HALL \\\n    { 0.4287f, 0.8700f, 0.3162f, 0.6310f, 0.8913f, 7.1100f, 0.3800f, 0.6100f, 0.1778f, 0.1000f, { 0.0000f, 0.0000f, 0.0000f }, 0.6310f, 0.0470f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.2500f, 0.2500f, 0.0000f, 0.9943f, 3316.1001f, 458.2000f, 0.0000f, 0x1 }\n\n#define EFX_REVERB_PRESET_SPACESTATION_CUPBOARD \\\n    { 0.1715f, 0.5600f, 0.3162f, 0.7079f, 0.8913f, 0.7900f, 0.8100f, 0.5500f, 1.4125f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 1.7783f, 0.0180f, { 0.0000f, 0.0000f, 0.0000f }, 0.1810f, 0.3100f, 0.2500f, 0.0000f, 0.9943f, 3316.1001f, 458.2000f, 0.0000f, 0x1 }\n\n#define EFX_REVERB_PRESET_SPACESTATION_ALCOVE \\\n    { 0.2109f, 0.7800f, 0.3162f, 0.7079f, 0.8913f, 1.1600f, 0.8100f, 0.5500f, 1.4125f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 1.0000f, 0.0180f, { 0.0000f, 0.0000f, 0.0000f }, 0.1920f, 0.2100f, 0.2500f, 0.0000f, 0.9943f, 3316.1001f, 458.2000f, 0.0000f, 0x1 }\n\n/* Wooden Galleon Presets */\n\n#define EFX_REVERB_PRESET_WOODEN_SMALLROOM \\\n    { 1.0000f, 1.0000f, 0.3162f, 0.1122f, 0.3162f, 0.7900f, 0.3200f, 0.8700f, 1.0000f, 0.0320f, { 0.0000f, 0.0000f, 0.0000f }, 0.8913f, 0.0290f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 4705.0000f, 99.6000f, 0.0000f, 0x1 }\n\n#define EFX_REVERB_PRESET_WOODEN_SHORTPASSAGE \\\n    { 1.0000f, 1.0000f, 0.3162f, 0.1259f, 0.3162f, 1.7500f, 0.5000f, 0.8700f, 0.8913f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 0.6310f, 0.0240f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 4705.0000f, 99.6000f, 0.0000f, 0x1 }\n\n#define EFX_REVERB_PRESET_WOODEN_MEDIUMROOM \\\n    { 1.0000f, 1.0000f, 0.3162f, 0.1000f, 0.2818f, 1.4700f, 0.4200f, 0.8200f, 0.8913f, 0.0490f, { 0.0000f, 0.0000f, 0.0000f }, 0.8913f, 0.0290f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 4705.0000f, 99.6000f, 0.0000f, 0x1 }\n\n#define EFX_REVERB_PRESET_WOODEN_LARGEROOM \\\n    { 1.0000f, 1.0000f, 0.3162f, 0.0891f, 0.2818f, 2.6500f, 0.3300f, 0.8200f, 0.8913f, 0.0660f, { 0.0000f, 0.0000f, 0.0000f }, 0.7943f, 0.0490f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 4705.0000f, 99.6000f, 0.0000f, 0x1 }\n\n#define EFX_REVERB_PRESET_WOODEN_LONGPASSAGE \\\n    { 1.0000f, 1.0000f, 0.3162f, 0.1000f, 0.3162f, 1.9900f, 0.4000f, 0.7900f, 1.0000f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 0.4467f, 0.0360f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 4705.0000f, 99.6000f, 0.0000f, 0x1 }\n\n#define EFX_REVERB_PRESET_WOODEN_HALL \\\n    { 1.0000f, 1.0000f, 0.3162f, 0.0794f, 0.2818f, 3.4500f, 0.3000f, 0.8200f, 0.8913f, 0.0880f, { 0.0000f, 0.0000f, 0.0000f }, 0.7943f, 0.0630f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 4705.0000f, 99.6000f, 0.0000f, 0x1 }\n\n#define EFX_REVERB_PRESET_WOODEN_CUPBOARD \\\n    { 1.0000f, 1.0000f, 0.3162f, 0.1413f, 0.3162f, 0.5600f, 0.4600f, 0.9100f, 1.1220f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 1.1220f, 0.0280f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 4705.0000f, 99.6000f, 0.0000f, 0x1 }\n\n#define EFX_REVERB_PRESET_WOODEN_COURTYARD \\\n    { 1.0000f, 0.6500f, 0.3162f, 0.0794f, 0.3162f, 1.7900f, 0.3500f, 0.7900f, 0.5623f, 0.1230f, { 0.0000f, 0.0000f, 0.0000f }, 0.1000f, 0.0320f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 4705.0000f, 99.6000f, 0.0000f, 0x1 }\n\n#define EFX_REVERB_PRESET_WOODEN_ALCOVE \\\n    { 1.0000f, 1.0000f, 0.3162f, 0.1259f, 0.3162f, 1.2200f, 0.6200f, 0.9100f, 1.1220f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 0.7079f, 0.0240f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 4705.0000f, 99.6000f, 0.0000f, 0x1 }\n\n/* Sports Presets */\n\n#define EFX_REVERB_PRESET_SPORT_EMPTYSTADIUM \\\n    { 1.0000f, 1.0000f, 0.3162f, 0.4467f, 0.7943f, 6.2600f, 0.5100f, 1.1000f, 0.0631f, 0.1830f, { 0.0000f, 0.0000f, 0.0000f }, 0.3981f, 0.0380f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }\n\n#define EFX_REVERB_PRESET_SPORT_SQUASHCOURT \\\n    { 1.0000f, 0.7500f, 0.3162f, 0.3162f, 0.7943f, 2.2200f, 0.9100f, 1.1600f, 0.4467f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 0.7943f, 0.0110f, { 0.0000f, 0.0000f, 0.0000f }, 0.1260f, 0.1900f, 0.2500f, 0.0000f, 0.9943f, 7176.8999f, 211.2000f, 0.0000f, 0x1 }\n\n#define EFX_REVERB_PRESET_SPORT_SMALLSWIMMINGPOOL \\\n    { 1.0000f, 0.7000f, 0.3162f, 0.7943f, 0.8913f, 2.7600f, 1.2500f, 1.1400f, 0.6310f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 0.7943f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.1790f, 0.1500f, 0.8950f, 0.1900f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 }\n\n#define EFX_REVERB_PRESET_SPORT_LARGESWIMMINGPOOL \\\n    { 1.0000f, 0.8200f, 0.3162f, 0.7943f, 1.0000f, 5.4900f, 1.3100f, 1.1400f, 0.4467f, 0.0390f, { 0.0000f, 0.0000f, 0.0000f }, 0.5012f, 0.0490f, { 0.0000f, 0.0000f, 0.0000f }, 0.2220f, 0.5500f, 1.1590f, 0.2100f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 }\n\n#define EFX_REVERB_PRESET_SPORT_GYMNASIUM \\\n    { 1.0000f, 0.8100f, 0.3162f, 0.4467f, 0.8913f, 3.1400f, 1.0600f, 1.3500f, 0.3981f, 0.0290f, { 0.0000f, 0.0000f, 0.0000f }, 0.5623f, 0.0450f, { 0.0000f, 0.0000f, 0.0000f }, 0.1460f, 0.1400f, 0.2500f, 0.0000f, 0.9943f, 7176.8999f, 211.2000f, 0.0000f, 0x1 }\n\n#define EFX_REVERB_PRESET_SPORT_FULLSTADIUM \\\n    { 1.0000f, 1.0000f, 0.3162f, 0.0708f, 0.7943f, 5.2500f, 0.1700f, 0.8000f, 0.1000f, 0.1880f, { 0.0000f, 0.0000f, 0.0000f }, 0.2818f, 0.0380f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }\n\n#define EFX_REVERB_PRESET_SPORT_STADIUMTANNOY \\\n    { 1.0000f, 0.7800f, 0.3162f, 0.5623f, 0.5012f, 2.5300f, 0.8800f, 0.6800f, 0.2818f, 0.2300f, { 0.0000f, 0.0000f, 0.0000f }, 0.5012f, 0.0630f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.2000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }\n\n/* Prefab Presets */\n\n#define EFX_REVERB_PRESET_PREFAB_WORKSHOP \\\n    { 0.4287f, 1.0000f, 0.3162f, 0.1413f, 0.3981f, 0.7600f, 1.0000f, 1.0000f, 1.0000f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 1.1220f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 }\n\n#define EFX_REVERB_PRESET_PREFAB_SCHOOLROOM \\\n    { 0.4022f, 0.6900f, 0.3162f, 0.6310f, 0.5012f, 0.9800f, 0.4500f, 0.1800f, 1.4125f, 0.0170f, { 0.0000f, 0.0000f, 0.0000f }, 1.4125f, 0.0150f, { 0.0000f, 0.0000f, 0.0000f }, 0.0950f, 0.1400f, 0.2500f, 0.0000f, 0.9943f, 7176.8999f, 211.2000f, 0.0000f, 0x1 }\n\n#define EFX_REVERB_PRESET_PREFAB_PRACTISEROOM \\\n    { 0.4022f, 0.8700f, 0.3162f, 0.3981f, 0.5012f, 1.1200f, 0.5600f, 0.1800f, 1.2589f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 1.4125f, 0.0110f, { 0.0000f, 0.0000f, 0.0000f }, 0.0950f, 0.1400f, 0.2500f, 0.0000f, 0.9943f, 7176.8999f, 211.2000f, 0.0000f, 0x1 }\n\n#define EFX_REVERB_PRESET_PREFAB_OUTHOUSE \\\n    { 1.0000f, 0.8200f, 0.3162f, 0.1122f, 0.1585f, 1.3800f, 0.3800f, 0.3500f, 0.8913f, 0.0240f, { 0.0000f, 0.0000f, -0.0000f }, 0.6310f, 0.0440f, { 0.0000f, 0.0000f, 0.0000f }, 0.1210f, 0.1700f, 0.2500f, 0.0000f, 0.9943f, 2854.3999f, 107.5000f, 0.0000f, 0x0 }\n\n#define EFX_REVERB_PRESET_PREFAB_CARAVAN \\\n    { 1.0000f, 1.0000f, 0.3162f, 0.0891f, 0.1259f, 0.4300f, 1.5000f, 1.0000f, 1.0000f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 1.9953f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 }\n\n/* Dome and Pipe Presets */\n\n#define EFX_REVERB_PRESET_DOME_TOMB \\\n    { 1.0000f, 0.7900f, 0.3162f, 0.3548f, 0.2239f, 4.1800f, 0.2100f, 0.1000f, 0.3868f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 1.6788f, 0.0220f, { 0.0000f, 0.0000f, 0.0000f }, 0.1770f, 0.1900f, 0.2500f, 0.0000f, 0.9943f, 2854.3999f, 20.0000f, 0.0000f, 0x0 }\n\n#define EFX_REVERB_PRESET_PIPE_SMALL \\\n    { 1.0000f, 1.0000f, 0.3162f, 0.3548f, 0.2239f, 5.0400f, 0.1000f, 0.1000f, 0.5012f, 0.0320f, { 0.0000f, 0.0000f, 0.0000f }, 2.5119f, 0.0150f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 2854.3999f, 20.0000f, 0.0000f, 0x1 }\n\n#define EFX_REVERB_PRESET_DOME_SAINTPAULS \\\n    { 1.0000f, 0.8700f, 0.3162f, 0.3548f, 0.2239f, 10.4800f, 0.1900f, 0.1000f, 0.1778f, 0.0900f, { 0.0000f, 0.0000f, 0.0000f }, 1.2589f, 0.0420f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.1200f, 0.2500f, 0.0000f, 0.9943f, 2854.3999f, 20.0000f, 0.0000f, 0x1 }\n\n#define EFX_REVERB_PRESET_PIPE_LONGTHIN \\\n    { 0.2560f, 0.9100f, 0.3162f, 0.4467f, 0.2818f, 9.2100f, 0.1800f, 0.1000f, 0.7079f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 0.7079f, 0.0220f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 2854.3999f, 20.0000f, 0.0000f, 0x0 }\n\n#define EFX_REVERB_PRESET_PIPE_LARGE \\\n    { 1.0000f, 1.0000f, 0.3162f, 0.3548f, 0.2239f, 8.4500f, 0.1000f, 0.1000f, 0.3981f, 0.0460f, { 0.0000f, 0.0000f, 0.0000f }, 1.5849f, 0.0320f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 2854.3999f, 20.0000f, 0.0000f, 0x1 }\n\n#define EFX_REVERB_PRESET_PIPE_RESONANT \\\n    { 0.1373f, 0.9100f, 0.3162f, 0.4467f, 0.2818f, 6.8100f, 0.1800f, 0.1000f, 0.7079f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 1.0000f, 0.0220f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 2854.3999f, 20.0000f, 0.0000f, 0x0 }\n\n/* Outdoors Presets */\n\n#define EFX_REVERB_PRESET_OUTDOORS_BACKYARD \\\n    { 1.0000f, 0.4500f, 0.3162f, 0.2512f, 0.5012f, 1.1200f, 0.3400f, 0.4600f, 0.4467f, 0.0690f, { 0.0000f, 0.0000f, -0.0000f }, 0.7079f, 0.0230f, { 0.0000f, 0.0000f, 0.0000f }, 0.2180f, 0.3400f, 0.2500f, 0.0000f, 0.9943f, 4399.1001f, 242.9000f, 0.0000f, 0x0 }\n\n#define EFX_REVERB_PRESET_OUTDOORS_ROLLINGPLAINS \\\n    { 1.0000f, 0.0000f, 0.3162f, 0.0112f, 0.6310f, 2.1300f, 0.2100f, 0.4600f, 0.1778f, 0.3000f, { 0.0000f, 0.0000f, -0.0000f }, 0.4467f, 0.0190f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 1.0000f, 0.2500f, 0.0000f, 0.9943f, 4399.1001f, 242.9000f, 0.0000f, 0x0 }\n\n#define EFX_REVERB_PRESET_OUTDOORS_DEEPCANYON \\\n    { 1.0000f, 0.7400f, 0.3162f, 0.1778f, 0.6310f, 3.8900f, 0.2100f, 0.4600f, 0.3162f, 0.2230f, { 0.0000f, 0.0000f, -0.0000f }, 0.3548f, 0.0190f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 1.0000f, 0.2500f, 0.0000f, 0.9943f, 4399.1001f, 242.9000f, 0.0000f, 0x0 }\n\n#define EFX_REVERB_PRESET_OUTDOORS_CREEK \\\n    { 1.0000f, 0.3500f, 0.3162f, 0.1778f, 0.5012f, 2.1300f, 0.2100f, 0.4600f, 0.3981f, 0.1150f, { 0.0000f, 0.0000f, -0.0000f }, 0.1995f, 0.0310f, { 0.0000f, 0.0000f, 0.0000f }, 0.2180f, 0.3400f, 0.2500f, 0.0000f, 0.9943f, 4399.1001f, 242.9000f, 0.0000f, 0x0 }\n\n#define EFX_REVERB_PRESET_OUTDOORS_VALLEY \\\n    { 1.0000f, 0.2800f, 0.3162f, 0.0282f, 0.1585f, 2.8800f, 0.2600f, 0.3500f, 0.1413f, 0.2630f, { 0.0000f, 0.0000f, -0.0000f }, 0.3981f, 0.1000f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.3400f, 0.2500f, 0.0000f, 0.9943f, 2854.3999f, 107.5000f, 0.0000f, 0x0 }\n\n/* Mood Presets */\n\n#define EFX_REVERB_PRESET_MOOD_HEAVEN \\\n    { 1.0000f, 0.9400f, 0.3162f, 0.7943f, 0.4467f, 5.0400f, 1.1200f, 0.5600f, 0.2427f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 1.2589f, 0.0290f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0800f, 2.7420f, 0.0500f, 0.9977f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }\n\n#define EFX_REVERB_PRESET_MOOD_HELL \\\n    { 1.0000f, 0.5700f, 0.3162f, 0.3548f, 0.4467f, 3.5700f, 0.4900f, 2.0000f, 0.0000f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 1.4125f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.1100f, 0.0400f, 2.1090f, 0.5200f, 0.9943f, 5000.0000f, 139.5000f, 0.0000f, 0x0 }\n\n#define EFX_REVERB_PRESET_MOOD_MEMORY \\\n    { 1.0000f, 0.8500f, 0.3162f, 0.6310f, 0.3548f, 4.0600f, 0.8200f, 0.5600f, 0.0398f, 0.0000f, { 0.0000f, 0.0000f, 0.0000f }, 1.1220f, 0.0000f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.4740f, 0.4500f, 0.9886f, 5000.0000f, 250.0000f, 0.0000f, 0x0 }\n\n/* Driving Presets */\n\n#define EFX_REVERB_PRESET_DRIVING_COMMENTATOR \\\n    { 1.0000f, 0.0000f, 0.3162f, 0.5623f, 0.5012f, 2.4200f, 0.8800f, 0.6800f, 0.1995f, 0.0930f, { 0.0000f, 0.0000f, 0.0000f }, 0.2512f, 0.0170f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 1.0000f, 0.2500f, 0.0000f, 0.9886f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }\n\n#define EFX_REVERB_PRESET_DRIVING_PITGARAGE \\\n    { 0.4287f, 0.5900f, 0.3162f, 0.7079f, 0.5623f, 1.7200f, 0.9300f, 0.8700f, 0.5623f, 0.0000f, { 0.0000f, 0.0000f, 0.0000f }, 1.2589f, 0.0160f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.1100f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 }\n\n#define EFX_REVERB_PRESET_DRIVING_INCAR_RACER \\\n    { 0.0832f, 0.8000f, 0.3162f, 1.0000f, 0.7943f, 0.1700f, 2.0000f, 0.4100f, 1.7783f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 0.7079f, 0.0150f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 10268.2002f, 251.0000f, 0.0000f, 0x1 }\n\n#define EFX_REVERB_PRESET_DRIVING_INCAR_SPORTS \\\n    { 0.0832f, 0.8000f, 0.3162f, 0.6310f, 1.0000f, 0.1700f, 0.7500f, 0.4100f, 1.0000f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 0.5623f, 0.0000f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 10268.2002f, 251.0000f, 0.0000f, 0x1 }\n\n#define EFX_REVERB_PRESET_DRIVING_INCAR_LUXURY \\\n    { 0.2560f, 1.0000f, 0.3162f, 0.1000f, 0.5012f, 0.1300f, 0.4100f, 0.4600f, 0.7943f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 1.5849f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 10268.2002f, 251.0000f, 0.0000f, 0x1 }\n\n#define EFX_REVERB_PRESET_DRIVING_FULLGRANDSTAND \\\n    { 1.0000f, 1.0000f, 0.3162f, 0.2818f, 0.6310f, 3.0100f, 1.3700f, 1.2800f, 0.3548f, 0.0900f, { 0.0000f, 0.0000f, 0.0000f }, 0.1778f, 0.0490f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 10420.2002f, 250.0000f, 0.0000f, 0x0 }\n\n#define EFX_REVERB_PRESET_DRIVING_EMPTYGRANDSTAND \\\n    { 1.0000f, 1.0000f, 0.3162f, 1.0000f, 0.7943f, 4.6200f, 1.7500f, 1.4000f, 0.2082f, 0.0900f, { 0.0000f, 0.0000f, 0.0000f }, 0.2512f, 0.0490f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 10420.2002f, 250.0000f, 0.0000f, 0x0 }\n\n#define EFX_REVERB_PRESET_DRIVING_TUNNEL \\\n    { 1.0000f, 0.8100f, 0.3162f, 0.3981f, 0.8913f, 3.4200f, 0.9400f, 1.3100f, 0.7079f, 0.0510f, { 0.0000f, 0.0000f, 0.0000f }, 0.7079f, 0.0470f, { 0.0000f, 0.0000f, 0.0000f }, 0.2140f, 0.0500f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 155.3000f, 0.0000f, 0x1 }\n\n/* City Presets */\n\n#define EFX_REVERB_PRESET_CITY_STREETS \\\n    { 1.0000f, 0.7800f, 0.3162f, 0.7079f, 0.8913f, 1.7900f, 1.1200f, 0.9100f, 0.2818f, 0.0460f, { 0.0000f, 0.0000f, 0.0000f }, 0.1995f, 0.0280f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.2000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }\n\n#define EFX_REVERB_PRESET_CITY_SUBWAY \\\n    { 1.0000f, 0.7400f, 0.3162f, 0.7079f, 0.8913f, 3.0100f, 1.2300f, 0.9100f, 0.7079f, 0.0460f, { 0.0000f, 0.0000f, 0.0000f }, 1.2589f, 0.0280f, { 0.0000f, 0.0000f, 0.0000f }, 0.1250f, 0.2100f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }\n\n#define EFX_REVERB_PRESET_CITY_MUSEUM \\\n    { 1.0000f, 0.8200f, 0.3162f, 0.1778f, 0.1778f, 3.2800f, 1.4000f, 0.5700f, 0.2512f, 0.0390f, { 0.0000f, 0.0000f, -0.0000f }, 0.8913f, 0.0340f, { 0.0000f, 0.0000f, 0.0000f }, 0.1300f, 0.1700f, 0.2500f, 0.0000f, 0.9943f, 2854.3999f, 107.5000f, 0.0000f, 0x0 }\n\n#define EFX_REVERB_PRESET_CITY_LIBRARY \\\n    { 1.0000f, 0.8200f, 0.3162f, 0.2818f, 0.0891f, 2.7600f, 0.8900f, 0.4100f, 0.3548f, 0.0290f, { 0.0000f, 0.0000f, -0.0000f }, 0.8913f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 0.1300f, 0.1700f, 0.2500f, 0.0000f, 0.9943f, 2854.3999f, 107.5000f, 0.0000f, 0x0 }\n\n#define EFX_REVERB_PRESET_CITY_UNDERPASS \\\n    { 1.0000f, 0.8200f, 0.3162f, 0.4467f, 0.8913f, 3.5700f, 1.1200f, 0.9100f, 0.3981f, 0.0590f, { 0.0000f, 0.0000f, 0.0000f }, 0.8913f, 0.0370f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.1400f, 0.2500f, 0.0000f, 0.9920f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }\n\n#define EFX_REVERB_PRESET_CITY_ABANDONED \\\n    { 1.0000f, 0.6900f, 0.3162f, 0.7943f, 0.8913f, 3.2800f, 1.1700f, 0.9100f, 0.4467f, 0.0440f, { 0.0000f, 0.0000f, 0.0000f }, 0.2818f, 0.0240f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.2000f, 0.2500f, 0.0000f, 0.9966f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }\n\n/* Misc. Presets */\n\n#define EFX_REVERB_PRESET_DUSTYROOM \\\n    { 0.3645f, 0.5600f, 0.3162f, 0.7943f, 0.7079f, 1.7900f, 0.3800f, 0.2100f, 0.5012f, 0.0020f, { 0.0000f, 0.0000f, 0.0000f }, 1.2589f, 0.0060f, { 0.0000f, 0.0000f, 0.0000f }, 0.2020f, 0.0500f, 0.2500f, 0.0000f, 0.9886f, 13046.0000f, 163.3000f, 0.0000f, 0x1 }\n\n#define EFX_REVERB_PRESET_CHAPEL \\\n    { 1.0000f, 0.8400f, 0.3162f, 0.5623f, 1.0000f, 4.6200f, 0.6400f, 1.2300f, 0.4467f, 0.0320f, { 0.0000f, 0.0000f, 0.0000f }, 0.7943f, 0.0490f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.1100f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }\n\n#define EFX_REVERB_PRESET_SMALLWATERROOM \\\n    { 1.0000f, 0.7000f, 0.3162f, 0.4477f, 1.0000f, 1.5100f, 1.2500f, 1.1400f, 0.8913f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 1.4125f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.1790f, 0.1500f, 0.8950f, 0.1900f, 0.9920f, 5000.0000f, 250.0000f, 0.0000f, 0x0 }\n\n#endif /* EFX_PRESETS_H */\n"
  },
  {
    "path": "vendor/openal-soft/include/AL/efx.h",
    "content": "#ifndef AL_EFX_H\n#define AL_EFX_H\n\n#include <float.h>\n\n#include \"alc.h\"\n#include \"al.h\"\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#define ALC_EXT_EFX_NAME                         \"ALC_EXT_EFX\"\n\n#define ALC_EFX_MAJOR_VERSION                    0x20001\n#define ALC_EFX_MINOR_VERSION                    0x20002\n#define ALC_MAX_AUXILIARY_SENDS                  0x20003\n\n\n/* Listener properties. */\n#define AL_METERS_PER_UNIT                       0x20004\n\n/* Source properties. */\n#define AL_DIRECT_FILTER                         0x20005\n#define AL_AUXILIARY_SEND_FILTER                 0x20006\n#define AL_AIR_ABSORPTION_FACTOR                 0x20007\n#define AL_ROOM_ROLLOFF_FACTOR                   0x20008\n#define AL_CONE_OUTER_GAINHF                     0x20009\n#define AL_DIRECT_FILTER_GAINHF_AUTO             0x2000A\n#define AL_AUXILIARY_SEND_FILTER_GAIN_AUTO       0x2000B\n#define AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO     0x2000C\n\n\n/* Effect properties. */\n\n/* Reverb effect parameters */\n#define AL_REVERB_DENSITY                        0x0001\n#define AL_REVERB_DIFFUSION                      0x0002\n#define AL_REVERB_GAIN                           0x0003\n#define AL_REVERB_GAINHF                         0x0004\n#define AL_REVERB_DECAY_TIME                     0x0005\n#define AL_REVERB_DECAY_HFRATIO                  0x0006\n#define AL_REVERB_REFLECTIONS_GAIN               0x0007\n#define AL_REVERB_REFLECTIONS_DELAY              0x0008\n#define AL_REVERB_LATE_REVERB_GAIN               0x0009\n#define AL_REVERB_LATE_REVERB_DELAY              0x000A\n#define AL_REVERB_AIR_ABSORPTION_GAINHF          0x000B\n#define AL_REVERB_ROOM_ROLLOFF_FACTOR            0x000C\n#define AL_REVERB_DECAY_HFLIMIT                  0x000D\n\n/* EAX Reverb effect parameters */\n#define AL_EAXREVERB_DENSITY                     0x0001\n#define AL_EAXREVERB_DIFFUSION                   0x0002\n#define AL_EAXREVERB_GAIN                        0x0003\n#define AL_EAXREVERB_GAINHF                      0x0004\n#define AL_EAXREVERB_GAINLF                      0x0005\n#define AL_EAXREVERB_DECAY_TIME                  0x0006\n#define AL_EAXREVERB_DECAY_HFRATIO               0x0007\n#define AL_EAXREVERB_DECAY_LFRATIO               0x0008\n#define AL_EAXREVERB_REFLECTIONS_GAIN            0x0009\n#define AL_EAXREVERB_REFLECTIONS_DELAY           0x000A\n#define AL_EAXREVERB_REFLECTIONS_PAN             0x000B\n#define AL_EAXREVERB_LATE_REVERB_GAIN            0x000C\n#define AL_EAXREVERB_LATE_REVERB_DELAY           0x000D\n#define AL_EAXREVERB_LATE_REVERB_PAN             0x000E\n#define AL_EAXREVERB_ECHO_TIME                   0x000F\n#define AL_EAXREVERB_ECHO_DEPTH                  0x0010\n#define AL_EAXREVERB_MODULATION_TIME             0x0011\n#define AL_EAXREVERB_MODULATION_DEPTH            0x0012\n#define AL_EAXREVERB_AIR_ABSORPTION_GAINHF       0x0013\n#define AL_EAXREVERB_HFREFERENCE                 0x0014\n#define AL_EAXREVERB_LFREFERENCE                 0x0015\n#define AL_EAXREVERB_ROOM_ROLLOFF_FACTOR         0x0016\n#define AL_EAXREVERB_DECAY_HFLIMIT               0x0017\n\n/* Chorus effect parameters */\n#define AL_CHORUS_WAVEFORM                       0x0001\n#define AL_CHORUS_PHASE                          0x0002\n#define AL_CHORUS_RATE                           0x0003\n#define AL_CHORUS_DEPTH                          0x0004\n#define AL_CHORUS_FEEDBACK                       0x0005\n#define AL_CHORUS_DELAY                          0x0006\n\n/* Distortion effect parameters */\n#define AL_DISTORTION_EDGE                       0x0001\n#define AL_DISTORTION_GAIN                       0x0002\n#define AL_DISTORTION_LOWPASS_CUTOFF             0x0003\n#define AL_DISTORTION_EQCENTER                   0x0004\n#define AL_DISTORTION_EQBANDWIDTH                0x0005\n\n/* Echo effect parameters */\n#define AL_ECHO_DELAY                            0x0001\n#define AL_ECHO_LRDELAY                          0x0002\n#define AL_ECHO_DAMPING                          0x0003\n#define AL_ECHO_FEEDBACK                         0x0004\n#define AL_ECHO_SPREAD                           0x0005\n\n/* Flanger effect parameters */\n#define AL_FLANGER_WAVEFORM                      0x0001\n#define AL_FLANGER_PHASE                         0x0002\n#define AL_FLANGER_RATE                          0x0003\n#define AL_FLANGER_DEPTH                         0x0004\n#define AL_FLANGER_FEEDBACK                      0x0005\n#define AL_FLANGER_DELAY                         0x0006\n\n/* Frequency shifter effect parameters */\n#define AL_FREQUENCY_SHIFTER_FREQUENCY           0x0001\n#define AL_FREQUENCY_SHIFTER_LEFT_DIRECTION      0x0002\n#define AL_FREQUENCY_SHIFTER_RIGHT_DIRECTION     0x0003\n\n/* Vocal morpher effect parameters */\n#define AL_VOCAL_MORPHER_PHONEMEA                0x0001\n#define AL_VOCAL_MORPHER_PHONEMEA_COARSE_TUNING  0x0002\n#define AL_VOCAL_MORPHER_PHONEMEB                0x0003\n#define AL_VOCAL_MORPHER_PHONEMEB_COARSE_TUNING  0x0004\n#define AL_VOCAL_MORPHER_WAVEFORM                0x0005\n#define AL_VOCAL_MORPHER_RATE                    0x0006\n\n/* Pitchshifter effect parameters */\n#define AL_PITCH_SHIFTER_COARSE_TUNE             0x0001\n#define AL_PITCH_SHIFTER_FINE_TUNE               0x0002\n\n/* Ringmodulator effect parameters */\n#define AL_RING_MODULATOR_FREQUENCY              0x0001\n#define AL_RING_MODULATOR_HIGHPASS_CUTOFF        0x0002\n#define AL_RING_MODULATOR_WAVEFORM               0x0003\n\n/* Autowah effect parameters */\n#define AL_AUTOWAH_ATTACK_TIME                   0x0001\n#define AL_AUTOWAH_RELEASE_TIME                  0x0002\n#define AL_AUTOWAH_RESONANCE                     0x0003\n#define AL_AUTOWAH_PEAK_GAIN                     0x0004\n\n/* Compressor effect parameters */\n#define AL_COMPRESSOR_ONOFF                      0x0001\n\n/* Equalizer effect parameters */\n#define AL_EQUALIZER_LOW_GAIN                    0x0001\n#define AL_EQUALIZER_LOW_CUTOFF                  0x0002\n#define AL_EQUALIZER_MID1_GAIN                   0x0003\n#define AL_EQUALIZER_MID1_CENTER                 0x0004\n#define AL_EQUALIZER_MID1_WIDTH                  0x0005\n#define AL_EQUALIZER_MID2_GAIN                   0x0006\n#define AL_EQUALIZER_MID2_CENTER                 0x0007\n#define AL_EQUALIZER_MID2_WIDTH                  0x0008\n#define AL_EQUALIZER_HIGH_GAIN                   0x0009\n#define AL_EQUALIZER_HIGH_CUTOFF                 0x000A\n\n/* Effect type */\n#define AL_EFFECT_FIRST_PARAMETER                0x0000\n#define AL_EFFECT_LAST_PARAMETER                 0x8000\n#define AL_EFFECT_TYPE                           0x8001\n\n/* Effect types, used with the AL_EFFECT_TYPE property */\n#define AL_EFFECT_NULL                           0x0000\n#define AL_EFFECT_REVERB                         0x0001\n#define AL_EFFECT_CHORUS                         0x0002\n#define AL_EFFECT_DISTORTION                     0x0003\n#define AL_EFFECT_ECHO                           0x0004\n#define AL_EFFECT_FLANGER                        0x0005\n#define AL_EFFECT_FREQUENCY_SHIFTER              0x0006\n#define AL_EFFECT_VOCAL_MORPHER                  0x0007\n#define AL_EFFECT_PITCH_SHIFTER                  0x0008\n#define AL_EFFECT_RING_MODULATOR                 0x0009\n#define AL_EFFECT_AUTOWAH                        0x000A\n#define AL_EFFECT_COMPRESSOR                     0x000B\n#define AL_EFFECT_EQUALIZER                      0x000C\n#define AL_EFFECT_EAXREVERB                      0x8000\n\n/* Auxiliary Effect Slot properties. */\n#define AL_EFFECTSLOT_EFFECT                     0x0001\n#define AL_EFFECTSLOT_GAIN                       0x0002\n#define AL_EFFECTSLOT_AUXILIARY_SEND_AUTO        0x0003\n\n/* NULL Auxiliary Slot ID to disable a source send. */\n#define AL_EFFECTSLOT_NULL                       0x0000\n\n\n/* Filter properties. */\n\n/* Lowpass filter parameters */\n#define AL_LOWPASS_GAIN                          0x0001\n#define AL_LOWPASS_GAINHF                        0x0002\n\n/* Highpass filter parameters */\n#define AL_HIGHPASS_GAIN                         0x0001\n#define AL_HIGHPASS_GAINLF                       0x0002\n\n/* Bandpass filter parameters */\n#define AL_BANDPASS_GAIN                         0x0001\n#define AL_BANDPASS_GAINLF                       0x0002\n#define AL_BANDPASS_GAINHF                       0x0003\n\n/* Filter type */\n#define AL_FILTER_FIRST_PARAMETER                0x0000\n#define AL_FILTER_LAST_PARAMETER                 0x8000\n#define AL_FILTER_TYPE                           0x8001\n\n/* Filter types, used with the AL_FILTER_TYPE property */\n#define AL_FILTER_NULL                           0x0000\n#define AL_FILTER_LOWPASS                        0x0001\n#define AL_FILTER_HIGHPASS                       0x0002\n#define AL_FILTER_BANDPASS                       0x0003\n\n\n/* Effect object function types. */\ntypedef void (AL_APIENTRY *LPALGENEFFECTS)(ALsizei, ALuint*);\ntypedef void (AL_APIENTRY *LPALDELETEEFFECTS)(ALsizei, const ALuint*);\ntypedef ALboolean (AL_APIENTRY *LPALISEFFECT)(ALuint);\ntypedef void (AL_APIENTRY *LPALEFFECTI)(ALuint, ALenum, ALint);\ntypedef void (AL_APIENTRY *LPALEFFECTIV)(ALuint, ALenum, const ALint*);\ntypedef void (AL_APIENTRY *LPALEFFECTF)(ALuint, ALenum, ALfloat);\ntypedef void (AL_APIENTRY *LPALEFFECTFV)(ALuint, ALenum, const ALfloat*);\ntypedef void (AL_APIENTRY *LPALGETEFFECTI)(ALuint, ALenum, ALint*);\ntypedef void (AL_APIENTRY *LPALGETEFFECTIV)(ALuint, ALenum, ALint*);\ntypedef void (AL_APIENTRY *LPALGETEFFECTF)(ALuint, ALenum, ALfloat*);\ntypedef void (AL_APIENTRY *LPALGETEFFECTFV)(ALuint, ALenum, ALfloat*);\n\n/* Filter object function types. */\ntypedef void (AL_APIENTRY *LPALGENFILTERS)(ALsizei, ALuint*);\ntypedef void (AL_APIENTRY *LPALDELETEFILTERS)(ALsizei, const ALuint*);\ntypedef ALboolean (AL_APIENTRY *LPALISFILTER)(ALuint);\ntypedef void (AL_APIENTRY *LPALFILTERI)(ALuint, ALenum, ALint);\ntypedef void (AL_APIENTRY *LPALFILTERIV)(ALuint, ALenum, const ALint*);\ntypedef void (AL_APIENTRY *LPALFILTERF)(ALuint, ALenum, ALfloat);\ntypedef void (AL_APIENTRY *LPALFILTERFV)(ALuint, ALenum, const ALfloat*);\ntypedef void (AL_APIENTRY *LPALGETFILTERI)(ALuint, ALenum, ALint*);\ntypedef void (AL_APIENTRY *LPALGETFILTERIV)(ALuint, ALenum, ALint*);\ntypedef void (AL_APIENTRY *LPALGETFILTERF)(ALuint, ALenum, ALfloat*);\ntypedef void (AL_APIENTRY *LPALGETFILTERFV)(ALuint, ALenum, ALfloat*);\n\n/* Auxiliary Effect Slot object function types. */\ntypedef void (AL_APIENTRY *LPALGENAUXILIARYEFFECTSLOTS)(ALsizei, ALuint*);\ntypedef void (AL_APIENTRY *LPALDELETEAUXILIARYEFFECTSLOTS)(ALsizei, const ALuint*);\ntypedef ALboolean (AL_APIENTRY *LPALISAUXILIARYEFFECTSLOT)(ALuint);\ntypedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTI)(ALuint, ALenum, ALint);\ntypedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTIV)(ALuint, ALenum, const ALint*);\ntypedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTF)(ALuint, ALenum, ALfloat);\ntypedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTFV)(ALuint, ALenum, const ALfloat*);\ntypedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTI)(ALuint, ALenum, ALint*);\ntypedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTIV)(ALuint, ALenum, ALint*);\ntypedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTF)(ALuint, ALenum, ALfloat*);\ntypedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTFV)(ALuint, ALenum, ALfloat*);\n\n#ifdef AL_ALEXT_PROTOTYPES\nAL_API void AL_APIENTRY alGenEffects(ALsizei n, ALuint *effects);\nAL_API void AL_APIENTRY alDeleteEffects(ALsizei n, const ALuint *effects);\nAL_API ALboolean AL_APIENTRY alIsEffect(ALuint effect);\nAL_API void AL_APIENTRY alEffecti(ALuint effect, ALenum param, ALint iValue);\nAL_API void AL_APIENTRY alEffectiv(ALuint effect, ALenum param, const ALint *piValues);\nAL_API void AL_APIENTRY alEffectf(ALuint effect, ALenum param, ALfloat flValue);\nAL_API void AL_APIENTRY alEffectfv(ALuint effect, ALenum param, const ALfloat *pflValues);\nAL_API void AL_APIENTRY alGetEffecti(ALuint effect, ALenum param, ALint *piValue);\nAL_API void AL_APIENTRY alGetEffectiv(ALuint effect, ALenum param, ALint *piValues);\nAL_API void AL_APIENTRY alGetEffectf(ALuint effect, ALenum param, ALfloat *pflValue);\nAL_API void AL_APIENTRY alGetEffectfv(ALuint effect, ALenum param, ALfloat *pflValues);\n\nAL_API void AL_APIENTRY alGenFilters(ALsizei n, ALuint *filters);\nAL_API void AL_APIENTRY alDeleteFilters(ALsizei n, const ALuint *filters);\nAL_API ALboolean AL_APIENTRY alIsFilter(ALuint filter);\nAL_API void AL_APIENTRY alFilteri(ALuint filter, ALenum param, ALint iValue);\nAL_API void AL_APIENTRY alFilteriv(ALuint filter, ALenum param, const ALint *piValues);\nAL_API void AL_APIENTRY alFilterf(ALuint filter, ALenum param, ALfloat flValue);\nAL_API void AL_APIENTRY alFilterfv(ALuint filter, ALenum param, const ALfloat *pflValues);\nAL_API void AL_APIENTRY alGetFilteri(ALuint filter, ALenum param, ALint *piValue);\nAL_API void AL_APIENTRY alGetFilteriv(ALuint filter, ALenum param, ALint *piValues);\nAL_API void AL_APIENTRY alGetFilterf(ALuint filter, ALenum param, ALfloat *pflValue);\nAL_API void AL_APIENTRY alGetFilterfv(ALuint filter, ALenum param, ALfloat *pflValues);\n\nAL_API void AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots);\nAL_API void AL_APIENTRY alDeleteAuxiliaryEffectSlots(ALsizei n, const ALuint *effectslots);\nAL_API ALboolean AL_APIENTRY alIsAuxiliaryEffectSlot(ALuint effectslot);\nAL_API void AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint iValue);\nAL_API void AL_APIENTRY alAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, const ALint *piValues);\nAL_API void AL_APIENTRY alAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat flValue);\nAL_API void AL_APIENTRY alAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, const ALfloat *pflValues);\nAL_API void AL_APIENTRY alGetAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint *piValue);\nAL_API void AL_APIENTRY alGetAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *piValues);\nAL_API void AL_APIENTRY alGetAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat *pflValue);\nAL_API void AL_APIENTRY alGetAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *pflValues);\n#endif\n\n/* Filter ranges and defaults. */\n\n/* Lowpass filter */\n#define AL_LOWPASS_MIN_GAIN                      (0.0f)\n#define AL_LOWPASS_MAX_GAIN                      (1.0f)\n#define AL_LOWPASS_DEFAULT_GAIN                  (1.0f)\n\n#define AL_LOWPASS_MIN_GAINHF                    (0.0f)\n#define AL_LOWPASS_MAX_GAINHF                    (1.0f)\n#define AL_LOWPASS_DEFAULT_GAINHF                (1.0f)\n\n/* Highpass filter */\n#define AL_HIGHPASS_MIN_GAIN                     (0.0f)\n#define AL_HIGHPASS_MAX_GAIN                     (1.0f)\n#define AL_HIGHPASS_DEFAULT_GAIN                 (1.0f)\n\n#define AL_HIGHPASS_MIN_GAINLF                   (0.0f)\n#define AL_HIGHPASS_MAX_GAINLF                   (1.0f)\n#define AL_HIGHPASS_DEFAULT_GAINLF               (1.0f)\n\n/* Bandpass filter */\n#define AL_BANDPASS_MIN_GAIN                     (0.0f)\n#define AL_BANDPASS_MAX_GAIN                     (1.0f)\n#define AL_BANDPASS_DEFAULT_GAIN                 (1.0f)\n\n#define AL_BANDPASS_MIN_GAINHF                   (0.0f)\n#define AL_BANDPASS_MAX_GAINHF                   (1.0f)\n#define AL_BANDPASS_DEFAULT_GAINHF               (1.0f)\n\n#define AL_BANDPASS_MIN_GAINLF                   (0.0f)\n#define AL_BANDPASS_MAX_GAINLF                   (1.0f)\n#define AL_BANDPASS_DEFAULT_GAINLF               (1.0f)\n\n\n/* Effect parameter ranges and defaults. */\n\n/* Standard reverb effect */\n#define AL_REVERB_MIN_DENSITY                    (0.0f)\n#define AL_REVERB_MAX_DENSITY                    (1.0f)\n#define AL_REVERB_DEFAULT_DENSITY                (1.0f)\n\n#define AL_REVERB_MIN_DIFFUSION                  (0.0f)\n#define AL_REVERB_MAX_DIFFUSION                  (1.0f)\n#define AL_REVERB_DEFAULT_DIFFUSION              (1.0f)\n\n#define AL_REVERB_MIN_GAIN                       (0.0f)\n#define AL_REVERB_MAX_GAIN                       (1.0f)\n#define AL_REVERB_DEFAULT_GAIN                   (0.32f)\n\n#define AL_REVERB_MIN_GAINHF                     (0.0f)\n#define AL_REVERB_MAX_GAINHF                     (1.0f)\n#define AL_REVERB_DEFAULT_GAINHF                 (0.89f)\n\n#define AL_REVERB_MIN_DECAY_TIME                 (0.1f)\n#define AL_REVERB_MAX_DECAY_TIME                 (20.0f)\n#define AL_REVERB_DEFAULT_DECAY_TIME             (1.49f)\n\n#define AL_REVERB_MIN_DECAY_HFRATIO              (0.1f)\n#define AL_REVERB_MAX_DECAY_HFRATIO              (2.0f)\n#define AL_REVERB_DEFAULT_DECAY_HFRATIO          (0.83f)\n\n#define AL_REVERB_MIN_REFLECTIONS_GAIN           (0.0f)\n#define AL_REVERB_MAX_REFLECTIONS_GAIN           (3.16f)\n#define AL_REVERB_DEFAULT_REFLECTIONS_GAIN       (0.05f)\n\n#define AL_REVERB_MIN_REFLECTIONS_DELAY          (0.0f)\n#define AL_REVERB_MAX_REFLECTIONS_DELAY          (0.3f)\n#define AL_REVERB_DEFAULT_REFLECTIONS_DELAY      (0.007f)\n\n#define AL_REVERB_MIN_LATE_REVERB_GAIN           (0.0f)\n#define AL_REVERB_MAX_LATE_REVERB_GAIN           (10.0f)\n#define AL_REVERB_DEFAULT_LATE_REVERB_GAIN       (1.26f)\n\n#define AL_REVERB_MIN_LATE_REVERB_DELAY          (0.0f)\n#define AL_REVERB_MAX_LATE_REVERB_DELAY          (0.1f)\n#define AL_REVERB_DEFAULT_LATE_REVERB_DELAY      (0.011f)\n\n#define AL_REVERB_MIN_AIR_ABSORPTION_GAINHF      (0.892f)\n#define AL_REVERB_MAX_AIR_ABSORPTION_GAINHF      (1.0f)\n#define AL_REVERB_DEFAULT_AIR_ABSORPTION_GAINHF  (0.994f)\n\n#define AL_REVERB_MIN_ROOM_ROLLOFF_FACTOR        (0.0f)\n#define AL_REVERB_MAX_ROOM_ROLLOFF_FACTOR        (10.0f)\n#define AL_REVERB_DEFAULT_ROOM_ROLLOFF_FACTOR    (0.0f)\n\n#define AL_REVERB_MIN_DECAY_HFLIMIT              AL_FALSE\n#define AL_REVERB_MAX_DECAY_HFLIMIT              AL_TRUE\n#define AL_REVERB_DEFAULT_DECAY_HFLIMIT          AL_TRUE\n\n/* EAX reverb effect */\n#define AL_EAXREVERB_MIN_DENSITY                 (0.0f)\n#define AL_EAXREVERB_MAX_DENSITY                 (1.0f)\n#define AL_EAXREVERB_DEFAULT_DENSITY             (1.0f)\n\n#define AL_EAXREVERB_MIN_DIFFUSION               (0.0f)\n#define AL_EAXREVERB_MAX_DIFFUSION               (1.0f)\n#define AL_EAXREVERB_DEFAULT_DIFFUSION           (1.0f)\n\n#define AL_EAXREVERB_MIN_GAIN                    (0.0f)\n#define AL_EAXREVERB_MAX_GAIN                    (1.0f)\n#define AL_EAXREVERB_DEFAULT_GAIN                (0.32f)\n\n#define AL_EAXREVERB_MIN_GAINHF                  (0.0f)\n#define AL_EAXREVERB_MAX_GAINHF                  (1.0f)\n#define AL_EAXREVERB_DEFAULT_GAINHF              (0.89f)\n\n#define AL_EAXREVERB_MIN_GAINLF                  (0.0f)\n#define AL_EAXREVERB_MAX_GAINLF                  (1.0f)\n#define AL_EAXREVERB_DEFAULT_GAINLF              (1.0f)\n\n#define AL_EAXREVERB_MIN_DECAY_TIME              (0.1f)\n#define AL_EAXREVERB_MAX_DECAY_TIME              (20.0f)\n#define AL_EAXREVERB_DEFAULT_DECAY_TIME          (1.49f)\n\n#define AL_EAXREVERB_MIN_DECAY_HFRATIO           (0.1f)\n#define AL_EAXREVERB_MAX_DECAY_HFRATIO           (2.0f)\n#define AL_EAXREVERB_DEFAULT_DECAY_HFRATIO       (0.83f)\n\n#define AL_EAXREVERB_MIN_DECAY_LFRATIO           (0.1f)\n#define AL_EAXREVERB_MAX_DECAY_LFRATIO           (2.0f)\n#define AL_EAXREVERB_DEFAULT_DECAY_LFRATIO       (1.0f)\n\n#define AL_EAXREVERB_MIN_REFLECTIONS_GAIN        (0.0f)\n#define AL_EAXREVERB_MAX_REFLECTIONS_GAIN        (3.16f)\n#define AL_EAXREVERB_DEFAULT_REFLECTIONS_GAIN    (0.05f)\n\n#define AL_EAXREVERB_MIN_REFLECTIONS_DELAY       (0.0f)\n#define AL_EAXREVERB_MAX_REFLECTIONS_DELAY       (0.3f)\n#define AL_EAXREVERB_DEFAULT_REFLECTIONS_DELAY   (0.007f)\n\n#define AL_EAXREVERB_DEFAULT_REFLECTIONS_PAN_XYZ (0.0f)\n\n#define AL_EAXREVERB_MIN_LATE_REVERB_GAIN        (0.0f)\n#define AL_EAXREVERB_MAX_LATE_REVERB_GAIN        (10.0f)\n#define AL_EAXREVERB_DEFAULT_LATE_REVERB_GAIN    (1.26f)\n\n#define AL_EAXREVERB_MIN_LATE_REVERB_DELAY       (0.0f)\n#define AL_EAXREVERB_MAX_LATE_REVERB_DELAY       (0.1f)\n#define AL_EAXREVERB_DEFAULT_LATE_REVERB_DELAY   (0.011f)\n\n#define AL_EAXREVERB_DEFAULT_LATE_REVERB_PAN_XYZ (0.0f)\n\n#define AL_EAXREVERB_MIN_ECHO_TIME               (0.075f)\n#define AL_EAXREVERB_MAX_ECHO_TIME               (0.25f)\n#define AL_EAXREVERB_DEFAULT_ECHO_TIME           (0.25f)\n\n#define AL_EAXREVERB_MIN_ECHO_DEPTH              (0.0f)\n#define AL_EAXREVERB_MAX_ECHO_DEPTH              (1.0f)\n#define AL_EAXREVERB_DEFAULT_ECHO_DEPTH          (0.0f)\n\n#define AL_EAXREVERB_MIN_MODULATION_TIME         (0.04f)\n#define AL_EAXREVERB_MAX_MODULATION_TIME         (4.0f)\n#define AL_EAXREVERB_DEFAULT_MODULATION_TIME     (0.25f)\n\n#define AL_EAXREVERB_MIN_MODULATION_DEPTH        (0.0f)\n#define AL_EAXREVERB_MAX_MODULATION_DEPTH        (1.0f)\n#define AL_EAXREVERB_DEFAULT_MODULATION_DEPTH    (0.0f)\n\n#define AL_EAXREVERB_MIN_AIR_ABSORPTION_GAINHF   (0.892f)\n#define AL_EAXREVERB_MAX_AIR_ABSORPTION_GAINHF   (1.0f)\n#define AL_EAXREVERB_DEFAULT_AIR_ABSORPTION_GAINHF (0.994f)\n\n#define AL_EAXREVERB_MIN_HFREFERENCE             (1000.0f)\n#define AL_EAXREVERB_MAX_HFREFERENCE             (20000.0f)\n#define AL_EAXREVERB_DEFAULT_HFREFERENCE         (5000.0f)\n\n#define AL_EAXREVERB_MIN_LFREFERENCE             (20.0f)\n#define AL_EAXREVERB_MAX_LFREFERENCE             (1000.0f)\n#define AL_EAXREVERB_DEFAULT_LFREFERENCE         (250.0f)\n\n#define AL_EAXREVERB_MIN_ROOM_ROLLOFF_FACTOR     (0.0f)\n#define AL_EAXREVERB_MAX_ROOM_ROLLOFF_FACTOR     (10.0f)\n#define AL_EAXREVERB_DEFAULT_ROOM_ROLLOFF_FACTOR (0.0f)\n\n#define AL_EAXREVERB_MIN_DECAY_HFLIMIT           AL_FALSE\n#define AL_EAXREVERB_MAX_DECAY_HFLIMIT           AL_TRUE\n#define AL_EAXREVERB_DEFAULT_DECAY_HFLIMIT       AL_TRUE\n\n/* Chorus effect */\n#define AL_CHORUS_WAVEFORM_SINUSOID              (0)\n#define AL_CHORUS_WAVEFORM_TRIANGLE              (1)\n\n#define AL_CHORUS_MIN_WAVEFORM                   (0)\n#define AL_CHORUS_MAX_WAVEFORM                   (1)\n#define AL_CHORUS_DEFAULT_WAVEFORM               (1)\n\n#define AL_CHORUS_MIN_PHASE                      (-180)\n#define AL_CHORUS_MAX_PHASE                      (180)\n#define AL_CHORUS_DEFAULT_PHASE                  (90)\n\n#define AL_CHORUS_MIN_RATE                       (0.0f)\n#define AL_CHORUS_MAX_RATE                       (10.0f)\n#define AL_CHORUS_DEFAULT_RATE                   (1.1f)\n\n#define AL_CHORUS_MIN_DEPTH                      (0.0f)\n#define AL_CHORUS_MAX_DEPTH                      (1.0f)\n#define AL_CHORUS_DEFAULT_DEPTH                  (0.1f)\n\n#define AL_CHORUS_MIN_FEEDBACK                   (-1.0f)\n#define AL_CHORUS_MAX_FEEDBACK                   (1.0f)\n#define AL_CHORUS_DEFAULT_FEEDBACK               (0.25f)\n\n#define AL_CHORUS_MIN_DELAY                      (0.0f)\n#define AL_CHORUS_MAX_DELAY                      (0.016f)\n#define AL_CHORUS_DEFAULT_DELAY                  (0.016f)\n\n/* Distortion effect */\n#define AL_DISTORTION_MIN_EDGE                   (0.0f)\n#define AL_DISTORTION_MAX_EDGE                   (1.0f)\n#define AL_DISTORTION_DEFAULT_EDGE               (0.2f)\n\n#define AL_DISTORTION_MIN_GAIN                   (0.01f)\n#define AL_DISTORTION_MAX_GAIN                   (1.0f)\n#define AL_DISTORTION_DEFAULT_GAIN               (0.05f)\n\n#define AL_DISTORTION_MIN_LOWPASS_CUTOFF         (80.0f)\n#define AL_DISTORTION_MAX_LOWPASS_CUTOFF         (24000.0f)\n#define AL_DISTORTION_DEFAULT_LOWPASS_CUTOFF     (8000.0f)\n\n#define AL_DISTORTION_MIN_EQCENTER               (80.0f)\n#define AL_DISTORTION_MAX_EQCENTER               (24000.0f)\n#define AL_DISTORTION_DEFAULT_EQCENTER           (3600.0f)\n\n#define AL_DISTORTION_MIN_EQBANDWIDTH            (80.0f)\n#define AL_DISTORTION_MAX_EQBANDWIDTH            (24000.0f)\n#define AL_DISTORTION_DEFAULT_EQBANDWIDTH        (3600.0f)\n\n/* Echo effect */\n#define AL_ECHO_MIN_DELAY                        (0.0f)\n#define AL_ECHO_MAX_DELAY                        (0.207f)\n#define AL_ECHO_DEFAULT_DELAY                    (0.1f)\n\n#define AL_ECHO_MIN_LRDELAY                      (0.0f)\n#define AL_ECHO_MAX_LRDELAY                      (0.404f)\n#define AL_ECHO_DEFAULT_LRDELAY                  (0.1f)\n\n#define AL_ECHO_MIN_DAMPING                      (0.0f)\n#define AL_ECHO_MAX_DAMPING                      (0.99f)\n#define AL_ECHO_DEFAULT_DAMPING                  (0.5f)\n\n#define AL_ECHO_MIN_FEEDBACK                     (0.0f)\n#define AL_ECHO_MAX_FEEDBACK                     (1.0f)\n#define AL_ECHO_DEFAULT_FEEDBACK                 (0.5f)\n\n#define AL_ECHO_MIN_SPREAD                       (-1.0f)\n#define AL_ECHO_MAX_SPREAD                       (1.0f)\n#define AL_ECHO_DEFAULT_SPREAD                   (-1.0f)\n\n/* Flanger effect */\n#define AL_FLANGER_WAVEFORM_SINUSOID             (0)\n#define AL_FLANGER_WAVEFORM_TRIANGLE             (1)\n\n#define AL_FLANGER_MIN_WAVEFORM                  (0)\n#define AL_FLANGER_MAX_WAVEFORM                  (1)\n#define AL_FLANGER_DEFAULT_WAVEFORM              (1)\n\n#define AL_FLANGER_MIN_PHASE                     (-180)\n#define AL_FLANGER_MAX_PHASE                     (180)\n#define AL_FLANGER_DEFAULT_PHASE                 (0)\n\n#define AL_FLANGER_MIN_RATE                      (0.0f)\n#define AL_FLANGER_MAX_RATE                      (10.0f)\n#define AL_FLANGER_DEFAULT_RATE                  (0.27f)\n\n#define AL_FLANGER_MIN_DEPTH                     (0.0f)\n#define AL_FLANGER_MAX_DEPTH                     (1.0f)\n#define AL_FLANGER_DEFAULT_DEPTH                 (1.0f)\n\n#define AL_FLANGER_MIN_FEEDBACK                  (-1.0f)\n#define AL_FLANGER_MAX_FEEDBACK                  (1.0f)\n#define AL_FLANGER_DEFAULT_FEEDBACK              (-0.5f)\n\n#define AL_FLANGER_MIN_DELAY                     (0.0f)\n#define AL_FLANGER_MAX_DELAY                     (0.004f)\n#define AL_FLANGER_DEFAULT_DELAY                 (0.002f)\n\n/* Frequency shifter effect */\n#define AL_FREQUENCY_SHIFTER_MIN_FREQUENCY       (0.0f)\n#define AL_FREQUENCY_SHIFTER_MAX_FREQUENCY       (24000.0f)\n#define AL_FREQUENCY_SHIFTER_DEFAULT_FREQUENCY   (0.0f)\n\n#define AL_FREQUENCY_SHIFTER_MIN_LEFT_DIRECTION  (0)\n#define AL_FREQUENCY_SHIFTER_MAX_LEFT_DIRECTION  (2)\n#define AL_FREQUENCY_SHIFTER_DEFAULT_LEFT_DIRECTION (0)\n\n#define AL_FREQUENCY_SHIFTER_DIRECTION_DOWN      (0)\n#define AL_FREQUENCY_SHIFTER_DIRECTION_UP        (1)\n#define AL_FREQUENCY_SHIFTER_DIRECTION_OFF       (2)\n\n#define AL_FREQUENCY_SHIFTER_MIN_RIGHT_DIRECTION (0)\n#define AL_FREQUENCY_SHIFTER_MAX_RIGHT_DIRECTION (2)\n#define AL_FREQUENCY_SHIFTER_DEFAULT_RIGHT_DIRECTION (0)\n\n/* Vocal morpher effect */\n#define AL_VOCAL_MORPHER_MIN_PHONEMEA            (0)\n#define AL_VOCAL_MORPHER_MAX_PHONEMEA            (29)\n#define AL_VOCAL_MORPHER_DEFAULT_PHONEMEA        (0)\n\n#define AL_VOCAL_MORPHER_MIN_PHONEMEA_COARSE_TUNING (-24)\n#define AL_VOCAL_MORPHER_MAX_PHONEMEA_COARSE_TUNING (24)\n#define AL_VOCAL_MORPHER_DEFAULT_PHONEMEA_COARSE_TUNING (0)\n\n#define AL_VOCAL_MORPHER_MIN_PHONEMEB            (0)\n#define AL_VOCAL_MORPHER_MAX_PHONEMEB            (29)\n#define AL_VOCAL_MORPHER_DEFAULT_PHONEMEB        (10)\n\n#define AL_VOCAL_MORPHER_MIN_PHONEMEB_COARSE_TUNING (-24)\n#define AL_VOCAL_MORPHER_MAX_PHONEMEB_COARSE_TUNING (24)\n#define AL_VOCAL_MORPHER_DEFAULT_PHONEMEB_COARSE_TUNING (0)\n\n#define AL_VOCAL_MORPHER_PHONEME_A               (0)\n#define AL_VOCAL_MORPHER_PHONEME_E               (1)\n#define AL_VOCAL_MORPHER_PHONEME_I               (2)\n#define AL_VOCAL_MORPHER_PHONEME_O               (3)\n#define AL_VOCAL_MORPHER_PHONEME_U               (4)\n#define AL_VOCAL_MORPHER_PHONEME_AA              (5)\n#define AL_VOCAL_MORPHER_PHONEME_AE              (6)\n#define AL_VOCAL_MORPHER_PHONEME_AH              (7)\n#define AL_VOCAL_MORPHER_PHONEME_AO              (8)\n#define AL_VOCAL_MORPHER_PHONEME_EH              (9)\n#define AL_VOCAL_MORPHER_PHONEME_ER              (10)\n#define AL_VOCAL_MORPHER_PHONEME_IH              (11)\n#define AL_VOCAL_MORPHER_PHONEME_IY              (12)\n#define AL_VOCAL_MORPHER_PHONEME_UH              (13)\n#define AL_VOCAL_MORPHER_PHONEME_UW              (14)\n#define AL_VOCAL_MORPHER_PHONEME_B               (15)\n#define AL_VOCAL_MORPHER_PHONEME_D               (16)\n#define AL_VOCAL_MORPHER_PHONEME_F               (17)\n#define AL_VOCAL_MORPHER_PHONEME_G               (18)\n#define AL_VOCAL_MORPHER_PHONEME_J               (19)\n#define AL_VOCAL_MORPHER_PHONEME_K               (20)\n#define AL_VOCAL_MORPHER_PHONEME_L               (21)\n#define AL_VOCAL_MORPHER_PHONEME_M               (22)\n#define AL_VOCAL_MORPHER_PHONEME_N               (23)\n#define AL_VOCAL_MORPHER_PHONEME_P               (24)\n#define AL_VOCAL_MORPHER_PHONEME_R               (25)\n#define AL_VOCAL_MORPHER_PHONEME_S               (26)\n#define AL_VOCAL_MORPHER_PHONEME_T               (27)\n#define AL_VOCAL_MORPHER_PHONEME_V               (28)\n#define AL_VOCAL_MORPHER_PHONEME_Z               (29)\n\n#define AL_VOCAL_MORPHER_WAVEFORM_SINUSOID       (0)\n#define AL_VOCAL_MORPHER_WAVEFORM_TRIANGLE       (1)\n#define AL_VOCAL_MORPHER_WAVEFORM_SAWTOOTH       (2)\n\n#define AL_VOCAL_MORPHER_MIN_WAVEFORM            (0)\n#define AL_VOCAL_MORPHER_MAX_WAVEFORM            (2)\n#define AL_VOCAL_MORPHER_DEFAULT_WAVEFORM        (0)\n\n#define AL_VOCAL_MORPHER_MIN_RATE                (0.0f)\n#define AL_VOCAL_MORPHER_MAX_RATE                (10.0f)\n#define AL_VOCAL_MORPHER_DEFAULT_RATE            (1.41f)\n\n/* Pitch shifter effect */\n#define AL_PITCH_SHIFTER_MIN_COARSE_TUNE         (-12)\n#define AL_PITCH_SHIFTER_MAX_COARSE_TUNE         (12)\n#define AL_PITCH_SHIFTER_DEFAULT_COARSE_TUNE     (12)\n\n#define AL_PITCH_SHIFTER_MIN_FINE_TUNE           (-50)\n#define AL_PITCH_SHIFTER_MAX_FINE_TUNE           (50)\n#define AL_PITCH_SHIFTER_DEFAULT_FINE_TUNE       (0)\n\n/* Ring modulator effect */\n#define AL_RING_MODULATOR_MIN_FREQUENCY          (0.0f)\n#define AL_RING_MODULATOR_MAX_FREQUENCY          (8000.0f)\n#define AL_RING_MODULATOR_DEFAULT_FREQUENCY      (440.0f)\n\n#define AL_RING_MODULATOR_MIN_HIGHPASS_CUTOFF    (0.0f)\n#define AL_RING_MODULATOR_MAX_HIGHPASS_CUTOFF    (24000.0f)\n#define AL_RING_MODULATOR_DEFAULT_HIGHPASS_CUTOFF (800.0f)\n\n#define AL_RING_MODULATOR_SINUSOID               (0)\n#define AL_RING_MODULATOR_SAWTOOTH               (1)\n#define AL_RING_MODULATOR_SQUARE                 (2)\n\n#define AL_RING_MODULATOR_MIN_WAVEFORM           (0)\n#define AL_RING_MODULATOR_MAX_WAVEFORM           (2)\n#define AL_RING_MODULATOR_DEFAULT_WAVEFORM       (0)\n\n/* Autowah effect */\n#define AL_AUTOWAH_MIN_ATTACK_TIME               (0.0001f)\n#define AL_AUTOWAH_MAX_ATTACK_TIME               (1.0f)\n#define AL_AUTOWAH_DEFAULT_ATTACK_TIME           (0.06f)\n\n#define AL_AUTOWAH_MIN_RELEASE_TIME              (0.0001f)\n#define AL_AUTOWAH_MAX_RELEASE_TIME              (1.0f)\n#define AL_AUTOWAH_DEFAULT_RELEASE_TIME          (0.06f)\n\n#define AL_AUTOWAH_MIN_RESONANCE                 (2.0f)\n#define AL_AUTOWAH_MAX_RESONANCE                 (1000.0f)\n#define AL_AUTOWAH_DEFAULT_RESONANCE             (1000.0f)\n\n#define AL_AUTOWAH_MIN_PEAK_GAIN                 (0.00003f)\n#define AL_AUTOWAH_MAX_PEAK_GAIN                 (31621.0f)\n#define AL_AUTOWAH_DEFAULT_PEAK_GAIN             (11.22f)\n\n/* Compressor effect */\n#define AL_COMPRESSOR_MIN_ONOFF                  (0)\n#define AL_COMPRESSOR_MAX_ONOFF                  (1)\n#define AL_COMPRESSOR_DEFAULT_ONOFF              (1)\n\n/* Equalizer effect */\n#define AL_EQUALIZER_MIN_LOW_GAIN                (0.126f)\n#define AL_EQUALIZER_MAX_LOW_GAIN                (7.943f)\n#define AL_EQUALIZER_DEFAULT_LOW_GAIN            (1.0f)\n\n#define AL_EQUALIZER_MIN_LOW_CUTOFF              (50.0f)\n#define AL_EQUALIZER_MAX_LOW_CUTOFF              (800.0f)\n#define AL_EQUALIZER_DEFAULT_LOW_CUTOFF          (200.0f)\n\n#define AL_EQUALIZER_MIN_MID1_GAIN               (0.126f)\n#define AL_EQUALIZER_MAX_MID1_GAIN               (7.943f)\n#define AL_EQUALIZER_DEFAULT_MID1_GAIN           (1.0f)\n\n#define AL_EQUALIZER_MIN_MID1_CENTER             (200.0f)\n#define AL_EQUALIZER_MAX_MID1_CENTER             (3000.0f)\n#define AL_EQUALIZER_DEFAULT_MID1_CENTER         (500.0f)\n\n#define AL_EQUALIZER_MIN_MID1_WIDTH              (0.01f)\n#define AL_EQUALIZER_MAX_MID1_WIDTH              (1.0f)\n#define AL_EQUALIZER_DEFAULT_MID1_WIDTH          (1.0f)\n\n#define AL_EQUALIZER_MIN_MID2_GAIN               (0.126f)\n#define AL_EQUALIZER_MAX_MID2_GAIN               (7.943f)\n#define AL_EQUALIZER_DEFAULT_MID2_GAIN           (1.0f)\n\n#define AL_EQUALIZER_MIN_MID2_CENTER             (1000.0f)\n#define AL_EQUALIZER_MAX_MID2_CENTER             (8000.0f)\n#define AL_EQUALIZER_DEFAULT_MID2_CENTER         (3000.0f)\n\n#define AL_EQUALIZER_MIN_MID2_WIDTH              (0.01f)\n#define AL_EQUALIZER_MAX_MID2_WIDTH              (1.0f)\n#define AL_EQUALIZER_DEFAULT_MID2_WIDTH          (1.0f)\n\n#define AL_EQUALIZER_MIN_HIGH_GAIN               (0.126f)\n#define AL_EQUALIZER_MAX_HIGH_GAIN               (7.943f)\n#define AL_EQUALIZER_DEFAULT_HIGH_GAIN           (1.0f)\n\n#define AL_EQUALIZER_MIN_HIGH_CUTOFF             (4000.0f)\n#define AL_EQUALIZER_MAX_HIGH_CUTOFF             (16000.0f)\n#define AL_EQUALIZER_DEFAULT_HIGH_CUTOFF         (6000.0f)\n\n\n/* Source parameter value ranges and defaults. */\n#define AL_MIN_AIR_ABSORPTION_FACTOR             (0.0f)\n#define AL_MAX_AIR_ABSORPTION_FACTOR             (10.0f)\n#define AL_DEFAULT_AIR_ABSORPTION_FACTOR         (0.0f)\n\n#define AL_MIN_ROOM_ROLLOFF_FACTOR               (0.0f)\n#define AL_MAX_ROOM_ROLLOFF_FACTOR               (10.0f)\n#define AL_DEFAULT_ROOM_ROLLOFF_FACTOR           (0.0f)\n\n#define AL_MIN_CONE_OUTER_GAINHF                 (0.0f)\n#define AL_MAX_CONE_OUTER_GAINHF                 (1.0f)\n#define AL_DEFAULT_CONE_OUTER_GAINHF             (1.0f)\n\n#define AL_MIN_DIRECT_FILTER_GAINHF_AUTO         AL_FALSE\n#define AL_MAX_DIRECT_FILTER_GAINHF_AUTO         AL_TRUE\n#define AL_DEFAULT_DIRECT_FILTER_GAINHF_AUTO     AL_TRUE\n\n#define AL_MIN_AUXILIARY_SEND_FILTER_GAIN_AUTO   AL_FALSE\n#define AL_MAX_AUXILIARY_SEND_FILTER_GAIN_AUTO   AL_TRUE\n#define AL_DEFAULT_AUXILIARY_SEND_FILTER_GAIN_AUTO AL_TRUE\n\n#define AL_MIN_AUXILIARY_SEND_FILTER_GAINHF_AUTO AL_FALSE\n#define AL_MAX_AUXILIARY_SEND_FILTER_GAINHF_AUTO AL_TRUE\n#define AL_DEFAULT_AUXILIARY_SEND_FILTER_GAINHF_AUTO AL_TRUE\n\n\n/* Listener parameter value ranges and defaults. */\n#define AL_MIN_METERS_PER_UNIT                   FLT_MIN\n#define AL_MAX_METERS_PER_UNIT                   FLT_MAX\n#define AL_DEFAULT_METERS_PER_UNIT               (1.0f)\n\n\n#ifdef __cplusplus\n}  /* extern \"C\" */\n#endif\n\n#endif /* AL_EFX_H */\n"
  },
  {
    "path": "vendor/openal-soft/libs/Win32/OpenAL32.def",
    "content": "EXPORTS\n    alBuffer3f\n    alBuffer3i\n    alBufferData\n    alBufferf\n    alBufferfv\n    alBufferi\n    alBufferiv\n    alDeleteBuffers\n    alDeleteSources\n    alDisable\n    alDistanceModel\n    alDopplerFactor\n    alDopplerVelocity\n    alEnable\n    alGenBuffers\n    alGenSources\n    alGetBoolean\n    alGetBooleanv\n    alGetBuffer3f\n    alGetBuffer3i\n    alGetBufferf\n    alGetBufferfv\n    alGetBufferi\n    alGetBufferiv\n    alGetDouble\n    alGetDoublev\n    alGetEnumValue\n    alGetError\n    alGetFloat\n    alGetFloatv\n    alGetInteger\n    alGetIntegerv\n    alGetListener3f\n    alGetListener3i\n    alGetListenerf\n    alGetListenerfv\n    alGetListeneri\n    alGetListeneriv\n    alGetProcAddress\n    alGetSource3f\n    alGetSource3i\n    alGetSourcef\n    alGetSourcefv\n    alGetSourcei\n    alGetSourceiv\n    alGetString\n    alIsBuffer\n    alIsEnabled\n    alIsExtensionPresent\n    alIsSource\n    alListener3f\n    alListener3i\n    alListenerf\n    alListenerfv\n    alListeneri\n    alListeneriv\n    alSource3f\n    alSource3i\n    alSourcePause\n    alSourcePausev\n    alSourcePlay\n    alSourcePlayv\n    alSourceQueueBuffers\n    alSourceRewind\n    alSourceRewindv\n    alSourceStop\n    alSourceStopv\n    alSourceUnqueueBuffers\n    alSourcef\n    alSourcefv\n    alSourcei\n    alSourceiv\n    alSpeedOfSound\n    alcCaptureCloseDevice\n    alcCaptureOpenDevice\n    alcCaptureSamples\n    alcCaptureStart\n    alcCaptureStop\n    alcCloseDevice\n    alcCreateContext\n    alcDestroyContext\n    alcGetContextsDevice\n    alcGetCurrentContext\n    alcGetEnumValue\n    alcGetError\n    alcGetIntegerv\n    alcGetProcAddress\n    alcGetString\n    alcGetThreadContext\n    alcIsExtensionPresent\n    alcMakeContextCurrent\n    alcOpenDevice\n    alcProcessContext\n    alcSetThreadContext\n    alcSuspendContext\n"
  },
  {
    "path": "vendor/openal-soft/libs/Win64/OpenAL32.def",
    "content": "EXPORTS\n    alBuffer3f\n    alBuffer3i\n    alBufferData\n    alBufferf\n    alBufferfv\n    alBufferi\n    alBufferiv\n    alDeleteBuffers\n    alDeleteSources\n    alDisable\n    alDistanceModel\n    alDopplerFactor\n    alDopplerVelocity\n    alEnable\n    alGenBuffers\n    alGenSources\n    alGetBoolean\n    alGetBooleanv\n    alGetBuffer3f\n    alGetBuffer3i\n    alGetBufferf\n    alGetBufferfv\n    alGetBufferi\n    alGetBufferiv\n    alGetDouble\n    alGetDoublev\n    alGetEnumValue\n    alGetError\n    alGetFloat\n    alGetFloatv\n    alGetInteger\n    alGetIntegerv\n    alGetListener3f\n    alGetListener3i\n    alGetListenerf\n    alGetListenerfv\n    alGetListeneri\n    alGetListeneriv\n    alGetProcAddress\n    alGetSource3f\n    alGetSource3i\n    alGetSourcef\n    alGetSourcefv\n    alGetSourcei\n    alGetSourceiv\n    alGetString\n    alIsBuffer\n    alIsEnabled\n    alIsExtensionPresent\n    alIsSource\n    alListener3f\n    alListener3i\n    alListenerf\n    alListenerfv\n    alListeneri\n    alListeneriv\n    alSource3f\n    alSource3i\n    alSourcePause\n    alSourcePausev\n    alSourcePlay\n    alSourcePlayv\n    alSourceQueueBuffers\n    alSourceRewind\n    alSourceRewindv\n    alSourceStop\n    alSourceStopv\n    alSourceUnqueueBuffers\n    alSourcef\n    alSourcefv\n    alSourcei\n    alSourceiv\n    alSpeedOfSound\n    alcCaptureCloseDevice\n    alcCaptureOpenDevice\n    alcCaptureSamples\n    alcCaptureStart\n    alcCaptureStop\n    alcCloseDevice\n    alcCreateContext\n    alcDestroyContext\n    alcGetContextsDevice\n    alcGetCurrentContext\n    alcGetEnumValue\n    alcGetError\n    alcGetIntegerv\n    alcGetProcAddress\n    alcGetString\n    alcGetThreadContext\n    alcIsExtensionPresent\n    alcMakeContextCurrent\n    alcOpenDevice\n    alcProcessContext\n    alcSetThreadContext\n    alcSuspendContext\n"
  },
  {
    "path": "vendor/openal-soft/readme.txt",
    "content": "OpenAL Soft Binary Distribution\n\nThese binaries are provided as a convenience. Users and developers may use it\nso they can use OpenAL Soft without having to build it from source.\n\nNote that it is still expected to install the OpenAL redistributable provided\nby Creative Labs (at http://openal.org/), as that will provide the \"router\"\nOpenAL32.dll that applications talk to, and may provide extra drivers for the\nuser's system. The DLLs provided here will simply add additional devices for\napplications to select from. If you do not wish to use the redistributable,\nthen rename soft_oal.dll to OpenAL32.dll (note: even the 64-bit DLL should be\nnamed OpenAL32.dll). Just be aware this will prevent other system-installed\nOpenAL implementations from working.\n\nTo use the 32-bit DLL, copy it from the bin\\Win32 folder to the folder that\nthe 32-bit OpenAL32.dll router is installed in.\nFor 32-bit Windows, the Win32 DLL will typically go into the system32 folder.\nFor 64-bit Windows, the Win32 DLL will typically go into the SysWOW64 folder.\n\nTo use the 64-bit DLL, copy it from the bin\\Win64 folder to the folder that\nthe 64-bit OpenAL32.dll router is installed in.\nFor 64-bit Windows, this will typically be the system32 folder.\n\nThe included openal-info32.exe and openal-info64.exe programs can be used to\ntell if the OpenAL Soft DLL is being detected. It should be run from a command\nshell, as the program will exit as soon as it's done printing information.\n\nA configuration GUI app is provided in the alsoft-config folder. It is a front-\nend to editing %AppData%\\alsoft.ini, which can be used to modify certain\nbehaviors for OpenAL Soft devices.\n\nHave fun!\n"
  }
]